--- linux-xilinx-zynqmp-5.4.0.orig/.github/pull_request_template.md
+++ linux-xilinx-zynqmp-5.4.0/.github/pull_request_template.md
@@ -0,0 +1,3 @@
+Please do not submit a Pull Request via github.  Our project makes use of
+mailing lists for patch submission and review.  For more details please see
+https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18842172/Create+and+Submit+a+Patch
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/ABI/stable/sysfs-driver-mlxreg-io
+++ linux-xilinx-zynqmp-5.4.0/Documentation/ABI/stable/sysfs-driver-mlxreg-io
@@ -29,13 +29,13 @@
 
 		The files are read only.
 
-What:		/sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/jtag_enable
+What:		/sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/cpld3_version
 
 Date:		November 2018
 KernelVersion:	5.0
 Contact:	Vadim Pasternak <vadimpmellanox.com>
 Description:	These files show with which CPLD versions have been burned
-		on LED board.
+		on LED or Gearbox board.
 
 		The files are read only.
 
@@ -121,6 +121,15 @@
 
 		The files are read only.
 
+What:		/sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/cpld4_version
+Date:		November 2018
+KernelVersion:	5.0
+Contact:	Vadim Pasternak <vadimpmellanox.com>
+Description:	These files show with which CPLD versions have been burned
+		on LED board.
+
+		The files are read only.
+
 Date:		June 2019
 KernelVersion:	5.3
 Contact:	Vadim Pasternak <vadimpmellanox.com>
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/ABI/stable/sysfs-firmware-zynqmp
+++ linux-xilinx-zynqmp-5.4.0/Documentation/ABI/stable/sysfs-firmware-zynqmp
@@ -0,0 +1,116 @@
+What:		/sys/firmware/zynqmp/ggs*
+Date:		January 2018
+KernelVersion:	4.15.0
+Contact:	"Jolly Shah" <jollys@xilinx.com>
+Description:
+		Read/Write PMU global general storage register value,
+		GLOBAL_GEN_STORAGE{0:3}.
+		Global general storage register that can be used
+		by system to pass information between masters.
+
+		The register is reset during system or power-on
+		resets. Three registers are used by the FSBL and
+		other Xilinx software products: GLOBAL_GEN_STORAGE{4:6}.
+
+		Usage:
+		# cat /sys/firmware/zynqmp/ggs0
+		# echo <mask> <value> > /sys/firmware/zynqmp/ggs0
+
+		Example:
+		# cat /sys/firmware/zynqmp/ggs0
+		# echo 0xFFFFFFFF 0x1234ABCD > /sys/firmware/zynqmp/ggs0
+
+Users:		Xilinx
+
+What:		/sys/firmware/zynqmp/pggs*
+Date:		January 2018
+KernelVersion:	4.15.0
+Contact:	"Jolly Shah" <jollys@xilinx.com>
+Description:
+		Read/Write PMU persistent global general storage register
+		value, PERS_GLOB_GEN_STORAGE{0:3}.
+		Persistent global general storage register that
+		can be used by system to pass information between
+		masters.
+
+		This register is only reset by the power-on reset
+		and maintains its value through a system reset.
+		Four registers are used by the FSBL and other Xilinx
+		software products: PERS_GLOB_GEN_STORAGE{4:7}.
+		Register is reset only by a POR reset.
+
+		Usage:
+		# cat /sys/firmware/zynqmp/pggs0
+		# echo <mask> <value> > /sys/firmware/zynqmp/pggs0
+
+		Example:
+		# cat /sys/firmware/zynqmp/pggs0
+		# echo 0xFFFFFFFF 0x1234ABCD > /sys/firmware/zynqmp/pggs0
+
+Users:		Xilinx
+
+What:		/sys/firmware/zynqmp/shutdown_scope
+Date:		February 2018
+KernelVersion:	4.15.6
+Contact:	"Jolly Shah" <jollys@xilinx.com>
+Description:
+		This sysfs interface allows to set the shutdown scope for the
+		next shutdown request. When the next shutdown is performed, the
+		platform specific portion of PSCI-system_off can use the chosen
+		shutdown scope.
+
+		Following are available shutdown scopes(subtypes):
+
+		subsystem:	Only the APU along with all of its peripherals
+				not used by other processing units will be
+				shut down. This may result in the FPD power
+				domain being shut down provided that no other
+				processing unit uses FPD peripherals or DRAM.
+		ps_only:	The complete PS will be shut down, including the
+				RPU, PMU, etc.  Only the PL domain (FPGA)
+				remains untouched.
+		system:		The complete system/device is shut down.
+
+		Usage:
+		# cat /sys/firmware/zynqmp/shutdown_scope
+		# echo <scope> > /sys/firmware/zynqmp/shutdown_scope
+
+		Example:
+		# cat /sys/firmware/zynqmp/shutdown_scope
+		# echo "subsystem" > /sys/firmware/zynqmp/shutdown_scope
+
+Users:		Xilinx
+
+What:		/sys/firmware/zynqmp/health_status
+Date:		April 2018
+KernelVersion:	4.14.0
+Contact:	"Rajan Vaja" <rajanv@xilinx.com>
+Description:
+		This sysfs interface allows to set the health status. If PMUFW
+		is compiled with CHECK_HEALTHY_BOOT, it will check the healthy
+		bit on FPD WDT expiration. If healthy bit is set by a user
+		application running in Linux, PMUFW will do APU only restart. If
+		healthy bit is not set during FPD WDT expiration, PMUFW will do
+		system restart.
+
+		Usage:
+		Set healty bit
+		# echo 1 > /sys/firmware/zynqmp/health_status
+
+		Unset healty bit
+		# echo 0 > /sys/firmware/zynqmp/health_status
+
+Users:		Xilinx
+
+What:		/sys/firmware/zynqmp/last_reset_reason
+Date:		June 2020
+KernelVersion:	5.4.0
+Contact:	"Tejas Patel" <tejasp@xilinx.com>
+Description:
+		This sysfs interface allows to get last reset reason.
+
+		Usage:
+		Get last reset reason
+		# cat /sys/firmware/zynqmp/last_reset_reason
+
+Users:		Xilinx
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/ABI/testing/debugfs-aufs
+++ linux-xilinx-zynqmp-5.4.0/Documentation/ABI/testing/debugfs-aufs
@@ -0,0 +1,55 @@
+What:		/debug/aufs/si_<id>/
+Date:		March 2009
+Contact:	J. R. Okajima <hooanon05g@gmail.com>
+Description:
+		Under /debug/aufs, a directory named si_<id> is created
+		per aufs mount, where <id> is a unique id generated
+		internally.
+
+What:		/debug/aufs/si_<id>/plink
+Date:		Apr 2013
+Contact:	J. R. Okajima <hooanon05g@gmail.com>
+Description:
+		It has three lines and shows the information about the
+		pseudo-link. The first line is a single number
+		representing a number of buckets. The second line is a
+		number of pseudo-links per buckets (separated by a
+		blank). The last line is a single number representing a
+		total number of psedo-links.
+		When the aufs mount option 'noplink' is specified, it
+		will show "1\n0\n0\n".
+
+What:		/debug/aufs/si_<id>/xib
+Date:		March 2009
+Contact:	J. R. Okajima <hooanon05g@gmail.com>
+Description:
+		It shows the consumed blocks by xib (External Inode Number
+		Bitmap), its block size and file size.
+		When the aufs mount option 'noxino' is specified, it
+		will be empty. About XINO files, see the aufs manual.
+
+What:		/debug/aufs/si_<id>/xi0, xi1 ... xiN and xiN-N
+Date:		March 2009
+Contact:	J. R. Okajima <hooanon05g@gmail.com>
+Description:
+		It shows the consumed blocks by xino (External Inode Number
+		Translation Table), its link count, block size and file
+		size.
+		Due to the file size limit, there may exist multiple
+		xino files per branch.  In this case, "-N" is added to
+		the filename and it corresponds to the index of the
+		internal xino array.  "-0" is omitted.
+		When the aufs mount option 'noxino' is specified, Those
+		entries won't exist.  About XINO files, see the aufs
+		manual.
+
+What:		/debug/aufs/si_<id>/xigen
+Date:		March 2009
+Contact:	J. R. Okajima <hooanon05g@gmail.com>
+Description:
+		It shows the consumed blocks by xigen (External Inode
+		Generation Table), its block size and file size.
+		If CONFIG_AUFS_EXPORT is disabled, this entry will not
+		be created.
+		When the aufs mount option 'noxino' is specified, it
+		will be empty. About XINO files, see the aufs manual.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/ABI/testing/debugfs-hisi-hpre
+++ linux-xilinx-zynqmp-5.4.0/Documentation/ABI/testing/debugfs-hisi-hpre
@@ -0,0 +1,57 @@
+What:           /sys/kernel/debug/hisi_hpre/<bdf>/cluster[0-3]/regs
+Date:           Sep 2019
+Contact:        linux-crypto@vger.kernel.org
+Description:    Dump debug registers from the HPRE cluster.
+		Only available for PF.
+
+What:           /sys/kernel/debug/hisi_hpre/<bdf>/cluster[0-3]/cluster_ctrl
+Date:           Sep 2019
+Contact:        linux-crypto@vger.kernel.org
+Description:    Write the HPRE core selection in the cluster into this file,
+		and then we can read the debug information of the core.
+		Only available for PF.
+
+What:           /sys/kernel/debug/hisi_hpre/<bdf>/rdclr_en
+Date:           Sep 2019
+Contact:        linux-crypto@vger.kernel.org
+Description:    HPRE cores debug registers read clear control. 1 means enable
+		register read clear, otherwise 0. Writing to this file has no
+		functional effect, only enable or disable counters clear after
+		reading of these registers.
+		Only available for PF.
+
+What:           /sys/kernel/debug/hisi_hpre/<bdf>/current_qm
+Date:           Sep 2019
+Contact:        linux-crypto@vger.kernel.org
+Description:    One HPRE controller has one PF and multiple VFs, each function
+		has a QM. Select the QM which below qm refers to.
+		Only available for PF.
+
+What:           /sys/kernel/debug/hisi_hpre/<bdf>/regs
+Date:           Sep 2019
+Contact:        linux-crypto@vger.kernel.org
+Description:    Dump debug registers from the HPRE.
+		Only available for PF.
+
+What:           /sys/kernel/debug/hisi_hpre/<bdf>/qm/qm_regs
+Date:           Sep 2019
+Contact:        linux-crypto@vger.kernel.org
+Description:    Dump debug registers from the QM.
+		Available for PF and VF in host. VF in guest currently only
+		has one debug register.
+
+What:           /sys/kernel/debug/hisi_hpre/<bdf>/qm/current_q
+Date:           Sep 2019
+Contact:        linux-crypto@vger.kernel.org
+Description:    One QM may contain multiple queues. Select specific queue to
+		show its debug registers in above qm_regs.
+		Only available for PF.
+
+What:           /sys/kernel/debug/hisi_hpre/<bdf>/qm/clear_enable
+Date:           Sep 2019
+Contact:        linux-crypto@vger.kernel.org
+Description:    QM debug registers(qm_regs) read clear control. 1 means enable
+		register read clear, otherwise 0.
+		Writing to this file has no functional effect, only enable or
+		disable counters clear after reading of these registers.
+		Only available for PF.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/ABI/testing/debugfs-hisi-sec
+++ linux-xilinx-zynqmp-5.4.0/Documentation/ABI/testing/debugfs-hisi-sec
@@ -0,0 +1,43 @@
+What:           /sys/kernel/debug/hisi_sec/<bdf>/sec_dfx
+Date:           Oct 2019
+Contact:        linux-crypto@vger.kernel.org
+Description:    Dump the debug registers of SEC cores.
+		Only available for PF.
+
+What:           /sys/kernel/debug/hisi_sec/<bdf>/clear_enable
+Date:           Oct 2019
+Contact:        linux-crypto@vger.kernel.org
+Description:    Enabling/disabling of clear action after reading
+		the SEC debug registers.
+		0: disable, 1: enable.
+		Only available for PF, and take no other effect on SEC.
+
+What:           /sys/kernel/debug/hisi_sec/<bdf>/current_qm
+Date:           Oct 2019
+Contact:        linux-crypto@vger.kernel.org
+Description:    One SEC controller has one PF and multiple VFs, each function
+		has a QM. This file can be used to select the QM which below
+		qm refers to.
+		Only available for PF.
+
+What:           /sys/kernel/debug/hisi_sec/<bdf>/qm/qm_regs
+Date:           Oct 2019
+Contact:        linux-crypto@vger.kernel.org
+Description:    Dump of QM related debug registers.
+		Available for PF and VF in host. VF in guest currently only
+		has one debug register.
+
+What:           /sys/kernel/debug/hisi_sec/<bdf>/qm/current_q
+Date:           Oct 2019
+Contact:        linux-crypto@vger.kernel.org
+Description:    One QM of SEC may contain multiple queues. Select specific
+		queue to show its debug registers in above 'qm_regs'.
+		Only available for PF.
+
+What:           /sys/kernel/debug/hisi_sec/<bdf>/qm/clear_enable
+Date:           Oct 2019
+Contact:        linux-crypto@vger.kernel.org
+Description:    Enabling/disabling of clear action after reading
+		the SEC's QM debug registers.
+		0: disable, 1: enable.
+		Only available for PF, and take no other effect on SEC.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/ABI/testing/evm
+++ linux-xilinx-zynqmp-5.4.0/Documentation/ABI/testing/evm
@@ -42,8 +42,30 @@
 		modification of EVM-protected metadata and
 		disable all further modification of policy
 
-		Note that once a key has been loaded, it will no longer be
-		possible to enable metadata modification.
+		Echoing a value is additive, the new value is added to the
+		existing initialization flags.
+
+		For example, after::
+
+		  echo 2 ><securityfs>/evm
+
+		another echo can be performed::
+
+		  echo 1 ><securityfs>/evm
+
+		and the resulting value will be 3.
+
+		Note that once an HMAC key has been loaded, it will no longer
+		be possible to enable metadata modification. Signaling that an
+		HMAC key has been loaded will clear the corresponding flag.
+		For example, if the current value is 6 (2 and 4 set)::
+
+		  echo 1 ><securityfs>/evm
+
+		will set the new value to 3 (4 cleared).
+
+		Loading an HMAC key is the only way to disable metadata
+		modification.
 
 		Until key loading has been signaled EVM can not create
 		or validate the 'security.evm' xattr, but returns
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/ABI/testing/ima_policy
+++ linux-xilinx-zynqmp-5.4.0/Documentation/ABI/testing/ima_policy
@@ -25,6 +25,7 @@
 			lsm:	[[subj_user=] [subj_role=] [subj_type=]
 				 [obj_user=] [obj_role=] [obj_type=]]
 			option:	[[appraise_type=]] [template=] [permit_directio]
+				[appraise_flag=]
 		base: 	func:= [BPRM_CHECK][MMAP_CHECK][CREDS_CHECK][FILE_CHECK][MODULE_CHECK]
 				[FIRMWARE_CHECK]
 				[KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK]
@@ -38,6 +39,9 @@
 			fowner:= decimal value
 		lsm:  	are LSM specific
 		option:	appraise_type:= [imasig] [imasig|modsig]
+			appraise_flag:= [check_blacklist]
+			Currently, blacklist check is only for files signed with appended
+			signature.
 			template:= name of a defined IMA template type
 			(eg, ima-ng). Only valid when action is "measure".
 			pcr:= decimal value
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/ABI/testing/sysfs-ata
+++ linux-xilinx-zynqmp-5.4.0/Documentation/ABI/testing/sysfs-ata
@@ -107,13 +107,14 @@
 				described in ATA8 7.16 and 7.17. Only valid if
 				the device is not a PM.
 
-		pio_mode:	(RO) Transfer modes supported by the device when
-				in PIO mode. Mostly used by PATA device.
+		pio_mode:	(RO) PIO transfer mode used by the device.
+				Mostly used by PATA devices.
 
-		xfer_mode:	(RO) Current transfer mode
+		xfer_mode:	(RO) Current transfer mode. Mostly used by
+				PATA devices.
 
-		dma_mode:	(RO) Transfer modes supported by the device when
-				in DMA mode. Mostly used by PATA device.
+		dma_mode:	(RO) DMA transfer mode used by the device.
+				Mostly used by PATA devices.
 
 		class:		(RO) Device class. Can be "ata" for disk,
 				"atapi" for packet device, "pmp" for PM, or
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/ABI/testing/sysfs-aufs
+++ linux-xilinx-zynqmp-5.4.0/Documentation/ABI/testing/sysfs-aufs
@@ -0,0 +1,31 @@
+What:		/sys/fs/aufs/si_<id>/
+Date:		March 2009
+Contact:	J. R. Okajima <hooanon05g@gmail.com>
+Description:
+		Under /sys/fs/aufs, a directory named si_<id> is created
+		per aufs mount, where <id> is a unique id generated
+		internally.
+
+What:		/sys/fs/aufs/si_<id>/br0, br1 ... brN
+Date:		March 2009
+Contact:	J. R. Okajima <hooanon05g@gmail.com>
+Description:
+		It shows the abolute path of a member directory (which
+		is called branch) in aufs, and its permission.
+
+What:		/sys/fs/aufs/si_<id>/brid0, brid1 ... bridN
+Date:		July 2013
+Contact:	J. R. Okajima <hooanon05g@gmail.com>
+Description:
+		It shows the id of a member directory (which is called
+		branch) in aufs.
+
+What:		/sys/fs/aufs/si_<id>/xi_path
+Date:		March 2009
+Contact:	J. R. Okajima <hooanon05g@gmail.com>
+Description:
+		It shows the abolute path of XINO (External Inode Number
+		Bitmap, Translation Table and Generation Table) file
+		even if it is the default path.
+		When the aufs mount option 'noxino' is specified, it
+		will be empty. About XINO files, see the aufs manual.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/ABI/testing/sysfs-bus-iio
+++ linux-xilinx-zynqmp-5.4.0/Documentation/ABI/testing/sysfs-bus-iio
@@ -138,7 +138,7 @@
 		Raw capacitance measurement from channel Y. Units after
 		application of scale and offset are nanofarads.
 
-What:		/sys/.../iio:deviceX/in_capacitanceY-in_capacitanceZ_raw
+What:		/sys/.../iio:deviceX/in_capacitanceY-capacitanceZ_raw
 KernelVersion:	3.2
 Contact:	linux-iio@vger.kernel.org
 Description:
@@ -1566,7 +1566,8 @@
 KernelVersion:	4.3
 Contact:	linux-iio@vger.kernel.org
 Description:
-		Raw (unscaled no offset etc.) percentage reading of a substance.
+		Raw (unscaled no offset etc.) reading of a substance. Units
+		after application of scale and offset are percents.
 
 What:		/sys/bus/iio/devices/iio:deviceX/in_resistance_raw
 What:		/sys/bus/iio/devices/iio:deviceX/in_resistanceX_raw
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/ABI/testing/sysfs-bus-iio-vf610
+++ linux-xilinx-zynqmp-5.4.0/Documentation/ABI/testing/sysfs-bus-iio-vf610
@@ -1,4 +1,4 @@
-What:		/sys/bus/iio/devices/iio:deviceX/conversion_mode
+What:		/sys/bus/iio/devices/iio:deviceX/in_conversion_mode
 KernelVersion:	4.2
 Contact:	linux-iio@vger.kernel.org
 Description:
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/ABI/testing/sysfs-bus-mei
+++ linux-xilinx-zynqmp-5.4.0/Documentation/ABI/testing/sysfs-bus-mei
@@ -4,7 +4,7 @@
 Contact:	Samuel Ortiz <sameo@linux.intel.com>
 		linux-mei@linux.intel.com
 Description:	Stores the same MODALIAS value emitted by uevent
-		Format: mei:<mei device name>:<device uuid>:
+		Format: mei:<mei device name>:<device uuid>:<protocol version>
 
 What:		/sys/bus/mei/devices/.../name
 Date:		May 2015
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/ABI/testing/sysfs-bus-pci
+++ linux-xilinx-zynqmp-5.4.0/Documentation/ABI/testing/sysfs-bus-pci
@@ -125,6 +125,17 @@
 		will be present in sysfs.  Writing 1 to this file
 		will perform reset.
 
+What:		/sys/bus/pci/devices/.../reset_subordinate
+Date:		October 2024
+Contact:	linux-pci@vger.kernel.org
+Description:
+		This is visible only for bridge devices. If you want to reset
+		all devices attached through the subordinate bus of a specific
+		bridge device, writing 1 to this will try to do it.  This will
+		affect all devices attached to the system through this bridge
+		similiar to writing 1 to their individual "reset" file, so use
+		with caution.
+
 What:		/sys/bus/pci/devices/.../vpd
 Date:		February 2008
 Contact:	Ben Hutchings <bwh@kernel.org>
@@ -347,3 +358,16 @@
 		If the device has any Peer-to-Peer memory registered, this
 	        file contains a '1' if the memory has been published for
 		use outside the driver that owns the device.
+
+What:		/sys/bus/pci/devices/.../link/clkpm
+		/sys/bus/pci/devices/.../link/l0s_aspm
+		/sys/bus/pci/devices/.../link/l1_aspm
+		/sys/bus/pci/devices/.../link/l1_1_aspm
+		/sys/bus/pci/devices/.../link/l1_2_aspm
+		/sys/bus/pci/devices/.../link/l1_1_pcipm
+		/sys/bus/pci/devices/.../link/l1_2_pcipm
+Date:		October 2019
+Contact:	Heiner Kallweit <hkallweit1@gmail.com>
+Description:	If ASPM is supported for an endpoint, these files can be
+		used to disable or enable the individual power management
+		states. Write y/1/on to enable, n/0/off to disable.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/ABI/testing/sysfs-class-devfreq
+++ linux-xilinx-zynqmp-5.4.0/Documentation/ABI/testing/sysfs-class-devfreq
@@ -7,6 +7,13 @@
 		The name of devfreq object denoted as ... is same as the
 		name of device using devfreq.
 
+What:		/sys/class/devfreq/.../name
+Date:		November 2019
+Contact:	Chanwoo Choi <cw00.choi@samsung.com>
+Description:
+		The /sys/class/devfreq/.../name shows the name of device
+		of the corresponding devfreq object.
+
 What:		/sys/class/devfreq/.../governor
 Date:		September 2011
 Contact:	MyungJoo Ham <myungjoo.ham@samsung.com>
@@ -54,6 +61,8 @@
 		In order to activate this ABI, the devfreq target device
 		driver should provide the list of available frequencies
 		with its profile.
+		If the transition table is bigger than PAGE_SIZE, reading
+		this will return an -EFBIG error.
 
 What:		/sys/class/devfreq/.../userspace/set_freq
 Date:		September 2011
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/ABI/testing/sysfs-class-fpga-bridge
+++ linux-xilinx-zynqmp-5.4.0/Documentation/ABI/testing/sysfs-class-fpga-bridge
@@ -9,3 +9,12 @@
 KernelVersion:	4.5
 Contact:	Alan Tull <atull@opensource.altera.com>
 Description:	Show bridge state as "enabled" or "disabled"
+
+What:		/sys/class/fpga_bridge/<bridge>/set
+Date:		January 2017
+KernelVersion:	4.9
+Contact:	Michal Simek <michal.simek@xilinx.com>
+Description:	Manual set bridge state (0-disable, !0 enable).
+		Enabling this option requires that the module is
+		compiled with #define DEBUG which is enabled by default
+		when CONFIG_DEBUG_KERNEL is setup.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/ABI/testing/sysfs-class-net-queues
+++ linux-xilinx-zynqmp-5.4.0/Documentation/ABI/testing/sysfs-class-net-queues
@@ -1,4 +1,4 @@
-What:		/sys/class/<iface>/queues/rx-<queue>/rps_cpus
+What:		/sys/class/net/<iface>/queues/rx-<queue>/rps_cpus
 Date:		March 2010
 KernelVersion:	2.6.35
 Contact:	netdev@vger.kernel.org
@@ -8,7 +8,7 @@
 		network device queue. Possible values depend on the number
 		of available CPU(s) in the system.
 
-What:		/sys/class/<iface>/queues/rx-<queue>/rps_flow_cnt
+What:		/sys/class/net/<iface>/queues/rx-<queue>/rps_flow_cnt
 Date:		April 2010
 KernelVersion:	2.6.35
 Contact:	netdev@vger.kernel.org
@@ -16,7 +16,7 @@
 		Number of Receive Packet Steering flows being currently
 		processed by this particular network device receive queue.
 
-What:		/sys/class/<iface>/queues/tx-<queue>/tx_timeout
+What:		/sys/class/net/<iface>/queues/tx-<queue>/tx_timeout
 Date:		November 2011
 KernelVersion:	3.3
 Contact:	netdev@vger.kernel.org
@@ -24,7 +24,7 @@
 		Indicates the number of transmit timeout events seen by this
 		network interface transmit queue.
 
-What:		/sys/class/<iface>/queues/tx-<queue>/tx_maxrate
+What:		/sys/class/net/<iface>/queues/tx-<queue>/tx_maxrate
 Date:		March 2015
 KernelVersion:	4.1
 Contact:	netdev@vger.kernel.org
@@ -32,7 +32,7 @@
 		A Mbps max-rate set for the queue, a value of zero means disabled,
 		default is disabled.
 
-What:		/sys/class/<iface>/queues/tx-<queue>/xps_cpus
+What:		/sys/class/net/<iface>/queues/tx-<queue>/xps_cpus
 Date:		November 2010
 KernelVersion:	2.6.38
 Contact:	netdev@vger.kernel.org
@@ -42,7 +42,7 @@
 		network device transmit queue. Possible vaules depend on the
 		number of available CPU(s) in the system.
 
-What:		/sys/class/<iface>/queues/tx-<queue>/xps_rxqs
+What:		/sys/class/net/<iface>/queues/tx-<queue>/xps_rxqs
 Date:		June 2018
 KernelVersion:	4.18.0
 Contact:	netdev@vger.kernel.org
@@ -53,7 +53,7 @@
 		number of available receive queue(s) in the network device.
 		Default is disabled.
 
-What:		/sys/class/<iface>/queues/tx-<queue>/byte_queue_limits/hold_time
+What:		/sys/class/net/<iface>/queues/tx-<queue>/byte_queue_limits/hold_time
 Date:		November 2011
 KernelVersion:	3.3
 Contact:	netdev@vger.kernel.org
@@ -62,7 +62,7 @@
 		of this particular network device transmit queue.
 		Default value is 1000.
 
-What:		/sys/class/<iface>/queues/tx-<queue>/byte_queue_limits/inflight
+What:		/sys/class/net/<iface>/queues/tx-<queue>/byte_queue_limits/inflight
 Date:		November 2011
 KernelVersion:	3.3
 Contact:	netdev@vger.kernel.org
@@ -70,7 +70,7 @@
 		Indicates the number of bytes (objects) in flight on this
 		network device transmit queue.
 
-What:		/sys/class/<iface>/queues/tx-<queue>/byte_queue_limits/limit
+What:		/sys/class/net/<iface>/queues/tx-<queue>/byte_queue_limits/limit
 Date:		November 2011
 KernelVersion:	3.3
 Contact:	netdev@vger.kernel.org
@@ -79,7 +79,7 @@
 		on this network device transmit queue. This value is clamped
 		to be within the bounds defined by limit_max and limit_min.
 
-What:		/sys/class/<iface>/queues/tx-<queue>/byte_queue_limits/limit_max
+What:		/sys/class/net/<iface>/queues/tx-<queue>/byte_queue_limits/limit_max
 Date:		November 2011
 KernelVersion:	3.3
 Contact:	netdev@vger.kernel.org
@@ -88,7 +88,7 @@
 		queued on this network device transmit queue. See
 		include/linux/dynamic_queue_limits.h for the default value.
 
-What:		/sys/class/<iface>/queues/tx-<queue>/byte_queue_limits/limit_min
+What:		/sys/class/net/<iface>/queues/tx-<queue>/byte_queue_limits/limit_min
 Date:		November 2011
 KernelVersion:	3.3
 Contact:	netdev@vger.kernel.org
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/ABI/testing/sysfs-devices-system-cpu
+++ linux-xilinx-zynqmp-5.4.0/Documentation/ABI/testing/sysfs-devices-system-cpu
@@ -480,14 +480,18 @@
 		cpu_capacity: capacity of cpu#.
 
 What:		/sys/devices/system/cpu/vulnerabilities
+		/sys/devices/system/cpu/vulnerabilities/gather_data_sampling
+		/sys/devices/system/cpu/vulnerabilities/itlb_multihit
+		/sys/devices/system/cpu/vulnerabilities/l1tf
+		/sys/devices/system/cpu/vulnerabilities/mds
 		/sys/devices/system/cpu/vulnerabilities/meltdown
+		/sys/devices/system/cpu/vulnerabilities/mmio_stale_data
+		/sys/devices/system/cpu/vulnerabilities/spec_store_bypass
 		/sys/devices/system/cpu/vulnerabilities/spectre_v1
 		/sys/devices/system/cpu/vulnerabilities/spectre_v2
-		/sys/devices/system/cpu/vulnerabilities/spec_store_bypass
-		/sys/devices/system/cpu/vulnerabilities/l1tf
-		/sys/devices/system/cpu/vulnerabilities/mds
+		/sys/devices/system/cpu/vulnerabilities/srbds
 		/sys/devices/system/cpu/vulnerabilities/tsx_async_abort
-		/sys/devices/system/cpu/vulnerabilities/itlb_multihit
+		/sys/devices/system/cpu/vulnerabilities/vmscape
 Date:		January 2018
 Contact:	Linux kernel mailing list <linux-kernel@vger.kernel.org>
 Description:	Information about CPU vulnerabilities
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/ABI/testing/sysfs-driver-cortexa53-edac
+++ linux-xilinx-zynqmp-5.4.0/Documentation/ABI/testing/sysfs-driver-cortexa53-edac
@@ -0,0 +1,10 @@
+What:		/sys/devices/system/edac/cpu_cache/inject_(L1/L2)_Cache_Error
+Date:		June 2016
+Contact:	nagasure@xilinx.com
+		punnaia@xilinx.com
+Description:    This control file allows to inject cache errors on cortexa53
+		L1 and L2 caches. arm provided error injection for cortexa53
+		caches (L1 and L2). Just echo 1 > /sys/devices/system/edac/
+		cpu_cache/inject_L1_Error for L1 cache error injection and
+		echo 1 > /sys/devices/system/edac/cpu_cache/inject_L2_Error
+		for L2 cache error injection.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/ABI/testing/sysfs-kernel-oops_count
+++ linux-xilinx-zynqmp-5.4.0/Documentation/ABI/testing/sysfs-kernel-oops_count
@@ -0,0 +1,6 @@
+What:		/sys/kernel/oops_count
+Date:		November 2022
+KernelVersion:	6.2.0
+Contact:	Linux Kernel Hardening List <linux-hardening@vger.kernel.org>
+Description:
+		Shows how many times the system has Oopsed since last boot.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/ABI/testing/sysfs-kernel-warn_count
+++ linux-xilinx-zynqmp-5.4.0/Documentation/ABI/testing/sysfs-kernel-warn_count
@@ -0,0 +1,6 @@
+What:		/sys/kernel/warn_count
+Date:		November 2022
+KernelVersion:	6.2.0
+Contact:	Linux Kernel Hardening List <linux-hardening@vger.kernel.org>
+Description:
+		Shows how many times the system has Warned since last boot.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/ABI/testing/sysfs-secvar
+++ linux-xilinx-zynqmp-5.4.0/Documentation/ABI/testing/sysfs-secvar
@@ -0,0 +1,46 @@
+What:		/sys/firmware/secvar
+Date:		August 2019
+Contact:	Nayna Jain <nayna@linux.ibm.com>
+Description:	This directory is created if the POWER firmware supports OS
+		secureboot, thereby secure variables. It exposes interface
+		for reading/writing the secure variables
+
+What:		/sys/firmware/secvar/vars
+Date:		August 2019
+Contact:	Nayna Jain <nayna@linux.ibm.com>
+Description:	This directory lists all the secure variables that are supported
+		by the firmware.
+
+What:		/sys/firmware/secvar/format
+Date:		August 2019
+Contact:	Nayna Jain <nayna@linux.ibm.com>
+Description:	A string indicating which backend is in use by the firmware.
+		This determines the format of the variable and the accepted
+		format of variable updates.
+
+What:		/sys/firmware/secvar/vars/<variable name>
+Date:		August 2019
+Contact:	Nayna Jain <nayna@linux.ibm.com>
+Description:	Each secure variable is represented as a directory named as
+		<variable_name>. The variable name is unique and is in ASCII
+		representation. The data and size can be determined by reading
+		their respective attribute files.
+
+What:		/sys/firmware/secvar/vars/<variable_name>/size
+Date:		August 2019
+Contact:	Nayna Jain <nayna@linux.ibm.com>
+Description:	An integer representation of the size of the content of the
+		variable. In other words, it represents the size of the data.
+
+What:		/sys/firmware/secvar/vars/<variable_name>/data
+Date:		August 2019
+Contact:	Nayna Jain h<nayna@linux.ibm.com>
+Description:	A read-only file containing the value of the variable. The size
+		of the file represents the maximum size of the variable data.
+
+What:		/sys/firmware/secvar/vars/<variable_name>/update
+Date:		August 2019
+Contact:	Nayna Jain <nayna@linux.ibm.com>
+Description:	A write-only file that is used to submit the new value for the
+		variable. The size of the file represents the maximum size of
+		the variable data that can be written.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/DMA-attributes.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/DMA-attributes.txt
@@ -5,24 +5,6 @@
 This document describes the semantics of the DMA attributes that are
 defined in linux/dma-mapping.h.
 
-DMA_ATTR_WRITE_BARRIER
-----------------------
-
-DMA_ATTR_WRITE_BARRIER is a (write) barrier attribute for DMA.  DMA
-to a memory region with the DMA_ATTR_WRITE_BARRIER attribute forces
-all pending DMA writes to complete, and thus provides a mechanism to
-strictly order DMA from a device across all intervening busses and
-bridges.  This barrier is not specific to a particular type of
-interconnect, it applies to the system as a whole, and so its
-implementation must account for the idiosyncrasies of the system all
-the way from the DMA device to memory.
-
-As an example of a situation where DMA_ATTR_WRITE_BARRIER would be
-useful, suppose that a device does a DMA write to indicate that data is
-ready and available in memory.  The DMA of the "completion indication"
-could race with data DMA.  Mapping the memory used for completion
-indications with DMA_ATTR_WRITE_BARRIER would prevent the race.
-
 DMA_ATTR_WEAK_ORDERING
 ----------------------
 
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/IPMI.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/IPMI.txt
@@ -518,7 +518,7 @@
 	[dbg_probe=1]
 
 The addresses are normal I2C addresses.  The adapter is the string
-name of the adapter, as shown in /sys/class/i2c-adapter/i2c-<n>/name.
+name of the adapter, as shown in /sys/bus/i2c/devices/i2c-<n>/name.
 It is *NOT* i2c-<n> itself.  Also, the comparison is done ignoring
 spaces, so if the name is "This is an I2C chip" you can say
 adapter_name=ThisisanI2cchip.  This is because it's hard to pass in
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/RCU/Design/Requirements/Requirements.html
+++ linux-xilinx-zynqmp-5.4.0/Documentation/RCU/Design/Requirements/Requirements.html
@@ -2342,7 +2342,7 @@
 The module-unload functions must therefore cancel any
 delayed calls to loadable-module functions, for example,
 any outstanding <tt>mod_timer()</tt> must be dealt with
-via <tt>del_timer_sync()</tt> or similar.
+via <tt>timer_shutdown_sync()</tt> or similar.
 
 <p>
 Unfortunately, there is no way to cancel an RCU callback;
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/accounting/psi.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/accounting/psi.rst
@@ -90,7 +90,8 @@
 for the same psi metric can be specified. However for each trigger a separate
 file descriptor is required to be able to poll it separately from others,
 therefore for each trigger a separate open() syscall should be made even
-when opening the same psi interface file.
+when opening the same psi interface file. Write operations to a file descriptor
+with an already existing psi trigger will fail with EBUSY.
 
 Monitors activate only when system enters stall state for the monitored
 psi metric and deactivates upon exit from the stall state. While system is
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/admin-guide/cgroup-v1/memory.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/admin-guide/cgroup-v1/memory.rst
@@ -82,6 +82,8 @@
  memory.swappiness		     set/show swappiness parameter of vmscan
 				     (See sysctl's vm.swappiness)
  memory.move_charge_at_immigrate     set/show controls of moving charges
+                                     This knob is deprecated and shouldn't be
+                                     used.
  memory.oom_control		     set/show oom controls.
  memory.numa_stat		     show the number of memory usage per numa
 				     node
@@ -745,8 +747,15 @@
        It is recommended to set the soft limit always below the hard limit,
        otherwise the hard limit will take precedence.
 
-8. Move charges at task migration
-=================================
+8. Move charges at task migration (DEPRECATED!)
+===============================================
+
+THIS IS DEPRECATED!
+
+It's expensive and unreliable! It's better practice to launch workload
+tasks directly from inside their target cgroup. Use dedicated workload
+cgroups to allow fine-grained policy adjustments without having to
+move physical pages between control domains.
 
 Users can move charges associated with a task along with task migration, that
 is, uncharge task's pages from the old cgroup and charge them to the new cgroup.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/admin-guide/device-mapper/dm-integrity.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/admin-guide/device-mapper/dm-integrity.rst
@@ -177,6 +177,12 @@
 	The bitmap flush interval in milliseconds. The metadata buffers
 	are synchronized when this interval expires.
 
+legacy_recalculate
+	Allow recalculating of volumes with HMAC keys. This is disabled by
+	default for security reasons - an attacker could modify the volume,
+	set recalc_sector to zero, and the kernel would not detect the
+	modification.
+
 
 The journal mode (D/J), buffer_sectors, journal_watermark, commit_time can
 be changed when reloading the target (load an inactive table and swap the
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/admin-guide/device-mapper/index.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/admin-guide/device-mapper/index.rst
@@ -8,6 +8,7 @@
     cache-policies
     cache
     delay
+    dm-clone
     dm-crypt
     dm-flakey
     dm-init
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/admin-guide/devices.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/admin-guide/devices.txt
@@ -3002,10 +3002,10 @@
 		65 = /dev/infiniband/issm1     Second InfiniBand IsSM device
 		  ...
 		127 = /dev/infiniband/issm63    63rd InfiniBand IsSM device
-		128 = /dev/infiniband/uverbs0   First InfiniBand verbs device
-		129 = /dev/infiniband/uverbs1   Second InfiniBand verbs device
+		192 = /dev/infiniband/uverbs0   First InfiniBand verbs device
+		193 = /dev/infiniband/uverbs1   Second InfiniBand verbs device
 		  ...
-		159 = /dev/infiniband/uverbs31  31st InfiniBand verbs device
+		223 = /dev/infiniband/uverbs31  31st InfiniBand verbs device
 
  232 char	Biometric Devices
 		0 = /dev/biometric/sensor0/fingerprint	first fingerprint sensor on first device
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/admin-guide/hw-vuln/cross-thread-rsb.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/admin-guide/hw-vuln/cross-thread-rsb.rst
@@ -0,0 +1,92 @@
+
+.. SPDX-License-Identifier: GPL-2.0
+
+Cross-Thread Return Address Predictions
+=======================================
+
+Certain AMD and Hygon processors are subject to a cross-thread return address
+predictions vulnerability. When running in SMT mode and one sibling thread
+transitions out of C0 state, the other sibling thread could use return target
+predictions from the sibling thread that transitioned out of C0.
+
+The Spectre v2 mitigations protect the Linux kernel, as it fills the return
+address prediction entries with safe targets when context switching to the idle
+thread. However, KVM does allow a VMM to prevent exiting guest mode when
+transitioning out of C0. This could result in a guest-controlled return target
+being consumed by the sibling thread.
+
+Affected processors
+-------------------
+
+The following CPUs are vulnerable:
+
+    - AMD Family 17h processors
+    - Hygon Family 18h processors
+
+Related CVEs
+------------
+
+The following CVE entry is related to this issue:
+
+   ==============  =======================================
+   CVE-2022-27672  Cross-Thread Return Address Predictions
+   ==============  =======================================
+
+Problem
+-------
+
+Affected SMT-capable processors support 1T and 2T modes of execution when SMT
+is enabled. In 2T mode, both threads in a core are executing code. For the
+processor core to enter 1T mode, it is required that one of the threads
+requests to transition out of the C0 state. This can be communicated with the
+HLT instruction or with an MWAIT instruction that requests non-C0.
+When the thread re-enters the C0 state, the processor transitions back
+to 2T mode, assuming the other thread is also still in C0 state.
+
+In affected processors, the return address predictor (RAP) is partitioned
+depending on the SMT mode. For instance, in 2T mode each thread uses a private
+16-entry RAP, but in 1T mode, the active thread uses a 32-entry RAP. Upon
+transition between 1T/2T mode, the RAP contents are not modified but the RAP
+pointers (which control the next return target to use for predictions) may
+change. This behavior may result in return targets from one SMT thread being
+used by RET predictions in the sibling thread following a 1T/2T switch. In
+particular, a RET instruction executed immediately after a transition to 1T may
+use a return target from the thread that just became idle. In theory, this
+could lead to information disclosure if the return targets used do not come
+from trustworthy code.
+
+Attack scenarios
+----------------
+
+An attack can be mounted on affected processors by performing a series of CALL
+instructions with targeted return locations and then transitioning out of C0
+state.
+
+Mitigation mechanism
+--------------------
+
+Before entering idle state, the kernel context switches to the idle thread. The
+context switch fills the RAP entries (referred to as the RSB in Linux) with safe
+targets by performing a sequence of CALL instructions.
+
+Prevent a guest VM from directly putting the processor into an idle state by
+intercepting HLT and MWAIT instructions.
+
+Both mitigations are required to fully address this issue.
+
+Mitigation control on the kernel command line
+---------------------------------------------
+
+Use existing Spectre v2 mitigations that will fill the RSB on context switch.
+
+Mitigation control for KVM - module parameter
+---------------------------------------------
+
+By default, the KVM hypervisor mitigates this issue by intercepting guest
+attempts to transition out of C0. A VMM can use the KVM_CAP_X86_DISABLE_EXITS
+capability to override those interceptions, but since this is not common, the
+mitigation that covers this path is not enabled by default.
+
+The mitigation for the KVM_CAP_X86_DISABLE_EXITS capability can be turned on
+using the boolean module parameter mitigate_smt_rsb, e.g.:
+        kvm.mitigate_smt_rsb=1
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/admin-guide/hw-vuln/gather_data_sampling.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/admin-guide/hw-vuln/gather_data_sampling.rst
@@ -0,0 +1,109 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+GDS - Gather Data Sampling
+==========================
+
+Gather Data Sampling is a hardware vulnerability which allows unprivileged
+speculative access to data which was previously stored in vector registers.
+
+Problem
+-------
+When a gather instruction performs loads from memory, different data elements
+are merged into the destination vector register. However, when a gather
+instruction that is transiently executed encounters a fault, stale data from
+architectural or internal vector registers may get transiently forwarded to the
+destination vector register instead. This will allow a malicious attacker to
+infer stale data using typical side channel techniques like cache timing
+attacks. GDS is a purely sampling-based attack.
+
+The attacker uses gather instructions to infer the stale vector register data.
+The victim does not need to do anything special other than use the vector
+registers. The victim does not need to use gather instructions to be
+vulnerable.
+
+Because the buffers are shared between Hyper-Threads cross Hyper-Thread attacks
+are possible.
+
+Attack scenarios
+----------------
+Without mitigation, GDS can infer stale data across virtually all
+permission boundaries:
+
+	Non-enclaves can infer SGX enclave data
+	Userspace can infer kernel data
+	Guests can infer data from hosts
+	Guest can infer guest from other guests
+	Users can infer data from other users
+
+Because of this, it is important to ensure that the mitigation stays enabled in
+lower-privilege contexts like guests and when running outside SGX enclaves.
+
+The hardware enforces the mitigation for SGX. Likewise, VMMs should  ensure
+that guests are not allowed to disable the GDS mitigation. If a host erred and
+allowed this, a guest could theoretically disable GDS mitigation, mount an
+attack, and re-enable it.
+
+Mitigation mechanism
+--------------------
+This issue is mitigated in microcode. The microcode defines the following new
+bits:
+
+ ================================   ===   ============================
+ IA32_ARCH_CAPABILITIES[GDS_CTRL]   R/O   Enumerates GDS vulnerability
+                                          and mitigation support.
+ IA32_ARCH_CAPABILITIES[GDS_NO]     R/O   Processor is not vulnerable.
+ IA32_MCU_OPT_CTRL[GDS_MITG_DIS]    R/W   Disables the mitigation
+                                          0 by default.
+ IA32_MCU_OPT_CTRL[GDS_MITG_LOCK]   R/W   Locks GDS_MITG_DIS=0. Writes
+                                          to GDS_MITG_DIS are ignored
+                                          Can't be cleared once set.
+ ================================   ===   ============================
+
+GDS can also be mitigated on systems that don't have updated microcode by
+disabling AVX. This can be done by setting gather_data_sampling="force" or
+"clearcpuid=avx" on the kernel command-line.
+
+If used, these options will disable AVX use by turning off XSAVE YMM support.
+However, the processor will still enumerate AVX support.  Userspace that
+does not follow proper AVX enumeration to check both AVX *and* XSAVE YMM
+support will break.
+
+Mitigation control on the kernel command line
+---------------------------------------------
+The mitigation can be disabled by setting "gather_data_sampling=off" or
+"mitigations=off" on the kernel command line. Not specifying either will default
+to the mitigation being enabled. Specifying "gather_data_sampling=force" will
+use the microcode mitigation when available or disable AVX on affected systems
+where the microcode hasn't been updated to include the mitigation.
+
+GDS System Information
+------------------------
+The kernel provides vulnerability status information through sysfs. For
+GDS this can be accessed by the following sysfs file:
+
+/sys/devices/system/cpu/vulnerabilities/gather_data_sampling
+
+The possible values contained in this file are:
+
+ ============================== =============================================
+ Not affected                   Processor not vulnerable.
+ Vulnerable                     Processor vulnerable and mitigation disabled.
+ Vulnerable: No microcode       Processor vulnerable and microcode is missing
+                                mitigation.
+ Mitigation: AVX disabled,
+ no microcode                   Processor is vulnerable and microcode is missing
+                                mitigation. AVX disabled as mitigation.
+ Mitigation: Microcode          Processor is vulnerable and mitigation is in
+                                effect.
+ Mitigation: Microcode (locked) Processor is vulnerable and mitigation is in
+                                effect and cannot be disabled.
+ Unknown: Dependent on
+ hypervisor status              Running on a virtual guest processor that is
+                                affected but with no way to know if host
+                                processor is mitigated or vulnerable.
+ ============================== =============================================
+
+GDS Default mitigation
+----------------------
+The updated microcode will enable the mitigation by default. The kernel's
+default action is to leave the mitigation enabled.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/admin-guide/hw-vuln/index.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/admin-guide/hw-vuln/index.rst
@@ -14,3 +14,8 @@
    mds
    tsx_async_abort
    multihit.rst
+   special-register-buffer-data-sampling.rst
+   processor_mmio_stale_data.rst
+   cross-thread-rsb.rst
+   gather_data_sampling.rst
+   vmscape
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/admin-guide/hw-vuln/mds.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/admin-guide/hw-vuln/mds.rst
@@ -265,8 +265,11 @@
 
   ============  =============================================================
 
-Not specifying this option is equivalent to "mds=full".
-
+Not specifying this option is equivalent to "mds=full". For processors
+that are affected by both TAA (TSX Asynchronous Abort) and MDS,
+specifying just "mds=off" without an accompanying "tsx_async_abort=off"
+will have no effect as the same mitigation is used for both
+vulnerabilities.
 
 Mitigation selection guide
 --------------------------
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst
@@ -0,0 +1,260 @@
+=========================================
+Processor MMIO Stale Data Vulnerabilities
+=========================================
+
+Processor MMIO Stale Data Vulnerabilities are a class of memory-mapped I/O
+(MMIO) vulnerabilities that can expose data. The sequences of operations for
+exposing data range from simple to very complex. Because most of the
+vulnerabilities require the attacker to have access to MMIO, many environments
+are not affected. System environments using virtualization where MMIO access is
+provided to untrusted guests may need mitigation. These vulnerabilities are
+not transient execution attacks. However, these vulnerabilities may propagate
+stale data into core fill buffers where the data can subsequently be inferred
+by an unmitigated transient execution attack. Mitigation for these
+vulnerabilities includes a combination of microcode update and software
+changes, depending on the platform and usage model. Some of these mitigations
+are similar to those used to mitigate Microarchitectural Data Sampling (MDS) or
+those used to mitigate Special Register Buffer Data Sampling (SRBDS).
+
+Data Propagators
+================
+Propagators are operations that result in stale data being copied or moved from
+one microarchitectural buffer or register to another. Processor MMIO Stale Data
+Vulnerabilities are operations that may result in stale data being directly
+read into an architectural, software-visible state or sampled from a buffer or
+register.
+
+Fill Buffer Stale Data Propagator (FBSDP)
+-----------------------------------------
+Stale data may propagate from fill buffers (FB) into the non-coherent portion
+of the uncore on some non-coherent writes. Fill buffer propagation by itself
+does not make stale data architecturally visible. Stale data must be propagated
+to a location where it is subject to reading or sampling.
+
+Sideband Stale Data Propagator (SSDP)
+-------------------------------------
+The sideband stale data propagator (SSDP) is limited to the client (including
+Intel Xeon server E3) uncore implementation. The sideband response buffer is
+shared by all client cores. For non-coherent reads that go to sideband
+destinations, the uncore logic returns 64 bytes of data to the core, including
+both requested data and unrequested stale data, from a transaction buffer and
+the sideband response buffer. As a result, stale data from the sideband
+response and transaction buffers may now reside in a core fill buffer.
+
+Primary Stale Data Propagator (PSDP)
+------------------------------------
+The primary stale data propagator (PSDP) is limited to the client (including
+Intel Xeon server E3) uncore implementation. Similar to the sideband response
+buffer, the primary response buffer is shared by all client cores. For some
+processors, MMIO primary reads will return 64 bytes of data to the core fill
+buffer including both requested data and unrequested stale data. This is
+similar to the sideband stale data propagator.
+
+Vulnerabilities
+===============
+Device Register Partial Write (DRPW) (CVE-2022-21166)
+-----------------------------------------------------
+Some endpoint MMIO registers incorrectly handle writes that are smaller than
+the register size. Instead of aborting the write or only copying the correct
+subset of bytes (for example, 2 bytes for a 2-byte write), more bytes than
+specified by the write transaction may be written to the register. On
+processors affected by FBSDP, this may expose stale data from the fill buffers
+of the core that created the write transaction.
+
+Shared Buffers Data Sampling (SBDS) (CVE-2022-21125)
+----------------------------------------------------
+After propagators may have moved data around the uncore and copied stale data
+into client core fill buffers, processors affected by MFBDS can leak data from
+the fill buffer. It is limited to the client (including Intel Xeon server E3)
+uncore implementation.
+
+Shared Buffers Data Read (SBDR) (CVE-2022-21123)
+------------------------------------------------
+It is similar to Shared Buffer Data Sampling (SBDS) except that the data is
+directly read into the architectural software-visible state. It is limited to
+the client (including Intel Xeon server E3) uncore implementation.
+
+Affected Processors
+===================
+Not all the CPUs are affected by all the variants. For instance, most
+processors for the server market (excluding Intel Xeon E3 processors) are
+impacted by only Device Register Partial Write (DRPW).
+
+Below is the list of affected Intel processors [#f1]_:
+
+   ===================  ============  =========
+   Common name          Family_Model  Steppings
+   ===================  ============  =========
+   HASWELL_X            06_3FH        2,4
+   SKYLAKE_L            06_4EH        3
+   BROADWELL_X          06_4FH        All
+   SKYLAKE_X            06_55H        3,4,6,7,11
+   BROADWELL_D          06_56H        3,4,5
+   SKYLAKE              06_5EH        3
+   ICELAKE_X            06_6AH        4,5,6
+   ICELAKE_D            06_6CH        1
+   ICELAKE_L            06_7EH        5
+   ATOM_TREMONT_D       06_86H        All
+   LAKEFIELD            06_8AH        1
+   KABYLAKE_L           06_8EH        9 to 12
+   ATOM_TREMONT         06_96H        1
+   ATOM_TREMONT_L       06_9CH        0
+   KABYLAKE             06_9EH        9 to 13
+   COMETLAKE            06_A5H        2,3,5
+   COMETLAKE_L          06_A6H        0,1
+   ROCKETLAKE           06_A7H        1
+   ===================  ============  =========
+
+If a CPU is in the affected processor list, but not affected by a variant, it
+is indicated by new bits in MSR IA32_ARCH_CAPABILITIES. As described in a later
+section, mitigation largely remains the same for all the variants, i.e. to
+clear the CPU fill buffers via VERW instruction.
+
+New bits in MSRs
+================
+Newer processors and microcode update on existing affected processors added new
+bits to IA32_ARCH_CAPABILITIES MSR. These bits can be used to enumerate
+specific variants of Processor MMIO Stale Data vulnerabilities and mitigation
+capability.
+
+MSR IA32_ARCH_CAPABILITIES
+--------------------------
+Bit 13 - SBDR_SSDP_NO - When set, processor is not affected by either the
+	 Shared Buffers Data Read (SBDR) vulnerability or the sideband stale
+	 data propagator (SSDP).
+Bit 14 - FBSDP_NO - When set, processor is not affected by the Fill Buffer
+	 Stale Data Propagator (FBSDP).
+Bit 15 - PSDP_NO - When set, processor is not affected by Primary Stale Data
+	 Propagator (PSDP).
+Bit 17 - FB_CLEAR - When set, VERW instruction will overwrite CPU fill buffer
+	 values as part of MD_CLEAR operations. Processors that do not
+	 enumerate MDS_NO (meaning they are affected by MDS) but that do
+	 enumerate support for both L1D_FLUSH and MD_CLEAR implicitly enumerate
+	 FB_CLEAR as part of their MD_CLEAR support.
+Bit 18 - FB_CLEAR_CTRL - Processor supports read and write to MSR
+	 IA32_MCU_OPT_CTRL[FB_CLEAR_DIS]. On such processors, the FB_CLEAR_DIS
+	 bit can be set to cause the VERW instruction to not perform the
+	 FB_CLEAR action. Not all processors that support FB_CLEAR will support
+	 FB_CLEAR_CTRL.
+
+MSR IA32_MCU_OPT_CTRL
+---------------------
+Bit 3 - FB_CLEAR_DIS - When set, VERW instruction does not perform the FB_CLEAR
+action. This may be useful to reduce the performance impact of FB_CLEAR in
+cases where system software deems it warranted (for example, when performance
+is more critical, or the untrusted software has no MMIO access). Note that
+FB_CLEAR_DIS has no impact on enumeration (for example, it does not change
+FB_CLEAR or MD_CLEAR enumeration) and it may not be supported on all processors
+that enumerate FB_CLEAR.
+
+Mitigation
+==========
+Like MDS, all variants of Processor MMIO Stale Data vulnerabilities  have the
+same mitigation strategy to force the CPU to clear the affected buffers before
+an attacker can extract the secrets.
+
+This is achieved by using the otherwise unused and obsolete VERW instruction in
+combination with a microcode update. The microcode clears the affected CPU
+buffers when the VERW instruction is executed.
+
+Kernel reuses the MDS function to invoke the buffer clearing:
+
+	mds_clear_cpu_buffers()
+
+On MDS affected CPUs, the kernel already invokes CPU buffer clear on
+kernel/userspace, hypervisor/guest and C-state (idle) transitions. No
+additional mitigation is needed on such CPUs.
+
+For CPUs not affected by MDS or TAA, mitigation is needed only for the attacker
+with MMIO capability. Therefore, VERW is not required for kernel/userspace. For
+virtualization case, VERW is only needed at VMENTER for a guest with MMIO
+capability.
+
+Mitigation points
+-----------------
+Return to user space
+^^^^^^^^^^^^^^^^^^^^
+Same mitigation as MDS when affected by MDS/TAA, otherwise no mitigation
+needed.
+
+C-State transition
+^^^^^^^^^^^^^^^^^^
+Control register writes by CPU during C-state transition can propagate data
+from fill buffer to uncore buffers. Execute VERW before C-state transition to
+clear CPU fill buffers.
+
+Guest entry point
+^^^^^^^^^^^^^^^^^
+Same mitigation as MDS when processor is also affected by MDS/TAA, otherwise
+execute VERW at VMENTER only for MMIO capable guests. On CPUs not affected by
+MDS/TAA, guest without MMIO access cannot extract secrets using Processor MMIO
+Stale Data vulnerabilities, so there is no need to execute VERW for such guests.
+
+Mitigation control on the kernel command line
+---------------------------------------------
+The kernel command line allows to control the Processor MMIO Stale Data
+mitigations at boot time with the option "mmio_stale_data=". The valid
+arguments for this option are:
+
+  ==========  =================================================================
+  full        If the CPU is vulnerable, enable mitigation; CPU buffer clearing
+              on exit to userspace and when entering a VM. Idle transitions are
+              protected as well. It does not automatically disable SMT.
+  full,nosmt  Same as full, with SMT disabled on vulnerable CPUs. This is the
+              complete mitigation.
+  off         Disables mitigation completely.
+  ==========  =================================================================
+
+If the CPU is affected and mmio_stale_data=off is not supplied on the kernel
+command line, then the kernel selects the appropriate mitigation.
+
+Mitigation status information
+-----------------------------
+The Linux kernel provides a sysfs interface to enumerate the current
+vulnerability status of the system: whether the system is vulnerable, and
+which mitigations are active. The relevant sysfs file is:
+
+	/sys/devices/system/cpu/vulnerabilities/mmio_stale_data
+
+The possible values in this file are:
+
+  .. list-table::
+
+     * - 'Not affected'
+       - The processor is not vulnerable
+     * - 'Vulnerable'
+       - The processor is vulnerable, but no mitigation enabled
+     * - 'Vulnerable: Clear CPU buffers attempted, no microcode'
+       - The processor is vulnerable, but microcode is not updated. The
+         mitigation is enabled on a best effort basis.
+     * - 'Mitigation: Clear CPU buffers'
+       - The processor is vulnerable and the CPU buffer clearing mitigation is
+         enabled.
+     * - 'Unknown: No mitigations'
+       - The processor vulnerability status is unknown because it is
+	 out of Servicing period. Mitigation is not attempted.
+
+Definitions:
+------------
+
+Servicing period: The process of providing functional and security updates to
+Intel processors or platforms, utilizing the Intel Platform Update (IPU)
+process or other similar mechanisms.
+
+End of Servicing Updates (ESU): ESU is the date at which Intel will no
+longer provide Servicing, such as through IPU or other similar update
+processes. ESU dates will typically be aligned to end of quarter.
+
+If the processor is vulnerable then the following information is appended to
+the above information:
+
+  ========================  ===========================================
+  'SMT vulnerable'          SMT is enabled
+  'SMT disabled'            SMT is disabled
+  'SMT Host state unknown'  Kernel runs in a VM, Host SMT state unknown
+  ========================  ===========================================
+
+References
+----------
+.. [#f1] Affected Processors
+   https://www.intel.com/content/www/us/en/developer/topic-technology/software-security-guidance/processors-affected-consolidated-product-cpu-model.html
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/admin-guide/hw-vuln/special-register-buffer-data-sampling.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/admin-guide/hw-vuln/special-register-buffer-data-sampling.rst
@@ -0,0 +1,149 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+SRBDS - Special Register Buffer Data Sampling
+=============================================
+
+SRBDS is a hardware vulnerability that allows MDS :doc:`mds` techniques to
+infer values returned from special register accesses.  Special register
+accesses are accesses to off core registers.  According to Intel's evaluation,
+the special register reads that have a security expectation of privacy are
+RDRAND, RDSEED and SGX EGETKEY.
+
+When RDRAND, RDSEED and EGETKEY instructions are used, the data is moved
+to the core through the special register mechanism that is susceptible
+to MDS attacks.
+
+Affected processors
+--------------------
+Core models (desktop, mobile, Xeon-E3) that implement RDRAND and/or RDSEED may
+be affected.
+
+A processor is affected by SRBDS if its Family_Model and stepping is
+in the following list, with the exception of the listed processors
+exporting MDS_NO while Intel TSX is available yet not enabled. The
+latter class of processors are only affected when Intel TSX is enabled
+by software using TSX_CTRL_MSR otherwise they are not affected.
+
+  =============  ============  ========
+  common name    Family_Model  Stepping
+  =============  ============  ========
+  IvyBridge      06_3AH        All
+
+  Haswell        06_3CH        All
+  Haswell_L      06_45H        All
+  Haswell_G      06_46H        All
+
+  Broadwell_G    06_47H        All
+  Broadwell      06_3DH        All
+
+  Skylake_L      06_4EH        All
+  Skylake        06_5EH        All
+
+  Kabylake_L     06_8EH        <= 0xC
+  Kabylake       06_9EH        <= 0xD
+  =============  ============  ========
+
+Related CVEs
+------------
+
+The following CVE entry is related to this SRBDS issue:
+
+    ==============  =====  =====================================
+    CVE-2020-0543   SRBDS  Special Register Buffer Data Sampling
+    ==============  =====  =====================================
+
+Attack scenarios
+----------------
+An unprivileged user can extract values returned from RDRAND and RDSEED
+executed on another core or sibling thread using MDS techniques.
+
+
+Mitigation mechanism
+-------------------
+Intel will release microcode updates that modify the RDRAND, RDSEED, and
+EGETKEY instructions to overwrite secret special register data in the shared
+staging buffer before the secret data can be accessed by another logical
+processor.
+
+During execution of the RDRAND, RDSEED, or EGETKEY instructions, off-core
+accesses from other logical processors will be delayed until the special
+register read is complete and the secret data in the shared staging buffer is
+overwritten.
+
+This has three effects on performance:
+
+#. RDRAND, RDSEED, or EGETKEY instructions have higher latency.
+
+#. Executing RDRAND at the same time on multiple logical processors will be
+   serialized, resulting in an overall reduction in the maximum RDRAND
+   bandwidth.
+
+#. Executing RDRAND, RDSEED or EGETKEY will delay memory accesses from other
+   logical processors that miss their core caches, with an impact similar to
+   legacy locked cache-line-split accesses.
+
+The microcode updates provide an opt-out mechanism (RNGDS_MITG_DIS) to disable
+the mitigation for RDRAND and RDSEED instructions executed outside of Intel
+Software Guard Extensions (Intel SGX) enclaves. On logical processors that
+disable the mitigation using this opt-out mechanism, RDRAND and RDSEED do not
+take longer to execute and do not impact performance of sibling logical
+processors memory accesses. The opt-out mechanism does not affect Intel SGX
+enclaves (including execution of RDRAND or RDSEED inside an enclave, as well
+as EGETKEY execution).
+
+IA32_MCU_OPT_CTRL MSR Definition
+--------------------------------
+Along with the mitigation for this issue, Intel added a new thread-scope
+IA32_MCU_OPT_CTRL MSR, (address 0x123). The presence of this MSR and
+RNGDS_MITG_DIS (bit 0) is enumerated by CPUID.(EAX=07H,ECX=0).EDX[SRBDS_CTRL =
+9]==1. This MSR is introduced through the microcode update.
+
+Setting IA32_MCU_OPT_CTRL[0] (RNGDS_MITG_DIS) to 1 for a logical processor
+disables the mitigation for RDRAND and RDSEED executed outside of an Intel SGX
+enclave on that logical processor. Opting out of the mitigation for a
+particular logical processor does not affect the RDRAND and RDSEED mitigations
+for other logical processors.
+
+Note that inside of an Intel SGX enclave, the mitigation is applied regardless
+of the value of RNGDS_MITG_DS.
+
+Mitigation control on the kernel command line
+---------------------------------------------
+The kernel command line allows control over the SRBDS mitigation at boot time
+with the option "srbds=".  The option for this is:
+
+  ============= =============================================================
+  off           This option disables SRBDS mitigation for RDRAND and RDSEED on
+                affected platforms.
+  ============= =============================================================
+
+SRBDS System Information
+-----------------------
+The Linux kernel provides vulnerability status information through sysfs.  For
+SRBDS this can be accessed by the following sysfs file:
+/sys/devices/system/cpu/vulnerabilities/srbds
+
+The possible values contained in this file are:
+
+ ============================== =============================================
+ Not affected                   Processor not vulnerable
+ Vulnerable                     Processor vulnerable and mitigation disabled
+ Vulnerable: No microcode       Processor vulnerable and microcode is missing
+                                mitigation
+ Mitigation: Microcode          Processor is vulnerable and mitigation is in
+                                effect.
+ Mitigation: TSX disabled       Processor is only vulnerable when TSX is
+                                enabled while this system was booted with TSX
+                                disabled.
+ Unknown: Dependent on
+ hypervisor status              Running on virtual guest processor that is
+                                affected but with no way to know if host
+                                processor is mitigated or vulnerable.
+ ============================== =============================================
+
+SRBDS Default mitigation
+------------------------
+This new microcode serializes processor access during execution of RDRAND,
+RDSEED ensures that the shared buffer is overwritten before it is released for
+reuse.  Use the "srbds=off" kernel command line to disable the mitigation for
+RDRAND and RDSEED.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/admin-guide/hw-vuln/spectre.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/admin-guide/hw-vuln/spectre.rst
@@ -60,8 +60,8 @@
 Spectre variant 1 attacks take advantage of speculative execution of
 conditional branches, while Spectre variant 2 attacks use speculative
 execution of indirect branches to leak privileged memory.
-See :ref:`[1] <spec_ref1>` :ref:`[5] <spec_ref5>` :ref:`[7] <spec_ref7>`
-:ref:`[10] <spec_ref10>` :ref:`[11] <spec_ref11>`.
+See :ref:`[1] <spec_ref1>` :ref:`[5] <spec_ref5>` :ref:`[6] <spec_ref6>`
+:ref:`[7] <spec_ref7>` :ref:`[10] <spec_ref10>` :ref:`[11] <spec_ref11>`.
 
 Spectre variant 1 (Bounds Check Bypass)
 ---------------------------------------
@@ -131,6 +131,18 @@
 speculative execution's side effects left in level 1 cache to infer the
 victim's data.
 
+Yet another variant 2 attack vector is for the attacker to poison the
+Branch History Buffer (BHB) to speculatively steer an indirect branch
+to a specific Branch Target Buffer (BTB) entry, even if the entry isn't
+associated with the source address of the indirect branch. Specifically,
+the BHB might be shared across privilege levels even in the presence of
+Enhanced IBRS.
+
+Previously the only known real-world BHB attack vector was via unprivileged
+eBPF. Further research has found attacks that don't require unprivileged eBPF.
+For a full mitigation against BHB attacks it is recommended to set BHI_DIS_S or
+use the BHB clearing sequence.
+
 Attack scenarios
 ----------------
 
@@ -364,13 +376,15 @@
 
   - Kernel status:
 
-  ====================================  =================================
-  'Not affected'                        The processor is not vulnerable
-  'Vulnerable'                          Vulnerable, no mitigation
-  'Mitigation: Full generic retpoline'  Software-focused mitigation
-  'Mitigation: Full AMD retpoline'      AMD-specific software mitigation
-  'Mitigation: Enhanced IBRS'           Hardware-focused mitigation
-  ====================================  =================================
+  ========================================  =================================
+  'Not affected'                            The processor is not vulnerable
+  'Mitigation: None'                        Vulnerable, no mitigation
+  'Mitigation: Retpolines'                  Use Retpoline thunks
+  'Mitigation: LFENCE'                      Use LFENCE instructions
+  'Mitigation: Enhanced IBRS'               Hardware-focused mitigation
+  'Mitigation: Enhanced IBRS + Retpolines'  Hardware-focused + Retpolines
+  'Mitigation: Enhanced IBRS + LFENCE'      Hardware-focused + LFENCE
+  ========================================  =================================
 
   - Firmware status: Show if Indirect Branch Restricted Speculation (IBRS) is
     used to protect against Spectre variant 2 attacks when calling firmware (x86 only).
@@ -407,6 +421,31 @@
   'RSB filling'   Protection of RSB on context switch enabled
   =============   ===========================================
 
+  - EIBRS Post-barrier Return Stack Buffer (PBRSB) protection status:
+
+  ===========================  =======================================================
+  'PBRSB-eIBRS: SW sequence'   CPU is affected and protection of RSB on VMEXIT enabled
+  'PBRSB-eIBRS: Vulnerable'    CPU is vulnerable
+  'PBRSB-eIBRS: Not affected'  CPU is not affected by PBRSB
+  ===========================  =======================================================
+
+  - Branch History Injection (BHI) protection status:
+
+.. list-table::
+
+ * - BHI: Not affected
+   - System is not affected
+ * - BHI: Retpoline
+   - System is protected by retpoline
+ * - BHI: BHI_DIS_S
+   - System is protected by BHI_DIS_S
+ * - BHI: SW loop, KVM SW loop
+   - System is protected by software clearing sequence
+ * - BHI: Vulnerable
+   - System is vulnerable to BHI
+ * - BHI: Vulnerable, KVM: SW loop
+   - System is vulnerable; KVM is protected by software clearing sequence
+
 Full mitigation might require a microcode update from the CPU
 vendor. When the necessary microcode is not available, the kernel will
 report vulnerability.
@@ -456,8 +495,19 @@
    On Intel Skylake-era systems the mitigation covers most, but not all,
    cases. See :ref:`[3] <spec_ref3>` for more details.
 
-   On CPUs with hardware mitigation for Spectre variant 2 (e.g. Enhanced
-   IBRS on x86), retpoline is automatically disabled at run time.
+   On CPUs with hardware mitigation for Spectre variant 2 (e.g. IBRS
+   or enhanced IBRS on x86), retpoline is automatically disabled at run time.
+
+   Systems which support enhanced IBRS (eIBRS) enable IBRS protection once at
+   boot, by setting the IBRS bit, and they're automatically protected against
+   Spectre v2 variant attacks.
+
+   On Intel's enhanced IBRS systems, this includes cross-thread branch target
+   injections on SMT systems (STIBP). In other words, Intel eIBRS enables
+   STIBP, too.
+
+   AMD Automatic IBRS does not protect userspace, and Legacy IBRS systems clear
+   the IBRS bit on exit to userspace, therefore both explicitly enable STIBP.
 
    The retpoline mitigation is turned on by default on vulnerable
    CPUs. It can be forced on or off by the administrator
@@ -468,7 +518,7 @@
    before invoking any firmware code to prevent Spectre variant 2 exploits
    using the firmware.
 
-   Using kernel address space randomization (CONFIG_RANDOMIZE_SLAB=y
+   Using kernel address space randomization (CONFIG_RANDOMIZE_BASE=y
    and CONFIG_SLAB_FREELIST_RANDOM=y in the kernel configuration) makes
    attacks on the kernel generally more difficult.
 
@@ -481,9 +531,12 @@
    For Spectre variant 2 mitigation, individual user programs
    can be compiled with return trampolines for indirect branches.
    This protects them from consuming poisoned entries in the branch
-   target buffer left by malicious software.  Alternatively, the
-   programs can disable their indirect branch speculation via prctl()
-   (See :ref:`Documentation/userspace-api/spec_ctrl.rst <set_spec_ctrl>`).
+   target buffer left by malicious software.
+
+   On legacy IBRS systems, at return to userspace, implicit STIBP is disabled
+   because the kernel clears the IBRS bit. In this case, the userspace programs
+   can disable indirect branch speculation via prctl() (See
+   :ref:`Documentation/userspace-api/spec_ctrl.rst <set_spec_ctrl>`).
    On x86, this will turn on STIBP to guard against attacks from the
    sibling thread when the user program is running, and use IBPB to
    flush the branch target buffer when switching to/from the program.
@@ -584,12 +637,14 @@
 
 		Specific mitigations can also be selected manually:
 
-		retpoline
-					replace indirect branches
-		retpoline,generic
-					google's original retpoline
-		retpoline,amd
-					AMD-specific minimal thunk
+                retpoline               auto pick between generic,lfence
+                retpoline,generic       Retpolines
+                retpoline,lfence        LFENCE; indirect branch
+                retpoline,amd           alias for retpoline,lfence
+                eibrs                   Enhanced/Auto IBRS
+                eibrs,retpoline         Enhanced/Auto IBRS + Retpolines
+                eibrs,lfence            Enhanced/Auto IBRS + LFENCE
+                ibrs                    use IBRS to protect kernel
 
 		Not specifying this option is equivalent to
 		spectre_v2=auto.
@@ -649,6 +704,24 @@
 		spectre_v2=off. Spectre variant 1 mitigations
 		cannot be disabled.
 
+	spectre_bhi=
+
+		[X86] Control mitigation of Branch History Injection
+		(BHI) vulnerability.  This setting affects the deployment
+		of the HW BHI control and the SW BHB clearing sequence.
+
+		on
+			(default) Enable the HW or SW mitigation as
+			needed.
+		off
+			Disable the mitigation.
+		auto
+			Enable the HW mitigation if needed, but
+			*don't* enable the SW mitigation except for KVM.
+			The system may be vulnerable.
+
+For spectre_v2_user see Documentation/admin-guide/kernel-parameters.txt
+
 Mitigation selection guide
 --------------------------
 
@@ -730,7 +803,7 @@
 
 .. _spec_ref6:
 
-[6] `Software techniques for managing speculation on AMD processors <https://developer.amd.com/wp-content/resources/90343-B_SoftwareTechniquesforManagingSpeculation_WP_7-18Update_FNL.pdf>`_.
+[6] `Software techniques for managing speculation on AMD processors <https://developer.amd.com/wp-content/resources/Managing-Speculation-on-AMD-Processors.pdf>`_.
 
 ARM white papers:
 
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/admin-guide/hw-vuln/tsx_async_abort.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/admin-guide/hw-vuln/tsx_async_abort.rst
@@ -174,7 +174,10 @@
                 CPU is not vulnerable to cross-thread TAA attacks.
   ============  =============================================================
 
-Not specifying this option is equivalent to "tsx_async_abort=full".
+Not specifying this option is equivalent to "tsx_async_abort=full". For
+processors that are affected by both TAA and MDS, specifying just
+"tsx_async_abort=off" without an accompanying "mds=off" will have no
+effect as the same mitigation is used for both vulnerabilities.
 
 The kernel command line also allows to control the TSX feature using the
 parameter "tsx=" on CPUs which support TSX control. MSR_IA32_TSX_CTRL is used
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/admin-guide/hw-vuln/vmscape.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/admin-guide/hw-vuln/vmscape.rst
@@ -0,0 +1,105 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+VMSCAPE
+=======
+
+VMSCAPE is a vulnerability that may allow a guest to influence the branch
+prediction in host userspace. It particularly affects hypervisors like QEMU.
+
+Even if a hypervisor may not have any sensitive data like disk encryption keys,
+guest-userspace may be able to attack the guest-kernel using the hypervisor as
+a confused deputy.
+
+Affected processors
+-------------------
+
+The following CPU families are affected by VMSCAPE:
+
+**Intel processors:**
+  - Skylake generation (Parts without Enhanced-IBRS)
+  - Cascade Lake generation - (Parts affected by ITS guest/host separation)
+  - Alder Lake and newer (Parts affected by BHI)
+
+Note that, BHI affected parts that use BHB clearing software mitigation e.g.
+Icelake are not vulnerable to VMSCAPE.
+
+**AMD processors:**
+  - Zen series (families 0x17, 0x19, 0x1a)
+
+** Hygon processors:**
+ - Family 0x18
+
+Mitigation
+----------
+
+Conditional IBPB
+----------------
+
+Kernel tracks when a CPU has run a potentially malicious guest and issues an
+IBPB before the first exit to userspace after VM-exit. If userspace did not run
+between VM-exit and the next VM-entry, no IBPB is issued.
+
+Note that the existing userspace mitigation against Spectre-v2 is effective in
+protecting the userspace. They are insufficient to protect the userspace VMMs
+from a malicious guest. This is because Spectre-v2 mitigations are applied at
+context switch time, while the userspace VMM can run after a VM-exit without a
+context switch.
+
+Vulnerability enumeration and mitigation is not applied inside a guest. This is
+because nested hypervisors should already be deploying IBPB to isolate
+themselves from nested guests.
+
+SMT considerations
+------------------
+
+When Simultaneous Multi-Threading (SMT) is enabled, hypervisors can be
+vulnerable to cross-thread attacks. For complete protection against VMSCAPE
+attacks in SMT environments, STIBP should be enabled.
+
+The kernel will issue a warning if SMT is enabled without adequate STIBP
+protection. Warning is not issued when:
+
+- SMT is disabled
+- STIBP is enabled system-wide
+- Intel eIBRS is enabled (which implies STIBP protection)
+
+System information and options
+------------------------------
+
+The sysfs file showing VMSCAPE mitigation status is:
+
+  /sys/devices/system/cpu/vulnerabilities/vmscape
+
+The possible values in this file are:
+
+ * 'Not affected':
+
+   The processor is not vulnerable to VMSCAPE attacks.
+
+ * 'Vulnerable':
+
+   The processor is vulnerable and no mitigation has been applied.
+
+ * 'Mitigation: IBPB before exit to userspace':
+
+   Conditional IBPB mitigation is enabled. The kernel tracks when a CPU has
+   run a potentially malicious guest and issues an IBPB before the first
+   exit to userspace after VM-exit.
+
+Mitigation control on the kernel command line
+----------------------------------------------
+
+The mitigation can be controlled via the ``vmscape=`` command line parameter:
+
+ * ``vmscape=off``:
+
+   Disable the VMSCAPE mitigation.
+
+ * ``vmscape=ibpb``:
+
+   Enable conditional IBPB mitigation (default when CONFIG_MITIGATION_VMSCAPE=y).
+
+ * ``vmscape=force``:
+
+   Force vulnerability detection and mitigation even on processors that are
+   not known to be affected.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/admin-guide/iostats.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/admin-guide/iostats.rst
@@ -99,7 +99,7 @@
 
     Since 5.0 this field counts jiffies when at least one request was
     started or completed. If request runs more than 2 jiffies then some
-    I/O time will not be accounted unless there are other requests.
+    I/O time might be not accounted in case of concurrent requests.
 
 Field 11 -- weighted # of milliseconds spent doing I/Os
     This field is incremented at each I/O start, I/O completion, I/O
@@ -133,6 +133,9 @@
 summed to) and the result given to the user.  There is no convenient
 user interface for accessing the per-CPU counters themselves.
 
+Since 4.19 request times are measured with nanoseconds precision and
+truncated to milliseconds before showing in this interface.
+
 Disks vs Partitions
 -------------------
 
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/admin-guide/kdump/vmcoreinfo.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/admin-guide/kdump/vmcoreinfo.rst
@@ -393,6 +393,17 @@
 The kernel randomization offset. Used to compute the page offset. If
 KASLR is disabled, this value is zero.
 
+TCR_EL1.T1SZ
+------------
+
+Indicates the size offset of the memory region addressed by TTBR1_EL1.
+The region size is 2^(64-T1SZ) bytes.
+
+TTBR1_EL1 is the table base address register specified by ARMv8-A
+architecture which is used to lookup the page-tables for the Virtual
+addresses in the higher VA range (refer to ARMv8 ARM document for
+more details).
+
 arm
 ===
 
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/admin-guide/kernel-parameters.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/admin-guide/kernel-parameters.txt
@@ -113,7 +113,7 @@
 			the GPE dispatcher.
 			This facility can be used to prevent such uncontrolled
 			GPE floodings.
-			Format: <int>
+			Format: <byte>
 
 	acpi_no_auto_serialize	[HW,ACPI]
 			Disable auto-serialization of AML methods
@@ -136,6 +136,10 @@
 			dynamic table installation which will install SSDT
 			tables to /sys/firmware/acpi/tables/dynamic.
 
+	acpi_no_watchdog	[HW,ACPI,WDT]
+			Ignore the ACPI-based watchdog interface (WDAT) and let
+			a native driver control the watchdog device instead.
+
 	acpi_rsdp=	[ACPI,EFI,KEXEC]
 			Pass the RSDP address to the kernel, mostly used
 			on machines running EFI runtime service to boot the
@@ -563,7 +567,13 @@
 			loops can be debugged more effectively on production
 			systems.
 
-	clearcpuid=BITNUM [X86]
+	clocksource.max_cswd_read_retries= [KNL]
+			Number of clocksource_watchdog() retries due to
+			external delays before the clock will be marked
+			unstable.  Defaults to three retries, that is,
+			four attempts to read the clock under test.
+
+	clearcpuid=BITNUM[,BITNUM...] [X86]
 			Disable CPUID feature X for the kernel. See
 			arch/x86/include/asm/cpufeatures.h for the valid bit
 			numbers. Note the Linux specific bits are not necessarily
@@ -680,6 +690,10 @@
 			0: default value, disable debugging
 			1: enable debugging at boot time
 
+	cpufreq_driver= [X86] Allow only the named cpu frequency scaling driver
+			to register. Example: cpufreq_driver=powernow-k8
+			Format: { none | STRING }
+
 	cpuidle.off=1	[CPU_IDLE]
 			disable the cpuidle sub-system
 
@@ -815,10 +829,6 @@
 
 	debugpat	[X86] Enable PAT debugging
 
-	decnet.addr=	[HW,NET]
-			Format: <area>[,<node>]
-			See also Documentation/networking/decnet.txt.
-
 	default_hugepagesz=
 			[same as hugepagesz=] The size of the default
 			HugeTLB page size. This is the size represented by
@@ -836,6 +846,18 @@
 			dump out devices still on the deferred probe list after
 			retrying.
 
+	dfltcc=		[HW,S390]
+			Format: { on | off | def_only | inf_only | always }
+			on:       s390 zlib hardware support for compression on
+			          level 1 and decompression (default)
+			off:      No s390 zlib hardware support
+			def_only: s390 zlib hardware support for deflate
+			          only (compression on level 1)
+			inf_only: s390 zlib hardware support for inflate
+			          only (decompression)
+			always:   Same as 'on' but ignores the selected compression
+			          level always using hardware support (used for debugging)
+
 	dhash_entries=	[KNL]
 			Set number of hash buckets for dentry cache.
 
@@ -1330,6 +1352,26 @@
 			Format: off | on
 			default: on
 
+	gather_data_sampling=
+			[X86,INTEL] Control the Gather Data Sampling (GDS)
+			mitigation.
+
+			Gather Data Sampling is a hardware vulnerability which
+			allows unprivileged speculative access to data which was
+			previously stored in vector registers.
+
+			This issue is mitigated by default in updated microcode.
+			The mitigation may have a performance impact but can be
+			disabled. On systems without the microcode mitigation
+			disabling AVX serves as a mitigation.
+
+			force:	Disable AVX to mitigate systems without
+				microcode mitigation. No effect if the microcode
+				mitigation is present. Known to cause crashes in
+				userspace with buggy AVX enumeration.
+
+			off:	Disable GDS mitigation.
+
 	gcov_persist=	[GCOV] When non-zero (default), profiling data for
 			kernel modules is saved and remains accessible via
 			debugfs, even when the module is unloaded/reloaded.
@@ -1477,6 +1519,8 @@
 			architectures force reset to be always executed
 	i8042.unlock	[HW] Unlock (ignore) the keylock
 	i8042.kbdreset	[HW] Reset device connected to KBD port
+	i8042.probe_defer
+			[HW] Allow deferred probing upon i8042 probe errors
 
 	i810=		[HW,DRM]
 
@@ -1932,24 +1976,57 @@
 
 	ivrs_ioapic	[HW,X86_64]
 			Provide an override to the IOAPIC-ID<->DEVICE-ID
-			mapping provided in the IVRS ACPI table. For
-			example, to map IOAPIC-ID decimal 10 to
-			PCI device 00:14.0 write the parameter as:
+			mapping provided in the IVRS ACPI table.
+			By default, PCI segment is 0, and can be omitted.
+
+			For example, to map IOAPIC-ID decimal 10 to
+			PCI segment 0x1 and PCI device 00:14.0,
+			write the parameter as:
+				ivrs_ioapic=10@0001:00:14.0
+
+			Deprecated formats:
+			* To map IOAPIC-ID decimal 10 to PCI device 00:14.0
+			  write the parameter as:
 				ivrs_ioapic[10]=00:14.0
+			* To map IOAPIC-ID decimal 10 to PCI segment 0x1 and
+			  PCI device 00:14.0 write the parameter as:
+				ivrs_ioapic[10]=0001:00:14.0
 
 	ivrs_hpet	[HW,X86_64]
 			Provide an override to the HPET-ID<->DEVICE-ID
-			mapping provided in the IVRS ACPI table. For
-			example, to map HPET-ID decimal 0 to
-			PCI device 00:14.0 write the parameter as:
+			mapping provided in the IVRS ACPI table.
+			By default, PCI segment is 0, and can be omitted.
+
+			For example, to map HPET-ID decimal 10 to
+			PCI segment 0x1 and PCI device 00:14.0,
+			write the parameter as:
+				ivrs_hpet=10@0001:00:14.0
+
+			Deprecated formats:
+			* To map HPET-ID decimal 0 to PCI device 00:14.0
+			  write the parameter as:
 				ivrs_hpet[0]=00:14.0
+			* To map HPET-ID decimal 10 to PCI segment 0x1 and
+			  PCI device 00:14.0 write the parameter as:
+				ivrs_ioapic[10]=0001:00:14.0
 
 	ivrs_acpihid	[HW,X86_64]
 			Provide an override to the ACPI-HID:UID<->DEVICE-ID
-			mapping provided in the IVRS ACPI table. For
-			example, to map UART-HID:UID AMD0020:0 to
-			PCI device 00:14.5 write the parameter as:
+			mapping provided in the IVRS ACPI table.
+			By default, PCI segment is 0, and can be omitted.
+
+			For example, to map UART-HID:UID AMD0020:0 to
+			PCI segment 0x1 and PCI device ID 00:14.5,
+			write the parameter as:
+				ivrs_acpihid=AMD0020:0@0001:00:14.5
+
+			Deprecated formats:
+			* To map UART-HID:UID AMD0020:0 to PCI segment is 0,
+			  PCI device ID 00:14.5, write the parameter as:
 				ivrs_acpihid[00:14.5]=AMD0020:0
+			* To map UART-HID:UID AMD0020:0 to PCI segment 0x1 and
+			  PCI device ID 00:14.5, write the parameter as:
+				ivrs_acpihid[0001:00:14.5]=AMD0020:0
 
 	js=		[HW,JOY] Analog joystick
 			See Documentation/input/joydev/joystick.rst.
@@ -2102,8 +2179,12 @@
 			Default is 1 (enabled)
 
 	kvm-intel.emulate_invalid_guest_state=
-			[KVM,Intel] Enable emulation of invalid guest states
-			Default is 0 (disabled)
+			[KVM,Intel] Disable emulation of invalid guest state.
+			Ignored if kvm-intel.enable_unrestricted_guest=1, as
+			guest state is never invalid for unrestricted guests.
+			This param doesn't apply to nested guests (L2), as KVM
+			never emulates invalid L2 guest state.
+			Default is 1 (enabled)
 
 	kvm-intel.flexpriority=
 			[KVM,Intel] Disable FlexPriority feature (TPR shadow).
@@ -2473,6 +2554,12 @@
 				     SMT on vulnerable CPUs
 			off        - Unconditionally disable MDS mitigation
 
+			On TAA-affected machines, mds=off can be prevented by
+			an active TAA mitigation as both vulnerabilities are
+			mitigated with the same mechanism so in order to disable
+			this mitigation, you need to specify tsx_async_abort=off
+			too.
+
 			Not specifying this option is equivalent to
 			mds=full.
 
@@ -2645,18 +2732,28 @@
 				Disable all optional CPU mitigations.  This
 				improves system performance, but it may also
 				expose users to several CPU vulnerabilities.
-				Equivalent to: nopti [X86,PPC]
-					       kpti=0 [ARM64]
-					       nospectre_v1 [X86,PPC]
+				Equivalent to: if nokaslr then kpti=0 [ARM64]
+					       gather_data_sampling=off [X86]
+					       kvm.nx_huge_pages=off [X86]
+					       l1tf=off [X86]
+					       mds=off [X86]
+					       mmio_stale_data=off [X86]
+					       no_entry_flush [PPC]
+					       no_uaccess_flush [PPC]
+					       mmio_stale_data=off [X86]
 					       nobp=0 [S390]
+					       nopti [X86,PPC]
+					       nospectre_bhb [ARM64]
+					       nospectre_v1 [X86,PPC]
 					       nospectre_v2 [X86,PPC,S390,ARM64]
-					       spectre_v2_user=off [X86]
+					       retbleed=off [X86]
 					       spec_store_bypass_disable=off [X86,PPC]
+					       spectre_bhi=off [X86]
+					       spectre_v2_user=off [X86]
+					       srbds=off [X86,INTEL]
 					       ssbd=force-off [ARM64]
-					       l1tf=off [X86]
-					       mds=off [X86]
 					       tsx_async_abort=off [X86]
-					       kvm.nx_huge_pages=off [X86]
+					       vmscape=off [X86]
 
 				Exceptions:
 					       This does not have any effect on
@@ -2678,6 +2775,7 @@
 				Equivalent to: l1tf=flush,nosmt [X86]
 					       mds=full,nosmt [X86]
 					       tsx_async_abort=full,nosmt [X86]
+					       mmio_stale_data=full,nosmt [X86]
 
 	mminit_loglevel=
 			[KNL] When CONFIG_DEBUG_MEMORY_INIT is set, this
@@ -2687,6 +2785,40 @@
 			log everything. Information is printed at KERN_DEBUG
 			so loglevel=8 may also need to be specified.
 
+	mmio_stale_data=
+			[X86,INTEL] Control mitigation for the Processor
+			MMIO Stale Data vulnerabilities.
+
+			Processor MMIO Stale Data is a class of
+			vulnerabilities that may expose data after an MMIO
+			operation. Exposed data could originate or end in
+			the same CPU buffers as affected by MDS and TAA.
+			Therefore, similar to MDS and TAA, the mitigation
+			is to clear the affected CPU buffers.
+
+			This parameter controls the mitigation. The
+			options are:
+
+			full       - Enable mitigation on vulnerable CPUs
+
+			full,nosmt - Enable mitigation and disable SMT on
+				     vulnerable CPUs.
+
+			off        - Unconditionally disable mitigation
+
+			On MDS or TAA affected machines,
+			mmio_stale_data=off can be prevented by an active
+			MDS or TAA mitigation as these vulnerabilities are
+			mitigated with the same mechanism so in order to
+			disable this mitigation, you need to specify
+			mds=off and tsx_async_abort=off too.
+
+			Not specifying this option is equivalent to
+			mmio_stale_data=full.
+
+			For details see:
+			Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst
+
 	module.sig_enforce
 			[KNL] When CONFIG_MODULE_SIG is set, this means that
 			modules without (valid) signatures will fail to load.
@@ -2731,7 +2863,7 @@
 			<name>,<region-number>[,<base>,<size>,<buswidth>,<altbuswidth>]
 
 	mtdparts=	[MTD]
-			See drivers/mtd/cmdlinepart.c.
+			See drivers/mtd/parsers/cmdlinepart.c
 
 	multitce=off	[PPC]  This parameter disables the use of the pSeries
 			firmware feature for updating multiple TCE entries
@@ -2979,6 +3111,8 @@
 
 	noefi		Disable EFI runtime services support.
 
+	no_entry_flush  [PPC] Don't flush the L1-D cache when entering the kernel.
+
 	noexec		[IA-64]
 
 	noexec		[X86]
@@ -3028,6 +3162,9 @@
 	nospec_store_bypass_disable
 			[HW] Disable all mitigations for the Speculative Store Bypass vulnerability
 
+	no_uaccess_flush
+	                [PPC] Don't flush the L1-D cache after accessing user data.
+
 	noxsave		[BUGS=X86] Disables x86 extended register state save
 			and restore using xsave. The kernel will fallback to
 			enabling legacy floating-point and sse state.
@@ -3402,6 +3539,12 @@
 		nomsi		[MSI] If the PCI_MSI kernel config parameter is
 				enabled, this kernel boot option can be used to
 				disable the use of MSI interrupts system-wide.
+		clearmsi	[X86] Clears MSI/MSI-X enable bits early in boot
+				time in order to avoid issues like adapters
+				screaming irqs and preventing boot progress.
+				Also, it enforces the PCI Local Bus spec
+				rule that those bits should be 0 in system reset
+				events (useful for kexec/kdump cases).
 		noioapicquirk	[APIC] Disable all boot interrupt quirks.
 				Safety option to keep boot IRQs enabled. This
 				should never be necessary.
@@ -3555,6 +3698,8 @@
 				may put more devices in an IOMMU group.
 		force_floating	[S390] Force usage of floating interrupts.
 		nomio		[S390] Do not use MIO instructions.
+		norid		[S390] ignore the RID field and force use of
+				one PCI domain per PCI function
 
 	pcie_aspm=	[PCIE] Forcibly enable or disable PCIe Active State Power
 			Management.
@@ -3567,6 +3712,8 @@
 			even if the platform doesn't give the OS permission to
 			use them.  This may cause conflicts if the platform
 			also tries to use these services.
+		dpc-native	Use native PCIe service for DPC only.  May
+				cause conflicts if firmware uses AER or DPC.
 		compat	Disable native PCIe services (PME, AER, DPC, PCIe
 			hotplug).
 
@@ -3697,6 +3844,16 @@
 	printk.time=	Show timing data prefixed to each printk message line
 			Format: <bool>  (1/Y/y=enable, 0/N/n=disable)
 
+	proc_mem.force_override= [KNL]
+			Format: {always | ptrace | never}
+			Traditionally /proc/pid/mem allows memory permissions to be
+			overridden without restrictions. This option may be set to
+			restrict that. Can be one of:
+			- 'always': traditional behavior always allows mem overrides.
+			- 'ptrace': only allow mem overrides for active ptracers.
+			- 'never':  never allow mem overrides.
+			If not specified, default is the CONFIG_PROC_MEM_* choice.
+
 	processor.max_cstate=	[HW,ACPI]
 			Limit processor to maximum C-state
 			max_cstate=9 overrides any DMI blacklist limit.
@@ -3720,6 +3877,11 @@
 			before loading.
 			See Documentation/admin-guide/blockdev/ramdisk.rst.
 
+	prot_virt=	[S390] enable hosting protected virtual machines
+			isolated from the hypervisor (if hardware supports
+			that).
+			Format: <bool>
+
 	psi=		[KNL] Enable or disable pressure stall information
 			tracking.
 			Format: <bool>
@@ -3777,6 +3939,12 @@
 			fully seed the kernel's CRNG. Default is controlled
 			by CONFIG_RANDOM_TRUST_CPU.
 
+	random.trust_bootloader={on,off}
+			[KNL] Enable or disable trusting the use of a
+			seed passed by the bootloader (if available) to
+			fully seed the kernel's CRNG. Default is controlled
+			by CONFIG_RANDOM_TRUST_BOOTLOADER.
+
 	ras=option[,option,...]	[KNL] RAS-specific options
 
 		cec_disable	[X86]
@@ -4227,6 +4395,18 @@
 
 	retain_initrd	[RAM] Keep initrd memory after extraction
 
+	retbleed=	[X86] Control mitigation of RETBleed (Arbitrary
+			Speculative Code Execution with Return Instructions)
+			vulnerability.
+
+			off         - unconditionally disable
+			auto        - automatically select a migitation
+
+			Selecting 'auto' will choose a mitigation method at run
+			time according to the CPU.
+
+			Not specifying this option is equivalent to retbleed=auto.
+
 	rfkill.default_state=
 		0	"airplane mode".  All wifi, bluetooth, wimax, gps, fm,
 			etc. communication is blocked by default.
@@ -4437,6 +4617,18 @@
 	sonypi.*=	[HW] Sony Programmable I/O Control Device driver
 			See Documentation/admin-guide/laptops/sonypi.rst
 
+	spectre_bhi=	[X86] Control mitigation of Branch History Injection
+			(BHI) vulnerability.  This setting affects the
+			deployment of the HW BHI control and the SW BHB
+			clearing sequence.
+
+			on   - (default) Enable the HW or SW mitigation
+			       as needed.
+			off  - Disable the mitigation.
+			auto - Enable the HW mitigation if needed, but
+			       *don't* enable the SW mitigation except
+			       for KVM.  The system may be vulnerable.
+
 	spectre_v2=	[X86] Control mitigation of Spectre variant 2
 			(indirect branch speculation) vulnerability.
 			The default operation protects the kernel from
@@ -4464,8 +4656,13 @@
 			Specific mitigations can also be selected manually:
 
 			retpoline	  - replace indirect branches
-			retpoline,generic - google's original retpoline
-			retpoline,amd     - AMD-specific minimal thunk
+			retpoline,generic - Retpolines
+			retpoline,lfence  - LFENCE; indirect branch
+			retpoline,amd     - alias for retpoline,lfence
+			eibrs		  - Enhanced/Auto IBRS
+			eibrs,retpoline   - Enhanced/Auto IBRS + Retpolines
+			eibrs,lfence      - Enhanced/Auto IBRS + LFENCE
+			ibrs		  - use IBRS to protect kernel
 
 			Not specifying this option is equivalent to
 			spectre_v2=auto.
@@ -4569,6 +4766,26 @@
 	spia_pedr=
 	spia_peddr=
 
+	srbds=		[X86,INTEL]
+			Control the Special Register Buffer Data Sampling
+			(SRBDS) mitigation.
+
+			Certain CPUs are vulnerable to an MDS-like
+			exploit which can leak bits from the random
+			number generator.
+
+			By default, this issue is mitigated by
+			microcode.  However, the microcode fix can cause
+			the RDRAND and RDSEED instructions to become
+			much slower.  Among other effects, this will
+			result in reduced throughput from /dev/urandom.
+
+			The microcode mitigation can be disabled with
+			the following option:
+
+			off:    Disable mitigation and remove
+				performance impact to RDRAND and RDSEED
+
 	srcutree.counter_wrap_check [KNL]
 			Specifies how frequently to check for
 			grace-period sequence counter wrap for the
@@ -4931,6 +5148,11 @@
 				     vulnerable to cross-thread TAA attacks.
 			off        - Unconditionally disable TAA mitigation
 
+			On MDS-affected machines, tsx_async_abort=off can be
+			prevented by an active MDS mitigation as both vulnerabilities
+			are mitigated with the same mechanism so in order to disable
+			this mitigation, you need to specify mds=off too.
+
 			Not specifying this option is equivalent to
 			tsx_async_abort=full.  On CPUs which are MDS affected
 			and deploy MDS mitigation, TAA mitigation is not
@@ -4990,8 +5212,7 @@
 
 	usbcore.old_scheme_first=
 			[USB] Start with the old device initialization
-			scheme,  applies only to low and full-speed devices
-			 (default 0 = off).
+			scheme (default 0 = off).
 
 	usbcore.usbfs_memory_mb=
 			[USB] Memory limit (in MB) for buffers allocated by
@@ -5090,13 +5311,13 @@
 			Flags is a set of characters, each corresponding
 			to a common usb-storage quirk flag as follows:
 				a = SANE_SENSE (collect more than 18 bytes
-					of sense data);
+					of sense data, not on uas);
 				b = BAD_SENSE (don't collect more than 18
-					bytes of sense data);
+					bytes of sense data, not on uas);
 				c = FIX_CAPACITY (decrease the reported
 					device capacity by one sector);
 				d = NO_READ_DISC_INFO (don't use
-					READ_DISC_INFO command);
+					READ_DISC_INFO command, not on uas);
 				e = NO_READ_CAPACITY_16 (don't use
 					READ_CAPACITY_16 command);
 				f = NO_REPORT_OPCODES (don't use report opcodes
@@ -5110,18 +5331,20 @@
 					device);
 				j = NO_REPORT_LUNS (don't use report luns
 					command, uas only);
+				k = NO_SAME (do not use WRITE_SAME, uas only)
 				l = NOT_LOCKABLE (don't try to lock and
-					unlock ejectable media);
+					unlock ejectable media, not on uas);
 				m = MAX_SECTORS_64 (don't transfer more
-					than 64 sectors = 32 KB at a time);
+					than 64 sectors = 32 KB at a time,
+					not on uas);
 				n = INITIAL_READ10 (force a retry of the
-					initial READ(10) command);
+					initial READ(10) command, not on uas);
 				o = CAPACITY_OK (accept the capacity
-					reported by the device);
+					reported by the device, not on uas);
 				p = WRITE_CACHE (the device cache is ON
-					by default);
+					by default, not on uas);
 				r = IGNORE_RESIDUE (the device reports
-					bogus residue values);
+					bogus residue values, not on uas);
 				s = SINGLE_LUN (the device has only one
 					Logical Unit);
 				t = NO_ATA_1X (don't allow ATA(12) and ATA(16)
@@ -5130,7 +5353,8 @@
 				w = NO_WP_DETECT (don't test whether the
 					medium is write-protected).
 				y = ALWAYS_SYNC (issue a SYNCHRONIZE_CACHE
-					even if the device claims no cache)
+					even if the device claims no cache,
+					not on uas)
 			Example: quirks=0419:aaf5:rl,0421:0433:rc
 
 	user_debug=	[KNL,ARM]
@@ -5239,6 +5463,16 @@
 	vmpoff=		[KNL,S390] Perform z/VM CP command after power off.
 			Format: <command>
 
+	vmscape=	[X86] Controls mitigation for VMscape attacks.
+			VMscape attacks can leak information from a userspace
+			hypervisor to a guest via speculative side-channels.
+
+			off		- disable the mitigation
+			ibpb		- use Indirect Branch Prediction Barrier
+					  (IBPB) mitigation (default)
+			force		- force vulnerability detection even on
+					  unaffected processors
+
 	vsyscall=	[X86-64]
 			Controls the behavior of vsyscalls (i.e. calls to
 			fixed addresses of 0xffffffffff600x00 from legacy
@@ -5408,6 +5642,10 @@
 			This option is obsoleted by the "nopv" option, which
 			has equivalent effect for XEN platform.
 
+	xen_no_vector_callback
+			[KNL,X86,XEN] Disable the vector callback for Xen
+			event channel interrupts.
+
 	xen_scrub_pages=	[XEN]
 			Boolean option to control scrubbing pages before giving them back
 			to Xen, for use by other domains. Can be also changed at runtime
@@ -5426,6 +5664,21 @@
 			as generic guest with no PV drivers. Currently support
 			XEN HVM, KVM, HYPER_V and VMWARE guest.
 
+	xen.balloon_boot_timeout= [XEN]
+			The time (in seconds) to wait before giving up to boot
+			in case initial ballooning fails to free enough memory.
+			Applies only when running as HVM or PVH guest and
+			started with less memory configured than allowed at
+			max. Default is 180.
+
+	xen.event_eoi_delay=	[XEN]
+			How long to delay EOI handling in case of event
+			storms (jiffies). Default is 10.
+
+	xen.event_loop_timeout=	[XEN]
+			After which time (jiffies) the event handling loop
+			should start to delay EOI handling. Default is 2.
+
 	xirc2ps_cs=	[NET,PCMCIA]
 			Format:
 			<irq>,<irq_mask>,<io>,<full_duplex>,<do_sound>,<lockup_hack>[,<irq2>[,<irq3>[,<irq4>]]]
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/admin-guide/pm/cpuidle.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/admin-guide/pm/cpuidle.rst
@@ -676,8 +676,8 @@
 by default this way, for example.
 
 The other kernel command line parameters controlling CPU idle time management
-described below are only relevant for the *x86* architecture and some of
-them affect Intel processors only.
+described below are only relevant for the *x86* architecture and references
+to ``intel_idle`` affect Intel processors only.
 
 The *x86* architecture support code recognizes three kernel command line
 options related to CPU idle time management: ``idle=poll``, ``idle=halt``,
@@ -699,10 +699,13 @@
 energy-efficiency.  Thus using it for performance reasons may not be a good idea
 at all.]
 
-The ``idle=nomwait`` option disables the ``intel_idle`` driver and causes
-``acpi_idle`` to be used (as long as all of the information needed by it is
-there in the system's ACPI tables), but it is not allowed to use the
-``MWAIT`` instruction of the CPUs to ask the hardware to enter idle states.
+The ``idle=nomwait`` option prevents the use of ``MWAIT`` instruction of
+the CPU to enter idle states. When this option is used, the ``acpi_idle``
+driver will use the ``HLT`` instruction instead of ``MWAIT``. On systems
+running Intel processors, this option disables the ``intel_idle`` driver
+and forces the use of the ``acpi_idle`` driver instead. Note that in either
+case, ``acpi_idle`` driver will function only if all the information needed
+by it is in the system's ACPI tables.
 
 In addition to the architecture-level kernel command line options affecting CPU
 idle time management, there are parameters affecting individual ``CPUIdle``
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/admin-guide/security-bugs.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/admin-guide/security-bugs.rst
@@ -56,31 +56,28 @@
 of the report are treated confidentially even after the embargo has been
 lifted, in perpetuity.
 
-Coordination
-------------
+Coordination with other groups
+------------------------------
 
-Fixes for sensitive bugs, such as those that might lead to privilege
-escalations, may need to be coordinated with the private
-<linux-distros@vs.openwall.org> mailing list so that distribution vendors
-are well prepared to issue a fixed kernel upon public disclosure of the
-upstream fix. Distros will need some time to test the proposed patch and
-will generally request at least a few days of embargo, and vendor update
-publication prefers to happen Tuesday through Thursday. When appropriate,
-the security team can assist with this coordination, or the reporter can
-include linux-distros from the start. In this case, remember to prefix
-the email Subject line with "[vs]" as described in the linux-distros wiki:
-<http://oss-security.openwall.org/wiki/mailing-lists/distros#how-to-use-the-lists>
+The kernel security team strongly recommends that reporters of potential
+security issues NEVER contact the "linux-distros" mailing list until
+AFTER discussing it with the kernel security team.  Do not Cc: both
+lists at once.  You may contact the linux-distros mailing list after a
+fix has been agreed on and you fully understand the requirements that
+doing so will impose on you and the kernel community.
+
+The different lists have different goals and the linux-distros rules do
+not contribute to actually fixing any potential security problems.
 
 CVE assignment
 --------------
 
-The security team does not normally assign CVEs, nor do we require them
-for reports or fixes, as this can needlessly complicate the process and
-may delay the bug handling. If a reporter wishes to have a CVE identifier
-assigned ahead of public disclosure, they will need to contact the private
-linux-distros list, described above. When such a CVE identifier is known
-before a patch is provided, it is desirable to mention it in the commit
-message if the reporter agrees.
+The security team does not assign CVEs, nor do we require them for
+reports or fixes, as this can needlessly complicate the process and may
+delay the bug handling.  If a reporter wishes to have a CVE identifier
+assigned, they should find one by themselves, for example by contacting
+MITRE directly.  However under no circumstances will a patch inclusion
+be delayed to wait for a CVE identifier to arrive.
 
 Non-disclosure agreements
 -------------------------
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/admin-guide/sysctl/kernel.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/admin-guide/sysctl/kernel.rst
@@ -48,6 +48,8 @@
 - hyperv_record_panic_msg
 - kexec_load_disabled
 - kptr_restrict
+- io_uring_disabled
+- io_uring_group
 - l2cr                        [ PPC only ]
 - modprobe                    ==> Documentation/debugging-modules.txt
 - modules_disabled
@@ -415,7 +417,6 @@
 
 kptr_restrict:
 ==============
-
 This toggle indicates whether restrictions are placed on
 exposing kernel addresses via /proc and other interfaces.
 
@@ -438,6 +439,35 @@
 %pK will be replaced with 0's regardless of privileges.
 
 
+io_uring_disabled:
+==================
+
+Prevents all processes from creating new io_uring instances. Enabling this
+shrinks the kernel's attack surface.
+
+= ======================================================================
+0 All processes can create io_uring instances as normal. This is the
+  default setting.
+1 io_uring creation is disabled (io_uring_setup() will fail with
+  -EPERM) for unprivileged processes not in the io_uring_group group.
+  Existing io_uring instances can still be used.  See the
+  documentation for io_uring_group for more information.
+2 io_uring creation is disabled for all processes. io_uring_setup()
+  always fails with -EPERM. Existing io_uring instances can still be
+  used.
+= ======================================================================
+
+
+io_uring_group:
+===============
+
+When io_uring_disabled is set to 1, a process must either be
+privileged (CAP_SYS_ADMIN) or be in the io_uring_group group in order
+to create an io_uring instance.  If io_uring_group is set to -1 (the
+default), only processes with the CAP_SYS_ADMIN capability may create
+io_uring instances.
+
+
 l2cr: (PPC only)
 ================
 
@@ -557,6 +587,15 @@
 scanned for a given scan.
 
 
+oops_limit
+==========
+
+Number of kernel oopses after which the kernel should panic when
+``panic_on_oops`` is not set. Setting this to 0 disables checking
+the count. Setting this to  1 has the same effect as setting
+``panic_on_oops=1``. The default value is 10000.
+
+
 osrelease, ostype & version:
 ============================
 
@@ -862,9 +901,40 @@
 a one-time setting until next reboot: once set, it cannot be changed by
 this sysctl interface anymore.
 
+pty
+===
 
-randomize_va_space:
-===================
+See Documentation/filesystems/devpts.rst.
+
+
+random
+======
+
+This is a directory, with the following entries:
+
+* ``boot_id``: a UUID generated the first time this is retrieved, and
+  unvarying after that;
+
+* ``uuid``: a UUID generated every time this is retrieved (this can
+  thus be used to generate UUIDs at will);
+
+* ``entropy_avail``: the pool's entropy count, in bits;
+
+* ``poolsize``: the entropy pool size, in bits;
+
+* ``urandom_min_reseed_secs``: obsolete (used to determine the minimum
+  number of seconds between urandom pool reseeding). This file is
+  writable for compatibility purposes, but writing to it has no effect
+  on any RNG behavior;
+
+* ``write_wakeup_threshold``: when the entropy count drops below this
+  (as a number of bits), processes waiting to write to ``/dev/random``
+  are woken up. This file is writable for compatibility purposes, but
+  writing to it has no effect on any RNG behavior.
+
+
+randomize_va_space
+==================
 
 This option can be used to select the type of process address
 space randomization that is used in the system, for architectures
@@ -1125,6 +1195,37 @@
 example.  If a system hangs up, try pressing the NMI switch.
 
 
+unprivileged_bpf_disabled:
+==========================
+
+Writing 1 to this entry will disable unprivileged calls to ``bpf()``;
+once disabled, calling ``bpf()`` without ``CAP_SYS_ADMIN`` will return
+``-EPERM``. Once set to 1, this can't be cleared from the running kernel
+anymore.
+
+Writing 2 to this entry will also disable unprivileged calls to ``bpf()``,
+however, an admin can still change this setting later on, if needed, by
+writing 0 or 1 to this entry.
+
+If ``BPF_UNPRIV_DEFAULT_OFF`` is enabled in the kernel config, then this
+entry will default to 2 instead of 0.
+
+= =============================================================
+0 Unprivileged calls to ``bpf()`` are enabled
+1 Unprivileged calls to ``bpf()`` are disabled without recovery
+2 Unprivileged calls to ``bpf()`` are disabled
+= =============================================================
+
+
+warn_limit
+==========
+
+Number of kernel warnings after which the kernel should panic when
+``panic_on_warn`` is not set. Setting this to 0 disables checking
+the warning count. Setting this to 1 has the same effect as setting
+``panic_on_warn=1``. The default value is 0.
+
+
 watchdog:
 =========
 
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/admin-guide/sysctl/net.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/admin-guide/sysctl/net.rst
@@ -31,17 +31,18 @@
 
 Table : Subdirectories in /proc/sys/net
 
- ========= =================== = ========== ==================
+ ========= =================== = ========== ===================
  Directory Content               Directory  Content
- ========= =================== = ========== ==================
- core      General parameter     appletalk  Appletalk protocol
- unix      Unix domain sockets   netrom     NET/ROM
- 802       E802 protocol         ax25       AX25
- ethernet  Ethernet protocol     rose       X.25 PLP layer
+ ========= =================== = ========== ===================
+ 802       E802 protocol         mptcp      Multipath TCP
+ appletalk Appletalk protocol    netfilter  Network Filter
+ ax25      AX25                  netrom     NET/ROM
+ bridge    Bridging              rose       X.25 PLP layer
+ core      General parameter     tipc       TIPC
+ ethernet  Ethernet protocol     unix       Unix domain sockets
  ipv4      IP version 4          x25        X.25 protocol
- bridge    Bridging              decnet     DEC net
- ipv6      IP version 6          tipc       TIPC
- ========= =================== = ========== ==================
+ ipv6      IP version 6
+ ========= =================== = ========== ===================
 
 1. /proc/sys/net/core - Network core options
 ============================================
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/admin-guide/sysctl/vm.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/admin-guide/sysctl/vm.rst
@@ -61,6 +61,7 @@
 - overcommit_memory
 - overcommit_ratio
 - page-cluster
+- page_lock_unfairness
 - panic_on_oom
 - percpu_pagelist_fraction
 - stat_interval
@@ -741,6 +742,14 @@
 that consecutive pages readahead would have brought in.
 
 
+page_lock_unfairness
+====================
+
+This value determines the number of times that the page lock can be
+stolen from under a waiter. After the lock is stolen the number of times
+specified in this file (default is 5), the "fair lock handoff" semantics
+will apply, and the waiter will only be awakened if the lock can be taken.
+
 panic_on_oom
 ============
 
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/arm/memory.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/arm/memory.rst
@@ -45,9 +45,14 @@
 fffe0000	fffe7fff	ITCM mapping area for platforms with
 				ITCM mounted inside the CPU.
 
-ffc00000	ffefffff	Fixmap mapping region.  Addresses provided
+ffc80000	ffefffff	Fixmap mapping region.  Addresses provided
 				by fix_to_virt() will be located here.
 
+ffc00000	ffc7ffff	Guard region
+
+ff800000	ffbfffff	Permanent, fixed read-only mapping of the
+				firmware provided DT blob
+
 fee00000	feffffff	Mapping of PCI I/O space. This is a static
 				mapping within the vmalloc space.
 
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/arm64/cpu-feature-registers.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/arm64/cpu-feature-registers.rst
@@ -92,7 +92,7 @@
 
 The infrastructure emulates only the following system register space::
 
-	Op0=3, Op1=0, CRn=0, CRm=0,4,5,6,7
+	Op0=3, Op1=0, CRn=0, CRm=0,2,3,4,5,6,7
 
 (See Table C5-6 'System instruction encodings for non-Debug System
 register accesses' in ARMv8 ARM DDI 0487A.h, for the list of
@@ -167,6 +167,42 @@
      | EL0                          | [3-0]   |    n    |
      +------------------------------+---------+---------+
 
+  10) MVFR0_EL1 - AArch32 Media and VFP Feature Register 0
+
+     +------------------------------+---------+---------+
+     | Name                         |  bits   | visible |
+     +------------------------------+---------+---------+
+     | FPDP                         | [11-8]  |    y    |
+     +------------------------------+---------+---------+
+
+  11) MVFR1_EL1 - AArch32 Media and VFP Feature Register 1
+
+     +------------------------------+---------+---------+
+     | Name                         |  bits   | visible |
+     +------------------------------+---------+---------+
+     | SIMDFMAC                     | [31-28] |    y    |
+     +------------------------------+---------+---------+
+     | SIMDSP                       | [19-16] |    y    |
+     +------------------------------+---------+---------+
+     | SIMDInt                      | [15-12] |    y    |
+     +------------------------------+---------+---------+
+     | SIMDLS                       | [11-8]  |    y    |
+     +------------------------------+---------+---------+
+
+  12) ID_ISAR5_EL1 - AArch32 Instruction Set Attribute Register 5
+
+     +------------------------------+---------+---------+
+     | Name                         |  bits   | visible |
+     +------------------------------+---------+---------+
+     | CRC32                        | [19-16] |    y    |
+     +------------------------------+---------+---------+
+     | SHA2                         | [15-12] |    y    |
+     +------------------------------+---------+---------+
+     | SHA1                         | [11-8]  |    y    |
+     +------------------------------+---------+---------+
+     | AES                          | [7-4]   |    y    |
+     +------------------------------+---------+---------+
+
 
   3) MIDR_EL1 - Main ID Register
 
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/arm64/silicon-errata.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/arm64/silicon-errata.rst
@@ -70,8 +70,12 @@
 +----------------+-----------------+-----------------+-----------------------------+
 | ARM            | Cortex-A57      | #834220         | ARM64_ERRATUM_834220        |
 +----------------+-----------------+-----------------+-----------------------------+
+| ARM            | Cortex-A57      | #1742098        | ARM64_ERRATUM_1742098       |
++----------------+-----------------+-----------------+-----------------------------+
 | ARM            | Cortex-A72      | #853709         | N/A                         |
 +----------------+-----------------+-----------------+-----------------------------+
+| ARM            | Cortex-A72      | #1655431        | ARM64_ERRATUM_1742098       |
++----------------+-----------------+-----------------+-----------------------------+
 | ARM            | Cortex-A73      | #858921         | ARM64_ERRATUM_858921        |
 +----------------+-----------------+-----------------+-----------------------------+
 | ARM            | Cortex-A55      | #1024718        | ARM64_ERRATUM_1024718       |
@@ -84,10 +88,52 @@
 +----------------+-----------------+-----------------+-----------------------------+
 | ARM            | Cortex-A76      | #1463225        | ARM64_ERRATUM_1463225       |
 +----------------+-----------------+-----------------+-----------------------------+
+| ARM            | Cortex-A76      | #3324349        | ARM64_ERRATUM_3194386       |
++----------------+-----------------+-----------------+-----------------------------+
+| ARM            | Cortex-A77      | #3324348        | ARM64_ERRATUM_3194386       |
++----------------+-----------------+-----------------+-----------------------------+
+| ARM            | Cortex-A78      | #3324344        | ARM64_ERRATUM_3194386       |
++----------------+-----------------+-----------------+-----------------------------+
+| ARM            | Cortex-A78C     | #3324346,3324347| ARM64_ERRATUM_3194386       |
++----------------+-----------------+-----------------+-----------------------------+
+| ARM            | Cortex-A710     | #3324338        | ARM64_ERRATUM_3194386       |
++----------------+-----------------+-----------------+-----------------------------+
+| ARM            | Cortex-A715     | #3456084        | ARM64_ERRATUM_3194386       |
++----------------+-----------------+-----------------+-----------------------------+
+| ARM            | Cortex-A720     | #3456091        | ARM64_ERRATUM_3194386       |
++----------------+-----------------+-----------------+-----------------------------+
+| ARM            | Cortex-A725     | #3456106        | ARM64_ERRATUM_3194386       |
++----------------+-----------------+-----------------+-----------------------------+
+| ARM            | Cortex-X1       | #3324344        | ARM64_ERRATUM_3194386       |
++----------------+-----------------+-----------------+-----------------------------+
+| ARM            | Cortex-X1C      | #3324346        | ARM64_ERRATUM_3194386       |
++----------------+-----------------+-----------------+-----------------------------+
+| ARM            | Cortex-X2       | #3324338        | ARM64_ERRATUM_3194386       |
++----------------+-----------------+-----------------+-----------------------------+
+| ARM            | Cortex-X3       | #3324335        | ARM64_ERRATUM_3194386       |
++----------------+-----------------+-----------------+-----------------------------+
+| ARM            | Cortex-X4       | #3194386        | ARM64_ERRATUM_3194386       |
++----------------+-----------------+-----------------+-----------------------------+
+| ARM            | Cortex-X925     | #3324334        | ARM64_ERRATUM_3194386       |
++----------------+-----------------+-----------------+-----------------------------+
 | ARM            | Neoverse-N1     | #1188873,1418040| ARM64_ERRATUM_1418040       |
 +----------------+-----------------+-----------------+-----------------------------+
 | ARM            | Neoverse-N1     | #1349291        | N/A                         |
 +----------------+-----------------+-----------------+-----------------------------+
+| ARM            | Neoverse-N1     | #1542419        | ARM64_ERRATUM_1542419       |
++----------------+-----------------+-----------------+-----------------------------+
+| ARM            | Neoverse-N1     | #3324349        | ARM64_ERRATUM_3194386       |
++----------------+-----------------+-----------------+-----------------------------+
+| ARM            | Neoverse-N2     | #3324339        | ARM64_ERRATUM_3194386       |
++----------------+-----------------+-----------------+-----------------------------+
+| ARM            | Neoverse-N3     | #3456111        | ARM64_ERRATUM_3194386       |
++----------------+-----------------+-----------------+-----------------------------+
+| ARM            | Neoverse-V1     | #3324341        | ARM64_ERRATUM_3194386       |
++----------------+-----------------+-----------------+-----------------------------+
+| ARM            | Neoverse-V2     | #3324336        | ARM64_ERRATUM_3194386       |
++----------------+-----------------+-----------------+-----------------------------+
+| ARM            | Neoverse-V3     | #3312417        | ARM64_ERRATUM_3194386       |
++----------------+-----------------+-----------------+-----------------------------+
 | ARM            | MMU-500         | #841119,826419  | N/A                         |
 +----------------+-----------------+-----------------+-----------------------------+
 +----------------+-----------------+-----------------+-----------------------------+
@@ -128,6 +174,9 @@
 +----------------+-----------------+-----------------+-----------------------------+
 | Hisilicon      | Hip08 SMMU PMCG | #162001800      | N/A                         |
 +----------------+-----------------+-----------------+-----------------------------+
+| Hisilicon      | Hip08 SMMU PMCG | #162001900      | N/A                         |
+|                | Hip09 SMMU PMCG |                 |                             |
++----------------+-----------------+-----------------+-----------------------------+
 +----------------+-----------------+-----------------+-----------------------------+
 | Qualcomm Tech. | Kryo/Falkor v1  | E1003           | QCOM_FALKOR_ERRATUM_1003    |
 +----------------+-----------------+-----------------+-----------------------------+
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/arm64/tagged-address-abi.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/arm64/tagged-address-abi.rst
@@ -44,8 +44,25 @@
 how the user addresses are used by the kernel:
 
 1. User addresses not accessed by the kernel but used for address space
-   management (e.g. ``mmap()``, ``mprotect()``, ``madvise()``). The use
-   of valid tagged pointers in this context is always allowed.
+   management (e.g. ``mprotect()``, ``madvise()``). The use of valid
+   tagged pointers in this context is allowed with these exceptions:
+
+   - ``brk()``, ``mmap()`` and the ``new_address`` argument to
+     ``mremap()`` as these have the potential to alias with existing
+      user addresses.
+
+     NOTE: This behaviour changed in v5.6 and so some earlier kernels may
+     incorrectly accept valid tagged pointers for the ``brk()``,
+     ``mmap()`` and ``mremap()`` system calls.
+
+   - The ``range.start``, ``start`` and ``dst`` arguments to the
+     ``UFFDIO_*`` ``ioctl()``s used on a file descriptor obtained from
+     ``userfaultfd()``, as fault addresses subsequently obtained by reading
+     the file descriptor will be untagged, which may otherwise confuse
+     tag-unaware programs.
+
+     NOTE: This behaviour changed in v5.14 and so some earlier kernels may
+     incorrectly accept valid tagged pointers for this system call.
 
 2. User addresses accessed by the kernel (e.g. ``write()``). This ABI
    relaxation is disabled by default and the application thread needs to
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/asm-annotations.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/asm-annotations.rst
@@ -0,0 +1,216 @@
+Assembler Annotations
+=====================
+
+Copyright (c) 2017-2019 Jiri Slaby
+
+This document describes the new macros for annotation of data and code in
+assembly. In particular, it contains information about ``SYM_FUNC_START``,
+``SYM_FUNC_END``, ``SYM_CODE_START``, and similar.
+
+Rationale
+---------
+Some code like entries, trampolines, or boot code needs to be written in
+assembly. The same as in C, such code is grouped into functions and
+accompanied with data. Standard assemblers do not force users into precisely
+marking these pieces as code, data, or even specifying their length.
+Nevertheless, assemblers provide developers with such annotations to aid
+debuggers throughout assembly. On top of that, developers also want to mark
+some functions as *global* in order to be visible outside of their translation
+units.
+
+Over time, the Linux kernel has adopted macros from various projects (like
+``binutils``) to facilitate such annotations. So for historic reasons,
+developers have been using ``ENTRY``, ``END``, ``ENDPROC``, and other
+annotations in assembly.  Due to the lack of their documentation, the macros
+are used in rather wrong contexts at some locations. Clearly, ``ENTRY`` was
+intended to denote the beginning of global symbols (be it data or code).
+``END`` used to mark the end of data or end of special functions with
+*non-standard* calling convention. In contrast, ``ENDPROC`` should annotate
+only ends of *standard* functions.
+
+When these macros are used correctly, they help assemblers generate a nice
+object with both sizes and types set correctly. For example, the result of
+``arch/x86/lib/putuser.S``::
+
+   Num:    Value          Size Type    Bind   Vis      Ndx Name
+    25: 0000000000000000    33 FUNC    GLOBAL DEFAULT    1 __put_user_1
+    29: 0000000000000030    37 FUNC    GLOBAL DEFAULT    1 __put_user_2
+    32: 0000000000000060    36 FUNC    GLOBAL DEFAULT    1 __put_user_4
+    35: 0000000000000090    37 FUNC    GLOBAL DEFAULT    1 __put_user_8
+
+This is not only important for debugging purposes. When there are properly
+annotated objects like this, tools can be run on them to generate more useful
+information. In particular, on properly annotated objects, ``objtool`` can be
+run to check and fix the object if needed. Currently, ``objtool`` can report
+missing frame pointer setup/destruction in functions. It can also
+automatically generate annotations for :doc:`ORC unwinder <x86/orc-unwinder>`
+for most code. Both of these are especially important to support reliable
+stack traces which are in turn necessary for :doc:`Kernel live patching
+<livepatch/livepatch>`.
+
+Caveat and Discussion
+---------------------
+As one might realize, there were only three macros previously. That is indeed
+insufficient to cover all the combinations of cases:
+
+* standard/non-standard function
+* code/data
+* global/local symbol
+
+There was a discussion_ and instead of extending the current ``ENTRY/END*``
+macros, it was decided that brand new macros should be introduced instead::
+
+    So how about using macro names that actually show the purpose, instead
+    of importing all the crappy, historic, essentially randomly chosen
+    debug symbol macro names from the binutils and older kernels?
+
+.. _discussion: https://lkml.kernel.org/r/20170217104757.28588-1-jslaby@suse.cz
+
+Macros Description
+------------------
+
+The new macros are prefixed with the ``SYM_`` prefix and can be divided into
+three main groups:
+
+1. ``SYM_FUNC_*`` -- to annotate C-like functions. This means functions with
+   standard C calling conventions, i.e. the stack contains a return address at
+   the predefined place and a return from the function can happen in a
+   standard way. When frame pointers are enabled, save/restore of frame
+   pointer shall happen at the start/end of a function, respectively, too.
+
+   Checking tools like ``objtool`` should ensure such marked functions conform
+   to these rules. The tools can also easily annotate these functions with
+   debugging information (like *ORC data*) automatically.
+
+2. ``SYM_CODE_*`` -- special functions called with special stack. Be it
+   interrupt handlers with special stack content, trampolines, or startup
+   functions.
+
+   Checking tools mostly ignore checking of these functions. But some debug
+   information still can be generated automatically. For correct debug data,
+   this code needs hints like ``UNWIND_HINT_REGS`` provided by developers.
+
+3. ``SYM_DATA*`` -- obviously data belonging to ``.data`` sections and not to
+   ``.text``. Data do not contain instructions, so they have to be treated
+   specially by the tools: they should not treat the bytes as instructions,
+   nor assign any debug information to them.
+
+Instruction Macros
+~~~~~~~~~~~~~~~~~~
+This section covers ``SYM_FUNC_*`` and ``SYM_CODE_*`` enumerated above.
+
+* ``SYM_FUNC_START`` and ``SYM_FUNC_START_LOCAL`` are supposed to be **the
+  most frequent markings**. They are used for functions with standard calling
+  conventions -- global and local. Like in C, they both align the functions to
+  architecture specific ``__ALIGN`` bytes. There are also ``_NOALIGN`` variants
+  for special cases where developers do not want this implicit alignment.
+
+  ``SYM_FUNC_START_WEAK`` and ``SYM_FUNC_START_WEAK_NOALIGN`` markings are
+  also offered as an assembler counterpart to the *weak* attribute known from
+  C.
+
+  All of these **shall** be coupled with ``SYM_FUNC_END``. First, it marks
+  the sequence of instructions as a function and computes its size to the
+  generated object file. Second, it also eases checking and processing such
+  object files as the tools can trivially find exact function boundaries.
+
+  So in most cases, developers should write something like in the following
+  example, having some asm instructions in between the macros, of course::
+
+    SYM_FUNC_START(function_hook)
+        ... asm insns ...
+    SYM_FUNC_END(function_hook)
+
+  In fact, this kind of annotation corresponds to the now deprecated ``ENTRY``
+  and ``ENDPROC`` macros.
+
+* ``SYM_FUNC_START_ALIAS`` and ``SYM_FUNC_START_LOCAL_ALIAS`` serve for those
+  who decided to have two or more names for one function. The typical use is::
+
+    SYM_FUNC_START_ALIAS(__memset)
+    SYM_FUNC_START(memset)
+        ... asm insns ...
+    SYM_FUNC_END(memset)
+    SYM_FUNC_END_ALIAS(__memset)
+
+  In this example, one can call ``__memset`` or ``memset`` with the same
+  result, except the debug information for the instructions is generated to
+  the object file only once -- for the non-``ALIAS`` case.
+
+* ``SYM_CODE_START`` and ``SYM_CODE_START_LOCAL`` should be used only in
+  special cases -- if you know what you are doing. This is used exclusively
+  for interrupt handlers and similar where the calling convention is not the C
+  one. ``_NOALIGN`` variants exist too. The use is the same as for the ``FUNC``
+  category above::
+
+    SYM_CODE_START_LOCAL(bad_put_user)
+        ... asm insns ...
+    SYM_CODE_END(bad_put_user)
+
+  Again, every ``SYM_CODE_START*`` **shall** be coupled by ``SYM_CODE_END``.
+
+  To some extent, this category corresponds to deprecated ``ENTRY`` and
+  ``END``. Except ``END`` had several other meanings too.
+
+* ``SYM_INNER_LABEL*`` is used to denote a label inside some
+  ``SYM_{CODE,FUNC}_START`` and ``SYM_{CODE,FUNC}_END``.  They are very similar
+  to C labels, except they can be made global. An example of use::
+
+    SYM_CODE_START(ftrace_caller)
+        /* save_mcount_regs fills in first two parameters */
+        ...
+
+    SYM_INNER_LABEL(ftrace_caller_op_ptr, SYM_L_GLOBAL)
+        /* Load the ftrace_ops into the 3rd parameter */
+        ...
+
+    SYM_INNER_LABEL(ftrace_call, SYM_L_GLOBAL)
+        call ftrace_stub
+        ...
+        retq
+    SYM_CODE_END(ftrace_caller)
+
+Data Macros
+~~~~~~~~~~~
+Similar to instructions, there is a couple of macros to describe data in the
+assembly.
+
+* ``SYM_DATA_START`` and ``SYM_DATA_START_LOCAL`` mark the start of some data
+  and shall be used in conjunction with either ``SYM_DATA_END``, or
+  ``SYM_DATA_END_LABEL``. The latter adds also a label to the end, so that
+  people can use ``lstack`` and (local) ``lstack_end`` in the following
+  example::
+
+    SYM_DATA_START_LOCAL(lstack)
+        .skip 4096
+    SYM_DATA_END_LABEL(lstack, SYM_L_LOCAL, lstack_end)
+
+* ``SYM_DATA`` and ``SYM_DATA_LOCAL`` are variants for simple, mostly one-line
+  data::
+
+    SYM_DATA(HEAP,     .long rm_heap)
+    SYM_DATA(heap_end, .long rm_stack)
+
+  In the end, they expand to ``SYM_DATA_START`` with ``SYM_DATA_END``
+  internally.
+
+Support Macros
+~~~~~~~~~~~~~~
+All the above reduce themselves to some invocation of ``SYM_START``,
+``SYM_END``, or ``SYM_ENTRY`` at last. Normally, developers should avoid using
+these.
+
+Further, in the above examples, one could see ``SYM_L_LOCAL``. There are also
+``SYM_L_GLOBAL`` and ``SYM_L_WEAK``. All are intended to denote linkage of a
+symbol marked by them. They are used either in ``_LABEL`` variants of the
+earlier macros, or in ``SYM_START``.
+
+
+Overriding Macros
+~~~~~~~~~~~~~~~~~
+Architecture can also override any of the macros in their own
+``asm/linkage.h``, including macros specifying the type of a symbol
+(``SYM_T_FUNC``, ``SYM_T_OBJECT``, and ``SYM_T_NONE``).  As every macro
+described in this file is surrounded by ``#ifdef`` + ``#endif``, it is enough
+to define the macros differently in the aforementioned architecture-dependent
+header.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/atomic_bitops.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/atomic_bitops.txt
@@ -59,7 +59,7 @@
  - RMW operations that have a return value are fully ordered.
 
  - RMW operations that are conditional are unordered on FAILURE,
-   otherwise the above rules apply. In the case of test_and_{}_bit() operations,
+   otherwise the above rules apply. In the case of test_and_set_bit_lock(),
    if the bit in memory is unchanged by the operation then it is deemed to have
    failed.
 
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/cgroups/namespace.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/cgroups/namespace.txt
@@ -0,0 +1,142 @@
+			CGroup Namespaces
+
+CGroup Namespace provides a mechanism to virtualize the view of the
+/proc/<pid>/cgroup file. The CLONE_NEWCGROUP clone-flag can be used with
+clone() and unshare() syscalls to create a new cgroup namespace.
+The process running inside the cgroup namespace will have its /proc/<pid>/cgroup
+output restricted to cgroupns-root. cgroupns-root is the cgroup of the process
+at the time of creation of the cgroup namespace.
+
+Prior to CGroup Namespace, the /proc/<pid>/cgroup file used to show complete
+path of the cgroup of a process. In a container setup (where a set of cgroups
+and namespaces are intended to isolate processes), the /proc/<pid>/cgroup file
+may leak potential system level information to the isolated processes.
+
+For Example:
+  $ cat /proc/self/cgroup
+  0:cpuset,cpu,cpuacct,memory,devices,freezer,hugetlb:/batchjobs/container_id1
+
+The path '/batchjobs/container_id1' can generally be considered as system-data
+and its desirable to not expose it to the isolated process.
+
+CGroup Namespaces can be used to restrict visibility of this path.
+For Example:
+  # Before creating cgroup namespace
+  $ ls -l /proc/self/ns/cgroup
+  lrwxrwxrwx 1 root root 0 2014-07-15 10:37 /proc/self/ns/cgroup -> cgroup:[4026531835]
+  $ cat /proc/self/cgroup
+  0:cpuset,cpu,cpuacct,memory,devices,freezer,hugetlb:/batchjobs/container_id1
+
+  # unshare(CLONE_NEWCGROUP) and exec /bin/bash
+  $ ~/unshare -c
+  [ns]$ ls -l /proc/self/ns/cgroup
+  lrwxrwxrwx 1 root root 0 2014-07-15 10:35 /proc/self/ns/cgroup -> cgroup:[4026532183]
+  # From within new cgroupns, process sees that its in the root cgroup
+  [ns]$ cat /proc/self/cgroup
+  0:cpuset,cpu,cpuacct,memory,devices,freezer,hugetlb:/
+
+  # From global cgroupns:
+  $ cat /proc/<pid>/cgroup
+  0:cpuset,cpu,cpuacct,memory,devices,freezer,hugetlb:/batchjobs/container_id1
+
+  # Unshare cgroupns along with userns and mountns
+  # Following calls unshare(CLONE_NEWCGROUP|CLONE_NEWUSER|CLONE_NEWNS), then
+  # sets up uid/gid map and execs /bin/bash
+  $ ~/unshare -c -u -m
+  # Originally, we were in /batchjobs/container_id1 cgroup. Mount our own cgroup
+  # hierarchy.
+  [ns]$ mount -t cgroup cgroup /tmp/cgroup
+  [ns]$ ls -l /tmp/cgroup
+  total 0
+  -r--r--r-- 1 root root 0 2014-10-13 09:32 cgroup.controllers
+  -r--r--r-- 1 root root 0 2014-10-13 09:32 cgroup.populated
+  -rw-r--r-- 1 root root 0 2014-10-13 09:25 cgroup.procs
+  -rw-r--r-- 1 root root 0 2014-10-13 09:32 cgroup.subtree_control
+
+The cgroupns-root (/batchjobs/container_id1 in above example) becomes the
+filesystem root for the namespace specific cgroupfs mount.
+
+The virtualization of /proc/self/cgroup file combined with restricting
+the view of cgroup hierarchy by namespace-private cgroupfs mount
+should provide a completely isolated cgroup view inside the container.
+
+In its current form, the cgroup namespaces patcheset provides following
+behavior:
+
+(1) The 'cgroupns-root' for a cgroup namespace is the cgroup in which
+    the process calling unshare is running.
+    For ex. if a process in /batchjobs/container_id1 cgroup calls unshare,
+    cgroup /batchjobs/container_id1 becomes the cgroupns-root.
+    For the init_cgroup_ns, this is the real root ('/') cgroup
+    (identified in code as cgrp_dfl_root.cgrp).
+
+(2) The cgroupns-root cgroup does not change even if the namespace
+    creator process later moves to a different cgroup.
+    $ ~/unshare -c # unshare cgroupns in some cgroup
+    [ns]$ cat /proc/self/cgroup
+    0:cpuset,cpu,cpuacct,memory,devices,freezer,hugetlb:/
+    [ns]$ mkdir sub_cgrp_1
+    [ns]$ echo 0 > sub_cgrp_1/cgroup.procs
+    [ns]$ cat /proc/self/cgroup
+    0:cpuset,cpu,cpuacct,memory,devices,freezer,hugetlb:/sub_cgrp_1
+
+(3) Each process gets its CGROUPNS specific view of /proc/<pid>/cgroup
+(a) Processes running inside the cgroup namespace will be able to see
+    cgroup paths (in /proc/self/cgroup) only inside their root cgroup
+    [ns]$ sleep 100000 &  # From within unshared cgroupns
+    [1] 7353
+    [ns]$ echo 7353 > sub_cgrp_1/cgroup.procs
+    [ns]$ cat /proc/7353/cgroup
+    0:cpuset,cpu,cpuacct,memory,devices,freezer,hugetlb:/sub_cgrp_1
+
+(b) From global cgroupns, the real cgroup path will be visible:
+    $ cat /proc/7353/cgroup
+    0:cpuset,cpu,cpuacct,memory,devices,freezer,hugetlb:/batchjobs/container_id1/sub_cgrp_1
+
+(c) From a sibling cgroupns (cgroupns root-ed at a different cgroup), cgroup
+    path relative to its own cgroupns-root will be shown:
+    # ns2's cgroupns-root is at '/batchjobs/container_id2'
+    [ns2]$ cat /proc/7353/cgroup
+    0:cpuset,cpu,cpuacct,memory,devices,freezer,hugetlb:/../container_id2/sub_cgrp_1
+
+    Note that the relative path always starts with '/' to indicate that its
+    relative to the cgroupns-root of the caller.
+
+(4) Processes inside a cgroupns can move in-and-out of the cgroupns-root
+    (if they have proper access to external cgroups).
+    # From inside cgroupns (with cgroupns-root at /batchjobs/container_id1), and
+    # assuming that the global hierarchy is still accessible inside cgroupns:
+    $ cat /proc/7353/cgroup
+    0:cpuset,cpu,cpuacct,memory,devices,freezer,hugetlb:/sub_cgrp_1
+    $ echo 7353 > batchjobs/container_id2/cgroup.procs
+    $ cat /proc/7353/cgroup
+    0:cpuset,cpu,cpuacct,memory,devices,freezer,hugetlb:/../container_id2
+
+    Note that this kind of setup is not encouraged. A task inside cgroupns
+    should only be exposed to its own cgroupns hierarchy. Otherwise it makes
+    the virtualization of /proc/<pid>/cgroup less useful.
+
+(5) Setns to another cgroup namespace is allowed when:
+    (a) the process has CAP_SYS_ADMIN in its current userns
+    (b) the process has CAP_SYS_ADMIN in the target cgroupns' userns
+    No implicit cgroup changes happen with attaching to another cgroupns. It
+    is expected that the somone moves the attaching process under the target
+    cgroupns-root.
+
+(6) When some thread from a multi-threaded process unshares its
+    cgroup-namespace, the new cgroupns gets applied to the entire process (all
+    the threads). For the unified-hierarchy this is expected as it only allows
+    process-level containerization.  For the legacy hierarchies this may be
+    unexpected.  So all the threads in the process will have the same cgroup.
+
+(7) The cgroup namespace is alive as long as there is atleast 1
+    process inside it. When the last process exits, the cgroup
+    namespace is destroyed. The cgroupns-root and the actual cgroups
+    remain though.
+
+(8) Namespace specific cgroup hierarchy can be mounted by a process running
+    inside cgroupns:
+    $ mount -t cgroup -o __DEVEL__sane_behavior cgroup $MOUNT_POINT
+
+    This will mount the unified cgroup hierarchy with cgroupns-root as the
+    filesystem root. The process needs CAP_SYS_ADMIN in its userns and mntns.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/conf.py
+++ linux-xilinx-zynqmp-5.4.0/Documentation/conf.py
@@ -98,7 +98,7 @@
 #
 # This is also used if you do content translation via gettext catalogs.
 # Usually you set "language" from the command line for these cases.
-language = None
+language = 'en'
 
 # There are two options for replacing |today|: either, you set today to some
 # non-false value, then it is used:
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/core-api/local_ops.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/core-api/local_ops.rst
@@ -191,7 +191,7 @@
 
     static void __exit test_exit(void)
     {
-            del_timer_sync(&test_timer);
+            timer_shutdown_sync(&test_timer);
     }
 
     module_init(test_init);
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/core-api/printk-formats.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/core-api/printk-formats.rst
@@ -508,6 +508,12 @@
 Thanks
 ======
 
+Kernel messages:
+
+       %pj	123456
+
+       For generating the jhash of a string truncated to six digits
+
 If you add other %p extensions, please extend <lib/test_printf.c> with
 one or more test cases, if at all feasible.
 
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/core-api/xarray.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/core-api/xarray.rst
@@ -461,13 +461,15 @@
 Each entry will only be returned once, no matter how many indices it
 occupies.
 
-Using xas_next() or xas_prev() with a multi-index xa_state
-is not supported.  Using either of these functions on a multi-index entry
-will reveal sibling entries; these should be skipped over by the caller.
+Using xas_next() or xas_prev() with a multi-index xa_state is not
+supported.  Using either of these functions on a multi-index entry will
+reveal sibling entries; these should be skipped over by the caller.
 
-Storing ``NULL`` into any index of a multi-index entry will set the entry
-at every index to ``NULL`` and dissolve the tie.  Splitting a multi-index
-entry into entries occupying smaller ranges is not yet supported.
+Storing ``NULL`` into any index of a multi-index entry will set the
+entry at every index to ``NULL`` and dissolve the tie.  A multi-index
+entry can be split into entries occupying smaller ranges by calling
+xas_split_alloc() without the xa_lock held, followed by taking the lock
+and calling xas_split().
 
 Functions and structures
 ========================
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/dev-tools/gdb-kernel-debugging.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/dev-tools/gdb-kernel-debugging.rst
@@ -39,6 +39,10 @@
   this mode. In this case, you should build the kernel with
   CONFIG_RANDOMIZE_BASE disabled if the architecture supports KASLR.
 
+- Build the gdb scripts (required on kernels v5.1 and above)::
+
+    make scripts_gdb
+
 - Enable the gdb stub of QEMU/KVM, either
 
     - at VM startup time by appending "-s" to the QEMU command line
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/Makefile
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/Makefile
@@ -12,7 +12,6 @@
 	$(call if_changed,chk_binding)
 
 DT_TMP_SCHEMA := processed-schema.yaml
-extra-y += $(DT_TMP_SCHEMA)
 
 quiet_cmd_mk_schema = SCHEMA  $@
       cmd_mk_schema = $(DT_MK_SCHEMA) $(DT_MK_SCHEMA_FLAGS) -o $@ $(real-prereqs)
@@ -26,8 +25,12 @@
 
 DT_SCHEMA_FILES ?= $(addprefix $(src)/,$(DT_DOCS))
 
+ifeq ($(CHECK_DTBS),)
 extra-y += $(patsubst $(src)/%.yaml,%.example.dts, $(DT_SCHEMA_FILES))
 extra-y += $(patsubst $(src)/%.yaml,%.example.dt.yaml, $(DT_SCHEMA_FILES))
+endif
 
 $(obj)/$(DT_TMP_SCHEMA): $(DT_SCHEMA_FILES) FORCE
 	$(call if_changed,mk_schema)
+
+extra-y += $(DT_TMP_SCHEMA)
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/arm/qcom.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/arm/qcom.yaml
@@ -112,8 +112,8 @@
           - const: qcom,msm8974
 
       - items:
-          - const: qcom,msm8916-mtp/1
           - const: qcom,msm8916-mtp
+          - const: qcom,msm8916-mtp/1
           - const: qcom,msm8916
 
       - items:
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/arm/tegra.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/arm/tegra.yaml
@@ -49,7 +49,7 @@
           - const: toradex,apalis_t30
           - const: nvidia,tegra30
       - items:
-          - const: toradex,apalis_t30-eval-v1.1
+          - const: toradex,apalis_t30-v1.1-eval
           - const: toradex,apalis_t30-eval
           - const: toradex,apalis_t30-v1.1
           - const: toradex,apalis_t30
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/arm/xilinx.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/arm/xilinx.yaml
@@ -58,12 +58,6 @@
           - const: xlnx,zynqmp-zc1254
           - const: xlnx,zynqmp
 
-      - description: Xilinx internal board zc1275
-        items:
-          - const: xlnx,zynqmp-zc1275-revA
-          - const: xlnx,zynqmp-zc1275
-          - const: xlnx,zynqmp
-
       - description: Xilinx 96boards compatible board zcu100
         items:
           - const: xlnx,zynqmp-zcu100-revC
@@ -91,6 +85,7 @@
         items:
           - enum:
               - xlnx,zynqmp-zcu104-revA
+              - xlnx,zynqmp-zcu104-revC
               - xlnx,zynqmp-zcu104-rev1.0
           - const: xlnx,zynqmp-zcu104
           - const: xlnx,zynqmp
@@ -107,8 +102,41 @@
         items:
           - enum:
               - xlnx,zynqmp-zcu111-revA
-              - xlnx,zynqmp-zcu11-rev1.0
+              - xlnx,zynqmp-zcu111-rev1.0
           - const: xlnx,zynqmp-zcu111
           - const: xlnx,zynqmp
 
+      - description: Xilinx evaluation board zcu208
+        items:
+          - enum:
+              - xlnx,zynqmp-zcu208-revA
+              - xlnx,zynqmp-zcu208-rev1.0
+          - const: xlnx,zynqmp-zcu208
+          - const: xlnx,zynqmp
+
+      - description: Xilinx evaluation board zcu216
+        items:
+          - enum:
+              - xlnx,zynqmp-zcu216-revA
+              - xlnx,zynqmp-zcu216-rev1.0
+          - const: xlnx,zynqmp-zcu216
+          - const: xlnx,zynqmp
+
+      - description: Xilinx evaluation board zcu1275
+        items:
+          - enum:
+              - xlnx,zynqmp-zcu1275-revA
+              - xlnx,zynqmp-zcu1275-revB
+              - xlnx,zynqmp-zcu1275-rev1.0
+          - const: xlnx,zynqmp-zcu1275
+          - const: xlnx,zynqmp
+
+      - description: Xilinx evaluation board zcu1285
+        items:
+          - enum:
+              - xlnx,zynqmp-zcu1285-revA
+              - xlnx,zynqmp-zcu1285-rev1.0
+          - const: xlnx,zynqmp-zcu1285
+          - const: xlnx,zynqmp
+
 ...
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/arm/zynq/zynq-efuse.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/arm/zynq/zynq-efuse.txt
@@ -0,0 +1,15 @@
+Device tree bindings for Zynq's eFuse Controller
+
+The Zynq eFuse controller provides the access to the chip efuses which contain
+information about device DNA, security settings and also device status.
+
+Required properties:
+ compatible: Compatibility string. Must be "xlnx,zynq-efuse".
+ reg: Specify the base and size of the EFUSE controller registers
+      in the memory map. E.g.: reg = <0xf800d000 0x20>;
+
+Example:
+efuse: efuse@f800d000 {
+	compatible = "xlnx,zynq-efuse";
+	reg = <0xf800d000 0x20>;
+};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/arm/zynq/zynq-ocmc.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/arm/zynq/zynq-ocmc.txt
@@ -0,0 +1,17 @@
+Device tree bindings for Zynq's OCM Controller
+
+The OCM is divided to 4 64kB segments which can be separately configured
+to low or high location. Location is controlled via SLCR.
+
+Required properties:
+ compatible: Compatibility string. Must be "xlnx,zynq-ocmc-1.0".
+ reg: Specify the base and size of the OCM controller registers
+      in the memory map. E.g.: reg = <0xf800c000 0x1000>;
+
+Example:
+ocmc: ocmc@f800c000 {
+	compatible = "xlnx,zynq-ocmc-1.0";
+	interrupt-parent = <&intc>;
+	interrupts = <0 3 4>;
+	reg = <0xf800c000 0x1000>;
+} ;
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/ata/ahci-ceva.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/ata/ahci-ceva.txt
@@ -38,6 +38,8 @@
 
 Optional properties:
   - ceva,broken-gen2: limit to gen1 speed instead of gen2.
+  - dma-coherent:     Enable this flag if CCI is enabled in design.
+		      Adding this flag configures AXI cache control register.
 
 Examples:
 	ahci@fd0c0000 {
@@ -56,4 +58,5 @@
 		ceva,p1-burst-params = /bits/ 8 <0x0A 0x08 0x4A 0x06>;
 		ceva,p1-retry-params = /bits/ 16 <0x0216 0x7F06>;
 		ceva,broken-gen2;
+		dma-coherent;
 	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/bus/allwinner,sun8i-a23-rsb.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/bus/allwinner,sun8i-a23-rsb.yaml
@@ -70,7 +70,6 @@
         #size-cells = <0>;
 
         pmic@3e3 {
-            compatible = "...";
             reg = <0x3e3>;
 
             /* ... */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/clock/adi,axi-clkgen.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/clock/adi,axi-clkgen.yaml
@@ -0,0 +1,67 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/adi,axi-clkgen.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Binding for Analog Devices AXI clkgen pcore clock generator
+
+maintainers:
+  - Lars-Peter Clausen <lars@metafoo.de>
+  - Michael Hennerich <michael.hennerich@analog.com>
+
+description: |
+  The axi_clkgen IP core is a software programmable clock generator,
+  that can be synthesized on various FPGA platforms.
+
+  Link: https://wiki.analog.com/resources/fpga/docs/axi_clkgen
+
+properties:
+  compatible:
+    enum:
+      - adi,axi-clkgen-2.00.a
+
+  clocks:
+    description:
+      Specifies the reference clock(s) from which the output frequency is
+      derived. This must either reference one clock if only the first clock
+      input is connected or two if both clock inputs are connected. The last
+      clock is the AXI bus clock that needs to be enabled so we can access the
+      core registers.
+    minItems: 2
+    maxItems: 3
+
+  clock-names:
+    oneOf:
+      - items:
+          - const: clkin1
+          - const: s_axi_aclk
+      - items:
+          - const: clkin1
+          - const: clkin2
+          - const: s_axi_aclk
+
+  '#clock-cells':
+    const: 0
+
+  reg:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - '#clock-cells'
+
+additionalProperties: false
+
+examples:
+  - |
+    clock-controller@ff000000 {
+      compatible = "adi,axi-clkgen-2.00.a";
+      #clock-cells = <0>;
+      reg = <0xff000000 0x1000>;
+      clocks = <&osc 1>, <&clkc 15>;
+      clock-names = "clkin1", "s_axi_aclk";
+    };
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/clock/idt,idt8t49n24x.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/clock/idt,idt8t49n24x.txt
@@ -0,0 +1,156 @@
+Binding for IDT 8T49N24x Universal Frequency Translator
+
+The 8T49N241 has one fractional-feedback PLL that can be used as a
+jitter attenuator and frequency translator. It is equipped with one
+integer and three fractional output dividers, allowing the generation
+of up to four different output frequencies, ranging from 8kHz to 1GHz.
+These frequencies are completely independent of each other, the input
+reference frequencies and the crystal reference frequency. The device
+places virtually no constraints on input to output frequency conversion,
+supporting all FEC rates, including the new revision of ITU-T
+Recommendation G.709 (2009), most with 0ppm conversion error.
+The outputs may select among LVPECL, LVDS, HCSL or LVCMOS output levels.
+
+The driver can read a full register map from the DT, and will use that
+register map to initialize the attached part (via I2C) when the system
+boots. Any configuration not supported by the common clock framework
+must be done via the full register map, including optimized settings.
+
+The 8T49N241 accepts up to two differential or single-ended input clocks
+and a fundamental-mode crystal input. The internal PLL can lock to either
+of the input reference clocks or just to the crystal to behave as a
+frequency synthesizer. The PLL can use the second input for redundant
+backup of the primary input reference, but in this case, both input clock
+references must be related in frequency.
+
+All outputs are currently assumed to be LVDS, unless overridden in the
+full register map in the DT.
+
+==I2C device node==
+
+Required properties:
+- compatible:	shall be one of "idt,idt8t49n241"
+- reg:		i2c device address, shall be one of 0x7C, 0x6C, 0x7D, 0x6D,
+		0x7E, 0x6E, 0x7F, 0x6F.
+- #clock-cells: From common clock bindings: Shall be 1.
+
+- clocks:	from common clock binding; input clock handle. Required.
+- clock-names:	from common clock binding; clock input names, shall be
+		one of "input-clk0", "input-clk1", "input-xtal". Required.
+
+==Mapping between clock specifier and physical pins==
+
+When referencing the provided clock in the DT using phandle and
+clock specifier, the following mapping applies:
+
+8T49N241:
+	0 -- Q0
+	1 -- Q1
+	2 -- Q2
+	3 -- Q3
+
+==Example==
+
+/* Example1: 25MHz input clock (via CLK0) */
+
+ref25: ref25m {
+	compatible = "fixed-clock";
+	#clock-cells = <0>;
+	clock-frequency = <25000000>;
+};
+
+i2c-master-node {
+
+	/* IDT 8T49N241 i2c universal frequency translator */
+	i2c241: clock-generator@6a {
+		compatible = "idt,idt8t49n241";
+		reg = <0x6c>;
+		#clock-cells = <1>;
+
+		/* Connect input-clk0 to 25MHz reference */
+		clocks = <&ref25m>;
+		clock-names = "input-clk0";
+	};
+};
+
+/* Consumer referencing the 8T49N241 pin Q1 */
+consumer {
+	...
+	clocks = <&i2c241 1>;
+	...
+}
+
+/* Example2: 40MHz xtal frequency, specify all settings */
+
+ref40: ref40m {
+	compatible = "fixed-clock";
+	#clock-cells = <0>;
+	clock-frequency = <40000000>;
+};
+
+i2c-master-node {
+
+	/* IDT 8T49N241 i2c universal frequency translator */
+	i2c241: clock-generator@6a {
+		compatible = "idt,idt8t49n241";
+		reg = <0x6c>;
+		#clock-cells = <1>;
+
+		/* Connect input-xtal to 40MHz reference */
+		clocks = <&ref40m>;
+		clock-names = "input-xtal";
+
+		settings=[
+09 50 00 60 67 C5 6C FF 03 00 30 00 00 01 00 00
+01 07 00 00 07 00 00 77 6D 06 00 00 00 00 00 FF
+FF FF FF 00 3F 00 2A 00 16 33 33 00 01 00 00 D0
+00 00 00 00 00 00 00 00 00 04 00 00 00 02 00 00
+00 00 00 00 00 00 00 17 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 D7 0A 2B 20 00 00 00 0B
+00 00 00 00 00 00 00 00 00 00 27 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+C3 00 08 01 00 00 00 00 00 00 00 00 00 30 00 00
+00 0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+00 00 00 00 85 00 00 9C 01 D4 02 71 07 00 00 00
+00 83 00 10 02 08 8C
+];
+	};
+};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.txt
@@ -46,7 +46,7 @@
 Example (R-Car H3):
 
 	usb2_clksel: clock-controller@e6590630 {
-		compatible = "renesas,r8a77950-rcar-usb2-clock-sel",
+		compatible = "renesas,r8a7795-rcar-usb2-clock-sel",
 			     "renesas,rcar-gen3-usb2-clock-sel";
 		reg = <0 0xe6590630 0 0x02>;
 		clocks = <&cpg CPG_MOD 703>, <&usb_extal>, <&usb_xtal>;
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/clock/silabs,si5324.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/clock/silabs,si5324.txt
@@ -0,0 +1,78 @@
+Binding for Silicon Labs si5324, si5328 and si5319 programmable
+I2C clock generator.
+
+Reference
+This binding uses the common clock binding[1].
+The si5324 is programmable i2c low-bandwidth, jitter-attenuating, precision
+clock multiplier with up to 2 output clocks. The internal structure can be
+found in [2].
+The internal pin structure of si5328 and si5319 can be found in [3].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] Si5324 Data Sheet
+	http://www.silabs.com/Support%20Documents/TechnicalDocs/Si5324.pdf
+[3] Si53xx Reference Manual
+	http://www.silabs.com/Support%20Documents/TechnicalDocs/
+	Si53xxReferenceManual.pdf
+
+==I2C device node==
+
+Required properties:
+- compatible: should be one of
+	"silabs,si5324"
+	"silabs,si5319"
+	"silabs,si5328"
+- reg: i2c device address.
+- #clock-cells: from common clock binding; shall be set to 1.
+- clocks: from common clock binding; list of parent clock
+  handles, clock name should be one of
+	"xtal"
+	"clkin1"
+	"clkin2"
+- #address-cells: shall be set to 1.
+- #size-cells: shall be set to 0.
+
+Optional properties:
+- silabs,pll-source: pair of (number, source) for each pll. Allows
+  to overwrite clock source of pll.
+
+==Child nodes==
+
+Each of the clock outputs can be overwritten individually by
+using a child node to the I2C device node. If a child node for a clock
+output is not set, the eeprom configuration is not overwritten.
+
+Required child node properties:
+- reg: number of clock output.
+- clock-frequency: default output frequency at power on
+
+Optional child node properties:
+- silabs,drive-strength: output drive strength in mA, shall be one of {2,4,6,8}.
+
+Example:
+Following example describes the ZCU102 board with hdmi design which
+uses si5319 as clock generator. XTAL is hard-wired on the board to act
+as input clock with a frequency of 114.285MHz.
+
+refhdmi: refhdmi {
+	compatible = "fixed-clock";
+	#clock-cells = <0>;
+	clock-frequency = <114285000>;
+};
+
+/* Si5319 i2c clock generator */
+si5319: clock-generator@68 {
+	status = "okay";
+	compatible = "silabs,si5319";
+	reg = <0x68>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+	#clock-cells = <1>;
+	clocks = <&refhdmi>;
+	clock-names = "xtal";
+
+	clk0 {
+		reg = <0>;
+		clock-frequency = <27000000>;
+	};
+};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/clock/xlnx,clocking-wizard.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/clock/xlnx,clocking-wizard.txt
@@ -0,0 +1,32 @@
+Binding for Xilinx Clocking Wizard IP Core
+
+This binding uses the common clock binding[1]. Details about the devices can be
+found in the product guide[2].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+[2] Clocking Wizard Product Guide
+http://www.xilinx.com/support/documentation/ip_documentation/clk_wiz/v5_1/pg065-clk-wiz.pdf
+
+Required properties:
+ - compatible: Must be 'xlnx,clocking-wizard'
+ - #clock-cells: Number of cells in a clock specifier. Should be 1
+ - reg: Base and size of the cores register space
+ - clocks: Handle to input clock
+ - clock-names: Tuple containing 'clk_in1' and 's_axi_aclk'
+ - clock-output-names: Names for the output clocks
+
+Optional properties:
+ - speed-grade: Speed grade of the device (valid values are 1..3)
+
+Example:
+	clock-generator@40040000 {
+		#clock-cells = <1>;
+		reg = <0x40040000 0x1000>;
+		compatible = "xlnx,clocking-wizard";
+		speed-grade = <1>;
+		clock-names = "clk_in1", "s_axi_aclk";
+		clocks = <&clkc 15>, <&clkc 15>;
+		clock-output-names = "clk_out0", "clk_out1", "clk_out2",
+				     "clk_out3", "clk_out4", "clk_out5",
+				     "clk_out6", "clk_out7";
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/clock/xlnx,versal-clk.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/clock/xlnx,versal-clk.yaml
@@ -0,0 +1,64 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/xlnx,versal-clk.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Xilinx Versal clock controller
+
+maintainers:
+  - Michal Simek <michal.simek@xilinx.com>
+  - Jolly Shah <jolly.shah@xilinx.com>
+  - Rajan Vaja <rajan.vaja@xilinx.com>
+
+description: |
+  The clock controller is a hardware block of Xilinx versal clock tree. It
+  reads required input clock frequencies from the devicetree and acts as clock
+  provider for all clock consumers of PS clocks.
+
+select: false
+
+properties:
+  compatible:
+    const: xlnx,versal-clk
+
+  "#clock-cells":
+    const: 1
+
+  clocks:
+    description: List of clock specifiers which are external input
+      clocks to the given clock controller.
+    items:
+      - description: reference clock
+      - description: alternate reference clock
+      - description: alternate reference clock for programmable logic
+
+  clock-names:
+    items:
+      - const: ref
+      - const: alt_ref
+      - const: pl_alt_ref
+
+required:
+  - compatible
+  - "#clock-cells"
+  - clocks
+  - clock-names
+
+additionalProperties: false
+
+examples:
+  - |
+    firmware {
+      zynqmp_firmware: zynqmp-firmware {
+        compatible = "xlnx,zynqmp-firmware";
+        method = "smc";
+        versal_clk: clock-controller {
+          #clock-cells = <1>;
+          compatible = "xlnx,versal-clk";
+          clocks = <&ref>, <&alt_ref>, <&pl_alt_ref>;
+          clock-names = "ref", "alt_ref", "pl_alt_ref";
+        };
+      };
+    };
+...
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/clock/xlnx,versal-wiz.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/clock/xlnx,versal-wiz.yaml
@@ -0,0 +1,58 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/xlnx,versal-wiz.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Xilinx Versal clocking wizard
+
+maintainers:
+  - Shubhrajyoti Datta <shubhrajyoti.datta@xilinx.com>
+
+description: |
+  The clocking wizard is a soft ip clocking block of Xilinx versal. It
+  reads required input clock frequencies from the devicetree and acts as clock
+  clock output.
+
+select: false
+
+properties:
+  compatible:
+    const: xlnx,clk-wizard-1.0
+
+  "#clock-cells":
+    const: 1
+
+  clocks:
+    description: List of clock specifiers which are external input
+      clocks to the given clock controller.
+    items:
+      - description: clock input
+      - description: axi clock
+
+  clock-names:
+    items:
+      - const: clk_in1
+      - const: s_axi_aclk
+
+required:
+  - compatible
+  - "#clock-cells"
+  - clocks
+  - clock-names
+
+additionalProperties: false
+
+examples:
+  - |
+    clock-generator@40040000 {
+        #clock-cells = <1>;
+        reg = <0x40040000 0x1000>;
+        compatible = "xlnx,clk-wizard-1.0";
+        speed-grade = <1>;
+        clock-names = "clk_in1", "s_axi_aclk";
+        clocks = <&clkc 15>, <&clkc 15>;clock-output-names = "clk_out1", "clk_out2",
+        "clk_out3", "clk_out4", "clk_out5",
+        "clk_out6", "clk_out7";
+    };
+...
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/crypto/xlnx,zynqmp-aes.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/crypto/xlnx,zynqmp-aes.txt
@@ -0,0 +1,12 @@
+Xilinx ZynqMP AES hw acceleration support
+
+The ZynqMP PS-AES hw accelerator is used to encrypt/decrypt
+the given user data.
+
+Required properties:
+- compatible: should contain "xlnx,zynqmp-aes"
+
+Example:
+	zynqmp_aes {
+		compatible = "xlnx,zynqmp-aes";
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/crypto/zynqmp-rsa.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/crypto/zynqmp-rsa.txt
@@ -0,0 +1,12 @@
+Xilinx ZynqMP RSA hw acceleration support
+
+The zynqmp PS-RSA hw accelerator is used to encrypt/decrypt
+the given user data.
+
+Required properties:
+- compatible:	should contain "xlnx,zynqmp-rsa"
+
+Example:
+	xlnx_rsa: zynqmp_rsa {
+		compatible = "xlnx,zynqmp-rsa";
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/crypto/zynqmp-sha.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/crypto/zynqmp-sha.txt
@@ -0,0 +1,12 @@
+Xilinx ZynqMP SHA3(keccak-384) hw acceleration support.
+
+The ZynqMp PS-SHA hw accelerator is used to calculate the
+SHA3(keccak-384) hash value on the given user data.
+
+Required properties:
+- compatible:	should contain "xlnx,zynqmp-keccak-384"
+
+Example:
+	xlnx_keccak_384: sha384 {
+		compatible = "xlnx,zynqmp-keccak-384";
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/display/amlogic,meson-dw-hdmi.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/display/amlogic,meson-dw-hdmi.yaml
@@ -10,6 +10,9 @@
 maintainers:
   - Neil Armstrong <narmstrong@baylibre.com>
 
+allOf:
+  - $ref: /schemas/sound/name-prefix.yaml#
+
 description: |
   The Amlogic Meson Synopsys Designware Integration is composed of
   - A Synopsys DesignWare HDMI Controller IP
@@ -101,6 +104,8 @@
   "#sound-dai-cells":
     const: 0
 
+  sound-name-prefix: true
+
 required:
   - compatible
   - reg
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/display/amlogic,meson-vpu.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/display/amlogic,meson-vpu.yaml
@@ -78,6 +78,10 @@
   interrupts:
     maxItems: 1
 
+  amlogic,canvas:
+    description: should point to a canvas provider node
+    $ref: /schemas/types.yaml#/definitions/phandle
+
   power-domains:
     maxItems: 1
     description: phandle to the associated power domain
@@ -106,6 +110,7 @@
   - port@1
   - "#address-cells"
   - "#size-cells"
+  - amlogic,canvas
 
 examples:
   - |
@@ -116,6 +121,7 @@
         interrupts = <3>;
         #address-cells = <1>;
         #size-cells = <0>;
+        amlogic,canvas = <&canvas>;
 
         /* CVBS VDAC output port */
         port@0 {
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.txt
@@ -16,6 +16,9 @@
   Documentation/devicetree/bindings/graph.txt. This port should be connected
   to the input port of an attached HDMI or LVDS encoder chip.
 
+Optional properties:
+- pinctrl-names: Contain "default" and "sleep".
+
 Example:
 
 dpi0: dpi@1401d000 {
@@ -26,6 +29,9 @@
 		 <&mmsys CLK_MM_DPI_ENGINE>,
 		 <&apmixedsys CLK_APMIXED_TVDPLL>;
 	clock-names = "pixel", "engine", "pll";
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&dpi_pin_func>;
+	pinctrl-1 = <&dpi_pin_idle>;
 
 	port {
 		dpi0_out: endpoint {
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/display/xlnx/bridge.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/display/xlnx/bridge.txt
@@ -0,0 +1,29 @@
+Xilinx DRM bridge
+-----------------
+
+The Xilinx DRM provides the interface layer called Xilinx bridge to bridge
+multiple components with a series of functions. It models a simple
+unidirectional communication, single client -> single bridge. The client
+is not limited to DRM compatible drivers, but can be any subsystem driver,
+but the client driver should call the bridge functions explicitly.
+
+Provider
+--------
+
+The bridge provider should assign a corresponding of_node to struct xlnx_bridge.
+For example, if its own node is used,
+
+	provider_node: provider_node {
+	};
+
+	bridge.of_node = provider_device->of_node;
+
+Client
+------
+
+The bridge client should have a phandle to the bridge device node. The bridge
+device node should be passed to get a bridge instance,
+
+       client_node {
+	       xlnx,bridge = <&provider_node>;
+       };
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/display/xlnx/xlnx,dp-tx.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/display/xlnx/xlnx,dp-tx.yaml
@@ -0,0 +1,169 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/xlnx/xlnx,dp-tx.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Xilinx DisplayPort Transmitter Subsystem
+
+maintainers:
+  - Rajesh Gugulothu <gugulothu.rajesh@xilinx.com>
+
+description: |
+  The Xilinx DisplayPort Tx Subsystem contains several subcores to implement
+  a DisplayPort Transmitter and outputs video data using DisplayPort protocol.
+  For more details, please refer to PG199 at https://www.xilinx.com/support/documentation/ip_documentation/dp_tx_subsystem/v2_1/pg199-displayport-tx-subsystem.pdf
+
+properties:
+  compatible:
+    items:
+      - enum:
+          - xlnx,v-dp-txss-3.0
+
+  reg:
+    maxItems: 1
+    description: DisplayPort Transmitter Subsystem registers
+
+  reg-names:
+    items:
+      - const: dp_base
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    description: List of clock specifiers
+    items:
+      - description: AXI Lite clock
+      - description: Video clock
+
+  clock-names:
+    items:
+      - const: s_axi_aclk
+      - const: tx_vid_clk
+
+  phys:
+    description: This denotes phandles for phy lanes registered
+                 for DP protocol.DisplayPort always require 4 lanes
+
+  phy-names:
+    items:
+      - const: dp-phy0
+      - const: dp-phy1
+      - const: dp-phy2
+      - const: dp-phy3
+
+  xlnx,max-lanes:
+    description: Max number of lanes that IP configured with.
+                 Possible values are 1, 2, 4.
+    allOf:
+      - $ref: /schemas/types.yaml#/definitions/uint32
+      - enum: [1, 2, 4]
+
+  xlnx,max-link-rate:
+    description: |
+      Max link rate that IP configured with.Possible values are as below -
+      162000 - 1.6 Gb/s
+      270000 - 2.7 Gb/s
+      540000 - 5.4 Gb/s
+      810000 - 8.1 Gb/s
+    allOf:
+      - $ref: /schemas/types.yaml#/definitions/uint32
+      - enum: [162000, 270000, 540000, 810000]
+
+  xlnx,bpc:
+    description: |
+      Max BPC value that IP configured with. For example if IP is configured
+      with 10 BPC means it supports (6, 8, 10) up to 10bpc.
+      Possible values are 6, 8, 10, 12, 16.
+    allOf:
+      - $ref: /schemas/types.yaml#/definitions/uint32
+      - enum: [6, 8, 10, 12, 16]
+
+  xlnx,audio-channels:
+    description: |
+      This denotes number of audio channels enabled in the IP
+      configuration. Possible values are 2, 3, 4, 5, 6, 7, 8.
+    allOf:
+      - $ref: /schemas/types.yaml#/definitions/uint32
+      - enum: [2, 3, 4, 5, 6, 7, 8]
+
+  ports:
+    type: object
+
+    properties:
+      port@0:
+        type: object
+        description: |
+          Output / source port node, endpoint describing modules
+          connected the DisplayPort transmitter
+
+        properties:
+          reg:
+            const: 0
+
+          endpoint:
+            type: object
+
+            properties:
+
+              remote-endpoint: true
+
+            required:
+              - remote-endpoint
+
+            additionalProperties: false
+
+        additionalProperties: false
+
+required:
+  - compatible
+  - reg
+  - reg-names
+  - interrupts
+  - clocks
+  - clock-names
+  - xlnx,max-link-rate
+  - xlnx,bpc
+  - xlnx,max-lanes
+  - phy-names
+  - phys
+  - ports
+
+additionalProperties: false
+
+examples:
+ - |
+   bus {
+       #address-cells = <2>;
+       #size-cells = <2>;
+
+       v_dp_txss1@a0100000 {
+           compatible = "xlnx,v-dp-txss-3.0";
+           reg = <0x0 0xa0100000 0x0 0x40000>;
+           reg-names = "dp_base";
+           clock-names = "s_axi_aclk", "tx_vid_clk";
+           clocks = <&zynqmp_clk 71>, <&si570_1>;
+           interrupts = <0 92 4>;
+           xlnx,max-lanes = <4>;
+           xlnx,max-link-rate = <810000>;
+           xlnx,bpc = <8>;
+           xlnx,audio-chan = <2>;
+           phy-names = "dp-phy0", "dp-phy1", "dp-phy2", "dp-phy3";
+           phys = <&vphy_lane0 0 1 1 0>, <&vphy_lane1 0 1 1 0>,
+                  <&vphy_lane2 0 1 1 0>, <&vphy_lane3 0 1 1 0>;
+
+           ports {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               port@0 {
+                   reg = <0>;
+                   dp_transmitter: endpoint {
+                       remote-endpoint = <&display_controller>;
+                   };
+               };
+           };
+       };
+   };
+...
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/display/xlnx/xlnx,dsi.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/display/xlnx/xlnx,dsi.txt
@@ -0,0 +1,74 @@
+Device-Tree bindings for Xilinx MIPI DSI Tx IP core
+
+The IP core supports transmission of video data in MIPI DSI protocol.
+
+Required properties:
+ - compatible: Should be "xlnx,dsi".
+
+ - reg: Base address and size of the IP core.
+
+ - xlnx,dsi-datatype: Color format. The value should be one of "MIPI_DSI_FMT_RGB888",
+  "MIPI_DSI_FMT_RGB666", "MIPI_DSI_FMT_RGB666_PACKED" or "MIPI_DSI_FMT_RGB565".
+
+ - simple_panel: The subnode for connected panel. This represents the
+   DSI peripheral connected to the DSI host node. Please refer to
+   Documentation/devicetree/bindings/display/mipi-dsi-bus.txt. The
+   simple-panel driver has auo,b101uan01 panel timing parameters added along
+   with other existing panels. DSI driver derive the required Tx IP controller
+   timing values from the panel timing parameters.
+
+ - port: Logical block can be used / connected independently with
+   external device. In the display controller port nodes, topology
+   for entire pipeline should be described using the DT bindings defined in
+   Documentation/devicetree/bindings/graph.txt.
+
+ - xlnx,dsi-num-lanes: Possible number of DSI lanes for the Tx controller.
+   The values should be 1, 2, 3 or 4. Based on xlnx,dsi-num-lanes and
+   line rate for the MIPI D-PHY core in Mbps, the AXI4-stream received by
+   Xilinx MIPI DSI Tx IP core adds markers as per DSI protocol and the packet
+   thus framed is convered to serial data by MIPI D-PHY core. Please refer
+   Xilinx pg238 for more details. This value should be equal to the number
+   of lanes supported by the connected DSI panel. Panel has to support this
+   value or has to be programmed to the same value that DSI Tx controller is
+   configured to.
+
+ - clocks: List of phandles to Video and 200Mhz DPHY clocks.
+
+ - clock-names: Must contain "s_axis_aclk" and "dphy_clk_200M" in same order as
+   clocks listed in clocks property.
+
+Required simple_panel properties:
+ - compatible: Value should be one of the panel names in
+   Documentation/devicetree/bindings/display/panel/. e.g. "auo,b101uan01".
+   For available panel compatible strings, please refer to bindings in
+   Documentation/devicetree/bindings/display/panel/
+
+Optional properties:
+ - xlnx,vpss: vpss phandle
+   This handle is required only when VPSS is connected to DSI as bridge.
+ - xlnx,dsi-cmd-mode: denotes command mode enable.
+
+Example:
+
+#include <dt-bindings/drm/mipi-dsi.h>
+	mipi_dsi_tx_subsystem@80000000 {
+		compatible = "xlnx,dsi";
+		reg = <0x0 0x80000000 0x0 0x10000>;
+		xlnx,dsi-num-lanes = <4>;
+		xlnx,dsi-data-type = <MIPI_DSI_FMT_RGB888>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		xlnx,vpss = <&v_proc_ss_0>;
+		clock-names = "dphy_clk_200M", "s_axis_aclk";
+		clocks = <&misc_clk_0>, <&misc_clk_1>;
+		encoder_dsi_port: port@0 {
+			reg = <0>;
+			dsi_encoder: endpoint {
+				remote-endpoint = <&xyz_port>;
+			};
+		};
+		simple_panel: simple-panel@0 {
+			compatible = "auo,b101uan01";
+			reg = <0>;
+			};
+		};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/display/xlnx/xlnx,mixer.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/display/xlnx/xlnx,mixer.txt
@@ -0,0 +1,166 @@
+Device-Tree bindings for Xilinx Video Mixer IP core
+
+The IP core provides a flexible video processing block for alpha blending
+and compositing multiple video and/or graphics layers.
+Support for up to sixteen layers based on IP version, with an optional logo
+layer, using a combination of video inputs from either frame buffer or
+streaming video cores (through AXI4-Stream interfaces) is provided.
+The Video Mixer always has one streaming input layer, known as master layer.
+
+Required properties:
+ - compatible: Must contain atleast one of
+	"xlnx,mixer-5.0" (MIXER 5.0 version)
+	"xlnx,mixer-4.0" (MIXER 4.0 version)
+	"xlnx,mixer-3.0" (MIXER 3.0 version)
+ - reg: Base address and size of the IP core.
+ - interrupts: Interrupt number.
+ - interrupts-parent: phandle for interrupt controller.
+ - reset-gpio: gpio to reset the mixer IP
+ - xlnx,enable-csc-coefficient-register: denotes colorimetry
+   coefficients can be programmed, valid for mixer 5.0 version only.
+ - xlnx,dma-addr-width: dma address width, valid values are 32 and 64
+ - xlnx,bpc: bits per component for mixer
+ - xlnx,ppc: pixel per clock for mixer
+ - xlnx,num-layers: Total number of layers (excluding logo)
+   Value ranges from 1-9 for compatible string xlnx,mixer-3.0 and
+   Value ranges from 1-17 for comptaible string xlnx,mixer-4.0 and above
+ - layer_[x]: node for [x] layer
+ - xlnx,layer-id: layer identifier number
+ - xlnx,vformat: video format for layer. See list of supported formats below.
+ - xlnx,layer-max-width: max layer width, mandatory for master layer
+   for overlay layers if scaling is alowed then this is mandatory otherwise
+   not required for overlay layers. Valid range is 64 to 8192
+ - xlnx,layer-max-height: max layer height, mandatory for master layer
+   Not required for overlay layers. Valid range is 64 to 4320
+ - xlnx,layer-primary: denotes the primary layer, should be mentioned in node
+   of layer which is expected to be constructing the primary plane
+
+Optional properties:
+ - dmas: dma attach to layer, mandatory for master layer
+   for rest other layers its optional
+ - dma-names: Should be "dma0", for more details on DMA identifier string
+   refer Documentation/devicetree/bindings/dma/dma.txt
+ - xlnx,layer-streaming: denotes layer can be streaming,
+   mandatory for master layer. Streaming layers need external dma, where
+   as non streaming layers read directly from memory.
+ - xlnx,layer-alpha: denotes layer can do alpha compositing
+ - xlnx,layer-scale: denotes layer can be scale to 2x and 4x
+ - xlnx,logo-layer: denotes logo layer is enable
+ - logo: logo layer
+ - xlnx,bridge: phandle to bridge node.
+   This handle is required only when VTC is connected as bridge.
+
+Supported Formats:
+	Mixer IP Format		Driver supported Format String
+	 BGR888			"RG24"
+	 RGB888			"BG24"
+	 XBGR2101010		"XB30"
+	 XRGB8888		"XR24"
+	 RGBA8888		"RA24"
+	 ABGR8888		"AB24"
+	 ARGB8888		"AR24"
+	 XBGR8888		"XB24"
+	 YUYV			"YUYV"
+	 UYVY			"UYVY"
+	 AYUV			"AYUV"
+	 NV12			"NV12"
+	 NV16			"NV16"
+	 Y8			"GREY"
+	 Y10			"Y10 " (Note: Space included)
+	 XVUY2101010		"XV30"
+	 VUY888			"VU24"
+	 XVUY8888		"XV24"
+	 XV15			"XV15"
+	 XV20			"XV20"
+Note : Format strings are case sensitive.
+
+Example:
+	v_mix_0: v_mix@80100000 {
+		compatible = "xlnx,mixer-3.0";
+		interrupt-parent = <&gic>;
+		interrupts = <0 93 4>;
+		reg = <0x0 0x80100000 0x0 0x80000>;
+
+		xlnx,dma-addr-width=<32>;
+		reset-gpios = <&gpio 1 1>;
+
+		xlnx,bpc = <8>;
+		xlnx,ppc = <2>;
+		xlnx,num-layers = <8>;
+		xlnx,logo-layer;
+		xlnx,bridge = <&v_tc_0>;
+
+		mixer_port: mixer_port@0 {
+			reg = <0>;
+			mixer_crtc: endpoint {
+				remote-endpoint = <&sdi_encoder>;
+			};
+		};
+		xv_mix_master: layer_0 {
+			xlnx,layer-id = <0>;
+			xlnx,vformat = "YUYV";
+			xlnx,layer-max-width = <4096>;
+			xlnx,layer-height = <2160>;
+			dmas = <&axi_vdma_0 0>;
+			dma-names = "dma0";
+			xlnx,layer-streaming;
+			xlnx,layer-primary;
+		};
+		xv_mix_overlay_1: layer_1 {
+			xlnx,layer-id = <1>;
+			xlnx,vformat = "NV16";
+			xlnx,layer-alpha;
+			xlnx,layer-scale;
+			xlnx,layer-max-width=<1920>;
+		};
+		xv_mix_overlay_2: layer_2 {
+			xlnx,layer-id = <2>;
+			xlnx,vformat = "YUYV";
+			xlnx,layer-alpha;
+			xlnx,layer-scale;
+			xlnx,layer-max-width=<1920>;
+		};
+		xv_mix_overlay_3: layer_3 {
+			xlnx,layer-id = <3>;
+			xlnx,vformat = "AYUV";
+			xlnx,layer-alpha;
+			xlnx,layer-scale;
+			xlnx,layer-max-width=<1920>;
+		};
+		xv_mix_overlay_4: layer_4 {
+			xlnx,layer-id = <4>;
+			xlnx,vformat = "GREY";
+			dmas = <&scaler_v_frmbuf_rd_0 0>;
+			dma-names = "dma0";
+			xlnx,layer-streaming;
+			xlnx,layer-alpha;
+			xlnx,layer-scale;
+			xlnx,layer-max-width=<1920>;
+		};
+		xv_mix_overlay_5: layer_5 {
+			xlnx,layer-id = <5>;
+			xlnx,vformat = "AB24";
+			xlnx,layer-alpha;
+			xlnx,layer-scale;
+			xlnx,layer-max-width=<1920>;
+		};
+		xv_mix_overlay_6: layer_6 {
+			xlnx,layer-id = <6>;
+			xlnx,vformat = "XB24";
+			xlnx,layer-alpha;
+			xlnx,layer-scale;
+			xlnx,layer-max-width=<1920>;
+			};
+		xv_mix_overlay_7: layer_7 {
+			xlnx,layer-id = <7>;
+			xlnx,vformat = "BG24";
+			xlnx,layer-alpha;
+			xlnx,layer-scale;
+			xlnx,layer-max-width=<1920>;
+		};
+		xv_mix_logo: logo {
+			xlnx,layer-id = <8>;
+			xlnx,logo-height = <64>;
+			xlnx,logo-width = <64>;
+		};
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/display/xlnx/xlnx,pl-disp.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/display/xlnx/xlnx,pl-disp.txt
@@ -0,0 +1,41 @@
+Xilinx PL Display driver
+------------------------
+
+Pl_Display is a logical device to provide completeness to xilinx display
+pipeline. This is a software driver for providing drm components crtc
+and plane for various IPs using xilinx display pipelines.
+
+A linear pipeline with multiple blocks:
+DMA --> PL_Display --> SDI
+
+Required properties:
+
+- compatible: Must be "xlnx,pl-disp"
+- dmas: dma attach to pipeline
+- dma-names: names for dma
+- xlnx,vformat: video format for layer
+- port: Logical block can be used / connected independently with
+  external device. In the display controller port nodes, topology
+  for entire pipeline should be described using the DT bindings defined in
+  Documentation/devicetree/bindings/graph.txt.
+- reg: Base address and size of device
+
+Optional properties:
+ - xlnx,bridge: bridge phandle
+   This handle is required only when VTC is connected as bridge.
+
+Example:
+
+	drm-pl-disp-drv {
+		compatible = "xlnx,pl-disp";
+		dmas = <&axi_vdma_0 0>;
+		dma-names = "dma0";
+		xlnx,vformat = "YUYV";
+		xlnx,bridge = <&v_tc_0>;
+		pl_disp_port@0 {
+			reg = <0>;
+			endpoint {
+				remote-endpoint = <&sdi_port>;
+			};
+		};
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/display/xlnx/xlnx,sdi-tx.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/display/xlnx/xlnx,sdi-tx.txt
@@ -0,0 +1,63 @@
+Device-Tree bindings for Xilinx SDI Tx subsystem
+
+The IP core supports transmission of video data in SDI Tx protocol
+
+Required properties:
+ - compatible: Should be "xlnx,sdi-tx".
+ - interrupts: Interrupt number.
+ - interrupts-parent: phandle for interrupt controller.
+ - reg: Base address and size of the IP core.
+ - port: Logical block can be used / connected independently with
+   external device. In the display controller port nodes, topology
+   for entire pipeline should be described using the DT bindings defined in
+   Documentation/devicetree/bindings/graph.txt.
+   Minimum one port is required. At max, 2 ports are present.
+   The reg index for AXI4 stream port is 0 and for ancillary data is 1.
+ - clocks: List of phandles to AXI Lite, Video and SDI Tx Clock
+ - clock-names: Must contain "s_axi_aclk", "video_in_clk" and "sdi_tx_clk"
+   in same order as clocks listed in clocks property.
+ - phy-reset-gpio: Specifier for a gpio that asserts GT phy
+
+Optional properties:
+ - xlnx,vpss: vpss phandle
+   This handle is required only when VPSS is connected to SDI as bridge.
+ - xlnx,tx-insert-c-str-st352: Insert ST352 payload in Chroma stream.
+ - interrupt-names: Should be "sdi_tx_irq". This is only required when
+   multiple interrupts are connected in the hardware design.
+ - xlnx,qpll1enabled: boolean property present when the QPLL1 drives GT clock
+   absent with QPLL0 drives GT clock
+- xlnx,picxo_enabled: boolean property present when PICXO is present in design
+
+Example:
+
+	sdi_tx_subsystem@80000000 {
+		compatible = "xlnx,sdi-tx";
+		reg = <0x0 0x80000000 0x0 0x10000>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 90 4>;
+		interrupt-names = "sdi_tx_irq";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		xlnx,vpss = <&v_proc_ss_0>;
+		clock-names = "s_axi_aclk", "video_in_clk", "sdi_tx_clk";
+		clocks = <&misc_clk_0>, <&misc_clk_1>, <&misc_clk_2>;
+		phy-reset-gpio = <&axi_gpio_0 0 0 0>;
+		xlnx,qpll1enabled;
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			encoder_sdi_port: port@0 {
+				reg = <0>;
+				sdi_encoder: endpoint {
+					remote-endpoint = <&pl_disp_crtc>;
+				};
+			};
+
+			sdi_audio_port: port@1 {
+				reg = <1>;
+				sdi_audio_sink_port: endpoint {
+					remote-endpoint = <&sditx_audio_embed_src_port>;
+				};
+			};
+		};
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/display/xlnx/xlnx,vpss-csc.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/display/xlnx/xlnx,vpss-csc.txt
@@ -0,0 +1,35 @@
+Xllinx VPSS Color Space Converter
+-----------------------------------------
+The Xilinx VPSS Color Space Converter is a Video IP that supports
+color space conversion from RGB to YUV 444/422/420 and vice versa.
+
+Required properties:
+
+- compatible: Must be "xlnx,vpss-csc".
+
+- reg: Physical base address and length of registers set for the device.
+
+- xlnx,video-width: This property qualifies the video format with sample
+  width expressed as a number of bits per pixel component. Supported video
+  width values are 8/10/12/16.
+
+-reset-gpios: GPIO specifier to assert/de-assert the reset line.
+
+- clocks: phandle to IP clock.
+
+- xlnx,max-width: Maximum number of pixels in a line.
+  Valid range from 64 to 8192.
+
+- xlnx,max-height: Maximum number of lines in a frame.
+  Valid range from 64 to 4320.
+
+Example:
+	csc@a0040000 {
+		compatible = "xlnx,vpss-csc";
+		reg = <0x0 0xa0040000 0x0 0x10000>;
+		reset-gpios = <&gpio 0x0 GPIO_ACTIVE_LOW>;
+		xlnx,video-width = <8>;
+		clocks = <&misc_clk_0>;
+		xlnx,max-width = <3840>;
+		xlnx,max-height = <2160>;
+	}
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/display/xlnx/xlnx,vpss-scaler.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/display/xlnx/xlnx,vpss-scaler.txt
@@ -0,0 +1,50 @@
+Xilinx VPSS Scaler
+------------------
+The Xilinx VPSS Scaler is a Video IP that supports up scaling,
+down scaling and no scaling functionailty. This supports custom
+resolution values between 0 to 4096.
+
+Required properties:
+
+- compatible: Must be "xlnx,vpss-scaler-2.2" or "xlnx,vpss-scaler".
+
+- reg: Physical base address and length of registers set for the device.
+
+- xlnx,num-hori-taps: The number of horizontal taps for scaling filter
+  supported tap values are 2/4/6/8/10/12.
+
+- xlnx,num-vert-taps: The number of vertical taps for scaling filter
+  supported tap values are 2/4/6/8/10/12.
+
+  A value of 2 represents bilinear filters. A value of 4 represents bicubic.
+  Values 6, 8, 10, 12 represent polyphase filters.
+
+- xlnx,pix-per-clk : The pixels per clock property of the IP.
+  supported values are 1 and 2.
+
+- reset-gpios: GPIO specifier to assert/de-assert the reset line.
+
+- clocks: List of phandles to AXI Lite and Video clock
+
+- clock-names: Must contain "aclk_ctrl" and "aclk_axis" in same order as clocks
+  listed in clocks property.
+
+- xlnx,max-width: Maximum number of pixels in a line.
+  Valid range from 64 to 8192.
+
+- xlnx,max-height: Maximum number of lines in a frame.
+  Valid range from 64 to 4320.
+
+Example:
+	scaler@a0040000 {
+		compatible = "xlnx,vpss-scaler";
+		reg = <0x0 0xa0000000 0x0 0x40000>;
+		reset-gpios = <&gpio 0x0 GPIO_ACTIVE_LOW>;
+		xlnx,num-hori-taps = <8>;
+		xlnx,num-vert-taps = <8>;
+		xlnx,pix-per-clk = <2>;
+		clock-names = "aclk_ctrl", "aclk_axis";
+		clocks = <&misc_clk_0>, <&misc_clk_1>;
+		xlnx,max-width = <3840>;
+		xlnx,max-height = <2160>;
+	}
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/display/xlnx/xlnx,vtc.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/display/xlnx/xlnx,vtc.txt
@@ -0,0 +1,32 @@
+Device-Tree bindings for Xilinx Video Timing Controller(VTC)
+
+Xilinx VTC is a general purpose video timing generator and detector.
+The input side of this core automatically detects horizontal and
+vertical synchronization, pulses, polarity, blanking timing and active pixels.
+While on the output, it generates the horizontal and vertical blanking and
+synchronization pulses used with a standard video system including support
+for programmable pulse polarity.
+
+The core is commonly used with Video in to AXI4-Stream core to detect the
+format and timing of incoming video data or with AXI4-Stream to Video out core
+to generate outgoing video timing for downstream sinks like a video monitor.
+
+For details please refer to
+https://www.xilinx.com/support/documentation/ip_documentation/v_tc/v6_1/pg016_v_tc.pdf
+
+Required properties:
+ - compatible: value should be "xlnx,bridge-v-tc-6.1"
+ - reg: base address and size of the VTC IP
+ - xlnx,pixels-per-clock: Pixels per clock of the stream. Can be 1, 2 or 4.
+ - clocks: List of phandles for AXI Lite and Video Clock
+ - clock-names: Must contain "s_axi_aclk" and "clk" in same order as clocks listed
+   in clocks property.
+
+Example:
+	v_tc_0: v_tc@80030000 {
+			compatible = "xlnx,bridge-v-tc-6.1";
+			reg = <0x0 0x80030000 0x0 0x10000>;
+			xlnx,pixels-per-clock = <2>;
+			clock-names = "s_axi_aclk", "clk";
+			clocks = <&misc_clk_0>, <&misc_clk_1>;
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/display/xlnx/xlnx,zynqmp-dpsub.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/display/xlnx/xlnx,zynqmp-dpsub.txt
@@ -0,0 +1,82 @@
+Xilinx ZynqMP DisplayPort subsystem
+-----------------------------------
+
+Required properties:
+
+- compatible: Must be "xlnx,zynqmp-dpsub-1.7".
+
+- reg: Physical base address and length of the registers set for the device.
+- reg-names: Must be "dp", "blend", "av_buf", and "aud" to map logical register
+  partitions.
+
+- interrupts: Interrupt number.
+- interrupts-parent: phandle for interrupt controller.
+
+- clocks: phandles for axi, audio, non-live video, and live video clocks.
+  axi clock is required. Audio clock is optional. If not present, audio will
+  be disabled. One of non-live or live video clock should be present.
+- clock-names: The identification strings are required. "aclk" for axi clock.
+  "dp_aud_clk" for audio clock. "dp_vtc_pixel_clk_in" for non-live video clock.
+  "dp_live_video_in_clk" for live video clock (clock from programmable logic).
+
+- phys: phandles for phy specifier. The number of lanes is configurable
+  between 1 and 2. The number of phandles should be 1 or 2.
+- phy-names: The identifier strings. "dp-phy" followed by index, 0 or 1.
+  For single lane, only "dp-phy0" is required. For dual lane, both "dp-phy0"
+  and "dp-phy1" are required where "dp-phy0" is the primary lane.
+
+- power-domains: phandle for the corresponding power domain
+
+- vid-layer, gfx-layer: Required to represent available layers
+
+Required layer properties
+
+- dmas: phandles for DMA channels as defined in
+  Documentation/devicetree/bindings/dma/dma.txt.
+- dma-names: The identifier strings are required. "gfx0" for graphics layer
+  dma channel. "vid" followed by index (0 - 2) for video layer dma channels.
+
+Optional child node
+
+- The driver populates any child device node in this node. This can be used,
+  for example, to populate the sound device from the DisplayPort subsystem
+  driver.
+
+Example:
+	zynqmp-display-subsystem@fd4a0000 {
+		compatible = "xlnx,zynqmp-dpsub-1.7";
+		reg = <0x0 0xfd4a0000 0x0 0x1000>,
+		      <0x0 0xfd4aa000 0x0 0x1000>,
+		      <0x0 0xfd4ab000 0x0 0x1000>,
+		      <0x0 0xfd4ac000 0x0 0x1000>;
+		reg-names = "dp", "blend", "av_buf", "aud";
+		interrupts = <0 119 4>;
+		interrupt-parent = <&gic>;
+
+		clock-names = "dp_apb_clk", "dp_aud_clk", "dp_live_video_in_clk";
+		clocks = <&dp_aclk>, <&clkc 17>, <&si570_1>;
+
+		phys = <&lane1>, <&lane0>;
+		phy-names = "dp-phy0", "dp-phy1";
+
+		power-domains = <&pd_dp>;
+
+		vid-layer {
+			dma-names = "vid0", "vid1", "vid2";
+			dmas = <&xlnx_dpdma 0>,
+			       <&xlnx_dpdma 1>,
+			       <&xlnx_dpdma 2>;
+		};
+
+		gfx-layer {
+			dma-names = "gfx0";
+			dmas = <&xlnx_dpdma 3>;
+		};
+
+		dma-names = "vid0", "vid1", "vid2", "gfx0";
+		dmas = <&xlnx_dpdma 0>,
+		       <&xlnx_dpdma 1>,
+		       <&xlnx_dpdma 2>,
+		       <&xlnx_dpdma 3>;
+	};
+};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml
@@ -58,7 +58,7 @@
 then:
   properties:
     clocks:
-      maxItems: 2
+      minItems: 2
 
   required:
     - clock-names
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/dma/moxa,moxart-dma.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/dma/moxa,moxart-dma.txt
@@ -34,8 +34,8 @@
 Use specific request line passing from dma
 For example, MMC request line is 5
 
-	sdhci: sdhci@98e00000 {
-		compatible = "moxa,moxart-sdhci";
+	mmc: mmc@98e00000 {
+		compatible = "moxa,moxart-mmc";
 		reg = <0x98e00000 0x5C>;
 		interrupts = <5 0>;
 		clocks = <&clk_apb>;
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/dma/xilinx/axi-dma.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/dma/xilinx/axi-dma.txt
@@ -0,0 +1,38 @@
+* Xilinx AXI DMA Test client
+
+Required properties:
+- compatible: Should be "xlnx,axi-dma-test-1.00.a"
+- dmas: a list of <[DMA device phandle] [Channel ID]> pairs,
+	where Channel ID is '0' for write/tx and '1' for read/rx
+	channel.
+- dma-names: a list of DMA channel names, one per "dmas" entry
+
+Example:
+++++++++
+
+dmatest_0: dmatest@0 {
+	compatible ="xlnx,axi-dma-test-1.00.a";
+	dmas = <&axi_dma_0 0
+		&axi_dma_0 1>;
+	dma-names = "axidma0", "axidma1";
+} ;
+
+
+Xilinx AXI DMA Device Node Example
+++++++++++++++++++++++++++++++++++++
+
+axi_dma_0: axidma@40400000 {
+	compatible = "xlnx,axi-dma-1.00.a";
+	#dma-cells = <1>;
+	reg = < 0x40400000 0x10000 >;
+	dma-channel@40400000 {
+		compatible = "xlnx,axi-dma-mm2s-channel";
+		interrupts = < 0 59 4 >;
+		xlnx,datawidth = <0x40>;
+	} ;
+	dma-channel@40400030 {
+		compatible = "xlnx,axi-dma-s2mm-channel";
+		interrupts = < 0 58 4 >;
+		xlnx,datawidth = <0x40>;
+	} ;
+} ;
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/dma/xilinx/ps-pcie-dma.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/dma/xilinx/ps-pcie-dma.txt
@@ -0,0 +1,67 @@
+* Xilinx PS PCIe Root DMA
+
+Required properties:
+- compatible: Should be "xlnx,ps_pcie_dma-1.00.a"
+- reg: Register offset for Root DMA channels
+- reg-names: Name for the register. Should be "ps_pcie_regbase"
+- interrupts: Interrupt pin for Root DMA
+- interrupt-names: Name for the interrupt. Should be "ps_pcie_rootdma_intr"
+- interrupt-parent: Should be gic in case of zynqmp
+- rootdma: Indicates this platform device is root dma.
+	This is required as the same platform driver will be invoked by pcie end points too
+- dma_vendorid: 16 bit PCIe device vendor id.
+	This can be later used by dma client for matching while using dma_request_channel
+- dma_deviceid: 16 bit PCIe device id
+	This can be later used by dma client for matching while using dma_request_channel
+- numchannels: Indicates number of channels to be enabled for the device.
+	Valid values are from 1 to 4 for zynqmp
+- ps_pcie_channel : One for each channel to be enabled.
+	This array contains channel specific properties.
+	Index 0: Direction of channel
+		Direction of channel can be either PCIe Memory to AXI memory i.e., Host to Card or
+		AXI Memory to PCIe memory i.e., Card to Host
+		PCIe to AXI Channel Direction is represented as 0x1
+		AXI to PCIe Channel Direction is represented as 0x0
+	Index 1: Number of Buffer Descriptors
+		This number describes number of buffer descriptors to be allocated for a channel
+	Index 2: Number of Queues
+		Each Channel has four DMA Buffer Descriptor Queues.
+		By default All four Queues will be managed by Root DMA driver.
+		User may choose to have only two queues either Source and it's Status Queue or
+			Destination and it's Status Queue to be handled by Driver.
+		The other two queues need to be handled by user logic which will not be part of this driver.
+		All Queues on Host is represented by 0x4
+		Two Queues on Host is represented by 0x2
+	Index 3: Coalesce Count
+		This number indicates the number of transfers after which interrupt needs to
+		be raised for the particular channel. The allowed range is from 0 to 255
+	Index 4: Coalesce Count Timer frequency
+		This property is used to control the frequency of poll timer. Poll timer is
+		created for a channel whenever coalesce count value (>= 1) is programmed for the particular
+		channel. This timer is helpful in draining out completed transactions even though interrupt is
+		not generated.
+
+Client Usage:
+	DMA clients can request for these channels using dma_request_channel API
+
+
+Xilinx PS PCIe Root DMA node Example
+++++++++++++++++++++++++++++++++++++
+
+	pci_rootdma: rootdma@fd0f0000 {
+		compatible = "xlnx,ps_pcie_dma-1.00.a";
+		reg = <0x0 0xfd0f0000 0x0 0x1000>;
+		reg-names = "ps_pcie_regbase";
+		interrupts = <0 117 4>;
+		interrupt-names = "ps_pcie_rootdma_intr";
+		interrupt-parent = <&gic>;
+		rootdma;
+		dma_vendorid = /bits/ 16 <0x10EE>;
+		dma_deviceid = /bits/ 16 <0xD021>;
+		numchannels = <0x4>;
+		#size-cells = <0x5>;
+		ps_pcie_channel0 = <0x1 0x7CF 0x4 0x0 0x3E8>;
+		ps_pcie_channel1 = <0x0 0x7CF 0x4 0x0 0x3E8>;
+		ps_pcie_channel2 = <0x1 0x7CF 0x4 0x0 0x3E8>;
+		ps_pcie_channel3 = <0x0 0x7CF 0x4 0x0 0x3E8>;
+    };
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/dma/xilinx/vdmatest.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/dma/xilinx/vdmatest.txt
@@ -0,0 +1,39 @@
+* Xilinx Video DMA Test client
+
+Required properties:
+- compatible: Should be "xlnx,axi-vdma-test-1.00.a"
+- dmas: a list of <[Video DMA device phandle] [Channel ID]> pairs,
+	where Channel ID is '0' for write/tx and '1' for read/rx
+	channel.
+- dma-names: a list of DMA channel names, one per "dmas" entry
+- xlnx,num-fstores: Should be the number of framebuffers as configured in
+	VDMA device node.
+
+Example:
+++++++++
+
+vdmatest_0: vdmatest@0 {
+	compatible ="xlnx,axi-vdma-test-1.00.a";
+	dmas = <&axi_vdma_0 0
+		&axi_vdma_0 1>;
+	dma-names = "vdma0", "vdma1";
+	xlnx,num-fstores = <0x8>;
+} ;
+
+
+Xilinx Video DMA Device Node Example
+++++++++++++++++++++++++++++++++++++
+axi_vdma_0: axivdma@44A40000 {
+	compatible = "xlnx,axi-vdma-1.00.a";
+	...
+	dma-channel@44A40000 {
+		...
+		xlnx,num-fstores = <0x8>;
+		...
+	} ;
+	dma-channel@44A40030 {
+		...
+		xlnx,num-fstores = <0x8>;
+		...
+	} ;
+} ;
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt
@@ -11,9 +11,16 @@
 Xilinx AXI CDMA engine, it does transfers between memory-mapped source
 address and a memory-mapped destination address.
 
+Xilinx AXI MCDMA engine, it does transfer between memory and AXI4 stream
+target devices. It can be configured to have up to 16 independent transmit
+and receive channels.
+
 Required properties:
-- compatible: Should be "xlnx,axi-vdma-1.00.a" or "xlnx,axi-dma-1.00.a" or
-	      "xlnx,axi-cdma-1.00.a""
+- compatible: Should be one of-
+		"xlnx,axi-vdma-1.00.a"
+		"xlnx,axi-dma-1.00.a"
+		"xlnx,axi-cdma-1.00.a"
+		"xlnx,axi-mcdma-1.00.a"
 - #dma-cells: Should be <1>, see "dmas" property below
 - reg: Should contain VDMA registers location and length.
 - xlnx,addrwidth: Should be the vdma addressing size in bits(ex: 32 bits).
@@ -29,7 +36,7 @@
 			   "m_axis_mm2s_aclk", "s_axis_s2mm_aclk"
 	For CDMA:
 	Required elements: "s_axi_lite_aclk", "m_axi_aclk"
-	FOR AXIDMA:
+	For AXIDMA and MCDMA:
 	Required elements: "s_axi_lite_aclk"
 	Optional elements: "m_axi_mm2s_aclk", "m_axi_s2mm_aclk",
 			   "m_axi_sg_aclk"
@@ -37,12 +44,11 @@
 Required properties for VDMA:
 - xlnx,num-fstores: Should be the number of framebuffers as configured in h/w.
 
-Optional properties for AXI DMA:
+Optional properties for AXI DMA and MCDMA:
 - xlnx,sg-length-width: Should be set to the width in bits of the length
 	register as configured in h/w. Takes values {8...26}. If the property
 	is missing or invalid then the default value 23 is used. This is the
 	maximum value that is supported by all IP versions.
-- xlnx,mcdma: Tells whether configured for multi-channel mode in the hardware.
 Optional properties for VDMA:
 - xlnx,flush-fsync: Tells which channel to Flush on Frame sync.
 	It takes following values:
@@ -55,8 +61,8 @@
 	For VDMA: It should be either "xlnx,axi-vdma-mm2s-channel" or
 	"xlnx,axi-vdma-s2mm-channel".
 	For CDMA: It should be "xlnx,axi-cdma-channel".
-	For AXIDMA: It should be either "xlnx,axi-dma-mm2s-channel" or
-	"xlnx,axi-dma-s2mm-channel".
+	For AXIDMA and MCDMA: It should be either "xlnx,axi-dma-mm2s-channel"
+	or "xlnx,axi-dma-s2mm-channel".
 - interrupts: Should contain per channel VDMA interrupts.
 - xlnx,datawidth: Should contain the stream data width, take values
 	{32,64...1024}.
@@ -69,8 +75,8 @@
 	enabled/disabled in hardware.
 - xlnx,enable-vert-flip: Tells vertical flip is
 	enabled/disabled in hardware(S2MM path).
-Optional child node properties for AXI DMA:
--dma-channels: Number of dma channels in child node.
+Optional child node properties for MCDMA:
+- dma-channels: Number of dma channels in child node.
 
 Example:
 ++++++++
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/dma/xilinx/xilinx_dpdma.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/dma/xilinx/xilinx_dpdma.txt
@@ -0,0 +1,91 @@
+Device-Tree bindings for Xilinx ZynqMP DisplayPort Subsystem
+
+The ZynqMP DisplayPort subsystem handles DMA channel buffer management,
+blending, and audio mixing. The DisplayPort subsystem receives display
+and audio frames from DPDMA and transmits output to the DisplayPort IP core.
+
+Required properties:
+ - compatible: Should be "xlnx,dpdma".
+ - reg: Base address and size of the IP core.
+ - interrupts: Interrupt number.
+ - interrupts-parent: phandle for interrupt controller.
+ - clocks: phandle for AXI clock
+ - clock-names: The identification string, "axi_clk", is always required.
+
+Required child node properties:
+- compatible: Should be one of "xlnx,video0", "xlnx,video1", "xlnx,video2",
+  "xlnx,graphics", "xlnx,audio0", or "xlnx,audio1".
+
+Example:
+
+	xlnx_dpdma: axidpdma@43c10000 {
+		compatible = "xlnx,dpdma";
+		reg = <0x43c10000 0x1000>;
+		interrupts = <0 54 4>;
+		interrupt-parent = <&intc>;
+		clocks = <&clkc 16>;
+		clock-names = "axi_clk";
+		xlnx,axi-clock-freq = <200000000>;
+
+		dma-channels = <6>;
+
+		#dma-cells = <1>;
+		dma-video0channel@43c10000 {
+			compatible = "xlnx,video0";
+		};
+		dma-video1channel@43c10000 {
+			compatible = "xlnx,video1";
+		};
+		dma-video2channel@43c10000 {
+			compatible = "xlnx,video2";
+		};
+		dma-graphicschannel@43c10000 {
+			compatible = "xlnx,graphics";
+		};
+		dma-audio0channel@43c10000 {
+			compatible = "xlnx,audio0";
+		};
+		dma-audio1channel@43c10000 {
+			compatible = "xlnx,audio1";
+		};
+	};
+
+* DMA client
+
+Required properties:
+- dmas: a list of <[DPDMA device phandle] [Channel ID]> pairs. "Channel ID"
+  is defined as video0 = 0, video1 = 1, video2 = 2, graphics = 3, audio0 = 4,
+  and audio1 = 5.
+
+Example:
+
+	xilinx_drm {
+		compatible = "xlnx,drm";
+		xlnx,encoder-slave = <&xlnx_dp>;
+		clocks = <&si570 0>;
+		xlnx,connector-type = "DisplayPort";
+		xlnx,dp-sub = <&xlnx_dp_sub>;
+		planes {
+			xlnx,pixel-format = "rgb565";
+			plane0 {
+				dmas = <&xlnx_dpdma 3>;
+				dma-names = "dma";
+			};
+			plane1 {
+				dmas = <&xlnx_dpdma 0>;
+				dma-names = "dma";
+			};
+		};
+	};
+
+	xlnx_dp_snd_pcm0: dp_snd_pcm0 {
+		compatible = "xlnx,dp-snd-pcm";
+		dmas = <&xlnx_dpdma 4>;
+		dma-names = "tx";
+	};
+
+	xlnx_dp_snd_pcm1: dp_snd_pcm1 {
+		compatible = "xlnx,dp-snd-pcm";
+		dmas = <&xlnx_dpdma 5>;
+		dma-names = "tx";
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/dma/xilinx/xilinx_frmbuf.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/dma/xilinx/xilinx_frmbuf.txt
@@ -0,0 +1,123 @@
+The Xilinx framebuffer DMA engine supports two soft IP blocks: one IP
+block is used for reading video frame data from memory (FB Read) to the device
+and the other IP block is used for writing video frame data from the device
+to memory (FB Write).  Both the FB Read/Write IP blocks are aware of the
+format of the data being written to or read from memory including RGB and
+YUV in packed, planar, and semi-planar formats.  Because the FB Read/Write
+is format aware, only one buffer pointer is needed by the IP blocks even
+when planar or semi-planar format are used.
+
+FB Read Required propertie(s):
+- compatible		: Should be "xlnx,axi-frmbuf-rd-v2.1". Older string
+			  "xlnx,axi-frmbuf-rd-v2" is now deprecated.
+
+Note: Compatible string "xlnx,axi-frmbuf-rd" and the hardware it
+represented is no longer supported.
+
+FB Write Required propertie(s):
+- compatible		: Should be "xlnx,axi-frmbuf-wr-v2.1". Older string
+			  "xlnx,axi-frmbuf-wr-v2" is now deprecated.
+
+Note: Compatible string "xlnx,axi-frmbuf-wr" and the hardware it
+represented is no longer supported.
+
+Required Properties Common to both FB Read and FB Write:
+- #dma-cells		: should be 1
+- interrupt-parent	: Interrupt controller the interrupt is routed through
+- interrupts		: Should contain DMA channel interrupt
+- reset-gpios		: Should contain GPIO reset phandle
+- reg			: Memory map for module access
+- xlnx,dma-addr-width	: Size of dma address pointer in IP (either 32 or 64)
+- xlnx,vid-formats	: A list of strings indicating what video memory
+			  formats the IP has been configured to support.
+			  See VIDEO FORMATS table below and examples.
+
+Required Properties Common to both FB Read and FB Write for v2.1:
+- xlnx,pixels-per-clock	: Pixels per clock set in IP (1, 2, 4 or 8)
+- clocks: Reference to the AXI Streaming clock feeding the AP_CLK
+- clock-names: Must have "ap_clk"
+- xlnx,max-height	: Maximum number of lines.
+			  Valid range from 64 to 4320.
+- xlnx,max-width	: Maximum number of pixels in a line.
+			  Valid range from 64 to 8192.
+
+Optional Properties Common to both FB Read and FB Write for v2.1:
+- xlnx,dma-align	: DMA alignment required in bytes.
+			  If absent then dma alignment is calculated as
+			  pixels per clock * 8.
+			  If present it should be power of 2 and at least
+			  pixels per clock * 8.
+			  Minimum is 8, 16, 32 when pixels-per-clock is
+			  1, 2 or 4.
+- xlnx,fid		: Field ID enabled for interlaced video support.
+			  Can be absent for progressive video.
+
+VIDEO FORMATS
+The following table describes the legal string values to be used for
+the xlnx,vid-formats property.  To the left is the string value and the
+two columns to the right describe how this is mapped to an equivalent V4L2
+and DRM fourcc code---respectively---by the driver.
+
+IP FORMAT	DTS String	V4L2 Fourcc		DRM Fourcc
+-------------|----------------|----------------------|---------------------
+RGB8		bgr888		V4L2_PIX_FMT_RGB24	DRM_FORMAT_BGR888
+BGR8		rgb888		V4L2_PIX_FMT_BGR24	DRM_FORMAT_RGB888
+RGBX8		xbgr8888	V4L2_PIX_FMT_BGRX32	DRM_FORMAT_XBGR8888
+RGBA8		abgr8888	<not supported>		DRM_FORMAT_ABGR8888
+BGRA8		argb8888	<not supported>		DRM_FORMAT_ARGB8888
+BGRX8		xrgb8888	V4L2_PIX_FMT_XBGR32	DRM_FORMAT_XRGB8888
+RGBX10		xbgr2101010	V4L2_PIX_FMT_XBGR30	DRM_FORMAT_XBGR2101010
+RGBX12		xbgr2121212	V4L2_PIX_FMT_XBGR40	<not supported>
+RGBX16		rgb16		V4L2_PIX_FMT_BGR40	<not supported>
+YUV8		vuy888		V4L2_PIX_FMT_VUY24	DRM_FORMAT_VUY888
+YUVX8		xvuy8888	V4L2_PIX_FMT_XVUY32	DRM_FORMAT_XVUY8888
+YUYV8		yuyv		V4L2_PIX_FMT_YUYV	DRM_FORMAT_YUYV
+UYVY8		uyvy		V4L2_PIX_FMT_UYVY	DRM_FORMAT_UYVY
+YUVA8		avuy8888	<not supported>		DRM_FORMAT_AVUY
+YUVX10		yuvx2101010	V4L2_PIX_FMT_XVUY10	DRM_FORMAT_XVUY2101010
+Y8		y8		V4L2_PIX_FMT_GREY	DRM_FORMAT_Y8
+Y10		y10		V4L2_PIX_FMT_XY10	DRM_FORMAT_Y10
+Y_UV8		nv16		V4L2_PIX_FMT_NV16	DRM_FORMAT_NV16
+Y_UV8		nv16		V4L2_PIX_FMT_NV16M	DRM_FORMAT_NV16
+Y_UV8_420	nv12		V4L2_PIX_FMT_NV12	DRM_FORMAT_NV12
+Y_UV8_420	nv12		V4L2_PIX_FMT_NV12M	DRM_FORMAT_NV12
+Y_UV10		xv20		V4L2_PIX_FMT_XV20M	DRM_FORMAT_XV20
+Y_UV10		xv20		V4L2_PIX_FMT_XV20	<not supported>
+Y_UV10_420	xv15		V4L2_PIX_FMT_XV15M	DRM_FORMAT_XV15
+Y_UV10_420	xv15		V4L2_PIX_FMT_XV20	<not supported>
+
+Examples:
+
+FB Read Example:
+++++++++
+v_frmbuf_rd_0: v_frmbuf_rd@80000000 {
+	#dma-cells = <1>;
+	compatible = "xlnx,axi-frmbuf-rd-v2.1";
+	interrupt-parent = <&gic>;
+	interrupts = <0 92 4>;
+	reset-gpios = <&gpio 80 1>;
+	reg = <0x0 0x80000000 0x0 0x10000>;
+	xlnx,dma-addr-width = <32>;
+	xlnx,vid-formats = "bgr888","xbgr8888";
+	xlnx,pixels-per-clock = <1>;
+	xlnx,dma-align = <8>;
+	clocks = <&vid_stream_clk>;
+	clock-names = "ap_clk"
+};
+
+FB Write Example:
+++++++++
+v_frmbuf_wr_0: v_frmbuf_wr@80000000 {
+	#dma-cells = <1>;
+	compatible = "xlnx,axi-frmbuf-wr-v2.1";
+	interrupt-parent = <&gic>;
+	interrupts = <0 92 4>;
+	reset-gpios = <&gpio 80 1>;
+	reg = <0x0 0x80000000 0x0 0x10000>;
+	xlnx,dma-addr-width = <64>;
+	xlnx,vid-formats = "bgr888","yuyv","nv16","nv12";
+	xlnx,pixels-per-clock = <2>;
+	xlnx,dma-align = <16>;
+	clocks = <&vid_stream_clk>;
+	clock-names = "ap_clk"
+};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/drm/zocl/zocl_drm.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/drm/zocl/zocl_drm.txt
@@ -0,0 +1,13 @@
+Binding for ZynQ OpenCL DRM driver
+
+Required properties:
+- compatible: should contain "xlnx,zocl"
+- reg: base address and size for memory mapped control port for opencl kernel
+
+Example:
+
+	zocl_drm {
+		compatible = "xlnx,zocl";
+		status = "okay";
+		reg = <0x80000000 0x10000>;
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/edac/cortex-arm64-edac.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/edac/cortex-arm64-edac.txt
@@ -0,0 +1,15 @@
+* ARM Cortex A57 and A53 L1/L2 cache error reporting
+
+CPU Memory Error Syndrome and L2 Memory Error Syndrome registers can be used
+for checking L1 and L2 memory errors.
+
+The following section describes the Cortex A57/A53 EDAC DT node binding.
+
+Required properties:
+- compatible: Should be "arm,cortex-a57-edac" or "arm,cortex-a53-edac"
+
+Example:
+	edac {
+		compatible = "arm,cortex-a57-edac";
+	};
+
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/edac/pl310_edac_l2.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/edac/pl310_edac_l2.txt
@@ -0,0 +1,19 @@
+Pl310 L2 Cache EDAC driver, it does reports the data and tag ram parity errors.
+
+Required properties:
+- compatible: Should be "arm,pl310-cache".
+- intterupts: Interrupt number to the cpu.
+- reg: Physical base address and size of cache controller's memory mapped
+  registers
+
+Example:
+++++++++
+
+	L2: cache-controller {
+		compatible = "arm,pl310-cache";
+		interrupts = <0 2 4>;
+		reg = <0xf8f02000 0x1000>;
+	};
+
+PL310 L2 Cache EDAC driver detects the Parity enable state by reading the
+appropriate control register.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/edac/xlnx,versal-ddrmc-edac.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/edac/xlnx,versal-ddrmc-edac.yaml
@@ -0,0 +1,60 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/edac/xlnx,versal-ddrmc-edac.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Xilinx Versal DDRMC EDAC driver
+
+maintainers:
+  - Sai Krishna Potthuri <lakshmi.sai.krishna.potthuri@xilinx.com>
+
+description: |
+  Versal DDR controller has an optional ECC support which correct
+  single bit ECC errors and detect double bit ECC errors.
+
+properties:
+  compatible:
+    items:
+      - enum:
+          - xlnx,versal-ddrmc-edac
+
+  reg:
+    maxItems: 2
+    items:
+      - description: DDR Memory Controller registers
+      - description: NOC registers corresponding to DDR Memory Controller
+
+  reg-names:
+    items:
+      - const: ddrmc_base
+      - const: ddrmc_noc_base
+
+  interrupts:
+    maxItems: 1
+
+  xlnx,mc-id:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: Instance number of the DDR Memory Controller
+
+required:
+  - compatible
+  - reg
+  - reg-names
+  - interrupts
+  - xlnx,mc-id
+
+examples:
+  - |
+    bus {
+      #address-cells = <2>;
+      #size-cells = <2>;
+      memory-controller@f6150000 {
+        compatible = "xlnx,versal-ddrmc-edac";
+        reg = <0x0 0xf6150000 0x0 0x2000>, <0x0 0xf6070000 0x0 0x20000>;
+        reg-names = "ddrmc_base", "ddrmc_noc_base";
+        interrupt-parent = <&gic>;
+        interrupts = <0 147 4>;
+        xlnx,mc-id = <0>;
+      };
+    };
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/edac/zynqmp_ocm_edac.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/edac/zynqmp_ocm_edac.txt
@@ -0,0 +1,18 @@
+Xilinx ZynqMP OCM EDAC driver, it does reports the OCM ECC single bit errors
+that are corrected and double bit ecc errors that are detected by the OCM
+ECC controller.
+
+Required properties:
+- compatible: Should be "xlnx,zynqmp-ocmc-1.0".
+- reg: Should contain OCM controller registers location and length.
+- interrupt-parent: Should be core interrupt controller.
+- interrupts: Property with a value describing the interrupt number.
+
+Example:
+++++++++
+ocm: memory-controller@ff960000 {
+	compatible = "xlnx,zynqmp-ocmc-1.0";
+	reg = <0x0 0xff960000 0x1000>;
+	interrupt-parent = <&gic>;
+	interrupts = <0 10 4>;
+};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/firmware/intel,ixp4xx-network-processing-engine.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/firmware/intel,ixp4xx-network-processing-engine.yaml
@@ -25,8 +25,6 @@
           - const: intel,ixp4xx-network-processing-engine
 
   reg:
-    minItems: 3
-    maxItems: 3
     items:
       - description: NPE0 register range
       - description: NPE1 register range
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-firmware.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/firmware/xilinx/xlnx,zynqmp-firmware.txt
@@ -11,7 +11,9 @@
 services.
 
 Required properties:
- - compatible:	Must contain:	"xlnx,zynqmp-firmware"
+ - compatible:	Must contain any of below:
+		"xlnx,zynqmp-firmware" for Zynq Ultrascale+ MPSoC
+		"xlnx,versal-firmware" for Versal
  - method:	The method of calling the PM-API firmware layer.
 		Permitted values are:
 		  - "smc" : SMC #0, following the SMCCC
@@ -21,10 +23,22 @@
 Example
 -------
 
+Zynq Ultrascale+ MPSoC
+----------------------
 firmware {
 	zynqmp_firmware: zynqmp-firmware {
 		compatible = "xlnx,zynqmp-firmware";
 		method = "smc";
 		...
 	};
+};
+
+Versal
+------
+firmware {
+	versal_firmware: versal-firmware {
+		compatible = "xlnx,versal-firmware";
+		method = "smc";
+		...
+	};
 };
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/fpga/fpga-region.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/fpga/fpga-region.txt
@@ -187,6 +187,12 @@
 - external-fpga-config : boolean, set if the FPGA has already been configured
 	prior to OS boot up.
 - encrypted-fpga-config : boolean, set if the bitstream is encrypted
+- userkey-encrypted-fpga-config: boolean, set if the bitstream is encrypted with
+	user key.
+- ddrmem-authenticated-fpga-config: boolean, if set do bitstream authentication
+	using DDR memory.
+- securemem-authenticated-fpga-config: boolean, if set do bitstream
+	authenticated using secure memory.
 - region-unfreeze-timeout-us : The maximum time in microseconds to wait for
 	bridges to successfully become enabled after the region has been
 	programmed.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/fpga/xilinx-pr-decoupler.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/fpga/xilinx-pr-decoupler.txt
@@ -7,13 +7,26 @@
 couple / enable the bridges which allows traffic to pass through the
 bridge normally.
 
+Xilinx LogiCORE Dynamic Function eXchange(DFX) AXI shutdown manager
+Softcore
+
+The Xilinx LogiCORE Dynamic Function eXchange(DFX) AXI shutdown manager
+manages one or more shutdown managers / fpga bridges.
+The controller can shutdown/passthrough the bridges which prevents
+AXI traffic from passing through the bridge. The controller safely
+handles AXI4MM and AXI4-Lite interfaces on a Reconfigurable Partition
+when it is undergoing dynamic reconfiguration (DFX), preventing system
+deadlock that can occur if AXI transactions are interrupted by DFX
+
 The Driver supports only MMIO handling. A PR region can have multiple
-PR Decouplers which can be handled independently or chained via decouple/
-decouple_status signals.
+PR Decouplers/AXI shutdown manager which can be handled independently
+or chained via decouple/ decouple_status signals.
 
 Required properties:
 - compatible		: Should contain "xlnx,pr-decoupler-1.00" followed by
-                          "xlnx,pr-decoupler"
+                          "xlnx,pr-decoupler" or
+			  "xlnx,dfx-axi-shutdown-manager-1.00" followed by
+			  "xlnx,dfx-axi-shutdown-manager"
 - regs			: base address and size for decoupler module
 - clocks		: input clock to IP
 - clock-names		: should contain "aclk"
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/fpga/xlnx,afi-fpga.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/fpga/xlnx,afi-fpga.txt
@@ -0,0 +1,61 @@
+Xilinx ZynqMp AFI interface Manager
+
+The Zynq UltraScale+ MPSoC Processing System core provides access from PL
+masters to PS internal peripherals, and memory through AXI FIFO interface
+(AFI) interfaces.
+
+Required properties:
+-compatible:		Should contain "xlnx,afi-fpga"
+-config-afi:		Pairs of  <regid value >
+
+The possible values of regid and values are
+ regid:		Regids of the register to be written possible values
+		0- AFIFM0_RDCTRL
+		1- AFIFM0_WRCTRL
+		2- AFIFM1_RDCTRL
+		3- AFIFM1_WRCTRL
+		4- AFIFM2_RDCTRL
+		5- AFIFM2_WRCTRL
+		6- AFIFM3_RDCTRL
+		7- AFIFM3_WRCTRL
+		8- AFIFM4_RDCTRL
+		9- AFIFM4_WRCTRL
+		10- AFIFM5_RDCTRL
+		11- AFIFM5_WRCTRL
+		12- AFIFM6_RDCTRL
+		13- AFIFM6_WRCTRL
+		14- AFIFS
+		15- AFIFS_SS2
+- value:	Array of values to be written.
+		for FM0_RDCTRL(0) the valid values-fabric width   2: 32-bit,1 : 64-bit ,0: 128-bit enabled
+		for FM0_WRCTRL(1) the valid values-fabric width   2: 32-bit,1 : 64-bit ,0: 128-bit enabled
+		for FM1_RDCTRL(2) the valid values-fabric width   2: 32-bit,1 : 64-bit ,0: 128-bit enabled
+		for FM1_WRCTRL(3) the valid values-fabric width   2: 32-bit,1 : 64-bit ,0: 128-bit enabled
+		for FM2_RDCTRL(4) the valid values-fabric width   2: 32-bit,1 : 64-bit ,0: 128-bit enabled
+		for FM2_WRCTRL(5) the valid values-fabric width   2: 32-bit,1 : 64-bit ,0: 128-bit enabled
+		for FM3_RDCTRL(6) the valid values-fabric width   2: 32-bit,1 : 64-bit ,0: 128-bit enabled
+		for FM3_WRCTRL(7) the valid values-fabric width   2: 32-bit,1 : 64-bit ,0: 128-bit enabled
+		for FM4_RDCTRL(8) the valid values-fabric width   2: 32-bit,1 : 64-bit ,0: 128-bit enabled
+		for FM4_WRCTRL(9) the valid values-fabric width   2: 32-bit,1 : 64-bit ,0: 128-bit enabled
+		for FM5_RDCTRL(10) the valid values-fabric width   2: 32-bit,1 : 64-bit ,0: 128-bit enabled
+		for FM5_WRCTRL(11) the valid values-fabric width   2: 32-bit,1 : 64-bit ,0: 128-bit enabled
+		for FM6_RDCTRL(12) the valid values-fabric width   2: 32-bit,1 : 64-bit ,0: 128-bit enabled
+		for FM6_WRCTRL(13) the valid values-fabric width   2: 32-bit,1 : 64-bit ,0: 128-bit enabled
+		for AFI_FA(14)
+			dw_ss1_sel	bits (11:10)
+			dw_ss0_sel	bits (9:8)
+				0x0: 32-bit AXI data width),
+				0x1: 64-bit AXI data width,
+				0x2: 128-bit AXI data
+		All other bits are 0 write ignored.
+
+		for AFI_FA(15)  selects for ss2AXI data width valid values
+					0x000: 32-bit AXI data width),
+					0x100: 64-bit AXI data width,
+					0x200: 128-bit AXI data
+
+Example:
+afi0: afi0 {
+	compatible = "xlnx,afi-fpga";
+	config-afi = <0 2>, <1 1>, <2 1>;
+};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/fpga/xlnx,versal-fpga.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/fpga/xlnx,versal-fpga.txt
@@ -0,0 +1,10 @@
+Device Tree versal-fpga bindings for the Versal SOC, Controlled
+using Versal SoC firmware interface.
+
+Required properties:
+- compatible: should contain "xlnx,versal-fpga"
+
+Example:
+	versal_fpga: fpga {
+		compatible = "xlnx,versal-fpga";
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/fpga/xlnx,zynq-afi-fpga.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/fpga/xlnx,zynq-afi-fpga.txt
@@ -0,0 +1,19 @@
+Xilinx Zynq AFI interface Manager
+
+The Zynq Processing System core provides access from PL masters to PS
+internal peripherals, and memory through AXI FIFO interface
+(AFI) interfaces.
+
+Required properties:
+-compatible:	Should contain "xlnx,zynq-afi-fpga"
+-reg:	Physical base address and size of the controller's register area.
+-xlnx,afi-buswidth :	Size of the afi bus width.
+			0: 64-bit AXI data width,
+			1: 32-bit AXI data width,
+
+Example:
+afi0: afi0 {
+	compatible = "xlnx,zynq-afi-fpga";
+	reg = <0xf8008000 0x1000>;
+	xlnx,afi-buswidth = <1>;
+};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/gpio/gpio-altera.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/gpio/gpio-altera.txt
@@ -9,8 +9,9 @@
   - The second cell is reserved and is currently unused.
 - gpio-controller : Marks the device node as a GPIO controller.
 - interrupt-controller: Mark the device node as an interrupt controller
-- #interrupt-cells : Should be 1. The interrupt type is fixed in the hardware.
+- #interrupt-cells : Should be 2. The interrupt type is fixed in the hardware.
   - The first cell is the GPIO offset number within the GPIO controller.
+  - The second cell is the interrupt trigger type and level flags.
 - interrupts: Specify the interrupt.
 - altr,interrupt-type: Specifies the interrupt trigger type the GPIO
   hardware is synthesized. This field is required if the Altera GPIO controller
@@ -38,6 +39,6 @@
 	altr,interrupt-type = <IRQ_TYPE_EDGE_RISING>;
 	#gpio-cells = <2>;
 	gpio-controller;
-	#interrupt-cells = <1>;
+	#interrupt-cells = <2>;
 	interrupt-controller;
 };
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/gpio/gpio-xilinx.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/gpio/gpio-xilinx.txt
@@ -8,11 +8,17 @@
 Required properties:
 - compatible : Should be "xlnx,xps-gpio-1.00.a"
 - reg : Address and length of the register set for the device
-- #gpio-cells : Should be two. The first cell is the pin number and the
-  second cell is used to specify optional parameters (currently unused).
+- #gpio-cells : Should be two or three. The first cell is the pin number,
+  The second cell is used to specify channel offset:
+		0 - first channel
+		8 - second channel
+  The third cell is optional and used to specify flags. Use the macros
+  defined in include/dt-bindings/gpio/gpio.h
 - gpio-controller : Marks the device node as a GPIO controller.
 
 Optional properties:
+- clock-names : Should be "s_axi_aclk"
+- clocks: Input clock specifier. Refer to common clock bindings.
 - interrupts : Interrupt mapping for GPIO IRQ.
 - xlnx,all-inputs : if n-th bit is setup, GPIO-n is input
 - xlnx,dout-default : if n-th bit is 1, GPIO-n default value is 1
@@ -23,6 +29,7 @@
 - xlnx,dout-default-2 : as above but the second channel
 - xlnx,gpio2-width : as above but for the second channel
 - xlnx,tri-default-2 : as above but for the second channel
+- xlnx,no-init : No initialisation at probe
 
 
 Example:
@@ -30,6 +37,8 @@
 	#gpio-cells = <2>;
 	compatible = "xlnx,xps-gpio-1.00.a";
 	gpio-controller ;
+	clock-names = "s_axi_aclk";
+	clocks = <&clkc 71>;
 	interrupt-parent = <&microblaze_0_intc>;
 	interrupts = < 6 2 >;
 	reg = < 0x40000000 0x10000 >;
@@ -44,3 +53,11 @@
 	xlnx,tri-default = <0xffffffff>;
 	xlnx,tri-default-2 = <0xffffffff>;
 } ;
+
+Example to demonstrate how reset-gpios property is used in drivers:
+
+driver: driver@80000000 {
+	compatible = "xlnx,driver";
+	reset-gpios = <&gpio 0 0 GPIO_ACTIVE_LOW>; /* gpio phandle, gpio pin-number, channel offset, flag state */
+	reg = <0x0 0x80000000 0x0 0x10000>;
+};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/gpio/gpio-zynq.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/gpio/gpio-zynq.txt
@@ -6,7 +6,9 @@
 			  - First cell is the GPIO line number
 			  - Second cell is used to specify optional
 			    parameters (unused)
-- compatible		: Should be "xlnx,zynq-gpio-1.0" or "xlnx,zynqmp-gpio-1.0"
+- compatible		: Should be "xlnx,zynq-gpio-1.0" or
+			  "xlnx,zynqmp-gpio-1.0" or "xlnx,versal-gpio-1.0
+			  or "xlnx,pmc-gpio-1.0
 - clocks		: Clock specifier (see clock bindings for details)
 - gpio-controller	: Marks the device node as a GPIO controller.
 - interrupts		: Interrupt specifier (see interrupt bindings for
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/gpio/sgpio-aspeed.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/gpio/sgpio-aspeed.txt
@@ -20,8 +20,9 @@
 - gpio-controller : Marks the device node as a GPIO controller
 - interrupts : Interrupt specifier, see interrupt-controller/interrupts.txt
 - interrupt-controller : Mark the GPIO controller as an interrupt-controller
-- ngpios : number of GPIO lines, see gpio.txt
-  (should be multiple of 8, up to 80 pins)
+- ngpios : number of *hardware* GPIO lines, see gpio.txt. This will expose
+  2 software GPIOs per hardware GPIO: one for hardware input, one for hardware
+  output. Up to 80 pins, must be a multiple of 8.
 - clocks : A phandle to the APB clock for SGPM clock division
 - bus-frequency : SGPM CLK frequency
 
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/gpu/samsung-rotator.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/gpu/samsung-rotator.yaml
@@ -0,0 +1,48 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/gpu/samsung-rotator.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Samsung SoC Image Rotator
+
+maintainers:
+  - Inki Dae <inki.dae@samsung.com>
+
+properties:
+  compatible:
+    enum:
+      - "samsung,s5pv210-rotator"
+      - "samsung,exynos4210-rotator"
+      - "samsung,exynos4212-rotator"
+      - "samsung,exynos5250-rotator"
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  clock-names:
+    items:
+    - const: rotator
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - clock-names
+
+examples:
+  - |
+    rotator@12810000 {
+        compatible = "samsung,exynos4210-rotator";
+        reg = <0x12810000 0x1000>;
+        interrupts = <0 83 0>;
+        clocks = <&clock 278>;
+        clock-names = "rotator";
+    };
+
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/hwmon/tps544.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/hwmon/tps544.txt
@@ -0,0 +1,14 @@
+TPS544B25 power regulator
+
+This power regulator driver supports voltage read/write and
+current calibration and readback.
+
+Required properties:
+- compatible: should be "ti,tps544"
+- reg: I2C slave address
+
+Example:
+tps544@24 {
+	compatible = "ti,tps544";
+	reg = <0x24>;
+};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml
@@ -85,7 +85,7 @@
       Must be the device tree identifier of the over-sampling
       mode pins. As the line is active high, it should be marked
       GPIO_ACTIVE_HIGH.
-    maxItems: 1
+    maxItems: 3
 
   adi,sw-mode:
     description:
@@ -128,9 +128,9 @@
                 adi,conversion-start-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>;
                 reset-gpios = <&gpio 27 GPIO_ACTIVE_HIGH>;
                 adi,first-data-gpios = <&gpio 22 GPIO_ACTIVE_HIGH>;
-                adi,oversampling-ratio-gpios = <&gpio 18 GPIO_ACTIVE_HIGH
-                                                &gpio 23 GPIO_ACTIVE_HIGH
-                                                &gpio 26 GPIO_ACTIVE_HIGH>;
+                adi,oversampling-ratio-gpios = <&gpio 18 GPIO_ACTIVE_HIGH>,
+                                               <&gpio 23 GPIO_ACTIVE_HIGH>,
+                                               <&gpio 26 GPIO_ACTIVE_HIGH>;
                 standby-gpios = <&gpio 24 GPIO_ACTIVE_LOW>;
                 adi,sw-mode;
         };
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/iio/adc/ti,ina260.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/iio/adc/ti,ina260.yaml
@@ -0,0 +1,57 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/adc/ti,ina260.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments INA260 power monitor
+
+maintainers:
+  - Shubhrajyoti Datta <shubhrajyoti.datta@xilinx.com>
+
+description: |
+  The INA260 is a digital-output, current, power and voltage monitor
+  with an I2C and SMBUS compatible interface with an integrated shunt
+  resistor. It features up to 16 programmable addresses on I2C compatible
+  interface. Datasheet - https://www.ti.com/lit/ds/symlink/ina260.pdf?ts=1608607288391
+
+properties:
+  compatible:
+    enum:
+      - ti,ina260
+
+  reg:
+    description: |
+      The 7-bits long I2c address of the device
+
+  "#io-channel-cells":
+    const: 1
+
+  interrupts:
+    description: |
+      IRQ line for the device
+
+  label:
+    description: |
+      A symbolic name for the device
+
+required:
+  - compatible
+  - reg
+  - "#io-channel-cells"
+
+additionalProperties: false
+
+examples:
+  - |
+    i2c {
+      #address-cells = <1>;
+      #size-cells = <0>;
+
+      ina260@40 {
+        compatible = "ti,ina260";
+        reg = <0x40>;
+        #io-channel-cells = <1>;
+      };
+    };
+...
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/iio/adc/xilinx-ams.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/iio/adc/xilinx-ams.txt
@@ -0,0 +1,159 @@
+Xilinx AMS device driver
+
+The AMS includes an ADC as well as on-chip sensors that can be used to
+sample external voltages and monitor on-die operating conditions, such as
+temperature and supply voltage levels. The AMS has two SYSMON blocks.
+PL-SYSMON block is capable of monitoring off chip voltage and temperature.
+PL-SYSMON block has DRP, JTAG and I2C interface to enable monitoring from
+external master. Out of this interface currenlty only DRP is supported.
+Other block PS-SYSMON is memory mapped to PS. Both of block has built-in
+alarm generation logic that is used to interrupt the processor based on
+condition set.
+
+All designs should have AMS register, but PS and PL are optional depending on
+the design. The driver can work with only PS, only PL and both PS and PL
+configurations. Please specify registers according to your design. DTS file
+should always have AMS module property. Providing PS & PL module is optional.
+
+Required properties:
+	- compatible: Should be "xlnx,zynqmp-ams"
+	- reg:  Should specify AMS register space
+	- interrupts: Interrupt number for the AMS control interface
+	- interrupt-names: Interrupt name, must be "ams-irq"
+	- clocks: Should contain a clock specifier for the device
+	- ranges: keep the property empty to map child address space
+	          (for PS and/or PL) nodes 1:1 onto the parent address
+	          space
+
+AMS device tree subnode:
+	- compatible: Should be "xlnx,zynqmp-ams-ps" or "xlnx,zynqmp-ams-pl"
+	- reg:  Register space for PS or PL
+
+Optional properties:
+
+Following optional property only valid for PL.
+	- xlnx,ext-channels: List of external channels that are connected to the
+	                     AMS PL module.
+
+	  The child nodes of this node represent the external channels which are
+	  connected to the AMS Module. If the property is not present
+	  no external channels will be assumed to be connected.
+
+	  Each child node represents one channel and has the following
+	  properties:
+		Required properties:
+			* reg: Pair of pins the channel is connected to.
+				0: VP/VN
+				1: VUSER0
+				2: VUSER1
+				3: VUSER3
+				4: VUSER4
+				5: VAUXP[0]/VAUXN[0]
+				6: VAUXP[1]/VAUXN[1]
+				...
+				20: VAUXP[15]/VAUXN[15]
+			  Note each channel number should only be used at most
+			  once.
+		Optional properties:
+			* xlnx,bipolar: If set the channel is used in bipolar
+			  mode.
+
+
+Example:
+	xilinx_ams: ams@ffa50000 {
+		compatible = "xlnx,zynqmp-ams";
+		interrupt-parent = <&gic>;
+		interrupts = <0 56 4>;
+		interrupt-names = "ams-irq";
+		clocks = <&clkc 70>;
+		reg = <0x0 0xffa50000 0x0 0x800>;
+		reg-names = "ams-base";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		ams_ps: ams_ps@ffa50800 {
+			compatible = "xlnx,zynqmp-ams-ps";
+			reg = <0x0 0xffa50800 0x0 0x400>;
+		};
+
+		ams_pl: ams_pl@ffa50c00 {
+			compatible = "xlnx,zynqmp-ams-pl";
+			reg = <0x0 0xffa50c00 0x0 0x400>;
+			xlnx,ext-channels {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				channel@0 {
+					reg = <0>;
+					xlnx,bipolar;
+				};
+				channel@1 {
+					reg = <1>;
+				};
+				channel@8 {
+					reg = <8>;
+					xlnx,bipolar;
+				};
+			};
+		};
+	};
+
+AMS Channels Details:
+
+Sysmon Block	|Channel|			Details					|Measurement
+		 Number									 Type
+---------------------------------------------------------------------------------------------------------
+AMS CTRL	|0	|System PLLs voltage measurement, VCC_PSPLL.			|Voltage
+		|1	|Battery voltage measurement, VCC_PSBATT.			|Voltage
+		|2	|PL Internal voltage measurement, VCCINT.			|Voltage
+		|3	|Block RAM voltage measurement, VCCBRAM.			|Voltage
+		|4	|PL Aux voltage measurement, VCCAUX.				|Voltage
+		|5	|Voltage measurement for six DDR I/O PLLs, VCC_PSDDR_PLL.	|Voltage
+		|6	|VCC_PSINTFP_DDR voltage measurement.				|Voltage
+---------------------------------------------------------------------------------------------------------
+PS Sysmon	|7	|LPD temperature measurement.					|Temperature
+		|8	|FPD Temperature Measurment (REMOTE).				|Temperature
+		|9	|VCC PS LPD voltage measurement (supply1).			|Voltage
+		|10	|VCC PS FPD voltage measurement (supply2).			|Voltage
+		|11	|PS Aux voltage reference (supply3).				|Voltage
+		|12	|DDR I/O VCC voltage measurement.				|Voltage
+		|13	|PS IO Bank 503 voltage measurement (supply5).			|Voltage
+		|14	|PS IO Bank 500 voltage measurement (supply6).			|Voltage
+		|15	|VCCO_PSIO1 voltage measurement.				|Voltage
+		|16	|VCCO_PSIO2 voltage measurement.				|Voltage
+		|17	|VCC_PS_GTR voltage measurement (VPS_MGTRAVCC).			|Voltage
+		|18	|VTT_PS_GTR voltage measurement (VPS_MGTRAVTT).			|Voltage
+		|19	|VCC_PSADC voltage measurement.					|Voltage
+---------------------------------------------------------------------------------------------------------
+PL Sysmon	|20	|PL Temperature measurement.					|Temperature
+		|21	|PL Internal Voltage Voltage measurement, VCCINT.		|Voltage
+		|22	|PL Auxiliary Voltage measurement, VCCAUX.			|Voltage
+		|23	|ADC Reference P+ Voltage measurement.				|Voltage
+		|24	|ADC Reference N- Voltage measurement.				|Voltage
+		|25	|PL Block RAM Voltage measurement, VCCBRAM.			|Voltage
+		|26	|LPD Internal Voltage measurement, VCC_PSINTLP (supply4).	|Voltage
+		|27	|FPD Internal Voltage measurement, VCC_PSINTFP (supply5).	|Voltage
+		|28	|PS Auxiliary Voltage measurement (supply6).			|Voltage
+		|29	|PL VCCADC Voltage measurement (vccams).			|Voltage
+		|30	|Differencial analog input signal Voltage measurment.		|Voltage
+		|31	|VUser0 Voltage measurement (supply7).				|Voltage
+		|32	|VUser1 Voltage measurement (supply8).				|Voltage
+		|33	|VUser2 Voltage measurement (supply9).				|Voltage
+		|34	|VUser3 Voltage measurement (supply10).				|Voltage
+		|35	|Auxiliary ch 0 Voltage measurement (VAux0).			|Voltage
+		|36	|Auxiliary ch 1 Voltage measurement (VAux1).			|Voltage
+		|37	|Auxiliary ch 2 Voltage measurement (VAux2).			|Voltage
+		|38	|Auxiliary ch 3 Voltage measurement (VAux3).			|Voltage
+		|39	|Auxiliary ch 4 Voltage measurement (VAux4).			|Voltage
+		|40	|Auxiliary ch 5 Voltage measurement (VAux5).			|Voltage
+		|41	|Auxiliary ch 6 Voltage measurement (VAux6).			|Voltage
+		|42	|Auxiliary ch 7 Voltage measurement (VAux7).			|Voltage
+		|43	|Auxiliary ch 8 Voltage measurement (VAux8).			|Voltage
+		|44	|Auxiliary ch 9 Voltage measurement (VAux9).			|Voltage
+		|45	|Auxiliary ch 10 Voltage measurement (VAux10).			|Voltage
+		|46	|Auxiliary ch 11 Voltage measurement (VAux11).			|Voltage
+		|47	|Auxiliary ch 12 Voltage measurement (VAux12).			|Voltage
+		|48	|Auxiliary ch 13 Voltage measurement (VAux13).			|Voltage
+		|49	|Auxiliary ch 14 Voltage measurement (VAux14).			|Voltage
+		|50	|Auxiliary ch 15 Voltage measurement (VAux15).			|Voltage
+---------------------------------------------------------------------------------------------------------
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/iio/adc/xilinx-xadc.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/iio/adc/xilinx-xadc.txt
@@ -15,6 +15,8 @@
 		  configuration interface to interface to the XADC hardmacro.
 		* "xlnx,axi-xadc-1.00.a": When using the axi-xadc pcore to
 		  interface to the XADC hardmacro.
+		* "xlnx,axi-sysmon-1.3": When using the axi-sysmon pcore to
+		  interface to the sysmon hardmacro.
 	- reg: Address and length of the register set for the device
 	- interrupts: Interrupt for the XADC control interface.
 	- clocks: When using the ZYNQ this must be the ZYNQ PCAP clock,
@@ -103,6 +105,23 @@
 
 		xlnx,channels {
 			#address-cells = <1>;
+			#size-cells = <0>;
+			channel@0 {
+				reg = <0>;
+				xlnx,bipolar;
+			};
+		};
+	};
+
+	xadc@44a00000 {
+		compatible = "xlnx,axi-sysmon-1.3";
+		interrupt-parent = <&axi_intc_0>;
+		interrupts = <2 2>;
+		clocks = <&clk_bus_0>;
+		reg = <0x44a00000 0x10000>;
+
+		xlnx,channels {
+			#address-cells = <1>;
 			#size-cells = <0>;
 			channel@0 {
 				reg = <0>;
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/iio/adc/xlnx,versal-sysmon.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/iio/adc/xlnx,versal-sysmon.yaml
@@ -0,0 +1,144 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright 2019 - 2020 Xilinx Inc.
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/adc/xlnx,versal-sysmon.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Xilinx Versal Sysmon Linux Driver
+
+maintainers:
+  - Anand Ashok Dumbre <anand.ashok.dumbre@xilinx.com>
+
+description: |
+  Sysmon Driver uses Linux IIO framework which was used to abstract the supply
+  voltages and temperatures across the chip as Voltage and Temperature
+  Channels in the framework. Since there are only 160 supply voltage registers
+  and 184 measurement points, there is no constant mapping of supply voltage
+  registers and the measurement points. User has to select the voltages to
+  monitor in design tool. Depending on the selection, a voltage supply gets
+  mapped to one of the supply registers. So, this mapping information is
+  provided to the driver via a device tree. Depending on the number of supplies
+  enabled in the design, the device tree will contain the information of name
+  of the supply enabled and the supply register it maps to.
+
+properties:
+  compatible:
+    items:
+      - enum:
+         - xlnx,versal-sysmon
+
+  reg:
+    description: Sysmon Registers
+    maxItems: 1
+
+  interrupts:
+    description: interrupt line for Sysmon
+    maxItems: 1
+
+  '#address-cells':
+    const: 1
+
+  '#size-cells':
+    const: 0
+
+  xlnx,numchannels:
+    $ref: /schemas/types.yaml#/definitions/uint8
+    maxItems: 1
+    description: |
+      Number of supply channels enabled in the design.
+      Possible values 0 - 160. Based on this value, child supply nodes will
+      be created
+
+patternProperties:
+  "^supply@([0-9]{1,2}|1[0-5][0-9])$":
+    type: object
+    description: |
+      Represents the supplies configured in the design.
+
+    properties:
+      reg:
+        $ref: /schemas/types.yaml#/definitions/uint32
+        minimum: 0
+        maximum: 159
+        description:
+          The supply number associated with the voltage.
+
+      xlnx,name:
+        $ref: /schemas/types.yaml#/definitions/string
+        description:
+          Name of the supply enabled
+
+      xlnx,bipolar:
+        $ref: /schemas/types.yaml#/definitions/flag
+        description:
+          If the supply has a bipolar type and the output will be signed
+
+    required:
+      - reg
+      - xlnx,name
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - xlnx,numchannels
+
+additionalProperties: false
+
+examples:
+  - |
+    bus {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        sysmon@f1270000 {
+            compatible = "xlnx,versal-sysmon";
+            reg = <0 0xf1270000 0 0x4000>;
+            interrupts = <0 0x90 0x4>;
+            xlnx,numchannels = /bits/8 <8>;
+            #address-cells = <1>;
+            #size-cells = <0>;
+            supply@0 {
+                    reg = <0>;
+                    xlnx,name = "vccint";
+            };
+
+            supply@31 {
+                    reg = <31>;
+                    xlnx,name = "vccsoc";
+            };
+
+            supply@32 {
+                    reg = <32>;
+                    xlnx,bipolar;
+                    xlnx,name = "vccram";
+            };
+
+            supply@63 {
+                    reg = <63>;
+                    xlnx,bipolar;
+                    xlnx,name = "vccaux";
+            };
+
+            supply@64 {
+                    reg = <64>;
+                    xlnx,name = "vccbram";
+            };
+
+            supply@95 {
+                    reg = <95>;
+                    xlnx,name = "gt_avaux";
+            };
+
+            supply@96 {
+                    reg = <96>;
+                    xlnx,name = "gt_vccaux";
+            };
+
+            supply@159 {
+                    reg = <159>;
+                    xlnx,name = "vccint_ir";
+            };
+        };
+    };
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/iio/iio-bindings.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/iio/iio-bindings.txt
@@ -18,12 +18,17 @@
 		   with a single IIO output and 1 for nodes with multiple
 		   IIO outputs.
 
+Optional properties:
+label:		   A symbolic name for the device.
+
+
 Example for a simple configuration with no trigger:
 
 	adc: voltage-sensor@35 {
 		compatible = "maxim,max1139";
 		reg = <0x35>;
 		#io-channel-cells = <1>;
+		label = "voltage_feedback_group1";
 	};
 
 Example for a configuration with trigger:
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt
@@ -21,7 +21,7 @@
 
 Example:
 	mux: mux-controller {
-		compatible = "mux-gpio";
+		compatible = "gpio-mux";
 		#mux-control-cells = <0>;
 
 		mux-gpios = <&pioA 0 GPIO_ACTIVE_HIGH>,
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml
@@ -138,6 +138,7 @@
       containing a set of sub-nodes.
     patternProperties:
       "^interrupt-partition-[0-9]+$":
+        type: object
         properties:
           affinity:
             $ref: /schemas/types.yaml#/definitions/phandle-array
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/interrupt-controller/ti,sci-intr.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/interrupt-controller/ti,sci-intr.txt
@@ -55,7 +55,7 @@
 			corresponds to a range of host irqs.
 
 For more details on TISCI IRQ resource management refer:
-http://downloads.ti.com/tisci/esd/latest/2_tisci_msgs/rm/rm_irq.html
+https://downloads.ti.com/tisci/esd/latest/2_tisci_msgs/rm/rm_irq.html
 
 Example:
 --------
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/interrupt-controller/xilinx,intc.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/interrupt-controller/xilinx,intc.txt
@@ -0,0 +1,56 @@
+Xilinx Interrupt Controller
+
+The controller is a soft IP core that is configured at build time for the
+number of interrupts and the type of each interrupt. These details cannot
+be changed at run time.
+
+Required properties:
+
+- compatible : should be "xlnx,xps-intc-1.00.a"
+- reg : Specifies base physical address and size of the registers.
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : Specifies the number of cells needed to encode an
+		     interrupt source. The value shall be a minimum of 1.
+		     The Xilinx device trees typically use 2 but the 2nd value
+		     is not used.
+- xlnx,kind-of-intr : A 32 bit value specifying the interrupt type for each
+		      possible interrupt (1 = edge, 0 = level). The interrupt
+		      type typically comes in thru the device tree node of
+		      the interrupt generating device, but in this case
+		      the interrupt type is determined by the interrupt
+		      controller based on how it was implemented.
+- xlnx,num-intr-inputs: Specifies the number of interrupts supported
+		        by the specific implementation of the controller (1-32).
+
+Optional properties:
+- interrupt-parent : Specifies an interrupt controller from which it is
+		     chained (cascaded).
+- interrupts : Specifies the interrupt of the parent controller from which
+	       it is chained.
+
+Example:
+
+axi_intc_0: interrupt-controller@41800000 {
+	#interrupt-cells = <2>;
+	compatible = "xlnx,xps-intc-1.00.a";
+	interrupt-controller;
+	reg = <0x41800000 0x10000>;
+	xlnx,kind-of-intr = <0x1>;
+	xlnx,num-intr-inputs = <0x1>;
+};
+
+Chained Example:
+
+The interrupt is chained to hardware interrupt 61 (29 + 32) of the GIC
+for Zynq.
+
+axi_intc_0: interrupt-controller@41800000 {
+	#interrupt-cells = <2>;
+	compatible = "xlnx,xps-intc-1.00.a";
+	interrupt-controller;
+	interrupt-parent = <&ps7_scugic_0>;
+	interrupts = <0 29 4>;
+	reg = <0x41800000 0x10000>;
+	xlnx,kind-of-intr = <0x1>;
+	xlnx,num-intr-inputs = <0x1>;
+};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/mailbox/xlnx,zynqmp-ipi-mailbox.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/mailbox/xlnx,zynqmp-ipi-mailbox.txt
@@ -87,7 +87,7 @@
 		ranges;
 
 		/* APU<->RPU0 IPI mailbox controller */
-		ipi_mailbox_rpu0: mailbox@ff90400 {
+		ipi_mailbox_rpu0: mailbox@ff990400 {
 			reg = <0xff990400 0x20>,
 			      <0xff990420 0x20>,
 			      <0xff990080 0x20>,
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/media/i2c/onnn,ap1302.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/media/i2c/onnn,ap1302.yaml
@@ -0,0 +1,202 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/i2c/onnn,ap1302.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ON Semiconductor AP1302 Advanced Image Coprocessor
+
+maintainers:
+  - Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+  - Anil Kumar M <anil.mamidala@xilinx.com>
+
+description: |-
+  The AP1302 is a standalone ISP for ON Semiconductor sensors. It interfaces to
+  up to two RAW CMOS sensors over MIPI CSI-2 connections, processes the two
+  video streams and outputs YUV frames to the host over a MIPI CSI-2 interface.
+  Frames are output side by side or on two virtual channels.
+
+  The sensors must be identical. They are connected to the AP1302 on dedicated
+  I2C buses, and are controlled by the AP1302 firmware. They are not accessible
+  from the host.
+
+properties:
+  compatible:
+    const: onnn,ap1302
+
+  reg:
+    description: I2C device address.
+    maxItems: 1
+
+  clocks:
+    description: Reference to the CLK clock.
+    maxItems: 1
+
+  reset-gpios:
+    description: Reference to the GPIO connected to the RST pin (active low).
+    maxItems: 1
+
+  standby-gpios:
+    description:
+      Reference to the GPIO connected to the STANDBY pin (active high).
+    maxItems: 1
+
+  port:
+    $ref: /schemas/graph.yaml#/$defs/port-base
+    unevaluatedProperties: false
+    description: MIPI CSI-2 output interface to the host.
+
+    properties:
+      endpoint:
+        $ref: /schemas/graph.yaml#/$defs/endpoint-base
+        unevaluatedProperties: false
+
+        properties:
+          clock-noncontinuous:
+            type: boolean
+
+          data-lanes:
+            oneOf:
+              - items:
+                  - const: 1
+              - items:
+                  - const: 1
+                  - const: 2
+              - items:
+                  - const: 1
+                  - const: 2
+                  - const: 3
+                  - const: 4
+
+        required:
+          - data-lanes
+
+  sensors:
+    type: object
+    description: List of connected sensors
+
+    properties:
+      "#address-cells":
+        const: 1
+
+      "#size-cells":
+        const: 0
+
+      onnn,model:
+        $ref: "/schemas/types.yaml#/definitions/string"
+        description: |
+          Model of the connected sensors. Must be a valid compatible string.
+
+          If no sensor is connected, this property must no be specified, and
+          the AP1302 can be used with it's internal test pattern generator.
+
+    patternProperties:
+      "^sensor@[01]":
+        type: object
+        description: |
+          Sensors connected to the first and second input, with one node per
+          sensor.
+
+        properties:
+          reg:
+            description: AP1302 input port number
+            maxItems: 1
+
+        patternProperties:
+          ".*-supply":
+            description: Power supplies for the sensor
+
+        required:
+          - reg
+
+        additionalProperties: false
+
+    required:
+      - "#address-cells"
+      - "#size-cells"
+
+    # How can we express that onnn,model requires one sensor object to be set ?
+
+    additionalProperties: false
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - port
+  - sensors
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        camera@3c {
+            compatible = "onnn,ap1302";
+            reg = <0x3c>;
+
+            clocks = <&clk24mhz>;
+
+            reset-gpios = <&pio 102 GPIO_ACTIVE_LOW>;
+            standby-gpios = <&pio 40 GPIO_ACTIVE_HIGH>;
+
+            port {
+                isp1_out: endpoint {
+                    remote-endpoint = <&seninf_in1>;
+                    data-lanes = <1 2 3 4>;
+                };
+            };
+
+            sensors {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                onnn,model = "onnn,ar0144";
+
+                sensor@0 {
+                    reg = <0>;
+
+                    vdd-supply = <&mt6358_vcamd_reg>;
+                    vaa-supply = <&mt6358_vcama1_reg>;
+                    vddio-supply = <&reg_1p8v_ext>;
+                };
+            };
+        };
+    };
+
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        camera@3c {
+            compatible = "onnn,ap1302";
+            reg = <0x3c>;
+
+            clocks = <&topckgen 0>;
+
+            reset-gpios = <&pio 102 GPIO_ACTIVE_LOW>;
+            standby-gpios = <&pio 40 GPIO_ACTIVE_HIGH>;
+
+            port {
+                isp2_out: endpoint {
+                    remote-endpoint = <&seninf_in1>;
+                    data-lanes = <1 2>;
+                };
+            };
+
+            sensors {
+                #address-cells = <1>;
+                #size-cells = <0>;
+            };
+        };
+    };
+
+...
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/media/xilinx/xlnx,axis-broadcaster.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/media/xilinx/xlnx,axis-broadcaster.yaml
@@ -0,0 +1,179 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/xilinx/xlnx,axis-broadcaster.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Xilinx AXI4-Stream Broadcaster
+
+maintainers:
+  - Ronak Shah <ronak.shah@xilinx.com>
+
+description: |
+  The AXI4-Stream Broadcaster provides a solution for replicating a single
+  inbound AXI4-Stream interface into multiple outbound AXI4-Stream interfaces.
+  Support for up to 16 outbound AXI4-Stream interfaces is provided.
+  For more details, Please refer to PG085 AXI4-Stream Infrastructure IP Suite.
+
+properties:
+  compatible:
+    items:
+      - enum:
+          - xlnx,axis-broadcaster-1.1
+
+  # See ./video-interfaces.txt for details
+  ports:
+    type: object
+
+    properties:
+      "#address-cells":
+        const: 1
+
+      "#size-cells":
+        const: 0
+
+      port@0:
+        type: object
+        description: |
+          Input/sink port node, describing module connected to the
+          input of AXI4-Stream Broadcaster.
+
+        properties:
+          reg:
+            description: |
+              Input/sink port number.
+            const: 0
+
+          endpoint:
+            type: object
+
+            properties:
+              remote-endpoint: true
+
+            required:
+              - remote-endpoint
+
+            additionalProperties: false
+
+        required:
+          - reg
+          - endpoint
+
+        additionalProperties: false
+
+    patternProperties:
+      "^port@([1-9]|1[0-6])$":
+        type: object
+        description: |
+          Output/source port node, describing module connected to the
+          output of AXI4-Stream Broadcaster.
+
+        properties:
+          reg:
+            description: |
+              Output/source port number. It can have min 2 ports and
+              max 16 ports, numbered from 1 to 16.
+            items:
+              minimum: 1
+              maximum: 16
+
+          endpoint:
+            type: object
+
+            properties:
+              remote-endpoint: true
+
+            required:
+              - remote-endpoint
+
+            additionalProperties: false
+
+        required:
+          - reg
+          - endpoint
+
+        additionalProperties: false
+
+    required:
+      - "#address-cells"
+      - "#size-cells"
+      - port@0
+      - port@1
+      - port@2
+
+    additionalProperties: false
+
+required:
+  - compatible
+  - ports
+
+additionalProperties: false
+
+examples:
+  - |
+    axis_broadcaster_0 {
+        compatible = "xlnx,axis-broadcaster-1.1";
+
+        ports {
+            #address-cells = <1>;
+            #size-cells = <0>;
+
+            port@0 {
+                /* Sink port */
+                reg = <0>;
+                axis_broad_0_in: endpoint {
+                    remote-endpoint = <&v_proc_ss_out>;
+                };
+            };
+            port@1 {
+                /* Source port */
+                reg = <1>;
+                axis_broad_0_out1: endpoint {
+                    remote-endpoint = <&v_frmbuf_wr_0_in>;
+                };
+            };
+            port@2 {
+                /* Source port */
+                reg = <2>;
+                axis_broad_0_out2: endpoint {
+                    remote-endpoint = <&v_frmbuf_wr_1_in>;
+                };
+            };
+            port@3 {
+                /* Source port */
+                reg = <3>;
+                axis_broad_0_out3: endpoint {
+                    remote-endpoint = <&v_frmbuf_wr_2_in>;
+                };
+            };
+            port@4 {
+                /* Source port */
+                reg = <4>;
+                axis_broad_0_out4: endpoint {
+                    remote-endpoint = <&v_frmbuf_wr_3_in>;
+                };
+            };
+            port@5 {
+                /* Source port */
+                reg = <5>;
+                axis_broad_0_out5: endpoint {
+                    remote-endpoint = <&v_frmbuf_wr_4_in>;
+                };
+            };
+            port@6 {
+                /* Source port */
+                reg = <6>;
+                axis_broad_0_out6: endpoint {
+                    remote-endpoint = <&v_frmbuf_wr_5_in>;
+                };
+            };
+            port@7 {
+                /* Source port */
+                reg = <7>;
+                axis_broad_0_out7: endpoint {
+                    remote-endpoint = <&v_frmbuf_wr_6_in>;
+                };
+            };
+        };
+    };
+...
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/media/xilinx/xlnx,csi2rxss.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/media/xilinx/xlnx,csi2rxss.txt
@@ -0,0 +1,129 @@
+
+Xilinx MIPI CSI2 Receiver Subsystem (CSI2RxSS)
+----------------------------------------------
+
+The Xilinx MIPI CSI2 Receiver Subsystem is used to capture MIPI CSI2 traffic
+from compliant camera sensors and send the output as AXI4 Stream video data
+for image processing. The subsystem consists of a MIPI DPHY in slave mode
+which captures the data packets. This is passed along the MIPI CSI2 IP which
+extracts the packet data. This data is taken in by the Video Format Bridge
+(VFB) if selected and converted into AXI4 Stream video data at selected
+pixels per clock as per AXI4-Stream Video IP and System Design UG934.
+
+For more details, please refer to PG232 MIPI CSI-2 Receiver Subsystem v4.1
+
+Required properties:
+
+- compatible: Must contain "xlnx,mipi-csi2-rx-subsystem-5.0" or
+  "xlnx,mipi-csi2-rx-subsystem-4.1" or "xlnx,mipi-csi2-rx-subsystem-4.0".
+  The older strings "xlnx,mipi-csi2-rx-subsystem-2.0" and
+  "xlnx,mipi-csi2-rx-subsystem-3.0" are deprecated.
+
+- reg: Physical base address and length of the registers set for the device.
+
+- xlnx,max-lanes: Maximum active lanes in the design.
+
+- xlnx,en-active-lanes: Enable Active lanes configuration in Protocol
+  Configuration Register.
+
+- xlnx,vc: Virtual Channel, specifies virtual channel number to be filtered.
+  If this is 4 then all virtual channels are allowed.
+
+- xlnx,csi-pxl-format: This denotes the CSI Data type selected in hw design.
+  Packets other than this data type (except for RAW8 and User defined data
+  types) will be filtered out. Possible values are RAW6, RAW7, RAW8, RAW10,
+  RAW12, RAW14, RAW16, RAW20, RGB444, RGB555, RGB565, RGB666, RGB888,
+  YUV4228bit and YUV420_8bit.
+
+- xlnx,vfb: Video Format Bridge, Denotes if Video Format Bridge is selected
+  so that output is as per AXI stream documented in UG934.
+
+- xlnx,ppc: Pixels per clock, Number of pixels to be transferred per pixel
+  clock. This is valid only if xlnx,vfb property is set to 1.
+
+- xlnx,axis-tdata-width: AXI Stream width, This denotes the AXI Stream width.
+  It depends on Data type chosen, Video Format Bridge enabled/disabled and
+  pixels per clock. If VFB is disabled then its value is either 0x20 (32 bit)
+  or 0x40(64 bit) width.
+
+- xlnx,video-format, xlnx,video-width: Video format and width, as defined in
+  video.txt.
+
+- port: Video port, using the DT bindings defined in ../video-interfaces.txt.
+  The CSI 2 Rx Subsystem has a two ports, one input port for connecting to
+  camera sensor and other is output port.
+
+- data-lanes: The number of data lanes through which CSI2 Rx Subsystem is
+  connected to the camera sensor as per video-interfaces.txt
+
+- clocks: List of phandles to AXI Lite, Video and 200 MHz DPHY clocks.
+
+- clock-names: Must contain "lite_aclk", "video_aclk" and "dphy_clk_200M" in
+  the same order as clocks listed in clocks property.
+
+Optional Properties
+
+- xlnx,en-vcx: When present, the max number of virtual channels can be 16 else 4.
+
+- reset-gpios: Optional specifier for a GPIO that asserts video_aresetn.
+
+- xlnx,dphy-present: Boolean to indicate whether DPHY register interface is
+  enabled or not. When this is present and compatible string is
+  xlnx,mipi-csi2-rx-subsystem-5.0 then DPHY offset is 0x1000 (4K) else
+  it is 0x1_0000 (64K).
+
+- xlnx,iic-present: Boolean to show whether subsystem's IIC is present or not.
+  This affects the base address of the DPHY. This can't be present when the
+  compatible string is "xlnx,mipi-csi2-rx-subsystem-4.1" or later.
+
+Example:
+
+	csiss_1: csiss@a0020000 {
+		compatible = "xlnx,mipi-csi2-rx-subsystem-5.0";
+		reg = <0x0 0xa0020000 0x0 0x20000>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 95 4>;
+
+		reset-gpios = <&gpio 81 1>;
+		xlnx,max-lanes = <0x4>;
+		xlnx,en-active-lanes;
+		xlnx,dphy-present;
+		xlnx,iic-present;
+		xlnx,vc = <0x4>;
+		xlnx,csi-pxl-format = "RAW8";
+		xlnx,vfb;
+		xlnx,ppc = <0x4>;
+		xlnx,axis-tdata-width = <0x20>;
+
+		clock-names = "lite_aclk", "dphy_clk_200M", "video_aclk";
+		clocks = <&misc_clk_0>, <&misc_clk_1>, <&misc_clk_2>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+
+				xlnx,video-format = <XVIP_VF_YUV_422>;
+				xlnx,video-width = <8>;
+				csiss_out: endpoint {
+					remote-endpoint = <&vcap_csiss_in>;
+				};
+			};
+			port@1 {
+				reg = <1>;
+
+				xlnx,video-format = <XVIP_VF_YUV_422>;
+				xlnx,video-width = <8>;
+
+				csiss_in: endpoint {
+					data-lanes = <1 2 3 4>;
+					/* MIPI CSI2 Camera handle */
+					remote-endpoint = <&vs2016_out>;
+				};
+
+			};
+
+		};
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/media/xilinx/xlnx,mem2mem.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/media/xilinx/xlnx,mem2mem.txt
@@ -0,0 +1,25 @@
+Xilinx Video IP MEM2MEM Pipeline (XVIM2M)
+----------------------------------------
+
+Xilinx video IP mem2mem pipeline processes DMA transfers to achieve memory
+copy from one physical memory to other. The data is copied by employing two
+DMA transfers memory to device and device to memory transactions one after
+the other. The DT node of the XVIM2M represents as a top level node of the
+pipeline and defines mappings between DMAs.
+
+Required properties:
+
+- compatible: Must be "xlnx,mem2mem".
+
+- dmas, dma-names: List of two DMA specifier and identifier strings (as
+  defined in Documentation/devicetree/bindings/dma/dma.txt) per port.
+  Identifier string of one DMA channel should be "tx" and other should be
+  "rx".
+
+Example:
+
+	video_m2m {
+		compatible = "xlnx,mem2mem";
+		dmas = <&dma_1 0>, <&dma_2 0>;
+		dma-names = "tx", "rx";
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/media/xilinx/xlnx,sdirxss.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/media/xilinx/xlnx,sdirxss.txt
@@ -0,0 +1,77 @@
+
+Xilinx SDI Receiver Subsystem
+------------------------------
+
+The Xilinx SDI Rx Subsystem is used to capture SDI Video in upto 12G mode.
+It outputs the video as an AXI4 Stream video data in YUV 422 10bpc mode.
+The subsystem consists of the SDI Rx IP whose SDI native output is connected
+to a SDI to Native conversion Bridge. The output of the Native bridge is
+connected to a Native to AXI4S Bridge which generates the AXI4 Stream of
+YUV422 or YUV420 10 bpc in dual pixel per clock.
+
+Required properties:
+
+- compatible: Must contain "xlnx,v-smpte-uhdsdi-rx-ss"
+
+- reg: Physical base address and length of the registers set for the device.
+
+- interrupts: Contains the interrupt line number.
+
+- interrupt-parent: phandle to interrupt controller.
+
+- xlnx,include-edh: Whether the EDH processor is enabled in design or not.
+
+- xlnx,line-rate: The maximum mode supported by the design.
+
+- clocks: Input clock specifier. Refer to common clock bindings.
+
+- clock-names: List of input clocks.
+  Required elements: "s_axi_aclk", "sdi_rx_clk", "video_out_clk"
+
+- port: Video port, using the DT bindings defined in ../video-interfaces.txt.
+  The SDI Rx subsystem has one port configured as output port.
+
+- xlnx,video-format, xlnx,video-width: Video format and width, as defined in
+  video.txt. Please note that the video format is fixed to either YUV422 or YUV420
+  and the video-width is 10.
+
+Optional properties:
+
+- reset_gt-gpios: contains GPIO reset phandle for FMC init done pin in GT.
+  This pin is active low.
+- picxo_reset-gpios: contains GPIO reset phandle for PICXO done pin for PICXO module.
+  This pin is active high.
+- xlnx,bpp: This denotes the bit depth as 10 or 12 based on IP configuration.
+  The default value is 10 for backward compatibility.
+
+Example:
+		v_smpte_uhdsdi_rx_ss: v_smpte_uhdsdi_rx_ss@80000000 {
+			compatible = "xlnx,v-smpte-uhdsdi-rx-ss";
+			interrupt-parent = <&gic>;
+			interrupts = <0 89 4>;
+			reg = <0x0 0x80000000 0x0 0x10000>;
+			xlnx,include-axilite = "true";
+			xlnx,include-edh = "true";
+			xlnx,include-vid-over-axi = "true";
+			xlnx,line-rate = "12G_SDI_8DS";
+			clocks = <&clk_1>, <&si570_1>, <&clk_2>;
+			clock-names = "s_axi_aclk", "sdi_rx_clk", "video_out_clk";
+			reset_gt-gpios = <&axi_gpio_0 0 0 GPIO_ACTIVE_LOW>;
+			picxo_reset-gpios = <&axi_gpio_0 2 0 GPIO_ACTIVE_HIGH>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+
+					xlnx,video-format = <XVIP_VF_YUV_422>;
+					xlnx,video-width = <10>;
+
+					sdirx_out: endpoint {
+						remote-endpoint = <&vcap_sdirx_in>;
+					};
+				};
+			};
+		};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/media/xilinx/xlnx,v-axi4s-switch.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/media/xilinx/xlnx,v-axi4s-switch.txt
@@ -0,0 +1,141 @@
+Xilinx AXI4-Stream Switch
+-------------------------------
+
+The AXI4-Stream Switch provides configurable routing between masters and slaves.
+It supports up to 16 masters/sources and 16 slaves/sinks and two routing options.
+There is atleast one slave/sink port and two master/source ports.
+
+The two routing options available are TDEST routing and control register routing.
+The TDEST based routing uses design parameters and hence there no software control.
+Each port is mapped as a pad and has its own format specified.
+
+Control register routing introduces an AXI4-Lite interface to configure the
+routing table. There is one register for each of the master interfaces to
+control each of the selectors. This routing mode requires that there is
+precisely only one path between master and slave. When attempting to map the
+same slave interface to multiple master interfaces, only the lowest master
+interface is able to access the slave interface.
+Here only the slave/sink ports have formats as master/source ports will inherit
+the corresponding slave ports formats. A routing table is maintained in this case.
+
+Please refer to PG085 AXI4-Stream Infrastructure IP Suite v2.2 for more details.
+
+Required properties:
+
+ - compatible: Must be "xlnx,axis-switch-1.1".
+ - xlnx,routing-mode: Can be 0 (TDEST routing) or 1 (Control reg routing)
+ - xlnx,num-si-slots: Number of slave / input ports. Min 1 Max 16 .
+ - xlnx,num-mi-slots: Number of master / output ports. Min 1 Max 16.
+ - ports: Video ports, using the DT bindings defined in ../video-interfaces.txt.
+ - clocks: Reference to the AXI Streaming clock feeding the ACLK and
+   AXI4 Lite control interface clock when control routing is enabled.
+ - clock-names: Must have "aclk".
+
+Optional properties:
+ - reg: Physical base address and length of the registers set for the device.
+	This is required only if xlnx,routing-mode is 1.
+ - clocks: Reference to AXI4 Lite control interface clock when routing-mode is 1.
+ - clock-names: "s_axi_ctl_clk" clock for AXI4 Lite interface when routing-mode is 1.
+
+Example:
+
+For TDEST routing, from 1 slave port to 4 master ports
+
+	axis_switch_0: axis_switch@0 {
+		compatible = "xlnx,axis-switch-1.1";
+		xlnx,routing-mode = <0x0>;
+		xlnx,num-si-slots = <0x1>;
+		xlnx,num-mi-slots = <0x4>;
+		clocks = <&vid_stream_clk>;
+		clock-names = "aclk";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			port@0 {
+				reg = <0>;
+				switch_in0: endpoint {
+					remote-endpoint = <&csirxss_out>;
+				};
+			};
+			port@1 {
+				reg = <1>;
+				switch_out0: endpoint {
+					remote-endpoint = <&vcap_csirxss0_in>;
+				};
+			};
+			port@2 {
+				reg = <2>;
+				switch_out1: endpoint {
+					remote-endpoint = <&vcap_csirxss1_in>;
+				};
+			};
+			port@3 {
+				reg = <3>;
+				switch_out2: endpoint {
+					remote-endpoint = <&vcap_csirxss2_in>;
+				};
+			};
+			port@4 {
+				reg = <4>;
+				switch_out3: endpoint {
+					remote-endpoint = <&vcap_csirxss3_in>;
+				};
+			};
+		};
+
+	};
+
+For Control reg based routing, from 2 slave ports to 4 master ports
+
+	axis_switch_0: axis_switch@a0050000 {
+		compatible = "xlnx,axis-switch-1.1";
+		reg = <0x0 0xa0050000 0x0 0x1000>;
+		xlnx,routing-mode = <0x1>;
+		xlnx,num-si-slots = <0x2>;
+		xlnx,num-mi-slots = <0x4>;
+		clocks = <&vid_stream_clk>, <&misc_clk_0>;
+		clock-names = "aclk", "s_axi_ctl_clk;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			port@0 {
+				reg = <0>;
+				switch_in0: endpoint {
+					remote-endpoint = <&csirxss_out>;
+				};
+			};
+			port@1 {
+				reg = <1>;
+				switch_in1: endpoint {
+					remote-endpoint = <&tpg_out>;
+				};
+			};
+			port@2 {
+				reg = <2>;
+				switch_out0: endpoint {
+					remote-endpoint = <&vcap_csirxss0_in>;
+				};
+			};
+			port@3 {
+				reg = <3>;
+				switch_out1: endpoint {
+					remote-endpoint = <&vcap_csirxss1_in>;
+				};
+			};
+			port@4 {
+				reg = <4>;
+				switch_out2: endpoint {
+					remote-endpoint = <&vcap_csirxss2_in>;
+				};
+			};
+			port@5 {
+				reg = <5>;
+				switch_out3: endpoint {
+					remote-endpoint = <&vcap_csirxss3_in>;
+				};
+			};
+		};
+
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/media/xilinx/xlnx,v-cfa.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/media/xilinx/xlnx,v-cfa.txt
@@ -0,0 +1,58 @@
+Xilinx Color Filter Array (CFA)
+-------------------------------
+
+Required properties:
+
+- compatible: Must be "xlnx,v-cfa-7.0".
+
+- reg: Physical base address and length of the registers set for the device.
+
+- clocks: Reference to the video core clock.
+
+- ports: Video ports, using the DT bindings defined in ../video-interfaces.txt.
+  The cfa has an input port (0) and an output port (1).
+
+Required port properties:
+
+- xlnx,video-format: Must be SENSOR_MONO for the input port (0), and RBG for
+  the output port (1).
+
+- xlnx,video-width: Video width as defined in video.txt
+
+- xlnx, cfa-pattern: Must be one of "rggb", "grbg", "gbrg", and "bggr" for the
+  input port (0). Must not be specified for the output port (1).
+
+Example:
+
+	cfa_0: cfa@400b0000 {
+		compatible = "xlnx,v-cfa-7.0";
+		reg = <0x400b0000 0x10000>;
+		clocks = <&clkc 15>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+
+				xlnx,video-format = <XVIP_VF_SENSOR_MONO>;
+				xlnx,video-width = <8>;
+				xlnx,cfa-pattern = "rggb";
+
+				cfa0_in: endpoint {
+					remote-endpoint = <&spc0_out>;
+				};
+			};
+			port@1 {
+				reg = <1>;
+
+				xlnx,video-format = <XVIP_VF_RBG>;
+				xlnx,video-width = <8>;
+
+				cfa0_out: endpoint {
+					remote-endpoint = <&ccm0_in>;
+				};
+			};
+		};
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/media/xilinx/xlnx,v-cresample.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/media/xilinx/xlnx,v-cresample.txt
@@ -0,0 +1,54 @@
+Xilinx Chroma Resampler (CRESAMPLE)
+-----------------------------------
+
+Required properties:
+
+- compatible: Must be "xlnx,v-cresample-4.0".
+
+- reg: Physical base address and length of the registers set for the device.
+
+- clocks: Reference to the video core clock.
+
+- ports: Video ports, using the DT bindings defined in ../video-interfaces.txt.
+  The cresample as han input port (0) and an output port (1).
+
+Required port properties:
+
+- xlnx,video-format: Must be one of YUV_444, YUV_422 or YUV_420 for the input
+  port (0), and one of YUV_422 or YUV_420 for the output port (1).
+
+- xlnx,video-width: Video width as defined in video.txt
+
+Example:
+
+	cresample_0: cresample@40120000 {
+		compatible = "xlnx,v-cresample-4.0";
+		reg = <0x40120000 0x10000>;
+		clocks = <&clkc 15>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+
+				xlnx,video-format = <XVIP_VF_YUV_444>;
+				xlnx,video-width = <8>;
+
+				cresample0_in: endpoint {
+					remote-endpoint = <&rgb2yuv0_out>;
+				};
+			};
+			port@1 {
+				reg = <1>;
+
+				xlnx,video-format = <XVIP_VF_YUV_422>;
+				xlnx,video-width = <8>;
+
+				cresample0_out: endpoint {
+					remote-endpoint = <&scaler0_in>;
+				};
+			};
+		};
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/media/xilinx/xlnx,v-demosaic.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/media/xilinx/xlnx,v-demosaic.txt
@@ -0,0 +1,62 @@
+Xilinx Video Demosaic IP
+-----------------------------
+The Xilinx Video Demosaic IP is used to interface to a Bayer video source.
+
+The driver set default Sink Pad media bus format to RGGB.
+The IP and driver only support RGB as its Source Pad media format.
+
+Required properties:
+
+- compatible: Must be "xlnx,v-demosaic".
+
+- reg: Physical base address and length of the registers set for the device.
+
+- clocks: Reference to the AXI Streaming clock feeding the Demosaic ap_clk.
+
+- xlnx,max-height: Maximum number of lines. Valid range is 64 to 4320.
+
+- xlnx,max-width: Maximum number of pixels in a line. Valid range is 64 to 8192.
+
+- reset-gpios: Specifier for GPIO that asserts Demosaic IP (AP_RST_N) reset.
+
+- ports: Video ports, using the DT bindings defined in ../video-interfaces.txt.
+
+Required port properties:
+
+- reg: This value represents the media pad of the V4L2 sub-device.
+  A Sink Pad is represented by reg = <0>
+  A Source Pad is represented by reg = <1>
+
+- xlnx,video-width: Video width as defined in video.txt
+
+Example:
+	demosaic_1: demosaic@a00b0000 {
+		compatible = "xlnx,v-demosaic";
+		reg = <0x0 0xa00b0000 0x0 0x10000>;
+		clocks = <&vid_stream_clk>;
+		reset-gpios = <&gpio 87 1>;
+		xlnx,max-width = <3840>;
+		xlnx,max-height = <2160>;
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				xlnx,video-width = <8>;
+
+				demosaic_in: endpoint {
+					remote-endpoint = <&tpg_out>;
+				};
+			};
+
+			port@1 {
+				reg = <1>;
+				xlnx,video-width = <8>;
+
+				demosaic_out: endpoint {
+					remote-endpoint = <&gamma_in>;
+				};
+			};
+		};
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/media/xilinx/xlnx,v-dprxss.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/media/xilinx/xlnx,v-dprxss.yaml
@@ -0,0 +1,175 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/xilinx/xlnx,v-dprxss.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Xilinx DisplayPort Receiver Subsystem
+
+maintainers:
+  - Rajesh Gugulothu <gugulothu.rajesh@xilinx.com>
+
+description: |
+  The DisplayPort subsystem is a full feature, hierarchically packaged
+  subsystem with a DisplayPort sink(RX). DP RX subsystem can capture
+  video data in different formats at different resolutions.
+  For more details, please refer to PG233 at https://www.xilinx.com/support/documentation/ip_documentation/dp_rx_subsystem/v2_1/pg233-displayport-rx-subsystem.pdf
+
+properties:
+  compatible:
+    items:
+      - enum:
+          - xlnx,v-dprxss-3.0
+
+  reg:
+    maxItems: 2
+    items:
+      - description: DisplayPort Receiver Subsystem registers
+      - description: EDID IP block registers
+
+  reg-names:
+    items:
+      - const: dp_base
+      - const: edid_base
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    description: List of clock specifiers
+    items:
+      - description: AXI Lite clock
+      - description: Link clock
+      - description: Video clock
+
+  clock-names:
+    items:
+      - const: s_axi_aclk
+      - const: rx_lnk_clk
+      - const: rx_vid_clk
+
+  phys:
+    description: This denotes phandles for phy lanes registered for DP
+                 protocol. Number of phy lanes registered are depends on
+                 the xlnx,lane-count property.
+
+  phy-names:
+    items:
+      - const: dp-phy0
+      - const: dp-phy1
+      - const: dp-phy2
+      - const: dp-phy3
+
+  xlnx,link-rate:
+    description: |
+      Max link rate that IP configured with.Possible values are as below -
+      0x6  - 1.62 Gb/s
+      0xa  - 2.7 Gb/s
+      0x14 - 5.4 Gb/s
+      0x1e - 8.1 Gb/s
+    allOf:
+      - $ref: /schemas/types.yaml#/definitions/uint32
+      - enum: [0x6, 0xa, 0x14, 0x1e]
+
+  xlnx,lane-count:
+    description: Max number of lanes that IP configured with.
+                 Possible values are 1, 2, 4.
+    allOf:
+      - $ref: /schemas/types.yaml#/definitions/uint32
+      - enum: [1, 2, 4]
+
+  xlnx,bpc:
+    description: |
+      Max BPC value that IP configured with. For example if IP is
+      configured
+      with 10 BPC means it supports (6, 8, 10) up to 10bpc.
+      Possible values are 6, 8, 10, 12, 16.
+    allOf:
+      - $ref: /schemas/types.yaml#/definitions/uint32
+      - enum: [6, 8, 10, 12, 16]
+
+  xlnx,audio-channels:
+    description: |
+      This denotes number of audio channels enabled in the IP
+      configuration. Possible values are 2, 3, 4, 5, 6, 7, 8.
+    allOf:
+      - $ref: /schemas/types.yaml#/definitions/uint32
+      - enum: [2, 3, 4, 5, 6, 7, 8]
+
+  ports:
+    type: object
+
+    properties:
+      port@0:
+        type: object
+        description: |
+          Output / source port node, endpoint describing modules
+          connected the DisplayPort receiver
+
+        properties:
+          reg:
+            const: 0
+
+          endpoint:
+            type: object
+
+            properties:
+
+              remote-endpoint: true
+
+            required:
+              - remote-endpoint
+
+            additionalProperties: false
+
+        additionalProperties: false
+
+required:
+  - clock-names
+  - clocks
+  - compatible
+  - interrupts
+  - reg
+  - reg-names
+  - link-rate
+  - bpc
+  - lane-count
+  - phy-names
+  - phys
+  - ports
+
+examples:
+ - |
+   v_dp_rxss1@a0040000 {
+       clock-names = "s_axi_aclk", "rx_lnk_clk", "rx_vid_clk" ;
+       clocks = <&zynqmp_clk 71>, <&zynqmp_clk 72>;
+       compatible = "xlnx,v-dp-rxss-3.0";
+       interrupt-names = "dprxss_dp_irq";
+       interrupt-parent = <&gic>;
+       interrupts = <0 89 4>;
+       reg = <0x0 0xa0040000 0x0 0x40000>,<0x0 0xa0010000 0x0 0x1000>;
+       reg-names = "dp_base", "edid_base";
+       xlnx,link-rate = <0x1e>;
+       xlnx,audio-enable;
+       xlnx,audio-channels = <2>;
+       xlnx,bpc = <10>;
+       xlnx,hdcp22-enable;
+       xlnx,hdcp-enable;
+       xlnx,lane-count = <4>;
+       phy-names = "dp-phy0", "dp-phy1", "dp-phy2", "dp-phy3";
+       phys = <&vphy_lane0 0 1 1 0>, <&vphy_lane1 0 1 1 0>,
+              <&vphy_lane2 0 1 1 0>, <&vphy_lane3 0 1 1 0>;
+
+       ports {
+           #address-cells = <1>;
+           #size-cells = <0>;
+
+           port@0 {
+               reg = <0>;
+               dp_rxss_out: endpoint {
+                   remote-endpoint = <&remap0_in>;
+               };
+           };
+       };
+   };
+...
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/media/xilinx/xlnx,v-gamma-lut.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/media/xilinx/xlnx,v-gamma-lut.txt
@@ -0,0 +1,63 @@
+Xilinx Video Gamma Correction IP
+-----------------------------------
+The Xilinx Video Gamma Correction IP is used to provide RGB gamma correction.
+The IP provides a look up table for each R,G and B components.
+
+Required properties:
+
+- compatible: Must be "xlnx,v-gamma-lut".
+
+- reg: Physical base address and length of the registers set for the device.
+
+- clocks: Reference to the clock that drives the ap_clk
+	  signal of Video Gamma Lookup.
+
+- xlnx,max-height: Maximum number of lines. Valid range is 64 to 4320.
+
+- xlnx,max-width: Maximum number of pixels in a line. Valid range is 64 to 8192.
+
+- reset-gpios: Specifier for a GPIO that asserts Gamma IP (AP_RST_N) reset
+
+- ports: Video ports, using the DT bindings defined in ../video-interfaces.txt.
+  The Gamma LUT IP has an input port (0) and an output port (1).
+
+
+Required port properties:
+- reg: This value represents the media pad of the V4L2 sub-device.
+  A Sink Pad is represented by reg = <0>
+  A Source Pad is represented by reg = <1>
+
+- xlnx,video-width: Video width as defined in video.txt. Can be either 8 or 10.
+
+Example:
+
+	gamma_lut_1: gamma_lut_1@0xa0080000 {
+		compatible = "xlnx,v-gamma-lut";
+		reg = <0x0 0xa0080000 0x0 0x10000>;
+		clocks = <&vid_stream_clk>;
+		reset-gpios = <&gpio 83 1>;
+		xlnx,max-height = <2160>;
+		xlnx,max-width = <3840>;
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				xlnx,video-width = <8>;
+
+				gamma_in: endpoint {
+					remote-endpoint = <&demosaic_out>;
+				};
+			};
+
+			port@1 {
+				reg = <1>;
+				xlnx,video-width = <8>;
+
+				gamma_out: endpoint {
+					remote-endpoint = <&csc_in>;
+				};
+			};
+		};
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/media/xilinx/xlnx,v-hls.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/media/xilinx/xlnx,v-hls.txt
@@ -0,0 +1,64 @@
+Xilinx High-Level Synthesis Core (HLS)
+--------------------------------------
+
+High-Level Synthesis cores are synthesized from a high-level function
+description developed by the user. As such their functions vary widely, but
+they all share a set of common characteristics that allow them to be described
+by common bindings.
+
+
+Required properties:
+
+- compatible: This property must contain "xlnx,v-hls" to indicate that the
+  core is compatible with the generic Xilinx HLS DT bindings. It can also
+  contain a more specific string to identify the HLS core implementation. The
+  value of those implementation-specific strings is out of scope for these DT
+  bindings.
+
+- reg: Physical base address and length of the registers sets for the device.
+  The HLS core has two registers sets, the first one contains the core
+  standard registers and the second one contains the custom user registers.
+
+- clocks: Reference to the video core clock.
+
+- ports: Video ports, using the DT bindings defined in ../video-interfaces.txt.
+  The HLS core has one input port (0) and one output port (1).
+
+Required port properties:
+
+- xlnx,video-format: Video format as defined in video.txt.
+- xlnx,video-width: Video width as defined in video.txt.
+
+Example:
+
+	hls_0: hls@43c00000 {
+		compatible = "xlnx,v-hls-sobel", "xlnx,v-hls";
+		reg = <0x43c00000 0x24>, <0x43c00024 0xa0>;
+		clocks = <&clkc 15>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+
+				xlnx,video-format = <XVIP_VF_YUV_422>;
+				xlnx,video-width = <8>;
+
+				hls0_in: endpoint {
+					remote-endpoint = <&vdma_out>;
+				};
+			};
+			port@1 {
+				reg = <1>;
+
+				xlnx,video-format = <XVIP_VF_YUV_422>;
+				xlnx,video-width = <8>;
+
+				hls0_out: endpoint {
+					remote-endpoint = <&vdma_in>;
+				};
+			};
+		};
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/media/xilinx/xlnx,v-multi-scaler.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/media/xilinx/xlnx,v-multi-scaler.txt
@@ -0,0 +1,95 @@
+Xilinx mem2mem Multi Video Scaler (XM2MSC)
+-----------------------------------------
+
+Required propertie(s):
+- compatible		: Should be "xlnx,v-multi-scaler-v1.0"
+- clocks		: Input clock specifier. Refer to common clk bindings.
+- interrupt-parent	: Interrupt controller the interrupt is routed through
+- interrupts		: Should contain MultiScaler interrupt
+- reset-gpios		: Should contain GPIO reset phandle
+- reg			: Physical base address and
+			  length of the registers set for the device.
+- xlnx,max-chan		: Maximum number of supported scaling channels (1 - 8)
+- xlnx,max-width	: Maximum number of supported column/width (64 - 3840)
+- xlnx,max-height	: Maximum number of supported row/height (64 - 2160)
+- xlnx,dma-addr-width	: dma address width (either 32 or 64)
+- xlnx,pixels-per-clock	: pixels per clock set in IP (1, 2 or 4)
+- xlnx,vid-formats	: A list of strings indicating what video memory
+			  formats the IP has been configured to support.
+			  See VIDEO FORMATS table below and examples.
+- xlnx,num-taps		: The number of filter taps for scaling (6, 8, 10, 12)
+
+VIDEO FORMATS
+The following table describes the legal string values to be used for
+the xlnx,vid-formats property. To the left is the string value and the
+column to the right describes the format.
+
+IP FORMAT	DTS String	Description
+-------------|----------------|---------------------
+RGB8		bgr888		Packed RGB, 8 bits per component.
+				Every RGB pixel in memory is represented with
+				24 bits.
+RGBX8		xbgr8888	Packed RGB, 8 bits per component. Every RGB
+				pixel in memory is represented with 32 bits.
+				Bits[31:24] do not contain pixel information.
+BGRX8		xrgb8888	Packed BGR, 8 bits per component. Every BGR
+				pixel in memory is represented with 32 bits.
+				Bits[31:24] do not contain pixel information.
+RGBX10		xbgr2101010	Packed RGB, 10 bits per component. Every RGB
+				pixel is represented with 32 bits. Bits[31:30]
+				do not contain any pixel information.
+YUV8		vuy888		Packed YUV 4:4:4, 8 bits per component. Every
+				YUV 4:4:4 pixel in memory is represented with
+				24 bits.
+YUVX8		xvuy8888	Packed YUV 4:4:4, 8 bits per component.
+				Every YUV 4:4:4 pixel in memory is represented
+				with 32 bits. Bits[31:24] do not contain pixel
+				information.
+YUYV8		yuyv		Packed YUV 4:2:2, 8 bits per component. Every
+				two YUV 4:2:2 pixels in memory are represented
+				with 32 bits.
+UYVY8		uyvy		Packed YUV 4:2:2, 8 bits per component.
+				Every two YUV 4:2:2 pixels in memory are
+				represented with 32 bits.
+YUVX10		yuvx2101010	Packed YUV 4:4:4, 10 bits per component.
+				Every YUV 4:4:4 pixel is represented with 32 bits.
+				Bits[31:30] do not contain any pixel information.
+Y8		y8		Packed Luma-Only, 8 bits per component. Every
+				luma-only pixel in memory is represented with
+				8 bits. Y8 is presented as YUV 4:4:4 on the
+				AXI4-Stream interface.
+Y10		y10		Packed Luma-Only, 10 bits per component. Every
+				three luma-only pixels in memory is represented
+				with 32 bits. Y10 is presented as YUV 4:4:4 on
+				the AXI4-Stream interface.
+Y_UV8		nv16		Semi-planar YUV 4:2:2 with 8 bits per component.
+				Y and UV stored in separate planes.
+Y_UV8_420	nv12		Semi-planar YUV 4:2:0 with 8 bits per component.
+				Y and UV stored in separate planes.
+Y_UV10		xv20		Semi-planar YUV 4:2:2 with 10 bits per component.
+				Every 3 pixels is represented with 32 bits.
+				Bits[31:30] do not contain any pixel information.
+				Y and UV stored in separate planes.
+Y_UV10_420	xv15		Semi-planar YUV 4:2:0 with 10 bits per component.
+				Every 3 pixels is represented with 32 bits.
+				Bits[31:30] do not contain any pixel information.
+				Y and UV stored in separate planes.
+
+Example
+
+v_multi_scaler_0: v_multi_scaler@a0000000 {\
+	clocks = <&clk 71>;
+	compatible = "xlnx,v-multi-scaler-v1.0";
+	interrupt-names = "interrupt";
+	interrupt-parent = <&gic>;
+	interrupts = <0 89 4>;
+	reg = <0x0 0xa0000000 0x0 0x10000>;
+	xlnx,vid-formats = "bgr888","vuy888";
+	reset-gpios = <&gpio 78 1>;
+	xlnx,max-chan = <0x01>;
+	xlnx,dma-addr-width = <0x20>;
+	xlnx,pixels-per-clock = /bits/ 8 <2>;
+	xlnx,max-width = <3840>;
+	xlnx,max-height = <2160>;
+	xlnx,num-taps = <6>;
+};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/media/xilinx/xlnx,v-remapper.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/media/xilinx/xlnx,v-remapper.txt
@@ -0,0 +1,61 @@
+Xilinx Video Remapper
+---------------------
+
+The IP core remaps input pixel components to produce an output pixel with
+less, more or the same number of components as the input pixel.
+
+Required properties:
+
+- compatible: Must be "xlnx,v-remapper".
+
+- clocks: Reference to the video core clock.
+
+- xlnx,video-width: Video pixel component width, as defined in video.txt.
+
+- #xlnx,s-components: Number of components per pixel at the input port
+  (between 1 and 4 inclusive).
+
+- #xlnx,m-components: Number of components per pixel at the output port
+  (between 1 and 4 inclusive).
+
+- xlnx,component-maps: Remapping configuration represented as an array of
+  integers. The array contains one entry per output component, in the low to
+  high order. Each entry corresponds to the zero-based position of the
+  corresponding input component, or the value 4 to drive a constant value on
+  the output component. For example, to remap RGB to BGR use <2 1 0>, and to
+  remap RBG to xRGB use <1 0 2 4>.
+
+- ports: Video ports, using the DT bindings defined in ../video-interfaces.txt.
+  The remapper as an input port (0) and and output port (1).
+
+Example: RBG to xRGB remapper
+
+	remapper_0: remapper {
+		compatible = "xlnx,v-remapper";
+
+		clocks = <&clkc 15>;
+
+		xlnx,video-width = <8>;
+
+		#xlnx,s-components = <3>;
+		#xlnx,m-components = <4>;
+		xlnx,component-maps = <1 0 2 4>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				remap0_in: endpoint {
+					remote-endpoint = <&tpg0_out>;
+				};
+			};
+			port@1 {
+				reg = <1>;
+				remap0_out: endpoint {
+					remote-endpoint = <&sobel0_in>;
+				};
+			};
+		};
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/media/xilinx/xlnx,v-rgb2yuv.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/media/xilinx/xlnx,v-rgb2yuv.txt
@@ -0,0 +1,54 @@
+Xilinx RGB to YUV (RGB2YUV)
+---------------------------
+
+Required properties:
+
+- compatible: Must be "xlnx,v-rgb2yuv-7.1".
+
+- reg: Physical base address and length of the registers set for the device.
+
+- clocks: Reference to the video core clock.
+
+- ports: Video ports, using the DT bindings defined in ../video-interfaces.txt.
+  The rgb2yuv has an input port (0) and an output port (1).
+
+Required port properties:
+
+- xlnx,video-format: Must be RBG for the input port (0) and YUV_444 for the
+  output port (1).
+
+- xlnx,video-width: Video width as defined in video.txt
+
+Example:
+
+	rgb2yuv_0: rgb2yuv@40100000 {
+		compatible = "xlnx,v-rgb2yuv-7.1";
+		reg = <0x40100000 0x10000>;
+		clocks = <&clkc 15>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+
+				xlnx,video-format = <XVIP_VF_RBG>;
+				xlnx,video-width = <8>;
+
+				rgb2yuv0_in: endpoint {
+					remote-endpoint = <&gamma0_out>;
+				};
+			};
+			port@1 {
+				reg = <1>;
+
+				xlnx,video-format = <XVIP_VF_YUV_444>;
+				xlnx,video-width = <8>;
+
+				rgb2yuv0_out: endpoint {
+					remote-endpoint = <&cresample0_in>;
+				};
+			};
+		};
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/media/xilinx/xlnx,v-scaler.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/media/xilinx/xlnx,v-scaler.txt
@@ -0,0 +1,75 @@
+Xilinx Scaler (SCALER)
+------------------------------------
+
+Required properties:
+
+- compatible: Must be "xlnx,v-scaler-8.1".
+
+- reg: Physical base address and length of the registers set for the device.
+
+- clocks: Reference to the video core clock.
+
+- xlnx,num-hori-taps, xlnx,num-vert-taps: The number of horizontal and vertical
+  taps for scaling filter(range: 2 - 12).
+
+- xlnx,max-num-phases: The maximum number of phases for scaling filter
+  (range: 2 - 64).
+
+- ports: Video ports, using the DT bindings defined in ../video-interfaces.txt.
+  The scaler has an input port (0) and an output port (1).
+
+Optional properties:
+
+- xlnx,separate-yc-coef: When set, this boolean property specifies that
+  the hardware uses separate coefficients for the luma and chroma filters.
+  Otherwise a single set of coefficients is shared for both.
+
+- xlnx,separate-hv-coef: When set, this boolean property specifies that
+  the hardware uses separate coefficients for the horizontal and vertical
+  filters. Otherwise a single set of coefficients is shared for both.
+
+Required port properties:
+
+- xlnx,video-format: Must be one of RBG, YUV_422, YUV_422 or YUV_420 for
+  both input port (0) and output port (1). The two formats must be identical.
+
+- xlnx,video-width: Video width as defined in video.txt
+
+Example:
+
+	scaler_0: scaler@43c30000 {
+		compatible = "xlnx,v-scaler-8.1";
+		reg = <0x43c30000 0x10000>;
+		clocks = <&clkc 15>;
+
+		xlnx,num-hori-taps = <12>;
+		xlnx,num-vert-taps = <12>;
+		xlnx,max-num-phases = <4>;
+		xlnx,separate-hv-coef;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+
+				xlnx,video-format = <XVIP_VF_YUV_422>;
+				xlnx,video-width = <8>;
+
+				scaler0_in: endpoint {
+					remote-endpoint = <&cresample0_out>;
+				};
+			};
+			port@1 {
+				reg = <1>;
+
+				xlnx,video-format = <XVIP_VF_YUV_422>;
+				xlnx,video-width = <8>;
+
+				scaler0_out: endpoint {
+					remote-endpoint = <&vcap0_in>;
+				};
+			};
+		};
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/media/xilinx/xlnx,v-scd.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/media/xilinx/xlnx,v-scd.txt
@@ -0,0 +1,164 @@
+Xilinx Scene Change Detection IP (SCD)
+--------------------------------------
+
+The Xilinx Scene Change Detection IP contains two blocks: one IP block is used
+for reading video frame data from memory to the device and the other IP block
+is used for determining whether there is a scene change between current and the
+previous frame. The IP supports YUV planar and semi-planar formats. IP only
+needs luma frame to determine the scene change event. The IP supports memory
+based model, which means that it will accept a dma buffer address and perform
+MEM2DEV transfer followed by statistical based image processing and give the
+data back to application if scene change detection is present or not.
+
+Another version of scene change detection IP which supports streaming model,
+which means that IP can be inserted in a capture pipeline. For example,
+"hdmirx -> streaming-scd -> fb_wr" is a typical capture pipeline where
+streaming SCD can be embedded. The IP accespts the AXI video data and perform
+histogram based statistical analysis to detect scene change. The IP supports
+single channel.
+
+Required properties:
+
+- compatible: Should be "xlnx,v-scd"
+
+- reg: Physical base address and length of the registers set for the device
+
+- clocks: Reference to the video core clock.
+
+- reset-gpios: Specifier for a GPIO that assert SCD (AP_RST_N) reset.
+
+- xlnx,memory-based: This is to differentiate between memory based and
+  streaming based IP. The value is 1 for memory based and 0 for streaming
+  based IPs.
+
+- xlnx,numstreams: Maximum active streams IP can support is 8 and this is based
+  on the design.
+
+- xlnx,addrwidth: Size of dma address pointer in IP (either 32 or 64)
+
+- subdev: Each channel will have its own subdev node. Each subdev will have its
+  sink port.
+
+- port: Video port, using the DT bindings defined in ../video-interfaces.txt.
+
+Example:
+
+1. Memory based device tree
+
+The following example shows how the device tree would look like for a memory
+based design where 8 streams are enabled.
+
+	scd: scenechange@a0100000 {
+		compatible = "xlnx,v-scd";
+		reg = <0x0 0xa0100000 0x0 0x1fff>;
+		clocks = <&misc_clk_0>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 90 4>;
+		reset-gpios = <&gpio 94 1>;
+
+		xlnx,memory-based;
+		xlnx,numstreams = <8>;
+		xlnx,addrwidth = <0x20>;
+
+		#address-cells = <1>;
+		#size-cells = <0>;
+		#dma-cells = <1>;
+
+		subdev@0 {
+			port@0 {
+				reg = <0>;
+				scd_in0: endpoint {
+					remote-endpoint = <&vcap0_out0>;
+				};
+			};
+		};
+		subdev@1 {
+			port@0 {
+				reg = <0>;
+				scd_in1: endpoint {
+					remote-endpoint = <&vcap0_out1>;
+				};
+			};
+		};
+		subdev@2 {
+			port@0 {
+				reg = <0>;
+				scd_in2: endpoint {
+					remote-endpoint = <&vcap0_out2>;
+				};
+			};
+		};
+		subdev@3 {
+			port@0 {
+				reg = <0>;
+				scd_in3: endpoint {
+					remote-endpoint = <&vcap0_out3>;
+				};
+			};
+		};
+		subdev@4 {
+			port@0 {
+				reg = <0>;
+				scd_in4: endpoint {
+					remote-endpoint = <&vcap0_out4>;
+				};
+			};
+		};
+		subdev@5 {
+			port@0 {
+				reg = <0>;
+				scd_in5: endpoint {
+					remote-endpoint = <&vcap0_out5>;
+				};
+			};
+		};
+		subdev@6 {
+			port@0 {
+				reg = <0>;
+				scd_in6: endpoint {
+					remote-endpoint = <&vcap0_out6>;
+				};
+			};
+		};
+		subdev@7 {
+			port@0 {
+				reg = <0>;
+			scd_in7: endpoint {
+					remote-endpoint = <&vcap0_out7>;
+				};
+			};
+		};
+	};
+
+2. Streaming based device tree
+
+The following example shows how the device tree would look like for a streaming
+based design.
+
+	scd: scenechange@a0280000 {
+		compatible = "xlnx,v-scd";
+		reg = <0x0 0xa0280000 0x0 0x1fff>;
+		clocks = <&clk 72>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 111 4>;
+		reset-gpios = <&gpio 100 1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		xlnx,numstreams = <1>;
+
+		scd {
+			port@0 {
+				reg = <0x0>;
+				scd_in0: endpoint {
+					remote-endpoint = <&vpss_scaler_out>;
+				};
+			};
+
+			port@1 {
+				reg = <0x1>;
+				scd_out0: endpoint {
+					remote-endpoint = <&vcap_hdmi_in_1>;
+				};
+			};
+		};
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/media/xilinx/xlnx,v-switch.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/media/xilinx/xlnx,v-switch.txt
@@ -0,0 +1,55 @@
+Xilinx Video Switch
+-------------------
+
+Required properties:
+
+  - compatible: Must be "xlnx,v-switch-1.0".
+
+  - reg: Physical base address and length of the registers set for the device.
+
+  - clocks: Reference to the video core clock.
+
+  - #xlnx,inputs: Number of input ports
+  - #xlnx,outputs: Number of outputs ports
+
+  - ports: Video ports, using the DT bindings defined in ../video-interfaces.txt.
+
+Example:
+
+	switch: switch@43c10000 {
+		compatible = "xlnx,v-switch-1.0";
+		reg = <0x43c10000 0x10000>;
+		clocks = <&clkc 15>;
+
+		#xlnx,inputs = <2>;
+		#xlnx,outputs = <2>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			port@0 {
+				reg = <0>;
+				switch_in0: endpoint {
+					remote-endpoint = <&tpg_out>;
+				};
+			};
+			port@1 {
+				reg = <1>;
+				switch_in1: endpoint {
+					remote-endpoint = <&cresample0_out>;
+				};
+			};
+			port@2 {
+				reg = <2>;
+				switch_out0: endpoint {
+					remote-endpoint = <&scaler0_in>;
+				};
+			};
+			port@3 {
+				reg = <3>;
+				switch_out1: endpoint {
+					remote-endpoint = <&vcap0_in1>;
+				};
+			};
+		};
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/media/xilinx/xlnx,v-tpg.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/media/xilinx/xlnx,v-tpg.txt
@@ -6,7 +6,8 @@
 - compatible: Must contain at least one of
 
     "xlnx,v-tpg-5.0" (TPG version 5.0)
-    "xlnx,v-tpg-6.0" (TPG version 6.0)
+    "xlnx,v-tpg-7.0" (TPG version 7.0)
+    "xlnx,v-tpg-8.0" (TPG version 8.0)
 
   TPG versions backward-compatible with previous versions should list all
   compatible versions in the newer to older order.
@@ -23,6 +24,8 @@
 
 Optional properties:
 
+- xlnx,ppc: Pixels per clock. Valid values are 1, 2, 4 or 8.
+
 - xlnx,vtc: A phandle referencing the Video Timing Controller that generates
   video timings for the TPG test patterns.
 
@@ -30,16 +33,26 @@
   input. The GPIO active level corresponds to the selection of VTC-generated
   video timings.
 
+- reset-gpios: Specifier for a GPIO that assert TPG (AP_RST_N) reset.
+  This property is mandatory for TPG v7.0 and above.
+
+- xlnx,max-height: Maximum number of lines.
+  This property is mandatory for TPG v8.0. Value ranges from 64 to 7760.
+
+- xlnx,max-width: Maximum number of pixels in a line.
+  This property is mandatory for TPG v8.0. Value ranges from 64 to 10328.
+
 The xlnx,vtc and timing-gpios properties are mandatory when the TPG is
 synthesized with two ports and forbidden when synthesized with one port.
 
 Example:
 
 	tpg_0: tpg@40050000 {
-		compatible = "xlnx,v-tpg-6.0", "xlnx,v-tpg-5.0";
+		compatible = "xlnx,v-tpg-5.0";
 		reg = <0x40050000 0x10000>;
 		clocks = <&clkc 15>;
 
+		xlnx,ppc = <2>;
 		xlnx,vtc = <&vtc_3>;
 		timing-gpios = <&ps7_gpio_0 55 GPIO_ACTIVE_LOW>;
 
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/media/xilinx/xlnx,v-vpss-csc.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/media/xilinx/xlnx,v-vpss-csc.txt
@@ -0,0 +1,67 @@
+Xilinx VPSS Color Space Converter (CSC)
+-----------------------------------------
+The Xilinx VPSS Color Space Converter (CSC) is a Video IP that supports
+color space conversion from RGB or YUV(444, 422, 420)input to RGB or
+YUV(444, 422, 420) output.
+
+Required properties:
+
+- compatible: Must be "xlnx,v-vpss-csc".
+
+- reg: Physical base address and length of the registers set for the device.
+
+- clocks: Reference to the clock that drives the ap_clk signal.
+
+- xlnx,max-height: Maximum number of lines.
+  Valid range from 64 to 4320.
+
+- xlnx,max-width: Maximum number of pixels in a line.
+  Valid range from 64 to 8192.
+
+- reset-gpios: Specifier for a GPIO that assert VPSS CSC (AP_RST_N) reset.
+
+- ports: Video ports, using the DT bindings defined in ../video-interfaces.txt.
+  The scaler has an input port (0) and an output port (1).
+
+Required port properties:
+
+- xlnx,video-format: Must be XVIP_VF_RBG, XVIP_VF_YUV_444 or XVIP_VF_YUV_422
+  for input port (0) and XVIP_VF_RBG, XVIP_VF_YUV_444 or XVIP_VF_YUV_422
+  for output port (1). See <dt-bindings/media/xilinx-vip.h> for more details.
+
+- xlnx,video-width: Video width as defined in video.txt. Must be either 8 or 10.
+
+Example:
+	csc_1:csc@a0040000 {
+		compatible = "xlnx,v-vpss-csc";
+		reg = <0x0 0xa0040000 0x0 0x10000>;
+		clocks = <&vid_stream_clk>;
+		reset-gpios = <&gpio 84 1>;
+		xlnx,max-width = <3840>;
+		xlnx,max-height = <2160>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			/* Sink Pad */
+			port@0 {
+				reg = <0>;
+				xlnx,video-format = <XVIP_VF_RBG>;
+				xlnx,video-width = <8>;
+
+				csc_in: endpoint {
+					remote-endpoint = <&gamma_out>;
+				};
+			};
+			/* Source Pad */
+			port@1 {
+				reg = <1>;
+				xlnx,video-format = <XVIP_VF_RBG>;
+				xlnx,video-width = <8>;
+
+				csc_out: endpoint {
+					remote-endpoint = <&scalar_in>;
+				};
+			};
+		};
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/media/xilinx/xlnx,v-vpss-scaler.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/media/xilinx/xlnx,v-vpss-scaler.txt
@@ -0,0 +1,93 @@
+  Xilinx VPSS Scaler
+------------------------
+
+Required properties:
+
+- compatible: Must be "xlnx,v-vpss-scaler-2.2" or "xlnx,v-vpss-scaler-1.0".
+  The older string "xlnx,v-vpss-scaler" will be deprecated.
+
+- reg: Physical base address and length of the registers set for the device.
+
+- clocks: Reference to the AXI Streaming clock feeding the VPSS Scaler AP_CLK
+  and AXI4 Lite control interface clock.
+
+- clock-names: Must contain "aclk_axis" and "aclk_ctrl" in the same order as
+  clocks listed in clocks property.
+
+- xlnx,num-hori-taps, xlnx,num-vert-taps: The number of horizontal and vertical
+  taps for scaling filter(range: 2,4,6,8,10,12).
+
+  A value of 2 represents bilinear filters. A value of 4 represents bicubic.
+  Values 6,8,10,12 represent polyphase filters.
+
+- xlnx,pix-per-clk : The pixels per clock property of the IP
+
+- reset-gpios: Specifier for a GPIO that assert for VPSS Scaler reset.
+  This property is mandatory for the Scaler
+
+- xlnx,max-height: Maximum number of lines.
+  Valid range from 64 to 4320.
+
+- xlnx,max-width: Maximum number of pixels in a line.
+  Valid range from 64 to 8192.
+
+- ports: Video ports, using the DT bindings defined in ../video-interfaces.txt.
+  The scaler has an input port (0) and an output port (1).
+
+Required port properties:
+
+- xlnx,video-format: Must be one of XVIP_VF_RBG or XVIP_VF_YUV_422 for
+  input port (0) and must be XVIP_VF_RBG or XVIP_VF_YUV_422 or for
+  the output port (1).
+  See <dt-bindings/media/xilinx-vip.h> for more details.
+
+- reg: This value represents the media pad of the V4L2 sub-device.
+  A Sink Pad is represented by reg = <0>
+  A Source Pad is represented by reg = <1>
+
+- xlnx,video-width: Video width as defined in video.txt
+
+Example:
+
+	scaler_1:scaler@a0000000 {
+		compatible = "xlnx,v-vpss-scaler-1.0";
+		reg = <0x0 0xa0000000 0x0 0x40000>;
+		clocks = <&vid_stream_clk>, <&misc_clk_2>;
+		clock-names = "aclk_axis", "aclk_ctrl";
+		xlnx,num-hori-taps = <8>;
+		xlnx,num-vert-taps = <8>;
+		xlnx,pix-per-clk = <2>;
+		reset-gpios = <&gpio 87 1>;
+		xlnx,max-width = <3840>;
+		xlnx,max-height = <2160>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				/* Sink Pad */
+				reg = <0>;
+
+				xlnx,video-format = <XVIP_VF_RBG>;
+				xlnx,video-width = <8>;
+
+				scaler_in: endpoint {
+					remote-endpoint = <&csc_out>;
+				};
+			};
+
+			port@1 {
+				/* Source Pad */
+				reg = <1>;
+
+				xlnx,video-format = <XVIP_VF_YUV_422>;
+				xlnx,video-width = <8>;
+
+				scaler_out: endpoint {
+					remote-endpoint = <&vcap_tpg_in>;
+				};
+			};
+		};
+
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/mfd/ahc1ec0.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/mfd/ahc1ec0.yaml
@@ -0,0 +1,69 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/ahc1ec0.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Advantech Embedded Controller (AHC1EC0)
+
+maintainers:
+  - Campion Kang <campion.kang@advantech.com.tw>
+
+description: |
+  AHC1EC0 is one of the embedded controllers used by Advantech to provide several
+  functions such as watchdog, hwmon, brightness, etc. Advantech related applications
+  can control the whole system via these functions.
+
+properties:
+  compatible:
+    const: advantech,ahc1ec0
+
+  advantech,sub-dev-nb:
+    description:
+      The number of sub-devices specified in the platform.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    maxItems: 1
+
+  advantech,sub-dev:
+    description:
+      A list of the sub-devices supported in the platform. Defines for the
+      appropriate values can found in dt-bindings/mfd/ahc1ec0-dt.h.
+    $ref: "/schemas/types.yaml#/definitions/uint32-array"
+    minItems: 1
+    maxItems: 6
+
+  advantech,hwmon-profile:
+    description:
+      The number of sub-devices specified in the platform. Defines for the
+      hwmon profiles can found in dt-bindings/mfd/ahc1ec0-dt.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    maxItems: 1
+
+required:
+  - compatible
+  - advantech,sub-dev-nb
+  - advantech,sub-dev
+
+if:
+  properties:
+    advantech,sub-dev:
+      contains:
+        const: 0x3
+then:
+  required:
+    - advantech,hwmon-profile
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/mfd/ahc1ec0-dt.h>
+    ahc1ec0 {
+        compatible = "advantech,ahc1ec0";
+
+        advantech,sub-dev-nb = <2>;
+        advantech,sub-dev = <AHC1EC0_SUBDEV_HWMON
+                             AHC1EC0_SUBDEV_WDT>;
+
+        advantech,hwmon-profile = <AHC1EC0_HWMON_PRO_UNO2271G>;
+    };
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/misc/jesd-phy.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/misc/jesd-phy.txt
@@ -0,0 +1,24 @@
+* Xilinx JESD204B Phy
+
+Description:
+The LogiCORE™ IP JESD204 PHY core implements a JESD204B Physical interface supporting
+line rates between 1.0 and 12.5 Gb/s on 1 to 12 lanes using GTX, GTH, or GTP transceivers.
+
+Required properties:
+- compatible = "xlnx,jesd204-phy-2.0"
+- reg = Should contain JESD204B phy registers location and length
+- xlnx,pll-selection = The PLL selection 3 for QPLL and 1 For CPLL
+- xlnx,lanes = No of Lanes
+- xlnx,gt-refclk-freq = Reference frequency in Hz
+- clocks = The phandle to the clock tree
+
+Example:
+++++++++
+	jesd204_phycores:phy@41e10000 {
+		compatible = "xlnx,jesd204-phy-2.0";
+		reg = <0x41e10000 0x10000>;
+		xlnx,gt-refclk-freq = "156250000";
+		xlnx,lanes = <0x1>;
+		xlnx,pll-selection = <0x3>;
+		clocks = <&si570>;
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/misc/jesd204b.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/misc/jesd204b.txt
@@ -0,0 +1,28 @@
+* Xilinx JESD204B core
+
+Description:
+The LogiCORE™ IP JESD204 core implements a JESD204B core
+
+Required properties:
+- compatible = Should be one of
+		"xlnx,jesd204-5.1";
+		"xlnx,jesd204-5.2";
+		"xlnx,jesd204-6.1";
+- reg = Should contain JESD204B registers location and length
+- xlnx,frames-per-multiframe = No of frames per multiframe
+- xlnx,bytes-per-frame = No of bytes per frame
+- xlnx,lanes = No of Lanes
+- xlnx,subclass = subclass
+- xlnx,node-is-transmit = should be present only for transmit nodes
+
+Example:
+++++++++
+jesd_Tx_axi_0: jesd_Tx@44a20000 {
+	compatible = "xlnx,jesd204-5.1";
+	reg = <0x44a20000 0x10000>;
+	xlnx,frames-per-multiframe = <30>;
+	xlnx,bytes-per-frame = <2>;
+	xlnx,subclass = <1>;
+	xlnx,lanes = <0x2>;
+	xlnx,node-is-transmit;
+};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/misc/xlnx,axi-traffic-gen.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/misc/xlnx,axi-traffic-gen.txt
@@ -0,0 +1,25 @@
+* Xilinx AXI Traffic generator IP
+
+Required properties:
+- compatible: "xlnx,axi-traffic-gen"
+- interrupts: Should contain AXI Traffic Generator interrupts.
+- interrupt-parent: Must be core interrupt controller.
+- reg: Should contain AXI Traffic Generator registers location and length.
+- interrupt-names: Should contain both the intr names of device - error
+		   and completion.
+- xlnx,device-id: Device instance Id.
+
+Optional properties:
+- clocks: Input clock specifier. Refer to common clock bindings.
+
+Example:
+++++++++
+axi_traffic_gen_1: axi-traffic-gen@76000000 {
+	compatible = "xlnx,axi-traffic-gen-1.0", "xlnx,axi-traffic-gen";
+	clocks = <&clkc 15>;
+	interrupts = <0 2 2 2>;
+	interrupt-parent = <&axi_intc_1>;
+	interrupt-names = "err-out", "irq-out";
+	reg = <0x76000000 0x800000>;
+	xlnx,device-id = <0x0>;
+} ;
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/misc/xlnx,fclk.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/misc/xlnx,fclk.txt
@@ -0,0 +1,12 @@
+* Xilinx fclk clock enable
+Temporary solution for enabling the PS_PL clocks.
+
+Required properties:
+- compatible: "xlnx,fclk"
+
+Example:
+++++++++
+fclk0: fclk0 {
+	compatible = "xlnx,fclk";
+	clocks = <&clkc 71>;
+};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/mmc/arasan,sdhci.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/mmc/arasan,sdhci.txt
@@ -15,6 +15,12 @@
     - "arasan,sdhci-5.1": generic Arasan SDHCI 5.1 PHY
     - "rockchip,rk3399-sdhci-5.1", "arasan,sdhci-5.1": rk3399 eMMC PHY
       For this device it is strongly suggested to include arasan,soc-ctl-syscon.
+    - "xlnx,zynqmp-8.9a": ZynqMP SDHCI 8.9a PHY
+      For this device it is strongly suggested to include clock-output-names and
+      #clock-cells.
+    - "xlnx,versal-8.9a": Versal SDHCI 8.9a PHY
+      For this device it is strongly suggested to include clock-output-names and
+      #clock-cells.
     - "ti,am654-sdhci-5.1", "arasan,sdhci-5.1": TI AM654 MMC PHY
 	Note: This binding has been deprecated and moved to [5].
     - "intel,lgm-sdhci-5.1-emmc", "arasan,sdhci-5.1": Intel LGM eMMC PHY
@@ -38,14 +44,20 @@
   - clock-output-names: If specified, this will be the name of the card clock
     which will be exposed by this device.  Required if #clock-cells is
     specified.
-  - #clock-cells: If specified this should be the value <0>.  With this property
-    in place we will export a clock representing the Card Clock.  This clock
-    is expected to be consumed by our PHY.  You must also specify
+  - #clock-cells: If specified this should be the value <0> or <1>. With this
+    property in place we will export one or two clocks representing the Card
+    Clock. These clocks are expected to be consumed by our PHY.
   - xlnx,fails-without-test-cd: when present, the controller doesn't work when
     the CD line is not connected properly, and the line is not connected
     properly. Test mode can be used to force the controller to function.
   - xlnx,int-clock-stable-broken: when present, the controller always reports
     that the internal clock is stable even when it is not.
+  - pinctrl-0: pin control group to be used for this controller.
+  - pinctrl-names: must contain a "default" entry.
+
+  - xlnx,mio-bank: When specified, this will indicate the MIO bank number in
+    which the command and data lines are configured. If not specified, driver
+    will assume this as 0.
 
 Example:
 	sdhci@e0100000 {
@@ -83,6 +95,30 @@
 		#clock-cells = <0>;
 	};
 
+	sdhci: mmc@ff160000 {
+		compatible = "xlnx,zynqmp-8.9a", "arasan,sdhci-8.9a";
+		interrupt-parent = <&gic>;
+		interrupts = <0 48 4>;
+		reg = <0x0 0xff160000 0x0 0x1000>;
+		clocks = <&clk200>, <&clk200>;
+		clock-names = "clk_xin", "clk_ahb";
+		clock-output-names = "clk_out_sd0", "clk_in_sd0";
+		#clock-cells = <1>;
+		clk-phase-sd-hs = <63>, <72>;
+	};
+
+	sdhci: mmc@f1040000 {
+		compatible = "xlnx,versal-8.9a", "arasan,sdhci-8.9a";
+		interrupt-parent = <&gic>;
+		interrupts = <0 126 4>;
+		reg = <0x0 0xf1040000 0x0 0x10000>;
+		clocks = <&clk200>, <&clk200>;
+		clock-names = "clk_xin", "clk_ahb";
+		clock-output-names = "clk_out_sd0", "clk_in_sd0";
+		#clock-cells = <1>;
+		clk-phase-sd-hs = <132>, <60>;
+	};
+
 	emmc: sdhci@ec700000 {
 		compatible = "intel,lgm-sdhci-5.1-emmc", "arasan,sdhci-5.1";
 		reg = <0xec700000 0x300>;
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/mmc/mmc-controller.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/mmc/mmc-controller.yaml
@@ -21,7 +21,7 @@
   "#address-cells":
     const: 1
     description: |
-      The cell is the slot ID if a function subnode is used.
+      The cell is the SDIO function number if a function subnode is used.
 
   "#size-cells":
     const: 0
@@ -333,6 +333,18 @@
     required:
       - reg
 
+  "^clk-phase-(legacy|sd-hs|mmc-(hs|hs[24]00|ddr52)|uhs-(sdr(12|25|50|104)|ddr50))$":
+    minItems: 2
+    maxItems: 2
+    allOf:
+      - $ref: /schemas/types.yaml#/definitions/uint32
+      - minimum: 0
+        maximum: 359
+    description:
+      Set the clock (phase) delays which are to be configured in the
+      controller while switching to particular speed mode. These values
+      are in pair of degrees.
+
 dependencies:
   cd-debounce-delay-ms: [ cd-gpios ]
   fixed-emmc-driver-type: [ non-removable ]
@@ -351,6 +363,7 @@
         keep-power-in-suspend;
         wakeup-source;
         mmc-pwrseq = <&sdhci0_pwrseq>;
+        clk-phase-sd-hs = <63>, <72>;
     };
 
   - |
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/mmc/mtk-sd.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/mmc/mtk-sd.txt
@@ -49,6 +49,8 @@
 		     error caused by stop clock(fifo full)
 		     Valid range = [0:0x7]. if not present, default value is 0.
 		     applied to compatible "mediatek,mt2701-mmc".
+- resets: Phandle and reset specifier pair to softreset line of MSDC IP.
+- reset-names: Should be "hrst".
 
 Examples:
 mmc0: mmc@11230000 {
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
@@ -15,8 +15,15 @@
   - "nvidia,tegra210-sdhci": for Tegra210
   - "nvidia,tegra186-sdhci": for Tegra186
   - "nvidia,tegra194-sdhci": for Tegra194
-- clocks : Must contain one entry, for the module clock.
-  See ../clocks/clock-bindings.txt for details.
+- clocks: For Tegra210, Tegra186 and Tegra194 must contain two entries.
+	  One for the module clock and one for the timeout clock.
+	  For all other Tegra devices, must contain a single entry for
+	  the module clock. See ../clocks/clock-bindings.txt for details.
+- clock-names: For Tegra210, Tegra186 and Tegra194 must contain the
+	       strings 'sdhci' and 'tmclk' to represent the module and
+	       the timeout clocks, respectively.
+	       For all other Tegra devices must contain the string 'sdhci'
+	       to represent the module clock.
 - resets : Must contain an entry for each entry in reset-names.
   See ../reset/reset.txt for details.
 - reset-names : Must include the following entries:
@@ -99,7 +106,7 @@
 
 Example:
 sdhci@700b0000 {
-	compatible = "nvidia,tegra210-sdhci", "nvidia,tegra124-sdhci";
+	compatible = "nvidia,tegra124-sdhci";
 	reg = <0x0 0x700b0000 0x0 0x200>;
 	interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
 	clocks = <&tegra_car TEGRA210_CLK_SDMMC1>;
@@ -107,6 +114,25 @@
 	resets = <&tegra_car 14>;
 	reset-names = "sdhci";
 	pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
+	pinctrl-0 = <&sdmmc1_3v3>;
+	pinctrl-1 = <&sdmmc1_1v8>;
+	nvidia,pad-autocal-pull-up-offset-3v3 = <0x00>;
+	nvidia,pad-autocal-pull-down-offset-3v3 = <0x7d>;
+	nvidia,pad-autocal-pull-up-offset-1v8 = <0x7b>;
+	nvidia,pad-autocal-pull-down-offset-1v8 = <0x7b>;
+	status = "disabled";
+};
+
+sdhci@700b0000 {
+	compatible = "nvidia,tegra210-sdhci";
+	reg = <0x0 0x700b0000 0x0 0x200>;
+	interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+	clocks = <&tegra_car TEGRA210_CLK_SDMMC1>,
+		 <&tegra_car TEGRA210_CLK_SDMMC_LEGACY>;
+	clock-names = "sdhci", "tmclk";
+	resets = <&tegra_car 14>;
+	reset-names = "sdhci";
+	pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
 	pinctrl-0 = <&sdmmc1_3v3>;
 	pinctrl-1 = <&sdmmc1_1v8>;
 	nvidia,pad-autocal-pull-up-offset-3v3 = <0x00>;
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/mtd/arasan_nand.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/mtd/arasan_nand.txt
@@ -0,0 +1,33 @@
+Arasan NAND Flash Controller with ONFI 3.1 support
+
+Required properties:
+- compatible:		Should be "xlnx,zynqmp-nand", "arasan,nfc-v3p10"
+- reg:			Memory map for module access
+- interrupt-parent:	Interrupt controller the interrupt is routed through
+- interrupts:		Should contain the interrupt for the device
+- clock-name:		List of input clocks - "sys", "flash"
+			(See clock bindings for details)
+- clocks:		Clock phandles (see clock bindings for details)
+
+Required properties for child node:
+- nand-ecc-mode: see nand.txt
+
+For NAND partition information please refer the below file
+Documentation/devicetree/bindings/mtd/partition.txt
+
+Example:
+	nfc: nand@ff100000 {
+		compatible = "xlnx,zynqmp-nand", "arasan,nfc-v3p10"
+		reg = <0x0 0xff100000 0x1000>;
+		clock-name = "sys", "flash"
+		clocks = <&misc_clk &misc_clk>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 14 4>;
+		#address-cells = <1>;
+		#size-cells = <0>
+
+		nand@0 {
+			reg = <0>
+			nand-ecc-mode = "hw";
+		};
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/mtd/cadence-quadspi.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/mtd/cadence-quadspi.txt
@@ -5,6 +5,7 @@
 	Generic default - "cdns,qspi-nor".
 	For TI 66AK2G SoC - "ti,k2g-qspi", "cdns,qspi-nor".
 	For TI AM654 SoC  - "ti,am654-ospi", "cdns,qspi-nor".
+	For xilinx versal - "xlnx,versal-ospi-1.0".
 - reg : Contains two entries, each of which is a tuple consisting of a
 	physical address and length. The first entry is the address and
 	length of the controller register set. The second entry is the
@@ -14,6 +15,7 @@
 - cdns,fifo-depth : Size of the data FIFO in words.
 - cdns,fifo-width : Bus width of the data FIFO in bytes.
 - cdns,trigger-address : 32-bit indirect AHB trigger address.
+- reset-gpios : GPIO to be used to reset the OSPI flash device.
 
 Optional properties:
 - cdns,is-decoded-cs : Flag to indicate whether decoder is used or not.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/mtd/gpmc-nand.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/mtd/gpmc-nand.txt
@@ -122,7 +122,7 @@
 	so the device should have enough free bytes available its OOB/Spare
 	area to accommodate ECC for entire page. In general following expression
 	helps in determining if given device can accommodate ECC syndrome:
-	"2 + (PAGESIZE / 512) * ECC_BYTES" >= OOBSIZE"
+	"2 + (PAGESIZE / 512) * ECC_BYTES" <= OOBSIZE"
 	where
 		OOBSIZE		number of bytes in OOB/spare area
 		PAGESIZE	number of bytes in main-area of device page
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt
@@ -78,6 +78,14 @@
 		   cannot reboot properly if the flash is left in the "wrong"
 		   state. This boolean flag can be used on such systems, to
 		   denote the absence of a reliable reset mechanism.
+ - multi-die 	:  Some flash devices have multiple dies in it. Read operation
+		   in these devices is bounded by its die segment. In a
+		   continuous read, across multiple dies, when the last byte of
+		   the selected die segment is read, the next byte read is the
+		   first byte of the same die segment. So to handle this issue,
+		   split a read transaction, that spans across multiple banks,
+		   into one read per bank.This boolean flag can be used for such
+		   flash devices, to denote the presence of multiple dies.
 
 Example:
 
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/mtd/nand-controller.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/mtd/nand-controller.yaml
@@ -44,7 +44,7 @@
     properties:
       reg:
         description:
-          Contains the native Ready/Busy IDs.
+          Contains the chip-select IDs.
 
       nand-ecc-mode:
         allOf:
@@ -139,6 +139,6 @@
         nand-ecc-mode = "soft";
         nand-ecc-algo = "bch";
 
-        /* controller specific properties */
+        /* NAND chip specific properties */
       };
     };
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/net/btusb.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/net/btusb.txt
@@ -38,7 +38,7 @@
 	compatible = "usb1286,204e";
 	reg = <1>;
 	interrupt-parent = <&gpio0>;
-	interrupt-name = "wakeup";
+	interrupt-names = "wakeup";
 	interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
     };
 };
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/net/can/tcan4x5x.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/net/can/tcan4x5x.txt
@@ -31,9 +31,9 @@
 		#address-cells = <1>;
 		#size-cells = <1>;
 		spi-max-frequency = <10000000>;
-		bosch,mram-cfg = <0x0 0 0 32 0 0 1 1>;
+		bosch,mram-cfg = <0x0 0 0 16 0 0 1 1>;
 		interrupt-parent = <&gpio1>;
-		interrupts = <14 GPIO_ACTIVE_LOW>;
+		interrupts = <14 IRQ_TYPE_LEVEL_LOW>;
 		device-state-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;
 		device-wake-gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>;
 		reset-gpios = <&gpio1 27 GPIO_ACTIVE_LOW>;
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/net/ethernet-controller.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/net/ethernet-controller.yaml
@@ -51,7 +51,7 @@
     description:
       Reference to an nvmem node for the MAC address
 
-  nvmem-cells-names:
+  nvmem-cell-names:
     const: mac-address
 
   phy-connection-type:
@@ -190,6 +190,11 @@
                 Indicates that full-duplex is used. When absent, half
                 duplex is assumed.
 
+            pause:
+              $ref: /schemas/types.yaml#definitions/flag
+              description:
+                Indicates that pause should be enabled.
+
             asym-pause:
               $ref: /schemas/types.yaml#definitions/flag
               description:
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/net/ethernet-phy.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/net/ethernet-phy.yaml
@@ -87,6 +87,14 @@
       compensate for the board being designed with the lanes
       swapped.
 
+  enet-phy-lane-no-swap:
+    $ref: /schemas/types.yaml#/definitions/flag
+    description:
+      If set, indicates that PHY will disable swap of the
+      TX/RX lanes. This property allows the PHY to work correcly after
+      e.g. wrong bootstrap configuration caused by issues in PCB
+      layout design.
+
   eee-broken-100tx:
     $ref: /schemas/types.yaml#definitions/flag
     description:
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/net/fsl-fman.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/net/fsl-fman.txt
@@ -110,6 +110,13 @@
 		Usage: required
 		Definition: See soc/fsl/qman.txt and soc/fsl/bman.txt
 
+- fsl,erratum-a050385
+		Usage: optional
+		Value type: boolean
+		Definition: A boolean property. Indicates the presence of the
+		erratum A050385 which indicates that DMA transactions that are
+		split can result in a FMan lock.
+
 =============================================================================
 FMan MURAM Node
 
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/net/macb.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/net/macb.txt
@@ -16,6 +16,7 @@
   Use "cdns,zynq-gem" Xilinx Zynq-7xxx SoC.
   Use "cdns,zynqmp-gem" for Zynq Ultrascale+ MPSoC.
   Use "sifive,fu540-c000-gem" for SiFive FU540-C000 SoC.
+  Use "cdns,versal-gem" for Xilinx Versal.
   Or the generic form: "cdns,emac".
 - reg: Address and length of the register set for the device
 	For "sifive,fu540-c000-gem", second range is required to specify the
@@ -38,12 +39,18 @@
   up via magic packet.
 - phy-handle : see ethernet.txt file in the same directory
 
+Optional properties:
+- rx-watermark: Set watermark value for pbuf_rxcutthru reg and enable
+  rx partial store and forward, only when compatible = "cdns,zynqmp-gem".
+  Value should be less than 0xFFF.
+
 Examples:
 
 	macb0: ethernet@fffc4000 {
 		compatible = "cdns,at32ap7000-macb";
 		reg = <0xfffc4000 0x4000>;
 		interrupts = <21>;
+		rx-watermark = /bits/ 16 <0x44>;
 		phy-mode = "rmii";
 		local-mac-address = [3a 0e 03 04 05 06];
 		clock-names = "pclk", "hclk", "tx_clk";
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/net/mscc-phy-vsc8531.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/net/mscc-phy-vsc8531.txt
@@ -31,7 +31,14 @@
 			  VSC8531_LINK_100_ACTIVITY (2),
 			  VSC8531_LINK_ACTIVITY (0) and
 			  VSC8531_DUPLEX_COLLISION (8).
-
+- vsc8531,rx-delay	: RGMII RX delay. Allowed values are defined in
+			  "include/dt-bindings/net/mscc-phy-vsc8531.h".
+			  Default value, set by the driver is
+			  VSC8531_RGMII_CLK_DELAY_1_1_NS.
+- vsc8531,tx-delay	: RGMII TX delay. Allowed values are defined in
+			  "include/dt-bindings/net/mscc-phy-vsc8531.h".
+			  Default value, set by the driver is
+			  VSC8531_RGMII_CLK_DELAY_0_2_NS.
 
 Table: 1 - Edge rate change
 ----------------------------------------------------------------|
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/net/nfc/nxp-nci.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/net/nfc/nxp-nci.txt
@@ -25,7 +25,7 @@
 		clock-frequency = <100000>;
 
 		interrupt-parent = <&gpio1>;
-		interrupts = <29 GPIO_ACTIVE_HIGH>;
+		interrupts = <29 IRQ_TYPE_LEVEL_HIGH>;
 
 		enable-gpios = <&gpio0 30 GPIO_ACTIVE_HIGH>;
 		firmware-gpios = <&gpio0 31 GPIO_ACTIVE_HIGH>;
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/net/nfc/pn544.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/net/nfc/pn544.txt
@@ -25,7 +25,7 @@
 		clock-frequency = <400000>;
 
 		interrupt-parent = <&gpio1>;
-		interrupts = <17 GPIO_ACTIVE_HIGH>;
+		interrupts = <17 IRQ_TYPE_LEVEL_HIGH>;
 
 		enable-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;
 		firmware-gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>;
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/net/snps,dwmac.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/net/snps,dwmac.yaml
@@ -347,6 +347,7 @@
               - st,spear600-gmac
 
     then:
+      properties:
         snps,tso:
           $ref: /schemas/types.yaml#definitions/flag
           description:
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt
@@ -81,6 +81,12 @@
 	Definition: Name of external front end module used. Some valid FEM names
 		    for example: "microsemi-lx5586", "sky85703-11"
 		    and "sky85803" etc.
+- qcom,snoc-host-cap-8bit-quirk:
+	Usage: Optional
+	Value type: <empty>
+	Definition: Quirk specifying that the firmware expects the 8bit version
+		    of the host capability QMI request
+
 
 Example (to supply PCI based wifi block details):
 
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/net/xilinx-phy.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/net/xilinx-phy.txt
@@ -0,0 +1,15 @@
+Xilinx PCS/PMA PHY bindings
+
+Required properties:
+	- reg - The ID number for the phy, usually a small integer
+
+Optional properties:
+	- xlnx,phy-type - Describes type 1000BaseX (set to 0x5) or
+			  SGMII (set to 0x4)
+
+Example:
+
+	ethernet-phy@9 {
+		reg = <9>;
+		xlnx,phy-type = <0x5>;
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/net/xilinx-tsn-ethernet.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/net/xilinx-tsn-ethernet.txt
@@ -0,0 +1,54 @@
+Xilinx TSN (time sensitive networking) TEMAC axi ethernet driver (xilinx_axienet)
+-----------------------------------------------------------------------
+
+Required properties:
+- compatible		: Should be "xlnx,tsn-ethernet-1.00.a".
+- reg			: Physical base address and size of the TSN registers map.
+- interrupts		: Property with a value describing the interrupt
+			  number.
+- interrupts-names	: Property denotes the interrupt names.
+- interrupt-parent	: Must be core interrupt controller.
+- phy-handle		: See ethernet.txt file [1].
+- local-mac-address	: See ethernet.txt file [1].
+- phy-mode		: see ethernet.txt file [1].
+
+Optional properties:
+- xlnx,tsn		: Denotes a ethernet with TSN capabilities.
+- xlnx,tsn-slave	: Denotes a TSN slave port.
+- xlnx,txcsum		: Tx checksum mode (Full, Partial and None).
+- xlnx,rxcsum		: Rx checksum mode (Full, Partial and None).
+- xlnx,phy-type		: Xilinx phy device type. See xilinx-phy.txt [2].
+- xlnx,eth-hasnobuf	: Used when 1G MAC is configured in non-processor mode.
+- xlnx,num-queue	: Number of queue supported in current design, range is
+			  2 to 5 and default value is 5.
+- xlnx,num-tc		: Number of traffic class supported in current design,
+			  range is 2,3 and default value is 3. It denotes
+			  the traffic classes based on VLAN-PCP value.
+- xlnx,qbv-addr		: Denotes mac scheduler physical base address.
+- xlnx,qbv-size		: Denotes mac scheduler address space size.
+
+[1] Documentation/devicetree/bindings/net/ethernet.txt
+[2] Documentation/devicetree/bindings/net/xilinx-phy.txt
+
+Example:
+
+	tsn_emac_0: tsn_mac@80040000 {
+		compatible = "xlnx,tsn-ethernet-1.00.a";
+		interrupt-parent = <&gic>;
+		interrupts = <0 104 4 0 106 4 0 91 4 0 110 4>;
+		interrupt-names = "interrupt_ptp_rx_1", "interrupt_ptp_tx_1", "mac_irq_1", "interrupt_ptp_timer";
+		local-mac-address = [ 00 0A 35 00 01 0e ];
+		phy-mode = "rgmii";
+		reg = <0x0 0x80040000 0x0 0x14000>;
+		tsn,endpoint = <&tsn_ep>;
+		xlnx,tsn;
+		xlnx,tsn-slave;
+		xlnx,phy-type = <0x3>;
+		xlnx,eth-hasnobuf;
+		xlnx,num-queue = <0x2>;
+		xlnx,num-tc = <0x3>;
+		xlnx,qbv-addr = <0x80054000>;
+		xlnx,qbv-size = <0x2000>;
+		xlnx,txsum = <0>;
+		xlnx,rxsum = <0>;
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/net/xilinx_axienet.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/net/xilinx_axienet.txt
@@ -1,34 +1,59 @@
 XILINX AXI ETHERNET Device Tree Bindings
 --------------------------------------------------------
 
-Also called  AXI 1G/2.5G Ethernet Subsystem, the xilinx axi ethernet IP core
-provides connectivity to an external ethernet PHY supporting different
-interfaces: MII, GMII, RGMII, SGMII, 1000BaseX. It also includes two
-segments of memory for buffering TX and RX, as well as the capability of
-offloading TX/RX checksum calculation off the processor.
+This driver supports following MAC configurations-
+a) AXI 1G/2.5G Ethernet Subsystem.
+b) 10G/25G High Speed Ethernet Subsystem.
+c) 10 Gigabit Ethernet Subsystem.
+d) USXGMII Ethernet Subsystem.
+e) MRMAC Ethernet Subsystem.
+
+AXI 1G/2.5G Ethernet Subsystem- also called  AXI 1G/2.5G Ethernet Subsystem,
+the xilinx axi ethernet IP core provides connectivity to an external ethernet
+PHY supporting different interfaces: MII, GMII, RGMII, SGMII, 1000BaseX.
+It also includes two segments of memory for buffering TX and RX, as well as
+the capability of offloading TX/RX checksum calculation off the processor.
 
 Management configuration is done through the AXI interface, while payload is
 sent and received through means of an AXI DMA controller. This driver
 includes the DMA driver code, so this driver is incompatible with AXI DMA
 driver.
 
-For more details about mdio please refer phy.txt file in the same directory.
+MRMAC is a hardened Ethernet IP on Versal supporting multiple rates from
+10G to 100G which can be used with a soft DMA controller.
+
+For details about MDIO please refer phy.txt [1].
 
 Required properties:
-- compatible	: Must be one of "xlnx,axi-ethernet-1.00.a",
-		  "xlnx,axi-ethernet-1.01.a", "xlnx,axi-ethernet-2.01.a"
+- compatible	: Must be one of "xlnx,axi-ethernet-1.00.a" or
+		  "xlnx,axi-ethernet-1.01.a" or "xlnx,axi-ethernet-2.01.a"
+		  for 1G MAC,
+		  "xlnx,ten-gig-eth-mac" for 10 Gigabit Ethernet Subsystem,
+		  "xlnx,xxv-ethernet-1.0" for 10G/25G MAC,
+		  "xlnx,axi-2_5-gig-ethernet-1.0" for 2.5G MAC,
+		  "xlnx,xxv-usxgmii-ethernet-1.0" for USXGMII and
+		  "xlnx,mrmac-ethernet-1.0" for MRMAC.
 - reg		: Address and length of the IO space, as well as the address
                   and length of the AXI DMA controller IO space, unless
                   axistream-connected is specified, in which case the reg
                   attribute of the node referenced by it is used.
 - interrupts	: Should be a list of 2 or 3 interrupts: TX DMA, RX DMA,
-		  and optionally Ethernet core. If axistream-connected is
-		  specified, the TX/RX DMA interrupts should be on that node
-		  instead, and only the Ethernet core interrupt is optionally
-		  specified here.
+		  and optionally Ethernet core.
 - phy-handle	: Should point to the external phy device.
 		  See ethernet.txt file in the same directory.
 - xlnx,rxmem	: Set to allocated memory buffer for Rx/Tx in the hardware
+Required properties (When AxiEthernet is configured with MCDMA):
+- xlnx,channel-ids	: Queue Identifier associated with the MCDMA Channel.
+- interrupt-names	: Should contain the interrupt names.
+
+Required properties when configured as MRMAC:
+- xlnx,mrmac-rate	: Can be 10000 or 25000 providing rate in Mbps.
+- xlnx,gtlane		: Indicate the GT reset and speed control lane for the
+			  the current MRMAC lane. Valid range is 0 to 3.
+- xlnx,gtpll		: Handle to AXI GPIO instance for GT PLL mask control.
+			  This is required to control the common PLL mask bits.
+- xlnx,gtctrl		: Handle to AXI GPIO instance for GT speed and reset
+			  control for each MRMAC lane.
 
 Optional properties:
 - phy-mode	: See ethernet.txt
@@ -38,39 +63,106 @@
 		  1 to enable partial TX checksum offload,
 		  2 to enable full TX checksum offload
 - xlnx,rxcsum	: Same values as xlnx,txcsum but for RX checksum offload
-- clocks	: AXI bus clock for the device. Refer to common clock bindings.
-		  Used to calculate MDIO clock divisor. If not specified, it is
-		  auto-detected from the CPU clock (but only on platforms where
-		  this is possible). New device trees should specify this - the
-		  auto detection is only for backward compatibility.
-- axistream-connected: Reference to another node which contains the resources
-		       for the AXI DMA controller used by this device.
-		       If this is specified, the DMA-related resources from that
-		       device (DMA registers and DMA TX/RX interrupts) rather
-		       than this one will be used.
+- clocks		: Input clock specifier. Refer to common clock bindings.
+- clock-names		: Input clock names. Refer to IP PG for signal description.
+			  1G/2.5G: s_axi_lite_clk, axis_clk and ref_clk.
+			  10G/25G and USXGMII: s_axi_aclk, rx_core_clk and dclk.
+			  10 Gigabit: s_axi_aclk and dclk.
+			  AXI DMA and MCDMA: m_axi_sg_aclk, m_axi_mm2s_aclk and
+			  m_axi_s2mm_aclk.
  - mdio		: Child node for MDIO bus. Must be defined if PHY access is
 		  required through the core's MDIO interface (i.e. always,
 		  unless the PHY is accessed through a different bus).
+- dma-coherent		: Present if dma operations are coherent.
+- xlnx,eth-hasnobuf	: Used when 1G MAC is configured in non-processor mode.
+- xlnx,rxtsfifo		: Configures the axi fifo for receive timestamping.
+
+Optional properties for connected DMA node:
+- xlnx,addrwidth	: Specify the width of the DMA address space in bits.
+			  Value type is u8. Valid range is 32-64. Default is 32.
+- xlnx,include-dre	: Tells whether DMA h/w is configured with data
+			  realignment engine(DRE) or not.
+
+Optional properties (When USXGMII is in use):
+- xlnx,usxgmii-rate	: USXGMII PHY speed - can be 10, 100, 1000, 2500,
+			  5000 or 10000.
+
+Optional properties (When AxiEthernet is configured with MCDMA):
+- xlnx,num-queues	: Number of queues h/w configured for.
+
+Optional properties for MRMAC:
+- xlnx,phcindex		: Indicate the index of the physical hardware clock
+			  to be used as per PTP clock connected to the given
+			  MRMAC lane. Valid range is 0 to 3.
+
+NOTE: Time Sensitive Networking (TSN) related DT bindings are explained in [4].
+
+[1] Documentation/devicetree/bindings/net/phy.txt
+[2] Documentation/devicetree/bindings/net/ethernet.txt
+[3] Documentation/devicetree/bindings/net/xilinx-phy.txt
+[4] Documentation/devicetree/bindings/net/xilinx_tsn.txt
+
+
+Example: AXI 1G/2.5G Ethernet Subsystem + AXIDMA
+
+	axi_eth_0_dma: dma@80040000 {
+			#dma-cells = <1>;
+			compatible = "xlnx,eth-dma";
+			xlnx,addrwidth = /bits/ 8 <32>;
+			<snip>
+	};
 
-Example:
-	axi_ethernet_eth: ethernet@40c00000 {
-		compatible = "xlnx,axi-ethernet-1.00.a";
-		device_type = "network";
-		interrupt-parent = <&microblaze_0_axi_intc>;
-		interrupts = <2 0 1>;
-		clocks = <&axi_clk>;
-		phy-mode = "mii";
-		reg = <0x40c00000 0x40000 0x50c00000 0x40000>;
-		xlnx,rxcsum = <0x2>;
-		xlnx,rxmem = <0x800>;
-		xlnx,txcsum = <0x2>;
-		phy-handle = <&phy0>;
-		axi_ethernetlite_0_mdio: mdio {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			phy0: phy@0 {
-				device_type = "ethernet-phy";
-				reg = <1>;
+	axi_eth_0: ethernet@80000000 {
+			axistream-connected = <&axi_eth_0_dma>;
+			compatible = "xlnx,axi-ethernet-1.00.a";
+			device_type = "network";
+			interrupt-names = "interrupt";
+			interrupt-parent = <&gic>;
+			interrupts = <0 91 4>;
+			phy-handle = <&phy2>;
+			phy-mode = "sgmii";
+			reg = <0x0 0x80000000 0x0 0x40000>;
+			xlnx,include-dre ;
+			xlnx,phy-type = <0x5>;
+			xlnx,rxcsum = <0x0>;
+			xlnx,rxmem = <0x1000>;
+			xlnx,txcsum = <0x0>;
+			axi_eth_0_mdio: mdio {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				phy2: phy@2 {
+					device_type = "ethernet-phy";
+					reg = <2>;
+				};
 			};
-		};
+	};
+
+Example for MRMAC Ethernet subsystem with MCDMA:
+	axi_mcdma_0: axi_mcdma@a4050000 {
+			#dma-cells = <1>;
+			compatible = "xlnx,axi-mcdma-1.1";
+			xlnx,addrwidth = <0x20>;
+			xlnx,include-dre;
+			<snip>
+	};
+
+	gt_pll: gpio@a4000000 {
+		reg = <0x0 0xa4000000 0x0 0x10000>;
+		<snip>
+	}
+
+	gt_ctrl: gpio@a4010000 {
+		reg = <0x0 0xa4010000 0x0 0x40000>;
+		<snip>
+	};
+
+	mrmac_0: mrmac@80000000 {
+		axistream-connected = <&axi_mcdma_0>;
+		compatible = "xlnx,mrmac-ethernet-1.0";
+		reg = <0x0 0xa4090000 0x0 0x1000>;
+		xlnx,mrmac-rate = <10000>;
+		xlnx,gtpll = <&gt_pll>;
+		xlnx,gtctrl = <&gt_ctrl>;
+		xlnx,gtlane = <0x0>;
+		xlnx,rxmem = <0x8000>;
 	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/net/xilinx_emaclite.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/net/xilinx_emaclite.txt
@@ -0,0 +1,35 @@
+Xilinx Axi Ethernetlite controller Device Tree Bindings
+---------------------------------------------------------
+
+Required properties:
+- compatible		: Should be "xlnx,opb-ethernetlite-1.01.a" or
+			  "xlnx,opb-ethernetlite-1.01.b" or
+			  "xlnx,opb-ethernetlite-1.00.a" or
+			  "xlnx,xps-ethernetlite-2.00.a" or
+			  "xlnx,xps-ethernetlite-2.01.a" or
+			  "xlnx,xps-ethernetlite-3.00.a" or.
+- reg			: Physical base address and size of the Axi ethernetlite
+			  registers map.
+- interrupts		: Property with a value describing the interrupt
+			  number.
+- interrupt-parent	: Must be core interrupt controller.
+- phy-handle		: See ethernet.txt file in the same directory.
+
+Optional properties:
+- local-mac-address	: See ethernet.txt file in the same directory.
+			  If absent, random mac address is selected.
+- xlnx,tx-ping-pong	: If present, hardware supports tx ping pong buffer.
+- xlnx,rx-ping-pong	: If present, hardware supports rx ping pong buffer.
+
+Example:
+	axi_ethernetlite_1: ethernet@40e00000 {
+                        compatible = "xlnx,axi-ethernetlite-3.0", "xlnx,xps-ethernetlite-1.00.a";
+                        device_type = "network";
+                        interrupt-parent = <&axi_intc_1>;
+                        interrupts = <1 0>;
+                        local-mac-address = [00 0a 35 00 00 00];
+                        phy-handle = <&phy0>;
+                        reg = <0x40e00000 0x10000>;
+                        xlnx,rx-ping-pong;
+                        xlnx,tx-ping-pong;
+	}
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/net/xilinx_tsn.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/net/xilinx_tsn.txt
@@ -0,0 +1,14 @@
+Xilinx TSN (time sensitive networking) IP driver (xilinx_tsn_ip)
+-----------------------------------------------------------------------
+
+Required properties:
+- compatible		: Should be one of "xlnx,tsn-endpoint-ethernet-mac-1.0",
+			  "xlnx,tsn-endpoint-ethernet-mac-2.0" for TSN.
+- reg			: Physical base address and size of the TSN registers map.
+
+Example:
+
+	tsn_endpoint_ip_0: tsn_endpoint_ip_0 {
+		compatible = "xlnx,tsn-endpoint-ethernet-mac-2.0";
+		reg = <0x0 0x80040000 0x0 0x40000>;
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/net/xilinx_tsn_ep.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/net/xilinx_tsn_ep.txt
@@ -0,0 +1,35 @@
+Xilinx TSN (time sensitive networking) EndPoint Driver (xilinx_tsn_ep)
+-------------------------------------------------------------------------------
+
+Required properties:
+- compatible		: Should be "xlnx,tsn-ep"
+- reg			: Physical base address and size of the TSN Endpoint
+				registers map
+- interrupts		: Property with a value describing the interrupt
+- interrupts-names	: Property denotes the interrupt names.
+- interrupt-parent	: Must be core interrupt controller.
+- local-mac-address	: See ethernet.txt [1].
+
+Optional properties:
+- xlnx,num-tc		: Number of traffic class supported in current design,
+			  range is 2,3 and default value is 3. It denotes
+			  the traffic classes based on VLAN-PCP value.
+- xlnx,channel-ids 	: Queue Identifier associated with the MCDMA Channel, range
+			  is Tx: "1 to 2" and Rx: "2 to 5", default value is "1 to 5".
+- xlnx,eth-hasnobuf	: Used when 1G MAC is configured in non processor mode.
+
+[1] Documentation/devicetree/bindings/net/ethernet.txt
+
+Example:
+
+	tsn_ep: tsn_ep@80056000 {
+		compatible = "xlnx,tsn-ep";
+		reg = <0x0 0x80056000 0x0 0xA000>;
+		xlnx,num-tc = <0x3>;
+		interrupt-names = "tsn_ep_scheduler_irq";
+		interrupt-parent = <&gic>;
+		interrupts = <0 111 4>;
+		local-mac-address = [00 0A 35 00 01 10];
+		xlnx,channel-ids = "1","2","3","4","5";
+		xlnx,eth-hasnobuf ;
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/net/xilinx_tsn_switch.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/net/xilinx_tsn_switch.txt
@@ -0,0 +1,23 @@
+Xilinx TSN (time sensitive networking) Switch Driver (xilinx_tsn_switch)
+-----------------------------------------------------------------------------
+
+Required properties:
+- compatible		: Should be "xlnx,tsn-switch"
+- reg			: Physical base address and size of the TSN registers map.
+
+Optional properties:
+- xlnx,num-tc		: Number of traffic class supported in current design,
+			  range is 2,3 and default value is 3. It denotes
+			  the traffic classes based on VLAN-PCP value.
+- xlnx,has-hwaddr-learning	: Denotes hardware address learning support
+- xlnx,has-inband-mgmt-tag	: Denotes inband management support
+
+Example:
+
+	epswitch: tsn_switch@80078000 {
+		compatible = "xlnx,tsn-switch";
+		reg = <0x0 0x80078000 0x0 0x4000>;
+		xlnx,num-tc = <0x3>;
+		xlnx,has-hwaddr-learning ;
+		xlnx,has-inband-mgmt-tag ;
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/nvmem/xlnx,zynqmp-nvmem.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/nvmem/xlnx,zynqmp-nvmem.txt
@@ -25,9 +25,78 @@
 			#size-cells = <1>;
 
 			/* Data cells */
-			soc_revision: soc_revision {
+			soc_revision: soc_revision@0 {
 				reg = <0x0 0x4>;
 			};
+			/*
+			* efuse memory access:
+			* all the efuse feilds need to be read
+			* with the exact size specified in the node
+			*/
+			/* DNA */
+			efuse_dna: efuse_dna@c {
+				reg = <0xc 0xc>;
+			};
+			/* User 0 */
+			efuse_usr0: efuse_usr0@20 {
+				reg = <0x20 0x4>;
+			};
+			/* User 1 */
+			efuse_usr1: efuse_usr1@24 {
+				reg = <0x24 0x4>;
+			};
+			/* User 2 */
+			efuse_usr2: efuse_usr2@28 {
+				reg = <0x28 0x4>;
+			};
+			/* User 3 */
+			efuse_usr3: efuse_usr3@2c {
+				reg = <0x2c 0x4>;
+			};
+			/* User 4 */
+			efuse_usr4: efuse_usr4@30 {
+				reg = <0x30 0x4>;
+			};
+			/* User 5 */
+			efuse_usr5: efuse_usr5@34 {
+				reg = <0x34 0x4>;
+			};
+			/* User 6 */
+			efuse_usr6: efuse_usr6@38 {
+				reg = <0x38 0x4>;
+			};
+			/* User 7 */
+			efuse_usr7: efuse_usr7@3c {
+				reg = <0x3c 0x4>;
+			};
+			/* Misc user control bits */
+			efuse_miscusr: efuse_miscusr@40 {
+				reg = <0x40 0x4>;
+			};
+			/* PUF chash */
+			efuse_chash: efuse_chash@50 {
+				reg = <0x50 0x4>;
+			};
+			/* PUF misc */
+			efuse_pufmisc: efuse_pufmisc@54 {
+				reg = <0x54 0x4>;
+			};
+			/* SEC_CTRL */
+			efuse_sec: efuse_sec@58 {
+				reg = <0x58 0x4>;
+			};
+			/* SPK ID */
+			efuse_spkid: efuse_spkid@5c {
+				reg = <0x5c 0x4>;
+			};
+			/* PPK0 hash */
+			efuse_ppk0hash: efuse_ppk0hash@a0 {
+				reg = <0xa0 0x30>;
+			};
+			/* PPK1 hash */
+			efuse_ppk1hash: efuse_ppk1hash@d0 {
+				reg = <0xd0 0x30>;
+			};
 		};
 	};
 };
@@ -44,3 +113,22 @@
 
 		...
 	};
+
+To program efuse memory, one should request specified bytes of size as below,
+NOTE: Efuse bits once programmed cannot be reverted.
+
+	- | TYPE	| OFFSET | SIZE(bytes)	|
+	- |User-0	| 0x20	 | 0x4		|
+	- |User-1	| 0x24	 | 0x4		|
+	- |User-2	| 0x28	 | 0x4		|
+	- |User-3	| 0x2C	 | 0x4		|
+	- |User-4	| 0x30	 | 0x4		|
+	- |User-5	| 0x34	 | 0x4		|
+	- |User-6	| 0x38	 | 0x4		|
+	- |User-7	| 0x3c	 | 0x4		|
+	- |Misc User	| 0x40	 | 0x4		|
+	- |SEC_CTRL	| 0x58	 | 0x4		|
+	- |SPK ID 	| 0x5C	 | 0x4		|
+	- |AES KEY 	| 0x60	 | 0x20		|
+	- |PPK0 hash	| 0xA0	 | 0x30		|
+	- |PPK1 hash	| 0xD0	 | 0x30		|
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/pci/nvidia,tegra194-pcie.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/pci/nvidia,tegra194-pcie.txt
@@ -118,7 +118,7 @@
 --------
 
 	pcie@14180000 {
-		compatible = "nvidia,tegra194-pcie", "snps,dw-pcie";
+		compatible = "nvidia,tegra194-pcie";
 		power-domains = <&bpmp TEGRA194_POWER_DOMAIN_PCIEX8B>;
 		reg = <0x00 0x14180000 0x0 0x00020000   /* appl registers (128K)      */
 		       0x00 0x38000000 0x0 0x00040000   /* configuration space (256K) */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/pci/xilinx-nwl-pcie.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/pci/xilinx-nwl-pcie.txt
@@ -18,6 +18,7 @@
 	"msi1, msi0": interrupt asserted when an MSI is received
 	"intx": interrupt asserted when a legacy interrupt is received
 	"misc": interrupt asserted when miscellaneous interrupt is received
+- clocks: Should contain a clock specifier for the device
 - interrupt-map-mask and interrupt-map: standard PCI properties to define the
 	mapping of the PCI interface to interrupt numbers.
 - ranges: ranges for the PCI memory regions (I/O space region is not
@@ -52,6 +53,7 @@
 			<0x0 0x0 0x0 0x2 &pcie_intc 0x2>,
 			<0x0 0x0 0x0 0x3 &pcie_intc 0x3>,
 			<0x0 0x0 0x0 0x4 &pcie_intc 0x4>;
+	clocks = <&clkc 23>
 
 	msi-parent = <&nwl_pcie>;
 	reg = <0x0 0xfd0e0000 0x0 0x1000>,
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/pci/xilinx-xdma-pl-pcie.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/pci/xilinx-xdma-pl-pcie.txt
@@ -0,0 +1,167 @@
+* Xilinx XDMA PL PCIe Root Port Bridge DT description
+
+Required properties:
+- #address-cells: Address representation for root ports, set to <3>
+- #size-cells: Size representation for root ports, set to <2>
+- #interrupt-cells: specifies the number of cells needed to encode an
+	interrupt source. The value must be 1.
+- compatible: Should contain "xlnx,xdma-host-3.00"
+- reg: Should contain XDMA PCIe registers location and length
+- device_type: must be "pci"
+- interrupts: Should contain AXI PCIe interrupt
+- interrupt-map-mask,
+  interrupt-map: standard PCI properties to define the mapping of the
+	PCI interface to interrupt numbers.
+- ranges: ranges for the PCI memory regions (I/O space region is not
+	supported by hardware)
+	Please refer to the standard PCI bus binding document for a more
+	detailed explanation
+
+For MSI DECODE mode:
+- interrupt-names: Must include the following entries:
+	"misc": interrupt asserted when legacy or error interrupt is received
+	"msi1, msi0": interrupt asserted when an MSI is received
+
+Interrupt controller child node
++++++++++++++++++++++++++++++++
+Required properties:
+- interrupt-controller: identifies the node as an interrupt controller
+- #address-cells: specifies the number of cells needed to encode an
+	address. The value must be 0.
+- #interrupt-cells: specifies the number of cells needed to encode an
+	interrupt source. The value must be 1.
+
+NOTE:
+The core provides a single interrupt for both INTx/MSI messages. So,
+created a interrupt controller node to support 'interrupt-map' DT
+functionality.  The driver will create an IRQ domain for this map, decode
+the four INTx interrupts in ISR and route them to this domain.
+
+
+Example:
+++++++++
+MSI FIFO mode:
+	xdma_0: axi-pcie@a0000000 {
+		#address-cells = <3>;
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		compatible = "xlnx,xdma-host-3.00";
+		device_type = "pci";
+		interrupt-map = <0 0 0 1 &pcie_intc_0 1>,
+				<0 0 0 2 &pcie_intc_0 2>,
+				<0 0 0 3 &pcie_intc_0 3>,
+				<0 0 0 4 &pcie_intc_0 4>;
+		interrupt-map-mask = <0 0 0 7>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 89 4>;
+		ranges = <0x02000000 0x00000000 0xB0000000 0x0 0xB0000000 0x00000000 0x01000000>,
+			<0x43000000 0x00000005 0x00000000 0x00000005 0x00000000 0x00000000 0x01000000>;
+		reg = <0x0 0xA0000000 0x0 0x10000000>;
+		pcie_intc_0: interrupt-controller {
+			#address-cells = <0>;
+			#interrupt-cells = <1>;
+			interrupt-controller ;
+		};
+	};
+
+MSI DECODE mode:
+	xdma_0: axi-pcie@a0000000 {
+		#address-cells = <3>;
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		compatible = "xlnx,xdma-host-3.00";
+		device_type = "pci";
+		interrupt-map = <0 0 0 1 &pcie_intc_0 1>, <0 0 0 2 &pcie_intc_0 2>, <0 0 0 3 &pcie_intc_0 3>, <0 0 0 4 &pcie_intc_0 4>;
+		interrupt-map-mask = <0 0 0 7>;
+		interrupt-parent = <&gic>;
+		interrupt-names = "misc", "msi0", "msi1";
+		interrupts = <0 89 4>, <0 90 4>, <0 91 4>;
+		ranges = <0x02000000 0x00000000 0xB0000000 0x0 0xB0000000 0x00000000 0x01000000>,
+			<0x43000000 0x00000005 0x00000000 0x00000005 0x00000000 0x00000000 0x01000000>;
+		reg = <0x0 0xA0000000 0x0 0x10000000>;
+		pcie_intc_0: interrupt-controller {
+			#address-cells = <0>;
+			#interrupt-cells = <1>;
+			interrupt-controller ;
+		};
+	};
+
+Versal CPM host Bridge DT description.
+
+The properties and their meanings are identical to those described in
+above Xilinx XDMA PL PCIe Root Port Bridge description.
+
+Properties that differ are:
+- compatible: Should contain "xlnx,versal-cpm-host-1.00"
+- reg: Should contain configuration space and CPM system level control and
+	status registers, and length
+- reg-names: Must include the following entries:
+	"cfg": configuration space region
+	"cpm_slcr": CPM system level control and status registers
+- msi-map: Maps a Requester ID to an MSI controller and associated MSI
+	sideband data
+
+Refer to the following binding document for more detailed description on
+the use of 'msi-map':
+	 Documentation/devicetree/bindings/pci/pci-msi.txt
+
+Example:
+	pci@fca10000 {
+		#address-cells = <3>;
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		compatible = "xlnx,versal-cpm-host-1.00";
+		interrupt-map = <0 0 0 1 &pcie_intc_0 1>,
+				<0 0 0 2 &pcie_intc_0 2>,
+				<0 0 0 3 &pcie_intc_0 3>,
+				<0 0 0 4 &pcie_intc_0 4>;
+		interrupt-map-mask = <0 0 0 7>;
+		interrupt-parent = <&gic>;
+		interrupt-names = "misc";
+		interrupts = <0 72 4>;
+		ranges = <0x02000000 0x00000000 0xE0000000 0x0 0xE0000000 0x00000000 0x10000000>,
+			 <0x43000000 0x00000080 0x00000000 0x00000080 0x00000000 0x00000000 0x80000000>;
+		msi-map = <0x0 &its_gic 0x0 0x10000>;
+		reg = <0x0 0xfca10000 0x0 0x1000>,
+		      <0x6 0x00000000 0x0 0x1000000>;
+		reg-names = "cpm_slcr", "cfg";
+		pcie_intc_0: pci-interrupt-controller {
+			#address-cells = <0>;
+			#interrupt-cells = <1>;
+			interrupt-controller ;
+		};
+	};
+
+Versal PL PCIe host Bridge DT description.
+
+The properties and their meanings are identical to those described in
+above Xilinx XDMA PL PCIe Root Port Bridge description.
+The IP supports only MSI DECODE mode.
+
+Properties that differ are:
+- compatible: Should contain "xlnx,pcie-dma-versal-2.0"
+
+Example:
+	pcie_dma_versal_0: axi-pcie@80000000 {
+		#address-cells = <3>;
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		compatible = "xlnx,pcie-dma-versal-2.0";
+		device_type = "pci";
+		interrupt-map = <0 0 0 1 &psv_pcie_intc_0 1>,
+				<0 0 0 2 &psv_pcie_intc_0 2>,
+				<0 0 0 3 &psv_pcie_intc_0 3>,
+				<0 0 0 4 &psv_pcie_intc_0 4>;
+		interrupt-map-mask = <0 0 0 7>;
+		interrupt-names = "misc", "msi0", "msi1";
+		interrupt-parent = <&gic>;
+		interrupts = <0 84 4 0 85 4 0 86 4>;
+		ranges = <0x02000000 0x00000000 0xB0000000 0x0 0xB0000000 0x00000000 0x10000000>,
+			 <0x43000000 0x00000005 0x00000000 0x00000005 0x00000000 0x00000000 0x01000000>;
+		reg = <0x0 0x80000000 0x0 0x10000000>;
+		psv_pcie_intc_0: interrupt-controller {
+			#address-cells = <0>;
+			#interrupt-cells = <1>;
+			interrupt-controller ;
+		};
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/perf/xilinx-apm.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/perf/xilinx-apm.yaml
@@ -0,0 +1,128 @@
+# SPDX-License-Identifier: GPL-2.0-or-later OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/perf/xilinx-apm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Xilinx Axi Performance Monitor device tree bindings
+
+maintainers:
+  - Shubhrajyoti Datta <shubhrajyoti.datta@xilinx.com>
+
+properties:
+  compatible:
+    items:
+      - enum:
+          - xlnx,axi-perf-monitor
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  xlnx,enable-profile:
+    allOf:
+      - $ref: /schemas/types.yaml#/definitions/uint32
+      - enum: [0, 1]
+    description:
+      Enables the profile mode.
+    maxItems: 1
+
+  xlnx,enable-trace:
+    allOf:
+      - $ref: /schemas/types.yaml#/definitions/uint32
+      - enum: [0, 1]
+    description:
+      Enables trace mode.
+    maxItems: 1
+
+  xlnx,num-monitor-slots:
+    allOf:
+      - $ref: /schemas/types.yaml#/definitions/uint32
+      - minimum: 1
+      - maximum: 8
+    description:
+      Number of monitor slots.
+
+  xlnx,enable-event-count:
+    allOf:
+      - $ref: /schemas/types.yaml#/definitions/uint32
+      - enum: [0, 1]
+    description:
+      Enable event count.
+
+  xlnx,enable-event-log:
+    allOf:
+      - $ref: /schemas/types.yaml#/definitions/uint32
+      - enum: [0, 1]
+    description:
+      Enable event log.
+
+  xlnx,have-sampled-metric-cnt:
+    allOf:
+      - $ref: /schemas/types.yaml#/definitions/uint32
+    description:
+      Sampled metric counters enabled in APM.
+
+  xlnx,metric-count-width:
+    allOf:
+      - $ref: /schemas/types.yaml#/definitions/uint32
+      - enum: [32, 64]
+    description:
+      Metric Counter width.
+
+  xlnx,num-of-counters:
+    allOf:
+      - $ref: /schemas/types.yaml#/definitions/uint32
+    description:
+      Number of counters in APM.
+
+  xlnx,metrics-sample-count-width:
+    allOf:
+      - $ref: /schemas/types.yaml#/definitions/uint32
+      - enum: [32, 64]
+    description:
+      Sampled metric counter width.
+
+  xlnx,global-count-width:
+    allOf:
+      - $ref: /schemas/types.yaml#/definitions/uint32
+      - enum: [32, 64]
+    description:
+      Global Clock counter width.
+
+  xlnx,id-filter-32bit:
+    description: APM is in 32-bit mode.
+    type: boolean
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - interrupts
+
+examples:
+  - |
+    apm@44a00000 {
+        compatible = "xlnx,axi-perf-monitor";
+        interrupt-parent = <&axi_intc_1>;
+        interrupts = <1 2>;
+        reg = <0x44a00000 0x1000>;
+        clocks = <&clkc 15>;
+        xlnx,enable-profile = <0>;
+        xlnx,enable-trace = <0>;
+        xlnx,num-monitor-slots = <4>;
+        xlnx,enable-event-count = <1>;
+        xlnx,enable-event-log = <1>;
+        xlnx,have-sampled-metric-cnt = <1>;
+        xlnx,num-of-counters = <8>;
+        xlnx,metric-count-width = <32>;
+        xlnx,metrics-sample-count-width = <32>;
+        xlnx,global-count-width = <32>;
+        xlnx,metric-count-scale = <1>;
+        xlnx,id-filter-32bit;
+    };
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/perf/xlnx-flexnoc-pm.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/perf/xlnx-flexnoc-pm.yaml
@@ -0,0 +1,45 @@
+# SPDX-License-Identifier: GPL-2.0-or-later OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/perf/xlnx-flexnoc-pm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Xilinx flexnoc Performance Monitor device tree bindings
+
+maintainers:
+  - Arnd Bergmann <arnd@arndb.de>
+  - Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+properties:
+  compatible:
+    # Versal SoC based boards
+    items:
+      - enum:
+          - xlnx,flexnoc-pm-2.7
+
+  reg:
+    items:
+      - description: funnel registers
+      - description: baselpd registers
+      - description: basefpd registers
+
+  reg-names:
+    # The core schema enforces this is a string array
+    items:
+      - const: funnel
+      - const: baselpd
+      - const: basefpd
+
+required:
+  - compatible
+  - reg
+
+examples:
+  - |
+    performance-monitor@f0920000 {
+        compatible = "xlnx,flexnoc-pm-2.7";
+        reg-names = "funnel", "baselpd", "basefpd";
+        reg = <0x0 0xf0920000 0x0 0x1000>,
+              <0x0 0xf0980000 0x0 0x9000>,
+              <0x0 0xf0b80000 0x0 0x9000>;
+    };
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/phy/amlogic,g12a-usb3-pcie-phy.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/phy/amlogic,g12a-usb3-pcie-phy.yaml
@@ -0,0 +1,57 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+# Copyright 2019 BayLibre, SAS
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/phy/amlogic,g12a-usb3-pcie-phy.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: Amlogic G12A USB3 + PCIE Combo PHY
+
+maintainers:
+  - Neil Armstrong <narmstrong@baylibre.com>
+
+properties:
+  compatible:
+    enum:
+      - amlogic,g12a-usb3-pcie-phy
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  clock-names:
+    items:
+      - const: ref_clk
+
+  resets:
+    maxItems: 1
+
+  reset-names:
+    items:
+      - const: phy
+
+  "#phy-cells":
+    const: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - resets
+  - reset-names
+  - "#phy-cells"
+
+examples:
+  - |
+    phy@46000 {
+          compatible = "amlogic,g12a-usb3-pcie-phy";
+          reg = <0x46000 0x2000>;
+          clocks = <&ref_clk>;
+          clock-names = "ref_clk";
+          resets = <&phy_reset>;
+          reset-names = "phy";
+          #phy-cells = <1>;
+    };
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/phy/phy-zynqmp.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/phy/phy-zynqmp.txt
@@ -0,0 +1,119 @@
+Xilinx ZynqMP PHY binding
+
+This binding describes a ZynqMP PHY device that is used to control ZynqMP
+High Speed Gigabit Transceiver(GT). ZynqMP PS GTR provides four lanes
+and are used by USB, SATA, PCIE, Display port and Ethernet SGMMI controllers.
+
+Required properties (controller (parent) node):
+- compatible	: Can be "xlnx,zynqmp-psgtr-v1.1" or "xlnx,zynqmp-psgtr"
+		  "xlnx,zynqmp-psgtr-v1.1" has the lpd address mapping removed
+
+- reg           : Address and length of register sets for each device in
+                  "reg-names"
+- reg-names     : The names of the register addresses corresponding to the
+		  registers filled in "reg":
+			- serdes: SERDES block register set
+			- siou: SIOU block register set
+			- lpd: Low power domain peripherals reset control
+
+Required nodes	:  A sub-node is required for each lane the controller
+		   provides.
+
+Required properties (port (child) nodes):
+lane0:
+- #phy-cells	: Should be 4
+		  Cell after port phandle is device type from:
+			- <PHY_TYPE_PCIE 0 LANE_NUM FREQUENCY>
+			- <PHY_TYPE_SATA 0 LANE_NUM FREQUENCY>
+			- <PHY_TYPE_USB3 0 LANE_NUM FREQUENCY>
+			- <PHY_TYPE_DP 1 LANE_NUM FREQUENCY>
+			- <PHY_TYPE_SGMII 0 LANE_NUM FREQUENCY>
+lane1:
+- #phy-cells	: Should be 4
+		  Cell after port phandle is device type from:
+			- <PHY_TYPE_PCIE 1 LANE_NUM FREQUENCY>
+			- <PHY_TYPE_SATA 1 LANE_NUM FREQUENCY>
+			- <PHY_TYPE_USB3 0 LANE_NUM FREQUENCY>
+			- <PHY_TYPE_DP 0 LANE_NUM FREQUENCY>
+			- <PHY_TYPE_SGMII 1 LANE_NUM FREQUENCY>
+lane2:
+- #phy-cells	: Should be 4
+		  Cell after port phandle is device type from:
+			- <PHY_TYPE_PCIE 2 LANE_NUM FREQUENCY>
+			- <PHY_TYPE_SATA 0 LANE_NUM FREQUENCY>
+			- <PHY_TYPE_USB3 0 LANE_NUM FREQUENCY>
+			- <PHY_TYPE_DP 1 LANE_NUM FREQUENC>
+			- <PHY_TYPE_SGMII 2 LANE_NUM FREQUENCY>
+lane3:
+- #phy-cells	: Should be 4
+		  Cell after port phandle is device type from:
+			- <PHY_TYPE_PCIE 3 LANE_NUM FREQUENCY>
+			- <PHY_TYPE_SATA 1 LANE_NUM FREQUENCY>
+			- <PHY_TYPE_USB3 1 LANE_NUM FREQUENCY >
+			- <PHY_TYPE_DP 0 LANE_NUM FREQUENCY>
+			- <PHY_TYPE_SGMII 3 LANE_NUM FREQUENCY>
+
+Note:	LANE_NUM : This determines which lane's reference clock is shared by controller.
+	FREQUENCY: This the clock frequency at which controller wants to operate.
+
+
+Example:
+	serdes: zynqmp_phy@fd400000 {
+		compatible = "xlnx,zynqmp-psgtr";
+		status = "okay";
+		reg = <0x0 0xfd400000 0x0 0x40000>, <0x0 0xfd3d0000 0x0 0x1000>,
+			<0x0 0xff5e0000 0x0 0x1000>;
+		reg-names = "serdes", "siou", "lpd";
+
+		lane0: lane@0 {
+			#phy-cells = <4>;
+		};
+		lane1: lane@1 {
+			#phy-cells = <4>;
+		};
+		lane2: lane@2 {
+			#phy-cells = <4>;
+		};
+		lane3: lane@3 {
+			#phy-cells = <4>;
+		};
+	};
+
+Specifying phy control of devices
+=================================
+
+Device nodes should specify the configuration required in their "phys"
+property, containing a phandle to the phy port node and a device type.
+
+phys = <PHANDLE CONTROLLER_TYPE CONTROLLER_INSTANCE LANE_NUM LANE_FREQ>;
+
+PHANDLE                 = &lane0 or &lane1 or &lane2 or &lane3
+CONTROLLER_TYPE         = PHY_TYPE_PCIE or PHY_TYPE_SATA or PHY_TYPE_USB
+			  or PHY_TYPE_DP or PHY_TYPE_SGMII
+CONTROLLER_INSTANCE     = Depends on controller type used, can be any of
+				PHY_TYPE_PCIE : 0 or 1 or 2 or 3
+				PHY_TYPE_SATA : 0 or 1
+				PHY_TYPE_USB  : 0 or 1
+				PHY_TYPE_DP   : 0 or 1
+				PHY_TYPE_SGMII: 0 or 1 or 2 or 3
+LANE_NUM                = Depends on which lane clock is used as ref clk, can be
+			  0 or 1 or 2 or 3
+LANE_FREQ               = Frequency that controller can operate, can be any of
+			  19.2Mhz,20Mhz,24Mhz,26Mhz,27Mhz,28.4Mhz,40Mhz,52Mhz,
+			  100Mhz,108Mhz,125Mhz,135Mhz,150Mhz
+
+Example:
+
+#include <dt-bindings/phy/phy.h>
+
+	usb@fe200000 {
+		...
+		phys	  = <&lane2 PHY_TYPE_USB3 0 2 2600000>;
+		...
+	};
+
+	ahci@fd0c0000 {
+		...
+		phys	  = <&lane3 PHY_TYPE_SATA 1 1 125000000>;
+		...
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/pinctrl/marvell,armada-37xx-pinctrl.txt
@@ -43,19 +43,19 @@
 
 group pwm0
  - pin 11 (GPIO1-11)
- - functions pwm, gpio
+ - functions pwm, led, gpio
 
 group pwm1
  - pin 12
- - functions pwm, gpio
+ - functions pwm, led, gpio
 
 group pwm2
  - pin 13
- - functions pwm, gpio
+ - functions pwm, led, gpio
 
 group pwm3
  - pin 14
- - functions pwm, gpio
+ - functions pwm, led, gpio
 
 group pmic1
  - pin 7
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/pinctrl/pincfg-node.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/pinctrl/pincfg-node.yaml
@@ -0,0 +1,140 @@
+# SPDX-License-Identifier: GPL-2.0-only
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/pincfg-node.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Generic pin configuration node schema
+
+maintainers:
+  - Linus Walleij <linus.walleij@linaro.org>
+
+description:
+  Many data items that are represented in a pin configuration node are common
+  and generic. Pin control bindings should use the properties defined below
+  where they are applicable; not all of these properties are relevant or useful
+  for all hardware or binding structures. Each individual binding document
+  should state which of these generic properties, if any, are used, and the
+  structure of the DT nodes that contain these properties.
+
+properties:
+  bias-disable:
+    type: boolean
+    description: disable any pin bias
+
+  bias-high-impedance:
+    type: boolean
+    description: high impedance mode ("third-state", "floating")
+
+  bias-bus-hold:
+    type: boolean
+    description: latch weakly
+
+  bias-pull-up:
+    oneOf:
+      - type: boolean
+      - $ref: /schemas/types.yaml#/definitions/uint32
+    description: pull up the pin. Takes as optional argument on hardware
+      supporting it the pull strength in Ohm.
+
+  bias-pull-down:
+    oneOf:
+      - type: boolean
+      - $ref: /schemas/types.yaml#/definitions/uint32
+    description: pull down the pin. Takes as optional argument on hardware
+      supporting it the pull strength in Ohm.
+
+  bias-pull-pin-default:
+    oneOf:
+      - type: boolean
+      - $ref: /schemas/types.yaml#/definitions/uint32
+    description: use pin-default pull state. Takes as optional argument on
+      hardware supporting it the pull strength in Ohm.
+
+  drive-push-pull:
+    type: boolean
+    description: drive actively high and low
+
+  drive-open-drain:
+    type: boolean
+    description: drive with open drain
+
+  drive-open-source:
+    type: boolean
+    description: drive with open source
+
+  drive-strength:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: sink or source at most X mA
+
+  drive-strength-microamp:
+    description: sink or source at most X uA
+
+  input-enable:
+    type: boolean
+    description: enable input on pin (no effect on output, such as
+      enabling an input buffer)
+
+  input-disable:
+    type: boolean
+    description: disable input on pin (no effect on output, such as
+      disabling an input buffer)
+
+  input-schmitt-enable:
+    type: boolean
+    description: enable schmitt-trigger mode
+
+  input-schmitt-disable:
+    type: boolean
+    description: disable schmitt-trigger mode
+
+  input-debounce:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: Takes the debounce time in usec as argument or 0 to disable
+      debouncing
+
+  power-source:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: select between different power supplies
+
+  low-power-enable:
+    type: boolean
+    description: enable low power mode
+
+  low-power-disable:
+    type: boolean
+    description: disable low power mode
+
+  output-disable:
+    type: boolean
+    description: disable output on a pin (such as disable an output buffer)
+
+  output-enable:
+    type: boolean
+    description: enable output on a pin without actively driving it
+      (such as enabling an output buffer)
+
+  output-low:
+    type: boolean
+    description: set the pin to output mode with low level
+
+  output-high:
+    type: boolean
+    description: set the pin to output mode with high level
+
+  sleep-hardware-state:
+    type: boolean
+    description: indicate this is sleep related state which will be
+      programmed into the registers for the sleep state.
+
+  slew-rate:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: set the slew rate
+
+  skew-delay:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description:
+      this affects the expected clock skew on input pins
+      and the delay before latching a value to an output
+      pin. Typically indicates how many double-inverters are
+      used to delay the signal.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
@@ -141,196 +141,8 @@
 
 == Generic pin multiplexing node content ==
 
-pin multiplexing nodes:
-
-function		- the mux function to select
-groups			- the list of groups to select with this function
-			  (either this or "pins" must be specified)
-pins			- the list of pins to select with this function (either
-			  this or "groups" must be specified)
-
-Example:
-
-state_0_node_a {
-	uart0 {
-		function = "uart0";
-		groups = "u0rxtx", "u0rtscts";
-	};
-};
-state_1_node_a {
-	spi0 {
-		function = "spi0";
-		groups = "spi0pins";
-	};
-};
-state_2_node_a {
-	function = "i2c0";
-	pins = "mfio29", "mfio30";
-};
-
-Optionally an alternative binding can be used if more suitable depending on the
-pin controller hardware. For hardware where there is a large number of identical
-pin controller instances, naming each pin and function can easily become
-unmaintainable. This is especially the case if the same controller is used for
-different pins and functions depending on the SoC revision and packaging.
-
-For cases like this, the pin controller driver may use pinctrl-pin-array helper
-binding with a hardware based index and a number of pin configuration values:
-
-pincontroller {
-	... /* Standard DT properties for the device itself elided */
-	#pinctrl-cells = <2>;
-
-	state_0_node_a {
-		pinctrl-pin-array = <
-			0 A_DELAY_PS(0) G_DELAY_PS(120)
-			4 A_DELAY_PS(0) G_DELAY_PS(360)
-			...
-		>;
-	};
-	...
-};
-
-Above #pinctrl-cells specifies the number of value cells in addition to the
-index of the registers. This is similar to the interrupts-extended binding with
-one exception. There is no need to specify the phandle for each entry as that
-is already known as the defined pins are always children of the pin controller
-node. Further having the phandle pointing to another pin controller would not
-currently work as the pinctrl framework uses named modes to group pins for each
-pin control device.
-
-The index for pinctrl-pin-array must relate to the hardware for the pinctrl
-registers, and must not be a virtual index of pin instances. The reason for
-this is to avoid mapping of the index in the dts files and the pin controller
-driver as it can change.
-
-For hardware where pin multiplexing configurations have to be specified for
-each single pin the number of required sub-nodes containing "pin" and
-"function" properties can quickly escalate and become hard to write and
-maintain.
-
-For cases like this, the pin controller driver may use the pinmux helper
-property, where the pin identifier is provided with mux configuration settings
-in a pinmux group. A pinmux group consists of the pin identifier and mux
-settings represented as a single integer or an array of integers.
-
-The pinmux property accepts an array of pinmux groups, each of them describing
-a single pin multiplexing configuration.
-
-pincontroller {
-	state_0_node_a {
-		pinmux = <PINMUX_GROUP>, <PINMUX_GROUP>, ...;
-	};
-};
-
-Each individual pin controller driver bindings documentation shall specify
-how pin IDs and pin multiplexing configuration are defined and assembled
-together in a pinmux group.
+See pinmux-node.yaml
 
 == Generic pin configuration node content ==
 
-Many data items that are represented in a pin configuration node are common
-and generic. Pin control bindings should use the properties defined below
-where they are applicable; not all of these properties are relevant or useful
-for all hardware or binding structures. Each individual binding document
-should state which of these generic properties, if any, are used, and the
-structure of the DT nodes that contain these properties.
-
-Supported generic properties are:
-
-pins			- the list of pins that properties in the node
-			  apply to (either this, "group" or "pinmux" has to be
-			  specified)
-group			- the group to apply the properties to, if the driver
-			  supports configuration of whole groups rather than
-			  individual pins (either this, "pins" or "pinmux" has
-			  to be specified)
-pinmux			- the list of numeric pin ids and their mux settings
-			  that properties in the node apply to (either this,
-			  "pins" or "groups" have to be specified)
-bias-disable		- disable any pin bias
-bias-high-impedance	- high impedance mode ("third-state", "floating")
-bias-bus-hold		- latch weakly
-bias-pull-up		- pull up the pin
-bias-pull-down		- pull down the pin
-bias-pull-pin-default	- use pin-default pull state
-drive-push-pull		- drive actively high and low
-drive-open-drain	- drive with open drain
-drive-open-source	- drive with open source
-drive-strength		- sink or source at most X mA
-drive-strength-microamp	- sink or source at most X uA
-input-enable		- enable input on pin (no effect on output, such as
-			  enabling an input buffer)
-input-disable		- disable input on pin (no effect on output, such as
-			  disabling an input buffer)
-input-schmitt-enable	- enable schmitt-trigger mode
-input-schmitt-disable	- disable schmitt-trigger mode
-input-debounce		- debounce mode with debound time X
-power-source		- select between different power supplies
-low-power-enable	- enable low power mode
-low-power-disable	- disable low power mode
-output-disable		- disable output on a pin (such as disable an output
-			  buffer)
-output-enable		- enable output on a pin without actively driving it
-			  (such as enabling an output buffer)
-output-low		- set the pin to output mode with low level
-output-high		- set the pin to output mode with high level
-sleep-hardware-state	- indicate this is sleep related state which will be programmed
-			  into the registers for the sleep state.
-slew-rate		- set the slew rate
-skew-delay		- this affects the expected clock skew on input pins
-			  and the delay before latching a value to an output
-			  pin. Typically indicates how many double-inverters are
-			  used to delay the signal.
-
-For example:
-
-state_0_node_a {
-	cts_rxd {
-		pins = "GPIO0_AJ5", "GPIO2_AH4"; /* CTS+RXD */
-		bias-pull-up;
-	};
-};
-state_1_node_a {
-	rts_txd {
-		pins = "GPIO1_AJ3", "GPIO3_AH3"; /* RTS+TXD */
-		output-high;
-	};
-};
-state_2_node_a {
-	foo {
-		group = "foo-group";
-		bias-pull-up;
-	};
-};
-state_3_node_a {
-	mux {
-		pinmux = <GPIOx_PINm_MUXn>, <GPIOx_PINj_MUXk)>;
-		input-enable;
-	};
-};
-
-Some of the generic properties take arguments. For those that do, the
-arguments are described below.
-
-- pins takes a list of pin names or IDs as a required argument. The specific
-  binding for the hardware defines:
-  - Whether the entries are integers or strings, and their meaning.
-
-- pinmux takes a list of pin IDs and mux settings as required argument. The
-  specific bindings for the hardware defines:
-  - How pin IDs and mux settings are defined and assembled together in a single
-    integer or an array of integers.
-
-- bias-pull-up, -down and -pin-default take as optional argument on hardware
-  supporting it the pull strength in Ohm. bias-disable will disable the pull.
-
-- drive-strength takes as argument the target strength in mA.
-
-- drive-strength-microamp takes as argument the target strength in uA.
-
-- input-debounce takes the debounce time in usec as argument
-  or 0 to disable debouncing
-
-More in-depth documentation on these parameters can be found in
-<include/linux/pinctrl/pinconf-generic.h>
+See pincfg-node.yaml
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/pinctrl/pinmux-node.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/pinctrl/pinmux-node.yaml
@@ -0,0 +1,132 @@
+# SPDX-License-Identifier: GPL-2.0-only
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/pinmux-node.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Generic pin multiplexing node schema
+
+maintainers:
+  - Linus Walleij <linus.walleij@linaro.org>
+
+description: |
+  The contents of the pin configuration child nodes are defined by the binding
+  for the individual pin controller device. The pin configuration nodes need not
+  be direct children of the pin controller device; they may be grandchildren,
+  for example. Whether this is legal, and whether there is any interaction
+  between the child and intermediate parent nodes, is again defined entirely by
+  the binding for the individual pin controller device.
+
+  While not required to be used, there are 3 generic forms of pin muxing nodes
+  which pin controller devices can use.
+
+  pin multiplexing nodes:
+
+  Example:
+
+  state_0_node_a {
+    uart0 {
+      function = "uart0";
+      groups = "u0rxtx", "u0rtscts";
+    };
+  };
+  state_1_node_a {
+    spi0 {
+      function = "spi0";
+      groups = "spi0pins";
+    };
+  };
+  state_2_node_a {
+    function = "i2c0";
+    pins = "mfio29", "mfio30";
+  };
+
+  Optionally an alternative binding can be used if more suitable depending on the
+  pin controller hardware. For hardware where there is a large number of identical
+  pin controller instances, naming each pin and function can easily become
+  unmaintainable. This is especially the case if the same controller is used for
+  different pins and functions depending on the SoC revision and packaging.
+
+  For cases like this, the pin controller driver may use pinctrl-pin-array helper
+  binding with a hardware based index and a number of pin configuration values:
+
+  pincontroller {
+    ... /* Standard DT properties for the device itself elided */
+    #pinctrl-cells = <2>;
+
+    state_0_node_a {
+      pinctrl-pin-array = <
+        0 A_DELAY_PS(0) G_DELAY_PS(120)
+        4 A_DELAY_PS(0) G_DELAY_PS(360)
+        ...
+        >;
+    };
+    ...
+  };
+
+  Above #pinctrl-cells specifies the number of value cells in addition to the
+  index of the registers. This is similar to the interrupts-extended binding with
+  one exception. There is no need to specify the phandle for each entry as that
+  is already known as the defined pins are always children of the pin controller
+  node. Further having the phandle pointing to another pin controller would not
+  currently work as the pinctrl framework uses named modes to group pins for each
+  pin control device.
+
+  The index for pinctrl-pin-array must relate to the hardware for the pinctrl
+  registers, and must not be a virtual index of pin instances. The reason for
+  this is to avoid mapping of the index in the dts files and the pin controller
+  driver as it can change.
+
+  For hardware where pin multiplexing configurations have to be specified for
+  each single pin the number of required sub-nodes containing "pin" and
+  "function" properties can quickly escalate and become hard to write and
+  maintain.
+
+  For cases like this, the pin controller driver may use the pinmux helper
+  property, where the pin identifier is provided with mux configuration settings
+  in a pinmux group. A pinmux group consists of the pin identifier and mux
+  settings represented as a single integer or an array of integers.
+
+  The pinmux property accepts an array of pinmux groups, each of them describing
+  a single pin multiplexing configuration.
+
+  pincontroller {
+    state_0_node_a {
+      pinmux = <PINMUX_GROUP>, <PINMUX_GROUP>, ...;
+    };
+  };
+
+  Each individual pin controller driver bindings documentation shall specify
+  how pin IDs and pin multiplexing configuration are defined and assembled
+  together in a pinmux group.
+
+properties:
+  function:
+    $ref: /schemas/types.yaml#/definitions/string
+    description: The mux function to select
+
+  pins:
+    oneOf:
+      - $ref: /schemas/types.yaml#/definitions/uint32-array
+      - $ref: /schemas/types.yaml#/definitions/string-array
+    description:
+      The list of pin identifiers that properties in the node apply to. The
+      specific binding for the hardware defines whether the entries are integers
+      or strings, and their meaning.
+
+  group:
+    $ref: /schemas/types.yaml#/definitions/string-array
+    description:
+      the group to apply the properties to, if the driver supports
+      configuration of whole groups rather than individual pins (either
+      this, "pins" or "pinmux" has to be specified)
+
+  pinmux:
+    allOf:
+      - $ref: /schemas/types.yaml#/definitions/uint32-array
+    description:
+      The list of numeric pin ids and their mux settings that properties in the
+      node apply to (either this, "pins" or "groups" have to be specified)
+
+  pinctrl-pin-array:
+    $ref: /schemas/types.yaml#/definitions/uint32-array
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/pinctrl/xlnx,zynqmp-pinctrl.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/pinctrl/xlnx,zynqmp-pinctrl.txt
@@ -0,0 +1,275 @@
+	Binding for Xilinx ZynqMP Pinctrl
+
+Required properties:
+- compatible: "xlnx,zynqmp-pinctrl"
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices, including the meaning of the
+phrase "pin configuration node".
+
+ZynqMP's pin configuration nodes act as a container for an arbitrary number of
+subnodes. Each of these subnodes represents some desired configuration for a
+pin, a group, or a list of pins or groups. This configuration can include the
+mux function to select on those pin(s)/group(s), and various pin configuration
+parameters, such as pull-up, slew rate, etc.
+
+Each configuration node can consist of multiple nodes describing the pinmux and
+pinconf options. Those nodes can be pinmux nodes or pinconf nodes.
+
+The name of each subnode is not important; all subnodes should be enumerated
+and processed purely based on their content.
+
+Required properties for pinmux nodes are:
+ - groups: A list of pinmux groups.
+ - function: The name of a pinmux function to activate for the specified set
+   of groups.
+
+Required properties for configuration nodes:
+One of:
+ - pins: A list of pin names
+ - groups: A list of pinmux groups.
+
+The following generic properties as defined in pinctrl-bindings.txt are valid
+to specify in a pinmux subnode:
+ groups, function
+
+The following generic properties as defined in pinctrl-bindings.txt are valid
+to specify in a pinconf subnode:
+ groups, pins, bias-disable, bias-pull-up, bias-pull-down, slew-rate
+
+ Valid arguments for 'slew-rate' are 'SLEW_RATE_SLOW' and 'SLEW_RATE_FAST' to
+ select between slow and fast respectively.
+
+ Valid values for groups are:
+ ethernet0_0_grp, ethernet1_0_grp, ethernet2_0_grp,
+ ethernet3_0_grp, gemtsu0_0_grp, gemtsu0_1_grp,
+ gemtsu0_2_grp, mdio0_0_grp, mdio1_0_grp,
+ mdio1_1_grp, mdio2_0_grp, mdio3_0_grp,
+ qspi0_0_grp, qspi_ss_0_grp, qspi_fbclk_0_grp,
+ spi0_0_grp, spi0_ss_0_grp, spi0_ss_1_grp,
+ spi0_ss_2_grp, spi0_1_grp, spi0_ss_3_grp,
+ spi0_ss_4_grp, spi0_ss_5_grp, spi0_2_grp,
+ spi0_ss_6_grp, spi0_ss_7_grp, spi0_ss_8_grp,
+ spi0_3_grp, spi0_ss_9_grp, spi0_ss_10_grp,
+ spi0_ss_11_grp, spi0_4_grp, spi0_ss_12_grp,
+ spi0_ss_13_grp, spi0_ss_14_grp, spi0_5_grp,
+ spi0_ss_15_grp, spi0_ss_16_grp, spi0_ss_17_grp,
+ spi1_0_grp, spi1_ss_0_grp, spi1_ss_1_grp,
+ spi1_ss_2_grp, spi1_1_grp, spi1_ss_3_grp,
+ spi1_ss_4_grp, spi1_ss_5_grp, spi1_2_grp,
+ spi1_ss_6_grp, spi1_ss_7_grp, spi1_ss_8_grp,
+ spi1_3_grp, spi1_ss_9_grp, spi1_ss_10_grp,
+ spi1_ss_11_grp, spi1_4_grp, spi1_ss_12_grp,
+ spi1_ss_13_grp, spi1_ss_14_grp, spi1_5_grp,
+ spi1_ss_15_grp, spi1_ss_16_grp, spi1_ss_17_grp,
+ sdio0_0_grp, sdio0_1_grp, sdio0_2_grp,
+ sdio0_3_grp, sdio0_4_grp, sdio0_5_grp,
+ sdio0_6_grp, sdio0_7_grp, sdio0_8_grp,
+ sdio0_9_grp, sdio0_10_grp, sdio0_11_grp,
+ sdio0_12_grp, sdio0_13_grp, sdio0_14_grp,
+ sdio0_15_grp, sdio0_16_grp, sdio0_17_grp,
+ sdio0_18_grp, sdio0_19_grp, sdio0_20_grp,
+ sdio0_21_grp, sdio0_22_grp, sdio0_23_grp,
+ sdio0_24_grp, sdio0_25_grp, sdio0_26_grp,
+ sdio0_27_grp, sdio0_28_grp, sdio0_29_grp,
+ sdio0_30_grp, sdio0_31_grp, sdio0_32_grp,
+ sdio0_pc_0_grp, sdio0_cd_0_grp, sdio0_wp_0_grp,
+ sdio0_pc_1_grp, sdio0_cd_1_grp, sdio0_wp_1_grp,
+ sdio0_pc_2_grp, sdio0_cd_2_grp, sdio0_wp_2_grp,
+ sdio1_0_grp, sdio1_1_grp, sdio1_2_grp,
+ sdio1_3_grp, sdio1_4_grp, sdio1_5_grp,
+ sdio1_6_grp, sdio1_7_grp, sdio1_8_grp,
+ sdio1_9_grp, sdio1_10_grp, sdio1_11_grp,
+ sdio1_12_grp, sdio1_13_grp, sdio1_14_grp,
+ sdio1_15_grp, sdio1_pc_0_grp, sdio1_cd_0_grp,
+ sdio1_wp_0_grp, sdio1_pc_1_grp, sdio1_cd_1_grp,
+ sdio1_wp_1_grp, nand0_0_grp, nand0_ce_0_grp,
+ nand0_rb_0_grp, nand0_dqs_0_grp, nand0_ce_1_grp,
+ nand0_rb_1_grp, nand0_dqs_1_grp, can0_0_grp,
+ can0_1_grp, can0_2_grp, can0_3_grp,
+ can0_4_grp, can0_5_grp, can0_6_grp,
+ can0_7_grp, can0_8_grp, can0_9_grp,
+ can0_10_grp, can0_11_grp, can0_12_grp,
+ can0_13_grp, can0_14_grp, can0_15_grp,
+ can0_16_grp, can0_17_grp, can0_18_grp,
+ can1_0_grp, can1_1_grp, can1_2_grp,
+ can1_3_grp, can1_4_grp, can1_5_grp,
+ can1_6_grp, can1_7_grp, can1_8_grp,
+ can1_9_grp, can1_10_grp, can1_11_grp,
+ can1_12_grp, can1_13_grp, can1_14_grp,
+ can1_15_grp, can1_16_grp, can1_17_grp,
+ can1_18_grp, can1_19_grp, uart0_0_grp,
+ uart0_1_grp, uart0_2_grp, uart0_3_grp,
+ uart0_4_grp, uart0_5_grp, uart0_6_grp,
+ uart0_7_grp, uart0_8_grp, uart0_9_grp,
+ uart0_10_grp, uart0_11_grp, uart0_12_grp,
+ uart0_13_grp, uart0_14_grp, uart0_15_grp,
+ uart0_16_grp, uart0_17_grp, uart0_18_grp,
+ uart1_0_grp, uart1_1_grp, uart1_2_grp,
+ uart1_3_grp, uart1_4_grp, uart1_5_grp,
+ uart1_6_grp, uart1_7_grp, uart1_8_grp,
+ uart1_9_grp, uart1_10_grp, uart1_11_grp,
+ uart1_12_grp, uart1_13_grp, uart1_14_grp,
+ uart1_15_grp, uart1_16_grp, uart1_17_grp,
+ uart1_18_grp, i2c0_0_grp, i2c0_1_grp,
+ i2c0_2_grp, i2c0_3_grp, i2c0_4_grp,
+ i2c0_5_grp, i2c0_6_grp, i2c0_7_grp,
+ i2c0_8_grp, i2c0_9_grp, i2c0_10_grp,
+ i2c0_11_grp, i2c0_12_grp, i2c0_13_grp,
+ i2c0_14_grp, i2c0_15_grp, i2c0_16_grp,
+ i2c0_17_grp, i2c0_18_grp, i2c1_0_grp,
+ i2c1_1_grp, i2c1_2_grp, i2c1_3_grp,
+ i2c1_4_grp, i2c1_5_grp, i2c1_6_grp,
+ i2c1_7_grp, i2c1_8_grp, i2c1_9_grp,
+ i2c1_10_grp, i2c1_11_grp, i2c1_12_grp,
+ i2c1_13_grp, i2c1_14_grp, i2c1_15_grp,
+ i2c1_16_grp, i2c1_17_grp, i2c1_18_grp,
+ i2c1_19_grp, ttc0_clk_0_grp, ttc0_wav_0_grp,
+ ttc0_clk_1_grp, ttc0_wav_1_grp, ttc0_clk_2_grp,
+ ttc0_wav_2_grp, ttc0_clk_3_grp, ttc0_wav_3_grp,
+ ttc0_clk_4_grp, ttc0_wav_4_grp, ttc0_clk_5_grp,
+ ttc0_wav_5_grp, ttc0_clk_6_grp, ttc0_wav_6_grp,
+ ttc0_clk_7_grp, ttc0_wav_7_grp, ttc0_clk_8_grp,
+ ttc0_wav_8_grp, ttc1_clk_0_grp, ttc1_wav_0_grp,
+ ttc1_clk_1_grp, ttc1_wav_1_grp, ttc1_clk_2_grp,
+ ttc1_wav_2_grp, ttc1_clk_3_grp, ttc1_wav_3_grp,
+ ttc1_clk_4_grp, ttc1_wav_4_grp, ttc1_clk_5_grp,
+ ttc1_wav_5_grp, ttc1_clk_6_grp, ttc1_wav_6_grp,
+ ttc1_clk_7_grp, ttc1_wav_7_grp, ttc1_clk_8_grp,
+ ttc1_wav_8_grp, ttc2_clk_0_grp, ttc2_wav_0_grp,
+ ttc2_clk_1_grp, ttc2_wav_1_grp, ttc2_clk_2_grp,
+ ttc2_wav_2_grp, ttc2_clk_3_grp, ttc2_wav_3_grp,
+ ttc2_clk_4_grp, ttc2_wav_4_grp, ttc2_clk_5_grp,
+ ttc2_wav_5_grp, ttc2_clk_6_grp, ttc2_wav_6_grp,
+ ttc2_clk_7_grp, ttc2_wav_7_grp, ttc2_clk_8_grp,
+ ttc2_wav_8_grp, ttc3_clk_0_grp, ttc3_wav_0_grp,
+ ttc3_clk_1_grp, ttc3_wav_1_grp, ttc3_clk_2_grp,
+ ttc3_wav_2_grp, ttc3_clk_3_grp, ttc3_wav_3_grp,
+ ttc3_clk_4_grp, ttc3_wav_4_grp, ttc3_clk_5_grp,
+ ttc3_wav_5_grp, ttc3_clk_6_grp, ttc3_wav_6_grp,
+ ttc3_clk_7_grp, ttc3_wav_7_grp, ttc3_clk_8_grp,
+ ttc3_wav_8_grp, swdt0_clk_0_grp, swdt0_rst_0_grp,
+ swdt0_clk_1_grp, swdt0_rst_1_grp, swdt0_clk_2_grp,
+ swdt0_rst_2_grp, swdt0_clk_3_grp, swdt0_rst_3_grp,
+ swdt0_clk_4_grp, swdt0_rst_4_grp, swdt0_clk_5_grp,
+ swdt0_rst_5_grp, swdt0_clk_6_grp, swdt0_rst_6_grp,
+ swdt0_clk_7_grp, swdt0_rst_7_grp, swdt0_clk_8_grp,
+ swdt0_rst_8_grp, swdt0_clk_9_grp, swdt0_rst_9_grp,
+ swdt0_clk_10_grp, swdt0_rst_10_grp, swdt0_clk_11_grp,
+ swdt0_rst_11_grp, swdt0_clk_12_grp, swdt0_rst_12_grp,
+ swdt1_clk_0_grp, swdt1_rst_0_grp, swdt1_clk_1_grp,
+ swdt1_rst_1_grp, swdt1_clk_2_grp, swdt1_rst_2_grp,
+ swdt1_clk_3_grp, swdt1_rst_3_grp, swdt1_clk_4_grp,
+ swdt1_rst_4_grp, swdt1_clk_5_grp, swdt1_rst_5_grp,
+ swdt1_clk_6_grp, swdt1_rst_6_grp, swdt1_clk_7_grp,
+ swdt1_rst_7_grp, swdt1_clk_8_grp, swdt1_rst_8_grp,
+ swdt1_clk_9_grp, swdt1_rst_9_grp, swdt1_clk_10_grp,
+ swdt1_rst_10_grp, swdt1_clk_11_grp, swdt1_rst_11_grp,
+ swdt1_clk_12_grp, swdt1_rst_12_grp, gpio0_0_grp,
+ gpio0_1_grp, gpio0_2_grp, gpio0_3_grp,
+ gpio0_4_grp, gpio0_5_grp, gpio0_6_grp,
+ gpio0_7_grp, gpio0_8_grp, gpio0_9_grp,
+ gpio0_10_grp, gpio0_11_grp, gpio0_12_grp,
+ gpio0_13_grp, gpio0_14_grp, gpio0_15_grp,
+ gpio0_16_grp, gpio0_17_grp, gpio0_18_grp,
+ gpio0_19_grp, gpio0_20_grp, gpio0_21_grp,
+ gpio0_22_grp, gpio0_23_grp, gpio0_24_grp,
+ gpio0_25_grp, gpio0_26_grp, gpio0_27_grp,
+ gpio0_28_grp, gpio0_29_grp, gpio0_30_grp,
+ gpio0_31_grp, gpio0_32_grp, gpio0_33_grp,
+ gpio0_34_grp, gpio0_35_grp, gpio0_36_grp,
+ gpio0_37_grp, gpio0_38_grp, gpio0_39_grp,
+ gpio0_40_grp, gpio0_41_grp, gpio0_42_grp,
+ gpio0_43_grp, gpio0_44_grp, gpio0_45_grp,
+ gpio0_46_grp, gpio0_47_grp, gpio0_48_grp,
+ gpio0_49_grp, gpio0_50_grp, gpio0_51_grp,
+ gpio0_52_grp, gpio0_53_grp, gpio0_54_grp,
+ gpio0_55_grp, gpio0_56_grp, gpio0_57_grp,
+ gpio0_58_grp, gpio0_59_grp, gpio0_60_grp,
+ gpio0_61_grp, gpio0_62_grp, gpio0_63_grp,
+ gpio0_64_grp, gpio0_65_grp, gpio0_66_grp,
+ gpio0_67_grp, gpio0_68_grp, gpio0_69_grp,
+ gpio0_70_grp, gpio0_71_grp, gpio0_72_grp,
+ gpio0_73_grp, gpio0_74_grp, gpio0_75_grp,
+ gpio0_76_grp, gpio0_77_grp, usb0_0_grp,
+ usb1_0_grp, pmu0_0_grp, pmu0_1_grp,
+ pmu0_2_grp, pmu0_3_grp, pmu0_4_grp,
+ pmu0_5_grp, pmu0_6_grp, pmu0_7_grp,
+ pmu0_8_grp, pmu0_9_grp, pmu0_10_grp,
+ pmu0_11_grp, pcie0_0_grp, pcie0_1_grp,
+ pcie0_2_grp, pcie0_3_grp, pcie0_4_grp,
+ pcie0_5_grp, pcie0_6_grp, pcie0_7_grp,
+ csu0_0_grp, csu0_1_grp, csu0_2_grp,
+ csu0_3_grp, csu0_4_grp, csu0_5_grp,
+ csu0_6_grp, csu0_7_grp, csu0_8_grp,
+ csu0_9_grp, csu0_10_grp, csu0_11_grp,
+ dpaux0_0_grp, dpaux0_1_grp, dpaux0_2_grp,
+ dpaux0_3_grp, pjtag0_0_grp, pjtag0_1_grp,
+ pjtag0_2_grp, pjtag0_3_grp, pjtag0_4_grp,
+ pjtag0_5_grp, trace0_0_grp, trace0_clk_0_grp,
+ trace0_1_grp, trace0_clk_1_grp, trace0_2_grp,
+ trace0_clk_2_grp, testscan0_0_grp
+
+ Valid values for pins are:
+   MIO0 - MIO77
+
+ Valid values for function are:
+   ethernet0, ethernet1, ethernet2, ethernet3, gemtsu0, usb0, usb1, mdio0,
+   mdio1, mdio2, mdio3, qspi0, qspi_fbclk, qspi_ss, spi0, spi1, spi0_ss,
+   spi1_ss, sdio0, sdio0_pc, sdio0_wp, sdio0_cd, sdio1, sdio1_pc, sdio1_wp,
+   sdio1_cd, nand0, nand0_ce, nand0_rb, nand0_dqs, can0, can1, uart0, uart1,
+   i2c0, i2c1, ttc0_clk, ttc0_wav, ttc1_clk, ttc1_wav, ttc2_clk, ttc2_wav,
+   ttc3_clk, ttc3_wav, swdt0_clk, swdt0_rst, swdt1_clk, swdt1_rst, gpio0, pmu0,
+   pcie0, csu0, dpaux0, pjtag0, trace0, trace0_clk, testscan0
+
+The following driver-specific properties as defined here are valid to specify in
+a pin configuration subnode:
+ - io-standard: Configure the pin to use the selected IO standard. Valid
+   arguments are 'IO_STANDARD_LVCMOS33' and 'IO_STANDARD_LVCMOS18'.
+ - schmitt-cmos: Selects either Schmitt or CMOS input for MIO pins. Valid
+   arguments are 'PIN_INPUT_TYPE_SCHMITT' and 'PIN_INPUT_TYPE_CMOS'.
+
+Example:
+
+firmware {
+	zynqmp_firmware: zynqmp-firmware {
+		compatible = "xlnx,zynqmp-firmware";
+		method = "smc";
+
+		pinctrl0: pinctrl {
+			compatible = "xlnx,zynqmp-pinctrl";
+
+			pinctrl_uart1_default: uart1-default {
+				mux {
+					groups = "uart0_4_grp";
+					function = "uart0";
+				};
+
+				conf {
+					groups = "uart0_4_grp";
+					slew-rate = <SLEW_RATE_SLOW>;
+					io-standard = <IO_STANDARD_LVCMOS18>;
+				};
+
+				conf-rx {
+					pins = "MIO18";
+					bias-high-impedance;
+				};
+
+				conf-tx {
+					pins = "MIO19";
+					bias-disable;
+					schmitt-cmos = <PIN_INPUT_TYPE_CMOS>;
+				};
+			};
+		};
+	};
+};
+
+uart1 {
+	...
+        pinctrl-names = "default";
+        pinctrl-0 = <&pinctrl_uart1_default>;
+	...
+
+};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/power/reset/xlnx,zynqmp-power.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/power/reset/xlnx,zynqmp-power.txt
@@ -8,9 +8,27 @@
  - compatible:		Must contain:	"xlnx,zynqmp-power"
  - interrupts:		Interrupt specifier
 
--------
-Example
--------
+Optional properties:
+ - mbox-names	: Name given to channels seen in the 'mboxes' property.
+		  "rx" - Mailbox corresponding to receive path
+		  "tx" - Mailbox corresponding to transmit path
+ - mboxes	: Standard property to specify a Mailbox. Each value of
+		  the mboxes property should contain a phandle to the
+		  mailbox controller device node and an args specifier
+		  that will be the phandle to the intended sub-mailbox
+		  child node to be used for communication. See
+		  Documentation/devicetree/bindings/mailbox/mailbox.txt
+		  for more details about the generic mailbox controller
+		  and client driver bindings. Also see
+		  Documentation/devicetree/bindings/mailbox/ \
+		  xlnx,zynqmp-ipi-mailbox.txt for typical controller that
+		  is used to communicate with this System controllers.
+
+--------
+Examples
+--------
+
+Example with interrupt method:
 
 firmware {
 	zynqmp_firmware: zynqmp-firmware {
@@ -23,3 +41,20 @@
 		};
 	};
 };
+
+Example with IPI mailbox method:
+
+firmware {
+
+	zynqmp_firmware: zynqmp-firmware {
+		compatible = "xlnx,zynqmp-firmware";
+		method = "smc";
+
+		zynqmp_power: zynqmp-power {
+			compatible = "xlnx,zynqmp-power";
+			mboxes = <&ipi_mailbox_pmu0 0>,
+				 <&ipi_mailbox_pmu0 1>;
+			mbox-names = "tx", "rx";
+		};
+	};
+};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/ptp/ptp-xilinx.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/ptp/ptp-xilinx.yaml
@@ -0,0 +1,34 @@
+# SPDX-License-Identifier: GPL-2.0-or-later OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/ptp/xilinx/ptp-xilinx.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Xilinx 1588 PTP timer-syncer
+
+maintainers:
+  - Harini Katakam <harini.katakam@xilinx.com>
+
+description: |
+  Xilinx 1588 PTP timer-syncer IP provides  precision timing functionality
+  along with capabiity for time and fine adjustment. This IP is provided
+  for use with Xilinx Ethernet MAC with HW timestamping capability.
+
+properties:
+  compatible:
+    const: xlnx,timer-syncer-1588-1.0
+
+  reg:
+    description: |
+      Offset and length of the register set for the device.
+
+required:
+  - compatible
+  - reg
+
+examples:
+  - |
+    ptp_timer@80000000 {
+        compatible = "xlnx,timer-syncer-1588-1.0";
+        reg = <0x0 0x80000000 0x0 0x10000>;
+    };
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/regulator/da9121.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/regulator/da9121.txt
@@ -0,0 +1,120 @@
+* Dialog Semiconductor DA9121 Single-channel 10A double-phase buck converter
+* Dialog Semiconductor DA9122 Double-channel  5A single-phase buck converter
+* Dialog Semiconductor DA9220 Double-channel  3A single-phase buck converter
+* Dialog Semiconductor DA9217 Single-channel  6A double-phase buck converter
+* Dialog Semiconductor DA9130 Single-channel 10A double-phase buck converter
+* Dialog Semiconductor DA9131 Double-channel  5A single-phase buck converter
+* Dialog Semiconductor DA9132 Double-channel  3A single-phase buck converter
+
+Required properties:
+
+- compatible : Should be "dlg,da9121" for DA9121
+- compatible : Should be "dlg,da9122" for DA9122
+- compatible : Should be "dlg,da9220" for DA9220
+- compatible : Should be "dlg,da9217" for DA9217
+- compatible : Should be "dlg,da9130" for DA9130
+- compatible : Should be "dlg,da9131" for DA9131
+- compatible : Should be "dlg,da9132" for DA9132
+- reg : Specifies the I2C slave address.
+- interrupt-parent : Specifies the reference to the interrupt controller.
+- interrupts : IRQ line information.
+
+Current limits
+
+  This is PER PHASE, and the current limit setting in the devices reflect
+  that with a maximum 10A limit. Allowing for transients as high as 100%
+  of the rated current, this translates across the device range to per
+  channel figures as so:
+
+                               | DA9121   DA9122     DA9220     DA9217   DA9140
+                               | /DA9130  /DA9131    /DA9132
+    -----------------------------------------------------------------------------
+    Output current / channel   | 10000000   5000000   3000000   6000000  40000000
+    Output current / phase     |  5000000   5000000   3000000   3000000  10000000
+    Min regulator-min-microamp |  7000000   3500000   3500000   7000000  15000000
+    Max regulator-max-microamp | 20000000  10000000   6000000  12000000  80000000
+    Device hardware default    | 15000000   7500000   5500000  11000000  TBD
+
+Optional properties:
+
+- dlg,irq-polling-delay-passive : Specify the polling period, measured in
+  milliseconds, between interrupt status update checks.
+
+Sub-nodes:
+
+- regulators : This node defines the settings for the BUCK. The content of the
+  sub-node is defined by the standard binding for regulators; see regulator.txt.
+  The DA9121 regulator is bound using their names listed below:
+
+    buck1 : BUCK1
+    buck2 : BUCK2	//DA9122, DA9220, DA9131, DA9132 only
+
+Optional properties for regulators:
+
+- regulator-mode         : defined in include/dt-bindings/regulator/dlg,da9121-regulator.h
+- regulator-initial-mode : Same as regulator-mode
+- dlg,enable-gpio        : Specify a valid GPIO for platform control of the regulator.
+- dlg,ripple-cancel      : defined in include/dt-bindings/regulator/dlg,da9121-regulator.h
+                           Only present on multi-channel devices
+
+Example:
+	pmic: da9121@68 {
+		compatible = "dlg,da9121";
+		reg = <0x68>;
+
+		interrupt-parent = <&gpio6>;
+		interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
+
+		dlg,irq-polling-delay-passive = <2000>;
+
+		regulators {
+			DA9121_BUCK1: buck1 {
+				regulator-name = "BUCK1";
+				regulator-min-microvolt = <300000>;
+				regulator-max-microvolt = <1900000>;
+				regulator-min-microamp = <7000000>;
+				regulator-max-microamp = <20000000>;
+				regulator-boot-on;
+				regulator-initial-mode = <DA9121_BUCK_MODE_AUTO>;
+				dlg,enable-gpio = <&gpio 1 GPIO_ACTIVE_HIGH>;
+			};
+		};
+	};
+
+
+Example:
+	pmic: da9122@68 {
+		compatible = "dlg,da9122";
+		reg = <0x68>;
+
+		interrupt-parent = <&gpio6>;
+		interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
+
+		dlg,irq-polling-delay-passive = <2000>;
+
+		regulators {
+			DA9122_BUCK1: buck1 {
+				regulator-name = "BUCK1";
+				regulator-min-microvolt = <300000>;
+				regulator-max-microvolt = <1900000>;
+				regulator-min-microamp = <3500000>;
+				regulator-max-microamp = <10000000>;
+				regulator-boot-on;
+				regulator-initial-mode = <DA9121_BUCK_MODE_AUTO>;
+				dlg,enable-gpio = <&gpio6 1 GPIO_ACTIVE_HIGH>;
+				dlg,ripple-cancel = <DA9121_BUCK_RIPPLE_CANCEL_NONE>;
+			};
+			DA9122_BUCK2: buck2 {
+				regulator-name = "BUCK2";
+				regulator-min-microvolt = <300000>;
+				regulator-max-microvolt = <1900000>;
+				regulator-min-microamp = <3500000>;
+				regulator-max-microamp = <10000000>;
+				regulator-boot-on;
+				regulator-initial-mode = <DA9121_BUCK_MODE_AUTO>;
+				dlg,enable-gpio = <&gpio6 2 GPIO_ACTIVE_HIGH>;
+				dlg,ripple-cancel = <DA9121_BUCK_RIPPLE_CANCEL_NONE>;
+			};
+		};
+	};
+
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/regulator/samsung,s5m8767.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/regulator/samsung,s5m8767.txt
@@ -13,6 +13,14 @@
 
 
 Required properties of the main device node (the parent!):
+ - s5m8767,pmic-buck-ds-gpios: GPIO specifiers for three host gpio's used
+   for selecting GPIO DVS lines. It is one-to-one mapped to dvs gpio lines.
+
+ [1] If either of the 's5m8767,pmic-buck[2/3/4]-uses-gpio-dvs' optional
+     property is specified, then all the eight voltage values for the
+     's5m8767,pmic-buck[2/3/4]-dvs-voltage' should be specified.
+
+Optional properties of the main device node (the parent!):
  - s5m8767,pmic-buck2-dvs-voltage: A set of 8 voltage values in micro-volt (uV)
    units for buck2 when changing voltage using gpio dvs. Refer to [1] below
    for additional information.
@@ -25,26 +33,13 @@
    units for buck4 when changing voltage using gpio dvs. Refer to [1] below
    for additional information.
 
- - s5m8767,pmic-buck-ds-gpios: GPIO specifiers for three host gpio's used
-   for selecting GPIO DVS lines. It is one-to-one mapped to dvs gpio lines.
-
- [1] If none of the 's5m8767,pmic-buck[2/3/4]-uses-gpio-dvs' optional
-     property is specified, the 's5m8767,pmic-buck[2/3/4]-dvs-voltage'
-     property should specify atleast one voltage level (which would be a
-     safe operating voltage).
-
-     If either of the 's5m8767,pmic-buck[2/3/4]-uses-gpio-dvs' optional
-     property is specified, then all the eight voltage values for the
-     's5m8767,pmic-buck[2/3/4]-dvs-voltage' should be specified.
-
-Optional properties of the main device node (the parent!):
  - s5m8767,pmic-buck2-uses-gpio-dvs: 'buck2' can be controlled by gpio dvs.
  - s5m8767,pmic-buck3-uses-gpio-dvs: 'buck3' can be controlled by gpio dvs.
  - s5m8767,pmic-buck4-uses-gpio-dvs: 'buck4' can be controlled by gpio dvs.
 
 Additional properties required if either of the optional properties are used:
 
- - s5m8767,pmic-buck234-default-dvs-idx: Default voltage setting selected from
+ - s5m8767,pmic-buck-default-dvs-idx: Default voltage setting selected from
    the possible 8 options selectable by the dvs gpios. The value of this
    property should be between 0 and 7. If not specified or if out of range, the
    default value of this property is set to 0.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/remoteproc/xilinx,zynqmp-r5-remoteproc.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/remoteproc/xilinx,zynqmp-r5-remoteproc.txt
@@ -0,0 +1,135 @@
+Xilinx ARM Cortex A53-R5 remoteproc driver
+==========================================
+
+ZynqMP family of devices use two Cortex R5 processors to help with various
+low power / real time tasks.
+
+This driver requires specific ZynqMP hardware design.
+
+ZynqMP R5 Device Node:
+=================================
+A ZynqMP R5 device node is used to represent RPU domain
+within ZynqMP SoC. This device node contains RPU processor
+subnodes.
+
+Required Properties:
+--------------------
+ - compatible : Should be "xlnx,zynqmp-r5-remoteproc-1.0"
+ - core_conf : R5 core configuration (valid string - split or lock-step)
+ - interrupts : Interrupt mapping for remoteproc IPI. It is required if the
+                user uses the remoteproc driver with the RPMsg kernel driver.
+ - interrupt-parent : Phandle for the interrupt controller. It is required if
+                      the user uses the remoteproc driver with the RPMsg kernel
+                      kernel driver.
+
+ZynqMP R5 Remoteproc Device Node:
+=================================
+A ZynqMP R5 Remoteproc device node is used to represent a RPU processor.
+It is a subnode to the ZynqMP R5 device node. It also contains tightly
+coupled memory subnodes.
+
+Required Properties:
+--------------------
+ - pnode-id:	ZynqMP R5 processor power domain ID which will be used by
+		ZynqMP power management unit to idetify the processor.
+
+Optional Properties:
+--------------------
+ - memory-region: reserved memory which will be used by R5 processor
+
+
+ZynqMP R5 Remoteproc Device Node:
+=================================
+A ZynqMP R5 Remoteproc device node is used to represent a RPU processor.
+It is a subnode to the ZynqMP R5 device node.
+
+Required Properties:
+--------------------
+ - pnode-id:	ZynqMP R5 processor power domain ID which will be used by
+		ZynqMP power management unit to idetify the processor.
+
+Optional Properties:
+--------------------
+ - memory-region:	reserved memory which will be used by R5 processor
+ - mboxes:		Specify tx and rx mailboxes
+ - mbox-names:		List of identifier strings for tx/rx mailbox channel.
+
+ZynqMP R5 TCM Device Node:
+=================================
+The ZynqMP R5 TCM device node is used to represent the TCM memory.
+It is a subnode to the ZynqMP R5 processor.
+
+Required Properties:
+--------------------
+ - reg:		TCM address range
+ - pnode-id:	TCM power domain ID
+
+
+Example:
+--------
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+		/* R5 0 firmware memory in DDR */
+		rproc_0_fw_reserved: rproc@3ed000000 {
+			no-map;
+			reg = <0x0 0x3ed00000 0x0 0x40000>;
+		};
+		/* DMA shared memory between APU and RPU */
+		rproc_0_dma_reserved: rproc@3ed400000 {
+			compatible = "shared-dma-pool";
+			no-map;
+			reg = <0x0 0x3ed40000 0x0 0x100000>;
+		};
+	};
+
+	zynqmp-r5-remoteproc@0 {
+		compatible = "xlnx,zynqmp-r5-remoteproc-1.0";
+		core_conf = "split";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+		r5-0: r5@0 {
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges;
+			memory-region = <&rproc_0_fw_reserved>,
+					<&rproc_0_dma_reserved>;
+			pnode-id = <0x7>;
+			mboxes = <&ipi_mailbox_rpu0 0>, <&ipi_mailbox_rpu0 1>;
+			mbox-names = "tx", "rx";
+			tcm-a: tcm@0 {
+				reg = <0x0 0xFFE00000 0x0 0x10000>,
+				pnode-id = <0xf>;
+			};
+			tcm-b: tcm@1 {
+				reg = <0x0 0xFFE20000 0x0 0x10000>,
+				pnode-id = <0x10>;
+			};
+		};
+	} ;
+
+	zynqmp_ipi {
+		compatible = "xlnx,zynqmp-ipi-mailbox";
+		interrupt-parent = <&gic>;
+		interrupts = <0 29 4>;
+		xlnx,ipi-id = <7>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		/* APU<->RPU0 IPI mailbox controller */
+		ipi_mailbox_rpu0: mailbox@ff90600 {
+			reg = <0xff990600 0x20>,
+			      <0xff990620 0x20>,
+			      <0xff9900c0 0x20>,
+			      <0xff9900e0 0x20>;
+			reg-names = "local_request_region",
+				    "local_response_region",
+				    "remote_request_region",
+				    "remote_response_region";
+			#mbox-cells = <1>;
+			xlnx,ipi-id = <1>;
+		};
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/remoteproc/zynq_remoteproc.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/remoteproc/zynq_remoteproc.txt
@@ -0,0 +1,47 @@
+Xilinx ARM Cortex A9-A9 remoteproc driver
+==========================================
+
+Zynq family of devices can use one A9 processor to help with various
+low power / real time tasks.
+
+This driver requires specific Zynq hardware design.
+
+Zynq RemoteProc Device Node:
+=================================
+A zynq_remoteproc device node is used to represent the 2nd A9 instance
+within Zynq SoC.
+
+Required properties:
+--------------------
+ - compatible : should be "xlnx,zynq_remoteproc"
+ - vring0: soft interrupt for kicking from firmware
+ - vring1: soft interrupt for kicking from Linux kernel
+
+Optional Properties:
+--------------------
+ - memory-region: reserved memory which will be used by R5 processor
+
+Example:
+--------
+
+	reserved-memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		rproc_0_reserved: rproc@3e000000 {
+			no-map;
+			reg = <0x3e000000 0x400000>;
+		};
+		rproc_0_dma: rproc@3e800000 {
+			no-map;
+			compatible = "shared-dma-pool";
+			reg = <0x3e800000 0x100000>;
+		};
+	};
+
+	zynq_remoteproc@0 {
+		compatible = "xlnx,zynq_remoteproc";
+		vring0 = <15>;
+		vring1 = <14>;
+		memory-region = <&rproc_0_reserved>, <&rproc_0_dma>;
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/reset/brcm,brcmstb-reset.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/reset/brcm,brcmstb-reset.txt
@@ -22,6 +22,6 @@
 	};
 
 	&ethernet_switch {
-		resets = <&reset>;
+		resets = <&reset 26>;
 		reset-names = "switch";
 	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/rng/omap3_rom_rng.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/rng/omap3_rom_rng.txt
@@ -0,0 +1,27 @@
+OMAP ROM RNG driver binding
+
+Secure SoCs may provide RNG via secure ROM calls like Nokia N900 does. The
+implementation can depend on the SoC secure ROM used.
+
+- compatible:
+	Usage: required
+	Value type: <string>
+	Definition: must be "nokia,n900-rom-rng"
+
+- clocks:
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: reference to the the RNG interface clock
+
+- clock-names:
+	Usage: required
+	Value type: <stringlist>
+	Definition: must be "ick"
+
+Example:
+
+	rom_rng: rng {
+		compatible = "nokia,n900-rom-rng";
+		clocks = <&rng_ick>;
+		clock-names = "ick";
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml
@@ -128,7 +128,6 @@
   - compatible
   - reg
   - interrupts
-  - clocks
   - clock-output-names
 
 additionalProperties: false
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/serial/pl011.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/serial/pl011.yaml
@@ -20,6 +20,7 @@
         enum:
           - arm,pl011
           - zte,zx296702-uart
+          - arm,xlnx-sbsa-uart
   required:
     - compatible
 
@@ -32,6 +33,10 @@
       - items:
           - const: zte,zx296702-uart
           - const: arm,primecell
+      - items:
+          - const: arm,xlnx-sbsa-uart
+          - const: arm,primecell
+
 
   reg:
     maxItems: 1
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/serial/uartlite.c
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/serial/uartlite.c
@@ -0,0 +1,26 @@
+Xilinx Axi Uartlite controller Device Tree Bindings
+---------------------------------------------------------
+
+Required properties:
+- compatible		: Can be either of
+				"xlnx,xps-uartlite-1.00.a"
+				"xlnx,opb-uartlite-1.00.b"
+- reg			: Physical base address and size of the Axi Uartlite
+			  registers map.
+- interrupts		: Property with a value describing the interrupt
+			  number.
+- interrupt-parent	: Must be core interrupt controller.
+
+Optional properties:
+- port-number		: Set Uart port number
+- clock-names		: Should be "s_axi_aclk"
+- clocks		: Input clock specifier. Refer to common clock bindings.
+
+Example:
+serial@800C0000 {
+	compatible = "xlnx,xps-uartlite-1.00.a";
+	reg = <0x0 0x800c0000 0x10000>;
+	interrupt-parent = <&gic>;
+	interrupts = <0x0 0x6e 0x1>;
+	port-number = <0>;
+};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/soc/xilinx/xlnx,ai-engine-npi.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/soc/xilinx/xlnx,ai-engine-npi.txt
@@ -0,0 +1,23 @@
+Xilinx AI Engine NPI
+--------------------
+
+The Xilinx AI Engine NPI space is where the privileged operations for AI Engine
+device are handled, such as reset and pll. The space is typically meant to be
+owned by platform management software, and this space is accessible only when
+the platform management software grants the access. Thus, this dt binding only
+works in such configuration, and in case the platform locks the access,
+the non-secure software fails to access the device.
+
+This is a temporary solution to allow direct access to NPI space.
+
+Required properties:
+
+- compatible: Must be "xlnx,ai-engine-npi"
+- reg: Physical base address and length of the registers set for the device.
+
+Example:
+
+	aie-npi@f70a0000 {
+		compatible = "xlnx,ai-engine-npi";
+		reg = <0x0 0xf70a0000 0x0 0x1000>;
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/soc/xilinx/xlnx,ai-engine.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/soc/xilinx/xlnx,ai-engine.yaml
@@ -0,0 +1,136 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/soc/xilinx/xlnx,ai-engine.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Xilinux AI Engine
+
+maintainers:
+ - Wendy Liang <wendy.liang@xilinx.com>
+
+description: |+
+  The Xilinx AI Engine is a tile processor with many cores (up to 400) that
+  can run in parallel. The data routing between cores is configured through
+  internal switches, and shim tiles interface with external interconnect, such
+  as memory or PL.
+
+properties:
+  compatible:
+    const: xlnx,ai-engine-v1.0
+
+  reg:
+    description: |
+      Physical base address and length of the device registers.
+      The AI engine address space assigned to Linux is defined by Xilinx
+      platform design tool.
+
+  '#address-cells':
+    enum: [2]
+    description: |
+      size of cell to describe AI engine range of tiles address.
+      It is the location of the starting tile of the range.
+      As the AI engine tiles are 2D array, the location of a tile
+      is presented as (column, row), the address cell is 2.
+
+  '#size-cells':
+    enum: [2]
+    description: |
+      size of cell to describe AI engine range of tiles size.
+      As the AI engine tiles are 2D array, the size cell is 2.
+
+  interrupts:
+    maxItems: 3
+
+  interrupt-names:
+    description: |
+      Should be "interrupt1", "interrupt2" or "interrupt3".
+
+required:
+  - compatible
+  - reg
+  - '#address-cells'
+  - '#size-cells'
+  - power-domains
+  - interrupt-parent
+  - interrupts
+  - interrupt-names
+
+patternProperties:
+  "^partition[0-9]@[0-9]+$":
+    type: object
+    description: |
+      AI engine partition which is a group of column based tiles of the AI
+      engine device. Each AI engine partition is isolated from the other
+      AI engine partitions. An AI engine partition is defined by Xilinx
+      platform design tools.
+      AI engine partition driver will create a FPGA bridge when probes the
+      AI engine partition. The AI engine SHIM row of the partition is the
+      bridge to connect AI engine partition, FPGA and PS.
+
+    properties:
+      reg:
+        description: |
+          It describes the group of tiles of the AI engine partition. It needs
+          to include the SHIM row. The format is defined by the parent AI engine
+          device node's '#address-cells' and '#size-cells' properties. e.g. a v1
+          AI engine device has 2D tiles array, the first row is SHIM row. A
+          partition which has 50 columns and 8 rows of core tiles and 1 row of
+          SHIM tiles will be presented as <0 0 50 9>.
+
+      label:
+        maxItems: 1
+
+      xlnx,partition-id:
+        $ref: /schemas/types.yaml#/definitions/uint32
+        description: |
+          AI engine partition ID, which is defined by Xilinx platform design
+          tool to identify the AI engine partition in the system.
+
+    required:
+      - reg
+      - xlnx,partition-id
+
+examples:
+  - |
+    #include <dt-bindings/power/xlnx-versal-power.h>
+    bus {
+      #address-cells = <2>;
+      #size-cells = <2>;
+
+      ai_engine: ai-engine@20000000000 {
+        compatible = "xlnx,ai-engine-v1.0";
+        reg = <0x200 0x0 0x1 0x0>;
+        #address-cells = <2>;
+        #size-cells = <2>;
+        power-domains = <&versal_firmware PM_DEV_AI>;
+        interrupt-parent = <&gic>;
+        interrupts = <0x0 0x94 0x4>,
+                        <0x0 0x95 0x4>,
+                        <0x0 0x96 0x4>;
+        interrupt-names = "interrupt1", "interrupt2", "interrupt3";
+
+        aie_partition0: aie-partition@0 {
+                /* 50 columns and 8 core tile rows + 1 SHIM row */
+                reg = <0 0 50 9>;
+                xlnx,partition-id = <1>;
+        };
+      };
+    };
+
+  - |
+    /*
+     * Device tree overlay example to for FPGA partial configuration which
+     * connects to AI engine partition.
+     */
+    fpga_region0: fpga_region0 {
+      fpga-bridges = <&aie_partition0>;
+    };
+    fragment@0 {
+      target = <&fpga_region0>;
+      #address-cells = <1>;
+      #size-cells = <1>;
+      __overlay__ {
+        firmware-name = "partition.pdi";
+      };
+    };
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/soc/xilinx/xlnx,ai_engine.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/soc/xilinx/xlnx,ai_engine.txt
@@ -0,0 +1,28 @@
+Xilinx AI Engine
+----------------
+
+The Xilinx AI Engine is a tile processor with many cores (up to 400) that
+can run in parallel. The data routing between cores is configured through
+internal switches, and shim tiles interface with external interconnect, such
+as memory or PL.
+
+Required properties:
+
+- compatible: Must be "xlnx,ai_engine".
+- reg: Physical base address and length of the registers set for the device.
+- interrupt-parent: the phandle to the interrupt controller.
+- interrupts: the interrupt numbers.
+- interrupt-names: Should be "interrupt0", "interrupt1", "interrupt2" or
+  "interrupt3".
+
+Example:
+
+	ai_engine@20000000000 {
+		compatible = "xlnx,ai_engine";
+		reg = <0x200 0x0 0x1 0x0>;
+		interrupt-parent = <&gic>;
+		interrupts = <0x0 0x94 0x1>,
+			     <0x0 0x95 0x1>,
+			     <0x0 0x96 0x1>;
+		interrupt-names = "interrupt1", "interrupt2", "interrupt3";
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/soc/xilinx/xlnx,vcu.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/soc/xilinx/xlnx,vcu.txt
@@ -16,16 +16,64 @@
 	1. vcu slcr
 	2. Logicore
 	reg-names should contain name for the each register sequence.
-- clocks: phandle for aclk and pll_ref clocksource
-- clock-names: The identification string, "aclk", is always required for
-   the axi clock. "pll_ref" is required for pll.
+- #clock-cells : Must be 1
+- clocks: phandle for aclk, pll_ref and encoder/decoder clocksources
+- clock-names: The identification string,
+	* "aclk", is always required for the axi clock.
+	* "pll_ref" is required for pll.
+	* "vcu_core_enc" is required for VCU core encoder.
+	* "vcu_core_dec" is required for VCU core decoder.
+	* "vcu_mcu_enc" is required for MCU core encoder.
+	* "vcu_mcu_dec" is required for MCU core decoder.
+- ranges
+- VCU Init driver node define the following child nodes:
+	* Allegro encoder driver node
+		- compatible: Must be "al,al5e"
+		- reg: There is a one set of register.
+		- interrupts: interrupt number to the cpu.
+		- interrupt-parent: the phandle for the interrupt controller
+		  that services interrupts for this device.
+	* Allegro decoder driver node
+		- compatible: Must be "al,al5d"
+		- reg: There is a one set of register.
+		- interrupts: interrupt number to the cpu.
+		- interrupt-parent: the phandle for the interrupt controller
+		  that services interrupts for this device.
+
+Optional properties:
+- reset-gpios : The GPIO used to reset the VCU, if available. Need use this
+		reset gpio when in design 'vcu_resetn' is driven by gpio. See
+		Documentation/devicetree/bindings/gpio/gpio.txt for details.
+- xlnx,skip-isolation : This property indicates the driver that vcu gasket
+			isolation is removed by hw by default, the driver can
+			skip isolation removal.
+
 Example:
 
 	xlnx_vcu: vcu@a0040000 {
 		compatible = "xlnx,vcu-logicoreip-1.0";
+		#address-cells = <2>;
+		#size-cells = <2>;
 		reg = <0x0 0xa0040000 0x0 0x1000>,
 			 <0x0 0xa0041000 0x0 0x1000>;
 		reg-names = "vcu_slcr", "logicore";
-		clocks = <&si570_1>, <&clkc 71>;
-		clock-names = "pll_ref", "aclk";
+		reset-gpios = <&gpio 0x4e GPIO_ACTIVE_HIGH>;
+		#clock-cells = <0x1>;
+		clock-names = "pll_ref", "aclk", "vcu_core_enc", "vcu_core_dec", "vcu_mcu_enc", "vcu_mcu_dec";
+		clocks = <&si570_1>, <&clkc 71>, <&xlnx_vcu 1>, <&xlnx_vcu 2>, <&xlnx_vcu 3>, <&xlnx_vcu 4>;
+		ranges;
+		xlnx,skip-isolation;
+		encoder: al5e@a0000000 {
+			compatible = "al,al5e";
+			reg = <0x0 0xa0000000 0x0 0x10000>;
+			interrupts = <0 89 4>;
+			interrupt-parent = <&gic>;
+		};
+
+		decoder: al5d@a0020000 {
+			compatible = "al,al5d";
+			reg = <0x0 0xa0020000 0x0 0x10000>;
+			interrupts = <0 89 4>;
+			interrupt-parent = <&gic>;
+		};
 	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/sound/mt8183-mt6358-ts3a227-max98357.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/sound/mt8183-mt6358-ts3a227-max98357.txt
@@ -2,9 +2,11 @@
 
 Required properties:
 - compatible : "mediatek,mt8183_mt6358_ts3a227_max98357"
-- mediatek,headset-codec: the phandles of ts3a227 codecs
 - mediatek,platform: the phandle of MT8183 ASoC platform
 
+Optional properties:
+- mediatek,headset-codec: the phandles of ts3a227 codecs
+
 Example:
 
 	sound {
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/sound/qcom,wcd9335.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/sound/qcom,wcd9335.txt
@@ -109,7 +109,7 @@
 	reg  = <1 0>;
 	interrupts = <&msmgpio 54 IRQ_TYPE_LEVEL_HIGH>;
 	interrupt-names = "intr2"
-	reset-gpios = <&msmgpio 64 0>;
+	reset-gpios = <&msmgpio 64 GPIO_ACTIVE_LOW>;
 	slim-ifc-dev  = <&wc9335_ifd>;
 	clock-names = "mclk", "native";
 	clocks = <&rpmcc RPM_SMD_DIV_CLK1>,
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/sound/rt5645.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/sound/rt5645.txt
@@ -16,6 +16,11 @@
   a GPIO spec for the external headphone detect pin. If jd-mode = 0,
   we will get the JD status by getting the value of hp-detect-gpios.
 
+- cbj-sleeve-gpios:
+  a GPIO spec to control the external combo jack circuit to tie the sleeve/ring2
+  contacts to the ground or floating. It could avoid some electric noise from the
+  active speaker jacks.
+
 - realtek,in2-differential
   Boolean. Indicate MIC2 input are differential, rather than single-ended.
 
@@ -64,6 +69,7 @@
 	compatible = "realtek,rt5650";
 	reg = <0x1a>;
 	hp-detect-gpios = <&gpio 19 0>;
+	cbj-sleeve-gpios = <&gpio 20 0>;
 	interrupt-parent = <&gpio>;
 	interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
 	realtek,dmic-en = "true";
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/sound/wm8994.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/sound/wm8994.txt
@@ -14,9 +14,15 @@
   - #gpio-cells : Must be 2. The first cell is the pin number and the
     second cell is used to specify optional parameters (currently unused).
 
-  - AVDD2-supply, DBVDD1-supply, DBVDD2-supply, DBVDD3-supply, CPVDD-supply,
-    SPKVDD1-supply, SPKVDD2-supply : power supplies for the device, as covered
-    in Documentation/devicetree/bindings/regulator/regulator.txt
+  - power supplies for the device, as covered in
+    Documentation/devicetree/bindings/regulator/regulator.txt, depending
+    on compatible:
+    - for wlf,wm1811 and wlf,wm8958:
+      AVDD1-supply, AVDD2-supply, DBVDD1-supply, DBVDD2-supply, DBVDD3-supply,
+      DCVDD-supply, CPVDD-supply, SPKVDD1-supply, SPKVDD2-supply
+    - for wlf,wm8994:
+      AVDD1-supply, AVDD2-supply, DBVDD-supply, DCVDD-supply, CPVDD-supply,
+      SPKVDD1-supply, SPKVDD2-supply
 
 Optional properties:
 
@@ -73,11 +79,11 @@
 
 	lineout1-se;
 
+	AVDD1-supply = <&regulator>;
 	AVDD2-supply = <&regulator>;
 	CPVDD-supply = <&regulator>;
-	DBVDD1-supply = <&regulator>;
-	DBVDD2-supply = <&regulator>;
-	DBVDD3-supply = <&regulator>;
+	DBVDD-supply = <&regulator>;
+	DCVDD-supply = <&regulator>;
 	SPKVDD1-supply = <&regulator>;
 	SPKVDD2-supply = <&regulator>;
 };
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/sound/xlnx,audio-formatter.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/sound/xlnx,audio-formatter.txt
@@ -1,6 +1,6 @@
 Device-Tree bindings for Xilinx PL audio formatter
 
-The IP core supports DMA, data formatting(AES<->PCM conversion)
+The IP core supports DMA, data formatting(packing, conversion)
 of audio samples.
 
 Required properties:
@@ -13,8 +13,21 @@
  - interrupts-parent: Phandle for interrupt controller.
  - interrupts: List of Interrupt numbers.
  - reg: Base address and size of the IP core instance.
+ - xlnx,tx: connected audio sink node.
+	    Should be one of below supported nodes:
+		1. HDMI video Tx output
+		2. I2S transmitter
+		3. UHDSDI audio embed
+	    Only those nodes were supported in sound card driver
+
+ - xlnx,rx: connected audio source node.
+	    Should be one of below supported nodes:
+		1. HDMI video Rx input
+		2. I2S receiver
+		3. UHDSDI audio extract
+	    Only those nodes were supported in sound card driver
  - clock-names: List of input clocks.
-   Required elements: "s_axi_lite_aclk", "aud_mclk"
+   Required elements: "s_axi_lite_aclk", "m_axis_mm2s_aclk", "aud_mclk", "s_axis_s2mm_aclk"
  - clocks: Input clock specifier. Refer to common clock bindings.
 
 Example:
@@ -24,6 +37,8 @@
 		interrupt-parent = <&gic>;
 		interrupts = <0 104 4>, <0 105 4>;
 		reg = <0x0 0x80010000 0x0 0x1000>;
-		clock-names = "s_axi_lite_aclk", "aud_mclk";
-		clocks = <&clk 71>, <&clk_wiz_1 0>;
+		xlnx,tx = <&i2s_transmitter>;
+		xlnx,rx = <&i2s_receiver>;
+		clock-names = "s_axi_lite_aclk", "m_axis_mm2s_aclk", "aud_mclk", "s_axis_s2mm_aclk";
+		clocks = <&clk 71>, <&audio_ss_0_clk_wiz_0 0>, <&audio_ss_0_clk_wiz_0 0>, <&clk 71>;
 	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/sound/xlnx,dp-snd-card.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/sound/xlnx,dp-snd-card.txt
@@ -0,0 +1,17 @@
+Device-Tree bindings for Xilinx ZynqMP DisplayPort Audio Card
+
+The card driver integrates codec and pcm components and represents as a single
+audio device.
+
+Required properties:
+ - compatible: Should be "xlnx,dp-snd-card".
+ - xlnx,dp-snd-pcm: phandle(s) to the ZynqMP DP PCM node.
+ - xlnx,dp-snd-codec: phandle to the ZynqMP DP card node.
+
+Example:
+
+	xlnx_dp_snd_card: dp_snd_card {
+		compatible = "xlnx,dp-snd-card";
+		xlnx,dp-snd-pcm = <&xlnx_dp_snd_pcm0>, <&xlnx_dp_snd_pcm1>;
+		xlnx,dp-snd-codec = <&xlnx_dp_snd_codec0>;
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/sound/xlnx,dp-snd-codec.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/sound/xlnx,dp-snd-codec.txt
@@ -0,0 +1,18 @@
+Device-Tree bindings for Xilinx ZynqMP DisplayPort Codec
+
+The codec driver handles the audio clock and format management.
+
+Required properties:
+ - compatible: Should be "xlnx,dp-snd-codec".
+ - clocks: The phandle for the audio clock. The audio clock should be
+   configured to the correct audio clock rate, which should be one of
+   (44100 * 512) or (48000 * 512).
+ - clock-names: The identification string should be "aud_clk".
+
+Example:
+
+	xlnx_dp_snd_codec0: dp_snd_codec0 {
+		compatible = "xlnx,dp-snd-codec";
+		clocks = <&dp_aud_clk>;
+		clock-names = "aud_clk";
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/sound/xlnx,dp-snd-pcm.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/sound/xlnx,dp-snd-pcm.txt
@@ -0,0 +1,18 @@
+Device-Tree bindings for Xilinx ZynqMP DisplayPort PCM
+
+The DPDMA driver of ZynqMP DisplayPort subsystem is based on DMA engine,
+and the DP PCM driver is based on snd dmaengine helpers.
+
+Required properties:
+ - compatible: Should be "xlnx,dp-snd-pcm" or "xlnx,dp-snd-pcm0" or "xlnx,dp-snd-pcm1".
+ - dmas: the phandle list of DMA specifiers. The dma channel ID should be one
+   of 4 for audio0 channel or 5 for audio1 channel.
+ - dma-names: the indentifier strings for DMAs. The value should be "tx".
+
+Example:
+
+	xlnx_dp_snd_pcm0: dp_snd_pcm0 {
+		compatible = "xlnx,dp-snd-pcm0";
+		dmas = <&xlnx_dpdma 4>;
+		dma-names = "tx";
+	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/sound/xlnx,i2s.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/sound/xlnx,i2s.txt
@@ -11,18 +11,31 @@
  - xlnx,dwidth: sample data width. Can be any of 16, 24.
  - xlnx,num-channels: Number of I2S streams. Can be any of 1, 2, 3, 4.
 		      supported channels = 2 * xlnx,num-channels
+ - xlnx,snd-pcm: reference to audio formatter block
+ - clock-names: List of input clocks.
+   Required elements for I2S Tx: "s_axi_ctrl_aclk", "aud_mclk", "s_axis_aud_aclk".
+   Required elements for I2S Rx: "s_axi_ctrl_aclk", "aud_mclk", "m_axis_aud_aclk".
+ - clocks: Input clock specifier. Refer to common clock bindings.
 
 Example:
 
 	i2s_receiver@a0080000 {
 		compatible = "xlnx,i2s-receiver-1.0";
+		clock-names = "s_axi_ctrl_aclk", "aud_mclk", "m_axis_aud_aclk";
+		clocks = <&clk 71>, <&audio_ss_0_clk_wiz_0 0>, <&clk 71>;
 		reg = <0x0 0xa0080000 0x0 0x10000>;
 		xlnx,dwidth = <0x18>;
 		xlnx,num-channels = <1>;
+		xlnx,snd-pcm = <&audio_ss_0_audio_formatter_0>;
 	};
 	i2s_transmitter@a0090000 {
 		compatible = "xlnx,i2s-transmitter-1.0";
+		clock-names = "s_axi_ctrl_aclk", "aud_mclk", "s_axis_aud_aclk";
+		clocks = <&clk 71>, <&audio_ss_0_clk_wiz_0 0>, <&audio_ss_0_clk_wiz_0 0>;
 		reg = <0x0 0xa0090000 0x0 0x10000>;
 		xlnx,dwidth = <0x18>;
 		xlnx,num-channels = <1>;
+		xlnx,snd-pcm = <&audio_ss_0_audio_formatter_0>;
 	};
+	Documentation of "audio_ss_0_audio_formatter_0" node is located
+	at Documentation/devicetree/bindings/sound/xlnx,audio-formatter.txt
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/sound/xlnx,spdif.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/sound/xlnx,spdif.txt
@@ -1,28 +1,27 @@
-Device-Tree bindings for Xilinx SPDIF IP
+Device-Tree bindings for Xilinx SPDIF PL IP
 
-The IP supports playback and capture of SPDIF audio
+The IP supports SPDIF based playback and capture audio
 
 Required properties:
  - compatible: "xlnx,spdif-2.0"
  - clock-names: List of input clocks.
-   Required elements: "s_axi_aclk", "aud_clk_i"
+   Required elements for SPDIF Tx: "aud_clk_i", "s_axi_aclk", "s_axis_aclk".
+   Required elements for SPDIF Rx: "aud_clk_i", "s_axi_aclk", "m_axis_aclk".
  - clocks: Input clock specifier. Refer to common clock bindings.
  - reg: Base address and address length of the IP core instance.
  - interrupts-parent: Phandle for interrupt controller.
  - interrupts: List of Interrupt numbers.
- - xlnx,spdif-mode: 0 :- receiver mode
-		    1 :- transmitter mode
- - xlnx,aud_clk_i: input audio clock value.
+ - xlnx,spdif-mode: 0 :- receiver mode ; 1 :- transmitter mode
+ - xlnx,snd-pcm: phandle to audio formatter node
 
-Example:
+Example - SPDIF Rx:
 	spdif_0: spdif@80010000 {
-		clock-names = "aud_clk_i", "s_axi_aclk";
-		clocks = <&misc_clk_0>, <&clk 71>;
+		clock-names = "aud_clk_i", "s_axi_aclk", "m_axis_aclk";
+		clocks = <&si570_1>, <&clk 71>, <&clk 71>;
 		compatible = "xlnx,spdif-2.0";
-		interrupt-names = "spdif_interrupt";
 		interrupt-parent = <&gic>;
 		interrupts = <0 91 4>;
 		reg = <0x0 0x80010000 0x0 0x10000>;
 		xlnx,spdif-mode = <1>;
-		xlnx,aud_clk_i = <49152913>;
+		xlnx,snd-pcm = <&audio_formatter_0>;
 	};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/sound/xlnx,v-uhdsdi-audio.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/sound/xlnx,v-uhdsdi-audio.txt
@@ -0,0 +1,60 @@
+Device-Tree bindings for Xilinx SDI audio
+
+The IP core supports embed/extract of audio in SDI Tx and Rx
+protocol respectively. Reference to PG:
+https://www.xilinx.com/support/documentation/ip_documentation/v_uhdsdi_audio/v1_0/pg309-v-uhdsdi-audio.pdf
+
+Required properties:
+ - compatible: Should be one of:
+		"xlnx,v-uhdsdi-audio-2.0"
+		"xlnx,v-uhdsdi-audio-1.0"
+   Note: v1.0 (xlnx,v-uhdsdi-audio-1.0) is deprecated
+   and driver no longer supports it. Mandatory to upgrade to v2.0
+ - interrupts: Interrupt number.
+ - interrupts-parent: phandle for interrupt controller.
+ - reg: Base address and size of the IP core instance.
+ - xlnx,snd-pcm: reference to audio formatter block
+ - clock-names: List of input clocks.
+   Required elements for SDI Embed: "s_axi_aclk", "s_axis_clk", "sdi_embed_clk".
+   Required elements for SDI Extract: "s_axi_aclk", "sdi_extract_clk", "m_axis_clk".
+ - clocks: Input clock specifier. Refer to common clock bindings.
+
+SDI embed contains a output port to remote endpoint of SDI video Tx node.
+This pipeline should be described using the DT bindings defined in
+Documentation/devicetree/bindings/graph.txt
+
+Example:
+
+	audio_ss_0_v_uhdsdi_audio_extract_0: v_uhdsdi_audio@80080000 {
+		compatible = "xlnx,v-uhdsdi-audio-2.0";
+		clock-names = "s_axi_aclk", "sdi_extract_clk", "m_axis_clk";
+		clocks = <&misc_clk_0>, <&misc_clk_1>, <&misc_clk_0>;
+		interrupt-names = "interrupt";
+		interrupt-parent = <&gic>;
+		interrupts = <0 106 4>;
+		reg = <0x0 0x80080000 0x0 0x10000>;
+		xlnx,snd-pcm = <&audio_ss_0_audio_formatter_0>;
+	};
+
+	audio_ss_0_v_uhdsdi_audio_embed_0: v_uhdsdi_audio@80090000 {
+		compatible = "xlnx,v-uhdsdi-audio-2.0";
+		clock-names = "s_axi_aclk", "s_axis_clk", "sdi_embed_clk";
+		clocks = <&misc_clk_0>, <&misc_clk_0>, <&misc_clk_1>;
+		interrupt-names = "interrupt";
+		interrupt-parent = <&gic>;
+		interrupts = <0 107 4>;
+		reg = <0x0 0x80090000 0x0 0x10000>;
+		xlnx,snd-pcm = <&audio_ss_0_audio_formatter_0>;
+		sdi_av_port: port@0 {
+			reg = <0>;
+			sditx_audio_embed_src: endpoint {
+				remote-endpoint = <&sdi_audio_sink_port>;
+			};
+		};
+	};
+
+	Node 'v_smpte_uhdsdi_tx_ss' is documented in SDI Tx video bindings,
+	located at Documentation/devicetree/bindings/display/xlnx/xlnx,sdi-tx.txt.
+
+	Node 'audio_ss_0_audio_formatter_0' node is documented
+	at Documentation/devicetree/bindings/sound/xlnx,audio-formatter.txt
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/spi/spi-mxic.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/spi/spi-mxic.txt
@@ -8,11 +8,13 @@
 - reg: should contain 2 entries, one for the registers and one for the direct
        mapping area
 - reg-names: should contain "regs" and "dirmap"
-- interrupts: interrupt line connected to the SPI controller
 - clock-names: should contain "ps_clk", "send_clk" and "send_dly_clk"
 - clocks: should contain 3 entries for the "ps_clk", "send_clk" and
 	  "send_dly_clk" clocks
 
+Optional properties:
+- interrupts: interrupt line connected to the SPI controller
+
 Example:
 
 	spi@43c30000 {
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/spi/spi-xilinx.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/spi/spi-xilinx.txt
@@ -6,16 +6,27 @@
 - reg			: Physical base address and size of SPI registers map.
 - interrupts		: Property with a value describing the interrupt
 			  number.
+- fifo-size		: Depth of TX/RX Fifos
 
 Optional properties:
-- xlnx,num-ss-bits	: Number of chip selects used.
+- num-cs		: Number of chip selects used.
+- bits-per-word		: Number of bits per word.
+- clock-names		: Can be one or more strings from "axi_clk", "axi4_clk"
+			  and "spi_clk" depending on IP configurations.
+- clocks		: Input clock specifier. Refer to common clock bindings.
+- xlnx,startup-block	: Indicates whether startup block is enabled or disabled.
 
 Example:
 	axi_quad_spi@41e00000 {
 			compatible = "xlnx,xps-spi-2.00.a";
+			clock-names = "axi_clk", "axi4_clk", "spi_clk";
+			clocks = <&clkc 71>, <&clkc 72>, <&clkc 73>;
 			interrupt-parent = <&intc>;
 			interrupts = <0 31 1>;
 			reg = <0x41e00000 0x10000>;
-			xlnx,num-ss-bits = <0x1>;
+			num-cs = <0x1>;
+			fifo-size = <256>;
+			bits-per-word = <8>;
+			xlnx,startup-block;
 	};
 
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/spi/spi-zynqmp-qspi.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/spi/spi-zynqmp-qspi.txt
@@ -2,7 +2,8 @@
 -------------------------------------------------------------------
 
 Required properties:
-- compatible		: Should be "xlnx,zynqmp-qspi-1.0".
+- compatible		: Should be "xlnx,zynqmp-qspi-1.0" for zynqmp or
+			  "xlnx,versal-qspi-1.0" for versal.
 - reg			: Physical base address and size of GQSPI registers map.
 - interrupts		: Property with a value describing the interrupt
 			  number.
@@ -12,6 +13,14 @@
 
 Optional properties:
 - num-cs		: Number of chip selects used.
+- has-io-mode		: boolean property describes the controller operating
+			  mode. if exists controller will operate in IO mode
+			  else dma mode.
+- is-dual		: zynqmp qspi support for dual-parallel mode configuration
+			  value should be 1.
+- is-stacked		: zynqmp qspi support for stacked mode configuration.
+			  to enable this mode, is-dual should be 0 and is-stacked
+			  should be 1.
 
 Example:
 	qspi: spi@ff0f0000 {
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/usb/dwc3-xilinx.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/usb/dwc3-xilinx.txt
@@ -1,7 +1,8 @@
 Xilinx SuperSpeed DWC3 USB SoC controller
 
 Required properties:
-- compatible:	Should contain "xlnx,zynqmp-dwc3"
+- compatible:	May contain "xlnx,zynqmp-dwc3" or "xlnx,versal-dwc3"
+- reg:		Base address and length of the register control block
 - clocks:	A list of phandles for the clocks listed in clock-names
 - clock-names:	Should contain the following:
   "bus_clk"	 Master/Core clock, have to be >= 125 MHz for SS
@@ -13,20 +14,38 @@
 A child node must exist to represent the core DWC3 IP block. The name of
 the node is not important. The content of the node is defined in dwc3.txt.
 
+Optional properties for xlnx,zynqmp-dwc3:
+- nvmem-cells:       list of phandle to the nvmem data cells.
+- nvmem-cell-names:  Names for the each nvmem-cells specified.
+
+Optional properties for snps,dwc3:
+- dma-coherent:	Enable this flag if CCI is enabled in design. Adding this
+		flag configures Global SoC bus Configuration Register and
+		Xilinx USB 3.0 IP - USB coherency register to enable CCI.
+- snps,enable-hibernation: Add this flag to enable hibernation support for
+		peripheral mode
+- interrupt-names: This property provides the names of the interrupt ids used
+
 Example device node:
 
 		usb@0 {
 			#address-cells = <0x2>;
 			#size-cells = <0x1>;
 			compatible = "xlnx,zynqmp-dwc3";
+			reg = <0x0 0xff9d0000 0x0 0x100>;
 			clock-names = "bus_clk" "ref_clk";
 			clocks = <&clk125>, <&clk125>;
 			ranges;
+			nvmem-cells = <&soc_revision>;
+			nvmem-cell-names = "soc_revision";
 
 			dwc3@fe200000 {
 				compatible = "snps,dwc3";
 				reg = <0x0 0xfe200000 0x40000>;
+				interrupt-name = "dwc_usb3";
 				interrupts = <0x0 0x41 0x4>;
 				dr_mode = "host";
+				dma-coherent;
+				snps,enable-hibernation
 			};
 		};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/usb/dwc3.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/usb/dwc3.txt
@@ -75,6 +75,8 @@
 			from P0 to P1/P2/P3 without delay.
  - snps,dis-tx-ipgap-linecheck-quirk: when set, disable u2mac linestate check
 			during HS transmit.
+ - snps,parkmode-disable-ss-quirk: when set, all SuperSpeed bus instances in
+			park mode are disabled.
  - snps,dis_metastability_quirk: when set, disable metastability workaround.
 			CAUTION: use only if you are absolutely sure of it.
  - snps,is-utmi-l1-suspend: true when DWC3 asserts output signal
@@ -85,6 +87,19 @@
  - snps,quirk-frame-length-adjustment: Value for GFLADJ_30MHZ field of GFLADJ
 	register for post-silicon frame length adjustment when the
 	fladj_30mhz_sdbnd signal is invalid or incorrect.
+ - snps,refclk_fladj: Enable frame length adjustment for SOF/ITP counter.
+ - snps,enable_guctl1_resume_quirk: Adding this flag sets bit 10 of GUCTL1
+	thus enabling the workaround in HW to fix the issue where the controller
+	was not able to generate correct CRC checksum on the very first transfer
+	packet after sending resume signal.
+ - snps,enable_guctl1_ipd_quirk: Adding this flag sets bit 9 of GUCTL1
+	enabling the workaround in HW to reduce the Inter Packet Delay (IPD)
+	and making controller enumerate FS/LS devices connected behind VIA-LAB.
+ - snps,xhci-stream-quirk: Dwc3 host controller has a bug where it sometimes
+	fails to process the traansfer descriptors present in the BULK IN
+	stream ring. Since the controller is not processing any TD, no transfer
+	events will be triggered, resulting in a hang condition. Enabling this
+	flag in dts fixes the above said issue.
  - snps,rx-thr-num-pkt-prd: periodic ESS RX packet threshold count - host mode
 			only. Set this and rx-max-burst-prd to a valid,
 			non-zero value 1-16 (DWC_usb31 programming guide
@@ -108,6 +123,8 @@
 			When just one value, which means INCRX burst mode enabled. When
 			more than one value, which means undefined length INCR burst type
 			enabled. The values can be 1, 4, 8, 16, 32, 64, 128 and 256.
+ - snps,mask_phy_reset: enabling this quirk masks phy reset signal from reaching
+			the ULPI phy after initialization done of the phy.
 
  - in addition all properties from usb-xhci.txt from the current directory are
    supported as well
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/usb/ehci-xilinx.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/usb/ehci-xilinx.txt
@@ -0,0 +1,21 @@
+Xilinx USB EHCI controller
+
+Required properties:
+- compatible: must be "xlnx,xps-usb-host-1.00.a"
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- interrupts: The EHCI interrupt
+
+Optional properties:
+- xlnx,ext-vbus-valid: Use external VBUS
+- xlnx,support-usb-fs: Support for Full Speed USB
+- xlnx,use-phy-bus-pwr: Use phy bus power in USB
+
+Example:
+
+	xps_usb_host_0: usb@82400000 {
+		compatible = "xlnx,xps-usb-host-1.00.a";
+		interrupt-parent = <&xps_intc_0>;
+		interrupts = < 0 2 >;
+		reg = < 0x82400000 0x200 >;
+	} ;
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/usb/microchip,usb5744.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/usb/microchip,usb5744.yaml
@@ -0,0 +1,56 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/usb/microchip,usb5744.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: Bindings for the Microchip USB5744 4-port Hub Controller
+
+description:
+  Microchip’s USB5744 SmartHub™ IC is a 4 port, SuperSpeed (SS)/Hi-Speed (HS),
+  low power, low pin count configurable and fully compliant with the USB 3.1
+  Gen 1 specification. The USB5744 also supports Full Speed (FS) and Low Speed
+  (LS) USB signaling, offering complete coverage of all defined USB operating
+  speeds. The new SuperSpeed hubs operate in parallel with the USB 2.0
+  controller, so 5 Gbps SuperSpeed data transfers are not affected by slower
+  USB 2.0 traffic.
+
+maintainers:
+  - Piyush Mehta <piyush.mehta@xilinx.com>
+  - Michal Simek <michal.simek@xilinx.com>
+
+properties:
+  compatible:
+    const: microchip,usb5744
+
+  reg:
+    maxItems: 1
+    description: |
+      Specifies the i2c slave address, it is required and should be 0x2d
+      if I2C is used.
+
+  reset-gpios:
+    maxItems: 1
+    description:
+      The phandle and specifier for the GPIO that controls the RESET line of
+      USB hub.
+
+required:
+  - compatible
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        usb5744@2d {
+            compatible = "microchip,usb5744";
+            reg = <0x2d>;
+            reset-gpios = <&gpio 44 GPIO_ACTIVE_HIGH>;
+        };
+    };
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/usb/udc-xilinx.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/usb/udc-xilinx.txt
@@ -6,13 +6,16 @@
 			  device registers map.
 - interrupts		: Should contain single irq line of USB2 device
 			  controller
-- xlnx,has-builtin-dma	: if DMA is included
+- xlnx,has-builtin-dma	: If DMA is included
 
-Example:
- 		axi-usb2-device@42e00000 {
-                        compatible = "xlnx,usb2-device-4.00.a";
-                        interrupts = <0x0 0x39 0x1>;
-                        reg = <0x42e00000 0x10000>;
-                        xlnx,has-builtin-dma;
-                };
+Optional properties:
+- clock-names		: Should be  "s_axi_aclk"
+- clocks		: Input clock specifier. Refer to common clock bindings.
 
+Example:
+		axi-usb2-device@42e00000 {
+			compatible = "xlnx,usb2-device-4.00.a";
+			interrupts = <0x0 0x39 0x1>;
+			reg = <0x42e00000 0x10000>;
+			xlnx,has-builtin-dma;
+		};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -633,6 +633,8 @@
     description: National Semiconductor
   "^nec,.*":
     description: NEC LCD Technologies, Ltd.
+  "^neofidelity,.*":
+    description: Neofidelity Inc.
   "^neonode,.*":
     description: Neonode Inc.
   "^netgear,.*":
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/video/xilinx-fb.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/video/xilinx-fb.txt
@@ -0,0 +1,35 @@
+Xilinx Axi TFT controller Device Tree Bindings
+---------------------------------------------------------
+
+Required properties:
+- compatible		: Can be any of the following
+			  "xlnx,xps-tft-1.00.a","xlnx,xps-tft-2.00.a",
+			  "xlnx,xps-tft-2.01.a","xlnx,plb-tft-cntlr-ref-1.00.a",
+			  "xlnx,plb-dvi-cntlr-ref-1.00.c"
+- reg			: Physical base address and size of the Axi Tft
+			  registers map
+- interrupts		: Property with a value describing the interrupt
+			  number
+- interrupt-parent	: Must be core interrupt controller
+- xlnx,dcr-splb-slave-if :	Accessing TFT Controller through Bus or DCR interface.
+				for BUS its value is 1 and for DCR it is 0.
+				default is BUS i.e. 1
+- resolution :	<xres yres> pixel resolution of framebuffer.Some
+		implementations use a different resolution
+- virtual-resolution :	<xvirt yvirt> Size of framebuffer in memory.
+- rotate-display :	(empty) rotate display 180 degrees
+- phys-size :	<screen_width_mm screen_height_mm> width and heigth of
+		screen
+
+Example:
+axi_tft_0: axi_tft@44a00000 {
+	compatible = "xlnx,xps-tft-1.00.a";
+	interrupt-parent = <&axi_intc>;
+	interrupts = <1 0>;
+	reg = <0x44a00000 0x10000>;
+	xlnx,dcr-splb-slave-if = <0x1>;
+	resolution = <640 480>;
+	virtual-resolution = <1024 480>;
+	phys-size = <1024 512>;
+	rotate-display;
+};
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/watchdog/of-xilinx-wdt.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/watchdog/of-xilinx-wdt.txt
@@ -1,21 +1,37 @@
-Xilinx AXI/PLB soft-core watchdog Device Tree Bindings
----------------------------------------------------------
+Xilinx AXI/PLB soft-core watchdog and window watchdog Device Tree Bindings
+--------------------------------------------------------------------------
 
 Required properties:
 - compatible		: Should be "xlnx,xps-timebase-wdt-1.00.a" or
-			  "xlnx,xps-timebase-wdt-1.01.a".
+			  "xlnx,xps-timebase-wdt-1.01.a" or
+			  "xlnx,versal-wwdt-1.0".
 - reg			: Physical base address and size
 
 Optional properties:
 - clocks		: Input clock specifier. Refer to common clock
 			  bindings.
 - clock-frequency	: Frequency of clock in Hz
+
+Optional properties for AXI/PLB soft-core watchdog:
 - xlnx,wdt-enable-once	: 0 - Watchdog can be restarted
 			  1 - Watchdog can be enabled just once
 - xlnx,wdt-interval	: Watchdog timeout interval in 2^<val> clock cycles,
 			  <val> is integer from 8 to 31.
 
+Optional properties for window watchdog:
+- timeout-sec          : Watchdog timeout value (in seconds).
+			 if unset, the default timeout is 10 seconds.
+- pretimeout-sec	: Watchdog pretimeout value in seconds.
+- interrupts		: IRQ line for the WWDT.
+- interrupt-names	: Interrupt line names "wdt" or "wwdt_reset_pending".
+			  wdt - will assert high after first (closed) window
+			  timer expires. wwdt_reset_pending - will assert high
+			  after second (open) window timer expires if WRP
+			  (Watchdog Reset pending) is configured with third
+			  (SST) timer.
+
 Example:
+Xilinx AXI/PLB soft-core watchdog:
 axi-timebase-wdt@40100000 {
 	clock-frequency = <50000000>;
 	compatible = "xlnx,xps-timebase-wdt-1.00.a";
@@ -24,3 +40,14 @@
 	xlnx,wdt-enable-once = <0x0>;
 	xlnx,wdt-interval = <0x1b>;
 } ;
+
+Xilinx Versal window watchdog:
+watchdog@fd4d0000 {
+	compatible = "xlnx,versal-wwdt-1.0";
+	reg = <0x0 0xfd4d0000 0x0 0x10000>;
+	clocks = <&clk25>;
+	timeout-sec = <10>;
+	interrupt-names = "wdt", "wwdt_reset_pending";
+	interrupts = <0x0 0x64 0x1>, <0x0 0x6D 0x1>;
+	pretimeout-sec = <5>;
+} ;
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/xilinx.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/xilinx.txt
@@ -253,6 +253,7 @@
 
       Optional properties:
        - 8-bit (empty) : Set this property for SystemACE in 8 bit mode
+       - port-number = <port_number> : Set port number for particular device
 
       iii) Xilinx EMAC and Xilinx TEMAC
 
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/xlnx,ctrl-fb.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/xlnx,ctrl-fb.txt
@@ -0,0 +1,22 @@
+The Xilinx framebuffer DMA engine supports two soft IP blocks: one IP
+block is used for reading video frame data from memory (FB Read) to the device
+and the other IP block is used for writing video frame data from the device
+to memory (FB Write).  Both the FB Read/Write IP blocks are aware of the
+format of the data being written to or read from memory including RGB and
+YUV in packed, planar, and semi-planar formats.  Because the FB Read/Write
+is format aware, only one buffer pointer is needed by the IP blocks even
+when planar or semi-planar format are used.
+
+Required properties:
+ - compatible: Should be "xlnx,ctrl-fbwr-1.0" for framebuffer Write OR
+	       "xlnx,ctrl-fbrd-1.0" for framebuffer Read.
+ - reg: Base address and size of the IP core.
+ - reset-gpios: gpio to reset the framebuffer IP
+
+Example:
+
+        fbwr@0xa0000000 {
+                compatible = "xlnx,ctrl-fbwr-1.0";
+                reg = <0x0 0xa0000000 0x0 0x10000>;
+                reset-gpios = <&gpio 82 1>;
+        };
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/bindings/xlnx,ctrl-vpss.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/bindings/xlnx,ctrl-vpss.txt
@@ -0,0 +1,21 @@
+The Xilinx VPSS Scaler is a Video IP that supports up scaling, down scaling and
+no scaling functionailty along with color space conversion. This supports custom
+resolution values between 0 to 4096.
+
+Required properties:
+
+- compatible: Must be "xlnx,ctrl-xvpss-1.0".
+- reg: Base address and size of the IP core.
+- reset-gpios: gpio to reset the framebuffer IP
+- xlnx,vpss-taps: number of taps
+- xlnx,vpss-ppc: pixels per clock
+
+Example:
+
+        ctrlvpss: vpss@0xa0200000 {
+                compatible = "xlnx,ctrl-xvpss-1.0";
+                reg = <0x0 0xa0200000 0x0 0x30000>;
+                reset-gpios = <&gpio 80 1>;
+                xlnx,vpss-taps = <6>;
+                xlnx,vpss-ppc = <2>;
+        };
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/configfs-overlays.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/configfs-overlays.txt
@@ -0,0 +1,31 @@
+Howto use the configfs overlay interface.
+
+A device-tree configfs entry is created in /config/device-tree/overlays
+and and it is manipulated using standard file system I/O.
+Note that this is a debug level interface, for use by developers and
+not necessarily something accessed by normal users due to the
+security implications of having direct access to the kernel's device tree.
+
+* To create an overlay you mkdir the directory:
+
+	# mkdir /config/device-tree/overlays/foo
+
+* Either you echo the overlay firmware file to the path property file.
+
+	# echo foo.dtbo >/config/device-tree/overlays/foo/path
+
+* Or you cat the contents of the overlay to the dtbo file
+
+	# cat foo.dtbo >/config/device-tree/overlays/foo/dtbo
+
+The overlay file will be applied, and devices will be created/destroyed
+as required.
+
+To remove it simply rmdir the directory.
+
+	# rmdir /config/device-tree/overlays/foo
+
+The rationalle of the dual interface (firmware & direct copy) is that each is
+better suited to different use patterns. The firmware interface is what's
+intended to be used by hardware managers in the kernel, while the copy interface
+make sense for developers (since it avoids problems with namespaces).
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/devicetree/writing-schema.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/devicetree/writing-schema.rst
@@ -130,11 +130,13 @@
 
     make dt_binding_check
 
-In order to perform validation of DT source files, use the `dtbs_check` target::
+In order to perform validation of DT source files, use the ``dtbs_check`` target::
 
     make dtbs_check
 
-This will first run the `dt_binding_check` which generates the processed schema.
+Note that ``dtbs_check`` will skip any binding schema files with errors. It is
+necessary to use ``dt_binding_check`` to get all the validation errors in the
+binding schema files.
 
 It is also possible to run checks with a single schema file by setting the
 ``DT_SCHEMA_FILES`` variable to a specific schema file.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/driver-api/dmaengine/dmatest.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/driver-api/dmaengine/dmatest.rst
@@ -143,13 +143,14 @@
 Allocating Channels
 -------------------
 
-Channels are required to be configured prior to starting the test run.
-Attempting to run the test without configuring the channels will fail.
+Channels do not need to be configured prior to starting a test run. Attempting
+to run the test without configuring the channels will result in testing any
+channels that are available.
 
 Example::
 
     % echo 1 > /sys/module/dmatest/parameters/run
-    dmatest: Could not start test, no channels configured
+    dmatest: No channels configured, continue with any
 
 Channels are registered using the "channel" parameter. Channels can be requested by their
 name, once requested, the channel is registered and a pending thread is added to the test list.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/driver-api/firewire.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/driver-api/firewire.rst
@@ -19,7 +19,7 @@
 Firewire char device data structures
 ====================================
 
-.. include:: /ABI/stable/firewire-cdev
+.. include:: ../ABI/stable/firewire-cdev
     :literal:
 
 .. kernel-doc:: include/uapi/linux/firewire-cdev.h
@@ -28,7 +28,7 @@
 Firewire device probing and sysfs interfaces
 ============================================
 
-.. include:: /ABI/stable/sysfs-bus-firewire
+.. include:: ../ABI/stable/sysfs-bus-firewire
     :literal:
 
 .. kernel-doc:: drivers/firewire/core-device.c
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/driver-api/libata.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/driver-api/libata.rst
@@ -250,7 +250,7 @@
 
 ::
 
-    void (*qc_prep) (struct ata_queued_cmd *qc);
+    enum ata_completion_errors (*qc_prep) (struct ata_queued_cmd *qc);
     int (*qc_issue) (struct ata_queued_cmd *qc);
 
 
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/driver-api/spi.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/driver-api/spi.rst
@@ -25,8 +25,8 @@
 a pair of FIFOs connected to dual DMA engines on the other side of the
 SPI shift register (maximizing throughput). Such drivers bridge between
 whatever bus they sit on (often the platform bus) and SPI, and expose
-the SPI side of their device as a :c:type:`struct spi_master
-<spi_master>`. SPI devices are children of that master,
+the SPI side of their device as a :c:type:`struct spi_controller
+<spi_controller>`. SPI devices are children of that master,
 represented as a :c:type:`struct spi_device <spi_device>` and
 manufactured from :c:type:`struct spi_board_info
 <spi_board_info>` descriptors which are usually provided by
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/fault-injection/fault-injection.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/fault-injection/fault-injection.rst
@@ -74,8 +74,8 @@
 
 - /sys/kernel/debug/fail*/times:
 
-	specifies how many times failures may happen at most.
-	A value of -1 means "no limit".
+	specifies how many times failures may happen at most. A value of -1
+	means "no limit".
 
 - /sys/kernel/debug/fail*/space:
 
@@ -163,11 +163,13 @@
 	- ERRNO: retval must be -1 to -MAX_ERRNO (-4096).
 	- ERR_NULL: retval must be 0 or -1 to -MAX_ERRNO (-4096).
 
-- /sys/kernel/debug/fail_function/<functiuon-name>/retval:
+- /sys/kernel/debug/fail_function/<function-name>/retval:
 
-	specifies the "error" return value to inject to the given
-	function for given function. This will be created when
-	user specifies new injection entry.
+	specifies the "error" return value to inject to the given function.
+	This will be created when the user specifies a new injection entry.
+	Note that this file only accepts unsigned values. So, if you want to
+	use a negative errno, you better use 'printf' instead of 'echo', e.g.:
+	$ printf %#x -12 > retval
 
 Boot option
 ^^^^^^^^^^^
@@ -331,7 +333,7 @@
     FAILTYPE=fail_function
     FAILFUNC=open_ctree
     echo $FAILFUNC > /sys/kernel/debug/$FAILTYPE/inject
-    echo -12 > /sys/kernel/debug/$FAILTYPE/$FAILFUNC/retval
+    printf %#x -12 > /sys/kernel/debug/$FAILTYPE/$FAILFUNC/retval
     echo N > /sys/kernel/debug/$FAILTYPE/task-filter
     echo 100 > /sys/kernel/debug/$FAILTYPE/probability
     echo 0 > /sys/kernel/debug/$FAILTYPE/interval
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/fb/fbcon.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/fb/fbcon.rst
@@ -127,7 +127,7 @@
 	is typically located on the same video card.  Thus, the consoles that
 	are controlled by the VGA console will be garbled.
 
-4. fbcon=rotate:<n>
+5. fbcon=rotate:<n>
 
 	This option changes the orientation angle of the console display. The
 	value 'n' accepts the following:
@@ -152,21 +152,21 @@
 	Actually, the underlying fb driver is totally ignorant of console
 	rotation.
 
-5. fbcon=margin:<color>
+6. fbcon=margin:<color>
 
 	This option specifies the color of the margins. The margins are the
 	leftover area at the right and the bottom of the screen that are not
 	used by text. By default, this area will be black. The 'color' value
 	is an integer number that depends on the framebuffer driver being used.
 
-6. fbcon=nodefer
+7. fbcon=nodefer
 
 	If the kernel is compiled with deferred fbcon takeover support, normally
 	the framebuffer contents, left in place by the firmware/bootloader, will
 	be preserved until there actually is some text is output to the console.
 	This option causes fbcon to bind immediately to the fbdev device.
 
-7. fbcon=logo-pos:<location>
+8. fbcon=logo-pos:<location>
 
 	The only possible 'location' is 'center' (without quotes), and when
 	given, the bootup logo is moved from the default top-left corner
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt
@@ -24,7 +24,7 @@
     |      parisc: |  ok  |
     |     powerpc: |  ok  |
     |       riscv: | TODO |
-    |        s390: | TODO |
+    |        s390: |  ok  |
     |          sh: | TODO |
     |       sparc: | TODO |
     |          um: | TODO |
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/filesystems/affs.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/filesystems/affs.txt
@@ -93,13 +93,15 @@
 
   - R maps to r for user, group and others. On directories, R implies x.
 
-  - If both W and D are allowed, w will be set.
+  - W maps to w.
 
   - E maps to x.
 
-  - H and P are always retained and ignored under Linux.
+  - D is ignored.
 
-  - A is always reset when a file is written to.
+  - H, S and P are always retained and ignored under Linux.
+
+  - A is cleared when a file is written to.
 
 User id and group id will be used unless set[gu]id are given as mount
 options. Since most of the Amiga file systems are single user systems
@@ -111,11 +113,13 @@
 
 The Linux rwxrwxrwx file mode is handled as follows:
 
-  - r permission will set R for user, group and others.
+  - r permission will allow R for user, group and others.
+
+  - w permission will allow W for user, group and others.
 
-  - w permission will set W and D for user, group and others.
+  - x permission of the user will allow E for plain files.
 
-  - x permission of the user will set E for plain files.
+  - D will be allowed for user, group and others.
 
   - All other flags (suid, sgid, ...) are ignored and will
     not be retained.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/filesystems/aufs/README
+++ linux-xilinx-zynqmp-5.4.0/Documentation/filesystems/aufs/README
@@ -0,0 +1,401 @@
+
+Aufs5 -- advanced multi layered unification filesystem version 5.x
+http://aufs.sf.net
+Junjiro R. Okajima
+
+
+0. Introduction
+----------------------------------------
+In the early days, aufs was entirely re-designed and re-implemented
+Unionfs Version 1.x series. Adding many original ideas, approaches,
+improvements and implementations, it became totally different from
+Unionfs while keeping the basic features.
+Later, Unionfs Version 2.x series began taking some of the same
+approaches to aufs1's.
+Unionfs was being developed by Professor Erez Zadok at Stony Brook
+University and his team.
+
+Aufs5 supports linux-v5.0 and later, If you want older kernel version
+support,
+- for linux-v4.x series, try aufs4-linux.git or aufs4-standalone.git
+- for linux-v3.x series, try aufs3-linux.git or aufs3-standalone.git
+- for linux-v2.6.16 and later, try aufs2-2.6.git, aufs2-standalone.git
+  or aufs1 from CVS on SourceForge.
+
+Note: it becomes clear that "Aufs was rejected. Let's give it up."
+      According to Christoph Hellwig, linux rejects all union-type
+      filesystems but UnionMount.
+<http://marc.info/?l=linux-kernel&m=123938533724484&w=2>
+
+PS. Al Viro seems have a plan to merge aufs as well as overlayfs and
+    UnionMount, and he pointed out an issue around a directory mutex
+    lock and aufs addressed it. But it is still unsure whether aufs will
+    be merged (or any other union solution).
+<http://marc.info/?l=linux-kernel&m=136312705029295&w=1>
+
+
+1. Features
+----------------------------------------
+- unite several directories into a single virtual filesystem. The member
+  directory is called as a branch.
+- you can specify the permission flags to the branch, which are 'readonly',
+  'readwrite' and 'whiteout-able.'
+- by upper writable branch, internal copyup and whiteout, files/dirs on
+  readonly branch are modifiable logically.
+- dynamic branch manipulation, add, del.
+- etc...
+
+Also there are many enhancements in aufs, such as:
+- test only the highest one for the directory permission (dirperm1)
+- copyup on open (coo=)
+- 'move' policy for copy-up between two writable branches, after
+  checking free space.
+- xattr, acl
+- readdir(3) in userspace.
+- keep inode number by external inode number table
+- keep the timestamps of file/dir in internal copyup operation
+- seekable directory, supporting NFS readdir.
+- whiteout is hardlinked in order to reduce the consumption of inodes
+  on branch
+- do not copyup, nor create a whiteout when it is unnecessary
+- revert a single systemcall when an error occurs in aufs
+- remount interface instead of ioctl
+- maintain /etc/mtab by an external command, /sbin/mount.aufs.
+- loopback mounted filesystem as a branch
+- kernel thread for removing the dir who has a plenty of whiteouts
+- support copyup sparse file (a file which has a 'hole' in it)
+- default permission flags for branches
+- selectable permission flags for ro branch, whether whiteout can
+  exist or not
+- export via NFS.
+- support <sysfs>/fs/aufs and <debugfs>/aufs.
+- support multiple writable branches, some policies to select one
+  among multiple writable branches.
+- a new semantics for link(2) and rename(2) to support multiple
+  writable branches.
+- no glibc changes are required.
+- pseudo hardlink (hardlink over branches)
+- allow a direct access manually to a file on branch, e.g. bypassing aufs.
+  including NFS or remote filesystem branch.
+- userspace wrapper for pathconf(3)/fpathconf(3) with _PC_LINK_MAX.
+- and more...
+
+Currently these features are dropped temporary from aufs5.
+See design/08plan.txt in detail.
+- nested mount, i.e. aufs as readonly no-whiteout branch of another aufs
+  (robr)
+- statistics of aufs thread (/sys/fs/aufs/stat)
+
+Features or just an idea in the future (see also design/*.txt),
+- reorder the branch index without del/re-add.
+- permanent xino files for NFSD
+- an option for refreshing the opened files after add/del branches
+- light version, without branch manipulation. (unnecessary?)
+- copyup in userspace
+- inotify in userspace
+- readv/writev
+
+
+2. Download
+----------------------------------------
+There are three GIT trees for aufs5, aufs5-linux.git,
+aufs5-standalone.git, and aufs-util.git. Note that there is no "5" in
+"aufs-util.git."
+While the aufs-util is always necessary, you need either of aufs5-linux
+or aufs5-standalone.
+
+The aufs5-linux tree includes the whole linux mainline GIT tree,
+git://git.kernel.org/.../torvalds/linux.git.
+And you cannot select CONFIG_AUFS_FS=m for this version, eg. you cannot
+build aufs5 as an external kernel module.
+Several extra patches are not included in this tree. Only
+aufs5-standalone tree contains them. They are described in the later
+section "Configuration and Compilation."
+
+On the other hand, the aufs5-standalone tree has only aufs source files
+and necessary patches, and you can select CONFIG_AUFS_FS=m.
+But you need to apply all aufs patches manually.
+
+You will find GIT branches whose name is in form of "aufs5.x" where "x"
+represents the linux kernel version, "linux-5.x". For instance,
+"aufs5.0" is for linux-5.0. For latest "linux-5.x-rcN", use
+"aufs5.x-rcN" branch.
+
+o aufs5-linux tree
+$ git clone --reference /your/linux/git/tree \
+	git://github.com/sfjro/aufs5-linux.git aufs5-linux.git
+- if you don't have linux GIT tree, then remove "--reference ..."
+$ cd aufs5-linux.git
+$ git checkout origin/aufs5.0
+
+Or You may want to directly git-pull aufs into your linux GIT tree, and
+leave the patch-work to GIT.
+$ cd /your/linux/git/tree
+$ git remote add aufs5 git://github.com/sfjro/aufs5-linux.git
+$ git fetch aufs5
+$ git checkout -b my5.0 v5.0
+$ (add your local change...)
+$ git pull aufs5 aufs5.0
+- now you have v5.0 + your_changes + aufs5.0 in you my5.0 branch.
+- you may need to solve some conflicts between your_changes and
+  aufs5.0. in this case, git-rerere is recommended so that you can
+  solve the similar conflicts automatically when you upgrade to 5.1 or
+  later in the future.
+
+o aufs5-standalone tree
+$ git clone git://github.com/sfjro/aufs5-standalone.git aufs5-standalone.git
+$ cd aufs5-standalone.git
+$ git checkout origin/aufs5.0
+
+o aufs-util tree
+$ git clone git://git.code.sf.net/p/aufs/aufs-util aufs-util.git
+- note that the public aufs-util.git is on SourceForge instead of
+  GitHUB.
+$ cd aufs-util.git
+$ git checkout origin/aufs5.0
+
+Note: The 5.x-rcN branch is to be used with `rc' kernel versions ONLY.
+The minor version number, 'x' in '5.x', of aufs may not always
+follow the minor version number of the kernel.
+Because changes in the kernel that cause the use of a new
+minor version number do not always require changes to aufs-util.
+
+Since aufs-util has its own minor version number, you may not be
+able to find a GIT branch in aufs-util for your kernel's
+exact minor version number.
+In this case, you should git-checkout the branch for the
+nearest lower number.
+
+For (an unreleased) example:
+If you are using "linux-5.10" and the "aufs5.10" branch
+does not exist in aufs-util repository, then "aufs5.9", "aufs5.8"
+or something numerically smaller is the branch for your kernel.
+
+Also you can view all branches by
+	$ git branch -a
+
+
+3. Configuration and Compilation
+----------------------------------------
+Make sure you have git-checkout'ed the correct branch.
+
+For aufs5-linux tree,
+- enable CONFIG_AUFS_FS.
+- set other aufs configurations if necessary.
+
+For aufs5-standalone tree,
+There are several ways to build.
+
+1.
+- apply ./aufs5-kbuild.patch to your kernel source files.
+- apply ./aufs5-base.patch too.
+- apply ./aufs5-mmap.patch too.
+- apply ./aufs5-standalone.patch too, if you have a plan to set
+  CONFIG_AUFS_FS=m. otherwise you don't need ./aufs5-standalone.patch.
+- copy ./{Documentation,fs,include/uapi/linux/aufs_type.h} files to your
+  kernel source tree. Never copy $PWD/include/uapi/linux/Kbuild.
+- enable CONFIG_AUFS_FS, you can select either
+  =m or =y.
+- and build your kernel as usual.
+- install the built kernel.
+- install the header files too by "make headers_install" to the
+  directory where you specify. By default, it is $PWD/usr.
+  "make help" shows a brief note for headers_install.
+- and reboot your system.
+
+2.
+- module only (CONFIG_AUFS_FS=m).
+- apply ./aufs5-base.patch to your kernel source files.
+- apply ./aufs5-mmap.patch too.
+- apply ./aufs5-standalone.patch too.
+- build your kernel, don't forget "make headers_install", and reboot.
+- edit ./config.mk and set other aufs configurations if necessary.
+  Note: You should read $PWD/fs/aufs/Kconfig carefully which describes
+  every aufs configurations.
+- build the module by simple "make".
+- you can specify ${KDIR} make variable which points to your kernel
+  source tree.
+- install the files
+  + run "make install" to install the aufs module, or copy the built
+    $PWD/aufs.ko to /lib/modules/... and run depmod -a (or reboot simply).
+  + run "make install_headers" (instead of headers_install) to install
+    the modified aufs header file (you can specify DESTDIR which is
+    available in aufs standalone version's Makefile only), or copy
+    $PWD/usr/include/linux/aufs_type.h to /usr/include/linux or wherever
+    you like manually. By default, the target directory is $PWD/usr.
+- no need to apply aufs5-kbuild.patch, nor copying source files to your
+  kernel source tree.
+
+Note: The header file aufs_type.h is necessary to build aufs-util
+      as well as "make headers_install" in the kernel source tree.
+      headers_install is subject to be forgotten, but it is essentially
+      necessary, not only for building aufs-util.
+      You may not meet problems without headers_install in some older
+      version though.
+
+And then,
+- read README in aufs-util, build and install it
+- note that your distribution may contain an obsoleted version of
+  aufs_type.h in /usr/include/linux or something. When you build aufs
+  utilities, make sure that your compiler refers the correct aufs header
+  file which is built by "make headers_install."
+- if you want to use readdir(3) in userspace or pathconf(3) wrapper,
+  then run "make install_ulib" too. And refer to the aufs manual in
+  detail.
+
+There several other patches in aufs5-standalone.git. They are all
+optional. When you meet some problems, they will help you.
+- aufs5-loopback.patch
+  Supports a nested loopback mount in a branch-fs. This patch is
+  unnecessary until aufs produces a message like "you may want to try
+  another patch for loopback file".
+- proc_mounts.patch
+  When there are many mountpoints and many mount(2)/umount(2) are
+  running, then /proc/mounts may not show the all mountpoints.  This
+  patch makes /proc/mounts always show the full mountpoints list.
+  If you don't want to apply this patch and meet such problem, then you
+  need to increase the value of 'ProcMounts_Times' make-variable in
+  aufs-util.git as a second best solution.
+- vfs-ino.patch
+  Modifies a system global kernel internal function get_next_ino() in
+  order to stop assigning 0 for an inode-number. Not directly related to
+  aufs, but recommended generally.
+- tmpfs-idr.patch
+  Keeps the tmpfs inode number as the lowest value. Effective to reduce
+  the size of aufs XINO files for tmpfs branch. Also it prevents the
+  duplication of inode number, which is important for backup tools and
+  other utilities. When you find aufs XINO files for tmpfs branch
+  growing too much, try this patch.
+- lockdep-debug.patch
+  Because aufs is not only an ordinary filesystem (callee of VFS), but
+  also a caller of VFS functions for branch filesystems, subclassing of
+  the internal locks for LOCKDEP is necessary. LOCKDEP is a debugging
+  feature of linux kernel. If you enable CONFIG_LOCKDEP, then you will
+  need to apply this debug patch to expand several constant values.
+  If you don't know what LOCKDEP is, then you don't have apply this
+  patch.
+
+
+4. Usage
+----------------------------------------
+At first, make sure aufs-util are installed, and please read the aufs
+manual, aufs.5 in aufs-util.git tree.
+$ man -l aufs.5
+
+And then,
+$ mkdir /tmp/rw /tmp/aufs
+# mount -t aufs -o br=/tmp/rw:${HOME} none /tmp/aufs
+
+Here is another example. The result is equivalent.
+# mount -t aufs -o br=/tmp/rw=rw:${HOME}=ro none /tmp/aufs
+  Or
+# mount -t aufs -o br:/tmp/rw none /tmp/aufs
+# mount -o remount,append:${HOME} /tmp/aufs
+
+Then, you can see whole tree of your home dir through /tmp/aufs. If
+you modify a file under /tmp/aufs, the one on your home directory is
+not affected, instead the same named file will be newly created under
+/tmp/rw. And all of your modification to a file will be applied to
+the one under /tmp/rw. This is called the file based Copy on Write
+(COW) method.
+Aufs mount options are described in aufs.5.
+If you run chroot or something and make your aufs as a root directory,
+then you need to customize the shutdown script. See the aufs manual in
+detail.
+
+Additionally, there are some sample usages of aufs which are a
+diskless system with network booting, and LiveCD over NFS.
+See sample dir in CVS tree on SourceForge.
+
+
+5. Contact
+----------------------------------------
+When you have any problems or strange behaviour in aufs, please let me
+know with:
+- /proc/mounts (instead of the output of mount(8))
+- /sys/module/aufs/*
+- /sys/fs/aufs/* (if you have them)
+- /debug/aufs/* (if you have them)
+- linux kernel version
+  if your kernel is not plain, for example modified by distributor,
+  the url where i can download its source is necessary too.
+- aufs version which was printed at loading the module or booting the
+  system, instead of the date you downloaded.
+- configuration (define/undefine CONFIG_AUFS_xxx)
+- kernel configuration or /proc/config.gz (if you have it)
+- LSM (linux security module, if you are using)
+- behaviour which you think to be incorrect
+- actual operation, reproducible one is better
+- mailto: aufs-users at lists.sourceforge.net
+
+Usually, I don't watch the Public Areas(Bugs, Support Requests, Patches,
+and Feature Requests) on SourceForge. Please join and write to
+aufs-users ML.
+
+
+6. Acknowledgements
+----------------------------------------
+Thanks to everyone who have tried and are using aufs, whoever
+have reported a bug or any feedback.
+
+Especially donators:
+Tomas Matejicek(slax.org) made a donation (much more than once).
+	Since Apr 2010, Tomas M (the author of Slax and Linux Live
+	scripts) is making "doubling" donations.
+	Unfortunately I cannot list all of the donators, but I really
+	appreciate.
+	It ends Aug 2010, but the ordinary donation URL is still available.
+	<http://sourceforge.net/donate/index.php?group_id=167503>
+Dai Itasaka made a donation (2007/8).
+Chuck Smith made a donation (2008/4, 10 and 12).
+Henk Schoneveld made a donation (2008/9).
+Chih-Wei Huang, ASUS, CTC donated Eee PC 4G (2008/10).
+Francois Dupoux made a donation (2008/11).
+Bruno Cesar Ribas and Luis Carlos Erpen de Bona, C3SL serves public
+	aufs2 GIT tree (2009/2).
+William Grant made a donation (2009/3).
+Patrick Lane made a donation (2009/4).
+The Mail Archive (mail-archive.com) made donations (2009/5).
+Nippy Networks (Ed Wildgoose) made a donation (2009/7).
+New Dream Network, LLC (www.dreamhost.com) made a donation (2009/11).
+Pavel Pronskiy made a donation (2011/2).
+Iridium and Inmarsat satellite phone retailer (www.mailasail.com), Nippy
+	Networks (Ed Wildgoose) made a donation for hardware (2011/3).
+Max Lekomcev (DOM-TV project) made a donation (2011/7, 12, 2012/3, 6 and
+11).
+Sam Liddicott made a donation (2011/9).
+Era Scarecrow made a donation (2013/4).
+Bor Ratajc made a donation (2013/4).
+Alessandro Gorreta made a donation (2013/4).
+POIRETTE Marc made a donation (2013/4).
+Alessandro Gorreta made a donation (2013/4).
+lauri kasvandik made a donation (2013/5).
+"pemasu from Finland" made a donation (2013/7).
+The Parted Magic Project made a donation (2013/9 and 11).
+Pavel Barta made a donation (2013/10).
+Nikolay Pertsev made a donation (2014/5).
+James B made a donation (2014/7 and 2015/7).
+Stefano Di Biase made a donation (2014/8).
+Daniel Epellei made a donation (2015/1).
+OmegaPhil made a donation (2016/1, 2018/4).
+Tomasz Szewczyk made a donation (2016/4).
+James Burry made a donation (2016/12).
+Carsten Rose made a donation (2018/9).
+Porteus Kiosk made a donation (2018/10).
+
+Thank you very much.
+Donations are always, including future donations, very important and
+helpful for me to keep on developing aufs.
+
+
+7.
+----------------------------------------
+If you are an experienced user, no explanation is needed. Aufs is
+just a linux filesystem.
+
+
+Enjoy!
+
+# Local variables: ;
+# mode: text;
+# End: ;
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/filesystems/aufs/design/01intro.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/filesystems/aufs/design/01intro.txt
@@ -0,0 +1,171 @@
+
+# Copyright (C) 2005-2020 Junjiro R. Okajima
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Introduction
+----------------------------------------
+
+aufs [ei ju: ef es] | /ey-yoo-ef-es/ | [a u f s]
+1. abbrev. for "advanced multi-layered unification filesystem".
+2. abbrev. for "another unionfs".
+3. abbrev. for "auf das" in German which means "on the" in English.
+   Ex. "Butter aufs Brot"(G) means "butter onto bread"(E).
+   But "Filesystem aufs Filesystem" is hard to understand.
+4. abbrev. for "African Urban Fashion Show".
+
+AUFS is a filesystem with features:
+- multi layered stackable unification filesystem, the member directory
+  is called as a branch.
+- branch permission and attribute, 'readonly', 'real-readonly',
+  'readwrite', 'whiteout-able', 'link-able whiteout', etc. and their
+  combination.
+- internal "file copy-on-write".
+- logical deletion, whiteout.
+- dynamic branch manipulation, adding, deleting and changing permission.
+- allow bypassing aufs, user's direct branch access.
+- external inode number translation table and bitmap which maintains the
+  persistent aufs inode number.
+- seekable directory, including NFS readdir.
+- file mapping, mmap and sharing pages.
+- pseudo-link, hardlink over branches.
+- loopback mounted filesystem as a branch.
+- several policies to select one among multiple writable branches.
+- revert a single systemcall when an error occurs in aufs.
+- and more...
+
+
+Multi Layered Stackable Unification Filesystem
+----------------------------------------------------------------------
+Most people already knows what it is.
+It is a filesystem which unifies several directories and provides a
+merged single directory. When users access a file, the access will be
+passed/re-directed/converted (sorry, I am not sure which English word is
+correct) to the real file on the member filesystem. The member
+filesystem is called 'lower filesystem' or 'branch' and has a mode
+'readonly' and 'readwrite.' And the deletion for a file on the lower
+readonly branch is handled by creating 'whiteout' on the upper writable
+branch.
+
+On LKML, there have been discussions about UnionMount (Jan Blunck,
+Bharata B Rao and Valerie Aurora) and Unionfs (Erez Zadok). They took
+different approaches to implement the merged-view.
+The former tries putting it into VFS, and the latter implements as a
+separate filesystem.
+(If I misunderstand about these implementations, please let me know and
+I shall correct it. Because it is a long time ago when I read their
+source files last time).
+
+UnionMount's approach will be able to small, but may be hard to share
+branches between several UnionMount since the whiteout in it is
+implemented in the inode on branch filesystem and always
+shared. According to Bharata's post, readdir does not seems to be
+finished yet.
+There are several missing features known in this implementations such as
+- for users, the inode number may change silently. eg. copy-up.
+- link(2) may break by copy-up.
+- read(2) may get an obsoleted filedata (fstat(2) too).
+- fcntl(F_SETLK) may be broken by copy-up.
+- unnecessary copy-up may happen, for example mmap(MAP_PRIVATE) after
+  open(O_RDWR).
+
+In linux-3.18, "overlay" filesystem (formerly known as "overlayfs") was
+merged into mainline. This is another implementation of UnionMount as a
+separated filesystem. All the limitations and known problems which
+UnionMount are equally inherited to "overlay" filesystem.
+
+Unionfs has a longer history. When I started implementing a stackable
+filesystem (Aug 2005), it already existed. It has virtual super_block,
+inode, dentry and file objects and they have an array pointing lower
+same kind objects. After contributing many patches for Unionfs, I
+re-started my project AUFS (Jun 2006).
+
+In AUFS, the structure of filesystem resembles to Unionfs, but I
+implemented my own ideas, approaches and enhancements and it became
+totally different one.
+
+Comparing DM snapshot and fs based implementation
+- the number of bytes to be copied between devices is much smaller.
+- the type of filesystem must be one and only.
+- the fs must be writable, no readonly fs, even for the lower original
+  device. so the compression fs will not be usable. but if we use
+  loopback mount, we may address this issue.
+  for instance,
+	mount /cdrom/squashfs.img /sq
+	losetup /sq/ext2.img
+	losetup /somewhere/cow
+	dmsetup "snapshot /dev/loop0 /dev/loop1 ..."
+- it will be difficult (or needs more operations) to extract the
+  difference between the original device and COW.
+- DM snapshot-merge may help a lot when users try merging. in the
+  fs-layer union, users will use rsync(1).
+
+You may want to read my old paper "Filesystems in LiveCD"
+(http://aufs.sourceforge.net/aufs2/report/sq/sq.pdf).
+
+
+Several characters/aspects/persona of aufs
+----------------------------------------------------------------------
+
+Aufs has several characters, aspects or persona.
+1. a filesystem, callee of VFS helper
+2. sub-VFS, caller of VFS helper for branches
+3. a virtual filesystem which maintains persistent inode number
+4. reader/writer of files on branches such like an application
+
+1. Callee of VFS Helper
+As an ordinary linux filesystem, aufs is a callee of VFS. For instance,
+unlink(2) from an application reaches sys_unlink() kernel function and
+then vfs_unlink() is called. vfs_unlink() is one of VFS helper and it
+calls filesystem specific unlink operation. Actually aufs implements the
+unlink operation but it behaves like a redirector.
+
+2. Caller of VFS Helper for Branches
+aufs_unlink() passes the unlink request to the branch filesystem as if
+it were called from VFS. So the called unlink operation of the branch
+filesystem acts as usual. As a caller of VFS helper, aufs should handle
+every necessary pre/post operation for the branch filesystem.
+- acquire the lock for the parent dir on a branch
+- lookup in a branch
+- revalidate dentry on a branch
+- mnt_want_write() for a branch
+- vfs_unlink() for a branch
+- mnt_drop_write() for a branch
+- release the lock on a branch
+
+3. Persistent Inode Number
+One of the most important issue for a filesystem is to maintain inode
+numbers. This is particularly important to support exporting a
+filesystem via NFS. Aufs is a virtual filesystem which doesn't have a
+backend block device for its own. But some storage is necessary to
+keep and maintain the inode numbers. It may be a large space and may not
+suit to keep in memory. Aufs rents some space from its first writable
+branch filesystem (by default) and creates file(s) on it. These files
+are created by aufs internally and removed soon (currently) keeping
+opened.
+Note: Because these files are removed, they are totally gone after
+      unmounting aufs. It means the inode numbers are not persistent
+      across unmount or reboot. I have a plan to make them really
+      persistent which will be important for aufs on NFS server.
+
+4. Read/Write Files Internally (copy-on-write)
+Because a branch can be readonly, when you write a file on it, aufs will
+"copy-up" it to the upper writable branch internally. And then write the
+originally requested thing to the file. Generally kernel doesn't
+open/read/write file actively. In aufs, even a single write may cause a
+internal "file copy". This behaviour is very similar to cp(1) command.
+
+Some people may think it is better to pass such work to user space
+helper, instead of doing in kernel space. Actually I am still thinking
+about it. But currently I have implemented it in kernel space.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/filesystems/aufs/design/02struct.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/filesystems/aufs/design/02struct.txt
@@ -0,0 +1,258 @@
+
+# Copyright (C) 2005-2020 Junjiro R. Okajima
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Basic Aufs Internal Structure
+
+Superblock/Inode/Dentry/File Objects
+----------------------------------------------------------------------
+As like an ordinary filesystem, aufs has its own
+superblock/inode/dentry/file objects. All these objects have a
+dynamically allocated array and store the same kind of pointers to the
+lower filesystem, branch.
+For example, when you build a union with one readwrite branch and one
+readonly, mounted /au, /rw and /ro respectively.
+- /au = /rw + /ro
+- /ro/fileA exists but /rw/fileA
+
+Aufs lookup operation finds /ro/fileA and gets dentry for that. These
+pointers are stored in a aufs dentry. The array in aufs dentry will be,
+- [0] = NULL (because /rw/fileA doesn't exist)
+- [1] = /ro/fileA
+
+This style of an array is essentially same to the aufs
+superblock/inode/dentry/file objects.
+
+Because aufs supports manipulating branches, ie. add/delete/change
+branches dynamically, these objects has its own generation. When
+branches are changed, the generation in aufs superblock is
+incremented. And a generation in other object are compared when it is
+accessed. When a generation in other objects are obsoleted, aufs
+refreshes the internal array.
+
+
+Superblock
+----------------------------------------------------------------------
+Additionally aufs superblock has some data for policies to select one
+among multiple writable branches, XIB files, pseudo-links and kobject.
+See below in detail.
+About the policies which supports copy-down a directory, see
+wbr_policy.txt too.
+
+
+Branch and XINO(External Inode Number Translation Table)
+----------------------------------------------------------------------
+Every branch has its own xino (external inode number translation table)
+file. The xino file is created and unlinked by aufs internally. When two
+members of a union exist on the same filesystem, they share the single
+xino file.
+The struct of a xino file is simple, just a sequence of aufs inode
+numbers which is indexed by the lower inode number.
+In the above sample, assume the inode number of /ro/fileA is i111 and
+aufs assigns the inode number i999 for fileA. Then aufs writes 999 as
+4(8) bytes at 111 * 4(8) bytes offset in the xino file.
+
+When the inode numbers are not contiguous, the xino file will be sparse
+which has a hole in it and doesn't consume as much disk space as it
+might appear. If your branch filesystem consumes disk space for such
+holes, then you should specify 'xino=' option at mounting aufs.
+
+Aufs has a mount option to free the disk blocks for such holes in XINO
+files on tmpfs or ramdisk. But it is not so effective actually. If you
+meet a problem of disk shortage due to XINO files, then you should try
+"tmpfs-ino.patch" (and "vfs-ino.patch" too) in aufs4-standalone.git.
+The patch localizes the assignment inumbers per tmpfs-mount and avoid
+the holes in XINO files.
+
+Also a writable branch has three kinds of "whiteout bases". All these
+are existed when the branch is joined to aufs, and their names are
+whiteout-ed doubly, so that users will never see their names in aufs
+hierarchy.
+1. a regular file which will be hardlinked to all whiteouts.
+2. a directory to store a pseudo-link.
+3. a directory to store an "orphan"-ed file temporary.
+
+1. Whiteout Base
+   When you remove a file on a readonly branch, aufs handles it as a
+   logical deletion and creates a whiteout on the upper writable branch
+   as a hardlink of this file in order not to consume inode on the
+   writable branch.
+2. Pseudo-link Dir
+   See below, Pseudo-link.
+3. Step-Parent Dir
+   When "fileC" exists on the lower readonly branch only and it is
+   opened and removed with its parent dir, and then user writes
+   something into it, then aufs copies-up fileC to this
+   directory. Because there is no other dir to store fileC. After
+   creating a file under this dir, the file is unlinked.
+
+Because aufs supports manipulating branches, ie. add/delete/change
+dynamically, a branch has its own id. When the branch order changes,
+aufs finds the new index by searching the branch id.
+
+
+Pseudo-link
+----------------------------------------------------------------------
+Assume "fileA" exists on the lower readonly branch only and it is
+hardlinked to "fileB" on the branch. When you write something to fileA,
+aufs copies-up it to the upper writable branch. Additionally aufs
+creates a hardlink under the Pseudo-link Directory of the writable
+branch. The inode of a pseudo-link is kept in aufs super_block as a
+simple list. If fileB is read after unlinking fileA, aufs returns
+filedata from the pseudo-link instead of the lower readonly
+branch. Because the pseudo-link is based upon the inode, to keep the
+inode number by xino (see above) is essentially necessary.
+
+All the hardlinks under the Pseudo-link Directory of the writable branch
+should be restored in a proper location later. Aufs provides a utility
+to do this. The userspace helpers executed at remounting and unmounting
+aufs by default.
+During this utility is running, it puts aufs into the pseudo-link
+maintenance mode. In this mode, only the process which began the
+maintenance mode (and its child processes) is allowed to operate in
+aufs. Some other processes which are not related to the pseudo-link will
+be allowed to run too, but the rest have to return an error or wait
+until the maintenance mode ends. If a process already acquires an inode
+mutex (in VFS), it has to return an error.
+
+
+XIB(external inode number bitmap)
+----------------------------------------------------------------------
+Addition to the xino file per a branch, aufs has an external inode number
+bitmap in a superblock object. It is also an internal file such like a
+xino file.
+It is a simple bitmap to mark whether the aufs inode number is in-use or
+not.
+To reduce the file I/O, aufs prepares a single memory page to cache xib.
+
+As well as XINO files, aufs has a feature to truncate/refresh XIB to
+reduce the number of consumed disk blocks for these files.
+
+
+Virtual or Vertical Dir, and Readdir in Userspace
+----------------------------------------------------------------------
+In order to support multiple layers (branches), aufs readdir operation
+constructs a virtual dir block on memory. For readdir, aufs calls
+vfs_readdir() internally for each dir on branches, merges their entries
+with eliminating the whiteout-ed ones, and sets it to file (dir)
+object. So the file object has its entry list until it is closed. The
+entry list will be updated when the file position is zero and becomes
+obsoleted. This decision is made in aufs automatically.
+
+The dynamically allocated memory block for the name of entries has a
+unit of 512 bytes (by default) and stores the names contiguously (no
+padding). Another block for each entry is handled by kmem_cache too.
+During building dir blocks, aufs creates hash list and judging whether
+the entry is whiteouted by its upper branch or already listed.
+The merged result is cached in the corresponding inode object and
+maintained by a customizable life-time option.
+
+Some people may call it can be a security hole or invite DoS attack
+since the opened and once readdir-ed dir (file object) holds its entry
+list and becomes a pressure for system memory. But I'd say it is similar
+to files under /proc or /sys. The virtual files in them also holds a
+memory page (generally) while they are opened. When an idea to reduce
+memory for them is introduced, it will be applied to aufs too.
+For those who really hate this situation, I've developed readdir(3)
+library which operates this merging in userspace. You just need to set
+LD_PRELOAD environment variable, and aufs will not consume no memory in
+kernel space for readdir(3).
+
+
+Workqueue
+----------------------------------------------------------------------
+Aufs sometimes requires privilege access to a branch. For instance,
+in copy-up/down operation. When a user process is going to make changes
+to a file which exists in the lower readonly branch only, and the mode
+of one of ancestor directories may not be writable by a user
+process. Here aufs copy-up the file with its ancestors and they may
+require privilege to set its owner/group/mode/etc.
+This is a typical case of a application character of aufs (see
+Introduction).
+
+Aufs uses workqueue synchronously for this case. It creates its own
+workqueue. The workqueue is a kernel thread and has privilege. Aufs
+passes the request to call mkdir or write (for example), and wait for
+its completion. This approach solves a problem of a signal handler
+simply.
+If aufs didn't adopt the workqueue and changed the privilege of the
+process, then the process may receive the unexpected SIGXFSZ or other
+signals.
+
+Also aufs uses the system global workqueue ("events" kernel thread) too
+for asynchronous tasks, such like handling inotify/fsnotify, re-creating a
+whiteout base and etc. This is unrelated to a privilege.
+Most of aufs operation tries acquiring a rw_semaphore for aufs
+superblock at the beginning, at the same time waits for the completion
+of all queued asynchronous tasks.
+
+
+Whiteout
+----------------------------------------------------------------------
+The whiteout in aufs is very similar to Unionfs's. That is represented
+by its filename. UnionMount takes an approach of a file mode, but I am
+afraid several utilities (find(1) or something) will have to support it.
+
+Basically the whiteout represents "logical deletion" which stops aufs to
+lookup further, but also it represents "dir is opaque" which also stop
+further lookup.
+
+In aufs, rmdir(2) and rename(2) for dir uses whiteout alternatively.
+In order to make several functions in a single systemcall to be
+revertible, aufs adopts an approach to rename a directory to a temporary
+unique whiteouted name.
+For example, in rename(2) dir where the target dir already existed, aufs
+renames the target dir to a temporary unique whiteouted name before the
+actual rename on a branch, and then handles other actions (make it opaque,
+update the attributes, etc). If an error happens in these actions, aufs
+simply renames the whiteouted name back and returns an error. If all are
+succeeded, aufs registers a function to remove the whiteouted unique
+temporary name completely and asynchronously to the system global
+workqueue.
+
+
+Copy-up
+----------------------------------------------------------------------
+It is a well-known feature or concept.
+When user modifies a file on a readonly branch, aufs operate "copy-up"
+internally and makes change to the new file on the upper writable branch.
+When the trigger systemcall does not update the timestamps of the parent
+dir, aufs reverts it after copy-up.
+
+
+Move-down (aufs3.9 and later)
+----------------------------------------------------------------------
+"Copy-up" is one of the essential feature in aufs. It copies a file from
+the lower readonly branch to the upper writable branch when a user
+changes something about the file.
+"Move-down" is an opposite action of copy-up. Basically this action is
+ran manually instead of automatically and internally.
+For desgin and implementation, aufs has to consider these issues.
+- whiteout for the file may exist on the lower branch.
+- ancestor directories may not exist on the lower branch.
+- diropq for the ancestor directories may exist on the upper branch.
+- free space on the lower branch will reduce.
+- another access to the file may happen during moving-down, including
+  UDBA (see "Revalidate Dentry and UDBA").
+- the file should not be hard-linked nor pseudo-linked. they should be
+  handled by auplink utility later.
+
+Sometimes users want to move-down a file from the upper writable branch
+to the lower readonly or writable branch. For instance,
+- the free space of the upper writable branch is going to run out.
+- create a new intermediate branch between the upper and lower branch.
+- etc.
+
+For this purpose, use "aumvdown" command in aufs-util.git.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/filesystems/aufs/design/03atomic_open.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/filesystems/aufs/design/03atomic_open.txt
@@ -0,0 +1,85 @@
+
+# Copyright (C) 2015-2020 Junjiro R. Okajima
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Support for a branch who has its ->atomic_open()
+----------------------------------------------------------------------
+The filesystems who implement its ->atomic_open() are not majority. For
+example NFSv4 does, and aufs should call NFSv4 ->atomic_open,
+particularly for open(O_CREAT|O_EXCL, 0400) case. Other than
+->atomic_open(), NFSv4 returns an error for this open(2). While I am not
+sure whether all filesystems who have ->atomic_open() behave like this,
+but NFSv4 surely returns the error.
+
+In order to support ->atomic_open() for aufs, there are a few
+approaches.
+
+A. Introduce aufs_atomic_open()
+   - calls one of VFS:do_last(), lookup_open() or atomic_open() for
+     branch fs.
+B. Introduce aufs_atomic_open() calling create, open and chmod. this is
+   an aufs user Pip Cet's approach
+   - calls aufs_create(), VFS finish_open() and notify_change().
+   - pass fake-mode to finish_open(), and then correct the mode by
+     notify_change().
+C. Extend aufs_open() to call branch fs's ->atomic_open()
+   - no aufs_atomic_open().
+   - aufs_lookup() registers the TID to an aufs internal object.
+   - aufs_create() does nothing when the matching TID is registered, but
+     registers the mode.
+   - aufs_open() calls branch fs's ->atomic_open() when the matching
+     TID is registered.
+D. Extend aufs_open() to re-try branch fs's ->open() with superuser's
+   credential
+   - no aufs_atomic_open().
+   - aufs_create() registers the TID to an internal object. this info
+     represents "this process created this file just now."
+   - when aufs gets EACCES from branch fs's ->open(), then confirm the
+     registered TID and re-try open() with superuser's credential.
+
+Pros and cons for each approach.
+
+A.
+   - straightforward but highly depends upon VFS internal.
+   - the atomic behavaiour is kept.
+   - some of parameters such as nameidata are hard to reproduce for
+     branch fs.
+   - large overhead.
+B.
+   - easy to implement.
+   - the atomic behavaiour is lost.
+C.
+   - the atomic behavaiour is kept.
+   - dirty and tricky.
+   - VFS checks whether the file is created correctly after calling
+     ->create(), which means this approach doesn't work.
+D.
+   - easy to implement.
+   - the atomic behavaiour is lost.
+   - to open a file with superuser's credential and give it to a user
+     process is a bad idea, since the file object keeps the credential
+     in it. It may affect LSM or something. This approach doesn't work
+     either.
+
+The approach A is ideal, but it hard to implement. So here is a
+variation of A, which is to be implemented.
+
+A-1. Introduce aufs_atomic_open()
+     - calls branch fs ->atomic_open() if exists. otherwise calls
+       vfs_create() and finish_open().
+     - the demerit is that the several checks after branch fs
+       ->atomic_open() are lost. in the ordinary case, the checks are
+       done by VFS:do_last(), lookup_open() and atomic_open(). some can
+       be implemented in aufs, but not all I am afraid.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/filesystems/aufs/design/03lookup.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/filesystems/aufs/design/03lookup.txt
@@ -0,0 +1,113 @@
+
+# Copyright (C) 2005-2020 Junjiro R. Okajima
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Lookup in a Branch
+----------------------------------------------------------------------
+Since aufs has a character of sub-VFS (see Introduction), it operates
+lookup for branches as VFS does. It may be a heavy work. But almost all
+lookup operation in aufs is the simplest case, ie. lookup only an entry
+directly connected to its parent. Digging down the directory hierarchy
+is unnecessary. VFS has a function lookup_one_len() for that use, and
+aufs calls it.
+
+When a branch is a remote filesystem, aufs basically relies upon its
+->d_revalidate(), also aufs forces the hardest revalidate tests for
+them.
+For d_revalidate, aufs implements three levels of revalidate tests. See
+"Revalidate Dentry and UDBA" in detail.
+
+
+Test Only the Highest One for the Directory Permission (dirperm1 option)
+----------------------------------------------------------------------
+Let's try case study.
+- aufs has two branches, upper readwrite and lower readonly.
+  /au = /rw + /ro
+- "dirA" exists under /ro, but /rw. and its mode is 0700.
+- user invoked "chmod a+rx /au/dirA"
+- the internal copy-up is activated and "/rw/dirA" is created and its
+  permission bits are set to world readable.
+- then "/au/dirA" becomes world readable?
+
+In this case, /ro/dirA is still 0700 since it exists in readonly branch,
+or it may be a natively readonly filesystem. If aufs respects the lower
+branch, it should not respond readdir request from other users. But user
+allowed it by chmod. Should really aufs rejects showing the entries
+under /ro/dirA?
+
+To be honest, I don't have a good solution for this case. So aufs
+implements 'dirperm1' and 'nodirperm1' mount options, and leave it to
+users.
+When dirperm1 is specified, aufs checks only the highest one for the
+directory permission, and shows the entries. Otherwise, as usual, checks
+every dir existing on all branches and rejects the request.
+
+As a side effect, dirperm1 option improves the performance of aufs
+because the number of permission check is reduced when the number of
+branch is many.
+
+
+Revalidate Dentry and UDBA (User's Direct Branch Access)
+----------------------------------------------------------------------
+Generally VFS helpers re-validate a dentry as a part of lookup.
+0. digging down the directory hierarchy.
+1. lock the parent dir by its i_mutex.
+2. lookup the final (child) entry.
+3. revalidate it.
+4. call the actual operation (create, unlink, etc.)
+5. unlock the parent dir
+
+If the filesystem implements its ->d_revalidate() (step 3), then it is
+called. Actually aufs implements it and checks the dentry on a branch is
+still valid.
+But it is not enough. Because aufs has to release the lock for the
+parent dir on a branch at the end of ->lookup() (step 2) and
+->d_revalidate() (step 3) while the i_mutex of the aufs dir is still
+held by VFS.
+If the file on a branch is changed directly, eg. bypassing aufs, after
+aufs released the lock, then the subsequent operation may cause
+something unpleasant result.
+
+This situation is a result of VFS architecture, ->lookup() and
+->d_revalidate() is separated. But I never say it is wrong. It is a good
+design from VFS's point of view. It is just not suitable for sub-VFS
+character in aufs.
+
+Aufs supports such case by three level of revalidation which is
+selectable by user.
+1. Simple Revalidate
+   Addition to the native flow in VFS's, confirm the child-parent
+   relationship on the branch just after locking the parent dir on the
+   branch in the "actual operation" (step 4). When this validation
+   fails, aufs returns EBUSY. ->d_revalidate() (step 3) in aufs still
+   checks the validation of the dentry on branches.
+2. Monitor Changes Internally by Inotify/Fsnotify
+   Addition to above, in the "actual operation" (step 4) aufs re-lookup
+   the dentry on the branch, and returns EBUSY if it finds different
+   dentry.
+   Additionally, aufs sets the inotify/fsnotify watch for every dir on branches
+   during it is in cache. When the event is notified, aufs registers a
+   function to kernel 'events' thread by schedule_work(). And the
+   function sets some special status to the cached aufs dentry and inode
+   private data. If they are not cached, then aufs has nothing to
+   do. When the same file is accessed through aufs (step 0-3) later,
+   aufs will detect the status and refresh all necessary data.
+   In this mode, aufs has to ignore the event which is fired by aufs
+   itself.
+3. No Extra Validation
+   This is the simplest test and doesn't add any additional revalidation
+   test, and skip the revalidation in step 4. It is useful and improves
+   aufs performance when system surely hide the aufs branches from user,
+   by over-mounting something (or another method).
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/filesystems/aufs/design/04branch.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/filesystems/aufs/design/04branch.txt
@@ -0,0 +1,74 @@
+
+# Copyright (C) 2005-2020 Junjiro R. Okajima
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Branch Manipulation
+
+Since aufs supports dynamic branch manipulation, ie. add/remove a branch
+and changing its permission/attribute, there are a lot of works to do.
+
+
+Add a Branch
+----------------------------------------------------------------------
+o Confirm the adding dir exists outside of aufs, including loopback
+  mount, and its various attributes.
+o Initialize the xino file and whiteout bases if necessary.
+  See struct.txt.
+
+o Check the owner/group/mode of the directory
+  When the owner/group/mode of the adding directory differs from the
+  existing branch, aufs issues a warning because it may impose a
+  security risk.
+  For example, when a upper writable branch has a world writable empty
+  top directory, a malicious user can create any files on the writable
+  branch directly, like copy-up and modify manually. If something like
+  /etc/{passwd,shadow} exists on the lower readonly branch but the upper
+  writable branch, and the writable branch is world-writable, then a
+  malicious guy may create /etc/passwd on the writable branch directly
+  and the infected file will be valid in aufs.
+  I am afraid it can be a security issue, but aufs can do nothing except
+  producing a warning.
+
+
+Delete a Branch
+----------------------------------------------------------------------
+o Confirm the deleting branch is not busy
+  To be general, there is one merit to adopt "remount" interface to
+  manipulate branches. It is to discard caches. At deleting a branch,
+  aufs checks the still cached (and connected) dentries and inodes. If
+  there are any, then they are all in-use. An inode without its
+  corresponding dentry can be alive alone (for example, inotify/fsnotify case).
+
+  For the cached one, aufs checks whether the same named entry exists on
+  other branches.
+  If the cached one is a directory, because aufs provides a merged view
+  to users, as long as one dir is left on any branch aufs can show the
+  dir to users. In this case, the branch can be removed from aufs.
+  Otherwise aufs rejects deleting the branch.
+
+  If any file on the deleting branch is opened by aufs, then aufs
+  rejects deleting.
+
+
+Modify the Permission of a Branch
+----------------------------------------------------------------------
+o Re-initialize or remove the xino file and whiteout bases if necessary.
+  See struct.txt.
+
+o rw --> ro: Confirm the modifying branch is not busy
+  Aufs rejects the request if any of these conditions are true.
+  - a file on the branch is mmap-ed.
+  - a regular file on the branch is opened for write and there is no
+    same named entry on the upper branch.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/filesystems/aufs/design/05wbr_policy.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/filesystems/aufs/design/05wbr_policy.txt
@@ -0,0 +1,64 @@
+
+# Copyright (C) 2005-2020 Junjiro R. Okajima
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Policies to Select One among Multiple Writable Branches
+----------------------------------------------------------------------
+When the number of writable branch is more than one, aufs has to decide
+the target branch for file creation or copy-up. By default, the highest
+writable branch which has the parent (or ancestor) dir of the target
+file is chosen (top-down-parent policy).
+By user's request, aufs implements some other policies to select the
+writable branch, for file creation several policies, round-robin,
+most-free-space, and other policies. For copy-up, top-down-parent,
+bottom-up-parent, bottom-up and others.
+
+As expected, the round-robin policy selects the branch in circular. When
+you have two writable branches and creates 10 new files, 5 files will be
+created for each branch. mkdir(2) systemcall is an exception. When you
+create 10 new directories, all will be created on the same branch.
+And the most-free-space policy selects the one which has most free
+space among the writable branches. The amount of free space will be
+checked by aufs internally, and users can specify its time interval.
+
+The policies for copy-up is more simple,
+top-down-parent is equivalent to the same named on in create policy,
+bottom-up-parent selects the writable branch where the parent dir
+exists and the nearest upper one from the copyup-source,
+bottom-up selects the nearest upper writable branch from the
+copyup-source, regardless the existence of the parent dir.
+
+There are some rules or exceptions to apply these policies.
+- If there is a readonly branch above the policy-selected branch and
+  the parent dir is marked as opaque (a variation of whiteout), or the
+  target (creating) file is whiteout-ed on the upper readonly branch,
+  then the result of the policy is ignored and the target file will be
+  created on the nearest upper writable branch than the readonly branch.
+- If there is a writable branch above the policy-selected branch and
+  the parent dir is marked as opaque or the target file is whiteouted
+  on the branch, then the result of the policy is ignored and the target
+  file will be created on the highest one among the upper writable
+  branches who has diropq or whiteout. In case of whiteout, aufs removes
+  it as usual.
+- link(2) and rename(2) systemcalls are exceptions in every policy.
+  They try selecting the branch where the source exists as possible
+  since copyup a large file will take long time. If it can't be,
+  ie. the branch where the source exists is readonly, then they will
+  follow the copyup policy.
+- There is an exception for rename(2) when the target exists.
+  If the rename target exists, aufs compares the index of the branches
+  where the source and the target exists and selects the higher
+  one. If the selected branch is readonly, then aufs follows the
+  copyup policy.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/filesystems/aufs/design/06dirren.dot
+++ linux-xilinx-zynqmp-5.4.0/Documentation/filesystems/aufs/design/06dirren.dot
@@ -0,0 +1,31 @@
+
+// to view this graph, run dot(1) command in GRAPHVIZ.
+
+digraph G {
+node [shape=box];
+whinfo [label="detailed info file\n(lower_brid_root-hinum, h_inum, namelen, old name)"];
+
+node [shape=oval];
+
+aufs_rename -> whinfo [label="store/remove"];
+
+node [shape=oval];
+inode_list [label="h_inum list in branch\ncache"];
+
+node [shape=box];
+whinode [label="h_inum list file"];
+
+node [shape=oval];
+brmgmt [label="br_add/del/mod/umount"];
+
+brmgmt -> inode_list [label="create/remove"];
+brmgmt -> whinode [label="load/store"];
+
+inode_list -> whinode [style=dashed,dir=both];
+
+aufs_rename -> inode_list [label="add/del"];
+
+aufs_lookup -> inode_list [label="search"];
+
+aufs_lookup -> whinfo [label="load/remove"];
+}
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/filesystems/aufs/design/06dirren.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/filesystems/aufs/design/06dirren.txt
@@ -0,0 +1,102 @@
+
+# Copyright (C) 2017-2020 Junjiro R. Okajima
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Special handling for renaming a directory (DIRREN)
+----------------------------------------------------------------------
+First, let's assume we have a simple usecase.
+
+- /u = /rw + /ro
+- /rw/dirA exists
+- /ro/dirA and /ro/dirA/file exist too
+- there is no dirB on both branches
+- a user issues rename("dirA", "dirB")
+
+Now, what should aufs behave against this rename(2)?
+There are a few possible cases.
+
+A. returns EROFS.
+   since dirA exists on a readonly branch which cannot be renamed.
+B. returns EXDEV.
+   it is possible to copy-up dirA (only the dir itself), but the child
+   entries ("file" in this case) should not be. it must be a bad
+   approach to copy-up recursively.
+C. returns a success.
+   even the branch /ro is readonly, aufs tries renaming it. Obviously it
+   is a violation of aufs' policy.
+D. construct an extra information which indicates that /ro/dirA should
+   be handled as the name of dirB.
+   overlayfs has a similar feature called REDIRECT.
+
+Until now, aufs implements the case B only which returns EXDEV, and
+expects the userspace application behaves like mv(1) which tries
+issueing rename(2) recursively.
+
+A new aufs feature called DIRREN is introduced which implements the case
+D. There are several "extra information" added.
+
+1. detailed info per renamed directory
+   path: /rw/dirB/$AUFS_WH_DR_INFO_PFX.<lower branch-id>
+2. the inode-number list of directories on a branch
+   path: /rw/dirB/$AUFS_WH_DR_BRHINO
+
+The filename of "detailed info per directory" represents the lower
+branch, and its format is
+- a type of the branch id
+  one of these.
+  + uuid (not implemented yet)
+  + fsid
+  + dev
+- the inode-number of the branch root dir
+
+And it contains these info in a single regular file.
+- magic number
+- branch's inode-number of the logically renamed dir
+- the name of the before-renamed dir
+
+The "detailed info per directory" file is created in aufs rename(2), and
+loaded in any lookup.
+The info is considered in lookup for the matching case only. Here
+"matching" means that the root of branch (in the info filename) is same
+to the current looking-up branch. After looking-up the before-renamed
+name, the inode-number is compared. And the matched dentry is used.
+
+The "inode-number list of directories" is a regular file which contains
+simply the inode-numbers on the branch. The file is created or updated
+in removing the branch, and loaded in adding the branch. Its lifetime is
+equal to the branch.
+The list is refered in lookup, and when the current target inode is
+found in the list, the aufs tries loading the "detailed info per
+directory" and get the changed and valid name of the dir.
+
+Theoretically these "extra informaiton" may be able to be put into XATTR
+in the dir inode. But aufs doesn't choose this way because
+1. XATTR may not be supported by the branch (or its configuration)
+2. XATTR may have its size limit.
+3. XATTR may be less easy to convert than a regular file, when the
+   format of the info is changed in the future.
+At the same time, I agree that the regular file approach is much slower
+than XATTR approach. So, in the future, aufs may take the XATTR or other
+better approach.
+
+This DIRREN feature is enabled by aufs configuration, and is activated
+by a new mount option.
+
+For the more complicated case, there is a work with UDBA option, which
+is to dected the direct access to the branches (by-passing aufs) and to
+maintain the cashes in aufs. Since a single cached aufs dentry may
+contains two names, before- and after-rename, the name comparision in
+UDBA handler may not work correctly. In this case, the behaviour will be
+equivalen to udba=reval case.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/filesystems/aufs/design/06fhsm.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/filesystems/aufs/design/06fhsm.txt
@@ -0,0 +1,120 @@
+
+# Copyright (C) 2011-2020 Junjiro R. Okajima
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+
+File-based Hierarchical Storage Management (FHSM)
+----------------------------------------------------------------------
+Hierarchical Storage Management (or HSM) is a well-known feature in the
+storage world. Aufs provides this feature as file-based with multiple
+writable branches, based upon the principle of "Colder, the Lower".
+Here the word "colder" means that the less used files, and "lower" means
+that the position in the order of the stacked branches vertically.
+These multiple writable branches are prioritized, ie. the topmost one
+should be the fastest drive and be used heavily.
+
+o Characters in aufs FHSM story
+- aufs itself and a new branch attribute.
+- a new ioctl interface to move-down and to establish a connection with
+  the daemon ("move-down" is a converse of "copy-up").
+- userspace tool and daemon.
+
+The userspace daemon establishes a connection with aufs and waits for
+the notification. The notified information is very similar to struct
+statfs containing the number of consumed blocks and inodes.
+When the consumed blocks/inodes of a branch exceeds the user-specified
+upper watermark, the daemon activates its move-down process until the
+consumed blocks/inodes reaches the user-specified lower watermark.
+
+The actual move-down is done by aufs based upon the request from
+user-space since we need to maintain the inode number and the internal
+pointer arrays in aufs.
+
+Currently aufs FHSM handles the regular files only. Additionally they
+must not be hard-linked nor pseudo-linked.
+
+
+o Cowork of aufs and the user-space daemon
+  During the userspace daemon established the connection, aufs sends a
+  small notification to it whenever aufs writes something into the
+  writable branch. But it may cost high since aufs issues statfs(2)
+  internally. So user can specify a new option to cache the
+  info. Actually the notification is controlled by these factors.
+  + the specified cache time.
+  + classified as "force" by aufs internally.
+  Until the specified time expires, aufs doesn't send the info
+  except the forced cases. When aufs decide forcing, the info is always
+  notified to userspace.
+  For example, the number of free inodes is generally large enough and
+  the shortage of it happens rarely. So aufs doesn't force the
+  notification when creating a new file, directory and others. This is
+  the typical case which aufs doesn't force.
+  When aufs writes the actual filedata and the files consumes any of new
+  blocks, the aufs forces notifying.
+
+
+o Interfaces in aufs
+- New branch attribute.
+  + fhsm
+    Specifies that the branch is managed by FHSM feature. In other word,
+    participant in the FHSM.
+    When nofhsm is set to the branch, it will not be the source/target
+    branch of the move-down operation. This attribute is set
+    independently from coo and moo attributes, and if you want full
+    FHSM, you should specify them as well.
+- New mount option.
+  + fhsm_sec
+    Specifies a second to suppress many less important info to be
+    notified.
+- New ioctl.
+  + AUFS_CTL_FHSM_FD
+    create a new file descriptor which userspace can read the notification
+    (a subset of struct statfs) from aufs.
+- Module parameter 'brs'
+  It has to be set to 1. Otherwise the new mount option 'fhsm' will not
+  be set.
+- mount helpers /sbin/mount.aufs and /sbin/umount.aufs
+  When there are two or more branches with fhsm attributes,
+  /sbin/mount.aufs invokes the user-space daemon and /sbin/umount.aufs
+  terminates it. As a result of remounting and branch-manipulation, the
+  number of branches with fhsm attribute can be one. In this case,
+  /sbin/mount.aufs will terminate the user-space daemon.
+
+
+Finally the operation is done as these steps in kernel-space.
+- make sure that,
+  + no one else is using the file.
+  + the file is not hard-linked.
+  + the file is not pseudo-linked.
+  + the file is a regular file.
+  + the parent dir is not opaqued.
+- find the target writable branch.
+- make sure the file is not whiteout-ed by the upper (than the target)
+  branch.
+- make the parent dir on the target branch.
+- mutex lock the inode on the branch.
+- unlink the whiteout on the target branch (if exists).
+- lookup and create the whiteout-ed temporary name on the target branch.
+- copy the file as the whiteout-ed temporary name on the target branch.
+- rename the whiteout-ed temporary name to the original name.
+- unlink the file on the source branch.
+- maintain the internal pointer array and the external inode number
+  table (XINO).
+- maintain the timestamps and other attributes of the parent dir and the
+  file.
+
+And of course, in every step, an error may happen. So the operation
+should restore the original file state after an error happens.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/filesystems/aufs/design/06mmap.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/filesystems/aufs/design/06mmap.txt
@@ -0,0 +1,72 @@
+
+# Copyright (C) 2005-2020 Junjiro R. Okajima
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+mmap(2) -- File Memory Mapping
+----------------------------------------------------------------------
+In aufs, the file-mapped pages are handled by a branch fs directly, no
+interaction with aufs. It means aufs_mmap() calls the branch fs's
+->mmap().
+This approach is simple and good, but there is one problem.
+Under /proc, several entries show the mmapped files by its path (with
+device and inode number), and the printed path will be the path on the
+branch fs's instead of virtual aufs's.
+This is not a problem in most cases, but some utilities lsof(1) (and its
+user) may expect the path on aufs.
+
+To address this issue, aufs adds a new member called vm_prfile in struct
+vm_area_struct (and struct vm_region). The original vm_file points to
+the file on the branch fs in order to handle everything correctly as
+usual. The new vm_prfile points to a virtual file in aufs, and the
+show-functions in procfs refers to vm_prfile if it is set.
+Also we need to maintain several other places where touching vm_file
+such like
+- fork()/clone() copies vma and the reference count of vm_file is
+  incremented.
+- merging vma maintains the ref count too.
+
+This is not a good approach. It just fakes the printed path. But it
+leaves all behaviour around f_mapping unchanged. This is surely an
+advantage.
+Actually aufs had adopted another complicated approach which calls
+generic_file_mmap() and handles struct vm_operations_struct. In this
+approach, aufs met a hard problem and I could not solve it without
+switching the approach.
+
+There may be one more another approach which is
+- bind-mount the branch-root onto the aufs-root internally
+- grab the new vfsmount (ie. struct mount)
+- lazy-umount the branch-root internally
+- in open(2) the aufs-file, open the branch-file with the hidden
+  vfsmount (instead of the original branch's vfsmount)
+- ideally this "bind-mount and lazy-umount" should be done atomically,
+  but it may be possible from userspace by the mount helper.
+
+Adding the internal hidden vfsmount and using it in opening a file, the
+file path under /proc will be printed correctly. This approach looks
+smarter, but is not possible I am afraid.
+- aufs-root may be bind-mount later. when it happens, another hidden
+  vfsmount will be required.
+- it is hard to get the chance to bind-mount and lazy-umount
+  + in kernel-space, FS can have vfsmount in open(2) via
+    file->f_path, and aufs can know its vfsmount. But several locks are
+    already acquired, and if aufs tries to bind-mount and lazy-umount
+    here, then it may cause a deadlock.
+  + in user-space, bind-mount doesn't invoke the mount helper.
+- since /proc shows dev and ino, aufs has to give vma these info. it
+  means a new member vm_prinode will be necessary. this is essentially
+  equivalent to vm_prfile described above.
+
+I have to give up this "looks-smater" approach.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/filesystems/aufs/design/06xattr.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/filesystems/aufs/design/06xattr.txt
@@ -0,0 +1,96 @@
+
+# Copyright (C) 2014-2020 Junjiro R. Okajima
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+
+Listing XATTR/EA and getting the value
+----------------------------------------------------------------------
+For the inode standard attributes (owner, group, timestamps, etc.), aufs
+shows the values from the topmost existing file. This behaviour is good
+for the non-dir entries since the bahaviour exactly matches the shown
+information. But for the directories, aufs considers all the same named
+entries on the lower branches. Which means, if one of the lower entry
+rejects readdir call, then aufs returns an error even if the topmost
+entry allows it. This behaviour is necessary to respect the branch fs's
+security, but can make users confused since the user-visible standard
+attributes don't match the behaviour.
+To address this issue, aufs has a mount option called dirperm1 which
+checks the permission for the topmost entry only, and ignores the lower
+entry's permission.
+
+A similar issue can happen around XATTR.
+getxattr(2) and listxattr(2) families behave as if dirperm1 option is
+always set. Otherwise these very unpleasant situation would happen.
+- listxattr(2) may return the duplicated entries.
+- users may not be able to remove or reset the XATTR forever,
+
+
+XATTR/EA support in the internal (copy,move)-(up,down)
+----------------------------------------------------------------------
+Generally the extended attributes of inode are categorized as these.
+- "security" for LSM and capability.
+- "system" for posix ACL, 'acl' mount option is required for the branch
+  fs generally.
+- "trusted" for userspace, CAP_SYS_ADMIN is required.
+- "user" for userspace, 'user_xattr' mount option is required for the
+  branch fs generally.
+
+Moreover there are some other categories. Aufs handles these rather
+unpopular categories as the ordinary ones, ie. there is no special
+condition nor exception.
+
+In copy-up, the support for XATTR on the dst branch may differ from the
+src branch. In this case, the copy-up operation will get an error and
+the original user operation which triggered the copy-up will fail. It
+can happen that even all copy-up will fail.
+When both of src and dst branches support XATTR and if an error occurs
+during copying XATTR, then the copy-up should fail obviously. That is a
+good reason and aufs should return an error to userspace. But when only
+the src branch support that XATTR, aufs should not return an error.
+For example, the src branch supports ACL but the dst branch doesn't
+because the dst branch may natively un-support it or temporary
+un-support it due to "noacl" mount option. Of course, the dst branch fs
+may NOT return an error even if the XATTR is not supported. It is
+totally up to the branch fs.
+
+Anyway when the aufs internal copy-up gets an error from the dst branch
+fs, then aufs tries removing the just copied entry and returns the error
+to the userspace. The worst case of this situation will be all copy-up
+will fail.
+
+For the copy-up operation, there two basic approaches.
+- copy the specified XATTR only (by category above), and return the
+  error unconditionally if it happens.
+- copy all XATTR, and ignore the error on the specified category only.
+
+In order to support XATTR and to implement the correct behaviour, aufs
+chooses the latter approach and introduces some new branch attributes,
+"icexsec", "icexsys", "icextr", "icexusr", and "icexoth".
+They correspond to the XATTR namespaces (see above). Additionally, to be
+convenient, "icex" is also provided which means all "icex*" attributes
+are set (here the word "icex" stands for "ignore copy-error on XATTR").
+
+The meaning of these attributes is to ignore the error from setting
+XATTR on that branch.
+Note that aufs tries copying all XATTR unconditionally, and ignores the
+error from the dst branch according to the specified attributes.
+
+Some XATTR may have its default value. The default value may come from
+the parent dir or the environment. If the default value is set at the
+file creating-time, it will be overwritten by copy-up.
+Some contradiction may happen I am afraid.
+Do we need another attribute to stop copying XATTR? I am unsure. For
+now, aufs implements the branch attributes to ignore the error.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/filesystems/aufs/design/07export.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/filesystems/aufs/design/07export.txt
@@ -0,0 +1,58 @@
+
+# Copyright (C) 2005-2020 Junjiro R. Okajima
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Export Aufs via NFS
+----------------------------------------------------------------------
+Here is an approach.
+- like xino/xib, add a new file 'xigen' which stores aufs inode
+  generation.
+- iget_locked(): initialize aufs inode generation for a new inode, and
+  store it in xigen file.
+- destroy_inode(): increment aufs inode generation and store it in xigen
+  file. it is necessary even if it is not unlinked, because any data of
+  inode may be changed by UDBA.
+- encode_fh(): for a root dir, simply return FILEID_ROOT. otherwise
+  build file handle by
+  + branch id (4 bytes)
+  + superblock generation (4 bytes)
+  + inode number (4 or 8 bytes)
+  + parent dir inode number (4 or 8 bytes)
+  + inode generation (4 bytes))
+  + return value of exportfs_encode_fh() for the parent on a branch (4
+    bytes)
+  + file handle for a branch (by exportfs_encode_fh())
+- fh_to_dentry():
+  + find the index of a branch from its id in handle, and check it is
+    still exist in aufs.
+  + 1st level: get the inode number from handle and search it in cache.
+  + 2nd level: if not found in cache, get the parent inode number from
+    the handle and search it in cache. and then open the found parent
+    dir, find the matching inode number by vfs_readdir() and get its
+    name, and call lookup_one_len() for the target dentry.
+  + 3rd level: if the parent dir is not cached, call
+    exportfs_decode_fh() for a branch and get the parent on a branch,
+    build a pathname of it, convert it a pathname in aufs, call
+    path_lookup(). now aufs gets a parent dir dentry, then handle it as
+    the 2nd level.
+  + to open the dir, aufs needs struct vfsmount. aufs keeps vfsmount
+    for every branch, but not itself. to get this, (currently) aufs
+    searches in current->nsproxy->mnt_ns list. it may not be a good
+    idea, but I didn't get other approach.
+  + test the generation of the gotten inode.
+- every inode operation: they may get EBUSY due to UDBA. in this case,
+  convert it into ESTALE for NFSD.
+- readdir(): call lockdep_on/off() because filldir in NFSD calls
+  lookup_one_len(), vfs_getattr(), encode_fh() and others.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/filesystems/aufs/design/08shwh.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/filesystems/aufs/design/08shwh.txt
@@ -0,0 +1,52 @@
+
+# Copyright (C) 2005-2020 Junjiro R. Okajima
+# 
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Show Whiteout Mode (shwh)
+----------------------------------------------------------------------
+Generally aufs hides the name of whiteouts. But in some cases, to show
+them is very useful for users. For instance, creating a new middle layer
+(branch) by merging existing layers.
+
+(borrowing aufs1 HOW-TO from a user, Michael Towers)
+When you have three branches,
+- Bottom: 'system', squashfs (underlying base system), read-only
+- Middle: 'mods', squashfs, read-only
+- Top: 'overlay', ram (tmpfs), read-write
+
+The top layer is loaded at boot time and saved at shutdown, to preserve
+the changes made to the system during the session.
+When larger changes have been made, or smaller changes have accumulated,
+the size of the saved top layer data grows. At this point, it would be
+nice to be able to merge the two overlay branches ('mods' and 'overlay')
+and rewrite the 'mods' squashfs, clearing the top layer and thus
+restoring save and load speed.
+
+This merging is simplified by the use of another aufs mount, of just the
+two overlay branches using the 'shwh' option.
+# mount -t aufs -o ro,shwh,br:/livesys/overlay=ro+wh:/livesys/mods=rr+wh \
+	aufs /livesys/merge_union
+
+A merged view of these two branches is then available at
+/livesys/merge_union, and the new feature is that the whiteouts are
+visible!
+Note that in 'shwh' mode the aufs mount must be 'ro', which will disable
+writing to all branches. Also the default mode for all branches is 'ro'.
+It is now possible to save the combined contents of the two overlay
+branches to a new squashfs, e.g.:
+# mksquashfs /livesys/merge_union /path/to/newmods.squash
+
+This new squashfs archive can be stored on the boot device and the
+initramfs will use it to replace the old one at the next boot.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/filesystems/aufs/design/10dynop.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/filesystems/aufs/design/10dynop.txt
@@ -0,0 +1,47 @@
+
+# Copyright (C) 2010-2020 Junjiro R. Okajima
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Dynamically customizable FS operations
+----------------------------------------------------------------------
+Generally FS operations (struct inode_operations, struct
+address_space_operations, struct file_operations, etc.) are defined as
+"static const", but it never means that FS have only one set of
+operation. Some FS have multiple sets of them. For instance, ext2 has
+three sets, one for XIP, for NOBH, and for normal.
+Since aufs overrides and redirects these operations, sometimes aufs has
+to change its behaviour according to the branch FS type. More importantly
+VFS acts differently if a function (member in the struct) is set or
+not. It means aufs should have several sets of operations and select one
+among them according to the branch FS definition.
+
+In order to solve this problem and not to affect the behaviour of VFS,
+aufs defines these operations dynamically. For instance, aufs defines
+dummy direct_IO function for struct address_space_operations, but it may
+not be set to the address_space_operations actually. When the branch FS
+doesn't have it, aufs doesn't set it to its address_space_operations
+while the function definition itself is still alive. So the behaviour
+itself will not change, and it will return an error when direct_IO is
+not set.
+
+The lifetime of these dynamically generated operation object is
+maintained by aufs branch object. When the branch is removed from aufs,
+the reference counter of the object is decremented. When it reaches
+zero, the dynamically generated operation object will be freed.
+
+This approach is designed to support AIO (io_submit), Direct I/O and
+XIP (DAX) mainly.
+Currently this approach is applied to address_space_operations for
+regular files only.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/filesystems/directory-locking.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/filesystems/directory-locking.rst
@@ -23,13 +23,15 @@
 locks victim and calls the method.  Locks are exclusive.
 
 4) rename() that is _not_ cross-directory.  Locking rules: caller locks
-the parent and finds source and target.  In case of exchange (with
-RENAME_EXCHANGE in flags argument) lock both.  In any case,
-if the target already exists, lock it.  If the source is a non-directory,
-lock it.  If we need to lock both, lock them in inode pointer order.
-Then call the method.  All locks are exclusive.
-NB: we might get away with locking the the source (and target in exchange
-case) shared.
+the parent and finds source and target.  Then we decide which of the
+source and target need to be locked.  Source needs to be locked if it's a
+non-directory; target - if it's a non-directory or about to be removed.
+Take the locks that need to be taken, in inode pointer order if need
+to take both (that can happen only when both source and target are
+non-directories - the source because it wouldn't be locked otherwise
+and the target because mixing directory and non-directory is allowed
+only with RENAME_EXCHANGE, and that won't be removing the target).
+After the locks had been taken, call the method.  All locks are exclusive.
 
 5) link creation.  Locking rules:
 
@@ -44,19 +46,22 @@
 rules:
 
 	* lock the filesystem
-	* lock parents in "ancestors first" order.
+	* lock parents in "ancestors first" order. If one is not ancestor of
+	  the other, lock the parent of source first.
 	* find source and target.
 	* if old parent is equal to or is a descendent of target
 	  fail with -ENOTEMPTY
 	* if new parent is equal to or is a descendent of source
 	  fail with -ELOOP
-	* If it's an exchange, lock both the source and the target.
-	* If the target exists, lock it.  If the source is a non-directory,
-	  lock it.  If we need to lock both, do so in inode pointer order.
+	* Lock both the source and the target provided they exist. If we
+	  need to lock two inodes of different type (dir vs non-dir), we lock
+	  the directory first. If we need to lock two inodes of the same type,
+	  lock them in inode pointer order.
+	* Lock subdirectories involved (source before target).
+	* Lock non-directories involved, in inode pointer order.
 	* call the method.
 
-All ->i_rwsem are taken exclusive.  Again, we might get away with locking
-the the source (and target in exchange case) shared.
+All ->i_rwsem are taken exclusive.
 
 The rules above obviously guarantee that all directories that are going to be
 read, modified or removed by method will be locked by caller.
@@ -66,8 +71,10 @@
 
 Proof:
 
-	First of all, at any moment we have a partial ordering of the
-	objects - A < B iff A is an ancestor of B.
+[XXX: will be updated once we are done massaging the lock_rename()]
+	First of all, at any moment we have a linear ordering of the
+	objects - A < B iff (A is an ancestor of B) or (B is not an ancestor
+        of A and ptr(A) < ptr(B)).
 
 	That ordering can change.  However, the following is true:
 
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/filesystems/ext4/attributes.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/filesystems/ext4/attributes.rst
@@ -76,7 +76,7 @@
      - Checksum of the extended attribute block.
    * - 0x14
      - \_\_u32
-     - h\_reserved[2]
+     - h\_reserved[3]
      - Zero.
 
 The checksum is calculated against the FS UUID, the 64-bit block number
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/filesystems/fsverity.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/filesystems/fsverity.rst
@@ -226,6 +226,14 @@
 The verity flag is not settable via FS_IOC_SETFLAGS.  You must use
 FS_IOC_ENABLE_VERITY instead, since parameters must be provided.
 
+statx
+-----
+
+Since Linux v5.5, the statx() system call sets STATX_ATTR_VERITY if
+the file has fs-verity enabled.  This can perform better than
+FS_IOC_GETFLAGS and FS_IOC_MEASURE_VERITY because it doesn't require
+opening the file, and opening verity files can be expensive.
+
 Accessing verity files
 ======================
 
@@ -398,7 +406,7 @@
 ext4
 ----
 
-ext4 supports fs-verity since Linux TODO and e2fsprogs v1.45.2.
+ext4 supports fs-verity since Linux v5.4 and e2fsprogs v1.45.2.
 
 To create verity files on an ext4 filesystem, the filesystem must have
 been formatted with ``-O verity`` or had ``tune2fs -O verity`` run on
@@ -434,7 +442,7 @@
 f2fs
 ----
 
-f2fs supports fs-verity since Linux TODO and f2fs-tools v1.11.0.
+f2fs supports fs-verity since Linux v5.4 and f2fs-tools v1.11.0.
 
 To create verity files on an f2fs filesystem, the filesystem must have
 been formatted with ``-O verity``.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/filesystems/locking.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/filesystems/locking.rst
@@ -95,7 +95,7 @@
 mkdir:		exclusive
 unlink:		exclusive (both)
 rmdir:		exclusive (both)(see below)
-rename:		exclusive (all)	(see below)
+rename:		exclusive (both parents, some children)	(see below)
 readlink:	no
 get_link:	no
 setattr:	exclusive
@@ -113,6 +113,9 @@
 	Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_rwsem
 	exclusive on victim.
 	cross-directory ->rename() has (per-superblock) ->s_vfs_rename_sem.
+	->unlink() and ->rename() have ->i_rwsem exclusive on all non-directories
+	involved.
+	->rename() has ->i_rwsem exclusive on any subdirectory that changes parent.
 
 See Documentation/filesystems/directory-locking.rst for more detailed discussion
 of the locking scheme for directory operations.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/filesystems/porting.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/filesystems/porting.rst
@@ -850,3 +850,29 @@
 d_alloc_pseudo() is internal-only; uses outside of alloc_file_pseudo() are
 very suspect (and won't work in modules).  Such uses are very likely to
 be misspelled d_alloc_anon().
+
+---
+
+**mandatory**
+
+[should've been added in 2016] stale comment in finish_open() nonwithstanding,
+failure exits in ->atomic_open() instances should *NOT* fput() the file,
+no matter what.  Everything is handled by the caller.
+
+---
+
+**mandatory**
+
+If ->rename() update of .. on cross-directory move needs an exclusion with
+directory modifications, do *not* lock the subdirectory in question in your
+->rename() - it's done by the caller now [that item should've been added in
+28eceeda130f "fs: Lock moved directories"].
+
+---
+
+**mandatory**
+
+On same-directory ->rename() the (tautological) update of .. is not protected
+by any locks; just don't do it if the old parent is the same as the new one.
+We really can't lock two subdirectories in same-directory rename - not without
+deadlocks.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/filesystems/seq_file.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/filesystems/seq_file.txt
@@ -192,6 +192,12 @@
 is a reasonable thing to do. The seq_file code will also avoid taking any
 other locks while the iterator is active.
 
+The iterater value returned by start() or next() is guaranteed to be
+passed to a subsequent next() or stop() call.  This allows resources
+such as locks that were taken to be reliably released.  There is *no*
+guarantee that the iterator will be passed to show(), though in practice
+it often will be.
+
 
 Formatted output
 
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/filesystems/sysfs.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/filesystems/sysfs.txt
@@ -232,12 +232,10 @@
   is 4096. 
 
 - show() methods should return the number of bytes printed into the
-  buffer. This is the return value of scnprintf().
+  buffer.
 
-- show() must not use snprintf() when formatting the value to be
-  returned to user space. If you can guarantee that an overflow
-  will never happen you can use sprintf() otherwise you must use
-  scnprintf().
+- show() should only use sysfs_emit() or sysfs_emit_at() when formatting
+  the value to be returned to user space.
 
 - store() should return the number of bytes used from the buffer. If the
   entire buffer has been used, just return the count argument.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/filesystems/vfs.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/filesystems/vfs.rst
@@ -1173,7 +1173,7 @@
 	return
 	-ECHILD and it will be called again in ref-walk mode.
 
-``_weak_revalidate``
+``d_weak_revalidate``
 	called when the VFS needs to revalidate a "jumped" dentry.  This
 	is called when a path-walk ends at dentry that was not acquired
 	by doing a lookup in the parent directory.  This includes "/",
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/firmware-guide/acpi/apei/einj.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/firmware-guide/acpi/apei/einj.rst
@@ -168,7 +168,7 @@
   0x00000008	Memory Correctable
   0x00000010	Memory Uncorrectable non-fatal
   # echo 0x12345000 > param1		# Set memory address for injection
-  # echo $((-1 << 12)) > param2		# Mask 0xfffffffffffff000 - anywhere in this page
+  # echo 0xfffffffffffff000 > param2		# Mask - anywhere in this page
   # echo 0x8 > error_type			# Choose correctable memory error
   # echo 1 > error_inject			# Inject now
 
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/firmware-guide/acpi/dsd/data-node-references.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/firmware-guide/acpi/dsd/data-node-references.rst
@@ -5,7 +5,7 @@
 Referencing hierarchical data nodes
 ===================================
 
-:Copyright: |copy| 2018 Intel Corporation
+:Copyright: |copy| 2018, 2021 Intel Corporation
 :Author: Sakari Ailus <sakari.ailus@linux.intel.com>
 
 ACPI in general allows referring to device objects in the tree only.
@@ -52,12 +52,14 @@
 	    Name (NOD0, Package() {
 		ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
 		Package () {
+		    Package () { "reg", 0 },
 		    Package () { "random-property", 3 },
 		}
 	    })
 	    Name (NOD1, Package() {
 		ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
 		Package () {
+		    Package () { "reg", 1 },
 		    Package () { "anothernode", "ANOD" },
 		}
 	    })
@@ -74,7 +76,11 @@
 	    Name (_DSD, Package () {
 		ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
 		Package () {
-		    Package () { "reference", ^DEV0, "node@1", "anothernode" },
+		    Package () {
+			"reference", Package () {
+			    ^DEV0, "node@1", "anothernode"
+			}
+		    },
 		}
 	    })
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/hwmon/lm90.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/hwmon/lm90.rst
@@ -123,6 +123,18 @@
 
 	       http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3497
 
+  * Maxim MAX6654
+
+    Prefix: 'max6654'
+
+    Addresses scanned: I2C 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b,
+
+			   0x4c, 0x4d and 0x4e
+
+    Datasheet: Publicly available at the Maxim website
+
+	       https://www.maximintegrated.com/en/products/sensors/MAX6654.html
+
   * Maxim MAX6657
 
     Prefix: 'max6657'
@@ -253,6 +265,16 @@
 
 	       http://www.ti.com/litv/pdf/sbos686
 
+  * Texas Instruments TMP461
+
+    Prefix: 'tmp461'
+
+    Addresses scanned: I2C 0x48 through 0x4F
+
+    Datasheet: Publicly available at TI website
+
+	       https://www.ti.com/lit/gpn/tmp461
+
 Author: Jean Delvare <jdelvare@suse.de>
 
 
@@ -301,6 +323,13 @@
   * Extended temperature range (breaks compatibility)
   * Lower resolution for remote temperature
 
+MAX6654:
+  * Better local resolution
+  * Selectable address
+  * Remote sensor type selection
+  * Extended temperature range
+  * Extended resolution only available when conversion rate <= 1 Hz
+
 MAX6657 and MAX6658:
   * Better local resolution
   * Remote sensor type selection
@@ -336,8 +365,8 @@
 
 All temperature values are given in degrees Celsius. Resolution
 is 1.0 degree for the local temperature, 0.125 degree for the remote
-temperature, except for the MAX6657, MAX6658 and MAX6659 which have a
-resolution of 0.125 degree for both temperatures.
+temperature, except for the MAX6654, MAX6657, MAX6658 and MAX6659 which have
+a resolution of 0.125 degree for both temperatures.
 
 Each sensor has its own high and low limits, plus a critical limit.
 Additionally, there is a relative hysteresis value common to both critical
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/hwmon/max31790.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/hwmon/max31790.rst
@@ -38,6 +38,7 @@
 fan[1-12]_input    RO  fan tachometer speed in RPM
 fan[1-12]_fault    RO  fan experienced fault
 fan[1-6]_target    RW  desired fan speed in RPM
-pwm[1-6]_enable    RW  regulator mode, 0=disabled, 1=manual mode, 2=rpm mode
-pwm[1-6]           RW  fan target duty cycle (0-255)
+pwm[1-6]_enable    RW  regulator mode, 0=disabled (duty cycle=0%), 1=manual mode, 2=rpm mode
+pwm[1-6]           RW  read: current pwm duty cycle,
+                       write: target pwm duty cycle (0-255)
 ================== === =======================================================
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/index.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/index.rst
@@ -135,6 +135,14 @@
    mic/index
    scheduler/index
 
+Architecture-agnostic documentation
+-----------------------------------
+
+.. toctree::
+   :maxdepth: 2
+
+   asm-annotations
+
 Architecture-specific documentation
 -----------------------------------
 
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/input/joydev/joystick.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/input/joydev/joystick.rst
@@ -517,6 +517,7 @@
 * AVB Mag Turbo Force
 * AVB Top Shot Pegasus
 * AVB Top Shot Force Feedback Racing Wheel
+* Boeder Force Feedback Wheel
 * Logitech WingMan Force
 * Logitech WingMan Force Wheel
 * Guillemot Race Leader Force Feedback
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/ioctl/ioctl-number.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/ioctl/ioctl-number.rst
@@ -301,7 +301,6 @@
 0x89  00-06  arch/x86/include/asm/sockios.h
 0x89  0B-DF  linux/sockios.h
 0x89  E0-EF  linux/sockios.h                                         SIOCPROTOPRIVATE range
-0x89  E0-EF  linux/dn.h                                              PROTOPRIVATE range
 0x89  F0-FF  linux/sockios.h                                         SIOCDEVPRIVATE range
 0x8B  all    linux/wireless.h
 0x8C  00-3F                                                          WiNRADiO driver
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kbuild/index.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kbuild/index.rst
@@ -19,6 +19,7 @@
 
     issues
     reproducible-builds
+    llvm
 
 .. only::  subproject and html
 
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kbuild/kbuild.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kbuild/kbuild.rst
@@ -262,3 +262,8 @@
 These two variables allow to override the user@host string displayed during
 boot and in /proc/version. The default value is the output of the commands
 whoami and host, respectively.
+
+LLVM
+----
+If this variable is set to 1, Kbuild will use Clang and LLVM utilities instead
+of GCC and GNU binutils to build the kernel.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kbuild/llvm.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kbuild/llvm.rst
@@ -0,0 +1,87 @@
+==============================
+Building Linux with Clang/LLVM
+==============================
+
+This document covers how to build the Linux kernel with Clang and LLVM
+utilities.
+
+About
+-----
+
+The Linux kernel has always traditionally been compiled with GNU toolchains
+such as GCC and binutils. Ongoing work has allowed for `Clang
+<https://clang.llvm.org/>`_ and `LLVM <https://llvm.org/>`_ utilities to be
+used as viable substitutes. Distributions such as `Android
+<https://www.android.com/>`_, `ChromeOS
+<https://www.chromium.org/chromium-os>`_, and `OpenMandriva
+<https://www.openmandriva.org/>`_ use Clang built kernels.  `LLVM is a
+collection of toolchain components implemented in terms of C++ objects
+<https://www.aosabook.org/en/llvm.html>`_. Clang is a front-end to LLVM that
+supports C and the GNU C extensions required by the kernel, and is pronounced
+"klang," not "see-lang."
+
+Clang
+-----
+
+The compiler used can be swapped out via `CC=` command line argument to `make`.
+`CC=` should be set when selecting a config and during a build.
+
+	make CC=clang defconfig
+
+	make CC=clang
+
+Cross Compiling
+---------------
+
+A single Clang compiler binary will typically contain all supported backends,
+which can help simplify cross compiling.
+
+	ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make CC=clang
+
+`CROSS_COMPILE` is not used to prefix the Clang compiler binary, instead
+`CROSS_COMPILE` is used to set a command line flag: `--target <triple>`. For
+example:
+
+	clang --target aarch64-linux-gnu foo.c
+
+LLVM Utilities
+--------------
+
+LLVM has substitutes for GNU binutils utilities. Kbuild supports `LLVM=1`
+to enable them.
+
+	make LLVM=1
+
+They can be enabled individually. The full list of the parameters:
+
+	make CC=clang LD=ld.lld AR=llvm-ar NM=llvm-nm STRIP=llvm-strip \\
+	  OBJCOPY=llvm-objcopy OBJDUMP=llvm-objdump OBJSIZE=llvm-size \\
+	  READELF=llvm-readelf HOSTCC=clang HOSTCXX=clang++ HOSTAR=llvm-ar \\
+	  HOSTLD=ld.lld
+
+Currently, the integrated assembler is disabled by default. You can pass
+`LLVM_IAS=1` to enable it.
+
+Getting Help
+------------
+
+- `Website <https://clangbuiltlinux.github.io/>`_
+- `Mailing List <https://groups.google.com/forum/#!forum/clang-built-linux>`_: <clang-built-linux@googlegroups.com>
+- `Issue Tracker <https://github.com/ClangBuiltLinux/linux/issues>`_
+- IRC: #clangbuiltlinux on chat.freenode.net
+- `Telegram <https://t.me/ClangBuiltLinux>`_: @ClangBuiltLinux
+- `Wiki <https://github.com/ClangBuiltLinux/linux/wiki>`_
+- `Beginner Bugs <https://github.com/ClangBuiltLinux/linux/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22>`_
+
+Getting LLVM
+-------------
+
+- http://releases.llvm.org/download.html
+- https://github.com/llvm/llvm-project
+- https://llvm.org/docs/GettingStarted.html
+- https://llvm.org/docs/CMake.html
+- https://apt.llvm.org/
+- https://www.archlinux.org/packages/extra/x86_64/llvm/
+- https://github.com/ClangBuiltLinux/tc-build
+- https://github.com/ClangBuiltLinux/linux/wiki/Building-Clang-from-source
+- https://android.googlesource.com/platform/prebuilts/clang/host/linux-x86/
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kbuild/makefiles.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kbuild/makefiles.rst
@@ -1115,23 +1115,6 @@
 	In this example, extra-y is used to list object files that
 	shall be built, but shall not be linked as part of built-in.a.
 
-    header-test-y
-
-	header-test-y specifies headers (`*.h`) in the current directory that
-	should be compile tested to ensure they are self-contained,
-	i.e. compilable as standalone units. If CONFIG_HEADER_TEST is enabled,
-	this builds them as part of extra-y.
-
-    header-test-pattern-y
-
-	This works as a weaker version of header-test-y, and accepts wildcard
-	patterns. The typical usage is::
-
-		header-test-pattern-y += *.h
-
-	This specifies all the files that matches to `*.h` in the current
-	directory, but the files in 'header-test-' are excluded.
-
 6.7 Commands useful for building a boot image
 ---------------------------------------------
 
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kbuild/modules.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kbuild/modules.rst
@@ -470,9 +470,9 @@
 
 	The syntax of the Module.symvers file is::
 
-	<CRC>       <Symbol>          <Namespace>  <Module>                         <Export Type>
+	<CRC>       <Symbol>         <Module>                         <Export Type>     <Namespace>
 
-	0xe1cc2a05  usb_stor_suspend  USB_STORAGE  drivers/usb/storage/usb-storage  EXPORT_SYMBOL_GPL
+	0xe1cc2a05  usb_stor_suspend drivers/usb/storage/usb-storage  EXPORT_SYMBOL_GPL USB_STORAGE
 
 	The fields are separated by tabs and values may be empty (e.g.
 	if no namespace is defined for an exported symbol).
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kernel-hacking/locking.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kernel-hacking/locking.rst
@@ -976,7 +976,7 @@
 
             while (list) {
                     struct foo *next = list->next;
-                    del_timer(&list->timer);
+                    timer_delete(&list->timer);
                     kfree(list);
                     list = next;
             }
@@ -990,7 +990,7 @@
 the element (which has already been freed!).
 
 This can be avoided by checking the result of
-:c:func:`del_timer()`: if it returns 1, the timer has been deleted.
+:c:func:`timer_delete()`: if it returns 1, the timer has been deleted.
 If 0, it means (in this case) that it is currently running, so we can
 do::
 
@@ -999,7 +999,7 @@
 
                     while (list) {
                             struct foo *next = list->next;
-                            if (!del_timer(&list->timer)) {
+                            if (!timer_delete(&list->timer)) {
                                     /* Give timer a chance to delete this */
                                     spin_unlock_bh(&list_lock);
                                     goto retry;
@@ -1014,9 +1014,13 @@
 Another common problem is deleting timers which restart themselves (by
 calling :c:func:`add_timer()` at the end of their timer function).
 Because this is a fairly common case which is prone to races, you should
-use :c:func:`del_timer_sync()` (``include/linux/timer.h``) to
-handle this case. It returns the number of times the timer had to be
-deleted before we finally stopped it from adding itself back in.
+use :c:func:`timer_delete_sync()` (``include/linux/timer.h``) to
+handle this case.
+
+Before freeing a timer, timer_shutdown() or timer_shutdown_sync() should be
+called which will keep it from being rearmed. Any subsequent attempt to
+rearm the timer will be silently ignored by the core code.
+
 
 Locking Speed
 =============
@@ -1344,7 +1348,7 @@
 
 -  :c:func:`kfree()`
 
--  :c:func:`add_timer()` and :c:func:`del_timer()`
+-  :c:func:`add_timer()` and :c:func:`timer_delete()`
 
 Mutex API reference
 ===================
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/IPVS
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/IPVS
@@ -0,0 +1,81 @@
+/*? Text: "%s(): NULL arg\n" */
+/*? Text: "%s(): NULL scheduler_name\n" */
+/*? Text: "%s(): [%s] pe already existed in the system\n" */
+/*? Text: "%s(): [%s] pe already linked\n" */
+/*? Text: "%s(): [%s] pe is not in the list. failed\n" */
+/*? Text: "%s(): [%s] scheduler already existed in the system\n" */
+/*? Text: "%s(): [%s] scheduler already linked\n" */
+/*? Text: "%s(): [%s] scheduler is not in the list. failed\n" */
+/*? Text: "%s(): done error\n" */
+/*? Text: "%s(): init error\n" */
+/*? Text: "%s(): lower threshold is higher than upper threshold\n" */
+/*? Text: "%s(): no memory\n" */
+/*? Text: "%s(): request for already hashed, called from %pF\n" */
+/*? Text: "%s(): request for unhash flagged, called from %pF\n" */
+/*? Text: "%s(): server weight less than zero\n" */
+/*? Text: "%s: %s %pI4:%d - %s\n" */
+/*? Text: "%s: %s [%pI6]:%d - %s\n" */
+/*? Text: "%s: %s [%pI6c]:%d - %s\n" */
+/*? Text: "%s: FWM %u 0x%08X - %s\n" */
+/*? Text: "%s: enter\n" */
+/*? Text: "%s: loaded support on port[%d] = %d\n" */
+/*? Text: "BACKUP v0, Dropping buffer bogus conn options\n" */
+/*? Text: "BACKUP v0, bogus conn\n" */
+/*? Text: "BACKUP, Dropping buffer, Err: %d in decoding\n" */
+/*? Text: "BACKUP, Dropping buffer, Unknown version %d\n" */
+/*? Text: "BACKUP, Dropping buffer, msg > buffer\n" */
+/*? Text: "BACKUP, Dropping buffer, to small\n" */
+/*? Text: "BACKUP, Invalid PE parameters\n" */
+/*? Text: "BUG control DEL with n=0 : %s:%d to %s:%d\n" */
+/*? Text: "Connection hash table configured (size=%d, memory=%ldKbytes)\n" */
+/*? Text: "Error binding address of the mcast interface\n" */
+/*? Text: "Error binding to the multicast addr\n" */
+/*? Text: "Error connecting to the multicast addr\n" */
+/*? Text: "Error during creation of socket; terminating\n" */
+/*? Text: "Error joining to the multicast group\n" */
+/*? Text: "Error setting outbound mcast interface\n" */
+/*? Text: "Failed to stop Backup Daemon\n" */
+/*? Text: "Failed to stop Master Daemon\n" */
+/*? Text: "Registered protocols (%s)\n" */
+/*? Text: "SYNC, connection pe_data invalid\n" */
+/*? Text: "Schedule: port zero only supported in persistent services, check your ipvs configuration\n" */
+/*? Text: "Scheduler module ip_vs_%s not found\n" */
+/*? Text: "There is no net ptr to find in the skb in %s() line:%d\n" */
+/*? Text: "UDP no ns data\n" */
+/*? Text: "You probably need to specify IP address on multicast interface.\n" */
+/*? Text: "[%s] pe registered.\n" */
+/*? Text: "[%s] pe unregistered.\n" */
+/*? Text: "[%s] scheduler registered.\n" */
+/*? Text: "[%s] scheduler unregistered.\n" */
+/*? Text: "can't register hooks.\n" */
+/*? Text: "can't register netlink/ioctl.\n" */
+/*? Text: "can't setup connection table.\n" */
+/*? Text: "can't setup control.\n" */
+/*? Text: "cannot register Generic Netlink interface.\n" */
+/*? Text: "cannot register sockopt.\n" */
+/*? Text: "get_ctl: len %u < %u\n" */
+/*? Text: "ip_vs_send_async error %d\n" */
+/*? Text: "ip_vs_sync_buff_create failed.\n" */
+/*? Text: "ipvs loaded.\n" */
+/*? Text: "ipvs unloaded.\n" */
+/*? Text: "length: %u != %u\n" */
+/*? Text: "netif_stop_queue() cannot be called before register_netdev()\n" */
+/*? Text: "not enough space in Netlink message\n" */
+/*? Text: "persistence engine module ip_vs_pe_%s not found\n" */
+/*? Text: "receiving message error\n" */
+/*? Text: "request control ADD for already controlled: %s:%d to %s:%d\n" */
+/*? Text: "request control DEL for uncontrolled: %s:%d to %s:%d\n" */
+/*? Text: "set_ctl: invalid protocol: %d %pI4:%d %s\n" */
+/*? Text: "set_ctl: len %u != %u\n" */
+/*? Text: "shouldn't reach here, because the box is on the half connection in the tun/dr module.\n" */
+/*? Text: "stopping backup sync thread %d ...\n" */
+/*? Text: "stopping master sync thread %d ...\n" */
+/*? Text: "sync thread started: state = BACKUP, mcast_ifn = %s, syncid = %d\n" */
+/*? Text: "sync thread started: state = MASTER, mcast_ifn = %s, syncid = %d\n" */
+/*? Text: "unknown Generic Netlink command\n" */
+/*? Text: "sync thread started: state = MASTER, mcast_ifn = %s, syncid = %d, id = %d\n" */
+/*? Text: "sync thread started: state = BACKUP, mcast_ifn = %s, syncid = %d, id = %d\n" */
+/*? Text: "flen=%u proglen=%u pass=%u image=%pK from=%s pid=%d\n" */
+/*? Text: "%s selects TX queue %d, but real number of TX queues is %d\n" */
+/*? Text: "Unknown mcast interface: %s\n" */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/aes_s390
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/aes_s390
@@ -0,0 +1,45 @@
+/*?
+ * Text: "Allocating XTS fallback algorithm %s failed\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: algorithm name
+ * Description:
+ * The aes_s390 module failed to allocate a software fallback for the AES
+ * modes that are not supported by the hardware. A possible reason for this
+ * problem is that the aes_generic module that provides the fallback
+ * algorithms is not available.
+ * User action:
+ * Ensure that the aes_generic module is available and loaded and reload
+ * the aes_s390 module.
+ */
+
+/*?
+ * Text: "Allocating AES fallback algorithm %s failed\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: algorithm name
+ * Description:
+ * The advanced encryption standard (AES) algorithm includes three modes with
+ * 128-bit, 192-bit, and 256-bit keys. Your hardware system only provides
+ * hardware acceleration for the 128-bit mode. The aes_s390 module failed to
+ * allocate a software fallback for the AES modes that are not supported by the
+ * hardware. A possible reason for this problem is that the aes_generic module
+ * that provides the fallback algorithms is not available.
+ * User action:
+ * Use the 128-bit mode only or ensure that the aes_generic module is available
+ * and loaded and reload the aes_s390 module.
+ */
+
+/*?
+ * Text: "AES hardware acceleration is only available for 128-bit keys\n"
+ * Severity: Informational
+ * Description:
+ * The advanced encryption standard (AES) algorithm includes three modes with
+ * 128-bit, 192-bit, and 256-bit keys. Your hardware system only provides
+ * hardware acceleration for the 128-bit key mode. The aes_s390 module
+ * will use the less performant software fallback algorithm for the 192-bit
+ * and 256-bit key modes.
+ * User action:
+ * None.
+ */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/af_iucv
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/af_iucv
@@ -0,0 +1,23 @@
+/*?
+ * Text: "Application %s on z/VM guest %s exceeds message limit\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: application name
+ *   @2: z/VM user ID
+ * Description:
+ * Messages or packets destined for the application have accumulated and
+ * reached the maximum value. The default for the message limit is 65535.
+ * You can specify a different limit as the value for MSGLIMIT within
+ * the IUCV statement of the z/VM virtual machine on which the application
+ * runs.
+ * User action:
+ * Ensure that you do not send data faster than the application retrieves
+ * them. Ensure that the message limit on the z/VM guest virtual machine
+ * on which the application runs is high enough.
+ */
+
+/*? Text: "Attempt to release alive iucv socket %p\n" */
+/*? Text: "netif_stop_queue() cannot be called before register_netdev()\n" */
+/*? Text: "flen=%u proglen=%u pass=%u image=%pK from=%s pid=%d\n" */
+/*? Text: "%s selects TX queue %d, but real number of TX queues is %d\n" */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/ap
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/ap
@@ -0,0 +1,49 @@
+/*?
+ * Text: "%d is not a valid cryptographic domain\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: AP  domain index
+ * Description:
+ * The cryptographic domain specified for the 'domain=' module or kernel
+ * parameter must be an integer in the range 0 to 15.
+ * User action:
+ * Reload the cryptographic device driver with a correct module parameter.
+ * If the device driver has been compiled into the kernel, correct the value
+ * in the kernel parameter line and reboot Linux.
+ */
+
+/*?
+ * Text: "The hardware system does not support AP instructions\n"
+ * Severity: Warning
+ * Description:
+ * The ap module addresses AP adapters through AP instructions. The hardware
+ * system on which the Linux instance runs does not support AP instructions.
+ * The ap module cannot detect any AP adapters.
+ * User action:
+ * Load the ap module only if your Linux instance runs on hardware that
+ * supports AP instructions. If the ap module has been compiled into the kernel,
+ * ignore this message.
+ */
+
+/*?
+ * Text: "Registering adapter interrupts for AP device %02x.%04x failed\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: AP device ID
+ *   @2: AP queue
+ * Description:
+ * The hardware system supports AP adapter interrupts but failed to enable
+ * an adapter for interrupts. Possible causes for this error are:
+ * i)   The AP adapter firmware does not support AP interrupts.
+ * ii)  An AP adapter firmware update to a firmware level that supports AP
+ *      adapter interrupts failed.
+ * iii) The AP adapter firmware has been successfully updated to a level that
+ *      supports AP interrupts but the new firmware has not been activated.
+ * User action:
+ * Ensure that the firmware on your AP adapters support AP interrupts and that
+ * any firmware updates have completed successfully. If necessary, deconfigure
+ * your cryptographic adapters and reconfigure them to ensure that any firmware
+ * updates become active, then reload the ap module. If the ap module has been
+ * compiled into the kernel, reboot Linux.
+ */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/appldata
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/appldata
@@ -0,0 +1,91 @@
+/*?
+ * Text: "Starting the data collection for %s failed with rc=%d\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: appldata module
+ *   @2: return code
+ * Description:
+ * The specified data collection module used the z/VM diagnose call
+ * DIAG 0xDC to start writing data. z/VM returned an error and the data
+ * collection could not start. If the return code is 5, your z/VM guest
+ * virtual machine is not authorized to write data records.
+ * User action:
+ * If the return code is 5, ensure that your z/VM guest virtual machine's
+ * entry in the z/VM directory includes the OPTION APPLMON statement.
+ * For other return codes see the section about DIAGNOSE Code X'DC'
+ * in "z/VM CP Programming Services".
+ */
+
+/*?
+ * Text: "Stopping the data collection for %s failed with rc=%d\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: appldata module
+ *   @2: return code
+ * Description:
+ * The specified data collection module used the z/VM diagnose call DIAG 0xDC
+ * to stop writing data. z/VM returned an error and the data collection
+ * continues.
+ * User action:
+ * See the section about DIAGNOSE Code X'DC' in "z/VM CP Programming Services".
+ */
+
+/*?
+ * Text: "Starting a new OS data collection failed with rc=%d\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: return code
+ * Description:
+ * After a CPU hotplug event, the record size for the running operating
+ * system data collection is no longer correct. The appldata_os module tried
+ * to start a new data collection with the correct record size but received
+ * an error from the z/VM diagnose call DIAG 0xDC. Any data collected with
+ * the current record size might be faulty.
+ * User action:
+ * Start a new data collection with the cappldata_os module. For information
+ * about starting data collections see "Device Drivers, Features, and
+ * Commands". For information about the return codes see the section about
+ * DIAGNOSE Code X'DC' in "z/VM CP Programming Services".
+ */
+
+/*?
+ * Text: "Stopping a faulty OS data collection failed with rc=%d\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: return code
+ * Description:
+ * After a CPU hotplug event, the record size for the running operating
+ * system data collection is no longer correct. The appldata_os module tried
+ * to stop the faulty data collection but received an error from the z/VM
+ * diagnose call DIAG 0xDC. Any data collected with the current record size
+ * might be faulty.
+ * User action:
+ * Try to restart appldata_os monitoring. For information about stopping
+ * and starting data collections see "Device Drivers, Features, and
+ * Commands". For information about the return codes see the section about
+ * DIAGNOSE Code X'DC' in "z/VM CP Programming Services".
+ */
+
+/*?
+ * Text: "Maximum OS record size %i exceeds the maximum record size %i\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: no of bytes
+ *   @2: no of bytes
+ * Description:
+ * The OS record size grows with the number of CPUs and is adjusted by the
+ * appldata_os module in response to CPU hotplug events. For more than 110
+ * CPUs the record size would exceed the maximum record size of 4024 bytes
+ * that is  supported by the z/VM hypervisor. To prevent the maximum supported
+ * record size from being exceeded while data collection is in progress,
+ * you cannot load the appldata_os module on Linux instances that are
+ * configured for a maximum of more than 110 CPUs.
+ * User action:
+ * If you do not want to collect operating system data, you can ignore this
+ * message. If you want to collect operating system data, reconfigure your
+ * Linux instance to support less than 110 CPUs.
+ */
+
+/*? Text: "netif_stop_queue() cannot be called before register_netdev()\n" */
+/*? Text: "%s selects TX queue %d, but real number of TX queues is %d\n" */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/bpf_jit
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/bpf_jit
@@ -0,0 +1,16 @@
+/*? Text: "flen=%u proglen=%u pass=%u image=%pK from=%s pid=%d\n" */
+/*? Text: "%s selects TX queue %d, but real number of TX queues is %d\n" */
+/*? Text: "netif_stop_queue() cannot be called before register_netdev()\n" */
+
+/*?
+ * Text: "Unknown opcode %02x\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: Instruction opcode
+ * Description:
+ * The BPF JIT compiler has found an unknown instruction in the BPF program
+ * and therefore stops the compilation. As a fallback, the interpreter is used.
+ * User action:
+ * Report this problem and the error message to your support organization.
+ */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/cio
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/cio
@@ -0,0 +1,247 @@
+/*?
+ * Text: "%s is not a valid device for the cio_ignore kernel parameter\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: device bus-ID
+ * Description:
+ * The device specification for the cio_ignore kernel parameter is
+ * syntactically incorrect or specifies an unknown device. This device is not
+ * excluded from being sensed and analyzed.
+ * User action:
+ * Correct your device specification in the kernel parameter line to have the
+ * device excluded when you next reboot Linux. You can write the correct
+ * device specification to /proc/cio_ignore to add the device to the list of
+ * devices to be excluded. This does not immediately make the device
+ * inaccessible but the device is ignored if it disappears and later reappears.
+ */
+
+/*?
+ * Text: "0.%x.%04x to 0.%x.%04x is not a valid range for cio_ignore\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: from subchannel set ID
+ *   @2: from device number
+ *   @3: to subchannel set ID
+ *   @4: to device number
+ * Description:
+ * The device range specified for the cio_ignore kernel parameter is
+ * syntactically incorrect. No devices specified with this range are
+ * excluded from being sensed and analyzed.
+ * User action:
+ * Correct your range specification in the kernel parameter line to have the
+ * range of devices  excluded when you next reboot Linux. You can write the
+ * correct range specification to /proc/cio_ignore to add the range of devices
+ * to the list of devices to be excluded. This does not immediately make the
+ * devices in the range inaccessible but any of these devices are ignored if
+ * they disappear and later reappear.
+ */
+
+/*?
+ * Text: "Processing %s for channel path %x.%02x\n"
+ * Severity: Notice
+ * Parameter:
+ *   @1: configuration change
+ *   @2: channel subsystem ID
+ *   @3: CHPID
+ * Description:
+ * A configuration change is in progress for the given channel path.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "No CCW console was found\n"
+ * Severity: Warning
+ * Description:
+ * Linux did not find the expected CCW console and tries to use an alternative
+ * console. A possible reason why the console was not found is that the console
+ * has been specified in the cio_ignore list.
+ * User action:
+ * None, if an appropriate alternative console has been found, and you want
+ * to use this alternative console. If you want to use the CCW console, ensure
+ * that is not specified in the cio_ignore list, explicitly specify the console
+ * with the 'condev=' kernel parameter, and reboot Linux.
+ */
+
+/*?
+ * Text: "Channel measurement facility initialized using format %s (mode %s)\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: format
+ *   @2: mode
+ * Description:
+ * The channel measurement facility has been initialized successfully.
+ * Format 'extended' should be used for z990 and later mainframe systems.
+ * Format 'basic' is intended for earlier mainframes. Mode 'autodetected' means
+ * that the format has been set automatically. Mode 'parameter' means that the
+ * format has been set according to the 'format=' kernel parameter.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "The CSS device driver initialization failed with errno=%d\n"
+ * Severity: Alert
+ * Parameter:
+ *   @1: Return code
+ * Description:
+ * The channel subsystem bus could not be established.
+ * User action:
+ * See the errno man page to find out what caused the problem.
+ */
+ /*? Text: "%s: Got subchannel machine check but no sch_event handler provided.\n" */
+
+/*?
+ * Text: "%s: Setting the device online failed because it is boxed\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: Device bus-ID
+ * Description:
+ * Initialization of a device did not complete because it did not respond in
+ * time or it was reserved by another operating system.
+ * User action:
+ * Make sure that the device is working correctly, then try again to set it
+ * online. For devices that support the reserve/release mechanism (for example
+ * DASDs), you can try to override the reservation of the other system by
+ * writing 'force' to the 'online' sysfs attribute of the affected device.
+ */
+
+/*?
+ * Text: "%s: Setting the device online failed because it is not operational\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: Device bus-ID
+ * Description:
+ * Initialization of a device did not complete because it is not present or
+ * not operational.
+ * User action:
+ * Make sure that the device is present and working correctly, then try again
+ * to set it online.
+ */
+
+/*?
+ * Text: "%s: The device stopped operating while being set offline\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: Device bus-ID
+ * Description:
+ * While the device was set offline, it was not present or not operational.
+ * The device is now inactive, but setting it online again might fail.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "%s: The device entered boxed state while being set offline\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: Device bus-ID
+ * Description:
+ * While the device was set offline, it did not respond in time or it was
+ * reserved by another operating system. The device is now inactive, but
+ * setting it online again might fail.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "Logging for subchannel 0.%x.%04x failed with errno=%d\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: subchannel set ID
+ *   @2: subchannel number
+ *   @3: errno
+ * Description:
+ * Capturing model-dependent logs and traces could not be triggered for the
+ * specified subchannel.
+ * User action:
+ * See the errno man page to find out what caused the problem.
+ */
+
+/*?
+ * Text: "Logging for subchannel 0.%x.%04x was triggered\n"
+ * Severity: Notice
+ * Parameter:
+ *   @1: subchannel set ID
+ *   @2: subchannel number
+ * Description:
+ * Model-dependent logs and traces may be captured for the specified
+ * subchannel.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "%s: No interrupt was received within %lus (CS=%02x, DS=%02x, CHPID=%x.%02x)\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: device number
+ *   @2: timeout value
+ *   @3: channel status
+ *   @4: device status
+ *   @5: channel subsystem ID
+ *   @6: CHPID
+ * Description:
+ * Internal I/Os are used by the common I/O layer to ensure that devices are
+ * operational and accessible.
+ * The common I/O layer did not receive an interrupt for an internal I/O
+ * during the specified timeout period.
+ * As a result, the device might assume a state that makes the device
+ * unusable to Linux until the problem is resolved.
+ * User action:
+ * Make sure that the device is working correctly and try the action again.
+ */
+
+/*?
+ * Text: "Link stopped: RS=%02x RSID=%04x IC=%02x IUPARAMS=%s IUNODEID=%s AUPARAMS=%s AUNODEID=%s\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: reporting source
+ *   @2: reporting source ID
+ *   @3: incident code
+ *   @4: incident unit parameters
+ *   @5: incident unit node ID
+ *   @6: attached unit parameters
+ *   @7: attached unit node ID
+ *
+ * Description:
+ * A hardware error has occurred. A unit at one end of an interface
+ * link has detected a failure in the link or in one of the units attached to
+ * the link. As a result, data transfer across the link has stopped. In the
+ * message text, the node IDs of involved units are represented in the
+ * following format: TTTTTT/MDL,MMM.PPSSSSSSSSSSSS,XXXX where TTTTTT refers to
+ * the machine type, MDL the model number, MMM the manufacturer, PP the
+ * manufacturing plant, SSSSSSSSSSSS the unit sequence number and XXXX the
+ * machine type-dependent physical interface number. If no data is available
+ * for the unit parameters or node ID field, "n/a" is used instead.
+ *
+ * User action:
+ * Report the problem to your support organization.
+ */
+
+/*?
+ * Text: "Link degraded: RS=%02x RSID=%04x IC=%02x IUPARAMS=%s IUNODEID=%s AUPARAMS=%s AUNODEID=%s\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: reporting source
+ *   @2: reporting source ID
+ *   @3: incident code
+ *   @4: incident unit parameters
+ *   @5: incident unit node ID
+ *   @6: attached unit parameters
+ *   @7: attached unit node ID
+ * Description:
+ * A hardware error has occurred. A unit at one end of an interface
+ * link has detected a failure in the link or in one of the units attached to
+ * the link. As a result, data transfer across the link is degraded. In the
+ * message text, the node IDs of involved units are represented in the
+ * following format: TTTTTT/MDL,MMM.PPSSSSSSSSSSSS,XXXX where TTTTTT refers to
+ * the machine type, MDL the model number, MMM the manufacturer, PP the
+ * manufacturing plant, SSSSSSSSSSSS the unit sequence number and XXXX the
+ * machine type-dependent physical interface number. If no data is available
+ * for the unit parameters or node ID field, "n/a" is used instead.
+ *
+ * User action:
+ * Report the problem to your support organization.
+ */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/cpcmd
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/cpcmd
@@ -0,0 +1,16 @@
+/*?
+ * Text: "The cpcmd kernel function failed to allocate a response buffer\n"
+ * Severity: Warning
+ * Description:
+ * IPL code, console detection, and device drivers like vmcp or vmlogrdr use
+ * the cpcmd kernel function to send commands to the z/VM control program (CP).
+ * If a program that uses the cpcmd function does not allocate a contiguous
+ * response buffer below 2 GB guest real storage, cpcmd creates a bounce buffer
+ * to be used as the response buffer. Because of low memory or memory
+ * fragmentation, cpcmd could not create the bounce buffer.
+ * User action:
+ * Look for related page allocation failure messages and at the stack trace to
+ * find out which program or operation failed. Free some memory and retry the
+ * failed operation. Consider allocating more memory to your z/VM guest virtual
+ * machine.
+ */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/cpu
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/cpu
@@ -0,0 +1,46 @@
+/*?
+ * Text: "%d configured CPUs, %d standby CPUs\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: number of configured CPUs
+ *   @2: number of standby CPUs
+ * Description:
+ * The kernel detected the given number of configured and standby CPUs.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "The CPU configuration topology of the machine is:"
+ * Severity: Informational
+ * Description:
+ * The first six values of the topology information represent fields Mag6 to
+ * Mag1 of system-information block (SYSIB) 15.1.2. These fields specify the
+ * maximum numbers of topology-list entries (TLE) at successive topology nesting
+ * levels. The last value represents the MNest value of SYSIB 15.1.2 which
+ * specifies the maximum possible nesting that can be configured through
+ * dynamic changes. For details see the SYSIB 15.1.2 information in the
+ * "Principles of Operation."
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "CPU %i exceeds the maximum %i and is excluded from the dump\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: CPU number
+ *   @2: maximum CPU number
+ * Description:
+ * The Linux kernel is used as a system dumper but it runs on more CPUs than
+ * it has been compiled for with the CONFIG_NR_CPUS kernel configuration
+ * option. The system dump will be created but information on one or more
+ * CPUs will be missing.
+ * User action:
+ * Update the system dump kernel to a newer version that supports more
+ * CPUs or reduce the number of installed CPUs and reproduce the problem
+ * that should be analyzed. If you send the system dump that prompted this
+ * message to a support organization, be sure to communicate that the dump
+ * does not include all CPU information.
+ */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/cpum_cf
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/cpum_cf
@@ -0,0 +1,68 @@
+/*?
+ * Text: "Enabling the performance measuring unit failed with rc=%x\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: error condition
+ * Description:
+ * The device driver failed to enable CPU counter sets with the
+ * load counter controls (lcctl) instruction.
+ * See the section about lcctl in "The Load-Program-Parameter and the CPU-Measurement
+ * Facilities", SA23-2260, for an explanation of the error conditions.
+ * User action:
+ * Stop the performance measurement programs and try again.
+ */
+
+/*?
+ * Text: "Disabling the performance measuring unit failed with rc=%x\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: error condition
+ * Description:
+ * The device driver failed to disable CPU counter sets with the
+ * load counter controls (lcctl) instruction.
+ * See the section about lcctl in "The Load-Program-Parameter and the CPU-Measurement
+ * Facilities", SA23-2260, for an explanation of the error conditions.
+ * User action:
+ * Stop the performance measurement programs and try again.
+ */
+
+/*?
+ * Text: "Registering the cpum_cf PMU failed with rc=%i\n"
+ * Severity: Error
+ * Parameter:
+ *  @1: error code
+ * Description:
+ * The device driver could not register the Performance Measurement Unit (PMU)
+ * for the CPU-measurement counter facility.
+ * A possible cause of this problem is memory constraints.
+ * User action:
+ * If the error code is -12 (ENOMEM), consider assigning more memory
+ * to your Linux instance.
+ */
+
+/*?
+ * Text: "CPU[%i] Counter data was lost\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: cpu number
+ * Description:
+ * CPU counter data was lost because of machine internal
+ * high-priority activities.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "Registering for CPU-measurement alerts failed with rc=%i\n"
+ * Severity: Error
+ * Parameter:
+ *  @1: error code
+ * Description:
+ * The device driver could not register to receive CPU-measurement alerts.
+ * Alerts make you aware of measurement errors.
+ * A possible cause of this problem is memory constraints.
+ * User action:
+ * If the error code is -12 (ENOMEM), consider assigning more memory
+ * to your Linux instance.
+ */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/cpum_sf
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/cpum_sf
@@ -0,0 +1,104 @@
+/*?
+ * Text: "The sampling buffer limits have changed to: min=%lu max=%lu (diag=x%lu)\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: minimum size in sample-data-blocks
+ *   @2: maximum size in sample-data-blocks
+ *   @3: size factor for buffering diagnostic-sampling data entries
+ * Description:
+ * The minimum or maximum size limit for the sampling facility buffer was
+ * changed.  The change is effective immediately.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "Switching off the sampling facility failed with rc=%i\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: error condition
+ * Description:
+ * The CPU-measurement sampling facility could not be switched off and continues
+ * to run.  For details, see LOAD SAMPLING CONTROLS in
+ * "The Load-Program-Parameter and the CPU-Measurement Facilities", SA23-2260.
+ * User action:
+ * If this problem persists, reboot your Linux instance.
+ */
+
+/*?
+ * Text: "Sample data was lost\n"
+ * Severity: Error
+ * Description:
+ * Sample data was lost because of machine-internal high-priority activities.
+ * The sampling facility is stopped.
+ * User action:
+ * End all performance measurement sessions.  Discard the measurement data,
+ * which are likely to be flawed.  Repeat your measurements.
+ * If the problem persists, contact your hardware administrator.
+ */
+
+/*?
+ * Text: "Sampling facility support for perf is not available: reason=%04x\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: reason code
+ * Description:
+ * The device driver could not initialize the sampling facility support.
+ * Possible reason codes are:
+ * 0001: The device driver failed to query CPU-measurement sampling facility
+ *	 information.
+ *
+ * 0002: The device driver does not support the basic-sampling function that
+ *	 is available on the LPAR within which the Linux instance runs.
+ *
+ * 0003: The device driver could not register to receive CPU-measurement alerts.
+ *	 A possible cause of this problem is memory constraints.
+ *
+ * 0004: The device driver could not register the Performance Measurement Unit
+ *	 (PMU) for the CPU-measurement sampling facility.
+ *	 A possible cause of this problem is memory constraints.
+ * User action:
+ * Consider assigning more memory to your Linux instance.
+ */
+
+/*?
+ * Text: "Loading sampling controls failed: op=%i err=%i\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: Type of operation
+ *   @2: Error condition
+ * Description:
+ * The sampling facility support could not load sampling controls to enable
+ * (operation type 1) or disable (operation type 2) the CPU-measurement sampling
+ * facility.  For details of the error condition, see LOAD SAMPLING CONTROLS in
+ * "The Load-Program-Parameter and the CPU-Measurement Facilities", SA23-2260.
+ * User action:
+ * If the problem persists, reboot your Linux instance.
+ */
+
+/*?
+ * Text: "A sampling buffer entry is incorrect (alert=0x%x)\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: Alert code
+ * Description:
+ * An incorrect sampling facility buffer entry was detected. The alert code
+ * indicates the root cause, for example, an incorrect entry address or an
+ * incorrect sample-data-block-table entry.
+ * User action:
+ * End active performance measurement sessions, for example, perf processes. If
+ * the problem persists, reboot your Linux instance.
+ */
+
+/*?
+ * Text: "Registering for s390dbf failed\n"
+ * Severity: Error
+ * Description:
+ * The device driver failed to register for the s390 debug feature.  You will
+ * not receive any debug information.  A possible cause of this problem is
+ * memory constraints.
+ * User action:
+ * Consider assigning more memory
+ * to your Linux instance.
+ */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/crc32-vx
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/crc32-vx
@@ -0,0 +1 @@
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/ctcm
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/ctcm
@@ -0,0 +1,202 @@
+/*?
+ * Text: "%s: An I/O-error occurred on the CTCM device\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the CTCM device
+ * Description:
+ * An I/O error was detected on one of the subchannels of the CTCM device.
+ * Depending on the error, the CTCM device driver might attempt an automatic
+ * recovery.
+ * User action:
+ * Check the status of the CTCM device, for example, with ifconfig. If the
+ * device is not operational, perform a manual recovery. See "Device Drivers,
+ * Features, and Commands" for details about how to recover a CTCM device.
+ */
+
+/*?
+ * Text: "%s: An adapter hardware operation timed out\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the CTCM device
+ * Description:
+ * The CTCM device uses an adapter to physically connect to its communication
+ * peer. An operation on this adapter timed out.
+ * User action:
+ * Check the status of the CTCM device, for example, with ifconfig. If the
+ * device is not operational, perform a manual recovery. See "Device Drivers,
+ * Features, and Commands" for details about how to recover a CTCM device.
+ */
+
+/*?
+ * Text: "%s: An error occurred on the adapter hardware\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the CTCM device
+ * Description:
+ * The CTCM device uses an adapter to physically connect to its communication
+ * peer. An operation on this adapter returned an error.
+ * User action:
+ * Check the status of the CTCM device, for example, with ifconfig. If the
+ * device is not operational, perform a manual recovery. See "Device Drivers,
+ * Features, and Commands" for details about how to recover a CTCM device.
+ */
+
+/*?
+ * Text: "%s: The communication peer has disconnected\n"
+ * Severity: Notice
+ * Parameter:
+ *   @1: channel ID
+ * Description:
+ * The remote device has disconnected. Possible reasons are that the remote
+ * interface has been closed or that the operating system instance with the
+ * communication peer has been rebooted or shut down.
+ * User action:
+ * Check the status of the peer device. Ensure that the peer operating system
+ * instance is running and that the peer interface is operational.
+ */
+
+/*?
+ * Text: "%s: The remote operating system is not available\n"
+ * Severity: Notice
+ * Parameter:
+ *   @1: channel ID
+ * Description:
+ * The operating system instance with the communication peer has disconnected.
+ * Possible reasons are that the operating system instance has been rebooted
+ * or shut down.
+ * User action:
+ * Ensure that the peer operating system instance is running and that the peer
+ * interface is operational.
+ */
+
+/*?
+ * Text: "%s: The adapter received a non-specific IRQ\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the CTCM device
+ * Description:
+ * The adapter hardware used by the CTCM device received an IRQ that cannot
+ * be mapped to a particular device. This is a hardware problem.
+ * User action:
+ * Check the status of the CTCM device, for example, with ifconfig. Check if
+ * the connection to the remote device still works. If the CTCM device is not
+ * operational, set it offline and back online. If this does not resolve the
+ * problem, perform a manual recovery. See "Device Drivers, Features, and
+ * Commands" for details about how to recover a CTCM device. If this problem
+ * persists, gather Linux debug data, collect the hardware logs, and report the
+ * problem to your support organization.
+ */
+
+/*?
+ * Text: "%s: A check occurred on the subchannel\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the CTCM device
+ * Description:
+ * A check condition has been detected on the subchannel.
+ * User action:
+ * Check if the connection to the remote device still works. If the CTCM device
+ * is not operational, set it offline and back online. If this does not resolve
+ * the problem, perform a manual recovery. See "Device Drivers, Features, and
+ * Commands" for details about how to recover a CTCM device. If this problem
+ * persists, gather Linux debug data and report the problem to your support
+ * organization.
+ */
+
+/*?
+ * Text: "%s: The communication peer is busy\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: channel ID
+ * Description:
+ * A busy target device was reported. This might be a temporary problem.
+ * User action:
+ * If this problem persists or is reported frequently ensure that the target
+ * device is working properly.
+ */
+
+/*?
+ * Text: "%s: The specified target device is not valid\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: channel ID
+ * Description:
+ * A target device was called with a faulty device specification. This is an
+ * adapter hardware problem.
+ * User action:
+ * Gather Linux debug data, collect the hardware logs, and contact IBM support.
+ */
+
+/*?
+ * Text: "An I/O operation resulted in error %04x\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: channel ID
+ *   @2: error information
+ * Description:
+ * A hardware operation ended with an error.
+ * User action:
+ * Check the status of the CTCM device, for example, with ifconfig. If the
+ * device is not operational, perform a manual recovery. See "Device Drivers,
+ * Features, and Commands" for details about how to recover a CTCM device.
+ * If this problem persists, gather Linux debug data, collect the hardware logs,
+ * and report the problem to your support organization.
+ */
+
+/*?
+ * Text: "%s: Initialization failed with RX/TX init handshake error %s\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the CTCM device
+ *   @2: error information
+ * Description:
+ * A problem occurred during the initialization of the connection. If the
+ * connection can be established after an automatic recovery, a success message
+ * is issued.
+ * User action:
+ * If the problem is not resolved by the automatic recovery process, check the
+ * local and remote device. If this problem persists, gather Linux debug data
+ * and report the problem to your support organization.
+ */
+
+/*?
+ * Text: "%s: The network backlog for %s is exceeded, package dropped\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the CTCM device
+ *   @2: calling function
+ * Description:
+ * There is more network traffic than can be handled by the device. The device
+ * is closed and some data has not been transmitted. The device might be
+ * recovered automatically.
+ * User action:
+ * Investigate and resolve the congestion. If necessary, set the device
+ * online to make it operational.
+ */
+
+/*?
+ * Text: "%s: The XID used in the MPC protocol is not valid, rc = %d\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the CTCM device
+ *   @2: return code
+ * Description:
+ * The exchange identification (XID) used by the CTCM device driver when
+ * in MPC mode is not valid.
+ * User action:
+ * Note the error information provided with this message and contact your
+ * support organization.
+ */
+
+/*? Text: "CTCM driver unloaded\n" */
+/*? Text: "%s: %s Internal error: net_device is NULL, ch = 0x%p\n" */
+/*? Text: "%s / Initializing the ctcm device driver failed, ret = %d\n" */
+/*? Text: "%s: %s: Internal error: Can't determine channel for interrupt device %s\n" */
+/*? Text: "CTCM driver initialized\n" */
+/*? Text: "%s: setup OK : r/w = %s/%s, protocol : %d\n" */
+/*? Text: "%s: Connected with remote side\n" */
+/*? Text: "%s: Restarting device\n" */
+/*? Text: "netif_stop_queue() cannot be called before register_netdev()\n" */
+/*? Text: "flen=%u proglen=%u pass=%u image=%pK from=%s pid=%d\n" */
+/*? Text: "%s selects TX queue %d, but real number of TX queues is %d\n" */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/dasd
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/dasd
@@ -0,0 +1,704 @@
+/* dasd_ioctl */
+
+/*?
+ * Text: "%s: The DASD has been put in the quiesce state\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * No I/O operation is possible on this device.
+ * User action:
+ * Resume the DASD to enable I/O operations.
+ */
+
+/*?
+ * Text: "%s: I/O operations have been resumed on the DASD\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * The DASD is no longer in state quiesce and I/O operations can be performed
+ * on the device.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "%s: The DASD cannot be formatted while it is enabled\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * The DASD you try to format is enabled. Enabled devices cannot be formatted.
+ * User action:
+ * Contact the owner of the formatting tool.
+ */
+
+/*?
+ * Text: "%s: The specified DASD is a partition and cannot be formatted\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * The DASD you try to format is a partition. Partitions cannot be formatted
+ * separately. You can only format a complete DASD including all its partitions.
+ * User action:
+ * Format the complete DASD.
+ * ATTENTION: Formatting irreversibly destroys all data on all partitions
+ * of the DASD.
+ */
+
+/*?
+ * Text: "%s: The specified DASD is a partition and cannot be checked\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * The DASD you try to check is a partition. Partitions cannot be checked
+ * separately. You can only check a complete DASD including all its partitions.
+ * User action:
+ * Check the complete DASD.
+ */
+
+/*?
+ * Text: "%s: Formatting unit %d failed with rc=%d\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: start track
+ *   @3: return code
+ * Description:
+ * The formatting process might have been interrupted by a signal, for example,
+ * CTRL+C. If the process was not interrupted intentionally, an I/O error
+ * might have occurred.
+ * User action:
+ * Retry to format the device. If the error persists, check the log file for
+ * related error messages. If you cannot resolve the error, note the return
+ * code and contact your support organization.
+ */
+
+
+/* dasd */
+
+/*?
+ * Text: "%s: Cancelling request %p failed with rc=%d\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: pointer to request
+ *   @3: return code of previous function
+ * Description:
+ * In response to a user action, the DASD device driver tried but failed to
+ * cancel a previously started I/O operation.
+ * User action:
+ * Try the action again.
+ */
+
+/*?
+ * Text: "%s: Flushing the DASD request queue failed for request %p\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: pointer to request
+ * Description:
+ * As part of the unloading process, the DASD device driver flushes the
+ * request queue. This failed because a previously started I/O operation
+ * could not be canceled.
+ * User action:
+ * Try again to unload the DASD device driver or to shut down Linux.
+ */
+
+/*?
+ * Text: "The DASD device driver could not be initialized\n"
+ * Severity: Informational
+ * Description:
+ * The initialization of the DASD device driver failed because of previous
+ * errors.
+ * User action:
+ * Check for related previous error messages.
+ */
+
+/*?
+ * Text: "%s: Accessing the DASD failed because it is in probeonly mode\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * The dasd= module or kernel parameter specified the probeonly attribute for
+ * the DASD you are trying to access. The DASD device driver cannot access
+ * DASDs that are in probeonly mode.
+ * User action:
+ * Change the dasd= parameter as to omit probeonly for the DASD and reload
+ * the DASD device driver. If the DASD device driver has been compiled into
+ * the kernel, reboot Linux.
+ */
+
+/*?
+ * Text: "%s: cqr %p timed out (%lus), %i retries remaining\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: request
+ *   @3: timeout value
+ *   @4: number of retries left
+ * Description:
+ * A try of the error recovery procedure (ERP) for the channel queued request
+ * (cqr) timed out and failed to recover the error. ERP continues for the DASD.
+ * User action:
+ * Ignore this message if it occurs infrequently and if the recovery succeeds
+ * during one of the retries. If this error persists, check for related
+ * previous error messages and report the problem to your support organization.
+ *
+ * The timeout can be changed by writing a new value to the sysfs 'expires' attribute of the DASD. The value specifies the timeout in seconds.
+ */
+
+/*?
+ * Text: "%s: cqr %p timed out (%lus) but cannot be ended, retrying in 5 s\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: request
+ *   @3: timeout value
+ * Description:
+ * A try of the error recovery procedure (ERP) for the channel queued request
+ * (cqr) timed out and failed to recover the error. The I/O request submitted
+ * during the try could not be canceled. The ERP waits for 5 seconds before
+ * trying again.
+ * User action:
+ * Ignore this message if it occurs infrequently and if the recovery succeeds
+ * during one of the retries. If this error persists, check for related
+ * previous error messages and report the problem to your support organization.
+ *
+ * The timeout can be changed by writing a new value to the sysfs 'expires' attribute of the DASD. The value specifies the timeout in seconds.
+ */
+
+/*?
+ * Text: "%s: The DASD cannot be set offline while it is in use\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * The DASD cannot be set offline because it is in use by an internal process.
+ * An action to free the DASD might not have completed yet.
+ * User action:
+ * Wait some time and set the DASD offline later.
+ */
+
+/*?
+ * Text: "%s: The DASD cannot be set offline with open count %i\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: count
+ * Description:
+ * The DASD is being used by one or more processes and cannot be set offline.
+ * User action:
+ * Ensure that the DASD is not in use anymore, for example, unmount all
+ * partitions. Then try again to set the DASD offline.
+ */
+
+/*?
+ * Text: "%s: Setting the DASD online failed with rc=%d\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: return code
+ * Description:
+ * The DASD could not be set online because of previous errors.
+ * User action:
+ * Look for previous error messages. If you cannot resolve the error, note
+ * the return code and contact your support organization.
+ */
+
+/*?
+ * Text: "%s Setting the DASD online with discipline %s failed with rc=%i\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: discipline
+ *   @3: return code
+ * Description:
+ * The DASD could not be set online because of previous errors.
+ * User action:
+ * Look for previous error messages. If you cannot resolve the error, note the
+ * return code and contact your support organization.
+ */
+
+/*?
+ * Text: "%s Setting the DASD online failed because of missing DIAG discipline\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * The DASD was to be set online with discipline DIAG but this discipline of
+ * the DASD device driver is not available.
+ * User action:
+ * Ensure that the dasd_diag_mod module is loaded. If your Linux system does
+ * not include this module, you cannot set DASDs online with the DIAG
+ * discipline.
+ */
+
+/*?
+ * Text: "%s Setting the DASD online failed because of a missing discipline\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * The DASD was to be set online with a DASD device driver discipline that
+ * is not available.
+ * User action:
+ * Ensure that all DASD modules are loaded correctly.
+ */
+
+---------------------------
+
+/*?
+ * Text: "The statistics feature has been switched off\n"
+ * Severity: Informational
+ * Description:
+ * The statistics feature of the DASD device driver has been switched off.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "The statistics feature has been switched on\n"
+ * Severity: Informational
+ * Description:
+ * The statistics feature of the DASD device driver has been switched on.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "The statistics have been reset\n"
+ * Severity: Informational
+ * Description:
+ * The DASD statistics data have been reset.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "%s is not a supported value for /proc/dasd/statistics\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: value
+ * Description:
+ * An incorrect value has been written to /proc/dasd/statistics.
+ * The supported values are: 'set on', 'set off', and 'reset'.
+ * User action:
+ * Write a supported value to /proc/dasd/statistics.
+ */
+
+/*?
+ * Text: "%s is not a valid device range\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: range
+ * Description:
+ * A device range specified with the dasd= parameter is not valid.
+ * User action:
+ * Examine the dasd= parameter and correct the device range.
+ */
+
+/*?
+ * Text: "The probeonly mode has been activated\n"
+ * Severity: Informational
+ * Description:
+ * The probeonly mode of the DASD device driver has been activated. In this
+ * mode the device driver rejects any 'open' syscalls with EPERM.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "The IPL device is not a CCW device\n"
+ * Severity: Error
+ * Description:
+ * The value for the dasd= parameter contains the 'ipldev' keyword. During
+ * the boot process this keyword is replaced with the device from which the
+ * IPL was performed. The 'ipldev' keyword is not valid if the IPL device is
+ * not a CCW device.
+ * User action:
+ * Do not specify the 'ipldev' keyword when performing an IPL from a device
+ * other than a CCW device.
+ */
+
+/*?
+ * Text: "A closing parenthesis ')' is missing in the dasd= parameter\n"
+ * Severity: Warning
+ * Description:
+ * The specification for the dasd= kernel or module parameter has an opening
+ * parenthesis '(' * without a matching closing parenthesis ')'.
+ * User action:
+ * Correct the parameter value.
+ */
+
+/*?
+ * Text: "The autodetection mode has been activated\n"
+ * Severity: Informational
+ * Description:
+ * The autodetection mode of the DASD device driver has been activated. In
+ * this mode the DASD device driver sets all detected DASDs online.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "%*s is not a supported device option\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: length of option code
+ *   @2: option code
+ * Description:
+ * The dasd= parameter includes an unknown option for a DASD or a device range.
+ * Options are specified in parenthesis and immediately follow a device or
+ * device range.
+ * User action:
+ * Check the dasd= syntax and remove any unsupported options from the dasd=
+ * parameter specification.
+ */
+
+/*?
+ * Text: "PAV support has be deactivated\n"
+ * Severity: Informational
+ * Description:
+ * The 'nopav' keyword has been specified with the dasd= kernel or module
+ * parameter. The Parallel Access Volume (PAV) support of the DASD device
+ * driver has been deactivated.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "'nopav' is not supported on z/VM\n"
+ * Severity: Informational
+ * Description:
+ * For Linux instances that run as guest operating systems of the z/VM
+ * hypervisor Parallel Access Volume (PAV) support is controlled by z/VM not
+ * by Linux.
+ * User action:
+ * Remove 'nopav' from the dasd= module or kernel parameter specification.
+ */
+
+/*?
+ * Text: "High Performance FICON support has been deactivated\n"
+ * Severity: Informational
+ * Description:
+ * The 'nofcx' keyword has been specified with the dasd= kernel or module
+ * parameter. The High Performance FICON (transport mode) support of the DASD
+ * device driver has been deactivated.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "The dasd= parameter value %s has an invalid ending\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: parameter value
+ * Description:
+ * The specified value for the dasd= kernel or module parameter is not correct.
+ * User action:
+ * Check the module or the kernel parameter.
+ */
+
+/*?
+ * Text: "Registering the device driver with major number %d failed\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: DASD major
+ * Description:
+ * Major number 94 is reserved for the DASD device driver. The DASD device
+ * driver failed to register with this major number. Another device driver
+ * might have used major number 94.
+ * User action:
+ * Determine which device driver uses major number 94 instead of the DASD
+ * device driver and unload this device driver. Then try again to load the
+ * DASD device driver.
+ */
+
+/*?
+  * Text: "%s: default ERP has run out of retries and failed\n"
+  * Severity: Error
+  * Parameter:
+  *   @1: bus ID of the DASD
+  * Description:
+  * The error recovery procedure (ERP) tried to recover an error but the number
+  * of retries for the I/O was exceeded before the error could be resolved.
+  * User action:
+  * Check for related previous error messages.
+  */
+
+/*?
+ * Text: "%s: Unable to terminate request %p on suspend\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: pointer to request
+ * Description:
+ * As part of the suspend process, the DASD device driver terminates requests
+ * on the request queue. This failed because a previously started I/O operation
+ * could not be canceled. The suspend process will be stopped.
+ * User action:
+ * Try again to suspend the system.
+ */
+
+/*?
+ * Text: "%s: ERP failed for the DASD\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * An error recovery procedure (ERP) was performed for the DASD but failed.
+ * User action:
+ * Check the message log for previous related error messages.
+ */
+
+/*?
+ * Text: "%s: An error occurred in the DASD device driver, reason=%s\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: reason code
+ * Description:
+ * This problem indicates a program error in the DASD device driver.
+ * User action:
+ * Note the reason code and contact your support organization.
+*/
+
+/*?
+ * Text: "%s: No operational channel path is left for the device\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * All channel paths to the device have become non-operational. The DASD
+ * device driver suspends I/O operations and queues I/O requests for this
+ * device until at least one channel path becomes operational again.
+ * User action:
+ * Ensure that each channel path to the device has been set up correctly
+ * and that the related physical cable connections are in place.
+ */
+
+/*?
+ * Text: "%s: No verified channel paths remain for the device\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * All verified channel paths to the device have become non-operational.
+ * Any other paths to the device have previously been identified as not usable.
+ * The DASD device driver suspends I/O operations and queues I/O requests
+ * for this device until at least one channel path becomes operational
+ * again.
+ * User action:
+ * Ensure that each channel path to the device has been set up correctly
+ * and that the related physical cable connections are in place.
+ * Set all paths to the device offline and online again to repeat the path
+ * verification. Alternatively, set the device offline and online again to
+ * verify all available paths for this device.
+ * If this problem persists, gather Linux debug data and report the problem
+ * to your support organization.
+ */
+
+/*?
+ * Text: "%s: A channel path to the device has become operational\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * At least one channel path of this device has become operational again.
+ * The DASD device driver resumes I/O operations to the device and processes
+ * the I/O requests that were queued while there was no operational channel path.
+ * User action:
+ * None.
+ */
+
+------------------------------------------------------------------------------------
+/* dasd_diag */
+
+/*?
+ * Text: "%s: A 64-bit DIAG call failed\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * 64-bit DIAG calls require a 64-bit z/VM version.
+ * User action:
+ * Use z/VM 5.2 or later or set the sysfs 'use_diag' attribute of the DASD to 0
+ * to switch off DIAG.
+ */
+
+/*?
+ * Text: "%s: Accessing the DASD failed because of an incorrect format (rc=%d)\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: return code
+ * Description:
+ * The format of the DASD is not correct.
+ * User action:
+ * Check the device format. For details about the return code see the
+ * section about the INITIALIZE function for DIAGNOSE Code X'250'
+ * in "z/VM CP Programming Services". If you cannot resolve the error, note
+ * the return code and contact your support organization.
+ */
+
+/*?
+ * Text: "%s: New DASD with %ld byte/block, total size %ld KB%s\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: bytes per block
+ *   @3: size
+ *   @4: access mode
+ * Description:
+ * A DASD with the indicated block size and total size has been set online.
+ * If the DASD is configured as read-only to the real or virtual hardware,
+ * the message includes an indication of this hardware access mode. The
+ * hardware access mode is independent from the 'readonly' attribute of
+ * the device in sysfs.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "%s: DIAG ERP failed with rc=%d\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: return code
+ * Description:
+ * An error in the DIAG processing could not be recovered by the error
+ * recovery procedure (ERP) of the DIAG discipline.
+ * User action:
+ * Note the return code, check for related I/O errors, and report this problem
+ * to your support organization.
+ */
+
+/*?
+ * Text: "%s: DIAG initialization failed with rc=%d\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: return code
+ * Description:
+ * Initializing the DASD with the DIAG discipline failed. Possible reasons for
+ * this problem are that the device has a device type other than FBA or ECKD,
+ * or has a block size other than one of the supported sizes:
+ * 512 byte, 1024 byte, 2048 byte, or 4096 byte.
+ * User action:
+ * Ensure that the device can be written to and has a supported device type
+ * and block size. For details about the return code see the section about
+ * the INITIALIZE function for DIAGNOSE Code X'250' in "z/VM CP Programming
+ * Services". If you cannot resolve the error, note the error code and contact
+ * your support organization.
+ */
+
+/*?
+ * Text: "%s: Device type %d is not supported in DIAG mode\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: device type
+ * Description:
+ * Only DASD of type FBA and ECKD are supported in DIAG mode.
+ * User action:
+ * Set the sysfs 'use_diag' attribute of the DASD to 0 and try again to access
+ * the DASD.
+ */
+
+/*?
+ * Text: "Discipline %s cannot be used without z/VM\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: discipline name
+ * Description:
+ * The discipline that is specified with the dasd= kernel or module parameter
+ * is only available for Linux instances that run as guest operating
+ * systems of the z/VM hypervisor.
+ * User action:
+ * Remove the unsupported discipline from the parameter string.
+ */
+
+/*?
+ * Text: "%s: The access mode of a DIAG device changed to read-only\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * A device changed its access mode from writeable to
+ * read-only while in use.
+ * User action:
+ * Set the device offline, ensure that the device is configured correctly in
+ * z/VM, then set the device online again.
+ */
+
+------------------------------------------------------------------------------------
+/* dasd_erp */
+
+/*?
+ * Text: "%s: A timeout error occurred for cqr %p\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: pointer to request
+ * Description:
+ * A channel queued request (cqr) failed because it timed out.
+ * One possible reason for this error is that a request did not
+ * complete within the timeout interval specified for the DASD.
+ * The timeout interval is set as the value of the 'timeout' sysfs
+ * attribute of a DASD. A value of 0 disables the timeout function.
+ * The timeout function can be used; for example, by mirroring setups;
+ * to quickly process a request queue for a DASD that has become unavailable.
+ * User action:
+ * Check the message log for previous related error messages.  Verify
+ * that the storage server and the connection from host to storage
+ * server are operational.  If the 'timeout' sysfs attribute of the
+ * DASD has been set to a value other than 0, verify that this
+ * setting is intentional and change it if required.
+ */
+
+/*?
+ * Text: "%s: A transport error occurred for cqr %p\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: pointer to request
+ * Description:
+ * A channel queued request (cqr) failed because the connection to the
+ * device was lost and the 'failfast' flag is set for the request.
+ * This flag can result from, for example:
+ *
+ * - A software layer above the DASD device driver;
+ *   for example, in a host based mirroring setup.
+ *
+ * - Value 1 for the 'failfast' sysfs attribute of the DASD.
+ *   This setting applies to all requests on the DASD.
+ *
+ * User action:
+ * Ensure that each channel path to the device has been set up
+ * correctly and that the related physical cable connections are in
+ * place. If the 'failfast' attribute of the DASD is set to 1,
+ * verify that this setting is intentional and change it to 0 if required.
+ */
+
+/*?
+ * Text: "%s Setting the DASD online failed because the required module %s could not be loaded (rc=%d)\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: kernel module name
+ *   @3: return code
+ * Description:
+ * The DASD was to be set online with discipline DIAG but this discipline of
+ * the DASD device driver is not available and an attempt to load the
+ * corresponding kernel module failed with the specified return code.
+ *
+ * User action:
+ * Ensure that the kernel module with the specified name is correctly installed
+ * or set the sysfs 'use_diag' attribute of the DASD to 0 to switch off DIAG.
+ */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/dasd-eckd
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/dasd-eckd
@@ -0,0 +1,2154 @@
+/* dasd_eckd */
+
+/*?
+ * Text: "%s: ERP failed for the DASD\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * An error recovery procedure (ERP) was performed for the DASD but failed.
+ * User action:
+ * Check the message log for previous related error messages.
+ */
+
+/*?
+ * Text: "%s: An error occurred in the DASD device driver, reason=%s\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: reason code
+ * Description:
+ * This problem indicates a program error in the DASD device driver.
+ * User action:
+ * Note the reason code and contact your support organization.
+*/
+
+/*?
+ * Text: "%s: Allocating memory for private DASD data failed\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * The DASD device driver maintains data structures for each DASD it manages.
+ * There is not enough memory to allocate these data structures for one or
+ * more DASD.
+ * User action:
+ * Free some memory and try the operation again.
+ */
+
+/*?
+ * Text: "%s: DASD with %d KB/block, %d KB total size, %d KB/track, %s\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: block size
+ *   @3: DASD size
+ *   @4: track size
+ *   @5: disc layout
+ * Description:
+ * A DASD with the shown characteristics has been set online.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "%s: Start track number %u used in formatting is too big\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: track number
+ * Description:
+ * The DASD format I/O control was used incorrectly by a formatting tool.
+ * User action:
+ * Contact the owner of the formatting tool.
+ */
+
+/*?
+ * Text: "%s: Stop track number %u used in formatting is too big\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: track number
+ * Description:
+ * The DASD format I/O control was used incorrectly by a formatting tool.
+ * User action:
+ * Contact the owner of the formatting tool.
+ */
+
+/*?
+ * Text: "%s: The DASD is not formatted\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * A DASD has been set online but it has not been formatted yet. You must
+ * format the DASD before you can use it.
+ * User action:
+ * Format the DASD, for example, with dasdfmt.
+ */
+
+/*?
+ * Text: "%s: 0x%x is not a known command\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: command
+ * Description:
+ * This problem is likely to be caused by a programming error.
+ * User action:
+ * Contact your support organization.
+ */
+
+/*?
+ * Text: "%s: Track 0 has no records following the VTOC\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * Linux has identified a volume table of contents (VTOC) on the DASD but
+ * cannot read any data records following the VTOC. A possible cause of this
+ * problem is that the DASD has been used with another System z operating
+ * system.
+ * User action:
+ * Format the DASD for usage with Linux, for example, with dasdfmt.
+ * ATTENTION: Formatting irreversibly destroys all data on the DASD.
+ */
+
+/*?
+ * Text: "%s: An I/O control call used incorrect flags 0x%x\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: flags
+ * Description:
+ * The DASD format I/O control was used incorrectly.
+ * User action:
+ * Contact the owner of the formatting tool.
+ */
+
+/*?
+ * Text: "%s: New DASD %04X/%02X (CU %04X/%02X) with %d cylinders, %d heads, %d sectors%s\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: device type
+ *   @3: device model
+ *   @4: control unit type
+ *   @5: control unit model
+ *   @6: number of cylinders
+ *   @7: tracks per cylinder
+ *   @8: sectors per track
+ *   @9: access mode
+ * Description:
+ * A DASD with the shown characteristics has been set online.
+ * If the DASD is configured as read-only to the real or virtual hardware,
+ * the message includes an indication of this hardware access mode. The
+ * hardware access mode is independent from the 'readonly' attribute of
+ * the device in sysfs.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "%s: The disk layout of the DASD is not supported\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * The DASD device driver only supports the following disk layouts: CDL, LDL,
+ * FBA, CMS, and CMS RESERVED.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "%s: Start track %u used in formatting exceeds end track\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: track number
+ * Description:
+ * The DASD format I/O control was used incorrectly by a formatting tool.
+ * User action:
+ * Contact the owner of the formatting tool.
+ */
+
+/*?
+ * Text: "%s: The DASD cache mode was set to %x (%i cylinder prestage)\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: operation mode
+ *   @3: number of cylinders
+ * Description:
+ * The DASD cache mode has been changed. See the storage system documentation
+ * for information about the different cache operation modes.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "%s: The DASD cannot be formatted with block size %u\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: block size
+ * Description:
+ * The block size specified for a format instruction is not valid. The block
+ * size must be between 512 and 4096 byte and must be a power of 2.
+ * User action:
+ * Call the format command with a supported block size.
+ */
+
+/*?
+ * Text: "%s: The UID of the DASD has changed\n"
+ * Severity: Error
+ * Parameter:
+ * @1: bus ID of the DASD
+ * Description:
+ * The Unique Identifier (UID) of a DASD that is currently in use has changed.
+ * This indicates that the physical disk has been replaced.
+ * User action:
+ * None if the replacement was intentional.
+ * If the disk change is not expected, stop using the disk to prevent possible
+ * data loss.
+*/
+
+
+/* dasd_3990_erp */
+
+/*?
+ * Text: "%s: is offline or not installed - INTERVENTION REQUIRED!!\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * The DASD to be accessed is not in an accessible state. The I/O operation
+ * will wait until the device is operational again. This is an operating system
+ * independent message that is issued by the storage system.
+ * User action:
+ * Make the DASD accessible again. For details see the storage system
+ * documentation.
+ */
+
+/*?
+ * Text: "%s: The DASD cannot be reached on any path (lpum=%x/opm=%x)\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: last path used mask
+ *   @3: online path mask
+ * Description:
+ * After a path to the DASD failed, the error recovery procedure of the DASD
+ * device driver tried but failed to reconnect the DASD through an alternative
+ * path.
+ * User action:
+ * Ensure that the cabling between the storage server and the mainframe
+ * system is securely in place. Check the file systems on the DASD when it is
+ * accessible again.
+ */
+
+/*?
+ * Text: "%s: Unable to allocate DCTL-CQR\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an internal error.
+ * User action:
+ * Contact your support organization.
+ */
+
+/*?
+ * Text: "%s: FORMAT 0 - Invalid Parameter\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * A data argument of a command is not valid. This is an operating system
+ * independent message that is issued by the storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 0 - DPS Installation Check\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This operating system independent message is issued by the storage system
+ *  for one of the following reasons:
+ * - A 3380 Model D or E DASD does not have the Dynamic Path Selection (DPS)
+ * feature in the DASD A-unit.
+ * - The device type of an attached DASD is not supported by the firmware.
+ * - A type 3390 DASD is attached to a 3 MB channel.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 2 - Reserved\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 1 - Drive motor switch is off\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 0 - CCW Count less than required\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * The CCW count of a command is less than required. This is an operating
+ * system independent message that is issued by the storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 0 - Channel requested ... %02x\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: reason code
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system. The possible reason codes indicate the following problems:
+ * 00 No Message.
+ * 01 The channel has requested unit check sense data.
+ * 02 The channel has requested retry and retry is exhausted.
+ * 03 A SA Check-2 error has occurred. This sense is presented with
+ *    Equipment Check.
+ * 04 The channel has requested retry and retry is not possible.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 0 - Status Not As Required: reason %02x\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: reason code
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system. There are several potential reasons for this message;
+ * byte 8 contains the reason code.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 4 - Reserved\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 1 - Device status 1 not valid\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 0 - Storage Path Restart\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * An operation for an active channel program was queued in a Storage Control
+ * when a warm start was received by the path. This is an operating system
+ * independent message that is issued by the storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 0 - Reset Notification\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * A system reset or its equivalent was received on an interface. The Unit
+ * Check that generates this sense is posted to the next channel initiated
+ * selection following the resetting event. This is an operating system
+ * independent message that is issued by the storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 0 - Invalid Command Sequence\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * An incorrect sequence of commands has occurred. This is an operating system
+ * independent message that is issued by the storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 1 - Missing device address bit\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT F - Subsystem Processing Error\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * A firmware logic error has been detected. This is an operating system
+ * independent message that is issued by the storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 1 - Seek incomplete\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 0 - Invalid Command\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * A command was issued that is not in the 2107/1750 command set.
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 0 - Reserved\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 0 - Command Invalid on Secondary Address\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * A command or order not allowed on a PPRC secondary device has been received
+ * by the secondary device. This is an operating system independent message
+ * that is issued by the storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 0 - Invalid Defective/Alternate Track Pointer\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * A defective track has been accessed. The subsystem generates an invalid
+ * Defective/Alternate Track Pointer as a part of RAID Recovery.
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 0 - Channel Returned with Incorrect retry CCW\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * A command portion of the CCW returned after a command retry sequence does
+ * not match the command for which retry was signaled. This is an operating
+ * system independent message that is issued by the storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 0 - Diagnostic of Special Command Violates File Mask\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * A command is not allowed under the Access Authorization specified by the
+ * File Mask. This is an operating system independent message that is issued
+ * by the storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 1 - Head address does not compare\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 1 - Reserved\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 1 - Device did not respond to selection\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 1 - Device check-2 error or Set Sector is not complete\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 0 - Device Error Source\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * The device has completed soft error logging. This is an operating system
+ * independent message that is issued by the storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 0 - Data Pinned for Device\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * Modified data in cache or in persistent storage exists for the DASD. The
+ * data cannot be destaged to the device. This track is the first track pinned
+ * for this device. This is an operating system independent message that is
+ * issued by the storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 6 - Overrun on channel C\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 1 - Device Status 1 not as expected\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 0 - Device Fenced - device = %02x\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: sense data byte 4
+ * Description:
+ * The device shown in sense byte 4 has been fenced. This is an operating
+ * system independent message that is issued by the storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 1 - Interruption cannot be reset\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 1 - Index missing\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT F - DASD Fast Write inhibited\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * DASD Fast Write is not allowed because of a nonvolatile storage battery
+ * check condition. This is an operating system independent message that is
+ * issued by the storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 7 - Invalid tag-in for an extended command sequence\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 4 - Key area error; offset active\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 4 - Count area error; offset active\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 1 - Track physical address did not compare\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 2 - 3990 check-2 error\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 1 - Offset active cannot be reset\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 7 - RCC 1 and RCC 2 sequences not successful\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 4 - No sync byte in count address area; offset active\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 4 - Data area error\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 6 - Overrun on channel A\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 4 - No sync byte in count address area\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 5 - Data Check in the key area\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT F - Caching status reset to default\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * The storage director has assigned two new subsystem status devices and
+ * resets the status to its default value. This is an operating system
+ * independent message that is issued by the storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 5 - Data Check in the data area; offset active\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 5 - Reserved\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 1 - Device not ready\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 4 - No sync byte in key area\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 8 - DASD controller failed to set or reset the long busy latch\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 1 - Cylinder address did not compare\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 3 - Reserved\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 4 - No sync byte in data area; offset active\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 2 - Support facility errors\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 4 - Key area error\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 8 - End operation with transfer count not zero\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 2 - Microcode detected error %02x\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: error code
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 5 - Data Check in the count area; offset active\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 3 - Allegiance terminated\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * Allegiance terminated because of a Reset Allegiance or an Unconditional
+ * Reserve command on another channel. This is an operating system independent
+ * message that is issued by the storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 4 - Home address area error\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 4 - Count area error\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 7 - Invalid tag-in during selection sequence\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 4 - No sync byte in data area\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 4 - No sync byte in home address area; offset active\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 4 - Home address area error; offset active\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 4 - Data area error; offset active\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 4 - No sync byte in home address area\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 5 - Data Check in the home address area; offset active\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 5 - Data Check in the home address area\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 5 - Data Check in the count area\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 4 - No sync byte in key area; offset active\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 7 - Invalid DCC selection response or timeout\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 5 - Data Check in the data area\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT F - Operation Terminated\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * The storage system ends an operation related to an active channel program
+ * when termination and redrive are required and logging is not desired.
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 6 - Overrun on channel B\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 5 - Data Check in the key area; offset active\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT F - Volume is suspended duplex\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * The duplex pair volume has entered the suspended duplex state because of a
+ * failure. This is an operating system independent message that is issued by
+ * the storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 6 - Overrun on channel D\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 7 - RCC 1 sequence not successful\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 6 - Overrun on channel E\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 7 - 3990 microcode time out when stopping selection\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 6 - Overrun on channel F\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 6 - Reserved\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 7 - RCC initiated by a connection check alert\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 6 - Overrun on channel G\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 7 - extra RCC required\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 6 - Overrun on channel H\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 8 - Unexpected end operation response code\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 7 - Permanent path error (DASD controller not available)\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 7 - Missing end operation; device transfer incomplete\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT F - Reserved\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT F - Cache or nonvolatile storage equipment failure\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * An equipment failure has occurred in the cache storage or nonvolatile
+ * storage of the storage system. This is an operating system independent
+ * message that is issued by the storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 8 - DPS cannot be filled\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 8 - Error correction code hardware fault\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 7 - Missing end operation; device transfer complete\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 7 - DASD controller not available on disconnected command chain\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 8 - No interruption from device during a command chain\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 7 - No response to selection after a poll interruption\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 9 - Track physical address did not compare while oriented\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 9 - Head address did not compare\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 7 - Invalid tag-in for an immediate command sequence\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 9 - Cylinder address did not compare\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 8 - DPS checks after a system reset or selective reset\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT F - Caching reinitiated\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * Caching has been automatically reinitiated following an error.
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 8 - End operation with transfer count zero\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 7 - Reserved\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 9 - Reserved\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 8 - Short busy time-out during device selection\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT F - Caching terminated\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * The storage system was unable to initiate caching or had to suspend caching
+ * for a 3990 control unit. If this problem is caused by a failure condition,
+ * an additional message will provide more information about the failure.
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * Check for additional messages that point out possible failures. For more
+ * information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT F - Subsystem status cannot be determined\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * The status of a DASD Fast Write or PPRC volume cannot be determined.
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT F - Nonvolatile storage terminated\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * The storage director has stopped using nonvolatile storage or cannot
+ * initiate nonvolatile storage. If this problem is caused by a failure, an
+ * additional message will provide more information about the failure. This is
+ * an operating system independent message that is issued by the storage system.
+ * User action:
+ * Check for additional messages that point out possible failures. For more
+ * information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT 8 - Reserved\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: Write inhibited path encountered\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an informational message.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "%s: FORMAT 9 - Device check-2 error\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This is an operating system independent message that is issued by the
+ * storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT F - Track format incorrect\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * A track format error occurred while data was being written to the DASD or
+ * while a duplex pair was being established. This is an operating system
+ * independent message that is issued by the storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: FORMAT F - Cache fast write access not authorized\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * A request for Cache Fast Write Data access cannot be satisfied because
+ * of missing access authorization for the storage system. This is an operating
+ * system independent message that is issued by the storage system.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: Data recovered during retry with PCI fetch mode active\n"
+ * Severity: Emerg
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * A data error has been recovered on the storages system but the Linux file
+ * system cannot be informed about the data mismatch. To prevent Linux from
+ * running with incorrect data, the DASD device driver will trigger a kernel
+ * panic.
+ * User action:
+ * Reset your real or virtual hardware and reboot Linux.
+ */
+
+/*?
+ * Text: "%s: The specified record was not found\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * The record to be accessed does not exist. The DASD might be unformatted
+ * or defect.
+ * User action:
+ * Try to format the DASD or replace it.
+ * ATTENTION: Formatting irreversibly destroys all data on the DASD.
+ */
+
+/*?
+ * Text: "%s: ERP %p (%02x) refers to %p\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: pointer to ERP
+ *   @3: ERP status
+ *   @4: cqr
+ * Description:
+ * This message provides debug information for the enhanced error recovery
+ * procedure (ERP).
+ * User action:
+ * If you do not need this information, you can suppress this message by
+ * switching off ERP logging, for example, by writing '1' to the 'erplog'
+ * sysfs attribute of the DASD.
+ */
+
+/*?
+ * Text: "%s: ERP chain at END of ERP-ACTION\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This message provides debug information for the enhanced error recovery
+ * procedure (ERP).
+ * User action:
+ * If you do not need this information, you can suppress this message by
+ * switching off ERP logging, for example, by writing '1' to the 'erplog'
+ * sysfs attribute of the DASD.
+ */
+
+/*?
+ * Text: "%s: The cylinder data for accessing the DASD is inconsistent\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * An error occurred in the storage system hardware.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: Accessing the DASD failed because of a hardware error\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * An error occurred in the storage system hardware.
+ * User action:
+ * For more information see the documentation of your storage system.
+ */
+
+/*?
+ * Text: "%s: ERP chain at BEGINNING of ERP-ACTION\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This message provides debug information for the enhanced error recovery
+ * procedure (ERP).
+ * User action:
+ * If you do not need this information, you can suppress this message by
+ * switching off ERP logging, for example, by writing '1' to the 'erplog'
+ * sysfs attribute of the DASD.
+ */
+
+/*?
+ * Text: "%s: ERP %p has run out of retries and failed\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: ERP pointer
+ * Description:
+ * The error recovery procedure (ERP) tried to recover an error but the number
+ * of retries for the I/O was exceeded before the error could be resolved.
+ * User action:
+ * Check for related previous error messages.
+ */
+
+/*?
+ * Text: "%s: SIM - SRC: %02x%02x%02x%02x\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: sense byte
+ *   @3: sense byte
+ *   @4: sense byte
+ *   @5: sense byte
+ * Description:
+ * This error message is a System Information Message (SIM) generated by the
+ * storage system. The System Reference Code (SRC) defines the error in detail.
+ * User action:
+ * Look up the SRC in the storage server documentation.
+ */
+
+/*?
+ * Text: "%s: log SIM - SRC: %02x%02x%02x%02x\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: sense byte
+ *   @3: sense byte
+ *   @4: sense byte
+ *   @5: sense byte
+ * Description:
+ * This System Information Message (SIM) is generated by the storage system.
+ * The System Reference Code (SRC) defines the error in detail.
+ * User action:
+ * Look up the SRC in the storage server documentation.
+ */
+
+/*?
+ * Text: "%s: Reading device feature codes failed with rc=%d\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: return code
+ * Description:
+ * The device feature codes state which advanced features are supported by a
+ * device.
+ * Examples for advanced features are PAV or high performance FICON.
+ * Some early devices do not provide feature codes and no advanced features are
+ * available on these devices.
+ * User action:
+ * None, if the DASD does not provide feature codes. If the DASD provides
+ * feature codes, make sure that it is working correctly, then set it offline
+ * and back online.
+ */
+
+/*?
+ * Text: "%s: A channel path group could not be established\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * Initialization of a DASD did not complete because a channel path group
+ * could not be established.
+ * User action:
+ * Make sure that the DASD is working correctly, then try again to set it
+ * online. If initialization still fails, reboot.
+ */
+
+/*?
+ * Text: "%s: The DASD is not operating in multipath mode\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * The DASD channel path group could not be configured to use multipath mode.
+ * This might negatively affect I/O performance on this DASD.
+ * User action:
+ * Make sure that the DASD is working correctly, then try again to set it
+ * online. If initialization still fails, reboot.
+ */
+
+/*?
+ * Text: "%s: Detecting the DASD disk layout failed because of an I/O error\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * The disk layout of the DASD could not be detected because of an unexpected
+ * I/O error. The DASD device driver treats the device like an unformatted DASD,
+ * and partitions on the device are not accessible.
+ * User action:
+ * If the DASD is formatted, make sure that the DASD is working correctly,
+ * then set it offline and back online. If the DASD is unformatted, format the
+ * DASD, for example, with dasdfmt.
+ * ATTENTION: Formatting irreversibly destroys all data on the DASD.
+ */
+
+/*?
+ * Text: "%s: An I/O request was rejected because writing is inhibited\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * An I/O request was returned with an error indication of 'command reject'
+ * and 'write inhibited'. The most likely reason for this error is a
+ * failed write request to a device that was attached as read-only in z/VM.
+ * User action:
+ * Set the device offline, ensure that the device is configured correctly in
+ * z/VM, then set the device online again.
+ */
+
+/*?
+ * Text: "%s: An Alias device was reassigned to a new base device with UID: %s\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: bus ID of the alias
+ *   @2: UID of new base device
+ * Description:
+ * The alias device with the indicated bus ID has been reassigned. The UID of the new base device is shown in the message.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "%s: Detecting the maximum supported data size for zHPF requests failed\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * High Performance FICON (zHPF) requests are limited to a hardware-dependent
+ * maximum data size. The DASD device driver failed to detect this size and zHPF
+ * is not available for this device.
+ * User action:
+ * Set the device offline and online again. If this problem persists, gather
+ * Linux debug data and report the problem to your support organization.
+ */
+
+/*?
+ * Text: "%s: Reading device feature codes failed (rc=%d) for new path %x\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: return code
+ *   @3: path mask
+ * Description:
+ * A new path has been made available to the a device.
+ * A command to read the device feature codes on this device returned an error.
+ * The new path will not be used for I/O.
+ * User action:
+ * Set the new path offline and online again to repeat the path verification.
+ * Alternatively, set the device offline and online again to
+ * verify all available paths for this device.
+ * If this problem persists, gather Linux debug data and report the problem
+ * to your support organization.
+ */
+
+/*?
+ * Text: "%s: Detecting the maximum data size for zHPF requests failed (rc=%d) for a new path %x\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: return code
+ *   @3: path mask
+ * Description:
+ * High Performance FICON (zHPF) requests are limited to a hardware-dependent
+ * maximum data size. A command to detect this size for
+ * a new path returned an error. The new path will not be used for I/O.
+ * User action:
+ * Set the new path offline and online again to repeat the path verification.
+ * Alternatively, set the device offline and online again to
+ * verify all available paths for this device.
+ * If this problem persists, gather Linux debug data and report the problem
+ * to your support organization.
+ */
+
+/*?
+ * Text: "%s: The maximum data size for zHPF requests %u on a new path %x is below the active maximum %u\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: size in bytes
+ *   @3: path mask
+ *   @4: size in bytes
+ * Description:
+ * High Performance FICON (zHPF) requests are limited to a hardware-dependent
+ * maximum data size. The maximum of the new path is below
+ * the previously established common maximum for the
+ * existing paths for this device. This could cause requests on the new
+ * path to fail. The new path will not be used for I/O.
+ * User action:
+ * Set the device offline and online again to establish a new common maximum
+ * data size for the device.
+ */
+
+/*?
+ * Text: "%s: The device reservation was lost\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * This Linux instance has lost its reservation of the device to another
+ * operating system instance. Depending on the reservation policy for the
+ * device, I/O might be blocked until the other operating system instance
+ * surrenders the reservation or all I/O requests might fail until the
+ * device is reset.
+ * User action:
+ * None, if this situation is handled by system automation software.
+ * If this situation is not handled by automation, check the
+ * last_known_reservation_state attribute of the device in sysfs.
+ * If the value is 'lost', verify that the device is no longer reserved
+ * by another operating system instance, then set the device offline and
+ * online again. For any other value of the last_known_reservation_state
+ * no action is required. I/O will resume when the device reservation is
+ * surrendered by the other operating system instance.
+ */
+
+/*?
+ * Text: "%s: The storage server does not support raw-track access\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * The DASD cannot be accessed in raw-track access mode because the storage
+ * server does not have all required features for this access mode.
+ * In raw-track access mode, the DASD device driver accesses complete ECKD
+ * tracks.
+ * By default, the DASD device driver accesses only the data fields of ECKD
+ * devices and omits the count and key data fields.
+ * User action:
+ * Ensure that the raw_track_access sysfs attribute of the DASD has the value
+ * 0 to access the device in default ECKD mode.
+ */
+
+/*?
+ * Text: "%s: The newly added channel path %02X will not be used because it leads to a different device %s\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: logical path mask
+ *   @3: UID
+ * Description:
+ * The newly added channel path has a different UID than the DASD device. This indicates
+ * an incorrect cabling. This path is not going to be used.
+ * User action:
+ * Check the cabling of the DASD device. Disconnect and reconnect the cable.
+ */
+
+/*?
+ * Text: "%s: Not all channel paths lead to the same device, path %02X leads to device %s instead of %s\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: logical path mask
+ *   @3: UID
+ *   @4: UID
+ * Description:
+ * Some channel paths have a different UID than others. This indicates
+ * an incorrect cabling. The DASD device is not enabled.
+ * User action:
+ * Check cabling of the DASD device and retry to enable the device.
+ */
+
+/*?
+ * Text: "Service on the storage server caused path %x.%02x to go offline"
+ * Severity: Warning
+ * Parameter:
+ *   @1: channel subsystem ID
+ *   @2: CHPID
+ * Description:
+ * A channel path to the DASD has been set offline because of
+ * a service action on the storage server. The path will be set back
+ * online automatically when the service action is completed.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "Path %x.%02x is back online after service on the storage server"
+ * Severity: Informational
+ * Parameter:
+ *   @1: channel subsystem ID
+ *   @2: CHPID
+ * Description:
+ * A path had been set offline temporarily because of a service
+ * action on the storage server.
+ * The service action has completed, and the channel path is available
+ * again.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "%s: High Performance FICON disabled\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * High Performance FICON (HPF) has been disabled. Either the device
+ * lost HPF functionality, or none of the remaining channel paths are
+ * HPF capable.
+ * User action:
+ * Report the problem to your support organization.
+ * Ensure that the cabling between the storage server and the mainframe
+ * system is securely in place.
+ * Reset the device and channel paths by writing "all" or a logical path mask
+ * to the path_reset sysfs attribute of the device.
+ */
+
+/*?
+ * Text: "%s: Channel path %02X lost HPF functionality and is disabled\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: logical path mask
+ * Description:
+ * A channel path has lost High Performance FICON (HPF) functionality
+ * and was removed from regular operations.
+ * User action:
+ * Report the problem to your support organization.
+ * Ensure that the cabling between the storage server and the mainframe
+ * system is securely in place.
+ * Reset the device and channel paths by writing "all" or a logical path mask
+ * to the path_reset sysfs attribute of the device.
+ */
+
+/*?
+ * Text: "%s: Path %x.%02x (pathmask %02x) is disabled - IFCC threshold exceeded\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: cssid
+ *   @3: chpid
+ *   @4: logical path mask
+ * Description:
+ * Due to numerous interface or channel control checks (IFCCs), a channel path
+ * was removed from regular operations to retain good I/O performance.
+ * User action:
+ * Ensure that the cabling between the storage server and the mainframe
+ * system is securely in place.
+ * Reset the device and channel paths by writing "all" or a logical path mask
+ * to the path_reset sysfs attribute of the device.
+ * If the problem persists, report it to your support organization.
+ */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/dasd-fba
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/dasd-fba
@@ -0,0 +1,36 @@
+
+/*?
+ * Text: "%s: New FBA DASD %04X/%02X (CU %04X/%02X) with %d MB and %d B/blk%s\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: bus ID of the DASD
+ *   @2: device type
+ *   @3: device model
+ *   @4: control unit type
+ *   @5: control unit model
+ *   @6: size
+ *   @7: bytes per block
+ *   @8: access mode
+ * Description:
+ * A DASD with the shown characteristics has been set online.
+ * If the DASD is configured as read-only to the real or virtual hardware,
+ * the message includes an indication of this hardware access mode. The
+ * hardware access mode is independent from the 'readonly' attribute of
+ * the device in sysfs.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "%s: Allocating memory for private DASD data failed\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the DASD
+ * Description:
+ * The DASD device driver maintains data structures for each DASD it manages.
+ * There is not enough memory to allocate these data structures for one or
+ * more DASD.
+ * User action:
+ * Free some memory and try the operation again.
+ */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/dcssblk
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/dcssblk
@@ -0,0 +1,206 @@
+/*?
+ * Text: "Adjacent DCSSs %s and %s are not contiguous\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: name 1
+ *   @2: name 2
+ * Description:
+ * You can only map a set of two or more DCSSs to a single DCSS device if the
+ * DCSSs in the set form a contiguous memory space. The DCSS device cannot be
+ * created because there is a memory gap between two adjacent DCSSs.
+ * User action:
+ * Ensure that you have specified all DCSSs that belong to the set. Check the
+ * definitions of the DCSSs on the z/VM hypervisor to verify that they form
+ * a contiguous memory space.
+ */
+
+/*?
+ * Text: "DCSS %s and DCSS %s have incompatible types\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: name 1
+ *   @2: name 2
+ * Description:
+ * You can only map a set of two or more DCSSs to a single DCSS device if
+ * either all DCSSs in the set have the same type or if the set contains DCSSs
+ * of the two types EW and EN but no other type. The DCSS device cannot be
+ * created because at least two of the specified DCSSs are not compatible.
+ * User action:
+ * Check the definitions of the DCSSs on the z/VM hypervisor to verify that
+ * their types are compatible.
+ */
+
+/*?
+ * Text: "DCSS %s is of type SC and cannot be loaded as exclusive-writable\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: device name
+ * Description:
+ * You cannot load a DCSS device in exclusive-writable access mode if the DCSS
+ * devise maps to one or more DCSSs of type SC.
+ * User action:
+ * Load the DCSS in shared access mode.
+ */
+
+/*?
+ * Text: "DCSS device %s is removed after a failed access mode change\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: device name
+ * Description:
+ * To change the access mode of a DCSS device, all DCSSs that map to the device
+ * were unloaded. Reloading the DCSSs for the new access mode failed and the
+ * device is removed.
+ * User action:
+ * Look for related messages to find out why the DCSSs could not be reloaded.
+ * If necessary, add the device again.
+ */
+
+/*?
+ * Text: "All DCSSs that map to device %s are saved\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: device name
+ * Description:
+ * A save request has been submitted for the DCSS device. Changes to all DCSSs
+ * that map to the device are saved permanently.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "Device %s is in use, its DCSSs will be saved when it becomes idle\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: device name
+ * Description:
+ * A save request for the device has been deferred until the device becomes
+ * idle. Then changes to all DCSSs that the device maps to will be saved
+ * permanently.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "A pending save request for device %s has been canceled\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: device name
+ * Description:
+ * A save request for the DCSSs that map to a DCSS device has been pending
+ * while the device was in use. This save request has been canceled. Changes to
+ * the DCSSs will not be saved permanently.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "Loaded %s with total size %lu bytes and capacity %lu sectors\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: DCSS names
+ *   @2: total size in bytes
+ *   @3: total size in 512 byte sectors
+ * Description:
+ * The listed DCSSs have been verified as contiguous and successfully loaded.
+ * The displayed sizes are the sums of all DCSSs.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "Device %s cannot be removed because it is not a known device\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: device name
+ * Description:
+ * The DCSS device you are trying to remove is not known to the DCSS device
+ * driver.
+ * User action:
+ * List the entries under /sys/devices/dcssblk/ to see the names of the
+ * existing DCSS devices.
+ */
+
+/*?
+ * Text: "Device %s cannot be removed while it is in use\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: device name
+ * Description:
+ * You are trying to remove a device that is in use.
+ * User action:
+ * Make sure that all users of the device close the device before you try to
+ * remove it.
+ */
+
+/*?
+ * Text: "Device %s has become idle and is being saved now\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: device name
+ * Description:
+ * A save request for the DCSSs that map to a DCSS device has been pending
+ * while the device was in use. The device has become idle and all changes
+ * to the DCSSs are now saved permanently.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "Writing to %s failed because it is a read-only device\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: device name
+ * Description:
+ * The DCSS device is in shared access mode and cannot be written to. Depending
+ * on the type of the DCSSs that the device maps to, you might be able to
+ * change the access mode to exclusive-writable.
+ * User action:
+ * If the DCSSs of the device are of type SC, do not attempt to write to the
+ * device. If the DCSSs of the device are of type ER or SR, change the access
+ * mode to exclusive-writable before writing to the device.
+ */
+
+/*?
+ * Text: "The address range of DCSS %s changed while the system was suspended\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: device name
+ * Description:
+ * After resuming the system, the start address or end address of a DCSS does
+ * not match the address when the system was suspended. DCSSs must not be
+ * changed after the system was suspended.
+ * This error cannot be recovered. The system is stopped with a kernel panic.
+ * User action:
+ * Reboot Linux.
+ */
+
+/*?
+ * Text: "Suspending the system failed because DCSS device %s is writable\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: device name
+ * Description:
+ * A system cannot be suspended if one or more DCSSs are accessed in exclusive-
+ * writable mode. DCSS segment types EW, SW, and EN are always writable and
+ * must be removed before a system is suspended.
+ * User action:
+ * Remove all DCSSs of segment types EW, SW, and EN by writing the DCSS name to
+ * the sysfs 'remove' attribute. Set the access mode for all DCSSs of segment
+ * types SR and ER to read-only by writing 1 to the sysfs 'shared' attribute of
+ * the DCSS. Then try again to suspend the system.
+ */
+
+/*?
+ * Text: "DCSS %s is of type SN or EN and cannot be saved\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: DCSS name
+ * Description:
+ * DCSSs of type SN or EN cannot be saved.
+ * User action:
+ * If the DCSS was set up with the intention to prevent the content from being saved,
+ * no action is necessary.
+ * To be able to save the content, you must define the DCSS with a type other than SN or EN.
+ */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/diag288_wdt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/diag288_wdt
@@ -0,0 +1,66 @@
+/*?
+ * Text: "The watchdog cannot be activated\n"
+ * Severity: Error
+ * Description:
+ * Diagnose instruction 0x288 was called to activate the diag288 watchdog.
+ * The diagnose call returned an error that cannot be handled by the device driver.
+ * The watchdog stays inactive.
+ * User action:
+ * Contact your support organization.
+ */
+
+/*?
+ * Text: "The watchdog cannot be initialized\n"
+ * Severity: Error
+ * Description:
+ * Diagnose instruction 0x288 was called to initialize the diag288 watchdog.
+ * The diagnose call returned an error that cannot be handled by the device driver.
+ * The watchdog stays inactive.
+ * A possible reason for this error is that your real or virtual hardware does not support
+ * the diag288 watchdog.
+ * User action:
+ * Confirm that the diag288 watchdog is supported in your environment.
+ * Use a watchdog that is supported in your environment.
+ */
+
+/*?
+ * Text: "The watchdog cannot be deactivated\n"
+ * Severity: Error
+ * Description:
+ * Diagnose instruction 0x288 was called to deactivate the diag288 watchdog.
+ * The diagnose call returned an error that cannot be handled by the device driver.
+ * The watchdog stays active and a watchdog timeout will trigger the configured timeout action.
+ * The diag288 watchdog device driver might intentionally be configured to prevent deactivation.
+ * User action:
+ * You can configure the diag288 watchdog device driver such that it can be deactivated.
+ * If the diag288 device driver has been compiled as a separate module, diag288_wdt, reload the module
+ * without specifying the 'nowayout' module parameter.
+ * If the diag288 device driver has been compiled into your kernel,
+ * reboot Linux without specifying the 'diag288.nowayout' kernel parameter'.
+ */
+
+/*?
+ * Text: "The watchdog timer cannot be started or reset\n"
+ * Severity: Error
+ * Description:
+ * Diagnose instruction 0x288 was called to start the diag288 watchdog or to set timer back to zero.
+ * The diagnose call returned an error that cannot be handled by the device driver.
+ * The watchdog stays inactive or becomes inactive.
+ * User action:
+ * Contact your support organization.
+ */
+
+/*?
+ * Text: "Linux cannot be suspended while the watchdog is in use\n"
+ * Severity: Error
+ * Description:
+ * The watchdog must not time out while Linux is suspended.
+ * Therefore, the diag288 watchdog device driver prevents Linux from being suspended
+ * while the watchdog is in use.
+ * User action:
+ * i) Stop the watchdog application. ii) If the problem persists, close the watchdog
+ * device node by issuing 'echo V > /dev/watchdog'.
+ * iii) If the device driver still prevents Linux from being suspended,
+ * contact your support organization.
+ */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/extmem
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/extmem
@@ -0,0 +1,293 @@
+/*?
+ * Text: "Querying a DCSS type failed with rc=%ld\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: return code
+ * Description:
+ * The DCSS kernel interface used z/VM diagnose call X'64' to query the
+ * type of a DCSS. z/VM failed to determine the type and returned an error.
+ * User action:
+ * Look for related messages to find out which DCSS is affected.
+ * For details about the return codes see the section about DIAGNOSE Code
+ * X'64' in "z/VM CP Programming Services".
+ */
+
+/*?
+ * Text: "Loading DCSS %s failed with rc=%ld\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: DCSS name
+ *   @2: return code
+ * Description:
+ * The DCSS kernel interface used diagnose call X'64' to load a DCSS. z/VM
+ * failed to load the DCSS and returned an error.
+ * User action:
+ * For details about the return codes see the section about DIAGNOSE Code
+ * X'64' in "z/VM CP Programming Services".
+ */
+
+/*?
+ * Text: "DCSS %s of range %p to %p and type %s loaded as exclusive-writable\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: DCSS name
+ *   @2: starting page address
+ *   @3: ending page address
+ *   @4: DCSS type
+ * Description:
+ * The DCSS was loaded successfully in exclusive-writable access mode.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "DCSS %s of range %p to %p and type %s loaded in shared access mode\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: DCSS name
+ *   @2: starting page address
+ *   @3: ending page address
+ *   @4: DCSS type
+ * Description:
+ * The DCSS was loaded successfully in shared access mode.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "DCSS %s is already in the requested access mode\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: DCSS name
+ * Description:
+ * A request to reload a DCSS with a new access mode has been rejected
+ * because the new access mode is the same as the current access mode.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "DCSS %s is in use and cannot be reloaded\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: DCSS name
+ * Description:
+ * Reloading a DCSS in a different access mode has failed because the DCSS is
+ * being used by one or more device drivers. The DCSS remains loaded with the
+ * current access mode.
+ * User action:
+ * Ensure that the DCSS is not used by any device driver then try again to
+ * load the DCSS with the new access mode.
+ */
+
+/*?
+ * Text: "DCSS %s overlaps with used memory resources and cannot be reloaded\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: DCSS name
+ * Description:
+ * The DCSS has been unloaded and cannot be reloaded because it overlaps with
+ * another loaded DCSS or with the memory of the z/VM guest virtual machine
+ * (guest storage).
+ * User action:
+ * Ensure that no DCSS is loaded that has overlapping memory resources
+ * with the DCSS you want to reload. If the DCSS overlaps with guest storage,
+ * use the DEF STORE CONFIG z/VM CP command to create a sufficient storage gap
+ * for the DCSS. For details, see the section about the DCSS device driver in
+ * "Device Drivers, Features, and Commands".
+ */
+
+/*?
+ * Text: "Reloading DCSS %s failed with rc=%ld\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: DCSS name
+ *   @2: return code
+ * Description:
+ * The DCSS kernel interface used z/VM diagnose call X'64' to reload a DCSS
+ * in a different access mode. The DCSS was unloaded but z/VM failed to reload
+ * the DCSS.
+ * User action:
+ * For details about the return codes see the section about DIAGNOSE Code
+ * X'64' in "z/VM CP Programming Services".
+ */
+
+/*?
+ * Text: "Unloading unknown DCSS %s failed\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: DCSS name
+ * Description:
+ * The specified DCSS cannot be unloaded. The DCSS is known to the DCSS device
+ * driver but not to the DCSS kernel interface. This problem indicates a
+ * program error in extmem.c.
+ * User action:
+ * Report this problem to your support organization.
+ */
+
+/*?
+ * Text: "Saving unknown DCSS %s failed\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: DCSS name
+ * Description:
+ * The specified DCSS cannot be saved. The DCSS is known to the DCSS device
+ * driver but not to the DCSS kernel interface. This problem indicates a
+ * program error in extmem.c.
+ * User action:
+ * Report this problem to your support organization.
+ */
+
+/*?
+ * Text: "Saving a DCSS failed with DEFSEG response code %i\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: response-code
+ * Description:
+ * The DEFSEG z/VM CP command failed to permanently save changes to a DCSS.
+ * User action:
+ * Ensure that the z/VM guest virtual machine is authorized to issue
+ * the CP DEFSEG command (typically privilege class E).
+ * Look for related messages to find the cause of this error. See also message
+ * HCP<response-code>E in the DEFSEG section of the "z/VM CP Command and
+ * Utility Reference".
+ */
+
+/*?
+ * Text: "Saving a DCSS failed with SAVESEG response code %i\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: response-code
+ * Description:
+ * The SAVESEG z/VM CP command failed to permanently save changes to a DCSS.
+ * User action:
+ * Ensure that the z/VM guest virtual machine is authorized to issue
+ * the CP SAVESEG command (typically privilege class E).
+ * Look for related messages to find the cause of this error. See also message
+ * HCP<response-code>E in the SAVESEG section of the "z/VM CP Command and
+ * Utility Reference".
+ */
+
+/*?
+ * Text: "DCSS %s cannot be loaded or queried\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: DCSS name
+ * Description:
+ * You cannot load or query the specified DCSS because it either is not defined
+ * in the z/VM hypervisor, or it is a class S DCSS, or it is above 2047 MB
+ * and the Linux system is a 31-bit system.
+ * User action:
+ * Use the CP command "QUERY NSS" to find out if the DCSS is a valid
+ * DCSS that can be loaded.
+ */
+
+/*?
+ * Text: "DCSS %s cannot be loaded or queried without z/VM\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: DCSS name
+ * Description:
+ * A DCSS is a z/VM resource. Your Linux instance is not running as a z/VM
+ * guest operating system and, therefore, cannot load DCSSs.
+ * User action:
+ * Load DCSSs only on Linux instances that run as z/VM guest operating systems.
+ */
+
+/*?
+ * Text: "Loading or querying DCSS %s resulted in a hardware error\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: DCSS name
+ * Description:
+ * Either the z/VM DIAGNOSE X'64' query or load call issued for the DCSS
+ * returned with an error.
+ * User action:
+ * Look for previous extmem message to find the return code from the
+ * DIAGNOSE X'64' query or load call. For details about the return codes see
+ * the section about DIAGNOSE Code X'64' in "z/VM CP Programming Services".
+ */
+
+/*?
+ * Text: "DCSS %s has multiple page ranges and cannot be loaded or queried\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: DCSS name
+ * Description:
+ * You can only load or query a DCSS with multiple page ranges if:
+ * - The DCSS has 6 or fewer page ranges
+ * - The page ranges form a contiguous address space
+ * - The page ranges are of type EW or EN
+ * User action:
+ * Check the definition of the DCSS to make sure that the conditions for
+ * DCSSs with multiple page ranges are met.
+ */
+
+/*?
+ * Text: "%s needs used memory resources and cannot be loaded or queried\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: DCSS name
+ * Description:
+ * You cannot load or query the DCSS because it overlaps with an already
+ * loaded DCSS or with the memory of the z/VM guest virtual machine
+ * (guest storage).
+ * User action:
+ * Ensure that no DCSS is loaded that has overlapping memory resources
+ * with the DCSS you want to load or query. If the DCSS overlaps with guest
+ * storage, use the DEF STORE CONFIG z/VM CP command to create a sufficient
+ * storage gap for the DCSS. For details, see the section about the DCSS
+ * device driver in "Device Drivers, Features, and Commands".
+ */
+
+/*?
+ * Text: "DCSS %s is already loaded in a different access mode\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: DCSS name
+ * Description:
+ * The DCSS you are trying to load has already been loaded in a different
+ * access mode. You cannot simultaneously load the DCSS in different modes.
+ * User action:
+ * Reload the DCSS in a different mode or load it with the same mode in which
+ * it has already been loaded.
+ */
+
+/*?
+ * Text: "There is not enough memory to load or query DCSS %s\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: DCSS name
+ * Description:
+ * The available memory is not enough to load or query the DCSS.
+ * User action:
+ * Free some memory and repeat the failed operation.
+ */
+
+/*?
+ * Text: "DCSS %s overlaps with used storage and cannot be loaded\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: DCSS name
+ * Description:
+ * You cannot load the DCSS because it overlaps with an already loaded DCSS
+ * or with the memory of the z/VM guest virtual machine (guest storage).
+ * User action:
+ * Ensure that no DCSS is loaded that has overlapping memory resources
+ * with the DCSS you want to load. If the DCSS overlaps with guest storage,
+ * use the DEF STORE CONFIG z/VM CP command to create a sufficient storage gap
+ * for the DCSS. For details, see the section about the DCSS device driver in
+ * "Device Drivers, Features, and Commands".
+ */
+
+/*?
+ * Text: "DCSS %s exceeds the kernel mapping range (%lu) and cannot be loaded\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: DCSS name
+ *   @2: kernel mapping range in bytes
+ * Description:
+ * You cannot load the DCSS because it exceeds the kernel mapping range limit.
+ * User action:
+ * Ensure that the DCSS range is defined below the kernel mapping range.
+ */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/hmcdrv
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/hmcdrv
@@ -0,0 +1,22 @@
+/*?
+ * Text: "Allocating the requested cache size of %zu bytes failed\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: size
+ * Description:
+ * You cannot use the 'hmcdrv' module.
+ * Either the cache size that was specified for the 'hmcdrv' module exceeded
+ * the maximum of 1048576 (1 megabyte), or not enough free memory was
+ * available.
+ * If the 'hmcdrv' module was compiled into the kernel, the cache size was
+ * specified with the 'hmcdrv.cachesize' kernel parameter.
+ * For a separate 'hmcdrv' module, the cache size was specified with the
+ * 'cachesize=' module parameter.
+ * User action:
+ * Specify a smaller cache size and try again to load the module.
+ * Do not exceed the maximum specification of 1048576 (1 megabyte).
+ * If necessary, free some memory and try again.
+ * If the module is compiled into the kernel, you must reboot Linux to change
+ * the cache size specification.
+ */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/hugetlb
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/hugetlb
@@ -0,0 +1,13 @@
+/*?
+ * Text: "hugepagesz= specifies an unsupported page size %s\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: size
+ * Description:
+ * The hugepagesz= kernel parameter specifies a huge page size
+ * that is not supported.
+ * User action:
+ * Specify "1M" for 1 MB huge pages. These are supported as of z10.
+ * Specify "2G" for 2 GB huge pages. These are supported as of zEC12
+ * and zBC12 machines.
+ */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/hvc_iucv
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/hvc_iucv
@@ -0,0 +1,123 @@
+/*?
+ * Text: "The z/VM IUCV HVC device driver cannot be used without z/VM\n"
+ * Severity: Notice
+ * Description:
+ * The z/VM IUCV hypervisor console (HVC) device driver requires the
+ * z/VM inter-user communication vehicle (IUCV).
+ * User action:
+ * Set "hvc_iucv=" to zero in the kernel parameter line and reboot Linux.
+ */
+
+/*?
+ * Text: "%lu is not a valid value for the hvc_iucv= kernel parameter\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: hvc_iucv_devices
+ * Description:
+ * The "hvc_iucv=" kernel parameter specifies the number of z/VM IUCV
+ * hypervisor console (HVC) terminal devices.
+ * The parameter value ranges from 0 to 8.
+ * If zero is specified, the z/VM IUCV HVC device driver is disabled
+ * and no IUCV-based terminal access is available.
+ * User action:
+ * Correct the "hvc_iucv=" setting in the kernel parameter line and
+ * reboot Linux.
+ */
+
+/*?
+ * Text: "Creating a new HVC terminal device failed with error code=%d\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: errno
+ * Description:
+ * The device driver initialization failed to allocate a new
+ * HVC terminal device.
+ * A possible cause of this problem is memory constraints.
+ * User action:
+ * If the error code is -12 (ENOMEM), consider assigning more memory
+ * to your z/VM guest virtual machine.
+ */
+
+/*?
+ * Text: "Registering HVC terminal device as Linux console failed\n"
+ * Severity: Error
+ * Description:
+ * The device driver initialization failed to set up the first HVC terminal
+ * device for use as Linux console.
+ * User action:
+ * If the error code is -12 (ENOMEM), consider assigning more memory
+ * to your z/VM guest virtual machine.
+ */
+
+/*?
+ * Text: "Registering IUCV handlers failed with error code=%d\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: errno
+ * Description:
+ * The device driver initialization failed to register with z/VM IUCV to
+ * handle IUCV connections, as well as sending and receiving of IUCV messages.
+ * User action:
+ * Check for related IUCV error messages and see the errno manual page
+ * to find out what caused the problem.
+ */
+
+/*?
+ * Text: "Allocating memory failed with reason code=%d\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: reason
+ * Description:
+ * The z/VM IUCV hypervisor console (HVC) device driver initialization failed,
+ * because of a general memory allocation failure. The reason code indicates
+ * the memory operation that has failed:
+ * 	kmem_cache (reason code=1),
+ * 	mempool (reason code=2), or
+ * 	hvc_iucv_allow= (reason code=3)
+ * User action:
+ * Consider assigning more memory to your z/VM guest virtual machine.
+ */
+
+/*?
+ * Text: "hvc_iucv_allow= does not specify a valid z/VM user ID list\n"
+ * Severity: Error
+ * Description:
+ * The "hvc_iucv_allow=" kernel parameter specifies a comma-separated list
+ * of z/VM user IDs that are permitted to connect to the z/VM IUCV hypervisor
+ * device driver.
+ * The z/VM user IDs in the list must not exceed eight characters and must
+ * not contain spaces.
+ * User action:
+ * Correct the "hvc_iucv_allow=" setting in the kernel parameter line and reboot
+ * Linux.
+ */
+
+/*?
+ * Text: "hvc_iucv_allow= specifies too many z/VM user IDs\n"
+ * Severity: Error
+ * Description:
+ * The "hvc_iucv_allow=" kernel parameter specifies a comma-separated list
+ * of z/VM user IDs that are permitted to connect to the z/VM IUCV hypervisor
+ * device driver.
+ * The number of z/VM user IDs that are specified with the "hvc_iucv_allow="
+ * kernel parameter exceeds the maximum of 500.
+ * User action:
+ * Correct the "hvc_iucv_allow=" setting by reducing the z/VM user IDs in
+ * the list and reboot Linux.
+ */
+
+/*?
+ * Text: "A connection request from z/VM user ID %s was refused\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: ID
+ * Description:
+ * An IUCV connection request from another z/VM guest virtual machine has been
+ * refused. The request was from a z/VM guest virtual machine that is not
+ * listed by the "hvc_iucv_allow=" kernel parameter.
+ * User action:
+ * Check the "hvc_iucv_allow=" kernel parameter setting.
+ * Consider adding the z/VM user ID to the "hvc_iucv_allow=" list in the kernel
+ * parameter line and reboot Linux.
+ */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/hypfs
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/hypfs
@@ -0,0 +1,56 @@
+/*?
+ * Text: "The hardware system does not support hypfs\n"
+ * Severity: Error
+ * Description:
+ * hypfs requires DIAGNOSE Code X'204' but this diagnose code is not available
+ * on your hardware. You need more recent hardware to use hypfs.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "The hardware system does not provide all functions required by hypfs\n"
+ * Severity: Error
+ * Description:
+ * hypfs requires DIAGNOSE Code X'224' but this diagnode code is not available
+ * on your hardware. You need more recent hardware to use hypfs.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "Updating the hypfs tree failed\n"
+ * Severity: Error
+ * Description:
+ * There was not enough memory available to update the hypfs tree.
+ * User action:
+ * Free some memory and try again to update the hypfs tree. Consider assigning
+ * more memory to your LPAR or z/VM guest virtual machine.
+ */
+
+/*?
+ * Text: "%s is not a valid mount option\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: mount option
+ * Description:
+ * hypfs has detected mount options that are not valid.
+ * User action:
+ * See "Device Drivers Features and Commands" for information about valid
+ * mount options for hypfs.
+ */
+
+/*?
+ * Text: "Initialization of hypfs failed with rc=%i\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: error code
+ * Description:
+ * Initialization of hypfs failed because of resource or hardware constraints.
+ * Possible reasons for this problem are insufficient free memory or missing
+ * hardware interfaces.
+ * User action:
+ * See errno.h for information about the error codes.
+ */
+
+/*? Text: "Hypervisor filesystem mounted\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/iucv
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/iucv
@@ -0,0 +1,33 @@
+/*?
+ * Text: "Defining an interrupt buffer on CPU %i failed with 0x%02x (%s)\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: CPU number
+ *   @2: hexadecimal error value
+ *   @3: short error code explanation
+ * Description:
+ * Defining an interrupt buffer for external interrupts failed. Error
+ * value 0x03 indicates a problem with the z/VM directory entry of the
+ * z/VM guest virtual machine. This problem can also be caused by a
+ * program error.
+ * User action:
+ * If the error value is 0x03, examine the z/VM directory entry of your
+ * z/VM guest virtual machine. If the directory entry is correct or if the
+ * error value is not 0x03, report this problem to your support organization.
+ */
+
+/*?
+ * Text: "Suspending Linux did not completely close all IUCV connections\n"
+ * Severity: Warning
+ * Description:
+ * When resuming a suspended Linux instance, the IUCV base code found
+ * data structures from one or more IUCV connections that existed before the
+ * Linux instance was suspended. Modules that use IUCV connections must close
+ * these connections when a Linux instance is suspended. This problem
+ * indicates an error in a program that used an IUCV connection.
+ * User action:
+ * Report this problem to your support organization.
+ */
+
+/*? Text: "iucv_external_interrupt: out of memory\n" */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/lcs
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/lcs
@@ -0,0 +1,169 @@
+/*?
+ * Text: "%s:  Allocating a socket buffer to interface %s failed\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the LCS device
+ *   @2: network interface
+ * Description:
+ * LAN channel station (LCS) devices require a socket buffer (SKB) structure
+ * for storing incoming data. The LCS device driver failed to allocate an SKB
+ * structure to the LCS device. A likely cause of this problem is memory
+ * constraints.
+ * User action:
+ * Free some memory and repeat the failed operation.
+ */
+
+/*?
+ * Text: "%s:  Shutting down the LCS device failed\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the LCS device
+ * Description:
+ * A request to shut down a LAN channel station (LCS) device resulted in an
+ * error. The error is logged in the LCS trace at trace level 4.
+ * User action:
+ * Try again to shut down the device. If the error persists, see the LCS trace
+ * to find out what causes the error.
+ */
+
+/*?
+ * Text: "%s: Detecting a network adapter for LCS devices failed with rc=%d (0x%x)\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the LCS device
+ *   @2: lcs_detect return code in decimal notation
+ *   @3: lcs_detect return code in hexadecimal notation
+ * Description:
+ * The LCS device driver could not initialize a network adapter.
+ * User action:
+ * Ensure that the physical connection from the port to the network is
+ * in place. If the error persists, note the return code from the error
+ * message and contact IBM support.
+ */
+
+/*?
+ * Text: "%s: A recovery process has been started for the LCS device\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the LCS device
+ * Description:
+ * The LAN channel station (LCS) device is shut down and restarted. The recovery
+ * process might have been initiated by a user or started automatically as a
+ * response to a device problem.
+ * User action:
+ * Wait until a message indicates the completion of the recovery process.
+ */
+
+/*?
+ * Text: "%s: An I/O-error occurred on the LCS device\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the LCS device
+ * Description:
+ * The LAN channel station (LCS) device reported a problem that can be recovered
+ * by the LCS device driver. Repeated occurrences of this problem indicate a
+ * malfunctioning device.
+ * User action:
+ * If this problem occurs frequently, initiate a recovery process for the
+ * device, for example, by writing '1' to the 'recover' sysfs attribute of the
+ * device.
+ */
+
+/*?
+ * Text: "%s: A command timed out on the LCS device\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the LCS device
+ * Description:
+ * The LAN channel station (LCS) device reported a problem that can be recovered
+ * by the LCS device driver. Repeated occurrences of this problem indicate a
+ * malfunctioning device.
+ * User action:
+ * If this problem occurs frequently, initiate a recovery process for the
+ * device, for example, by writing '1' to the 'recover' sysfs attribute of the
+ * device.
+ */
+
+/*?
+ * Text: "%s: An error occurred on the LCS device, rc=%ld\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the LCS device
+ *   @2: return code
+ * Description:
+ * The LAN channel station (LCS) device reported a problem that can be recovered
+ * by the LCS device driver. Repeated occurrences of this problem indicate a
+ * malfunctioning device.
+ * User action:
+ * If this problem occurs frequently, initiate a recovery process for the
+ * device, for example, by writing '1' to the 'recover' sysfs attribute of the
+ * device.
+ */
+
+/*?
+ * Text: "%s: The LCS device stopped because of an error, dstat=0x%X, cstat=0x%X \n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the LCS device
+ *   @2: device status
+ *   @3: subchannel status
+ * Description:
+ * The LAN channel station (LCS) device reported an error. The LCS device driver
+ * might start a device recovery process.
+ * User action:
+ * If the device driver does not start a recovery process, initiate a recovery
+ * process, for example, by writing '1' to the 'recover' sysfs attribute of the
+ * device. If the problem persists, note the status information provided with
+ * the message and contact IBM support.
+ */
+
+/*?
+ * Text: "%s: Starting an LCS device resulted in an error, rc=%d!\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the LCS device
+ *   @2: ccw_device_start return code in decimal notation
+ * Description:
+ * The LAN channel station (LCS) device driver failed to initialize an LCS
+ * device. The device is not operational.
+ * User action:
+ * Initiate a recovery process, for example, by writing '1' to the 'recover'
+ * sysfs attribute of the device. If the problem persists, contact IBM support.
+ */
+
+/*?
+ * Text: "%s: Sending data from the LCS device to the LAN failed with rc=%d\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the LCS device
+ *   @2: ccw_device_resume return code in decimal notation
+ * Description:
+ * The LAN channel station (LCS) device driver could not send data to the LAN
+ * using the LCS device. This might be a temporary problem. Operations continue
+ * on the LCS device.
+ * User action:
+ * If this problem occurs frequently, initiate a recovery process, for example,
+ * by writing '1' to the 'recover' sysfs attribute of the device. If the
+ * problem persists, contact IBM support.
+ */
+
+/*? Text: "Query IPAssist failed. Assuming unsupported!\n" */
+/*? Text: "Stoplan for %s initiated by LGW\n" */
+/*? Text: "Not enough memory to add new multicast entry!\n" */
+/*? Text: "Not enough memory for debug facility.\n" */
+/*? Text: "Adding multicast address failed. Table possibly full!\n" */
+/*? Text: "Error in opening device!\n" */
+/*? Text: "LCS device %s %s IPv6 support\n" */
+/*? Text: "Device %s successfully recovered!\n" */
+/*? Text: "LCS device %s %s Multicast support\n" */
+/*? Text: " Initialization failed\n" */
+/*? Text: "Loading %s\n" */
+/*? Text: "Initialization failed\n" */
+/*? Text: "Terminating lcs module.\n" */
+/*? Text: "Device %s could not be recovered!\n" */
+/*? Text: "Initializing the lcs device driver failed\n" */
+/*? Text: "%s: The lcs device driver failed to recover the device\n" */
+/*? Text: "netif_stop_queue() cannot be called before register_netdev()\n" */
+/*? Text: "flen=%u proglen=%u pass=%u image=%pK from=%s pid=%d\n" */
+/*? Text: "%s selects TX queue %d, but real number of TX queues is %d\n" */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/monreader
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/monreader
@@ -0,0 +1,128 @@
+/*?
+ * Text: "Reading monitor data failed with rc=%i\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: return code
+ * Description:
+ * The z/VM *MONITOR record device driver failed to read monitor data
+ * because the IUCV REPLY function failed. The read function against
+ * the monitor record device returns EIO. All monitor data that has been read
+ * since the last read with 0 size is incorrect.
+ * User action:
+ * Disregard all monitor data that has been read since the last read with
+ * 0 size. If the device driver has been compiled as a separate module, unload
+ * and reload the monreader module. If the device driver has been compiled
+ * into the kernel, reboot Linux. For more information about possible causes
+ * of the error see the IUCV section in "z/VM CP Programming Services" and
+ * the *MONITOR section in "z/VM Performance".
+ */
+
+/*?
+ * Text: "z/VM *MONITOR system service disconnected with rc=%i\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: IPUSER SEVER return code
+ * Description:
+ * The z/VM *MONITOR record device driver receives monitor records through
+ * an IUCV connection to the z/VM *MONITOR system service. This connection
+ * has been severed and the read function of the z/VM *MONITOR device driver
+ * returns EIO. All data received since the last read with 0 size is incorrect.
+ * User action:
+ * Disregard all monitor data read since the last read with 0 size. Close and
+ * reopen the monitor record device. For information about the IPUSER SEVER
+ * return codes see "z/VM Performance".
+ */
+
+/*?
+ * Text: "The read queue for monitor data is full\n"
+ * Severity: Warning
+ * Description:
+ * The read function of the z/VM *MONITOR device driver returns EOVERFLOW
+ * because not enough monitor data has been read since the monitor device
+ * has been opened. Monitor data already read are valid and subsequent reads
+ * return valid data but some intermediate data might be missing.
+ * User action:
+ * Be aware that monitor data might be missing. Assure that you regularly
+ * read monitor data after opening the monitor record device.
+ */
+
+/*?
+ * Text: "Connecting to the z/VM *MONITOR system service failed with rc=%i\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: IUCV CONNECT return code
+ * Description:
+ * The z/VM *MONITOR record device driver receives monitor records through
+ * an IUCV connection to the z/VM *MONITOR system service. This connection
+ * could not be established when the monitor record device was opened. If
+ * the return code is 15, your z/VM guest virtual machine is not authorized
+ * to connect to the *MONITOR system service.
+ * User action:
+ * If the return code is 15, ensure that the IUCV *MONITOR statement is
+ * included in the z/VM directory entry for your z/VM guest virtual machine.
+ * For other IUCV CONNECT return codes see the IUCV section in "CP Programming
+ * Services" and the *MONITOR section in "z/VM  Performance".
+ */
+
+/*?
+ * Text: "Disconnecting the z/VM *MONITOR system service failed with rc=%i\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: IUCV SEVER return code
+ * Description:
+ * The z/VM *MONITOR record device driver receives monitor data through an
+ * IUCV connection to the z/VM *MONITOR system service. This connection
+ * could not be closed when the monitor record device was closed. You might
+ * not be able to resume monitoring.
+ * User action:
+ * No immediate action is necessary. If you cannot open the monitor record
+ * device in the future, reboot Linux. For information about the IUCV SEVER
+ * return codes see the IUCV section in "CP Programming Services" and the
+ * *MONITOR section in "z/VM  Performance".
+ */
+
+/*?
+ * Text: "The z/VM *MONITOR record device driver cannot be loaded without z/VM\n"
+ * Severity: Error
+ * Description:
+ * The z/VM *MONITOR record device driver uses z/VM system services to provide
+ * monitor data about z/VM guest operating systems to applications on Linux.
+ * On Linux instances that run in environments other than the z/VM hypervisor,
+ * the z/VM *MONITOR record device driver does not provide any useful
+ * function and the corresponding monreader module cannot be loaded.
+ * User action:
+ * Load the z/VM *MONITOR record device driver only on Linux instances that run
+ * as guest operating systems of the z/VM hypervisor. If the z/VM *MONITOR
+ * record device driver has been compiled into the kernel, ignore this message.
+ */
+
+/*?
+ * Text: "The z/VM *MONITOR record device driver failed to register with IUCV\n"
+ * Severity: Error
+ * Description:
+ * The z/VM *MONITOR record device driver receives monitor data through an IUCV
+ * connection and needs to register with the IUCV device driver. This
+ * registration failed and the z/VM *MONITOR record device driver was not
+ * loaded. A possible cause of this problem is insufficient memory.
+ * User action:
+ * Free some memory and try again to load the module. If the z/VM *MONITOR
+ * record device driver has been compiled into the kernel, you might have to
+ * configure more memory and reboot Linux. If you do not want to read monitor
+ * data, ignore this message.
+ */
+
+/*?
+ * Text: "The specified *MONITOR DCSS %s does not have the required type SC\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: DCSS name
+ * Description:
+ * The DCSS that was specified with the monreader.mondcss kernel parameter or
+ * with the mondcss module parameter cannot be a *MONITOR DCSS because it is
+ * not of type SC.
+ * User action:
+ * Confirm that you are using the name of the DCSS that has been configured as
+ * the *MONITOR DCSS on the z/VM hypervisor. If the default name, MONDCSS, is
+ * used, omit the monreader.mondcss or mondcss parameter.
+ */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/monwriter
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/monwriter
@@ -0,0 +1,17 @@
+/*?
+ * Text: "Writing monitor data failed with rc=%i\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: return code
+ * Description:
+ * The monitor stream application device driver used the z/VM diagnose call
+ * DIAG X'DC' to start writing monitor data. z/VM returned an error and the
+ * monitor data cannot be written. If the return code is 5, your z/VM guest
+ * virtual machine is not authorized to write monitor data.
+ * User action:
+ * If the return code is 5, ensure that your z/VM guest virtual machine's
+ * entry in the z/VM directory includes the OPTION APPLMON statement.
+ * For other return codes see the section about DIAGNOSE Code X'DC'
+ * in "z/VM CP Programming Services".
+ */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/netiucv
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/netiucv
@@ -0,0 +1,156 @@
+/*?
+ * Text: "%s: The peer interface of the IUCV device has closed the connection\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: bus ID of the IUCV device
+ * Description:
+ * The peer interface on the remote z/VM guest virtual machine has closed the
+ * connection. Do not expect further packets on this interface. Any packets
+ * you send to this interface will be dropped.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "%s: The IUCV device failed to connect to z/VM guest %s\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the IUCV device
+ *   @2: z/VM user ID
+ * Description:
+ * The connection cannot be established because the z/VM guest virtual
+ * machine with the peer interface is not running.
+ * User action:
+ * Ensure that the z/VM guest virtual machine with the peer interface is
+ * running; then try again to establish the connection.
+ */
+
+/*?
+ * Text: "%s: The IUCV device failed to connect to the peer on z/VM guest %s\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the IUCV device
+ *   @2: z/VM user ID
+ * Description:
+ * The connection cannot be established because the z/VM guest virtual machine
+ * with the peer interface is not configured for IUCV connections.
+ * User action:
+ * Configure the z/VM guest virtual machine with the peer interface for IUCV
+ * connections; then try again to establish the connection.
+ */
+
+/*?
+ * Text: "%s: Connecting the IUCV device would exceed the maximum number of IUCV connections\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the IUCV device
+ * Description:
+ * The connection cannot be established because the maximum number of IUCV
+ * connections has been reached on the local z/VM guest virtual machine.
+ * User action:
+ * Close some of the established IUCV connections on the local z/VM guest
+ * virtual machine; then try again to establish the connection.
+ */
+
+/*?
+ * Text: "%s: z/VM guest %s has too many IUCV connections to connect with the IUCV device\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the IUCV device
+ *   @2: remote z/VM user ID
+ * Description:
+ * Connecting to the remote z/VM guest virtual machine failed because the
+ * maximum number of IUCV connections for the remote z/VM guest virtual
+ * machine has been reached.
+ * User action:
+ * Close some of the established IUCV connections on the remote z/VM guest
+ * virtual machine; then try again to establish the connection.
+ */
+
+/*?
+ * Text: "%s: The IUCV device cannot connect to a z/VM guest with no IUCV authorization\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the IUCV device
+ * Description:
+ * Because the remote z/VM guest virtual machine is not authorized for IUCV
+ * connections, the connection cannot be established.
+ * User action:
+ * Add the statements 'IUCV ALLOW' and 'IUCV ANY' to the z/VM directory
+ * entry of the remote z/VM guest virtual machine; then try again to
+ * establish the connection. See "z/VM CP Planning and Administration"
+ * for details about the IUCV statements.
+ */
+
+/*?
+ * Text: "%s: Connecting the IUCV device failed with error %d\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the IUCV device
+ *   @2: error code
+ * Description:
+ * The connection cannot be established because of an IUCV CONNECT error.
+ * User action:
+ * Report this problem to your support organization.
+ */
+
+/*?
+ * Text: "%s: The IUCV device has been connected successfully to %s\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: bus ID of the IUCV device
+ *   @2: remote z/VM user ID
+ * Description:
+ * The connection has been established and the interface is ready to
+ * transmit communication packages.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "%s: The IUCV interface to %s has been established successfully\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: bus ID of the IUCV device
+ *   @2: remote z/VM user ID
+ * Description:
+ * The IUCV interface to the remote z/VM guest virtual machine has been
+ * established and can be activated with "ifconfig up" or an equivalent
+ * command.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "%s: The IUCV device is connected to %s and cannot be removed\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the IUCV device
+ *   @2: remote z/VM user ID
+ * Description:
+ * Removing a connection failed because the interface is active with a peer
+ * interface on a remote z/VM guest virtual machine.
+ * User action:
+ * Deactivate the interface with "ifconfig down" or an equivalent command;
+ * then try again to remove the interface.
+ */
+
+/*?
+ * Text: "%s: The peer z/VM guest %s has closed the connection\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: bus ID of the IUCV device
+ *   @2: remote z/VM user ID
+ * Description:
+ * The peer interface is no longer available.
+ * User action:
+ * Either deactivate and remove the interface, or wait for the peer
+ * z/VM guest to re-establish the interface.
+ */
+
+/*? Text: "driver unloaded\n" */
+/*? Text: "driver initialized\n" */
+/*? Text: "netif_stop_queue() cannot be called before register_netdev()\n" */
+/*? Text: "flen=%u proglen=%u pass=%u image=%pK from=%s pid=%d\n" */
+/*? Text: "%s selects TX queue %d, but real number of TX queues is %d\n" */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/numa
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/numa
@@ -0,0 +1,11 @@
+/*?
+ * Text: "NUMA mode: %s\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: mode
+ * Description:
+ * Linux started with the specified NUMA mode.
+ * User action:
+ * None.
+ */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/numa_emu
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/numa_emu
@@ -0,0 +1,50 @@
+/*?
+ * Text: "Not enough memory for %d nodes, reducing node count\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: requested number of nodes
+ * Description:
+ * Using the requested memory stripe size for emulating the requested number of
+ * NUMA nodes requires more than the available memory. The number of nodes is
+ * specified with the emu_nodes= kernel parameter. The memory stripe size to
+ * be used for distributing the available memory among the nodes is specified
+ * with the emu_size= kernel parameter. Fewer nodes were created than the
+ * requested number; each node has one memory stripe of the requested size.
+ * User action:
+ * Specify fewer nodes, reduce the memory stripe size, or make more memory
+ * available to your Linux instance.
+ */
+
+/*?
+ * Text: "Creating %d nodes with memory stripe size %ld MB\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: number of nodes
+ *   @2: stripe size
+ * Description:
+ * NUMA emulation is activated with the reported number of NUMA nodes.
+ * The specified memory stripe size is used to distribute, in round-robin
+ * fashion, the available memory among the nodes.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "Increasing memory stripe size from %ld MB to %ld MB\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: requested memory stripe size
+ *   @2: adjusted memory stripe size
+ * Description:
+ * NUMA  emulation  could  not  use  the  requested memory stripe size and
+ * therefore has increased it to the next possible value.
+ * The requested memory stripe size is a default value or it was specified
+ * with the emu_size= kernel parameter.
+ * The memory stripe size must be a multiple of the memory block size that
+ * can be read in hexadecimal notation from
+ * /sys/devices/system/memory/block_size_bytes.
+ * User action:
+ * To avoid this message in the future, specify a valid memory stripe size
+ * with the emu_size= kernel parameter.
+ */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/os_info
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/os_info
@@ -0,0 +1,36 @@
+/*?
+ * Text: "entry %i: %s (addr=0x%lx size=%lu)\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: entry ID
+ *   @2: entry state
+ *   @3: entry address
+ *   @4: entry size
+ * Description:
+ * Linux is running in kdump mode and reports information defined by the
+ * previously running production kernel. Possible values for
+ * "entry state" are:
+ *
+ * - copied: The entry has been found, verified, and copied
+ *
+ * - not available: The entry has not been defined
+ *
+ * - checksum failed: The entry has been found, but it is not valid
+ * User action:
+ * If kdump fails, contact your service organization and include this message
+ * in the error report.
+ */
+
+/*?
+ * Text: "crashkernel: addr=0x%lx size=%lu\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: address
+ *   @2: size
+ * Description:
+ * Linux is running in kdump mode and reports the address and size of
+ * the memory area that was reserved for kdump by the previously running
+ * production kernel.
+ * User action:
+ * None.
+ */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/perf
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/perf
@@ -0,0 +1,90 @@
+/*?
+ * Text: "CPU[%i] CPUM_CF: ver=%u.%u A=%04x E=%04x C=%04x\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: cpu number
+ *   @2: first version number
+ *   @3: second version number
+ *   @4: counter set authorization
+ *   @5: counter set enable controls
+ *   @6: counter set activation controls
+ * Description:
+ * This message displays information about the CPU-measurement counter facility
+ * (CPUM_CF) on a particular CPU.  For details, see
+ * "The Load-Program-Parameter and the CPU-Measurement Facilities", SA23-2260.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "CPU[%i] CPUM_SF: basic=%i diag=%i min=%lu max=%lu cpu_speed=%u\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: cpu number
+ *   @2: authorization status for the basic-sampling function
+ *   @3: authorization status for the diagnostic-sampling function
+ *   @4: minimum sampling interval
+ *   @5: maximum sampling interval
+ *   @6: cpu speed
+ * Description:
+ * This message displays generic information about the CPU-measurement sampling
+ * facility (CPUM_SF) on a particular CPU.  For details, see
+ * "The Load-Program-Parameter and the CPU-Measurement Facilities", SA23-2260.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "CPU[%i] CPUM_SF: Basic-sampling: a=%i e=%i c=%i bsdes=%i tear=%016lx dear=%016lx\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: cpu number
+ *   @2: authorization control
+ *   @3: enable control
+ *   @4: activation control
+ *   @5: basic-sampling-data-entry size
+ *   @6: tear register contents
+ *   @7: dear register contents
+ * Description:
+ * This message displays information about the basic-sampling function of the
+ * CPU-measurement sampling facility (CPUM_SF) on a particular CPU.
+ * For details, see
+ * "The Load-Program-Parameter and the CPU-Measurement Facilities", SA23-2260.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "CPU[%i] CPUM_SF: Diagnostic-sampling: a=%i e=%i c=%i dsdes=%i tear=%016lx dear=%016lx\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: cpu number
+ *   @2: authorization control
+ *   @3: enable control
+ *   @4: activation control
+ *   @5: diagnostic-sampling-data-entry size
+ *   @6: tear register contents
+ *   @7: dear register contents
+ * Description:
+ * This message displays information about the diagnostic-sampling function of the
+ * CPU-measurement sampling facility (CPUM_SF) on a particular CPU.
+ * For details, see
+ * "The Load-Program-Parameter and the CPU-Measurement Facilities", SA23-2260.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "The sampling facility is already reserved by %p\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: address of perf sampling support owner
+ * Description:
+ * A process tried to reserve the sampling facility support, but it was already
+ * reserved by another process.
+ * User action:
+ * Check whether another process, for example, the perf program or OProfile is
+ * currently active.  Retry activating the sampling facility after the other
+ * process has ended.
+ */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/prng
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/prng
@@ -0,0 +1,103 @@
+/* prng */
+
+/*?
+ * Text: "prng runs in TDES mode with chunksize=%d and reseed_limit=%u\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: read chunk size in bytes
+ *   @2: reseed limit
+ * Description:
+ * The pseudo-random number device driver started in triple DES mode.
+ * For IBM mainframes earlier than IBM zEnterprise EC12 (zEC12),
+ * triple DES is the only available mode.
+ * As of zEC12, the preferred mode is SHA-512.
+ * User action:
+ * If triple DES is the expected mode, no action is required.
+ * Otherwise, verify that the prng started with the mode= module or
+ * prng.mode= kernel parameter set to a value other than 1.
+ * The value 1 forces triple DES mode. Also ensure that the mainframe
+ * runs with the latest firmware level.
+ */
+
+/*?
+ * Text: "The prng module stopped after running in triple DES mode\n"
+ * Severity: Informational
+ * Description:
+ * The pseudo-random number device driver was running in triple DES mode.
+ * The device driver module, prng, was unloaded, or it stopped
+ * because Linux shut down.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "The prng module cannot start in SHA-512 mode\n"
+ * Severity: Error
+ * Description:
+ * The pseudo-random number device driver was loaded with the mode= module parameter
+ * or the prng.mode= kernel parameter set to 2. This setting forces SHA-512 mode,
+ * but the required support for MSA 5 is not available. This support requires an IBM
+ * zEnterprise EC12 (zEC12) or later mainframe.
+ * User action:
+ * If your mainframe is earlier than zEC12, set the mode= module or
+ * prng.mode= kernel parameter to 0 or 1 to run the
+ * pseudo-random number device driver in triple DES mode.
+ * Otherwise, ensure that MSA 5 support available.
+ */
+
+/*?
+ * Text: "prng runs in SHA-512 mode with chunksize=%d and reseed_limit=%u\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: read chunk size in bytes
+ *   @2: reseed limit
+ * Description:
+ * The pseudo-random number device driver started in SHA-512 mode.
+ * As of IBM zEnterprise EC12, this is the preferred mode.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "The prng module stopped after running in SHA-512 mode\n"
+ * Severity: Informational
+ * Description:
+ * The pseudo-random number device driver was running in SHA-512 mode.
+ * The device driver module, prng, was unloaded, or stopped
+ * because Linux shut down.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "The prng self test state test for the SHA-512 mode failed\n"
+ * Severity: Error
+ * Description:
+ * The pseudo-random number device driver is not operational because the self test failed.
+ * After processing a published National Institute of Standards and Technology (NIST) test vector for the
+ * Deterministic Random Bit Generator (DRBG) algorithm, the device driver
+ * was not in the expected working state. This failure might indicate
+ * that the cryptographic software or hardware is not working correctly.
+ * The processed NIST test vector was: Hash Drbg, Sha-512, Count #0.
+ * User action:
+ * Unload and reload the prng module, or
+ * if prng was compiled into the kernel, restart Linux.
+ * If the error persists, contact your support organization.
+ */
+
+/*?
+ * Text: "The prng self test data test for the SHA-512 mode failed\n"
+ * Severity: Error
+ * Description:
+ * The pseudo-random number device driver is not operational because the self test failed.
+ * After processing a published National Institute of Standards and Technology (NIST) test vector for the
+ * Deterministic Random Bit Generator (DRBG) algorithm, the device driver
+ * did not produce the expected pseudo-random data. This failure might indicate
+ * that the cryptographic software or hardware is not working correctly.
+ * The processed NIST test vector was: Hash Drbg, Sha-512, Count #0.
+ * User action:
+ * Unload and reload the prng module, or
+ * if prng was compiled into the kernel, restart Linux.
+ * If the error persists, contact your support organization.
+ */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/qeth
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/qeth
@@ -0,0 +1,929 @@
+/*?
+ * Text: "%s: The LAN is offline\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ * Description:
+ * A start LAN command was sent by the qeth device driver but the physical or
+ * virtual adapter has not started the LAN. The LAN might take a few seconds
+ * to become available.
+ * User action:
+ * Check the status of the qeth device, for example, with the lsqeth command.
+ * If the device does not become operational within a few seconds, initiate a
+ * recovery process, for example, by writing '1' to the 'recover' sysfs
+ * attribute of the device.
+ */
+
+/*?
+ * Text: "%s: A recovery process has been started for the device\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ * Description:
+ * A recovery process was started either by the qeth device driver or through
+ * a user command.
+ * User action:
+ * Wait until a message indicates the completion of the recovery process.
+ */
+
+/*?
+ * Text: "%s: The qeth device driver failed to recover an error on the device\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ * Description:
+ * The qeth device driver performed an automatic recovery operation to recover
+ * an error on a qeth device. The recovery operation failed.
+ * User action:
+ * Try the following actions in the given order: i) Check the status of the
+ * qeth device, for example, with the lsqeth command. ii) Initiate a recovery
+ * process by writing '1' to the 'recover' sysfs attribute of the device.
+ * iii) Ungroup and regroup the subchannel triplet of the device. vi) Reboot
+ * Linux. v) If the problem persists, gather Linux debug data and report the
+ * problem to your support organization.
+ */
+
+/*?
+ * Text: "%s: Device recovery failed to restore all offload features\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ * Description:
+ * The qeth device driver performed a recovery operation on a qeth device. Part
+ * of the recovery is to restore the offload features that were enabled before
+ * the recovery. At least one of those offload features could not be restored.
+ * User action:
+ * Check which offload features are enabled on the device, for example with
+ * the "ethtool -k" command. Try to explicitly re-enable the missing offload
+ * features for the device, for example with the "ethtool -K" command.
+ */
+
+/*?
+ * Text: "%s: The link for interface %s on CHPID 0x%X failed\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ *   @2: network interface name
+ *   @3: CHPID
+ * Description:
+ * A network link failed. A possible reason for this error is that a physical
+ * network cable has been disconnected.
+ * User action:
+ * Ensure that the network cable on the adapter hardware is connected properly.
+ * If the connection is to a guest LAN, ensure that the device is still coupled
+ * to the guest LAN.
+ */
+
+/*?
+ * Text: "%s: The link for %s on CHPID 0x%X has been restored\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ *   @2: network interface name
+ *   @3: CHPID
+ * Description:
+ * A failed network link has been re-established. A device recovery is in
+ * progress.
+ * User action:
+ * Wait until a message indicates the completion of the recovery process.
+ */
+
+/*?
+ * Text: "%s: A hardware operation timed out on the device\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ * Description:
+ * A hardware operation timed out on the qeth device.
+ * User action:
+ * Check the status of the qeth device, for example, with the lsqeth command.
+ * If the device is not operational, initiate a recovery process, for example,
+ * by writing '1' to the 'recover' sysfs attribute of the device.
+ */
+
+/*?
+ * Text: "%s: The adapter hardware is of an unknown type\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ * Description:
+ * The qeth device driver does not recognize the adapter hardware. The cause
+ * of this problem could be a hardware error or a Linux level that does not
+ * support your adapter hardware.
+ * User action:
+ * i) Investigate if your adapter hardware is supported by your Linux level.
+ * Consider using hardware that is supported by your Linux level or upgrading
+ * to a Linux level that supports your hardware. ii) Install the latest
+ * firmware on your adapter hardware. iii) If the problem persists and is not
+ * caused by a version mismatch, contact IBM support.
+ */
+
+/*?
+ * Text: "%s: The adapter is used exclusively by another host\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ * Description:
+ * The qeth adapter is exclusively used by another host.
+ * User action:
+ * Use another qeth adapter or configure this one not exclusively to a
+ * particular host.
+ */
+
+/*?
+ * Text: "%s: QDIO reported an error, rc=%i\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ *   @2: return code
+ * Description:
+ * The QDIO subsystem reported an error.
+ * User action:
+ * Check for related QDIO errors. Check the status of the qeth device, for
+ * example, with the lsqeth command. If the device is not operational, initiate
+ * a recovery process, for example, by writing '1' to the 'recover' sysfs
+ * attribute of the device.
+ */
+
+/*?
+ * Text: "%s: There is no kernel module to support discipline %d\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ *   @2: discipline
+ * Description:
+ * The qeth device driver or a user command requested a kernel module for a
+ * particular qeth discipline. Either the discipline is not supported by the
+ * qeth device driver or the requested module is not available to your Linux
+ * system.
+ * User action:
+ * Check if the requested discipline module has been compiled into the kernel
+ * or is present in /lib/modules/<version>/kernel/drivers/s390/net.
+ */
+
+/*?
+ * Text: "Initializing the qeth device driver failed\n"
+ * Severity: Error
+ * Parameter:
+ * Description:
+ * The base module of the qeth device driver could not be initialized.
+ * User action:
+ * See errno.h to determine the reason for the error.
+ * i) Reboot Linux. ii) If the problem persists, gather Linux debug data and
+ * report the problem to your support organization.
+ */
+
+/*?
+ * Text: "%s: Registering IP address %s failed\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ *   @2: IP address
+ * Description:
+ * An IP address could not be registered with the network adapter.
+ * User action:
+ * Check if another operating system instance has already registered the
+ * IP address with the same network adapter or at the same logical IP subnet.
+ */
+
+/*?
+ * Text: "%s: Reading the adapter MAC address failed\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ * Description:
+ * The qeth device driver could not read the MAC address from the network
+ * adapter.
+ * User action:
+ * Ungroup and regroup the subchannel triplet of the device. If this does not
+ * resolve the problem, reboot Linux. If the problem persists, gather Linux
+ * debug data and report the problem to your support organization.
+ */
+
+/*?
+ * Text: "%s: Starting ARP processing support for %s failed\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ *   @2: network interface name
+ * Description:
+ * The qeth device driver could not start ARP support on the network adapter.
+ * User action:
+ * Ungroup and regroup the subchannel triplet of the device. If this does not
+ * resolve the problem, reboot Linux. If the problem persists, gather Linux
+ * debug data and report the problem to your support organization.
+ */
+
+/*?
+ * Text: "%s: Starting IP fragmentation support for %s failed\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ *   @2: network interface name
+ * Description:
+ * The qeth device driver could not start IP fragmentation support on the
+ * network adapter.
+ * User action:
+ * Ungroup and regroup the subchannel triplet of the device. If this does not
+ * resolve the problem, reboot Linux. If the problem persists, gather Linux
+ * debug data and report the problem to your support organization.
+ */
+
+/*?
+ * Text: "%s: Starting VLAN support for %s failed\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ *   @2: network interface name
+ * Description:
+ * The qeth device driver could not start VLAN support on the network adapter.
+ * User action:
+ * None if you do not require VLAN support. If you need VLAN support,
+ * ungroup and regroup the subchannel triplet of the device. If this does not
+ * resolve the problem, reboot Linux. If the problem persists, gather Linux
+ * debug data and report the problem to your support organization.
+ */
+
+/*?
+ * Text: "%s: Starting multicast support for %s failed\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ *   @2: network interface name
+ * Description:
+ * The qeth device driver could not start multicast support on the network
+ * adapter.
+ * User action:
+ * Ungroup and regroup the subchannel triplet of the device. If this does not
+ * resolve the problem, reboot Linux. If the problem persists, gather Linux
+ * debug data and report the problem to your support organization.
+ */
+
+/*?
+ * Text: "%s: Activating IPv6 support for %s failed\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ *   @2: network interface name
+ * Description:
+ * The qeth device driver could not activate IPv6 support on the network
+ * adapter.
+ * User action:
+ * None if you do not require IPv6 communication. If you need IPv6 support,
+ * ungroup and regroup the subchannel triplet of the device. If this does not
+ * resolve the problem, reboot Linux. If the problem persists, gather Linux
+ * debug data and report the problem to your support organization.
+ */
+
+/*?
+ * Text: "%s: Enabling the passthrough mode for %s failed\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ *   @2: network interface name
+ * Description:
+ * The qeth device driver could not enable the passthrough mode on the
+ * network adapter. The passthrough mode is required for all network traffic
+ * other than IPv4. In particular, the passthrough mode is required for IPv6
+ * traffic.
+ * User action:
+ * None if all you want to support is IPv4 communication. If you want to support
+ * IPv6 or other network traffic apart from IPv4, ungroup and regroup the
+ * subchannel triplet of the device. If this does not resolve the problem,
+ * reboot Linux. If the problem persists, gather Linux debug data and report
+ * the problem to your support organization.
+ */
+
+/*?
+ * Text: "%s: Enabling broadcast filtering for %s failed\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ *   @2: network interface name
+ * Description:
+ * The qeth device driver could not enable broadcast filtering on the network
+ * adapter.
+ * User action:
+ * Ungroup and regroup the subchannel triplet of the device. If this does not
+ * resolve the problem, reboot Linux. If the problem persists, gather Linux
+ * debug data and report the problem to your support organization.
+ */
+
+/*?
+ * Text: "%s: Setting up broadcast filtering for %s failed\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ *   @2: network interface name
+ * Description:
+ * The qeth device driver could not set up broadcast filtering on the network
+ * adapter.
+ * User action:
+ * Ungroup and regroup the subchannel triplet of the device. If this does not
+ * resolve the problem, reboot Linux. If the problem persists, gather Linux
+ * debug data and report the problem to your support organization.
+ */
+
+/*?
+ * Text: "%s: Setting up broadcast echo filtering for %s failed\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ *   @2: network interface name
+ * Description:
+ * The qeth device driver could not set up broadcast echo filtering on the
+ * network adapter.
+ * User action:
+ * Ungroup and regroup the subchannel triplet of the device. If this does not
+ * resolve the problem, reboot Linux. If the problem persists, gather Linux
+ * debug data and report the problem to your support organization.
+ */
+
+/*?
+ * Text: "%s: Starting HW checksumming for %s failed, using SW checksumming\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ *   @2: network interface name
+ * Description:
+ * The network adapter supports hardware checksumming for IP packages
+ * but the qeth device driver could not start hardware checksumming on the
+ * adapter. The qeth device driver continues to use software checksumming for
+ * IP packages.
+ * User action:
+ * None if you do not require hardware checksumming for network
+ * traffic. If you want to enable hardware checksumming, ungroup and regroup
+ * the subchannel triplet of the device. If this does not resolve the problem,
+ * reboot Linux. If the problem persists, gather Linux debug data and report
+ * the problem to your support organization.
+ */
+
+/*?
+ * Text: "%s: Enabling HW checksumming for %s failed, using SW checksumming\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ *   @2: network interface name
+ * Description:
+ * The network adapter supports hardware checksumming for IP packages
+ * but the qeth device driver could not enable hardware checksumming on the
+ * adapter. The qeth device driver continues to use software checksumming for
+ * IP packages.
+ * User action:
+ * None if you do not require hardware checksumming for network
+ * traffic. If you want to enable hardware checksumming, ungroup and regroup
+ * the subchannel triplet of the device. If this does not resolve the problem,
+ * reboot Linux. If the problem persists, gather Linux debug data and report
+ * the problem to your support organization.
+ */
+
+/*?
+ * Text: "%s: Starting outbound TCP segmentation offload for %s failed\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ *   @2: network interface name
+ * Description:
+ * The network adapter supports TCP segmentation offload, but the qeth device
+ * driver could not start this support on the adapter.
+ * User action:
+ * None if you do not require TCP segmentation offload. If you want to
+ * enable TCP segmentation offload, ungroup and regroup the subchannel triplet
+ * of the device. If this does not resolve the problem, reboot Linux. If the
+ * problem persists, gather Linux debug data and report the problem to your
+ * support organization.
+ */
+
+/*?
+ * Text: "%s: The network adapter failed to generate a unique ID\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ * Description:
+ * In IBM mainframe environments, network interfaces are not identified by
+ * a specific MAC address. Therefore, the network adapters provide the network
+ * interfaces with unique IDs to be used in their IPv6 link local addresses.
+ * Without such a unique ID, duplicate addresses might be assigned in other
+ * LPARs.
+ * User action:
+ * Install the latest firmware on the adapter hardware. Manually, configure
+ * an IPv6 link local address for this device.
+ */
+
+/*?
+ * Text: "There is no IPv6 support for the layer 3 discipline\n"
+ * Severity: Warning
+ * Description:
+ * If you want to use IPv6 with the layer 3 discipline, you need a Linux kernel
+ * with IPv6 support. Because your Linux kernel has not been compiled with
+ * IPv6 support, you cannot use IPv6 with the layer 3 discipline, even if your
+ * adapter supports IPv6.
+ * User action:
+ * Use a Linux kernel that has been complied to include IPv6 support if you
+ * want to use IPv6 with layer 3 qeth devices.
+ */
+
+/*?
+ * Text: "%s: The qeth device is not configured for the OSI layer required by z/VM\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ * Description:
+ * A qeth device that connects to a virtual network on z/VM must be configured for the
+ * same Open Systems Interconnection (OSI) layer as the virtual network. An ETHERNET
+ * guest LAN or VSWITCH uses the data link layer (layer 2) while an IP guest LAN
+ * or VSWITCH uses the network layer (layer 3).
+ * User action:
+ * If you are connecting to an ETHERNET guest LAN or VSWITCH, set the layer2 sysfs
+ * attribute of the qeth device to 1. If you are connecting to an IP guest LAN or
+ * VSWITCH, set the layer2 sysfs attribute of the qeth device to 0.
+ */
+
+/*?
+ * Text: "%s: Starting source MAC-address support for %s failed\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ *   @2: network interface name
+ * Description:
+ * The qeth device driver could not enable source MAC-address on the network
+ * adapter.
+ * User action:
+ * Ungroup and regroup the subchannel triplet of the device. If this does not
+ * resolve the problem, reboot Linux. If the problem persists, gather Linux
+ * debug data and report the problem to your support organization.
+ */
+
+/*?
+ * Text: "%s: MAC address %pM already exists\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ *   @2: MAC-address
+ * Description:
+ * Setting the MAC address for the qeth device fails, because this
+ * MAC address is already defined on the OSA CHPID.
+ * User action:
+ * Use a different MAC address for this qeth device.
+ */
+
+/*?
+ * Text: "%s: MAC address %pM is not authorized\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ *   @2: MAC-address
+ * Description:
+ * This qeth device is a virtual network interface card (NIC), to which z/VM
+ * has already assigned a MAC address. z/VM MAC address verification does
+ * not allow you to change this predefined address.
+ * User action:
+ * None; use the MAC address that has been assigned by z/VM.
+ */
+
+/*?
+ * Text: "%s: The HiperSockets network traffic analyzer is activated\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ * Description:
+ * The sysfs 'sniffer' attribute of the HiperSockets device has the value '1'.
+ * The corresponding HiperSockets interface has been switched into promiscuous mode.
+ * As a result, the HiperSockets network traffic analyzer is started on the device.
+ * User action:
+ * None.
+ */
+
+ /*?
+  * Text: "%s: The HiperSockets network traffic analyzer is deactivated\n"
+  * Severity: Informational
+  * Parameter:
+  *   @1: bus ID of the qeth device
+  * Description:
+  * The sysfs 'sniffer' attribute of the HiperSockets device has the value '1'.
+  * Promiscuous mode has been switched off for the corresponding HiperSockets interface
+  * As a result, the HiperSockets network traffic analyzer is stopped on the device.
+  * User action:
+  * None.
+  */
+
+/*?
+ * Text: "%s: The device is not authorized to run as a HiperSockets network traffic analyzer\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ * Description:
+ * The sysfs 'sniffer' attribute of the HiperSockets device has the value '1'.
+ * The corresponding HiperSockets interface is switched into promiscuous mode
+ * but the network traffic analyzer (NTA) rules configured at the Support Element (SE)
+ * do not allow tracing. Possible reasons are:
+ * - Tracing is not authorized for all HiperSockets LANs in the mainframe system
+ * - Tracing is not authorized for this HiperSockets LAN
+ * - LPAR is not authorized to enable an NTA
+ * User action:
+ * Configure appropriate HiperSockets NTA rules at the SE.
+ */
+
+/*?
+ * Text: "%s: A HiperSockets network traffic analyzer is already active in the HiperSockets LAN\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ * Description:
+ * The sysfs 'sniffer' attribute of the HiperSockets device has the value '1'.
+ * The HiperSockets interface is switched into promiscuous mode but another
+ * HiperSockets device on the same HiperSockets LAN is already running as
+ * a network traffic analyzer.
+ * A HiperSockets LAN can only have one active network traffic analyzer.
+ * User action:
+ * Do not configure multiple HiperSockets devices in the same HiperSockets LAN as
+ * tracing devices.
+ */
+
+/*?
+ * Text: "%s: Enabling HW TX checksumming for %s failed, using SW TX checksumming\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ *   @2: network interface name
+ * Description:
+ * The network adapter supports hardware checksumming for outgoing IP packages
+ * but the qeth device driver could not enable hardware TX checksumming on the
+ * adapter. The qeth device driver continues to use software checksumming for
+ * outgoing IP packages.
+ * User action:
+ * None if you do not require hardware checksumming for outgoing network
+ * traffic. If you want to enable hardware checksumming, ungroup and regroup
+ * the subchannel triplet of the device. If this does not resolve the problem,
+ * reboot Linux. If the problem persists, gather Linux debug data and report
+ * the problem to your support organization.
+ */
+
+/*?
+ * Text: "%s: A connection could not be established because of an OLM limit\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ * Description:
+ * z/OS has activated Optimized Latency Mode (OLM) for a connection through an OSA Express3 adapter.
+ * This reduces the maximum number of concurrent connections per physical port for shared adapters.
+ * The new connection would exceed the maximum. Linux cannot establish further connections using
+ * this adapter.
+ * User action:
+ * If possible, deactivate an existing connection that uses this adapter and try again to establish
+ * the new connection. If you cannot free an existing connection, use a different adapter for the
+ * new connection.
+ */
+
+/*?
+ * Text: "%s: Setting the device online failed because of insufficient authorization\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ * Description:
+ * The qeth device is configured with OSX CHPIDs. An OSX CHPID cannot be activated unless the LPAR is explicitly authorized to access it.
+ * For z/VM guest operating systems, the z/VM user ID must be explicitly authorized in addition to the LPAR.
+ * You grant these authorizations through the Service Element.
+ * User action:
+ * At the Service Element, authorize the LPAR and, if applicable, the z/VM user ID for using the OSX CHPIDs with which the qeth device has been configured.
+ * Then try again to set the device online.
+ */
+
+/*?
+ * Text: "%s: portname is deprecated and is ignored\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ * Description:
+ * An OSA-Express port name was required to identify a shared OSA port.
+ * All operating system instances that shared the port had to use the same port name.
+ * This requirement no longer applies, and the specified portname attribute is ignored.
+ * User action:
+ * For future upgrades, remove OSA port name specifications from your
+ * network configuration.
+ */
+
+/*? Text: "core functions removed\n" */
+/*? Text: "%s: Device is a%s card%s%s%s\nwith link type %s.\n" */
+/*? Text: "%s: issue_next_read failed: no iob available!\n" */
+/*? Text: "%s: Priority Queueing not supported\n" */
+/*? Text: "%s: sense data available. cstat 0x%X dstat 0x%X\n" */
+/*? Text: "loading core functions\n" */
+/*? Text: "%s: MAC address %pM successfully registered on device %s\n" */
+/*? Text: "%s: Device successfully recovered!\n" */
+/*? Text: "register layer 2 discipline\n" */
+/*? Text: "unregister layer 2 discipline\n" */
+/*? Text: "%s: Hardware IP fragmentation not supported on %s\n" */
+/*? Text: "%s: IPv6 not supported on %s\n" */
+/*? Text: "%s: VLAN not supported on %s\n" */
+/*? Text: "%s: Inbound source MAC-address not supported on %s\n" */
+/*? Text: "%s: IPV6 enabled\n" */
+/*? Text: "%s: ARP processing not supported on %s!\n" */
+/*? Text: "%s: Hardware IP fragmentation enabled \n" */
+/*? Text: "%s: set adapter parameters not supported.\n" */
+/*? Text: "%s: VLAN enabled\n" */
+/*? Text: "register layer 3 discipline\n" */
+/*? Text: "%s: Outbound TSO enabled\n" */
+/*? Text: "%s: Broadcast not supported on %s\n" */
+/*? Text: "%s: Outbound TSO not supported on %s\n" */
+/*? Text: "%s: Inbound HW Checksumming not supported on %s,\ncontinuing using Inbound SW Checksumming\n" */
+/*? Text: "%s: Using no checksumming on %s.\n" */
+/*? Text: "%s: Broadcast enabled\n" */
+/*? Text: "%s: Multicast not supported on %s\n" */
+/*? Text: "%s: Using SW checksumming on %s.\n" */
+/*? Text: "%s: HW Checksumming (%sbound) enabled\n" */
+/*? Text: "unregister layer 3 discipline\n" */
+/*? Text: "%s: Multicast enabled\n" */
+/*? Text: "%s: QDIO data connection isolation is deactivated\n" */
+/*? Text: "%s: QDIO data connection isolation is activated\n" */
+/*? Text: "%s: Adapter does not support QDIO data connection isolation\n" */
+/*? Text: "%s: Adapter is dedicated. QDIO data connection isolation not supported\n" */
+/*? Text: "%s: TSO does not permit QDIO data connection isolation\n" */
+/*? Text: "%s: HW TX Checksumming enabled\n" */
+/*? Text: "netif_stop_queue() cannot be called before register_netdev()\n" */
+/*? Text: "qeth_l3: ignoring TR device\n" */
+/*? Text: "flen=%u proglen=%u pass=%u image=%pK from=%s pid=%d\n" */
+/*? Text: "%s selects TX queue %d, but real number of TX queues is %d\n" */
+
+/*?
+ * Text: "%s: Turning off reflective relay mode at the adjacent switch failed\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ * Description:
+ * The policy for the QDIO data connection isolation was
+ * changed successfully, and communications are now handled according to the
+ * new policy. The ISOLATION_FORWARD policy is no longer used, but the qeth
+ * device driver could not turn off the reflective relay mode on the adjacent
+ * switch port.
+ * User action:
+ * Check the adjacent switch for errors and correct the problem.
+ */
+
+/*?
+ * Text: "%s: The adjacent switch port does not support reflective relay mode\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ * Description:
+ * The 'isolation' sysfs attribute of the qeth device could not be set to 'forward'.
+ * This setting selects the ISOLATION_FORWARD policy for the QDIO data connection
+ * isolation. The ISOLATION_FORWARD policy requires a network adapter in Virtual
+ * Ethernet Port Aggregator (VEPA) mode with an adjacent switch port in reflective
+ * relay mode.
+ * User action:
+ * Use a switch port that supports reflective relay mode if you want to use the
+ * ISOLATION_FORWARD policy for the qeth device.
+ */
+
+/*?
+ * Text: "%s: The reflective relay mode cannot be enabled at the adjacent switch port"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ * Description:
+ * The 'isolation' sysfs attribute of the qeth device could not be set to 'forward'.
+ * This setting selects the ISOLATION_FORWARD policy for the QDIO data connection
+ * isolation. The ISOLATION_FORWARD policy requires a network adapter in Virtual
+ * Ethernet Port Aggregator (VEPA) mode with an adjacent switch port in reflective relay
+ * mode. The qeth device driver failed to enable the required reflective relay mode on
+ * the adjacent switch port although the switch port supports this mode.
+ * User action:
+ * Enable reflective relay mode on the switch for the adjacent port and try again.
+ */
+
+/*?
+ * Text: "%s: Interface %s is down because the adjacent port is no longer in reflective relay mode\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ *   @2: interface name
+ * Description:
+ * The ISOLATION_FORWARD policy is active for the QDIO data connection isolation
+ * of the qeth device. This policy requires a network adapter in Virtual Ethernet
+ * Port Aggregator (VEPA) mode with an adjacent switch port in reflective relay mode.
+ * The reflective relay mode on the adjacent switch port was disabled. The qeth device
+ * was set offline and the interface was deactivated to prevent any unintended network traffic.
+ * User action:
+ * Enable the reflective relay mode again on the adjacent port or use the 'isolation'
+ * sysfs attribute of the qeth device to set a different policy for the QDIO data connection
+ * isolation. You can then resume operations by setting the qeth device back
+ * online and activating the interface.
+ */
+
+/*?
+ * Text: "%s: Failed to create completion queue\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ * Description:
+ * The HiperSockets device could not be configured with a completion queue.
+ * A completion queue is required to operate AF_IUCV communication in an LPAR.
+ * User action:
+ * i) Investigate if you have the latest firmware level in place.
+ * ii) If the problem persists and is not caused by a version mismatch, contact IBM
+ * support.
+ */
+
+/*?
+ * Text: "%s: Completion Queueing supported\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ * Description:
+ * The HiperSockets device supports completion queueing. This is required to
+ * set up AF_IUCV communication in an LPAR.
+ */
+
+/*?
+ * Text: "%s: Completion Queue support enabled"
+ * Severity: Informational
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ * Description:
+ * The HiperSockets device is enabled for completion queueing. This is part of
+ * the process to set up AF_IUCV communication in an LPAR.
+ */
+
+/*?
+ * Text: "%s: Completion Queue support disabled"
+ * Severity: Informational
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ * Description:
+ * The HiperSockets device is disabled for completion queueing. This device
+ * cannot or no longer be used to set up AF_IUCV communication in an LPAR.
+ */
+
+/*?
+ * Text: "%s: The device represents a Bridge Capable Port\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ * Description:
+ * You can configure this device as a Bridge Port.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "%s: The device is not configured as a Bridge Port\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ * Description:
+ * The Bridge Port role cannot be withdrawn from a device
+ * that is not configured as a Bridge Port.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "%s: The LAN already has a primary Bridge Port\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ * Description:
+ * A LAN can have multiple secondary Bridge Ports, but only
+ * one primary Bridge Port. Configuring the device as a
+ * primary Bridge Port failed because another port on the
+ * LAN has been configured as the primary Bridge Port.
+ * User action:
+ * Find out which operating system instance has configured the primary
+ * Bridge Port. Assure that the primary role for this port is withdrawn
+ * before trying again to configure your device as the primary Bridge
+ * Port. Alternatively, consider configuring your device as a secondary
+ * Bridge Port.
+ */
+
+/*?
+ * Text: "%s: The device is already a secondary Bridge Port\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ * Description:
+ * A device cannot be configured as a primary or secondary
+ * Bridge Port if it is already configured as a secondary Bridge Port.
+ * User action:
+ * None, if you want the device to be a secondary Bridge Port.
+ * If you want to configure the device as the primary Bridge Port,
+ * withdraw the secondary role by writing 'none' to the 'bridgeport_role'
+ * sysfs attribute of the device. Then try again to configure the
+ * device as the primary Bridge Port.
+ */
+
+/*?
+ * Text: "%s: The LAN cannot have more secondary Bridge Ports\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ * Description:
+ * A LAN can have up to five secondary Bridge Ports.
+ * You cannot configure a further device as a secondary
+ * Bridge Port unless the Bridge Ports role is withdrawn from one of
+ * the existing secondary Bridge Ports.
+ * User action:
+ * Assure that the Bridge Port role is withdrawn from one of the
+ * existing secondary Bridge Ports before trying again to configure your
+ * device as a secondary Bridge Port.
+ */
+
+/*?
+ * Text: "%s: The device is already a primary Bridge Port\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ * Description:
+ * A device cannot be configured as a primary or secondary
+ * Bridge Port if it is already configured as a primary Bridge Port.
+ * User action:
+ * None, if you want the device to be a primary Bridge Port.
+ * If you want to configure the device as a secondary Bridge Port,
+ * withdraw the primary role by writing 'none' to the 'bridgeport_role'
+ * sysfs attribute of the device. Then try again to configure the
+ * device as the secondary Bridge Port.
+ */
+
+/*?
+ * Text: "%s: The device is not authorized to be a Bridge Port\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ * Description:
+ * The device cannot be configured as a Bridge Port because
+ * the required authorizations in the hardware are not in place.
+ * User action:
+ * See your hardware documentation about how to authorize
+ * ports for becoming a Bridge Port.
+ */
+
+/*?
+ * Text: "%s: A Bridge Port is already configured by a different operating system\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ * Description:
+ * Linux instances cannot configure the target port as a Bridge Port.
+ * Another operating system already uses a Bridge Port on the HiperSockets
+ * or on the OSA adapter. For example, a z/VM instance might be using
+ * a port in a VSWITCH configuration. Multiple Bridge Ports on the same
+ * HiperSockets or OSA adapter must be configured by instances of the same
+ * operating system, for example, all Linux or all z/VM.
+ * User action:
+ * Reconsider your network topology. Configure Bridge Ports only for ports
+ * on adapters where any other Bridge Ports are configured by other Linux
+ * instances.
+ */
+
+/*?
+ * Text: "%s: Setting address notification failed\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ * Description:
+ * Enabling or disabling the address notification feature of a
+ * HiperSockets device failed. The device might not be configured as a
+ * Bridge Port.
+ * User action:
+ * None, unless you need address notifications for this device.
+ * If you need notifications, confirm that your device is attached to a
+ * HiperSockets LAN that supports Bridge Capable Ports and that your
+ * device is configured as a Bridge Port. If the 'bridgeport_role'
+ * sysfs attribute of the device contains, one of the values 'primary'
+ * or 'secondary' and you cannot set the address notification, contact
+ * your support organization.
+ */
+
+/*?
+ * Text: "%s: Address notification from the Bridge Port stopped %s (%s)\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ *   @2: network interface name
+ *   @3: error reported by the hardware
+ * Description:
+ * A Bridge Port no longer provides address notifications.
+ * Possible reasons include traffic overflow and that the device is no
+ * longer configured as a Bridge Port. A udev event with
+ * BRIDGEDHOST=abort was emitted to alert applications that rely on the
+ * address notifications.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "%s: The qeth driver ran out of channel command buffers\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the qeth device
+ * Description:
+ * Command buffers can temporarily run out during periods of
+ * intense network configuration activities.
+ * The device driver recovers from this condition as outstanding
+ * commands are completed.
+ * User action:
+ * Wait for a short time. If the problem persists,
+ * initiate a recovery process by writing '1' to the 'recover'
+ * sysfs attribute of the device.
+ */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/s390dbf
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/s390dbf
@@ -0,0 +1,83 @@
+/*?
+ * Text: "Root becomes the owner of all s390dbf files in sysfs\n"
+ * Severity: Warning
+ * Description:
+ * The S/390 debug feature you are using only supports uid/gid = 0.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "Registering debug feature %s failed\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: feature name
+ * Description:
+ * The initialization of an S/390 debug feature failed. A likely cause of this
+ * problem is memory constraints. The system keeps running, but the debug
+ * data for this feature will not be available in sysfs.
+ * User action:
+ * Consider assigning more memory to your LPAR or z/VM guest virtual machine.
+ */
+
+/*?
+ * Text: "Registering view %s/%s would exceed the maximum number of views %i\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: feature name
+ *   @2: view name
+ *   @3: maximum
+ * Description:
+ * The maximum number of allowed debug feature views has been reached. The
+ * view has not been registered. The system keeps running but the new view
+ * will not be available in sysfs. This is a program error.
+ * User action:
+ * Report this problem to your support partner.
+ */
+
+/*?
+ * Text: "%s is not a valid level for a debug feature\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: level
+ * Description:
+ * Setting a new level for a debug feature by using the 'level' sysfs attribute
+ * failed. Valid levels are the minus sign (-) and the integers in the
+ * range 0 to 6. The minus sign switches off the feature. The numbers switch
+ * the feature on, where higher numbers produce more debug output.
+ * User action:
+ * Write a valid value to the 'level' sysfs attribute.
+ */
+
+/*?
+ * Text: "Flushing debug data failed because %c is not a valid area\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: debug area number
+ * Description:
+ * Flushing a debug area by using the 'flush' sysfs attribute failed. Valid
+ * values are the minus sign (-) for flushing all areas, or the number of the
+ * respective area for flushing a single area.
+ * User action:
+ * Write a valid area number or the minus sign (-) to the 'flush' sysfs
+ * attribute.
+ */
+
+/*?
+ * Text: "Allocating memory for %i pages failed\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: number of pages
+ * Description:
+ * Setting the debug feature size by using the 'page' sysfs attribute failed.
+ * Linux did not have enough memory for expanding the debug feature to the
+ * requested size.
+ * User action:
+ * Use a smaller number of pages for the debug feature or allocate more
+ * memory to your LPAR or z/VM guest virtual machine.
+ */
+
+/*? Text: "%s: set new size (%i pages)\n" */
+/*? Text: "%s: switched off\n" */
+/*? Text: "%s: level %i is out of range (%i - %i)\n" */
+/*? Text: "Registering view %s/%s failed due to out of memory\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/sclp_cmd
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/sclp_cmd
@@ -0,0 +1,44 @@
+/*? Text: "sync request failed (cmd=0x%08x, status=0x%02x)\n" */
+/*? Text: "readcpuinfo failed (response=0x%04x)\n" */
+/*? Text: "configure cpu failed (cmd=0x%08x, response=0x%04x)\n" */
+/*? Text: "configure channel-path failed (cmd=0x%08x, response=0x%04x)\n" */
+/*? Text: "read channel-path info failed (response=0x%04x)\n" */
+/*? Text: "assign storage failed (cmd=0x%08x, response=0x%04x, rn=0x%04x)\n" */
+/*? Text: "configure PCI I/O adapter failed: cmd=0x%08x  response=0x%04x\n" */
+/*? Text: "request failed (status=0x%02x)\n" */
+/*? Text: "request failed with response code 0x%x\n" */
+
+/*?
+ * Text: "Memory hotplug state changed, suspend refused.\n"
+ * Severity: Error
+ * Description:
+ * Suspend is refused after a memory hotplug operation was performed.
+ * User action:
+ * The system needs to be restarted and no memory hotplug operation must be
+ * performed in order to allow suspend.
+ */
+
+/*?
+ * Text: "Standby memory at 0x%llx (%lluM of %lluM usable)\n"
+ * Severity: Informational
+ * Parameter:
+ * @1: start address of standby memory
+ * @2: usable memory in MB
+ * @3: total detected memory in MB
+ * Description:
+ * Standby memory was detected. It can be used for memory hotplug only
+ * if it is aligned to the Linux hotplug memory block size.
+ * If the aligned amount of memory matches the total amount,
+ * all detected standby memory can be used. Otherwise, some of the detected
+ * memory is unaligned and cannot be used.
+ * User action:
+ * None, if the usable and the total amount of detected standby memory match.
+ * If the amounts of memory do not match,
+ * check the memory setup of your guest virtual machine and ensure that
+ * the standby memory start and end
+ * address is aligned to the Linux hotplug memory block size.
+ * On Linux, issue "cat /sys/devices/system/memory/block_size_bytes"
+ * to find the hotplug memory block size value in hexadecimal notation.
+ * On z/VM, query your memory setup with "vmcp q v store".
+ */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/sclp_config
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/sclp_config
@@ -0,0 +1,15 @@
+/*?
+ * Text: "CPU capability may have changed\n"
+ * Severity: Informational
+ * Description:
+ * The capability of the CPUs in the configuration may have been upgraded
+ * or downgraded. This message may also appear if the capability of the
+ * CPUs in the configuration did not change.
+ * For details see the STORE SYSTEM INFORMATION description in the
+ * "Principles of Operation."
+ * User action:
+ * The user can examine /proc/sysinfo for CPU capability values.
+ */
+/*? Text: "Open for Business request failed with response code 0x%04x\n" */
+/*? Text: "SCLP receiver did not register to receive Configuration Management Data Events.\n" */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/sclp_cpi
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/sclp_cpi
@@ -0,0 +1,3 @@
+/*? Text: "request failed (status=0x%02x)\n" */
+/*? Text: "request failed with response code 0x%x\n" */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/sclp_ocf
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/sclp_ocf
@@ -0,0 +1 @@
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/sclp_sdias
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/sclp_sdias
@@ -0,0 +1,4 @@
+/*? Text: "sclp_send failed for get_nr_blocks\n" */
+/*? Text: "SCLP error: %x\n" */
+/*? Text: "sclp_send failed: %x\n" */
+/*? Text: "Error from SCLP while copying hsa. Event status = %x\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/scm_block
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/scm_block
@@ -0,0 +1,51 @@
+/*?
+ * Text: "%lx: The capabilities of the SCM increment changed\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: start address of the SCM increment
+ * Description:
+ * A configuration change is in progress for the storage class memory (SCM)
+ * increment.
+ * User action:
+ * Verify that the capability of the SCM increment is as intended; for
+ * example, with lsscm.
+ */
+
+/*?
+ * Text: "An I/O operation to SCM failed with rc=%d\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: return code
+ * Description:
+ * An error occurred during I/O to storage class memory (SCM). The operation
+ * was repeated, but the maximum number of retries was exceeded before the
+ * request could be fulfilled.
+ * User action:
+ * Contact your support organization.
+ */
+
+/*?
+ * Text: "%lx: Write access to the SCM increment is suspended\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: start address of the SCM increment
+ * Description:
+ * A concurrent firmware upgrade is in progress. For the duration of the
+ * upgrade, write access to the storage class memory (SCM) increment has been
+ * suspended.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "%lx: Write access to the SCM increment is restored\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: start address of the SCM increment
+ * Description:
+ * Write access to the storage class memory (SCM) increment was restored
+ * after a temporary suspension during a concurrent firmware upgrade.
+ * User action:
+ * None.
+ */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/setup
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/setup
@@ -0,0 +1,165 @@
+/*?
+ * Text: "The initial RAM disk does not fit into the memory\n"
+ * Severity: Error
+ * Description:
+ * The load address and the size of the initial RAM disk specify a memory
+ * area that is not available.
+ * User action:
+ * Lower the load address of the initial RAM disk, reduce the size of the
+ * initial RAM disk, or increase the size of the system memory to make the
+ * initial RAM disk fit into the memory.
+ */
+
+/*?
+ * Text: "The maximum memory size is %luMB\n"
+ * Severity: Notice
+ * Parameter:
+ *   @1: size in MB
+ * Description:
+ * The system memory size cannot exceed the amount of memory that is
+ * provided by the real or virtual hardware. It can be further reduced
+ * through an upper memory address limit that is specified with the
+ * mem= kernel parameter.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "Linux is running as a z/VM guest operating system in 31-bit mode\n"
+ * Severity: Informational
+ * Description:
+ * The 31-bit Linux kernel detected that it is running as a guest operating
+ * system of the z/VM hypervisor.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "Linux is running natively in 31-bit mode\n"
+ * Severity: Informational
+ * Description:
+ * The 31-bit Linux kernel detected that it is running on an IBM mainframe,
+ * either as the sole operating system in an LPAR or as the sole operating
+ * system on the entire mainframe. The Linux kernel is not running as a
+ * guest operating system of the z/VM hypervisor.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "The hardware system has IEEE compatible floating point units\n"
+ * Severity: Informational
+ * Description:
+ * The Linux kernel detected that it is running on a hardware system with
+ * CPUs that have IEEE compatible floating point units.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "The hardware system has no IEEE compatible floating point units\n"
+ * Severity: Informational
+ * Description:
+ * The Linux kernel detected that it is running on a hardware system with
+ * CPUs that do not have IEEE compatible floating point units.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "Linux is running as a z/VM guest operating system in 64-bit mode\n"
+ * Severity: Informational
+ * Description:
+ * The 64-bit Linux kernel detected that it is running as a guest operating
+ * system of the z/VM hypervisor.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "Linux is running under KVM in 64-bit mode\n"
+ * Severity: Informational
+ * Description:
+ * The 64-bit Linux kernel detected that it is running as a guest operating
+ * system of the KVM hypervisor.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "Linux is running natively in 64-bit mode\n"
+ * Severity: Informational
+ * Description:
+ * The 64-bit Linux kernel detected that it is running on an IBM mainframe,
+ * either as the sole operating system in an LPAR or as the sole operating
+ * system on the entire mainframe. The Linux kernel is not running as a
+ * guest operating system of the z/VM hypervisor.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "Defining the Linux kernel NSS failed with rc=%d\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: return code
+ * Description:
+ * The Linux kernel could not define the named saved system (NSS) with
+ * the z/VM CP DEFSYS command. The return code represents the numeric
+ * portion of the CP DEFSYS error message.
+ * User action:
+ * For return code 1, the z/VM guest virtual machine is not authorized
+ * to define named saved systems.
+ * Ensure that the z/VM guest virtual machine is authorized to issue
+ * the CP DEFSYS command (typically privilege class E).
+ * For other return codes, see the help and message documentation for
+ * the CP DEFSYS command.
+ */
+
+/*?
+ * Text: "Saving the Linux kernel NSS failed with rc=%d\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: return code
+ * Description:
+ * The Linux kernel could not save the named saved system (NSS) with
+ * the z/VM CP SAVESYS command. The return code represents the numeric
+ * portion of the CP SAVESYS error message.
+ * User action:
+ * For return code 1, the z/VM guest virtual machine is not authorized
+ * to save named saved systems.
+ * Ensure that the z/VM guest virtual machine is authorized to issue
+ * the CP SAVESYS command (typically privilege class E).
+ * For other return codes, see the help and message documentation for
+ * the CP SAVESYS command.
+ */
+
+/*?
+ * Text: "crashkernel reservation failed: %s\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: reason string
+ * Description:
+ * The memory reservation for the kdump "crashkernel" parameter was not
+ * successful. The Linux kernel was either not able to find a free memory
+ * area or an invalid area has been defined. The reason string describes the
+ * cause of the failure in more detail.
+ * User action:
+ * Increase the memory footprint of your virtual machine or adjust the values
+ * for the "crashkernel" kernel parameter. Then boot your Linux system again.
+ */
+
+/*?
+ * Text: "Reserving %lluMB of memory at %lluMB for crashkernel (System RAM: %luMB)\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: amount of reserved memory
+ *   @2: storage location of reserved memory
+ *   @3: amount of system RAM
+ * Description:
+ * The memory reservation for the kdump "crashkernel" parameter was successful
+ * and a kdump kernel can now be loaded with the kexec tool.
+ * User action:
+ * None.
+ */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/smsgiucv
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/smsgiucv
@@ -0,0 +1 @@
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/smsgiucv_app
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/smsgiucv_app
@@ -0,0 +1 @@
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/tape
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/tape
@@ -0,0 +1,63 @@
+/*?
+ * Text: "%s: A tape unit was detached while in use\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * A tape unit has been detached from the I/O configuration while a tape
+ * was being accessed. This typically results in I/O error messages and
+ * potentially in damaged data on the tape.
+ * User action:
+ * Check the output of the application that accesses the tape device.
+ * If this problem occurred during a write-type operation, consider repeating
+ * the operation after bringing the tape device back online.
+ */
+
+/*?
+ * Text: "%s: A tape cartridge has been mounted\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * A tape cartridge has been inserted into the tape unit. The tape in the
+ * tape unit is ready to be accessed.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "%s: The tape cartridge has been successfully unloaded\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * The tape cartridge has been unloaded from the tape unit. Insert a tape
+ * cartridge before accessing the tape device.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "A cartridge is loaded in tape device %s, refusing to suspend\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * A request to suspend a tape device currently loaded with a cartridge is
+ * rejected.
+ * User action:
+ * Unload the tape device. Then try to suspend the system again.
+ */
+
+/*?
+ * Text: "Tape device %s is busy, refusing to suspend\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * A request to suspend a tape device being currently in use is rejected.
+ * User action:
+ * Terminate applications performing tape operations
+ * and then try to suspend the system again.
+ */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/tape_34xx
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/tape_34xx
@@ -0,0 +1,418 @@
+/*?
+ * Text: "%s: An unexpected condition %d occurred in tape error recovery\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the tape device
+ *   @2: number
+ * Description:
+ * The control unit has reported an error condition that is not recognized by
+ * the error recovery process of the tape device driver.
+ * User action:
+ * Report this problem and the condition number from the message to your
+ * support organization.
+ */
+
+/*?
+ * Text: "%s: A data overrun occurred between the control unit and tape unit\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * A data overrun error has occurred on the connection between the control
+ * unit and the tape unit. If this problem occurred during a write-type
+ * operation, the integrity of the data on the tape might be compromised.
+ * User action:
+ * Use a faster connection. If this problem occurred during a write-type
+ * operation, consider repositioning the tape and repeating the operation.
+ */
+
+/*?
+ * Text: "%s: The block ID sequence on the tape is incorrect\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * The control unit has detected an incorrect block ID sequence on the tape.
+ * This problem typically indicates that the data on the tape is damaged.
+ * User action:
+ * If this problem occurred during a write-type operation reposition the tape
+ * and repeat the operation.
+ */
+
+/*?
+ * Text: "%s: A read error occurred that cannot be recovered\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * A read error has occurred that cannot be recovered. The current tape might
+ * be damaged.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "%s: A write error on the tape cannot be recovered\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * A write error has occurred that could not be recovered by the automatic
+ * error recovery process.
+ * User action:
+ * Use a different tape cartridge.
+ */
+
+/*?
+ * Text: "%s: Writing the ID-mark failed\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * The ID-mark at the beginning of tape could not be written. The tape medium
+ * might be write-protected.
+ * User action:
+ * Try a different tape cartridge. Ensure that the write-protection on the
+ * cartridge is switched off.
+ */
+
+/*?
+ * Text: "%s: Reading the tape beyond the end of the recorded area failed\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * A read-type operation failed because it extended beyond the end of the
+ * recorded area on the tape medium.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "%s: The tape contains an incorrect block ID sequence\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * The control unit has detected an incorrect block ID sequence on the tape.
+ * This problem typically indicates that the data on the tape is damaged.
+ * User action:
+ * If this problem occurred during a write-type operation reposition the tape
+ * and repeat the operation.
+ */
+
+/*?
+ * Text: "%s: A path equipment check occurred for the tape device\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * A path equipment check has occurred. This check indicates problems with the
+ * connection between the mainframe system and the tape control unit.
+ * User action:
+ * Ensure that the cable connections between the mainframe system and the
+ * control unit are securely in place and not damaged.
+ */
+
+/*?
+ * Text: "%s: The tape unit cannot process the tape format\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * Either the tape unit is not able to read the format ID mark, or the
+ * specified format is not supported by the tape unit.
+ * User action:
+ * If you do not need the data recorded on the current tape, use a different
+ * tape or write a new format ID mark at the beginning of the tape. Be aware
+ * that writing a new ID mark leads to a loss of all data that has been
+ * recorded on the tape. If you need the data on the current tape, use a tape
+ * unit that supports the tape format.
+ */
+
+/*?
+ * Text: "%s: The tape medium is write-protected\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * A write-type operation failed because the tape medium is write-protected.
+ * User action:
+ * Eject the tape cartridge, switch off the write protection on the cartridge,
+ * insert the cartridge, and try the operation again.
+ */
+
+/*?
+ * Text: "%s: The tape does not have the required tape tension\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * The tape does not have the required tape tension.
+ * User action:
+ * Rewind and reposition the tape, then repeat the operation.
+ */
+
+/*?
+ * Text: "%s: The tape unit failed to load the cartridge\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * An error has occurred while loading the tape cartridge.
+ * User action:
+ * Unload the cartridge and load it again.
+ */
+
+/*?
+ * Text: "%s: Automatic unloading of the tape cartridge failed\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * The tape unit failed to unload the cartridge.
+ * User action:
+ * Unload the cartridge manually by using the eject button on the tape unit.
+ */
+
+/*?
+ * Text: "%s: An equipment check has occurred on the tape unit\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * Possible reasons for the check condition are a unit adapter error, a buffer
+ * error on the lower interface, an unusable internal path, or an error that
+ * has occurred while loading the cartridge.
+ * User action:
+ * Examine the tape unit and the cartridge loader. Consult the tape unit
+ * documentation for details.
+ */
+
+/*?
+ * Text: "%s: The tape information states an incorrect length\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * The tape is shorter than stated at the beginning of the tape data. A
+ * possible reason for this problem is that the tape might have been physically
+ * truncated. Data written to the tape might be incomplete or damaged.
+ * User action:
+ * If this problem occurred during a write-type operation, consider repeating
+ * the operation with a different tape cartridge.
+ */
+
+/*?
+ * Text: "%s: The tape unit is not ready\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * The tape unit is online but not ready.
+ * User action:
+ * Turn the ready switch on the tape unit to the ready position and try the
+ * operation again.
+ */
+
+/*?
+ * Text: "%s: The tape medium has been rewound or unloaded manually\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * The tape unit rewind button, unload button, or both have been used to
+ * rewind or unload the tape cartridge. A tape cartridge other than the
+ * intended cartridge might have been inserted or the tape medium might not
+ * be at the expected position.
+ * User action:
+ * Verify that the correct tape cartridge has been inserted and that the tape
+ * medium is at the required position before continuing to work with the tape.
+ */
+
+/*?
+ * Text: "%s: The tape subsystem is running in degraded mode\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * The tape subsystem is not operating at its maximum performance.
+ * User action:
+ * Contact your service representative for the tape unit and report this
+ * problem.
+ */
+
+/*?
+ * Text: "%s: The tape unit is already assigned\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * The tape unit is already assigned to another channel path.
+ * User action:
+ * Free the tape unit from the operating system instance to which it is
+ * currently assigned then try again.
+ */
+
+/*?
+ * Text: "%s: The tape unit is not online\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * The tape unit is not online to the tape device driver.
+ * User action:
+ * Ensure that the tape unit is operational and that the cable connections
+ * between the control unit and the tape unit are securely in place and not
+ * damaged.
+ */
+
+/*?
+ * Text: "%s: The control unit has fenced access to the tape volume\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * The control unit fences further access to the current tape volume. The data
+ * integrity on the tape volume might have been compromised.
+ * User action:
+ * Rewind and unload the tape cartridge.
+ */
+
+/*?
+ * Text: "%s: A parity error occurred on the tape bus\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * A data parity check error occurred on the bus. Data that was read or written
+ * while the error occurred is not valid.
+ * User action:
+ * Reposition the tape and repeat the read-type or write-type operation.
+ */
+
+/*?
+ * Text: "%s: I/O error recovery failed on the tape control unit\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * An I/O error occurred that cannot be recovered by the automatic error
+ * recovery process of the tape control unit. The application that operates
+ * the tape unit will receive a return value of -EIO which indicates an
+ * I/O error. The data on the tape might be damaged.
+ * User action:
+ * If this problem occurred during a write-type operation, consider
+ * repositioning the tape and repeating the operation.
+ */
+
+/*?
+ * Text: "%s: The tape unit requires a firmware update\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * The tape unit requires firmware patches from the tape control unit but the
+ * required patches are not available on the control unit.
+ * User action:
+ * Make the require patches available on the control unit then reposition the
+ * tape and retry the operation. For details about obtaining and installing
+ * firmware updates see the control unit documentation.
+ */
+
+/*?
+ * Text: "%s: The maximum block size for buffered mode is exceeded\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * The block to be written is larger than allowed for the buffered mode.
+ * User action:
+ * Use a smaller block size.
+ */
+
+/*?
+ * Text: "%s: A channel interface error cannot be recovered\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * An error has occurred on the channel interface. This error cannot
+ * be recovered by the control unit error recovery process.
+ * User action:
+ * See the documentation of the control unit.
+ */
+
+/*?
+ * Text: "%s: A channel protocol error occurred\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * An error was detected in the channel protocol.
+ * User action:
+ * Reposition the tape and try the operation again.
+ */
+
+/*?
+ * Text: "%s: The tape unit does not support the compaction algorithm\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * The tape unit cannot read the current tape. The data on the tape has been
+ * compressed with an algorithm that is not supported by the tape unit.
+ * User action:
+ * Use a tape unit that supports the compaction algorithm used for the
+ * current tape.
+ */
+
+/*?
+ * Text: "%s: The tape unit does not support tape format 3480-2 XF\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * The tape unit does not support tapes recorded in the 3480-2 XF format.
+ * User action:
+ * If you do not need the data recorded on the current tape, rewind the tape
+ * and overwrite it with a supported format. If you need the data on the
+ * current tape, use a tape unit that supports the tape format.
+ */
+
+/*?
+ * Text: "%s: The tape unit does not support format 3480 XF\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * The tape unit does not support tapes recorded in the 3480 XF format.
+ * User action:
+ * If you do not need the data recorded on the current tape, rewind the tape
+ * and overwrite it with a supported format. If you need the data on the
+ * current tape, use a tape unit that supports the tape format.
+ */
+
+/*?
+ * Text: "%s: The tape unit does not support the current tape length\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * The length of the tape in the cartridge is incompatible with the tape unit.
+ * User action:
+ * Either use a different tape unit or use a tape with a supported length.
+ */
+
+/*?
+ * Text: "%s: The tape unit does not support the tape length\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * The length of the tape in the cartridge is incompatible with the tape
+ * unit.
+ * User action:
+ * Either use a different tape unit or use a tape with a supported length.
+ */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/tape_3590
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/tape_3590
@@ -0,0 +1,183 @@
+/*?
+ * Text: "%s: The tape medium must be loaded into a different tape unit\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * The tape device has indicated an error condition that requires loading
+ * the tape cartridge into a different tape unit to recover.
+ * User action:
+ * Unload the cartridge and use a different tape unit to retry the operation.
+ */
+
+/*?
+ * Text: "%s: Tape media information: exception %s, service %s\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ *   @2: exception
+ *   @3: service
+ * Description:
+ * This is an operating system independent tape medium information message
+ * that was issued by the tape unit. The information in the message is
+ * intended for the IBM customer engineer.
+ * User action:
+ * See the documentation for the tape unit for further information.
+ */
+
+/*?
+ * Text: "%s: Device subsystem information: exception %s, service %s\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ *   @2: exception
+ *   @3: required service action
+ * Description:
+ * This is an operating system independent device subsystem information message
+ * that was issued by the tape unit. The information in the message is
+ * intended for the IBM customer engineer.
+ * User action:
+ * See the documentation for the tape unit for further information.
+ */
+
+/*?
+ * Text: "%s: I/O subsystem information: exception %s, service %s\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ *   @2: exception
+ *   @3: required service action
+ * Description:
+ * This is an operating system independent I/O subsystem information message
+ * that was issued by the tape unit. The information in the message is
+ * intended for the IBM customer engineer.
+ * User action:
+ * See the documentation for the tape unit for further information.
+ */
+
+/*?
+ * Text: "%s: The tape unit has issued sense message %s\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ *   @2: sense message code
+ * Description:
+ * The tape unit has issued an operating system independent sense message.
+ * User action:
+ * See the documentation for the tape unit for further information.
+ */
+
+/*?
+ * Text: "%s: The tape unit has issued an unknown sense message code 0x%x\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ *   @2: code
+ * Description:
+ * The tape device driver has received an unknown sense message from the
+ * tape unit.
+ * User action:
+ * See the documentation for the tape unit for further information.
+ */
+
+/*?
+ * Text: "%s: MIM SEV=%i, MC=%02x, ES=%x/%x, RC=%02x-%04x-%02x\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ *   @2: SEV
+ *   @3: message code
+ *   @4: exception
+ *   @5: required service action
+ *   @6: refcode
+ *   @7: mid
+ *   @8: fid
+ * Description:
+ * This is an operating system independent information message that was
+ * issued by the tape unit. The information in the message is intended for
+ * the IBM customer engineer.
+ * User action:
+ * See to the documentation for the tape unit for further information.
+ */
+
+/*?
+ * Text: "%s: IOSIM SEV=%i, DEVTYPE=3590/%02x, MC=%02x, ES=%x/%x, REF=0x%04x-0x%04x-0x%04x\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ *   @2: SEV
+ *   @3: model
+ *   @4: message code
+ *   @5: exception
+ *   @6: required service action
+ *   @7: refcode1
+ *   @8: refcode2
+ *   @9: refcode3
+ * Description:
+ * This is an operating system independent I/O subsystem information message
+ * that was issued by the tape unit. The information in the message is
+ * intended for the IBM customer engineer.
+ * User action:
+ * See the documentation for the tape unit for further information.
+ */
+
+/*?
+ * Text: "%s: DEVSIM SEV=%i, DEVTYPE=3590/%02x, MC=%02x, ES=%x/%x, REF=0x%04x-0x%04x-0x%04x\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ *   @2: SEV
+ *   @3: model
+ *   @4: message code
+ *   @5: exception
+ *   @6: required service action
+ *   @7: refcode1
+ *   @8: refcode2
+ *   @9: refcode3
+ * Description:
+ * This is an operating system independent device subsystem information message
+ * issued by the tape unit. The information in the message is intended for
+ * the IBM customer engineer.
+ * User action:
+ * See the documentation for the tape unit for further information.
+ */
+
+/*?
+ * Text: "%s: The tape unit has issued an unknown sense message code %x\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ *   @2: code
+ * Description:
+ * The tape device has issued a sense message, that is unknown to the device
+ * driver.
+ * User action:
+ * Use the message code printed as hexadecimal value and see the documentation
+ * for the tape unit for further information.
+ */
+
+/*?
+ * Text: "%s: The tape unit failed to obtain the encryption key from EKM\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * The tape unit was unable to retrieve the encryption key required to decode
+ * the data on the tape from the enterprise key manager (EKM).
+ * User action:
+ * See the EKM and tape unit documentation for information about how to enable
+ * the tape unit to retrieve the encryption key.
+ */
+
+/*?
+ * Text: "%s: A different host has privileged access to the tape unit\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the tape device
+ * Description:
+ * You cannot access the tape unit because a different operating system
+ * instance has privileged access to the unit.
+ * User action:
+ * Unload the current cartridge to solve this problem.
+ */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/time
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/time
@@ -0,0 +1,36 @@
+/*?
+ * Text: "The ETR interface has adjusted the clock by %li microseconds\n"
+ * Severity: Notice
+ * Parameter:
+ *   @1: number of microseconds
+ * Description:
+ * The external time reference (ETR) interface has synchronized the system
+ * clock  with the external reference and set it to a new value. The time
+ * difference between the old and new clock value has been passed to the
+ * network time protocol (NTP) as a single shot adjustment.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "The real or virtual hardware system does not provide an ETR interface\n"
+ * Severity: Warning
+ * Description:
+ * The 'etr=' parameter has been passed on the kernel parameter line for
+ * a Linux instance that does not have access to the external time reference
+ * (ETR) facility.
+ * User action:
+ * To avoid this warning remove the 'etr=' kernel parameter.
+ */
+
+/*?
+ * Text: "The real or virtual hardware system does not provide an STP interface\n"
+ * Severity: Warning
+ * Description:
+ * The 'stp=' parameter has been passed on the kernel parameter line for
+ * a Linux instance that does not have access to the server time protocol
+ * (STP) facility.
+ * User action:
+ * To avoid this warning remove the 'stp=' kernel parameter.
+ */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/vmlogrdr
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/vmlogrdr
@@ -0,0 +1,19 @@
+/*? Text: "vmlogrdr: failed to start recording automatically\n" */
+/*? Text: "vmlogrdr: connection severed with reason %i\n" */
+/*? Text: "vmlogrdr: iucv connection to %s failed with rc %i \n" */
+/*? Text: "vmlogrdr: failed to stop recording automatically\n" */
+/*? Text: "not running under VM, driver not loaded.\n" */
+
+/*?
+ * Text: "vmlogrdr: device %s is busy. Refuse to suspend.\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: device name
+ * Description:
+ * Suspending vmlogrdr devices that are in uses is not supported.
+ * A request to suspend such a device is refused.
+ * User action:
+ * Close all applications that use any of the vmlogrdr devices
+ * and then try to suspend the system again.
+ */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/vmur
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/vmur
@@ -0,0 +1,48 @@
+/*?
+ * Text: "The %s cannot be loaded without z/VM\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: z/VM virtual unit record device driver
+ * Description:
+ * The z/VM virtual unit record device driver provides Linux with access to
+ * z/VM virtual unit record devices like punch card readers, card punches, and
+ * line printers. On Linux instances that run in environments other than the
+ * z/VM hypervisor, the device driver does not provide any useful function and
+ * the corresponding vmur module cannot be loaded.
+ * User action:
+ * Load the vmur module only on Linux instances that run as guest operating
+ * systems of the z/VM hypervisor. If the z/VM virtual unit record device
+ * has been compiled into the kernel, ignore this message.
+ */
+
+/*?
+ * Text: "Kernel function alloc_chrdev_region failed with error code %d\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: error code according to errno definitions
+ * Description:
+ * The z/VM virtual unit record device driver (vmur) needs to register a range
+ * of character device minor numbers from 0x0000 to 0xffff.
+ * This registration failed, probably because of memory constraints.
+ * User action:
+ * Free some memory and reload the vmur module. If the z/VM virtual unit
+ * record device driver has been compiled into the kernel reboot Linux.
+ * Consider assigning more memory to your LPAR or z/VM guest virtual machine.
+ */
+
+/*?
+ * Text: "Unit record device %s is busy, %s refusing to suspend.\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the unit record device
+ *   @1: z/VM virtual unit record device driver
+ * Description:
+ * Linux cannot be suspended while a unit record device is in use.
+ * User action:
+ * Stop all applications that work on z/VM spool file queues, for example, the
+ * vmur tool. Then try again to suspend Linux.
+ */
+
+/*? Text: "%s loaded.\n" */
+/*? Text: "%s unloaded.\n" */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/xpram
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/xpram
@@ -0,0 +1,74 @@
+/*?
+ * Text: "%d is not a valid number of XPRAM devices\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: number of partitions
+ * Description:
+ * The number of XPRAM partitions specified for the 'devs' module parameter
+ * or with the 'xpram.parts' kernel parameter must be an integer in the
+ * range 1 to 32. The XPRAM device driver created a maximum of 32 partitions
+ * that are probably not configured as intended.
+ * User action:
+ * If the XPRAM device driver has been compiled as a separate module,
+ * unload the module and load it again with a correct value for the 'devs'
+ * module parameter. If the XPRAM device driver has been compiled
+ * into the kernel, correct the 'xpram.parts' parameter in the kernel
+ * command line and restart Linux.
+ */
+
+/*?
+ * Text: "Not enough expanded memory available\n"
+ * Severity: Error
+ * Description:
+ * The amount of expanded memory required to set up your XPRAM partitions
+ * depends on the 'sizes' parameter specified for the xpram module or on
+ * the specifications for the 'xpram.parts' parameter if the XPRAM device
+ * driver has been compiled into the kernel. Your
+ * current specification exceed the amount of available expanded memory.
+ * Your XPRAM partitions are probably not configured as intended.
+ * User action:
+ * If the XPRAM device driver has been compiled as a separate module,
+ * unload the xpram module and load it again with an appropriate value
+ * for the 'sizes' module parameter. If the XPRAM device driver has been
+ * compiled into the kernel, adjust the 'xpram.parts' parameter in the
+ * kernel command line and restart Linux. If you need more than the
+ * available expanded memory, increase the expanded memory allocation for
+ * your virtual hardware or LPAR.
+ */
+
+/*?
+ * Text: "No expanded memory available\n"
+ * Severity: Error
+ * Description:
+ * The XPRAM device driver has been loaded in a Linux instance that runs
+ * in an LPAR or virtual hardware without expanded memory.
+ * No XPRAM partitions are created.
+ * User action:
+ * Allocate expanded memory for your LPAR or virtual hardware or do not
+ * load the xpram module. You can ignore this message, if you do not want
+ * to create XPRAM partitions.
+ */
+
+/*?
+ * Text: "Resuming the system failed: %s\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: cause of the failure
+ * Description:
+ * A system cannot be resumed if the expanded memory setup changes
+ * after hibernation. Possible reasons for the failure are:
+ * - Expanded memory was removed after hibernation.
+ * - Size of the expanded memory changed after hibernation.
+ * The system is stopped with a kernel panic.
+ * User action:
+ * Reboot Linux.
+ */
+
+/*? Text: "  number of devices (partitions): %d \n" */
+/*? Text: "  size of partition %d: %u kB\n" */
+/*? Text: "  size of partition %d to be set automatically\n" */
+/*? Text: "  memory needed (for sized partitions): %lu kB\n" */
+/*? Text: "  partitions to be sized automatically: %d\n" */
+/*? Text: "  automatically determined partition size: %lu kB\n" */
+/*? Text: "  %u pages expanded memory found (%lu KB).\n" */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/zcrypt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/zcrypt
@@ -0,0 +1,22 @@
+/*?
+ * Text: "Cryptographic device %02x.%04x failed and was set offline\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: AP device ID
+ *   @2: AP queue
+ * Description:
+ * A cryptographic device failed to process a cryptographic request.
+ * The cryptographic device driver could not correct the error and
+ * set the device offline. The application that issued the
+ * request received an indication that the request has failed.
+ * User action:
+ * Use the lszcrypt command to confirm that the cryptographic
+ * hardware is still configured to your LPAR or z/VM guest virtual
+ * machine. If the device is available to your Linux instance the
+ * command output contains a line that begins with 'card<device index>',
+ * where <device index> is the two-digit decimal number in the message text.
+ * After ensuring that the device is available, use the chzcrypt command to
+ * set it online again.
+ * If the error persists, contact your support organization.
+ */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/zdump
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/zdump
@@ -0,0 +1,27 @@
+/*?
+ * Text: "The 32-bit dump tool cannot be used for a 64-bit system\n"
+ * Severity: Alert
+ * Description:
+ * The dump process ends without creating a system dump.
+ * User action:
+ * Use a 64-bit dump tool to obtain a system dump for 64-bit Linux instance.
+ */
+/*?
+ * Text: "The 64-bit dump tool cannot be used for a 32-bit system\n"
+ * Severity: Alert
+ * Description:
+ * The dump process ends without creating a system dump.
+ * User action:
+ * Use a 32-bit dump tool to obtain a system dump for 32-bit Linux instance.
+ */
+/*?
+ * Text: "The dump process started for a 64-bit operating system\n"
+ * Severity: Alert
+ * Description:
+ * The SCSI dump process started to create a dump for a 64-bit operating
+ * system instance.
+ * User action:
+ * None.
+ */
+/*? Text: "0x%x is an unknown architecture.\n" */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/zfcp
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/zfcp
@@ -0,0 +1,709 @@
+/*?
+ * Text: "%s is not a valid SCSI device\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: device specification
+ * Description:
+ * The specification for an initial SCSI device provided with the 'zfcp.device'
+ * kernel parameter or with the 'device' module parameter is syntactically
+ * incorrect. The specified SCSI device could not be attached to the Linux
+ * system.
+ * User action:
+ * Correct the value for the 'zfcp.device' or 'device' parameter and reboot
+ * Linux. See "Device Drivers, Features, and Commands" for information about
+ * the syntax.
+ */
+
+/*?
+ * Text: "The zfcp device driver could not register with the common I/O layer\n"
+ * Severity: Error
+ * Description:
+ * The device driver initialization failed. A possible cause of this problem is
+ * memory constraints.
+ * User action:
+ * Free some memory and try again to load the zfcp device driver. If the zfcp
+ * device driver has been compiled into the kernel, reboot Linux. Consider
+ * assigning more memory to your LPAR or z/VM guest virtual machine. If the
+ * problem persists, contact your support organization.
+ */
+
+/*?
+ * Text: "%s: Setting up data structures for the FCP adapter failed\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ * Description:
+ * The zfcp device driver could not allocate data structures for an FCP adapter.
+ * A possible reason for this problem is memory constraints.
+ * User action:
+ * Set the FCP adapter offline or detach it from the Linux system, free some
+ * memory and set the FCP adapter online again or attach it again. If this
+ * problem persists, gather Linux debug data, collect the FCP adapter
+ * hardware logs, and report the problem to your support organization.
+ */
+
+/*?
+ * Text: "%s: The FCP device is operational again\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ * Description:
+ * An FCP device has been unavailable because it had been detached from the
+ * Linux system or because the corresponding CHPID was offline. The FCP device
+ * is now available again and the zfcp device driver resumes all operations to
+ * the FCP device.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "%s: The CHPID for the FCP device is offline\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ * Description:
+ * The CHPID for an FCP device has been set offline, either logically in Linux
+ * or on the hardware.
+ * User action:
+ * Find out which CHPID corresponds to the FCP device, for example, with the
+ * lscss command. Check if the CHPID has been set logically offline in sysfs.
+ * Write 'on' to the CHPID's status attribute to set it online. If the CHPID is
+ * online in sysfs, find out if it has been varied offline through a hardware
+ * management interface, for example the service element (SE).
+ */
+
+/*?
+ * Text: "%s: The FCP device has been detached\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ * Description:
+ * An FCP device is no longer available to Linux.
+ * User action:
+ * Ensure that the FCP adapter is operational and attached to the LPAR or z/VM
+ * virtual machine.
+ */
+
+/*?
+ * Text: "%s: The FCP device did not respond within the specified time\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ * Description:
+ * The common I/O layer waited for a response from the FCP adapter but
+ * no response was received within the specified time limit. This might
+ * indicate a hardware problem.
+ * User action:
+ * Consult your hardware administrator. If this problem persists,
+ * gather Linux debug data, collect the FCP adapter hardware logs, and
+ * report the problem to your support organization.
+ */
+
+/*?
+ * Text: "%s: Registering the FCP device with the SCSI stack failed\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ * Description:
+ * The FCP adapter could not be registered with the Linux SCSI
+ * stack. A possible reason for this problem is memory constraints.
+ * User action:
+ * Set the FCP adapter offline or detach it from the Linux system, free some
+ * memory and set the FCP adapter online again or attach it again. If this
+ * problem persists, gather Linux debug data, collect the FCP adapter
+ * hardware logs, and report the problem to your support organization.
+ */
+
+/*?
+ * Text: "%s: ERP cannot recover an error on the FCP device\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ * Description:
+ * An error occurred on an FCP device. The error recovery procedure (ERP)
+ * could not resolve the error. The FCP device driver cannot use the FCP device.
+ * User action:
+ * Check for previous error messages for the same FCP device to find the
+ * cause of the problem.
+ */
+
+/*?
+ * Text: "%s: Creating an ERP thread for the FCP device failed.\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ * Description:
+ * The zfcp device driver could not set up error recovery procedure (ERP)
+ * processing for the FCP device. The FCP device is not available for use
+ * in Linux.
+ * User action:
+ * Free some memory and try again to load the zfcp device driver. If the zfcp
+ * device driver has been compiled into the kernel, reboot Linux. Consider
+ * assigning more memory to your LPAR or z/VM guest virtual machine. If the
+ * problem persists, contact your support organization.
+ */
+
+/*?
+ * Text: "%s: ERP failed for LUN 0x%016Lx on port 0x%016Lx\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ *   @2: LUN
+ *   @3: WWPN
+ * Description:
+ * An error occurred on the SCSI device at the specified LUN. The error recovery
+ * procedure (ERP) could not resolve the error. The SCSI device is not
+ * available.
+ * User action:
+ * Verify that the LUN is correct. Check the fibre channel fabric for errors
+ * related to the specified WWPN and LUN, the storage server, and Linux.
+ */
+
+/*?
+ * Text: "%s: ERP failed for remote port 0x%016Lx\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ *   @2: WWPN
+ * Description:
+ * An error occurred on a remote port. The error recovery procedure (ERP)
+ * could not resolve the error. The port is not available.
+ * User action:
+ * Verify that the WWPN is correct and check the fibre channel fabric for
+ * errors related to the WWPN.
+ */
+
+/*?
+ * Text: "%s: Registering port 0x%016Lx failed\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ *   @2: WWPN
+ * Description:
+ * The Linux kernel could not allocate enough memory to register the
+ * remote port with the indicated WWPN with the SCSI stack. The remote
+ * port is not available.
+ * User action:
+ * Free some memory and trigger the rescan for ports.
+ */
+
+/*?
+ * Text: "%s: A QDIO problem occurred\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ * Description:
+ * QDIO reported a problem to the zfcp device driver. The zfcp device driver
+ * tries to recover this problem.
+ * User action:
+ * Check for related error messages. If this problem occurs frequently, gather
+ * Linux debug data and contact your support organization.
+ */
+
+/*?
+ * Text: "%s: Setting up the QDIO connection to the FCP adapter failed\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ * Description:
+ * The zfcp device driver failed to establish a QDIO connection with the FCP
+ * adapter.
+ * User action:
+ * Set the FCP adapter offline or detach it from the Linux system, free some
+ * memory and set the FCP adapter online again or attach it again. If this
+ * problem persists, gather Linux debug data, collect the FCP adapter
+ * hardware logs, and report the problem to your support organization.
+ */
+
+/*?
+ * Text: "%s: The FCP adapter reported a problem that cannot be recovered\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ * Description:
+ * The FCP adapter has a problem that cannot be recovered by the zfcp device
+ * driver. The zfcp device driver stopped using the FCP device.
+ * User action:
+ * Gather Linux debug data, collect the FCP adapter hardware logs, and report
+ * this problem to your support organization.
+ */
+
+/*?
+ * Text: "%s: There is a wrap plug instead of a fibre channel cable\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ * Description:
+ * The FCP adapter is not physically connected to the fibre channel fabric.
+ * User action:
+ * Remove the wrap plug from the FCP adapter and connect the adapter with the
+ * fibre channel fabric.
+ */
+
+/*?
+ * Text: "%s: FCP device not operational because of an unsupported FC class\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ * Description:
+ * The FCP adapter hardware does not support the fibre channel service class
+ * requested by the zfcp device driver. This problem indicates a program error
+ * in the zfcp device driver.
+ * User action:
+ * Gather Linux debug data, collect the FCP adapter hardware logs, and report
+ * this problem to your support organization.
+ */
+
+/*?
+ * Text: "%s: 0x%Lx is an ambiguous request identifier\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ *   @2: request ID
+ * Description:
+ * The FCP adapter reported that it received the same request ID twice. This is
+ * an error. The zfcp device driver stopped using the FCP device.
+ * User action:
+ * Gather Linux debug data, collect the FCP adapter hardware logs, and report
+ * this problem to your support organization.
+ */
+
+/*?
+ * Text: "%s: QTCB version 0x%x not supported by FCP adapter (0x%x to 0x%x)\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ *   @2: requested version
+ *   @3: lowest supported version
+ *   @4: highest supported version
+ * Description:
+ * See message text.
+ * The queue transfer control block (QTCB) version requested by the zfcp device
+ * driver is not supported by the FCP adapter hardware.
+ * User action:
+ * If the requested version is higher than the highest version supported by the
+ * hardware, install more recent firmware on the FCP adapter. If the requested
+ * version is lower then the lowest version supported by the hardware, upgrade
+ * to a Linux level with a more recent zfcp device driver.
+ */
+
+/*?
+ * Text: "%s: The FCP adapter could not log in to the fibre channel fabric\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ * Description:
+ * The fibre channel switch rejected the login request from the FCP adapter.
+ * User action:
+ * Check the fibre channel fabric or switch logs for possible errors.
+ */
+
+/*?
+ * Text: "%s: The FCP device is suspended because of a firmware update\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ * Description:
+ * The FCP device is not available while a firmware update is in progress. This
+ * problem is temporary. The FCP device will resume operations when the
+ * firmware update is completed.
+ * User action:
+ * Wait 10 seconds and try the operation again.
+ */
+
+/*?
+ * Text: "%s: All NPIV ports on the FCP adapter have been assigned\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ * Description:
+ * The number of N_Port ID Virtualization (NPIV) ports that can be assigned
+ * on an FCP adapter is limited. Once assigned, NPIV ports are not released
+ * automatically but have to be released explicitly through the support
+ * element (SE).
+ * User action:
+ * Identify NPIV ports that have been assigned but are no longer in use and
+ * release them from the SE.
+ */
+
+/*?
+ * Text: "%s: The link between the FCP adapter and the FC fabric is down\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ * Description:
+ * The FCP adapter is not usable. Specific error information is not available.
+ * User action:
+ * Check the cabling and the fibre channel fabric configuration. If this
+ * problem persists, gather Linux debug data, collect the FCP adapter
+ * hardware logs, and report the problem to your support organization.
+ */
+
+/*?
+ * Text: "%s: The QTCB type is not supported by the FCP adapter\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ * Description:
+ * The queue transfer control block (QTCB) type requested by the zfcp device
+ * driver is not supported by the FCP adapter hardware.
+ * User action:
+ * Install the latest firmware on your FCP adapter hardware. If this does not
+ * resolve the problem, upgrade to a Linux level with a more recent zfcp device
+ * driver. If the problem persists, contact your support organization.
+ */
+
+/*?
+ * Text: "%s: The error threshold for checksum statistics has been exceeded\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ * Description:
+ * The FCP adapter has reported a large number of bit errors. This might
+ * indicate a problem with the physical components of the fibre channel fabric.
+ * Details about the errors have been written to the HBA trace for the FCP
+ * adapter.
+ * User action:
+ * Check for problems in the fibre channel fabric and ensure that all cables
+ * are properly plugged.
+ */
+
+/*?
+ * Text: "%s: The local link has been restored\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ * Description:
+ * A problem with the connection between the FCP adapter and the adjacent node
+ * on the fibre channel fabric has been resolved. The FCP adapter is now
+ * available again.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "%s: The mode table on the FCP adapter has been damaged\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ * Description:
+ * This is an FCP adapter hardware problem.
+ * User action:
+ * Report this problem with FCP hardware logs to IBM support.
+ */
+
+/*?
+ * Text: "%s: The adjacent fibre channel node does not support FCP\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ * Description:
+ * The fibre channel switch or storage system that is connected to the FCP
+ * channel does not support the fibre channel protocol (FCP). The zfcp
+ * device driver stopped using the FCP device.
+ * User action:
+ * Check the adjacent fibre channel node.
+ */
+
+/*?
+ * Text: "%s: The FCP adapter does not recognize the command 0x%x\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ *   @2: command
+ * Description:
+ * A command code that was sent from the zfcp device driver to the FCP adapter
+ * is not valid. The zfcp device driver stopped using the FCP device.
+ * User action:
+ * Gather Linux debug data, collect the FCP adapter hardware logs, and report
+ * this problem to your support organization.
+ */
+
+/*?
+ * Text: "%s: There is no light signal from the local fibre channel cable\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ * Description:
+ * There is no signal on the fibre channel cable that connects the FCP adapter
+ * to the fibre channel fabric.
+ * User action:
+ * Ensure that the cable is in place and connected properly to the FCP adapter
+ * and to the adjacent fibre channel switch or storage system.
+ */
+
+/*?
+ * Text: "%s: The WWPN assignment file on the FCP adapter has been damaged\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ * Description:
+ * This is an FCP adapter hardware problem.
+ * User action:
+ * Report this problem with FCP hardware logs to IBM support.
+ */
+
+/*?
+ * Text: "%s: The FCP device detected a WWPN that is duplicate or not valid\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ * Description:
+ * This condition indicates an error in the FCP adapter hardware or in the z/VM
+ * hypervisor.
+ * User action:
+ * Gather Linux debug data, collect the FCP adapter hardware logs, and report
+ * this problem to IBM support.
+ */
+
+/*?
+ * Text: "%s: The fibre channel fabric does not support NPIV\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ * Description:
+ * The FCP adapter requires N_Port ID Virtualization (NPIV) from the adjacent
+ * fibre channel node. Either the FCP adapter is connected to a fibre channel
+ * switch that does not support NPIV or the FCP adapter tries to use NPIV in a
+ * point-to-point setup. The connection is not operational.
+ * User action:
+ * Verify that NPIV is correctly used for this connection. Check the FCP adapter
+ * configuration and the fibre channel switch configuration. If necessary,
+ * update the fibre channel switch firmware.
+ */
+
+/*?
+ * Text: "%s: The FCP adapter cannot support more NPIV ports\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ * Description:
+ * N_Port ID Virtualization (NPIV) ports consume physical resources on the FCP
+ * adapter. The FCP adapter resources are exhausted. The connection is not
+ * operational.
+ * User action:
+ * Analyze the number of available NPIV ports and which operating system
+ * instances use them. If necessary, reconfigure your setup to move some
+ * NPIV ports to an FCP adapter with free resources.
+ */
+
+/*?
+ * Text: "%s: The adjacent switch cannot support more NPIV ports\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ * Description:
+ * N_Port ID Virtualization (NPIV) ports consume physical resources. The
+ * resources of the fibre channel switch that is connected to the FCP adapter
+ * are exhausted. The connection is not operational.
+ * User action:
+ * Analyze the number of available NPIV ports on the adjacent fibre channel
+ * switch and how they are used. If necessary, reconfigure your fibre channel
+ * fabric to accommodate the required NPIV ports.
+ */
+
+/*?
+ * Text: "%s: 0x%x is not a valid transfer protocol status\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ *   @2: status information
+ * Description:
+ * The transfer protocol status information reported by the FCP adapter is not
+ * a valid status for the zfcp device driver. The zfcp device driver stopped
+ * using the FCP device.
+ * User action:
+ * Gather Linux debug data, collect the FCP adapter hardware logs, and report
+ * this problem to your support organization.
+ */
+
+/*?
+ * Text: "%s: Unknown or unsupported arbitrated loop fibre channel topology detected\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ * Description:
+ * The FCP device is connected to a fibre channel arbitrated loop or the FCP adapter
+ * reported an unknown fibre channel topology. The zfcp device driver supports
+ * point-to-point connections and switched fibre channel fabrics but not arbitrated
+ * loop topologies. The FCP device cannot be used.
+ * User action:
+ * Check the fibre channel setup and ensure that only supported topologies are
+ * connected to the FCP adapter.
+ */
+
+/*?
+ * Text: "%s: FCP adapter maximum QTCB size (%d bytes) is too small\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ *   @2: maximum supported size
+ *   @3: requested QTCB size
+ * Description:
+ * The queue transfer control block (QTCB) size requested by the zfcp
+ * device driver is not supported by the FCP adapter hardware.
+ * User action:
+ * Update the firmware on your FCP adapter hardware to the latest
+ * available level and update the Linux kernel to the latest supported
+ * level. If the problem persists, contact your support organization.
+ */
+
+/*?
+ * Text: "%s: The FCP adapter only supports newer control block versions\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ * Description:
+ * The protocol supported by the FCP adapter is not compatible with the zfcp
+ * device driver.
+ * User action:
+ * Upgrade your Linux kernel to a level that includes a zfcp device driver
+ * with support for the control block version required by your FCP adapter.
+ */
+
+/*?
+ * Text: "%s: The FCP adapter only supports older control block versions\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ * Description:
+ * The protocol supported by the FCP adapter is not compatible with the zfcp
+ * device driver.
+ * User action:
+ * Install the latest firmware on your FCP adapter.
+ */
+
+/*?
+ * Text: "%s: Not enough FCP adapter resources to open remote port 0x%016Lx\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ *   @2: WWPN
+ * Description:
+ * Each port that is opened consumes physical resources of the FCP adapter to
+ * which it is attached. These resources are exhausted and the specified port
+ * cannot be opened.
+ * User action:
+ * Reduce the total number of remote ports that are attached to the
+ * FCP adapter.
+ */
+
+/*?
+ * Text: "%s: LUN 0x%Lx on port 0x%Lx is already in use by CSS%d, MIF Image ID %x\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ *   @2: LUN
+ *   @3: remote port WWPN
+ *   @4: channel subsystem ID
+ *   @5: MIF Image ID of the LPAR
+ * Description:
+ * The SCSI device at the indicated LUN is already in use by another system.
+ * Only one system at a time can use the SCSI device.
+ * User action:
+ * Ensure that the other system stops using the device before trying to use it.
+ */
+
+/*?
+ * Text: "%s: No handle is available for LUN 0x%016Lx on port 0x%016Lx\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ *   @2: LUN
+ *   @3: WWPN
+ * Description:
+ * The FCP adapter can only open a limited number of SCSI devices. This limit
+ * has been reached and the SCSI device at the indicated LUN cannot be opened.
+ * User action:
+ * For FCP subchannels running in non-NPIV mode, check all SCSI
+ * devices opened through the FCP adapter and close some of them.  For
+ * FCP subchannels running in NPIV mode, verify the SAN zoning and
+ * host connections on the storage systems. Ensure that the zoning and
+ * host connections only allow access to the required LUNs. As a
+ * workaround, disable the automatic LUN scanning by setting the
+ * zfcp.allow_lun_scan kernel parameter or the allow_lun_scan module
+ * parameter to 0.
+ */
+
+/*?
+ * Text: "%s: Incorrect direction %d, LUN 0x%016Lx on port 0x%016Lx closed\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ *   @2: value in direction field
+ *   @3: LUN
+ *   @4: WWPN
+ * Description:
+ * The direction field in a SCSI request contains an incorrect value. The zfcp
+ * device driver closed down the SCSI device at the indicated LUN.
+ * User action:
+ * Gather Linux debug data and report this problem to your support organization.
+ */
+
+/*?
+ * Text: "%s: Incorrect CDB length %d, LUN 0x%016Lx on port 0x%016Lx closed\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ *   @2: value in length field
+ *   @3: LUN
+ *   @4: WWPN
+ * Description:
+ * The control-data-block (CDB) length field in a SCSI request is not valid or
+ * too large for the FCP adapter. The zfcp device driver closed down the SCSI
+ * device at the indicated LUN.
+ * User action:
+ * Gather Linux debug data and report this problem to your support organization.
+ */
+
+/*?
+ * Text: "%s: Opening WKA port 0x%x failed\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ *   @2: destination ID of the WKA port
+ * Description:
+ * The FCP adapter rejected a request to open the specified
+ * well-known address (WKA) port. No retry is possible.
+ * User action:
+ * Verify the setup and check if the maximum number of remote ports
+ * used through this adapter is below the maximum allowed. If the
+ * problem persists, gather Linux debug data, collect the FCP adapter
+ * hardware logs, and report the problem to your support organization.
+ */
+
+/*?
+ * Text: "%s: The name server reported %d words residual data\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ *   @2: number of words in residual data
+ * Description:
+ * The fibre channel name server sent too much information about remote ports.
+ * The zfcp device driver did not receive sufficient information to attach all
+ * available remote ports in the SAN.
+ * User action:
+ * Verify that you are running the latest firmware level on the FCP
+ * adapter. Check your SAN setup and consider reducing the number of ports
+ * visible to the FCP adapter by using more restrictive zoning in the SAN.
+ */
+
+/*?
+ * Text: "%s: A port opened with WWPN 0x%016Lx returned data that identifies it as WWPN 0x%016Lx\n"
+ * Severity: Warning
+ * Parameter:
+ *   @1: bus ID of the zfcp device
+ *   @2: expected WWPN
+ *   @3: reported WWPN
+ * Description:
+ * A remote port was opened successfully, but it reported an
+ * unexpected WWPN in the returned port login (PLOGI) data. This
+ * condition might have been caused by a change applied to the SAN
+ * configuration while the port was being opened.
+ * User action:
+ * If this condition is only temporary and access to the remote port
+ * is possible, no action is required. If the condition persists,
+ * identify the storage system with the specified WWPN and contact the
+ * support organization of the storage system.
+ */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/s390/zpci
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/s390/zpci
@@ -0,0 +1,42 @@
+/*?
+ * Text: "%s: Event 0x%x reconfigured PCI function 0x%x\n"
+ * Severity: Informational
+ * Parameter:
+ *   @1: device name of the function
+ *   @2: PCI event code
+ *   @3: function ID
+ * Description:
+ * The availability of a PCI function has changed.
+ * Possible reasons for the change include PCI configuration actions on the
+ * Hardware Management Console or hypervisor.
+ * For shared PCI functions, the function might also have been reserved or
+ * released by another system.
+ * If the device name of a function is shown as 'n/a', the device registration
+ * with the PCI device driver has not completed.
+ * The function ID identifies the function to the I/O configuration (IOCDS).
+ * The PCI event code can be useful diagnostic information for your support
+ * organization.
+ * User action:
+ * None.
+ */
+
+/*?
+ * Text: "%s: Event 0x%x reports an error for PCI function 0x%x\n"
+ * Severity: Error
+ * Parameter:
+ *   @1: device name of the function
+ *   @2: PCI event code
+ *   @3: function ID
+ * Description:
+ * A PCI function entered an error state from which it cannot recover
+ * automatically.
+ * User action:
+ * Trigger a recovery action by writing '1' to the 'recover' sysfs attribute
+ * of the PCI function.
+ * In sysfs, PCI functions are represented as /sys/bus/pci/devices/<name>,
+ * where <name> is the device name of the function.
+ * If the device name of a function is shown as 'n/a', the device
+ * registration with the PCI device driver has not completed.
+ * If the problem persists, contact your support organization.
+ */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/sbp_target
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/sbp_target
@@ -0,0 +1,49 @@
+/*? Text: "ABORT TASK SET not implemented\n" */
+/*? Text: "ABORT TASK not implemented\n" */
+/*? Text: "Cannot change the directory_id on an active target.\n" */
+/*? Text: "Cannot enable a target with no LUNs!\n" */
+/*? Text: "Could not update Config ROM\n" */
+/*? Text: "Ignoring ORB_POINTER write while active.\n" */
+/*? Text: "LOGICAL UNIT RESET not implemented\n" */
+/*? Text: "Node ACL not found for %s\n" */
+/*? Text: "Only one TPG per Unit is possible.\n" */
+/*? Text: "QUERY LOGINS not implemented\n" */
+/*? Text: "Reconnect timer expired for node: %016llx\n" */
+/*? Text: "SET PASSWORD not implemented\n" */
+/*? Text: "TARGET RESET not implemented\n" */
+/*? Text: "Unable to allocate struct sbp_nacl\n" */
+/*? Text: "Unable to allocate struct sbp_tpg\n" */
+/*? Text: "Unable to allocate struct sbp_tport\n" */
+/*? Text: "Waiting for reconnect from node: %016llx\n" */
+/*? Text: "cannot find login: %d\n" */
+/*? Text: "failed to allocate login descriptor\n" */
+/*? Text: "failed to allocate login response block\n" */
+/*? Text: "failed to allocate session descriptor\n" */
+/*? Text: "failed to init se_session\n" */
+/*? Text: "failed to map command block handler: %d\n" */
+/*? Text: "failed to read peer GUID: %d\n" */
+/*? Text: "ignoring management request while busy\n" */
+/*? Text: "ignoring request from foreign node (%x != %x)\n" */
+/*? Text: "ignoring request with wrong generation\n" */
+/*? Text: "initiator already logged-in\n" */
+/*? Text: "login to unknown LUN: %d\n" */
+/*? Text: "logout from different node ID\n" */
+/*? Text: "max number of logins reached\n" */
+/*? Text: "mgt_agent LOGIN to LUN %d from %016llx\n" */
+/*? Text: "mgt_agent LOGOUT from LUN %d session %d\n" */
+/*? Text: "mgt_agent RECONNECT from %016llx\n" */
+/*? Text: "mgt_agent RECONNECT login GUID doesn't match\n" */
+/*? Text: "mgt_agent RECONNECT unknown login ID\n" */
+/*? Text: "mgt_orb bad request\n" */
+/*? Text: "netif_stop_queue() cannot be called before register_netdev()\n" */
+/*? Text: "refusing exclusive login with other active logins\n" */
+/*? Text: "refusing login while another exclusive login present\n" */
+/*? Text: "sbp_run_transaction: page size ignored\n" */
+/*? Text: "sbp_send_sense: unknown sense format: 0x%x\n" */
+/*? Text: "target_fabric_configfs_init() failed\n" */
+/*? Text: "target_fabric_configfs_register() failed for SBP\n" */
+/*? Text: "unknown management function 0x%x\n" */
+/*? Text: "unlink LUN: failed to update unit directory\n" */
+/*? Text: "flen=%u proglen=%u pass=%u image=%pK from=%s pid=%d\n" */
+/*? Text: "%s selects TX queue %d, but real number of TX queues is %d\n" */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
\ No newline at end of file
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/kmsg/zram
+++ linux-xilinx-zynqmp-5.4.0/Documentation/kmsg/zram
@@ -0,0 +1,34 @@
+/*? Text: "Error allocating compressor buffer space\n" */
+/*? Text: "Error allocating memory for compressed page: %u, size=%zu\n" */
+/*? Text: "Error creating memory pool\n" */
+/*? Text: "num_devices not specified. Using default: 1\n" */
+/*? Text: "Error allocating compressor working memory!\n" */
+/*? Text: "Error allocating zram address table\n" */
+/*? Text: "Unable to get major number\n" */
+/*? Text: "Compression failed! err=%d\n" */
+/*? Text: "Decompression failed! err=%d, page=%u\n" */
+/*? Text: "There is little point creating a zram of greater than twice the size of memory since we expect a 2:1 compression ratio. Note that zram uses about 0.1%% of the size of the disk when not in use so a huge zram is wasteful.\n\tMemory Size: %zu kB\n\tSize you selected: %llu kB\nContinuing anyway ...\n" */
+/*? Text: "disk size not provided. You can use disksize_kb module param to specify size.\nUsing default: (%u%% of RAM).\n" */
+/*? Text: "Error creating sysfs group" */
+/*? Text: "Error allocating memory for incompressible page: %u\n" */
+/*? Text: "Creating %u devices ...\n" */
+/*? Text: "Initialization failed: err=%d\n" */
+/*? Text: "Error allocating disk queue for device %d\n" */
+/*? Text: "Error allocating disk structure for device %d\n" */
+/*? Text: "Invalid value for num_devices: %u\n" */
+/*? Text: "Error allocating temp memory!\n" */
+/*? Text: "Unable to allocate temp memory\n" */
+/*? Text: "Created %u device(s) ...\n" */
+/*? Text: "There is little point creating a zram of greater than twice the size of memory since we expect a 2:1 compression ratio. Note that zram uses about 0.1%% of the size of the disk when not in use so a huge zram is wasteful.\n\tMemory Size: %lu kB\n\tSize you selected: %llu kB\nContinuing anyway ...\n" */
+/*? Text: "Cannot change disksize for initialized device\n" */
+/*? Text: "Can't change algorithm for initialized device\n" */
+/*? Text: "Cannot initialise %s compressing backend\n" */
+/*? Text: "Cannot change max compression streams\n" */
+/*? Text: "Destroyed %u device(s)\n" */
+/*? Text: "Created %u device(s)\n" */
+/*? Text: "Unable to register zram-control class\n" */
+/*? Text: "Removed device: %s\n" */
+/*? Text: "Added device: %s\n" */
+/*? Text: "Error creating sysfs group for device %d\n" */
+/*? Text: "Error allocating memory for compressed page: %u, size=%u\n" */
+/*? Text: "%s: %d output lines suppressed due to ratelimiting\n" */
\ No newline at end of file
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/lzo.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/lzo.txt
@@ -159,11 +159,15 @@
            distance = 16384 + (H << 14) + D
            state = S (copy S literals after this block)
            End of stream is reached if distance == 16384
+           In version 1 only, to prevent ambiguity with the RLE case when
+           ((distance & 0x803f) == 0x803f) && (261 <= length <= 264), the
+           compressor must not emit block copies where distance and length
+           meet these conditions.
 
         In version 1 only, this instruction is also used to encode a run of
-        zeros if distance = 0xbfff, i.e. H = 1 and the D bits are all 1.
+           zeros if distance = 0xbfff, i.e. H = 1 and the D bits are all 1.
            In this case, it is followed by a fourth byte, X.
-           run length = ((X << 3) | (0 0 0 0 0 L L L)) + 4.
+           run length = ((X << 3) | (0 0 0 0 0 L L L)) + 4
 
       0 0 1 L L L L L  (32..63)
            Copy of small block within 16kB distance (preferably less than 34B)
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/media/kapi/v4l2-dev.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/media/kapi/v4l2-dev.rst
@@ -185,7 +185,7 @@
 
 .. code-block:: c
 
-	err = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
+	err = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
 	if (err) {
 		video_device_release(vdev); /* or kfree(my_vdev); */
 		return err;
@@ -201,7 +201,7 @@
 ========================== ====================	 ==============================
 :c:type:`vfl_devnode_type` Device name		 Usage
 ========================== ====================	 ==============================
-``VFL_TYPE_GRABBER``       ``/dev/videoX``       for video input/output devices
+``VFL_TYPE_VIDEO``         ``/dev/videoX``       for video input/output devices
 ``VFL_TYPE_VBI``           ``/dev/vbiX``         for vertical blank data (i.e.
 						 closed captions, teletext)
 ``VFL_TYPE_RADIO``         ``/dev/radioX``       for radio tuners
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/media/uapi/mediactl/media-types.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/media/uapi/mediactl/media-types.rst
@@ -46,6 +46,7 @@
 .. _MEDIA-ENT-F-PROC-VIDEO-STATISTICS:
 .. _MEDIA-ENT-F-PROC-VIDEO-ENCODER:
 .. _MEDIA-ENT-F-PROC-VIDEO-DECODER:
+.. _MEDIA-ENT-F-PROC-VIDEO-ISP:
 .. _MEDIA-ENT-F-VID-MUX:
 .. _MEDIA-ENT-F-VID-IF-BRIDGE:
 .. _MEDIA-ENT-F-DV-DECODER:
@@ -208,6 +209,12 @@
           decompressing a compressed video stream into uncompressed video
 	  frames. Must have one sink pad and at least one source pad.
 
+    *  -  ``MEDIA_ENT_F_PROC_VIDEO_ISP``
+       -  An Image Signal Processor (ISP) device. ISPs generally are one of a
+	  kind devices that have their specific control interfaces using a
+	  combination of custom V4L2 controls and IOCTLs, and parameters
+	  supplied in a metadata buffer.
+
     *  -  ``MEDIA_ENT_F_VID_MUX``
        - Video multiplexer. An entity capable of multiplexing must have at
          least two sink pads and one source pad, and must pass the video
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/media/uapi/v4l/biblio.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/media/uapi/v4l/biblio.rst
@@ -405,3 +405,13 @@
 :title:     RFC 6386: "VP8 Data Format and Decoding Guide"
 
 :author:    J. Bankoski et al.
+
+.. _itu2100:
+
+ITU BT.2100
+===========
+
+
+:title:     ITU-R Recommendation BT.2100-2 (07/2018) "Image parameter values for high dynamic range television for use in production and international programme exchange"
+
+:author:    International Telecommunication Union (http://www.itu.int)
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/media/uapi/v4l/colorspaces-defs.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/media/uapi/v4l/colorspaces-defs.rst
@@ -36,8 +36,7 @@
 :c:type:`v4l2_hsv_encoding` specifies which encoding is used.
 
 .. note:: The default R'G'B' quantization is full range for all
-   colorspaces except for BT.2020 which uses limited range R'G'B'
-   quantization.
+   colorspaces. HSV formats are always full range.
 
 .. tabularcolumns:: |p{6.7cm}|p{10.8cm}|
 
@@ -107,6 +106,8 @@
       - Use the DCI-P3 transfer function.
     * - ``V4L2_XFER_FUNC_SMPTE2084``
       - Use the SMPTE 2084 transfer function. See :ref:`xf-smpte-2084`.
+    * - ``V4L2_XFER_FUNC_HLG``
+      - Use the Hybrid Log Gamma(HLG) transfer function. See :ref:`xf-hlg`.
 
 
 
@@ -169,8 +170,8 @@
       - Details
     * - ``V4L2_QUANTIZATION_DEFAULT``
       - Use the default quantization encoding as defined by the
-	colorspace. This is always full range for R'G'B' (except for the
-	BT.2020 colorspace) and HSV. It is usually limited range for Y'CbCr.
+	colorspace. This is always full range for R'G'B' and HSV.
+	It is usually limited range for Y'CbCr.
     * - ``V4L2_QUANTIZATION_FULL_RANGE``
       - Use the full range quantization encoding. I.e. the range [0…1] is
 	mapped to [0…255] (with possible clipping to [1…254] to avoid the
@@ -180,4 +181,4 @@
     * - ``V4L2_QUANTIZATION_LIM_RANGE``
       - Use the limited range quantization encoding. I.e. the range [0…1]
 	is mapped to [16…235]. Cb and Cr are mapped from [-0.5…0.5] to
-	[16…240].
+	[16…240]. Limited Range cannot be used with HSV.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/media/uapi/v4l/colorspaces-details.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/media/uapi/v4l/colorspaces-details.rst
@@ -377,9 +377,8 @@
 The :ref:`itu2020` standard defines the colorspace used by Ultra-high
 definition television (UHDTV). The default transfer function is
 ``V4L2_XFER_FUNC_709``. The default Y'CbCr encoding is
-``V4L2_YCBCR_ENC_BT2020``. The default R'G'B' quantization is limited
-range (!), and so is the default Y'CbCr quantization. The chromaticities
-of the primary colors and the white reference are:
+``V4L2_YCBCR_ENC_BT2020``. The default Y'CbCr quantization is limited range.
+The chromaticities of the primary colors and the white reference are:
 
 
 
@@ -811,3 +810,34 @@
 
 There are better methods, see e.g. :ref:`colimg` for more in-depth information
 about this.
+
+
+.. _xf-hlg:
+
+Transfer Function HLG (V4L2_XFER_FUNC_HLG)
+=======================================================
+
+The :ref:`itu2100` defines the transfer function used.
+
+Constants:
+
+.. math::
+    a = 0.17883277
+
+    b = 1 - 4 * a = 0.28466892
+
+    c = 0.5 - a * \ln (4 * a) = 0.55991073
+
+Transfer function:
+
+.. math::
+
+     E' = \begin{cases}\sqrt(3 * E) & 0 \leq E \leq \frac{1}{12}
+     \\ a * \ln(12 * E - b) + c & \frac{1}{12} \le E \leq 1\end{cases}
+
+Inverse Transfer function:
+
+.. math::
+
+     x' =\begin{cases}x^{2} / 3  & 0 \leq x \leq \frac{1}{12}
+     \\(exp((x - c) / a) + b) / 12 & \frac{1}{12} \le x \leq 1\end{cases}
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/media/uapi/v4l/subdev-formats.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/media/uapi/v4l/subdev-formats.rst
@@ -1531,6 +1531,43 @@
       - b\ :sub:`2`
       - b\ :sub:`1`
       - b\ :sub:`0`
+    * .. _MEDIA-BUS-FMT-RBG101010-1X30:
+
+      - MEDIA_BUS_FMT_RBG101010_1X30
+      - 0x1100
+      -
+      - 0
+      - 0
+      - r\ :sub:`9`
+      - r\ :sub:`8`
+      - r\ :sub:`7`
+      - r\ :sub:`6`
+      - r\ :sub:`5`
+      - r\ :sub:`4`
+      - r\ :sub:`3`
+      - r\ :sub:`2`
+      - r\ :sub:`1`
+      - r\ :sub:`0`
+      - b\ :sub:`9`
+      - b\ :sub:`8`
+      - b\ :sub:`7`
+      - b\ :sub:`6`
+      - b\ :sub:`5`
+      - b\ :sub:`4`
+      - b\ :sub:`3`
+      - b\ :sub:`2`
+      - b\ :sub:`1`
+      - b\ :sub:`0`
+      - g\ :sub:`9`
+      - g\ :sub:`8`
+      - g\ :sub:`7`
+      - g\ :sub:`6`
+      - g\ :sub:`5`
+      - g\ :sub:`4`
+      - g\ :sub:`3`
+      - g\ :sub:`2`
+      - g\ :sub:`1`
+      - g\ :sub:`0`
 
 .. raw:: latex
 
@@ -1638,6 +1675,47 @@
       - b\ :sub:`2`
       - b\ :sub:`1`
       - b\ :sub:`0`
+    * .. _MEDIA-BUS-FMT-RBG121212-1X36:
+
+      - MEDIA_BUS_FMT_RBG121212_1X36
+      - 0x1101
+      -
+      - r\ :sub:`11`
+      - r\ :sub:`10`
+      - r\ :sub:`9`
+      - r\ :sub:`8`
+      - r\ :sub:`7`
+      - r\ :sub:`6`
+      - r\ :sub:`5`
+      - r\ :sub:`4`
+      - r\ :sub:`3`
+      - r\ :sub:`2`
+      - r\ :sub:`1`
+      - r\ :sub:`0`
+      - b\ :sub:`11`
+      - b\ :sub:`10`
+      - b\ :sub:`9`
+      - b\ :sub:`8`
+      - b\ :sub:`7`
+      - b\ :sub:`6`
+      - b\ :sub:`5`
+      - b\ :sub:`4`
+      - b\ :sub:`3`
+      - b\ :sub:`2`
+      - b\ :sub:`1`
+      - b\ :sub:`0`
+      - g\ :sub:`11`
+      - g\ :sub:`10`
+      - g\ :sub:`9`
+      - g\ :sub:`8`
+      - g\ :sub:`7`
+      - g\ :sub:`6`
+      - g\ :sub:`5`
+      - g\ :sub:`4`
+      - g\ :sub:`3`
+      - g\ :sub:`2`
+      - g\ :sub:`1`
+      - g\ :sub:`0`
 
 .. raw:: latex
 
@@ -1807,6 +1885,78 @@
       - b\ :sub:`2`
       - b\ :sub:`1`
       - b\ :sub:`0`
+    * .. _MEDIA-BUS-FMT-RBG161616-1X48:
+
+      - MEDIA_BUS_FMT_RBG161616_1X48
+      - 0x1102
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      - r\ :sub:`15`
+      - r\ :sub:`14`
+      - r\ :sub:`13`
+      - r\ :sub:`12`
+      - r\ :sub:`11`
+      - r\ :sub:`10`
+      - r\ :sub:`9`
+      - r\ :sub:`8`
+      - r\ :sub:`7`
+      - r\ :sub:`6`
+      - r\ :sub:`5`
+      - r\ :sub:`4`
+      - r\ :sub:`3`
+      - r\ :sub:`2`
+      - r\ :sub:`1`
+      - r\ :sub:`0`
+    * -
+      -
+      -
+      - b\ :sub:`15`
+      - b\ :sub:`14`
+      - b\ :sub:`13`
+      - b\ :sub:`12`
+      - b\ :sub:`11`
+      - b\ :sub:`10`
+      - b\ :sub:`9`
+      - b\ :sub:`8`
+      - b\ :sub:`7`
+      - b\ :sub:`6`
+      - b\ :sub:`5`
+      - b\ :sub:`4`
+      - b\ :sub:`3`
+      - b\ :sub:`2`
+      - b\ :sub:`1`
+      - b\ :sub:`0`
+      - g\ :sub:`15`
+      - g\ :sub:`14`
+      - g\ :sub:`13`
+      - g\ :sub:`12`
+      - g\ :sub:`11`
+      - g\ :sub:`10`
+      - g\ :sub:`9`
+      - g\ :sub:`8`
+      - g\ :sub:`7`
+      - g\ :sub:`6`
+      - g\ :sub:`5`
+      - g\ :sub:`4`
+      - g\ :sub:`3`
+      - g\ :sub:`2`
+      - g\ :sub:`1`
+      - g\ :sub:`0`
 
 .. raw:: latex
 
@@ -5187,6 +5337,148 @@
       - u\ :sub:`2`
       - u\ :sub:`1`
       - u\ :sub:`0`
+    * .. _MEDIA-BUS-FMT-VYYUYY10_4X20:
+
+      - MEDIA_BUS_FMT_VYYUYY10_4X20
+      - 0x2101
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      - u\ :sub:`9`
+      - u\ :sub:`8`
+      - u\ :sub:`7`
+      - u\ :sub:`6`
+      - u\ :sub:`5`
+      - u\ :sub:`4`
+      - u\ :sub:`3`
+      - u\ :sub:`2`
+      - u\ :sub:`1`
+      - u\ :sub:`0`
+      - y\ :sub:`9`
+      - y\ :sub:`8`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+    * -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      - v\ :sub:`9`
+      - v\ :sub:`8`
+      - v\ :sub:`7`
+      - v\ :sub:`6`
+      - v\ :sub:`5`
+      - v\ :sub:`4`
+      - v\ :sub:`3`
+      - v\ :sub:`2`
+      - v\ :sub:`1`
+      - v\ :sub:`0`
+      - y\ :sub:`9`
+      - y\ :sub:`8`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+    * -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      - y\ :sub:`9`
+      - y\ :sub:`8`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+    * -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      - y\ :sub:`9`
+      - y\ :sub:`8`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
     * .. _MEDIA-BUS-FMT-Y12-1X12:
 
       - MEDIA_BUS_FMT_Y12_1X12
@@ -6944,6 +7236,185 @@
       - u\ :sub:`2`
       - u\ :sub:`1`
       - u\ :sub:`0`
+    * .. _MEDIA-BUS-FMT-UYYVYY12-4X24:
+
+      - MEDIA_BUS_FMT_UYYVYY12_4X24
+      - 0x2103
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      - u\ :sub:`11`
+      - u\ :sub:`10`
+      - u\ :sub:`9`
+      - u\ :sub:`8`
+      - u\ :sub:`7`
+      - u\ :sub:`6`
+      - u\ :sub:`5`
+      - u\ :sub:`4`
+      - u\ :sub:`3`
+      - u\ :sub:`2`
+      - u\ :sub:`1`
+      - u\ :sub:`0`
+      - y\ :sub:`11`
+      - y\ :sub:`10`
+      - y\ :sub:`9`
+      - y\ :sub:`8`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+    * -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      - v\ :sub:`11`
+      - v\ :sub:`10`
+      - v\ :sub:`9`
+      - v\ :sub:`8`
+      - v\ :sub:`7`
+      - v\ :sub:`6`
+      - v\ :sub:`5`
+      - v\ :sub:`4`
+      - v\ :sub:`3`
+      - v\ :sub:`2`
+      - v\ :sub:`1`
+      - v\ :sub:`0`
+      - y\ :sub:`11`
+      - y\ :sub:`10`
+      - y\ :sub:`9`
+      - y\ :sub:`8`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+    * -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      - y\ :sub:`11`
+      - y\ :sub:`10`
+      - y\ :sub:`9`
+      - y\ :sub:`8`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+    * -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      - y\ :sub:`11`
+      - y\ :sub:`10`
+      - y\ :sub:`9`
+      - y\ :sub:`8`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+    * .. _MEDIA-BUS-FMT-VYYUYY8-1X24:
+
+      - MEDIA_BUS_FMT_VYYUYY8_1X24
+      - 0x2100
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      - v\ :sub:`3`
+      - v\ :sub:`2`
+      - v\ :sub:`1`
+      - v\ :sub:`0`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+      - u\ :sub:`3`
+      - u\ :sub:`2`
+      - u\ :sub:`1`
+      - u\ :sub:`0`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
     * .. _MEDIA-BUS-FMT-YUV10-1X30:
 
       - MEDIA_BUS_FMT_YUV10_1X30
@@ -6981,6 +7452,43 @@
       - v\ :sub:`2`
       - v\ :sub:`1`
       - v\ :sub:`0`
+    * .. _MEDIA-BUS-FMT-VUY10-1X30:
+
+      - MEDIA_BUS_FMT_VUY10_1X30
+      - 0x2102
+      -
+      -
+      -
+      - v\ :sub:`9`
+      - v\ :sub:`8`
+      - v\ :sub:`7`
+      - v\ :sub:`6`
+      - v\ :sub:`5`
+      - v\ :sub:`4`
+      - v\ :sub:`3`
+      - v\ :sub:`2`
+      - v\ :sub:`1`
+      - v\ :sub:`0`
+      - u\ :sub:`9`
+      - u\ :sub:`8`
+      - u\ :sub:`7`
+      - u\ :sub:`6`
+      - u\ :sub:`5`
+      - u\ :sub:`4`
+      - u\ :sub:`3`
+      - u\ :sub:`2`
+      - u\ :sub:`1`
+      - u\ :sub:`0`
+      - y\ :sub:`9`
+      - y\ :sub:`8`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
     * .. _MEDIA-BUS-FMT-UYYVYY10-0-5X30:
 
       - MEDIA_BUS_FMT_UYYVYY10_0_5X30
@@ -7053,6 +7561,43 @@
       - y\ :sub:`2`
       - y\ :sub:`1`
       - y\ :sub:`0`
+    * .. _MEDIA-BUS-FMT-Y16-1X16:
+
+      - MEDIA_BUS_FMT_Y16_1X16
+      - 0x2105
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      - y\ :sub:`15`
+      - y\ :sub:`14`
+      - y\ :sub:`13`
+      - y\ :sub:`12`
+      - y\ :sub:`11`
+      - y\ :sub:`10`
+      - y\ :sub:`9`
+      - y\ :sub:`8`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
     * .. _MEDIA-BUS-FMT-AYUV8-1X32:
 
       - MEDIA_BUS_FMT_AYUV8_1X32
@@ -7090,6 +7635,220 @@
       - v\ :sub:`2`
       - v\ :sub:`1`
       - v\ :sub:`0`
+    * .. _MEDIA-BUS-FMT-UYYVYY16-4X32:
+
+      - MEDIA_BUS_FMT_UYYVYY16_4X32
+      - 0x2106
+      -
+      - u\ :sub:`15`
+      - u\ :sub:`14`
+      - u\ :sub:`13`
+      - u\ :sub:`12`
+      - u\ :sub:`11`
+      - u\ :sub:`10`
+      - u\ :sub:`9`
+      - u\ :sub:`8`
+      - u\ :sub:`7`
+      - u\ :sub:`6`
+      - u\ :sub:`5`
+      - u\ :sub:`4`
+      - u\ :sub:`3`
+      - u\ :sub:`2`
+      - u\ :sub:`1`
+      - u\ :sub:`0`
+      - y\ :sub:`15`
+      - y\ :sub:`14`
+      - y\ :sub:`13`
+      - y\ :sub:`12`
+      - y\ :sub:`11`
+      - y\ :sub:`10`
+      - y\ :sub:`9`
+      - y\ :sub:`8`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+    * -
+      -
+      -
+      - v\ :sub:`15`
+      - v\ :sub:`14`
+      - v\ :sub:`13`
+      - v\ :sub:`12`
+      - v\ :sub:`11`
+      - v\ :sub:`10`
+      - v\ :sub:`9`
+      - v\ :sub:`8`
+      - v\ :sub:`7`
+      - v\ :sub:`6`
+      - v\ :sub:`5`
+      - v\ :sub:`4`
+      - v\ :sub:`3`
+      - v\ :sub:`2`
+      - v\ :sub:`1`
+      - v\ :sub:`0`
+      - y\ :sub:`15`
+      - y\ :sub:`14`
+      - y\ :sub:`13`
+      - y\ :sub:`12`
+      - y\ :sub:`11`
+      - y\ :sub:`10`
+      - y\ :sub:`9`
+      - y\ :sub:`8`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+    * -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      - y\ :sub:`15`
+      - y\ :sub:`14`
+      - y\ :sub:`13`
+      - y\ :sub:`12`
+      - y\ :sub:`11`
+      - y\ :sub:`10`
+      - y\ :sub:`9`
+      - y\ :sub:`8`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+    * -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      - y\ :sub:`15`
+      - y\ :sub:`14`
+      - y\ :sub:`13`
+      - y\ :sub:`12`
+      - y\ :sub:`11`
+      - y\ :sub:`10`
+      - y\ :sub:`9`
+      - y\ :sub:`8`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+    * .. _MEDIA-BUS-FMT-UYVY16-2X32:
+
+      - MEDIA_BUS_FMT_UYVY16_2X32
+      - 0x2108
+      -
+      - u\ :sub:`15`
+      - u\ :sub:`14`
+      - u\ :sub:`13`
+      - u\ :sub:`12`
+      - u\ :sub:`11`
+      - u\ :sub:`10`
+      - u\ :sub:`9`
+      - u\ :sub:`8`
+      - u\ :sub:`7`
+      - u\ :sub:`6`
+      - u\ :sub:`5`
+      - u\ :sub:`4`
+      - u\ :sub:`3`
+      - u\ :sub:`2`
+      - u\ :sub:`1`
+      - u\ :sub:`0`
+      - y\ :sub:`15`
+      - y\ :sub:`14`
+      - y\ :sub:`13`
+      - y\ :sub:`12`
+      - y\ :sub:`11`
+      - y\ :sub:`10`
+      - y\ :sub:`9`
+      - y\ :sub:`8`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
+    * -
+      -
+      -
+      - v\ :sub:`15`
+      - v\ :sub:`14`
+      - v\ :sub:`13`
+      - v\ :sub:`12`
+      - v\ :sub:`11`
+      - v\ :sub:`10`
+      - v\ :sub:`9`
+      - v\ :sub:`8`
+      - v\ :sub:`7`
+      - v\ :sub:`6`
+      - v\ :sub:`5`
+      - v\ :sub:`4`
+      - v\ :sub:`3`
+      - v\ :sub:`2`
+      - v\ :sub:`1`
+      - v\ :sub:`0`
+      - y\ :sub:`15`
+      - y\ :sub:`14`
+      - y\ :sub:`13`
+      - y\ :sub:`12`
+      - y\ :sub:`11`
+      - y\ :sub:`10`
+      - y\ :sub:`9`
+      - y\ :sub:`8`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
 
 
 .. raw:: latex
@@ -7278,6 +8037,47 @@
       - v\ :sub:`2`
       - v\ :sub:`1`
       - v\ :sub:`0`
+    * .. _MEDIA-BUS-FMT-VUY12-1X36:
+
+      - MEDIA_BUS_FMT_VUY12_1X36
+      - 0x2104
+      -
+      - v\ :sub:`11`
+      - v\ :sub:`10`
+      - v\ :sub:`9`
+      - v\ :sub:`8`
+      - v\ :sub:`7`
+      - v\ :sub:`6`
+      - v\ :sub:`5`
+      - v\ :sub:`4`
+      - v\ :sub:`3`
+      - v\ :sub:`2`
+      - v\ :sub:`1`
+      - v\ :sub:`0`
+      - u\ :sub:`11`
+      - u\ :sub:`10`
+      - u\ :sub:`9`
+      - u\ :sub:`8`
+      - u\ :sub:`7`
+      - u\ :sub:`6`
+      - u\ :sub:`5`
+      - u\ :sub:`4`
+      - u\ :sub:`3`
+      - u\ :sub:`2`
+      - u\ :sub:`1`
+      - u\ :sub:`0`
+      - y\ :sub:`11`
+      - y\ :sub:`10`
+      - y\ :sub:`9`
+      - y\ :sub:`8`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
 
 
 .. raw:: latex
@@ -7448,6 +8248,78 @@
       - v\ :sub:`2`
       - v\ :sub:`1`
       - v\ :sub:`0`
+    * .. _MEDIA-BUS-FMT-VUY16-1X48:
+
+      - MEDIA_BUS_FMT_VUY16_1X48
+      - 0x2107
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      -
+      - v\ :sub:`15`
+      - v\ :sub:`14`
+      - v\ :sub:`13`
+      - v\ :sub:`12`
+      - v\ :sub:`11`
+      - v\ :sub:`10`
+      - v\ :sub:`9`
+      - v\ :sub:`8`
+      - v\ :sub:`7`
+      - v\ :sub:`6`
+      - v\ :sub:`5`
+      - v\ :sub:`4`
+      - v\ :sub:`3`
+      - v\ :sub:`2`
+      - v\ :sub:`1`
+      - v\ :sub:`0`
+    * -
+      -
+      -
+      - u\ :sub:`15`
+      - u\ :sub:`14`
+      - u\ :sub:`13`
+      - u\ :sub:`12`
+      - u\ :sub:`11`
+      - u\ :sub:`10`
+      - u\ :sub:`9`
+      - u\ :sub:`8`
+      - u\ :sub:`7`
+      - u\ :sub:`6`
+      - u\ :sub:`5`
+      - u\ :sub:`4`
+      - u\ :sub:`3`
+      - u\ :sub:`2`
+      - u\ :sub:`1`
+      - u\ :sub:`0`
+      - y\ :sub:`15`
+      - y\ :sub:`14`
+      - y\ :sub:`13`
+      - y\ :sub:`12`
+      - y\ :sub:`11`
+      - y\ :sub:`10`
+      - y\ :sub:`8`
+      - y\ :sub:`8`
+      - y\ :sub:`7`
+      - y\ :sub:`6`
+      - y\ :sub:`5`
+      - y\ :sub:`4`
+      - y\ :sub:`3`
+      - y\ :sub:`2`
+      - y\ :sub:`1`
+      - y\ :sub:`0`
     * .. _MEDIA-BUS-FMT-UYYVYY16-0-5X48:
 
       - MEDIA_BUS_FMT_UYYVYY16_0_5X48
@@ -7794,3 +8666,30 @@
       - 0x5001
       - Interleaved raw UYVY and JPEG image format with embedded meta-data
 	used by Samsung S3C73MX camera sensors.
+
+.. _v4l2-mbus-metadata-fmts:
+
+Metadata Formats
+^^^^^^^^^^^^^^^^
+
+This section lists all metadata formats.
+
+The following table lists the existing metadata formats.
+
+.. tabularcolumns:: |p{8.0cm}|p{1.4cm}|p{7.7cm}|
+
+.. flat-table:: Metadata formats
+    :header-rows:  1
+    :stub-columns: 0
+
+    * - Identifier
+      - Code
+      - Comments
+    * .. _MEDIA-BUS-FMT-METADATA-FIXED:
+
+      - MEDIA_BUS_FMT_METADATA_FIXED
+      - 0x7001
+      - This format should be used when the same driver handles
+	both sides of the link and the bus format is a fixed
+	metadata format that is not configurable from userspace.
+	Width and height will be set to 0 for this format.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/media/uapi/v4l/vidioc-queryctrl.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/media/uapi/v4l/vidioc-queryctrl.rst
@@ -473,6 +473,12 @@
       - n/a
       - A struct :c:type:`v4l2_ctrl_h264_decode_params`, containing H264
 	decode parameters for stateless video decoders.
+    * - ``V4L2_CTRL_TYPE_HDR``
+      - n/a
+      - n/a
+      - n/a
+      - A struct :c:type:`v4l2_metadata_hdr`, containing HDR
+	metadata.
 
 .. tabularcolumns:: |p{6.6cm}|p{2.2cm}|p{8.7cm}|
 
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/media/videodev2.h.rst.exceptions
+++ linux-xilinx-zynqmp-5.4.0/Documentation/media/videodev2.h.rst.exceptions
@@ -81,6 +81,7 @@
 replace symbol V4L2_XFER_FUNC_SMPTE2084 :c:type:`v4l2_xfer_func`
 replace symbol V4L2_XFER_FUNC_SMPTE240M :c:type:`v4l2_xfer_func`
 replace symbol V4L2_XFER_FUNC_SRGB :c:type:`v4l2_xfer_func`
+replace symbol V4L2_XFER_FUNC_HLG :c:type:`v4l2_xfer_func`
 
 # Documented enum v4l2_ycbcr_encoding
 replace symbol V4L2_YCBCR_ENC_601 :c:type:`v4l2_ycbcr_encoding`
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/misc-devices/xilinx_flex.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/misc-devices/xilinx_flex.txt
@@ -0,0 +1,66 @@
+Kernel driver xilinx_flex
+============================
+
+Supported chips:
+Versal SOC
+
+Author:
+	Shubhrajyoti Datta <shubhrajyoti.datta@xilinx.com>
+
+Description
+-----------
+
+Versal uses the Arteris FlexNoC interconnect instead of the ARM NIC. FlexNoC
+provides the capability to integrate performance counters in the interconnect.
+It has configurable probe points to monitor the packet and forwards it to
+observer for logging. It supports read and write transaction counts for
+request and response.
+
+Features:
+---> Run-time programmable selection of packet probe points.
+---> Recording of traffic and link statistics.
+---> Separate read and write response and request count.
+
+SYSFS:
+
+counteridfpd
+	RW - shows the counter number selected for the FPD Flexnoc.
+
+counterfpd_rdreq
+	RO - shows the read request count for the FPD counters.
+
+counterfpdsrc
+	WO - sets the source of the FPD counter.
+
+counterfpd_wrrsp
+	RO - shows the write response count for the FPD counters.
+
+counterfpd_rdrsp
+	RO - shows the read response count for the FPD counters.
+
+counterfpd_wrreq
+	RO - shows the write request count for the FPD counters.
+
+counterfpdport
+	WO - sets the port number selected for the FPD Flexnoc.
+
+counteridlpd
+	RW - shows the counter number selected for the LPD Flexnoc.
+
+counterlpdport
+	WO - sets the port number selected for the LPD Flexnoc.
+
+counterlpd_rdreq
+	RO - shows the read request count for the LPD counters.
+
+counterlpd_wrreq
+	RO - shows the write request count for the LPD counters.
+
+counterlpd_wrrsp
+	RO - shows the write response count for the LPD counters.
+
+counterlpdsrc
+	WO - sets the source of the LPD counter.
+
+counterlpd_rdrsp
+	RO - shows the read response count for the LPD counters.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/misc-devices/xilinx_sdfec.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/misc-devices/xilinx_sdfec.rst
@@ -0,0 +1,291 @@
+.. SPDX-License-Identifier: GPL-2.0+
+====================
+Xilinx SD-FEC Driver
+====================
+
+Overview
+========
+
+This driver supports SD-FEC Integrated Block for Zynq |Ultrascale+ (TM)| RFSoCs.
+
+.. |Ultrascale+ (TM)| unicode:: Ultrascale+ U+2122
+   .. with trademark sign
+
+For a full description of SD-FEC core features, see the `SD-FEC Product Guide (PG256) <https://www.xilinx.com/cgi-bin/docs/ipdoc?c=sd_fec;v=latest;d=pg256-sdfec-integrated-block.pdf>`_
+
+This driver supports the following features:
+
+  - Retrieval of the Integrated Block configuration and status information
+  - Configuration of LDPC codes
+  - Configuration of Turbo decoding
+  - Monitoring errors
+
+Missing features, known issues, and limitations of the SD-FEC driver are as
+follows:
+
+  - Only allows a single open file handler to any instance of the driver at any time
+  - Reset of the SD-FEC Integrated Block is not controlled by this driver
+  - Does not support shared LDPC code table wraparound
+
+The device tree entry is described in:
+`linux-xlnx/Documentation/devicetree/bindings/misc/xlnx,sd-fec.txt <https://github.com/Xilinx/linux-xlnx/blob/master/Documentation/devicetree/bindings/misc/xlnx%2Csd-fec.txt>`_
+
+
+Modes of Operation
+------------------
+
+The driver works with the SD-FEC core in two modes of operation:
+
+  - Run-time configuration
+  - Programmable Logic (PL) initialization
+
+
+Run-time Configuration
+~~~~~~~~~~~~~~~~~~~~~~
+
+For Run-time configuration the role of driver is to allow the software application to do the following:
+
+	- Load the configuration parameters for either Turbo decode or LDPC encode or decode
+	- Activate the SD-FEC core
+	- Monitor the SD-FEC core for errors
+	- Retrieve the status and configuration of the SD-FEC core
+
+Programmable Logic (PL) Initialization
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+For PL initialization, supporting logic loads configuration parameters for either
+the Turbo decode or LDPC encode or decode.  The role of the driver is to allow
+the software application to do the following:
+
+	- Activate the SD-FEC core
+	- Monitor the SD-FEC core for errors
+	- Retrieve the status and configuration of the SD-FEC core
+
+
+Driver Structure
+================
+
+The driver provides a platform device where the ``probe`` and ``remove``
+operations are provided.
+
+  - probe: Updates configuration register with device-tree entries plus determines the current activate state of the core, for example, is the core bypassed or has the core been started.
+
+
+The driver defines the following driver file operations to provide user
+application interfaces:
+
+  - open: Implements restriction that only a single file descriptor can be open per SD-FEC instance at any time
+  - release: Allows another file descriptor to be open, that is after current file descriptor is closed
+  - poll: Provides a method to monitor for SD-FEC Error events
+  - unlocked_ioctl: Provides the the following ioctl commands that allows the application configure the SD-FEC core:
+
+		- :c:macro:`XSDFEC_START_DEV`
+		- :c:macro:`XSDFEC_STOP_DEV`
+		- :c:macro:`XSDFEC_GET_STATUS`
+		- :c:macro:`XSDFEC_SET_IRQ`
+		- :c:macro:`XSDFEC_SET_TURBO`
+		- :c:macro:`XSDFEC_ADD_LDPC_CODE_PARAMS`
+		- :c:macro:`XSDFEC_GET_CONFIG`
+		- :c:macro:`XSDFEC_SET_ORDER`
+		- :c:macro:`XSDFEC_SET_BYPASS`
+		- :c:macro:`XSDFEC_IS_ACTIVE`
+		- :c:macro:`XSDFEC_CLEAR_STATS`
+		- :c:macro:`XSDFEC_SET_DEFAULT_CONFIG`
+
+
+Driver Usage
+============
+
+
+Overview
+--------
+
+After opening the driver, the user should find out what operations need to be
+performed to configure and activate the SD-FEC core and determine the
+configuration of the driver.
+The following outlines the flow the user should perform:
+
+  - Determine Configuration
+  - Set the order, if not already configured as desired
+  - Set Turbo decode, LPDC encode or decode parameters, depending on how the
+    SD-FEC core is configured plus if the SD-FEC has not been configured for PL
+    initialization
+  - Enable interrupts, if not already enabled
+  - Bypass the SD-FEC core, if required
+  - Start the SD-FEC core if not already started
+  - Get the SD-FEC core status
+  - Monitor for interrupts
+  - Stop the SD-FEC core
+
+
+Note: When monitoring for interrupts if a critical error is detected where a reset is required, the driver will be required to load the default configuration.
+
+
+Determine Configuration
+-----------------------
+
+Determine the configuration of the SD-FEC core by using the ioctl
+:c:macro:`XSDFEC_GET_CONFIG`.
+
+Set the Order
+-------------
+
+Setting the order determines how the order of Blocks can change from input to output.
+
+Setting the order is done by using the ioctl :c:macro:`XSDFEC_SET_ORDER`
+
+Setting the order can only be done if the following restrictions are met:
+
+	- The ``state`` member of struct :c:type:`xsdfec_status <xsdfec_status>` filled by the ioctl :c:macro:`XSDFEC_GET_STATUS` indicates the SD-FEC core has not STARTED
+
+
+Add LDPC Codes
+--------------
+
+The following steps indicate how to add LDPC codes to the SD-FEC core:
+
+	- Use the auto-generated parameters to fill the :c:type:`struct xsdfec_ldpc_params <xsdfec_ldpc_params>` for the desired LDPC code.
+	- Set the SC, QA, and LA table offsets for the LPDC parameters and the parameters in the structure :c:type:`struct xsdfec_ldpc_params <xsdfec_ldpc_params>`
+	- Set the desired Code Id value in the structure :c:type:`struct xsdfec_ldpc_params <xsdfec_ldpc_params>`
+	- Add the LPDC Code Parameters using the ioctl :c:macro:`XSDFEC_ADD_LDPC_CODE_PARAMS`
+	- For the applied LPDC Code Parameter use the function :c:func:`xsdfec_calculate_shared_ldpc_table_entry_size` to calculate the size of shared LPDC code tables. This allows the user to determine the shared table usage so when selecting the table offsets for the next LDPC code parameters unused table areas can be selected.
+	- Repeat for each LDPC code parameter.
+
+Adding LDPC codes can only be done if the following restrictions are met:
+
+	- The ``code`` member of :c:type:`struct xsdfec_config <xsdfec_config>` filled by the ioctl :c:macro:`XSDFEC_GET_CONFIG` indicates the SD-FEC core is configured as LDPC
+	- The ``code_wr_protect`` of :c:type:`struct xsdfec_config <xsdfec_config>` filled by the ioctl :c:macro:`XSDFEC_GET_CONFIG` indicates that write protection is not enabled
+	- The ``state`` member of struct :c:type:`xsdfec_status <xsdfec_status>` filled by the ioctl :c:macro:`XSDFEC_GET_STATUS` indicates the SD-FEC core has not started
+
+Set Turbo Decode
+----------------
+
+Configuring the Turbo decode parameters is done by using the ioctl :c:macro:`XSDFEC_SET_TURBO` using auto-generated parameters to fill the :c:type:`struct xsdfec_turbo <xsdfec_turbo>` for the desired Turbo code.
+
+Adding Turbo decode can only be done if the following restrictions are met:
+
+	- The ``code`` member of :c:type:`struct xsdfec_config <xsdfec_config>` filled by the ioctl :c:macro:`XSDFEC_GET_CONFIG` indicates the SD-FEC core is configured as TURBO
+	- The ``state`` member of struct :c:type:`xsdfec_status <xsdfec_status>` filled by the ioctl :c:macro:`XSDFEC_GET_STATUS` indicates the SD-FEC core has not STARTED
+
+Enable Interrupts
+-----------------
+
+Enabling or disabling interrupts is done by using the ioctl :c:macro:`XSDFEC_SET_IRQ`. The members of the parameter passed, :c:type:`struct xsdfec_irq <xsdfec_irq>`, to the ioctl are used to set and clear different categories of interrupts. The category of interrupt is controlled as following:
+
+  - ``enable_isr`` controls the ``tlast`` interrupts
+  - ``enable_ecc_isr`` controls the ECC interrupts
+
+If the ``code`` member of :c:type:`struct xsdfec_config <xsdfec_config>` filled by the ioctl :c:macro:`XSDFEC_GET_CONFIG` indicates the SD-FEC core is configured as TURBO then the enabling ECC errors is not required.
+
+Bypass the SD-FEC
+-----------------
+
+Bypassing the SD-FEC is done by using the ioctl :c:macro:`XSDFEC_SET_BYPASS`
+
+Bypassing the SD-FEC can only be done if the following restrictions are met:
+
+	- The ``state`` member of :c:type:`struct xsdfec_status <xsdfec_status>` filled by the ioctl :c:macro:`XSDFEC_GET_STATUS` indicates the SD-FEC core has not STARTED
+
+Start the SD-FEC core
+---------------------
+
+Start the SD-FEC core by using the ioctl :c:macro:`XSDFEC_START_DEV`
+
+Get SD-FEC Status
+-----------------
+
+Get the SD-FEC status of the device by using the ioctl :c:macro:`XSDFEC_GET_STATUS`, which will fill the :c:type:`struct xsdfec_status <xsdfec_status>`
+
+Monitor for Interrupts
+----------------------
+
+	- Use the poll system call to monitor for an interrupt. The poll system call waits for an interrupt to wake it up or times out if no interrupt occurs.
+	- On return Poll ``revents`` will indicate whether stats and/or state have been updated
+		- ``POLLPRI`` indicates a critical error and the user should use :c:macro:`XSDFEC_GET_STATUS` and :c:macro:`XSDFEC_GET_STATS` to confirm
+		- ``POLLRDNORM`` indicates a non-critical error has occurred and the user should use  :c:macro:`XSDFEC_GET_STATS` to confirm
+	- Get stats by using the ioctl :c:macro:`XSDFEC_GET_STATS`
+		- For critical error the ``isr_err_count`` or ``uecc_count`` member  of :c:type:`struct xsdfec_stats <xsdfec_stats>` is non-zero
+		- For non-critical errors the ``cecc_count`` member of :c:type:`struct xsdfec_stats <xsdfec_stats>` is non-zero
+	- Get state by using the ioctl :c:macro:`XSDFEC_GET_STATUS`
+		- For a critical error the ``state`` of :c:type:`xsdfec_status <xsdfec_status>` will indicate a Reset Is Required
+	- Clear stats by using the ioctl :c:macro:`XSDFEC_CLEAR_STATS`
+
+If a critical error is detected where a reset is required. The application is required to call the ioctl :c:macro:`XSDFEC_SET_DEFAULT_CONFIG`, after the reset and it is not required to call the ioctl :c:macro:`XSDFEC_STOP_DEV`
+
+Note: Using poll system call prevents busy looping using :c:macro:`XSDFEC_GET_STATS` and :c:macro:`XSDFEC_GET_STATUS`
+
+Stop the SD-FEC Core
+---------------------
+
+Stop the device by using the ioctl :c:macro:`XSDFEC_STOP_DEV`
+
+Set the Default Configuration
+-----------------------------
+
+Load default configuration by using the ioctl :c:macro:`XSDFEC_SET_DEFAULT_CONFIG` to restore the driver.
+
+Limitations
+-----------
+
+Users should not duplicate SD-FEC device file handlers, for example fork() or dup() a process that has a created an SD-FEC file handler.
+
+Driver IOCTLs
+==============
+
+.. c:macro:: XSDFEC_START_DEV
+.. kernel-doc:: include/uapi/misc/xilinx_sdfec.h
+   :doc: XSDFEC_START_DEV
+
+.. c:macro:: XSDFEC_STOP_DEV
+.. kernel-doc:: include/uapi/misc/xilinx_sdfec.h
+   :doc: XSDFEC_STOP_DEV
+
+.. c:macro:: XSDFEC_GET_STATUS
+.. kernel-doc:: include/uapi/misc/xilinx_sdfec.h
+   :doc: XSDFEC_GET_STATUS
+
+.. c:macro:: XSDFEC_SET_IRQ
+.. kernel-doc:: include/uapi/misc/xilinx_sdfec.h
+   :doc: XSDFEC_SET_IRQ
+
+.. c:macro:: XSDFEC_SET_TURBO
+.. kernel-doc:: include/uapi/misc/xilinx_sdfec.h
+   :doc: XSDFEC_SET_TURBO
+
+.. c:macro:: XSDFEC_ADD_LDPC_CODE_PARAMS
+.. kernel-doc:: include/uapi/misc/xilinx_sdfec.h
+   :doc: XSDFEC_ADD_LDPC_CODE_PARAMS
+
+.. c:macro:: XSDFEC_GET_CONFIG
+.. kernel-doc:: include/uapi/misc/xilinx_sdfec.h
+   :doc: XSDFEC_GET_CONFIG
+
+.. c:macro:: XSDFEC_SET_ORDER
+.. kernel-doc:: include/uapi/misc/xilinx_sdfec.h
+   :doc: XSDFEC_SET_ORDER
+
+.. c:macro:: XSDFEC_SET_BYPASS
+.. kernel-doc:: include/uapi/misc/xilinx_sdfec.h
+   :doc: XSDFEC_SET_BYPASS
+
+.. c:macro:: XSDFEC_IS_ACTIVE
+.. kernel-doc:: include/uapi/misc/xilinx_sdfec.h
+   :doc: XSDFEC_IS_ACTIVE
+
+.. c:macro:: XSDFEC_CLEAR_STATS
+.. kernel-doc:: include/uapi/misc/xilinx_sdfec.h
+   :doc: XSDFEC_CLEAR_STATS
+
+.. c:macro:: XSDFEC_GET_STATS
+.. kernel-doc:: include/uapi/misc/xilinx_sdfec.h
+   :doc: XSDFEC_GET_STATS
+
+.. c:macro:: XSDFEC_SET_DEFAULT_CONFIG
+.. kernel-doc:: include/uapi/misc/xilinx_sdfec.h
+   :doc: XSDFEC_SET_DEFAULT_CONFIG
+
+Driver Type Definitions
+=======================
+
+.. kernel-doc:: include/uapi/misc/xilinx_sdfec.h
+   :internal:
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/misc-devices/xilinx_trafgen.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/misc-devices/xilinx_trafgen.txt
@@ -0,0 +1,97 @@
+Kernel driver xilinx_trafgen
+============================
+
+Supported chips:
+Zynq SOC, Xilinx 7 series fpga's (Virtex,Kintex,Artix)
+
+Data Sheet:
+	http://www.xilinx.com/support/documentation/ip_documentation/axi_traffic_gen/v2_0/pg125-axi-traffic-gen.pdf
+
+Author:
+        Kedareswara Rao Appana <appanad@xilinx.com>
+
+Description
+-----------
+
+AXI Traffic Generator IP is a core that stresses the AXI4 interconnect and other
+AXI4 peripherals in the system. It generates a wide variety of AXI4 transactions
+based on the core programming.
+
+Features:
+---> Configurable option to generate and accept data according to different
+traffic profiles.
+---> Supports dependent/independent transaction between read/write master port
+with configurable delays.
+---> Programmable repeat count for each transaction with
+constant/increment/random address.
+---> External start/stop to generate traffic without processor intervention.
+---> Generates IP-specific traffic on AXI interface for pre-defined protocols.
+
+SYSFS:
+
+id
+	RO - shows the trafgen id.
+
+resource
+	RO - shows the baseaddress for the trafgen.
+
+master_start_stop
+	RW - monitors the master start logic.
+
+config_slave_status
+	RW - configure and monitors the slave status.
+
+err_sts
+	RW - get the error statistics/clear the errors.
+
+err_en
+	WO - enable the errors.
+
+intr_en
+	WO - enable the interrupts.
+
+last_valid_index
+	RW - gets the last valid index value.
+
+config_sts_show
+	RO - show the config status value.
+
+mram_clear
+	WO - clears the master ram.
+
+cram_clear
+	WO - clears the command ram.
+
+pram_clear
+	WO - clears the parameter ram.
+
+static_enable
+	RO - enables the static mode.
+
+static_burst_len
+	RW - gets/sets the static burst length.
+
+static_transferdone
+	RW - monitors the static transfer done status.
+
+reset_static_transferdone
+	RO - resets the static transferdone bit.
+
+stream_cfg
+	RW - sets the stream configuration parameters like delay.
+
+stream_tktsn
+	RW - TSTRB/TKEEP value for the last beat of the
+transfer set n. N can be 1 to 4.
+
+stream_enable
+	RO - enables the streaming mode.
+
+stream_transferlen
+	RW - get/set the streaming mode transfer length.
+
+stream_transfercnt
+	RW - get/set the streaming mode transfer count.
+
+loop_enable
+	RW - get/set loop enable value.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/networking/af_xdp.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/networking/af_xdp.rst
@@ -40,13 +40,13 @@
 appropriate (malloc, mmap, huge pages, etc). This memory area is then
 registered with the kernel using the new setsockopt XDP_UMEM_REG. The
 UMEM also has two rings: the FILL ring and the COMPLETION ring. The
-fill ring is used by the application to send down addr for the kernel
+FILL ring is used by the application to send down addr for the kernel
 to fill in with RX packet data. References to these frames will then
 appear in the RX ring once each packet has been received. The
-completion ring, on the other hand, contains frame addr that the
+COMPLETION ring, on the other hand, contains frame addr that the
 kernel has transmitted completely and can now be used again by user
 space, for either TX or RX. Thus, the frame addrs appearing in the
-completion ring are addrs that were previously transmitted using the
+COMPLETION ring are addrs that were previously transmitted using the
 TX ring. In summary, the RX and FILL rings are used for the RX path
 and the TX and COMPLETION rings are used for the TX path.
 
@@ -91,11 +91,16 @@
 ========
 
 In order to use an AF_XDP socket, a number of associated objects need
-to be setup.
+to be setup. These objects and their options are explained in the
+following sections.
 
-Jonathan Corbet has also written an excellent article on LWN,
-"Accelerating networking with AF_XDP". It can be found at
-https://lwn.net/Articles/750845/.
+For an overview on how AF_XDP works, you can also take a look at the
+Linux Plumbers paper from 2018 on the subject:
+http://vger.kernel.org/lpc_net2018_talks/lpc18_paper_af_xdp_perf-v2.pdf. Do
+NOT consult the paper from 2017 on "AF_PACKET v4", the first attempt
+at AF_XDP. Nearly everything changed since then. Jonathan Corbet has
+also written an excellent article on LWN, "Accelerating networking
+with AF_XDP". It can be found at https://lwn.net/Articles/750845/.
 
 UMEM
 ----
@@ -113,22 +118,22 @@
 struct sockaddr_xdp member sxdp_flags, and passing the file descriptor
 of A to struct sockaddr_xdp member sxdp_shared_umem_fd.
 
-The UMEM has two single-producer/single-consumer rings, that are used
+The UMEM has two single-producer/single-consumer rings that are used
 to transfer ownership of UMEM frames between the kernel and the
 user-space application.
 
 Rings
 -----
 
-There are a four different kind of rings: Fill, Completion, RX and
+There are a four different kind of rings: FILL, COMPLETION, RX and
 TX. All rings are single-producer/single-consumer, so the user-space
 application need explicit synchronization of multiple
 processes/threads are reading/writing to them.
 
-The UMEM uses two rings: Fill and Completion. Each socket associated
+The UMEM uses two rings: FILL and COMPLETION. Each socket associated
 with the UMEM must have an RX queue, TX queue or both. Say, that there
 is a setup with four sockets (all doing TX and RX). Then there will be
-one Fill ring, one Completion ring, four TX rings and four RX rings.
+one FILL ring, one COMPLETION ring, four TX rings and four RX rings.
 
 The rings are head(producer)/tail(consumer) based rings. A producer
 writes the data ring at the index pointed out by struct xdp_ring
@@ -146,7 +151,7 @@
 UMEM Fill Ring
 ~~~~~~~~~~~~~~
 
-The Fill ring is used to transfer ownership of UMEM frames from
+The FILL ring is used to transfer ownership of UMEM frames from
 user-space to kernel-space. The UMEM addrs are passed in the ring. As
 an example, if the UMEM is 64k and each chunk is 4k, then the UMEM has
 16 chunks and can pass addrs between 0 and 64k.
@@ -164,8 +169,8 @@
 UMEM Completion Ring
 ~~~~~~~~~~~~~~~~~~~~
 
-The Completion Ring is used transfer ownership of UMEM frames from
-kernel-space to user-space. Just like the Fill ring, UMEM indicies are
+The COMPLETION Ring is used transfer ownership of UMEM frames from
+kernel-space to user-space. Just like the FILL ring, UMEM indices are
 used.
 
 Frames passed from the kernel to user-space are frames that has been
@@ -181,7 +186,7 @@
 is a struct xdp_desc descriptor. The descriptor contains UMEM offset
 (addr) and the length of the data (len).
 
-If no frames have been passed to kernel via the Fill ring, no
+If no frames have been passed to kernel via the FILL ring, no
 descriptors will (or can) appear on the RX ring.
 
 The user application consumes struct xdp_desc descriptors from this
@@ -199,8 +204,24 @@
 The user application produces struct xdp_desc descriptors to this
 ring.
 
+Libbpf
+======
+
+Libbpf is a helper library for eBPF and XDP that makes using these
+technologies a lot simpler. It also contains specific helper functions
+in tools/lib/bpf/xsk.h for facilitating the use of AF_XDP. It
+contains two types of functions: those that can be used to make the
+setup of AF_XDP socket easier and ones that can be used in the data
+plane to access the rings safely and quickly. To see an example on how
+to use this API, please take a look at the sample application in
+samples/bpf/xdpsock_usr.c which uses libbpf for both setup and data
+plane operations.
+
+We recommend that you use this library unless you have become a power
+user. It will make your program a lot simpler.
+
 XSKMAP / BPF_MAP_TYPE_XSKMAP
-----------------------------
+============================
 
 On XDP side there is a BPF map type BPF_MAP_TYPE_XSKMAP (XSKMAP) that
 is used in conjunction with bpf_redirect_map() to pass the ingress
@@ -216,21 +237,193 @@
 successfully pass data to the socket. Please refer to the sample
 application (samples/bpf/) in for an example.
 
+Configuration Flags and Socket Options
+======================================
+
+These are the various configuration flags that can be used to control
+and monitor the behavior of AF_XDP sockets.
+
+XDP_COPY and XDP_ZERO_COPY bind flags
+-------------------------------------
+
+When you bind to a socket, the kernel will first try to use zero-copy
+copy. If zero-copy is not supported, it will fall back on using copy
+mode, i.e. copying all packets out to user space. But if you would
+like to force a certain mode, you can use the following flags. If you
+pass the XDP_COPY flag to the bind call, the kernel will force the
+socket into copy mode. If it cannot use copy mode, the bind call will
+fail with an error. Conversely, the XDP_ZERO_COPY flag will force the
+socket into zero-copy mode or fail.
+
+XDP_SHARED_UMEM bind flag
+-------------------------
+
+This flag enables you to bind multiple sockets to the same UMEM, but
+only if they share the same queue id. In this mode, each socket has
+their own RX and TX rings, but the UMEM (tied to the fist socket
+created) only has a single FILL ring and a single COMPLETION
+ring. To use this mode, create the first socket and bind it in the normal
+way. Create a second socket and create an RX and a TX ring, or at
+least one of them, but no FILL or COMPLETION rings as the ones from
+the first socket will be used. In the bind call, set he
+XDP_SHARED_UMEM option and provide the initial socket's fd in the
+sxdp_shared_umem_fd field. You can attach an arbitrary number of extra
+sockets this way.
+
+What socket will then a packet arrive on? This is decided by the XDP
+program. Put all the sockets in the XSK_MAP and just indicate which
+index in the array you would like to send each packet to. A simple
+round-robin example of distributing packets is shown below:
+
+.. code-block:: c
+
+   #include <linux/bpf.h>
+   #include "bpf_helpers.h"
+
+   #define MAX_SOCKS 16
+
+   struct {
+        __uint(type, BPF_MAP_TYPE_XSKMAP);
+        __uint(max_entries, MAX_SOCKS);
+        __uint(key_size, sizeof(int));
+        __uint(value_size, sizeof(int));
+   } xsks_map SEC(".maps");
+
+   static unsigned int rr;
+
+   SEC("xdp_sock") int xdp_sock_prog(struct xdp_md *ctx)
+   {
+	rr = (rr + 1) & (MAX_SOCKS - 1);
+
+	return bpf_redirect_map(&xsks_map, rr, 0);
+   }
+
+Note, that since there is only a single set of FILL and COMPLETION
+rings, and they are single producer, single consumer rings, you need
+to make sure that multiple processes or threads do not use these rings
+concurrently. There are no synchronization primitives in the
+libbpf code that protects multiple users at this point in time.
+
+XDP_USE_NEED_WAKEUP bind flag
+-----------------------------
+
+This option adds support for a new flag called need_wakeup that is
+present in the FILL ring and the TX ring, the rings for which user
+space is a producer. When this option is set in the bind call, the
+need_wakeup flag will be set if the kernel needs to be explicitly
+woken up by a syscall to continue processing packets. If the flag is
+zero, no syscall is needed.
+
+If the flag is set on the FILL ring, the application needs to call
+poll() to be able to continue to receive packets on the RX ring. This
+can happen, for example, when the kernel has detected that there are no
+more buffers on the FILL ring and no buffers left on the RX HW ring of
+the NIC. In this case, interrupts are turned off as the NIC cannot
+receive any packets (as there are no buffers to put them in), and the
+need_wakeup flag is set so that user space can put buffers on the
+FILL ring and then call poll() so that the kernel driver can put these
+buffers on the HW ring and start to receive packets.
+
+If the flag is set for the TX ring, it means that the application
+needs to explicitly notify the kernel to send any packets put on the
+TX ring. This can be accomplished either by a poll() call, as in the
+RX path, or by calling sendto().
+
+An example of how to use this flag can be found in
+samples/bpf/xdpsock_user.c. An example with the use of libbpf helpers
+would look like this for the TX path:
+
+.. code-block:: c
+
+   if (xsk_ring_prod__needs_wakeup(&my_tx_ring))
+      sendto(xsk_socket__fd(xsk_handle), NULL, 0, MSG_DONTWAIT, NULL, 0);
+
+I.e., only use the syscall if the flag is set.
+
+We recommend that you always enable this mode as it usually leads to
+better performance especially if you run the application and the
+driver on the same core, but also if you use different cores for the
+application and the kernel driver, as it reduces the number of
+syscalls needed for the TX path.
+
+XDP_{RX|TX|UMEM_FILL|UMEM_COMPLETION}_RING setsockopts
+------------------------------------------------------
+
+These setsockopts sets the number of descriptors that the RX, TX,
+FILL, and COMPLETION rings respectively should have. It is mandatory
+to set the size of at least one of the RX and TX rings. If you set
+both, you will be able to both receive and send traffic from your
+application, but if you only want to do one of them, you can save
+resources by only setting up one of them. Both the FILL ring and the
+COMPLETION ring are mandatory if you have a UMEM tied to your socket,
+which is the normal case. But if the XDP_SHARED_UMEM flag is used, any
+socket after the first one does not have a UMEM and should in that
+case not have any FILL or COMPLETION rings created.
+
+XDP_UMEM_REG setsockopt
+-----------------------
+
+This setsockopt registers a UMEM to a socket. This is the area that
+contain all the buffers that packet can recide in. The call takes a
+pointer to the beginning of this area and the size of it. Moreover, it
+also has parameter called chunk_size that is the size that the UMEM is
+divided into. It can only be 2K or 4K at the moment. If you have an
+UMEM area that is 128K and a chunk size of 2K, this means that you
+will be able to hold a maximum of 128K / 2K = 64 packets in your UMEM
+area and that your largest packet size can be 2K.
+
+There is also an option to set the headroom of each single buffer in
+the UMEM. If you set this to N bytes, it means that the packet will
+start N bytes into the buffer leaving the first N bytes for the
+application to use. The final option is the flags field, but it will
+be dealt with in separate sections for each UMEM flag.
+
+SO_BINDTODEVICE setsockopt
+--------------------------
+
+This is a generic SOL_SOCKET option that can be used to tie AF_XDP
+socket to a particular network interface.  It is useful when a socket
+is created by a privileged process and passed to a non-privileged one.
+Once the option is set, kernel will refuse attempts to bind that socket
+to a different interface.  Updating the value requires CAP_NET_RAW.
+
+XDP_STATISTICS getsockopt
+-------------------------
+
+Gets drop statistics of a socket that can be useful for debug
+purposes. The supported statistics are shown below:
+
+.. code-block:: c
+
+   struct xdp_statistics {
+	  __u64 rx_dropped; /* Dropped for reasons other than invalid desc */
+	  __u64 rx_invalid_descs; /* Dropped due to invalid descriptor */
+	  __u64 tx_invalid_descs; /* Dropped due to invalid descriptor */
+   };
+
+XDP_OPTIONS getsockopt
+----------------------
+
+Gets options from an XDP socket. The only one supported so far is
+XDP_OPTIONS_ZEROCOPY which tells you if zero-copy is on or not.
+
 Usage
 =====
 
-In order to use AF_XDP sockets there are two parts needed. The
+In order to use AF_XDP sockets two parts are needed. The
 user-space application and the XDP program. For a complete setup and
 usage example, please refer to the sample application. The user-space
 side is xdpsock_user.c and the XDP side is part of libbpf.
 
-The XDP code sample included in tools/lib/bpf/xsk.c is the following::
+The XDP code sample included in tools/lib/bpf/xsk.c is the following:
+
+.. code-block:: c
 
    SEC("xdp_sock") int xdp_sock_prog(struct xdp_md *ctx)
    {
        int index = ctx->rx_queue_index;
 
-       // A set entry here means that the correspnding queue_id
+       // A set entry here means that the corresponding queue_id
        // has an active AF_XDP socket bound to it.
        if (bpf_map_lookup_elem(&xsks_map, &index))
            return bpf_redirect_map(&xsks_map, index, 0);
@@ -238,7 +431,10 @@
        return XDP_PASS;
    }
 
-Naive ring dequeue and enqueue could look like this::
+A simple but not so performance ring dequeue and enqueue could look
+like this:
+
+.. code-block:: c
 
     // struct xdp_rxtx_ring {
     // 	__u32 *producer;
@@ -287,17 +483,16 @@
         return 0;
     }
 
-
-For a more optimized version, please refer to the sample application.
+But please use the libbpf functions as they are optimized and ready to
+use. Will make your life easier.
 
 Sample application
 ==================
 
 There is a xdpsock benchmarking/test application included that
-demonstrates how to use AF_XDP sockets with both private and shared
-UMEMs. Say that you would like your UDP traffic from port 4242 to end
-up in queue 16, that we will enable AF_XDP on. Here, we use ethtool
-for this::
+demonstrates how to use AF_XDP sockets with private UMEMs. Say that
+you would like your UDP traffic from port 4242 to end up in queue 16,
+that we will enable AF_XDP on. Here, we use ethtool for this::
 
       ethtool -N p3p2 rx-flow-hash udp4 fn
       ethtool -N p3p2 flow-type udp4 src-port 4242 dst-port 4242 \
@@ -311,13 +506,18 @@
 For XDP_SKB mode, use the switch "-S" instead of "-N" and all options
 can be displayed with "-h", as usual.
 
+This sample application uses libbpf to make the setup and usage of
+AF_XDP simpler. If you want to know how the raw uapi of AF_XDP is
+really used to make something more advanced, take a look at the libbpf
+code in tools/lib/bpf/xsk.[ch].
+
 FAQ
 =======
 
 Q: I am not seeing any traffic on the socket. What am I doing wrong?
 
 A: When a netdev of a physical NIC is initialized, Linux usually
-   allocates one Rx and Tx queue pair per core. So on a 8 core system,
+   allocates one RX and TX queue pair per core. So on a 8 core system,
    queue ids 0 to 7 will be allocated, one per core. In the AF_XDP
    bind call or the xsk_socket__create libbpf function call, you
    specify a specific queue id to bind to and it is only the traffic
@@ -343,9 +543,21 @@
      sudo ethtool -N <interface> flow-type udp4 src-port 4242 dst-port \
      4242 action 2
 
-   A number of other ways are possible all up to the capabilitites of
+   A number of other ways are possible all up to the capabilities of
    the NIC you have.
 
+Q: Can I use the XSKMAP to implement a switch betwen different umems
+   in copy mode?
+
+A: The short answer is no, that is not supported at the moment. The
+   XSKMAP can only be used to switch traffic coming in on queue id X
+   to sockets bound to the same queue id X. The XSKMAP can contain
+   sockets bound to different queue ids, for example X and Y, but only
+   traffic goming in from queue id Y can be directed to sockets bound
+   to the same queue id Y. In zero-copy mode, you should use the
+   switch, or other distribution mechanism, in your NIC to direct
+   traffic to the correct queue id and socket.
+
 Credits
 =======
 
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/networking/bonding.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/networking/bonding.txt
@@ -191,11 +191,12 @@
 ad_actor_system
 
 	In an AD system, this specifies the mac-address for the actor in
-	protocol packet exchanges (LACPDUs). The value cannot be NULL or
-	multicast. It is preferred to have the local-admin bit set for this
-	mac but driver does not enforce it. If the value is not given then
-	system defaults to using the masters' mac address as actors' system
-	address.
+	protocol packet exchanges (LACPDUs). The value cannot be a multicast
+	address. If the all-zeroes MAC is specified, bonding will internally
+	use the MAC of the bond itself. It is preferred to have the
+	local-admin bit set for this mac but driver does not enforce it. If
+	the value is not given then system defaults to using the masters'
+	mac address as actors' system address.
 
 	This parameter has effect only in 802.3ad mode and is available through
 	SysFs interface.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/networking/device_drivers/amazon/ena.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/networking/device_drivers/amazon/ena.txt
@@ -248,7 +248,7 @@
   inputs for hash functions.
 - The driver configures RSS settings using the AQ SetFeature command
   (ENA_ADMIN_RSS_HASH_FUNCTION, ENA_ADMIN_RSS_HASH_INPUT and
-  ENA_ADMIN_RSS_REDIRECTION_TABLE_CONFIG properties).
+  ENA_ADMIN_RSS_INDIRECTION_TABLE_CONFIG properties).
 - If the NETIF_F_RXHASH flag is set, the 32-bit result of the hash
   function delivered in the Rx CQ descriptor is set in the received
   SKB.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/networking/device_drivers/mellanox/mlx5.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/networking/device_drivers/mellanox/mlx5.rst
@@ -154,6 +154,27 @@
       values:
          cmode runtime value smfs
 
+enable_roce: RoCE enablement state
+----------------------------------
+RoCE enablement state controls driver support for RoCE traffic.
+When RoCE is disabled, there is no gid table, only raw ethernet QPs are supported and traffic on the well known UDP RoCE port is handled as raw ethernet traffic.
+
+To change RoCE enablement state a user must change the driverinit cmode value and run devlink reload.
+
+User command examples:
+
+- Disable RoCE::
+
+    $ devlink dev param set pci/0000:06:00.0 name enable_roce value false cmode driverinit
+    $ devlink dev reload pci/0000:06:00.0
+
+- Read RoCE enablement state::
+
+    $ devlink dev param show pci/0000:06:00.0 name enable_roce
+      pci/0000:06:00.0:
+      name enable_roce type generic
+      values:
+         cmode driverinit value true
 
 Devlink health reporters
 ========================
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/networking/devlink-params-mlx5.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/networking/devlink-params-mlx5.txt
@@ -0,0 +1,17 @@
+flow_steering_mode	[DEVICE, DRIVER-SPECIFIC]
+			Controls the flow steering mode of the driver.
+			Two modes are supported:
+			1. 'dmfs' - Device managed flow steering.
+			2. 'smfs  - Software/Driver managed flow steering.
+			In DMFS mode, the HW steering entities are created and
+			managed through the Firmware.
+			In SMFS mode, the HW steering entities are created and
+			managed though by the driver directly into Hardware
+			without firmware intervention.
+			Type: String
+			Configuration mode: runtime
+
+enable_roce		[DEVICE, GENERIC]
+			Enable handling of RoCE traffic in the device.
+			Defaultly enabled.
+			Configuration mode: driverinit
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/networking/devlink-params.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/networking/devlink-params.txt
@@ -65,3 +65,7 @@
 			  Reset only if device firmware can be found in the
 			  filesystem.
 			Type: u8
+
+enable_roce		[DEVICE, GENERIC]
+			Enable handling of RoCE traffic in the device.
+			Type: Boolean
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/networking/ip-sysctl.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/networking/ip-sysctl.txt
@@ -876,7 +876,7 @@
 cipso_cache_bucket_size - INTEGER
 	The CIPSO label cache consists of a fixed size hash table with each
 	hash bucket containing a number of cache entries.  This variable limits
-	the number of entries in each hash bucket; the larger the value the
+	the number of entries in each hash bucket; the larger the value is, the
 	more CIPSO label mappings that can be cached.  When the number of
 	entries in a given hash bucket reaches this limit adding new entries
 	causes the oldest entry in the bucket to be removed to make room.
@@ -953,7 +953,7 @@
 	which can be quite useful - but may break some applications.
 	Default: 0
 
-ip_dynaddr - BOOLEAN
+ip_dynaddr - INTEGER
 	If set non-zero, enables support for dynamic addresses.
 	If set to a non-zero value larger than 1, a kernel log
 	message will be printed when dynamic address rewriting
@@ -1000,12 +1000,14 @@
 icmp_msgs_per_sec - INTEGER
 	Limit maximal number of ICMP packets sent per second from this host.
 	Only messages whose type matches icmp_ratemask (see below) are
-	controlled by this limit.
+	controlled by this limit. For security reasons, the precise count
+	of messages per second is randomized.
 	Default: 1000
 
 icmp_msgs_burst - INTEGER
 	icmp_msgs_per_sec controls number of ICMP packets sent per second,
 	while icmp_msgs_burst controls the burst size of these packets.
+	For security reasons, the precise burst size is randomized.
 	Default: 50
 
 icmp_ratemask - INTEGER
@@ -2282,7 +2284,14 @@
 	Default: 4K
 
 sctp_wmem  - vector of 3 INTEGERs: min, default, max
-	Currently this tunable has no effect.
+	Only the first value ("min") is used, "default" and "max" are
+	ignored.
+
+	min: Minimum size of send buffer that can be used by SCTP sockets.
+	It is guaranteed to each SCTP socket (but not association) even
+	under moderate memory pressure.
+
+	Default: 4K
 
 addr_scope_policy - INTEGER
 	Control IPv4 address scoping - draft-stewart-tsvwg-sctp-ipv4-00
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/networking/ipvs-sysctl.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/networking/ipvs-sysctl.txt
@@ -30,8 +30,7 @@
 
 	0: disable any special handling on port reuse. The new
 	connection will be delivered to the same real server that was
-	servicing the previous connection. This will effectively
-	disable expire_nodest_conn.
+	servicing the previous connection.
 
 	bit 1: enable rescheduling of new connections when it is safe.
 	That is, whenever expire_nodest_conn and for TCP sockets, when
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/networking/j1939.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/networking/j1939.rst
@@ -339,7 +339,7 @@
 			.pgn = J1939_PGN_ADDRESS_CLAIMED,
 			.pgn_mask = J1939_PGN_PDU1_MAX,
 		}, {
-			.pgn = J1939_PGN_ADDRESS_REQUEST,
+			.pgn = J1939_PGN_REQUEST,
 			.pgn_mask = J1939_PGN_PDU1_MAX,
 		}, {
 			.pgn = J1939_PGN_ADDRESS_COMMANDED,
@@ -414,8 +414,8 @@
 		.can_family = AF_CAN,
 		.can_addr.j1939 = {
 			.name = J1939_NO_NAME;
-			.pgn = 0x30,
-			.addr = 0x12300,
+			.addr = 0x30,
+			.pgn = 0x12300,
 		},
 	};
 
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/networking/nf_flowtable.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/networking/nf_flowtable.txt
@@ -76,7 +76,7 @@
 
         table inet x {
 		flowtable f {
-			hook ingress priority 0 devices = { eth0, eth1 };
+			hook ingress priority 0; devices = { eth0, eth1 };
 		}
                 chain y {
                         type filter hook forward priority 0; policy accept;
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/power/runtime_pm.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/power/runtime_pm.rst
@@ -382,6 +382,12 @@
       nonzero, increment the counter and return 1; otherwise return 0 without
       changing the counter
 
+  `int pm_runtime_get_if_active(struct device *dev, bool ign_usage_count);`
+    - return -EINVAL if 'power.disable_depth' is nonzero; otherwise, if the
+      runtime PM status is RPM_ACTIVE, and either ign_usage_count is true
+      or the device's usage_count is non-zero, increment the counter and
+      return 1; otherwise return 0 without changing the counter
+
   `void pm_runtime_put_noidle(struct device *dev);`
     - decrement the device's usage counter
 
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/process/code-of-conduct-interpretation.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/process/code-of-conduct-interpretation.rst
@@ -51,7 +51,7 @@
 uncertain how to handle situations that come up.  It will not be
 considered a violation report unless you want it to be.  If you are
 uncertain about approaching the TAB or any other maintainers, please
-reach out to our conflict mediator, Mishi Choudhary <mishi@linux.com>.
+reach out to our conflict mediator, Joanna Lee <jlee@linuxfoundation.org>.
 
 In the end, "be kind to each other" is really what the end goal is for
 everybody.  We know everyone is human and we all fail at times, but the
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/process/deprecated.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/process/deprecated.rst
@@ -48,6 +48,9 @@
 
 	foo = kmalloc_array(count, size, GFP_KERNEL);
 
+Specifically, kmalloc() can be replaced with kmalloc_array(), and
+kzalloc() can be replaced with kcalloc().
+
 If no 2-factor form is available, the saturate-on-overflow helpers should
 be used::
 
@@ -63,9 +66,20 @@
 
 	header = kzalloc(struct_size(header, item, count), GFP_KERNEL);
 
-See :c:func:`array_size`, :c:func:`array3_size`, and :c:func:`struct_size`,
-for more details as well as the related :c:func:`check_add_overflow` and
-:c:func:`check_mul_overflow` family of functions.
+For other calculations, please compose the use of the size_mul(),
+size_add(), and size_sub() helpers. For example, in the case of::
+
+	foo = krealloc(current_size + chunk_size * (count - 3), GFP_KERNEL);
+
+Instead, use the helpers::
+
+	foo = krealloc(size_add(current_size,
+				size_mul(chunk_size,
+					 size_sub(count, 3))), GFP_KERNEL);
+
+For more details, also see array3_size() and flex_array_size(),
+as well as the related check_mul_overflow(), check_add_overflow(),
+check_sub_overflow(), and check_shl_overflow() family of functions.
 
 simple_strtol(), simple_strtoll(), simple_strtoul(), simple_strtoull()
 ----------------------------------------------------------------------
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/process/stable-kernel-rules.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/process/stable-kernel-rules.rst
@@ -174,7 +174,16 @@
  - The finalized and tagged releases of all stable kernels can be found
    in separate branches per version at:
 
-	https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git
+	https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
+
+ - The release candidate of all stable kernel versions can be found at:
+
+        https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git/
+
+   .. warning::
+      The -stable-rc tree is a snapshot in time of the stable-queue tree and
+      will change frequently, hence will be rebased often. It should only be
+      used for testing purposes (e.g. to be consumed by CI systems).
 
 
 Review committee
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/process/submitting-patches.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/process/submitting-patches.rst
@@ -133,7 +133,7 @@
 
 The maintainer will thank you if you write your patch description in a
 form which can be easily pulled into Linux's source code management
-system, ``git``, as a "commit log".  See :ref:`explicit_in_reply_to`.
+system, ``git``, as a "commit log".  See :ref:`the_canonical_patch_format`.
 
 Solve only one problem per patch.  If your description starts to get
 long, that's a sign that you probably need to split up your patch.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/s390/index.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/s390/index.rst
@@ -15,6 +15,7 @@
     vfio-ccw
     zfcpdump
     common_io
+    pci
 
     text_files
 
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/s390/pci.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/s390/pci.rst
@@ -0,0 +1,126 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=========
+S/390 PCI
+=========
+
+Authors:
+        - Pierre Morel
+
+Copyright, IBM Corp. 2020
+
+
+command line parameters and debugfs entries
+===========================================
+
+Command line parameters
+-----------------------
+
+* nomio
+
+  Do not use MIO instructions.
+
+* norid
+
+  Ignore the RID field and force use of one PCI domain per PCI function.
+
+debugfs entries
+---------------
+
+* /sys/kernel/debug/s390dbf/pci_*/ (S/390 debug feature)
+
+  Some views generated by the debug feature to hold various debug outputs.
+
+  - /sys/kernel/debug/s390dbf/pci_msg/sprintf
+    Messages from the processing of PCI events like machine check handling
+    and setting of global functionality like UID checking.
+
+  The level of logging can be changed to be more or less verbose by piping to
+  /sys/kernel/debug/s390dbf/pci_*/level a number between 0 and 6; see the
+  documentation on the S/390 debug feature (Documentation/s390/s390dbf.rst)
+  for details.
+
+Sysfs entries
+=============
+
+Specific entries, or entries specificities for zPCI functions.
+
+* /sys/bus/pci/slots/XXXXXXXX
+
+  The slot entries are setup using the FID (Function Identifier) of the
+  PCI function.
+
+  - /sys/bus/pci/slots/XXXXXXXX/power
+
+  A physical function currently supporting virtual function can not be
+  powered-off until all virtual-function have been removed with
+  echo 0 > /sys/bus/pci/devices/XXXX:XX:XX.X/sriov_numvf
+
+* /sys/bus/pci/devices/XXXX:XX:XX.X/
+
+  - function_id
+    zPCI function identifier unique for the complete Z System.
+    It define uniquely a function in the system.
+
+  - function_handle
+    Low level identifier used for a configured PCI function.
+    It may be useful for debuging.
+
+  - pchid
+    Model dependent location of the I/O adapter.
+
+  - pfgid
+    PCI Function Group ID, functions sharing identical functionality
+    are using a common identifier.
+    A PCI group defines interrupts, IOMMU, IOTLB and DMA specifics.
+
+  - vfn
+    The Virtual Function Number, from 1 to N for virtual functions.
+    0 for physical functions.
+
+  - pft
+    PCI function type specifies the type of the PCI function.
+
+  - port
+    The port correspond to the physical port the function is attached to.
+    It also gives an indication on the physical function a virtual function
+    is attached to.
+
+  - uid
+    The UID, Unique Identifier is defined when configuring a LPAR and is
+    unique inside an LPAR.
+
+  - pfip/segmentX
+    The segments are used to determine the isolation of a function.
+    They corresponds to the physical path to the function.
+    The more the segment are different the more the functions are isolated.
+
+Enumeration and hotplug
+=======================
+
+The PCI address is made of 4 parts: domain, bus, device and function,
+like in DDDD:BB:dd.f
+
+* When not using multi-functions (norid is set or firmware does not support
+  multi-functions)
+
+  - There is only one function per domain.
+
+  - the domain is set from the zPCI function's UID as defined during the
+    LPAR creation.
+
+  - Addresses look like DDDD:00:00.0
+
+* When using multi-functions (norid parameter is not set), there are some
+  change in the way zPCI functions are addressed:
+
+  - There is still only one bus per domain.
+
+  - There can be up to 256 functions per bus.
+
+  - The domain part of the address of all functions of all functions for
+    a multi-Function device is set from the zPCI function's UID as defined
+    in the LPAR creation for the function zero.
+
+  - New functions will only be ready to be used after the function zero
+    (the function with devfn 0) has been enumerated.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/scsi/smartpqi.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/scsi/smartpqi.txt
@@ -29,7 +29,7 @@
   smartpqi host attributes:
   -------------------------
   /sys/class/scsi_host/host*/rescan
-  /sys/class/scsi_host/host*/version
+  /sys/class/scsi_host/host*/driver_version
 
   The host rescan attribute is a write only attribute. Writing to this
   attribute will trigger the driver to scan for new, changed, or removed
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/sound/hd-audio/index.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/sound/hd-audio/index.rst
@@ -8,3 +8,4 @@
    models
    controls
    dp-mst
+   realtek-pc-beep
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/sound/hd-audio/models.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/sound/hd-audio/models.rst
@@ -216,8 +216,6 @@
     ALC298 fixups on Dell AIO machines
 alc275-dell-xps
     ALC275 fixups on Dell XPS models
-alc256-dell-xps13
-    ALC256 fixups on Dell XPS13
 lenovo-spk-noise
     Workaround for speaker noise on Lenovo machines
 lenovo-hotkey
@@ -263,6 +261,10 @@
 huawei-mbx-stereo
     Enable initialization verbs for Huawei MBX stereo speakers;
     might be risky, try this at your own risk
+alc298-samsung-headphone
+    Samsung laptops with ALC298
+alc256-samsung-headphone
+    Samsung laptops with ALC256
 
 ALC66x/67x/892
 ==============
@@ -700,7 +702,7 @@
 no-jd
     BIOS setup but without jack-detection
 intel
-    Intel DG45* mobos
+    Intel D*45* mobos
 dell-m6-amic
     Dell desktops/laptops with analog mics
 dell-m6-dmic
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/sound/hd-audio/realtek-pc-beep.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/sound/hd-audio/realtek-pc-beep.rst
@@ -0,0 +1,129 @@
+===============================
+Realtek PC Beep Hidden Register
+===============================
+
+This file documents the "PC Beep Hidden Register", which is present in certain
+Realtek HDA codecs and controls a muxer and pair of passthrough mixers that can
+route audio between pins but aren't themselves exposed as HDA widgets. As far
+as I can tell, these hidden routes are designed to allow flexible PC Beep output
+for codecs that don't have mixer widgets in their output paths. Why it's easier
+to hide a mixer behind an undocumented vendor register than to just expose it
+as a widget, I have no idea.
+
+Register Description
+====================
+
+The register is accessed via processing coefficient 0x36 on NID 20h. Bits not
+identified below have no discernible effect on my machine, a Dell XPS 13 9350::
+
+  MSB                           LSB
+  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  | |h|S|L|         | B |R|       | Known bits
+  +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+  |0|0|1|1|  0x7  |0|0x0|1|  0x7  | Reset value
+  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+1Ah input select (B): 2 bits
+  When zero, expose the PC Beep line (from the internal beep generator, when
+  enabled with the Set Beep Generation verb on NID 01h, or else from the
+  external PCBEEP pin) on the 1Ah pin node. When nonzero, expose the headphone
+  jack (or possibly Line In on some machines) input instead. If PC Beep is
+  selected, the 1Ah boost control has no effect.
+
+Amplify 1Ah loopback, left (L): 1 bit
+  Amplify the left channel of 1Ah before mixing it into outputs as specified
+  by h and S bits. Does not affect the level of 1Ah exposed to other widgets.
+
+Amplify 1Ah loopback, right (R): 1 bit
+  Amplify the right channel of 1Ah before mixing it into outputs as specified
+  by h and S bits. Does not affect the level of 1Ah exposed to other widgets.
+
+Loopback 1Ah to 21h [active low] (h): 1 bit
+  When zero, mix 1Ah (possibly with amplification, depending on L and R bits)
+  into 21h (headphone jack on my machine). Mixed signal respects the mute
+  setting on 21h.
+
+Loopback 1Ah to 14h (S): 1 bit
+  When one, mix 1Ah (possibly with amplification, depending on L and R bits)
+  into 14h (internal speaker on my machine). Mixed signal **ignores** the mute
+  setting on 14h and is present whenever 14h is configured as an output.
+
+Path diagrams
+=============
+
+1Ah input selection (DIV is the PC Beep divider set on NID 01h)::
+
+  <Beep generator>   <PCBEEP pin>    <Headphone jack>
+          |                |                |
+          +--DIV--+--!DIV--+       {1Ah boost control}
+                  |                         |
+                  +--(b == 0)--+--(b != 0)--+
+                               |
+               >1Ah (Beep/Headphone Mic/Line In)<
+
+Loopback of 1Ah to 21h/14h::
+
+               <1Ah (Beep/Headphone Mic/Line In)>
+                               |
+                        {amplify if L/R}
+                               |
+                  +-----!h-----+-----S-----+
+                  |                        |
+          {21h mute control}               |
+                  |                        |
+          >21h (Headphone)<     >14h (Internal Speaker)<
+
+Background
+==========
+
+All Realtek HDA codecs have a vendor-defined widget with node ID 20h which
+provides access to a bank of registers that control various codec functions.
+Registers are read and written via the standard HDA processing coefficient
+verbs (Set/Get Coefficient Index, Set/Get Processing Coefficient). The node is
+named "Realtek Vendor Registers" in public datasheets' verb listings and,
+apart from that, is entirely undocumented.
+
+This particular register, exposed at coefficient 0x36 and named in commits from
+Realtek, is of note: unlike most registers, which seem to control detailed
+amplifier parameters not in scope of the HDA specification, it controls audio
+routing which could just as easily have been defined using standard HDA mixer
+and selector widgets.
+
+Specifically, it selects between two sources for the input pin widget with Node
+ID (NID) 1Ah: the widget's signal can come either from an audio jack (on my
+laptop, a Dell XPS 13 9350, it's the headphone jack, but comments in Realtek
+commits indicate that it might be a Line In on some machines) or from the PC
+Beep line (which is itself multiplexed between the codec's internal beep
+generator and external PCBEEP pin, depending on if the beep generator is
+enabled via verbs on NID 01h). Additionally, it can mix (with optional
+amplification) that signal onto the 21h and/or 14h output pins.
+
+The register's reset value is 0x3717, corresponding to PC Beep on 1Ah that is
+then amplified and mixed into both the headphones and the speakers. Not only
+does this violate the HDA specification, which says that "[a vendor defined
+beep input pin] connection may be maintained *only* while the Link reset
+(**RST#**) is asserted", it means that we cannot ignore the register if we care
+about the input that 1Ah would otherwise expose or if the PCBEEP trace is
+poorly shielded and picks up chassis noise (both of which are the case on my
+machine).
+
+Unfortunately, there are lots of ways to get this register configuration wrong.
+Linux, it seems, has gone through most of them. For one, the register resets
+after S3 suspend: judging by existing code, this isn't the case for all vendor
+registers, and it's led to some fixes that improve behavior on cold boot but
+don't last after suspend. Other fixes have successfully switched the 1Ah input
+away from PC Beep but have failed to disable both loopback paths. On my
+machine, this means that the headphone input is amplified and looped back to
+the headphone output, which uses the exact same pins! As you might expect, this
+causes terrible headphone noise, the character of which is controlled by the
+1Ah boost control. (If you've seen instructions online to fix XPS 13 headphone
+noise by changing "Headphone Mic Boost" in ALSA, now you know why.)
+
+The information here has been obtained through black-box reverse engineering of
+the ALC256 codec's behavior and is not guaranteed to be correct. It likely
+also applies for the ALC255, ALC257, ALC235, and ALC236, since those codecs
+seem to be close relatives of the ALC256. (They all share one initialization
+function.) Additionally, other codecs like the ALC225 and ALC285 also have this
+register, judging by existing fixups in ``patch_realtek.c``, but specific
+data (e.g. node IDs, bit positions, pin mappings) for those codecs may differ
+from what I've described here.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/sound/soc/dapm.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/sound/soc/dapm.rst
@@ -234,7 +234,7 @@
 a virtual widget - a widget with no control bits e.g.
 ::
 
-  SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_DAPM_NOPM, 0, 0, NULL, 0),
+  SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
 
 This can be used to merge to signal paths together in software.
 
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/sphinx/kernel_include.py
+++ linux-xilinx-zynqmp-5.4.0/Documentation/sphinx/kernel_include.py
@@ -94,7 +94,6 @@
         # HINT: this is the only line I had to change / commented out:
         #path = utils.relative_path(None, path)
 
-        path = nodes.reprunicode(path)
         encoding = self.options.get(
             'encoding', self.state.document.settings.input_encoding)
         e_handler=self.state.document.settings.input_encoding_error_handler
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/sphinx/load_config.py
+++ linux-xilinx-zynqmp-5.4.0/Documentation/sphinx/load_config.py
@@ -3,7 +3,7 @@
 
 import os
 import sys
-from sphinx.util.pycompat import execfile_
+from sphinx.util.osutil import fs_encoding
 
 # ------------------------------------------------------------------------------
 def loadConfig(namespace):
@@ -48,7 +48,9 @@
             sys.stdout.write("load additional sphinx-config: %s\n" % config_file)
             config = namespace.copy()
             config['__file__'] = config_file
-            execfile_(config_file, config)
+            with open(config_file, 'rb') as f:
+                code = compile(f.read(), fs_encoding, 'exec')
+                exec(code, config)
             del config['__file__']
             namespace.update(config)
         else:
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/sphinx/parse-headers.pl
+++ linux-xilinx-zynqmp-5.4.0/Documentation/sphinx/parse-headers.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 use strict;
 use Text::Tabs;
 use Getopt::Long;
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/target/tcm_mod_builder.py
+++ linux-xilinx-zynqmp-5.4.0/Documentation/target/tcm_mod_builder.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
 # The TCM v4 multi-protocol fabric module generation script for drivers/target/$NEW_MOD
 #
 # Copyright (c) 2010 Rising Tide Systems
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/timers/hrtimers.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/timers/hrtimers.rst
@@ -118,7 +118,7 @@
 was not really a win, due to the different data structures. Also, the
 hrtimer functions now have clearer behavior and clearer names - such as
 hrtimer_try_to_cancel() and hrtimer_cancel() [which are roughly
-equivalent to del_timer() and del_timer_sync()] - so there's no direct
+equivalent to timer_delete() and timer_delete_sync()] - so there's no direct
 1:1 mapping between them on the algorithmic level, and thus no real
 potential for code sharing either.
 
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/timers/no_hz.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/timers/no_hz.rst
@@ -129,11 +129,8 @@
 online to handle timekeeping tasks in order to ensure that system
 calls like gettimeofday() returns accurate values on adaptive-tick CPUs.
 (This is not an issue for CONFIG_NO_HZ_IDLE=y because there are no running
-user processes to observe slight drifts in clock rate.)  Therefore, the
-boot CPU is prohibited from entering adaptive-ticks mode.  Specifying a
-"nohz_full=" mask that includes the boot CPU will result in a boot-time
-error message, and the boot CPU will be removed from the mask.  Note that
-this means that your system must have at least two CPUs in order for
+user processes to observe slight drifts in clock rate.) Note that this
+means that your system must have at least two CPUs in order for
 CONFIG_NO_HZ_FULL=y to do anything for you.
 
 Finally, adaptive-ticks CPUs must have their RCU callbacks offloaded.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/trace/histogram.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/trace/histogram.rst
@@ -39,7 +39,7 @@
   will use the event's kernel stacktrace as the key.  The keywords
   'keys' or 'key' can be used to specify keys, and the keywords
   'values', 'vals', or 'val' can be used to specify values.  Compound
-  keys consisting of up to two fields can be specified by the 'keys'
+  keys consisting of up to three fields can be specified by the 'keys'
   keyword.  Hashing a compound key produces a unique entry in the
   table for each unique combination of component keys, and can be
   useful for providing more fine-grained summaries of event data.
@@ -191,7 +191,7 @@
                                 with the event, in nanoseconds.  May be
 			        modified by .usecs to have timestamps
 			        interpreted as microseconds.
-    cpu                    int  the cpu on which the event occurred.
+    common_cpu             int  the cpu on which the event occurred.
     ====================== ==== =======================================
 
 Extended error information
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/trace/postprocess/decode_msr.py
+++ linux-xilinx-zynqmp-5.4.0/Documentation/trace/postprocess/decode_msr.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
 # add symbolic names to read_msr / write_msr in trace
 # decode_msr msr-index.h < trace
 import sys
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/trace/postprocess/trace-pagealloc-postprocess.pl
+++ linux-xilinx-zynqmp-5.4.0/Documentation/trace/postprocess/trace-pagealloc-postprocess.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 # This is a POC (proof of concept or piece of crap, take your pick) for reading the
 # text representation of trace output related to page allocation. It makes an attempt
 # to extract some high-level information on what is going on. The accuracy of the parser
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/trace/postprocess/trace-vmscan-postprocess.pl
+++ linux-xilinx-zynqmp-5.4.0/Documentation/trace/postprocess/trace-vmscan-postprocess.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 # This is a POC for reading the text representation of trace output related to
 # page reclaim. It makes an attempt to extract some high-level information on
 # what is going on. The accuracy of the parser may vary
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/translations/it_IT/kernel-hacking/locking.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/translations/it_IT/kernel-hacking/locking.rst
@@ -998,7 +998,7 @@
 
             while (list) {
                     struct foo *next = list->next;
-                    del_timer(&list->timer);
+                    timer_delete(&list->timer);
                     kfree(list);
                     list = next;
             }
@@ -1011,7 +1011,7 @@
 di eliminare il suo oggetto (che però è già stato eliminato).
 
 Questo può essere evitato controllando il valore di ritorno di
-:c:func:`del_timer()`: se ritorna 1, il temporizzatore è stato già
+:c:func:`timer_delete()`: se ritorna 1, il temporizzatore è stato già
 rimosso. Se 0, significa (in questo caso) che il temporizzatore è in
 esecuzione, quindi possiamo fare come segue::
 
@@ -1020,7 +1020,7 @@
 
                     while (list) {
                             struct foo *next = list->next;
-                            if (!del_timer(&list->timer)) {
+                            if (!timer_delete(&list->timer)) {
                                     /* Give timer a chance to delete this */
                                     spin_unlock_bh(&list_lock);
                                     goto retry;
@@ -1034,10 +1034,8 @@
 Un altro problema è l'eliminazione dei temporizzatori che si riavviano
 da soli (chiamando :c:func:`add_timer()` alla fine della loro esecuzione).
 Dato che questo è un problema abbastanza comune con una propensione
-alle corse critiche, dovreste usare :c:func:`del_timer_sync()`
-(``include/linux/timer.h``) per gestire questo caso. Questa ritorna il
-numero di volte che il temporizzatore è stato interrotto prima che
-fosse in grado di fermarlo senza che si riavviasse.
+alle corse critiche, dovreste usare :c:func:`timer_delete_sync()`
+(``include/linux/timer.h``) per gestire questo caso.
 
 Velocità della sincronizzazione
 ===============================
@@ -1384,7 +1382,7 @@
 
 -  :c:func:`kfree()`
 
--  :c:func:`add_timer()` e :c:func:`del_timer()`
+-  :c:func:`add_timer()` e :c:func:`timer_delete()`
 
 Riferimento per l'API dei Mutex
 ===============================
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/translations/zh_CN/video4linux/v4l2-framework.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/translations/zh_CN/video4linux/v4l2-framework.txt
@@ -649,7 +649,7 @@
 
 接下来你需要注册视频设备：这会为你创建一个字符设备。
 
-	err = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
+	err = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
 	if (err) {
 		video_device_release(vdev); /* or kfree(my_vdev); */
 		return err;
@@ -660,7 +660,7 @@
 
 注册哪种设备是根据类型（type）参数。存在以下类型：
 
-VFL_TYPE_GRABBER: 用于视频输入/输出设备的 videoX
+VFL_TYPE_VIDEO: 用于视频输入/输出设备的 videoX
 VFL_TYPE_VBI: 用于垂直消隐数据的 vbiX (例如，隐藏式字幕，图文电视)
 VFL_TYPE_RADIO: 用于广播调谐器的 radioX
 
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/userspace-api/seccomp_filter.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/userspace-api/seccomp_filter.rst
@@ -250,14 +250,14 @@
 seccomp notification fd to receive a ``struct seccomp_notif``, which contains
 five members: the input length of the structure, a unique-per-filter ``id``,
 the ``pid`` of the task which triggered this request (which may be 0 if the
-task is in a pid ns not visible from the listener's pid namespace), a ``flags``
-member which for now only has ``SECCOMP_NOTIF_FLAG_SIGNALED``, representing
-whether or not the notification is a result of a non-fatal signal, and the
-``data`` passed to seccomp. Userspace can then make a decision based on this
-information about what to do, and ``ioctl(SECCOMP_IOCTL_NOTIF_SEND)`` a
-response, indicating what should be returned to userspace. The ``id`` member of
-``struct seccomp_notif_resp`` should be the same ``id`` as in ``struct
-seccomp_notif``.
+task is in a pid ns not visible from the listener's pid namespace). The
+notification also contains the ``data`` passed to seccomp, and a filters flag.
+The structure should be zeroed out prior to calling the ioctl.
+
+Userspace can then make a decision based on this information about what to do,
+and ``ioctl(SECCOMP_IOCTL_NOTIF_SEND)`` a response, indicating what should be
+returned to userspace. The ``id`` member of ``struct seccomp_notif_resp`` should
+be the same ``id`` as in ``struct seccomp_notif``.
 
 It is worth noting that ``struct seccomp_data`` contains the values of register
 arguments to the syscall, but does not contain pointers to memory. The task's
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/virt/kvm/api.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/virt/kvm/api.txt
@@ -172,6 +172,9 @@
 be retrieved using KVM_CAP_ARM_VM_IPA_SIZE of the KVM_CHECK_EXTENSION
 ioctl() at run-time.
 
+Creation of the VM will fail if the requested IPA size (whether it is
+implicit or explicit) is unsupported on the host.
+
 Please note that configuring the IPA size does not affect the capability
 exposed by the guest CPUs in ID_AA64MMFR0_EL1[PARange]. It only affects
 size of the address translated by the stage2 level (guest physical to
@@ -1132,6 +1135,9 @@
 the entire memory slot size.  Any object may back this memory, including
 anonymous memory, ordinary files, and hugetlbfs.
 
+On architectures that support a form of address tagging, userspace_addr must
+be an untagged address.
+
 It is recommended that the lower 21 bits of guest_phys_addr and userspace_addr
 be identical.  This allows large pages in the guest to be backed by large
 pages in the host.
@@ -1897,9 +1903,11 @@
 Parameters: struct kvm_one_reg (in)
 Returns: 0 on success, negative value on failure
 Errors:
-  ENOENT:   no such register
-  EINVAL:   invalid register ID, or no such register
-  EPERM:    (arm64) register access not allowed before vcpu finalization
+  ENOENT   no such register
+  EINVAL   invalid register ID, or no such register or used with VMs in
+           protected virtualization mode on s390
+  EPERM    (arm64) register access not allowed before vcpu finalization
+
 (These error codes are indicative only: do not rely on a specific error
 code being returned in a specific situation.)
 
@@ -2290,9 +2298,11 @@
 Parameters: struct kvm_one_reg (in and out)
 Returns: 0 on success, negative value on failure
 Errors include:
-  ENOENT:   no such register
-  EINVAL:   invalid register ID, or no such register
-  EPERM:    (arm64) register access not allowed before vcpu finalization
+  ENOENT   no such register
+  EINVAL   invalid register ID, or no such register or used with VMs in
+           protected virtualization mode on s390
+  EPERM    (arm64) register access not allowed before vcpu finalization
+
 (These error codes are indicative only: do not rely on a specific error
 code being returned in a specific situation.)
 
@@ -3058,51 +3068,116 @@
 
 4.89 KVM_S390_MEM_OP
 
-Capability: KVM_CAP_S390_MEM_OP
-Architectures: s390
-Type: vcpu ioctl
-Parameters: struct kvm_s390_mem_op (in)
-Returns: = 0 on success,
-         < 0 on generic error (e.g. -EFAULT or -ENOMEM),
-         > 0 if an exception occurred while walking the page tables
-
-Read or write data from/to the logical (virtual) memory of a VCPU.
+:Capability: KVM_CAP_S390_MEM_OP, KVM_CAP_S390_PROTECTED, KVM_CAP_S390_MEM_OP_EXTENSION
+:Architectures: s390
+:Type: vm ioctl, vcpu ioctl
+:Parameters: struct kvm_s390_mem_op (in)
+:Returns: = 0 on success,
+          < 0 on generic error (e.g. -EFAULT or -ENOMEM),
+          > 0 if an exception occurred while walking the page tables
+
+Read or write data from/to the VM's memory.
+The KVM_CAP_S390_MEM_OP_EXTENSION capability specifies what functionality is
+supported.
 
-Parameters are specified via the following structure:
+Parameters are specified via the following structure::
 
-struct kvm_s390_mem_op {
+  struct kvm_s390_mem_op {
 	__u64 gaddr;		/* the guest address */
 	__u64 flags;		/* flags */
 	__u32 size;		/* amount of bytes */
 	__u32 op;		/* type of operation */
 	__u64 buf;		/* buffer in userspace */
-	__u8 ar;		/* the access register number */
-	__u8 reserved[31];	/* should be set to 0 */
-};
-
-The type of operation is specified in the "op" field. It is either
-KVM_S390_MEMOP_LOGICAL_READ for reading from logical memory space or
-KVM_S390_MEMOP_LOGICAL_WRITE for writing to logical memory space. The
-KVM_S390_MEMOP_F_CHECK_ONLY flag can be set in the "flags" field to check
-whether the corresponding memory access would create an access exception
-(without touching the data in the memory at the destination). In case an
-access exception occurred while walking the MMU tables of the guest, the
-ioctl returns a positive error number to indicate the type of exception.
-This exception is also raised directly at the corresponding VCPU if the
-flag KVM_S390_MEMOP_F_INJECT_EXCEPTION is set in the "flags" field.
+	union {
+		struct {
+			__u8 ar;	/* the access register number */
+			__u8 key;	/* access key, ignored if flag unset */
+		};
+		__u32 sida_offset; /* offset into the sida */
+		__u8 reserved[32]; /* ignored */
+	};
+  };
 
 The start address of the memory region has to be specified in the "gaddr"
 field, and the length of the region in the "size" field (which must not
 be 0). The maximum value for "size" can be obtained by checking the
 KVM_CAP_S390_MEM_OP capability. "buf" is the buffer supplied by the
 userspace application where the read data should be written to for
-KVM_S390_MEMOP_LOGICAL_READ, or where the data that should be written is
-stored for a KVM_S390_MEMOP_LOGICAL_WRITE. When KVM_S390_MEMOP_F_CHECK_ONLY
-is specified, "buf" is unused and can be NULL. "ar" designates the access
-register number to be used; the valid range is 0..15.
+a read access, or where the data that should be written is stored for
+a write access.  The "reserved" field is meant for future extensions.
+Reserved and unused values are ignored. Future extension that add members must
+introduce new flags.
+
+The type of operation is specified in the "op" field. Flags modifying
+their behavior can be set in the "flags" field. Undefined flag bits must
+be set to 0.
+
+Possible operations are:
+  * ``KVM_S390_MEMOP_LOGICAL_READ``
+  * ``KVM_S390_MEMOP_LOGICAL_WRITE``
+  * ``KVM_S390_MEMOP_ABSOLUTE_READ``
+  * ``KVM_S390_MEMOP_ABSOLUTE_WRITE``
+  * ``KVM_S390_MEMOP_SIDA_READ``
+  * ``KVM_S390_MEMOP_SIDA_WRITE``
+
+Logical read/write:
+
+Access logical memory, i.e. translate the given guest address to an absolute
+address given the state of the VCPU and use the absolute address as target of
+the access. "ar" designates the access register number to be used; the valid
+range is 0..15.
+Logical accesses are permitted for the VCPU ioctl only.
+Logical accesses are permitted for non-protected guests only.
+
+Supported flags:
+  * ``KVM_S390_MEMOP_F_CHECK_ONLY``
+  * ``KVM_S390_MEMOP_F_INJECT_EXCEPTION``
+  * ``KVM_S390_MEMOP_F_SKEY_PROTECTION``
+
+The KVM_S390_MEMOP_F_CHECK_ONLY flag can be set to check whether the
+corresponding memory access would cause an access exception; however,
+no actual access to the data in memory at the destination is performed.
+In this case, "buf" is unused and can be NULL.
+
+In case an access exception occurred during the access (or would occur
+in case of KVM_S390_MEMOP_F_CHECK_ONLY), the ioctl returns a positive
+error number indicating the type of exception. This exception is also
+raised directly at the corresponding VCPU if the flag
+KVM_S390_MEMOP_F_INJECT_EXCEPTION is set.
+
+If the KVM_S390_MEMOP_F_SKEY_PROTECTION flag is set, storage key
+protection is also in effect and may cause exceptions if accesses are
+prohibited given the access key designated by "key"; the valid range is 0..15.
+KVM_S390_MEMOP_F_SKEY_PROTECTION is available if KVM_CAP_S390_MEM_OP_EXTENSION
+is > 0.
+
+Absolute read/write:
+
+Access absolute memory. This operation is intended to be used with the
+KVM_S390_MEMOP_F_SKEY_PROTECTION flag, to allow accessing memory and performing
+the checks required for storage key protection as one operation (as opposed to
+user space getting the storage keys, performing the checks, and accessing
+memory thereafter, which could lead to a delay between check and access).
+Absolute accesses are permitted for the VM ioctl if KVM_CAP_S390_MEM_OP_EXTENSION
+is > 0.
+Currently absolute accesses are not permitted for VCPU ioctls.
+Absolute accesses are permitted for non-protected guests only.
+
+Supported flags:
+  * ``KVM_S390_MEMOP_F_CHECK_ONLY``
+  * ``KVM_S390_MEMOP_F_SKEY_PROTECTION``
+
+The semantics of the flags are as for logical accesses.
+
+SIDA read/write:
+
+Access the secure instruction data area which contains memory operands necessary
+for instruction emulation for protected guests.
+SIDA accesses are available if the KVM_CAP_S390_PROTECTED capability is available.
+SIDA accesses are permitted for the VCPU ioctl only.
+SIDA accesses are permitted for protected guests only.
 
-The "reserved" field is meant for future extensions. It is not used by
-KVM with the currently defined set of flags.
+No flags are supported.
 
 4.90 KVM_S390_GET_SKEYS
 
@@ -3609,6 +3684,18 @@
 Parameters: struct kvm_s390_cmma_log (in, out)
 Returns: 0 on success, a negative value on error
 
+Errors:
+
+  ======     =============================================================
+  ENOMEM     not enough memory can be allocated to complete the task
+  ENXIO      if CMMA is not enabled
+  EINVAL     if KVM_S390_CMMA_PEEK is not set but migration mode was not enabled
+  EINVAL     if KVM_S390_CMMA_PEEK is not set but dirty tracking has been
+             disabled (and thus migration mode was automatically disabled)
+  EFAULT     if the userspace address is invalid or if no page table is
+             present for the addresses (e.g. when using hugepages).
+  ======     =============================================================
+
 This ioctl is used to get the values of the CMMA bits on the s390
 architecture. It is meant to be used in two scenarios:
 - During live migration to save the CMMA values. Live migration needs
@@ -3685,12 +3772,6 @@
 
 values points to the userspace buffer where the result will be stored.
 
-This ioctl can fail with -ENOMEM if not enough memory can be allocated to
-complete the task, with -ENXIO if CMMA is not enabled, with -EINVAL if
-KVM_S390_CMMA_PEEK is not set but migration mode was not enabled, with
--EFAULT if the userspace address is invalid or if no page table is
-present for the addresses (e.g. when using hugepages).
-
 4.108 KVM_S390_SET_CMMA_BITS
 
 Capability: KVM_CAP_S390_CMMA_MIGRATION
@@ -4127,6 +4208,90 @@
 #define KVM_PMU_EVENT_DENY 1
 
 
+4.122 KVM_S390_NORMAL_RESET
+
+Capability: KVM_CAP_S390_VCPU_RESETS
+Architectures: s390
+Type: vcpu ioctl
+Parameters: none
+Returns: 0
+
+This ioctl resets VCPU registers and control structures according to
+the cpu reset definition in the POP (Principles Of Operation).
+
+4.123 KVM_S390_INITIAL_RESET
+
+Capability: none
+Architectures: s390
+Type: vcpu ioctl
+Parameters: none
+Returns: 0
+
+This ioctl resets VCPU registers and control structures according to
+the initial cpu reset definition in the POP. However, the cpu is not
+put into ESA mode. This reset is a superset of the normal reset.
+
+4.124 KVM_S390_CLEAR_RESET
+
+Capability: KVM_CAP_S390_VCPU_RESETS
+Architectures: s390
+Type: vcpu ioctl
+Parameters: none
+Returns: 0
+
+This ioctl resets VCPU registers and control structures according to
+the clear cpu reset definition in the POP. However, the cpu is not put
+into ESA mode. This reset is a superset of the initial reset.
+
+
+4.125 KVM_S390_PV_COMMAND
+-------------------------
+
+:Capability: KVM_CAP_S390_PROTECTED
+:Architectures: s390
+:Type: vm ioctl
+:Parameters: struct kvm_pv_cmd
+:Returns: 0 on success, < 0 on error
+
+::
+
+  struct kvm_pv_cmd {
+	__u32 cmd;	/* Command to be executed */
+	__u16 rc;	/* Ultravisor return code */
+	__u16 rrc;	/* Ultravisor return reason code */
+	__u64 data;	/* Data or address */
+	__u32 flags;    /* flags for future extensions. Must be 0 for now */
+	__u32 reserved[3];
+  };
+
+cmd values:
+
+KVM_PV_ENABLE
+  Allocate memory and register the VM with the Ultravisor, thereby
+  donating memory to the Ultravisor that will become inaccessible to
+  KVM. All existing CPUs are converted to protected ones. After this
+  command has succeeded, any CPU added via hotplug will become
+  protected during its creation as well.
+
+KVM_PV_DISABLE
+
+  Deregister the VM from the Ultravisor and reclaim the memory that
+  had been donated to the Ultravisor, making it usable by the kernel
+  again.  All registered VCPUs are converted back to non-protected
+  ones.
+
+KVM_PV_VM_SET_SEC_PARMS
+  Pass the image header from VM memory to the Ultravisor in
+  preparation of image unpacking and verification.
+
+KVM_PV_VM_UNPACK
+  Unpack (protect and decrypt) a page of the encrypted boot image.
+
+KVM_PV_VM_VERIFY
+  Verify the integrity of the unpacked image. Only if this succeeds,
+  KVM is allowed to start protected VCPUs.
+
+
 5. The kvm_run structure
 ------------------------
 
@@ -4444,9 +4609,11 @@
 #define KVM_EXIT_HYPERV_SYNIC          1
 #define KVM_EXIT_HYPERV_HCALL          2
 			__u32 type;
+			__u32 pad1;
 			union {
 				struct {
 					__u32 msr;
+					__u32 pad2;
 					__u64 control;
 					__u64 evt_page;
 					__u64 msg_page;
@@ -5322,3 +5489,21 @@
 flush hypercalls by Hyper-V) so userspace should disable KVM identification
 in CPUID and only exposes Hyper-V identification. In this case, guest
 thinks it's running on Hyper-V and only use Hyper-V hypercalls.
+
+8.22 KVM_CAP_S390_VCPU_RESETS
+
+Architectures: s390
+
+This capability indicates that the KVM_S390_NORMAL_RESET and
+KVM_S390_CLEAR_RESET ioctls are available.
+
+8.23 KVM_CAP_S390_PROTECTED
+
+Architecture: s390
+
+
+This capability indicates that the Ultravisor has been initialized and
+KVM can therefore start protected VMs.
+This capability governs the KVM_S390_PV_COMMAND ioctl and the
+KVM_MP_STATE_LOAD MP_STATE. KVM_SET_MP_STATE can fail for protected
+guests when the state change is invalid.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/virt/kvm/devices/s390_flic.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/virt/kvm/devices/s390_flic.txt
@@ -100,15 +100,9 @@
       mask or unmask the adapter, as specified in mask
 
     KVM_S390_IO_ADAPTER_MAP
-      perform a gmap translation for the guest address provided in addr,
-      pin a userspace page for the translated address and add it to the
-      list of mappings
-      Note: A new mapping will be created unconditionally; therefore,
-            the calling code should avoid making duplicate mappings.
-
+      This is now a no-op. The mapping is purely done by the irq route.
     KVM_S390_IO_ADAPTER_UNMAP
-      release a userspace page for the translated address specified in addr
-      from the list of mappings
+      This is now a no-op. The mapping is purely done by the irq route.
 
   KVM_DEV_FLIC_AISM
     modify the adapter-interruption-suppression mode for a given isc if the
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/virt/kvm/devices/vm.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/virt/kvm/devices/vm.txt
@@ -183,6 +183,7 @@
 Parameters: address of a buffer in user space to store the data (u8) to
 Returns:    -EFAULT if the given address is not accessible from kernel space
 	    -EINVAL if setting the TOD clock extension to != 0 is not supported
+        -EOPNOTSUPP for a PV guest (TOD managed by the ultravisor)
 
 3.2. ATTRIBUTE: KVM_S390_VM_TOD_LOW
 
@@ -191,6 +192,8 @@
 
 Parameters: address of a buffer in user space to store the data (u64) to
 Returns:    -EFAULT if the given address is not accessible from kernel space
+        -EOPNOTSUPP for a PV guest (TOD managed by the ultravisor)
+
 
 3.3. ATTRIBUTE: KVM_S390_VM_TOD_EXT
 Allows user space to set/get bits 0-63 of the TOD clock register as defined in
@@ -202,6 +205,7 @@
             (kvm_s390_vm_tod_clock) to
 Returns:    -EFAULT if the given address is not accessible from kernel space
 	    -EINVAL if setting the TOD clock extension to != 0 is not supported
+        -EOPNOTSUPP for a PV guest (TOD managed by the ultravisor)
 
 4. GROUP: KVM_S390_VM_CRYPTO
 Architectures: s390
@@ -254,6 +258,10 @@
 Setting this attribute when migration mode is already active will have
 no effects.
 
+Dirty tracking must be enabled on all memslots, else -EINVAL is returned. When
+dirty tracking is disabled on any memslot, migration mode is automatically
+stopped.
+
 Parameters: none
 Returns:    -ENOMEM if there is not enough free memory to start migration mode
 	    -EINVAL if the state of the VM is invalid (e.g. no memory defined)
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/virt/kvm/index.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/virt/kvm/index.rst
@@ -9,4 +9,6 @@
 
    amd-memory-encryption
    cpuid
+   s390-pv
+   s390-pv-boot
    vcpu-requests
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/virt/kvm/mmu.txt
+++ linux-xilinx-zynqmp-5.4.0/Documentation/virt/kvm/mmu.txt
@@ -152,8 +152,8 @@
     shadow pages) so role.quadrant takes values in the range 0..3.  Each
     quadrant maps 1GB virtual address space.
   role.access:
-    Inherited guest access permissions in the form uwx.  Note execute
-    permission is positive, not negative.
+    Inherited guest access permissions from the parent ptes in the form uwx.
+    Note execute permission is positive, not negative.
   role.invalid:
     The page is invalid and should not be used.  It is a root page that is
     currently pinned (by a cpu hardware register pointing to it); once it is
@@ -420,7 +420,7 @@
 number, it will ignore the cached MMIO information and handle the page
 fault through the slow path.
 
-Since only 19 bits are used to store generation-number on mmio spte, all
+Since only 18 bits are used to store generation-number on mmio spte, all
 pages are zapped when there is an overflow.
 
 Unfortunately, a single memory access might access kvm_memslots(kvm) multiple
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/virt/kvm/s390-pv-boot.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/virt/kvm/s390-pv-boot.rst
@@ -0,0 +1,84 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+======================================
+s390 (IBM Z) Boot/IPL of Protected VMs
+======================================
+
+Summary
+-------
+The memory of Protected Virtual Machines (PVMs) is not accessible to
+I/O or the hypervisor. In those cases where the hypervisor needs to
+access the memory of a PVM, that memory must be made accessible.
+Memory made accessible to the hypervisor will be encrypted. See
+:doc:`s390-pv` for details."
+
+On IPL (boot) a small plaintext bootloader is started, which provides
+information about the encrypted components and necessary metadata to
+KVM to decrypt the protected virtual machine.
+
+Based on this data, KVM will make the protected virtual machine known
+to the Ultravisor (UV) and instruct it to secure the memory of the
+PVM, decrypt the components and verify the data and address list
+hashes, to ensure integrity. Afterwards KVM can run the PVM via the
+SIE instruction which the UV will intercept and execute on KVM's
+behalf.
+
+As the guest image is just like an opaque kernel image that does the
+switch into PV mode itself, the user can load encrypted guest
+executables and data via every available method (network, dasd, scsi,
+direct kernel, ...) without the need to change the boot process.
+
+
+Diag308
+-------
+This diagnose instruction is the basic mechanism to handle IPL and
+related operations for virtual machines. The VM can set and retrieve
+IPL information blocks, that specify the IPL method/devices and
+request VM memory and subsystem resets, as well as IPLs.
+
+For PVMs this concept has been extended with new subcodes:
+
+Subcode 8: Set an IPL Information Block of type 5 (information block
+for PVMs)
+Subcode 9: Store the saved block in guest memory
+Subcode 10: Move into Protected Virtualization mode
+
+The new PV load-device-specific-parameters field specifies all data
+that is necessary to move into PV mode.
+
+* PV Header origin
+* PV Header length
+* List of Components composed of
+   * AES-XTS Tweak prefix
+   * Origin
+   * Size
+
+The PV header contains the keys and hashes, which the UV will use to
+decrypt and verify the PV, as well as control flags and a start PSW.
+
+The components are for instance an encrypted kernel, kernel parameters
+and initrd. The components are decrypted by the UV.
+
+After the initial import of the encrypted data, all defined pages will
+contain the guest content. All non-specified pages will start out as
+zero pages on first access.
+
+
+When running in protected virtualization mode, some subcodes will result in
+exceptions or return error codes.
+
+Subcodes 4 and 7, which specify operations that do not clear the guest
+memory, will result in specification exceptions. This is because the
+UV will clear all memory when a secure VM is removed, and therefore
+non-clearing IPL subcodes are not allowed.
+
+Subcodes 8, 9, 10 will result in specification exceptions.
+Re-IPL into a protected mode is only possible via a detour into non
+protected mode.
+
+Keys
+----
+Every CEC will have a unique public key to enable tooling to build
+encrypted images.
+See  `s390-tools <https://github.com/ibm-s390-tools/s390-tools/>`_
+for the tooling.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/virt/kvm/s390-pv.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/virt/kvm/s390-pv.rst
@@ -0,0 +1,116 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=========================================
+s390 (IBM Z) Ultravisor and Protected VMs
+=========================================
+
+Summary
+-------
+Protected virtual machines (PVM) are KVM VMs that do not allow KVM to
+access VM state like guest memory or guest registers. Instead, the
+PVMs are mostly managed by a new entity called Ultravisor (UV). The UV
+provides an API that can be used by PVMs and KVM to request management
+actions.
+
+Each guest starts in non-protected mode and then may make a request to
+transition into protected mode. On transition, KVM registers the guest
+and its VCPUs with the Ultravisor and prepares everything for running
+it.
+
+The Ultravisor will secure and decrypt the guest's boot memory
+(i.e. kernel/initrd). It will safeguard state changes like VCPU
+starts/stops and injected interrupts while the guest is running.
+
+As access to the guest's state, such as the SIE state description, is
+normally needed to be able to run a VM, some changes have been made in
+the behavior of the SIE instruction. A new format 4 state description
+has been introduced, where some fields have different meanings for a
+PVM. SIE exits are minimized as much as possible to improve speed and
+reduce exposed guest state.
+
+
+Interrupt injection
+-------------------
+Interrupt injection is safeguarded by the Ultravisor. As KVM doesn't
+have access to the VCPUs' lowcores, injection is handled via the
+format 4 state description.
+
+Machine check, external, IO and restart interruptions each can be
+injected on SIE entry via a bit in the interrupt injection control
+field (offset 0x54). If the guest cpu is not enabled for the interrupt
+at the time of injection, a validity interception is recognized. The
+format 4 state description contains fields in the interception data
+block where data associated with the interrupt can be transported.
+
+Program and Service Call exceptions have another layer of
+safeguarding; they can only be injected for instructions that have
+been intercepted into KVM. The exceptions need to be a valid outcome
+of an instruction emulation by KVM, e.g. we can never inject a
+addressing exception as they are reported by SIE since KVM has no
+access to the guest memory.
+
+
+Mask notification interceptions
+-------------------------------
+KVM cannot intercept lctl(g) and lpsw(e) anymore in order to be
+notified when a PVM enables a certain class of interrupt.  As a
+replacement, two new interception codes have been introduced: One
+indicating that the contents of CRs 0, 6, or 14 have been changed,
+indicating different interruption subclasses; and one indicating that
+PSW bit 13 has been changed, indicating that a machine check
+intervention was requested and those are now enabled.
+
+Instruction emulation
+---------------------
+With the format 4 state description for PVMs, the SIE instruction already
+interprets more instructions than it does with format 2. It is not able
+to interpret every instruction, but needs to hand some tasks to KVM;
+therefore, the SIE and the ultravisor safeguard emulation inputs and outputs.
+
+The control structures associated with SIE provide the Secure
+Instruction Data Area (SIDA), the Interception Parameters (IP) and the
+Secure Interception General Register Save Area.  Guest GRs and most of
+the instruction data, such as I/O data structures, are filtered.
+Instruction data is copied to and from the SIDA when needed.  Guest
+GRs are put into / retrieved from the Secure Interception General
+Register Save Area.
+
+Only GR values needed to emulate an instruction will be copied into this
+save area and the real register numbers will be hidden.
+
+The Interception Parameters state description field still contains the
+the bytes of the instruction text, but with pre-set register values
+instead of the actual ones. I.e. each instruction always uses the same
+instruction text, in order not to leak guest instruction text.
+This also implies that the register content that a guest had in r<n>
+may be in r<m> from the hypervisor's point of view.
+
+The Secure Instruction Data Area contains instruction storage
+data. Instruction data, i.e. data being referenced by an instruction
+like the SCCB for sclp, is moved via the SIDA. When an instruction is
+intercepted, the SIE will only allow data and program interrupts for
+this instruction to be moved to the guest via the two data areas
+discussed before. Other data is either ignored or results in validity
+interceptions.
+
+
+Instruction emulation interceptions
+-----------------------------------
+There are two types of SIE secure instruction intercepts: the normal
+and the notification type. Normal secure instruction intercepts will
+make the guest pending for instruction completion of the intercepted
+instruction type, i.e. on SIE entry it is attempted to complete
+emulation of the instruction with the data provided by KVM. That might
+be a program exception or instruction completion.
+
+The notification type intercepts inform KVM about guest environment
+changes due to guest instruction interpretation. Such an interception
+is recognized, for example, for the store prefix instruction to provide
+the new lowcore location. On SIE reentry, any KVM data in the data areas
+is ignored and execution continues as if the guest instruction had
+completed. For that reason KVM is not allowed to inject a program
+interrupt.
+
+Links
+-----
+`KVM Forum 2019 presentation <https://static.sched.com/hosted_files/kvmforum2019/3b/ibm_protected_vms_s390x.pdf>`_
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/vm/memory-model.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/vm/memory-model.rst
@@ -52,8 +52,7 @@
 usable until the call to :c:func:`memblock_free_all` that hands all
 the memory to the page allocator.
 
-If an architecture enables `CONFIG_ARCH_HAS_HOLES_MEMORYMODEL` option,
-it may free parts of the `mem_map` array that do not cover the
+An architecture may free parts of the `mem_map` array that do not cover the
 actual physical pages. In such case, the architecture specific
 :c:func:`pfn_valid` implementation should take the holes in the
 `mem_map` into account.
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/vm/slub.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/vm/slub.rst
@@ -160,7 +160,7 @@
 Here is a sample of slub debug output::
 
  ====================================================================
- BUG kmalloc-8: Redzone overwritten
+ BUG kmalloc-8: Right Redzone overwritten
  --------------------------------------------------------------------
 
  INFO: 0xc90f6d28-0xc90f6d2b. First byte 0x00 instead of 0xcc
@@ -168,10 +168,10 @@
  INFO: Object 0xc90f6d20 @offset=3360 fp=0xc90f6d58
  INFO: Allocated in get_modalias+0x61/0xf5 age=53 cpu=1 pid=554
 
- Bytes b4 0xc90f6d10:  00 00 00 00 00 00 00 00 5a 5a 5a 5a 5a 5a 5a 5a ........ZZZZZZZZ
-   Object 0xc90f6d20:  31 30 31 39 2e 30 30 35                         1019.005
-  Redzone 0xc90f6d28:  00 cc cc cc                                     .
-  Padding 0xc90f6d50:  5a 5a 5a 5a 5a 5a 5a 5a                         ZZZZZZZZ
+ Bytes b4 (0xc90f6d10): 00 00 00 00 00 00 00 00 5a 5a 5a 5a 5a 5a 5a 5a ........ZZZZZZZZ
+ Object   (0xc90f6d20): 31 30 31 39 2e 30 30 35                         1019.005
+ Redzone  (0xc90f6d28): 00 cc cc cc                                     .
+ Padding  (0xc90f6d50): 5a 5a 5a 5a 5a 5a 5a 5a                         ZZZZZZZZ
 
    [<c010523d>] dump_trace+0x63/0x1eb
    [<c01053df>] show_trace_log_lvl+0x1a/0x2f
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/x86/topology.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/x86/topology.rst
@@ -41,6 +41,8 @@
 Packages contain a number of cores plus shared resources, e.g. DRAM
 controller, shared caches etc.
 
+Modern systems may also use the term 'Die' for package.
+
 AMD nomenclature for package is 'Node'.
 
 Package-related topology information in the kernel:
@@ -53,11 +55,18 @@
 
     The number of dies in a package. This information is retrieved via CPUID.
 
+  - cpuinfo_x86.cpu_die_id:
+
+    The physical ID of the die. This information is retrieved via CPUID.
+
   - cpuinfo_x86.phys_proc_id:
 
     The physical ID of the package. This information is retrieved via CPUID
     and deduced from the APIC IDs of the cores in the package.
 
+    Modern systems use this value for the socket. There may be multiple
+    packages within a socket. This value may differ from cpu_die_id.
+
   - cpuinfo_x86.logical_proc_id:
 
     The logical ID of the package. As we do not trust BIOSes to enumerate the
--- linux-xilinx-zynqmp-5.4.0.orig/Documentation/xtensa/mmu.rst
+++ linux-xilinx-zynqmp-5.4.0/Documentation/xtensa/mmu.rst
@@ -82,7 +82,8 @@
   +------------------+
   | VMALLOC area     |  VMALLOC_START            0xc0000000  128MB - 64KB
   +------------------+  VMALLOC_END
-  | Cache aliasing   |  TLBTEMP_BASE_1           0xc7ff0000  DCACHE_WAY_SIZE
+  +------------------+
+  | Cache aliasing   |  TLBTEMP_BASE_1           0xc8000000  DCACHE_WAY_SIZE
   | remap area 1     |
   +------------------+
   | Cache aliasing   |  TLBTEMP_BASE_2                       DCACHE_WAY_SIZE
@@ -124,7 +125,8 @@
   +------------------+
   | VMALLOC area     |  VMALLOC_START            0xa0000000  128MB - 64KB
   +------------------+  VMALLOC_END
-  | Cache aliasing   |  TLBTEMP_BASE_1           0xa7ff0000  DCACHE_WAY_SIZE
+  +------------------+
+  | Cache aliasing   |  TLBTEMP_BASE_1           0xa8000000  DCACHE_WAY_SIZE
   | remap area 1     |
   +------------------+
   | Cache aliasing   |  TLBTEMP_BASE_2                       DCACHE_WAY_SIZE
@@ -167,7 +169,8 @@
   +------------------+
   | VMALLOC area     |  VMALLOC_START            0x90000000  128MB - 64KB
   +------------------+  VMALLOC_END
-  | Cache aliasing   |  TLBTEMP_BASE_1           0x97ff0000  DCACHE_WAY_SIZE
+  +------------------+
+  | Cache aliasing   |  TLBTEMP_BASE_1           0x98000000  DCACHE_WAY_SIZE
   | remap area 1     |
   +------------------+
   | Cache aliasing   |  TLBTEMP_BASE_2                       DCACHE_WAY_SIZE
--- linux-xilinx-zynqmp-5.4.0.orig/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/Kconfig
@@ -21,6 +21,8 @@
 
 source "drivers/Kconfig"
 
+source "ubuntu/Kconfig"
+
 source "fs/Kconfig"
 
 source "security/Kconfig"
--- linux-xilinx-zynqmp-5.4.0.orig/MAINTAINERS
+++ linux-xilinx-zynqmp-5.4.0/MAINTAINERS
@@ -537,6 +537,17 @@
 F:	Documentation/scsi/advansys.txt
 F:	drivers/scsi/advansys.c
 
+ADVANTECH AHC1EC0 EMBEDDED CONTROLLER DRIVER
+M:	Campion Kang <campion.kang@advantech.com.tw>
+L:	linux-kernel@vger.kernel.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/mfd/ahc1ec0.yaml
+F:	drivers/hwmon/ahc1ec0-hwmon.c
+F:	drivers/mfd/ahc1ec0.c
+F:	drivers/watchdog/ahc1ec0-wdt.c
+F:	include/dt-bindings/mfd/ahc1ec0-dt.h
+F:	include/linux/mfd/ahc1ec0.h
+
 ADXL34X THREE-AXIS DIGITAL ACCELEROMETER DRIVER (ADXL345/ADXL346)
 M:	Michael Hennerich <michael.hennerich@analog.com>
 W:	http://wiki.analog.com/ADXL345
@@ -1101,7 +1112,7 @@
 M:	William Breathitt Gray <vilhelm.gray@gmail.com>
 L:	linux-iio@vger.kernel.org
 S:	Maintained
-F:	drivers/iio/adc/stx104.c
+F:	drivers/iio/addac/stx104.c
 
 APM DRIVER
 M:	Jiri Kosina <jikos@kernel.org>
@@ -2778,8 +2789,11 @@
 
 ATMEL MACB ETHERNET DRIVER
 M:	Nicolas Ferre <nicolas.ferre@microchip.com>
+R:	Harini Katakam <harini.katakam@xilinx.com>
+L:	git@xilinx.com
 S:	Supported
 F:	drivers/net/ethernet/cadence/
+W:	https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18841740/Macb+Driver
 
 ATMEL MAXTOUCH DRIVER
 M:	Nick Dyer <nick@shmanahar.org>
@@ -2832,6 +2846,19 @@
 F:	include/uapi/linux/audit.h
 F:	kernel/audit*
 
+AUFS (advanced multi layered unification filesystem) FILESYSTEM
+M:	"J. R. Okajima" <hooanon05g@gmail.com>
+L:	aufs-users@lists.sourceforge.net (members only)
+L:	linux-unionfs@vger.kernel.org
+W:	http://aufs.sourceforge.net
+T:	git://github.com/sfjro/aufs4-linux.git
+S:	Supported
+F:	Documentation/filesystems/aufs/
+F:	Documentation/ABI/testing/debugfs-aufs
+F:	Documentation/ABI/testing/sysfs-aufs
+F:	fs/aufs/
+F:	include/uapi/linux/aufs_type.h
+
 AUXILIARY DISPLAY DRIVERS
 M:	Miguel Ojeda Sandonis <miguel.ojeda.sandonis@gmail.com>
 S:	Maintained
@@ -3588,6 +3615,13 @@
 F:	Documentation/filesystems/caching/cachefiles.txt
 F:	fs/cachefiles/
 
+CADENCE I2C DRIVER
+M:	Shubhrajyoti Datta <shubhrajyoti.datta@xilinx.com>
+R:	Venkata Visweswarachari Mallavarapu <vmallava@xilinx.com>
+L:	git@xilinx.com
+F:	drivers/i2c/busses/i2c-cadence.c
+W:	https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18842160/Cadence+I2C+Driver
+
 CADENCE MIPI-CSI2 BRIDGES
 M:	Maxime Ripard <mripard@kernel.org>
 L:	linux-media@vger.kernel.org
@@ -3872,6 +3906,15 @@
 F:	drivers/misc/
 F:	include/linux/miscdevice.h
 
+CHAR and MISC XILINX AI ENGINE DRIVER
+M:	Wendy Liang <wendy.liang@xilinx.com>
+M:	Hyun Kwon <hyun.kwon@xilinx.com>
+S:	Maintained
+F:	Documentation/devicetree/bindings/soc/xilinx/xlnx,ai-engine.yaml
+F:	drivers/misc/xilinx-ai-engine/
+F:	include/linux/xlnx-ai-engine.h
+F:	include/uapi/linux/xlnx-ai-engine.h
+
 CHECKPATCH
 M:	Andy Whitcroft <apw@canonical.com>
 M:	Joe Perches <joe@perches.com>
@@ -3887,6 +3930,7 @@
 
 CHIPIDEA USB HIGH SPEED DUAL ROLE CONTROLLER
 M:	Peter Chen <Peter.Chen@nxp.com>
+R:	Anurag Kumar Vulisha <anurag.kumar.vulisha@xilinx.com>
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb.git
 L:	linux-usb@vger.kernel.org
 S:	Maintained
@@ -4028,6 +4072,7 @@
 C:	irc://chat.freenode.net/clangbuiltlinux
 S:	Supported
 K:	\b(?i:clang|llvm)\b
+F:	Documentation/kbuild/llvm.rst
 
 CLEANCACHE API
 M:	Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
@@ -4616,13 +4661,6 @@
 F:	include/linux/tfrc.h
 F:	net/dccp/
 
-DECnet NETWORK LAYER
-W:	http://linux-decnet.sourceforge.net
-L:	linux-decnet-user@lists.sourceforge.net
-S:	Orphan
-F:	Documentation/networking/decnet.txt
-F:	net/decnet/
-
 DECSTATION PLATFORM SUPPORT
 M:	"Maciej W. Rozycki" <macro@linux-mips.org>
 L:	linux-mips@vger.kernel.org
@@ -4739,6 +4777,7 @@
 
 DESIGNWARE USB3 DRD IP DRIVER
 M:	Felipe Balbi <balbi@kernel.org>
+R:	Anurag Kumar Vulisha <anurag.kumar.vulisha@xilinx.com>
 L:	linux-usb@vger.kernel.org
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
 S:	Maintained
@@ -5573,6 +5612,15 @@
 F:	include/uapi/drm/etnaviv_drm.h
 F:	Documentation/devicetree/bindings/display/etnaviv/
 
+DRM DRIVERS FOR XILINX
+M:	Hyun Kwon <hyun.kwon@xilinx.com>
+M:	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+L:	dri-devel@lists.freedesktop.org
+S:	Maintained
+F:	drivers/gpu/drm/xlnx/
+F:	Documentation/devicetree/bindings/display/xlnx/
+T:	git git://anongit.freedesktop.org/drm/drm-misc
+
 DRM DRIVERS FOR ZTE ZX
 M:	Shawn Guo <shawnguo@kernel.org>
 L:	dri-devel@lists.freedesktop.org
@@ -6973,6 +7021,7 @@
 S:	Maintained
 F:	Documentation/firmware-guide/acpi/gpio-properties.rst
 F:	drivers/gpio/gpiolib-acpi.c
+F:	drivers/gpio/gpiolib-acpi.h
 
 GPIO IR Transmitter
 M:	Sean Young <sean@mess.org>
@@ -7364,6 +7413,25 @@
 F:	net/802/hippi.c
 F:	drivers/net/hippi/
 
+HISILICON SECURITY ENGINE V2 DRIVER (SEC2)
+M:	Zaibo Xu <xuzaibo@huawei.com>
+L:	linux-crypto@vger.kernel.org
+S:	Maintained
+F:	drivers/crypto/hisilicon/sec2/sec_crypto.c
+F:	drivers/crypto/hisilicon/sec2/sec_main.c
+F:	drivers/crypto/hisilicon/sec2/sec_crypto.h
+F:	drivers/crypto/hisilicon/sec2/sec.h
+F:	Documentation/ABI/testing/debugfs-hisi-sec
+
+HISILICON HIGH PERFORMANCE RSA ENGINE DRIVER (HPRE)
+M:	Zaibo Xu <xuzaibo@huawei.com>
+L:	linux-crypto@vger.kernel.org
+S:	Maintained
+F:	drivers/crypto/hisilicon/hpre/hpre_crypto.c
+F:	drivers/crypto/hisilicon/hpre/hpre_main.c
+F:	drivers/crypto/hisilicon/hpre/hpre.h
+F:	Documentation/ABI/testing/debugfs-hisi-hpre
+
 HISILICON NETWORK SUBSYSTEM 3 DRIVER (HNS3)
 M:	Yisen Zhuang <yisen.zhuang@huawei.com>
 M:	Salil Mehta <salil.mehta@huawei.com>
@@ -7372,6 +7440,11 @@
 S:	Maintained
 F:	drivers/net/ethernet/hisilicon/hns3/
 
+HISILICON TRUE RANDOM NUMBER GENERATOR V2 SUPPORT
+M:	Zaibo Xu <xuzaibo@huawei.com>
+S:	Maintained
+F:	drivers/char/hw_random/hisi-trng-v2.c
+
 HISILICON LPC BUS DRIVER
 M:	john.garry@huawei.com
 W:	http://www.hisilicon.com
@@ -7410,6 +7483,12 @@
 F:	drivers/scsi/hisi_sas/
 F:	Documentation/devicetree/bindings/scsi/hisilicon-sas.txt
 
+HISILICON V3XX SPI NOR FLASH Controller Driver
+M:	John Garry <john.garry@huawei.com>
+W:	http://www.hisilicon.com
+S:	Maintained
+F:	drivers/spi/spi-hisi-sfc-v3xx.c
+
 HISILICON QM AND ZIP Controller DRIVER
 M:	Zhou Wang <wangzhou1@hisilicon.com>
 L:	linux-crypto@vger.kernel.org
@@ -7417,7 +7496,6 @@
 F:	drivers/crypto/hisilicon/qm.c
 F:	drivers/crypto/hisilicon/qm.h
 F:	drivers/crypto/hisilicon/sgl.c
-F:	drivers/crypto/hisilicon/sgl.h
 F:	drivers/crypto/hisilicon/zip/
 F:	Documentation/ABI/testing/debugfs-hisi-zip
 
@@ -8039,6 +8117,14 @@
 F:	drivers/hwmon/ina2xx.c
 F:	include/linux/platform_data/ina2xx.h
 
+INA260 POWER MONITOR DRIVER
+M:	Shubhrajyoti Datta <shubhrajyoti.datta@xilinx.com>
+R:	Raviteja Narayanam <raviteja.narayanam@xilinx.com>
+R:	Michal Simek <michal.simek@xilinx.com>
+S:	Maintained
+F:	drivers/iio/adc/ina260-adc.c
+F:	Documentation/devicetree/bindings/iio/adc/ti,ina260.yaml
+
 INDUSTRY PACK SUBSYSTEM (IPACK)
 M:	Samuel Iglesias Gonsalvez <siglesias@igalia.com>
 M:	Jens Taprogge <jens.taprogge@taprogge.org>
@@ -8200,7 +8286,7 @@
 M:	Rodrigo Vivi <rodrigo.vivi@intel.com>
 L:	intel-gfx@lists.freedesktop.org
 W:	https://01.org/linuxgraphics/
-B:	https://01.org/linuxgraphics/documentation/how-report-bugs
+B:	https://gitlab.freedesktop.org/drm/intel/-/wikis/How-to-file-i915-bugs
 C:	irc://chat.freenode.net/intel-gfx
 Q:	http://patchwork.freedesktop.org/project/intel-gfx/
 T:	git git://anongit.freedesktop.org/drm-intel
@@ -8703,8 +8789,10 @@
 L:	netdev@vger.kernel.org
 W:	http://www.isdn4linux.de
 S:	Maintained
-F:	drivers/isdn/mISDN
-F:	drivers/isdn/hardware
+F:	drivers/isdn/mISDN/
+F:	drivers/isdn/hardware/
+F:	drivers/isdn/Kconfig
+F:	drivers/isdn/Makefile
 
 ISDN/CAPI SUBSYSTEM
 M:	Karsten Keil <isdn@linux-pingi.de>
@@ -8991,6 +9079,7 @@
 W:	http://www.ibm.com/developerworks/linux/linux390/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux.git
 S:	Supported
+F:	Documentation/virt/kvm/s390*
 F:	arch/s390/include/uapi/asm/kvm*
 F:	arch/s390/include/asm/gmap.h
 F:	arch/s390/include/asm/kvm*
@@ -9266,6 +9355,12 @@
 F:	drivers/ata/sata_gemini.c
 F:	drivers/ata/sata_gemini.h
 
+LIBATA SATA AHCI CEVA CONTROLLER DRIVER
+M:	Anurag Kumar Vulisha <anurag.kumar.vulisha@xilinx.com>
+S:	Maintained
+F:	drivers/ata/ahci_ceva.c
+F:	Documentation/devicetree/bindings/ata/ahci-ceva.txt
+
 LIBATA SATA AHCI PLATFORM devices support
 M:	Hans de Goede <hdegoede@redhat.com>
 M:	Jens Axboe <axboe@kernel.dk>
@@ -13636,6 +13731,7 @@
 
 RANDOM NUMBER DRIVER
 M:	"Theodore Ts'o" <tytso@mit.edu>
+M:	Jason A. Donenfeld <Jason@zx2c4.com>
 S:	Maintained
 F:	drivers/char/random.c
 
@@ -14131,6 +14227,7 @@
 S:	Supported
 F:	arch/s390/pci/
 F:	drivers/pci/hotplug/s390_pci_hpc.c
+F:	Documentation/s390/pci.rst
 
 S390 VFIO-CCW DRIVER
 M:	Cornelia Huck <cohuck@redhat.com>
@@ -14656,6 +14753,7 @@
 S:	Maintained
 F:	drivers/net/phy/phylink.c
 F:	drivers/net/phy/sfp*
+F:	include/linux/mdio/mdio-i2c.h
 F:	include/linux/phylink.h
 F:	include/linux/sfp.h
 K:	phylink
@@ -17014,6 +17112,7 @@
 
 USB XHCI DRIVER
 M:	Mathias Nyman <mathias.nyman@intel.com>
+R:	Anurag Kumar Vulisha <anurag.kumar.vulisha@xilinx.com>
 L:	linux-usb@vger.kernel.org
 S:	Supported
 F:	drivers/usb/host/xhci*
@@ -17071,6 +17170,11 @@
 F:	drivers/uio/
 F:	include/linux/uio_driver.h
 
+USERSPACE I/O (UIO) DRIVER FOR XILINX AI ENGINE NPI
+M:	Hyun Kwon <hyun.kwon@xilinx.com>
+S:	Maintained
+F:	Documentation/devicetree/bindings/soc/xilinx/xlnx,ai-engine-npi.txt
+
 UTIL-LINUX PACKAGE
 M:	Karel Zak <kzak@redhat.com>
 L:	util-linux@vger.kernel.org
@@ -17859,7 +17963,8 @@
 F:	sound/xen/*
 
 XFS FILESYSTEM
-M:	Darrick J. Wong <darrick.wong@oracle.com>
+M:	Chandan Babu R <chandan.babu@oracle.com>
+M:	Darrick J. Wong <djwong@kernel.org>
 M:	linux-xfs@vger.kernel.org
 L:	linux-xfs@vger.kernel.org
 W:	http://xfs.org/
@@ -17873,10 +17978,215 @@
 F:	include/uapi/linux/dqblk_xfs.h
 F:	include/uapi/linux/fsmap.h
 
+XILINX AUDIO FORMATTER (ASoC) DRIVER
+M:	Maruthi Srinivas Bayyavarapu <maruthi.srinivas.bayyavarapu@xilinx.com>
+R:	Vishal Sagar <vishal.sagar@xilinx.com>
+S:	Maintained
+L:	git@xilinx.com
+F:	Documentation/devicetree/bindings/sound/xlnx,audio-formatter.txt
+F:	sound/soc/xilinx/xlnx_formatter_pcm.c
+
+XILINX AXI DMAENGINE DRIVER
+M:	Radhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
+R:	Appana Durga Kedareswara rao <appana.durga.rao@xilinx.com>
+R:	Harini Katakam <harini.katakam@xilinx.com>
+S:	Maintained
+F:	drivers/dma/xilinx/xilinx_dma.c
+F:	Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt
+
 XILINX AXI ETHERNET DRIVER
 M:	Radhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
 S:	Maintained
 F:	drivers/net/ethernet/xilinx/xilinx_axienet*
+F:	Documentation/devicetree/bindings/net/xilinx_axienet.txt
+
+XILINX AXI SPI DRIVER
+M:	Shubhrajyoti Datta <shubhrajyoti.datta@xilinx.com>
+R:	Naga Sureshkumar Relli <naga.sureshkumar.relli@xilinx.com>
+S:	Maintained
+F:	drivers/spi/spi-xilinx.c
+F:	Documentation/devicetree/bindings/spi/spi-xilinx.txt
+
+XILINX FLEXNOC PERFORMANCE MONITOR DRIVER
+M:	Shubhrajyoti Datta <shubhrajyoti.datta@xilinx.com>
+R:	Radhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
+R:	Srinivas Goud <srinivas.goud@xilinx.com>
+S:	Maintained
+F:	drivers/misc/xilinx_flex_pm.c
+F:	Documentation/devicetree/bindings/misc/xlnx,flexnoc-pm.txt
+
+XILINX AXI USB DRIVER
+M:	Anurag Kumar Vulisha <anurag.kumar.vulisha@xilinx.com>
+S:	Maintained
+F:	drivers/usb/gadget/udc/udc-xilinx.c
+F:	Documentation/devicetree/bindings/usb/udc-xilinx.txt
+
+XILINX AXI PERFORMANCE MONITOR DRIVER
+M:	Shubhrajyoti Datta <shubhrajyoti.datta@xilinx.com>
+S:	Maintained
+F:	drivers/uio/uio_xilinx_apm.c
+F:	Documentation/devicetree/bindings/uio/xilinx_apm.txt
+
+XILINX CAN DRIVER
+M:	Shubhrajyoti Datta <shubhrajyoti.datta@xilinx.com>
+R:	Naga Sureshkumar Relli <naga.sureshkumar.relli@xilinx.com>
+R:	Appana Durga Kedareswara rao <appana.durga.rao@xilinx.com>
+S:	Maintained
+F:	drivers/net/can/xilinx_can.c
+F:	Documentation/devicetree/bindings/net/can/xilinx_can.txt
+
+XILINX DMA FRAMEBUFFER READ/WRITE DRIVER
+M:	Vishal Sagar <vishal.sagar@xilinx.com>
+R:	Hyun Kwon <hyun.kwon@xilinx.com>
+S:	Maintained
+L:	git@xilinx.com
+F:	Documentation/devicetree/bindings/dma/xilinx/xilinx_frmbuf.txt
+F:	drivers/dma/xilinx/xilinx_frmbuf.c
+F:	include/linux/dma/xilinx_frmbuf.h
+
+XILINX EMACLITE DRIVER
+M:	Radhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
+R:	Appana Durga Kedareswara rao <appana.durga.rao@xilinx.com>
+R:	Harini Katakam <harini.katakam@xilinx.com>
+S:	Maintained
+F:	drivers/net/ethernet/xilinx/xilinx_emaclite.c
+F:	Documentation/devicetree/bindings/net/xilinx_emaclite.txt
+
+XILINX GMII2RGMII DRIVER
+M:	Harini Katakam <harini.katakam@xilinx.com>
+R:	Radhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
+R:	Appana Durga Kedareswara rao <appana.durga.rao@xilinx.com>
+S:	Maintained
+F:	drivers/net/phy/xilinx_gmii2rgmii.c
+W:	https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18842246/Xilinx+GMII2RGMII+convertor
+
+XILINX GQSPI ZYNQMP SPI DRIVER
+M:	Naga Sureshkumar Relli <naga.sureshkumar.relli@xilinx.com>
+R:	Amit Kumar Mahapatra <amit.kumar-mahapatra@xilinx.com>
+F:	drivers/spi/spi-zynqmp-gqspi.c
+W:	https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18841754/Zynqmp+QSPI+Driver
+
+XILINX I2S AUDIO (ASoC) DRIVER
+M:	Maruthi Srinivas Bayyavarapu <maruthi.srinivas.bayyavarapu@xilinx.com>
+R:	Vishal Sagar <vishal.sagar@xilinx.com>
+S:	Maintained
+L:	git@xilinx.com
+F:	Documentation/devicetree/bindings/sound/xlnx,i2s.txt
+F:	sound/soc/xilinx/xlnx_i2s.c
+
+XILINX MEDIA AXIS SWITCH DRIVER
+M:	Vishal Sagar <vishal.sagar@xilinx.com>
+R:	Hyun Kwon <hyun.kwon@xilinx.com>
+S:	Maintained
+L:	git@xilinx.com
+F:	Documentation/devicetree/bindings/media/xilinx/xlnx,v-axi4s-switch.txt
+F:	drivers/media/platform/xilinx/xilinx-axis-switch.c
+
+XILINX MEDIA CSI2RXSS DRIVER
+M:	Vishal Sagar <vishal.sagar@xilinx.com>
+R:	Hyun Kwon <hyun.kwon@xilinx.com>
+L:	git@xilinx.com
+S:	Maintained
+F:	Documentation/devicetree/bindings/media/xilinx/xlnx,csi2rxss.txt
+F:	drivers/media/platform/xilinx/xilinx-csi2rxss.c
+F:	include/uapi/linux/xilinx-csi2rxss.h
+
+XILINX MEDIA DEMOSAIC DRIVER
+M:	Vishal Sagar <vishal.sagar@xilinx.com>
+R:	Hyun Kwon <hyun.kwon@xilinx.com>
+L:	git@xilinx.com
+S:	Maintained
+F:	Documentation/devicetree/bindings/media/xilinx/xlnx,v-demosaic.txt
+F:	drivers/media/platform/xilinx/xilinx-demosaic.c
+
+XILINX MEDIA GAMMA DRIVER
+M:	Vishal Sagar <vishal.sagar@xilinx.com>
+R:	Hyun Kwon <hyun.kwon@xilinx.com>
+S:	Maintained
+L:	git@xilinx.com
+F:	Documentation/devicetree/bindings/media/xilinx/xlnx,v-gamma-lut.txt
+F:	drivers/media/platform/xilinx/xilinx-gamma.c
+F:	drivers/media/platform/xilinx/xilinx-gamma-coeff.h
+
+XILINX MEDIA SDI RX DRIVER
+M:	Vishal Sagar <vishal.sagar@xilinx.com>
+R:	Hyun Kwon <hyun.kwon@xilinx.com>
+S:	Maintained
+L:	git@xilinx.com
+F:	Documentation/devicetree/bindings/media/xilinx/xlnx,sdirxss.txt
+F:	drivers/media/platform/xilinx/xilinx-sdirxss.c
+F:	include/uapi/linux/xilinx-sdirxss.h
+
+XILINX MEDIA VPSS COLOR SPACE CONVERTER DRIVER
+M:	Vishal Sagar <vishal.sagar@xilinx.com>
+R:	Hyun Kwon <hyun.kwon@xilinx.com>
+L:	git@xilinx.com
+S:	Maintained
+F:	Documentation/devicetree/bindings/media/xilinx/xlnx,v-vpss-csc.txt
+F:	drivers/media/platform/xilinx/xilinx-vpss-csc.c
+
+XILINX MEDIA VPSS SCALER DRIVER
+M:	Vishal Sagar <vishal.sagar@xilinx.com>
+R:	Hyun Kwon <hyun.kwon@xilinx.com>
+S:	Maintained
+L:	git@xilinx.com
+F:	Documentation/devicetree/bindings/media/xilinx/xlnx,v-vpss-scaler.txt
+F:	drivers/media/platform/xilinx/xilinx-vpss-scaler.c
+
+XILINX PL SOUND CARD (ASoC) DRIVER
+M:	Maruthi Srinivas Bayyavarapu <maruthi.srinivas.bayyavarapu@xilinx.com>
+R:	Vishal Sagar <vishal.sagar@xilinx.com>
+S:	Maintained
+L:	git@xilinx.com
+F:	sound/soc/xilinx/xlnx_pl_snd_card.c
+
+XILINX QSPI ZYNQ SPI DRIVER
+M:	Naga Sureshkumar Relli <naga.sureshkumar.relli@xilinx.com>
+R:	Amit Kumar Mahapatra <amit.kumar-mahapatra@xilinx.com>
+F:	drivers/spi/spi-zynq-qspi.c
+W:	https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18842262/Zynq+QSPI+Driver
+
+XILINX RTC ZYNQMP DRIVER
+M:	Neeli Srinivas <srinivas.neeli@xilinx.com>
+R:	Srinivas Goud <srinivas.goud@xilinx.com>
+R:	Shubhrajyoti Datta <shubhrajyoti.datta@xilinx.com>
+S:	Maintained
+F:	drivers/rtc/rtc-zynqmp.c
+
+XILINX SD-FEC IP CORES
+M:	Derek Kiernan <derek.kiernan@xilinx.com>
+M:	Dragan Cvetic <dragan.cvetic@xilinx.com>
+S:	Maintained
+F:	Documentation/devicetree/bindings/misc/xlnx,sd-fec.txt
+F:	Documentation/misc-devices/xilinx_sdfec.rst
+F:	drivers/misc/xilinx_sdfec.c
+F:	drivers/misc/Kconfig
+F:	drivers/misc/Makefile
+F:	include/uapi/misc/xilinx_sdfec.h
+
+XILINX SDI AUDIO (ASoC) DRIVER
+M:	Maruthi Srinivas Bayyavarapu <maruthi.srinivas.bayyavarapu@xilinx.com>
+R:	Vishal Sagar <vishal.sagar@xilinx.com>
+S:	Maintained
+L:	git@xilinx.com
+F:	Documentation/devicetree/bindings/sound/xlnx,v-uhdsdi-audio.txt
+F:	sound/soc/xilinx/xlnx_sdi_audio.c
+
+XILINX SPDIF AUDIO (ASoC) DRIVER
+M:	Maruthi Srinivas Bayyavarapu <maruthi.srinivas.bayyavarapu@xilinx.com>
+R:	Vishal Sagar <vishal.sagar@xilinx.com>
+S:	Maintained
+L:	git@xilinx.com
+F:	Documentation/devicetree/bindings/sound/xlnx,spdif.txt
+F:	sound/soc/xilinx/xlnx_spdif.c
+
+XILINX VERSAL SYSMON DRIVER
+M:	Anand Ashok Dumbre <anand.ashok.dumbre@xilinx.com>
+R:	Dragan Cvetic <dragan.cvetic@xilinx.com>
+L:	git@xilinx.com
+S:	Maintained
+F:	Documentation/devicetree/bindings/iio/adc/xlnx,versal-sysmon.yaml
+F:	drivers/iio/adc/versal-sysmon.c
 
 XILINX UARTLITE SERIAL DRIVER
 M:	Peter Korsgaard <jacmet@sunsite.dk>
@@ -17884,6 +18194,12 @@
 S:	Maintained
 F:	drivers/tty/serial/uartlite.c
 
+XILINX UARTPS DRIVER
+M:	Shubhrajyoti Datta <shubhrajyoti.datta@xilinx.com>
+S:	Maintained
+F:	drivers/tty/serial/xilinx_uartps.c
+F:	Documentation/devicetree/bindings/serial/cdns,uart.txt
+
 XILINX VIDEO IP CORES
 M:	Hyun Kwon <hyun.kwon@xilinx.com>
 M:	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
@@ -17894,6 +18210,79 @@
 F:	drivers/media/platform/xilinx/
 F:	include/uapi/linux/xilinx-v4l2-controls.h
 
+XILINX ZYNQ FPGA MANAGER DRIVER
+M:	Nava Kishore Manne <nava.manne@xilinx.com>
+R:	Appana Durga Kedareswara rao <appana.durga.rao@xilinx.com>
+S:	Maintained
+F:	drivers/fpga/zynq-fpga.c
+F:	Documentation/devicetree/bindings/fpga/xilinx-zynq-fpga-mgr.txt
+
+XILINX ZYNQMP AES DRIVER
+M:	Kalyani Akula <kalyani.akula@xilinx.com>
+M:	Nava Kishore Manne <nava.manne@xilinx.com>
+R:	Appana Durga Kedareswara rao <appana.durga.rao@xilinx.com>
+S:	Maintained
+F:	drivers/crypto/zynqmp-aes.c
+F:	Documentation/devicetree/bindings/crypto/xlnx,zynqmp-aes.txt
+
+XILINX ZYNQMP DMAENGINE DRIVER
+M:	Appana Durga Kedareswara rao <appana.durga.rao@xilinx.com>
+R:	Radhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
+R:	Harini Katakam <harini.katakam@xilinx.com>
+S:	Maintained
+F:	drivers/dma/xilinx/zynqmp_dma.c
+F:	Documentation/devicetree/bindings/dma/xilinx/zynqmp_dma.txt
+
+XILINX ZYNQMP FPGA MANAGER DRIVER
+M:	Nava Kishore Manne <nava.manne@xilinx.com>
+R:	Appana Durga Kedareswara rao <appana.durga.rao@xilinx.com>
+S:	Maintained
+F:	drivers/fpga/zynqmp-fpga.c
+F:	Documentation/devicetree/bindings/fpga/xilinx-zynqmp-fpga-mgr.txt
+
+ZYNQMP IPI MAILBOX CONTROLLER DRIVER
+M:	Wendy Liang <wendy.liang@xilinx.com>
+S:	Maintained
+F:	drivers/mailbox/zynqmp-ipi-mailbox.c
+F:	include/linux/mailbox/zynqmp-ipi-message.h
+F:	Documentation/devicetree/bindings/mailbox/xlnx,zynqmp-ipi-mailbox.txt
+
+XILINX VERSAL DDRMC EDAC DRIVER
+M:	Sai Krishna Potthuri <lakshmi.sai.krishna.potthuri@xilinx.com>
+R:	Michal Simek <michal.simek@xilinx.com>
+R:	Srinivas Goud <srinivas.goud@xilinx.com>
+S:	Maintained
+F:	drivers/edac/xilinx_ddrmc_edac.c
+F:	Documentation/devicetree/bindings/edac/xlnx,versal-ddrmc-edac.yaml
+
+XILINX ZYNQMP PHY DRIVER
+M:	Anurag Kumar Vulisha <anurag.kumar.vulisha@xilinx.com>
+S:	Maintained
+F:	drivers/phy/phy-zynqmp.c
+F:	Documentation/devicetree/bindings/phy/phy-zynqmp.txt
+
+XILINX ZYNQMP R5 REMOTE PROCESSOR (REMOTEPROC) SUBSYSTEM
+M:	Wendy Liang <wendy.liang@xilinx.com>
+S:	Maintained
+F:	Documentation/devicetree/bindings/remoteproc/xilinx,zynqmp-r5-remoteproc.txt
+F:	drivers/remoteproc/zynqmp_r5_remoteproc.c
+
+XILINX ZYNQMP RSA DRIVER
+M:	Nava Kishore Manne <nava.manne@xilinx.com>
+M:	Kalyani Akula <kalyani.akula@xilinx.com>
+R:	Appana Durga Kedareswara rao <appana.durga.rao@xilinx.com>
+S:	Maintained
+F:	drivers/crypto/zynqmp-rsa.c
+F:	Documentation/devicetree/bindings/crypto/zynqmp-rsa.txt
+
+XILINX ZYNQMP SHA DRIVER
+M:	Nava Kishore Manne <nava.manne@xilinx.com>
+M:	Kalyani Akula <kalyani.akula@xilinx.com>
+R:	Appana Durga Kedareswara rao <appana.durga.rao@xilinx.com>
+S:	Maintained
+F:	drivers/crypto/zynqmp-sha.c
+F:	Documentation/devicetree/bindings/crypto/zynqmp-sha.txt
+
 XILINX SD-FEC IP CORES
 M:	Derek Kiernan <derek.kiernan@xilinx.com>
 M:	Dragan Cvetic <dragan.cvetic@xilinx.com>
--- linux-xilinx-zynqmp-5.4.0.orig/Makefile
+++ linux-xilinx-zynqmp-5.4.0/Makefile
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 VERSION = 5
 PATCHLEVEL = 4
-SUBLEVEL = 0
+SUBLEVEL = 292
 EXTRAVERSION =
 NAME = Kleptomaniac Octopus
 
@@ -89,9 +89,16 @@
 
 # If the user is running make -s (silent mode), suppress echoing of
 # commands
+# make-4.0 (and later) keep single letter options in the 1st word of MAKEFLAGS.
 
-ifneq ($(findstring s,$(filter-out --%,$(MAKEFLAGS))),)
-  quiet=silent_
+ifeq ($(filter 3.%,$(MAKE_VERSION)),)
+silence:=$(findstring s,$(firstword -$(MAKEFLAGS)))
+else
+silence:=$(findstring s,$(filter-out --%,$(MAKEFLAGS)))
+endif
+
+ifeq ($(silence),s)
+quiet=silent_
 endif
 
 export quiet Q KBUILD_VERBOSE
@@ -206,6 +213,20 @@
   KBUILD_CHECKSRC = 0
 endif
 
+# Call message checker as part of the C compilation
+#
+# Use 'make D=1' to enable checking
+# Use 'make D=2' to create the message catalog
+
+ifdef D
+  ifeq ("$(origin D)", "command line")
+    KBUILD_KMSG_CHECK = $(D)
+  endif
+endif
+ifndef KBUILD_KMSG_CHECK
+  KBUILD_KMSG_CHECK = 0
+endif
+
 # Use make M=dir or set the environment variable KBUILD_EXTMOD to specify the
 # directory of external module to build. Setting M= takes precedence.
 ifeq ("$(origin M)", "command line")
@@ -394,8 +415,13 @@
 HOST_LFS_LDFLAGS := $(shell getconf LFS_LDFLAGS 2>/dev/null)
 HOST_LFS_LIBS := $(shell getconf LFS_LIBS 2>/dev/null)
 
-HOSTCC       = gcc
-HOSTCXX      = g++
+ifneq ($(LLVM),)
+HOSTCC	= clang
+HOSTCXX	= clang++
+else
+HOSTCC	= gcc
+HOSTCXX	= g++
+endif
 KBUILD_HOSTCFLAGS   := -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 \
 		-fomit-frame-pointer -std=gnu89 $(HOST_LFS_CFLAGS) \
 		$(HOSTCFLAGS)
@@ -404,31 +430,49 @@
 KBUILD_HOSTLDLIBS   := $(HOST_LFS_LIBS) $(HOSTLDLIBS)
 
 # Make variables (CC, etc...)
-AS		= $(CROSS_COMPILE)as
-LD		= $(CROSS_COMPILE)ld
-CC		= $(CROSS_COMPILE)gcc
 CPP		= $(CC) -E
+ifneq ($(LLVM),)
+CC		= clang
+LD		= ld.lld
+AR		= llvm-ar
+NM		= llvm-nm
+OBJCOPY		= llvm-objcopy
+OBJDUMP		= llvm-objdump
+READELF		= llvm-readelf
+OBJSIZE		= llvm-size
+STRIP		= llvm-strip
+else
+CC		= $(CROSS_COMPILE)gcc
+LD		= $(CROSS_COMPILE)ld
 AR		= $(CROSS_COMPILE)ar
 NM		= $(CROSS_COMPILE)nm
-STRIP		= $(CROSS_COMPILE)strip
 OBJCOPY		= $(CROSS_COMPILE)objcopy
 OBJDUMP		= $(CROSS_COMPILE)objdump
+READELF		= $(CROSS_COMPILE)readelf
 OBJSIZE		= $(CROSS_COMPILE)size
+STRIP		= $(CROSS_COMPILE)strip
+endif
 PAHOLE		= pahole
 LEX		= flex
 YACC		= bison
 AWK		= awk
 INSTALLKERNEL  := installkernel
-DEPMOD		= /sbin/depmod
+DEPMOD		= depmod
 PERL		= perl
 PYTHON		= python
-PYTHON2		= python2
 PYTHON3		= python3
 CHECK		= sparse
 BASH		= bash
+KGZIP		= gzip
+KBZIP2		= bzip2
+KLZOP		= lzop
+LZMA		= lzma
+LZ4		= lz4c
+XZ		= xz
 
 CHECKFLAGS     := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \
 		  -Wbitwise -Wno-return-void -Wno-unknown-attribute $(CF)
+KMSG_CHECK	= $(srctree)/scripts/kmsg-doc
 NOSTDINC_FLAGS :=
 CFLAGS_MODULE   =
 AFLAGS_MODULE   =
@@ -437,6 +481,13 @@
 AFLAGS_KERNEL	=
 LDFLAGS_vmlinux =
 
+# Prefer linux-backports-modules
+ifneq ($(KBUILD_SRC),)
+ifneq ($(shell if test -e $(KBUILD_OUTPUT)/ubuntu-build; then echo yes; fi),yes)
+UBUNTUINCLUDE := -I/usr/src/linux-headers-lbm-$(KERNELRELEASE)
+endif
+endif
+
 # Use USERINCLUDE when you must reference the UAPI directories only.
 USERINCLUDE    := \
 		-I$(srctree)/arch/$(SRCARCH)/include/uapi \
@@ -448,17 +499,21 @@
 # Use LINUXINCLUDE when you must reference the include/ directory.
 # Needed to be compatible with the O= option
 LINUXINCLUDE    := \
+		$(UBUNTUINCLUDE) \
 		-I$(srctree)/arch/$(SRCARCH)/include \
 		-I$(objtree)/arch/$(SRCARCH)/include/generated \
 		$(if $(building_out_of_srctree),-I$(srctree)/include) \
 		-I$(objtree)/include \
 		$(USERINCLUDE)
 
+# UBUNTU: Include our third party driver stuff too
+LINUXINCLUDE   += -Iubuntu/include $(if $(KBUILD_SRC),-I$(srctree)/ubuntu/include)
+
 KBUILD_AFLAGS   := -D__ASSEMBLY__ -fno-PIE
 KBUILD_CFLAGS   := -Wall -Wundef -Werror=strict-prototypes -Wno-trigraphs \
 		   -fno-strict-aliasing -fno-common -fshort-wchar -fno-PIE \
 		   -Werror=implicit-function-declaration -Werror=implicit-int \
-		   -Wno-format-security \
+		   -Werror=return-type -Wno-format-security \
 		   -std=gnu89
 KBUILD_CPPFLAGS := -D__KERNEL__
 KBUILD_AFLAGS_KERNEL :=
@@ -471,15 +526,17 @@
 GCC_PLUGINS_CFLAGS :=
 CLANG_FLAGS :=
 
-export ARCH SRCARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE AS LD CC
-export CPP AR NM STRIP OBJCOPY OBJDUMP OBJSIZE PAHOLE LEX YACC AWK INSTALLKERNEL
-export PERL PYTHON PYTHON2 PYTHON3 CHECK CHECKFLAGS MAKE UTS_MACHINE HOSTCXX
+export ARCH SRCARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE LD CC
+export CPP AR NM STRIP OBJCOPY OBJDUMP OBJSIZE READELF PAHOLE LEX YACC AWK INSTALLKERNEL
+export PERL PYTHON PYTHON3 CHECK CHECKFLAGS MAKE UTS_MACHINE HOSTCXX
+export KGZIP KBZIP2 KLZOP LZMA LZ4 XZ
 export KBUILD_HOSTCXXFLAGS KBUILD_HOSTLDFLAGS KBUILD_HOSTLDLIBS LDFLAGS_MODULE
 
 export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS KBUILD_LDFLAGS
 export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE
 export CFLAGS_KASAN CFLAGS_KASAN_NOSANITIZE CFLAGS_UBSAN
 export KBUILD_AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
+export KBUILD_KMSG_CHECK KMSG_CHECK
 export KBUILD_AFLAGS_MODULE KBUILD_CFLAGS_MODULE KBUILD_LDFLAGS_MODULE
 export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL
 
@@ -528,13 +585,13 @@
 ifneq ($(CROSS_COMPILE),)
 CLANG_FLAGS	+= --target=$(notdir $(CROSS_COMPILE:%-=%))
 GCC_TOOLCHAIN_DIR := $(dir $(shell which $(CROSS_COMPILE)elfedit))
-CLANG_FLAGS	+= --prefix=$(GCC_TOOLCHAIN_DIR)
+CLANG_FLAGS	+= --prefix=$(GCC_TOOLCHAIN_DIR)$(notdir $(CROSS_COMPILE))
 GCC_TOOLCHAIN	:= $(realpath $(GCC_TOOLCHAIN_DIR)/..)
 endif
 ifneq ($(GCC_TOOLCHAIN),)
 CLANG_FLAGS	+= --gcc-toolchain=$(GCC_TOOLCHAIN)
 endif
-ifeq ($(shell $(AS) --version 2>&1 | head -n 1 | grep clang),)
+ifneq ($(LLVM_IAS),1)
 CLANG_FLAGS	+= -no-integrated-as
 endif
 CLANG_FLAGS	+= -Werror=unknown-warning-option
@@ -587,12 +644,8 @@
 KBUILD_BUILTIN := 1
 
 # If we have only "make modules", don't compile built-in objects.
-# When we're building modules with modversions, we need to consider
-# the built-in objects during the descend as well, in order to
-# make sure the checksums are up to date before we record them.
-
 ifeq ($(MAKECMDGOALS),modules)
-  KBUILD_BUILTIN := $(if $(CONFIG_MODVERSIONS),1)
+  KBUILD_BUILTIN :=
 endif
 
 # If we have "make <whatever> modules", compile modules
@@ -616,9 +669,8 @@
 ifeq ($(KBUILD_EXTMOD),)
 # Objects we will link into vmlinux / subdirs we need to visit
 init-y		:= init/
-drivers-y	:= drivers/ sound/
+drivers-y	:= drivers/ sound/ ubuntu/
 drivers-$(CONFIG_SAMPLES) += samples/
-drivers-$(CONFIG_KERNEL_HEADER_TEST) += include/
 net-y		:= net/
 libs-y		:= lib/
 core-y		:= usr/
@@ -708,12 +760,9 @@
 KBUILD_CFLAGS += -Os
 endif
 
-ifdef CONFIG_CC_DISABLE_WARN_MAYBE_UNINITIALIZED
-KBUILD_CFLAGS   += -Wno-maybe-uninitialized
-endif
-
 # Tell gcc to never replace conditional load with a non-conditional one
 KBUILD_CFLAGS	+= $(call cc-option,--param=allow-store-data-races=0)
+KBUILD_CFLAGS	+= $(call cc-option,-fno-allow-store-data-races)
 
 include scripts/Makefile.kcov
 include scripts/Makefile.gcc-plugins
@@ -750,17 +799,21 @@
 KBUILD_CFLAGS += -mno-global-merge
 else
 
-# These warnings generated too much noise in a regular build.
-# Use make W=1 to enable them (see scripts/Makefile.extrawarn)
-KBUILD_CFLAGS += -Wno-unused-but-set-variable
-
 # Warn about unmarked fall-throughs in switch statement.
 # Disabled for clang while comment to attribute conversion happens and
 # https://github.com/ClangBuiltLinux/linux/issues/636 is discussed.
 KBUILD_CFLAGS += $(call cc-option,-Wimplicit-fallthrough,)
 endif
 
+# These warnings generated too much noise in a regular build.
+# Use make W=1 to enable them (see scripts/Makefile.extrawarn)
+KBUILD_CFLAGS += $(call cc-disable-warning, unused-but-set-variable)
+
 KBUILD_CFLAGS += $(call cc-disable-warning, unused-const-variable)
+
+# These result in bogus false positives
+KBUILD_CFLAGS += $(call cc-disable-warning, dangling-pointer)
+
 ifdef CONFIG_FRAME_POINTER
 KBUILD_CFLAGS	+= -fno-omit-frame-pointer -fno-optimize-sibling-calls
 else
@@ -787,8 +840,13 @@
 else
 DEBUG_CFLAGS	+= -g
 endif
+ifeq ($(LLVM_IAS),1)
+KBUILD_AFLAGS	+= -g
+else
 KBUILD_AFLAGS	+= -Wa,-gdwarf-2
 endif
+endif
+
 ifdef CONFIG_DEBUG_INFO_DWARF4
 DEBUG_CFLAGS	+= -gdwarf-4
 endif
@@ -861,6 +919,17 @@
 # disable stringop warnings in gcc 8+
 KBUILD_CFLAGS += $(call cc-disable-warning, stringop-truncation)
 
+# We'll want to enable this eventually, but it's not going away for 5.7 at least
+KBUILD_CFLAGS += $(call cc-disable-warning, zero-length-bounds)
+KBUILD_CFLAGS += $(call cc-disable-warning, array-bounds)
+KBUILD_CFLAGS += $(call cc-disable-warning, stringop-overflow)
+
+# Another good warning that we'll want to enable eventually
+KBUILD_CFLAGS += $(call cc-disable-warning, restrict)
+
+# Enabled with W=2, disabled by default as noisy
+KBUILD_CFLAGS += $(call cc-disable-warning, maybe-uninitialized)
+
 # disable invalid "can't wrap" optimizations for signed / pointers
 KBUILD_CFLAGS	+= $(call cc-option,-fno-strict-overflow)
 
@@ -891,12 +960,6 @@
 # change __FILE__ to the relative path from the srctree
 KBUILD_CFLAGS	+= $(call cc-option,-fmacro-prefix-map=$(srctree)/=)
 
-# ensure -fcf-protection is disabled when using retpoline as it is
-# incompatible with -mindirect-branch=thunk-extern
-ifdef CONFIG_RETPOLINE
-KBUILD_CFLAGS += $(call cc-option,-fcf-protection=none)
-endif
-
 include scripts/Makefile.kasan
 include scripts/Makefile.extrawarn
 include scripts/Makefile.ubsan
@@ -909,12 +972,20 @@
 KBUILD_LDFLAGS_MODULE += --build-id
 LDFLAGS_vmlinux += --build-id
 
+KBUILD_LDFLAGS	+= -z noexecstack
+KBUILD_LDFLAGS	+= $(call ld-option,--no-warn-rwx-segments)
+
 ifeq ($(CONFIG_STRIP_ASM_SYMS),y)
 LDFLAGS_vmlinux	+= $(call ld-option, -X,)
 endif
 
 ifeq ($(CONFIG_RELR),y)
-LDFLAGS_vmlinux	+= --pack-dyn-relocs=relr
+LDFLAGS_vmlinux	+= --pack-dyn-relocs=relr --use-android-relr-tags
+endif
+
+# userspace programs are linked via the compiler, use the correct linker
+ifeq ($(CONFIG_CC_IS_CLANG)$(CONFIG_LD_IS_LLD),yy)
+KBUILD_USERLDFLAGS += $(call cc-option, --ld-path=$(LD))
 endif
 
 # make the checker run with the right architecture
@@ -978,10 +1049,10 @@
 mod_compress_cmd = true
 ifdef CONFIG_MODULE_COMPRESS
   ifdef CONFIG_MODULE_COMPRESS_GZIP
-    mod_compress_cmd = gzip -n -f
+    mod_compress_cmd = $(KGZIP) -n -f
   endif # CONFIG_MODULE_COMPRESS_GZIP
   ifdef CONFIG_MODULE_COMPRESS_XZ
-    mod_compress_cmd = xz -f
+    mod_compress_cmd = $(XZ) -f
   endif # CONFIG_MODULE_COMPRESS_XZ
 endif # CONFIG_MODULE_COMPRESS
 export mod_compress_cmd
@@ -999,7 +1070,7 @@
 
 ifdef CONFIG_STACK_VALIDATION
   has_libelf := $(call try-run,\
-		echo "int main() {}" | $(HOSTCC) -xc -o /dev/null $(HOST_LIBELF_LIBS) -,1,0)
+		echo "int main() {}" | $(HOSTCC) $(KBUILD_HOSTLDFLAGS) -xc -o /dev/null $(HOST_LIBELF_LIBS) -,1,0)
   ifeq ($(has_libelf),1)
     objtool_target := tools/objtool FORCE
   else
@@ -1050,7 +1121,7 @@
 ifdef CONFIG_TRIM_UNUSED_KSYMS
 autoksyms_recursive: descend modules.order
 	$(Q)$(CONFIG_SHELL) $(srctree)/scripts/adjust_autoksyms.sh \
-	  "$(MAKE) -f $(srctree)/Makefile vmlinux"
+	  "$(MAKE) -f $(srctree)/Makefile autoksyms_recursive"
 endif
 
 # For the kernel to actually contain only the needed exported symbols,
@@ -1152,11 +1223,19 @@
 endef
 
 define filechk_version.h
-	echo \#define LINUX_VERSION_CODE $(shell                         \
-	expr $(VERSION) \* 65536 + 0$(PATCHLEVEL) \* 256 + 0$(SUBLEVEL)); \
-	echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))'
+	if [ $(SUBLEVEL) -gt 255 ]; then                                 \
+		echo \#define LINUX_VERSION_CODE $(shell                 \
+		expr $(VERSION) \* 65536 + $(PATCHLEVEL) \* 256 + 255); \
+	else                                                             \
+		echo \#define LINUX_VERSION_CODE $(shell                 \
+		expr $(VERSION) \* 65536 + $(PATCHLEVEL) \* 256 + $(SUBLEVEL)); \
+	fi;                                                              \
+	echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) +  \
+	((c) > 255 ? 255 : (c)))'
 endef
 
+$(version_h): PATCHLEVEL := $(if $(PATCHLEVEL), $(PATCHLEVEL), 0)
+$(version_h): SUBLEVEL := $(if $(SUBLEVEL), $(SUBLEVEL), 0)
 $(version_h): FORCE
 	$(call filechk,version.h)
 	$(Q)rm -f $(old_version_h)
@@ -1195,20 +1274,17 @@
 	  $(error Headers not exportable for the $(SRCARCH) architecture))
 	$(Q)$(MAKE) $(hdr-inst)=include/uapi
 	$(Q)$(MAKE) $(hdr-inst)=arch/$(SRCARCH)/include/uapi
+	$(Q)$(MAKE) $(hdr-inst)=ubuntu/include dst=include oldheaders=
 
+# Deprecated. It is no-op now.
 PHONY += headers_check
-headers_check: headers
-	$(Q)$(MAKE) $(hdr-inst)=include/uapi HDRCHECK=1
-	$(Q)$(MAKE) $(hdr-inst)=arch/$(SRCARCH)/include/uapi HDRCHECK=1
+headers_check:
+	@:
 
 ifdef CONFIG_HEADERS_INSTALL
 prepare: headers
 endif
 
-ifdef CONFIG_HEADERS_CHECK
-all: headers_check
-endif
-
 PHONY += scripts_unifdef
 scripts_unifdef: scripts_basic
 	$(Q)$(MAKE) $(build)=scripts scripts/unifdef
@@ -1242,12 +1318,16 @@
 %.dtb: include/config/kernel.release scripts_dtc
 	$(Q)$(MAKE) $(build)=$(dtstree) $(dtstree)/$@
 
-PHONY += dtbs dtbs_install dt_binding_check
-dtbs dtbs_check: include/config/kernel.release scripts_dtc
+PHONY += dtbs dtbs_install dtbs_check
+dtbs: include/config/kernel.release scripts_dtc
 	$(Q)$(MAKE) $(build)=$(dtstree)
 
+ifneq ($(filter dtbs_check, $(MAKECMDGOALS)),)
+dtbs: dt_binding_check
+endif
+
 dtbs_check: export CHECK_DTBS=1
-dtbs_check: dt_binding_check
+dtbs_check: dtbs
 
 dtbs_install:
 	$(Q)$(MAKE) $(dtbinst)=$(dtstree)
@@ -1262,6 +1342,7 @@
 scripts_dtc: scripts_basic
 	$(Q)$(MAKE) $(build)=scripts/dtc
 
+PHONY += dt_binding_check
 dt_binding_check: scripts_dtc
 	$(Q)$(MAKE) $(build)=Documentation/devicetree/bindings
 
@@ -1274,6 +1355,13 @@
 
 all: modules
 
+# When we're building modules with modversions, we need to consider
+# the built-in objects during the descend as well, in order to
+# make sure the checksums are up to date before we record them.
+ifdef CONFIG_MODVERSIONS
+  KBUILD_BUILTIN := 1
+endif
+
 # Build modules
 #
 # A module can be listed more than once in obj-m resulting in
@@ -1476,7 +1564,6 @@
 	@echo  '  versioncheck    - Sanity check on version.h usage'
 	@echo  '  includecheck    - Check for duplicate included header files'
 	@echo  '  export_report   - List the usages of all exported symbols'
-	@echo  '  headers_check   - Sanity check on exported headers'
 	@echo  '  headerdep       - Detect inclusion cycles in headers'
 	@echo  '  coccicheck      - Check with Coccinelle'
 	@echo  ''
@@ -1641,6 +1728,50 @@
 PHONY += prepare
 endif # KBUILD_EXTMOD
 
+# Single targets
+# ---------------------------------------------------------------------------
+# To build individual files in subdirectories, you can do like this:
+#
+#   make foo/bar/baz.s
+#
+# The supported suffixes for single-target are listed in 'single-targets'
+#
+# To build only under specific subdirectories, you can do like this:
+#
+#   make foo/bar/baz/
+
+ifdef single-build
+
+# .ko is special because modpost is needed
+single-ko := $(sort $(filter %.ko, $(MAKECMDGOALS)))
+single-no-ko := $(sort $(patsubst %.ko,%.mod, $(MAKECMDGOALS)))
+
+$(single-ko): single_modpost
+	@:
+$(single-no-ko): descend
+	@:
+
+ifeq ($(KBUILD_EXTMOD),)
+# For the single build of in-tree modules, use a temporary file to avoid
+# the situation of modules_install installing an invalid modules.order.
+MODORDER := .modules.tmp
+endif
+
+PHONY += single_modpost
+single_modpost: $(single-no-ko)
+	$(Q){ $(foreach m, $(single-ko), echo $(extmod-prefix)$m;) } > $(MODORDER)
+	$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
+
+KBUILD_MODULES := 1
+
+export KBUILD_SINGLE_TARGETS := $(addprefix $(extmod-prefix), $(single-no-ko))
+
+# trim unrelated directories
+build-dirs := $(foreach d, $(build-dirs), \
+			$(if $(filter $(d)/%, $(KBUILD_SINGLE_TARGETS)), $(d)))
+
+endif
+
 # Handle descending into subdirectories listed in $(build-dirs)
 # Preset locale variables to speed up the build process. Limit locale
 # tweaks to this spot to avoid wrong language settings when running
@@ -1649,7 +1780,9 @@
 PHONY += descend $(build-dirs)
 descend: $(build-dirs)
 $(build-dirs): prepare
-	$(Q)$(MAKE) $(build)=$@ single-build=$(single-build) need-builtin=1 need-modorder=1
+	$(Q)$(MAKE) $(build)=$@ \
+	single-build=$(if $(filter-out $@/, $(single-no-ko)),1) \
+	need-builtin=1 need-modorder=1
 
 clean-dirs := $(addprefix _clean_, $(clean-dirs))
 PHONY += $(clean-dirs) clean
@@ -1753,50 +1886,6 @@
 	$(Q)mkdir -p $(objtree)/tools
 	$(Q)$(MAKE) LDFLAGS= MAKEFLAGS="$(tools_silent) $(filter --j% -j,$(MAKEFLAGS))" O=$(abspath $(objtree)) subdir=tools -C $(srctree)/tools/ $*
 
-# Single targets
-# ---------------------------------------------------------------------------
-# To build individual files in subdirectories, you can do like this:
-#
-#   make foo/bar/baz.s
-#
-# The supported suffixes for single-target are listed in 'single-targets'
-#
-# To build only under specific subdirectories, you can do like this:
-#
-#   make foo/bar/baz/
-
-ifdef single-build
-
-single-all := $(filter $(single-targets), $(MAKECMDGOALS))
-
-# .ko is special because modpost is needed
-single-ko := $(sort $(filter %.ko, $(single-all)))
-single-no-ko := $(sort $(patsubst %.ko,%.mod, $(single-all)))
-
-$(single-ko): single_modpost
-	@:
-$(single-no-ko): descend
-	@:
-
-ifeq ($(KBUILD_EXTMOD),)
-# For the single build of in-tree modules, use a temporary file to avoid
-# the situation of modules_install installing an invalid modules.order.
-MODORDER := .modules.tmp
-endif
-
-PHONY += single_modpost
-single_modpost: $(single-no-ko)
-	$(Q){ $(foreach m, $(single-ko), echo $(extmod-prefix)$m;) } > $(MODORDER)
-	$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
-
-KBUILD_MODULES := 1
-
-export KBUILD_SINGLE_TARGETS := $(addprefix $(extmod-prefix), $(single-no-ko))
-
-single-build = $(if $(filter-out $@/, $(single-no-ko)),1)
-
-endif
-
 # FIXME Should go into a make.lib or something
 # ===========================================================================
 
--- linux-xilinx-zynqmp-5.4.0.orig/Ubuntu.md
+++ linux-xilinx-zynqmp-5.4.0/Ubuntu.md
@@ -0,0 +1,7 @@
+Name:    linux-xilinx-zynqmp
+Version: 5.4.0
+Series:  20.04 (focal)
+Description:
+    This is the source code for the Ubuntu linux kernel for the 20.04 series. This
+    source tree is used to produce the flavours: xilinx-zynqmp.
+    This kernel is configured to support specific Xilinx platforms.
--- linux-xilinx-zynqmp-5.4.0.orig/arch/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/Kconfig
@@ -131,6 +131,22 @@
 	    managed by the kernel and kept transparent to the probed
 	    application. )
 
+config HAVE_64BIT_ALIGNED_ACCESS
+	def_bool 64BIT && !HAVE_EFFICIENT_UNALIGNED_ACCESS
+	help
+	  Some architectures require 64 bit accesses to be 64 bit
+	  aligned, which also requires structs containing 64 bit values
+	  to be 64 bit aligned too. This includes some 32 bit
+	  architectures which can do 64 bit accesses, as well as 64 bit
+	  architectures without unaligned access.
+
+	  This symbol should be selected by an architecture if 64 bit
+	  accesses are required to be 64 bit aligned in this way even
+	  though it is not a 64 bit architecture.
+
+	  See Documentation/unaligned-memory-access.txt for more
+	  information on the topic of unaligned memory accesses.
+
 config HAVE_EFFICIENT_UNALIGNED_ACCESS
 	bool
 	help
@@ -255,6 +271,9 @@
 	select ARCH_HAS_DMA_PREP_COHERENT
 	bool
 
+config ARCH_HAS_CPU_FINALIZE_INIT
+	bool
+
 # Select if arch init_task must go in the __init_task_data section
 config ARCH_TASK_STRUCT_ON_STACK
        bool
@@ -396,15 +415,22 @@
 config HAVE_RCU_TABLE_FREE
 	bool
 
-config HAVE_RCU_TABLE_NO_INVALIDATE
+config HAVE_MMU_GATHER_PAGE_SIZE
 	bool
 
-config HAVE_MMU_GATHER_PAGE_SIZE
+config MMU_GATHER_NO_RANGE
 	bool
 
 config HAVE_MMU_GATHER_NO_GATHER
 	bool
 
+config ARCH_WANT_IRQS_OFF_ACTIVATE_MM
+	bool
+	help
+	  Temporary select until all architectures can be converted to have
+	  irqs disabled over activate_mm. Architectures that do IPI based TLB
+	  shootdowns should enable this.
+
 config ARCH_HAVE_NMI_SAFE_CMPXCHG
 	bool
 
@@ -892,27 +918,6 @@
 config ARCH_HAS_PHYS_TO_DMA
 	bool
 
-config ARCH_HAS_REFCOUNT
-	bool
-	help
-	  An architecture selects this when it has implemented refcount_t
-	  using open coded assembly primitives that provide an optimized
-	  refcount_t implementation, possibly at the expense of some full
-	  refcount state checks of CONFIG_REFCOUNT_FULL=y.
-
-	  The refcount overflow check behavior, however, must be retained.
-	  Catching overflows is the primary security concern for protecting
-	  against bugs in reference counts.
-
-config REFCOUNT_FULL
-	bool "Perform full reference count validation at the expense of speed"
-	help
-	  Enabling this switches the refcounting infrastructure from a fast
-	  unchecked atomic_t implementation to a fully state checked
-	  implementation, which can be (slightly) slower but provides protections
-	  against various use-after-free conditions that can be used in
-	  security flaw exploits.
-
 config HAVE_ARCH_COMPILER_H
 	bool
 	help
--- linux-xilinx-zynqmp-5.4.0.orig/arch/alpha/configs/defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/alpha/configs/defconfig
@@ -36,7 +36,6 @@
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_SCSI_AIC7XXX=m
 CONFIG_AIC7XXX_CMDS_PER_DEVICE=253
 # CONFIG_AIC7XXX_DEBUG_ENABLE is not set
--- linux-xilinx-zynqmp-5.4.0.orig/arch/alpha/include/asm/io.h
+++ linux-xilinx-zynqmp-5.4.0/arch/alpha/include/asm/io.h
@@ -61,7 +61,7 @@
  * Change virtual addresses to physical addresses and vv.
  */
 #ifdef USE_48_BIT_KSEG
-static inline unsigned long virt_to_phys(void *address)
+static inline unsigned long virt_to_phys(volatile void *address)
 {
 	return (unsigned long)address - IDENT_ADDR;
 }
@@ -71,7 +71,7 @@
 	return (void *) (address + IDENT_ADDR);
 }
 #else
-static inline unsigned long virt_to_phys(void *address)
+static inline unsigned long virt_to_phys(volatile void *address)
 {
         unsigned long phys = (unsigned long)address;
 
@@ -107,7 +107,7 @@
 extern unsigned long __direct_map_base;
 extern unsigned long __direct_map_size;
 
-static inline unsigned long __deprecated virt_to_bus(void *address)
+static inline unsigned long __deprecated virt_to_bus(volatile void *address)
 {
 	unsigned long phys = virt_to_phys(address);
 	unsigned long bus = phys + __direct_map_base;
@@ -322,14 +322,18 @@
 #if IO_CONCAT(__IO_PREFIX,trivial_io_bw)
 extern inline unsigned int ioread8(void __iomem *addr)
 {
-	unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread8)(addr);
+	unsigned int ret;
+	mb();
+	ret = IO_CONCAT(__IO_PREFIX,ioread8)(addr);
 	mb();
 	return ret;
 }
 
 extern inline unsigned int ioread16(void __iomem *addr)
 {
-	unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread16)(addr);
+	unsigned int ret;
+	mb();
+	ret = IO_CONCAT(__IO_PREFIX,ioread16)(addr);
 	mb();
 	return ret;
 }
@@ -370,7 +374,9 @@
 #if IO_CONCAT(__IO_PREFIX,trivial_io_lq)
 extern inline unsigned int ioread32(void __iomem *addr)
 {
-	unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread32)(addr);
+	unsigned int ret;
+	mb();
+	ret = IO_CONCAT(__IO_PREFIX,ioread32)(addr);
 	mb();
 	return ret;
 }
@@ -415,14 +421,18 @@
 
 extern inline u8 readb(const volatile void __iomem *addr)
 {
-	u8 ret = __raw_readb(addr);
+	u8 ret;
+	mb();
+	ret = __raw_readb(addr);
 	mb();
 	return ret;
 }
 
 extern inline u16 readw(const volatile void __iomem *addr)
 {
-	u16 ret = __raw_readw(addr);
+	u16 ret;
+	mb();
+	ret = __raw_readw(addr);
 	mb();
 	return ret;
 }
@@ -463,14 +473,18 @@
 
 extern inline u32 readl(const volatile void __iomem *addr)
 {
-	u32 ret = __raw_readl(addr);
+	u32 ret;
+	mb();
+	ret = __raw_readl(addr);
 	mb();
 	return ret;
 }
 
 extern inline u64 readq(const volatile void __iomem *addr)
 {
-	u64 ret = __raw_readq(addr);
+	u64 ret;
+	mb();
+	ret = __raw_readq(addr);
 	mb();
 	return ret;
 }
@@ -488,10 +502,10 @@
 }
 #endif
 
-#define ioread16be(p) be16_to_cpu(ioread16(p))
-#define ioread32be(p) be32_to_cpu(ioread32(p))
-#define iowrite16be(v,p) iowrite16(cpu_to_be16(v), (p))
-#define iowrite32be(v,p) iowrite32(cpu_to_be32(v), (p))
+#define ioread16be(p) swab16(ioread16(p))
+#define ioread32be(p) swab32(ioread32(p))
+#define iowrite16be(v,p) iowrite16(swab16(v), (p))
+#define iowrite32be(v,p) iowrite32(swab32(v), (p))
 
 #define inb_p		inb
 #define inw_p		inw
@@ -499,14 +513,44 @@
 #define outb_p		outb
 #define outw_p		outw
 #define outl_p		outl
-#define readb_relaxed(addr)	__raw_readb(addr)
-#define readw_relaxed(addr)	__raw_readw(addr)
-#define readl_relaxed(addr)	__raw_readl(addr)
-#define readq_relaxed(addr)	__raw_readq(addr)
-#define writeb_relaxed(b, addr)	__raw_writeb(b, addr)
-#define writew_relaxed(b, addr)	__raw_writew(b, addr)
-#define writel_relaxed(b, addr)	__raw_writel(b, addr)
-#define writeq_relaxed(b, addr)	__raw_writeq(b, addr)
+
+extern u8 readb_relaxed(const volatile void __iomem *addr);
+extern u16 readw_relaxed(const volatile void __iomem *addr);
+extern u32 readl_relaxed(const volatile void __iomem *addr);
+extern u64 readq_relaxed(const volatile void __iomem *addr);
+
+#if IO_CONCAT(__IO_PREFIX,trivial_io_bw)
+extern inline u8 readb_relaxed(const volatile void __iomem *addr)
+{
+	mb();
+	return __raw_readb(addr);
+}
+
+extern inline u16 readw_relaxed(const volatile void __iomem *addr)
+{
+	mb();
+	return __raw_readw(addr);
+}
+#endif
+
+#if IO_CONCAT(__IO_PREFIX,trivial_io_lq)
+extern inline u32 readl_relaxed(const volatile void __iomem *addr)
+{
+	mb();
+	return __raw_readl(addr);
+}
+
+extern inline u64 readq_relaxed(const volatile void __iomem *addr)
+{
+	mb();
+	return __raw_readq(addr);
+}
+#endif
+
+#define writeb_relaxed	writeb
+#define writew_relaxed	writew
+#define writel_relaxed	writel
+#define writeq_relaxed	writeq
 
 /*
  * String version of IO memory access ops:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/alpha/include/asm/timex.h
+++ linux-xilinx-zynqmp-5.4.0/arch/alpha/include/asm/timex.h
@@ -28,5 +28,6 @@
 	__asm__ __volatile__ ("rpcc %0" : "=r"(ret));
 	return ret;
 }
+#define get_cycles get_cycles
 
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/alpha/include/uapi/asm/ptrace.h
+++ linux-xilinx-zynqmp-5.4.0/arch/alpha/include/uapi/asm/ptrace.h
@@ -42,6 +42,8 @@
 	unsigned long trap_a0;
 	unsigned long trap_a1;
 	unsigned long trap_a2;
+/* This makes the stack 16-byte aligned as GCC expects */
+	unsigned long __pad0;
 /* These are saved by PAL-code: */
 	unsigned long ps;
 	unsigned long pc;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/alpha/kernel/asm-offsets.c
+++ linux-xilinx-zynqmp-5.4.0/arch/alpha/kernel/asm-offsets.c
@@ -32,7 +32,9 @@
         DEFINE(CRED_EGID, offsetof(struct cred, egid));
         BLANK();
 
+	DEFINE(SP_OFF, offsetof(struct pt_regs, ps));
 	DEFINE(SIZEOF_PT_REGS, sizeof(struct pt_regs));
+	DEFINE(SWITCH_STACK_SIZE, sizeof(struct switch_stack));
 	DEFINE(PT_PTRACED, PT_PTRACED);
 	DEFINE(CLONE_VM, CLONE_VM);
 	DEFINE(CLONE_UNTRACED, CLONE_UNTRACED);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/alpha/kernel/entry.S
+++ linux-xilinx-zynqmp-5.4.0/arch/alpha/kernel/entry.S
@@ -15,10 +15,6 @@
 	.set noat
 	.cfi_sections	.debug_frame
 
-/* Stack offsets.  */
-#define SP_OFF			184
-#define SWITCH_STACK_SIZE	320
-
 .macro	CFI_START_OSF_FRAME	func
 	.align	4
 	.globl	\func
@@ -199,8 +195,8 @@
 CFI_START_OSF_FRAME entMM
 	SAVE_ALL
 /* save $9 - $15 so the inline exception code can manipulate them.  */
-	subq	$sp, 56, $sp
-	.cfi_adjust_cfa_offset	56
+	subq	$sp, 64, $sp
+	.cfi_adjust_cfa_offset	64
 	stq	$9, 0($sp)
 	stq	$10, 8($sp)
 	stq	$11, 16($sp)
@@ -215,7 +211,7 @@
 	.cfi_rel_offset	$13, 32
 	.cfi_rel_offset	$14, 40
 	.cfi_rel_offset	$15, 48
-	addq	$sp, 56, $19
+	addq	$sp, 64, $19
 /* handle the fault */
 	lda	$8, 0x3fff
 	bic	$sp, $8, $8
@@ -228,7 +224,7 @@
 	ldq	$13, 32($sp)
 	ldq	$14, 40($sp)
 	ldq	$15, 48($sp)
-	addq	$sp, 56, $sp
+	addq	$sp, 64, $sp
 	.cfi_restore	$9
 	.cfi_restore	$10
 	.cfi_restore	$11
@@ -236,7 +232,7 @@
 	.cfi_restore	$13
 	.cfi_restore	$14
 	.cfi_restore	$15
-	.cfi_adjust_cfa_offset	-56
+	.cfi_adjust_cfa_offset	-64
 /* finish up the syscall as normal.  */
 	br	ret_from_sys_call
 CFI_END_OSF_FRAME entMM
@@ -383,8 +379,8 @@
 	.cfi_restore	$0
 	.cfi_adjust_cfa_offset	-256
 	SAVE_ALL		/* setup normal kernel stack */
-	lda	$sp, -56($sp)
-	.cfi_adjust_cfa_offset	56
+	lda	$sp, -64($sp)
+	.cfi_adjust_cfa_offset	64
 	stq	$9, 0($sp)
 	stq	$10, 8($sp)
 	stq	$11, 16($sp)
@@ -400,7 +396,7 @@
 	.cfi_rel_offset	$14, 40
 	.cfi_rel_offset	$15, 48
 	lda	$8, 0x3fff
-	addq	$sp, 56, $19
+	addq	$sp, 64, $19
 	bic	$sp, $8, $8
 	jsr	$26, do_entUnaUser
 	ldq	$9, 0($sp)
@@ -410,7 +406,7 @@
 	ldq	$13, 32($sp)
 	ldq	$14, 40($sp)
 	ldq	$15, 48($sp)
-	lda	$sp, 56($sp)
+	lda	$sp, 64($sp)
 	.cfi_restore	$9
 	.cfi_restore	$10
 	.cfi_restore	$11
@@ -418,7 +414,7 @@
 	.cfi_restore	$13
 	.cfi_restore	$14
 	.cfi_restore	$15
-	.cfi_adjust_cfa_offset	-56
+	.cfi_adjust_cfa_offset	-64
 	br	ret_from_sys_call
 CFI_END_OSF_FRAME entUna
 
@@ -469,8 +465,10 @@
 #ifdef CONFIG_AUDITSYSCALL
 	lda     $6, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT
 	and     $3, $6, $3
-#endif
 	bne     $3, strace
+#else
+	blbs    $3, strace		/* check for SYSCALL_TRACE in disguise */
+#endif
 	beq	$4, 1f
 	ldq	$27, 0($5)
 1:	jsr	$26, ($27), sys_ni_syscall
--- linux-xilinx-zynqmp-5.4.0.orig/arch/alpha/kernel/io.c
+++ linux-xilinx-zynqmp-5.4.0/arch/alpha/kernel/io.c
@@ -16,21 +16,27 @@
 unsigned int
 ioread8(void __iomem *addr)
 {
-	unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread8)(addr);
+	unsigned int ret;
+	mb();
+	ret = IO_CONCAT(__IO_PREFIX,ioread8)(addr);
 	mb();
 	return ret;
 }
 
 unsigned int ioread16(void __iomem *addr)
 {
-	unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread16)(addr);
+	unsigned int ret;
+	mb();
+	ret = IO_CONCAT(__IO_PREFIX,ioread16)(addr);
 	mb();
 	return ret;
 }
 
 unsigned int ioread32(void __iomem *addr)
 {
-	unsigned int ret = IO_CONCAT(__IO_PREFIX,ioread32)(addr);
+	unsigned int ret;
+	mb();
+	ret = IO_CONCAT(__IO_PREFIX,ioread32)(addr);
 	mb();
 	return ret;
 }
@@ -148,28 +154,36 @@
 
 u8 readb(const volatile void __iomem *addr)
 {
-	u8 ret = __raw_readb(addr);
+	u8 ret;
+	mb();
+	ret = __raw_readb(addr);
 	mb();
 	return ret;
 }
 
 u16 readw(const volatile void __iomem *addr)
 {
-	u16 ret = __raw_readw(addr);
+	u16 ret;
+	mb();
+	ret = __raw_readw(addr);
 	mb();
 	return ret;
 }
 
 u32 readl(const volatile void __iomem *addr)
 {
-	u32 ret = __raw_readl(addr);
+	u32 ret;
+	mb();
+	ret = __raw_readl(addr);
 	mb();
 	return ret;
 }
 
 u64 readq(const volatile void __iomem *addr)
 {
-	u64 ret = __raw_readq(addr);
+	u64 ret;
+	mb();
+	ret = __raw_readq(addr);
 	mb();
 	return ret;
 }
@@ -207,6 +221,38 @@
 EXPORT_SYMBOL(writel);
 EXPORT_SYMBOL(writeq);
 
+/*
+ * The _relaxed functions must be ordered w.r.t. each other, but they don't
+ * have to be ordered w.r.t. other memory accesses.
+ */
+u8 readb_relaxed(const volatile void __iomem *addr)
+{
+	mb();
+	return __raw_readb(addr);
+}
+
+u16 readw_relaxed(const volatile void __iomem *addr)
+{
+	mb();
+	return __raw_readw(addr);
+}
+
+u32 readl_relaxed(const volatile void __iomem *addr)
+{
+	mb();
+	return __raw_readl(addr);
+}
+
+u64 readq_relaxed(const volatile void __iomem *addr)
+{
+	mb();
+	return __raw_readq(addr);
+}
+
+EXPORT_SYMBOL(readb_relaxed);
+EXPORT_SYMBOL(readw_relaxed);
+EXPORT_SYMBOL(readl_relaxed);
+EXPORT_SYMBOL(readq_relaxed);
 
 /*
  * Read COUNT 8-bit bytes from port PORT into memory starting at SRC.
--- linux-xilinx-zynqmp-5.4.0.orig/arch/alpha/kernel/module.c
+++ linux-xilinx-zynqmp-5.4.0/arch/alpha/kernel/module.c
@@ -146,10 +146,8 @@
 	base = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr;
 	symtab = (Elf64_Sym *)sechdrs[symindex].sh_addr;
 
-	/* The small sections were sorted to the end of the segment.
-	   The following should definitely cover them.  */
-	gp = (u64)me->core_layout.base + me->core_layout.size - 0x8000;
 	got = sechdrs[me->arch.gotsecindex].sh_addr;
+	gp = got + 0x8000;
 
 	for (i = 0; i < n; i++) {
 		unsigned long r_sym = ELF64_R_SYM (rela[i].r_info);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/alpha/kernel/osf_sys.c
+++ linux-xilinx-zynqmp-5.4.0/arch/alpha/kernel/osf_sys.c
@@ -963,7 +963,7 @@
 }
 
 static inline long
-put_tv_to_tv32(struct timeval32 __user *o, struct timeval *i)
+put_tv_to_tv32(struct timeval32 __user *o, struct __kernel_old_timeval *i)
 {
 	return copy_to_user(o, &(struct timeval32){
 				.tv_sec = i->tv_sec,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/alpha/kernel/setup.c
+++ linux-xilinx-zynqmp-5.4.0/arch/alpha/kernel/setup.c
@@ -394,8 +394,7 @@
 extern void setup_memory(void *);
 #endif /* !CONFIG_DISCONTIGMEM */
 
-int __init
-page_is_ram(unsigned long pfn)
+int page_is_ram(unsigned long pfn)
 {
 	struct memclust_struct * cluster;
 	struct memdesc_struct * memdesc;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/alpha/kernel/smp.c
+++ linux-xilinx-zynqmp-5.4.0/arch/alpha/kernel/smp.c
@@ -585,7 +585,7 @@
 smp_send_stop(void)
 {
 	cpumask_t to_whom;
-	cpumask_copy(&to_whom, cpu_possible_mask);
+	cpumask_copy(&to_whom, cpu_online_mask);
 	cpumask_clear_cpu(smp_processor_id(), &to_whom);
 #ifdef DEBUG_IPI_MSG
 	if (hard_smp_processor_id() != boot_cpu_id)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/alpha/kernel/srmcons.c
+++ linux-xilinx-zynqmp-5.4.0/arch/alpha/kernel/srmcons.c
@@ -59,7 +59,7 @@
 	} while((result.bits.status & 1) && (++loops < 10));
 
 	if (count)
-		tty_schedule_flip(port);
+		tty_flip_buffer_push(port);
 
 	return count;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/alpha/kernel/traps.c
+++ linux-xilinx-zynqmp-5.4.0/arch/alpha/kernel/traps.c
@@ -192,7 +192,7 @@
 		local_irq_enable();
 		while (1);
 	}
-	do_exit(SIGSEGV);
+	make_task_dead(SIGSEGV);
 }
 
 #ifndef CONFIG_MATHEMU
@@ -235,7 +235,21 @@
 {
 	int signo, code;
 
-	if ((regs->ps & ~IPL_MAX) == 0) {
+	if (type == 3) { /* FEN fault */
+		/* Irritating users can call PAL_clrfen to disable the
+		   FPU for the process.  The kernel will then trap in
+		   do_switch_stack and undo_switch_stack when we try
+		   to save and restore the FP registers.
+
+		   Given that GCC by default generates code that uses the
+		   FP registers, PAL_clrfen is not useful except for DoS
+		   attacks.  So turn the bleeding FPU back on and be done
+		   with it.  */
+		current_thread_info()->pcb.flags |= 1;
+		__reload_thread(&current_thread_info()->pcb);
+		return;
+	}
+	if (!user_mode(regs)) {
 		if (type == 1) {
 			const unsigned int *data
 			  = (const unsigned int *) regs->pc;
@@ -368,20 +382,6 @@
 		}
 		break;
 
-	      case 3: /* FEN fault */
-		/* Irritating users can call PAL_clrfen to disable the
-		   FPU for the process.  The kernel will then trap in
-		   do_switch_stack and undo_switch_stack when we try
-		   to save and restore the FP registers.
-
-		   Given that GCC by default generates code that uses the
-		   FP registers, PAL_clrfen is not useful except for DoS
-		   attacks.  So turn the bleeding FPU back on and be done
-		   with it.  */
-		current_thread_info()->pcb.flags |= 1;
-		__reload_thread(&current_thread_info()->pcb);
-		return;
-
 	      case 5: /* illoc */
 	      default: /* unexpected instruction-fault type */
 		      ;
@@ -577,7 +577,7 @@
 
 	printk("Bad unaligned kernel access at %016lx: %p %lx %lu\n",
 		pc, va, opcode, reg);
-	do_exit(SIGSEGV);
+	make_task_dead(SIGSEGV);
 
 got_exception:
 	/* Ok, we caught the exception, but we don't want it.  Is there
@@ -632,7 +632,7 @@
 		local_irq_enable();
 		while (1);
 	}
-	do_exit(SIGSEGV);
+	make_task_dead(SIGSEGV);
 }
 
 /*
@@ -709,7 +709,7 @@
 static int unauser_reg_offsets[32] = {
 	R(r0), R(r1), R(r2), R(r3), R(r4), R(r5), R(r6), R(r7), R(r8),
 	/* r9 ... r15 are stored in front of regs.  */
-	-56, -48, -40, -32, -24, -16, -8,
+	-64, -56, -48, -40, -32, -24, -16,	/* padding at -8 */
 	R(r16), R(r17), R(r18),
 	R(r19), R(r20), R(r21), R(r22), R(r23), R(r24), R(r25), R(r26),
 	R(r27), R(r28), R(gp),
--- linux-xilinx-zynqmp-5.4.0.orig/arch/alpha/mm/fault.c
+++ linux-xilinx-zynqmp-5.4.0/arch/alpha/mm/fault.c
@@ -77,8 +77,8 @@
 
 /* Macro for exception fixup code to access integer registers.  */
 #define dpf_reg(r)							\
-	(((unsigned long *)regs)[(r) <= 8 ? (r) : (r) <= 15 ? (r)-16 :	\
-				 (r) <= 18 ? (r)+10 : (r)-10])
+	(((unsigned long *)regs)[(r) <= 8 ? (r) : (r) <= 15 ? (r)-17 :	\
+				 (r) <= 18 ? (r)+11 : (r)-10])
 
 asmlinkage void
 do_page_fault(unsigned long address, unsigned long mmcsr,
@@ -206,7 +206,7 @@
 	printk(KERN_ALERT "Unable to handle kernel paging request at "
 	       "virtual address %016lx\n", address);
 	die_if_kernel("Oops", regs, cause, (unsigned long*)regs - 16);
-	do_exit(SIGKILL);
+	make_task_dead(SIGKILL);
 
 	/* We ran out of memory, or some other thing happened to us that
 	   made us unable to handle the page fault gracefully.  */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arc/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/arc/Kconfig
@@ -29,6 +29,7 @@
 	select GENERIC_SMP_IDLE_THREAD
 	select HAVE_ARCH_KGDB
 	select HAVE_ARCH_TRACEHOOK
+	select HAVE_COPY_THREAD_TLS
 	select HAVE_DEBUG_STACKOVERFLOW
 	select HAVE_FUTEX_CMPXCHG if FUTEX
 	select HAVE_IOREMAP_PROT
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arc/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/arc/Makefile
@@ -6,7 +6,7 @@
 KBUILD_DEFCONFIG := nsim_hs_defconfig
 
 ifeq ($(CROSS_COMPILE),)
-CROSS_COMPILE := $(call cc-cross-prefix, arc-linux- arceb-linux-)
+CROSS_COMPILE := $(call cc-cross-prefix, arc-linux- arceb-linux- arc-linux-gnu-)
 endif
 
 cflags-y	+= -fno-common -pipe -fno-builtin -mmedium-calls -D__linux__
@@ -90,16 +90,22 @@
 
 boot		:= arch/arc/boot
 
-#default target for make without any arguments.
-KBUILD_IMAGE	:= $(boot)/bootpImage
-
-all:	bootpImage
-bootpImage: vmlinux
-
-boot_targets += uImage uImage.bin uImage.gz
+boot_targets := uImage.bin uImage.gz uImage.lzma
 
+PHONY += $(boot_targets)
 $(boot_targets): vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 
+uimage-default-y			:= uImage.bin
+uimage-default-$(CONFIG_KERNEL_GZIP)	:= uImage.gz
+uimage-default-$(CONFIG_KERNEL_LZMA)	:= uImage.lzma
+
+PHONY += uImage
+uImage: $(uimage-default-y)
+	@ln -sf $< $(boot)/uImage
+	@$(kecho) '  Image $(boot)/uImage is ready'
+
+CLEAN_FILES += $(boot)/uImage
+
 archclean:
 	$(Q)$(MAKE) $(clean)=$(boot)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arc/boot/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/arc/boot/Makefile
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
-targets := vmlinux.bin vmlinux.bin.gz uImage
+targets := vmlinux.bin vmlinux.bin.gz
 
 # uImage build relies on mkimage being availble on your host for ARC target
 # You will need to build u-boot for ARC, rename mkimage to arc-elf32-mkimage
@@ -13,11 +13,6 @@
 UIMAGE_LOADADDR    = $(CONFIG_LINUX_LINK_BASE)
 UIMAGE_ENTRYADDR   = $(LINUX_START_TEXT)
 
-suffix-y := bin
-suffix-$(CONFIG_KERNEL_GZIP)	:= gz
-suffix-$(CONFIG_KERNEL_LZMA)	:= lzma
-
-targets += uImage
 targets += uImage.bin
 targets += uImage.gz
 targets += uImage.lzma
@@ -42,7 +37,3 @@
 
 $(obj)/uImage.lzma: $(obj)/vmlinux.bin.lzma FORCE
 	$(call if_changed,uimage,lzma)
-
-$(obj)/uImage: $(obj)/uImage.$(suffix-y)
-	@ln -sf $(notdir $<) $@
-	@echo '  Image $@ is ready'
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arc/boot/dts/axc001.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arc/boot/dts/axc001.dtsi
@@ -85,7 +85,7 @@
 	 * avoid duplicating the MB dtsi file given that IRQ from
 	 * this intc to cpu intc are different for axs101 and axs103
 	 */
-	mb_intc: dw-apb-ictl@e0012000 {
+	mb_intc: interrupt-controller@e0012000 {
 		#interrupt-cells = <1>;
 		compatible = "snps,dw-apb-ictl";
 		reg = < 0x0 0xe0012000 0x0 0x200 >;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arc/boot/dts/axc003.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arc/boot/dts/axc003.dtsi
@@ -129,7 +129,7 @@
 	 * avoid duplicating the MB dtsi file given that IRQ from
 	 * this intc to cpu intc are different for axs101 and axs103
 	 */
-	mb_intc: dw-apb-ictl@e0012000 {
+	mb_intc: interrupt-controller@e0012000 {
 		#interrupt-cells = <1>;
 		compatible = "snps,dw-apb-ictl";
 		reg = < 0x0 0xe0012000 0x0 0x200 >;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arc/boot/dts/axc003_idu.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arc/boot/dts/axc003_idu.dtsi
@@ -135,7 +135,7 @@
 	 * avoid duplicating the MB dtsi file given that IRQ from
 	 * this intc to cpu intc are different for axs101 and axs103
 	 */
-	mb_intc: dw-apb-ictl@e0012000 {
+	mb_intc: interrupt-controller@e0012000 {
 		#interrupt-cells = <1>;
 		compatible = "snps,dw-apb-ictl";
 		reg = < 0x0 0xe0012000 0x0 0x200 >;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arc/boot/dts/axs10x_mb.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arc/boot/dts/axs10x_mb.dtsi
@@ -77,6 +77,7 @@
 			interrupt-names = "macirq";
 			phy-mode = "rgmii";
 			snps,pbl = < 32 >;
+			snps,multicast-filter-bins = <256>;
 			clocks = <&apbclk>;
 			clock-names = "stmmaceth";
 			max-speed = <100>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arc/boot/dts/hsdk.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arc/boot/dts/hsdk.dts
@@ -88,6 +88,8 @@
 
 	arcpct: pct {
 		compatible = "snps,archs-pct";
+		interrupt-parent = <&cpu_intc>;
+		interrupts = <20>;
 	};
 
 	/* TIMER0 with interrupt for clockevent */
@@ -203,12 +205,11 @@
 		};
 
 		gmac: ethernet@8000 {
-			#interrupt-cells = <1>;
 			compatible = "snps,dwmac";
 			reg = <0x8000 0x2000>;
 			interrupts = <10>;
 			interrupt-names = "macirq";
-			phy-mode = "rgmii";
+			phy-mode = "rgmii-id";
 			snps,pbl = <32>;
 			snps,multicast-filter-bins = <256>;
 			clocks = <&gmacclk>;
@@ -226,7 +227,7 @@
 				#address-cells = <1>;
 				#size-cells = <0>;
 				compatible = "snps,dwmac-mdio";
-				phy0: ethernet-phy@0 {
+				phy0: ethernet-phy@0 { /* Micrel KSZ9031 */
 					reg = <0>;
 				};
 			};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arc/boot/dts/vdk_axc003.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arc/boot/dts/vdk_axc003.dtsi
@@ -46,7 +46,7 @@
 
 	};
 
-	mb_intc: dw-apb-ictl@e0012000 {
+	mb_intc: interrupt-controller@e0012000 {
 		#interrupt-cells = <1>;
 		compatible = "snps,dw-apb-ictl";
 		reg = < 0xe0012000 0x200 >;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arc/boot/dts/vdk_axc003_idu.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arc/boot/dts/vdk_axc003_idu.dtsi
@@ -54,7 +54,7 @@
 
 	};
 
-	mb_intc: dw-apb-ictl@e0012000 {
+	mb_intc: interrupt-controller@e0012000 {
 		#interrupt-cells = <1>;
 		compatible = "snps,dw-apb-ictl";
 		reg = < 0xe0012000 0x200 >;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arc/include/asm/Kbuild
+++ linux-xilinx-zynqmp-5.4.0/arch/arc/include/asm/Kbuild
@@ -17,7 +17,6 @@
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
 generic-y += mmiowb.h
-generic-y += msi.h
 generic-y += parport.h
 generic-y += percpu.h
 generic-y += preempt.h
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arc/include/asm/elf.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arc/include/asm/elf.h
@@ -19,7 +19,7 @@
 #define  R_ARC_32_PCREL		0x31
 
 /*to set parameters in the core dumps */
-#define ELF_ARCH		EM_ARCOMPACT
+#define ELF_ARCH		EM_ARC_INUSE
 #define ELF_CLASS		ELFCLASS32
 
 #ifdef CONFIG_CPU_BIG_ENDIAN
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arc/include/asm/io.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arc/include/asm/io.h
@@ -32,7 +32,7 @@
 {
 }
 
-extern void iounmap(const void __iomem *addr);
+extern void iounmap(const volatile void __iomem *addr);
 
 #define ioremap_nocache(phy, sz)	ioremap(phy, sz)
 #define ioremap_wc(phy, sz)		ioremap(phy, sz)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arc/include/asm/linkage.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arc/include/asm/linkage.h
@@ -8,6 +8,10 @@
 
 #include <asm/dwarf.h>
 
+#define ASM_NL		 `	/* use '`' to mark new line in macro */
+#define __ALIGN		.align 4
+#define __ALIGN_STR	__stringify(__ALIGN)
+
 #ifdef __ASSEMBLY__
 
 .macro ST2 e, o, off
@@ -28,8 +32,6 @@
 #endif
 .endm
 
-#define ASM_NL		 `	/* use '`' to mark new line in macro */
-
 /* annotation for data we want in DCCM - if enabled in .config */
 .macro ARCFP_DATA nm
 #ifdef CONFIG_ARC_HAS_DCCM
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arc/include/asm/page.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arc/include/asm/page.h
@@ -7,9 +7,22 @@
 
 #include <uapi/asm/page.h>
 
+#ifdef CONFIG_ARC_HAS_PAE40
+
+#define MAX_POSSIBLE_PHYSMEM_BITS	40
+#define PAGE_MASK_PHYS			(0xff00000000ull | PAGE_MASK)
+
+#else /* CONFIG_ARC_HAS_PAE40 */
+
+#define MAX_POSSIBLE_PHYSMEM_BITS	32
+#define PAGE_MASK_PHYS			PAGE_MASK
+
+#endif /* CONFIG_ARC_HAS_PAE40 */
+
 #ifndef __ASSEMBLY__
 
 #define clear_page(paddr)		memset((paddr), 0, PAGE_SIZE)
+#define copy_user_page(to, from, vaddr, pg)	copy_page(to, from)
 #define copy_page(to, from)		memcpy((to), (from), PAGE_SIZE)
 
 struct vm_area_struct;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arc/include/asm/pgtable.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arc/include/asm/pgtable.h
@@ -108,8 +108,8 @@
 #define ___DEF (_PAGE_PRESENT | _PAGE_CACHEABLE)
 
 /* Set of bits not changed in pte_modify */
-#define _PAGE_CHG_MASK	(PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_SPECIAL)
-
+#define _PAGE_CHG_MASK	(PAGE_MASK_PHYS | _PAGE_ACCESSED | _PAGE_DIRTY | \
+							   _PAGE_SPECIAL)
 /* More Abbrevaited helpers */
 #define PAGE_U_NONE     __pgprot(___DEF)
 #define PAGE_U_R        __pgprot(___DEF | _PAGE_READ)
@@ -133,11 +133,7 @@
 #define PTE_BITS_IN_PD0		(_PAGE_GLOBAL | _PAGE_PRESENT | _PAGE_HW_SZ)
 #define PTE_BITS_RWX		(_PAGE_EXECUTE | _PAGE_WRITE | _PAGE_READ)
 
-#ifdef CONFIG_ARC_HAS_PAE40
-#define PTE_BITS_NON_RWX_IN_PD1	(0xff00000000 | PAGE_MASK | _PAGE_CACHEABLE)
-#else
-#define PTE_BITS_NON_RWX_IN_PD1	(PAGE_MASK | _PAGE_CACHEABLE)
-#endif
+#define PTE_BITS_NON_RWX_IN_PD1	(PAGE_MASK_PHYS | _PAGE_CACHEABLE)
 
 /**************************************************************************
  * Mapping of vm_flags (Generic VM) to PTE flags (arch specific)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arc/include/asm/syscalls.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arc/include/asm/syscalls.h
@@ -11,6 +11,7 @@
 #include <linux/types.h>
 
 int sys_clone_wrapper(int, int, int, int, int);
+int sys_clone3_wrapper(void *, size_t);
 int sys_cacheflush(uint32_t, uint32_t uint32_t);
 int sys_arc_settls(void *);
 int sys_arc_gettls(void);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arc/include/uapi/asm/page.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arc/include/uapi/asm/page.h
@@ -33,5 +33,4 @@
 
 #define PAGE_MASK	(~(PAGE_SIZE-1))
 
-
 #endif /* _UAPI__ASM_ARC_PAGE_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arc/include/uapi/asm/sigcontext.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arc/include/uapi/asm/sigcontext.h
@@ -18,6 +18,7 @@
  */
 struct sigcontext {
 	struct user_regs_struct regs;
+	struct user_regs_arcv2 v2abi;
 };
 
 #endif /* _ASM_ARC_SIGCONTEXT_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arc/include/uapi/asm/unistd.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arc/include/uapi/asm/unistd.h
@@ -21,6 +21,7 @@
 #define __ARCH_WANT_SET_GET_RLIMIT
 #define __ARCH_WANT_SYS_EXECVE
 #define __ARCH_WANT_SYS_CLONE
+#define __ARCH_WANT_SYS_CLONE3
 #define __ARCH_WANT_SYS_VFORK
 #define __ARCH_WANT_SYS_FORK
 #define __ARCH_WANT_TIME32_SYSCALLS
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arc/kernel/entry.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arc/kernel/entry.S
@@ -35,6 +35,18 @@
 	b .Lret_from_system_call
 END(sys_clone_wrapper)
 
+ENTRY(sys_clone3_wrapper)
+	SAVE_CALLEE_SAVED_USER
+	bl  @sys_clone3
+	DISCARD_CALLEE_SAVED_USER
+
+	GET_CURR_THR_INFO_FLAGS   r10
+	btst r10, TIF_SYSCALL_TRACE
+	bnz  tracesys_exit
+
+	b .Lret_from_system_call
+END(sys_clone3_wrapper)
+
 ENTRY(ret_from_fork)
 	; when the forked child comes here from the __switch_to function
 	; r0 has the last task pointer.
@@ -153,7 +165,6 @@
 tracesys:
 	; save EFA in case tracer wants the PC of traced task
 	; using ERET won't work since next-PC has already committed
-	lr  r12, [efa]
 	GET_CURR_TASK_FIELD_PTR   TASK_THREAD, r11
 	st  r12, [r11, THREAD_FAULT_ADDR]	; thread.fault_address
 
@@ -166,7 +177,7 @@
 
 	; Do the Sys Call as we normally would.
 	; Validate the Sys Call number
-	cmp     r8,  NR_syscalls
+	cmp     r8,  NR_syscalls - 1
 	mov.hi  r0, -ENOSYS
 	bhi     tracesys_exit
 
@@ -188,6 +199,7 @@
 	st  r0, [sp, PT_r0]     ; sys call return value in pt_regs
 
 	;POST Sys Call Ptrace Hook
+	mov r0, sp		; pt_regs needed
 	bl  @syscall_trace_exit
 	b   ret_from_exception ; NOT ret_from_system_call at is saves r0 which
 	; we'd done before calling post hook above
@@ -196,15 +208,9 @@
 ; Breakpoint TRAP
 ; ---------------------------------------------
 trap_with_param:
-
-	; stop_pc info by gdb needs this info
-	lr  r0, [efa]
+	mov r0, r12	; EFA in case ptracer/gdb wants stop_pc
 	mov r1, sp
 
-	; Now that we have read EFA, it is safe to do "fake" rtie
-	;   and get out of CPU exception mode
-	FAKE_RET_FROM_EXCPN
-
 	; Save callee regs in case gdb wants to have a look
 	; SP will grow up by size of CALLEE Reg-File
 	; NOTE: clobbers r12
@@ -231,6 +237,10 @@
 
 	EXCEPTION_PROLOGUE
 
+	lr  r12, [efa]
+
+	FAKE_RET_FROM_EXCPN
+
 	;============ TRAP 1   :breakpoints
 	; Check ECR for trap with arg (PROLOGUE ensures r10 has ECR)
 	bmsk.f 0, r10, 7
@@ -238,9 +248,6 @@
 
 	;============ TRAP  (no param): syscall top level
 
-	; First return from Exception to pure K mode (Exception/IRQs renabled)
-	FAKE_RET_FROM_EXCPN
-
 	; If syscall tracing ongoing, invoke pre-post-hooks
 	GET_CURR_THR_INFO_FLAGS   r10
 	btst r10, TIF_SYSCALL_TRACE
@@ -249,7 +256,7 @@
 	;============ Normal syscall case
 
 	; syscall num shd not exceed the total system calls avail
-	cmp     r8,  NR_syscalls
+	cmp     r8,  NR_syscalls - 1
 	mov.hi  r0, -ENOSYS
 	bhi     .Lret_from_system_call
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arc/kernel/perf_event.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arc/kernel/perf_event.c
@@ -562,7 +562,7 @@
 {
 	struct arc_reg_pct_build pct_bcr;
 	struct arc_reg_cc_build cc_bcr;
-	int i, has_interrupts;
+	int i, has_interrupts, irq = -1;
 	int counter_size;	/* in bits */
 
 	union cc_name {
@@ -638,22 +638,25 @@
 	};
 
 	if (has_interrupts) {
-		int irq = platform_get_irq(pdev, 0);
-
-		if (irq < 0) {
-			pr_err("Cannot get IRQ number for the platform\n");
-			return -ENODEV;
+		irq = platform_get_irq(pdev, 0);
+		if (irq >= 0) {
+			int ret;
+
+			arc_pmu->irq = irq;
+
+			/* intc map function ensures irq_set_percpu_devid() called */
+			ret = request_percpu_irq(irq, arc_pmu_intr, "ARC perf counters",
+						 this_cpu_ptr(&arc_pmu_cpu));
+
+			if (!ret)
+				on_each_cpu(arc_cpu_pmu_irq_init, &irq, 1);
+			else
+				irq = -1;
 		}
 
-		arc_pmu->irq = irq;
-
-		/* intc map function ensures irq_set_percpu_devid() called */
-		request_percpu_irq(irq, arc_pmu_intr, "ARC perf counters",
-				   this_cpu_ptr(&arc_pmu_cpu));
-
-		on_each_cpu(arc_cpu_pmu_irq_init, &irq, 1);
+	}
 
-	} else
+	if (irq == -1)
 		arc_pmu->pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
 
 	/*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arc/kernel/process.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arc/kernel/process.c
@@ -171,9 +171,8 @@
  * |    user_r25    |
  * ------------------  <===== END of PAGE
  */
-int copy_thread(unsigned long clone_flags,
-		unsigned long usp, unsigned long kthread_arg,
-		struct task_struct *p)
+int copy_thread_tls(unsigned long clone_flags, unsigned long usp,
+	unsigned long kthread_arg, struct task_struct *p, unsigned long tls)
 {
 	struct pt_regs *c_regs;        /* child's pt_regs */
 	unsigned long *childksp;       /* to unwind out of __switch_to() */
@@ -231,7 +230,7 @@
 		 * set task's userland tls data ptr from 4th arg
 		 * clone C-lib call is difft from clone sys-call
 		 */
-		task_thread_info(p)->thr_ptr = regs->r3;
+		task_thread_info(p)->thr_ptr = tls;
 	} else {
 		/* Normal fork case: set parent's TLS ptr in child */
 		task_thread_info(p)->thr_ptr =
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arc/kernel/setup.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arc/kernel/setup.c
@@ -12,6 +12,7 @@
 #include <linux/clocksource.h>
 #include <linux/console.h>
 #include <linux/module.h>
+#include <linux/sizes.h>
 #include <linux/cpu.h>
 #include <linux/of_fdt.h>
 #include <linux/of.h>
@@ -409,12 +410,12 @@
 	if ((unsigned int)__arc_dccm_base != cpu->dccm.base_addr)
 		panic("Linux built with incorrect DCCM Base address\n");
 
-	if (CONFIG_ARC_DCCM_SZ != cpu->dccm.sz)
+	if (CONFIG_ARC_DCCM_SZ * SZ_1K != cpu->dccm.sz)
 		panic("Linux built with incorrect DCCM Size\n");
 #endif
 
 #ifdef CONFIG_ARC_HAS_ICCM
-	if (CONFIG_ARC_ICCM_SZ != cpu->iccm.sz)
+	if (CONFIG_ARC_ICCM_SZ * SZ_1K != cpu->iccm.sz)
 		panic("Linux built with incorrect ICCM Size\n");
 #endif
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arc/kernel/signal.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arc/kernel/signal.c
@@ -61,6 +61,41 @@
 	unsigned int sigret_magic;
 };
 
+static int save_arcv2_regs(struct sigcontext __user *mctx, struct pt_regs *regs)
+{
+	int err = 0;
+#ifndef CONFIG_ISA_ARCOMPACT
+	struct user_regs_arcv2 v2abi;
+
+	v2abi.r30 = regs->r30;
+#ifdef CONFIG_ARC_HAS_ACCL_REGS
+	v2abi.r58 = regs->r58;
+	v2abi.r59 = regs->r59;
+#else
+	v2abi.r58 = v2abi.r59 = 0;
+#endif
+	err = __copy_to_user(&mctx->v2abi, (void const *)&v2abi, sizeof(v2abi));
+#endif
+	return err;
+}
+
+static int restore_arcv2_regs(struct sigcontext __user *mctx, struct pt_regs *regs)
+{
+	int err = 0;
+#ifndef CONFIG_ISA_ARCOMPACT
+	struct user_regs_arcv2 v2abi;
+
+	err = __copy_from_user(&v2abi, &mctx->v2abi, sizeof(v2abi));
+
+	regs->r30 = v2abi.r30;
+#ifdef CONFIG_ARC_HAS_ACCL_REGS
+	regs->r58 = v2abi.r58;
+	regs->r59 = v2abi.r59;
+#endif
+#endif
+	return err;
+}
+
 static int
 stash_usr_regs(struct rt_sigframe __user *sf, struct pt_regs *regs,
 	       sigset_t *set)
@@ -94,9 +129,13 @@
 
 	err = __copy_to_user(&(sf->uc.uc_mcontext.regs.scratch), &uregs.scratch,
 			     sizeof(sf->uc.uc_mcontext.regs.scratch));
+
+	if (is_isa_arcv2())
+		err |= save_arcv2_regs(&(sf->uc.uc_mcontext), regs);
+
 	err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(sigset_t));
 
-	return err;
+	return err ? -EFAULT : 0;
 }
 
 static int restore_usr_regs(struct pt_regs *regs, struct rt_sigframe __user *sf)
@@ -109,8 +148,12 @@
 	err |= __copy_from_user(&uregs.scratch,
 				&(sf->uc.uc_mcontext.regs.scratch),
 				sizeof(sf->uc.uc_mcontext.regs.scratch));
+
+	if (is_isa_arcv2())
+		err |= restore_arcv2_regs(&(sf->uc.uc_mcontext), regs);
+
 	if (err)
-		return err;
+		return -EFAULT;
 
 	set_current_blocked(&set);
 	regs->bta	= uregs.scratch.bta;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arc/kernel/stacktrace.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arc/kernel/stacktrace.c
@@ -38,15 +38,15 @@
 
 #ifdef CONFIG_ARC_DW2_UNWIND
 
-static void seed_unwind_frame_info(struct task_struct *tsk,
-				   struct pt_regs *regs,
-				   struct unwind_frame_info *frame_info)
+static int
+seed_unwind_frame_info(struct task_struct *tsk, struct pt_regs *regs,
+		       struct unwind_frame_info *frame_info)
 {
 	/*
 	 * synchronous unwinding (e.g. dump_stack)
 	 *  - uses current values of SP and friends
 	 */
-	if (tsk == NULL && regs == NULL) {
+	if (regs == NULL && (tsk == NULL || tsk == current)) {
 		unsigned long fp, sp, blink, ret;
 		frame_info->task = current;
 
@@ -65,11 +65,15 @@
 		frame_info->call_frame = 0;
 	} else if (regs == NULL) {
 		/*
-		 * Asynchronous unwinding of sleeping task
-		 *  - Gets SP etc from task's pt_regs (saved bottom of kernel
-		 *    mode stack of task)
+		 * Asynchronous unwinding of a likely sleeping task
+		 *  - first ensure it is actually sleeping
+		 *  - if so, it will be in __switch_to, kernel mode SP of task
+		 *    is safe-kept and BLINK at a well known location in there
 		 */
 
+		if (tsk->state == TASK_RUNNING)
+			return -1;
+
 		frame_info->task = tsk;
 
 		frame_info->regs.r27 = TSK_K_FP(tsk);
@@ -103,6 +107,8 @@
 		frame_info->regs.r63 = regs->ret;
 		frame_info->call_frame = 0;
 	}
+
+	return 0;
 }
 
 #endif
@@ -112,11 +118,12 @@
 		int (*consumer_fn) (unsigned int, void *), void *arg)
 {
 #ifdef CONFIG_ARC_DW2_UNWIND
-	int ret = 0;
+	int ret = 0, cnt = 0;
 	unsigned int address;
 	struct unwind_frame_info frame_info;
 
-	seed_unwind_frame_info(tsk, regs, &frame_info);
+	if (seed_unwind_frame_info(tsk, regs, &frame_info))
+		return 0;
 
 	while (1) {
 		address = UNW_PC(&frame_info);
@@ -132,6 +139,11 @@
 			break;
 
 		frame_info.regs.r63 = frame_info.regs.r31;
+
+		if (cnt++ > 128) {
+			printk("unwinder looping too long, aborting !\n");
+			return 0;
+		}
 	}
 
 	return address;		/* return the last address it saw */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arc/kernel/sys.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arc/kernel/sys.c
@@ -7,6 +7,7 @@
 #include <asm/syscalls.h>
 
 #define sys_clone	sys_clone_wrapper
+#define sys_clone3	sys_clone3_wrapper
 
 #undef __SYSCALL
 #define __SYSCALL(nr, call) [nr] = (call),
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arc/kernel/vmlinux.lds.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arc/kernel/vmlinux.lds.S
@@ -88,6 +88,8 @@
 		CPUIDLE_TEXT
 		LOCK_TEXT
 		KPROBES_TEXT
+		IRQENTRY_TEXT
+		SOFTIRQENTRY_TEXT
 		*(.fixup)
 		*(.gnu.warning)
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arc/mm/cache.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arc/mm/cache.c
@@ -1123,7 +1123,7 @@
 	clear_page(to);
 	clear_bit(PG_dc_clean, &page->flags);
 }
-
+EXPORT_SYMBOL(clear_user_page);
 
 /**********************************************************************
  * Explicit Cache flush request from user space via syscall
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arc/mm/dma.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arc/mm/dma.c
@@ -48,8 +48,8 @@
  * upper layer functions (in include/linux/dma-mapping.h)
  */
 
-void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr,
-		size_t size, enum dma_data_direction dir)
+void arch_sync_dma_for_device(phys_addr_t paddr, size_t size,
+		enum dma_data_direction dir)
 {
 	switch (dir) {
 	case DMA_TO_DEVICE:
@@ -69,8 +69,8 @@
 	}
 }
 
-void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr,
-		size_t size, enum dma_data_direction dir)
+void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size,
+		enum dma_data_direction dir)
 {
 	switch (dir) {
 	case DMA_TO_DEVICE:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arc/mm/ioremap.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arc/mm/ioremap.c
@@ -53,9 +53,10 @@
 void __iomem *ioremap_prot(phys_addr_t paddr, unsigned long size,
 			   unsigned long flags)
 {
+	unsigned int off;
 	unsigned long vaddr;
 	struct vm_struct *area;
-	phys_addr_t off, end;
+	phys_addr_t end;
 	pgprot_t prot = __pgprot(flags);
 
 	/* Don't allow wraparound, zero size */
@@ -72,7 +73,7 @@
 
 	/* Mappings have to be page-aligned */
 	off = paddr & ~PAGE_MASK;
-	paddr &= PAGE_MASK;
+	paddr &= PAGE_MASK_PHYS;
 	size = PAGE_ALIGN(end + 1) - paddr;
 
 	/*
@@ -92,7 +93,7 @@
 EXPORT_SYMBOL(ioremap_prot);
 
 
-void iounmap(const void __iomem *addr)
+void iounmap(const volatile void __iomem *addr)
 {
 	/* weird double cast to handle phys_addr_t > 32 bits */
 	if (arc_uncached_addr_space((phys_addr_t)(u32)addr))
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arc/mm/tlb.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arc/mm/tlb.c
@@ -597,7 +597,7 @@
 		      pte_t *ptep)
 {
 	unsigned long vaddr = vaddr_unaligned & PAGE_MASK;
-	phys_addr_t paddr = pte_val(*ptep) & PAGE_MASK;
+	phys_addr_t paddr = pte_val(*ptep) & PAGE_MASK_PHYS;
 	struct page *page = pfn_to_page(pte_pfn(*ptep));
 
 	create_tlb(vma, vaddr, ptep);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arc/plat-eznps/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/arc/plat-eznps/Kconfig
@@ -6,8 +6,9 @@
 
 menuconfig ARC_PLAT_EZNPS
 	bool "\"EZchip\" ARC dev platform"
+	depends on ISA_ARCOMPACT
 	select CPU_BIG_ENDIAN
-	select CLKSRC_NPS
+	select CLKSRC_NPS if !PHYS_ADDR_T_64BIT
 	select EZNPS_GIC
 	select EZCHIP_NPS_MANAGEMENT_ENET if ETHERNET
 	help
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arc/plat-eznps/include/plat/ctop.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arc/plat-eznps/include/plat/ctop.h
@@ -33,7 +33,6 @@
 #define CTOP_AUX_DPC				(CTOP_AUX_BASE + 0x02C)
 #define CTOP_AUX_LPC				(CTOP_AUX_BASE + 0x030)
 #define CTOP_AUX_EFLAGS				(CTOP_AUX_BASE + 0x080)
-#define CTOP_AUX_IACK				(CTOP_AUX_BASE + 0x088)
 #define CTOP_AUX_GPA1				(CTOP_AUX_BASE + 0x08C)
 #define CTOP_AUX_UDMC				(CTOP_AUX_BASE + 0x300)
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arc/plat-hsdk/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/arc/plat-hsdk/Kconfig
@@ -8,5 +8,6 @@
 	select ARC_HAS_ACCL_REGS
 	select ARC_IRQ_NO_AUTOSAVE
 	select CLK_HSDK
+	select RESET_CONTROLLER
 	select RESET_HSDK
 	select HAVE_PCI
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/Kconfig
@@ -5,6 +5,7 @@
 	select ARCH_32BIT_OFF_T
 	select ARCH_CLOCKSOURCE_DATA
 	select ARCH_HAS_BINFMT_FLAT
+	select ARCH_HAS_CPU_FINALIZE_INIT if MMU
 	select ARCH_HAS_DEBUG_VIRTUAL if MMU
 	select ARCH_HAS_DEVMEM_IS_ALLOWED
 	select ARCH_HAS_DMA_COHERENT_TO_PFN if SWIOTLB
@@ -26,7 +27,7 @@
 	select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
 	select ARCH_HAVE_CUSTOM_GPIO_H
 	select ARCH_HAS_GCOV_PROFILE_ALL
-	select ARCH_KEEP_MEMBLOCK if HAVE_ARCH_PFN_VALID || KEXEC
+	select ARCH_KEEP_MEMBLOCK
 	select ARCH_MIGHT_HAVE_PC_PARPORT
 	select ARCH_NO_SG_CHAIN if !ARM_HAS_SG_CHAIN
 	select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX
@@ -73,8 +74,9 @@
 	select HAVE_ARM_SMCCC if CPU_V7
 	select HAVE_EBPF_JIT if !CPU_ENDIAN_BE32
 	select HAVE_CONTEXT_TRACKING
+	select HAVE_COPY_THREAD_TLS
 	select HAVE_C_RECORDMCOUNT
-	select HAVE_DEBUG_KMEMLEAK
+	select HAVE_DEBUG_KMEMLEAK if !XIP_KERNEL
 	select HAVE_DMA_CONTIGUOUS if MMU
 	select HAVE_DYNAMIC_FTRACE if !XIP_KERNEL && !CPU_ENDIAN_BE32 && MMU
 	select HAVE_DYNAMIC_FTRACE_WITH_REGS if HAVE_DYNAMIC_FTRACE
@@ -84,6 +86,7 @@
 	select HAVE_FTRACE_MCOUNT_RECORD if !XIP_KERNEL
 	select HAVE_FUNCTION_GRAPH_TRACER if !THUMB2_KERNEL && !CC_IS_CLANG
 	select HAVE_FUNCTION_TRACER if !XIP_KERNEL && (CC_IS_GCC || CLANG_VERSION >= 100000)
+	select HAVE_FUTEX_CMPXCHG if FUTEX
 	select HAVE_GCC_PLUGINS
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS && (CPU_V6 || CPU_V6K || CPU_V7)
 	select HAVE_IDE if PCI || ISA || PCMCIA
@@ -117,7 +120,6 @@
 	select OLD_SIGSUSPEND3
 	select PCI_SYSCALL if PCI
 	select PERF_USE_VMALLOC
-	select REFCOUNT_FULL
 	select RTC_LIB
 	select SYS_SUPPORTS_APM_EMULATION
 	# Above selects are sorted alphabetically; please add new ones
@@ -506,8 +508,10 @@
 	select HAVE_S3C2410_WATCHDOG if WATCHDOG
 	select HAVE_S3C_RTC if RTC_CLASS
 	select NEED_MACH_IO_H
+	select S3C2410_WATCHDOG
 	select SAMSUNG_ATAGS
 	select USE_OF
+	select WATCHDOG
 	help
 	  Samsung S3C2410, S3C2412, S3C2413, S3C2416, S3C2440, S3C2442, S3C2443
 	  and S3C2450 SoCs based systems, such as the Simtec Electronics BAST
@@ -517,7 +521,6 @@
 config ARCH_OMAP1
 	bool "TI OMAP1"
 	depends on MMU
-	select ARCH_HAS_HOLES_MEMORYMODEL
 	select ARCH_OMAP
 	select CLKDEV_LOOKUP
 	select CLKSRC_MMIO
@@ -1514,9 +1517,6 @@
 	  UNPREDICTABLE (in fact it can be predicted that it won't work
 	  at all). If in doubt say N.
 
-config ARCH_HAS_HOLES_MEMORYMODEL
-	bool
-
 config ARCH_SPARSEMEM_ENABLE
 	bool
 
@@ -1524,7 +1524,7 @@
 	def_bool ARCH_SPARSEMEM_ENABLE
 
 config HAVE_ARCH_PFN_VALID
-	def_bool ARCH_HAS_HOLES_MEMORYMODEL || !SPARSEMEM
+	def_bool y
 
 config HIGHMEM
 	bool "High Memory Support"
@@ -1838,7 +1838,6 @@
 choice
 	prompt "Kernel command line type" if CMDLINE != ""
 	default CMDLINE_FROM_BOOTLOADER
-	depends on ATAGS
 
 config CMDLINE_FROM_BOOTLOADER
 	bool "Use bootloader kernel arguments if available"
@@ -1906,7 +1905,7 @@
 config KEXEC
 	bool "Kexec system call (EXPERIMENTAL)"
 	depends on (!SMP || PM_SLEEP_SMP)
-	depends on !CPU_V7M
+	depends on MMU
 	select KEXEC_CORE
 	help
 	  kexec is a system call that implements the ability to shutdown your
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/Makefile
@@ -66,15 +66,15 @@
 # Note that GCC does not numerically define an architecture version
 # macro, but instead defines a whole series of macros which makes
 # testing for a specific architecture or later rather impossible.
-arch-$(CONFIG_CPU_32v7M)	=-D__LINUX_ARM_ARCH__=7 -march=armv7-m -Wa,-march=armv7-m
-arch-$(CONFIG_CPU_32v7)		=-D__LINUX_ARM_ARCH__=7 $(call cc-option,-march=armv7-a,-march=armv5t -Wa$(comma)-march=armv7-a)
-arch-$(CONFIG_CPU_32v6)		=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6)
+arch-$(CONFIG_CPU_32v7M)	=-D__LINUX_ARM_ARCH__=7 -march=armv7-m
+arch-$(CONFIG_CPU_32v7)		=-D__LINUX_ARM_ARCH__=7 -march=armv7-a
+arch-$(CONFIG_CPU_32v6)		=-D__LINUX_ARM_ARCH__=6 -march=armv6
 # Only override the compiler option if ARMv6. The ARMv6K extensions are
 # always available in ARMv7
 ifeq ($(CONFIG_CPU_32v6),y)
-arch-$(CONFIG_CPU_32v6K)	=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6k,-march=armv5t -Wa$(comma)-march=armv6k)
+arch-$(CONFIG_CPU_32v6K)	=-D__LINUX_ARM_ARCH__=6 -march=armv6k
 endif
-arch-$(CONFIG_CPU_32v5)		=-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4t)
+arch-$(CONFIG_CPU_32v5)		=-D__LINUX_ARM_ARCH__=5 -march=armv5te
 arch-$(CONFIG_CPU_32v4T)	=-D__LINUX_ARM_ARCH__=4 -march=armv4t
 arch-$(CONFIG_CPU_32v4)		=-D__LINUX_ARM_ARCH__=4 -march=armv4
 arch-$(CONFIG_CPU_32v3)		=-D__LINUX_ARM_ARCH__=3 -march=armv3m
@@ -88,7 +88,7 @@
 tune-$(CONFIG_CPU_ARM740T)	=-mtune=arm7tdmi
 tune-$(CONFIG_CPU_ARM9TDMI)	=-mtune=arm9tdmi
 tune-$(CONFIG_CPU_ARM940T)	=-mtune=arm9tdmi
-tune-$(CONFIG_CPU_ARM946E)	=$(call cc-option,-mtune=arm9e,-mtune=arm9tdmi)
+tune-$(CONFIG_CPU_ARM946E)	=-mtune=arm9e
 tune-$(CONFIG_CPU_ARM920T)	=-mtune=arm9tdmi
 tune-$(CONFIG_CPU_ARM922T)	=-mtune=arm9tdmi
 tune-$(CONFIG_CPU_ARM925T)	=-mtune=arm9tdmi
@@ -96,11 +96,11 @@
 tune-$(CONFIG_CPU_FA526)	=-mtune=arm9tdmi
 tune-$(CONFIG_CPU_SA110)	=-mtune=strongarm110
 tune-$(CONFIG_CPU_SA1100)	=-mtune=strongarm1100
-tune-$(CONFIG_CPU_XSCALE)	=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale
-tune-$(CONFIG_CPU_XSC3)		=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale
-tune-$(CONFIG_CPU_FEROCEON)	=$(call cc-option,-mtune=marvell-f,-mtune=xscale)
-tune-$(CONFIG_CPU_V6)		=$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm)
-tune-$(CONFIG_CPU_V6K)		=$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm)
+tune-$(CONFIG_CPU_XSCALE)	=-mtune=xscale
+tune-$(CONFIG_CPU_XSC3)		=-mtune=xscale
+tune-$(CONFIG_CPU_FEROCEON)	=-mtune=xscale
+tune-$(CONFIG_CPU_V6)		=-mtune=arm1136j-s
+tune-$(CONFIG_CPU_V6K)		=-mtune=arm1136j-s
 
 # Evaluate tune cc-option calls now
 tune-y := $(tune-y)
@@ -307,13 +307,15 @@
 ifeq ($(CONFIG_STACKPROTECTOR_PER_TASK),y)
 prepare: stack_protector_prepare
 stack_protector_prepare: prepare0
-	$(eval KBUILD_CFLAGS += \
+	$(eval SSP_PLUGIN_CFLAGS := \
 		-fplugin-arg-arm_ssp_per_task_plugin-tso=$(shell	\
 			awk '{if ($$2 == "THREAD_SZ_ORDER") print $$3;}'\
 				include/generated/asm-offsets.h)	\
 		-fplugin-arg-arm_ssp_per_task_plugin-offset=$(shell	\
 			awk '{if ($$2 == "TI_STACK_CANARY") print $$3;}'\
 				include/generated/asm-offsets.h))
+	$(eval KBUILD_CFLAGS += $(SSP_PLUGIN_CFLAGS))
+	$(eval GCC_PLUGINS_CFLAGS += $(SSP_PLUGIN_CFLAGS))
 endif
 
 all:	$(notdir $(KBUILD_IMAGE))
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/bootp/init.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/bootp/init.S
@@ -13,7 +13,7 @@
  *  size immediately following the kernel, we could build this into
  *  a binary blob, and concatenate the zImage using the cat command.
  */
-		.section .start,#alloc,#execinstr
+		.section .start, "ax"
 		.type	_start, #function
 		.globl	_start
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/compressed/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/compressed/Makefile
@@ -90,6 +90,8 @@
 	$(addprefix $(obj)/,$(libfdt_hdrs))
 
 ifeq ($(CONFIG_ARM_ATAG_DTB_COMPAT),y)
+CFLAGS_REMOVE_atags_to_fdt.o += -Wframe-larger-than=${CONFIG_FRAME_WARN}
+CFLAGS_atags_to_fdt.o += -Wframe-larger-than=1280
 OBJS	+= $(libfdt_objs) atags_to_fdt.o
 endif
 
@@ -101,7 +103,6 @@
 		$(libfdt) $(libfdt_hdrs) hyp-stub.S
 
 KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING
-KBUILD_CFLAGS += $(DISABLE_ARM_SSP_PER_TASK_PLUGIN)
 
 ifeq ($(CONFIG_FUNCTION_TRACER),y)
 ORIG_CFLAGS := $(KBUILD_CFLAGS)
@@ -117,13 +118,14 @@
 CFLAGS_fdt_rw.o := $(nossp_flags)
 CFLAGS_fdt_wip.o := $(nossp_flags)
 
-ccflags-y := -fpic $(call cc-option,-mno-single-pic-base,) -fno-builtin -I$(obj)
+ccflags-y := -fpic $(call cc-option,-mno-single-pic-base,) -fno-builtin \
+	     -I$(obj) $(DISABLE_ARM_SSP_PER_TASK_PLUGIN)
 asflags-y := -DZIMAGE
 
 # Supply kernel BSS size to the decompressor via a linker symbol.
-KBSS_SZ = $(shell echo $$(($$($(CROSS_COMPILE)nm $(obj)/../../../../vmlinux | \
-		sed -n -e 's/^\([^ ]*\) [AB] __bss_start$$/-0x\1/p' \
-		       -e 's/^\([^ ]*\) [AB] __bss_stop$$/+0x\1/p') )) )
+KBSS_SZ = $(shell echo $$(($$($(NM) $(obj)/../../../../vmlinux | \
+		sed -n -e 's/^\([^ ]*\) [ABD] __bss_start$$/-0x\1/p' \
+		       -e 's/^\([^ ]*\) [ABD] __bss_stop$$/+0x\1/p') )) )
 LDFLAGS_vmlinux = --defsym _kernel_bss_size=$(KBSS_SZ)
 # Supply ZRELADDR to the decompressor via a linker symbol.
 ifneq ($(CONFIG_AUTO_ZRELADDR),y)
@@ -165,7 +167,7 @@
 # The .data section is already discarded by the linker script so no need
 # to bother about it here.
 check_for_bad_syms = \
-bad_syms=$$($(CROSS_COMPILE)nm $@ | sed -n 's/^.\{8\} [bc] \(.*\)/\1/p') && \
+bad_syms=$$($(NM) $@ | sed -n 's/^.\{8\} [bc] \(.*\)/\1/p') && \
 [ -z "$$bad_syms" ] || \
   ( echo "following symbols must have non local/private scope:" >&2; \
     echo "$$bad_syms" >&2; false )
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/compressed/big-endian.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/compressed/big-endian.S
@@ -6,7 +6,7 @@
  *  Author: Nicolas Pitre
  */
 
-	.section ".start", #alloc, #execinstr
+	.section ".start", "ax"
 
 	mrc	p15, 0, r0, c1, c0, 0	@ read control reg
 	orr	r0, r0, #(1 << 7)	@ enable big endian mode
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/compressed/decompress.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/compressed/decompress.c
@@ -47,7 +47,10 @@
 #endif
 
 #ifdef CONFIG_KERNEL_XZ
+/* Prevent KASAN override of string helpers in decompressor */
+#undef memmove
 #define memmove memmove
+#undef memcpy
 #define memcpy memcpy
 #include "../../../../lib/decompress_unxz.c"
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/compressed/efi-header.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/compressed/efi-header.S
@@ -9,16 +9,22 @@
 #include <linux/sizes.h>
 
 		.macro	__nop
-#ifdef CONFIG_EFI_STUB
-		@ This is almost but not quite a NOP, since it does clobber the
-		@ condition flags. But it is the best we can do for EFI, since
-		@ PE/COFF expects the magic string "MZ" at offset 0, while the
-		@ ARM/Linux boot protocol expects an executable instruction
-		@ there.
-		.inst	MZ_MAGIC | (0x1310 << 16)	@ tstne r0, #0x4d000
-#else
  AR_CLASS(	mov	r0, r0		)
   M_CLASS(	nop.w			)
+		.endm
+
+		.macro __initial_nops
+#ifdef CONFIG_EFI_STUB
+		@ This is a two-instruction NOP, which happens to bear the
+		@ PE/COFF signature "MZ" in the first two bytes, so the kernel
+		@ is accepted as an EFI binary. Booting via the UEFI stub
+		@ will not execute those instructions, but the ARM/Linux
+		@ boot protocol does, so we need some NOPs here.
+		.inst	MZ_MAGIC | (0xe225 << 16)	@ eor r5, r5, 0x4d000
+		eor	r5, r5, 0x4d000			@ undo previous insn
+#else
+		__nop
+		__nop
 #endif
 		.endm
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/compressed/head.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/compressed/head.S
@@ -140,7 +140,7 @@
 #endif
 		.endm
 
-		.section ".start", #alloc, #execinstr
+		.section ".start", "ax"
 /*
  * sort out different calling conventions
  */
@@ -165,7 +165,8 @@
 		 * were patching the initial instructions of the kernel, i.e
 		 * had started to exploit this "patch area".
 		 */
-		.rept	7
+		__initial_nops
+		.rept	5
 		__nop
 		.endr
 #ifndef CONFIG_THUMB2_KERNEL
@@ -1142,9 +1143,9 @@
 __armv7_mmu_cache_off:
 		mrc	p15, 0, r0, c1, c0
 #ifdef CONFIG_MMU
-		bic	r0, r0, #0x000d
+		bic	r0, r0, #0x0005
 #else
-		bic	r0, r0, #0x000c
+		bic	r0, r0, #0x0004
 #endif
 		mcr	p15, 0, r0, c1, c0	@ turn MMU and cache off
 		mov	r12, lr
@@ -1273,7 +1274,7 @@
 __armv5tej_mmu_cache_flush:
 		tst	r4, #1
 		movne	pc, lr
-1:		mrc	p15, 0, r15, c7, c14, 3	@ test,clean,invalidate D cache
+1:		mrc	p15, 0, APSR_nzcv, c7, c14, 3	@ test,clean,invalidate D cache
 		bne	1b
 		mcr	p15, 0, r0, c7, c5, 0	@ flush I cache
 		mcr	p15, 0, r0, c7, c10, 4	@ drain WB
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/compressed/libfdt_env.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/compressed/libfdt_env.h
@@ -2,11 +2,13 @@
 #ifndef _ARM_LIBFDT_ENV_H
 #define _ARM_LIBFDT_ENV_H
 
+#include <linux/limits.h>
 #include <linux/types.h>
 #include <linux/string.h>
 #include <asm/byteorder.h>
 
-#define INT_MAX			((int)(~0U>>1))
+#define INT32_MAX	S32_MAX
+#define UINT32_MAX	U32_MAX
 
 typedef __be16 fdt16_t;
 typedef __be32 fdt32_t;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/compressed/piggy.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/compressed/piggy.S
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: GPL-2.0 */
-	.section .piggydata,#alloc
+	.section .piggydata, "a"
 	.globl	input_data
 input_data:
 	.incbin	"arch/arm/boot/compressed/piggy_data"
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/compressed/vmlinux.lds.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/compressed/vmlinux.lds.S
@@ -43,7 +43,7 @@
   }
   .table : ALIGN(4) {
     _table_start = .;
-    LONG(ZIMAGE_MAGIC(2))
+    LONG(ZIMAGE_MAGIC(4))
     LONG(ZIMAGE_MAGIC(0x5a534c4b))
     LONG(ZIMAGE_MAGIC(__piggy_size_addr - _start))
     LONG(ZIMAGE_MAGIC(_kernel_bss_size))
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/deflate_xip_data.sh
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/deflate_xip_data.sh
@@ -56,7 +56,7 @@
 # substitute the data section by a compressed version
 $DD if="$XIPIMAGE" count=$data_start iflag=count_bytes of="$XIPIMAGE.tmp"
 $DD if="$XIPIMAGE"  skip=$data_start iflag=skip_bytes |
-gzip -9 >> "$XIPIMAGE.tmp"
+$KGZIP -9 >> "$XIPIMAGE.tmp"
 
 # replace kernel binary
 mv -f "$XIPIMAGE.tmp" "$XIPIMAGE"
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/am335x-boneblack-common.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/am335x-boneblack-common.dtsi
@@ -131,6 +131,11 @@
 };
 
 / {
+	memory@80000000 {
+		device_type = "memory";
+		reg = <0x80000000 0x20000000>; /* 512 MB */
+	};
+
 	clk_mcasp0_fixed: clk_mcasp0_fixed {
 		#clock-cells = <0>;
 		compatible = "fixed-clock";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/am335x-cm-t335.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/am335x-cm-t335.dts
@@ -516,7 +516,7 @@
 	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&spi0_pins>;
-	ti,pindir-d0-out-d1-in = <1>;
+	ti,pindir-d0-out-d1-in;
 	/* WLS1271 WiFi */
 	wlcore: wlcore@1 {
 		compatible = "ti,wl1271";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/am335x-pcm-953.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/am335x-pcm-953.dtsi
@@ -12,22 +12,20 @@
 	compatible = "phytec,am335x-pcm-953", "phytec,am335x-phycore-som", "ti,am33xx";
 
 	/* Power */
-	regulators {
-		vcc3v3: fixedregulator@1 {
-			compatible = "regulator-fixed";
-			regulator-name = "vcc3v3";
-			regulator-min-microvolt = <3300000>;
-			regulator-max-microvolt = <3300000>;
-			regulator-boot-on;
-		};
+	vcc3v3: fixedregulator1 {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc3v3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+	};
 
-		vcc1v8: fixedregulator@2 {
-			compatible = "regulator-fixed";
-			regulator-name = "vcc1v8";
-			regulator-min-microvolt = <1800000>;
-			regulator-max-microvolt = <1800000>;
-			regulator-boot-on;
-		};
+	vcc1v8: fixedregulator2 {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc1v8";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-boot-on;
 	};
 
 	/* User IO */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/am335x-pocketbeagle.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/am335x-pocketbeagle.dts
@@ -88,7 +88,6 @@
 			AM33XX_PADCONF(AM335X_PIN_MMC0_DAT3, PIN_INPUT_PULLUP, MUX_MODE0)
 			AM33XX_PADCONF(AM335X_PIN_MMC0_CMD, PIN_INPUT_PULLUP, MUX_MODE0)
 			AM33XX_PADCONF(AM335X_PIN_MMC0_CLK, PIN_INPUT_PULLUP, MUX_MODE0)
-			AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKR, PIN_INPUT, MUX_MODE4)		/* (B12) mcasp0_aclkr.mmc0_sdwp */
 		>;
 	};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/am335x-sancloud-bbe.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/am335x-sancloud-bbe.dts
@@ -108,7 +108,7 @@
 
 &cpsw_emac0 {
 	phy-handle = <&ethphy0>;
-	phy-mode = "rgmii-txid";
+	phy-mode = "rgmii-id";
 };
 
 &i2c0 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/am33xx-l4.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/am33xx-l4.dtsi
@@ -1337,8 +1337,7 @@
 				ti,dual-volt;
 				ti,needs-special-reset;
 				ti,needs-special-hs-handling;
-				dmas = <&edma_xbar 24 0 0
-					&edma_xbar 25 0 0>;
+				dmas = <&edma 24 0>, <&edma 25 0>;
 				dma-names = "tx", "rx";
 				interrupts = <64>;
 				reg = <0x0 0x1000>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/am33xx.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/am33xx.dtsi
@@ -40,6 +40,9 @@
 		ethernet1 = &cpsw_emac1;
 		spi0 = &spi0;
 		spi1 = &spi1;
+		mmc0 = &mmc1;
+		mmc1 = &mmc2;
+		mmc2 = &mmc3;
 	};
 
 	cpus {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/am3517-evm.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/am3517-evm.dts
@@ -160,6 +160,8 @@
 
 	/* HS USB Host PHY on PORT 1 */
 	hsusb1_phy: hsusb1_phy {
+		pinctrl-names = "default";
+		pinctrl-0 = <&hsusb1_rst_pins>;
 		compatible = "usb-nop-xceiv";
 		reset-gpios = <&gpio2 25 GPIO_ACTIVE_LOW>; /* gpio_57 */
 		#phy-cells = <0>;
@@ -167,7 +169,9 @@
 };
 
 &davinci_emac {
-	     status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&ethernet_pins>;
+	status = "okay";
 };
 
 &davinci_mdio {
@@ -192,6 +196,8 @@
 };
 
 &i2c2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c2_pins>;
 	clock-frequency = <400000>;
 	/* User DIP swithes [1:8] / User LEDS [1:2] */
 	tca6416: gpio@21 {
@@ -204,6 +210,8 @@
 };
 
 &i2c3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c3_pins>;
 	clock-frequency = <400000>;
 };
 
@@ -222,6 +230,8 @@
 };
 
 &usbhshost {
+	pinctrl-names = "default";
+	pinctrl-0 = <&hsusb1_pins>;
 	port1-mode = "ehci-phy";
 };
 
@@ -230,8 +240,35 @@
 };
 
 &omap3_pmx_core {
-	pinctrl-names = "default";
-	pinctrl-0 = <&hsusb1_rst_pins>;
+
+	ethernet_pins: pinmux_ethernet_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x21fe, PIN_INPUT | MUX_MODE0) /* rmii_mdio_data */
+			OMAP3_CORE1_IOPAD(0x2200, MUX_MODE0) /* rmii_mdio_clk */
+			OMAP3_CORE1_IOPAD(0x2202, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rmii_rxd0 */
+			OMAP3_CORE1_IOPAD(0x2204, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rmii_rxd1 */
+			OMAP3_CORE1_IOPAD(0x2206, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rmii_crs_dv */
+			OMAP3_CORE1_IOPAD(0x2208, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* rmii_rxer */
+			OMAP3_CORE1_IOPAD(0x220a, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* rmii_txd0 */
+			OMAP3_CORE1_IOPAD(0x220c, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* rmii_txd1 */
+			OMAP3_CORE1_IOPAD(0x220e, PIN_OUTPUT_PULLDOWN |MUX_MODE0) /* rmii_txen */
+			OMAP3_CORE1_IOPAD(0x2210, PIN_INPUT_PULLDOWN | MUX_MODE0) /* rmii_50mhz_clk */
+		>;
+	};
+
+	i2c2_pins: pinmux_i2c2_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x21be, PIN_INPUT_PULLUP | MUX_MODE0)  /* i2c2_scl */
+			OMAP3_CORE1_IOPAD(0x21c0, PIN_INPUT_PULLUP | MUX_MODE0)  /* i2c2_sda */
+		>;
+	};
+
+	i2c3_pins: pinmux_i2c3_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x21c2, PIN_INPUT_PULLUP | MUX_MODE0)  /* i2c3_scl */
+			OMAP3_CORE1_IOPAD(0x21c4, PIN_INPUT_PULLUP | MUX_MODE0)  /* i2c3_sda */
+		>;
+	};
 
 	leds_pins: pinmux_leds_pins {
 		pinctrl-single,pins = <
@@ -299,8 +336,6 @@
 };
 
 &omap3_pmx_core2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&hsusb1_pins>;
 
 	hsusb1_pins: pinmux_hsusb1_pins {
 		pinctrl-single,pins = <
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/am3517-som.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/am3517-som.dtsi
@@ -69,6 +69,8 @@
 };
 
 &i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c1_pins>;
 	clock-frequency = <400000>;
 
 	s35390a: s35390a@30 {
@@ -179,6 +181,13 @@
 
 &omap3_pmx_core {
 
+	i2c1_pins: pinmux_i2c1_pins {
+		pinctrl-single,pins = <
+			OMAP3_CORE1_IOPAD(0x21ba, PIN_INPUT_PULLUP | MUX_MODE0)  /* i2c1_scl */
+			OMAP3_CORE1_IOPAD(0x21bc, PIN_INPUT_PULLUP | MUX_MODE0)  /* i2c1_sda */
+		>;
+	};
+
 	wl12xx_buffer_pins: pinmux_wl12xx_buffer_pins {
 		pinctrl-single,pins = <
 			OMAP3_CORE1_IOPAD(0x2156, PIN_OUTPUT | MUX_MODE4)  /* mmc1_dat7.gpio_129 */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/am437x-gp-evm.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/am437x-gp-evm.dts
@@ -86,7 +86,7 @@
 		};
 
 	lcd0: display {
-		compatible = "osddisplays,osd057T0559-34ts", "panel-dpi";
+		compatible = "osddisplays,osd070t1718-19ts", "panel-dpi";
 		label = "lcd";
 
 		backlight = <&lcd_bl>;
@@ -829,11 +829,14 @@
 	status = "okay";
 };
 
+&gpio5_target {
+	ti,no-reset-on-init;
+};
+
 &gpio5 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&display_mux_pins>;
 	status = "okay";
-	ti,no-reset-on-init;
 
 	p8 {
 		/*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/am437x-idk-evm.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/am437x-idk-evm.dts
@@ -526,11 +526,11 @@
 	 * Supply voltage supervisor on board will not allow opp50 so
 	 * disable it and set opp100 as suspend OPP.
 	 */
-	opp50@300000000 {
+	opp50-300000000 {
 		status = "disabled";
 	};
 
-	opp100@600000000 {
+	opp100-600000000 {
 		opp-suspend;
 	};
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/am437x-l4.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/am437x-l4.dtsi
@@ -1576,8 +1576,9 @@
 			reg-names = "rev";
 			ti,hwmods = "d_can0";
 			/* Domains (P, C): per_pwrdm, l4ls_clkdm */
-			clocks = <&l4ls_clkctrl AM4_L4LS_D_CAN0_CLKCTRL 0>;
-			clock-names = "fck";
+			clocks = <&l4ls_clkctrl AM4_L4LS_D_CAN0_CLKCTRL 0>,
+			<&dcan0_fck>;
+			clock-names = "fck", "osc";
 			#address-cells = <1>;
 			#size-cells = <1>;
 			ranges = <0x0 0xcc000 0x2000>;
@@ -1585,6 +1586,8 @@
 			dcan0: can@0 {
 				compatible = "ti,am4372-d_can", "ti,am3352-d_can";
 				reg = <0x0 0x2000>;
+				clocks = <&dcan0_fck>;
+				clock-names = "fck";
 				syscon-raminit = <&scm_conf 0x644 0>;
 				interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
 				status = "disabled";
@@ -1597,8 +1600,9 @@
 			reg-names = "rev";
 			ti,hwmods = "d_can1";
 			/* Domains (P, C): per_pwrdm, l4ls_clkdm */
-			clocks = <&l4ls_clkctrl AM4_L4LS_D_CAN1_CLKCTRL 0>;
-			clock-names = "fck";
+			clocks = <&l4ls_clkctrl AM4_L4LS_D_CAN1_CLKCTRL 0>,
+			<&dcan1_fck>;
+			clock-names = "fck", "osc";
 			#address-cells = <1>;
 			#size-cells = <1>;
 			ranges = <0x0 0xd0000 0x2000>;
@@ -1606,6 +1610,8 @@
 			dcan1: can@0 {
 				compatible = "ti,am4372-d_can", "ti,am3352-d_can";
 				reg = <0x0 0x2000>;
+				clocks = <&dcan1_fck>;
+				clock-names = "fck";
 				syscon-raminit = <&scm_conf 0x644 1>;
 				interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
 				status = "disabled";
@@ -2071,7 +2077,7 @@
 			};
 		};
 
-		target-module@22000 {			/* 0x48322000, ap 116 64.0 */
+		gpio5_target: target-module@22000 {		/* 0x48322000, ap 116 64.0 */
 			compatible = "ti,sysc-omap2", "ti,sysc";
 			ti,hwmods = "gpio6";
 			reg = <0x22000 0x4>,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/am43x-epos-evm.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/am43x-epos-evm.dts
@@ -42,7 +42,7 @@
 	};
 
 	lcd0: display {
-		compatible = "osddisplays,osd057T0559-34ts", "panel-dpi";
+		compatible = "osddisplays,osd070t1718-19ts", "panel-dpi";
 		label = "lcd";
 
 		backlight = <&lcd_bl>;
@@ -589,7 +589,7 @@
 	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&i2c0_pins>;
-	clock-frequency = <400000>;
+	clock-frequency = <100000>;
 
 	tps65218: tps65218@24 {
 		reg = <0x24>;
@@ -848,6 +848,7 @@
 	pinctrl-names = "default", "sleep";
 	pinctrl-0 = <&spi0_pins_default>;
 	pinctrl-1 = <&spi0_pins_sleep>;
+	ti,pindir-d0-out-d1-in;
 };
 
 &spi1 {
@@ -855,6 +856,7 @@
 	pinctrl-names = "default", "sleep";
 	pinctrl-0 = <&spi1_pins_default>;
 	pinctrl-1 = <&spi1_pins_sleep>;
+	ti,pindir-d0-out-d1-in;
 };
 
 &usb2_phy1 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/am43xx-clocks.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/am43xx-clocks.dtsi
@@ -704,6 +704,60 @@
 		ti,bit-shift = <8>;
 		reg = <0x2a48>;
 	};
+
+	clkout1_osc_div_ck: clkout1-osc-div-ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&sys_clkin_ck>;
+		ti,bit-shift = <20>;
+		ti,max-div = <4>;
+		reg = <0x4100>;
+	};
+
+	clkout1_src2_mux_ck: clkout1-src2-mux-ck {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&clk_rc32k_ck>, <&sysclk_div>, <&dpll_ddr_m2_ck>,
+			 <&dpll_per_m2_ck>, <&dpll_disp_m2_ck>,
+			 <&dpll_mpu_m2_ck>;
+		reg = <0x4100>;
+	};
+
+	clkout1_src2_pre_div_ck: clkout1-src2-pre-div-ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&clkout1_src2_mux_ck>;
+		ti,bit-shift = <4>;
+		ti,max-div = <8>;
+		reg = <0x4100>;
+	};
+
+	clkout1_src2_post_div_ck: clkout1-src2-post-div-ck {
+		#clock-cells = <0>;
+		compatible = "ti,divider-clock";
+		clocks = <&clkout1_src2_pre_div_ck>;
+		ti,bit-shift = <8>;
+		ti,max-div = <32>;
+		ti,index-power-of-two;
+		reg = <0x4100>;
+	};
+
+	clkout1_mux_ck: clkout1-mux-ck {
+		#clock-cells = <0>;
+		compatible = "ti,mux-clock";
+		clocks = <&clkout1_osc_div_ck>, <&clk_rc32k_ck>,
+			 <&clkout1_src2_post_div_ck>, <&dpll_extdev_m2_ck>;
+		ti,bit-shift = <16>;
+		reg = <0x4100>;
+	};
+
+	clkout1_ck: clkout1-ck {
+		#clock-cells = <0>;
+		compatible = "ti,gate-clock";
+		clocks = <&clkout1_mux_ck>;
+		ti,bit-shift = <23>;
+		reg = <0x4100>;
+	};
 };
 
 &prcm {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/am571x-idk.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/am571x-idk.dts
@@ -167,11 +167,7 @@
 
 &pcie1_rc {
 	status = "okay";
-	gpios = <&gpio3 23 GPIO_ACTIVE_HIGH>;
-};
-
-&pcie1_ep {
-	gpios = <&gpio3 23 GPIO_ACTIVE_HIGH>;
+	gpios = <&gpio5 18 GPIO_ACTIVE_HIGH>;
 };
 
 &mmc1 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/am572x-idk-common.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/am572x-idk-common.dtsi
@@ -147,10 +147,6 @@
 	gpios = <&gpio3 23 GPIO_ACTIVE_HIGH>;
 };
 
-&pcie1_ep {
-	gpios = <&gpio3 23 GPIO_ACTIVE_HIGH>;
-};
-
 &mailbox5 {
 	status = "okay";
 	mbox_ipu1_ipc3x: mbox_ipu1_ipc3x {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi
@@ -29,6 +29,27 @@
 		reg = <0x0 0x80000000 0x0 0x80000000>;
 	};
 
+	main_12v0: fixedregulator-main_12v0 {
+		/* main supply */
+		compatible = "regulator-fixed";
+		regulator-name = "main_12v0";
+		regulator-min-microvolt = <12000000>;
+		regulator-max-microvolt = <12000000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	evm_5v0: fixedregulator-evm_5v0 {
+		/* Output of TPS54531D */
+		compatible = "regulator-fixed";
+		regulator-name = "evm_5v0";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		vin-supply = <&main_12v0>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
 	vdd_3v3: fixedregulator-vdd_3v3 {
 		compatible = "regulator-fixed";
 		regulator-name = "vdd_3v3";
@@ -547,10 +568,6 @@
 	gpios = <&gpio2 8 GPIO_ACTIVE_LOW>;
 };
 
-&pcie1_ep {
-	gpios = <&gpio2 8 GPIO_ACTIVE_LOW>;
-};
-
 &mcasp3 {
 	#sound-dai-cells = <0>;
 	assigned-clocks = <&l4per2_clkctrl DRA7_L4PER2_MCASP3_CLKCTRL 24>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/am57xx-cl-som-am57x.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/am57xx-cl-som-am57x.dts
@@ -527,7 +527,7 @@
 
 		interrupt-parent = <&gpio1>;
 		interrupts = <31 0>;
-		pendown-gpio = <&gpio1 31 0>;
+		pendown-gpio = <&gpio1 31 GPIO_ACTIVE_LOW>;
 
 
 		ti,x-min = /bits/ 16 <0x0>;
@@ -611,12 +611,11 @@
 	>;
 };
 
-&gpio3 {
-	status = "okay";
+&gpio3_target {
 	ti,no-reset-on-init;
 };
 
-&gpio2 {
+&gpio2_target {
 	status = "okay";
 	ti,no-reset-on-init;
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/arm-realview-pb1176.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/arm-realview-pb1176.dts
@@ -435,7 +435,7 @@
 
 		/* Direct-mapped development chip ROM */
 		pb1176_rom@10200000 {
-			compatible = "direct-mapped";
+			compatible = "mtd-rom";
 			reg = <0x10200000 0x4000>;
 			bank-width = <1>;
 		};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/armada-370.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/armada-370.dtsi
@@ -74,7 +74,7 @@
 
 			pcie2: pcie@2,0 {
 				device_type = "pci";
-				assigned-addresses = <0x82002800 0 0x80000 0 0x2000>;
+				assigned-addresses = <0x82001000 0 0x80000 0 0x2000>;
 				reg = <0x1000 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/armada-375.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/armada-375.dtsi
@@ -584,7 +584,7 @@
 
 			pcie1: pcie@2,0 {
 				device_type = "pci";
-				assigned-addresses = <0x82000800 0 0x44000 0 0x2000>;
+				assigned-addresses = <0x82001000 0 0x44000 0 0x2000>;
 				reg = <0x1000 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/armada-380.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/armada-380.dtsi
@@ -79,7 +79,7 @@
 			/* x1 port */
 			pcie@2,0 {
 				device_type = "pci";
-				assigned-addresses = <0x82000800 0 0x40000 0 0x2000>;
+				assigned-addresses = <0x82001000 0 0x40000 0 0x2000>;
 				reg = <0x1000 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
@@ -98,7 +98,7 @@
 			/* x1 port */
 			pcie@3,0 {
 				device_type = "pci";
-				assigned-addresses = <0x82000800 0 0x44000 0 0x2000>;
+				assigned-addresses = <0x82001800 0 0x44000 0 0x2000>;
 				reg = <0x1800 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/armada-385-turris-omnia.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/armada-385-turris-omnia.dts
@@ -22,6 +22,12 @@
 		stdout-path = &uart0;
 	};
 
+	aliases {
+		ethernet0 = &eth0;
+		ethernet1 = &eth1;
+		ethernet2 = &eth2;
+	};
+
 	memory {
 		device_type = "memory";
 		reg = <0x00000000 0x40000000>; /* 1024 MB */
@@ -236,6 +242,7 @@
 		status = "okay";
 		compatible = "ethernet-phy-id0141.0DD1", "ethernet-phy-ieee802.3-c22";
 		reg = <1>;
+		marvell,reg-init = <3 18 0 0x4985>;
 
 		/* irq is connected to &pcawan pin 7 */
 	};
@@ -290,7 +297,17 @@
 				};
 			};
 
-			/* port 6 is connected to eth0 */
+			ports@6 {
+				reg = <6>;
+				label = "cpu";
+				ethernet = <&eth0>;
+				phy-mode = "rgmii-id";
+
+				fixed-link {
+					speed = <1000>;
+					full-duplex;
+				};
+			};
 		};
 	};
 };
@@ -306,7 +323,7 @@
 		marvell,function = "spi0";
 	};
 
-	spi0cs1_pins: spi0cs1-pins {
+	spi0cs2_pins: spi0cs2-pins {
 		marvell,pins = "mpp26";
 		marvell,function = "spi0";
 	};
@@ -341,7 +358,7 @@
 		};
 	};
 
-	/* MISO, MOSI, SCLK and CS1 are routed to pin header CN11 */
+	/* MISO, MOSI, SCLK and CS2 are routed to pin header CN11 */
 };
 
 &uart0 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/armada-385.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/armada-385.dtsi
@@ -84,7 +84,7 @@
 			/* x1 port */
 			pcie2: pcie@2,0 {
 				device_type = "pci";
-				assigned-addresses = <0x82000800 0 0x40000 0 0x2000>;
+				assigned-addresses = <0x82001000 0 0x40000 0 0x2000>;
 				reg = <0x1000 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
@@ -103,7 +103,7 @@
 			/* x1 port */
 			pcie3: pcie@3,0 {
 				device_type = "pci";
-				assigned-addresses = <0x82000800 0 0x44000 0 0x2000>;
+				assigned-addresses = <0x82001800 0 0x44000 0 0x2000>;
 				reg = <0x1800 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
@@ -125,7 +125,7 @@
 			 */
 			pcie4: pcie@4,0 {
 				device_type = "pci";
-				assigned-addresses = <0x82000800 0 0x48000 0 0x2000>;
+				assigned-addresses = <0x82002000 0 0x48000 0 0x2000>;
 				reg = <0x2000 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/armada-388-helios4.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/armada-388-helios4.dts
@@ -70,6 +70,9 @@
 
 	system-leds {
 		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&helios_system_led_pins>;
+
 		status-led {
 			label = "helios4:green:status";
 			gpios = <&gpio0 24 GPIO_ACTIVE_LOW>;
@@ -86,6 +89,9 @@
 
 	io-leds {
 		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&helios_io_led_pins>;
+
 		sata1-led {
 			label = "helios4:green:ata1";
 			gpios = <&gpio1 17 GPIO_ACTIVE_LOW>;
@@ -121,11 +127,15 @@
 	fan1: j10-pwm {
 		compatible = "pwm-fan";
 		pwms = <&gpio1 9 40000>;	/* Target freq:25 kHz */
+		pinctrl-names = "default";
+		pinctrl-0 = <&helios_fan1_pins>;
 	};
 
 	fan2: j17-pwm {
 		compatible = "pwm-fan";
 		pwms = <&gpio1 23 40000>;	/* Target freq:25 kHz */
+		pinctrl-names = "default";
+		pinctrl-0 = <&helios_fan2_pins>;
 	};
 
 	usb2_phy: usb2-phy {
@@ -291,16 +301,22 @@
 						       "mpp39", "mpp40";
 					marvell,function = "sd0";
 				};
-				helios_led_pins: helios-led-pins {
-					marvell,pins = "mpp24", "mpp25",
-						       "mpp49", "mpp50",
+				helios_system_led_pins: helios-system-led-pins {
+					marvell,pins = "mpp24", "mpp25";
+					marvell,function = "gpio";
+				};
+				helios_io_led_pins: helios-io-led-pins {
+					marvell,pins = "mpp49", "mpp50",
 						       "mpp52", "mpp53",
 						       "mpp54";
 					marvell,function = "gpio";
 				};
-				helios_fan_pins: helios-fan-pins {
-					marvell,pins = "mpp41", "mpp43",
-						       "mpp48", "mpp55";
+				helios_fan1_pins: helios_fan1_pins {
+					marvell,pins = "mpp41", "mpp43";
+					marvell,function = "gpio";
+				};
+				helios_fan2_pins: helios_fan2_pins {
+					marvell,pins = "mpp48", "mpp55";
 					marvell,function = "gpio";
 				};
 				microsom_spi1_cs_pins: spi1-cs-pins {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/armada-38x.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/armada-38x.dtsi
@@ -165,7 +165,7 @@
 			};
 
 			uart0: serial@12000 {
-				compatible = "marvell,armada-38x-uart";
+				compatible = "marvell,armada-38x-uart", "ns16550a";
 				reg = <0x12000 0x100>;
 				reg-shift = <2>;
 				interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
@@ -175,7 +175,7 @@
 			};
 
 			uart1: serial@12100 {
-				compatible = "marvell,armada-38x-uart";
+				compatible = "marvell,armada-38x-uart", "ns16550a";
 				reg = <0x12100 0x100>;
 				reg-shift = <2>;
 				interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
@@ -339,7 +339,8 @@
 
 			comphy: phy@18300 {
 				compatible = "marvell,armada-380-comphy";
-				reg = <0x18300 0x100>;
+				reg-names = "comphy", "conf";
+				reg = <0x18300 0x100>, <0x18460 4>;
 				#address-cells = <1>;
 				#size-cells = <0>;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/armada-39x.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/armada-39x.dtsi
@@ -457,7 +457,7 @@
 			/* x1 port */
 			pcie@2,0 {
 				device_type = "pci";
-				assigned-addresses = <0x82000800 0 0x40000 0 0x2000>;
+				assigned-addresses = <0x82001000 0 0x40000 0 0x2000>;
 				reg = <0x1000 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
@@ -476,7 +476,7 @@
 			/* x1 port */
 			pcie@3,0 {
 				device_type = "pci";
-				assigned-addresses = <0x82000800 0 0x44000 0 0x2000>;
+				assigned-addresses = <0x82001800 0 0x44000 0 0x2000>;
 				reg = <0x1800 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
@@ -498,7 +498,7 @@
 			 */
 			pcie@4,0 {
 				device_type = "pci";
-				assigned-addresses = <0x82000800 0 0x48000 0 0x2000>;
+				assigned-addresses = <0x82002000 0 0x48000 0 0x2000>;
 				reg = <0x2000 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/armada-xp-98dx3236.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/armada-xp-98dx3236.dtsi
@@ -266,11 +266,6 @@
 	reg = <0x11000 0x100>;
 };
 
-&i2c1 {
-	compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c";
-	reg = <0x11100 0x100>;
-};
-
 &mpic {
 	reg = <0x20a00 0x2d0>, <0x21070 0x58>;
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/armada-xp-mv78230.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/armada-xp-mv78230.dtsi
@@ -97,7 +97,7 @@
 
 			pcie2: pcie@2,0 {
 				device_type = "pci";
-				assigned-addresses = <0x82000800 0 0x44000 0 0x2000>;
+				assigned-addresses = <0x82001000 0 0x44000 0 0x2000>;
 				reg = <0x1000 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
@@ -115,7 +115,7 @@
 
 			pcie3: pcie@3,0 {
 				device_type = "pci";
-				assigned-addresses = <0x82000800 0 0x48000 0 0x2000>;
+				assigned-addresses = <0x82001800 0 0x48000 0 0x2000>;
 				reg = <0x1800 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
@@ -133,7 +133,7 @@
 
 			pcie4: pcie@4,0 {
 				device_type = "pci";
-				assigned-addresses = <0x82000800 0 0x4c000 0 0x2000>;
+				assigned-addresses = <0x82002000 0 0x4c000 0 0x2000>;
 				reg = <0x2000 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
@@ -151,7 +151,7 @@
 
 			pcie5: pcie@5,0 {
 				device_type = "pci";
-				assigned-addresses = <0x82000800 0 0x80000 0 0x2000>;
+				assigned-addresses = <0x82002800 0 0x80000 0 0x2000>;
 				reg = <0x2800 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/armada-xp-mv78260.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/armada-xp-mv78260.dtsi
@@ -112,7 +112,7 @@
 
 			pcie2: pcie@2,0 {
 				device_type = "pci";
-				assigned-addresses = <0x82000800 0 0x44000 0 0x2000>;
+				assigned-addresses = <0x82001000 0 0x44000 0 0x2000>;
 				reg = <0x1000 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
@@ -130,7 +130,7 @@
 
 			pcie3: pcie@3,0 {
 				device_type = "pci";
-				assigned-addresses = <0x82000800 0 0x48000 0 0x2000>;
+				assigned-addresses = <0x82001800 0 0x48000 0 0x2000>;
 				reg = <0x1800 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
@@ -148,7 +148,7 @@
 
 			pcie4: pcie@4,0 {
 				device_type = "pci";
-				assigned-addresses = <0x82000800 0 0x4c000 0 0x2000>;
+				assigned-addresses = <0x82002000 0 0x4c000 0 0x2000>;
 				reg = <0x2000 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
@@ -166,7 +166,7 @@
 
 			pcie5: pcie@5,0 {
 				device_type = "pci";
-				assigned-addresses = <0x82000800 0 0x80000 0 0x2000>;
+				assigned-addresses = <0x82002800 0 0x80000 0 0x2000>;
 				reg = <0x2800 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
@@ -184,7 +184,7 @@
 
 			pcie6: pcie@6,0 {
 				device_type = "pci";
-				assigned-addresses = <0x82000800 0 0x84000 0 0x2000>;
+				assigned-addresses = <0x82003000 0 0x84000 0 0x2000>;
 				reg = <0x3000 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
@@ -202,7 +202,7 @@
 
 			pcie7: pcie@7,0 {
 				device_type = "pci";
-				assigned-addresses = <0x82000800 0 0x88000 0 0x2000>;
+				assigned-addresses = <0x82003800 0 0x88000 0 0x2000>;
 				reg = <0x3800 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
@@ -220,7 +220,7 @@
 
 			pcie8: pcie@8,0 {
 				device_type = "pci";
-				assigned-addresses = <0x82000800 0 0x8c000 0 0x2000>;
+				assigned-addresses = <0x82004000 0 0x8c000 0 0x2000>;
 				reg = <0x4000 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
@@ -238,7 +238,7 @@
 
 			pcie9: pcie@9,0 {
 				device_type = "pci";
-				assigned-addresses = <0x82000800 0 0x42000 0 0x2000>;
+				assigned-addresses = <0x82004800 0 0x42000 0 0x2000>;
 				reg = <0x4800 0 0 0 0>;
 				#address-cells = <3>;
 				#size-cells = <2>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/aspeed-ast2500-evb.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/aspeed-ast2500-evb.dts
@@ -5,7 +5,7 @@
 
 / {
 	model = "AST2500 EVB";
-	compatible = "aspeed,ast2500";
+	compatible = "aspeed,ast2500-evb", "aspeed,ast2500";
 
 	aliases {
 		serial4 = &uart5;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/aspeed-ast2600-evb.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/aspeed-ast2600-evb.dts
@@ -7,7 +7,7 @@
 
 / {
 	model = "AST2600 EVB";
-	compatible = "aspeed,ast2600";
+	compatible = "aspeed,ast2600-evb-a1", "aspeed,ast2600";
 
 	aliases {
 		serial4 = &uart5;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/aspeed-bmc-facebook-tiogapass.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/aspeed-bmc-facebook-tiogapass.dts
@@ -81,11 +81,6 @@
 	status = "okay";
 };
 
-&vuart {
-	// VUART Host Console
-	status = "okay";
-};
-
 &uart1 {
 	// Host Console
 	status = "okay";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/aspeed-bmc-intel-s2600wf.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/aspeed-bmc-intel-s2600wf.dts
@@ -22,9 +22,9 @@
 		#size-cells = <1>;
 		ranges;
 
-		vga_memory: framebuffer@7f000000 {
+		vga_memory: framebuffer@9f000000 {
 			no-map;
-			reg = <0x7f000000 0x01000000>;
+			reg = <0x9f000000 0x01000000>; /* 16M */
 		};
 	};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/aspeed-g4.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/aspeed-g4.dtsi
@@ -371,6 +371,7 @@
 						compatible = "aspeed,ast2400-ibt-bmc";
 						reg = <0xc0 0x18>;
 						interrupts = <8>;
+						clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
 						status = "disabled";
 					};
 				};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/aspeed-g5.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/aspeed-g5.dtsi
@@ -464,6 +464,7 @@
 						compatible = "aspeed,ast2500-ibt-bmc";
 						reg = <0xc0 0x18>;
 						interrupts = <8>;
+						clocks = <&syscon ASPEED_CLK_GATE_LCLK>;
 						status = "disabled";
 					};
 				};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/aspeed-g6-pinctrl.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/aspeed-g6-pinctrl.dtsi
@@ -117,11 +117,6 @@
 		groups = "FWSPID";
 	};
 
-	pinctrl_fwqspid_default: fwqspid_default {
-		function = "FWQSPID";
-		groups = "FWQSPID";
-	};
-
 	pinctrl_fwspiwp_default: fwspiwp_default {
 		function = "FWSPIWP";
 		groups = "FWSPIWP";
@@ -208,12 +203,12 @@
 	};
 
 	pinctrl_hvi3c3_default: hvi3c3_default {
-		function = "HVI3C3";
+		function = "I3C3";
 		groups = "HVI3C3";
 	};
 
 	pinctrl_hvi3c4_default: hvi3c4_default {
-		function = "HVI3C4";
+		function = "I3C4";
 		groups = "HVI3C4";
 	};
 
@@ -653,12 +648,12 @@
 	};
 
 	pinctrl_qspi1_default: qspi1_default {
-		function = "QSPI1";
+		function = "SPI1";
 		groups = "QSPI1";
 	};
 
 	pinctrl_qspi2_default: qspi2_default {
-		function = "QSPI2";
+		function = "SPI2";
 		groups = "QSPI2";
 	};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/at91-sama5d27_som1.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/at91-sama5d27_som1.dtsi
@@ -44,8 +44,8 @@
 				pinctrl-0 = <&pinctrl_macb0_default>;
 				phy-mode = "rmii";
 
-				ethernet-phy@0 {
-					reg = <0x0>;
+				ethernet-phy@7 {
+					reg = <0x7>;
 					interrupt-parent = <&pioA>;
 					interrupts = <PIN_PD31 IRQ_TYPE_LEVEL_LOW>;
 					pinctrl-names = "default";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/at91-sama5d27_som1_ek.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/at91-sama5d27_som1_ek.dts
@@ -69,7 +69,6 @@
 			isc: isc@f0008000 {
 				pinctrl-names = "default";
 				pinctrl-0 = <&pinctrl_isc_base &pinctrl_isc_data_8bit &pinctrl_isc_data_9_10 &pinctrl_isc_data_11_12>;
-				status = "okay";
 			};
 
 			qspi1: spi@f0024000 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/at91-sama5d2_ptc_ek.dts
@@ -40,7 +40,7 @@
 
 	ahb {
 		usb0: gadget@300000 {
-			atmel,vbus-gpio = <&pioA PIN_PA27 GPIO_ACTIVE_HIGH>;
+			atmel,vbus-gpio = <&pioA PIN_PB11 GPIO_ACTIVE_HIGH>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_usba_vbus>;
 			status = "okay";
@@ -125,8 +125,6 @@
 			bus-width = <8>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_sdmmc0_default>;
-			non-removable;
-			mmc-ddr-1_8v;
 			status = "okay";
 		};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/at91-sama5d3_xplained.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/at91-sama5d3_xplained.dts
@@ -242,6 +242,11 @@
 						atmel,pins =
 							<AT91_PIOE 9 AT91_PERIPH_GPIO AT91_PINCTRL_DEGLITCH>;	/* PE9, conflicts with A9 */
 					};
+					pinctrl_usb_default: usb_default {
+						atmel,pins =
+							<AT91_PIOE 3 AT91_PERIPH_GPIO AT91_PINCTRL_NONE
+							 AT91_PIOE 4 AT91_PERIPH_GPIO AT91_PINCTRL_NONE>;
+					};
 				};
 			};
 		};
@@ -259,6 +264,8 @@
 					   &pioE 3 GPIO_ACTIVE_LOW
 					   &pioE 4 GPIO_ACTIVE_LOW
 					  >;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_usb_default>;
 			status = "okay";
 		};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/at91-sama5d4_xplained.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/at91-sama5d4_xplained.dts
@@ -133,6 +133,11 @@
 						atmel,pins =
 							<AT91_PIOE 31 AT91_PERIPH_GPIO AT91_PINCTRL_DEGLITCH>;
 					};
+					pinctrl_usb_default: usb_default {
+						atmel,pins =
+							<AT91_PIOE 11 AT91_PERIPH_GPIO AT91_PINCTRL_NONE
+							 AT91_PIOE 14 AT91_PERIPH_GPIO AT91_PINCTRL_NONE>;
+					};
 					pinctrl_key_gpio: key_gpio_0 {
 						atmel,pins =
 							<AT91_PIOE 8 AT91_PERIPH_GPIO AT91_PINCTRL_PULL_UP_DEGLITCH>;
@@ -158,6 +163,8 @@
 					   &pioE 11 GPIO_ACTIVE_HIGH
 					   &pioE 14 GPIO_ACTIVE_HIGH
 					  >;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pinctrl_usb_default>;
 			status = "okay";
 		};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/at91-tse850-3.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/at91-tse850-3.dts
@@ -262,7 +262,7 @@
 &macb1 {
 	status = "okay";
 
-	phy-mode = "rgmii";
+	phy-mode = "rmii";
 
 	#address-cells = <1>;
 	#size-cells = <0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/at91sam9260.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/at91sam9260.dtsi
@@ -187,7 +187,7 @@
 				usart0 {
 					pinctrl_usart0: usart0-0 {
 						atmel,pins =
-							<AT91_PIOB 4 AT91_PERIPH_A AT91_PINCTRL_NONE
+							<AT91_PIOB 4 AT91_PERIPH_A AT91_PINCTRL_PULL_UP
 							 AT91_PIOB 5 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>;
 					};
 
@@ -221,7 +221,7 @@
 				usart1 {
 					pinctrl_usart1: usart1-0 {
 						atmel,pins =
-							<AT91_PIOB 6 AT91_PERIPH_A AT91_PINCTRL_NONE
+							<AT91_PIOB 6 AT91_PERIPH_A AT91_PINCTRL_PULL_UP
 							 AT91_PIOB 7 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>;
 					};
 
@@ -239,7 +239,7 @@
 				usart2 {
 					pinctrl_usart2: usart2-0 {
 						atmel,pins =
-							<AT91_PIOB 8 AT91_PERIPH_A AT91_PINCTRL_NONE
+							<AT91_PIOB 8 AT91_PERIPH_A AT91_PINCTRL_PULL_UP
 							 AT91_PIOB 9 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>;
 					};
 
@@ -257,7 +257,7 @@
 				usart3 {
 					pinctrl_usart3: usart3-0 {
 						atmel,pins =
-							<AT91_PIOB 10 AT91_PERIPH_A AT91_PINCTRL_NONE
+							<AT91_PIOB 10 AT91_PERIPH_A AT91_PINCTRL_PULL_UP
 							 AT91_PIOB 11 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>;
 					};
 
@@ -275,7 +275,7 @@
 				uart0 {
 					pinctrl_uart0: uart0-0 {
 						atmel,pins =
-							<AT91_PIOA 31 AT91_PERIPH_B AT91_PINCTRL_NONE
+							<AT91_PIOA 31 AT91_PERIPH_B AT91_PINCTRL_PULL_UP
 							 AT91_PIOA 30 AT91_PERIPH_B AT91_PINCTRL_PULL_UP>;
 					};
 				};
@@ -283,7 +283,7 @@
 				uart1 {
 					pinctrl_uart1: uart1-0 {
 						atmel,pins =
-							<AT91_PIOB 12 AT91_PERIPH_A AT91_PINCTRL_NONE
+							<AT91_PIOB 12 AT91_PERIPH_A AT91_PINCTRL_PULL_UP
 							 AT91_PIOB 13 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>;
 					};
 				};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/at91sam9261.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/at91sam9261.dtsi
@@ -329,7 +329,7 @@
 				usart0 {
 					pinctrl_usart0: usart0-0 {
 						atmel,pins =
-							<AT91_PIOC 8 AT91_PERIPH_A AT91_PINCTRL_NONE>,
+							<AT91_PIOC 8 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>,
 							<AT91_PIOC 9 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>;
 					};
 
@@ -347,7 +347,7 @@
 				usart1 {
 					pinctrl_usart1: usart1-0 {
 						atmel,pins =
-							<AT91_PIOC 12 AT91_PERIPH_A AT91_PINCTRL_NONE>,
+							<AT91_PIOC 12 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>,
 							<AT91_PIOC 13 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>;
 					};
 
@@ -365,7 +365,7 @@
 				usart2 {
 					pinctrl_usart2: usart2-0 {
 						atmel,pins =
-							<AT91_PIOC 14 AT91_PERIPH_A AT91_PINCTRL_NONE>,
+							<AT91_PIOC 14 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>,
 							<AT91_PIOC 15 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>;
 					};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/at91sam9261ek.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/at91sam9261ek.dts
@@ -156,7 +156,7 @@
 					compatible = "ti,ads7843";
 					interrupts-extended = <&pioC 2 IRQ_TYPE_EDGE_BOTH>;
 					spi-max-frequency = <3000000>;
-					pendown-gpio = <&pioC 2 GPIO_ACTIVE_HIGH>;
+					pendown-gpio = <&pioC 2 GPIO_ACTIVE_LOW>;
 
 					ti,x-min = /bits/ 16 <150>;
 					ti,x-max = /bits/ 16 <3830>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/at91sam9263.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/at91sam9263.dtsi
@@ -183,7 +183,7 @@
 				usart0 {
 					pinctrl_usart0: usart0-0 {
 						atmel,pins =
-							<AT91_PIOA 26 AT91_PERIPH_A AT91_PINCTRL_NONE
+							<AT91_PIOA 26 AT91_PERIPH_A AT91_PINCTRL_PULL_UP
 							 AT91_PIOA 27 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>;
 					};
 
@@ -201,7 +201,7 @@
 				usart1 {
 					pinctrl_usart1: usart1-0 {
 						atmel,pins =
-							<AT91_PIOD 0 AT91_PERIPH_A AT91_PINCTRL_NONE
+							<AT91_PIOD 0 AT91_PERIPH_A AT91_PINCTRL_PULL_UP
 							 AT91_PIOD 1 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>;
 					};
 
@@ -219,7 +219,7 @@
 				usart2 {
 					pinctrl_usart2: usart2-0 {
 						atmel,pins =
-							<AT91_PIOD 2 AT91_PERIPH_A AT91_PINCTRL_NONE
+							<AT91_PIOD 2 AT91_PERIPH_A AT91_PINCTRL_PULL_UP
 							 AT91_PIOD 3 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>;
 					};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/at91sam9g20ek_common.dtsi
@@ -38,6 +38,13 @@
 
 				};
 
+				usb1 {
+					pinctrl_usb1_vbus_gpio: usb1_vbus_gpio {
+						atmel,pins =
+							<AT91_PIOC 5 AT91_PERIPH_GPIO AT91_PINCTRL_DEGLITCH>;	/* PC5 GPIO */
+					};
+				};
+
 				mmc0_slot1 {
 					pinctrl_board_mmc0_slot1: mmc0_slot1-board {
 						atmel,pins =
@@ -83,6 +90,8 @@
 			};
 
 			usb1: gadget@fffa4000 {
+				pinctrl-0 = <&pinctrl_usb1_vbus_gpio>;
+				pinctrl-names = "default";
 				atmel,vbus-gpio = <&pioC 5 GPIO_ACTIVE_HIGH>;
 				status = "okay";
 			};
@@ -217,6 +226,12 @@
 		wm8731: wm8731@1b {
 			compatible = "wm8731";
 			reg = <0x1b>;
+
+			/* PCK0 at 12MHz */
+			clocks = <&pmc PMC_TYPE_SYSTEM 8>;
+			clock-names = "mclk";
+			assigned-clocks = <&pmc PMC_TYPE_SYSTEM 8>;
+			assigned-clock-rates = <12000000>;
 		};
 	};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/at91sam9g45.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/at91sam9g45.dtsi
@@ -556,7 +556,7 @@
 				usart0 {
 					pinctrl_usart0: usart0-0 {
 						atmel,pins =
-							<AT91_PIOB 19 AT91_PERIPH_A AT91_PINCTRL_NONE
+							<AT91_PIOB 19 AT91_PERIPH_A AT91_PINCTRL_PULL_UP
 							 AT91_PIOB 18 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>;
 					};
 
@@ -574,7 +574,7 @@
 				usart1 {
 					pinctrl_usart1: usart1-0 {
 						atmel,pins =
-							<AT91_PIOB 4 AT91_PERIPH_A AT91_PINCTRL_NONE
+							<AT91_PIOB 4 AT91_PERIPH_A AT91_PINCTRL_PULL_UP
 							 AT91_PIOB 5 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>;
 					};
 
@@ -592,7 +592,7 @@
 				usart2 {
 					pinctrl_usart2: usart2-0 {
 						atmel,pins =
-							<AT91_PIOB 6 AT91_PERIPH_A AT91_PINCTRL_NONE
+							<AT91_PIOB 6 AT91_PERIPH_A AT91_PINCTRL_PULL_UP
 							 AT91_PIOB 7 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>;
 					};
 
@@ -610,7 +610,7 @@
 				usart3 {
 					pinctrl_usart3: usart3-0 {
 						atmel,pins =
-							<AT91_PIOB 8 AT91_PERIPH_A AT91_PINCTRL_NONE
+							<AT91_PIOB 8 AT91_PERIPH_A AT91_PINCTRL_PULL_UP
 							 AT91_PIOB 9 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>;
 					};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/at91sam9rl.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/at91sam9rl.dtsi
@@ -278,23 +278,26 @@
 				atmel,adc-use-res = "highres";
 
 				trigger0 {
-					trigger-name = "timer-counter-0";
+					trigger-name = "external-rising";
 					trigger-value = <0x1>;
+					trigger-external;
 				};
+
 				trigger1 {
-					trigger-name = "timer-counter-1";
-					trigger-value = <0x3>;
+					trigger-name = "external-falling";
+					trigger-value = <0x2>;
+					trigger-external;
 				};
 
 				trigger2 {
-					trigger-name = "timer-counter-2";
-					trigger-value = <0x5>;
+					trigger-name = "external-any";
+					trigger-value = <0x3>;
+					trigger-external;
 				};
 
 				trigger3 {
-					trigger-name = "external";
-					trigger-value = <0x13>;
-					trigger-external;
+					trigger-name = "continuous";
+					trigger-value = <0x6>;
 				};
 			};
 
@@ -682,7 +685,7 @@
 				usart0 {
 					pinctrl_usart0: usart0-0 {
 						atmel,pins =
-							<AT91_PIOA 6 AT91_PERIPH_A AT91_PINCTRL_NONE>,
+							<AT91_PIOA 6 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>,
 							<AT91_PIOA 7 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>;
 					};
 
@@ -721,7 +724,7 @@
 				usart1 {
 					pinctrl_usart1: usart1-0 {
 						atmel,pins =
-							<AT91_PIOA 11 AT91_PERIPH_A AT91_PINCTRL_NONE>,
+							<AT91_PIOA 11 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>,
 							<AT91_PIOA 12 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>;
 					};
 
@@ -744,7 +747,7 @@
 				usart2 {
 					pinctrl_usart2: usart2-0 {
 						atmel,pins =
-							<AT91_PIOA 13 AT91_PERIPH_A AT91_PINCTRL_NONE>,
+							<AT91_PIOA 13 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>,
 							<AT91_PIOA 14 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>;
 					};
 
@@ -767,7 +770,7 @@
 				usart3 {
 					pinctrl_usart3: usart3-0 {
 						atmel,pins =
-							<AT91_PIOB 0 AT91_PERIPH_A AT91_PINCTRL_NONE>,
+							<AT91_PIOB 0 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>,
 							<AT91_PIOB 1 AT91_PERIPH_A AT91_PINCTRL_PULL_UP>;
 					};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/bcm-cygnus.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/bcm-cygnus.dtsi
@@ -174,8 +174,8 @@
 		mdio: mdio@18002000 {
 			compatible = "brcm,iproc-mdio";
 			reg = <0x18002000 0x8>;
-			#size-cells = <1>;
-			#address-cells = <0>;
+			#size-cells = <0>;
+			#address-cells = <1>;
 			status = "disabled";
 
 			gphy0: ethernet-phy@0 {
@@ -460,7 +460,7 @@
 			status = "disabled";
 		};
 
-		nand: nand@18046000 {
+		nand_controller: nand-controller@18046000 {
 			compatible = "brcm,nand-iproc", "brcm,brcmnand-v6.1";
 			reg = <0x18046000 0x600>, <0xf8105408 0x600>,
 			      <0x18046f00 0x20>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/bcm-hr2.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/bcm-hr2.dtsi
@@ -75,7 +75,7 @@
 		timer@20200 {
 			compatible = "arm,cortex-a9-global-timer";
 			reg = <0x20200 0x100>;
-			interrupts = <GIC_PPI 11 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_PPI 11 IRQ_TYPE_EDGE_RISING>;
 			clocks = <&periph_clk>;
 		};
 
@@ -83,7 +83,7 @@
 			compatible = "arm,cortex-a9-twd-timer";
 			reg = <0x20600 0x20>;
 			interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(1) |
-						  IRQ_TYPE_LEVEL_HIGH)>;
+						  IRQ_TYPE_EDGE_RISING)>;
 			clocks = <&periph_clk>;
 		};
 
@@ -91,7 +91,7 @@
 			compatible = "arm,cortex-a9-twd-wdt";
 			reg = <0x20620 0x20>;
 			interrupts = <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(1) |
-						  IRQ_TYPE_LEVEL_HIGH)>;
+						  IRQ_TYPE_EDGE_RISING)>;
 			clocks = <&periph_clk>;
 		};
 
@@ -179,7 +179,7 @@
 			status = "disabled";
 		};
 
-		nand: nand@26000 {
+		nand_controller: nand-controller@26000 {
 			compatible = "brcm,nand-iproc", "brcm,brcmnand-v6.1";
 			reg = <0x26000 0x600>,
 			      <0x11b408 0x600>,
@@ -217,7 +217,7 @@
 		};
 
 		qspi: spi@27200 {
-			compatible = "brcm,spi-bcm-qspi", "brcm,spi-nsp-qspi";
+			compatible = "brcm,spi-nsp-qspi", "brcm,spi-bcm-qspi";
 			reg = <0x027200 0x184>,
 			      <0x027000 0x124>,
 			      <0x11c408 0x004>,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/bcm-nsp.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/bcm-nsp.dtsi
@@ -77,7 +77,7 @@
 		interrupt-affinity = <&cpu0>, <&cpu1>;
 	};
 
-	mpcore@19000000 {
+	mpcore-bus@19000000 {
 		compatible = "simple-bus";
 		ranges = <0x00000000 0x19000000 0x00023000>;
 		#address-cells = <1>;
@@ -217,7 +217,7 @@
 			#dma-cells = <1>;
 		};
 
-		sdio: sdhci@21000 {
+		sdio: mmc@21000 {
 			compatible = "brcm,sdhci-iproc-cygnus";
 			reg = <0x21000 0x100>;
 			interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
@@ -257,17 +257,17 @@
 			status = "disabled";
 		};
 
-		mailbox: mailbox@25000 {
+		mailbox: mailbox@25c00 {
 			compatible = "brcm,iproc-fa2-mbox";
-			reg = <0x25000 0x445>;
-			interrupts = <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>;
+			reg = <0x25c00 0x400>;
+			interrupts = <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>;
 			#mbox-cells = <1>;
 			brcm,rx-status-len = <32>;
 			brcm,use-bcm-hdr;
 			dma-coherent;
 		};
 
-		nand: nand@26000 {
+		nand_controller: nand-controller@26000 {
 			compatible = "brcm,nand-iproc", "brcm,brcmnand-v6.1";
 			reg = <0x026000 0x600>,
 			      <0x11b408 0x600>,
@@ -282,7 +282,7 @@
 		};
 
 		qspi: spi@27200 {
-			compatible = "brcm,spi-bcm-qspi", "brcm,spi-nsp-qspi";
+			compatible = "brcm,spi-nsp-qspi", "brcm,spi-bcm-qspi";
 			reg = <0x027200 0x184>,
 			      <0x027000 0x124>,
 			      <0x11c408 0x004>,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/bcm2835-rpi-b.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/bcm2835-rpi-b.dts
@@ -53,18 +53,17 @@
 			  "GPIO18",
 			  "NC", /* GPIO19 */
 			  "NC", /* GPIO20 */
-			  "GPIO21",
+			  "CAM_GPIO0",
 			  "GPIO22",
 			  "GPIO23",
 			  "GPIO24",
 			  "GPIO25",
 			  "NC", /* GPIO26 */
-			  "CAM_GPIO0",
-			  /* Binary number representing build/revision */
-			  "CONFIG0",
-			  "CONFIG1",
-			  "CONFIG2",
-			  "CONFIG3",
+			  "GPIO27",
+			  "GPIO28",
+			  "GPIO29",
+			  "GPIO30",
+			  "GPIO31",
 			  "NC", /* GPIO32 */
 			  "NC", /* GPIO33 */
 			  "NC", /* GPIO34 */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts
@@ -24,7 +24,7 @@
 
 	leds {
 		act {
-			gpios = <&gpio 47 GPIO_ACTIVE_HIGH>;
+			gpios = <&gpio 47 GPIO_ACTIVE_LOW>;
 		};
 	};
 
@@ -74,16 +74,18 @@
 			  "GPIO27",
 			  "SDA0",
 			  "SCL0",
-			  "NC", /* GPIO30 */
-			  "NC", /* GPIO31 */
-			  "NC", /* GPIO32 */
-			  "NC", /* GPIO33 */
-			  "NC", /* GPIO34 */
-			  "NC", /* GPIO35 */
-			  "NC", /* GPIO36 */
-			  "NC", /* GPIO37 */
-			  "NC", /* GPIO38 */
-			  "NC", /* GPIO39 */
+			  /* Used by BT module */
+			  "CTS0",
+			  "RTS0",
+			  "TXD0",
+			  "RXD0",
+			  /* Used by Wifi */
+			  "SD1_CLK",
+			  "SD1_CMD",
+			  "SD1_DATA0",
+			  "SD1_DATA1",
+			  "SD1_DATA2",
+			  "SD1_DATA3",
 			  "CAM_GPIO1", /* GPIO40 */
 			  "WL_ON", /* GPIO41 */
 			  "NC", /* GPIO42 */
@@ -112,6 +114,7 @@
 &sdhci {
 	#address-cells = <1>;
 	#size-cells = <0>;
+	pinctrl-names = "default";
 	pinctrl-0 = <&emmc_gpio34 &gpclk2_gpio43>;
 	bus-width = <4>;
 	mmc-pwrseq = <&wifi_pwrseq>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts
@@ -43,7 +43,7 @@
 		#gpio-cells = <2>;
 		gpio-line-names = "BT_ON",
 				  "WL_ON",
-				  "STATUS_LED_R",
+				  "PWR_LED_R",
 				  "LAN_RUN",
 				  "",
 				  "CAM_GPIO0",
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/bcm2837-rpi-cm3-io3.dts
@@ -63,8 +63,8 @@
 			  "GPIO43",
 			  "GPIO44",
 			  "GPIO45",
-			  "GPIO46",
-			  "GPIO47",
+			  "SMPS_SCL",
+			  "SMPS_SDA",
 			  /* Used by eMMC */
 			  "SD_CLK_R",
 			  "SD_CMD_R",
@@ -77,7 +77,7 @@
 };
 
 &hdmi {
-	hpd-gpios = <&expgpio 1 GPIO_ACTIVE_LOW>;
+	hpd-gpios = <&expgpio 0 GPIO_ACTIVE_LOW>;
 	power-domains = <&power RPI_POWER_DOMAIN_HDMI>;
 	status = "okay";
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/bcm2837.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/bcm2837.dtsi
@@ -38,12 +38,26 @@
 		#size-cells = <0>;
 		enable-method = "brcm,bcm2836-smp"; // for ARM 32-bit
 
+		/* Source for d/i-cache-line-size and d/i-cache-sets
+		 * https://developer.arm.com/documentation/ddi0500/e/level-1-memory-system
+		 * /about-the-l1-memory-system?lang=en
+		 *
+		 * Source for d/i-cache-size
+		 * https://magpi.raspberrypi.com/articles/raspberry-pi-3-specs-benchmarks
+		 */
 		cpu0: cpu@0 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a53";
 			reg = <0>;
 			enable-method = "spin-table";
 			cpu-release-addr = <0x0 0x000000d8>;
+			d-cache-size = <0x8000>;
+			d-cache-line-size = <64>;
+			d-cache-sets = <128>; // 32KiB(size)/64(line-size)=512ways/4-way set
+			i-cache-size = <0x8000>;
+			i-cache-line-size = <64>;
+			i-cache-sets = <256>; // 32KiB(size)/64(line-size)=512ways/2-way set
+			next-level-cache = <&l2>;
 		};
 
 		cpu1: cpu@1 {
@@ -52,6 +66,13 @@
 			reg = <1>;
 			enable-method = "spin-table";
 			cpu-release-addr = <0x0 0x000000e0>;
+			d-cache-size = <0x8000>;
+			d-cache-line-size = <64>;
+			d-cache-sets = <128>; // 32KiB(size)/64(line-size)=512ways/4-way set
+			i-cache-size = <0x8000>;
+			i-cache-line-size = <64>;
+			i-cache-sets = <256>; // 32KiB(size)/64(line-size)=512ways/2-way set
+			next-level-cache = <&l2>;
 		};
 
 		cpu2: cpu@2 {
@@ -60,6 +81,13 @@
 			reg = <2>;
 			enable-method = "spin-table";
 			cpu-release-addr = <0x0 0x000000e8>;
+			d-cache-size = <0x8000>;
+			d-cache-line-size = <64>;
+			d-cache-sets = <128>; // 32KiB(size)/64(line-size)=512ways/4-way set
+			i-cache-size = <0x8000>;
+			i-cache-line-size = <64>;
+			i-cache-sets = <256>; // 32KiB(size)/64(line-size)=512ways/2-way set
+			next-level-cache = <&l2>;
 		};
 
 		cpu3: cpu@3 {
@@ -68,6 +96,27 @@
 			reg = <3>;
 			enable-method = "spin-table";
 			cpu-release-addr = <0x0 0x000000f0>;
+			d-cache-size = <0x8000>;
+			d-cache-line-size = <64>;
+			d-cache-sets = <128>; // 32KiB(size)/64(line-size)=512ways/4-way set
+			i-cache-size = <0x8000>;
+			i-cache-line-size = <64>;
+			i-cache-sets = <256>; // 32KiB(size)/64(line-size)=512ways/2-way set
+			next-level-cache = <&l2>;
+		};
+
+		/* Source for cache-line-size + cache-sets
+		 * https://developer.arm.com/documentation/ddi0500
+		 * /e/level-2-memory-system/about-the-l2-memory-system?lang=en
+		 * Source for cache-size
+		 * https://datasheets.raspberrypi.com/cm/cm1-and-cm3-datasheet.pdf
+		 */
+		l2: l2-cache0 {
+			compatible = "cache";
+			cache-size = <0x80000>;
+			cache-line-size = <64>;
+			cache-sets = <512>; // 512KiB(size)/64(line-size)=8192ways/16-way set
+			cache-level = <2>;
 		};
 	};
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/bcm283x.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/bcm283x.dtsi
@@ -40,7 +40,7 @@
 
 			trips {
 				cpu-crit {
-					temperature	= <80000>;
+					temperature	= <90000>;
 					hysteresis	= <0>;
 					type		= "critical";
 				};
@@ -183,6 +183,7 @@
 
 			interrupt-controller;
 			#interrupt-cells = <2>;
+			gpio-ranges = <&gpio 0 0 54>;
 
 			/* Defines pin muxing groups according to
 			 * BCM2835-ARM-Peripherals.pdf page 102.
@@ -488,6 +489,7 @@
 					     "dsi0_ddr2",
 					     "dsi0_ddr";
 
+			status = "disabled";
 		};
 
 		thermal: thermal@7e212000 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/bcm4708-linksys-ea6500-v2.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/bcm4708-linksys-ea6500-v2.dts
@@ -19,7 +19,8 @@
 
 	memory@0 {
 		device_type = "memory";
-		reg = <0x00000000 0x08000000>;
+		reg = <0x00000000 0x08000000>,
+		      <0x88000000 0x08000000>;
 	};
 
 	gpio-keys {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/bcm47189-luxul-xap-1440.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/bcm47189-luxul-xap-1440.dts
@@ -26,7 +26,6 @@
 		wlan {
 			label = "bcm53xx:blue:wlan";
 			gpios = <&chipcommon 10 GPIO_ACTIVE_LOW>;
-			linux,default-trigger = "default-off";
 		};
 
 		system {
@@ -46,3 +45,16 @@
 		};
 	};
 };
+
+&gmac0 {
+	phy-mode = "rgmii";
+	phy-handle = <&bcm54210e>;
+
+	mdio {
+		/delete-node/ switch@1e;
+
+		bcm54210e: ethernet-phy@0 {
+			reg = <0>;
+		};
+	};
+};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/bcm47189-luxul-xap-810.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/bcm47189-luxul-xap-810.dts
@@ -26,7 +26,6 @@
 		5ghz {
 			label = "bcm53xx:blue:5ghz";
 			gpios = <&chipcommon 11 GPIO_ACTIVE_HIGH>;
-			linux,default-trigger = "default-off";
 		};
 
 		system {
@@ -42,7 +41,6 @@
 		2ghz {
 			label = "bcm53xx:blue:2ghz";
 			gpios = <&pcie0_chipcommon 3 GPIO_ACTIVE_HIGH>;
-			linux,default-trigger = "default-off";
 		};
 	};
 
@@ -83,3 +81,16 @@
 		};
 	};
 };
+
+&gmac0 {
+	phy-mode = "rgmii";
+	phy-handle = <&bcm54210e>;
+
+	mdio {
+		/delete-node/ switch@1e;
+
+		bcm54210e: ethernet-phy@0 {
+			reg = <0>;
+		};
+	};
+};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/bcm5301x.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/bcm5301x.dtsi
@@ -242,6 +242,8 @@
 
 			gpio-controller;
 			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
 		};
 
 		pcie0: pcie@12000 {
@@ -353,8 +355,8 @@
 	mdio: mdio@18003000 {
 		compatible = "brcm,iproc-mdio";
 		reg = <0x18003000 0x8>;
-		#size-cells = <1>;
-		#address-cells = <0>;
+		#size-cells = <0>;
+		#address-cells = <1>;
 	};
 
 	mdio-bus-mux@18003000 {
@@ -387,7 +389,7 @@
 	i2c0: i2c@18009000 {
 		compatible = "brcm,iproc-i2c";
 		reg = <0x18009000 0x50>;
-		interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 		clock-frequency = <100000>;
@@ -488,33 +490,32 @@
 	};
 
 	spi@18029200 {
-		compatible = "brcm,spi-bcm-qspi", "brcm,spi-nsp-qspi";
+		compatible = "brcm,spi-nsp-qspi", "brcm,spi-bcm-qspi";
 		reg = <0x18029200 0x184>,
 		      <0x18029000 0x124>,
 		      <0x1811b408 0x004>,
 		      <0x180293a0 0x01c>;
 		reg-names = "mspi", "bspi", "intr_regs", "intr_status_reg";
-		interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
+		interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
 			     <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>,
 			     <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>,
 			     <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>,
-			     <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>,
-			     <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>,
-			     <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
-		interrupt-names = "spi_lr_fullness_reached",
+			     <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "mspi_done",
+				  "mspi_halted",
+				  "spi_lr_fullness_reached",
 				  "spi_lr_session_aborted",
 				  "spi_lr_impatient",
 				  "spi_lr_session_done",
-				  "spi_lr_overhead",
-				  "mspi_done",
-				  "mspi_halted";
+				  "spi_lr_overread";
 		clocks = <&iprocmed>;
-		clock-names = "iprocmed";
 		num-cs = <2>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		spi_nor: spi-nor@0 {
+		spi_nor: flash@0 {
 			compatible = "jedec,spi-nor";
 			reg = <0>;
 			spi-max-frequency = <20000000>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/bcm53573.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/bcm53573.dtsi
@@ -127,6 +127,9 @@
 
 		pcie0: pcie@2000 {
 			reg = <0x00002000 0x1000>;
+
+			#address-cells = <3>;
+			#size-cells = <2>;
 		};
 
 		usb2: usb2@4000 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/bcm63138.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/bcm63138.dtsi
@@ -203,7 +203,7 @@
 			status = "disabled";
 		};
 
-		nand: nand@2000 {
+		nand_controller: nand-controller@2000 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			compatible = "brcm,nand-bcm63138", "brcm,brcmnand-v7.0", "brcm,brcmnand";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/bcm7445-bcm97445svmb.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/bcm7445-bcm97445svmb.dts
@@ -14,10 +14,10 @@
 	};
 };
 
-&nand {
+&nand_controller {
 	status = "okay";
 
-	nandcs@1 {
+	nand@1 {
 		compatible = "brcm,nandcs";
 		reg = <1>;
 		nand-ecc-step-size = <512>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/bcm7445.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/bcm7445.dtsi
@@ -148,7 +148,7 @@
 			reg-names = "aon-ctrl", "aon-sram";
 		};
 
-		nand: nand@3e2800 {
+		nand_controller: nand-controller@3e2800 {
 			status = "disabled";
 			#address-cells = <1>;
 			#size-cells = <0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/bcm911360_entphn.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/bcm911360_entphn.dts
@@ -82,8 +82,8 @@
 	status = "okay";
 };
 
-&nand {
-	nandcs@1 {
+&nand_controller {
+	nand@1 {
 		compatible = "brcm,nandcs";
 		reg = <0>;
 		nand-on-flash-bbt;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/bcm947189acdbmr.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/bcm947189acdbmr.dts
@@ -60,9 +60,9 @@
 	spi {
 		compatible = "spi-gpio";
 		num-chipselects = <1>;
-		gpio-sck = <&chipcommon 21 0>;
-		gpio-miso = <&chipcommon 22 0>;
-		gpio-mosi = <&chipcommon 23 0>;
+		sck-gpios = <&chipcommon 21 0>;
+		miso-gpios = <&chipcommon 22 0>;
+		mosi-gpios = <&chipcommon 23 0>;
 		cs-gpios = <&chipcommon 24 0>;
 		#address-cells = <1>;
 		#size-cells = <0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/bcm958300k.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/bcm958300k.dts
@@ -60,8 +60,8 @@
 	status = "okay";
 };
 
-&nand {
-	nandcs@1 {
+&nand_controller {
+	nand@1 {
 		compatible = "brcm,nandcs";
 		reg = <0>;
 		nand-on-flash-bbt;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/bcm958305k.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/bcm958305k.dts
@@ -68,8 +68,8 @@
 	status = "okay";
 };
 
-&nand {
-	nandcs@1 {
+&nand_controller {
+	nand@1 {
 		compatible = "brcm,nandcs";
 		reg = <0>;
 		nand-on-flash-bbt;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/bcm958522er.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/bcm958522er.dts
@@ -70,8 +70,8 @@
 	status = "okay";
 };
 
-&nand {
-	nandcs@0 {
+&nand_controller {
+	nand@0 {
 		compatible = "brcm,nandcs";
 		reg = <0>;
 		nand-on-flash-bbt;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/bcm958525er.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/bcm958525er.dts
@@ -70,8 +70,8 @@
 	status = "okay";
 };
 
-&nand {
-	nandcs@0 {
+&nand_controller {
+	nand@0 {
 		compatible = "brcm,nandcs";
 		reg = <0>;
 		nand-on-flash-bbt;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/bcm958525xmc.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/bcm958525xmc.dts
@@ -86,8 +86,8 @@
 	};
 };
 
-&nand {
-	nandcs@0 {
+&nand_controller {
+	nand@0 {
 		compatible = "brcm,nandcs";
 		reg = <0>;
 		nand-on-flash-bbt;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/bcm958622hr.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/bcm958622hr.dts
@@ -74,8 +74,8 @@
 	status = "okay";
 };
 
-&nand {
-	nandcs@0 {
+&nand_controller {
+	nand@0 {
 		compatible = "brcm,nandcs";
 		reg = <0>;
 		nand-on-flash-bbt;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/bcm958623hr.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/bcm958623hr.dts
@@ -74,8 +74,8 @@
 	status = "okay";
 };
 
-&nand {
-	nandcs@0 {
+&nand_controller {
+	nand@0 {
 		compatible = "brcm,nandcs";
 		reg = <0>;
 		nand-on-flash-bbt;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/bcm958625hr.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/bcm958625hr.dts
@@ -90,8 +90,8 @@
 	status = "okay";
 };
 
-&nand {
-	nandcs@0 {
+&nand_controller {
+	nand@0 {
 		compatible = "brcm,nandcs";
 		reg = <0>;
 		nand-on-flash-bbt;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/bcm958625k.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/bcm958625k.dts
@@ -64,8 +64,8 @@
 	status = "okay";
 };
 
-&nand {
-	nandcs@0 {
+&nand_controller {
+	nand@0 {
 		compatible = "brcm,nandcs";
 		reg = <0>;
 		nand-on-flash-bbt;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/bcm963138dvt.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/bcm963138dvt.dts
@@ -31,10 +31,10 @@
 	status = "okay";
 };
 
-&nand {
+&nand_controller {
 	status = "okay";
 
-	nandcs@0 {
+	nand@0 {
 		compatible = "brcm,nandcs";
 		reg = <0>;
 		nand-ecc-strength = <4>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/bcm988312hr.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/bcm988312hr.dts
@@ -74,8 +74,8 @@
 	status = "okay";
 };
 
-&nand {
-	nandcs@0 {
+&nand_controller {
+	nand@0 {
 		compatible = "brcm,nandcs";
 		reg = <0>;
 		nand-on-flash-bbt;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/dm8148-evm.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/dm8148-evm.dts
@@ -24,12 +24,12 @@
 
 &cpsw_emac0 {
 	phy-handle = <&ethphy0>;
-	phy-mode = "rgmii";
+	phy-mode = "rgmii-id";
 };
 
 &cpsw_emac1 {
 	phy-handle = <&ethphy1>;
-	phy-mode = "rgmii";
+	phy-mode = "rgmii-id";
 };
 
 &davinci_mdio {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/dm8148-t410.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/dm8148-t410.dts
@@ -33,12 +33,12 @@
 
 &cpsw_emac0 {
 	phy-handle = <&ethphy0>;
-	phy-mode = "rgmii";
+	phy-mode = "rgmii-id";
 };
 
 &cpsw_emac1 {
 	phy-handle = <&ethphy1>;
-	phy-mode = "rgmii";
+	phy-mode = "rgmii-id";
 };
 
 &davinci_mdio {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/dove.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/dove.dtsi
@@ -129,7 +129,7 @@
 			pcie1: pcie@2 {
 				device_type = "pci";
 				status = "disabled";
-				assigned-addresses = <0x82002800 0 0x80000 0 0x2000>;
+				assigned-addresses = <0x82001000 0 0x80000 0 0x2000>;
 				reg = <0x1000 0 0 0 0>;
 				clocks = <&gate_clk 5>;
 				marvell,pcie-port = <1>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/dra62x-j5eco-evm.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/dra62x-j5eco-evm.dts
@@ -24,12 +24,12 @@
 
 &cpsw_emac0 {
 	phy-handle = <&ethphy0>;
-	phy-mode = "rgmii";
+	phy-mode = "rgmii-id";
 };
 
 &cpsw_emac1 {
 	phy-handle = <&ethphy1>;
-	phy-mode = "rgmii";
+	phy-mode = "rgmii-id";
 };
 
 &davinci_mdio {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/dra7-l4.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/dra7-l4.dtsi
@@ -1176,7 +1176,7 @@
 			};
 		};
 
-		target-module@34000 {			/* 0x48034000, ap 7 46.0 */
+		timer3_target: target-module@34000 {	/* 0x48034000, ap 7 46.0 */
 			compatible = "ti,sysc-omap4-timer", "ti,sysc";
 			ti,hwmods = "timer3";
 			reg = <0x34000 0x4>,
@@ -1204,7 +1204,7 @@
 			};
 		};
 
-		target-module@36000 {			/* 0x48036000, ap 9 4e.0 */
+		timer4_target: target-module@36000 {	/* 0x48036000, ap 9 4e.0 */
 			compatible = "ti,sysc-omap4-timer", "ti,sysc";
 			ti,hwmods = "timer4";
 			reg = <0x36000 0x4>,
@@ -1326,7 +1326,7 @@
 			};
 		};
 
-		target-module@55000 {			/* 0x48055000, ap 13 0e.0 */
+		gpio2_target: target-module@55000 {		/* 0x48055000, ap 13 0e.0 */
 			compatible = "ti,sysc-omap2", "ti,sysc";
 			reg = <0x55000 0x4>,
 			      <0x55010 0x4>,
@@ -1359,7 +1359,7 @@
 			};
 		};
 
-		target-module@57000 {			/* 0x48057000, ap 15 06.0 */
+		gpio3_target: target-module@57000 {		/* 0x48057000, ap 15 06.0 */
 			compatible = "ti,sysc-omap2", "ti,sysc";
 			reg = <0x57000 0x4>,
 			      <0x57010 0x4>,
@@ -3059,7 +3059,7 @@
 
 				davinci_mdio: mdio@1000 {
 					compatible = "ti,cpsw-mdio","ti,davinci_mdio";
-					clocks = <&gmac_clkctrl DRA7_GMAC_GMAC_CLKCTRL 0>;
+					clocks = <&gmac_main_clk>;
 					clock-names = "fck";
 					#address-cells = <1>;
 					#size-cells = <0>;
@@ -3413,6 +3413,7 @@
 				clocks = <&l4per3_clkctrl DRA7_L4PER3_TIMER13_CLKCTRL 24>;
 				clock-names = "fck";
 				interrupts = <GIC_SPI 339 IRQ_TYPE_LEVEL_HIGH>;
+				ti,timer-pwm;
 			};
 		};
 
@@ -3441,6 +3442,7 @@
 				clocks = <&l4per3_clkctrl DRA7_L4PER3_TIMER14_CLKCTRL 24>;
 				clock-names = "fck";
 				interrupts = <GIC_SPI 340 IRQ_TYPE_LEVEL_HIGH>;
+				ti,timer-pwm;
 			};
 		};
 
@@ -3469,6 +3471,7 @@
 				clocks = <&l4per3_clkctrl DRA7_L4PER3_TIMER15_CLKCTRL 24>;
 				clock-names = "fck";
 				interrupts = <GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH>;
+				ti,timer-pwm;
 			};
 		};
 
@@ -3497,6 +3500,7 @@
 				clocks = <&l4per3_clkctrl DRA7_L4PER3_TIMER16_CLKCTRL 24>;
 				clock-names = "fck";
 				interrupts = <GIC_SPI 342 IRQ_TYPE_LEVEL_HIGH>;
+				ti,timer-pwm;
 			};
 		};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/dra7.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/dra7.dtsi
@@ -46,6 +46,7 @@
 
 	timer {
 		compatible = "arm,armv7-timer";
+		status = "disabled";	/* See ARM architected timer wrap erratum i940 */
 		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
 			     <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
 			     <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
@@ -148,6 +149,7 @@
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges = <0x0 0x0 0x0 0xc0000000>;
+		dma-ranges = <0x80000000 0x0 0x80000000 0x80000000>;
 		ti,hwmods = "l3_main_1", "l3_main_2";
 		reg = <0x0 0x44000000 0x0 0x1000000>,
 		      <0x0 0x45000000 0x0 0x1000>;
@@ -171,6 +173,7 @@
 			#address-cells = <1>;
 			ranges = <0x51000000 0x51000000 0x3000
 				  0x0	     0x20000000 0x10000000>;
+			dma-ranges;
 			/**
 			 * To enable PCI endpoint mode, disable the pcie1_rc
 			 * node and enable pcie1_ep mode.
@@ -228,6 +231,7 @@
 			#address-cells = <1>;
 			ranges = <0x51800000 0x51800000 0x3000
 				  0x0	     0x30000000 0x10000000>;
+			dma-ranges;
 			status = "disabled";
 			pcie2_rc: pcie@51800000 {
 				reg = <0x51800000 0x2000>, <0x51802000 0x14c>, <0x1000 0x2000>;
@@ -763,3 +767,22 @@
 
 #include "dra7-l4.dtsi"
 #include "dra7xx-clocks.dtsi"
+
+/* Local timers, see ARM architected timer wrap erratum i940 */
+&timer3_target {
+	ti,no-reset-on-init;
+	ti,no-idle;
+	timer@0 {
+		assigned-clocks = <&l4per_clkctrl DRA7_L4PER_TIMER3_CLKCTRL 24>;
+		assigned-clock-parents = <&timer_sys_clk_div>;
+	};
+};
+
+&timer4_target {
+	ti,no-reset-on-init;
+	ti,no-idle;
+	timer@0 {
+		assigned-clocks = <&l4per_clkctrl DRA7_L4PER_TIMER4_CLKCTRL 24>;
+		assigned-clock-parents = <&timer_sys_clk_div>;
+	};
+};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/dra76x.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/dra76x.dtsi
@@ -32,8 +32,8 @@
 				interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>,
 					     <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
 				interrupt-names = "int0", "int1";
-				clocks = <&mcan_clk>, <&l3_iclk_div>;
-				clock-names = "cclk", "hclk";
+				clocks = <&l3_iclk_div>, <&mcan_clk>;
+				clock-names = "hclk", "cclk";
 				bosch,mram-cfg = <0x0 0 0 32 0 0 1 1>;
 			};
 		};
@@ -86,3 +86,8 @@
 &usb4_tm {
 	status = "disabled";
 };
+
+&mmc3 {
+	/* dra76x is not affected by i887 */
+	max-frequency = <96000000>;
+};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/dra7xx-clocks.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/dra7xx-clocks.dtsi
@@ -796,16 +796,6 @@
 		clock-div = <1>;
 	};
 
-	ipu1_gfclk_mux: ipu1_gfclk_mux@520 {
-		#clock-cells = <0>;
-		compatible = "ti,mux-clock";
-		clocks = <&dpll_abe_m2x2_ck>, <&dpll_core_h22x2_ck>;
-		ti,bit-shift = <24>;
-		reg = <0x0520>;
-		assigned-clocks = <&ipu1_gfclk_mux>;
-		assigned-clock-parents = <&dpll_core_h22x2_ck>;
-	};
-
 	dummy_ck: dummy_ck {
 		#clock-cells = <0>;
 		compatible = "fixed-clock";
@@ -1564,6 +1554,8 @@
 			compatible = "ti,clkctrl";
 			reg = <0x20 0x4>;
 			#clock-cells = <2>;
+			assigned-clocks = <&ipu1_clkctrl DRA7_IPU1_MMU_IPU1_CLKCTRL 24>;
+			assigned-clock-parents = <&dpll_core_h22x2_ck>;
 		};
 
 		ipu_clkctrl: ipu-clkctrl@50 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/exynos3250-artik5.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/exynos3250-artik5.dtsi
@@ -75,7 +75,7 @@
 	s2mps14_pmic@66 {
 		compatible = "samsung,s2mps14-pmic";
 		interrupt-parent = <&gpx3>;
-		interrupts = <5 IRQ_TYPE_NONE>;
+		interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&s2mps14_irq>;
 		reg = <0x66>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/exynos3250-monk.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/exynos3250-monk.dts
@@ -195,7 +195,7 @@
 	s2mps14_pmic@66 {
 		compatible = "samsung,s2mps14-pmic";
 		interrupt-parent = <&gpx0>;
-		interrupts = <7 IRQ_TYPE_NONE>;
+		interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
 		reg = <0x66>;
 		wakeup-source;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/exynos3250-rinato.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/exynos3250-rinato.dts
@@ -239,7 +239,7 @@
 	i80-if-timings {
 		cs-setup = <0>;
 		wr-setup = <0>;
-		wr-act = <1>;
+		wr-active = <1>;
 		wr-hold = <0>;
 	};
 };
@@ -260,7 +260,7 @@
 	s2mps14_pmic@66 {
 		compatible = "samsung,s2mps14-pmic";
 		interrupt-parent = <&gpx0>;
-		interrupts = <7 IRQ_TYPE_NONE>;
+		interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
 		reg = <0x66>;
 		wakeup-source;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/exynos4-cpu-thermal.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/exynos4-cpu-thermal.dtsi
@@ -10,7 +10,7 @@
 / {
 thermal-zones {
 	cpu_thermal: cpu-thermal {
-		thermal-sensors = <&tmu 0>;
+		thermal-sensors = <&tmu>;
 		polling-delay-passive = <0>;
 		polling-delay = <0>;
 		trips {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/exynos4.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/exynos4.dtsi
@@ -605,7 +605,7 @@
 			status = "disabled";
 
 			hdmi_i2c_phy: hdmiphy@38 {
-				compatible = "exynos4210-hdmiphy";
+				compatible = "samsung,exynos4210-hdmiphy";
 				reg = <0x38>;
 			};
 		};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/exynos4210-smdkv310.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/exynos4210-smdkv310.dts
@@ -64,7 +64,7 @@
 &keypad {
 	samsung,keypad-num-rows = <2>;
 	samsung,keypad-num-columns = <8>;
-	linux,keypad-no-autorepeat;
+	linux,input-no-autorepeat;
 	wakeup-source;
 	pinctrl-names = "default";
 	pinctrl-0 = <&keypad_rows &keypad_cols>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/exynos4210-universal_c210.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/exynos4210-universal_c210.dts
@@ -115,7 +115,7 @@
 		gpio-sck = <&gpy3 1 GPIO_ACTIVE_HIGH>;
 		gpio-mosi = <&gpy3 3 GPIO_ACTIVE_HIGH>;
 		num-chipselects = <1>;
-		cs-gpios = <&gpy4 3 GPIO_ACTIVE_HIGH>;
+		cs-gpios = <&gpy4 3 GPIO_ACTIVE_LOW>;
 
 		lcd@0 {
 			compatible = "samsung,ld9040";
@@ -124,8 +124,6 @@
 			vci-supply = <&ldo17_reg>;
 			reset-gpios = <&gpy4 5 GPIO_ACTIVE_HIGH>;
 			spi-max-frequency = <1200000>;
-			spi-cpol;
-			spi-cpha;
 			power-on-delay = <10>;
 			reset-delay = <10>;
 			panel-width-mm = <90>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/exynos4412-galaxy-s3.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/exynos4412-galaxy-s3.dtsi
@@ -68,7 +68,7 @@
 
 	i2c_cm36651: i2c-gpio-2 {
 		compatible = "i2c-gpio";
-		gpios = <&gpf0 0 GPIO_ACTIVE_LOW>, <&gpf0 1 GPIO_ACTIVE_LOW>;
+		gpios = <&gpf0 0 GPIO_ACTIVE_HIGH>, <&gpf0 1 GPIO_ACTIVE_HIGH>;
 		i2c-gpio,delay-us = <2>;
 		#address-cells = <1>;
 		#size-cells = <0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/exynos4412-itop-elite.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/exynos4412-itop-elite.dts
@@ -179,7 +179,7 @@
 		compatible = "wlf,wm8960";
 		reg = <0x1a>;
 		clocks = <&pmu_system_controller 0>;
-		clock-names = "MCLK1";
+		clock-names = "mclk";
 		wlf,shared-lrclk;
 		#sound-dai-cells = <0>;
 	};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/exynos4412-midas.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/exynos4412-midas.dtsi
@@ -139,7 +139,7 @@
 		max77693@66 {
 			compatible = "maxim,max77693";
 			interrupt-parent = <&gpx1>;
-			interrupts = <5 IRQ_TYPE_EDGE_FALLING>;
+			interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&max77693_irq>;
 			reg = <0x66>;
@@ -187,7 +187,7 @@
 		max77693-fuel-gauge@36 {
 			compatible = "maxim,max17047";
 			interrupt-parent = <&gpx2>;
-			interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+			interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&max77693_fuel_irq>;
 			reg = <0x36>;
@@ -534,7 +534,7 @@
 		clocks = <&camera 1>;
 		clock-names = "extclk";
 		samsung,camclk-out = <1>;
-		gpios = <&gpm1 6 GPIO_ACTIVE_HIGH>;
+		gpios = <&gpm1 6 GPIO_ACTIVE_LOW>;
 
 		port {
 			is_s5k6a3_ep: endpoint {
@@ -588,7 +588,7 @@
 	max77686: max77686_pmic@9 {
 		compatible = "maxim,max77686";
 		interrupt-parent = <&gpx0>;
-		interrupts = <7 IRQ_TYPE_NONE>;
+		interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
 		pinctrl-0 = <&max77686_irq>;
 		pinctrl-names = "default";
 		reg = <0x09>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
@@ -274,7 +274,7 @@
 	max77686: pmic@9 {
 		compatible = "maxim,max77686";
 		interrupt-parent = <&gpx3>;
-		interrupts = <2 IRQ_TYPE_NONE>;
+		interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&max77686_irq>;
 		reg = <0x09>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/exynos4412-origen.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/exynos4412-origen.dts
@@ -86,7 +86,7 @@
 };
 
 &ehci {
-	samsung,vbus-gpio = <&gpx3 5 1>;
+	samsung,vbus-gpio = <&gpx3 5 GPIO_ACTIVE_HIGH>;
 	status = "okay";
 	phys = <&exynos_usbphy 2>, <&exynos_usbphy 3>;
 	phy-names = "hsic0", "hsic1";
@@ -431,7 +431,7 @@
 &keypad {
 	samsung,keypad-num-rows = <3>;
 	samsung,keypad-num-columns = <2>;
-	linux,keypad-no-autorepeat;
+	linux,input-no-autorepeat;
 	wakeup-source;
 	pinctrl-0 = <&keypad_rows &keypad_cols>;
 	pinctrl-names = "default";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/exynos4412-smdk4412.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/exynos4412-smdk4412.dts
@@ -43,7 +43,7 @@
 &keypad {
 	samsung,keypad-num-rows = <3>;
 	samsung,keypad-num-columns = <8>;
-	linux,keypad-no-autorepeat;
+	linux,input-no-autorepeat;
 	wakeup-source;
 	pinctrl-0 = <&keypad_rows &keypad_cols>;
 	pinctrl-names = "default";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/exynos5250-pinctrl.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/exynos5250-pinctrl.dtsi
@@ -260,7 +260,7 @@
 	};
 
 	uart3_data: uart3-data {
-		samsung,pins = "gpa1-4", "gpa1-4";
+		samsung,pins = "gpa1-4", "gpa1-5";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
 		samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;
 		samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/exynos5250-smdk5250.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/exynos5250-smdk5250.dts
@@ -117,6 +117,9 @@
 	status = "okay";
 	ddc = <&i2c_2>;
 	hpd-gpios = <&gpx3 7 GPIO_ACTIVE_HIGH>;
+	vdd-supply = <&ldo8_reg>;
+	vdd_osc-supply = <&ldo10_reg>;
+	vdd_pll-supply = <&ldo8_reg>;
 };
 
 &i2c_0 {
@@ -125,7 +128,7 @@
 	samsung,i2c-max-bus-freq = <20000>;
 
 	eeprom@50 {
-		compatible = "samsung,s524ad0xd1";
+		compatible = "samsung,s524ad0xd1", "atmel,24c128";
 		reg = <0x50>;
 	};
 
@@ -133,7 +136,7 @@
 		compatible = "maxim,max77686";
 		reg = <0x09>;
 		interrupt-parent = <&gpx3>;
-		interrupts = <2 IRQ_TYPE_NONE>;
+		interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&max77686_irq>;
 		wakeup-source;
@@ -284,7 +287,7 @@
 	samsung,i2c-max-bus-freq = <20000>;
 
 	eeprom@51 {
-		compatible = "samsung,s524ad0xd1";
+		compatible = "samsung,s524ad0xd1", "atmel,24c128";
 		reg = <0x51>;
 	};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/exynos5250-snow-common.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/exynos5250-snow-common.dtsi
@@ -292,7 +292,7 @@
 	max77686: max77686@9 {
 		compatible = "maxim,max77686";
 		interrupt-parent = <&gpx3>;
-		interrupts = <2 IRQ_TYPE_NONE>;
+		interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&max77686_irq>;
 		wakeup-source;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/exynos5250-spring.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/exynos5250-spring.dts
@@ -108,7 +108,7 @@
 		compatible = "samsung,s5m8767-pmic";
 		reg = <0x66>;
 		interrupt-parent = <&gpx3>;
-		interrupts = <2 IRQ_TYPE_NONE>;
+		interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&s5m8767_irq &s5m8767_dvs &s5m8767_ds>;
 		wakeup-source;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/exynos5410-odroidxu.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/exynos5410-odroidxu.dts
@@ -116,7 +116,6 @@
 };
 
 &cpu0_thermal {
-	thermal-sensors = <&tmu_cpu0 0>;
 	polling-delay-passive = <0>;
 	polling-delay = <0>;
 
@@ -327,6 +326,8 @@
 				regulator-name = "vddq_lcd";
 				regulator-min-microvolt = <1800000>;
 				regulator-max-microvolt = <1800000>;
+				/* Supplies also GPK and GPJ */
+				regulator-always-on;
 			};
 
 			ldo8_reg: LDO8 {
@@ -637,11 +638,11 @@
 };
 
 &usbdrd_dwc3_0 {
-	dr_mode = "host";
+	dr_mode = "peripheral";
 };
 
 &usbdrd_dwc3_1 {
-	dr_mode = "peripheral";
+	dr_mode = "host";
 };
 
 &usbdrd3_0 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/exynos5410-pinctrl.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/exynos5410-pinctrl.dtsi
@@ -560,6 +560,34 @@
 		interrupt-controller;
 		#interrupt-cells = <2>;
 	};
+
+	usb3_1_oc: usb3-1-oc {
+		samsung,pins = "gpk2-4", "gpk2-5";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+	};
+
+	usb3_1_vbusctrl: usb3-1-vbusctrl {
+		samsung,pins = "gpk2-6", "gpk2-7";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
+		samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+	};
+
+	usb3_0_oc: usb3-0-oc {
+		samsung,pins = "gpk3-0", "gpk3-1";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
+		samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+	};
+
+	usb3_0_vbusctrl: usb3-0-vbusctrl {
+		samsung,pins = "gpk3-2", "gpk3-3";
+		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
+		samsung,pin-pud = <EXYNOS_PIN_PULL_DOWN>;
+		samsung,pin-drv = <EXYNOS5420_PIN_DRV_LV1>;
+	};
 };
 
 &pinctrl_2 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/exynos5410.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/exynos5410.dtsi
@@ -398,6 +398,8 @@
 &usbdrd3_0 {
 	clocks = <&clock CLK_USBD300>;
 	clock-names = "usbdrd30";
+	pinctrl-names = "default";
+	pinctrl-0 = <&usb3_0_oc>, <&usb3_0_vbusctrl>;
 };
 
 &usbdrd_phy0 {
@@ -409,6 +411,8 @@
 &usbdrd3_1 {
 	clocks = <&clock CLK_USBD301>;
 	clock-names = "usbdrd30";
+	pinctrl-names = "default";
+	pinctrl-0 = <&usb3_1_oc>, <&usb3_1_vbusctrl>;
 };
 
 &usbdrd_dwc3_1 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/exynos5420-arndale-octa.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/exynos5420-arndale-octa.dts
@@ -349,7 +349,7 @@
 		reg = <0x66>;
 
 		interrupt-parent = <&gpx3>;
-		interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
+		interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&s2mps11_irq>;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/exynos5420-smdk5420.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/exynos5420-smdk5420.dts
@@ -132,6 +132,9 @@
 	hpd-gpios = <&gpx3 7 GPIO_ACTIVE_HIGH>;
 	pinctrl-names = "default";
 	pinctrl-0 = <&hdmi_hpd_irq>;
+	vdd-supply = <&ldo6_reg>;
+	vdd_osc-supply = <&ldo7_reg>;
+	vdd_pll-supply = <&ldo6_reg>;
 };
 
 &hsi2c_4 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/exynos5420.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/exynos5420.dtsi
@@ -539,7 +539,7 @@
 		};
 
 		mipi_phy: mipi-video-phy {
-			compatible = "samsung,s5pv210-mipi-video-phy";
+			compatible = "samsung,exynos5420-mipi-video-phy";
 			syscon = <&pmu_system_controller>;
 			#phy-cells = <1>;
 		};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/exynos5422-odroid-core.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/exynos5422-odroid-core.dtsi
@@ -141,7 +141,7 @@
 		samsung,s2mps11-acokb-ground;
 
 		interrupt-parent = <&gpx0>;
-		interrupts = <4 IRQ_TYPE_EDGE_FALLING>;
+		interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&s2mps11_irq>;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/exynos5422-odroidhc1.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/exynos5422-odroidhc1.dts
@@ -22,7 +22,7 @@
 			label = "blue:heartbeat";
 			pwms = <&pwm 2 2000000 0>;
 			pwm-names = "pwm2";
-			max_brightness = <255>;
+			max-brightness = <255>;
 			linux,default-trigger = "heartbeat";
 		};
 	};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/exynos5422-odroidxu4.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/exynos5422-odroidxu4.dts
@@ -24,7 +24,7 @@
 			label = "blue:heartbeat";
 			pwms = <&pwm 2 2000000 0>;
 			pwm-names = "pwm2";
-			max_brightness = <255>;
+			max-brightness = <255>;
 			linux,default-trigger = "heartbeat";
 		};
 	};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi
@@ -22,7 +22,7 @@
 			 * Green LED is much brighter than the others
 			 * so limit its max brightness
 			 */
-			max_brightness = <127>;
+			max-brightness = <127>;
 			linux,default-trigger = "mmc0";
 		};
 
@@ -30,7 +30,7 @@
 			label = "blue:heartbeat";
 			pwms = <&pwm 2 2000000 0>;
 			pwm-names = "pwm2";
-			max_brightness = <255>;
+			max-brightness = <255>;
 			linux,default-trigger = "heartbeat";
 		};
 	};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/gemini-dlink-dns-313.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/gemini-dlink-dns-313.dts
@@ -140,7 +140,7 @@
 		};
 	};
 
-	mdio0: ethernet-phy {
+	mdio0: mdio {
 		compatible = "virtual,mdio-gpio";
 		/* Uses MDC and MDIO */
 		gpios = <&gpio0 22 GPIO_ACTIVE_HIGH>, /* MDC */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/gemini-nas4220b.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/gemini-nas4220b.dts
@@ -62,7 +62,7 @@
 		};
 	};
 
-	mdio0: ethernet-phy {
+	mdio0: mdio {
 		compatible = "virtual,mdio-gpio";
 		gpios = <&gpio0 22 GPIO_ACTIVE_HIGH>, /* MDC */
 			<&gpio0 21 GPIO_ACTIVE_HIGH>; /* MDIO */
@@ -84,7 +84,7 @@
 			partitions {
 				compatible = "redboot-fis";
 				/* Eraseblock at 0xfe0000 */
-				fis-index-block = <0x1fc>;
+				fis-index-block = <0x7f>;
 			};
 		};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/gemini-rut1xx.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/gemini-rut1xx.dts
@@ -56,7 +56,7 @@
 		};
 	};
 
-	mdio0: ethernet-phy {
+	mdio0: mdio {
 		compatible = "virtual,mdio-gpio";
 		gpios = <&gpio0 22 GPIO_ACTIVE_HIGH>, /* MDC */
 			<&gpio0 21 GPIO_ACTIVE_HIGH>; /* MDIO */
@@ -114,18 +114,6 @@
 		};
 
 		ethernet@60000000 {
-			status = "okay";
-
-			ethernet-port@0 {
-				phy-mode = "rgmii";
-				phy-handle = <&phy0>;
-			};
-			ethernet-port@1 {
-				/* Not used in this platform */
-			};
-		};
-
-		ethernet@60000000 {
 			status = "okay";
 
 			ethernet-port@0 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/gemini-wbd111.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/gemini-wbd111.dts
@@ -68,7 +68,7 @@
 		};
 	};
 
-	mdio0: ethernet-phy {
+	mdio0: mdio {
 		compatible = "virtual,mdio-gpio";
 		gpios = <&gpio0 22 GPIO_ACTIVE_HIGH>, /* MDC */
 			<&gpio0 21 GPIO_ACTIVE_HIGH>; /* MDIO */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/gemini-wbd222.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/gemini-wbd222.dts
@@ -67,7 +67,7 @@
 		};
 	};
 
-	mdio0: ethernet-phy {
+	mdio0: mdio {
 		compatible = "virtual,mdio-gpio";
 		gpios = <&gpio0 22 GPIO_ACTIVE_HIGH>, /* MDC */
 			<&gpio0 21 GPIO_ACTIVE_HIGH>; /* MDIO */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/gemini.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/gemini.dtsi
@@ -286,6 +286,7 @@
 			clock-names = "PCLK", "PCICLK";
 			pinctrl-names = "default";
 			pinctrl-0 = <&pci_default_pins>;
+			device_type = "pci";
 			#address-cells = <3>;
 			#size-cells = <2>;
 			#interrupt-cells = <1>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx1-ads.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx1-ads.dts
@@ -65,7 +65,7 @@
 	pinctrl-0 = <&pinctrl_weim>;
 	status = "okay";
 
-	nor: nor@0,0 {
+	nor: flash@0,0 {
 		compatible = "cfi-flash";
 		reg = <0 0x00000000 0x02000000>;
 		bank-width = <4>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx1-apf9328.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx1-apf9328.dts
@@ -45,7 +45,7 @@
 	pinctrl-0 = <&pinctrl_weim>;
 	status = "okay";
 
-	nor: nor@0,0 {
+	nor: flash@0,0 {
 		compatible = "cfi-flash";
 		reg = <0 0x00000000 0x02000000>;
 		bank-width = <2>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx1.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx1.dtsi
@@ -268,9 +268,12 @@
 			status = "disabled";
 		};
 
-		esram: esram@300000 {
+		esram: sram@300000 {
 			compatible = "mmio-sram";
 			reg = <0x00300000 0x20000>;
+			ranges = <0 0x00300000 0x20000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
 		};
 	};
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx23-evk.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx23-evk.dts
@@ -79,7 +79,6 @@
 						MX23_PAD_LCD_RESET__GPIO_1_18
 						MX23_PAD_PWM3__GPIO_1_29
 						MX23_PAD_PWM4__GPIO_1_30
-						MX23_PAD_SSP1_DETECT__SSP1_DETECT
 					>;
 					fsl,drive-strength = <MXS_DRIVE_4mA>;
 					fsl,voltage = <MXS_VOLTAGE_HIGH>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx23-sansa.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx23-sansa.dts
@@ -175,10 +175,8 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 		compatible = "i2c-gpio";
-		gpios = <
-			&gpio1 24 0		/* SDA */
-			&gpio1 22 0		/* SCL */
-		>;
+		sda-gpios = <&gpio1 24 0>;
+		scl-gpios = <&gpio1 22 0>;
 		i2c-gpio,delay-us = <2>;	/* ~100 kHz */
 	};
 
@@ -186,10 +184,8 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 		compatible = "i2c-gpio";
-		gpios = <
-			&gpio0 31 0		/* SDA */
-			&gpio0 30 0		/* SCL */
-		>;
+		sda-gpios = <&gpio0 31 0>;
+		scl-gpios = <&gpio0 30 0>;
 		i2c-gpio,delay-us = <2>;	/* ~100 kHz */
 
 		touch: touch@20 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx23.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx23.dtsi
@@ -59,7 +59,7 @@
 				reg = <0x80000000 0x2000>;
 			};
 
-			dma_apbh: dma-apbh@80004000 {
+			dma_apbh: dma-controller@80004000 {
 				compatible = "fsl,imx23-dma-apbh";
 				reg = <0x80004000 0x2000>;
 				interrupts = <0 14 20 0
@@ -406,7 +406,7 @@
 				status = "disabled";
 			};
 
-			dma_apbx: dma-apbx@80024000 {
+			dma_apbx: dma-controller@80024000 {
 				compatible = "fsl,imx23-dma-apbx";
 				reg = <0x80024000 0x2000>;
 				interrupts = <7 5 9 26
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx25-eukrea-cpuimx25.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx25-eukrea-cpuimx25.dtsi
@@ -27,7 +27,7 @@
 	pinctrl-0 = <&pinctrl_i2c1>;
 	status = "okay";
 
-	pcf8563@51 {
+	rtc@51 {
 		compatible = "nxp,pcf8563";
 		reg = <0x51>;
 	};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-cmo-qvga.dts
@@ -16,7 +16,7 @@
 		bus-width = <18>;
 		display-timings {
 			native-mode = <&qvga_timings>;
-			qvga_timings: 320x240 {
+			qvga_timings: timing0 {
 				clock-frequency = <6500000>;
 				hactive = <320>;
 				vactive = <240>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-svga.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-svga.dts
@@ -16,7 +16,7 @@
 		bus-width = <18>;
 		display-timings {
 			native-mode = <&dvi_svga_timings>;
-			dvi_svga_timings: 800x600 {
+			dvi_svga_timings: timing0 {
 				clock-frequency = <40000000>;
 				hactive = <800>;
 				vactive = <600>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard-dvi-vga.dts
@@ -16,7 +16,7 @@
 		bus-width = <18>;
 		display-timings {
 			native-mode = <&dvi_vga_timings>;
-			dvi_vga_timings: 640x480 {
+			dvi_vga_timings: timing0 {
 				clock-frequency = <31250000>;
 				hactive = <640>;
 				vactive = <480>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx25-pdk.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx25-pdk.dts
@@ -78,7 +78,7 @@
 		bus-width = <18>;
 		display-timings {
 			native-mode = <&wvga_timings>;
-			wvga_timings: 640x480 {
+			wvga_timings: timing0 {
 				hactive = <640>;
 				vactive = <480>;
 				hback-porch = <45>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx27-apf27dev.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx27-apf27dev.dts
@@ -16,7 +16,7 @@
 		fsl,pcr = <0xfae80083>;	/* non-standard but required */
 		display-timings {
 			native-mode = <&timing0>;
-			timing0: 800x480 {
+			timing0: timing0 {
 				clock-frequency = <33000033>;
 				hactive = <800>;
 				vactive = <480>;
@@ -47,7 +47,7 @@
 		pinctrl-names = "default";
 		pinctrl-0 = <&pinctrl_gpio_leds>;
 
-		user {
+		led-user {
 			label = "Heartbeat";
 			gpios = <&gpio6 14 GPIO_ACTIVE_HIGH>;
 			linux,default-trigger = "heartbeat";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx27-eukrea-cpuimx27.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx27-eukrea-cpuimx27.dtsi
@@ -33,7 +33,7 @@
 	pinctrl-0 = <&pinctrl_i2c1>;
 	status = "okay";
 
-	pcf8563@51 {
+	rtc@51 {
 		compatible = "nxp,pcf8563";
 		reg = <0x51>;
 	};
@@ -90,7 +90,7 @@
 &weim {
 	status = "okay";
 
-	nor: nor@0,0 {
+	nor: flash@0,0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
 		compatible = "cfi-flash";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx27-eukrea-mbimxsd27-baseboard.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx27-eukrea-mbimxsd27-baseboard.dts
@@ -16,7 +16,7 @@
 
 		display-timings {
 			native-mode = <&timing0>;
-			timing0: 320x240 {
+			timing0: timing0 {
 				clock-frequency = <6500000>;
 				hactive = <320>;
 				vactive = <240>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx27-phytec-phycard-s-rdk.dts
@@ -19,7 +19,7 @@
 		fsl,pcr = <0xf0c88080>;	/* non-standard but required */
 		display-timings {
 			native-mode = <&timing0>;
-			timing0: 640x480 {
+			timing0: timing0 {
 				hactive = <640>;
 				vactive = <480>;
 				hback-porch = <112>;
@@ -75,8 +75,8 @@
 	imx27-phycard-s-rdk {
 		pinctrl_i2c1: i2c1grp {
 			fsl,pins = <
-				MX27_PAD_I2C2_SDA__I2C2_SDA 0x0
-				MX27_PAD_I2C2_SCL__I2C2_SCL 0x0
+				MX27_PAD_I2C_DATA__I2C_DATA 0x0
+				MX27_PAD_I2C_CLK__I2C_CLK 0x0
 			>;
 		};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx27-phytec-phycore-rdk.dts
@@ -19,7 +19,7 @@
 
 		display-timings {
 			native-mode = <&timing0>;
-			timing0: 240x320 {
+			timing0: timing0 {
 				clock-frequency = <5500000>;
 				hactive = <240>;
 				vactive = <320>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx27-phytec-phycore-som.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx27-phytec-phycore-som.dtsi
@@ -322,7 +322,7 @@
 &weim {
 	status = "okay";
 
-	nor: nor@0,0 {
+	nor: flash@0,0 {
 		compatible = "cfi-flash";
 		reg = <0 0x00000000 0x02000000>;
 		bank-width = <2>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx27.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx27.dtsi
@@ -588,6 +588,9 @@
 		iram: iram@ffff4c00 {
 			compatible = "mmio-sram";
 			reg = <0xffff4c00 0xb400>;
+			ranges = <0 0xffff4c00 0xb400>;
+			#address-cells = <1>;
+			#size-cells = <1>;
 		};
 	};
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx28.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx28.dtsi
@@ -78,7 +78,7 @@
 				status = "disabled";
 			};
 
-			dma_apbh: dma-apbh@80004000 {
+			dma_apbh: dma-controller@80004000 {
 				compatible = "fsl,imx28-dma-apbh";
 				reg = <0x80004000 0x2000>;
 				interrupts = <82 83 84 85
@@ -982,7 +982,7 @@
 				status = "disabled";
 			};
 
-			dma_apbx: dma-apbx@80024000 {
+			dma_apbx: dma-controller@80024000 {
 				compatible = "fsl,imx28-dma-apbx";
 				reg = <0x80024000 0x2000>;
 				interrupts = <78 79 66 0
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx35.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx35.dtsi
@@ -59,7 +59,7 @@
 		interrupt-parent = <&avic>;
 		ranges;
 
-		L2: l2-cache@30000000 {
+		L2: cache-controller@30000000 {
 			compatible = "arm,l210-cache";
 			reg = <0x30000000 0x1000>;
 			cache-unified;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx50-evk.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx50-evk.dts
@@ -59,7 +59,7 @@
 				MX50_PAD_CSPI_MISO__CSPI_MISO		0x00
 				MX50_PAD_CSPI_MOSI__CSPI_MOSI		0x00
 				MX50_PAD_CSPI_SS0__GPIO4_11		0xc4
-				MX50_PAD_ECSPI1_MOSI__CSPI_SS1		0xf4
+				MX50_PAD_ECSPI1_MOSI__GPIO4_13		0x84
 			>;
 		};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx53-m53menlo.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx53-m53menlo.dts
@@ -53,14 +53,40 @@
 		};
 	};
 
+	lvds-decoder {
+		compatible = "ti,ds90cf364a", "lvds-decoder";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+
+				lvds_decoder_in: endpoint {
+					remote-endpoint = <&lvds0_out>;
+				};
+			};
+
+			port@1 {
+				reg = <1>;
+
+				lvds_decoder_out: endpoint {
+					remote-endpoint = <&panel_in>;
+				};
+			};
+		};
+	};
+
 	panel {
 		compatible = "edt,etm0700g0dh6";
 		pinctrl-0 = <&pinctrl_display_gpio>;
+		pinctrl-names = "default";
 		enable-gpios = <&gpio6 0 GPIO_ACTIVE_HIGH>;
 
 		port {
 			panel_in: endpoint {
-				remote-endpoint = <&lvds0_out>;
+				remote-endpoint = <&lvds_decoder_out>;
 			};
 		};
 	};
@@ -76,8 +102,7 @@
 		regulator-name = "vbus";
 		regulator-min-microvolt = <5000000>;
 		regulator-max-microvolt = <5000000>;
-		gpio = <&gpio1 2 GPIO_ACTIVE_HIGH>;
-		enable-active-high;
+		gpio = <&gpio1 2 0>;
 	};
 };
 
@@ -388,13 +413,13 @@
 
 		pinctrl_power_button: powerbutgrp {
 			fsl,pins = <
-				MX53_PAD_SD2_DATA2__GPIO1_13		0x1e4
+				MX53_PAD_SD2_DATA0__GPIO1_15		0x1e4
 			>;
 		};
 
 		pinctrl_power_out: poweroutgrp {
 			fsl,pins = <
-				MX53_PAD_SD2_DATA0__GPIO1_15		0x1e4
+				MX53_PAD_SD2_DATA2__GPIO1_13		0x1e4
 			>;
 		};
 
@@ -450,7 +475,7 @@
 			reg = <2>;
 
 			lvds0_out: endpoint {
-				remote-endpoint = <&panel_in>;
+				remote-endpoint = <&lvds_decoder_in>;
 			};
 		};
 	};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx53-ppd.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx53-ppd.dts
@@ -70,6 +70,12 @@
 		clock-frequency = <11289600>;
 	};
 
+	achc_24M: achc-clock {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <24000000>;
+	};
+
 	sgtlsound: sound {
 		compatible = "fsl,imx53-cpuvo-sgtl5000",
 			     "fsl,imx-audio-sgtl5000";
@@ -287,16 +293,13 @@
 		    &gpio4 12 GPIO_ACTIVE_LOW>;
 	status = "okay";
 
-	spidev0: spi@0 {
-		compatible = "ge,achc";
-		reg = <0>;
-		spi-max-frequency = <1000000>;
-	};
-
-	spidev1: spi@1 {
-		compatible = "ge,achc";
-		reg = <1>;
-		spi-max-frequency = <1000000>;
+	spidev0: spi@1 {
+		compatible = "ge,achc", "nxp,kinetis-k20";
+		reg = <1>, <0>;
+		vdd-supply = <&reg_3v3>;
+		vdda-supply = <&reg_3v3>;
+		clocks = <&achc_24M>;
+		reset-gpios = <&gpio3 6 GPIO_ACTIVE_LOW>;
 	};
 
 	gpioxra0: gpio@2 {
@@ -458,7 +461,7 @@
 	scl-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;
 	status = "okay";
 
-	i2c-switch@70 {
+	i2c-mux@70 {
 		compatible = "nxp,pca9547";
 		#address-cells = <1>;
 		#size-cells = <0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6dl-icore-mipi.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6dl-icore-mipi.dts
@@ -8,7 +8,7 @@
 /dts-v1/;
 
 #include "imx6dl.dtsi"
-#include "imx6qdl-icore.dtsi"
+#include "imx6qdl-icore-1.5.dtsi"
 
 / {
 	model = "Engicam i.CoreM6 DualLite/Solo MIPI Starter Kit";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6dl-yapp4-common.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6dl-yapp4-common.dtsi
@@ -96,27 +96,22 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_enet>;
 	phy-mode = "rgmii-id";
-	phy-reset-gpios = <&gpio1 25 GPIO_ACTIVE_LOW>;
-	phy-reset-duration = <20>;
 	phy-supply = <&sw2_reg>;
-	phy-handle = <&ethphy0>;
 	status = "okay";
 
+	fixed-link {
+		speed = <1000>;
+		full-duplex;
+	};
+
 	mdio {
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		phy_port2: phy@1 {
-			reg = <1>;
-		};
-
-		phy_port3: phy@2 {
-			reg = <2>;
-		};
-
 		switch@10 {
 			compatible = "qca,qca8334";
-			reg = <10>;
+			reg = <0x10>;
+			reset-gpios = <&gpio1 25 GPIO_ACTIVE_LOW>;
 
 			switch_ports: ports {
 				#address-cells = <1>;
@@ -137,15 +132,30 @@
 				port@2 {
 					reg = <2>;
 					label = "eth2";
+					phy-mode = "internal";
 					phy-handle = <&phy_port2>;
 				};
 
 				port@3 {
 					reg = <3>;
 					label = "eth1";
+					phy-mode = "internal";
 					phy-handle = <&phy_port3>;
 				};
 			};
+
+			mdio {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				phy_port2: ethernet-phy@1 {
+					reg = <1>;
+				};
+
+				phy_port3: ethernet-phy@2 {
+					reg = <2>;
+				};
+			};
 		};
 	};
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6dl-yapp4-ursa.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6dl-yapp4-ursa.dts
@@ -38,7 +38,7 @@
 };
 
 &switch_ports {
-	/delete-node/ port@2;
+	/delete-node/ port@3;
 };
 
 &touchscreen {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6dl.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6dl.dtsi
@@ -81,6 +81,9 @@
 		ocram: sram@900000 {
 			compatible = "mmio-sram";
 			reg = <0x00900000 0x20000>;
+			ranges = <0 0x00900000 0x20000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
 			clocks = <&clks IMX6QDL_CLK_OCRAM>;
 		};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6q-b450v3.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6q-b450v3.dts
@@ -65,13 +65,6 @@
 	};
 };
 
-&clks {
-	assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>,
-			  <&clks IMX6QDL_CLK_LDB_DI1_SEL>;
-	assigned-clock-parents = <&clks IMX6QDL_CLK_PLL3_USB_OTG>,
-				 <&clks IMX6QDL_CLK_PLL3_USB_OTG>;
-};
-
 &ldb {
 	status = "okay";
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6q-b650v3.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6q-b650v3.dts
@@ -65,13 +65,6 @@
 	};
 };
 
-&clks {
-	assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>,
-			  <&clks IMX6QDL_CLK_LDB_DI1_SEL>;
-	assigned-clock-parents = <&clks IMX6QDL_CLK_PLL3_USB_OTG>,
-				 <&clks IMX6QDL_CLK_PLL3_USB_OTG>;
-};
-
 &ldb {
 	status = "okay";
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6q-b850v3.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6q-b850v3.dts
@@ -53,17 +53,6 @@
 	};
 };
 
-&clks {
-	assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>,
-			  <&clks IMX6QDL_CLK_LDB_DI1_SEL>,
-			  <&clks IMX6QDL_CLK_IPU1_DI0_PRE_SEL>,
-			  <&clks IMX6QDL_CLK_IPU2_DI0_PRE_SEL>;
-	assigned-clock-parents = <&clks IMX6QDL_CLK_PLL5_VIDEO_DIV>,
-				 <&clks IMX6QDL_CLK_PLL5_VIDEO_DIV>,
-				 <&clks IMX6QDL_CLK_PLL2_PFD2_396M>,
-				 <&clks IMX6QDL_CLK_PLL2_PFD2_396M>;
-};
-
 &ldb {
 	fsl,dual-channel;
 	status = "okay";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6q-bx50v3.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6q-bx50v3.dtsi
@@ -377,3 +377,18 @@
 		#interrupt-cells = <1>;
 	};
 };
+
+&clks {
+	assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>,
+			  <&clks IMX6QDL_CLK_LDB_DI1_SEL>,
+			  <&clks IMX6QDL_CLK_IPU1_DI0_PRE_SEL>,
+			  <&clks IMX6QDL_CLK_IPU1_DI1_PRE_SEL>,
+			  <&clks IMX6QDL_CLK_IPU2_DI0_PRE_SEL>,
+			  <&clks IMX6QDL_CLK_IPU2_DI1_PRE_SEL>;
+	assigned-clock-parents = <&clks IMX6QDL_CLK_PLL5_VIDEO_DIV>,
+				 <&clks IMX6QDL_CLK_PLL5_VIDEO_DIV>,
+				 <&clks IMX6QDL_CLK_PLL2_PFD0_352M>,
+				 <&clks IMX6QDL_CLK_PLL2_PFD0_352M>,
+				 <&clks IMX6QDL_CLK_PLL2_PFD0_352M>,
+				 <&clks IMX6QDL_CLK_PLL2_PFD0_352M>;
+};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6q-dhcom-pdk2.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6q-dhcom-pdk2.dts
@@ -55,7 +55,7 @@
 		#sound-dai-cells = <0>;
 		clocks = <&clk_ext_audio_codec>;
 		VDDA-supply = <&reg_3p3v>;
-		VDDIO-supply = <&reg_3p3v>;
+		VDDIO-supply = <&sw2_reg>;
 	};
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6q-dhcom-som.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6q-dhcom-som.dtsi
@@ -98,30 +98,40 @@
 			reg = <0>;
 			max-speed = <100>;
 			reset-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
-			reset-delay-us = <1000>;
-			reset-post-delay-us = <1000>;
+			reset-assert-us = <1000>;
+			reset-deassert-us = <1000>;
+			smsc,disable-energy-detect; /* Make plugin detection reliable */
 		};
 	};
 };
 
 &i2c1 {
 	clock-frequency = <100000>;
-	pinctrl-names = "default";
+	pinctrl-names = "default", "gpio";
 	pinctrl-0 = <&pinctrl_i2c1>;
+	pinctrl-1 = <&pinctrl_i2c1_gpio>;
+	scl-gpios = <&gpio3 21 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+	sda-gpios = <&gpio3 28 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
 	status = "okay";
 };
 
 &i2c2 {
 	clock-frequency = <100000>;
-	pinctrl-names = "default";
+	pinctrl-names = "default", "gpio";
 	pinctrl-0 = <&pinctrl_i2c2>;
+	pinctrl-1 = <&pinctrl_i2c2_gpio>;
+	scl-gpios = <&gpio4 12 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+	sda-gpios = <&gpio4 13 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
 	status = "okay";
 };
 
 &i2c3 {
 	clock-frequency = <100000>;
-	pinctrl-names = "default";
+	pinctrl-names = "default", "gpio";
 	pinctrl-0 = <&pinctrl_i2c3>;
+	pinctrl-1 = <&pinctrl_i2c3_gpio>;
+	scl-gpios = <&gpio1 3 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+	sda-gpios = <&gpio1 6 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
 	status = "okay";
 
 	ltc3676: pmic@3c {
@@ -206,7 +216,7 @@
 	};
 
 	rtc@56 {
-		compatible = "rv3029c2";
+		compatible = "microcrystal,rv3029";
 		pinctrl-names = "default";
 		pinctrl-0 = <&pinctrl_rtc_hw300>;
 		reg = <0x56>;
@@ -287,6 +297,13 @@
 		>;
 	};
 
+	pinctrl_i2c1_gpio: i2c1-gpio-grp {
+		fsl,pins = <
+			MX6QDL_PAD_EIM_D21__GPIO3_IO21		0x4001b8b1
+			MX6QDL_PAD_EIM_D28__GPIO3_IO28		0x4001b8b1
+		>;
+	};
+
 	pinctrl_i2c2: i2c2-grp {
 		fsl,pins = <
 			MX6QDL_PAD_KEY_COL3__I2C2_SCL		0x4001b8b1
@@ -294,6 +311,13 @@
 		>;
 	};
 
+	pinctrl_i2c2_gpio: i2c2-gpio-grp {
+		fsl,pins = <
+			MX6QDL_PAD_KEY_COL3__GPIO4_IO12		0x4001b8b1
+			MX6QDL_PAD_KEY_ROW3__GPIO4_IO13		0x4001b8b1
+		>;
+	};
+
 	pinctrl_i2c3: i2c3-grp {
 		fsl,pins = <
 			MX6QDL_PAD_GPIO_3__I2C3_SCL		0x4001b8b1
@@ -301,6 +325,13 @@
 		>;
 	};
 
+	pinctrl_i2c3_gpio: i2c3-gpio-grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_3__GPIO1_IO03		0x4001b8b1
+			MX6QDL_PAD_GPIO_6__GPIO1_IO06		0x4001b8b1
+		>;
+	};
+
 	pinctrl_pmic_hw300: pmic-hw300-grp {
 		fsl,pins = <
 			MX6QDL_PAD_EIM_A25__GPIO5_IO02		0x1B0B0
@@ -408,6 +439,18 @@
 	vin-supply = <&sw1_reg>;
 };
 
+&reg_pu {
+	vin-supply = <&sw1_reg>;
+};
+
+&reg_vdd1p1 {
+	vin-supply = <&sw2_reg>;
+};
+
+&reg_vdd2p5 {
+	vin-supply = <&sw2_reg>;
+};
+
 &uart1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_uart1>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6q.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6q.dtsi
@@ -158,6 +158,9 @@
 		ocram: sram@900000 {
 			compatible = "mmio-sram";
 			reg = <0x00900000 0x40000>;
+			ranges = <0 0x00900000 0x40000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
 			clocks = <&clks IMX6QDL_CLK_OCRAM>;
 		};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6qdl-apalis.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6qdl-apalis.dtsi
@@ -314,6 +314,8 @@
 	codec: sgtl5000@a {
 		compatible = "fsl,sgtl5000";
 		reg = <0x0a>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_sgtl5000>;
 		clocks = <&clks IMX6QDL_CLK_CKO>;
 		VDDA-supply = <&reg_module_3v3_audio>;
 		VDDIO-supply = <&reg_module_3v3>;
@@ -543,8 +545,6 @@
 			MX6QDL_PAD_DISP0_DAT21__AUD4_TXD	0x130b0
 			MX6QDL_PAD_DISP0_DAT22__AUD4_TXFS	0x130b0
 			MX6QDL_PAD_DISP0_DAT23__AUD4_RXD	0x130b0
-			/* SGTL5000 sys_mclk */
-			MX6QDL_PAD_GPIO_5__CCM_CLKO1		0x130b0
 		>;
 	};
 
@@ -810,6 +810,12 @@
 		>;
 	};
 
+	pinctrl_sgtl5000: sgtl5000grp {
+		fsl,pins = <
+			MX6QDL_PAD_GPIO_5__CCM_CLKO1	0x130b0
+		>;
+	};
+
 	pinctrl_spdif: spdifgrp {
 		fsl,pins = <
 			MX6QDL_PAD_GPIO_16__SPDIF_IN  0x1b0b0
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6qdl-emcon-avari.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6qdl-emcon-avari.dtsi
@@ -126,7 +126,7 @@
 		compatible = "nxp,pca8574";
 		reg = <0x3a>;
 		gpio-controller;
-		#gpio-cells = <1>;
+		#gpio-cells = <2>;
 	};
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
@@ -273,7 +273,7 @@
 
 			/* VDD_AUD_1P8: Audio codec */
 			reg_aud_1p8v: ldo3 {
-				regulator-name = "vdd1p8";
+				regulator-name = "vdd1p8a";
 				regulator-min-microvolt = <1800000>;
 				regulator-max-microvolt = <1800000>;
 				regulator-boot-on;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6qdl-gw551x.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6qdl-gw551x.dtsi
@@ -105,19 +105,16 @@
 	sound-digital {
 		compatible = "simple-audio-card";
 		simple-audio-card,name = "tda1997x-audio";
+		simple-audio-card,format = "i2s";
+		simple-audio-card,bitclock-master = <&sound_codec>;
+		simple-audio-card,frame-master = <&sound_codec>;
 
-		simple-audio-card,dai-link@0 {
-			format = "i2s";
-
-			cpu {
-				sound-dai = <&ssi2>;
-			};
+		sound_cpu: simple-audio-card,cpu {
+			sound-dai = <&ssi1>;
+		};
 
-			codec {
-				bitclock-master;
-				frame-master;
-				sound-dai = <&hdmi_receiver>;
-			};
+		sound_codec: simple-audio-card,codec {
+			sound-dai = <&hdmi_receiver>;
 		};
 	};
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6qdl-gw560x.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6qdl-gw560x.dtsi
@@ -464,7 +464,6 @@
 &uart1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_uart1>;
-	uart-has-rtscts;
 	rts-gpios = <&gpio7 1 GPIO_ACTIVE_HIGH>;
 	status = "okay";
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6qdl-icore.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6qdl-icore.dtsi
@@ -384,7 +384,7 @@
 
 	pinctrl_usbotg: usbotggrp {
 		fsl,pins = <
-			MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
+			MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059
 		>;
 	};
 
@@ -396,6 +396,7 @@
 			MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17070
 			MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17070
 			MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17070
+			MX6QDL_PAD_GPIO_1__GPIO1_IO01  0x1b0b0
 		>;
 	};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6qdl-kontron-samx6i.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6qdl-kontron-samx6i.dtsi
@@ -51,16 +51,6 @@
 		vin-supply = <&reg_3p3v_s5>;
 	};
 
-	reg_3p3v_s0: regulator-3p3v-s0 {
-		compatible = "regulator-fixed";
-		regulator-name = "V_3V3_S0";
-		regulator-min-microvolt = <3300000>;
-		regulator-max-microvolt = <3300000>;
-		regulator-always-on;
-		regulator-boot-on;
-		vin-supply = <&reg_3p3v_s5>;
-	};
-
 	reg_3p3v_s5: regulator-3p3v-s5 {
 		compatible = "regulator-fixed";
 		regulator-name = "V_3V3_S5";
@@ -167,7 +157,7 @@
 		i2c-gpio,delay-us = <2>; /* ~100 kHz */
 		#address-cells = <1>;
 		#size-cells = <0>;
-		status = "disabld";
+		status = "disabled";
 	};
 
 	i2c_cam: i2c-gpio-cam {
@@ -179,7 +169,7 @@
 		i2c-gpio,delay-us = <2>; /* ~100 kHz */
 		#address-cells = <1>;
 		#size-cells = <0>;
-		status = "disabld";
+		status = "disabled";
 	};
 };
 
@@ -269,8 +259,20 @@
 &fec {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_enet>;
-	phy-mode = "rgmii";
-	phy-reset-gpios = <&gpio1 25 GPIO_ACTIVE_LOW>;
+	phy-connection-type = "rgmii-id";
+	phy-handle = <&ethphy>;
+
+	mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ethphy: ethernet-phy@1 {
+			compatible = "ethernet-phy-ieee802.3-c22";
+			reg = <1>;
+			reset-gpios = <&gpio2 1 GPIO_ACTIVE_LOW>;
+			reset-assert-us = <1000>;
+		};
+	};
 };
 
 &i2c_intern {
@@ -510,7 +512,7 @@
 			MX6QDL_PAD_ENET_MDIO__ENET_MDIO       0x1b0b0
 			MX6QDL_PAD_ENET_MDC__ENET_MDC         0x1b0b0
 			MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK  0x1b0b0
-			MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25    0x1b0b0 /* RST_GBE0_PHY# */
+			MX6QDL_PAD_NANDF_D1__GPIO2_IO01       0x1b0b0 /* RST_GBE0_PHY# */
 		>;
 	};
 
@@ -551,7 +553,7 @@
 
 	pinctrl_i2c3: i2c3grp {
 		fsl,pins = <
-			MX6QDL_PAD_GPIO_3__I2C3_SCL		0x4001b8b1
+			MX6QDL_PAD_GPIO_5__I2C3_SCL		0x4001b8b1
 			MX6QDL_PAD_GPIO_16__I2C3_SDA		0x4001b8b1
 		>;
 	};
@@ -723,7 +725,7 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_pcie>;
 	wake-up-gpio = <&gpio6 18 GPIO_ACTIVE_HIGH>;
-	reset-gpio = <&gpio3 13 GPIO_ACTIVE_HIGH>;
+	reset-gpio = <&gpio3 13 GPIO_ACTIVE_LOW>;
 };
 
 /* LCD_BKLT_PWM */
@@ -811,5 +813,6 @@
 	/* CPLD is feeded by watchdog (hardwired) */
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_wdog1>;
+	fsl,ext-reset-output;
 	status = "okay";
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi
@@ -315,8 +315,8 @@
 			fsl,pins = <
 				MX6QDL_PAD_EIM_D24__UART3_TX_DATA	0x1b0b1
 				MX6QDL_PAD_EIM_D25__UART3_RX_DATA	0x1b0b1
-				MX6QDL_PAD_EIM_D30__UART3_RTS_B		0x1b0b1
-				MX6QDL_PAD_EIM_D31__UART3_CTS_B		0x1b0b1
+				MX6QDL_PAD_EIM_D31__UART3_RTS_B		0x1b0b1
+				MX6QDL_PAD_EIM_D30__UART3_CTS_B		0x1b0b1
 			>;
 		};
 
@@ -403,6 +403,7 @@
 &uart3 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_uart3>;
+	uart-has-rtscts;
 	status = "disabled";
 };
 
@@ -432,6 +433,7 @@
 	pinctrl-0 = <&pinctrl_usdhc2>;
 	cd-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
 	wp-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
+	vmmc-supply = <&vdd_sd1_reg>;
 	status = "disabled";
 };
 
@@ -441,5 +443,6 @@
 		     &pinctrl_usdhc3_cdwp>;
 	cd-gpios = <&gpio1 27 GPIO_ACTIVE_LOW>;
 	wp-gpios = <&gpio1 29 GPIO_ACTIVE_HIGH>;
+	vmmc-supply = <&vdd_sd0_reg>;
 	status = "disabled";
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6qdl-phytec-phycore-som.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6qdl-phytec-phycore-som.dtsi
@@ -107,14 +107,14 @@
 		regulators {
 			vdd_arm: buck1 {
 				regulator-name = "vdd_arm";
-				regulator-min-microvolt = <730000>;
+				regulator-min-microvolt = <925000>;
 				regulator-max-microvolt = <1380000>;
 				regulator-always-on;
 			};
 
 			vdd_soc: buck2 {
 				regulator-name = "vdd_soc";
-				regulator-min-microvolt = <730000>;
+				regulator-min-microvolt = <1150000>;
 				regulator-max-microvolt = <1380000>;
 				regulator-always-on;
 			};
@@ -183,7 +183,6 @@
 	pinctrl-0 = <&pinctrl_usdhc4>;
 	bus-width = <8>;
 	non-removable;
-	vmmc-supply = <&vdd_emmc_1p8>;
 	status = "disabled";
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
@@ -749,10 +749,6 @@
 	vin-supply = <&vgen5_reg>;
 };
 
-&reg_vdd3p0 {
-	vin-supply = <&sw2_reg>;
-};
-
 &reg_vdd2p5 {
 	vin-supply = <&vgen5_reg>;
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6qdl-sr-som-ti.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6qdl-sr-som-ti.dtsi
@@ -153,6 +153,7 @@
 	bus-width = <4>;
 	keep-power-in-suspend;
 	mmc-pwrseq = <&pwrseq_ti_wifi>;
+	cap-power-off-card;
 	non-removable;
 	vmmc-supply = <&vcc_3v3>;
 	/* vqmmc-supply = <&nvcc_sd1>; - MMC layer doesn't like it! */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6qdl-sr-som.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6qdl-sr-som.dtsi
@@ -54,7 +54,13 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_microsom_enet_ar8035>;
 	phy-mode = "rgmii-id";
-	phy-reset-duration = <2>;
+
+	/*
+	 * The PHY seems to require a long-enough reset duration to avoid
+	 * some rare issues where the PHY gets stuck in an inconsistent and
+	 * non-functional state at boot-up. 10ms proved to be fine .
+	 */
+	phy-reset-duration = <10>;
 	phy-reset-gpios = <&gpio4 15 GPIO_ACTIVE_LOW>;
 	status = "okay";
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6qdl-ts7970.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6qdl-ts7970.dtsi
@@ -226,7 +226,7 @@
 		reg = <0x28>;
 		#gpio-cells = <2>;
 		gpio-controller;
-		ngpio = <32>;
+		ngpios = <62>;
 	};
 
 	sgtl5000: codec@a {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6qdl-udoo.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6qdl-udoo.dtsi
@@ -5,6 +5,8 @@
  * Author: Fabio Estevam <fabio.estevam@freescale.com>
  */
 
+#include <dt-bindings/gpio/gpio.h>
+
 / {
 	aliases {
 		backlight = &backlight;
@@ -98,7 +100,7 @@
 &fec {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_enet>;
-	phy-mode = "rgmii";
+	phy-mode = "rgmii-id";
 	status = "okay";
 };
 
@@ -218,6 +220,7 @@
 				MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x17059
 				MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x17059
 				MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x17059
+				MX6QDL_PAD_SD3_DAT5__GPIO7_IO00		0x1b0b0
 			>;
 		};
 
@@ -290,7 +293,7 @@
 &usdhc3 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_usdhc3>;
-	non-removable;
+	cd-gpios = <&gpio7 0 GPIO_ACTIVE_LOW>;
 	status = "okay";
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6qdl-wandboard-revd1.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6qdl-wandboard-revd1.dtsi
@@ -166,7 +166,6 @@
 				MX6QDL_PAD_RGMII_RD2__RGMII_RD2		0x1b030
 				MX6QDL_PAD_RGMII_RD3__RGMII_RD3		0x1b030
 				MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL	0x1b030
-				MX6QDL_PAD_GPIO_6__ENET_IRQ		0x000b1
 			>;
 		};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6qdl-zii-rdu2.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6qdl-zii-rdu2.dtsi
@@ -627,7 +627,7 @@
 	pinctrl-0 = <&pinctrl_usdhc2>;
 	bus-width = <4>;
 	cd-gpios = <&gpio2 2 GPIO_ACTIVE_LOW>;
-	wp-gpios = <&gpio2 3 GPIO_ACTIVE_HIGH>;
+	disable-wp;
 	vmmc-supply = <&reg_3p3v_sd>;
 	vqmmc-supply = <&reg_3p3v>;
 	no-1-8-v;
@@ -640,7 +640,7 @@
 	pinctrl-0 = <&pinctrl_usdhc3>;
 	bus-width = <4>;
 	cd-gpios = <&gpio2 0 GPIO_ACTIVE_LOW>;
-	wp-gpios = <&gpio2 1 GPIO_ACTIVE_HIGH>;
+	disable-wp;
 	vmmc-supply = <&reg_3p3v_sd>;
 	vqmmc-supply = <&reg_3p3v>;
 	no-1-8-v;
@@ -774,6 +774,7 @@
 &usbh1 {
 	vbus-supply = <&reg_5p0v_main>;
 	disable-over-current;
+	maximum-speed = "full-speed";
 	status = "okay";
 };
 
@@ -1055,7 +1056,6 @@
 			MX6QDL_PAD_SD2_DAT1__SD2_DATA1		0x17059
 			MX6QDL_PAD_SD2_DAT2__SD2_DATA2		0x17059
 			MX6QDL_PAD_SD2_DAT3__SD2_DATA3		0x17059
-			MX6QDL_PAD_NANDF_D3__GPIO2_IO03		0x40010040
 			MX6QDL_PAD_NANDF_D2__GPIO2_IO02		0x40010040
 		>;
 	};
@@ -1068,7 +1068,6 @@
 			MX6QDL_PAD_SD3_DAT1__SD3_DATA1		0x17059
 			MX6QDL_PAD_SD3_DAT2__SD3_DATA2		0x17059
 			MX6QDL_PAD_SD3_DAT3__SD3_DATA3		0x17059
-			MX6QDL_PAD_NANDF_D1__GPIO2_IO01		0x40010040
 			MX6QDL_PAD_NANDF_D0__GPIO2_IO00		0x40010040
 
 		>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6qdl.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6qdl.dtsi
@@ -45,6 +45,10 @@
 		spi1 = &ecspi2;
 		spi2 = &ecspi3;
 		spi3 = &ecspi4;
+		usb0 = &usbotg;
+		usb1 = &usbh1;
+		usb2 = &usbh2;
+		usb3 = &usbh3;
 		usbphy0 = &usbphy1;
 		usbphy1 = &usbphy2;
 	};
@@ -156,7 +160,7 @@
 		interrupt-parent = <&gpc>;
 		ranges;
 
-		dma_apbh: dma-apbh@110000 {
+		dma_apbh: dma-controller@110000 {
 			compatible = "fsl,imx6q-dma-apbh", "fsl,imx28-dma-apbh";
 			reg = <0x00110000 0x2000>;
 			interrupts = <0 13 IRQ_TYPE_LEVEL_HIGH>,
@@ -255,7 +259,7 @@
 			interrupt-parent = <&intc>;
 		};
 
-		L2: l2-cache@a02000 {
+		L2: cache-controller@a02000 {
 			compatible = "arm,pl310-cache";
 			reg = <0x00a02000 0x1000>;
 			interrupts = <0 92 IRQ_TYPE_LEVEL_HIGH>;
@@ -574,7 +578,7 @@
 				status = "disabled";
 			};
 
-			gpt: gpt@2098000 {
+			gpt: timer@2098000 {
 				compatible = "fsl,imx6q-gpt", "fsl,imx31-gpt";
 				reg = <0x02098000 0x4000>;
 				interrupts = <0 55 IRQ_TYPE_LEVEL_HIGH>;
@@ -766,7 +770,7 @@
 					regulator-name = "vddpu";
 					regulator-min-microvolt = <725000>;
 					regulator-max-microvolt = <1450000>;
-					regulator-enable-ramp-delay = <150>;
+					regulator-enable-ramp-delay = <380>;
 					anatop-reg-offset = <0x140>;
 					anatop-vol-bit-shift = <9>;
 					anatop-vol-bit-width = <5>;
@@ -1039,9 +1043,8 @@
 				compatible = "fsl,imx6q-fec";
 				reg = <0x02188000 0x4000>;
 				interrupt-names = "int0", "pps";
-				interrupts-extended =
-					<&intc 0 118 IRQ_TYPE_LEVEL_HIGH>,
-					<&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
+				interrupts = <0 118 IRQ_TYPE_LEVEL_HIGH>,
+					     <0 119 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks IMX6QDL_CLK_ENET>,
 					 <&clks IMX6QDL_CLK_ENET>,
 					 <&clks IMX6QDL_CLK_ENET_REF>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6qp.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6qp.dtsi
@@ -9,12 +9,18 @@
 		ocram2: sram@940000 {
 			compatible = "mmio-sram";
 			reg = <0x00940000 0x20000>;
+			ranges = <0 0x00940000 0x20000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
 			clocks = <&clks IMX6QDL_CLK_OCRAM>;
 		};
 
 		ocram3: sram@960000 {
 			compatible = "mmio-sram";
 			reg = <0x00960000 0x20000>;
+			ranges = <0 0x00960000 0x20000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
 			clocks = <&clks IMX6QDL_CLK_OCRAM>;
 		};
 
@@ -77,7 +83,6 @@
 };
 
 &fec {
-	/delete-property/interrupts-extended;
 	interrupts = <0 118 IRQ_TYPE_LEVEL_HIGH>,
 		     <0 119 IRQ_TYPE_LEVEL_HIGH>;
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6sl-evk.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6sl-evk.dts
@@ -584,10 +584,6 @@
 	vin-supply = <&sw2_reg>;
 };
 
-&reg_vdd3p0 {
-	vin-supply = <&sw2_reg>;
-};
-
 &reg_vdd2p5 {
 	vin-supply = <&sw2_reg>;
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6sl.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6sl.dtsi
@@ -39,6 +39,9 @@
 		spi1 = &ecspi2;
 		spi2 = &ecspi3;
 		spi3 = &ecspi4;
+		usb0 = &usbotg1;
+		usb1 = &usbotg2;
+		usb2 = &usbh;
 		usbphy0 = &usbphy1;
 		usbphy1 = &usbphy2;
 	};
@@ -121,6 +124,9 @@
 		ocram: sram@900000 {
 			compatible = "mmio-sram";
 			reg = <0x00900000 0x20000>;
+			ranges = <0 0x00900000 0x20000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
 			clocks = <&clks IMX6SL_CLK_OCRAM>;
 		};
 
@@ -133,7 +139,7 @@
 			interrupt-parent = <&intc>;
 		};
 
-		L2: l2-cache@a02000 {
+		L2: cache-controller@a02000 {
 			compatible = "arm,pl310-cache";
 			reg = <0x00a02000 0x1000>;
 			interrupts = <0 92 IRQ_TYPE_LEVEL_HIGH>;
@@ -380,7 +386,7 @@
 				clock-names = "ipg", "per";
 			};
 
-			gpt: gpt@2098000 {
+			gpt: timer@2098000 {
 				compatible = "fsl,imx6sl-gpt";
 				reg = <0x02098000 0x4000>;
 				interrupts = <0 55 IRQ_TYPE_LEVEL_HIGH>;
@@ -936,8 +942,10 @@
 			};
 
 			rngb: rngb@21b4000 {
+				compatible = "fsl,imx6sl-rngb", "fsl,imx25-rngb";
 				reg = <0x021b4000 0x4000>;
 				interrupts = <0 5 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX6SL_CLK_DUMMY>;
 			};
 
 			weim: weim@21b8000 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6sll-evk.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6sll-evk.dts
@@ -265,10 +265,6 @@
 	status = "okay";
 };
 
-&reg_3p0 {
-	vin-supply = <&sw2_reg>;
-};
-
 &snvs_poweroff {
 	status = "okay";
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6sll.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6sll.dtsi
@@ -36,6 +36,8 @@
 		spi1 = &ecspi2;
 		spi3 = &ecspi3;
 		spi4 = &ecspi4;
+		usb0 = &usbotg1;
+		usb1 = &usbotg2;
 		usbphy0 = &usbphy1;
 		usbphy1 = &usbphy2;
 	};
@@ -49,20 +51,18 @@
 			device_type = "cpu";
 			reg = <0>;
 			next-level-cache = <&L2>;
-			operating-points = <
+			operating-points =
 				/* kHz    uV */
-				996000  1275000
-				792000  1175000
-				396000  1075000
-				198000	975000
-			>;
-			fsl,soc-operating-points = <
+				<996000  1275000>,
+				<792000  1175000>,
+				<396000  1075000>,
+				<198000	  975000>;
+			fsl,soc-operating-points =
 				/* ARM kHz      SOC-PU uV */
-				996000          1175000
-				792000          1175000
-				396000          1175000
-				198000		1175000
-			>;
+				<996000         1175000>,
+				<792000         1175000>,
+				<396000         1175000>,
+				<198000		1175000>;
 			clock-latency = <61036>; /* two CLK32 periods */
 			#cooling-cells = <2>;
 			clocks = <&clks IMX6SLL_CLK_ARM>,
@@ -123,6 +123,9 @@
 		ocram: sram@900000 {
 			compatible = "mmio-sram";
 			reg = <0x00900000 0x20000>;
+			ranges = <0 0x00900000 0x20000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
 		};
 
 		intc: interrupt-controller@a01000 {
@@ -134,7 +137,7 @@
 			interrupt-parent = <&intc>;
 		};
 
-		L2: l2-cache@a02000 {
+		L2: cache-controller@a02000 {
 			compatible = "arm,pl310-cache";
 			reg = <0x00a02000 0x1000>;
 			interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
@@ -269,7 +272,7 @@
 					status = "disabled";
 				};
 
-				ssi1: ssi-controller@2028000 {
+				ssi1: ssi@2028000 {
 					compatible = "fsl,imx6sl-ssi", "fsl,imx51-ssi";
 					reg = <0x02028000 0x4000>;
 					interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
@@ -282,7 +285,7 @@
 					status = "disabled";
 				};
 
-				ssi2: ssi-controller@202c000 {
+				ssi2: ssi@202c000 {
 					compatible = "fsl,imx6sl-ssi", "fsl,imx51-ssi";
 					reg = <0x0202c000 0x4000>;
 					interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
@@ -295,7 +298,7 @@
 					status = "disabled";
 				};
 
-				ssi3: ssi-controller@2030000 {
+				ssi3: ssi@2030000 {
 					compatible = "fsl,imx6sl-ssi", "fsl,imx51-ssi";
 					reg = <0x02030000 0x4000>;
 					interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
@@ -547,7 +550,7 @@
 				reg = <0x020ca000 0x1000>;
 				interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks IMX6SLL_CLK_USBPHY2>;
-				phy-reg_3p0-supply = <&reg_3p0>;
+				phy-3p0-supply = <&reg_3p0>;
 				fsl,anatop = <&anatop>;
 			};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6sx-sabreauto.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6sx-sabreauto.dts
@@ -99,7 +99,7 @@
 &fec2 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_enet2>;
-	phy-mode = "rgmii";
+	phy-mode = "rgmii-id";
 	phy-handle = <&ethphy0>;
 	fsl,magic-packet;
 	status = "okay";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6sx-sdb-reva.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6sx-sdb-reva.dts
@@ -159,10 +159,6 @@
 	vin-supply = <&vgen6_reg>;
 };
 
-&reg_vdd3p0 {
-	vin-supply = <&sw2_reg>;
-};
-
 &reg_vdd2p5 {
 	vin-supply = <&vgen6_reg>;
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6sx-sdb.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6sx-sdb.dts
@@ -141,10 +141,6 @@
 	vin-supply = <&vgen6_reg>;
 };
 
-&reg_vdd3p0 {
-	vin-supply = <&sw2_reg>;
-};
-
 &reg_vdd2p5 {
 	vin-supply = <&vgen6_reg>;
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6sx-sdb.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6sx-sdb.dtsi
@@ -213,7 +213,7 @@
 &fec2 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_enet2>;
-	phy-mode = "rgmii";
+	phy-mode = "rgmii-id";
 	phy-handle = <&ethphy2>;
 	status = "okay";
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6sx.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6sx.dtsi
@@ -49,6 +49,9 @@
 		spi2 = &ecspi3;
 		spi3 = &ecspi4;
 		spi4 = &ecspi5;
+		usb0 = &usbotg1;
+		usb1 = &usbotg2;
+		usb2 = &usbh;
 		usbphy0 = &usbphy1;
 		usbphy1 = &usbphy2;
 	};
@@ -163,12 +166,18 @@
 		ocram_s: sram@8f8000 {
 			compatible = "mmio-sram";
 			reg = <0x008f8000 0x4000>;
+			ranges = <0 0x008f8000 0x4000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
 			clocks = <&clks IMX6SX_CLK_OCRAM_S>;
 		};
 
 		ocram: sram@900000 {
 			compatible = "mmio-sram";
 			reg = <0x00900000 0x20000>;
+			ranges = <0 0x00900000 0x20000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
 			clocks = <&clks IMX6SX_CLK_OCRAM>;
 		};
 
@@ -181,7 +190,7 @@
 			interrupt-parent = <&intc>;
 		};
 
-		L2: l2-cache@a02000 {
+		L2: cache-controller@a02000 {
 			compatible = "arm,pl310-cache";
 			reg = <0x00a02000 0x1000>;
 			interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
@@ -202,7 +211,7 @@
 			power-domains = <&pd_pu>;
 		};
 
-		dma_apbh: dma-apbh@1804000 {
+		dma_apbh: dma-controller@1804000 {
 			compatible = "fsl,imx6sx-dma-apbh", "fsl,imx28-dma-apbh";
 			reg = <0x01804000 0x2000>;
 			interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
@@ -466,7 +475,7 @@
 				status = "disabled";
 			};
 
-			gpt: gpt@2098000 {
+			gpt: timer@2098000 {
 				compatible = "fsl,imx6sx-gpt", "fsl,imx6dl-gpt";
 				reg = <0x02098000 0x4000>;
 				interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
@@ -949,6 +958,8 @@
 					 <&clks IMX6SX_CLK_USDHC1>;
 				clock-names = "ipg", "ahb", "per";
 				bus-width = <4>;
+				fsl,tuning-start-tap = <20>;
+				fsl,tuning-step= <2>;
 				status = "disabled";
 			};
 
@@ -961,6 +972,8 @@
 					 <&clks IMX6SX_CLK_USDHC2>;
 				clock-names = "ipg", "ahb", "per";
 				bus-width = <4>;
+				fsl,tuning-start-tap = <20>;
+				fsl,tuning-step= <2>;
 				status = "disabled";
 			};
 
@@ -973,6 +986,8 @@
 					 <&clks IMX6SX_CLK_USDHC3>;
 				clock-names = "ipg", "ahb", "per";
 				bus-width = <4>;
+				fsl,tuning-start-tap = <20>;
+				fsl,tuning-step= <2>;
 				status = "disabled";
 			};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6ul-14x14-evk.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6ul-14x14-evk.dtsi
@@ -215,7 +215,7 @@
 	flash0: n25q256a@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "micron,n25q256a";
+		compatible = "micron,n25q256a", "jedec,spi-nor";
 		spi-max-frequency = <29000000>;
 		spi-rx-bus-width = <4>;
 		spi-tx-bus-width = <4>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6ul-kontron-n6310-s.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6ul-kontron-n6310-s.dts
@@ -157,10 +157,6 @@
 	status = "okay";
 };
 
-&snvs_poweroff {
-	status = "okay";
-};
-
 &uart1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_uart1>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6ul.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6ul.dtsi
@@ -47,6 +47,8 @@
 		spi1 = &ecspi2;
 		spi2 = &ecspi3;
 		spi3 = &ecspi4;
+		usb0 = &usbotg1;
+		usb1 = &usbotg2;
 		usbphy0 = &usbphy1;
 		usbphy1 = &usbphy2;
 	};
@@ -62,20 +64,18 @@
 			clock-frequency = <696000000>;
 			clock-latency = <61036>; /* two CLK32 periods */
 			#cooling-cells = <2>;
-			operating-points = <
+			operating-points =
 				/* kHz	uV */
-				696000	1275000
-				528000	1175000
-				396000	1025000
-				198000	950000
-			>;
-			fsl,soc-operating-points = <
+				<696000	1275000>,
+				<528000	1175000>,
+				<396000	1025000>,
+				<198000	950000>;
+			fsl,soc-operating-points =
 				/* KHz	uV */
-				696000	1275000
-				528000	1175000
-				396000	1175000
-				198000	1175000
-			>;
+				<696000	1275000>,
+				<528000	1175000>,
+				<396000	1175000>,
+				<198000	1175000>;
 			clocks = <&clks IMX6UL_CLK_ARM>,
 				 <&clks IMX6UL_CLK_PLL2_BUS>,
 				 <&clks IMX6UL_CLK_PLL2_PFD2>,
@@ -157,6 +157,9 @@
 		ocram: sram@900000 {
 			compatible = "mmio-sram";
 			reg = <0x00900000 0x20000>;
+			ranges = <0 0x00900000 0x20000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
 		};
 
 		intc: interrupt-controller@a01000 {
@@ -171,7 +174,7 @@
 			      <0x00a06000 0x2000>;
 		};
 
-		dma_apbh: dma-apbh@1804000 {
+		dma_apbh: dma-controller@1804000 {
 			compatible = "fsl,imx6q-dma-apbh", "fsl,imx28-dma-apbh";
 			reg = <0x01804000 0x2000>;
 			interrupts = <0 13 IRQ_TYPE_LEVEL_HIGH>,
@@ -430,7 +433,7 @@
 				status = "disabled";
 			};
 
-			gpt1: gpt@2098000 {
+			gpt1: timer@2098000 {
 				compatible = "fsl,imx6ul-gpt", "fsl,imx6sx-gpt";
 				reg = <0x02098000 0x4000>;
 				interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
@@ -704,7 +707,7 @@
 				reg = <0x020e4000 0x4000>;
 			};
 
-			gpt2: gpt@20e8000 {
+			gpt2: timer@20e8000 {
 				compatible = "fsl,imx6ul-gpt", "fsl,imx6sx-gpt";
 				reg = <0x020e8000 0x4000>;
 				interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
@@ -966,7 +969,7 @@
 			};
 
 			csi: csi@21c4000 {
-				compatible = "fsl,imx6ul-csi", "fsl,imx7-csi";
+				compatible = "fsl,imx6ul-csi";
 				reg = <0x021c4000 0x4000>;
 				interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks IMX6UL_CLK_CSI>;
@@ -975,7 +978,7 @@
 			};
 
 			lcdif: lcdif@21c8000 {
-				compatible = "fsl,imx6ul-lcdif", "fsl,imx28-lcdif";
+				compatible = "fsl,imx6ul-lcdif", "fsl,imx6sx-lcdif";
 				reg = <0x021c8000 0x4000>;
 				interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks IMX6UL_CLK_LCDIF_PIX>,
@@ -996,7 +999,7 @@
 			qspi: spi@21e0000 {
 				#address-cells = <1>;
 				#size-cells = <0>;
-				compatible = "fsl,imx6ul-qspi", "fsl,imx6sx-qspi";
+				compatible = "fsl,imx6ul-qspi";
 				reg = <0x021e0000 0x4000>, <0x60000000 0x10000000>;
 				reg-names = "QuadSPI", "QuadSPI-memory";
 				interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6ull-colibri-wifi.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6ull-colibri-wifi.dtsi
@@ -43,6 +43,7 @@
 	assigned-clock-rates = <0>, <198000000>;
 	cap-power-off-card;
 	keep-power-in-suspend;
+	max-frequency = <25000000>;
 	mmc-pwrseq = <&wifi_pwrseq>;
 	no-1-8-v;
 	non-removable;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6ull-colibri.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6ull-colibri.dtsi
@@ -37,7 +37,7 @@
 
 	reg_sd1_vmmc: regulator-sd1-vmmc {
 		compatible = "regulator-gpio";
-		gpio = <&gpio5 9 GPIO_ACTIVE_HIGH>;
+		gpios = <&gpio5 9 GPIO_ACTIVE_HIGH>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&pinctrl_snvs_reg_sd>;
 		regulator-always-on;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx6ull-pinfunc.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx6ull-pinfunc.h
@@ -82,6 +82,6 @@
 #define MX6ULL_PAD_CSI_DATA04__ESAI_TX_FS                         0x01F4 0x0480 0x0000 0x9 0x0
 #define MX6ULL_PAD_CSI_DATA05__ESAI_TX_CLK                        0x01F8 0x0484 0x0000 0x9 0x0
 #define MX6ULL_PAD_CSI_DATA06__ESAI_TX5_RX0                       0x01FC 0x0488 0x0000 0x9 0x0
-#define MX6ULL_PAD_CSI_DATA07__ESAI_T0                            0x0200 0x048C 0x0000 0x9 0x0
+#define MX6ULL_PAD_CSI_DATA07__ESAI_TX0                           0x0200 0x048C 0x0000 0x9 0x0
 
 #endif /* __DTS_IMX6ULL_PINFUNC_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx7-colibri.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx7-colibri.dtsi
@@ -77,7 +77,7 @@
 
 		dailink_master: simple-audio-card,codec {
 			sound-dai = <&codec>;
-			clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_CLK>;
+			clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_DIV>;
 		};
 	};
 };
@@ -152,7 +152,7 @@
 		compatible = "fsl,sgtl5000";
 		#sound-dai-cells = <0>;
 		reg = <0x0a>;
-		clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_CLK>;
+		clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_DIV>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&pinctrl_sai1_mclk>;
 		VDDA-supply = <&reg_module_3v3_avdd>;
@@ -337,7 +337,6 @@
 	assigned-clock-rates = <400000000>;
 	bus-width = <8>;
 	fsl,tuning-step = <2>;
-	max-frequency = <100000000>;
 	vmmc-supply = <&reg_module_3v3>;
 	vqmmc-supply = <&reg_DCDC3>;
 	non-removable;
@@ -347,7 +346,7 @@
 &iomuxc {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_gpio1 &pinctrl_gpio2 &pinctrl_gpio3 &pinctrl_gpio4
-		     &pinctrl_gpio7>;
+		     &pinctrl_gpio7 &pinctrl_usbc_det>;
 
 	pinctrl_gpio1: gpio1-grp {
 		fsl,pins = <
@@ -452,7 +451,6 @@
 
 	pinctrl_enet1: enet1grp {
 		fsl,pins = <
-			MX7D_PAD_ENET1_CRS__GPIO7_IO14			0x14
 			MX7D_PAD_ENET1_RGMII_RX_CTL__ENET1_RGMII_RX_CTL	0x73
 			MX7D_PAD_ENET1_RGMII_RD0__ENET1_RGMII_RD0	0x73
 			MX7D_PAD_ENET1_RGMII_RD1__ENET1_RGMII_RD1	0x73
@@ -650,6 +648,12 @@
 		>;
 	};
 
+	pinctrl_usbc_det: gpio-usbc-det {
+		fsl,pins = <
+			MX7D_PAD_ENET1_CRS__GPIO7_IO14	0x14
+		>;
+	};
+
 	pinctrl_usbh_reg: gpio-usbh-vbus {
 		fsl,pins = <
 			MX7D_PAD_UART3_CTS_B__GPIO4_IO7	0x14 /* SODIMM 129 USBH PEN */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx7-mba7.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx7-mba7.dtsi
@@ -250,7 +250,7 @@
 	tlv320aic32x4: audio-codec@18 {
 		compatible = "ti,tlv320aic32x4";
 		reg = <0x18>;
-		clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_CLK>;
+		clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_DIV>;
 		clock-names = "mclk";
 		ldoin-supply = <&reg_audio_3v3>;
 		iov-supply = <&reg_audio_3v3>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx7d-meerkat96.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx7d-meerkat96.dts
@@ -193,7 +193,7 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_usdhc1>;
 	keep-power-in-suspend;
-	tuning-step = <2>;
+	fsl,tuning-step = <2>;
 	vmmc-supply = <&reg_3p3v>;
 	no-1-8-v;
 	broken-cd;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx7d-nitrogen7.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx7d-nitrogen7.dts
@@ -284,7 +284,7 @@
 	codec: wm8960@1a {
 		compatible = "wlf,wm8960";
 		reg = <0x1a>;
-		clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_CLK>;
+		clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_DIV>;
 		clock-names = "mclk";
 		wlf,shared-lrclk;
 	};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx7d-pico-hobbit.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx7d-pico-hobbit.dts
@@ -31,7 +31,7 @@
 
 		dailink_master: simple-audio-card,codec {
 			sound-dai = <&sgtl5000>;
-			clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_CLK>;
+			clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_DIV>;
 		};
 	};
 };
@@ -41,7 +41,7 @@
 		#sound-dai-cells = <0>;
 		reg = <0x0a>;
 		compatible = "fsl,sgtl5000";
-		clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_CLK>;
+		clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_DIV>;
 		VDDA-supply = <&reg_2p5v>;
 		VDDIO-supply = <&reg_vref_1v8>;
 	};
@@ -64,7 +64,7 @@
 		interrupt-parent = <&gpio2>;
 		interrupts = <7 0>;
 		spi-max-frequency = <1000000>;
-		pendown-gpio = <&gpio2 7 0>;
+		pendown-gpio = <&gpio2 7 GPIO_ACTIVE_LOW>;
 		vcc-supply = <&reg_3p3v>;
 		ti,x-min = /bits/ 16 <0>;
 		ti,x-max = /bits/ 16 <4095>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx7d-pico-pi.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx7d-pico-pi.dts
@@ -31,7 +31,7 @@
 
 		dailink_master: simple-audio-card,codec {
 			sound-dai = <&sgtl5000>;
-			clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_CLK>;
+			clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_DIV>;
 		};
 	};
 };
@@ -41,7 +41,7 @@
 		#sound-dai-cells = <0>;
 		reg = <0x0a>;
 		compatible = "fsl,sgtl5000";
-		clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_CLK>;
+		clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_DIV>;
 		VDDA-supply = <&reg_2p5v>;
 		VDDIO-supply = <&reg_vref_1v8>;
 	};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx7d-pico.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx7d-pico.dtsi
@@ -307,7 +307,7 @@
 	pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
 	cd-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
 	bus-width = <4>;
-	tuning-step = <2>;
+	fsl,tuning-step = <2>;
 	vmmc-supply = <&reg_3p3v>;
 	wakeup-source;
 	no-1-8-v;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx7d-sdb.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx7d-sdb.dts
@@ -176,13 +176,8 @@
 		pinctrl-0 = <&pinctrl_tsc2046_pendown>;
 		interrupt-parent = <&gpio2>;
 		interrupts = <29 0>;
-		pendown-gpio = <&gpio2 29 GPIO_ACTIVE_HIGH>;
-		ti,x-min = /bits/ 16 <0>;
-		ti,x-max = /bits/ 16 <0>;
-		ti,y-min = /bits/ 16 <0>;
-		ti,y-max = /bits/ 16 <0>;
-		ti,pressure-max = /bits/ 16 <0>;
-		ti,x-plate-ohms = /bits/ 16 <400>;
+		pendown-gpio = <&gpio2 29 GPIO_ACTIVE_LOW>;
+		touchscreen-max-pressure = <255>;
 		wakeup-source;
 	};
 };
@@ -356,7 +351,7 @@
 	codec: wm8960@1a {
 		compatible = "wlf,wm8960";
 		reg = <0x1a>;
-		clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_CLK>;
+		clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_DIV>;
 		clock-names = "mclk";
 		wlf,shared-lrclk;
 	};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx7d-zii-rmu2.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx7d-zii-rmu2.dts
@@ -350,7 +350,7 @@
 
 &iomuxc_lpsr {
 	pinctrl_enet1_phy_interrupt: enet1phyinterruptgrp {
-		fsl,phy = <
+		fsl,pins = <
 			MX7D_PAD_LPSR_GPIO1_IO02__GPIO1_IO2	0x08
 		>;
 	};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx7d.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx7d.dtsi
@@ -7,6 +7,12 @@
 #include <dt-bindings/reset/imx7-reset.h>
 
 / {
+	aliases {
+		usb0 = &usbotg1;
+		usb1 = &usbotg2;
+		usb2 = &usbh;
+	};
+
 	cpus {
 		cpu0: cpu@0 {
 			clock-frequency = <996000000>;
@@ -198,9 +204,6 @@
 };
 
 &ca_funnel_in_ports {
-	#address-cells = <1>;
-	#size-cells = <0>;
-
 	port@1 {
 		reg = <1>;
 		ca_funnel_in_port1: endpoint {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx7s-colibri.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx7s-colibri.dtsi
@@ -49,3 +49,7 @@
 		reg = <0x80000000 0x10000000>;
 	};
 };
+
+&gpmi {
+	status = "okay";
+};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx7s-warp.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx7s-warp.dts
@@ -75,7 +75,7 @@
 
 		dailink_master: simple-audio-card,codec {
 			sound-dai = <&codec>;
-			clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_CLK>;
+			clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_DIV>;
 		};
 	};
 };
@@ -232,7 +232,7 @@
 		#sound-dai-cells = <0>;
 		reg = <0x0a>;
 		compatible = "fsl,sgtl5000";
-		clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_CLK>;
+		clocks = <&clks IMX7D_AUDIO_MCLK_ROOT_DIV>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&pinctrl_sai1_mclk>;
 		VDDA-supply = <&vgen4_reg>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx7s.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx7s.dtsi
@@ -47,6 +47,8 @@
 		spi1 = &ecspi2;
 		spi2 = &ecspi3;
 		spi3 = &ecspi4;
+		usb0 = &usbotg1;
+		usb1 = &usbh;
 	};
 
 	cpus {
@@ -181,7 +183,11 @@
 			clock-names = "apb_pclk";
 
 			ca_funnel_in_ports: in-ports {
-				port {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
 					ca_funnel_in_port0: endpoint {
 						remote-endpoint = <&etm0_out_port>;
 					};
@@ -444,8 +450,8 @@
 				fsl,input-sel = <&iomuxc>;
 			};
 
-			gpt1: gpt@302d0000 {
-				compatible = "fsl,imx7d-gpt", "fsl,imx6sx-gpt";
+			gpt1: timer@302d0000 {
+				compatible = "fsl,imx7d-gpt", "fsl,imx6dl-gpt";
 				reg = <0x302d0000 0x10000>;
 				interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks IMX7D_GPT1_ROOT_CLK>,
@@ -453,8 +459,8 @@
 				clock-names = "ipg", "per";
 			};
 
-			gpt2: gpt@302e0000 {
-				compatible = "fsl,imx7d-gpt", "fsl,imx6sx-gpt";
+			gpt2: timer@302e0000 {
+				compatible = "fsl,imx7d-gpt", "fsl,imx6dl-gpt";
 				reg = <0x302e0000 0x10000>;
 				interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks IMX7D_GPT2_ROOT_CLK>,
@@ -463,8 +469,8 @@
 				status = "disabled";
 			};
 
-			gpt3: gpt@302f0000 {
-				compatible = "fsl,imx7d-gpt", "fsl,imx6sx-gpt";
+			gpt3: timer@302f0000 {
+				compatible = "fsl,imx7d-gpt", "fsl,imx6dl-gpt";
 				reg = <0x302f0000 0x10000>;
 				interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks IMX7D_GPT3_ROOT_CLK>,
@@ -473,8 +479,8 @@
 				status = "disabled";
 			};
 
-			gpt4: gpt@30300000 {
-				compatible = "fsl,imx7d-gpt", "fsl,imx6sx-gpt";
+			gpt4: timer@30300000 {
+				compatible = "fsl,imx7d-gpt", "fsl,imx6dl-gpt";
 				reg = <0x30300000 0x10000>;
 				interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks IMX7D_GPT4_ROOT_CLK>,
@@ -504,7 +510,7 @@
 
 				mux: mux-controller {
 					compatible = "mmio-mux";
-					#mux-control-cells = <0>;
+					#mux-control-cells = <1>;
 					mux-reg-masks = <0x14 0x00000010>;
 				};
 
@@ -763,7 +769,7 @@
 			};
 
 			lcdif: lcdif@30730000 {
-				compatible = "fsl,imx7d-lcdif", "fsl,imx28-lcdif";
+				compatible = "fsl,imx7d-lcdif", "fsl,imx6sx-lcdif";
 				reg = <0x30730000 0x10000>;
 				interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clks IMX7D_LCDIF_PIXEL_ROOT_CLK>,
@@ -1131,6 +1137,8 @@
 					<&clks IMX7D_USDHC1_ROOT_CLK>;
 				clock-names = "ipg", "ahb", "per";
 				bus-width = <4>;
+				fsl,tuning-step = <2>;
+				fsl,tuning-start-tap = <20>;
 				status = "disabled";
 			};
 
@@ -1143,6 +1151,8 @@
 					<&clks IMX7D_USDHC2_ROOT_CLK>;
 				clock-names = "ipg", "ahb", "per";
 				bus-width = <4>;
+				fsl,tuning-step = <2>;
+				fsl,tuning-start-tap = <20>;
 				status = "disabled";
 			};
 
@@ -1155,6 +1165,8 @@
 					<&clks IMX7D_USDHC3_ROOT_CLK>;
 				clock-names = "ipg", "ahb", "per";
 				bus-width = <4>;
+				fsl,tuning-step = <2>;
+				fsl,tuning-start-tap = <20>;
 				status = "disabled";
 			};
 
@@ -1190,14 +1202,13 @@
 			};
 		};
 
-		dma_apbh: dma-apbh@33000000 {
+		dma_apbh: dma-controller@33000000 {
 			compatible = "fsl,imx7d-dma-apbh", "fsl,imx28-dma-apbh";
 			reg = <0x33000000 0x2000>;
 			interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
-			interrupt-names = "gpmi0", "gpmi1", "gpmi2", "gpmi3";
 			#dma-cells = <1>;
 			dma-channels = <4>;
 			clocks = <&clks IMX7D_NAND_USDHC_BUS_RAWNAND_CLK>;
@@ -1206,7 +1217,7 @@
 		gpmi: gpmi-nand@33002000{
 			compatible = "fsl,imx7d-gpmi-nand";
 			#address-cells = <1>;
-			#size-cells = <1>;
+			#size-cells = <0>;
 			reg = <0x33002000 0x2000>, <0x33004000 0x4000>;
 			reg-names = "gpmi-nand", "bch";
 			interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/imx7ulp.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/imx7ulp.dtsi
@@ -37,10 +37,10 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		cpu0: cpu@0 {
+		cpu0: cpu@f00 {
 			compatible = "arm,cortex-a7";
 			device_type = "cpu";
-			reg = <0>;
+			reg = <0xf00>;
 		};
 	};
 
@@ -397,7 +397,7 @@
 			clocks = <&pcc2 IMX7ULP_CLK_RGPIO2P1>,
 				 <&pcc3 IMX7ULP_CLK_PCTLC>;
 			clock-names = "gpio", "port";
-			gpio-ranges = <&iomuxc1 0 0 32>;
+			gpio-ranges = <&iomuxc1 0 0 20>;
 		};
 
 		gpio_ptd: gpio@40af0000 {
@@ -411,7 +411,7 @@
 			clocks = <&pcc2 IMX7ULP_CLK_RGPIO2P1>,
 				 <&pcc3 IMX7ULP_CLK_PCTLD>;
 			clock-names = "gpio", "port";
-			gpio-ranges = <&iomuxc1 0 32 32>;
+			gpio-ranges = <&iomuxc1 0 32 12>;
 		};
 
 		gpio_pte: gpio@40b00000 {
@@ -425,7 +425,7 @@
 			clocks = <&pcc2 IMX7ULP_CLK_RGPIO2P1>,
 				 <&pcc3 IMX7ULP_CLK_PCTLE>;
 			clock-names = "gpio", "port";
-			gpio-ranges = <&iomuxc1 0 64 32>;
+			gpio-ranges = <&iomuxc1 0 64 16>;
 		};
 
 		gpio_ptf: gpio@40b10000 {
@@ -439,7 +439,7 @@
 			clocks = <&pcc2 IMX7ULP_CLK_RGPIO2P1>,
 				 <&pcc3 IMX7ULP_CLK_PCTLF>;
 			clock-names = "gpio", "port";
-			gpio-ranges = <&iomuxc1 0 96 32>;
+			gpio-ranges = <&iomuxc1 0 96 20>;
 		};
 	};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/integratorap.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/integratorap.dts
@@ -155,6 +155,7 @@
 
 	pci: pciv3@62000000 {
 		compatible = "arm,integrator-ap-pci", "v3,v360epc-pci";
+		device_type = "pci";
 		#interrupt-cells = <1>;
 		#size-cells = <2>;
 		#address-cells = <3>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/kirkwood-lsxl.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/kirkwood-lsxl.dtsi
@@ -10,6 +10,11 @@
 
 	ocp@f1000000 {
 		pinctrl: pin-controller@10000 {
+			/* Non-default UART pins */
+			pmx_uart0: pmx-uart0 {
+				marvell,pins = "mpp4", "mpp5";
+			};
+
 			pmx_power_hdd: pmx-power-hdd {
 				marvell,pins = "mpp10";
 				marvell,function = "gpo";
@@ -213,22 +218,11 @@
 &mdio {
 	status = "okay";
 
-	ethphy0: ethernet-phy@0 {
-		reg = <0>;
-	};
-
 	ethphy1: ethernet-phy@8 {
 		reg = <8>;
 	};
 };
 
-&eth0 {
-	status = "okay";
-	ethernet0-port@0 {
-		phy-handle = <&ethphy0>;
-	};
-};
-
 &eth1 {
 	status = "okay";
 	ethernet1-port@0 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/logicpd-som-lv-35xx-devkit.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/logicpd-som-lv-35xx-devkit.dts
@@ -11,3 +11,18 @@
 	model = "LogicPD Zoom OMAP35xx SOM-LV Development Kit";
 	compatible = "logicpd,dm3730-som-lv-devkit", "ti,omap3";
 };
+
+&omap3_pmx_core2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&hsusb2_2_pins>;
+	hsusb2_2_pins: pinmux_hsusb2_2_pins {
+		pinctrl-single,pins = <
+			OMAP3430_CORE2_IOPAD(0x25f0, PIN_OUTPUT | MUX_MODE3)            /* etk_d10.hsusb2_clk */
+			OMAP3430_CORE2_IOPAD(0x25f2, PIN_OUTPUT | MUX_MODE3)            /* etk_d11.hsusb2_stp */
+			OMAP3430_CORE2_IOPAD(0x25f4, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d12.hsusb2_dir */
+			OMAP3430_CORE2_IOPAD(0x25f6, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d13.hsusb2_nxt */
+			OMAP3430_CORE2_IOPAD(0x25f8, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d14.hsusb2_data0 */
+			OMAP3430_CORE2_IOPAD(0x25fa, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d15.hsusb2_data1 */
+		>;
+	};
+};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/logicpd-som-lv-37xx-devkit.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/logicpd-som-lv-37xx-devkit.dts
@@ -11,3 +11,18 @@
 	model = "LogicPD Zoom DM3730 SOM-LV Development Kit";
 	compatible = "logicpd,dm3730-som-lv-devkit", "ti,omap3630", "ti,omap3";
 };
+
+&omap3_pmx_core2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&hsusb2_2_pins>;
+	hsusb2_2_pins: pinmux_hsusb2_2_pins {
+		pinctrl-single,pins = <
+			OMAP3630_CORE2_IOPAD(0x25f0, PIN_OUTPUT | MUX_MODE3)            /* etk_d10.hsusb2_clk */
+			OMAP3630_CORE2_IOPAD(0x25f2, PIN_OUTPUT | MUX_MODE3)            /* etk_d11.hsusb2_stp */
+			OMAP3630_CORE2_IOPAD(0x25f4, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d12.hsusb2_dir */
+			OMAP3630_CORE2_IOPAD(0x25f6, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d13.hsusb2_nxt */
+			OMAP3630_CORE2_IOPAD(0x25f8, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d14.hsusb2_data0 */
+			OMAP3630_CORE2_IOPAD(0x25fa, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d15.hsusb2_data1 */
+		>;
+	};
+};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/logicpd-som-lv-baseboard.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/logicpd-som-lv-baseboard.dtsi
@@ -51,6 +51,8 @@
 
 &mcbsp2 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcbsp2_pins>;
 };
 
 &charger {
@@ -102,35 +104,18 @@
 		regulator-max-microvolt = <3300000>;
 	};
 
-	lcd0: display@0 {
-		compatible = "panel-dpi";
-		label = "28";
-		status = "okay";
-		/* default-on; */
+	lcd0: display {
+		/* This isn't the exact LCD, but the timings meet spec */
+		compatible = "logicpd,type28";
 		pinctrl-names = "default";
 		pinctrl-0 = <&lcd_enable_pin>;
-		enable-gpios = <&gpio5 27 GPIO_ACTIVE_HIGH>;	/* gpio155, lcd INI */
+		backlight = <&bl>;
+		enable-gpios = <&gpio5 27 GPIO_ACTIVE_HIGH>;
 		port {
 			lcd_in: endpoint {
 				remote-endpoint = <&dpi_out>;
 			};
 		};
-
-		panel-timing {
-			clock-frequency = <9000000>;
-			hactive = <480>;
-			vactive = <272>;
-			hfront-porch = <3>;
-			hback-porch = <2>;
-			hsync-len = <42>;
-			vback-porch = <3>;
-			vfront-porch = <2>;
-			vsync-len = <11>;
-			hsync-active = <1>;
-			vsync-active = <1>;
-			de-active = <1>;
-			pixelclk-active = <0>;
-		};
 	};
 
 	bl: backlight {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/logicpd-som-lv.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/logicpd-som-lv.dtsi
@@ -265,21 +265,6 @@
 	};
 };
 
-&omap3_pmx_core2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&hsusb2_2_pins>;
-	hsusb2_2_pins: pinmux_hsusb2_2_pins {
-		pinctrl-single,pins = <
-			OMAP3630_CORE2_IOPAD(0x25f0, PIN_OUTPUT | MUX_MODE3)            /* etk_d10.hsusb2_clk */
-			OMAP3630_CORE2_IOPAD(0x25f2, PIN_OUTPUT | MUX_MODE3)            /* etk_d11.hsusb2_stp */
-			OMAP3630_CORE2_IOPAD(0x25f4, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d12.hsusb2_dir */
-			OMAP3630_CORE2_IOPAD(0x25f6, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d13.hsusb2_nxt */
-			OMAP3630_CORE2_IOPAD(0x25f8, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d14.hsusb2_data0 */
-			OMAP3630_CORE2_IOPAD(0x25fa, PIN_INPUT_PULLDOWN | MUX_MODE3)    /* etk_d15.hsusb2_data1 */
-		>;
-	};
-};
-
 &uart2 {
 	interrupts-extended = <&intc 73 &omap3_pmx_core OMAP3_UART2_RX>;
 	pinctrl-names = "default";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/logicpd-torpedo-37xx-devkit-28.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/logicpd-torpedo-37xx-devkit-28.dts
@@ -11,22 +11,6 @@
 #include "logicpd-torpedo-37xx-devkit.dts"
 
 &lcd0 {
-
-	label = "28";
-
-	panel-timing {
-		clock-frequency = <9000000>;
-		hactive = <480>;
-		vactive = <272>;
-		hfront-porch = <3>;
-		hback-porch = <2>;
-		hsync-len = <42>;
-		vback-porch = <3>;
-		vfront-porch = <2>;
-		vsync-len = <11>;
-		hsync-active = <1>;
-		vsync-active = <1>;
-		de-active = <1>;
-		pixelclk-active = <0>;
-	};
+	/* To make it work, set CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=4 */
+	compatible = "logicpd,type28";
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/logicpd-torpedo-baseboard.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/logicpd-torpedo-baseboard.dtsi
@@ -80,6 +80,8 @@
 };
 
 &mcbsp2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcbsp2_pins>;
 	status = "okay";
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/lpc32xx.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/lpc32xx.dtsi
@@ -329,9 +329,6 @@
 
 					clocks = <&xtal_32k>, <&xtal>;
 					clock-names = "xtal_32k", "xtal";
-
-					assigned-clocks = <&clk LPC32XX_CLK_HCLK_PLL>;
-					assigned-clock-rates = <208000000>;
 				};
 			};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/ls1021a-tsn.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/ls1021a-tsn.dts
@@ -247,7 +247,7 @@
 
 	flash@0 {
 		/* Rev. A uses 64MB flash, Rev. B & C use 32MB flash */
-		compatible = "jedec,spi-nor", "s25fl256s1", "s25fl512s";
+		compatible = "jedec,spi-nor";
 		spi-max-frequency = <20000000>;
 		#address-cells = <1>;
 		#size-cells = <1>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/ls1021a.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/ls1021a.dtsi
@@ -181,7 +181,7 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <0x0 0x1550000 0x0 0x10000>,
-			      <0x0 0x40000000 0x0 0x40000000>;
+			      <0x0 0x40000000 0x0 0x20000000>;
 			reg-names = "QuadSPI", "QuadSPI-memory";
 			interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
 			clock-names = "qspi_en", "qspi";
@@ -311,39 +311,6 @@
 			#thermal-sensor-cells = <1>;
 		};
 
-		thermal-zones {
-			cpu_thermal: cpu-thermal {
-				polling-delay-passive = <1000>;
-				polling-delay = <5000>;
-
-				thermal-sensors = <&tmu 0>;
-
-				trips {
-					cpu_alert: cpu-alert {
-						temperature = <85000>;
-						hysteresis = <2000>;
-						type = "passive";
-					};
-					cpu_crit: cpu-crit {
-						temperature = <95000>;
-						hysteresis = <2000>;
-						type = "critical";
-					};
-				};
-
-				cooling-maps {
-					map0 {
-						trip = <&cpu_alert>;
-						cooling-device =
-							<&cpu0 THERMAL_NO_LIMIT
-							THERMAL_NO_LIMIT>,
-							<&cpu1 THERMAL_NO_LIMIT
-							THERMAL_NO_LIMIT>;
-					};
-				};
-			};
-		};
-
 		dspi0: spi@2100000 {
 			compatible = "fsl,ls1021a-v1.0-dspi";
 			#address-cells = <1>;
@@ -728,7 +695,7 @@
 		};
 
 		mdio0: mdio@2d24000 {
-			compatible = "fsl,etsec2-mdio";
+			compatible = "gianfar";
 			device_type = "mdio";
 			#address-cells = <1>;
 			#size-cells = <0>;
@@ -737,7 +704,7 @@
 		};
 
 		mdio1: mdio@2d64000 {
-			compatible = "fsl,etsec2-mdio";
+			compatible = "gianfar";
 			device_type = "mdio";
 			#address-cells = <1>;
 			#size-cells = <0>;
@@ -753,7 +720,7 @@
 			fsl,tmr-prsc    = <2>;
 			fsl,tmr-add     = <0xaaaaaaab>;
 			fsl,tmr-fiper1  = <999999995>;
-			fsl,tmr-fiper2  = <99990>;
+			fsl,tmr-fiper2  = <999999995>;
 			fsl,max-adj     = <499999999>;
 			fsl,extts-fifo;
 		};
@@ -984,4 +951,37 @@
 		};
 
 	};
+
+	thermal-zones {
+		cpu_thermal: cpu-thermal {
+			polling-delay-passive = <1000>;
+			polling-delay = <5000>;
+
+			thermal-sensors = <&tmu 0>;
+
+			trips {
+				cpu_alert: cpu-alert {
+					temperature = <85000>;
+					hysteresis = <2000>;
+					type = "passive";
+				};
+				cpu_crit: cpu-crit {
+					temperature = <95000>;
+					hysteresis = <2000>;
+					type = "critical";
+				};
+			};
+
+			cooling-maps {
+				map0 {
+					trip = <&cpu_alert>;
+					cooling-device =
+						<&cpu0 THERMAL_NO_LIMIT
+						THERMAL_NO_LIMIT>,
+						<&cpu1 THERMAL_NO_LIMIT
+						THERMAL_NO_LIMIT>;
+				};
+			};
+		};
+	};
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/meson.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/meson.dtsi
@@ -49,14 +49,14 @@
 			};
 
 			uart_A: serial@84c0 {
-				compatible = "amlogic,meson6-uart", "amlogic,meson-uart";
+				compatible = "amlogic,meson6-uart";
 				reg = <0x84c0 0x18>;
 				interrupts = <GIC_SPI 26 IRQ_TYPE_EDGE_RISING>;
 				status = "disabled";
 			};
 
 			uart_B: serial@84dc {
-				compatible = "amlogic,meson6-uart", "amlogic,meson-uart";
+				compatible = "amlogic,meson6-uart";
 				reg = <0x84dc 0x18>;
 				interrupts = <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>;
 				status = "disabled";
@@ -94,7 +94,7 @@
 			};
 
 			uart_C: serial@8700 {
-				compatible = "amlogic,meson6-uart", "amlogic,meson-uart";
+				compatible = "amlogic,meson6-uart";
 				reg = <0x8700 0x18>;
 				interrupts = <GIC_SPI 93 IRQ_TYPE_EDGE_RISING>;
 				status = "disabled";
@@ -196,7 +196,7 @@
 			};
 
 			uart_AO: serial@4c0 {
-				compatible = "amlogic,meson6-uart", "amlogic,meson-ao-uart", "amlogic,meson-uart";
+				compatible = "amlogic,meson6-uart", "amlogic,meson-ao-uart";
 				reg = <0x4c0 0x18>;
 				interrupts = <GIC_SPI 90 IRQ_TYPE_EDGE_RISING>;
 				status = "disabled";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/meson8.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/meson8.dtsi
@@ -129,8 +129,8 @@
 	gpu_opp_table: gpu-opp-table {
 		compatible = "operating-points-v2";
 
-		opp-182150000 {
-			opp-hz = /bits/ 64 <182150000>;
+		opp-182142857 {
+			opp-hz = /bits/ 64 <182142857>;
 			opp-microvolt = <1150000>;
 		};
 		opp-318750000 {
@@ -230,8 +230,6 @@
 				     <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 171 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>,
@@ -243,8 +241,13 @@
 					  "pp2", "ppmmu2", "pp4", "ppmmu4",
 					  "pp5", "ppmmu5", "pp6", "ppmmu6";
 			resets = <&reset RESET_MALI>;
+
 			clocks = <&clkc CLKID_CLK81>, <&clkc CLKID_MALI>;
 			clock-names = "bus", "core";
+
+			assigned-clocks = <&clkc CLKID_MALI>;
+			assigned-clock-rates = <318750000>;
+
 			operating-points-v2 = <&gpu_opp_table>;
 		};
 	};
@@ -253,7 +256,7 @@
 &aobus {
 	pmu: pmu@e0 {
 		compatible = "amlogic,meson8-pmu", "syscon";
-		reg = <0xe0 0x8>;
+		reg = <0xe0 0x18>;
 	};
 
 	pinctrl_aobus: pinctrl@84 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/meson8b-ec100.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/meson8b-ec100.dts
@@ -148,7 +148,7 @@
 		regulator-min-microvolt = <860000>;
 		regulator-max-microvolt = <1140000>;
 
-		vin-supply = <&vcc_5v>;
+		pwm-supply = <&vcc_5v>;
 
 		pwms = <&pwm_cd 0 1148 0>;
 		pwm-dutycycle-range = <100 0>;
@@ -232,7 +232,7 @@
 		regulator-min-microvolt = <860000>;
 		regulator-max-microvolt = <1140000>;
 
-		vin-supply = <&vcc_5v>;
+		pwm-supply = <&vcc_5v>;
 
 		pwms = <&pwm_cd 1 1148 0>;
 		pwm-dutycycle-range = <100 0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/meson8b-mxq.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/meson8b-mxq.dts
@@ -39,6 +39,8 @@
 		regulator-min-microvolt = <860000>;
 		regulator-max-microvolt = <1140000>;
 
+		pwm-supply = <&vcc_5v>;
+
 		pwms = <&pwm_cd 0 1148 0>;
 		pwm-dutycycle-range = <100 0>;
 
@@ -84,7 +86,7 @@
 		regulator-min-microvolt = <860000>;
 		regulator-max-microvolt = <1140000>;
 
-		vin-supply = <&vcc_5v>;
+		pwm-supply = <&vcc_5v>;
 
 		pwms = <&pwm_cd 1 1148 0>;
 		pwm-dutycycle-range = <100 0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/meson8b-odroidc1.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/meson8b-odroidc1.dts
@@ -130,7 +130,7 @@
 		regulator-min-microvolt = <860000>;
 		regulator-max-microvolt = <1140000>;
 
-		vin-supply = <&p5v0>;
+		pwm-supply = <&p5v0>;
 
 		pwms = <&pwm_cd 0 12218 0>;
 		pwm-dutycycle-range = <91 0>;
@@ -162,7 +162,7 @@
 		regulator-min-microvolt = <860000>;
 		regulator-max-microvolt = <1140000>;
 
-		vin-supply = <&p5v0>;
+		pwm-supply = <&p5v0>;
 
 		pwms = <&pwm_cd 1 12218 0>;
 		pwm-dutycycle-range = <91 0>;
@@ -219,7 +219,7 @@
 			reg = <0>;
 
 			reset-assert-us = <10000>;
-			reset-deassert-us = <30000>;
+			reset-deassert-us = <80000>;
 			reset-gpios = <&gpio GPIOH_4 GPIO_ACTIVE_LOW>;
 
 			interrupt-parent = <&gpio_intc>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/meson8b.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/meson8b.dtsi
@@ -125,8 +125,8 @@
 			opp-hz = /bits/ 64 <255000000>;
 			opp-microvolt = <1100000>;
 		};
-		opp-364300000 {
-			opp-hz = /bits/ 64 <364300000>;
+		opp-364285714 {
+			opp-hz = /bits/ 64 <364285714>;
 			opp-microvolt = <1100000>;
 		};
 		opp-425000000 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/meson8m2-mxiii-plus.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/meson8m2-mxiii-plus.dts
@@ -83,7 +83,7 @@
 			reg = <0>;
 
 			reset-assert-us = <10000>;
-			reset-deassert-us = <30000>;
+			reset-deassert-us = <80000>;
 			reset-gpios = <&gpio GPIOH_4 GPIO_ACTIVE_LOW>;
 		};
 	};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/mmp2-brownstone.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/mmp2-brownstone.dts
@@ -19,176 +19,174 @@
 		device_type = "memory";
 		reg = <0x00000000 0x08000000>;
 	};
+};
+
+&uart3 {
+	status = "okay";
+};
 
-	soc {
-		apb@d4000000 {
-			uart3: uart@d4018000 {
-				status = "okay";
-			};
-			twsi1: i2c@d4011000 {
-				status = "okay";
-				pmic: max8925@3c {
-					compatible = "maxium,max8925";
-					reg = <0x3c>;
-					interrupts = <1>;
-					interrupt-parent = <&intcmux4>;
-					interrupt-controller;
-					#interrupt-cells = <1>;
-					maxim,tsc-irq = <0>;
+&twsi1 {
+	status = "okay";
+	pmic: max8925@3c {
+		compatible = "maxim,max8925";
+		reg = <0x3c>;
+		interrupts = <1>;
+		interrupt-parent = <&intcmux4>;
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		maxim,tsc-irq = <0>;
 
-					regulators {
-						SDV1 {
-							regulator-min-microvolt = <637500>;
-							regulator-max-microvolt = <1425000>;
-							regulator-boot-on;
-							regulator-always-on;
-						};
-						SDV2 {
-							regulator-min-microvolt = <650000>;
-							regulator-max-microvolt = <2225000>;
-							regulator-boot-on;
-							regulator-always-on;
-						};
-						SDV3 {
-							regulator-min-microvolt = <750000>;
-							regulator-max-microvolt = <3900000>;
-							regulator-boot-on;
-							regulator-always-on;
-						};
-						LDO1 {
-							regulator-min-microvolt = <750000>;
-							regulator-max-microvolt = <3900000>;
-							regulator-boot-on;
-							regulator-always-on;
-						};
-						LDO2 {
-							regulator-min-microvolt = <650000>;
-							regulator-max-microvolt = <2250000>;
-							regulator-boot-on;
-							regulator-always-on;
-						};
-						LDO3 {
-							regulator-min-microvolt = <650000>;
-							regulator-max-microvolt = <2250000>;
-							regulator-boot-on;
-							regulator-always-on;
-						};
-						LDO4 {
-							regulator-min-microvolt = <750000>;
-							regulator-max-microvolt = <3900000>;
-							regulator-boot-on;
-							regulator-always-on;
-						};
-						LDO5 {
-							regulator-min-microvolt = <750000>;
-							regulator-max-microvolt = <3900000>;
-							regulator-boot-on;
-							regulator-always-on;
-						};
-						LDO6 {
-							regulator-min-microvolt = <750000>;
-							regulator-max-microvolt = <3900000>;
-							regulator-boot-on;
-							regulator-always-on;
-						};
-						LDO7 {
-							regulator-min-microvolt = <750000>;
-							regulator-max-microvolt = <3900000>;
-							regulator-boot-on;
-							regulator-always-on;
-						};
-						LDO8 {
-							regulator-min-microvolt = <750000>;
-							regulator-max-microvolt = <3900000>;
-							regulator-boot-on;
-							regulator-always-on;
-						};
-						LDO9 {
-							regulator-min-microvolt = <750000>;
-							regulator-max-microvolt = <3900000>;
-							regulator-boot-on;
-							regulator-always-on;
-						};
-						LDO10 {
-							regulator-min-microvolt = <750000>;
-							regulator-max-microvolt = <3900000>;
-						};
-						LDO11 {
-							regulator-min-microvolt = <750000>;
-							regulator-max-microvolt = <3900000>;
-							regulator-boot-on;
-							regulator-always-on;
-						};
-						LDO12 {
-							regulator-min-microvolt = <750000>;
-							regulator-max-microvolt = <3900000>;
-							regulator-boot-on;
-							regulator-always-on;
-						};
-						LDO13 {
-							regulator-min-microvolt = <750000>;
-							regulator-max-microvolt = <3900000>;
-							regulator-boot-on;
-							regulator-always-on;
-						};
-						LDO14 {
-							regulator-min-microvolt = <750000>;
-							regulator-max-microvolt = <3900000>;
-							regulator-boot-on;
-							regulator-always-on;
-						};
-						LDO15 {
-							regulator-min-microvolt = <750000>;
-							regulator-max-microvolt = <3900000>;
-							regulator-boot-on;
-							regulator-always-on;
-						};
-						LDO16 {
-							regulator-min-microvolt = <750000>;
-							regulator-max-microvolt = <3900000>;
-							regulator-boot-on;
-							regulator-always-on;
-						};
-						LDO17 {
-							regulator-min-microvolt = <650000>;
-							regulator-max-microvolt = <2250000>;
-							regulator-boot-on;
-							regulator-always-on;
-						};
-						LDO18 {
-							regulator-min-microvolt = <650000>;
-							regulator-max-microvolt = <2250000>;
-							regulator-boot-on;
-							regulator-always-on;
-						};
-						LDO19 {
-							regulator-min-microvolt = <750000>;
-							regulator-max-microvolt = <3900000>;
-							regulator-boot-on;
-							regulator-always-on;
-						};
-						LDO20 {
-							regulator-min-microvolt = <750000>;
-							regulator-max-microvolt = <3900000>;
-							regulator-boot-on;
-							regulator-always-on;
-						};
-					};
-					backlight {
-						maxim,max8925-dual-string = <0>;
-					};
-					charger {
-						batt-detect = <0>;
-						topoff-threshold = <1>;
-						fast-charge = <7>;
-						no-temp-support = <0>;
-						no-insert-detect = <0>;
-					};
-				};
+		regulators {
+			SDV1 {
+				regulator-min-microvolt = <637500>;
+				regulator-max-microvolt = <1425000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+			SDV2 {
+				regulator-min-microvolt = <650000>;
+				regulator-max-microvolt = <2225000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+			SDV3 {
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt = <3900000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+			LDO1 {
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt = <3900000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+			LDO2 {
+				regulator-min-microvolt = <650000>;
+				regulator-max-microvolt = <2250000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+			LDO3 {
+				regulator-min-microvolt = <650000>;
+				regulator-max-microvolt = <2250000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+			LDO4 {
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt = <3900000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+			LDO5 {
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt = <3900000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+			LDO6 {
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt = <3900000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+			LDO7 {
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt = <3900000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+			LDO8 {
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt = <3900000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+			LDO9 {
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt = <3900000>;
+				regulator-boot-on;
+				regulator-always-on;
 			};
-			rtc: rtc@d4010000 {
-				status = "okay";
+			LDO10 {
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt = <3900000>;
 			};
+			LDO11 {
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt = <3900000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+			LDO12 {
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt = <3900000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+			LDO13 {
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt = <3900000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+			LDO14 {
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt = <3900000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+			LDO15 {
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt = <3900000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+			LDO16 {
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt = <3900000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+			LDO17 {
+				regulator-min-microvolt = <650000>;
+				regulator-max-microvolt = <2250000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+			LDO18 {
+				regulator-min-microvolt = <650000>;
+				regulator-max-microvolt = <2250000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+			LDO19 {
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt = <3900000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+			LDO20 {
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt = <3900000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+		};
+		backlight {
+			maxim,max8925-dual-string = <0>;
+		};
+		charger {
+			batt-detect = <0>;
+			topoff-threshold = <1>;
+			fast-charge = <7>;
+			no-temp-support = <0>;
+			no-insert-detect = <0>;
 		};
 	};
 };
+
+&rtc {
+	status = "okay";
+};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/motorola-cpcap-mapphone.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/motorola-cpcap-mapphone.dtsi
@@ -13,8 +13,10 @@
 		#interrupt-cells = <2>;
 		#address-cells = <1>;
 		#size-cells = <0>;
-		spi-max-frequency = <3000000>;
+		spi-max-frequency = <9600000>;
 		spi-cs-high;
+		spi-cpol;
+		spi-cpha;
 
 		cpcap_adc: adc {
 			compatible = "motorola,mapphone-cpcap-adc";
@@ -160,12 +162,12 @@
 		regulator-enable-ramp-delay = <1000>;
 	};
 
-	/* Used by DSS */
+	/* Used by DSS and is the "zerov_regulator" trigger for SoC off mode */
 	vcsi: VCSI {
 		regulator-min-microvolt = <1800000>;
 		regulator-max-microvolt = <1800000>;
 		regulator-enable-ramp-delay = <1000>;
-		regulator-boot-on;
+		regulator-always-on;
 	};
 
 	vdac: VDAC {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/moxart-uc7112lx.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/moxart-uc7112lx.dts
@@ -79,7 +79,7 @@
 	clocks = <&ref12>;
 };
 
-&sdhci {
+&mmc {
 	status = "okay";
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/moxart.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/moxart.dtsi
@@ -93,8 +93,8 @@
 			clock-names = "PCLK";
 		};
 
-		sdhci: sdhci@98e00000 {
-			compatible = "moxa,moxart-sdhci";
+		mmc: mmc@98e00000 {
+			compatible = "moxa,moxart-mmc";
 			reg = <0x98e00000 0x5C>;
 			interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&clk_apb>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/mt7623.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/mt7623.dtsi
@@ -320,7 +320,7 @@
 		clock-names = "spi", "wrap";
 	};
 
-	cir: cir@10013000 {
+	cir: ir-receiver@10013000 {
 		compatible = "mediatek,mt7623-cir";
 		reg = <0 0x10013000 0 0x1000>;
 		interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_LOW>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts
@@ -192,6 +192,7 @@
 					fixed-link {
 						speed = <1000>;
 						full-duplex;
+						pause;
 					};
 				};
 			};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/mt7623n-rfb-emmc.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/mt7623n-rfb-emmc.dts
@@ -138,6 +138,7 @@
 	mac@1 {
 		compatible = "mediatek,eth-mac";
 		reg = <1>;
+		phy-mode = "rgmii";
 		phy-handle = <&phy5>;
 	};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/omap-gpmc-smsc9221.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/omap-gpmc-smsc9221.dtsi
@@ -29,7 +29,7 @@
 		compatible = "smsc,lan9221","smsc,lan9115";
 		bank-width = <2>;
 
-		gpmc,mux-add-data;
+		gpmc,mux-add-data = <0>;
 		gpmc,cs-on-ns = <0>;
 		gpmc,cs-rd-off-ns = <42>;
 		gpmc,cs-wr-off-ns = <36>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/omap3-cm-t3x.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/omap3-cm-t3x.dtsi
@@ -227,7 +227,7 @@
 
 		interrupt-parent = <&gpio2>;
 		interrupts = <25 0>;		/* gpio_57 */
-		pendown-gpio = <&gpio2 25 GPIO_ACTIVE_HIGH>;
+		pendown-gpio = <&gpio2 25 GPIO_ACTIVE_LOW>;
 
 		ti,x-min = /bits/ 16 <0x0>;
 		ti,x-max = /bits/ 16 <0x0fff>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/omap3-devkit8000-lcd-common.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/omap3-devkit8000-lcd-common.dtsi
@@ -54,7 +54,7 @@
 
 		interrupt-parent = <&gpio1>;
 		interrupts = <27 0>;		/* gpio_27 */
-		pendown-gpio = <&gpio1 27 GPIO_ACTIVE_HIGH>;
+		pendown-gpio = <&gpio1 27 GPIO_ACTIVE_LOW>;
 
 		ti,x-min = /bits/ 16 <0x0>;
 		ti,x-max = /bits/ 16 <0x0fff>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/omap3-gta04.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/omap3-gta04.dtsi
@@ -31,6 +31,8 @@
 	aliases {
 		display0 = &lcd;
 		display1 = &tv0;
+		/delete-property/ mmc2;
+		/delete-property/ mmc3;
 	};
 
 	ldo_3v3: fixedregulator {
@@ -515,7 +517,7 @@
 		compatible = "bosch,bma180";
 		reg = <0x41>;
 		pinctrl-names = "default";
-		pintcrl-0 = <&bma180_pins>;
+		pinctrl-0 = <&bma180_pins>;
 		interrupt-parent = <&gpio4>;
 		interrupts = <19 IRQ_TYPE_LEVEL_HIGH>; /* GPIO_115 */
 	};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/omap3-gta04a5one.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/omap3-gta04a5one.dts
@@ -5,9 +5,11 @@
 
 #include "omap3-gta04a5.dts"
 
-&omap3_pmx_core {
+/ {
 	model = "Goldelico GTA04A5/Letux 2804 with OneNAND";
+};
 
+&omap3_pmx_core {
 	gpmc_pins: pinmux_gpmc_pins {
 		pinctrl-single,pins = <
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/omap3-lilly-a83x.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/omap3-lilly-a83x.dtsi
@@ -311,7 +311,7 @@
 		interrupt-parent = <&gpio1>;
 		interrupts = <8 0>;   /* boot6 / gpio_8 */
 		spi-max-frequency = <1000000>;
-		pendown-gpio = <&gpio1 8 GPIO_ACTIVE_HIGH>;
+		pendown-gpio = <&gpio1 8 GPIO_ACTIVE_LOW>;
 		vcc-supply = <&reg_vcc3>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&tsc2048_pins>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/omap3-n900.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/omap3-n900.dts
@@ -105,6 +105,14 @@
 			linux,code = <SW_FRONT_PROXIMITY>;
 			linux,can-disable;
 		};
+
+		machine_cover {
+			label = "Machine Cover";
+			gpios = <&gpio6 0 GPIO_ACTIVE_LOW>; /* 160 */
+			linux,input-type = <EV_SW>;
+			linux,code = <SW_MACHINE_COVER>;
+			linux,can-disable;
+		};
 	};
 
 	isp1707: isp1707 {
@@ -155,6 +163,12 @@
 		pwms = <&pwm9 0 26316 0>; /* 38000 Hz */
 	};
 
+	rom_rng: rng {
+		compatible = "nokia,n900-rom-rng";
+		clocks = <&rng_ick>;
+		clock-names = "ick";
+	};
+
 	/* controlled (enabled/disabled) directly by bcm2048 and wl1251 */
 	vctcxo: vctcxo {
 		compatible = "fixed-clock";
@@ -808,10 +822,6 @@
 	pinctrl-0 = <&mmc1_pins>;
 	vmmc-supply = <&vmmc1>;
 	bus-width = <4>;
-	/* For debugging, it is often good idea to remove this GPIO.
-	   It means you can remove back cover (to reboot by removing
-	   battery) and still use the MMC card. */
-	cd-gpios = <&gpio6 0 GPIO_ACTIVE_LOW>; /* 160 */
 };
 
 /* most boards use vaux3, only some old versions use vmmc2 instead */
@@ -843,34 +853,46 @@
 		compatible = "ti,omap2-onenand";
 		reg = <0 0 0x20000>;	/* CS0, offset 0, IO size 128K */
 
+		/*
+		 * These timings are based on CONFIG_OMAP_GPMC_DEBUG=y reported
+		 * bootloader set values when booted with v5.1
+		 * (OneNAND Manufacturer: Samsung):
+		 *
+		 *   cs0 GPMC_CS_CONFIG1: 0xfb001202
+		 *   cs0 GPMC_CS_CONFIG2: 0x00111100
+		 *   cs0 GPMC_CS_CONFIG3: 0x00020200
+		 *   cs0 GPMC_CS_CONFIG4: 0x11001102
+		 *   cs0 GPMC_CS_CONFIG5: 0x03101616
+		 *   cs0 GPMC_CS_CONFIG6: 0x90060000
+		 */
 		gpmc,sync-read;
 		gpmc,sync-write;
 		gpmc,burst-length = <16>;
 		gpmc,burst-read;
 		gpmc,burst-wrap;
 		gpmc,burst-write;
-		gpmc,device-width = <2>; /* GPMC_DEVWIDTH_16BIT */
-		gpmc,mux-add-data = <2>; /* GPMC_MUX_AD */
+		gpmc,device-width = <2>;
+		gpmc,mux-add-data = <2>;
 		gpmc,cs-on-ns = <0>;
-		gpmc,cs-rd-off-ns = <87>;
-		gpmc,cs-wr-off-ns = <87>;
+		gpmc,cs-rd-off-ns = <102>;
+		gpmc,cs-wr-off-ns = <102>;
 		gpmc,adv-on-ns = <0>;
-		gpmc,adv-rd-off-ns = <10>;
-		gpmc,adv-wr-off-ns = <10>;
-		gpmc,oe-on-ns = <15>;
-		gpmc,oe-off-ns = <87>;
+		gpmc,adv-rd-off-ns = <12>;
+		gpmc,adv-wr-off-ns = <12>;
+		gpmc,oe-on-ns = <12>;
+		gpmc,oe-off-ns = <102>;
 		gpmc,we-on-ns = <0>;
-		gpmc,we-off-ns = <87>;
-		gpmc,rd-cycle-ns = <112>;
-		gpmc,wr-cycle-ns = <112>;
-		gpmc,access-ns = <81>;
-		gpmc,page-burst-access-ns = <15>;
+		gpmc,we-off-ns = <102>;
+		gpmc,rd-cycle-ns = <132>;
+		gpmc,wr-cycle-ns = <132>;
+		gpmc,access-ns = <96>;
+		gpmc,page-burst-access-ns = <18>;
 		gpmc,bus-turnaround-ns = <0>;
 		gpmc,cycle2cycle-delay-ns = <0>;
 		gpmc,wait-monitoring-ns = <0>;
-		gpmc,clk-activation-ns = <5>;
-		gpmc,wr-data-mux-bus-ns = <30>;
-		gpmc,wr-access-ns = <81>;
+		gpmc,clk-activation-ns = <6>;
+		gpmc,wr-data-mux-bus-ns = <36>;
+		gpmc,wr-access-ns = <96>;
 		gpmc,sync-clk-ps = <15000>;
 
 		/*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/omap3-overo-common-lcd35.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/omap3-overo-common-lcd35.dtsi
@@ -149,7 +149,7 @@
 
 		interrupt-parent = <&gpio4>;
 		interrupts = <18 0>;			/* gpio_114 */
-		pendown-gpio = <&gpio4 18 GPIO_ACTIVE_HIGH>;
+		pendown-gpio = <&gpio4 18 GPIO_ACTIVE_LOW>;
 
 		ti,x-min = /bits/ 16 <0x0>;
 		ti,x-max = /bits/ 16 <0x0fff>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/omap3-overo-common-lcd43.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/omap3-overo-common-lcd43.dtsi
@@ -160,7 +160,7 @@
 
 		interrupt-parent = <&gpio4>;
 		interrupts = <18 0>;			/* gpio_114 */
-		pendown-gpio = <&gpio4 18 GPIO_ACTIVE_HIGH>;
+		pendown-gpio = <&gpio4 18 GPIO_ACTIVE_LOW>;
 
 		ti,x-min = /bits/ 16 <0x0>;
 		ti,x-max = /bits/ 16 <0x0fff>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/omap3-overo-tobiduo-common.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/omap3-overo-tobiduo-common.dtsi
@@ -22,7 +22,7 @@
 		compatible = "smsc,lan9221","smsc,lan9115";
 		bank-width = <2>;
 
-		gpmc,mux-add-data;
+		gpmc,mux-add-data = <0>;
 		gpmc,cs-on-ns = <0>;
 		gpmc,cs-rd-off-ns = <42>;
 		gpmc,cs-wr-off-ns = <36>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/omap3-pandora-common.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/omap3-pandora-common.dtsi
@@ -226,6 +226,17 @@
 		gpio = <&gpio6 4 GPIO_ACTIVE_HIGH>;	/* GPIO_164 */
 	};
 
+	/* wl1251 wifi+bt module */
+	wlan_en: fixed-regulator-wg7210_en {
+		compatible = "regulator-fixed";
+		regulator-name = "vwlan";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		startup-delay-us = <50000>;
+		enable-active-high;
+		gpio = <&gpio1 23 GPIO_ACTIVE_HIGH>;
+	};
+
 	/* wg7210 (wifi+bt module) 32k clock buffer */
 	wg7210_32k: fixed-regulator-wg7210_32k {
 		compatible = "regulator-fixed";
@@ -522,9 +533,30 @@
 	/*wp-gpios = <&gpio4 31 GPIO_ACTIVE_HIGH>;*/	/* GPIO_127 */
 };
 
-/* mmc3 is probed using pdata-quirks to pass wl1251 card data */
 &mmc3 {
-	status = "disabled";
+	vmmc-supply = <&wlan_en>;
+
+	bus-width = <4>;
+	non-removable;
+	ti,non-removable;
+	cap-power-off-card;
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc3_pins>;
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	wlan: wifi@1 {
+		compatible = "ti,wl1251";
+
+		reg = <1>;
+
+		interrupt-parent = <&gpio1>;
+		interrupts = <21 IRQ_TYPE_LEVEL_HIGH>;	/* GPIO_21 */
+
+		ti,wl1251-has-eeprom;
+	};
 };
 
 /* bluetooth*/
@@ -619,7 +651,7 @@
 		pinctrl-0 = <&penirq_pins>;
 		interrupt-parent = <&gpio3>;
 		interrupts = <30 IRQ_TYPE_NONE>;	/* GPIO_94 */
-		pendown-gpio = <&gpio3 30 GPIO_ACTIVE_HIGH>;
+		pendown-gpio = <&gpio3 30 GPIO_ACTIVE_LOW>;
 		vcc-supply = <&vaux4>;
 
 		ti,x-min = /bits/ 16 <0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/omap3-tao3530.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/omap3-tao3530.dtsi
@@ -222,7 +222,7 @@
 	pinctrl-0 = <&mmc1_pins>;
 	vmmc-supply = <&vmmc1>;
 	vqmmc-supply = <&vsim>;
-	cd-gpios = <&twl_gpio 0 GPIO_ACTIVE_HIGH>;
+	cd-gpios = <&twl_gpio 0 GPIO_ACTIVE_LOW>;
 	bus-width = <8>;
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/omap3.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/omap3.dtsi
@@ -23,6 +23,9 @@
 		i2c0 = &i2c1;
 		i2c1 = &i2c2;
 		i2c2 = &i2c3;
+		mmc0 = &mmc1;
+		mmc1 = &mmc2;
+		mmc2 = &mmc3;
 		serial0 = &uart1;
 		serial1 = &uart2;
 		serial2 = &uart3;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/omap3430-sdp.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/omap3430-sdp.dts
@@ -101,7 +101,7 @@
 
 	nand@1,0 {
 		compatible = "ti,omap2-nand";
-		reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
+		reg = <1 0 4>; /* CS1, offset 0, IO size 4 */
 		interrupt-parent = <&gpmc>;
 		interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
 			     <1 IRQ_TYPE_NONE>;	/* termcount */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/omap4-droid4-xt894.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/omap4-droid4-xt894.dts
@@ -656,12 +656,12 @@
 /* Configure pwm clock source for timers 8 & 9 */
 &timer8 {
 	assigned-clocks = <&abe_clkctrl OMAP4_TIMER8_CLKCTRL 24>;
-	assigned-clock-parents = <&sys_clkin_ck>;
+	assigned-clock-parents = <&sys_32k_ck>;
 };
 
 &timer9 {
 	assigned-clocks = <&l4_per_clkctrl OMAP4_TIMER9_CLKCTRL 24>;
-	assigned-clock-parents = <&sys_clkin_ck>;
+	assigned-clock-parents = <&sys_32k_ck>;
 };
 
 /*
@@ -678,6 +678,7 @@
 &uart3 {
 	interrupts-extended = <&wakeupgen GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH
 			       &omap4_pmx_core 0x17c>;
+	overrun-throttle-ms = <500>;
 };
 
 &uart4 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/omap4-duovero-parlor.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/omap4-duovero-parlor.dts
@@ -139,7 +139,7 @@
 	ethernet@gpmc {
 		reg = <5 0 0xff>;
 		interrupt-parent = <&gpio2>;
-		interrupts = <12 IRQ_TYPE_EDGE_FALLING>;	/* gpio_44 */
+		interrupts = <12 IRQ_TYPE_LEVEL_LOW>;		/* gpio_44 */
 
 		phy-mode = "mii";
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/omap4-panda-es.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/omap4-panda-es.dts
@@ -46,7 +46,7 @@
 
 	button_pins: pinmux_button_pins {
 		pinctrl-single,pins = <
-			OMAP4_IOPAD(0x11b, PIN_INPUT_PULLUP | MUX_MODE3) /* gpio_113 */
+			OMAP4_IOPAD(0x0fc, PIN_INPUT_PULLUP | MUX_MODE3) /* gpio_113 */
 		>;
 	};
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/omap4.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/omap4.dtsi
@@ -22,6 +22,11 @@
 		i2c1 = &i2c2;
 		i2c2 = &i2c3;
 		i2c3 = &i2c4;
+		mmc0 = &mmc1;
+		mmc1 = &mmc2;
+		mmc2 = &mmc3;
+		mmc3 = &mmc4;
+		mmc4 = &mmc5;
 		serial0 = &uart1;
 		serial1 = &uart2;
 		serial2 = &uart3;
@@ -328,10 +333,10 @@
 			status = "disabled";
 		};
 
-		target-module@56000000 {
+		sgx_module: target-module@56000000 {
 			compatible = "ti,sysc-omap4", "ti,sysc";
-			reg = <0x5601fc00 0x4>,
-			      <0x5601fc10 0x4>;
+			reg = <0x5600fe00 0x4>,
+			      <0x5600fe10 0x4>;
 			reg-names = "rev", "sysc";
 			ti,sysc-midle = <SYSC_IDLE_FORCE>,
 					<SYSC_IDLE_NO>,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/omap443x.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/omap443x.dtsi
@@ -33,10 +33,12 @@
 	};
 
 	ocp {
+		/* 4430 has only gpio_86 tshut and no talert interrupt */
 		bandgap: bandgap@4a002260 {
 			reg = <0x4a002260 0x4
 			       0x4a00232C 0x4>;
 			compatible = "ti,omap4430-bandgap";
+			gpios = <&gpio3 22 GPIO_ACTIVE_HIGH>;
 
 			#thermal-sensor-cells = <0>;
 		};
@@ -74,3 +76,13 @@
 };
 
 /include/ "omap443x-clocks.dtsi"
+
+/*
+ * Use dpll_per for sgx at 153.6MHz like droid4 stock v3.0.8 Android kernel
+ */
+&sgx_module {
+	assigned-clocks = <&l3_gfx_clkctrl OMAP4_GPU_CLKCTRL 24>,
+			  <&dpll_per_m7x2_ck>;
+	assigned-clock-rates = <0>, <153600000>;
+	assigned-clock-parents = <&dpll_per_m7x2_ck>;
+};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/omap44xx-clocks.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/omap44xx-clocks.dtsi
@@ -770,14 +770,6 @@
 		ti,max-div = <2>;
 	};
 
-	sha2md5_fck: sha2md5_fck@15c8 {
-		#clock-cells = <0>;
-		compatible = "ti,gate-clock";
-		clocks = <&l3_div_ck>;
-		ti,bit-shift = <1>;
-		reg = <0x15c8>;
-	};
-
 	usb_phy_cm_clk32k: usb_phy_cm_clk32k@640 {
 		#clock-cells = <0>;
 		compatible = "ti,gate-clock";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/omap5-board-common.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/omap5-board-common.dtsi
@@ -30,14 +30,6 @@
 		regulator-max-microvolt = <5000000>;
 	};
 
-	vdds_1v8_main: fixedregulator-vdds_1v8_main {
-		compatible = "regulator-fixed";
-		regulator-name = "vdds_1v8_main";
-		vin-supply = <&smps7_reg>;
-		regulator-min-microvolt = <1800000>;
-		regulator-max-microvolt = <1800000>;
-	};
-
 	vmmcsd_fixed: fixedregulator-mmcsd {
 		compatible = "regulator-fixed";
 		regulator-name = "vmmcsd_fixed";
@@ -487,6 +479,7 @@
 					regulator-boot-on;
 				};
 
+				vdds_1v8_main:
 				smps7_reg: smps7 {
 					/* VDDS_1v8_OMAP over VDDS_1v8_MAIN */
 					regulator-name = "smps7";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/omap5-cm-t54.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/omap5-cm-t54.dts
@@ -354,7 +354,7 @@
 
 		interrupt-parent = <&gpio1>;
 		interrupts = <15 0>;			/* gpio1_wk15 */
-		pendown-gpio = <&gpio1 15 GPIO_ACTIVE_HIGH>;
+		pendown-gpio = <&gpio1 15 GPIO_ACTIVE_LOW>;
 
 
 		ti,x-min = /bits/ 16 <0x0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/omap5.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/omap5.dtsi
@@ -25,6 +25,11 @@
 		i2c2 = &i2c3;
 		i2c3 = &i2c4;
 		i2c4 = &i2c5;
+		mmc0 = &mmc1;
+		mmc1 = &mmc2;
+		mmc2 = &mmc3;
+		mmc3 = &mmc4;
+		mmc4 = &mmc5;
 		serial0 = &uart1;
 		serial1 = &uart2;
 		serial2 = &uart3;
@@ -143,6 +148,7 @@
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges = <0 0 0 0xc0000000>;
+		dma-ranges = <0x80000000 0x0 0x80000000 0x80000000>;
 		ti,hwmods = "l3_main_1", "l3_main_2", "l3_main_3";
 		reg = <0 0x44000000 0 0x2000>,
 		      <0 0x44800000 0 0x3000>,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/owl-s500.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/owl-s500.dtsi
@@ -84,21 +84,21 @@
 		global_timer: timer@b0020200 {
 			compatible = "arm,cortex-a9-global-timer";
 			reg = <0xb0020200 0x100>;
-			interrupts = <GIC_PPI 0 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_EDGE_RISING)>;
+			interrupts = <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_EDGE_RISING)>;
 			status = "disabled";
 		};
 
 		twd_timer: timer@b0020600 {
 			compatible = "arm,cortex-a9-twd-timer";
 			reg = <0xb0020600 0x20>;
-			interrupts = <GIC_PPI 2 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_EDGE_RISING)>;
+			interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_EDGE_RISING)>;
 			status = "disabled";
 		};
 
 		twd_wdt: wdt@b0020620 {
 			compatible = "arm,cortex-a9-twd-wdt";
 			reg = <0xb0020620 0xe0>;
-			interrupts = <GIC_PPI 3 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_EDGE_RISING)>;
+			interrupts = <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_EDGE_RISING)>;
 			status = "disabled";
 		};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/ox810se.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/ox810se.dtsi
@@ -323,8 +323,8 @@
 					interrupt-controller;
 					reg = <0 0x200>;
 					#interrupt-cells = <1>;
-					valid-mask = <0xFFFFFFFF>;
-					clear-mask = <0>;
+					valid-mask = <0xffffffff>;
+					clear-mask = <0xffffffff>;
 				};
 
 				timer0: timer@200 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/ox820.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/ox820.dtsi
@@ -240,8 +240,8 @@
 					reg = <0 0x200>;
 					interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
 					#interrupt-cells = <1>;
-					valid-mask = <0xFFFFFFFF>;
-					clear-mask = <0>;
+					valid-mask = <0xffffffff>;
+					clear-mask = <0xffffffff>;
 				};
 
 				timer0: timer@200 {
@@ -287,7 +287,7 @@
 				clocks = <&armclk>;
 			};
 
-			gic: gic@1000 {
+			gic: interrupt-controller@1000 {
 				compatible = "arm,arm11mp-gic";
 				interrupt-controller;
 				#interrupt-cells = <3>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/picoxcell-pc3x2.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/picoxcell-pc3x2.dtsi
@@ -45,18 +45,21 @@
 		emac: gem@30000 {
 			compatible = "cadence,gem";
 			reg = <0x30000 0x10000>;
+			interrupt-parent = <&vic0>;
 			interrupts = <31>;
 		};
 
 		dmac1: dmac@40000 {
 			compatible = "snps,dw-dmac";
 			reg = <0x40000 0x10000>;
+			interrupt-parent = <&vic0>;
 			interrupts = <25>;
 		};
 
 		dmac2: dmac@50000 {
 			compatible = "snps,dw-dmac";
 			reg = <0x50000 0x10000>;
+			interrupt-parent = <&vic0>;
 			interrupts = <26>;
 		};
 
@@ -234,6 +237,7 @@
 		axi2pico@c0000000 {
 			compatible = "picochip,axi2pico-pc3x2";
 			reg = <0xc0000000 0x10000>;
+			interrupt-parent = <&vic0>;
 			interrupts = <13 14 15 16 17 18 19 20 21>;
 		};
 	};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/qcom-apq8064.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/qcom-apq8064.dtsi
@@ -198,7 +198,7 @@
 			clock-frequency = <19200000>;
 		};
 
-		pxo_board {
+		pxo_board: pxo_board {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <27000000>;
@@ -759,7 +759,7 @@
 
 				xoadc: xoadc@197 {
 					compatible = "qcom,pm8921-adc";
-					reg = <197>;
+					reg = <0x197>;
 					interrupts-extended = <&pmicintc 78 IRQ_TYPE_EDGE_RISING>;
 					#address-cells = <2>;
 					#size-cells = <0>;
@@ -1147,7 +1147,7 @@
 		};
 
 		gpu: adreno-3xx@4300000 {
-			compatible = "qcom,adreno-3xx";
+			compatible = "qcom,adreno-320.2", "qcom,adreno";
 			reg = <0x04300000 0x20000>;
 			reg-names = "kgsl_3d0_reg_memory";
 			interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
@@ -1162,7 +1162,6 @@
 			    <&mmcc GFX3D_AHB_CLK>,
 			    <&mmcc GFX3D_AXI_CLK>,
 			    <&mmcc MMSS_IMEM_AHB_CLK>;
-			qcom,chipid = <0x03020002>;
 
 			iommus = <&gfx3d 0
 				  &gfx3d 1
@@ -1261,9 +1260,9 @@
 				<&mmcc DSI1_BYTE_CLK>,
 				<&mmcc DSI_PIXEL_CLK>,
 				<&mmcc DSI1_ESC_CLK>;
-			clock-names = "iface_clk", "bus_clk", "core_mmss_clk",
-					"src_clk", "byte_clk", "pixel_clk",
-					"core_clk";
+			clock-names = "iface", "bus", "core_mmss",
+					"src", "byte", "pixel",
+					"core";
 
 			assigned-clocks = <&mmcc DSI1_BYTE_SRC>,
 					<&mmcc DSI1_ESC_SRC>,
@@ -1305,7 +1304,7 @@
 			reg-names = "dsi_pll", "dsi_phy", "dsi_phy_regulator";
 			clock-names = "iface_clk", "ref";
 			clocks = <&mmcc DSI_M_AHB_CLK>,
-				 <&cxo_board>;
+				 <&pxo_board>;
 		};
 
 
@@ -1571,7 +1570,7 @@
 		};
 
 		etb@1a01000 {
-			compatible = "coresight-etb10", "arm,primecell";
+			compatible = "arm,coresight-etb10", "arm,primecell";
 			reg = <0x1a01000 0x1000>;
 
 			clocks = <&rpmcc RPM_QDSS_CLK>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/qcom-ipq4019.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/qcom-ipq4019.dtsi
@@ -141,7 +141,8 @@
 	clocks {
 		sleep_clk: sleep_clk {
 			compatible = "fixed-clock";
-			clock-frequency = <32768>;
+			clock-frequency = <32000>;
+			clock-output-names = "gcc_sleep_clk_src";
 			#clock-cells = <0>;
 		};
 
@@ -392,8 +393,8 @@
 			#address-cells = <3>;
 			#size-cells = <2>;
 
-			ranges = <0x81000000 0 0x40200000 0x40200000 0 0x00100000>,
-				 <0x82000000 0 0x40300000 0x40300000 0 0x00d00000>;
+			ranges = <0x81000000 0x0 0x00000000 0x40200000 0x0 0x00100000>,
+				 <0x82000000 0x0 0x40300000 0x40300000 0x0 0x00d00000>;
 
 			interrupts = <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>;
 			interrupt-names = "msi";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/qcom-ipq8064.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/qcom-ipq8064.dtsi
@@ -451,8 +451,8 @@
 			#address-cells = <3>;
 			#size-cells = <2>;
 
-			ranges = <0x81000000 0 0x0fe00000 0x0fe00000 0 0x00100000   /* downstream I/O */
-				  0x82000000 0 0x08000000 0x08000000 0 0x07e00000>; /* non-prefetchable memory */
+			ranges = <0x81000000 0x0 0x00000000 0x0fe00000 0x0 0x00010000   /* I/O */
+				  0x82000000 0x0 0x08000000 0x08000000 0x0 0x07e00000>; /* MEM */
 
 			interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
 			interrupt-names = "msi";
@@ -502,8 +502,8 @@
 			#address-cells = <3>;
 			#size-cells = <2>;
 
-			ranges = <0x81000000 0 0x31e00000 0x31e00000 0 0x00100000   /* downstream I/O */
-				  0x82000000 0 0x2e000000 0x2e000000 0 0x03e00000>; /* non-prefetchable memory */
+			ranges = <0x81000000 0x0 0x00000000 0x31e00000 0x0 0x00010000   /* I/O */
+				  0x82000000 0x0 0x2e000000 0x2e000000 0x0 0x03e00000>; /* MEM */
 
 			interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
 			interrupt-names = "msi";
@@ -553,8 +553,8 @@
 			#address-cells = <3>;
 			#size-cells = <2>;
 
-			ranges = <0x81000000 0 0x35e00000 0x35e00000 0 0x00100000   /* downstream I/O */
-				  0x82000000 0 0x32000000 0x32000000 0 0x03e00000>; /* non-prefetchable memory */
+			ranges = <0x81000000 0x0 0x00000000 0x35e00000 0x0 0x00010000   /* I/O */
+				  0x82000000 0x0 0x32000000 0x32000000 0x0 0x03e00000>; /* MEM */
 
 			interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
 			interrupt-names = "msi";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/qcom-mdm9615.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/qcom-mdm9615.dtsi
@@ -82,14 +82,12 @@
 		};
 	};
 
-	regulators {
-		vsdcc_fixed: vsdcc-regulator {
-			compatible = "regulator-fixed";
-			regulator-name = "SDCC Power";
-			regulator-min-microvolt = <2700000>;
-			regulator-max-microvolt = <2700000>;
-			regulator-always-on;
-		};
+	vsdcc_fixed: vsdcc-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "SDCC Power";
+		regulator-min-microvolt = <2700000>;
+		regulator-max-microvolt = <2700000>;
+		regulator-always-on;
 	};
 
 	soc: soc {
@@ -323,6 +321,7 @@
 
 				pmicgpio: gpio@150 {
 					compatible = "qcom,pm8018-gpio", "qcom,ssbi-gpio";
+					reg = <0x150>;
 					interrupt-controller;
 					#interrupt-cells = <2>;
 					gpio-controller;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/qcom-msm8960.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/qcom-msm8960.dtsi
@@ -145,7 +145,9 @@
 			reg		= <0x108000 0x1000>;
 			qcom,ipc	= <&l2cc 0x8 2>;
 
-			interrupts	= <0 19 0>, <0 21 0>, <0 22 0>;
+			interrupts	= <GIC_SPI 19 IRQ_TYPE_EDGE_RISING>,
+					  <GIC_SPI 21 IRQ_TYPE_EDGE_RISING>,
+					  <GIC_SPI 22 IRQ_TYPE_EDGE_RISING>;
 			interrupt-names	= "ack", "err", "wakeup";
 
 			regulators {
@@ -191,7 +193,7 @@
 				compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
 				reg = <0x16440000 0x1000>,
 				      <0x16400000 0x1000>;
-				interrupts = <0 154 0x0>;
+				interrupts = <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&gcc GSBI5_UART_CLK>, <&gcc GSBI5_H_CLK>;
 				clock-names = "core", "iface";
 				status = "disabled";
@@ -317,7 +319,7 @@
 				#address-cells = <1>;
 				#size-cells = <0>;
 				reg = <0x16080000 0x1000>;
-				interrupts = <0 147 0>;
+				interrupts = <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>;
 				spi-max-frequency = <24000000>;
 				cs-gpios = <&msmgpio 8 0>;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/qcom-msm8974.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/qcom-msm8974.dtsi
@@ -1213,8 +1213,8 @@
 				#phy-cells = <0>;
 				qcom,dsi-phy-index = <0>;
 
-				clocks = <&mmcc MDSS_AHB_CLK>;
-				clock-names = "iface";
+				clocks = <&mmcc MDSS_AHB_CLK>, <&xo_board>;
+				clock-names = "iface", "ref";
 			};
 		};
 	};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/qcom-pm8841.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/qcom-pm8841.dtsi
@@ -25,6 +25,7 @@
 			compatible = "qcom,spmi-temp-alarm";
 			reg = <0x2400>;
 			interrupts = <4 0x24 0 IRQ_TYPE_EDGE_RISING>;
+			#thermal-sensor-cells = <0>;
 		};
 	};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/r8a73a4.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/r8a73a4.dtsi
@@ -131,7 +131,14 @@
 	cmt1: timer@e6130000 {
 		compatible = "renesas,r8a73a4-cmt1", "renesas,rcar-gen2-cmt1";
 		reg = <0 0xe6130000 0 0x1004>;
-		interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp3_clks R8A73A4_CLK_CMT1>;
 		clock-names = "fck";
 		power-domains = <&pd_c5>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/r8a7740.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/r8a7740.dtsi
@@ -479,7 +479,7 @@
 		cpg_clocks: cpg_clocks@e6150000 {
 			compatible = "renesas,r8a7740-cpg-clocks";
 			reg = <0xe6150000 0x10000>;
-			clocks = <&extal1_clk>, <&extalr_clk>;
+			clocks = <&extal1_clk>, <&extal2_clk>, <&extalr_clk>;
 			#clock-cells = <1>;
 			clock-output-names = "system", "pllc0", "pllc1",
 					     "pllc2", "r",
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/r8a7743.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/r8a7743.dtsi
@@ -338,7 +338,7 @@
 			#thermal-sensor-cells = <0>;
 		};
 
-		ipmmu_sy0: mmu@e6280000 {
+		ipmmu_sy0: iommu@e6280000 {
 			compatible = "renesas,ipmmu-r8a7743",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xe6280000 0 0x1000>;
@@ -348,7 +348,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_sy1: mmu@e6290000 {
+		ipmmu_sy1: iommu@e6290000 {
 			compatible = "renesas,ipmmu-r8a7743",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xe6290000 0 0x1000>;
@@ -357,7 +357,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_ds: mmu@e6740000 {
+		ipmmu_ds: iommu@e6740000 {
 			compatible = "renesas,ipmmu-r8a7743",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xe6740000 0 0x1000>;
@@ -367,7 +367,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_mp: mmu@ec680000 {
+		ipmmu_mp: iommu@ec680000 {
 			compatible = "renesas,ipmmu-r8a7743",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xec680000 0 0x1000>;
@@ -376,7 +376,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_mx: mmu@fe951000 {
+		ipmmu_mx: iommu@fe951000 {
 			compatible = "renesas,ipmmu-r8a7743",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xfe951000 0 0x1000>;
@@ -386,7 +386,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_gp: mmu@e62a0000 {
+		ipmmu_gp: iommu@e62a0000 {
 			compatible = "renesas,ipmmu-r8a7743",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xe62a0000 0 0x1000>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/r8a7744.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/r8a7744.dtsi
@@ -338,7 +338,7 @@
 			#thermal-sensor-cells = <0>;
 		};
 
-		ipmmu_sy0: mmu@e6280000 {
+		ipmmu_sy0: iommu@e6280000 {
 			compatible = "renesas,ipmmu-r8a7744",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xe6280000 0 0x1000>;
@@ -348,7 +348,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_sy1: mmu@e6290000 {
+		ipmmu_sy1: iommu@e6290000 {
 			compatible = "renesas,ipmmu-r8a7744",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xe6290000 0 0x1000>;
@@ -357,7 +357,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_ds: mmu@e6740000 {
+		ipmmu_ds: iommu@e6740000 {
 			compatible = "renesas,ipmmu-r8a7744",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xe6740000 0 0x1000>;
@@ -367,7 +367,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_mp: mmu@ec680000 {
+		ipmmu_mp: iommu@ec680000 {
 			compatible = "renesas,ipmmu-r8a7744",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xec680000 0 0x1000>;
@@ -376,7 +376,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_mx: mmu@fe951000 {
+		ipmmu_mx: iommu@fe951000 {
 			compatible = "renesas,ipmmu-r8a7744",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xfe951000 0 0x1000>;
@@ -386,7 +386,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_gp: mmu@e62a0000 {
+		ipmmu_gp: iommu@e62a0000 {
 			compatible = "renesas,ipmmu-r8a7744",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xe62a0000 0 0x1000>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/r8a7745.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/r8a7745.dtsi
@@ -302,7 +302,7 @@
 			resets = <&cpg 407>;
 		};
 
-		ipmmu_sy0: mmu@e6280000 {
+		ipmmu_sy0: iommu@e6280000 {
 			compatible = "renesas,ipmmu-r8a7745",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xe6280000 0 0x1000>;
@@ -312,7 +312,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_sy1: mmu@e6290000 {
+		ipmmu_sy1: iommu@e6290000 {
 			compatible = "renesas,ipmmu-r8a7745",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xe6290000 0 0x1000>;
@@ -321,7 +321,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_ds: mmu@e6740000 {
+		ipmmu_ds: iommu@e6740000 {
 			compatible = "renesas,ipmmu-r8a7745",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xe6740000 0 0x1000>;
@@ -331,7 +331,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_mp: mmu@ec680000 {
+		ipmmu_mp: iommu@ec680000 {
 			compatible = "renesas,ipmmu-r8a7745",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xec680000 0 0x1000>;
@@ -340,7 +340,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_mx: mmu@fe951000 {
+		ipmmu_mx: iommu@fe951000 {
 			compatible = "renesas,ipmmu-r8a7745",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xfe951000 0 0x1000>;
@@ -350,7 +350,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_gp: mmu@e62a0000 {
+		ipmmu_gp: iommu@e62a0000 {
 			compatible = "renesas,ipmmu-r8a7745",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xe62a0000 0 0x1000>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/r8a7779-marzen.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/r8a7779-marzen.dts
@@ -146,7 +146,7 @@
 	status = "okay";
 
 	clocks = <&mstp1_clks R8A7779_CLK_DU>, <&x3_clk>;
-	clock-names = "du", "dclkin.0";
+	clock-names = "du.0", "dclkin.0";
 
 	ports {
 		port@0 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/r8a7779.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/r8a7779.dtsi
@@ -68,6 +68,14 @@
 		      <0xf0000100 0x100>;
 	};
 
+	timer@f0000200 {
+		compatible = "arm,cortex-a9-global-timer";
+		reg = <0xf0000200 0x100>;
+		interrupts = <GIC_PPI 11
+			(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_EDGE_RISING)>;
+		clocks = <&cpg_clocks R8A7779_CLK_ZS>;
+	};
+
 	timer@f0000600 {
 		compatible = "arm,cortex-a9-twd-timer";
 		reg = <0xf0000600 0x20>;
@@ -455,6 +463,7 @@
 		reg = <0xfff80000 0x40000>;
 		interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&mstp1_clks R8A7779_CLK_DU>;
+		clock-names = "du.0";
 		power-domains = <&sysc R8A7779_PD_ALWAYS_ON>;
 		status = "disabled";
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/r8a7790.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/r8a7790.dtsi
@@ -427,7 +427,7 @@
 			#thermal-sensor-cells = <0>;
 		};
 
-		ipmmu_sy0: mmu@e6280000 {
+		ipmmu_sy0: iommu@e6280000 {
 			compatible = "renesas,ipmmu-r8a7790",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xe6280000 0 0x1000>;
@@ -437,7 +437,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_sy1: mmu@e6290000 {
+		ipmmu_sy1: iommu@e6290000 {
 			compatible = "renesas,ipmmu-r8a7790",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xe6290000 0 0x1000>;
@@ -446,7 +446,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_ds: mmu@e6740000 {
+		ipmmu_ds: iommu@e6740000 {
 			compatible = "renesas,ipmmu-r8a7790",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xe6740000 0 0x1000>;
@@ -456,7 +456,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_mp: mmu@ec680000 {
+		ipmmu_mp: iommu@ec680000 {
 			compatible = "renesas,ipmmu-r8a7790",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xec680000 0 0x1000>;
@@ -465,7 +465,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_mx: mmu@fe951000 {
+		ipmmu_mx: iommu@fe951000 {
 			compatible = "renesas,ipmmu-r8a7790",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xfe951000 0 0x1000>;
@@ -475,7 +475,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_rt: mmu@ffc80000 {
+		ipmmu_rt: iommu@ffc80000 {
 			compatible = "renesas,ipmmu-r8a7790",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xffc80000 0 0x1000>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/r8a7791.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/r8a7791.dtsi
@@ -350,7 +350,7 @@
 			#thermal-sensor-cells = <0>;
 		};
 
-		ipmmu_sy0: mmu@e6280000 {
+		ipmmu_sy0: iommu@e6280000 {
 			compatible = "renesas,ipmmu-r8a7791",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xe6280000 0 0x1000>;
@@ -360,7 +360,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_sy1: mmu@e6290000 {
+		ipmmu_sy1: iommu@e6290000 {
 			compatible = "renesas,ipmmu-r8a7791",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xe6290000 0 0x1000>;
@@ -369,7 +369,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_ds: mmu@e6740000 {
+		ipmmu_ds: iommu@e6740000 {
 			compatible = "renesas,ipmmu-r8a7791",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xe6740000 0 0x1000>;
@@ -379,7 +379,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_mp: mmu@ec680000 {
+		ipmmu_mp: iommu@ec680000 {
 			compatible = "renesas,ipmmu-r8a7791",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xec680000 0 0x1000>;
@@ -388,7 +388,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_mx: mmu@fe951000 {
+		ipmmu_mx: iommu@fe951000 {
 			compatible = "renesas,ipmmu-r8a7791",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xfe951000 0 0x1000>;
@@ -398,7 +398,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_rt: mmu@ffc80000 {
+		ipmmu_rt: iommu@ffc80000 {
 			compatible = "renesas,ipmmu-r8a7791",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xffc80000 0 0x1000>;
@@ -407,7 +407,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_gp: mmu@e62a0000 {
+		ipmmu_gp: iommu@e62a0000 {
 			compatible = "renesas,ipmmu-r8a7791",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xe62a0000 0 0x1000>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/r8a7793-gose.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/r8a7793-gose.dts
@@ -339,7 +339,7 @@
 			reg = <0x20>;
 			remote = <&vin1>;
 
-			port {
+			ports {
 				#address-cells = <1>;
 				#size-cells = <0>;
 
@@ -399,7 +399,7 @@
 			interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
 			default-input = <0>;
 
-			port {
+			ports {
 				#address-cells = <1>;
 				#size-cells = <0>;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/r8a7793.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/r8a7793.dtsi
@@ -336,7 +336,7 @@
 			#thermal-sensor-cells = <0>;
 		};
 
-		ipmmu_sy0: mmu@e6280000 {
+		ipmmu_sy0: iommu@e6280000 {
 			compatible = "renesas,ipmmu-r8a7793",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xe6280000 0 0x1000>;
@@ -346,7 +346,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_sy1: mmu@e6290000 {
+		ipmmu_sy1: iommu@e6290000 {
 			compatible = "renesas,ipmmu-r8a7793",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xe6290000 0 0x1000>;
@@ -355,7 +355,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_ds: mmu@e6740000 {
+		ipmmu_ds: iommu@e6740000 {
 			compatible = "renesas,ipmmu-r8a7793",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xe6740000 0 0x1000>;
@@ -365,7 +365,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_mp: mmu@ec680000 {
+		ipmmu_mp: iommu@ec680000 {
 			compatible = "renesas,ipmmu-r8a7793",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xec680000 0 0x1000>;
@@ -374,7 +374,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_mx: mmu@fe951000 {
+		ipmmu_mx: iommu@fe951000 {
 			compatible = "renesas,ipmmu-r8a7793",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xfe951000 0 0x1000>;
@@ -384,7 +384,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_rt: mmu@ffc80000 {
+		ipmmu_rt: iommu@ffc80000 {
 			compatible = "renesas,ipmmu-r8a7793",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xffc80000 0 0x1000>;
@@ -393,7 +393,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_gp: mmu@e62a0000 {
+		ipmmu_gp: iommu@e62a0000 {
 			compatible = "renesas,ipmmu-r8a7793",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xe62a0000 0 0x1000>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/r8a7794.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/r8a7794.dtsi
@@ -290,7 +290,7 @@
 			resets = <&cpg 407>;
 		};
 
-		ipmmu_sy0: mmu@e6280000 {
+		ipmmu_sy0: iommu@e6280000 {
 			compatible = "renesas,ipmmu-r8a7794",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xe6280000 0 0x1000>;
@@ -300,7 +300,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_sy1: mmu@e6290000 {
+		ipmmu_sy1: iommu@e6290000 {
 			compatible = "renesas,ipmmu-r8a7794",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xe6290000 0 0x1000>;
@@ -309,7 +309,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_ds: mmu@e6740000 {
+		ipmmu_ds: iommu@e6740000 {
 			compatible = "renesas,ipmmu-r8a7794",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xe6740000 0 0x1000>;
@@ -319,7 +319,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_mp: mmu@ec680000 {
+		ipmmu_mp: iommu@ec680000 {
 			compatible = "renesas,ipmmu-r8a7794",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xec680000 0 0x1000>;
@@ -328,7 +328,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_mx: mmu@fe951000 {
+		ipmmu_mx: iommu@fe951000 {
 			compatible = "renesas,ipmmu-r8a7794",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xfe951000 0 0x1000>;
@@ -338,7 +338,7 @@
 			status = "disabled";
 		};
 
-		ipmmu_gp: mmu@e62a0000 {
+		ipmmu_gp: iommu@e62a0000 {
 			compatible = "renesas,ipmmu-r8a7794",
 				     "renesas,ipmmu-vmsa";
 			reg = <0 0xe62a0000 0 0x1000>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/rk3036-evb.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/rk3036-evb.dts
@@ -31,7 +31,7 @@
 &i2c1 {
 	status = "okay";
 
-	hym8563: hym8563@51 {
+	hym8563: rtc@51 {
 		compatible = "haoyu,hym8563";
 		reg = <0x51>;
 		#clock-cells = <0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/rk3036-kylin.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/rk3036-kylin.dts
@@ -300,8 +300,8 @@
 &i2c2 {
 	status = "okay";
 
-	rt5616: rt5616@1b {
-		compatible = "rt5616";
+	rt5616: audio-codec@1b {
+		compatible = "realtek,rt5616";
 		reg = <0x1b>;
 		clocks = <&cru SCLK_I2S_OUT>;
 		clock-names = "mclk";
@@ -390,7 +390,7 @@
 		};
 	};
 
-	sleep {
+	suspend {
 		global_pwroff: global-pwroff {
 			rockchip,pins = <2 RK_PA7 1 &pcfg_pull_none>;
 		};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/rk3036.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/rk3036.dtsi
@@ -128,7 +128,7 @@
 		assigned-clocks = <&cru SCLK_GPU>;
 		assigned-clock-rates = <100000000>;
 		clocks = <&cru SCLK_GPU>, <&cru SCLK_GPU>;
-		clock-names = "core", "bus";
+		clock-names = "bus", "core";
 		resets = <&cru SRST_GPU>;
 		status = "disabled";
 	};
@@ -317,12 +317,13 @@
 		};
 	};
 
-	acodec: acodec-ana@20030000 {
-		compatible = "rk3036-codec";
+	acodec: audio-codec@20030000 {
+		compatible = "rockchip,rk3036-codec";
 		reg = <0x20030000 0x4000>;
-		rockchip,grf = <&grf>;
 		clock-names = "acodec_pclk";
 		clocks = <&cru PCLK_ACODEC>;
+		rockchip,grf = <&grf>;
+		#sound-dai-cells = <0>;
 		status = "disabled";
 	};
 
@@ -332,17 +333,24 @@
 		interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&cru  PCLK_HDMI>;
 		clock-names = "pclk";
-		rockchip,grf = <&grf>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&hdmi_ctl>;
 		status = "disabled";
 
-		hdmi_in: port {
+		ports {
 			#address-cells = <1>;
 			#size-cells = <0>;
-			hdmi_in_vop: endpoint@0 {
+
+			hdmi_in: port@0 {
 				reg = <0>;
-				remote-endpoint = <&vop_out_hdmi>;
+
+				hdmi_in_vop: endpoint {
+					remote-endpoint = <&vop_out_hdmi>;
+				};
+			};
+
+			hdmi_out: port@1 {
+				reg = <1>;
 			};
 		};
 	};
@@ -481,11 +489,11 @@
 	};
 
 	spi: spi@20074000 {
-		compatible = "rockchip,rockchip-spi";
+		compatible = "rockchip,rk3036-spi";
 		reg = <0x20074000 0x1000>;
 		interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&cru PCLK_SPI>, <&cru SCLK_SPI>;
-		clock-names = "apb-pclk","spi_pclk";
+		clocks = <&cru SCLK_SPI>, <&cru PCLK_SPI>;
+		clock-names = "spiclk", "apb_pclk";
 		dmas = <&pdma 8>, <&pdma 9>;
 		dma-names = "tx", "rx";
 		pinctrl-names = "default";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/rk3066a.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/rk3066a.dtsi
@@ -124,6 +124,7 @@
 		pinctrl-0 = <&hdmii2c_xfer>, <&hdmi_hpd>;
 		power-domains = <&power RK3066_PD_VIO>;
 		rockchip,grf = <&grf>;
+		#sound-dai-cells = <0>;
 		status = "disabled";
 
 		ports {
@@ -761,7 +762,7 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		pd_vio@RK3066_PD_VIO {
+		power-domain@RK3066_PD_VIO {
 			reg = <RK3066_PD_VIO>;
 			clocks = <&cru ACLK_LCDC0>,
 				 <&cru ACLK_LCDC1>,
@@ -788,7 +789,7 @@
 				 <&qos_rga>;
 		};
 
-		pd_video@RK3066_PD_VIDEO {
+		power-domain@RK3066_PD_VIDEO {
 			reg = <RK3066_PD_VIDEO>;
 			clocks = <&cru ACLK_VDPU>,
 				 <&cru ACLK_VEPU>,
@@ -797,7 +798,7 @@
 			pm_qos = <&qos_vpu>;
 		};
 
-		pd_gpu@RK3066_PD_GPU {
+		power-domain@RK3066_PD_GPU {
 			reg = <RK3066_PD_GPU>;
 			clocks = <&cru ACLK_GPU>;
 			pm_qos = <&qos_gpu>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/rk3188-bqedison2qc.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/rk3188-bqedison2qc.dts
@@ -58,20 +58,25 @@
 
 	lvds-encoder {
 		compatible = "ti,sn75lvds83", "lvds-encoder";
-		#address-cells = <1>;
-		#size-cells = <0>;
 
-		port@0 {
-			reg = <0>;
-			lvds_in_vop0: endpoint {
-				remote-endpoint = <&vop0_out_lvds>;
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+
+				lvds_in_vop0: endpoint {
+					remote-endpoint = <&vop0_out_lvds>;
+				};
 			};
-		};
 
-		port@1 {
-			reg = <1>;
-			lvds_out_panel: endpoint {
-				remote-endpoint = <&panel_in_lvds>;
+			port@1 {
+				reg = <1>;
+
+				lvds_out_panel: endpoint {
+					remote-endpoint = <&panel_in_lvds>;
+				};
 			};
 		};
 	};
@@ -465,10 +470,13 @@
 	non-removable;
 	pinctrl-names = "default";
 	pinctrl-0 = <&sd1_clk>, <&sd1_cmd>, <&sd1_bus4>;
-	vmmcq-supply = <&vccio_wl>;
+	vqmmc-supply = <&vccio_wl>;
+	#address-cells = <1>;
+	#size-cells = <0>;
 	status = "okay";
 
 	brcmf: wifi@1 {
+		reg = <1>;
 		compatible = "brcm,bcm4329-fmac";
 		interrupt-parent = <&gpio3>;
 		interrupts = <RK_PD2 GPIO_ACTIVE_HIGH>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/rk3188-radxarock.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/rk3188-radxarock.dts
@@ -67,7 +67,7 @@
 		#sound-dai-cells = <0>;
 	};
 
-	ir_recv: gpio-ir-receiver {
+	ir_recv: ir-receiver {
 		compatible = "gpio-ir-receiver";
 		gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>;
 		pinctrl-names = "default";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/rk3188.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/rk3188.dtsi
@@ -150,16 +150,16 @@
 		compatible = "rockchip,rk3188-timer", "rockchip,rk3288-timer";
 		reg = <0x2000e000 0x20>;
 		interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&cru SCLK_TIMER3>, <&cru PCLK_TIMER3>;
-		clock-names = "timer", "pclk";
+		clocks = <&cru PCLK_TIMER3>, <&cru SCLK_TIMER3>;
+		clock-names = "pclk", "timer";
 	};
 
 	timer6: timer@200380a0 {
 		compatible = "rockchip,rk3188-timer", "rockchip,rk3288-timer";
 		reg = <0x200380a0 0x20>;
 		interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&cru SCLK_TIMER6>, <&cru PCLK_TIMER0>;
-		clock-names = "timer", "pclk";
+		clocks = <&cru PCLK_TIMER0>, <&cru SCLK_TIMER6>;
+		clock-names = "pclk", "timer";
 	};
 
 	i2s0: i2s@1011a000 {
@@ -404,7 +404,7 @@
 				rockchip,pins = <2 RK_PD3 1 &pcfg_pull_none>;
 			};
 
-			lcdc1_rgb24: ldcd1-rgb24 {
+			lcdc1_rgb24: lcdc1-rgb24 {
 				rockchip,pins = <2 RK_PA0 1 &pcfg_pull_none>,
 						<2 RK_PA1 1 &pcfg_pull_none>,
 						<2 RK_PA2 1 &pcfg_pull_none>,
@@ -632,7 +632,6 @@
 
 &global_timer {
 	interrupts = <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_EDGE_RISING)>;
-	status = "disabled";
 };
 
 &local_timer {
@@ -701,7 +700,7 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		pd_vio@RK3188_PD_VIO {
+		power-domain@RK3188_PD_VIO {
 			reg = <RK3188_PD_VIO>;
 			clocks = <&cru ACLK_LCDC0>,
 				 <&cru ACLK_LCDC1>,
@@ -723,7 +722,7 @@
 				 <&qos_rga>;
 		};
 
-		pd_video@RK3188_PD_VIDEO {
+		power-domain@RK3188_PD_VIDEO {
 			reg = <RK3188_PD_VIDEO>;
 			clocks = <&cru ACLK_VDPU>,
 				 <&cru ACLK_VEPU>,
@@ -732,7 +731,7 @@
 			pm_qos = <&qos_vpu>;
 		};
 
-		pd_gpu@RK3188_PD_GPU {
+		power-domain@RK3188_PD_GPU {
 			reg = <RK3188_PD_GPU>;
 			clocks = <&cru ACLK_GPU>;
 			pm_qos = <&qos_gpu>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/rk3228-evb.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/rk3228-evb.dts
@@ -46,7 +46,7 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		phy: phy@0 {
+		phy: ethernet-phy@0 {
 			compatible = "ethernet-phy-id1234.d400", "ethernet-phy-ieee802.3-c22";
 			reg = <0>;
 			clocks = <&cru SCLK_MAC_PHY>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/rk3229-xms6.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/rk3229-xms6.dts
@@ -150,7 +150,7 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 
-		phy: phy@0 {
+		phy: ethernet-phy@0 {
 			compatible = "ethernet-phy-id1234.d400",
 			             "ethernet-phy-ieee802.3-c22";
 			reg = <0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/rk322x.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/rk322x.dtsi
@@ -561,7 +561,7 @@
 				  "pp1",
 				  "ppmmu1";
 		clocks = <&cru ACLK_GPU>, <&cru ACLK_GPU>;
-		clock-names = "core", "bus";
+		clock-names = "bus", "core";
 		resets = <&cru SRST_GPU_A>;
 		status = "disabled";
 	};
@@ -570,10 +570,9 @@
 		compatible = "rockchip,iommu";
 		reg = <0x20020800 0x100>;
 		interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
-		interrupt-names = "vpu_mmu";
 		clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>;
 		clock-names = "aclk", "iface";
-		iommu-cells = <0>;
+		#iommu-cells = <0>;
 		status = "disabled";
 	};
 
@@ -581,10 +580,9 @@
 		compatible = "rockchip,iommu";
 		reg = <0x20030480 0x40>, <0x200304c0 0x40>;
 		interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
-		interrupt-names = "vdec_mmu";
 		clocks = <&cru ACLK_RKVDEC>, <&cru HCLK_RKVDEC>;
 		clock-names = "aclk", "iface";
-		iommu-cells = <0>;
+		#iommu-cells = <0>;
 		status = "disabled";
 	};
 
@@ -614,7 +612,6 @@
 		compatible = "rockchip,iommu";
 		reg = <0x20053f00 0x100>;
 		interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
-		interrupt-names = "vop_mmu";
 		clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>;
 		clock-names = "aclk", "iface";
 		#iommu-cells = <0>;
@@ -625,10 +622,9 @@
 		compatible = "rockchip,iommu";
 		reg = <0x20070800 0x100>;
 		interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
-		interrupt-names = "iep_mmu";
 		clocks = <&cru ACLK_IEP>, <&cru HCLK_IEP>;
 		clock-names = "aclk", "iface";
-		iommu-cells = <0>;
+		#iommu-cells = <0>;
 		status = "disabled";
 	};
 
@@ -639,8 +635,8 @@
 		interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
 		assigned-clocks = <&cru SCLK_HDMI_PHY>;
 		assigned-clock-parents = <&hdmi_phy>;
-		clocks = <&cru SCLK_HDMI_HDCP>, <&cru PCLK_HDMI_CTRL>, <&cru SCLK_HDMI_CEC>;
-		clock-names = "isfr", "iahb", "cec";
+		clocks = <&cru PCLK_HDMI_CTRL>, <&cru SCLK_HDMI_HDCP>, <&cru SCLK_HDMI_CEC>;
+		clock-names = "iahb", "isfr", "cec";
 		pinctrl-names = "default";
 		pinctrl-0 = <&hdmii2c_xfer &hdmi_hpd &hdmi_cec>;
 		resets = <&cru SRST_HDMI_P>;
@@ -1033,7 +1029,7 @@
 			};
 		};
 
-		spi-0 {
+		spi0 {
 			spi0_clk: spi0-clk {
 				rockchip,pins = <0 RK_PB1 2 &pcfg_pull_up>;
 			};
@@ -1051,7 +1047,7 @@
 			};
 		};
 
-		spi-1 {
+		spi1 {
 			spi1_clk: spi1-clk {
 				rockchip,pins = <0 RK_PC7 2 &pcfg_pull_up>;
 			};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/rk3288-evb-act8846.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/rk3288-evb-act8846.dts
@@ -53,7 +53,7 @@
 		vin-supply = <&vcc_sys>;
 	};
 
-	hym8563@51 {
+	rtc@51 {
 		compatible = "haoyu,hym8563";
 		reg = <0x51>;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/rk3288-firefly.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/rk3288-firefly.dtsi
@@ -233,7 +233,7 @@
 		vin-supply = <&vcc_sys>;
 	};
 
-	hym8563: hym8563@51 {
+	hym8563: rtc@51 {
 		compatible = "haoyu,hym8563";
 		reg = <0x51>;
 		#clock-cells = <0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/rk3288-miqi.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/rk3288-miqi.dts
@@ -145,7 +145,7 @@
 		vin-supply = <&vcc_sys>;
 	};
 
-	hym8563: hym8563@51 {
+	hym8563: rtc@51 {
 		compatible = "haoyu,hym8563";
 		reg = <0x51>;
 		#clock-cells = <0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/rk3288-rock2-som.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/rk3288-rock2-som.dtsi
@@ -218,7 +218,7 @@
 	flash0-supply = <&vcc_flash>;
 	flash1-supply = <&vccio_pmu>;
 	gpio30-supply = <&vccio_pmu>;
-	gpio1830 = <&vcc_io>;
+	gpio1830-supply = <&vcc_io>;
 	lcdc-supply = <&vcc_io>;
 	sdcard-supply = <&vccio_sd>;
 	wifi-supply = <&vcc_18>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/rk3288-rock2-square.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/rk3288-rock2-square.dts
@@ -165,7 +165,7 @@
 };
 
 &i2c0 {
-	hym8563: hym8563@51 {
+	hym8563: rtc@51 {
 		compatible = "haoyu,hym8563";
 		reg = <0x51>;
 		#clock-cells = <0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/rk3288-vyasa.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/rk3288-vyasa.dts
@@ -357,10 +357,10 @@
 	audio-supply = <&vcc_18>;
 	bb-supply = <&vcc_io>;
 	dvp-supply = <&vcc_io>;
-	flash0-suuply = <&vcc_18>;
+	flash0-supply = <&vcc_18>;
 	flash1-supply = <&vcc_lan>;
 	gpio30-supply = <&vcc_io>;
-	gpio1830 = <&vcc_io>;
+	gpio1830-supply = <&vcc_io>;
 	lcdc-supply = <&vcc_io>;
 	sdcard-supply = <&vccio_sd>;
 	wifi-supply = <&vcc_18>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/rk3288.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/rk3288.dtsi
@@ -238,8 +238,8 @@
 		compatible = "rockchip,rk3288-timer";
 		reg = <0x0 0xff810000 0x0 0x20>;
 		interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&xin24m>, <&cru PCLK_TIMER>;
-		clock-names = "timer", "pclk";
+		clocks = <&cru PCLK_TIMER>, <&xin24m>;
+		clock-names = "pclk", "timer";
 	};
 
 	display-subsystem {
@@ -771,7 +771,7 @@
 			 *	*_HDMI		HDMI
 			 *	*_MIPI_*	MIPI
 			 */
-			pd_vio@RK3288_PD_VIO {
+			power-domain@RK3288_PD_VIO {
 				reg = <RK3288_PD_VIO>;
 				clocks = <&cru ACLK_IEP>,
 					 <&cru ACLK_ISP>,
@@ -813,7 +813,7 @@
 			 * Note: The following 3 are HEVC(H.265) clocks,
 			 * and on the ACLK_HEVC_NIU (NOC).
 			 */
-			pd_hevc@RK3288_PD_HEVC {
+			power-domain@RK3288_PD_HEVC {
 				reg = <RK3288_PD_HEVC>;
 				clocks = <&cru ACLK_HEVC>,
 					 <&cru SCLK_HEVC_CABAC>,
@@ -827,7 +827,7 @@
 			 * (video endecoder & decoder) clocks that on the
 			 * ACLK_VCODEC_NIU and HCLK_VCODEC_NIU (NOC).
 			 */
-			pd_video@RK3288_PD_VIDEO {
+			power-domain@RK3288_PD_VIDEO {
 				reg = <RK3288_PD_VIDEO>;
 				clocks = <&cru ACLK_VCODEC>,
 					 <&cru HCLK_VCODEC>;
@@ -838,7 +838,7 @@
 			 * Note: ACLK_GPU is the GPU clock,
 			 * and on the ACLK_GPU_NIU (NOC).
 			 */
-			pd_gpu@RK3288_PD_GPU {
+			power-domain@RK3288_PD_GPU {
 				reg = <RK3288_PD_GPU>;
 				clocks = <&cru ACLK_GPU>;
 				pm_qos = <&qos_gpu_r>,
@@ -942,7 +942,7 @@
 		status = "disabled";
 	};
 
-	spdif: sound@ff88b0000 {
+	spdif: sound@ff8b0000 {
 		compatible = "rockchip,rk3288-spdif", "rockchip,rk3066-spdif";
 		reg = <0x0 0xff8b0000 0x0 0x10000>;
 		#sound-dai-cells = <0>;
@@ -975,7 +975,7 @@
 		status = "disabled";
 	};
 
-	crypto: cypto-controller@ff8a0000 {
+	crypto: crypto@ff8a0000 {
 		compatible = "rockchip,rk3288-crypto";
 		reg = <0x0 0xff8a0000 0x0 0x4000>;
 		interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
@@ -1188,6 +1188,7 @@
 		clock-names = "dp", "pclk";
 		phys = <&edp_phy>;
 		phy-names = "dp";
+		power-domains = <&power RK3288_PD_VIO>;
 		resets = <&cru SRST_EDP>;
 		reset-names = "dp";
 		rockchip,grf = <&grf>;
@@ -1575,7 +1576,7 @@
 			drive-strength = <12>;
 		};
 
-		sleep {
+		suspend {
 			global_pwroff: global-pwroff {
 				rockchip,pins = <0 RK_PA0 1 &pcfg_pull_none>;
 			};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/rk3xxx.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/rk3xxx.dtsi
@@ -84,7 +84,7 @@
 		compatible = "arm,mali-400";
 		reg = <0x10090000 0x10000>;
 		clocks = <&cru ACLK_GPU>, <&cru ACLK_GPU>;
-		clock-names = "core", "bus";
+		clock-names = "bus", "core";
 		assigned-clocks = <&cru ACLK_GPU>;
 		assigned-clock-rates = <100000000>;
 		resets = <&cru SRST_GPU>;
@@ -108,6 +108,13 @@
 		reg = <0x1013c200 0x20>;
 		interrupts = <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_EDGE_RISING)>;
 		clocks = <&cru CORE_PERI>;
+		status = "disabled";
+		/* The clock source and the sched_clock provided by the arm_global_timer
+		 * on Rockchip rk3066a/rk3188 are quite unstable because their rates
+		 * depend on the CPU frequency.
+		 * Keep the arm_global_timer disabled in order to have the
+		 * DW_APB_TIMER (rk3066a) or ROCKCHIP_TIMER (rk3188) selected by default.
+		 */
 	};
 
 	local_timer: local-timer@1013c600 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/s3c6410-mini6410.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/s3c6410-mini6410.dts
@@ -28,29 +28,21 @@
 		bootargs = "console=ttySAC0,115200n8 earlyprintk rootwait root=/dev/mmcblk0p1";
 	};
 
-	clocks {
-		compatible = "simple-bus";
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		fin_pll: oscillator@0 {
-			compatible = "fixed-clock";
-			reg = <0>;
-			clock-frequency = <12000000>;
-			clock-output-names = "fin_pll";
-			#clock-cells = <0>;
-		};
+	fin_pll: oscillator-0 {
+		compatible = "fixed-clock";
+		clock-frequency = <12000000>;
+		clock-output-names = "fin_pll";
+		#clock-cells = <0>;
+	};
 
-		xusbxti: oscillator@1 {
-			compatible = "fixed-clock";
-			reg = <1>;
-			clock-output-names = "xusbxti";
-			clock-frequency = <48000000>;
-			#clock-cells = <0>;
-		};
+	xusbxti: oscillator-1 {
+		compatible = "fixed-clock";
+		clock-output-names = "xusbxti";
+		clock-frequency = <48000000>;
+		#clock-cells = <0>;
 	};
 
-	srom-cs1@18000000 {
+	srom-cs1-bus@18000000 {
 		compatible = "simple-bus";
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -59,7 +51,7 @@
 
 		ethernet@18000000 {
 			compatible = "davicom,dm9000";
-			reg = <0x18000000 0x2 0x18000004 0x2>;
+			reg = <0x18000000 0x2>, <0x18000004 0x2>;
 			interrupt-parent = <&gpn>;
 			interrupts = <7 IRQ_TYPE_LEVEL_HIGH>;
 			davicom,no-eeprom;
@@ -165,6 +157,10 @@
 	};
 };
 
+&clocks {
+	clocks = <&fin_pll>;
+};
+
 &sdhci0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&sd0_clk>, <&sd0_cmd>, <&sd0_cd>, <&sd0_bus4>;
@@ -197,12 +193,12 @@
 };
 
 &pinctrl0 {
-	gpio_leds: gpio-leds {
+	gpio_leds: gpio-leds-pins {
 		samsung,pins = "gpk-4", "gpk-5", "gpk-6", "gpk-7";
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	gpio_keys: gpio-keys {
+	gpio_keys: gpio-keys-pins {
 		samsung,pins = "gpn-0", "gpn-1", "gpn-2", "gpn-3",
 				"gpn-4", "gpn-5", "gpl-11", "gpl-12";
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/s3c6410-smdk6410.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/s3c6410-smdk6410.dts
@@ -69,6 +69,10 @@
 	};
 };
 
+&clocks {
+	clocks = <&fin_pll>;
+};
+
 &sdhci0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&sd0_clk>, <&sd0_cmd>, <&sd0_cd>, <&sd0_bus4>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/s3c64xx-pinctrl.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/s3c64xx-pinctrl.dtsi
@@ -16,111 +16,111 @@
 	 * Pin banks
 	 */
 
-	gpa: gpa {
+	gpa: gpa-gpio-bank {
 		gpio-controller;
 		#gpio-cells = <2>;
 		interrupt-controller;
 		#interrupt-cells = <2>;
 	};
 
-	gpb: gpb {
+	gpb: gpb-gpio-bank {
 		gpio-controller;
 		#gpio-cells = <2>;
 		interrupt-controller;
 		#interrupt-cells = <2>;
 	};
 
-	gpc: gpc {
+	gpc: gpc-gpio-bank {
 		gpio-controller;
 		#gpio-cells = <2>;
 		interrupt-controller;
 		#interrupt-cells = <2>;
 	};
 
-	gpd: gpd {
+	gpd: gpd-gpio-bank {
 		gpio-controller;
 		#gpio-cells = <2>;
 		interrupt-controller;
 		#interrupt-cells = <2>;
 	};
 
-	gpe: gpe {
+	gpe: gpe-gpio-bank {
 		gpio-controller;
 		#gpio-cells = <2>;
 	};
 
-	gpf: gpf {
+	gpf: gpf-gpio-bank {
 		gpio-controller;
 		#gpio-cells = <2>;
 		interrupt-controller;
 		#interrupt-cells = <2>;
 	};
 
-	gpg: gpg {
+	gpg: gpg-gpio-bank {
 		gpio-controller;
 		#gpio-cells = <2>;
 		interrupt-controller;
 		#interrupt-cells = <2>;
 	};
 
-	gph: gph {
+	gph: gph-gpio-bank {
 		gpio-controller;
 		#gpio-cells = <2>;
 		interrupt-controller;
 		#interrupt-cells = <2>;
 	};
 
-	gpi: gpi {
+	gpi: gpi-gpio-bank {
 		gpio-controller;
 		#gpio-cells = <2>;
 	};
 
-	gpj: gpj {
+	gpj: gpj-gpio-bank {
 		gpio-controller;
 		#gpio-cells = <2>;
 	};
 
-	gpk: gpk {
+	gpk: gpk-gpio-bank {
 		gpio-controller;
 		#gpio-cells = <2>;
 	};
 
-	gpl: gpl {
+	gpl: gpl-gpio-bank {
 		gpio-controller;
 		#gpio-cells = <2>;
 		interrupt-controller;
 		#interrupt-cells = <2>;
 	};
 
-	gpm: gpm {
+	gpm: gpm-gpio-bank {
 		gpio-controller;
 		#gpio-cells = <2>;
 		interrupt-controller;
 		#interrupt-cells = <2>;
 	};
 
-	gpn: gpn {
+	gpn: gpn-gpio-bank {
 		gpio-controller;
 		#gpio-cells = <2>;
 		interrupt-controller;
 		#interrupt-cells = <2>;
 	};
 
-	gpo: gpo {
+	gpo: gpo-gpio-bank {
 		gpio-controller;
 		#gpio-cells = <2>;
 		interrupt-controller;
 		#interrupt-cells = <2>;
 	};
 
-	gpp: gpp {
+	gpp: gpp-gpio-bank {
 		gpio-controller;
 		#gpio-cells = <2>;
 		interrupt-controller;
 		#interrupt-cells = <2>;
 	};
 
-	gpq: gpq {
+	gpq: gpq-gpio-bank {
 		gpio-controller;
 		#gpio-cells = <2>;
 		interrupt-controller;
@@ -131,225 +131,225 @@
 	 * Pin groups
 	 */
 
-	uart0_data: uart0-data {
+	uart0_data: uart0-data-pins {
 		samsung,pins = "gpa-0", "gpa-1";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	uart0_fctl: uart0-fctl {
+	uart0_fctl: uart0-fctl-pins {
 		samsung,pins = "gpa-2", "gpa-3";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	uart1_data: uart1-data {
+	uart1_data: uart1-data-pins {
 		samsung,pins = "gpa-4", "gpa-5";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	uart1_fctl: uart1-fctl {
+	uart1_fctl: uart1-fctl-pins {
 		samsung,pins = "gpa-6", "gpa-7";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	uart2_data: uart2-data {
+	uart2_data: uart2-data-pins {
 		samsung,pins = "gpb-0", "gpb-1";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	uart3_data: uart3-data {
+	uart3_data: uart3-data-pins {
 		samsung,pins = "gpb-2", "gpb-3";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	ext_dma_0: ext-dma-0 {
+	ext_dma_0: ext-dma-0-pins {
 		samsung,pins = "gpb-0", "gpb-1";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	ext_dma_1: ext-dma-1 {
+	ext_dma_1: ext-dma-1-pins {
 		samsung,pins = "gpb-2", "gpb-3";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_4>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	irda_data_0: irda-data-0 {
+	irda_data_0: irda-data-0-pins {
 		samsung,pins = "gpb-0", "gpb-1";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_4>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	irda_data_1: irda-data-1 {
+	irda_data_1: irda-data-1-pins {
 		samsung,pins = "gpb-2", "gpb-3";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	irda_sdbw: irda-sdbw {
+	irda_sdbw: irda-sdbw-pins {
 		samsung,pins = "gpb-4";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	i2c0_bus: i2c0-bus {
+	i2c0_bus: i2c0-bus-pins {
 		samsung,pins = "gpb-5", "gpb-6";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_UP>;
 	};
 
-	i2c1_bus: i2c1-bus {
+	i2c1_bus: i2c1-bus-pins {
 		/* S3C6410-only */
 		samsung,pins = "gpb-2", "gpb-3";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_6>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_UP>;
 	};
 
-	spi0_bus: spi0-bus {
+	spi0_bus: spi0-bus-pins {
 		samsung,pins = "gpc-0", "gpc-1", "gpc-2";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_UP>;
 	};
 
-	spi0_cs: spi0-cs {
+	spi0_cs: spi0-cs-pins {
 		samsung,pins = "gpc-3";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	spi1_bus: spi1-bus {
+	spi1_bus: spi1-bus-pins {
 		samsung,pins = "gpc-4", "gpc-5", "gpc-6";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_UP>;
 	};
 
-	spi1_cs: spi1-cs {
+	spi1_cs: spi1-cs-pins {
 		samsung,pins = "gpc-7";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	sd0_cmd: sd0-cmd {
+	sd0_cmd: sd0-cmd-pins {
 		samsung,pins = "gpg-1";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	sd0_clk: sd0-clk {
+	sd0_clk: sd0-clk-pins {
 		samsung,pins = "gpg-0";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	sd0_bus1: sd0-bus1 {
+	sd0_bus1: sd0-bus1-pins {
 		samsung,pins = "gpg-2";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	sd0_bus4: sd0-bus4 {
+	sd0_bus4: sd0-bus4-pins {
 		samsung,pins = "gpg-2", "gpg-3", "gpg-4", "gpg-5";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	sd0_cd: sd0-cd {
+	sd0_cd: sd0-cd-pins {
 		samsung,pins = "gpg-6";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_UP>;
 	};
 
-	sd1_cmd: sd1-cmd {
+	sd1_cmd: sd1-cmd-pins {
 		samsung,pins = "gph-1";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	sd1_clk: sd1-clk {
+	sd1_clk: sd1-clk-pins {
 		samsung,pins = "gph-0";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	sd1_bus1: sd1-bus1 {
+	sd1_bus1: sd1-bus1-pins {
 		samsung,pins = "gph-2";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	sd1_bus4: sd1-bus4 {
+	sd1_bus4: sd1-bus4-pins {
 		samsung,pins = "gph-2", "gph-3", "gph-4", "gph-5";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	sd1_bus8: sd1-bus8 {
+	sd1_bus8: sd1-bus8-pins {
 		samsung,pins = "gph-2", "gph-3", "gph-4", "gph-5",
 				"gph-6", "gph-7", "gph-8", "gph-9";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	sd1_cd: sd1-cd {
+	sd1_cd: sd1-cd-pins {
 		samsung,pins = "gpg-6";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_UP>;
 	};
 
-	sd2_cmd: sd2-cmd {
+	sd2_cmd: sd2-cmd-pins {
 		samsung,pins = "gpc-4";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	sd2_clk: sd2-clk {
+	sd2_clk: sd2-clk-pins {
 		samsung,pins = "gpc-5";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	sd2_bus1: sd2-bus1 {
+	sd2_bus1: sd2-bus1-pins {
 		samsung,pins = "gph-6";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	sd2_bus4: sd2-bus4 {
+	sd2_bus4: sd2-bus4-pins {
 		samsung,pins = "gph-6", "gph-7", "gph-8", "gph-9";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	i2s0_bus: i2s0-bus {
+	i2s0_bus: i2s0-bus-pins {
 		samsung,pins = "gpd-0", "gpd-2", "gpd-3", "gpd-4";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	i2s0_cdclk: i2s0-cdclk {
+	i2s0_cdclk: i2s0-cdclk-pins {
 		samsung,pins = "gpd-1";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	i2s1_bus: i2s1-bus {
+	i2s1_bus: i2s1-bus-pins {
 		samsung,pins = "gpe-0", "gpe-2", "gpe-3", "gpe-4";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	i2s1_cdclk: i2s1-cdclk {
+	i2s1_cdclk: i2s1-cdclk-pins {
 		samsung,pins = "gpe-1";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	i2s2_bus: i2s2-bus {
+	i2s2_bus: i2s2-bus-pins {
 		/* S3C6410-only */
 		samsung,pins = "gpc-4", "gpc-5", "gpc-6", "gph-6",
 				"gph-8", "gph-9";
@@ -357,50 +357,50 @@
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	i2s2_cdclk: i2s2-cdclk {
+	i2s2_cdclk: i2s2-cdclk-pins {
 		/* S3C6410-only */
 		samsung,pins = "gph-7";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_5>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	pcm0_bus: pcm0-bus {
+	pcm0_bus: pcm0-bus-pins {
 		samsung,pins = "gpd-0", "gpd-2", "gpd-3", "gpd-4";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	pcm0_extclk: pcm0-extclk {
+	pcm0_extclk: pcm0-extclk-pins {
 		samsung,pins = "gpd-1";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	pcm1_bus: pcm1-bus {
+	pcm1_bus: pcm1-bus-pins {
 		samsung,pins = "gpe-0", "gpe-2", "gpe-3", "gpe-4";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	pcm1_extclk: pcm1-extclk {
+	pcm1_extclk: pcm1-extclk-pins {
 		samsung,pins = "gpe-1";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	ac97_bus_0: ac97-bus-0 {
+	ac97_bus_0: ac97-bus-0-pins {
 		samsung,pins = "gpd-0", "gpd-1", "gpd-2", "gpd-3", "gpd-4";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_4>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	ac97_bus_1: ac97-bus-1 {
+	ac97_bus_1: ac97-bus-1-pins {
 		samsung,pins = "gpe-0", "gpe-1", "gpe-2", "gpe-3", "gpe-4";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_4>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	cam_port: cam-port {
+	cam_port: cam-port-pins {
 		samsung,pins = "gpf-0", "gpf-1", "gpf-2", "gpf-4",
 				"gpf-5", "gpf-6", "gpf-7", "gpf-8",
 				"gpf-9", "gpf-10", "gpf-11", "gpf-12";
@@ -408,242 +408,242 @@
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	cam_rst: cam-rst {
+	cam_rst: cam-rst-pins {
 		samsung,pins = "gpf-3";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	cam_field: cam-field {
+	cam_field: cam-field-pins {
 		/* S3C6410-only */
 		samsung,pins = "gpb-4";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	pwm_extclk: pwm-extclk {
+	pwm_extclk: pwm-extclk-pins {
 		samsung,pins = "gpf-13";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	pwm0_out: pwm0-out {
+	pwm0_out: pwm0-out-pins {
 		samsung,pins = "gpf-14";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	pwm1_out: pwm1-out {
+	pwm1_out: pwm1-out-pins {
 		samsung,pins = "gpf-15";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	clkout0: clkout-0 {
+	clkout0: clkout-0-pins {
 		samsung,pins = "gpf-14";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	keypad_col0_0: keypad-col0-0 {
+	keypad_col0_0: keypad-col0-0-pins {
 		samsung,pins = "gph-0";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_4>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	keypad_col1_0: keypad-col1-0 {
+	keypad_col1_0: keypad-col1-0-pins {
 		samsung,pins = "gph-1";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_4>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	keypad_col2_0: keypad-col2-0 {
+	keypad_col2_0: keypad-col2-0-pins {
 		samsung,pins = "gph-2";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_4>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	keypad_col3_0: keypad-col3-0 {
+	keypad_col3_0: keypad-col3-0-pins {
 		samsung,pins = "gph-3";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_4>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	keypad_col4_0: keypad-col4-0 {
+	keypad_col4_0: keypad-col4-0-pins {
 		samsung,pins = "gph-4";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_4>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	keypad_col5_0: keypad-col5-0 {
+	keypad_col5_0: keypad-col5-0-pins {
 		samsung,pins = "gph-5";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_4>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	keypad_col6_0: keypad-col6-0 {
+	keypad_col6_0: keypad-col6-0-pins {
 		samsung,pins = "gph-6";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_4>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	keypad_col7_0: keypad-col7-0 {
+	keypad_col7_0: keypad-col7-0-pins {
 		samsung,pins = "gph-7";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_4>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	keypad_col0_1: keypad-col0-1 {
+	keypad_col0_1: keypad-col0-1-pins {
 		samsung,pins = "gpl-0";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	keypad_col1_1: keypad-col1-1 {
+	keypad_col1_1: keypad-col1-1-pins {
 		samsung,pins = "gpl-1";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	keypad_col2_1: keypad-col2-1 {
+	keypad_col2_1: keypad-col2-1-pins {
 		samsung,pins = "gpl-2";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	keypad_col3_1: keypad-col3-1 {
+	keypad_col3_1: keypad-col3-1-pins {
 		samsung,pins = "gpl-3";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	keypad_col4_1: keypad-col4-1 {
+	keypad_col4_1: keypad-col4-1-pins {
 		samsung,pins = "gpl-4";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	keypad_col5_1: keypad-col5-1 {
+	keypad_col5_1: keypad-col5-1-pins {
 		samsung,pins = "gpl-5";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	keypad_col6_1: keypad-col6-1 {
+	keypad_col6_1: keypad-col6-1-pins {
 		samsung,pins = "gpl-6";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	keypad_col7_1: keypad-col7-1 {
+	keypad_col7_1: keypad-col7-1-pins {
 		samsung,pins = "gpl-7";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	keypad_row0_0: keypad-row0-0 {
+	keypad_row0_0: keypad-row0-0-pins {
 		samsung,pins = "gpk-8";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	keypad_row1_0: keypad-row1-0 {
+	keypad_row1_0: keypad-row1-0-pins {
 		samsung,pins = "gpk-9";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	keypad_row2_0: keypad-row2-0 {
+	keypad_row2_0: keypad-row2-0-pins {
 		samsung,pins = "gpk-10";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	keypad_row3_0: keypad-row3-0 {
+	keypad_row3_0: keypad-row3-0-pins {
 		samsung,pins = "gpk-11";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	keypad_row4_0: keypad-row4-0 {
+	keypad_row4_0: keypad-row4-0-pins {
 		samsung,pins = "gpk-12";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	keypad_row5_0: keypad-row5-0 {
+	keypad_row5_0: keypad-row5-0-pins {
 		samsung,pins = "gpk-13";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	keypad_row6_0: keypad-row6-0 {
+	keypad_row6_0: keypad-row6-0-pins {
 		samsung,pins = "gpk-14";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	keypad_row7_0: keypad-row7-0 {
+	keypad_row7_0: keypad-row7-0-pins {
 		samsung,pins = "gpk-15";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	keypad_row0_1: keypad-row0-1 {
+	keypad_row0_1: keypad-row0-1-pins {
 		samsung,pins = "gpn-0";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	keypad_row1_1: keypad-row1-1 {
+	keypad_row1_1: keypad-row1-1-pins {
 		samsung,pins = "gpn-1";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	keypad_row2_1: keypad-row2-1 {
+	keypad_row2_1: keypad-row2-1-pins {
 		samsung,pins = "gpn-2";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	keypad_row3_1: keypad-row3-1 {
+	keypad_row3_1: keypad-row3-1-pins {
 		samsung,pins = "gpn-3";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	keypad_row4_1: keypad-row4-1 {
+	keypad_row4_1: keypad-row4-1-pins {
 		samsung,pins = "gpn-4";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	keypad_row5_1: keypad-row5-1 {
+	keypad_row5_1: keypad-row5-1-pins {
 		samsung,pins = "gpn-5";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	keypad_row6_1: keypad-row6-1 {
+	keypad_row6_1: keypad-row6-1-pins {
 		samsung,pins = "gpn-6";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	keypad_row7_1: keypad-row7-1 {
+	keypad_row7_1: keypad-row7-1-pins {
 		samsung,pins = "gpn-7";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	lcd_ctrl: lcd-ctrl {
+	lcd_ctrl: lcd-ctrl-pins {
 		samsung,pins = "gpj-8", "gpj-9", "gpj-10", "gpj-11";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_2>;
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	lcd_data16: lcd-data-width16 {
+	lcd_data16: lcd-data-width16-pins {
 		samsung,pins = "gpi-3", "gpi-4", "gpi-5", "gpi-6",
 				"gpi-7", "gpi-10", "gpi-11", "gpi-12",
 				"gpi-13", "gpi-14", "gpi-15", "gpj-3",
@@ -652,7 +652,7 @@
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	lcd_data18: lcd-data-width18 {
+	lcd_data18: lcd-data-width18-pins {
 		samsung,pins = "gpi-2", "gpi-3", "gpi-4", "gpi-5",
 				"gpi-6", "gpi-7", "gpi-10", "gpi-11",
 				"gpi-12", "gpi-13", "gpi-14", "gpi-15",
@@ -662,7 +662,7 @@
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	lcd_data24: lcd-data-width24 {
+	lcd_data24: lcd-data-width24-pins {
 		samsung,pins = "gpi-0", "gpi-1", "gpi-2", "gpi-3",
 				"gpi-4", "gpi-5", "gpi-6", "gpi-7",
 				"gpi-8", "gpi-9", "gpi-10", "gpi-11",
@@ -673,7 +673,7 @@
 		samsung,pin-pud = <S3C64XX_PIN_PULL_NONE>;
 	};
 
-	hsi_bus: hsi-bus {
+	hsi_bus: hsi-bus-pins {
 		samsung,pins = "gpk-0", "gpk-1", "gpk-2", "gpk-3",
 				"gpk-4", "gpk-5", "gpk-6", "gpk-7";
 		samsung,pin-function = <EXYNOS_PIN_FUNC_3>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/s5pv210-aries.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/s5pv210-aries.dtsi
@@ -454,6 +454,7 @@
 	pinctrl-names = "default";
 	cap-sd-highspeed;
 	cap-mmc-highspeed;
+	keep-power-in-suspend;
 
 	mmc-pwrseq = <&wifi_pwrseq>;
 	non-removable;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/s5pv210-smdkv210.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/s5pv210-smdkv210.dts
@@ -15,6 +15,7 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/input/input.h>
 #include "s5pv210.dtsi"
 
@@ -31,11 +32,18 @@
 		reg = <0x20000000 0x40000000>;
 	};
 
-	ethernet@18000000 {
+	pmic_ap_clk: clock-0 {
+		/* Workaround for missing PMIC and its clock */
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <32768>;
+	};
+
+	ethernet@a8000000 {
 		compatible = "davicom,dm9000";
-		reg = <0xA8000000 0x2 0xA8000002 0x2>;
+		reg = <0xa8000000 0x2>, <0xa8000002 0x2>;
 		interrupt-parent = <&gph1>;
-		interrupts = <1 4>;
+		interrupts = <1 IRQ_TYPE_LEVEL_HIGH>;
 		local-mac-address = [00 00 de ad be ef];
 		davicom,no-eeprom;
 	};
@@ -47,6 +55,14 @@
 		default-brightness-level = <6>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&pwm3_out>;
+		power-supply = <&dc5v_reg>;
+	};
+
+	dc5v_reg: regulator-0 {
+		compatible = "regulator-fixed";
+		regulator-name = "DC5V";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
 	};
 };
 
@@ -147,6 +163,8 @@
 
 &rtc {
 	status = "okay";
+	clocks = <&clocks CLK_RTC>, <&pmic_ap_clk>;
+	clock-names = "rtc", "rtc_src";
 };
 
 &sdhci0 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/s5pv210.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/s5pv210.dtsi
@@ -52,34 +52,26 @@
 		};
 	};
 
+	xxti: oscillator-0 {
+		compatible = "fixed-clock";
+		clock-frequency = <0>;
+		clock-output-names = "xxti";
+		#clock-cells = <0>;
+	};
+
+	xusbxti: oscillator-1 {
+		compatible = "fixed-clock";
+		clock-frequency = <0>;
+		clock-output-names = "xusbxti";
+		#clock-cells = <0>;
+	};
+
 	soc {
 		compatible = "simple-bus";
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges;
 
-		external-clocks {
-			compatible = "simple-bus";
-			#address-cells = <1>;
-			#size-cells = <0>;
-
-			xxti: oscillator@0 {
-				compatible = "fixed-clock";
-				reg = <0>;
-				clock-frequency = <0>;
-				clock-output-names = "xxti";
-				#clock-cells = <0>;
-			};
-
-			xusbxti: oscillator@1 {
-				compatible = "fixed-clock";
-				reg = <1>;
-				clock-frequency = <0>;
-				clock-output-names = "xusbxti";
-				#clock-cells = <0>;
-			};
-		};
-
 		onenand: onenand@b0600000 {
 			compatible = "samsung,s5pv210-onenand";
 			reg = <0xb0600000 0x2000>,
@@ -100,19 +92,16 @@
 		};
 
 		clocks: clock-controller@e0100000 {
-			compatible = "samsung,s5pv210-clock", "simple-bus";
+			compatible = "samsung,s5pv210-clock";
 			reg = <0xe0100000 0x10000>;
 			clock-names = "xxti", "xusbxti";
 			clocks = <&xxti>, <&xusbxti>;
 			#clock-cells = <1>;
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges;
+		};
 
-			pmu_syscon: syscon@e0108000 {
-				compatible = "samsung-s5pv210-pmu", "syscon";
-				reg = <0xe0108000 0x8000>;
-			};
+		pmu_syscon: syscon@e0108000 {
+			compatible = "samsung-s5pv210-pmu", "syscon";
+			reg = <0xe0108000 0x8000>;
 		};
 
 		pinctrl0: pinctrl@e0200000 {
@@ -128,35 +117,28 @@
 			};
 		};
 
-		amba {
-			#address-cells = <1>;
-			#size-cells = <1>;
-			compatible = "simple-bus";
-			ranges;
-
-			pdma0: dma@e0900000 {
-				compatible = "arm,pl330", "arm,primecell";
-				reg = <0xe0900000 0x1000>;
-				interrupt-parent = <&vic0>;
-				interrupts = <19>;
-				clocks = <&clocks CLK_PDMA0>;
-				clock-names = "apb_pclk";
-				#dma-cells = <1>;
-				#dma-channels = <8>;
-				#dma-requests = <32>;
-			};
+		pdma0: dma@e0900000 {
+			compatible = "arm,pl330", "arm,primecell";
+			reg = <0xe0900000 0x1000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <19>;
+			clocks = <&clocks CLK_PDMA0>;
+			clock-names = "apb_pclk";
+			#dma-cells = <1>;
+			#dma-channels = <8>;
+			#dma-requests = <32>;
+		};
 
-			pdma1: dma@e0a00000 {
-				compatible = "arm,pl330", "arm,primecell";
-				reg = <0xe0a00000 0x1000>;
-				interrupt-parent = <&vic0>;
-				interrupts = <20>;
-				clocks = <&clocks CLK_PDMA1>;
-				clock-names = "apb_pclk";
-				#dma-cells = <1>;
-				#dma-channels = <8>;
-				#dma-requests = <32>;
-			};
+		pdma1: dma@e0a00000 {
+			compatible = "arm,pl330", "arm,primecell";
+			reg = <0xe0a00000 0x1000>;
+			interrupt-parent = <&vic0>;
+			interrupts = <20>;
+			clocks = <&clocks CLK_PDMA1>;
+			clock-names = "apb_pclk";
+			#dma-cells = <1>;
+			#dma-channels = <8>;
+			#dma-requests = <32>;
 		};
 
 		spi0: spi@e1300000 {
@@ -229,43 +211,36 @@
 			status = "disabled";
 		};
 
-		audio-subsystem {
-			compatible = "samsung,s5pv210-audss", "simple-bus";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges;
-
-			clk_audss: clock-controller@eee10000 {
-				compatible = "samsung,s5pv210-audss-clock";
-				reg = <0xeee10000 0x1000>;
-				clock-names = "hclk", "xxti",
-						"fout_epll",
-						"sclk_audio0";
-				clocks = <&clocks DOUT_HCLKP>, <&xxti>,
-						<&clocks FOUT_EPLL>,
-						<&clocks SCLK_AUDIO0>;
-				#clock-cells = <1>;
-			};
+		clk_audss: clock-controller@eee10000 {
+			compatible = "samsung,s5pv210-audss-clock";
+			reg = <0xeee10000 0x1000>;
+			clock-names = "hclk", "xxti",
+				      "fout_epll",
+				      "sclk_audio0";
+			clocks = <&clocks DOUT_HCLKP>, <&xxti>,
+				 <&clocks FOUT_EPLL>,
+				 <&clocks SCLK_AUDIO0>;
+			#clock-cells = <1>;
+		};
 
-			i2s0: i2s@eee30000 {
-				compatible = "samsung,s5pv210-i2s";
-				reg = <0xeee30000 0x1000>;
-				interrupt-parent = <&vic2>;
-				interrupts = <16>;
-				dma-names = "rx", "tx", "tx-sec";
-				dmas = <&pdma1 9>, <&pdma1 10>, <&pdma1 11>;
-				clock-names = "iis",
-						"i2s_opclk0",
-						"i2s_opclk1";
-				clocks = <&clk_audss CLK_I2S>,
-						<&clk_audss CLK_I2S>,
-						<&clk_audss CLK_DOUT_AUD_BUS>;
-				samsung,idma-addr = <0xc0010000>;
-				pinctrl-names = "default";
-				pinctrl-0 = <&i2s0_bus>;
-				#sound-dai-cells = <0>;
-				status = "disabled";
-			};
+		i2s0: i2s@eee30000 {
+			compatible = "samsung,s5pv210-i2s";
+			reg = <0xeee30000 0x1000>;
+			interrupt-parent = <&vic2>;
+			interrupts = <16>;
+			dma-names = "rx", "tx", "tx-sec";
+			dmas = <&pdma1 9>, <&pdma1 10>, <&pdma1 11>;
+			clock-names = "iis",
+				      "i2s_opclk0",
+				      "i2s_opclk1";
+			clocks = <&clk_audss CLK_I2S>,
+				 <&clk_audss CLK_I2S>,
+				 <&clk_audss CLK_DOUT_AUD_BUS>;
+			samsung,idma-addr = <0xc0010000>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&i2s0_bus>;
+			#sound-dai-cells = <0>;
+			status = "disabled";
 		};
 
 		i2s1: i2s@e2100000 {
@@ -596,7 +571,7 @@
 				interrupts = <29>;
 				clocks = <&clocks CLK_CSIS>,
 						<&clocks SCLK_CSIS>;
-				clock-names = "clk_csis",
+				clock-names = "csis",
 						"sclk_csis";
 				bus-width = <4>;
 				status = "disabled";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/sama5d2.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/sama5d2.dtsi
@@ -526,7 +526,7 @@
 				pmecc: ecc-engine@f8014070 {
 					compatible = "atmel,sama5d2-pmecc";
 					reg = <0xf8014070 0x490>,
-					      <0xf8014500 0x100>;
+					      <0xf8014500 0x200>;
 				};
 			};
 
@@ -648,6 +648,7 @@
 				clocks = <&pmc PMC_TYPE_PERIPHERAL 51>;
 				#address-cells = <1>;
 				#size-cells = <1>;
+				no-memory-wc;
 				ranges = <0 0xf8044000 0x1420>;
 			};
 
@@ -716,7 +717,7 @@
 
 			can0: can@f8054000 {
 				compatible = "bosch,m_can";
-				reg = <0xf8054000 0x4000>, <0x210000 0x4000>;
+				reg = <0xf8054000 0x4000>, <0x210000 0x1c00>;
 				reg-names = "m_can", "message_ram";
 				interrupts = <56 IRQ_TYPE_LEVEL_HIGH 7>,
 					     <64 IRQ_TYPE_LEVEL_HIGH 7>;
@@ -932,13 +933,13 @@
 				clocks = <&pmc PMC_TYPE_PERIPHERAL 55>, <&pmc PMC_TYPE_GCK 55>;
 				clock-names = "pclk", "gclk";
 				assigned-clocks = <&pmc PMC_TYPE_CORE PMC_I2S1_MUX>;
-				assigned-parrents = <&pmc PMC_TYPE_GCK 55>;
+				assigned-clock-parents = <&pmc PMC_TYPE_GCK 55>;
 				status = "disabled";
 			};
 
 			can1: can@fc050000 {
 				compatible = "bosch,m_can";
-				reg = <0xfc050000 0x4000>, <0x210000 0x4000>;
+				reg = <0xfc050000 0x4000>, <0x210000 0x3800>;
 				reg-names = "m_can", "message_ram";
 				interrupts = <57 IRQ_TYPE_LEVEL_HIGH 7>,
 					     <65 IRQ_TYPE_LEVEL_HIGH 7>;
@@ -948,7 +949,7 @@
 				assigned-clocks = <&pmc PMC_TYPE_GCK 57>;
 				assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_UTMI>;
 				assigned-clock-rates = <40000000>;
-				bosch,mram-cfg = <0x1100 0 0 64 0 0 32 32>;
+				bosch,mram-cfg = <0x1c00 0 0 64 0 0 32 32>;
 				status = "disabled";
 			};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/sama5d3.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/sama5d3.dtsi
@@ -1188,49 +1188,49 @@
 					usart0_clk: usart0_clk {
 						#clock-cells = <0>;
 						reg = <12>;
-						atmel,clk-output-range = <0 66000000>;
+						atmel,clk-output-range = <0 83000000>;
 					};
 
 					usart1_clk: usart1_clk {
 						#clock-cells = <0>;
 						reg = <13>;
-						atmel,clk-output-range = <0 66000000>;
+						atmel,clk-output-range = <0 83000000>;
 					};
 
 					usart2_clk: usart2_clk {
 						#clock-cells = <0>;
 						reg = <14>;
-						atmel,clk-output-range = <0 66000000>;
+						atmel,clk-output-range = <0 83000000>;
 					};
 
 					usart3_clk: usart3_clk {
 						#clock-cells = <0>;
 						reg = <15>;
-						atmel,clk-output-range = <0 66000000>;
+						atmel,clk-output-range = <0 83000000>;
 					};
 
 					uart0_clk: uart0_clk {
 						#clock-cells = <0>;
 						reg = <16>;
-						atmel,clk-output-range = <0 66000000>;
+						atmel,clk-output-range = <0 83000000>;
 					};
 
 					twi0_clk: twi0_clk {
 						reg = <18>;
 						#clock-cells = <0>;
-						atmel,clk-output-range = <0 16625000>;
+						atmel,clk-output-range = <0 41500000>;
 					};
 
 					twi1_clk: twi1_clk {
 						#clock-cells = <0>;
 						reg = <19>;
-						atmel,clk-output-range = <0 16625000>;
+						atmel,clk-output-range = <0 41500000>;
 					};
 
 					twi2_clk: twi2_clk {
 						#clock-cells = <0>;
 						reg = <20>;
-						atmel,clk-output-range = <0 16625000>;
+						atmel,clk-output-range = <0 41500000>;
 					};
 
 					mci0_clk: mci0_clk {
@@ -1246,19 +1246,19 @@
 					spi0_clk: spi0_clk {
 						#clock-cells = <0>;
 						reg = <24>;
-						atmel,clk-output-range = <0 133000000>;
+						atmel,clk-output-range = <0 166000000>;
 					};
 
 					spi1_clk: spi1_clk {
 						#clock-cells = <0>;
 						reg = <25>;
-						atmel,clk-output-range = <0 133000000>;
+						atmel,clk-output-range = <0 166000000>;
 					};
 
 					tcb0_clk: tcb0_clk {
 						#clock-cells = <0>;
 						reg = <26>;
-						atmel,clk-output-range = <0 133000000>;
+						atmel,clk-output-range = <0 166000000>;
 					};
 
 					pwm_clk: pwm_clk {
@@ -1269,7 +1269,7 @@
 					adc_clk: adc_clk {
 						#clock-cells = <0>;
 						reg = <29>;
-						atmel,clk-output-range = <0 66000000>;
+						atmel,clk-output-range = <0 83000000>;
 					};
 
 					dma0_clk: dma0_clk {
@@ -1300,13 +1300,13 @@
 					ssc0_clk: ssc0_clk {
 						#clock-cells = <0>;
 						reg = <38>;
-						atmel,clk-output-range = <0 66000000>;
+						atmel,clk-output-range = <0 83000000>;
 					};
 
 					ssc1_clk: ssc1_clk {
 						#clock-cells = <0>;
 						reg = <39>;
-						atmel,clk-output-range = <0 66000000>;
+						atmel,clk-output-range = <0 83000000>;
 					};
 
 					sha_clk: sha_clk {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/sama5d3_can.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/sama5d3_can.dtsi
@@ -36,13 +36,13 @@
 					can0_clk: can0_clk {
 						#clock-cells = <0>;
 						reg = <40>;
-						atmel,clk-output-range = <0 66000000>;
+						atmel,clk-output-range = <0 83000000>;
 					};
 
 					can1_clk: can1_clk {
 						#clock-cells = <0>;
 						reg = <41>;
-						atmel,clk-output-range = <0 66000000>;
+						atmel,clk-output-range = <0 83000000>;
 					};
 				};
 			};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/sama5d3_tcb1.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/sama5d3_tcb1.dtsi
@@ -22,6 +22,7 @@
 					tcb1_clk: tcb1_clk {
 						#clock-cells = <0>;
 						reg = <27>;
+						atmel,clk-output-range = <0 166000000>;
 					};
 				};
 			};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/sama5d3_uart.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/sama5d3_uart.dtsi
@@ -41,13 +41,13 @@
 					uart0_clk: uart0_clk {
 						#clock-cells = <0>;
 						reg = <16>;
-						atmel,clk-output-range = <0 66000000>;
+						atmel,clk-output-range = <0 83000000>;
 					};
 
 					uart1_clk: uart1_clk {
 						#clock-cells = <0>;
 						reg = <17>;
-						atmel,clk-output-range = <0 66000000>;
+						atmel,clk-output-range = <0 83000000>;
 					};
 				};
 			};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/sama5d4.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/sama5d4.dtsi
@@ -914,7 +914,7 @@
 					0xffffffff 0x3ffcfe7c 0x1c010101	/* pioA */
 					0x7fffffff 0xfffccc3a 0x3f00cc3a	/* pioB */
 					0xffffffff 0x3ff83fff 0xff00ffff	/* pioC */
-					0x0003ff00 0x8002a800 0x00000000	/* pioD */
+					0xb003ff00 0x8002a800 0x00000000	/* pioD */
 					0xffffffff 0x7fffffff 0x76fff1bf	/* pioE */
 					>;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/socfpga.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/socfpga.dtsi
@@ -710,7 +710,7 @@
 			};
 		};
 
-		L2: l2-cache@fffef000 {
+		L2: cache-controller@fffef000 {
 			compatible = "arm,pl310-cache";
 			reg = <0xfffef000 0x1000>;
 			interrupts = <0 38 0x04>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/socfpga_arria10.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/socfpga_arria10.dtsi
@@ -636,7 +636,7 @@
 			reg = <0xffcfb100 0x80>;
 		};
 
-		L2: l2-cache@fffff000 {
+		L2: cache-controller@fffff000 {
 			compatible = "arm,pl310-cache";
 			reg = <0xfffff000 0x1000>;
 			interrupts = <0 18 IRQ_TYPE_LEVEL_HIGH>;
@@ -819,7 +819,7 @@
 		timer3: timer3@ffd00100 {
 			compatible = "snps,dw-apb-timer";
 			interrupts = <0 118 IRQ_TYPE_LEVEL_HIGH>;
-			reg = <0xffd01000 0x100>;
+			reg = <0xffd00100 0x100>;
 			clocks = <&l4_sys_free_clk>;
 			clock-names = "timer";
 			resets = <&rst L4SYSTIMER1_RESET>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/socfpga_arria10_socdk_qspi.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/socfpga_arria10_socdk_qspi.dts
@@ -12,7 +12,7 @@
 	flash0: n25q00@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "n25q00aa";
+		compatible = "micron,mt25qu02g", "jedec,spi-nor";
 		reg = <0>;
 		spi-max-frequency = <100000000>;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/socfpga_arria5_socdk.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/socfpga_arria5_socdk.dts
@@ -119,7 +119,7 @@
 	flash: flash@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "n25q256a";
+		compatible = "micron,n25q256a", "jedec,spi-nor";
 		reg = <0>;
 		spi-max-frequency = <100000000>;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts
@@ -124,7 +124,7 @@
 	flash0: n25q00@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "n25q00";
+		compatible = "micron,mt25qu02g", "jedec,spi-nor";
 		reg = <0>;	/* chip select */
 		spi-max-frequency = <100000000>;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/socfpga_cyclone5_sockit.dts
@@ -169,7 +169,7 @@
 	flash: flash@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "n25q00";
+		compatible = "micron,mt25qu02g", "jedec,spi-nor";
 		reg = <0>;
 		spi-max-frequency = <100000000>;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/socfpga_cyclone5_socrates.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/socfpga_cyclone5_socrates.dts
@@ -80,7 +80,7 @@
 	flash: flash@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "n25q256a";
+		compatible = "micron,n25q256a", "jedec,spi-nor";
 		reg = <0>;
 		spi-max-frequency = <100000000>;
 		m25p,fast-read;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/socfpga_cyclone5_sodia.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/socfpga_cyclone5_sodia.dts
@@ -116,7 +116,7 @@
 	flash0: n25q512a@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "n25q512a";
+		compatible = "micron,n25q512a", "jedec,spi-nor";
 		reg = <0>;
 		spi-max-frequency = <100000000>;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts
@@ -224,7 +224,7 @@
 	n25q128@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "n25q128";
+		compatible = "micron,n25q128", "jedec,spi-nor";
 		reg = <0>;		/* chip select */
 		spi-max-frequency = <100000000>;
 		m25p,fast-read;
@@ -241,7 +241,7 @@
 	n25q00@1 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "n25q00";
+		compatible = "micron,mt25qu02g", "jedec,spi-nor";
 		reg = <1>;		/* chip select */
 		spi-max-frequency = <100000000>;
 		m25p,fast-read;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/spear1340.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/spear1340.dtsi
@@ -136,9 +136,9 @@
 				reg = <0xb4100000 0x1000>;
 				interrupts = <0 105 0x4>;
 				status = "disabled";
-				dmas = <&dwdma0 12 0 1>,
-					<&dwdma0 13 1 0>;
-				dma-names = "tx", "rx";
+				dmas = <&dwdma0 13 0 1>,
+					<&dwdma0 12 1 0>;
+				dma-names = "rx", "tx";
 			};
 
 			thermal@e07008c4 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/spear13xx.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/spear13xx.dtsi
@@ -284,9 +284,9 @@
 				#size-cells = <0>;
 				interrupts = <0 31 0x4>;
 				status = "disabled";
-				dmas = <&dwdma0 4 0 0>,
-					<&dwdma0 5 0 0>;
-				dma-names = "tx", "rx";
+				dmas = <&dwdma0 5 0 0>,
+					<&dwdma0 4 0 0>;
+				dma-names = "rx", "tx";
 			};
 
 			rtc@e0580000 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/spear320-hmi.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/spear320-hmi.dts
@@ -242,7 +242,7 @@
 					irq-trigger = <0x1>;
 
 					stmpegpio: stmpe-gpio {
-						compatible = "stmpe,gpio";
+						compatible = "st,stmpe-gpio";
 						reg = <0>;
 						gpio-controller;
 						#gpio-cells = <2>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/spear3xx.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/spear3xx.dtsi
@@ -47,7 +47,7 @@
 		};
 
 		gmac: eth@e0800000 {
-			compatible = "st,spear600-gmac";
+			compatible = "snps,dwmac-3.40a";
 			reg = <0xe0800000 0x8000>;
 			interrupts = <23 22>;
 			interrupt-names = "macirq", "eth_wake_irq";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/spear600.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/spear600.dtsi
@@ -47,7 +47,7 @@
 			compatible = "arm,pl110", "arm,primecell";
 			reg = <0xfc200000 0x1000>;
 			interrupt-parent = <&vic1>;
-			interrupts = <12>;
+			interrupts = <13>;
 			status = "disabled";
 		};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/ste-nomadik-stn8815.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/ste-nomadik-stn8815.dtsi
@@ -755,14 +755,14 @@
 			status = "disabled";
 		};
 
-		vica: intc@10140000 {
+		vica: interrupt-controller@10140000 {
 			compatible = "arm,versatile-vic";
 			interrupt-controller;
 			#interrupt-cells = <1>;
 			reg = <0x10140000 0x20>;
 		};
 
-		vicb: intc@10140020 {
+		vicb: interrupt-controller@10140020 {
 			compatible = "arm,versatile-vic";
 			interrupt-controller;
 			#interrupt-cells = <1>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/stihxxx-b2120.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/stihxxx-b2120.dtsi
@@ -46,7 +46,7 @@
 			/* DAC */
 			format = "i2s";
 			mclk-fs = <256>;
-			frame-inversion = <1>;
+			frame-inversion;
 			cpu {
 				sound-dai = <&sti_uni_player2>;
 			};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/stm32429i-eval.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/stm32429i-eval.dts
@@ -112,17 +112,15 @@
 		};
 	};
 
-	gpio_keys {
+	gpio-keys {
 		compatible = "gpio-keys";
-		#address-cells = <1>;
-		#size-cells = <0>;
 		autorepeat;
-		button@0 {
+		button-0 {
 			label = "Wake up";
 			linux,code = <KEY_WAKEUP>;
 			gpios = <&gpioa 0 0>;
 		};
-		button@1 {
+		button-1 {
 			label = "Tamper";
 			linux,code = <KEY_RESTART>;
 			gpios = <&gpioc 13 0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/stm32746g-eval.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/stm32746g-eval.dts
@@ -81,12 +81,10 @@
 		};
 	};
 
-	gpio_keys {
+	gpio-keys {
 		compatible = "gpio-keys";
-		#address-cells = <1>;
-		#size-cells = <0>;
 		autorepeat;
-		button@0 {
+		button-0 {
 			label = "Wake up";
 			linux,code = <KEY_WAKEUP>;
 			gpios = <&gpioc 13 0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/stm32f429-disco.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/stm32f429-disco.dts
@@ -79,12 +79,10 @@
 		};
 	};
 
-	gpio_keys {
+	gpio-keys {
 		compatible = "gpio-keys";
-		#address-cells = <1>;
-		#size-cells = <0>;
 		autorepeat;
-		button@0 {
+		button-0 {
 			label = "User";
 			linux,code = <KEY_HOME>;
 			gpios = <&gpioa 0 0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/stm32f429.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/stm32f429.dtsi
@@ -283,8 +283,6 @@
 		};
 
 		timers13: timers@40001c00 {
-			#address-cells = <1>;
-			#size-cells = <0>;
 			compatible = "st,stm32-timers";
 			reg = <0x40001C00 0x400>;
 			clocks = <&rcc 0 STM32F4_APB1_CLOCK(TIM13)>;
@@ -299,8 +297,6 @@
 		};
 
 		timers14: timers@40002000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
 			compatible = "st,stm32-timers";
 			reg = <0x40002000 0x400>;
 			clocks = <&rcc 0 STM32F4_APB1_CLOCK(TIM14)>;
@@ -623,8 +619,6 @@
 		};
 
 		timers10: timers@40014400 {
-			#address-cells = <1>;
-			#size-cells = <0>;
 			compatible = "st,stm32-timers";
 			reg = <0x40014400 0x400>;
 			clocks = <&rcc 0 STM32F4_APB2_CLOCK(TIM10)>;
@@ -639,8 +633,6 @@
 		};
 
 		timers11: timers@40014800 {
-			#address-cells = <1>;
-			#size-cells = <0>;
 			compatible = "st,stm32-timers";
 			reg = <0x40014800 0x400>;
 			clocks = <&rcc 0 STM32F4_APB2_CLOCK(TIM11)>;
@@ -696,7 +688,7 @@
 			status = "disabled";
 		};
 
-		rcc: rcc@40023810 {
+		rcc: rcc@40023800 {
 			#reset-cells = <1>;
 			#clock-cells = <2>;
 			compatible = "st,stm32f42xx-rcc", "st,stm32-rcc";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/stm32f469-disco.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/stm32f469-disco.dts
@@ -76,6 +76,13 @@
 		regulator-max-microvolt = <3300000>;
 	};
 
+	vdd_dsi: vdd-dsi {
+		compatible = "regulator-fixed";
+		regulator-name = "vdd_dsi";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
 	soc {
 		dma-ranges = <0xc0000000 0x0 0x10000000>;
 	};
@@ -97,12 +104,10 @@
 		};
 	};
 
-	gpio_keys {
+	gpio-keys {
 		compatible = "gpio-keys";
-		#address-cells = <1>;
-		#size-cells = <0>;
 		autorepeat;
-		button@0 {
+		button-0 {
 			label = "User";
 			linux,code = <KEY_WAKEUP>;
 			gpios = <&gpioa 0 GPIO_ACTIVE_HIGH>;
@@ -155,6 +160,7 @@
 		compatible = "orisetech,otm8009a";
 		reg = <0>; /* dsi virtual channel (0..3) */
 		reset-gpios = <&gpioh 7 GPIO_ACTIVE_LOW>;
+		power-supply = <&vdd_dsi>;
 		status = "okay";
 
 		port {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/stm32f7-pinctrl.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/stm32f7-pinctrl.dtsi
@@ -284,6 +284,88 @@
 					slew-rate = <2>;
 				};
 			};
+
+			can1_pins_a: can1-0 {
+				pins1 {
+					pinmux = <STM32_PINMUX('A', 12, AF9)>; /* CAN1_TX */
+				};
+				pins2 {
+					pinmux = <STM32_PINMUX('A', 11, AF9)>; /* CAN1_RX */
+					bias-pull-up;
+				};
+			};
+
+			can1_pins_b: can1-1 {
+				pins1 {
+					pinmux = <STM32_PINMUX('B', 9, AF9)>; /* CAN1_TX */
+				};
+				pins2 {
+					pinmux = <STM32_PINMUX('B', 8, AF9)>; /* CAN1_RX */
+					bias-pull-up;
+				};
+			};
+
+			can1_pins_c: can1-2 {
+				pins1 {
+					pinmux = <STM32_PINMUX('D', 1, AF9)>; /* CAN1_TX */
+				};
+				pins2 {
+					pinmux = <STM32_PINMUX('D', 0, AF9)>; /* CAN1_RX */
+					bias-pull-up;
+
+				};
+			};
+
+			can1_pins_d: can1-3 {
+				pins1 {
+					pinmux = <STM32_PINMUX('H', 13, AF9)>; /* CAN1_TX */
+				};
+				pins2 {
+					pinmux = <STM32_PINMUX('H', 14, AF9)>; /* CAN1_RX */
+					bias-pull-up;
+
+				};
+			};
+
+			can2_pins_a: can2-0 {
+				pins1 {
+					pinmux = <STM32_PINMUX('B', 6, AF9)>; /* CAN2_TX */
+				};
+				pins2 {
+					pinmux = <STM32_PINMUX('B', 5, AF9)>; /* CAN2_RX */
+					bias-pull-up;
+				};
+			};
+
+			can2_pins_b: can2-1 {
+				pins1 {
+					pinmux = <STM32_PINMUX('B', 13, AF9)>; /* CAN2_TX */
+				};
+				pins2 {
+					pinmux = <STM32_PINMUX('B', 12, AF9)>; /* CAN2_RX */
+					bias-pull-up;
+				};
+			};
+
+			can3_pins_a: can3-0 {
+				pins1 {
+					pinmux = <STM32_PINMUX('A', 15, AF11)>; /* CAN3_TX */
+				};
+				pins2 {
+					pinmux = <STM32_PINMUX('A', 8, AF11)>; /* CAN3_RX */
+					bias-pull-up;
+				};
+			};
+
+			can3_pins_b: can3-1 {
+				pins1 {
+					pinmux = <STM32_PINMUX('B', 4, AF11)>;  /* CAN3_TX */
+				};
+				pins2 {
+					pinmux = <STM32_PINMUX('B', 3, AF11)>; /* CAN3_RX */
+					bias-pull-up;
+				};
+			};
 		};
 	};
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/stm32f746.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/stm32f746.dtsi
@@ -265,8 +265,6 @@
 		};
 
 		timers13: timers@40001c00 {
-			#address-cells = <1>;
-			#size-cells = <0>;
 			compatible = "st,stm32-timers";
 			reg = <0x40001C00 0x400>;
 			clocks = <&rcc 0 STM32F7_APB1_CLOCK(TIM13)>;
@@ -281,8 +279,6 @@
 		};
 
 		timers14: timers@40002000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
 			compatible = "st,stm32-timers";
 			reg = <0x40002000 0x400>;
 			clocks = <&rcc 0 STM32F7_APB1_CLOCK(TIM14)>;
@@ -366,9 +362,9 @@
 			status = "disabled";
 		};
 
-		i2c3: i2c@40005C00 {
+		i2c3: i2c@40005c00 {
 			compatible = "st,stm32f7-i2c";
-			reg = <0x40005C00 0x400>;
+			reg = <0x40005c00 0x400>;
 			interrupts = <72>,
 				     <73>;
 			resets = <&rcc STM32F7_APB1_RESET(I2C3)>;
@@ -533,8 +529,6 @@
 		};
 
 		timers10: timers@40014400 {
-			#address-cells = <1>;
-			#size-cells = <0>;
 			compatible = "st,stm32-timers";
 			reg = <0x40014400 0x400>;
 			clocks = <&rcc 0 STM32F7_APB2_CLOCK(TIM10)>;
@@ -549,8 +543,6 @@
 		};
 
 		timers11: timers@40014800 {
-			#address-cells = <1>;
-			#size-cells = <0>;
 			compatible = "st,stm32-timers";
 			reg = <0x40014800 0x400>;
 			clocks = <&rcc 0 STM32F7_APB2_CLOCK(TIM11)>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/stm32f769-disco.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/stm32f769-disco.dts
@@ -75,12 +75,10 @@
 		};
 	};
 
-	gpio_keys {
+	gpio-keys {
 		compatible = "gpio-keys";
-		#address-cells = <1>;
-		#size-cells = <0>;
 		autorepeat;
-		button@0 {
+		button-0 {
 			label = "User";
 			linux,code = <KEY_HOME>;
 			gpios = <&gpioa 0 GPIO_ACTIVE_HIGH>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/stm32h743.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/stm32h743.dtsi
@@ -438,8 +438,6 @@
 		};
 
 		lptimer4: timer@58002c00 {
-			#address-cells = <1>;
-			#size-cells = <0>;
 			compatible = "st,stm32-lptimer";
 			reg = <0x58002c00 0x400>;
 			clocks = <&rcc LPTIM4_CK>;
@@ -454,8 +452,6 @@
 		};
 
 		lptimer5: timer@58003000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
 			compatible = "st,stm32-lptimer";
 			reg = <0x58003000 0x400>;
 			clocks = <&rcc LPTIM5_CK>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/stm32mp157a-avenger96.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/stm32mp157a-avenger96.dts
@@ -91,6 +91,9 @@
 		#address-cells = <1>;
 		#size-cells = <0>;
 		compatible = "snps,dwmac-mdio";
+		reset-gpios = <&gpioz 2 GPIO_ACTIVE_LOW>;
+		reset-delay-us = <1000>;
+
 		phy0: ethernet-phy@7 {
 			reg = <7>;
 		};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/stm32mp157c.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/stm32mp157c.dtsi
@@ -515,7 +515,7 @@
 			compatible = "st,stm32-cec";
 			reg = <0x40016000 0x400>;
 			interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc CEC_K>, <&clk_lse>;
+			clocks = <&rcc CEC_K>, <&rcc CEC>;
 			clock-names = "cec", "hdmi-cec";
 			status = "disabled";
 		};
@@ -773,7 +773,7 @@
 				#sound-dai-cells = <0>;
 
 				compatible = "st,stm32-sai-sub-a";
-				reg = <0x4 0x1c>;
+				reg = <0x4 0x20>;
 				clocks = <&rcc SAI1_K>;
 				clock-names = "sai_ck";
 				dmas = <&dmamux1 87 0x400 0x01>;
@@ -783,7 +783,7 @@
 			sai1b: audio-controller@4400a024 {
 				#sound-dai-cells = <0>;
 				compatible = "st,stm32-sai-sub-b";
-				reg = <0x24 0x1c>;
+				reg = <0x24 0x20>;
 				clocks = <&rcc SAI1_K>;
 				clock-names = "sai_ck";
 				dmas = <&dmamux1 88 0x400 0x01>;
@@ -804,7 +804,7 @@
 			sai2a: audio-controller@4400b004 {
 				#sound-dai-cells = <0>;
 				compatible = "st,stm32-sai-sub-a";
-				reg = <0x4 0x1c>;
+				reg = <0x4 0x20>;
 				clocks = <&rcc SAI2_K>;
 				clock-names = "sai_ck";
 				dmas = <&dmamux1 89 0x400 0x01>;
@@ -814,7 +814,7 @@
 			sai2b: audio-controller@4400b024 {
 				#sound-dai-cells = <0>;
 				compatible = "st,stm32-sai-sub-b";
-				reg = <0x24 0x1c>;
+				reg = <0x24 0x20>;
 				clocks = <&rcc SAI2_K>;
 				clock-names = "sai_ck";
 				dmas = <&dmamux1 90 0x400 0x01>;
@@ -835,7 +835,7 @@
 			sai3a: audio-controller@4400c004 {
 				#sound-dai-cells = <0>;
 				compatible = "st,stm32-sai-sub-a";
-				reg = <0x04 0x1c>;
+				reg = <0x04 0x20>;
 				clocks = <&rcc SAI3_K>;
 				clock-names = "sai_ck";
 				dmas = <&dmamux1 113 0x400 0x01>;
@@ -845,7 +845,7 @@
 			sai3b: audio-controller@4400c024 {
 				#sound-dai-cells = <0>;
 				compatible = "st,stm32-sai-sub-b";
-				reg = <0x24 0x1c>;
+				reg = <0x24 0x20>;
 				clocks = <&rcc SAI3_K>;
 				clock-names = "sai_ck";
 				dmas = <&dmamux1 114 0x400 0x01>;
@@ -1191,7 +1191,7 @@
 			sai4a: audio-controller@50027004 {
 				#sound-dai-cells = <0>;
 				compatible = "st,stm32-sai-sub-a";
-				reg = <0x04 0x1c>;
+				reg = <0x04 0x20>;
 				clocks = <&rcc SAI4_K>;
 				clock-names = "sai_ck";
 				dmas = <&dmamux1 99 0x400 0x01>;
@@ -1201,7 +1201,7 @@
 			sai4b: audio-controller@50027024 {
 				#sound-dai-cells = <0>;
 				compatible = "st,stm32-sai-sub-b";
-				reg = <0x24 0x1c>;
+				reg = <0x24 0x20>;
 				clocks = <&rcc SAI4_K>;
 				clock-names = "sai_ck";
 				dmas = <&dmamux1 100 0x400 0x01>;
@@ -1311,12 +1311,6 @@
 			status = "disabled";
 		};
 
-		stmmac_axi_config_0: stmmac-axi-config {
-			snps,wr_osr_lmt = <0x7>;
-			snps,rd_osr_lmt = <0x7>;
-			snps,blen = <0 0 0 0 16 8 4>;
-		};
-
 		ethernet0: ethernet@5800a000 {
 			compatible = "st,stm32mp1-dwmac", "snps,dwmac-4.20a";
 			reg = <0x5800a000 0x2000>;
@@ -1339,6 +1333,12 @@
 			snps,axi-config = <&stmmac_axi_config_0>;
 			snps,tso;
 			status = "disabled";
+
+			stmmac_axi_config_0: stmmac-axi-config {
+				snps,wr_osr_lmt = <0x7>;
+				snps,rd_osr_lmt = <0x7>;
+				snps,blen = <0 0 0 0 16 8 4>;
+			};
 		};
 
 		usbh_ohci: usbh-ohci@5800c000 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/sun4i-a10.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -143,7 +143,7 @@
 			trips {
 				cpu_alert0: cpu-alert0 {
 					/* milliCelsius */
-					temperature = <850000>;
+					temperature = <85000>;
 					hysteresis = <2000>;
 					type = "passive";
 				};
@@ -198,7 +198,7 @@
 		default-pool {
 			compatible = "shared-dma-pool";
 			size = <0x6000000>;
-			alloc-ranges = <0x4a000000 0x6000000>;
+			alloc-ranges = <0x40000000 0x10000000>;
 			reusable;
 			linux,cma-default;
 		};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/sun5i.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/sun5i.dtsi
@@ -117,7 +117,7 @@
 		default-pool {
 			compatible = "shared-dma-pool";
 			size = <0x6000000>;
-			alloc-ranges = <0x4a000000 0x6000000>;
+			alloc-ranges = <0x40000000 0x10000000>;
 			reusable;
 			linux,cma-default;
 		};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/sun6i-a31-hummingbird.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/sun6i-a31-hummingbird.dts
@@ -154,7 +154,7 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&gmac_rgmii_pins>;
 	phy-handle = <&phy1>;
-	phy-mode = "rgmii";
+	phy-mode = "rgmii-id";
 	status = "okay";
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/sun7i-a20-bananapi-m1-plus.dts
@@ -130,7 +130,7 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&gmac_rgmii_pins>;
 	phy-handle = <&phy1>;
-	phy-mode = "rgmii";
+	phy-mode = "rgmii-id";
 	phy-supply = <&reg_gmac_3v3>;
 	status = "okay";
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/sun7i-a20-bananapi.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/sun7i-a20-bananapi.dts
@@ -132,7 +132,7 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&gmac_rgmii_pins>;
 	phy-handle = <&phy1>;
-	phy-mode = "rgmii";
+	phy-mode = "rgmii-id";
 	phy-supply = <&reg_gmac_3v3>;
 	status = "okay";
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/sun7i-a20-bananapro.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/sun7i-a20-bananapro.dts
@@ -110,7 +110,7 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&gmac_rgmii_pins>;
 	phy-handle = <&phy1>;
-	phy-mode = "rgmii";
+	phy-mode = "rgmii-id";
 	phy-supply = <&reg_gmac_3v3>;
 	status = "okay";
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/sun7i-a20-cubietruck.dts
@@ -151,7 +151,7 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&gmac_rgmii_pins>;
 	phy-handle = <&phy1>;
-	phy-mode = "rgmii";
+	phy-mode = "rgmii-id";
 	status = "okay";
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/sun7i-a20-olinuxino-lime2.dts
@@ -112,7 +112,7 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&gmac_rgmii_pins>;
 	phy-handle = <&phy1>;
-	phy-mode = "rgmii";
+	phy-mode = "rgmii-id";
 	status = "okay";
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/sun7i-a20-pcduino3-nano.dts
@@ -1,5 +1,5 @@
 /*
- * Copyright 2015 Adam Sampson <ats@offog.org>
+ * Copyright 2015-2020 Adam Sampson <ats@offog.org>
  *
  * This file is dual-licensed: you can use it either under the terms
  * of the GPL or the X11 license, at your option. Note that this dual
@@ -115,7 +115,7 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&gmac_rgmii_pins>;
 	phy-handle = <&phy1>;
-	phy-mode = "rgmii";
+	phy-mode = "rgmii-id";
 	status = "okay";
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/sun7i-a20.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -180,7 +180,7 @@
 		default-pool {
 			compatible = "shared-dma-pool";
 			size = <0x6000000>;
-			alloc-ranges = <0x4a000000 0x6000000>;
+			alloc-ranges = <0x40000000 0x10000000>;
 			reusable;
 			linux,cma-default;
 		};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/sun8i-a83t-bananapi-m3.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/sun8i-a83t-bananapi-m3.dts
@@ -131,7 +131,7 @@
 	pinctrl-0 = <&emac_rgmii_pins>;
 	phy-supply = <&reg_sw>;
 	phy-handle = <&rgmii_phy>;
-	phy-mode = "rgmii";
+	phy-mode = "rgmii-id";
 	allwinner,rx-delay-ps = <700>;
 	allwinner,tx-delay-ps = <700>;
 	status = "okay";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/sun8i-a83t-cubietruck-plus.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/sun8i-a83t-cubietruck-plus.dts
@@ -101,7 +101,7 @@
 		initial-mode = <1>; /* initialize in HUB mode */
 		disabled-ports = <1>;
 		intn-gpios = <&pio 7 5 GPIO_ACTIVE_HIGH>; /* PH5 */
-		reset-gpios = <&pio 4 16 GPIO_ACTIVE_HIGH>; /* PE16 */
+		reset-gpios = <&pio 4 16 GPIO_ACTIVE_LOW>; /* PE16 */
 		connect-gpios = <&pio 4 17 GPIO_ACTIVE_HIGH>; /* PE17 */
 		refclk-frequency = <19200000>;
 	};
@@ -183,7 +183,7 @@
 	pinctrl-0 = <&emac_rgmii_pins>;
 	phy-supply = <&reg_dldo4>;
 	phy-handle = <&rgmii_phy>;
-	phy-mode = "rgmii";
+	phy-mode = "rgmii-id";
 	status = "okay";
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts
@@ -358,8 +358,8 @@
 };
 
 &reg_dldo3 {
-	regulator-min-microvolt = <2800000>;
-	regulator-max-microvolt = <2800000>;
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
 	regulator-name = "vdd-csi";
 };
 
@@ -482,7 +482,8 @@
 };
 
 &usbphy {
-	usb0_id_det-gpios = <&pio 7 11 GPIO_ACTIVE_HIGH>; /* PH11 */
+	usb0_id_det-gpios = <&pio 7 11 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>; /* PH11 */
+	usb0_vbus_power-supply = <&usb_power_supply>;
 	usb0_vbus-supply = <&reg_drivevbus>;
 	usb1_vbus-supply = <&reg_vmain>;
 	usb2_vbus-supply = <&reg_vmain>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/sun8i-a83t.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/sun8i-a83t.dtsi
@@ -313,7 +313,7 @@
 
 		display_clocks: clock@1000000 {
 			compatible = "allwinner,sun8i-a83t-de2-clk";
-			reg = <0x01000000 0x100000>;
+			reg = <0x01000000 0x10000>;
 			clocks = <&ccu CLK_BUS_DE>,
 				 <&ccu CLK_PLL_DE>;
 			clock-names = "bus",
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/sun8i-h2-plus-bananapi-m2-zero.dts
@@ -31,7 +31,7 @@
 
 		pwr_led {
 			label = "bananapi-m2-zero:red:pwr";
-			gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>; /* PL10 */
+			gpios = <&r_pio 0 10 GPIO_ACTIVE_LOW>; /* PL10 */
 			default-state = "on";
 		};
 	};
@@ -62,6 +62,30 @@
 		states = <1100000 0>, <1300000 1>;
 	};
 
+	reg_vcc_dram: vcc-dram {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc-dram";
+		regulator-min-microvolt = <1500000>;
+		regulator-max-microvolt = <1500000>;
+		regulator-always-on;
+		regulator-boot-on;
+		enable-active-high;
+		gpio = <&r_pio 0 9 GPIO_ACTIVE_HIGH>; /* PL9 */
+		vin-supply = <&reg_vcc5v0>;
+	};
+
+	reg_vcc1v2: vcc1v2 {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc1v2";
+		regulator-min-microvolt = <1200000>;
+		regulator-max-microvolt = <1200000>;
+		regulator-always-on;
+		regulator-boot-on;
+		enable-active-high;
+		gpio = <&r_pio 0 8 GPIO_ACTIVE_HIGH>; /* PL8 */
+		vin-supply = <&reg_vcc5v0>;
+	};
+
 	wifi_pwrseq: wifi_pwrseq {
 		compatible = "mmc-pwrseq-simple";
 		reset-gpios = <&r_pio 0 7 GPIO_ACTIVE_LOW>; /* PL7 */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts
@@ -169,7 +169,7 @@
 	flash@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
-		compatible = "mxicy,mx25l1606e", "winbond,w25q128";
+		compatible = "mxicy,mx25l1606e", "jedec,spi-nor";
 		reg = <0>;
 		spi-max-frequency = <40000000>;
 	};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/sun8i-h3-orangepi-pc-plus.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/sun8i-h3-orangepi-pc-plus.dts
@@ -53,11 +53,6 @@
 	};
 };
 
-&emac {
-	/* LEDs changed to active high on the plus */
-	/delete-property/ allwinner,leds-active-low;
-};
-
 &mmc1 {
 	vmmc-supply = <&reg_vcc3v3>;
 	bus-width = <4>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/sun8i-h3-orangepi-plus2e.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/sun8i-h3-orangepi-plus2e.dts
@@ -67,7 +67,7 @@
 	pinctrl-0 = <&emac_rgmii_pins>;
 	phy-supply = <&reg_gmac_3v3>;
 	phy-handle = <&ext_rgmii_phy>;
-	phy-mode = "rgmii";
+	phy-mode = "rgmii-id";
 	status = "okay";
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/sun8i-h3.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/sun8i-h3.dtsi
@@ -80,7 +80,7 @@
 			#cooling-cells = <2>;
 		};
 
-		cpu@1 {
+		cpu1: cpu@1 {
 			compatible = "arm,cortex-a7";
 			device_type = "cpu";
 			reg = <1>;
@@ -90,7 +90,7 @@
 			#cooling-cells = <2>;
 		};
 
-		cpu@2 {
+		cpu2: cpu@2 {
 			compatible = "arm,cortex-a7";
 			device_type = "cpu";
 			reg = <2>;
@@ -100,7 +100,7 @@
 			#cooling-cells = <2>;
 		};
 
-		cpu@3 {
+		cpu3: cpu@3 {
 			compatible = "arm,cortex-a7";
 			device_type = "cpu";
 			reg = <3>;
@@ -111,6 +111,15 @@
 		};
 	};
 
+	pmu {
+		compatible = "arm,cortex-a7-pmu";
+		interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
+	};
+
 	timer {
 		compatible = "arm,armv7-timer";
 		interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts
@@ -129,7 +129,7 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&gmac_rgmii_pins>;
 	phy-handle = <&phy1>;
-	phy-mode = "rgmii";
+	phy-mode = "rgmii-id";
 	phy-supply = <&reg_dc1sw>;
 	status = "okay";
 };
@@ -223,16 +223,16 @@
 };
 
 &reg_dc1sw {
-	regulator-min-microvolt = <3000000>;
-	regulator-max-microvolt = <3000000>;
+	regulator-min-microvolt = <3300000>;
+	regulator-max-microvolt = <3300000>;
 	regulator-name = "vcc-gmac-phy";
 };
 
 &reg_dcdc1 {
 	regulator-always-on;
-	regulator-min-microvolt = <3000000>;
-	regulator-max-microvolt = <3000000>;
-	regulator-name = "vcc-3v0";
+	regulator-min-microvolt = <3300000>;
+	regulator-max-microvolt = <3300000>;
+	regulator-name = "vcc-3v3";
 };
 
 &reg_dcdc2 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/sun8i-r40.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/sun8i-r40.dtsi
@@ -118,7 +118,7 @@
 		display_clocks: clock@1000000 {
 			compatible = "allwinner,sun8i-r40-de2-clk",
 				     "allwinner,sun8i-h3-de2-clk";
-			reg = <0x01000000 0x100000>;
+			reg = <0x01000000 0x10000>;
 			clocks = <&ccu CLK_BUS_DE>,
 				 <&ccu CLK_DE>;
 			clock-names = "bus",
@@ -266,6 +266,16 @@
 			#phy-cells = <1>;
 		};
 
+		ahci: sata@1c18000 {
+			compatible = "allwinner,sun8i-r40-ahci";
+			reg = <0x01c18000 0x1000>;
+			interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_SATA>, <&ccu CLK_SATA>;
+			resets = <&ccu RST_BUS_SATA>;
+			reset-names = "ahci";
+			status = "disabled";
+		};
+
 		ehci1: usb@1c19000 {
 			compatible = "allwinner,sun8i-r40-ehci", "generic-ehci";
 			reg = <0x01c19000 0x100>;
@@ -557,17 +567,6 @@
 			#size-cells = <0>;
 		};
 
-		ahci: sata@1c18000 {
-			compatible = "allwinner,sun8i-r40-ahci";
-			reg = <0x01c18000 0x1000>;
-			interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&ccu CLK_BUS_SATA>, <&ccu CLK_SATA>;
-			resets = <&ccu RST_BUS_SATA>;
-			reset-names = "ahci";
-			status = "disabled";
-
-		};
-
 		gmac: ethernet@1c50000 {
 			compatible = "allwinner,sun8i-r40-gmac";
 			syscon = <&ccu>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/sun8i-v3s.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/sun8i-v3s.dtsi
@@ -105,7 +105,7 @@
 
 		display_clocks: clock@1000000 {
 			compatible = "allwinner,sun8i-v3s-de2-clk";
-			reg = <0x01000000 0x100000>;
+			reg = <0x01000000 0x10000>;
 			clocks = <&ccu CLK_BUS_DE>,
 				 <&ccu CLK_DE>;
 			clock-names = "bus",
@@ -423,7 +423,7 @@
 		gic: interrupt-controller@1c81000 {
 			compatible = "arm,gic-400";
 			reg = <0x01c81000 0x1000>,
-			      <0x01c82000 0x1000>,
+			      <0x01c82000 0x2000>,
 			      <0x01c84000 0x2000>,
 			      <0x01c86000 0x2000>;
 			interrupt-controller;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/sun8i-v40-bananapi-m2-berry.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/sun8i-v40-bananapi-m2-berry.dts
@@ -120,7 +120,7 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&gmac_rgmii_pins>;
 	phy-handle = <&phy1>;
-	phy-mode = "rgmii";
+	phy-mode = "rgmii-id";
 	phy-supply = <&reg_dc1sw>;
 	status = "okay";
 };
@@ -198,16 +198,16 @@
 };
 
 &reg_dc1sw {
-	regulator-min-microvolt = <3000000>;
-	regulator-max-microvolt = <3000000>;
+	regulator-min-microvolt = <3300000>;
+	regulator-max-microvolt = <3300000>;
 	regulator-name = "vcc-gmac-phy";
 };
 
 &reg_dcdc1 {
 	regulator-always-on;
-	regulator-min-microvolt = <3000000>;
-	regulator-max-microvolt = <3000000>;
-	regulator-name = "vcc-3v0";
+	regulator-min-microvolt = <3300000>;
+	regulator-max-microvolt = <3300000>;
+	regulator-name = "vcc-3v3";
 };
 
 &reg_dcdc2 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/sun9i-a80-cubieboard4.dts
@@ -129,7 +129,7 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&gmac_rgmii_pins>;
 	phy-handle = <&phy1>;
-	phy-mode = "rgmii";
+	phy-mode = "rgmii-id";
 	phy-supply = <&reg_cldo1>;
 	status = "okay";
 };
@@ -280,8 +280,8 @@
 
 			reg_dcdc5: dcdc5 {
 				regulator-always-on;
-				regulator-min-microvolt = <1425000>;
-				regulator-max-microvolt = <1575000>;
+				regulator-min-microvolt = <1450000>;
+				regulator-max-microvolt = <1550000>;
 				regulator-name = "vcc-dram";
 			};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/sun9i-a80-optimus.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/sun9i-a80-optimus.dts
@@ -124,7 +124,7 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&gmac_rgmii_pins>;
 	phy-handle = <&phy1>;
-	phy-mode = "rgmii";
+	phy-mode = "rgmii-id";
 	phy-supply = <&reg_cldo1>;
 	status = "okay";
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/suniv-f1c100s.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/suniv-f1c100s.dtsi
@@ -104,8 +104,10 @@
 
 		wdt: watchdog@1c20ca0 {
 			compatible = "allwinner,suniv-f1c100s-wdt",
-				     "allwinner,sun4i-a10-wdt";
+				     "allwinner,sun6i-a31-wdt";
 			reg = <0x01c20ca0 0x20>;
+			interrupts = <16>;
+			clocks = <&osc32k>;
 		};
 
 		uart0: serial@1c25000 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/sunxi-bananapi-m2-plus-v1.2.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/sunxi-bananapi-m2-plus-v1.2.dtsi
@@ -16,15 +16,27 @@
 		regulator-type = "voltage";
 		regulator-boot-on;
 		regulator-always-on;
-		regulator-min-microvolt = <1100000>;
-		regulator-max-microvolt = <1300000>;
+		regulator-min-microvolt = <1108475>;
+		regulator-max-microvolt = <1308475>;
 		regulator-ramp-delay = <50>; /* 4ms */
 		gpios = <&r_pio 0 1 GPIO_ACTIVE_HIGH>; /* PL1 */
 		gpios-states = <0x1>;
-		states = <1100000 0>, <1300000 1>;
+		states = <1108475 0>, <1308475 1>;
 	};
 };
 
 &cpu0 {
 	cpu-supply = <&reg_vdd_cpux>;
 };
+
+&cpu1 {
+	cpu-supply = <&reg_vdd_cpux>;
+};
+
+&cpu2 {
+	cpu-supply = <&reg_vdd_cpux>;
+};
+
+&cpu3 {
+	cpu-supply = <&reg_vdd_cpux>;
+};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/sunxi-bananapi-m2-plus.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/sunxi-bananapi-m2-plus.dtsi
@@ -126,7 +126,7 @@
 	pinctrl-0 = <&emac_rgmii_pins>;
 	phy-supply = <&reg_gmac_3v3>;
 	phy-handle = <&ext_rgmii_phy>;
-	phy-mode = "rgmii";
+	phy-mode = "rgmii-id";
 
 	status = "okay";
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/sunxi-h3-h5.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/sunxi-h3-h5.dtsi
@@ -113,7 +113,7 @@
 
 		display_clocks: clock@1000000 {
 			/* compatible is in per SoC .dtsi file */
-			reg = <0x01000000 0x100000>;
+			reg = <0x01000000 0x10000>;
 			clocks = <&ccu CLK_BUS_DE>,
 				 <&ccu CLK_DE>;
 			clock-names = "bus",
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/tegra20-tamonten.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/tegra20-tamonten.dtsi
@@ -183,10 +183,11 @@
 			};
 			conf_ata {
 				nvidia,pins = "ata", "atb", "atc", "atd", "ate",
-					"cdev1", "cdev2", "dap1", "dtb", "gma",
-					"gmb", "gmc", "gmd", "gme", "gpu7",
-					"gpv", "i2cp", "pta", "rm", "slxa",
-					"slxk", "spia", "spib", "uac";
+					"cdev1", "cdev2", "dap1", "dtb", "dtf",
+					"gma", "gmb", "gmc", "gmd", "gme", "gpu7",
+					"gpv", "i2cp", "irrx", "irtx", "pta",
+					"rm", "slxa", "slxk", "spia", "spib",
+					"uac";
 				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
 				nvidia,tristate = <TEGRA_PIN_DISABLE>;
 			};
@@ -202,7 +203,7 @@
 			};
 			conf_crtp {
 				nvidia,pins = "crtp", "dap2", "dap3", "dap4",
-					"dtc", "dte", "dtf", "gpu", "sdio1",
+					"dtc", "dte", "gpu", "sdio1",
 					"slxc", "slxd", "spdi", "spdo", "spig",
 					"uda";
 				nvidia,pull = <TEGRA_PIN_PULL_NONE>;
@@ -211,7 +212,7 @@
 			conf_ddc {
 				nvidia,pins = "ddc", "dta", "dtd", "kbca",
 					"kbcb", "kbcc", "kbcd", "kbce", "kbcf",
-					"sdc";
+					"sdc", "uad", "uca";
 				nvidia,pull = <TEGRA_PIN_PULL_UP>;
 				nvidia,tristate = <TEGRA_PIN_DISABLE>;
 			};
@@ -221,10 +222,9 @@
 					"lvp0", "owc", "sdb";
 				nvidia,tristate = <TEGRA_PIN_ENABLE>;
 			};
-			conf_irrx {
-				nvidia,pins = "irrx", "irtx", "sdd", "spic",
-					"spie", "spih", "uaa", "uab", "uad",
-					"uca", "ucb";
+			conf_sdd {
+				nvidia,pins = "sdd", "spic", "spie", "spih",
+					"uaa", "uab", "ucb";
 				nvidia,pull = <TEGRA_PIN_PULL_UP>;
 				nvidia,tristate = <TEGRA_PIN_ENABLE>;
 			};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/uniphier-pxs2.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/uniphier-pxs2.dtsi
@@ -571,7 +571,7 @@
 			clocks = <&sys_clk 6>;
 			reset-names = "ether";
 			resets = <&sys_rst 6>;
-			phy-mode = "rgmii";
+			phy-mode = "rgmii-id";
 			local-mac-address = [00 00 00 00 00 00];
 			socionext,syscon-phy-mode = <&soc_glue 0>;
 
@@ -585,8 +585,8 @@
 			compatible = "socionext,uniphier-dwc3", "snps,dwc3";
 			status = "disabled";
 			reg = <0x65a00000 0xcd00>;
-			interrupt-names = "host", "peripheral";
-			interrupts = <0 134 4>, <0 135 4>;
+			interrupt-names = "dwc_usb3";
+			interrupts = <0 134 4>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_usb0>, <&pinctrl_usb2>;
 			clock-names = "ref", "bus_early", "suspend";
@@ -681,8 +681,8 @@
 			compatible = "socionext,uniphier-dwc3", "snps,dwc3";
 			status = "disabled";
 			reg = <0x65c00000 0xcd00>;
-			interrupt-names = "host", "peripheral";
-			interrupts = <0 137 4>, <0 138 4>;
+			interrupt-names = "dwc_usb3";
+			interrupts = <0 137 4>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_usb1>, <&pinctrl_usb3>;
 			clock-names = "ref", "bus_early", "suspend";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/versatile-ab.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/versatile-ab.dts
@@ -195,16 +195,15 @@
 		#size-cells = <1>;
 		ranges;
 
-		vic: intc@10140000 {
+		vic: interrupt-controller@10140000 {
 			compatible = "arm,versatile-vic";
 			interrupt-controller;
 			#interrupt-cells = <1>;
 			reg = <0x10140000 0x1000>;
-			clear-mask = <0xffffffff>;
 			valid-mask = <0xffffffff>;
 		};
 
-		sic: intc@10003000 {
+		sic: interrupt-controller@10003000 {
 			compatible = "arm,versatile-sic";
 			interrupt-controller;
 			#interrupt-cells = <1>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/versatile-pb.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/versatile-pb.dts
@@ -7,7 +7,7 @@
 
 	amba {
 		/* The Versatile PB is using more SIC IRQ lines than the AB */
-		sic: intc@10003000 {
+		sic: interrupt-controller@10003000 {
 			clear-mask = <0xffffffff>;
 			/*
 			 * Valid interrupt lines mask according to
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
@@ -31,7 +31,7 @@
 			#interrupt-cells = <1>;
 			ranges;
 
-			nor_flash: flash@0,00000000 {
+			nor_flash: flash@0 {
 				compatible = "arm,vexpress-flash", "cfi-flash";
 				reg = <0 0x00000000 0x04000000>,
 				      <4 0x00000000 0x04000000>;
@@ -41,13 +41,13 @@
 				};
 			};
 
-			psram@1,00000000 {
+			psram@100000000 {
 				compatible = "arm,vexpress-psram", "mtd-ram";
 				reg = <1 0x00000000 0x02000000>;
 				bank-width = <4>;
 			};
 
-			ethernet@2,02000000 {
+			ethernet@202000000 {
 				compatible = "smsc,lan9118", "smsc,lan9115";
 				reg = <2 0x02000000 0x10000>;
 				interrupts = <15>;
@@ -59,14 +59,14 @@
 				vddvario-supply = <&v2m_fixed_3v3>;
 			};
 
-			usb@2,03000000 {
+			usb@203000000 {
 				compatible = "nxp,usb-isp1761";
 				reg = <2 0x03000000 0x20000>;
 				interrupts = <16>;
 				port1-otg;
 			};
 
-			iofpga@3,00000000 {
+			iofpga@300000000 {
 				compatible = "simple-bus";
 				#address-cells = <1>;
 				#size-cells = <1>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/vexpress-v2p-ca5s.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/vexpress-v2p-ca5s.dts
@@ -132,6 +132,7 @@
 		reg = <0x2c0f0000 0x1000>;
 		interrupts = <0 84 4>;
 		cache-level = <2>;
+		cache-unified;
 	};
 
 	pmu {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/vfxxx.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/vfxxx.dtsi
@@ -495,7 +495,7 @@
 			};
 
 			ocotp: ocotp@400a5000 {
-				compatible = "fsl,vf610-ocotp";
+				compatible = "fsl,vf610-ocotp", "syscon";
 				reg = <0x400a5000 0x1000>;
 				clocks = <&clks VF610_CLK_OCOTP>;
 			};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/zynq-7000.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/zynq-7000.dtsi
@@ -1,6 +1,9 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0+
 /*
- * Copyright (C) 2011 - 2014 Xilinx
+ * Xilinx Zynq 7000 DTSI
+ * Describes the hardware common to all Zynq 7000-based boards.
+ *
+ *  Copyright (C) 2011 - 2015 Xilinx
  */
 
 / {
@@ -59,7 +62,41 @@
 		regulator-always-on;
 	};
 
+	replicator {
+		compatible = "arm,coresight-static-replicator";
+		clocks = <&clkc 27>, <&clkc 46>, <&clkc 47>;
+		clock-names = "apb_pclk", "dbg_trc", "dbg_apb";
+
+		out-ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			/* replicator output ports */
+			port@0 {
+				reg = <0>;
+				replicator_out_port0: endpoint {
+					remote-endpoint = <&tpiu_in_port>;
+				};
+			};
+			port@1 {
+				reg = <1>;
+				replicator_out_port1: endpoint {
+					remote-endpoint = <&etb_in_port>;
+				};
+			};
+		};
+		in-ports {
+			/* replicator input port */
+			port {
+				replicator_in_port0: endpoint {
+					remote-endpoint = <&funnel_out_port>;
+				};
+			};
+		};
+	};
+
 	amba: amba {
+		u-boot,dm-pre-reloc;
 		compatible = "simple-bus";
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -155,6 +192,13 @@
 			reg = <0xf8006000 0x1000>;
 		};
 
+		ocmc: ocmc@f800c000 {
+			compatible = "xlnx,zynq-ocmc-1.0";
+			interrupt-parent = <&intc>;
+			interrupts = <0 3 4>;
+			reg = <0xf800c000 0x1000>;
+		};
+
 		uart0: serial@e0000000 {
 			compatible = "xlnx,xuartps", "cdns,uart-r1p8";
 			status = "disabled";
@@ -197,6 +241,45 @@
 			#size-cells = <0>;
 		};
 
+		qspi: spi@e000d000 {
+			clock-names = "ref_clk", "pclk";
+			clocks = <&clkc 10>, <&clkc 43>;
+			compatible = "xlnx,zynq-qspi-1.0";
+			status = "disabled";
+			interrupt-parent = <&intc>;
+			interrupts = <0 19 4>;
+			reg = <0xe000d000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
+		smcc: memory-controller@e000e000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			status = "disabled";
+			clock-names = "memclk", "apb_pclk";
+			clocks = <&clkc 11>, <&clkc 44>;
+			compatible = "arm,pl353-smc-r2p1", "arm,primecell";
+			interrupt-parent = <&intc>;
+			interrupts = <0 18 4>;
+			ranges ;
+			reg = <0xe000e000 0x1000>;
+			nand0: flash@e1000000 {
+				status = "disabled";
+				compatible = "arm,pl353-nand-r2p1";
+				reg = <0xe1000000 0x1000000>;
+				#address-cells = <1>;
+				#size-cells = <1>;
+			};
+			nor0: flash@e2000000 {
+				status = "disabled";
+				compatible = "cfi-flash";
+				reg = <0xe2000000 0x2000000>;
+				#address-cells = <1>;
+				#size-cells = <1>;
+			};
+		};
+
 		gem0: ethernet@e000b000 {
 			compatible = "cdns,zynq-gem", "cdns,gem";
 			reg = <0xe000b000 0x1000>;
@@ -240,15 +323,17 @@
 		};
 
 		slcr: slcr@f8000000 {
+			u-boot,dm-pre-reloc;
 			#address-cells = <1>;
 			#size-cells = <1>;
 			compatible = "xlnx,zynq-slcr", "syscon", "simple-mfd";
 			reg = <0xF8000000 0x1000>;
 			ranges;
 			clkc: clkc@100 {
+				u-boot,dm-pre-reloc;
 				#clock-cells = <1>;
 				compatible = "xlnx,ps7-clkc";
-				fclk-enable = <0>;
+				fclk-enable = <0xf>;
 				clock-output-names = "armpll", "ddrpll", "iopll", "cpu_6or4x",
 						"cpu_3or2x", "cpu_2x", "cpu_1x", "ddr2x", "ddr3x",
 						"dci", "lqspi", "smc", "pcap", "gem0", "gem1",
@@ -297,14 +382,19 @@
 
 		devcfg: devcfg@f8007000 {
 			compatible = "xlnx,zynq-devcfg-1.0";
-			reg = <0xf8007000 0x100>;
 			interrupt-parent = <&intc>;
 			interrupts = <0 8 4>;
-			clocks = <&clkc 12>;
-			clock-names = "ref_clk";
+			reg = <0xf8007000 0x100>;
+			clocks = <&clkc 12>, <&clkc 15>, <&clkc 16>, <&clkc 17>, <&clkc 18>;
+			clock-names = "ref_clk", "fclk0", "fclk1", "fclk2", "fclk3";
 			syscon = <&slcr>;
 		};
 
+		efuse: efuse@f800d000 {
+			compatible = "xlnx,zynq-efuse";
+			reg = <0xf800d000 0x20>;
+		};
+
 		global_timer: timer@f8f00200 {
 			compatible = "arm,cortex-a9-global-timer";
 			reg = <0xf8f00200 0x20>;
@@ -365,5 +455,107 @@
 			reg = <0xf8005000 0x1000>;
 			timeout-sec = <10>;
 		};
+
+		etb@f8801000 {
+			compatible = "arm,coresight-etb10", "arm,primecell";
+			reg = <0xf8801000 0x1000>;
+			clocks = <&clkc 27>, <&clkc 46>, <&clkc 47>;
+			clock-names = "apb_pclk", "dbg_trc", "dbg_apb";
+			in-ports {
+				port {
+					etb_in_port: endpoint {
+						remote-endpoint = <&replicator_out_port1>;
+					};
+				};
+			};
+		};
+
+		tpiu@f8803000 {
+			compatible = "arm,coresight-tpiu", "arm,primecell";
+			reg = <0xf8803000 0x1000>;
+			clocks = <&clkc 27>, <&clkc 46>, <&clkc 47>;
+			clock-names = "apb_pclk", "dbg_trc", "dbg_apb";
+			in-ports {
+				port {
+					tpiu_in_port: endpoint {
+						remote-endpoint = <&replicator_out_port0>;
+					};
+				};
+			};
+		};
+
+		funnel@f8804000 {
+			compatible = "arm,coresight-static-funnel", "arm,primecell";
+			reg = <0xf8804000 0x1000>;
+			clocks = <&clkc 27>, <&clkc 46>, <&clkc 47>;
+			clock-names = "apb_pclk", "dbg_trc", "dbg_apb";
+
+			/* funnel output ports */
+			out-ports {
+				port {
+					funnel_out_port: endpoint {
+						remote-endpoint =
+							<&replicator_in_port0>;
+					};
+				};
+			};
+
+			in-ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				/* funnel input ports */
+				port@0 {
+					reg = <0>;
+					funnel0_in_port0: endpoint {
+						remote-endpoint = <&ptm0_out_port>;
+					};
+				};
+
+				port@1 {
+					reg = <1>;
+					funnel0_in_port1: endpoint {
+						remote-endpoint = <&ptm1_out_port>;
+					};
+				};
+
+				port@2 {
+					reg = <2>;
+					funnel0_in_port2: endpoint {
+					};
+				};
+				/* The other input ports are not connect to anything */
+			};
+		};
+
+		ptm@f889c000 {
+			compatible = "arm,coresight-etm3x", "arm,primecell";
+			reg = <0xf889c000 0x1000>;
+			clocks = <&clkc 27>, <&clkc 46>, <&clkc 47>;
+			clock-names = "apb_pclk", "dbg_trc", "dbg_apb";
+			cpu = <&cpu0>;
+			out-ports {
+				port {
+					ptm0_out_port: endpoint {
+						remote-endpoint = <&funnel0_in_port0>;
+					};
+				};
+			};
+		};
+
+		ptm@f889d000 {
+			compatible = "arm,coresight-etm3x", "arm,primecell";
+			reg = <0xf889d000 0x1000>;
+			clocks = <&clkc 27>, <&clkc 46>, <&clkc 47>;
+			clock-names = "apb_pclk", "dbg_trc", "dbg_apb";
+			cpu = <&cpu1>;
+			out-ports {
+				port {
+					ptm1_out_port: endpoint {
+						remote-endpoint = <&funnel0_in_port1>;
+					};
+				};
+			};
+		};
 	};
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/zynq-cc108.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/zynq-cc108.dts
@@ -18,6 +18,7 @@
 	aliases {
 		ethernet0 = &gem0;
 		serial0 = &uart0;
+		spi0 = &qspi;
 	};
 
 	chosen {
@@ -52,6 +53,45 @@
 	};
 };
 
+&qspi {
+	status = "okay";
+	is-dual = <0>;
+	num-cs = <1>;
+	flash@0 { /* 16 MB */
+		compatible = "n25q128a11";
+		reg = <0x0>;
+		spi-max-frequency = <50000000>;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <4>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		partition@0 {
+			label = "qspi-fsbl-uboot-bs";
+			reg = <0x0 0x400000>; /* 4MB */
+		};
+		partition@400000 {
+			label = "qspi-linux";
+			reg = <0x400000 0x400000>; /* 4MB */
+		};
+		partition@800000 {
+			label = "qspi-rootfs";
+			reg = <0x800000 0x400000>; /* 4MB */
+		};
+		partition@c00000 {
+			label = "qspi-devicetree";
+			reg = <0xc00000 0x100000>; /* 1MB */
+		};
+		partition@d00000 {
+			label = "qspi-scratch";
+			reg = <0xd00000 0x200000>; /* 2MB */
+		};
+		partition@f00000 {
+			label = "qspi-uboot-env";
+			reg = <0xf00000 0x100000>; /* 1MB */
+		};
+	};
+};
+
 &sdhci1 {
 	status = "okay";
 	broken-cd ;
@@ -59,6 +99,7 @@
 };
 
 &uart0 {
+	u-boot,dm-pre-reloc;
 	status = "okay";
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/zynq-zc702.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/zynq-zc702.dts
@@ -1,6 +1,6 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0+
 /*
- *  Copyright (C) 2011 - 2014 Xilinx
+ *  Copyright (C) 2011 - 2015 Xilinx
  *  Copyright (C) 2012 National Instruments Corp.
  */
 /dts-v1/;
@@ -14,7 +14,9 @@
 		ethernet0 = &gem0;
 		i2c0 = &i2c0;
 		serial0 = &uart1;
+		spi0 = &qspi;
 		mmc0 = &sdhci0;
+		usb0 = &usb0;
 	};
 
 	memory@0 {
@@ -56,9 +58,12 @@
 		};
 	};
 
-	usb_phy0: phy0 {
-		compatible = "usb-nop-xceiv";
+	usb_phy0: phy0@e0002000 {
+		compatible = "ulpi-phy";
 		#phy-cells = <0>;
+		reg = <0xe0002000 0x1000>;
+		view-port = <0x0170>;
+		drv-vbus;
 	};
 };
 
@@ -85,6 +90,8 @@
 	phy-handle = <&ethernet_phy>;
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_gem0_default>;
+	phy-reset-gpio = <&gpio0 11 0>;
+	phy-reset-active-low;
 
 	ethernet_phy: ethernet-phy@7 {
 		reg = <7>;
@@ -100,8 +107,11 @@
 &i2c0 {
 	status = "okay";
 	clock-frequency = <400000>;
-	pinctrl-names = "default";
+	pinctrl-names = "default", "gpio";
 	pinctrl-0 = <&pinctrl_i2c0_default>;
+	pinctrl-1 = <&pinctrl_i2c0_gpio>;
+	scl-gpios = <&gpio0 50 0>;
+	sda-gpios = <&gpio0 51 0>;
 
 	i2c-mux@74 {
 		compatible = "nxp,pca9548";
@@ -292,6 +302,19 @@
 		};
 	};
 
+	pinctrl_i2c0_gpio: i2c0-gpio {
+		mux {
+			groups = "gpio0_50_grp", "gpio0_51_grp";
+			function = "gpio0";
+		};
+
+		conf {
+			groups = "gpio0_50_grp", "gpio0_51_grp";
+			slew-rate = <0>;
+			io-standard = <1>;
+		};
+	};
+
 	pinctrl_sdhci0_default: sdhci0-default {
 		mux {
 			groups = "sdio0_2_grp";
@@ -380,13 +403,51 @@
 	};
 };
 
+&qspi {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+	is-dual = <0>;
+	num-cs = <1>;
+	flash@0 {
+		compatible = "n25q128a11";
+		reg = <0x0>;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <4>;
+		spi-max-frequency = <50000000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		partition@0 {
+			label = "qspi-fsbl-uboot";
+			reg = <0x0 0x100000>;
+		};
+		partition@100000 {
+			label = "qspi-linux";
+			reg = <0x100000 0x500000>;
+		};
+		partition@600000 {
+			label = "qspi-device-tree";
+			reg = <0x600000 0x20000>;
+		};
+		partition@620000 {
+			label = "qspi-rootfs";
+			reg = <0x620000 0x5E0000>;
+		};
+		partition@c00000 {
+			label = "qspi-bitstream";
+			reg = <0xC00000 0x400000>;
+		};
+	};
+};
+
 &sdhci0 {
+	u-boot,dm-pre-reloc;
 	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_sdhci0_default>;
 };
 
 &uart1 {
+	u-boot,dm-pre-reloc;
 	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_uart1_default>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/zynq-zc706.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/zynq-zc706.dts
@@ -1,6 +1,6 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0+
 /*
- *  Copyright (C) 2011 - 2014 Xilinx
+ *  Copyright (C) 2011 - 2015 Xilinx
  *  Copyright (C) 2012 National Instruments Corp.
  */
 /dts-v1/;
@@ -14,6 +14,7 @@
 		ethernet0 = &gem0;
 		i2c0 = &i2c0;
 		serial0 = &uart1;
+		spi0 = &qspi;
 		mmc0 = &sdhci0;
 	};
 
@@ -27,9 +28,12 @@
 		stdout-path = "serial0:115200n8";
 	};
 
-	usb_phy0: phy0 {
-		compatible = "usb-nop-xceiv";
+	usb_phy0: phy0@e0002000 {
+		compatible = "ulpi-phy";
 		#phy-cells = <0>;
+		reg = <0xe0002000 0x1000>;
+		view-port = <0x0170>;
+		drv-vbus;
 	};
 };
 
@@ -303,13 +307,51 @@
 	};
 };
 
+&qspi {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+	is-dual = <1>;
+	num-cs = <1>;
+	flash@0 {
+		compatible = "n25q128a11";
+		reg = <0x0>;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <4>;
+		spi-max-frequency = <50000000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		partition@0 {
+			label = "qspi-fsbl-uboot";
+			reg = <0x0 0x100000>;
+		};
+		partition@100000 {
+			label = "qspi-linux";
+			reg = <0x100000 0x500000>;
+		};
+		partition@600000 {
+			label = "qspi-device-tree";
+			reg = <0x600000 0x20000>;
+		};
+		partition@620000 {
+			label = "qspi-rootfs";
+			reg = <0x620000 0x5E0000>;
+		};
+		partition@c00000 {
+			label = "qspi-bitstream";
+			reg = <0xC00000 0x400000>;
+		};
+	};
+};
+
 &sdhci0 {
+	u-boot,dm-pre-reloc;
 	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_sdhci0_default>;
 };
 
 &uart1 {
+	u-boot,dm-pre-reloc;
 	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_uart1_default>;
@@ -322,3 +364,7 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_usb0_default>;
 };
+
+&watchdog0 {
+	reset-on-timeout;
+};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/zynq-zc770-xm010.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/zynq-zc770-xm010.dts
@@ -15,6 +15,7 @@
 		ethernet0 = &gem0;
 		i2c0 = &i2c0;
 		serial0 = &uart1;
+		spi0 = &qspi;
 		spi1 = &spi1;
 	};
 
@@ -57,7 +58,41 @@
 		compatible = "atmel,24c02";
 		reg = <0x52>;
 	};
+};
 
+&qspi {
+	status = "okay";
+	is-dual = <0>;
+	num-cs = <1>;
+	flash@0 {
+		compatible = "n25q128a11";
+		reg = <0x0>;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <4>;
+		spi-max-frequency = <50000000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		partition@0 {
+			label = "qspi-fsbl-uboot";
+			reg = <0x0 0x100000>;
+		};
+		partition@100000 {
+			label = "qspi-linux";
+			reg = <0x100000 0x500000>;
+		};
+		partition@600000 {
+			label = "qspi-device-tree";
+			reg = <0x600000 0x20000>;
+		};
+		partition@620000 {
+			label = "qspi-rootfs";
+			reg = <0x620000 0x5E0000>;
+		};
+		partition@c00000 {
+			label = "qspi-bitstream";
+			reg = <0xC00000 0x400000>;
+		};
+	};
 };
 
 &sdhci0 {
@@ -85,6 +120,7 @@
 };
 
 &uart1 {
+	u-boot,dm-pre-reloc;
 	status = "okay";
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/zynq-zc770-xm011.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/zynq-zc770-xm011.dts
@@ -47,6 +47,47 @@
 	};
 };
 
+&nand0 {
+	status = "okay";
+	arm,nand-cycle-t0 = <0x4>;
+	arm,nand-cycle-t1 = <0x4>;
+	arm,nand-cycle-t2 = <0x1>;
+	arm,nand-cycle-t3 = <0x2>;
+	arm,nand-cycle-t4 = <0x2>;
+	arm,nand-cycle-t5 = <0x2>;
+	arm,nand-cycle-t6 = <0x4>;
+
+	partition@0 {
+		label = "nand-fsbl-uboot";
+		reg = <0x0 0x100000>;
+	};
+	partition@100000 {
+		label = "nand-linux";
+		reg = <0x100000 0x500000>;
+	};
+	partition@600000 {
+		label = "nand-device-tree";
+		reg = <0x600000 0x20000>;
+	};
+	partition@620000 {
+		label = "nand-rootfs";
+		reg = <0x620000 0x5E0000>;
+	};
+	partition@c00000 {
+		label = "nand-bitstream";
+		reg = <0xC00000 0x400000>;
+	};
+};
+
+&smcc {
+	status = "okay";
+	arm,addr25 = <0x0>;
+	arm,nor-chip-sel0 = <0x0>;
+	arm,nor-chip-sel1 = <0x0>;
+	arm,sram-chip-sel0 = <0x0>;
+	arm,sram-chip-sel1 = <0x0>;
+};
+
 &spi0 {
 	status = "okay";
 	num-cs = <4>;
@@ -54,6 +95,7 @@
 };
 
 &uart1 {
+	u-boot,dm-pre-reloc;
 	status = "okay";
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/zynq-zc770-xm012.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/zynq-zc770-xm012.dts
@@ -53,6 +53,47 @@
 	};
 };
 
+&nor0 {
+	status = "okay";
+	bank-width = <1>;
+	xlnx,sram-cycle-t0 = <0xb>;
+	xlnx,sram-cycle-t1 = <0xb>;
+	xlnx,sram-cycle-t2 = <0x4>;
+	xlnx,sram-cycle-t3 = <0x4>;
+	xlnx,sram-cycle-t4 = <0x3>;
+	xlnx,sram-cycle-t5 = <0x3>;
+	xlnx,sram-cycle-t6 = <0x2>;
+	partition@0 {
+		label = "nor-fsbl-uboot";
+		reg = <0x0 0x100000>;
+	};
+	partition@100000 {
+		label = "nor-linux";
+		reg = <0x100000 0x500000>;
+	};
+	partition@600000 {
+		label = "nor-device-tree";
+		reg = <0x600000 0x20000>;
+	};
+	partition@620000 {
+		label = "nor-rootfs";
+		reg = <0x620000 0x5E0000>;
+	};
+	partition@c00000 {
+		label = "nor-bitstream";
+		reg = <0xC00000 0x400000>;
+	};
+};
+
+&smcc {
+	status = "okay";
+	arm,addr25 = <0x1>;
+	arm,nor-chip-sel0 = <0x1>;
+	arm,nor-chip-sel1 = <0x0>;
+	arm,sram-chip-sel0 = <0x0>;
+	arm,sram-chip-sel1 = <0x0>;
+};
+
 &spi1 {
 	status = "okay";
 	num-cs = <4>;
@@ -60,5 +101,6 @@
 };
 
 &uart1 {
+	u-boot,dm-pre-reloc;
 	status = "okay";
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/zynq-zc770-xm013.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/zynq-zc770-xm013.dts
@@ -15,6 +15,7 @@
 		ethernet0 = &gem1;
 		i2c0 = &i2c1;
 		serial0 = &uart0;
+		spi0 = &qspi;
 		spi1 = &spi0;
 	};
 
@@ -58,6 +59,41 @@
 	};
 };
 
+&qspi {
+	status = "okay";
+	is-dual = <1>;
+	num-cs = <1>;
+	flash@0 {
+		compatible = "n25q128a11";
+		reg = <0x0>;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <4>;
+		spi-max-frequency = <50000000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		partition@0 {
+			label = "qspi-fsbl-uboot";
+			reg = <0x0 0x100000>;
+		};
+		partition@100000 {
+			label = "qspi-linux";
+			reg = <0x100000 0x500000>;
+		};
+		partition@600000 {
+			label = "qspi-device-tree";
+			reg = <0x600000 0x20000>;
+		};
+		partition@620000 {
+			label = "qspi-rootfs";
+			reg = <0x620000 0x5E0000>;
+		};
+		partition@c00000 {
+			label = "qspi-bitstream";
+			reg = <0xC00000 0x400000>;
+		};
+	};
+};
+
 &spi0 {
 	status = "okay";
 	num-cs = <4>;
@@ -74,5 +110,6 @@
 };
 
 &uart0 {
+	u-boot,dm-pre-reloc;
 	status = "okay";
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/zynq-zed.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/zynq-zed.dts
@@ -1,6 +1,6 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0+
 /*
- *  Copyright (C) 2011 - 2014 Xilinx
+ *  Copyright (C) 2011 - 2015 Xilinx
  *  Copyright (C) 2012 National Instruments Corp.
  */
 /dts-v1/;
@@ -13,6 +13,7 @@
 	aliases {
 		ethernet0 = &gem0;
 		serial0 = &uart1;
+		spi0 = &qspi;
 		mmc0 = &sdhci0;
 	};
 
@@ -26,9 +27,12 @@
 		stdout-path = "serial0:115200n8";
 	};
 
-	usb_phy0: phy0 {
-		compatible = "usb-nop-xceiv";
+	usb_phy0: phy0@e0002000 {
+		compatible = "ulpi-phy";
 		#phy-cells = <0>;
+		reg = <0xe0002000 0x1000>;
+		view-port = <0x0170>;
+		drv-vbus;
 	};
 };
 
@@ -47,11 +51,50 @@
 	};
 };
 
+&qspi {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+	is-dual = <0>;
+	num-cs = <1>;
+	flash@0 {
+		compatible = "spansion,s25fl256s1", "jedec,spi-nor";
+		reg = <0>;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <4>;
+		spi-max-frequency = <50000000>;
+		m25p,fast-read;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		partition@0 {
+			label = "qspi-fsbl-uboot";
+			reg = <0x0 0x100000>;
+		};
+		partition@100000 {
+			label = "qspi-linux";
+			reg = <0x100000 0x500000>;
+		};
+		partition@600000 {
+			label = "qspi-device-tree";
+			reg = <0x600000 0x20000>;
+		};
+		partition@620000 {
+			label = "qspi-rootfs";
+			reg = <0x620000 0x5E0000>;
+		};
+		partition@c00000 {
+			label = "qspi-bitstream";
+			reg = <0xC00000 0x400000>;
+		};
+	};
+};
+
 &sdhci0 {
+	u-boot,dm-pre-reloc;
 	status = "okay";
 };
 
 &uart1 {
+	u-boot,dm-pre-reloc;
 	status = "okay";
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/boot/dts/zynq-zybo.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/boot/dts/zynq-zybo.dts
@@ -1,6 +1,6 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0+
 /*
- *  Copyright (C) 2011 - 2014 Xilinx
+ *  Copyright (C) 2011 - 2015 Xilinx
  *  Copyright (C) 2012 National Instruments Corp.
  */
 /dts-v1/;
@@ -13,6 +13,7 @@
 	aliases {
 		ethernet0 = &gem0;
 		serial0 = &uart1;
+		spi0 = &qspi;
 		mmc0 = &sdhci0;
 	};
 
@@ -48,11 +49,18 @@
 	};
 };
 
+&qspi {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
 &sdhci0 {
+	u-boot,dm-pre-reloc;
 	status = "okay";
 };
 
 &uart1 {
+	u-boot,dm-pre-reloc;
 	status = "okay";
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/configs/aspeed_g5_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/configs/aspeed_g5_defconfig
@@ -139,6 +139,7 @@
 CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_ASPEED_VUART=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DW=y
 CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_ASPEED_KCS_IPMI_BMC=y
 CONFIG_ASPEED_BT_IPMI_BMC=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/configs/exynos_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/configs/exynos_defconfig
@@ -38,6 +38,7 @@
 CONFIG_CRYPTO_SHA512_ARM=m
 CONFIG_CRYPTO_AES_ARM_BS=m
 CONFIG_CRYPTO_CHACHA20_NEON=m
+CONFIG_KALLSYMS_ALL=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_PARTITION_ADVANCED=y
@@ -92,6 +93,7 @@
 CONFIG_BLK_DEV_CRYPTOLOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_SG=y
 CONFIG_ATA=y
@@ -290,6 +292,7 @@
 CONFIG_COMMON_CLK_MAX77686=y
 CONFIG_COMMON_CLK_S2MPS11=y
 CONFIG_EXYNOS_IOMMU=y
+CONFIG_PM_DEVFREQ=y
 CONFIG_DEVFREQ_GOV_PERFORMANCE=y
 CONFIG_DEVFREQ_GOV_POWERSAVE=y
 CONFIG_DEVFREQ_GOV_USERSPACE=y
@@ -348,9 +351,13 @@
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_INFO=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_SOFTLOCKUP_DETECTOR=y
 # CONFIG_DETECT_HUNG_TASK is not set
 CONFIG_PROVE_LOCKING=y
 CONFIG_DEBUG_ATOMIC_SLEEP=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
 CONFIG_DEBUG_USER=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/configs/imx_v6_v7_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/configs/imx_v6_v7_defconfig
@@ -460,6 +460,7 @@
 CONFIG_FONT_8x16=y
 CONFIG_PRINTK_TIME=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_PROVE_LOCKING=y
 # CONFIG_DEBUG_BUGVERBOSE is not set
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/configs/omap2plus_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/configs/omap2plus_defconfig
@@ -552,5 +552,6 @@
 CONFIG_DEBUG_INFO_SPLIT=y
 CONFIG_DEBUG_INFO_DWARF4=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
 CONFIG_SCHEDSTATS=y
 # CONFIG_DEBUG_BUGVERBOSE is not set
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/configs/rpc_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/configs/rpc_defconfig
@@ -32,7 +32,6 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/configs/s3c2410_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/configs/s3c2410_defconfig
@@ -202,7 +202,6 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=y
 CONFIG_CHR_DEV_SCH=m
 CONFIG_SCSI_CONSTANTS=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/configs/xilinx_zynq_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/configs/xilinx_zynq_defconfig
@@ -0,0 +1,239 @@
+CONFIG_LOCALVERSION="-xilinx"
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CGROUPS=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL_SYSCALL=y
+# CONFIG_BUG is not set
+CONFIG_EMBEDDED=y
+CONFIG_PERF_EVENTS=y
+CONFIG_SLAB=y
+CONFIG_ARCH_VEXPRESS=y
+CONFIG_ARCH_ZYNQ=y
+CONFIG_PL310_ERRATA_588369=y
+CONFIG_PL310_ERRATA_727915=y
+CONFIG_PL310_ERRATA_769419=y
+CONFIG_ARM_ERRATA_754322=y
+CONFIG_ARM_ERRATA_754327=y
+CONFIG_ARM_ERRATA_764369=y
+CONFIG_ARM_ERRATA_775420=y
+CONFIG_SMP=y
+CONFIG_SCHED_MC=y
+CONFIG_SCHED_SMT=y
+CONFIG_HIGHMEM=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_ARM_ZYNQ_CPUIDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_COMPACTION is not set
+CONFIG_CMA=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=m
+CONFIG_SYN_COOKIES=y
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_CAN=y
+CONFIG_CAN_XILINXCAN=y
+CONFIG_PCI=y
+CONFIG_PCI_MSI=y
+CONFIG_PCIE_XILINX=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_CONNECTOR=y
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_RAW_NAND=y
+CONFIG_MTD_NAND_PL353=y
+CONFIG_MTD_SPI_NOR=y
+CONFIG_OF_OVERLAY=y
+CONFIG_OF_CONFIGFS=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_XILINX_TRAFGEN=y
+CONFIG_EEPROM_AT24=y
+CONFIG_EEPROM_AT25=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_NETDEVICES=y
+CONFIG_MACB=y
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+CONFIG_E1000E=y
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+CONFIG_R8169=y
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_XILINX_EMACLITE=y
+CONFIG_XILINX_AXI_EMAC=y
+CONFIG_MDIO_BITBANG=y
+CONFIG_MARVELL_PHY=y
+CONFIG_VITESSE_PHY=y
+CONFIG_INPUT_SPARSEKMAP=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_GPIO_POLLED=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_XILINX_PS_UART=y
+CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MUX=y
+CONFIG_I2C_MUX_PCA954x=y
+CONFIG_I2C_CADENCE=y
+CONFIG_SPI=y
+CONFIG_SPI_CADENCE=y
+CONFIG_SPI_XILINX=y
+CONFIG_SPI_ZYNQ_QSPI=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_XILINX=y
+CONFIG_GPIO_ZYNQ=y
+CONFIG_PMBUS=y
+CONFIG_SENSORS_UCD9000=y
+CONFIG_SENSORS_UCD9200=y
+CONFIG_THERMAL=y
+CONFIG_CPU_THERMAL=y
+CONFIG_WATCHDOG=y
+CONFIG_XILINX_WATCHDOG=y
+CONFIG_CADENCE_WATCHDOG=y
+CONFIG_REGULATOR=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_VIDEO_XILINX=y
+CONFIG_VIDEO_XILINX_CFA=y
+CONFIG_VIDEO_XILINX_CRESAMPLE=y
+CONFIG_VIDEO_XILINX_REMAPPER=y
+CONFIG_VIDEO_XILINX_RGB2YUV=y
+CONFIG_VIDEO_XILINX_SCALER=y
+CONFIG_VIDEO_XILINX_SWITCH=y
+CONFIG_VIDEO_XILINX_TPG=y
+CONFIG_VIDEO_ADV7604=y
+CONFIG_DRM=y
+CONFIG_DRM_XLNX=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_ADI=y
+CONFIG_SND_SOC_ADI_AXI_I2S=y
+CONFIG_SND_SOC_ADI_AXI_SPDIF=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_STORAGE=y
+CONFIG_USB_CHIPIDEA=y
+CONFIG_USB_CHIPIDEA_UDC=y
+CONFIG_USB_CHIPIDEA_HOST=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_USB_ULPI=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_XILINX=y
+CONFIG_USB_CONFIGFS=m
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+CONFIG_USB_ZERO=m
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_OF_ARASAN=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_ONESHOT=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_CPU=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_LEDS_TRIGGER_TRANSIENT=y
+CONFIG_LEDS_TRIGGER_CAMERA=y
+CONFIG_EDAC=y
+CONFIG_EDAC_SYNOPSYS=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_PCF8563=y
+CONFIG_PL330_DMA=y
+CONFIG_XILINX_DMA=y
+CONFIG_XILINX_DMA_ENGINES=y
+CONFIG_UIO=y
+CONFIG_UIO_PDRV_GENIRQ=y
+CONFIG_UIO_XILINX_APM=y
+CONFIG_COMMON_CLK_SI570=y
+CONFIG_REMOTEPROC=y
+CONFIG_ZYNQ_REMOTEPROC=m
+CONFIG_MEMORY=y
+CONFIG_IIO=y
+CONFIG_XILINX_XADC=y
+CONFIG_XILINX_INTC=y
+CONFIG_RAS=y
+CONFIG_FPGA=y
+CONFIG_FPGA_MGR_ZYNQ_FPGA=y
+CONFIG_FPGA_MGR_ZYNQ_AFI_FPGA=y
+CONFIG_FPGA_BRIDGE=y
+CONFIG_XILINX_PR_DECOUPLER=y
+CONFIG_FPGA_REGION=y
+CONFIG_OF_FPGA_REGION=y
+CONFIG_EXT3_FS=y
+# CONFIG_DNOTIFY is not set
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_DMA_CMA=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_RCU_CPU_STALL_TIMEOUT=60
+# CONFIG_FTRACE is not set
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/crypto/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/crypto/Kconfig
@@ -30,7 +30,7 @@
 
 config CRYPTO_SHA1_ARM_CE
 	tristate "SHA1 digest algorithm (ARM v8 Crypto Extensions)"
-	depends on KERNEL_MODE_NEON
+	depends on KERNEL_MODE_NEON && (CC_IS_CLANG || GCC_VERSION >= 40800)
 	select CRYPTO_SHA1_ARM
 	select CRYPTO_HASH
 	help
@@ -39,7 +39,7 @@
 
 config CRYPTO_SHA2_ARM_CE
 	tristate "SHA-224/256 digest algorithm (ARM v8 Crypto Extensions)"
-	depends on KERNEL_MODE_NEON
+	depends on KERNEL_MODE_NEON && (CC_IS_CLANG || GCC_VERSION >= 40800)
 	select CRYPTO_SHA256_ARM
 	select CRYPTO_HASH
 	help
@@ -96,7 +96,7 @@
 
 config CRYPTO_AES_ARM_CE
 	tristate "Accelerated AES using ARMv8 Crypto Extensions"
-	depends on KERNEL_MODE_NEON
+	depends on KERNEL_MODE_NEON && (CC_IS_CLANG || GCC_VERSION >= 40800)
 	select CRYPTO_BLKCIPHER
 	select CRYPTO_LIB_AES
 	select CRYPTO_SIMD
@@ -106,7 +106,7 @@
 
 config CRYPTO_GHASH_ARM_CE
 	tristate "PMULL-accelerated GHASH using NEON/ARMv8 Crypto Extensions"
-	depends on KERNEL_MODE_NEON
+	depends on KERNEL_MODE_NEON && (CC_IS_CLANG || GCC_VERSION >= 40800)
 	select CRYPTO_HASH
 	select CRYPTO_CRYPTD
 	select CRYPTO_GF128MUL
@@ -118,12 +118,14 @@
 
 config CRYPTO_CRCT10DIF_ARM_CE
 	tristate "CRCT10DIF digest algorithm using PMULL instructions"
-	depends on KERNEL_MODE_NEON && CRC_T10DIF
+	depends on KERNEL_MODE_NEON && (CC_IS_CLANG || GCC_VERSION >= 40800)
+	depends on CRC_T10DIF
 	select CRYPTO_HASH
 
 config CRYPTO_CRC32_ARM_CE
 	tristate "CRC32(C) digest algorithm using CRC and/or PMULL instructions"
-	depends on KERNEL_MODE_NEON && CRC32
+	depends on KERNEL_MODE_NEON && (CC_IS_CLANG || GCC_VERSION >= 40800)
+	depends on CRC32
 	select CRYPTO_HASH
 
 config CRYPTO_CHACHA20_NEON
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/crypto/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/crypto/Makefile
@@ -12,32 +12,12 @@
 obj-$(CONFIG_CRYPTO_CHACHA20_NEON) += chacha-neon.o
 obj-$(CONFIG_CRYPTO_NHPOLY1305_NEON) += nhpoly1305-neon.o
 
-ce-obj-$(CONFIG_CRYPTO_AES_ARM_CE) += aes-arm-ce.o
-ce-obj-$(CONFIG_CRYPTO_SHA1_ARM_CE) += sha1-arm-ce.o
-ce-obj-$(CONFIG_CRYPTO_SHA2_ARM_CE) += sha2-arm-ce.o
-ce-obj-$(CONFIG_CRYPTO_GHASH_ARM_CE) += ghash-arm-ce.o
-ce-obj-$(CONFIG_CRYPTO_CRCT10DIF_ARM_CE) += crct10dif-arm-ce.o
-crc-obj-$(CONFIG_CRYPTO_CRC32_ARM_CE) += crc32-arm-ce.o
-
-ifneq ($(crc-obj-y)$(crc-obj-m),)
-ifeq ($(call as-instr,.arch armv8-a\n.arch_extension crc,y,n),y)
-ce-obj-y += $(crc-obj-y)
-ce-obj-m += $(crc-obj-m)
-else
-$(warning These CRC Extensions modules need binutils 2.23 or higher)
-$(warning $(crc-obj-y) $(crc-obj-m))
-endif
-endif
-
-ifneq ($(ce-obj-y)$(ce-obj-m),)
-ifeq ($(call as-instr,.fpu crypto-neon-fp-armv8,y,n),y)
-obj-y += $(ce-obj-y)
-obj-m += $(ce-obj-m)
-else
-$(warning These ARMv8 Crypto Extensions modules need binutils 2.23 or higher)
-$(warning $(ce-obj-y) $(ce-obj-m))
-endif
-endif
+obj-$(CONFIG_CRYPTO_AES_ARM_CE) += aes-arm-ce.o
+obj-$(CONFIG_CRYPTO_SHA1_ARM_CE) += sha1-arm-ce.o
+obj-$(CONFIG_CRYPTO_SHA2_ARM_CE) += sha2-arm-ce.o
+obj-$(CONFIG_CRYPTO_GHASH_ARM_CE) += ghash-arm-ce.o
+obj-$(CONFIG_CRYPTO_CRCT10DIF_ARM_CE) += crct10dif-arm-ce.o
+obj-$(CONFIG_CRYPTO_CRC32_ARM_CE) += crc32-arm-ce.o
 
 aes-arm-y	:= aes-cipher-core.o aes-cipher-glue.o
 aes-arm-bs-y	:= aes-neonbs-core.o aes-neonbs-glue.o
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/crypto/aes-ce-core.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/crypto/aes-ce-core.S
@@ -386,20 +386,32 @@
 .Lctrloop4x:
 	subs		r4, r4, #4
 	bmi		.Lctr1x
-	add		r6, r6, #1
+
+	/*
+	 * NOTE: the sequence below has been carefully tweaked to avoid
+	 * a silicon erratum that exists in Cortex-A57 (#1742098) and
+	 * Cortex-A72 (#1655431) cores, where AESE/AESMC instruction pairs
+	 * may produce an incorrect result if they take their input from a
+	 * register of which a single 32-bit lane has been updated the last
+	 * time it was modified. To work around this, the lanes of registers
+	 * q0-q3 below are not manipulated individually, and the different
+	 * counter values are prepared by successive manipulations of q7.
+	 */
+	add		ip, r6, #1
 	vmov		q0, q7
+	rev		ip, ip
+	add		lr, r6, #2
+	vmov		s31, ip			@ set lane 3 of q1 via q7
+	add		ip, r6, #3
+	rev		lr, lr
 	vmov		q1, q7
-	rev		ip, r6
-	add		r6, r6, #1
+	vmov		s31, lr			@ set lane 3 of q2 via q7
+	rev		ip, ip
 	vmov		q2, q7
-	vmov		s7, ip
-	rev		ip, r6
-	add		r6, r6, #1
+	vmov		s31, ip			@ set lane 3 of q3 via q7
+	add		r6, r6, #4
 	vmov		q3, q7
-	vmov		s11, ip
-	rev		ip, r6
-	add		r6, r6, #1
-	vmov		s15, ip
+
 	vld1.8		{q4-q5}, [r1]!
 	vld1.8		{q6}, [r1]!
 	vld1.8		{q15}, [r1]!
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/crypto/crct10dif-ce-core.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/crypto/crct10dif-ce-core.S
@@ -72,7 +72,7 @@
 #endif
 
 	.text
-	.arch		armv7-a
+	.arch		armv8-a
 	.fpu		crypto-neon-fp-armv8
 
 	init_crc	.req	r0
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/crypto/ghash-ce-core.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/crypto/ghash-ce-core.S
@@ -8,6 +8,9 @@
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 
+	.arch		armv8-a
+	.fpu		crypto-neon-fp-armv8
+
 	SHASH		.req	q0
 	T1		.req	q1
 	XL		.req	q2
@@ -88,7 +91,6 @@
 	T3_H		.req	d17
 
 	.text
-	.fpu		crypto-neon-fp-armv8
 
 	.macro		__pmull_p64, rd, rn, rm, b1, b2, b3, b4
 	vmull.p64	\rd, \rn, \rm
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/crypto/nhpoly1305-neon-glue.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/crypto/nhpoly1305-neon-glue.c
@@ -30,7 +30,7 @@
 		return crypto_nhpoly1305_update(desc, src, srclen);
 
 	do {
-		unsigned int n = min_t(unsigned int, srclen, PAGE_SIZE);
+		unsigned int n = min_t(unsigned int, srclen, SZ_4K);
 
 		kernel_neon_begin();
 		crypto_nhpoly1305_update_helper(desc, src, n, _nh_neon);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/crypto/sha1-ce-core.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/crypto/sha1-ce-core.S
@@ -10,6 +10,7 @@
 #include <asm/assembler.h>
 
 	.text
+	.arch		armv8-a
 	.fpu		crypto-neon-fp-armv8
 
 	k0		.req	q0
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/crypto/sha2-ce-core.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/crypto/sha2-ce-core.S
@@ -10,6 +10,7 @@
 #include <asm/assembler.h>
 
 	.text
+	.arch		armv8-a
 	.fpu		crypto-neon-fp-armv8
 
 	k0		.req	q7
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/crypto/sha256-armv4.pl
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/crypto/sha256-armv4.pl
@@ -175,7 +175,6 @@
 #else
 .syntax unified
 # ifdef __thumb2__
-#  define adrl adr
 .thumb
 # else
 .code   32
@@ -471,7 +470,8 @@
 	stmdb	sp!,{r4-r12,lr}
 
 	sub	$H,sp,#16*4+16
-	adrl	$Ktbl,K256
+	adr	$Ktbl,.Lsha256_block_data_order
+	sub	$Ktbl,$Ktbl,#.Lsha256_block_data_order-K256
 	bic	$H,$H,#15		@ align for 128-bit stores
 	mov	$t2,sp
 	mov	sp,$H			@ alloca
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/crypto/sha256-core.S_shipped
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/crypto/sha256-core.S_shipped
@@ -56,7 +56,6 @@
 #else
 .syntax unified
 # ifdef __thumb2__
-#  define adrl adr
 .thumb
 # else
 .code   32
@@ -1885,7 +1884,8 @@
 	stmdb	sp!,{r4-r12,lr}
 
 	sub	r11,sp,#16*4+16
-	adrl	r14,K256
+	adr	r14,.Lsha256_block_data_order
+	sub	r14,r14,#.Lsha256_block_data_order-K256
 	bic	r11,r11,#15		@ align for 128-bit stores
 	mov	r12,sp
 	mov	sp,r11			@ alloca
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/crypto/sha256_glue.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/crypto/sha256_glue.c
@@ -25,8 +25,8 @@
 
 #include "sha256_glue.h"
 
-asmlinkage void sha256_block_data_order(u32 *digest, const void *data,
-					unsigned int num_blks);
+asmlinkage void sha256_block_data_order(struct sha256_state *state,
+					const u8 *data, int num_blks);
 
 int crypto_sha256_arm_update(struct shash_desc *desc, const u8 *data,
 			     unsigned int len)
@@ -34,23 +34,20 @@
 	/* make sure casting to sha256_block_fn() is safe */
 	BUILD_BUG_ON(offsetof(struct sha256_state, state) != 0);
 
-	return sha256_base_do_update(desc, data, len,
-				(sha256_block_fn *)sha256_block_data_order);
+	return sha256_base_do_update(desc, data, len, sha256_block_data_order);
 }
 EXPORT_SYMBOL(crypto_sha256_arm_update);
 
 static int crypto_sha256_arm_final(struct shash_desc *desc, u8 *out)
 {
-	sha256_base_do_finalize(desc,
-				(sha256_block_fn *)sha256_block_data_order);
+	sha256_base_do_finalize(desc, sha256_block_data_order);
 	return sha256_base_finish(desc, out);
 }
 
 int crypto_sha256_arm_finup(struct shash_desc *desc, const u8 *data,
 			    unsigned int len, u8 *out)
 {
-	sha256_base_do_update(desc, data, len,
-			      (sha256_block_fn *)sha256_block_data_order);
+	sha256_base_do_update(desc, data, len, sha256_block_data_order);
 	return crypto_sha256_arm_final(desc, out);
 }
 EXPORT_SYMBOL(crypto_sha256_arm_finup);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/crypto/sha512-armv4.pl
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/crypto/sha512-armv4.pl
@@ -212,7 +212,6 @@
 #else
 .syntax unified
 # ifdef __thumb2__
-#  define adrl adr
 .thumb
 # else
 .code   32
@@ -602,7 +601,8 @@
 	dmb				@ errata #451034 on early Cortex A8
 	add	$len,$inp,$len,lsl#7	@ len to point at the end of inp
 	VFP_ABI_PUSH
-	adrl	$Ktbl,K512
+	adr	$Ktbl,.Lsha512_block_data_order
+	sub	$Ktbl,$Ktbl,.Lsha512_block_data_order-K512
 	vldmia	$ctx,{$A-$H}		@ load context
 .Loop_neon:
 ___
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/crypto/sha512-core.S_shipped
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/crypto/sha512-core.S_shipped
@@ -79,7 +79,6 @@
 #else
 .syntax unified
 # ifdef __thumb2__
-#  define adrl adr
 .thumb
 # else
 .code   32
@@ -543,7 +542,8 @@
 	dmb				@ errata #451034 on early Cortex A8
 	add	r2,r1,r2,lsl#7	@ len to point at the end of inp
 	VFP_ABI_PUSH
-	adrl	r3,K512
+	adr	r3,.Lsha512_block_data_order
+	sub	r3,r3,.Lsha512_block_data_order-K512
 	vldmia	r0,{d16-d23}		@ load context
 .Loop_neon:
 	vshr.u64	d24,d20,#14	@ 0
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/crypto/sha512-glue.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/crypto/sha512-glue.c
@@ -25,27 +25,25 @@
 MODULE_ALIAS_CRYPTO("sha384-arm");
 MODULE_ALIAS_CRYPTO("sha512-arm");
 
-asmlinkage void sha512_block_data_order(u64 *state, u8 const *src, int blocks);
+asmlinkage void sha512_block_data_order(struct sha512_state *state,
+					u8 const *src, int blocks);
 
 int sha512_arm_update(struct shash_desc *desc, const u8 *data,
 		      unsigned int len)
 {
-	return sha512_base_do_update(desc, data, len,
-		(sha512_block_fn *)sha512_block_data_order);
+	return sha512_base_do_update(desc, data, len, sha512_block_data_order);
 }
 
 static int sha512_arm_final(struct shash_desc *desc, u8 *out)
 {
-	sha512_base_do_finalize(desc,
-		(sha512_block_fn *)sha512_block_data_order);
+	sha512_base_do_finalize(desc, sha512_block_data_order);
 	return sha512_base_finish(desc, out);
 }
 
 int sha512_arm_finup(struct shash_desc *desc, const u8 *data,
 		     unsigned int len, u8 *out)
 {
-	sha512_base_do_update(desc, data, len,
-		(sha512_block_fn *)sha512_block_data_order);
+	sha512_base_do_update(desc, data, len, sha512_block_data_order);
 	return sha512_arm_final(desc, out);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/include/asm/Kbuild
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/include/asm/Kbuild
@@ -12,7 +12,6 @@
 generic-y += local64.h
 generic-y += mm-arch-hooks.h
 generic-y += mmiowb.h
-generic-y += msi.h
 generic-y += parport.h
 generic-y += preempt.h
 generic-y += seccomp.h
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/include/asm/assembler.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/include/asm/assembler.h
@@ -18,11 +18,11 @@
 #endif
 
 #include <asm/ptrace.h>
-#include <asm/domain.h>
 #include <asm/opcodes-virt.h>
 #include <asm/asm-offsets.h>
 #include <asm/page.h>
 #include <asm/thread_info.h>
+#include <asm/uaccess-asm.h>
 
 #define IOMEM(x)	(x)
 
@@ -107,6 +107,16 @@
 	.endm
 #endif
 
+#if __LINUX_ARM_ARCH__ < 7
+	.macro	dsb, args
+	mcr	p15, 0, r0, c7, c10, 4
+	.endm
+
+	.macro	isb, args
+	mcr	p15, 0, r0, c7, c5, 4
+	.endm
+#endif
+
 	.macro asm_trace_hardirqs_off, save=1
 #if defined(CONFIG_TRACE_IRQFLAGS)
 	.if \save
@@ -269,10 +279,9 @@
 	.endif							;\
 	.popsection
 #define ALT_UP_B(label)					\
-	.equ	up_b_offset, label - 9998b			;\
 	.pushsection ".alt.smp.init", "a"			;\
 	.long	9998b						;\
-	W(b)	. + up_b_offset					;\
+	W(b)	. + (label - 9998b)					;\
 	.popsection
 #else
 #define ALT_SMP(instr...)
@@ -446,79 +455,6 @@
 	.size \name , . - \name
 	.endm
 
-	.macro	csdb
-#ifdef CONFIG_THUMB2_KERNEL
-	.inst.w	0xf3af8014
-#else
-	.inst	0xe320f014
-#endif
-	.endm
-
-	.macro check_uaccess, addr:req, size:req, limit:req, tmp:req, bad:req
-#ifndef CONFIG_CPU_USE_DOMAINS
-	adds	\tmp, \addr, #\size - 1
-	sbcscc	\tmp, \tmp, \limit
-	bcs	\bad
-#ifdef CONFIG_CPU_SPECTRE
-	movcs	\addr, #0
-	csdb
-#endif
-#endif
-	.endm
-
-	.macro uaccess_mask_range_ptr, addr:req, size:req, limit:req, tmp:req
-#ifdef CONFIG_CPU_SPECTRE
-	sub	\tmp, \limit, #1
-	subs	\tmp, \tmp, \addr	@ tmp = limit - 1 - addr
-	addhs	\tmp, \tmp, #1		@ if (tmp >= 0) {
-	subshs	\tmp, \tmp, \size	@ tmp = limit - (addr + size) }
-	movlo	\addr, #0		@ if (tmp < 0) addr = NULL
-	csdb
-#endif
-	.endm
-
-	.macro	uaccess_disable, tmp, isb=1
-#ifdef CONFIG_CPU_SW_DOMAIN_PAN
-	/*
-	 * Whenever we re-enter userspace, the domains should always be
-	 * set appropriately.
-	 */
-	mov	\tmp, #DACR_UACCESS_DISABLE
-	mcr	p15, 0, \tmp, c3, c0, 0		@ Set domain register
-	.if	\isb
-	instr_sync
-	.endif
-#endif
-	.endm
-
-	.macro	uaccess_enable, tmp, isb=1
-#ifdef CONFIG_CPU_SW_DOMAIN_PAN
-	/*
-	 * Whenever we re-enter userspace, the domains should always be
-	 * set appropriately.
-	 */
-	mov	\tmp, #DACR_UACCESS_ENABLE
-	mcr	p15, 0, \tmp, c3, c0, 0
-	.if	\isb
-	instr_sync
-	.endif
-#endif
-	.endm
-
-	.macro	uaccess_save, tmp
-#ifdef CONFIG_CPU_SW_DOMAIN_PAN
-	mrc	p15, 0, \tmp, c3, c0, 0
-	str	\tmp, [sp, #SVC_DACR]
-#endif
-	.endm
-
-	.macro	uaccess_restore
-#ifdef CONFIG_CPU_SW_DOMAIN_PAN
-	ldr	r0, [sp, #SVC_DACR]
-	mcr	p15, 0, r0, c3, c0, 0
-#endif
-	.endm
-
 	.irp	c,,eq,ne,cs,cc,mi,pl,vs,vc,hi,ls,ge,lt,gt,le,hs,lo
 	.macro	ret\c, reg
 #if __LINUX_ARM_ARCH__ < 6
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/include/asm/bugs.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/include/asm/bugs.h
@@ -1,7 +1,5 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- *  arch/arm/include/asm/bugs.h
- *
  *  Copyright (C) 1995-2003 Russell King
  */
 #ifndef __ASM_BUGS_H
@@ -10,10 +8,8 @@
 extern void check_writebuffer_bugs(void);
 
 #ifdef CONFIG_MMU
-extern void check_bugs(void);
 extern void check_other_bugs(void);
 #else
-#define check_bugs() do { } while (0)
 #define check_other_bugs() do { } while (0)
 #endif
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/include/asm/clocksource.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/include/asm/clocksource.h
@@ -1,8 +1,17 @@
 #ifndef _ASM_CLOCKSOURCE_H
 #define _ASM_CLOCKSOURCE_H
 
+enum vdso_arch_clockmode {
+	/* vdso clocksource not usable */
+	VDSO_CLOCKMODE_NONE,
+	/* vdso clocksource usable */
+	VDSO_CLOCKMODE_ARCHTIMER,
+	VDSO_CLOCKMODE_ARCHTIMER_NOCOMPAT = VDSO_CLOCKMODE_ARCHTIMER,
+};
+
 struct arch_clocksource_data {
-	bool vdso_direct;	/* Usable for direct VDSO access? */
+	/* Usable for direct VDSO access? */
+	enum vdso_arch_clockmode clock_mode;
 };
 
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/include/asm/exception.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/include/asm/exception.h
@@ -10,10 +10,6 @@
 
 #include <linux/interrupt.h>
 
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
 #define __exception_irq_entry	__irq_entry
-#else
-#define __exception_irq_entry
-#endif
 
 #endif /* __ASM_ARM_EXCEPTION_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/include/asm/fixmap.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/include/asm/fixmap.h
@@ -2,7 +2,7 @@
 #ifndef _ASM_FIXMAP_H
 #define _ASM_FIXMAP_H
 
-#define FIXADDR_START		0xffc00000UL
+#define FIXADDR_START		0xffc80000UL
 #define FIXADDR_END		0xfff00000UL
 #define FIXADDR_TOP		(FIXADDR_END - PAGE_SIZE)
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/include/asm/ftrace.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/include/asm/ftrace.h
@@ -16,6 +16,9 @@
 
 #ifdef CONFIG_DYNAMIC_FTRACE
 struct dyn_arch_ftrace {
+#ifdef CONFIG_ARM_MODULE_PLTS
+	struct module *mod;
+#endif
 };
 
 static inline unsigned long ftrace_call_adjust(unsigned long addr)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/include/asm/futex.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/include/asm/futex.h
@@ -164,8 +164,13 @@
 	preempt_enable();
 #endif
 
-	if (!ret)
-		*oval = oldval;
+	/*
+	 * Store unconditionally. If ret != 0 the extra store is the least
+	 * of the worries but GCC cannot figure out that __futex_atomic_op()
+	 * is either setting ret to -EFAULT or storing the old value in
+	 * oldval which results in a uninitialized warning at the call site.
+	 */
+	*oval = oldval;
 
 	return ret;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/include/asm/hardirq.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/include/asm/hardirq.h
@@ -6,8 +6,7 @@
 #include <linux/threads.h>
 #include <asm/irq.h>
 
-/* number of IPIS _not_ including IPI_CPU_BACKTRACE */
-#define NR_IPI	7
+#define NR_IPI	16
 
 typedef struct {
 	unsigned int __softirq_pending;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/include/asm/insn.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/include/asm/insn.h
@@ -13,18 +13,18 @@
 }
 
 unsigned long
-__arm_gen_branch(unsigned long pc, unsigned long addr, bool link);
+__arm_gen_branch(unsigned long pc, unsigned long addr, bool link, bool warn);
 
 static inline unsigned long
 arm_gen_branch(unsigned long pc, unsigned long addr)
 {
-	return __arm_gen_branch(pc, addr, false);
+	return __arm_gen_branch(pc, addr, false, true);
 }
 
 static inline unsigned long
-arm_gen_branch_link(unsigned long pc, unsigned long addr)
+arm_gen_branch_link(unsigned long pc, unsigned long addr, bool warn)
 {
-	return __arm_gen_branch(pc, addr, true);
+	return __arm_gen_branch(pc, addr, true, warn);
 }
 
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/include/asm/io.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/include/asm/io.h
@@ -457,6 +457,9 @@
 extern int valid_phys_addr_range(phys_addr_t addr, size_t size);
 extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
 extern int devmem_is_allowed(unsigned long pfn);
+extern bool arch_memremap_can_ram_remap(resource_size_t offset, size_t size,
+					unsigned long flags);
+#define arch_memremap_can_ram_remap arch_memremap_can_ram_remap
 #endif
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/include/asm/kexec-internal.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/include/asm/kexec-internal.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ARM_KEXEC_INTERNAL_H
+#define _ARM_KEXEC_INTERNAL_H
+
+struct kexec_relocate_data {
+	unsigned long kexec_start_address;
+	unsigned long kexec_indirection_page;
+	unsigned long kexec_mach_type;
+	unsigned long kexec_r2;
+};
+
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/include/asm/kprobes.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/include/asm/kprobes.h
@@ -44,20 +44,20 @@
 			     unsigned long val, void *data);
 
 /* optinsn template addresses */
-extern __visible kprobe_opcode_t optprobe_template_entry;
-extern __visible kprobe_opcode_t optprobe_template_val;
-extern __visible kprobe_opcode_t optprobe_template_call;
-extern __visible kprobe_opcode_t optprobe_template_end;
-extern __visible kprobe_opcode_t optprobe_template_sub_sp;
-extern __visible kprobe_opcode_t optprobe_template_add_sp;
-extern __visible kprobe_opcode_t optprobe_template_restore_begin;
-extern __visible kprobe_opcode_t optprobe_template_restore_orig_insn;
-extern __visible kprobe_opcode_t optprobe_template_restore_end;
+extern __visible kprobe_opcode_t optprobe_template_entry[];
+extern __visible kprobe_opcode_t optprobe_template_val[];
+extern __visible kprobe_opcode_t optprobe_template_call[];
+extern __visible kprobe_opcode_t optprobe_template_end[];
+extern __visible kprobe_opcode_t optprobe_template_sub_sp[];
+extern __visible kprobe_opcode_t optprobe_template_add_sp[];
+extern __visible kprobe_opcode_t optprobe_template_restore_begin[];
+extern __visible kprobe_opcode_t optprobe_template_restore_orig_insn[];
+extern __visible kprobe_opcode_t optprobe_template_restore_end[];
 
 #define MAX_OPTIMIZED_LENGTH	4
 #define MAX_OPTINSN_SIZE				\
-	((unsigned long)&optprobe_template_end -	\
-	 (unsigned long)&optprobe_template_entry)
+	((unsigned long)optprobe_template_end -	\
+	 (unsigned long)optprobe_template_entry)
 #define RELATIVEJUMP_SIZE	4
 
 struct arch_optimized_insn {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/include/asm/kvm_asm.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/include/asm/kvm_asm.h
@@ -56,7 +56,7 @@
 extern void __kvm_flush_vm_context(void);
 extern void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa);
 extern void __kvm_tlb_flush_vmid(struct kvm *kvm);
-extern void __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu);
+extern void __kvm_flush_cpu_context(struct kvm_vcpu *vcpu);
 
 extern void __kvm_timer_set_cntvoff(u32 cntvoff_low, u32 cntvoff_high);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/include/asm/kvm_emulate.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/include/asm/kvm_emulate.h
@@ -14,13 +14,25 @@
 #include <asm/cputype.h>
 
 /* arm64 compatibility macros */
+#define PSR_AA32_MODE_FIQ	FIQ_MODE
+#define PSR_AA32_MODE_SVC	SVC_MODE
 #define PSR_AA32_MODE_ABT	ABT_MODE
 #define PSR_AA32_MODE_UND	UND_MODE
 #define PSR_AA32_T_BIT		PSR_T_BIT
+#define PSR_AA32_F_BIT		PSR_F_BIT
 #define PSR_AA32_I_BIT		PSR_I_BIT
 #define PSR_AA32_A_BIT		PSR_A_BIT
 #define PSR_AA32_E_BIT		PSR_E_BIT
 #define PSR_AA32_IT_MASK	PSR_IT_MASK
+#define PSR_AA32_GE_MASK	0x000f0000
+#define PSR_AA32_DIT_BIT	0x00200000
+#define PSR_AA32_PAN_BIT	0x00400000
+#define PSR_AA32_SSBS_BIT	0x00800000
+#define PSR_AA32_Q_BIT		PSR_Q_BIT
+#define PSR_AA32_V_BIT		PSR_V_BIT
+#define PSR_AA32_C_BIT		PSR_C_BIT
+#define PSR_AA32_Z_BIT		PSR_Z_BIT
+#define PSR_AA32_N_BIT		PSR_N_BIT
 
 unsigned long *vcpu_reg(struct kvm_vcpu *vcpu, u8 reg_num);
 
@@ -41,6 +53,11 @@
 	*__vcpu_spsr(vcpu) = v;
 }
 
+static inline unsigned long host_spsr_to_spsr32(unsigned long spsr)
+{
+	return spsr;
+}
+
 static inline unsigned long vcpu_get_reg(struct kvm_vcpu *vcpu,
 					 u8 reg_num)
 {
@@ -177,12 +194,17 @@
 	return kvm_vcpu_get_hsr(vcpu) & HSR_SSE;
 }
 
+static inline bool kvm_vcpu_dabt_issf(const struct kvm_vcpu *vcpu)
+{
+	return false;
+}
+
 static inline int kvm_vcpu_dabt_get_rd(struct kvm_vcpu *vcpu)
 {
 	return (kvm_vcpu_get_hsr(vcpu) & HSR_SRT_MASK) >> HSR_SRT_SHIFT;
 }
 
-static inline bool kvm_vcpu_dabt_iss1tw(struct kvm_vcpu *vcpu)
+static inline bool kvm_vcpu_abt_iss1tw(const struct kvm_vcpu *vcpu)
 {
 	return kvm_vcpu_get_hsr(vcpu) & HSR_DABT_S1PTW;
 }
@@ -214,16 +236,21 @@
 	return kvm_vcpu_get_hsr(vcpu) & HSR_IL;
 }
 
-static inline u8 kvm_vcpu_trap_get_class(struct kvm_vcpu *vcpu)
+static inline u8 kvm_vcpu_trap_get_class(const struct kvm_vcpu *vcpu)
 {
 	return kvm_vcpu_get_hsr(vcpu) >> HSR_EC_SHIFT;
 }
 
-static inline bool kvm_vcpu_trap_is_iabt(struct kvm_vcpu *vcpu)
+static inline bool kvm_vcpu_trap_is_iabt(const struct kvm_vcpu *vcpu)
 {
 	return kvm_vcpu_trap_get_class(vcpu) == HSR_EC_IABT;
 }
 
+static inline bool kvm_vcpu_trap_is_exec_fault(const struct kvm_vcpu *vcpu)
+{
+	return kvm_vcpu_trap_is_iabt(vcpu) && !kvm_vcpu_abt_iss1tw(vcpu);
+}
+
 static inline u8 kvm_vcpu_trap_get_fault(struct kvm_vcpu *vcpu)
 {
 	return kvm_vcpu_get_hsr(vcpu) & HSR_FSC;
@@ -341,6 +368,7 @@
 	}
 }
 
-static inline void vcpu_ptrauth_setup_lazy(struct kvm_vcpu *vcpu) {}
+static inline bool vcpu_has_ptrauth(struct kvm_vcpu *vcpu) { return false; }
+static inline void vcpu_ptrauth_disable(struct kvm_vcpu *vcpu) { }
 
 #endif /* __ARM_KVM_EMULATE_H__ */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/include/asm/kvm_host.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/include/asm/kvm_host.h
@@ -266,7 +266,7 @@
 
 #define KVM_ARCH_WANT_MMU_NOTIFIER
 int kvm_unmap_hva_range(struct kvm *kvm,
-			unsigned long start, unsigned long end);
+			unsigned long start, unsigned long end, unsigned flags);
 int kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte);
 
 unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu);
@@ -335,6 +335,7 @@
 static inline void kvm_arch_vcpu_block_finish(struct kvm_vcpu *vcpu) {}
 
 static inline void kvm_arm_init_debug(void) {}
+static inline void kvm_arm_vcpu_init_debug(struct kvm_vcpu *vcpu) {}
 static inline void kvm_arm_setup_debug(struct kvm_vcpu *vcpu) {}
 static inline void kvm_arm_clear_debug(struct kvm_vcpu *vcpu) {}
 static inline void kvm_arm_reset_debug_ptr(struct kvm_vcpu *vcpu) {}
@@ -421,4 +422,6 @@
 	return true;
 }
 
+#define kvm_arm_vcpu_loaded(vcpu)	(false)
+
 #endif /* __ARM_KVM_HOST_H__ */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/include/asm/kvm_mmio.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/include/asm/kvm_mmio.h
@@ -14,6 +14,8 @@
 struct kvm_decode {
 	unsigned long rt;
 	bool sign_extend;
+	/* Not used on 32-bit arm */
+	bool sixty_four;
 };
 
 void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/include/asm/mach/map.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/include/asm/mach/map.h
@@ -27,6 +27,7 @@
 	MT_HIGH_VECTORS,
 	MT_MEMORY_RWX,
 	MT_MEMORY_RW,
+	MT_MEMORY_RO,
 	MT_ROM,
 	MT_MEMORY_RWX_NONCACHED,
 	MT_MEMORY_RW_DTCM,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/include/asm/memory.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/include/asm/memory.h
@@ -67,6 +67,10 @@
  */
 #define XIP_VIRT_ADDR(physaddr)  (MODULES_VADDR + ((physaddr) & 0x000fffff))
 
+#define FDT_FIXED_BASE		UL(0xff800000)
+#define FDT_FIXED_SIZE		(2 * SECTION_SIZE)
+#define FDT_VIRT_BASE(physbase)	((void *)(FDT_FIXED_BASE | (physbase) % SECTION_SIZE))
+
 #if !defined(CONFIG_SMP) && !defined(CONFIG_ARM_LPAE)
 /*
  * Allow 16MB-aligned ioremap pages
@@ -107,6 +111,7 @@
 #define MODULES_VADDR		PAGE_OFFSET
 
 #define XIP_VIRT_ADDR(physaddr)  (physaddr)
+#define FDT_VIRT_BASE(physbase)  ((void *)(physbase))
 
 #endif /* !CONFIG_MMU */
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/include/asm/module.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/include/asm/module.h
@@ -19,8 +19,18 @@
 };
 #endif
 
+#define PLT_ENT_STRIDE		L1_CACHE_BYTES
+#define PLT_ENT_COUNT		(PLT_ENT_STRIDE / sizeof(u32))
+#define PLT_ENT_SIZE		(sizeof(struct plt_entries) / PLT_ENT_COUNT)
+
+struct plt_entries {
+	u32	ldr[PLT_ENT_COUNT];
+	u32	lit[PLT_ENT_COUNT];
+};
+
 struct mod_plt_sec {
 	struct elf32_shdr	*plt;
+	struct plt_entries	*plt_ent;
 	int			plt_count;
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/include/asm/percpu.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/include/asm/percpu.h
@@ -5,6 +5,8 @@
 #ifndef _ASM_ARM_PERCPU_H_
 #define _ASM_ARM_PERCPU_H_
 
+#include <asm/thread_info.h>
+
 /*
  * Same as asm-generic/percpu.h, except that we store the per cpu offset
  * in the TPIDRPRW. TPIDRPRW only exists on V6K and V7
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/include/asm/perf_event.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/include/asm/perf_event.h
@@ -17,7 +17,7 @@
 
 #define perf_arch_fetch_caller_regs(regs, __ip) { \
 	(regs)->ARM_pc = (__ip); \
-	(regs)->ARM_fp = (unsigned long) __builtin_frame_address(0); \
+	frame_pointer((regs)) = (unsigned long) __builtin_frame_address(0); \
 	(regs)->ARM_sp = current_stack_pointer; \
 	(regs)->ARM_cpsr = SVC_MODE; \
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/include/asm/pgtable-2level.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/include/asm/pgtable-2level.h
@@ -75,6 +75,8 @@
 #define PTE_HWTABLE_OFF		(PTE_HWTABLE_PTRS * sizeof(pte_t))
 #define PTE_HWTABLE_SIZE	(PTRS_PER_PTE * sizeof(u32))
 
+#define MAX_POSSIBLE_PHYSMEM_BITS	32
+
 /*
  * PMD_SHIFT determines the size of the area a second-level page table can map
  * PGDIR_SHIFT determines what a third-level page table entry can map
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/include/asm/pgtable-3level.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/include/asm/pgtable-3level.h
@@ -25,6 +25,8 @@
 #define PTE_HWTABLE_OFF		(0)
 #define PTE_HWTABLE_SIZE	(PTRS_PER_PTE * sizeof(u64))
 
+#define MAX_POSSIBLE_PHYSMEM_BITS 40
+
 /*
  * PGDIR_SHIFT determines the size a top-level page table entry can map.
  */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/include/asm/pgtable-nommu.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/include/asm/pgtable-nommu.h
@@ -52,12 +52,6 @@
 typedef pte_t *pte_addr_t;
 
 /*
- * ZERO_PAGE is a global shared page that is always zero: used
- * for zero-mapped memory areas etc..
- */
-#define ZERO_PAGE(vaddr)	(virt_to_page(0))
-
-/*
  * Mark the prot value as uncacheable and unbufferable.
  */
 #define pgprot_noncached(prot)	(prot)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/include/asm/pgtable.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/include/asm/pgtable.h
@@ -10,6 +10,15 @@
 #include <linux/const.h>
 #include <asm/proc-fns.h>
 
+#ifndef __ASSEMBLY__
+/*
+ * ZERO_PAGE is a global shared page that is always zero: used
+ * for zero-mapped memory areas etc..
+ */
+extern struct page *empty_zero_page;
+#define ZERO_PAGE(vaddr)	(empty_zero_page)
+#endif
+
 #ifndef CONFIG_MMU
 
 #include <asm-generic/4level-fixup.h>
@@ -166,13 +175,6 @@
 #define __S111  __PAGE_SHARED_EXEC
 
 #ifndef __ASSEMBLY__
-/*
- * ZERO_PAGE is a global shared page that is always zero: used
- * for zero-mapped memory areas etc..
- */
-extern struct page *empty_zero_page;
-#define ZERO_PAGE(vaddr)	(empty_zero_page)
-
 
 extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/include/asm/prom.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/include/asm/prom.h
@@ -9,12 +9,12 @@
 
 #ifdef CONFIG_OF
 
-extern const struct machine_desc *setup_machine_fdt(unsigned int dt_phys);
+extern const struct machine_desc *setup_machine_fdt(void *dt_virt);
 extern void __init arm_dt_init_cpu_maps(void);
 
 #else /* CONFIG_OF */
 
-static inline const struct machine_desc *setup_machine_fdt(unsigned int dt_phys)
+static inline const struct machine_desc *setup_machine_fdt(void *dt_virt)
 {
 	return NULL;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/include/asm/ptrace.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/include/asm/ptrace.h
@@ -164,5 +164,31 @@
 		((current_stack_pointer | (THREAD_SIZE - 1)) - 7) - 1;	\
 })
 
+
+/*
+ * Update ITSTATE after normal execution of an IT block instruction.
+ *
+ * The 8 IT state bits are split into two parts in CPSR:
+ *	ITSTATE<1:0> are in CPSR<26:25>
+ *	ITSTATE<7:2> are in CPSR<15:10>
+ */
+static inline unsigned long it_advance(unsigned long cpsr)
+{
+	if ((cpsr & 0x06000400) == 0) {
+		/* ITSTATE<2:0> == 0 means end of IT block, so clear IT state */
+		cpsr &= ~PSR_IT_MASK;
+	} else {
+		/* We need to shift left ITSTATE<4:0> */
+		const unsigned long mask = 0x06001c00;  /* Mask ITSTATE<4:0> */
+		unsigned long it = cpsr & mask;
+		it <<= 1;
+		it |= it >> (27 - 10);  /* Carry ITSTATE<2> to correct place */
+		it &= mask;
+		cpsr &= ~mask;
+		cpsr |= it;
+	}
+	return cpsr;
+}
+
 #endif /* __ASSEMBLY__ */
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/include/asm/smp.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/include/asm/smp.h
@@ -120,4 +120,7 @@
  */
 extern void smp_set_ops(const struct smp_operations *);
 
+extern int set_ipi_handler(int ipinr, void *handler, char *desc);
+extern void clear_ipi_handler(int ipinr);
+
 #endif /* ifndef __ASM_ARM_SMP_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/include/asm/spectre.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/include/asm/spectre.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __ASM_SPECTRE_H
+#define __ASM_SPECTRE_H
+
+enum {
+	SPECTRE_UNAFFECTED,
+	SPECTRE_MITIGATED,
+	SPECTRE_VULNERABLE,
+};
+
+enum {
+	__SPECTRE_V2_METHOD_BPIALL,
+	__SPECTRE_V2_METHOD_ICIALLU,
+	__SPECTRE_V2_METHOD_SMC,
+	__SPECTRE_V2_METHOD_HVC,
+	__SPECTRE_V2_METHOD_LOOP8,
+};
+
+enum {
+	SPECTRE_V2_METHOD_BPIALL = BIT(__SPECTRE_V2_METHOD_BPIALL),
+	SPECTRE_V2_METHOD_ICIALLU = BIT(__SPECTRE_V2_METHOD_ICIALLU),
+	SPECTRE_V2_METHOD_SMC = BIT(__SPECTRE_V2_METHOD_SMC),
+	SPECTRE_V2_METHOD_HVC = BIT(__SPECTRE_V2_METHOD_HVC),
+	SPECTRE_V2_METHOD_LOOP8 = BIT(__SPECTRE_V2_METHOD_LOOP8),
+};
+
+#ifdef CONFIG_GENERIC_CPU_VULNERABILITIES
+void spectre_v2_update_state(unsigned int state, unsigned int methods);
+#else
+static inline void spectre_v2_update_state(unsigned int state,
+					   unsigned int methods)
+{}
+#endif
+
+int spectre_bhb_update_vectors(unsigned int method);
+
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/include/asm/timex.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/include/asm/timex.h
@@ -11,5 +11,6 @@
 
 typedef unsigned long cycles_t;
 #define get_cycles()	({ cycles_t c; read_current_timer(&c) ? 0 : c; })
+#define random_get_entropy() (((unsigned long)get_cycles()) ?: random_get_entropy_fallback())
 
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/include/asm/uaccess-asm.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/include/asm/uaccess-asm.h
@@ -0,0 +1,117 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __ASM_UACCESS_ASM_H__
+#define __ASM_UACCESS_ASM_H__
+
+#include <asm/asm-offsets.h>
+#include <asm/domain.h>
+#include <asm/memory.h>
+#include <asm/thread_info.h>
+
+	.macro	csdb
+#ifdef CONFIG_THUMB2_KERNEL
+	.inst.w	0xf3af8014
+#else
+	.inst	0xe320f014
+#endif
+	.endm
+
+	.macro check_uaccess, addr:req, size:req, limit:req, tmp:req, bad:req
+#ifndef CONFIG_CPU_USE_DOMAINS
+	adds	\tmp, \addr, #\size - 1
+	sbcscc	\tmp, \tmp, \limit
+	bcs	\bad
+#ifdef CONFIG_CPU_SPECTRE
+	movcs	\addr, #0
+	csdb
+#endif
+#endif
+	.endm
+
+	.macro uaccess_mask_range_ptr, addr:req, size:req, limit:req, tmp:req
+#ifdef CONFIG_CPU_SPECTRE
+	sub	\tmp, \limit, #1
+	subs	\tmp, \tmp, \addr	@ tmp = limit - 1 - addr
+	addhs	\tmp, \tmp, #1		@ if (tmp >= 0) {
+	subshs	\tmp, \tmp, \size	@ tmp = limit - (addr + size) }
+	movlo	\addr, #0		@ if (tmp < 0) addr = NULL
+	csdb
+#endif
+	.endm
+
+	.macro	uaccess_disable, tmp, isb=1
+#ifdef CONFIG_CPU_SW_DOMAIN_PAN
+	/*
+	 * Whenever we re-enter userspace, the domains should always be
+	 * set appropriately.
+	 */
+	mov	\tmp, #DACR_UACCESS_DISABLE
+	mcr	p15, 0, \tmp, c3, c0, 0		@ Set domain register
+	.if	\isb
+	instr_sync
+	.endif
+#endif
+	.endm
+
+	.macro	uaccess_enable, tmp, isb=1
+#ifdef CONFIG_CPU_SW_DOMAIN_PAN
+	/*
+	 * Whenever we re-enter userspace, the domains should always be
+	 * set appropriately.
+	 */
+	mov	\tmp, #DACR_UACCESS_ENABLE
+	mcr	p15, 0, \tmp, c3, c0, 0
+	.if	\isb
+	instr_sync
+	.endif
+#endif
+	.endm
+
+#if defined(CONFIG_CPU_SW_DOMAIN_PAN) || defined(CONFIG_CPU_USE_DOMAINS)
+#define DACR(x...)	x
+#else
+#define DACR(x...)
+#endif
+
+	/*
+	 * Save the address limit on entry to a privileged exception.
+	 *
+	 * If we are using the DACR for kernel access by the user accessors
+	 * (CONFIG_CPU_USE_DOMAINS=y), always reset the DACR kernel domain
+	 * back to client mode, whether or not \disable is set.
+	 *
+	 * If we are using SW PAN, set the DACR user domain to no access
+	 * if \disable is set.
+	 */
+	.macro	uaccess_entry, tsk, tmp0, tmp1, tmp2, disable
+	ldr	\tmp1, [\tsk, #TI_ADDR_LIMIT]
+	mov	\tmp2, #TASK_SIZE
+	str	\tmp2, [\tsk, #TI_ADDR_LIMIT]
+ DACR(	mrc	p15, 0, \tmp0, c3, c0, 0)
+ DACR(	str	\tmp0, [sp, #SVC_DACR])
+	str	\tmp1, [sp, #SVC_ADDR_LIMIT]
+	.if \disable && IS_ENABLED(CONFIG_CPU_SW_DOMAIN_PAN)
+	/* kernel=client, user=no access */
+	mov	\tmp2, #DACR_UACCESS_DISABLE
+	mcr	p15, 0, \tmp2, c3, c0, 0
+	instr_sync
+	.elseif IS_ENABLED(CONFIG_CPU_USE_DOMAINS)
+	/* kernel=client */
+	bic	\tmp2, \tmp0, #domain_mask(DOMAIN_KERNEL)
+	orr	\tmp2, \tmp2, #domain_val(DOMAIN_KERNEL, DOMAIN_CLIENT)
+	mcr	p15, 0, \tmp2, c3, c0, 0
+	instr_sync
+	.endif
+	.endm
+
+	/* Restore the user access state previously saved by uaccess_entry */
+	.macro	uaccess_exit, tsk, tmp0, tmp1
+	ldr	\tmp1, [sp, #SVC_ADDR_LIMIT]
+ DACR(	ldr	\tmp0, [sp, #SVC_DACR])
+	str	\tmp1, [\tsk, #TI_ADDR_LIMIT]
+ DACR(	mcr	p15, 0, \tmp0, c3, c0, 0)
+	.endm
+
+#undef DACR
+
+#endif /* __ASM_UACCESS_ASM_H__ */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/include/asm/uaccess.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/include/asm/uaccess.h
@@ -143,16 +143,6 @@
 extern int __get_user_64t_2(void *);
 extern int __get_user_64t_4(void *);
 
-#define __GUP_CLOBBER_1	"lr", "cc"
-#ifdef CONFIG_CPU_USE_DOMAINS
-#define __GUP_CLOBBER_2	"ip", "lr", "cc"
-#else
-#define __GUP_CLOBBER_2 "lr", "cc"
-#endif
-#define __GUP_CLOBBER_4	"lr", "cc"
-#define __GUP_CLOBBER_32t_8 "lr", "cc"
-#define __GUP_CLOBBER_8	"lr", "cc"
-
 #define __get_user_x(__r2, __p, __e, __l, __s)				\
 	   __asm__ __volatile__ (					\
 		__asmeq("%0", "r0") __asmeq("%1", "r2")			\
@@ -160,7 +150,7 @@
 		"bl	__get_user_" #__s				\
 		: "=&r" (__e), "=r" (__r2)				\
 		: "0" (__p), "r" (__l)					\
-		: __GUP_CLOBBER_##__s)
+		: "ip", "lr", "cc")
 
 /* narrowing a double-word get into a single 32bit word register: */
 #ifdef __ARMEB__
@@ -182,7 +172,7 @@
 		"bl	__get_user_64t_" #__s				\
 		: "=&r" (__e), "=r" (__r2)				\
 		: "0" (__p), "r" (__l)					\
-		: __GUP_CLOBBER_##__s)
+		: "ip", "lr", "cc")
 #else
 #define __get_user_x_64t __get_user_x
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/include/asm/vfpmacros.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/include/asm/vfpmacros.h
@@ -19,23 +19,25 @@
 
 	@ read all the working registers back into the VFP
 	.macro	VFPFLDMIA, base, tmp
+	.fpu	vfpv2
 #if __LINUX_ARM_ARCH__ < 6
-	LDC	p11, cr0, [\base],#33*4		    @ FLDMIAX \base!, {d0-d15}
+	fldmiax	\base!, {d0-d15}
 #else
-	LDC	p11, cr0, [\base],#32*4		    @ FLDMIAD \base!, {d0-d15}
+	vldmia	\base!, {d0-d15}
 #endif
 #ifdef CONFIG_VFPv3
+	.fpu	vfpv3
 #if __LINUX_ARM_ARCH__ <= 6
 	ldr	\tmp, =elf_hwcap		    @ may not have MVFR regs
 	ldr	\tmp, [\tmp, #0]
 	tst	\tmp, #HWCAP_VFPD32
-	ldclne	p11, cr0, [\base],#32*4		    @ FLDMIAD \base!, {d16-d31}
+	vldmiane \base!, {d16-d31}
 	addeq	\base, \base, #32*4		    @ step over unused register space
 #else
 	VFPFMRX	\tmp, MVFR0			    @ Media and VFP Feature Register 0
 	and	\tmp, \tmp, #MVFR0_A_SIMD_MASK	    @ A_SIMD field
 	cmp	\tmp, #2			    @ 32 x 64bit registers?
-	ldcleq	p11, cr0, [\base],#32*4		    @ FLDMIAD \base!, {d16-d31}
+	vldmiaeq \base!, {d16-d31}
 	addne	\base, \base, #32*4		    @ step over unused register space
 #endif
 #endif
@@ -44,22 +46,23 @@
 	@ write all the working registers out of the VFP
 	.macro	VFPFSTMIA, base, tmp
 #if __LINUX_ARM_ARCH__ < 6
-	STC	p11, cr0, [\base],#33*4		    @ FSTMIAX \base!, {d0-d15}
+	fstmiax	\base!, {d0-d15}
 #else
-	STC	p11, cr0, [\base],#32*4		    @ FSTMIAD \base!, {d0-d15}
+	vstmia	\base!, {d0-d15}
 #endif
 #ifdef CONFIG_VFPv3
+	.fpu	vfpv3
 #if __LINUX_ARM_ARCH__ <= 6
 	ldr	\tmp, =elf_hwcap		    @ may not have MVFR regs
 	ldr	\tmp, [\tmp, #0]
 	tst	\tmp, #HWCAP_VFPD32
-	stclne	p11, cr0, [\base],#32*4		    @ FSTMIAD \base!, {d16-d31}
+	vstmiane \base!, {d16-d31}
 	addeq	\base, \base, #32*4		    @ step over unused register space
 #else
 	VFPFMRX	\tmp, MVFR0			    @ Media and VFP Feature Register 0
 	and	\tmp, \tmp, #MVFR0_A_SIMD_MASK	    @ A_SIMD field
 	cmp	\tmp, #2			    @ 32 x 64bit registers?
-	stcleq	p11, cr0, [\base],#32*4		    @ FSTMIAD \base!, {d16-d31}
+	vstmiaeq \base!, {d16-d31}
 	addne	\base, \base, #32*4		    @ step over unused register space
 #endif
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/Makefile
@@ -17,10 +17,14 @@
 # Object file lists.
 
 obj-y		:= elf.o entry-common.o irq.o opcodes.o \
-		   process.o ptrace.o reboot.o return_address.o \
+		   process.o ptrace.o reboot.o \
 		   setup.o signal.o sigreturn_codes.o \
 		   stacktrace.o sys_arm.o time.o traps.o
 
+ifneq ($(CONFIG_ARM_UNWIND),y)
+obj-$(CONFIG_FRAME_POINTER)	+= return_address.o
+endif
+
 obj-$(CONFIG_ATAGS)		+= atags_parse.o
 obj-$(CONFIG_ATAGS_PROC)	+= atags_proc.o
 obj-$(CONFIG_DEPRECATED_PARAM_STRUCT) += atags_compat.o
@@ -102,4 +106,6 @@
 
 obj-$(CONFIG_HAVE_ARM_SMCCC)	+= smccc-call.o
 
+obj-$(CONFIG_GENERIC_CPU_VULNERABILITIES) += spectre.o
+
 extra-y := $(head-y) vmlinux.lds
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/asm-offsets.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/asm-offsets.c
@@ -15,6 +15,7 @@
 #include <linux/kvm_host.h>
 #endif
 #include <asm/cacheflush.h>
+#include <asm/kexec-internal.h>
 #include <asm/glue-df.h>
 #include <asm/glue-pf.h>
 #include <asm/mach/arch.h>
@@ -26,6 +27,7 @@
 #include <asm/vdso_datapage.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <linux/kbuild.h>
+#include <linux/arm-smccc.h>
 #include "signal.h"
 
 /*
@@ -159,6 +161,8 @@
   DEFINE(SLEEP_SAVE_SP_PHYS,	offsetof(struct sleep_save_sp, save_ptr_stash_phys));
   DEFINE(SLEEP_SAVE_SP_VIRT,	offsetof(struct sleep_save_sp, save_ptr_stash));
 #endif
+  DEFINE(ARM_SMCCC_QUIRK_ID_OFFS,	offsetof(struct arm_smccc_quirk, id));
+  DEFINE(ARM_SMCCC_QUIRK_STATE_OFFS,	offsetof(struct arm_smccc_quirk, state));
   BLANK();
   DEFINE(DMA_BIDIRECTIONAL,	DMA_BIDIRECTIONAL);
   DEFINE(DMA_TO_DEVICE,		DMA_TO_DEVICE);
@@ -190,5 +194,9 @@
   DEFINE(MPU_RGN_PRBAR,	offsetof(struct mpu_rgn, prbar));
   DEFINE(MPU_RGN_PRLAR,	offsetof(struct mpu_rgn, prlar));
 #endif
+  DEFINE(KEXEC_START_ADDR,	offsetof(struct kexec_relocate_data, kexec_start_address));
+  DEFINE(KEXEC_INDIR_PAGE,	offsetof(struct kexec_relocate_data, kexec_indirection_page));
+  DEFINE(KEXEC_MACH_TYPE,	offsetof(struct kexec_relocate_data, kexec_mach_type));
+  DEFINE(KEXEC_R2,		offsetof(struct kexec_relocate_data, kexec_r2));
   return 0; 
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/atags.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/atags.h
@@ -2,11 +2,11 @@
 void convert_to_tag_list(struct tag *tags);
 
 #ifdef CONFIG_ATAGS
-const struct machine_desc *setup_machine_tags(phys_addr_t __atags_pointer,
+const struct machine_desc *setup_machine_tags(void *__atags_vaddr,
 	unsigned int machine_nr);
 #else
 static inline const struct machine_desc * __init __noreturn
-setup_machine_tags(phys_addr_t __atags_pointer, unsigned int machine_nr)
+setup_machine_tags(void *__atags_vaddr, unsigned int machine_nr)
 {
 	early_print("no ATAGS support: can't continue\n");
 	while (true);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/atags_parse.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/atags_parse.c
@@ -176,7 +176,7 @@
 }
 
 const struct machine_desc * __init
-setup_machine_tags(phys_addr_t __atags_pointer, unsigned int machine_nr)
+setup_machine_tags(void *atags_vaddr, unsigned int machine_nr)
 {
 	struct tag *tags = (struct tag *)&default_tags;
 	const struct machine_desc *mdesc = NULL, *p;
@@ -197,8 +197,8 @@
 	if (!mdesc)
 		return NULL;
 
-	if (__atags_pointer)
-		tags = phys_to_virt(__atags_pointer);
+	if (atags_vaddr)
+		tags = atags_vaddr;
 	else if (mdesc->atag_offset)
 		tags = (void *)(PAGE_OFFSET + mdesc->atag_offset);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/bugs.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/bugs.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <linux/init.h>
+#include <linux/cpu.h>
 #include <asm/bugs.h>
 #include <asm/proc-fns.h>
 
@@ -11,7 +12,7 @@
 #endif
 }
 
-void __init check_bugs(void)
+void __init arch_cpu_finalize_init(void)
 {
 	check_writebuffer_bugs();
 	check_other_bugs();
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/devtree.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/devtree.c
@@ -203,12 +203,12 @@
 
 /**
  * setup_machine_fdt - Machine setup when an dtb was passed to the kernel
- * @dt_phys: physical address of dt blob
+ * @dt_virt: virtual address of dt blob
  *
  * If a dtb was passed to the kernel in r2, then use it to choose the
  * correct machine_desc and to setup the system.
  */
-const struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys)
+const struct machine_desc * __init setup_machine_fdt(void *dt_virt)
 {
 	const struct machine_desc *mdesc, *mdesc_best = NULL;
 
@@ -221,7 +221,7 @@
 	mdesc_best = &__mach_desc_GENERIC_DT;
 #endif
 
-	if (!dt_phys || !early_init_dt_verify(phys_to_virt(dt_phys)))
+	if (!dt_virt || !early_init_dt_verify(dt_virt))
 		return NULL;
 
 	mdesc = of_flat_dt_match_machine(mdesc_best, arch_get_next_mach);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/entry-armv.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/entry-armv.S
@@ -27,6 +27,7 @@
 #include <asm/unistd.h>
 #include <asm/tls.h>
 #include <asm/system_info.h>
+#include <asm/uaccess-asm.h>
 
 #include "entry-header.S"
 #include <asm/entry-macro-multi.S>
@@ -179,15 +180,7 @@
 	stmia	r7, {r2 - r6}
 
 	get_thread_info tsk
-	ldr	r0, [tsk, #TI_ADDR_LIMIT]
-	mov	r1, #TASK_SIZE
-	str	r1, [tsk, #TI_ADDR_LIMIT]
-	str	r0, [sp, #SVC_ADDR_LIMIT]
-
-	uaccess_save r0
-	.if \uaccess
-	uaccess_disable r0
-	.endif
+	uaccess_entry tsk, r0, r1, r2, \uaccess
 
 	.if \trace
 #ifdef CONFIG_TRACE_IRQFLAGS
@@ -259,31 +252,10 @@
 #else
 	svc_entry
 #endif
-	@
-	@ call emulation code, which returns using r9 if it has emulated
-	@ the instruction, or the more conventional lr if we are to treat
-	@ this as a real undefined instruction
-	@
-	@  r0 - instruction
-	@
-#ifndef CONFIG_THUMB2_KERNEL
-	ldr	r0, [r4, #-4]
-#else
-	mov	r1, #2
-	ldrh	r0, [r4, #-2]			@ Thumb instruction at LR - 2
-	cmp	r0, #0xe800			@ 32-bit instruction if xx >= 0
-	blo	__und_svc_fault
-	ldrh	r9, [r4]			@ bottom 16 bits
-	add	r4, r4, #2
-	str	r4, [sp, #S_PC]
-	orr	r0, r9, r0, lsl #16
-#endif
-	badr	r9, __und_svc_finish
-	mov	r2, r4
-	bl	call_fpe
 
 	mov	r1, #4				@ PC correction to apply
-__und_svc_fault:
+ THUMB(	tst	r5, #PSR_T_BIT		)	@ exception taken in Thumb mode?
+ THUMB(	movne	r1, #2			)	@ if so, fix up PC correction
 	mov	r0, sp				@ struct pt_regs *regs
 	bl	__und_fault
 
@@ -624,11 +596,9 @@
 	tstne	r0, #0x04000000			@ bit 26 set on both ARM and Thumb-2
 	reteq	lr
 	and	r8, r0, #0x00000f00		@ mask out CP number
- THUMB(	lsr	r8, r8, #8		)
 	mov	r7, #1
-	add	r6, r10, #TI_USED_CP
- ARM(	strb	r7, [r6, r8, lsr #8]	)	@ set appropriate used_cp[]
- THUMB(	strb	r7, [r6, r8]		)	@ set appropriate used_cp[]
+	add	r6, r10, r8, lsr #8		@ add used_cp[] array offset first
+	strb	r7, [r6, #TI_USED_CP]		@ set appropriate used_cp[]
 #ifdef CONFIG_IWMMXT
 	@ Test if we need to give access to iWMMXt coprocessors
 	ldr	r5, [r10, #TI_FLAGS]
@@ -637,7 +607,7 @@
 	bcs	iwmmxt_task_enable
 #endif
  ARM(	add	pc, pc, r8, lsr #6	)
- THUMB(	lsl	r8, r8, #2		)
+ THUMB(	lsr	r8, r8, #6		)
  THUMB(	add	pc, r8			)
 	nop
 
@@ -1035,12 +1005,11 @@
 	sub	lr, lr, #\correction
 	.endif
 
-	@
-	@ Save r0, lr_<exception> (parent PC) and spsr_<exception>
-	@ (parent CPSR)
-	@
+	@ Save r0, lr_<exception> (parent PC)
 	stmia	sp, {r0, lr}		@ save r0, lr
-	mrs	lr, spsr
+
+	@ Save spsr_<exception> (parent CPSR)
+2:	mrs	lr, spsr
 	str	lr, [sp, #8]		@ save spsr
 
 	@
@@ -1061,6 +1030,44 @@
 	movs	pc, lr			@ branch to handler in SVC mode
 ENDPROC(vector_\name)
 
+#ifdef CONFIG_HARDEN_BRANCH_HISTORY
+	.subsection 1
+	.align 5
+vector_bhb_loop8_\name:
+	.if \correction
+	sub	lr, lr, #\correction
+	.endif
+
+	@ Save r0, lr_<exception> (parent PC)
+	stmia	sp, {r0, lr}
+
+	@ bhb workaround
+	mov	r0, #8
+3:	W(b)	. + 4
+	subs	r0, r0, #1
+	bne	3b
+	dsb
+	isb
+	b	2b
+ENDPROC(vector_bhb_loop8_\name)
+
+vector_bhb_bpiall_\name:
+	.if \correction
+	sub	lr, lr, #\correction
+	.endif
+
+	@ Save r0, lr_<exception> (parent PC)
+	stmia	sp, {r0, lr}
+
+	@ bhb workaround
+	mcr	p15, 0, r0, c7, c5, 6	@ BPIALL
+	@ isb not needed due to "movs pc, lr" in the vector stub
+	@ which gives a "context synchronisation".
+	b	2b
+ENDPROC(vector_bhb_bpiall_\name)
+	.previous
+#endif
+
 	.align	2
 	@ handler addresses follow this label
 1:
@@ -1069,6 +1076,10 @@
 	.section .stubs, "ax", %progbits
 	@ This must be the first word
 	.word	vector_swi
+#ifdef CONFIG_HARDEN_BRANCH_HISTORY
+	.word	vector_bhb_loop8_swi
+	.word	vector_bhb_bpiall_swi
+#endif
 
 vector_rst:
  ARM(	swi	SYS_ERROR0	)
@@ -1183,8 +1194,10 @@
  * FIQ "NMI" handler
  *-----------------------------------------------------------------------------
  * Handle a FIQ using the SVC stack allowing FIQ act like NMI on x86
- * systems.
+ * systems. This must be the last vector stub, so lets place it in its own
+ * subsection.
  */
+	.subsection 2
 	vector_stub	fiq, FIQ_MODE, 4
 
 	.long	__fiq_usr			@  0  (USR_26 / USR_32)
@@ -1217,6 +1230,30 @@
 	W(b)	vector_irq
 	W(b)	vector_fiq
 
+#ifdef CONFIG_HARDEN_BRANCH_HISTORY
+	.section .vectors.bhb.loop8, "ax", %progbits
+.L__vectors_bhb_loop8_start:
+	W(b)	vector_rst
+	W(b)	vector_bhb_loop8_und
+	W(ldr)	pc, .L__vectors_bhb_loop8_start + 0x1004
+	W(b)	vector_bhb_loop8_pabt
+	W(b)	vector_bhb_loop8_dabt
+	W(b)	vector_addrexcptn
+	W(b)	vector_bhb_loop8_irq
+	W(b)	vector_bhb_loop8_fiq
+
+	.section .vectors.bhb.bpiall, "ax", %progbits
+.L__vectors_bhb_bpiall_start:
+	W(b)	vector_rst
+	W(b)	vector_bhb_bpiall_und
+	W(ldr)	pc, .L__vectors_bhb_bpiall_start + 0x1008
+	W(b)	vector_bhb_bpiall_pabt
+	W(b)	vector_bhb_bpiall_dabt
+	W(b)	vector_addrexcptn
+	W(b)	vector_bhb_bpiall_irq
+	W(b)	vector_bhb_bpiall_fiq
+#endif
+
 	.data
 	.align	2
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/entry-common.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/entry-common.S
@@ -163,12 +163,36 @@
  */
 
 	.align	5
+#ifdef CONFIG_HARDEN_BRANCH_HISTORY
+ENTRY(vector_bhb_loop8_swi)
+	sub	sp, sp, #PT_REGS_SIZE
+	stmia	sp, {r0 - r12}
+	mov	r8, #8
+1:	b	2f
+2:	subs	r8, r8, #1
+	bne	1b
+	dsb
+	isb
+	b	3f
+ENDPROC(vector_bhb_loop8_swi)
+
+	.align	5
+ENTRY(vector_bhb_bpiall_swi)
+	sub	sp, sp, #PT_REGS_SIZE
+	stmia	sp, {r0 - r12}
+	mcr	p15, 0, r8, c7, c5, 6	@ BPIALL
+	isb
+	b	3f
+ENDPROC(vector_bhb_bpiall_swi)
+#endif
+	.align	5
 ENTRY(vector_swi)
 #ifdef CONFIG_CPU_V7M
 	v7m_exception_entry
 #else
 	sub	sp, sp, #PT_REGS_SIZE
 	stmia	sp, {r0 - r12}			@ Calling r0 - r12
+3:
  ARM(	add	r8, sp, #S_PC		)
  ARM(	stmdb	r8, {sp, lr}^		)	@ Calling sp, lr
  THUMB(	mov	r8, sp			)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/entry-header.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/entry-header.S
@@ -6,6 +6,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/errno.h>
 #include <asm/thread_info.h>
+#include <asm/uaccess-asm.h>
 #include <asm/v7m.h>
 
 @ Bad Abort numbers
@@ -217,9 +218,7 @@
 	blne	trace_hardirqs_off
 #endif
 	.endif
-	ldr	r1, [sp, #SVC_ADDR_LIMIT]
-	uaccess_restore
-	str	r1, [tsk, #TI_ADDR_LIMIT]
+	uaccess_exit tsk, r0, r1
 
 #ifndef CONFIG_THUMB2_KERNEL
 	@ ARM mode SVC restore
@@ -263,9 +262,7 @@
 	@ on the stack remains correct).
 	@
 	.macro  svc_exit_via_fiq
-	ldr	r1, [sp, #SVC_ADDR_LIMIT]
-	uaccess_restore
-	str	r1, [tsk, #TI_ADDR_LIMIT]
+	uaccess_exit tsk, r0, r1
 #ifndef CONFIG_THUMB2_KERNEL
 	@ ARM mode restore
 	mov	r0, sp
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/ftrace.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/ftrace.c
@@ -71,9 +71,10 @@
 	return 0;
 }
 
-static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr)
+static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr,
+					 bool warn)
 {
-	return arm_gen_branch_link(pc, addr);
+	return arm_gen_branch_link(pc, addr, warn);
 }
 
 static int ftrace_modify_code(unsigned long pc, unsigned long old,
@@ -112,14 +113,14 @@
 	int ret;
 
 	pc = (unsigned long)&ftrace_call;
-	new = ftrace_call_replace(pc, (unsigned long)func);
+	new = ftrace_call_replace(pc, (unsigned long)func, true);
 
 	ret = ftrace_modify_code(pc, 0, new, false);
 
 #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
 	if (!ret) {
 		pc = (unsigned long)&ftrace_regs_call;
-		new = ftrace_call_replace(pc, (unsigned long)func);
+		new = ftrace_call_replace(pc, (unsigned long)func, true);
 
 		ret = ftrace_modify_code(pc, 0, new, false);
 	}
@@ -132,10 +133,22 @@
 {
 	unsigned long new, old;
 	unsigned long ip = rec->ip;
+	unsigned long aaddr = adjust_address(rec, addr);
+	struct module *mod = NULL;
+
+#ifdef CONFIG_ARM_MODULE_PLTS
+	mod = rec->arch.mod;
+#endif
 
 	old = ftrace_nop_replace(rec);
 
-	new = ftrace_call_replace(ip, adjust_address(rec, addr));
+	new = ftrace_call_replace(ip, aaddr, !mod);
+#ifdef CONFIG_ARM_MODULE_PLTS
+	if (!new && mod) {
+		aaddr = get_module_plt(mod, ip, aaddr);
+		new = ftrace_call_replace(ip, aaddr, true);
+	}
+#endif
 
 	return ftrace_modify_code(rec->ip, old, new, true);
 }
@@ -148,9 +161,9 @@
 	unsigned long new, old;
 	unsigned long ip = rec->ip;
 
-	old = ftrace_call_replace(ip, adjust_address(rec, old_addr));
+	old = ftrace_call_replace(ip, adjust_address(rec, old_addr), true);
 
-	new = ftrace_call_replace(ip, adjust_address(rec, addr));
+	new = ftrace_call_replace(ip, adjust_address(rec, addr), true);
 
 	return ftrace_modify_code(rec->ip, old, new, true);
 }
@@ -160,12 +173,29 @@
 int ftrace_make_nop(struct module *mod,
 		    struct dyn_ftrace *rec, unsigned long addr)
 {
+	unsigned long aaddr = adjust_address(rec, addr);
 	unsigned long ip = rec->ip;
 	unsigned long old;
 	unsigned long new;
 	int ret;
 
-	old = ftrace_call_replace(ip, adjust_address(rec, addr));
+#ifdef CONFIG_ARM_MODULE_PLTS
+	/* mod is only supplied during module loading */
+	if (!mod)
+		mod = rec->arch.mod;
+	else
+		rec->arch.mod = mod;
+#endif
+
+	old = ftrace_call_replace(ip, aaddr,
+				  !IS_ENABLED(CONFIG_ARM_MODULE_PLTS) || !mod);
+#ifdef CONFIG_ARM_MODULE_PLTS
+	if (!old && mod) {
+		aaddr = get_module_plt(mod, ip, aaddr);
+		old = ftrace_call_replace(ip, aaddr, true);
+	}
+#endif
+
 	new = ftrace_nop_replace(rec);
 	ret = ftrace_modify_code(ip, old, new, true);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/head.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/head.S
@@ -274,11 +274,10 @@
 	 * We map 2 sections in case the ATAGs/DTB crosses a section boundary.
 	 */
 	mov	r0, r2, lsr #SECTION_SHIFT
-	movs	r0, r0, lsl #SECTION_SHIFT
-	subne	r3, r0, r8
-	addne	r3, r3, #PAGE_OFFSET
-	addne	r3, r4, r3, lsr #(SECTION_SHIFT - PMD_ORDER)
-	orrne	r6, r7, r0
+	cmp	r2, #0
+	ldrne	r3, =FDT_FIXED_BASE >> (SECTION_SHIFT - PMD_ORDER)
+	addne	r3, r3, r4
+	orrne	r6, r7, r0, lsl #SECTION_SHIFT
 	strne	r6, [r3], #1 << PMD_ORDER
 	addne	r6, r6, #1 << SECTION_SHIFT
 	strne	r6, [r3]
@@ -672,11 +671,7 @@
 	bcc	1b
 	bx	lr
 #else
-#ifdef CONFIG_CPU_ENDIAN_BE8
-	moveq	r0, #0x00004000	@ set bit 22, mov to mvn instruction
-#else
 	moveq	r0, #0x400000	@ set bit 22, mov to mvn instruction
-#endif
 	b	2f
 1:	ldr	ip, [r7, r3]
 #ifdef CONFIG_CPU_ENDIAN_BE8
@@ -685,7 +680,7 @@
 	tst	ip, #0x000f0000	@ check the rotation field
 	orrne	ip, ip, r6, lsl #24 @ mask in offset bits 31-24
 	biceq	ip, ip, #0x00004000 @ clear bit 22
-	orreq	ip, ip, r0      @ mask in offset bits 7-0
+	orreq	ip, ip, r0, ror #8  @ mask in offset bits 7-0
 #else
 	bic	ip, ip, #0x000000ff
 	tst	ip, #0xf00	@ check the rotation field
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/hw_breakpoint.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/hw_breakpoint.c
@@ -623,7 +623,7 @@
 	hw->address &= ~alignment_mask;
 	hw->ctrl.len <<= offset;
 
-	if (is_default_overflow_handler(bp)) {
+	if (uses_default_overflow_handler(bp)) {
 		/*
 		 * Mismatch breakpoints are required for single-stepping
 		 * breakpoints.
@@ -680,26 +680,68 @@
 	arch_install_hw_breakpoint(bp);
 }
 
+/*
+ * Arm32 hardware does not always report a watchpoint hit address that matches
+ * one of the watchpoints set. It can also report an address "near" the
+ * watchpoint if a single instruction access both watched and unwatched
+ * addresses. There is no straight-forward way, short of disassembling the
+ * offending instruction, to map that address back to the watchpoint. This
+ * function computes the distance of the memory access from the watchpoint as a
+ * heuristic for the likelyhood that a given access triggered the watchpoint.
+ *
+ * See this same function in the arm64 platform code, which has the same
+ * problem.
+ *
+ * The function returns the distance of the address from the bytes watched by
+ * the watchpoint. In case of an exact match, it returns 0.
+ */
+static u32 get_distance_from_watchpoint(unsigned long addr, u32 val,
+					struct arch_hw_breakpoint_ctrl *ctrl)
+{
+	u32 wp_low, wp_high;
+	u32 lens, lene;
+
+	lens = __ffs(ctrl->len);
+	lene = __fls(ctrl->len);
+
+	wp_low = val + lens;
+	wp_high = val + lene;
+	if (addr < wp_low)
+		return wp_low - addr;
+	else if (addr > wp_high)
+		return addr - wp_high;
+	else
+		return 0;
+}
+
+static int watchpoint_fault_on_uaccess(struct pt_regs *regs,
+				       struct arch_hw_breakpoint *info)
+{
+	return !user_mode(regs) && info->ctrl.privilege == ARM_BREAKPOINT_USER;
+}
+
 static void watchpoint_handler(unsigned long addr, unsigned int fsr,
 			       struct pt_regs *regs)
 {
-	int i, access;
-	u32 val, ctrl_reg, alignment_mask;
+	int i, access, closest_match = 0;
+	u32 min_dist = -1, dist;
+	u32 val, ctrl_reg;
 	struct perf_event *wp, **slots;
 	struct arch_hw_breakpoint *info;
 	struct arch_hw_breakpoint_ctrl ctrl;
 
 	slots = this_cpu_ptr(wp_on_reg);
 
+	/*
+	 * Find all watchpoints that match the reported address. If no exact
+	 * match is found. Attribute the hit to the closest watchpoint.
+	 */
+	rcu_read_lock();
 	for (i = 0; i < core_num_wrps; ++i) {
-		rcu_read_lock();
-
 		wp = slots[i];
-
 		if (wp == NULL)
-			goto unlock;
+			continue;
 
-		info = counter_arch_bp(wp);
 		/*
 		 * The DFAR is an unknown value on debug architectures prior
 		 * to 7.1. Since we only allow a single watchpoint on these
@@ -708,50 +750,69 @@
 		 */
 		if (debug_arch < ARM_DEBUG_ARCH_V7_1) {
 			BUG_ON(i > 0);
+			info = counter_arch_bp(wp);
 			info->trigger = wp->attr.bp_addr;
 		} else {
-			if (info->ctrl.len == ARM_BREAKPOINT_LEN_8)
-				alignment_mask = 0x7;
-			else
-				alignment_mask = 0x3;
-
-			/* Check if the watchpoint value matches. */
-			val = read_wb_reg(ARM_BASE_WVR + i);
-			if (val != (addr & ~alignment_mask))
-				goto unlock;
-
-			/* Possible match, check the byte address select. */
-			ctrl_reg = read_wb_reg(ARM_BASE_WCR + i);
-			decode_ctrl_reg(ctrl_reg, &ctrl);
-			if (!((1 << (addr & alignment_mask)) & ctrl.len))
-				goto unlock;
-
 			/* Check that the access type matches. */
 			if (debug_exception_updates_fsr()) {
 				access = (fsr & ARM_FSR_ACCESS_MASK) ?
 					  HW_BREAKPOINT_W : HW_BREAKPOINT_R;
 				if (!(access & hw_breakpoint_type(wp)))
-					goto unlock;
+					continue;
+			}
+
+			val = read_wb_reg(ARM_BASE_WVR + i);
+			ctrl_reg = read_wb_reg(ARM_BASE_WCR + i);
+			decode_ctrl_reg(ctrl_reg, &ctrl);
+			dist = get_distance_from_watchpoint(addr, val, &ctrl);
+			if (dist < min_dist) {
+				min_dist = dist;
+				closest_match = i;
 			}
+			/* Is this an exact match? */
+			if (dist != 0)
+				continue;
 
 			/* We have a winner. */
+			info = counter_arch_bp(wp);
 			info->trigger = addr;
 		}
 
 		pr_debug("watchpoint fired: address = 0x%x\n", info->trigger);
+
+		/*
+		 * If we triggered a user watchpoint from a uaccess routine,
+		 * then handle the stepping ourselves since userspace really
+		 * can't help us with this.
+		 */
+		if (watchpoint_fault_on_uaccess(regs, info))
+			goto step;
+
 		perf_bp_event(wp, regs);
 
 		/*
-		 * If no overflow handler is present, insert a temporary
-		 * mismatch breakpoint so we can single-step over the
-		 * watchpoint trigger.
+		 * Defer stepping to the overflow handler if one is installed.
+		 * Otherwise, insert a temporary mismatch breakpoint so that
+		 * we can single-step over the watchpoint trigger.
 		 */
-		if (is_default_overflow_handler(wp))
-			enable_single_step(wp, instruction_pointer(regs));
+		if (!uses_default_overflow_handler(wp))
+			continue;
+step:
+		enable_single_step(wp, instruction_pointer(regs));
+	}
 
-unlock:
-		rcu_read_unlock();
+	if (min_dist > 0 && min_dist != -1) {
+		/* No exact match found. */
+		wp = slots[closest_match];
+		info = counter_arch_bp(wp);
+		info->trigger = addr;
+		pr_debug("watchpoint fired: address = 0x%x\n", info->trigger);
+		perf_bp_event(wp, regs);
+		if (uses_default_overflow_handler(wp))
+			enable_single_step(wp, instruction_pointer(regs));
 	}
+
+	rcu_read_unlock();
 }
 
 static void watchpoint_single_step_handler(unsigned long pc)
@@ -822,7 +883,7 @@
 			info->trigger = addr;
 			pr_debug("breakpoint fired: address = 0x%x\n", addr);
 			perf_bp_event(bp, regs);
-			if (!bp->overflow_handler)
+			if (uses_default_overflow_handler(bp))
 				enable_single_step(bp, addr);
 			goto unlock;
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/hyp-stub.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/hyp-stub.S
@@ -146,10 +146,9 @@
 #if !defined(ZIMAGE) && defined(CONFIG_ARM_ARCH_TIMER)
 	@ make CNTP_* and CNTPCT accessible from PL1
 	mrc	p15, 0, r7, c0, c1, 1	@ ID_PFR1
-	lsr	r7, #16
-	and	r7, #0xf
-	cmp	r7, #1
-	bne	1f
+	ubfx	r7, r7, #16, #4
+	teq	r7, #0
+	beq	1f
 	mrc	p15, 4, r7, c14, c1, 0	@ CNTHCTL
 	orr	r7, r7, #3		@ PL1PCEN | PL1PCTEN
 	mcr	p15, 4, r7, c14, c1, 0	@ CNTHCTL
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/insn.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/insn.c
@@ -3,8 +3,9 @@
 #include <linux/kernel.h>
 #include <asm/opcodes.h>
 
-static unsigned long
-__arm_gen_branch_thumb2(unsigned long pc, unsigned long addr, bool link)
+static unsigned long __arm_gen_branch_thumb2(unsigned long pc,
+					     unsigned long addr, bool link,
+					     bool warn)
 {
 	unsigned long s, j1, j2, i1, i2, imm10, imm11;
 	unsigned long first, second;
@@ -12,7 +13,7 @@
 
 	offset = (long)addr - (long)(pc + 4);
 	if (offset < -16777216 || offset > 16777214) {
-		WARN_ON_ONCE(1);
+		WARN_ON_ONCE(warn);
 		return 0;
 	}
 
@@ -33,8 +34,8 @@
 	return __opcode_thumb32_compose(first, second);
 }
 
-static unsigned long
-__arm_gen_branch_arm(unsigned long pc, unsigned long addr, bool link)
+static unsigned long __arm_gen_branch_arm(unsigned long pc, unsigned long addr,
+					  bool link, bool warn)
 {
 	unsigned long opcode = 0xea000000;
 	long offset;
@@ -44,7 +45,7 @@
 
 	offset = (long)addr - (long)(pc + 8);
 	if (unlikely(offset < -33554432 || offset > 33554428)) {
-		WARN_ON_ONCE(1);
+		WARN_ON_ONCE(warn);
 		return 0;
 	}
 
@@ -54,10 +55,10 @@
 }
 
 unsigned long
-__arm_gen_branch(unsigned long pc, unsigned long addr, bool link)
+__arm_gen_branch(unsigned long pc, unsigned long addr, bool link, bool warn)
 {
 	if (IS_ENABLED(CONFIG_THUMB2_KERNEL))
-		return __arm_gen_branch_thumb2(pc, addr, link);
+		return __arm_gen_branch_thumb2(pc, addr, link, warn);
 	else
-		return __arm_gen_branch_arm(pc, addr, link);
+		return __arm_gen_branch_arm(pc, addr, link, warn);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/iwmmxt.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/iwmmxt.S
@@ -16,6 +16,7 @@
 #include <asm/thread_info.h>
 #include <asm/asm-offsets.h>
 #include <asm/assembler.h>
+#include "iwmmxt.h"
 
 #if defined(CONFIG_CPU_PJ4) || defined(CONFIG_CPU_PJ4B)
 #define PJ4(code...)		code
@@ -113,33 +114,33 @@
 
 concan_dump:
 
-	wstrw	wCSSF, [r1, #MMX_WCSSF]
-	wstrw	wCASF, [r1, #MMX_WCASF]
-	wstrw	wCGR0, [r1, #MMX_WCGR0]
-	wstrw	wCGR1, [r1, #MMX_WCGR1]
-	wstrw	wCGR2, [r1, #MMX_WCGR2]
-	wstrw	wCGR3, [r1, #MMX_WCGR3]
+	wstrw	wCSSF, r1, MMX_WCSSF
+	wstrw	wCASF, r1, MMX_WCASF
+	wstrw	wCGR0, r1, MMX_WCGR0
+	wstrw	wCGR1, r1, MMX_WCGR1
+	wstrw	wCGR2, r1, MMX_WCGR2
+	wstrw	wCGR3, r1, MMX_WCGR3
 
 1:	@ MUP? wRn
 	tst	r2, #0x2
 	beq	2f
 
-	wstrd	wR0,  [r1, #MMX_WR0]
-	wstrd	wR1,  [r1, #MMX_WR1]
-	wstrd	wR2,  [r1, #MMX_WR2]
-	wstrd	wR3,  [r1, #MMX_WR3]
-	wstrd	wR4,  [r1, #MMX_WR4]
-	wstrd	wR5,  [r1, #MMX_WR5]
-	wstrd	wR6,  [r1, #MMX_WR6]
-	wstrd	wR7,  [r1, #MMX_WR7]
-	wstrd	wR8,  [r1, #MMX_WR8]
-	wstrd	wR9,  [r1, #MMX_WR9]
-	wstrd	wR10, [r1, #MMX_WR10]
-	wstrd	wR11, [r1, #MMX_WR11]
-	wstrd	wR12, [r1, #MMX_WR12]
-	wstrd	wR13, [r1, #MMX_WR13]
-	wstrd	wR14, [r1, #MMX_WR14]
-	wstrd	wR15, [r1, #MMX_WR15]
+	wstrd	wR0,  r1, MMX_WR0
+	wstrd	wR1,  r1, MMX_WR1
+	wstrd	wR2,  r1, MMX_WR2
+	wstrd	wR3,  r1, MMX_WR3
+	wstrd	wR4,  r1, MMX_WR4
+	wstrd	wR5,  r1, MMX_WR5
+	wstrd	wR6,  r1, MMX_WR6
+	wstrd	wR7,  r1, MMX_WR7
+	wstrd	wR8,  r1, MMX_WR8
+	wstrd	wR9,  r1, MMX_WR9
+	wstrd	wR10, r1, MMX_WR10
+	wstrd	wR11, r1, MMX_WR11
+	wstrd	wR12, r1, MMX_WR12
+	wstrd	wR13, r1, MMX_WR13
+	wstrd	wR14, r1, MMX_WR14
+	wstrd	wR15, r1, MMX_WR15
 
 2:	teq	r0, #0				@ anything to load?
 	reteq	lr				@ if not, return
@@ -147,30 +148,30 @@
 concan_load:
 
 	@ Load wRn
-	wldrd	wR0,  [r0, #MMX_WR0]
-	wldrd	wR1,  [r0, #MMX_WR1]
-	wldrd	wR2,  [r0, #MMX_WR2]
-	wldrd	wR3,  [r0, #MMX_WR3]
-	wldrd	wR4,  [r0, #MMX_WR4]
-	wldrd	wR5,  [r0, #MMX_WR5]
-	wldrd	wR6,  [r0, #MMX_WR6]
-	wldrd	wR7,  [r0, #MMX_WR7]
-	wldrd	wR8,  [r0, #MMX_WR8]
-	wldrd	wR9,  [r0, #MMX_WR9]
-	wldrd	wR10, [r0, #MMX_WR10]
-	wldrd	wR11, [r0, #MMX_WR11]
-	wldrd	wR12, [r0, #MMX_WR12]
-	wldrd	wR13, [r0, #MMX_WR13]
-	wldrd	wR14, [r0, #MMX_WR14]
-	wldrd	wR15, [r0, #MMX_WR15]
+	wldrd	wR0,  r0, MMX_WR0
+	wldrd	wR1,  r0, MMX_WR1
+	wldrd	wR2,  r0, MMX_WR2
+	wldrd	wR3,  r0, MMX_WR3
+	wldrd	wR4,  r0, MMX_WR4
+	wldrd	wR5,  r0, MMX_WR5
+	wldrd	wR6,  r0, MMX_WR6
+	wldrd	wR7,  r0, MMX_WR7
+	wldrd	wR8,  r0, MMX_WR8
+	wldrd	wR9,  r0, MMX_WR9
+	wldrd	wR10, r0, MMX_WR10
+	wldrd	wR11, r0, MMX_WR11
+	wldrd	wR12, r0, MMX_WR12
+	wldrd	wR13, r0, MMX_WR13
+	wldrd	wR14, r0, MMX_WR14
+	wldrd	wR15, r0, MMX_WR15
 
 	@ Load wCx
-	wldrw	wCSSF, [r0, #MMX_WCSSF]
-	wldrw	wCASF, [r0, #MMX_WCASF]
-	wldrw	wCGR0, [r0, #MMX_WCGR0]
-	wldrw	wCGR1, [r0, #MMX_WCGR1]
-	wldrw	wCGR2, [r0, #MMX_WCGR2]
-	wldrw	wCGR3, [r0, #MMX_WCGR3]
+	wldrw	wCSSF, r0, MMX_WCSSF
+	wldrw	wCASF, r0, MMX_WCASF
+	wldrw	wCGR0, r0, MMX_WCGR0
+	wldrw	wCGR1, r0, MMX_WCGR1
+	wldrw	wCGR2, r0, MMX_WCGR2
+	wldrw	wCGR3, r0, MMX_WCGR3
 
 	@ clear CUP/MUP (only if r1 != 0)
 	teq	r1, #0
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/iwmmxt.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/iwmmxt.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __IWMMXT_H__
+#define __IWMMXT_H__
+
+.irp b, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+.set .LwR\b, \b
+.set .Lr\b, \b
+.endr
+
+.set .LwCSSF, 0x2
+.set .LwCASF, 0x3
+.set .LwCGR0, 0x8
+.set .LwCGR1, 0x9
+.set .LwCGR2, 0xa
+.set .LwCGR3, 0xb
+
+.macro wldrd, reg:req, base:req, offset:req
+.inst 0xedd00100 | (.L\reg << 12) | (.L\base << 16) | (\offset >> 2)
+.endm
+
+.macro wldrw, reg:req, base:req, offset:req
+.inst 0xfd900100 | (.L\reg << 12) | (.L\base << 16) | (\offset >> 2)
+.endm
+
+.macro wstrd, reg:req, base:req, offset:req
+.inst 0xedc00100 | (.L\reg << 12) | (.L\base << 16) | (\offset >> 2)
+.endm
+
+.macro wstrw, reg:req, base:req, offset:req
+.inst 0xfd800100 | (.L\reg << 12) | (.L\base << 16) | (\offset >> 2)
+.endm
+
+#ifdef __clang__
+
+#define wCon c1
+
+.macro tmrc, dest:req, control:req
+mrc p1, 0, \dest, \control, c0, 0
+.endm
+
+.macro tmcr, control:req, src:req
+mcr p1, 0, \src, \control, c0, 0
+.endm
+#endif
+
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/kgdb.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/kgdb.c
@@ -154,22 +154,38 @@
 	return 0;
 }
 
-static struct undef_hook kgdb_brkpt_hook = {
+static struct undef_hook kgdb_brkpt_arm_hook = {
 	.instr_mask		= 0xffffffff,
 	.instr_val		= KGDB_BREAKINST,
-	.cpsr_mask		= MODE_MASK,
+	.cpsr_mask		= PSR_T_BIT | MODE_MASK,
 	.cpsr_val		= SVC_MODE,
 	.fn			= kgdb_brk_fn
 };
 
-static struct undef_hook kgdb_compiled_brkpt_hook = {
+static struct undef_hook kgdb_brkpt_thumb_hook = {
+	.instr_mask		= 0xffff,
+	.instr_val		= KGDB_BREAKINST & 0xffff,
+	.cpsr_mask		= PSR_T_BIT | MODE_MASK,
+	.cpsr_val		= PSR_T_BIT | SVC_MODE,
+	.fn			= kgdb_brk_fn
+};
+
+static struct undef_hook kgdb_compiled_brkpt_arm_hook = {
 	.instr_mask		= 0xffffffff,
 	.instr_val		= KGDB_COMPILED_BREAK,
-	.cpsr_mask		= MODE_MASK,
+	.cpsr_mask		= PSR_T_BIT | MODE_MASK,
 	.cpsr_val		= SVC_MODE,
 	.fn			= kgdb_compiled_brk_fn
 };
 
+static struct undef_hook kgdb_compiled_brkpt_thumb_hook = {
+	.instr_mask		= 0xffff,
+	.instr_val		= KGDB_COMPILED_BREAK & 0xffff,
+	.cpsr_mask		= PSR_T_BIT | MODE_MASK,
+	.cpsr_val		= PSR_T_BIT | SVC_MODE,
+	.fn			= kgdb_compiled_brk_fn
+};
+
 static int __kgdb_notify(struct die_args *args, unsigned long cmd)
 {
 	struct pt_regs *regs = args->regs;
@@ -210,8 +226,10 @@
 	if (ret != 0)
 		return ret;
 
-	register_undef_hook(&kgdb_brkpt_hook);
-	register_undef_hook(&kgdb_compiled_brkpt_hook);
+	register_undef_hook(&kgdb_brkpt_arm_hook);
+	register_undef_hook(&kgdb_brkpt_thumb_hook);
+	register_undef_hook(&kgdb_compiled_brkpt_arm_hook);
+	register_undef_hook(&kgdb_compiled_brkpt_thumb_hook);
 
 	return 0;
 }
@@ -224,8 +242,10 @@
  */
 void kgdb_arch_exit(void)
 {
-	unregister_undef_hook(&kgdb_brkpt_hook);
-	unregister_undef_hook(&kgdb_compiled_brkpt_hook);
+	unregister_undef_hook(&kgdb_brkpt_arm_hook);
+	unregister_undef_hook(&kgdb_brkpt_thumb_hook);
+	unregister_undef_hook(&kgdb_compiled_brkpt_arm_hook);
+	unregister_undef_hook(&kgdb_compiled_brkpt_thumb_hook);
 	unregister_die_notifier(&kgdb_notifier);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/machine_kexec.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/machine_kexec.c
@@ -15,6 +15,7 @@
 #include <asm/pgalloc.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
+#include <asm/kexec-internal.h>
 #include <asm/fncpy.h>
 #include <asm/mach-types.h>
 #include <asm/smp_plat.h>
@@ -24,11 +25,6 @@
 extern void relocate_new_kernel(void);
 extern const unsigned int relocate_new_kernel_size;
 
-extern unsigned long kexec_start_address;
-extern unsigned long kexec_indirection_page;
-extern unsigned long kexec_mach_type;
-extern unsigned long kexec_boot_atags;
-
 static atomic_t waiting_for_crash_ipi;
 
 /*
@@ -161,6 +157,7 @@
 void machine_kexec(struct kimage *image)
 {
 	unsigned long page_list, reboot_entry_phys;
+	struct kexec_relocate_data *data;
 	void (*reboot_entry)(void);
 	void *reboot_code_buffer;
 
@@ -176,18 +173,17 @@
 
 	reboot_code_buffer = page_address(image->control_code_page);
 
-	/* Prepare parameters for reboot_code_buffer*/
-	set_kernel_text_rw();
-	kexec_start_address = image->start;
-	kexec_indirection_page = page_list;
-	kexec_mach_type = machine_arch_type;
-	kexec_boot_atags = image->arch.kernel_r2;
-
 	/* copy our kernel relocation code to the control code page */
 	reboot_entry = fncpy(reboot_code_buffer,
 			     &relocate_new_kernel,
 			     relocate_new_kernel_size);
 
+	data = reboot_code_buffer + relocate_new_kernel_size;
+	data->kexec_start_address = image->start;
+	data->kexec_indirection_page = page_list;
+	data->kexec_mach_type = machine_arch_type;
+	data->kexec_r2 = image->arch.kernel_r2;
+
 	/* get the identity mapping physical address for the reboot code */
 	reboot_entry_phys = virt_to_idmap(reboot_entry);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/module-plts.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/module-plts.c
@@ -4,6 +4,7 @@
  */
 
 #include <linux/elf.h>
+#include <linux/ftrace.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/sort.h>
@@ -11,10 +12,6 @@
 #include <asm/cache.h>
 #include <asm/opcodes.h>
 
-#define PLT_ENT_STRIDE		L1_CACHE_BYTES
-#define PLT_ENT_COUNT		(PLT_ENT_STRIDE / sizeof(u32))
-#define PLT_ENT_SIZE		(sizeof(struct plt_entries) / PLT_ENT_COUNT)
-
 #ifdef CONFIG_THUMB2_KERNEL
 #define PLT_ENT_LDR		__opcode_to_mem_thumb32(0xf8dff000 | \
 							(PLT_ENT_STRIDE - 4))
@@ -23,9 +20,11 @@
 						    (PLT_ENT_STRIDE - 8))
 #endif
 
-struct plt_entries {
-	u32	ldr[PLT_ENT_COUNT];
-	u32	lit[PLT_ENT_COUNT];
+static const u32 fixed_plts[] = {
+#ifdef CONFIG_DYNAMIC_FTRACE
+	FTRACE_ADDR,
+	MCOUNT_ADDR,
+#endif
 };
 
 static bool in_init(const struct module *mod, unsigned long loc)
@@ -33,14 +32,40 @@
 	return loc - (u32)mod->init_layout.base < mod->init_layout.size;
 }
 
+static void prealloc_fixed(struct mod_plt_sec *pltsec, struct plt_entries *plt)
+{
+	int i;
+
+	if (!ARRAY_SIZE(fixed_plts) || pltsec->plt_count)
+		return;
+	pltsec->plt_count = ARRAY_SIZE(fixed_plts);
+
+	for (i = 0; i < ARRAY_SIZE(plt->ldr); ++i)
+		plt->ldr[i] = PLT_ENT_LDR;
+
+	BUILD_BUG_ON(sizeof(fixed_plts) > sizeof(plt->lit));
+	memcpy(plt->lit, fixed_plts, sizeof(fixed_plts));
+}
+
 u32 get_module_plt(struct module *mod, unsigned long loc, Elf32_Addr val)
 {
 	struct mod_plt_sec *pltsec = !in_init(mod, loc) ? &mod->arch.core :
 							  &mod->arch.init;
+	struct plt_entries *plt;
+	int idx;
+
+	/* cache the address, ELF header is available only during module load */
+	if (!pltsec->plt_ent)
+		pltsec->plt_ent = (struct plt_entries *)pltsec->plt->sh_addr;
+	plt = pltsec->plt_ent;
 
-	struct plt_entries *plt = (struct plt_entries *)pltsec->plt->sh_addr;
-	int idx = 0;
+	prealloc_fixed(pltsec, plt);
+
+	for (idx = 0; idx < ARRAY_SIZE(fixed_plts); ++idx)
+		if (plt->lit[idx] == val)
+			return (u32)&plt->ldr[idx];
 
+	idx = 0;
 	/*
 	 * Look for an existing entry pointing to 'val'. Given that the
 	 * relocations are sorted, this will be the last entry we allocated.
@@ -188,8 +213,8 @@
 int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
 			      char *secstrings, struct module *mod)
 {
-	unsigned long core_plts = 0;
-	unsigned long init_plts = 0;
+	unsigned long core_plts = ARRAY_SIZE(fixed_plts);
+	unsigned long init_plts = ARRAY_SIZE(fixed_plts);
 	Elf32_Shdr *s, *sechdrs_end = sechdrs + ehdr->e_shnum;
 	Elf32_Sym *syms = NULL;
 
@@ -244,6 +269,7 @@
 	mod->arch.core.plt->sh_size = round_up(core_plts * PLT_ENT_SIZE,
 					       sizeof(struct plt_entries));
 	mod->arch.core.plt_count = 0;
+	mod->arch.core.plt_ent = NULL;
 
 	mod->arch.init.plt->sh_type = SHT_NOBITS;
 	mod->arch.init.plt->sh_flags = SHF_EXECINSTR | SHF_ALLOC;
@@ -251,6 +277,7 @@
 	mod->arch.init.plt->sh_size = round_up(init_plts * PLT_ENT_SIZE,
 					       sizeof(struct plt_entries));
 	mod->arch.init.plt_count = 0;
+	mod->arch.init.plt_ent = NULL;
 
 	pr_debug("%s: plt=%x, init.plt=%x\n", __func__,
 		 mod->arch.core.plt->sh_size, mod->arch.init.plt->sh_size);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/perf_callchain.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/perf_callchain.c
@@ -62,9 +62,10 @@
 void
 perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs)
 {
+	struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs();
 	struct frame_tail __user *tail;
 
-	if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
+	if (guest_cbs && guest_cbs->is_in_guest()) {
 		/* We don't support guest os callchain now */
 		return;
 	}
@@ -98,9 +99,10 @@
 void
 perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs)
 {
+	struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs();
 	struct stackframe fr;
 
-	if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
+	if (guest_cbs && guest_cbs->is_in_guest()) {
 		/* We don't support guest os callchain now */
 		return;
 	}
@@ -111,18 +113,21 @@
 
 unsigned long perf_instruction_pointer(struct pt_regs *regs)
 {
-	if (perf_guest_cbs && perf_guest_cbs->is_in_guest())
-		return perf_guest_cbs->get_guest_ip();
+	struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs();
+
+	if (guest_cbs && guest_cbs->is_in_guest())
+		return guest_cbs->get_guest_ip();
 
 	return instruction_pointer(regs);
 }
 
 unsigned long perf_misc_flags(struct pt_regs *regs)
 {
+	struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs();
 	int misc = 0;
 
-	if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
-		if (perf_guest_cbs->is_user_mode())
+	if (guest_cbs && guest_cbs->is_in_guest()) {
+		if (guest_cbs->is_user_mode())
 			misc |= PERF_RECORD_MISC_GUEST_USER;
 		else
 			misc |= PERF_RECORD_MISC_GUEST_KERNEL;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/perf_event_v7.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/perf_event_v7.c
@@ -773,10 +773,10 @@
 		pr_err("CPU%u writing wrong counter %d\n",
 			smp_processor_id(), idx);
 	} else if (idx == ARMV7_IDX_CYCLE_COUNTER) {
-		asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (value));
+		asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" ((u32)value));
 	} else {
 		armv7_pmnc_select_counter(idx);
-		asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r" (value));
+		asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r" ((u32)value));
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/process.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/process.c
@@ -224,8 +224,8 @@
 asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
 
 int
-copy_thread(unsigned long clone_flags, unsigned long stack_start,
-	    unsigned long stk_sz, struct task_struct *p)
+copy_thread_tls(unsigned long clone_flags, unsigned long stack_start,
+	    unsigned long stk_sz, struct task_struct *p, unsigned long tls)
 {
 	struct thread_info *thread = task_thread_info(p);
 	struct pt_regs *childregs = task_pt_regs(p);
@@ -259,7 +259,7 @@
 	clear_ptrace_hw_breakpoint(p);
 
 	if (clone_flags & CLONE_SETTLS)
-		thread->tp_value[0] = childregs->ARM_r3;
+		thread->tp_value[0] = tls;
 	thread->tp_value[1] = get_tpuser();
 
 	thread_notify(THREAD_NOTIFY_COPY, thread);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/ptrace.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/ptrace.c
@@ -219,8 +219,8 @@
 };
 
 static struct undef_hook thumb_break_hook = {
-	.instr_mask	= 0xffff,
-	.instr_val	= 0xde01,
+	.instr_mask	= 0xffffffff,
+	.instr_val	= 0x0000de01,
 	.cpsr_mask	= PSR_T_BIT,
 	.cpsr_val	= PSR_T_BIT,
 	.fn		= break_trap,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/relocate_kernel.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/relocate_kernel.S
@@ -5,14 +5,16 @@
 
 #include <linux/linkage.h>
 #include <asm/assembler.h>
+#include <asm/asm-offsets.h>
 #include <asm/kexec.h>
 
 	.align	3	/* not needed for this code, but keeps fncpy() happy */
 
 ENTRY(relocate_new_kernel)
 
-	ldr	r0,kexec_indirection_page
-	ldr	r1,kexec_start_address
+	adr	r7, relocate_new_kernel_end
+	ldr	r0, [r7, #KEXEC_INDIR_PAGE]
+	ldr	r1, [r7, #KEXEC_START_ADDR]
 
 	/*
 	 * If there is no indirection page (we are doing crashdumps)
@@ -57,34 +59,16 @@
 
 2:
 	/* Jump to relocated kernel */
-	mov lr,r1
-	mov r0,#0
-	ldr r1,kexec_mach_type
-	ldr r2,kexec_boot_atags
- ARM(	ret lr	)
- THUMB(	bx lr		)
-
-	.align
-
-	.globl kexec_start_address
-kexec_start_address:
-	.long	0x0
-
-	.globl kexec_indirection_page
-kexec_indirection_page:
-	.long	0x0
-
-	.globl kexec_mach_type
-kexec_mach_type:
-	.long	0x0
-
-	/* phy addr of the atags for the new kernel */
-	.globl kexec_boot_atags
-kexec_boot_atags:
-	.long	0x0
+	mov	lr, r1
+	mov	r0, #0
+	ldr	r1, [r7, #KEXEC_MACH_TYPE]
+	ldr	r2, [r7, #KEXEC_R2]
+ ARM(	ret	lr	)
+ THUMB(	bx	lr	)
 
 ENDPROC(relocate_new_kernel)
 
+	.align	3
 relocate_new_kernel_end:
 
 	.globl relocate_new_kernel_size
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/return_address.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/return_address.c
@@ -7,8 +7,6 @@
  */
 #include <linux/export.h>
 #include <linux/ftrace.h>
-
-#if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND)
 #include <linux/sched.h>
 
 #include <asm/stacktrace.h>
@@ -53,6 +51,4 @@
 		return NULL;
 }
 
-#endif /* if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND) */
-
 EXPORT_SYMBOL_GPL(return_address);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/setup.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/setup.c
@@ -18,6 +18,7 @@
 #include <linux/of_platform.h>
 #include <linux/init.h>
 #include <linux/kexec.h>
+#include <linux/libfdt.h>
 #include <linux/of_fdt.h>
 #include <linux/cpu.h>
 #include <linux/interrupt.h>
@@ -543,9 +544,11 @@
 	 * In Thumb-2, msr with an immediate value is not allowed.
 	 */
 #ifdef CONFIG_THUMB2_KERNEL
-#define PLC	"r"
+#define PLC_l	"l"
+#define PLC_r	"r"
 #else
-#define PLC	"I"
+#define PLC_l	"I"
+#define PLC_r	"I"
 #endif
 
 	/*
@@ -567,15 +570,15 @@
 	"msr	cpsr_c, %9"
 	    :
 	    : "r" (stk),
-	      PLC (PSR_F_BIT | PSR_I_BIT | IRQ_MODE),
+	      PLC_r (PSR_F_BIT | PSR_I_BIT | IRQ_MODE),
 	      "I" (offsetof(struct stack, irq[0])),
-	      PLC (PSR_F_BIT | PSR_I_BIT | ABT_MODE),
+	      PLC_r (PSR_F_BIT | PSR_I_BIT | ABT_MODE),
 	      "I" (offsetof(struct stack, abt[0])),
-	      PLC (PSR_F_BIT | PSR_I_BIT | UND_MODE),
+	      PLC_r (PSR_F_BIT | PSR_I_BIT | UND_MODE),
 	      "I" (offsetof(struct stack, und[0])),
-	      PLC (PSR_F_BIT | PSR_I_BIT | FIQ_MODE),
+	      PLC_r (PSR_F_BIT | PSR_I_BIT | FIQ_MODE),
 	      "I" (offsetof(struct stack, fiq[0])),
-	      PLC (PSR_F_BIT | PSR_I_BIT | SVC_MODE)
+	      PLC_l (PSR_F_BIT | PSR_I_BIT | SVC_MODE)
 	    : "r14");
 #endif
 }
@@ -1075,19 +1078,27 @@
 
 void __init setup_arch(char **cmdline_p)
 {
-	const struct machine_desc *mdesc;
+	const struct machine_desc *mdesc = NULL;
+	void *atags_vaddr = NULL;
+
+	if (__atags_pointer)
+		atags_vaddr = FDT_VIRT_BASE(__atags_pointer);
 
 	setup_processor();
-	mdesc = setup_machine_fdt(__atags_pointer);
+	if (atags_vaddr) {
+		mdesc = setup_machine_fdt(atags_vaddr);
+		if (mdesc)
+			memblock_reserve(__atags_pointer,
+					 fdt_totalsize(atags_vaddr));
+	}
 	if (!mdesc)
-		mdesc = setup_machine_tags(__atags_pointer, __machine_arch_type);
+		mdesc = setup_machine_tags(atags_vaddr, __machine_arch_type);
 	if (!mdesc) {
 		early_print("\nError: invalid dtb and unrecognized/unsupported machine ID\n");
 		early_print("  r1=0x%08x, r2=0x%08x\n", __machine_arch_type,
 			    __atags_pointer);
 		if (__atags_pointer)
-			early_print("  r2[]=%*ph\n", 16,
-				    phys_to_virt(__atags_pointer));
+			early_print("  r2[]=%*ph\n", 16, atags_vaddr);
 		dump_machine_table();
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/signal.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/signal.c
@@ -694,18 +694,20 @@
 
 	addr = page_address(page);
 
+	/* Poison the entire page */
+	memset32(addr, __opcode_to_mem_arm(0xe7fddef1),
+		 PAGE_SIZE / sizeof(u32));
+
 	/* Give the signal return code some randomness */
 	offset = 0x200 + (get_random_int() & 0x7fc);
 	signal_return_offset = offset;
 
-	/*
-	 * Copy signal return handlers into the vector page, and
-	 * set sigreturn to be a pointer to these.
-	 */
+	/* Copy signal return handlers into the page */
 	memcpy(addr + offset, sigreturn_codes, sizeof(sigreturn_codes));
 
-	ptr = (unsigned long)addr + offset;
-	flush_icache_range(ptr, ptr + sizeof(sigreturn_codes));
+	/* Flush out all instructions in this page */
+	ptr = (unsigned long)addr;
+	flush_icache_range(ptr, ptr + PAGE_SIZE);
 
 	return page;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/smccc-call.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/smccc-call.S
@@ -3,7 +3,9 @@
  * Copyright (c) 2015, Linaro Limited
  */
 #include <linux/linkage.h>
+#include <linux/arm-smccc.h>
 
+#include <asm/asm-offsets.h>
 #include <asm/opcodes-sec.h>
 #include <asm/opcodes-virt.h>
 #include <asm/unwind.h>
@@ -27,7 +29,14 @@
 UNWIND(	.save	{r4-r7})
 	ldm	r12, {r4-r7}
 	\instr
-	pop	{r4-r7}
+	ldr	r4, [sp, #36]
+	cmp	r4, #0
+	beq	1f			// No quirk structure
+	ldr     r5, [r4, #ARM_SMCCC_QUIRK_ID_OFFS]
+	cmp     r5, #ARM_SMCCC_QUIRK_QCOM_A6
+	bne	1f			// No quirk present
+	str	r6, [r4, #ARM_SMCCC_QUIRK_STATE_OFFS]
+1:	pop	{r4-r7}
 	ldr	r12, [sp, #(4 * 4)]
 	stm	r12, {r0-r3}
 	bx	lr
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/smp.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/smp.c
@@ -240,6 +240,10 @@
 	if (ret)
 		return ret;
 
+#ifdef CONFIG_GENERIC_ARCH_TOPOLOGY
+	remove_cpu_topology(cpu);
+#endif
+
 	/*
 	 * Take this CPU offline.  Once we clear this, we can't return,
 	 * and we must not schedule until we're ready to give up the cpu.
@@ -506,20 +510,59 @@
 		__smp_cross_call = fn;
 }
 
-static const char *ipi_types[NR_IPI] __tracepoint_string = {
-#define S(x,s)	[x] = s
-	S(IPI_WAKEUP, "CPU wakeup interrupts"),
-	S(IPI_TIMER, "Timer broadcast interrupts"),
-	S(IPI_RESCHEDULE, "Rescheduling interrupts"),
-	S(IPI_CALL_FUNC, "Function call interrupts"),
-	S(IPI_CPU_STOP, "CPU stop interrupts"),
-	S(IPI_IRQ_WORK, "IRQ work interrupts"),
-	S(IPI_COMPLETION, "completion interrupts"),
+struct ipi {
+	const char *desc;
+	void (*handler)(void);
+};
+
+static void ipi_cpu_stop(void);
+static void ipi_complete(void);
+
+#define IPI_DESC_STRING_IPI_WAKEUP "CPU wakeup interrupts"
+#define IPI_DESC_STRING_IPI_TIMER "Timer broadcast interrupts"
+#define IPI_DESC_STRING_IPI_RESCHEDULE "Rescheduling interrupts"
+#define IPI_DESC_STRING_IPI_CALL_FUNC "Function call interrupts"
+#define IPI_DESC_STRING_IPI_CPU_STOP "CPU stop interrupts"
+#define IPI_DESC_STRING_IPI_IRQ_WORK "IRQ work interrupts"
+#define IPI_DESC_STRING_IPI_COMPLETION "completion interrupts"
+
+#define IPI_DESC_STR(x) IPI_DESC_STRING_ ## x
+
+static const char* ipi_desc_strings[] __tracepoint_string =
+		{
+			[IPI_WAKEUP] = IPI_DESC_STR(IPI_WAKEUP),
+			[IPI_TIMER] = IPI_DESC_STR(IPI_TIMER),
+			[IPI_RESCHEDULE] = IPI_DESC_STR(IPI_RESCHEDULE),
+			[IPI_CALL_FUNC] = IPI_DESC_STR(IPI_CALL_FUNC),
+			[IPI_CPU_STOP] = IPI_DESC_STR(IPI_CPU_STOP),
+			[IPI_IRQ_WORK] = IPI_DESC_STR(IPI_IRQ_WORK),
+			[IPI_COMPLETION] = IPI_DESC_STR(IPI_COMPLETION),
+		};
+
+
+static void tick_receive_broadcast_local(void)
+{
+	tick_receive_broadcast();
+}
+
+static struct ipi ipi_types[NR_IPI] = {
+#define S(x, f)	[x].desc = IPI_DESC_STR(x), [x].handler = f
+	S(IPI_WAKEUP, NULL),
+#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
+	S(IPI_TIMER, tick_receive_broadcast_local),
+#endif
+	S(IPI_RESCHEDULE, scheduler_ipi),
+	S(IPI_CALL_FUNC, generic_smp_call_function_interrupt),
+	S(IPI_CPU_STOP, ipi_cpu_stop),
+#ifdef CONFIG_IRQ_WORK
+	S(IPI_IRQ_WORK, irq_work_run),
+#endif
+	S(IPI_COMPLETION, ipi_complete),
 };
 
 static void smp_cross_call(const struct cpumask *target, unsigned int ipinr)
 {
-	trace_ipi_raise_rcuidle(target, ipi_types[ipinr]);
+	trace_ipi_raise_rcuidle(target, ipi_desc_strings[ipinr]);
 	__smp_cross_call(target, ipinr);
 }
 
@@ -528,13 +571,13 @@
 	unsigned int cpu, i;
 
 	for (i = 0; i < NR_IPI; i++) {
-		seq_printf(p, "%*s%u: ", prec - 1, "IPI", i);
-
-		for_each_online_cpu(cpu)
-			seq_printf(p, "%10u ",
-				   __get_irq_stat(cpu, ipi_irqs[i]));
-
-		seq_printf(p, " %s\n", ipi_types[i]);
+		if (ipi_types[i].handler) {
+			seq_printf(p, "%*s%u: ", prec - 1, "IPI", i);
+			for_each_present_cpu(cpu)
+				seq_printf(p, "%10u ",
+					__get_irq_stat(cpu, ipi_irqs[i]));
+			seq_printf(p, " %s\n", ipi_types[i].desc);
+		}
 	}
 }
 
@@ -584,8 +627,10 @@
 /*
  * ipi_cpu_stop - handle IPI from smp_send_stop()
  */
-static void ipi_cpu_stop(unsigned int cpu)
+static void ipi_cpu_stop(void)
 {
+	unsigned int cpu = smp_processor_id();
+
 	if (system_state <= SYSTEM_RUNNING) {
 		raw_spin_lock(&stop_lock);
 		pr_crit("CPU%u: stopping\n", cpu);
@@ -612,8 +657,10 @@
 	return IPI_COMPLETION;
 }
 
-static void ipi_complete(unsigned int cpu)
+static void ipi_complete(void)
 {
+	unsigned int cpu = smp_processor_id();
+
 	complete(per_cpu(cpu_completion, cpu));
 }
 
@@ -630,71 +677,48 @@
 	unsigned int cpu = smp_processor_id();
 	struct pt_regs *old_regs = set_irq_regs(regs);
 
-	if ((unsigned)ipinr < NR_IPI) {
-		trace_ipi_entry_rcuidle(ipi_types[ipinr]);
+	if (ipi_types[ipinr].handler) {
 		__inc_irq_stat(cpu, ipi_irqs[ipinr]);
-	}
-
-	switch (ipinr) {
-	case IPI_WAKEUP:
-		break;
-
-#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
-	case IPI_TIMER:
-		irq_enter();
-		tick_receive_broadcast();
-		irq_exit();
-		break;
-#endif
-
-	case IPI_RESCHEDULE:
-		scheduler_ipi();
-		break;
-
-	case IPI_CALL_FUNC:
 		irq_enter();
-		generic_smp_call_function_interrupt();
+		(*ipi_types[ipinr].handler)();
 		irq_exit();
-		break;
+	} else
+		pr_debug("CPU%u: Unknown IPI message 0x%x\n", cpu, ipinr);
 
-	case IPI_CPU_STOP:
-		irq_enter();
-		ipi_cpu_stop(cpu);
-		irq_exit();
-		break;
+	set_irq_regs(old_regs);
+}
 
-#ifdef CONFIG_IRQ_WORK
-	case IPI_IRQ_WORK:
-		irq_enter();
-		irq_work_run();
-		irq_exit();
-		break;
-#endif
+/*
+ * set_ipi_handler:
+ * Interface provided for a kernel module to specify an IPI handler function.
+ */
+int set_ipi_handler(int ipinr, void *handler, char *desc)
+{
+	unsigned int cpu = smp_processor_id();
 
-	case IPI_COMPLETION:
-		irq_enter();
-		ipi_complete(cpu);
-		irq_exit();
-		break;
+	if (ipi_types[ipinr].handler) {
+		pr_crit("CPU%u: IPI handler 0x%x already registered to %pf\n",
+					cpu, ipinr, ipi_types[ipinr].handler);
+		return -1;
+	}
 
-	case IPI_CPU_BACKTRACE:
-		printk_nmi_enter();
-		irq_enter();
-		nmi_cpu_backtrace(regs);
-		irq_exit();
-		printk_nmi_exit();
-		break;
+	ipi_types[ipinr].handler = handler;
+	ipi_types[ipinr].desc = desc;
 
-	default:
-		pr_crit("CPU%u: Unknown IPI message 0x%x\n",
-		        cpu, ipinr);
-		break;
-	}
+	return 0;
+}
+EXPORT_SYMBOL(set_ipi_handler);
 
-	if ((unsigned)ipinr < NR_IPI)
-		trace_ipi_exit_rcuidle(ipi_types[ipinr]);
-	set_irq_regs(old_regs);
+/*
+ * clear_ipi_handler:
+ * Interface provided for a kernel module to clear an IPI handler function.
+ */
+void clear_ipi_handler(int ipinr)
+{
+	ipi_types[ipinr].handler = NULL;
+	ipi_types[ipinr].desc = NULL;
 }
+EXPORT_SYMBOL(clear_ipi_handler);
 
 void smp_send_reschedule(int cpu)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/spectre.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/spectre.c
@@ -0,0 +1,71 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <linux/bpf.h>
+#include <linux/cpu.h>
+#include <linux/device.h>
+
+#include <asm/spectre.h>
+
+static bool _unprivileged_ebpf_enabled(void)
+{
+#ifdef CONFIG_BPF_SYSCALL
+	return !sysctl_unprivileged_bpf_disabled;
+#else
+	return false;
+#endif
+}
+
+ssize_t cpu_show_spectre_v1(struct device *dev, struct device_attribute *attr,
+			    char *buf)
+{
+	return sprintf(buf, "Mitigation: __user pointer sanitization\n");
+}
+
+static unsigned int spectre_v2_state;
+static unsigned int spectre_v2_methods;
+
+void spectre_v2_update_state(unsigned int state, unsigned int method)
+{
+	if (state > spectre_v2_state)
+		spectre_v2_state = state;
+	spectre_v2_methods |= method;
+}
+
+ssize_t cpu_show_spectre_v2(struct device *dev, struct device_attribute *attr,
+			    char *buf)
+{
+	const char *method;
+
+	if (spectre_v2_state == SPECTRE_UNAFFECTED)
+		return sprintf(buf, "%s\n", "Not affected");
+
+	if (spectre_v2_state != SPECTRE_MITIGATED)
+		return sprintf(buf, "%s\n", "Vulnerable");
+
+	if (_unprivileged_ebpf_enabled())
+		return sprintf(buf, "Vulnerable: Unprivileged eBPF enabled\n");
+
+	switch (spectre_v2_methods) {
+	case SPECTRE_V2_METHOD_BPIALL:
+		method = "Branch predictor hardening";
+		break;
+
+	case SPECTRE_V2_METHOD_ICIALLU:
+		method = "I-cache invalidation";
+		break;
+
+	case SPECTRE_V2_METHOD_SMC:
+	case SPECTRE_V2_METHOD_HVC:
+		method = "Firmware call";
+		break;
+
+	case SPECTRE_V2_METHOD_LOOP8:
+		method = "History overwrite";
+		break;
+
+	default:
+		method = "Multiple mitigations";
+		break;
+	}
+
+	return sprintf(buf, "Mitigation: %s\n", method);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/stacktrace.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/stacktrace.c
@@ -22,6 +22,19 @@
  * A simple function epilogue looks like this:
  *	ldm	sp, {fp, sp, pc}
  *
+ * When compiled with clang, pc and sp are not pushed. A simple function
+ * prologue looks like this when built with clang:
+ *
+ *	stmdb	{..., fp, lr}
+ *	add	fp, sp, #x
+ *	sub	sp, sp, #y
+ *
+ * A simple function epilogue looks like this when built with clang:
+ *
+ *	sub	sp, fp, #x
+ *	ldm	{..., fp, pc}
+ *
+ *
  * Note that with framepointer enabled, even the leaf functions have the same
  * prologue and epilogue, therefore we can ignore the LR value in this case.
  */
@@ -34,14 +47,24 @@
 	low = frame->sp;
 	high = ALIGN(low, THREAD_SIZE);
 
+#ifdef CONFIG_CC_IS_CLANG
+	/* check current frame pointer is within bounds */
+	if (fp < low + 4 || fp > high - 4)
+		return -EINVAL;
+
+	frame->sp = frame->fp;
+	frame->fp = READ_ONCE_NOCHECK(*(unsigned long *)(fp));
+	frame->pc = READ_ONCE_NOCHECK(*(unsigned long *)(fp + 4));
+#else
 	/* check current frame pointer is within bounds */
 	if (fp < low + 12 || fp > high - 4)
 		return -EINVAL;
 
 	/* restore the registers from the stack frame */
-	frame->fp = *(unsigned long *)(fp - 12);
-	frame->sp = *(unsigned long *)(fp - 8);
-	frame->pc = *(unsigned long *)(fp - 4);
+	frame->fp = READ_ONCE_NOCHECK(*(unsigned long *)(fp - 12));
+	frame->sp = READ_ONCE_NOCHECK(*(unsigned long *)(fp - 8));
+	frame->pc = READ_ONCE_NOCHECK(*(unsigned long *)(fp - 4));
+#endif
 
 	return 0;
 }
@@ -92,6 +115,8 @@
 		return 0;
 
 	regs = (struct pt_regs *)frame->sp;
+	if ((unsigned long)&regs[1] > ALIGN(frame->sp, THREAD_SIZE))
+		return 0;
 
 	trace->entries[trace->nr_entries++] = regs->ARM_pc;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/suspend.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/suspend.c
@@ -1,4 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0
+#include <linux/ftrace.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/mm_types.h>
@@ -27,12 +28,22 @@
 		return -EINVAL;
 
 	/*
+	 * Function graph tracer state gets incosistent when the kernel
+	 * calls functions that never return (aka suspend finishers) hence
+	 * disable graph tracing during their execution.
+	 */
+	pause_graph_tracing();
+
+	/*
 	 * Provide a temporary page table with an identity mapping for
 	 * the MMU-enable code, required for resuming.  On successful
 	 * resume (indicated by a zero return code), we need to switch
 	 * back to the correct page tables.
 	 */
 	ret = __cpu_suspend(arg, fn, __mpidr);
+
+	unpause_graph_tracing();
+
 	if (ret == 0) {
 		cpu_switch_mm(mm->pgd, mm);
 		local_flush_bp_all();
@@ -46,7 +57,13 @@
 int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
 {
 	u32 __mpidr = cpu_logical_map(smp_processor_id());
-	return __cpu_suspend(arg, fn, __mpidr);
+	int ret;
+
+	pause_graph_tracing();
+	ret = __cpu_suspend(arg, fn, __mpidr);
+	unpause_graph_tracing();
+
+	return ret;
 }
 #define	idmap_pgd	NULL
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/topology.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/topology.c
@@ -196,9 +196,8 @@
 	struct cpu_topology *cpuid_topo = &cpu_topology[cpuid];
 	unsigned int mpidr;
 
-	/* If the cpu topology has been already set, just return */
-	if (cpuid_topo->core_id != -1)
-		return;
+	if (cpuid_topo->package_id != -1)
+		goto topology_populated;
 
 	mpidr = read_cpuid_mpidr();
 
@@ -231,14 +230,15 @@
 		cpuid_topo->package_id = -1;
 	}
 
-	update_siblings_masks(cpuid);
-
 	update_cpu_capacity(cpuid);
 
 	pr_info("CPU%u: thread %d, cpu %d, socket %d, mpidr %x\n",
 		cpuid, cpu_topology[cpuid].thread_id,
 		cpu_topology[cpuid].core_id,
 		cpu_topology[cpuid].package_id, mpidr);
+
+topology_populated:
+	update_siblings_masks(cpuid);
 }
 
 static inline int cpu_corepower_flags(void)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/traps.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/traps.c
@@ -30,6 +30,7 @@
 #include <linux/atomic.h>
 #include <asm/cacheflush.h>
 #include <asm/exception.h>
+#include <asm/spectre.h>
 #include <asm/unistd.h>
 #include <asm/traps.h>
 #include <asm/ptrace.h>
@@ -64,14 +65,16 @@
 
 void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame)
 {
+	unsigned long end = frame + 4 + sizeof(struct pt_regs);
+
 #ifdef CONFIG_KALLSYMS
 	printk("[<%08lx>] (%ps) from [<%08lx>] (%pS)\n", where, (void *)where, from, (void *)from);
 #else
 	printk("Function entered at [<%08lx>] from [<%08lx>]\n", where, from);
 #endif
 
-	if (in_entry_text(from))
-		dump_mem("", "Exception stack", frame + 4, frame + 4 + sizeof(struct pt_regs));
+	if (in_entry_text(from) && end <= ALIGN(frame, THREAD_SIZE))
+		dump_mem("", "Exception stack", frame + 4, end);
 }
 
 void dump_backtrace_stm(u32 *stack, u32 instruction)
@@ -338,7 +341,7 @@
 	if (panic_on_oops)
 		panic("Fatal exception");
 	if (signr)
-		do_exit(signr);
+		make_task_dead(signr);
 }
 
 /*
@@ -797,10 +800,59 @@
 }
 #endif
 
+#ifndef CONFIG_CPU_V7M
+static void copy_from_lma(void *vma, void *lma_start, void *lma_end)
+{
+	memcpy(vma, lma_start, lma_end - lma_start);
+}
+
+static void flush_vectors(void *vma, size_t offset, size_t size)
+{
+	unsigned long start = (unsigned long)vma + offset;
+	unsigned long end = start + size;
+
+	flush_icache_range(start, end);
+}
+
+#ifdef CONFIG_HARDEN_BRANCH_HISTORY
+int spectre_bhb_update_vectors(unsigned int method)
+{
+	extern char __vectors_bhb_bpiall_start[], __vectors_bhb_bpiall_end[];
+	extern char __vectors_bhb_loop8_start[], __vectors_bhb_loop8_end[];
+	void *vec_start, *vec_end;
+
+	if (system_state > SYSTEM_SCHEDULING) {
+		pr_err("CPU%u: Spectre BHB workaround too late - system vulnerable\n",
+		       smp_processor_id());
+		return SPECTRE_VULNERABLE;
+	}
+
+	switch (method) {
+	case SPECTRE_V2_METHOD_LOOP8:
+		vec_start = __vectors_bhb_loop8_start;
+		vec_end = __vectors_bhb_loop8_end;
+		break;
+
+	case SPECTRE_V2_METHOD_BPIALL:
+		vec_start = __vectors_bhb_bpiall_start;
+		vec_end = __vectors_bhb_bpiall_end;
+		break;
+
+	default:
+		pr_err("CPU%u: unknown Spectre BHB state %d\n",
+		       smp_processor_id(), method);
+		return SPECTRE_VULNERABLE;
+	}
+
+	copy_from_lma(vectors_page, vec_start, vec_end);
+	flush_vectors(vectors_page, 0, vec_end - vec_start);
+
+	return SPECTRE_MITIGATED;
+}
+#endif
+
 void __init early_trap_init(void *vectors_base)
 {
-#ifndef CONFIG_CPU_V7M
-	unsigned long vectors = (unsigned long)vectors_base;
 	extern char __stubs_start[], __stubs_end[];
 	extern char __vectors_start[], __vectors_end[];
 	unsigned i;
@@ -821,17 +873,20 @@
 	 * into the vector page, mapped at 0xffff0000, and ensure these
 	 * are visible to the instruction stream.
 	 */
-	memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start);
-	memcpy((void *)vectors + 0x1000, __stubs_start, __stubs_end - __stubs_start);
+	copy_from_lma(vectors_base, __vectors_start, __vectors_end);
+	copy_from_lma(vectors_base + 0x1000, __stubs_start, __stubs_end);
 
 	kuser_init(vectors_base);
 
-	flush_icache_range(vectors, vectors + PAGE_SIZE * 2);
+	flush_vectors(vectors_base, 0, PAGE_SIZE * 2);
+}
 #else /* ifndef CONFIG_CPU_V7M */
+void __init early_trap_init(void *vectors_base)
+{
 	/*
 	 * on V7-M there is no need to copy the vector table to a dedicated
 	 * memory area. The address is configurable and so a table in the kernel
 	 * image can be used.
 	 */
-#endif
 }
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/unwind.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/unwind.c
@@ -300,6 +300,29 @@
 	return URC_OK;
 }
 
+static unsigned long unwind_decode_uleb128(struct unwind_ctrl_block *ctrl)
+{
+	unsigned long bytes = 0;
+	unsigned long insn;
+	unsigned long result = 0;
+
+	/*
+	 * unwind_get_byte() will advance `ctrl` one instruction at a time, so
+	 * loop until we get an instruction byte where bit 7 is not set.
+	 *
+	 * Note: This decodes a maximum of 4 bytes to output 28 bits data where
+	 * max is 0xfffffff: that will cover a vsp increment of 1073742336, hence
+	 * it is sufficient for unwinding the stack.
+	 */
+	do {
+		insn = unwind_get_byte(ctrl);
+		result |= (insn & 0x7f) << (bytes * 7);
+		bytes++;
+	} while (!!(insn & 0x80) && (bytes != sizeof(result)));
+
+	return result;
+}
+
 /*
  * Execute the current unwind instruction.
  */
@@ -353,7 +376,7 @@
 		if (ret)
 			goto error;
 	} else if (insn == 0xb2) {
-		unsigned long uleb128 = unwind_get_byte(ctrl);
+		unsigned long uleb128 = unwind_decode_uleb128(ctrl);
 
 		ctrl->vrs[SP] += 0x204 + (uleb128 << 2);
 	} else {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/vdso.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/vdso.c
@@ -93,6 +93,8 @@
 	 */
 	np = of_find_compatible_node(NULL, NULL, "arm,armv7-timer");
 	if (!np)
+		np = of_find_compatible_node(NULL, NULL, "arm,armv8-timer");
+	if (!np)
 		goto out_put;
 
 	if (of_property_read_bool(np, "arm,cpu-registers-not-fw-configured"))
@@ -279,7 +281,7 @@
 	if (!IS_ENABLED(CONFIG_ARM_ARCH_TIMER))
 		return false;
 
-	if (!tk->tkr_mono.clock->archdata.vdso_direct)
+	if (tk->tkr_mono.clock->archdata.clock_mode != VDSO_CLOCKMODE_ARCHTIMER)
 		return false;
 
 	return true;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/vmlinux-xip.lds.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/vmlinux-xip.lds.S
@@ -180,7 +180,7 @@
 ASSERT((_end - __bss_start) >= 12288, ".bss too small for CONFIG_XIP_DEFLATED_DATA")
 #endif
 
-#ifdef CONFIG_ARM_MPU
+#if defined(CONFIG_ARM_MPU) && !defined(CONFIG_COMPILE_TEST)
 /*
  * Due to PMSAv7 restriction on base address and size we have to
  * enforce minimal alignment restrictions. It was seen that weaker
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kernel/vmlinux.lds.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kernel/vmlinux.lds.h
@@ -25,6 +25,19 @@
 #define ARM_MMU_DISCARD(x)	x
 #endif
 
+/*
+ * ld.lld does not support NOCROSSREFS:
+ * https://github.com/ClangBuiltLinux/linux/issues/1609
+ */
+#ifdef CONFIG_LD_IS_LLD
+#define NOCROSSREFS
+#endif
+
+/* Set start/end symbol names to the LMA for the section */
+#define ARM_LMA(sym, section)						\
+	sym##_start = LOADADDR(section);				\
+	sym##_end = LOADADDR(section) + SIZEOF(section)
+
 #define PROC_INFO							\
 		. = ALIGN(4);						\
 		__proc_info_begin = .;					\
@@ -100,19 +113,31 @@
  * only thing that matters is their relative offsets
  */
 #define ARM_VECTORS							\
-	__vectors_start = .;						\
-	.vectors 0xffff0000 : AT(__vectors_start) {			\
-		*(.vectors)						\
+	__vectors_lma = .;						\
+	OVERLAY 0xffff0000 : NOCROSSREFS AT(__vectors_lma) {		\
+		.vectors {						\
+			*(.vectors)					\
+		}							\
+		.vectors.bhb.loop8 {					\
+			*(.vectors.bhb.loop8)				\
+		}							\
+		.vectors.bhb.bpiall {					\
+			*(.vectors.bhb.bpiall)				\
+		}							\
 	}								\
-	. = __vectors_start + SIZEOF(.vectors);				\
-	__vectors_end = .;						\
+	ARM_LMA(__vectors, .vectors);					\
+	ARM_LMA(__vectors_bhb_loop8, .vectors.bhb.loop8);		\
+	ARM_LMA(__vectors_bhb_bpiall, .vectors.bhb.bpiall);		\
+	. = __vectors_lma + SIZEOF(.vectors) +				\
+		SIZEOF(.vectors.bhb.loop8) +				\
+		SIZEOF(.vectors.bhb.bpiall);				\
 									\
-	__stubs_start = .;						\
-	.stubs ADDR(.vectors) + 0x1000 : AT(__stubs_start) {		\
+	__stubs_lma = .;						\
+	.stubs ADDR(.vectors) + 0x1000 : AT(__stubs_lma) {		\
 		*(.stubs)						\
 	}								\
-	. = __stubs_start + SIZEOF(.stubs);				\
-	__stubs_end = .;						\
+	ARM_LMA(__stubs, .stubs);					\
+	. = __stubs_lma + SIZEOF(.stubs);				\
 									\
 	PROVIDE(vector_fiq_offset = vector_fiq - ADDR(.vectors));
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/kvm/hyp/tlb.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/kvm/hyp/tlb.c
@@ -45,7 +45,7 @@
 	__kvm_tlb_flush_vmid(kvm);
 }
 
-void __hyp_text __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu)
+void __hyp_text __kvm_flush_cpu_context(struct kvm_vcpu *vcpu)
 {
 	struct kvm *kvm = kern_hyp_va(kern_hyp_va(vcpu)->kvm);
 
@@ -54,6 +54,7 @@
 	isb();
 
 	write_sysreg(0, TLBIALL);
+	write_sysreg(0, ICIALLU);
 	dsb(nsh);
 	isb();
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/lib/copy_from_user.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/lib/copy_from_user.S
@@ -118,7 +118,7 @@
 
 ENDPROC(arm_copy_from_user)
 
-	.pushsection .fixup,"ax"
+	.pushsection .text.fixup,"ax"
 	.align 0
 	copy_abort_preamble
 	ldmfd	sp!, {r1, r2, r3}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/lib/findbit.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/lib/findbit.S
@@ -40,8 +40,8 @@
  * Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit, int offset)
  */
 ENTRY(_find_next_zero_bit_le)
-		teq	r1, #0
-		beq	3b
+		cmp	r2, r1
+		bhs	3b
 		ands	ip, r2, #7
 		beq	1b			@ If new byte, goto old routine
  ARM(		ldrb	r3, [r0, r2, lsr #3]	)
@@ -81,8 +81,8 @@
  * Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit, int offset)
  */
 ENTRY(_find_next_bit_le)
-		teq	r1, #0
-		beq	3b
+		cmp	r2, r1
+		bhs	3b
 		ands	ip, r2, #7
 		beq	1b			@ If new byte, goto old routine
  ARM(		ldrb	r3, [r0, r2, lsr #3]	)
@@ -115,8 +115,8 @@
 ENDPROC(_find_first_zero_bit_be)
 
 ENTRY(_find_next_zero_bit_be)
-		teq	r1, #0
-		beq	3b
+		cmp	r2, r1
+		bhs	3b
 		ands	ip, r2, #7
 		beq	1b			@ If new byte, goto old routine
 		eor	r3, r2, #0x18		@ big endian byte ordering
@@ -149,8 +149,8 @@
 ENDPROC(_find_first_bit_be)
 
 ENTRY(_find_next_bit_be)
-		teq	r1, #0
-		beq	3b
+		cmp	r2, r1
+		bhs	3b
 		ands	ip, r2, #7
 		beq	1b			@ If new byte, goto old routine
 		eor	r3, r2, #0x18		@ big endian byte ordering
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/lib/memset.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/lib/memset.S
@@ -16,6 +16,7 @@
 ENTRY(mmioset)
 ENTRY(memset)
 UNWIND( .fnstart         )
+	and	r1, r1, #255		@ cast to unsigned char
 	ands	r3, r0, #3		@ 1 unaligned?
 	mov	ip, r0			@ preserve r0 as return value
 	bne	6f			@ 1
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/lib/xor-neon.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/lib/xor-neon.c
@@ -26,8 +26,9 @@
  * While older versions of GCC do not generate incorrect code, they fail to
  * recognize the parallel nature of these functions, and emit plain ARM code,
  * which is known to be slower than the optimized ARM code in asm-arm/xor.h.
+ *
+ * #warning This code requires at least version 4.6 of GCC
  */
-#warning This code requires at least version 4.6 of GCC
 #endif
 
 #pragma GCC diagnostic ignored "-Wunused-variable"
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-at91/pm.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-at91/pm.c
@@ -103,7 +103,7 @@
 
 static const struct of_device_id sama5d2_ws_ids[] = {
 	{ .compatible = "atmel,sama5d2-gem",		.data = &ws_info[0] },
-	{ .compatible = "atmel,at91rm9200-rtc",		.data = &ws_info[1] },
+	{ .compatible = "atmel,sama5d2-rtc",		.data = &ws_info[1] },
 	{ .compatible = "atmel,sama5d3-udc",		.data = &ws_info[2] },
 	{ .compatible = "atmel,at91rm9200-ohci",	.data = &ws_info[2] },
 	{ .compatible = "usb-ohci",			.data = &ws_info[2] },
@@ -114,12 +114,12 @@
 };
 
 static const struct of_device_id sam9x60_ws_ids[] = {
-	{ .compatible = "atmel,at91sam9x5-rtc",		.data = &ws_info[1] },
+	{ .compatible = "microchip,sam9x60-rtc",	.data = &ws_info[1] },
 	{ .compatible = "atmel,at91rm9200-ohci",	.data = &ws_info[2] },
 	{ .compatible = "usb-ohci",			.data = &ws_info[2] },
 	{ .compatible = "atmel,at91sam9g45-ehci",	.data = &ws_info[2] },
 	{ .compatible = "usb-ehci",			.data = &ws_info[2] },
-	{ .compatible = "atmel,at91sam9260-rtt",	.data = &ws_info[4] },
+	{ .compatible = "microchip,sam9x60-rtt",	.data = &ws_info[4] },
 	{ .compatible = "cdns,sam9x60-macb",		.data = &ws_info[5] },
 	{ /* sentinel */ }
 };
@@ -592,13 +592,13 @@
 	sram_pool = gen_pool_get(&pdev->dev, NULL);
 	if (!sram_pool) {
 		pr_warn("%s: sram pool unavailable!\n", __func__);
-		return;
+		goto out_put_device;
 	}
 
 	sram_base = gen_pool_alloc(sram_pool, at91_pm_suspend_in_sram_sz);
 	if (!sram_base) {
 		pr_warn("%s: unable to alloc sram!\n", __func__);
-		return;
+		goto out_put_device;
 	}
 
 	sram_pbase = gen_pool_virt_to_phys(sram_pool, sram_base);
@@ -606,12 +606,17 @@
 					at91_pm_suspend_in_sram_sz, false);
 	if (!at91_suspend_sram_fn) {
 		pr_warn("SRAM: Could not map\n");
-		return;
+		goto out_put_device;
 	}
 
 	/* Copy the pm suspend handler to SRAM */
 	at91_suspend_sram_fn = fncpy(at91_suspend_sram_fn,
 			&at91_pm_suspend_in_sram, at91_pm_suspend_in_sram_sz);
+	return;
+
+out_put_device:
+	put_device(&pdev->dev);
+	return;
 }
 
 static bool __init at91_is_pm_mode_active(int pm_mode)
@@ -691,6 +696,12 @@
 		soc_pm.data.suspend_mode = AT91_PM_ULP0;
 }
 
+static const struct of_device_id atmel_shdwc_ids[] = {
+	{ .compatible = "atmel,sama5d2-shdwc" },
+	{ .compatible = "microchip,sam9x60-shdwc" },
+	{ /* sentinel. */ }
+};
+
 static void __init at91_pm_modes_init(void)
 {
 	struct device_node *np;
@@ -700,7 +711,7 @@
 	    !at91_is_pm_mode_active(AT91_PM_ULP1))
 		return;
 
-	np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-shdwc");
+	np = of_find_matching_node(NULL, atmel_shdwc_ids);
 	if (!np) {
 		pr_warn("%s: failed to find shdwc!\n", __func__);
 		goto ulp1_default;
@@ -751,6 +762,7 @@
 	{ .compatible = "atmel,sama5d3-pmc", .data = &pmc_infos[1] },
 	{ .compatible = "atmel,sama5d4-pmc", .data = &pmc_infos[1] },
 	{ .compatible = "atmel,sama5d2-pmc", .data = &pmc_infos[1] },
+	{ .compatible = "microchip,sam9x60-pmc", .data = &pmc_infos[1] },
 	{ /* sentinel */ },
 };
 
@@ -765,6 +777,7 @@
 
 	pmc_np = of_find_matching_node_and_match(NULL, atmel_pmc_ids, &of_id);
 	soc_pm.data.pmc = of_iomap(pmc_np, 0);
+	of_node_put(pmc_np);
 	if (!soc_pm.data.pmc) {
 		pr_err("AT91: PM not supported, PMC not found\n");
 		return;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-at91/pm_suspend.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-at91/pm_suspend.S
@@ -268,6 +268,10 @@
 	orr	tmp1, tmp1, #AT91_PMC_KEY
 	str	tmp1, [pmc, #AT91_CKGR_MOR]
 
+	/* Quirk for SAM9X60's PMC */
+	nop
+	nop
+
 	wait_mckrdy
 
 	/* Enable the crystal oscillator */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-axxia/platsmp.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-axxia/platsmp.c
@@ -39,6 +39,7 @@
 		return -ENOENT;
 
 	syscon = of_iomap(syscon_np, 0);
+	of_node_put(syscon_np);
 	if (!syscon)
 		return -ENOMEM;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-bcm/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-bcm/Kconfig
@@ -214,7 +214,6 @@
 	select HAVE_ARM_ARCH_TIMER
 	select BRCMSTB_L2_IRQ
 	select BCM7120_L2_IRQ
-	select ARCH_HAS_HOLES_MEMORYMODEL
 	select ZONE_DMA if ARM_LPAE
 	select SOC_BRCMSTB
 	select SOC_BUS
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-bcm/bcm_kona_smc.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-bcm/bcm_kona_smc.c
@@ -54,6 +54,7 @@
 		return -ENODEV;
 
 	prop_val = of_get_address(node, 0, &prop_size, NULL);
+	of_node_put(node);
 	if (!prop_val)
 		return -EINVAL;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-cns3xxx/core.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-cns3xxx/core.c
@@ -376,6 +376,7 @@
 		/* De-Asscer SATA Reset */
 		cns3xxx_pwr_soft_rst(CNS3XXX_PWR_SOFTWARE_RST(SATA));
 	}
+	of_node_put(dn);
 
 	dn = of_find_compatible_node(NULL, NULL, "cavium,cns3420-sdhci");
 	if (of_device_is_available(dn)) {
@@ -389,6 +390,7 @@
 		cns3xxx_pwr_clk_en(CNS3XXX_PWR_CLK_EN(SDIO));
 		cns3xxx_pwr_soft_rst(CNS3XXX_PWR_SOFTWARE_RST(SDIO));
 	}
+	of_node_put(dn);
 
 	pm_power_off = cns3xxx_power_off;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-davinci/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-davinci/Kconfig
@@ -3,12 +3,13 @@
 menuconfig ARCH_DAVINCI
 	bool "TI DaVinci"
 	depends on ARCH_MULTI_V5
+	select CPU_ARM926T
 	select DAVINCI_TIMER
 	select ZONE_DMA
-	select ARCH_HAS_HOLES_MEMORYMODEL
 	select PM_GENERIC_DOMAINS if PM
 	select PM_GENERIC_DOMAINS_OF if PM && OF
 	select REGMAP_MMIO
+	select RESET_CONTROLLER
 	select HAVE_IDE
 	select PINCTRL_SINGLE
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-davinci/board-da850-evm.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-davinci/board-da850-evm.c
@@ -1101,11 +1101,13 @@
 	int ret;
 	u32 val;
 	struct davinci_soc_info *soc_info = &davinci_soc_info;
-	u8 rmii_en = soc_info->emac_pdata->rmii_en;
+	u8 rmii_en;
 
 	if (!machine_is_davinci_da850_evm())
 		return 0;
 
+	rmii_en = soc_info->emac_pdata->rmii_en;
+
 	cfg_chip3_base = DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG);
 
 	val = __raw_readl(cfg_chip3_base);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-davinci/pm.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-davinci/pm.c
@@ -62,7 +62,7 @@
 
 	/* Configure sleep count in deep sleep register */
 	val = __raw_readl(pm_config.deepsleep_reg);
-	val &= ~DEEPSLEEP_SLEEPCOUNT_MASK,
+	val &= ~DEEPSLEEP_SLEEPCOUNT_MASK;
 	val |= pm_config.sleepcount;
 	__raw_writel(val, pm_config.deepsleep_reg);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-ep93xx/core.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-ep93xx/core.c
@@ -337,6 +337,7 @@
 				GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
 		GPIO_LOOKUP_IDX("G", 0, NULL, 1,
 				GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
+		{ }
 	},
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-ep93xx/timer-ep93xx.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-ep93xx/timer-ep93xx.c
@@ -9,6 +9,7 @@
 #include <linux/io.h>
 #include <asm/mach/time.h>
 #include "soc.h"
+#include "platform.h"
 
 /*************************************************************************
  * Timer handling for EP93xx
@@ -60,7 +61,7 @@
 	return ret;
 }
 
-u64 ep93xx_clocksource_read(struct clocksource *c)
+static u64 ep93xx_clocksource_read(struct clocksource *c)
 {
 	u64 ret;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-exynos/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-exynos/Kconfig
@@ -8,7 +8,6 @@
 menuconfig ARCH_EXYNOS
 	bool "Samsung EXYNOS"
 	depends on ARCH_MULTI_V7
-	select ARCH_HAS_HOLES_MEMORYMODEL
 	select ARCH_SUPPORTS_BIG_ENDIAN
 	select ARM_AMBA
 	select ARM_GIC
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-exynos/exynos.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-exynos/exynos.c
@@ -46,6 +46,7 @@
 		sysram_base_addr = of_iomap(node, 0);
 		sysram_base_phys = of_translate_address(node,
 					   of_get_address(node, 0, NULL, NULL));
+		of_node_put(node);
 		break;
 	}
 
@@ -53,6 +54,7 @@
 		if (!of_device_is_available(node))
 			continue;
 		sysram_ns_base_addr = of_iomap(node, 0);
+		of_node_put(node);
 		break;
 	}
 }
@@ -134,6 +136,7 @@
 	np = of_find_matching_node(NULL, exynos_dt_pmu_match);
 	if (np)
 		pmu_base_addr = of_iomap(np, 0);
+	of_node_put(np);
 }
 
 static void __init exynos_init_irq(void)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-exynos/mcpm-exynos.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-exynos/mcpm-exynos.c
@@ -26,6 +26,7 @@
 #define EXYNOS5420_USE_L2_COMMON_UP_STATE	BIT(30)
 
 static void __iomem *ns_sram_base_addr __ro_after_init;
+static bool secure_firmware __ro_after_init;
 
 /*
  * The common v7_exit_coherency_flush API could not be used because of the
@@ -58,15 +59,16 @@
 static int exynos_cpu_powerup(unsigned int cpu, unsigned int cluster)
 {
 	unsigned int cpunr = cpu + (cluster * EXYNOS5420_CPUS_PER_CLUSTER);
+	bool state;
 
 	pr_debug("%s: cpu %u cluster %u\n", __func__, cpu, cluster);
 	if (cpu >= EXYNOS5420_CPUS_PER_CLUSTER ||
 		cluster >= EXYNOS5420_NR_CLUSTERS)
 		return -EINVAL;
 
-	if (!exynos_cpu_power_state(cpunr)) {
-		exynos_cpu_power_up(cpunr);
-
+	state = exynos_cpu_power_state(cpunr);
+	exynos_cpu_power_up(cpunr);
+	if (!state && secure_firmware) {
 		/*
 		 * This assumes the cluster number of the big cores(Cortex A15)
 		 * is 0 and the Little cores(Cortex A7) is 1.
@@ -258,6 +260,8 @@
 		return -ENOMEM;
 	}
 
+	secure_firmware = exynos_secure_firmware_available();
+
 	/*
 	 * To increase the stability of KFC reset we need to program
 	 * the PMU SPARE3 register
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-footbridge/cats-pci.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-footbridge/cats-pci.c
@@ -15,14 +15,14 @@
 #include <asm/mach-types.h>
 
 /* cats host-specific stuff */
-static int irqmap_cats[] __initdata = { IRQ_PCI, IRQ_IN0, IRQ_IN1, IRQ_IN3 };
+static int irqmap_cats[] = { IRQ_PCI, IRQ_IN0, IRQ_IN1, IRQ_IN3 };
 
 static u8 cats_no_swizzle(struct pci_dev *dev, u8 *pin)
 {
 	return 0;
 }
 
-static int __init cats_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+static int cats_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	if (dev->irq >= 255)
 		return -1;	/* not a valid interrupt. */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-footbridge/dc21285.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-footbridge/dc21285.c
@@ -66,15 +66,15 @@
 	if (addr)
 		switch (size) {
 		case 1:
-			asm("ldrb	%0, [%1, %2]"
+			asm volatile("ldrb	%0, [%1, %2]"
 				: "=r" (v) : "r" (addr), "r" (where) : "cc");
 			break;
 		case 2:
-			asm("ldrh	%0, [%1, %2]"
+			asm volatile("ldrh	%0, [%1, %2]"
 				: "=r" (v) : "r" (addr), "r" (where) : "cc");
 			break;
 		case 4:
-			asm("ldr	%0, [%1, %2]"
+			asm volatile("ldr	%0, [%1, %2]"
 				: "=r" (v) : "r" (addr), "r" (where) : "cc");
 			break;
 		}
@@ -100,17 +100,17 @@
 	if (addr)
 		switch (size) {
 		case 1:
-			asm("strb	%0, [%1, %2]"
+			asm volatile("strb	%0, [%1, %2]"
 				: : "r" (value), "r" (addr), "r" (where)
 				: "cc");
 			break;
 		case 2:
-			asm("strh	%0, [%1, %2]"
+			asm volatile("strh	%0, [%1, %2]"
 				: : "r" (value), "r" (addr), "r" (where)
 				: "cc");
 			break;
 		case 4:
-			asm("str	%0, [%1, %2]"
+			asm volatile("str	%0, [%1, %2]"
 				: : "r" (value), "r" (addr), "r" (where)
 				: "cc");
 			break;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-footbridge/ebsa285-pci.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-footbridge/ebsa285-pci.c
@@ -14,9 +14,9 @@
 #include <asm/mach/pci.h>
 #include <asm/mach-types.h>
 
-static int irqmap_ebsa285[] __initdata = { IRQ_IN3, IRQ_IN1, IRQ_IN0, IRQ_PCI };
+static int irqmap_ebsa285[] = { IRQ_IN3, IRQ_IN1, IRQ_IN0, IRQ_PCI };
 
-static int __init ebsa285_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+static int ebsa285_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	if (dev->vendor == PCI_VENDOR_ID_CONTAQ &&
 	    dev->device == PCI_DEVICE_ID_CONTAQ_82C693)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-footbridge/netwinder-pci.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-footbridge/netwinder-pci.c
@@ -18,7 +18,7 @@
  * We now use the slot ID instead of the device identifiers to select
  * which interrupt is routed where.
  */
-static int __init netwinder_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+static int netwinder_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	switch (slot) {
 	case 0:  /* host bridge */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-footbridge/personal-pci.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-footbridge/personal-pci.c
@@ -14,13 +14,12 @@
 #include <asm/mach/pci.h>
 #include <asm/mach-types.h>
 
-static int irqmap_personal_server[] __initdata = {
+static int irqmap_personal_server[] = {
 	IRQ_IN0, IRQ_IN1, IRQ_IN2, IRQ_IN3, 0, 0, 0,
 	IRQ_DOORBELLHOST, IRQ_DMA1, IRQ_DMA2, IRQ_PCI
 };
 
-static int __init personal_server_map_irq(const struct pci_dev *dev, u8 slot,
-	u8 pin)
+static int personal_server_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	unsigned char line;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-highbank/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-highbank/Kconfig
@@ -2,7 +2,6 @@
 config ARCH_HIGHBANK
 	bool "Calxeda ECX-1000/2000 (Highbank/Midway)"
 	depends on ARCH_MULTI_V7
-	select ARCH_HAS_HOLES_MEMORYMODEL
 	select ARCH_SUPPORTS_BIG_ENDIAN
 	select ARM_AMBA
 	select ARM_ERRATA_764369 if SMP
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-hisi/platsmp.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-hisi/platsmp.c
@@ -67,14 +67,17 @@
 		}
 		ctrl_base = of_iomap(np, 0);
 		if (!ctrl_base) {
+			of_node_put(np);
 			pr_err("failed to map address\n");
 			return;
 		}
 		if (of_property_read_u32(np, "smp-offset", &offset) < 0) {
+			of_node_put(np);
 			pr_err("failed to find smp-offset property\n");
 			return;
 		}
 		ctrl_base += offset;
+		of_node_put(np);
 	}
 }
 
@@ -160,6 +163,7 @@
 	if (WARN_ON(!node))
 		return -1;
 	ctrl_base = of_iomap(node, 0);
+	of_node_put(node);
 
 	/* set the secondary core boot from DDR */
 	remap_reg_value = readl_relaxed(ctrl_base + REG_SC_CTRL);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-imx/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-imx/Kconfig
@@ -520,6 +520,7 @@
 	bool "i.MX6 UltraLite support"
 	select PINCTRL_IMX6UL
 	select SOC_IMX6
+	select ARM_ERRATA_814220
 
 	help
 	  This enables support for Freescale i.MX6 UltraLite processor.
@@ -556,6 +557,7 @@
 	select PINCTRL_IMX7D
 	select SOC_IMX7D_CA7 if ARCH_MULTI_V7
 	select SOC_IMX7D_CM4 if ARM_SINGLE_ARMV7M
+	select ARM_ERRATA_814220 if ARCH_MULTI_V7
 	help
 		This enables support for Freescale i.MX7 Dual processor.
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-imx/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-imx/Makefile
@@ -91,6 +91,10 @@
 obj-$(CONFIG_SOC_IMX6) += suspend-imx6.o
 obj-$(CONFIG_SOC_IMX53) += suspend-imx53.o
 endif
+ifeq ($(CONFIG_ARM_CPU_SUSPEND),y)
+AFLAGS_resume-imx6.o :=-Wa,-march=armv7-a
+obj-$(CONFIG_SOC_IMX6) += resume-imx6.o
+endif
 obj-$(CONFIG_SOC_IMX6) += pm-imx6.o
 
 obj-$(CONFIG_SOC_IMX1) += mach-imx1.o
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-imx/common.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-imx/common.h
@@ -109,17 +109,17 @@
 int imx_cpu_kill(unsigned int cpu);
 
 #ifdef CONFIG_SUSPEND
-void v7_cpu_resume(void);
 void imx53_suspend(void __iomem *ocram_vbase);
 extern const u32 imx53_suspend_sz;
 void imx6_suspend(void __iomem *ocram_vbase);
 #else
-static inline void v7_cpu_resume(void) {}
 static inline void imx53_suspend(void __iomem *ocram_vbase) {}
 static const u32 imx53_suspend_sz;
 static inline void imx6_suspend(void __iomem *ocram_vbase) {}
 #endif
 
+void v7_cpu_resume(void);
+
 void imx6_pm_ccm_init(const char *ccm_compat);
 void imx6q_pm_init(void);
 void imx6dl_pm_init(void);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-imx/cpu-imx25.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-imx/cpu-imx25.c
@@ -23,6 +23,7 @@
 
 	np = of_find_compatible_node(NULL, NULL, "fsl,imx25-iim");
 	iim_base = of_iomap(np, 0);
+	of_node_put(np);
 	BUG_ON(!iim_base);
 	rev = readl(iim_base + MXC_IIMSREV);
 	iounmap(iim_base);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-imx/cpu-imx27.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-imx/cpu-imx27.c
@@ -9,6 +9,7 @@
  */
 
 #include <linux/io.h>
+#include <linux/of_address.h>
 #include <linux/module.h>
 
 #include "hardware.h"
@@ -17,16 +18,24 @@
 static int mx27_cpu_partnumber;
 
 #define SYS_CHIP_ID             0x00    /* The offset of CHIP ID register */
+#define SYSCTRL_OFFSET		0x800	/* Offset from CCM base address */
 
 static int mx27_read_cpu_rev(void)
 {
+	void __iomem *ccm_base;
+	struct device_node *np;
 	u32 val;
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx27-ccm");
+	ccm_base = of_iomap(np, 0);
+	of_node_put(np);
+	BUG_ON(!ccm_base);
 	/*
 	 * now we have access to the IO registers. As we need
 	 * the silicon revision very early we read it here to
 	 * avoid any further hooks
 	*/
-	val = imx_readl(MX27_IO_ADDRESS(MX27_SYSCTRL_BASE_ADDR + SYS_CHIP_ID));
+	val = imx_readl(ccm_base + SYSCTRL_OFFSET + SYS_CHIP_ID);
 
 	mx27_cpu_partnumber = (int)((val >> 12) & 0xFFFF);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-imx/cpu-imx31.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-imx/cpu-imx31.c
@@ -6,6 +6,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/of_address.h>
 #include <linux/io.h>
 
 #include "common.h"
@@ -32,10 +33,17 @@
 
 static int mx31_read_cpu_rev(void)
 {
+	void __iomem *iim_base;
+	struct device_node *np;
 	u32 i, srev;
 
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx31-iim");
+	iim_base = of_iomap(np, 0);
+	of_node_put(np);
+	BUG_ON(!iim_base);
+
 	/* read SREV register from IIM module */
-	srev = imx_readl(MX31_IO_ADDRESS(MX31_IIM_BASE_ADDR + MXC_IIMSREV));
+	srev = imx_readl(iim_base + MXC_IIMSREV);
 	srev &= 0xff;
 
 	for (i = 0; i < ARRAY_SIZE(mx31_cpu_type); i++)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-imx/cpu-imx35.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-imx/cpu-imx35.c
@@ -5,6 +5,7 @@
  * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
  */
 #include <linux/module.h>
+#include <linux/of_address.h>
 #include <linux/io.h>
 
 #include "hardware.h"
@@ -14,9 +15,16 @@
 
 static int mx35_read_cpu_rev(void)
 {
+	void __iomem *iim_base;
+	struct device_node *np;
 	u32 rev;
 
-	rev = imx_readl(MX35_IO_ADDRESS(MX35_IIM_BASE_ADDR + MXC_IIMSREV));
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx35-iim");
+	iim_base = of_iomap(np, 0);
+	of_node_put(np);
+	BUG_ON(!iim_base);
+
+	rev = imx_readl(iim_base + MXC_IIMSREV);
 	switch (rev) {
 	case 0x00:
 		return IMX_CHIP_REVISION_1_0;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-imx/cpu-imx5.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-imx/cpu-imx5.c
@@ -28,6 +28,7 @@
 
 	np = of_find_compatible_node(NULL, NULL, compat);
 	iim_base = of_iomap(np, 0);
+	of_node_put(np);
 	WARN_ON(!iim_base);
 
 	srev = readl(iim_base + IIM_SREV) & 0xff;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-imx/mmdc.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-imx/mmdc.c
@@ -99,10 +99,12 @@
 	cpumask_t cpu;
 	struct hrtimer hrtimer;
 	unsigned int active_events;
+	int id;
 	struct device *dev;
 	struct perf_event *mmdc_events[MMDC_NUM_COUNTERS];
 	struct hlist_node node;
 	struct fsl_mmdc_devtype_data *devtype_data;
+	struct clk *mmdc_ipg_clk;
 };
 
 /*
@@ -432,8 +434,6 @@
 static int mmdc_pmu_init(struct mmdc_pmu *pmu_mmdc,
 		void __iomem *mmdc_base, struct device *dev)
 {
-	int mmdc_num;
-
 	*pmu_mmdc = (struct mmdc_pmu) {
 		.pmu = (struct pmu) {
 			.task_ctx_nr    = perf_invalid_context,
@@ -451,26 +451,29 @@
 		.active_events = 0,
 	};
 
-	mmdc_num = ida_simple_get(&mmdc_ida, 0, 0, GFP_KERNEL);
+	pmu_mmdc->id = ida_simple_get(&mmdc_ida, 0, 0, GFP_KERNEL);
 
-	return mmdc_num;
+	return pmu_mmdc->id;
 }
 
 static int imx_mmdc_remove(struct platform_device *pdev)
 {
 	struct mmdc_pmu *pmu_mmdc = platform_get_drvdata(pdev);
 
+	ida_simple_remove(&mmdc_ida, pmu_mmdc->id);
 	cpuhp_state_remove_instance_nocalls(cpuhp_mmdc_state, &pmu_mmdc->node);
 	perf_pmu_unregister(&pmu_mmdc->pmu);
+	iounmap(pmu_mmdc->mmdc_base);
+	clk_disable_unprepare(pmu_mmdc->mmdc_ipg_clk);
 	kfree(pmu_mmdc);
 	return 0;
 }
 
-static int imx_mmdc_perf_init(struct platform_device *pdev, void __iomem *mmdc_base)
+static int imx_mmdc_perf_init(struct platform_device *pdev, void __iomem *mmdc_base,
+			      struct clk *mmdc_ipg_clk)
 {
 	struct mmdc_pmu *pmu_mmdc;
 	char *name;
-	int mmdc_num;
 	int ret;
 	const struct of_device_id *of_id =
 		of_match_device(imx_mmdc_dt_ids, &pdev->dev);
@@ -493,13 +496,18 @@
 		cpuhp_mmdc_state = ret;
 	}
 
-	mmdc_num = mmdc_pmu_init(pmu_mmdc, mmdc_base, &pdev->dev);
-	if (mmdc_num == 0)
-		name = "mmdc";
-	else
-		name = devm_kasprintf(&pdev->dev,
-				GFP_KERNEL, "mmdc%d", mmdc_num);
+	ret = mmdc_pmu_init(pmu_mmdc, mmdc_base, &pdev->dev);
+	if (ret < 0)
+		goto  pmu_free;
+
+	name = devm_kasprintf(&pdev->dev,
+				GFP_KERNEL, "mmdc%d", ret);
+	if (!name) {
+		ret = -ENOMEM;
+		goto pmu_release_id;
+	}
 
+	pmu_mmdc->mmdc_ipg_clk = mmdc_ipg_clk;
 	pmu_mmdc->devtype_data = (struct fsl_mmdc_devtype_data *)of_id->data;
 
 	hrtimer_init(&pmu_mmdc->hrtimer, CLOCK_MONOTONIC,
@@ -522,6 +530,8 @@
 	pr_warn("MMDC Perf PMU failed (%d), disabled\n", ret);
 	cpuhp_state_remove_instance_nocalls(cpuhp_mmdc_state, &pmu_mmdc->node);
 	hrtimer_cancel(&pmu_mmdc->hrtimer);
+pmu_release_id:
+	ida_simple_remove(&mmdc_ida, pmu_mmdc->id);
 pmu_free:
 	kfree(pmu_mmdc);
 	return ret;
@@ -529,7 +539,7 @@
 
 #else
 #define imx_mmdc_remove NULL
-#define imx_mmdc_perf_init(pdev, mmdc_base) 0
+#define imx_mmdc_perf_init(pdev, mmdc_base, mmdc_ipg_clk) 0
 #endif
 
 static int imx_mmdc_probe(struct platform_device *pdev)
@@ -567,7 +577,13 @@
 	val &= ~(1 << BP_MMDC_MAPSR_PSD);
 	writel_relaxed(val, reg);
 
-	return imx_mmdc_perf_init(pdev, mmdc_base);
+	err = imx_mmdc_perf_init(pdev, mmdc_base, mmdc_ipg_clk);
+	if (err) {
+		iounmap(mmdc_base);
+		clk_disable_unprepare(mmdc_ipg_clk);
+	}
+
+	return err;
 }
 
 int imx_mmdc_get_ddr_type(void)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-imx/pm-imx5.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-imx/pm-imx5.c
@@ -295,14 +295,14 @@
 	if (!ocram_pool) {
 		pr_warn("%s: ocram pool unavailable!\n", __func__);
 		ret = -ENODEV;
-		goto put_node;
+		goto put_device;
 	}
 
 	ocram_base = gen_pool_alloc(ocram_pool, size);
 	if (!ocram_base) {
 		pr_warn("%s: unable to alloc ocram!\n", __func__);
 		ret = -ENOMEM;
-		goto put_node;
+		goto put_device;
 	}
 
 	phys = gen_pool_virt_to_phys(ocram_pool, ocram_base);
@@ -312,6 +312,8 @@
 	if (virt_out)
 		*virt_out = virt;
 
+put_device:
+	put_device(&pdev->dev);
 put_node:
 	of_node_put(node);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-imx/pm-imx6.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-imx/pm-imx6.c
@@ -9,6 +9,7 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/genalloc.h>
+#include <linux/irqchip/arm-gic.h>
 #include <linux/mfd/syscon.h>
 #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
 #include <linux/of.h>
@@ -493,14 +494,14 @@
 	if (!ocram_pool) {
 		pr_warn("%s: ocram pool unavailable!\n", __func__);
 		ret = -ENODEV;
-		goto put_node;
+		goto put_device;
 	}
 
 	ocram_base = gen_pool_alloc(ocram_pool, MX6Q_SUSPEND_OCRAM_SIZE);
 	if (!ocram_base) {
 		pr_warn("%s: unable to alloc ocram!\n", __func__);
 		ret = -ENOMEM;
-		goto put_node;
+		goto put_device;
 	}
 
 	ocram_pbase = gen_pool_virt_to_phys(ocram_pool, ocram_base);
@@ -523,7 +524,7 @@
 	ret = imx6_pm_get_base(&pm_info->mmdc_base, socdata->mmdc_compat);
 	if (ret) {
 		pr_warn("%s: failed to get mmdc base %d!\n", __func__, ret);
-		goto put_node;
+		goto put_device;
 	}
 
 	ret = imx6_pm_get_base(&pm_info->src_base, socdata->src_compat);
@@ -570,7 +571,7 @@
 		&imx6_suspend,
 		MX6Q_SUSPEND_OCRAM_SIZE - sizeof(*pm_info));
 
-	goto put_node;
+	goto put_device;
 
 pl310_cache_map_failed:
 	iounmap(pm_info->gpc_base.vbase);
@@ -580,6 +581,8 @@
 	iounmap(pm_info->src_base.vbase);
 src_map_failed:
 	iounmap(pm_info->mmdc_base.vbase);
+put_device:
+	put_device(&pdev->dev);
 put_node:
 	of_node_put(node);
 
@@ -616,6 +619,7 @@
 
 static void imx6_pm_stby_poweroff(void)
 {
+	gic_cpu_if_down(0);
 	imx6_set_lpm(STOP_POWER_OFF);
 	imx6q_suspend_finish(0);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-imx/resume-imx6.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-imx/resume-imx6.S
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/asm-offsets.h>
+#include <asm/hardware/cache-l2x0.h>
+#include "hardware.h"
+
+/*
+ * The following code must assume it is running from physical address
+ * where absolute virtual addresses to the data section have to be
+ * turned into relative ones.
+ */
+
+ENTRY(v7_cpu_resume)
+	bl	v7_invalidate_l1
+#ifdef CONFIG_CACHE_L2X0
+	bl	l2c310_early_resume
+#endif
+	b	cpu_resume
+ENDPROC(v7_cpu_resume)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-imx/suspend-imx53.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-imx/suspend-imx53.S
@@ -28,11 +28,11 @@
  *                              ^
  *                              ^
  *                      imx53_suspend code
- *              PM_INFO structure(imx53_suspend_info)
+ *              PM_INFO structure(imx5_cpu_suspend_info)
  * ======================== low address =======================
  */
 
-/* Offsets of members of struct imx53_suspend_info */
+/* Offsets of members of struct imx5_cpu_suspend_info */
 #define SUSPEND_INFO_MX53_M4IF_V_OFFSET		0x0
 #define SUSPEND_INFO_MX53_IOMUXC_V_OFFSET	0x4
 #define SUSPEND_INFO_MX53_IO_COUNT_OFFSET	0x8
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-imx/suspend-imx6.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-imx/suspend-imx6.S
@@ -67,6 +67,7 @@
 #define MX6Q_CCM_CCR	0x0
 
 	.align 3
+	.arm
 
 	.macro  sync_l2_cache
 
@@ -327,17 +328,3 @@
 
 	ret	lr
 ENDPROC(imx6_suspend)
-
-/*
- * The following code must assume it is running from physical address
- * where absolute virtual addresses to the data section have to be
- * turned into relative ones.
- */
-
-ENTRY(v7_cpu_resume)
-	bl	v7_invalidate_l1
-#ifdef CONFIG_CACHE_L2X0
-	bl	l2c310_early_resume
-#endif
-	b	cpu_resume
-ENDPROC(v7_cpu_resume)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-integrator/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-integrator/Kconfig
@@ -4,6 +4,8 @@
 	depends on ARCH_MULTI_V4T || ARCH_MULTI_V5 || ARCH_MULTI_V6
 	select ARM_AMBA
 	select COMMON_CLK_VERSATILE
+	select CMA
+	select DMA_CMA
 	select HAVE_TCM
 	select ICST
 	select MFD_SYSCON
@@ -35,14 +37,13 @@
 	select ARM_VIC
 	select GPIO_PL061
 	select GPIOLIB
+	select REGULATOR
+	select REGULATOR_FIXED_VOLTAGE
 	help
 	  The IM-PD1 is an add-on logic module for the Integrator which
 	  allows ARM(R) Ltd PrimeCells to be developed and evaluated.
 	  The IM-PD1 can be found on the Integrator/PP2 platform.
 
-	  To compile this driver as a module, choose M here: the
-	  module will be called impd1.
-
 config INTEGRATOR_CM7TDMI
 	bool "Integrator/CM7TDMI core module"
 	depends on ARCH_INTEGRATOR_AP
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-iop32x/include/mach/entry-macro.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-iop32x/include/mach/entry-macro.S
@@ -20,7 +20,7 @@
 	mrc     p6, 0, \irqstat, c8, c0, 0	@ Read IINTSRC
 	cmp     \irqstat, #0
 	clzne   \irqnr, \irqstat
-	rsbne   \irqnr, \irqnr, #31
+	rsbne   \irqnr, \irqnr, #32
 	.endm
 
 	.macro arch_ret_to_user, tmp1, tmp2
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-iop32x/include/mach/irqs.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-iop32x/include/mach/irqs.h
@@ -9,6 +9,6 @@
 #ifndef __IRQS_H
 #define __IRQS_H
 
-#define NR_IRQS			32
+#define NR_IRQS			33
 
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-iop32x/irq.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-iop32x/irq.c
@@ -32,14 +32,14 @@
 static void
 iop32x_irq_mask(struct irq_data *d)
 {
-	iop32x_mask &= ~(1 << d->irq);
+	iop32x_mask &= ~(1 << (d->irq - 1));
 	intctl_write(iop32x_mask);
 }
 
 static void
 iop32x_irq_unmask(struct irq_data *d)
 {
-	iop32x_mask |= 1 << d->irq;
+	iop32x_mask |= 1 << (d->irq - 1);
 	intctl_write(iop32x_mask);
 }
 
@@ -65,7 +65,7 @@
 	    machine_is_em7210())
 		*IOP3XX_PCIIRSR = 0x0f;
 
-	for (i = 0; i < NR_IRQS; i++) {
+	for (i = 1; i < NR_IRQS; i++) {
 		irq_set_chip_and_handler(i, &ext_chip, handle_level_irq);
 		irq_clear_status_flags(i, IRQ_NOREQUEST | IRQ_NOPROBE);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-iop32x/irqs.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-iop32x/irqs.h
@@ -7,36 +7,40 @@
 #ifndef __IOP32X_IRQS_H
 #define __IOP32X_IRQS_H
 
+/* Interrupts in Linux start at 1, hardware starts at 0 */
+
+#define IOP_IRQ(x) ((x) + 1)
+
 /*
  * IOP80321 chipset interrupts
  */
-#define IRQ_IOP32X_DMA0_EOT	0
-#define IRQ_IOP32X_DMA0_EOC	1
-#define IRQ_IOP32X_DMA1_EOT	2
-#define IRQ_IOP32X_DMA1_EOC	3
-#define IRQ_IOP32X_AA_EOT	6
-#define IRQ_IOP32X_AA_EOC	7
-#define IRQ_IOP32X_CORE_PMON	8
-#define IRQ_IOP32X_TIMER0	9
-#define IRQ_IOP32X_TIMER1	10
-#define IRQ_IOP32X_I2C_0	11
-#define IRQ_IOP32X_I2C_1	12
-#define IRQ_IOP32X_MESSAGING	13
-#define IRQ_IOP32X_ATU_BIST	14
-#define IRQ_IOP32X_PERFMON	15
-#define IRQ_IOP32X_CORE_PMU	16
-#define IRQ_IOP32X_BIU_ERR	17
-#define IRQ_IOP32X_ATU_ERR	18
-#define IRQ_IOP32X_MCU_ERR	19
-#define IRQ_IOP32X_DMA0_ERR	20
-#define IRQ_IOP32X_DMA1_ERR	21
-#define IRQ_IOP32X_AA_ERR	23
-#define IRQ_IOP32X_MSG_ERR	24
-#define IRQ_IOP32X_SSP		25
-#define IRQ_IOP32X_XINT0	27
-#define IRQ_IOP32X_XINT1	28
-#define IRQ_IOP32X_XINT2	29
-#define IRQ_IOP32X_XINT3	30
-#define IRQ_IOP32X_HPI		31
+#define IRQ_IOP32X_DMA0_EOT	IOP_IRQ(0)
+#define IRQ_IOP32X_DMA0_EOC	IOP_IRQ(1)
+#define IRQ_IOP32X_DMA1_EOT	IOP_IRQ(2)
+#define IRQ_IOP32X_DMA1_EOC	IOP_IRQ(3)
+#define IRQ_IOP32X_AA_EOT	IOP_IRQ(6)
+#define IRQ_IOP32X_AA_EOC	IOP_IRQ(7)
+#define IRQ_IOP32X_CORE_PMON	IOP_IRQ(8)
+#define IRQ_IOP32X_TIMER0	IOP_IRQ(9)
+#define IRQ_IOP32X_TIMER1	IOP_IRQ(10)
+#define IRQ_IOP32X_I2C_0	IOP_IRQ(11)
+#define IRQ_IOP32X_I2C_1	IOP_IRQ(12)
+#define IRQ_IOP32X_MESSAGING	IOP_IRQ(13)
+#define IRQ_IOP32X_ATU_BIST	IOP_IRQ(14)
+#define IRQ_IOP32X_PERFMON	IOP_IRQ(15)
+#define IRQ_IOP32X_CORE_PMU	IOP_IRQ(16)
+#define IRQ_IOP32X_BIU_ERR	IOP_IRQ(17)
+#define IRQ_IOP32X_ATU_ERR	IOP_IRQ(18)
+#define IRQ_IOP32X_MCU_ERR	IOP_IRQ(19)
+#define IRQ_IOP32X_DMA0_ERR	IOP_IRQ(20)
+#define IRQ_IOP32X_DMA1_ERR	IOP_IRQ(21)
+#define IRQ_IOP32X_AA_ERR	IOP_IRQ(23)
+#define IRQ_IOP32X_MSG_ERR	IOP_IRQ(24)
+#define IRQ_IOP32X_SSP		IOP_IRQ(25)
+#define IRQ_IOP32X_XINT0	IOP_IRQ(27)
+#define IRQ_IOP32X_XINT1	IOP_IRQ(28)
+#define IRQ_IOP32X_XINT2	IOP_IRQ(29)
+#define IRQ_IOP32X_XINT3	IOP_IRQ(30)
+#define IRQ_IOP32X_HPI		IOP_IRQ(31)
 
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-ixp4xx/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-ixp4xx/Kconfig
@@ -13,7 +13,6 @@
 	select I2C
 	select I2C_IOP3XX
 	select PCI
-	select TIMER_OF
 	select USE_OF
 	help
 	  Say 'Y' here to support Device Tree-based IXP4xx platforms.
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-keystone/keystone.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-keystone/keystone.c
@@ -62,7 +62,7 @@
 static long long __init keystone_pv_fixup(void)
 {
 	long long offset;
-	phys_addr_t mem_start, mem_end;
+	u64 mem_start, mem_end;
 
 	mem_start = memblock_start_of_DRAM();
 	mem_end = memblock_end_of_DRAM();
@@ -75,7 +75,7 @@
 	if (mem_start < KEYSTONE_HIGH_PHYS_START ||
 	    mem_end   > KEYSTONE_HIGH_PHYS_END) {
 		pr_crit("Invalid address space for memory (%08llx-%08llx)\n",
-		        (u64)mem_start, (u64)mem_end);
+		        mem_start, mem_end);
 		return 0;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-mediatek/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-mediatek/Kconfig
@@ -30,6 +30,7 @@
 config MACH_MT7629
 	bool "MediaTek MT7629 SoCs support"
 	default ARCH_MEDIATEK
+	select HAVE_ARM_ARCH_TIMER
 
 config MACH_MT8127
 	bool "MediaTek MT8127 SoCs support"
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-meson/platsmp.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-meson/platsmp.c
@@ -71,6 +71,7 @@
 	}
 
 	sram_base = of_iomap(node, 0);
+	of_node_put(node);
 	if (!sram_base) {
 		pr_err("Couldn't map SRAM registers\n");
 		return;
@@ -91,6 +92,7 @@
 	}
 
 	scu_base = of_iomap(node, 0);
+	of_node_put(node);
 	if (!scu_base) {
 		pr_err("Couldn't map SCU registers\n");
 		return;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-mmp/sram.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-mmp/sram.c
@@ -72,6 +72,8 @@
 	if (!info)
 		return -ENOMEM;
 
+	platform_set_drvdata(pdev, info);
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (res == NULL) {
 		dev_err(&pdev->dev, "no memory resource defined\n");
@@ -107,8 +109,6 @@
 	list_add(&info->node, &sram_bank_list);
 	mutex_unlock(&sram_lock);
 
-	platform_set_drvdata(pdev, info);
-
 	dev_info(&pdev->dev, "initialized\n");
 	return 0;
 
@@ -127,17 +127,19 @@
 	struct sram_bank_info *info;
 
 	info = platform_get_drvdata(pdev);
-	if (info == NULL)
-		return -ENODEV;
 
-	mutex_lock(&sram_lock);
-	list_del(&info->node);
-	mutex_unlock(&sram_lock);
+	if (info->sram_size) {
+		mutex_lock(&sram_lock);
+		list_del(&info->node);
+		mutex_unlock(&sram_lock);
+
+		gen_pool_destroy(info->gpool);
+		iounmap(info->sram_virt);
+		kfree(info->pool_name);
+	}
 
-	gen_pool_destroy(info->gpool);
-	iounmap(info->sram_virt);
-	kfree(info->pool_name);
 	kfree(info);
+
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-mmp/time.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-mmp/time.c
@@ -44,18 +44,21 @@
 static void __iomem *mmp_timer_base = TIMERS_VIRT_BASE;
 
 /*
- * FIXME: the timer needs some delay to stablize the counter capture
+ * Read the timer through the CVWR register. Delay is required after requesting
+ * a read. The CR register cannot be directly read due to metastability issues
+ * documented in the PXA168 software manual.
  */
 static inline uint32_t timer_read(void)
 {
-	int delay = 100;
+	uint32_t val;
+	int delay = 3;
 
 	__raw_writel(1, mmp_timer_base + TMR_CVWR(1));
 
 	while (delay--)
-		cpu_relax();
+		val = __raw_readl(mmp_timer_base + TMR_CVWR(1));
 
-	return __raw_readl(mmp_timer_base + TMR_CVWR(1));
+	return val;
 }
 
 static u64 notrace mmp_read_sched_clock(void)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-mxs/mach-mxs.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-mxs/mach-mxs.c
@@ -387,8 +387,10 @@
 
 	root = of_find_node_by_path("/");
 	ret = of_property_read_string(root, "model", &soc_dev_attr->machine);
-	if (ret)
+	if (ret) {
+		kfree(soc_dev_attr);
 		return;
+	}
 
 	soc_dev_attr->family = "Freescale MXS Family";
 	soc_dev_attr->soc_id = mxs_get_soc_id();
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-npcm/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-npcm/Kconfig
@@ -11,7 +11,7 @@
 	depends on ARCH_MULTI_V7
 	select PINCTRL_NPCM7XX
 	select NPCM7XX_TIMER
-	select ARCH_REQUIRE_GPIOLIB
+	select GPIOLIB
 	select CACHE_L2X0
 	select ARM_GIC
 	select HAVE_ARM_TWD if SMP
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-omap1/ams-delta-fiq-handler.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-omap1/ams-delta-fiq-handler.S
@@ -15,6 +15,7 @@
 #include <linux/platform_data/gpio-omap.h>
 
 #include <asm/assembler.h>
+#include <asm/irq.h>
 
 #include "ams-delta-fiq.h"
 #include "board-ams-delta.h"
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-omap1/clock.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-omap1/clock.c
@@ -41,7 +41,7 @@
 unsigned long omap1_uart_recalc(struct clk *clk)
 {
 	unsigned int val = __raw_readl(clk->enable_reg);
-	return val & clk->enable_bit ? 48000000 : 12000000;
+	return val & 1 << clk->enable_bit ? 48000000 : 12000000;
 }
 
 unsigned long omap1_sossi_recalc(struct clk *clk)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-omap1/pm.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-omap1/pm.c
@@ -596,11 +596,6 @@
 	return IRQ_HANDLED;
 }
 
-static struct irqaction omap_wakeup_irq = {
-	.name		= "peripheral wakeup",
-	.handler	= omap_wakeup_interrupt
-};
-
 
 
 static const struct platform_suspend_ops omap_pm_ops = {
@@ -613,6 +608,7 @@
 static int __init omap_pm_init(void)
 {
 	int error = 0;
+	int irq;
 
 	if (!cpu_class_is_omap1())
 		return -ENODEV;
@@ -656,9 +652,12 @@
 	arm_pm_idle = omap1_pm_idle;
 
 	if (cpu_is_omap7xx())
-		setup_irq(INT_7XX_WAKE_UP_REQ, &omap_wakeup_irq);
+		irq = INT_7XX_WAKE_UP_REQ;
 	else if (cpu_is_omap16xx())
-		setup_irq(INT_1610_WAKE_UP_REQ, &omap_wakeup_irq);
+		irq = INT_1610_WAKE_UP_REQ;
+	if (request_irq(irq, omap_wakeup_interrupt, 0, "peripheral wakeup",
+			NULL))
+		pr_err("Failed to request irq %d (peripheral wakeup)\n", irq);
 
 	/* Program new power ramp-up time
 	 * (0 for most boards since we don't lower voltage when in deep sleep)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-omap1/time.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-omap1/time.c
@@ -155,15 +155,11 @@
 	return IRQ_HANDLED;
 }
 
-static struct irqaction omap_mpu_timer1_irq = {
-	.name		= "mpu_timer1",
-	.flags		= IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= omap_mpu_timer1_interrupt,
-};
-
 static __init void omap_init_mpu_timer(unsigned long rate)
 {
-	setup_irq(INT_TIMER1, &omap_mpu_timer1_irq);
+	if (request_irq(INT_TIMER1, omap_mpu_timer1_interrupt,
+			IRQF_TIMER | IRQF_IRQPOLL, "mpu_timer1", NULL))
+		pr_err("Failed to request irq %d (mpu_timer1)\n", INT_TIMER1);
 	omap_mpu_timer_start(0, (rate / HZ) - 1, 1);
 
 	clockevent_mpu_timer1.cpumask = cpumask_of(0);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-omap1/timer.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-omap1/timer.c
@@ -165,7 +165,7 @@
 	kfree(pdata);
 
 err_free_pdev:
-	platform_device_unregister(pdev);
+	platform_device_put(pdev);
 
 	return ret;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-omap1/timer32k.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-omap1/timer32k.c
@@ -148,15 +148,11 @@
 	return IRQ_HANDLED;
 }
 
-static struct irqaction omap_32k_timer_irq = {
-	.name		= "32KHz timer",
-	.flags		= IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= omap_32k_timer_interrupt,
-};
-
 static __init void omap_init_32k_timer(void)
 {
-	setup_irq(INT_OS_TIMER, &omap_32k_timer_irq);
+	if (request_irq(INT_OS_TIMER, omap_32k_timer_interrupt,
+			IRQF_TIMER | IRQF_IRQPOLL, "32KHz timer", NULL))
+		pr_err("Failed to request irq %d(32KHz timer)\n", INT_OS_TIMER);
 
 	clockevent_32k_timer.cpumask = cpumask_of(0);
 	clockevents_config_and_register(&clockevent_32k_timer,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-omap2/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-omap2/Kconfig
@@ -94,7 +94,7 @@
 config ARCH_OMAP2PLUS
 	bool
 	select ARCH_HAS_BANDGAP
-	select ARCH_HAS_HOLES_MEMORYMODEL
+	select ARCH_HAS_RESET_CONTROLLER
 	select ARCH_OMAP
 	select CLKSRC_MMIO
 	select GENERIC_IRQ_CHIP
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-omap2/board-generic.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-omap2/board-generic.c
@@ -327,7 +327,7 @@
 	.init_late	= dra7xx_init_late,
 	.init_irq	= omap_gic_of_init,
 	.init_machine	= omap_generic_init,
-	.init_time	= omap5_realtime_timer_init,
+	.init_time	= omap3_gptimer_timer_init,
 	.dt_compat	= dra74x_boards_compat,
 	.restart	= omap44xx_restart,
 MACHINE_END
@@ -350,7 +350,7 @@
 	.init_late	= dra7xx_init_late,
 	.init_irq	= omap_gic_of_init,
 	.init_machine	= omap_generic_init,
-	.init_time	= omap5_realtime_timer_init,
+	.init_time	= omap3_gptimer_timer_init,
 	.dt_compat	= dra72x_boards_compat,
 	.restart	= omap44xx_restart,
 MACHINE_END
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-omap2/board-n8x0.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-omap2/board-n8x0.c
@@ -322,6 +322,7 @@
 
 static void n8x0_mmc_callback(void *data, u8 card_mask)
 {
+#ifdef CONFIG_MMC_OMAP
 	int bit, *openp, index;
 
 	if (board_is_n800()) {
@@ -339,7 +340,6 @@
 	else
 		*openp = 0;
 
-#ifdef CONFIG_MMC_OMAP
 	omap_mmc_notify_cover_event(mmc_device, index, *openp);
 #else
 	pr_warn("MMC: notify cover event not available\n");
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-omap2/cpuidle34xx.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-omap2/cpuidle34xx.c
@@ -109,6 +109,7 @@
 			    int index)
 {
 	struct omap3_idle_statedata *cx = &omap3_idle_data[index];
+	int error;
 
 	if (omap_irq_pending() || need_resched())
 		goto return_sleep_time;
@@ -125,8 +126,11 @@
 	 * Call idle CPU PM enter notifier chain so that
 	 * VFP context is saved.
 	 */
-	if (cx->mpu_state == PWRDM_POWER_OFF)
-		cpu_pm_enter();
+	if (cx->mpu_state == PWRDM_POWER_OFF) {
+		error = cpu_pm_enter();
+		if (error)
+			goto out_clkdm_set;
+	}
 
 	/* Execute ARM wfi */
 	omap_sram_idle();
@@ -139,6 +143,7 @@
 	    pwrdm_read_prev_pwrst(mpu_pd) == PWRDM_POWER_OFF)
 		cpu_pm_exit();
 
+out_clkdm_set:
 	/* Re-allow idle for C1 */
 	if (cx->flags & OMAP_CPUIDLE_CX_NO_CLKDM_IDLE)
 		clkdm_allow_idle(mpu_pd->pwrdm_clkdms[0]);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-omap2/cpuidle44xx.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-omap2/cpuidle44xx.c
@@ -122,6 +122,7 @@
 {
 	struct idle_statedata *cx = state_ptr + index;
 	u32 mpuss_can_lose_context = 0;
+	int error;
 
 	/*
 	 * CPU0 has to wait and stay ON until CPU1 is OFF state.
@@ -150,27 +151,37 @@
 				 (cx->mpu_logic_state == PWRDM_POWER_OFF);
 
 	/* Enter broadcast mode for periodic timers */
-	tick_broadcast_enable();
+	RCU_NONIDLE(tick_broadcast_enable());
 
 	/* Enter broadcast mode for one-shot timers */
-	tick_broadcast_enter();
+	RCU_NONIDLE(tick_broadcast_enter());
 
 	/*
 	 * Call idle CPU PM enter notifier chain so that
 	 * VFP and per CPU interrupt context is saved.
 	 */
-	cpu_pm_enter();
+	error = cpu_pm_enter();
+	if (error)
+		goto cpu_pm_out;
 
 	if (dev->cpu == 0) {
 		pwrdm_set_logic_retst(mpu_pd, cx->mpu_logic_state);
-		omap_set_pwrdm_state(mpu_pd, cx->mpu_state);
+		RCU_NONIDLE(omap_set_pwrdm_state(mpu_pd, cx->mpu_state));
 
 		/*
 		 * Call idle CPU cluster PM enter notifier chain
 		 * to save GIC and wakeupgen context.
 		 */
-		if (mpuss_can_lose_context)
-			cpu_cluster_pm_enter();
+		if (mpuss_can_lose_context) {
+			error = cpu_cluster_pm_enter();
+			if (error) {
+				index = 0;
+				cx = state_ptr + index;
+				pwrdm_set_logic_retst(mpu_pd, cx->mpu_logic_state);
+				RCU_NONIDLE(omap_set_pwrdm_state(mpu_pd, cx->mpu_state));
+				mpuss_can_lose_context = 0;
+			}
+		}
 	}
 
 	omap4_enter_lowpower(dev->cpu, cx->cpu_state);
@@ -183,9 +194,9 @@
 		    mpuss_can_lose_context)
 			gic_dist_disable();
 
-		clkdm_deny_idle(cpu_clkdm[1]);
-		omap_set_pwrdm_state(cpu_pd[1], PWRDM_POWER_ON);
-		clkdm_allow_idle(cpu_clkdm[1]);
+		RCU_NONIDLE(clkdm_deny_idle(cpu_clkdm[1]));
+		RCU_NONIDLE(omap_set_pwrdm_state(cpu_pd[1], PWRDM_POWER_ON));
+		RCU_NONIDLE(clkdm_allow_idle(cpu_clkdm[1]));
 
 		if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD) &&
 		    mpuss_can_lose_context) {
@@ -198,19 +209,20 @@
 	}
 
 	/*
-	 * Call idle CPU PM exit notifier chain to restore
-	 * VFP and per CPU IRQ context.
-	 */
-	cpu_pm_exit();
-
-	/*
 	 * Call idle CPU cluster PM exit notifier chain
 	 * to restore GIC and wakeupgen context.
 	 */
 	if (dev->cpu == 0 && mpuss_can_lose_context)
 		cpu_cluster_pm_exit();
 
-	tick_broadcast_exit();
+	/*
+	 * Call idle CPU PM exit notifier chain to restore
+	 * VFP and per CPU IRQ context.
+	 */
+	cpu_pm_exit();
+
+cpu_pm_out:
+	RCU_NONIDLE(tick_broadcast_exit());
 
 fail:
 	cpuidle_coupled_parallel_barrier(dev, &abort_barrier);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-omap2/display.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-omap2/display.c
@@ -211,6 +211,7 @@
 	node = of_find_node_by_name(NULL, "omap4_padconf_global");
 	if (node)
 		omap4_dsi_mux_syscon = syscon_node_to_regmap(node);
+	of_node_put(node);
 
 	return 0;
 }
@@ -259,10 +260,13 @@
 
 	if (!pdev) {
 		pr_err("Unable to find DSS platform device\n");
+		of_node_put(node);
 		return -ENODEV;
 	}
 
 	r = of_platform_populate(node, NULL, NULL, &pdev->dev);
+	put_device(&pdev->dev);
+	of_node_put(node);
 	if (r) {
 		pr_err("Unable to populate DSS submodule devices\n");
 		return r;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-omap2/id.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-omap2/id.c
@@ -797,10 +797,15 @@
 
 	soc_dev_attr->machine  = soc_name;
 	soc_dev_attr->family   = omap_get_family();
+	if (!soc_dev_attr->family) {
+		kfree(soc_dev_attr);
+		return;
+	}
 	soc_dev_attr->revision = soc_rev;
 
 	soc_dev = soc_device_register(soc_dev_attr);
 	if (IS_ERR(soc_dev)) {
+		kfree(soc_dev_attr->family);
 		kfree(soc_dev_attr);
 		return;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-omap2/omap-iommu.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-omap2/omap-iommu.c
@@ -11,14 +11,43 @@
 
 #include "omap_hwmod.h"
 #include "omap_device.h"
+#include "clockdomain.h"
 #include "powerdomain.h"
 
+static void omap_iommu_dra7_emu_swsup_config(struct platform_device *pdev,
+					     bool enable)
+{
+	static struct clockdomain *emu_clkdm;
+	static DEFINE_SPINLOCK(emu_lock);
+	static atomic_t count;
+	struct device_node *np = pdev->dev.of_node;
+
+	if (!of_device_is_compatible(np, "ti,dra7-dsp-iommu"))
+		return;
+
+	if (!emu_clkdm) {
+		emu_clkdm = clkdm_lookup("emu_clkdm");
+		if (WARN_ON_ONCE(!emu_clkdm))
+			return;
+	}
+
+	spin_lock(&emu_lock);
+
+	if (enable && (atomic_inc_return(&count) == 1))
+		clkdm_deny_idle(emu_clkdm);
+	else if (!enable && (atomic_dec_return(&count) == 0))
+		clkdm_allow_idle(emu_clkdm);
+
+	spin_unlock(&emu_lock);
+}
+
 int omap_iommu_set_pwrdm_constraint(struct platform_device *pdev, bool request,
 				    u8 *pwrst)
 {
 	struct powerdomain *pwrdm;
 	struct omap_device *od;
 	u8 next_pwrst;
+	int ret = 0;
 
 	od = to_omap_device(pdev);
 	if (!od)
@@ -31,13 +60,21 @@
 	if (!pwrdm)
 		return -EINVAL;
 
-	if (request)
+	if (request) {
 		*pwrst = pwrdm_read_next_pwrst(pwrdm);
+		omap_iommu_dra7_emu_swsup_config(pdev, true);
+	}
 
 	if (*pwrst > PWRDM_POWER_RET)
-		return 0;
+		goto out;
 
 	next_pwrst = request ? PWRDM_POWER_ON : *pwrst;
 
-	return pwrdm_set_next_pwrst(pwrdm, next_pwrst);
+	ret = pwrdm_set_next_pwrst(pwrdm, next_pwrst);
+
+out:
+	if (!request)
+		omap_iommu_dra7_emu_swsup_config(pdev, false);
+
+	return ret;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-omap2/omap4-common.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-omap2/omap4-common.c
@@ -314,10 +314,12 @@
 
 	np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-gic");
 	gic_dist_base_addr = of_iomap(np, 0);
+	of_node_put(np);
 	WARN_ON(!gic_dist_base_addr);
 
 	np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-twd-timer");
 	twd_base = of_iomap(np, 0);
+	of_node_put(np);
 	WARN_ON(!twd_base);
 
 skip_errata_init:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-omap2/omap_device.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-omap2/omap_device.c
@@ -234,10 +234,12 @@
 		break;
 	case BUS_NOTIFY_BIND_DRIVER:
 		od = to_omap_device(pdev);
-		if (od && (od->_state == OMAP_DEVICE_STATE_ENABLED) &&
-		    pm_runtime_status_suspended(dev)) {
+		if (od) {
 			od->_driver_status = BUS_NOTIFY_BIND_DRIVER;
-			pm_runtime_set_active(dev);
+			if (od->_state == OMAP_DEVICE_STATE_ENABLED &&
+			    pm_runtime_status_suspended(dev)) {
+				pm_runtime_set_active(dev);
+			}
 		}
 		break;
 	case BUS_NOTIFY_ADD_DEVICE:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-omap2/omap_hwmod.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-omap2/omap_hwmod.c
@@ -782,8 +782,10 @@
 
 	for_each_matching_node(np, ti_clkctrl_match_table) {
 		ret = _setup_clkctrl_provider(np);
-		if (ret)
+		if (ret) {
+			of_node_put(np);
 			break;
+		}
 	}
 
 	return ret;
@@ -3535,7 +3537,7 @@
 };
 
 static const struct omap_hwmod_reset omap_reset_quirks[] = {
-	{ .match = "dss", .len = 3, .reset = omap_dss_reset, },
+	{ .match = "dss_core", .len = 8, .reset = omap_dss_reset, },
 	{ .match = "hdq1w", .len = 5, .reset = omap_hdq1w_reset, },
 	{ .match = "i2c", .len = 3, .reset = omap_i2c_reset, },
 	{ .match = "wd_timer", .len = 8, .reset = omap2_wd_timer_reset, },
@@ -3656,6 +3658,8 @@
 		oh->flags |= HWMOD_SWSUP_SIDLE_ACT;
 	if (data->cfg->quirks & SYSC_QUIRK_SWSUP_MSTANDBY)
 		oh->flags |= HWMOD_SWSUP_MSTANDBY;
+	if (data->cfg->quirks & SYSC_QUIRK_CLKDM_NOAUTO)
+		oh->flags |= HWMOD_CLKDM_NOAUTO;
 
 	error = omap_hwmod_check_module(dev, oh, data, sysc_fields,
 					rev_offs, sysc_offs, syss_offs,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-omap2/pdata-quirks.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-omap2/pdata-quirks.c
@@ -7,7 +7,6 @@
 #include <linux/clk.h>
 #include <linux/davinci_emac.h>
 #include <linux/gpio.h>
-#include <linux/gpio/machine.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/of_platform.h>
@@ -45,6 +44,17 @@
 static struct of_dev_auxdata omap_auxdata_lookup[];
 static struct twl4030_gpio_platform_data twl_gpio_auxdata;
 
+#if IS_ENABLED(CONFIG_OMAP_IOMMU)
+int omap_iommu_set_pwrdm_constraint(struct platform_device *pdev, bool request,
+				    u8 *pwrst);
+#else
+static inline int omap_iommu_set_pwrdm_constraint(struct platform_device *pdev,
+						  bool request, u8 *pwrst)
+{
+	return 0;
+}
+#endif
+
 #ifdef CONFIG_MACH_NOKIA_N8X0
 static void __init omap2420_n8x0_legacy_init(void)
 {
@@ -269,14 +279,6 @@
 	am35xx_emac_reset();
 }
 
-static struct platform_device omap3_rom_rng_device = {
-	.name		= "omap3-rom-rng",
-	.id		= -1,
-	.dev	= {
-		.platform_data	= rx51_secure_rng_call,
-	},
-};
-
 static void __init nokia_n900_legacy_init(void)
 {
 	hsmmc2_internal_input_clk();
@@ -292,9 +294,6 @@
 			pr_warn("RX-51: Not enabling ARM errata 430973 workaround\n");
 			pr_warn("Thumb binaries may crash randomly without this workaround\n");
 		}
-
-		pr_info("RX-51: Registering OMAP3 HWRNG device\n");
-		platform_device_register(&omap3_rom_rng_device);
 	}
 }
 
@@ -311,131 +310,18 @@
 }
 
 /* omap3pandora legacy devices */
-#define PANDORA_WIFI_IRQ_GPIO		21
-#define PANDORA_WIFI_NRESET_GPIO	23
 
 static struct platform_device pandora_backlight = {
 	.name	= "pandora-backlight",
 	.id	= -1,
 };
 
-static struct regulator_consumer_supply pandora_vmmc3_supply[] = {
-	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.2"),
-};
-
-static struct regulator_init_data pandora_vmmc3 = {
-	.constraints = {
-		.valid_ops_mask		= REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(pandora_vmmc3_supply),
-	.consumer_supplies	= pandora_vmmc3_supply,
-};
-
-static struct fixed_voltage_config pandora_vwlan = {
-	.supply_name		= "vwlan",
-	.microvolts		= 1800000, /* 1.8V */
-	.startup_delay		= 50000, /* 50ms */
-	.init_data		= &pandora_vmmc3,
-};
-
-static struct platform_device pandora_vwlan_device = {
-	.name		= "reg-fixed-voltage",
-	.id		= 1,
-	.dev = {
-		.platform_data = &pandora_vwlan,
-	},
-};
-
-static struct gpiod_lookup_table pandora_vwlan_gpiod_table = {
-	.dev_id = "reg-fixed-voltage.1",
-	.table = {
-		/*
-		 * As this is a low GPIO number it should be at the first
-		 * GPIO bank.
-		 */
-		GPIO_LOOKUP("gpio-0-31", PANDORA_WIFI_NRESET_GPIO,
-			    NULL, GPIO_ACTIVE_HIGH),
-		{ },
-	},
-};
-
-static void pandora_wl1251_init_card(struct mmc_card *card)
-{
-	/*
-	 * We have TI wl1251 attached to MMC3. Pass this information to
-	 * SDIO core because it can't be probed by normal methods.
-	 */
-	if (card->type == MMC_TYPE_SDIO || card->type == MMC_TYPE_SD_COMBO) {
-		card->quirks |= MMC_QUIRK_NONSTD_SDIO;
-		card->cccr.wide_bus = 1;
-		card->cis.vendor = 0x104c;
-		card->cis.device = 0x9066;
-		card->cis.blksize = 512;
-		card->cis.max_dtr = 24000000;
-		card->ocr = 0x80;
-	}
-}
-
-static struct omap2_hsmmc_info pandora_mmc3[] = {
-	{
-		.mmc		= 3,
-		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_POWER_OFF_CARD,
-		.init_card	= pandora_wl1251_init_card,
-	},
-	{}	/* Terminator */
-};
-
-static void __init pandora_wl1251_init(void)
-{
-	struct wl1251_platform_data pandora_wl1251_pdata;
-	int ret;
-
-	memset(&pandora_wl1251_pdata, 0, sizeof(pandora_wl1251_pdata));
-
-	pandora_wl1251_pdata.power_gpio = -1;
-
-	ret = gpio_request_one(PANDORA_WIFI_IRQ_GPIO, GPIOF_IN, "wl1251 irq");
-	if (ret < 0)
-		goto fail;
-
-	pandora_wl1251_pdata.irq = gpio_to_irq(PANDORA_WIFI_IRQ_GPIO);
-	if (pandora_wl1251_pdata.irq < 0)
-		goto fail_irq;
-
-	pandora_wl1251_pdata.use_eeprom = true;
-	ret = wl1251_set_platform_data(&pandora_wl1251_pdata);
-	if (ret < 0)
-		goto fail_irq;
-
-	return;
-
-fail_irq:
-	gpio_free(PANDORA_WIFI_IRQ_GPIO);
-fail:
-	pr_err("wl1251 board initialisation failed\n");
-}
-
 static void __init omap3_pandora_legacy_init(void)
 {
 	platform_device_register(&pandora_backlight);
-	gpiod_add_lookup_table(&pandora_vwlan_gpiod_table);
-	platform_device_register(&pandora_vwlan_device);
-	omap_hsmmc_init(pandora_mmc3);
-	omap_hsmmc_late_init(pandora_mmc3);
-	pandora_wl1251_init();
 }
 #endif /* CONFIG_ARCH_OMAP3 */
 
-#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5)
-static struct iommu_platform_data omap4_iommu_pdata = {
-	.reset_name = "mmu_cache",
-	.assert_reset = omap_device_assert_hardreset,
-	.deassert_reset = omap_device_deassert_hardreset,
-	.device_enable = omap_device_enable,
-	.device_idle = omap_device_idle,
-};
-#endif
-
 #if defined(CONFIG_SOC_AM33XX) || defined(CONFIG_SOC_AM43XX)
 static struct wkup_m3_platform_data wkup_m3_data = {
 	.reset_name = "wkup_m3",
@@ -451,6 +337,10 @@
 #endif
 
 #ifdef CONFIG_SOC_DRA7XX
+static struct iommu_platform_data dra7_ipu1_dsp_iommu_pdata = {
+	.set_pwrdm_constraint = omap_iommu_set_pwrdm_constraint,
+};
+
 static struct omap_hsmmc_platform_data dra7_hsmmc_data_mmc1;
 static struct omap_hsmmc_platform_data dra7_hsmmc_data_mmc2;
 static struct omap_hsmmc_platform_data dra7_hsmmc_data_mmc3;
@@ -472,10 +362,14 @@
 
 static struct clockdomain *ti_sysc_find_one_clockdomain(struct clk *clk)
 {
+	struct clk_hw *hw = __clk_get_hw(clk);
 	struct clockdomain *clkdm = NULL;
 	struct clk_hw_omap *hwclk;
 
-	hwclk = to_clk_hw_omap(__clk_get_hw(clk));
+	hwclk = to_clk_hw_omap(hw);
+	if (!omap2_clk_is_hw_omap(hw))
+		return NULL;
+
 	if (hwclk && hwclk->clkdm_name)
 		clkdm = clkdm_lookup(hwclk->clkdm_name);
 
@@ -638,6 +532,7 @@
 	OF_DEV_AUXDATA("ti,davinci_mdio", 0x5c030000, "davinci_mdio.0", NULL),
 	OF_DEV_AUXDATA("ti,am3517-emac", 0x5c000000, "davinci_emac.0",
 		       &am35xx_emac_pdata),
+	OF_DEV_AUXDATA("nokia,n900-rom-rng", 0, NULL, rx51_secure_rng_call),
 	/* McBSP modules with sidetone core */
 #if IS_ENABLED(CONFIG_SND_SOC_OMAP_MCBSP)
 	OF_DEV_AUXDATA("ti,omap3-mcbsp", 0x49022000, "49022000.mcbsp", &mcbsp_pdata),
@@ -653,10 +548,6 @@
 		       &wkup_m3_data),
 #endif
 #if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5)
-	OF_DEV_AUXDATA("ti,omap4-iommu", 0x4a066000, "4a066000.mmu",
-		       &omap4_iommu_pdata),
-	OF_DEV_AUXDATA("ti,omap4-iommu", 0x55082000, "55082000.mmu",
-		       &omap4_iommu_pdata),
 	OF_DEV_AUXDATA("ti,omap4-smartreflex-iva", 0x4a0db000,
 		       "4a0db000.smartreflex", &omap_sr_pdata[OMAP_SR_IVA]),
 	OF_DEV_AUXDATA("ti,omap4-smartreflex-core", 0x4a0dd000,
@@ -671,6 +562,12 @@
 		       &dra7_hsmmc_data_mmc2),
 	OF_DEV_AUXDATA("ti,dra7-hsmmc", 0x480ad000, "480ad000.mmc",
 		       &dra7_hsmmc_data_mmc3),
+	OF_DEV_AUXDATA("ti,dra7-dsp-iommu", 0x40d01000, "40d01000.mmu",
+		       &dra7_ipu1_dsp_iommu_pdata),
+	OF_DEV_AUXDATA("ti,dra7-dsp-iommu", 0x41501000, "41501000.mmu",
+		       &dra7_ipu1_dsp_iommu_pdata),
+	OF_DEV_AUXDATA("ti,dra7-iommu", 0x58882000, "58882000.mmu",
+		       &dra7_ipu1_dsp_iommu_pdata),
 #endif
 	/* Common auxdata */
 	OF_DEV_AUXDATA("ti,sysc", 0, NULL, &ti_sysc_pdata),
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-omap2/pm34xx.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-omap2/pm34xx.c
@@ -194,6 +194,7 @@
 	int per_next_state = PWRDM_POWER_ON;
 	int core_next_state = PWRDM_POWER_ON;
 	u32 sdrc_pwr = 0;
+	int error;
 
 	mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm);
 	switch (mpu_next_state) {
@@ -222,8 +223,11 @@
 	pwrdm_pre_transition(NULL);
 
 	/* PER */
-	if (per_next_state == PWRDM_POWER_OFF)
-		cpu_cluster_pm_enter();
+	if (per_next_state == PWRDM_POWER_OFF) {
+		error = cpu_cluster_pm_enter();
+		if (error)
+			return;
+	}
 
 	/* CORE */
 	if (core_next_state < PWRDM_POWER_ON) {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-omap2/powerdomain.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-omap2/powerdomain.c
@@ -174,7 +174,7 @@
 		break;
 	case PWRDM_STATE_PREV:
 		prev = pwrdm_read_prev_pwrst(pwrdm);
-		if (pwrdm->state != prev)
+		if (prev >= 0 && pwrdm->state != prev)
 			pwrdm->state_counter[prev]++;
 		if (prev == PWRDM_POWER_RET)
 			_update_logic_membank_counters(pwrdm);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-omap2/prm3xxx.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-omap2/prm3xxx.c
@@ -708,6 +708,7 @@
 	}
 
 	irq_num = of_irq_get(np, 0);
+	of_node_put(np);
 	if (irq_num == -EPROBE_DEFER)
 		return irq_num;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-omap2/sleep34xx.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-omap2/sleep34xx.S
@@ -72,7 +72,7 @@
 	stmfd	sp!, {lr}	@ save registers on stack
 	/* Setup so that we will disable and enable l2 */
 	mov	r1, #0x1
-	adrl	r3, l2dis_3630_offset	@ may be too distant for plain adr
+	adr	r3, l2dis_3630_offset
 	ldr	r2, [r3]		@ value for offset
 	str	r1, [r2, r3]		@ write to l2dis_3630
 	ldmfd	sp!, {pc}	@ restore regs and return
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-omap2/timer.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-omap2/timer.c
@@ -42,6 +42,7 @@
 #include <linux/platform_device.h>
 #include <linux/platform_data/dmtimer-omap.h>
 #include <linux/sched_clock.h>
+#include <linux/cpu.h>
 
 #include <asm/mach/time.h>
 
@@ -63,15 +64,28 @@
 
 /* Clockevent code */
 
-static struct omap_dm_timer clkev;
-static struct clock_event_device clockevent_gpt;
-
 /* Clockevent hwmod for am335x and am437x suspend */
 static struct omap_hwmod *clockevent_gpt_hwmod;
 
 /* Clockesource hwmod for am437x suspend */
 static struct omap_hwmod *clocksource_gpt_hwmod;
 
+struct dmtimer_clockevent {
+	struct clock_event_device dev;
+	struct omap_dm_timer timer;
+};
+
+static struct dmtimer_clockevent clockevent;
+
+static struct omap_dm_timer *to_dmtimer(struct clock_event_device *clockevent)
+{
+	struct dmtimer_clockevent *clkevt =
+		container_of(clockevent, struct dmtimer_clockevent, dev);
+	struct omap_dm_timer *timer = &clkevt->timer;
+
+	return timer;
+}
+
 #ifdef CONFIG_SOC_HAS_REALTIME_COUNTER
 static unsigned long arch_timer_freq;
 
@@ -83,24 +97,21 @@
 
 static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id)
 {
-	struct clock_event_device *evt = &clockevent_gpt;
-
-	__omap_dm_timer_write_status(&clkev, OMAP_TIMER_INT_OVERFLOW);
+	struct dmtimer_clockevent *clkevt = dev_id;
+	struct clock_event_device *evt = &clkevt->dev;
+	struct omap_dm_timer *timer = &clkevt->timer;
 
+	__omap_dm_timer_write_status(timer, OMAP_TIMER_INT_OVERFLOW);
 	evt->event_handler(evt);
 	return IRQ_HANDLED;
 }
 
-static struct irqaction omap2_gp_timer_irq = {
-	.name		= "gp_timer",
-	.flags		= IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= omap2_gp_timer_interrupt,
-};
-
 static int omap2_gp_timer_set_next_event(unsigned long cycles,
 					 struct clock_event_device *evt)
 {
-	__omap_dm_timer_load_start(&clkev, OMAP_TIMER_CTRL_ST,
+	struct omap_dm_timer *timer = to_dmtimer(evt);
+
+	__omap_dm_timer_load_start(timer, OMAP_TIMER_CTRL_ST,
 				   0xffffffff - cycles, OMAP_TIMER_POSTED);
 
 	return 0;
@@ -108,22 +119,26 @@
 
 static int omap2_gp_timer_shutdown(struct clock_event_device *evt)
 {
-	__omap_dm_timer_stop(&clkev, OMAP_TIMER_POSTED, clkev.rate);
+	struct omap_dm_timer *timer = to_dmtimer(evt);
+
+	__omap_dm_timer_stop(timer, OMAP_TIMER_POSTED, timer->rate);
+
 	return 0;
 }
 
 static int omap2_gp_timer_set_periodic(struct clock_event_device *evt)
 {
+	struct omap_dm_timer *timer = to_dmtimer(evt);
 	u32 period;
 
-	__omap_dm_timer_stop(&clkev, OMAP_TIMER_POSTED, clkev.rate);
+	__omap_dm_timer_stop(timer, OMAP_TIMER_POSTED, timer->rate);
 
-	period = clkev.rate / HZ;
+	period = timer->rate / HZ;
 	period -= 1;
 	/* Looks like we need to first set the load value separately */
-	__omap_dm_timer_write(&clkev, OMAP_TIMER_LOAD_REG, 0xffffffff - period,
+	__omap_dm_timer_write(timer, OMAP_TIMER_LOAD_REG, 0xffffffff - period,
 			      OMAP_TIMER_POSTED);
-	__omap_dm_timer_load_start(&clkev,
+	__omap_dm_timer_load_start(timer,
 				   OMAP_TIMER_CTRL_AR | OMAP_TIMER_CTRL_ST,
 				   0xffffffff - period, OMAP_TIMER_POSTED);
 	return 0;
@@ -137,26 +152,17 @@
 	omap_hwmod_idle(clockevent_gpt_hwmod);
 }
 
-static void omap_clkevt_unidle(struct clock_event_device *unused)
+static void omap_clkevt_unidle(struct clock_event_device *evt)
 {
+	struct omap_dm_timer *timer = to_dmtimer(evt);
+
 	if (!clockevent_gpt_hwmod)
 		return;
 
 	omap_hwmod_enable(clockevent_gpt_hwmod);
-	__omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);
+	__omap_dm_timer_int_enable(timer, OMAP_TIMER_INT_OVERFLOW);
 }
 
-static struct clock_event_device clockevent_gpt = {
-	.features		= CLOCK_EVT_FEAT_PERIODIC |
-				  CLOCK_EVT_FEAT_ONESHOT,
-	.rating			= 300,
-	.set_next_event		= omap2_gp_timer_set_next_event,
-	.set_state_shutdown	= omap2_gp_timer_shutdown,
-	.set_state_periodic	= omap2_gp_timer_set_periodic,
-	.set_state_oneshot	= omap2_gp_timer_shutdown,
-	.tick_resume		= omap2_gp_timer_shutdown,
-};
-
 static const struct of_device_id omap_timer_match[] __initconst = {
 	{ .compatible = "ti,omap2420-timer", },
 	{ .compatible = "ti,omap3430-timer", },
@@ -362,47 +368,104 @@
 }
 #endif
 
-static void __init omap2_gp_clockevent_init(int gptimer_id,
-						const char *fck_source,
-						const char *property)
+static void __init dmtimer_clkevt_init_common(struct dmtimer_clockevent *clkevt,
+					      int gptimer_id,
+					      const char *fck_source,
+					      unsigned int features,
+					      const struct cpumask *cpumask,
+					      const char *property,
+					      int rating, const char *name)
 {
+	struct omap_dm_timer *timer = &clkevt->timer;
 	int res;
 
-	clkev.id = gptimer_id;
-	clkev.errata = omap_dm_timer_get_errata();
+	timer->id = gptimer_id;
+	timer->errata = omap_dm_timer_get_errata();
+	clkevt->dev.features = features;
+	clkevt->dev.rating = rating;
+	clkevt->dev.set_next_event = omap2_gp_timer_set_next_event;
+	clkevt->dev.set_state_shutdown = omap2_gp_timer_shutdown;
+	clkevt->dev.set_state_periodic = omap2_gp_timer_set_periodic;
+	clkevt->dev.set_state_oneshot = omap2_gp_timer_shutdown;
+	clkevt->dev.tick_resume = omap2_gp_timer_shutdown;
 
 	/*
 	 * For clock-event timers we never read the timer counter and
 	 * so we are not impacted by errata i103 and i767. Therefore,
 	 * we can safely ignore this errata for clock-event timers.
 	 */
-	__omap_dm_timer_override_errata(&clkev, OMAP_TIMER_ERRATA_I103_I767);
+	__omap_dm_timer_override_errata(timer, OMAP_TIMER_ERRATA_I103_I767);
 
-	res = omap_dm_timer_init_one(&clkev, fck_source, property,
-				     &clockevent_gpt.name, OMAP_TIMER_POSTED);
+	res = omap_dm_timer_init_one(timer, fck_source, property,
+				     &clkevt->dev.name, OMAP_TIMER_POSTED);
 	BUG_ON(res);
 
-	omap2_gp_timer_irq.dev_id = &clkev;
-	setup_irq(clkev.irq, &omap2_gp_timer_irq);
+	clkevt->dev.cpumask = cpumask;
+	clkevt->dev.irq = omap_dm_timer_get_irq(timer);
 
-	__omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);
+	if (request_irq(clkevt->dev.irq, omap2_gp_timer_interrupt,
+			IRQF_TIMER | IRQF_IRQPOLL, name, clkevt))
+		pr_err("Failed to request irq %d (gp_timer)\n", clkevt->dev.irq);
 
-	clockevent_gpt.cpumask = cpu_possible_mask;
-	clockevent_gpt.irq = omap_dm_timer_get_irq(&clkev);
-	clockevents_config_and_register(&clockevent_gpt, clkev.rate,
-					3, /* Timer internal resynch latency */
-					0xffffffff);
+	__omap_dm_timer_int_enable(timer, OMAP_TIMER_INT_OVERFLOW);
 
 	if (soc_is_am33xx() || soc_is_am43xx()) {
-		clockevent_gpt.suspend = omap_clkevt_idle;
-		clockevent_gpt.resume = omap_clkevt_unidle;
+		clkevt->dev.suspend = omap_clkevt_idle;
+		clkevt->dev.resume = omap_clkevt_unidle;
 
 		clockevent_gpt_hwmod =
-			omap_hwmod_lookup(clockevent_gpt.name);
+			omap_hwmod_lookup(clkevt->dev.name);
 	}
 
-	pr_info("OMAP clockevent source: %s at %lu Hz\n", clockevent_gpt.name,
-		clkev.rate);
+	pr_info("OMAP clockevent source: %s at %lu Hz\n", clkevt->dev.name,
+		timer->rate);
+}
+
+static DEFINE_PER_CPU(struct dmtimer_clockevent, dmtimer_percpu_timer);
+
+static int omap_gptimer_starting_cpu(unsigned int cpu)
+{
+	struct dmtimer_clockevent *clkevt = per_cpu_ptr(&dmtimer_percpu_timer, cpu);
+	struct clock_event_device *dev = &clkevt->dev;
+	struct omap_dm_timer *timer = &clkevt->timer;
+
+	clockevents_config_and_register(dev, timer->rate, 3, ULONG_MAX);
+	irq_force_affinity(dev->irq, cpumask_of(cpu));
+
+	return 0;
+}
+
+static int __init dmtimer_percpu_quirk_init(void)
+{
+	struct dmtimer_clockevent *clkevt;
+	struct clock_event_device *dev;
+	struct device_node *arm_timer;
+	struct omap_dm_timer *timer;
+	int cpu = 0;
+
+	arm_timer = of_find_compatible_node(NULL, NULL, "arm,armv7-timer");
+	if (of_device_is_available(arm_timer)) {
+		pr_warn_once("ARM architected timer wrap issue i940 detected\n");
+		return 0;
+	}
+
+	for_each_possible_cpu(cpu) {
+		clkevt = per_cpu_ptr(&dmtimer_percpu_timer, cpu);
+		dev = &clkevt->dev;
+		timer = &clkevt->timer;
+
+		dmtimer_clkevt_init_common(clkevt, 0, "timer_sys_ck",
+					   CLOCK_EVT_FEAT_ONESHOT,
+					   cpumask_of(cpu),
+					   "assigned-clock-parents",
+					   500, "percpu timer");
+	}
+
+	cpuhp_setup_state(CPUHP_AP_OMAP_DM_TIMER_STARTING,
+			  "clockevents/omap/gptimer:starting",
+			  omap_gptimer_starting_cpu, NULL);
+
+	return 0;
 }
 
 /* Clocksource code */
@@ -542,7 +605,15 @@
 {
 	omap_clk_init();
 	omap_dmtimer_init();
-	omap2_gp_clockevent_init(clkev_nr, clkev_src, clkev_prop);
+	dmtimer_clkevt_init_common(&clockevent, clkev_nr, clkev_src,
+				   CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+				   cpu_possible_mask, clkev_prop, 300, "clockevent");
+	clockevents_config_and_register(&clockevent.dev, clockevent.timer.rate,
+					3, /* Timer internal resynch latency */
+					0xffffffff);
+
+	if (soc_is_dra7xx())
+		dmtimer_percpu_quirk_init();
 
 	/* Enable the use of clocksource="gp_timer" kernel parameter */
 	if (use_gptimer_clksrc || gptimer)
@@ -571,7 +642,7 @@
 #endif /* CONFIG_ARCH_OMAP3 */
 
 #if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_AM33XX) || \
-	defined(CONFIG_SOC_AM43XX)
+	defined(CONFIG_SOC_AM43XX) || defined(CONFIG_SOC_DRA7XX)
 void __init omap3_gptimer_timer_init(void)
 {
 	__omap_sync32k_timer_init(2, "timer_sys_ck", NULL,
@@ -629,6 +700,7 @@
 	}
 
 	rate = clk_get_rate(sys_clk);
+	clk_put(sys_clk);
 
 	if (soc_is_dra7xx()) {
 		/*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-orion5x/board-dt.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-orion5x/board-dt.c
@@ -63,6 +63,9 @@
 	if (of_machine_is_compatible("maxtor,shared-storage-2"))
 		mss2_init();
 
+	if (of_machine_is_compatible("lacie,d2-network"))
+		d2net_init();
+
 	of_platform_default_populate(NULL, orion5x_auxdata_lookup, NULL);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-orion5x/common.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-orion5x/common.h
@@ -75,6 +75,12 @@
 static inline void mss2_init(void) {}
 #endif
 
+#ifdef CONFIG_MACH_D2NET_DT
+void d2net_init(void);
+#else
+static inline void d2net_init(void) {}
+#endif
+
 /*****************************************************************************
  * Helpers to access Orion registers
  ****************************************************************************/
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-pxa/cm-x300.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-pxa/cm-x300.c
@@ -355,13 +355,13 @@
 static struct gpiod_lookup_table cm_x300_spi_gpiod_table = {
 	.dev_id         = "spi_gpio",
 	.table          = {
-		GPIO_LOOKUP("gpio-pxa", GPIO_LCD_SCL,
+		GPIO_LOOKUP("pca9555.1", GPIO_LCD_SCL - GPIO_LCD_BASE,
 			    "sck", GPIO_ACTIVE_HIGH),
-		GPIO_LOOKUP("gpio-pxa", GPIO_LCD_DIN,
+		GPIO_LOOKUP("pca9555.1", GPIO_LCD_DIN - GPIO_LCD_BASE,
 			    "mosi", GPIO_ACTIVE_HIGH),
-		GPIO_LOOKUP("gpio-pxa", GPIO_LCD_DOUT,
+		GPIO_LOOKUP("pca9555.1", GPIO_LCD_DOUT - GPIO_LCD_BASE,
 			    "miso", GPIO_ACTIVE_HIGH),
-		GPIO_LOOKUP("gpio-pxa", GPIO_LCD_CS,
+		GPIO_LOOKUP("pca9555.1", GPIO_LCD_CS - GPIO_LCD_BASE,
 			    "cs", GPIO_ACTIVE_HIGH),
 		{ },
 	},
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-pxa/magician.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-pxa/magician.c
@@ -675,7 +675,7 @@
 static struct gpiod_lookup_table bq24022_gpiod_table = {
 	.dev_id = "gpio-regulator",
 	.table = {
-		GPIO_LOOKUP("gpio-pxa", EGPIO_MAGICIAN_BQ24022_ISET2,
+		GPIO_LOOKUP("htc-egpio-0", EGPIO_MAGICIAN_BQ24022_ISET2 - MAGICIAN_EGPIO_BASE,
 			    NULL, GPIO_ACTIVE_HIGH),
 		GPIO_LOOKUP("gpio-pxa", GPIO30_MAGICIAN_BQ24022_nCHARGE_EN,
 			    "enable", GPIO_ACTIVE_LOW),
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-pxa/sharpsl_pm.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-pxa/sharpsl_pm.c
@@ -220,8 +220,6 @@
 {
 	schedule_delayed_work(&sharpsl_bat, msecs_to_jiffies(125));
 }
-EXPORT_SYMBOL(sharpsl_battery_kick);
-
 
 static void sharpsl_battery_thread(struct work_struct *private_)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-pxa/spitz.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-pxa/spitz.c
@@ -9,7 +9,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h>	/* symbol_get ; symbol_put */
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/gpio_keys.h>
@@ -514,17 +513,6 @@
 	.gpio_cs		= SPITZ_GPIO_ADS7846_CS,
 };
 
-static void spitz_bl_kick_battery(void)
-{
-	void (*kick_batt)(void);
-
-	kick_batt = symbol_get(sharpsl_battery_kick);
-	if (kick_batt) {
-		kick_batt();
-		symbol_put(sharpsl_battery_kick);
-	}
-}
-
 static struct corgi_lcd_platform_data spitz_lcdcon_info = {
 	.init_mode		= CORGI_LCD_MODE_VGA,
 	.max_intensity		= 0x2f,
@@ -532,7 +520,7 @@
 	.limit_mask		= 0x0b,
 	.gpio_backlight_cont	= SPITZ_GPIO_BACKLIGHT_CONT,
 	.gpio_backlight_on	= SPITZ_GPIO_BACKLIGHT_ON,
-	.kick_battery		= spitz_bl_kick_battery,
+	.kick_battery		= sharpsl_battery_kick,
 };
 
 static struct pxa2xx_spi_chip spitz_lcdcon_chip = {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-pxa/tosa.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-pxa/tosa.c
@@ -295,9 +295,9 @@
 	.table = {
 		GPIO_LOOKUP("gpio-pxa", TOSA_GPIO_nSD_DETECT,
 			    "cd", GPIO_ACTIVE_LOW),
-		GPIO_LOOKUP("gpio-pxa", TOSA_GPIO_SD_WP,
+		GPIO_LOOKUP("sharp-scoop.0", TOSA_GPIO_SD_WP - TOSA_SCOOP_GPIO_BASE,
 			    "wp", GPIO_ACTIVE_LOW),
-		GPIO_LOOKUP("gpio-pxa", TOSA_GPIO_PWR_ON,
+		GPIO_LOOKUP("sharp-scoop.0", TOSA_GPIO_PWR_ON - TOSA_SCOOP_GPIO_BASE,
 			    "power", GPIO_ACTIVE_HIGH),
 		{ },
 	},
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-realview/platsmp-dt.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-realview/platsmp-dt.c
@@ -66,6 +66,7 @@
 		return;
 	}
 	map = syscon_node_to_regmap(np);
+	of_node_put(np);
 	if (IS_ERR(map)) {
 		pr_err("PLATSMP: No syscon regmap\n");
 		return;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-s3c24xx/mach-at2440evb.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-s3c24xx/mach-at2440evb.c
@@ -143,7 +143,7 @@
 	.dev_id = "s3c2410-sdi",
 	.table = {
 		/* Card detect S3C2410_GPG(10) */
-		GPIO_LOOKUP("GPG", 10, "cd", GPIO_ACTIVE_LOW),
+		GPIO_LOOKUP("GPIOG", 10, "cd", GPIO_ACTIVE_LOW),
 		{ },
 	},
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-s3c24xx/mach-h1940.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-s3c24xx/mach-h1940.c
@@ -468,9 +468,9 @@
 	.dev_id = "s3c2410-sdi",
 	.table = {
 		/* Card detect S3C2410_GPF(5) */
-		GPIO_LOOKUP("GPF", 5, "cd", GPIO_ACTIVE_LOW),
+		GPIO_LOOKUP("GPIOF", 5, "cd", GPIO_ACTIVE_LOW),
 		/* Write protect S3C2410_GPH(8) */
-		GPIO_LOOKUP("GPH", 8, "wp", GPIO_ACTIVE_LOW),
+		GPIO_LOOKUP("GPIOH", 8, "wp", GPIO_ACTIVE_LOW),
 		{ },
 	},
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-s3c24xx/mach-jive.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-s3c24xx/mach-jive.c
@@ -237,11 +237,11 @@
 	unsigned long set;
 
 	if (options == NULL || options[0] == '\0')
-		return 0;
+		return 1;
 
 	if (kstrtoul(options, 10, &set)) {
 		printk(KERN_ERR "failed to parse mtdset=%s\n", options);
-		return 0;
+		return 1;
 	}
 
 	switch (set) {
@@ -256,7 +256,7 @@
 		       "using default.", set);
 	}
 
-	return 0;
+	return 1;
 }
 
 /* parse the mtdset= option given to the kernel command line */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-s3c24xx/mach-mini2440.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-s3c24xx/mach-mini2440.c
@@ -244,9 +244,9 @@
 	.dev_id = "s3c2410-sdi",
 	.table = {
 		/* Card detect S3C2410_GPG(8) */
-		GPIO_LOOKUP("GPG", 8, "cd", GPIO_ACTIVE_LOW),
+		GPIO_LOOKUP("GPIOG", 8, "cd", GPIO_ACTIVE_LOW),
 		/* Write protect S3C2410_GPH(8) */
-		GPIO_LOOKUP("GPH", 8, "wp", GPIO_ACTIVE_HIGH),
+		GPIO_LOOKUP("GPIOH", 8, "wp", GPIO_ACTIVE_HIGH),
 		{ },
 	},
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-s3c24xx/mach-n30.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-s3c24xx/mach-n30.c
@@ -359,9 +359,9 @@
 	.dev_id = "s3c2410-sdi",
 	.table = {
 		/* Card detect S3C2410_GPF(1) */
-		GPIO_LOOKUP("GPF", 1, "cd", GPIO_ACTIVE_LOW),
+		GPIO_LOOKUP("GPIOF", 1, "cd", GPIO_ACTIVE_LOW),
 		/* Write protect S3C2410_GPG(10) */
-		GPIO_LOOKUP("GPG", 10, "wp", GPIO_ACTIVE_LOW),
+		GPIO_LOOKUP("GPIOG", 10, "wp", GPIO_ACTIVE_LOW),
 		{ },
 	},
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-s3c24xx/mach-rx1950.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-s3c24xx/mach-rx1950.c
@@ -567,9 +567,9 @@
 	.dev_id = "s3c2410-sdi",
 	.table = {
 		/* Card detect S3C2410_GPF(5) */
-		GPIO_LOOKUP("GPF", 5, "cd", GPIO_ACTIVE_LOW),
+		GPIO_LOOKUP("GPIOF", 5, "cd", GPIO_ACTIVE_LOW),
 		/* Write protect S3C2410_GPH(8) */
-		GPIO_LOOKUP("GPH", 8, "wp", GPIO_ACTIVE_LOW),
+		GPIO_LOOKUP("GPIOH", 8, "wp", GPIO_ACTIVE_LOW),
 		{ },
 	},
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-s5pv210/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-s5pv210/Kconfig
@@ -8,7 +8,6 @@
 config ARCH_S5PV210
 	bool "Samsung S5PV210/S5PC110"
 	depends on ARCH_MULTI_V7
-	select ARCH_HAS_HOLES_MEMORYMODEL
 	select ARM_VIC
 	select CLKSRC_SAMSUNG_PWM
 	select COMMON_CLK_SAMSUNG
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-sa1100/assabet.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-sa1100/assabet.c
@@ -653,7 +653,7 @@
  */
 static void __init get_assabet_scr(void)
 {
-	unsigned long uninitialized_var(scr), i;
+	unsigned long scr, i;
 
 	GPDR |= 0x3fc;			/* Configure GPIO 9:2 as outputs */
 	GPSR = 0x3fc;			/* Write 0xFF to GPIO 9:2 */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-sa1100/jornada720_ssp.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-sa1100/jornada720_ssp.c
@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0-only
-/**
+/*
  *  arch/arm/mac-sa1100/jornada720_ssp.c
  *
  *  Copyright (C) 2006/2007 Kristoffer Ericson <Kristoffer.Ericson@gmail.com>
@@ -26,6 +26,7 @@
 
 /**
  * jornada_ssp_reverse - reverses input byte
+ * @byte: input byte to reverse
  *
  * we need to reverse all data we receive from the mcu due to its physical location
  * returns : 01110111 -> 11101110
@@ -46,6 +47,7 @@
 
 /**
  * jornada_ssp_byte - waits for ready ssp bus and sends byte
+ * @byte: input byte to transmit
  *
  * waits for fifo buffer to clear and then transmits, if it doesn't then we will
  * timeout after <timeout> rounds. Needs mcu running before its called.
@@ -77,6 +79,7 @@
 
 /**
  * jornada_ssp_inout - decide if input is command or trading byte
+ * @byte: input byte to send (may be %TXDUMMY)
  *
  * returns : (jornada_ssp_byte(byte)) on success
  *         : %-ETIMEDOUT on timeout failure
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-shmobile/headsmp.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-shmobile/headsmp.S
@@ -136,6 +136,7 @@
 	.long	shmobile_smp_arg - 1b
 
 	.bss
+	.align	2
 	.globl	shmobile_smp_mpidr
 shmobile_smp_mpidr:
 	.space	NR_CPUS * 4
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c
@@ -125,6 +125,7 @@
 
 	list_for_each_entry_safe(pos, tmp, &quirk_list, list) {
 		list_del(&pos->list);
+		of_node_put(pos->np);
 		kfree(pos);
 	}
 
@@ -154,8 +155,10 @@
 		return -ENODEV;
 
 	for_each_matching_node_and_match(np, rcar_gen2_quirk_match, &id) {
-		if (!of_device_is_available(np))
+		if (!of_device_is_available(np)) {
+			of_node_put(np);
 			break;
+		}
 
 		ret = of_property_read_u32(np, "reg", &addr);
 		if (ret)	/* Skip invalid entry and continue */
@@ -164,6 +167,7 @@
 		quirk = kzalloc(sizeof(*quirk), GFP_KERNEL);
 		if (!quirk) {
 			ret = -ENOMEM;
+			of_node_put(np);
 			goto err_mem;
 		}
 
@@ -171,11 +175,12 @@
 		memcpy(&quirk->i2c_msg, id->data, sizeof(quirk->i2c_msg));
 
 		quirk->id = id;
-		quirk->np = np;
+		quirk->np = of_node_get(np);
 		quirk->i2c_msg.addr = addr;
 
 		ret = of_irq_parse_one(np, 0, argsa);
 		if (ret) {	/* Skip invalid entry and continue */
+			of_node_put(np);
 			kfree(quirk);
 			continue;
 		}
@@ -222,6 +227,7 @@
 err_mem:
 	list_for_each_entry_safe(pos, tmp, &quirk_list, list) {
 		list_del(&pos->list);
+		of_node_put(pos->np);
 		kfree(pos);
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-socfpga/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-socfpga/Kconfig
@@ -2,6 +2,7 @@
 menuconfig ARCH_SOCFPGA
 	bool "Altera SOCFPGA family"
 	depends on ARCH_MULTI_V7
+	select ARCH_HAS_RESET_CONTROLLER
 	select ARCH_SUPPORTS_BIG_ENDIAN
 	select ARM_AMBA
 	select ARM_GIC
@@ -19,6 +20,7 @@
 	select PL310_ERRATA_727915
 	select PL310_ERRATA_753970 if PL310
 	select PL310_ERRATA_769419
+	select RESET_CONTROLLER
 
 if ARCH_SOCFPGA
 config SOCFPGA_SUSPEND
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-socfpga/core.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-socfpga/core.h
@@ -33,7 +33,7 @@
 u32 socfpga_sdram_self_refresh(u32 sdr_base);
 extern unsigned int socfpga_sdram_self_refresh_sz;
 
-extern char secondary_trampoline, secondary_trampoline_end;
+extern char secondary_trampoline[], secondary_trampoline_end[];
 
 extern unsigned long socfpga_cpu1start_addr;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-socfpga/platsmp.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-socfpga/platsmp.c
@@ -20,14 +20,14 @@
 
 static int socfpga_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
-	int trampoline_size = &secondary_trampoline_end - &secondary_trampoline;
+	int trampoline_size = secondary_trampoline_end - secondary_trampoline;
 
 	if (socfpga_cpu1start_addr) {
 		/* This will put CPU #1 into reset. */
 		writel(RSTMGR_MPUMODRST_CPU1,
 		       rst_manager_base_addr + SOCFPGA_RSTMGR_MODMPURST);
 
-		memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size);
+		memcpy(phys_to_virt(0), secondary_trampoline, trampoline_size);
 
 		writel(__pa_symbol(secondary_startup),
 		       sys_manager_base_addr + (socfpga_cpu1start_addr & 0x000000ff));
@@ -45,12 +45,12 @@
 
 static int socfpga_a10_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
-	int trampoline_size = &secondary_trampoline_end - &secondary_trampoline;
+	int trampoline_size = secondary_trampoline_end - secondary_trampoline;
 
 	if (socfpga_cpu1start_addr) {
 		writel(RSTMGR_MPUMODRST_CPU1, rst_manager_base_addr +
 		       SOCFPGA_A10_RSTMGR_MODMPURST);
-		memcpy(phys_to_virt(0), &secondary_trampoline, trampoline_size);
+		memcpy(phys_to_virt(0), secondary_trampoline, trampoline_size);
 
 		writel(__pa_symbol(secondary_startup),
 		       sys_manager_base_addr + (socfpga_cpu1start_addr & 0x00000fff));
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-socfpga/pm.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-socfpga/pm.c
@@ -49,14 +49,14 @@
 	if (!ocram_pool) {
 		pr_warn("%s: ocram pool unavailable!\n", __func__);
 		ret = -ENODEV;
-		goto put_node;
+		goto put_device;
 	}
 
 	ocram_base = gen_pool_alloc(ocram_pool, socfpga_sdram_self_refresh_sz);
 	if (!ocram_base) {
 		pr_warn("%s: unable to alloc ocram!\n", __func__);
 		ret = -ENOMEM;
-		goto put_node;
+		goto put_device;
 	}
 
 	ocram_pbase = gen_pool_virt_to_phys(ocram_pool, ocram_base);
@@ -67,7 +67,7 @@
 	if (!suspend_ocram_base) {
 		pr_warn("%s: __arm_ioremap_exec failed!\n", __func__);
 		ret = -ENOMEM;
-		goto put_node;
+		goto put_device;
 	}
 
 	/* Copy the code that puts DDR in self refresh to ocram */
@@ -81,6 +81,8 @@
 	if (!socfpga_sdram_self_refresh_in_ocram)
 		ret = -EFAULT;
 
+put_device:
+	put_device(&pdev->dev);
 put_node:
 	of_node_put(np);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-spear/time.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-spear/time.c
@@ -93,7 +93,7 @@
 		200, 16, clocksource_mmio_readw_up);
 }
 
-static inline void timer_shutdown(struct clock_event_device *evt)
+static inline void spear_timer_shutdown(struct clock_event_device *evt)
 {
 	u16 val = readw(gpt_base + CR(CLKEVT));
 
@@ -104,7 +104,7 @@
 
 static int spear_shutdown(struct clock_event_device *evt)
 {
-	timer_shutdown(evt);
+	spear_timer_shutdown(evt);
 
 	return 0;
 }
@@ -114,7 +114,7 @@
 	u16 val;
 
 	/* stop the timer */
-	timer_shutdown(evt);
+	spear_timer_shutdown(evt);
 
 	val = readw(gpt_base + CR(CLKEVT));
 	val |= CTRL_ONE_SHOT;
@@ -129,7 +129,7 @@
 	u16 val;
 
 	/* stop the timer */
-	timer_shutdown(evt);
+	spear_timer_shutdown(evt);
 
 	period = clk_get_rate(gpt_clk) / HZ;
 	period >>= CTRL_PRESCALER16;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-sunxi/mc_smp.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-sunxi/mc_smp.c
@@ -804,16 +804,16 @@
 	for (i = 0; i < ARRAY_SIZE(sunxi_mc_smp_data); i++) {
 		ret = of_property_match_string(node, "enable-method",
 					       sunxi_mc_smp_data[i].enable_method);
-		if (!ret)
+		if (ret >= 0)
 			break;
 	}
 
-	is_a83t = sunxi_mc_smp_data[i].is_a83t;
-
 	of_node_put(node);
-	if (ret)
+	if (ret < 0)
 		return -ENODEV;
 
+	is_a83t = sunxi_mc_smp_data[i].is_a83t;
+
 	if (!sunxi_mc_smp_cpu_table_init())
 		return -EINVAL;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-sunxi/sunxi.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-sunxi/sunxi.c
@@ -66,6 +66,7 @@
 	"allwinner,sun8i-h2-plus",
 	"allwinner,sun8i-h3",
 	"allwinner,sun8i-r40",
+	"allwinner,sun8i-v3",
 	"allwinner,sun8i-v3s",
 	NULL,
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-tango/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-tango/Kconfig
@@ -3,7 +3,6 @@
 	bool "Sigma Designs Tango4 (SMP87xx)"
 	depends on ARCH_MULTI_V7
 	# Cortex-A9 MPCore r3p0, PL310 r3p2
-	select ARCH_HAS_HOLES_MEMORYMODEL
 	select ARM_ERRATA_754322
 	select ARM_ERRATA_764369 if SMP
 	select ARM_ERRATA_775420
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-tegra/reset-handler.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-tegra/reset-handler.S
@@ -44,16 +44,16 @@
 	cmp	r6, #TEGRA20
 	beq	1f				@ Yes
 	/* Clear the flow controller flags for this CPU. */
-	cpu_to_csr_reg r1, r0
+	cpu_to_csr_reg r3, r0
 	mov32	r2, TEGRA_FLOW_CTRL_BASE
-	ldr	r1, [r2, r1]
+	ldr	r1, [r2, r3]
 	/* Clear event & intr flag */
 	orr	r1, r1, \
 		#FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
 	movw	r0, #0x3FFD	@ enable, cluster_switch, immed, bitmaps
 				@ & ext flags for CPU power mgnt
 	bic	r1, r1, r0
-	str	r1, [r2]
+	str	r1, [r2, r3]
 1:
 
 	mov32	r9, 0xc09
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-tegra/sleep-tegra30.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-tegra/sleep-tegra30.S
@@ -370,6 +370,14 @@
 	pll_locked r1, r0, CLK_RESET_PLLC_BASE
 	pll_locked r1, r0, CLK_RESET_PLLX_BASE
 
+	tegra_get_soc_id TEGRA_APB_MISC_BASE, r1
+	cmp	r1, #TEGRA30
+	beq	1f
+	ldr	r1, [r0, #CLK_RESET_PLLP_BASE]
+	bic	r1, r1, #(1<<31)	@ disable PllP bypass
+	str	r1, [r0, #CLK_RESET_PLLP_BASE]
+1:
+
 	mov32	r7, TEGRA_TMRUS_BASE
 	ldr	r1, [r7]
 	add	r1, r1, #LOCK_DELAY
@@ -630,7 +638,10 @@
 	str	r0, [r4, #PMC_PLLP_WB0_OVERRIDE]
 
 	/* disable PLLP, PLLA, PLLC and PLLX */
+	tegra_get_soc_id TEGRA_APB_MISC_BASE, r1
+	cmp	r1, #TEGRA30
 	ldr	r0, [r5, #CLK_RESET_PLLP_BASE]
+	orrne	r0, r0, #(1 << 31)	@ enable PllP bypass on fast cluster
 	bic	r0, r0, #(1 << 30)
 	str	r0, [r5, #CLK_RESET_PLLP_BASE]
 	ldr	r0, [r5, #CLK_RESET_PLLA_BASE]
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-tegra/tegra.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-tegra/tegra.c
@@ -106,8 +106,8 @@
 };
 
 DT_MACHINE_START(TEGRA_DT, "NVIDIA Tegra SoC (Flattened Device Tree)")
-	.l2c_aux_val	= 0x3c400001,
-	.l2c_aux_mask	= 0xc20fc3fe,
+	.l2c_aux_val	= 0x3c400000,
+	.l2c_aux_mask	= 0xc20fc3ff,
 	.smp		= smp_ops(tegra_smp_ops),
 	.map_io		= tegra_map_common_io,
 	.init_early	= tegra_init_early,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-vexpress/dcscb.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-vexpress/dcscb.c
@@ -143,6 +143,7 @@
 	if (!node)
 		return -ENODEV;
 	dcscb_base = of_iomap(node, 0);
+	of_node_put(node);
 	if (!dcscb_base)
 		return -EADDRNOTAVAIL;
 	cfg = readl_relaxed(dcscb_base + DCS_CFG_R);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-vexpress/spc.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-vexpress/spc.c
@@ -551,8 +551,9 @@
 
 static int __init ve_spc_clk_init(void)
 {
-	int cpu;
+	int cpu, cluster;
 	struct clk *clk;
+	bool init_opp_table[MAX_CLUSTERS] = { false };
 
 	if (!info)
 		return 0; /* Continue only if SPC is initialised */
@@ -578,8 +579,17 @@
 			continue;
 		}
 
+		cluster = topology_physical_package_id(cpu_dev->id);
+		if (cluster < 0 || init_opp_table[cluster])
+			continue;
+
 		if (ve_init_opp_table(cpu_dev))
 			pr_warn("failed to initialise cpu%d opp table\n", cpu);
+		else if (dev_pm_opp_set_sharing_cpus(cpu_dev,
+			 topology_core_cpumask(cpu_dev->id)))
+			pr_warn("failed to mark OPPs shared for cpu%d\n", cpu);
+		else
+			init_opp_table[cluster] = true;
 	}
 
 	platform_device_register_simple("vexpress-spc-cpufreq", -1, NULL, 0);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-zynq/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-zynq/Kconfig
@@ -17,3 +17,19 @@
 	select SOC_BUS
 	help
 	  Support for Xilinx Zynq ARM Cortex A9 Platform
+
+if ARCH_ZYNQ
+
+menu "Xilinx Specific Options"
+
+config XILINX_PREFETCH
+	bool "Cache Prefetch"
+	default y
+	help
+	  This option turns on L1 & L2 cache prefetching to get the best performance
+	  in many cases. This may not always be the best performance depending on
+	  the usage.
+
+endmenu
+
+endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-zynq/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-zynq/Makefile
@@ -4,5 +4,10 @@
 #
 
 # Common support
-obj-y				:= common.o slcr.o pm.o
+obj-y				:= common.o efuse.o slcr.o zynq_ocm.o pm.o
+
 obj-$(CONFIG_SMP)		+= headsmp.o platsmp.o
+ORIG_AFLAGS := $(KBUILD_AFLAGS)
+KBUILD_AFLAGS = $(subst -march=armv6k,,$(ORIG_AFLAGS))
+AFLAGS_suspend.o 		+=-Wa,-march=armv7-a -mcpu=cortex-a9
+obj-$(CONFIG_SUSPEND)		+= suspend.o
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-zynq/common.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-zynq/common.c
@@ -77,6 +77,7 @@
 	}
 
 	zynq_devcfg_base = of_iomap(np, 0);
+	of_node_put(np);
 	if (!zynq_devcfg_base) {
 		pr_err("%s: Unable to map I/O memory\n", __func__);
 		return -1;
@@ -95,6 +96,7 @@
 {
 	zynq_core_pm_init();
 	zynq_pm_late_init();
+	zynq_prefetch_init();
 }
 
 /**
@@ -175,6 +177,7 @@
 
 static void __init zynq_irq_init(void)
 {
+	zynq_early_efuse_init();
 	zynq_early_slcr_init();
 	irqchip_init();
 }
@@ -186,8 +189,13 @@
 
 DT_MACHINE_START(XILINX_EP107, "Xilinx Zynq Platform")
 	/* 64KB way size, 8-way associativity, parity disabled */
-	.l2c_aux_val    = 0x00400000,
+#ifdef CONFIG_XILINX_PREFETCH
+	.l2c_aux_val	= 0x30400000,
+	.l2c_aux_mask	= 0xcfbfffff,
+#else
+	.l2c_aux_val	= 0x00400000,
 	.l2c_aux_mask	= 0xffbfffff,
+#endif
 	.smp		= smp_ops(zynq_smp_ops),
 	.map_io		= zynq_map_io,
 	.init_irq	= zynq_irq_init,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-zynq/common.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-zynq/common.h
@@ -15,8 +15,12 @@
 extern void zynq_slcr_cpu_start(int cpu);
 extern bool zynq_slcr_cpu_state_read(int cpu);
 extern void zynq_slcr_cpu_state_write(int cpu, bool die);
+extern u32 zynq_slcr_get_ocm_config(void);
 extern u32 zynq_slcr_get_device_id(void);
 
+extern bool zynq_efuse_cpu_state(int cpu);
+extern int zynq_early_efuse_init(void);
+
 #ifdef CONFIG_SMP
 extern char zynq_secondary_trampoline;
 extern char zynq_secondary_trampoline_jump;
@@ -25,9 +29,31 @@
 extern const struct smp_operations zynq_smp_ops;
 #endif
 
+extern void zynq_slcr_init_preload_fpga(void);
+extern void zynq_slcr_init_postload_fpga(void);
+
+extern void __iomem *zynq_slcr_base;
 extern void __iomem *zynq_scu_base;
 
 void zynq_pm_late_init(void);
+extern unsigned int zynq_sys_suspend_sz;
+int zynq_sys_suspend(void __iomem *ddrc_base, void __iomem *slcr_base);
+
+static inline void zynq_prefetch_init(void)
+{
+	/*
+	 * Enable prefetching in aux control register. L2 prefetch must
+	 * only be enabled if the slave supports it (PL310 does)
+	 */
+	asm volatile ("mrc   p15, 0, r1, c1, c0, 1\n"
+#ifdef CONFIG_XILINX_PREFETCH
+		      "orr   r1, r1, #6\n"
+#else
+		      "bic   r1, r1, #6\n"
+#endif
+		      "mcr   p15, 0, r1, c1, c0, 1\n"
+		      : : : "r1");
+}
 
 static inline void zynq_core_pm_init(void)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-zynq/efuse.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-zynq/efuse.c
@@ -0,0 +1,78 @@
+/*
+ * Xilinx EFUSE driver
+ *
+ * Copyright (c) 2016 Xilinx Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include "common.h"
+
+#define EFUSE_STATUS_OFFSET	0x10
+
+/* 0 means cpu1 is working, 1 means cpu1 is broken */
+#define EFUSE_STATUS_CPU_BIT	BIT(7)
+
+void __iomem *zynq_efuse_base;
+
+/**
+ * zynq_efuse_cpu_state - Read/write cpu state
+ * @cpu:	cpu number
+ *
+ * Return: true if cpu is running, false if cpu is broken
+ */
+bool zynq_efuse_cpu_state(int cpu)
+{
+	u32 state;
+
+	if (!cpu)
+		return true;
+
+	if (!zynq_efuse_base)
+		return true;
+
+	state = readl(zynq_efuse_base + EFUSE_STATUS_OFFSET);
+	state &= EFUSE_STATUS_CPU_BIT;
+
+	if (!state)
+		return true;
+
+	return false;
+}
+
+/**
+ * zynq_early_efuse_init - Early efuse init function
+ *
+ * Return:	0 on success, negative errno otherwise.
+ *
+ * Called very early during boot from platform code.
+ */
+int __init zynq_early_efuse_init(void)
+{
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "xlnx,zynq-efuse");
+	if (!np) {
+		pr_err("%s: no efuse node found\n", __func__);
+		return -1;
+	}
+
+	zynq_efuse_base = of_iomap(np, 0);
+	if (!zynq_efuse_base) {
+		pr_err("%s: Unable to map I/O memory\n", __func__);
+		return -1;
+	}
+
+	np->data = (__force void *)zynq_efuse_base;
+
+	pr_info("%s mapped to %p\n", np->name, zynq_efuse_base);
+
+	of_node_put(np);
+
+	return 0;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-zynq/platsmp.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-zynq/platsmp.c
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
 #include <asm/smp_scu.h>
 #include <linux/irqchip/arm-gic.h>
 #include "common.h"
@@ -30,6 +31,7 @@
 {
 	u32 trampoline_code_size = &zynq_secondary_trampoline_end -
 						&zynq_secondary_trampoline;
+	u32 phy_cpuid = cpu_logical_map(cpu);
 
 	/* MS: Expectation that SLCR are directly map and accessible */
 	/* Not possible to jump to non aligned address */
@@ -39,7 +41,7 @@
 		u32 trampoline_size = &zynq_secondary_trampoline_jump -
 						&zynq_secondary_trampoline;
 
-		zynq_slcr_cpu_stop(cpu);
+		zynq_slcr_cpu_stop(phy_cpuid);
 		if (address) {
 			if (__pa(PAGE_OFFSET)) {
 				zero = ioremap(0, trampoline_code_size);
@@ -68,7 +70,7 @@
 			if (__pa(PAGE_OFFSET))
 				iounmap(zero);
 		}
-		zynq_slcr_cpu_start(cpu);
+		zynq_slcr_cpu_start(phy_cpuid);
 
 		return 0;
 	}
@@ -81,6 +83,9 @@
 
 static int zynq_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
+	if (!zynq_efuse_cpu_state(cpu))
+		return -1;
+
 	return zynq_cpun_start(__pa_symbol(secondary_startup_arm), cpu);
 }
 
@@ -113,6 +118,7 @@
 static void zynq_secondary_init(unsigned int cpu)
 {
 	zynq_core_pm_init();
+	zynq_prefetch_init();
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-zynq/pm.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-zynq/pm.c
@@ -7,6 +7,14 @@
  *  Sören Brinkmann <soren.brinkmann@xilinx.com>
  */
 
+#include <linux/clk/zynq.h>
+#include <linux/genalloc.h>
+#include <linux/suspend.h>
+#include <asm/cacheflush.h>
+#include <asm/fncpy.h>
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/mach/map.h>
+#include <asm/suspend.h>
 #include <linux/io.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
@@ -22,6 +30,165 @@
 
 static void __iomem *ddrc_base;
 
+#ifdef CONFIG_SUSPEND
+static int (*zynq_suspend_ptr)(void __iomem *, void __iomem *);
+
+static int zynq_pm_prepare_late(void)
+{
+	return zynq_clk_suspend_early();
+}
+
+static void zynq_pm_wake(void)
+{
+	zynq_clk_resume_late();
+}
+
+static int zynq_pm_suspend(unsigned long arg)
+{
+	u32 reg;
+	int do_ddrpll_bypass = 1;
+
+	/* Topswitch clock stop disable */
+	zynq_clk_topswitch_disable();
+
+	if (!zynq_suspend_ptr || !ddrc_base) {
+		do_ddrpll_bypass = 0;
+	} else {
+		/* enable DDRC self-refresh mode */
+		reg = readl(ddrc_base + DDRC_CTRL_REG1_OFFS);
+		reg |= DDRC_SELFREFRESH_MASK;
+		writel(reg, ddrc_base + DDRC_CTRL_REG1_OFFS);
+	}
+
+	if (do_ddrpll_bypass) {
+		/*
+		 * Going this way will turn off DDR related clocks and the DDR
+		 * PLL. I.e. We might brake sub systems relying on any of this
+		 * clocks. And even worse: If there are any other masters in the
+		 * system (e.g. in the PL) accessing DDR they are screwed.
+		 */
+		flush_cache_all();
+		if (zynq_suspend_ptr(ddrc_base, zynq_slcr_base))
+			pr_warn("DDR self refresh failed.\n");
+	} else {
+		WARN_ONCE(1, "DRAM self-refresh not available\n");
+		cpu_do_idle();
+	}
+
+	/* disable DDRC self-refresh mode */
+	if (do_ddrpll_bypass) {
+		reg = readl(ddrc_base + DDRC_CTRL_REG1_OFFS);
+		reg &= ~DDRC_SELFREFRESH_MASK;
+		writel(reg, ddrc_base + DDRC_CTRL_REG1_OFFS);
+	}
+
+	/* Topswitch clock stop enable */
+	zynq_clk_topswitch_enable();
+
+	return 0;
+}
+
+static int zynq_pm_enter(suspend_state_t suspend_state)
+{
+	switch (suspend_state) {
+	case PM_SUSPEND_STANDBY:
+	case PM_SUSPEND_MEM:
+		cpu_suspend(0, zynq_pm_suspend);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct platform_suspend_ops zynq_pm_ops = {
+	.prepare_late	= zynq_pm_prepare_late,
+	.enter		= zynq_pm_enter,
+	.wake		= zynq_pm_wake,
+	.valid		= suspend_valid_only_mem,
+};
+
+/**
+ * zynq_pm_remap_ocm() - Remap OCM
+ * Returns a pointer to the mapped memory or NULL.
+ *
+ * Remap the OCM.
+ */
+static void __iomem *zynq_pm_remap_ocm(void)
+{
+	struct device_node *np;
+	const char *comp = "xlnx,zynq-ocmc-1.0";
+	void __iomem *base = NULL;
+
+	np = of_find_compatible_node(NULL, NULL, comp);
+	if (np) {
+		struct device *dev;
+		unsigned long pool_addr;
+		unsigned long pool_addr_virt;
+		struct gen_pool *pool;
+
+		of_node_put(np);
+
+		dev = &(of_find_device_by_node(np)->dev);
+
+		/* Get OCM pool from device tree or platform data */
+		pool = gen_pool_get(dev, NULL);
+		if (!pool) {
+			pr_warn("%s: OCM pool is not available\n", __func__);
+			return NULL;
+		}
+
+		pool_addr_virt = gen_pool_alloc(pool, zynq_sys_suspend_sz);
+		if (!pool_addr_virt) {
+			pr_warn("%s: Can't get OCM poll\n", __func__);
+			return NULL;
+		}
+		pool_addr = gen_pool_virt_to_phys(pool, pool_addr_virt);
+		if (!pool_addr) {
+			pr_warn("%s: Can't get physical address of OCM pool\n",
+				__func__);
+			return NULL;
+		}
+		base = __arm_ioremap_exec(pool_addr, zynq_sys_suspend_sz,
+				     MT_MEMORY_RWX);
+		if (!base) {
+			pr_warn("%s: IOremap OCM pool failed\n", __func__);
+			return NULL;
+		}
+		pr_debug("%s: Remap OCM %s from %lx to %lx\n", __func__, comp,
+			 pool_addr_virt, (unsigned long)base);
+	} else {
+		pr_warn("%s: no compatible node found for '%s'\n", __func__,
+				comp);
+	}
+
+	return base;
+}
+
+static void zynq_pm_suspend_init(void)
+{
+	void __iomem *ocm_base = zynq_pm_remap_ocm();
+
+	if (!ocm_base) {
+		pr_warn("%s: Unable to map OCM.\n", __func__);
+	} else {
+		/*
+		 * Copy code to suspend system into OCM. The suspend code
+		 * needs to run from OCM as DRAM may no longer be available
+		 * when the PLL is stopped.
+		 */
+		zynq_suspend_ptr = fncpy((__force void *)ocm_base,
+					 (__force void *)&zynq_sys_suspend,
+					 zynq_sys_suspend_sz);
+	}
+
+	suspend_set_ops(&zynq_pm_ops);
+}
+#else	/* CONFIG_SUSPEND */
+static void zynq_pm_suspend_init(void) { };
+#endif	/* CONFIG_SUSPEND */
+
 /**
  * zynq_pm_ioremap() - Create IO mappings
  * @comp:	DT compatible string
@@ -68,4 +235,7 @@
 		reg |= DDRC_CLOCKSTOP_MASK;
 		writel(reg, ddrc_base + DDRC_DRAM_PARAM_REG3_OFFS);
 	}
+
+	/* set up suspend */
+	zynq_pm_suspend_init();
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-zynq/slcr.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-zynq/slcr.c
@@ -16,10 +16,13 @@
 /* register offsets */
 #define SLCR_UNLOCK_OFFSET		0x8   /* SCLR unlock register */
 #define SLCR_PS_RST_CTRL_OFFSET		0x200 /* PS Software Reset Control */
+#define SLCR_FPGA_RST_CTRL_OFFSET	0x240 /* FPGA Software Reset Control */
 #define SLCR_A9_CPU_RST_CTRL_OFFSET	0x244 /* CPU Software Reset Control */
 #define SLCR_REBOOT_STATUS_OFFSET	0x258 /* PS Reboot Status */
 #define SLCR_PSS_IDCODE			0x530 /* PS IDCODE */
 #define SLCR_L2C_RAM			0xA1C /* L2C_RAM in AR#54190 */
+#define SLCR_LVL_SHFTR_EN_OFFSET	0x900 /* Level Shifters Enable */
+#define SLCR_OCM_CFG_OFFSET		0x910 /* OCM Address Mapping */
 
 #define SLCR_UNLOCK_MAGIC		0xDF0D
 #define SLCR_A9_CPU_CLKSTOP		0x10
@@ -27,7 +30,7 @@
 #define SLCR_PSS_IDCODE_DEVICE_SHIFT	12
 #define SLCR_PSS_IDCODE_DEVICE_MASK	0x1F
 
-static void __iomem *zynq_slcr_base;
+void __iomem *zynq_slcr_base;
 static struct regmap *zynq_slcr_regmap;
 
 /**
@@ -116,6 +119,48 @@
 };
 
 /**
+ * zynq_slcr_get_ocm_config - Get SLCR OCM config
+ *
+ * return:	OCM config bits
+ */
+u32 zynq_slcr_get_ocm_config(void)
+{
+	u32 ret;
+
+	zynq_slcr_read(&ret, SLCR_OCM_CFG_OFFSET);
+	return ret;
+}
+
+/**
+ * zynq_slcr_init_preload_fpga - Disable communication from the PL to PS.
+ */
+void zynq_slcr_init_preload_fpga(void)
+{
+	/* Assert FPGA top level output resets */
+	zynq_slcr_write(0xF, SLCR_FPGA_RST_CTRL_OFFSET);
+
+	/* Disable level shifters */
+	zynq_slcr_write(0, SLCR_LVL_SHFTR_EN_OFFSET);
+
+	/* Enable output level shifters */
+	zynq_slcr_write(0xA, SLCR_LVL_SHFTR_EN_OFFSET);
+}
+EXPORT_SYMBOL(zynq_slcr_init_preload_fpga);
+
+/**
+ * zynq_slcr_init_postload_fpga - Re-enable communication from the PL to PS.
+ */
+void zynq_slcr_init_postload_fpga(void)
+{
+	/* Enable level shifters */
+	zynq_slcr_write(0xf, SLCR_LVL_SHFTR_EN_OFFSET);
+
+	/* Deassert AXI interface resets */
+	zynq_slcr_write(0, SLCR_FPGA_RST_CTRL_OFFSET);
+}
+EXPORT_SYMBOL(zynq_slcr_init_postload_fpga);
+
+/**
  * zynq_slcr_cpu_start - Start cpu
  * @cpu:	cpu number
  */
@@ -213,6 +258,7 @@
 	zynq_slcr_regmap = syscon_regmap_lookup_by_compatible("xlnx,zynq-slcr");
 	if (IS_ERR(zynq_slcr_regmap)) {
 		pr_err("%s: failed to find zynq-slcr\n", __func__);
+		of_node_put(np);
 		return -ENODEV;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-zynq/suspend.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-zynq/suspend.S
@@ -0,0 +1,185 @@
+/*
+ * Suspend support for Zynq
+ *
+ *  Copyright (C) 2012 Xilinx
+ *
+ *  Soren Brinkmann <soren.brinkmann@xilinx.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/linkage.h>
+
+#define ARMPLL_CTRL_OFFS	0x100
+#define DDRPLL_CTRL_OFFS	0x104
+#define PLLSTATUS_OFFS		0x10c
+#define DDR_CLK_CTRL_OFFS	0x124
+#define DCI_CLK_CTRL_OFFS	0x128
+#define MODE_STS_OFFS		0x54
+
+#define PLL_RESET_MASK		1
+#define PLL_PWRDWN_MASK		(1 << 1)
+#define PLL_BYPASS_MASK		(1 << 4)
+#define DCICLK_ENABLE_MASK	1
+#define DDRCLK_ENABLE_MASK	3
+#define ARM_LOCK_MASK		(1 << 0)
+#define DDR_LOCK_MASK		(1 << 1)
+#define DDRC_STATUS_MASK	7
+
+#define DDRC_OPMODE_SR		3
+#define MAXTRIES		100
+
+	.text
+	.align 3
+
+/**
+ * zynq_sys_suspend - Enter suspend
+ * @ddrc_base:	Base address of the DDRC
+ * @slcr_base:	Base address of the SLCR
+ * Returns -1 if DRAM subsystem is not gated off, 0 otherwise.
+ *
+ * This function is moved into OCM and finishes the suspend operation. I.e. DDR
+ * related clocks are gated off and the DDR PLL is bypassed.
+ */
+ENTRY(zynq_sys_suspend)
+	push	{r4 - r7}
+
+	/* Check DDRC is in self-refresh mode */
+	ldr	r2, [r0, #MODE_STS_OFFS]
+	and	r2, #DDRC_STATUS_MASK
+	cmp	r2, #DDRC_OPMODE_SR
+	movweq	r3, #0xff00
+	bne	suspend
+
+	mov	r3, #MAXTRIES
+	movw	r4, #0xfff0
+	movt	r4, #0x1f
+	/* Wait for command queue empty */
+1:	subs	r3, #1
+	movweq	r3, #0xff00
+	beq	suspend
+	dsb	sy
+	ldr	r2, [r0, #MODE_STS_OFFS]
+	ands	r2, r4
+	bne	1b
+
+	dsb	sy
+
+	/*
+	 * Wait for DDRC pipeline/queues to drain.
+	 * We should wait ~40 DDR cycles. DDR is still at full speed while the
+	 * CPU might already run in PLL bypass mode. The fastest speed the CPU
+	 * runs at is ~1 GHz ~ 2 * DDR speed.
+	 */
+	mov	r3, #160
+1:	nop
+	subs	r3, #1
+	bne	1b
+
+	dsb	sy
+
+	/* read back CAM status once more */
+	ldr	r2, [r0, #MODE_STS_OFFS]
+	ands	r2, r4
+	movwne	r3, #0xff00
+	bne	suspend
+
+	/* Stop DDR clocks */
+	ldr	r2, [r1, #DDR_CLK_CTRL_OFFS]
+	bic	r2, #DDRCLK_ENABLE_MASK
+	str	r2, [r1, #DDR_CLK_CTRL_OFFS]
+
+	dmb	st
+
+	ldr	r2, [r1, #DCI_CLK_CTRL_OFFS]
+	bic	r2, #DCICLK_ENABLE_MASK
+	str	r2, [r1, #DCI_CLK_CTRL_OFFS]
+
+	dmb	st
+
+	/* Bypass and powerdown DDR PLL */
+	ldr	r2, [r1, #DDRPLL_CTRL_OFFS]
+	orr	r2, #PLL_BYPASS_MASK
+	str	r2, [r1, #DDRPLL_CTRL_OFFS]
+	orr	r2, #(PLL_PWRDWN_MASK | PLL_RESET_MASK)
+	str	r2, [r1, #DDRPLL_CTRL_OFFS]
+
+	/* Bypass and powerdown ARM PLL */
+	ldr	r2, [r1, #ARMPLL_CTRL_OFFS]
+	orr	r2, #PLL_BYPASS_MASK
+	str	r2, [r1, #ARMPLL_CTRL_OFFS]
+	orr	r2, #(PLL_PWRDWN_MASK | PLL_RESET_MASK)
+	str	r2, [r1, #ARMPLL_CTRL_OFFS]
+
+suspend:
+	dsb	sy
+	wfi
+	dsb	sy
+	cmp	r3, #0xff00
+	moveq	r0, #-1
+	beq	exit
+
+	/* Power up ARM PLL */
+	ldr	r2, [r1, #ARMPLL_CTRL_OFFS]
+	bic	r2, #(PLL_PWRDWN_MASK | PLL_RESET_MASK)
+	str	r2, [r1, #ARMPLL_CTRL_OFFS]
+	/* wait for lock */
+1:	ldr	r2, [r1, #PLLSTATUS_OFFS]
+	ands	r2, #ARM_LOCK_MASK
+	beq	1b
+
+	dsb	sy
+
+	/* Disable ARM PLL bypass */
+	ldr	r2, [r1, #ARMPLL_CTRL_OFFS]
+	bic	r2, #PLL_BYPASS_MASK
+	str	r2, [r1, #ARMPLL_CTRL_OFFS]
+
+	dmb	st
+
+	/* Power up DDR PLL */
+	ldr	r2, [r1, #DDRPLL_CTRL_OFFS]
+	bic	r2, #(PLL_PWRDWN_MASK | PLL_RESET_MASK)
+	str	r2, [r1, #DDRPLL_CTRL_OFFS]
+	/* wait for lock */
+1:	ldr	r2, [r1, #PLLSTATUS_OFFS]
+	ands	r2, #DDR_LOCK_MASK
+	beq	1b
+
+	dsb	sy
+
+	/* Disable DDR PLL bypass */
+	ldr	r2, [r1, #DDRPLL_CTRL_OFFS]
+	bic	r2, #PLL_BYPASS_MASK
+	str	r2, [r1, #DDRPLL_CTRL_OFFS]
+
+	dmb	st
+
+	/* Start DDR clocks */
+	ldr	r2, [r1, #DCI_CLK_CTRL_OFFS]
+	orr	r2, #DCICLK_ENABLE_MASK
+	str	r2, [r1, #DCI_CLK_CTRL_OFFS]
+
+	dmb	st
+
+	ldr	r2, [r1, #DDR_CLK_CTRL_OFFS]
+	orr	r2, #DDRCLK_ENABLE_MASK
+	str	r2, [r1, #DDR_CLK_CTRL_OFFS]
+
+	dsb	sy
+
+	mov	r0, #0
+exit:	pop	{r4 - r7}
+	bx	lr
+
+ENTRY(zynq_sys_suspend_sz)
+	.word	. - zynq_sys_suspend
+
+	ENDPROC(zynq_sys_suspend)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mach-zynq/zynq_ocm.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mach-zynq/zynq_ocm.c
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2013 Xilinx
+ *
+ * Based on "Generic on-chip SRAM allocation driver"
+ *
+ * Copyright (C) 2012 Philipp Zabel, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/genalloc.h>
+
+#include "common.h"
+
+#define ZYNQ_OCM_HIGHADDR	0xfffc0000
+#define ZYNQ_OCM_LOWADDR	0x0
+#define ZYNQ_OCM_BLOCK_SIZE	0x10000
+#define ZYNQ_OCM_BLOCKS		4
+#define ZYNQ_OCM_GRANULARITY	32
+
+#define ZYNQ_OCM_PARITY_CTRL	0x0
+#define ZYNQ_OCM_PARITY_ENABLE	0x1e
+
+#define ZYNQ_OCM_PARITY_ERRADDRESS	0x4
+
+#define ZYNQ_OCM_IRQ_STS		0x8
+#define ZYNQ_OCM_IRQ_STS_ERR_MASK	0x7
+
+struct zynq_ocm_dev {
+	void __iomem *base;
+	int irq;
+	struct gen_pool *pool;
+	struct resource res[ZYNQ_OCM_BLOCKS];
+};
+
+/**
+ * zynq_ocm_irq_handler - Interrupt service routine of the OCM controller
+ * @irq:	IRQ number
+ * @data:	Pointer to the zynq_ocm_dev structure
+ *
+ * Return:	IRQ_HANDLED when handled; IRQ_NONE otherwise.
+ */
+static irqreturn_t zynq_ocm_irq_handler(int irq, void *data)
+{
+	u32 sts;
+	u32 err_addr;
+	struct zynq_ocm_dev *zynq_ocm = data;
+
+	/* check status */
+	sts = readl(zynq_ocm->base + ZYNQ_OCM_IRQ_STS);
+	if (sts & ZYNQ_OCM_IRQ_STS_ERR_MASK) {
+		/* check error address */
+		err_addr = readl(zynq_ocm->base + ZYNQ_OCM_PARITY_ERRADDRESS);
+		pr_err("%s: OCM err intr generated at 0x%04x (stat: 0x%08x).",
+		       __func__, err_addr, sts & ZYNQ_OCM_IRQ_STS_ERR_MASK);
+		return IRQ_HANDLED;
+	}
+	pr_warn("%s: Interrupt generated by OCM, but no error is found.",
+		__func__);
+
+	return IRQ_NONE;
+}
+
+/**
+ * zynq_ocm_probe - Probe method for the OCM driver
+ * @pdev:	Pointer to the platform_device structure
+ *
+ * This function initializes the driver data structures and the hardware.
+ *
+ * Return:	0 on success and error value on failure
+ */
+static int zynq_ocm_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct zynq_ocm_dev *zynq_ocm;
+	u32 i, ocm_config, curr;
+	struct resource *res;
+
+	ocm_config = zynq_slcr_get_ocm_config();
+
+	zynq_ocm = devm_kzalloc(&pdev->dev, sizeof(*zynq_ocm), GFP_KERNEL);
+	if (!zynq_ocm)
+		return -ENOMEM;
+
+	zynq_ocm->pool = devm_gen_pool_create(&pdev->dev,
+					      ilog2(ZYNQ_OCM_GRANULARITY),
+					      NUMA_NO_NODE, NULL);
+	if (!zynq_ocm->pool)
+		return -ENOMEM;
+
+	curr = 0; /* For storing current struct resource for OCM */
+	for (i = 0; i < ZYNQ_OCM_BLOCKS; i++) {
+		u32 base, start, end;
+
+		/* Setup base address for 64kB OCM block */
+		if (ocm_config & BIT(i))
+			base = ZYNQ_OCM_HIGHADDR;
+		else
+			base = ZYNQ_OCM_LOWADDR;
+
+		/* Calculate start and end block addresses */
+		start = i * ZYNQ_OCM_BLOCK_SIZE + base;
+		end = start + (ZYNQ_OCM_BLOCK_SIZE - 1);
+
+		/* Concatenate OCM blocks together to get bigger pool */
+		if (i > 0 && start == (zynq_ocm->res[curr - 1].end + 1)) {
+			zynq_ocm->res[curr - 1].end = end;
+		} else {
+#ifdef CONFIG_SMP
+			/*
+			 * OCM block if placed at 0x0 has special meaning
+			 * for SMP because jump trampoline is added there.
+			 * Ensure that this address won't be allocated.
+			 */
+			if (!base) {
+				u32 trampoline_code_size =
+					&zynq_secondary_trampoline_end -
+					&zynq_secondary_trampoline;
+				dev_dbg(&pdev->dev,
+					"Allocate reset vector table %dB\n",
+					trampoline_code_size);
+				/* postpone start offset */
+				start += trampoline_code_size;
+			}
+#endif
+			/* First resource is always initialized */
+			zynq_ocm->res[curr].start = start;
+			zynq_ocm->res[curr].end = end;
+			zynq_ocm->res[curr].flags = IORESOURCE_MEM;
+			curr++; /* Increment curr value */
+		}
+		dev_dbg(&pdev->dev, "OCM block %d, start %x, end %x\n",
+			i, start, end);
+	}
+
+	/*
+	 * Separate pool allocation from OCM block detection to ensure
+	 * the biggest possible pool.
+	 */
+	for (i = 0; i < ZYNQ_OCM_BLOCKS; i++) {
+		unsigned long size;
+		void __iomem *virt_base;
+
+		/* Skip all zero size resources */
+		if (zynq_ocm->res[i].end == 0)
+			break;
+		dev_dbg(&pdev->dev, "OCM resources %d, start %x, end %x\n",
+			i, zynq_ocm->res[i].start, zynq_ocm->res[i].end);
+		size = resource_size(&zynq_ocm->res[i]);
+		virt_base = devm_ioremap_resource(&pdev->dev,
+						  &zynq_ocm->res[i]);
+		if (IS_ERR(virt_base))
+			return PTR_ERR(virt_base);
+
+		ret = gen_pool_add_virt(zynq_ocm->pool,
+					(unsigned long)virt_base,
+					zynq_ocm->res[i].start, size, -1);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "Gen pool failed\n");
+			return ret;
+		}
+		dev_info(&pdev->dev, "ZYNQ OCM pool: %ld KiB @ 0x%p\n",
+			 size / 1024, virt_base);
+	}
+
+	/* Get OCM config space */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	zynq_ocm->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(zynq_ocm->base))
+		return PTR_ERR(zynq_ocm->base);
+
+	/* Allocate OCM parity IRQ */
+	zynq_ocm->irq = platform_get_irq(pdev, 0);
+	if (zynq_ocm->irq < 0) {
+		dev_err(&pdev->dev, "irq resource not found\n");
+		return zynq_ocm->irq;
+	}
+	ret = devm_request_irq(&pdev->dev, zynq_ocm->irq, zynq_ocm_irq_handler,
+			       0, pdev->name, zynq_ocm);
+	if (ret != 0) {
+		dev_err(&pdev->dev, "request_irq failed\n");
+		return ret;
+	}
+
+	/* Enable parity errors */
+	writel(ZYNQ_OCM_PARITY_ENABLE, zynq_ocm->base + ZYNQ_OCM_PARITY_CTRL);
+
+	platform_set_drvdata(pdev, zynq_ocm);
+
+	return 0;
+}
+
+/**
+ * zynq_ocm_remove - Remove method for the OCM driver
+ * @pdev:	Pointer to the platform_device structure
+ *
+ * This function is called if a device is physically removed from the system or
+ * if the driver module is being unloaded. It frees all resources allocated to
+ * the device.
+ *
+ * Return:	0 on success and error value on failure
+ */
+static int zynq_ocm_remove(struct platform_device *pdev)
+{
+	struct zynq_ocm_dev *zynq_ocm = platform_get_drvdata(pdev);
+
+	if (gen_pool_avail(zynq_ocm->pool) < gen_pool_size(zynq_ocm->pool))
+		dev_dbg(&pdev->dev, "removed while SRAM allocated\n");
+
+	return 0;
+}
+
+static struct of_device_id zynq_ocm_dt_ids[] = {
+	{ .compatible = "xlnx,zynq-ocmc-1.0" },
+	{ /* end of table */ }
+};
+
+static struct platform_driver zynq_ocm_driver = {
+	.driver = {
+		.name = "zynq-ocm",
+		.of_match_table = zynq_ocm_dt_ids,
+	},
+	.probe = zynq_ocm_probe,
+	.remove = zynq_ocm_remove,
+};
+
+static int __init zynq_ocm_init(void)
+{
+	return platform_driver_register(&zynq_ocm_driver);
+}
+
+arch_initcall(zynq_ocm_init);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/Kconfig
@@ -743,6 +743,7 @@
 config CPU_BIG_ENDIAN
 	bool "Build big-endian kernel"
 	depends on ARCH_SUPPORTS_BIG_ENDIAN
+	depends on !LD_IS_LLD
 	help
 	  Say Y if you plan on running a kernel in big-endian mode.
 	  Note that your board must be properly built and your board
@@ -752,7 +753,7 @@
 config CPU_ENDIAN_BE8
 	bool
 	depends on CPU_BIG_ENDIAN
-	default CPU_V6 || CPU_V6K || CPU_V7
+	default CPU_V6 || CPU_V6K || CPU_V7 || CPU_V7M
 	help
 	  Support for the BE-8 (big-endian) mode on ARMv6 and ARMv7 processors.
 
@@ -832,6 +833,7 @@
 
 config CPU_SPECTRE
 	bool
+	select GENERIC_CPU_VULNERABILITIES
 
 config HARDEN_BRANCH_PREDICTOR
 	bool "Harden the branch predictor against aliasing attacks" if EXPERT
@@ -852,6 +854,16 @@
 
 	   If unsure, say Y.
 
+config HARDEN_BRANCH_HISTORY
+	bool "Harden Spectre style attacks against branch history" if EXPERT
+	depends on CPU_SPECTRE
+	default y
+	help
+	  Speculation attacks against some high-performance processors can
+	  make use of branch history to influence future speculation. When
+	  taking an exception, a sequence of branches overwrites the branch
+	  history, or branch history is invalidated.
+
 config TLS_REG_EMUL
 	bool
 	select NEED_KUSER_HELPERS
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/alignment.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/alignment.c
@@ -799,7 +799,7 @@
 static int
 do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 {
-	union offset_union uninitialized_var(offset);
+	union offset_union offset;
 	unsigned long instrptr;
 	int (*handler)(unsigned long addr, u32 instr, struct pt_regs *regs);
 	unsigned int type;
@@ -935,6 +935,9 @@
 	if (type == TYPE_LDST)
 		do_alignment_finish_ldst(addr, instr, regs, offset);
 
+	if (thumb_mode(regs))
+		regs->ARM_cpsr = it_advance(regs->ARM_cpsr);
+
 	return 0;
 
  bad_or_fault:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/cache-l2x0.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/cache-l2x0.c
@@ -1249,20 +1249,28 @@
 
 	ret = of_property_read_u32(np, "prefetch-data", &val);
 	if (ret == 0) {
-		if (val)
+		if (val) {
 			prefetch |= L310_PREFETCH_CTRL_DATA_PREFETCH;
-		else
+			*aux_val |= L310_PREFETCH_CTRL_DATA_PREFETCH;
+		} else {
 			prefetch &= ~L310_PREFETCH_CTRL_DATA_PREFETCH;
+			*aux_val &= ~L310_PREFETCH_CTRL_DATA_PREFETCH;
+		}
+		*aux_mask &= ~L310_PREFETCH_CTRL_DATA_PREFETCH;
 	} else if (ret != -EINVAL) {
 		pr_err("L2C-310 OF prefetch-data property value is missing\n");
 	}
 
 	ret = of_property_read_u32(np, "prefetch-instr", &val);
 	if (ret == 0) {
-		if (val)
+		if (val) {
 			prefetch |= L310_PREFETCH_CTRL_INSTR_PREFETCH;
-		else
+			*aux_val |= L310_PREFETCH_CTRL_INSTR_PREFETCH;
+		} else {
 			prefetch &= ~L310_PREFETCH_CTRL_INSTR_PREFETCH;
+			*aux_val &= ~L310_PREFETCH_CTRL_INSTR_PREFETCH;
+		}
+		*aux_mask &= ~L310_PREFETCH_CTRL_INSTR_PREFETCH;
 	} else if (ret != -EINVAL) {
 		pr_err("L2C-310 OF prefetch-instr property value is missing\n");
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/dma-mapping-nommu.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/dma-mapping-nommu.c
@@ -35,7 +35,7 @@
 				 unsigned long attrs)
 
 {
-	void *ret = dma_alloc_from_global_coherent(size, dma_handle);
+	void *ret = dma_alloc_from_global_coherent(dev, size, dma_handle);
 
 	/*
 	 * dma_alloc_from_global_coherent() may fail because:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/dma-mapping.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/dma-mapping.c
@@ -221,7 +221,7 @@
 
 static int __dma_supported(struct device *dev, u64 mask, bool warn)
 {
-	unsigned long max_dma_pfn = min(max_pfn, arm_dma_pfn_limit);
+	unsigned long max_dma_pfn = min(max_pfn - 1, arm_dma_pfn_limit);
 
 	/*
 	 * Translate the device's DMA mask to a PFN limit.  This
@@ -2332,15 +2332,15 @@
 }
 
 #ifdef CONFIG_SWIOTLB
-void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr,
-		size_t size, enum dma_data_direction dir)
+void arch_sync_dma_for_device(phys_addr_t paddr, size_t size,
+		enum dma_data_direction dir)
 {
 	__dma_page_cpu_to_dev(phys_to_page(paddr), paddr & (PAGE_SIZE - 1),
 			      size, dir);
 }
 
-void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr,
-		size_t size, enum dma_data_direction dir)
+void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size,
+		enum dma_data_direction dir)
 {
 	__dma_page_dev_to_cpu(phys_to_page(paddr), paddr & (PAGE_SIZE - 1),
 			      size, dir);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/fault.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/fault.c
@@ -27,6 +27,13 @@
 
 #ifdef CONFIG_MMU
 
+bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size)
+{
+	unsigned long addr = (unsigned long)unsafe_src;
+
+	return addr >= TASK_SIZE && ULONG_MAX - addr >= size;
+}
+
 /*
  * This is useful to dump out the page tables associated with
  * 'addr' in mm 'mm'.
@@ -124,7 +131,7 @@
 	show_pte(KERN_ALERT, mm, addr);
 	die("Oops", regs, fsr);
 	bust_spinlocks(0);
-	do_exit(SIGKILL);
+	make_task_dead(SIGKILL);
 }
 
 /*
@@ -563,6 +570,7 @@
 	if (!inf->fn(addr, ifsr | FSR_LNX_PF, regs))
 		return;
 
+	pr_alert("8<--- cut here ---\n");
 	pr_alert("Unhandled prefetch abort: %s (0x%03x) at 0x%08lx\n",
 		inf->name, ifsr, addr);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/flush.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/flush.c
@@ -280,6 +280,8 @@
 		return;
 
 	page = pfn_to_page(pfn);
+	if (PageReserved(page))
+		return;
 	if (cache_is_vipt_aliasing())
 		mapping = page_mapping_file(page);
 	else
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/init.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/init.c
@@ -176,11 +176,22 @@
 int pfn_valid(unsigned long pfn)
 {
 	phys_addr_t addr = __pfn_to_phys(pfn);
+	unsigned long pageblock_size = PAGE_SIZE * pageblock_nr_pages;
 
 	if (__phys_to_pfn(addr) != pfn)
 		return 0;
 
-	return memblock_is_map_memory(__pfn_to_phys(pfn));
+	/*
+	 * If address less than pageblock_size bytes away from a present
+	 * memory chunk there still will be a memory map entry for it
+	 * because we round freed memory map to the pageblock boundaries.
+	 */
+	if (memblock_overlaps_region(&memblock.memory,
+				     ALIGN_DOWN(addr, pageblock_size),
+				     pageblock_size))
+		return 1;
+
+	return 0;
 }
 EXPORT_SYMBOL(pfn_valid);
 #endif
@@ -274,7 +285,6 @@
 	if (mdesc->reserve)
 		mdesc->reserve();
 
-	early_init_fdt_reserve_self();
 	early_init_fdt_scan_reserved_mem();
 
 	/* reserve memory for DMA contiguous allocations */
@@ -323,7 +333,7 @@
 		*p++ = 0xe7fddef0;
 }
 
-static inline void
+static inline void __init
 free_memmap(unsigned long start_pfn, unsigned long end_pfn)
 {
 	struct page *start_pg, *end_pg;
@@ -372,14 +382,14 @@
 		 */
 		start = min(start,
 				 ALIGN(prev_end, PAGES_PER_SECTION));
-#else
+#endif
 		/*
-		 * Align down here since the VM subsystem insists that the
-		 * memmap entries are valid from the bank start aligned to
-		 * MAX_ORDER_NR_PAGES.
+		 * Align down here since many operations in VM subsystem
+		 * presume that there are no holes in the memory map inside
+		 * a pageblock
 		 */
-		start = round_down(start, MAX_ORDER_NR_PAGES);
-#endif
+		start = round_down(start, pageblock_nr_pages);
+
 		/*
 		 * If we had a previous bank, and there is a space
 		 * between the current bank and the previous, free it.
@@ -388,18 +398,20 @@
 			free_memmap(prev_end, start);
 
 		/*
-		 * Align up here since the VM subsystem insists that the
-		 * memmap entries are valid from the bank end aligned to
-		 * MAX_ORDER_NR_PAGES.
+		 * Align up here since many operations in VM subsystem
+		 * presume that there are no holes in the memory map inside
+		 * a pageblock
 		 */
 		prev_end = ALIGN(memblock_region_memory_end_pfn(reg),
-				 MAX_ORDER_NR_PAGES);
+				 pageblock_nr_pages);
 	}
 
 #ifdef CONFIG_SPARSEMEM
-	if (!IS_ALIGNED(prev_end, PAGES_PER_SECTION))
+	if (!IS_ALIGNED(prev_end, PAGES_PER_SECTION)) {
+		prev_end = ALIGN(prev_end, pageblock_nr_pages);
 		free_memmap(prev_end,
 			    ALIGN(prev_end, PAGES_PER_SECTION));
+	}
 #endif
 }
 
@@ -470,7 +482,11 @@
 void __init mem_init(void)
 {
 #ifdef CONFIG_ARM_LPAE
-	swiotlb_init(1);
+	if (swiotlb_force == SWIOTLB_FORCE ||
+	    max_pfn > arm_dma_pfn_limit)
+		swiotlb_init(1);
+	else
+		swiotlb_force = SWIOTLB_NO_FORCE;
 #endif
 
 	set_max_mapnr(pfn_to_page(max_pfn) - mem_map);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/ioremap.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/ioremap.c
@@ -27,6 +27,7 @@
 #include <linux/vmalloc.h>
 #include <linux/io.h>
 #include <linux/sizes.h>
+#include <linux/memblock.h>
 
 #include <asm/cp15.h>
 #include <asm/cputype.h>
@@ -301,7 +302,8 @@
 	 * Don't allow RAM to be mapped with mismatched attributes - this
 	 * causes problems with ARMv6+
 	 */
-	if (WARN_ON(pfn_valid(pfn) && mtype != MT_MEMORY_RW))
+	if (WARN_ON(memblock_is_map_memory(PFN_PHYS(pfn)) &&
+		    mtype != MT_MEMORY_RW))
 		return NULL;
 
 	area = get_vm_area_caller(size, VM_IOREMAP, caller);
@@ -498,3 +500,11 @@
 {
 	early_ioremap_setup();
 }
+
+bool arch_memremap_can_ram_remap(resource_size_t offset, size_t size,
+				 unsigned long flags)
+{
+	unsigned long pfn = PHYS_PFN(offset);
+
+	return memblock_is_map_memory(pfn);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/mmu.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/mmu.c
@@ -39,6 +39,8 @@
 #include "mm.h"
 #include "tcm.h"
 
+extern unsigned long __atags_pointer;
+
 /*
  * empty_zero_page is a special page that is used for
  * zero-initialized data and COW.
@@ -227,12 +229,14 @@
 static int __init early_cachepolicy(char *p)
 {
 	pr_warn("cachepolicy kernel parameter not supported without cp15\n");
+	return 0;
 }
 early_param("cachepolicy", early_cachepolicy);
 
 static int __init noalign_setup(char *__unused)
 {
 	pr_warn("noalign kernel parameter not supported without cp15\n");
+	return 1;
 }
 __setup("noalign", noalign_setup);
 
@@ -312,6 +316,17 @@
 		.prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE,
 		.domain    = DOMAIN_KERNEL,
 	},
+	[MT_MEMORY_RO] = {
+		.prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
+			     L_PTE_XN | L_PTE_RDONLY,
+		.prot_l1   = PMD_TYPE_TABLE,
+#ifdef CONFIG_ARM_LPAE
+		.prot_sect = PMD_TYPE_SECT | L_PMD_SECT_RDONLY | PMD_SECT_AP2,
+#else
+		.prot_sect = PMD_TYPE_SECT,
+#endif
+		.domain    = DOMAIN_KERNEL,
+	},
 	[MT_ROM] = {
 		.prot_sect = PMD_TYPE_SECT,
 		.domain    = DOMAIN_KERNEL,
@@ -413,9 +428,9 @@
 		     FIXADDR_END);
 	BUG_ON(idx >= __end_of_fixed_addresses);
 
-	/* we only support device mappings until pgprot_kernel has been set */
+	/* We support only device mappings before pgprot_kernel is set. */
 	if (WARN_ON(pgprot_val(prot) != pgprot_val(FIXMAP_PAGE_IO) &&
-		    pgprot_val(pgprot_kernel) == 0))
+		    pgprot_val(prot) && pgprot_val(pgprot_kernel) == 0))
 		return;
 
 	if (pgprot_val(prot))
@@ -511,6 +526,7 @@
 
 			/* Also setup NX memory mapping */
 			mem_types[MT_MEMORY_RW].prot_sect |= PMD_SECT_XN;
+			mem_types[MT_MEMORY_RO].prot_sect |= PMD_SECT_XN;
 		}
 		if (cpu_arch >= CPU_ARCH_ARMv7 && (cr & CR_TRE)) {
 			/*
@@ -593,6 +609,7 @@
 		mem_types[MT_ROM].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
 		mem_types[MT_MINICLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
 		mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
+		mem_types[MT_MEMORY_RO].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
 #endif
 
 		/*
@@ -613,6 +630,8 @@
 			mem_types[MT_MEMORY_RWX].prot_pte |= L_PTE_SHARED;
 			mem_types[MT_MEMORY_RW].prot_sect |= PMD_SECT_S;
 			mem_types[MT_MEMORY_RW].prot_pte |= L_PTE_SHARED;
+			mem_types[MT_MEMORY_RO].prot_sect |= PMD_SECT_S;
+			mem_types[MT_MEMORY_RO].prot_pte |= L_PTE_SHARED;
 			mem_types[MT_MEMORY_DMA_READY].prot_pte |= L_PTE_SHARED;
 			mem_types[MT_MEMORY_RWX_NONCACHED].prot_sect |= PMD_SECT_S;
 			mem_types[MT_MEMORY_RWX_NONCACHED].prot_pte |= L_PTE_SHARED;
@@ -676,6 +695,8 @@
 	mem_types[MT_MEMORY_RWX].prot_pte |= kern_pgprot;
 	mem_types[MT_MEMORY_RW].prot_sect |= ecc_mask | cp->pmd;
 	mem_types[MT_MEMORY_RW].prot_pte |= kern_pgprot;
+	mem_types[MT_MEMORY_RO].prot_sect |= ecc_mask | cp->pmd;
+	mem_types[MT_MEMORY_RO].prot_pte |= kern_pgprot;
 	mem_types[MT_MEMORY_DMA_READY].prot_pte |= kern_pgprot;
 	mem_types[MT_MEMORY_RWX_NONCACHED].prot_sect |= ecc_mask;
 	mem_types[MT_ROM].prot_sect |= cp->pmd;
@@ -962,7 +983,7 @@
 		return;
 	}
 
-	if ((md->type == MT_DEVICE || md->type == MT_ROM) &&
+	if (md->type == MT_DEVICE &&
 	    md->virtual >= PAGE_OFFSET && md->virtual < FIXADDR_START &&
 	    (md->virtual < VMALLOC_START || md->virtual >= VMALLOC_END)) {
 		pr_warn("BUG: mapping for 0x%08llx at 0x%08lx out of vmalloc space\n",
@@ -1352,6 +1373,15 @@
 	for (addr = VMALLOC_START; addr < (FIXADDR_TOP & PMD_MASK); addr += PMD_SIZE)
 		pmd_clear(pmd_off_k(addr));
 
+	if (__atags_pointer) {
+		/* create a read-only mapping of the device tree */
+		map.pfn = __phys_to_pfn(__atags_pointer & SECTION_MASK);
+		map.virtual = FDT_FIXED_BASE;
+		map.length = FDT_FIXED_SIZE;
+		map.type = MT_MEMORY_RO;
+		create_mapping(&map);
+	}
+
 	/*
 	 * Map the kernel if it is XIP.
 	 * It is always first in the modulearea.
@@ -1512,8 +1542,7 @@
 }
 
 #ifdef CONFIG_ARM_PV_FIXUP
-extern unsigned long __atags_pointer;
-typedef void pgtables_remap(long long offset, unsigned long pgd, void *bdata);
+typedef void pgtables_remap(long long offset, unsigned long pgd);
 pgtables_remap lpae_pgtables_remap_asm;
 
 /*
@@ -1526,7 +1555,6 @@
 	unsigned long pa_pgd;
 	unsigned int cr, ttbcr;
 	long long offset;
-	void *boot_data;
 
 	if (!mdesc->pv_fixup)
 		return;
@@ -1543,7 +1571,6 @@
 	 */
 	lpae_pgtables_remap = (pgtables_remap *)(unsigned long)__pa(lpae_pgtables_remap_asm);
 	pa_pgd = __pa(swapper_pg_dir);
-	boot_data = __va(__atags_pointer);
 	barrier();
 
 	pr_info("Switching physical address space to 0x%08llx\n",
@@ -1579,7 +1606,7 @@
 	 * needs to be assembly.  It's fairly simple, as we're using the
 	 * temporary tables setup by the initial assembly code.
 	 */
-	lpae_pgtables_remap(offset, pa_pgd, boot_data);
+	lpae_pgtables_remap(offset, pa_pgd);
 
 	/* Re-enable the caches and cacheable TLB walks */
 	asm volatile("mcr p15, 0, %0, c2, c0, 2" : : "r" (ttbcr));
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/nommu.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/nommu.c
@@ -26,6 +26,13 @@
 
 unsigned long vectors_base;
 
+/*
+ * empty_zero_page is a special page that is used for
+ * zero-initialized data and COW.
+ */
+struct page *empty_zero_page;
+EXPORT_SYMBOL(empty_zero_page);
+
 #ifdef CONFIG_ARM_MPU
 struct mpu_rgn_info mpu_rgn_info;
 #endif
@@ -148,9 +155,21 @@
  */
 void __init paging_init(const struct machine_desc *mdesc)
 {
+	void *zero_page;
+
 	early_trap_init((void *)vectors_base);
 	mpu_setup();
+
+	/* allocate the zero page. */
+	zero_page = (void *)memblock_alloc(PAGE_SIZE, PAGE_SIZE);
+	if (!zero_page)
+		panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
+		      __func__, PAGE_SIZE, PAGE_SIZE);
+
 	bootmem_init();
+
+	empty_zero_page = virt_to_page(zero_page);
+	flush_dcache_page(empty_zero_page);
 }
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/proc-arm1020.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/proc-arm1020.S
@@ -491,7 +491,7 @@
 
 	.align
 
-	.section ".proc.info.init", #alloc
+	.section ".proc.info.init", "a"
 
 	.type	__arm1020_proc_info,#object
 __arm1020_proc_info:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/proc-arm1020e.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/proc-arm1020e.S
@@ -449,7 +449,7 @@
 
 	.align
 
-	.section ".proc.info.init", #alloc
+	.section ".proc.info.init", "a"
 
 	.type	__arm1020e_proc_info,#object
 __arm1020e_proc_info:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/proc-arm1022.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/proc-arm1022.S
@@ -443,7 +443,7 @@
 
 	.align
 
-	.section ".proc.info.init", #alloc
+	.section ".proc.info.init", "a"
 
 	.type	__arm1022_proc_info,#object
 __arm1022_proc_info:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/proc-arm1026.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/proc-arm1026.S
@@ -138,7 +138,7 @@
 	mov	ip, #0
 __flush_whole_cache:
 #ifndef CONFIG_CPU_DCACHE_DISABLE
-1:	mrc	p15, 0, r15, c7, c14, 3		@ test, clean, invalidate
+1:	mrc	p15, 0, APSR_nzcv, c7, c14, 3		@ test, clean, invalidate
 	bne	1b
 #endif
 	tst	r2, #VM_EXEC
@@ -363,7 +363,7 @@
 #ifdef CONFIG_MMU
 	mov	r1, #0
 #ifndef CONFIG_CPU_DCACHE_DISABLE
-1:	mrc	p15, 0, r15, c7, c14, 3		@ test, clean, invalidate
+1:	mrc	p15, 0, APSR_nzcv, c7, c14, 3		@ test, clean, invalidate
 	bne	1b
 #endif
 #ifndef CONFIG_CPU_ICACHE_DISABLE
@@ -437,7 +437,7 @@
 	string	cpu_arm1026_name, "ARM1026EJ-S"
 	.align
 
-	.section ".proc.info.init", #alloc
+	.section ".proc.info.init", "a"
 
 	.type	__arm1026_proc_info,#object
 __arm1026_proc_info:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/proc-arm720.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/proc-arm720.S
@@ -172,7 +172,7 @@
  * See <asm/procinfo.h> for a definition of this structure.
  */
 	
-		.section ".proc.info.init", #alloc
+		.section ".proc.info.init", "a"
 
 .macro arm720_proc_info name:req, cpu_val:req, cpu_mask:req, cpu_name:req, cpu_flush:req
 		.type	__\name\()_proc_info,#object
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/proc-arm740.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/proc-arm740.S
@@ -128,7 +128,7 @@
 
 	.align
 
-	.section ".proc.info.init", #alloc
+	.section ".proc.info.init", "a"
 	.type	__arm740_proc_info,#object
 __arm740_proc_info:
 	.long	0x41807400
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/proc-arm7tdmi.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/proc-arm7tdmi.S
@@ -72,7 +72,7 @@
 
 		.align
 
-		.section ".proc.info.init", #alloc
+		.section ".proc.info.init", "a"
 
 .macro arm7tdmi_proc_info name:req, cpu_val:req, cpu_mask:req, cpu_name:req, \
 	extra_hwcaps=0
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/proc-arm920.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/proc-arm920.S
@@ -434,7 +434,7 @@
 
 	.align
 
-	.section ".proc.info.init", #alloc
+	.section ".proc.info.init", "a"
 
 	.type	__arm920_proc_info,#object
 __arm920_proc_info:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/proc-arm922.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/proc-arm922.S
@@ -412,7 +412,7 @@
 
 	.align
 
-	.section ".proc.info.init", #alloc
+	.section ".proc.info.init", "a"
 
 	.type	__arm922_proc_info,#object
 __arm922_proc_info:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/proc-arm925.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/proc-arm925.S
@@ -477,7 +477,7 @@
 
 	.align
 
-	.section ".proc.info.init", #alloc
+	.section ".proc.info.init", "a"
 
 .macro arm925_proc_info name:req, cpu_val:req, cpu_mask:req, cpu_name:req, cache
 	.type	__\name\()_proc_info,#object
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/proc-arm926.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/proc-arm926.S
@@ -131,7 +131,7 @@
 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
 	mcr	p15, 0, ip, c7, c6, 0		@ invalidate D cache
 #else
-1:	mrc	p15, 0, r15, c7, c14, 3 	@ test,clean,invalidate
+1:	mrc	p15, 0, APSR_nzcv, c7, c14, 3 	@ test,clean,invalidate
 	bne	1b
 #endif
 	tst	r2, #VM_EXEC
@@ -358,7 +358,7 @@
 	mcr	p15, 0, ip, c7, c6, 0		@ invalidate D cache
 #else
 @ && 'Clean & Invalidate whole DCache'
-1:	mrc	p15, 0, r15, c7, c14, 3 	@ test,clean,invalidate
+1:	mrc	p15, 0, APSR_nzcv, c7, c14, 3 	@ test,clean,invalidate
 	bne	1b
 #endif
 	mcr	p15, 0, ip, c7, c5, 0		@ invalidate I cache
@@ -460,7 +460,7 @@
 
 	.align
 
-	.section ".proc.info.init", #alloc
+	.section ".proc.info.init", "a"
 
 	.type	__arm926_proc_info,#object
 __arm926_proc_info:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/proc-arm940.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/proc-arm940.S
@@ -340,7 +340,7 @@
 
 	.align
 
-	.section ".proc.info.init", #alloc
+	.section ".proc.info.init", "a"
 
 	.type	__arm940_proc_info,#object
 __arm940_proc_info:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/proc-arm946.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/proc-arm946.S
@@ -395,7 +395,7 @@
 
 	.align
 
-	.section ".proc.info.init", #alloc
+	.section ".proc.info.init", "a"
 	.type	__arm946_proc_info,#object
 __arm946_proc_info:
 	.long	0x41009460
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/proc-arm9tdmi.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/proc-arm9tdmi.S
@@ -66,7 +66,7 @@
 
 		.align
 
-		.section ".proc.info.init", #alloc
+		.section ".proc.info.init", "a"
 
 .macro arm9tdmi_proc_info name:req, cpu_val:req, cpu_mask:req, cpu_name:req
 		.type	__\name\()_proc_info, #object
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/proc-fa526.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/proc-fa526.S
@@ -185,7 +185,7 @@
 
 	.align
 
-	.section ".proc.info.init", #alloc
+	.section ".proc.info.init", "a"
 
 	.type	__fa526_proc_info,#object
 __fa526_proc_info:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/proc-feroceon.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/proc-feroceon.S
@@ -571,7 +571,7 @@
 
 	.align
 
-	.section ".proc.info.init", #alloc
+	.section ".proc.info.init", "a"
 
 .macro feroceon_proc_info name:req, cpu_val:req, cpu_mask:req, cpu_name:req, cache:req
 	.type	__\name\()_proc_info,#object
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/proc-macros.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/proc-macros.S
@@ -5,6 +5,7 @@
  *  VMA_VM_FLAGS
  *  VM_EXEC
  */
+#include <linux/const.h>
 #include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 
@@ -30,7 +31,7 @@
  * act_mm - get current->active_mm
  */
 	.macro	act_mm, rd
-	bic	\rd, sp, #8128
+	bic	\rd, sp, #(THREAD_SIZE - 1) & ~63
 	bic	\rd, \rd, #63
 	ldr	\rd, [\rd, #TI_TASK]
 	.if (TSK_ACTIVE_MM > IMM12_MASK)
@@ -341,6 +342,7 @@
 
 .macro define_tlb_functions name:req, flags_up:req, flags_smp
 	.type	\name\()_tlb_fns, #object
+	.align 2
 ENTRY(\name\()_tlb_fns)
 	.long	\name\()_flush_user_tlb_range
 	.long	\name\()_flush_kern_tlb_range
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/proc-mohawk.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/proc-mohawk.S
@@ -416,7 +416,7 @@
 
 	.align
 
-	.section ".proc.info.init", #alloc
+	.section ".proc.info.init", "a"
 
 	.type	__88sv331x_proc_info,#object
 __88sv331x_proc_info:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/proc-sa110.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/proc-sa110.S
@@ -196,7 +196,7 @@
 
 	.align
 
-	.section ".proc.info.init", #alloc
+	.section ".proc.info.init", "a"
 
 	.type	__sa110_proc_info,#object
 __sa110_proc_info:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/proc-sa1100.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/proc-sa1100.S
@@ -239,7 +239,7 @@
 
 	.align
 
-	.section ".proc.info.init", #alloc
+	.section ".proc.info.init", "a"
 
 .macro sa1100_proc_info name:req, cpu_val:req, cpu_mask:req, cpu_name:req
 	.type	__\name\()_proc_info,#object
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/proc-v6.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/proc-v6.S
@@ -261,7 +261,7 @@
 	string	cpu_elf_name, "v6"
 	.align
 
-	.section ".proc.info.init", #alloc
+	.section ".proc.info.init", "a"
 
 	/*
 	 * Match any ARMv6 processor core.
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/proc-v7-bugs.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/proc-v7-bugs.c
@@ -7,8 +7,35 @@
 #include <asm/cp15.h>
 #include <asm/cputype.h>
 #include <asm/proc-fns.h>
+#include <asm/spectre.h>
 #include <asm/system_misc.h>
 
+#ifdef CONFIG_ARM_PSCI
+static int __maybe_unused spectre_v2_get_cpu_fw_mitigation_state(void)
+{
+	struct arm_smccc_res res;
+
+	arm_smccc_1_1_invoke(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
+			     ARM_SMCCC_ARCH_WORKAROUND_1, &res);
+
+	switch ((int)res.a0) {
+	case SMCCC_RET_SUCCESS:
+		return SPECTRE_MITIGATED;
+
+	case SMCCC_ARCH_WORKAROUND_RET_UNAFFECTED:
+		return SPECTRE_UNAFFECTED;
+
+	default:
+		return SPECTRE_VULNERABLE;
+	}
+}
+#else
+static int __maybe_unused spectre_v2_get_cpu_fw_mitigation_state(void)
+{
+	return SPECTRE_VULNERABLE;
+}
+#endif
+
 #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
 DEFINE_PER_CPU(harden_branch_predictor_fn_t, harden_branch_predictor_fn);
 
@@ -37,13 +64,60 @@
 	arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL);
 }
 
-static void cpu_v7_spectre_init(void)
+static unsigned int spectre_v2_install_workaround(unsigned int method)
 {
 	const char *spectre_v2_method = NULL;
 	int cpu = smp_processor_id();
 
 	if (per_cpu(harden_branch_predictor_fn, cpu))
-		return;
+		return SPECTRE_MITIGATED;
+
+	switch (method) {
+	case SPECTRE_V2_METHOD_BPIALL:
+		per_cpu(harden_branch_predictor_fn, cpu) =
+			harden_branch_predictor_bpiall;
+		spectre_v2_method = "BPIALL";
+		break;
+
+	case SPECTRE_V2_METHOD_ICIALLU:
+		per_cpu(harden_branch_predictor_fn, cpu) =
+			harden_branch_predictor_iciallu;
+		spectre_v2_method = "ICIALLU";
+		break;
+
+	case SPECTRE_V2_METHOD_HVC:
+		per_cpu(harden_branch_predictor_fn, cpu) =
+			call_hvc_arch_workaround_1;
+		cpu_do_switch_mm = cpu_v7_hvc_switch_mm;
+		spectre_v2_method = "hypervisor";
+		break;
+
+	case SPECTRE_V2_METHOD_SMC:
+		per_cpu(harden_branch_predictor_fn, cpu) =
+			call_smc_arch_workaround_1;
+		cpu_do_switch_mm = cpu_v7_smc_switch_mm;
+		spectre_v2_method = "firmware";
+		break;
+	}
+
+	if (spectre_v2_method)
+		pr_info("CPU%u: Spectre v2: using %s workaround\n",
+			smp_processor_id(), spectre_v2_method);
+
+	return SPECTRE_MITIGATED;
+}
+#else
+static unsigned int spectre_v2_install_workaround(unsigned int method)
+{
+	pr_info_once("Spectre V2: workarounds disabled by configuration\n");
+
+	return SPECTRE_VULNERABLE;
+}
+#endif
+
+static void cpu_v7_spectre_v2_init(void)
+{
+	unsigned int state, method = 0;
 
 	switch (read_cpuid_part()) {
 	case ARM_CPU_PART_CORTEX_A8:
@@ -52,29 +126,37 @@
 	case ARM_CPU_PART_CORTEX_A17:
 	case ARM_CPU_PART_CORTEX_A73:
 	case ARM_CPU_PART_CORTEX_A75:
-		per_cpu(harden_branch_predictor_fn, cpu) =
-			harden_branch_predictor_bpiall;
-		spectre_v2_method = "BPIALL";
+		state = SPECTRE_MITIGATED;
+		method = SPECTRE_V2_METHOD_BPIALL;
 		break;
 
 	case ARM_CPU_PART_CORTEX_A15:
 	case ARM_CPU_PART_BRAHMA_B15:
-		per_cpu(harden_branch_predictor_fn, cpu) =
-			harden_branch_predictor_iciallu;
-		spectre_v2_method = "ICIALLU";
+		state = SPECTRE_MITIGATED;
+		method = SPECTRE_V2_METHOD_ICIALLU;
+		break;
+
+	case ARM_CPU_PART_BRAHMA_B53:
+		/* Requires no workaround */
+		state = SPECTRE_UNAFFECTED;
 		break;
 
-#ifdef CONFIG_ARM_PSCI
 	default:
 		/* Other ARM CPUs require no workaround */
-		if (read_cpuid_implementor() == ARM_CPU_IMP_ARM)
+		if (read_cpuid_implementor() == ARM_CPU_IMP_ARM) {
+			state = SPECTRE_UNAFFECTED;
 			break;
+		}
 		/* fallthrough */
-		/* Cortex A57/A72 require firmware workaround */
+	/* Cortex A57/A72 require firmware workaround */
 	case ARM_CPU_PART_CORTEX_A57:
 	case ARM_CPU_PART_CORTEX_A72: {
 		struct arm_smccc_res res;
 
+		state = spectre_v2_get_cpu_fw_mitigation_state();
+		if (state != SPECTRE_MITIGATED)
+			break;
+
 		if (psci_ops.smccc_version == SMCCC_VERSION_1_0)
 			break;
 
@@ -84,10 +166,7 @@
 					  ARM_SMCCC_ARCH_WORKAROUND_1, &res);
 			if ((int)res.a0 != 0)
 				break;
-			per_cpu(harden_branch_predictor_fn, cpu) =
-				call_hvc_arch_workaround_1;
-			cpu_do_switch_mm = cpu_v7_hvc_switch_mm;
-			spectre_v2_method = "hypervisor";
+			method = SPECTRE_V2_METHOD_HVC;
 			break;
 
 		case PSCI_CONDUIT_SMC:
@@ -95,29 +174,97 @@
 					  ARM_SMCCC_ARCH_WORKAROUND_1, &res);
 			if ((int)res.a0 != 0)
 				break;
-			per_cpu(harden_branch_predictor_fn, cpu) =
-				call_smc_arch_workaround_1;
-			cpu_do_switch_mm = cpu_v7_smc_switch_mm;
-			spectre_v2_method = "firmware";
+			method = SPECTRE_V2_METHOD_SMC;
 			break;
 
 		default:
+			state = SPECTRE_VULNERABLE;
 			break;
 		}
 	}
-#endif
 	}
 
-	if (spectre_v2_method)
-		pr_info("CPU%u: Spectre v2: using %s workaround\n",
-			smp_processor_id(), spectre_v2_method);
+	if (state == SPECTRE_MITIGATED)
+		state = spectre_v2_install_workaround(method);
+
+	spectre_v2_update_state(state, method);
+}
+
+#ifdef CONFIG_HARDEN_BRANCH_HISTORY
+static int spectre_bhb_method;
+
+static const char *spectre_bhb_method_name(int method)
+{
+	switch (method) {
+	case SPECTRE_V2_METHOD_LOOP8:
+		return "loop";
+
+	case SPECTRE_V2_METHOD_BPIALL:
+		return "BPIALL";
+
+	default:
+		return "unknown";
+	}
+}
+
+static int spectre_bhb_install_workaround(int method)
+{
+	if (spectre_bhb_method != method) {
+		if (spectre_bhb_method) {
+			pr_err("CPU%u: Spectre BHB: method disagreement, system vulnerable\n",
+			       smp_processor_id());
+
+			return SPECTRE_VULNERABLE;
+		}
+
+		if (spectre_bhb_update_vectors(method) == SPECTRE_VULNERABLE)
+			return SPECTRE_VULNERABLE;
+
+		spectre_bhb_method = method;
+
+		pr_info("CPU%u: Spectre BHB: enabling %s workaround for all CPUs\n",
+			smp_processor_id(), spectre_bhb_method_name(method));
+	}
+
+	return SPECTRE_MITIGATED;
 }
 #else
-static void cpu_v7_spectre_init(void)
+static int spectre_bhb_install_workaround(int method)
 {
+	return SPECTRE_VULNERABLE;
 }
 #endif
 
+static void cpu_v7_spectre_bhb_init(void)
+{
+	unsigned int state, method = 0;
+
+	switch (read_cpuid_part()) {
+	case ARM_CPU_PART_CORTEX_A15:
+	case ARM_CPU_PART_BRAHMA_B15:
+	case ARM_CPU_PART_CORTEX_A57:
+	case ARM_CPU_PART_CORTEX_A72:
+		state = SPECTRE_MITIGATED;
+		method = SPECTRE_V2_METHOD_LOOP8;
+		break;
+
+	case ARM_CPU_PART_CORTEX_A73:
+	case ARM_CPU_PART_CORTEX_A75:
+		state = SPECTRE_MITIGATED;
+		method = SPECTRE_V2_METHOD_BPIALL;
+		break;
+
+	default:
+		state = SPECTRE_UNAFFECTED;
+		break;
+	}
+
+	if (state == SPECTRE_MITIGATED)
+		state = spectre_bhb_install_workaround(method);
+
+	spectre_v2_update_state(state, method);
+}
+
 static __maybe_unused bool cpu_v7_check_auxcr_set(bool *warned,
 						  u32 mask, const char *msg)
 {
@@ -146,16 +293,18 @@
 void cpu_v7_ca8_ibe(void)
 {
 	if (check_spectre_auxcr(this_cpu_ptr(&spectre_warned), BIT(6)))
-		cpu_v7_spectre_init();
+		cpu_v7_spectre_v2_init();
 }
 
 void cpu_v7_ca15_ibe(void)
 {
 	if (check_spectre_auxcr(this_cpu_ptr(&spectre_warned), BIT(0)))
-		cpu_v7_spectre_init();
+		cpu_v7_spectre_v2_init();
+	cpu_v7_spectre_bhb_init();
 }
 
 void cpu_v7_bugs_init(void)
 {
-	cpu_v7_spectre_init();
+	cpu_v7_spectre_v2_init();
+	cpu_v7_spectre_bhb_init();
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/proc-v7.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/proc-v7.S
@@ -644,7 +644,7 @@
 	string	cpu_elf_name, "v7"
 	.align
 
-	.section ".proc.info.init", #alloc
+	.section ".proc.info.init", "a"
 
 	/*
 	 * Standard v7 proc info content
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/proc-v7m.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/proc-v7m.S
@@ -93,7 +93,7 @@
 	ret	lr
 ENDPROC(cpu_cm7_proc_fin)
 
-	.section ".init.text", #alloc, #execinstr
+	.section ".init.text", "ax"
 
 __v7m_cm7_setup:
 	mov	r8, #(V7M_SCB_CCR_DC | V7M_SCB_CCR_IC| V7M_SCB_CCR_BP)
@@ -177,7 +177,7 @@
 	string cpu_elf_name "v7m"
 	string cpu_v7m_name "ARMv7-M"
 
-	.section ".proc.info.init", #alloc
+	.section ".proc.info.init", "a"
 
 .macro __v7m_proc name, initfunc, cache_fns = nop_cache_fns, hwcaps = 0,  proc_fns = v7m_processor_functions
 	.long	0			/* proc_info_list.__cpu_mm_mmu_flags */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/proc-xsc3.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/proc-xsc3.S
@@ -496,7 +496,7 @@
 
 	.align
 
-	.section ".proc.info.init", #alloc
+	.section ".proc.info.init", "a"
 
 .macro xsc3_proc_info name:req, cpu_val:req, cpu_mask:req
 	.type	__\name\()_proc_info,#object
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/proc-xscale.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/proc-xscale.S
@@ -610,7 +610,7 @@
 
 	.align
 
-	.section ".proc.info.init", #alloc
+	.section ".proc.info.init", "a"
 
 .macro xscale_proc_info name:req, cpu_val:req, cpu_mask:req, cpu_name:req, cache
 	.type	__\name\()_proc_info,#object
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/mm/pv-fixup-asm.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/mm/pv-fixup-asm.S
@@ -39,8 +39,8 @@
 
 	/* Update level 2 entries for the boot data */
 	add	r7, r2, #0x1000
-	add	r7, r7, r3, lsr #SECTION_SHIFT - L2_ORDER
-	bic	r7, r7, #(1 << L2_ORDER) - 1
+	movw	r3, #FDT_FIXED_BASE >> (SECTION_SHIFT - L2_ORDER)
+	add	r7, r7, r3
 	ldrd	r4, r5, [r7]
 	adds	r4, r4, r0
 	adc	r5, r5, r1
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/net/bpf_jit_32.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/net/bpf_jit_32.c
@@ -36,6 +36,10 @@
  *                        +-----+
  *                        |RSVD | JIT scratchpad
  * current ARM_SP =>      +-----+ <= (BPF_FP - STACK_SIZE + SCRATCH_SIZE)
+ *                        | ... | caller-saved registers
+ *                        +-----+
+ *                        | ... | arguments passed on stack
+ * ARM_SP during call =>  +-----|
  *                        |     |
  *                        | ... | Function call stack
  *                        |     |
@@ -63,6 +67,12 @@
  *
  * When popping registers off the stack at the end of a BPF function, we
  * reference them via the current ARM_FP register.
+ *
+ * Some eBPF operations are implemented via a call to a helper function.
+ * Such calls are "invisible" in the eBPF code, so it is up to the calling
+ * program to preserve any caller-saved ARM registers during the call. The
+ * JIT emits code to push and pop those registers onto the stack, immediately
+ * above the callee stack frame.
  */
 #define CALLEE_MASK	(1 << ARM_R4 | 1 << ARM_R5 | 1 << ARM_R6 | \
 			 1 << ARM_R7 | 1 << ARM_R8 | 1 << ARM_R9 | \
@@ -70,6 +80,8 @@
 #define CALLEE_PUSH_MASK (CALLEE_MASK | 1 << ARM_LR)
 #define CALLEE_POP_MASK  (CALLEE_MASK | 1 << ARM_PC)
 
+#define CALLER_MASK	(1 << ARM_R0 | 1 << ARM_R1 | 1 << ARM_R2 | 1 << ARM_R3)
+
 enum {
 	/* Stack layout - these are offsets from (top of stack - 4) */
 	BPF_R2_HI,
@@ -464,6 +476,7 @@
 
 static inline void emit_udivmod(u8 rd, u8 rm, u8 rn, struct jit_ctx *ctx, u8 op)
 {
+	const int exclude_mask = BIT(ARM_R0) | BIT(ARM_R1);
 	const s8 *tmp = bpf2a32[TMP_REG_1];
 
 #if __LINUX_ARM_ARCH__ == 7
@@ -495,11 +508,17 @@
 		emit(ARM_MOV_R(ARM_R0, rm), ctx);
 	}
 
+	/* Push caller-saved registers on stack */
+	emit(ARM_PUSH(CALLER_MASK & ~exclude_mask), ctx);
+
 	/* Call appropriate function */
 	emit_mov_i(ARM_IP, op == BPF_DIV ?
 		   (u32)jit_udiv32 : (u32)jit_mod32, ctx);
 	emit_blx_r(ARM_IP, ctx);
 
+	/* Restore caller-saved registers from stack */
+	emit(ARM_POP(CALLER_MASK & ~exclude_mask), ctx);
+
 	/* Save return value */
 	if (rd != ARM_R0)
 		emit(ARM_MOV_R(rd, ARM_R0), ctx);
@@ -929,7 +948,11 @@
 	rd = arm_bpf_get_reg64(dst, tmp, ctx);
 
 	/* Do LSR operation */
-	if (val < 32) {
+	if (val == 0) {
+		/* An immediate value of 0 encodes a shift amount of 32
+		 * for LSR. To shift by 0, don't do anything.
+		 */
+	} else if (val < 32) {
 		emit(ARM_MOV_SI(tmp2[1], rd[1], SRTYPE_LSR, val), ctx);
 		emit(ARM_ORR_SI(rd[1], tmp2[1], rd[0], SRTYPE_ASL, 32 - val), ctx);
 		emit(ARM_MOV_SI(rd[0], rd[0], SRTYPE_LSR, val), ctx);
@@ -955,7 +978,11 @@
 	rd = arm_bpf_get_reg64(dst, tmp, ctx);
 
 	/* Do ARSH operation */
-	if (val < 32) {
+	if (val == 0) {
+		/* An immediate value of 0 encodes a shift amount of 32
+		 * for ASR. To shift by 0, don't do anything.
+		 */
+	} else if (val < 32) {
 		emit(ARM_MOV_SI(tmp2[1], rd[1], SRTYPE_LSR, val), ctx);
 		emit(ARM_ORR_SI(rd[1], tmp2[1], rd[0], SRTYPE_ASL, 32 - val), ctx);
 		emit(ARM_MOV_SI(rd[0], rd[0], SRTYPE_ASR, val), ctx);
@@ -992,21 +1019,35 @@
 	arm_bpf_put_reg32(dst_hi, rd[0], ctx);
 }
 
+static bool is_ldst_imm(s16 off, const u8 size)
+{
+	s16 off_max = 0;
+
+	switch (size) {
+	case BPF_B:
+	case BPF_W:
+		off_max = 0xfff;
+		break;
+	case BPF_H:
+		off_max = 0xff;
+		break;
+	case BPF_DW:
+		/* Need to make sure off+4 does not overflow. */
+		off_max = 0xfff - 4;
+		break;
+	}
+	return -off_max <= off && off <= off_max;
+}
+
 /* *(size *)(dst + off) = src */
 static inline void emit_str_r(const s8 dst, const s8 src[],
-			      s32 off, struct jit_ctx *ctx, const u8 sz){
+			      s16 off, struct jit_ctx *ctx, const u8 sz){
 	const s8 *tmp = bpf2a32[TMP_REG_1];
-	s32 off_max;
 	s8 rd;
 
 	rd = arm_bpf_get_reg32(dst, tmp[1], ctx);
 
-	if (sz == BPF_H)
-		off_max = 0xff;
-	else
-		off_max = 0xfff;
-
-	if (off < 0 || off > off_max) {
+	if (!is_ldst_imm(off, sz)) {
 		emit_a32_mov_i(tmp[0], off, ctx);
 		emit(ARM_ADD_R(tmp[0], tmp[0], rd), ctx);
 		rd = tmp[0];
@@ -1035,18 +1076,12 @@
 
 /* dst = *(size*)(src + off) */
 static inline void emit_ldx_r(const s8 dst[], const s8 src,
-			      s32 off, struct jit_ctx *ctx, const u8 sz){
+			      s16 off, struct jit_ctx *ctx, const u8 sz){
 	const s8 *tmp = bpf2a32[TMP_REG_1];
 	const s8 *rd = is_stacked(dst_lo) ? tmp : dst;
 	s8 rm = src;
-	s32 off_max;
-
-	if (sz == BPF_H)
-		off_max = 0xff;
-	else
-		off_max = 0xfff;
 
-	if (off < 0 || off > off_max) {
+	if (!is_ldst_imm(off, sz)) {
 		emit_a32_mov_i(tmp[0], off, ctx);
 		emit(ARM_ADD_R(tmp[0], tmp[0], src), ctx);
 		rm = tmp[0];
@@ -1586,6 +1621,9 @@
 		rn = arm_bpf_get_reg32(src_lo, tmp2[1], ctx);
 		emit_ldx_r(dst, rn, off, ctx, BPF_SIZE(code));
 		break;
+	/* speculation barrier */
+	case BPF_ST | BPF_NOSPEC:
+		break;
 	/* ST: *(size *)(dst + off) = imm */
 	case BPF_ST | BPF_MEM | BPF_W:
 	case BPF_ST | BPF_MEM | BPF_H:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/nwfpe/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/nwfpe/Makefile
@@ -11,3 +11,9 @@
 				   entry.o
 
 nwfpe-$(CONFIG_FPE_NWFPE_XP)	+= extended_cpdo.o
+
+# Try really hard to avoid generating calls to __aeabi_uldivmod() from
+# float64_rem() due to loop elision.
+ifdef CONFIG_CC_IS_CLANG
+CFLAGS_softfloat.o	+= -mllvm -replexitval=never
+endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/plat-samsung/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/plat-samsung/Kconfig
@@ -241,6 +241,7 @@
 	depends on PM && DEBUG_KERNEL
 	depends on PLAT_S3C24XX || ARCH_S3C64XX || ARCH_S5PV210
 	depends on DEBUG_EXYNOS_UART || DEBUG_S3C24XX_UART || DEBUG_S3C2410_UART
+	depends on DEBUG_LL && MMU
 	help
 	  Say Y here if you want verbose debugging from the PM Suspend and
 	  Resume code. See <file:Documentation/arm/samsung-s3c24xx/suspend.rst>
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/probes/decode.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/probes/decode.h
@@ -14,6 +14,7 @@
 #include <linux/types.h>
 #include <linux/stddef.h>
 #include <asm/probes.h>
+#include <asm/ptrace.h>
 #include <asm/kprobes.h>
 
 void __init arm_probes_decode_init(void);
@@ -35,31 +36,6 @@
 #endif
 
 
-/*
- * Update ITSTATE after normal execution of an IT block instruction.
- *
- * The 8 IT state bits are split into two parts in CPSR:
- *	ITSTATE<1:0> are in CPSR<26:25>
- *	ITSTATE<7:2> are in CPSR<15:10>
- */
-static inline unsigned long it_advance(unsigned long cpsr)
-	{
-	if ((cpsr & 0x06000400) == 0) {
-		/* ITSTATE<2:0> == 0 means end of IT block, so clear IT state */
-		cpsr &= ~PSR_IT_MASK;
-	} else {
-		/* We need to shift left ITSTATE<4:0> */
-		const unsigned long mask = 0x06001c00;  /* Mask ITSTATE<4:0> */
-		unsigned long it = cpsr & mask;
-		it <<= 1;
-		it |= it >> (27 - 10);  /* Carry ITSTATE<2> to correct place */
-		it &= mask;
-		cpsr &= ~mask;
-		cpsr |= it;
-	}
-	return cpsr;
-}
-
 static inline void __kprobes bx_write_pc(long pcv, struct pt_regs *regs)
 {
 	long cpsr = regs->ARM_cpsr;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/probes/kprobes/checkers-common.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/probes/kprobes/checkers-common.c
@@ -40,7 +40,7 @@
  * Different from other insn uses imm8, the real addressing offset of
  * STRD in T32 encoding should be imm8 * 4. See ARMARM description.
  */
-enum probes_insn checker_stack_use_t32strd(probes_opcode_t insn,
+static enum probes_insn checker_stack_use_t32strd(probes_opcode_t insn,
 		struct arch_probes_insn *asi,
 		const struct decode_header *h)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/probes/kprobes/core.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/probes/kprobes/core.c
@@ -231,7 +231,7 @@
  * kprobe, and that level is reserved for user kprobe handlers, so we can't
  * risk encountering a new kprobe in an interrupt handler.
  */
-void __kprobes kprobe_handler(struct pt_regs *regs)
+static void __kprobes kprobe_handler(struct pt_regs *regs)
 {
 	struct kprobe *p, *cur;
 	struct kprobe_ctlblk *kcb;
@@ -534,7 +534,7 @@
 
 #endif /* !CONFIG_THUMB2_KERNEL */
 
-int __init arch_init_kprobes()
+int __init arch_init_kprobes(void)
 {
 	arm_probes_decode_init();
 #ifdef CONFIG_THUMB2_KERNEL
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/probes/kprobes/opt-arm.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/probes/kprobes/opt-arm.c
@@ -85,21 +85,21 @@
 			"optprobe_template_end:\n");
 
 #define TMPL_VAL_IDX \
-	((unsigned long *)&optprobe_template_val - (unsigned long *)&optprobe_template_entry)
+	((unsigned long *)optprobe_template_val - (unsigned long *)optprobe_template_entry)
 #define TMPL_CALL_IDX \
-	((unsigned long *)&optprobe_template_call - (unsigned long *)&optprobe_template_entry)
+	((unsigned long *)optprobe_template_call - (unsigned long *)optprobe_template_entry)
 #define TMPL_END_IDX \
-	((unsigned long *)&optprobe_template_end - (unsigned long *)&optprobe_template_entry)
+	((unsigned long *)optprobe_template_end - (unsigned long *)optprobe_template_entry)
 #define TMPL_ADD_SP \
-	((unsigned long *)&optprobe_template_add_sp - (unsigned long *)&optprobe_template_entry)
+	((unsigned long *)optprobe_template_add_sp - (unsigned long *)optprobe_template_entry)
 #define TMPL_SUB_SP \
-	((unsigned long *)&optprobe_template_sub_sp - (unsigned long *)&optprobe_template_entry)
+	((unsigned long *)optprobe_template_sub_sp - (unsigned long *)optprobe_template_entry)
 #define TMPL_RESTORE_BEGIN \
-	((unsigned long *)&optprobe_template_restore_begin - (unsigned long *)&optprobe_template_entry)
+	((unsigned long *)optprobe_template_restore_begin - (unsigned long *)optprobe_template_entry)
 #define TMPL_RESTORE_ORIGN_INSN \
-	((unsigned long *)&optprobe_template_restore_orig_insn - (unsigned long *)&optprobe_template_entry)
+	((unsigned long *)optprobe_template_restore_orig_insn - (unsigned long *)optprobe_template_entry)
 #define TMPL_RESTORE_END \
-	((unsigned long *)&optprobe_template_restore_end - (unsigned long *)&optprobe_template_entry)
+	((unsigned long *)optprobe_template_restore_end - (unsigned long *)optprobe_template_entry)
 
 /*
  * ARM can always optimize an instruction when using ARM ISA, except
@@ -145,8 +145,6 @@
 	}
 }
 
-extern void kprobe_handler(struct pt_regs *regs);
-
 static void
 optimized_callback(struct optimized_kprobe *op, struct pt_regs *regs)
 {
@@ -234,7 +232,7 @@
 	}
 
 	/* Copy arch-dep-instance from template. */
-	memcpy(code, (unsigned long *)&optprobe_template_entry,
+	memcpy(code, (unsigned long *)optprobe_template_entry,
 			TMPL_END_IDX * sizeof(kprobe_opcode_t));
 
 	/* Adjust buffer according to instruction. */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/probes/kprobes/test-core.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/probes/kprobes/test-core.c
@@ -720,7 +720,7 @@
 	[REG_TYPE_NOSPPCX]	= COVERAGE_ANY_REG | COVERAGE_SP,
 };
 
-unsigned coverage_start_registers(const struct decode_header *h)
+static unsigned coverage_start_registers(const struct decode_header *h)
 {
 	unsigned regs = 0;
 	int i;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/probes/kprobes/test-core.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/probes/kprobes/test-core.h
@@ -453,3 +453,7 @@
 #else
 void kprobe_arm_test_cases(void);
 #endif
+
+void __kprobes_test_case_start(void);
+void __kprobes_test_case_end_16(void);
+void __kprobes_test_case_end_32(void);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/probes/kprobes/test-thumb.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/probes/kprobes/test-thumb.c
@@ -441,21 +441,21 @@
 		"3:	mvn	r0, r0	\n\t"
 		"2:	nop		\n\t")
 
-	TEST_RX("tbh	[pc, r",7, (9f-(1f+4))>>1,"]",
+	TEST_RX("tbh	[pc, r",7, (9f-(1f+4))>>1,", lsl #1]",
 		"9:			\n\t"
 		".short	(2f-1b-4)>>1	\n\t"
 		".short	(3f-1b-4)>>1	\n\t"
 		"3:	mvn	r0, r0	\n\t"
 		"2:	nop		\n\t")
 
-	TEST_RX("tbh	[pc, r",12, ((9f-(1f+4))>>1)+1,"]",
+	TEST_RX("tbh	[pc, r",12, ((9f-(1f+4))>>1)+1,", lsl #1]",
 		"9:			\n\t"
 		".short	(2f-1b-4)>>1	\n\t"
 		".short	(3f-1b-4)>>1	\n\t"
 		"3:	mvn	r0, r0	\n\t"
 		"2:	nop		\n\t")
 
-	TEST_RRX("tbh	[r",1,9f, ", r",14,1,"]",
+	TEST_RRX("tbh	[r",1,9f, ", r",14,1,", lsl #1]",
 		"9:			\n\t"
 		".short	(2f-1b-4)>>1	\n\t"
 		".short	(3f-1b-4)>>1	\n\t"
@@ -468,10 +468,10 @@
 
 	TEST_UNSUPPORTED("strexb	r0, r1, [r2]")
 	TEST_UNSUPPORTED("strexh	r0, r1, [r2]")
-	TEST_UNSUPPORTED("strexd	r0, r1, [r2]")
+	TEST_UNSUPPORTED("strexd	r0, r1, r2, [r2]")
 	TEST_UNSUPPORTED("ldrexb	r0, [r1]")
 	TEST_UNSUPPORTED("ldrexh	r0, [r1]")
-	TEST_UNSUPPORTED("ldrexd	r0, [r1]")
+	TEST_UNSUPPORTED("ldrexd	r0, r1, [r1]")
 
 	TEST_GROUP("Data-processing (shifted register) and (modified immediate)")
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/probes/uprobes/core.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/probes/uprobes/core.c
@@ -204,7 +204,7 @@
 static struct undef_hook uprobes_arm_break_hook = {
 	.instr_mask	= 0x0fffffff,
 	.instr_val	= (UPROBE_SWBP_ARM_INSN & 0x0fffffff),
-	.cpsr_mask	= MODE_MASK,
+	.cpsr_mask	= (PSR_T_BIT | MODE_MASK),
 	.cpsr_val	= USR_MODE,
 	.fn		= uprobe_trap_handler,
 };
@@ -212,7 +212,7 @@
 static struct undef_hook uprobes_arm_ss_hook = {
 	.instr_mask	= 0x0fffffff,
 	.instr_val	= (UPROBE_SS_ARM_INSN & 0x0fffffff),
-	.cpsr_mask	= MODE_MASK,
+	.cpsr_mask	= (PSR_T_BIT | MODE_MASK),
 	.cpsr_val	= USR_MODE,
 	.fn		= uprobe_trap_handler,
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/vfp/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/vfp/Makefile
@@ -8,6 +8,4 @@
 # ccflags-y := -DDEBUG
 # asflags-y := -DDEBUG
 
-KBUILD_AFLAGS	:=$(KBUILD_AFLAGS:-msoft-float=-Wa,-mfpu=softvfp+vfp -mfloat-abi=soft)
-
 obj-y		+= vfpmodule.o entry.o vfphw.o vfpsingle.o vfpdouble.o
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/vfp/entry.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/vfp/entry.S
@@ -37,20 +37,3 @@
 	.align	2
 .LCvfp:
 	.word	vfp_vector
-
-@ This code is called if the VFP does not exist. It needs to flag the
-@ failure to the VFP initialisation code.
-
-	__INIT
-ENTRY(vfp_testing_entry)
-	dec_preempt_count_ti r10, r4
-	ldr	r0, VFP_arch_address
-	str	r0, [r0]		@ set to non-zero value
-	ret	r9			@ we have handled the fault
-ENDPROC(vfp_testing_entry)
-
-	.align	2
-VFP_arch_address:
-	.word	VFP_arch
-
-	__FINIT
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/vfp/vfphw.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/vfp/vfphw.S
@@ -78,11 +78,6 @@
 ENTRY(vfp_support_entry)
 	DBGSTR3	"instr %08x pc %08x state %p", r0, r2, r10
 
-	ldr	r3, [sp, #S_PSR]	@ Neither lazy restore nor FP exceptions
-	and	r3, r3, #MODE_MASK	@ are supported in kernel mode
-	teq	r3, #USR_MODE
-	bne	vfp_kmode_exception	@ Returns through lr
-
 	VFPFMRX	r1, FPEXC		@ Is the VFP enabled?
 	DBGSTR1	"fpexc %08x", r1
 	tst	r1, #FPEXC_EN
@@ -258,11 +253,14 @@
 
 ENTRY(vfp_get_float)
 	tbl_branch r0, r3, #3
+	.fpu	vfpv2
 	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
-1:	mrc	p10, 0, r0, c\dr, c0, 0	@ fmrs	r0, s0
+1:	vmov	r0, s\dr
 	ret	lr
 	.org	1b + 8
-1:	mrc	p10, 0, r0, c\dr, c0, 4	@ fmrs	r0, s1
+	.endr
+	.irp	dr,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
+1:	vmov	r0, s\dr
 	ret	lr
 	.org	1b + 8
 	.endr
@@ -270,11 +268,14 @@
 
 ENTRY(vfp_put_float)
 	tbl_branch r1, r3, #3
+	.fpu	vfpv2
 	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
-1:	mcr	p10, 0, r0, c\dr, c0, 0	@ fmsr	r0, s0
+1:	vmov	s\dr, r0
 	ret	lr
 	.org	1b + 8
-1:	mcr	p10, 0, r0, c\dr, c0, 4	@ fmsr	r0, s1
+	.endr
+	.irp	dr,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
+1:	vmov	s\dr, r0
 	ret	lr
 	.org	1b + 8
 	.endr
@@ -282,15 +283,17 @@
 
 ENTRY(vfp_get_double)
 	tbl_branch r0, r3, #3
+	.fpu	vfpv2
 	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
-1:	fmrrd	r0, r1, d\dr
+1:	vmov	r0, r1, d\dr
 	ret	lr
 	.org	1b + 8
 	.endr
 #ifdef CONFIG_VFPv3
 	@ d16 - d31 registers
-	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
-1:	mrrc	p11, 3, r0, r1, c\dr	@ fmrrd	r0, r1, d\dr
+	.fpu	vfpv3
+	.irp	dr,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
+1:	vmov	r0, r1, d\dr
 	ret	lr
 	.org	1b + 8
 	.endr
@@ -304,15 +307,17 @@
 
 ENTRY(vfp_put_double)
 	tbl_branch r2, r3, #3
+	.fpu	vfpv2
 	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
-1:	fmdrr	d\dr, r0, r1
+1:	vmov	d\dr, r0, r1
 	ret	lr
 	.org	1b + 8
 	.endr
 #ifdef CONFIG_VFPv3
+	.fpu	vfpv3
 	@ d16 - d31 registers
-	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
-1:	mcrr	p11, 3, r0, r1, c\dr	@ fmdrr	r0, r1, d\dr
+	.irp	dr,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
+1:	vmov	d\dr, r0, r1
 	ret	lr
 	.org	1b + 8
 	.endr
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/vfp/vfpmodule.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/vfp/vfpmodule.c
@@ -23,6 +23,7 @@
 #include <asm/cputype.h>
 #include <asm/system_info.h>
 #include <asm/thread_notify.h>
+#include <asm/traps.h>
 #include <asm/vfp.h>
 
 #include "vfpinstr.h"
@@ -31,7 +32,6 @@
 /*
  * Our undef handlers (in entry.S)
  */
-asmlinkage void vfp_testing_entry(void);
 asmlinkage void vfp_support_entry(void);
 asmlinkage void vfp_null_entry(void);
 
@@ -42,7 +42,7 @@
  * Used in startup: set to non-zero if VFP checks fail
  * After startup, holds VFP architecture
  */
-unsigned int VFP_arch;
+static unsigned int __initdata VFP_arch;
 
 /*
  * The pointer to the vfpstate structure of the thread which currently
@@ -436,7 +436,7 @@
  * present on all CPUs within a SMP complex. Needs to be called prior to
  * vfp_init().
  */
-void vfp_disable(void)
+void __init vfp_disable(void)
 {
 	if (VFP_arch) {
 		pr_debug("%s: should be called prior to vfp_init\n", __func__);
@@ -642,7 +642,9 @@
 	return 0;
 }
 
-void vfp_kmode_exception(void)
+#ifdef CONFIG_KERNEL_MODE_NEON
+
+static int vfp_kmode_exception(struct pt_regs *regs, unsigned int instr)
 {
 	/*
 	 * If we reach this point, a floating point exception has been raised
@@ -660,9 +662,51 @@
 		pr_crit("BUG: unsupported FP instruction in kernel mode\n");
 	else
 		pr_crit("BUG: FP instruction issued in kernel mode with FP unit disabled\n");
+	pr_crit("FPEXC == 0x%08x\n", fmrx(FPEXC));
+	return 1;
 }
 
-#ifdef CONFIG_KERNEL_MODE_NEON
+static struct undef_hook vfp_kmode_exception_hook[] = {{
+	.instr_mask	= 0xfe000000,
+	.instr_val	= 0xf2000000,
+	.cpsr_mask	= MODE_MASK | PSR_T_BIT,
+	.cpsr_val	= SVC_MODE,
+	.fn		= vfp_kmode_exception,
+}, {
+	.instr_mask	= 0xff100000,
+	.instr_val	= 0xf4000000,
+	.cpsr_mask	= MODE_MASK | PSR_T_BIT,
+	.cpsr_val	= SVC_MODE,
+	.fn		= vfp_kmode_exception,
+}, {
+	.instr_mask	= 0xef000000,
+	.instr_val	= 0xef000000,
+	.cpsr_mask	= MODE_MASK | PSR_T_BIT,
+	.cpsr_val	= SVC_MODE | PSR_T_BIT,
+	.fn		= vfp_kmode_exception,
+}, {
+	.instr_mask	= 0xff100000,
+	.instr_val	= 0xf9000000,
+	.cpsr_mask	= MODE_MASK | PSR_T_BIT,
+	.cpsr_val	= SVC_MODE | PSR_T_BIT,
+	.fn		= vfp_kmode_exception,
+}, {
+	.instr_mask	= 0x0c000e00,
+	.instr_val	= 0x0c000a00,
+	.cpsr_mask	= MODE_MASK,
+	.cpsr_val	= SVC_MODE,
+	.fn		= vfp_kmode_exception,
+}};
+
+static int __init vfp_kmode_exception_hook_init(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(vfp_kmode_exception_hook); i++)
+		register_undef_hook(&vfp_kmode_exception_hook[i]);
+	return 0;
+}
+subsys_initcall(vfp_kmode_exception_hook_init);
 
 /*
  * Kernel-side NEON support functions
@@ -708,6 +752,21 @@
 
 #endif /* CONFIG_KERNEL_MODE_NEON */
 
+static int __init vfp_detect(struct pt_regs *regs, unsigned int instr)
+{
+	VFP_arch = UINT_MAX;	/* mark as not present */
+	regs->ARM_pc += 4;
+	return 0;
+}
+
+static struct undef_hook vfp_detect_hook __initdata = {
+	.instr_mask	= 0x0c000e00,
+	.instr_val	= 0x0c000a00,
+	.cpsr_mask	= MODE_MASK,
+	.cpsr_val	= SVC_MODE,
+	.fn		= vfp_detect,
+};
+
 /*
  * VFP support code initialisation.
  */
@@ -728,10 +787,11 @@
 	 * The handler is already setup to just log calls, so
 	 * we just need to read the VFPSID register.
 	 */
-	vfp_vector = vfp_testing_entry;
+	register_undef_hook(&vfp_detect_hook);
 	barrier();
 	vfpsid = fmrx(FPSID);
 	barrier();
+	unregister_undef_hook(&vfp_detect_hook);
 	vfp_vector = vfp_null_entry;
 
 	pr_info("VFP support v0.3: ");
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/xen/enlighten.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/xen/enlighten.c
@@ -354,7 +354,8 @@
 	 * for secondary CPUs as they are brought up.
 	 * For uniformity we use VCPUOP_register_vcpu_info even on cpu0.
 	 */
-	xen_vcpu_info = alloc_percpu(struct vcpu_info);
+	xen_vcpu_info = __alloc_percpu(sizeof(struct vcpu_info),
+				       1 << fls(sizeof(struct vcpu_info) - 1));
 	if (xen_vcpu_info == NULL)
 		return -ENOMEM;
 
@@ -370,8 +371,6 @@
 		return -ENOMEM;
 	}
 	gnttab_init();
-	if (!xen_initial_domain())
-		xenbus_probe(NULL);
 
 	/*
 	 * Making sure board specific code will not set up ops for
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/xen/mm.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/xen/mm.c
@@ -70,20 +70,20 @@
  * pfn_valid returns true the pages is local and we can use the native
  * dma-direct functions, otherwise we call the Xen specific version.
  */
-void xen_dma_sync_for_cpu(struct device *dev, dma_addr_t handle,
-		phys_addr_t paddr, size_t size, enum dma_data_direction dir)
+void xen_dma_sync_for_cpu(dma_addr_t handle, phys_addr_t paddr, size_t size,
+		enum dma_data_direction dir)
 {
 	if (pfn_valid(PFN_DOWN(handle)))
-		arch_sync_dma_for_cpu(dev, paddr, size, dir);
+		arch_sync_dma_for_cpu(paddr, size, dir);
 	else if (dir != DMA_TO_DEVICE)
 		dma_cache_maint(handle, size, GNTTAB_CACHE_INVAL);
 }
 
-void xen_dma_sync_for_device(struct device *dev, dma_addr_t handle,
-		phys_addr_t paddr, size_t size, enum dma_data_direction dir)
+void xen_dma_sync_for_device(dma_addr_t handle, phys_addr_t paddr, size_t size,
+		enum dma_data_direction dir)
 {
 	if (pfn_valid(PFN_DOWN(handle)))
-		arch_sync_dma_for_device(dev, paddr, size, dir);
+		arch_sync_dma_for_device(paddr, size, dir);
 	else if (dir == DMA_FROM_DEVICE)
 		dma_cache_maint(handle, size, GNTTAB_CACHE_INVAL);
 	else
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm/xen/p2m.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm/xen/p2m.c
@@ -62,11 +62,12 @@
 
 unsigned long __pfn_to_mfn(unsigned long pfn)
 {
-	struct rb_node *n = phys_to_mach.rb_node;
+	struct rb_node *n;
 	struct xen_p2m_entry *entry;
 	unsigned long irqflags;
 
 	read_lock_irqsave(&p2m_lock, irqflags);
+	n = phys_to_mach.rb_node;
 	while (n) {
 		entry = rb_entry(n, struct xen_p2m_entry, rbnode_phys);
 		if (entry->pfn <= pfn &&
@@ -93,10 +94,39 @@
 	int i;
 
 	for (i = 0; i < count; i++) {
+		struct gnttab_unmap_grant_ref unmap;
+		int rc;
+
 		if (map_ops[i].status)
 			continue;
-		set_phys_to_machine(map_ops[i].host_addr >> XEN_PAGE_SHIFT,
-				    map_ops[i].dev_bus_addr >> XEN_PAGE_SHIFT);
+		if (likely(set_phys_to_machine(map_ops[i].host_addr >> XEN_PAGE_SHIFT,
+				    map_ops[i].dev_bus_addr >> XEN_PAGE_SHIFT)))
+			continue;
+
+		/*
+		 * Signal an error for this slot. This in turn requires
+		 * immediate unmapping.
+		 */
+		map_ops[i].status = GNTST_general_error;
+		unmap.host_addr = map_ops[i].host_addr,
+		unmap.handle = map_ops[i].handle;
+		map_ops[i].handle = ~0;
+		if (map_ops[i].flags & GNTMAP_device_map)
+			unmap.dev_bus_addr = map_ops[i].dev_bus_addr;
+		else
+			unmap.dev_bus_addr = 0;
+
+		/*
+		 * Pre-populate the status field, to be recognizable in
+		 * the log message below.
+		 */
+		unmap.status = 1;
+
+		rc = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
+					       &unmap, 1);
+		if (rc || unmap.status != GNTST_okay)
+			pr_err_once("gnttab unmap failed: rc=%d st=%d\n",
+				    rc, unmap.status);
 	}
 
 	return 0;
@@ -124,10 +154,11 @@
 	int rc;
 	unsigned long irqflags;
 	struct xen_p2m_entry *p2m_entry;
-	struct rb_node *n = phys_to_mach.rb_node;
+	struct rb_node *n;
 
 	if (mfn == INVALID_P2M_ENTRY) {
 		write_lock_irqsave(&p2m_lock, irqflags);
+		n = phys_to_mach.rb_node;
 		while (n) {
 			p2m_entry = rb_entry(n, struct xen_p2m_entry, rbnode_phys);
 			if (p2m_entry->pfn <= pfn &&
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/Kconfig
@@ -139,6 +139,7 @@
 	select HAVE_CMPXCHG_DOUBLE
 	select HAVE_CMPXCHG_LOCAL
 	select HAVE_CONTEXT_TRACKING
+	select HAVE_COPY_THREAD_TLS
 	select HAVE_DEBUG_BUGVERBOSE
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DMA_CONTIGUOUS
@@ -180,7 +181,6 @@
 	select PCI_SYSCALL if PCI
 	select POWER_RESET
 	select POWER_SUPPLY
-	select REFCOUNT_FULL
 	select SPARSE_IRQ
 	select SWIOTLB
 	select SYSCTL_EXCEPTION_TRACE
@@ -488,7 +488,7 @@
 	help
 	  This option adds a workaround for ARM Cortex-A55 Erratum 1024718.
 
-	  Affected Cortex-A55 cores (r0p0, r0p1, r1p0) could cause incorrect
+	  Affected Cortex-A55 cores (all revisions) could cause incorrect
 	  update of the hardware dirty bit when the DBM/AP bits are updated
 	  without a break-before-make. The workaround is to disable the usage
 	  of hardware DBM locally on the affected cores. CPUs not affected by
@@ -558,6 +558,78 @@
 
 	  If unsure, say Y.
 
+config ARM64_ERRATUM_1542419
+	bool "Neoverse-N1: workaround mis-ordering of instruction fetches"
+	default y
+	help
+	  This option adds a workaround for ARM Neoverse-N1 erratum
+	  1542419.
+
+	  Affected Neoverse-N1 cores could execute a stale instruction when
+	  modified by another CPU. The workaround depends on a firmware
+	  counterpart.
+
+	  Workaround the issue by hiding the DIC feature from EL0. This
+	  forces user-space to perform cache maintenance.
+
+	  If unsure, say Y.
+
+config ARM64_ERRATUM_1742098
+	bool "Cortex-A57/A72: 1742098: ELR recorded incorrectly on interrupt taken between cryptographic instructions in a sequence"
+	depends on COMPAT
+	default y
+	help
+	  This option removes the AES hwcap for aarch32 user-space to
+	  workaround erratum 1742098 on Cortex-A57 and Cortex-A72.
+
+	  Affected parts may corrupt the AES state if an interrupt is
+	  taken between a pair of AES instructions. These instructions
+	  are only present if the cryptography extensions are present.
+	  All software should have a fallback implementation for CPUs
+	  that don't implement the cryptography extensions.
+
+	  If unsure, say Y.
+
+config ARM64_ERRATUM_3194386
+	bool "Cortex-*/Neoverse-*: workaround for MSR SSBS not self-synchronizing"
+	default y
+	help
+	  This option adds the workaround for the following errata:
+
+	  * ARM Cortex-A76 erratum 3324349
+	  * ARM Cortex-A77 erratum 3324348
+	  * ARM Cortex-A78 erratum 3324344
+	  * ARM Cortex-A78C erratum 3324346
+	  * ARM Cortex-A78C erratum 3324347
+	  * ARM Cortex-A710 erratam 3324338
+	  * ARM Cortex-A715 errartum 3456084
+	  * ARM Cortex-A720 erratum 3456091
+	  * ARM Cortex-A725 erratum 3456106
+	  * ARM Cortex-X1 erratum 3324344
+	  * ARM Cortex-X1C erratum 3324346
+	  * ARM Cortex-X2 erratum 3324338
+	  * ARM Cortex-X3 erratum 3324335
+	  * ARM Cortex-X4 erratum 3194386
+	  * ARM Cortex-X925 erratum 3324334
+	  * ARM Neoverse-N1 erratum 3324349
+	  * ARM Neoverse N2 erratum 3324339
+	  * ARM Neoverse-N3 erratum 3456111
+	  * ARM Neoverse-V1 erratum 3324341
+	  * ARM Neoverse V2 erratum 3324336
+	  * ARM Neoverse-V3 erratum 3312417
+
+	  On affected cores "MSR SSBS, #0" instructions may not affect
+	  subsequent speculative instructions, which may permit unexepected
+	  speculative store bypassing.
+
+	  Work around this problem by placing a Speculation Barrier (SB) or
+	  Instruction Synchronization Barrier (ISB) after kernel changes to
+	  SSBS. The presence of the SSBS special-purpose register is hidden
+	  from hwcaps and EL0 reads of ID_AA64PFR1_EL1, such that userspace
+	  will use the PR_SPEC_STORE_BYPASS prctl to change SSBS.
+
+	  If unsure, say Y.
+
 config CAVIUM_ERRATUM_22375
 	bool "Cavium erratum 22375, 24313"
 	default y
@@ -1048,6 +1120,7 @@
 config FORCE_MAX_ZONEORDER
 	int
 	default "14" if (ARM64_64K_PAGES && TRANSPARENT_HUGEPAGE)
+	default "13" if (ARCH_THUNDER && ARM64_4K_PAGES)
 	default "12" if (ARM64_16K_PAGES && TRANSPARENT_HUGEPAGE)
 	default "11"
 	help
@@ -1122,6 +1195,15 @@
 
 	  If unsure, say Y.
 
+config MITIGATE_SPECTRE_BRANCH_HISTORY
+	bool "Mitigate Spectre style attacks against branch history" if EXPERT
+	default y
+	help
+	  Speculation attacks against some high-performance processors can
+	  make use of branch history to influence future speculation.
+	  When taking an exception from user-space, a sequence of branches
+	  or a firmware call overwrites the branch history.
+
 config RODATA_FULL_DEFAULT_ENABLED
 	bool "Apply r/o permissions of VM areas also to their linear aliases"
 	default y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/Kconfig.platforms
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/Kconfig.platforms
@@ -54,6 +54,7 @@
 config ARCH_BERLIN
 	bool "Marvell Berlin SoC Family"
 	select DW_APB_ICTL
+	select DW_APB_TIMER_OF
 	select GPIOLIB
 	select PINCTRL
 	help
@@ -224,6 +225,7 @@
 
 config ARCH_SYNQUACER
 	bool "Socionext SynQuacer SoC Family"
+	select IRQ_FASTEOI_HIERARCHY_HANDLERS
 
 config ARCH_TEGRA
 	bool "NVIDIA Tegra SoC Family"
@@ -294,6 +296,8 @@
 
 config ARCH_ZYNQMP
 	bool "Xilinx ZynqMP Family"
+	select PINCTRL
+	select PINCTRL_ZYNQMP
 	select ZYNQMP_FIRMWARE
 	help
 	  This enables support for Xilinx ZynqMP Family
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/Makefile
@@ -18,7 +18,7 @@
 # Pass --no-apply-dynamic-relocs to restore pre-binutils-2.27 behaviour
 # for relative relocs, since this leads to better Image compression
 # with the relocation offsets always being zero.
-LDFLAGS_vmlinux		+= -shared -Bsymbolic -z notext -z norelro \
+LDFLAGS_vmlinux		+= -shared -Bsymbolic -z notext \
 			$(call ld-option, --no-apply-dynamic-relocs)
 endif
 
@@ -72,23 +72,31 @@
 					include/generated/asm-offsets.h))
 endif
 
+# Ensure that if the compiler supports branch protection we default it
+# off.
+KBUILD_CFLAGS += $(call cc-option,-mbranch-protection=none)
+
 ifeq ($(CONFIG_CPU_BIG_ENDIAN), y)
 KBUILD_CPPFLAGS	+= -mbig-endian
 CHECKFLAGS	+= -D__AARCH64EB__
 AS		+= -EB
 # Prefer the baremetal ELF build target, but not all toolchains include
 # it so fall back to the standard linux version if needed.
-KBUILD_LDFLAGS	+= -EB $(call ld-option, -maarch64elfb, -maarch64linuxb)
+KBUILD_LDFLAGS	+= -EB $(call ld-option, -maarch64elfb, -maarch64linuxb -z norelro)
 UTS_MACHINE	:= aarch64_be
 else
 KBUILD_CPPFLAGS	+= -mlittle-endian
 CHECKFLAGS	+= -D__AARCH64EL__
 AS		+= -EL
 # Same as above, prefer ELF but fall back to linux target if needed.
-KBUILD_LDFLAGS	+= -EL $(call ld-option, -maarch64elf, -maarch64linux)
+KBUILD_LDFLAGS	+= -EL $(call ld-option, -maarch64elf, -maarch64linux -z norelro)
 UTS_MACHINE	:= aarch64
 endif
 
+ifeq ($(CONFIG_LD_IS_LLD), y)
+KBUILD_LDFLAGS	+= -z norelro
+endif
+
 CHECKFLAGS	+= -D__aarch64__
 
 ifeq ($(CONFIG_ARM64_MODULE_PLTS),y)
@@ -142,6 +150,8 @@
 PHONY += vdso_install
 vdso_install:
 	$(Q)$(MAKE) $(build)=arch/arm64/kernel/vdso $@
+	$(if $(CONFIG_COMPAT_VDSO), \
+		$(Q)$(MAKE) $(build)=arch/arm64/kernel/vdso32 $@)
 
 # We use MRPROPER_FILES and CLEAN_FILES now
 archclean:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/Makefile
@@ -16,7 +16,7 @@
 
 OBJCOPYFLAGS_Image :=-O binary -R .note -R .note.gnu.build-id -R .comment -S
 
-targets := Image Image.gz
+targets := Image Image.bz2 Image.gz Image.lz4 Image.lzma Image.lzo
 
 $(obj)/Image: vmlinux FORCE
 	$(call if_changed,objcopy)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/actions/s700.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/actions/s700.dtsi
@@ -231,7 +231,7 @@
 
 		pinctrl: pinctrl@e01b0000 {
 			compatible = "actions,s700-pinctrl";
-			reg = <0x0 0xe01b0000 0x0 0x1000>;
+			reg = <0x0 0xe01b0000 0x0 0x100>;
 			clocks = <&cmu CLK_GPIO>;
 			gpio-controller;
 			gpio-ranges = <&pinctrl 0 0 136>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts
@@ -127,7 +127,7 @@
 &emac {
 	pinctrl-names = "default";
 	pinctrl-0 = <&rgmii_pins>;
-	phy-mode = "rgmii";
+	phy-mode = "rgmii-id";
 	phy-handle = <&ext_rgmii_phy>;
 	phy-supply = <&reg_dc1sw>;
 	status = "okay";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino-emmc.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino-emmc.dts
@@ -15,7 +15,7 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&mmc2_pins>;
 	vmmc-supply = <&reg_dcdc1>;
-	vqmmc-supply = <&reg_dcdc1>;
+	vqmmc-supply = <&reg_eldo1>;
 	bus-width = <8>;
 	non-removable;
 	cap-mmc-hw-reset;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts
@@ -140,7 +140,7 @@
 &mmc1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&mmc1_pins>;
-	vmmc-supply = <&reg_aldo2>;
+	vmmc-supply = <&reg_dcdc1>;
 	vqmmc-supply = <&reg_dldo4>;
 	mmc-pwrseq = <&wifi_pwrseq>;
 	bus-width = <4>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dts
@@ -78,7 +78,7 @@
 	leds {
 		compatible = "gpio-leds";
 
-		status {
+		led-0 {
 			label = "orangepi:green:status";
 			gpios = <&pio 7 11 GPIO_ACTIVE_HIGH>; /* PH11 */
 		};
@@ -129,7 +129,7 @@
 &emac {
 	pinctrl-names = "default";
 	pinctrl-0 = <&rgmii_pins>;
-	phy-mode = "rgmii";
+	phy-mode = "rgmii-id";
 	phy-handle = <&ext_rgmii_phy>;
 	phy-supply = <&reg_gmac_3v3>;
 	status = "okay";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-lts.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-lts.dts
@@ -11,3 +11,7 @@
 	compatible = "pine64,pine64-lts", "allwinner,sun50i-r18",
 		     "allwinner,sun50i-a64";
 };
+
+&mmc0 {
+	broken-cd;		/* card detect is broken on *some* boards */
+};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts
@@ -52,7 +52,7 @@
 &emac {
 	pinctrl-names = "default";
 	pinctrl-0 = <&rgmii_pins>;
-	phy-mode = "rgmii";
+	phy-mode = "rgmii-txid";
 	phy-handle = <&ext_rgmii_phy>;
 	status = "okay";
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts
@@ -103,8 +103,6 @@
 };
 
 &ehci0 {
-	phys = <&usbphy 0>;
-	phy-names = "usb";
 	status = "okay";
 };
 
@@ -142,6 +140,7 @@
 	pinctrl-0 = <&mmc2_pins>, <&mmc2_ds_pin>;
 	vmmc-supply = <&reg_dcdc1>;
 	vqmmc-supply = <&reg_eldo1>;
+	max-frequency = <200000000>;
 	bus-width = <8>;
 	non-removable;
 	cap-mmc-hw-reset;
@@ -150,8 +149,6 @@
 };
 
 &ohci0 {
-	phys = <&usbphy 0>;
-	phy-names = "usb";
 	status = "okay";
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine.dtsi
@@ -55,10 +55,9 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&mmc0_pins>;
 	vmmc-supply = <&reg_dcdc1>;
-	non-removable;
 	disable-wp;
 	bus-width = <4>;
-	cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
+	cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; /* PF6 push-pull switch */
 	status = "okay";
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -142,6 +142,15 @@
 		clock-output-names = "ext-osc32k";
 	};
 
+	pmu {
+		compatible = "arm,cortex-a53-pmu";
+		interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
+	};
+
 	psci {
 		compatible = "arm,psci-0.2";
 		method = "smc";
@@ -218,7 +227,7 @@
 
 			display_clocks: clock@0 {
 				compatible = "allwinner,sun50i-a64-de2-clk";
-				reg = <0x0 0x100000>;
+				reg = <0x0 0x10000>;
 				clocks = <&ccu CLK_BUS_DE>,
 					 <&ccu CLK_DE>;
 				clock-names = "bus",
@@ -467,7 +476,7 @@
 			resets = <&ccu RST_BUS_MMC2>;
 			reset-names = "ahb";
 			interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
-			max-frequency = <200000000>;
+			max-frequency = <150000000>;
 			status = "disabled";
 			#address-cells = <1>;
 			#size-cells = <0>;
@@ -521,6 +530,8 @@
 				 <&ccu CLK_USB_OHCI0>;
 			resets = <&ccu RST_BUS_OHCI0>,
 				 <&ccu RST_BUS_EHCI0>;
+			phys = <&usbphy 0>;
+			phy-names = "usb";
 			status = "disabled";
 		};
 
@@ -531,6 +542,8 @@
 			clocks = <&ccu CLK_BUS_OHCI0>,
 				 <&ccu CLK_USB_OHCI0>;
 			resets = <&ccu RST_BUS_OHCI0>;
+			phys = <&usbphy 0>;
+			phy-names = "usb";
 			status = "disabled";
 		};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-neo2.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-neo2.dts
@@ -114,7 +114,7 @@
 	pinctrl-0 = <&emac_rgmii_pins>;
 	phy-supply = <&reg_gmac_3v3>;
 	phy-handle = <&ext_rgmii_phy>;
-	phy-mode = "rgmii";
+	phy-mode = "rgmii-id";
 	status = "okay";
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts
@@ -157,7 +157,7 @@
 	pinctrl-0 = <&emac_rgmii_pins>;
 	phy-supply = <&reg_gmac_3v3>;
 	phy-handle = <&ext_rgmii_phy>;
-	phy-mode = "rgmii";
+	phy-mode = "rgmii-id";
 	status = "okay";
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts
@@ -164,7 +164,7 @@
 	pinctrl-0 = <&emac_rgmii_pins>;
 	phy-supply = <&reg_gmac_3v3>;
 	phy-handle = <&ext_rgmii_phy>;
-	phy-mode = "rgmii";
+	phy-mode = "rgmii-id";
 	status = "okay";
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-zero-plus.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-zero-plus.dts
@@ -72,7 +72,7 @@
 	pinctrl-0 = <&emac_rgmii_pins>;
 	phy-supply = <&reg_gmac_3v3>;
 	phy-handle = <&ext_rgmii_phy>;
-	phy-mode = "rgmii";
+	phy-mode = "rgmii-id";
 	status = "okay";
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi
@@ -54,21 +54,21 @@
 			enable-method = "psci";
 		};
 
-		cpu@1 {
+		cpu1: cpu@1 {
 			compatible = "arm,cortex-a53";
 			device_type = "cpu";
 			reg = <1>;
 			enable-method = "psci";
 		};
 
-		cpu@2 {
+		cpu2: cpu@2 {
 			compatible = "arm,cortex-a53";
 			device_type = "cpu";
 			reg = <2>;
 			enable-method = "psci";
 		};
 
-		cpu@3 {
+		cpu3: cpu@3 {
 			compatible = "arm,cortex-a53";
 			device_type = "cpu";
 			reg = <3>;
@@ -76,6 +76,15 @@
 		};
 	};
 
+	pmu {
+		compatible = "arm,cortex-a53-pmu";
+		interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
+	};
+
 	psci {
 		compatible = "arm,psci-0.2";
 		method = "smc";
@@ -146,8 +155,7 @@
 				     <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+				     <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
 			interrupt-names = "gp",
 					  "gpmmu",
 					  "pp",
@@ -158,8 +166,7 @@
 					  "pp2",
 					  "ppmmu2",
 					  "pp3",
-					  "ppmmu3",
-					  "pmu";
+					  "ppmmu3";
 			clocks = <&ccu CLK_BUS_GPU>, <&ccu CLK_GPU>;
 			clock-names = "bus", "core";
 			resets = <&ccu RST_BUS_GPU>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts
@@ -83,7 +83,7 @@
 &emac {
 	pinctrl-names = "default";
 	pinctrl-0 = <&ext_rgmii_pins>;
-	phy-mode = "rgmii";
+	phy-mode = "rgmii-id";
 	phy-handle = <&ext_rgmii_phy>;
 	phy-supply = <&reg_aldo2>;
 	status = "okay";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
@@ -66,7 +66,7 @@
 &emac {
 	pinctrl-names = "default";
 	pinctrl-0 = <&ext_rgmii_pins>;
-	phy-mode = "rgmii";
+	phy-mode = "rgmii-id";
 	phy-handle = <&ext_rgmii_phy>;
 	phy-supply = <&reg_aldo2>;
 	allwinner,rx-delay-ps = <200>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
@@ -70,6 +70,15 @@
 		clock-output-names = "ext_osc32k";
 	};
 
+	pmu {
+		compatible = "arm,cortex-a53-pmu";
+		interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
+	};
+
 	psci {
 		compatible = "arm,psci-0.2";
 		method = "smc";
@@ -323,6 +332,7 @@
 			interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&mmc0_pins>;
+			max-frequency = <150000000>;
 			status = "disabled";
 			#address-cells = <1>;
 			#size-cells = <0>;
@@ -339,6 +349,7 @@
 			interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&mmc1_pins>;
+			max-frequency = <150000000>;
 			status = "disabled";
 			#address-cells = <1>;
 			#size-cells = <0>;
@@ -355,6 +366,7 @@
 			interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&mmc2_pins>;
+			max-frequency = <150000000>;
 			status = "disabled";
 			#address-cells = <1>;
 			#size-cells = <0>;
@@ -524,6 +536,8 @@
 				 <&ccu CLK_USB_OHCI0>;
 			resets = <&ccu RST_BUS_OHCI0>,
 				 <&ccu RST_BUS_EHCI0>;
+			phys = <&usb2phy 0>;
+			phy-names = "usb";
 			status = "disabled";
 		};
 
@@ -534,6 +548,8 @@
 			clocks = <&ccu CLK_BUS_OHCI0>,
 				 <&ccu CLK_USB_OHCI0>;
 			resets = <&ccu RST_BUS_OHCI0>;
+			phys = <&usb2phy 0>;
+			phy-names = "usb";
 			status = "disabled";
 		};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
@@ -61,10 +61,10 @@
 
 	pmu {
 		compatible = "arm,armv8-pmuv3";
-		interrupts = <0 120 8>,
-			     <0 121 8>,
-			     <0 122 8>,
-			     <0 123 8>;
+		interrupts = <0 170 4>,
+			     <0 171 4>,
+			     <0 172 4>,
+			     <0 173 4>;
 		interrupt-affinity = <&cpu0>,
 				     <&cpu1>,
 				     <&cpu2>,
@@ -77,7 +77,7 @@
 		method = "smc";
 	};
 
-	intc: intc@fffc1000 {
+	intc: interrupt-controller@fffc1000 {
 		compatible = "arm,gic-400", "arm,cortex-a15-gic";
 		#interrupt-cells = <3>;
 		interrupt-controller;
@@ -302,7 +302,7 @@
 			status = "disabled";
 		};
 
-		nand: nand@ffb90000 {
+		nand: nand-controller@ffb90000 {
 			#address-cells = <1>;
 			#size-cells = <0>;
 			compatible = "altr,socfpga-denali-nand";
@@ -445,7 +445,7 @@
 			clock-names = "timer";
 		};
 
-		uart0: serial0@ffc02000 {
+		uart0: serial@ffc02000 {
 			compatible = "snps,dw-apb-uart";
 			reg = <0xffc02000 0x100>;
 			interrupts = <0 108 4>;
@@ -456,7 +456,7 @@
 			status = "disabled";
 		};
 
-		uart1: serial1@ffc02100 {
+		uart1: serial@ffc02100 {
 			compatible = "snps,dw-apb-uart";
 			reg = <0xffc02100 0x100>;
 			interrupts = <0 109 4>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts
@@ -129,7 +129,7 @@
 	status = "okay";
 	clock-frequency = <100000>;
 	i2c-sda-falling-time-ns = <890>;  /* hcnt */
-	i2c-sdl-falling-time-ns = <890>;  /* lcnt */
+	i2c-scl-falling-time-ns = <890>;  /* lcnt */
 
 	adc@14 {
 		compatible = "lltc,ltc2497";
@@ -155,6 +155,7 @@
 };
 
 &qspi {
+	status = "okay";
 	flash@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
@@ -150,7 +150,7 @@
 		scpi_clocks: clocks {
 			compatible = "arm,scpi-clocks";
 
-			scpi_dvfs: clock-controller {
+			scpi_dvfs: clocks-0 {
 				compatible = "arm,scpi-dvfs-clocks";
 				#clock-cells = <1>;
 				clock-indices = <0>;
@@ -159,7 +159,7 @@
 		};
 
 		scpi_sensors: sensors {
-			compatible = "amlogic,meson-gxbb-scpi-sensors";
+			compatible = "amlogic,meson-gxbb-scpi-sensors", "arm,scpi-sensors";
 			#thermal-sensor-cells = <1>;
 		};
 	};
@@ -1162,7 +1162,7 @@
 
 			toddr_a: audio-controller@100 {
 				compatible = "amlogic,axg-toddr";
-				reg = <0x0 0x100 0x0 0x1c>;
+				reg = <0x0 0x100 0x0 0x2c>;
 				#sound-dai-cells = <0>;
 				sound-name-prefix = "TODDR_A";
 				interrupts = <GIC_SPI 84 IRQ_TYPE_EDGE_RISING>;
@@ -1173,7 +1173,7 @@
 
 			toddr_b: audio-controller@140 {
 				compatible = "amlogic,axg-toddr";
-				reg = <0x0 0x140 0x0 0x1c>;
+				reg = <0x0 0x140 0x0 0x2c>;
 				#sound-dai-cells = <0>;
 				sound-name-prefix = "TODDR_B";
 				interrupts = <GIC_SPI 85 IRQ_TYPE_EDGE_RISING>;
@@ -1184,7 +1184,7 @@
 
 			toddr_c: audio-controller@180 {
 				compatible = "amlogic,axg-toddr";
-				reg = <0x0 0x180 0x0 0x1c>;
+				reg = <0x0 0x180 0x0 0x2c>;
 				#sound-dai-cells = <0>;
 				sound-name-prefix = "TODDR_C";
 				interrupts = <GIC_SPI 86 IRQ_TYPE_EDGE_RISING>;
@@ -1195,7 +1195,7 @@
 
 			frddr_a: audio-controller@1c0 {
 				compatible = "amlogic,axg-frddr";
-				reg = <0x0 0x1c0 0x0 0x1c>;
+				reg = <0x0 0x1c0 0x0 0x2c>;
 				#sound-dai-cells = <0>;
 				sound-name-prefix = "FRDDR_A";
 				interrupts = <GIC_SPI 88 IRQ_TYPE_EDGE_RISING>;
@@ -1206,7 +1206,7 @@
 
 			frddr_b: audio-controller@200 {
 				compatible = "amlogic,axg-frddr";
-				reg = <0x0 0x200 0x0 0x1c>;
+				reg = <0x0 0x200 0x0 0x2c>;
 				#sound-dai-cells = <0>;
 				sound-name-prefix = "FRDDR_B";
 				interrupts = <GIC_SPI 89 IRQ_TYPE_EDGE_RISING>;
@@ -1217,7 +1217,7 @@
 
 			frddr_c: audio-controller@240 {
 				compatible = "amlogic,axg-frddr";
-				reg = <0x0 0x240 0x0 0x1c>;
+				reg = <0x0 0x240 0x0 0x2c>;
 				#sound-dai-cells = <0>;
 				sound-name-prefix = "FRDDR_C";
 				interrupts = <GIC_SPI 90 IRQ_TYPE_EDGE_RISING>;
@@ -1705,7 +1705,7 @@
 			sd_emmc_b: sd@5000 {
 				compatible = "amlogic,meson-axg-mmc";
 				reg = <0x0 0x5000 0x0 0x800>;
-				interrupts = <GIC_SPI 217 IRQ_TYPE_EDGE_RISING>;
+				interrupts = <GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH>;
 				status = "disabled";
 				clocks = <&clkc CLKID_SD_EMMC_B>,
 					<&clkc CLKID_SD_EMMC_B_CLK0>,
@@ -1717,7 +1717,7 @@
 			sd_emmc_c: mmc@7000 {
 				compatible = "amlogic,meson-axg-mmc";
 				reg = <0x0 0x7000 0x0 0x800>;
-				interrupts = <GIC_SPI 218 IRQ_TYPE_EDGE_RISING>;
+				interrupts = <GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH>;
 				status = "disabled";
 				clocks = <&clkc CLKID_SD_EMMC_C>,
 					<&clkc CLKID_SD_EMMC_C_CLK0>,
@@ -1728,18 +1728,18 @@
 		};
 
 		sram: sram@fffc0000 {
-			compatible = "amlogic,meson-axg-sram", "mmio-sram";
+			compatible = "mmio-sram";
 			reg = <0x0 0xfffc0000 0x0 0x20000>;
 			#address-cells = <1>;
 			#size-cells = <1>;
 			ranges = <0 0x0 0xfffc0000 0x20000>;
 
-			cpu_scp_lpri: scp-shmem@13000 {
+			cpu_scp_lpri: scp-sram@13000 {
 				compatible = "amlogic,meson-axg-scp-shmem";
 				reg = <0x13000 0x400>;
 			};
 
-			cpu_scp_hpri: scp-shmem@13400 {
+			cpu_scp_hpri: scp-sram@13400 {
 				compatible = "amlogic,meson-axg-scp-shmem";
 				reg = <0x13400 0x400>;
 			};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
@@ -76,6 +76,12 @@
 			no-map;
 		};
 
+		/* 32 MiB reserved for ARM Trusted Firmware (BL32) */
+		secmon_reserved_bl32: secmon@5300000 {
+			reg = <0x0 0x05300000 0x0 0x2000000>;
+			no-map;
+		};
+
 		linux,cma {
 			compatible = "shared-dma-pool";
 			reusable;
@@ -167,6 +173,8 @@
 				hwrng: rng@218 {
 					compatible = "amlogic,meson-rng";
 					reg = <0x0 0x218 0x0 0x4>;
+					clocks = <&clkc CLKID_RNG0>;
+					clock-names = "core";
 				};
 			};
 
@@ -1368,10 +1376,9 @@
 
 			dmc: bus@38000 {
 				compatible = "simple-bus";
-				reg = <0x0 0x38000 0x0 0x400>;
 				#address-cells = <2>;
 				#size-cells = <2>;
-				ranges = <0x0 0x0 0x0 0x38000 0x0 0x400>;
+				ranges = <0x0 0x0 0x0 0x38000 0x0 0x2000>;
 
 				canvas: video-lut@48 {
 					compatible = "amlogic,canvas";
@@ -1509,7 +1516,7 @@
 				toddr_a: audio-controller@100 {
 					compatible = "amlogic,g12a-toddr",
 						     "amlogic,axg-toddr";
-					reg = <0x0 0x100 0x0 0x1c>;
+					reg = <0x0 0x100 0x0 0x2c>;
 					#sound-dai-cells = <0>;
 					sound-name-prefix = "TODDR_A";
 					interrupts = <GIC_SPI 148 IRQ_TYPE_EDGE_RISING>;
@@ -1521,7 +1528,7 @@
 				toddr_b: audio-controller@140 {
 					compatible = "amlogic,g12a-toddr",
 						     "amlogic,axg-toddr";
-					reg = <0x0 0x140 0x0 0x1c>;
+					reg = <0x0 0x140 0x0 0x2c>;
 					#sound-dai-cells = <0>;
 					sound-name-prefix = "TODDR_B";
 					interrupts = <GIC_SPI 149 IRQ_TYPE_EDGE_RISING>;
@@ -1533,7 +1540,7 @@
 				toddr_c: audio-controller@180 {
 					compatible = "amlogic,g12a-toddr",
 						     "amlogic,axg-toddr";
-					reg = <0x0 0x180 0x0 0x1c>;
+					reg = <0x0 0x180 0x0 0x2c>;
 					#sound-dai-cells = <0>;
 					sound-name-prefix = "TODDR_C";
 					interrupts = <GIC_SPI 150 IRQ_TYPE_EDGE_RISING>;
@@ -1545,7 +1552,7 @@
 				frddr_a: audio-controller@1c0 {
 					compatible = "amlogic,g12a-frddr",
 						     "amlogic,axg-frddr";
-					reg = <0x0 0x1c0 0x0 0x1c>;
+					reg = <0x0 0x1c0 0x0 0x2c>;
 					#sound-dai-cells = <0>;
 					sound-name-prefix = "FRDDR_A";
 					interrupts = <GIC_SPI 152 IRQ_TYPE_EDGE_RISING>;
@@ -1557,7 +1564,7 @@
 				frddr_b: audio-controller@200 {
 					compatible = "amlogic,g12a-frddr",
 						     "amlogic,axg-frddr";
-					reg = <0x0 0x200 0x0 0x1c>;
+					reg = <0x0 0x200 0x0 0x2c>;
 					#sound-dai-cells = <0>;
 					sound-name-prefix = "FRDDR_B";
 					interrupts = <GIC_SPI 153 IRQ_TYPE_EDGE_RISING>;
@@ -1569,7 +1576,7 @@
 				frddr_c: audio-controller@240 {
 					compatible = "amlogic,g12a-frddr",
 						     "amlogic,axg-frddr";
-					reg = <0x0 0x240 0x0 0x1c>;
+					reg = <0x0 0x240 0x0 0x2c>;
 					#sound-dai-cells = <0>;
 					sound-name-prefix = "FRDDR_C";
 					interrupts = <GIC_SPI 154 IRQ_TYPE_EDGE_RISING>;
@@ -1775,7 +1782,7 @@
 					#address-cells = <1>;
 					#size-cells = <0>;
 
-					internal_ephy: ethernet_phy@8 {
+					internal_ephy: ethernet-phy@8 {
 						compatible = "ethernet-phy-id0180.3301",
 							     "ethernet-phy-ieee802.3-c22";
 						interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
@@ -2309,7 +2316,7 @@
 		sd_emmc_a: sd@ffe03000 {
 			compatible = "amlogic,meson-axg-mmc";
 			reg = <0x0 0xffe03000 0x0 0x800>;
-			interrupts = <GIC_SPI 189 IRQ_TYPE_EDGE_RISING>;
+			interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>;
 			status = "disabled";
 			clocks = <&clkc CLKID_SD_EMMC_A>,
 				 <&clkc CLKID_SD_EMMC_A_CLK0>,
@@ -2321,7 +2328,7 @@
 		sd_emmc_b: sd@ffe05000 {
 			compatible = "amlogic,meson-axg-mmc";
 			reg = <0x0 0xffe05000 0x0 0x800>;
-			interrupts = <GIC_SPI 190 IRQ_TYPE_EDGE_RISING>;
+			interrupts = <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>;
 			status = "disabled";
 			clocks = <&clkc CLKID_SD_EMMC_B>,
 				 <&clkc CLKID_SD_EMMC_B_CLK0>,
@@ -2333,7 +2340,7 @@
 		sd_emmc_c: mmc@ffe07000 {
 			compatible = "amlogic,meson-axg-mmc";
 			reg = <0x0 0xffe07000 0x0 0x800>;
-			interrupts = <GIC_SPI 191 IRQ_TYPE_EDGE_RISING>;
+			interrupts = <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>;
 			status = "disabled";
 			clocks = <&clkc CLKID_SD_EMMC_C>,
 				 <&clkc CLKID_SD_EMMC_C_CLK0>,
@@ -2365,7 +2372,7 @@
 				reg = <0x0 0xff400000 0x0 0x40000>;
 				interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clkc CLKID_USB1_DDR_BRIDGE>;
-				clock-names = "ddr";
+				clock-names = "otg";
 				phys = <&usb2_phy1>;
 				phy-names = "usb2-phy";
 				dr_mode = "peripheral";
@@ -2380,7 +2387,8 @@
 				interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
 				dr_mode = "host";
 				snps,dis_u2_susphy_quirk;
-				snps,quirk-frame-length-adjustment;
+				snps,quirk-frame-length-adjustment = <0x20>;
+				snps,parkmode-disable-ss-quirk;
 			};
 		};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/amlogic/meson-g12a-sei510.dts
@@ -139,7 +139,7 @@
 		regulator-min-microvolt = <721000>;
 		regulator-max-microvolt = <1022000>;
 
-		vin-supply = <&dc_in>;
+		pwm-supply = <&dc_in>;
 
 		pwms = <&pwm_AO_cd 1 1250 0>;
 		pwm-dutycycle-range = <100 0>;
@@ -157,14 +157,6 @@
 		regulator-always-on;
 	};
 
-	reserved-memory {
-		/* TEE Reserved Memory */
-		bl32_reserved: bl32@5000000 {
-			reg = <0x0 0x05300000 0x0 0x2000000>;
-			no-map;
-		};
-	};
-
 	sdio_pwrseq: sdio-pwrseq {
 		compatible = "mmc-pwrseq-simple";
 		reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/amlogic/meson-g12a-u200.dts
@@ -139,7 +139,7 @@
 		regulator-min-microvolt = <721000>;
 		regulator-max-microvolt = <1022000>;
 
-		vin-supply = <&main_12v>;
+		pwm-supply = <&main_12v>;
 
 		pwms = <&pwm_AO_cd 1 1250 0>;
 		pwm-dutycycle-range = <100 0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/amlogic/meson-g12a-x96-max.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/amlogic/meson-g12a-x96-max.dts
@@ -139,7 +139,7 @@
 		regulator-min-microvolt = <721000>;
 		regulator-max-microvolt = <1022000>;
 
-		vin-supply = <&dc_in>;
+		pwm-supply = <&dc_in>;
 
 		pwms = <&pwm_AO_cd 1 1250 0>;
 		pwm-dutycycle-range = <100 0>;
@@ -340,7 +340,7 @@
 		eee-broken-1000t;
 
 		reset-assert-us = <10000>;
-		reset-deassert-us = <30000>;
+		reset-deassert-us = <80000>;
 		reset-gpios = <&gpio GPIOZ_15 (GPIO_ACTIVE_LOW | GPIO_OPEN_DRAIN)>;
 
 		interrupt-parent = <&gpio_intc>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi
@@ -54,26 +54,6 @@
 		compatible = "operating-points-v2";
 		opp-shared;
 
-		opp-100000000 {
-			opp-hz = /bits/ 64 <100000000>;
-			opp-microvolt = <731000>;
-		};
-
-		opp-250000000 {
-			opp-hz = /bits/ 64 <250000000>;
-			opp-microvolt = <731000>;
-		};
-
-		opp-500000000 {
-			opp-hz = /bits/ 64 <500000000>;
-			opp-microvolt = <731000>;
-		};
-
-		opp-667000000 {
-			opp-hz = /bits/ 64 <666666666>;
-			opp-microvolt = <731000>;
-		};
-
 		opp-1000000000 {
 			opp-hz = /bits/ 64 <1000000000>;
 			opp-microvolt = <731000>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/amlogic/meson-g12b-a311d.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/amlogic/meson-g12b-a311d.dtsi
@@ -11,26 +11,6 @@
 		compatible = "operating-points-v2";
 		opp-shared;
 
-		opp-100000000 {
-			opp-hz = /bits/ 64 <100000000>;
-			opp-microvolt = <731000>;
-		};
-
-		opp-250000000 {
-			opp-hz = /bits/ 64 <250000000>;
-			opp-microvolt = <731000>;
-		};
-
-		opp-500000000 {
-			opp-hz = /bits/ 64 <500000000>;
-			opp-microvolt = <731000>;
-		};
-
-		opp-667000000 {
-			opp-hz = /bits/ 64 <667000000>;
-			opp-microvolt = <731000>;
-		};
-
 		opp-1000000000 {
 			opp-hz = /bits/ 64 <1000000000>;
 			opp-microvolt = <761000>;
@@ -71,26 +51,6 @@
 		compatible = "operating-points-v2";
 		opp-shared;
 
-		opp-100000000 {
-			opp-hz = /bits/ 64 <100000000>;
-			opp-microvolt = <731000>;
-		};
-
-		opp-250000000 {
-			opp-hz = /bits/ 64 <250000000>;
-			opp-microvolt = <731000>;
-		};
-
-		opp-500000000 {
-			opp-hz = /bits/ 64 <500000000>;
-			opp-microvolt = <731000>;
-		};
-
-		opp-667000000 {
-			opp-hz = /bits/ 64 <667000000>;
-			opp-microvolt = <731000>;
-		};
-
 		opp-1000000000 {
 			opp-hz = /bits/ 64 <1000000000>;
 			opp-microvolt = <731000>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/amlogic/meson-g12b-khadas-vim3.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/amlogic/meson-g12b-khadas-vim3.dtsi
@@ -152,6 +152,10 @@
 	clock-latency = <50000>;
 };
 
+&frddr_a {
+	status = "okay";
+};
+
 &frddr_b {
 	status = "okay";
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/amlogic/meson-g12b-s922x.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/amlogic/meson-g12b-s922x.dtsi
@@ -11,26 +11,6 @@
 		compatible = "operating-points-v2";
 		opp-shared;
 
-		opp-100000000 {
-			opp-hz = /bits/ 64 <100000000>;
-			opp-microvolt = <731000>;
-		};
-
-		opp-250000000 {
-			opp-hz = /bits/ 64 <250000000>;
-			opp-microvolt = <731000>;
-		};
-
-		opp-500000000 {
-			opp-hz = /bits/ 64 <500000000>;
-			opp-microvolt = <731000>;
-		};
-
-		opp-667000000 {
-			opp-hz = /bits/ 64 <667000000>;
-			opp-microvolt = <731000>;
-		};
-
 		opp-1000000000 {
 			opp-hz = /bits/ 64 <1000000000>;
 			opp-microvolt = <731000>;
@@ -71,26 +51,6 @@
 		compatible = "operating-points-v2";
 		opp-shared;
 
-		opp-100000000 {
-			opp-hz = /bits/ 64 <100000000>;
-			opp-microvolt = <751000>;
-		};
-
-		opp-250000000 {
-			opp-hz = /bits/ 64 <250000000>;
-			opp-microvolt = <751000>;
-		};
-
-		opp-500000000 {
-			opp-hz = /bits/ 64 <500000000>;
-			opp-microvolt = <751000>;
-		};
-
-		opp-667000000 {
-			opp-hz = /bits/ 64 <667000000>;
-			opp-microvolt = <751000>;
-		};
-
 		opp-1000000000 {
 			opp-hz = /bits/ 64 <1000000000>;
 			opp-microvolt = <771000>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
@@ -41,6 +41,12 @@
 			no-map;
 		};
 
+		/* 32 MiB reserved for ARM Trusted Firmware (BL32) */
+		secmon_reserved_bl32: secmon@5300000 {
+			reg = <0x0 0x05300000 0x0 0x2000000>;
+			no-map;
+		};
+
 		linux,cma {
 			compatible = "shared-dma-pool";
 			reusable;
@@ -166,7 +172,7 @@
 			reg = <0x14 0x10>;
 		};
 
-		eth_mac: eth_mac@34 {
+		eth_mac: eth-mac@34 {
 			reg = <0x34 0x10>;
 		};
 
@@ -183,7 +189,7 @@
 		scpi_clocks: clocks {
 			compatible = "arm,scpi-clocks";
 
-			scpi_dvfs: scpi_clocks@0 {
+			scpi_dvfs: clocks-0 {
 				compatible = "arm,scpi-dvfs-clocks";
 				#clock-cells = <1>;
 				clock-indices = <0>;
@@ -345,20 +351,20 @@
 		};
 
 		sram: sram@c8000000 {
-			compatible = "amlogic,meson-gx-sram", "amlogic,meson-gxbb-sram", "mmio-sram";
+			compatible = "mmio-sram";
 			reg = <0x0 0xc8000000 0x0 0x14000>;
 
 			#address-cells = <1>;
 			#size-cells = <1>;
 			ranges = <0 0x0 0xc8000000 0x14000>;
 
-			cpu_scp_lpri: scp-shmem@0 {
-				compatible = "amlogic,meson-gx-scp-shmem", "amlogic,meson-gxbb-scp-shmem";
+			cpu_scp_lpri: scp-sram@0 {
+				compatible = "amlogic,meson-gxbb-scp-shmem";
 				reg = <0x13000 0x400>;
 			};
 
-			cpu_scp_hpri: scp-shmem@200 {
-				compatible = "amlogic,meson-gx-scp-shmem", "amlogic,meson-gxbb-scp-shmem";
+			cpu_scp_hpri: scp-sram@200 {
+				compatible = "amlogic,meson-gxbb-scp-shmem";
 				reg = <0x13400 0x400>;
 			};
 		};
@@ -458,7 +464,7 @@
 			#size-cells = <2>;
 			ranges = <0x0 0x0 0x0 0xc8834000 0x0 0x2000>;
 
-			hwrng: rng {
+			hwrng: rng@0 {
 				compatible = "amlogic,meson-rng";
 				reg = <0x0 0x0 0x0 0x4>;
 			};
@@ -522,21 +528,21 @@
 			sd_emmc_a: mmc@70000 {
 				compatible = "amlogic,meson-gx-mmc", "amlogic,meson-gxbb-mmc";
 				reg = <0x0 0x70000 0x0 0x800>;
-				interrupts = <GIC_SPI 216 IRQ_TYPE_EDGE_RISING>;
+				interrupts = <GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH>;
 				status = "disabled";
 			};
 
 			sd_emmc_b: mmc@72000 {
 				compatible = "amlogic,meson-gx-mmc", "amlogic,meson-gxbb-mmc";
 				reg = <0x0 0x72000 0x0 0x800>;
-				interrupts = <GIC_SPI 217 IRQ_TYPE_EDGE_RISING>;
+				interrupts = <GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH>;
 				status = "disabled";
 			};
 
 			sd_emmc_c: mmc@74000 {
 				compatible = "amlogic,meson-gx-mmc", "amlogic,meson-gxbb-mmc";
 				reg = <0x0 0x74000 0x0 0x800>;
-				interrupts = <GIC_SPI 218 IRQ_TYPE_EDGE_RISING>;
+				interrupts = <GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH>;
 				status = "disabled";
 			};
 		};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/amlogic/meson-gxbb-nanopi-k2.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/amlogic/meson-gxbb-nanopi-k2.dts
@@ -165,7 +165,7 @@
 			reg = <0>;
 
 			reset-assert-us = <10000>;
-			reset-deassert-us = <30000>;
+			reset-deassert-us = <80000>;
 			reset-gpios = <&gpio GPIOZ_14 GPIO_ACTIVE_LOW>;
 
 			interrupt-parent = <&gpio_intc>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
@@ -138,7 +138,7 @@
 			reg = <0>;
 
 			reset-assert-us = <10000>;
-			reset-deassert-us = <30000>;
+			reset-deassert-us = <80000>;
 			reset-gpios = <&gpio GPIOZ_14 GPIO_ACTIVE_LOW>;
 
 			interrupt-parent = <&gpio_intc>;
@@ -296,7 +296,7 @@
 };
 
 &usb0_phy {
-	status = "okay";
+	status = "disabled";
 	phy-supply = <&usb_otg_pwr>;
 };
 
@@ -306,7 +306,7 @@
 };
 
 &usb0 {
-	status = "okay";
+	status = "disabled";
 };
 
 &usb1 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
@@ -126,7 +126,7 @@
 			reg = <0>;
 
 			reset-assert-us = <10000>;
-			reset-deassert-us = <30000>;
+			reset-deassert-us = <80000>;
 			reset-gpios = <&gpio GPIOZ_14 GPIO_ACTIVE_LOW>;
 
 			interrupt-parent = <&gpio_intc>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/amlogic/meson-gxbb-wetek.dtsi
@@ -6,6 +6,7 @@
  */
 
 #include "meson-gxbb.dtsi"
+#include <dt-bindings/gpio/gpio.h>
 
 / {
 	aliases {
@@ -64,6 +65,7 @@
 		regulator-name = "VDDIO_AO18";
 		regulator-min-microvolt = <1800000>;
 		regulator-max-microvolt = <1800000>;
+		regulator-always-on;
 	};
 
 	vcc_3v3: regulator-vcc_3v3 {
@@ -147,7 +149,7 @@
 			reg = <0>;
 
 			reset-assert-us = <10000>;
-			reset-deassert-us = <30000>;
+			reset-deassert-us = <80000>;
 			reset-gpios = <&gpio GPIOZ_14 GPIO_ACTIVE_LOW>;
 		};
 	};
@@ -157,6 +159,7 @@
 	status = "okay";
 	pinctrl-0 = <&hdmi_hpd_pins>, <&hdmi_i2c_pins>;
 	pinctrl-names = "default";
+	hdmi-supply = <&vddio_ao18>;
 };
 
 &hdmi_tx_tmds_port {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -326,8 +326,8 @@
 		 <&reset RESET_HDMI_SYSTEM_RESET>,
 		 <&reset RESET_HDMI_TX>;
 	reset-names = "hdmitx_apb", "hdmitx", "hdmitx_phy";
-	clocks = <&clkc CLKID_HDMI_PCLK>,
-		 <&clkc CLKID_CLK81>,
+	clocks = <&clkc CLKID_HDMI>,
+		 <&clkc CLKID_HDMI_PCLK>,
 		 <&clkc CLKID_GCLK_VENCI_INT0>;
 	clock-names = "isfr", "iahb", "venci";
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/amlogic/meson-gxl-s805x-libretech-ac.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/amlogic/meson-gxl-s805x-libretech-ac.dts
@@ -9,7 +9,7 @@
 
 #include <dt-bindings/input/input.h>
 
-#include "meson-gxl-s905x.dtsi"
+#include "meson-gxl-s805x.dtsi"
 
 / {
 	compatible = "libretech,aml-s805x-ac", "amlogic,s805x",
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/amlogic/meson-gxl-s805x-p241.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/amlogic/meson-gxl-s805x-p241.dts
@@ -9,7 +9,7 @@
 
 #include <dt-bindings/input/input.h>
 
-#include "meson-gxl-s905x.dtsi"
+#include "meson-gxl-s805x.dtsi"
 
 / {
 	compatible = "amlogic,p241", "amlogic,s805x", "amlogic,meson-gxl";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/amlogic/meson-gxl-s805x.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/amlogic/meson-gxl-s805x.dtsi
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2020 BayLibre SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#include "meson-gxl-s905x.dtsi"
+
+/ {
+	compatible = "amlogic,s805x", "amlogic,meson-gxl";
+};
+
+/* The S805X Package doesn't seem to handle the 744MHz OPP correctly */
+&mali {
+	assigned-clocks = <&clkc CLKID_MALI_0_SEL>,
+			  <&clkc CLKID_MALI_0>,
+			  <&clkc CLKID_MALI>; /* Glitch free mux */
+	assigned-clock-parents = <&clkc CLKID_FCLK_DIV3>,
+				 <0>, /* Do Nothing */
+				 <&clkc CLKID_MALI_0>;
+	assigned-clock-rates = <0>, /* Do Nothing */
+			       <666666666>,
+			       <0>; /* Do Nothing */
+};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts
@@ -82,7 +82,7 @@
 
 		/* External PHY reset is shared with internal PHY Led signal */
 		reset-assert-us = <10000>;
-		reset-deassert-us = <30000>;
+		reset-deassert-us = <80000>;
 		reset-gpios = <&gpio GPIOZ_14 GPIO_ACTIVE_LOW>;
 
 		interrupt-parent = <&gpio_intc>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-phicomm-n1.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-phicomm-n1.dts
@@ -18,7 +18,7 @@
 	leds {
 		compatible = "gpio-leds";
 
-		status {
+		led {
 			label = "n1:white:status";
 			gpios = <&gpio_ao GPIOAO_9 GPIO_ACTIVE_HIGH>;
 			default-state = "on";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts
@@ -33,11 +33,9 @@
 
 	gpio-keys-polled {
 		compatible = "gpio-keys-polled";
-		#address-cells = <1>;
-		#size-cells = <0>;
 		poll-interval = <100>;
 
-		button@0 {
+		power-button {
 			label = "power";
 			linux,code = <KEY_POWER>;
 			gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_LOW>;
@@ -192,6 +190,9 @@
 	bluetooth {
 		compatible = "brcm,bcm43438-bt";
 		shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>;
+		max-speed = <2000000>;
+		clocks = <&wifi32k>;
+		clock-names = "lpo";
 	};
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
@@ -273,8 +273,8 @@
 		 <&reset RESET_HDMI_SYSTEM_RESET>,
 		 <&reset RESET_HDMI_TX>;
 	reset-names = "hdmitx_apb", "hdmitx", "hdmitx_phy";
-	clocks = <&clkc CLKID_HDMI_PCLK>,
-		 <&clkc CLKID_CLK81>,
+	clocks = <&clkc CLKID_HDMI>,
+		 <&clkc CLKID_HDMI_PCLK>,
 		 <&clkc CLKID_GCLK_VENCI_INT0>;
 	clock-names = "isfr", "iahb", "venci";
 };
@@ -288,6 +288,11 @@
 	};
 };
 
+&hwrng {
+	clocks = <&clkc CLKID_RNG0>;
+	clock-names = "core";
+};
+
 &i2c_A {
 	clocks = <&clkc CLKID_I2C>;
 };
@@ -695,7 +700,7 @@
 		};
 	};
 
-	eth-phy-mux {
+	eth-phy-mux@55c {
 		compatible = "mdio-mux-mmioreg", "mdio-mux";
 		#address-cells = <1>;
 		#size-cells = <0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts
@@ -251,7 +251,7 @@
 		reg = <0>;
 
 		reset-assert-us = <10000>;
-		reset-deassert-us = <30000>;
+		reset-deassert-us = <80000>;
 		reset-gpios = <&gpio GPIOZ_14 GPIO_ACTIVE_LOW>;
 
 		interrupt-parent = <&gpio_intc>;
@@ -327,7 +327,7 @@
 	#size-cells = <0>;
 
 	bus-width = <4>;
-	max-frequency = <50000000>;
+	max-frequency = <60000000>;
 
 	non-removable;
 	disable-wp;
@@ -395,7 +395,7 @@
 		#size-cells = <1>;
 		compatible = "winbond,w25q16", "jedec,spi-nor";
 		reg = <0>;
-		spi-max-frequency = <3000000>;
+		spi-max-frequency = <104000000>;
 	};
 };
 
@@ -409,6 +409,9 @@
 	bluetooth {
 		compatible = "brcm,bcm43438-bt";
 		shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>;
+		max-speed = <2000000>;
+		clocks = <&wifi32k>;
+		clock-names = "lpo";
 	};
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts
@@ -112,7 +112,7 @@
 		max-speed = <1000>;
 
 		reset-assert-us = <10000>;
-		reset-deassert-us = <30000>;
+		reset-deassert-us = <80000>;
 		reset-gpios = <&gpio GPIOZ_14 GPIO_ACTIVE_LOW>;
 	};
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/amlogic/meson-gxm-q200.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/amlogic/meson-gxm-q200.dts
@@ -64,7 +64,7 @@
 
 		/* External PHY reset is shared with internal PHY Led signal */
 		reset-assert-us = <10000>;
-		reset-deassert-us = <30000>;
+		reset-deassert-us = <80000>;
 		reset-gpios = <&gpio GPIOZ_14 GPIO_ACTIVE_LOW>;
 
 		interrupt-parent = <&gpio_intc>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/amlogic/meson-gxm-rbox-pro.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/amlogic/meson-gxm-rbox-pro.dts
@@ -114,7 +114,7 @@
 		max-speed = <1000>;
 
 		reset-assert-us = <10000>;
-		reset-deassert-us = <30000>;
+		reset-deassert-us = <80000>;
 		reset-gpios = <&gpio GPIOZ_14 GPIO_ACTIVE_LOW>;
 	};
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/amlogic/meson-khadas-vim3.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/amlogic/meson-khadas-vim3.dtsi
@@ -43,13 +43,13 @@
 
 		white {
 			label = "vim3:white:sys";
-			gpios = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_LOW>;
+			gpios = <&gpio_ao GPIOAO_4 GPIO_ACTIVE_HIGH>;
 			linux,default-trigger = "heartbeat";
 		};
 
 		red {
 			label = "vim3:red";
-			gpios = <&gpio_expander 5 GPIO_ACTIVE_LOW>;
+			gpios = <&gpio_expander 5 GPIO_ACTIVE_HIGH>;
 		};
 	};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/amlogic/meson-sm1-sei610.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/amlogic/meson-sm1-sei610.dts
@@ -164,14 +164,6 @@
 		regulator-always-on;
 	};
 
-	reserved-memory {
-		/* TEE Reserved Memory */
-		bl32_reserved: bl32@5000000 {
-			reg = <0x0 0x05300000 0x0 0x2000000>;
-			no-map;
-		};
-	};
-
 	sdio_pwrseq: sdio-pwrseq {
 		compatible = "mmc-pwrseq-simple";
 		reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>;
@@ -361,6 +353,9 @@
 
 	bluetooth {
 		compatible = "brcm,bcm43438-bt";
+		interrupt-parent = <&gpio_intc>;
+		interrupts = <95 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "host-wakeup";
 		shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>;
 		max-speed = <2000000>;
 		clocks = <&wifi32k>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi
@@ -55,26 +55,6 @@
 		compatible = "operating-points-v2";
 		opp-shared;
 
-		opp-100000000 {
-			opp-hz = /bits/ 64 <100000000>;
-			opp-microvolt = <730000>;
-		};
-
-		opp-250000000 {
-			opp-hz = /bits/ 64 <250000000>;
-			opp-microvolt = <730000>;
-		};
-
-		opp-500000000 {
-			opp-hz = /bits/ 64 <500000000>;
-			opp-microvolt = <730000>;
-		};
-
-		opp-667000000 {
-			opp-hz = /bits/ 64 <666666666>;
-			opp-microvolt = <750000>;
-		};
-
 		opp-1000000000 {
 			opp-hz = /bits/ 64 <1000000000>;
 			opp-microvolt = <770000>;
@@ -90,7 +70,7 @@
 			opp-microvolt = <790000>;
 		};
 
-		opp-1512000000 {
+		opp-1500000000 {
 			opp-hz = /bits/ 64 <1500000000>;
 			opp-microvolt = <800000>;
 		};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/arm/foundation-v8-gicv2.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/arm/foundation-v8-gicv2.dtsi
@@ -8,7 +8,7 @@
 	gic: interrupt-controller@2c001000 {
 		compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
 		#interrupt-cells = <3>;
-		#address-cells = <2>;
+		#address-cells = <1>;
 		interrupt-controller;
 		reg = <0x0 0x2c001000 0 0x1000>,
 		      <0x0 0x2c002000 0 0x2000>,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/arm/foundation-v8-gicv3.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/arm/foundation-v8-gicv3.dtsi
@@ -8,9 +8,9 @@
 	gic: interrupt-controller@2f000000 {
 		compatible = "arm,gic-v3";
 		#interrupt-cells = <3>;
-		#address-cells = <2>;
-		#size-cells = <2>;
-		ranges;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x0 0x0 0x2f000000 0x100000>;
 		interrupt-controller;
 		reg =	<0x0 0x2f000000 0x0 0x10000>,
 			<0x0 0x2f100000 0x0 0x200000>,
@@ -22,7 +22,7 @@
 		its: its@2f020000 {
 			compatible = "arm,gic-v3-its";
 			msi-controller;
-			reg = <0x0 0x2f020000 0x0 0x20000>;
+			reg = <0x20000 0x20000>;
 		};
 	};
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/arm/foundation-v8.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/arm/foundation-v8.dtsi
@@ -107,51 +107,51 @@
 
 		#interrupt-cells = <1>;
 		interrupt-map-mask = <0 0 63>;
-		interrupt-map = <0 0  0 &gic 0 0 GIC_SPI  0 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0  1 &gic 0 0 GIC_SPI  1 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0  2 &gic 0 0 GIC_SPI  2 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0  3 &gic 0 0 GIC_SPI  3 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0  4 &gic 0 0 GIC_SPI  4 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0  5 &gic 0 0 GIC_SPI  5 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0  6 &gic 0 0 GIC_SPI  6 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0  7 &gic 0 0 GIC_SPI  7 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0  8 &gic 0 0 GIC_SPI  8 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0  9 &gic 0 0 GIC_SPI  9 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 10 &gic 0 0 GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 11 &gic 0 0 GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 12 &gic 0 0 GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 13 &gic 0 0 GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 14 &gic 0 0 GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 15 &gic 0 0 GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 16 &gic 0 0 GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 17 &gic 0 0 GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 18 &gic 0 0 GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 19 &gic 0 0 GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 20 &gic 0 0 GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 21 &gic 0 0 GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 22 &gic 0 0 GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 23 &gic 0 0 GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 24 &gic 0 0 GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 25 &gic 0 0 GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 26 &gic 0 0 GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 27 &gic 0 0 GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 28 &gic 0 0 GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 29 &gic 0 0 GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 30 &gic 0 0 GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 31 &gic 0 0 GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 32 &gic 0 0 GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 33 &gic 0 0 GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 34 &gic 0 0 GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 35 &gic 0 0 GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 36 &gic 0 0 GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 37 &gic 0 0 GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 38 &gic 0 0 GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 39 &gic 0 0 GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 40 &gic 0 0 GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 41 &gic 0 0 GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 42 &gic 0 0 GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-map = <0 0  0 &gic 0 GIC_SPI  0 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0  1 &gic 0 GIC_SPI  1 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0  2 &gic 0 GIC_SPI  2 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0  3 &gic 0 GIC_SPI  3 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0  4 &gic 0 GIC_SPI  4 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0  5 &gic 0 GIC_SPI  5 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0  6 &gic 0 GIC_SPI  6 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0  7 &gic 0 GIC_SPI  7 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0  8 &gic 0 GIC_SPI  8 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0  9 &gic 0 GIC_SPI  9 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 10 &gic 0 GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 11 &gic 0 GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 12 &gic 0 GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 13 &gic 0 GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 14 &gic 0 GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 15 &gic 0 GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 16 &gic 0 GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 17 &gic 0 GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 18 &gic 0 GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 19 &gic 0 GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 20 &gic 0 GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 21 &gic 0 GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 22 &gic 0 GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 23 &gic 0 GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 24 &gic 0 GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 25 &gic 0 GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 26 &gic 0 GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 27 &gic 0 GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 28 &gic 0 GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 29 &gic 0 GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 30 &gic 0 GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 31 &gic 0 GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 32 &gic 0 GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 33 &gic 0 GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 34 &gic 0 GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 35 &gic 0 GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 36 &gic 0 GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 37 &gic 0 GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 38 &gic 0 GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 39 &gic 0 GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 40 &gic 0 GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 41 &gic 0 GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 42 &gic 0 GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
 
-		ethernet@2,02000000 {
+		ethernet@202000000 {
 			compatible = "smsc,lan91c111";
 			reg = <2 0x02000000 0x10000>;
 			interrupts = <15>;
@@ -178,7 +178,7 @@
 			clock-output-names = "v2m:refclk32khz";
 		};
 
-		iofpga@3,00000000 {
+		iofpga@300000000 {
 			compatible = "simple-bus";
 			#address-cells = <1>;
 			#size-cells = <1>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/arm/fvp-base-revc.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/arm/fvp-base-revc.dts
@@ -161,10 +161,10 @@
 		bus-range = <0x0 0x1>;
 		reg = <0x0 0x40000000 0x0 0x10000000>;
 		ranges = <0x2000000 0x0 0x50000000 0x0 0x50000000 0x0 0x10000000>;
-		interrupt-map = <0 0 0 1 &gic GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 0 2 &gic GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 0 3 &gic GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 0 4 &gic GIC_SPI 171 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-map = <0 0 0 1 &gic 0 0 GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 0 2 &gic 0 0 GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 0 3 &gic 0 0 GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 0 4 &gic 0 0 GIC_SPI 171 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-map-mask = <0x0 0x0 0x0 0x7>;
 		msi-map = <0x0 &its 0x0 0x10000>;
 		iommu-map = <0x0 &smmu 0x0 0x10000>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/arm/juno-base.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/arm/juno-base.dtsi
@@ -6,7 +6,6 @@
 	/*
 	 *  Devices shared by all Juno boards
 	 */
-	dma-ranges = <0 0 0 0 0x100 0>;
 
 	memtimer: timer@2a810000 {
 		compatible = "arm,armv7-timer-mem";
@@ -63,35 +62,35 @@
 		      <0x0 0x2c02f000 0 0x2000>,
 		      <0x0 0x2c04f000 0 0x2000>,
 		      <0x0 0x2c06f000 0 0x2000>;
-		#address-cells = <2>;
+		#address-cells = <1>;
 		#interrupt-cells = <3>;
-		#size-cells = <2>;
+		#size-cells = <1>;
 		interrupt-controller;
 		interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_HIGH)>;
-		ranges = <0 0 0 0x2c1c0000 0 0x40000>;
+		ranges = <0 0 0x2c1c0000 0x40000>;
 
 		v2m_0: v2m@0 {
 			compatible = "arm,gic-v2m-frame";
 			msi-controller;
-			reg = <0 0 0 0x10000>;
+			reg = <0 0x10000>;
 		};
 
 		v2m@10000 {
 			compatible = "arm,gic-v2m-frame";
 			msi-controller;
-			reg = <0 0x10000 0 0x10000>;
+			reg = <0x10000 0x10000>;
 		};
 
 		v2m@20000 {
 			compatible = "arm,gic-v2m-frame";
 			msi-controller;
-			reg = <0 0x20000 0 0x10000>;
+			reg = <0x20000 0x10000>;
 		};
 
 		v2m@30000 {
 			compatible = "arm,gic-v2m-frame";
 			msi-controller;
-			reg = <0 0x30000 0 0x10000>;
+			reg = <0x30000 0x10000>;
 		};
 	};
 
@@ -520,10 +519,10 @@
 			 <0x42000000 0x40 0x00000000 0x40 0x00000000 0x1 0x00000000>;
 		#interrupt-cells = <1>;
 		interrupt-map-mask = <0 0 0 7>;
-		interrupt-map = <0 0 0 1 &gic 0 0 GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 0 2 &gic 0 0 GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 0 3 &gic 0 0 GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 0 4 &gic 0 0 GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-map = <0 0 0 1 &gic 0 GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 0 2 &gic 0 GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 0 3 &gic 0 GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 0 4 &gic 0 GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>;
 		msi-parent = <&v2m_0>;
 		status = "disabled";
 		iommu-map-mask = <0x0>;	/* RC has no means to output PCI RID */
@@ -538,13 +537,13 @@
 		clocks {
 			compatible = "arm,scpi-clocks";
 
-			scpi_dvfs: scpi-dvfs {
+			scpi_dvfs: clocks-0 {
 				compatible = "arm,scpi-dvfs-clocks";
 				#clock-cells = <1>;
 				clock-indices = <0>, <1>, <2>;
 				clock-output-names = "atlclk", "aplclk","gpuclk";
 			};
-			scpi_clk: scpi-clk {
+			scpi_clk: clocks-1 {
 				compatible = "arm,scpi-variable-clocks";
 				#clock-cells = <1>;
 				clock-indices = <3>;
@@ -552,7 +551,7 @@
 			};
 		};
 
-		scpi_devpd: scpi-power-domains {
+		scpi_devpd: power-controller {
 			compatible = "arm,scpi-power-domains";
 			num-domains = <2>;
 			#power-domain-cells = <1>;
@@ -787,19 +786,19 @@
 
 		#interrupt-cells = <1>;
 		interrupt-map-mask = <0 0 15>;
-		interrupt-map = <0 0  0 &gic 0 0 GIC_SPI  68 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0  1 &gic 0 0 GIC_SPI  69 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0  2 &gic 0 0 GIC_SPI  70 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0  3 &gic 0 0 GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0  4 &gic 0 0 GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0  5 &gic 0 0 GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0  6 &gic 0 0 GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0  7 &gic 0 0 GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0  8 &gic 0 0 GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0  9 &gic 0 0 GIC_SPI 166 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 10 &gic 0 0 GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 11 &gic 0 0 GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>,
-				<0 0 12 &gic 0 0 GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-map = <0 0  0 &gic 0 GIC_SPI  68 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0  1 &gic 0 GIC_SPI  69 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0  2 &gic 0 GIC_SPI  70 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0  3 &gic 0 GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0  4 &gic 0 GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0  5 &gic 0 GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0  6 &gic 0 GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0  7 &gic 0 GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0  8 &gic 0 GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0  9 &gic 0 GIC_SPI 166 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 10 &gic 0 GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 11 &gic 0 GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>,
+				<0 0 12 &gic 0 GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>;
 	};
 
 	site2: tlx@60000000 {
@@ -809,6 +808,6 @@
 		ranges = <0 0 0x60000000 0x10000000>;
 		#interrupt-cells = <1>;
 		interrupt-map-mask = <0 0>;
-		interrupt-map = <0 0 &gic 0 0 GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-map = <0 0 &gic 0 GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
 	};
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/arm/juno-clocks.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/arm/juno-clocks.dtsi
@@ -8,10 +8,10 @@
  */
 / {
 	/* SoC fixed clocks */
-	soc_uartclk: refclk7273800hz {
+	soc_uartclk: refclk7372800hz {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
-		clock-frequency = <7273800>;
+		clock-frequency = <7372800>;
 		clock-output-names = "juno:uartclk";
 	};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/arm/juno-motherboard.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/arm/juno-motherboard.dtsi
@@ -103,7 +103,7 @@
 				};
 			};
 
-			flash@0,00000000 {
+			flash@0 {
 				/* 2 * 32MiB NOR Flash memory mounted on CS0 */
 				compatible = "arm,vexpress-flash", "cfi-flash";
 				reg = <0 0x00000000 0x04000000>;
@@ -120,7 +120,7 @@
 				};
 			};
 
-			ethernet@2,00000000 {
+			ethernet@200000000 {
 				compatible = "smsc,lan9118", "smsc,lan9115";
 				reg = <2 0x00000000 0x10000>;
 				interrupts = <3>;
@@ -133,7 +133,7 @@
 				vddvario-supply = <&mb_fixed_3v3>;
 			};
 
-			iofpga@3,00000000 {
+			iofpga@300000000 {
 				compatible = "simple-bus";
 				#address-cells = <1>;
 				#size-cells = <1>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/arm/rtsm_ve-motherboard-rs2.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/arm/rtsm_ve-motherboard-rs2.dtsi
@@ -9,7 +9,7 @@
 		motherboard {
 			arm,v2m-memory-map = "rs2";
 
-			iofpga@3,00000000 {
+			iofpga@300000000 {
 				virtio-p9@140000 {
 					compatible = "virtio,mmio";
 					reg = <0x140000 0x200>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi
@@ -17,14 +17,14 @@
 			#interrupt-cells = <1>;
 			ranges;
 
-			flash@0,00000000 {
+			flash@0 {
 				compatible = "arm,vexpress-flash", "cfi-flash";
 				reg = <0 0x00000000 0x04000000>,
 				      <4 0x00000000 0x04000000>;
 				bank-width = <4>;
 			};
 
-			ethernet@2,02000000 {
+			ethernet@202000000 {
 				compatible = "smsc,lan91c111";
 				reg = <2 0x02000000 0x10000>;
 				interrupts = <15>;
@@ -51,7 +51,7 @@
 				clock-output-names = "v2m:refclk32khz";
 			};
 
-			iofpga@3,00000000 {
+			iofpga@300000000 {
 				compatible = "simple-bus";
 				#address-cells = <1>;
 				#size-cells = <1>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/broadcom/northstar2/ns2-svk.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/broadcom/northstar2/ns2-svk.dts
@@ -111,8 +111,8 @@
 		compatible = "silabs,si3226x";
 		reg = <0>;
 		spi-max-frequency = <5000000>;
-		spi-cpha = <1>;
-		spi-cpol = <1>;
+		spi-cpha;
+		spi-cpol;
 		pl022,hierarchy = <0>;
 		pl022,interface = <0>;
 		pl022,slave-tx-disable = <0>;
@@ -135,8 +135,8 @@
 		at25,byte-len = <0x8000>;
 		at25,addr-mode = <2>;
 		at25,page-size = <64>;
-		spi-cpha = <1>;
-		spi-cpol = <1>;
+		spi-cpha;
+		spi-cpol;
 		pl022,hierarchy = <0>;
 		pl022,interface = <0>;
 		pl022,slave-tx-disable = <0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/broadcom/northstar2/ns2.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/broadcom/northstar2/ns2.dtsi
@@ -687,7 +687,7 @@
 			};
 		};
 
-		sata: ahci@663f2000 {
+		sata: sata@663f2000 {
 			compatible = "brcm,iproc-ahci", "generic-ahci";
 			reg = <0x663f2000 0x1000>;
 			dma-coherent;
@@ -745,7 +745,7 @@
 		};
 
 		qspi: spi@66470200 {
-			compatible = "brcm,spi-bcm-qspi", "brcm,spi-ns2-qspi";
+			compatible = "brcm,spi-ns2-qspi", "brcm,spi-bcm-qspi";
 			reg = <0x66470200 0x184>,
 				<0x66470000 0x124>,
 				<0x67017408 0x004>,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/broadcom/stingray/stingray-usb.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/broadcom/stingray/stingray-usb.dtsi
@@ -4,21 +4,26 @@
  */
 	usb {
 		compatible = "simple-bus";
-		dma-ranges;
-		#address-cells = <1>;
-		#size-cells = <1>;
-		ranges = <0x0 0x0 0x68500000 0x00400000>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges = <0x0 0x0 0x0 0x68500000 0x0 0x00400000>;
+
+		/*
+		 * Internally, USB bus to the interconnect can only address up
+		 * to 40-bit
+		 */
+		dma-ranges = <0 0 0 0 0x100 0x0>;
 
 		usbphy0: usb-phy@0 {
 			compatible = "brcm,sr-usb-combo-phy";
-			reg = <0x00000000 0x100>;
+			reg = <0x0 0x00000000 0x0 0x100>;
 			#phy-cells = <1>;
 			status = "disabled";
 		};
 
 		xhci0: usb@1000 {
 			compatible = "generic-xhci";
-			reg = <0x00001000 0x1000>;
+			reg = <0x0 0x00001000 0x0 0x1000>;
 			interrupts = <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>;
 			phys = <&usbphy0 1>, <&usbphy0 0>;
 			phy-names = "phy0", "phy1";
@@ -28,7 +33,7 @@
 
 		bdc0: usb@2000 {
 			compatible = "brcm,bdc-v0.16";
-			reg = <0x00002000 0x1000>;
+			reg = <0x0 0x00002000 0x0 0x1000>;
 			interrupts = <GIC_SPI 259 IRQ_TYPE_LEVEL_HIGH>;
 			phys = <&usbphy0 0>, <&usbphy0 1>;
 			phy-names = "phy0", "phy1";
@@ -38,21 +43,21 @@
 
 		usbphy1: usb-phy@10000 {
 			compatible = "brcm,sr-usb-combo-phy";
-			reg = <0x00010000 0x100>;
+			reg = <0x0 0x00010000 0x0 0x100>;
 			#phy-cells = <1>;
 			status = "disabled";
 		};
 
 		usbphy2: usb-phy@20000 {
 			compatible = "brcm,sr-usb-hs-phy";
-			reg = <0x00020000 0x100>;
+			reg = <0x0 0x00020000 0x0 0x100>;
 			#phy-cells = <0>;
 			status = "disabled";
 		};
 
 		xhci1: usb@11000 {
 			compatible = "generic-xhci";
-			reg = <0x00011000 0x1000>;
+			reg = <0x0 0x00011000 0x0 0x1000>;
 			interrupts = <GIC_SPI 263 IRQ_TYPE_LEVEL_HIGH>;
 			phys = <&usbphy1 1>, <&usbphy2>, <&usbphy1 0>;
 			phy-names = "phy0", "phy1", "phy2";
@@ -62,7 +67,7 @@
 
 		bdc1: usb@21000 {
 			compatible = "brcm,bdc-v0.16";
-			reg = <0x00021000 0x1000>;
+			reg = <0x0 0x00021000 0x0 0x1000>;
 			interrupts = <GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>;
 			phys = <&usbphy2>;
 			phy-names = "phy0";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/exynos/exynos5433-tm2-common.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/exynos/exynos5433-tm2-common.dtsi
@@ -389,7 +389,7 @@
 	s2mps13-pmic@66 {
 		compatible = "samsung,s2mps13-pmic";
 		interrupt-parent = <&gpa0>;
-		interrupts = <7 IRQ_TYPE_NONE>;
+		interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
 		reg = <0x66>;
 		samsung,s2mps11-wrstbi-ground;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/exynos/exynos5433.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/exynos/exynos5433.dtsi
@@ -18,8 +18,8 @@
 
 / {
 	compatible = "samsung,exynos5433";
-	#address-cells = <1>;
-	#size-cells = <1>;
+	#address-cells = <2>;
+	#size-cells = <2>;
 
 	interrupt-parent = <&gic>;
 
@@ -311,7 +311,7 @@
 		compatible = "simple-bus";
 		#address-cells = <1>;
 		#size-cells = <1>;
-		ranges;
+		ranges = <0x0 0x0 0x0 0x18000000>;
 
 		chipid@10000000 {
 			compatible = "samsung,exynos4210-chipid";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/exynos/exynos7-espresso.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/exynos/exynos7-espresso.dts
@@ -90,7 +90,7 @@
 	s2mps15_pmic@66 {
 		compatible = "samsung,s2mps15-pmic";
 		reg = <0x66>;
-		interrupts = <2 IRQ_TYPE_NONE>;
+		interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
 		interrupt-parent = <&gpa0>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&pmic_irq>;
@@ -157,6 +157,7 @@
 				regulator-min-microvolt = <700000>;
 				regulator-max-microvolt = <1150000>;
 				regulator-enable-ramp-delay = <125>;
+				regulator-always-on;
 			};
 
 			ldo8_reg: LDO8 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/exynos/exynos7.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/exynos/exynos7.dtsi
@@ -12,8 +12,8 @@
 / {
 	compatible = "samsung,exynos7";
 	interrupt-parent = <&gic>;
-	#address-cells = <1>;
-	#size-cells = <1>;
+	#address-cells = <2>;
+	#size-cells = <2>;
 
 	aliases {
 		pinctrl0 = &pinctrl_alive;
@@ -90,15 +90,17 @@
 	};
 
 	psci {
-		compatible = "arm,psci-0.2";
+		compatible = "arm,psci";
 		method = "smc";
+		cpu_off = <0x84000002>;
+		cpu_on = <0xC4000003>;
 	};
 
 	soc: soc {
 		compatible = "simple-bus";
 		#address-cells = <1>;
 		#size-cells = <1>;
-		ranges;
+		ranges = <0 0 0 0x18000000>;
 
 		chipid@10000000 {
 			compatible = "samsung,exynos4210-chipid";
@@ -111,7 +113,7 @@
 			#address-cells = <0>;
 			interrupt-controller;
 			reg =	<0x11001000 0x1000>,
-				<0x11002000 0x1000>,
+				<0x11002000 0x2000>,
 				<0x11004000 0x2000>,
 				<0x11006000 0x2000>;
 		};
@@ -494,13 +496,6 @@
 		pmu_system_controller: system-controller@105c0000 {
 			compatible = "samsung,exynos7-pmu", "syscon";
 			reg = <0x105c0000 0x5000>;
-
-			reboot: syscon-reboot {
-				compatible = "syscon-reboot";
-				regmap = <&pmu_system_controller>;
-				offset = <0x0400>;
-				mask = <0x1>;
-			};
 		};
 
 		rtc: rtc@10590000 {
@@ -650,3 +645,4 @@
 };
 
 #include "exynos7-pinctrl.dtsi"
+#include "arm/exynos-syscon-restart.dtsi"
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
@@ -177,6 +177,7 @@
 			ranges = <0x0 0x00 0x1700000 0x100000>;
 			reg = <0x00 0x1700000 0x0 0x100000>;
 			interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
+			dma-coherent;
 
 			sec_jr0: jr@10000 {
 				compatible = "fsl,sec-v5.4-job-ring",
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dts
@@ -161,11 +161,6 @@
 				vcc-supply = <&sb_3v3>;
 			};
 
-			rtc@51 {
-				compatible = "nxp,pcf2129";
-				reg = <0x51>;
-			};
-
 			eeprom@56 {
 				compatible = "atmel,24c512";
 				reg = <0x56>;
@@ -209,6 +204,15 @@
 
 };
 
+&i2c1 {
+	status = "okay";
+
+	rtc@51 {
+		compatible = "nxp,pcf2129";
+		reg = <0x51>;
+	};
+};
+
 &enetc_port1 {
 	phy-handle = <&qds_phy1>;
 	phy-connection-type = "rgmii-id";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi
@@ -65,7 +65,7 @@
 		};
 	};
 
-	sysclk: clock-sysclk {
+	sysclk: sysclk {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <100000000>;
@@ -102,8 +102,8 @@
 
 	reboot {
 		compatible ="syscon-reboot";
-		regmap = <&dcfg>;
-		offset = <0xb0>;
+		regmap = <&rst>;
+		offset = <0>;
 		mask = <0x02>;
 	};
 
@@ -151,14 +151,20 @@
 		ddr: memory-controller@1080000 {
 			compatible = "fsl,qoriq-memory-controller";
 			reg = <0x0 0x1080000 0x0 0x1000>;
-			interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>;
-			big-endian;
+			interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+			little-endian;
 		};
 
 		dcfg: syscon@1e00000 {
 			compatible = "fsl,ls1028a-dcfg", "syscon";
 			reg = <0x0 0x1e00000 0x0 0x10000>;
-			big-endian;
+			little-endian;
+		};
+
+		rst: syscon@1e60000 {
+			compatible = "syscon";
+			reg = <0x0 0x1e60000 0x0 0x10000>;
+			little-endian;
 		};
 
 		scfg: syscon@1fc0000 {
@@ -281,6 +287,24 @@
 			status = "disabled";
 		};
 
+		can0: can@2180000 {
+			compatible = "fsl,ls1028ar1-flexcan", "fsl,lx2160ar1-flexcan";
+			reg = <0x0 0x2180000 0x0 0x10000>;
+			interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&sysclk>, <&clockgen 4 1>;
+			clock-names = "ipg", "per";
+			status = "disabled";
+		};
+
+		can1: can@2190000 {
+			compatible = "fsl,ls1028ar1-flexcan", "fsl,lx2160ar1-flexcan";
+			reg = <0x0 0x2190000 0x0 0x10000>;
+			interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&sysclk>, <&clockgen 4 1>;
+			clock-names = "ipg", "per";
+			status = "disabled";
+		};
+
 		duart0: serial@21c0500 {
 			compatible = "fsl,ns16550", "ns16550a";
 			reg = <0x00 0x21c0500 0x0 0x100>;
@@ -490,14 +514,14 @@
 			compatible = "arm,sp805", "arm,primecell";
 			reg = <0x0 0xc000000 0x0 0x1000>;
 			clocks = <&clockgen 4 15>, <&clockgen 4 15>;
-			clock-names = "apb_pclk", "wdog_clk";
+			clock-names = "wdog_clk", "apb_pclk";
 		};
 
 		cluster1_core1_watchdog: watchdog@c010000 {
 			compatible = "arm,sp805", "arm,primecell";
 			reg = <0x0 0xc010000 0x0 0x1000>;
 			clocks = <&clockgen 4 15>, <&clockgen 4 15>;
-			clock-names = "apb_pclk", "wdog_clk";
+			clock-names = "wdog_clk", "apb_pclk";
 		};
 
 		sai1: audio-controller@f100000 {
@@ -567,7 +591,7 @@
 					       0x00010004 0x0000003d
 					       0x00010005 0x00000045
 					       0x00010006 0x0000004d
-					       0x00010007 0x00000045
+					       0x00010007 0x00000055
 					       0x00010008 0x0000005e
 					       0x00010009 0x00000066
 					       0x0001000a 0x0000006e
@@ -667,7 +691,7 @@
 			ethernet@0,4 {
 				compatible = "fsl,enetc-ptp";
 				reg = <0x000400 0 0 0 0>;
-				clocks = <&clockgen 4 0>;
+				clocks = <&clockgen 2 3>;
 				little-endian;
 			};
 		};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/freescale/fsl-ls1043-post.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/freescale/fsl-ls1043-post.dtsi
@@ -20,6 +20,8 @@
 };
 
 &fman0 {
+	fsl,erratum-a050385;
+
 	/* these aliases provide the FMan ports mapping */
 	enet0: ethernet@e0000 {
 	};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/freescale/fsl-ls1043a-rdb.dts
@@ -119,12 +119,12 @@
 
 	ethernet@e4000 {
 		phy-handle = <&rgmii_phy1>;
-		phy-connection-type = "rgmii-txid";
+		phy-connection-type = "rgmii-id";
 	};
 
 	ethernet@e6000 {
 		phy-handle = <&rgmii_phy2>;
-		phy-connection-type = "rgmii-txid";
+		phy-connection-type = "rgmii-id";
 	};
 
 	ethernet@e8000 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
@@ -241,6 +241,7 @@
 			ranges = <0x0 0x00 0x1700000 0x100000>;
 			reg = <0x00 0x1700000 0x0 0x100000>;
 			interrupts = <0 75 0x4>;
+			dma-coherent;
 
 			sec_jr0: jr@10000 {
 				compatible = "fsl,sec-v5.4-job-ring",
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/freescale/fsl-ls1046a-frwy.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/freescale/fsl-ls1046a-frwy.dts
@@ -83,15 +83,9 @@
 			};
 
 			eeprom@52 {
-				compatible = "atmel,24c512";
+				compatible = "onnn,cat24c04", "atmel,24c04";
 				reg = <0x52>;
 			};
-
-			eeprom@53 {
-				compatible = "atmel,24c512";
-				reg = <0x53>;
-			};
-
 		};
 	};
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/freescale/fsl-ls1046a-rdb.dts
@@ -58,14 +58,9 @@
 	};
 
 	eeprom@52 {
-		compatible = "atmel,24c512";
+		compatible = "onnn,cat24c05", "atmel,24c04";
 		reg = <0x52>;
 	};
-
-	eeprom@53 {
-		compatible = "atmel,24c512";
-		reg = <0x53>;
-	};
 };
 
 &i2c3 {
@@ -127,12 +122,12 @@
 &fman0 {
 	ethernet@e4000 {
 		phy-handle = <&rgmii_phy1>;
-		phy-connection-type = "rgmii";
+		phy-connection-type = "rgmii-id";
 	};
 
 	ethernet@e6000 {
 		phy-handle = <&rgmii_phy2>;
-		phy-connection-type = "rgmii";
+		phy-connection-type = "rgmii-id";
 	};
 
 	ethernet@e8000 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
@@ -244,6 +244,7 @@
 			ranges = <0x0 0x00 0x1700000 0x100000>;
 			reg = <0x00 0x1700000 0x0 0x100000>;
 			interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
+			dma-coherent;
 
 			sec_jr0: jr@10000 {
 				compatible = "fsl,sec-v5.4-job-ring",
@@ -304,7 +305,7 @@
 
 		dcfg: dcfg@1ee0000 {
 			compatible = "fsl,ls1046a-dcfg", "syscon";
-			reg = <0x0 0x1ee0000 0x0 0x10000>;
+			reg = <0x0 0x1ee0000 0x0 0x1000>;
 			big-endian;
 		};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
@@ -637,59 +637,59 @@
 		};
 
 		cluster1_core0_watchdog: wdt@c000000 {
-			compatible = "arm,sp805-wdt", "arm,primecell";
+			compatible = "arm,sp805", "arm,primecell";
 			reg = <0x0 0xc000000 0x0 0x1000>;
 			clocks = <&clockgen 4 3>, <&clockgen 4 3>;
-			clock-names = "apb_pclk", "wdog_clk";
+			clock-names = "wdog_clk", "apb_pclk";
 		};
 
 		cluster1_core1_watchdog: wdt@c010000 {
-			compatible = "arm,sp805-wdt", "arm,primecell";
+			compatible = "arm,sp805", "arm,primecell";
 			reg = <0x0 0xc010000 0x0 0x1000>;
 			clocks = <&clockgen 4 3>, <&clockgen 4 3>;
-			clock-names = "apb_pclk", "wdog_clk";
+			clock-names = "wdog_clk", "apb_pclk";
 		};
 
 		cluster1_core2_watchdog: wdt@c020000 {
-			compatible = "arm,sp805-wdt", "arm,primecell";
+			compatible = "arm,sp805", "arm,primecell";
 			reg = <0x0 0xc020000 0x0 0x1000>;
 			clocks = <&clockgen 4 3>, <&clockgen 4 3>;
-			clock-names = "apb_pclk", "wdog_clk";
+			clock-names = "wdog_clk", "apb_pclk";
 		};
 
 		cluster1_core3_watchdog: wdt@c030000 {
-			compatible = "arm,sp805-wdt", "arm,primecell";
+			compatible = "arm,sp805", "arm,primecell";
 			reg = <0x0 0xc030000 0x0 0x1000>;
 			clocks = <&clockgen 4 3>, <&clockgen 4 3>;
-			clock-names = "apb_pclk", "wdog_clk";
+			clock-names = "wdog_clk", "apb_pclk";
 		};
 
 		cluster2_core0_watchdog: wdt@c100000 {
-			compatible = "arm,sp805-wdt", "arm,primecell";
+			compatible = "arm,sp805", "arm,primecell";
 			reg = <0x0 0xc100000 0x0 0x1000>;
 			clocks = <&clockgen 4 3>, <&clockgen 4 3>;
-			clock-names = "apb_pclk", "wdog_clk";
+			clock-names = "wdog_clk", "apb_pclk";
 		};
 
 		cluster2_core1_watchdog: wdt@c110000 {
-			compatible = "arm,sp805-wdt", "arm,primecell";
+			compatible = "arm,sp805", "arm,primecell";
 			reg = <0x0 0xc110000 0x0 0x1000>;
 			clocks = <&clockgen 4 3>, <&clockgen 4 3>;
-			clock-names = "apb_pclk", "wdog_clk";
+			clock-names = "wdog_clk", "apb_pclk";
 		};
 
 		cluster2_core2_watchdog: wdt@c120000 {
-			compatible = "arm,sp805-wdt", "arm,primecell";
+			compatible = "arm,sp805", "arm,primecell";
 			reg = <0x0 0xc120000 0x0 0x1000>;
 			clocks = <&clockgen 4 3>, <&clockgen 4 3>;
-			clock-names = "apb_pclk", "wdog_clk";
+			clock-names = "wdog_clk", "apb_pclk";
 		};
 
 		cluster2_core3_watchdog: wdt@c130000 {
-			compatible = "arm,sp805-wdt", "arm,primecell";
+			compatible = "arm,sp805", "arm,primecell";
 			reg = <0x0 0xc130000 0x0 0x1000>;
 			clocks = <&clockgen 4 3>, <&clockgen 4 3>;
-			clock-names = "apb_pclk", "wdog_clk";
+			clock-names = "wdog_clk", "apb_pclk";
 		};
 
 		fsl_mc: fsl-mc@80c000000 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi
@@ -227,59 +227,59 @@
 		};
 
 		cluster1_core0_watchdog: wdt@c000000 {
-			compatible = "arm,sp805-wdt", "arm,primecell";
+			compatible = "arm,sp805", "arm,primecell";
 			reg = <0x0 0xc000000 0x0 0x1000>;
 			clocks = <&clockgen 4 3>, <&clockgen 4 3>;
-			clock-names = "apb_pclk", "wdog_clk";
+			clock-names = "wdog_clk", "apb_pclk";
 		};
 
 		cluster1_core1_watchdog: wdt@c010000 {
-			compatible = "arm,sp805-wdt", "arm,primecell";
+			compatible = "arm,sp805", "arm,primecell";
 			reg = <0x0 0xc010000 0x0 0x1000>;
 			clocks = <&clockgen 4 3>, <&clockgen 4 3>;
-			clock-names = "apb_pclk", "wdog_clk";
+			clock-names = "wdog_clk", "apb_pclk";
 		};
 
 		cluster2_core0_watchdog: wdt@c100000 {
-			compatible = "arm,sp805-wdt", "arm,primecell";
+			compatible = "arm,sp805", "arm,primecell";
 			reg = <0x0 0xc100000 0x0 0x1000>;
 			clocks = <&clockgen 4 3>, <&clockgen 4 3>;
-			clock-names = "apb_pclk", "wdog_clk";
+			clock-names = "wdog_clk", "apb_pclk";
 		};
 
 		cluster2_core1_watchdog: wdt@c110000 {
-			compatible = "arm,sp805-wdt", "arm,primecell";
+			compatible = "arm,sp805", "arm,primecell";
 			reg = <0x0 0xc110000 0x0 0x1000>;
 			clocks = <&clockgen 4 3>, <&clockgen 4 3>;
-			clock-names = "apb_pclk", "wdog_clk";
+			clock-names = "wdog_clk", "apb_pclk";
 		};
 
 		cluster3_core0_watchdog: wdt@c200000 {
-			compatible = "arm,sp805-wdt", "arm,primecell";
+			compatible = "arm,sp805", "arm,primecell";
 			reg = <0x0 0xc200000 0x0 0x1000>;
 			clocks = <&clockgen 4 3>, <&clockgen 4 3>;
-			clock-names = "apb_pclk", "wdog_clk";
+			clock-names = "wdog_clk", "apb_pclk";
 		};
 
 		cluster3_core1_watchdog: wdt@c210000 {
-			compatible = "arm,sp805-wdt", "arm,primecell";
+			compatible = "arm,sp805", "arm,primecell";
 			reg = <0x0 0xc210000 0x0 0x1000>;
 			clocks = <&clockgen 4 3>, <&clockgen 4 3>;
-			clock-names = "apb_pclk", "wdog_clk";
+			clock-names = "wdog_clk", "apb_pclk";
 		};
 
 		cluster4_core0_watchdog: wdt@c300000 {
-			compatible = "arm,sp805-wdt", "arm,primecell";
+			compatible = "arm,sp805", "arm,primecell";
 			reg = <0x0 0xc300000 0x0 0x1000>;
 			clocks = <&clockgen 4 3>, <&clockgen 4 3>;
-			clock-names = "apb_pclk", "wdog_clk";
+			clock-names = "wdog_clk", "apb_pclk";
 		};
 
 		cluster4_core1_watchdog: wdt@c310000 {
-			compatible = "arm,sp805-wdt", "arm,primecell";
+			compatible = "arm,sp805", "arm,primecell";
 			reg = <0x0 0xc310000 0x0 0x1000>;
 			clocks = <&clockgen 4 3>, <&clockgen 4 3>;
-			clock-names = "apb_pclk", "wdog_clk";
+			clock-names = "wdog_clk", "apb_pclk";
 		};
 
 		crypto: crypto@8000000 {
@@ -501,7 +501,6 @@
 			clocks = <&clockgen 4 3>;
 			clock-names = "dspi";
 			spi-num-chipselects = <5>;
-			bus-num = <0>;
 		};
 
 		esdhc: esdhc@2140000 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/freescale/imx8mm-evk.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/freescale/imx8mm-evk.dts
@@ -62,6 +62,8 @@
 
 		cpudai: simple-audio-card,cpu {
 			sound-dai = <&sai3>;
+			dai-tdm-slot-num = <2>;
+			dai-tdm-slot-width = <32>;
 		};
 
 		simple-audio-card,codec {
@@ -229,7 +231,7 @@
 
 			ldo1_reg: LDO1 {
 				regulator-name = "LDO1";
-				regulator-min-microvolt = <3000000>;
+				regulator-min-microvolt = <1600000>;
 				regulator-max-microvolt = <3300000>;
 				regulator-boot-on;
 				regulator-always-on;
@@ -237,7 +239,7 @@
 
 			ldo2_reg: LDO2 {
 				regulator-name = "LDO2";
-				regulator-min-microvolt = <900000>;
+				regulator-min-microvolt = <800000>;
 				regulator-max-microvolt = <900000>;
 				regulator-boot-on;
 				regulator-always-on;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/freescale/imx8mm-pinfunc.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/freescale/imx8mm-pinfunc.h
@@ -124,7 +124,7 @@
 #define MX8MM_IOMUXC_SD1_CMD_USDHC1_CMD                                     0x0A4 0x30C 0x000 0x0 0x0
 #define MX8MM_IOMUXC_SD1_CMD_GPIO2_IO1                                      0x0A4 0x30C 0x000 0x5 0x0
 #define MX8MM_IOMUXC_SD1_DATA0_USDHC1_DATA0                                 0x0A8 0x310 0x000 0x0 0x0
-#define MX8MM_IOMUXC_SD1_DATA0_GPIO2_IO2                                    0x0A8 0x31  0x000 0x5 0x0
+#define MX8MM_IOMUXC_SD1_DATA0_GPIO2_IO2                                    0x0A8 0x310 0x000 0x5 0x0
 #define MX8MM_IOMUXC_SD1_DATA1_USDHC1_DATA1                                 0x0AC 0x314 0x000 0x0 0x0
 #define MX8MM_IOMUXC_SD1_DATA1_GPIO2_IO3                                    0x0AC 0x314 0x000 0x5 0x0
 #define MX8MM_IOMUXC_SD1_DATA2_USDHC1_DATA2                                 0x0B0 0x318 0x000 0x0 0x0
@@ -585,7 +585,7 @@
 #define MX8MM_IOMUXC_UART1_RXD_GPIO5_IO22                                   0x234 0x49C 0x000 0x5 0x0
 #define MX8MM_IOMUXC_UART1_RXD_TPSMP_HDATA24                                0x234 0x49C 0x000 0x7 0x0
 #define MX8MM_IOMUXC_UART1_TXD_UART1_DCE_TX                                 0x238 0x4A0 0x000 0x0 0x0
-#define MX8MM_IOMUXC_UART1_TXD_UART1_DTE_RX                                 0x238 0x4A0 0x4F4 0x0 0x0
+#define MX8MM_IOMUXC_UART1_TXD_UART1_DTE_RX                                 0x238 0x4A0 0x4F4 0x0 0x1
 #define MX8MM_IOMUXC_UART1_TXD_ECSPI3_MOSI                                  0x238 0x4A0 0x000 0x1 0x0
 #define MX8MM_IOMUXC_UART1_TXD_GPIO5_IO23                                   0x238 0x4A0 0x000 0x5 0x0
 #define MX8MM_IOMUXC_UART1_TXD_TPSMP_HDATA25                                0x238 0x4A0 0x000 0x7 0x0
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/freescale/imx8mm.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/freescale/imx8mm.dtsi
@@ -126,7 +126,7 @@
 
 		opp-1600000000 {
 			opp-hz = /bits/ 64 <1600000000>;
-			opp-microvolt = <900000>;
+			opp-microvolt = <950000>;
 			opp-supported-hw = <0xc>, <0x7>;
 			clock-latency-ns = <150000>;
 			opp-suspend;
@@ -479,14 +479,18 @@
 						<&clk IMX8MM_CLK_AUDIO_AHB>,
 						<&clk IMX8MM_CLK_IPG_AUDIO_ROOT>,
 						<&clk IMX8MM_SYS_PLL3>,
-						<&clk IMX8MM_VIDEO_PLL1>;
+						<&clk IMX8MM_VIDEO_PLL1>,
+						<&clk IMX8MM_AUDIO_PLL1>,
+						<&clk IMX8MM_AUDIO_PLL2>;
 				assigned-clock-parents = <&clk IMX8MM_SYS_PLL3_OUT>,
 							 <&clk IMX8MM_SYS_PLL1_800M>;
 				assigned-clock-rates = <0>,
 							<400000000>,
 							<400000000>,
 							<750000000>,
-							<594000000>;
+							<594000000>,
+							<393216000>,
+							<361267200>;
 			};
 
 			src: reset-controller@30390000 {
@@ -741,7 +745,7 @@
 				reg = <0x30bd0000 0x10000>;
 				interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clk IMX8MM_CLK_SDMA1_ROOT>,
-					 <&clk IMX8MM_CLK_SDMA1_ROOT>;
+					 <&clk IMX8MM_CLK_AHB>;
 				clock-names = "ipg", "ahb";
 				#dma-cells = <3>;
 				fsl,sdma-ram-script-name = "imx/sdma/sdma-imx7d.bin";
@@ -834,10 +838,10 @@
 			clocks = <&clk IMX8MM_CLK_NAND_USDHC_BUS_RAWNAND_CLK>;
 		};
 
-		gpmi: nand-controller@33002000{
+		gpmi: nand-controller@33002000 {
 			compatible = "fsl,imx8mm-gpmi-nand", "fsl,imx7d-gpmi-nand";
 			#address-cells = <1>;
-			#size-cells = <1>;
+			#size-cells = <0>;
 			reg = <0x33002000 0x2000>, <0x33004000 0x4000>;
 			reg-names = "gpmi-nand", "bch";
 			interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/freescale/imx8mn-ddr4-evk.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/freescale/imx8mn-ddr4-evk.dts
@@ -213,6 +213,10 @@
 		interrupts = <3 GPIO_ACTIVE_LOW>;
 		rohm,reset-snvs-powered;
 
+		#clock-cells = <0>;
+		clocks = <&osc_32k 0>;
+		clock-output-names = "clk-32k-out";
+
 		regulators {
 			buck1_reg: BUCK1 {
 				regulator-name = "BUCK1";
@@ -268,7 +272,7 @@
 
 			ldo1_reg: LDO1 {
 				regulator-name = "LDO1";
-				regulator-min-microvolt = <3000000>;
+				regulator-min-microvolt = <1600000>;
 				regulator-max-microvolt = <3300000>;
 				regulator-boot-on;
 				regulator-always-on;
@@ -276,7 +280,7 @@
 
 			ldo2_reg: LDO2 {
 				regulator-name = "LDO2";
-				regulator-min-microvolt = <900000>;
+				regulator-min-microvolt = <800000>;
 				regulator-max-microvolt = <900000>;
 				regulator-boot-on;
 				regulator-always-on;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/freescale/imx8mn.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/freescale/imx8mn.dtsi
@@ -616,7 +616,7 @@
 				reg = <0x30bd0000 0x10000>;
 				interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clk IMX8MN_CLK_SDMA1_ROOT>,
-					 <&clk IMX8MN_CLK_SDMA1_ROOT>;
+					 <&clk IMX8MN_CLK_AHB>;
 				clock-names = "ipg", "ahb";
 				#dma-cells = <3>;
 				fsl,sdma-ram-script-name = "imx/sdma/sdma-imx7d.bin";
@@ -677,28 +677,6 @@
 				#index-cells = <1>;
 				reg = <0x32e40200 0x200>;
 			};
-
-			usbotg2: usb@32e50000 {
-				compatible = "fsl,imx8mn-usb", "fsl,imx7d-usb";
-				reg = <0x32e50000 0x200>;
-				interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
-				clocks = <&clk IMX8MN_CLK_USB1_CTRL_ROOT>;
-				clock-names = "usb1_ctrl_root_clk";
-				assigned-clocks = <&clk IMX8MN_CLK_USB_BUS>,
-						  <&clk IMX8MN_CLK_USB_CORE_REF>;
-				assigned-clock-parents = <&clk IMX8MN_SYS_PLL2_500M>,
-							 <&clk IMX8MN_SYS_PLL1_100M>;
-				fsl,usbphy = <&usbphynop2>;
-				fsl,usbmisc = <&usbmisc2 0>;
-				status = "disabled";
-			};
-
-			usbmisc2: usbmisc@32e50200 {
-				compatible = "fsl,imx8mn-usbmisc", "fsl,imx7d-usbmisc";
-				#index-cells = <1>;
-				reg = <0x32e50200 0x200>;
-			};
-
 		};
 
 		dma_apbh: dma-controller@33000000 {
@@ -717,7 +695,7 @@
 		gpmi: nand-controller@33002000 {
 			compatible = "fsl,imx8mn-gpmi-nand", "fsl,imx7d-gpmi-nand";
 			#address-cells = <1>;
-			#size-cells = <1>;
+			#size-cells = <0>;
 			reg = <0x33002000 0x2000>, <0x33004000 0x4000>;
 			reg-names = "gpmi-nand", "bch";
 			interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
@@ -744,14 +722,6 @@
 		compatible = "usb-nop-xceiv";
 		clocks = <&clk IMX8MN_CLK_USB_PHY_REF>;
 		assigned-clocks = <&clk IMX8MN_CLK_USB_PHY_REF>;
-		assigned-clock-parents = <&clk IMX8MN_SYS_PLL1_100M>;
-		clock-names = "main_clk";
-	};
-
-	usbphynop2: usbphynop2 {
-		compatible = "usb-nop-xceiv";
-		clocks = <&clk IMX8MN_CLK_USB_PHY_REF>;
-		assigned-clocks = <&clk IMX8MN_CLK_USB_PHY_REF>;
 		assigned-clock-parents = <&clk IMX8MN_SYS_PLL1_100M>;
 		clock-names = "main_clk";
 	};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts
@@ -421,7 +421,7 @@
 		pinctrl-names = "default";
 		pinctrl-0 = <&pinctrl_imu>;
 		interrupt-parent = <&gpio3>;
-		interrupts = <19 IRQ_TYPE_LEVEL_LOW>;
+		interrupts = <19 IRQ_TYPE_LEVEL_HIGH>;
 		vdd-supply = <&reg_3v3_p>;
 		vddio-supply = <&reg_3v3_p>;
 	};
@@ -743,6 +743,7 @@
 };
 
 &usb3_phy0 {
+	vbus-supply = <&reg_5v_p>;
 	status = "okay";
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/freescale/imx8mq-pinfunc.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/freescale/imx8mq-pinfunc.h
@@ -130,7 +130,7 @@
 #define MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD                                     0x0A4 0x30C 0x000 0x0 0x0
 #define MX8MQ_IOMUXC_SD1_CMD_GPIO2_IO1                                      0x0A4 0x30C 0x000 0x5 0x0
 #define MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0                                 0x0A8 0x310 0x000 0x0 0x0
-#define MX8MQ_IOMUXC_SD1_DATA0_GPIO2_IO2                                    0x0A8 0x31  0x000 0x5 0x0
+#define MX8MQ_IOMUXC_SD1_DATA0_GPIO2_IO2                                    0x0A8 0x310 0x000 0x5 0x0
 #define MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1                                 0x0AC 0x314 0x000 0x0 0x0
 #define MX8MQ_IOMUXC_SD1_DATA1_GPIO2_IO3                                    0x0AC 0x314 0x000 0x5 0x0
 #define MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2                                 0x0B0 0x318 0x000 0x0 0x0
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/freescale/imx8mq-zii-ultra.dtsi
@@ -45,8 +45,8 @@
 	reg_12p0_main: regulator-12p0-main {
 		compatible = "regulator-fixed";
 		regulator-name = "12V_MAIN";
-		regulator-min-microvolt = <5000000>;
-		regulator-max-microvolt = <5000000>;
+		regulator-min-microvolt = <12000000>;
+		regulator-max-microvolt = <12000000>;
 		regulator-always-on;
 	};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/freescale/imx8mq.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/freescale/imx8mq.dtsi
@@ -349,7 +349,7 @@
 			tmu: tmu@30260000 {
 				compatible = "fsl,imx8mq-tmu";
 				reg = <0x30260000 0x10000>;
-				interrupt = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
+				interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&clk IMX8MQ_CLK_TMU_ROOT>;
 				little-endian;
 				fsl,tmu-range = <0xb0000 0xa0026 0x80048 0x70061>;
@@ -516,6 +516,7 @@
 			gpc: gpc@303a0000 {
 				compatible = "fsl,imx8mq-gpc";
 				reg = <0x303a0000 0x10000>;
+				interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
 				interrupt-parent = <&gic>;
 				interrupt-controller;
 				#interrupt-cells = <3>;
@@ -1055,6 +1056,14 @@
 			         <&src IMX8MQ_RESET_PCIE_CTRL_APPS_EN>,
 			         <&src IMX8MQ_RESET_PCIE_CTRL_APPS_TURNOFF>;
 			reset-names = "pciephy", "apps", "turnoff";
+			assigned-clocks = <&clk IMX8MQ_CLK_PCIE1_CTRL>,
+			                  <&clk IMX8MQ_CLK_PCIE1_PHY>,
+			                  <&clk IMX8MQ_CLK_PCIE1_AUX>;
+			assigned-clock-parents = <&clk IMX8MQ_SYS2_PLL_250M>,
+			                         <&clk IMX8MQ_SYS2_PLL_100M>,
+			                         <&clk IMX8MQ_SYS1_PLL_80M>;
+			assigned-clock-rates = <250000000>, <100000000>,
+			                       <10000000>;
 			status = "disabled";
 		};
 
@@ -1084,6 +1093,14 @@
 			         <&src IMX8MQ_RESET_PCIE2_CTRL_APPS_EN>,
 			         <&src IMX8MQ_RESET_PCIE2_CTRL_APPS_TURNOFF>;
 			reset-names = "pciephy", "apps", "turnoff";
+			assigned-clocks = <&clk IMX8MQ_CLK_PCIE2_CTRL>,
+			                  <&clk IMX8MQ_CLK_PCIE2_PHY>,
+			                  <&clk IMX8MQ_CLK_PCIE2_AUX>;
+			assigned-clock-parents = <&clk IMX8MQ_SYS2_PLL_250M>,
+			                         <&clk IMX8MQ_SYS2_PLL_100M>,
+			                         <&clk IMX8MQ_SYS1_PLL_80M>;
+			assigned-clock-rates = <250000000>, <100000000>,
+			                       <10000000>;
 			status = "disabled";
 		};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/freescale/imx8qxp-mek.dts
@@ -52,11 +52,6 @@
 			compatible = "ethernet-phy-ieee802.3-c22";
 			reg = <0>;
 		};
-
-		ethphy1: ethernet-phy@1 {
-			compatible = "ethernet-phy-ieee802.3-c22";
-			reg = <1>;
-		};
 	};
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts
@@ -530,6 +530,17 @@
 		status = "ok";
 		compatible = "adi,adv7533";
 		reg = <0x39>;
+		adi,dsi-lanes = <4>;
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			port@0 {
+				reg = <0>;
+			};
+			port@1 {
+				reg = <1>;
+			};
+		};
 	};
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
@@ -1086,7 +1086,7 @@
 		};
 
 		watchdog0: watchdog@e8a06000 {
-			compatible = "arm,sp805-wdt", "arm,primecell";
+			compatible = "arm,sp805", "arm,primecell";
 			reg = <0x0 0xe8a06000 0x0 0x1000>;
 			interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&crg_ctrl HI3660_OSC32K>;
@@ -1094,7 +1094,7 @@
 		};
 
 		watchdog1: watchdog@e8a07000 {
-			compatible = "arm,sp805-wdt", "arm,primecell";
+			compatible = "arm,sp805", "arm,primecell";
 			reg = <0x0 0xe8a07000 0x0 0x1000>;
 			interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&crg_ctrl HI3660_OSC32K>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/hisilicon/hi3798cv200.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/hisilicon/hi3798cv200.dtsi
@@ -58,7 +58,7 @@
 	gic: interrupt-controller@f1001000 {
 		compatible = "arm,gic-400";
 		reg = <0x0 0xf1001000 0x0 0x1000>,  /* GICD */
-		      <0x0 0xf1002000 0x0 0x100>;   /* GICC */
+		      <0x0 0xf1002000 0x0 0x2000>;  /* GICC */
 		#address-cells = <0>;
 		#interrupt-cells = <3>;
 		interrupt-controller;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
@@ -516,7 +516,7 @@
 		reg = <0x39>;
 		interrupt-parent = <&gpio1>;
 		interrupts = <1 2>;
-		pd-gpio = <&gpio0 4 0>;
+		pd-gpios = <&gpio0 4 0>;
 		adi,dsi-lanes = <4>;
 		#sound-dai-cells = <0>;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
@@ -839,7 +839,7 @@
 		};
 
 		watchdog0: watchdog@f8005000 {
-			compatible = "arm,sp805-wdt", "arm,primecell";
+			compatible = "arm,sp805", "arm,primecell";
 			reg = <0x0 0xf8005000 0x0 0x1000>;
 			interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&ao_ctrl HI6220_WDT0_PCLK>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/intel/socfpga_agilex.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/intel/socfpga_agilex.dtsi
@@ -47,10 +47,10 @@
 
 	pmu {
 		compatible = "arm,armv8-pmuv3";
-		interrupts = <0 120 8>,
-			     <0 121 8>,
-			     <0 122 8>,
-			     <0 123 8>;
+		interrupts = <0 170 4>,
+			     <0 171 4>,
+			     <0 172 4>,
+			     <0 173 4>;
 		interrupt-affinity = <&cpu0>,
 				     <&cpu1>,
 				     <&cpu2>,
@@ -82,7 +82,7 @@
 		ranges = <0 0 0 0xffffffff>;
 
 		gmac0: ethernet@ff800000 {
-			compatible = "altr,socfpga-stmmac", "snps,dwmac-3.74a", "snps,dwmac";
+			compatible = "altr,socfpga-stmmac-a10-s10", "snps,dwmac-3.74a", "snps,dwmac";
 			reg = <0xff800000 0x2000>;
 			interrupts = <0 90 4>;
 			interrupt-names = "macirq";
@@ -97,7 +97,7 @@
 		};
 
 		gmac1: ethernet@ff802000 {
-			compatible = "altr,socfpga-stmmac", "snps,dwmac-3.74a", "snps,dwmac";
+			compatible = "altr,socfpga-stmmac-a10-s10", "snps,dwmac-3.74a", "snps,dwmac";
 			reg = <0xff802000 0x2000>;
 			interrupts = <0 91 4>;
 			interrupt-names = "macirq";
@@ -112,7 +112,7 @@
 		};
 
 		gmac2: ethernet@ff804000 {
-			compatible = "altr,socfpga-stmmac", "snps,dwmac-3.74a", "snps,dwmac";
+			compatible = "altr,socfpga-stmmac-a10-s10", "snps,dwmac-3.74a", "snps,dwmac";
 			reg = <0xff804000 0x2000>;
 			interrupts = <0 92 4>;
 			interrupt-names = "macirq";
@@ -369,7 +369,7 @@
 		};
 
 		usb0: usb@ffb00000 {
-			compatible = "snps,dwc2";
+			compatible = "intel,socfpga-agilex-hsotg", "snps,dwc2";
 			reg = <0xffb00000 0x40000>;
 			interrupts = <0 93 4>;
 			phys = <&usbphy0>;
@@ -381,7 +381,7 @@
 		};
 
 		usb1: usb@ffb40000 {
-			compatible = "snps,dwc2";
+			compatible = "intel,socfpga-agilex-hsotg", "snps,dwc2";
 			reg = <0xffb40000 0x40000>;
 			interrupts = <0 94 4>;
 			phys = <&usbphy0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/marvell/armada-3720-db.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/marvell/armada-3720-db.dts
@@ -128,6 +128,9 @@
 
 /* CON15(V2.0)/CON17(V1.4) : PCIe / CON15(V2.0)/CON12(V1.4) :mini-PCIe */
 &pcie0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie_reset_pins &pcie_clkreq_pins>;
+	reset-gpios = <&gpiosb 3 GPIO_ACTIVE_LOW>;
 	status = "okay";
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts
@@ -19,6 +19,16 @@
 	model = "Globalscale Marvell ESPRESSOBin Board";
 	compatible = "globalscale,espressobin", "marvell,armada3720", "marvell,armada3710";
 
+	aliases {
+		ethernet0 = &eth0;
+		/* for dsa slave device */
+		ethernet1 = &switch0port1;
+		ethernet2 = &switch0port2;
+		ethernet3 = &switch0port3;
+		serial0 = &uart0;
+		serial1 = &uart1;
+	};
+
 	chosen {
 		stdout-path = "serial0:115200n8";
 	};
@@ -49,6 +59,7 @@
 	phys = <&comphy1 0>;
 	pinctrl-names = "default";
 	pinctrl-0 = <&pcie_reset_pins &pcie_clkreq_pins>;
+	reset-gpios = <&gpiosb 3 GPIO_ACTIVE_LOW>;
 };
 
 /* J6 */
@@ -141,7 +152,7 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 
-			port@0 {
+			switch0port0: port@0 {
 				reg = <0>;
 				label = "cpu";
 				ethernet = <&eth0>;
@@ -152,19 +163,19 @@
 				};
 			};
 
-			port@1 {
+			switch0port1: port@1 {
 				reg = <1>;
 				label = "wan";
 				phy-handle = <&switch0phy0>;
 			};
 
-			port@2 {
+			switch0port2: port@2 {
 				reg = <2>;
 				label = "lan0";
 				phy-handle = <&switch0phy1>;
 			};
 
-			port@3 {
+			switch0port3: port@3 {
 				reg = <3>;
 				label = "lan1";
 				phy-handle = <&switch0phy2>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts
@@ -18,6 +18,7 @@
 
 	aliases {
 		spi0 = &spi0;
+		ethernet0 = &eth0;
 		ethernet1 = &eth1;
 	};
 
@@ -95,7 +96,7 @@
 	};
 
 	sfp: sfp {
-		compatible = "sff,sfp+";
+		compatible = "sff,sfp";
 		i2c-bus = <&i2c0>;
 		los-gpio = <&moxtet_sfp 0 GPIO_ACTIVE_HIGH>;
 		tx-fault-gpio = <&moxtet_sfp 1 GPIO_ACTIVE_HIGH>;
@@ -106,24 +107,30 @@
 		/* enabled by U-Boot if SFP module is present */
 		status = "disabled";
 	};
+
+	firmware {
+		armada-3700-rwtm {
+			compatible = "marvell,armada-3700-rwtm-firmware", "cznic,turris-mox-rwtm";
+		};
+	};
 };
 
 &i2c0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&i2c1_pins>;
 	clock-frequency = <100000>;
+	/delete-property/ mrvl,i2c-fast-mode;
 	status = "okay";
 
+	/* MCP7940MT-I/MNY RTC */
 	rtc@6f {
 		compatible = "microchip,mcp7940x";
 		reg = <0x6f>;
+		interrupt-parent = <&gpiosb>;
+		interrupts = <5 IRQ_TYPE_EDGE_FALLING>; /* GPIO2_5 */
 	};
 };
 
-&pcie_reset_pins {
-	function = "gpio";
-};
-
 &pcie0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pcie_reset_pins &pcie_clkreq_pins>;
@@ -131,6 +138,28 @@
 	max-link-speed = <2>;
 	reset-gpios = <&gpiosb 3 GPIO_ACTIVE_LOW>;
 	phys = <&comphy1 0>;
+	/*
+	 * U-Boot port for Turris Mox has a bug which always expects that "ranges" DT property
+	 * contains exactly 2 ranges with 3 (child) address cells, 2 (parent) address cells and
+	 * 2 size cells and also expects that the second range starts at 16 MB offset. Also it
+	 * expects that first range uses same address for PCI (child) and CPU (parent) cells (so
+	 * no remapping) and that this address is the lowest from all specified ranges. If these
+	 * conditions are not met then U-Boot crashes during loading kernel DTB file. PCIe address
+	 * space is 128 MB long, so the best split between MEM and IO is to use fixed 16 MB window
+	 * for IO and the rest 112 MB (64+32+16) for MEM, despite that maximal IO size is just 64 kB.
+	 * This bug is not present in U-Boot ports for other Armada 3700 devices and is fixed in
+	 * U-Boot version 2021.07. See relevant U-Boot commits (the last one contains fix):
+	 * https://source.denx.de/u-boot/u-boot/-/commit/cb2ddb291ee6fcbddd6d8f4ff49089dfe580f5d7
+	 * https://source.denx.de/u-boot/u-boot/-/commit/c64ac3b3185aeb3846297ad7391fc6df8ecd73bf
+	 * https://source.denx.de/u-boot/u-boot/-/commit/4a82fca8e330157081fc132a591ebd99ba02ee33
+	 * Bug related to requirement of same child and parent addresses for first range is fixed
+	 * in U-Boot version 2022.04 by following commit:
+	 * https://source.denx.de/u-boot/u-boot/-/commit/1fd54253bca7d43d046bba4853fe5fafd034bc17
+	 */
+	#address-cells = <3>;
+	#size-cells = <2>;
+	ranges = <0x81000000 0 0xe8000000   0 0xe8000000   0 0x01000000   /* Port 0 IO */
+		  0x82000000 0 0xe9000000   0 0xe9000000   0 0x07000000>; /* Port 0 MEM */
 
 	/* enabled by U-Boot if PCIe module is present */
 	status = "disabled";
@@ -144,7 +173,7 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&rgmii_pins>;
 	phy-mode = "rgmii-id";
-	phy = <&phy1>;
+	phy-handle = <&phy1>;
 	status = "okay";
 };
 
@@ -171,6 +200,8 @@
 	marvell,pad-type = "sd";
 	vqmmc-supply = <&vsdio_reg>;
 	mmc-pwrseq = <&sdhci1_pwrseq>;
+	/* forbid SDR104 for FCC purposes */
+	sdhci-caps-mask = <0x2 0x0>;
 	status = "okay";
 };
 
@@ -200,7 +231,7 @@
 			};
 
 			partition@20000 {
-				label = "u-boot";
+				label = "a53-firmware";
 				reg = <0x20000 0x160000>;
 			};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/marvell/armada-3720-uDPU.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/marvell/armada-3720-uDPU.dts
@@ -143,6 +143,7 @@
 	phy-mode = "sgmii";
 	status = "okay";
 	managed = "in-band-status";
+	phys = <&comphy1 0>;
 	sfp = <&sfp_eth0>;
 };
 
@@ -150,11 +151,14 @@
 	phy-mode = "sgmii";
 	status = "okay";
 	managed = "in-band-status";
+	phys = <&comphy0 1>;
 	sfp = <&sfp_eth1>;
 };
 
 &usb3 {
 	status = "okay";
+	phys = <&usb2_utmi_otg_phy>;
+	phy-names = "usb2-utmi-otg-phy";
 };
 
 &uart0 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
@@ -134,7 +134,7 @@
 
 			uart0: serial@12000 {
 				compatible = "marvell,armada-3700-uart";
-				reg = <0x12000 0x200>;
+				reg = <0x12000 0x18>;
 				clocks = <&xtalclk>;
 				interrupts =
 				<GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
@@ -156,7 +156,8 @@
 			};
 
 			nb_periph_clk: nb-periph-clk@13000 {
-				compatible = "marvell,armada-3700-periph-clock-nb";
+				compatible = "marvell,armada-3700-periph-clock-nb",
+					     "syscon";
 				reg = <0x13000 0x100>;
 				clocks = <&tbg 0>, <&tbg 1>, <&tbg 2>,
 				<&tbg 3>, <&xtalclk>;
@@ -317,7 +318,7 @@
 
 				pcie_reset_pins: pcie-reset-pins {
 					groups = "pcie1";
-					function = "pcie";
+					function = "gpio";
 				};
 
 				pcie_clkreq_pins: pcie-clkreq-pins {
@@ -486,8 +487,15 @@
 			#interrupt-cells = <1>;
 			msi-parent = <&pcie0>;
 			msi-controller;
-			ranges = <0x82000000 0 0xe8000000   0 0xe8000000 0 0x1000000 /* Port 0 MEM */
-				  0x81000000 0 0xe9000000   0 0xe9000000 0 0x10000>; /* Port 0 IO*/
+			/*
+			 * The 128 MiB address range [0xe8000000-0xf0000000] is
+			 * dedicated for PCIe and can be assigned to 8 windows
+			 * with size a power of two. Use one 64 KiB window for
+			 * IO at the end and the remaining seven windows
+			 * (totaling 127 MiB) for MEM.
+			 */
+			ranges = <0x82000000 0 0xe8000000   0 0xe8000000   0 0x07f00000   /* Port 0 MEM */
+				  0x81000000 0 0x00000000   0 0xefff0000   0 0x00010000>; /* Port 0 IO */
 			interrupt-map-mask = <0 0 0 7>;
 			interrupt-map = <0 0 0 1 &pcie_intc 0>,
 					<0 0 0 2 &pcie_intc 1>,
@@ -499,4 +507,12 @@
 			};
 		};
 	};
+
+	firmware {
+		armada-3700-rwtm {
+			compatible = "marvell,armada-3700-rwtm-firmware";
+			mboxes = <&rwtm 0>;
+			status = "okay";
+		};
+	};
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts
@@ -367,6 +367,7 @@
 		pinctrl-0 = <&cp0_copper_eth_phy_reset>;
 		reset-gpios = <&cp0_gpio2 11 GPIO_ACTIVE_LOW>;
 		reset-assert-us = <10000>;
+		reset-deassert-us = <10000>;
 	};
 
 	switch0: switch0@4 {
@@ -408,6 +409,8 @@
 				reg = <5>;
 				label = "cpu";
 				ethernet = <&cp1_eth2>;
+				phy-mode = "2500base-x";
+				managed = "in-band-status";
 			};
 		};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dtsi
@@ -71,6 +71,7 @@
 		tx-fault-gpio  = <&cp1_gpio1 26 GPIO_ACTIVE_HIGH>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&cp1_sfpp0_pins>;
+		maximum-power-milliwatt = <2000>;
 	};
 
 	sfp_eth1: sfp-eth1 {
@@ -83,6 +84,7 @@
 		tx-fault-gpio = <&cp0_gpio2 30 GPIO_ACTIVE_HIGH>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&cp1_sfpp1_pins &cp0_sfpp1_pins>;
+		maximum-power-milliwatt = <2000>;
 	};
 
 	sfp_eth3: sfp-eth3 {
@@ -95,6 +97,7 @@
 		tx-fault-gpio = <&cp0_gpio2 19 GPIO_ACTIVE_HIGH>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&cp0_sfp_1g_pins &cp1_sfp_1g_pins>;
+		maximum-power-milliwatt = <2000>;
 	};
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/marvell/armada-ap806-dual.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/marvell/armada-ap806-dual.dtsi
@@ -21,6 +21,7 @@
 			reg = <0x000>;
 			enable-method = "psci";
 			#cooling-cells = <2>;
+			clocks = <&cpu_clk 0>;
 		};
 		cpu1: cpu@1 {
 			device_type = "cpu";
@@ -28,6 +29,7 @@
 			reg = <0x001>;
 			enable-method = "psci";
 			#cooling-cells = <2>;
+			clocks = <&cpu_clk 0>;
 		};
 	};
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/marvell/armada-cp110.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/marvell/armada-cp110.dtsi
@@ -438,10 +438,10 @@
 
 		CP110_LABEL(nand_controller): nand@720000 {
 			/*
-			* Due to the limitation of the pins available
-			* this controller is only usable on the CPM
-			* for A7K and on the CPS for A8K.
-			*/
+			 * Due to the limitation of the pins available
+			 * this controller is only usable on the CPM
+			 * for A7K and on the CPS for A8K.
+			 */
 			compatible = "marvell,armada-8k-nand-controller",
 				"marvell,armada370-nand-controller";
 			reg = <0x720000 0x54>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/mediatek/mt2712-evb.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/mediatek/mt2712-evb.dts
@@ -26,14 +26,14 @@
 		stdout-path = "serial0:921600n8";
 	};
 
-	cpus_fixed_vproc0: fixedregulator@0 {
+	cpus_fixed_vproc0: regulator-vproc-buck0 {
 		compatible = "regulator-fixed";
 		regulator-name = "vproc_buck0";
 		regulator-min-microvolt = <1000000>;
 		regulator-max-microvolt = <1000000>;
 	};
 
-	cpus_fixed_vproc1: fixedregulator@1 {
+	cpus_fixed_vproc1: regulator-vproc-buck1 {
 		compatible = "regulator-fixed";
 		regulator-name = "vproc_buck1";
 		regulator-min-microvolt = <1000000>;
@@ -50,7 +50,7 @@
 		id-gpio = <&pio 14 GPIO_ACTIVE_HIGH>;
 	};
 
-	usb_p0_vbus: regulator@2 {
+	usb_p0_vbus: regulator-usb-p0-vbus {
 		compatible = "regulator-fixed";
 		regulator-name = "p0_vbus";
 		regulator-min-microvolt = <5000000>;
@@ -59,7 +59,7 @@
 		enable-active-high;
 	};
 
-	usb_p1_vbus: regulator@3 {
+	usb_p1_vbus: regulator-usb-p1-vbus {
 		compatible = "regulator-fixed";
 		regulator-name = "p1_vbus";
 		regulator-min-microvolt = <5000000>;
@@ -68,7 +68,7 @@
 		enable-active-high;
 	};
 
-	usb_p2_vbus: regulator@4 {
+	usb_p2_vbus: regulator-usb-p2-vbus {
 		compatible = "regulator-fixed";
 		regulator-name = "p2_vbus";
 		regulator-min-microvolt = <5000000>;
@@ -77,7 +77,7 @@
 		enable-active-high;
 	};
 
-	usb_p3_vbus: regulator@5 {
+	usb_p3_vbus: regulator-usb-p3-vbus {
 		compatible = "regulator-fixed";
 		regulator-name = "p3_vbus";
 		regulator-min-microvolt = <5000000>;
@@ -105,15 +105,89 @@
 	proc-supply = <&cpus_fixed_vproc1>;
 };
 
+&eth {
+	phy-mode ="rgmii-rxid";
+	phy-handle = <&ethernet_phy0>;
+	mediatek,tx-delay-ps = <1530>;
+	snps,reset-gpio = <&pio 87 GPIO_ACTIVE_LOW>;
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&eth_default>;
+	pinctrl-1 = <&eth_sleep>;
+	status = "okay";
+
+	mdio {
+		compatible = "snps,dwmac-mdio";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		ethernet_phy0: ethernet-phy@5 {
+			compatible = "ethernet-phy-id0243.0d90";
+			reg = <0x5>;
+		};
+	};
+};
+
 &pio {
-	usb0_id_pins_float: usb0_iddig {
+	eth_default: eth-default-pins {
+		tx_pins {
+			pinmux = <MT2712_PIN_71_GBE_TXD3__FUNC_GBE_TXD3>,
+				 <MT2712_PIN_72_GBE_TXD2__FUNC_GBE_TXD2>,
+				 <MT2712_PIN_73_GBE_TXD1__FUNC_GBE_TXD1>,
+				 <MT2712_PIN_74_GBE_TXD0__FUNC_GBE_TXD0>,
+				 <MT2712_PIN_75_GBE_TXC__FUNC_GBE_TXC>,
+				 <MT2712_PIN_76_GBE_TXEN__FUNC_GBE_TXEN>;
+			drive-strength = <MTK_DRIVE_8mA>;
+		};
+		rx_pins {
+			pinmux = <MT2712_PIN_78_GBE_RXD3__FUNC_GBE_RXD3>,
+				 <MT2712_PIN_79_GBE_RXD2__FUNC_GBE_RXD2>,
+				 <MT2712_PIN_80_GBE_RXD1__FUNC_GBE_RXD1>,
+				 <MT2712_PIN_81_GBE_RXD0__FUNC_GBE_RXD0>,
+				 <MT2712_PIN_82_GBE_RXDV__FUNC_GBE_RXDV>,
+				 <MT2712_PIN_84_GBE_RXC__FUNC_GBE_RXC>;
+			input-enable;
+		};
+		mdio_pins {
+			pinmux = <MT2712_PIN_85_GBE_MDC__FUNC_GBE_MDC>,
+				 <MT2712_PIN_86_GBE_MDIO__FUNC_GBE_MDIO>;
+			drive-strength = <MTK_DRIVE_8mA>;
+			input-enable;
+		};
+	};
+
+	eth_sleep: eth-sleep-pins {
+		tx_pins {
+			pinmux = <MT2712_PIN_71_GBE_TXD3__FUNC_GPIO71>,
+				 <MT2712_PIN_72_GBE_TXD2__FUNC_GPIO72>,
+				 <MT2712_PIN_73_GBE_TXD1__FUNC_GPIO73>,
+				 <MT2712_PIN_74_GBE_TXD0__FUNC_GPIO74>,
+				 <MT2712_PIN_75_GBE_TXC__FUNC_GPIO75>,
+				 <MT2712_PIN_76_GBE_TXEN__FUNC_GPIO76>;
+		};
+		rx_pins {
+			pinmux = <MT2712_PIN_78_GBE_RXD3__FUNC_GPIO78>,
+				 <MT2712_PIN_79_GBE_RXD2__FUNC_GPIO79>,
+				 <MT2712_PIN_80_GBE_RXD1__FUNC_GPIO80>,
+				 <MT2712_PIN_81_GBE_RXD0__FUNC_GPIO81>,
+				 <MT2712_PIN_82_GBE_RXDV__FUNC_GPIO82>,
+				 <MT2712_PIN_84_GBE_RXC__FUNC_GPIO84>;
+			input-disable;
+		};
+		mdio_pins {
+			pinmux = <MT2712_PIN_85_GBE_MDC__FUNC_GPIO85>,
+				 <MT2712_PIN_86_GBE_MDIO__FUNC_GPIO86>;
+			input-disable;
+			bias-disable;
+		};
+	};
+
+	usb0_id_pins_float: usb0-iddig-pins {
 		pins_iddig {
 			pinmux = <MT2712_PIN_12_IDDIG_P0__FUNC_IDDIG_A>;
 			bias-pull-up;
 		};
 	};
 
-	usb1_id_pins_float: usb1_iddig {
+	usb1_id_pins_float: usb1-iddig-pins {
 		pins_iddig {
 			pinmux = <MT2712_PIN_14_IDDIG_P1__FUNC_IDDIG_B>;
 			bias-pull-up;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/mediatek/mt2712e.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/mediatek/mt2712e.dtsi
@@ -160,70 +160,70 @@
 		#clock-cells = <0>;
 	};
 
-	clk26m: oscillator@0 {
+	clk26m: oscillator-26m {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <26000000>;
 		clock-output-names = "clk26m";
 	};
 
-	clk32k: oscillator@1 {
+	clk32k: oscillator-32k {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <32768>;
 		clock-output-names = "clk32k";
 	};
 
-	clkfpc: oscillator@2 {
+	clkfpc: oscillator-50m {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <50000000>;
 		clock-output-names = "clkfpc";
 	};
 
-	clkaud_ext_i_0: oscillator@3 {
+	clkaud_ext_i_0: oscillator-aud0 {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <6500000>;
 		clock-output-names = "clkaud_ext_i_0";
 	};
 
-	clkaud_ext_i_1: oscillator@4 {
+	clkaud_ext_i_1: oscillator-aud1 {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <196608000>;
 		clock-output-names = "clkaud_ext_i_1";
 	};
 
-	clkaud_ext_i_2: oscillator@5 {
+	clkaud_ext_i_2: oscillator-aud2 {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <180633600>;
 		clock-output-names = "clkaud_ext_i_2";
 	};
 
-	clki2si0_mck_i: oscillator@6 {
+	clki2si0_mck_i: oscillator-i2s0 {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <30000000>;
 		clock-output-names = "clki2si0_mck_i";
 	};
 
-	clki2si1_mck_i: oscillator@7 {
+	clki2si1_mck_i: oscillator-i2s1 {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <30000000>;
 		clock-output-names = "clki2si1_mck_i";
 	};
 
-	clki2si2_mck_i: oscillator@8 {
+	clki2si2_mck_i: oscillator-i2s2 {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <30000000>;
 		clock-output-names = "clki2si2_mck_i";
 	};
 
-	clktdmin_mclk_i: oscillator@9 {
+	clktdmin_mclk_i: oscillator-mclk {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <30000000>;
@@ -249,10 +249,11 @@
 		#clock-cells = <1>;
 	};
 
-	infracfg: syscon@10001000 {
+	infracfg: clock-controller@10001000 {
 		compatible = "mediatek,mt2712-infracfg", "syscon";
 		reg = <0 0x10001000 0 0x1000>;
 		#clock-cells = <1>;
+		#reset-cells = <1>;
 	};
 
 	pericfg: syscon@10003000 {
@@ -266,7 +267,7 @@
 		reg = <0 0x10005000 0 0x1000>;
 	};
 
-	pio: pinctrl@10005000 {
+	pio: pinctrl@1000b000 {
 		compatible = "mediatek,mt2712-pinctrl";
 		reg = <0 0x1000b000 0 0x1000>;
 		mediatek,pctl-regmap = <&syscfg_pctl_a>;
@@ -632,6 +633,71 @@
 		status = "disabled";
 	};
 
+	stmmac_axi_setup: stmmac-axi-config {
+		snps,wr_osr_lmt = <0x7>;
+		snps,rd_osr_lmt = <0x7>;
+		snps,blen = <0 0 0 0 16 8 4>;
+	};
+
+	mtl_rx_setup: rx-queues-config {
+		snps,rx-queues-to-use = <1>;
+		snps,rx-sched-sp;
+		queue0 {
+			snps,dcb-algorithm;
+			snps,map-to-dma-channel = <0x0>;
+			snps,priority = <0x0>;
+		};
+	};
+
+	mtl_tx_setup: tx-queues-config {
+		snps,tx-queues-to-use = <3>;
+		snps,tx-sched-wrr;
+		queue0 {
+			snps,weight = <0x10>;
+			snps,dcb-algorithm;
+			snps,priority = <0x0>;
+		};
+		queue1 {
+			snps,weight = <0x11>;
+			snps,dcb-algorithm;
+			snps,priority = <0x1>;
+		};
+		queue2 {
+			snps,weight = <0x12>;
+			snps,dcb-algorithm;
+			snps,priority = <0x2>;
+		};
+	};
+
+	eth: ethernet@1101c000 {
+		compatible = "mediatek,mt2712-gmac";
+		reg = <0 0x1101c000 0 0x1300>;
+		interrupts = <GIC_SPI 237 IRQ_TYPE_LEVEL_LOW>;
+		interrupt-names = "macirq";
+		mac-address = [00 55 7b b5 7d f7];
+		clock-names = "axi",
+			      "apb",
+			      "mac_main",
+			      "ptp_ref";
+		clocks = <&pericfg CLK_PERI_GMAC>,
+			 <&pericfg CLK_PERI_GMAC_PCLK>,
+			 <&topckgen CLK_TOP_ETHER_125M_SEL>,
+			 <&topckgen CLK_TOP_ETHER_50M_SEL>;
+		assigned-clocks = <&topckgen CLK_TOP_ETHER_125M_SEL>,
+				  <&topckgen CLK_TOP_ETHER_50M_SEL>;
+		assigned-clock-parents = <&topckgen CLK_TOP_ETHERPLL_125M>,
+					 <&topckgen CLK_TOP_APLL1_D3>;
+		power-domains = <&scpsys MT2712_POWER_DOMAIN_AUDIO>;
+		mediatek,pericfg = <&pericfg>;
+		snps,axi-config = <&stmmac_axi_setup>;
+		snps,mtl-rx-config = <&mtl_rx_setup>;
+		snps,mtl-tx-config = <&mtl_tx_setup>;
+		snps,txpbl = <1>;
+		snps,rxpbl = <1>;
+		clk_csr = <0>;
+		status = "disabled";
+	};
+
 	mmc0: mmc@11230000 {
 		compatible = "mediatek,mt2712-mmc";
 		reg = <0 0x11230000 0 0x1000>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/mediatek/mt6797.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/mediatek/mt6797.dtsi
@@ -102,7 +102,7 @@
 		};
 	};
 
-	clk26m: oscillator@0 {
+	clk26m: oscillator-26m {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <26000000>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts
@@ -49,7 +49,7 @@
 		wps {
 			label = "wps";
 			linux,code = <KEY_WPS_BUTTON>;
-			gpios = <&pio 102 GPIO_ACTIVE_HIGH>;
+			gpios = <&pio 102 GPIO_ACTIVE_LOW>;
 		};
 	};
 
@@ -69,8 +69,9 @@
 		};
 	};
 
-	memory {
+	memory@40000000 {
 		reg = <0 0x40000000 0 0x40000000>;
+		device_type = "memory";
 	};
 
 	reg_1p8v: regulator-1p8v {
@@ -234,8 +235,8 @@
 	/* eMMC is shared pin with parallel NAND */
 	emmc_pins_default: emmc-pins-default {
 		mux {
-			function = "emmc", "emmc_rst";
-			groups = "emmc";
+			function = "emmc";
+			groups = "emmc", "emmc_rst";
 		};
 
 		/* "NDL0","NDL1","NDL2","NDL3","NDL4","NDL5","NDL6","NDL7",
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
@@ -55,8 +55,9 @@
 		};
 	};
 
-	memory {
+	memory@40000000 {
 		reg = <0 0x40000000 0 0x20000000>;
+		device_type = "memory";
 	};
 
 	reg_1p8v: regulator-1p8v {
@@ -197,8 +198,8 @@
 	/* eMMC is shared pin with parallel NAND */
 	emmc_pins_default: emmc-pins-default {
 		mux {
-			function = "emmc", "emmc_rst";
-			groups = "emmc";
+			function = "emmc";
+			groups = "emmc", "emmc_rst";
 		};
 
 		/* "NDL0","NDL1","NDL2","NDL3","NDL4","NDL5","NDL6","NDL7",
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/mediatek/mt7622.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/mediatek/mt7622.dtsi
@@ -244,7 +244,7 @@
 		clock-names = "hif_sel";
 	};
 
-	cir: cir@10009000 {
+	cir: ir-receiver@10009000 {
 		compatible = "mediatek,mt7622-cir";
 		reg = <0 0x10009000 0 0x1000>;
 		interrupts = <GIC_SPI 175 IRQ_TYPE_LEVEL_LOW>;
@@ -428,6 +428,7 @@
 	pwm: pwm@11006000 {
 		compatible = "mediatek,mt7622-pwm";
 		reg = <0 0x11006000 0 0x1000>;
+		#pwm-cells = <2>;
 		interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_LOW>;
 		clocks = <&topckgen CLK_TOP_PWM_SEL>,
 			 <&pericfg CLK_PERI_PWM_PD>,
@@ -506,7 +507,6 @@
 			 <&pericfg CLK_PERI_AUXADC_PD>;
 		clock-names = "therm", "auxadc";
 		resets = <&pericfg MT7622_PERI_THERM_SW_RST>;
-		reset-names = "therm";
 		mediatek,auxadc = <&auxadc>;
 		mediatek,apmixedsys = <&apmixedsys>;
 		nvmem-cells = <&thermal_calibration>;
@@ -686,6 +686,8 @@
 		clocks = <&pericfg CLK_PERI_MSDC30_0_PD>,
 			 <&topckgen CLK_TOP_MSDC50_0_SEL>;
 		clock-names = "source", "hclk";
+		resets = <&pericfg MT7622_PERI_MSDC0_SW_RST>;
+		reset-names = "hrst";
 		status = "disabled";
 	};
 
@@ -696,6 +698,8 @@
 		clocks = <&pericfg CLK_PERI_MSDC30_1_PD>,
 			 <&topckgen CLK_TOP_AXI_SEL>;
 		clock-names = "source", "hclk";
+		resets = <&pericfg MT7622_PERI_MSDC1_SW_RST>;
+		reset-names = "hrst";
 		status = "disabled";
 	};
 
@@ -896,9 +900,7 @@
 	};
 
 	eth: ethernet@1b100000 {
-		compatible = "mediatek,mt7622-eth",
-			     "mediatek,mt2701-eth",
-			     "syscon";
+		compatible = "mediatek,mt7622-eth";
 		reg = <0 0x1b100000 0 0x20000>;
 		interrupts = <GIC_SPI 223 IRQ_TYPE_LEVEL_LOW>,
 			     <GIC_SPI 224 IRQ_TYPE_LEVEL_LOW>,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/mediatek/mt8173-evb.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/mediatek/mt8173-evb.dts
@@ -43,7 +43,7 @@
 		id-gpio = <&pio 16 GPIO_ACTIVE_HIGH>;
 	};
 
-	usb_p1_vbus: regulator@0 {
+	usb_p1_vbus: regulator-usb-p1 {
 		compatible = "regulator-fixed";
 		regulator-name = "usb_vbus";
 		regulator-min-microvolt = <5000000>;
@@ -52,7 +52,7 @@
 		enable-active-high;
 	};
 
-	usb_p0_vbus: regulator@1 {
+	usb_p0_vbus: regulator-usb-p0 {
 		compatible = "regulator-fixed";
 		regulator-name = "vbus";
 		regulator-min-microvolt = <5000000>;
@@ -303,11 +303,10 @@
 		interrupt-controller;
 		#interrupt-cells = <2>;
 
-		mt6397regulator: mt6397regulator {
+		regulators {
 			compatible = "mediatek,mt6397-regulator";
 
 			mt6397_vpca15_reg: buck_vpca15 {
-				regulator-compatible = "buck_vpca15";
 				regulator-name = "vpca15";
 				regulator-min-microvolt = < 700000>;
 				regulator-max-microvolt = <1350000>;
@@ -316,7 +315,6 @@
 			};
 
 			mt6397_vpca7_reg: buck_vpca7 {
-				regulator-compatible = "buck_vpca7";
 				regulator-name = "vpca7";
 				regulator-min-microvolt = < 700000>;
 				regulator-max-microvolt = <1350000>;
@@ -325,7 +323,6 @@
 			};
 
 			mt6397_vsramca15_reg: buck_vsramca15 {
-				regulator-compatible = "buck_vsramca15";
 				regulator-name = "vsramca15";
 				regulator-min-microvolt = < 700000>;
 				regulator-max-microvolt = <1350000>;
@@ -334,7 +331,6 @@
 			};
 
 			mt6397_vsramca7_reg: buck_vsramca7 {
-				regulator-compatible = "buck_vsramca7";
 				regulator-name = "vsramca7";
 				regulator-min-microvolt = < 700000>;
 				regulator-max-microvolt = <1350000>;
@@ -343,7 +339,6 @@
 			};
 
 			mt6397_vcore_reg: buck_vcore {
-				regulator-compatible = "buck_vcore";
 				regulator-name = "vcore";
 				regulator-min-microvolt = < 700000>;
 				regulator-max-microvolt = <1350000>;
@@ -352,7 +347,6 @@
 			};
 
 			mt6397_vgpu_reg: buck_vgpu {
-				regulator-compatible = "buck_vgpu";
 				regulator-name = "vgpu";
 				regulator-min-microvolt = < 700000>;
 				regulator-max-microvolt = <1350000>;
@@ -361,7 +355,6 @@
 			};
 
 			mt6397_vdrm_reg: buck_vdrm {
-				regulator-compatible = "buck_vdrm";
 				regulator-name = "vdrm";
 				regulator-min-microvolt = <1200000>;
 				regulator-max-microvolt = <1400000>;
@@ -370,7 +363,6 @@
 			};
 
 			mt6397_vio18_reg: buck_vio18 {
-				regulator-compatible = "buck_vio18";
 				regulator-name = "vio18";
 				regulator-min-microvolt = <1620000>;
 				regulator-max-microvolt = <1980000>;
@@ -379,19 +371,16 @@
 			};
 
 			mt6397_vtcxo_reg: ldo_vtcxo {
-				regulator-compatible = "ldo_vtcxo";
 				regulator-name = "vtcxo";
 				regulator-always-on;
 			};
 
 			mt6397_va28_reg: ldo_va28 {
-				regulator-compatible = "ldo_va28";
 				regulator-name = "va28";
 				regulator-always-on;
 			};
 
 			mt6397_vcama_reg: ldo_vcama {
-				regulator-compatible = "ldo_vcama";
 				regulator-name = "vcama";
 				regulator-min-microvolt = <1500000>;
 				regulator-max-microvolt = <2800000>;
@@ -399,18 +388,15 @@
 			};
 
 			mt6397_vio28_reg: ldo_vio28 {
-				regulator-compatible = "ldo_vio28";
 				regulator-name = "vio28";
 				regulator-always-on;
 			};
 
 			mt6397_vusb_reg: ldo_vusb {
-				regulator-compatible = "ldo_vusb";
 				regulator-name = "vusb";
 			};
 
 			mt6397_vmc_reg: ldo_vmc {
-				regulator-compatible = "ldo_vmc";
 				regulator-name = "vmc";
 				regulator-min-microvolt = <1800000>;
 				regulator-max-microvolt = <3300000>;
@@ -418,7 +404,6 @@
 			};
 
 			mt6397_vmch_reg: ldo_vmch {
-				regulator-compatible = "ldo_vmch";
 				regulator-name = "vmch";
 				regulator-min-microvolt = <3000000>;
 				regulator-max-microvolt = <3300000>;
@@ -426,7 +411,6 @@
 			};
 
 			mt6397_vemc_3v3_reg: ldo_vemc3v3 {
-				regulator-compatible = "ldo_vemc3v3";
 				regulator-name = "vemc_3v3";
 				regulator-min-microvolt = <3000000>;
 				regulator-max-microvolt = <3300000>;
@@ -434,7 +418,6 @@
 			};
 
 			mt6397_vgp1_reg: ldo_vgp1 {
-				regulator-compatible = "ldo_vgp1";
 				regulator-name = "vcamd";
 				regulator-min-microvolt = <1220000>;
 				regulator-max-microvolt = <3300000>;
@@ -442,7 +425,6 @@
 			};
 
 			mt6397_vgp2_reg: ldo_vgp2 {
-				regulator-compatible = "ldo_vgp2";
 				regulator-name = "vcamio";
 				regulator-min-microvolt = <1000000>;
 				regulator-max-microvolt = <3300000>;
@@ -450,7 +432,6 @@
 			};
 
 			mt6397_vgp3_reg: ldo_vgp3 {
-				regulator-compatible = "ldo_vgp3";
 				regulator-name = "vcamaf";
 				regulator-min-microvolt = <1200000>;
 				regulator-max-microvolt = <3300000>;
@@ -458,7 +439,6 @@
 			};
 
 			mt6397_vgp4_reg: ldo_vgp4 {
-				regulator-compatible = "ldo_vgp4";
 				regulator-name = "vgp4";
 				regulator-min-microvolt = <1200000>;
 				regulator-max-microvolt = <3300000>;
@@ -466,7 +446,6 @@
 			};
 
 			mt6397_vgp5_reg: ldo_vgp5 {
-				regulator-compatible = "ldo_vgp5";
 				regulator-name = "vgp5";
 				regulator-min-microvolt = <1200000>;
 				regulator-max-microvolt = <3000000>;
@@ -474,7 +453,6 @@
 			};
 
 			mt6397_vgp6_reg: ldo_vgp6 {
-				regulator-compatible = "ldo_vgp6";
 				regulator-name = "vgp6";
 				regulator-min-microvolt = <1200000>;
 				regulator-max-microvolt = <3300000>;
@@ -482,7 +460,6 @@
 			};
 
 			mt6397_vibr_reg: ldo_vibr {
-				regulator-compatible = "ldo_vibr";
 				regulator-name = "vibr";
 				regulator-min-microvolt = <1300000>;
 				regulator-max-microvolt = <3300000>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/mediatek/mt8173.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/mediatek/mt8173.dtsi
@@ -238,21 +238,21 @@
 		cpu_on	      = <0x84000003>;
 	};
 
-	clk26m: oscillator@0 {
+	clk26m: oscillator0 {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <26000000>;
 		clock-output-names = "clk26m";
 	};
 
-	clk32k: oscillator@1 {
+	clk32k: oscillator1 {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <32000>;
 		clock-output-names = "clk32k";
 	};
 
-	cpum_ck: oscillator@2 {
+	cpum_ck: oscillator2 {
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <0>;
@@ -268,19 +268,19 @@
 			sustainable-power = <1500>; /* milliwatts */
 
 			trips {
-				threshold: trip-point@0 {
+				threshold: trip-point0 {
 					temperature = <68000>;
 					hysteresis = <2000>;
 					type = "passive";
 				};
 
-				target: trip-point@1 {
+				target: trip-point1 {
 					temperature = <85000>;
 					hysteresis = <2000>;
 					type = "passive";
 				};
 
-				cpu_crit: cpu_crit@0 {
+				cpu_crit: cpu_crit0 {
 					temperature = <115000>;
 					hysteresis = <2000>;
 					type = "critical";
@@ -288,13 +288,13 @@
 			};
 
 			cooling-maps {
-				map@0 {
+				map0 {
 					trip = <&target>;
 					cooling-device = <&cpu0 0 0>,
 							 <&cpu1 0 0>;
 					contribution = <3072>;
 				};
-				map@1 {
+				map1 {
 					trip = <&target>;
 					cooling-device = <&cpu2 0 0>,
 							 <&cpu3 0 0>;
@@ -308,7 +308,7 @@
 		#address-cells = <2>;
 		#size-cells = <2>;
 		ranges;
-		vpu_dma_reserved: vpu_dma_mem_region {
+		vpu_dma_reserved: vpu_dma_mem_region@b7000000 {
 			compatible = "shared-dma-pool";
 			reg = <0 0xb7000000 0 0x500000>;
 			alignment = <0x1000>;
@@ -360,7 +360,7 @@
 			reg = <0 0x10005000 0 0x1000>;
 		};
 
-		pio: pinctrl@10005000 {
+		pio: pinctrl@1000b000 {
 			compatible = "mediatek,mt8173-pinctrl";
 			reg = <0 0x1000b000 0 0x1000>;
 			mediatek,pctl-regmap = <&syscfg_pctl_a>;
@@ -567,7 +567,7 @@
 			status = "disabled";
 		};
 
-		gic: interrupt-controller@10220000 {
+		gic: interrupt-controller@10221000 {
 			compatible = "arm,gic-400";
 			#interrupt-cells = <3>;
 			interrupt-parent = <&gic>;
@@ -1137,7 +1137,7 @@
 				 <&mmsys CLK_MM_DSI1_DIGITAL>,
 				 <&mipi_tx1>;
 			clock-names = "engine", "digital", "hs";
-			phy = <&mipi_tx1>;
+			phys = <&mipi_tx1>;
 			phy-names = "dphy";
 			status = "disabled";
 		};
@@ -1397,8 +1397,8 @@
 				      "venc_lt_sel";
 			assigned-clocks = <&topckgen CLK_TOP_VENC_SEL>,
 					  <&topckgen CLK_TOP_VENC_LT_SEL>;
-			assigned-clock-parents = <&topckgen CLK_TOP_VENCPLL_D2>,
-						 <&topckgen CLK_TOP_UNIVPLL1_D2>;
+			assigned-clock-parents = <&topckgen CLK_TOP_VCODECPLL>,
+						 <&topckgen CLK_TOP_VCODECPLL_370P5>;
 		};
 
 		vencltsys: clock-controller@19000000 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/nvidia/tegra132-norrin.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/nvidia/tegra132-norrin.dts
@@ -9,8 +9,8 @@
 	compatible = "nvidia,norrin", "nvidia,tegra132", "nvidia,tegra124";
 
 	aliases {
-		rtc0 = "/i2c@7000d000/as3722@40";
-		rtc1 = "/rtc@7000e000";
+		rtc0 = &as3722;
+		rtc1 = &tegra_rtc;
 		serial0 = &uarta;
 	};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/nvidia/tegra132.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/nvidia/tegra132.dtsi
@@ -569,7 +569,7 @@
 		status = "disabled";
 	};
 
-	rtc@7000e000 {
+	tegra_rtc: rtc@7000e000 {
 		compatible = "nvidia,tegra124-rtc", "nvidia,tegra20-rtc";
 		reg = <0x0 0x7000e000 0x0 0x100>;
 		interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
@@ -1082,13 +1082,13 @@
 
 		cpu@0 {
 			device_type = "cpu";
-			compatible = "nvidia,denver";
+			compatible = "nvidia,tegra132-denver";
 			reg = <0>;
 		};
 
 		cpu@1 {
 			device_type = "cpu";
-			compatible = "nvidia,denver";
+			compatible = "nvidia,tegra132-denver";
 			reg = <1>;
 		};
 	};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts
@@ -10,18 +10,6 @@
 	model = "NVIDIA Jetson TX2 Developer Kit";
 	compatible = "nvidia,p2771-0000", "nvidia,tegra186";
 
-	aconnect {
-		status = "okay";
-
-		dma-controller@2930000 {
-			status = "okay";
-		};
-
-		interrupt-controller@2a40000 {
-			status = "okay";
-		};
-	};
-
 	i2c@3160000 {
 		power-monitor@42 {
 			compatible = "ti,ina3221";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/nvidia/tegra186.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/nvidia/tegra186.dtsi
@@ -309,8 +309,9 @@
 		compatible = "nvidia,tegra186-sdhci";
 		reg = <0x0 0x03400000 0x0 0x10000>;
 		interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&bpmp TEGRA186_CLK_SDMMC1>;
-		clock-names = "sdhci";
+		clocks = <&bpmp TEGRA186_CLK_SDMMC1>,
+			 <&bpmp TEGRA186_CLK_SDMMC_LEGACY_TM>;
+		clock-names = "sdhci", "tmclk";
 		resets = <&bpmp TEGRA186_RESET_SDMMC1>;
 		reset-names = "sdhci";
 		iommus = <&smmu TEGRA186_SID_SDMMC1>;
@@ -335,8 +336,9 @@
 		compatible = "nvidia,tegra186-sdhci";
 		reg = <0x0 0x03420000 0x0 0x10000>;
 		interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&bpmp TEGRA186_CLK_SDMMC2>;
-		clock-names = "sdhci";
+		clocks = <&bpmp TEGRA186_CLK_SDMMC2>,
+			 <&bpmp TEGRA186_CLK_SDMMC_LEGACY_TM>;
+		clock-names = "sdhci", "tmclk";
 		resets = <&bpmp TEGRA186_RESET_SDMMC2>;
 		reset-names = "sdhci";
 		iommus = <&smmu TEGRA186_SID_SDMMC2>;
@@ -356,8 +358,9 @@
 		compatible = "nvidia,tegra186-sdhci";
 		reg = <0x0 0x03440000 0x0 0x10000>;
 		interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&bpmp TEGRA186_CLK_SDMMC3>;
-		clock-names = "sdhci";
+		clocks = <&bpmp TEGRA186_CLK_SDMMC3>,
+			 <&bpmp TEGRA186_CLK_SDMMC_LEGACY_TM>;
+		clock-names = "sdhci", "tmclk";
 		resets = <&bpmp TEGRA186_RESET_SDMMC3>;
 		reset-names = "sdhci";
 		iommus = <&smmu TEGRA186_SID_SDMMC3>;
@@ -379,8 +382,9 @@
 		compatible = "nvidia,tegra186-sdhci";
 		reg = <0x0 0x03460000 0x0 0x10000>;
 		interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&bpmp TEGRA186_CLK_SDMMC4>;
-		clock-names = "sdhci";
+		clocks = <&bpmp TEGRA186_CLK_SDMMC4>,
+			 <&bpmp TEGRA186_CLK_SDMMC_LEGACY_TM>;
+		clock-names = "sdhci", "tmclk";
 		assigned-clocks = <&bpmp TEGRA186_CLK_SDMMC4>,
 				  <&bpmp TEGRA186_CLK_PLLC4_VCO>;
 		assigned-clock-parents = <&bpmp TEGRA186_CLK_PLLC4_VCO>;
@@ -705,7 +709,7 @@
 
 	ccplex@e000000 {
 		compatible = "nvidia,tegra186-ccplex-cluster";
-		reg = <0x0 0x0e000000 0x0 0x3fffff>;
+		reg = <0x0 0x0e000000 0x0 0x400000>;
 
 		nvidia,bpmp = <&bpmp>;
 	};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi
@@ -32,7 +32,7 @@
 
 			phy-reset-gpios = <&gpio TEGRA194_MAIN_GPIO(G, 5) GPIO_ACTIVE_LOW>;
 			phy-handle = <&phy>;
-			phy-mode = "rgmii";
+			phy-mode = "rgmii-id";
 
 			mdio {
 				#address-cells = <1>;
@@ -309,9 +309,8 @@
 			regulator-name = "VDD_12V";
 			regulator-min-microvolt = <1200000>;
 			regulator-max-microvolt = <1200000>;
-			gpio = <&gpio TEGRA194_MAIN_GPIO(A, 1) GPIO_ACTIVE_LOW>;
+			gpio = <&gpio TEGRA194_MAIN_GPIO(A, 1) GPIO_ACTIVE_HIGH>;
 			regulator-boot-on;
-			enable-active-low;
 		};
 	};
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/nvidia/tegra194.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/nvidia/tegra194.dtsi
@@ -144,7 +144,7 @@
 					nvidia,schmitt = <TEGRA_PIN_DISABLE>;
 					nvidia,lpdr = <TEGRA_PIN_ENABLE>;
 					nvidia,enable-input = <TEGRA_PIN_DISABLE>;
-					nvidia,io-high-voltage = <TEGRA_PIN_ENABLE>;
+					nvidia,io-hv = <TEGRA_PIN_ENABLE>;
 					nvidia,tristate = <TEGRA_PIN_DISABLE>;
 					nvidia,pull = <TEGRA_PIN_PULL_NONE>;
 				};
@@ -156,7 +156,7 @@
 					nvidia,schmitt = <TEGRA_PIN_DISABLE>;
 					nvidia,lpdr = <TEGRA_PIN_ENABLE>;
 					nvidia,enable-input = <TEGRA_PIN_ENABLE>;
-					nvidia,io-high-voltage = <TEGRA_PIN_ENABLE>;
+					nvidia,io-hv = <TEGRA_PIN_ENABLE>;
 					nvidia,tristate = <TEGRA_PIN_DISABLE>;
 					nvidia,pull = <TEGRA_PIN_PULL_NONE>;
 				};
@@ -403,8 +403,9 @@
 			compatible = "nvidia,tegra194-sdhci", "nvidia,tegra186-sdhci";
 			reg = <0x03400000 0x10000>;
 			interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&bpmp TEGRA194_CLK_SDMMC1>;
-			clock-names = "sdhci";
+			clocks = <&bpmp TEGRA194_CLK_SDMMC1>,
+				 <&bpmp TEGRA194_CLK_SDMMC_LEGACY_TM>;
+			clock-names = "sdhci", "tmclk";
 			resets = <&bpmp TEGRA194_RESET_SDMMC1>;
 			reset-names = "sdhci";
 			nvidia,pad-autocal-pull-up-offset-3v3-timeout =
@@ -425,8 +426,9 @@
 			compatible = "nvidia,tegra194-sdhci", "nvidia,tegra186-sdhci";
 			reg = <0x03440000 0x10000>;
 			interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&bpmp TEGRA194_CLK_SDMMC3>;
-			clock-names = "sdhci";
+			clocks = <&bpmp TEGRA194_CLK_SDMMC3>,
+				 <&bpmp TEGRA194_CLK_SDMMC_LEGACY_TM>;
+			clock-names = "sdhci", "tmclk";
 			resets = <&bpmp TEGRA194_RESET_SDMMC3>;
 			reset-names = "sdhci";
 			nvidia,pad-autocal-pull-up-offset-1v8 = <0x00>;
@@ -448,8 +450,9 @@
 			compatible = "nvidia,tegra194-sdhci", "nvidia,tegra186-sdhci";
 			reg = <0x03460000 0x10000>;
 			interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&bpmp TEGRA194_CLK_SDMMC4>;
-			clock-names = "sdhci";
+			clocks = <&bpmp TEGRA194_CLK_SDMMC4>,
+				 <&bpmp TEGRA194_CLK_SDMMC_LEGACY_TM>;
+			clock-names = "sdhci", "tmclk";
 			assigned-clocks = <&bpmp TEGRA194_CLK_SDMMC4>,
 					  <&bpmp TEGRA194_CLK_PLLC4>;
 			assigned-clock-parents =
@@ -689,7 +692,7 @@
 
 		hsp_aon: hsp@c150000 {
 			compatible = "nvidia,tegra194-hsp", "nvidia,tegra186-hsp";
-			reg = <0x0c150000 0xa0000>;
+			reg = <0x0c150000 0x90000>;
 			interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>,
 			             <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>,
 			             <GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>,
@@ -1151,7 +1154,7 @@
 	};
 
 	pcie@14100000 {
-		compatible = "nvidia,tegra194-pcie", "snps,dw-pcie";
+		compatible = "nvidia,tegra194-pcie";
 		power-domains = <&bpmp TEGRA194_POWER_DOMAIN_PCIEX1A>;
 		reg = <0x00 0x14100000 0x0 0x00020000   /* appl registers (128K)      */
 		       0x00 0x30000000 0x0 0x00040000   /* configuration space (256K) */
@@ -1192,12 +1195,12 @@
 
 		bus-range = <0x0 0xff>;
 		ranges = <0x81000000 0x0  0x30100000 0x0  0x30100000 0x0 0x00100000   /* downstream I/O (1MB) */
-			  0xc2000000 0x12 0x00000000 0x12 0x00000000 0x0 0x30000000   /* prefetchable memory (768MB) */
+			  0xc3000000 0x12 0x00000000 0x12 0x00000000 0x0 0x30000000   /* prefetchable memory (768MB) */
 			  0x82000000 0x0  0x40000000 0x12 0x30000000 0x0 0x10000000>; /* non-prefetchable memory (256MB) */
 	};
 
 	pcie@14120000 {
-		compatible = "nvidia,tegra194-pcie", "snps,dw-pcie";
+		compatible = "nvidia,tegra194-pcie";
 		power-domains = <&bpmp TEGRA194_POWER_DOMAIN_PCIEX1A>;
 		reg = <0x00 0x14120000 0x0 0x00020000   /* appl registers (128K)      */
 		       0x00 0x32000000 0x0 0x00040000   /* configuration space (256K) */
@@ -1238,12 +1241,12 @@
 
 		bus-range = <0x0 0xff>;
 		ranges = <0x81000000 0x0  0x32100000 0x0  0x32100000 0x0 0x00100000   /* downstream I/O (1MB) */
-			  0xc2000000 0x12 0x40000000 0x12 0x40000000 0x0 0x30000000   /* prefetchable memory (768MB) */
+			  0xc3000000 0x12 0x40000000 0x12 0x40000000 0x0 0x30000000   /* prefetchable memory (768MB) */
 			  0x82000000 0x0  0x40000000 0x12 0x70000000 0x0 0x10000000>; /* non-prefetchable memory (256MB) */
 	};
 
 	pcie@14140000 {
-		compatible = "nvidia,tegra194-pcie", "snps,dw-pcie";
+		compatible = "nvidia,tegra194-pcie";
 		power-domains = <&bpmp TEGRA194_POWER_DOMAIN_PCIEX1A>;
 		reg = <0x00 0x14140000 0x0 0x00020000   /* appl registers (128K)      */
 		       0x00 0x34000000 0x0 0x00040000   /* configuration space (256K) */
@@ -1284,12 +1287,12 @@
 
 		bus-range = <0x0 0xff>;
 		ranges = <0x81000000 0x0  0x34100000 0x0  0x34100000 0x0 0x00100000   /* downstream I/O (1MB) */
-			  0xc2000000 0x12 0x80000000 0x12 0x80000000 0x0 0x30000000   /* prefetchable memory (768MB) */
+			  0xc3000000 0x12 0x80000000 0x12 0x80000000 0x0 0x30000000   /* prefetchable memory (768MB) */
 			  0x82000000 0x0  0x40000000 0x12 0xb0000000 0x0 0x10000000>; /* non-prefetchable memory (256MB) */
 	};
 
 	pcie@14160000 {
-		compatible = "nvidia,tegra194-pcie", "snps,dw-pcie";
+		compatible = "nvidia,tegra194-pcie";
 		power-domains = <&bpmp TEGRA194_POWER_DOMAIN_PCIEX4A>;
 		reg = <0x00 0x14160000 0x0 0x00020000   /* appl registers (128K)      */
 		       0x00 0x36000000 0x0 0x00040000   /* configuration space (256K) */
@@ -1330,12 +1333,12 @@
 
 		bus-range = <0x0 0xff>;
 		ranges = <0x81000000 0x0  0x36100000 0x0  0x36100000 0x0 0x00100000   /* downstream I/O (1MB) */
-			  0xc2000000 0x14 0x00000000 0x14 0x00000000 0x3 0x40000000   /* prefetchable memory (13GB) */
+			  0xc3000000 0x14 0x00000000 0x14 0x00000000 0x3 0x40000000   /* prefetchable memory (13GB) */
 			  0x82000000 0x0  0x40000000 0x17 0x40000000 0x0 0xc0000000>; /* non-prefetchable memory (3GB) */
 	};
 
 	pcie@14180000 {
-		compatible = "nvidia,tegra194-pcie", "snps,dw-pcie";
+		compatible = "nvidia,tegra194-pcie";
 		power-domains = <&bpmp TEGRA194_POWER_DOMAIN_PCIEX8B>;
 		reg = <0x00 0x14180000 0x0 0x00020000   /* appl registers (128K)      */
 		       0x00 0x38000000 0x0 0x00040000   /* configuration space (256K) */
@@ -1376,12 +1379,12 @@
 
 		bus-range = <0x0 0xff>;
 		ranges = <0x81000000 0x0  0x38100000 0x0  0x38100000 0x0 0x00100000   /* downstream I/O (1MB) */
-			  0xc2000000 0x18 0x00000000 0x18 0x00000000 0x3 0x40000000   /* prefetchable memory (13GB) */
+			  0xc3000000 0x18 0x00000000 0x18 0x00000000 0x3 0x40000000   /* prefetchable memory (13GB) */
 			  0x82000000 0x0  0x40000000 0x1b 0x40000000 0x0 0xc0000000>; /* non-prefetchable memory (3GB) */
 	};
 
 	pcie@141a0000 {
-		compatible = "nvidia,tegra194-pcie", "snps,dw-pcie";
+		compatible = "nvidia,tegra194-pcie";
 		power-domains = <&bpmp TEGRA194_POWER_DOMAIN_PCIEX8A>;
 		reg = <0x00 0x141a0000 0x0 0x00020000   /* appl registers (128K)      */
 		       0x00 0x3a000000 0x0 0x00040000   /* configuration space (256K) */
@@ -1426,10 +1429,109 @@
 
 		bus-range = <0x0 0xff>;
 		ranges = <0x81000000 0x0  0x3a100000 0x0  0x3a100000 0x0 0x00100000   /* downstream I/O (1MB) */
-			  0xc2000000 0x1c 0x00000000 0x1c 0x00000000 0x3 0x40000000   /* prefetchable memory (13GB) */
+			  0xc3000000 0x1c 0x00000000 0x1c 0x00000000 0x3 0x40000000   /* prefetchable memory (13GB) */
 			  0x82000000 0x0  0x40000000 0x1f 0x40000000 0x0 0xc0000000>; /* non-prefetchable memory (3GB) */
 	};
 
+	pcie_ep@14160000 {
+		compatible = "nvidia,tegra194-pcie-ep";
+		power-domains = <&bpmp TEGRA194_POWER_DOMAIN_PCIEX4A>;
+		reg = <0x00 0x14160000 0x0 0x00020000   /* appl registers (128K)      */
+		       0x00 0x36040000 0x0 0x00040000   /* iATU_DMA reg space (256K)  */
+		       0x00 0x36080000 0x0 0x00040000   /* DBI reg space (256K)       */
+		       0x14 0x00000000 0x4 0x00000000>; /* Address Space (16G)        */
+		reg-names = "appl", "atu_dma", "dbi", "addr_space";
+
+		status = "disabled";
+
+		num-lanes = <4>;
+		num-ib-windows = <2>;
+		num-ob-windows = <8>;
+
+		clocks = <&bpmp TEGRA194_CLK_PEX0_CORE_4>;
+		clock-names = "core";
+
+		resets = <&bpmp TEGRA194_RESET_PEX0_CORE_4_APB>,
+			 <&bpmp TEGRA194_RESET_PEX0_CORE_4>;
+		reset-names = "apb", "core";
+
+		interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;	/* controller interrupt */
+		interrupt-names = "intr";
+
+		nvidia,bpmp = <&bpmp 4>;
+
+		nvidia,aspm-cmrt-us = <60>;
+		nvidia,aspm-pwr-on-t-us = <20>;
+		nvidia,aspm-l0s-entrance-latency-us = <3>;
+	};
+
+	pcie_ep@14180000 {
+		compatible = "nvidia,tegra194-pcie-ep";
+		power-domains = <&bpmp TEGRA194_POWER_DOMAIN_PCIEX8B>;
+		reg = <0x00 0x14180000 0x0 0x00020000   /* appl registers (128K)      */
+		       0x00 0x38040000 0x0 0x00040000   /* iATU_DMA reg space (256K)  */
+		       0x00 0x38080000 0x0 0x00040000   /* DBI reg space (256K)       */
+		       0x18 0x00000000 0x4 0x00000000>; /* Address Space (16G)        */
+		reg-names = "appl", "atu_dma", "dbi", "addr_space";
+
+		status = "disabled";
+
+		num-lanes = <8>;
+		num-ib-windows = <2>;
+		num-ob-windows = <8>;
+
+		clocks = <&bpmp TEGRA194_CLK_PEX0_CORE_0>;
+		clock-names = "core";
+
+		resets = <&bpmp TEGRA194_RESET_PEX0_CORE_0_APB>,
+			 <&bpmp TEGRA194_RESET_PEX0_CORE_0>;
+		reset-names = "apb", "core";
+
+		interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;	/* controller interrupt */
+		interrupt-names = "intr";
+
+		nvidia,bpmp = <&bpmp 0>;
+
+		nvidia,aspm-cmrt-us = <60>;
+		nvidia,aspm-pwr-on-t-us = <20>;
+		nvidia,aspm-l0s-entrance-latency-us = <3>;
+	};
+
+	pcie_ep@141a0000 {
+		compatible = "nvidia,tegra194-pcie-ep";
+		power-domains = <&bpmp TEGRA194_POWER_DOMAIN_PCIEX8A>;
+		reg = <0x00 0x141a0000 0x0 0x00020000   /* appl registers (128K)      */
+		       0x00 0x3a040000 0x0 0x00040000   /* iATU_DMA reg space (256K)  */
+		       0x00 0x3a080000 0x0 0x00040000   /* DBI reg space (256K)       */
+		       0x1c 0x00000000 0x4 0x00000000>; /* Address Space (16G)        */
+		reg-names = "appl", "atu_dma", "dbi", "addr_space";
+
+		status = "disabled";
+
+		num-lanes = <8>;
+		num-ib-windows = <2>;
+		num-ob-windows = <8>;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&clkreq_c5_bi_dir_state>;
+
+		clocks = <&bpmp TEGRA194_CLK_PEX1_CORE_5>;
+		clock-names = "core";
+
+		resets = <&bpmp TEGRA194_RESET_PEX1_CORE_5_APB>,
+			 <&bpmp TEGRA194_RESET_PEX1_CORE_5>;
+		reset-names = "apb", "core";
+
+		interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;	/* controller interrupt */
+		interrupt-names = "intr";
+
+		nvidia,bpmp = <&bpmp 5>;
+
+		nvidia,aspm-cmrt-us = <60>;
+		nvidia,aspm-pwr-on-t-us = <20>;
+		nvidia,aspm-l0s-entrance-latency-us = <3>;
+	};
+
 	sysram@40000000 {
 		compatible = "nvidia,tegra194-sysram", "mmio-sram";
 		reg = <0x0 0x40000000 0x0 0x50000>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
@@ -1612,7 +1612,7 @@
 			regulator-name = "VDD_HDMI_5V0";
 			regulator-min-microvolt = <5000000>;
 			regulator-max-microvolt = <5000000>;
-			gpio = <&exp1 12 GPIO_ACTIVE_LOW>;
+			gpio = <&exp1 12 GPIO_ACTIVE_HIGH>;
 			enable-active-high;
 			vin-supply = <&vdd_5v0_sys>;
 		};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/nvidia/tegra210.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/nvidia/tegra210.dtsi
@@ -917,6 +917,7 @@
 			 <&tegra_car 128>, /* hda2hdmi */
 			 <&tegra_car 111>; /* hda2codec_2x */
 		reset-names = "hda", "hda2hdmi", "hda2codec_2x";
+		power-domains = <&pd_sor>;
 		status = "disabled";
 	};
 
@@ -1116,8 +1117,9 @@
 		compatible = "nvidia,tegra210-sdhci", "nvidia,tegra124-sdhci";
 		reg = <0x0 0x700b0000 0x0 0x200>;
 		interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&tegra_car TEGRA210_CLK_SDMMC1>;
-		clock-names = "sdhci";
+		clocks = <&tegra_car TEGRA210_CLK_SDMMC1>,
+			 <&tegra_car TEGRA210_CLK_SDMMC_LEGACY>;
+		clock-names = "sdhci", "tmclk";
 		resets = <&tegra_car 14>;
 		reset-names = "sdhci";
 		pinctrl-names = "sdmmc-3v3", "sdmmc-1v8",
@@ -1144,8 +1146,9 @@
 		compatible = "nvidia,tegra210-sdhci", "nvidia,tegra124-sdhci";
 		reg = <0x0 0x700b0200 0x0 0x200>;
 		interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&tegra_car TEGRA210_CLK_SDMMC2>;
-		clock-names = "sdhci";
+		clocks = <&tegra_car TEGRA210_CLK_SDMMC2>,
+			 <&tegra_car TEGRA210_CLK_SDMMC_LEGACY>;
+		clock-names = "sdhci", "tmclk";
 		resets = <&tegra_car 9>;
 		reset-names = "sdhci";
 		pinctrl-names = "sdmmc-1v8-drv";
@@ -1161,8 +1164,9 @@
 		compatible = "nvidia,tegra210-sdhci", "nvidia,tegra124-sdhci";
 		reg = <0x0 0x700b0400 0x0 0x200>;
 		interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&tegra_car TEGRA210_CLK_SDMMC3>;
-		clock-names = "sdhci";
+		clocks = <&tegra_car TEGRA210_CLK_SDMMC3>,
+			 <&tegra_car TEGRA210_CLK_SDMMC_LEGACY>;
+		clock-names = "sdhci", "tmclk";
 		resets = <&tegra_car 69>;
 		reset-names = "sdhci";
 		pinctrl-names = "sdmmc-3v3", "sdmmc-1v8",
@@ -1184,8 +1188,9 @@
 		compatible = "nvidia,tegra210-sdhci", "nvidia,tegra124-sdhci";
 		reg = <0x0 0x700b0600 0x0 0x200>;
 		interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&tegra_car TEGRA210_CLK_SDMMC4>;
-		clock-names = "sdhci";
+		clocks = <&tegra_car TEGRA210_CLK_SDMMC4>,
+			 <&tegra_car TEGRA210_CLK_SDMMC_LEGACY>;
+		clock-names = "sdhci", "tmclk";
 		resets = <&tegra_car 15>;
 		reset-names = "sdhci";
 		pinctrl-names = "sdmmc-3v3-drv", "sdmmc-1v8-drv";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
@@ -77,425 +77,427 @@
 			enable-gpios = <&pm8994_gpios 15 0>;
 		};
 	};
+};
 
-	soc {
-		serial@7570000 {
-			label = "BT-UART";
-			status = "okay";
-			pinctrl-names = "default", "sleep";
-			pinctrl-0 = <&blsp1_uart1_default>;
-			pinctrl-1 = <&blsp1_uart1_sleep>;
+&blsp1_uart1 {
+	label = "BT-UART";
+	status = "okay";
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&blsp1_uart1_default>;
+	pinctrl-1 = <&blsp1_uart1_sleep>;
 
-			bluetooth {
-				compatible = "qcom,qca6174-bt";
+	bluetooth {
+		compatible = "qcom,qca6174-bt";
 
-				/* bt_disable_n gpio */
-				enable-gpios = <&pm8994_gpios 19 GPIO_ACTIVE_HIGH>;
+		/* bt_disable_n gpio */
+		enable-gpios = <&pm8994_gpios 19 GPIO_ACTIVE_HIGH>;
 
-				clocks = <&divclk4>;
-			};
-		};
+		clocks = <&divclk4>;
+	};
+};
 
-		serial@75b0000 {
-			label = "LS-UART1";
-			status = "okay";
-			pinctrl-names = "default", "sleep";
-			pinctrl-0 = <&blsp2_uart1_2pins_default>;
-			pinctrl-1 = <&blsp2_uart1_2pins_sleep>;
-		};
+&blsp2_uart1 {
+	label = "LS-UART1";
+	status = "okay";
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&blsp2_uart1_2pins_default>;
+	pinctrl-1 = <&blsp2_uart1_2pins_sleep>;
+};
 
-		serial@75b1000 {
-			label = "LS-UART0";
-			status = "disabled";
-			pinctrl-names = "default", "sleep";
-			pinctrl-0 = <&blsp2_uart2_4pins_default>;
-			pinctrl-1 = <&blsp2_uart2_4pins_sleep>;
-		};
+&blsp2_uart2 {
+	label = "LS-UART0";
+	status = "disabled";
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&blsp2_uart2_4pins_default>;
+	pinctrl-1 = <&blsp2_uart2_4pins_sleep>;
+};
 
-		i2c@7577000 {
-		/* On Low speed expansion */
-			label = "LS-I2C0";
-			status = "okay";
-		};
+&blsp1_i2c2 {
+	/* On Low speed expansion */
+	label = "LS-I2C0";
+	status = "okay";
+};
 
-		i2c@75b6000 {
-		/* On Low speed expansion */
-			label = "LS-I2C1";
-			status = "okay";
-		};
+&blsp2_i2c1 {
+	/* On Low speed expansion */
+	label = "LS-I2C1";
+	status = "okay";
+};
 
-		spi@7575000 {
-		/* On Low speed expansion */
-			label = "LS-SPI0";
-			status = "okay";
-		};
+&blsp1_spi0 {
+	/* On Low speed expansion */
+	label = "LS-SPI0";
+	status = "okay";
+};
 
-		i2c@75b5000 {
-		/* On High speed expansion */
-			label = "HS-I2C2";
-			status = "okay";
-		};
+&blsp2_i2c0 {
+	/* On High speed expansion */
+	label = "HS-I2C2";
+	status = "okay";
+};
 
-		spi@75ba000{
-		/* On High speed expansion */
-			label = "HS-SPI1";
-			status = "okay";
-		};
+&blsp2_spi5 {
+	/* On High speed expansion */
+	label = "HS-SPI1";
+	status = "okay";
+};
 
-		sdhci@74a4900 {
-		/* External SD card */
-			pinctrl-names = "default", "sleep";
-			pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>;
-			pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>;
-			cd-gpios = <&msmgpio 38 0x1>;
-			vmmc-supply = <&pm8994_l21>;
-			vqmmc-supply = <&pm8994_l13>;
-			status = "okay";
-		};
+&camss {
+	vdda-supply = <&pm8994_l2>;
+};
 
-		phy@627000 {
-			status = "okay";
-		};
+&sdhc2 {
+	/* External SD card */
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>;
+	pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>;
+	cd-gpios = <&msmgpio 38 0x1>;
+	vmmc-supply = <&pm8994_l21>;
+	vqmmc-supply = <&pm8994_l13>;
+	status = "okay";
+};
 
-		ufshc@624000 {
-			status = "okay";
-		};
+&ufsphy {
+	status = "okay";
 
-		pinctrl@1010000 {
-			gpio-line-names =
-				"[SPI0_DOUT]", /* GPIO_0, BLSP1_SPI_MOSI, LSEC pin 14 */
-				"[SPI0_DIN]", /* GPIO_1, BLSP1_SPI_MISO, LSEC pin 10 */
-				"[SPI0_CS]", /* GPIO_2, BLSP1_SPI_CS_N, LSEC pin 12 */
-				"[SPI0_SCLK]", /* GPIO_3, BLSP1_SPI_CLK, LSEC pin 8 */
-				"[UART1_TxD]", /* GPIO_4, BLSP8_UART_TX, LSEC pin 11 */
-				"[UART1_RxD]", /* GPIO_5, BLSP8_UART_RX, LSEC pin 13 */
-				"[I2C1_SDA]", /* GPIO_6, BLSP8_I2C_SDA, LSEC pin 21 */
-				"[I2C1_SCL]", /* GPIO_7, BLSP8_I2C_SCL, LSEC pin 19 */
-				"GPIO-H", /* GPIO_8, LCD0_RESET_N, LSEC pin 30 */
-				"TP93", /* GPIO_9 */
-				"GPIO-G", /* GPIO_10, MDP_VSYNC_P, LSEC pin 29 */
-				"[MDP_VSYNC_S]", /* GPIO_11, S HSEC pin 55 */
-				"NC", /* GPIO_12 */
-				"[CSI0_MCLK]", /* GPIO_13, CAM_MCLK0, P HSEC pin 15 */
-				"[CAM_MCLK1]", /* GPIO_14, J14 pin 11 */
-				"[CSI1_MCLK]", /* GPIO_15, CAM_MCLK2, P HSEC pin 17 */
-				"TP99", /* GPIO_16 */
-				"[I2C2_SDA]", /* GPIO_17, CCI_I2C_SDA0, P HSEC pin 34 */
-				"[I2C2_SCL]", /* GPIO_18, CCI_I2C_SCL0, P HSEC pin 32 */
-				"[CCI_I2C_SDA1]", /* GPIO_19, S HSEC pin 38 */
-				"[CCI_I2C_SCL1]", /* GPIO_20, S HSEC pin 36 */
-				"FLASH_STROBE_EN", /* GPIO_21, S HSEC pin 5 */
-				"FLASH_STROBE_TRIG", /* GPIO_22, S HSEC pin 1 */
-				"GPIO-K", /* GPIO_23, CAM2_RST_N, LSEC pin 33 */
-				"GPIO-D", /* GPIO_24, LSEC pin 26 */
-				"GPIO-I", /* GPIO_25, CAM0_RST_N, LSEC pin 31 */
-				"GPIO-J", /* GPIO_26, CAM0_STANDBY_N, LSEC pin 32 */
-				"BLSP6_I2C_SDA", /* GPIO_27 */
-				"BLSP6_I2C_SCL", /* GPIO_28 */
-				"GPIO-B", /* GPIO_29, TS0_RESET_N, LSEC pin 24 */
-				"GPIO30", /* GPIO_30, S HSEC pin 4 */
-				"HDMI_CEC", /* GPIO_31 */
-				"HDMI_DDC_CLOCK", /* GPIO_32 */
-				"HDMI_DDC_DATA", /* GPIO_33 */
-				"HDMI_HOT_PLUG_DETECT", /* GPIO_34 */
-				"PCIE0_RST_N", /* GPIO_35 */
-				"PCIE0_CLKREQ_N", /* GPIO_36 */
-				"PCIE0_WAKE", /* GPIO_37 */
-				"SD_CARD_DET_N", /* GPIO_38 */
-				"TSIF1_SYNC", /* GPIO_39, S HSEC pin 48 */
-				"W_DISABLE_N", /* GPIO_40 */
-				"[BLSP9_UART_TX]", /* GPIO_41 */
-				"[BLSP9_UART_RX]", /* GPIO_42 */
-				"[BLSP2_UART_CTS_N]", /* GPIO_43 */
-				"[BLSP2_UART_RFR_N]", /* GPIO_44 */
-				"[BLSP3_UART_TX]", /* GPIO_45 */
-				"[BLSP3_UART_RX]", /* GPIO_46 */
-				"[I2C0_SDA]", /* GPIO_47, LS_I2C0_SDA, LSEC pin 17 */
-				"[I2C0_SCL]", /* GPIO_48, LS_I2C0_SCL, LSEC pin 15 */
-				"[UART0_TxD]", /* GPIO_49, BLSP9_UART_TX, LSEC pin 5 */
-				"[UART0_RxD]", /* GPIO_50, BLSP9_UART_RX, LSEC pin 7 */
-				"[UART0_CTS]", /* GPIO_51, BLSP9_UART_CTS_N, LSEC pin 3 */
-				"[UART0_RTS]", /* GPIO_52, BLSP9_UART_RFR_N, LSEC pin 9 */
-				"[CODEC_INT1_N]", /* GPIO_53 */
-				"[CODEC_INT2_N]", /* GPIO_54 */
-				"[BLSP7_I2C_SDA]", /* GPIO_55 */
-				"[BLSP7_I2C_SCL]", /* GPIO_56 */
-				"MI2S_MCLK", /* GPIO_57, S HSEC pin 3 */
-				"[PCM_CLK]", /* GPIO_58, QUA_MI2S_SCK, LSEC pin 18 */
-				"[PCM_FS]", /* GPIO_59, QUA_MI2S_WS, LSEC pin 16 */
-				"[PCM_DO]", /* GPIO_60, QUA_MI2S_DATA0, LSEC pin 20 */
-				"[PCM_DI]", /* GPIO_61, QUA_MI2S_DATA1, LSEC pin 22 */
-				"GPIO-E", /* GPIO_62, LSEC pin 27 */
-				"TP87", /* GPIO_63 */
-				"[CODEC_RST_N]", /* GPIO_64 */
-				"[PCM1_CLK]", /* GPIO_65 */
-				"[PCM1_SYNC]", /* GPIO_66 */
-				"[PCM1_DIN]", /* GPIO_67 */
-				"[PCM1_DOUT]", /* GPIO_68 */
-				"AUDIO_REF_CLK", /* GPIO_69 */
-				"SLIMBUS_CLK", /* GPIO_70 */
-				"SLIMBUS_DATA0", /* GPIO_71 */
-				"SLIMBUS_DATA1", /* GPIO_72 */
-				"NC", /* GPIO_73 */
-				"NC", /* GPIO_74 */
-				"NC", /* GPIO_75 */
-				"NC", /* GPIO_76 */
-				"TP94", /* GPIO_77 */
-				"NC", /* GPIO_78 */
-				"TP95", /* GPIO_79 */
-				"GPIO-A", /* GPIO_80, MEMS_RESET_N, LSEC pin 23 */
-				"TP88", /* GPIO_81 */
-				"TP89", /* GPIO_82 */
-				"TP90", /* GPIO_83 */
-				"TP91", /* GPIO_84 */
-				"[SD_DAT0]", /* GPIO_85, BLSP12_SPI_MOSI, P HSEC pin 1 */
-				"[SD_CMD]", /* GPIO_86, BLSP12_SPI_MISO, P HSEC pin 11 */
-				"[SD_DAT3]", /* GPIO_87, BLSP12_SPI_CS_N, P HSEC pin 7 */
-				"[SD_SCLK]", /* GPIO_88, BLSP12_SPI_CLK, P HSEC pin 9 */
-				"TSIF1_CLK", /* GPIO_89, S HSEC pin 42 */
-				"TSIF1_EN", /* GPIO_90, S HSEC pin 46 */
-				"TSIF1_DATA", /* GPIO_91, S HSEC pin 44 */
-				"NC", /* GPIO_92 */
-				"TSIF2_CLK", /* GPIO_93, S HSEC pin 52 */
-				"TSIF2_EN", /* GPIO_94, S HSEC pin 56 */
-				"TSIF2_DATA", /* GPIO_95, S HSEC pin 54 */
-				"TSIF2_SYNC", /* GPIO_96, S HSEC pin 58 */
-				"NC", /* GPIO_97 */
-				"CAM1_STANDBY_N", /* GPIO_98 */
-				"NC", /* GPIO_99 */
-				"NC", /* GPIO_100 */
-				"[LCD1_RESET_N]", /* GPIO_101, S HSEC pin 51 */
-				"BOOT_CONFIG1", /* GPIO_102 */
-				"USB_HUB_RESET", /* GPIO_103 */
-				"CAM1_RST_N", /* GPIO_104 */
-				"NC", /* GPIO_105 */
-				"NC", /* GPIO_106 */
-				"NC", /* GPIO_107 */
-				"NC", /* GPIO_108 */
-				"NC", /* GPIO_109 */
-				"NC", /* GPIO_110 */
-				"NC", /* GPIO_111 */
-				"NC", /* GPIO_112 */
-				"PMI8994_BUA", /* GPIO_113 */
-				"PCIE2_RST_N", /* GPIO_114 */
-				"PCIE2_CLKREQ_N", /* GPIO_115 */
-				"PCIE2_WAKE", /* GPIO_116 */
-				"SSC_IRQ_0", /* GPIO_117 */
-				"SSC_IRQ_1", /* GPIO_118 */
-				"SSC_IRQ_2", /* GPIO_119 */
-				"NC", /* GPIO_120 */
-				"GPIO121", /* GPIO_121, S HSEC pin 2 */
-				"NC", /* GPIO_122 */
-				"SSC_IRQ_6", /* GPIO_123 */
-				"SSC_IRQ_7", /* GPIO_124 */
-				"GPIO-C", /* GPIO_125, TS_INT0, LSEC pin 25 */
-				"BOOT_CONFIG5", /* GPIO_126 */
-				"NC", /* GPIO_127 */
-				"NC", /* GPIO_128 */
-				"BOOT_CONFIG7", /* GPIO_129 */
-				"PCIE1_RST_N", /* GPIO_130 */
-				"PCIE1_CLKREQ_N", /* GPIO_131 */
-				"PCIE1_WAKE", /* GPIO_132 */
-				"GPIO-L", /* GPIO_133, CAM2_STANDBY_N, LSEC pin 34 */
-				"NC", /* GPIO_134 */
-				"NC", /* GPIO_135 */
-				"BOOT_CONFIG8", /* GPIO_136 */
-				"NC", /* GPIO_137 */
-				"NC", /* GPIO_138 */
-				"GPS_SSBI2", /* GPIO_139 */
-				"GPS_SSBI1", /* GPIO_140 */
-				"NC", /* GPIO_141 */
-				"NC", /* GPIO_142 */
-				"NC", /* GPIO_143 */
-				"BOOT_CONFIG6", /* GPIO_144 */
-				"NC", /* GPIO_145 */
-				"NC", /* GPIO_146 */
-				"NC", /* GPIO_147 */
-				"NC", /* GPIO_148 */
-				"NC"; /* GPIO_149 */
-		};
+	vdda-phy-supply = <&pm8994_l28>;
+	vdda-pll-supply = <&pm8994_l12>;
 
-		qcom,spmi@400f000 {
-			pmic@0 {
-				gpios@c000 {
-					gpio-line-names =
-						"NC",
-						"KEY_VOLP_N",
-						"NC",
-						"BL1_PWM",
-						"GPIO-F", /* BL0_PWM, LSEC pin 28 */
-						"BL1_EN",
-						"NC",
-						"WLAN_EN",
-						"NC",
-						"NC",
-						"NC",
-						"NC",
-						"NC",
-						"NC",
-						"DIVCLK1",
-						"DIVCLK2",
-						"DIVCLK3",
-						"DIVCLK4",
-						"BT_EN",
-						"PMIC_SLB",
-						"PMIC_BUA",
-						"USB_VBUS_DET";
-				};
-
-				mpps@a000 {
-					gpio-line-names =
-						"VDDPX_BIAS",
-						"WIFI_LED",
-						"NC",
-						"BT_LED",
-						"PM_MPP05",
-						"PM_MPP06",
-						"PM_MPP07",
-						"NC";
-				};
-			};
+	vdda-phy-max-microamp = <18380>;
+	vdda-pll-max-microamp = <9440>;
 
-			pmic@2 {
-				gpios@c000 {
-					gpio-line-names =
-						"NC",
-						"SPKR_AMP_EN1",
-						"SPKR_AMP_EN2",
-						"TP61",
-						"NC",
-						"USB2_VBUS_DET",
-						"NC",
-						"NC",
-						"NC",
-						"NC";
-				};
-			};
-		};
+	vddp-ref-clk-supply = <&pm8994_l25>;
+	vddp-ref-clk-max-microamp = <100>;
+	vddp-ref-clk-always-on;
+};
 
-		phy@34000 {
-			status = "okay";
-		};
+&ufshc {
+	status = "okay";
 
-		phy@7410000 {
-			status = "okay";
-		};
+	vcc-supply = <&pm8994_l20>;
+	vccq-supply = <&pm8994_l25>;
+	vccq2-supply = <&pm8994_s4>;
+
+	vcc-max-microamp = <600000>;
+	vccq-max-microamp = <450000>;
+	vccq2-max-microamp = <450000>;
+};
 
-		phy@7411000 {
-			status = "okay";
-		};
+&msmgpio {
+	gpio-line-names =
+		"[SPI0_DOUT]", /* GPIO_0, BLSP1_SPI_MOSI, LSEC pin 14 */
+		"[SPI0_DIN]", /* GPIO_1, BLSP1_SPI_MISO, LSEC pin 10 */
+		"[SPI0_CS]", /* GPIO_2, BLSP1_SPI_CS_N, LSEC pin 12 */
+		"[SPI0_SCLK]", /* GPIO_3, BLSP1_SPI_CLK, LSEC pin 8 */
+		"[UART1_TxD]", /* GPIO_4, BLSP8_UART_TX, LSEC pin 11 */
+		"[UART1_RxD]", /* GPIO_5, BLSP8_UART_RX, LSEC pin 13 */
+		"[I2C1_SDA]", /* GPIO_6, BLSP8_I2C_SDA, LSEC pin 21 */
+		"[I2C1_SCL]", /* GPIO_7, BLSP8_I2C_SCL, LSEC pin 19 */
+		"GPIO-H", /* GPIO_8, LCD0_RESET_N, LSEC pin 30 */
+		"TP93", /* GPIO_9 */
+		"GPIO-G", /* GPIO_10, MDP_VSYNC_P, LSEC pin 29 */
+		"[MDP_VSYNC_S]", /* GPIO_11, S HSEC pin 55 */
+		"NC", /* GPIO_12 */
+		"[CSI0_MCLK]", /* GPIO_13, CAM_MCLK0, P HSEC pin 15 */
+		"[CAM_MCLK1]", /* GPIO_14, J14 pin 11 */
+		"[CSI1_MCLK]", /* GPIO_15, CAM_MCLK2, P HSEC pin 17 */
+		"TP99", /* GPIO_16 */
+		"[I2C2_SDA]", /* GPIO_17, CCI_I2C_SDA0, P HSEC pin 34 */
+		"[I2C2_SCL]", /* GPIO_18, CCI_I2C_SCL0, P HSEC pin 32 */
+		"[CCI_I2C_SDA1]", /* GPIO_19, S HSEC pin 38 */
+		"[CCI_I2C_SCL1]", /* GPIO_20, S HSEC pin 36 */
+		"FLASH_STROBE_EN", /* GPIO_21, S HSEC pin 5 */
+		"FLASH_STROBE_TRIG", /* GPIO_22, S HSEC pin 1 */
+		"GPIO-K", /* GPIO_23, CAM2_RST_N, LSEC pin 33 */
+		"GPIO-D", /* GPIO_24, LSEC pin 26 */
+		"GPIO-I", /* GPIO_25, CAM0_RST_N, LSEC pin 31 */
+		"GPIO-J", /* GPIO_26, CAM0_STANDBY_N, LSEC pin 32 */
+		"BLSP6_I2C_SDA", /* GPIO_27 */
+		"BLSP6_I2C_SCL", /* GPIO_28 */
+		"GPIO-B", /* GPIO_29, TS0_RESET_N, LSEC pin 24 */
+		"GPIO30", /* GPIO_30, S HSEC pin 4 */
+		"HDMI_CEC", /* GPIO_31 */
+		"HDMI_DDC_CLOCK", /* GPIO_32 */
+		"HDMI_DDC_DATA", /* GPIO_33 */
+		"HDMI_HOT_PLUG_DETECT", /* GPIO_34 */
+		"PCIE0_RST_N", /* GPIO_35 */
+		"PCIE0_CLKREQ_N", /* GPIO_36 */
+		"PCIE0_WAKE", /* GPIO_37 */
+		"SD_CARD_DET_N", /* GPIO_38 */
+		"TSIF1_SYNC", /* GPIO_39, S HSEC pin 48 */
+		"W_DISABLE_N", /* GPIO_40 */
+		"[BLSP9_UART_TX]", /* GPIO_41 */
+		"[BLSP9_UART_RX]", /* GPIO_42 */
+		"[BLSP2_UART_CTS_N]", /* GPIO_43 */
+		"[BLSP2_UART_RFR_N]", /* GPIO_44 */
+		"[BLSP3_UART_TX]", /* GPIO_45 */
+		"[BLSP3_UART_RX]", /* GPIO_46 */
+		"[I2C0_SDA]", /* GPIO_47, LS_I2C0_SDA, LSEC pin 17 */
+		"[I2C0_SCL]", /* GPIO_48, LS_I2C0_SCL, LSEC pin 15 */
+		"[UART0_TxD]", /* GPIO_49, BLSP9_UART_TX, LSEC pin 5 */
+		"[UART0_RxD]", /* GPIO_50, BLSP9_UART_RX, LSEC pin 7 */
+		"[UART0_CTS]", /* GPIO_51, BLSP9_UART_CTS_N, LSEC pin 3 */
+		"[UART0_RTS]", /* GPIO_52, BLSP9_UART_RFR_N, LSEC pin 9 */
+		"[CODEC_INT1_N]", /* GPIO_53 */
+		"[CODEC_INT2_N]", /* GPIO_54 */
+		"[BLSP7_I2C_SDA]", /* GPIO_55 */
+		"[BLSP7_I2C_SCL]", /* GPIO_56 */
+		"MI2S_MCLK", /* GPIO_57, S HSEC pin 3 */
+		"[PCM_CLK]", /* GPIO_58, QUA_MI2S_SCK, LSEC pin 18 */
+		"[PCM_FS]", /* GPIO_59, QUA_MI2S_WS, LSEC pin 16 */
+		"[PCM_DO]", /* GPIO_60, QUA_MI2S_DATA0, LSEC pin 20 */
+		"[PCM_DI]", /* GPIO_61, QUA_MI2S_DATA1, LSEC pin 22 */
+		"GPIO-E", /* GPIO_62, LSEC pin 27 */
+		"TP87", /* GPIO_63 */
+		"[CODEC_RST_N]", /* GPIO_64 */
+		"[PCM1_CLK]", /* GPIO_65 */
+		"[PCM1_SYNC]", /* GPIO_66 */
+		"[PCM1_DIN]", /* GPIO_67 */
+		"[PCM1_DOUT]", /* GPIO_68 */
+		"AUDIO_REF_CLK", /* GPIO_69 */
+		"SLIMBUS_CLK", /* GPIO_70 */
+		"SLIMBUS_DATA0", /* GPIO_71 */
+		"SLIMBUS_DATA1", /* GPIO_72 */
+		"NC", /* GPIO_73 */
+		"NC", /* GPIO_74 */
+		"NC", /* GPIO_75 */
+		"NC", /* GPIO_76 */
+		"TP94", /* GPIO_77 */
+		"NC", /* GPIO_78 */
+		"TP95", /* GPIO_79 */
+		"GPIO-A", /* GPIO_80, MEMS_RESET_N, LSEC pin 23 */
+		"TP88", /* GPIO_81 */
+		"TP89", /* GPIO_82 */
+		"TP90", /* GPIO_83 */
+		"TP91", /* GPIO_84 */
+		"[SD_DAT0]", /* GPIO_85, BLSP12_SPI_MOSI, P HSEC pin 1 */
+		"[SD_CMD]", /* GPIO_86, BLSP12_SPI_MISO, P HSEC pin 11 */
+		"[SD_DAT3]", /* GPIO_87, BLSP12_SPI_CS_N, P HSEC pin 7 */
+		"[SD_SCLK]", /* GPIO_88, BLSP12_SPI_CLK, P HSEC pin 9 */
+		"TSIF1_CLK", /* GPIO_89, S HSEC pin 42 */
+		"TSIF1_EN", /* GPIO_90, S HSEC pin 46 */
+		"TSIF1_DATA", /* GPIO_91, S HSEC pin 44 */
+		"NC", /* GPIO_92 */
+		"TSIF2_CLK", /* GPIO_93, S HSEC pin 52 */
+		"TSIF2_EN", /* GPIO_94, S HSEC pin 56 */
+		"TSIF2_DATA", /* GPIO_95, S HSEC pin 54 */
+		"TSIF2_SYNC", /* GPIO_96, S HSEC pin 58 */
+		"NC", /* GPIO_97 */
+		"CAM1_STANDBY_N", /* GPIO_98 */
+		"NC", /* GPIO_99 */
+		"NC", /* GPIO_100 */
+		"[LCD1_RESET_N]", /* GPIO_101, S HSEC pin 51 */
+		"BOOT_CONFIG1", /* GPIO_102 */
+		"USB_HUB_RESET", /* GPIO_103 */
+		"CAM1_RST_N", /* GPIO_104 */
+		"NC", /* GPIO_105 */
+		"NC", /* GPIO_106 */
+		"NC", /* GPIO_107 */
+		"NC", /* GPIO_108 */
+		"NC", /* GPIO_109 */
+		"NC", /* GPIO_110 */
+		"NC", /* GPIO_111 */
+		"NC", /* GPIO_112 */
+		"PMI8994_BUA", /* GPIO_113 */
+		"PCIE2_RST_N", /* GPIO_114 */
+		"PCIE2_CLKREQ_N", /* GPIO_115 */
+		"PCIE2_WAKE", /* GPIO_116 */
+		"SSC_IRQ_0", /* GPIO_117 */
+		"SSC_IRQ_1", /* GPIO_118 */
+		"SSC_IRQ_2", /* GPIO_119 */
+		"NC", /* GPIO_120 */
+		"GPIO121", /* GPIO_121, S HSEC pin 2 */
+		"NC", /* GPIO_122 */
+		"SSC_IRQ_6", /* GPIO_123 */
+		"SSC_IRQ_7", /* GPIO_124 */
+		"GPIO-C", /* GPIO_125, TS_INT0, LSEC pin 25 */
+		"BOOT_CONFIG5", /* GPIO_126 */
+		"NC", /* GPIO_127 */
+		"NC", /* GPIO_128 */
+		"BOOT_CONFIG7", /* GPIO_129 */
+		"PCIE1_RST_N", /* GPIO_130 */
+		"PCIE1_CLKREQ_N", /* GPIO_131 */
+		"PCIE1_WAKE", /* GPIO_132 */
+		"GPIO-L", /* GPIO_133, CAM2_STANDBY_N, LSEC pin 34 */
+		"NC", /* GPIO_134 */
+		"NC", /* GPIO_135 */
+		"BOOT_CONFIG8", /* GPIO_136 */
+		"NC", /* GPIO_137 */
+		"NC", /* GPIO_138 */
+		"GPS_SSBI2", /* GPIO_139 */
+		"GPS_SSBI1", /* GPIO_140 */
+		"NC", /* GPIO_141 */
+		"NC", /* GPIO_142 */
+		"NC", /* GPIO_143 */
+		"BOOT_CONFIG6", /* GPIO_144 */
+		"NC", /* GPIO_145 */
+		"NC", /* GPIO_146 */
+		"NC", /* GPIO_147 */
+		"NC", /* GPIO_148 */
+		"NC"; /* GPIO_149 */
+};
 
-		phy@7412000 {
-			status = "okay";
-		};
+&pm8994_gpios {
+	gpio-line-names =
+		"NC",
+		"KEY_VOLP_N",
+		"NC",
+		"BL1_PWM",
+		"GPIO-F", /* BL0_PWM, LSEC pin 28 */
+		"BL1_EN",
+		"NC",
+		"WLAN_EN",
+		"NC",
+		"NC",
+		"NC",
+		"NC",
+		"NC",
+		"NC",
+		"DIVCLK1",
+		"DIVCLK2",
+		"DIVCLK3",
+		"DIVCLK4",
+		"BT_EN",
+		"PMIC_SLB",
+		"PMIC_BUA",
+		"USB_VBUS_DET";
+};
 
-		usb@6af8800 {
-			status = "okay";
-			extcon = <&usb3_id>;
-
-			dwc3@6a00000 {
-				extcon = <&usb3_id>;
-				dr_mode = "otg";
-			};
-		};
+&pm8994_mpps {
+	gpio-line-names =
+		"VDDPX_BIAS",
+		"WIFI_LED",
+		"NC",
+		"BT_LED",
+		"PM_MPP05",
+		"PM_MPP06",
+		"PM_MPP07",
+		"NC";
+};
 
-		usb3_id: usb3-id {
-			compatible = "linux,extcon-usb-gpio";
-			id-gpio = <&pm8994_gpios 22 GPIO_ACTIVE_HIGH>;
-			pinctrl-names = "default";
-			pinctrl-0 = <&usb3_vbus_det_gpio>;
-		};
+&pmi8994_gpios {
+	gpio-line-names =
+		"NC",
+		"SPKR_AMP_EN1",
+		"SPKR_AMP_EN2",
+		"TP61",
+		"NC",
+		"USB2_VBUS_DET",
+		"NC",
+		"NC",
+		"NC",
+		"NC";
+};
 
-		usb@76f8800 {
-			status = "okay";
-			extcon = <&usb2_id>;
-
-			dwc3@7600000 {
-				extcon = <&usb2_id>;
-				dr_mode = "otg";
-				maximum-speed = "high-speed";
-			};
-		};
+&pcie_phy {
+	status = "okay";
 
-		usb2_id: usb2-id {
-			compatible = "linux,extcon-usb-gpio";
-			id-gpio = <&pmi8994_gpios 6 GPIO_ACTIVE_HIGH>;
-			pinctrl-names = "default";
-			pinctrl-0 = <&usb2_vbus_det_gpio>;
-		};
+	vdda-phy-supply = <&pm8994_l28>;
+	vdda-pll-supply = <&pm8994_l12>;
+};
 
-		wlan_en: wlan-en-1-8v {
-			pinctrl-names = "default";
-			pinctrl-0 = <&wlan_en_gpios>;
-			compatible = "regulator-fixed";
-			regulator-name = "wlan-en-regulator";
-			regulator-min-microvolt = <1800000>;
-			regulator-max-microvolt = <1800000>;
-
-			gpio = <&pm8994_gpios 8 0>;
-
-			/* WLAN card specific delay */
-			startup-delay-us = <70000>;
-			enable-active-high;
-		};
+&usb3phy {
+	status = "okay";
 
-		agnoc@0 {
-			pcie@600000 {
-				status = "okay";
-				perst-gpio = <&msmgpio 35 GPIO_ACTIVE_LOW>;
-				vddpe-3v3-supply = <&wlan_en>;
-			};
+	vdda-phy-supply = <&pm8994_l28>;
+	vdda-pll-supply = <&pm8994_l12>;
 
-			pcie@608000 {
-				status = "okay";
-				perst-gpio = <&msmgpio 130 GPIO_ACTIVE_LOW>;
-			};
+};
 
-			pcie@610000 {
-				status = "okay";
-				perst-gpio = <&msmgpio 114 GPIO_ACTIVE_LOW>;
-			};
-		};
+&hsusb_phy1 {
+	status = "okay";
 
-		slim_msm: slim@91c0000 {
-			ngd@1 {
-				wcd9335: codec@1{
-					clock-names = "mclk", "slimbus";
-					clocks = <&div1_mclk>,
-						 <&rpmcc RPM_SMD_BB_CLK1>;
-				};
-			};
-		};
+	vdda-pll-supply = <&pm8994_l12>;
+	vdda-phy-dpdm-supply = <&pm8994_l24>;
+};
 
-		mdss@900000 {
-			status = "okay";
+&hsusb_phy2 {
+	status = "okay";
 
-			mdp@901000 {
-				status = "okay";
-			};
+	vdda-pll-supply = <&pm8994_l12>;
+	vdda-phy-dpdm-supply = <&pm8994_l24>;
+};
 
-			hdmi-phy@9a0600 {
-				status = "okay";
+&usb3 {
+	status = "okay";
+	extcon = <&usb3_id>;
+
+	dwc3@6a00000 {
+		extcon = <&usb3_id>;
+		dr_mode = "otg";
+	};
+};
 
-				vddio-supply = <&pm8994_l12>;
-				vcca-supply = <&pm8994_l28>;
-				#phy-cells = <0>;
-			};
+&usb2 {
+	status = "okay";
+	extcon = <&usb2_id>;
+
+	dwc3@7600000 {
+		extcon = <&usb2_id>;
+		dr_mode = "otg";
+		maximum-speed = "high-speed";
+	};
+};
 
-			hdmi-tx@9a0000 {
-				status = "okay";
+&pcie0 {
+	status = "okay";
+	perst-gpio = <&msmgpio 35 GPIO_ACTIVE_LOW>;
+	vddpe-3v3-supply = <&wlan_en>;
+	vdda-supply = <&pm8994_l28>;
+};
 
-				pinctrl-names = "default", "sleep";
-				pinctrl-0 = <&hdmi_hpd_active &hdmi_ddc_active>;
-				pinctrl-1 = <&hdmi_hpd_suspend &hdmi_ddc_suspend>;
+&pcie1 {
+	status = "okay";
+	perst-gpio = <&msmgpio 130 GPIO_ACTIVE_LOW>;
+	vdda-supply = <&pm8994_l28>;
+};
 
-				core-vdda-supply = <&pm8994_l12>;
-				core-vcc-supply = <&pm8994_s4>;
-			};
-		};
-	};
+&pcie2 {
+	status = "okay";
+	perst-gpio = <&msmgpio 114 GPIO_ACTIVE_LOW>;
+	vdda-supply = <&pm8994_l28>;
+};
+
+&wcd9335 {
+	clock-names = "mclk", "slimbus";
+	clocks = <&div1_mclk>,
+		 <&rpmcc RPM_SMD_BB_CLK1>;
+
+	vdd-buck-supply = <&pm8994_s4>;
+	vdd-buck-sido-supply = <&pm8994_s4>;
+	vdd-tx-supply = <&pm8994_s4>;
+	vdd-rx-supply = <&pm8994_s4>;
+	vdd-io-supply = <&pm8994_s4>;
+};
+
+&mdss {
+	status = "okay";
+};
+
+&mdp {
+	status = "okay";
+};
+
+&hdmi_phy {
+	status = "okay";
+
+	vddio-supply = <&pm8994_l12>;
+	vcca-supply = <&pm8994_l28>;
+	#phy-cells = <0>;
+};
+
+&hdmi {
+	status = "okay";
 
+	pinctrl-names = "default", "sleep";
+	pinctrl-0 = <&hdmi_hpd_active &hdmi_ddc_active>;
+	pinctrl-1 = <&hdmi_hpd_suspend &hdmi_ddc_suspend>;
 
+	core-vdda-supply = <&pm8994_l12>;
+	core-vcc-supply = <&pm8994_s4>;
+};
+
+/ {
 	gpio_keys {
 		compatible = "gpio-keys";
 		#address-cells = <1>;
@@ -623,6 +625,8 @@
 				l21 {
 					regulator-min-microvolt = <2950000>;
 					regulator-max-microvolt = <2950000>;
+					regulator-allow-set-load;
+					regulator-system-load = <200000>;
 				};
 				l22 {
 					regulator-min-microvolt = <3300000>;
@@ -665,6 +669,35 @@
 			};
 		};
 	};
+
+	usb2_id: usb2-id {
+		compatible = "linux,extcon-usb-gpio";
+		id-gpio = <&pmi8994_gpios 6 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&usb2_vbus_det_gpio>;
+	};
+
+	usb3_id: usb3-id {
+		compatible = "linux,extcon-usb-gpio";
+		id-gpio = <&pm8994_gpios 22 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&usb3_vbus_det_gpio>;
+	};
+
+	wlan_en: wlan-en-1-8v {
+		pinctrl-names = "default";
+		pinctrl-0 = <&wlan_en_gpios>;
+		compatible = "regulator-fixed";
+		regulator-name = "wlan-en-regulator";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+
+		gpio = <&pm8994_gpios 8 0>;
+
+		/* WLAN card specific delay */
+		startup-delay-us = <70000>;
+		enable-active-high;
+	};
 };
 
 &spmi_bus {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/qcom/ipq8074-hk01.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/qcom/ipq8074-hk01.dts
@@ -20,7 +20,7 @@
 		stdout-path = "serial0";
 	};
 
-	memory {
+	memory@40000000 {
 		device_type = "memory";
 		reg = <0x0 0x40000000 0x0 0x20000000>;
 	};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/qcom/ipq8074.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/qcom/ipq8074.dtsi
@@ -253,7 +253,7 @@
 			status = "disabled";
 		};
 
-		qpic_nand: nand@79b0000 {
+		qpic_nand: nand-controller@79b0000 {
 			compatible = "qcom,ipq8074-nand";
 			reg = <0x79b0000 0x10000>;
 			#address-cells = <1>;
@@ -482,7 +482,7 @@
 	clocks {
 		sleep_clk: sleep_clk {
 			compatible = "fixed-clock";
-			clock-frequency = <32000>;
+			clock-frequency = <32768>;
 			#clock-cells = <0>;
 		};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/qcom/msm8916-pins.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/qcom/msm8916-pins.dtsi
@@ -508,7 +508,7 @@
 				pins = "gpio63", "gpio64", "gpio65", "gpio66",
 				       "gpio67", "gpio68";
 				drive-strength = <8>;
-				bias-pull-none;
+				bias-disable;
 			};
 		};
 		cdc_pdm_lines_sus: pdm_lines_off {
@@ -521,7 +521,7 @@
 				pins = "gpio63", "gpio64", "gpio65", "gpio66",
 				       "gpio67", "gpio68";
 				drive-strength = <2>;
-				bias-disable;
+				bias-pull-down;
 			};
 		};
 	};
@@ -537,7 +537,7 @@
 				pins = "gpio113", "gpio114", "gpio115",
 				       "gpio116";
 				drive-strength = <8>;
-				bias-pull-none;
+				bias-disable;
 			};
 		};
 
@@ -565,7 +565,7 @@
 			pinconf {
 				pins = "gpio110";
 				drive-strength = <8>;
-				bias-pull-none;
+				bias-disable;
 			};
 		};
 
@@ -591,7 +591,7 @@
 			pinconf {
 				pins = "gpio116";
 				drive-strength = <8>;
-				bias-pull-none;
+				bias-disable;
 			};
 		};
 		ext_mclk_tlmm_lines_sus: mclk_lines_off {
@@ -619,7 +619,7 @@
 				pins = "gpio112", "gpio117", "gpio118",
 					"gpio119";
 				drive-strength = <8>;
-				bias-pull-none;
+				bias-disable;
 			};
 		};
 		ext_sec_tlmm_lines_sus: tlmm_lines_off {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/qcom/msm8916.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/qcom/msm8916.dtsi
@@ -16,8 +16,8 @@
 	#size-cells = <2>;
 
 	aliases {
-		sdhc1 = &sdhc_1; /* SDC1 eMMC slot */
-		sdhc2 = &sdhc_2; /* SDC2 SD card slot */
+		mmc0 = &sdhc_1; /* SDC1 eMMC slot */
+		mmc1 = &sdhc_2; /* SDC2 SD card slot */
 	};
 
 	chosen { };
@@ -53,7 +53,7 @@
 			no-map;
 		};
 
-		reserved@8668000 {
+		reserved@86680000 {
 			reg = <0x0 0x86680000 0x0 0x80000>;
 			no-map;
 		};
@@ -66,7 +66,7 @@
 			qcom,client-id = <1>;
 		};
 
-		rfsa@867e00000 {
+		rfsa@867e0000 {
 			reg = <0x0 0x867e0000 0x0 0x20000>;
 			no-map;
 		};
@@ -175,14 +175,14 @@
 	};
 
 	thermal-zones {
-		cpu0_1-thermal {
+		cpu0-1-thermal {
 			polling-delay-passive = <250>;
 			polling-delay = <1000>;
 
 			thermal-sensors = <&tsens 4>;
 
 			trips {
-				cpu0_1_alert0: trip-point@0 {
+				cpu0_1_alert0: trip-point0 {
 					temperature = <75000>;
 					hysteresis = <2000>;
 					type = "passive";
@@ -205,14 +205,14 @@
 			};
 		};
 
-		cpu2_3-thermal {
+		cpu2-3-thermal {
 			polling-delay-passive = <250>;
 			polling-delay = <1000>;
 
 			thermal-sensors = <&tsens 3>;
 
 			trips {
-				cpu2_3_alert0: trip-point@0 {
+				cpu2_3_alert0: trip-point0 {
 					temperature = <75000>;
 					hysteresis = <2000>;
 					type = "passive";
@@ -242,7 +242,7 @@
 			thermal-sensors = <&tsens 2>;
 
 			trips {
-				gpu_alert0: trip-point@0 {
+				gpu_alert0: trip-point0 {
 					temperature = <75000>;
 					hysteresis = <2000>;
 					type = "passive";
@@ -262,7 +262,7 @@
 			thermal-sensors = <&tsens 1>;
 
 			trips {
-				cam_alert0: trip-point@0 {
+				cam_alert0: trip-point0 {
 					temperature = <75000>;
 					hysteresis = <2000>;
 					type = "hot";
@@ -277,7 +277,7 @@
 			thermal-sensors = <&tsens 0>;
 
 			trips {
-				modem_alert0: trip-point@0 {
+				modem_alert0: trip-point0 {
 					temperature = <85000>;
 					hysteresis = <2000>;
 					type = "hot";
@@ -934,7 +934,7 @@
 				reg-names = "mdp_phys";
 
 				interrupt-parent = <&mdss>;
-				interrupts = <0 0>;
+				interrupts = <0>;
 
 				clocks = <&gcc GCC_MDSS_AHB_CLK>,
 					 <&gcc GCC_MDSS_AXI_CLK>,
@@ -966,7 +966,7 @@
 				reg-names = "dsi_ctrl";
 
 				interrupt-parent = <&mdss>;
-				interrupts = <4 0>;
+				interrupts = <4>;
 
 				assigned-clocks = <&gcc BYTE0_CLK_SRC>,
 						  <&gcc PCLK0_CLK_SRC>;
@@ -1097,8 +1097,8 @@
 			vddmx-supply = <&pm8916_l3>;
 			vddpx-supply = <&pm8916_l7>;
 
-			qcom,state = <&wcnss_smp2p_out 0>;
-			qcom,state-names = "stop";
+			qcom,smem-states = <&wcnss_smp2p_out 0>;
+			qcom,smem-state-names = "stop";
 
 			pinctrl-names = "default";
 			pinctrl-0 = <&wcnss_pin_a>;
@@ -1451,7 +1451,7 @@
 			};
 		};
 
-		camss: camss@1b00000 {
+		camss: camss@1b0ac00 {
 			compatible = "qcom,msm8916-camss";
 			reg = <0x1b0ac00 0x200>,
 				<0x1b00030 0x4>,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/qcom/msm8994-angler-rev-101.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/qcom/msm8994-angler-rev-101.dts
@@ -30,3 +30,7 @@
 		};
 	};
 };
+
+&msmgpio {
+	gpio-reserved-ranges = <85 4>;
+};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -433,6 +433,19 @@
 		};
 	};
 
+	etm {
+		compatible = "qcom,coresight-remote-etm";
+
+		out-ports {
+			port {
+				modem_etm_out_funnel_in2: endpoint {
+					remote-endpoint =
+					  <&funnel_in2_in_modem_etm>;
+				};
+			};
+		};
+	};
+
 	psci {
 		compatible = "arm,psci-1.0";
 		method = "smc";
@@ -571,7 +584,7 @@
 
 		rpm_msg_ram: memory@68000 {
 			compatible = "qcom,rpm-msg-ram";
-			reg = <0x68000 0x6000>;
+			reg = <0x00068000 0x6000>;
 		};
 
 		rng: rng@83000 {
@@ -583,28 +596,28 @@
 
 		tcsr_mutex_regs: syscon@740000 {
 			compatible = "syscon";
-			reg = <0x740000 0x20000>;
+			reg = <0x00740000 0x20000>;
 		};
 
 		tsens0: thermal-sensor@4a9000 {
 			compatible = "qcom,msm8996-tsens";
-			reg = <0x4a9000 0x1000>, /* TM */
-			      <0x4a8000 0x1000>; /* SROT */
+			reg = <0x004a9000 0x1000>, /* TM */
+			      <0x004a8000 0x1000>; /* SROT */
 			#qcom,sensors = <13>;
 			#thermal-sensor-cells = <1>;
 		};
 
 		tsens1: thermal-sensor@4ad000 {
 			compatible = "qcom,msm8996-tsens";
-			reg = <0x4ad000 0x1000>, /* TM */
-			      <0x4ac000 0x1000>; /* SROT */
+			reg = <0x004ad000 0x1000>, /* TM */
+			      <0x004ac000 0x1000>; /* SROT */
 			#qcom,sensors = <8>;
 			#thermal-sensor-cells = <1>;
 		};
 
 		tcsr: syscon@7a0000 {
 			compatible = "qcom,tcsr-msm8996", "syscon";
-			reg = <0x7a0000 0x18000>;
+			reg = <0x007a0000 0x18000>;
 		};
 
 		intc: interrupt-controller@9bc0000 {
@@ -620,7 +633,7 @@
 
 		apcs_glb: mailbox@9820000 {
 			compatible = "qcom,msm8996-apcs-hmss-global";
-			reg = <0x9820000 0x1000>;
+			reg = <0x09820000 0x1000>;
 
 			#mbox-cells = <1>;
 		};
@@ -630,7 +643,7 @@
 			#clock-cells = <1>;
 			#reset-cells = <1>;
 			#power-domain-cells = <1>;
-			reg = <0x300000 0x90000>;
+			reg = <0x00300000 0x90000>;
 		};
 
 		stm@3002000 {
@@ -736,6 +749,14 @@
 			clocks = <&rpmcc RPM_QDSS_CLK>, <&rpmcc RPM_QDSS_A_CLK>;
 			clock-names = "apb_pclk", "atclk";
 
+			in-ports {
+				port {
+					funnel_in2_in_modem_etm: endpoint {
+						remote-endpoint =
+						  <&modem_etm_out_funnel_in2>;
+					};
+				};
+			};
 
 			out-ports {
 				port {
@@ -1103,7 +1124,7 @@
 
 		kryocc: clock-controller@6400000 {
 			compatible = "qcom,apcc-msm8996";
-			reg = <0x6400000 0x90000>;
+			reg = <0x06400000 0x90000>;
 			#clock-cells = <1>;
 		};
 
@@ -1149,7 +1170,7 @@
 
 		blsp2_uart1: serial@75b0000 {
 			compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
-			reg = <0x75b0000 0x1000>;
+			reg = <0x075b0000 0x1000>;
 			interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&gcc GCC_BLSP2_UART2_APPS_CLK>,
 				 <&gcc GCC_BLSP2_AHB_CLK>;
@@ -1215,7 +1236,7 @@
 		sdhc2: sdhci@74a4900 {
 			 status = "disabled";
 			 compatible = "qcom,sdhci-msm-v4";
-			 reg = <0x74a4900 0x314>, <0x74a4000 0x800>;
+			 reg = <0x074a4900 0x314>, <0x074a4000 0x800>;
 			 reg-names = "hc_mem", "core_mem";
 
 			 interrupts = <0 125 IRQ_TYPE_LEVEL_HIGH>,
@@ -1300,11 +1321,11 @@
 
 		spmi_bus: qcom,spmi@400f000 {
 			compatible = "qcom,spmi-pmic-arb";
-			reg = <0x400f000 0x1000>,
-			      <0x4400000 0x800000>,
-			      <0x4c00000 0x800000>,
-			      <0x5800000 0x200000>,
-			      <0x400a000 0x002100>;
+			reg = <0x0400f000 0x1000>,
+			      <0x04400000 0x800000>,
+			      <0x04c00000 0x800000>,
+			      <0x05800000 0x200000>,
+			      <0x0400a000 0x002100>;
 			reg-names = "core", "chnls", "obsrvr", "intr", "cnfg";
 			interrupt-names = "periph_irq";
 			interrupts = <GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH>;
@@ -1318,20 +1339,10 @@
 
 		ufsphy: phy@627000 {
 			compatible = "qcom,msm8996-ufs-phy-qmp-14nm";
-			reg = <0x627000 0xda8>;
+			reg = <0x00627000 0xda8>;
 			reg-names = "phy_mem";
 			#phy-cells = <0>;
 
-			vdda-phy-supply = <&pm8994_l28>;
-			vdda-pll-supply = <&pm8994_l12>;
-
-			vdda-phy-max-microamp = <18380>;
-			vdda-pll-max-microamp = <9440>;
-
-			vddp-ref-clk-supply = <&pm8994_l25>;
-			vddp-ref-clk-max-microamp = <100>;
-			vddp-ref-clk-always-on;
-
 			clock-names = "ref_clk_src", "ref_clk";
 			clocks = <&rpmcc RPM_SMD_LN_BB_CLK>,
 				 <&gcc GCC_UFS_CLKREF_CLK>;
@@ -1341,20 +1352,12 @@
 
 		ufshc: ufshc@624000 {
 			compatible = "qcom,ufshc";
-			reg = <0x624000 0x2500>;
+			reg = <0x00624000 0x2500>;
 			interrupts = <GIC_SPI 265 IRQ_TYPE_LEVEL_HIGH>;
 
 			phys = <&ufsphy>;
 			phy-names = "ufsphy";
 
-			vcc-supply = <&pm8994_l20>;
-			vccq-supply = <&pm8994_l25>;
-			vccq2-supply = <&pm8994_s4>;
-
-			vcc-max-microamp = <600000>;
-			vccq-max-microamp = <450000>;
-			vccq2-max-microamp = <450000>;
-
 			power-domains = <&gcc UFS_GDSC>;
 
 			clock-names =
@@ -1383,7 +1386,7 @@
 				<&gcc GCC_UFS_RX_SYMBOL_0_CLK>;
 			freq-table-hz =
 				<100000000 200000000>,
-				<0 0>,
+				<100000000 200000000>,
 				<0 0>,
 				<0 0>,
 				<0 0>,
@@ -1408,7 +1411,7 @@
 			#clock-cells = <1>;
 			#reset-cells = <1>;
 			#power-domain-cells = <1>;
-			reg = <0x8c0000 0x40000>;
+			reg = <0x008c0000 0x40000>;
 			assigned-clocks = <&mmcc MMPLL9_PLL>,
 					  <&mmcc MMPLL1_PLL>,
 					  <&mmcc MMPLL3_PLL>,
@@ -1423,7 +1426,7 @@
 
 		qfprom@74000 {
 			compatible = "qcom,qfprom";
-			reg = <0x74000 0x8ff>;
+			reg = <0x00074000 0x8ff>;
 			#address-cells = <1>;
 			#size-cells = <1>;
 
@@ -1443,9 +1446,9 @@
 			};
 		};
 
-		phy@34000 {
+		pcie_phy: phy@34000 {
 			compatible = "qcom,msm8996-qmp-pcie-phy";
-			reg = <0x34000 0x488>;
+			reg = <0x00034000 0x488>;
 			#clock-cells = <1>;
 			#address-cells = <1>;
 			#size-cells = <1>;
@@ -1456,9 +1459,6 @@
 				<&gcc GCC_PCIE_CLKREF_CLK>;
 			clock-names = "aux", "cfg_ahb", "ref";
 
-			vdda-phy-supply = <&pm8994_l28>;
-			vdda-pll-supply = <&pm8994_l12>;
-
 			resets = <&gcc GCC_PCIE_PHY_BCR>,
 				<&gcc GCC_PCIE_PHY_COM_BCR>,
 				<&gcc GCC_PCIE_PHY_COM_NOCSR_BCR>;
@@ -1466,9 +1466,9 @@
 			status = "disabled";
 
 			pciephy_0: lane@35000 {
-				reg = <0x035000 0x130>,
-					<0x035200 0x200>,
-					<0x035400 0x1dc>;
+				reg = <0x00035000 0x130>,
+				      <0x00035200 0x200>,
+				      <0x00035400 0x1dc>;
 				#phy-cells = <0>;
 
 				clock-output-names = "pcie_0_pipe_clk_src";
@@ -1479,9 +1479,9 @@
 			};
 
 			pciephy_1: lane@36000 {
-				reg = <0x036000 0x130>,
-					<0x036200 0x200>,
-					<0x036400 0x1dc>;
+				reg = <0x00036000 0x130>,
+				      <0x00036200 0x200>,
+				      <0x00036400 0x1dc>;
 				#phy-cells = <0>;
 
 				clock-output-names = "pcie_1_pipe_clk_src";
@@ -1492,9 +1492,9 @@
 			};
 
 			pciephy_2: lane@37000 {
-				reg = <0x037000 0x130>,
-					<0x037200 0x200>,
-					<0x037400 0x1dc>;
+				reg = <0x00037000 0x130>,
+				      <0x00037200 0x200>,
+				      <0x00037400 0x1dc>;
 				#phy-cells = <0>;
 
 				clock-output-names = "pcie_2_pipe_clk_src";
@@ -1505,9 +1505,9 @@
 			};
 		};
 
-		phy@7410000 {
+		usb3phy: phy@7410000 {
 			compatible = "qcom,msm8996-qmp-usb3-phy";
-			reg = <0x7410000 0x1c4>;
+			reg = <0x07410000 0x1c4>;
 			#clock-cells = <1>;
 			#address-cells = <1>;
 			#size-cells = <1>;
@@ -1518,18 +1518,15 @@
 				<&gcc GCC_USB3_CLKREF_CLK>;
 			clock-names = "aux", "cfg_ahb", "ref";
 
-			vdda-phy-supply = <&pm8994_l28>;
-			vdda-pll-supply = <&pm8994_l12>;
-
 			resets = <&gcc GCC_USB3_PHY_BCR>,
 				<&gcc GCC_USB3PHY_PHY_BCR>;
 			reset-names = "phy", "common";
 			status = "disabled";
 
 			ssusb_phy_0: lane@7410200 {
-				reg = <0x7410200 0x200>,
-					<0x7410400 0x130>,
-					<0x7410600 0x1a8>;
+				reg = <0x07410200 0x200>,
+				      <0x07410400 0x130>,
+				      <0x07410600 0x1a8>;
 				#phy-cells = <0>;
 
 				clock-output-names = "usb3_phy_pipe_clk_src";
@@ -1540,16 +1537,13 @@
 
 		hsusb_phy1: phy@7411000 {
 			compatible = "qcom,msm8996-qusb2-phy";
-			reg = <0x7411000 0x180>;
+			reg = <0x07411000 0x180>;
 			#phy-cells = <0>;
 
 			clocks = <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>,
 				<&gcc GCC_RX1_USB2_CLKREF_CLK>;
 			clock-names = "cfg_ahb", "ref";
 
-			vdda-pll-supply = <&pm8994_l12>;
-			vdda-phy-dpdm-supply = <&pm8994_l24>;
-
 			resets = <&gcc GCC_QUSB2PHY_PRIM_BCR>;
 			nvmem-cells = <&qusb2p_hstx_trim>;
 			status = "disabled";
@@ -1557,16 +1551,13 @@
 
 		hsusb_phy2: phy@7412000 {
 			compatible = "qcom,msm8996-qusb2-phy";
-			reg = <0x7412000 0x180>;
+			reg = <0x07412000 0x180>;
 			#phy-cells = <0>;
 
 			clocks = <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>,
 				<&gcc GCC_RX2_USB2_CLKREF_CLK>;
 			clock-names = "cfg_ahb", "ref";
 
-			vdda-pll-supply = <&pm8994_l12>;
-			vdda-phy-dpdm-supply = <&pm8994_l24>;
-
 			resets = <&gcc GCC_QUSB2PHY_SEC_BCR>;
 			nvmem-cells = <&qusb2s_hstx_trim>;
 			status = "disabled";
@@ -1574,7 +1565,7 @@
 
 		usb2: usb@76f8800 {
 			compatible = "qcom,msm8996-dwc3", "qcom,dwc3";
-			reg = <0x76f8800 0x400>;
+			reg = <0x076f8800 0x400>;
 			#address-cells = <1>;
 			#size-cells = <1>;
 			ranges;
@@ -1594,16 +1585,18 @@
 
 			dwc3@7600000 {
 				compatible = "snps,dwc3";
-				reg = <0x7600000 0xcc00>;
+				reg = <0x07600000 0xcc00>;
 				interrupts = <0 138 IRQ_TYPE_LEVEL_HIGH>;
 				phys = <&hsusb_phy2>;
 				phy-names = "usb2-phy";
+				snps,dis_u2_susphy_quirk;
+				snps,dis_enblslpm_quirk;
 			};
 		};
 
 		usb3: usb@6af8800 {
 			compatible = "qcom,msm8996-dwc3", "qcom,dwc3";
-			reg = <0x6af8800 0x400>;
+			reg = <0x06af8800 0x400>;
 			#address-cells = <1>;
 			#size-cells = <1>;
 			ranges;
@@ -1624,16 +1617,18 @@
 
 			dwc3@6a00000 {
 				compatible = "snps,dwc3";
-				reg = <0x6a00000 0xcc00>;
+				reg = <0x06a00000 0xcc00>;
 				interrupts = <0 131 IRQ_TYPE_LEVEL_HIGH>;
 				phys = <&hsusb_phy1>, <&ssusb_phy_0>;
 				phy-names = "usb2-phy", "usb3-phy";
+				snps,dis_u2_susphy_quirk;
+				snps,dis_enblslpm_quirk;
 			};
 		};
 
 		vfe_smmu: iommu@da0000 {
 			compatible = "qcom,msm8996-smmu-v2", "qcom,smmu-v2";
-			reg = <0xda0000 0x10000>;
+			reg = <0x00da0000 0x10000>;
 
 			#global-interrupts = <1>;
 			interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>,
@@ -1649,20 +1644,20 @@
 
 		camss: camss@a00000 {
 			compatible = "qcom,msm8996-camss";
-			reg = <0xa34000 0x1000>,
-				<0xa00030 0x4>,
-				<0xa35000 0x1000>,
-				<0xa00038 0x4>,
-				<0xa36000 0x1000>,
-				<0xa00040 0x4>,
-				<0xa30000 0x100>,
-				<0xa30400 0x100>,
-				<0xa30800 0x100>,
-				<0xa30c00 0x100>,
-				<0xa31000 0x500>,
-				<0xa00020 0x10>,
-				<0xa10000 0x1000>,
-				<0xa14000 0x1000>;
+			reg = <0x00a34000 0x1000>,
+			      <0x00a00030 0x4>,
+			      <0x00a35000 0x1000>,
+			      <0x00a00038 0x4>,
+			      <0x00a36000 0x1000>,
+			      <0x00a00040 0x4>,
+			      <0x00a30000 0x100>,
+			      <0x00a30400 0x100>,
+			      <0x00a30800 0x100>,
+			      <0x00a30c00 0x100>,
+			      <0x00a31000 0x500>,
+			      <0x00a00020 0x10>,
+			      <0x00a10000 0x1000>,
+			      <0x00a14000 0x1000>;
 			reg-names = "csiphy0",
 				"csiphy0_clk_mux",
 				"csiphy1",
@@ -1677,16 +1672,16 @@
 				"csi_clk_mux",
 				"vfe0",
 				"vfe1";
-			interrupts = <GIC_SPI 78 0>,
-				<GIC_SPI 79 0>,
-				<GIC_SPI 80 0>,
-				<GIC_SPI 296 0>,
-				<GIC_SPI 297 0>,
-				<GIC_SPI 298 0>,
-				<GIC_SPI 299 0>,
-				<GIC_SPI 309 0>,
-				<GIC_SPI 314 0>,
-				<GIC_SPI 315 0>;
+			interrupts = <GIC_SPI 78 IRQ_TYPE_EDGE_RISING>,
+				<GIC_SPI 79 IRQ_TYPE_EDGE_RISING>,
+				<GIC_SPI 80 IRQ_TYPE_EDGE_RISING>,
+				<GIC_SPI 296 IRQ_TYPE_EDGE_RISING>,
+				<GIC_SPI 297 IRQ_TYPE_EDGE_RISING>,
+				<GIC_SPI 298 IRQ_TYPE_EDGE_RISING>,
+				<GIC_SPI 299 IRQ_TYPE_EDGE_RISING>,
+				<GIC_SPI 309 IRQ_TYPE_EDGE_RISING>,
+				<GIC_SPI 314 IRQ_TYPE_EDGE_RISING>,
+				<GIC_SPI 315 IRQ_TYPE_EDGE_RISING>;
 			interrupt-names = "csiphy0",
 				"csiphy1",
 				"csiphy2",
@@ -1770,7 +1765,6 @@
 				"vfe1_stream",
 				"vfe_ahb",
 				"vfe_axi";
-			vdda-supply = <&pm8994_l2>;
 			iommus = <&vfe_smmu 0>,
 				 <&vfe_smmu 1>,
 				 <&vfe_smmu 2>,
@@ -1784,7 +1778,7 @@
 
 		adreno_smmu: iommu@b40000 {
 			compatible = "qcom,msm8996-smmu-v2", "qcom,smmu-v2";
-			reg = <0xb40000 0x10000>;
+			reg = <0x00b40000 0x10000>;
 
 			#global-interrupts = <1>;
 			interrupts = <GIC_SPI 334 IRQ_TYPE_LEVEL_HIGH>,
@@ -1801,7 +1795,7 @@
 
 		mdp_smmu: iommu@d00000 {
 			compatible = "qcom,msm8996-smmu-v2", "qcom,smmu-v2";
-			reg = <0xd00000 0x10000>;
+			reg = <0x00d00000 0x10000>;
 
 			#global-interrupts = <1>;
 			interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>,
@@ -1817,7 +1811,7 @@
 
 		lpass_q6_smmu: iommu@1600000 {
 			compatible = "qcom,msm8996-smmu-v2", "qcom,smmu-v2";
-			reg = <0x1600000 0x20000>;
+			reg = <0x01600000 0x20000>;
 			#iommu-cells = <1>;
 			power-domains = <&gcc HLOS1_VOTE_LPASS_CORE_GDSC>;
 
@@ -1882,9 +1876,6 @@
 				pinctrl-0 = <&pcie0_clkreq_default &pcie0_perst_default &pcie0_wake_default>;
 				pinctrl-1 = <&pcie0_clkreq_sleep &pcie0_perst_default &pcie0_wake_sleep>;
 
-
-				vdda-supply = <&pm8994_l28>;
-
 				linux,pci-domain = <0>;
 
 				clocks = <&gcc GCC_PCIE_0_PIPE_CLK>,
@@ -1937,8 +1928,6 @@
 				pinctrl-0 = <&pcie1_clkreq_default &pcie1_perst_default &pcie1_wake_default>;
 				pinctrl-1 = <&pcie1_clkreq_sleep &pcie1_perst_default &pcie1_wake_sleep>;
 
-
-				vdda-supply = <&pm8994_l28>;
 				linux,pci-domain = <1>;
 
 				clocks = <&gcc GCC_PCIE_1_PIPE_CLK>,
@@ -1990,8 +1979,6 @@
 				pinctrl-0 = <&pcie2_clkreq_default &pcie2_perst_default &pcie2_wake_default>;
 				pinctrl-1 = <&pcie2_clkreq_sleep &pcie2_perst_default &pcie2_wake_sleep >;
 
-				vdda-supply = <&pm8994_l28>;
-
 				linux,pci-domain = <2>;
 				clocks = <&gcc GCC_PCIE_2_PIPE_CLK>,
 					<&gcc GCC_PCIE_2_AUX_CLK>,
@@ -2011,7 +1998,7 @@
 		{
 			compatible = "qcom,bam-v1.7.0";
 			qcom,controlled-remotely;
-			reg = <0x9184000 0x32000>;
+			reg = <0x09184000 0x32000>;
 			num-channels  = <31>;
 			interrupts = <0 164 IRQ_TYPE_LEVEL_HIGH>;
 			#dma-cells = <1>;
@@ -2021,7 +2008,7 @@
 
 		slim_msm: slim@91c0000 {
 			compatible = "qcom,slim-ngd-v1.5.0";
-			reg = <0x91c0000 0x2C000>;
+			reg = <0x091c0000 0x2C000>;
 			reg-names = "ctrl";
 			interrupts = <0 163 IRQ_TYPE_LEVEL_HIGH>;
 			dmas =	<&slimbam 3>, <&slimbam 4>,
@@ -2056,12 +2043,6 @@
 
 					slim-ifc-dev  = <&tasha_ifd>;
 
-					vdd-buck-supply = <&pm8994_s4>;
-					vdd-buck-sido-supply = <&pm8994_s4>;
-					vdd-tx-supply = <&pm8994_s4>;
-					vdd-rx-supply = <&pm8994_s4>;
-					vdd-io-supply = <&pm8994_s4>;
-
 					#sound-dai-cells = <1>;
 				};
 			};
@@ -2071,7 +2052,7 @@
 			compatible = "qcom,adreno-530.2", "qcom,adreno";
 			#stream-id-cells = <16>;
 
-			reg = <0xb00000 0x3f000>;
+			reg = <0x00b00000 0x3f000>;
 			reg-names = "kgsl_3d0_reg_memory";
 
 			interrupts = <0 300 IRQ_TYPE_LEVEL_HIGH>;
@@ -2094,9 +2075,6 @@
 			nvmem-cells = <&gpu_speed_bin>;
 			nvmem-cell-names = "speed_bin";
 
-			qcom,gpu-quirk-two-pass-use-wfi;
-			qcom,gpu-quirk-fault-detect-mask;
-
 			operating-points-v2 = <&gpu_opp_table>;
 
 			gpu_opp_table: opp-table {
@@ -2145,9 +2123,9 @@
 		mdss: mdss@900000 {
 			compatible = "qcom,mdss";
 
-			reg = <0x900000 0x1000>,
-			      <0x9b0000 0x1040>,
-			      <0x9b8000 0x1040>;
+			reg = <0x00900000 0x1000>,
+			      <0x009b0000 0x1040>,
+			      <0x009b8000 0x1040>;
 			reg-names = "mdss_phys",
 				    "vbif_phys",
 				    "vbif_nrt_phys";
@@ -2167,7 +2145,7 @@
 
 			mdp: mdp@901000 {
 				compatible = "qcom,mdp5";
-				reg = <0x901000 0x90000>;
+				reg = <0x00901000 0x90000>;
 				reg-names = "mdp_phys";
 
 				interrupt-parent = <&mdss>;
@@ -2243,12 +2221,12 @@
 			hdmi_phy: hdmi-phy@9a0600 {
 				#phy-cells = <0>;
 				compatible = "qcom,hdmi-phy-8996";
-				reg = <0x9a0600 0x1c4>,
-				      <0x9a0a00 0x124>,
-				      <0x9a0c00 0x124>,
-				      <0x9a0e00 0x124>,
-				      <0x9a1000 0x124>,
-				      <0x9a1200 0x0c8>;
+				reg = <0x009a0600 0x1c4>,
+				      <0x009a0a00 0x124>,
+				      <0x009a0c00 0x124>,
+				      <0x009a0e00 0x124>,
+				      <0x009a1000 0x124>,
+				      <0x009a1200 0x0c8>;
 				reg-names = "hdmi_pll",
 					    "hdmi_tx_l0",
 					    "hdmi_tx_l1",
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/qcom/msm8998-clamshell.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/qcom/msm8998-clamshell.dtsi
@@ -23,6 +23,43 @@
 	};
 };
 
+/*
+ * The laptop FW does not appear to support the retention state as it is
+ * not advertised as enabled in ACPI, and enabling it in DT can cause boot
+ * hangs.
+ */
+&CPU0 {
+	cpu-idle-states = <&LITTLE_CPU_SLEEP_1>;
+};
+
+&CPU1 {
+	cpu-idle-states = <&LITTLE_CPU_SLEEP_1>;
+};
+
+&CPU2 {
+	cpu-idle-states = <&LITTLE_CPU_SLEEP_1>;
+};
+
+&CPU3 {
+	cpu-idle-states = <&LITTLE_CPU_SLEEP_1>;
+};
+
+&CPU4 {
+	cpu-idle-states = <&BIG_CPU_SLEEP_1>;
+};
+
+&CPU5 {
+	cpu-idle-states = <&BIG_CPU_SLEEP_1>;
+};
+
+&CPU6 {
+	cpu-idle-states = <&BIG_CPU_SLEEP_1>;
+};
+
+&CPU7 {
+	cpu-idle-states = <&BIG_CPU_SLEEP_1>;
+};
+
 &qusb2phy {
 	status = "okay";
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/qcom/msm8998-mtp.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/qcom/msm8998-mtp.dtsi
@@ -27,6 +27,66 @@
 	status = "okay";
 };
 
+&etf {
+	status = "okay";
+};
+
+&etm1 {
+	status = "okay";
+};
+
+&etm2 {
+	status = "okay";
+};
+
+&etm3 {
+	status = "okay";
+};
+
+&etm4 {
+	status = "okay";
+};
+
+&etm5 {
+	status = "okay";
+};
+
+&etm6 {
+	status = "okay";
+};
+
+&etm7 {
+	status = "okay";
+};
+
+&etm8 {
+	status = "okay";
+};
+
+&etr {
+	status = "okay";
+};
+
+&funnel1 {
+	status = "okay";
+};
+
+&funnel2 {
+	status = "okay";
+};
+
+&funnel3 {
+	status = "okay";
+};
+
+&funnel4 {
+	status = "okay";
+};
+
+&funnel5 {
+	status = "okay";
+};
+
 &pm8005_lsid1 {
 	pm8005-regulators {
 		compatible = "qcom,pm8005-regulators";
@@ -51,6 +111,10 @@
 	vdda-phy-dpdm-supply = <&vreg_l24a_3p075>;
 };
 
+&replicator1 {
+	status = "okay";
+};
+
 &rpm_requests {
 	pm8998-regulators {
 		compatible = "qcom,rpm-pm8998-regulators";
@@ -249,6 +313,10 @@
 	pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>;
 };
 
+&stm {
+	status = "okay";
+};
+
 &ufshc {
 	vcc-supply = <&vreg_l20a_2p95>;
 	vccq-supply = <&vreg_l26a_1p2>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/qcom/msm8998.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/qcom/msm8998.dtsi
@@ -246,38 +246,42 @@
 			LITTLE_CPU_SLEEP_0: cpu-sleep-0-0 {
 				compatible = "arm,idle-state";
 				idle-state-name = "little-retention";
+				/* CPU Retention (C2D), L2 Active */
 				arm,psci-suspend-param = <0x00000002>;
 				entry-latency-us = <81>;
 				exit-latency-us = <86>;
-				min-residency-us = <200>;
+				min-residency-us = <504>;
 			};
 
 			LITTLE_CPU_SLEEP_1: cpu-sleep-0-1 {
 				compatible = "arm,idle-state";
 				idle-state-name = "little-power-collapse";
+				/* CPU + L2 Power Collapse (C3, D4) */
 				arm,psci-suspend-param = <0x40000003>;
-				entry-latency-us = <273>;
-				exit-latency-us = <612>;
-				min-residency-us = <1000>;
+				entry-latency-us = <814>;
+				exit-latency-us = <4562>;
+				min-residency-us = <9183>;
 				local-timer-stop;
 			};
 
 			BIG_CPU_SLEEP_0: cpu-sleep-1-0 {
 				compatible = "arm,idle-state";
 				idle-state-name = "big-retention";
+				/* CPU Retention (C2D), L2 Active */
 				arm,psci-suspend-param = <0x00000002>;
 				entry-latency-us = <79>;
 				exit-latency-us = <82>;
-				min-residency-us = <200>;
+				min-residency-us = <1302>;
 			};
 
 			BIG_CPU_SLEEP_1: cpu-sleep-1-1 {
 				compatible = "arm,idle-state";
 				idle-state-name = "big-power-collapse";
+				/* CPU + L2 Power Collapse (C3, D4) */
 				arm,psci-suspend-param = <0x40000003>;
-				entry-latency-us = <336>;
-				exit-latency-us = <525>;
-				min-residency-us = <1000>;
+				entry-latency-us = <724>;
+				exit-latency-us = <2027>;
+				min-residency-us = <9419>;
 				local-timer-stop;
 			};
 		};
@@ -868,10 +872,10 @@
 			interrupts = <GIC_SPI 405 IRQ_TYPE_LEVEL_HIGH>;
 			interrupt-names = "msi";
 			interrupt-map-mask = <0 0 0 0x7>;
-			interrupt-map =	<0 0 0 1 &intc 0 135 IRQ_TYPE_LEVEL_HIGH>,
-					<0 0 0 2 &intc 0 136 IRQ_TYPE_LEVEL_HIGH>,
-					<0 0 0 3 &intc 0 138 IRQ_TYPE_LEVEL_HIGH>,
-					<0 0 0 4 &intc 0 139 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-map =	<0 0 0 1 &intc 0 0 135 IRQ_TYPE_LEVEL_HIGH>,
+					<0 0 0 2 &intc 0 0 136 IRQ_TYPE_LEVEL_HIGH>,
+					<0 0 0 3 &intc 0 0 138 IRQ_TYPE_LEVEL_HIGH>,
+					<0 0 0 4 &intc 0 0 139 IRQ_TYPE_LEVEL_HIGH>;
 
 			clocks = <&gcc GCC_PCIE_0_PIPE_CLK>,
 				 <&gcc GCC_PCIE_0_MSTR_AXI_CLK>,
@@ -985,7 +989,7 @@
 
 		tcsr_mutex_regs: syscon@1f40000 {
 			compatible = "syscon";
-			reg = <0x01f40000 0x20000>;
+			reg = <0x01f40000 0x40000>;
 		};
 
 		tlmm: pinctrl@3400000 {
@@ -998,11 +1002,12 @@
 			#interrupt-cells = <0x2>;
 		};
 
-		stm@6002000 {
+		stm: stm@6002000 {
 			compatible = "arm,coresight-stm", "arm,primecell";
 			reg = <0x06002000 0x1000>,
 			      <0x16280000 0x180000>;
 			reg-names = "stm-base", "stm-data-base";
+			status = "disabled";
 
 			clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
 			clock-names = "apb_pclk", "atclk";
@@ -1016,9 +1021,10 @@
 			};
 		};
 
-		funnel@6041000 {
+		funnel1: funnel@6041000 {
 			compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
 			reg = <0x06041000 0x1000>;
+			status = "disabled";
 
 			clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
 			clock-names = "apb_pclk", "atclk";
@@ -1045,9 +1051,10 @@
 			};
 		};
 
-		funnel@6042000 {
+		funnel2: funnel@6042000 {
 			compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
 			reg = <0x06042000 0x1000>;
+			status = "disabled";
 
 			clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
 			clock-names = "apb_pclk", "atclk";
@@ -1075,9 +1082,10 @@
 			};
 		};
 
-		funnel@6045000 {
+		funnel3: funnel@6045000 {
 			compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
 			reg = <0x06045000 0x1000>;
+			status = "disabled";
 
 			clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
 			clock-names = "apb_pclk", "atclk";
@@ -1113,9 +1121,10 @@
 			};
 		};
 
-		replicator@6046000 {
+		replicator1: replicator@6046000 {
 			compatible = "arm,coresight-dynamic-replicator", "arm,primecell";
 			reg = <0x06046000 0x1000>;
+			status = "disabled";
 
 			clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
 			clock-names = "apb_pclk", "atclk";
@@ -1137,9 +1146,10 @@
 			};
 		};
 
-		etf@6047000 {
+		etf: etf@6047000 {
 			compatible = "arm,coresight-tmc", "arm,primecell";
 			reg = <0x06047000 0x1000>;
+			status = "disabled";
 
 			clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
 			clock-names = "apb_pclk", "atclk";
@@ -1163,9 +1173,10 @@
 			};
 		};
 
-		etr@6048000 {
+		etr: etr@6048000 {
 			compatible = "arm,coresight-tmc", "arm,primecell";
 			reg = <0x06048000 0x1000>;
+			status = "disabled";
 
 			clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
 			clock-names = "apb_pclk", "atclk";
@@ -1181,9 +1192,10 @@
 			};
 		};
 
-		etm@7840000 {
+		etm1: etm@7840000 {
 			compatible = "arm,coresight-etm4x", "arm,primecell";
 			reg = <0x07840000 0x1000>;
+			status = "disabled";
 
 			clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
 			clock-names = "apb_pclk", "atclk";
@@ -1200,9 +1212,10 @@
 			};
 		};
 
-		etm@7940000 {
+		etm2: etm@7940000 {
 			compatible = "arm,coresight-etm4x", "arm,primecell";
 			reg = <0x07940000 0x1000>;
+			status = "disabled";
 
 			clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
 			clock-names = "apb_pclk", "atclk";
@@ -1219,9 +1232,10 @@
 			};
 		};
 
-		etm@7a40000 {
+		etm3: etm@7a40000 {
 			compatible = "arm,coresight-etm4x", "arm,primecell";
 			reg = <0x07a40000 0x1000>;
+			status = "disabled";
 
 			clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
 			clock-names = "apb_pclk", "atclk";
@@ -1238,9 +1252,10 @@
 			};
 		};
 
-		etm@7b40000 {
+		etm4: etm@7b40000 {
 			compatible = "arm,coresight-etm4x", "arm,primecell";
 			reg = <0x07b40000 0x1000>;
+			status = "disabled";
 
 			clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
 			clock-names = "apb_pclk", "atclk";
@@ -1257,9 +1272,10 @@
 			};
 		};
 
-		funnel@7b60000 { /* APSS Funnel */
+		funnel4: funnel@7b60000 { /* APSS Funnel */
 			compatible = "arm,coresight-etm4x", "arm,primecell";
 			reg = <0x07b60000 0x1000>;
+			status = "disabled";
 
 			clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
 			clock-names = "apb_pclk", "atclk";
@@ -1343,9 +1359,10 @@
 			};
 		};
 
-		funnel@7b70000 {
+		funnel5: funnel@7b70000 {
 			compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
 			reg = <0x07b70000 0x1000>;
+			status = "disabled";
 
 			clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
 			clock-names = "apb_pclk", "atclk";
@@ -1369,66 +1386,78 @@
 			};
 		};
 
-		etm@7c40000 {
+		etm5: etm@7c40000 {
 			compatible = "arm,coresight-etm4x", "arm,primecell";
 			reg = <0x07c40000 0x1000>;
+			status = "disabled";
 
 			clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
 			clock-names = "apb_pclk", "atclk";
 
 			cpu = <&CPU4>;
 
-			port{
-				etm4_out: endpoint {
-					remote-endpoint = <&apss_funnel_in4>;
+			out-ports {
+				port{
+					etm4_out: endpoint {
+						remote-endpoint = <&apss_funnel_in4>;
+					};
 				};
 			};
 		};
 
-		etm@7d40000 {
+		etm6: etm@7d40000 {
 			compatible = "arm,coresight-etm4x", "arm,primecell";
 			reg = <0x07d40000 0x1000>;
+			status = "disabled";
 
 			clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
 			clock-names = "apb_pclk", "atclk";
 
 			cpu = <&CPU5>;
 
-			port{
-				etm5_out: endpoint {
-					remote-endpoint = <&apss_funnel_in5>;
+			out-ports {
+				port{
+					etm5_out: endpoint {
+						remote-endpoint = <&apss_funnel_in5>;
+					};
 				};
 			};
 		};
 
-		etm@7e40000 {
+		etm7: etm@7e40000 {
 			compatible = "arm,coresight-etm4x", "arm,primecell";
 			reg = <0x07e40000 0x1000>;
+			status = "disabled";
 
 			clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
 			clock-names = "apb_pclk", "atclk";
 
 			cpu = <&CPU6>;
 
-			port{
-				etm6_out: endpoint {
-					remote-endpoint = <&apss_funnel_in6>;
+			out-ports {
+				port{
+					etm6_out: endpoint {
+						remote-endpoint = <&apss_funnel_in6>;
+					};
 				};
 			};
 		};
 
-		etm@7f40000 {
+		etm8: etm@7f40000 {
 			compatible = "arm,coresight-etm4x", "arm,primecell";
 			reg = <0x07f40000 0x1000>;
+			status = "disabled";
 
 			clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
 			clock-names = "apb_pclk", "atclk";
 
 			cpu = <&CPU7>;
 
-			port{
-				etm7_out: endpoint {
-					remote-endpoint = <&apss_funnel_in7>;
+			out-ports {
+				port{
+					etm7_out: endpoint {
+						remote-endpoint = <&apss_funnel_in7>;
+					};
 				};
 			};
 		};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/qcom/pm8150.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/qcom/pm8150.dtsi
@@ -17,7 +17,7 @@
 		#size-cells = <0>;
 
 		pon: power-on@800 {
-			compatible = "qcom,pm8916-pon";
+			compatible = "qcom,pm8998-pon";
 			reg = <0x0800>;
 			pwrkey {
 				compatible = "qcom,pm8941-pwrkey";
@@ -73,18 +73,8 @@
 			reg = <0xc000>;
 			gpio-controller;
 			#gpio-cells = <2>;
-			interrupts = <0x0 0xc0 0x0 IRQ_TYPE_NONE>,
-				     <0x0 0xc1 0x0 IRQ_TYPE_NONE>,
-				     <0x0 0xc2 0x0 IRQ_TYPE_NONE>,
-				     <0x0 0xc3 0x0 IRQ_TYPE_NONE>,
-				     <0x0 0xc4 0x0 IRQ_TYPE_NONE>,
-				     <0x0 0xc5 0x0 IRQ_TYPE_NONE>,
-				     <0x0 0xc6 0x0 IRQ_TYPE_NONE>,
-				     <0x0 0xc7 0x0 IRQ_TYPE_NONE>,
-				     <0x0 0xc8 0x0 IRQ_TYPE_NONE>,
-				     <0x0 0xc9 0x0 IRQ_TYPE_NONE>,
-				     <0x0 0xca 0x0 IRQ_TYPE_NONE>,
-				     <0x0 0xcb 0x0 IRQ_TYPE_NONE>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
 		};
 	};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/qcom/pm8150b.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/qcom/pm8150b.dtsi
@@ -62,18 +62,8 @@
 			reg = <0xc000>;
 			gpio-controller;
 			#gpio-cells = <2>;
-			interrupts = <0x2 0xc0 0x0 IRQ_TYPE_NONE>,
-				     <0x2 0xc1 0x0 IRQ_TYPE_NONE>,
-				     <0x2 0xc2 0x0 IRQ_TYPE_NONE>,
-				     <0x2 0xc3 0x0 IRQ_TYPE_NONE>,
-				     <0x2 0xc4 0x0 IRQ_TYPE_NONE>,
-				     <0x2 0xc5 0x0 IRQ_TYPE_NONE>,
-				     <0x2 0xc6 0x0 IRQ_TYPE_NONE>,
-				     <0x2 0xc7 0x0 IRQ_TYPE_NONE>,
-				     <0x2 0xc8 0x0 IRQ_TYPE_NONE>,
-				     <0x2 0xc9 0x0 IRQ_TYPE_NONE>,
-				     <0x2 0xca 0x0 IRQ_TYPE_NONE>,
-				     <0x2 0xcb 0x0 IRQ_TYPE_NONE>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
 		};
 	};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/qcom/pm8150l.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/qcom/pm8150l.dtsi
@@ -56,18 +56,8 @@
 			reg = <0xc000>;
 			gpio-controller;
 			#gpio-cells = <2>;
-			interrupts = <0x4 0xc0 0x0 IRQ_TYPE_NONE>,
-				     <0x4 0xc1 0x0 IRQ_TYPE_NONE>,
-				     <0x4 0xc2 0x0 IRQ_TYPE_NONE>,
-				     <0x4 0xc3 0x0 IRQ_TYPE_NONE>,
-				     <0x4 0xc4 0x0 IRQ_TYPE_NONE>,
-				     <0x4 0xc5 0x0 IRQ_TYPE_NONE>,
-				     <0x4 0xc6 0x0 IRQ_TYPE_NONE>,
-				     <0x4 0xc7 0x0 IRQ_TYPE_NONE>,
-				     <0x4 0xc8 0x0 IRQ_TYPE_NONE>,
-				     <0x4 0xc9 0x0 IRQ_TYPE_NONE>,
-				     <0x4 0xca 0x0 IRQ_TYPE_NONE>,
-				     <0x4 0xcb 0x0 IRQ_TYPE_NONE>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
 		};
 	};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/qcom/pm8916.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/qcom/pm8916.dtsi
@@ -113,7 +113,7 @@
 
 		wcd_codec: codec@f000 {
 			compatible = "qcom,pm8916-wcd-analog-codec";
-			reg = <0xf000 0x200>;
+			reg = <0xf000>;
 			reg-names = "pmic-codec-core";
 			clocks = <&gcc GCC_CODEC_DIGCODEC_CLK>;
 			clock-names = "mclk";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/qcom/qcs404-evb.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/qcom/qcs404-evb.dtsi
@@ -43,7 +43,7 @@
 		vddrf-supply = <&vreg_l1_1p3>;
 		vddch0-supply = <&vdd_ch0_3p3>;
 
-		local-bd-address = [ 02 00 00 00 5a ad ];
+		local-bd-address = [ 00 00 00 00 00 00 ];
 
 		max-speed = <3200000>;
 	};
@@ -73,6 +73,7 @@
 		regulator-always-on;
 		regulator-boot-on;
 		regulator-name = "vdd_apc";
+		regulator-initial-mode = <1>;
 		regulator-min-microvolt = <1048000>;
 		regulator-max-microvolt = <1384000>;
 	};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/qcom/qcs404.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/qcom/qcs404.dtsi
@@ -533,7 +533,7 @@
 
 			clocks = <&gcc GCC_PCIE_0_PIPE_CLK>;
 			resets = <&gcc GCC_PCIEPHY_0_PHY_BCR>,
-				 <&gcc 21>;
+				 <&gcc GCC_PCIE_0_PIPE_ARES>;
 			reset-names = "phy", "pipe";
 
 			clock-output-names = "pcie_0_pipe_clk";
@@ -991,12 +991,12 @@
 				 <&gcc GCC_PCIE_0_SLV_AXI_CLK>;
 			clock-names = "iface", "aux", "master_bus", "slave_bus";
 
-			resets = <&gcc 18>,
-				 <&gcc 17>,
-				 <&gcc 15>,
-				 <&gcc 19>,
+			resets = <&gcc GCC_PCIE_0_AXI_MASTER_ARES>,
+				 <&gcc GCC_PCIE_0_AXI_SLAVE_ARES>,
+				 <&gcc GCC_PCIE_0_AXI_MASTER_STICKY_ARES>,
+				 <&gcc GCC_PCIE_0_CORE_STICKY_ARES>,
 				 <&gcc GCC_PCIE_0_BCR>,
-				 <&gcc 16>;
+				 <&gcc GCC_PCIE_0_AHB_ARES>;
 			reset-names = "axi_m",
 				      "axi_s",
 				      "axi_m_sticky",
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi
@@ -165,6 +165,8 @@
 /delete-node/ &venus_mem;
 /delete-node/ &cdsp_mem;
 /delete-node/ &cdsp_pas;
+/delete-node/ &zap_shader;
+/delete-node/ &gpu_mem;
 
 /* Increase the size from 120 MB to 128 MB */
 &mpss_region {
@@ -1308,7 +1310,7 @@
 		config {
 			pins = "gpio126";
 			function = "gpio";
-			bias-no-pull;
+			bias-disable;
 			drive-strength = <2>;
 			output-low;
 		};
@@ -1318,7 +1320,7 @@
 		config {
 			pins = "gpio126";
 			function = "gpio";
-			bias-no-pull;
+			bias-disable;
 			drive-strength = <2>;
 			output-high;
 		};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/qcom/sdm845-db845c.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/qcom/sdm845-db845c.dts
@@ -53,8 +53,8 @@
 		user4 {
 			label = "green:user4";
 			gpios = <&pm8998_gpio 13 GPIO_ACTIVE_HIGH>;
-			linux,default-trigger = "panic-indicator";
 			default-state = "off";
+			panic-indicator;
 		};
 
 		wlan {
@@ -337,7 +337,9 @@
 &gcc {
 	protected-clocks = <GCC_QSPI_CORE_CLK>,
 			   <GCC_QSPI_CORE_CLK_SRC>,
-			   <GCC_QSPI_CNOC_PERIPH_AHB_CLK>;
+			   <GCC_QSPI_CNOC_PERIPH_AHB_CLK>,
+			   <GCC_LPASS_Q6_AXI_CLK>,
+			   <GCC_LPASS_SWAY_CLK>;
 };
 
 &pm8998_gpio {
@@ -517,6 +519,8 @@
 	vdd-1.8-xo-supply = <&vreg_l7a_1p8>;
 	vdd-1.3-rfa-supply = <&vreg_l17a_1p3>;
 	vdd-3.3-ch0-supply = <&vreg_l25a_3p3>;
+
+	qcom,snoc-host-cap-8bit-quirk;
 };
 
 /* PINCTRL - additions to nodes defined in sdm845.dtsi */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/qcom/sdm845-mtp.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/qcom/sdm845-mtp.dts
@@ -468,6 +468,8 @@
 	vdd-1.8-xo-supply = <&vreg_l7a_1p8>;
 	vdd-1.3-rfa-supply = <&vreg_l17a_1p3>;
 	vdd-3.3-ch0-supply = <&vreg_l25a_3p3>;
+
+	qcom,snoc-host-cap-8bit-quirk;
 };
 
 /* PINCTRL - additions to nodes defined in sdm845.dtsi */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -715,6 +715,7 @@
 			#clock-cells = <1>;
 			#reset-cells = <1>;
 			#power-domain-cells = <1>;
+			power-domains = <&rpmhpd SDM845_CX>;
 		};
 
 		qfprom@784000 {
@@ -1419,6 +1420,8 @@
 			clocks = <&gcc GCC_UFS_MEM_CLKREF_CLK>,
 				 <&gcc GCC_UFS_PHY_PHY_AUX_CLK>;
 
+			power-domains = <&gcc UFS_PHY_GDSC>;
+
 			resets = <&ufs_mem_hc 0>;
 			reset-names = "ufsphy";
 			status = "disabled";
@@ -2500,10 +2503,10 @@
 					  <&gcc GCC_USB30_PRIM_MASTER_CLK>;
 			assigned-clock-rates = <19200000>, <150000000>;
 
-			interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 486 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 488 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 489 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts-extended = <&intc GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>,
+					      <&intc GIC_SPI 486 IRQ_TYPE_LEVEL_HIGH>,
+					      <&pdc_intc 8 IRQ_TYPE_EDGE_BOTH>,
+					      <&pdc_intc 9 IRQ_TYPE_EDGE_BOTH>;
 			interrupt-names = "hs_phy_irq", "ss_phy_irq",
 					  "dm_hs_phy_irq", "dp_hs_phy_irq";
 
@@ -2544,10 +2547,10 @@
 					  <&gcc GCC_USB30_SEC_MASTER_CLK>;
 			assigned-clock-rates = <19200000>, <150000000>;
 
-			interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 487 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 490 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 491 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts-extended = <&intc GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>,
+					      <&intc GIC_SPI 487 IRQ_TYPE_LEVEL_HIGH>,
+					      <&pdc_intc 10 IRQ_TYPE_EDGE_BOTH>,
+					      <&pdc_intc 11 IRQ_TYPE_EDGE_BOTH>;
 			interrupt-names = "hs_phy_irq", "ss_phy_irq",
 					  "dm_hs_phy_irq", "dp_hs_phy_irq";
 
@@ -2824,7 +2827,7 @@
 
 			qcom,gmu = <&gmu>;
 
-			zap-shader {
+			zap_shader: zap-shader {
 				memory-region = <&gpu_mem>;
 			};
 
@@ -2939,6 +2942,15 @@
 			#power-domain-cells = <1>;
 		};
 
+		pdc_intc: interrupt-controller@b220000 {
+			compatible = "qcom,sdm845-pdc", "qcom,pdc";
+			reg = <0 0x0b220000 0 0x30000>;
+			qcom,pdc-ranges = <0 480 94>, <94 609 15>, <115 630 7>;
+			#interrupt-cells = <2>;
+			interrupt-parent = <&intc>;
+			interrupt-controller;
+		};
+
 		pdc_reset: reset-controller@b2e0000 {
 			compatible = "qcom,sdm845-pdc-global";
 			reg = <0 0x0b2e0000 0 0x20000>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts
@@ -232,7 +232,9 @@
 &gcc {
 	protected-clocks = <GCC_QSPI_CORE_CLK>,
 			   <GCC_QSPI_CORE_CLK_SRC>,
-			   <GCC_QSPI_CNOC_PERIPH_AHB_CLK>;
+			   <GCC_QSPI_CNOC_PERIPH_AHB_CLK>,
+			   <GCC_LPASS_Q6_AXI_CLK>,
+			   <GCC_LPASS_SWAY_CLK>;
 };
 
 &i2c1 {
@@ -243,24 +245,23 @@
 &i2c3 {
 	status = "okay";
 	clock-frequency = <400000>;
+	/* Overwrite pinctrl-0 from sdm845.dtsi */
+	pinctrl-0 = <&qup_i2c3_default &i2c3_hid_active>;
 
-	hid@15 {
+	tsel: hid@15 {
 		compatible = "hid-over-i2c";
 		reg = <0x15>;
 		hid-descr-addr = <0x1>;
 
-		interrupts-extended = <&tlmm 37 IRQ_TYPE_EDGE_RISING>;
+		interrupts-extended = <&tlmm 37 IRQ_TYPE_LEVEL_HIGH>;
 	};
 
-	hid@2c {
+	tsc2: hid@2c {
 		compatible = "hid-over-i2c";
 		reg = <0x2c>;
 		hid-descr-addr = <0x20>;
 
-		interrupts-extended = <&tlmm 37 IRQ_TYPE_EDGE_RISING>;
-
-		pinctrl-names = "default";
-		pinctrl-0 = <&i2c2_hid_active>;
+		interrupts-extended = <&tlmm 37 IRQ_TYPE_LEVEL_HIGH>;
 	};
 };
 
@@ -268,15 +269,15 @@
 	status = "okay";
 	clock-frequency = <400000>;
 
-	hid@10 {
+	tsc1: hid@10 {
 		compatible = "hid-over-i2c";
 		reg = <0x10>;
 		hid-descr-addr = <0x1>;
 
-		interrupts-extended = <&tlmm 125 IRQ_TYPE_EDGE_FALLING>;
+		interrupts-extended = <&tlmm 125 IRQ_TYPE_LEVEL_LOW>;
 
 		pinctrl-names = "default";
-		pinctrl-0 = <&i2c6_hid_active>;
+		pinctrl-0 = <&i2c5_hid_active>;
 	};
 };
 
@@ -284,7 +285,7 @@
 	status = "okay";
 	clock-frequency = <400000>;
 
-	hid@5c {
+	ecsh: hid@5c {
 		compatible = "hid-over-i2c";
 		reg = <0x5c>;
 		hid-descr-addr = <0x1>;
@@ -292,13 +293,15 @@
 		interrupts-extended = <&tlmm 92 IRQ_TYPE_LEVEL_LOW>;
 
 		pinctrl-names = "default";
-		pinctrl-0 = <&i2c12_hid_active>;
+		pinctrl-0 = <&i2c11_hid_active>;
 	};
 };
 
 &qup_i2c12_default {
-	drive-strength = <2>;
-	bias-disable;
+	pinmux {
+		drive-strength = <2>;
+		bias-disable;
+	};
 };
 
 &qup_uart6_default {
@@ -335,7 +338,7 @@
 &tlmm {
 	gpio-reserved-ranges = <0 4>, <81 4>;
 
-	i2c2_hid_active: i2c2-hid-active {
+	i2c3_hid_active: i2c2-hid-active {
 		pins = <37>;
 		function = "gpio";
 
@@ -344,7 +347,7 @@
 		drive-strength = <2>;
 	};
 
-	i2c6_hid_active: i2c6-hid-active {
+	i2c5_hid_active: i2c5-hid-active {
 		pins = <125>;
 		function = "gpio";
 
@@ -353,7 +356,7 @@
 		drive-strength = <2>;
 	};
 
-	i2c12_hid_active: i2c12-hid-active {
+	i2c11_hid_active: i2c11-hid-active {
 		pins = <92>;
 		function = "gpio";
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/qcom/sm8150.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/qcom/sm8150.dtsi
@@ -336,7 +336,7 @@
 			      <0x0 0x03D00000 0x0 0x300000>;
 			reg-names = "west", "east", "north", "south";
 			interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
-			gpio-ranges = <&tlmm 0 0 175>;
+			gpio-ranges = <&tlmm 0 0 176>;
 			gpio-controller;
 			#gpio-cells = <2>;
 			interrupt-controller;
@@ -459,9 +459,9 @@
 			qcom,tcs-offset = <0xd00>;
 			qcom,drv-id = <2>;
 			qcom,tcs-config = <ACTIVE_TCS  2>,
-					  <SLEEP_TCS   1>,
-					  <WAKE_TCS    1>,
-					  <CONTROL_TCS 0>;
+					  <SLEEP_TCS   3>,
+					  <WAKE_TCS    3>,
+					  <CONTROL_TCS 1>;
 
 			rpmhcc: clock-controller {
 				compatible = "qcom,sm8150-rpmh-clk";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/renesas/cat875.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/renesas/cat875.dtsi
@@ -22,7 +22,6 @@
 	status = "okay";
 
 	phy0: ethernet-phy@0 {
-		rxc-skew-ps = <1500>;
 		reg = <0>;
 		interrupt-parent = <&gpio2>;
 		interrupts = <21 IRQ_TYPE_LEVEL_LOW>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/renesas/hihope-common.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/renesas/hihope-common.dtsi
@@ -86,7 +86,7 @@
 
 		label = "rcar-sound";
 
-		dais = <&rsnd_port0>;
+		dais = <&rsnd_port>;
 	};
 
 	vbus0_usb2: regulator-vbus0-usb2 {
@@ -191,7 +191,7 @@
 		port@2 {
 			reg = <2>;
 			dw_hdmi0_snd_in: endpoint {
-				remote-endpoint = <&rsnd_endpoint0>;
+				remote-endpoint = <&rsnd_endpoint>;
 			};
 		};
 	};
@@ -327,17 +327,15 @@
 	/* Single DAI */
 	#sound-dai-cells = <0>;
 
-	ports {
-		rsnd_port0: port@0 {
-			rsnd_endpoint0: endpoint {
-				remote-endpoint = <&dw_hdmi0_snd_in>;
-
-				dai-format = "i2s";
-				bitclock-master = <&rsnd_endpoint0>;
-				frame-master = <&rsnd_endpoint0>;
+	rsnd_port: port {
+		rsnd_endpoint: endpoint {
+			remote-endpoint = <&dw_hdmi0_snd_in>;
+
+			dai-format = "i2s";
+			bitclock-master = <&rsnd_endpoint>;
+			frame-master = <&rsnd_endpoint>;
 
-				playback = <&ssi2>;
-			};
+			playback = <&ssi2>;
 		};
 	};
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/renesas/hihope-rzg2-ex.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/renesas/hihope-rzg2-ex.dtsi
@@ -23,7 +23,6 @@
 	status = "okay";
 
 	phy0: ethernet-phy@0 {
-		rxc-skew-ps = <1500>;
 		reg = <0>;
 		interrupt-parent = <&gpio2>;
 		interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/renesas/r8a774a1.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/renesas/r8a774a1.dtsi
@@ -1726,17 +1726,6 @@
 				      "ssi.1", "ssi.0";
 			status = "disabled";
 
-			ports {
-				#address-cells = <1>;
-				#size-cells = <0>;
-				port@0 {
-					reg = <0>;
-				};
-				port@1 {
-					reg = <1>;
-				};
-			};
-
 			rcar_sound,ctu {
 				ctu00: ctu-0 { };
 				ctu01: ctu-1 { };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/renesas/r8a774c0.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/renesas/r8a774c0.dtsi
@@ -49,17 +49,14 @@
 		opp-shared;
 		opp-800000000 {
 			opp-hz = /bits/ 64 <800000000>;
-			opp-microvolt = <820000>;
 			clock-latency-ns = <300000>;
 		};
 		opp-1000000000 {
 			opp-hz = /bits/ 64 <1000000000>;
-			opp-microvolt = <820000>;
 			clock-latency-ns = <300000>;
 		};
 		opp-1200000000 {
 			opp-hz = /bits/ 64 <1200000000>;
-			opp-microvolt = <820000>;
 			clock-latency-ns = <300000>;
 			opp-suspend;
 		};
@@ -1212,9 +1209,8 @@
 			reg = <0 0xe6ea0000 0 0x0064>;
 			interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cpg CPG_MOD 210>;
-			dmas = <&dmac1 0x43>, <&dmac1 0x42>,
-			       <&dmac2 0x43>, <&dmac2 0x42>;
-			dma-names = "tx", "rx", "tx", "rx";
+			dmas = <&dmac0 0x43>, <&dmac0 0x42>;
+			dma-names = "tx", "rx";
 			power-domains = <&sysc R8A774C0_PD_ALWAYS_ON>;
 			resets = <&cpg 210>;
 			#address-cells = <1>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts
@@ -59,7 +59,7 @@
 	memory@48000000 {
 		device_type = "memory";
 		/* first 128MB is reserved for secure area. */
-		reg = <0x0 0x48000000 0x0 0x38000000>;
+		reg = <0x0 0x48000000 0x0 0x78000000>;
 	};
 
 	osc5_clk: osc5-clock {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/renesas/r8a77970.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/renesas/r8a77970.dtsi
@@ -652,7 +652,7 @@
 		};
 
 		pwm3: pwm@e6e33000 {
-			compatible = "renesas,pwm-r8a7790", "renesas,pwm-rcar";
+			compatible = "renesas,pwm-r8a77970", "renesas,pwm-rcar";
 			reg = <0 0xe6e33000 0 8>;
 			#pwm-cells = <2>;
 			clocks = <&cpg CPG_MOD 523>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/renesas/r8a77980.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/renesas/r8a77980.dtsi
@@ -990,8 +990,8 @@
 
 					reg = <1>;
 
-					vin4csi41: endpoint@2 {
-						reg = <2>;
+					vin4csi41: endpoint@3 {
+						reg = <3>;
 						remote-endpoint = <&csi41vin4>;
 					};
 				};
@@ -1018,8 +1018,8 @@
 
 					reg = <1>;
 
-					vin5csi41: endpoint@2 {
-						reg = <2>;
+					vin5csi41: endpoint@3 {
+						reg = <3>;
 						remote-endpoint = <&csi41vin5>;
 					};
 				};
@@ -1046,8 +1046,8 @@
 
 					reg = <1>;
 
-					vin6csi41: endpoint@2 {
-						reg = <2>;
+					vin6csi41: endpoint@3 {
+						reg = <3>;
 						remote-endpoint = <&csi41vin6>;
 					};
 				};
@@ -1074,8 +1074,8 @@
 
 					reg = <1>;
 
-					vin7csi41: endpoint@2 {
-						reg = <2>;
+					vin7csi41: endpoint@3 {
+						reg = <3>;
 						remote-endpoint = <&csi41vin7>;
 					};
 				};
@@ -1318,6 +1318,7 @@
 		ipmmu_vip0: mmu@e7b00000 {
 			compatible = "renesas,ipmmu-r8a77980";
 			reg = <0 0xe7b00000 0 0x1000>;
+			renesas,ipmmu-main = <&ipmmu_mm 4>;
 			power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
 			#iommu-cells = <1>;
 		};
@@ -1325,6 +1326,7 @@
 		ipmmu_vip1: mmu@e7960000 {
 			compatible = "renesas,ipmmu-r8a77980";
 			reg = <0 0xe7960000 0 0x1000>;
+			renesas,ipmmu-main = <&ipmmu_mm 11>;
 			power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
 			#iommu-cells = <1>;
 		};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
@@ -636,7 +636,6 @@
 	/* audio_clkout0/1/2/3 */
 	#clock-cells = <1>;
 	clock-frequency = <12288000 11289600>;
-	clkout-lr-synchronous;
 
 	status = "okay";
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/renesas/r8a77990.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/renesas/r8a77990.dtsi
@@ -60,17 +60,14 @@
 		opp-shared;
 		opp-800000000 {
 			opp-hz = /bits/ 64 <800000000>;
-			opp-microvolt = <820000>;
 			clock-latency-ns = <300000>;
 		};
 		opp-1000000000 {
 			opp-hz = /bits/ 64 <1000000000>;
-			opp-microvolt = <820000>;
 			clock-latency-ns = <300000>;
 		};
 		opp-1200000000 {
 			opp-hz = /bits/ 64 <1200000000>;
-			opp-microvolt = <820000>;
 			clock-latency-ns = <300000>;
 			opp-suspend;
 		};
@@ -1168,9 +1165,8 @@
 			reg = <0 0xe6ea0000 0 0x0064>;
 			interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&cpg CPG_MOD 210>;
-			dmas = <&dmac1 0x43>, <&dmac1 0x42>,
-			       <&dmac2 0x43>, <&dmac2 0x42>;
-			dma-names = "tx", "rx", "tx", "rx";
+			dmas = <&dmac0 0x43>, <&dmac0 0x42>;
+			dma-names = "tx", "rx";
 			power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
 			resets = <&cpg 210>;
 			#address-cells = <1>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/renesas/r8a77995-draak.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/renesas/r8a77995-draak.dts
@@ -277,10 +277,6 @@
 		interrupt-parent = <&gpio1>;
 		interrupts = <28 IRQ_TYPE_LEVEL_LOW>;
 
-		/* Depends on LVDS */
-		max-clock = <135000000>;
-		min-vrefresh = <50>;
-
 		adi,input-depth = <8>;
 		adi,input-colorspace = "rgb";
 		adi,input-clock = "1x";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/renesas/ulcb-kf.dtsi
@@ -269,7 +269,7 @@
 	};
 
 	scif1_pins: scif1 {
-		groups = "scif1_data_b", "scif1_ctrl";
+		groups = "scif1_data_b";
 		function = "scif1";
 	};
 
@@ -329,7 +329,6 @@
 &scif1 {
 	pinctrl-0 = <&scif1_pins>;
 	pinctrl-names = "default";
-	uart-has-rtscts;
 
 	status = "okay";
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/renesas/ulcb.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/renesas/ulcb.dtsi
@@ -470,6 +470,7 @@
 	mmc-hs200-1_8v;
 	mmc-hs400-1_8v;
 	non-removable;
+	full-pwr-cycle-in-suspend;
 	status = "okay";
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/rockchip/px30.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/rockchip/px30.dtsi
@@ -213,28 +213,31 @@
 			#size-cells = <0>;
 
 			/* These power domains are grouped by VD_LOGIC */
-			pd_usb@PX30_PD_USB {
+			power-domain@PX30_PD_USB {
 				reg = <PX30_PD_USB>;
 				clocks = <&cru HCLK_HOST>,
 					 <&cru HCLK_OTG>,
 					 <&cru SCLK_OTG_ADP>;
 				pm_qos = <&qos_usb_host>, <&qos_usb_otg>;
+				#power-domain-cells = <0>;
 			};
-			pd_sdcard@PX30_PD_SDCARD {
+			power-domain@PX30_PD_SDCARD {
 				reg = <PX30_PD_SDCARD>;
 				clocks = <&cru HCLK_SDMMC>,
 					 <&cru SCLK_SDMMC>;
 				pm_qos = <&qos_sdmmc>;
+				#power-domain-cells = <0>;
 			};
-			pd_gmac@PX30_PD_GMAC {
+			power-domain@PX30_PD_GMAC {
 				reg = <PX30_PD_GMAC>;
 				clocks = <&cru ACLK_GMAC>,
 					 <&cru PCLK_GMAC>,
 					 <&cru SCLK_MAC_REF>,
 					 <&cru SCLK_GMAC_RX_TX>;
 				pm_qos = <&qos_gmac>;
+				#power-domain-cells = <0>;
 			};
-			pd_mmc_nand@PX30_PD_MMC_NAND {
+			power-domain@PX30_PD_MMC_NAND {
 				reg = <PX30_PD_MMC_NAND>;
 				clocks =  <&cru HCLK_NANDC>,
 					  <&cru HCLK_EMMC>,
@@ -246,15 +249,17 @@
 					  <&cru SCLK_SFC>;
 				pm_qos = <&qos_emmc>, <&qos_nand>,
 					 <&qos_sdio>, <&qos_sfc>;
+				#power-domain-cells = <0>;
 			};
-			pd_vpu@PX30_PD_VPU {
+			power-domain@PX30_PD_VPU {
 				reg = <PX30_PD_VPU>;
 				clocks = <&cru ACLK_VPU>,
 					 <&cru HCLK_VPU>,
 					 <&cru SCLK_CORE_VPU>;
 				pm_qos = <&qos_vpu>, <&qos_vpu_r128>;
+				#power-domain-cells = <0>;
 			};
-			pd_vo@PX30_PD_VO {
+			power-domain@PX30_PD_VO {
 				reg = <PX30_PD_VO>;
 				clocks = <&cru ACLK_RGA>,
 					 <&cru ACLK_VOPB>,
@@ -269,8 +274,9 @@
 					 <&cru SCLK_VOPB_PWM>;
 				pm_qos = <&qos_rga_rd>, <&qos_rga_wr>,
 					 <&qos_vop_m0>, <&qos_vop_m1>;
+				#power-domain-cells = <0>;
 			};
-			pd_vi@PX30_PD_VI {
+			power-domain@PX30_PD_VI {
 				reg = <PX30_PD_VI>;
 				clocks = <&cru ACLK_CIF>,
 					 <&cru ACLK_ISP>,
@@ -280,11 +286,13 @@
 				pm_qos = <&qos_isp_128>, <&qos_isp_rd>,
 					 <&qos_isp_wr>, <&qos_isp_m1>,
 					 <&qos_vip>;
+				#power-domain-cells = <0>;
 			};
-			pd_gpu@PX30_PD_GPU {
+			power-domain@PX30_PD_GPU {
 				reg = <PX30_PD_GPU>;
 				clocks = <&cru SCLK_GPU>;
 				pm_qos = <&qos_gpu>;
+				#power-domain-cells = <0>;
 			};
 		};
 	};
@@ -768,7 +776,7 @@
 		interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>,
 			 <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
-		clock-names = "biu", "ciu", "ciu-drv", "ciu-sample";
+		clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
 		fifo-depth = <0x100>;
 		max-frequency = <150000000>;
 		pinctrl-names = "default";
@@ -783,7 +791,7 @@
 		interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&cru HCLK_SDIO>, <&cru SCLK_SDIO>,
 			 <&cru SCLK_SDIO_DRV>, <&cru SCLK_SDIO_SAMPLE>;
-		clock-names = "biu", "ciu", "ciu-drv", "ciu-sample";
+		clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
 		fifo-depth = <0x100>;
 		max-frequency = <150000000>;
 		pinctrl-names = "default";
@@ -798,7 +806,7 @@
 		interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>,
 			 <&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>;
-		clock-names = "biu", "ciu", "ciu-drv", "ciu-sample";
+		clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
 		fifo-depth = <0x100>;
 		max-frequency = <150000000>;
 		power-domains = <&power PX30_PD_MMC_NAND>;
@@ -860,7 +868,7 @@
 	vopl_mmu: iommu@ff470f00 {
 		compatible = "rockchip,iommu";
 		reg = <0x0 0xff470f00 0x0 0x100>;
-		interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "vopl_mmu";
 		clocks = <&cru ACLK_VOPL>, <&cru HCLK_VOPL>;
 		clock-names = "aclk", "hclk";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/rockchip/rk3328-evb.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/rockchip/rk3328-evb.dts
@@ -86,13 +86,13 @@
 	assigned-clock-rate = <50000000>;
 	assigned-clocks = <&cru SCLK_MAC2PHY>;
 	assigned-clock-parents = <&cru SCLK_MAC2PHY_SRC>;
-
+	status = "okay";
 };
 
 &i2c1 {
 	status = "okay";
 
-	rk805: rk805@18 {
+	rk805: pmic@18 {
 		compatible = "rockchip,rk805";
 		reg = <0x18>;
 		interrupt-parent = <&gpio2>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts
@@ -90,7 +90,6 @@
 			linux,default-trigger = "heartbeat";
 			gpios = <&rk805 1 GPIO_ACTIVE_LOW>;
 			default-state = "on";
-			mode = <0x23>;
 		};
 
 		user {
@@ -98,7 +97,6 @@
 			linux,default-trigger = "mmc1";
 			gpios = <&rk805 0 GPIO_ACTIVE_LOW>;
 			default-state = "off";
-			mode = <0x05>;
 		};
 	};
 };
@@ -333,6 +331,7 @@
 };
 
 &usb20_otg {
+	dr_mode = "host";
 	status = "okay";
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts
@@ -169,7 +169,7 @@
 &i2c1 {
 	status = "okay";
 
-	rk805: rk805@18 {
+	rk805: pmic@18 {
 		compatible = "rockchip,rk805";
 		reg = <0x18>;
 		interrupt-parent = <&gpio2>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/rockchip/rk3328.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/rockchip/rk3328.dtsi
@@ -270,15 +270,19 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 
-			pd_hevc@RK3328_PD_HEVC {
+			power-domain@RK3328_PD_HEVC {
 				reg = <RK3328_PD_HEVC>;
+				clocks = <&cru SCLK_VENC_CORE>;
+				#power-domain-cells = <0>;
 			};
-			pd_video@RK3328_PD_VIDEO {
+			power-domain@RK3328_PD_VIDEO {
 				reg = <RK3328_PD_VIDEO>;
+				#power-domain-cells = <0>;
 			};
-			pd_vpu@RK3328_PD_VPU {
+			power-domain@RK3328_PD_VPU {
 				reg = <RK3328_PD_VPU>;
 				clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>;
+				#power-domain-cells = <0>;
 			};
 		};
 
@@ -555,7 +559,7 @@
 
 	gpu: gpu@ff300000 {
 		compatible = "rockchip,rk3328-mali", "arm,mali-450";
-		reg = <0x0 0xff300000 0x0 0x40000>;
+		reg = <0x0 0xff300000 0x0 0x30000>;
 		interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>,
 			     <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>,
 			     <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>,
@@ -667,8 +671,7 @@
 		compatible = "rockchip,rk3328-dw-hdmi";
 		reg = <0x0 0xff3c0000 0x0 0x20000>;
 		reg-io-width = <4>;
-		interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>,
-			     <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+		interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&cru PCLK_HDMI>,
 			 <&cru SCLK_HDMI_SFC>,
 			 <&cru SCLK_RTC32K>;
@@ -684,11 +687,20 @@
 		status = "disabled";
 
 		ports {
-			hdmi_in: port {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			hdmi_in: port@0 {
+				reg = <0>;
+
 				hdmi_in_vop: endpoint {
 					remote-endpoint = <&vop_out_hdmi>;
 				};
 			};
+
+			hdmi_out: port@1 {
+				reg = <1>;
+			};
 		};
 	};
 
@@ -754,8 +766,8 @@
 			<0>, <24000000>,
 			<24000000>, <24000000>,
 			<15000000>, <15000000>,
-			<100000000>, <100000000>,
-			<100000000>, <100000000>,
+			<300000000>, <100000000>,
+			<400000000>, <100000000>,
 			<50000000>, <100000000>,
 			<100000000>, <100000000>,
 			<50000000>, <50000000>,
@@ -1190,8 +1202,8 @@
 
 		uart0 {
 			uart0_xfer: uart0-xfer {
-				rockchip,pins = <1 RK_PB1 1 &pcfg_pull_up>,
-						<1 RK_PB0 1 &pcfg_pull_none>;
+				rockchip,pins = <1 RK_PB1 1 &pcfg_pull_none>,
+						<1 RK_PB0 1 &pcfg_pull_up>;
 			};
 
 			uart0_cts: uart0-cts {
@@ -1209,8 +1221,8 @@
 
 		uart1 {
 			uart1_xfer: uart1-xfer {
-				rockchip,pins = <3 RK_PA4 4 &pcfg_pull_up>,
-						<3 RK_PA6 4 &pcfg_pull_none>;
+				rockchip,pins = <3 RK_PA4 4 &pcfg_pull_none>,
+						<3 RK_PA6 4 &pcfg_pull_up>;
 			};
 
 			uart1_cts: uart1-cts {
@@ -1228,15 +1240,15 @@
 
 		uart2-0 {
 			uart2m0_xfer: uart2m0-xfer {
-				rockchip,pins = <1 RK_PA0 2 &pcfg_pull_up>,
-						<1 RK_PA1 2 &pcfg_pull_none>;
+				rockchip,pins = <1 RK_PA0 2 &pcfg_pull_none>,
+						<1 RK_PA1 2 &pcfg_pull_up>;
 			};
 		};
 
 		uart2-1 {
 			uart2m1_xfer: uart2m1-xfer {
-				rockchip,pins = <2 RK_PA0 1 &pcfg_pull_up>,
-						<2 RK_PA1 1 &pcfg_pull_none>;
+				rockchip,pins = <2 RK_PA0 1 &pcfg_pull_none>,
+						<2 RK_PA1 1 &pcfg_pull_up>;
 			};
 		};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/rockchip/rk3368-lion.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/rockchip/rk3368-lion.dtsi
@@ -56,7 +56,6 @@
 			fan: fan@18 {
 				compatible = "ti,amc6821";
 				reg = <0x18>;
-				#cooling-cells = <2>;
 			};
 
 			rtc_twi: rtc@6f {
@@ -156,7 +155,7 @@
 	pinctrl-0 = <&rgmii_pins>;
 	snps,reset-active-low;
 	snps,reset-delays-us = <0 10000 50000>;
-	snps,reset-gpio = <&gpio3 RK_PB3 GPIO_ACTIVE_HIGH>;
+	snps,reset-gpio = <&gpio3 RK_PB3 GPIO_ACTIVE_LOW>;
 	tx_delay = <0x10>;
 	rx_delay = <0x10>;
 	status = "okay";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/rockchip/rk3368.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/rockchip/rk3368.dtsi
@@ -686,6 +686,7 @@
 		dma-names = "tx";
 		pinctrl-names = "default";
 		pinctrl-0 = <&spdif_tx>;
+		#sound-dai-cells = <0>;
 		status = "disabled";
 	};
 
@@ -697,6 +698,7 @@
 		clocks = <&cru SCLK_I2S_2CH>, <&cru HCLK_I2S_2CH>;
 		dmas = <&dmac_bus 6>, <&dmac_bus 7>;
 		dma-names = "tx", "rx";
+		#sound-dai-cells = <0>;
 		status = "disabled";
 	};
 
@@ -710,6 +712,7 @@
 		dma-names = "tx", "rx";
 		pinctrl-names = "default";
 		pinctrl-0 = <&i2s_8ch_bus>;
+		#sound-dai-cells = <0>;
 		status = "disabled";
 	};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts
@@ -666,12 +666,15 @@
 	sd-uhs-sdr104;
 
 	/* Power supply */
-	vqmmc-supply = &vcc1v8_s3;	/* IO line */
-	vmmc-supply = &vcc_sdio;	/* card's power */
+	vqmmc-supply = <&vcc1v8_s3>;	/* IO line */
+	vmmc-supply = <&vcc_sdio>;	/* card's power */
 
+	#address-cells = <1>;
+	#size-cells = <0>;
 	status = "okay";
 
 	brcmf: wifi@1 {
+		reg = <1>;
 		compatible = "brcm,bcm4329-fmac";
 		interrupt-parent = <&gpio0>;
 		interrupts = <RK_PA3 GPIO_ACTIVE_HIGH>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/rockchip/rk3399-gru-bob.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/rockchip/rk3399-gru-bob.dts
@@ -77,3 +77,8 @@
 		};
 	};
 };
+
+&wlan_host_wake_l {
+	/* Kevin has an external pull up, but Bob does not. */
+	rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>;
+};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/rockchip/rk3399-gru-chromebook.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/rockchip/rk3399-gru-chromebook.dtsi
@@ -237,6 +237,14 @@
 &edp {
 	status = "okay";
 
+	/*
+	 * eDP PHY/clk don't sync reliably at anything other than 24 MHz. Only
+	 * set this here, because rk3399-gru.dtsi ensures we can generate this
+	 * off GPLL=600MHz, whereas some other RK3399 boards may not.
+	 */
+	assigned-clocks = <&cru PCLK_EDP>;
+	assigned-clock-rates = <24000000>;
+
 	ports {
 		edp_out: port@1 {
 			reg = <1>;
@@ -397,6 +405,7 @@
 	};
 
 	wlan_host_wake_l: wlan-host-wake-l {
+		/* Kevin has an external pull up, but Bob does not */
 		rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
 	};
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi
@@ -281,7 +281,7 @@
 
 	sound: sound {
 		compatible = "rockchip,rk3399-gru-sound";
-		rockchip,cpu = <&i2s0 &i2s2>;
+		rockchip,cpu = <&i2s0 &spdif>;
 	};
 };
 
@@ -432,10 +432,6 @@
 	status = "okay";
 };
 
-&i2s2 {
-	status = "okay";
-};
-
 &io_domains {
 	status = "okay";
 
@@ -532,6 +528,17 @@
 	vqmmc-supply = <&ppvar_sd_card_io>;
 };
 
+&spdif {
+	status = "okay";
+
+	/*
+	 * SPDIF is routed internally to DP; we either don't use these pins, or
+	 * mux them to something else.
+	 */
+	/delete-property/ pinctrl-0;
+	/delete-property/ pinctrl-names;
+};
+
 &spi1 {
 	status = "okay";
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/rockchip/rk3399-khadas-edge.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/rockchip/rk3399-khadas-edge.dtsi
@@ -654,9 +654,12 @@
 	sd-uhs-sdr104;
 	vqmmc-supply = <&vcc1v8_s3>;
 	vmmc-supply = <&vccio_sd>;
+	#address-cells = <1>;
+	#size-cells = <0>;
 	status = "okay";
 
 	brcmf: wifi@1 {
+		reg = <1>;
 		compatible = "brcm,bcm4329-fmac";
 		interrupt-parent = <&gpio0>;
 		interrupts = <RK_PA3 GPIO_ACTIVE_HIGH>;
@@ -682,7 +685,6 @@
 &sdhci {
 	bus-width = <8>;
 	mmc-hs400-1_8v;
-	mmc-hs400-enhanced-strobe;
 	non-removable;
 	status = "okay";
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/rockchip/rk3399-leez-p710.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/rockchip/rk3399-leez-p710.dts
@@ -49,7 +49,7 @@
 		regulator-boot-on;
 		regulator-min-microvolt = <3300000>;
 		regulator-max-microvolt = <3300000>;
-		vim-supply = <&vcc3v3_sys>;
+		vin-supply = <&vcc3v3_sys>;
 	};
 
 	vcc3v3_sys: vcc3v3-sys {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/rockchip/rk3399-nanopc-t4.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/rockchip/rk3399-nanopc-t4.dts
@@ -94,33 +94,6 @@
 	};
 };
 
-&gpu_thermal {
-	trips {
-		gpu_warm: gpu_warm {
-			temperature = <55000>;
-			hysteresis = <2000>;
-			type = "active";
-		};
-
-		gpu_hot: gpu_hot {
-			temperature = <65000>;
-			hysteresis = <2000>;
-			type = "active";
-		};
-	};
-	cooling-maps {
-		map1 {
-			trip = <&gpu_warm>;
-			cooling-device = <&fan THERMAL_NO_LIMIT 1>;
-		};
-
-		map2 {
-			trip = <&gpu_hot>;
-			cooling-device = <&fan 2 THERMAL_NO_LIMIT>;
-		};
-	};
-};
-
 &pinctrl {
 	ir {
 		ir_rx: ir-rx {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/rockchip/rk3399-orangepi.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/rockchip/rk3399-orangepi.dts
@@ -648,9 +648,12 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&sdio0_bus4 &sdio0_cmd &sdio0_clk>;
 	sd-uhs-sdr104;
+	#address-cells = <1>;
+	#size-cells = <0>;
 	status = "okay";
 
 	brcmf: wifi@1 {
+		reg = <1>;
 		compatible = "brcm,bcm4329-fmac";
 		interrupt-parent = <&gpio0>;
 		interrupts = <RK_PA3 GPIO_ACTIVE_HIGH>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts
@@ -203,7 +203,7 @@
 	cap-sd-highspeed;
 	cd-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>;
 	disable-wp;
-	max-frequency = <150000000>;
+	max-frequency = <40000000>;
 	pinctrl-names = "default";
 	pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_bus4>;
 	vmmc-supply = <&vcc3v3_baseboard>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi
@@ -101,8 +101,7 @@
 
 	vcc5v0_host: vcc5v0-host-regulator {
 		compatible = "regulator-fixed";
-		gpio = <&gpio4 RK_PA3 GPIO_ACTIVE_HIGH>;
-		enable-active-low;
+		gpio = <&gpio4 RK_PA3 GPIO_ACTIVE_LOW>;
 		pinctrl-names = "default";
 		pinctrl-0 = <&vcc5v0_host_en>;
 		regulator-name = "vcc5v0_host";
@@ -149,6 +148,22 @@
 	drive-impedance-ohm = <33>;
 };
 
+&gpio3 {
+	/*
+	 * The Qseven BIOS_DISABLE signal on the RK3399-Q7 keeps the on-module
+	 * eMMC and SPI flash powered-down initially (in fact it keeps the
+	 * reset signal asserted). BIOS_DISABLE_OVERRIDE pin allows to override
+	 * that signal so that eMMC and SPI can be used regardless of the state
+	 * of the signal.
+	 */
+	bios-disable-override-hog {
+		gpios = <RK_PD5 GPIO_ACTIVE_LOW>;
+		gpio-hog;
+		line-name = "bios_disable_override";
+		output-high;
+	};
+};
+
 &gmac {
 	assigned-clocks = <&cru SCLK_RMII_SRC>;
 	assigned-clock-parents = <&clkin_gmac>;
@@ -157,11 +172,11 @@
 	phy-mode = "rgmii";
 	pinctrl-names = "default";
 	pinctrl-0 = <&rgmii_pins>;
-	snps,reset-gpio = <&gpio3 RK_PC0 GPIO_ACTIVE_HIGH>;
+	snps,reset-gpio = <&gpio3 RK_PC0 GPIO_ACTIVE_LOW>;
 	snps,reset-active-low;
 	snps,reset-delays-us = <0 10000 50000>;
 	tx_delay = <0x10>;
-	rx_delay = <0x10>;
+	rx_delay = <0x23>;
 	status = "okay";
 };
 
@@ -426,16 +441,27 @@
 	gpio1830-supply = <&vcc_1v8>;
 };
 
-&pmu_io_domains {
-	status = "okay";
-	pmu1830-supply = <&vcc_1v8>;
-};
-
-&pwm2 {
-	status = "okay";
+&pcie_clkreqn_cpm {
+	rockchip,pins =
+		<2 RK_PD2 RK_FUNC_GPIO &pcfg_pull_up>;
 };
 
 &pinctrl {
+	pinctrl-names = "default";
+	pinctrl-0 = <&q7_thermal_pin &bios_disable_override_hog_pin>;
+
+	gpios {
+		bios_disable_override_hog_pin: bios-disable-override-hog-pin {
+			rockchip,pins =
+				<3 RK_PD5 RK_FUNC_GPIO &pcfg_pull_down>;
+		};
+
+		q7_thermal_pin: q7-thermal-pin {
+			rockchip,pins =
+				<0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>;
+		};
+	};
+
 	i2c8 {
 		i2c8_xfer_a: i2c8-xfer {
 			rockchip,pins =
@@ -466,7 +492,22 @@
 	};
 };
 
+&pmu_io_domains {
+	status = "okay";
+	pmu1830-supply = <&vcc_1v8>;
+};
+
+&pwm2 {
+	status = "okay";
+};
+
 &sdhci {
+	/*
+	 * Signal integrity isn't great at 200MHz but 100MHz has proven stable
+	 * enough.
+	 */
+	max-frequency = <100000000>;
+
 	bus-width = <8>;
 	mmc-hs400-1_8v;
 	mmc-hs400-enhanced-strobe;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts
@@ -441,7 +441,6 @@
 &i2s1 {
 	rockchip,playback-channels = <2>;
 	rockchip,capture-channels = <2>;
-	status = "okay";
 };
 
 &i2s2 {
@@ -452,7 +451,7 @@
 	status = "okay";
 
 	bt656-supply = <&vcc_3v0>;
-	audio-supply = <&vcc_3v0>;
+	audio-supply = <&vcc1v8_codec>;
 	sdmmc-supply = <&vcc_sdio>;
 	gpio1830-supply = <&vcc_3v0>;
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi
@@ -557,7 +557,7 @@
 	bluetooth {
 		compatible = "brcm,bcm43438-bt";
 		clocks = <&rk808 1>;
-		clock-names = "ext_clock";
+		clock-names = "txco";
 		device-wakeup-gpios = <&gpio2 RK_PD3 GPIO_ACTIVE_HIGH>;
 		host-wakeup-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_HIGH>;
 		shutdown-gpios = <&gpio0 RK_PB1 GPIO_ACTIVE_HIGH>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/rockchip/rk3399-sapphire-excavator.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/rockchip/rk3399-sapphire-excavator.dts
@@ -159,7 +159,7 @@
 	status = "okay";
 
 	rt5651: rt5651@1a {
-		compatible = "rockchip,rt5651";
+		compatible = "realtek,rt5651";
 		reg = <0x1a>;
 		clocks = <&cru SCLK_I2S_8CH_OUT>;
 		clock-names = "mclk";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -29,6 +29,9 @@
 		i2c6 = &i2c6;
 		i2c7 = &i2c7;
 		i2c8 = &i2c8;
+		mmc0 = &sdio0;
+		mmc1 = &sdmmc;
+		mmc2 = &sdhci;
 		serial0 = &uart0;
 		serial1 = &uart1;
 		serial2 = &uart2;
@@ -229,6 +232,7 @@
 		reg = <0x0 0xf8000000 0x0 0x2000000>,
 		      <0x0 0xfd000000 0x0 0x1000000>;
 		reg-names = "axi-base", "apb-base";
+		device_type = "pci";
 		#address-cells = <3>;
 		#size-cells = <2>;
 		#interrupt-cells = <1>;
@@ -247,7 +251,6 @@
 				<0 0 0 2 &pcie0_intc 1>,
 				<0 0 0 3 &pcie0_intc 2>,
 				<0 0 0 4 &pcie0_intc 3>;
-		linux,pci-domain = <0>;
 		max-link-speed = <1>;
 		msi-map = <0x0 &its 0x0 0x1000>;
 		phys = <&pcie_phy 0>, <&pcie_phy 1>,
@@ -410,7 +413,7 @@
 		reset-names = "usb3-otg";
 		status = "disabled";
 
-		usbdrd_dwc3_0: dwc3 {
+		usbdrd_dwc3_0: usb@fe800000 {
 			compatible = "snps,dwc3";
 			reg = <0x0 0xfe800000 0x0 0x100000>;
 			interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH 0>;
@@ -446,7 +449,7 @@
 		reset-names = "usb3-otg";
 		status = "disabled";
 
-		usbdrd_dwc3_1: dwc3 {
+		usbdrd_dwc3_1: usb@fe900000 {
 			compatible = "snps,dwc3";
 			reg = <0x0 0xfe900000 0x0 0x100000>;
 			interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH 0>;
@@ -998,6 +1001,7 @@
 				clocks = <&cru ACLK_IEP>,
 					 <&cru HCLK_IEP>;
 				pm_qos = <&qos_iep>;
+				#power-domain-cells = <0>;
 			};
 			pd_rga@RK3399_PD_RGA {
 				reg = <RK3399_PD_RGA>;
@@ -1005,12 +1009,14 @@
 					 <&cru HCLK_RGA>;
 				pm_qos = <&qos_rga_r>,
 					 <&qos_rga_w>;
+				#power-domain-cells = <0>;
 			};
 			pd_vcodec@RK3399_PD_VCODEC {
 				reg = <RK3399_PD_VCODEC>;
 				clocks = <&cru ACLK_VCODEC>,
 					 <&cru HCLK_VCODEC>;
 				pm_qos = <&qos_video_m0>;
+				#power-domain-cells = <0>;
 			};
 			pd_vdu@RK3399_PD_VDU {
 				reg = <RK3399_PD_VDU>;
@@ -1018,6 +1024,7 @@
 					 <&cru HCLK_VDU>;
 				pm_qos = <&qos_video_m1_r>,
 					 <&qos_video_m1_w>;
+				#power-domain-cells = <0>;
 			};
 
 			/* These power domains are grouped by VD_GPU */
@@ -1025,43 +1032,63 @@
 				reg = <RK3399_PD_GPU>;
 				clocks = <&cru ACLK_GPU>;
 				pm_qos = <&qos_gpu>;
+				#power-domain-cells = <0>;
 			};
 
 			/* These power domains are grouped by VD_LOGIC */
 			pd_edp@RK3399_PD_EDP {
 				reg = <RK3399_PD_EDP>;
 				clocks = <&cru PCLK_EDP_CTRL>;
+				#power-domain-cells = <0>;
 			};
 			pd_emmc@RK3399_PD_EMMC {
 				reg = <RK3399_PD_EMMC>;
 				clocks = <&cru ACLK_EMMC>;
 				pm_qos = <&qos_emmc>;
+				#power-domain-cells = <0>;
 			};
 			pd_gmac@RK3399_PD_GMAC {
 				reg = <RK3399_PD_GMAC>;
 				clocks = <&cru ACLK_GMAC>,
 					 <&cru PCLK_GMAC>;
 				pm_qos = <&qos_gmac>;
+				#power-domain-cells = <0>;
 			};
 			pd_sd@RK3399_PD_SD {
 				reg = <RK3399_PD_SD>;
 				clocks = <&cru HCLK_SDMMC>,
 					 <&cru SCLK_SDMMC>;
 				pm_qos = <&qos_sd>;
+				#power-domain-cells = <0>;
 			};
 			pd_sdioaudio@RK3399_PD_SDIOAUDIO {
 				reg = <RK3399_PD_SDIOAUDIO>;
 				clocks = <&cru HCLK_SDIO>;
 				pm_qos = <&qos_sdioaudio>;
+				#power-domain-cells = <0>;
+			};
+			pd_tcpc0@RK3399_PD_TCPD0 {
+				reg = <RK3399_PD_TCPD0>;
+				clocks = <&cru SCLK_UPHY0_TCPDCORE>,
+					 <&cru SCLK_UPHY0_TCPDPHY_REF>;
+				#power-domain-cells = <0>;
+			};
+			pd_tcpc1@RK3399_PD_TCPD1 {
+				reg = <RK3399_PD_TCPD1>;
+				clocks = <&cru SCLK_UPHY1_TCPDCORE>,
+					 <&cru SCLK_UPHY1_TCPDPHY_REF>;
+				#power-domain-cells = <0>;
 			};
 			pd_usb3@RK3399_PD_USB3 {
 				reg = <RK3399_PD_USB3>;
 				clocks = <&cru ACLK_USB3>;
 				pm_qos = <&qos_usb_otg0>,
 					 <&qos_usb_otg1>;
+				#power-domain-cells = <0>;
 			};
 			pd_vio@RK3399_PD_VIO {
 				reg = <RK3399_PD_VIO>;
+				#power-domain-cells = <1>;
 				#address-cells = <1>;
 				#size-cells = <0>;
 
@@ -1071,6 +1098,7 @@
 						 <&cru HCLK_HDCP>,
 						 <&cru PCLK_HDCP>;
 					pm_qos = <&qos_hdcp>;
+					#power-domain-cells = <0>;
 				};
 				pd_isp0@RK3399_PD_ISP0 {
 					reg = <RK3399_PD_ISP0>;
@@ -1078,6 +1106,7 @@
 						 <&cru HCLK_ISP0>;
 					pm_qos = <&qos_isp0_m0>,
 						 <&qos_isp0_m1>;
+					#power-domain-cells = <0>;
 				};
 				pd_isp1@RK3399_PD_ISP1 {
 					reg = <RK3399_PD_ISP1>;
@@ -1085,19 +1114,11 @@
 						 <&cru HCLK_ISP1>;
 					pm_qos = <&qos_isp1_m0>,
 						 <&qos_isp1_m1>;
-				};
-				pd_tcpc0@RK3399_PD_TCPC0 {
-					reg = <RK3399_PD_TCPD0>;
-					clocks = <&cru SCLK_UPHY0_TCPDCORE>,
-						 <&cru SCLK_UPHY0_TCPDPHY_REF>;
-				};
-				pd_tcpc1@RK3399_PD_TCPC1 {
-					reg = <RK3399_PD_TCPD1>;
-					clocks = <&cru SCLK_UPHY1_TCPDCORE>,
-						 <&cru SCLK_UPHY1_TCPDPHY_REF>;
+					#power-domain-cells = <0>;
 				};
 				pd_vo@RK3399_PD_VO {
 					reg = <RK3399_PD_VO>;
+					#power-domain-cells = <1>;
 					#address-cells = <1>;
 					#size-cells = <0>;
 
@@ -1107,12 +1128,14 @@
 							 <&cru HCLK_VOP0>;
 						pm_qos = <&qos_vop_big_r>,
 							 <&qos_vop_big_w>;
+						#power-domain-cells = <0>;
 					};
 					pd_vopl@RK3399_PD_VOPL {
 						reg = <RK3399_PD_VOPL>;
 						clocks = <&cru ACLK_VOP1>,
 							 <&cru HCLK_VOP1>;
 						pm_qos = <&qos_vop_little>;
+						#power-domain-cells = <0>;
 					};
 				};
 			};
@@ -1444,6 +1467,7 @@
 			reg = <0xf780 0x24>;
 			clocks = <&sdhci>;
 			clock-names = "emmcclk";
+			drive-impedance-ohm = <50>;
 			#phy-cells = <0>;
 			status = "disabled";
 		};
@@ -1454,7 +1478,6 @@
 			clock-names = "refclk";
 			#phy-cells = <1>;
 			resets = <&cru SRST_PCIEPHY>;
-			drive-impedance-ohm = <50>;
 			reset-names = "phy";
 			status = "disabled";
 		};
@@ -1740,21 +1763,25 @@
 	hdmi: hdmi@ff940000 {
 		compatible = "rockchip,rk3399-dw-hdmi";
 		reg = <0x0 0xff940000 0x0 0x20000>;
+		reg-io-width = <4>;
 		interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH 0>;
 		clocks = <&cru PCLK_HDMI_CTRL>,
 			 <&cru SCLK_HDMI_SFR>,
-			 <&cru PLL_VPLL>,
+			 <&cru SCLK_HDMI_CEC>,
 			 <&cru PCLK_VIO_GRF>,
-			 <&cru SCLK_HDMI_CEC>;
-		clock-names = "iahb", "isfr", "vpll", "grf", "cec";
+			 <&cru PLL_VPLL>;
+		clock-names = "iahb", "isfr", "cec", "grf", "vpll";
 		power-domains = <&power RK3399_PD_HDCP>;
-		reg-io-width = <4>;
 		rockchip,grf = <&grf>;
 		#sound-dai-cells = <0>;
 		status = "disabled";
 
 		ports {
-			hdmi_in: port {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			hdmi_in: port@0 {
+				reg = <0>;
 				#address-cells = <1>;
 				#size-cells = <0>;
 
@@ -1767,6 +1794,10 @@
 					remote-endpoint = <&vopl_out_hdmi>;
 				};
 			};
+
+			hdmi_out: port@1 {
+				reg = <1>;
+			};
 		};
 	};
 
@@ -1881,10 +1912,10 @@
 	gpu: gpu@ff9a0000 {
 		compatible = "rockchip,rk3399-mali", "arm,mali-t860";
 		reg = <0x0 0xff9a0000 0x0 0x10000>;
-		interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH 0>,
-			     <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH 0>,
-			     <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH 0>;
-		interrupt-names = "gpu", "job", "mmu";
+		interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH 0>,
+			     <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH 0>;
+		interrupt-names = "job", "mmu", "gpu";
 		clocks = <&cru ACLK_GPU>;
 		power-domains = <&power RK3399_PD_GPU>;
 		status = "disabled";
@@ -2314,7 +2345,7 @@
 			};
 		};
 
-		sleep {
+		suspend {
 			ap_pwroff: ap-pwroff {
 				rockchip,pins = <1 RK_PA5 1 &pcfg_pull_none>;
 			};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi
@@ -718,7 +718,7 @@
 			clocks = <&sys_clk 6>;
 			reset-names = "ether";
 			resets = <&sys_rst 6>;
-			phy-mode = "rgmii";
+			phy-mode = "rgmii-id";
 			local-mac-address = [00 00 00 00 00 00];
 			socionext,syscon-phy-mode = <&soc_glue 0>;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/socionext/uniphier-pxs3.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/socionext/uniphier-pxs3.dtsi
@@ -509,7 +509,7 @@
 			clocks = <&sys_clk 6>;
 			reset-names = "ether";
 			resets = <&sys_rst 6>;
-			phy-mode = "rgmii";
+			phy-mode = "rgmii-id";
 			local-mac-address = [00 00 00 00 00 00];
 			socionext,syscon-phy-mode = <&soc_glue 0>;
 
@@ -530,7 +530,7 @@
 			clocks = <&sys_clk 7>;
 			reset-names = "ether";
 			resets = <&sys_rst 7>;
-			phy-mode = "rgmii";
+			phy-mode = "rgmii-id";
 			local-mac-address = [00 00 00 00 00 00];
 			socionext,syscon-phy-mode = <&soc_glue 1>;
 
@@ -544,8 +544,8 @@
 			compatible = "socionext,uniphier-dwc3", "snps,dwc3";
 			status = "disabled";
 			reg = <0x65a00000 0xcd00>;
-			interrupt-names = "host", "peripheral";
-			interrupts = <0 134 4>, <0 135 4>;
+			interrupt-names = "dwc_usb3";
+			interrupts = <0 134 4>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_usb0>, <&pinctrl_usb2>;
 			clock-names = "ref", "bus_early", "suspend";
@@ -646,8 +646,8 @@
 			compatible = "socionext,uniphier-dwc3", "snps,dwc3";
 			status = "disabled";
 			reg = <0x65c00000 0xcd00>;
-			interrupt-names = "host", "peripheral";
-			interrupts = <0 137 4>, <0 138 4>;
+			interrupt-names = "dwc_usb3";
+			interrupts = <0 137 4>;
 			pinctrl-names = "default";
 			pinctrl-0 = <&pinctrl_usb1>, <&pinctrl_usb3>;
 			clock-names = "ref", "bus_early", "suspend";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
@@ -307,6 +307,7 @@
 		interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
 		dma-coherent;
 		power-domains = <&k3_pds 151 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 151 2>, <&k3_clks 151 7>;
 		assigned-clocks = <&k3_clks 151 2>, <&k3_clks 151 7>;
 		assigned-clock-parents = <&k3_clks 151 4>,	/* set REF_CLK to 20MHz i.e. PER0_PLL/48 */
 					 <&k3_clks 151 9>;	/* set PIPE3_TXB_CLK to CLK_12M_RC/256 (for HS only) */
@@ -346,6 +347,7 @@
 		interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
 		dma-coherent;
 		power-domains = <&k3_pds 152 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 152 2>;
 		assigned-clocks = <&k3_clks 152 2>;
 		assigned-clock-parents = <&k3_clks 152 4>;	/* set REF_CLK to 20MHz i.e. PER0_PLL/48 */
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi
@@ -43,6 +43,7 @@
 	smmu0: smmu@36600000 {
 		compatible = "arm,smmu-v3";
 		reg = <0x0 0x36600000 0x0 0x100000>;
+		power-domains = <&k3_pds 229 TI_SCI_PD_EXCLUSIVE>;
 		interrupt-parent = <&gic500>;
 		interrupts = <GIC_SPI 772 IRQ_TYPE_EDGE_RISING>,
 			     <GIC_SPI 768 IRQ_TYPE_EDGE_RISING>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/ti/k3-j721e.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/ti/k3-j721e.dtsi
@@ -60,7 +60,7 @@
 			i-cache-sets = <256>;
 			d-cache-size = <0x8000>;
 			d-cache-line-size = <64>;
-			d-cache-sets = <128>;
+			d-cache-sets = <256>;
 			next-level-cache = <&L2_0>;
 		};
 
@@ -74,7 +74,7 @@
 			i-cache-sets = <256>;
 			d-cache-size = <0x8000>;
 			d-cache-line-size = <64>;
-			d-cache-sets = <128>;
+			d-cache-sets = <256>;
 			next-level-cache = <&L2_0>;
 		};
 	};
@@ -84,7 +84,7 @@
 		cache-level = <2>;
 		cache-size = <0x100000>;
 		cache-line-size = <64>;
-		cache-sets = <2048>;
+		cache-sets = <1024>;
 		next-level-cache = <&msmc_l3>;
 	};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/xilinx/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/xilinx/Makefile
@@ -2,7 +2,6 @@
 dtb-$(CONFIG_ARCH_ZYNQMP) += avnet-ultra96-rev1.dtb
 dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-zc1232-revA.dtb
 dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-zc1254-revA.dtb
-dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-zc1275-revA.dtb
 dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-zc1751-xm015-dc1.dtb
 dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-zc1751-xm016-dc2.dtb
 dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-zc1751-xm017-dc3.dtb
@@ -13,5 +12,11 @@
 dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-zcu102-revB.dtb
 dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-zcu102-rev1.0.dtb
 dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-zcu104-revA.dtb
+dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-zcu104-revC.dtb
 dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-zcu106-revA.dtb
 dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-zcu111-revA.dtb
+dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-zcu1275-revA.dtb
+dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-zcu1275-revB.dtb
+dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-zcu1285-revA.dtb
+dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-zcu208-revA.dtb
+dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-zcu216-revA.dtb
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/xilinx/avnet-ultra96-rev1.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/xilinx/avnet-ultra96-rev1.dts
@@ -2,7 +2,7 @@
 /*
  * dts file for Avnet Ultra96 rev1
  *
- * (C) Copyright 2018, Xilinx, Inc.
+ * (C) Copyright 2018 - 2020, Xilinx, Inc.
  *
  * Michal Simek <michal.simek@xilinx.com>
  */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/xilinx/zynqmp-clk-ccf.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/xilinx/zynqmp-clk-ccf.dtsi
@@ -0,0 +1,317 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Clock specification for Xilinx ZynqMP
+ *
+ * (C) Copyright 2017 - 2020, Xilinx, Inc.
+ *
+ * Michal Simek <michal.simek@xilinx.com>
+ */
+
+#include <dt-bindings/clock/xlnx-zynqmp-clk.h>
+/ {
+	fclk0: fclk0 {
+		status = "okay";
+		compatible = "xlnx,fclk";
+		clocks = <&zynqmp_clk PL0_REF>;
+	};
+
+	fclk1: fclk1 {
+		status = "okay";
+		compatible = "xlnx,fclk";
+		clocks = <&zynqmp_clk PL1_REF>;
+	};
+
+	fclk2: fclk2 {
+		status = "okay";
+		compatible = "xlnx,fclk";
+		clocks = <&zynqmp_clk PL2_REF>;
+	};
+
+	fclk3: fclk3 {
+		status = "okay";
+		compatible = "xlnx,fclk";
+		clocks = <&zynqmp_clk PL3_REF>;
+	};
+
+	pss_ref_clk: pss_ref_clk {
+		u-boot,dm-pre-reloc;
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <33333333>;
+	};
+
+	video_clk: video_clk {
+		u-boot,dm-pre-reloc;
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <27000000>;
+	};
+
+	pss_alt_ref_clk: pss_alt_ref_clk {
+		u-boot,dm-pre-reloc;
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <0>;
+	};
+
+	gt_crx_ref_clk: gt_crx_ref_clk {
+		u-boot,dm-pre-reloc;
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <108000000>;
+	};
+
+	aux_ref_clk: aux_ref_clk {
+		u-boot,dm-pre-reloc;
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <27000000>;
+	};
+
+	dp_aclk: dp_aclk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <100000000>;
+		clock-accuracy = <100>;
+	};
+};
+
+&zynqmp_firmware {
+	zynqmp_clk: clock-controller {
+		u-boot,dm-pre-reloc;
+		#clock-cells = <1>;
+		compatible = "xlnx,zynqmp-clk";
+		clocks = <&pss_ref_clk>, <&video_clk>, <&pss_alt_ref_clk>,
+			 <&aux_ref_clk>, <&gt_crx_ref_clk>;
+		clock-names = "pss_ref_clk", "video_clk", "pss_alt_ref_clk",
+			      "aux_ref_clk", "gt_crx_ref_clk";
+	};
+};
+
+&can0 {
+	clocks = <&zynqmp_clk CAN0_REF>, <&zynqmp_clk LPD_LSBUS>;
+};
+
+&can1 {
+	clocks = <&zynqmp_clk CAN1_REF>, <&zynqmp_clk LPD_LSBUS>;
+};
+
+&cpu0 {
+	clocks = <&zynqmp_clk ACPU>;
+};
+
+&fpd_dma_chan1 {
+	clocks = <&zynqmp_clk GDMA_REF>, <&zynqmp_clk LPD_LSBUS>;
+};
+
+&fpd_dma_chan2 {
+	clocks = <&zynqmp_clk GDMA_REF>, <&zynqmp_clk LPD_LSBUS>;
+};
+
+&fpd_dma_chan3 {
+	clocks = <&zynqmp_clk GDMA_REF>, <&zynqmp_clk LPD_LSBUS>;
+};
+
+&fpd_dma_chan4 {
+	clocks = <&zynqmp_clk GDMA_REF>, <&zynqmp_clk LPD_LSBUS>;
+};
+
+&fpd_dma_chan5 {
+	clocks = <&zynqmp_clk GDMA_REF>, <&zynqmp_clk LPD_LSBUS>;
+};
+
+&fpd_dma_chan6 {
+	clocks = <&zynqmp_clk GDMA_REF>, <&zynqmp_clk LPD_LSBUS>;
+};
+
+&fpd_dma_chan7 {
+	clocks = <&zynqmp_clk GDMA_REF>, <&zynqmp_clk LPD_LSBUS>;
+};
+
+&fpd_dma_chan8 {
+	clocks = <&zynqmp_clk GDMA_REF>, <&zynqmp_clk LPD_LSBUS>;
+};
+
+&gpu {
+	clocks = <&zynqmp_clk GPU_REF>, <&zynqmp_clk GPU_PP0_REF>, <&zynqmp_clk GPU_PP1_REF>;
+};
+
+&lpd_dma_chan1 {
+	clocks = <&zynqmp_clk ADMA_REF>, <&zynqmp_clk LPD_LSBUS>;
+};
+
+&lpd_dma_chan2 {
+	clocks = <&zynqmp_clk ADMA_REF>, <&zynqmp_clk LPD_LSBUS>;
+};
+
+&lpd_dma_chan3 {
+	clocks = <&zynqmp_clk ADMA_REF>, <&zynqmp_clk LPD_LSBUS>;
+};
+
+&lpd_dma_chan4 {
+	clocks = <&zynqmp_clk ADMA_REF>, <&zynqmp_clk LPD_LSBUS>;
+};
+
+&lpd_dma_chan5 {
+	clocks = <&zynqmp_clk ADMA_REF>, <&zynqmp_clk LPD_LSBUS>;
+};
+
+&lpd_dma_chan6 {
+	clocks = <&zynqmp_clk ADMA_REF>, <&zynqmp_clk LPD_LSBUS>;
+};
+
+&lpd_dma_chan7 {
+	clocks = <&zynqmp_clk ADMA_REF>, <&zynqmp_clk LPD_LSBUS>;
+};
+
+&lpd_dma_chan8 {
+	clocks = <&zynqmp_clk ADMA_REF>, <&zynqmp_clk LPD_LSBUS>;
+};
+
+&nand0 {
+	clocks = <&zynqmp_clk NAND_REF>, <&zynqmp_clk LPD_LSBUS>;
+};
+
+&gem0 {
+	clocks = <&zynqmp_clk LPD_LSBUS>, <&zynqmp_clk GEM0_REF>,
+		 <&zynqmp_clk GEM0_TX>, <&zynqmp_clk GEM0_RX>,
+		 <&zynqmp_clk GEM_TSU>;
+	clock-names = "pclk", "hclk", "tx_clk", "rx_clk", "tsu_clk";
+};
+
+&gem1 {
+	clocks = <&zynqmp_clk LPD_LSBUS>, <&zynqmp_clk GEM1_REF>,
+		 <&zynqmp_clk GEM1_TX>, <&zynqmp_clk GEM1_RX>,
+		 <&zynqmp_clk GEM_TSU>;
+	clock-names = "pclk", "hclk", "tx_clk", "rx_clk", "tsu_clk";
+};
+
+&gem2 {
+	clocks = <&zynqmp_clk LPD_LSBUS>, <&zynqmp_clk GEM2_REF>,
+		 <&zynqmp_clk GEM2_TX>, <&zynqmp_clk GEM2_RX>,
+		 <&zynqmp_clk GEM_TSU>;
+	clock-names = "pclk", "hclk", "tx_clk", "rx_clk", "tsu_clk";
+};
+
+&gem3 {
+	clocks = <&zynqmp_clk LPD_LSBUS>, <&zynqmp_clk GEM3_REF>,
+		 <&zynqmp_clk GEM3_TX>, <&zynqmp_clk GEM3_RX>,
+		 <&zynqmp_clk GEM_TSU>;
+	clock-names = "pclk", "hclk", "tx_clk", "rx_clk", "tsu_clk";
+};
+
+&gpio {
+	clocks = <&zynqmp_clk LPD_LSBUS>;
+};
+
+&i2c0 {
+	clocks = <&zynqmp_clk I2C0_REF>;
+};
+
+&i2c1 {
+	clocks = <&zynqmp_clk I2C1_REF>;
+};
+
+&perf_monitor_ocm {
+	clocks = <&zynqmp_clk LPD_LSBUS>;
+};
+
+&perf_monitor_ddr {
+	clocks = <&zynqmp_clk TOPSW_LSBUS>;
+};
+
+&perf_monitor_cci {
+	clocks = <&zynqmp_clk TOPSW_LSBUS>;
+};
+
+&perf_monitor_lpd {
+	clocks = <&zynqmp_clk LPD_LSBUS>;
+};
+
+&pcie {
+	clocks = <&zynqmp_clk PCIE_REF>;
+};
+
+&qspi {
+	clocks = <&zynqmp_clk QSPI_REF>, <&zynqmp_clk LPD_LSBUS>;
+};
+
+&sata {
+	clocks = <&zynqmp_clk SATA_REF>;
+};
+
+&sdhci0 {
+	clocks = <&zynqmp_clk SDIO0_REF>, <&zynqmp_clk LPD_LSBUS>;
+};
+
+&sdhci1 {
+	clocks = <&zynqmp_clk SDIO1_REF>, <&zynqmp_clk LPD_LSBUS>;
+};
+
+&spi0 {
+	clocks = <&zynqmp_clk SPI0_REF>, <&zynqmp_clk LPD_LSBUS>;
+};
+
+&spi1 {
+	clocks = <&zynqmp_clk SPI1_REF>, <&zynqmp_clk LPD_LSBUS>;
+};
+
+&ttc0 {
+	clocks = <&zynqmp_clk LPD_LSBUS>;
+};
+
+&ttc1 {
+	clocks = <&zynqmp_clk LPD_LSBUS>;
+};
+
+&ttc2 {
+	clocks = <&zynqmp_clk LPD_LSBUS>;
+};
+
+&ttc3 {
+	clocks = <&zynqmp_clk LPD_LSBUS>;
+};
+
+&uart0 {
+	clocks = <&zynqmp_clk UART0_REF>, <&zynqmp_clk LPD_LSBUS>;
+};
+
+&uart1 {
+	clocks = <&zynqmp_clk UART1_REF>, <&zynqmp_clk LPD_LSBUS>;
+};
+
+&usb0 {
+	clocks = <&zynqmp_clk USB0_BUS_REF>, <&zynqmp_clk USB3_DUAL_REF>;
+};
+
+&usb1 {
+	clocks = <&zynqmp_clk USB1_BUS_REF>, <&zynqmp_clk USB3_DUAL_REF>;
+};
+
+&watchdog0 {
+	clocks = <&zynqmp_clk WDT>;
+};
+
+&lpd_watchdog {
+	clocks = <&zynqmp_clk LPD_WDT>;
+};
+
+&xilinx_ams {
+	clocks = <&zynqmp_clk AMS_REF>;
+};
+
+&zynqmp_dpsub {
+	clocks = <&dp_aclk>, <&zynqmp_clk DP_AUDIO_REF>, <&zynqmp_clk DP_VIDEO_REF>;
+};
+
+&xlnx_dpdma {
+	clocks = <&zynqmp_clk DPDMA_REF>;
+};
+
+&zynqmp_dp_snd_codec0 {
+	clocks = <&zynqmp_clk DP_AUDIO_REF>;
+};
+
+&zynqmp_pcap {
+	clocks = <&zynqmp_clk PCAP>;
+};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/xilinx/zynqmp-clk.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/xilinx/zynqmp-clk.dtsi
@@ -2,7 +2,7 @@
 /*
  * Clock specification for Xilinx ZynqMP
  *
- * (C) Copyright 2015 - 2018, Xilinx, Inc.
+ * (C) Copyright 2015 - 2020, Xilinx, Inc.
  *
  * Michal Simek <michal.simek@xilinx.com>
  */
@@ -12,6 +12,7 @@
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <100000000>;
+		u-boot,dm-pre-reloc;
 	};
 
 	clk125: clk125 {
@@ -24,6 +25,7 @@
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <200000000>;
+		u-boot,dm-pre-reloc;
 	};
 
 	clk250: clk250 {
@@ -36,6 +38,7 @@
 		compatible = "fixed-clock";
 		#clock-cells = <0>;
 		clock-frequency = <300000000>;
+		u-boot,dm-pre-reloc;
 	};
 
 	clk600: clk600 {
@@ -144,6 +147,10 @@
 	clocks = <&clk600>, <&clk100>;
 };
 
+&nand0 {
+	clocks = <&clk100 &clk100>;
+};
+
 &gem0 {
 	clocks = <&clk125>, <&clk125>, <&clk125>;
 };
@@ -172,6 +179,26 @@
 	clocks = <&clk100>;
 };
 
+&perf_monitor_ocm {
+	clocks = <&clk100>;
+};
+
+&perf_monitor_ddr {
+	clocks = <&clk100>;
+};
+
+&perf_monitor_cci {
+	clocks = <&clk100>;
+};
+
+&perf_monitor_lpd {
+	clocks = <&clk100>;
+};
+
+&qspi {
+	clocks = <&clk300 &clk300>;
+};
+
 &sata {
 	clocks = <&clk250>;
 };
@@ -209,5 +236,21 @@
 };
 
 &watchdog0 {
+	clocks = <&clk100>;
+};
+
+&lpd_watchdog {
 	clocks = <&clk250>;
 };
+
+&zynqmp_dpsub {
+	clocks = <&dp_aclk>, <&dp_aud_clk>, <&drm_clock>;
+};
+
+&xlnx_dpdma {
+	clocks = <&dpdma_clk>;
+};
+
+&zynqmp_dp_snd_codec0 {
+	clocks = <&dp_aud_clk>;
+};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/xilinx/zynqmp-zc1232-revA.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/xilinx/zynqmp-zc1232-revA.dts
@@ -2,7 +2,7 @@
 /*
  * dts file for Xilinx ZynqMP ZC1232
  *
- * (C) Copyright 2017 - 2018, Xilinx, Inc.
+ * (C) Copyright 2017 - 2020, Xilinx, Inc.
  *
  * Michal Simek <michal.simek@xilinx.com>
  */
@@ -10,7 +10,8 @@
 /dts-v1/;
 
 #include "zynqmp.dtsi"
-#include "zynqmp-clk.dtsi"
+#include "zynqmp-clk-ccf.dtsi"
+#include <dt-bindings/phy/phy.h>
 
 / {
 	model = "ZynqMP ZC1232 RevA";
@@ -19,6 +20,7 @@
 	aliases {
 		serial0 = &uart0;
 		serial1 = &dcc;
+		spi0 = &qspi;
 	};
 
 	chosen {
@@ -36,6 +38,35 @@
 	status = "okay";
 };
 
+&qspi {
+	status = "okay";
+	flash@0 {
+		compatible = "m25p80", "jedec,spi-nor"; /* 32MB FIXME */
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x0>;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <4>;
+		spi-max-frequency = <108000000>; /* Based on DC1 spec */
+		partition@0 { /* for testing purpose */
+			label = "qspi-fsbl-uboot";
+			reg = <0x0 0x100000>;
+		};
+		partition@100000 { /* for testing purpose */
+			label = "qspi-linux";
+			reg = <0x100000 0x500000>;
+		};
+		partition@600000 { /* for testing purpose */
+			label = "qspi-device-tree";
+			reg = <0x600000 0x20000>;
+		};
+		partition@620000 { /* for testing purpose */
+			label = "qspi-rootfs";
+			reg = <0x620000 0x5E0000>;
+		};
+	};
+};
+
 &sata {
 	status = "okay";
 	/* SATA OOB timing settings */
@@ -47,6 +78,8 @@
 	ceva,p1-comwake-params = /bits/ 8 <0x06 0x14 0x08 0x0E>;
 	ceva,p1-burst-params = /bits/ 8 <0x13 0x08 0x4A 0x06>;
 	ceva,p1-retry-params = /bits/ 16 <0x96A4 0x3FFC>;
+	phy-names = "sata-phy";
+	phys = <&lane0 PHY_TYPE_SATA 0 0 125000000>, <&lane1 PHY_TYPE_SATA 1 1 125000000>;
 };
 
 &uart0 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/xilinx/zynqmp-zc1254-revA.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/xilinx/zynqmp-zc1254-revA.dts
@@ -2,7 +2,7 @@
 /*
  * dts file for Xilinx ZynqMP ZC1254
  *
- * (C) Copyright 2015 - 2018, Xilinx, Inc.
+ * (C) Copyright 2015 - 2020, Xilinx, Inc.
  *
  * Michal Simek <michal.simek@xilinx.com>
  * Siva Durga Prasad Paladugu <sivadur@xilinx.com>
@@ -11,7 +11,7 @@
 /dts-v1/;
 
 #include "zynqmp.dtsi"
-#include "zynqmp-clk.dtsi"
+#include "zynqmp-clk-ccf.dtsi"
 
 / {
 	model = "ZynqMP ZC1254 RevA";
@@ -20,6 +20,7 @@
 	aliases {
 		serial0 = &uart0;
 		serial1 = &dcc;
+		spi0 = &qspi;
 	};
 
 	chosen {
@@ -37,6 +38,35 @@
 	status = "okay";
 };
 
+&qspi {
+	status = "okay";
+	flash@0 {
+		compatible = "m25p80", "jedec,spi-nor"; /* 32MB */
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x0>;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <4>; /* FIXME also DUAL configuration possible */
+		spi-max-frequency = <108000000>; /* Based on DC1 spec */
+		partition@0 { /* for testing purpose */
+			label = "qspi-fsbl-uboot";
+			reg = <0x0 0x100000>;
+		};
+		partition@100000 { /* for testing purpose */
+			label = "qspi-linux";
+			reg = <0x100000 0x500000>;
+		};
+		partition@600000 { /* for testing purpose */
+			label = "qspi-device-tree";
+			reg = <0x600000 0x20000>;
+		};
+		partition@620000 { /* for testing purpose */
+			label = "qspi-rootfs";
+			reg = <0x620000 0x5E0000>;
+		};
+	};
+};
+
 &uart0 {
 	status = "okay";
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm015-dc1.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm015-dc1.dts
@@ -2,7 +2,7 @@
 /*
  * dts file for Xilinx ZynqMP zc1751-xm015-dc1
  *
- * (C) Copyright 2015 - 2018, Xilinx, Inc.
+ * (C) Copyright 2015 - 2020, Xilinx, Inc.
  *
  * Michal Simek <michal.simek@xilinx.com>
  */
@@ -10,8 +10,10 @@
 /dts-v1/;
 
 #include "zynqmp.dtsi"
-#include "zynqmp-clk.dtsi"
+#include "zynqmp-clk-ccf.dtsi"
+#include <dt-bindings/phy/phy.h>
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
 
 / {
 	model = "ZynqMP zc1751-xm015-dc1 RevA";
@@ -19,11 +21,14 @@
 
 	aliases {
 		ethernet0 = &gem3;
+		gpio0 = &gpio;
 		i2c0 = &i2c1;
 		mmc0 = &sdhci0;
 		mmc1 = &sdhci1;
 		rtc0 = &rtc;
 		serial0 = &uart0;
+		spi0 = &qspi;
+		usb0 = &usb0;
 	};
 
 	chosen {
@@ -73,19 +78,31 @@
 	status = "okay";
 	phy-handle = <&phy0>;
 	phy-mode = "rgmii-id";
-	phy0: phy@0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gem3_default>;
+	phy0: ethernet-phy@0 {
 		reg = <0>;
 	};
 };
 
 &gpio {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gpio_default>;
 };
 
+&gpu {
+	status = "okay";
+};
 
 &i2c1 {
 	status = "okay";
 	clock-frequency = <400000>;
+	pinctrl-names = "default", "gpio";
+	pinctrl-0 = <&pinctrl_i2c1_default>;
+	pinctrl-1 = <&pinctrl_i2c1_gpio>;
+	scl-gpios = <&gpio 36 GPIO_ACTIVE_HIGH>;
+	sda-gpios = <&gpio 37 GPIO_ACTIVE_HIGH>;
 
 	eeprom: eeprom@55 {
 		compatible = "atmel,24c64"; /* 24AA64 */
@@ -93,6 +110,245 @@
 	};
 };
 
+&pinctrl0 {
+	status = "okay";
+	pinctrl_i2c1_default: i2c1-default {
+		mux {
+			groups = "i2c1_9_grp";
+			function = "i2c1";
+		};
+
+		conf {
+			groups = "i2c1_9_grp";
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_i2c1_gpio: i2c1-gpio {
+		mux {
+			groups = "gpio0_36_grp", "gpio0_37_grp";
+			function = "gpio0";
+		};
+
+		conf {
+			groups = "gpio0_36_grp", "gpio0_37_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_uart0_default: uart0-default {
+		mux {
+			groups = "uart0_8_grp";
+			function = "uart0";
+		};
+
+		conf {
+			groups = "uart0_8_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-rx {
+			pins = "MIO34";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO35";
+			bias-disable;
+		};
+	};
+
+	pinctrl_usb0_default: usb0-default {
+		mux {
+			groups = "usb0_0_grp";
+			function = "usb0";
+		};
+
+		conf {
+			groups = "usb0_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-rx {
+			pins = "MIO52", "MIO53", "MIO55";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO54", "MIO56", "MIO57", "MIO58", "MIO59",
+			       "MIO60", "MIO61", "MIO62", "MIO63";
+			bias-disable;
+		};
+	};
+
+	pinctrl_gem3_default: gem3-default {
+		mux {
+			function = "ethernet3";
+			groups = "ethernet3_0_grp";
+		};
+
+		conf {
+			groups = "ethernet3_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-rx {
+			pins = "MIO70", "MIO71", "MIO72", "MIO73", "MIO74",
+									"MIO75";
+			bias-high-impedance;
+			low-power-disable;
+		};
+
+		conf-tx {
+			pins = "MIO64", "MIO65", "MIO66", "MIO67", "MIO68",
+									"MIO69";
+			bias-disable;
+			low-power-enable;
+		};
+
+		mux-mdio {
+			function = "mdio3";
+			groups = "mdio3_0_grp";
+		};
+
+		conf-mdio {
+			groups = "mdio3_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+			bias-disable;
+		};
+	};
+
+	pinctrl_sdhci0_default: sdhci0-default {
+		mux {
+			groups = "sdio0_0_grp";
+			function = "sdio0";
+		};
+
+		conf {
+			groups = "sdio0_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+			bias-disable;
+		};
+
+		mux-cd {
+			groups = "sdio0_cd_0_grp";
+			function = "sdio0_cd";
+		};
+
+		conf-cd {
+			groups = "sdio0_cd_0_grp";
+			bias-high-impedance;
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		mux-wp {
+			groups = "sdio0_wp_0_grp";
+			function = "sdio0_wp";
+		};
+
+		conf-wp {
+			groups = "sdio0_wp_0_grp";
+			bias-high-impedance;
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_sdhci1_default: sdhci1-default {
+		mux {
+			groups = "sdio1_0_grp";
+			function = "sdio1";
+		};
+
+		conf {
+			groups = "sdio1_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+			bias-disable;
+		};
+
+		mux-cd {
+			groups = "sdio1_cd_0_grp";
+			function = "sdio1_cd";
+		};
+
+		conf-cd {
+			groups = "sdio1_cd_0_grp";
+			bias-high-impedance;
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		mux-wp {
+			groups = "sdio1_wp_0_grp";
+			function = "sdio1_wp";
+		};
+
+		conf-wp {
+			groups = "sdio1_wp_0_grp";
+			bias-high-impedance;
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_gpio_default: gpio-default {
+		mux {
+			function = "gpio0";
+			groups = "gpio0_38_grp";
+		};
+
+		conf {
+			groups = "gpio0_38_grp";
+			bias-disable;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+};
+
+&qspi {
+	status = "okay";
+	flash@0 {
+		compatible = "m25p80", "jedec,spi-nor"; /* Micron MT25QU512ABB8ESF */
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x0>;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <4>;
+		spi-max-frequency = <108000000>; /* Based on DC1 spec */
+		partition@0 { /* for testing purpose */
+			label = "qspi-fsbl-uboot";
+			reg = <0x0 0x100000>;
+		};
+		partition@100000 { /* for testing purpose */
+			label = "qspi-linux";
+			reg = <0x100000 0x500000>;
+		};
+		partition@600000 { /* for testing purpose */
+			label = "qspi-device-tree";
+			reg = <0x600000 0x20000>;
+		};
+		partition@620000 { /* for testing purpose */
+			label = "qspi-rootfs";
+			reg = <0x620000 0x5E0000>;
+		};
+	};
+};
+
 &rtc {
 	status = "okay";
 };
@@ -108,24 +364,79 @@
 	ceva,p1-comwake-params = /bits/ 8 <0x06 0x19 0x08 0x0E>;
 	ceva,p1-burst-params = /bits/ 8 <0x13 0x08 0x4A 0x06>;
 	ceva,p1-retry-params = /bits/ 16 <0x96A4 0x3FFC>;
+	phy-names = "sata-phy";
+	phys = <&lane3 PHY_TYPE_SATA 1 3 150000000>;
 };
 
 /* eMMC */
 &sdhci0 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sdhci0_default>;
 	bus-width = <8>;
+	xlnx,mio-bank = <0>;
 };
 
 /* SD1 with level shifter */
 &sdhci1 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sdhci1_default>;
+	/*
+	 * This property should be removed for supporting UHS mode
+	 */
+	no-1-8-v;
+	xlnx,mio-bank = <1>;
+};
+
+&serdes {
+	status = "okay";
 };
 
 &uart0 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart0_default>;
 };
 
 /* ULPI SMSC USB3320 */
 &usb0 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usb0_default>;
+};
+
+&dwc3_0 {
+	status = "okay";
+	dr_mode = "host";
+	snps,usb3_lpm_capable;
+	phy-names = "usb3-phy";
+	phys = <&lane2 PHY_TYPE_USB3 0 2 26000000>;
+};
+
+&zynqmp_dpsub {
+	status = "okay";
+	phy-names = "dp-phy0", "dp-phy1";
+	phys = <&lane1 PHY_TYPE_DP 0 0 27000000>,
+	       <&lane0 PHY_TYPE_DP 1 1 27000000>;
+};
+
+&zynqmp_dp_snd_pcm0 {
+	status = "okay";
+};
+
+&zynqmp_dp_snd_pcm1 {
+	status = "okay";
+};
+
+&zynqmp_dp_snd_card0 {
+	status = "okay";
+};
+
+&zynqmp_dp_snd_codec0 {
+	status = "okay";
+};
+
+&xlnx_dpdma {
+	status = "okay";
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm016-dc2.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm016-dc2.dts
@@ -2,7 +2,7 @@
 /*
  * dts file for Xilinx ZynqMP zc1751-xm016-dc2
  *
- * (C) Copyright 2015 - 2018, Xilinx, Inc.
+ * (C) Copyright 2015 - 2020, Xilinx, Inc.
  *
  * Michal Simek <michal.simek@xilinx.com>
  */
@@ -10,8 +10,9 @@
 /dts-v1/;
 
 #include "zynqmp.dtsi"
-#include "zynqmp-clk.dtsi"
+#include "zynqmp-clk-ccf.dtsi"
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
 
 / {
 	model = "ZynqMP zc1751-xm016-dc2 RevA";
@@ -21,12 +22,14 @@
 		can0 = &can0;
 		can1 = &can1;
 		ethernet0 = &gem2;
+		gpio0 = &gpio;
 		i2c0 = &i2c0;
 		rtc0 = &rtc;
 		serial0 = &uart0;
 		serial1 = &uart1;
 		spi0 = &spi0;
 		spi1 = &spi1;
+		usb0 = &usb1;
 	};
 
 	chosen {
@@ -42,10 +45,14 @@
 
 &can0 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_can0_default>;
 };
 
 &can1 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_can1_default>;
 };
 
 &fpd_dma_chan1 {
@@ -84,7 +91,9 @@
 	status = "okay";
 	phy-handle = <&phy0>;
 	phy-mode = "rgmii-id";
-	phy0: phy@5 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gem2_default>;
+	phy0: ethernet-phy@5 {
 		reg = <5>;
 		ti,rx-internal-delay = <0x8>;
 		ti,tx-internal-delay = <0xa>;
@@ -100,6 +109,11 @@
 &i2c0 {
 	status = "okay";
 	clock-frequency = <400000>;
+	pinctrl-names = "default", "gpio";
+	pinctrl-0 = <&pinctrl_i2c0_default>;
+	pinctrl-1 = <&pinctrl_i2c0_gpio>;
+	scl-gpios = <&gpio 6 GPIO_ACTIVE_HIGH>;
+	sda-gpios = <&gpio 7 GPIO_ACTIVE_HIGH>;
 
 	tca6416_u26: gpio@20 {
 		compatible = "ti,tca6416";
@@ -115,6 +129,353 @@
 	};
 };
 
+&nand0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_nand0_default>;
+	arasan,has-mdma;
+
+	nand@0 {
+		reg = <0x0>;
+		#address-cells = <0x2>;
+		#size-cells = <0x1>;
+
+		partition@0 {	/* for testing purpose */
+			label = "nand-fsbl-uboot";
+			reg = <0x0 0x0 0x400000>;
+		};
+		partition@1 {	/* for testing purpose */
+			label = "nand-linux";
+			reg = <0x0 0x400000 0x1400000>;
+		};
+		partition@2 {	/* for testing purpose */
+			label = "nand-device-tree";
+			reg = <0x0 0x1800000 0x400000>;
+		};
+		partition@3 {	/* for testing purpose */
+			label = "nand-rootfs";
+			reg = <0x0 0x1c00000 0x1400000>;
+		};
+		partition@4 {	/* for testing purpose */
+			label = "nand-bitstream";
+			reg = <0x0 0x3000000 0x400000>;
+		};
+		partition@5 {	/* for testing purpose */
+			label = "nand-misc";
+			reg = <0x0 0x3400000 0xfcc00000>;
+		};
+	};
+	nand@1 {
+		reg = <0x1>;
+		#address-cells = <0x2>;
+		#size-cells = <0x1>;
+
+		partition@0 {	/* for testing purpose */
+			label = "nand1-fsbl-uboot";
+			reg = <0x0 0x0 0x400000>;
+		};
+		partition@1 {	/* for testing purpose */
+			label = "nand1-linux";
+			reg = <0x0 0x400000 0x1400000>;
+		};
+		partition@2 {	/* for testing purpose */
+			label = "nand1-device-tree";
+			reg = <0x0 0x1800000 0x400000>;
+		};
+		partition@3 {	/* for testing purpose */
+			label = "nand1-rootfs";
+			reg = <0x0 0x1c00000 0x1400000>;
+		};
+		partition@4 {	/* for testing purpose */
+			label = "nand1-bitstream";
+			reg = <0x0 0x3000000 0x400000>;
+		};
+		partition@5 {	/* for testing purpose */
+			label = "nand1-misc";
+			reg = <0x0 0x3400000 0xfcc00000>;
+		};
+	};
+};
+
+&pinctrl0 {
+	status = "okay";
+	pinctrl_can0_default: can0-default {
+		mux {
+			function = "can0";
+			groups = "can0_9_grp";
+		};
+
+		conf {
+			groups = "can0_9_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-rx {
+			pins = "MIO38";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO39";
+			bias-disable;
+		};
+	};
+
+	pinctrl_can1_default: can1-default {
+		mux {
+			function = "can1";
+			groups = "can1_8_grp";
+		};
+
+		conf {
+			groups = "can1_8_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-rx {
+			pins = "MIO33";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO32";
+			bias-disable;
+		};
+	};
+
+	pinctrl_i2c0_default: i2c0-default {
+		mux {
+			groups = "i2c0_1_grp";
+			function = "i2c0";
+		};
+
+		conf {
+			groups = "i2c0_1_grp";
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_i2c0_gpio: i2c0-gpio {
+		mux {
+			groups = "gpio0_6_grp", "gpio0_7_grp";
+			function = "gpio0";
+		};
+
+		conf {
+			groups = "gpio0_6_grp", "gpio0_7_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_uart0_default: uart0-default {
+		mux {
+			groups = "uart0_10_grp";
+			function = "uart0";
+		};
+
+		conf {
+			groups = "uart0_10_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-rx {
+			pins = "MIO42";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO43";
+			bias-disable;
+		};
+	};
+
+	pinctrl_uart1_default: uart1-default {
+		mux {
+			groups = "uart1_10_grp";
+			function = "uart1";
+		};
+
+		conf {
+			groups = "uart1_10_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-rx {
+			pins = "MIO41";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO40";
+			bias-disable;
+		};
+	};
+
+	pinctrl_usb1_default: usb1-default {
+		mux {
+			groups = "usb1_0_grp";
+			function = "usb1";
+		};
+
+		conf {
+			groups = "usb1_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-rx {
+			pins = "MIO64", "MIO65", "MIO67";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO66", "MIO68", "MIO69", "MIO70", "MIO71",
+			       "MIO72", "MIO73", "MIO74", "MIO75";
+			bias-disable;
+		};
+	};
+
+	pinctrl_gem2_default: gem2-default {
+		mux {
+			function = "ethernet2";
+			groups = "ethernet2_0_grp";
+		};
+
+		conf {
+			groups = "ethernet2_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-rx {
+			pins = "MIO58", "MIO59", "MIO60", "MIO61", "MIO62",
+									"MIO63";
+			bias-high-impedance;
+			low-power-disable;
+		};
+
+		conf-tx {
+			pins = "MIO52", "MIO53", "MIO54", "MIO55", "MIO56",
+									"MIO57";
+			bias-disable;
+			low-power-enable;
+		};
+
+		mux-mdio {
+			function = "mdio2";
+			groups = "mdio2_0_grp";
+		};
+
+		conf-mdio {
+			groups = "mdio2_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+			bias-disable;
+		};
+	};
+
+	pinctrl_nand0_default: nand0-default {
+		mux {
+			groups = "nand0_0_grp";
+			function = "nand0";
+		};
+
+		conf {
+			groups = "nand0_0_grp";
+			bias-pull-up;
+		};
+
+		mux-ce {
+			groups = "nand0_ce_0_grp";
+			function = "nand0_ce";
+		};
+
+		conf-ce {
+			groups = "nand0_ce_0_grp";
+			bias-pull-up;
+		};
+
+		mux-rb {
+			groups = "nand0_rb_0_grp";
+			function = "nand0_rb";
+		};
+
+		conf-rb {
+			groups = "nand0_rb_0_grp";
+			bias-pull-up;
+		};
+
+		mux-dqs {
+			groups = "nand0_dqs_0_grp";
+			function = "nand0_dqs";
+		};
+
+		conf-dqs {
+			groups = "nand0_dqs_0_grp";
+			bias-pull-up;
+		};
+	};
+
+	pinctrl_spi0_default: spi0-default {
+		mux {
+			groups = "spi0_0_grp";
+			function = "spi0";
+		};
+
+		conf {
+			groups = "spi0_0_grp";
+			bias-disable;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		mux-cs {
+			groups = "spi0_ss_0_grp", "spi0_ss_1_grp",
+							"spi0_ss_2_grp";
+			function = "spi0_ss";
+		};
+
+		conf-cs {
+			groups = "spi0_ss_0_grp", "spi0_ss_1_grp",
+							"spi0_ss_2_grp";
+			bias-disable;
+		};
+	};
+
+	pinctrl_spi1_default: spi1-default {
+		mux {
+			groups = "spi1_3_grp";
+			function = "spi1";
+		};
+
+		conf {
+			groups = "spi1_3_grp";
+			bias-disable;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		mux-cs {
+			groups = "spi1_ss_9_grp", "spi1_ss_10_grp",
+							"spi1_ss_11_grp";
+			function = "spi1_ss";
+		};
+
+		conf-cs {
+			groups = "spi1_ss_9_grp", "spi1_ss_10_grp",
+							"spi1_ss_11_grp";
+			bias-disable;
+		};
+	};
+};
+
 &rtc {
 	status = "okay";
 };
@@ -122,8 +483,10 @@
 &spi0 {
 	status = "okay";
 	num-cs = <1>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_spi0_default>;
 
-	spi0_flash0: flash0@0 {
+	spi0_flash0: flash@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
 		compatible = "sst,sst25wf080", "jedec,spi-nor";
@@ -131,7 +494,7 @@
 		reg = <0>;
 
 		partition@0 {
-			label = "data";
+			label = "spi0-data";
 			reg = <0x0 0x100000>;
 		};
 	};
@@ -140,8 +503,10 @@
 &spi1 {
 	status = "okay";
 	num-cs = <1>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_spi1_default>;
 
-	spi1_flash0: flash0@0 {
+	spi1_flash0: flash@0 {
 		#address-cells = <1>;
 		#size-cells = <1>;
 		compatible = "atmel,at45db041e", "atmel,at45", "atmel,dataflash";
@@ -149,7 +514,7 @@
 		reg = <0>;
 
 		partition@0 {
-			label = "data";
+			label = "spi1-data";
 			reg = <0x0 0x84000>;
 		};
 	};
@@ -158,12 +523,23 @@
 /* ULPI SMSC USB3320 */
 &usb1 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usb1_default>;
+};
+
+&dwc3_1 {
+	status = "okay";
+	dr_mode = "host";
 };
 
 &uart0 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart0_default>;
 };
 
 &uart1 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1_default>;
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm017-dc3.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm017-dc3.dts
@@ -2,7 +2,7 @@
 /*
  * dts file for Xilinx ZynqMP zc1751-xm017-dc3
  *
- * (C) Copyright 2016 - 2018, Xilinx, Inc.
+ * (C) Copyright 2016 - 2020, Xilinx, Inc.
  *
  * Michal Simek <michal.simek@xilinx.com>
  */
@@ -10,7 +10,7 @@
 /dts-v1/;
 
 #include "zynqmp.dtsi"
-#include "zynqmp-clk.dtsi"
+#include "zynqmp-clk-ccf.dtsi"
 
 / {
 	model = "ZynqMP zc1751-xm017-dc3 RevA";
@@ -18,12 +18,15 @@
 
 	aliases {
 		ethernet0 = &gem0;
+		gpio0 = &gpio;
 		i2c0 = &i2c0;
 		i2c1 = &i2c1;
 		mmc0 = &sdhci1;
 		rtc0 = &rtc;
 		serial0 = &uart0;
 		serial1 = &uart1;
+		usb0 = &usb0;
+		usb1 = &usb1;
 	};
 
 	chosen {
@@ -73,7 +76,7 @@
 	status = "okay";
 	phy-handle = <&phy0>;
 	phy-mode = "rgmii-id";
-	phy0: phy@0 { /* VSC8211 */
+	phy0: ethernet-phy@0 { /* VSC8211 */
 		reg = <0>;
 	};
 };
@@ -107,6 +110,63 @@
 	clock-frequency = <400000>;
 };
 
+/* MT29F64G08AECDBJ4-6 */
+&nand0 {
+	status = "okay";
+	arasan,has-mdma;
+	num-cs = <2>;
+
+	partition@0 {	/* for testing purpose */
+		label = "nand-fsbl-uboot";
+		reg = <0x0 0x0 0x400000>;
+	};
+	partition@1 {	/* for testing purpose */
+		label = "nand-linux";
+		reg = <0x0 0x400000 0x1400000>;
+	};
+	partition@2 {	/* for testing purpose */
+		label = "nand-device-tree";
+		reg = <0x0 0x1800000 0x400000>;
+	};
+	partition@3 {	/* for testing purpose */
+		label = "nand-rootfs";
+		reg = <0x0 0x1C00000 0x1400000>;
+	};
+	partition@4 {	/* for testing purpose */
+		label = "nand-bitstream";
+		reg = <0x0 0x3000000 0x400000>;
+	};
+	partition@5 {	/* for testing purpose */
+		label = "nand-misc";
+		reg = <0x0 0x3400000 0xFCC00000>;
+	};
+
+	partition@6 {	/* for testing purpose */
+		label = "nand1-fsbl-uboot";
+		reg = <0x1 0x0 0x400000>;
+	};
+	partition@7 {	/* for testing purpose */
+		label = "nand1-linux";
+		reg = <0x1 0x400000 0x1400000>;
+	};
+	partition@8 {	/* for testing purpose */
+		label = "nand1-device-tree";
+		reg = <0x1 0x1800000 0x400000>;
+	};
+	partition@9 {	/* for testing purpose */
+		label = "nand1-rootfs";
+		reg = <0x1 0x1C00000 0x1400000>;
+	};
+	partition@10 {	/* for testing purpose */
+		label = "nand1-bitstream";
+		reg = <0x1 0x3000000 0x400000>;
+	};
+	partition@11 {	/* for testing purpose */
+		label = "nand1-misc";
+		reg = <0x1 0x3400000 0xFCC00000>;
+	};
+};
+
 &rtc {
 	status = "okay";
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm018-dc4.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm018-dc4.dts
@@ -2,7 +2,7 @@
 /*
  * dts file for Xilinx ZynqMP zc1751-xm018-dc4
  *
- * (C) Copyright 2015 - 2018, Xilinx, Inc.
+ * (C) Copyright 2015 - 2020, Xilinx, Inc.
  *
  * Michal Simek <michal.simek@xilinx.com>
  */
@@ -10,22 +10,26 @@
 /dts-v1/;
 
 #include "zynqmp.dtsi"
-#include "zynqmp-clk.dtsi"
+#include "zynqmp-clk-ccf.dtsi"
 
 / {
 	model = "ZynqMP zc1751-xm018-dc4";
 	compatible = "xlnx,zynqmp-zc1751", "xlnx,zynqmp";
 
 	aliases {
+		can0 = &can0;
+		can1 = &can1;
 		ethernet0 = &gem0;
 		ethernet1 = &gem1;
 		ethernet2 = &gem2;
 		ethernet3 = &gem3;
+		gpio0 = &gpio;
 		i2c0 = &i2c0;
 		i2c1 = &i2c1;
 		rtc0 = &rtc;
 		serial0 = &uart0;
 		serial1 = &uart1;
+		spi0 = &qspi;
 	};
 
 	chosen {
@@ -111,6 +115,14 @@
 	status = "okay";
 };
 
+&zynqmp_dpsub {
+	status = "okay";
+};
+
+&xlnx_dpdma {
+	status = "okay";
+};
+
 &gem0 {
 	status = "okay";
 	phy-mode = "rgmii-id";
@@ -151,6 +163,10 @@
 	status = "okay";
 };
 
+&gpu {
+	status = "okay";
+};
+
 &i2c0 {
 	clock-frequency = <400000>;
 	status = "okay";
@@ -161,6 +177,35 @@
 	status = "okay";
 };
 
+&qspi {
+	status = "okay";
+	flash@0 {
+		compatible = "m25p80", "jedec,spi-nor"; /* 32MB */
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x0>;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <4>; /* also DUAL configuration possible */
+		spi-max-frequency = <108000000>; /* Based on DC1 spec */
+		partition@0 { /* for testing purpose */
+			label = "qspi-fsbl-uboot";
+			reg = <0x0 0x100000>;
+		};
+		partition@100000 { /* for testing purpose */
+			label = "qspi-linux";
+			reg = <0x100000 0x500000>;
+		};
+		partition@600000 { /* for testing purpose */
+			label = "qspi-device-tree";
+			reg = <0x600000 0x20000>;
+		};
+		partition@620000 { /* for testing purpose */
+			label = "qspi-rootfs";
+			reg = <0x620000 0x5E0000>;
+		};
+	};
+};
+
 &rtc {
 	status = "okay";
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm019-dc5.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/xilinx/zynqmp-zc1751-xm019-dc5.dts
@@ -2,7 +2,7 @@
 /*
  * dts file for Xilinx ZynqMP zc1751-xm019-dc5
  *
- * (C) Copyright 2015 - 2018, Xilinx, Inc.
+ * (C) Copyright 2015 - 2020, Xilinx, Inc.
  *
  * Siva Durga Prasad <siva.durga.paladugu@xilinx.com>
  * Michal Simek <michal.simek@xilinx.com>
@@ -11,8 +11,9 @@
 /dts-v1/;
 
 #include "zynqmp.dtsi"
-#include "zynqmp-clk.dtsi"
+#include "zynqmp-clk-ccf.dtsi"
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
 
 / {
 	model = "ZynqMP zc1751-xm019-dc5 RevA";
@@ -20,6 +21,7 @@
 
 	aliases {
 		ethernet0 = &gem1;
+		gpio0 = &gpio;
 		i2c0 = &i2c0;
 		i2c1 = &i2c1;
 		mmc0 = &sdhci0;
@@ -74,7 +76,9 @@
 	status = "okay";
 	phy-handle = <&phy0>;
 	phy-mode = "rgmii-id";
-	phy0: phy@0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gem1_default>;
+	phy0: ethernet-phy@0 {
 		reg = <0>;
 	};
 };
@@ -85,41 +89,366 @@
 
 &i2c0 {
 	status = "okay";
+	pinctrl-names = "default", "gpio";
+	pinctrl-0 = <&pinctrl_i2c0_default>;
+	pinctrl-1 = <&pinctrl_i2c0_gpio>;
+	scl-gpios = <&gpio 74 GPIO_ACTIVE_HIGH>;
+	sda-gpios = <&gpio 75 GPIO_ACTIVE_HIGH>;
 };
 
 &i2c1 {
 	status = "okay";
+	pinctrl-names = "default", "gpio";
+	pinctrl-0 = <&pinctrl_i2c1_default>;
+	pinctrl-1 = <&pinctrl_i2c1_gpio>;
+	scl-gpios = <&gpio 76 GPIO_ACTIVE_HIGH>;
+	sda-gpios = <&gpio 77 GPIO_ACTIVE_HIGH>;
+
+};
+
+&pinctrl0 {
+	status = "okay";
+	pinctrl_i2c0_default: i2c0-default {
+		mux {
+			groups = "i2c0_18_grp";
+			function = "i2c0";
+		};
+
+		conf {
+			groups = "i2c0_18_grp";
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_i2c0_gpio: i2c0-gpio {
+		mux {
+			groups = "gpio0_74_grp", "gpio0_75_grp";
+			function = "gpio0";
+		};
+
+		conf {
+			groups = "gpio0_74_grp", "gpio0_75_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_i2c1_default: i2c1-default {
+		mux {
+			groups = "i2c1_19_grp";
+			function = "i2c1";
+		};
+
+		conf {
+			groups = "i2c1_19_grp";
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_i2c1_gpio: i2c1-gpio {
+		mux {
+			groups = "gpio0_76_grp", "gpio0_77_grp";
+			function = "gpio0";
+		};
+
+		conf {
+			groups = "gpio0_76_grp", "gpio0_77_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_uart0_default: uart0-default {
+		mux {
+			groups = "uart0_17_grp";
+			function = "uart0";
+		};
+
+		conf {
+			groups = "uart0_17_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-rx {
+			pins = "MIO70";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO71";
+			bias-disable;
+		};
+	};
+
+	pinctrl_uart1_default: uart1-default {
+		mux {
+			groups = "uart1_18_grp";
+			function = "uart1";
+		};
+
+		conf {
+			groups = "uart1_18_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-rx {
+			pins = "MIO73";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO72";
+			bias-disable;
+		};
+	};
+
+	pinctrl_gem1_default: gem1-default {
+		mux {
+			function = "ethernet1";
+			groups = "ethernet1_0_grp";
+		};
+
+		conf {
+			groups = "ethernet1_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-rx {
+			pins = "MIO44", "MIO45", "MIO46", "MIO47", "MIO48",
+									"MIO49";
+			bias-high-impedance;
+			low-power-disable;
+		};
+
+		conf-tx {
+			pins = "MIO38", "MIO39", "MIO40", "MIO41", "MIO42",
+									"MIO43";
+			bias-disable;
+			low-power-enable;
+		};
+
+		mux-mdio {
+			function = "mdio1";
+			groups = "mdio1_0_grp";
+		};
+
+		conf-mdio {
+			groups = "mdio1_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+			bias-disable;
+		};
+	};
+
+	pinctrl_sdhci0_default: sdhci0-default {
+		mux {
+			groups = "sdio0_0_grp";
+			function = "sdio0";
+		};
+
+		conf {
+			groups = "sdio0_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+			bias-disable;
+		};
+
+		mux-cd {
+			groups = "sdio0_cd_0_grp";
+			function = "sdio0_cd";
+		};
+
+		conf-cd {
+			groups = "sdio0_cd_0_grp";
+			bias-high-impedance;
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		mux-wp {
+			groups = "sdio0_wp_0_grp";
+			function = "sdio0_wp";
+		};
+
+		conf-wp {
+			groups = "sdio0_wp_0_grp";
+			bias-high-impedance;
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_watchdog0_default: watchdog0-default {
+		mux-clk {
+			groups = "swdt0_clk_1_grp";
+			function = "swdt0_clk";
+		};
+
+		conf-clk {
+			groups = "swdt0_clk_1_grp";
+			bias-pull-up;
+		};
+
+		mux-rst {
+			groups = "swdt0_rst_1_grp";
+			function = "swdt0_rst";
+		};
+
+		conf-rst {
+			groups = "swdt0_rst_1_grp";
+			bias-disable;
+			slew-rate = <SLEW_RATE_SLOW>;
+		};
+	};
+
+	pinctrl_ttc0_default: ttc0-default {
+		mux-clk {
+			groups = "ttc0_clk_0_grp";
+			function = "ttc0_clk";
+		};
+
+		conf-clk {
+			groups = "ttc0_clk_0_grp";
+			bias-pull-up;
+		};
+
+		mux-wav {
+			groups = "ttc0_wav_0_grp";
+			function = "ttc0_wav";
+		};
+
+		conf-wav {
+			groups = "ttc0_wav_0_grp";
+			bias-disable;
+			slew-rate = <SLEW_RATE_SLOW>;
+		};
+	};
+
+	pinctrl_ttc1_default: ttc1-default {
+		mux-clk {
+			groups = "ttc1_clk_0_grp";
+			function = "ttc1_clk";
+		};
+
+		conf-clk {
+			groups = "ttc1_clk_0_grp";
+			bias-pull-up;
+		};
+
+		mux-wav {
+			groups = "ttc1_wav_0_grp";
+			function = "ttc1_wav";
+		};
+
+		conf-wav {
+			groups = "ttc1_wav_0_grp";
+			bias-disable;
+			slew-rate = <SLEW_RATE_SLOW>;
+		};
+	};
+
+	pinctrl_ttc2_default: ttc2-default {
+		mux-clk {
+			groups = "ttc2_clk_0_grp";
+			function = "ttc2_clk";
+		};
+
+		conf-clk {
+			groups = "ttc2_clk_0_grp";
+			bias-pull-up;
+		};
+
+		mux-wav {
+			groups = "ttc2_wav_0_grp";
+			function = "ttc2_wav";
+		};
+
+		conf-wav {
+			groups = "ttc2_wav_0_grp";
+			bias-disable;
+			slew-rate = <SLEW_RATE_SLOW>;
+		};
+	};
+
+	pinctrl_ttc3_default: ttc3-default {
+		mux-clk {
+			groups = "ttc3_clk_0_grp";
+			function = "ttc3_clk";
+		};
+
+		conf-clk {
+			groups = "ttc3_clk_0_grp";
+			bias-pull-up;
+		};
+
+		mux-wav {
+			groups = "ttc3_wav_0_grp";
+			function = "ttc3_wav";
+		};
+
+		conf-wav {
+			groups = "ttc3_wav_0_grp";
+			bias-disable;
+			slew-rate = <SLEW_RATE_SLOW>;
+		};
+	};
 };
 
 &sdhci0 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sdhci0_default>;
 	no-1-8-v;
+	xlnx,mio-bank = <0>;
 };
 
 &ttc0 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ttc0_default>;
 };
 
 &ttc1 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ttc1_default>;
 };
 
 &ttc2 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ttc2_default>;
 };
 
 &ttc3 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_ttc3_default>;
 };
 
 &uart0 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart0_default>;
 };
 
 &uart1 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1_default>;
 };
 
 &watchdog0 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_watchdog0_default>;
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/xilinx/zynqmp-zcu100-revC.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/xilinx/zynqmp-zcu100-revC.dts
@@ -2,7 +2,7 @@
 /*
  * dts file for Xilinx ZynqMP ZCU100 revC
  *
- * (C) Copyright 2016 - 2018, Xilinx, Inc.
+ * (C) Copyright 2016 - 2020, Xilinx, Inc.
  *
  * Michal Simek <michal.simek@xilinx.com>
  * Nathalie Chan King Choy
@@ -11,16 +11,19 @@
 /dts-v1/;
 
 #include "zynqmp.dtsi"
-#include "zynqmp-clk.dtsi"
+#include "zynqmp-clk-ccf.dtsi"
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
+#include <dt-bindings/phy/phy.h>
 
 / {
 	model = "ZynqMP ZCU100 RevC";
 	compatible = "xlnx,zynqmp-zcu100-revC", "xlnx,zynqmp-zcu100", "xlnx,zynqmp";
 
 	aliases {
+		gpio0 = &gpio;
 		i2c0 = &i2c1;
 		rtc0 = &rtc;
 		serial0 = &uart1;
@@ -28,6 +31,8 @@
 		serial2 = &dcc;
 		spi0 = &spi0;
 		spi1 = &spi1;
+		usb0 = &usb0;
+		usb1 = &usb1;
 		mmc0 = &sdhci0;
 		mmc1 = &sdhci1;
 	};
@@ -54,6 +59,15 @@
 		};
 	};
 
+	iio-hwmon {
+		compatible = "iio-hwmon";
+		io-channels = <&xilinx_ams 0>, <&xilinx_ams 1>, <&xilinx_ams 2>,
+			      <&xilinx_ams 3>, <&xilinx_ams 4>, <&xilinx_ams 5>,
+			      <&xilinx_ams 6>, <&xilinx_ams 7>, <&xilinx_ams 8>,
+			      <&xilinx_ams 9>, <&xilinx_ams 10>,
+			      <&xilinx_ams 11>, <&xilinx_ams 12>;
+	};
+
 	leds {
 		compatible = "gpio-leds";
 		ds2 {
@@ -89,6 +103,15 @@
 		};
 	};
 
+	ltc2954: ltc2954 { /* U7 */
+		compatible = "lltc,ltc2954", "lltc,ltc2952";
+		status = "disabled";
+		trigger-gpios = <&gpio 26 GPIO_ACTIVE_LOW>; /* INT line - input */
+		/* If there is HW watchdog on mezzanine this signal should be connected there */
+		watchdog-gpios = <&gpio 35 GPIO_ACTIVE_HIGH>; /* MIO on PAD */
+		kill-gpios = <&gpio 34 GPIO_ACTIVE_LOW>; /* KILL signal - output */
+	};
+
 	wmmcsdio_fixed: fixedregulator-mmcsdio {
 		compatible = "regulator-fixed";
 		regulator-name = "wmmcsdio_fixed";
@@ -103,6 +126,11 @@
 		reset-gpios = <&gpio 7 GPIO_ACTIVE_LOW>; /* WIFI_EN */
 		post-power-on-delay-ms = <10>;
 	};
+
+	ina226 {
+		compatible = "iio-hwmon";
+		io-channels = <&u35 0>, <&u35 1>, <&u35 2>, <&u35 3>;
+	};
 };
 
 &dcc {
@@ -140,8 +168,17 @@
 			  "", "", "", "";
 };
 
+&gpu {
+	status = "okay";
+};
+
 &i2c1 {
 	status = "okay";
+	pinctrl-names = "default", "gpio";
+	pinctrl-0 = <&pinctrl_i2c1_default>;
+	pinctrl-1 = <&pinctrl_i2c1_gpio>;
+	scl-gpios = <&gpio 4 GPIO_ACTIVE_HIGH>;
+	sda-gpios = <&gpio 5 GPIO_ACTIVE_HIGH>;
 	clock-frequency = <100000>;
 	i2c-mux@75 { /* u11 */
 		compatible = "nxp,pca9548";
@@ -191,8 +228,9 @@
 			#size-cells = <0>;
 			reg = <5>;
 			/* PS_PMBUS */
-			ina226@40 { /* u35 */
+			u35: ina226@40 { /* u35 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
 				reg = <0x40>;
 				shunt-resistor = <10000>;
 				/* MIO31 is alert which should be routed to PMUFW */
@@ -218,6 +256,221 @@
 	};
 };
 
+&pinctrl0 {
+	status = "okay";
+	pinctrl_i2c1_default: i2c1-default {
+		mux {
+			groups = "i2c1_1_grp";
+			function = "i2c1";
+		};
+
+		conf {
+			groups = "i2c1_1_grp";
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_i2c1_gpio: i2c1-gpio {
+		mux {
+			groups = "gpio0_4_grp", "gpio0_5_grp";
+			function = "gpio0";
+		};
+
+		conf {
+			groups = "gpio0_4_grp", "gpio0_5_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_sdhci0_default: sdhci0-default {
+		mux {
+			groups = "sdio0_3_grp";
+			function = "sdio0";
+		};
+
+		conf {
+			groups = "sdio0_3_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+			bias-disable;
+		};
+
+		mux-cd {
+			groups = "sdio0_cd_0_grp";
+			function = "sdio0_cd";
+		};
+
+		conf-cd {
+			groups = "sdio0_cd_0_grp";
+			bias-high-impedance;
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_sdhci1_default: sdhci1-default {
+		mux {
+			groups = "sdio1_2_grp";
+			function = "sdio1";
+		};
+
+		conf {
+			groups = "sdio1_2_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+			bias-disable;
+		};
+	};
+
+	pinctrl_spi0_default: spi0-default {
+		mux {
+			groups = "spi0_3_grp";
+			function = "spi0";
+		};
+
+		conf {
+			groups = "spi0_3_grp";
+			bias-disable;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		mux-cs {
+			groups = "spi0_ss_9_grp";
+			function = "spi0_ss";
+		};
+
+		conf-cs {
+			groups = "spi0_ss_9_grp";
+			bias-disable;
+		};
+
+	};
+
+	pinctrl_spi1_default: spi1-default {
+		mux {
+			groups = "spi1_0_grp";
+			function = "spi1";
+		};
+
+		conf {
+			groups = "spi1_0_grp";
+			bias-disable;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		mux-cs {
+			groups = "spi1_ss_0_grp";
+			function = "spi1_ss";
+		};
+
+		conf-cs {
+			groups = "spi1_ss_0_grp";
+			bias-disable;
+		};
+
+	};
+
+	pinctrl_uart0_default: uart0-default {
+		mux {
+			groups = "uart0_0_grp";
+			function = "uart0";
+		};
+
+		conf {
+			groups = "uart0_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-rx {
+			pins = "MIO3";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO2";
+			bias-disable;
+		};
+	};
+
+	pinctrl_uart1_default: uart1-default {
+		mux {
+			groups = "uart1_0_grp";
+			function = "uart1";
+		};
+
+		conf {
+			groups = "uart1_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-rx {
+			pins = "MIO1";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO0";
+			bias-disable;
+		};
+	};
+
+	pinctrl_usb0_default: usb0-default {
+		mux {
+			groups = "usb0_0_grp";
+			function = "usb0";
+		};
+
+		conf {
+			groups = "usb0_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-rx {
+			pins = "MIO52", "MIO53", "MIO55";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO54", "MIO56", "MIO57", "MIO58", "MIO59",
+			       "MIO60", "MIO61", "MIO62", "MIO63";
+			bias-disable;
+		};
+	};
+
+	pinctrl_usb1_default: usb1-default {
+		mux {
+			groups = "usb1_0_grp";
+			function = "usb1";
+		};
+
+		conf {
+			groups = "usb1_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-rx {
+			pins = "MIO64", "MIO65", "MIO67";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO66", "MIO68", "MIO69", "MIO70", "MIO71",
+			       "MIO72", "MIO73", "MIO74", "MIO75";
+			bias-disable;
+		};
+	};
+};
+
 &rtc {
 	status = "okay";
 };
@@ -226,13 +479,18 @@
 &sdhci0 {
 	status = "okay";
 	no-1-8-v;
-	broken-cd; /* CD has to be enabled by default */
 	disable-wp;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sdhci0_default>;
+	xlnx,mio-bank = <0>;
 };
 
 &sdhci1 {
 	status = "okay";
 	bus-width = <0x4>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sdhci1_default>;
+	xlnx,mio-bank = <0>;
 	non-removable;
 	disable-wp;
 	cap-power-off-card;
@@ -248,18 +506,30 @@
 	};
 };
 
+&serdes {
+	status = "okay";
+};
+
 &spi0 { /* Low Speed connector */
 	status = "okay";
 	label = "LS-SPI0";
+	num-cs = <1>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_spi0_default>;
 };
 
 &spi1 { /* High Speed connector */
 	status = "okay";
 	label = "HS-SPI1";
+	num-cs = <1>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_spi1_default>;
 };
 
 &uart0 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart0_default>;
 	bluetooth {
 		compatible = "ti,wl1831-st";
 		enable-gpios = <&gpio 8 GPIO_ACTIVE_HIGH>;
@@ -268,19 +538,76 @@
 
 &uart1 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1_default>;
 
 };
 
 /* ULPI SMSC USB3320 */
 &usb0 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usb0_default>;
+};
+
+&dwc3_0 {
+	status = "okay";
+	dr_mode = "peripheral";
+	phy-names = "usb3-phy";
+	phys = <&lane2 PHY_TYPE_USB3 0 0 26000000>;
+	maximum-speed = "super-speed";
 };
 
 /* ULPI SMSC USB3320 */
 &usb1 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usb1_default>;
+};
+
+&dwc3_1 {
+	status = "okay";
+	dr_mode = "host";
+	phy-names = "usb3-phy";
+	phys = <&lane3 PHY_TYPE_USB3 1 0 26000000>;
+	maximum-speed = "super-speed";
 };
 
 &watchdog0 {
 	status = "okay";
 };
+
+&zynqmp_dpsub {
+	status = "okay";
+	phy-names = "dp-phy0", "dp-phy1";
+	phys = <&lane1 PHY_TYPE_DP 0 1 27000000>,
+	       <&lane0 PHY_TYPE_DP 1 1 27000000>;
+};
+
+&zynqmp_dp_snd_pcm0 {
+	status = "okay";
+};
+
+&zynqmp_dp_snd_pcm1 {
+	status = "okay";
+};
+
+&zynqmp_dp_snd_card0 {
+	status = "okay";
+};
+
+&zynqmp_dp_snd_codec0 {
+	status = "okay";
+};
+
+&xlnx_dpdma {
+	status = "okay";
+};
+
+&xilinx_ams {
+	status = "okay";
+};
+
+&ams_ps {
+	status = "okay";
+};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev1.0.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev1.0.dts
@@ -2,7 +2,7 @@
 /*
  * dts file for Xilinx ZynqMP ZCU102 Rev1.0
  *
- * (C) Copyright 2016 - 2018, Xilinx, Inc.
+ * (C) Copyright 2016 - 2020, Xilinx, Inc.
  *
  * Michal Simek <michal.simek@xilinx.com>
  */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-revA.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-revA.dts
@@ -2,7 +2,7 @@
 /*
  * dts file for Xilinx ZynqMP ZCU102 RevA
  *
- * (C) Copyright 2015 - 2018, Xilinx, Inc.
+ * (C) Copyright 2015 - 2020, Xilinx, Inc.
  *
  * Michal Simek <michal.simek@xilinx.com>
  */
@@ -10,9 +10,11 @@
 /dts-v1/;
 
 #include "zynqmp.dtsi"
-#include "zynqmp-clk.dtsi"
+#include "zynqmp-clk-ccf.dtsi"
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
+#include <dt-bindings/phy/phy.h>
 
 / {
 	model = "ZynqMP ZCU102 RevA";
@@ -20,6 +22,7 @@
 
 	aliases {
 		ethernet0 = &gem3;
+		gpio0 = &gpio;
 		i2c0 = &i2c0;
 		i2c1 = &i2c1;
 		mmc0 = &sdhci1;
@@ -27,11 +30,14 @@
 		serial0 = &uart0;
 		serial1 = &uart1;
 		serial2 = &dcc;
+		spi0 = &qspi;
+		usb0 = &usb0;
 	};
 
 	chosen {
 		bootargs = "earlycon";
 		stdout-path = "serial0:115200n8";
+		xlnx,eeprom = &eeprom;
 	};
 
 	memory@0 {
@@ -59,10 +65,85 @@
 			linux,default-trigger = "heartbeat";
 		};
 	};
+
+	ina226-u76 {
+		compatible = "iio-hwmon";
+		io-channels = <&u76 0>, <&u76 1>, <&u76 2>, <&u76 3>;
+	};
+	ina226-u77 {
+		compatible = "iio-hwmon";
+		io-channels = <&u77 0>, <&u77 1>, <&u77 2>, <&u77 3>;
+	};
+	ina226-u78 {
+		compatible = "iio-hwmon";
+		io-channels = <&u78 0>, <&u78 1>, <&u78 2>, <&u78 3>;
+	};
+	ina226-u87 {
+		compatible = "iio-hwmon";
+		io-channels = <&u87 0>, <&u87 1>, <&u87 2>, <&u87 3>;
+	};
+	ina226-u85 {
+		compatible = "iio-hwmon";
+		io-channels = <&u85 0>, <&u85 1>, <&u85 2>, <&u85 3>;
+	};
+	ina226-u86 {
+		compatible = "iio-hwmon";
+		io-channels = <&u86 0>, <&u86 1>, <&u86 2>, <&u86 3>;
+	};
+	ina226-u93 {
+		compatible = "iio-hwmon";
+		io-channels = <&u93 0>, <&u93 1>, <&u93 2>, <&u93 3>;
+	};
+	ina226-u88 {
+		compatible = "iio-hwmon";
+		io-channels = <&u88 0>, <&u88 1>, <&u88 2>, <&u88 3>;
+	};
+	ina226-u15 {
+		compatible = "iio-hwmon";
+		io-channels = <&u15 0>, <&u15 1>, <&u15 2>, <&u15 3>;
+	};
+	ina226-u92 {
+		compatible = "iio-hwmon";
+		io-channels = <&u92 0>, <&u92 1>, <&u92 2>, <&u92 3>;
+	};
+	ina226-u79 {
+		compatible = "iio-hwmon";
+		io-channels = <&u79 0>, <&u79 1>, <&u79 2>, <&u79 3>;
+	};
+	ina226-u81 {
+		compatible = "iio-hwmon";
+		io-channels = <&u81 0>, <&u81 1>, <&u81 2>, <&u81 3>;
+	};
+	ina226-u80 {
+		compatible = "iio-hwmon";
+		io-channels = <&u80 0>, <&u80 1>, <&u80 2>, <&u80 3>;
+	};
+	ina226-u84 {
+		compatible = "iio-hwmon";
+		io-channels = <&u84 0>, <&u84 1>, <&u84 2>, <&u84 3>;
+	};
+	ina226-u16 {
+		compatible = "iio-hwmon";
+		io-channels = <&u16 0>, <&u16 1>, <&u16 2>, <&u16 3>;
+	};
+	ina226-u65 {
+		compatible = "iio-hwmon";
+		io-channels = <&u65 0>, <&u65 1>, <&u65 2>, <&u65 3>;
+	};
+	ina226-u74 {
+		compatible = "iio-hwmon";
+		io-channels = <&u74 0>, <&u74 1>, <&u74 2>, <&u74 3>;
+	};
+	ina226-u75 {
+		compatible = "iio-hwmon";
+		io-channels = <&u75 0>, <&u75 1>, <&u75 2>, <&u75 3>;
+	};
 };
 
 &can1 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_can1_default>;
 };
 
 &dcc {
@@ -105,41 +186,45 @@
 	status = "okay";
 	phy-handle = <&phy0>;
 	phy-mode = "rgmii-id";
-	phy0: phy@21 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gem3_default>;
+	phy0: ethernet-phy@21 {
 		reg = <21>;
 		ti,rx-internal-delay = <0x8>;
 		ti,tx-internal-delay = <0xa>;
 		ti,fifo-depth = <0x1>;
 		ti,dp83867-rxctrl-strap-quirk;
+		/* reset-gpios = <&tca6416_u97 6 GPIO_ACTIVE_LOW>; */
 	};
 };
 
 &gpio {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gpio_default>;
+};
+
+&gpu {
+	status = "okay";
 };
 
 &i2c0 {
 	status = "okay";
 	clock-frequency = <400000>;
+	pinctrl-names = "default", "gpio";
+	pinctrl-0 = <&pinctrl_i2c0_default>;
+	pinctrl-1 = <&pinctrl_i2c0_gpio>;
+	scl-gpios = <&gpio 14 GPIO_ACTIVE_HIGH>;
+	sda-gpios = <&gpio 15 GPIO_ACTIVE_HIGH>;
 
 	tca6416_u97: gpio@20 {
 		compatible = "ti,tca6416";
 		reg = <0x20>;
-		gpio-controller;
+		gpio-controller; /* IRQ not connected */
 		#gpio-cells = <2>;
-		/*
-		 * IRQ not connected
-		 * Lines:
-		 * 0 - PS_GTR_LAN_SEL0
-		 * 1 - PS_GTR_LAN_SEL1
-		 * 2 - PS_GTR_LAN_SEL2
-		 * 3 - PS_GTR_LAN_SEL3
-		 * 4 - PCI_CLK_DIR_SEL
-		 * 5 - IIC_MUX_RESET_B
-		 * 6 - GEM3_EXP_RESET_B
-		 * 7, 10 - 17 - not connected
-		 */
-
+		gpio-line-names = "PS_GTR_LAN_SEL0", "PS_GTR_LAN_SEL1", "PS_GTR_LAN_SEL2", "PS_GTR_LAN_SEL3",
+				"PCI_CLK_DIR_SEL", "IIC_MUX_RESET_B", "GEM3_EXP_RESET_B",
+				"", "", "", "", "", "", "", "", "";
 		gtr-sel0 {
 			gpio-hog;
 			gpios = <0 0>;
@@ -169,27 +254,12 @@
 	tca6416_u61: gpio@21 {
 		compatible = "ti,tca6416";
 		reg = <0x21>;
-		gpio-controller;
+		gpio-controller; /* IRQ not connected */
 		#gpio-cells = <2>;
-		/*
-		 * IRQ not connected
-		 * Lines:
-		 * 0 - VCCPSPLL_EN
-		 * 1 - MGTRAVCC_EN
-		 * 2 - MGTRAVTT_EN
-		 * 3 - VCCPSDDRPLL_EN
-		 * 4 - MIO26_PMU_INPUT_LS
-		 * 5 - PL_PMBUS_ALERT
-		 * 6 - PS_PMBUS_ALERT
-		 * 7 - MAXIM_PMBUS_ALERT
-		 * 10 - PL_DDR4_VTERM_EN
-		 * 11 - PL_DDR4_VPP_2V5_EN
-		 * 12 - PS_DIMM_VDDQ_TO_PSVCCO_ON
-		 * 13 - PS_DIMM_SUSPEND_EN
-		 * 14 - PS_DDR4_VTERM_EN
-		 * 15 - PS_DDR4_VPP_2V5_EN
-		 * 16 - 17 - not connected
-		 */
+		gpio-line-names = "VCCPSPLL_EN", "MGTRAVCC_EN", "MGTRAVTT_EN", "VCCPSDDRPLL_EN", "MIO26_PMU_INPUT_LS",
+				"PL_PMBUS_ALERT", "PS_PMBUS_ALERT", "MAXIM_PMBUS_ALERT", "PL_DDR4_VTERM_EN",
+				"PL_DDR4_VPP_2V5_EN", "PS_DIMM_VDDQ_TO_PSVCCO_ON", "PS_DIMM_SUSPEND_EN",
+				"PS_DDR4_VTERM_EN", "PS_DDR4_VPP_2V5_EN", "", "";
 	};
 
 	i2c-mux@75 { /* u60 */
@@ -202,53 +272,73 @@
 			#size-cells = <0>;
 			reg = <0>;
 			/* PS_PMBUS */
-			ina226@40 { /* u76 */
+			u76: ina226@40 { /* u76 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u76";
 				reg = <0x40>;
 				shunt-resistor = <5000>;
 			};
-			ina226@41 { /* u77 */
+			u77: ina226@41 { /* u77 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u77";
 				reg = <0x41>;
 				shunt-resistor = <5000>;
 			};
-			ina226@42 { /* u78 */
+			u78: ina226@42 { /* u78 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u78";
 				reg = <0x42>;
 				shunt-resistor = <5000>;
 			};
-			ina226@43 { /* u87 */
+			u87: ina226@43 { /* u87 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u87";
 				reg = <0x43>;
 				shunt-resistor = <5000>;
 			};
-			ina226@44 { /* u85 */
+			u85: ina226@44 { /* u85 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u85";
 				reg = <0x44>;
 				shunt-resistor = <5000>;
 			};
-			ina226@45 { /* u86 */
+			u86: ina226@45 { /* u86 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u86";
 				reg = <0x45>;
 				shunt-resistor = <5000>;
 			};
-			ina226@46 { /* u93 */
+			u93: ina226@46 { /* u93 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u93";
 				reg = <0x46>;
 				shunt-resistor = <5000>;
 			};
-			ina226@47 { /* u88 */
+			u88: ina226@47 { /* u88 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u88";
 				reg = <0x47>;
 				shunt-resistor = <5000>;
 			};
-			ina226@4a { /* u15 */
+			u15: ina226@4a { /* u15 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u15";
 				reg = <0x4a>;
 				shunt-resistor = <5000>;
 			};
-			ina226@4b { /* u92 */
+			u92: ina226@4b { /* u92 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u92";
 				reg = <0x4b>;
 				shunt-resistor = <5000>;
 			};
@@ -258,43 +348,59 @@
 			#size-cells = <0>;
 			reg = <1>;
 			/* PL_PMBUS */
-			ina226@40 { /* u79 */
+			u79: ina226@40 { /* u79 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u79";
 				reg = <0x40>;
 				shunt-resistor = <2000>;
 			};
-			ina226@41 { /* u81 */
+			u81: ina226@41 { /* u81 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u81";
 				reg = <0x41>;
 				shunt-resistor = <5000>;
 			};
-			ina226@42 { /* u80 */
+			u80: ina226@42 { /* u80 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u80";
 				reg = <0x42>;
 				shunt-resistor = <5000>;
 			};
-			ina226@43 { /* u84 */
+			u84: ina226@43 { /* u84 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u84";
 				reg = <0x43>;
 				shunt-resistor = <5000>;
 			};
-			ina226@44 { /* u16 */
+			u16: ina226@44 { /* u16 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u16";
 				reg = <0x44>;
 				shunt-resistor = <5000>;
 			};
-			ina226@45 { /* u65 */
+			u65: ina226@45 { /* u65 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u65";
 				reg = <0x45>;
 				shunt-resistor = <5000>;
 			};
-			ina226@46 { /* u74 */
+			u74: ina226@46 { /* u74 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u74";
 				reg = <0x46>;
 				shunt-resistor = <5000>;
 			};
-			ina226@47 { /* u75 */
+			u75: ina226@47 { /* u75 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u75";
 				reg = <0x47>;
 				shunt-resistor = <5000>;
 			};
@@ -353,7 +459,6 @@
 				status = "disabled"; /* unreachable */
 				reg = <0x20>;
 			};
-
 			max20751@72 { /* u95 */
 				compatible = "maxim,max20751";
 				reg = <0x72>;
@@ -370,6 +475,11 @@
 &i2c1 {
 	status = "okay";
 	clock-frequency = <400000>;
+	pinctrl-names = "default", "gpio";
+	pinctrl-0 = <&pinctrl_i2c1_default>;
+	pinctrl-1 = <&pinctrl_i2c1_gpio>;
+	scl-gpios = <&gpio 16 GPIO_ACTIVE_HIGH>;
+	sda-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>;
 
 	/* PL i2c via PCA9306 - u45 */
 	i2c-mux@74 { /* u34 */
@@ -399,6 +509,7 @@
 			#size-cells = <0>;
 			reg = <1>;
 			si5341: clock-generator@36 { /* SI5341 - u69 */
+				compatible = "silabs,si5341";
 				reg = <0x36>;
 			};
 
@@ -414,6 +525,7 @@
 				temperature-stability = <50>;
 				factory-fout = <300000000>;
 				clock-frequency = <300000000>;
+				clock-output-names = "si570_user";
 			};
 		};
 		i2c@3 {
@@ -427,6 +539,7 @@
 				temperature-stability = <50>; /* copy from zc702 */
 				factory-fout = <156250000>;
 				clock-frequency = <148500000>;
+				clock-output-names = "si570_mgt";
 			};
 		};
 		i2c@4 {
@@ -434,6 +547,7 @@
 			#size-cells = <0>;
 			reg = <4>;
 			si5328: clock-generator@69 {/* SI5328 - u20 */
+				compatible = "silabs,si5328";
 				reg = <0x69>;
 				/*
 				 * Chip has interrupt present connected to PL
@@ -502,10 +616,303 @@
 	};
 };
 
+&pinctrl0 {
+	status = "okay";
+	pinctrl_i2c0_default: i2c0-default {
+		mux {
+			groups = "i2c0_3_grp";
+			function = "i2c0";
+		};
+
+		conf {
+			groups = "i2c0_3_grp";
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_i2c0_gpio: i2c0-gpio {
+		mux {
+			groups = "gpio0_14_grp", "gpio0_15_grp";
+			function = "gpio0";
+		};
+
+		conf {
+			groups = "gpio0_14_grp", "gpio0_15_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_i2c1_default: i2c1-default {
+		mux {
+			groups = "i2c1_4_grp";
+			function = "i2c1";
+		};
+
+		conf {
+			groups = "i2c1_4_grp";
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_i2c1_gpio: i2c1-gpio {
+		mux {
+			groups = "gpio0_16_grp", "gpio0_17_grp";
+			function = "gpio0";
+		};
+
+		conf {
+			groups = "gpio0_16_grp", "gpio0_17_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_uart0_default: uart0-default {
+		mux {
+			groups = "uart0_4_grp";
+			function = "uart0";
+		};
+
+		conf {
+			groups = "uart0_4_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-rx {
+			pins = "MIO18";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO19";
+			bias-disable;
+		};
+	};
+
+	pinctrl_uart1_default: uart1-default {
+		mux {
+			groups = "uart1_5_grp";
+			function = "uart1";
+		};
+
+		conf {
+			groups = "uart1_5_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-rx {
+			pins = "MIO21";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO20";
+			bias-disable;
+		};
+	};
+
+	pinctrl_usb0_default: usb0-default {
+		mux {
+			groups = "usb0_0_grp";
+			function = "usb0";
+		};
+
+		conf {
+			groups = "usb0_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-rx {
+			pins = "MIO52", "MIO53", "MIO55";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO54", "MIO56", "MIO57", "MIO58", "MIO59",
+			       "MIO60", "MIO61", "MIO62", "MIO63";
+			bias-disable;
+		};
+	};
+
+	pinctrl_gem3_default: gem3-default {
+		mux {
+			function = "ethernet3";
+			groups = "ethernet3_0_grp";
+		};
+
+		conf {
+			groups = "ethernet3_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-rx {
+			pins = "MIO70", "MIO71", "MIO72", "MIO73", "MIO74",
+									"MIO75";
+			bias-high-impedance;
+			low-power-disable;
+		};
+
+		conf-tx {
+			pins = "MIO64", "MIO65", "MIO66", "MIO67", "MIO68",
+									"MIO69";
+			bias-disable;
+			low-power-enable;
+		};
+
+		mux-mdio {
+			function = "mdio3";
+			groups = "mdio3_0_grp";
+		};
+
+		conf-mdio {
+			groups = "mdio3_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+			bias-disable;
+		};
+	};
+
+	pinctrl_can1_default: can1-default {
+		mux {
+			function = "can1";
+			groups = "can1_6_grp";
+		};
+
+		conf {
+			groups = "can1_6_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-rx {
+			pins = "MIO25";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO24";
+			bias-disable;
+		};
+	};
+
+	pinctrl_sdhci1_default: sdhci1-default {
+		mux {
+			groups = "sdio1_0_grp";
+			function = "sdio1";
+		};
+
+		conf {
+			groups = "sdio1_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+			bias-disable;
+		};
+
+		mux-cd {
+			groups = "sdio1_cd_0_grp";
+			function = "sdio1_cd";
+		};
+
+		conf-cd {
+			groups = "sdio1_cd_0_grp";
+			bias-high-impedance;
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		mux-wp {
+			groups = "sdio1_wp_0_grp";
+			function = "sdio1_wp";
+		};
+
+		conf-wp {
+			groups = "sdio1_wp_0_grp";
+			bias-high-impedance;
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_gpio_default: gpio-default {
+		mux-sw {
+			function = "gpio0";
+			groups = "gpio0_22_grp", "gpio0_23_grp";
+		};
+
+		conf-sw {
+			groups = "gpio0_22_grp", "gpio0_23_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		mux-msp {
+			function = "gpio0";
+			groups = "gpio0_13_grp", "gpio0_38_grp";
+		};
+
+		conf-msp {
+			groups = "gpio0_13_grp", "gpio0_38_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-pull-up {
+			pins = "MIO22", "MIO23";
+			bias-pull-up;
+		};
+
+		conf-pull-none {
+			pins = "MIO13", "MIO38";
+			bias-disable;
+		};
+	};
+};
+
 &pcie {
 	status = "okay";
 };
 
+&qspi {
+	status = "okay";
+	is-dual = <1>;
+	flash@0 {
+		compatible = "m25p80", "jedec,spi-nor"; /* 32MB */
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x0>;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <4>; /* FIXME also DUAL configuration possible */
+		spi-max-frequency = <108000000>; /* Based on DC1 spec */
+		partition@0 { /* for testing purpose */
+			label = "qspi-fsbl-uboot";
+			reg = <0x0 0x100000>;
+		};
+		partition@100000 { /* for testing purpose */
+			label = "qspi-linux";
+			reg = <0x100000 0x500000>;
+		};
+		partition@600000 { /* for testing purpose */
+			label = "qspi-device-tree";
+			reg = <0x600000 0x20000>;
+		};
+		partition@620000 { /* for testing purpose */
+			label = "qspi-rootfs";
+			reg = <0x620000 0x5E0000>;
+		};
+	};
+};
+
 &rtc {
 	status = "okay";
 };
@@ -521,27 +928,93 @@
 	ceva,p1-comwake-params = /bits/ 8 <0x06 0x14 0x08 0x0E>;
 	ceva,p1-burst-params = /bits/ 8 <0x13 0x08 0x4A 0x06>;
 	ceva,p1-retry-params = /bits/ 16 <0x96A4 0x3FFC>;
+	phy-names = "sata-phy";
+	phys = <&lane3 PHY_TYPE_SATA 1 1 125000000>;
 };
 
 /* SD1 with level shifter */
 &sdhci1 {
 	status = "okay";
+	/*
+	 * 1.0 revision has level shifter and this property should be
+	 * removed for supporting UHS mode
+	 */
 	no-1-8-v;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sdhci1_default>;
+	xlnx,mio-bank = <1>;
+};
+
+&serdes {
+	status = "okay";
 };
 
 &uart0 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart0_default>;
 };
 
 &uart1 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1_default>;
 };
 
 /* ULPI SMSC USB3320 */
 &usb0 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usb0_default>;
+};
+
+&dwc3_0 {
+	status = "okay";
+	dr_mode = "host";
+	snps,usb3_lpm_capable;
+	phy-names = "usb3-phy";
+	phys = <&lane2 PHY_TYPE_USB3 0 2 26000000>;
+	maximum-speed = "super-speed";
 };
 
 &watchdog0 {
 	status = "okay";
 };
+
+&xilinx_ams {
+	status = "okay";
+};
+
+&ams_ps {
+	status = "okay";
+};
+
+&ams_pl {
+	status = "okay";
+};
+
+&zynqmp_dpsub {
+	status = "okay";
+	phy-names = "dp-phy0";
+	phys = <&lane1 PHY_TYPE_DP 0 3 27000000>;
+};
+
+&zynqmp_dp_snd_codec0 {
+	status = "okay";
+};
+
+&zynqmp_dp_snd_pcm0 {
+	status = "okay";
+};
+
+&zynqmp_dp_snd_pcm1 {
+	status = "okay";
+};
+
+&zynqmp_dp_snd_card0 {
+	status = "okay";
+};
+
+&xlnx_dpdma {
+	status = "okay";
+};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-revB.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-revB.dts
@@ -2,7 +2,7 @@
 /*
  * dts file for Xilinx ZynqMP ZCU102 RevB
  *
- * (C) Copyright 2016 - 2018, Xilinx, Inc.
+ * (C) Copyright 2016 - 2020, Xilinx, Inc.
  *
  * Michal Simek <michal.simek@xilinx.com>
  */
@@ -16,15 +16,16 @@
 
 &gem3 {
 	phy-handle = <&phyc>;
-	phyc: phy@c {
+	phyc: ethernet-phy@c {
 		reg = <0xc>;
 		ti,rx-internal-delay = <0x8>;
 		ti,tx-internal-delay = <0xa>;
 		ti,fifo-depth = <0x1>;
 		ti,dp83867-rxctrl-strap-quirk;
+		/* reset-gpios = <&tca6416_u97 6 GPIO_ACTIVE_LOW>; */
 	};
 	/* Cleanup from RevA */
-	/delete-node/ phy@21;
+	/delete-node/ ethernet-phy@21;
 };
 
 /* Fix collision with u61 */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/xilinx/zynqmp-zcu104-revA.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/xilinx/zynqmp-zcu104-revA.dts
@@ -2,7 +2,7 @@
 /*
  * dts file for Xilinx ZynqMP ZCU104
  *
- * (C) Copyright 2017 - 2018, Xilinx, Inc.
+ * (C) Copyright 2017 - 2020, Xilinx, Inc.
  *
  * Michal Simek <michal.simek@xilinx.com>
  */
@@ -10,8 +10,10 @@
 /dts-v1/;
 
 #include "zynqmp.dtsi"
-#include "zynqmp-clk.dtsi"
+#include "zynqmp-clk-ccf.dtsi"
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
+#include <dt-bindings/phy/phy.h>
 
 / {
 	model = "ZynqMP ZCU104 RevA";
@@ -19,12 +21,15 @@
 
 	aliases {
 		ethernet0 = &gem3;
+		gpio0 = &gpio;
 		i2c0 = &i2c1;
 		mmc0 = &sdhci1;
 		rtc0 = &rtc;
 		serial0 = &uart0;
 		serial1 = &uart1;
 		serial2 = &dcc;
+		spi0 = &qspi;
+		usb0 = &usb0;
 	};
 
 	chosen {
@@ -40,17 +45,53 @@
 
 &can1 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_can1_default>;
 };
 
 &dcc {
 	status = "okay";
 };
 
+&fpd_dma_chan1 {
+	status = "okay";
+};
+
+&fpd_dma_chan2 {
+	status = "okay";
+};
+
+&fpd_dma_chan3 {
+	status = "okay";
+};
+
+&fpd_dma_chan4 {
+	status = "okay";
+};
+
+&fpd_dma_chan5 {
+	status = "okay";
+};
+
+&fpd_dma_chan6 {
+	status = "okay";
+};
+
+&fpd_dma_chan7 {
+	status = "okay";
+};
+
+&fpd_dma_chan8 {
+	status = "okay";
+};
+
 &gem3 {
 	status = "okay";
 	phy-handle = <&phy0>;
 	phy-mode = "rgmii-id";
-	phy0: phy@c {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gem3_default>;
+	phy0: ethernet-phy@c {
 		reg = <0xc>;
 		ti,rx-internal-delay = <0x8>;
 		ti,tx-internal-delay = <0xa>;
@@ -63,9 +104,18 @@
 	status = "okay";
 };
 
+&gpu {
+	status = "okay";
+};
+
 &i2c1 {
 	status = "okay";
 	clock-frequency = <400000>;
+	pinctrl-names = "default", "gpio";
+	pinctrl-0 = <&pinctrl_i2c1_default>;
+	pinctrl-1 = <&pinctrl_i2c1_gpio>;
+	scl-gpios = <&gpio 16 GPIO_ACTIVE_HIGH>;
+	sda-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>;
 
 	/* Another connection to this bus via PL i2c via PCA9306 - u45 */
 	i2c-mux@74 { /* u34 */
@@ -85,7 +135,7 @@
 			 * 512B - 768B address 0x56
 			 * 768B - 1024B address 0x57
 			 */
-			eeprom@54 { /* u23 */
+			eeprom: eeprom@54 { /* u23 */
 				compatible = "atmel,24c08";
 				reg = <0x54>;
 				#address-cells = <1>;
@@ -98,6 +148,7 @@
 			#size-cells = <0>;
 			reg = <1>;
 			clock_8t49n287: clock-generator@6c { /* 8T49N287 - u182 */
+				compatible = "idt,8t49n287";
 				reg = <0x6c>;
 			};
 		};
@@ -106,11 +157,13 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <2>;
-			irps5401_43: irps54012@43 { /* IRPS5401 - u175 */
-				reg = <0x43>;
+			irps5401_43: irps5401@43 { /* IRPS5401 - u175 */
+				compatible = "infineon,irps5401";
+				reg = <0x43>; /* pmbus / i2c 0x13 */
 			};
-			irps5401_4d: irps54012@4d { /* IRPS5401 - u180 */
-				reg = <0x4d>;
+			irps5401_44: irps5401@44 { /* IRPS5401 - u180 */
+				compatible = "infineon,irps5401";
+				reg = <0x44>; /* pmbus / i2c 0x14 */
 			};
 		};
 
@@ -118,9 +171,9 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <4>;
-			tca6416_u97: gpio@21 {
+			tca6416_u97: gpio@20 {
 				compatible = "ti,tca6416";
-				reg = <0x21>;
+				reg = <0x20>;
 				gpio-controller;
 				#gpio-cells = <2>;
 				/*
@@ -154,6 +207,233 @@
 	};
 };
 
+&pinctrl0 {
+	status = "okay";
+
+	pinctrl_can1_default: can1-default {
+		mux {
+			function = "can1";
+			groups = "can1_6_grp";
+		};
+
+		conf {
+			groups = "can1_6_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+			drive-strength = <12>;
+		};
+
+		conf-rx {
+			pins = "MIO25";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO24";
+			bias-disable;
+		};
+	};
+
+	pinctrl_i2c1_default: i2c1-default {
+		mux {
+			groups = "i2c1_4_grp";
+			function = "i2c1";
+		};
+
+		conf {
+			groups = "i2c1_4_grp";
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+			drive-strength = <12>;
+		};
+	};
+
+	pinctrl_i2c1_gpio: i2c1-gpio {
+		mux {
+			groups = "gpio0_16_grp", "gpio0_17_grp";
+			function = "gpio0";
+		};
+
+		conf {
+			groups = "gpio0_16_grp", "gpio0_17_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+			drive-strength = <12>;
+		};
+	};
+
+	pinctrl_gem3_default: gem3-default {
+		mux {
+			function = "ethernet3";
+			groups = "ethernet3_0_grp";
+		};
+
+		conf {
+			groups = "ethernet3_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+			drive-strength = <12>;
+		};
+
+		conf-rx {
+			pins = "MIO70", "MIO71", "MIO72", "MIO73", "MIO74",
+									"MIO75";
+			bias-high-impedance;
+			low-power-disable;
+		};
+
+		conf-tx {
+			pins = "MIO64", "MIO65", "MIO66", "MIO67", "MIO68",
+									"MIO69";
+			bias-disable;
+			low-power-enable;
+		};
+
+		mux-mdio {
+			function = "mdio3";
+			groups = "mdio3_0_grp";
+		};
+
+		conf-mdio {
+			groups = "mdio3_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+			bias-disable;
+		};
+	};
+
+	pinctrl_sdhci1_default: sdhci1-default {
+		mux {
+			groups = "sdio1_0_grp";
+			function = "sdio1";
+		};
+
+		conf {
+			groups = "sdio1_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+			bias-disable;
+			drive-strength = <12>;
+		};
+
+		mux-cd {
+			groups = "sdio1_cd_0_grp";
+			function = "sdio1_cd";
+		};
+
+		conf-cd {
+			groups = "sdio1_cd_0_grp";
+			bias-high-impedance;
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_uart0_default: uart0-default {
+		mux {
+			groups = "uart0_4_grp";
+			function = "uart0";
+		};
+
+		conf {
+			groups = "uart0_4_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+			drive-strength = <12>;
+		};
+
+		conf-rx {
+			pins = "MIO18";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO19";
+			bias-disable;
+		};
+	};
+
+	pinctrl_uart1_default: uart1-default {
+		mux {
+			groups = "uart1_5_grp";
+			function = "uart1";
+		};
+
+		conf {
+			groups = "uart1_5_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+			drive-strength = <12>;
+		};
+
+		conf-rx {
+			pins = "MIO21";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO20";
+			bias-disable;
+		};
+	};
+
+	pinctrl_usb0_default: usb0-default {
+		mux {
+			groups = "usb0_0_grp";
+			function = "usb0";
+		};
+
+		conf {
+			groups = "usb0_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+			drive-strength = <12>;
+		};
+
+		conf-rx {
+			pins = "MIO52", "MIO53", "MIO55";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO54", "MIO56", "MIO57", "MIO58", "MIO59",
+			       "MIO60", "MIO61", "MIO62", "MIO63";
+			bias-disable;
+		};
+	};
+};
+
+&qspi {
+	status = "okay";
+	flash@0 {
+		compatible = "m25p80", "jedec,spi-nor"; /* n25q512a 128MiB */
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x0>;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <4>;
+		spi-max-frequency = <108000000>; /* Based on DC1 spec */
+		partition@0 { /* for testing purpose */
+			label = "qspi-fsbl-uboot";
+			reg = <0x0 0x100000>;
+		};
+		partition@100000 { /* for testing purpose */
+			label = "qspi-linux";
+			reg = <0x100000 0x500000>;
+		};
+		partition@600000 { /* for testing purpose */
+			label = "qspi-device-tree";
+			reg = <0x600000 0x20000>;
+		};
+		partition@620000 { /* for testing purpose */
+			label = "qspi-rootfs";
+			reg = <0x620000 0x5E0000>;
+		};
+	};
+};
+
 &rtc {
 	status = "okay";
 };
@@ -169,28 +449,90 @@
 	ceva,p1-comwake-params = /bits/ 8 <0x06 0x14 0x08 0x0E>;
 	ceva,p1-burst-params = /bits/ 8 <0x13 0x08 0x4A 0x06>;
 	ceva,p1-retry-params = /bits/ 16 <0x96A4 0x3FFC>;
+	phy-names = "sata-phy";
+	phys = <&lane3 PHY_TYPE_SATA 1 1 125000000>;
 };
 
 /* SD1 with level shifter */
 &sdhci1 {
 	status = "okay";
 	no-1-8-v;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sdhci1_default>;
+	xlnx,mio-bank = <1>;
 	disable-wp;
 };
 
+&serdes {
+	status = "okay";
+};
+
 &uart0 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart0_default>;
 };
 
 &uart1 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1_default>;
 };
 
 /* ULPI SMSC USB3320 */
 &usb0 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usb0_default>;
+};
+
+&dwc3_0 {
+	status = "okay";
+	dr_mode = "host";
+	snps,usb3_lpm_capable;
+	phy-names = "usb3-phy";
+	phys = <&lane2 PHY_TYPE_USB3 0 2 26000000>;
+	maximum-speed = "super-speed";
 };
 
 &watchdog0 {
 	status = "okay";
 };
+
+&xilinx_ams {
+	status = "okay";
+};
+
+&ams_ps {
+	status = "okay";
+};
+
+&ams_pl {
+	status = "okay";
+};
+
+&zynqmp_dpsub {
+	status = "okay";
+	phy-names = "dp-phy0", "dp-phy1";
+	phys = <&lane1 PHY_TYPE_DP 0 3 27000000>, <&lane0 PHY_TYPE_DP 1 3 27000000>;
+};
+
+&zynqmp_dp_snd_pcm0 {
+	status = "okay";
+};
+
+&zynqmp_dp_snd_pcm1 {
+	status = "okay";
+};
+
+&zynqmp_dp_snd_card0 {
+	status = "okay";
+};
+
+&zynqmp_dp_snd_codec0 {
+	status = "okay";
+};
+
+&xlnx_dpdma {
+	status = "okay";
+};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/xilinx/zynqmp-zcu104-revC.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/xilinx/zynqmp-zcu104-revC.dts
@@ -0,0 +1,551 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * dts file for Xilinx ZynqMP ZCU104
+ *
+ * (C) Copyright 2017 - 2020, Xilinx, Inc.
+ *
+ * Michal Simek <michal.simek@xilinx.com>
+ */
+
+/dts-v1/;
+
+#include "zynqmp.dtsi"
+#include "zynqmp-clk-ccf.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
+#include <dt-bindings/phy/phy.h>
+
+/ {
+	model = "ZynqMP ZCU104 RevC";
+	compatible = "xlnx,zynqmp-zcu104-revC", "xlnx,zynqmp-zcu104", "xlnx,zynqmp";
+
+	aliases {
+		ethernet0 = &gem3;
+		gpio0 = &gpio;
+		i2c0 = &i2c1;
+		mmc0 = &sdhci1;
+		rtc0 = &rtc;
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &dcc;
+		spi0 = &qspi;
+		usb0 = &usb0;
+	};
+
+	chosen {
+		bootargs = "earlycon";
+		stdout-path = "serial0:115200n8";
+		xlnx,eeprom = &eeprom;
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x80000000>;
+	};
+
+	ina226 {
+		compatible = "iio-hwmon";
+		io-channels = <&u183 0>, <&u183 1>, <&u183 2>, <&u183 3>;
+	};
+};
+
+&can1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_can1_default>;
+};
+
+&dcc {
+	status = "okay";
+};
+
+&fpd_dma_chan1 {
+	status = "okay";
+};
+
+&fpd_dma_chan2 {
+	status = "okay";
+};
+
+&fpd_dma_chan3 {
+	status = "okay";
+};
+
+&fpd_dma_chan4 {
+	status = "okay";
+};
+
+&fpd_dma_chan5 {
+	status = "okay";
+};
+
+&fpd_dma_chan6 {
+	status = "okay";
+};
+
+&fpd_dma_chan7 {
+	status = "okay";
+};
+
+&fpd_dma_chan8 {
+	status = "okay";
+};
+
+&gem3 {
+	status = "okay";
+	phy-handle = <&phy0>;
+	phy-mode = "rgmii-id";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gem3_default>;
+	phy0: ethernet-phy@c {
+		reg = <0xc>;
+		ti,rx-internal-delay = <0x8>;
+		ti,tx-internal-delay = <0xa>;
+		ti,fifo-depth = <0x1>;
+		ti,dp83867-rxctrl-strap-quirk;
+	};
+};
+
+&gpio {
+	status = "okay";
+};
+
+&gpu {
+	status = "okay";
+};
+
+&i2c1 {
+	status = "okay";
+	clock-frequency = <400000>;
+	pinctrl-names = "default", "gpio";
+	pinctrl-0 = <&pinctrl_i2c1_default>;
+	pinctrl-1 = <&pinctrl_i2c1_gpio>;
+	scl-gpios = <&gpio 16 GPIO_ACTIVE_HIGH>;
+	sda-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>;
+
+	tca6416_u97: gpio@20 {
+		compatible = "ti,tca6416";
+		reg = <0x20>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		/*
+		 * IRQ not connected
+		 * Lines:
+		 * 0 - IRPS5401_ALERT_B
+		 * 1 - HDMI_8T49N241_INT_ALM
+		 * 2 - MAX6643_OT_B
+		 * 3 - MAX6643_FANFAIL_B
+		 * 5 - IIC_MUX_RESET_B
+		 * 6 - GEM3_EXP_RESET_B
+		 * 7 - FMC_LPC_PRSNT_M2C_B
+		 * 4, 10 - 17 - not connected
+		 */
+	};
+
+	/* Another connection to this bus via PL i2c via PCA9306 - u45 */
+	i2c-mux@74 { /* u34 */
+		compatible = "nxp,pca9548";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x74>;
+		i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+			/*
+			 * IIC_EEPROM 1kB memory which uses 256B blocks
+			 * where every block has different address.
+			 *    0 - 256B address 0x54
+			 * 256B - 512B address 0x55
+			 * 512B - 768B address 0x56
+			 * 768B - 1024B address 0x57
+			 */
+			eeprom: eeprom@54 { /* u23 */
+				compatible = "atmel,24c08";
+				reg = <0x54>;
+				#address-cells = <1>;
+				#size-cells = <1>;
+			};
+		};
+
+		i2c@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+			clock_8t49n287: clock-generator@6c { /* 8T49N287 - u182 */
+				compatible = "idt,8t49n287";
+				reg = <0x6c>;
+			};
+		};
+
+		i2c@2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+			irps5401_43: irps5401@43 { /* IRPS5401 - u175 */
+				compatible = "infineon,irps5401";
+				reg = <0x43>; /* pmbus / i2c 0x13 */
+			};
+			irps5401_44: irps5401@44 { /* IRPS5401 - u180 */
+				compatible = "infineon,irps5401";
+				reg = <0x44>; /* pmbus / i2c 0x14 */
+			};
+		};
+
+		i2c@3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+			u183: ina226@40 { /* u183 */
+				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				reg = <0x40>;
+				shunt-resistor = <5000>;
+			};
+		};
+
+		i2c@5 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <5>;
+		};
+
+		i2c@7 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <7>;
+		};
+
+		/* 4, 6 not connected */
+	};
+};
+
+&pinctrl0 {
+	status = "okay";
+
+	pinctrl_can1_default: can1-default {
+		mux {
+			function = "can1";
+			groups = "can1_6_grp";
+		};
+
+		conf {
+			groups = "can1_6_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+			drive-strength = <12>;
+		};
+
+		conf-rx {
+			pins = "MIO25";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO24";
+			bias-disable;
+		};
+	};
+
+	pinctrl_i2c1_default: i2c1-default {
+		mux {
+			groups = "i2c1_4_grp";
+			function = "i2c1";
+		};
+
+		conf {
+			groups = "i2c1_4_grp";
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+			drive-strength = <12>;
+		};
+	};
+
+	pinctrl_i2c1_gpio: i2c1-gpio {
+		mux {
+			groups = "gpio0_16_grp", "gpio0_17_grp";
+			function = "gpio0";
+		};
+
+		conf {
+			groups = "gpio0_16_grp", "gpio0_17_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+			drive-strength = <12>;
+		};
+	};
+
+	pinctrl_gem3_default: gem3-default {
+		mux {
+			function = "ethernet3";
+			groups = "ethernet3_0_grp";
+		};
+
+		conf {
+			groups = "ethernet3_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+			drive-strength = <12>;
+		};
+
+		conf-rx {
+			pins = "MIO70", "MIO71", "MIO72", "MIO73", "MIO74",
+									"MIO75";
+			bias-high-impedance;
+			low-power-disable;
+		};
+
+		conf-tx {
+			pins = "MIO64", "MIO65", "MIO66", "MIO67", "MIO68",
+									"MIO69";
+			bias-disable;
+			low-power-enable;
+		};
+
+		mux-mdio {
+			function = "mdio3";
+			groups = "mdio3_0_grp";
+		};
+
+		conf-mdio {
+			groups = "mdio3_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+			bias-disable;
+		};
+	};
+
+	pinctrl_sdhci1_default: sdhci1-default {
+		mux {
+			groups = "sdio1_0_grp";
+			function = "sdio1";
+		};
+
+		conf {
+			groups = "sdio1_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+			bias-disable;
+			drive-strength = <12>;
+		};
+
+		mux-cd {
+			groups = "sdio1_cd_0_grp";
+			function = "sdio1_cd";
+		};
+
+		conf-cd {
+			groups = "sdio1_cd_0_grp";
+			bias-high-impedance;
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_uart0_default: uart0-default {
+		mux {
+			groups = "uart0_4_grp";
+			function = "uart0";
+		};
+
+		conf {
+			groups = "uart0_4_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+			drive-strength = <12>;
+		};
+
+		conf-rx {
+			pins = "MIO18";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO19";
+			bias-disable;
+		};
+	};
+
+	pinctrl_uart1_default: uart1-default {
+		mux {
+			groups = "uart1_5_grp";
+			function = "uart1";
+		};
+
+		conf {
+			groups = "uart1_5_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+			drive-strength = <12>;
+		};
+
+		conf-rx {
+			pins = "MIO21";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO20";
+			bias-disable;
+		};
+	};
+
+	pinctrl_usb0_default: usb0-default {
+		mux {
+			groups = "usb0_0_grp";
+			function = "usb0";
+		};
+
+		conf {
+			groups = "usb0_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+			drive-strength = <12>;
+		};
+
+		conf-rx {
+			pins = "MIO52", "MIO53", "MIO55";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO54", "MIO56", "MIO57", "MIO58", "MIO59",
+			       "MIO60", "MIO61", "MIO62", "MIO63";
+			bias-disable;
+		};
+	};
+};
+
+&qspi {
+	status = "okay";
+	flash@0 {
+		compatible = "m25p80", "jedec,spi-nor"; /* n25q512a 128MiB */
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x0>;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <4>;
+		spi-max-frequency = <108000000>; /* Based on DC1 spec */
+		partition@0 { /* for testing purpose */
+			label = "qspi-fsbl-uboot";
+			reg = <0x0 0x100000>;
+		};
+		partition@100000 { /* for testing purpose */
+			label = "qspi-linux";
+			reg = <0x100000 0x500000>;
+		};
+		partition@600000 { /* for testing purpose */
+			label = "qspi-device-tree";
+			reg = <0x600000 0x20000>;
+		};
+		partition@620000 { /* for testing purpose */
+			label = "qspi-rootfs";
+			reg = <0x620000 0x5E0000>;
+		};
+	};
+};
+
+&rtc {
+	status = "okay";
+};
+
+&sata {
+	status = "okay";
+	/* SATA OOB timing settings */
+	ceva,p0-cominit-params = /bits/ 8 <0x18 0x40 0x18 0x28>;
+	ceva,p0-comwake-params = /bits/ 8 <0x06 0x14 0x08 0x0E>;
+	ceva,p0-burst-params = /bits/ 8 <0x13 0x08 0x4A 0x06>;
+	ceva,p0-retry-params = /bits/ 16 <0x96A4 0x3FFC>;
+	ceva,p1-cominit-params = /bits/ 8 <0x18 0x40 0x18 0x28>;
+	ceva,p1-comwake-params = /bits/ 8 <0x06 0x14 0x08 0x0E>;
+	ceva,p1-burst-params = /bits/ 8 <0x13 0x08 0x4A 0x06>;
+	ceva,p1-retry-params = /bits/ 16 <0x96A4 0x3FFC>;
+	phy-names = "sata-phy";
+	phys = <&lane3 PHY_TYPE_SATA 1 1 125000000>;
+};
+
+/* SD1 with level shifter */
+&sdhci1 {
+	status = "okay";
+	no-1-8-v;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sdhci1_default>;
+	xlnx,mio-bank = <1>;
+	disable-wp;
+};
+
+&serdes {
+	status = "okay";
+};
+
+&uart0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart0_default>;
+};
+
+&uart1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1_default>;
+};
+
+/* ULPI SMSC USB3320 */
+&usb0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usb0_default>;
+};
+
+&dwc3_0 {
+	status = "okay";
+	dr_mode = "host";
+	snps,usb3_lpm_capable;
+	phy-names = "usb3-phy";
+	phys = <&lane2 PHY_TYPE_USB3 0 2 26000000>;
+	maximum-speed = "super-speed";
+};
+
+&watchdog0 {
+	status = "okay";
+};
+
+&xilinx_ams {
+	status = "okay";
+};
+
+&ams_ps {
+	status = "okay";
+};
+
+&ams_pl {
+	status = "okay";
+};
+
+&zynqmp_dpsub {
+	status = "okay";
+	phy-names = "dp-phy0", "dp-phy1";
+	phys = <&lane1 PHY_TYPE_DP 0 3 27000000>, <&lane0 PHY_TYPE_DP 1 3 27000000>;
+};
+
+&zynqmp_dp_snd_pcm0 {
+	status = "okay";
+};
+
+&zynqmp_dp_snd_pcm1 {
+	status = "okay";
+};
+
+&zynqmp_dp_snd_card0 {
+	status = "okay";
+};
+
+&zynqmp_dp_snd_codec0 {
+	status = "okay";
+};
+
+&xlnx_dpdma {
+	status = "okay";
+};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/xilinx/zynqmp-zcu106-revA.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/xilinx/zynqmp-zcu106-revA.dts
@@ -2,7 +2,7 @@
 /*
  * dts file for Xilinx ZynqMP ZCU106
  *
- * (C) Copyright 2016, Xilinx, Inc.
+ * (C) Copyright 2016 - 2020, Xilinx, Inc.
  *
  * Michal Simek <michal.simek@xilinx.com>
  */
@@ -10,9 +10,11 @@
 /dts-v1/;
 
 #include "zynqmp.dtsi"
-#include "zynqmp-clk.dtsi"
+#include "zynqmp-clk-ccf.dtsi"
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
+#include <dt-bindings/phy/phy.h>
 
 / {
 	model = "ZynqMP ZCU106 RevA";
@@ -20,6 +22,7 @@
 
 	aliases {
 		ethernet0 = &gem3;
+		gpio0 = &gpio;
 		i2c0 = &i2c0;
 		i2c1 = &i2c1;
 		mmc0 = &sdhci1;
@@ -27,11 +30,14 @@
 		serial0 = &uart0;
 		serial1 = &uart1;
 		serial2 = &dcc;
+		spi0 = &qspi;
+		usb0 = &usb0;
 	};
 
 	chosen {
 		bootargs = "earlycon";
 		stdout-path = "serial0:115200n8";
+		xlnx,eeprom = &eeprom;
 	};
 
 	memory@0 {
@@ -59,17 +65,91 @@
 			linux,default-trigger = "heartbeat";
 		};
 	};
+
+	ina226-u76 {
+		compatible = "iio-hwmon";
+		io-channels = <&u76 0>, <&u76 1>, <&u76 2>, <&u76 3>;
+	};
+	ina226-u77 {
+		compatible = "iio-hwmon";
+		io-channels = <&u77 0>, <&u77 1>, <&u77 2>, <&u77 3>;
+	};
+	ina226-u78 {
+		compatible = "iio-hwmon";
+		io-channels = <&u78 0>, <&u78 1>, <&u78 2>, <&u78 3>;
+	};
+	ina226-u87 {
+		compatible = "iio-hwmon";
+		io-channels = <&u87 0>, <&u87 1>, <&u87 2>, <&u87 3>;
+	};
+	ina226-u85 {
+		compatible = "iio-hwmon";
+		io-channels = <&u85 0>, <&u85 1>, <&u85 2>, <&u85 3>;
+	};
+	ina226-u86 {
+		compatible = "iio-hwmon";
+		io-channels = <&u86 0>, <&u86 1>, <&u86 2>, <&u86 3>;
+	};
+	ina226-u93 {
+		compatible = "iio-hwmon";
+		io-channels = <&u93 0>, <&u93 1>, <&u93 2>, <&u93 3>;
+	};
+	ina226-u88 {
+		compatible = "iio-hwmon";
+		io-channels = <&u88 0>, <&u88 1>, <&u88 2>, <&u88 3>;
+	};
+	ina226-u15 {
+		compatible = "iio-hwmon";
+		io-channels = <&u15 0>, <&u15 1>, <&u15 2>, <&u15 3>;
+	};
+	ina226-u92 {
+		compatible = "iio-hwmon";
+		io-channels = <&u92 0>, <&u92 1>, <&u92 2>, <&u92 3>;
+	};
+	ina226-u79 {
+		compatible = "iio-hwmon";
+		io-channels = <&u79 0>, <&u79 1>, <&u79 2>, <&u79 3>;
+	};
+	ina226-u81 {
+		compatible = "iio-hwmon";
+		io-channels = <&u81 0>, <&u81 1>, <&u81 2>, <&u81 3>;
+	};
+	ina226-u80 {
+		compatible = "iio-hwmon";
+		io-channels = <&u80 0>, <&u80 1>, <&u80 2>, <&u80 3>;
+	};
+	ina226-u84 {
+		compatible = "iio-hwmon";
+		io-channels = <&u84 0>, <&u84 1>, <&u84 2>, <&u84 3>;
+	};
+	ina226-u16 {
+		compatible = "iio-hwmon";
+		io-channels = <&u16 0>, <&u16 1>, <&u16 2>, <&u16 3>;
+	};
+	ina226-u65 {
+		compatible = "iio-hwmon";
+		io-channels = <&u65 0>, <&u65 1>, <&u65 2>, <&u65 3>;
+	};
+	ina226-u74 {
+		compatible = "iio-hwmon";
+		io-channels = <&u74 0>, <&u74 1>, <&u74 2>, <&u74 3>;
+	};
+	ina226-u75 {
+		compatible = "iio-hwmon";
+		io-channels = <&u75 0>, <&u75 1>, <&u75 2>, <&u75 3>;
+	};
 };
 
 &can1 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_can1_default>;
 };
 
 &dcc {
 	status = "okay";
 };
 
-/* fpd_dma clk 667MHz, lpd_dma 500MHz */
 &fpd_dma_chan1 {
 	status = "okay";
 };
@@ -106,7 +186,9 @@
 	status = "okay";
 	phy-handle = <&phy0>;
 	phy-mode = "rgmii-id";
-	phy0: phy@c {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gem3_default>;
+	phy0: ethernet-phy@c {
 		reg = <0xc>;
 		ti,rx-internal-delay = <0x8>;
 		ti,tx-internal-delay = <0xa>;
@@ -117,11 +199,22 @@
 
 &gpio {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gpio_default>;
+};
+
+&gpu {
+	status = "okay";
 };
 
 &i2c0 {
 	status = "okay";
 	clock-frequency = <400000>;
+	pinctrl-names = "default", "gpio";
+	pinctrl-0 = <&pinctrl_i2c0_default>;
+	pinctrl-1 = <&pinctrl_i2c0_gpio>;
+	scl-gpios = <&gpio 14 GPIO_ACTIVE_HIGH>;
+	sda-gpios = <&gpio 15 GPIO_ACTIVE_HIGH>;
 
 	tca6416_u97: gpio@20 {
 		compatible = "ti,tca6416";
@@ -177,53 +270,73 @@
 			#size-cells = <0>;
 			reg = <0>;
 			/* PS_PMBUS */
-			ina226@40 { /* u76 */
+			u76: ina226@40 { /* u76 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u76";
 				reg = <0x40>;
 				shunt-resistor = <5000>;
 			};
-			ina226@41 { /* u77 */
+			u77: ina226@41 { /* u77 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u77";
 				reg = <0x41>;
 				shunt-resistor = <5000>;
 			};
-			ina226@42 { /* u78 */
+			u78: ina226@42 { /* u78 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u78";
 				reg = <0x42>;
 				shunt-resistor = <5000>;
 			};
-			ina226@43 { /* u87 */
+			u87: ina226@43 { /* u87 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u87";
 				reg = <0x43>;
 				shunt-resistor = <5000>;
 			};
-			ina226@44 { /* u85 */
+			u85: ina226@44 { /* u85 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u85";
 				reg = <0x44>;
 				shunt-resistor = <5000>;
 			};
-			ina226@45 { /* u86 */
+			u86: ina226@45 { /* u86 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u86";
 				reg = <0x45>;
 				shunt-resistor = <5000>;
 			};
-			ina226@46 { /* u93 */
+			u93: ina226@46 { /* u93 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u93";
 				reg = <0x46>;
 				shunt-resistor = <5000>;
 			};
-			ina226@47 { /* u88 */
+			u88: ina226@47 { /* u88 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u88";
 				reg = <0x47>;
 				shunt-resistor = <5000>;
 			};
-			ina226@4a { /* u15 */
+			u15: ina226@4a { /* u15 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u15";
 				reg = <0x4a>;
 				shunt-resistor = <5000>;
 			};
-			ina226@4b { /* u92 */
+			u92: ina226@4b { /* u92 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u92";
 				reg = <0x4b>;
 				shunt-resistor = <5000>;
 			};
@@ -233,43 +346,59 @@
 			#size-cells = <0>;
 			reg = <1>;
 			/* PL_PMBUS */
-			ina226@40 { /* u79 */
+			u79: ina226@40 { /* u79 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u79";
 				reg = <0x40>;
 				shunt-resistor = <2000>;
 			};
-			ina226@41 { /* u81 */
+			u81: ina226@41 { /* u81 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u81";
 				reg = <0x41>;
 				shunt-resistor = <5000>;
 			};
-			ina226@42 { /* u80 */
+			u80: ina226@42 { /* u80 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u80";
 				reg = <0x42>;
 				shunt-resistor = <5000>;
 			};
-			ina226@43 { /* u84 */
+			u84: ina226@43 { /* u84 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u84";
 				reg = <0x43>;
 				shunt-resistor = <5000>;
 			};
-			ina226@44 { /* u16 */
+			u16: ina226@44 { /* u16 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u16";
 				reg = <0x44>;
 				shunt-resistor = <5000>;
 			};
-			ina226@45 { /* u65 */
+			u65: ina226@45 { /* u65 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u65";
 				reg = <0x45>;
 				shunt-resistor = <5000>;
 			};
-			ina226@46 { /* u74 */
+			u74: ina226@46 { /* u74 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u74";
 				reg = <0x46>;
 				shunt-resistor = <5000>;
 			};
-			ina226@47 { /* u75 */
+			u75: ina226@47 { /* u75 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u75";
 				reg = <0x47>;
 				shunt-resistor = <5000>;
 			};
@@ -344,6 +473,11 @@
 &i2c1 {
 	status = "okay";
 	clock-frequency = <400000>;
+	pinctrl-names = "default", "gpio";
+	pinctrl-0 = <&pinctrl_i2c1_default>;
+	pinctrl-1 = <&pinctrl_i2c1_gpio>;
+	scl-gpios = <&gpio 16 GPIO_ACTIVE_HIGH>;
+	sda-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>;
 
 	/* PL i2c via PCA9306 - u45 */
 	i2c-mux@74 { /* u34 */
@@ -373,6 +507,7 @@
 			#size-cells = <0>;
 			reg = <1>;
 			si5341: clock-generator@36 { /* SI5341 - u69 */
+				compatible = "si5341";
 				reg = <0x36>;
 			};
 
@@ -388,6 +523,7 @@
 				temperature-stability = <50>;
 				factory-fout = <300000000>;
 				clock-frequency = <300000000>;
+				clock-output-names = "si570_user";
 			};
 		};
 		i2c@3 {
@@ -401,6 +537,7 @@
 				temperature-stability = <50>; /* copy from zc702 */
 				factory-fout = <156250000>;
 				clock-frequency = <148500000>;
+				clock-output-names = "si570_mgt";
 			};
 		};
 		i2c@4 {
@@ -408,6 +545,7 @@
 			#size-cells = <0>;
 			reg = <4>;
 			si5328: clock-generator@69 {/* SI5328 - u20 */
+				compatible = "silabs,si5328";
 				reg = <0x69>;
 			};
 		};
@@ -480,6 +618,299 @@
 	};
 };
 
+&pinctrl0 {
+	status = "okay";
+	pinctrl_i2c0_default: i2c0-default {
+		mux {
+			groups = "i2c0_3_grp";
+			function = "i2c0";
+		};
+
+		conf {
+			groups = "i2c0_3_grp";
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_i2c0_gpio: i2c0-gpio {
+		mux {
+			groups = "gpio0_14_grp", "gpio0_15_grp";
+			function = "gpio0";
+		};
+
+		conf {
+			groups = "gpio0_14_grp", "gpio0_15_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_i2c1_default: i2c1-default {
+		mux {
+			groups = "i2c1_4_grp";
+			function = "i2c1";
+		};
+
+		conf {
+			groups = "i2c1_4_grp";
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_i2c1_gpio: i2c1-gpio {
+		mux {
+			groups = "gpio0_16_grp", "gpio0_17_grp";
+			function = "gpio0";
+		};
+
+		conf {
+			groups = "gpio0_16_grp", "gpio0_17_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_uart0_default: uart0-default {
+		mux {
+			groups = "uart0_4_grp";
+			function = "uart0";
+		};
+
+		conf {
+			groups = "uart0_4_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-rx {
+			pins = "MIO18";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO19";
+			bias-disable;
+		};
+	};
+
+	pinctrl_uart1_default: uart1-default {
+		mux {
+			groups = "uart1_5_grp";
+			function = "uart1";
+		};
+
+		conf {
+			groups = "uart1_5_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-rx {
+			pins = "MIO21";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO20";
+			bias-disable;
+		};
+	};
+
+	pinctrl_usb0_default: usb0-default {
+		mux {
+			groups = "usb0_0_grp";
+			function = "usb0";
+		};
+
+		conf {
+			groups = "usb0_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-rx {
+			pins = "MIO52", "MIO53", "MIO55";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO54", "MIO56", "MIO57", "MIO58", "MIO59",
+			       "MIO60", "MIO61", "MIO62", "MIO63";
+			bias-disable;
+		};
+	};
+
+	pinctrl_gem3_default: gem3-default {
+		mux {
+			function = "ethernet3";
+			groups = "ethernet3_0_grp";
+		};
+
+		conf {
+			groups = "ethernet3_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-rx {
+			pins = "MIO70", "MIO71", "MIO72", "MIO73", "MIO74",
+									"MIO75";
+			bias-high-impedance;
+			low-power-disable;
+		};
+
+		conf-tx {
+			pins = "MIO64", "MIO65", "MIO66", "MIO67", "MIO68",
+									"MIO69";
+			bias-disable;
+			low-power-enable;
+		};
+
+		mux-mdio {
+			function = "mdio3";
+			groups = "mdio3_0_grp";
+		};
+
+		conf-mdio {
+			groups = "mdio3_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+			bias-disable;
+		};
+	};
+
+	pinctrl_can1_default: can1-default {
+		mux {
+			function = "can1";
+			groups = "can1_6_grp";
+		};
+
+		conf {
+			groups = "can1_6_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-rx {
+			pins = "MIO25";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO24";
+			bias-disable;
+		};
+	};
+
+	pinctrl_sdhci1_default: sdhci1-default {
+		mux {
+			groups = "sdio1_0_grp";
+			function = "sdio1";
+		};
+
+		conf {
+			groups = "sdio1_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+			bias-disable;
+		};
+
+		mux-cd {
+			groups = "sdio1_cd_0_grp";
+			function = "sdio1_cd";
+		};
+
+		conf-cd {
+			groups = "sdio1_cd_0_grp";
+			bias-high-impedance;
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		mux-wp {
+			groups = "sdio1_wp_0_grp";
+			function = "sdio1_wp";
+		};
+
+		conf-wp {
+			groups = "sdio1_wp_0_grp";
+			bias-high-impedance;
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_gpio_default: gpio-default {
+		mux {
+			function = "gpio0";
+			groups = "gpio0_22_grp", "gpio0_23_grp";
+		};
+
+		conf {
+			groups = "gpio0_22_grp", "gpio0_23_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		mux-msp {
+			function = "gpio0";
+			groups = "gpio0_13_grp", "gpio0_38_grp";
+		};
+
+		conf-msp {
+			groups = "gpio0_13_grp", "gpio0_38_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-pull-up {
+			pins = "MIO22";
+			bias-pull-up;
+		};
+
+		conf-pull-none {
+			pins = "MIO13", "MIO23", "MIO38";
+			bias-disable;
+		};
+	};
+};
+
+&qspi {
+	status = "okay";
+	is-dual = <1>;
+	flash@0 {
+		compatible = "m25p80", "jedec,spi-nor"; /* 32MB */
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x0>;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <4>; /* FIXME also DUAL configuration possible */
+		spi-max-frequency = <108000000>; /* Based on DC1 spec */
+		partition@0 { /* for testing purpose */
+			label = "qspi-fsbl-uboot";
+			reg = <0x0 0x100000>;
+		};
+		partition@100000 { /* for testing purpose */
+			label = "qspi-linux";
+			reg = <0x100000 0x500000>;
+		};
+		partition@600000 { /* for testing purpose */
+			label = "qspi-device-tree";
+			reg = <0x600000 0x20000>;
+		};
+		partition@620000 { /* for testing purpose */
+			label = "qspi-rootfs";
+			reg = <0x620000 0x5E0000>;
+		};
+	};
+};
+
 &rtc {
 	status = "okay";
 };
@@ -495,27 +926,79 @@
 	ceva,p1-comwake-params = /bits/ 8 <0x06 0x14 0x08 0x0E>;
 	ceva,p1-burst-params = /bits/ 8 <0x13 0x08 0x4A 0x06>;
 	ceva,p1-retry-params = /bits/ 16 <0x96A4 0x3FFC>;
+	phy-names = "sata-phy";
+	phys = <&lane3 PHY_TYPE_SATA 1 1 125000000>;
 };
 
 /* SD1 with level shifter */
 &sdhci1 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sdhci1_default>;
+	/*
+	 * This property should be removed for supporting UHS mode
+	 */
 	no-1-8-v;
+	xlnx,mio-bank = <1>;
+};
+
+&serdes {
+	status = "okay";
 };
 
 &uart0 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart0_default>;
 };
 
 &uart1 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1_default>;
 };
 
 /* ULPI SMSC USB3320 */
 &usb0 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usb0_default>;
+};
+
+&dwc3_0 {
+	status = "okay";
+	dr_mode = "host";
+	snps,usb3_lpm_capable;
+	phy-names = "usb3-phy";
+	phys = <&lane2 PHY_TYPE_USB3 0 2 26000000>;
 };
 
 &watchdog0 {
 	status = "okay";
 };
+
+&zynqmp_dpsub {
+	status = "okay";
+	phy-names = "dp-phy0", "dp-phy1";
+	phys = <&lane1 PHY_TYPE_DP 0 3 27000000>, <&lane0 PHY_TYPE_DP 1 3 27000000>;
+};
+
+&zynqmp_dp_snd_pcm0 {
+	status = "okay";
+};
+
+&zynqmp_dp_snd_pcm1 {
+	status = "okay";
+};
+
+&zynqmp_dp_snd_card0 {
+	status = "okay";
+};
+
+&zynqmp_dp_snd_codec0 {
+	status = "okay";
+};
+
+&xlnx_dpdma {
+	status = "okay";
+};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/xilinx/zynqmp-zcu111-revA.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/xilinx/zynqmp-zcu111-revA.dts
@@ -2,7 +2,7 @@
 /*
  * dts file for Xilinx ZynqMP ZCU111
  *
- * (C) Copyright 2017 - 2018, Xilinx, Inc.
+ * (C) Copyright 2017 - 2020, Xilinx, Inc.
  *
  * Michal Simek <michal.simek@xilinx.com>
  */
@@ -10,9 +10,11 @@
 /dts-v1/;
 
 #include "zynqmp.dtsi"
-#include "zynqmp-clk.dtsi"
+#include "zynqmp-clk-ccf.dtsi"
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
+#include <dt-bindings/phy/phy.h>
 
 / {
 	model = "ZynqMP ZCU111 RevA";
@@ -20,17 +22,21 @@
 
 	aliases {
 		ethernet0 = &gem3;
+		gpio0 = &gpio;
 		i2c0 = &i2c0;
 		i2c1 = &i2c1;
 		mmc0 = &sdhci1;
 		rtc0 = &rtc;
 		serial0 = &uart0;
 		serial1 = &dcc;
+		spi0 = &qspi;
+		usb0 = &usb0;
 	};
 
 	chosen {
 		bootargs = "earlycon";
 		stdout-path = "serial0:115200n8";
+		xlnx,eeprom = &eeprom;
 	};
 
 	memory@0 {
@@ -59,6 +65,63 @@
 			linux,default-trigger = "heartbeat";
 		};
 	};
+
+	ina226-u67 {
+		compatible = "iio-hwmon";
+		io-channels = <&u67 0>, <&u67 1>, <&u67 2>, <&u67 3>;
+	};
+	ina226-u59 {
+		compatible = "iio-hwmon";
+		io-channels = <&u59 0>, <&u59 1>, <&u59 2>, <&u59 3>;
+	};
+	ina226-u61 {
+		compatible = "iio-hwmon";
+		io-channels = <&u61 0>, <&u61 1>, <&u61 2>, <&u61 3>;
+	};
+	ina226-u60 {
+		compatible = "iio-hwmon";
+		io-channels = <&u60 0>, <&u60 1>, <&u60 2>, <&u60 3>;
+	};
+	ina226-u64 {
+		compatible = "iio-hwmon";
+		io-channels = <&u64 0>, <&u64 1>, <&u64 2>, <&u64 3>;
+	};
+	ina226-u69 {
+		compatible = "iio-hwmon";
+		io-channels = <&u69 0>, <&u69 1>, <&u69 2>, <&u69 3>;
+	};
+	ina226-u66 {
+		compatible = "iio-hwmon";
+		io-channels = <&u66 0>, <&u66 1>, <&u66 2>, <&u66 3>;
+	};
+	ina226-u65 {
+		compatible = "iio-hwmon";
+		io-channels = <&u65 0>, <&u65 1>, <&u65 2>, <&u65 3>;
+	};
+	ina226-u63 {
+		compatible = "iio-hwmon";
+		io-channels = <&u63 0>, <&u63 1>, <&u63 2>, <&u63 3>;
+	};
+	ina226-u3 {
+		compatible = "iio-hwmon";
+		io-channels = <&u3 0>, <&u3 1>, <&u3 2>, <&u3 3>;
+	};
+	ina226-u71 {
+		compatible = "iio-hwmon";
+		io-channels = <&u71 0>, <&u71 1>, <&u71 2>, <&u71 3>;
+	};
+	ina226-u77 {
+		compatible = "iio-hwmon";
+		io-channels = <&u77 0>, <&u77 1>, <&u77 2>, <&u77 3>;
+	};
+	ina226-u73 {
+		compatible = "iio-hwmon";
+		io-channels = <&u73 0>, <&u73 1>, <&u73 2>, <&u73 3>;
+	};
+	ina226-u79 {
+		compatible = "iio-hwmon";
+		io-channels = <&u79 0>, <&u79 1>, <&u79 2>, <&u79 3>;
+	};
 };
 
 &dcc {
@@ -101,7 +164,9 @@
 	status = "okay";
 	phy-handle = <&phy0>;
 	phy-mode = "rgmii-id";
-	phy0: phy@c {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gem3_default>;
+	phy0: ethernet-phy@c {
 		reg = <0xc>;
 		ti,rx-internal-delay = <0x8>;
 		ti,tx-internal-delay = <0xa>;
@@ -112,11 +177,22 @@
 
 &gpio {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gpio_default>;
+};
+
+&gpu {
+	status = "okay";
 };
 
 &i2c0 {
 	status = "okay";
 	clock-frequency = <400000>;
+	pinctrl-names = "default", "gpio";
+	pinctrl-0 = <&pinctrl_i2c0_default>;
+	pinctrl-1 = <&pinctrl_i2c0_gpio>;
+	scl-gpios = <&gpio 14 GPIO_ACTIVE_HIGH>;
+	sda-gpios = <&gpio 15 GPIO_ACTIVE_HIGH>;
 
 	tca6416_u22: gpio@20 {
 		compatible = "ti,tca6416";
@@ -152,73 +228,101 @@
 			reg = <0>;
 			/* PS_PMBUS */
 			/* PMBUS_ALERT done via pca9544 */
-			ina226@40 { /* u67 */
+			u67: ina226@40 { /* u67 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u67";
 				reg = <0x40>;
 				shunt-resistor = <2000>;
 			};
-			ina226@41 { /* u59 */
+			u59: ina226@41 { /* u59 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u59";
 				reg = <0x41>;
 				shunt-resistor = <5000>;
 			};
-			ina226@42 { /* u61 */
+			u61: ina226@42 { /* u61 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u61";
 				reg = <0x42>;
 				shunt-resistor = <5000>;
 			};
-			ina226@43 { /* u60 */
+			u60: ina226@43 { /* u60 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u60";
 				reg = <0x43>;
 				shunt-resistor = <5000>;
 			};
-			ina226@45 { /* u64 */
+			u64: ina226@45 { /* u64 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u64";
 				reg = <0x45>;
 				shunt-resistor = <5000>;
 			};
-			ina226@46 { /* u69 */
+			u69: ina226@46 { /* u69 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u69";
 				reg = <0x46>;
 				shunt-resistor = <2000>;
 			};
-			ina226@47 { /* u66 */
+			u66: ina226@47 { /* u66 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u66";
 				reg = <0x47>;
 				shunt-resistor = <5000>;
 			};
-			ina226@48 { /* u65 */
+			u65: ina226@48 { /* u65 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u65";
 				reg = <0x48>;
 				shunt-resistor = <5000>;
 			};
-			ina226@49 { /* u63 */
+			u63: ina226@49 { /* u63 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u63";
 				reg = <0x49>;
 				shunt-resistor = <5000>;
 			};
-			ina226@4a { /* u3 */
+			u3: ina226@4a { /* u3 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u3";
 				reg = <0x4a>;
 				shunt-resistor = <5000>;
 			};
-			ina226@4b { /* u71 */
+			u71: ina226@4b { /* u71 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u71";
 				reg = <0x4b>;
 				shunt-resistor = <5000>;
 			};
-			ina226@4c { /* u77 */
+			u77: ina226@4c { /* u77 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u77";
 				reg = <0x4c>;
 				shunt-resistor = <5000>;
 			};
-			ina226@4d { /* u73 */
+			u73: ina226@4d { /* u73 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u73";
 				reg = <0x4d>;
 				shunt-resistor = <5000>;
 			};
-			ina226@4e { /* u79 */
+			u79: ina226@4e { /* u79 */
 				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u79";
 				reg = <0x4e>;
 				shunt-resistor = <5000>;
 			};
@@ -233,13 +337,16 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 			reg = <2>;
-			irps5401_43: irps54012@43 { /* IRPS5401 - u53 check these */
+			irps5401_43: irps5401@43 { /* IRPS5401 - u53 check these */
+				compatible = "infineon,irps5401";
 				reg = <0x43>;
 			};
-			irps5401_44: irps54012@44 { /* IRPS5401 - u55 */
+			irps5401_44: irps5401@44 { /* IRPS5401 - u55 */
+				compatible = "infineon,irps5401";
 				reg = <0x44>;
 			};
-			irps5401_45: irps54012@45 { /* IRPS5401 - u57 */
+			irps5401_45: irps5401@45 { /* IRPS5401 - u57 */
+				compatible = "infineon,irps5401";
 				reg = <0x45>;
 			};
 			/* u68 IR38064 +0 */
@@ -261,6 +368,11 @@
 &i2c1 {
 	status = "okay";
 	clock-frequency = <400000>;
+	pinctrl-names = "default", "gpio";
+	pinctrl-0 = <&pinctrl_i2c1_default>;
+	pinctrl-1 = <&pinctrl_i2c1_gpio>;
+	scl-gpios = <&gpio 16 GPIO_ACTIVE_HIGH>;
+	sda-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>;
 
 	i2c-mux@74 { /* u26 */
 		compatible = "nxp,pca9548";
@@ -289,6 +401,7 @@
 			#size-cells = <0>;
 			reg = <1>;
 			si5341: clock-generator@36 { /* SI5341 - u46 */
+				compatible = "si5341";
 				reg = <0x36>;
 			};
 
@@ -304,6 +417,7 @@
 				temperature-stability = <50>;
 				factory-fout = <300000000>;
 				clock-frequency = <300000000>;
+				clock-output-names = "si570_user";
 			};
 		};
 		i2c@3 {
@@ -316,7 +430,8 @@
 				reg = <0x5d>;
 				temperature-stability = <50>;
 				factory-fout = <156250000>;
-				clock-frequency = <148500000>;
+				clock-frequency = <156250000>;
+				clock-output-names = "si570_mgt";
 			};
 		};
 		i2c@4 {
@@ -324,6 +439,7 @@
 			#size-cells = <0>;
 			reg = <4>;
 			si5328: clock-generator@69 { /* SI5328 - u48 */
+				compatible = "silabs,si5328";
 				reg = <0x69>;
 			};
 		};
@@ -410,6 +526,240 @@
 	};
 };
 
+&pinctrl0 {
+	status = "okay";
+	pinctrl_i2c0_default: i2c0-default {
+		mux {
+			groups = "i2c0_3_grp";
+			function = "i2c0";
+		};
+
+		conf {
+			groups = "i2c0_3_grp";
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_i2c0_gpio: i2c0-gpio {
+		mux {
+			groups = "gpio0_14_grp", "gpio0_15_grp";
+			function = "gpio0";
+		};
+
+		conf {
+			groups = "gpio0_14_grp", "gpio0_15_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_i2c1_default: i2c1-default {
+		mux {
+			groups = "i2c1_4_grp";
+			function = "i2c1";
+		};
+
+		conf {
+			groups = "i2c1_4_grp";
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_i2c1_gpio: i2c1-gpio {
+		mux {
+			groups = "gpio0_16_grp", "gpio0_17_grp";
+			function = "gpio0";
+		};
+
+		conf {
+			groups = "gpio0_16_grp", "gpio0_17_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_uart0_default: uart0-default {
+		mux {
+			groups = "uart0_4_grp";
+			function = "uart0";
+		};
+
+		conf {
+			groups = "uart0_4_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-rx {
+			pins = "MIO18";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO19";
+			bias-disable;
+		};
+	};
+
+	pinctrl_usb0_default: usb0-default {
+		mux {
+			groups = "usb0_0_grp";
+			function = "usb0";
+		};
+
+		conf {
+			groups = "usb0_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-rx {
+			pins = "MIO52", "MIO53", "MIO55";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO54", "MIO56", "MIO57", "MIO58", "MIO59",
+			       "MIO60", "MIO61", "MIO62", "MIO63";
+			bias-disable;
+		};
+	};
+
+	pinctrl_gem3_default: gem3-default {
+		mux {
+			function = "ethernet3";
+			groups = "ethernet3_0_grp";
+		};
+
+		conf {
+			groups = "ethernet3_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-rx {
+			pins = "MIO70", "MIO71", "MIO72", "MIO73", "MIO74",
+									"MIO75";
+			bias-high-impedance;
+			low-power-disable;
+		};
+
+		conf-tx {
+			pins = "MIO64", "MIO65", "MIO66", "MIO67", "MIO68",
+									"MIO69";
+			bias-disable;
+			low-power-enable;
+		};
+
+		mux-mdio {
+			function = "mdio3";
+			groups = "mdio3_0_grp";
+		};
+
+		conf-mdio {
+			groups = "mdio3_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+			bias-disable;
+		};
+	};
+
+	pinctrl_sdhci1_default: sdhci1-default {
+		mux {
+			groups = "sdio1_0_grp";
+			function = "sdio1";
+		};
+
+		conf {
+			groups = "sdio1_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+			bias-disable;
+		};
+
+		mux-cd {
+			groups = "sdio1_cd_0_grp";
+			function = "sdio1_cd";
+		};
+
+		conf-cd {
+			groups = "sdio1_cd_0_grp";
+			bias-high-impedance;
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_gpio_default: gpio-default {
+		mux {
+			function = "gpio0";
+			groups = "gpio0_22_grp", "gpio0_23_grp";
+		};
+
+		conf {
+			groups = "gpio0_22_grp", "gpio0_23_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		mux-msp {
+			function = "gpio0";
+			groups = "gpio0_13_grp", "gpio0_38_grp";
+		};
+
+		conf-msp {
+			groups = "gpio0_13_grp", "gpio0_38_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-pull-up {
+			pins = "MIO22";
+			bias-pull-up;
+		};
+
+		conf-pull-none {
+			pins = "MIO13", "MIO23", "MIO38";
+			bias-disable;
+		};
+	};
+};
+
+&qspi {
+	status = "okay";
+	is-dual = <1>;
+	flash@0 {
+		compatible = "m25p80", "jedec,spi-nor"; /* 32MB */
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x0>;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <4>; /* FIXME also DUAL configuration possible */
+		spi-max-frequency = <108000000>; /* Based on DC1 spec */
+		partition@0 { /* for testing purpose */
+			label = "qspi-fsbl-uboot";
+			reg = <0x0 0x100000>;
+		};
+		partition@100000 { /* for testing purpose */
+			label = "qspi-linux";
+			reg = <0x100000 0x500000>;
+		};
+		partition@600000 { /* for testing purpose */
+			label = "qspi-device-tree";
+			reg = <0x600000 0x20000>;
+		};
+		partition@620000 { /* for testing purpose */
+			label = "qspi-rootfs";
+			reg = <0x620000 0x5E0000>;
+		};
+	};
+};
+
 &rtc {
 	status = "okay";
 };
@@ -425,19 +775,70 @@
 	ceva,p1-comwake-params = /bits/ 8 <0x06 0x14 0x08 0x0E>;
 	ceva,p1-burst-params = /bits/ 8 <0x13 0x08 0x4A 0x06>;
 	ceva,p1-retry-params = /bits/ 16 <0x96A4 0x3FFC>;
+	phy-names = "sata-phy";
+	phys = <&lane3 PHY_TYPE_SATA 1 3 125000000>;
 };
 
 /* SD1 with level shifter */
 &sdhci1 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sdhci1_default>;
+	disable-wp;
+	/*
+	 * This property should be removed for supporting UHS mode
+	 */
 	no-1-8-v;
+	xlnx,mio-bank = <1>;
+};
+
+&serdes {
+	status = "okay";
 };
 
 &uart0 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart0_default>;
 };
 
 /* ULPI SMSC USB3320 */
 &usb0 {
 	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usb0_default>;
+};
+
+&dwc3_0 {
+	status = "okay";
+	dr_mode = "host";
+	snps,usb3_lpm_capable;
+	phy-names = "usb3-phy";
+	phys = <&lane2 PHY_TYPE_USB3 0 2 26000000>;
+};
+
+&zynqmp_dpsub {
+	status = "okay";
+	phy-names = "dp-phy0", "dp-phy1";
+	phys = <&lane1 PHY_TYPE_DP 0 1 27000000>, <&lane0 PHY_TYPE_DP 1 1 27000000>;
+};
+
+&zynqmp_dp_snd_pcm0 {
+	status = "okay";
+};
+
+&zynqmp_dp_snd_pcm1 {
+	status = "okay";
+};
+
+&zynqmp_dp_snd_card0 {
+	status = "okay";
+};
+
+&zynqmp_dp_snd_codec0 {
+	status = "okay";
+};
+
+&xlnx_dpdma {
+	status = "okay";
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/xilinx/zynqmp-zcu1275-revA.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/xilinx/zynqmp-zcu1275-revA.dts
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * dts file for Xilinx ZynqMP ZCU1275
+ *
+ * (C) Copyright 2017 - 2020, Xilinx, Inc.
+ *
+ * Michal Simek <michal.simek@xilinx.com>
+ * Siva Durga Prasad Paladugu <sivadur@xilinx.com>
+ */
+
+/dts-v1/;
+
+#include "zynqmp.dtsi"
+#include "zynqmp-clk-ccf.dtsi"
+
+/ {
+	model = "ZynqMP ZCU1275 RevA";
+	compatible = "xlnx,zynqmp-zcu1275-revA", "xlnx,zynqmp-zcu1275",
+		     "xlnx,zynqmp";
+
+	aliases {
+		serial0 = &uart0;
+		serial1 = &dcc;
+		spi0 = &qspi;
+	};
+
+	chosen {
+		bootargs = "earlycon";
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x80000000>;
+	};
+};
+
+&dcc {
+	status = "okay";
+};
+
+&qspi {
+	status = "okay";
+	flash@0 {
+		compatible = "m25p80", "jedec,spi-nor"; /* 32MB */
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x0>;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <4>; /* FIXME also DUAL configuration possible */
+		spi-max-frequency = <108000000>; /* Based on DC1 spec */
+		partition@0 { /* for testing purpose */
+			label = "qspi-fsbl-uboot";
+			reg = <0x0 0x100000>;
+		};
+		partition@100000 { /* for testing purpose */
+			label = "qspi-linux";
+			reg = <0x100000 0x500000>;
+		};
+		partition@600000 { /* for testing purpose */
+			label = "qspi-device-tree";
+			reg = <0x600000 0x20000>;
+		};
+		partition@620000 { /* for testing purpose */
+			label = "qspi-rootfs";
+			reg = <0x620000 0x5E0000>;
+		};
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/xilinx/zynqmp-zcu1275-revB.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/xilinx/zynqmp-zcu1275-revB.dts
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * dts file for Xilinx ZynqMP ZCU1275 RevB
+ *
+ * (C) Copyright 2018 - 2020, Xilinx, Inc.
+ *
+ * Michal Simek <michal.simek@xilinx.com>
+ * Siva Durga Prasad Paladugu <sivadur@xilinx.com>
+ */
+
+/dts-v1/;
+
+#include "zynqmp.dtsi"
+#include "zynqmp-clk-ccf.dtsi"
+
+/ {
+	model = "ZynqMP ZCU1275 RevB";
+	compatible = "xlnx,zynqmp-zcu1275-revB", "xlnx,zynqmp-zcu1275",
+		     "xlnx,zynqmp";
+
+	aliases {
+		serial0 = &uart0;
+		serial1 = &dcc;
+		spi0 = &qspi;
+		mmc0 = &sdhci1;
+		ethernet0 = &gem1;
+	};
+
+	chosen {
+		bootargs = "earlycon";
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x80000000>;
+	};
+};
+
+&dcc {
+	status = "okay";
+};
+
+&gem1 {
+	status = "okay";
+	/* U-Boot gmii-to-rgmii bridge */
+	phy-mode = "gmii";
+	phy-handle = <&gmiitorgmii>;
+	phy: ethernet-phy@0 {
+		reg = <0x0>;
+	};
+	gmiitorgmii: gmiitorgmii@8 {
+		compatible = "xlnx,gmii-to-rgmii-1.0";
+		reg = <8>;
+		phy-handle = <&phy>;
+	};
+
+	/* Linux gmii-to-rgmii bridge */
+	mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		phy1: ethernet-phy@1 {
+			reg = <1>; /* KSZ9031RNXIC on AES-FMC-NETW1-G */
+			rxc-skew-ps = <1800>; /* Skew control of RX_CLK pad output */
+			txc-skew-ps = <1800>; /* Skew control of GTX_CLK pad input */
+			txen-skew-ps = <900>; /* Skew control of TX_CTL pad input */
+			rxdv-skew-ps = <0>; /* Skew control of RX_CTL pad output */
+			rxd0-skew-ps = <0>; /* Skew control of RXD0 pad output */
+			rxd1-skew-ps = <0>; /* Skew control of RXD1 pad output */
+			rxd2-skew-ps = <0>; /* Skew control of RXD2 pad output */
+			rxd3-skew-ps = <0>; /* Skew control of RXD3 pad output */
+			txd0-skew-ps = <900>; /* Skew control of TXD0 pad input */
+			txd1-skew-ps = <900>; /* Skew control of TXD1 pad input */
+			txd2-skew-ps = <900>; /* Skew control of TXD2 pad input */
+			txd3-skew-ps = <900>; /* Skew control of TXD3 pad input */
+		};
+	};
+};
+
+&qspi {
+	status = "okay";
+	flash@0 {
+		compatible = "m25p80", "jedec,spi-nor"; /* 32MB */
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x0>;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <1>;
+		spi-max-frequency = <108000000>; /* Based on DC1 spec */
+		partition@0 { /* for testing purpose */
+			label = "qspi-fsbl-uboot";
+			reg = <0x0 0x100000>;
+		};
+		partition@100000 { /* for testing purpose */
+			label = "qspi-linux";
+			reg = <0x100000 0x500000>;
+		};
+		partition@600000 { /* for testing purpose */
+			label = "qspi-device-tree";
+			reg = <0x600000 0x20000>;
+		};
+		partition@620000 { /* for testing purpose */
+			label = "qspi-rootfs";
+			reg = <0x620000 0x5E0000>;
+		};
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&sdhci1 {
+	status = "okay";
+	/*
+	 * 1.0 revision has level shifter and this property should be
+	 * removed for supporting UHS mode
+	 */
+	no-1-8-v;
+	xlnx,mio-bank = <1>;
+};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/xilinx/zynqmp-zcu1285-revA.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/xilinx/zynqmp-zcu1285-revA.dts
@@ -0,0 +1,272 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * dts file for Xilinx ZynqMP ZCU1285 RevA
+ *
+ * (C) Copyright 2018 - 2020, Xilinx, Inc.
+ *
+ * Michal Simek <michal.simek@xilinx.com>
+ * Siva Durga Prasad Paladugu <sivadur@xilinx.com>
+ */
+
+/dts-v1/;
+
+#include "zynqmp.dtsi"
+#include "zynqmp-clk-ccf.dtsi"
+
+/ {
+	model = "ZynqMP ZCU1285 RevA";
+	compatible = "xlnx,zynqmp-zcu1285-revA", "xlnx,zynqmp-zcu1285",
+		     "xlnx,zynqmp";
+
+	aliases {
+		serial0 = &uart0;
+		serial1 = &dcc;
+		spi0 = &qspi;
+		mmc0 = &sdhci1;
+		ethernet0 = &gem1; /* EMIO */
+		i2c = &i2c0; /* EMIO */
+	};
+
+	chosen {
+		bootargs = "earlycon";
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x80000000>;
+	};
+
+	ina226-u60 {
+		compatible = "iio-hwmon";
+		io-channels = <&u60 0>, <&u60 1>, <&u60 2>, <&u60 3>;
+	};
+	ina226-u61 {
+		compatible = "iio-hwmon";
+		io-channels = <&u61 0>, <&u61 1>, <&u61 2>, <&u61 3>;
+	};
+	ina226-u63 {
+		compatible = "iio-hwmon";
+		io-channels = <&u63 0>, <&u63 1>, <&u63 2>, <&u63 3>;
+	};
+	ina226-u65 {
+		compatible = "iio-hwmon";
+		io-channels = <&u65 0>, <&u65 1>, <&u65 2>, <&u65 3>;
+	};
+	ina226-u64 {
+		compatible = "iio-hwmon";
+		io-channels = <&u64 0>, <&u64 1>, <&u64 2>, <&u64 3>;
+	};
+};
+
+&dcc {
+	status = "okay";
+};
+
+&i2c0 {
+	status = "okay";
+	clock-frequency = <400000>;
+
+	i2c-mux@75 {
+		compatible = "nxp,pca9548"; /* u22 */
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x75>;
+
+		i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+			/* PMBUS */
+			max20751@74 { /* u23 */
+				compatible = "maxim,max20751";
+				reg = <0x74>;
+			};
+			max20751@70 { /* u89 */
+				compatible = "maxim,max20751";
+				reg = <0x70>;
+			};
+			max15301@a { /* u28 */
+				compatible = "maxim,max15301";
+				reg = <0xa>;
+			};
+			max15303@b { /* u48 */
+				compatible = "maxim,max15303";
+				reg = <0xb>;
+			};
+			max15303@d { /* u27 */
+				compatible = "maxim,max15303";
+				reg = <0xd>;
+			};
+			max15303@e { /* u11 */
+				compatible = "maxim,max15303";
+				reg = <0xe>;
+			};
+			max15303@f { /* u96 */
+				compatible = "maxim,max15303";
+				reg = <0xf>;
+			};
+			max15303@11 { /* u47 */
+				compatible = "maxim,max15303";
+				reg = <0x11>;
+			};
+			max15303@12 { /* u24 */
+				compatible = "maxim,max15303";
+				reg = <0x12>;
+			};
+			max15301@13 { /* u29 */
+				compatible = "maxim,max15301";
+				reg = <0x13>;
+			};
+			max15303@14 { /* u51 */
+				compatible = "maxim,max15303";
+				reg = <0x14>;
+			};
+			max15303@15 { /* u30 */
+				compatible = "maxim,max15303";
+				reg = <0x15>;
+			};
+			max15303@16 { /* u102 */
+				compatible = "maxim,max15303";
+				reg = <0x16>;
+			};
+			max15301@17 { /* u50 */
+				compatible = "maxim,max15301";
+				reg = <0x17>;
+			};
+			max15301@18 { /* u31 */
+				compatible = "maxim,max15301";
+				reg = <0x18>;
+			};
+		};
+		i2c@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+			/* CM_I2C */
+		};
+		i2c@2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+			/* SYS_EEPROM */
+			eeprom: eeprom@54 { /* u101 */
+				compatible = "atmel,24c32"; /* 24LC32A */
+				reg = <0x54>;
+			};
+		};
+		i2c@3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+			/* FMC1 */
+		};
+		i2c@4 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <4>;
+			/* FMC2 */
+		};
+		i2c@5 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <5>;
+			/* ANALOG_PMBUS */
+			u60: ina226@40 { /* u60 */
+				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u60";
+				reg = <0x40>;
+				shunt-resistor = <1000>;
+			};
+			u61: ina226@41 { /* u61 */
+				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u61";
+				reg = <0x41>;
+				shunt-resistor = <1000>;
+			};
+			u63: ina226@42 { /* u63 */
+				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u63";
+				reg = <0x42>;
+				shunt-resistor = <1000>;
+			};
+			u65: ina226@43 { /* u65 */
+				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u65";
+				reg = <0x43>;
+				shunt-resistor = <1000>;
+			};
+			u64: ina226@44 { /* u64 */
+				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-u64";
+				reg = <0x44>;
+				shunt-resistor = <1000>;
+			};
+		};
+		i2c@6 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <6>;
+			/* ANALOG_CM_I2C */
+		};
+		i2c@7 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <7>;
+			/* FMC3 */
+		};
+	};
+};
+
+&gem1 {
+	mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		phy1: ethernet-phy@1 {
+			reg = <1>; /* KSZ9031RNXIC on AES-FMC-NETW1-G */
+			rxc-skew-ps = <1800>; /* Skew control of RX_CLK pad output */
+			txc-skew-ps = <1800>; /* Skew control of GTX_CLK pad input */
+			txen-skew-ps = <900>; /* Skew control of TX_CTL pad input */
+			rxdv-skew-ps = <0>; /* Skew control of RX_CTL pad output */
+			rxd0-skew-ps = <0>; /* Skew control of RXD0 pad output */
+			rxd1-skew-ps = <0>; /* Skew control of RXD1 pad output */
+			rxd2-skew-ps = <0>; /* Skew control of RXD2 pad output */
+			rxd3-skew-ps = <0>; /* Skew control of RXD3 pad output */
+			txd0-skew-ps = <900>; /* Skew control of TXD0 pad input */
+			txd1-skew-ps = <900>; /* Skew control of TXD1 pad input */
+			txd2-skew-ps = <900>; /* Skew control of TXD2 pad input */
+			txd3-skew-ps = <900>; /* Skew control of TXD3 pad input */
+		};
+	};
+};
+
+&qspi {
+	status = "okay";
+	flash@0 {
+		compatible = "m25p80", "jedec,spi-nor"; /* 32MB */
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x0>;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <1>;
+		spi-max-frequency = <108000000>; /* Based on DC1 spec */
+	};
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&sdhci1 {
+	status = "okay";
+	/*
+	 * This property should be removed for supporting UHS mode
+	 */
+	no-1-8-v;
+	xlnx,mio-bank = <1>;
+};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/xilinx/zynqmp-zcu208-revA.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/xilinx/zynqmp-zcu208-revA.dts
@@ -0,0 +1,658 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * dts file for Xilinx ZynqMP ZCU208
+ *
+ * (C) Copyright 2017 - 2020, Xilinx, Inc.
+ *
+ * Michal Simek <michal.simek@xilinx.com>
+ */
+
+/dts-v1/;
+
+#include "zynqmp.dtsi"
+#include "zynqmp-clk-ccf.dtsi"
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
+#include <dt-bindings/phy/phy.h>
+
+/ {
+	model = "ZynqMP ZCU208 RevA";
+	compatible = "xlnx,zynqmp-zcu208-revA", "xlnx,zynqmp-zcu208", "xlnx,zynqmp";
+
+	aliases {
+		ethernet0 = &gem3;
+		gpio0 = &gpio;
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+		mmc0 = &sdhci1;
+		rtc0 = &rtc;
+		serial0 = &uart0;
+		serial1 = &dcc;
+		spi0 = &qspi;
+		usb0 = &usb0;
+	};
+
+	chosen {
+		bootargs = "earlycon";
+		stdout-path = "serial0:115200n8";
+		xlnx,eeprom = &eeprom;
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x80000000>, <0x8 0x00000000 0x0 0x80000000>;
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		autorepeat;
+		sw19 {
+			label = "sw19";
+			gpios = <&gpio 22 GPIO_ACTIVE_HIGH>;
+			linux,code = <KEY_DOWN>;
+			wakeup-source;
+			autorepeat;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		heartbeat_led {
+			label = "heartbeat";
+			gpios = <&gpio 23 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+
+	ina226-vccint {
+		compatible = "iio-hwmon";
+		io-channels = <&vccint 0>, <&vccint 1>, <&vccint 2>, <&vccint 3>;
+	};
+	ina226-vccint-io-bram-ps {
+		compatible = "iio-hwmon";
+		io-channels = <&vccint_io_bram_ps 0>, <&vccint_io_bram_ps 1>, <&vccint_io_bram_ps 2>, <&vccint_io_bram_ps 3>;
+	};
+	ina226-vcc1v8 {
+		compatible = "iio-hwmon";
+		io-channels = <&vcc1v8 0>, <&vcc1v8 1>, <&vcc1v8 2>, <&vcc1v8 3>;
+	};
+	ina226-vcc1v2 {
+		compatible = "iio-hwmon";
+		io-channels = <&vcc1v2 0>, <&vcc1v2 1>, <&vcc1v2 2>, <&vcc1v2 3>;
+	};
+	ina226-vadj-fmc {
+		compatible = "iio-hwmon";
+		io-channels = <&vadj_fmc 0>, <&vadj_fmc 1>, <&vadj_fmc 2>, <&vadj_fmc 3>;
+	};
+	ina226-mgtavcc {
+		compatible = "iio-hwmon";
+		io-channels = <&mgtavcc 0>, <&mgtavcc 1>, <&mgtavcc 2>, <&mgtavcc 3>;
+	};
+	ina226-mgt1v2 {
+		compatible = "iio-hwmon";
+		io-channels = <&mgt1v2 0>, <&mgt1v2 1>, <&mgt1v2 2>, <&mgt1v2 3>;
+	};
+	ina226-mgt1v8 {
+		compatible = "iio-hwmon";
+		io-channels = <&mgt1v8 0>, <&mgt1v8 1>, <&mgt1v8 2>, <&mgt1v8 3>;
+	};
+	ina226-vccint-ams {
+		compatible = "iio-hwmon";
+		io-channels = <&vccint_ams 0>, <&vccint_ams 1>, <&vccint_ams 2>, <&vccint_ams 3>;
+	};
+	ina226-dac-avtt {
+		compatible = "iio-hwmon";
+		io-channels = <&dac_avtt 0>, <&dac_avtt 1>, <&dac_avtt 2>, <&dac_avtt 3>;
+	};
+	ina226-dac-avccaux {
+		compatible = "iio-hwmon";
+		io-channels = <&dac_avccaux 0>, <&dac_avccaux 1>, <&dac_avccaux 2>, <&dac_avccaux 3>;
+	};
+	ina226-adc-avcc {
+		compatible = "iio-hwmon";
+		io-channels = <&adc_avcc 0>, <&adc_avcc 1>, <&adc_avcc 2>, <&adc_avcc 3>;
+	};
+	ina226-adc-avccaux {
+		compatible = "iio-hwmon";
+		io-channels = <&adc_avccaux 0>, <&adc_avccaux 1>, <&adc_avccaux 2>, <&adc_avccaux 3>;
+	};
+	ina226-dac-avcc {
+		compatible = "iio-hwmon";
+		io-channels = <&dac_avcc 0>, <&dac_avcc 1>, <&dac_avcc 2>, <&dac_avcc 3>;
+	};
+};
+
+&dcc {
+	status = "okay";
+};
+
+&fpd_dma_chan1 {
+	status = "okay";
+};
+
+&fpd_dma_chan2 {
+	status = "okay";
+};
+
+&fpd_dma_chan3 {
+	status = "okay";
+};
+
+&fpd_dma_chan4 {
+	status = "okay";
+};
+
+&fpd_dma_chan5 {
+	status = "okay";
+};
+
+&fpd_dma_chan6 {
+	status = "okay";
+};
+
+&fpd_dma_chan7 {
+	status = "okay";
+};
+
+&fpd_dma_chan8 {
+	status = "okay";
+};
+
+&gem3 {
+	status = "okay";
+	phy-handle = <&phy0>;
+	phy-mode = "rgmii-id";
+	phy0: ethernet-phy@c {
+		reg = <0xc>;
+		ti,rx-internal-delay = <0x8>;
+		ti,tx-internal-delay = <0xa>;
+		ti,fifo-depth = <0x1>;
+		ti,dp83867-rxctrl-strap-quirk;
+	};
+};
+
+&gpio {
+	status = "okay";
+	gpio-line-names = "QSPI_LWR_CLK", "QSPI_LWR_DQ1", "QSPI_LWR_DQ2", "QSPI_LWR_DQ3", "QSPI_LWR_DQ0", /* 0 - 4 */
+		  "QSPI_LWR_CS_B", "", "QSPI_UPR_CS_B", "QSPI_UPR_DQ0", "QSPI_UPR_DQ1", /* 5 - 9 */
+		  "QSPI_UPR_DQ2", "QSPI_UPR_DQ3", "QSPI_UPR_CLK", "PS_GPIO2", "I2C0_SCL", /* 10 - 14 */
+		  "I2C0_SDA", "I2C1_SCL", "I2C1_SDA", "UART0_TXD", "UART0_RXD", /* 15 - 19 */
+		  "", "", "BUTTON", "LED", "", /* 20 - 24 */
+		  "", "PMU_INPUT", "", "", "", /* 25 - 29 */
+		  "", "", "PMU_GPO0", "PMU_GPO1", "PMU_GPO2", /* 30 - 34 */
+		  "PMU_GPO3", "PMU_GPO4", "PMU_GPO5", "PS_GPIO1", "SDIO_SEL", /* 35 - 39 */
+		  "SDIO_DIR_CMD", "SDIO_DIR_DAT0", "SDIO_DIR_DAT1", "", "", /* 40 - 44 */
+		  "SDIO_DETECT", "SDIO_DAT0", "SDIO_DAT1", "SDIO_DAT2", "SDIO_DAT3", /* 45 - 49 */
+		  "SDIO_CMD", "SDIO_CLK", "USB_CLK", "USB_DIR", "USB_DATA2", /* 50 - 54 */
+		  "USB_NXT", "USB_DATA0", "USB_DATA1", "USB_STP", "USB_DATA3", /* 55 - 59 */
+		  "USB_DATA4", "USB_DATA5", "USB_DATA6", "USB_DATA7", "ENET_TX_CLK", /* 60 - 64 */
+		  "ENET_TX_D0", "ENET_TX_D1", "ENET_TX_D2", "ENET_TX_D3", "ENET_TX_CTRL", /* 65 - 69 */
+		  "ENET_RX_CLK", "ENET_RX_D0", "ENET_RX_D1", "ENET_RX_D2", "ENET_RX_D3", /* 70 - 74 */
+		  "ENET_RX_CTRL", "ENET_MDC", "ENET_MDIO", /* 75 - 77, MIO end and EMIO start */
+		  "", "", /* 78 - 79 */
+		  "", "", "", "", "", /* 80 - 84 */
+		  "", "", "", "", "", /* 85 -89 */
+		  "", "", "", "", "", /* 90 - 94 */
+		  "", "", "", "", "", /* 95 - 99 */
+		  "", "", "", "", "", /* 100 - 104 */
+		  "", "", "", "", "", /* 105 - 109 */
+		  "", "", "", "", "", /* 110 - 114 */
+		  "", "", "", "", "", /* 115 - 119 */
+		  "", "", "", "", "", /* 120 - 124 */
+		  "", "", "", "", "", /* 125 - 129 */
+		  "", "", "", "", "", /* 130 - 134 */
+		  "", "", "", "", "", /* 135 - 139 */
+		  "", "", "", "", "", /* 140 - 144 */
+		  "", "", "", "", "", /* 145 - 149 */
+		  "", "", "", "", "", /* 150 - 154 */
+		  "", "", "", "", "", /* 155 - 159 */
+		  "", "", "", "", "", /* 160 - 164 */
+		  "", "", "", "", "", /* 165 - 169 */
+		  "", "", "", ""; /* 170 - 174 */
+};
+
+&i2c0 {
+	status = "okay";
+	clock-frequency = <400000>;
+	pinctrl-names = "default", "gpio";
+	pinctrl-0 = <&pinctrl_i2c0_default>;
+	pinctrl-1 = <&pinctrl_i2c0_gpio>;
+	scl-gpios = <&gpio 14 GPIO_ACTIVE_HIGH>;
+	sda-gpios = <&gpio 15 GPIO_ACTIVE_HIGH>;
+
+	tca6416_u15: gpio@20 { /* u15 */
+		compatible = "ti,tca6416";
+		reg = <0x20>;
+		gpio-controller; /* interrupt not connected */
+		#gpio-cells = <2>;
+		gpio-line-names = "MAX6643_OT_B", "MAX6643_FANFAIL_B", "MIO26_PMU_INPUT_LS", "DAC_AVTT_VOUT_SEL", /* 0 - 3 */
+				  "", "IIC_MUX_RESET_B", "GEM3_EXP_RESET_B", "MAX6643_FULL_SPEED", /* 4 - 7 */
+				  "FMCP_HSPC_PRSNT_M2C_B", "", "", "VCCINT_VRHOT_B", /* 10 - 13 */
+				  "", "8A34001_EXP_RST_B", "IRPS5401_ALERT_B", "INA226_PMBUS_ALERT"; /* 14 - 17 */
+	};
+
+	i2c-mux@75 { /* u17 */
+		compatible = "nxp,pca9544";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x75>;
+		i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+			/* PS_PMBUS */
+			/* PMBUS_ALERT done via pca9544 */
+			vccint: ina226@40 { /* u65 */
+				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-vccint";
+				reg = <0x40>;
+				shunt-resistor = <5000>;
+			};
+			vccint_io_bram_ps: ina226@41 { /* u57 */
+				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-vccint-io-bram-ps";
+				reg = <0x41>;
+				shunt-resistor = <5000>;
+			};
+			vcc1v8: ina226@42 { /* u60 */
+				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-vcc1v8";
+				reg = <0x42>;
+				shunt-resistor = <2000>;
+			};
+			vcc1v2: ina226@43 { /* u58 */
+				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-vcc1v2";
+				reg = <0x43>;
+				shunt-resistor = <5000>;
+			};
+			vadj_fmc: ina226@45 { /* u62 */
+				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-vadj-fmc";
+				reg = <0x45>;
+				shunt-resistor = <5000>;
+			};
+			mgtavcc: ina226@46 { /* u67 */
+				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-mgtavcc";
+				reg = <0x46>;
+				shunt-resistor = <2000>;
+			};
+			mgt1v2: ina226@47 { /* u63 */
+				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-mgt1v2";
+				reg = <0x47>;
+				shunt-resistor = <5000>;
+			};
+			mgt1v8: ina226@48 { /* u64 */
+				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-mgt1v8";
+				reg = <0x48>;
+				shunt-resistor = <5000>;
+			};
+			vccint_ams: ina226@49 { /* u61 */
+				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-vccint-ams";
+				reg = <0x49>;
+				shunt-resistor = <5000>;
+			};
+			dac_avtt: ina226@4a { /* u59 */
+				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-dac-avtt";
+				reg = <0x4a>;
+				shunt-resistor = <5000>;
+			};
+			dac_avccaux: ina226@4b { /* u124 */
+				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-dac-avccaux";
+				reg = <0x4b>;
+				shunt-resistor = <5000>;
+			};
+			adc_avcc: ina226@4c { /* u75 */
+				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-adc-avcc";
+				reg = <0x4c>;
+				shunt-resistor = <5000>;
+			};
+			adc_avccaux: ina226@4d { /* u71 */
+				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-adc-avccaux";
+				reg = <0x4d>;
+				shunt-resistor = <5000>;
+			};
+			dac_avcc: ina226@4e { /* u77 */
+				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-dac-avcc";
+				reg = <0x4e>;
+				shunt-resistor = <5000>;
+			};
+		};
+		i2c@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+			/* NC */
+		};
+		i2c@2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+			/* u104 - ir35215 0x10/0x40 */
+			/* u127 - ir38164 0x1b/0x4b */
+			/* u112 - ir38164 0x13/0x43 */
+			/* u123 - ir38164 0x1c/0x4c */
+
+			irps5401_44: irps5401@44 { /* IRPS5401 - u53 */
+				compatible = "infineon,irps5401";
+				reg = <0x44>; /* i2c addr 0x14 */
+			};
+			irps5401_45: irps5401@45 { /* IRPS5401 - u55 */
+				compatible = "infineon,irps5401";
+				reg = <0x45>; /* i2c addr 0x15 */
+			};
+			/* J21 header too */
+
+		};
+		i2c@3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+			/* SYSMON */
+		};
+	};
+	/* u38 MPS430 */
+};
+
+&i2c1 {
+	status = "okay";
+	clock-frequency = <400000>;
+	pinctrl-names = "default", "gpio";
+	pinctrl-0 = <&pinctrl_i2c1_default>;
+	pinctrl-1 = <&pinctrl_i2c1_gpio>;
+	scl-gpios = <&gpio 16 GPIO_ACTIVE_HIGH>;
+	sda-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>;
+
+	i2c-mux@74 {
+		compatible = "nxp,pca9548"; /* u20 */
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x74>;
+		/* FIXME reset-gpios = <&tca6416_u15 SYSCTLR_IIC_MUX0_RESET_B GPIO_ACTIVE_HIGH>; */
+		i2c_eeprom: i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+			/*
+			 * IIC_EEPROM 1kB memory which uses 256B blocks
+			 * where every block has different address.
+			 *    0 - 256B address 0x54
+			 * 256B - 512B address 0x55
+			 * 512B - 768B address 0x56
+			 * 768B - 1024B address 0x57
+			 */
+			eeprom: eeprom@54 { /* u21 */
+				compatible = "atmel,24c128";
+				reg = <0x54>;
+			};
+		};
+		i2c_si5341: i2c@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+			si5341: clock-generator@36 { /* SI5341 - u43 */
+				compatible = "si5341";
+				reg = <0x36>;
+			};
+
+		};
+		i2c_si570_user_c0: i2c@2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+			si570_1: clock-generator@5d { /* USER C0 SI570 - u47 */
+				#clock-cells = <0>;
+				compatible = "silabs,si570";
+				reg = <0x5d>;
+				temperature-stability = <50>;
+				factory-fout = <300000000>;
+				clock-frequency = <300000000>;
+				clock-output-names = "si570_user_c0";
+			};
+		};
+		i2c_si570_mgt: i2c@3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+			si570_2: clock-generator@5d { /* USER MGT SI570 - u48 */
+				#clock-cells = <0>;
+				compatible = "silabs,si570";
+				reg = <0x5d>;
+				temperature-stability = <50>;
+				factory-fout = <156250000>;
+				clock-frequency = <148500000>;
+				clock-output-names = "si570_mgt";
+			};
+		};
+		i2c_8a34001: i2c@4 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <4>;
+			/* U409B - 8a34001 */
+		};
+		i2c_clk104: i2c@5 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <5>;
+			/* CLK104_SDA */
+		};
+		i2c@6 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <6>;
+			/* RFMCP connector */
+		};
+		/* 7 NC */
+	};
+
+	i2c-mux@75 {
+		compatible = "nxp,pca9548"; /* u22 */
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x75>;
+		/* FIXME reset-gpios = <&tca6416_u15 SYSCTLR_IIC_MUX0_RESET_B GPIO_ACTIVE_HIGH>; */
+		i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+			/* FMCP_HSPC_IIC */
+		};
+		i2c_si570_user_c1: i2c@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+			si570_3: clock-generator@5d { /* USER C1 SI570 - u130 */
+				#clock-cells = <0>;
+				compatible = "silabs,si570";
+				reg = <0x5d>;
+				temperature-stability = <50>;
+				factory-fout = <300000000>;
+				clock-frequency = <300000000>;
+				clock-output-names = "si570_user_c1";
+			};
+		};
+		i2c@2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+			/* SYSMON */
+		};
+		i2c@3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+			/* DDR4 SODIMM */
+		};
+		i2c@4 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <4>;
+			/* SFP3 */
+		};
+		i2c@5 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <5>;
+			/* SFP2 */
+		};
+		i2c@6 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <6>;
+			/* SFP1 */
+		};
+		i2c@7 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <7>;
+			/* SFP0 */
+		};
+	};
+	/* MSP430 */
+};
+
+&pinctrl0 {
+	status = "okay";
+	pinctrl_i2c0_default: i2c0-default {
+		mux {
+			groups = "i2c0_3_grp";
+			function = "i2c0";
+		};
+
+		conf {
+			groups = "i2c0_3_grp";
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_i2c0_gpio: i2c0-gpio {
+		mux {
+			groups = "gpio0_14_grp", "gpio0_15_grp";
+			function = "gpio0";
+		};
+
+		conf {
+			groups = "gpio0_14_grp", "gpio0_15_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_i2c1_default: i2c1-default {
+		mux {
+			groups = "i2c1_4_grp";
+			function = "i2c1";
+		};
+
+		conf {
+			groups = "i2c1_4_grp";
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_i2c1_gpio: i2c1-gpio {
+		mux {
+			groups = "gpio0_16_grp", "gpio0_17_grp";
+			function = "gpio0";
+		};
+
+		conf {
+			groups = "gpio0_16_grp", "gpio0_17_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+};
+
+&qspi {
+	status = "okay";
+	is-dual = <1>;
+	flash@0 {
+		compatible = "m25p80", "jedec,spi-nor"; /* U11 and U12 MT25QU02GCBBE12 1Gb */
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0>;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <4>; /* FIXME also DUAL configuration possible */
+		spi-max-frequency = <108000000>; /* Based on DC1 spec */
+	};
+};
+
+&rtc {
+	status = "okay";
+};
+
+&sata {
+	status = "okay";
+	/* SATA OOB timing settings */
+	ceva,p0-cominit-params = /bits/ 8 <0x18 0x40 0x18 0x28>;
+	ceva,p0-comwake-params = /bits/ 8 <0x06 0x14 0x08 0x0E>;
+	ceva,p0-burst-params = /bits/ 8 <0x13 0x08 0x4A 0x06>;
+	ceva,p0-retry-params = /bits/ 16 <0x96A4 0x3FFC>;
+	ceva,p1-cominit-params = /bits/ 8 <0x18 0x40 0x18 0x28>;
+	ceva,p1-comwake-params = /bits/ 8 <0x06 0x14 0x08 0x0E>;
+	ceva,p1-burst-params = /bits/ 8 <0x13 0x08 0x4A 0x06>;
+	ceva,p1-retry-params = /bits/ 16 <0x96A4 0x3FFC>;
+	phy-names = "sata-phy";
+	phys = <&lane3 PHY_TYPE_SATA 1 3 125000000>;
+};
+
+/* SD1 with level shifter */
+&sdhci1 {
+	status = "okay";
+	disable-wp;
+	/*
+	 * This property should be removed for supporting UHS mode
+	 */
+	no-1-8-v;
+	xlnx,mio-bank = <1>;
+};
+
+&serdes {
+	status = "okay";
+};
+
+&uart0 {
+	status = "okay";
+};
+
+/* ULPI SMSC USB3320 */
+&usb0 {
+	status = "okay";
+};
+
+&dwc3_0 {
+	status = "okay";
+	dr_mode = "host";
+	snps,usb3_lpm_capable;
+	phy-names = "usb3-phy";
+	phys = <&lane2 PHY_TYPE_USB3 0 2 26000000>;
+};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/xilinx/zynqmp-zcu216-revA.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/xilinx/zynqmp-zcu216-revA.dts
@@ -0,0 +1,662 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * dts file for Xilinx ZynqMP ZCU216
+ *
+ * (C) Copyright 2017 - 2020, Xilinx, Inc.
+ *
+ * Michal Simek <michal.simek@xilinx.com>
+ */
+
+/dts-v1/;
+
+#include "zynqmp.dtsi"
+#include "zynqmp-clk-ccf.dtsi"
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
+#include <dt-bindings/phy/phy.h>
+
+/ {
+	model = "ZynqMP ZCU216 RevA";
+	compatible = "xlnx,zynqmp-zcu216-revA", "xlnx,zynqmp-zcu216", "xlnx,zynqmp";
+
+	aliases {
+		ethernet0 = &gem3;
+		gpio0 = &gpio;
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+		mmc0 = &sdhci1;
+		rtc0 = &rtc;
+		serial0 = &uart0;
+		serial1 = &dcc;
+		spi0 = &qspi;
+		usb0 = &usb0;
+	};
+
+	chosen {
+		bootargs = "earlycon";
+		stdout-path = "serial0:115200n8";
+		xlnx,eeprom = <&eeprom>;
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x0 0x0 0x0 0x80000000>, <0x8 0x00000000 0x0 0x80000000>;
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		autorepeat;
+		sw19 {
+			label = "sw19";
+			gpios = <&gpio 22 GPIO_ACTIVE_HIGH>;
+			linux,code = <KEY_DOWN>;
+			wakeup-source;
+			autorepeat;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		heartbeat_led {
+			label = "heartbeat";
+			gpios = <&gpio 23 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+
+	ina226-vccint {
+		compatible = "iio-hwmon";
+		io-channels = <&vccint 0>, <&vccint 1>, <&vccint 2>, <&vccint 3>;
+	};
+	ina226-vccint-io-bram-ps {
+		compatible = "iio-hwmon";
+		io-channels = <&vccint_io_bram_ps 0>, <&vccint_io_bram_ps 1>, <&vccint_io_bram_ps 2>, <&vccint_io_bram_ps 3>;
+	};
+	ina226-vcc1v8 {
+		compatible = "iio-hwmon";
+		io-channels = <&vcc1v8 0>, <&vcc1v8 1>, <&vcc1v8 2>, <&vcc1v8 3>;
+	};
+	ina226-vcc1v2 {
+		compatible = "iio-hwmon";
+		io-channels = <&vcc1v2 0>, <&vcc1v2 1>, <&vcc1v2 2>, <&vcc1v2 3>;
+	};
+	ina226-vadj-fmc {
+		compatible = "iio-hwmon";
+		io-channels = <&vadj_fmc 0>, <&vadj_fmc 1>, <&vadj_fmc 2>, <&vadj_fmc 3>;
+	};
+	ina226-mgtavcc {
+		compatible = "iio-hwmon";
+		io-channels = <&mgtavcc 0>, <&mgtavcc 1>, <&mgtavcc 2>, <&mgtavcc 3>;
+	};
+	ina226-mgt1v2 {
+		compatible = "iio-hwmon";
+		io-channels = <&mgt1v2 0>, <&mgt1v2 1>, <&mgt1v2 2>, <&mgt1v2 3>;
+	};
+	ina226-mgt1v8 {
+		compatible = "iio-hwmon";
+		io-channels = <&mgt1v8 0>, <&mgt1v8 1>, <&mgt1v8 2>, <&mgt1v8 3>;
+	};
+	ina226-vccint-ams {
+		compatible = "iio-hwmon";
+		io-channels = <&vccint_ams 0>, <&vccint_ams 1>, <&vccint_ams 2>, <&vccint_ams 3>;
+	};
+	ina226-dac-avtt {
+		compatible = "iio-hwmon";
+		io-channels = <&dac_avtt 0>, <&dac_avtt 1>, <&dac_avtt 2>, <&dac_avtt 3>;
+	};
+	ina226-dac-avccaux {
+		compatible = "iio-hwmon";
+		io-channels = <&dac_avccaux 0>, <&dac_avccaux 1>, <&dac_avccaux 2>, <&dac_avccaux 3>;
+	};
+	ina226-adc-avcc {
+		compatible = "iio-hwmon";
+		io-channels = <&adc_avcc 0>, <&adc_avcc 1>, <&adc_avcc 2>, <&adc_avcc 3>;
+	};
+	ina226-adc-avccaux {
+		compatible = "iio-hwmon";
+		io-channels = <&adc_avccaux 0>, <&adc_avccaux 1>, <&adc_avccaux 2>, <&adc_avccaux 3>;
+	};
+	ina226-dac-avcc {
+		compatible = "iio-hwmon";
+		io-channels = <&dac_avcc 0>, <&dac_avcc 1>, <&dac_avcc 2>, <&dac_avcc 3>;
+	};
+};
+
+&dcc {
+	status = "okay";
+};
+
+&fpd_dma_chan1 {
+	status = "okay";
+};
+
+&fpd_dma_chan2 {
+	status = "okay";
+};
+
+&fpd_dma_chan3 {
+	status = "okay";
+};
+
+&fpd_dma_chan4 {
+	status = "okay";
+};
+
+&fpd_dma_chan5 {
+	status = "okay";
+};
+
+&fpd_dma_chan6 {
+	status = "okay";
+};
+
+&fpd_dma_chan7 {
+	status = "okay";
+};
+
+&fpd_dma_chan8 {
+	status = "okay";
+};
+
+&gem3 {
+	status = "okay";
+	phy-handle = <&phy0>;
+	phy-mode = "rgmii-id";
+	phy0: ethernet-phy@c {
+		reg = <0xc>;
+		ti,rx-internal-delay = <0x8>;
+		ti,tx-internal-delay = <0xa>;
+		ti,fifo-depth = <0x1>;
+		ti,dp83867-rxctrl-strap-quirk;
+	};
+};
+
+&gpio {
+	status = "okay";
+	gpio-line-names = "QSPI_LWR_CLK", "QSPI_LWR_DQ1", "QSPI_LWR_DQ2", "QSPI_LWR_DQ3", "QSPI_LWR_DQ0", /* 0 - 4 */
+		  "QSPI_LWR_CS_B", "", "QSPI_UPR_CS_B", "QSPI_UPR_DQ0", "QSPI_UPR_DQ1", /* 5 - 9 */
+		  "QSPI_UPR_DQ2", "QSPI_UPR_DQ3", "QSPI_UPR_CLK", "PS_GPIO2", "I2C0_SCL", /* 10 - 14 */
+		  "I2C0_SDA", "I2C1_SCL", "I2C1_SDA", "UART0_TXD", "UART0_RXD", /* 15 - 19 */
+		  "", "", "BUTTON", "LED", "", /* 20 - 24 */
+		  "", "PMU_INPUT", "", "", "", /* 25 - 29 */
+		  "", "", "PMU_GPO0", "PMU_GPO1", "PMU_GPO2", /* 30 - 34 */
+		  "PMU_GPO3", "PMU_GPO4", "PMU_GPO5", "PS_GPIO1", "SDIO_SEL", /* 35 - 39 */
+		  "SDIO_DIR_CMD", "SDIO_DIR_DAT0", "SDIO_DIR_DAT1", "", "", /* 40 - 44 */
+		  "SDIO_DETECT", "SDIO_DAT0", "SDIO_DAT1", "SDIO_DAT2", "SDIO_DAT3", /* 45 - 49 */
+		  "SDIO_CMD", "SDIO_CLK", "USB_CLK", "USB_DIR", "USB_DATA2", /* 50 - 54 */
+		  "USB_NXT", "USB_DATA0", "USB_DATA1", "USB_STP", "USB_DATA3", /* 55 - 59 */
+		  "USB_DATA4", "USB_DATA5", "USB_DATA6", "USB_DATA7", "ENET_TX_CLK", /* 60 - 64 */
+		  "ENET_TX_D0", "ENET_TX_D1", "ENET_TX_D2", "ENET_TX_D3", "ENET_TX_CTRL", /* 65 - 69 */
+		  "ENET_RX_CLK", "ENET_RX_D0", "ENET_RX_D1", "ENET_RX_D2", "ENET_RX_D3", /* 70 - 74 */
+		  "ENET_RX_CTRL", "ENET_MDC", "ENET_MDIO", /* 75 - 77, MIO end and EMIO start */
+		  "", "", /* 78 - 79 */
+		  "", "", "", "", "", /* 80 - 84 */
+		  "", "", "", "", "", /* 85 -89 */
+		  "", "", "", "", "", /* 90 - 94 */
+		  "", "", "", "", "", /* 95 - 99 */
+		  "", "", "", "", "", /* 100 - 104 */
+		  "", "", "", "", "", /* 105 - 109 */
+		  "", "", "", "", "", /* 110 - 114 */
+		  "", "", "", "", "", /* 115 - 119 */
+		  "", "", "", "", "", /* 120 - 124 */
+		  "", "", "", "", "", /* 125 - 129 */
+		  "", "", "", "", "", /* 130 - 134 */
+		  "", "", "", "", "", /* 135 - 139 */
+		  "", "", "", "", "", /* 140 - 144 */
+		  "", "", "", "", "", /* 145 - 149 */
+		  "", "", "", "", "", /* 150 - 154 */
+		  "", "", "", "", "", /* 155 - 159 */
+		  "", "", "", "", "", /* 160 - 164 */
+		  "", "", "", "", "", /* 165 - 169 */
+		  "", "", "", ""; /* 170 - 174 */
+};
+
+&gpu {
+	status = "okay";
+};
+
+&i2c0 {
+	status = "okay";
+	clock-frequency = <400000>;
+	pinctrl-names = "default", "gpio";
+	pinctrl-0 = <&pinctrl_i2c0_default>;
+	pinctrl-1 = <&pinctrl_i2c0_gpio>;
+	scl-gpios = <&gpio 14 GPIO_ACTIVE_HIGH>;
+	sda-gpios = <&gpio 15 GPIO_ACTIVE_HIGH>;
+
+	tca6416_u15: gpio@20 { /* u15 */
+		compatible = "ti,tca6416";
+		reg = <0x20>;
+		gpio-controller; /* interrupt not connected */
+		#gpio-cells = <2>;
+		gpio-line-names = "MAX6643_OT_B", "MAX6643_FANFAIL_B", "MIO26_PMU_INPUT_LS", "", /* 0 - 3 */
+				  "", "IIC_MUX_RESET_B", "GEM3_EXP_RESET_B", "MAX6643_FULL_SPEED", /* 4 - 7 */
+				  "FMCP_HSPC_PRSNT_M2C_B", "", "", "VCCINT_VRHOT_B", /* 10 - 13 */
+				  "", "8A34001_EXP_RST_B", "IRPS5401_ALERT_B", "INA226_PMBUS_ALERT"; /* 14 - 17 */
+	};
+
+	i2c-mux@75 { /* u17 */
+		compatible = "nxp,pca9544";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x75>;
+		i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+			/* PS_PMBUS */
+			/* PMBUS_ALERT done via pca9544 */
+			vccint: ina226@40 { /* u65 */
+				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-vccint";
+				reg = <0x40>;
+				shunt-resistor = <5000>;
+			};
+			vccint_io_bram_ps: ina226@41 { /* u57 */
+				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-vccint-io-bram-ps";
+				reg = <0x41>;
+				shunt-resistor = <5000>;
+			};
+			vcc1v8: ina226@42 { /* u60 */
+				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-vcc1v8";
+				reg = <0x42>;
+				shunt-resistor = <2000>;
+			};
+			vcc1v2: ina226@43 { /* u58 */
+				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-vcc1v2";
+				reg = <0x43>;
+				shunt-resistor = <5000>;
+			};
+			vadj_fmc: ina226@45 { /* u62 */
+				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-vadj-fmc";
+				reg = <0x45>;
+				shunt-resistor = <5000>;
+			};
+			mgtavcc: ina226@46 { /* u67 */
+				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-mgtavcc";
+				reg = <0x46>;
+				shunt-resistor = <2000>;
+			};
+			mgt1v2: ina226@47 { /* u63 */
+				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-mgt1v2";
+				reg = <0x47>;
+				shunt-resistor = <5000>;
+			};
+			mgt1v8: ina226@48 { /* u64 */
+				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-mgt1v8";
+				reg = <0x48>;
+				shunt-resistor = <5000>;
+			};
+			vccint_ams: ina226@49 { /* u61 */
+				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-vccint-ams";
+				reg = <0x49>;
+				shunt-resistor = <5000>;
+			};
+			dac_avtt: ina226@4a { /* u59 */
+				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-dac-avtt";
+				reg = <0x4a>;
+				shunt-resistor = <5000>;
+			};
+			dac_avccaux: ina226@4b { /* u124 */
+				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-dac-avccaux";
+				reg = <0x4b>;
+				shunt-resistor = <5000>;
+			};
+			adc_avcc: ina226@4c { /* u75 */
+				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-adc-avcc";
+				reg = <0x4c>;
+				shunt-resistor = <5000>;
+			};
+			adc_avccaux: ina226@4d { /* u71 */
+				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-adc-avccaux";
+				reg = <0x4d>;
+				shunt-resistor = <5000>;
+			};
+			dac_avcc: ina226@4e { /* u77 */
+				compatible = "ti,ina226";
+				#io-channel-cells = <1>;
+				label = "ina226-dac-avcc";
+				reg = <0x4e>;
+				shunt-resistor = <5000>;
+			};
+		};
+		i2c@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+			/* NC */
+		};
+		i2c@2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+			/* u104 - ir35215 0x10/0x40 */
+			/* u127 - ir38164 0x1b/0x4b */
+			/* u112 - ir38164 0x13/0x43 */
+			/* u123 - ir38164 0x1c/0x4c */
+
+			irps5401_44: irps5401@44 { /* IRPS5401 - u53 */
+				compatible = "infineon,irps5401";
+				reg = <0x44>; /* i2c addr 0x14 */
+			};
+			irps5401_45: irps5401@45 { /* IRPS5401 - u55 */
+				compatible = "infineon,irps5401";
+				reg = <0x45>; /* i2c addr 0x15 */
+			};
+			/* J21 header too */
+
+		};
+		i2c@3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+			/* SYSMON */
+		};
+	};
+	/* u38 MPS430 */
+};
+
+&i2c1 {
+	status = "okay";
+	clock-frequency = <400000>;
+	pinctrl-names = "default", "gpio";
+	pinctrl-0 = <&pinctrl_i2c1_default>;
+	pinctrl-1 = <&pinctrl_i2c1_gpio>;
+	scl-gpios = <&gpio 16 GPIO_ACTIVE_HIGH>;
+	sda-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>;
+
+	i2c-mux@74 {
+		compatible = "nxp,pca9548"; /* u20 */
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x74>;
+		/* FIXME reset-gpios = <&tca6416_u15 SYSCTLR_IIC_MUX0_RESET_B GPIO_ACTIVE_HIGH>; */
+		i2c_eeprom: i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+			/*
+			 * IIC_EEPROM 1kB memory which uses 256B blocks
+			 * where every block has different address.
+			 *    0 - 256B address 0x54
+			 * 256B - 512B address 0x55
+			 * 512B - 768B address 0x56
+			 * 768B - 1024B address 0x57
+			 */
+			eeprom: eeprom@54 { /* u21 */
+				compatible = "atmel,24c128";
+				reg = <0x54>;
+			};
+		};
+		i2c_si5341: i2c@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+			si5341: clock-generator@36 { /* SI5341 - u43 */
+				compatible = "si5341";
+				reg = <0x36>;
+			};
+
+		};
+		i2c_si570_user_c0: i2c@2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+			si570_1: clock-generator@5d { /* USER C0 SI570 - u47 */
+				#clock-cells = <0>;
+				compatible = "silabs,si570";
+				reg = <0x5d>;
+				temperature-stability = <50>;
+				factory-fout = <300000000>;
+				clock-frequency = <300000000>;
+				clock-output-names = "si570_user_c0";
+			};
+		};
+		i2c_si570_mgt: i2c@3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+			si570_2: clock-generator@5d { /* USER MGT SI570 - u48 */
+				#clock-cells = <0>;
+				compatible = "silabs,si570";
+				reg = <0x5d>;
+				temperature-stability = <50>;
+				factory-fout = <156250000>;
+				clock-frequency = <148500000>;
+				clock-output-names = "si570_mgt";
+			};
+		};
+		i2c_8a34001: i2c@4 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <4>;
+			/* U409B - 8a34001 */
+		};
+		i2c_clk104: i2c@5 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <5>;
+			/* CLK104_SDA */
+		};
+		i2c@6 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <6>;
+			/* RFMCP connector */
+		};
+		/* 7 NC */
+	};
+
+	i2c-mux@75 {
+		compatible = "nxp,pca9548"; /* u22 */
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x75>;
+		/* FIXME reset-gpios = <&tca6416_u15 SYSCTLR_IIC_MUX0_RESET_B GPIO_ACTIVE_HIGH>; */
+		i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+			/* FMCP_HSPC_IIC */
+		};
+		i2c_si570_user_c1: i2c@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+			si570_3: clock-generator@5d { /* USER C1 SI570 - u130 */
+				#clock-cells = <0>;
+				compatible = "silabs,si570";
+				reg = <0x5d>;
+				temperature-stability = <50>;
+				factory-fout = <300000000>;
+				clock-frequency = <300000000>;
+				clock-output-names = "si570_user_c1";
+			};
+		};
+		i2c@2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+			/* SYSMON */
+		};
+		i2c@3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+			/* DDR4 SODIMM */
+		};
+		i2c@4 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <4>;
+			/* SFP3 */
+		};
+		i2c@5 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <5>;
+			/* SFP2 */
+		};
+		i2c@6 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <6>;
+			/* SFP1 */
+		};
+		i2c@7 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <7>;
+			/* SFP0 */
+		};
+	};
+	/* MSP430 */
+};
+
+&pinctrl0 {
+	status = "okay";
+	pinctrl_i2c0_default: i2c0-default {
+		mux {
+			groups = "i2c0_3_grp";
+			function = "i2c0";
+		};
+
+		conf {
+			groups = "i2c0_3_grp";
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_i2c0_gpio: i2c0-gpio {
+		mux {
+			groups = "gpio0_14_grp", "gpio0_15_grp";
+			function = "gpio0";
+		};
+
+		conf {
+			groups = "gpio0_14_grp", "gpio0_15_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_i2c1_default: i2c1-default {
+		mux {
+			groups = "i2c1_4_grp";
+			function = "i2c1";
+		};
+
+		conf {
+			groups = "i2c1_4_grp";
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+
+	pinctrl_i2c1_gpio: i2c1-gpio {
+		mux {
+			groups = "gpio0_16_grp", "gpio0_17_grp";
+			function = "gpio0";
+		};
+
+		conf {
+			groups = "gpio0_16_grp", "gpio0_17_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			io-standard = <IO_STANDARD_LVCMOS18>;
+		};
+	};
+};
+
+&qspi {
+	status = "okay";
+	is-dual = <1>;
+	flash@0 {
+		compatible = "m25p80", "jedec,spi-nor"; /* U11 and U12 MT25QU02GCBBE12 1Gb */
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x0>;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <4>; /* FIXME also DUAL configuration possible */
+		spi-max-frequency = <108000000>; /* Based on DC1 spec */
+	};
+};
+
+&rtc {
+	status = "okay";
+};
+
+&sata {
+	status = "okay";
+	/* SATA OOB timing settings */
+	ceva,p0-cominit-params = /bits/ 8 <0x18 0x40 0x18 0x28>;
+	ceva,p0-comwake-params = /bits/ 8 <0x06 0x14 0x08 0x0E>;
+	ceva,p0-burst-params = /bits/ 8 <0x13 0x08 0x4A 0x06>;
+	ceva,p0-retry-params = /bits/ 16 <0x96A4 0x3FFC>;
+	ceva,p1-cominit-params = /bits/ 8 <0x18 0x40 0x18 0x28>;
+	ceva,p1-comwake-params = /bits/ 8 <0x06 0x14 0x08 0x0E>;
+	ceva,p1-burst-params = /bits/ 8 <0x13 0x08 0x4A 0x06>;
+	ceva,p1-retry-params = /bits/ 16 <0x96A4 0x3FFC>;
+	phy-names = "sata-phy";
+	phys = <&lane3 PHY_TYPE_SATA 1 3 125000000>;
+};
+
+/* SD1 with level shifter */
+&sdhci1 {
+	status = "okay";
+	disable-wp;
+	/*
+	 * This property should be removed for supporting UHS mode
+	 */
+	no-1-8-v;
+	xlnx,mio-bank = <1>;
+};
+
+&serdes {
+	status = "okay";
+};
+
+&uart0 {
+	status = "okay";
+};
+
+/* ULPI SMSC USB3320 */
+&usb0 {
+	status = "okay";
+};
+
+&dwc3_0 {
+	status = "okay";
+	dr_mode = "host";
+	snps,usb3_lpm_capable;
+	phy-names = "usb3-phy";
+	phys = <&lane2 PHY_TYPE_USB3 0 2 26000000>;
+};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
@@ -2,7 +2,7 @@
 /*
  * dts file for Xilinx ZynqMP
  *
- * (C) Copyright 2014 - 2015, Xilinx, Inc.
+ * (C) Copyright 2014 - 2020, Xilinx, Inc.
  *
  * Michal Simek <michal.simek@xilinx.com>
  *
@@ -12,6 +12,9 @@
  * the License, or (at your option) any later version.
  */
 
+#include <dt-bindings/power/xlnx-zynqmp-power.h>
+#include <dt-bindings/reset/xlnx-zynqmp-resets.h>
+
 / {
 	compatible = "xlnx,zynqmp";
 	#address-cells = <2>;
@@ -96,9 +99,33 @@
 		};
 	};
 
+	zynqmp_ipi {
+		u-boot,dm-pre-reloc;
+		compatible = "xlnx,zynqmp-ipi-mailbox";
+		interrupt-parent = <&gic>;
+		interrupts = <0 35 4>;
+		xlnx,ipi-id = <0>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		ipi_mailbox_pmu1: mailbox@ff990400 {
+			u-boot,dm-pre-reloc;
+			reg = <0x0 0xff9905c0 0x0 0x20>,
+			      <0x0 0xff9905e0 0x0 0x20>,
+			      <0x0 0xff990e80 0x0 0x20>,
+			      <0x0 0xff990ea0 0x0 0x20>;
+			reg-names = "local_request_region", "local_response_region",
+				    "remote_request_region", "remote_response_region";
+			#mbox-cells = <1>;
+			xlnx,ipi-id = <4>;
+		};
+	};
+
 	dcc: dcc {
 		compatible = "arm,dcc";
 		status = "disabled";
+		u-boot,dm-pre-reloc;
 	};
 
 	pmu {
@@ -115,6 +142,40 @@
 		method = "smc";
 	};
 
+	firmware {
+		zynqmp_firmware: zynqmp-firmware {
+			compatible = "xlnx,zynqmp-firmware";
+			method = "smc";
+			#power-domain-cells = <0x1>;
+			u-boot,dm-pre-reloc;
+
+			zynqmp_pcap: pcap {
+				compatible = "xlnx,zynqmp-pcap-fpga";
+				clock-names = "ref_clk";
+			};
+
+			zynqmp_power: zynqmp-power {
+				u-boot,dm-pre-reloc;
+				compatible = "xlnx,zynqmp-power";
+				interrupt-parent = <&gic>;
+				interrupts = <0 35 4>;
+				mboxes = <&ipi_mailbox_pmu1 0>,
+					 <&ipi_mailbox_pmu1 1>;
+				mbox-names = "tx", "rx";
+			};
+
+			zynqmp_reset: reset-controller {
+				compatible = "xlnx,zynqmp-reset";
+				#reset-cells = <1>;
+			};
+
+			pinctrl0: pinctrl {
+				compatible = "xlnx,zynqmp-pinctrl";
+				status = "disabled";
+			};
+		};
+	};
+
 	timer {
 		compatible = "arm,armv8-timer";
 		interrupt-parent = <&gic>;
@@ -124,6 +185,89 @@
 			     <1 10 0xf08>;
 	};
 
+	edac {
+		compatible = "arm,cortex-a53-edac";
+	};
+
+	fpga_full: fpga-full {
+		compatible = "fpga-region";
+		fpga-mgr = <&zynqmp_pcap>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+	};
+
+	nvmem_firmware {
+		compatible = "xlnx,zynqmp-nvmem-fw";
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		soc_revision: soc_revision@0 {
+			reg = <0x0 0x4>;
+		};
+		/* efuse access */
+		efuse_dna: efuse_dna@c {
+			reg = <0xc 0xc>;
+		};
+		efuse_usr0: efuse_usr0@20 {
+			reg = <0x20 0x4>;
+		};
+		efuse_usr1: efuse_usr1@24 {
+			reg = <0x24 0x4>;
+		};
+		efuse_usr2: efuse_usr2@28 {
+			reg = <0x28 0x4>;
+		};
+		efuse_usr3: efuse_usr3@2c {
+			reg = <0x2c 0x4>;
+		};
+		efuse_usr4: efuse_usr4@30 {
+			reg = <0x30 0x4>;
+		};
+		efuse_usr5: efuse_usr5@34 {
+			reg = <0x34 0x4>;
+		};
+		efuse_usr6: efuse_usr6@38 {
+			reg = <0x38 0x4>;
+		};
+		efuse_usr7: efuse_usr7@3c {
+			reg = <0x3c 0x4>;
+		};
+		efuse_miscusr: efuse_miscusr@40 {
+			reg = <0x40 0x4>;
+		};
+		efuse_chash: efuse_chash@50 {
+			reg = <0x50 0x4>;
+		};
+		efuse_pufmisc: efuse_pufmisc@54 {
+			reg = <0x54 0x4>;
+		};
+		efuse_sec: efuse_sec@58 {
+			reg = <0x58 0x4>;
+		};
+		efuse_spkid: efuse_spkid@5c {
+			reg = <0x5c 0x4>;
+		};
+		efuse_ppk0hash: efuse_ppk0hash@a0 {
+			reg = <0xa0 0x30>;
+		};
+		efuse_ppk1hash: efuse_ppk1hash@d0 {
+			reg = <0xd0 0x30>;
+		};
+	};
+
+	xlnx_rsa: zynqmp_rsa {
+		compatible = "xlnx,zynqmp-rsa";
+	};
+
+	xlnx_keccak_384: sha384 {
+		compatible = "xlnx,zynqmp-keccak-384";
+	};
+
+	xlnx_aes: zynqmp_aes {
+		compatible = "xlnx,zynqmp-aes";
+	};
+
 	amba_apu: amba-apu@0 {
 		compatible = "simple-bus";
 		#address-cells = <2>;
@@ -131,7 +275,7 @@
 		ranges = <0 0 0 0 0xffffffff>;
 
 		gic: interrupt-controller@f9010000 {
-			compatible = "arm,gic-400", "arm,cortex-a15-gic";
+			compatible = "arm,gic-400";
 			#interrupt-cells = <3>;
 			reg = <0x0 0xf9010000 0x10000>,
 			      <0x0 0xf9020000 0x20000>,
@@ -143,8 +287,23 @@
 		};
 	};
 
+	smmu: smmu@fd800000 {
+		compatible = "arm,mmu-500";
+		reg = <0x0 0xfd800000 0x0 0x20000>;
+		#iommu-cells = <1>;
+		status = "disabled";
+		#global-interrupts = <1>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 155 4>,
+			<0 155 4>, <0 155 4>, <0 155 4>, <0 155 4>,
+			<0 155 4>, <0 155 4>, <0 155 4>, <0 155 4>,
+			<0 155 4>, <0 155 4>, <0 155 4>, <0 155 4>,
+			<0 155 4>, <0 155 4>, <0 155 4>, <0 155 4>;
+	};
+
 	amba: amba {
 		compatible = "simple-bus";
+		u-boot,dm-pre-reloc;
 		#address-cells = <2>;
 		#size-cells = <2>;
 		ranges;
@@ -158,6 +317,7 @@
 			interrupt-parent = <&gic>;
 			tx-fifo-depth = <0x40>;
 			rx-fifo-depth = <0x40>;
+			power-domains = <&zynqmp_firmware PD_CAN_0>;
 		};
 
 		can1: can@ff070000 {
@@ -169,6 +329,7 @@
 			interrupt-parent = <&gic>;
 			tx-fifo-depth = <0x40>;
 			rx-fifo-depth = <0x40>;
+			power-domains = <&zynqmp_firmware PD_CAN_1>;
 		};
 
 		cci: cci@fd6e0000 {
@@ -199,6 +360,9 @@
 			interrupts = <0 124 4>;
 			clock-names = "clk_main", "clk_apb";
 			xlnx,bus-width = <128>;
+			#stream-id-cells = <1>;
+			iommus = <&smmu 0x14e8>;
+			power-domains = <&zynqmp_firmware PD_GDMA>;
 		};
 
 		fpd_dma_chan2: dma@fd510000 {
@@ -209,6 +373,9 @@
 			interrupts = <0 125 4>;
 			clock-names = "clk_main", "clk_apb";
 			xlnx,bus-width = <128>;
+			#stream-id-cells = <1>;
+			iommus = <&smmu 0x14e9>;
+			power-domains = <&zynqmp_firmware PD_GDMA>;
 		};
 
 		fpd_dma_chan3: dma@fd520000 {
@@ -219,6 +386,9 @@
 			interrupts = <0 126 4>;
 			clock-names = "clk_main", "clk_apb";
 			xlnx,bus-width = <128>;
+			#stream-id-cells = <1>;
+			iommus = <&smmu 0x14ea>;
+			power-domains = <&zynqmp_firmware PD_GDMA>;
 		};
 
 		fpd_dma_chan4: dma@fd530000 {
@@ -229,6 +399,9 @@
 			interrupts = <0 127 4>;
 			clock-names = "clk_main", "clk_apb";
 			xlnx,bus-width = <128>;
+			#stream-id-cells = <1>;
+			iommus = <&smmu 0x14eb>;
+			power-domains = <&zynqmp_firmware PD_GDMA>;
 		};
 
 		fpd_dma_chan5: dma@fd540000 {
@@ -239,6 +412,9 @@
 			interrupts = <0 128 4>;
 			clock-names = "clk_main", "clk_apb";
 			xlnx,bus-width = <128>;
+			#stream-id-cells = <1>;
+			iommus = <&smmu 0x14ec>;
+			power-domains = <&zynqmp_firmware PD_GDMA>;
 		};
 
 		fpd_dma_chan6: dma@fd550000 {
@@ -249,6 +425,9 @@
 			interrupts = <0 129 4>;
 			clock-names = "clk_main", "clk_apb";
 			xlnx,bus-width = <128>;
+			#stream-id-cells = <1>;
+			iommus = <&smmu 0x14ed>;
+			power-domains = <&zynqmp_firmware PD_GDMA>;
 		};
 
 		fpd_dma_chan7: dma@fd560000 {
@@ -259,6 +438,9 @@
 			interrupts = <0 130 4>;
 			clock-names = "clk_main", "clk_apb";
 			xlnx,bus-width = <128>;
+			#stream-id-cells = <1>;
+			iommus = <&smmu 0x14ee>;
+			power-domains = <&zynqmp_firmware PD_GDMA>;
 		};
 
 		fpd_dma_chan8: dma@fd570000 {
@@ -269,6 +451,20 @@
 			interrupts = <0 131 4>;
 			clock-names = "clk_main", "clk_apb";
 			xlnx,bus-width = <128>;
+			#stream-id-cells = <1>;
+			iommus = <&smmu 0x14ef>;
+			power-domains = <&zynqmp_firmware PD_GDMA>;
+		};
+
+		gpu: gpu@fd4b0000 {
+			status = "disabled";
+			compatible = "arm,mali-400", "arm,mali-utgard";
+			reg = <0x0 0xfd4b0000 0x0 0x10000>;
+			interrupt-parent = <&gic>;
+			interrupts = <0 132 4>, <0 132 4>, <0 132 4>, <0 132 4>, <0 132 4>, <0 132 4>;
+			interrupt-names = "IRQGP", "IRQGPMMU", "IRQPP0", "IRQPPMMU0", "IRQPP1", "IRQPPMMU1";
+			clock-names = "gpu", "gpu_pp0", "gpu_pp1";
+			power-domains = <&zynqmp_firmware PD_GPU>;
 		};
 
 		/* LPDDMA default allows only secured access. inorder to enable
@@ -283,6 +479,9 @@
 			interrupts = <0 77 4>;
 			clock-names = "clk_main", "clk_apb";
 			xlnx,bus-width = <64>;
+			#stream-id-cells = <1>;
+			/* iommus = <&smmu 0x868>; */
+			power-domains = <&zynqmp_firmware PD_ADMA>;
 		};
 
 		lpd_dma_chan2: dma@ffa90000 {
@@ -293,6 +492,9 @@
 			interrupts = <0 78 4>;
 			clock-names = "clk_main", "clk_apb";
 			xlnx,bus-width = <64>;
+			#stream-id-cells = <1>;
+			/* iommus = <&smmu 0x869>; */
+			power-domains = <&zynqmp_firmware PD_ADMA>;
 		};
 
 		lpd_dma_chan3: dma@ffaa0000 {
@@ -303,6 +505,9 @@
 			interrupts = <0 79 4>;
 			clock-names = "clk_main", "clk_apb";
 			xlnx,bus-width = <64>;
+			#stream-id-cells = <1>;
+			/* iommus = <&smmu 0x86a>; */
+			power-domains = <&zynqmp_firmware PD_ADMA>;
 		};
 
 		lpd_dma_chan4: dma@ffab0000 {
@@ -313,6 +518,9 @@
 			interrupts = <0 80 4>;
 			clock-names = "clk_main", "clk_apb";
 			xlnx,bus-width = <64>;
+			#stream-id-cells = <1>;
+			/* iommus = <&smmu 0x86b>; */
+			power-domains = <&zynqmp_firmware PD_ADMA>;
 		};
 
 		lpd_dma_chan5: dma@ffac0000 {
@@ -323,6 +531,9 @@
 			interrupts = <0 81 4>;
 			clock-names = "clk_main", "clk_apb";
 			xlnx,bus-width = <64>;
+			#stream-id-cells = <1>;
+			/* iommus = <&smmu 0x86c>; */
+			power-domains = <&zynqmp_firmware PD_ADMA>;
 		};
 
 		lpd_dma_chan6: dma@ffad0000 {
@@ -333,6 +544,9 @@
 			interrupts = <0 82 4>;
 			clock-names = "clk_main", "clk_apb";
 			xlnx,bus-width = <64>;
+			#stream-id-cells = <1>;
+			/* iommus = <&smmu 0x86d>; */
+			power-domains = <&zynqmp_firmware PD_ADMA>;
 		};
 
 		lpd_dma_chan7: dma@ffae0000 {
@@ -343,6 +557,9 @@
 			interrupts = <0 83 4>;
 			clock-names = "clk_main", "clk_apb";
 			xlnx,bus-width = <64>;
+			#stream-id-cells = <1>;
+			/* iommus = <&smmu 0x86e>; */
+			power-domains = <&zynqmp_firmware PD_ADMA>;
 		};
 
 		lpd_dma_chan8: dma@ffaf0000 {
@@ -353,6 +570,9 @@
 			interrupts = <0 84 4>;
 			clock-names = "clk_main", "clk_apb";
 			xlnx,bus-width = <64>;
+			#stream-id-cells = <1>;
+			/* iommus = <&smmu 0x86f>; */
+			power-domains = <&zynqmp_firmware PD_ADMA>;
 		};
 
 		mc: memory-controller@fd070000 {
@@ -362,6 +582,20 @@
 			interrupts = <0 112 4>;
 		};
 
+		nand0: nand@ff100000 {
+			compatible = "arasan,nfc-v3p10";
+			status = "disabled";
+			reg = <0x0 0xff100000 0x0 0x1000>;
+			clock-names = "clk_sys", "clk_flash";
+			interrupt-parent = <&gic>;
+			interrupts = <0 14 4>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			#stream-id-cells = <1>;
+			iommus = <&smmu 0x872>;
+			power-domains = <&zynqmp_firmware PD_NAND>;
+		};
+
 		gem0: ethernet@ff0b0000 {
 			compatible = "cdns,zynqmp-gem", "cdns,gem";
 			status = "disabled";
@@ -371,6 +605,9 @@
 			clock-names = "pclk", "hclk", "tx_clk";
 			#address-cells = <1>;
 			#size-cells = <0>;
+			#stream-id-cells = <1>;
+			iommus = <&smmu 0x874>;
+			power-domains = <&zynqmp_firmware PD_ETH_0>;
 		};
 
 		gem1: ethernet@ff0c0000 {
@@ -382,6 +619,9 @@
 			clock-names = "pclk", "hclk", "tx_clk";
 			#address-cells = <1>;
 			#size-cells = <0>;
+			#stream-id-cells = <1>;
+			iommus = <&smmu 0x875>;
+			power-domains = <&zynqmp_firmware PD_ETH_1>;
 		};
 
 		gem2: ethernet@ff0d0000 {
@@ -393,6 +633,9 @@
 			clock-names = "pclk", "hclk", "tx_clk";
 			#address-cells = <1>;
 			#size-cells = <0>;
+			#stream-id-cells = <1>;
+			iommus = <&smmu 0x876>;
+			power-domains = <&zynqmp_firmware PD_ETH_2>;
 		};
 
 		gem3: ethernet@ff0e0000 {
@@ -404,6 +647,9 @@
 			clock-names = "pclk", "hclk", "tx_clk";
 			#address-cells = <1>;
 			#size-cells = <0>;
+			#stream-id-cells = <1>;
+			iommus = <&smmu 0x877>;
+			power-domains = <&zynqmp_firmware PD_ETH_3>;
 		};
 
 		gpio: gpio@ff0a0000 {
@@ -416,26 +662,108 @@
 			interrupt-controller;
 			#interrupt-cells = <2>;
 			reg = <0x0 0xff0a0000 0x0 0x1000>;
+			power-domains = <&zynqmp_firmware PD_GPIO>;
 		};
 
 		i2c0: i2c@ff020000 {
-			compatible = "cdns,i2c-r1p14", "cdns,i2c-r1p10";
+			compatible = "cdns,i2c-r1p14";
 			status = "disabled";
 			interrupt-parent = <&gic>;
 			interrupts = <0 17 4>;
 			reg = <0x0 0xff020000 0x0 0x1000>;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			power-domains = <&zynqmp_firmware PD_I2C_0>;
 		};
 
 		i2c1: i2c@ff030000 {
-			compatible = "cdns,i2c-r1p14", "cdns,i2c-r1p10";
+			compatible = "cdns,i2c-r1p14";
 			status = "disabled";
 			interrupt-parent = <&gic>;
 			interrupts = <0 18 4>;
 			reg = <0x0 0xff030000 0x0 0x1000>;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			power-domains = <&zynqmp_firmware PD_I2C_1>;
+		};
+
+		ocm: memory-controller@ff960000 {
+			compatible = "xlnx,zynqmp-ocmc-1.0";
+			reg = <0x0 0xff960000 0x0 0x1000>;
+			interrupt-parent = <&gic>;
+			interrupts = <0 10 4>;
+		};
+
+		perf_monitor_ocm: perf-monitor@ffa00000 {
+			compatible = "xlnx,axi-perf-monitor";
+			reg = <0x0 0xffa00000 0x0 0x10000>;
+			interrupts = <0 25 4>;
+			interrupt-parent = <&gic>;
+			xlnx,enable-profile = <0>;
+			xlnx,enable-trace = <0>;
+			xlnx,num-monitor-slots = <1>;
+			xlnx,enable-event-count = <1>;
+			xlnx,enable-event-log = <1>;
+			xlnx,have-sampled-metric-cnt = <1>;
+			xlnx,num-of-counters = <8>;
+			xlnx,metric-count-width = <32>;
+			xlnx,metrics-sample-count-width = <32>;
+			xlnx,global-count-width = <32>;
+			xlnx,metric-count-scale = <1>;
+		};
+
+		perf_monitor_ddr: perf-monitor@fd0b0000 {
+			compatible = "xlnx,axi-perf-monitor";
+			reg = <0x0 0xfd0b0000 0x0 0x10000>;
+			interrupts = <0 123 4>;
+			interrupt-parent = <&gic>;
+			xlnx,enable-profile = <0>;
+			xlnx,enable-trace = <0>;
+			xlnx,num-monitor-slots = <6>;
+			xlnx,enable-event-count = <1>;
+			xlnx,enable-event-log = <0>;
+			xlnx,have-sampled-metric-cnt = <1>;
+			xlnx,num-of-counters = <10>;
+			xlnx,metric-count-width = <32>;
+			xlnx,metrics-sample-count-width = <32>;
+			xlnx,global-count-width = <32>;
+			xlnx,metric-count-scale = <1>;
+		};
+
+		perf_monitor_cci: perf-monitor@fd490000 {
+			compatible = "xlnx,axi-perf-monitor";
+			reg = <0x0 0xfd490000 0x0 0x10000>;
+			interrupts = <0 123 4>;
+			interrupt-parent = <&gic>;
+			xlnx,enable-profile = <0>;
+			xlnx,enable-trace = <0>;
+			xlnx,num-monitor-slots = <1>;
+			xlnx,enable-event-count = <1>;
+			xlnx,enable-event-log = <0>;
+			xlnx,have-sampled-metric-cnt = <1>;
+			xlnx,num-of-counters = <8>;
+			xlnx,metric-count-width = <32>;
+			xlnx,metrics-sample-count-width = <32>;
+			xlnx,global-count-width = <32>;
+			xlnx,metric-count-scale = <1>;
+		};
+
+		perf_monitor_lpd: perf-monitor@ffa10000 {
+			compatible = "xlnx,axi-perf-monitor";
+			reg = <0x0 0xffa10000 0x0 0x10000>;
+			interrupts = <0 25 4>;
+			interrupt-parent = <&gic>;
+			xlnx,enable-profile = <0>;
+			xlnx,enable-trace = <0>;
+			xlnx,num-monitor-slots = <1>;
+			xlnx,enable-event-count = <1>;
+			xlnx,enable-event-log = <1>;
+			xlnx,have-sampled-metric-cnt = <1>;
+			xlnx,num-of-counters = <8>;
+			xlnx,metric-count-width = <32>;
+			xlnx,metrics-sample-count-width = <32>;
+			xlnx,global-count-width = <32>;
+			xlnx,metric-count-scale = <1>;
 		};
 
 		pcie: pcie@fd0e0000 {
@@ -467,6 +795,7 @@
 					<0x0 0x0 0x0 0x2 &pcie_intc 0x2>,
 					<0x0 0x0 0x0 0x3 &pcie_intc 0x3>,
 					<0x0 0x0 0x0 0x4 &pcie_intc 0x4>;
+			power-domains = <&zynqmp_firmware PD_PCIE>;
 			pcie_intc: legacy-interrupt-controller {
 				interrupt-controller;
 				#address-cells = <0>;
@@ -474,6 +803,23 @@
 			};
 		};
 
+		qspi: spi@ff0f0000 {
+			u-boot,dm-pre-reloc;
+			compatible = "xlnx,zynqmp-qspi-1.0";
+			status = "disabled";
+			clock-names = "ref_clk", "pclk";
+			interrupts = <0 15 4>;
+			interrupt-parent = <&gic>;
+			num-cs = <1>;
+			reg = <0x0 0xff0f0000 0x0 0x1000>,
+			      <0x0 0xc0000000 0x0 0x8000000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			#stream-id-cells = <1>;
+			iommus = <&smmu 0x873>;
+			power-domains = <&zynqmp_firmware PD_QSPI>;
+		};
+
 		rtc: rtc@ffa60000 {
 			compatible = "xlnx,zynqmp-rtc";
 			status = "disabled";
@@ -484,43 +830,91 @@
 			calibration = <0x8000>;
 		};
 
+		serdes: zynqmp_phy@fd400000 {
+			compatible = "xlnx,zynqmp-psgtr-v1.1";
+			status = "disabled";
+			reg = <0x0 0xfd400000 0x0 0x40000>,
+			      <0x0 0xfd3d0000 0x0 0x1000>;
+			reg-names = "serdes", "siou";
+			nvmem-cells = <&soc_revision>;
+			nvmem-cell-names = "soc_revision";
+			resets = <&zynqmp_reset ZYNQMP_RESET_SATA>,
+				 <&zynqmp_reset ZYNQMP_RESET_USB0_CORERESET>,
+				 <&zynqmp_reset ZYNQMP_RESET_USB1_CORERESET>,
+				 <&zynqmp_reset ZYNQMP_RESET_USB0_HIBERRESET>,
+				 <&zynqmp_reset ZYNQMP_RESET_USB1_HIBERRESET>,
+				 <&zynqmp_reset ZYNQMP_RESET_USB0_APB>,
+				 <&zynqmp_reset ZYNQMP_RESET_USB1_APB>,
+				 <&zynqmp_reset ZYNQMP_RESET_DP>,
+				 <&zynqmp_reset ZYNQMP_RESET_GEM0>,
+				 <&zynqmp_reset ZYNQMP_RESET_GEM1>,
+				 <&zynqmp_reset ZYNQMP_RESET_GEM2>,
+				 <&zynqmp_reset ZYNQMP_RESET_GEM3>;
+			reset-names = "sata_rst", "usb0_crst", "usb1_crst",
+				      "usb0_hibrst", "usb1_hibrst", "usb0_apbrst",
+				      "usb1_apbrst", "dp_rst", "gem0_rst",
+				      "gem1_rst", "gem2_rst", "gem3_rst";
+			lane0: lane0 {
+				#phy-cells = <4>;
+			};
+			lane1: lane1 {
+				#phy-cells = <4>;
+			};
+			lane2: lane2 {
+				#phy-cells = <4>;
+			};
+			lane3: lane3 {
+				#phy-cells = <4>;
+			};
+		};
+
 		sata: ahci@fd0c0000 {
 			compatible = "ceva,ahci-1v84";
 			status = "disabled";
 			reg = <0x0 0xfd0c0000 0x0 0x2000>;
 			interrupt-parent = <&gic>;
 			interrupts = <0 133 4>;
+			power-domains = <&zynqmp_firmware PD_SATA>;
+			#stream-id-cells = <4>;
+			/* iommus = <&smmu 0x4c0>, <&smmu 0x4c1>, */
+			/*	 <&smmu 0x4c2>, <&smmu 0x4c3>; */
+			/* dma-coherent; */
 		};
 
 		sdhci0: mmc@ff160000 {
-			compatible = "arasan,sdhci-8.9a";
+			u-boot,dm-pre-reloc;
+			compatible = "xlnx,zynqmp-8.9a", "arasan,sdhci-8.9a";
 			status = "disabled";
 			interrupt-parent = <&gic>;
 			interrupts = <0 48 4>;
 			reg = <0x0 0xff160000 0x0 0x1000>;
 			clock-names = "clk_xin", "clk_ahb";
+			xlnx,device_id = <0>;
+			#stream-id-cells = <1>;
+			iommus = <&smmu 0x870>;
+			power-domains = <&zynqmp_firmware PD_SD_0>;
+			nvmem-cells = <&soc_revision>;
+			nvmem-cell-names = "soc_revision";
+			#clock-cells = <1>;
+			clock-output-names = "clk_out_sd0", "clk_in_sd0";
 		};
 
 		sdhci1: mmc@ff170000 {
-			compatible = "arasan,sdhci-8.9a";
+			u-boot,dm-pre-reloc;
+			compatible = "xlnx,zynqmp-8.9a", "arasan,sdhci-8.9a";
 			status = "disabled";
 			interrupt-parent = <&gic>;
 			interrupts = <0 49 4>;
 			reg = <0x0 0xff170000 0x0 0x1000>;
 			clock-names = "clk_xin", "clk_ahb";
-		};
-
-		smmu: smmu@fd800000 {
-			compatible = "arm,mmu-500";
-			reg = <0x0 0xfd800000 0x0 0x20000>;
-			status = "disabled";
-			#global-interrupts = <1>;
-			interrupt-parent = <&gic>;
-			interrupts = <0 155 4>,
-				<0 155 4>, <0 155 4>, <0 155 4>, <0 155 4>,
-				<0 155 4>, <0 155 4>, <0 155 4>, <0 155 4>,
-				<0 155 4>, <0 155 4>, <0 155 4>, <0 155 4>,
-				<0 155 4>, <0 155 4>, <0 155 4>, <0 155 4>;
+			xlnx,device_id = <1>;
+			#stream-id-cells = <1>;
+			iommus = <&smmu 0x871>;
+			power-domains = <&zynqmp_firmware PD_SD_1>;
+			nvmem-cells = <&soc_revision>;
+			nvmem-cell-names = "soc_revision";
+			#clock-cells = <1>;
+			clock-output-names = "clk_out_sd1", "clk_in_sd1";
 		};
 
 		spi0: spi@ff040000 {
@@ -532,6 +926,7 @@
 			clock-names = "ref_clk", "pclk";
 			#address-cells = <1>;
 			#size-cells = <0>;
+			power-domains = <&zynqmp_firmware PD_SPI_0>;
 		};
 
 		spi1: spi@ff050000 {
@@ -543,6 +938,7 @@
 			clock-names = "ref_clk", "pclk";
 			#address-cells = <1>;
 			#size-cells = <0>;
+			power-domains = <&zynqmp_firmware PD_SPI_1>;
 		};
 
 		ttc0: timer@ff110000 {
@@ -552,6 +948,7 @@
 			interrupts = <0 36 4>, <0 37 4>, <0 38 4>;
 			reg = <0x0 0xff110000 0x0 0x1000>;
 			timer-width = <32>;
+			power-domains = <&zynqmp_firmware PD_TTC_0>;
 		};
 
 		ttc1: timer@ff120000 {
@@ -561,6 +958,7 @@
 			interrupts = <0 39 4>, <0 40 4>, <0 41 4>;
 			reg = <0x0 0xff120000 0x0 0x1000>;
 			timer-width = <32>;
+			power-domains = <&zynqmp_firmware PD_TTC_1>;
 		};
 
 		ttc2: timer@ff130000 {
@@ -570,6 +968,7 @@
 			interrupts = <0 42 4>, <0 43 4>, <0 44 4>;
 			reg = <0x0 0xff130000 0x0 0x1000>;
 			timer-width = <32>;
+			power-domains = <&zynqmp_firmware PD_TTC_2>;
 		};
 
 		ttc3: timer@ff140000 {
@@ -579,42 +978,90 @@
 			interrupts = <0 45 4>, <0 46 4>, <0 47 4>;
 			reg = <0x0 0xff140000 0x0 0x1000>;
 			timer-width = <32>;
+			power-domains = <&zynqmp_firmware PD_TTC_3>;
 		};
 
 		uart0: serial@ff000000 {
-			compatible = "cdns,uart-r1p12", "xlnx,xuartps";
+			u-boot,dm-pre-reloc;
+			compatible = "xlnx,zynqmp-uart", "cdns,uart-r1p12";
 			status = "disabled";
 			interrupt-parent = <&gic>;
 			interrupts = <0 21 4>;
 			reg = <0x0 0xff000000 0x0 0x1000>;
 			clock-names = "uart_clk", "pclk";
+			power-domains = <&zynqmp_firmware PD_UART_0>;
 		};
 
 		uart1: serial@ff010000 {
-			compatible = "cdns,uart-r1p12", "xlnx,xuartps";
+			u-boot,dm-pre-reloc;
+			compatible = "xlnx,zynqmp-uart", "cdns,uart-r1p12";
 			status = "disabled";
 			interrupt-parent = <&gic>;
 			interrupts = <0 22 4>;
 			reg = <0x0 0xff010000 0x0 0x1000>;
 			clock-names = "uart_clk", "pclk";
+			power-domains = <&zynqmp_firmware PD_UART_1>;
 		};
 
-		usb0: usb@fe200000 {
-			compatible = "snps,dwc3";
+		usb0: usb0@ff9d0000 {
+			#address-cells = <2>;
+			#size-cells = <2>;
 			status = "disabled";
-			interrupt-parent = <&gic>;
-			interrupts = <0 65 4>;
-			reg = <0x0 0xfe200000 0x0 0x40000>;
-			clock-names = "clk_xin", "clk_ahb";
+			compatible = "xlnx,zynqmp-dwc3";
+			reg = <0x0 0xff9d0000 0x0 0x100>;
+			clock-names = "bus_clk", "ref_clk";
+			power-domains = <&zynqmp_firmware PD_USB_0>;
+			ranges;
+			nvmem-cells = <&soc_revision>;
+			nvmem-cell-names = "soc_revision";
+
+			dwc3_0: dwc3@fe200000 {
+				compatible = "snps,dwc3";
+				status = "disabled";
+				reg = <0x0 0xfe200000 0x0 0x40000>;
+				interrupt-parent = <&gic>;
+				interrupt-names = "dwc_usb3", "otg", "hiber";
+				interrupts = <0 65 4>, <0 69 4>, <0 75 4>;
+				#stream-id-cells = <1>;
+				iommus = <&smmu 0x860>;
+				snps,quirk-frame-length-adjustment = <0x20>;
+				snps,refclk_fladj;
+				snps,enable_guctl1_resume_quirk;
+				snps,enable_guctl1_ipd_quirk;
+				snps,xhci-stream-quirk;
+				/* dma-coherent; */
+				/* snps,enable-hibernation; */
+			};
 		};
 
-		usb1: usb@fe300000 {
-			compatible = "snps,dwc3";
+		usb1: usb1@ff9e0000 {
+			#address-cells = <2>;
+			#size-cells = <2>;
 			status = "disabled";
-			interrupt-parent = <&gic>;
-			interrupts = <0 70 4>;
-			reg = <0x0 0xfe300000 0x0 0x40000>;
-			clock-names = "clk_xin", "clk_ahb";
+			compatible = "xlnx,zynqmp-dwc3";
+			reg = <0x0 0xff9e0000 0x0 0x100>;
+			clock-names = "bus_clk", "ref_clk";
+			power-domains = <&zynqmp_firmware PD_USB_1>;
+			ranges;
+			nvmem-cells = <&soc_revision>;
+			nvmem-cell-names = "soc_revision";
+
+			dwc3_1: dwc3@fe300000 {
+				compatible = "snps,dwc3";
+				status = "disabled";
+				reg = <0x0 0xfe300000 0x0 0x40000>;
+				interrupt-parent = <&gic>;
+				interrupt-names = "dwc_usb3", "otg", "hiber";
+				interrupts = <0 70 4>, <0 74 4>, <0 76 4>;
+				#stream-id-cells = <1>;
+				iommus = <&smmu 0x861>;
+				snps,quirk-frame-length-adjustment = <0x20>;
+				snps,refclk_fladj;
+				snps,enable_guctl1_resume_quirk;
+				snps,enable_guctl1_ipd_quirk;
+				snps,xhci-stream-quirk;
+				/* dma-coherent; */
+			};
 		};
 
 		watchdog0: watchdog@fd4d0000 {
@@ -623,7 +1070,130 @@
 			interrupt-parent = <&gic>;
 			interrupts = <0 113 1>;
 			reg = <0x0 0xfd4d0000 0x0 0x1000>;
+			timeout-sec = <60>;
+			reset-on-timeout;
+		};
+
+		lpd_watchdog: watchdog@ff150000 {
+			compatible = "cdns,wdt-r1p2";
+			status = "disabled";
+			interrupt-parent = <&gic>;
+			interrupts = <0 52 1>;
+			reg = <0x0 0xff150000 0x0 0x1000>;
 			timeout-sec = <10>;
 		};
+
+		xilinx_ams: ams@ffa50000 {
+			compatible = "xlnx,zynqmp-ams";
+			status = "disabled";
+			interrupt-parent = <&gic>;
+			interrupts = <0 56 4>;
+			interrupt-names = "ams-irq";
+			reg = <0x0 0xffa50000 0x0 0x800>;
+			reg-names = "ams-base";
+			#address-cells = <2>;
+			#size-cells = <2>;
+			#io-channel-cells = <1>;
+			ranges;
+
+			ams_ps: ams_ps@ffa50800 {
+				compatible = "xlnx,zynqmp-ams-ps";
+				status = "disabled";
+				reg = <0x0 0xffa50800 0x0 0x400>;
+			};
+
+			ams_pl: ams_pl@ffa50c00 {
+				compatible = "xlnx,zynqmp-ams-pl";
+				status = "disabled";
+				reg = <0x0 0xffa50c00 0x0 0x400>;
+			};
+		};
+
+		xlnx_dpdma: dma@fd4c0000 {
+			compatible = "xlnx,dpdma";
+			status = "disabled";
+			reg = <0x0 0xfd4c0000 0x0 0x1000>;
+			interrupts = <0 122 4>;
+			interrupt-parent = <&gic>;
+			clock-names = "axi_clk";
+			power-domains = <&zynqmp_firmware PD_DP>;
+			dma-channels = <6>;
+			#dma-cells = <1>;
+			dma-video0channel {
+				compatible = "xlnx,video0";
+			};
+			dma-video1channel {
+				compatible = "xlnx,video1";
+			};
+			dma-video2channel {
+				compatible = "xlnx,video2";
+			};
+			dma-graphicschannel {
+				compatible = "xlnx,graphics";
+			};
+			dma-audio0channel {
+				compatible = "xlnx,audio0";
+			};
+			dma-audio1channel {
+				compatible = "xlnx,audio1";
+			};
+		};
+
+		zynqmp_dpsub: zynqmp-display@fd4a0000 {
+			compatible = "xlnx,zynqmp-dpsub-1.7";
+			status = "disabled";
+			reg = <0x0 0xfd4a0000 0x0 0x1000>,
+			      <0x0 0xfd4aa000 0x0 0x1000>,
+			      <0x0 0xfd4ab000 0x0 0x1000>,
+			      <0x0 0xfd4ac000 0x0 0x1000>;
+			reg-names = "dp", "blend", "av_buf", "aud";
+			interrupts = <0 119 4>;
+			interrupt-parent = <&gic>;
+
+			clock-names = "dp_apb_clk", "dp_aud_clk",
+				      "dp_vtc_pixel_clk_in";
+
+			power-domains = <&zynqmp_firmware PD_DP>;
+
+			vid_layer: vid-layer {
+				dma-names = "vid0", "vid1", "vid2";
+				dmas = <&xlnx_dpdma 0>,
+				       <&xlnx_dpdma 1>,
+				       <&xlnx_dpdma 2>;
+			};
+
+			gfx_layer: gfx-layer {
+				dma-names = "gfx0";
+				dmas = <&xlnx_dpdma 3>;
+			};
+
+			/* dummy node to indicate there's no child i2c device */
+			i2c-bus {
+			};
+
+			zynqmp_dp_snd_codec0: zynqmp_dp_snd_codec0 {
+				compatible = "xlnx,dp-snd-codec";
+				clock-names = "aud_clk";
+			};
+
+			zynqmp_dp_snd_pcm0: zynqmp_dp_snd_pcm0 {
+				compatible = "xlnx,dp-snd-pcm0";
+				dmas = <&xlnx_dpdma 4>;
+				dma-names = "tx";
+			};
+
+			zynqmp_dp_snd_pcm1: zynqmp_dp_snd_pcm1 {
+				compatible = "xlnx,dp-snd-pcm1";
+				dmas = <&xlnx_dpdma 5>;
+				dma-names = "tx";
+			};
+
+			zynqmp_dp_snd_card0: zynqmp_dp_snd_card {
+				compatible = "xlnx,dp-snd-card";
+				xlnx,dp-snd-pcm = <&zynqmp_dp_snd_pcm0>,
+						  <&zynqmp_dp_snd_pcm1>;
+				xlnx,dp-snd-codec = <&zynqmp_dp_snd_codec0>;
+			};
+		};
 	};
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/configs/xilinx_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/configs/xilinx_defconfig
@@ -0,0 +1,461 @@
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_AUDIT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_CGROUPS=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+CONFIG_PROFILING=y
+CONFIG_ARCH_ZYNQMP=y
+CONFIG_ARM64_VA_BITS_48=y
+CONFIG_NR_CPUS=4
+CONFIG_KEXEC=y
+CONFIG_CRASH_DUMP=y
+CONFIG_COMPAT=y
+CONFIG_CPU_IDLE=y
+CONFIG_ARM_CPUIDLE=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+CONFIG_CPUFREQ_DT=y
+CONFIG_ZYNQMP_FIRMWARE_DEBUG=y
+CONFIG_ARM64_CRYPTO=y
+CONFIG_CRYPTO_SHA1_ARM64_CE=y
+CONFIG_CRYPTO_SHA2_ARM64_CE=y
+CONFIG_CRYPTO_SHA512_ARM64_CE=y
+CONFIG_CRYPTO_SHA3_ARM64=y
+CONFIG_CRYPTO_SM3_ARM64_CE=y
+CONFIG_CRYPTO_SM4_ARM64_CE=y
+CONFIG_CRYPTO_GHASH_ARM64_CE=y
+CONFIG_CRYPTO_AES_ARM64_CE_CCM=y
+CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
+CONFIG_CRYPTO_CHACHA20_NEON=y
+CONFIG_CRYPTO_AES_ARM64_BS=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_SPARSEMEM_VMEMMAP is not set
+CONFIG_MEMORY_HOTPLUG=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=32768
+CONFIG_TRANSPARENT_HUGEPAGE=y
+CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y
+CONFIG_CMA=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_SYN_COOKIES=y
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_SNMP=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_XT_MARK=y
+CONFIG_NETFILTER_XT_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=y
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_BRIDGE_NF_EBTABLES=y
+CONFIG_BRIDGE_EBT_T_FILTER=y
+CONFIG_BRIDGE_EBT_T_NAT=y
+CONFIG_BRIDGE_EBT_MARK_T=y
+CONFIG_BRIDGE=y
+CONFIG_NET_PKTGEN=y
+CONFIG_CAN=y
+CONFIG_CAN_XILINXCAN=y
+CONFIG_BT=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+CONFIG_BT_LEDS=y
+CONFIG_BT_HCIBTUSB=y
+CONFIG_BT_HCIBTSDIO=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_ATH3K=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIUART_3WIRE=y
+CONFIG_BT_HCIUART_INTEL=y
+CONFIG_BT_HCIUART_QCA=y
+CONFIG_BT_HCIBCM203X=y
+CONFIG_BT_HCIBPA10X=y
+CONFIG_BT_HCIBFUSB=y
+CONFIG_BT_HCIVHCI=y
+CONFIG_BT_MRVL=y
+CONFIG_BT_MRVL_SDIO=y
+CONFIG_BT_ATH3K=y
+CONFIG_BT_WILINK=y
+CONFIG_CFG80211=y
+CONFIG_NL80211_TESTMODE=y
+CONFIG_CFG80211_CERTIFICATION_ONUS=y
+CONFIG_CFG80211_REG_CELLULAR_HINTS=y
+CONFIG_CFG80211_REG_RELAX_NO_IR=y
+CONFIG_CFG80211_WEXT=y
+CONFIG_MAC80211=y
+CONFIG_MAC80211_LEDS=y
+CONFIG_MAC80211_MESSAGE_TRACING=y
+CONFIG_MAC80211_DEBUG_MENU=y
+CONFIG_RFKILL=y
+CONFIG_RFKILL_INPUT=y
+CONFIG_RFKILL_GPIO=y
+CONFIG_NET_9P=y
+CONFIG_PCI=y
+CONFIG_PCIE_XILINX_NWL=y
+CONFIG_PCIE_XILINX=y
+CONFIG_PCIE_XDMA_PL=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_CONNECTOR=y
+CONFIG_MTD=y
+CONFIG_MTD_TESTS=m
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_OOPS=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_DATAFLASH=y
+CONFIG_MTD_RAW_NAND=y
+CONFIG_MTD_NAND_ARASAN=y
+CONFIG_MTD_SPI_NOR=y
+# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
+CONFIG_SPI_CADENCE_QUADSPI=y
+CONFIG_MTD_UBI=y
+CONFIG_OF_OVERLAY=y
+CONFIG_OF_CONFIGFS=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=65536
+CONFIG_SRAM=y
+CONFIG_XILINX_SDFEC=y
+CONFIG_XILINX_FLEX_PM=y
+CONFIG_XILINX_TRAFGEN=y
+CONFIG_XILINX_AIE=y
+CONFIG_XILINX_JESD204B=y
+CONFIG_XILINX_JESD204B_PHY=y
+CONFIG_EEPROM_AT24=y
+CONFIG_EEPROM_AT25=y
+CONFIG_TI_ST=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_ATA=y
+CONFIG_SATA_AHCI_PLATFORM=y
+CONFIG_AHCI_CEVA=y
+# CONFIG_ATA_SFF is not set
+CONFIG_NETDEVICES=y
+CONFIG_TUN=y
+CONFIG_MACB=y
+CONFIG_XILINX_EMACLITE=y
+CONFIG_XILINX_AXI_EMAC=y
+CONFIG_AMD_PHY=y
+CONFIG_AT803X_PHY=y
+CONFIG_BCM7XXX_PHY=y
+CONFIG_BCM87XX_PHY=y
+CONFIG_BROADCOM_PHY=y
+CONFIG_CICADA_PHY=y
+CONFIG_DAVICOM_PHY=y
+CONFIG_DP83848_PHY=y
+CONFIG_DP83867_PHY=y
+CONFIG_ICPLUS_PHY=y
+CONFIG_LSI_ET1011C_PHY=y
+CONFIG_LXT_PHY=y
+CONFIG_MARVELL_PHY=y
+CONFIG_MICREL_PHY=y
+CONFIG_MICROSEMI_PHY=y
+CONFIG_NATIONAL_PHY=y
+CONFIG_QSEMI_PHY=y
+CONFIG_REALTEK_PHY=y
+CONFIG_SMSC_PHY=y
+CONFIG_STE10XP=y
+CONFIG_VITESSE_PHY=y
+CONFIG_XILINX_PHY=y
+CONFIG_XILINX_GMII2RGMII=y
+CONFIG_USB_USBNET=y
+CONFIG_WL18XX=y
+CONFIG_WLCORE_SPI=y
+CONFIG_WLCORE_SDIO=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_GPIO_POLLED=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SERIAL_AMBA_PL010=y
+CONFIG_SERIAL_AMBA_PL010_CONSOLE=y
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+CONFIG_SERIAL_MAX310X=y
+CONFIG_SERIAL_UARTLITE=y
+CONFIG_SERIAL_UARTLITE_CONSOLE=y
+CONFIG_SERIAL_XILINX_PS_UART=y
+CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y
+CONFIG_SERIAL_DEV_BUS=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_TCG_TPM=y
+CONFIG_TCG_TIS_SPI=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MUX=y
+CONFIG_I2C_MUX_PCA9541=y
+CONFIG_I2C_MUX_PCA954x=y
+CONFIG_I2C_CADENCE=y
+CONFIG_I2C_XILINX=y
+CONFIG_SPI=y
+CONFIG_SPI_CADENCE=y
+CONFIG_SPI_XILINX=y
+CONFIG_SPI_ZYNQMP_GQSPI=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_XILINX=y
+CONFIG_GPIO_ZYNQ=y
+CONFIG_GPIO_PCA953X=y
+CONFIG_GPIO_TPS65086=y
+CONFIG_POWER_RESET_LTC2952=y
+CONFIG_SENSORS_IIO_HWMON=y
+CONFIG_SENSORS_LM63=y
+CONFIG_PMBUS=y
+CONFIG_SENSORS_IRPS5401=y
+CONFIG_SENSORS_MAX20751=y
+CONFIG_WATCHDOG=y
+CONFIG_XILINX_WATCHDOG=y
+CONFIG_CADENCE_WATCHDOG=y
+CONFIG_MFD_TPS65086=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_DA9121=y
+CONFIG_REGULATOR_GPIO=y
+CONFIG_REGULATOR_TPS65086=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_MEDIA_USB_SUPPORT=y
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_VIDEO_XILINX=y
+CONFIG_VIDEO_XILINX_AXI4S_SWITCH=y
+CONFIG_VIDEO_XILINX_CFA=y
+CONFIG_VIDEO_XILINX_CRESAMPLE=y
+CONFIG_VIDEO_XILINX_DEMOSAIC=y
+CONFIG_VIDEO_XILINX_GAMMA=y
+CONFIG_VIDEO_XILINX_HLS=y
+CONFIG_VIDEO_XILINX_REMAPPER=y
+CONFIG_VIDEO_XILINX_RGB2YUV=y
+CONFIG_VIDEO_XILINX_SCALER=y
+CONFIG_VIDEO_XILINX_MULTISCALER=y
+CONFIG_VIDEO_XILINX_SDIRXSS=y
+CONFIG_VIDEO_XILINX_SWITCH=y
+CONFIG_VIDEO_XILINX_TPG=y
+CONFIG_VIDEO_XILINX_VPSS_CSC=y
+CONFIG_VIDEO_XILINX_VPSS_SCALER=y
+CONFIG_VIDEO_XILINX_CSI2RXSS=y
+CONFIG_VIDEO_XILINX_DPRXSS=y
+CONFIG_VIDEO_XILINX_SCD=y
+CONFIG_VIDEO_XILINX_M2M=y
+CONFIG_VIDEO_XILINX_AXI4S_BROADCASTER=y
+CONFIG_VIDEO_IMX274=y
+CONFIG_VIDEO_AP1302=y
+# CONFIG_VGA_ARB is not set
+CONFIG_DRM=y
+CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM=y
+CONFIG_DRM_XLNX=y
+CONFIG_DRM_XLNX_BRIDGE=y
+CONFIG_DRM_XLNX_BRIDGE_DEBUG_FS=y
+CONFIG_DRM_ZYNQMP_DPSUB=y
+CONFIG_DRM_XLNX_DPTX=y
+CONFIG_DRM_XLNX_DSI=y
+CONFIG_DRM_XLNX_MIXER=y
+CONFIG_DRM_XLNX_PL_DISP=y
+CONFIG_DRM_XLNX_SDI=y
+CONFIG_DRM_XLNX_BRIDGE_CSC=y
+CONFIG_DRM_XLNX_BRIDGE_SCALER=y
+CONFIG_DRM_XLNX_BRIDGE_VTC=y
+CONFIG_FB_XILINX=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_PCI is not set
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_XILINX_DP=y
+CONFIG_SND_SOC_XILINX_AUDIO_FORMATTER=y
+CONFIG_SND_SOC_XILINX_SDI=y
+CONFIG_SND_SOC_XILINX_I2S=y
+CONFIG_SND_SOC_XILINX_SPDIF=y
+CONFIG_SND_SOC_XILINX_PL_SND_CARD=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+# CONFIG_USB_DEFAULT_PERSIST is not set
+CONFIG_USB_OTG=y
+CONFIG_USB_OTG_FSM=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_UAS=y
+CONFIG_USB_DWC3=y
+CONFIG_USB_USB5744=m
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_XILINX=y
+CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_EEM=y
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_EEM=y
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_OF_ARASAN=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_ONESHOT=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_CPU=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_LEDS_TRIGGER_TRANSIENT=y
+CONFIG_LEDS_TRIGGER_CAMERA=y
+CONFIG_EDAC=y
+CONFIG_EDAC_SYNOPSYS=y
+CONFIG_EDAC_ZYNQMP_OCM=y
+CONFIG_EDAC_XILINX_DDR=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_ZYNQMP=y
+CONFIG_XILINX_DMA=y
+CONFIG_XILINX_ZYNQMP_DMA=y
+CONFIG_XILINX_PS_PCIE_DMA=y
+CONFIG_DMATEST=y
+CONFIG_UIO_XILINX_APM=y
+CONFIG_UIO_XILINX_AI_ENGINE=y
+CONFIG_STAGING=y
+CONFIG_ION=y
+CONFIG_ION_SYSTEM_HEAP=y
+CONFIG_ION_CMA_HEAP=y
+CONFIG_XILINX_APF=y
+CONFIG_XILINX_DMA_APF=y
+CONFIG_XILINX_FCLK=y
+CONFIG_XLNX_SYNC=y
+CONFIG_COMMON_CLK_SI570=y
+CONFIG_COMMON_CLK_SI5324=y
+CONFIG_COMMON_CLK_IDT8T49N24X=y
+CONFIG_COMMON_CLK_XLNX_CLKWZRD=y
+CONFIG_COMMON_CLK_ZYNQMP=y
+# CONFIG_ARM_ARCH_TIMER_EVTSTREAM is not set
+# CONFIG_FSL_ERRATUM_A008585 is not set
+CONFIG_REMOTEPROC=y
+CONFIG_ZYNQMP_R5_REMOTEPROC=m
+CONFIG_XILINX_VCU=m
+CONFIG_IIO=y
+CONFIG_INA2XX_ADC=y
+CONFIG_INA260_ADC=y
+CONFIG_XILINX_XADC=y
+CONFIG_XILINX_AMS=y
+CONFIG_VERSAL_SYSMON=y
+CONFIG_XILINX_INTC=y
+CONFIG_RESET_CONTROLLER=y
+CONFIG_ARM_CCI_PMU=y
+# CONFIG_ARM_PMU is not set
+CONFIG_RAS=y
+CONFIG_ANDROID=y
+CONFIG_NVMEM_ZYNQMP=y
+CONFIG_FPGA=y
+CONFIG_XILINX_AFI_FPGA=y
+CONFIG_XILINX_PR_DECOUPLER=y
+CONFIG_FPGA_REGION=y
+CONFIG_OF_FPGA_REGION=y
+CONFIG_FPGA_MGR_ZYNQMP_FPGA=y
+CONFIG_FPGA_MGR_VERSAL_FPGA=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_BTRFS_FS=y
+CONFIG_EXPORTFS_BLOCK_OPS=y
+CONFIG_QUOTA=y
+CONFIG_QFMT_V2=y
+CONFIG_AUTOFS4_FS=y
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_HUGETLBFS=y
+CONFIG_ECRYPT_FS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RUBIN=y
+CONFIG_UBIFS_FS=y
+CONFIG_CRAMFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_V4_1=y
+CONFIG_NFS_V4_2=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
+CONFIG_CRYPTO_CRCT10DIF=y
+CONFIG_CRYPTO_USER_API_SKCIPHER=y
+CONFIG_CRYPTO_DEV_ZYNQMP_SHA3=y
+CONFIG_CRYPTO_DEV_XILINX_RSA=y
+CONFIG_CRYPTO_DEV_ZYNQMP_AES=y
+# CONFIG_XZ_DEC_X86 is not set
+# CONFIG_XZ_DEC_POWERPC is not set
+# CONFIG_XZ_DEC_IA64 is not set
+# CONFIG_XZ_DEC_ARM is not set
+# CONFIG_XZ_DEC_ARMTHUMB is not set
+# CONFIG_XZ_DEC_SPARC is not set
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=256
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_FTRACE is not set
+# CONFIG_STRICT_DEVMEM is not set
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/configs/xilinx_versal_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/configs/xilinx_versal_defconfig
@@ -0,0 +1,234 @@
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_AUDIT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EMBEDDED=y
+CONFIG_PERF_EVENTS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+CONFIG_ARCH_ZYNQMP=y
+CONFIG_ARM64_VA_BITS_48=y
+CONFIG_NR_CPUS=2
+CONFIG_COMPAT=y
+# CONFIG_EFI is not set
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+CONFIG_CPUFREQ_DT=y
+CONFIG_ZYNQMP_FIRMWARE_DEBUG=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_SPARSEMEM_VMEMMAP is not set
+# CONFIG_COMPACTION is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=32768
+CONFIG_CMA=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_SYN_COOKIES=y
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_SNMP=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_XTABLES=y
+CONFIG_NETFILTER_XT_MARK=y
+CONFIG_NETFILTER_XT_CONNMARK=y
+CONFIG_BRIDGE_NF_EBTABLES=y
+CONFIG_BRIDGE_EBT_T_FILTER=y
+CONFIG_BRIDGE_EBT_T_NAT=y
+CONFIG_BRIDGE_EBT_MARK_T=y
+CONFIG_BRIDGE=y
+CONFIG_NET_PKTGEN=y
+CONFIG_CAN=y
+CONFIG_CAN_XILINXCAN=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_MTD=y
+CONFIG_MTD_TESTS=m
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_OOPS=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_DATAFLASH=y
+CONFIG_MTD_RAW_NAND=y
+CONFIG_MTD_SPI_NOR=y
+# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
+CONFIG_SPI_CADENCE_QUADSPI=y
+CONFIG_MTD_UBI=y
+CONFIG_OF_OVERLAY=y
+CONFIG_OF_CONFIGFS=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=65536
+CONFIG_SRAM=y
+CONFIG_XILINX_AIE=y
+CONFIG_EEPROM_AT24=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_NETDEVICES=y
+CONFIG_TUN=y
+CONFIG_MACB=y
+CONFIG_DP83848_PHY=y
+CONFIG_DP83867_PHY=y
+CONFIG_MARVELL_PHY=y
+CONFIG_MICROSEMI_PHY=y
+CONFIG_REALTEK_PHY=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_SERIAL_AMBA_PL010=y
+CONFIG_SERIAL_AMBA_PL010_CONSOLE=y
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+CONFIG_SERIAL_XILINX_PS_UART=y
+CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_CADENCE=y
+CONFIG_SPI=y
+CONFIG_SPI_CADENCE=y
+CONFIG_SPI_XILINX=y
+CONFIG_SPI_ZYNQMP_GQSPI=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_ZYNQ=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_XILINX_WATCHDOG=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_VIDEO_XILINX=y
+CONFIG_VIDEO_XILINX_AXI4S_SWITCH=y
+CONFIG_VIDEO_XILINX_CFA=y
+CONFIG_VIDEO_XILINX_CRESAMPLE=y
+CONFIG_VIDEO_XILINX_DEMOSAIC=y
+CONFIG_VIDEO_XILINX_GAMMA=y
+CONFIG_VIDEO_XILINX_HLS=y
+CONFIG_VIDEO_XILINX_REMAPPER=y
+CONFIG_VIDEO_XILINX_RGB2YUV=y
+CONFIG_VIDEO_XILINX_SCALER=y
+CONFIG_VIDEO_XILINX_MULTISCALER=y
+CONFIG_VIDEO_XILINX_SDIRXSS=y
+CONFIG_VIDEO_XILINX_SWITCH=y
+CONFIG_VIDEO_XILINX_TPG=y
+CONFIG_VIDEO_XILINX_VPSS_CSC=y
+CONFIG_VIDEO_XILINX_VPSS_SCALER=y
+CONFIG_VIDEO_XILINX_CSI2RXSS=y
+CONFIG_VIDEO_XILINX_SCD=y
+CONFIG_VIDEO_XILINX_M2M=y
+CONFIG_DRM=y
+CONFIG_DRM_XLNX=y
+CONFIG_DRM_XLNX_BRIDGE=y
+CONFIG_DRM_XLNX_BRIDGE_DEBUG_FS=y
+CONFIG_DRM_XLNX_DSI=y
+CONFIG_DRM_XLNX_MIXER=y
+CONFIG_DRM_XLNX_PL_DISP=y
+CONFIG_DRM_XLNX_SDI=y
+CONFIG_DRM_XLNX_BRIDGE_CSC=y
+CONFIG_DRM_XLNX_BRIDGE_SCALER=y
+CONFIG_DRM_XLNX_BRIDGE_VTC=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_OTG=y
+CONFIG_USB_OTG_FSM=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_DWC3=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_OF_ARASAN=y
+CONFIG_EDAC=y
+CONFIG_EDAC_XILINX_DDR=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_ZYNQMP=y
+CONFIG_XILINX_ZYNQMP_DMA=y
+CONFIG_DMATEST=y
+CONFIG_UIO=y
+CONFIG_UIO_XILINX_AI_ENGINE=y
+CONFIG_STAGING=y
+CONFIG_ION=y
+CONFIG_ION_SYSTEM_HEAP=y
+CONFIG_ION_CMA_HEAP=y
+CONFIG_COMMON_CLK_ZYNQMP=y
+# CONFIG_ARM_ARCH_TIMER_EVTSTREAM is not set
+# CONFIG_FSL_ERRATUM_A008585 is not set
+CONFIG_IIO=y
+CONFIG_VERSAL_SYSMON=y
+CONFIG_XILINX_INTC=y
+CONFIG_ARM_CCI_PMU=y
+# CONFIG_ARM_PMU is not set
+CONFIG_RAS=y
+CONFIG_ANDROID=y
+CONFIG_FPGA=y
+CONFIG_XILINX_PR_DECOUPLER=y
+CONFIG_FPGA_REGION=y
+CONFIG_OF_FPGA_REGION=y
+CONFIG_FPGA_MGR_VERSAL_FPGA=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_BTRFS_FS=y
+CONFIG_EXPORTFS_BLOCK_OPS=y
+CONFIG_QUOTA=y
+CONFIG_QFMT_V2=y
+CONFIG_AUTOFS4_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_ECRYPT_FS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RUBIN=y
+CONFIG_UBIFS_FS=y
+CONFIG_CRAMFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_XZ_DEC_X86 is not set
+# CONFIG_XZ_DEC_POWERPC is not set
+# CONFIG_XZ_DEC_IA64 is not set
+# CONFIG_XZ_DEC_ARM is not set
+# CONFIG_XZ_DEC_ARMTHUMB is not set
+# CONFIG_XZ_DEC_SPARC is not set
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=256
+CONFIG_PRINTK_TIME=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_FTRACE is not set
+# CONFIG_STRICT_DEVMEM is not set
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/configs/xilinx_zynqmp_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/configs/xilinx_zynqmp_defconfig
@@ -0,0 +1,407 @@
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_AUDIT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_CGROUPS=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+CONFIG_PROFILING=y
+CONFIG_ARCH_ZYNQMP=y
+CONFIG_NR_CPUS=4
+CONFIG_COMPAT=y
+# CONFIG_DMI is not set
+CONFIG_CPU_IDLE=y
+CONFIG_ARM_CPUIDLE=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+CONFIG_CPUFREQ_DT=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MEMORY_HOTPLUG=y
+CONFIG_DEFAULT_MMAP_MIN_ADDR=32768
+CONFIG_TRANSPARENT_HUGEPAGE=y
+CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y
+CONFIG_CMA=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_SYN_COOKIES=y
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CT_NETLINK=m
+CONFIG_NETFILTER_XT_MARK=y
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=y
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_BRIDGE_NF_EBTABLES=y
+CONFIG_BRIDGE_EBT_T_FILTER=y
+CONFIG_BRIDGE_EBT_T_NAT=y
+CONFIG_BRIDGE_EBT_MARK_T=y
+CONFIG_BRIDGE=y
+CONFIG_NET_PKTGEN=y
+CONFIG_CAN=y
+CONFIG_CAN_XILINXCAN=y
+CONFIG_BT=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+CONFIG_BT_LEDS=y
+CONFIG_BT_HCIBTUSB=y
+CONFIG_BT_HCIBTSDIO=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_ATH3K=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIUART_3WIRE=y
+CONFIG_BT_HCIUART_INTEL=y
+CONFIG_BT_HCIUART_QCA=y
+CONFIG_BT_HCIBCM203X=y
+CONFIG_BT_HCIBPA10X=y
+CONFIG_BT_HCIBFUSB=y
+CONFIG_BT_HCIVHCI=y
+CONFIG_BT_MRVL=y
+CONFIG_BT_MRVL_SDIO=y
+CONFIG_BT_ATH3K=y
+CONFIG_BT_WILINK=y
+CONFIG_CFG80211=y
+CONFIG_NL80211_TESTMODE=y
+CONFIG_CFG80211_CERTIFICATION_ONUS=y
+CONFIG_CFG80211_REG_CELLULAR_HINTS=y
+CONFIG_CFG80211_REG_RELAX_NO_IR=y
+CONFIG_CFG80211_WEXT=y
+CONFIG_MAC80211=y
+CONFIG_MAC80211_LEDS=y
+CONFIG_MAC80211_MESSAGE_TRACING=y
+CONFIG_MAC80211_DEBUG_MENU=y
+CONFIG_RFKILL=y
+CONFIG_RFKILL_INPUT=y
+CONFIG_RFKILL_GPIO=y
+CONFIG_NET_9P=y
+CONFIG_PCI=y
+CONFIG_PCIE_XILINX_NWL=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_CONNECTOR=y
+CONFIG_MTD=y
+CONFIG_MTD_TESTS=m
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_OOPS=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_DATAFLASH=y
+CONFIG_MTD_RAW_NAND=y
+CONFIG_MTD_NAND_ARASAN=y
+CONFIG_MTD_SPI_NOR=y
+# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
+CONFIG_MTD_UBI=y
+CONFIG_OF_OVERLAY=y
+CONFIG_OF_CONFIGFS=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=65536
+CONFIG_XILINX_SDFEC=y
+CONFIG_XILINX_JESD204B=y
+CONFIG_XILINX_JESD204B_PHY=y
+CONFIG_EEPROM_AT24=y
+CONFIG_EEPROM_AT25=y
+CONFIG_TI_ST=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_ATA=y
+CONFIG_SATA_AHCI_PLATFORM=y
+CONFIG_AHCI_CEVA=y
+# CONFIG_ATA_SFF is not set
+CONFIG_NETDEVICES=y
+CONFIG_TUN=y
+CONFIG_MACB=y
+CONFIG_XILINX_EMACLITE=y
+CONFIG_XILINX_AXI_EMAC=y
+CONFIG_AMD_PHY=y
+CONFIG_AT803X_PHY=y
+CONFIG_BCM7XXX_PHY=y
+CONFIG_BCM87XX_PHY=y
+CONFIG_BROADCOM_PHY=y
+CONFIG_CICADA_PHY=y
+CONFIG_DAVICOM_PHY=y
+CONFIG_DP83867_PHY=y
+CONFIG_ICPLUS_PHY=y
+CONFIG_LSI_ET1011C_PHY=y
+CONFIG_LXT_PHY=y
+CONFIG_MARVELL_PHY=y
+CONFIG_MICREL_PHY=y
+CONFIG_NATIONAL_PHY=y
+CONFIG_QSEMI_PHY=y
+CONFIG_REALTEK_PHY=y
+CONFIG_SMSC_PHY=y
+CONFIG_STE10XP=y
+CONFIG_VITESSE_PHY=y
+CONFIG_XILINX_GMII2RGMII=y
+CONFIG_USB_USBNET=y
+CONFIG_WL18XX=y
+CONFIG_WLCORE_SPI=y
+CONFIG_WLCORE_SDIO=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_GPIO_POLLED=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SERIAL_MAX310X=y
+CONFIG_SERIAL_UARTLITE=y
+CONFIG_SERIAL_UARTLITE_CONSOLE=y
+CONFIG_SERIAL_XILINX_PS_UART=y
+CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y
+CONFIG_SERIAL_DEV_BUS=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_TCG_TPM=y
+CONFIG_TCG_TIS_SPI=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MUX=y
+CONFIG_I2C_MUX_PCA954x=y
+CONFIG_I2C_CADENCE=y
+CONFIG_I2C_XILINX=y
+CONFIG_I2C_SLAVE=y
+CONFIG_I2C_SLAVE_EEPROM=y
+CONFIG_SPI=y
+CONFIG_SPI_CADENCE=y
+CONFIG_SPI_XILINX=y
+CONFIG_SPI_ZYNQMP_GQSPI=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_XILINX=y
+CONFIG_GPIO_ZYNQ=y
+CONFIG_GPIO_PCA953X=y
+CONFIG_GPIO_TPS65086=y
+CONFIG_POWER_RESET_LTC2952=y
+CONFIG_SENSORS_IIO_HWMON=y
+CONFIG_SENSORS_LM63=y
+CONFIG_PMBUS=y
+CONFIG_SENSORS_IRPS5401=y
+CONFIG_SENSORS_MAX20751=y
+CONFIG_WATCHDOG=y
+CONFIG_XILINX_WATCHDOG=y
+CONFIG_CADENCE_WATCHDOG=y
+CONFIG_MFD_TPS65086=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_DA9121=y
+CONFIG_REGULATOR_GPIO=y
+CONFIG_REGULATOR_TPS65086=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_MEDIA_USB_SUPPORT=y
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_VIDEO_XILINX=y
+CONFIG_VIDEO_XILINX_AXI4S_SWITCH=y
+CONFIG_VIDEO_XILINX_CFA=y
+CONFIG_VIDEO_XILINX_CRESAMPLE=y
+CONFIG_VIDEO_XILINX_DEMOSAIC=y
+CONFIG_VIDEO_XILINX_GAMMA=y
+CONFIG_VIDEO_XILINX_HLS=y
+CONFIG_VIDEO_XILINX_REMAPPER=y
+CONFIG_VIDEO_XILINX_RGB2YUV=y
+CONFIG_VIDEO_XILINX_SCALER=y
+CONFIG_VIDEO_XILINX_MULTISCALER=y
+CONFIG_VIDEO_XILINX_SDIRXSS=y
+CONFIG_VIDEO_XILINX_SWITCH=y
+CONFIG_VIDEO_XILINX_TPG=y
+CONFIG_VIDEO_XILINX_VPSS_CSC=y
+CONFIG_VIDEO_XILINX_VPSS_SCALER=y
+CONFIG_VIDEO_XILINX_CSI2RXSS=y
+CONFIG_VIDEO_XILINX_SCD=y
+CONFIG_VIDEO_XILINX_M2M=y
+CONFIG_VIDEO_XILINX_AXI4S_BROADCASTER=y
+CONFIG_VIDEO_IMX274=y
+CONFIG_VIDEO_AP1302=y
+# CONFIG_VGA_ARB is not set
+CONFIG_DRM=y
+CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM=y
+CONFIG_DRM_XLNX=y
+CONFIG_DRM_XLNX_BRIDGE=y
+CONFIG_DRM_XLNX_BRIDGE_DEBUG_FS=y
+CONFIG_DRM_ZYNQMP_DPSUB=y
+CONFIG_DRM_XLNX_DSI=y
+CONFIG_DRM_XLNX_MIXER=y
+CONFIG_DRM_XLNX_PL_DISP=y
+CONFIG_DRM_XLNX_SDI=y
+CONFIG_DRM_XLNX_BRIDGE_CSC=y
+CONFIG_DRM_XLNX_BRIDGE_SCALER=y
+CONFIG_DRM_XLNX_BRIDGE_VTC=y
+CONFIG_FB_XILINX=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_PCI is not set
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_XILINX_DP=y
+CONFIG_SND_SOC_XILINX_AUDIO_FORMATTER=y
+CONFIG_SND_SOC_XILINX_SDI=y
+CONFIG_SND_SOC_XILINX_I2S=y
+CONFIG_SND_SOC_XILINX_SPDIF=y
+CONFIG_SND_SOC_XILINX_PL_SND_CARD=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+# CONFIG_USB_DEFAULT_PERSIST is not set
+CONFIG_USB_OTG=y
+CONFIG_USB_OTG_FSM=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_UAS=y
+CONFIG_USB_DWC3=y
+CONFIG_USB_USB5744=m
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_XILINX=y
+CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_EEM=y
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_EEM=y
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_OF_ARASAN=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_ONESHOT=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_CPU=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_LEDS_TRIGGER_TRANSIENT=y
+CONFIG_LEDS_TRIGGER_CAMERA=y
+CONFIG_EDAC=y
+CONFIG_EDAC_SYNOPSYS=y
+CONFIG_EDAC_ZYNQMP_OCM=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_ZYNQMP=y
+CONFIG_XILINX_DMA=y
+CONFIG_XILINX_ZYNQMP_DMA=y
+CONFIG_DMATEST=y
+CONFIG_UIO=y
+CONFIG_UIO_PDRV_GENIRQ=m
+CONFIG_UIO_DMEM_GENIRQ=m
+CONFIG_UIO_XILINX_APM=y
+CONFIG_STAGING=y
+CONFIG_ION=y
+CONFIG_ION_SYSTEM_HEAP=y
+CONFIG_ION_CMA_HEAP=y
+CONFIG_XILINX_FCLK=y
+CONFIG_XLNX_SYNC=y
+CONFIG_COMMON_CLK_SI570=y
+CONFIG_COMMON_CLK_SI5324=y
+CONFIG_COMMON_CLK_IDT8T49N24X=y
+CONFIG_COMMON_CLK_XLNX_CLKWZRD=y
+CONFIG_COMMON_CLK_ZYNQMP=y
+CONFIG_REMOTEPROC=y
+CONFIG_ZYNQMP_R5_REMOTEPROC=m
+CONFIG_XILINX_VCU=m
+CONFIG_IIO=y
+CONFIG_INA2XX_ADC=y
+CONFIG_INA260_ADC=y
+CONFIG_XILINX_XADC=y
+CONFIG_XILINX_AMS=y
+CONFIG_XILINX_INTC=y
+CONFIG_RESET_CONTROLLER=y
+CONFIG_RAS=y
+CONFIG_ANDROID=y
+CONFIG_NVMEM_ZYNQMP=y
+CONFIG_FPGA=y
+CONFIG_XILINX_AFI_FPGA=y
+CONFIG_FPGA_BRIDGE=y
+CONFIG_XILINX_PR_DECOUPLER=y
+CONFIG_FPGA_REGION=y
+CONFIG_OF_FPGA_REGION=y
+CONFIG_FPGA_MGR_ZYNQMP_FPGA=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_BTRFS_FS=y
+CONFIG_QUOTA=y
+CONFIG_QFMT_V2=y
+CONFIG_AUTOFS4_FS=y
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_HUGETLBFS=y
+CONFIG_ECRYPT_FS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RUBIN=y
+CONFIG_UBIFS_FS=y
+CONFIG_CRAMFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_V4_1=y
+CONFIG_NFS_V4_2=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set
+CONFIG_CRYPTO_CRCT10DIF=y
+CONFIG_CRYPTO_USER_API_SKCIPHER=y
+CONFIG_CRYPTO_DEV_ZYNQMP_SHA3=y
+CONFIG_CRYPTO_DEV_XILINX_RSA=y
+CONFIG_CRYPTO_DEV_ZYNQMP_AES=y
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=256
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_FS=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_FTRACE is not set
+# CONFIG_STRICT_DEVMEM is not set
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/crypto/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/crypto/Kconfig
@@ -59,6 +59,7 @@
 	select CRYPTO_HASH
 	select CRYPTO_GF128MUL
 	select CRYPTO_LIB_AES
+	select CRYPTO_AEAD
 
 config CRYPTO_CRCT10DIF_ARM64_CE
 	tristate "CRCT10DIF digest algorithm using PMULL instructions"
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/crypto/aes-glue.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/crypto/aes-glue.c
@@ -55,7 +55,7 @@
 #define aes_mac_update		neon_aes_mac_update
 MODULE_DESCRIPTION("AES-ECB/CBC/CTR/XTS using ARMv8 NEON");
 #endif
-#if defined(USE_V8_CRYPTO_EXTENSIONS) || !defined(CONFIG_CRYPTO_AES_ARM64_BS)
+#if defined(USE_V8_CRYPTO_EXTENSIONS) || !IS_ENABLED(CONFIG_CRYPTO_AES_ARM64_BS)
 MODULE_ALIAS_CRYPTO("ecb(aes)");
 MODULE_ALIAS_CRYPTO("cbc(aes)");
 MODULE_ALIAS_CRYPTO("ctr(aes)");
@@ -668,7 +668,7 @@
 }
 
 static struct skcipher_alg aes_algs[] = { {
-#if defined(USE_V8_CRYPTO_EXTENSIONS) || !defined(CONFIG_CRYPTO_AES_ARM64_BS)
+#if defined(USE_V8_CRYPTO_EXTENSIONS) || !IS_ENABLED(CONFIG_CRYPTO_AES_ARM64_BS)
 	.base = {
 		.cra_name		= "__ecb(aes)",
 		.cra_driver_name	= "__ecb-aes-" MODE,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/crypto/aes-neonbs-glue.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/crypto/aes-neonbs-glue.c
@@ -384,7 +384,7 @@
 			goto xts_tail;
 
 		kernel_neon_end();
-		skcipher_walk_done(&walk, nbytes);
+		err = skcipher_walk_done(&walk, nbytes);
 	}
 
 	if (err || likely(!tail))
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/crypto/ghash-ce-glue.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/crypto/ghash-ce-glue.c
@@ -261,7 +261,7 @@
 static struct shash_alg ghash_alg[] = {{
 	.base.cra_name		= "ghash",
 	.base.cra_driver_name	= "ghash-neon",
-	.base.cra_priority	= 100,
+	.base.cra_priority	= 150,
 	.base.cra_blocksize	= GHASH_BLOCK_SIZE,
 	.base.cra_ctxsize	= sizeof(struct ghash_key),
 	.base.cra_module	= THIS_MODULE,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/crypto/nhpoly1305-neon-glue.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/crypto/nhpoly1305-neon-glue.c
@@ -30,7 +30,7 @@
 		return crypto_nhpoly1305_update(desc, src, srclen);
 
 	do {
-		unsigned int n = min_t(unsigned int, srclen, PAGE_SIZE);
+		unsigned int n = min_t(unsigned int, srclen, SZ_4K);
 
 		kernel_neon_begin();
 		crypto_nhpoly1305_update_helper(desc, src, n, _nh_neon);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/crypto/sha1-ce-glue.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/crypto/sha1-ce-glue.c
@@ -19,6 +19,7 @@
 MODULE_DESCRIPTION("SHA1 secure hash using ARMv8 Crypto Extensions");
 MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
 MODULE_LICENSE("GPL v2");
+MODULE_ALIAS_CRYPTO("sha1");
 
 struct sha1_ce_state {
 	struct sha1_state	sst;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/crypto/sha2-ce-glue.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/crypto/sha2-ce-glue.c
@@ -19,6 +19,8 @@
 MODULE_DESCRIPTION("SHA-224/SHA-256 secure hash using ARMv8 Crypto Extensions");
 MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
 MODULE_LICENSE("GPL v2");
+MODULE_ALIAS_CRYPTO("sha224");
+MODULE_ALIAS_CRYPTO("sha256");
 
 struct sha256_ce_state {
 	struct sha256_state	sst;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/crypto/sha3-ce-glue.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/crypto/sha3-ce-glue.c
@@ -23,6 +23,10 @@
 MODULE_DESCRIPTION("SHA3 secure hash using ARMv8 Crypto Extensions");
 MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
 MODULE_LICENSE("GPL v2");
+MODULE_ALIAS_CRYPTO("sha3-224");
+MODULE_ALIAS_CRYPTO("sha3-256");
+MODULE_ALIAS_CRYPTO("sha3-384");
+MODULE_ALIAS_CRYPTO("sha3-512");
 
 asmlinkage void sha3_ce_transform(u64 *st, const u8 *data, int blocks,
 				  int md_len);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/crypto/sha512-ce-glue.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/crypto/sha512-ce-glue.c
@@ -23,6 +23,8 @@
 MODULE_DESCRIPTION("SHA-384/SHA-512 secure hash using ARMv8 Crypto Extensions");
 MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
 MODULE_LICENSE("GPL v2");
+MODULE_ALIAS_CRYPTO("sha384");
+MODULE_ALIAS_CRYPTO("sha512");
 
 asmlinkage void sha512_ce_transform(struct sha512_state *sst, u8 const *src,
 				    int blocks);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/Kbuild
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/Kbuild
@@ -3,7 +3,6 @@
 generic-y += delay.h
 generic-y += div64.h
 generic-y += dma.h
-generic-y += dma-contiguous.h
 generic-y += dma-mapping.h
 generic-y += early_ioremap.h
 generic-y += emergency-restart.h
@@ -16,7 +15,6 @@
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
 generic-y += mmiowb.h
-generic-y += msi.h
 generic-y += qrwlock.h
 generic-y += qspinlock.h
 generic-y += serial.h
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/acpi.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/acpi.h
@@ -12,6 +12,7 @@
 #include <linux/efi.h>
 #include <linux/memblock.h>
 #include <linux/psci.h>
+#include <linux/stddef.h>
 
 #include <asm/cputype.h>
 #include <asm/io.h>
@@ -31,14 +32,14 @@
  * is therefore used to delimit the MADT GICC structure minimum length
  * appropriately.
  */
-#define ACPI_MADT_GICC_MIN_LENGTH   ACPI_OFFSET(  \
+#define ACPI_MADT_GICC_MIN_LENGTH   offsetof(  \
 	struct acpi_madt_generic_interrupt, efficiency_class)
 
 #define BAD_MADT_GICC_ENTRY(entry, end)					\
 	(!(entry) || (entry)->header.length < ACPI_MADT_GICC_MIN_LENGTH || \
 	(unsigned long)(entry) + (entry)->header.length > (end))
 
-#define ACPI_MADT_GICC_SPE  (ACPI_OFFSET(struct acpi_madt_generic_interrupt, \
+#define ACPI_MADT_GICC_SPE  (offsetof(struct acpi_madt_generic_interrupt, \
 	spe_interrupt) + sizeof(u16))
 
 /* Basic configuration for ACPI */
@@ -109,6 +110,18 @@
 	return	acpi_cpu_get_madt_gicc(cpu)->uid;
 }
 
+static inline int get_cpu_for_acpi_id(u32 uid)
+{
+	int cpu;
+
+	for (cpu = 0; cpu < nr_cpu_ids; cpu++)
+		if (acpi_cpu_get_madt_gicc(cpu) &&
+		    uid == get_acpi_id_for_cpu(cpu))
+			return cpu;
+
+	return -EINVAL;
+}
+
 static inline void arch_fix_phys_package_id(int num, u32 slot) { }
 void __init acpi_init_cpus(void);
 int apei_claim_sea(struct pt_regs *regs);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/alternative.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/alternative.h
@@ -35,13 +35,16 @@
 static inline void apply_alternatives_module(void *start, size_t length) { }
 #endif
 
-#define ALTINSTR_ENTRY(feature,cb)					      \
+#define ALTINSTR_ENTRY(feature)					              \
 	" .word 661b - .\n"				/* label           */ \
-	" .if " __stringify(cb) " == 0\n"				      \
 	" .word 663f - .\n"				/* new instruction */ \
-	" .else\n"							      \
+	" .hword " __stringify(feature) "\n"		/* feature bit     */ \
+	" .byte 662b-661b\n"				/* source len      */ \
+	" .byte 664f-663f\n"				/* replacement len */
+
+#define ALTINSTR_ENTRY_CB(feature, cb)					      \
+	" .word 661b - .\n"				/* label           */ \
 	" .word " __stringify(cb) "- .\n"		/* callback */	      \
-	" .endif\n"							      \
 	" .hword " __stringify(feature) "\n"		/* feature bit     */ \
 	" .byte 662b-661b\n"				/* source len      */ \
 	" .byte 664f-663f\n"				/* replacement len */
@@ -62,33 +65,40 @@
  *
  * Alternatives with callbacks do not generate replacement instructions.
  */
-#define __ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg_enabled, cb)	\
+#define __ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg_enabled)	\
 	".if "__stringify(cfg_enabled)" == 1\n"				\
 	"661:\n\t"							\
 	oldinstr "\n"							\
 	"662:\n"							\
 	".pushsection .altinstructions,\"a\"\n"				\
-	ALTINSTR_ENTRY(feature,cb)					\
+	ALTINSTR_ENTRY(feature)						\
 	".popsection\n"							\
-	" .if " __stringify(cb) " == 0\n"				\
-	".pushsection .altinstr_replacement, \"a\"\n"			\
+	".subsection 1\n"						\
 	"663:\n\t"							\
 	newinstr "\n"							\
 	"664:\n\t"							\
-	".popsection\n\t"						\
 	".org	. - (664b-663b) + (662b-661b)\n\t"			\
-	".org	. - (662b-661b) + (664b-663b)\n"			\
-	".else\n\t"							\
+	".org	. - (662b-661b) + (664b-663b)\n\t"			\
+	".previous\n"							\
+	".endif\n"
+
+#define __ALTERNATIVE_CFG_CB(oldinstr, feature, cfg_enabled, cb)	\
+	".if "__stringify(cfg_enabled)" == 1\n"				\
+	"661:\n\t"							\
+	oldinstr "\n"							\
+	"662:\n"							\
+	".pushsection .altinstructions,\"a\"\n"				\
+	ALTINSTR_ENTRY_CB(feature, cb)					\
+	".popsection\n"							\
 	"663:\n\t"							\
 	"664:\n\t"							\
-	".endif\n"							\
 	".endif\n"
 
 #define _ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg, ...)	\
-	__ALTERNATIVE_CFG(oldinstr, newinstr, feature, IS_ENABLED(cfg), 0)
+	__ALTERNATIVE_CFG(oldinstr, newinstr, feature, IS_ENABLED(cfg))
 
 #define ALTERNATIVE_CB(oldinstr, cb) \
-	__ALTERNATIVE_CFG(oldinstr, "NOT_AN_INSTRUCTION", ARM64_CB_PATCH, 1, cb)
+	__ALTERNATIVE_CFG_CB(oldinstr, ARM64_CB_PATCH, 1, cb)
 #else
 
 #include <asm/assembler.h>
@@ -107,11 +117,11 @@
 662:	.pushsection .altinstructions, "a"
 	altinstruction_entry 661b, 663f, \cap, 662b-661b, 664f-663f
 	.popsection
-	.pushsection .altinstr_replacement, "ax"
+	.subsection 1
 663:	\insn2
-664:	.popsection
-	.org	. - (664b-663b) + (662b-661b)
+664:	.org	. - (664b-663b) + (662b-661b)
 	.org	. - (662b-661b) + (664b-663b)
+	.previous
 	.endif
 .endm
 
@@ -150,7 +160,7 @@
 	.pushsection .altinstructions, "a"
 	altinstruction_entry 663f, 661f, \cap, 664f-663f, 662f-661f
 	.popsection
-	.pushsection .altinstr_replacement, "ax"
+	.subsection 1
 	.align 2	/* So GAS knows label 661 is suitably aligned */
 661:
 .endm
@@ -169,9 +179,9 @@
 .macro alternative_else
 662:
 	.if .Lasm_alt_mode==0
-	.pushsection .altinstr_replacement, "ax"
+	.subsection 1
 	.else
-	.popsection
+	.previous
 	.endif
 663:
 .endm
@@ -181,11 +191,11 @@
  */
 .macro alternative_endif
 664:
-	.if .Lasm_alt_mode==0
-	.popsection
-	.endif
 	.org	. - (664b-663b) + (662b-661b)
 	.org	. - (662b-661b) + (664b-663b)
+	.if .Lasm_alt_mode==0
+	.previous
+	.endif
 .endm
 
 /*
@@ -211,7 +221,7 @@
 
 .macro user_alt, label, oldinstr, newinstr, cond
 9999:	alternative_insn "\oldinstr", "\newinstr", \cond
-	_ASM_EXTABLE 9999b, \label
+	_asm_extable 9999b, \label
 .endm
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/arch_gicv3.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/arch_gicv3.h
@@ -109,7 +109,7 @@
 	return read_sysreg_s(SYS_ICC_PMR_EL1);
 }
 
-static inline void gic_write_pmr(u32 val)
+static __always_inline void gic_write_pmr(u32 val)
 {
 	write_sysreg_s(val, SYS_ICC_PMR_EL1);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/arch_timer.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/arch_timer.h
@@ -58,6 +58,7 @@
 	u64 (*read_cntvct_el0)(void);
 	int (*set_next_event_phys)(unsigned long, struct clock_event_device *);
 	int (*set_next_event_virt)(unsigned long, struct clock_event_device *);
+	bool disable_compat_vdso;
 };
 
 DECLARE_PER_CPU(const struct arch_timer_erratum_workaround *,
@@ -164,25 +165,6 @@
 	isb();
 }
 
-/*
- * Ensure that reads of the counter are treated the same as memory reads
- * for the purposes of ordering by subsequent memory barriers.
- *
- * This insanity brought to you by speculative system register reads,
- * out-of-order memory accesses, sequence locks and Thomas Gleixner.
- *
- * http://lists.infradead.org/pipermail/linux-arm-kernel/2019-February/631195.html
- */
-#define arch_counter_enforce_ordering(val) do {				\
-	u64 tmp, _val = (val);						\
-									\
-	asm volatile(							\
-	"	eor	%0, %1, %1\n"					\
-	"	add	%0, sp, %0\n"					\
-	"	ldr	xzr, [%0]"					\
-	: "=r" (tmp) : "r" (_val));					\
-} while (0)
-
 static __always_inline u64 __arch_counter_get_cntpct_stable(void)
 {
 	u64 cnt;
@@ -223,8 +205,6 @@
 	return cnt;
 }
 
-#undef arch_counter_enforce_ordering
-
 static inline int arch_timer_arch_init(void)
 {
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/asm-bug.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/asm-bug.h
@@ -28,6 +28,7 @@
 	14470:	.long 14471f - 14470b;			\
 _BUGVERBOSE_LOCATION(__FILE__, __LINE__)		\
 		.short flags; 				\
+		.align 2;				\
 		.popsection;				\
 	14471:
 #else
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/asm-uaccess.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/asm-uaccess.h
@@ -15,10 +15,10 @@
 	.macro	__uaccess_ttbr0_disable, tmp1
 	mrs	\tmp1, ttbr1_el1			// swapper_pg_dir
 	bic	\tmp1, \tmp1, #TTBR_ASID_MASK
-	sub	\tmp1, \tmp1, #RESERVED_TTBR0_SIZE	// reserved_ttbr0 just before swapper_pg_dir
+	sub	\tmp1, \tmp1, #PAGE_SIZE		// reserved_pg_dir just before swapper_pg_dir
 	msr	ttbr0_el1, \tmp1			// set reserved TTBR0_EL1
 	isb
-	add	\tmp1, \tmp1, #RESERVED_TTBR0_SIZE
+	add	\tmp1, \tmp1, #PAGE_SIZE
 	msr	ttbr1_el1, \tmp1		// set reserved ASID
 	isb
 	.endm
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/assembler.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/assembler.h
@@ -111,6 +111,13 @@
 	.endm
 
 /*
+ * Clear Branch History instruction
+ */
+	.macro clearbhb
+	hint	#22
+	.endm
+
+/*
  * Speculation barrier
  */
 	.macro	sb
@@ -462,6 +469,7 @@
 	.endm
 
 /*
+ * Deprecated! Use SYM_FUNC_{START,START_WEAK,END}_PI instead.
  * Annotate a function as position independent, i.e., safe to be called before
  * the kernel virtual mapping is activated.
  */
@@ -756,4 +764,30 @@
 .Lyield_out_\@ :
 	.endm
 
+	.macro __mitigate_spectre_bhb_loop      tmp
+#ifdef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY
+alternative_cb  spectre_bhb_patch_loop_iter
+	mov	\tmp, #32		// Patched to correct the immediate
+alternative_cb_end
+.Lspectre_bhb_loop\@:
+	b	. + 4
+	subs	\tmp, \tmp, #1
+	b.ne	.Lspectre_bhb_loop\@
+	sb
+#endif /* CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */
+	.endm
+
+	/* Save/restores x0-x3 to the stack */
+	.macro __mitigate_spectre_bhb_fw
+#ifdef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY
+	stp	x0, x1, [sp, #-16]!
+	stp	x2, x3, [sp, #-16]!
+	mov	w0, #ARM_SMCCC_ARCH_WORKAROUND_3
+alternative_cb	arm64_update_smccc_conduit
+	nop					// Patched to SMC/HVC #0
+alternative_cb_end
+	ldp	x2, x3, [sp], #16
+	ldp	x0, x1, [sp], #16
+#endif /* CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */
+	.endm
 #endif	/* __ASM_ASSEMBLER_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/atomic.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/atomic.h
@@ -17,7 +17,7 @@
 #include <asm/lse.h>
 
 #define ATOMIC_OP(op)							\
-static inline void arch_##op(int i, atomic_t *v)			\
+static __always_inline void arch_##op(int i, atomic_t *v)		\
 {									\
 	__lse_ll_sc_body(op, i, v);					\
 }
@@ -32,7 +32,7 @@
 #undef ATOMIC_OP
 
 #define ATOMIC_FETCH_OP(name, op)					\
-static inline int arch_##op##name(int i, atomic_t *v)			\
+static __always_inline int arch_##op##name(int i, atomic_t *v)		\
 {									\
 	return __lse_ll_sc_body(op##name, i, v);			\
 }
@@ -56,7 +56,7 @@
 #undef ATOMIC_FETCH_OPS
 
 #define ATOMIC64_OP(op)							\
-static inline void arch_##op(long i, atomic64_t *v)			\
+static __always_inline void arch_##op(long i, atomic64_t *v)		\
 {									\
 	__lse_ll_sc_body(op, i, v);					\
 }
@@ -71,7 +71,7 @@
 #undef ATOMIC64_OP
 
 #define ATOMIC64_FETCH_OP(name, op)					\
-static inline long arch_##op##name(long i, atomic64_t *v)		\
+static __always_inline long arch_##op##name(long i, atomic64_t *v)	\
 {									\
 	return __lse_ll_sc_body(op##name, i, v);			\
 }
@@ -94,7 +94,7 @@
 #undef ATOMIC64_FETCH_OP
 #undef ATOMIC64_FETCH_OPS
 
-static inline long arch_atomic64_dec_if_positive(atomic64_t *v)
+static __always_inline long arch_atomic64_dec_if_positive(atomic64_t *v)
 {
 	return __lse_ll_sc_body(atomic64_dec_if_positive, v);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/atomic_ll_sc.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/atomic_ll_sc.h
@@ -12,19 +12,6 @@
 
 #include <linux/stringify.h>
 
-#if IS_ENABLED(CONFIG_ARM64_LSE_ATOMICS) && IS_ENABLED(CONFIG_AS_LSE)
-#define __LL_SC_FALLBACK(asm_ops)					\
-"	b	3f\n"							\
-"	.subsection	1\n"						\
-"3:\n"									\
-asm_ops "\n"								\
-"	b	4f\n"							\
-"	.previous\n"							\
-"4:\n"
-#else
-#define __LL_SC_FALLBACK(asm_ops) asm_ops
-#endif
-
 #ifndef CONFIG_CC_HAS_K_CONSTRAINT
 #define K
 #endif
@@ -43,12 +30,11 @@
 	int result;							\
 									\
 	asm volatile("// atomic_" #op "\n"				\
-	__LL_SC_FALLBACK(						\
-"	prfm	pstl1strm, %2\n"					\
-"1:	ldxr	%w0, %2\n"						\
-"	" #asm_op "	%w0, %w0, %w3\n"				\
-"	stxr	%w1, %w0, %2\n"						\
-"	cbnz	%w1, 1b\n")						\
+	"	prfm	pstl1strm, %2\n"				\
+	"1:	ldxr	%w0, %2\n"					\
+	"	" #asm_op "	%w0, %w0, %w3\n"			\
+	"	stxr	%w1, %w0, %2\n"					\
+	"	cbnz	%w1, 1b\n"					\
 	: "=&r" (result), "=&r" (tmp), "+Q" (v->counter)		\
 	: __stringify(constraint) "r" (i));				\
 }
@@ -61,13 +47,12 @@
 	int result;							\
 									\
 	asm volatile("// atomic_" #op "_return" #name "\n"		\
-	__LL_SC_FALLBACK(						\
-"	prfm	pstl1strm, %2\n"					\
-"1:	ld" #acq "xr	%w0, %2\n"					\
-"	" #asm_op "	%w0, %w0, %w3\n"				\
-"	st" #rel "xr	%w1, %w0, %2\n"					\
-"	cbnz	%w1, 1b\n"						\
-"	" #mb )								\
+	"	prfm	pstl1strm, %2\n"				\
+	"1:	ld" #acq "xr	%w0, %2\n"				\
+	"	" #asm_op "	%w0, %w0, %w3\n"			\
+	"	st" #rel "xr	%w1, %w0, %2\n"				\
+	"	cbnz	%w1, 1b\n"					\
+	"	" #mb							\
 	: "=&r" (result), "=&r" (tmp), "+Q" (v->counter)		\
 	: __stringify(constraint) "r" (i)				\
 	: cl);								\
@@ -83,13 +68,12 @@
 	int val, result;						\
 									\
 	asm volatile("// atomic_fetch_" #op #name "\n"			\
-	__LL_SC_FALLBACK(						\
-"	prfm	pstl1strm, %3\n"					\
-"1:	ld" #acq "xr	%w0, %3\n"					\
-"	" #asm_op "	%w1, %w0, %w4\n"				\
-"	st" #rel "xr	%w2, %w1, %3\n"					\
-"	cbnz	%w2, 1b\n"						\
-"	" #mb )								\
+	"	prfm	pstl1strm, %3\n"				\
+	"1:	ld" #acq "xr	%w0, %3\n"				\
+	"	" #asm_op "	%w1, %w0, %w4\n"			\
+	"	st" #rel "xr	%w2, %w1, %3\n"				\
+	"	cbnz	%w2, 1b\n"					\
+	"	" #mb							\
 	: "=&r" (result), "=&r" (val), "=&r" (tmp), "+Q" (v->counter)	\
 	: __stringify(constraint) "r" (i)				\
 	: cl);								\
@@ -142,12 +126,11 @@
 	unsigned long tmp;						\
 									\
 	asm volatile("// atomic64_" #op "\n"				\
-	__LL_SC_FALLBACK(						\
-"	prfm	pstl1strm, %2\n"					\
-"1:	ldxr	%0, %2\n"						\
-"	" #asm_op "	%0, %0, %3\n"					\
-"	stxr	%w1, %0, %2\n"						\
-"	cbnz	%w1, 1b")						\
+	"	prfm	pstl1strm, %2\n"				\
+	"1:	ldxr	%0, %2\n"					\
+	"	" #asm_op "	%0, %0, %3\n"				\
+	"	stxr	%w1, %0, %2\n"					\
+	"	cbnz	%w1, 1b"					\
 	: "=&r" (result), "=&r" (tmp), "+Q" (v->counter)		\
 	: __stringify(constraint) "r" (i));				\
 }
@@ -160,13 +143,12 @@
 	unsigned long tmp;						\
 									\
 	asm volatile("// atomic64_" #op "_return" #name "\n"		\
-	__LL_SC_FALLBACK(						\
-"	prfm	pstl1strm, %2\n"					\
-"1:	ld" #acq "xr	%0, %2\n"					\
-"	" #asm_op "	%0, %0, %3\n"					\
-"	st" #rel "xr	%w1, %0, %2\n"					\
-"	cbnz	%w1, 1b\n"						\
-"	" #mb )								\
+	"	prfm	pstl1strm, %2\n"				\
+	"1:	ld" #acq "xr	%0, %2\n"				\
+	"	" #asm_op "	%0, %0, %3\n"				\
+	"	st" #rel "xr	%w1, %0, %2\n"				\
+	"	cbnz	%w1, 1b\n"					\
+	"	" #mb							\
 	: "=&r" (result), "=&r" (tmp), "+Q" (v->counter)		\
 	: __stringify(constraint) "r" (i)				\
 	: cl);								\
@@ -176,19 +158,18 @@
 
 #define ATOMIC64_FETCH_OP(name, mb, acq, rel, cl, op, asm_op, constraint)\
 static inline long							\
-__ll_sc_atomic64_fetch_##op##name(s64 i, atomic64_t *v)		\
+__ll_sc_atomic64_fetch_##op##name(s64 i, atomic64_t *v)			\
 {									\
 	s64 result, val;						\
 	unsigned long tmp;						\
 									\
 	asm volatile("// atomic64_fetch_" #op #name "\n"		\
-	__LL_SC_FALLBACK(						\
-"	prfm	pstl1strm, %3\n"					\
-"1:	ld" #acq "xr	%0, %3\n"					\
-"	" #asm_op "	%1, %0, %4\n"					\
-"	st" #rel "xr	%w2, %1, %3\n"					\
-"	cbnz	%w2, 1b\n"						\
-"	" #mb )								\
+	"	prfm	pstl1strm, %3\n"				\
+	"1:	ld" #acq "xr	%0, %3\n"				\
+	"	" #asm_op "	%1, %0, %4\n"				\
+	"	st" #rel "xr	%w2, %1, %3\n"				\
+	"	cbnz	%w2, 1b\n"					\
+	"	" #mb							\
 	: "=&r" (result), "=&r" (val), "=&r" (tmp), "+Q" (v->counter)	\
 	: __stringify(constraint) "r" (i)				\
 	: cl);								\
@@ -240,15 +221,14 @@
 	unsigned long tmp;
 
 	asm volatile("// atomic64_dec_if_positive\n"
-	__LL_SC_FALLBACK(
-"	prfm	pstl1strm, %2\n"
-"1:	ldxr	%0, %2\n"
-"	subs	%0, %0, #1\n"
-"	b.lt	2f\n"
-"	stlxr	%w1, %0, %2\n"
-"	cbnz	%w1, 1b\n"
-"	dmb	ish\n"
-"2:")
+	"	prfm	pstl1strm, %2\n"
+	"1:	ldxr	%0, %2\n"
+	"	subs	%0, %0, #1\n"
+	"	b.lt	2f\n"
+	"	stlxr	%w1, %0, %2\n"
+	"	cbnz	%w1, 1b\n"
+	"	dmb	ish\n"
+	"2:"
 	: "=&r" (result), "=&r" (tmp), "+Q" (v->counter)
 	:
 	: "cc", "memory");
@@ -274,7 +254,6 @@
 		old = (u##sz)old;					\
 									\
 	asm volatile(							\
-	__LL_SC_FALLBACK(						\
 	"	prfm	pstl1strm, %[v]\n"				\
 	"1:	ld" #acq "xr" #sfx "\t%" #w "[oldval], %[v]\n"		\
 	"	eor	%" #w "[tmp], %" #w "[oldval], %" #w "[old]\n"	\
@@ -282,7 +261,7 @@
 	"	st" #rel "xr" #sfx "\t%w[tmp], %" #w "[new], %[v]\n"	\
 	"	cbnz	%w[tmp], 1b\n"					\
 	"	" #mb "\n"						\
-	"2:")								\
+	"2:"								\
 	: [tmp] "=&r" (tmp), [oldval] "=&r" (oldval),			\
 	  [v] "+Q" (*(u##sz *)ptr)					\
 	: [old] __stringify(constraint) "r" (old), [new] "r" (new)	\
@@ -326,7 +305,6 @@
 	unsigned long tmp, ret;						\
 									\
 	asm volatile("// __cmpxchg_double" #name "\n"			\
-	__LL_SC_FALLBACK(						\
 	"	prfm	pstl1strm, %2\n"				\
 	"1:	ldxp	%0, %1, %2\n"					\
 	"	eor	%0, %0, %3\n"					\
@@ -336,8 +314,8 @@
 	"	st" #rel "xp	%w0, %5, %6, %2\n"			\
 	"	cbnz	%w0, 1b\n"					\
 	"	" #mb "\n"						\
-	"2:")								\
-	: "=&r" (tmp), "=&r" (ret), "+Q" (*(unsigned long *)ptr)	\
+	"2:"								\
+	: "=&r" (tmp), "=&r" (ret), "+Q" (*(__uint128_t *)ptr)		\
 	: "r" (old1), "r" (old2), "r" (new1), "r" (new2)		\
 	: cl);								\
 									\
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/atomic_lse.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/atomic_lse.h
@@ -11,10 +11,11 @@
 #define __ASM_ATOMIC_LSE_H
 
 #define ATOMIC_OP(op, asm_op)						\
-static inline void __lse_atomic_##op(int i, atomic_t *v)			\
+static inline void __lse_atomic_##op(int i, atomic_t *v)		\
 {									\
 	asm volatile(							\
-"	" #asm_op "	%w[i], %[v]\n"					\
+	__LSE_PREAMBLE							\
+	"	" #asm_op "	%w[i], %[v]\n"				\
 	: [i] "+r" (i), [v] "+Q" (v->counter)				\
 	: "r" (v));							\
 }
@@ -30,7 +31,8 @@
 static inline int __lse_atomic_fetch_##op##name(int i, atomic_t *v)	\
 {									\
 	asm volatile(							\
-"	" #asm_op #mb "	%w[i], %w[i], %[v]"				\
+	__LSE_PREAMBLE							\
+	"	" #asm_op #mb "	%w[i], %w[i], %[v]"			\
 	: [i] "+r" (i), [v] "+Q" (v->counter)				\
 	: "r" (v)							\
 	: cl);								\
@@ -58,6 +60,7 @@
 	u32 tmp;							\
 									\
 	asm volatile(							\
+	__LSE_PREAMBLE							\
 	"	ldadd" #mb "	%w[i], %w[tmp], %[v]\n"			\
 	"	add	%w[i], %w[i], %w[tmp]"				\
 	: [i] "+r" (i), [v] "+Q" (v->counter), [tmp] "=&r" (tmp)	\
@@ -77,6 +80,7 @@
 static inline void __lse_atomic_and(int i, atomic_t *v)
 {
 	asm volatile(
+	__LSE_PREAMBLE
 	"	mvn	%w[i], %w[i]\n"
 	"	stclr	%w[i], %[v]"
 	: [i] "+&r" (i), [v] "+Q" (v->counter)
@@ -87,6 +91,7 @@
 static inline int __lse_atomic_fetch_and##name(int i, atomic_t *v)	\
 {									\
 	asm volatile(							\
+	__LSE_PREAMBLE							\
 	"	mvn	%w[i], %w[i]\n"					\
 	"	ldclr" #mb "	%w[i], %w[i], %[v]"			\
 	: [i] "+&r" (i), [v] "+Q" (v->counter)				\
@@ -106,6 +111,7 @@
 static inline void __lse_atomic_sub(int i, atomic_t *v)
 {
 	asm volatile(
+	__LSE_PREAMBLE
 	"	neg	%w[i], %w[i]\n"
 	"	stadd	%w[i], %[v]"
 	: [i] "+&r" (i), [v] "+Q" (v->counter)
@@ -118,12 +124,13 @@
 	u32 tmp;							\
 									\
 	asm volatile(							\
+	__LSE_PREAMBLE							\
 	"	neg	%w[i], %w[i]\n"					\
 	"	ldadd" #mb "	%w[i], %w[tmp], %[v]\n"			\
 	"	add	%w[i], %w[i], %w[tmp]"				\
 	: [i] "+&r" (i), [v] "+Q" (v->counter), [tmp] "=&r" (tmp)	\
 	: "r" (v)							\
-	: cl);							\
+	: cl);								\
 									\
 	return i;							\
 }
@@ -139,6 +146,7 @@
 static inline int __lse_atomic_fetch_sub##name(int i, atomic_t *v)	\
 {									\
 	asm volatile(							\
+	__LSE_PREAMBLE							\
 	"	neg	%w[i], %w[i]\n"					\
 	"	ldadd" #mb "	%w[i], %w[i], %[v]"			\
 	: [i] "+&r" (i), [v] "+Q" (v->counter)				\
@@ -159,7 +167,8 @@
 static inline void __lse_atomic64_##op(s64 i, atomic64_t *v)		\
 {									\
 	asm volatile(							\
-"	" #asm_op "	%[i], %[v]\n"					\
+	__LSE_PREAMBLE							\
+	"	" #asm_op "	%[i], %[v]\n"				\
 	: [i] "+r" (i), [v] "+Q" (v->counter)				\
 	: "r" (v));							\
 }
@@ -175,7 +184,8 @@
 static inline long __lse_atomic64_fetch_##op##name(s64 i, atomic64_t *v)\
 {									\
 	asm volatile(							\
-"	" #asm_op #mb "	%[i], %[i], %[v]"				\
+	__LSE_PREAMBLE							\
+	"	" #asm_op #mb "	%[i], %[i], %[v]"			\
 	: [i] "+r" (i), [v] "+Q" (v->counter)				\
 	: "r" (v)							\
 	: cl);								\
@@ -203,6 +213,7 @@
 	unsigned long tmp;						\
 									\
 	asm volatile(							\
+	__LSE_PREAMBLE							\
 	"	ldadd" #mb "	%[i], %x[tmp], %[v]\n"			\
 	"	add	%[i], %[i], %x[tmp]"				\
 	: [i] "+r" (i), [v] "+Q" (v->counter), [tmp] "=&r" (tmp)	\
@@ -222,6 +233,7 @@
 static inline void __lse_atomic64_and(s64 i, atomic64_t *v)
 {
 	asm volatile(
+	__LSE_PREAMBLE
 	"	mvn	%[i], %[i]\n"
 	"	stclr	%[i], %[v]"
 	: [i] "+&r" (i), [v] "+Q" (v->counter)
@@ -232,6 +244,7 @@
 static inline long __lse_atomic64_fetch_and##name(s64 i, atomic64_t *v)	\
 {									\
 	asm volatile(							\
+	__LSE_PREAMBLE							\
 	"	mvn	%[i], %[i]\n"					\
 	"	ldclr" #mb "	%[i], %[i], %[v]"			\
 	: [i] "+&r" (i), [v] "+Q" (v->counter)				\
@@ -251,6 +264,7 @@
 static inline void __lse_atomic64_sub(s64 i, atomic64_t *v)
 {
 	asm volatile(
+	__LSE_PREAMBLE
 	"	neg	%[i], %[i]\n"
 	"	stadd	%[i], %[v]"
 	: [i] "+&r" (i), [v] "+Q" (v->counter)
@@ -258,11 +272,12 @@
 }
 
 #define ATOMIC64_OP_SUB_RETURN(name, mb, cl...)				\
-static inline long __lse_atomic64_sub_return##name(s64 i, atomic64_t *v)	\
+static inline long __lse_atomic64_sub_return##name(s64 i, atomic64_t *v)\
 {									\
 	unsigned long tmp;						\
 									\
 	asm volatile(							\
+	__LSE_PREAMBLE							\
 	"	neg	%[i], %[i]\n"					\
 	"	ldadd" #mb "	%[i], %x[tmp], %[v]\n"			\
 	"	add	%[i], %[i], %x[tmp]"				\
@@ -284,6 +299,7 @@
 static inline long __lse_atomic64_fetch_sub##name(s64 i, atomic64_t *v)	\
 {									\
 	asm volatile(							\
+	__LSE_PREAMBLE							\
 	"	neg	%[i], %[i]\n"					\
 	"	ldadd" #mb "	%[i], %[i], %[v]"			\
 	: [i] "+&r" (i), [v] "+Q" (v->counter)				\
@@ -305,6 +321,7 @@
 	unsigned long tmp;
 
 	asm volatile(
+	__LSE_PREAMBLE
 	"1:	ldr	%x[tmp], %[v]\n"
 	"	subs	%[ret], %x[tmp], #1\n"
 	"	b.lt	2f\n"
@@ -332,6 +349,7 @@
 	unsigned long tmp;						\
 									\
 	asm volatile(							\
+	__LSE_PREAMBLE							\
 	"	mov	%" #w "[tmp], %" #w "[old]\n"			\
 	"	cas" #mb #sfx "\t%" #w "[tmp], %" #w "[new], %[v]\n"	\
 	"	mov	%" #w "[ret], %" #w "[tmp]"			\
@@ -379,12 +397,13 @@
 	register unsigned long x4 asm ("x4") = (unsigned long)ptr;	\
 									\
 	asm volatile(							\
+	__LSE_PREAMBLE							\
 	"	casp" #mb "\t%[old1], %[old2], %[new1], %[new2], %[v]\n"\
 	"	eor	%[old1], %[old1], %[oldval1]\n"			\
 	"	eor	%[old2], %[old2], %[oldval2]\n"			\
 	"	orr	%[old1], %[old1], %[old2]"			\
 	: [old1] "+&r" (x0), [old2] "+&r" (x1),				\
-	  [v] "+Q" (*(unsigned long *)ptr)				\
+	  [v] "+Q" (*(__uint128_t *)ptr)				\
 	: [new1] "r" (x2), [new2] "r" (x3), [ptr] "r" (x4),		\
 	  [oldval1] "r" (oldval1), [oldval2] "r" (oldval2)		\
 	: cl);								\
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/barrier.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/barrier.h
@@ -57,6 +57,25 @@
 	return mask;
 }
 
+/*
+ * Ensure that reads of the counter are treated the same as memory reads
+ * for the purposes of ordering by subsequent memory barriers.
+ *
+ * This insanity brought to you by speculative system register reads,
+ * out-of-order memory accesses, sequence locks and Thomas Gleixner.
+ *
+ * http://lists.infradead.org/pipermail/linux-arm-kernel/2019-February/631195.html
+ */
+#define arch_counter_enforce_ordering(val) do {				\
+	u64 tmp, _val = (val);						\
+									\
+	asm volatile(							\
+	"	eor	%0, %1, %1\n"					\
+	"	add	%0, sp, %0\n"					\
+	"	ldr	xzr, [%0]"					\
+	: "=r" (tmp) : "r" (_val));					\
+} while (0)
+
 #define __smp_mb()	dmb(ish)
 #define __smp_rmb()	dmb(ishld)
 #define __smp_wmb()	dmb(ishst)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/brk-imm.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/brk-imm.h
@@ -10,6 +10,7 @@
  * #imm16 values used for BRK instruction generation
  * 0x004: for installing kprobes
  * 0x005: for installing uprobes
+ * 0x006: for kprobe software single-step
  * Allowed values for kgdb are 0x400 - 0x7ff
  * 0x100: for triggering a fault on purpose (reserved)
  * 0x400: for dynamic BRK instruction
@@ -19,6 +20,7 @@
  */
 #define KPROBES_BRK_IMM			0x004
 #define UPROBES_BRK_IMM			0x005
+#define KPROBES_BRK_SS_IMM		0x006
 #define FAULT_BRK_IMM			0x100
 #define KGDB_DYN_DBG_BRK_IMM		0x400
 #define KGDB_COMPILED_DBG_BRK_IMM	0x401
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/cache.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/cache.h
@@ -11,6 +11,7 @@
 #define CTR_L1IP_MASK		3
 #define CTR_DMINLINE_SHIFT	16
 #define CTR_IMINLINE_SHIFT	0
+#define CTR_IMINLINE_MASK	0xf
 #define CTR_ERG_SHIFT		20
 #define CTR_CWG_SHIFT		24
 #define CTR_CWG_MASK		15
@@ -18,7 +19,7 @@
 #define CTR_DIC_SHIFT		29
 
 #define CTR_CACHE_MINLINE_MASK	\
-	(0xf << CTR_DMINLINE_SHIFT | 0xf << CTR_IMINLINE_SHIFT)
+	(0xf << CTR_DMINLINE_SHIFT | CTR_IMINLINE_MASK << CTR_IMINLINE_SHIFT)
 
 #define CTR_L1IP(ctr)		(((ctr) >> CTR_L1IP_SHIFT) & CTR_L1IP_MASK)
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/cacheflush.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/cacheflush.h
@@ -79,7 +79,7 @@
 	 * IPI all online CPUs so that they undergo a context synchronization
 	 * event and are forced to refetch the new instructions.
 	 */
-#ifdef CONFIG_KGDB
+
 	/*
 	 * KGDB performs cache maintenance with interrupts disabled, so we
 	 * will deadlock trying to IPI the secondary CPUs. In theory, we can
@@ -89,9 +89,9 @@
 	 * the patching operation, so we don't need extra IPIs here anyway.
 	 * In which case, add a KGDB-specific bodge and return early.
 	 */
-	if (kgdb_connected && irqs_disabled())
+	if (in_dbg_master())
 		return;
-#endif
+
 	kick_all_cpus_sync();
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/checksum.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/checksum.h
@@ -19,16 +19,17 @@
 {
 	__uint128_t tmp;
 	u64 sum;
+	int n = ihl; /* we want it signed */
 
 	tmp = *(const __uint128_t *)iph;
 	iph += 16;
-	ihl -= 4;
+	n -= 4;
 	tmp += ((tmp >> 64) | (tmp << 64));
 	sum = tmp >> 64;
 	do {
 		sum += *(const u32 *)iph;
 		iph += 4;
-	} while (--ihl);
+	} while (--n > 0);
 
 	sum += ((sum >> 32) | (sum << 32));
 	return csum_fold((__force u32)(sum >> 32));
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/clocksource.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/clocksource.h
@@ -2,8 +2,11 @@
 #ifndef _ASM_CLOCKSOURCE_H
 #define _ASM_CLOCKSOURCE_H
 
+#include <asm/vdso/clocksource.h>
+
 struct arch_clocksource_data {
-	bool vdso_direct;	/* Usable for direct VDSO access? */
+	/* Usable for direct VDSO access? */
+	enum vdso_arch_clockmode clock_mode;
 };
 
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/compat.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/compat.h
@@ -4,6 +4,9 @@
  */
 #ifndef __ASM_COMPAT_H
 #define __ASM_COMPAT_H
+
+#include <asm-generic/compat.h>
+
 #ifdef CONFIG_COMPAT
 
 /*
@@ -13,8 +16,6 @@
 #include <linux/sched.h>
 #include <linux/sched/task_stack.h>
 
-#include <asm-generic/compat.h>
-
 #define COMPAT_USER_HZ		100
 #ifdef __AARCH64EB__
 #define COMPAT_UTS_MACHINE	"armv8b\0\0"
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/cpu.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/cpu.h
@@ -25,6 +25,7 @@
 	u64		reg_id_aa64dfr1;
 	u64		reg_id_aa64isar0;
 	u64		reg_id_aa64isar1;
+	u64		reg_id_aa64isar2;
 	u64		reg_id_aa64mmfr0;
 	u64		reg_id_aa64mmfr1;
 	u64		reg_id_aa64mmfr2;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/cpucaps.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/cpucaps.h
@@ -54,7 +54,11 @@
 #define ARM64_WORKAROUND_1463225		44
 #define ARM64_WORKAROUND_CAVIUM_TX2_219_TVM	45
 #define ARM64_WORKAROUND_CAVIUM_TX2_219_PRFM	46
+#define ARM64_WORKAROUND_1542419		47
+#define ARM64_SPECTRE_BHB			48
+#define ARM64_WORKAROUND_1742098		49
+#define ARM64_WORKAROUND_SPECULATIVE_SSBS	50
 
-#define ARM64_NCAPS				47
+#define ARM64_NCAPS				51
 
 #endif /* __ASM_CPUCAPS_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/cpufeature.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/cpufeature.h
@@ -262,6 +262,8 @@
 /*
  * CPU feature detected at boot time based on feature of one or more CPUs.
  * All possible conflicts for a late CPU are ignored.
+ * NOTE: this means that a late CPU with the feature will *not* cause the
+ * capability to be advertised by cpus_have_*cap()!
  */
 #define ARM64_CPUCAP_WEAK_LOCAL_CPU_FEATURE		\
 	(ARM64_CPUCAP_SCOPE_LOCAL_CPU		|	\
@@ -447,6 +449,29 @@
 	return cpuid_feature_extract_unsigned_field_width(features, field, 4);
 }
 
+/*
+ * Fields that identify the version of the Performance Monitors Extension do
+ * not follow the standard ID scheme. See ARM DDI 0487E.a page D13-2825,
+ * "Alternative ID scheme used for the Performance Monitors Extension version".
+ */
+static inline u64 __attribute_const__
+cpuid_feature_cap_perfmon_field(u64 features, int field, u64 cap)
+{
+	u64 val = cpuid_feature_extract_unsigned_field(features, field);
+	u64 mask = GENMASK_ULL(field + 3, field);
+
+	/* Treat IMPLEMENTATION DEFINED functionality as unimplemented */
+	if (val == 0xf)
+		val = 0;
+
+	if (val > cap) {
+		features &= ~mask;
+		features |= (cap << field) & mask;
+	}
+
+	return features;
+}
+
 static inline u64 arm64_ftr_mask(const struct arm64_ftr_bits *ftrp)
 {
 	return (u64)GENMASK(ftrp->shift + ftrp->width - 1, ftrp->shift);
@@ -506,6 +531,34 @@
 	return id_aa64mmfr0_mixed_endian_el0(read_cpuid(ID_AA64MMFR0_EL1));
 }
 
+static inline bool supports_csv2p3(int scope)
+{
+	u64 pfr0;
+	u8 csv2_val;
+
+	if (scope == SCOPE_LOCAL_CPU)
+		pfr0 = read_sysreg_s(SYS_ID_AA64PFR0_EL1);
+	else
+		pfr0 = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1);
+
+	csv2_val = cpuid_feature_extract_unsigned_field(pfr0,
+							ID_AA64PFR0_CSV2_SHIFT);
+	return csv2_val == 3;
+}
+
+static inline bool supports_clearbhb(int scope)
+{
+	u64 isar2;
+
+	if (scope == SCOPE_LOCAL_CPU)
+		isar2 = read_sysreg_s(SYS_ID_AA64ISAR2_EL1);
+	else
+		isar2 = read_sanitised_ftr_reg(SYS_ID_AA64ISAR2_EL1);
+
+	return cpuid_feature_extract_unsigned_field(isar2,
+						    ID_AA64ISAR2_CLEARBHB_SHIFT);
+}
+
 static inline bool system_supports_32bit_el0(void)
 {
 	return cpus_have_const_cap(ARM64_HAS_32BIT_EL0);
@@ -601,7 +654,7 @@
 		 cpus_have_const_cap(ARM64_HAS_GENERIC_AUTH_IMP_DEF));
 }
 
-static inline bool system_uses_irq_prio_masking(void)
+static __always_inline bool system_uses_irq_prio_masking(void)
 {
 	return IS_ENABLED(CONFIG_ARM64_PSEUDO_NMI) &&
 	       cpus_have_const_cap(ARM64_HAS_IRQ_PRIO_MASKING);
@@ -637,6 +690,18 @@
 
 void arm64_set_ssbd_mitigation(bool state);
 
+/* Watch out, ordering is important here. */
+enum mitigation_state {
+	SPECTRE_UNAFFECTED,
+	SPECTRE_MITIGATED,
+	SPECTRE_VULNERABLE,
+};
+
+enum mitigation_state arm64_get_spectre_bhb_state(void);
+bool is_spectre_bhb_affected(const struct arm64_cpu_capabilities *entry, int scope);
+u8 spectre_bhb_loop_affected(int scope);
+void spectre_bhb_enable_mitigation(const struct arm64_cpu_capabilities *__unused);
+
 extern int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt);
 
 static inline u32 id_aa64mmfr0_parange_to_phys_shift(int parange)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/cputype.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/cputype.h
@@ -41,7 +41,7 @@
 	(((midr) & MIDR_IMPLEMENTOR_MASK) >> MIDR_IMPLEMENTOR_SHIFT)
 
 #define MIDR_CPU_MODEL(imp, partnum) \
-	(((imp)			<< MIDR_IMPLEMENTOR_SHIFT) | \
+	((_AT(u32, imp)		<< MIDR_IMPLEMENTOR_SHIFT) | \
 	(0xf			<< MIDR_ARCHITECTURE_SHIFT) | \
 	((partnum)		<< MIDR_PARTNUM_SHIFT))
 
@@ -59,6 +59,7 @@
 #define ARM_CPU_IMP_NVIDIA		0x4E
 #define ARM_CPU_IMP_FUJITSU		0x46
 #define ARM_CPU_IMP_HISI		0x48
+#define ARM_CPU_IMP_AMPERE		0xC0
 
 #define ARM_CPU_PART_AEM_V8		0xD0F
 #define ARM_CPU_PART_FOUNDATION		0xD00
@@ -71,6 +72,24 @@
 #define ARM_CPU_PART_CORTEX_A55		0xD05
 #define ARM_CPU_PART_CORTEX_A76		0xD0B
 #define ARM_CPU_PART_NEOVERSE_N1	0xD0C
+#define ARM_CPU_PART_CORTEX_A77		0xD0D
+#define ARM_CPU_PART_NEOVERSE_V1	0xD40
+#define ARM_CPU_PART_CORTEX_A78		0xD41
+#define ARM_CPU_PART_CORTEX_X1		0xD44
+#define ARM_CPU_PART_CORTEX_A710	0xD47
+#define ARM_CPU_PART_CORTEX_A715	0xD4D
+#define ARM_CPU_PART_CORTEX_X2		0xD48
+#define ARM_CPU_PART_NEOVERSE_N2	0xD49
+#define ARM_CPU_PART_CORTEX_A78C	0xD4B
+#define ARM_CPU_PART_CORTEX_X1C		0xD4C
+#define ARM_CPU_PART_CORTEX_X3		0xD4E
+#define ARM_CPU_PART_NEOVERSE_V2	0xD4F
+#define ARM_CPU_PART_CORTEX_A720	0xD81
+#define ARM_CPU_PART_CORTEX_X4		0xD82
+#define ARM_CPU_PART_NEOVERSE_V3	0xD84
+#define ARM_CPU_PART_CORTEX_X925	0xD85
+#define ARM_CPU_PART_CORTEX_A725	0xD87
+#define ARM_CPU_PART_NEOVERSE_N3	0xD8E
 
 #define APM_CPU_PART_POTENZA		0x000
 
@@ -93,6 +112,8 @@
 
 #define HISI_CPU_PART_TSV110		0xD01
 
+#define AMPERE_CPU_PART_AMPERE1		0xAC3
+
 #define MIDR_CORTEX_A53 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53)
 #define MIDR_CORTEX_A57 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57)
 #define MIDR_CORTEX_A72 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A72)
@@ -102,6 +123,24 @@
 #define MIDR_CORTEX_A55 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A55)
 #define MIDR_CORTEX_A76	MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A76)
 #define MIDR_NEOVERSE_N1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N1)
+#define MIDR_CORTEX_A77	MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A77)
+#define MIDR_NEOVERSE_V1	MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V1)
+#define MIDR_CORTEX_A78	MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78)
+#define MIDR_CORTEX_X1	MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1)
+#define MIDR_CORTEX_A710 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A710)
+#define MIDR_CORTEX_A715 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A715)
+#define MIDR_CORTEX_X2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X2)
+#define MIDR_NEOVERSE_N2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N2)
+#define MIDR_CORTEX_A78C	MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78C)
+#define MIDR_CORTEX_X1C	MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1C)
+#define MIDR_CORTEX_X3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X3)
+#define MIDR_NEOVERSE_V2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V2)
+#define MIDR_CORTEX_A720 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A720)
+#define MIDR_CORTEX_X4 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X4)
+#define MIDR_NEOVERSE_V3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_V3)
+#define MIDR_CORTEX_X925 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X925)
+#define MIDR_CORTEX_A725 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A725)
+#define MIDR_NEOVERSE_N3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N3)
 #define MIDR_THUNDERX	MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX)
 #define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX)
 #define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX)
@@ -115,6 +154,7 @@
 #define MIDR_NVIDIA_CARMEL MIDR_CPU_MODEL(ARM_CPU_IMP_NVIDIA, NVIDIA_CPU_PART_CARMEL)
 #define MIDR_FUJITSU_A64FX MIDR_CPU_MODEL(ARM_CPU_IMP_FUJITSU, FUJITSU_CPU_PART_A64FX)
 #define MIDR_HISI_TSV110 MIDR_CPU_MODEL(ARM_CPU_IMP_HISI, HISI_CPU_PART_TSV110)
+#define MIDR_AMPERE1 MIDR_CPU_MODEL(ARM_CPU_IMP_AMPERE, AMPERE_CPU_PART_AMPERE1)
 
 /* Fujitsu Erratum 010001 affects A64FX 1.0 and 1.1, (v0r0 and v1r0) */
 #define MIDR_FUJITSU_ERRATUM_010001		MIDR_FUJITSU_A64FX
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/daifflags.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/daifflags.h
@@ -36,7 +36,7 @@
 	trace_hardirqs_off();
 }
 
-static inline unsigned long local_daif_save(void)
+static inline unsigned long local_daif_save_flags(void)
 {
 	unsigned long flags;
 
@@ -48,6 +48,15 @@
 			flags |= PSR_I_BIT;
 	}
 
+	return flags;
+}
+
+static inline unsigned long local_daif_save(void)
+{
+	unsigned long flags;
+
+	flags = local_daif_save_flags();
+
 	local_daif_mask();
 
 	return flags;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/debug-monitors.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/debug-monitors.h
@@ -53,6 +53,7 @@
 
 /* kprobes BRK opcodes with ESR encoding  */
 #define BRK64_OPCODE_KPROBES	(AARCH64_BREAK_MON | (KPROBES_BRK_IMM << 5))
+#define BRK64_OPCODE_KPROBES_SS	(AARCH64_BREAK_MON | (KPROBES_BRK_SS_IMM << 5))
 /* uprobes BRK opcodes with ESR encoding  */
 #define BRK64_OPCODE_UPROBES	(AARCH64_BREAK_MON | (UPROBES_BRK_IMM << 5))
 
@@ -109,10 +110,13 @@
 
 void user_rewind_single_step(struct task_struct *task);
 void user_fastforward_single_step(struct task_struct *task);
+void user_regs_reset_single_step(struct user_pt_regs *regs,
+				 struct task_struct *task);
 
 void kernel_enable_single_step(struct pt_regs *regs);
 void kernel_disable_single_step(void);
 int kernel_active_single_step(void);
+void kernel_rewind_single_step(struct pt_regs *regs);
 
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
 int reinstall_suspended_bps(struct pt_regs *regs);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/fixmap.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/fixmap.h
@@ -63,9 +63,11 @@
 #endif /* CONFIG_ACPI_APEI_GHES */
 
 #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
+	FIX_ENTRY_TRAMP_TEXT3,
+	FIX_ENTRY_TRAMP_TEXT2,
+	FIX_ENTRY_TRAMP_TEXT1,
 	FIX_ENTRY_TRAMP_DATA,
-	FIX_ENTRY_TRAMP_TEXT,
-#define TRAMP_VALIAS		(__fix_to_virt(FIX_ENTRY_TRAMP_TEXT))
+#define TRAMP_VALIAS		(__fix_to_virt(FIX_ENTRY_TRAMP_TEXT1))
 #endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */
 	__end_of_permanent_fixed_addresses,
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/io.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/io.h
@@ -204,4 +204,8 @@
 
 extern int devmem_is_allowed(unsigned long pfn);
 
+extern bool arch_memremap_can_ram_remap(resource_size_t offset, size_t size,
+					unsigned long flags);
+#define arch_memremap_can_ram_remap arch_memremap_can_ram_remap
+
 #endif	/* __ASM_IO_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/kernel-pgtable.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/kernel-pgtable.h
@@ -65,8 +65,8 @@
 #define EARLY_KASLR	(0)
 #endif
 
-#define EARLY_ENTRIES(vstart, vend, shift) (((vend) >> (shift)) \
-					- ((vstart) >> (shift)) + 1 + EARLY_KASLR)
+#define EARLY_ENTRIES(vstart, vend, shift) \
+	((((vend) - 1) >> (shift)) - ((vstart) >> (shift)) + 1 + EARLY_KASLR)
 
 #define EARLY_PGDS(vstart, vend) (EARLY_ENTRIES(vstart, vend, PGDIR_SHIFT))
 
@@ -89,12 +89,6 @@
 #define INIT_DIR_SIZE (PAGE_SIZE * EARLY_PAGES(KIMAGE_VADDR + TEXT_OFFSET, _end))
 #define IDMAP_DIR_SIZE		(IDMAP_PGTABLE_LEVELS * PAGE_SIZE)
 
-#ifdef CONFIG_ARM64_SW_TTBR0_PAN
-#define RESERVED_TTBR0_SIZE	(PAGE_SIZE)
-#else
-#define RESERVED_TTBR0_SIZE	(0)
-#endif
-
 /* Initial memory map size */
 #if ARM64_SWAPPER_USES_SECTION_MAPS
 #define SWAPPER_BLOCK_SHIFT	SECTION_SHIFT
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/kprobes.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/kprobes.h
@@ -16,7 +16,7 @@
 #include <linux/percpu.h>
 
 #define __ARCH_WANT_KPROBES_INSN_SLOT
-#define MAX_INSN_SIZE			1
+#define MAX_INSN_SIZE			2
 
 #define flush_insn_slot(p)		do { } while (0)
 #define kretprobe_blacklist_size	0
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/kvm_arm.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/kvm_arm.h
@@ -72,11 +72,12 @@
  * IMO:		Override CPSR.I and enable signaling with VI
  * FMO:		Override CPSR.F and enable signaling with VF
  * SWIO:	Turn set/way invalidates into set/way clean+invalidate
+ * PTW:		Take a stage2 fault if a stage1 walk steps in device memory
  */
 #define HCR_GUEST_FLAGS (HCR_TSC | HCR_TSW | HCR_TWE | HCR_TWI | HCR_VM | \
 			 HCR_TVM | HCR_BSU_IS | HCR_FB | HCR_TAC | \
 			 HCR_AMO | HCR_SWIO | HCR_TIDCP | HCR_RW | HCR_TLOR | \
-			 HCR_FMO | HCR_IMO)
+			 HCR_FMO | HCR_IMO | HCR_PTW )
 #define HCR_VIRT_EXCP_MASK (HCR_VSE | HCR_VI | HCR_VF)
 #define HCR_HOST_NVHE_FLAGS (HCR_RW | HCR_API | HCR_APK)
 #define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H)
@@ -275,6 +276,7 @@
 #define CPTR_EL2_DEFAULT	CPTR_EL2_RES1
 
 /* Hyp Debug Configuration Register bits */
+#define MDCR_EL2_TTRF		(1 << 19)
 #define MDCR_EL2_TPMS		(1 << 14)
 #define MDCR_EL2_E2PB_MASK	(UL(0x3))
 #define MDCR_EL2_E2PB_SHIFT	(UL(12))
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/kvm_asm.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/kvm_asm.h
@@ -60,7 +60,7 @@
 extern void __kvm_flush_vm_context(void);
 extern void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa);
 extern void __kvm_tlb_flush_vmid(struct kvm *kvm);
-extern void __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu);
+extern void __kvm_flush_cpu_context(struct kvm_vcpu *vcpu);
 
 extern void __kvm_timer_set_cntvoff(u32 cntvoff_low, u32 cntvoff_high);
 
@@ -88,6 +88,34 @@
 		*__hyp_this_cpu_ptr(sym);				\
 	 })
 
+#define __KVM_EXTABLE(from, to)						\
+	"	.pushsection	__kvm_ex_table, \"a\"\n"		\
+	"	.align		3\n"					\
+	"	.long		(" #from " - .), (" #to " - .)\n"	\
+	"	.popsection\n"
+
+
+#define __kvm_at(at_op, addr)						\
+( { 									\
+	int __kvm_at_err = 0;						\
+	u64 spsr, elr;							\
+	asm volatile(							\
+	"	mrs	%1, spsr_el2\n"					\
+	"	mrs	%2, elr_el2\n"					\
+	"1:	at	"at_op", %3\n"					\
+	"	isb\n"							\
+	"	b	9f\n"						\
+	"2:	msr	spsr_el2, %1\n"					\
+	"	msr	elr_el2, %2\n"					\
+	"	mov	%w0, %4\n"					\
+	"9:\n"								\
+	__KVM_EXTABLE(1b, 2b)						\
+	: "+r" (__kvm_at_err), "=&r" (spsr), "=&r" (elr)		\
+	: "r" (addr), "i" (-EFAULT));					\
+	__kvm_at_err;							\
+} )
+
+
 #else /* __ASSEMBLY__ */
 
 .macro hyp_adr_this_cpu reg, sym, tmp
@@ -113,6 +141,21 @@
 	kern_hyp_va	\vcpu
 .endm
 
+/*
+ * KVM extable for unexpected exceptions.
+ * In the same format _asm_extable, but output to a different section so that
+ * it can be mapped to EL2. The KVM version is not sorted. The caller must
+ * ensure:
+ * x18 has the hypervisor value to allow any Shadow-Call-Stack instrumented
+ * code to write to it, and that SPSR_EL2 and ELR_EL2 are restored by the fixup.
+ */
+.macro	_kvm_extable, from, to
+	.pushsection	__kvm_ex_table, "a"
+	.align		3
+	.long		(\from - .), (\to - .)
+	.popsection
+.endm
+
 #endif
 
 #endif /* __ARM_KVM_ASM_H__ */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/kvm_emulate.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/kvm_emulate.h
@@ -97,12 +97,6 @@
 	vcpu->arch.hcr_el2 &= ~(HCR_API | HCR_APK);
 }
 
-static inline void vcpu_ptrauth_setup_lazy(struct kvm_vcpu *vcpu)
-{
-	if (vcpu_has_ptrauth(vcpu))
-		vcpu_ptrauth_disable(vcpu);
-}
-
 static inline unsigned long vcpu_get_vsesr(struct kvm_vcpu *vcpu)
 {
 	return vcpu->arch.vsesr_el2;
@@ -204,6 +198,38 @@
 		vcpu_gp_regs(vcpu)->spsr[KVM_SPSR_EL1] = v;
 }
 
+/*
+ * The layout of SPSR for an AArch32 state is different when observed from an
+ * AArch64 SPSR_ELx or an AArch32 SPSR_*. This function generates the AArch32
+ * view given an AArch64 view.
+ *
+ * In ARM DDI 0487E.a see:
+ *
+ * - The AArch64 view (SPSR_EL2) in section C5.2.18, page C5-426
+ * - The AArch32 view (SPSR_abt) in section G8.2.126, page G8-6256
+ * - The AArch32 view (SPSR_und) in section G8.2.132, page G8-6280
+ *
+ * Which show the following differences:
+ *
+ * | Bit | AA64 | AA32 | Notes                       |
+ * +-----+------+------+-----------------------------|
+ * | 24  | DIT  | J    | J is RES0 in ARMv8          |
+ * | 21  | SS   | DIT  | SS doesn't exist in AArch32 |
+ *
+ * ... and all other bits are (currently) common.
+ */
+static inline unsigned long host_spsr_to_spsr32(unsigned long spsr)
+{
+	const unsigned long overlap = BIT(24) | BIT(21);
+	unsigned long dit = !!(spsr & PSR_AA32_DIT_BIT);
+
+	spsr &= ~overlap;
+
+	spsr |= dit << 21;
+
+	return spsr;
+}
+
 static inline bool vcpu_mode_priv(const struct kvm_vcpu *vcpu)
 {
 	u32 mode;
@@ -263,12 +289,17 @@
 	return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_SSE);
 }
 
+static inline bool kvm_vcpu_dabt_issf(const struct kvm_vcpu *vcpu)
+{
+	return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_SF);
+}
+
 static inline int kvm_vcpu_dabt_get_rd(const struct kvm_vcpu *vcpu)
 {
 	return (kvm_vcpu_get_hsr(vcpu) & ESR_ELx_SRT_MASK) >> ESR_ELx_SRT_SHIFT;
 }
 
-static inline bool kvm_vcpu_dabt_iss1tw(const struct kvm_vcpu *vcpu)
+static __always_inline bool kvm_vcpu_abt_iss1tw(const struct kvm_vcpu *vcpu)
 {
 	return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_S1PTW);
 }
@@ -276,7 +307,7 @@
 static inline bool kvm_vcpu_dabt_iswrite(const struct kvm_vcpu *vcpu)
 {
 	return !!(kvm_vcpu_get_hsr(vcpu) & ESR_ELx_WNR) ||
-		kvm_vcpu_dabt_iss1tw(vcpu); /* AF/DBM update */
+		kvm_vcpu_abt_iss1tw(vcpu); /* AF/DBM update */
 }
 
 static inline bool kvm_vcpu_dabt_is_cm(const struct kvm_vcpu *vcpu)
@@ -305,6 +336,11 @@
 	return kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_IABT_LOW;
 }
 
+static inline bool kvm_vcpu_trap_is_exec_fault(const struct kvm_vcpu *vcpu)
+{
+	return kvm_vcpu_trap_is_iabt(vcpu) && !kvm_vcpu_abt_iss1tw(vcpu);
+}
+
 static inline u8 kvm_vcpu_trap_get_fault(const struct kvm_vcpu *vcpu)
 {
 	return kvm_vcpu_get_hsr(vcpu) & ESR_ELx_FSC;
@@ -342,6 +378,27 @@
 
 static inline bool kvm_is_write_fault(struct kvm_vcpu *vcpu)
 {
+	if (kvm_vcpu_abt_iss1tw(vcpu)) {
+		/*
+		 * Only a permission fault on a S1PTW should be
+		 * considered as a write. Otherwise, page tables baked
+		 * in a read-only memslot will result in an exception
+		 * being delivered in the guest.
+		 *
+		 * The drawback is that we end-up faulting twice if the
+		 * guest is using any of HW AF/DB: a translation fault
+		 * to map the page containing the PT (read only at
+		 * first), then a permission fault to allow the flags
+		 * to be set.
+		 */
+		switch (kvm_vcpu_trap_get_fault_type(vcpu)) {
+		case ESR_ELx_FSC_PERM:
+			return true;
+		default:
+			return false;
+		}
+	}
+
 	if (kvm_vcpu_trap_is_iabt(vcpu))
 		return false;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/kvm_host.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/kvm_host.h
@@ -182,6 +182,7 @@
 #define c2_TTBR1	(TTBR1_EL1 * 2)	/* Translation Table Base Register 1 */
 #define c2_TTBR1_high	(c2_TTBR1 + 1)	/* TTBR1 top 32 bits */
 #define c2_TTBCR	(TCR_EL1 * 2)	/* Translation Table Base Control R. */
+#define c2_TTBCR2	(c2_TTBCR + 1)	/* Translation Table Base Control R. 2 */
 #define c3_DACR		(DACR32_EL2 * 2)/* Domain Access Control Register */
 #define c5_DFSR		(ESR_EL1 * 2)	/* Data Fault Status Register */
 #define c5_IFSR		(IFSR32_EL2 * 2)/* Instruction Fault Status Register */
@@ -209,6 +210,7 @@
 #define cp14_DBGWCR0	(DBGWCR0_EL1 * 2)
 #define cp14_DBGWVR0	(DBGWVR0_EL1 * 2)
 #define cp14_DBGDCCINT	(MDCCINT_EL1 * 2)
+#define cp14_DBGVCR	(DBGVCR32_EL2 * 2)
 
 #define NR_COPRO_REGS	(NR_SYS_REGS * 2)
 
@@ -392,8 +394,10 @@
  * CP14 and CP15 live in the same array, as they are backed by the
  * same system registers.
  */
-#define vcpu_cp14(v,r)		((v)->arch.ctxt.copro[(r)])
-#define vcpu_cp15(v,r)		((v)->arch.ctxt.copro[(r)])
+#define CPx_BIAS		IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)
+
+#define vcpu_cp14(v,r)		((v)->arch.ctxt.copro[(r) ^ CPx_BIAS])
+#define vcpu_cp15(v,r)		((v)->arch.ctxt.copro[(r) ^ CPx_BIAS])
 
 struct kvm_vm_stat {
 	ulong remote_tlb_flush;
@@ -425,7 +429,7 @@
 
 #define KVM_ARCH_WANT_MMU_NOTIFIER
 int kvm_unmap_hva_range(struct kvm *kvm,
-			unsigned long start, unsigned long end);
+			unsigned long start, unsigned long end, unsigned flags);
 int kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte);
 int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end);
 int kvm_test_age_hva(struct kvm *kvm, unsigned long hva);
@@ -548,6 +552,7 @@
 static inline void kvm_arch_vcpu_block_finish(struct kvm_vcpu *vcpu) {}
 
 void kvm_arm_init_debug(void);
+void kvm_arm_vcpu_init_debug(struct kvm_vcpu *vcpu);
 void kvm_arm_setup_debug(struct kvm_vcpu *vcpu);
 void kvm_arm_clear_debug(struct kvm_vcpu *vcpu);
 void kvm_arm_reset_debug_ptr(struct kvm_vcpu *vcpu);
@@ -677,4 +682,6 @@
 #define kvm_arm_vcpu_sve_finalized(vcpu) \
 	((vcpu)->arch.flags & KVM_ARM64_VCPU_SVE_FINALIZED)
 
+#define kvm_arm_vcpu_loaded(vcpu)	((vcpu)->arch.sysregs_loaded_on_cpu)
+
 #endif /* __ARM64_KVM_HOST_H__ */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/kvm_hyp.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/kvm_hyp.h
@@ -71,6 +71,9 @@
 
 void __debug_switch_to_guest(struct kvm_vcpu *vcpu);
 void __debug_switch_to_host(struct kvm_vcpu *vcpu);
+void __debug_save_host_buffers_nvhe(struct kvm_vcpu *vcpu);
+void __debug_restore_host_buffers_nvhe(struct kvm_vcpu *vcpu);
+
 
 void __fpsimd_save_state(struct user_fpsimd_state *fp_regs);
 void __fpsimd_restore_state(struct user_fpsimd_state *fp_regs);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/kvm_mmio.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/kvm_mmio.h
@@ -10,13 +10,11 @@
 #include <linux/kvm_host.h>
 #include <asm/kvm_arm.h>
 
-/*
- * This is annoying. The mmio code requires this, even if we don't
- * need any decoding. To be fixed.
- */
 struct kvm_decode {
 	unsigned long rt;
 	bool sign_extend;
+	/* Witdth of the register accessed by the faulting instruction is 64-bits */
+	bool sixty_four;
 };
 
 void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/kvm_mmu.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/kvm_mmu.h
@@ -478,7 +478,9 @@
 	void *vect = kern_hyp_va(kvm_ksym_ref(__kvm_hyp_vector));
 	int slot = -1;
 
-	if (cpus_have_const_cap(ARM64_HARDEN_BRANCH_PREDICTOR) && data->fn) {
+	if ((cpus_have_const_cap(ARM64_HARDEN_BRANCH_PREDICTOR) ||
+	     cpus_have_const_cap(ARM64_SPECTRE_BHB)) &&
+	    data && data->template_start) {
 		vect = kern_hyp_va(kvm_ksym_ref(__bp_harden_hyp_vecs_start));
 		slot = data->hyp_vectors_slot;
 	}
@@ -507,7 +509,8 @@
 	 * !HBP +  HEL2 -> allocate one vector slot and use exec mapping
 	 *  HBP +  HEL2 -> use hardened vertors and use exec mapping
 	 */
-	if (cpus_have_const_cap(ARM64_HARDEN_BRANCH_PREDICTOR)) {
+	if (cpus_have_const_cap(ARM64_HARDEN_BRANCH_PREDICTOR) ||
+	    cpus_have_const_cap(ARM64_SPECTRE_BHB)) {
 		__kvm_bp_vect_base = kvm_ksym_ref(__bp_harden_hyp_vecs_start);
 		__kvm_bp_vect_base = kern_hyp_va(__kvm_bp_vect_base);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/linkage.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/linkage.h
@@ -4,4 +4,20 @@
 #define __ALIGN		.align 2
 #define __ALIGN_STR	".align 2"
 
+/*
+ * Annotate a function as position independent, i.e., safe to be called before
+ * the kernel virtual mapping is activated.
+ */
+#define SYM_FUNC_START_PI(x)			\
+		SYM_FUNC_START_ALIAS(__pi_##x);	\
+		SYM_FUNC_START(x)
+
+#define SYM_FUNC_START_WEAK_PI(x)		\
+		SYM_FUNC_START_ALIAS(__pi_##x);	\
+		SYM_FUNC_START_WEAK(x)
+
+#define SYM_FUNC_END_PI(x)			\
+		SYM_FUNC_END(x);		\
+		SYM_FUNC_END_ALIAS(__pi_##x)
+
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/lse.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/lse.h
@@ -6,6 +6,8 @@
 
 #if defined(CONFIG_AS_LSE) && defined(CONFIG_ARM64_LSE_ATOMICS)
 
+#define __LSE_PREAMBLE	".arch_extension lse\n"
+
 #include <linux/compiler_types.h>
 #include <linux/export.h>
 #include <linux/jump_label.h>
@@ -14,8 +16,6 @@
 #include <asm/atomic_lse.h>
 #include <asm/cpucaps.h>
 
-__asm__(".arch_extension	lse");
-
 extern struct static_key_false cpu_hwcap_keys[ARM64_NCAPS];
 extern struct static_key_false arm64_const_caps_ready;
 
@@ -34,7 +34,7 @@
 
 /* In-line patching at runtime */
 #define ARM64_LSE_ATOMIC_INSN(llsc, lse)				\
-	ALTERNATIVE(llsc, lse, ARM64_HAS_LSE_ATOMICS)
+	ALTERNATIVE(llsc, __LSE_PREAMBLE lse, ARM64_HAS_LSE_ATOMICS)
 
 #else	/* CONFIG_AS_LSE && CONFIG_ARM64_LSE_ATOMICS */
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/memory.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/memory.h
@@ -178,7 +178,6 @@
 #include <linux/bitops.h>
 #include <linux/mmdebug.h>
 
-extern s64			physvirt_offset;
 extern s64			memstart_addr;
 /* PHYS_OFFSET - the physical address of the start of memory. */
 #define PHYS_OFFSET		({ VM_BUG_ON(memstart_addr & 1); memstart_addr; })
@@ -219,7 +218,7 @@
 	((__force __typeof__(addr))sign_extend64((__force u64)(addr), 55))
 
 #define untagged_addr(addr)	({					\
-	u64 __addr = (__force u64)addr;					\
+	u64 __addr = (__force u64)(addr);					\
 	__addr &= __untagged_addr(__addr);				\
 	(__force __typeof__(addr))__addr;				\
 })
@@ -248,13 +247,13 @@
 
 
 /*
- * The linear kernel range starts at the bottom of the virtual address
- * space. Testing the top bit for the start of the region is a
- * sufficient check and avoids having to worry about the tag.
+ * Check whether an arbitrary address is within the linear map, which
+ * lives in the [PAGE_OFFSET, PAGE_END) interval at the bottom of the
+ * kernel's TTBR1 address range.
  */
-#define __is_lm_address(addr)	(!(((u64)addr) & BIT(vabits_actual - 1)))
+#define __is_lm_address(addr)	(((u64)(addr) ^ PAGE_OFFSET) < (PAGE_END - PAGE_OFFSET))
 
-#define __lm_to_phys(addr)	(((addr) + physvirt_offset))
+#define __lm_to_phys(addr)	(((addr) & ~PAGE_OFFSET) + PHYS_OFFSET)
 #define __kimg_to_phys(addr)	((addr) - kimage_voffset)
 
 #define __virt_to_phys_nodebug(x) ({					\
@@ -272,7 +271,7 @@
 #define __phys_addr_symbol(x)	__pa_symbol_nodebug(x)
 #endif /* CONFIG_DEBUG_VIRTUAL */
 
-#define __phys_to_virt(x)	((unsigned long)((x) - physvirt_offset))
+#define __phys_to_virt(x)	((unsigned long)((x) - PHYS_OFFSET) | PAGE_OFFSET)
 #define __phys_to_kimg(x)	((unsigned long)((x) + kimage_voffset))
 
 /*
@@ -316,6 +315,11 @@
 #define ARCH_PFN_OFFSET		((unsigned long)PHYS_PFN_OFFSET)
 
 #if !defined(CONFIG_SPARSEMEM_VMEMMAP) || defined(CONFIG_DEBUG_VIRTUAL)
+#define page_to_virt(x)	({						\
+	__typeof__(x) __page = x;					\
+	void *__addr = __va(page_to_phys(__page));			\
+	(void *)__tag_set((const void *)__addr, page_kasan_tag(__page));\
+})
 #define virt_to_page(x)		pfn_to_page(virt_to_pfn(x))
 #else
 #define page_to_virt(x)	({						\
@@ -333,7 +337,7 @@
 #endif /* !CONFIG_SPARSEMEM_VMEMMAP || CONFIG_DEBUG_VIRTUAL */
 
 #define virt_addr_valid(addr)	({					\
-	__typeof__(addr) __addr = addr;					\
+	__typeof__(addr) __addr = __tag_reset(addr);			\
 	__is_lm_address(__addr) && pfn_valid(virt_to_pfn(__addr));	\
 })
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/mmu.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/mmu.h
@@ -29,7 +29,7 @@
  */
 #define ASID(mm)	((mm)->context.id.counter & 0xffff)
 
-static inline bool arm64_kernel_unmapped_at_el0(void)
+static __always_inline bool arm64_kernel_unmapped_at_el0(void)
 {
 	return IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0) &&
 	       cpus_have_const_cap(ARM64_UNMAP_KERNEL_AT_EL0);
@@ -82,6 +82,12 @@
 struct bp_hardening_data {
 	int			hyp_vectors_slot;
 	bp_hardening_cb_t	fn;
+
+	/*
+	 * template_start is only used by the BHB mitigation to identify the
+	 * hyp_vectors_slot sequence.
+	 */
+	const char *template_start;
 };
 
 #if (defined(CONFIG_HARDEN_BRANCH_PREDICTOR) ||	\
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/mmu_context.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/mmu_context.h
@@ -36,11 +36,11 @@
 }
 
 /*
- * Set TTBR0 to empty_zero_page. No translations will be possible via TTBR0.
+ * Set TTBR0 to reserved_pg_dir. No translations will be possible via TTBR0.
  */
 static inline void cpu_set_reserved_ttbr0(void)
 {
-	unsigned long ttbr = phys_to_ttbr(__pa_symbol(empty_zero_page));
+	unsigned long ttbr = phys_to_ttbr(__pa_symbol(reserved_pg_dir));
 
 	write_sysreg(ttbr, ttbr0_el1);
 	isb();
@@ -63,10 +63,7 @@
 
 static inline bool __cpu_uses_extended_idmap(void)
 {
-	if (IS_ENABLED(CONFIG_ARM64_VA_BITS_52))
-		return false;
-
-	return unlikely(idmap_t0sz != TCR_T0SZ(VA_BITS));
+	return unlikely(idmap_t0sz != TCR_T0SZ(vabits_actual));
 }
 
 /*
@@ -187,9 +184,9 @@
 		return;
 
 	if (mm == &init_mm)
-		ttbr = __pa_symbol(empty_zero_page);
+		ttbr = phys_to_ttbr(__pa_symbol(reserved_pg_dir));
 	else
-		ttbr = virt_to_phys(mm->pgd) | ASID(mm) << 48;
+		ttbr = phys_to_ttbr(virt_to_phys(mm->pgd)) | ASID(mm) << 48;
 
 	WRITE_ONCE(task_thread_info(tsk)->ttbr0, ttbr);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/numa.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/numa.h
@@ -25,6 +25,9 @@
 /* Returns a pointer to the cpumask of CPUs on Node 'node'. */
 static inline const struct cpumask *cpumask_of_node(int node)
 {
+	if (node == NUMA_NO_NODE)
+		return cpu_all_mask;
+
 	return node_to_cpumask_map[node];
 }
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/pgtable-hwdef.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/pgtable-hwdef.h
@@ -215,6 +215,7 @@
 #define TCR_TxSZ(x)		(TCR_T0SZ(x) | TCR_T1SZ(x))
 #define TCR_TxSZ_WIDTH		6
 #define TCR_T0SZ_MASK		(((UL(1) << TCR_TxSZ_WIDTH) - 1) << TCR_T0SZ_OFFSET)
+#define TCR_T1SZ_MASK		(((UL(1) << TCR_TxSZ_WIDTH) - 1) << TCR_T1SZ_OFFSET)
 
 #define TCR_EPD0_SHIFT		7
 #define TCR_EPD0_MASK		(UL(1) << TCR_EPD0_SHIFT)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/pgtable-prot.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/pgtable-prot.h
@@ -54,7 +54,7 @@
 #define PAGE_HYP		__pgprot(_HYP_PAGE_DEFAULT | PTE_HYP | PTE_HYP_XN)
 #define PAGE_HYP_EXEC		__pgprot(_HYP_PAGE_DEFAULT | PTE_HYP | PTE_RDONLY)
 #define PAGE_HYP_RO		__pgprot(_HYP_PAGE_DEFAULT | PTE_HYP | PTE_RDONLY | PTE_HYP_XN)
-#define PAGE_HYP_DEVICE		__pgprot(PROT_DEVICE_nGnRE | PTE_HYP)
+#define PAGE_HYP_DEVICE		__pgprot(_PROT_DEFAULT | PTE_ATTRINDX(MT_DEVICE_nGnRE) | PTE_HYP | PTE_HYP_XN)
 
 #define PAGE_S2_MEMATTR(attr)						\
 	({								\
@@ -85,13 +85,12 @@
 #define PAGE_SHARED_EXEC	__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_WRITE)
 #define PAGE_READONLY		__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_UXN)
 #define PAGE_READONLY_EXEC	__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN)
-#define PAGE_EXECONLY		__pgprot(_PAGE_DEFAULT | PTE_RDONLY | PTE_NG | PTE_PXN)
 
 #define __P000  PAGE_NONE
 #define __P001  PAGE_READONLY
 #define __P010  PAGE_READONLY
 #define __P011  PAGE_READONLY
-#define __P100  PAGE_EXECONLY
+#define __P100  PAGE_READONLY_EXEC
 #define __P101  PAGE_READONLY_EXEC
 #define __P110  PAGE_READONLY_EXEC
 #define __P111  PAGE_READONLY_EXEC
@@ -100,7 +99,7 @@
 #define __S001  PAGE_READONLY
 #define __S010  PAGE_SHARED
 #define __S011  PAGE_SHARED
-#define __S100  PAGE_EXECONLY
+#define __S100  PAGE_READONLY_EXEC
 #define __S101  PAGE_READONLY_EXEC
 #define __S110  PAGE_SHARED_EXEC
 #define __S111  PAGE_SHARED_EXEC
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/pgtable.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/pgtable.h
@@ -23,6 +23,8 @@
 #define VMALLOC_START		(MODULES_END)
 #define VMALLOC_END		(- PUD_SIZE - VMEMMAP_SIZE - SZ_64K)
 
+#define vmemmap			((struct page *)VMEMMAP_START - (memstart_addr >> PAGE_SHIFT))
+
 #define FIRST_USER_ADDRESS	0UL
 
 #ifndef __ASSEMBLY__
@@ -33,8 +35,6 @@
 #include <linux/mm_types.h>
 #include <linux/sched.h>
 
-extern struct page *vmemmap;
-
 extern void __pte_error(const char *file, int line, unsigned long val);
 extern void __pmd_error(const char *file, int line, unsigned long val);
 extern void __pud_error(const char *file, int line, unsigned long val);
@@ -54,9 +54,15 @@
  * page table entry, taking care of 52-bit addresses.
  */
 #ifdef CONFIG_ARM64_PA_BITS_52
-#define __pte_to_phys(pte)	\
-	((pte_val(pte) & PTE_ADDR_LOW) | ((pte_val(pte) & PTE_ADDR_HIGH) << 36))
-#define __phys_to_pte_val(phys)	(((phys) | ((phys) >> 36)) & PTE_ADDR_MASK)
+static inline phys_addr_t __pte_to_phys(pte_t pte)
+{
+	return (pte_val(pte) & PTE_ADDR_LOW) |
+		((pte_val(pte) & PTE_ADDR_HIGH) << 36);
+}
+static inline pteval_t __phys_to_pte_val(phys_addr_t phys)
+{
+	return (phys | (phys >> 36)) & PTE_ADDR_MASK;
+}
 #else
 #define __pte_to_phys(pte)	(pte_val(pte) & PTE_ADDR_MASK)
 #define __phys_to_pte_val(phys)	(phys)
@@ -96,14 +102,8 @@
 #define pte_dirty(pte)		(pte_sw_dirty(pte) || pte_hw_dirty(pte))
 
 #define pte_valid(pte)		(!!(pte_val(pte) & PTE_VALID))
-/*
- * Execute-only user mappings do not have the PTE_USER bit set. All valid
- * kernel mappings have the PTE_UXN bit set.
- */
 #define pte_valid_not_user(pte) \
-	((pte_val(pte) & (PTE_VALID | PTE_USER | PTE_UXN)) == (PTE_VALID | PTE_UXN))
-#define pte_valid_young(pte) \
-	((pte_val(pte) & (PTE_VALID | PTE_AF)) == (PTE_VALID | PTE_AF))
+	((pte_val(pte) & (PTE_VALID | PTE_USER)) == PTE_VALID)
 #define pte_valid_user(pte) \
 	((pte_val(pte) & (PTE_VALID | PTE_USER)) == (PTE_VALID | PTE_USER))
 
@@ -111,14 +111,17 @@
  * Could the pte be present in the TLB? We must check mm_tlb_flush_pending
  * so that we don't erroneously return false for pages that have been
  * remapped as PROT_NONE but are yet to be flushed from the TLB.
+ * Note that we can't make any assumptions based on the state of the access
+ * flag, since ptep_clear_flush_young() elides a DSB when invalidating the
+ * TLB.
  */
 #define pte_accessible(mm, pte)	\
-	(mm_tlb_flush_pending(mm) ? pte_present(pte) : pte_valid_young(pte))
+	(mm_tlb_flush_pending(mm) ? pte_present(pte) : pte_valid(pte))
 
 /*
  * p??_access_permitted() is true for valid user mappings (subject to the
- * write permission check) other than user execute-only which do not have the
- * PTE_USER bit set. PROT_NONE mappings do not have the PTE_VALID bit set.
+ * write permission check). PROT_NONE mappings do not have the PTE_VALID bit
+ * set.
  */
 #define pte_access_permitted(pte, write) \
 	(pte_valid_user(pte) && (!(write) || pte_write(pte)))
@@ -139,13 +142,6 @@
 	return pte;
 }
 
-static inline pte_t pte_wrprotect(pte_t pte)
-{
-	pte = clear_pte_bit(pte, __pgprot(PTE_WRITE));
-	pte = set_pte_bit(pte, __pgprot(PTE_RDONLY));
-	return pte;
-}
-
 static inline pte_t pte_mkwrite(pte_t pte)
 {
 	pte = set_pte_bit(pte, __pgprot(PTE_WRITE));
@@ -171,6 +167,20 @@
 	return pte;
 }
 
+static inline pte_t pte_wrprotect(pte_t pte)
+{
+	/*
+	 * If hardware-dirty (PTE_WRITE/DBM bit set and PTE_RDONLY
+	 * clear), set the PTE_DIRTY bit.
+	 */
+	if (pte_hw_dirty(pte))
+		pte = pte_mkdirty(pte);
+
+	pte = clear_pte_bit(pte, __pgprot(PTE_WRITE));
+	pte = set_pte_bit(pte, __pgprot(PTE_RDONLY));
+	return pte;
+}
+
 static inline pte_t pte_mkold(pte_t pte)
 {
 	return clear_pte_bit(pte, __pgprot(PTE_AF));
@@ -460,7 +470,9 @@
 extern pgd_t init_pg_end[];
 extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 extern pgd_t idmap_pg_dir[PTRS_PER_PGD];
+extern pgd_t idmap_pg_end[];
 extern pgd_t tramp_pg_dir[PTRS_PER_PGD];
+extern pgd_t reserved_pg_dir[PTRS_PER_PGD];
 
 extern void set_swapper_pgd(pgd_t *pgdp, pgd_t pgd);
 
@@ -667,6 +679,12 @@
 	if (pte_hw_dirty(pte))
 		pte = pte_mkdirty(pte);
 	pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask);
+	/*
+	 * If we end up clearing hw dirtiness for a sw-dirty PTE, set hardware
+	 * dirtiness again.
+	 */
+	if (pte_sw_dirty(pte))
+		pte = pte_mkdirty(pte);
 	return pte;
 }
 
@@ -785,12 +803,6 @@
 	pte = READ_ONCE(*ptep);
 	do {
 		old_pte = pte;
-		/*
-		 * If hardware-dirty (PTE_WRITE/DBM bit set and PTE_RDONLY
-		 * clear), set the PTE_DIRTY bit.
-		 */
-		if (pte_hw_dirty(pte))
-			pte = pte_mkdirty(pte);
 		pte = pte_wrprotect(pte);
 		pte_val(pte) = cmpxchg_relaxed(&pte_val(*ptep),
 					       pte_val(old_pte), pte_val(pte));
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/pointer_auth.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/pointer_auth.h
@@ -3,7 +3,6 @@
 #define __ASM_POINTER_AUTH_H
 
 #include <linux/bitops.h>
-#include <linux/random.h>
 
 #include <asm/cpufeature.h>
 #include <asm/memory.h>
@@ -30,6 +29,13 @@
 	struct ptrauth_key apga;
 };
 
+/*
+ * Only include random.h once ptrauth_keys_* structures are defined
+ * to avoid yet another circular include hell (random.h * ends up
+ * including asm/smp.h, which requires ptrauth_keys_kernel).
+ */
+#include <linux/random.h>
+
 static inline void ptrauth_keys_init(struct ptrauth_keys *keys)
 {
 	if (system_supports_address_auth()) {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/processor.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/processor.h
@@ -184,8 +184,9 @@
 
 static inline void start_thread_common(struct pt_regs *regs, unsigned long pc)
 {
+	s32 previous_syscall = regs->syscallno;
 	memset(regs, 0, sizeof(*regs));
-	forget_syscall(regs);
+	regs->syscallno = previous_syscall;
 	regs->pc = pc;
 
 	if (system_uses_irq_prio_masking())
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/ptrace.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/ptrace.h
@@ -62,6 +62,7 @@
 #define PSR_AA32_I_BIT		0x00000080
 #define PSR_AA32_A_BIT		0x00000100
 #define PSR_AA32_E_BIT		0x00000200
+#define PSR_AA32_PAN_BIT	0x00400000
 #define PSR_AA32_SSBS_BIT	0x00800000
 #define PSR_AA32_DIT_BIT	0x01000000
 #define PSR_AA32_Q_BIT		0x08000000
@@ -298,7 +299,17 @@
 
 static inline unsigned long regs_return_value(struct pt_regs *regs)
 {
-	return regs->regs[0];
+	unsigned long val = regs->regs[0];
+
+	/*
+	 * Audit currently uses regs_return_value() instead of
+	 * syscall_get_return_value(). Apply the same sign-extension here until
+	 * audit is updated to use syscall_get_return_value().
+	 */
+	if (compat_user_mode(regs))
+		val = sign_extend64(val, 31);
+
+	return val;
 }
 
 static inline void regs_set_return_value(struct pt_regs *regs, unsigned long rc)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/sections.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/sections.h
@@ -15,8 +15,14 @@
 extern char __idmap_text_start[], __idmap_text_end[];
 extern char __initdata_begin[], __initdata_end[];
 extern char __inittext_begin[], __inittext_end[];
+extern char __exittext_begin[], __exittext_end[];
 extern char __irqentry_text_start[], __irqentry_text_end[];
 extern char __mmuoff_data_start[], __mmuoff_data_end[];
 extern char __entry_tramp_text_start[], __entry_tramp_text_end[];
 
+static inline size_t entry_tramp_text_size(void)
+{
+	return __entry_tramp_text_end - __entry_tramp_text_start;
+}
+
 #endif /* __ASM_SECTIONS_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/smp.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/smp.h
@@ -46,7 +46,12 @@
  * Logical CPU mapping.
  */
 extern u64 __cpu_logical_map[NR_CPUS];
-#define cpu_logical_map(cpu)    __cpu_logical_map[cpu]
+extern u64 cpu_logical_map(int cpu);
+
+static inline void set_cpu_logical_map(int cpu, u64 hwid)
+{
+	__cpu_logical_map[cpu] = hwid;
+}
 
 struct seq_file;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/syscall.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/syscall.h
@@ -29,25 +29,36 @@
 	regs->regs[0] = regs->orig_x0;
 }
 
+static inline long syscall_get_return_value(struct task_struct *task,
+					    struct pt_regs *regs)
+{
+	unsigned long val = regs->regs[0];
+
+	if (is_compat_thread(task_thread_info(task)))
+		val = sign_extend64(val, 31);
+
+	return val;
+}
 
 static inline long syscall_get_error(struct task_struct *task,
 				     struct pt_regs *regs)
 {
-	unsigned long error = regs->regs[0];
-	return IS_ERR_VALUE(error) ? error : 0;
-}
+	unsigned long error = syscall_get_return_value(task, regs);
 
-static inline long syscall_get_return_value(struct task_struct *task,
-					    struct pt_regs *regs)
-{
-	return regs->regs[0];
+	return IS_ERR_VALUE(error) ? error : 0;
 }
 
 static inline void syscall_set_return_value(struct task_struct *task,
 					    struct pt_regs *regs,
 					    int error, long val)
 {
-	regs->regs[0] = (long) error ? error : val;
+	if (error)
+		val = error;
+
+	if (is_compat_thread(task_thread_info(task)))
+		val = lower_32_bits(val);
+
+	regs->regs[0] = val;
 }
 
 #define SYSCALL_MAX_ARGS 6
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/syscall_wrapper.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/syscall_wrapper.h
@@ -8,7 +8,7 @@
 #ifndef __ASM_SYSCALL_WRAPPER_H
 #define __ASM_SYSCALL_WRAPPER_H
 
-struct pt_regs;
+#include <asm/ptrace.h>
 
 #define SC_ARM64_REGS_TO_ARGS(x, ...)				\
 	__MAP(x,__SC_ARGS					\
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/sysreg.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/sysreg.h
@@ -49,7 +49,9 @@
 #ifndef CONFIG_BROKEN_GAS_INST
 
 #ifdef __ASSEMBLY__
-#define __emit_inst(x)			.inst (x)
+// The space separator is omitted so that __emit_inst(x) can be parsed as
+// either an assembler directive or an assembler macro argument.
+#define __emit_inst(x)			.inst(x)
 #else
 #define __emit_inst(x)			".inst " __stringify((x)) "\n\t"
 #endif
@@ -100,8 +102,14 @@
 #define SB_BARRIER_INSN			__SYS_BARRIER_INSN(0, 7, 31)
 
 #define SYS_DC_ISW			sys_insn(1, 0, 7, 6, 2)
+#define SYS_DC_IGSW			sys_insn(1, 0, 7, 6, 4)
+#define SYS_DC_IGDSW			sys_insn(1, 0, 7, 6, 6)
 #define SYS_DC_CSW			sys_insn(1, 0, 7, 10, 2)
+#define SYS_DC_CGSW			sys_insn(1, 0, 7, 10, 4)
+#define SYS_DC_CGDSW			sys_insn(1, 0, 7, 10, 6)
 #define SYS_DC_CISW			sys_insn(1, 0, 7, 14, 2)
+#define SYS_DC_CIGSW			sys_insn(1, 0, 7, 14, 4)
+#define SYS_DC_CIGDSW			sys_insn(1, 0, 7, 14, 6)
 
 #define SYS_OSDTRRX_EL1			sys_reg(2, 0, 0, 0, 2)
 #define SYS_MDCCINT_EL1			sys_reg(2, 0, 0, 2, 0)
@@ -163,6 +171,7 @@
 
 #define SYS_ID_AA64ISAR0_EL1		sys_reg(3, 0, 0, 6, 0)
 #define SYS_ID_AA64ISAR1_EL1		sys_reg(3, 0, 0, 6, 1)
+#define SYS_ID_AA64ISAR2_EL1		sys_reg(3, 0, 0, 6, 2)
 
 #define SYS_ID_AA64MMFR0_EL1		sys_reg(3, 0, 0, 7, 0)
 #define SYS_ID_AA64MMFR1_EL1		sys_reg(3, 0, 0, 7, 1)
@@ -573,6 +582,21 @@
 #define ID_AA64ISAR1_GPI_NI		0x0
 #define ID_AA64ISAR1_GPI_IMP_DEF	0x1
 
+/* id_aa64isar2 */
+#define ID_AA64ISAR2_CLEARBHB_SHIFT	28
+#define ID_AA64ISAR2_RPRES_SHIFT	4
+#define ID_AA64ISAR2_WFXT_SHIFT		0
+
+#define ID_AA64ISAR2_RPRES_8BIT		0x0
+#define ID_AA64ISAR2_RPRES_12BIT	0x1
+/*
+ * Value 0x1 has been removed from the architecture, and is
+ * reserved, but has not yet been removed from the ARM ARM
+ * as of ARM DDI 0487G.b.
+ */
+#define ID_AA64ISAR2_WFXT_NI		0x0
+#define ID_AA64ISAR2_WFXT_SUPPORTED	0x2
+
 /* id_aa64pfr0 */
 #define ID_AA64PFR0_CSV3_SHIFT		60
 #define ID_AA64PFR0_CSV2_SHIFT		56
@@ -644,6 +668,7 @@
 #endif
 
 /* id_aa64mmfr1 */
+#define ID_AA64MMFR1_ECBHB_SHIFT	60
 #define ID_AA64MMFR1_PAN_SHIFT		20
 #define ID_AA64MMFR1_LOR_SHIFT		16
 #define ID_AA64MMFR1_HPD_SHIFT		12
@@ -672,6 +697,12 @@
 #define ID_AA64DFR0_TRACEVER_SHIFT	4
 #define ID_AA64DFR0_DEBUGVER_SHIFT	0
 
+#define ID_AA64DFR0_PMUVER_8_1		0x4
+
+#define ID_DFR0_PERFMON_SHIFT		24
+
+#define ID_DFR0_PERFMON_8_1		0x4
+
 #define ID_ISAR5_RDM_SHIFT		24
 #define ID_ISAR5_CRC32_SHIFT		16
 #define ID_ISAR5_SHA2_SHIFT		12
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/thread_info.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/thread_info.h
@@ -91,6 +91,7 @@
 #define _TIF_SYSCALL_EMU	(1 << TIF_SYSCALL_EMU)
 #define _TIF_UPROBE		(1 << TIF_UPROBE)
 #define _TIF_FSCHECK		(1 << TIF_FSCHECK)
+#define _TIF_SINGLESTEP		(1 << TIF_SINGLESTEP)
 #define _TIF_32BIT		(1 << TIF_32BIT)
 #define _TIF_SVE		(1 << TIF_SVE)
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/uaccess.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/uaccess.h
@@ -62,8 +62,13 @@
 {
 	unsigned long ret, limit = current_thread_info()->addr_limit;
 
+	/*
+	 * Asynchronous I/O running in a kernel thread does not have the
+	 * TIF_TAGGED_ADDR flag of the process owning the mm, so always untag
+	 * the user address before checking.
+	 */
 	if (IS_ENABLED(CONFIG_ARM64_TAGGED_ADDR_ABI) &&
-	    test_thread_flag(TIF_TAGGED_ADDR))
+	    (current->flags & PF_KTHREAD || test_thread_flag(TIF_TAGGED_ADDR)))
 		addr = untagged_addr(addr);
 
 	__chk_user_ptr(addr);
@@ -107,8 +112,8 @@
 	local_irq_save(flags);
 	ttbr = read_sysreg(ttbr1_el1);
 	ttbr &= ~TTBR_ASID_MASK;
-	/* reserved_ttbr0 placed before swapper_pg_dir */
-	write_sysreg(ttbr - RESERVED_TTBR0_SIZE, ttbr0_el1);
+	/* reserved_pg_dir placed before swapper_pg_dir */
+	write_sysreg(ttbr - PAGE_SIZE, ttbr0_el1);
 	isb();
 	/* Set reserved ASID */
 	write_sysreg(ttbr, ttbr1_el1);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/unistd.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/unistd.h
@@ -25,8 +25,8 @@
 #define __NR_compat_gettimeofday	78
 #define __NR_compat_sigreturn		119
 #define __NR_compat_rt_sigreturn	173
-#define __NR_compat_clock_getres	247
 #define __NR_compat_clock_gettime	263
+#define __NR_compat_clock_getres	264
 #define __NR_compat_clock_gettime64	403
 #define __NR_compat_clock_getres_time64	406
 
@@ -42,7 +42,6 @@
 #endif
 
 #define __ARCH_WANT_SYS_CLONE
-#define __ARCH_WANT_SYS_CLONE3
 
 #ifndef __COMPAT_SYSCALL_NR
 #include <uapi/asm/unistd.h>
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/uprobes.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/uprobes.h
@@ -10,21 +10,19 @@
 #include <asm/insn.h>
 #include <asm/probes.h>
 
-#define MAX_UINSN_BYTES		AARCH64_INSN_SIZE
-
-#define UPROBE_SWBP_INSN	BRK64_OPCODE_UPROBES
+#define UPROBE_SWBP_INSN	cpu_to_le32(BRK64_OPCODE_UPROBES)
 #define UPROBE_SWBP_INSN_SIZE	AARCH64_INSN_SIZE
-#define UPROBE_XOL_SLOT_BYTES	MAX_UINSN_BYTES
+#define UPROBE_XOL_SLOT_BYTES	AARCH64_INSN_SIZE
 
-typedef u32 uprobe_opcode_t;
+typedef __le32 uprobe_opcode_t;
 
 struct arch_uprobe_task {
 };
 
 struct arch_uprobe {
 	union {
-		u8 insn[MAX_UINSN_BYTES];
-		u8 ixol[MAX_UINSN_BYTES];
+		__le32 insn;
+		__le32 ixol;
 	};
 	struct arch_probe_insn api;
 	bool simulate;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/vdso/clocksource.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/vdso/clocksource.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ASM_VDSOCLOCKSOURCE_H
+#define __ASM_VDSOCLOCKSOURCE_H
+
+enum vdso_arch_clockmode {
+	/* vdso clocksource not usable */
+	VDSO_CLOCKMODE_NONE,
+	/* vdso clocksource for both 32 and 64bit tasks */
+	VDSO_CLOCKMODE_ARCHTIMER,
+	/* vdso clocksource for 64bit tasks only */
+	VDSO_CLOCKMODE_ARCHTIMER_NOCOMPAT,
+};
+
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/vdso/compat_gettimeofday.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/vdso/compat_gettimeofday.h
@@ -10,6 +10,7 @@
 #include <asm/unistd.h>
 #include <uapi/linux/time.h>
 
+#include <asm/vdso/clocksource.h>
 #include <asm/vdso/compat_barrier.h>
 
 #define __VDSO_USE_SYSCALL		ULLONG_MAX
@@ -117,10 +118,10 @@
 	u64 res;
 
 	/*
-	 * clock_mode == 0 implies that vDSO are enabled otherwise
+	 * clock_mode == ARCHTIMER implies that vDSO are enabled otherwise
 	 * fallback on syscall.
 	 */
-	if (clock_mode)
+	if (clock_mode != VDSO_CLOCKMODE_ARCHTIMER)
 		return __VDSO_USE_SYSCALL;
 
 	/*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/vdso/gettimeofday.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/vdso/gettimeofday.h
@@ -10,6 +10,8 @@
 #include <asm/unistd.h>
 #include <uapi/linux/time.h>
 
+#include <asm/vdso/clocksource.h>
+
 #define __VDSO_USE_SYSCALL		ULLONG_MAX
 
 #define VDSO_HAS_CLOCK_GETRES		1
@@ -71,10 +73,10 @@
 	u64 res;
 
 	/*
-	 * clock_mode == 0 implies that vDSO are enabled otherwise
+	 * clock_mode != NONE implies that vDSO are enabled otherwise
 	 * fallback on syscall.
 	 */
-	if (clock_mode)
+	if (clock_mode == VDSO_CLOCKMODE_NONE)
 		return __VDSO_USE_SYSCALL;
 
 	/*
@@ -83,11 +85,7 @@
 	 */
 	isb();
 	asm volatile("mrs %0, cntvct_el0" : "=r" (res) :: "memory");
-	/*
-	 * This isb() is required to prevent that the seq lock is
-	 * speculated.#
-	 */
-	isb();
+	arch_counter_enforce_ordering(res);
 
 	return res;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/vdso/vsyscall.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/vdso/vsyscall.h
@@ -24,9 +24,7 @@
 static __always_inline
 int __arm64_get_clock_mode(struct timekeeper *tk)
 {
-	u32 use_syscall = !tk->tkr_mono.clock->archdata.vdso_direct;
-
-	return use_syscall;
+	return tk->tkr_mono.clock->archdata.clock_mode;
 }
 #define __arch_get_clock_mode __arm64_get_clock_mode
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/vectors.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/vectors.h
@@ -0,0 +1,73 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2022 ARM Ltd.
+ */
+#ifndef __ASM_VECTORS_H
+#define __ASM_VECTORS_H
+
+#include <linux/bug.h>
+#include <linux/percpu.h>
+
+#include <asm/fixmap.h>
+
+extern char vectors[];
+extern char tramp_vectors[];
+extern char __bp_harden_el1_vectors[];
+
+/*
+ * Note: the order of this enum corresponds to two arrays in entry.S:
+ * tramp_vecs and __bp_harden_el1_vectors. By default the canonical
+ * 'full fat' vectors are used directly.
+ */
+enum arm64_bp_harden_el1_vectors {
+#ifdef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY
+	/*
+	 * Perform the BHB loop mitigation, before branching to the canonical
+	 * vectors.
+	 */
+	EL1_VECTOR_BHB_LOOP,
+
+	/*
+	 * Make the SMC call for firmware mitigation, before branching to the
+	 * canonical vectors.
+	 */
+	EL1_VECTOR_BHB_FW,
+
+	/*
+	 * Use the ClearBHB instruction, before branching to the canonical
+	 * vectors.
+	 */
+	EL1_VECTOR_BHB_CLEAR_INSN,
+#endif /* CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */
+
+	/*
+	 * Remap the kernel before branching to the canonical vectors.
+	 */
+	EL1_VECTOR_KPTI,
+};
+
+#ifndef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY
+#define EL1_VECTOR_BHB_LOOP		-1
+#define EL1_VECTOR_BHB_FW		-1
+#define EL1_VECTOR_BHB_CLEAR_INSN	-1
+#endif /* !CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */
+
+/* The vectors to use on return from EL0. e.g. to remap the kernel */
+DECLARE_PER_CPU_READ_MOSTLY(const char *, this_cpu_vector);
+
+#ifndef CONFIG_UNMAP_KERNEL_AT_EL0
+#define TRAMP_VALIAS	0ul
+#endif
+
+static inline const char *
+arm64_get_bp_hardening_vector(enum arm64_bp_harden_el1_vectors slot)
+{
+	if (arm64_kernel_unmapped_at_el0())
+		return (char *)(TRAMP_VALIAS + SZ_2K * slot);
+
+	WARN_ON_ONCE(slot == EL1_VECTOR_KPTI);
+
+	return __bp_harden_el1_vectors + SZ_2K * slot;
+}
+
+#endif /* __ASM_VECTORS_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/asm/word-at-a-time.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/asm/word-at-a-time.h
@@ -53,7 +53,7 @@
  */
 static inline unsigned long load_unaligned_zeropad(const void *addr)
 {
-	unsigned long ret, offset;
+	unsigned long ret, tmp;
 
 	/* Load word from unaligned pointer addr */
 	asm(
@@ -61,9 +61,9 @@
 	"2:\n"
 	"	.pushsection .fixup,\"ax\"\n"
 	"	.align 2\n"
-	"3:	and	%1, %2, #0x7\n"
-	"	bic	%2, %2, #0x7\n"
-	"	ldr	%0, [%2]\n"
+	"3:	bic	%1, %2, #0x7\n"
+	"	ldr	%0, [%1]\n"
+	"	and	%1, %2, #0x7\n"
 	"	lsl	%1, %1, #0x3\n"
 #ifndef __AARCH64EB__
 	"	lsr	%0, %0, %1\n"
@@ -73,7 +73,7 @@
 	"	b	2b\n"
 	"	.popsection\n"
 	_ASM_EXTABLE(1b, 3b)
-	: "=&r" (ret), "=&r" (offset)
+	: "=&r" (ret), "=&r" (tmp)
 	: "r" (addr), "Q" (*(unsigned long *)addr));
 
 	return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/uapi/asm/kvm.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/uapi/asm/kvm.h
@@ -240,6 +240,11 @@
 #define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_REQUIRED	3
 #define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_ENABLED     	(1U << 4)
 
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3	KVM_REG_ARM_FW_REG(3)
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_NOT_AVAIL		0
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_AVAIL		1
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_NOT_REQUIRED	2
+
 /* SVE registers */
 #define KVM_REG_ARM64_SVE		(0x15 << KVM_REG_ARM_COPROC_SHIFT)
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/uapi/asm/ptrace.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/uapi/asm/ptrace.h
@@ -49,6 +49,7 @@
 #define PSR_SSBS_BIT	0x00001000
 #define PSR_PAN_BIT	0x00400000
 #define PSR_UAO_BIT	0x00800000
+#define PSR_DIT_BIT	0x01000000
 #define PSR_V_BIT	0x10000000
 #define PSR_C_BIT	0x20000000
 #define PSR_Z_BIT	0x40000000
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/include/uapi/asm/unistd.h
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/include/uapi/asm/unistd.h
@@ -19,5 +19,6 @@
 #define __ARCH_WANT_NEW_STAT
 #define __ARCH_WANT_SET_GET_RLIMIT
 #define __ARCH_WANT_TIME32_SYSCALLS
+#define __ARCH_WANT_SYS_CLONE3
 
 #include <asm-generic/unistd.h>
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/acpi.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/acpi.c
@@ -19,6 +19,7 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
+#include <linux/irq_work.h>
 #include <linux/memblock.h>
 #include <linux/of_fdt.h>
 #include <linux/smp.h>
@@ -269,12 +270,19 @@
 int apei_claim_sea(struct pt_regs *regs)
 {
 	int err = -ENOENT;
+	bool return_to_irqs_enabled;
 	unsigned long current_flags;
 
 	if (!IS_ENABLED(CONFIG_ACPI_APEI_GHES))
 		return err;
 
-	current_flags = arch_local_save_flags();
+	current_flags = local_daif_save_flags();
+
+	/* current_flags isn't useful here as daif doesn't tell us about pNMI */
+	return_to_irqs_enabled = !irqs_disabled_flags(arch_local_save_flags());
+
+	if (regs)
+		return_to_irqs_enabled = interrupts_enabled(regs);
 
 	/*
 	 * SEA can interrupt SError, mask it and describe this as an NMI so
@@ -284,6 +292,23 @@
 	nmi_enter();
 	err = ghes_notify_sea();
 	nmi_exit();
+
+	/*
+	 * APEI NMI-like notifications are deferred to irq_work. Unless
+	 * we interrupted irqs-masked code, we can do that now.
+	 */
+	if (!err) {
+		if (return_to_irqs_enabled) {
+			local_daif_restore(DAIF_PROCCTX_NOIRQ);
+			__irq_enter();
+			irq_work_run();
+			__irq_exit();
+		} else {
+			pr_warn_ratelimited("APEI work queued but not completed");
+			err = -EINPROGRESS;
+		}
+	}
+
 	local_daif_restore(current_flags);
 
 	return err;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/acpi_numa.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/acpi_numa.c
@@ -27,24 +27,13 @@
 
 #include <asm/numa.h>
 
-static int acpi_early_node_map[NR_CPUS] __initdata = { NUMA_NO_NODE };
+static int acpi_early_node_map[NR_CPUS] __initdata = { [0 ... NR_CPUS - 1] = NUMA_NO_NODE };
 
 int __init acpi_numa_get_nid(unsigned int cpu)
 {
 	return acpi_early_node_map[cpu];
 }
 
-static inline int get_cpu_for_acpi_id(u32 uid)
-{
-	int cpu;
-
-	for (cpu = 0; cpu < nr_cpu_ids; cpu++)
-		if (uid == get_acpi_id_for_cpu(cpu))
-			return cpu;
-
-	return -EINVAL;
-}
-
 static int __init acpi_parse_gicc_pxm(union acpi_subtable_headers *header,
 				      const unsigned long end)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/alternative.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/alternative.c
@@ -41,27 +41,15 @@
 /*
  * Check if the target PC is within an alternative block.
  */
-static bool branch_insn_requires_update(struct alt_instr *alt, unsigned long pc)
+static __always_inline bool branch_insn_requires_update(struct alt_instr *alt, unsigned long pc)
 {
-	unsigned long replptr;
-
-	if (kernel_text_address(pc))
-		return true;
-
-	replptr = (unsigned long)ALT_REPL_PTR(alt);
-	if (pc >= replptr && pc <= (replptr + alt->alt_len))
-		return false;
-
-	/*
-	 * Branching into *another* alternate sequence is doomed, and
-	 * we're not even trying to fix it up.
-	 */
-	BUG();
+	unsigned long replptr = (unsigned long)ALT_REPL_PTR(alt);
+	return !(pc >= replptr && pc <= (replptr + alt->alt_len));
 }
 
 #define align_down(x, a)	((unsigned long)(x) & ~(((unsigned long)(a)) - 1))
 
-static u32 get_alt_insn(struct alt_instr *alt, __le32 *insnptr, __le32 *altinsnptr)
+static __always_inline u32 get_alt_insn(struct alt_instr *alt, __le32 *insnptr, __le32 *altinsnptr)
 {
 	u32 insn;
 
@@ -106,7 +94,7 @@
 	return insn;
 }
 
-static void patch_alternative(struct alt_instr *alt,
+static noinstr void patch_alternative(struct alt_instr *alt,
 			      __le32 *origptr, __le32 *updptr, int nr_inst)
 {
 	__le32 *replptr;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/armv8_deprecated.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/armv8_deprecated.c
@@ -59,6 +59,7 @@
 static LIST_HEAD(insn_emulation);
 static int nr_insn_emulated __initdata;
 static DEFINE_RAW_SPINLOCK(insn_emulation_lock);
+static DEFINE_MUTEX(insn_emulation_mutex);
 
 static void register_emulation_hooks(struct insn_emulation_ops *ops)
 {
@@ -207,10 +208,12 @@
 				  loff_t *ppos)
 {
 	int ret = 0;
-	struct insn_emulation *insn = (struct insn_emulation *) table->data;
-	enum insn_emulation_mode prev_mode = insn->current_mode;
+	struct insn_emulation *insn;
+	enum insn_emulation_mode prev_mode;
 
-	table->data = &insn->current_mode;
+	mutex_lock(&insn_emulation_mutex);
+	insn = container_of(table->data, struct insn_emulation, current_mode);
+	prev_mode = insn->current_mode;
 	ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
 
 	if (ret || !write || prev_mode == insn->current_mode)
@@ -223,7 +226,7 @@
 		update_insn_emulation_mode(insn, INSN_UNDEF);
 	}
 ret:
-	table->data = insn;
+	mutex_unlock(&insn_emulation_mutex);
 	return ret;
 }
 
@@ -247,7 +250,7 @@
 		sysctl->maxlen = sizeof(int);
 
 		sysctl->procname = insn->ops->name;
-		sysctl->data = insn;
+		sysctl->data = &insn->current_mode;
 		sysctl->extra1 = &insn->min;
 		sysctl->extra2 = &insn->max;
 		sysctl->proc_handler = emulation_proc_handler;
@@ -601,7 +604,7 @@
 	},
 	{
 		/* Thumb mode */
-		.instr_mask	= 0x0000fff7,
+		.instr_mask	= 0xfffffff7,
 		.instr_val	= 0x0000b650,
 		.pstate_mask	= (PSR_AA32_T_BIT | PSR_AA32_MODE_MASK),
 		.pstate_val	= (PSR_AA32_T_BIT | PSR_AA32_MODE_USR),
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/cacheinfo.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/cacheinfo.c
@@ -43,9 +43,10 @@
 	this_leaf->type = type;
 }
 
-static int __init_cache_level(unsigned int cpu)
+int init_cache_level(unsigned int cpu)
 {
-	unsigned int ctype, level, leaves, fw_level;
+	unsigned int ctype, level, leaves;
+	int fw_level;
 	struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
 
 	for (level = 1, leaves = 0; level <= MAX_CACHE_LEVEL; level++) {
@@ -63,6 +64,9 @@
 	else
 		fw_level = acpi_find_last_cache_level(cpu);
 
+	if (fw_level < 0)
+		return fw_level;
+
 	if (level < fw_level) {
 		/*
 		 * some external caches not specified in CLIDR_EL1
@@ -78,25 +82,24 @@
 	return 0;
 }
 
-static int __populate_cache_leaves(unsigned int cpu)
+int populate_cache_leaves(unsigned int cpu)
 {
 	unsigned int level, idx;
 	enum cache_type type;
 	struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
-	struct cacheinfo *this_leaf = this_cpu_ci->info_list;
+	struct cacheinfo *infos = this_cpu_ci->info_list;
 
 	for (idx = 0, level = 1; level <= this_cpu_ci->num_levels &&
-	     idx < this_cpu_ci->num_leaves; idx++, level++) {
+	     idx < this_cpu_ci->num_leaves; level++) {
 		type = get_cache_type(level);
 		if (type == CACHE_TYPE_SEPARATE) {
-			ci_leaf_init(this_leaf++, CACHE_TYPE_DATA, level);
-			ci_leaf_init(this_leaf++, CACHE_TYPE_INST, level);
+			if (idx + 1 >= this_cpu_ci->num_leaves)
+				break;
+			ci_leaf_init(&infos[idx++], CACHE_TYPE_DATA, level);
+			ci_leaf_init(&infos[idx++], CACHE_TYPE_INST, level);
 		} else {
-			ci_leaf_init(this_leaf++, type, level);
+			ci_leaf_init(&infos[idx++], type, level);
 		}
 	}
 	return 0;
 }
-
-DEFINE_SMP_CALL_CACHE_FUNCTION(init_cache_level)
-DEFINE_SMP_CALL_CACHE_FUNCTION(populate_cache_leaves)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/cpu_errata.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/cpu_errata.c
@@ -13,6 +13,7 @@
 #include <asm/cputype.h>
 #include <asm/cpufeature.h>
 #include <asm/smp_plat.h>
+#include <asm/vectors.h>
 
 static bool __maybe_unused
 is_affected_midr_range(const struct arm64_cpu_capabilities *entry, int scope)
@@ -88,13 +89,21 @@
 }
 
 static void
-cpu_enable_trap_ctr_access(const struct arm64_cpu_capabilities *__unused)
+cpu_enable_trap_ctr_access(const struct arm64_cpu_capabilities *cap)
 {
 	u64 mask = arm64_ftr_reg_ctrel0.strict_mask;
+	bool enable_uct_trap = false;
 
 	/* Trap CTR_EL0 access on this CPU, only if it has a mismatch */
 	if ((read_cpuid_cachetype() & mask) !=
 	    (arm64_ftr_reg_ctrel0.sys_val & mask))
+		enable_uct_trap = true;
+
+	/* ... or if the system is affected by an erratum */
+	if (cap->capability == ARM64_WORKAROUND_1542419)
+		enable_uct_trap = true;
+
+	if (enable_uct_trap)
 		sysreg_clear_set(sctlr_el1, SCTLR_EL1_UCT, 0);
 }
 
@@ -108,6 +117,16 @@
 #ifdef CONFIG_KVM_INDIRECT_VECTORS
 extern char __smccc_workaround_1_smc_start[];
 extern char __smccc_workaround_1_smc_end[];
+extern char __smccc_workaround_3_smc_start[];
+extern char __smccc_workaround_3_smc_end[];
+extern char __spectre_bhb_loop_k8_start[];
+extern char __spectre_bhb_loop_k8_end[];
+extern char __spectre_bhb_loop_k24_start[];
+extern char __spectre_bhb_loop_k24_end[];
+extern char __spectre_bhb_loop_k32_start[];
+extern char __spectre_bhb_loop_k32_end[];
+extern char __spectre_bhb_clearbhb_start[];
+extern char __spectre_bhb_clearbhb_end[];
 
 static void __copy_hyp_vect_bpi(int slot, const char *hyp_vecs_start,
 				const char *hyp_vecs_end)
@@ -121,11 +140,11 @@
 	__flush_icache_range((uintptr_t)dst, (uintptr_t)dst + SZ_2K);
 }
 
+static DEFINE_RAW_SPINLOCK(bp_lock);
 static void install_bp_hardening_cb(bp_hardening_cb_t fn,
 				    const char *hyp_vecs_start,
 				    const char *hyp_vecs_end)
 {
-	static DEFINE_RAW_SPINLOCK(bp_lock);
 	int cpu, slot = -1;
 
 	/*
@@ -151,8 +170,12 @@
 		__copy_hyp_vect_bpi(slot, hyp_vecs_start, hyp_vecs_end);
 	}
 
-	__this_cpu_write(bp_hardening_data.hyp_vectors_slot, slot);
-	__this_cpu_write(bp_hardening_data.fn, fn);
+	if (fn != __this_cpu_read(bp_hardening_data.fn)) {
+		__this_cpu_write(bp_hardening_data.hyp_vectors_slot, slot);
+		__this_cpu_write(bp_hardening_data.fn, fn);
+		__this_cpu_write(bp_hardening_data.template_start,
+				 hyp_vecs_start);
+	}
 	raw_spin_unlock(&bp_lock);
 }
 #else
@@ -349,6 +372,19 @@
 			asm volatile(SET_PSTATE_SSBS(0));
 		else
 			asm volatile(SET_PSTATE_SSBS(1));
+
+		/*
+		 * SSBS is self-synchronizing and is intended to affect
+		 * subsequent speculative instructions, but some CPUs can
+		 * speculate with a stale value of SSBS.
+		 *
+		 * Mitigate this with an unconditional speculation barrier, as
+		 * CPUs could mis-speculate branches and bypass a conditional
+		 * barrier.
+		 */
+		if (IS_ENABLED(CONFIG_ARM64_ERRATUM_3194386))
+			spec_bar();
+
 		return;
 	}
 
@@ -484,6 +520,12 @@
 	return required;
 }
 
+static void cpu_enable_ssbd_mitigation(const struct arm64_cpu_capabilities *cap)
+{
+	if (ssbd_state != ARM64_SSBD_FORCE_DISABLE)
+		cap->matches(cap, SCOPE_LOCAL_CPU);
+}
+
 /* known invulnerable cores */
 static const struct midr_range arm64_ssb_cpus[] = {
 	MIDR_ALL_VERSIONS(MIDR_CORTEX_A35),
@@ -575,6 +617,7 @@
 	MIDR_ALL_VERSIONS(MIDR_CORTEX_A53),
 	MIDR_ALL_VERSIONS(MIDR_CORTEX_A55),
 	MIDR_ALL_VERSIONS(MIDR_BRAHMA_B53),
+	MIDR_ALL_VERSIONS(MIDR_HISI_TSV110),
 	{ /* sentinel */ }
 };
 
@@ -626,6 +669,12 @@
 	return (need_wa > 0);
 }
 
+static void
+cpu_enable_branch_predictor_hardening(const struct arm64_cpu_capabilities *cap)
+{
+	cap->matches(cap, SCOPE_LOCAL_CPU);
+}
+
 static const __maybe_unused struct midr_range tx2_family_cpus[] = {
 	MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN),
 	MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2),
@@ -650,6 +699,18 @@
 	return false;
 }
 
+static bool __maybe_unused
+has_neoverse_n1_erratum_1542419(const struct arm64_cpu_capabilities *entry,
+				int scope)
+{
+	u32 midr = read_cpuid_id();
+	bool has_dic = read_cpuid_cachetype() & BIT(CTR_DIC_SHIFT);
+	const struct midr_range range = MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1);
+
+	WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible());
+	return is_midr_in_range(midr, &range) && has_dic;
+}
+
 #ifdef CONFIG_HARDEN_EL2_VECTORS
 
 static const struct midr_range arm64_harden_el2_vectors[] = {
@@ -772,6 +833,40 @@
 };
 #endif
 
+#ifdef CONFIG_ARM64_ERRATUM_1742098
+static struct midr_range broken_aarch32_aes[] = {
+	MIDR_RANGE(MIDR_CORTEX_A57, 0, 1, 0xf, 0xf),
+	MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
+	{},
+};
+#endif
+
+#ifdef CONFIG_ARM64_ERRATUM_3194386
+static const struct midr_range erratum_spec_ssbs_list[] = {
+	MIDR_ALL_VERSIONS(MIDR_CORTEX_A76),
+	MIDR_ALL_VERSIONS(MIDR_CORTEX_A77),
+	MIDR_ALL_VERSIONS(MIDR_CORTEX_A78),
+	MIDR_ALL_VERSIONS(MIDR_CORTEX_A78C),
+	MIDR_ALL_VERSIONS(MIDR_CORTEX_A710),
+	MIDR_ALL_VERSIONS(MIDR_CORTEX_A715),
+	MIDR_ALL_VERSIONS(MIDR_CORTEX_A720),
+	MIDR_ALL_VERSIONS(MIDR_CORTEX_A725),
+	MIDR_ALL_VERSIONS(MIDR_CORTEX_X1),
+	MIDR_ALL_VERSIONS(MIDR_CORTEX_X1C),
+	MIDR_ALL_VERSIONS(MIDR_CORTEX_X2),
+	MIDR_ALL_VERSIONS(MIDR_CORTEX_X3),
+	MIDR_ALL_VERSIONS(MIDR_CORTEX_X4),
+	MIDR_ALL_VERSIONS(MIDR_CORTEX_X925),
+	MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1),
+	MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2),
+	MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N3),
+	MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V1),
+	MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V2),
+	MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V3),
+	{}
+};
+#endif
+
 const struct arm64_cpu_capabilities arm64_errata[] = {
 #ifdef CONFIG_ARM64_WORKAROUND_CLEAN_CACHE
 	{
@@ -873,9 +968,11 @@
 	},
 #endif
 	{
+		.desc = "Branch predictor hardening",
 		.capability = ARM64_HARDEN_BRANCH_PREDICTOR,
 		.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
 		.matches = check_branch_predictor,
+		.cpu_enable = cpu_enable_branch_predictor_hardening,
 	},
 #ifdef CONFIG_HARDEN_EL2_VECTORS
 	{
@@ -889,13 +986,27 @@
 		.capability = ARM64_SSBD,
 		.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
 		.matches = has_ssbd_mitigation,
+		.cpu_enable = cpu_enable_ssbd_mitigation,
 		.midr_range_list = arm64_ssb_cpus,
 	},
+	{
+		.desc = "Spectre-BHB",
+		.capability = ARM64_SPECTRE_BHB,
+		.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
+		.matches = is_spectre_bhb_affected,
+		.cpu_enable = spectre_bhb_enable_mitigation,
+	},
 #ifdef CONFIG_ARM64_ERRATUM_1418040
 	{
 		.desc = "ARM erratum 1418040",
 		.capability = ARM64_WORKAROUND_1418040,
 		ERRATA_MIDR_RANGE_LIST(erratum_1418040_list),
+		/*
+		 * We need to allow affected CPUs to come in late, but
+		 * also need the non-affected CPUs to be able to come
+		 * in at any point in time. Wonderful.
+		 */
+		.type = ARM64_CPUCAP_WEAK_LOCAL_CPU_FEATURE,
 	},
 #endif
 #ifdef CONFIG_ARM64_ERRATUM_1165522
@@ -927,6 +1038,31 @@
 		ERRATA_MIDR_RANGE_LIST(tx2_family_cpus),
 	},
 #endif
+#ifdef CONFIG_ARM64_ERRATUM_1542419
+	{
+		/* we depend on the firmware portion for correctness */
+		.desc = "ARM erratum 1542419 (kernel portion)",
+		.capability = ARM64_WORKAROUND_1542419,
+		.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
+		.matches = has_neoverse_n1_erratum_1542419,
+		.cpu_enable = cpu_enable_trap_ctr_access,
+	},
+#endif
+#ifdef CONFIG_ARM64_ERRATUM_1742098
+	{
+		.desc = "ARM erratum 1742098",
+		.capability = ARM64_WORKAROUND_1742098,
+		CAP_MIDR_RANGE_LIST(broken_aarch32_aes),
+		.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
+	},
+#endif
+#ifdef CONFIG_ARM64_ERRATUM_3194386
+	{
+		.desc = "SSBS not fully self-synchronizing",
+		.capability = ARM64_WORKAROUND_SPECULATIVE_SSBS,
+		ERRATA_MIDR_RANGE_LIST(erratum_spec_ssbs_list),
+	},
+#endif
 	{
 	}
 };
@@ -937,15 +1073,41 @@
 	return sprintf(buf, "Mitigation: __user pointer sanitization\n");
 }
 
+static const char *get_bhb_affected_string(enum mitigation_state bhb_state)
+{
+	switch (bhb_state) {
+	case SPECTRE_UNAFFECTED:
+		return "";
+	default:
+	case SPECTRE_VULNERABLE:
+		return ", but not BHB";
+	case SPECTRE_MITIGATED:
+		return ", BHB";
+	}
+}
+
 ssize_t cpu_show_spectre_v2(struct device *dev, struct device_attribute *attr,
 		char *buf)
 {
+	enum mitigation_state bhb_state = arm64_get_spectre_bhb_state();
+	const char *bhb_str = get_bhb_affected_string(bhb_state);
+	const char *v2_str = "Branch predictor hardening";
+
 	switch (get_spectre_v2_workaround_state()) {
 	case ARM64_BP_HARDEN_NOT_REQUIRED:
-		return sprintf(buf, "Not affected\n");
-        case ARM64_BP_HARDEN_WA_NEEDED:
-		return sprintf(buf, "Mitigation: Branch predictor hardening\n");
-        case ARM64_BP_HARDEN_UNKNOWN:
+		if (bhb_state == SPECTRE_UNAFFECTED)
+			return sprintf(buf, "Not affected\n");
+
+		/*
+		 * Platforms affected by Spectre-BHB can't report
+		 * "Not affected" for Spectre-v2.
+		 */
+		v2_str = "CSV2";
+		fallthrough;
+	case ARM64_BP_HARDEN_WA_NEEDED:
+		return sprintf(buf, "Mitigation: %s%s\n", v2_str, bhb_str);
+	case ARM64_BP_HARDEN_UNKNOWN:
+		fallthrough;
 	default:
 		return sprintf(buf, "Vulnerable\n");
 	}
@@ -967,3 +1129,348 @@
 
 	return sprintf(buf, "Vulnerable\n");
 }
+
+/*
+ * We try to ensure that the mitigation state can never change as the result of
+ * onlining a late CPU.
+ */
+static void update_mitigation_state(enum mitigation_state *oldp,
+				    enum mitigation_state new)
+{
+	enum mitigation_state state;
+
+	do {
+		state = READ_ONCE(*oldp);
+		if (new <= state)
+			break;
+	} while (cmpxchg_relaxed(oldp, state, new) != state);
+}
+
+/*
+ * Spectre BHB.
+ *
+ * A CPU is either:
+ * - Mitigated by a branchy loop a CPU specific number of times, and listed
+ *   in our "loop mitigated list".
+ * - Mitigated in software by the firmware Spectre v2 call.
+ * - Has the ClearBHB instruction to perform the mitigation.
+ * - Has the 'Exception Clears Branch History Buffer' (ECBHB) feature, so no
+ *   software mitigation in the vectors is needed.
+ * - Has CSV2.3, so is unaffected.
+ */
+static enum mitigation_state spectre_bhb_state;
+
+enum mitigation_state arm64_get_spectre_bhb_state(void)
+{
+	return spectre_bhb_state;
+}
+
+/*
+ * This must be called with SCOPE_LOCAL_CPU for each type of CPU, before any
+ * SCOPE_SYSTEM call will give the right answer.
+ */
+u8 spectre_bhb_loop_affected(int scope)
+{
+	u8 k = 0;
+	static u8 max_bhb_k;
+
+	if (scope == SCOPE_LOCAL_CPU) {
+		static const struct midr_range spectre_bhb_k32_list[] = {
+			MIDR_ALL_VERSIONS(MIDR_CORTEX_A78),
+			MIDR_ALL_VERSIONS(MIDR_CORTEX_A78C),
+			MIDR_ALL_VERSIONS(MIDR_CORTEX_X1),
+			MIDR_ALL_VERSIONS(MIDR_CORTEX_A710),
+			MIDR_ALL_VERSIONS(MIDR_CORTEX_X2),
+			MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N2),
+			MIDR_ALL_VERSIONS(MIDR_NEOVERSE_V1),
+			{},
+		};
+		static const struct midr_range spectre_bhb_k24_list[] = {
+			MIDR_ALL_VERSIONS(MIDR_CORTEX_A76),
+			MIDR_ALL_VERSIONS(MIDR_CORTEX_A77),
+			MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1),
+			{},
+		};
+		static const struct midr_range spectre_bhb_k11_list[] = {
+			MIDR_ALL_VERSIONS(MIDR_AMPERE1),
+			{},
+		};
+		static const struct midr_range spectre_bhb_k8_list[] = {
+			MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
+			MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
+			{},
+		};
+
+		if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k32_list))
+			k = 32;
+		else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k24_list))
+			k = 24;
+		else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k11_list))
+			k = 11;
+		else if (is_midr_in_range_list(read_cpuid_id(), spectre_bhb_k8_list))
+			k =  8;
+
+		max_bhb_k = max(max_bhb_k, k);
+	} else {
+		k = max_bhb_k;
+	}
+
+	return k;
+}
+
+static enum mitigation_state spectre_bhb_get_cpu_fw_mitigation_state(void)
+{
+	int ret;
+	struct arm_smccc_res res;
+
+	if (psci_ops.smccc_version == SMCCC_VERSION_1_0)
+		return SPECTRE_VULNERABLE;
+
+	switch (psci_ops.conduit) {
+	case PSCI_CONDUIT_HVC:
+		arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
+				  ARM_SMCCC_ARCH_WORKAROUND_3, &res);
+		break;
+
+	case PSCI_CONDUIT_SMC:
+		arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
+				  ARM_SMCCC_ARCH_WORKAROUND_3, &res);
+		break;
+
+	default:
+		return SPECTRE_VULNERABLE;
+	}
+
+	ret = res.a0;
+	switch (ret) {
+	case SMCCC_RET_SUCCESS:
+		return SPECTRE_MITIGATED;
+	case SMCCC_ARCH_WORKAROUND_RET_UNAFFECTED:
+		return SPECTRE_UNAFFECTED;
+	default:
+		fallthrough;
+	case SMCCC_RET_NOT_SUPPORTED:
+		return SPECTRE_VULNERABLE;
+	}
+}
+
+static bool is_spectre_bhb_fw_affected(int scope)
+{
+	static bool system_affected;
+	enum mitigation_state fw_state;
+	bool has_smccc = (psci_ops.smccc_version >= SMCCC_VERSION_1_1);
+	static const struct midr_range spectre_bhb_firmware_mitigated_list[] = {
+		MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
+		MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
+		{},
+	};
+	bool cpu_in_list = is_midr_in_range_list(read_cpuid_id(),
+					 spectre_bhb_firmware_mitigated_list);
+
+	if (scope != SCOPE_LOCAL_CPU)
+		return system_affected;
+
+	fw_state = spectre_bhb_get_cpu_fw_mitigation_state();
+	if (cpu_in_list || (has_smccc && fw_state == SPECTRE_MITIGATED)) {
+		system_affected = true;
+		return true;
+	}
+
+	return false;
+}
+
+static bool supports_ecbhb(int scope)
+{
+	u64 mmfr1;
+
+	if (scope == SCOPE_LOCAL_CPU)
+		mmfr1 = read_sysreg_s(SYS_ID_AA64MMFR1_EL1);
+	else
+		mmfr1 = read_sanitised_ftr_reg(SYS_ID_AA64MMFR1_EL1);
+
+	return cpuid_feature_extract_unsigned_field(mmfr1,
+						    ID_AA64MMFR1_ECBHB_SHIFT);
+}
+
+bool is_spectre_bhb_affected(const struct arm64_cpu_capabilities *entry,
+			     int scope)
+{
+	WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible());
+
+	if (supports_csv2p3(scope))
+		return false;
+
+	if (supports_clearbhb(scope))
+		return true;
+
+	if (spectre_bhb_loop_affected(scope))
+		return true;
+
+	if (is_spectre_bhb_fw_affected(scope))
+		return true;
+
+	return false;
+}
+
+static void this_cpu_set_vectors(enum arm64_bp_harden_el1_vectors slot)
+{
+	const char *v = arm64_get_bp_hardening_vector(slot);
+
+	if (slot < 0)
+		return;
+
+	__this_cpu_write(this_cpu_vector, v);
+
+	/*
+	 * When KPTI is in use, the vectors are switched when exiting to
+	 * user-space.
+	 */
+	if (arm64_kernel_unmapped_at_el0())
+		return;
+
+	write_sysreg(v, vbar_el1);
+	isb();
+}
+
+#ifdef CONFIG_KVM_INDIRECT_VECTORS
+static const char *kvm_bhb_get_vecs_end(const char *start)
+{
+	if (start == __smccc_workaround_3_smc_start)
+		return __smccc_workaround_3_smc_end;
+	else if (start == __spectre_bhb_loop_k8_start)
+		return __spectre_bhb_loop_k8_end;
+	else if (start == __spectre_bhb_loop_k24_start)
+		return __spectre_bhb_loop_k24_end;
+	else if (start == __spectre_bhb_loop_k32_start)
+		return __spectre_bhb_loop_k32_end;
+	else if (start == __spectre_bhb_clearbhb_start)
+		return __spectre_bhb_clearbhb_end;
+
+	return NULL;
+}
+
+static void kvm_setup_bhb_slot(const char *hyp_vecs_start)
+{
+	int cpu, slot = -1;
+	const char *hyp_vecs_end;
+
+	if (!IS_ENABLED(CONFIG_KVM) || !is_hyp_mode_available())
+		return;
+
+	hyp_vecs_end = kvm_bhb_get_vecs_end(hyp_vecs_start);
+	if (WARN_ON_ONCE(!hyp_vecs_start || !hyp_vecs_end))
+		return;
+
+	raw_spin_lock(&bp_lock);
+	for_each_possible_cpu(cpu) {
+		if (per_cpu(bp_hardening_data.template_start, cpu) == hyp_vecs_start) {
+			slot = per_cpu(bp_hardening_data.hyp_vectors_slot, cpu);
+			break;
+		}
+	}
+
+	if (slot == -1) {
+		slot = atomic_inc_return(&arm64_el2_vector_last_slot);
+		BUG_ON(slot >= BP_HARDEN_EL2_SLOTS);
+		__copy_hyp_vect_bpi(slot, hyp_vecs_start, hyp_vecs_end);
+	}
+
+	if (hyp_vecs_start != __this_cpu_read(bp_hardening_data.template_start)) {
+		__this_cpu_write(bp_hardening_data.hyp_vectors_slot, slot);
+		__this_cpu_write(bp_hardening_data.template_start,
+				 hyp_vecs_start);
+	}
+	raw_spin_unlock(&bp_lock);
+}
+#else
+#define __smccc_workaround_3_smc_start NULL
+#define __spectre_bhb_loop_k8_start NULL
+#define __spectre_bhb_loop_k24_start NULL
+#define __spectre_bhb_loop_k32_start NULL
+#define __spectre_bhb_clearbhb_start NULL
+
+static void kvm_setup_bhb_slot(const char *hyp_vecs_start) { }
+#endif
+
+void spectre_bhb_enable_mitigation(const struct arm64_cpu_capabilities *entry)
+{
+	enum mitigation_state fw_state, state = SPECTRE_VULNERABLE;
+
+	if (!is_spectre_bhb_affected(entry, SCOPE_LOCAL_CPU))
+		return;
+
+	if (get_spectre_v2_workaround_state() == ARM64_BP_HARDEN_UNKNOWN) {
+		/* No point mitigating Spectre-BHB alone. */
+	} else if (!IS_ENABLED(CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY)) {
+		pr_info_once("spectre-bhb mitigation disabled by compile time option\n");
+	} else if (cpu_mitigations_off()) {
+		pr_info_once("spectre-bhb mitigation disabled by command line option\n");
+	} else if (supports_ecbhb(SCOPE_LOCAL_CPU)) {
+		state = SPECTRE_MITIGATED;
+	} else if (supports_clearbhb(SCOPE_LOCAL_CPU)) {
+		kvm_setup_bhb_slot(__spectre_bhb_clearbhb_start);
+		this_cpu_set_vectors(EL1_VECTOR_BHB_CLEAR_INSN);
+
+		state = SPECTRE_MITIGATED;
+	} else if (spectre_bhb_loop_affected(SCOPE_LOCAL_CPU)) {
+		switch (spectre_bhb_loop_affected(SCOPE_SYSTEM)) {
+		case 8:
+			/*
+			 * A57/A72-r0 will already have selected the
+			 * spectre-indirect vector, which is sufficient
+			 * for BHB too.
+			 */
+			if (!__this_cpu_read(bp_hardening_data.fn))
+				kvm_setup_bhb_slot(__spectre_bhb_loop_k8_start);
+			break;
+		case 24:
+			kvm_setup_bhb_slot(__spectre_bhb_loop_k24_start);
+			break;
+		case 32:
+			kvm_setup_bhb_slot(__spectre_bhb_loop_k32_start);
+			break;
+		default:
+			WARN_ON_ONCE(1);
+		}
+		this_cpu_set_vectors(EL1_VECTOR_BHB_LOOP);
+
+		state = SPECTRE_MITIGATED;
+	} else if (is_spectre_bhb_fw_affected(SCOPE_LOCAL_CPU)) {
+		fw_state = spectre_bhb_get_cpu_fw_mitigation_state();
+		if (fw_state == SPECTRE_MITIGATED) {
+			kvm_setup_bhb_slot(__smccc_workaround_3_smc_start);
+			this_cpu_set_vectors(EL1_VECTOR_BHB_FW);
+
+			/*
+			 * With WA3 in the vectors, the WA1 calls can be
+			 * removed.
+			 */
+			__this_cpu_write(bp_hardening_data.fn, NULL);
+
+			state = SPECTRE_MITIGATED;
+		}
+	}
+
+	update_mitigation_state(&spectre_bhb_state, state);
+}
+
+/* Patched to correct the immediate */
+void noinstr spectre_bhb_patch_loop_iter(struct alt_instr *alt,
+				   __le32 *origptr, __le32 *updptr, int nr_inst)
+{
+	u8 rd;
+	u32 insn;
+	u16 loop_count = spectre_bhb_loop_affected(SCOPE_SYSTEM);
+
+	BUG_ON(nr_inst != 1); /* MOV -> MOV */
+
+	if (!IS_ENABLED(CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY))
+		return;
+
+	insn = le32_to_cpu(*origptr);
+	rd = aarch64_insn_decode_register(AARCH64_INSN_REGTYPE_RD, insn);
+	insn = aarch64_insn_gen_movewide(rd, loop_count, 0,
+					 AARCH64_INSN_VARIANT_64BIT,
+					 AARCH64_INSN_MOVEWIDE_ZERO);
+	*updptr++ = cpu_to_le32(insn);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/cpufeature.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/cpufeature.c
@@ -10,19 +10,23 @@
 #include <linux/bsearch.h>
 #include <linux/cpumask.h>
 #include <linux/crash_dump.h>
+#include <linux/percpu.h>
 #include <linux/sort.h>
 #include <linux/stop_machine.h>
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/cpu.h>
+
 #include <asm/cpu.h>
 #include <asm/cpufeature.h>
 #include <asm/cpu_ops.h>
 #include <asm/fpsimd.h>
+#include <asm/hwcap.h>
 #include <asm/mmu_context.h>
 #include <asm/processor.h>
 #include <asm/sysreg.h>
 #include <asm/traps.h>
+#include <asm/vectors.h>
 #include <asm/virt.h>
 
 /* Kernel representation of AT_HWCAP and AT_HWCAP2 */
@@ -32,9 +36,7 @@
 #define COMPAT_ELF_HWCAP_DEFAULT	\
 				(COMPAT_HWCAP_HALF|COMPAT_HWCAP_THUMB|\
 				 COMPAT_HWCAP_FAST_MULT|COMPAT_HWCAP_EDSP|\
-				 COMPAT_HWCAP_TLS|COMPAT_HWCAP_VFP|\
-				 COMPAT_HWCAP_VFPv3|COMPAT_HWCAP_VFPv4|\
-				 COMPAT_HWCAP_NEON|COMPAT_HWCAP_IDIV|\
+				 COMPAT_HWCAP_TLS|COMPAT_HWCAP_IDIV|\
 				 COMPAT_HWCAP_LPAE)
 unsigned int compat_elf_hwcap __read_mostly = COMPAT_ELF_HWCAP_DEFAULT;
 unsigned int compat_elf_hwcap2 __read_mostly;
@@ -47,6 +49,8 @@
 /* Need also bit for ARM64_CB_PATCH */
 DECLARE_BITMAP(boot_capabilities, ARM64_NPATCHABLE);
 
+DEFINE_PER_CPU_READ_MOSTLY(const char *, this_cpu_vector) = vectors;
+
 /*
  * Flag to indicate if we have computed the system wide
  * capabilities based on the boot time active CPUs. This
@@ -152,6 +156,11 @@
 	ARM64_FTR_END,
 };
 
+static const struct arm64_ftr_bits ftr_id_aa64isar2[] = {
+	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_HIGHER_SAFE, ID_AA64ISAR2_CLEARBHB_SHIFT, 4, 0),
+	ARM64_FTR_END,
+};
+
 static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = {
 	ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_CSV3_SHIFT, 4, 0),
 	ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_CSV2_SHIFT, 4, 0),
@@ -162,11 +171,10 @@
 	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_GIC_SHIFT, 4, 0),
 	S_ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_ASIMD_SHIFT, 4, ID_AA64PFR0_ASIMD_NI),
 	S_ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_FP_SHIFT, 4, ID_AA64PFR0_FP_NI),
-	/* Linux doesn't care about the EL3 */
 	ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL3_SHIFT, 4, 0),
-	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL2_SHIFT, 4, 0),
-	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL1_SHIFT, 4, ID_AA64PFR0_EL1_64BIT_ONLY),
-	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL0_SHIFT, 4, ID_AA64PFR0_EL0_64BIT_ONLY),
+	ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL2_SHIFT, 4, 0),
+	ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL1_SHIFT, 4, ID_AA64PFR0_EL1_64BIT_ONLY),
+	ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_EL0_SHIFT, 4, ID_AA64PFR0_EL0_64BIT_ONLY),
 	ARM64_FTR_END,
 };
 
@@ -280,11 +288,34 @@
 	 * of support.
 	 */
 	S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_EXACT, ID_AA64DFR0_PMUVER_SHIFT, 4, 0),
-	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64DFR0_TRACEVER_SHIFT, 4, 0),
 	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64DFR0_DEBUGVER_SHIFT, 4, 0x6),
 	ARM64_FTR_END,
 };
 
+static const struct arm64_ftr_bits ftr_mvfr0[] = {
+	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_FPROUND_SHIFT, 4, 0),
+	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_FPSHVEC_SHIFT, 4, 0),
+	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_FPSQRT_SHIFT, 4, 0),
+	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_FPDIVIDE_SHIFT, 4, 0),
+	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_FPTRAP_SHIFT, 4, 0),
+	ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_FPDP_SHIFT, 4, 0),
+	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_FPSP_SHIFT, 4, 0),
+	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_SIMD_SHIFT, 4, 0),
+	ARM64_FTR_END,
+};
+
+static const struct arm64_ftr_bits ftr_mvfr1[] = {
+	ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_SIMDFMAC_SHIFT, 4, 0),
+	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_FPHP_SHIFT, 4, 0),
+	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_SIMDHP_SHIFT, 4, 0),
+	ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_SIMDSP_SHIFT, 4, 0),
+	ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_SIMDINT_SHIFT, 4, 0),
+	ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_SIMDLS_SHIFT, 4, 0),
+	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_FPDNAN_SHIFT, 4, 0),
+	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_FPFTZ_SHIFT, 4, 0),
+	ARM64_FTR_END,
+};
+
 static const struct arm64_ftr_bits ftr_mvfr2[] = {
 	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 4, 4, 0),		/* FPMisc */
 	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 0, 4, 0),		/* SIMDMisc */
@@ -300,10 +331,10 @@
 
 static const struct arm64_ftr_bits ftr_id_isar5[] = {
 	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_RDM_SHIFT, 4, 0),
-	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_CRC32_SHIFT, 4, 0),
-	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_SHA2_SHIFT, 4, 0),
-	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_SHA1_SHIFT, 4, 0),
-	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_AES_SHIFT, 4, 0),
+	ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_CRC32_SHIFT, 4, 0),
+	ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_SHA2_SHIFT, 4, 0),
+	ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_SHA1_SHIFT, 4, 0),
+	ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_AES_SHIFT, 4, 0),
 	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_SEVL_SHIFT, 4, 0),
 	ARM64_FTR_END,
 };
@@ -322,7 +353,7 @@
 };
 
 static const struct arm64_ftr_bits ftr_id_dfr0[] = {
-	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 28, 4, 0),
+	/* [31:28] TraceFilt */
 	S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 24, 4, 0xf),	/* PerfMon */
 	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 20, 4, 0),
 	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 16, 4, 0),
@@ -343,7 +374,7 @@
  * Common ftr bits for a 32bit register with all hidden, strict
  * attributes, with 4bit feature fields and a default safe value of
  * 0. Covers the following 32bit registers:
- * id_isar[0-4], id_mmfr[1-3], id_pfr1, mvfr[0-1]
+ * id_isar[1-3], id_mmfr[1-3]
  */
 static const struct arm64_ftr_bits ftr_generic_32bits[] = {
 	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 28, 4, 0),
@@ -398,8 +429,8 @@
 	ARM64_FTR_REG(SYS_ID_MMFR4_EL1, ftr_id_mmfr4),
 
 	/* Op1 = 0, CRn = 0, CRm = 3 */
-	ARM64_FTR_REG(SYS_MVFR0_EL1, ftr_generic_32bits),
-	ARM64_FTR_REG(SYS_MVFR1_EL1, ftr_generic_32bits),
+	ARM64_FTR_REG(SYS_MVFR0_EL1, ftr_mvfr0),
+	ARM64_FTR_REG(SYS_MVFR1_EL1, ftr_mvfr1),
 	ARM64_FTR_REG(SYS_MVFR2_EL1, ftr_mvfr2),
 
 	/* Op1 = 0, CRn = 0, CRm = 4 */
@@ -414,6 +445,7 @@
 	/* Op1 = 0, CRn = 0, CRm = 6 */
 	ARM64_FTR_REG(SYS_ID_AA64ISAR0_EL1, ftr_id_aa64isar0),
 	ARM64_FTR_REG(SYS_ID_AA64ISAR1_EL1, ftr_id_aa64isar1),
+	ARM64_FTR_REG(SYS_ID_AA64ISAR2_EL1, ftr_id_aa64isar2),
 
 	/* Op1 = 0, CRn = 0, CRm = 7 */
 	ARM64_FTR_REG(SYS_ID_AA64MMFR0_EL1, ftr_id_aa64mmfr0),
@@ -585,6 +617,7 @@
 	init_cpu_ftr_reg(SYS_ID_AA64DFR1_EL1, info->reg_id_aa64dfr1);
 	init_cpu_ftr_reg(SYS_ID_AA64ISAR0_EL1, info->reg_id_aa64isar0);
 	init_cpu_ftr_reg(SYS_ID_AA64ISAR1_EL1, info->reg_id_aa64isar1);
+	init_cpu_ftr_reg(SYS_ID_AA64ISAR2_EL1, info->reg_id_aa64isar2);
 	init_cpu_ftr_reg(SYS_ID_AA64MMFR0_EL1, info->reg_id_aa64mmfr0);
 	init_cpu_ftr_reg(SYS_ID_AA64MMFR1_EL1, info->reg_id_aa64mmfr1);
 	init_cpu_ftr_reg(SYS_ID_AA64MMFR2_EL1, info->reg_id_aa64mmfr2);
@@ -708,6 +741,8 @@
 				      info->reg_id_aa64isar0, boot->reg_id_aa64isar0);
 	taint |= check_update_ftr_reg(SYS_ID_AA64ISAR1_EL1, cpu,
 				      info->reg_id_aa64isar1, boot->reg_id_aa64isar1);
+	taint |= check_update_ftr_reg(SYS_ID_AA64ISAR2_EL1, cpu,
+				      info->reg_id_aa64isar2, boot->reg_id_aa64isar2);
 
 	/*
 	 * Differing PARange support is fine as long as all peripherals and
@@ -721,9 +756,6 @@
 	taint |= check_update_ftr_reg(SYS_ID_AA64MMFR2_EL1, cpu,
 				      info->reg_id_aa64mmfr2, boot->reg_id_aa64mmfr2);
 
-	/*
-	 * EL3 is not our concern.
-	 */
 	taint |= check_update_ftr_reg(SYS_ID_AA64PFR0_EL1, cpu,
 				      info->reg_id_aa64pfr0, boot->reg_id_aa64pfr0);
 	taint |= check_update_ftr_reg(SYS_ID_AA64PFR1_EL1, cpu,
@@ -845,6 +877,7 @@
 	read_sysreg_case(SYS_ID_AA64MMFR2_EL1);
 	read_sysreg_case(SYS_ID_AA64ISAR0_EL1);
 	read_sysreg_case(SYS_ID_AA64ISAR1_EL1);
+	read_sysreg_case(SYS_ID_AA64ISAR2_EL1);
 
 	read_sysreg_case(SYS_CNTFRQ_EL0);
 	read_sysreg_case(SYS_CTR_EL0);
@@ -866,17 +899,39 @@
 	return val >= entry->min_field_value;
 }
 
-static bool
-has_cpuid_feature(const struct arm64_cpu_capabilities *entry, int scope)
+static u64
+read_scoped_sysreg(const struct arm64_cpu_capabilities *entry, int scope)
 {
-	u64 val;
-
 	WARN_ON(scope == SCOPE_LOCAL_CPU && preemptible());
 	if (scope == SCOPE_SYSTEM)
-		val = read_sanitised_ftr_reg(entry->sys_reg);
+		return read_sanitised_ftr_reg(entry->sys_reg);
 	else
-		val = __read_sysreg_by_encoding(entry->sys_reg);
+		return __read_sysreg_by_encoding(entry->sys_reg);
+}
+
+static bool
+has_user_cpuid_feature(const struct arm64_cpu_capabilities *entry, int scope)
+{
+	int mask;
+	struct arm64_ftr_reg *regp;
+	u64 val = read_scoped_sysreg(entry, scope);
+
+	regp = get_arm64_ftr_reg(entry->sys_reg);
+	if (!regp)
+		return false;
+
+	mask = cpuid_feature_extract_unsigned_field(regp->user_mask,
+						    entry->field_pos);
+	if (!mask)
+		return false;
+
+	return feature_matches(val, entry);
+}
 
+static bool
+has_cpuid_feature(const struct arm64_cpu_capabilities *entry, int scope)
+{
+	u64 val = read_scoped_sysreg(entry, scope);
 	return feature_matches(val, entry);
 }
 
@@ -1045,6 +1100,12 @@
 	static bool kpti_applied = false;
 	int cpu = smp_processor_id();
 
+	if (__this_cpu_read(this_cpu_vector) == vectors) {
+		const char *v = arm64_get_bp_hardening_vector(EL1_VECTOR_KPTI);
+
+		__this_cpu_write(this_cpu_vector, v);
+	}
+
 	/*
 	 * We don't need to rewrite the page-tables if either we've done
 	 * it already or we have KASLR enabled and therefore have not
@@ -1098,7 +1159,7 @@
 	/* List of CPUs which have broken DBM support. */
 	static const struct midr_range cpus[] = {
 #ifdef CONFIG_ARM64_ERRATUM_1024718
-		MIDR_RANGE(MIDR_CORTEX_A55, 0, 0, 1, 0),  // A55 r0p0 -r1p0
+		MIDR_ALL_VERSIONS(MIDR_CORTEX_A55),
 #endif
 		{},
 	};
@@ -1266,6 +1327,25 @@
 }
 #endif
 
+static void user_feature_fixup(void)
+{
+	if (cpus_have_cap(ARM64_WORKAROUND_SPECULATIVE_SSBS)) {
+		struct arm64_ftr_reg *regp;
+
+		regp = get_arm64_ftr_reg(SYS_ID_AA64PFR1_EL1);
+		if (regp)
+			regp->user_mask &= ~GENMASK(7, 4); /* SSBS */
+	}
+}
+
+static void elf_hwcap_fixup(void)
+{
+#ifdef CONFIG_ARM64_ERRATUM_1742098
+	if (cpus_have_const_cap(ARM64_WORKAROUND_1742098))
+		compat_elf_hwcap2 &= ~COMPAT_HWCAP2_AES;
+#endif /* ARM64_ERRATUM_1742098 */
+}
+
 static const struct arm64_cpu_capabilities arm64_features[] = {
 	{
 		.desc = "GIC system register CPU interface",
@@ -1367,7 +1447,7 @@
 	{
 		/* FP/SIMD is not implemented */
 		.capability = ARM64_HAS_NO_FPSIMD,
-		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
+		.type = ARM64_CPUCAP_BOOT_RESTRICTED_CPU_LOCAL_FEATURE,
 		.min_field_value = 0,
 		.matches = has_no_fpsimd,
 	},
@@ -1570,7 +1650,7 @@
 };
 
 #define HWCAP_CPUID_MATCH(reg, field, s, min_value)				\
-		.matches = has_cpuid_feature,					\
+		.matches = has_user_cpuid_feature,				\
 		.sys_reg = reg,							\
 		.field_pos = field,						\
 		.sign = s,							\
@@ -1595,6 +1675,12 @@
 		.match_list = list,						\
 	}
 
+#define HWCAP_CAP_MATCH(match, cap_type, cap)					\
+	{									\
+		__HWCAP_CAP(#cap, cap_type, cap)				\
+		.matches = match,						\
+	}
+
 #ifdef CONFIG_ARM64_PTR_AUTH
 static const struct arm64_cpu_capabilities ptr_auth_hwcap_addr_matches[] = {
 	{
@@ -1668,8 +1754,35 @@
 	{},
 };
 
+#ifdef CONFIG_COMPAT
+static bool compat_has_neon(const struct arm64_cpu_capabilities *cap, int scope)
+{
+	/*
+	 * Check that all of MVFR1_EL1.{SIMDSP, SIMDInt, SIMDLS} are available,
+	 * in line with that of arm32 as in vfp_init(). We make sure that the
+	 * check is future proof, by making sure value is non-zero.
+	 */
+	u32 mvfr1;
+
+	WARN_ON(scope == SCOPE_LOCAL_CPU && preemptible());
+	if (scope == SCOPE_SYSTEM)
+		mvfr1 = read_sanitised_ftr_reg(SYS_MVFR1_EL1);
+	else
+		mvfr1 = read_sysreg_s(SYS_MVFR1_EL1);
+
+	return cpuid_feature_extract_unsigned_field(mvfr1, MVFR1_SIMDSP_SHIFT) &&
+		cpuid_feature_extract_unsigned_field(mvfr1, MVFR1_SIMDINT_SHIFT) &&
+		cpuid_feature_extract_unsigned_field(mvfr1, MVFR1_SIMDLS_SHIFT);
+}
+#endif
+
 static const struct arm64_cpu_capabilities compat_elf_hwcaps[] = {
 #ifdef CONFIG_COMPAT
+	HWCAP_CAP_MATCH(compat_has_neon, CAP_COMPAT_HWCAP, COMPAT_HWCAP_NEON),
+	HWCAP_CAP(SYS_MVFR1_EL1, MVFR1_SIMDFMAC_SHIFT, FTR_UNSIGNED, 1, CAP_COMPAT_HWCAP, COMPAT_HWCAP_VFPv4),
+	/* Arm v8 mandates MVFR0.FPDP == {0, 2}. So, piggy back on this for the presence of VFP support */
+	HWCAP_CAP(SYS_MVFR0_EL1, MVFR0_FPDP_SHIFT, FTR_UNSIGNED, 2, CAP_COMPAT_HWCAP, COMPAT_HWCAP_VFP),
+	HWCAP_CAP(SYS_MVFR0_EL1, MVFR0_FPDP_SHIFT, FTR_UNSIGNED, 2, CAP_COMPAT_HWCAP, COMPAT_HWCAP_VFPv3),
 	HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_AES_SHIFT, FTR_UNSIGNED, 2, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_PMULL),
 	HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_AES_SHIFT, FTR_UNSIGNED, 1, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_AES),
 	HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_SHA1_SHIFT, FTR_UNSIGNED, 1, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_SHA1),
@@ -2054,10 +2167,13 @@
 
 	setup_system_capabilities();
 	mark_const_caps_ready();
+	user_feature_fixup();
 	setup_elf_hwcaps(arm64_elf_hwcaps);
 
-	if (system_supports_32bit_el0())
+	if (system_supports_32bit_el0()) {
 		setup_elf_hwcaps(compat_elf_hwcaps);
+		elf_hwcap_fixup();
+	}
 
 	if (system_uses_ttbr0_pan())
 		pr_info("emulated: Privileged Access Never (PAN) using TTBR0_EL1 switching\n");
@@ -2090,7 +2206,7 @@
 
 /*
  * We emulate only the following system register space.
- * Op0 = 0x3, CRn = 0x0, Op1 = 0x0, CRm = [0, 4 - 7]
+ * Op0 = 0x3, CRn = 0x0, Op1 = 0x0, CRm = [0, 2 - 7]
  * See Table C5-6 System instruction encodings for System register accesses,
  * ARMv8 ARM(ARM DDI 0487A.f) for more details.
  */
@@ -2100,7 +2216,7 @@
 		sys_reg_CRn(id) == 0x0 &&
 		sys_reg_Op1(id) == 0x0 &&
 		(sys_reg_CRm(id) == 0 ||
-		 ((sys_reg_CRm(id) >= 4) && (sys_reg_CRm(id) <= 7))));
+		 ((sys_reg_CRm(id) >= 2) && (sys_reg_CRm(id) <= 7))));
 }
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/cpuidle.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/cpuidle.c
@@ -53,6 +53,9 @@
 	struct acpi_lpi_state *lpi;
 	struct acpi_processor *pr = per_cpu(processors, cpu);
 
+	if (unlikely(!pr || !pr->flags.has_lpi))
+		return -EINVAL;
+
 	/*
 	 * If the PSCI cpu_suspend function hook has not been initialized
 	 * idle states must not be enabled, so bail out
@@ -60,9 +63,6 @@
 	if (!psci_ops.cpu_suspend)
 		return -EOPNOTSUPP;
 
-	if (unlikely(!pr || !pr->flags.has_lpi))
-		return -EINVAL;
-
 	count = pr->power.count - 1;
 	if (count <= 0)
 		return -ENODEV;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/cpuinfo.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/cpuinfo.c
@@ -344,6 +344,7 @@
 	info->reg_id_aa64dfr1 = read_cpuid(ID_AA64DFR1_EL1);
 	info->reg_id_aa64isar0 = read_cpuid(ID_AA64ISAR0_EL1);
 	info->reg_id_aa64isar1 = read_cpuid(ID_AA64ISAR1_EL1);
+	info->reg_id_aa64isar2 = read_cpuid(ID_AA64ISAR2_EL1);
 	info->reg_id_aa64mmfr0 = read_cpuid(ID_AA64MMFR0_EL1);
 	info->reg_id_aa64mmfr1 = read_cpuid(ID_AA64MMFR1_EL1);
 	info->reg_id_aa64mmfr2 = read_cpuid(ID_AA64MMFR2_EL1);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/crash_core.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/crash_core.c
@@ -6,6 +6,14 @@
 
 #include <linux/crash_core.h>
 #include <asm/memory.h>
+#include <asm/pgtable-hwdef.h>
+
+static inline u64 get_tcr_el1_t1sz(void);
+
+static inline u64 get_tcr_el1_t1sz(void)
+{
+	return (read_sysreg(tcr_el1) & TCR_T1SZ_MASK) >> TCR_T1SZ_OFFSET;
+}
 
 void arch_crash_save_vmcoreinfo(void)
 {
@@ -15,5 +23,7 @@
 						kimage_voffset);
 	vmcoreinfo_append_str("NUMBER(PHYS_OFFSET)=0x%llx\n",
 						PHYS_OFFSET);
+	vmcoreinfo_append_str("NUMBER(TCR_EL1_T1SZ)=0x%llx\n",
+						get_tcr_el1_t1sz());
 	vmcoreinfo_append_str("KERNELOFFSET=%lx\n", kaslr_offset());
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/crash_dump.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/crash_dump.c
@@ -64,5 +64,7 @@
 ssize_t elfcorehdr_read(char *buf, size_t count, u64 *ppos)
 {
 	memcpy(buf, phys_to_virt((phys_addr_t)*ppos), count);
+	*ppos += count;
+
 	return count;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/debug-monitors.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/debug-monitors.c
@@ -141,17 +141,20 @@
 /*
  * Single step API and exception handling.
  */
-static void set_regs_spsr_ss(struct pt_regs *regs)
+static void set_user_regs_spsr_ss(struct user_pt_regs *regs)
 {
 	regs->pstate |= DBG_SPSR_SS;
 }
-NOKPROBE_SYMBOL(set_regs_spsr_ss);
+NOKPROBE_SYMBOL(set_user_regs_spsr_ss);
 
-static void clear_regs_spsr_ss(struct pt_regs *regs)
+static void clear_user_regs_spsr_ss(struct user_pt_regs *regs)
 {
 	regs->pstate &= ~DBG_SPSR_SS;
 }
-NOKPROBE_SYMBOL(clear_regs_spsr_ss);
+NOKPROBE_SYMBOL(clear_user_regs_spsr_ss);
+
+#define set_regs_spsr_ss(r)	set_user_regs_spsr_ss(&(r)->user_regs)
+#define clear_regs_spsr_ss(r)	clear_user_regs_spsr_ss(&(r)->user_regs)
 
 static DEFINE_SPINLOCK(debug_hook_lock);
 static LIST_HEAD(user_step_hook);
@@ -393,17 +396,26 @@
 	 * If single step is active for this thread, then set SPSR.SS
 	 * to 1 to avoid returning to the active-pending state.
 	 */
-	if (test_ti_thread_flag(task_thread_info(task), TIF_SINGLESTEP))
+	if (test_tsk_thread_flag(task, TIF_SINGLESTEP))
 		set_regs_spsr_ss(task_pt_regs(task));
 }
 NOKPROBE_SYMBOL(user_rewind_single_step);
 
 void user_fastforward_single_step(struct task_struct *task)
 {
-	if (test_ti_thread_flag(task_thread_info(task), TIF_SINGLESTEP))
+	if (test_tsk_thread_flag(task, TIF_SINGLESTEP))
 		clear_regs_spsr_ss(task_pt_regs(task));
 }
 
+void user_regs_reset_single_step(struct user_pt_regs *regs,
+				 struct task_struct *task)
+{
+	if (test_tsk_thread_flag(task, TIF_SINGLESTEP))
+		set_user_regs_spsr_ss(regs);
+	else
+		clear_user_regs_spsr_ss(regs);
+}
+
 /* Kernel API */
 void kernel_enable_single_step(struct pt_regs *regs)
 {
@@ -429,6 +441,11 @@
 }
 NOKPROBE_SYMBOL(kernel_active_single_step);
 
+void kernel_rewind_single_step(struct pt_regs *regs)
+{
+	set_regs_spsr_ss(regs);
+}
+
 /* ptrace API */
 void user_enable_single_step(struct task_struct *task)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/efi.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/efi.c
@@ -12,6 +12,14 @@
 
 #include <asm/efi.h>
 
+static bool region_is_misaligned(const efi_memory_desc_t *md)
+{
+	if (PAGE_SIZE == EFI_PAGE_SIZE)
+		return false;
+	return !PAGE_ALIGNED(md->phys_addr) ||
+	       !PAGE_ALIGNED(md->num_pages << EFI_PAGE_SHIFT);
+}
+
 /*
  * Only regions of type EFI_RUNTIME_SERVICES_CODE need to be
  * executable, everything else can be mapped with the XN bits
@@ -25,14 +33,22 @@
 	if (type == EFI_MEMORY_MAPPED_IO)
 		return PROT_DEVICE_nGnRE;
 
-	if (WARN_ONCE(!PAGE_ALIGNED(md->phys_addr),
-		      "UEFI Runtime regions are not aligned to 64 KB -- buggy firmware?"))
+	if (region_is_misaligned(md)) {
+		static bool __initdata code_is_misaligned;
+
 		/*
-		 * If the region is not aligned to the page size of the OS, we
-		 * can not use strict permissions, since that would also affect
-		 * the mapping attributes of the adjacent regions.
+		 * Regions that are not aligned to the OS page size cannot be
+		 * mapped with strict permissions, as those might interfere
+		 * with the permissions that are needed by the adjacent
+		 * region's mapping. However, if we haven't encountered any
+		 * misaligned runtime code regions so far, we can safely use
+		 * non-executable permissions for non-code regions.
 		 */
-		return pgprot_val(PAGE_KERNEL_EXEC);
+		code_is_misaligned |= (type == EFI_RUNTIME_SERVICES_CODE);
+
+		return code_is_misaligned ? pgprot_val(PAGE_KERNEL_EXEC)
+					  : pgprot_val(PAGE_KERNEL);
+	}
 
 	/* R-- */
 	if ((attr & (EFI_MEMORY_XP | EFI_MEMORY_RO)) ==
@@ -62,19 +78,16 @@
 	bool page_mappings_only = (md->type == EFI_RUNTIME_SERVICES_CODE ||
 				   md->type == EFI_RUNTIME_SERVICES_DATA);
 
-	if (!PAGE_ALIGNED(md->phys_addr) ||
-	    !PAGE_ALIGNED(md->num_pages << EFI_PAGE_SHIFT)) {
-		/*
-		 * If the end address of this region is not aligned to page
-		 * size, the mapping is rounded up, and may end up sharing a
-		 * page frame with the next UEFI memory region. If we create
-		 * a block entry now, we may need to split it again when mapping
-		 * the next region, and support for that is going to be removed
-		 * from the MMU routines. So avoid block mappings altogether in
-		 * that case.
-		 */
+	/*
+	 * If this region is not aligned to the page size used by the OS, the
+	 * mapping will be rounded outwards, and may end up sharing a page
+	 * frame with an adjacent runtime memory region. Given that the page
+	 * table descriptor covering the shared page will be rewritten when the
+	 * adjacent region gets mapped, we must avoid block mappings here so we
+	 * don't have to worry about splitting them when that happens.
+	 */
+	if (region_is_misaligned(md))
 		page_mappings_only = true;
-	}
 
 	create_pgd_mapping(mm, md->phys_addr, md->virt_addr,
 			   md->num_pages << EFI_PAGE_SHIFT,
@@ -101,6 +114,9 @@
 	BUG_ON(md->type != EFI_RUNTIME_SERVICES_CODE &&
 	       md->type != EFI_RUNTIME_SERVICES_DATA);
 
+	if (region_is_misaligned(md))
+		return 0;
+
 	/*
 	 * Calling apply_to_page_range() is only safe on regions that are
 	 * guaranteed to be mapped down to pages. Since we are only called
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/entry.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/entry.S
@@ -59,18 +59,21 @@
 
 	.macro kernel_ventry, el, label, regsize = 64
 	.align 7
-#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
-alternative_if ARM64_UNMAP_KERNEL_AT_EL0
+.Lventry_start\@:
 	.if	\el == 0
+	/*
+	 * This must be the first instruction of the EL0 vector entries. It is
+	 * skipped by the trampoline vectors, to trigger the cleanup.
+	 */
+	b	.Lskip_tramp_vectors_cleanup\@
 	.if	\regsize == 64
 	mrs	x30, tpidrro_el0
 	msr	tpidrro_el0, xzr
 	.else
 	mov	x30, xzr
 	.endif
+.Lskip_tramp_vectors_cleanup\@:
 	.endif
-alternative_else_nop_endif
-#endif
 
 	sub	sp, sp, #S_FRAME_SIZE
 #ifdef CONFIG_VMAP_STACK
@@ -116,11 +119,15 @@
 	mrs	x0, tpidrro_el0
 #endif
 	b	el\()\el\()_\label
+.org .Lventry_start\@ + 128	// Did we overflow the ventry slot?
 	.endm
 
-	.macro tramp_alias, dst, sym
+	.macro tramp_alias, dst, sym, tmp
 	mov_q	\dst, TRAMP_VALIAS
-	add	\dst, \dst, #(\sym - .entry.tramp.text)
+	adr_l	\tmp, \sym
+	add	\dst, \dst, \tmp
+	adr_l	\tmp, .entry.tramp.text
+	sub	\dst, \dst, \tmp
 	.endm
 
 	// This macro corrupts x0-x3. It is the caller's duty
@@ -361,21 +368,25 @@
 	ldp	x24, x25, [sp, #16 * 12]
 	ldp	x26, x27, [sp, #16 * 13]
 	ldp	x28, x29, [sp, #16 * 14]
-	ldr	lr, [sp, #S_LR]
-	add	sp, sp, #S_FRAME_SIZE		// restore sp
 
 	.if	\el == 0
-alternative_insn eret, nop, ARM64_UNMAP_KERNEL_AT_EL0
+alternative_if_not ARM64_UNMAP_KERNEL_AT_EL0
+	ldr	lr, [sp, #S_LR]
+	add	sp, sp, #S_FRAME_SIZE		// restore sp
+	eret
+alternative_else_nop_endif
 #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
 	bne	5f
-	msr	far_el1, x30
-	tramp_alias	x30, tramp_exit_native
+	msr	far_el1, x29
+	tramp_alias	x30, tramp_exit_native, x29
 	br	x30
 5:
-	tramp_alias	x30, tramp_exit_compat
+	tramp_alias	x30, tramp_exit_compat, x29
 	br	x30
 #endif
 	.else
+	ldr	lr, [sp, #S_LR]
+	add	sp, sp, #S_FRAME_SIZE		// restore sp
 	eret
 	.endif
 	sb
@@ -1012,15 +1023,10 @@
 
 	.popsection				// .entry.text
 
-#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
-/*
- * Exception vectors trampoline.
- */
-	.pushsection ".entry.tramp.text", "ax"
-
+	// Move from tramp_pg_dir to swapper_pg_dir
 	.macro tramp_map_kernel, tmp
 	mrs	\tmp, ttbr1_el1
-	add	\tmp, \tmp, #(PAGE_SIZE + RESERVED_TTBR0_SIZE)
+	add	\tmp, \tmp, #(2 * PAGE_SIZE)
 	bic	\tmp, \tmp, #USER_ASID_FLAG
 	msr	ttbr1_el1, \tmp
 #ifdef CONFIG_QCOM_FALKOR_ERRATUM_1003
@@ -1037,9 +1043,10 @@
 #endif /* CONFIG_QCOM_FALKOR_ERRATUM_1003 */
 	.endm
 
+	// Move from swapper_pg_dir to tramp_pg_dir
 	.macro tramp_unmap_kernel, tmp
 	mrs	\tmp, ttbr1_el1
-	sub	\tmp, \tmp, #(PAGE_SIZE + RESERVED_TTBR0_SIZE)
+	sub	\tmp, \tmp, #(2 * PAGE_SIZE)
 	orr	\tmp, \tmp, #USER_ASID_FLAG
 	msr	ttbr1_el1, \tmp
 	/*
@@ -1049,12 +1056,47 @@
 	 */
 	.endm
 
-	.macro tramp_ventry, regsize = 64
+	.macro tramp_data_page	dst
+	adr_l	\dst, .entry.tramp.text
+	sub	\dst, \dst, PAGE_SIZE
+	.endm
+
+	.macro tramp_data_read_var	dst, var
+#ifdef CONFIG_RANDOMIZE_BASE
+	tramp_data_page		\dst
+	add	\dst, \dst, #:lo12:__entry_tramp_data_\var
+	ldr	\dst, [\dst]
+#else
+	ldr	\dst, =\var
+#endif
+	.endm
+
+#define BHB_MITIGATION_NONE	0
+#define BHB_MITIGATION_LOOP	1
+#define BHB_MITIGATION_FW	2
+#define BHB_MITIGATION_INSN	3
+
+	.macro tramp_ventry, vector_start, regsize, kpti, bhb
 	.align	7
 1:
 	.if	\regsize == 64
 	msr	tpidrro_el0, x30	// Restored in kernel_ventry
 	.endif
+
+	.if	\bhb == BHB_MITIGATION_LOOP
+	/*
+	 * This sequence must appear before the first indirect branch. i.e. the
+	 * ret out of tramp_ventry. It appears here because x30 is free.
+	 */
+	__mitigate_spectre_bhb_loop	x30
+	.endif // \bhb == BHB_MITIGATION_LOOP
+
+	.if	\bhb == BHB_MITIGATION_INSN
+	clearbhb
+	isb
+	.endif // \bhb == BHB_MITIGATION_INSN
+
+	.if	\kpti == 1
 	/*
 	 * Defend against branch aliasing attacks by pushing a dummy
 	 * entry onto the return stack and using a RET instruction to
@@ -1064,46 +1106,79 @@
 	b	.
 2:
 	tramp_map_kernel	x30
-#ifdef CONFIG_RANDOMIZE_BASE
-	adr	x30, tramp_vectors + PAGE_SIZE
 alternative_insn isb, nop, ARM64_WORKAROUND_QCOM_FALKOR_E1003
-	ldr	x30, [x30]
-#else
-	ldr	x30, =vectors
-#endif
+	tramp_data_read_var	x30, vectors
 alternative_if_not ARM64_WORKAROUND_CAVIUM_TX2_219_PRFM
-	prfm	plil1strm, [x30, #(1b - tramp_vectors)]
+	prfm	plil1strm, [x30, #(1b - \vector_start)]
 alternative_else_nop_endif
+
 	msr	vbar_el1, x30
-	add	x30, x30, #(1b - tramp_vectors)
 	isb
+	.else
+	ldr	x30, =vectors
+	.endif // \kpti == 1
+
+	.if	\bhb == BHB_MITIGATION_FW
+	/*
+	 * The firmware sequence must appear before the first indirect branch.
+	 * i.e. the ret out of tramp_ventry. But it also needs the stack to be
+	 * mapped to save/restore the registers the SMC clobbers.
+	 */
+	__mitigate_spectre_bhb_fw
+	.endif // \bhb == BHB_MITIGATION_FW
+
+	add	x30, x30, #(1b - \vector_start + 4)
 	ret
+.org 1b + 128	// Did we overflow the ventry slot?
 	.endm
 
 	.macro tramp_exit, regsize = 64
-	adr	x30, tramp_vectors
+	tramp_data_read_var	x30, this_cpu_vector
+alternative_if_not ARM64_HAS_VIRT_HOST_EXTN
+	mrs	x29, tpidr_el1
+alternative_else
+	mrs	x29, tpidr_el2
+alternative_endif
+	ldr	x30, [x30, x29]
+
 	msr	vbar_el1, x30
-	tramp_unmap_kernel	x30
+	ldr	lr, [sp, #S_LR]
+	tramp_unmap_kernel	x29
 	.if	\regsize == 64
-	mrs	x30, far_el1
+	mrs	x29, far_el1
 	.endif
+	add	sp, sp, #S_FRAME_SIZE		// restore sp
 	eret
 	sb
 	.endm
 
-	.align	11
-ENTRY(tramp_vectors)
+	.macro	generate_tramp_vector,	kpti, bhb
+.Lvector_start\@:
 	.space	0x400
 
-	tramp_ventry
-	tramp_ventry
-	tramp_ventry
-	tramp_ventry
-
-	tramp_ventry	32
-	tramp_ventry	32
-	tramp_ventry	32
-	tramp_ventry	32
+	.rept	4
+	tramp_ventry	.Lvector_start\@, 64, \kpti, \bhb
+	.endr
+	.rept	4
+	tramp_ventry	.Lvector_start\@, 32, \kpti, \bhb
+	.endr
+	.endm
+
+#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
+/*
+ * Exception vectors trampoline.
+ * The order must match __bp_harden_el1_vectors and the
+ * arm64_bp_harden_el1_vectors enum.
+ */
+	.pushsection ".entry.tramp.text", "ax"
+	.align	11
+ENTRY(tramp_vectors)
+#ifdef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY
+	generate_tramp_vector	kpti=1, bhb=BHB_MITIGATION_LOOP
+	generate_tramp_vector	kpti=1, bhb=BHB_MITIGATION_FW
+	generate_tramp_vector	kpti=1, bhb=BHB_MITIGATION_INSN
+#endif /* CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */
+	generate_tramp_vector	kpti=1, bhb=BHB_MITIGATION_NONE
 END(tramp_vectors)
 
 ENTRY(tramp_exit_native)
@@ -1121,12 +1196,56 @@
 	.align PAGE_SHIFT
 	.globl	__entry_tramp_data_start
 __entry_tramp_data_start:
+__entry_tramp_data_vectors:
 	.quad	vectors
+#ifdef CONFIG_ARM_SDE_INTERFACE
+__entry_tramp_data___sdei_asm_handler:
+	.quad	__sdei_asm_handler
+#endif /* CONFIG_ARM_SDE_INTERFACE */
+__entry_tramp_data_this_cpu_vector:
+	.quad	this_cpu_vector
 	.popsection				// .rodata
 #endif /* CONFIG_RANDOMIZE_BASE */
 #endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */
 
 /*
+ * Exception vectors for spectre mitigations on entry from EL1 when
+ * kpti is not in use.
+ */
+	.macro generate_el1_vector, bhb
+.Lvector_start\@:
+	kernel_ventry	1, sync_invalid			// Synchronous EL1t
+	kernel_ventry	1, irq_invalid			// IRQ EL1t
+	kernel_ventry	1, fiq_invalid			// FIQ EL1t
+	kernel_ventry	1, error_invalid		// Error EL1t
+
+	kernel_ventry	1, sync				// Synchronous EL1h
+	kernel_ventry	1, irq				// IRQ EL1h
+	kernel_ventry	1, fiq_invalid			// FIQ EL1h
+	kernel_ventry	1, error			// Error EL1h
+
+	.rept	4
+	tramp_ventry	.Lvector_start\@, 64, 0, \bhb
+	.endr
+	.rept 4
+	tramp_ventry	.Lvector_start\@, 32, 0, \bhb
+	.endr
+	.endm
+
+/* The order must match tramp_vecs and the arm64_bp_harden_el1_vectors enum. */
+	.pushsection ".entry.text", "ax"
+	.align	11
+SYM_CODE_START(__bp_harden_el1_vectors)
+#ifdef CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY
+	generate_el1_vector	bhb=BHB_MITIGATION_LOOP
+	generate_el1_vector	bhb=BHB_MITIGATION_FW
+	generate_el1_vector	bhb=BHB_MITIGATION_INSN
+#endif /* CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY */
+SYM_CODE_END(__bp_harden_el1_vectors)
+	.popsection
+
+
+/*
  * Register switch for AArch64. The callee-saved registers need to be saved
  * and restored. On entry:
  *   x0 = previous task_struct (must be preserved across the switch)
@@ -1212,13 +1331,7 @@
 	 */
 1:	str	x4, [x1, #(SDEI_EVENT_INTREGS + S_ORIG_ADDR_LIMIT)]
 
-#ifdef CONFIG_RANDOMIZE_BASE
-	adr	x4, tramp_vectors + PAGE_SIZE
-	add	x4, x4, #:lo12:__sdei_asm_trampoline_next_handler
-	ldr	x4, [x4]
-#else
-	ldr	x4, =__sdei_asm_handler
-#endif
+	tramp_data_read_var     x4, __sdei_asm_handler
 	br	x4
 ENDPROC(__sdei_asm_entry_trampoline)
 NOKPROBE(__sdei_asm_entry_trampoline)
@@ -1241,12 +1354,6 @@
 NOKPROBE(__sdei_asm_exit_trampoline)
 	.ltorg
 .popsection		// .entry.tramp.text
-#ifdef CONFIG_RANDOMIZE_BASE
-.pushsection ".rodata", "a"
-__sdei_asm_trampoline_next_handler:
-	.quad	__sdei_asm_handler
-.popsection		// .rodata
-#endif /* CONFIG_RANDOMIZE_BASE */
 #endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */
 
 /*
@@ -1342,7 +1449,7 @@
 alternative_else_nop_endif
 
 #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
-	tramp_alias	dst=x5, sym=__sdei_asm_exit_trampoline
+	tramp_alias	dst=x5, sym=__sdei_asm_exit_trampoline, tmp=x3
 	br	x5
 #endif
 ENDPROC(__sdei_asm_handler)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/fpsimd.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/fpsimd.c
@@ -269,6 +269,7 @@
  */
 static void task_fpsimd_load(void)
 {
+	WARN_ON(!system_supports_fpsimd());
 	WARN_ON(!have_cpu_fpsimd_context());
 
 	if (system_supports_sve() && test_thread_flag(TIF_SVE))
@@ -289,6 +290,7 @@
 		this_cpu_ptr(&fpsimd_last_state);
 	/* set by fpsimd_bind_task_to_cpu() or fpsimd_bind_state_to_cpu() */
 
+	WARN_ON(!system_supports_fpsimd());
 	WARN_ON(!have_cpu_fpsimd_context());
 
 	if (!test_thread_flag(TIF_FOREIGN_FPSTATE)) {
@@ -336,7 +338,7 @@
 	return sve_vl_from_vq(__bit_to_vq(bit));
 }
 
-#ifdef CONFIG_SYSCTL
+#if defined(CONFIG_ARM64_SVE) && defined(CONFIG_SYSCTL)
 
 static int sve_proc_do_default_vl(struct ctl_table *table, int write,
 				  void __user *buffer, size_t *lenp,
@@ -382,9 +384,9 @@
 	return 0;
 }
 
-#else /* ! CONFIG_SYSCTL */
+#else /* ! (CONFIG_ARM64_SVE && CONFIG_SYSCTL) */
 static int __init sve_sysctl_init(void) { return 0; }
-#endif /* ! CONFIG_SYSCTL */
+#endif /* ! (CONFIG_ARM64_SVE && CONFIG_SYSCTL) */
 
 #define ZREG(sve_state, vq, n) ((char *)(sve_state) +		\
 	(SVE_SIG_ZREG_OFFSET(vq, n) - SVE_SIG_REGS_OFFSET))
@@ -496,7 +498,7 @@
 void sve_alloc(struct task_struct *task)
 {
 	if (task->thread.sve_state) {
-		memset(task->thread.sve_state, 0, sve_state_size(current));
+		memset(task->thread.sve_state, 0, sve_state_size(task));
 		return;
 	}
 
@@ -1092,6 +1094,7 @@
 	struct fpsimd_last_state_struct *last =
 		this_cpu_ptr(&fpsimd_last_state);
 
+	WARN_ON(!system_supports_fpsimd());
 	last->st = &current->thread.uw.fpsimd_state;
 	last->sve_state = current->thread.sve_state;
 	last->sve_vl = current->thread.sve_vl;
@@ -1114,6 +1117,7 @@
 	struct fpsimd_last_state_struct *last =
 		this_cpu_ptr(&fpsimd_last_state);
 
+	WARN_ON(!system_supports_fpsimd());
 	WARN_ON(!in_softirq() && !irqs_disabled());
 
 	last->st = st;
@@ -1128,8 +1132,19 @@
  */
 void fpsimd_restore_current_state(void)
 {
-	if (!system_supports_fpsimd())
+	/*
+	 * For the tasks that were created before we detected the absence of
+	 * FP/SIMD, the TIF_FOREIGN_FPSTATE could be set via fpsimd_thread_switch(),
+	 * e.g, init. This could be then inherited by the children processes.
+	 * If we later detect that the system doesn't support FP/SIMD,
+	 * we must clear the flag for  all the tasks to indicate that the
+	 * FPSTATE is clean (as we can't have one) to avoid looping for ever in
+	 * do_notify_resume().
+	 */
+	if (!system_supports_fpsimd()) {
+		clear_thread_flag(TIF_FOREIGN_FPSTATE);
 		return;
+	}
 
 	get_cpu_fpsimd_context();
 
@@ -1148,7 +1163,7 @@
  */
 void fpsimd_update_current_state(struct user_fpsimd_state const *state)
 {
-	if (!system_supports_fpsimd())
+	if (WARN_ON(!system_supports_fpsimd()))
 		return;
 
 	get_cpu_fpsimd_context();
@@ -1179,7 +1194,13 @@
 void fpsimd_flush_task_state(struct task_struct *t)
 {
 	t->thread.fpsimd_cpu = NR_CPUS;
-
+	/*
+	 * If we don't support fpsimd, bail out after we have
+	 * reset the fpsimd_cpu for this task and clear the
+	 * FPSTATE.
+	 */
+	if (!system_supports_fpsimd())
+		return;
 	barrier();
 	set_tsk_thread_flag(t, TIF_FOREIGN_FPSTATE);
 
@@ -1193,6 +1214,7 @@
  */
 static void fpsimd_flush_cpu_state(void)
 {
+	WARN_ON(!system_supports_fpsimd());
 	__this_cpu_write(fpsimd_last_state.st, NULL);
 	set_thread_flag(TIF_FOREIGN_FPSTATE);
 }
@@ -1203,6 +1225,8 @@
  */
 void fpsimd_save_and_flush_cpu_state(void)
 {
+	if (!system_supports_fpsimd())
+		return;
 	WARN_ON(preemptible());
 	__get_cpu_fpsimd_context();
 	fpsimd_save();
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/ftrace.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/ftrace.c
@@ -69,14 +69,26 @@
 {
 	unsigned long pc = rec->ip;
 	u32 old, new;
-	long offset = (long)pc - (long)addr;
+	long offset = (long)addr - (long)pc;
 
 	if (offset < -SZ_128M || offset >= SZ_128M) {
 #ifdef CONFIG_ARM64_MODULE_PLTS
-		struct plt_entry trampoline, *dst;
 		struct module *mod;
 
 		/*
+		 * There is only one ftrace trampoline per module. For now,
+		 * this is not a problem since on arm64, all dynamic ftrace
+		 * invocations are routed via ftrace_caller(). This will need
+		 * to be revisited if support for multiple ftrace entry points
+		 * is added in the future, but for now, the pr_err() below
+		 * deals with a theoretical issue only.
+		 */
+		if (addr != FTRACE_ADDR) {
+			pr_err("ftrace: far branches to multiple entry points unsupported inside a single module\n");
+			return -EINVAL;
+		}
+
+		/*
 		 * On kernels that support module PLTs, the offset between the
 		 * branch instruction and its target may legally exceed the
 		 * range of an ordinary relative 'bl' opcode. In this case, we
@@ -93,46 +105,7 @@
 		if (WARN_ON(!mod))
 			return -EINVAL;
 
-		/*
-		 * There is only one ftrace trampoline per module. For now,
-		 * this is not a problem since on arm64, all dynamic ftrace
-		 * invocations are routed via ftrace_caller(). This will need
-		 * to be revisited if support for multiple ftrace entry points
-		 * is added in the future, but for now, the pr_err() below
-		 * deals with a theoretical issue only.
-		 *
-		 * Note that PLTs are place relative, and plt_entries_equal()
-		 * checks whether they point to the same target. Here, we need
-		 * to check if the actual opcodes are in fact identical,
-		 * regardless of the offset in memory so use memcmp() instead.
-		 */
-		dst = mod->arch.ftrace_trampoline;
-		trampoline = get_plt_entry(addr, dst);
-		if (memcmp(dst, &trampoline, sizeof(trampoline))) {
-			if (plt_entry_is_initialized(dst)) {
-				pr_err("ftrace: far branches to multiple entry points unsupported inside a single module\n");
-				return -EINVAL;
-			}
-
-			/* point the trampoline to our ftrace entry point */
-			module_disable_ro(mod);
-			*dst = trampoline;
-			module_enable_ro(mod, true);
-
-			/*
-			 * Ensure updated trampoline is visible to instruction
-			 * fetch before we patch in the branch. Although the
-			 * architecture doesn't require an IPI in this case,
-			 * Neoverse-N1 erratum #1542419 does require one
-			 * if the TLB maintenance in module_enable_ro() is
-			 * skipped due to rodata_enabled. It doesn't seem worth
-			 * it to make it conditional given that this is
-			 * certainly not a fast-path.
-			 */
-			flush_icache_range((unsigned long)&dst[0],
-					   (unsigned long)&dst[1]);
-		}
-		addr = (unsigned long)dst;
+		addr = (unsigned long)mod->arch.ftrace_trampoline;
 #else /* CONFIG_ARM64_MODULE_PLTS */
 		return -EINVAL;
 #endif /* CONFIG_ARM64_MODULE_PLTS */
@@ -153,7 +126,7 @@
 	unsigned long pc = rec->ip;
 	bool validate = true;
 	u32 old = 0, new;
-	long offset = (long)pc - (long)addr;
+	long offset = (long)addr - (long)pc;
 
 	if (offset < -SZ_128M || offset >= SZ_128M) {
 #ifdef CONFIG_ARM64_MODULE_PLTS
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/head.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/head.S
@@ -194,7 +194,7 @@
  * to be composed of multiple pages. (This effectively scales the end index).
  *
  *	vstart:	virtual address of start of range
- *	vend:	virtual address of end of range
+ *	vend:	virtual address of end of range - we map [vstart, vend]
  *	shift:	shift used to transform virtual address into index
  *	ptrs:	number of entries in page table
  *	istart:	index in table corresponding to vstart
@@ -231,17 +231,18 @@
  *
  *	tbl:	location of page table
  *	rtbl:	address to be used for first level page table entry (typically tbl + PAGE_SIZE)
- *	vstart:	start address to map
- *	vend:	end address to map - we map [vstart, vend]
+ *	vstart:	virtual address of start of range
+ *	vend:	virtual address of end of range - we map [vstart, vend - 1]
  *	flags:	flags to use to map last level entries
  *	phys:	physical address corresponding to vstart - physical memory is contiguous
  *	pgds:	the number of pgd entries
  *
  * Temporaries:	istart, iend, tmp, count, sv - these need to be different registers
- * Preserves:	vstart, vend, flags
- * Corrupts:	tbl, rtbl, istart, iend, tmp, count, sv
+ * Preserves:	vstart, flags
+ * Corrupts:	tbl, rtbl, vend, istart, iend, tmp, count, sv
  */
 	.macro map_memory, tbl, rtbl, vstart, vend, flags, phys, pgds, istart, iend, tmp, count, sv
+	sub \vend, \vend, #1
 	add \rtbl, \tbl, #PAGE_SIZE
 	mov \sv, \rtbl
 	mov \count, #0
@@ -337,7 +338,7 @@
 	 */
 	adrp	x5, __idmap_text_end
 	clz	x5, x5
-	cmp	x5, TCR_T0SZ(VA_BITS)	// default T0SZ small enough?
+	cmp	x5, TCR_T0SZ(VA_BITS_MIN) // default T0SZ small enough?
 	b.ge	1f			// .. then skip VA range extension
 
 	adr_l	x6, idmap_t0sz
@@ -393,13 +394,19 @@
 
 	/*
 	 * Since the page tables have been populated with non-cacheable
-	 * accesses (MMU disabled), invalidate the idmap and swapper page
-	 * tables again to remove any speculatively loaded cache lines.
+	 * accesses (MMU disabled), invalidate those tables again to
+	 * remove any speculatively loaded cache lines.
 	 */
+	dmb	sy
+
 	adrp	x0, idmap_pg_dir
+	adrp	x1, idmap_pg_end
+	sub	x1, x1, x0
+	bl	__inval_dcache_area
+
+	adrp	x0, init_pg_dir
 	adrp	x1, init_pg_end
 	sub	x1, x1, x0
-	dmb	sy
 	bl	__inval_dcache_area
 
 	ret	x28
@@ -964,6 +971,7 @@
 
 	tlbi	vmalle1				// Remove any stale TLB entries
 	dsb	nsh
+	isb
 
 	msr	sctlr_el1, x19			// re-enable the MMU
 	isb
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/hw_breakpoint.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/hw_breakpoint.c
@@ -654,7 +654,7 @@
 		perf_bp_event(bp, regs);
 
 		/* Do we need to handle the stepping? */
-		if (is_default_overflow_handler(bp))
+		if (uses_default_overflow_handler(bp))
 			step = 1;
 unlock:
 		rcu_read_unlock();
@@ -730,6 +730,27 @@
 		return 0;
 }
 
+static int watchpoint_report(struct perf_event *wp, unsigned long addr,
+			     struct pt_regs *regs)
+{
+	int step = uses_default_overflow_handler(wp);
+	struct arch_hw_breakpoint *info = counter_arch_bp(wp);
+
+	info->trigger = addr;
+
+	/*
+	 * If we triggered a user watchpoint from a uaccess routine, then
+	 * handle the stepping ourselves since userspace really can't help
+	 * us with this.
+	 */
+	if (!user_mode(regs) && info->ctrl.privilege == AARCH64_BREAKPOINT_EL0)
+		step = 1;
+	else
+		perf_bp_event(wp, regs);
+
+	return step;
+}
+
 static int watchpoint_handler(unsigned long addr, unsigned int esr,
 			      struct pt_regs *regs)
 {
@@ -739,7 +760,6 @@
 	u64 val;
 	struct perf_event *wp, **slots;
 	struct debug_info *debug_info;
-	struct arch_hw_breakpoint *info;
 	struct arch_hw_breakpoint_ctrl ctrl;
 
 	slots = this_cpu_ptr(wp_on_reg);
@@ -777,25 +797,13 @@
 		if (dist != 0)
 			continue;
 
-		info = counter_arch_bp(wp);
-		info->trigger = addr;
-		perf_bp_event(wp, regs);
-
-		/* Do we need to handle the stepping? */
-		if (is_default_overflow_handler(wp))
-			step = 1;
+		step = watchpoint_report(wp, addr, regs);
 	}
-	if (min_dist > 0 && min_dist != -1) {
-		/* No exact match found. */
-		wp = slots[closest_match];
-		info = counter_arch_bp(wp);
-		info->trigger = addr;
-		perf_bp_event(wp, regs);
 
-		/* Do we need to handle the stepping? */
-		if (is_default_overflow_handler(wp))
-			step = 1;
-	}
+	/* No exact match found? */
+	if (min_dist > 0 && min_dist != -1)
+		step = watchpoint_report(slots[closest_match], addr, regs);
+
 	rcu_read_unlock();
 
 	if (!step)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/insn.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/insn.c
@@ -21,6 +21,7 @@
 #include <asm/fixmap.h>
 #include <asm/insn.h>
 #include <asm/kprobes.h>
+#include <asm/sections.h>
 
 #define AARCH64_INSN_SF_BIT	BIT(31)
 #define AARCH64_INSN_N_BIT	BIT(22)
@@ -78,16 +79,29 @@
 
 static DEFINE_RAW_SPINLOCK(patch_lock);
 
+static bool is_exit_text(unsigned long addr)
+{
+	/* discarded with init text/data */
+	return system_state < SYSTEM_RUNNING &&
+		addr >= (unsigned long)__exittext_begin &&
+		addr < (unsigned long)__exittext_end;
+}
+
+static bool is_image_text(unsigned long addr)
+{
+	return core_kernel_text(addr) || is_exit_text(addr);
+}
+
 static void __kprobes *patch_map(void *addr, int fixmap)
 {
 	unsigned long uintaddr = (uintptr_t) addr;
-	bool module = !core_kernel_text(uintaddr);
+	bool image = is_image_text(uintaddr);
 	struct page *page;
 
-	if (module && IS_ENABLED(CONFIG_STRICT_MODULE_RWX))
-		page = vmalloc_to_page(addr);
-	else if (!module)
+	if (image)
 		page = phys_to_page(__pa_symbol(addr));
+	else if (IS_ENABLED(CONFIG_STRICT_MODULE_RWX))
+		page = vmalloc_to_page(addr);
 	else
 		return addr;
 
@@ -193,8 +207,8 @@
 	int i, ret = 0;
 	struct aarch64_insn_patch *pp = arg;
 
-	/* The first CPU becomes master */
-	if (atomic_inc_return(&pp->cpu_count) == 1) {
+	/* The last CPU becomes master */
+	if (atomic_inc_return(&pp->cpu_count) == num_online_cpus()) {
 		for (i = 0; ret == 0 && i < pp->insn_cnt; i++)
 			ret = aarch64_insn_patch_text_nosync(pp->text_addrs[i],
 							     pp->new_insns[i]);
@@ -1508,16 +1522,10 @@
 				    u32 insn)
 {
 	unsigned int immr, imms, n, ones, ror, esz, tmp;
-	u64 mask = ~0UL;
-
-	/* Can't encode full zeroes or full ones */
-	if (!imm || !~imm)
-		return AARCH64_BREAK_FAULT;
+	u64 mask;
 
 	switch (variant) {
 	case AARCH64_INSN_VARIANT_32BIT:
-		if (upper_32_bits(imm))
-			return AARCH64_BREAK_FAULT;
 		esz = 32;
 		break;
 	case AARCH64_INSN_VARIANT_64BIT:
@@ -1529,6 +1537,12 @@
 		return AARCH64_BREAK_FAULT;
 	}
 
+	mask = GENMASK(esz - 1, 0);
+
+	/* Can't encode full zeroes, full ones, or value wider than the mask */
+	if (!imm || imm == mask || imm & ~mask)
+		return AARCH64_BREAK_FAULT;
+
 	/*
 	 * Inverse of Replicate(). Try to spot a repeating pattern
 	 * with a pow2 stride.
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/kgdb.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/kgdb.c
@@ -223,6 +223,8 @@
 		 */
 		if (!kernel_active_single_step())
 			kernel_enable_single_step(linux_regs);
+		else
+			kernel_rewind_single_step(linux_regs);
 		err = 0;
 		break;
 	default:
@@ -252,7 +254,7 @@
 	if (!kgdb_single_step)
 		return DBG_HOOK_ERROR;
 
-	kgdb_handle_exception(1, SIGTRAP, 0, regs);
+	kgdb_handle_exception(0, SIGTRAP, 0, regs);
 	return DBG_HOOK_HANDLED;
 }
 NOKPROBE_SYMBOL(kgdb_step_brk_fn);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/machine_kexec.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/machine_kexec.c
@@ -189,6 +189,7 @@
 	 * the offline CPUs. Therefore, we must use the __* variant here.
 	 */
 	__flush_icache_range((uintptr_t)reboot_code_buffer,
+			     (uintptr_t)reboot_code_buffer +
 			     arm64_relocate_new_kernel_size);
 
 	/* Flush the kimage list and its buffers. */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/machine_kexec_file.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/machine_kexec_file.c
@@ -150,8 +150,10 @@
 
 		/* duplicate a device tree blob */
 		ret = fdt_open_into(initial_boot_params, buf, buf_size);
-		if (ret)
+		if (ret) {
+			vfree(buf);
 			return -EINVAL;
+		}
 
 		ret = setup_dtb(image, initrd_load_addr, initrd_len,
 				cmdline, buf);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/module-plts.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/module-plts.c
@@ -270,8 +270,7 @@
 			mod->arch.core.plt_shndx = i;
 		else if (!strcmp(secstrings + sechdrs[i].sh_name, ".init.plt"))
 			mod->arch.init.plt_shndx = i;
-		else if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE) &&
-			 !strcmp(secstrings + sechdrs[i].sh_name,
+		else if (!strcmp(secstrings + sechdrs[i].sh_name,
 				 ".text.ftrace_trampoline"))
 			tramp = sechdrs + i;
 		else if (sechdrs[i].sh_type == SHT_SYMTAB)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/module.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/module.c
@@ -9,6 +9,7 @@
 
 #include <linux/bitops.h>
 #include <linux/elf.h>
+#include <linux/ftrace.h>
 #include <linux/gfp.h>
 #include <linux/kasan.h>
 #include <linux/kernel.h>
@@ -470,22 +471,48 @@
 	return -ENOEXEC;
 }
 
-int module_finalize(const Elf_Ehdr *hdr,
-		    const Elf_Shdr *sechdrs,
-		    struct module *me)
+static const Elf_Shdr *find_section(const Elf_Ehdr *hdr,
+				    const Elf_Shdr *sechdrs,
+				    const char *name)
 {
 	const Elf_Shdr *s, *se;
 	const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
 
 	for (s = sechdrs, se = sechdrs + hdr->e_shnum; s < se; s++) {
-		if (strcmp(".altinstructions", secstrs + s->sh_name) == 0)
-			apply_alternatives_module((void *)s->sh_addr, s->sh_size);
-#ifdef CONFIG_ARM64_MODULE_PLTS
-		if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE) &&
-		    !strcmp(".text.ftrace_trampoline", secstrs + s->sh_name))
-			me->arch.ftrace_trampoline = (void *)s->sh_addr;
-#endif
+		if (strcmp(name, secstrs + s->sh_name) == 0)
+			return s;
 	}
 
+	return NULL;
+}
+
+static int module_init_ftrace_plt(const Elf_Ehdr *hdr,
+				  const Elf_Shdr *sechdrs,
+				  struct module *mod)
+{
+#if defined(CONFIG_ARM64_MODULE_PLTS) && defined(CONFIG_DYNAMIC_FTRACE)
+	const Elf_Shdr *s;
+	struct plt_entry *plt;
+
+	s = find_section(hdr, sechdrs, ".text.ftrace_trampoline");
+	if (!s)
+		return -ENOEXEC;
+
+	plt = (void *)s->sh_addr;
+	*plt = get_plt_entry(FTRACE_ADDR, plt);
+	mod->arch.ftrace_trampoline = plt;
+#endif
 	return 0;
 }
+
+int module_finalize(const Elf_Ehdr *hdr,
+		    const Elf_Shdr *sechdrs,
+		    struct module *me)
+{
+	const Elf_Shdr *s;
+	s = find_section(hdr, sechdrs, ".altinstructions");
+	if (s)
+		apply_alternatives_module((void *)s->sh_addr, s->sh_size);
+
+	return module_init_ftrace_plt(hdr, sechdrs, me);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/module.lds
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/module.lds
@@ -1,5 +1,5 @@
 SECTIONS {
-	.plt (NOLOAD) : { BYTE(0) }
-	.init.plt (NOLOAD) : { BYTE(0) }
-	.text.ftrace_trampoline (NOLOAD) : { BYTE(0) }
+	.plt 0 : { BYTE(0) }
+	.init.plt 0 : { BYTE(0) }
+	.text.ftrace_trampoline 0 : { BYTE(0) }
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/perf_callchain.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/perf_callchain.c
@@ -102,7 +102,9 @@
 void perf_callchain_user(struct perf_callchain_entry_ctx *entry,
 			 struct pt_regs *regs)
 {
-	if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
+	struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs();
+
+	if (guest_cbs && guest_cbs->is_in_guest()) {
 		/* We don't support guest os callchain now */
 		return;
 	}
@@ -147,9 +149,10 @@
 void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
 			   struct pt_regs *regs)
 {
+	struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs();
 	struct stackframe frame;
 
-	if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
+	if (guest_cbs && guest_cbs->is_in_guest()) {
 		/* We don't support guest os callchain now */
 		return;
 	}
@@ -160,18 +163,21 @@
 
 unsigned long perf_instruction_pointer(struct pt_regs *regs)
 {
-	if (perf_guest_cbs && perf_guest_cbs->is_in_guest())
-		return perf_guest_cbs->get_guest_ip();
+	struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs();
+
+	if (guest_cbs && guest_cbs->is_in_guest())
+		return guest_cbs->get_guest_ip();
 
 	return instruction_pointer(regs);
 }
 
 unsigned long perf_misc_flags(struct pt_regs *regs)
 {
+	struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs();
 	int misc = 0;
 
-	if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
-		if (perf_guest_cbs->is_user_mode())
+	if (guest_cbs && guest_cbs->is_in_guest()) {
+		if (guest_cbs->is_user_mode())
 			misc |= PERF_RECORD_MISC_GUEST_USER;
 		else
 			misc |= PERF_RECORD_MISC_GUEST_KERNEL;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/perf_event.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/perf_event.c
@@ -155,7 +155,7 @@
 
 	pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr);
 
-	return sprintf(page, "event=0x%03llx\n", pmu_attr->id);
+	return sprintf(page, "event=0x%04llx\n", pmu_attr->id);
 }
 
 #define ARMV8_EVENT_ATTR(name, config) \
@@ -303,10 +303,13 @@
 	    test_bit(pmu_attr->id, cpu_pmu->pmceid_bitmap))
 		return attr->mode;
 
-	pmu_attr->id -= ARMV8_PMUV3_EXT_COMMON_EVENT_BASE;
-	if (pmu_attr->id < ARMV8_PMUV3_MAX_COMMON_EVENTS &&
-	    test_bit(pmu_attr->id, cpu_pmu->pmceid_ext_bitmap))
-		return attr->mode;
+	if (pmu_attr->id >= ARMV8_PMUV3_EXT_COMMON_EVENT_BASE) {
+		u64 id = pmu_attr->id - ARMV8_PMUV3_EXT_COMMON_EVENT_BASE;
+
+		if (id < ARMV8_PMUV3_MAX_COMMON_EVENTS &&
+		    test_bit(id, cpu_pmu->pmceid_ext_bitmap))
+			return attr->mode;
+	}
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/perf_regs.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/perf_regs.c
@@ -15,15 +15,34 @@
 		return 0;
 
 	/*
-	 * Compat (i.e. 32 bit) mode:
-	 * - PC has been set in the pt_regs struct in kernel_entry,
-	 * - Handle SP and LR here.
+	 * Our handling of compat tasks (PERF_SAMPLE_REGS_ABI_32) is weird, but
+	 * we're stuck with it for ABI compatability reasons.
+	 *
+	 * For a 32-bit consumer inspecting a 32-bit task, then it will look at
+	 * the first 16 registers (see arch/arm/include/uapi/asm/perf_regs.h).
+	 * These correspond directly to a prefix of the registers saved in our
+	 * 'struct pt_regs', with the exception of the PC, so we copy that down
+	 * (x15 corresponds to SP_hyp in the architecture).
+	 *
+	 * So far, so good.
+	 *
+	 * The oddity arises when a 64-bit consumer looks at a 32-bit task and
+	 * asks for registers beyond PERF_REG_ARM_MAX. In this case, we return
+	 * SP_usr, LR_usr and PC in the positions where the AArch64 SP, LR and
+	 * PC registers would normally live. The initial idea was to allow a
+	 * 64-bit unwinder to unwind a 32-bit task and, although it's not clear
+	 * how well that works in practice, somebody might be relying on it.
+	 *
+	 * At the time we make a sample, we don't know whether the consumer is
+	 * 32-bit or 64-bit, so we have to cater for both possibilities.
 	 */
 	if (compat_user_mode(regs)) {
 		if ((u32)idx == PERF_REG_ARM64_SP)
 			return regs->compat_sp;
 		if ((u32)idx == PERF_REG_ARM64_LR)
 			return regs->compat_lr;
+		if (idx == 15)
+			return regs->pc;
 	}
 
 	if ((u32)idx == PERF_REG_ARM64_SP)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/probes/decode-insn.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/probes/decode-insn.c
@@ -96,10 +96,6 @@
 	    aarch64_insn_is_blr(insn) ||
 	    aarch64_insn_is_ret(insn)) {
 		api->handler = simulate_br_blr_ret;
-	} else if (aarch64_insn_is_ldr_lit(insn)) {
-		api->handler = simulate_ldr_literal;
-	} else if (aarch64_insn_is_ldrsw_lit(insn)) {
-		api->handler = simulate_ldrsw_literal;
 	} else {
 		/*
 		 * Instruction cannot be stepped out-of-line and we don't
@@ -137,6 +133,17 @@
 	probe_opcode_t insn = le32_to_cpu(*addr);
 	probe_opcode_t *scan_end = NULL;
 	unsigned long size = 0, offset = 0;
+	struct arch_probe_insn *api = &asi->api;
+
+	if (aarch64_insn_is_ldr_lit(insn)) {
+		api->handler = simulate_ldr_literal;
+		decoded = INSN_GOOD_NO_SLOT;
+	} else if (aarch64_insn_is_ldrsw_lit(insn)) {
+		api->handler = simulate_ldrsw_literal;
+		decoded = INSN_GOOD_NO_SLOT;
+	} else {
+		decoded = arm_probe_decode_insn(insn, &asi->api);
+	}
 
 	/*
 	 * If there's a symbol defined in front of and near enough to
@@ -154,7 +161,6 @@
 		else
 			scan_end = addr - MAX_ATOMIC_CONTEXT_SIZE;
 	}
-	decoded = arm_probe_decode_insn(insn, &asi->api);
 
 	if (decoded != INSN_REJECTED && scan_end)
 		if (is_probed_address_atomic(addr - 1, scan_end))
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/probes/kprobes.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/probes/kprobes.c
@@ -36,25 +36,16 @@
 static void __kprobes
 post_kprobe_handler(struct kprobe_ctlblk *, struct pt_regs *);
 
-static int __kprobes patch_text(kprobe_opcode_t *addr, u32 opcode)
-{
-	void *addrs[1];
-	u32 insns[1];
-
-	addrs[0] = addr;
-	insns[0] = opcode;
-
-	return aarch64_insn_patch_text(addrs, insns, 1);
-}
-
 static void __kprobes arch_prepare_ss_slot(struct kprobe *p)
 {
+	kprobe_opcode_t *addr = p->ainsn.api.insn;
+	void *addrs[] = {addr, addr + 1};
+	u32 insns[] = {p->opcode, BRK64_OPCODE_KPROBES_SS};
+
 	/* prepare insn slot */
-	patch_text(p->ainsn.api.insn, p->opcode);
+	aarch64_insn_patch_text(addrs, insns, 2);
 
-	flush_icache_range((uintptr_t) (p->ainsn.api.insn),
-			   (uintptr_t) (p->ainsn.api.insn) +
-			   MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
+	flush_icache_range((uintptr_t)addr, (uintptr_t)(addr + MAX_INSN_SIZE));
 
 	/*
 	 * Needs restoring of return address after stepping xol.
@@ -134,13 +125,18 @@
 /* arm kprobe: install breakpoint in text */
 void __kprobes arch_arm_kprobe(struct kprobe *p)
 {
-	patch_text(p->addr, BRK64_OPCODE_KPROBES);
+	void *addr = p->addr;
+	u32 insn = BRK64_OPCODE_KPROBES;
+
+	aarch64_insn_patch_text(&addr, &insn, 1);
 }
 
 /* disarm kprobe: remove breakpoint from text */
 void __kprobes arch_disarm_kprobe(struct kprobe *p)
 {
-	patch_text(p->addr, p->opcode);
+	void *addr = p->addr;
+
+	aarch64_insn_patch_text(&addr, &p->opcode, 1);
 }
 
 void __kprobes arch_remove_kprobe(struct kprobe *p)
@@ -169,20 +165,15 @@
 }
 
 /*
- * Interrupts need to be disabled before single-step mode is set, and not
- * reenabled until after single-step mode ends.
- * Without disabling interrupt on local CPU, there is a chance of
- * interrupt occurrence in the period of exception return and  start of
- * out-of-line single-step, that result in wrongly single stepping
- * into the interrupt handler.
+ * Mask all of DAIF while executing the instruction out-of-line, to keep things
+ * simple and avoid nesting exceptions. Interrupts do have to be disabled since
+ * the kprobe state is per-CPU and doesn't get migrated.
  */
 static void __kprobes kprobes_save_local_irqflag(struct kprobe_ctlblk *kcb,
 						struct pt_regs *regs)
 {
 	kcb->saved_irqflag = regs->pstate & DAIF_MASK;
-	regs->pstate |= PSR_I_BIT;
-	/* Unmask PSTATE.D for enabling software step exceptions. */
-	regs->pstate &= ~PSR_D_BIT;
+	regs->pstate |= DAIF_MASK;
 }
 
 static void __kprobes kprobes_restore_local_irqflag(struct kprobe_ctlblk *kcb,
@@ -225,10 +216,7 @@
 		slot = (unsigned long)p->ainsn.api.insn;
 
 		set_ss_context(kcb, slot);	/* mark pending ss */
-
-		/* IRQs and single stepping do not mix well. */
 		kprobes_save_local_irqflag(kcb, regs);
-		kernel_enable_single_step(regs);
 		instruction_pointer_set(regs, slot);
 	} else {
 		/* insn simulation */
@@ -279,12 +267,8 @@
 	}
 	/* call post handler */
 	kcb->kprobe_status = KPROBE_HIT_SSDONE;
-	if (cur->post_handler)	{
-		/* post_handler can hit breakpoint and single step
-		 * again, so we enable D-flag for recursive exception.
-		 */
+	if (cur->post_handler)
 		cur->post_handler(cur, regs, 0);
-	}
 
 	reset_current_kprobe();
 }
@@ -308,8 +292,6 @@
 		if (!instruction_pointer(regs))
 			BUG();
 
-		kernel_disable_single_step();
-
 		if (kcb->kprobe_status == KPROBE_REENTER)
 			restore_previous_kprobe(kcb);
 		else
@@ -371,10 +353,6 @@
 			 * pre-handler and it returned non-zero, it will
 			 * modify the execution path and no need to single
 			 * stepping. Let's just reset current kprobe and exit.
-			 *
-			 * pre_handler can hit a breakpoint and can step thru
-			 * before return, keep PSTATE D-flag enabled until
-			 * pre_handler return back.
 			 */
 			if (!p->pre_handler || !p->pre_handler(p, regs)) {
 				setup_singlestep(p, regs, kcb, 0);
@@ -405,7 +383,7 @@
 }
 
 static int __kprobes
-kprobe_single_step_handler(struct pt_regs *regs, unsigned int esr)
+kprobe_breakpoint_ss_handler(struct pt_regs *regs, unsigned int esr)
 {
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 	int retval;
@@ -415,16 +393,15 @@
 
 	if (retval == DBG_HOOK_HANDLED) {
 		kprobes_restore_local_irqflag(kcb, regs);
-		kernel_disable_single_step();
-
 		post_kprobe_handler(kcb, regs);
 	}
 
 	return retval;
 }
 
-static struct step_hook kprobes_step_hook = {
-	.fn = kprobe_single_step_handler,
+static struct break_hook kprobes_break_ss_hook = {
+	.imm = KPROBES_BRK_SS_IMM,
+	.fn = kprobe_breakpoint_ss_handler,
 };
 
 static int __kprobes
@@ -568,7 +545,7 @@
 int __init arch_init_kprobes(void)
 {
 	register_kernel_break_hook(&kprobes_break_hook);
-	register_kernel_step_hook(&kprobes_step_hook);
+	register_kernel_break_hook(&kprobes_break_ss_hook);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/probes/simulate-insn.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/probes/simulate-insn.c
@@ -170,17 +170,15 @@
 void __kprobes
 simulate_ldr_literal(u32 opcode, long addr, struct pt_regs *regs)
 {
-	u64 *load_addr;
+	unsigned long load_addr;
 	int xn = opcode & 0x1f;
-	int disp;
 
-	disp = ldr_displacement(opcode);
-	load_addr = (u64 *) (addr + disp);
+	load_addr = addr + ldr_displacement(opcode);
 
 	if (opcode & (1 << 30))	/* x0-x30 */
-		set_x_reg(regs, xn, *load_addr);
+		set_x_reg(regs, xn, READ_ONCE(*(u64 *)load_addr));
 	else			/* w0-w30 */
-		set_w_reg(regs, xn, *load_addr);
+		set_w_reg(regs, xn, READ_ONCE(*(u32 *)load_addr));
 
 	instruction_pointer_set(regs, instruction_pointer(regs) + 4);
 }
@@ -188,14 +186,12 @@
 void __kprobes
 simulate_ldrsw_literal(u32 opcode, long addr, struct pt_regs *regs)
 {
-	s32 *load_addr;
+	unsigned long load_addr;
 	int xn = opcode & 0x1f;
-	int disp;
 
-	disp = ldr_displacement(opcode);
-	load_addr = (s32 *) (addr + disp);
+	load_addr = addr + ldr_displacement(opcode);
 
-	set_x_reg(regs, xn, *load_addr);
+	set_x_reg(regs, xn, READ_ONCE(*(s32 *)load_addr));
 
 	instruction_pointer_set(regs, instruction_pointer(regs) + 4);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/probes/uprobes.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/probes/uprobes.c
@@ -38,11 +38,11 @@
 
 	/* TODO: Currently we do not support AARCH32 instruction probing */
 	if (mm->context.flags & MMCF_AARCH32)
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 	else if (!IS_ALIGNED(addr, AARCH64_INSN_SIZE))
 		return -EINVAL;
 
-	insn = *(probe_opcode_t *)(&auprobe->insn[0]);
+	insn = le32_to_cpu(auprobe->insn);
 
 	switch (arm_probe_decode_insn(insn, &auprobe->api)) {
 	case INSN_REJECTED:
@@ -108,7 +108,7 @@
 	if (!auprobe->simulate)
 		return false;
 
-	insn = *(probe_opcode_t *)(&auprobe->insn[0]);
+	insn = le32_to_cpu(auprobe->insn);
 	addr = instruction_pointer(regs);
 
 	if (auprobe->api.handler)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/process.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/process.c
@@ -56,7 +56,7 @@
 
 #if defined(CONFIG_STACKPROTECTOR) && !defined(CONFIG_STACKPROTECTOR_PER_TASK)
 #include <linux/stackprotector.h>
-unsigned long __stack_chk_guard __read_mostly;
+unsigned long __stack_chk_guard __ro_after_init;
 EXPORT_SYMBOL(__stack_chk_guard);
 #endif
 
@@ -360,8 +360,8 @@
 
 asmlinkage void ret_from_fork(void) asm("ret_from_fork");
 
-int copy_thread(unsigned long clone_flags, unsigned long stack_start,
-		unsigned long stk_sz, struct task_struct *p)
+int copy_thread_tls(unsigned long clone_flags, unsigned long stack_start,
+		unsigned long stk_sz, struct task_struct *p, unsigned long tls)
 {
 	struct pt_regs *childregs = task_pt_regs(p);
 
@@ -394,11 +394,11 @@
 		}
 
 		/*
-		 * If a TLS pointer was passed to clone (4th argument), use it
-		 * for the new thread.
+		 * If a TLS pointer was passed to clone, use it for the new
+		 * thread.
 		 */
 		if (clone_flags & CLONE_SETTLS)
-			p->thread.uw.tp_value = childregs->regs[3];
+			p->thread.uw.tp_value = tls;
 	} else {
 		memset(childregs, 0, sizeof(struct pt_regs));
 		childregs->pstate = PSR_MODE_EL1h;
@@ -434,7 +434,7 @@
 
 	if (is_compat_thread(task_thread_info(next)))
 		write_sysreg(next->thread.uw.tp_value, tpidrro_el0);
-	else if (!arm64_kernel_unmapped_at_el0())
+	else
 		write_sysreg(0, tpidrro_el0);
 
 	write_sysreg(*task_user_tls(next), tpidr_el0);
@@ -466,6 +466,13 @@
 	if (unlikely(next->flags & PF_KTHREAD))
 		return;
 
+	/*
+	 * If all CPUs implement the SSBS extension, then we just need to
+	 * context-switch the PSTATE field.
+	 */
+	if (cpu_have_feature(cpu_feature(SSBS)))
+		return;
+
 	/* If the mitigation is enabled, then we leave SSBS clear. */
 	if ((arm64_get_ssbd_state() == ARM64_SSBD_FORCE_ENABLE) ||
 	    test_tsk_thread_flag(next, TIF_SSBD))
@@ -492,6 +499,30 @@
 }
 
 /*
+ * ARM erratum 1418040 handling, affecting the 32bit view of CNTVCT.
+ * Ensure access is disabled when switching to a 32bit task, ensure
+ * access is enabled when switching to a 64bit task.
+ */
+static void erratum_1418040_thread_switch(struct task_struct *next)
+{
+	if (!IS_ENABLED(CONFIG_ARM64_ERRATUM_1418040) ||
+	    !this_cpu_has_cap(ARM64_WORKAROUND_1418040))
+		return;
+
+	if (is_compat_thread(task_thread_info(next)))
+		sysreg_clear_set(cntkctl_el1, ARCH_TIMER_USR_VCT_ACCESS_EN, 0);
+	else
+		sysreg_clear_set(cntkctl_el1, 0, ARCH_TIMER_USR_VCT_ACCESS_EN);
+}
+
+static void erratum_1418040_new_exec(void)
+{
+	preempt_disable();
+	erratum_1418040_thread_switch(current);
+	preempt_enable();
+}
+
+/*
  * Thread switching.
  */
 __notrace_funcgraph struct task_struct *__switch_to(struct task_struct *prev,
@@ -507,6 +538,7 @@
 	uao_thread_switch(next);
 	ptrauth_thread_switch(next);
 	ssbs_thread_switch(next);
+	erratum_1418040_thread_switch(next);
 
 	/*
 	 * Complete any pending TLB or cache maintenance on this CPU in case
@@ -565,6 +597,7 @@
 	current->mm->context.flags = is_compat_task() ? MMCF_AARCH32 : 0;
 
 	ptrauth_thread_init_user(current);
+	erratum_1418040_new_exec();
 }
 
 #ifdef CONFIG_ARM64_TAGGED_ADDR_ABI
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/psci.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/psci.c
@@ -66,7 +66,6 @@
 
 static void cpu_psci_cpu_die(unsigned int cpu)
 {
-	int ret;
 	/*
 	 * There are no known implementations of PSCI actually using the
 	 * power state field, pass a sensible default for now.
@@ -74,14 +73,13 @@
 	u32 state = PSCI_POWER_STATE_TYPE_POWER_DOWN <<
 		    PSCI_0_2_POWER_STATE_TYPE_SHIFT;
 
-	ret = psci_ops.cpu_off(state);
-
-	pr_crit("unable to power off CPU%u (%d)\n", cpu, ret);
+	psci_ops.cpu_off(state);
 }
 
 static int cpu_psci_cpu_kill(unsigned int cpu)
 {
-	int err, i;
+	int err;
+	unsigned long start, end;
 
 	if (!psci_ops.affinity_info)
 		return 0;
@@ -91,16 +89,18 @@
 	 * while it is dying. So, try again a few times.
 	 */
 
-	for (i = 0; i < 10; i++) {
+	start = jiffies;
+	end = start + msecs_to_jiffies(100);
+	do {
 		err = psci_ops.affinity_info(cpu_logical_map(cpu), 0);
 		if (err == PSCI_0_2_AFFINITY_LEVEL_OFF) {
-			pr_info("CPU%d killed.\n", cpu);
+			pr_info("CPU%d killed (polled %d ms)\n", cpu,
+				jiffies_to_msecs(jiffies - start));
 			return 0;
 		}
 
-		msleep(10);
-		pr_info("Retrying again to check for CPU kill\n");
-	}
+		usleep_range(100, 1000);
+	} while (time_before(jiffies, end));
 
 	pr_warn("CPU%d may not have shut down cleanly (AFFINITY_INFO reports %d)\n",
 			cpu, err);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/ptrace.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/ptrace.c
@@ -615,6 +615,13 @@
 	return 0;
 }
 
+static int fpr_active(struct task_struct *target, const struct user_regset *regset)
+{
+	if (!system_supports_fpsimd())
+		return -ENODEV;
+	return regset->n;
+}
+
 /*
  * TODO: update fp accessors for lazy context switching (sync/flush hwstate)
  */
@@ -637,6 +644,9 @@
 		   unsigned int pos, unsigned int count,
 		   void *kbuf, void __user *ubuf)
 {
+	if (!system_supports_fpsimd())
+		return -EINVAL;
+
 	if (target == current)
 		fpsimd_preserve_current_state();
 
@@ -676,6 +686,9 @@
 {
 	int ret;
 
+	if (!system_supports_fpsimd())
+		return -EINVAL;
+
 	ret = __fpr_set(target, regset, pos, count, kbuf, ubuf, 0);
 	if (ret)
 		return ret;
@@ -1134,6 +1147,7 @@
 		 */
 		.size = sizeof(u32),
 		.align = sizeof(u32),
+		.active = fpr_active,
 		.get = fpr_get,
 		.set = fpr_set
 	},
@@ -1348,6 +1362,9 @@
 	compat_ulong_t fpscr;
 	int ret, vregs_end_pos;
 
+	if (!system_supports_fpsimd())
+		return -EINVAL;
+
 	uregs = &target->thread.uw.fpsimd_state;
 
 	if (target == current)
@@ -1381,6 +1398,9 @@
 	compat_ulong_t fpscr;
 	int ret, vregs_end_pos;
 
+	if (!system_supports_fpsimd())
+		return -EINVAL;
+
 	uregs = &target->thread.uw.fpsimd_state;
 
 	vregs_end_pos = VFP_STATE_SIZE - sizeof(compat_ulong_t);
@@ -1438,6 +1458,7 @@
 		.n = VFP_STATE_SIZE / sizeof(compat_ulong_t),
 		.size = sizeof(compat_ulong_t),
 		.align = sizeof(compat_ulong_t),
+		.active = fpr_active,
 		.get = compat_vfp_get,
 		.set = compat_vfp_set
 	},
@@ -1798,20 +1819,32 @@
 	saved_reg = regs->regs[regno];
 	regs->regs[regno] = dir;
 
-	if (dir == PTRACE_SYSCALL_EXIT)
+	if (dir == PTRACE_SYSCALL_ENTER) {
+		if (tracehook_report_syscall_entry(regs))
+			forget_syscall(regs);
+		regs->regs[regno] = saved_reg;
+	} else if (!test_thread_flag(TIF_SINGLESTEP)) {
 		tracehook_report_syscall_exit(regs, 0);
-	else if (tracehook_report_syscall_entry(regs))
-		forget_syscall(regs);
+		regs->regs[regno] = saved_reg;
+	} else {
+		regs->regs[regno] = saved_reg;
 
-	regs->regs[regno] = saved_reg;
+		/*
+		 * Signal a pseudo-step exception since we are stepping but
+		 * tracer modifications to the registers may have rewound the
+		 * state machine.
+		 */
+		tracehook_report_syscall_exit(regs, 1);
+	}
 }
 
 int syscall_trace_enter(struct pt_regs *regs)
 {
-	if (test_thread_flag(TIF_SYSCALL_TRACE) ||
-		test_thread_flag(TIF_SYSCALL_EMU)) {
+	unsigned long flags = READ_ONCE(current_thread_info()->flags);
+
+	if (flags & (_TIF_SYSCALL_EMU | _TIF_SYSCALL_TRACE)) {
 		tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER);
-		if (!in_syscall(regs) || test_thread_flag(TIF_SYSCALL_EMU))
+		if (flags & _TIF_SYSCALL_EMU)
 			return -1;
 	}
 
@@ -1830,12 +1863,14 @@
 
 void syscall_trace_exit(struct pt_regs *regs)
 {
+	unsigned long flags = READ_ONCE(current_thread_info()->flags);
+
 	audit_syscall_exit(regs);
 
-	if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
-		trace_sys_exit(regs, regs_return_value(regs));
+	if (flags & _TIF_SYSCALL_TRACEPOINT)
+		trace_sys_exit(regs, syscall_get_return_value(current, regs));
 
-	if (test_thread_flag(TIF_SYSCALL_TRACE))
+	if (flags & (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP))
 		tracehook_report_syscall(regs, PTRACE_SYSCALL_EXIT);
 
 	rseq_syscall(regs);
@@ -1913,8 +1948,8 @@
  */
 int valid_user_regs(struct user_pt_regs *regs, struct task_struct *task)
 {
-	if (!test_tsk_thread_flag(task, TIF_SINGLESTEP))
-		regs->pstate &= ~DBG_SPSR_SS;
+	/* https://lore.kernel.org/lkml/20191118131525.GA4180@willie-the-truck */
+	user_regs_reset_single_step(regs, task);
 
 	if (is_compat_thread(task_thread_info(task)))
 		return valid_compat_regs(regs);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/setup.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/setup.c
@@ -85,7 +85,7 @@
 void __init smp_setup_processor_id(void)
 {
 	u64 mpidr = read_cpuid_mpidr() & MPIDR_HWID_BITMASK;
-	cpu_logical_map(0) = mpidr;
+	set_cpu_logical_map(0, mpidr);
 
 	/*
 	 * clear __my_cpu_offset on boot CPU to avoid hang caused by
@@ -276,6 +276,12 @@
 
 u64 __cpu_logical_map[NR_CPUS] = { [0 ... NR_CPUS-1] = INVALID_HWID };
 
+u64 cpu_logical_map(int cpu)
+{
+	return __cpu_logical_map[cpu];
+}
+EXPORT_SYMBOL_GPL(cpu_logical_map);
+
 void __init setup_arch(char **cmdline_p)
 {
 	init_mm.start_code = (unsigned long) _text;
@@ -350,7 +356,7 @@
 	 * faults in case uaccess_enable() is inadvertently called by the init
 	 * thread.
 	 */
-	init_task.thread_info.ttbr0 = __pa_symbol(empty_zero_page);
+	init_task.thread_info.ttbr0 = phys_to_ttbr(__pa_symbol(reserved_pg_dir));
 #endif
 
 #ifdef CONFIG_VT
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/signal.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/signal.c
@@ -29,6 +29,7 @@
 #include <asm/unistd.h>
 #include <asm/fpsimd.h>
 #include <asm/ptrace.h>
+#include <asm/syscall.h>
 #include <asm/signal32.h>
 #include <asm/traps.h>
 #include <asm/vdso.h>
@@ -782,7 +783,6 @@
  */
 static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
 {
-	struct task_struct *tsk = current;
 	sigset_t *oldset = sigmask_to_save();
 	int usig = ksig->sig;
 	int ret;
@@ -806,14 +806,8 @@
 	 */
 	ret |= !valid_user_regs(&regs->user_regs, current);
 
-	/*
-	 * Fast forward the stepping logic so we step into the signal
-	 * handler.
-	 */
-	if (!ret)
-		user_fastforward_single_step(tsk);
-
-	signal_setup_done(ret, ksig, 0);
+	/* Step into the signal handler if we are stepping */
+	signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
 }
 
 /*
@@ -875,7 +869,7 @@
 		     retval == -ERESTART_RESTARTBLOCK ||
 		     (retval == -ERESTARTSYS &&
 		      !(ksig.ka.sa.sa_flags & SA_RESTART)))) {
-			regs->regs[0] = -EINTR;
+			syscall_set_return_value(current, regs, -EINTR, 0);
 			regs->pc = continue_addr;
 		}
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/smp.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/smp.c
@@ -215,6 +215,7 @@
 	if (system_uses_irq_prio_masking())
 		init_gic_priority_masking();
 
+	rcu_cpu_starting(cpu);
 	preempt_disable();
 	trace_hardirqs_off();
 
@@ -387,6 +388,7 @@
 
 	/* Mark this CPU absent */
 	set_cpu_present(cpu, 0);
+	rcu_report_dead(cpu);
 
 #ifdef CONFIG_HOTPLUG_CPU
 	update_cpu_boot_status(CPU_KILL_ME);
@@ -549,7 +551,7 @@
 		return;
 
 	/* map the logical cpu id to cpu MPIDR */
-	cpu_logical_map(cpu_count) = hwid;
+	set_cpu_logical_map(cpu_count, hwid);
 
 	cpu_madt_gicc[cpu_count] = *processor;
 
@@ -663,7 +665,7 @@
 			goto next;
 
 		pr_debug("cpu logical map 0x%llx\n", hwid);
-		cpu_logical_map(cpu_count) = hwid;
+		set_cpu_logical_map(cpu_count, hwid);
 
 		early_map_cpu_to_node(cpu_count, of_node_to_nid(dn));
 next:
@@ -704,7 +706,7 @@
 	for (i = 1; i < nr_cpu_ids; i++) {
 		if (cpu_logical_map(i) != INVALID_HWID) {
 			if (smp_cpu_setup(i))
-				cpu_logical_map(i) = INVALID_HWID;
+				set_cpu_logical_map(i, INVALID_HWID);
 		}
 	}
 }
@@ -955,11 +957,22 @@
 }
 #endif
 
+/*
+ * The number of CPUs online, not counting this CPU (which may not be
+ * fully online and so not counted in num_online_cpus()).
+ */
+static inline unsigned int num_other_online_cpus(void)
+{
+	unsigned int this_cpu_online = cpu_online(smp_processor_id());
+
+	return num_online_cpus() - this_cpu_online;
+}
+
 void smp_send_stop(void)
 {
 	unsigned long timeout;
 
-	if (num_online_cpus() > 1) {
+	if (num_other_online_cpus()) {
 		cpumask_t mask;
 
 		cpumask_copy(&mask, cpu_online_mask);
@@ -972,10 +985,10 @@
 
 	/* Wait up to one second for other CPUs to stop */
 	timeout = USEC_PER_SEC;
-	while (num_online_cpus() > 1 && timeout--)
+	while (num_other_online_cpus() && timeout--)
 		udelay(1);
 
-	if (num_online_cpus() > 1)
+	if (num_other_online_cpus())
 		pr_warning("SMP: failed to stop secondary CPUs %*pbl\n",
 			   cpumask_pr_args(cpu_online_mask));
 
@@ -998,7 +1011,11 @@
 
 	cpus_stopped = 1;
 
-	if (num_online_cpus() == 1) {
+	/*
+	 * If this cpu is the only one alive at this point in time, online or
+	 * not, there are no stop messages to be sent around, so just back out.
+	 */
+	if (num_other_online_cpus() == 0) {
 		sdei_mask_local_cpu();
 		return;
 	}
@@ -1006,7 +1023,7 @@
 	cpumask_copy(&mask, cpu_online_mask);
 	cpumask_clear_cpu(smp_processor_id(), &mask);
 
-	atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
+	atomic_set(&waiting_for_crash_ipi, num_other_online_cpus());
 
 	pr_crit("SMP: stopping secondary CPUs\n");
 	smp_cross_call(&mask, IPI_CPU_CRASH_STOP);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/sys_compat.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/sys_compat.c
@@ -8,6 +8,7 @@
  */
 
 #include <linux/compat.h>
+#include <linux/cpufeature.h>
 #include <linux/personality.h>
 #include <linux/sched.h>
 #include <linux/sched/signal.h>
@@ -17,6 +18,7 @@
 
 #include <asm/cacheflush.h>
 #include <asm/system_misc.h>
+#include <asm/tlbflush.h>
 #include <asm/unistd.h>
 
 static long
@@ -30,6 +32,15 @@
 		if (fatal_signal_pending(current))
 			return 0;
 
+		if (cpus_have_const_cap(ARM64_WORKAROUND_1542419)) {
+			/*
+			 * The workaround requires an inner-shareable tlbi.
+			 * We pick the reserved-ASID to minimise the impact.
+			 */
+			__tlbi(aside1is, __TLBI_VADDR(0, 0));
+			dsb(ish);
+		}
+
 		ret = __flush_cache_user_range(start, start + chunk);
 		if (ret)
 			return ret;
@@ -104,6 +115,6 @@
 		(compat_thumb_mode(regs) ? 2 : 4);
 
 	arm64_notify_die("Oops - bad compat syscall(2)", regs,
-			 SIGILL, ILL_ILLTRP, addr, scno);
+			 SIGILL, ILL_ILLTRP, addr, 0);
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/syscall.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/syscall.c
@@ -50,7 +50,7 @@
 		ret = do_ni_syscall(regs, scno);
 	}
 
-	regs->regs[0] = ret;
+	syscall_set_return_value(current, regs, 0, ret);
 }
 
 static inline bool has_syscall_work(unsigned long flags)
@@ -99,13 +99,13 @@
 	regs->syscallno = scno;
 
 	cortex_a76_erratum_1463225_svc_handler();
+	user_exit_irqoff();
 	local_daif_restore(DAIF_PROCCTX);
-	user_exit();
 
 	if (has_syscall_work(flags)) {
 		/* set default errno for user-issued syscall(-1) */
 		if (scno == NO_SYSCALL)
-			regs->regs[0] = -ENOSYS;
+			syscall_set_return_value(current, regs, -ENOSYS, 0);
 		scno = syscall_trace_enter(regs);
 		if (scno == NO_SYSCALL)
 			goto trace_exit;
@@ -121,7 +121,7 @@
 	if (!has_syscall_work(flags) && !IS_ENABLED(CONFIG_DEBUG_RSEQ)) {
 		local_daif_mask();
 		flags = current_thread_info()->flags;
-		if (!has_syscall_work(flags)) {
+		if (!has_syscall_work(flags) && !(flags & _TIF_SINGLESTEP)) {
 			/*
 			 * We're off to userspace, where interrupts are
 			 * always enabled after we restore the flags from
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/topology.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/topology.c
@@ -21,44 +21,6 @@
 #include <asm/cputype.h>
 #include <asm/topology.h>
 
-void store_cpu_topology(unsigned int cpuid)
-{
-	struct cpu_topology *cpuid_topo = &cpu_topology[cpuid];
-	u64 mpidr;
-
-	if (cpuid_topo->package_id != -1)
-		goto topology_populated;
-
-	mpidr = read_cpuid_mpidr();
-
-	/* Uniprocessor systems can rely on default topology values */
-	if (mpidr & MPIDR_UP_BITMASK)
-		return;
-
-	/* Create cpu topology mapping based on MPIDR. */
-	if (mpidr & MPIDR_MT_BITMASK) {
-		/* Multiprocessor system : Multi-threads per core */
-		cpuid_topo->thread_id  = MPIDR_AFFINITY_LEVEL(mpidr, 0);
-		cpuid_topo->core_id    = MPIDR_AFFINITY_LEVEL(mpidr, 1);
-		cpuid_topo->package_id = MPIDR_AFFINITY_LEVEL(mpidr, 2) |
-					 MPIDR_AFFINITY_LEVEL(mpidr, 3) << 8;
-	} else {
-		/* Multiprocessor system : Single-thread per core */
-		cpuid_topo->thread_id  = -1;
-		cpuid_topo->core_id    = MPIDR_AFFINITY_LEVEL(mpidr, 0);
-		cpuid_topo->package_id = MPIDR_AFFINITY_LEVEL(mpidr, 1) |
-					 MPIDR_AFFINITY_LEVEL(mpidr, 2) << 8 |
-					 MPIDR_AFFINITY_LEVEL(mpidr, 3) << 16;
-	}
-
-	pr_debug("CPU%u: cluster %d core %d thread %d mpidr %#016llx\n",
-		 cpuid, cpuid_topo->package_id, cpuid_topo->core_id,
-		 cpuid_topo->thread_id, mpidr);
-
-topology_populated:
-	update_siblings_masks(cpuid);
-}
-
 #ifdef CONFIG_ACPI
 static bool __init acpi_cpu_is_threaded(int cpu)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/traps.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/traps.c
@@ -202,7 +202,7 @@
 	raw_spin_unlock_irqrestore(&die_lock, flags);
 
 	if (ret != NOTIFY_STOP)
-		do_exit(SIGSEGV);
+		make_task_dead(SIGSEGV);
 }
 
 static void arm64_show_signal(int signo, const char *str)
@@ -470,6 +470,15 @@
 	int rt = ESR_ELx_SYS64_ISS_RT(esr);
 	unsigned long val = arm64_ftr_reg_user_value(&arm64_ftr_reg_ctrel0);
 
+	if (cpus_have_const_cap(ARM64_WORKAROUND_1542419)) {
+		/* Hide DIC so that we can trap the unnecessary maintenance...*/
+		val &= ~BIT(CTR_DIC_SHIFT);
+
+		/* ... and fake IminLine to reduce the number of traps. */
+		val &= ~CTR_IMINLINE_MASK;
+		val |= (PAGE_SHIFT - 2) & CTR_IMINLINE_MASK;
+	}
+
 	pt_regs_write_reg(regs, rt, val);
 
 	arm64_skip_faulting_instruction(regs, AARCH64_INSN_SIZE);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/vdso.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/vdso.c
@@ -260,18 +260,7 @@
 	if (ret)
 		return ret;
 
-	ret = aarch32_alloc_kuser_vdso_page();
-	if (ret) {
-		unsigned long c_vvar =
-			(unsigned long)page_to_virt(aarch32_vdso_pages[C_VVAR]);
-		unsigned long c_vdso =
-			(unsigned long)page_to_virt(aarch32_vdso_pages[C_VDSO]);
-
-		free_page(c_vvar);
-		free_page(c_vdso);
-	}
-
-	return ret;
+	return aarch32_alloc_kuser_vdso_page();
 }
 #else
 static int __aarch32_alloc_vdso_pages(void)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/vdso/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/vdso/Makefile
@@ -32,7 +32,7 @@
 OBJECT_FILES_NON_STANDARD	:= y
 KCOV_INSTRUMENT			:= n
 
-CFLAGS_vgettimeofday.o = -O2 -mcmodel=tiny
+CFLAGS_vgettimeofday.o = -O2 -mcmodel=tiny -fasynchronous-unwind-tables
 
 ifneq ($(c-gettimeofday-y),)
   CFLAGS_vgettimeofday.o += -include $(c-gettimeofday-y)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/vdso/vdso.lds.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/vdso/vdso.lds.S
@@ -28,6 +28,13 @@
 	.gnu.version_d	: { *(.gnu.version_d) }
 	.gnu.version_r	: { *(.gnu.version_r) }
 
+	/*
+	 * Discard .note.gnu.property sections which are unused and have
+	 * different alignment requirement from vDSO note sections.
+	 */
+	/DISCARD/	: {
+		*(.note.GNU-stack .note.gnu.property)
+	}
 	.note		: { *(.note.*) }		:text	:note
 
 	. = ALIGN(16);
@@ -48,7 +55,6 @@
 	PROVIDE(end = .);
 
 	/DISCARD/	: {
-		*(.note.GNU-stack)
 		*(.data .data.* .gnu.linkonce.d.* .sdata*)
 		*(.bss .sbss .dynbss .dynsbss)
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/vdso32/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/vdso32/Makefile
@@ -32,7 +32,8 @@
 # As a result we set our own flags here.
 
 # KBUILD_CPPFLAGS and NOSTDINC_FLAGS from top-level Makefile
-VDSO_CPPFLAGS := -D__KERNEL__ -nostdinc -isystem $(shell $(CC_COMPAT) -print-file-name=include)
+VDSO_CPPFLAGS := -D__KERNEL__ -nostdinc
+VDSO_CPPFLAGS += -isystem $(shell $(CC_COMPAT) -print-file-name=include 2>/dev/null)
 VDSO_CPPFLAGS += $(LINUXINCLUDE)
 
 # Common C and assembly flags
@@ -190,7 +191,7 @@
       cmd_vdsosym = $(NM) $< | $(gen-vdsosym) | LC_ALL=C sort > $@
 
 # Install commands for the unstripped file
-quiet_cmd_vdso_install = INSTALL $@
+quiet_cmd_vdso_install = INSTALL32 $@
       cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/vdso32.so
 
 vdso.so: $(obj)/vdso.so.dbg
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kernel/vmlinux.lds.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kernel/vmlinux.lds.S
@@ -24,6 +24,13 @@
 
 jiffies = jiffies_64;
 
+
+#define HYPERVISOR_EXTABLE					\
+	. = ALIGN(SZ_8);					\
+	__start___kvm_ex_table = .;				\
+	*(__kvm_ex_table)					\
+	__stop___kvm_ex_table = .;
+
 #define HYPERVISOR_TEXT					\
 	/*						\
 	 * Align to 4 KB so that			\
@@ -39,6 +46,7 @@
 	__hyp_idmap_text_end = .;			\
 	__hyp_text_start = .;				\
 	*(.hyp.text)					\
+	HYPERVISOR_EXTABLE				\
 	__hyp_text_end = .;
 
 #define IDMAP_TEXT					\
@@ -142,28 +150,30 @@
 	. = ALIGN(PAGE_SIZE);
 	idmap_pg_dir = .;
 	. += IDMAP_DIR_SIZE;
+	idmap_pg_end = .;
 
 #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
 	tramp_pg_dir = .;
 	. += PAGE_SIZE;
 #endif
 
-#ifdef CONFIG_ARM64_SW_TTBR0_PAN
-	reserved_ttbr0 = .;
-	. += RESERVED_TTBR0_SIZE;
-#endif
+	reserved_pg_dir = .;
+	. += PAGE_SIZE;
+
 	swapper_pg_dir = .;
 	. += PAGE_SIZE;
-	swapper_pg_end = .;
 
 	. = ALIGN(SEGMENT_ALIGN);
 	__init_begin = .;
 	__inittext_begin = .;
 
 	INIT_TEXT_SECTION(8)
+
+	__exittext_begin = .;
 	.exit.text : {
 		ARM_EXIT_KEEP(EXIT_TEXT)
 	}
+	__exittext_end = .;
 
 	. = ALIGN(4);
 	.altinstructions : {
@@ -171,9 +181,6 @@
 		*(.altinstructions)
 		__alt_instructions_end = .;
 	}
-	.altinstr_replacement : {
-		*(.altinstr_replacement)
-	}
 
 	. = ALIGN(PAGE_SIZE);
 	__inittext_end = .;
@@ -269,7 +276,7 @@
 	<= SZ_4K, "Hibernate exit text too big or misaligned")
 #endif
 #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
-ASSERT((__entry_tramp_text_end - __entry_tramp_text_start) == PAGE_SIZE,
+ASSERT((__entry_tramp_text_end - __entry_tramp_text_start) <= 3*PAGE_SIZE,
 	"Entry trampoline text too big")
 #endif
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kvm/debug.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kvm/debug.c
@@ -69,6 +69,64 @@
 }
 
 /**
+ * kvm_arm_setup_mdcr_el2 - configure vcpu mdcr_el2 value
+ *
+ * @vcpu:	the vcpu pointer
+ *
+ * This ensures we will trap access to:
+ *  - Performance monitors (MDCR_EL2_TPM/MDCR_EL2_TPMCR)
+ *  - Debug ROM Address (MDCR_EL2_TDRA)
+ *  - OS related registers (MDCR_EL2_TDOSA)
+ *  - Statistical profiler (MDCR_EL2_TPMS/MDCR_EL2_E2PB)
+ *  - Self-hosted Trace Filter controls (MDCR_EL2_TTRF)
+ */
+static void kvm_arm_setup_mdcr_el2(struct kvm_vcpu *vcpu)
+{
+	/*
+	 * This also clears MDCR_EL2_E2PB_MASK to disable guest access
+	 * to the profiling buffer.
+	 */
+	vcpu->arch.mdcr_el2 = __this_cpu_read(mdcr_el2) & MDCR_EL2_HPMN_MASK;
+	vcpu->arch.mdcr_el2 |= (MDCR_EL2_TPM |
+				MDCR_EL2_TPMS |
+				MDCR_EL2_TTRF |
+				MDCR_EL2_TPMCR |
+				MDCR_EL2_TDRA |
+				MDCR_EL2_TDOSA);
+
+	/* Is the VM being debugged by userspace? */
+	if (vcpu->guest_debug)
+		/* Route all software debug exceptions to EL2 */
+		vcpu->arch.mdcr_el2 |= MDCR_EL2_TDE;
+
+	/*
+	 * Trap debug register access when one of the following is true:
+	 *  - Userspace is using the hardware to debug the guest
+	 *  (KVM_GUESTDBG_USE_HW is set).
+	 *  - The guest is not using debug (KVM_ARM64_DEBUG_DIRTY is clear).
+	 */
+	if ((vcpu->guest_debug & KVM_GUESTDBG_USE_HW) ||
+	    !(vcpu->arch.flags & KVM_ARM64_DEBUG_DIRTY))
+		vcpu->arch.mdcr_el2 |= MDCR_EL2_TDA;
+
+	trace_kvm_arm_set_dreg32("MDCR_EL2", vcpu->arch.mdcr_el2);
+}
+
+/**
+ * kvm_arm_vcpu_init_debug - setup vcpu debug traps
+ *
+ * @vcpu:	the vcpu pointer
+ *
+ * Set vcpu initial mdcr_el2 value.
+ */
+void kvm_arm_vcpu_init_debug(struct kvm_vcpu *vcpu)
+{
+	preempt_disable();
+	kvm_arm_setup_mdcr_el2(vcpu);
+	preempt_enable();
+}
+
+/**
  * kvm_arm_reset_debug_ptr - reset the debug ptr to point to the vcpu state
  */
 
@@ -83,12 +141,7 @@
  * @vcpu:	the vcpu pointer
  *
  * This is called before each entry into the hypervisor to setup any
- * debug related registers. Currently this just ensures we will trap
- * access to:
- *  - Performance monitors (MDCR_EL2_TPM/MDCR_EL2_TPMCR)
- *  - Debug ROM Address (MDCR_EL2_TDRA)
- *  - OS related registers (MDCR_EL2_TDOSA)
- *  - Statistical profiler (MDCR_EL2_TPMS/MDCR_EL2_E2PB)
+ * debug related registers.
  *
  * Additionally, KVM only traps guest accesses to the debug registers if
  * the guest is not actively using them (see the KVM_ARM64_DEBUG_DIRTY
@@ -100,27 +153,14 @@
 
 void kvm_arm_setup_debug(struct kvm_vcpu *vcpu)
 {
-	bool trap_debug = !(vcpu->arch.flags & KVM_ARM64_DEBUG_DIRTY);
-	unsigned long mdscr;
+	unsigned long mdscr, orig_mdcr_el2 = vcpu->arch.mdcr_el2;
 
 	trace_kvm_arm_setup_debug(vcpu, vcpu->guest_debug);
 
-	/*
-	 * This also clears MDCR_EL2_E2PB_MASK to disable guest access
-	 * to the profiling buffer.
-	 */
-	vcpu->arch.mdcr_el2 = __this_cpu_read(mdcr_el2) & MDCR_EL2_HPMN_MASK;
-	vcpu->arch.mdcr_el2 |= (MDCR_EL2_TPM |
-				MDCR_EL2_TPMS |
-				MDCR_EL2_TPMCR |
-				MDCR_EL2_TDRA |
-				MDCR_EL2_TDOSA);
+	kvm_arm_setup_mdcr_el2(vcpu);
 
 	/* Is Guest debugging in effect? */
 	if (vcpu->guest_debug) {
-		/* Route all software debug exceptions to EL2 */
-		vcpu->arch.mdcr_el2 |= MDCR_EL2_TDE;
-
 		/* Save guest debug state */
 		save_guest_debug_regs(vcpu);
 
@@ -174,7 +214,6 @@
 
 			vcpu->arch.debug_ptr = &vcpu->arch.external_debug_state;
 			vcpu->arch.flags |= KVM_ARM64_DEBUG_DIRTY;
-			trap_debug = true;
 
 			trace_kvm_arm_set_regset("BKPTS", get_num_brps(),
 						&vcpu->arch.debug_ptr->dbg_bcr[0],
@@ -189,15 +228,14 @@
 	BUG_ON(!vcpu->guest_debug &&
 		vcpu->arch.debug_ptr != &vcpu->arch.vcpu_debug_state);
 
-	/* Trap debug register access */
-	if (trap_debug)
-		vcpu->arch.mdcr_el2 |= MDCR_EL2_TDA;
-
 	/* If KDE or MDE are set, perform a full save/restore cycle. */
 	if (vcpu_read_sys_reg(vcpu, MDSCR_EL1) & (DBG_MDSCR_KDE | DBG_MDSCR_MDE))
 		vcpu->arch.flags |= KVM_ARM64_DEBUG_DIRTY;
 
-	trace_kvm_arm_set_dreg32("MDCR_EL2", vcpu->arch.mdcr_el2);
+	/* Write mdcr_el2 changes since vcpu_load on VHE systems */
+	if (has_vhe() && orig_mdcr_el2 != vcpu->arch.mdcr_el2)
+		write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2);
+
 	trace_kvm_arm_set_dreg32("MDSCR_EL1", vcpu_read_sys_reg(vcpu, MDSCR_EL1));
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kvm/guest.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kvm/guest.c
@@ -186,6 +186,7 @@
 		case PSR_AA32_MODE_SVC:
 		case PSR_AA32_MODE_ABT:
 		case PSR_AA32_MODE_UND:
+		case PSR_AA32_MODE_SYS:
 			if (!vcpu_el1_is_32bit(vcpu))
 				return -EINVAL;
 			break;
@@ -202,6 +203,13 @@
 	}
 
 	memcpy((u32 *)regs + off, valp, KVM_REG_SIZE(reg->id));
+
+	if (*vcpu_cpsr(vcpu) & PSR_MODE32_BIT) {
+		int i;
+
+		for (i = 0; i < 16; i++)
+			*vcpu_reg32(vcpu, i) = (u32)*vcpu_reg32(vcpu, i);
+	}
 out:
 	return err;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kvm/handle_exit.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kvm/handle_exit.c
@@ -162,31 +162,16 @@
 	return 1;
 }
 
-#define __ptrauth_save_key(regs, key)						\
-({										\
-	regs[key ## KEYLO_EL1] = read_sysreg_s(SYS_ ## key ## KEYLO_EL1);	\
-	regs[key ## KEYHI_EL1] = read_sysreg_s(SYS_ ## key ## KEYHI_EL1);	\
-})
-
 /*
  * Handle the guest trying to use a ptrauth instruction, or trying to access a
  * ptrauth register.
  */
 void kvm_arm_vcpu_ptrauth_trap(struct kvm_vcpu *vcpu)
 {
-	struct kvm_cpu_context *ctxt;
-
-	if (vcpu_has_ptrauth(vcpu)) {
+	if (vcpu_has_ptrauth(vcpu))
 		vcpu_ptrauth_enable(vcpu);
-		ctxt = vcpu->arch.host_cpu_context;
-		__ptrauth_save_key(ctxt->sys_regs, APIA);
-		__ptrauth_save_key(ctxt->sys_regs, APIB);
-		__ptrauth_save_key(ctxt->sys_regs, APDA);
-		__ptrauth_save_key(ctxt->sys_regs, APDB);
-		__ptrauth_save_key(ctxt->sys_regs, APGA);
-	} else {
+	else
 		kvm_inject_undefined(vcpu);
-	}
 }
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kvm/hyp-init.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kvm/hyp-init.S
@@ -136,11 +136,15 @@
 
 1:	cmp	x0, #HVC_RESET_VECTORS
 	b.ne	1f
-reset:
+
 	/*
-	 * Reset kvm back to the hyp stub. Do not clobber x0-x4 in
-	 * case we coming via HVC_SOFT_RESTART.
+	 * Set the HVC_RESET_VECTORS return code before entering the common
+	 * path so that we do not clobber x0-x2 in case we are coming via
+	 * HVC_SOFT_RESTART.
 	 */
+	mov	x0, xzr
+reset:
+	/* Reset kvm back to the hyp stub. */
 	mrs	x5, sctlr_el2
 	ldr	x6, =SCTLR_ELx_FLAGS
 	bic	x5, x5, x6		// Clear SCTL_M and etc
@@ -151,7 +155,6 @@
 	/* Install stub vectors */
 	adr_l	x5, __hyp_stub_vectors
 	msr	vbar_el2, x5
-	mov	x0, xzr
 	eret
 
 1:	/* Bad stub call */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kvm/hyp/debug-sr.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kvm/hyp/debug-sr.c
@@ -168,6 +168,21 @@
 	write_sysreg(ctxt->sys_regs[MDCCINT_EL1], mdccint_el1);
 }
 
+void __hyp_text __debug_save_host_buffers_nvhe(struct kvm_vcpu *vcpu)
+{
+	/*
+	 * Non-VHE: Disable and flush SPE data generation
+	 * VHE: The vcpu can run, but it can't hide.
+	 */
+	__debug_save_spe_nvhe(&vcpu->arch.host_debug_state.pmscr_el1);
+
+}
+
+void __hyp_text __debug_restore_host_buffers_nvhe(struct kvm_vcpu *vcpu)
+{
+	__debug_restore_spe_nvhe(vcpu->arch.host_debug_state.pmscr_el1);
+}
+
 void __hyp_text __debug_switch_to_guest(struct kvm_vcpu *vcpu)
 {
 	struct kvm_cpu_context *host_ctxt;
@@ -175,13 +190,6 @@
 	struct kvm_guest_debug_arch *host_dbg;
 	struct kvm_guest_debug_arch *guest_dbg;
 
-	/*
-	 * Non-VHE: Disable and flush SPE data generation
-	 * VHE: The vcpu can run, but it can't hide.
-	 */
-	if (!has_vhe())
-		__debug_save_spe_nvhe(&vcpu->arch.host_debug_state.pmscr_el1);
-
 	if (!(vcpu->arch.flags & KVM_ARM64_DEBUG_DIRTY))
 		return;
 
@@ -201,8 +209,6 @@
 	struct kvm_guest_debug_arch *host_dbg;
 	struct kvm_guest_debug_arch *guest_dbg;
 
-	if (!has_vhe())
-		__debug_restore_spe_nvhe(vcpu->arch.host_debug_state.pmscr_el1);
 
 	if (!(vcpu->arch.flags & KVM_ARM64_DEBUG_DIRTY))
 		return;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kvm/hyp/entry.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kvm/hyp/entry.S
@@ -173,20 +173,23 @@
 	// This is our single instruction exception window. A pending
 	// SError is guaranteed to occur at the earliest when we unmask
 	// it, and at the latest just after the ISB.
-	.global	abort_guest_exit_start
 abort_guest_exit_start:
 
 	isb
 
-	.global	abort_guest_exit_end
 abort_guest_exit_end:
 
 	msr	daifset, #4	// Mask aborts
+	ret
 
-	// If the exception took place, restore the EL1 exception
-	// context so that we can report some information.
-	// Merge the exception code with the SError pending bit.
-	tbz	x0, #ARM_EXIT_WITH_SERROR_BIT, 1f
+	_kvm_extable	abort_guest_exit_start, 9997f
+	_kvm_extable	abort_guest_exit_end, 9997f
+9997:
+	msr	daifset, #4	// Mask aborts
+	mov	x0, #(1 << ARM_EXIT_WITH_SERROR_BIT)
+
+	// restore the EL1 exception context so that we can report some
+	// information. Merge the exception code with the SError pending bit.
 	msr	elr_el2, x2
 	msr	esr_el2, x3
 	msr	spsr_el2, x4
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kvm/hyp/hyp-entry.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kvm/hyp/hyp-entry.S
@@ -15,6 +15,30 @@
 #include <asm/kvm_mmu.h>
 #include <asm/mmu.h>
 
+.macro save_caller_saved_regs_vect
+	/* x0 and x1 were saved in the vector entry */
+	stp	x2, x3,   [sp, #-16]!
+	stp	x4, x5,   [sp, #-16]!
+	stp	x6, x7,   [sp, #-16]!
+	stp	x8, x9,   [sp, #-16]!
+	stp	x10, x11, [sp, #-16]!
+	stp	x12, x13, [sp, #-16]!
+	stp	x14, x15, [sp, #-16]!
+	stp	x16, x17, [sp, #-16]!
+.endm
+
+.macro restore_caller_saved_regs_vect
+	ldp	x16, x17, [sp], #16
+	ldp	x14, x15, [sp], #16
+	ldp	x12, x13, [sp], #16
+	ldp	x10, x11, [sp], #16
+	ldp	x8, x9,   [sp], #16
+	ldp	x6, x7,   [sp], #16
+	ldp	x4, x5,   [sp], #16
+	ldp	x2, x3,   [sp], #16
+	ldp	x0, x1,   [sp], #16
+.endm
+
 	.text
 	.pushsection	.hyp.text, "ax"
 
@@ -89,6 +113,10 @@
 	/* ARM_SMCCC_ARCH_WORKAROUND_2 handling */
 	eor	w1, w1, #(ARM_SMCCC_ARCH_WORKAROUND_1 ^ \
 			  ARM_SMCCC_ARCH_WORKAROUND_2)
+	cbz	w1, wa_epilogue
+
+	eor	w1, w1, #(ARM_SMCCC_ARCH_WORKAROUND_2 ^ \
+			  ARM_SMCCC_ARCH_WORKAROUND_3)
 	cbnz	w1, el1_trap
 
 #ifdef CONFIG_ARM64_SSBD
@@ -142,13 +170,19 @@
 	b	__guest_exit
 
 el2_sync:
-	/* Check for illegal exception return, otherwise panic */
+	/* Check for illegal exception return */
 	mrs	x0, spsr_el2
+	tbnz	x0, #20, 1f
 
-	/* if this was something else, then panic! */
-	tst	x0, #PSR_IL_BIT
-	b.eq	__hyp_panic
+	save_caller_saved_regs_vect
+	stp     x29, x30, [sp, #-16]!
+	bl	kvm_unexpected_el2_exception
+	ldp     x29, x30, [sp], #16
+	restore_caller_saved_regs_vect
+
+	eret
 
+1:
 	/* Let's attempt a recovery from the illegal exception return */
 	get_vcpu_ptr	x1, x0
 	mov	x0, #ARM_EXCEPTION_IL
@@ -156,27 +190,14 @@
 
 
 el2_error:
-	ldp	x0, x1, [sp], #16
+	save_caller_saved_regs_vect
+	stp     x29, x30, [sp, #-16]!
+
+	bl	kvm_unexpected_el2_exception
+
+	ldp     x29, x30, [sp], #16
+	restore_caller_saved_regs_vect
 
-	/*
-	 * Only two possibilities:
-	 * 1) Either we come from the exit path, having just unmasked
-	 *    PSTATE.A: change the return code to an EL2 fault, and
-	 *    carry on, as we're already in a sane state to handle it.
-	 * 2) Or we come from anywhere else, and that's a bug: we panic.
-	 *
-	 * For (1), x0 contains the original return code and x1 doesn't
-	 * contain anything meaningful at that stage. We can reuse them
-	 * as temp registers.
-	 * For (2), who cares?
-	 */
-	mrs	x0, elr_el2
-	adr	x1, abort_guest_exit_start
-	cmp	x0, x1
-	adr	x1, abort_guest_exit_end
-	ccmp	x0, x1, #4, ne
-	b.ne	__hyp_panic
-	mov	x0, #(1 << ARM_EXIT_WITH_SERROR_BIT)
 	eret
 	sb
 
@@ -330,4 +351,64 @@
 	ldp	x0, x1, [sp, #(8 * 2)]
 	add	sp, sp, #(8 * 4)
 ENTRY(__smccc_workaround_1_smc_end)
+
+ENTRY(__smccc_workaround_3_smc_start)
+	esb
+	sub	sp, sp, #(8 * 4)
+	stp	x2, x3, [sp, #(8 * 0)]
+	stp	x0, x1, [sp, #(8 * 2)]
+	mov	w0, #ARM_SMCCC_ARCH_WORKAROUND_3
+	smc	#0
+	ldp	x2, x3, [sp, #(8 * 0)]
+	ldp	x0, x1, [sp, #(8 * 2)]
+	add	sp, sp, #(8 * 4)
+ENTRY(__smccc_workaround_3_smc_end)
+
+ENTRY(__spectre_bhb_loop_k8_start)
+	esb
+	sub	sp, sp, #(8 * 2)
+	stp	x0, x1, [sp, #(8 * 0)]
+	mov	x0, #8
+2:	b	. + 4
+	subs	x0, x0, #1
+	b.ne	2b
+	dsb	nsh
+	isb
+	ldp	x0, x1, [sp, #(8 * 0)]
+	add	sp, sp, #(8 * 2)
+ENTRY(__spectre_bhb_loop_k8_end)
+
+ENTRY(__spectre_bhb_loop_k24_start)
+	esb
+	sub	sp, sp, #(8 * 2)
+	stp	x0, x1, [sp, #(8 * 0)]
+	mov	x0, #8
+2:	b	. + 4
+	subs	x0, x0, #1
+	b.ne	2b
+	dsb	nsh
+	isb
+	ldp	x0, x1, [sp, #(8 * 0)]
+	add	sp, sp, #(8 * 2)
+ENTRY(__spectre_bhb_loop_k24_end)
+
+ENTRY(__spectre_bhb_loop_k32_start)
+	esb
+	sub	sp, sp, #(8 * 2)
+	stp	x0, x1, [sp, #(8 * 0)]
+	mov     x0, #8
+2:	b	. + 4
+	subs	x0, x0, #1
+	b.ne	2b
+	dsb	nsh
+	isb
+	ldp	x0, x1, [sp, #(8 * 0)]
+	add	sp, sp, #(8 * 2)
+ENTRY(__spectre_bhb_loop_k32_end)
+
+ENTRY(__spectre_bhb_clearbhb_start)
+	esb
+	clearbhb
+	isb
+ENTRY(__spectre_bhb_clearbhb_end)
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kvm/hyp/switch.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kvm/hyp/switch.c
@@ -14,6 +14,7 @@
 
 #include <asm/arch_gicv3.h>
 #include <asm/cpufeature.h>
+#include <asm/extable.h>
 #include <asm/kprobes.h>
 #include <asm/kvm_asm.h>
 #include <asm/kvm_emulate.h>
@@ -24,11 +25,23 @@
 #include <asm/debug-monitors.h>
 #include <asm/processor.h>
 #include <asm/thread_info.h>
+#include <asm/vectors.h>
+
+extern struct exception_table_entry __start___kvm_ex_table;
+extern struct exception_table_entry __stop___kvm_ex_table;
 
 /* Check whether the FP regs were dirtied while in the host-side run loop: */
 static bool __hyp_text update_fp_enabled(struct kvm_vcpu *vcpu)
 {
-	if (vcpu->arch.host_thread_info->flags & _TIF_FOREIGN_FPSTATE)
+	/*
+	 * When the system doesn't support FP/SIMD, we cannot rely on
+	 * the _TIF_FOREIGN_FPSTATE flag. However, we always inject an
+	 * abort on the very first access to FP and thus we should never
+	 * see KVM_ARM64_FP_ENABLED. For added safety, make sure we always
+	 * trap the accesses.
+	 */
+	if (!system_supports_fpsimd() ||
+	    vcpu->arch.host_thread_info->flags & _TIF_FOREIGN_FPSTATE)
 		vcpu->arch.flags &= ~(KVM_ARM64_FP_ENABLED |
 				      KVM_ARM64_FP_HOST);
 
@@ -140,7 +153,7 @@
 
 static void deactivate_traps_vhe(void)
 {
-	extern char vectors[];	/* kernel exception vectors */
+	const char *host_vectors = vectors;
 	write_sysreg(HCR_HOST_VHE_FLAGS, hcr_el2);
 
 	/*
@@ -151,7 +164,10 @@
 	asm(ALTERNATIVE("nop", "isb", ARM64_WORKAROUND_1165522));
 
 	write_sysreg(CPACR_EL1_DEFAULT, cpacr_el1);
-	write_sysreg(vectors, vbar_el1);
+
+	if (!arm64_kernel_unmapped_at_el0())
+		host_vectors = __this_cpu_read(this_cpu_vector);
+	write_sysreg(host_vectors, vbar_el1);
 }
 NOKPROBE_SYMBOL(deactivate_traps_vhe);
 
@@ -249,10 +265,10 @@
 	 * saved the guest context yet, and we may return early...
 	 */
 	par = read_sysreg(par_el1);
-	asm volatile("at s1e1r, %0" : : "r" (far));
-	isb();
-
-	tmp = read_sysreg(par_el1);
+	if (!__kvm_at("s1e1r", far))
+		tmp = read_sysreg(par_el1);
+	else
+		tmp = SYS_PAR_EL1_F; /* back to the guest */
 	write_sysreg(par, par_el1);
 
 	if (unlikely(tmp & SYS_PAR_EL1_F))
@@ -484,7 +500,7 @@
 			kvm_vcpu_trap_get_fault_type(vcpu) == FSC_FAULT &&
 			kvm_vcpu_dabt_isvalid(vcpu) &&
 			!kvm_vcpu_dabt_isextabt(vcpu) &&
-			!kvm_vcpu_dabt_iss1tw(vcpu);
+			!kvm_vcpu_abt_iss1tw(vcpu);
 
 		if (valid) {
 			int ret = __vgic_v2_perform_cpuif_access(vcpu);
@@ -670,6 +686,15 @@
 
 	__sysreg_save_state_nvhe(host_ctxt);
 
+	/*
+	 * We must flush and disable the SPE buffer for nVHE, as
+	 * the translation regime(EL1&0) is going to be loaded with
+	 * that of the guest. And we must do this before we change the
+	 * translation regime to EL2 (via MDCR_EL2_EPB == 0) and
+	 * before we load guest Stage1.
+	 */
+	__debug_save_host_buffers_nvhe(vcpu);
+
 	__activate_vm(kern_hyp_va(vcpu->kvm));
 	__activate_traps(vcpu);
 
@@ -708,11 +733,13 @@
 	if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED)
 		__fpsimd_save_fpexc32(vcpu);
 
+	__debug_switch_to_host(vcpu);
+
 	/*
 	 * This must come after restoring the host sysregs, since a non-VHE
 	 * system may enable SPE here and make use of the TTBRs.
 	 */
-	__debug_switch_to_host(vcpu);
+	__debug_restore_host_buffers_nvhe(vcpu);
 
 	if (pmu_switch_needed)
 		__pmu_switch_to_host(host_ctxt);
@@ -746,7 +773,7 @@
 	 * making sure it is a kernel address and not a PC-relative
 	 * reference.
 	 */
-	asm volatile("ldr %0, =__hyp_panic_string" : "=r" (str_va));
+	asm volatile("ldr %0, =%1" : "=r" (str_va) : "S" (__hyp_panic_string));
 
 	__hyp_do_panic(str_va,
 		       spsr, elr,
@@ -783,3 +810,30 @@
 
 	unreachable();
 }
+
+asmlinkage void __hyp_text kvm_unexpected_el2_exception(void)
+{
+	unsigned long addr, fixup;
+	struct kvm_cpu_context *host_ctxt;
+	struct exception_table_entry *entry, *end;
+	unsigned long elr_el2 = read_sysreg(elr_el2);
+
+	entry = hyp_symbol_addr(__start___kvm_ex_table);
+	end = hyp_symbol_addr(__stop___kvm_ex_table);
+	host_ctxt = &__hyp_this_cpu_ptr(kvm_host_data)->host_ctxt;
+
+	while (entry < end) {
+		addr = (unsigned long)&entry->insn + entry->insn;
+		fixup = (unsigned long)&entry->fixup + entry->fixup;
+
+		if (addr != elr_el2) {
+			entry++;
+			continue;
+		}
+
+		write_sysreg(fixup, elr_el2);
+		return;
+	}
+
+	hyp_panic(host_ctxt);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kvm/hyp/tlb.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kvm/hyp/tlb.c
@@ -182,7 +182,7 @@
 	__tlb_switch_to_host(kvm, &cxt);
 }
 
-void __hyp_text __kvm_tlb_flush_local_vmid(struct kvm_vcpu *vcpu)
+void __hyp_text __kvm_flush_cpu_context(struct kvm_vcpu *vcpu)
 {
 	struct kvm *kvm = kern_hyp_va(kern_hyp_va(vcpu)->kvm);
 	struct tlb_inv_context cxt;
@@ -191,6 +191,7 @@
 	__tlb_switch_to_guest(kvm, &cxt);
 
 	__tlbi(vmalle1);
+	asm volatile("ic iallu");
 	dsb(nsh);
 	isb();
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kvm/inject_fault.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kvm/inject_fault.c
@@ -14,9 +14,6 @@
 #include <asm/kvm_emulate.h>
 #include <asm/esr.h>
 
-#define PSTATE_FAULT_BITS_64 	(PSR_MODE_EL1h | PSR_A_BIT | PSR_F_BIT | \
-				 PSR_I_BIT | PSR_D_BIT)
-
 #define CURRENT_EL_SP_EL0_VECTOR	0x0
 #define CURRENT_EL_SP_ELx_VECTOR	0x200
 #define LOWER_EL_AArch64_VECTOR		0x400
@@ -50,6 +47,69 @@
 	return vcpu_read_sys_reg(vcpu, VBAR_EL1) + exc_offset + type;
 }
 
+/*
+ * When an exception is taken, most PSTATE fields are left unchanged in the
+ * handler. However, some are explicitly overridden (e.g. M[4:0]). Luckily all
+ * of the inherited bits have the same position in the AArch64/AArch32 SPSR_ELx
+ * layouts, so we don't need to shuffle these for exceptions from AArch32 EL0.
+ *
+ * For the SPSR_ELx layout for AArch64, see ARM DDI 0487E.a page C5-429.
+ * For the SPSR_ELx layout for AArch32, see ARM DDI 0487E.a page C5-426.
+ *
+ * Here we manipulate the fields in order of the AArch64 SPSR_ELx layout, from
+ * MSB to LSB.
+ */
+static unsigned long get_except64_pstate(struct kvm_vcpu *vcpu)
+{
+	unsigned long sctlr = vcpu_read_sys_reg(vcpu, SCTLR_EL1);
+	unsigned long old, new;
+
+	old = *vcpu_cpsr(vcpu);
+	new = 0;
+
+	new |= (old & PSR_N_BIT);
+	new |= (old & PSR_Z_BIT);
+	new |= (old & PSR_C_BIT);
+	new |= (old & PSR_V_BIT);
+
+	// TODO: TCO (if/when ARMv8.5-MemTag is exposed to guests)
+
+	new |= (old & PSR_DIT_BIT);
+
+	// PSTATE.UAO is set to zero upon any exception to AArch64
+	// See ARM DDI 0487E.a, page D5-2579.
+
+	// PSTATE.PAN is unchanged unless SCTLR_ELx.SPAN == 0b0
+	// SCTLR_ELx.SPAN is RES1 when ARMv8.1-PAN is not implemented
+	// See ARM DDI 0487E.a, page D5-2578.
+	new |= (old & PSR_PAN_BIT);
+	if (!(sctlr & SCTLR_EL1_SPAN))
+		new |= PSR_PAN_BIT;
+
+	// PSTATE.SS is set to zero upon any exception to AArch64
+	// See ARM DDI 0487E.a, page D2-2452.
+
+	// PSTATE.IL is set to zero upon any exception to AArch64
+	// See ARM DDI 0487E.a, page D1-2306.
+
+	// PSTATE.SSBS is set to SCTLR_ELx.DSSBS upon any exception to AArch64
+	// See ARM DDI 0487E.a, page D13-3258
+	if (sctlr & SCTLR_ELx_DSSBS)
+		new |= PSR_SSBS_BIT;
+
+	// PSTATE.BTYPE is set to zero upon any exception to AArch64
+	// See ARM DDI 0487E.a, pages D1-2293 to D1-2294.
+
+	new |= PSR_D_BIT;
+	new |= PSR_A_BIT;
+	new |= PSR_I_BIT;
+	new |= PSR_F_BIT;
+
+	new |= PSR_MODE_EL1h;
+
+	return new;
+}
+
 static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr)
 {
 	unsigned long cpsr = *vcpu_cpsr(vcpu);
@@ -59,7 +119,7 @@
 	vcpu_write_elr_el1(vcpu, *vcpu_pc(vcpu));
 	*vcpu_pc(vcpu) = get_except_vector(vcpu, except_type_sync);
 
-	*vcpu_cpsr(vcpu) = PSTATE_FAULT_BITS_64;
+	*vcpu_cpsr(vcpu) = get_except64_pstate(vcpu);
 	vcpu_write_spsr(vcpu, cpsr);
 
 	vcpu_write_sys_reg(vcpu, addr, FAR_EL1);
@@ -94,7 +154,7 @@
 	vcpu_write_elr_el1(vcpu, *vcpu_pc(vcpu));
 	*vcpu_pc(vcpu) = get_except_vector(vcpu, except_type_sync);
 
-	*vcpu_cpsr(vcpu) = PSTATE_FAULT_BITS_64;
+	*vcpu_cpsr(vcpu) = get_except64_pstate(vcpu);
 	vcpu_write_spsr(vcpu, cpsr);
 
 	/*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kvm/reset.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kvm/reset.c
@@ -258,7 +258,7 @@
 int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
 {
 	const struct kvm_regs *cpu_reset;
-	int ret = -EINVAL;
+	int ret;
 	bool loaded;
 
 	/* Reset PMU outside of the non-preemptible section */
@@ -281,15 +281,19 @@
 
 	if (test_bit(KVM_ARM_VCPU_PTRAUTH_ADDRESS, vcpu->arch.features) ||
 	    test_bit(KVM_ARM_VCPU_PTRAUTH_GENERIC, vcpu->arch.features)) {
-		if (kvm_vcpu_enable_ptrauth(vcpu))
+		if (kvm_vcpu_enable_ptrauth(vcpu)) {
+			ret = -EINVAL;
 			goto out;
+		}
 	}
 
 	switch (vcpu->arch.target) {
 	default:
 		if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features)) {
-			if (!cpu_has_32bit_el1())
+			if (!cpu_has_32bit_el1()) {
+				ret = -EINVAL;
 				goto out;
+			}
 			cpu_reset = &default_regs_reset32;
 		} else {
 			cpu_reset = &default_regs_reset;
@@ -374,10 +378,10 @@
 		pr_info("kvm: Limiting the IPA size due to kernel %s Address limit\n",
 			(va_max < pa_max) ? "Virtual" : "Physical");
 
-	WARN(ipa_max < KVM_PHYS_SHIFT,
-	     "KVM IPA limit (%d bit) is smaller than default size\n", ipa_max);
 	kvm_ipa_limit = ipa_max;
-	kvm_info("IPA Size Limit: %dbits\n", kvm_ipa_limit);
+	kvm_info("IPA Size Limit: %d bits%s\n", kvm_ipa_limit,
+		 ((kvm_ipa_limit < KVM_PHYS_SHIFT) ?
+		  " (Reduced IPA size, limited VM/VMM compatibility)" : ""));
 }
 
 /*
@@ -404,6 +408,11 @@
 			return -EINVAL;
 	} else {
 		phys_shift = KVM_PHYS_SHIFT;
+		if (phys_shift > kvm_ipa_limit) {
+			pr_warn_once("%s using unsupported default IPA limit, upgrade your VMM\n",
+				     current->comm);
+			return -EINVAL;
+		}
 	}
 
 	parange = read_sanitised_ftr_reg(SYS_ID_AA64MMFR0_EL1) & 7;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/kvm/sys_regs.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/kvm/sys_regs.c
@@ -432,14 +432,14 @@
 		     struct sys_reg_params *p,
 		     const struct sys_reg_desc *rd)
 {
-	u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_bvr[rd->reg];
+	u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_bvr[rd->CRm];
 
 	if (p->is_write)
 		reg_to_dbg(vcpu, p, dbg_reg);
 	else
 		dbg_to_reg(vcpu, p, dbg_reg);
 
-	trace_trap_reg(__func__, rd->reg, p->is_write, *dbg_reg);
+	trace_trap_reg(__func__, rd->CRm, p->is_write, *dbg_reg);
 
 	return true;
 }
@@ -447,7 +447,7 @@
 static int set_bvr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
 		const struct kvm_one_reg *reg, void __user *uaddr)
 {
-	__u64 *r = &vcpu->arch.vcpu_debug_state.dbg_bvr[rd->reg];
+	__u64 *r = &vcpu->arch.vcpu_debug_state.dbg_bvr[rd->CRm];
 
 	if (copy_from_user(r, uaddr, KVM_REG_SIZE(reg->id)) != 0)
 		return -EFAULT;
@@ -457,7 +457,7 @@
 static int get_bvr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
 	const struct kvm_one_reg *reg, void __user *uaddr)
 {
-	__u64 *r = &vcpu->arch.vcpu_debug_state.dbg_bvr[rd->reg];
+	__u64 *r = &vcpu->arch.vcpu_debug_state.dbg_bvr[rd->CRm];
 
 	if (copy_to_user(uaddr, r, KVM_REG_SIZE(reg->id)) != 0)
 		return -EFAULT;
@@ -467,21 +467,21 @@
 static void reset_bvr(struct kvm_vcpu *vcpu,
 		      const struct sys_reg_desc *rd)
 {
-	vcpu->arch.vcpu_debug_state.dbg_bvr[rd->reg] = rd->val;
+	vcpu->arch.vcpu_debug_state.dbg_bvr[rd->CRm] = rd->val;
 }
 
 static bool trap_bcr(struct kvm_vcpu *vcpu,
 		     struct sys_reg_params *p,
 		     const struct sys_reg_desc *rd)
 {
-	u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_bcr[rd->reg];
+	u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_bcr[rd->CRm];
 
 	if (p->is_write)
 		reg_to_dbg(vcpu, p, dbg_reg);
 	else
 		dbg_to_reg(vcpu, p, dbg_reg);
 
-	trace_trap_reg(__func__, rd->reg, p->is_write, *dbg_reg);
+	trace_trap_reg(__func__, rd->CRm, p->is_write, *dbg_reg);
 
 	return true;
 }
@@ -489,7 +489,7 @@
 static int set_bcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
 		const struct kvm_one_reg *reg, void __user *uaddr)
 {
-	__u64 *r = &vcpu->arch.vcpu_debug_state.dbg_bcr[rd->reg];
+	__u64 *r = &vcpu->arch.vcpu_debug_state.dbg_bcr[rd->CRm];
 
 	if (copy_from_user(r, uaddr, KVM_REG_SIZE(reg->id)) != 0)
 		return -EFAULT;
@@ -500,7 +500,7 @@
 static int get_bcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
 	const struct kvm_one_reg *reg, void __user *uaddr)
 {
-	__u64 *r = &vcpu->arch.vcpu_debug_state.dbg_bcr[rd->reg];
+	__u64 *r = &vcpu->arch.vcpu_debug_state.dbg_bcr[rd->CRm];
 
 	if (copy_to_user(uaddr, r, KVM_REG_SIZE(reg->id)) != 0)
 		return -EFAULT;
@@ -510,22 +510,22 @@
 static void reset_bcr(struct kvm_vcpu *vcpu,
 		      const struct sys_reg_desc *rd)
 {
-	vcpu->arch.vcpu_debug_state.dbg_bcr[rd->reg] = rd->val;
+	vcpu->arch.vcpu_debug_state.dbg_bcr[rd->CRm] = rd->val;
 }
 
 static bool trap_wvr(struct kvm_vcpu *vcpu,
 		     struct sys_reg_params *p,
 		     const struct sys_reg_desc *rd)
 {
-	u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_wvr[rd->reg];
+	u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_wvr[rd->CRm];
 
 	if (p->is_write)
 		reg_to_dbg(vcpu, p, dbg_reg);
 	else
 		dbg_to_reg(vcpu, p, dbg_reg);
 
-	trace_trap_reg(__func__, rd->reg, p->is_write,
-		vcpu->arch.vcpu_debug_state.dbg_wvr[rd->reg]);
+	trace_trap_reg(__func__, rd->CRm, p->is_write,
+		vcpu->arch.vcpu_debug_state.dbg_wvr[rd->CRm]);
 
 	return true;
 }
@@ -533,7 +533,7 @@
 static int set_wvr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
 		const struct kvm_one_reg *reg, void __user *uaddr)
 {
-	__u64 *r = &vcpu->arch.vcpu_debug_state.dbg_wvr[rd->reg];
+	__u64 *r = &vcpu->arch.vcpu_debug_state.dbg_wvr[rd->CRm];
 
 	if (copy_from_user(r, uaddr, KVM_REG_SIZE(reg->id)) != 0)
 		return -EFAULT;
@@ -543,7 +543,7 @@
 static int get_wvr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
 	const struct kvm_one_reg *reg, void __user *uaddr)
 {
-	__u64 *r = &vcpu->arch.vcpu_debug_state.dbg_wvr[rd->reg];
+	__u64 *r = &vcpu->arch.vcpu_debug_state.dbg_wvr[rd->CRm];
 
 	if (copy_to_user(uaddr, r, KVM_REG_SIZE(reg->id)) != 0)
 		return -EFAULT;
@@ -553,21 +553,21 @@
 static void reset_wvr(struct kvm_vcpu *vcpu,
 		      const struct sys_reg_desc *rd)
 {
-	vcpu->arch.vcpu_debug_state.dbg_wvr[rd->reg] = rd->val;
+	vcpu->arch.vcpu_debug_state.dbg_wvr[rd->CRm] = rd->val;
 }
 
 static bool trap_wcr(struct kvm_vcpu *vcpu,
 		     struct sys_reg_params *p,
 		     const struct sys_reg_desc *rd)
 {
-	u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_wcr[rd->reg];
+	u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_wcr[rd->CRm];
 
 	if (p->is_write)
 		reg_to_dbg(vcpu, p, dbg_reg);
 	else
 		dbg_to_reg(vcpu, p, dbg_reg);
 
-	trace_trap_reg(__func__, rd->reg, p->is_write, *dbg_reg);
+	trace_trap_reg(__func__, rd->CRm, p->is_write, *dbg_reg);
 
 	return true;
 }
@@ -575,7 +575,7 @@
 static int set_wcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
 		const struct kvm_one_reg *reg, void __user *uaddr)
 {
-	__u64 *r = &vcpu->arch.vcpu_debug_state.dbg_wcr[rd->reg];
+	__u64 *r = &vcpu->arch.vcpu_debug_state.dbg_wcr[rd->CRm];
 
 	if (copy_from_user(r, uaddr, KVM_REG_SIZE(reg->id)) != 0)
 		return -EFAULT;
@@ -585,7 +585,7 @@
 static int get_wcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
 	const struct kvm_one_reg *reg, void __user *uaddr)
 {
-	__u64 *r = &vcpu->arch.vcpu_debug_state.dbg_wcr[rd->reg];
+	__u64 *r = &vcpu->arch.vcpu_debug_state.dbg_wcr[rd->CRm];
 
 	if (copy_to_user(uaddr, r, KVM_REG_SIZE(reg->id)) != 0)
 		return -EFAULT;
@@ -595,7 +595,7 @@
 static void reset_wcr(struct kvm_vcpu *vcpu,
 		      const struct sys_reg_desc *rd)
 {
-	vcpu->arch.vcpu_debug_state.dbg_wcr[rd->reg] = rd->val;
+	vcpu->arch.vcpu_debug_state.dbg_wcr[rd->CRm] = rd->val;
 }
 
 static void reset_amair_el1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
@@ -625,6 +625,10 @@
 {
 	u64 pmcr, val;
 
+	/* No PMU available, PMCR_EL0 may UNDEF... */
+	if (!kvm_arm_support_pmu_v3())
+		return;
+
 	pmcr = read_sysreg(pmcr_el0);
 	/*
 	 * Writable bits of PMCR_EL0 (ARMV8_PMU_PMCR_MASK) are reset to UNKNOWN
@@ -1085,6 +1089,16 @@
 			 (0xfUL << ID_AA64ISAR1_API_SHIFT) |
 			 (0xfUL << ID_AA64ISAR1_GPA_SHIFT) |
 			 (0xfUL << ID_AA64ISAR1_GPI_SHIFT));
+	} else if (id == SYS_ID_AA64DFR0_EL1) {
+		/* Limit guests to PMUv3 for ARMv8.1 */
+		val = cpuid_feature_cap_perfmon_field(val,
+						ID_AA64DFR0_PMUVER_SHIFT,
+						ID_AA64DFR0_PMUVER_8_1);
+	} else if (id == SYS_ID_DFR0_EL1) {
+		/* Limit guests to PMUv3 for ARMv8.1 */
+		val = cpuid_feature_cap_perfmon_field(val,
+						ID_DFR0_PERFMON_SHIFT,
+						ID_DFR0_PERFMON_8_1);
 	}
 
 	return val;
@@ -1132,16 +1146,6 @@
 	return REG_HIDDEN_USER | REG_HIDDEN_GUEST;
 }
 
-/* Visibility overrides for SVE-specific ID registers */
-static unsigned int sve_id_visibility(const struct kvm_vcpu *vcpu,
-				      const struct sys_reg_desc *rd)
-{
-	if (vcpu_has_sve(vcpu))
-		return 0;
-
-	return REG_HIDDEN_USER;
-}
-
 /* Generate the emulated ID_AA64ZFR0_EL1 value exposed to the guest */
 static u64 guest_id_aa64zfr0_el1(const struct kvm_vcpu *vcpu)
 {
@@ -1168,9 +1172,6 @@
 {
 	u64 val;
 
-	if (WARN_ON(!vcpu_has_sve(vcpu)))
-		return -ENOENT;
-
 	val = guest_id_aa64zfr0_el1(vcpu);
 	return reg_to_user(uaddr, &val, reg->id);
 }
@@ -1183,9 +1184,6 @@
 	int err;
 	u64 val;
 
-	if (WARN_ON(!vcpu_has_sve(vcpu)))
-		return -ENOENT;
-
 	err = reg_from_user(&val, uaddr, id);
 	if (err)
 		return err;
@@ -1280,10 +1278,16 @@
 static bool access_csselr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
 			  const struct sys_reg_desc *r)
 {
+	int reg = r->reg;
+
+	/* See the 32bit mapping in kvm_host.h */
+	if (p->is_aarch32)
+		reg = r->reg / 2;
+
 	if (p->is_write)
-		vcpu_write_sys_reg(vcpu, p->regval, r->reg);
+		vcpu_write_sys_reg(vcpu, p->regval, reg);
 	else
-		p->regval = vcpu_read_sys_reg(vcpu, r->reg);
+		p->regval = vcpu_read_sys_reg(vcpu, reg);
 	return true;
 }
 
@@ -1442,7 +1446,7 @@
 	ID_SANITISED(ID_AA64PFR1_EL1),
 	ID_UNALLOCATED(4,2),
 	ID_UNALLOCATED(4,3),
-	{ SYS_DESC(SYS_ID_AA64ZFR0_EL1), access_id_aa64zfr0_el1, .get_user = get_id_aa64zfr0_el1, .set_user = set_id_aa64zfr0_el1, .visibility = sve_id_visibility },
+	{ SYS_DESC(SYS_ID_AA64ZFR0_EL1), access_id_aa64zfr0_el1, .get_user = get_id_aa64zfr0_el1, .set_user = set_id_aa64zfr0_el1, },
 	ID_UNALLOCATED(4,5),
 	ID_UNALLOCATED(4,6),
 	ID_UNALLOCATED(4,7),
@@ -1460,7 +1464,7 @@
 	/* CRm=6 */
 	ID_SANITISED(ID_AA64ISAR0_EL1),
 	ID_SANITISED(ID_AA64ISAR1_EL1),
-	ID_UNALLOCATED(6,2),
+	ID_SANITISED(ID_AA64ISAR2_EL1),
 	ID_UNALLOCATED(6,3),
 	ID_UNALLOCATED(6,4),
 	ID_UNALLOCATED(6,5),
@@ -1740,9 +1744,9 @@
 	{ Op1( 0), CRn( 0), CRm( 1), Op2( 0), trap_raz_wi },
 	DBG_BCR_BVR_WCR_WVR(1),
 	/* DBGDCCINT */
-	{ Op1( 0), CRn( 0), CRm( 2), Op2( 0), trap_debug32 },
+	{ Op1( 0), CRn( 0), CRm( 2), Op2( 0), trap_debug32, NULL, cp14_DBGDCCINT },
 	/* DBGDSCRext */
-	{ Op1( 0), CRn( 0), CRm( 2), Op2( 2), trap_debug32 },
+	{ Op1( 0), CRn( 0), CRm( 2), Op2( 2), trap_debug32, NULL, cp14_DBGDSCRext },
 	DBG_BCR_BVR_WCR_WVR(2),
 	/* DBGDTR[RT]Xint */
 	{ Op1( 0), CRn( 0), CRm( 3), Op2( 0), trap_raz_wi },
@@ -1757,7 +1761,7 @@
 	{ Op1( 0), CRn( 0), CRm( 6), Op2( 2), trap_raz_wi },
 	DBG_BCR_BVR_WCR_WVR(6),
 	/* DBGVCR */
-	{ Op1( 0), CRn( 0), CRm( 7), Op2( 0), trap_debug32 },
+	{ Op1( 0), CRn( 0), CRm( 7), Op2( 0), trap_debug32, NULL, cp14_DBGVCR },
 	DBG_BCR_BVR_WCR_WVR(7),
 	DBG_BCR_BVR_WCR_WVR(8),
 	DBG_BCR_BVR_WCR_WVR(9),
@@ -1847,6 +1851,7 @@
 	{ Op1( 0), CRn( 2), CRm( 0), Op2( 0), access_vm_reg, NULL, c2_TTBR0 },
 	{ Op1( 0), CRn( 2), CRm( 0), Op2( 1), access_vm_reg, NULL, c2_TTBR1 },
 	{ Op1( 0), CRn( 2), CRm( 0), Op2( 2), access_vm_reg, NULL, c2_TTBCR },
+	{ Op1( 0), CRn( 2), CRm( 0), Op2( 3), access_vm_reg, NULL, c2_TTBCR2 },
 	{ Op1( 0), CRn( 3), CRm( 0), Op2( 0), access_vm_reg, NULL, c3_DACR },
 	{ Op1( 0), CRn( 5), CRm( 0), Op2( 0), access_vm_reg, NULL, c5_DFSR },
 	{ Op1( 0), CRn( 5), CRm( 0), Op2( 1), access_vm_reg, NULL, c5_IFSR },
@@ -2360,8 +2365,11 @@
 	if ((id & KVM_REG_ARM_COPROC_MASK) != KVM_REG_ARM64_SYSREG)
 		return NULL;
 
+	if (!index_to_params(id, &params))
+		return NULL;
+
 	table = get_target_table(vcpu->arch.target, true, &num);
-	r = find_reg_by_id(id, &params, table, num);
+	r = find_reg(&params, table, num);
 	if (!r)
 		r = find_reg(&params, sys_reg_descs, ARRAY_SIZE(sys_reg_descs));
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/lib/clear_page.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/lib/clear_page.S
@@ -14,7 +14,7 @@
  * Parameters:
  *	x0 - dest
  */
-ENTRY(clear_page)
+SYM_FUNC_START(clear_page)
 	mrs	x1, dczid_el0
 	and	w1, w1, #0xf
 	mov	x2, #4
@@ -25,5 +25,5 @@
 	tst	x0, #(PAGE_SIZE - 1)
 	b.ne	1b
 	ret
-ENDPROC(clear_page)
+SYM_FUNC_END(clear_page)
 EXPORT_SYMBOL(clear_page)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/lib/clear_user.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/lib/clear_user.S
@@ -19,7 +19,7 @@
  *
  * Alignment fixed up by hardware.
  */
-ENTRY(__arch_clear_user)
+SYM_FUNC_START(__arch_clear_user)
 	mov	x2, x1			// save the size for fixup return
 	subs	x1, x1, #8
 	b.mi	2f
@@ -40,7 +40,7 @@
 uao_user_alternative 9f, strb, sttrb, wzr, x0, 0
 5:	mov	x0, #0
 	ret
-ENDPROC(__arch_clear_user)
+SYM_FUNC_END(__arch_clear_user)
 EXPORT_SYMBOL(__arch_clear_user)
 
 	.section .fixup,"ax"
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/lib/copy_from_user.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/lib/copy_from_user.S
@@ -53,12 +53,12 @@
 	.endm
 
 end	.req	x5
-ENTRY(__arch_copy_from_user)
+SYM_FUNC_START(__arch_copy_from_user)
 	add	end, x0, x2
 #include "copy_template.S"
 	mov	x0, #0				// Nothing to copy
 	ret
-ENDPROC(__arch_copy_from_user)
+SYM_FUNC_END(__arch_copy_from_user)
 EXPORT_SYMBOL(__arch_copy_from_user)
 
 	.section .fixup,"ax"
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/lib/copy_in_user.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/lib/copy_in_user.S
@@ -55,12 +55,12 @@
 
 end	.req	x5
 
-ENTRY(__arch_copy_in_user)
+SYM_FUNC_START(__arch_copy_in_user)
 	add	end, x0, x2
 #include "copy_template.S"
 	mov	x0, #0
 	ret
-ENDPROC(__arch_copy_in_user)
+SYM_FUNC_END(__arch_copy_in_user)
 EXPORT_SYMBOL(__arch_copy_in_user)
 
 	.section .fixup,"ax"
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/lib/copy_page.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/lib/copy_page.S
@@ -17,7 +17,7 @@
  *	x0 - dest
  *	x1 - src
  */
-ENTRY(copy_page)
+SYM_FUNC_START(copy_page)
 alternative_if ARM64_HAS_NO_HW_PREFETCH
 	// Prefetch three cache lines ahead.
 	prfm	pldl1strm, [x1, #128]
@@ -75,5 +75,5 @@
 	stnp	x16, x17, [x0, #112]
 
 	ret
-ENDPROC(copy_page)
+SYM_FUNC_END(copy_page)
 EXPORT_SYMBOL(copy_page)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/lib/copy_to_user.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/lib/copy_to_user.S
@@ -52,12 +52,12 @@
 	.endm
 
 end	.req	x5
-ENTRY(__arch_copy_to_user)
+SYM_FUNC_START(__arch_copy_to_user)
 	add	end, x0, x2
 #include "copy_template.S"
 	mov	x0, #0
 	ret
-ENDPROC(__arch_copy_to_user)
+SYM_FUNC_END(__arch_copy_to_user)
 EXPORT_SYMBOL(__arch_copy_to_user)
 
 	.section .fixup,"ax"
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/lib/crc32.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/lib/crc32.S
@@ -85,17 +85,17 @@
 	.endm
 
 	.align		5
-ENTRY(crc32_le)
+SYM_FUNC_START(crc32_le)
 alternative_if_not ARM64_HAS_CRC32
 	b		crc32_le_base
 alternative_else_nop_endif
 	__crc32
-ENDPROC(crc32_le)
+SYM_FUNC_END(crc32_le)
 
 	.align		5
-ENTRY(__crc32c_le)
+SYM_FUNC_START(__crc32c_le)
 alternative_if_not ARM64_HAS_CRC32
 	b		__crc32c_le_base
 alternative_else_nop_endif
 	__crc32		c
-ENDPROC(__crc32c_le)
+SYM_FUNC_END(__crc32c_le)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/lib/memchr.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/lib/memchr.S
@@ -19,7 +19,7 @@
  * Returns:
  *	x0 - address of first occurrence of 'c' or 0
  */
-WEAK(memchr)
+SYM_FUNC_START_WEAK_PI(memchr)
 	and	w1, w1, #0xff
 1:	subs	x2, x2, #1
 	b.mi	2f
@@ -30,5 +30,5 @@
 	ret
 2:	mov	x0, #0
 	ret
-ENDPIPROC(memchr)
+SYM_FUNC_END_PI(memchr)
 EXPORT_SYMBOL_NOKASAN(memchr)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/lib/memcmp.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/lib/memcmp.S
@@ -46,7 +46,7 @@
 limit_wd	.req	x12
 mask		.req	x13
 
-WEAK(memcmp)
+SYM_FUNC_START_WEAK_PI(memcmp)
 	cbz	limit, .Lret0
 	eor	tmp1, src1, src2
 	tst	tmp1, #7
@@ -243,5 +243,5 @@
 .Lret0:
 	mov	result, #0
 	ret
-ENDPIPROC(memcmp)
+SYM_FUNC_END_PI(memcmp)
 EXPORT_SYMBOL_NOKASAN(memcmp)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/lib/memcpy.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/lib/memcpy.S
@@ -56,12 +56,11 @@
 	stp \ptr, \regB, [\regC], \val
 	.endm
 
-	.weak memcpy
-ENTRY(__memcpy)
-ENTRY(memcpy)
+SYM_FUNC_START_ALIAS(__memcpy)
+SYM_FUNC_START_WEAK_PI(memcpy)
 #include "copy_template.S"
 	ret
-ENDPIPROC(memcpy)
+SYM_FUNC_END_PI(memcpy)
 EXPORT_SYMBOL(memcpy)
-ENDPROC(__memcpy)
+SYM_FUNC_END_ALIAS(__memcpy)
 EXPORT_SYMBOL(__memcpy)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/lib/memmove.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/lib/memmove.S
@@ -45,9 +45,8 @@
 D_l	.req	x13
 D_h	.req	x14
 
-	.weak memmove
-ENTRY(__memmove)
-ENTRY(memmove)
+SYM_FUNC_START_ALIAS(__memmove)
+SYM_FUNC_START_WEAK_PI(memmove)
 	cmp	dstin, src
 	b.lo	__memcpy
 	add	tmp1, src, count
@@ -184,7 +183,7 @@
 	tst	count, #0x3f
 	b.ne	.Ltail63
 	ret
-ENDPIPROC(memmove)
+SYM_FUNC_END_PI(memmove)
 EXPORT_SYMBOL(memmove)
-ENDPROC(__memmove)
+SYM_FUNC_END_ALIAS(__memmove)
 EXPORT_SYMBOL(__memmove)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/lib/memset.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/lib/memset.S
@@ -42,9 +42,8 @@
 tmp3w		.req	w9
 tmp3		.req	x9
 
-	.weak memset
-ENTRY(__memset)
-ENTRY(memset)
+SYM_FUNC_START_ALIAS(__memset)
+SYM_FUNC_START_WEAK_PI(memset)
 	mov	dst, dstin	/* Preserve return value.  */
 	and	A_lw, val, #255
 	orr	A_lw, A_lw, A_lw, lsl #8
@@ -203,7 +202,7 @@
 	ands	count, count, zva_bits_x
 	b.ne	.Ltail_maybe_long
 	ret
-ENDPIPROC(memset)
+SYM_FUNC_END_PI(memset)
 EXPORT_SYMBOL(memset)
-ENDPROC(__memset)
+SYM_FUNC_END_ALIAS(__memset)
 EXPORT_SYMBOL(__memset)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/lib/strchr.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/lib/strchr.S
@@ -18,7 +18,7 @@
  * Returns:
  *	x0 - address of first occurrence of 'c' or 0
  */
-WEAK(strchr)
+SYM_FUNC_START_WEAK(strchr)
 	and	w1, w1, #0xff
 1:	ldrb	w2, [x0], #1
 	cmp	w2, w1
@@ -28,5 +28,5 @@
 	cmp	w2, w1
 	csel	x0, x0, xzr, eq
 	ret
-ENDPROC(strchr)
+SYM_FUNC_END(strchr)
 EXPORT_SYMBOL_NOKASAN(strchr)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/lib/strcmp.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/lib/strcmp.S
@@ -48,7 +48,7 @@
 zeroones	.req	x10
 pos		.req	x11
 
-WEAK(strcmp)
+SYM_FUNC_START_WEAK_PI(strcmp)
 	eor	tmp1, src1, src2
 	mov	zeroones, #REP8_01
 	tst	tmp1, #7
@@ -219,5 +219,5 @@
 	lsr	data1, data1, #56
 	sub	result, data1, data2, lsr #56
 	ret
-ENDPIPROC(strcmp)
+SYM_FUNC_END_PI(strcmp)
 EXPORT_SYMBOL_NOKASAN(strcmp)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/lib/strlen.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/lib/strlen.S
@@ -44,7 +44,7 @@
 #define REP8_7f 0x7f7f7f7f7f7f7f7f
 #define REP8_80 0x8080808080808080
 
-WEAK(strlen)
+SYM_FUNC_START_WEAK_PI(strlen)
 	mov	zeroones, #REP8_01
 	bic	src, srcin, #15
 	ands	tmp1, srcin, #15
@@ -111,5 +111,5 @@
 	csinv	data1, data1, xzr, le
 	csel	data2, data2, data2a, le
 	b	.Lrealigned
-ENDPIPROC(strlen)
+SYM_FUNC_END_PI(strlen)
 EXPORT_SYMBOL_NOKASAN(strlen)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/lib/strncmp.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/lib/strncmp.S
@@ -52,7 +52,7 @@
 mask		.req	x14
 endloop		.req	x15
 
-WEAK(strncmp)
+SYM_FUNC_START_WEAK_PI(strncmp)
 	cbz	limit, .Lret0
 	eor	tmp1, src1, src2
 	mov	zeroones, #REP8_01
@@ -295,5 +295,5 @@
 .Lret0:
 	mov	result, #0
 	ret
-ENDPIPROC(strncmp)
+SYM_FUNC_END_PI(strncmp)
 EXPORT_SYMBOL_NOKASAN(strncmp)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/lib/strnlen.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/lib/strnlen.S
@@ -47,7 +47,7 @@
 #define REP8_7f 0x7f7f7f7f7f7f7f7f
 #define REP8_80 0x8080808080808080
 
-WEAK(strnlen)
+SYM_FUNC_START_WEAK_PI(strnlen)
 	cbz	limit, .Lhit_limit
 	mov	zeroones, #REP8_01
 	bic	src, srcin, #15
@@ -156,5 +156,5 @@
 .Lhit_limit:
 	mov	len, limit
 	ret
-ENDPIPROC(strnlen)
+SYM_FUNC_END_PI(strnlen)
 EXPORT_SYMBOL_NOKASAN(strnlen)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/lib/strrchr.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/lib/strrchr.S
@@ -18,7 +18,7 @@
  * Returns:
  *	x0 - address of last occurrence of 'c' or 0
  */
-WEAK(strrchr)
+SYM_FUNC_START_WEAK_PI(strrchr)
 	mov	x3, #0
 	and	w1, w1, #0xff
 1:	ldrb	w2, [x0], #1
@@ -29,5 +29,5 @@
 	b	1b
 2:	mov	x0, x3
 	ret
-ENDPIPROC(strrchr)
+SYM_FUNC_END_PI(strrchr)
 EXPORT_SYMBOL_NOKASAN(strrchr)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/lib/tishift.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/lib/tishift.S
@@ -7,7 +7,7 @@
 
 #include <asm/assembler.h>
 
-ENTRY(__ashlti3)
+SYM_FUNC_START(__ashlti3)
 	cbz	x2, 1f
 	mov	x3, #64
 	sub	x3, x3, x2
@@ -26,10 +26,10 @@
 	lsl	x1, x0, x1
 	mov	x0, x2
 	ret
-ENDPROC(__ashlti3)
+SYM_FUNC_END(__ashlti3)
 EXPORT_SYMBOL(__ashlti3)
 
-ENTRY(__ashrti3)
+SYM_FUNC_START(__ashrti3)
 	cbz	x2, 1f
 	mov	x3, #64
 	sub	x3, x3, x2
@@ -48,10 +48,10 @@
 	asr	x0, x1, x0
 	mov	x1, x2
 	ret
-ENDPROC(__ashrti3)
+SYM_FUNC_END(__ashrti3)
 EXPORT_SYMBOL(__ashrti3)
 
-ENTRY(__lshrti3)
+SYM_FUNC_START(__lshrti3)
 	cbz	x2, 1f
 	mov	x3, #64
 	sub	x3, x3, x2
@@ -70,5 +70,5 @@
 	lsr	x0, x1, x0
 	mov	x1, x2
 	ret
-ENDPROC(__lshrti3)
+SYM_FUNC_END(__lshrti3)
 EXPORT_SYMBOL(__lshrti3)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/mm/cache.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/mm/cache.S
@@ -228,8 +228,6 @@
  *	- dir	- DMA direction
  */
 ENTRY(__dma_map_area)
-	cmp	w2, #DMA_FROM_DEVICE
-	b.eq	__dma_inv_area
 	b	__dma_clean_area
 ENDPIPROC(__dma_map_area)
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/mm/dma-mapping.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/mm/dma-mapping.c
@@ -13,14 +13,14 @@
 
 #include <asm/cacheflush.h>
 
-void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr,
-		size_t size, enum dma_data_direction dir)
+void arch_sync_dma_for_device(phys_addr_t paddr, size_t size,
+		enum dma_data_direction dir)
 {
 	__dma_map_area(phys_to_virt(paddr), size, dir);
 }
 
-void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr,
-		size_t size, enum dma_data_direction dir)
+void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size,
+		enum dma_data_direction dir)
 {
 	__dma_unmap_area(phys_to_virt(paddr), size, dir);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/mm/fault.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/mm/fault.c
@@ -296,7 +296,7 @@
 	show_pte(addr);
 	die("Oops", regs, esr);
 	bust_spinlocks(0);
-	do_exit(SIGKILL);
+	make_task_dead(SIGKILL);
 }
 
 static void __do_kernel_fault(unsigned long addr, unsigned int esr,
@@ -403,8 +403,8 @@
 	}
 }
 
-#define VM_FAULT_BADMAP		0x010000
-#define VM_FAULT_BADACCESS	0x020000
+#define VM_FAULT_BADMAP		((__force vm_fault_t)0x010000)
+#define VM_FAULT_BADACCESS	((__force vm_fault_t)0x020000)
 
 static vm_fault_t __do_page_fault(struct mm_struct *mm, unsigned long addr,
 			   unsigned int mm_flags, unsigned long vm_flags)
@@ -454,7 +454,7 @@
 	const struct fault_info *inf;
 	struct mm_struct *mm = current->mm;
 	vm_fault_t fault, major = 0;
-	unsigned long vm_flags = VM_READ | VM_WRITE;
+	unsigned long vm_flags = VM_READ | VM_WRITE | VM_EXEC;
 	unsigned int mm_flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
 
 	if (kprobe_page_fault(regs, esr))
@@ -654,11 +654,13 @@
 
 	inf = esr_to_fault_info(esr);
 
-	/*
-	 * Return value ignored as we rely on signal merging.
-	 * Future patches will make this more robust.
-	 */
-	apei_claim_sea(regs);
+	if (user_mode(regs) && apei_claim_sea(regs) == 0) {
+		/*
+		 * APEI claimed this as a firmware-first notification.
+		 * Some processing deferred to task_work before ret_to_user().
+		 */
+		return 0;
+	}
 
 	if (esr & ESR_ELx_FnV)
 		siaddr = NULL;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/mm/hugetlbpage.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/mm/hugetlbpage.c
@@ -230,6 +230,8 @@
 		ptep = (pte_t *)pudp;
 	} else if (sz == (CONT_PTE_SIZE)) {
 		pmdp = pmd_alloc(mm, pudp, addr);
+		if (!pmdp)
+			return NULL;
 
 		WARN_ON(addr & (sz - 1));
 		/*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/mm/init.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/mm/init.c
@@ -50,12 +50,6 @@
 s64 memstart_addr __ro_after_init = -1;
 EXPORT_SYMBOL(memstart_addr);
 
-s64 physvirt_offset __ro_after_init;
-EXPORT_SYMBOL(physvirt_offset);
-
-struct page *vmemmap __ro_after_init;
-EXPORT_SYMBOL(vmemmap);
-
 phys_addr_t arm64_dma_phys_limit __ro_after_init;
 
 #ifdef CONFIG_KEXEC_CORE
@@ -251,6 +245,18 @@
 
 	if (!valid_section(__nr_to_section(pfn_to_section_nr(pfn))))
 		return 0;
+
+	/*
+	 * ZONE_DEVICE memory does not have the memblock entries.
+	 * memblock_is_map_memory() check for ZONE_DEVICE based
+	 * addresses will always fail. Even the normal hotplugged
+	 * memory will never have MEMBLOCK_NOMAP flag set in their
+	 * memblock entries. Skip memblock search for all non early
+	 * memory sections covering all of hotplug memory including
+	 * both normal and ZONE_DEVICE based.
+	 */
+	if (!early_section(__pfn_to_section(pfn)))
+		return pfn_section_valid(__pfn_to_section(pfn), pfn);
 #endif
 	return memblock_is_map_memory(addr);
 }
@@ -321,20 +327,6 @@
 	memstart_addr = round_down(memblock_start_of_DRAM(),
 				   ARM64_MEMSTART_ALIGN);
 
-	physvirt_offset = PHYS_OFFSET - PAGE_OFFSET;
-
-	vmemmap = ((struct page *)VMEMMAP_START - (memstart_addr >> PAGE_SHIFT));
-
-	/*
-	 * If we are running with a 52-bit kernel VA config on a system that
-	 * does not support it, we have to offset our vmemmap and physvirt_offset
-	 * s.t. we avoid the 52-bit portion of the direct linear map
-	 */
-	if (IS_ENABLED(CONFIG_ARM64_VA_BITS_52) && (vabits_actual != 52)) {
-		vmemmap += (_PAGE_OFFSET(48) - _PAGE_OFFSET(52)) >> PAGE_SHIFT;
-		physvirt_offset = PHYS_OFFSET - _PAGE_OFFSET(48);
-	}
-
 	/*
 	 * Remove the memory that we will not be able to cover with the
 	 * linear mapping. Take care not to clip the kernel which may be
@@ -350,6 +342,16 @@
 	}
 
 	/*
+	 * If we are running with a 52-bit kernel VA config on a system that
+	 * does not support it, we have to place the available physical
+	 * memory in the 48-bit addressable part of the linear region, i.e.,
+	 * we have to move it upward. Since memstart_addr represents the
+	 * physical address of PAGE_OFFSET, we have to *subtract* from it.
+	 */
+	if (IS_ENABLED(CONFIG_ARM64_VA_BITS_52) && (vabits_actual != 52))
+		memstart_addr -= _PAGE_OFFSET(48) - _PAGE_OFFSET(52);
+
+	/*
 	 * Apply the memory limit if it was set. Since the kernel may be loaded
 	 * high up in memory, add back the kernel region that must be accessible
 	 * via the linear mapping.
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/mm/ioremap.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/mm/ioremap.c
@@ -13,6 +13,7 @@
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
 #include <linux/io.h>
+#include <linux/memblock.h>
 
 #include <asm/fixmap.h>
 #include <asm/tlbflush.h>
@@ -100,3 +101,11 @@
 {
 	early_ioremap_setup();
 }
+
+bool arch_memremap_can_ram_remap(resource_size_t offset, size_t size,
+				 unsigned long flags)
+{
+	unsigned long pfn = PHYS_PFN(offset);
+
+	return memblock_is_map_memory(pfn);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/mm/mmu.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/mm/mmu.c
@@ -38,7 +38,7 @@
 #define NO_BLOCK_MAPPINGS	BIT(0)
 #define NO_CONT_MAPPINGS	BIT(1)
 
-u64 idmap_t0sz = TCR_T0SZ(VA_BITS);
+u64 idmap_t0sz = TCR_T0SZ(VA_BITS_MIN);
 u64 idmap_ptrs_per_pgd = PTRS_PER_PGD;
 
 u64 __section(".mmuoff.data.write") vabits_actual;
@@ -399,7 +399,7 @@
 static void __init create_mapping_noalloc(phys_addr_t phys, unsigned long virt,
 				  phys_addr_t size, pgprot_t prot)
 {
-	if ((virt >= PAGE_END) && (virt < VMALLOC_START)) {
+	if (virt < PAGE_OFFSET) {
 		pr_warn("BUG: not creating mapping for %pa at 0x%016lx - outside kernel range\n",
 			&phys, virt);
 		return;
@@ -426,7 +426,7 @@
 static void update_mapping_prot(phys_addr_t phys, unsigned long virt,
 				phys_addr_t size, pgprot_t prot)
 {
-	if ((virt >= PAGE_END) && (virt < VMALLOC_START)) {
+	if (virt < PAGE_OFFSET) {
 		pr_warn("BUG: not updating mapping for %pa at 0x%016lx - outside kernel range\n",
 			&phys, virt);
 		return;
@@ -583,6 +583,8 @@
 #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
 static int __init map_entry_trampoline(void)
 {
+	int i;
+
 	pgprot_t prot = rodata_enabled ? PAGE_KERNEL_ROX : PAGE_KERNEL_EXEC;
 	phys_addr_t pa_start = __pa_symbol(__entry_tramp_text_start);
 
@@ -591,11 +593,15 @@
 
 	/* Map only the text into the trampoline page table */
 	memset(tramp_pg_dir, 0, PGD_SIZE);
-	__create_pgd_mapping(tramp_pg_dir, pa_start, TRAMP_VALIAS, PAGE_SIZE,
-			     prot, __pgd_pgtable_alloc, 0);
+	__create_pgd_mapping(tramp_pg_dir, pa_start, TRAMP_VALIAS,
+			     entry_tramp_text_size(), prot,
+			     __pgd_pgtable_alloc, NO_BLOCK_MAPPINGS);
 
 	/* Map both the text and data into the kernel page table */
-	__set_fixmap(FIX_ENTRY_TRAMP_TEXT, pa_start, prot);
+	for (i = 0; i < DIV_ROUND_UP(entry_tramp_text_size(), PAGE_SIZE); i++)
+		__set_fixmap(FIX_ENTRY_TRAMP_TEXT1 - i,
+			     pa_start + i * PAGE_SIZE, prot);
+
 	if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
 		extern char __entry_tramp_data_start[];
 
@@ -1069,7 +1075,6 @@
 {
 	unsigned long start_pfn = start >> PAGE_SHIFT;
 	unsigned long nr_pages = size >> PAGE_SHIFT;
-	struct zone *zone;
 
 	/*
 	 * FIXME: Cleanup page tables (also in arch_add_memory() in case
@@ -1078,7 +1083,6 @@
 	 * unplug. ARCH_ENABLE_MEMORY_HOTREMOVE must not be
 	 * unlocked yet.
 	 */
-	zone = page_zone(pfn_to_page(start_pfn));
-	__remove_pages(zone, start_pfn, nr_pages, altmap);
+	__remove_pages(start_pfn, nr_pages, altmap);
 }
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/mm/numa.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/mm/numa.c
@@ -46,7 +46,11 @@
  */
 const struct cpumask *cpumask_of_node(int node)
 {
-	if (WARN_ON(node >= nr_node_ids))
+
+	if (node == NUMA_NO_NODE)
+		return cpu_all_mask;
+
+	if (WARN_ON(node < 0 || node >= nr_node_ids))
 		return cpu_none_mask;
 
 	if (WARN_ON(node_to_cpumask_map[node] == NULL))
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/mm/physaddr.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/mm/physaddr.c
@@ -9,7 +9,7 @@
 
 phys_addr_t __virt_to_phys(unsigned long x)
 {
-	WARN(!__is_lm_address(x),
+	WARN(!__is_lm_address(__tag_reset(x)),
 	     "virt_to_phys used for non-linear address: %pK (%pS)\n",
 	      (void *)x,
 	      (void *)x);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/mm/proc.S
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/mm/proc.S
@@ -166,7 +166,7 @@
 	.pushsection ".idmap.text", "awx"
 
 .macro	__idmap_cpu_set_reserved_ttbr1, tmp1, tmp2
-	adrp	\tmp1, empty_zero_page
+	adrp	\tmp1, reserved_pg_dir
 	phys_to_ttbr \tmp2, \tmp1
 	offset_ttbr1 \tmp2, \tmp1
 	msr	ttbr1_el1, \tmp2
--- linux-xilinx-zynqmp-5.4.0.orig/arch/arm64/net/bpf_jit_comp.c
+++ linux-xilinx-zynqmp-5.4.0/arch/arm64/net/bpf_jit_comp.c
@@ -141,14 +141,17 @@
 	}
 }
 
-static inline int bpf2a64_offset(int bpf_to, int bpf_from,
+static inline int bpf2a64_offset(int bpf_insn, int off,
 				 const struct jit_ctx *ctx)
 {
-	int to = ctx->offset[bpf_to];
-	/* -1 to account for the Branch instruction */
-	int from = ctx->offset[bpf_from] - 1;
-
-	return to - from;
+	/* BPF JMP offset is relative to the next instruction */
+	bpf_insn++;
+	/*
+	 * Whereas arm64 branch instructions encode the offset
+	 * from the branch itself, so we must subtract 1 from the
+	 * instruction offset.
+	 */
+	return ctx->offset[bpf_insn + off] - (ctx->offset[bpf_insn] - 1);
 }
 
 static void jit_fill_hole(void *area, unsigned int size)
@@ -532,7 +535,7 @@
 
 	/* JUMP off */
 	case BPF_JMP | BPF_JA:
-		jmp_offset = bpf2a64_offset(i + off, i, ctx);
+		jmp_offset = bpf2a64_offset(i, off, ctx);
 		check_imm26(jmp_offset);
 		emit(A64_B(jmp_offset), ctx);
 		break;
@@ -559,7 +562,7 @@
 	case BPF_JMP32 | BPF_JSLE | BPF_X:
 		emit(A64_CMP(is64, dst, src), ctx);
 emit_cond_jmp:
-		jmp_offset = bpf2a64_offset(i + off, i, ctx);
+		jmp_offset = bpf2a64_offset(i, off, ctx);
 		check_imm19(jmp_offset);
 		switch (BPF_OP(code)) {
 		case BPF_JEQ:
@@ -698,6 +701,19 @@
 		}
 		break;
 
+	/* speculation barrier */
+	case BPF_ST | BPF_NOSPEC:
+		/*
+		 * Nothing required here.
+		 *
+		 * In case of arm64, we rely on the firmware mitigation of
+		 * Speculative Store Bypass as controlled via the ssbd kernel
+		 * parameter. Whenever the mitigation is enabled, it works
+		 * for all of the kernel code with no need to provide any
+		 * additional instructions.
+		 */
+		break;
+
 	/* ST: *(size *)(dst + off) = imm */
 	case BPF_ST | BPF_MEM | BPF_W:
 	case BPF_ST | BPF_MEM | BPF_H:
@@ -780,10 +796,21 @@
 	const struct bpf_prog *prog = ctx->prog;
 	int i;
 
+	/*
+	 * - offset[0] offset of the end of prologue,
+	 *   start of the 1st instruction.
+	 * - offset[1] - offset of the end of 1st instruction,
+	 *   start of the 2nd instruction
+	 * [....]
+	 * - offset[3] - offset of the end of 3rd instruction,
+	 *   start of 4th instruction
+	 */
 	for (i = 0; i < prog->len; i++) {
 		const struct bpf_insn *insn = &prog->insnsi[i];
 		int ret;
 
+		if (ctx->image == NULL)
+			ctx->offset[i] = ctx->idx;
 		ret = build_insn(insn, ctx, extra_pass);
 		if (ret > 0) {
 			i++;
@@ -791,11 +818,16 @@
 				ctx->offset[i] = ctx->idx;
 			continue;
 		}
-		if (ctx->image == NULL)
-			ctx->offset[i] = ctx->idx;
 		if (ret)
 			return ret;
 	}
+	/*
+	 * offset is allocated with prog->len + 1 so fill in
+	 * the last element with the offset after the last
+	 * instruction (end of program)
+	 */
+	if (ctx->image == NULL)
+		ctx->offset[i] = ctx->idx;
 
 	return 0;
 }
@@ -871,21 +903,24 @@
 	memset(&ctx, 0, sizeof(ctx));
 	ctx.prog = prog;
 
-	ctx.offset = kcalloc(prog->len, sizeof(int), GFP_KERNEL);
+	ctx.offset = kcalloc(prog->len + 1, sizeof(int), GFP_KERNEL);
 	if (ctx.offset == NULL) {
 		prog = orig_prog;
 		goto out_off;
 	}
 
-	/* 1. Initial fake pass to compute ctx->idx. */
-
-	/* Fake pass to fill in ctx->offset. */
-	if (build_body(&ctx, extra_pass)) {
+	/*
+	 * 1. Initial fake pass to compute ctx->idx and ctx->offset.
+	 *
+	 * BPF line info needs ctx->offset[i] to be the offset of
+	 * instruction[i] in jited image, so build prologue first.
+	 */
+	if (build_prologue(&ctx, was_classic)) {
 		prog = orig_prog;
 		goto out_off;
 	}
 
-	if (build_prologue(&ctx, was_classic)) {
+	if (build_body(&ctx, extra_pass)) {
 		prog = orig_prog;
 		goto out_off;
 	}
@@ -938,6 +973,7 @@
 			bpf_jit_binary_free(header);
 			prog->bpf_func = NULL;
 			prog->jited = 0;
+			prog->jited_len = 0;
 			goto out_off;
 		}
 		bpf_jit_binary_lock_ro(header);
@@ -951,7 +987,12 @@
 	prog->jited_len = image_size;
 
 	if (!prog->is_func || extra_pass) {
-		bpf_prog_fill_jited_linfo(prog, ctx.offset);
+		int i;
+
+		/* offset[prog->len] is the size of program */
+		for (i = 0; i <= prog->len; i++)
+			ctx.offset[i] *= AARCH64_INSN_SIZE;
+		bpf_prog_fill_jited_linfo(prog, ctx.offset + 1);
 out_off:
 		kfree(ctx.offset);
 		kfree(jit_data);
@@ -964,6 +1005,11 @@
 	return prog;
 }
 
+u64 bpf_jit_alloc_exec_limit(void)
+{
+	return BPF_JIT_REGION_SIZE;
+}
+
 void *bpf_jit_alloc_exec(unsigned long size)
 {
 	return __vmalloc_node_range(size, PAGE_SIZE, BPF_JIT_REGION_START,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/c6x/mm/dma-coherent.c
+++ linux-xilinx-zynqmp-5.4.0/arch/c6x/mm/dma-coherent.c
@@ -140,7 +140,7 @@
 		      sizeof(long));
 }
 
-static void c6x_dma_sync(struct device *dev, phys_addr_t paddr, size_t size,
+static void c6x_dma_sync(phys_addr_t paddr, size_t size,
 		enum dma_data_direction dir)
 {
 	BUG_ON(!valid_dma_direction(dir));
@@ -160,14 +160,14 @@
 	}
 }
 
-void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr,
-		size_t size, enum dma_data_direction dir)
+void arch_sync_dma_for_device(phys_addr_t paddr, size_t size,
+		enum dma_data_direction dir)
 {
-	return c6x_dma_sync(dev, paddr, size, dir);
+	return c6x_dma_sync(paddr, size, dir);
 }
 
-void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr,
-		size_t size, enum dma_data_direction dir)
+void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size,
+		enum dma_data_direction dir)
 {
-	return c6x_dma_sync(dev, paddr, size, dir);
+	return c6x_dma_sync(paddr, size, dir);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/csky/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/csky/Kconfig
@@ -36,6 +36,7 @@
 	select GX6605S_TIMER if CPU_CK610
 	select HAVE_ARCH_TRACEHOOK
 	select HAVE_ARCH_AUDITSYSCALL
+	select HAVE_COPY_THREAD_TLS
 	select HAVE_DYNAMIC_FTRACE
 	select HAVE_FUNCTION_TRACER
 	select HAVE_FUNCTION_GRAPH_TRACER
@@ -74,7 +75,7 @@
 config CPU_HAS_LDSTEX
 	bool
 	help
-	  For SMP, CPU needs "ldex&stex" instrcutions to atomic operations.
+	  For SMP, CPU needs "ldex&stex" instructions for atomic operations.
 
 config CPU_NEED_TLBSYNC
 	bool
@@ -219,7 +220,7 @@
 	int "Maximum zone order"
 	default "11"
 
-config RAM_BASE
+config DRAM_BASE
 	hex "DRAM start addr (the same with memory-section in dts)"
 	default 0x0
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/csky/abiv1/alignment.c
+++ linux-xilinx-zynqmp-5.4.0/arch/csky/abiv1/alignment.c
@@ -294,7 +294,7 @@
 				__func__, opcode, rz, rx, imm, addr);
 		show_regs(regs);
 		bust_spinlocks(0);
-		do_exit(SIGKILL);
+		make_task_dead(SIGKILL);
 	}
 
 	force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *)addr);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/csky/abiv1/inc/abi/entry.h
+++ linux-xilinx-zynqmp-5.4.0/arch/csky/abiv1/inc/abi/entry.h
@@ -16,14 +16,16 @@
 #define LSAVE_A4	40
 #define LSAVE_A5	44
 
+#define usp ss1
+
 .macro USPTOKSP
-	mtcr	sp, ss1
+	mtcr	sp, usp
 	mfcr	sp, ss0
 .endm
 
 .macro KSPTOUSP
 	mtcr	sp, ss0
-	mfcr	sp, ss1
+	mfcr	sp, usp
 .endm
 
 .macro	SAVE_ALL epc_inc
@@ -45,7 +47,13 @@
 	add	lr, r13
 	stw     lr, (sp, 8)
 
+	mov	lr, sp
+	addi	lr, 32
+	addi	lr, 32
+	addi	lr, 16
+	bt	2f
 	mfcr	lr, ss1
+2:
 	stw     lr, (sp, 16)
 
 	stw     a0, (sp, 20)
@@ -79,9 +87,10 @@
 	ldw     a0, (sp, 12)
 	mtcr    a0, epsr
 	btsti   a0, 31
+	bt      1f
 	ldw     a0, (sp, 16)
 	mtcr	a0, ss1
-
+1:
 	ldw     a0, (sp, 24)
 	ldw     a1, (sp, 28)
 	ldw     a2, (sp, 32)
@@ -102,9 +111,9 @@
 	addi	sp, 32
 	addi	sp, 8
 
-	bt      1f
+	bt      2f
 	KSPTOUSP
-1:
+2:
 	rte
 .endm
 
@@ -158,15 +167,12 @@
 	 *   BA     Reserved  C   D   V
 	 */
 	cprcr	r6, cpcr30
-	lsri	r6, 28
-	lsli	r6, 28
+	lsri	r6, 29
+	lsli	r6, 29
 	addi	r6, 0xe
 	cpwcr	r6, cpcr30
 
-	lsri	r6, 28
-	addi	r6, 2
-	lsli	r6, 28
-	addi	r6, 0xe
+	movi	r6, 0
 	cpwcr	r6, cpcr31
 .endm
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/csky/abiv2/fpu.c
+++ linux-xilinx-zynqmp-5.4.0/arch/csky/abiv2/fpu.c
@@ -10,11 +10,6 @@
 #define MTCR_DIST	0xC0006420
 #define MFCR_DIST	0xC0006020
 
-void __init init_fpu(void)
-{
-	mtcr("cr<1, 2>", 0);
-}
-
 /*
  * fpu_libc_helper() is to help libc to excute:
  *  - mfcr %a, cr<1, 2>
--- linux-xilinx-zynqmp-5.4.0.orig/arch/csky/abiv2/inc/abi/entry.h
+++ linux-xilinx-zynqmp-5.4.0/arch/csky/abiv2/inc/abi/entry.h
@@ -13,6 +13,8 @@
 #define LSAVE_A1	28
 #define LSAVE_A2	32
 #define LSAVE_A3	36
+#define LSAVE_A4	40
+#define LSAVE_A5	44
 
 #define KSPTOUSP
 #define USPTOKSP
@@ -31,7 +33,13 @@
 
 	mfcr	lr, epsr
 	stw	lr, (sp, 12)
+	btsti   lr, 31
+	bf      1f
+	addi    lr, sp, 152
+	br	2f
+1:
 	mfcr	lr, usp
+2:
 	stw	lr, (sp, 16)
 
 	stw     a0, (sp, 20)
@@ -64,8 +72,10 @@
 	mtcr	a0, epc
 	ldw	a0, (sp, 12)
 	mtcr	a0, epsr
+	btsti   a0, 31
 	ldw	a0, (sp, 16)
 	mtcr	a0, usp
+	mtcr	a0, ss0
 
 #ifdef CONFIG_CPU_HAS_HILO
 	ldw	a0, (sp, 140)
@@ -86,6 +96,9 @@
 	addi    sp, 40
 	ldm     r16-r30, (sp)
 	addi    sp, 72
+	bf	1f
+	mfcr	sp, ss0
+1:
 	rte
 .endm
 
@@ -214,16 +227,13 @@
 	 */
 	mfcr	r6, cr<30, 15> /* Get MSA0 */
 2:
-	lsri	r6, 28
-	lsli	r6, 28
+	lsri	r6, 29
+	lsli	r6, 29
 	addi	r6, 0x1ce
 	mtcr	r6, cr<30, 15> /* Set MSA0 */
 
-	lsri	r6, 28
-	addi	r6, 2
-	lsli	r6, 28
-	addi	r6, 0x1ce
-	mtcr	r6, cr<31, 15> /* Set MSA1 */
+	movi    r6, 0
+	mtcr	r6, cr<31, 15> /* Clr MSA1 */
 
 	/* enable MMU */
 	mfcr    r6, cr18
--- linux-xilinx-zynqmp-5.4.0.orig/arch/csky/abiv2/inc/abi/fpu.h
+++ linux-xilinx-zynqmp-5.4.0/arch/csky/abiv2/inc/abi/fpu.h
@@ -9,7 +9,8 @@
 
 int fpu_libc_helper(struct pt_regs *regs);
 void fpu_fpe(struct pt_regs *regs);
-void __init init_fpu(void);
+
+static inline void init_fpu(void) { mtcr("cr<1, 2>", 0); }
 
 void save_to_user_fp(struct user_fp *user_fp);
 void restore_from_user_fp(struct user_fp *user_fp);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/csky/include/asm/Kbuild
+++ linux-xilinx-zynqmp-5.4.0/arch/csky/include/asm/Kbuild
@@ -7,7 +7,6 @@
 generic-y += device.h
 generic-y += div64.h
 generic-y += dma.h
-generic-y += dma-contiguous.h
 generic-y += dma-mapping.h
 generic-y += emergency-restart.h
 generic-y += exec.h
--- linux-xilinx-zynqmp-5.4.0.orig/arch/csky/include/asm/page.h
+++ linux-xilinx-zynqmp-5.4.0/arch/csky/include/asm/page.h
@@ -28,7 +28,7 @@
 #define SSEG_SIZE	0x20000000
 #define LOWMEM_LIMIT	(SSEG_SIZE * 2)
 
-#define PHYS_OFFSET_OFFSET (CONFIG_RAM_BASE & (SSEG_SIZE - 1))
+#define PHYS_OFFSET_OFFSET (CONFIG_DRAM_BASE & (SSEG_SIZE - 1))
 
 #ifndef __ASSEMBLY__
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/csky/include/asm/processor.h
+++ linux-xilinx-zynqmp-5.4.0/arch/csky/include/asm/processor.h
@@ -43,6 +43,7 @@
 struct thread_struct {
 	unsigned long  ksp;       /* kernel stack pointer */
 	unsigned long  sr;        /* saved status register */
+	unsigned long  trap_no;   /* saved status register */
 
 	/* FPU regs */
 	struct user_fp __aligned(16) user_fp;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/csky/include/asm/uaccess.h
+++ linux-xilinx-zynqmp-5.4.0/arch/csky/include/asm/uaccess.h
@@ -254,7 +254,7 @@
 
 extern int __get_user_bad(void);
 
-#define __copy_user(to, from, n)			\
+#define ___copy_to_user(to, from, n)			\
 do {							\
 	int w0, w1, w2, w3;				\
 	asm volatile(					\
@@ -289,31 +289,34 @@
 	"       subi    %0, 4           \n"		\
 	"       br      3b              \n"		\
 	"5:     cmpnei  %0, 0           \n"  /* 1B */   \
-	"       bf      8f              \n"		\
+	"       bf      13f             \n"		\
 	"       ldb     %3, (%2, 0)     \n"		\
 	"6:     stb     %3, (%1, 0)     \n"		\
 	"       addi    %2,  1          \n"		\
 	"       addi    %1,  1          \n"		\
 	"       subi    %0,  1          \n"		\
 	"       br      5b              \n"		\
-	"7:     br      8f              \n"		\
+	"7:     subi	%0,  4          \n"		\
+	"8:     subi	%0,  4          \n"		\
+	"12:    subi	%0,  4          \n"		\
+	"       br      13f             \n"		\
 	".section __ex_table, \"a\"     \n"		\
 	".align   2                     \n"		\
-	".long    2b, 7b                \n"		\
-	".long    9b, 7b                \n"		\
-	".long   10b, 7b                \n"		\
+	".long    2b, 13f               \n"		\
+	".long    4b, 13f               \n"		\
+	".long    6b, 13f               \n"		\
+	".long    9b, 12b               \n"		\
+	".long   10b, 8b                \n"		\
 	".long   11b, 7b                \n"		\
-	".long    4b, 7b                \n"		\
-	".long    6b, 7b                \n"		\
 	".previous                      \n"		\
-	"8:                             \n"		\
+	"13:                            \n"		\
 	: "=r"(n), "=r"(to), "=r"(from), "=r"(w0),	\
 	  "=r"(w1), "=r"(w2), "=r"(w3)			\
 	: "0"(n), "1"(to), "2"(from)			\
 	: "memory");					\
 } while (0)
 
-#define __copy_user_zeroing(to, from, n)		\
+#define ___copy_from_user(to, from, n)			\
 do {							\
 	int tmp;					\
 	int nsave;					\
@@ -356,22 +359,22 @@
 	"       addi    %1,  1          \n"		\
 	"       subi    %0,  1          \n"		\
 	"       br      5b              \n"		\
-	"8:     mov     %3, %0          \n"		\
-	"       movi    %4, 0           \n"		\
-	"9:     stb     %4, (%1, 0)     \n"		\
-	"       addi    %1, 1           \n"		\
-	"       subi    %3, 1           \n"		\
-	"       cmpnei  %3, 0           \n"		\
-	"       bt      9b              \n"		\
-	"       br      7f              \n"		\
+	"8:     stw     %3, (%1, 0)     \n"		\
+	"       subi    %0, 4           \n"		\
+	"       bf      7f              \n"		\
+	"9:     subi    %0, 8           \n"		\
+	"       bf      7f              \n"		\
+	"13:    stw     %3, (%1, 8)     \n"		\
+	"       subi    %0, 12          \n"		\
+	"       bf      7f              \n"		\
 	".section __ex_table, \"a\"     \n"		\
 	".align   2                     \n"		\
-	".long    2b, 8b                \n"		\
+	".long    2b, 7f                \n"		\
+	".long    4b, 7f                \n"		\
+	".long    6b, 7f                \n"		\
 	".long   10b, 8b                \n"		\
-	".long   11b, 8b                \n"		\
-	".long   12b, 8b                \n"		\
-	".long    4b, 8b                \n"		\
-	".long    6b, 8b                \n"		\
+	".long   11b, 9b                \n"		\
+	".long   12b,13b                \n"		\
 	".previous                      \n"		\
 	"7:                             \n"		\
 	: "=r"(n), "=r"(to), "=r"(from), "=r"(nsave),	\
--- linux-xilinx-zynqmp-5.4.0.orig/arch/csky/include/uapi/asm/unistd.h
+++ linux-xilinx-zynqmp-5.4.0/arch/csky/include/uapi/asm/unistd.h
@@ -1,9 +1,13 @@
 /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
 // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
 
+#define __ARCH_WANT_STAT64
+#define __ARCH_WANT_NEW_STAT
 #define __ARCH_WANT_SYS_CLONE
+#define __ARCH_WANT_SYS_CLONE3
 #define __ARCH_WANT_SET_GET_RLIMIT
 #define __ARCH_WANT_TIME32_SYSCALLS
+#define __ARCH_WANT_SYNC_FILE_RANGE2
 #include <asm-generic/unistd.h>
 
 #define __NR_set_thread_area	(__NR_arch_specific_syscall + 0)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/csky/kernel/atomic.S
+++ linux-xilinx-zynqmp-5.4.0/arch/csky/kernel/atomic.S
@@ -17,10 +17,12 @@
 	mfcr	a3, epc
 	addi	a3, TRAP0_SIZE
 
-	subi    sp, 8
+	subi    sp, 16
 	stw     a3, (sp, 0)
 	mfcr    a3, epsr
 	stw     a3, (sp, 4)
+	mfcr	a3, usp
+	stw     a3, (sp, 8)
 
 	psrset	ee
 #ifdef CONFIG_CPU_HAS_LDSTEX
@@ -47,7 +49,9 @@
 	mtcr	a3, epc
 	ldw     a3, (sp, 4)
 	mtcr	a3, epsr
-	addi	sp, 8
+	ldw     a3, (sp, 8)
+	mtcr	a3, usp
+	addi	sp, 16
 	KSPTOUSP
 	rte
 END(csky_cmpxchg)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/csky/kernel/entry.S
+++ linux-xilinx-zynqmp-5.4.0/arch/csky/kernel/entry.S
@@ -170,8 +170,10 @@
 	ldw	a3, (sp, LSAVE_A3)
 #if defined(__CSKYABIV2__)
 	subi	sp, 8
-	stw	r5, (sp, 0x4)
-	stw	r4, (sp, 0x0)
+	ldw	r9, (sp, LSAVE_A4)
+	stw	r9, (sp, 0x0)
+	ldw	r9, (sp, LSAVE_A5)
+	stw	r9, (sp, 0x4)
 #else
 	ldw	r6, (sp, LSAVE_A4)
 	ldw	r7, (sp, LSAVE_A5)
@@ -318,8 +320,6 @@
 
 	mfcr	a2, psr			/* Save PSR value */
 	stw	a2, (a3, THREAD_SR)	/* Save PSR in task struct */
-	bclri	a2, 6			/* Disable interrupts */
-	mtcr	a2, psr
 
 	SAVE_SWITCH_STACK
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/csky/kernel/head.S
+++ linux-xilinx-zynqmp-5.4.0/arch/csky/kernel/head.S
@@ -21,6 +21,11 @@
 ENTRY(_start_smp_secondary)
 	SETUP_MMU
 
+	/* copy msa1 from CPU0 */
+	lrw     r6, secondary_msa1
+	ld.w	r6, (r6, 0)
+	mtcr	r6, cr<31, 15>
+
 	/* set stack point */
 	lrw     r6, secondary_stack
 	ld.w	r6, (r6, 0)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/csky/kernel/perf_callchain.c
+++ linux-xilinx-zynqmp-5.4.0/arch/csky/kernel/perf_callchain.c
@@ -12,12 +12,17 @@
 
 static int unwind_frame_kernel(struct stackframe *frame)
 {
-	if (kstack_end((void *)frame->fp))
+	unsigned long low = (unsigned long)task_stack_page(current);
+	unsigned long high = low + THREAD_SIZE;
+
+	if (unlikely(frame->fp < low || frame->fp > high))
 		return -EPERM;
-	if (frame->fp & 0x3 || frame->fp < TASK_SIZE)
+
+	if (kstack_end((void *)frame->fp) || frame->fp & 0x3)
 		return -EPERM;
 
 	*frame = *(struct stackframe *)frame->fp;
+
 	if (__kernel_text_address(frame->lr)) {
 		int graph = 0;
 
@@ -81,10 +86,11 @@
 void perf_callchain_user(struct perf_callchain_entry_ctx *entry,
 			 struct pt_regs *regs)
 {
+	struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs();
 	unsigned long fp = 0;
 
 	/* C-SKY does not support virtualization. */
-	if (perf_guest_cbs && perf_guest_cbs->is_in_guest())
+	if (guest_cbs && guest_cbs->is_in_guest())
 		return;
 
 	fp = regs->regs[4];
@@ -105,10 +111,11 @@
 void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
 			   struct pt_regs *regs)
 {
+	struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs();
 	struct stackframe fr;
 
 	/* C-SKY does not support virtualization. */
-	if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
+	if (guest_cbs && guest_cbs->is_in_guest()) {
 		pr_warn("C-SKY does not support perf in guest mode!");
 		return;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/csky/kernel/process.c
+++ linux-xilinx-zynqmp-5.4.0/arch/csky/kernel/process.c
@@ -34,10 +34,11 @@
 	return sw->r15;
 }
 
-int copy_thread(unsigned long clone_flags,
+int copy_thread_tls(unsigned long clone_flags,
 		unsigned long usp,
 		unsigned long kthread_arg,
-		struct task_struct *p)
+		struct task_struct *p,
+		unsigned long tls)
 {
 	struct switch_stack *childstack;
 	struct pt_regs *childregs = task_pt_regs(p);
@@ -64,7 +65,7 @@
 			childregs->usp = usp;
 		if (clone_flags & CLONE_SETTLS)
 			task_thread_info(p)->tp_value = childregs->tls
-						      = childregs->regs[0];
+						      = tls;
 
 		childregs->a0 = 0;
 		childstack->r15 = (unsigned long) ret_from_fork;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/csky/kernel/ptrace.c
+++ linux-xilinx-zynqmp-5.4.0/arch/csky/kernel/ptrace.c
@@ -96,7 +96,8 @@
 	if (ret)
 		return ret;
 
-	regs.sr = task_pt_regs(target)->sr;
+	/* BIT(0) of regs.sr is Condition Code/Carry bit */
+	regs.sr = (regs.sr & BIT(0)) | (task_pt_regs(target)->sr & ~BIT(0));
 #ifdef CONFIG_CPU_HAS_HILO
 	regs.dcsr = task_pt_regs(target)->dcsr;
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/csky/kernel/setup.c
+++ linux-xilinx-zynqmp-5.4.0/arch/csky/kernel/setup.c
@@ -24,26 +24,9 @@
 };
 #endif
 
-phys_addr_t __init_memblock memblock_end_of_REG0(void)
-{
-	return (memblock.memory.regions[0].base +
-		memblock.memory.regions[0].size);
-}
-
-phys_addr_t __init_memblock memblock_start_of_REG1(void)
-{
-	return memblock.memory.regions[1].base;
-}
-
-size_t __init_memblock memblock_size_of_REG1(void)
-{
-	return memblock.memory.regions[1].size;
-}
-
 static void __init csky_memblock_init(void)
 {
 	unsigned long zone_size[MAX_NR_ZONES];
-	unsigned long zhole_size[MAX_NR_ZONES];
 	signed long size;
 
 	memblock_reserve(__pa(_stext), _end - _stext);
@@ -57,54 +40,36 @@
 	memblock_dump_all();
 
 	memset(zone_size, 0, sizeof(zone_size));
-	memset(zhole_size, 0, sizeof(zhole_size));
 
 	min_low_pfn = PFN_UP(memblock_start_of_DRAM());
-	max_pfn	    = PFN_DOWN(memblock_end_of_DRAM());
-
-	max_low_pfn = PFN_UP(memblock_end_of_REG0());
-	if (max_low_pfn == 0)
-		max_low_pfn = max_pfn;
+	max_low_pfn = max_pfn = PFN_DOWN(memblock_end_of_DRAM());
 
 	size = max_pfn - min_low_pfn;
 
-	if (memblock.memory.cnt > 1) {
-		zone_size[ZONE_NORMAL]  =
-			PFN_DOWN(memblock_start_of_REG1()) - min_low_pfn;
-		zhole_size[ZONE_NORMAL] =
-			PFN_DOWN(memblock_start_of_REG1()) - max_low_pfn;
+	if (size <= PFN_DOWN(SSEG_SIZE - PHYS_OFFSET_OFFSET))
+		zone_size[ZONE_NORMAL] = size;
+	else if (size < PFN_DOWN(LOWMEM_LIMIT - PHYS_OFFSET_OFFSET)) {
+		zone_size[ZONE_NORMAL] =
+				PFN_DOWN(SSEG_SIZE - PHYS_OFFSET_OFFSET);
+		max_low_pfn = min_low_pfn + zone_size[ZONE_NORMAL];
 	} else {
-		if (size <= PFN_DOWN(LOWMEM_LIMIT - PHYS_OFFSET_OFFSET))
-			zone_size[ZONE_NORMAL] = max_pfn - min_low_pfn;
-		else {
-			zone_size[ZONE_NORMAL] =
+		zone_size[ZONE_NORMAL] =
 				PFN_DOWN(LOWMEM_LIMIT - PHYS_OFFSET_OFFSET);
-			max_low_pfn = min_low_pfn + zone_size[ZONE_NORMAL];
-		}
+		max_low_pfn = min_low_pfn + zone_size[ZONE_NORMAL];
+		write_mmu_msa1(read_mmu_msa0() + SSEG_SIZE);
 	}
 
 #ifdef CONFIG_HIGHMEM
-	size = 0;
-	if (memblock.memory.cnt > 1) {
-		size = PFN_DOWN(memblock_size_of_REG1());
-		highstart_pfn = PFN_DOWN(memblock_start_of_REG1());
-	} else {
-		size = max_pfn - min_low_pfn -
-			PFN_DOWN(LOWMEM_LIMIT - PHYS_OFFSET_OFFSET);
-		highstart_pfn =  min_low_pfn +
-			PFN_DOWN(LOWMEM_LIMIT - PHYS_OFFSET_OFFSET);
-	}
-
-	if (size > 0)
-		zone_size[ZONE_HIGHMEM] = size;
+	zone_size[ZONE_HIGHMEM] = max_pfn - max_low_pfn;
 
-	highend_pfn = max_pfn;
+	highstart_pfn = max_low_pfn;
+	highend_pfn   = max_pfn;
 #endif
 	memblock_set_current_limit(PFN_PHYS(max_low_pfn));
 
 	dma_contiguous_reserve(0);
 
-	free_area_init_node(0, zone_size, min_low_pfn, zhole_size);
+	free_area_init_node(0, zone_size, min_low_pfn, NULL);
 }
 
 void __init setup_arch(char **cmdline_p)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/csky/kernel/signal.c
+++ linux-xilinx-zynqmp-5.4.0/arch/csky/kernel/signal.c
@@ -52,10 +52,14 @@
 	struct sigcontext __user *sc)
 {
 	int err = 0;
+	unsigned long sr = regs->sr;
 
 	/* sc_pt_regs is structured the same as the start of pt_regs */
 	err |= __copy_from_user(regs, &sc->sc_pt_regs, sizeof(struct pt_regs));
 
+	/* BIT(0) of regs->sr is Condition Code/Carry bit */
+	regs->sr = (sr & ~1) | (regs->sr & 1);
+
 	/* Restore the floating-point state. */
 	err |= restore_fpu_state(sc);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/csky/kernel/smp.c
+++ linux-xilinx-zynqmp-5.4.0/arch/csky/kernel/smp.c
@@ -22,6 +22,9 @@
 #include <asm/sections.h>
 #include <asm/mmu_context.h>
 #include <asm/pgalloc.h>
+#ifdef CONFIG_CPU_HAS_FPU
+#include <abi/fpu.h>
+#endif
 
 struct ipi_data_struct {
 	unsigned long bits ____cacheline_aligned;
@@ -120,7 +123,7 @@
 	int rc;
 
 	if (ipi_irq == 0)
-		panic("%s IRQ mapping failed\n", __func__);
+		return;
 
 	rc = request_percpu_irq(ipi_irq, handle_ipi, "IPI Interrupt",
 				&ipi_dummy_dev);
@@ -156,6 +159,8 @@
 volatile unsigned int secondary_ccr;
 volatile unsigned int secondary_stack;
 
+unsigned long secondary_msa1;
+
 int __cpu_up(unsigned int cpu, struct task_struct *tidle)
 {
 	unsigned long mask = 1 << cpu;
@@ -164,6 +169,7 @@
 		(unsigned int) task_stack_page(tidle) + THREAD_SIZE - 8;
 	secondary_hint = mfcr("cr31");
 	secondary_ccr  = mfcr("cr18");
+	secondary_msa1 = read_mmu_msa1();
 
 	/*
 	 * Because other CPUs are in reset status, we must flush data
--- linux-xilinx-zynqmp-5.4.0.orig/arch/csky/kernel/traps.c
+++ linux-xilinx-zynqmp-5.4.0/arch/csky/kernel/traps.c
@@ -85,7 +85,7 @@
 	pr_err("%s: %08x\n", str, nr);
 	show_regs(regs);
 	add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
-	do_exit(SIGSEGV);
+	make_task_dead(SIGSEGV);
 }
 
 void buserr(struct pt_regs *regs)
@@ -115,8 +115,9 @@
 	int sig;
 	unsigned long vector;
 	siginfo_t info;
+	struct task_struct *tsk = current;
 
-	vector = (mfcr("psr") >> 16) & 0xff;
+	vector = (regs->sr >> 16) & 0xff;
 
 	switch (vector) {
 	case VEC_ZERODIV:
@@ -129,6 +130,7 @@
 		sig = SIGTRAP;
 		break;
 	case VEC_ILLEGAL:
+		tsk->thread.trap_no = vector;
 		die_if_kernel("Kernel mode ILLEGAL", regs, vector);
 #ifndef CONFIG_CPU_NO_USER_BKPT
 		if (*(uint16_t *)instruction_pointer(regs) != USR_BKPT)
@@ -146,16 +148,20 @@
 		sig = SIGTRAP;
 		break;
 	case VEC_ACCESS:
+		tsk->thread.trap_no = vector;
 		return buserr(regs);
 #ifdef CONFIG_CPU_NEED_SOFTALIGN
 	case VEC_ALIGN:
+		tsk->thread.trap_no = vector;
 		return csky_alignment(regs);
 #endif
 #ifdef CONFIG_CPU_HAS_FPU
 	case VEC_FPE:
+		tsk->thread.trap_no = vector;
 		die_if_kernel("Kernel mode FPE", regs, vector);
 		return fpu_fpe(regs);
 	case VEC_PRIV:
+		tsk->thread.trap_no = vector;
 		die_if_kernel("Kernel mode PRIV", regs, vector);
 		if (fpu_libc_helper(regs))
 			return;
@@ -164,5 +170,8 @@
 		sig = SIGSEGV;
 		break;
 	}
+
+	tsk->thread.trap_no = vector;
+
 	send_sig(sig, current, 0);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/csky/lib/usercopy.c
+++ linux-xilinx-zynqmp-5.4.0/arch/csky/lib/usercopy.c
@@ -7,10 +7,7 @@
 unsigned long raw_copy_from_user(void *to, const void *from,
 			unsigned long n)
 {
-	if (access_ok(from, n))
-		__copy_user_zeroing(to, from, n);
-	else
-		memset(to, 0, n);
+	___copy_from_user(to, from, n);
 	return n;
 }
 EXPORT_SYMBOL(raw_copy_from_user);
@@ -18,8 +15,7 @@
 unsigned long raw_copy_to_user(void *to, const void *from,
 			unsigned long n)
 {
-	if (access_ok(to, n))
-		__copy_user(to, from, n);
+	___copy_to_user(to, from, n);
 	return n;
 }
 EXPORT_SYMBOL(raw_copy_to_user);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/csky/mm/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/csky/mm/Makefile
@@ -1,8 +1,10 @@
 # SPDX-License-Identifier: GPL-2.0-only
 ifeq ($(CONFIG_CPU_HAS_CACHEV2),y)
 obj-y +=			cachev2.o
+CFLAGS_REMOVE_cachev2.o = $(CC_FLAGS_FTRACE)
 else
 obj-y +=			cachev1.o
+CFLAGS_REMOVE_cachev1.o = $(CC_FLAGS_FTRACE)
 endif
 
 obj-y +=			dma-mapping.o
--- linux-xilinx-zynqmp-5.4.0.orig/arch/csky/mm/dma-mapping.c
+++ linux-xilinx-zynqmp-5.4.0/arch/csky/mm/dma-mapping.c
@@ -58,8 +58,8 @@
 	cache_op(page_to_phys(page), size, dma_wbinv_set_zero_range);
 }
 
-void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr,
-			      size_t size, enum dma_data_direction dir)
+void arch_sync_dma_for_device(phys_addr_t paddr, size_t size,
+		enum dma_data_direction dir)
 {
 	switch (dir) {
 	case DMA_TO_DEVICE:
@@ -74,8 +74,8 @@
 	}
 }
 
-void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr,
-			   size_t size, enum dma_data_direction dir)
+void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size,
+		enum dma_data_direction dir)
 {
 	switch (dir) {
 	case DMA_TO_DEVICE:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/csky/mm/fault.c
+++ linux-xilinx-zynqmp-5.4.0/arch/csky/mm/fault.c
@@ -179,11 +179,14 @@
 bad_area_nosemaphore:
 	/* User mode accesses just cause a SIGSEGV */
 	if (user_mode(regs)) {
+		tsk->thread.trap_no = (regs->sr >> 16) & 0xff;
 		force_sig_fault(SIGSEGV, si_code, (void __user *)address);
 		return;
 	}
 
 no_context:
+	tsk->thread.trap_no = (regs->sr >> 16) & 0xff;
+
 	/* Are we prepared to handle this kernel fault? */
 	if (fixup_exception(regs))
 		return;
@@ -198,6 +201,8 @@
 	die_if_kernel("Oops", regs, write);
 
 out_of_memory:
+	tsk->thread.trap_no = (regs->sr >> 16) & 0xff;
+
 	/*
 	 * We ran out of memory, call the OOM killer, and return the userspace
 	 * (which will retry the fault, or kill us if we got oom-killed).
@@ -206,6 +211,8 @@
 	return;
 
 do_sigbus:
+	tsk->thread.trap_no = (regs->sr >> 16) & 0xff;
+
 	up_read(&mm->mmap_sem);
 
 	/* Kernel mode? Handle exceptions or die */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/csky/mm/init.c
+++ linux-xilinx-zynqmp-5.4.0/arch/csky/mm/init.c
@@ -31,6 +31,7 @@
 
 pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned_bss;
 pte_t invalid_pte_table[PTRS_PER_PTE] __page_aligned_bss;
+EXPORT_SYMBOL(invalid_pte_table);
 unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]
 						__page_aligned_bss;
 EXPORT_SYMBOL(empty_zero_page);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/h8300/kernel/asm-offsets.c
+++ linux-xilinx-zynqmp-5.4.0/arch/h8300/kernel/asm-offsets.c
@@ -63,6 +63,9 @@
 	OFFSET(TI_FLAGS, thread_info, flags);
 	OFFSET(TI_CPU, thread_info, cpu);
 	OFFSET(TI_PRE, thread_info, preempt_count);
+#ifdef CONFIG_PREEMPTION
+	DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count));
+#endif
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/h8300/kernel/traps.c
+++ linux-xilinx-zynqmp-5.4.0/arch/h8300/kernel/traps.c
@@ -17,6 +17,7 @@
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/sched/debug.h>
+#include <linux/sched/task.h>
 #include <linux/mm_types.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -110,7 +111,7 @@
 	dump(fp);
 
 	spin_unlock_irq(&die_lock);
-	do_exit(SIGSEGV);
+	make_task_dead(SIGSEGV);
 }
 
 static int kstack_depth_to_print = 24;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/h8300/mm/fault.c
+++ linux-xilinx-zynqmp-5.4.0/arch/h8300/mm/fault.c
@@ -52,7 +52,7 @@
 	printk(" at virtual address %08lx\n", address);
 	if (!user_mode(regs))
 		die("Oops", regs, error_code);
-	do_exit(SIGKILL);
+	make_task_dead(SIGKILL);
 
 	return 1;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/hexagon/include/asm/atomic.h
+++ linux-xilinx-zynqmp-5.4.0/arch/hexagon/include/asm/atomic.h
@@ -91,7 +91,7 @@
 		"1:	%0 = memw_locked(%1);\n"			\
 		"	%0 = "#op "(%0,%2);\n"				\
 		"	memw_locked(%1,P3)=%0;\n"			\
-		"	if !P3 jump 1b;\n"				\
+		"	if (!P3) jump 1b;\n"				\
 		: "=&r" (output)					\
 		: "r" (&v->counter), "r" (i)				\
 		: "memory", "p3"					\
@@ -107,7 +107,7 @@
 		"1:	%0 = memw_locked(%1);\n"			\
 		"	%0 = "#op "(%0,%2);\n"				\
 		"	memw_locked(%1,P3)=%0;\n"			\
-		"	if !P3 jump 1b;\n"				\
+		"	if (!P3) jump 1b;\n"				\
 		: "=&r" (output)					\
 		: "r" (&v->counter), "r" (i)				\
 		: "memory", "p3"					\
@@ -124,7 +124,7 @@
 		"1:	%0 = memw_locked(%2);\n"			\
 		"	%1 = "#op "(%0,%3);\n"				\
 		"	memw_locked(%2,P3)=%1;\n"			\
-		"	if !P3 jump 1b;\n"				\
+		"	if (!P3) jump 1b;\n"				\
 		: "=&r" (output), "=&r" (val)				\
 		: "r" (&v->counter), "r" (i)				\
 		: "memory", "p3"					\
@@ -173,7 +173,7 @@
 		"	}"
 		"	memw_locked(%2, p3) = %1;"
 		"	{"
-		"		if !p3 jump 1b;"
+		"		if (!p3) jump 1b;"
 		"	}"
 		"2:"
 		: "=&r" (__oldval), "=&r" (tmp)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/hexagon/include/asm/bitops.h
+++ linux-xilinx-zynqmp-5.4.0/arch/hexagon/include/asm/bitops.h
@@ -38,7 +38,7 @@
 	"1:	R12 = memw_locked(R10);\n"
 	"	{ P0 = tstbit(R12,R11); R12 = clrbit(R12,R11); }\n"
 	"	memw_locked(R10,P1) = R12;\n"
-	"	{if !P1 jump 1b; %0 = mux(P0,#1,#0);}\n"
+	"	{if (!P1) jump 1b; %0 = mux(P0,#1,#0);}\n"
 	: "=&r" (oldval)
 	: "r" (addr), "r" (nr)
 	: "r10", "r11", "r12", "p0", "p1", "memory"
@@ -62,7 +62,7 @@
 	"1:	R12 = memw_locked(R10);\n"
 	"	{ P0 = tstbit(R12,R11); R12 = setbit(R12,R11); }\n"
 	"	memw_locked(R10,P1) = R12;\n"
-	"	{if !P1 jump 1b; %0 = mux(P0,#1,#0);}\n"
+	"	{if (!P1) jump 1b; %0 = mux(P0,#1,#0);}\n"
 	: "=&r" (oldval)
 	: "r" (addr), "r" (nr)
 	: "r10", "r11", "r12", "p0", "p1", "memory"
@@ -88,7 +88,7 @@
 	"1:	R12 = memw_locked(R10);\n"
 	"	{ P0 = tstbit(R12,R11); R12 = togglebit(R12,R11); }\n"
 	"	memw_locked(R10,P1) = R12;\n"
-	"	{if !P1 jump 1b; %0 = mux(P0,#1,#0);}\n"
+	"	{if (!P1) jump 1b; %0 = mux(P0,#1,#0);}\n"
 	: "=&r" (oldval)
 	: "r" (addr), "r" (nr)
 	: "r10", "r11", "r12", "p0", "p1", "memory"
@@ -223,7 +223,7 @@
 	int r;
 
 	asm("{ P0 = cmp.eq(%1,#0); %0 = ct0(%1);}\n"
-		"{ if P0 %0 = #0; if !P0 %0 = add(%0,#1);}\n"
+		"{ if (P0) %0 = #0; if (!P0) %0 = add(%0,#1);}\n"
 		: "=&r" (r)
 		: "r" (x)
 		: "p0");
--- linux-xilinx-zynqmp-5.4.0.orig/arch/hexagon/include/asm/cmpxchg.h
+++ linux-xilinx-zynqmp-5.4.0/arch/hexagon/include/asm/cmpxchg.h
@@ -30,7 +30,7 @@
 	__asm__ __volatile__ (
 	"1:	%0 = memw_locked(%1);\n"    /*  load into retval */
 	"	memw_locked(%1,P0) = %2;\n" /*  store into memory */
-	"	if !P0 jump 1b;\n"
+	"	if (!P0) jump 1b;\n"
 	: "=&r" (retval)
 	: "r" (ptr), "r" (x)
 	: "memory", "p0"
@@ -56,7 +56,7 @@
 	__typeof__(ptr) __ptr = (ptr);				\
 	__typeof__(*(ptr)) __old = (old);			\
 	__typeof__(*(ptr)) __new = (new);			\
-	__typeof__(*(ptr)) __oldval = 0;			\
+	__typeof__(*(ptr)) __oldval = (__typeof__(*(ptr))) 0;	\
 								\
 	asm volatile(						\
 		"1:	%0 = memw_locked(%1);\n"		\
--- linux-xilinx-zynqmp-5.4.0.orig/arch/hexagon/include/asm/futex.h
+++ linux-xilinx-zynqmp-5.4.0/arch/hexagon/include/asm/futex.h
@@ -16,7 +16,7 @@
 	    /* For example: %1 = %4 */ \
 	    insn \
 	"2: memw_locked(%3,p2) = %1;\n" \
-	"   if !p2 jump 1b;\n" \
+	"   if (!p2) jump 1b;\n" \
 	"   %1 = #0;\n" \
 	"3:\n" \
 	".section .fixup,\"ax\"\n" \
@@ -84,10 +84,10 @@
 	"1: %1 = memw_locked(%3)\n"
 	"   {\n"
 	"      p2 = cmp.eq(%1,%4)\n"
-	"      if !p2.new jump:NT 3f\n"
+	"      if (!p2.new) jump:NT 3f\n"
 	"   }\n"
 	"2: memw_locked(%3,p2) = %5\n"
-	"   if !p2 jump 1b\n"
+	"   if (!p2) jump 1b\n"
 	"3:\n"
 	".section .fixup,\"ax\"\n"
 	"4: %0 = #%6\n"
--- linux-xilinx-zynqmp-5.4.0.orig/arch/hexagon/include/asm/io.h
+++ linux-xilinx-zynqmp-5.4.0/arch/hexagon/include/asm/io.h
@@ -171,16 +171,10 @@
 #define writew_relaxed __raw_writew
 #define writel_relaxed __raw_writel
 
-/*
- * Need an mtype somewhere in here, for cache type deals?
- * This is probably too long for an inline.
- */
-void __iomem *ioremap_nocache(unsigned long phys_addr, unsigned long size);
+void __iomem *ioremap(unsigned long phys_addr, unsigned long size);
+#define ioremap_nocache ioremap
+#define ioremap_uc(X, Y) ioremap((X), (Y))
 
-static inline void __iomem *ioremap(unsigned long phys_addr, unsigned long size)
-{
-	return ioremap_nocache(phys_addr, size);
-}
 
 static inline void iounmap(volatile void __iomem *addr)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/hexagon/include/asm/spinlock.h
+++ linux-xilinx-zynqmp-5.4.0/arch/hexagon/include/asm/spinlock.h
@@ -30,9 +30,9 @@
 	__asm__ __volatile__(
 		"1:	R6 = memw_locked(%0);\n"
 		"	{ P3 = cmp.ge(R6,#0); R6 = add(R6,#1);}\n"
-		"	{ if !P3 jump 1b; }\n"
+		"	{ if (!P3) jump 1b; }\n"
 		"	memw_locked(%0,P3) = R6;\n"
-		"	{ if !P3 jump 1b; }\n"
+		"	{ if (!P3) jump 1b; }\n"
 		:
 		: "r" (&lock->lock)
 		: "memory", "r6", "p3"
@@ -46,7 +46,7 @@
 		"1:	R6 = memw_locked(%0);\n"
 		"	R6 = add(R6,#-1);\n"
 		"	memw_locked(%0,P3) = R6\n"
-		"	if !P3 jump 1b;\n"
+		"	if (!P3) jump 1b;\n"
 		:
 		: "r" (&lock->lock)
 		: "memory", "r6", "p3"
@@ -61,7 +61,7 @@
 	__asm__ __volatile__(
 		"	R6 = memw_locked(%1);\n"
 		"	{ %0 = #0; P3 = cmp.ge(R6,#0); R6 = add(R6,#1);}\n"
-		"	{ if !P3 jump 1f; }\n"
+		"	{ if (!P3) jump 1f; }\n"
 		"	memw_locked(%1,P3) = R6;\n"
 		"	{ %0 = P3 }\n"
 		"1:\n"
@@ -78,9 +78,9 @@
 	__asm__ __volatile__(
 		"1:	R6 = memw_locked(%0)\n"
 		"	{ P3 = cmp.eq(R6,#0);  R6 = #-1;}\n"
-		"	{ if !P3 jump 1b; }\n"
+		"	{ if (!P3) jump 1b; }\n"
 		"	memw_locked(%0,P3) = R6;\n"
-		"	{ if !P3 jump 1b; }\n"
+		"	{ if (!P3) jump 1b; }\n"
 		:
 		: "r" (&lock->lock)
 		: "memory", "r6", "p3"
@@ -94,7 +94,7 @@
 	__asm__ __volatile__(
 		"	R6 = memw_locked(%1)\n"
 		"	{ %0 = #0; P3 = cmp.eq(R6,#0);  R6 = #-1;}\n"
-		"	{ if !P3 jump 1f; }\n"
+		"	{ if (!P3) jump 1f; }\n"
 		"	memw_locked(%1,P3) = R6;\n"
 		"	%0 = P3;\n"
 		"1:\n"
@@ -117,9 +117,9 @@
 	__asm__ __volatile__(
 		"1:	R6 = memw_locked(%0);\n"
 		"	P3 = cmp.eq(R6,#0);\n"
-		"	{ if !P3 jump 1b; R6 = #1; }\n"
+		"	{ if (!P3) jump 1b; R6 = #1; }\n"
 		"	memw_locked(%0,P3) = R6;\n"
-		"	{ if !P3 jump 1b; }\n"
+		"	{ if (!P3) jump 1b; }\n"
 		:
 		: "r" (&lock->lock)
 		: "memory", "r6", "p3"
@@ -139,7 +139,7 @@
 	__asm__ __volatile__(
 		"	R6 = memw_locked(%1);\n"
 		"	P3 = cmp.eq(R6,#0);\n"
-		"	{ if !P3 jump 1f; R6 = #1; %0 = #0; }\n"
+		"	{ if (!P3) jump 1f; R6 = #1; %0 = #0; }\n"
 		"	memw_locked(%1,P3) = R6;\n"
 		"	%0 = P3;\n"
 		"1:\n"
--- linux-xilinx-zynqmp-5.4.0.orig/arch/hexagon/include/asm/syscalls.h
+++ linux-xilinx-zynqmp-5.4.0/arch/hexagon/include/asm/syscalls.h
@@ -0,0 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#include <asm-generic/syscalls.h>
+
+asmlinkage long sys_hexagon_fadvise64_64(int fd, int advice,
+	                                  u32 a2, u32 a3, u32 a4, u32 a5);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/hexagon/include/uapi/asm/unistd.h
+++ linux-xilinx-zynqmp-5.4.0/arch/hexagon/include/uapi/asm/unistd.h
@@ -36,5 +36,6 @@
 #define __ARCH_WANT_SYS_VFORK
 #define __ARCH_WANT_SYS_FORK
 #define __ARCH_WANT_TIME32_SYSCALLS
+#define __ARCH_WANT_SYNC_FILE_RANGE2
 
 #include <asm-generic/unistd.h>
--- linux-xilinx-zynqmp-5.4.0.orig/arch/hexagon/kernel/dma.c
+++ linux-xilinx-zynqmp-5.4.0/arch/hexagon/kernel/dma.c
@@ -55,8 +55,8 @@
 	gen_pool_free(coherent_pool, (unsigned long) vaddr, size);
 }
 
-void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr,
-		size_t size, enum dma_data_direction dir)
+void arch_sync_dma_for_device(phys_addr_t paddr, size_t size,
+		enum dma_data_direction dir)
 {
 	void *addr = phys_to_virt(paddr);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/hexagon/kernel/hexagon_ksyms.c
+++ linux-xilinx-zynqmp-5.4.0/arch/hexagon/kernel/hexagon_ksyms.c
@@ -20,7 +20,7 @@
 EXPORT_SYMBOL(__vmsetie);
 EXPORT_SYMBOL(__vmyield);
 EXPORT_SYMBOL(empty_zero_page);
-EXPORT_SYMBOL(ioremap_nocache);
+EXPORT_SYMBOL(ioremap);
 EXPORT_SYMBOL(memcpy);
 EXPORT_SYMBOL(memset);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/hexagon/kernel/stacktrace.c
+++ linux-xilinx-zynqmp-5.4.0/arch/hexagon/kernel/stacktrace.c
@@ -11,8 +11,6 @@
 #include <linux/thread_info.h>
 #include <linux/module.h>
 
-register unsigned long current_frame_pointer asm("r30");
-
 struct stackframe {
 	unsigned long fp;
 	unsigned long rets;
@@ -30,7 +28,7 @@
 
 	low = (unsigned long)task_stack_page(current);
 	high = low + THREAD_SIZE;
-	fp = current_frame_pointer;
+	fp = (unsigned long)__builtin_frame_address(0);
 
 	while (fp >= low && fp <= (high - sizeof(*frame))) {
 		frame = (struct stackframe *)fp;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/hexagon/kernel/syscalltab.c
+++ linux-xilinx-zynqmp-5.4.0/arch/hexagon/kernel/syscalltab.c
@@ -14,6 +14,13 @@
 #undef __SYSCALL
 #define __SYSCALL(nr, call) [nr] = (call),
 
+SYSCALL_DEFINE6(hexagon_fadvise64_64, int, fd, int, advice,
+		SC_ARG64(offset), SC_ARG64(len))
+{
+	return ksys_fadvise64_64(fd, SC_VAL64(loff_t, offset), SC_VAL64(loff_t, len), advice);
+}
+#define sys_fadvise64_64 sys_hexagon_fadvise64_64
+
 void *sys_call_table[__NR_syscalls] = {
 #include <asm/unistd.h>
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/hexagon/kernel/traps.c
+++ linux-xilinx-zynqmp-5.4.0/arch/hexagon/kernel/traps.c
@@ -202,8 +202,10 @@
 	printk(KERN_EMERG "Oops: %s[#%d]:\n", str, ++die.counter);
 
 	if (notify_die(DIE_OOPS, str, regs, err, pt_cause(regs), SIGSEGV) ==
-	    NOTIFY_STOP)
+	    NOTIFY_STOP) {
+		spin_unlock_irq(&die.lock);
 		return 1;
+	}
 
 	print_modules();
 	show_regs(regs);
@@ -221,7 +223,7 @@
 		panic("Fatal exception");
 
 	oops_exit();
-	do_exit(err);
+	make_task_dead(err);
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/hexagon/kernel/vm_entry.S
+++ linux-xilinx-zynqmp-5.4.0/arch/hexagon/kernel/vm_entry.S
@@ -369,7 +369,7 @@
 		R26.L = #LO(do_work_pending);
 		R0 = #VM_INT_DISABLE;
 	}
-	if P0 jump check_work_pending
+	if (P0) jump check_work_pending
 	{
 		R0 = R25;
 		callr R24
--- linux-xilinx-zynqmp-5.4.0.orig/arch/hexagon/kernel/vmlinux.lds.S
+++ linux-xilinx-zynqmp-5.4.0/arch/hexagon/kernel/vmlinux.lds.S
@@ -60,13 +60,8 @@
 
 	_end = .;
 
-	/DISCARD/ : {
-		EXIT_TEXT
-		EXIT_DATA
-		EXIT_CALL
-	}
-
 	STABS_DEBUG
 	DWARF_DEBUG
 
+	DISCARDS
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/hexagon/lib/io.c
+++ linux-xilinx-zynqmp-5.4.0/arch/hexagon/lib/io.c
@@ -27,6 +27,7 @@
 		*dst++ = *src;
 
 }
+EXPORT_SYMBOL(__raw_readsw);
 
 /*
  * __raw_writesw - read words a short at a time
@@ -47,6 +48,7 @@
 
 
 }
+EXPORT_SYMBOL(__raw_writesw);
 
 /*  Pretty sure len is pre-adjusted for the length of the access already */
 void __raw_readsl(const void __iomem *addr, void *data, int len)
@@ -62,6 +64,7 @@
 
 
 }
+EXPORT_SYMBOL(__raw_readsl);
 
 void __raw_writesl(void __iomem *addr, const void *data, int len)
 {
@@ -76,3 +79,4 @@
 
 
 }
+EXPORT_SYMBOL(__raw_writesl);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/hexagon/mm/ioremap.c
+++ linux-xilinx-zynqmp-5.4.0/arch/hexagon/mm/ioremap.c
@@ -9,7 +9,7 @@
 #include <linux/vmalloc.h>
 #include <linux/mm.h>
 
-void __iomem *ioremap_nocache(unsigned long phys_addr, unsigned long size)
+void __iomem *ioremap(unsigned long phys_addr, unsigned long size)
 {
 	unsigned long last_addr, addr;
 	unsigned long offset = phys_addr & ~PAGE_MASK;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/ia64/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/ia64/Kconfig
@@ -8,6 +8,7 @@
 
 config IA64
 	bool
+	select ARCH_HAS_CPU_FINALIZE_INIT
 	select ARCH_MIGHT_HAVE_PC_PARPORT
 	select ARCH_MIGHT_HAVE_PC_SERIO
 	select ACPI
@@ -360,7 +361,7 @@
 	depends on PROC_KCORE
 
 config IA64_MCA_RECOVERY
-	tristate "MCA recovery from errors other than TLB."
+	bool "MCA recovery from errors other than TLB."
 
 config PERFMON
 	bool "Performance monitor support"
--- linux-xilinx-zynqmp-5.4.0.orig/arch/ia64/Kconfig.debug
+++ linux-xilinx-zynqmp-5.4.0/arch/ia64/Kconfig.debug
@@ -39,7 +39,7 @@
 
 config IA64_DEBUG_CMPXCHG
 	bool "Turn on compare-and-exchange bug checking (slow!)"
-	depends on DEBUG_KERNEL
+	depends on DEBUG_KERNEL && PRINTK
 	help
 	  Selecting this option turns on bug checking for the IA-64
 	  compare-and-exchange instructions.  This is slow!  Itaniums
--- linux-xilinx-zynqmp-5.4.0.orig/arch/ia64/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/ia64/Makefile
@@ -40,7 +40,7 @@
 endif
 
 quiet_cmd_gzip = GZIP    $@
-cmd_gzip = cat $(real-prereqs) | gzip -n -f -9 > $@
+cmd_gzip = cat $(real-prereqs) | $(KGZIP) -n -f -9 > $@
 
 quiet_cmd_objcopy = OBJCOPY $@
 cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@
--- linux-xilinx-zynqmp-5.4.0.orig/arch/ia64/configs/zx1_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/ia64/configs/zx1_defconfig
@@ -35,7 +35,6 @@
 CONFIG_CHR_DEV_ST=y
 CONFIG_CHR_DEV_OSST=y
 CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/ia64/include/asm/module.h
+++ linux-xilinx-zynqmp-5.4.0/arch/ia64/include/asm/module.h
@@ -14,16 +14,20 @@
 struct elf64_shdr;			/* forward declration */
 
 struct mod_arch_specific {
+	/* Used only at module load time. */
 	struct elf64_shdr *core_plt;	/* core PLT section */
 	struct elf64_shdr *init_plt;	/* init PLT section */
 	struct elf64_shdr *got;		/* global offset table */
 	struct elf64_shdr *opd;		/* official procedure descriptors */
 	struct elf64_shdr *unwind;	/* unwind-table section */
 	unsigned long gp;		/* global-pointer for module */
+	unsigned int next_got_entry;	/* index of next available got entry */
 
+	/* Used at module run and cleanup time. */
 	void *core_unw_table;		/* core unwind-table cookie returned by unwinder */
 	void *init_unw_table;		/* init unwind-table cookie returned by unwinder */
-	unsigned int next_got_entry;	/* index of next available got entry */
+	void *opd_addr;			/* symbolize uses .opd to get to actual function */
+	unsigned long opd_size;
 };
 
 #define MODULE_PROC_FAMILY	"ia64"
--- linux-xilinx-zynqmp-5.4.0.orig/arch/ia64/include/asm/processor.h
+++ linux-xilinx-zynqmp-5.4.0/arch/ia64/include/asm/processor.h
@@ -552,7 +552,7 @@
 {
 	unsigned int reg = vector / 64;
 	unsigned int bit = vector % 64;
-	u64 irr;
+	unsigned long irr;
 
 	switch (reg) {
 	case 0: irr = ia64_getreg(_IA64_REG_CR_IRR0); break;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/ia64/include/asm/ptrace.h
+++ linux-xilinx-zynqmp-5.4.0/arch/ia64/include/asm/ptrace.h
@@ -54,8 +54,7 @@
 
 static inline unsigned long user_stack_pointer(struct pt_regs *regs)
 {
-	/* FIXME: should this be bspstore + nr_dirty regs? */
-	return regs->ar_bspstore;
+	return regs->r12;
 }
 
 static inline int is_syscall_success(struct pt_regs *regs)
@@ -79,11 +78,6 @@
 	unsigned long __ip = instruction_pointer(regs);			\
 	(__ip & ~3UL) + ((__ip & 3UL) << 2);				\
 })
-/*
- * Why not default?  Because user_stack_pointer() on ia64 gives register
- * stack backing store instead...
- */
-#define current_user_stack_pointer() (current_pt_regs()->r12)
 
   /* given a pointer to a task_struct, return the user's pt_regs */
 # define task_pt_regs(t)		(((struct pt_regs *) ((char *) (t) + IA64_STK_OFFSET)) - 1)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/ia64/include/asm/syscall.h
+++ linux-xilinx-zynqmp-5.4.0/arch/ia64/include/asm/syscall.h
@@ -32,7 +32,7 @@
 static inline long syscall_get_error(struct task_struct *task,
 				     struct pt_regs *regs)
 {
-	return regs->r10 == -1 ? regs->r8:0;
+	return regs->r10 == -1 ? -regs->r8:0;
 }
 
 static inline long syscall_get_return_value(struct task_struct *task,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/ia64/include/asm/timex.h
+++ linux-xilinx-zynqmp-5.4.0/arch/ia64/include/asm/timex.h
@@ -39,6 +39,7 @@
 	ret = ia64_getreg(_IA64_REG_AR_ITC);
 	return ret;
 }
+#define get_cycles get_cycles
 
 extern void ia64_cpu_local_tick (void);
 extern unsigned long long ia64_native_sched_clock (void);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/ia64/kernel/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/ia64/kernel/Makefile
@@ -41,7 +41,7 @@
 endif
 obj-$(CONFIG_INTEL_IOMMU)	+= pci-dma.o
 
-obj-$(CONFIG_BINFMT_ELF)	+= elfcore.o
+obj-$(CONFIG_ELF_CORE)		+= elfcore.o
 
 # fp_emulate() expects f2-f5,f16-f31 to contain the user-level state.
 CFLAGS_traps.o  += -mfixed-range=f2-f5,f16-f31
--- linux-xilinx-zynqmp-5.4.0.orig/arch/ia64/kernel/acpi.c
+++ linux-xilinx-zynqmp-5.4.0/arch/ia64/kernel/acpi.c
@@ -448,7 +448,8 @@
 	if (srat_num_cpus == 0) {
 		node_set_online(0);
 		node_cpuid[0].phys_id = hard_smp_processor_id();
-		return;
+		slit_distance(0, 0) = LOCAL_DISTANCE;
+		goto out;
 	}
 
 	/*
@@ -491,7 +492,7 @@
 			for (j = 0; j < MAX_NUMNODES; j++)
 				slit_distance(i, j) = i == j ?
 					LOCAL_DISTANCE : REMOTE_DISTANCE;
-		return;
+		goto out;
 	}
 
 	memset(numa_slit, -1, sizeof(numa_slit));
@@ -516,6 +517,8 @@
 		printk("\n");
 	}
 #endif
+out:
+	node_possible_map = node_online_map;
 }
 #endif				/* CONFIG_ACPI_NUMA */
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/ia64/kernel/err_inject.c
+++ linux-xilinx-zynqmp-5.4.0/arch/ia64/kernel/err_inject.c
@@ -59,7 +59,7 @@
 		char *buf)						\
 {									\
 	u32 cpu=dev->id;						\
-	return sprintf(buf, "%lx\n", name[cpu]);			\
+	return sprintf(buf, "%llx\n", name[cpu]);			\
 }
 
 #define store(name)							\
@@ -86,9 +86,9 @@
 
 #ifdef ERR_INJ_DEBUG
 	printk(KERN_DEBUG "pal_mc_err_inject for cpu%d:\n", cpu);
-	printk(KERN_DEBUG "err_type_info=%lx,\n", err_type_info[cpu]);
-	printk(KERN_DEBUG "err_struct_info=%lx,\n", err_struct_info[cpu]);
-	printk(KERN_DEBUG "err_data_buffer=%lx, %lx, %lx.\n",
+	printk(KERN_DEBUG "err_type_info=%llx,\n", err_type_info[cpu]);
+	printk(KERN_DEBUG "err_struct_info=%llx,\n", err_struct_info[cpu]);
+	printk(KERN_DEBUG "err_data_buffer=%llx, %llx, %llx.\n",
 			  err_data_buffer[cpu].data1,
 			  err_data_buffer[cpu].data2,
 			  err_data_buffer[cpu].data3);
@@ -117,8 +117,8 @@
 
 #ifdef ERR_INJ_DEBUG
 	printk(KERN_DEBUG "Returns: status=%d,\n", (int)status[cpu]);
-	printk(KERN_DEBUG "capabilities=%lx,\n", capabilities[cpu]);
-	printk(KERN_DEBUG "resources=%lx\n", resources[cpu]);
+	printk(KERN_DEBUG "capabilities=%llx,\n", capabilities[cpu]);
+	printk(KERN_DEBUG "resources=%llx\n", resources[cpu]);
 #endif
 	return size;
 }
@@ -131,7 +131,7 @@
 			char *buf)
 {
 	unsigned int cpu=dev->id;
-	return sprintf(buf, "%lx\n", phys_addr[cpu]);
+	return sprintf(buf, "%llx\n", phys_addr[cpu]);
 }
 
 static ssize_t
@@ -145,7 +145,7 @@
 	ret = get_user_pages_fast(virt_addr, 1, FOLL_WRITE, NULL);
 	if (ret<=0) {
 #ifdef ERR_INJ_DEBUG
-		printk("Virtual address %lx is not existing.\n",virt_addr);
+		printk("Virtual address %llx is not existing.\n", virt_addr);
 #endif
 		return -EINVAL;
 	}
@@ -163,7 +163,7 @@
 {
 	unsigned int cpu=dev->id;
 
-	return sprintf(buf, "%lx, %lx, %lx\n",
+	return sprintf(buf, "%llx, %llx, %llx\n",
 			err_data_buffer[cpu].data1,
 			err_data_buffer[cpu].data2,
 			err_data_buffer[cpu].data3);
@@ -178,13 +178,13 @@
 	int ret;
 
 #ifdef ERR_INJ_DEBUG
-	printk("write err_data_buffer=[%lx,%lx,%lx] on cpu%d\n",
+	printk("write err_data_buffer=[%llx,%llx,%llx] on cpu%d\n",
 		 err_data_buffer[cpu].data1,
 		 err_data_buffer[cpu].data2,
 		 err_data_buffer[cpu].data3,
 		 cpu);
 #endif
-	ret=sscanf(buf, "%lx, %lx, %lx",
+	ret = sscanf(buf, "%llx, %llx, %llx",
 			&err_data_buffer[cpu].data1,
 			&err_data_buffer[cpu].data2,
 			&err_data_buffer[cpu].data3);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/ia64/kernel/kprobes.c
+++ linux-xilinx-zynqmp-5.4.0/arch/ia64/kernel/kprobes.c
@@ -411,7 +411,7 @@
 	struct hlist_node *tmp;
 	unsigned long flags, orig_ret_address = 0;
 	unsigned long trampoline_address =
-		((struct fnptr *)kretprobe_trampoline)->ip;
+		(unsigned long)dereference_function_descriptor(kretprobe_trampoline);
 
 	INIT_HLIST_HEAD(&empty_rp);
 	kretprobe_hash_lock(current, &head, &flags);
@@ -487,7 +487,7 @@
 	ri->ret_addr = (kprobe_opcode_t *)regs->b0;
 
 	/* Replace the return addr with trampoline addr */
-	regs->b0 = ((struct fnptr *)kretprobe_trampoline)->ip;
+	regs->b0 = (unsigned long)dereference_function_descriptor(kretprobe_trampoline);
 }
 
 /* Check the instruction in the slot is break */
@@ -991,14 +991,14 @@
 int __init arch_init_kprobes(void)
 {
 	trampoline_p.addr =
-		(kprobe_opcode_t *)((struct fnptr *)kretprobe_trampoline)->ip;
+		dereference_function_descriptor(kretprobe_trampoline);
 	return register_kprobe(&trampoline_p);
 }
 
 int __kprobes arch_trampoline_kprobe(struct kprobe *p)
 {
 	if (p->addr ==
-		(kprobe_opcode_t *)((struct fnptr *)kretprobe_trampoline)->ip)
+		dereference_function_descriptor(kretprobe_trampoline))
 		return 1;
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/ia64/kernel/mca.c
+++ linux-xilinx-zynqmp-5.4.0/arch/ia64/kernel/mca.c
@@ -1851,7 +1851,7 @@
 			data = mca_bootmem();
 			first_time = 0;
 		} else
-			data = (void *)__get_free_pages(GFP_KERNEL,
+			data = (void *)__get_free_pages(GFP_ATOMIC,
 							get_order(sz));
 		if (!data)
 			panic("Could not allocate MCA memory for cpu %d\n",
--- linux-xilinx-zynqmp-5.4.0.orig/arch/ia64/kernel/mca_drv.c
+++ linux-xilinx-zynqmp-5.4.0/arch/ia64/kernel/mca_drv.c
@@ -12,6 +12,7 @@
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/sched.h>
+#include <linux/sched/task.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/kallsyms.h>
@@ -176,7 +177,7 @@
 	spin_unlock(&mca_bh_lock);
 
 	/* This process is about to be killed itself */
-	do_exit(SIGKILL);
+	make_task_dead(SIGKILL);
 }
 
 /**
@@ -343,7 +344,7 @@
 
 	/* - 2 - */
 	sect_min_size = sal_log_sect_min_sizes[0];
-	for (i = 1; i < sizeof sal_log_sect_min_sizes/sizeof(size_t); i++)
+	for (i = 1; i < ARRAY_SIZE(sal_log_sect_min_sizes); i++)
 		if (sect_min_size > sal_log_sect_min_sizes[i])
 			sect_min_size = sal_log_sect_min_sizes[i];
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/ia64/kernel/module.c
+++ linux-xilinx-zynqmp-5.4.0/arch/ia64/kernel/module.c
@@ -905,9 +905,31 @@
 int
 module_finalize (const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *mod)
 {
+	struct mod_arch_specific *mas = &mod->arch;
+
 	DEBUGP("%s: init: entry=%p\n", __func__, mod->init);
-	if (mod->arch.unwind)
+	if (mas->unwind)
 		register_unwind_table(mod);
+
+	/*
+	 * ".opd" was already relocated to the final destination. Store
+	 * it's address for use in symbolizer.
+	 */
+	mas->opd_addr = (void *)mas->opd->sh_addr;
+	mas->opd_size = mas->opd->sh_size;
+
+	/*
+	 * Module relocation was already done at this point. Section
+	 * headers are about to be deleted. Wipe out load-time context.
+	 */
+	mas->core_plt = NULL;
+	mas->init_plt = NULL;
+	mas->got = NULL;
+	mas->opd = NULL;
+	mas->unwind = NULL;
+	mas->gp = 0;
+	mas->next_got_entry = 0;
+
 	return 0;
 }
 
@@ -926,10 +948,9 @@
 
 void *dereference_module_function_descriptor(struct module *mod, void *ptr)
 {
-	Elf64_Shdr *opd = mod->arch.opd;
+	struct mod_arch_specific *mas = &mod->arch;
 
-	if (ptr < (void *)opd->sh_addr ||
-			ptr >= (void *)(opd->sh_addr + opd->sh_size))
+	if (ptr < mas->opd_addr || ptr >= mas->opd_addr + mas->opd_size)
 		return ptr;
 
 	return dereference_function_descriptor(ptr);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/ia64/kernel/process.c
+++ linux-xilinx-zynqmp-5.4.0/arch/ia64/kernel/process.c
@@ -444,7 +444,7 @@
 do_copy_task_regs (struct task_struct *task, struct unw_frame_info *info, void *arg)
 {
 	unsigned long mask, sp, nat_bits = 0, ar_rnat, urbs_end, cfm;
-	unsigned long uninitialized_var(ip);	/* GCC be quiet */
+	unsigned long ip;
 	elf_greg_t *dst = arg;
 	struct pt_regs *pt;
 	char nat;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/ia64/kernel/ptrace.c
+++ linux-xilinx-zynqmp-5.4.0/arch/ia64/kernel/ptrace.c
@@ -2147,27 +2147,39 @@
 {
 	struct syscall_get_set_args *args = data;
 	struct pt_regs *pt = args->regs;
-	unsigned long *krbs, cfm, ndirty;
+	unsigned long *krbs, cfm, ndirty, nlocals, nouts;
 	int i, count;
 
 	if (unw_unwind_to_user(info) < 0)
 		return;
 
+	/*
+	 * We get here via a few paths:
+	 * - break instruction: cfm is shared with caller.
+	 *   syscall args are in out= regs, locals are non-empty.
+	 * - epsinstruction: cfm is set by br.call
+	 *   locals don't exist.
+	 *
+	 * For both cases argguments are reachable in cfm.sof - cfm.sol.
+	 * CFM: [ ... | sor: 17..14 | sol : 13..7 | sof : 6..0 ]
+	 */
 	cfm = pt->cr_ifs;
+	nlocals = (cfm >> 7) & 0x7f; /* aka sol */
+	nouts = (cfm & 0x7f) - nlocals; /* aka sof - sol */
 	krbs = (unsigned long *)info->task + IA64_RBS_OFFSET/8;
 	ndirty = ia64_rse_num_regs(krbs, krbs + (pt->loadrs >> 19));
 
 	count = 0;
 	if (in_syscall(pt))
-		count = min_t(int, args->n, cfm & 0x7f);
+		count = min_t(int, args->n, nouts);
 
+	/* Iterate over outs. */
 	for (i = 0; i < count; i++) {
+		int j = ndirty + nlocals + i + args->i;
 		if (args->rw)
-			*ia64_rse_skip_regs(krbs, ndirty + i + args->i) =
-				args->args[i];
+			*ia64_rse_skip_regs(krbs, j) = args->args[i];
 		else
-			args->args[i] = *ia64_rse_skip_regs(krbs,
-				ndirty + i + args->i);
+			args->args[i] = *ia64_rse_skip_regs(krbs, j);
 	}
 
 	if (!args->rw) {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/ia64/kernel/salinfo.c
+++ linux-xilinx-zynqmp-5.4.0/arch/ia64/kernel/salinfo.c
@@ -581,7 +581,7 @@
  * 'data' contains an integer that corresponds to the feature we're
  * testing
  */
-static int proc_salinfo_show(struct seq_file *m, void *v)
+static int __maybe_unused proc_salinfo_show(struct seq_file *m, void *v)
 {
 	unsigned long data = (unsigned long)v;
 	seq_puts(m, (sal_platform_features & data) ? "1\n" : "0\n");
--- linux-xilinx-zynqmp-5.4.0.orig/arch/ia64/kernel/setup.c
+++ linux-xilinx-zynqmp-5.4.0/arch/ia64/kernel/setup.c
@@ -1073,8 +1073,7 @@
 	}
 }
 
-void __init
-check_bugs (void)
+void __init arch_cpu_finalize_init(void)
 {
 	ia64_patch_mckinley_e9((unsigned long) __start___mckinley_e9_bundles,
 			       (unsigned long) __end___mckinley_e9_bundles);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/ia64/kernel/topology.c
+++ linux-xilinx-zynqmp-5.4.0/arch/ia64/kernel/topology.c
@@ -3,9 +3,8 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * This file contains NUMA specific variables and functions which can
- * be split away from DISCONTIGMEM and are used on NUMA machines with
- * contiguous memory.
+ * This file contains NUMA specific variables and functions which are used on
+ * NUMA machines with contiguous memory.
  * 		2002/08/07 Erich Focht <efocht@ess.nec.de>
  * Populate cpu entries in sysfs for non-numa systems as well
  *  	Intel Corporation - Ashok Raj
--- linux-xilinx-zynqmp-5.4.0.orig/arch/ia64/kernel/traps.c
+++ linux-xilinx-zynqmp-5.4.0/arch/ia64/kernel/traps.c
@@ -85,7 +85,7 @@
 	if (panic_on_oops)
 		panic("Fatal exception");
 
-  	do_exit(SIGSEGV);
+	make_task_dead(SIGSEGV);
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/ia64/mm/contig.c
+++ linux-xilinx-zynqmp-5.4.0/arch/ia64/mm/contig.c
@@ -81,7 +81,7 @@
 	return __per_cpu_start + __per_cpu_offset[smp_processor_id()];
 }
 
-static inline void
+static inline __init void
 alloc_per_cpu_data(void)
 {
 	size_t size = PERCPU_PAGE_SIZE * num_possible_cpus();
--- linux-xilinx-zynqmp-5.4.0.orig/arch/ia64/mm/discontig.c
+++ linux-xilinx-zynqmp-5.4.0/arch/ia64/mm/discontig.c
@@ -95,7 +95,7 @@
  * acpi_boot_init() (which builds the node_to_cpu_mask array) hasn't been
  * called yet.  Note that node 0 will also count all non-existent cpus.
  */
-static int __meminit early_nr_cpus_node(int node)
+static int early_nr_cpus_node(int node)
 {
 	int cpu, n = 0;
 
@@ -110,7 +110,7 @@
  * compute_pernodesize - compute size of pernode data
  * @node: the node id.
  */
-static unsigned long __meminit compute_pernodesize(int node)
+static unsigned long compute_pernodesize(int node)
 {
 	unsigned long pernodesize = 0, cpus;
 
@@ -180,7 +180,7 @@
 void __init setup_per_cpu_areas(void)
 {
 	struct pcpu_alloc_info *ai;
-	struct pcpu_group_info *uninitialized_var(gi);
+	struct pcpu_group_info *gi;
 	unsigned int *cpu_map;
 	void *base;
 	unsigned long base_offset;
@@ -367,7 +367,7 @@
 	}
 }
 
-static void __meminit scatter_node_data(void)
+static void scatter_node_data(void)
 {
 	pg_data_t **dst;
 	int node;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/ia64/mm/fault.c
+++ linux-xilinx-zynqmp-5.4.0/arch/ia64/mm/fault.c
@@ -272,7 +272,7 @@
 		regs = NULL;
 	bust_spinlocks(0);
 	if (regs)
-		do_exit(SIGKILL);
+		make_task_dead(SIGKILL);
 	return;
 
   out_of_memory:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/ia64/mm/init.c
+++ linux-xilinx-zynqmp-5.4.0/arch/ia64/mm/init.c
@@ -73,8 +73,8 @@
  * DMA can be marked as "clean" so that lazy_mmu_prot_update() doesn't have to
  * flush them when they get mapped into an executable vm-area.
  */
-void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr,
-		size_t size, enum dma_data_direction dir)
+void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size,
+		enum dma_data_direction dir)
 {
 	unsigned long pfn = PHYS_PFN(paddr);
 
@@ -518,7 +518,7 @@
 	if (map_start < map_end)
 		memmap_init_zone((unsigned long)(map_end - map_start),
 				 args->nid, args->zone, page_to_pfn(map_start),
-				 MEMMAP_EARLY, NULL);
+				 MEMINIT_EARLY, NULL);
 	return 0;
 }
 
@@ -527,8 +527,8 @@
 	     unsigned long start_pfn)
 {
 	if (!vmem_map) {
-		memmap_init_zone(size, nid, zone, start_pfn, MEMMAP_EARLY,
-				NULL);
+		memmap_init_zone(size, nid, zone, start_pfn,
+				 MEMINIT_EARLY, NULL);
 	} else {
 		struct page *start;
 		struct memmap_init_callback_data args;
@@ -689,9 +689,7 @@
 {
 	unsigned long start_pfn = start >> PAGE_SHIFT;
 	unsigned long nr_pages = size >> PAGE_SHIFT;
-	struct zone *zone;
 
-	zone = page_zone(pfn_to_page(start_pfn));
-	__remove_pages(zone, start_pfn, nr_pages, altmap);
+	__remove_pages(start_pfn, nr_pages, altmap);
 }
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/ia64/mm/numa.c
+++ linux-xilinx-zynqmp-5.4.0/arch/ia64/mm/numa.c
@@ -3,9 +3,8 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * This file contains NUMA specific variables and functions which can
- * be split away from DISCONTIGMEM and are used on NUMA machines with
- * contiguous memory.
+ * This file contains NUMA specific variables and functions which are used on
+ * NUMA machines with contiguous memory.
  * 
  *                         2002/08/07 Erich Focht <efocht@ess.nec.de>
  */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/ia64/mm/tlb.c
+++ linux-xilinx-zynqmp-5.4.0/arch/ia64/mm/tlb.c
@@ -369,7 +369,7 @@
 
 void ia64_tlb_init(void)
 {
-	ia64_ptce_info_t uninitialized_var(ptce_info); /* GCC be quiet */
+	ia64_ptce_info_t ptce_info;
 	u64 tr_pgbits;
 	long status;
 	pal_vm_info_1_u_t vm_info_1;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/ia64/scripts/unwcheck.py
+++ linux-xilinx-zynqmp-5.4.0/arch/ia64/scripts/unwcheck.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
 # SPDX-License-Identifier: GPL-2.0
 #
 # Usage: unwcheck.py FILE
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/68000/entry.S
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/68000/entry.S
@@ -47,6 +47,8 @@
 	jbsr	syscall_trace_enter
 	RESTORE_SWITCH_STACK
 	addql	#4,%sp
+	addql	#1,%d0
+	jeq	ret_from_exception
 	movel	%sp@(PT_OFF_ORIG_D0),%d1
 	movel	#-ENOSYS,%d0
 	cmpl	#NR_syscalls,%d1
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/Kconfig
@@ -4,6 +4,7 @@
 	default y
 	select ARCH_32BIT_OFF_T
 	select ARCH_HAS_BINFMT_FLAT
+	select ARCH_HAS_CPU_FINALIZE_INIT if MMU
 	select ARCH_HAS_DMA_PREP_COHERENT if HAS_DMA && MMU && !COLDFIRE
 	select ARCH_HAS_SYNC_DMA_FOR_DEVICE if HAS_DMA
 	select ARCH_MIGHT_HAVE_PC_PARPORT if ISA
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/Kconfig.bus
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/Kconfig.bus
@@ -63,7 +63,7 @@
 
 endif
 
-if !MMU
+if COLDFIRE
 
 config ISA_DMA_API
         def_bool !M5272
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/Kconfig.cpu
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/Kconfig.cpu
@@ -309,7 +309,7 @@
 
 config M68KFPU_EMU
 	bool "Math emulation support"
-	depends on MMU
+	depends on M68KCLASSIC && FPU
 	help
 	  At some point in the future, this will cause floating-point math
 	  instructions to be emulated by the kernel on machines that lack a
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/Kconfig.devices
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/Kconfig.devices
@@ -19,6 +19,7 @@
 # We have a dedicated heartbeat LED. :-)
 config PROC_HARDWARE
 	bool "/proc/hardware support"
+	depends on PROC_FS
 	help
 	  Say Y here to support the /proc/hardware file, which gives you
 	  access to information about the machine you're running on,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/Kconfig.machine
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/Kconfig.machine
@@ -23,6 +23,9 @@
 	  this kernel on an Atari, say Y here and browse the material
 	  available in <file:Documentation/m68k>; otherwise say N.
 
+config ATARI_KBD_CORE
+	bool
+
 config MAC
 	bool "Macintosh support"
 	depends on MMU
@@ -187,6 +190,7 @@
 config MEMORY_RESERVE
 	int "Memory reservation (MiB)"
 	depends on (UCSIMM || UCDIMM)
+	default 0
 	help
 	  Reserve certain memory regions on 68x328 based boards.
 
@@ -316,6 +320,7 @@
 
 config UBOOT
 	bool "Support for U-Boot command line parameters"
+	depends on COLDFIRE
 	help
 	  If you say Y here kernel will try to collect command
 	  line parameters from the initial u-boot stack.
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/Makefile
@@ -135,10 +135,10 @@
 ifndef CONFIG_KGDB
 	cp vmlinux vmlinux.tmp
 	$(STRIP) vmlinux.tmp
-	gzip -9c vmlinux.tmp >vmlinux.gz
+	$(KGZIP) -9c vmlinux.tmp >vmlinux.gz
 	rm vmlinux.tmp
 else
-	gzip -9c vmlinux >vmlinux.gz
+	$(KGZIP) -9c vmlinux >vmlinux.gz
 endif
 
 bzImage: vmlinux.bz2
@@ -148,10 +148,10 @@
 ifndef CONFIG_KGDB
 	cp vmlinux vmlinux.tmp
 	$(STRIP) vmlinux.tmp
-	bzip2 -1c vmlinux.tmp >vmlinux.bz2
+	$(KBZIP2) -1c vmlinux.tmp >vmlinux.bz2
 	rm vmlinux.tmp
 else
-	bzip2 -1c vmlinux >vmlinux.bz2
+	$(KBZIP2) -1c vmlinux >vmlinux.bz2
 endif
 
 archclean:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/amiga/config.c
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/amiga/config.c
@@ -180,6 +180,15 @@
 			dev->slotsize = be16_to_cpu(cd->cd_SlotSize);
 			dev->boardaddr = be32_to_cpu(cd->cd_BoardAddr);
 			dev->boardsize = be32_to_cpu(cd->cd_BoardSize);
+
+			/* CS-LAB Warp 1260 workaround */
+			if (be16_to_cpu(dev->rom.er_Manufacturer) == ZORRO_MANUF(ZORRO_PROD_CSLAB_WARP_1260) &&
+			    dev->rom.er_Product == ZORRO_PROD(ZORRO_PROD_CSLAB_WARP_1260)) {
+
+				/* turn off all interrupts */
+				pr_info("Warp 1260 card detected: applying interrupt storm workaround\n");
+				*(uint32_t *)(dev->boardaddr + 0x1000) = 0xfff;
+			}
 		} else
 			pr_warn("amiga_parse_bootinfo: too many AutoConfig devices\n");
 #endif /* CONFIG_ZORRO */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/atari/ataints.c
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/atari/ataints.c
@@ -302,11 +302,7 @@
 
 	if (ATARIHW_PRESENT(SCU)) {
 		/* init the SCU if present */
-		tt_scu.sys_mask = 0x10;		/* enable VBL (for the cursor) and
-									 * disable HSYNC interrupts (who
-									 * needs them?)  MFP and SCC are
-									 * enabled in VME mask
-									 */
+		tt_scu.sys_mask = 0x0;		/* disable all interrupts */
 		tt_scu.vme_mask = 0x60;		/* enable MFP and SCC ints */
 	} else {
 		/* If no SCU and no Hades, the HSYNC interrupt needs to be
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/coldfire/device.c
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/coldfire/device.c
@@ -92,7 +92,7 @@
 	.dev.platform_data	= mcf_uart_platform_data,
 };
 
-#if IS_ENABLED(CONFIG_FEC)
+#ifdef MCFFEC_BASE0
 
 #ifdef CONFIG_M5441x
 #define FEC_NAME	"enet-fec"
@@ -144,6 +144,7 @@
 		.platform_data		= FEC_PDATA,
 	}
 };
+#endif /* MCFFEC_BASE0 */
 
 #ifdef MCFFEC_BASE1
 static struct resource mcf_fec1_resources[] = {
@@ -181,7 +182,6 @@
 	}
 };
 #endif /* MCFFEC_BASE1 */
-#endif /* CONFIG_FEC */
 
 #if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI)
 /*
@@ -556,12 +556,12 @@
 
 static struct platform_device *mcf_devices[] __initdata = {
 	&mcf_uart,
-#if IS_ENABLED(CONFIG_FEC)
+#ifdef MCFFEC_BASE0
 	&mcf_fec0,
+#endif
 #ifdef MCFFEC_BASE1
 	&mcf_fec1,
 #endif
-#endif
 #if IS_ENABLED(CONFIG_SPI_COLDFIRE_QSPI)
 	&mcf_qspi,
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/coldfire/entry.S
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/coldfire/entry.S
@@ -92,6 +92,8 @@
 	jbsr	syscall_trace_enter
 	RESTORE_SWITCH_STACK
 	addql	#4,%sp
+	addql	#1,%d0
+	jeq	ret_from_exception
 	movel	%d3,%a0
 	jbsr	%a0@
 	movel	%d0,%sp@(PT_OFF_D0)		/* save the return value */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/coldfire/pci.c
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/coldfire/pci.c
@@ -216,8 +216,10 @@
 
 	/* Keep a virtual mapping to IO/config space active */
 	iospace = (unsigned long) ioremap(PCI_IO_PA, PCI_IO_SIZE);
-	if (iospace == 0)
+	if (iospace == 0) {
+		pci_free_host_bridge(bridge);
 		return -ENODEV;
+	}
 	pr_info("Coldfire: PCI IO/config window mapped to 0x%x\n",
 		(u32) iospace);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/configs/amiga_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/configs/amiga_defconfig
@@ -334,7 +334,6 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_SAS_ATTRS=m
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/configs/apollo_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/configs/apollo_defconfig
@@ -319,7 +319,6 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_SAS_ATTRS=m
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/configs/atari_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/configs/atari_defconfig
@@ -334,7 +334,6 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_SAS_ATTRS=m
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/configs/bvme6000_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/configs/bvme6000_defconfig
@@ -316,7 +316,6 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_SAS_ATTRS=m
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/configs/hp300_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/configs/hp300_defconfig
@@ -318,7 +318,6 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_SAS_ATTRS=m
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/configs/mac_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/configs/mac_defconfig
@@ -325,7 +325,6 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_SAS_ATTRS=m
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/configs/multi_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/configs/multi_defconfig
@@ -358,7 +358,6 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_SAS_ATTRS=m
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/configs/mvme147_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/configs/mvme147_defconfig
@@ -315,7 +315,6 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_SAS_ATTRS=m
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/configs/mvme16x_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/configs/mvme16x_defconfig
@@ -316,7 +316,6 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_SAS_ATTRS=m
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/configs/q40_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/configs/q40_defconfig
@@ -324,7 +324,6 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_SAS_ATTRS=m
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/configs/sun3_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/configs/sun3_defconfig
@@ -313,7 +313,6 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_SAS_ATTRS=m
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/configs/sun3x_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/configs/sun3x_defconfig
@@ -313,7 +313,6 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_SAS_ATTRS=m
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/emu/nfeth.c
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/emu/nfeth.c
@@ -254,8 +254,8 @@
 
 	for (i = 0; i < MAX_UNIT; i++) {
 		if (nfeth_dev[i]) {
-			unregister_netdev(nfeth_dev[0]);
-			free_netdev(nfeth_dev[0]);
+			unregister_netdev(nfeth_dev[i]);
+			free_netdev(nfeth_dev[i]);
 		}
 	}
 	free_irq(nfEtherIRQ, nfeth_interrupt);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/fpsp040/skeleton.S
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/fpsp040/skeleton.S
@@ -499,12 +499,13 @@
 	dbf	%d0,morein
 	rts
 
-	.section .fixup,#alloc,#execinstr
+	.section .fixup,"ax"
 	.even
 1:
-	jbra	fpsp040_die
+	jbsr	fpsp040_die
+	jbra	.Lnotkern
 
-	.section __ex_table,#alloc
+	.section __ex_table,"a"
 	.align	4
 
 	.long	in_ea,1b
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/ifpsp060/os.S
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/ifpsp060/os.S
@@ -379,11 +379,11 @@
 
 
 | Execption handling for movs access to illegal memory
-	.section .fixup,#alloc,#execinstr
+	.section .fixup,"ax"
 	.even
 1:	moveq		#-1,%d1
 	rts
-.section __ex_table,#alloc
+.section __ex_table,"a"
 	.align 4
 	.long	dmrbuae,1b
 	.long	dmrwuae,1b
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/include/asm/cmpxchg.h
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/include/asm/cmpxchg.h
@@ -33,7 +33,7 @@
 		x = tmp;
 		break;
 	default:
-		tmp = __invalid_xchg_size(x, ptr, size);
+		x = __invalid_xchg_size(x, ptr, size);
 		break;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/include/asm/m53xxacr.h
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/include/asm/m53xxacr.h
@@ -89,9 +89,9 @@
  * coherency though in all cases. And for copyback caches we will need
  * to push cached data as well.
  */
-#define CACHE_INIT	  CACR_CINVA
-#define CACHE_INVALIDATE  CACR_CINVA
-#define CACHE_INVALIDATED CACR_CINVA
+#define CACHE_INIT        (CACHE_MODE + CACR_CINVA - CACR_EC)
+#define CACHE_INVALIDATE  (CACHE_MODE + CACR_CINVA)
+#define CACHE_INVALIDATED (CACHE_MODE + CACR_CINVA)
 
 #define ACR0_MODE	((CONFIG_RAMBASE & 0xff000000) + \
 			 (0x000f0000) + \
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/include/asm/mac_via.h
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/include/asm/mac_via.h
@@ -257,6 +257,7 @@
 
 struct irq_desc;
 
+extern void via_l2_flush(int writeback);
 extern void via_register_interrupts(void);
 extern void via_irq_enable(int);
 extern void via_irq_disable(int);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/include/asm/mcfgpio.h
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/include/asm/mcfgpio.h
@@ -144,7 +144,7 @@
  * read-modify-write as well as those controlled by the EPORT and GPIO modules.
  */
 #define MCFGPIO_SCR_START		40
-#elif defined(CONFIGM5441x)
+#elif defined(CONFIG_M5441x)
 /* The m5441x EPORT doesn't have its own GPIO port, uses PORT C */
 #define MCFGPIO_SCR_START		0
 #else
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/include/asm/mvme147hw.h
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/include/asm/mvme147hw.h
@@ -66,6 +66,9 @@
 #define PCC_INT_ENAB		0x08
 
 #define PCC_TIMER_INT_CLR	0x80
+
+#define PCC_TIMER_TIC_EN	0x01
+#define PCC_TIMER_COC_EN	0x02
 #define PCC_TIMER_CLR_OVF	0x04
 
 #define PCC_LEVEL_ABORT		0x07
@@ -90,8 +93,8 @@
 #define M147_SCC_B_ADDR		0xfffe3000
 #define M147_SCC_PCLK		5000000
 
-#define MVME147_IRQ_SCSI_PORT	(IRQ_USER+0x45)
-#define MVME147_IRQ_SCSI_DMA	(IRQ_USER+0x46)
+#define MVME147_IRQ_SCSI_PORT	(IRQ_USER + 5)
+#define MVME147_IRQ_SCSI_DMA	(IRQ_USER + 6)
 
 /* SCC interrupts, for MVME147 */
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/include/asm/pgtable_no.h
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/include/asm/pgtable_no.h
@@ -42,7 +42,8 @@
  * ZERO_PAGE is a global shared page that is always zero: used
  * for zero-mapped memory areas etc..
  */
-#define ZERO_PAGE(vaddr)	(virt_to_page(0))
+extern void *empty_zero_page;
+#define ZERO_PAGE(vaddr)	(virt_to_page(empty_zero_page))
 
 /*
  * All 32bit addresses are effectively valid for vmalloc...
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/include/asm/raw_io.h
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/include/asm/raw_io.h
@@ -17,21 +17,21 @@
  * two accesses to memory, which may be undesirable for some devices.
  */
 #define in_8(addr) \
-    ({ u8 __v = (*(__force volatile u8 *) (addr)); __v; })
+    ({ u8 __v = (*(__force volatile u8 *) (unsigned long)(addr)); __v; })
 #define in_be16(addr) \
-    ({ u16 __v = (*(__force volatile u16 *) (addr)); __v; })
+    ({ u16 __v = (*(__force volatile u16 *) (unsigned long)(addr)); __v; })
 #define in_be32(addr) \
-    ({ u32 __v = (*(__force volatile u32 *) (addr)); __v; })
+    ({ u32 __v = (*(__force volatile u32 *) (unsigned long)(addr)); __v; })
 #define in_le16(addr) \
-    ({ u16 __v = le16_to_cpu(*(__force volatile __le16 *) (addr)); __v; })
+    ({ u16 __v = le16_to_cpu(*(__force volatile __le16 *) (unsigned long)(addr)); __v; })
 #define in_le32(addr) \
-    ({ u32 __v = le32_to_cpu(*(__force volatile __le32 *) (addr)); __v; })
+    ({ u32 __v = le32_to_cpu(*(__force volatile __le32 *) (unsigned long)(addr)); __v; })
 
-#define out_8(addr,b) (void)((*(__force volatile u8 *) (addr)) = (b))
-#define out_be16(addr,w) (void)((*(__force volatile u16 *) (addr)) = (w))
-#define out_be32(addr,l) (void)((*(__force volatile u32 *) (addr)) = (l))
-#define out_le16(addr,w) (void)((*(__force volatile __le16 *) (addr)) = cpu_to_le16(w))
-#define out_le32(addr,l) (void)((*(__force volatile __le32 *) (addr)) = cpu_to_le32(l))
+#define out_8(addr,b) (void)((*(__force volatile u8 *) (unsigned long)(addr)) = (b))
+#define out_be16(addr,w) (void)((*(__force volatile u16 *) (unsigned long)(addr)) = (w))
+#define out_be32(addr,l) (void)((*(__force volatile u32 *) (unsigned long)(addr)) = (l))
+#define out_le16(addr,w) (void)((*(__force volatile __le16 *) (unsigned long)(addr)) = cpu_to_le16(w))
+#define out_le32(addr,l) (void)((*(__force volatile __le32 *) (unsigned long)(addr)) = cpu_to_le32(l))
 
 #define raw_inb in_8
 #define raw_inw in_be16
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/include/asm/timex.h
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/include/asm/timex.h
@@ -35,7 +35,7 @@
 {
 	if (mach_random_get_entropy)
 		return mach_random_get_entropy();
-	return 0;
+	return random_get_entropy_fallback();
 }
 #define random_get_entropy	random_get_entropy
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/include/asm/vga.h
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/include/asm/vga.h
@@ -9,7 +9,7 @@
  */
 #ifndef CONFIG_PCI
 
-#include <asm/raw_io.h>
+#include <asm/io.h>
 #include <asm/kmap.h>
 
 /*
@@ -29,9 +29,9 @@
 #define inw_p(port)		0
 #define outb_p(port, val)	do { } while (0)
 #define outw(port, val)		do { } while (0)
-#define readb			raw_inb
-#define writeb			raw_outb
-#define writew			raw_outw
+#define readb			__raw_readb
+#define writeb			__raw_writeb
+#define writew			__raw_writew
 
 #endif /* CONFIG_PCI */
 #endif /* _ASM_M68K_VGA_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/kernel/dma.c
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/kernel/dma.c
@@ -61,8 +61,8 @@
 
 #endif /* CONFIG_MMU && !CONFIG_COLDFIRE */
 
-void arch_sync_dma_for_device(struct device *dev, phys_addr_t handle,
-		size_t size, enum dma_data_direction dir)
+void arch_sync_dma_for_device(phys_addr_t handle, size_t size,
+		enum dma_data_direction dir)
 {
 	switch (dir) {
 	case DMA_BIDIRECTIONAL:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/kernel/early_printk.c
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/kernel/early_printk.c
@@ -12,8 +12,9 @@
 #include <linux/string.h>
 #include <asm/setup.h>
 
-extern void mvme16x_cons_write(struct console *co,
-			       const char *str, unsigned count);
+
+#include "../mvme147/mvme147.h"
+#include "../mvme16x/mvme16x.h"
 
 asmlinkage void __init debug_cons_nputs(const char *s, unsigned n);
 
@@ -22,7 +23,9 @@
 {
 #if !(defined(CONFIG_SUN3) || defined(CONFIG_M68000) || \
       defined(CONFIG_COLDFIRE))
-	if (MACH_IS_MVME16x)
+	if (MACH_IS_MVME147)
+		mvme147_scc_write(c, s, n);
+	else if (MACH_IS_MVME16x)
 		mvme16x_cons_write(c, s, n);
 	else
 		debug_cons_nputs(s, n);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/kernel/entry.S
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/kernel/entry.S
@@ -160,9 +160,12 @@
 	jbsr	syscall_trace
 	RESTORE_SWITCH_STACK
 	addql	#4,%sp
+	addql	#1,%d0			| optimization for cmpil #-1,%d0
+	jeq	ret_from_syscall
 	movel	%sp@(PT_OFF_ORIG_D0),%d0
 	cmpl	#NR_syscalls,%d0
 	jcs	syscall
+	jra	ret_from_syscall
 badsys:
 	movel	#-ENOSYS,%sp@(PT_OFF_D0)
 	jra	ret_from_syscall
@@ -179,6 +182,8 @@
 	movel	%curptr@(TASK_STACK),%a1
 	tstb	%a1@(TINFO_FLAGS+2)
 	jge	1f
+	lea	%sp@(SWITCH_STACK_SIZE),%a1
+	movel	%a1,%curptr@(TASK_THREAD+THREAD_ESP0)
 	jbsr	syscall_trace
 1:	RESTORE_SWITCH_STACK
 	addql	#4,%sp
@@ -422,7 +427,9 @@
 	movec	%a0,%dfc
 
 	/* restore status register */
-	movew	%a1@(TASK_THREAD+THREAD_SR),%sr
+	movew	%a1@(TASK_THREAD+THREAD_SR),%d0
+	oriw	#0x0700,%d0
+	movew	%d0,%sr
 
 	rts
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/kernel/relocate_kernel.S
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/kernel/relocate_kernel.S
@@ -26,7 +26,7 @@
 	lea %pc@(.Lcopy),%a4
 2:	addl #0x00000000,%a4		/* virt_to_phys() */
 
-	.section ".m68k_fixup","aw"
+	.section .m68k_fixup,"aw"
 	.long M68K_FIXUP_MEMOFFSET, 2b+2
 	.previous
 
@@ -49,7 +49,7 @@
 	lea %pc@(.Lcont040),%a4
 5:	addl #0x00000000,%a4		/* virt_to_phys() */
 
-	.section ".m68k_fixup","aw"
+	.section .m68k_fixup,"aw"
 	.long M68K_FIXUP_MEMOFFSET, 5b+2
 	.previous
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/kernel/setup_mm.c
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/kernel/setup_mm.c
@@ -10,6 +10,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/cpu.h>
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/delay.h>
@@ -527,7 +528,7 @@
 module_init(proc_hardware_init);
 #endif
 
-void check_bugs(void)
+void __init arch_cpu_finalize_init(void)
 {
 #if defined(CONFIG_FPU) && !defined(CONFIG_M68KFPU_EMU)
 	if (m68k_fputype == 0) {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/kernel/setup_no.c
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/kernel/setup_no.c
@@ -139,7 +139,8 @@
 	pr_debug("MEMORY -> ROMFS=0x%p-0x%06lx MEM=0x%06lx-0x%06lx\n ",
 		 __bss_stop, memory_start, memory_start, memory_end);
 
-	memblock_add(memory_start, memory_end - memory_start);
+	memblock_add(_rambase, memory_end - _rambase);
+	memblock_reserve(_rambase, memory_start - _rambase);
 
 	/* Keep a copy of command line */
 	*cmdline_p = &command_line[0];
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/kernel/signal.c
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/kernel/signal.c
@@ -448,7 +448,7 @@
 
 	if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) {
 		fpu_version = sc->sc_fpstate[0];
-		if (CPU_IS_020_OR_030 &&
+		if (CPU_IS_020_OR_030 && !regs->stkadj &&
 		    regs->vector >= (VEC_FPBRUC * 4) &&
 		    regs->vector <= (VEC_FPNAN * 4)) {
 			/* Clear pending exception in 68882 idle frame */
@@ -511,7 +511,7 @@
 		if (!(CPU_IS_060 || CPU_IS_COLDFIRE))
 			context_size = fpstate[1];
 		fpu_version = fpstate[0];
-		if (CPU_IS_020_OR_030 &&
+		if (CPU_IS_020_OR_030 && !regs->stkadj &&
 		    regs->vector >= (VEC_FPBRUC * 4) &&
 		    regs->vector <= (VEC_FPNAN * 4)) {
 			/* Clear pending exception in 68882 idle frame */
@@ -829,18 +829,24 @@
 	return 0;
 }
 
+static inline struct pt_regs *rte_regs(struct pt_regs *regs)
+{
+	return (void *)regs + regs->stkadj;
+}
+
 static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
 			     unsigned long mask)
 {
+	struct pt_regs *tregs = rte_regs(regs);
 	sc->sc_mask = mask;
 	sc->sc_usp = rdusp();
 	sc->sc_d0 = regs->d0;
 	sc->sc_d1 = regs->d1;
 	sc->sc_a0 = regs->a0;
 	sc->sc_a1 = regs->a1;
-	sc->sc_sr = regs->sr;
-	sc->sc_pc = regs->pc;
-	sc->sc_formatvec = regs->format << 12 | regs->vector;
+	sc->sc_sr = tregs->sr;
+	sc->sc_pc = tregs->pc;
+	sc->sc_formatvec = tregs->format << 12 | tregs->vector;
 	save_a5_state(sc, regs);
 	save_fpu_state(sc, regs);
 }
@@ -848,6 +854,7 @@
 static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *regs)
 {
 	struct switch_stack *sw = (struct switch_stack *)regs - 1;
+	struct pt_regs *tregs = rte_regs(regs);
 	greg_t __user *gregs = uc->uc_mcontext.gregs;
 	int err = 0;
 
@@ -868,43 +875,50 @@
 	err |= __put_user(sw->a5, &gregs[13]);
 	err |= __put_user(sw->a6, &gregs[14]);
 	err |= __put_user(rdusp(), &gregs[15]);
-	err |= __put_user(regs->pc, &gregs[16]);
-	err |= __put_user(regs->sr, &gregs[17]);
-	err |= __put_user((regs->format << 12) | regs->vector, &uc->uc_formatvec);
+	err |= __put_user(tregs->pc, &gregs[16]);
+	err |= __put_user(tregs->sr, &gregs[17]);
+	err |= __put_user((tregs->format << 12) | tregs->vector, &uc->uc_formatvec);
 	err |= rt_save_fpu_state(uc, regs);
 	return err;
 }
 
 static inline void __user *
-get_sigframe(struct ksignal *ksig, size_t frame_size)
+get_sigframe(struct ksignal *ksig, struct pt_regs *tregs, size_t frame_size)
 {
 	unsigned long usp = sigsp(rdusp(), ksig);
+	unsigned long gap = 0;
+
+	if (CPU_IS_020_OR_030 && tregs->format == 0xb) {
+		/* USP is unreliable so use worst-case value */
+		gap = 256;
+	}
 
-	return (void __user *)((usp - frame_size) & -8UL);
+	return (void __user *)((usp - gap - frame_size) & -8UL);
 }
 
 static int setup_frame(struct ksignal *ksig, sigset_t *set,
 			struct pt_regs *regs)
 {
 	struct sigframe __user *frame;
-	int fsize = frame_extra_sizes(regs->format);
+	struct pt_regs *tregs = rte_regs(regs);
+	int fsize = frame_extra_sizes(tregs->format);
 	struct sigcontext context;
 	int err = 0, sig = ksig->sig;
 
 	if (fsize < 0) {
 		pr_debug("setup_frame: Unknown frame format %#x\n",
-			 regs->format);
+			 tregs->format);
 		return -EFAULT;
 	}
 
-	frame = get_sigframe(ksig, sizeof(*frame) + fsize);
+	frame = get_sigframe(ksig, tregs, sizeof(*frame) + fsize);
 
 	if (fsize)
 		err |= copy_to_user (frame + 1, regs + 1, fsize);
 
 	err |= __put_user(sig, &frame->sig);
 
-	err |= __put_user(regs->vector, &frame->code);
+	err |= __put_user(tregs->vector, &frame->code);
 	err |= __put_user(&frame->sc, &frame->psc);
 
 	if (_NSIG_WORDS > 1)
@@ -930,33 +944,27 @@
 	push_cache ((unsigned long) &frame->retcode);
 
 	/*
-	 * Set up registers for signal handler.  All the state we are about
-	 * to destroy is successfully copied to sigframe.
-	 */
-	wrusp ((unsigned long) frame);
-	regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
-	adjustformat(regs);
-
-	/*
 	 * This is subtle; if we build more than one sigframe, all but the
 	 * first one will see frame format 0 and have fsize == 0, so we won't
 	 * screw stkadj.
 	 */
-	if (fsize)
+	if (fsize) {
 		regs->stkadj = fsize;
-
-	/* Prepare to skip over the extra stuff in the exception frame.  */
-	if (regs->stkadj) {
-		struct pt_regs *tregs =
-			(struct pt_regs *)((ulong)regs + regs->stkadj);
+		tregs = rte_regs(regs);
 		pr_debug("Performing stackadjust=%04lx\n", regs->stkadj);
-		/* This must be copied with decreasing addresses to
-                   handle overlaps.  */
 		tregs->vector = 0;
 		tregs->format = 0;
-		tregs->pc = regs->pc;
 		tregs->sr = regs->sr;
 	}
+
+	/*
+	 * Set up registers for signal handler.  All the state we are about
+	 * to destroy is successfully copied to sigframe.
+	 */
+	wrusp ((unsigned long) frame);
+	tregs->pc = (unsigned long) ksig->ka.sa.sa_handler;
+	adjustformat(regs);
+
 	return 0;
 }
 
@@ -964,7 +972,8 @@
 			   struct pt_regs *regs)
 {
 	struct rt_sigframe __user *frame;
-	int fsize = frame_extra_sizes(regs->format);
+	struct pt_regs *tregs = rte_regs(regs);
+	int fsize = frame_extra_sizes(tregs->format);
 	int err = 0, sig = ksig->sig;
 
 	if (fsize < 0) {
@@ -973,7 +982,7 @@
 		return -EFAULT;
 	}
 
-	frame = get_sigframe(ksig, sizeof(*frame));
+	frame = get_sigframe(ksig, tregs, sizeof(*frame));
 
 	if (fsize)
 		err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize);
@@ -1014,33 +1023,26 @@
 	push_cache ((unsigned long) &frame->retcode);
 
 	/*
-	 * Set up registers for signal handler.  All the state we are about
-	 * to destroy is successfully copied to sigframe.
-	 */
-	wrusp ((unsigned long) frame);
-	regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
-	adjustformat(regs);
-
-	/*
 	 * This is subtle; if we build more than one sigframe, all but the
 	 * first one will see frame format 0 and have fsize == 0, so we won't
 	 * screw stkadj.
 	 */
-	if (fsize)
+	if (fsize) {
 		regs->stkadj = fsize;
-
-	/* Prepare to skip over the extra stuff in the exception frame.  */
-	if (regs->stkadj) {
-		struct pt_regs *tregs =
-			(struct pt_regs *)((ulong)regs + regs->stkadj);
+		tregs = rte_regs(regs);
 		pr_debug("Performing stackadjust=%04lx\n", regs->stkadj);
-		/* This must be copied with decreasing addresses to
-                   handle overlaps.  */
 		tregs->vector = 0;
 		tregs->format = 0;
-		tregs->pc = regs->pc;
 		tregs->sr = regs->sr;
 	}
+
+	/*
+	 * Set up registers for signal handler.  All the state we are about
+	 * to destroy is successfully copied to sigframe.
+	 */
+	wrusp ((unsigned long) frame);
+	tregs->pc = (unsigned long) ksig->ka.sa.sa_handler;
+	adjustformat(regs);
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/kernel/sys_m68k.c
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/kernel/sys_m68k.c
@@ -388,6 +388,8 @@
 		ret = -EPERM;
 		if (!capable(CAP_SYS_ADMIN))
 			goto out;
+
+		down_read(&current->mm->mmap_sem);
 	} else {
 		struct vm_area_struct *vma;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/kernel/traps.c
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/kernel/traps.c
@@ -30,6 +30,7 @@
 #include <linux/init.h>
 #include <linux/ptrace.h>
 #include <linux/kallsyms.h>
+#include <linux/extable.h>
 
 #include <asm/setup.h>
 #include <asm/fpu.h>
@@ -550,7 +551,8 @@
 			errorcode |= 2;
 
 		if (mmusr & (MMU_I | MMU_WP)) {
-			if (ssw & 4) {
+			/* We might have an exception table for this PC */
+			if (ssw & 4 && !search_exception_tables(fp->ptregs.pc)) {
 				pr_err("Data %s fault at %#010lx in %s (pc=%#lx)\n",
 				       ssw & RW ? "read" : "write",
 				       fp->un.fmtb.daddr,
@@ -1139,7 +1141,7 @@
 	pr_crit("%s: %08x\n", str, nr);
 	show_registers(fp);
 	add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
-	do_exit(SIGSEGV);
+	make_task_dead(SIGSEGV);
 }
 
 asmlinkage void set_esp0(unsigned long ssp)
@@ -1153,7 +1155,7 @@
  */
 asmlinkage void fpsp040_die(void)
 {
-	do_exit(SIGSEGV);
+	force_sigsegv(SIGSEGV);
 }
 
 #ifdef CONFIG_M68KFPU_EMU
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/mac/config.c
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/mac/config.c
@@ -59,7 +59,6 @@
 extern void iop_init(void);
 extern void via_init(void);
 extern void via_init_clock(irq_handler_t func);
-extern void via_flush_cache(void);
 extern void oss_init(void);
 extern void psc_init(void);
 extern void baboon_init(void);
@@ -130,21 +129,6 @@
 	return unknown;
 }
 
-/*
- * Flip into 24bit mode for an instant - flushes the L2 cache card. We
- * have to disable interrupts for this. Our IRQ handlers will crap
- * themselves if they take an IRQ in 24bit mode!
- */
-
-static void mac_cache_card_flush(int writeback)
-{
-	unsigned long flags;
-
-	local_irq_save(flags);
-	via_flush_cache();
-	local_irq_restore(flags);
-}
-
 void __init config_mac(void)
 {
 	if (!MACH_IS_MAC)
@@ -175,9 +159,8 @@
 	 * not.
 	 */
 
-	if (macintosh_config->ident == MAC_MODEL_IICI
-	    || macintosh_config->ident == MAC_MODEL_IIFX)
-		mach_l2_flush = mac_cache_card_flush;
+	if (macintosh_config->ident == MAC_MODEL_IICI)
+		mach_l2_flush = via_l2_flush;
 }
 
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/mac/iop.c
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/mac/iop.c
@@ -183,7 +183,7 @@
 
 static __inline__ void iop_stop(volatile struct mac_iop *iop)
 {
-	iop->status_ctrl &= ~IOP_RUN;
+	iop->status_ctrl = IOP_AUTOINC;
 }
 
 static __inline__ void iop_start(volatile struct mac_iop *iop)
@@ -191,14 +191,9 @@
 	iop->status_ctrl = IOP_RUN | IOP_AUTOINC;
 }
 
-static __inline__ void iop_bypass(volatile struct mac_iop *iop)
-{
-	iop->status_ctrl |= IOP_BYPASS;
-}
-
 static __inline__ void iop_interrupt(volatile struct mac_iop *iop)
 {
-	iop->status_ctrl |= IOP_IRQ;
+	iop->status_ctrl = IOP_IRQ | IOP_RUN | IOP_AUTOINC;
 }
 
 static int iop_alive(volatile struct mac_iop *iop)
@@ -244,7 +239,6 @@
 		} else {
 			iop_base[IOP_NUM_SCC] = (struct mac_iop *) SCC_IOP_BASE_QUADRA;
 		}
-		iop_base[IOP_NUM_SCC]->status_ctrl = 0x87;
 		iop_scc_present = 1;
 	} else {
 		iop_base[IOP_NUM_SCC] = NULL;
@@ -256,7 +250,7 @@
 		} else {
 			iop_base[IOP_NUM_ISM] = (struct mac_iop *) ISM_IOP_BASE_QUADRA;
 		}
-		iop_base[IOP_NUM_ISM]->status_ctrl = 0;
+		iop_stop(iop_base[IOP_NUM_ISM]);
 		iop_ism_present = 1;
 	} else {
 		iop_base[IOP_NUM_ISM] = NULL;
@@ -416,7 +410,8 @@
 	msg->status = IOP_MSGSTATUS_UNUSED;
 	msg = msg->next;
 	iop_send_queue[iop_num][chan] = msg;
-	if (msg) iop_do_send(msg);
+	if (msg && iop_readb(iop, IOP_ADDR_SEND_STATE + chan) == IOP_MSG_IDLE)
+		iop_do_send(msg);
 }
 
 /*
@@ -490,16 +485,12 @@
 
 	if (!(q = iop_send_queue[iop_num][chan])) {
 		iop_send_queue[iop_num][chan] = msg;
+		iop_do_send(msg);
 	} else {
 		while (q->next) q = q->next;
 		q->next = msg;
 	}
 
-	if (iop_readb(iop_base[iop_num],
-	    IOP_ADDR_SEND_STATE + chan) == IOP_MSG_IDLE) {
-		iop_do_send(msg);
-	}
-
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/mac/misc.c
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/mac/misc.c
@@ -452,30 +452,18 @@
 
 void mac_reset(void)
 {
-	if (macintosh_config->adb_type == MAC_ADB_II &&
-	    macintosh_config->ident != MAC_MODEL_SE30) {
-		/* need ROMBASE in booter */
-		/* indeed, plus need to MAP THE ROM !! */
-
-		if (mac_bi_data.rombase == 0)
-			mac_bi_data.rombase = 0x40800000;
-
-		/* works on some */
-		rom_reset = (void *) (mac_bi_data.rombase + 0xa);
-
-		local_irq_disable();
-		rom_reset();
 #ifdef CONFIG_ADB_CUDA
-	} else if (macintosh_config->adb_type == MAC_ADB_EGRET ||
-	           macintosh_config->adb_type == MAC_ADB_CUDA) {
+	if (macintosh_config->adb_type == MAC_ADB_EGRET ||
+	    macintosh_config->adb_type == MAC_ADB_CUDA) {
 		cuda_restart();
+	} else
 #endif
 #ifdef CONFIG_ADB_PMU
-	} else if (macintosh_config->adb_type == MAC_ADB_PB2) {
+	if (macintosh_config->adb_type == MAC_ADB_PB2) {
 		pmu_restart();
+	} else
 #endif
-	} else if (CPU_IS_030) {
-
+	if (CPU_IS_030) {
 		/* 030-specific reset routine.  The idea is general, but the
 		 * specific registers to reset are '030-specific.  Until I
 		 * have a non-030 machine, I can't test anything else.
@@ -523,6 +511,18 @@
 		    "jmp %/a0@\n\t" /* jump to the reset vector */
 		    ".chip 68k"
 		    : : "r" (offset), "a" (rombase) : "a0");
+	} else {
+		/* need ROMBASE in booter */
+		/* indeed, plus need to MAP THE ROM !! */
+
+		if (mac_bi_data.rombase == 0)
+			mac_bi_data.rombase = 0x40800000;
+
+		/* works on some */
+		rom_reset = (void *)(mac_bi_data.rombase + 0xa);
+
+		local_irq_disable();
+		rom_reset();
 	}
 
 	/* should never get here */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/mac/via.c
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/mac/via.c
@@ -294,10 +294,14 @@
  * the system into 24-bit mode for an instant.
  */
 
-void via_flush_cache(void)
+void via_l2_flush(int writeback)
 {
+	unsigned long flags;
+
+	local_irq_save(flags);
 	via2[gBufB] &= ~VIA2B_vMode32;
 	via2[gBufB] |= VIA2B_vMode32;
+	local_irq_restore(flags);
 }
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/mm/fault.c
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/mm/fault.c
@@ -48,7 +48,7 @@
 			pr_alert("Unable to handle kernel access");
 		pr_cont(" at virtual address %p\n", addr);
 		die_if_kernel("Oops", regs, 0 /*error_code*/);
-		do_exit(SIGKILL);
+		make_task_dead(SIGKILL);
 	}
 
 	return 1;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/mm/mcfmmu.c
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/mm/mcfmmu.c
@@ -164,7 +164,7 @@
 	m68k_memory[0].addr = _rambase;
 	m68k_memory[0].size = _ramend - _rambase;
 
-	memblock_add(m68k_memory[0].addr, m68k_memory[0].size);
+	memblock_add_node(m68k_memory[0].addr, m68k_memory[0].size, 0);
 
 	/* compute total pages in system */
 	num_pages = PFN_DOWN(_ramend - _rambase);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/mvme147/config.c
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/mvme147/config.c
@@ -36,6 +36,7 @@
 #include <asm/machdep.h>
 #include <asm/mvme147hw.h>
 
+#include "mvme147.h"
 
 static void mvme147_get_model(char *model);
 extern void mvme147_sched_init(irq_handler_t handler);
@@ -117,8 +118,10 @@
 	unsigned long flags;
 
 	local_irq_save(flags);
-	m147_pcc->t1_int_cntrl = PCC_TIMER_INT_CLR;
-	m147_pcc->t1_cntrl = PCC_TIMER_CLR_OVF;
+	m147_pcc->t1_cntrl = PCC_TIMER_CLR_OVF | PCC_TIMER_COC_EN |
+			     PCC_TIMER_TIC_EN;
+	m147_pcc->t1_int_cntrl = PCC_INT_ENAB | PCC_TIMER_INT_CLR |
+				 PCC_LEVEL_TIMER1;
 	clk_total += PCC_TIMER_CYCLES;
 	timer_routine(0, NULL);
 	local_irq_restore(flags);
@@ -136,10 +139,10 @@
 	/* Init the clock with a value */
 	/* The clock counter increments until 0xFFFF then reloads */
 	m147_pcc->t1_preload = PCC_TIMER_PRELOAD;
-	m147_pcc->t1_cntrl = 0x0;	/* clear timer */
-	m147_pcc->t1_cntrl = 0x3;	/* start timer */
-	m147_pcc->t1_int_cntrl = PCC_TIMER_INT_CLR;  /* clear pending ints */
-	m147_pcc->t1_int_cntrl = PCC_INT_ENAB|PCC_LEVEL_TIMER1;
+	m147_pcc->t1_cntrl = PCC_TIMER_CLR_OVF | PCC_TIMER_COC_EN |
+			     PCC_TIMER_TIC_EN;
+	m147_pcc->t1_int_cntrl = PCC_INT_ENAB | PCC_TIMER_INT_CLR |
+				 PCC_LEVEL_TIMER1;
 
 	clocksource_register_hz(&mvme147_clk, PCC_TIMER_CLOCK_FREQ);
 }
@@ -187,3 +190,32 @@
 	}
 	return 0;
 }
+
+static void scc_delay(void)
+{
+	__asm__ __volatile__ ("nop; nop;");
+}
+
+static void scc_write(char ch)
+{
+	do {
+		scc_delay();
+	} while (!(in_8(M147_SCC_A_ADDR) & BIT(2)));
+	scc_delay();
+	out_8(M147_SCC_A_ADDR, 8);
+	scc_delay();
+	out_8(M147_SCC_A_ADDR, ch);
+}
+
+void mvme147_scc_write(struct console *co, const char *str, unsigned int count)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	while (count--)	{
+		if (*str == '\n')
+			scc_write('\r');
+		scc_write(*str++);
+	}
+	local_irq_restore(flags);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/mvme147/mvme147.h
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/mvme147/mvme147.h
@@ -0,0 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+struct console;
+
+/* config.c */
+void mvme147_scc_write(struct console *co, const char *str, unsigned int count);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/mvme16x/config.c
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/mvme16x/config.c
@@ -39,6 +39,8 @@
 #include <asm/machdep.h>
 #include <asm/mvme16xhw.h>
 
+#include "mvme16x.h"
+
 extern t_bdid mvme_bdid;
 
 static MK48T08ptr_t volatile rtc = (MK48T08ptr_t)MVME_RTC_BASE;
@@ -368,6 +370,7 @@
 #define PCCTOVR1_COC_EN      0x02
 #define PCCTOVR1_OVR_CLR     0x04
 
+#define PCCTIC1_INT_LEVEL    6
 #define PCCTIC1_INT_CLR      0x08
 #define PCCTIC1_INT_EN       0x10
 
@@ -377,8 +380,8 @@
 	unsigned long flags;
 
 	local_irq_save(flags);
-	out_8(PCCTIC1, in_8(PCCTIC1) | PCCTIC1_INT_CLR);
-	out_8(PCCTOVR1, PCCTOVR1_OVR_CLR);
+	out_8(PCCTOVR1, PCCTOVR1_OVR_CLR | PCCTOVR1_TIC_EN | PCCTOVR1_COC_EN);
+	out_8(PCCTIC1, PCCTIC1_INT_EN | PCCTIC1_INT_CLR | PCCTIC1_INT_LEVEL);
 	clk_total += PCC_TIMER_CYCLES;
 	timer_routine(0, NULL);
 	local_irq_restore(flags);
@@ -392,14 +395,15 @@
     int irq;
 
     /* Using PCCchip2 or MC2 chip tick timer 1 */
-    out_be32(PCCTCNT1, 0);
-    out_be32(PCCTCMP1, PCC_TIMER_CYCLES);
-    out_8(PCCTOVR1, in_8(PCCTOVR1) | PCCTOVR1_TIC_EN | PCCTOVR1_COC_EN);
-    out_8(PCCTIC1, PCCTIC1_INT_EN | 6);
     if (request_irq(MVME16x_IRQ_TIMER, mvme16x_timer_int, IRQF_TIMER, "timer",
                     timer_routine))
 	panic ("Couldn't register timer int");
 
+    out_be32(PCCTCNT1, 0);
+    out_be32(PCCTCMP1, PCC_TIMER_CYCLES);
+    out_8(PCCTOVR1, PCCTOVR1_OVR_CLR | PCCTOVR1_TIC_EN | PCCTOVR1_COC_EN);
+    out_8(PCCTIC1, PCCTIC1_INT_EN | PCCTIC1_INT_CLR | PCCTIC1_INT_LEVEL);
+
     clocksource_register_hz(&mvme16x_clk, PCC_TIMER_CLOCK_FREQ);
 
     if (brdno == 0x0162 || brdno == 0x172)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/mvme16x/mvme16x.h
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/mvme16x/mvme16x.h
@@ -0,0 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+struct console;
+
+/* config.c */
+void mvme16x_cons_write(struct console *co, const char *str, unsigned count);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/m68k/q40/config.c
+++ linux-xilinx-zynqmp-5.4.0/arch/m68k/q40/config.c
@@ -264,6 +264,7 @@
 {
 	int tmp = Q40_RTC_CTRL;
 
+	pll->pll_ctrl = 0;
 	pll->pll_value = tmp & Q40_RTC_PLL_MASK;
 	if (tmp & Q40_RTC_PLL_SIGN)
 		pll->pll_value = -pll->pll_value;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/Kconfig
@@ -28,6 +28,7 @@
 	select HAVE_ARCH_HASH
 	select HAVE_ARCH_KGDB
 	select HAVE_DEBUG_KMEMLEAK
+	select HAVE_DMA_CONTIGUOUS
 	select HAVE_DYNAMIC_FTRACE
 	select HAVE_FTRACE_MCOUNT_RECORD
 	select HAVE_FUNCTION_GRAPH_TRACER
@@ -46,6 +47,9 @@
 	select VIRT_TO_BUS
 	select CPU_NO_EFFICIENT_FFS
 	select MMU_GATHER_NO_RANGE if MMU
+	select SPARSE_IRQ
+	select GENERIC_IRQ_MULTI_HANDLER
+	select HANDLE_DOMAIN_IRQ
 
 # Endianness selection
 choice
@@ -63,6 +67,33 @@
 
 endchoice
 
+config SMP
+	bool "SMP support (EXPERIMENTAL)"
+	default n
+	help
+	  This option enables SMP support for MicroBlaze. Every CPU has its own
+	  BRAM connected via LMB. The BRAM is used as CPU private memory, which
+	  is one reason CPU hotplug is not yet supported.
+	  Timers and interrupt controllers are placed on the same bus and
+	  accessible by all CPUs, but every CPU is assigned one timer and one
+	  interrupt controller. There is also one free running clock source
+	  timer for the whole system. The boot CPU wakes up other CPUs by
+	  sending a wake-up software Interrupt to a specific CPU that is
+	  sleeping. Wake-up will cause a jump to DDR start address where it is
+	  assumed that the kernel is placed. There is currently no support for
+	  placing the kernel at a different location.
+
+config GENERIC_LOCKBREAK
+	bool
+	default y
+	depends on SMP && PREEMPT
+
+config NR_CPUS
+	int "Maximum number of CPUs (2-8)"
+	range 2 8
+	depends on SMP
+	default "2"
+
 config ZONE_DMA
 	def_bool y
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/configs/mmu_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/configs/mmu_defconfig
@@ -26,6 +26,7 @@
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_PARTITION_ADVANCED=y
 # CONFIG_EFI_PARTITION is not set
+CONFIG_CMA=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -33,6 +34,8 @@
 # CONFIG_IPV6 is not set
 CONFIG_BRIDGE=m
 CONFIG_PCI=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_MTD=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_INTELEXT=y
@@ -71,14 +74,16 @@
 CONFIG_UIO=y
 CONFIG_UIO_PDRV_GENIRQ=y
 CONFIG_UIO_DMEM_GENIRQ=y
-CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
 # CONFIG_DNOTIFY is not set
+CONFIG_TMPFS=y
 CONFIG_CRAMFS=y
 CONFIG_ROMFS_FS=y
 CONFIG_NFS_FS=y
 CONFIG_CIFS=y
 CONFIG_CIFS_STATS2=y
 CONFIG_ENCRYPTED_KEYS=y
+CONFIG_DMA_CMA=y
 CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_SLAB=y
 CONFIG_DETECT_HUNG_TASK=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/configs/nommu_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/configs/nommu_defconfig
@@ -70,7 +70,7 @@
 CONFIG_FB=y
 CONFIG_FB_XILINX=y
 # CONFIG_USB_SUPPORT is not set
-CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
 # CONFIG_DNOTIFY is not set
 CONFIG_CRAMFS=y
 CONFIG_ROMFS_FS=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/Kbuild
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/Kbuild
@@ -1,7 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
 generated-y += syscall_table.h
-generic-y += barrier.h
-generic-y += bitops.h
 generic-y += bug.h
 generic-y += bugs.h
 generic-y += compat.h
@@ -12,7 +10,7 @@
 generic-y += exec.h
 generic-y += extable.h
 generic-y += fb.h
-generic-y += hardirq.h
+generic-y += hw_irq.h
 generic-y += irq_regs.h
 generic-y += irq_work.h
 generic-y += kdebug.h
@@ -31,8 +29,10 @@
 generic-y += serial.h
 generic-y += shmparam.h
 generic-y += syscalls.h
+generic-y += tlb.h
 generic-y += topology.h
 generic-y += trace_clock.h
+generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/atomic.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/atomic.h
@@ -1,28 +1,269 @@
 /* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2013-2020 Xilinx, Inc.
+ */
+
 #ifndef _ASM_MICROBLAZE_ATOMIC_H
 #define _ASM_MICROBLAZE_ATOMIC_H
 
+#include <linux/types.h>
 #include <asm/cmpxchg.h>
-#include <asm-generic/atomic.h>
-#include <asm-generic/atomic64.h>
+
+#define ATOMIC_INIT(i)	{ (i) }
+
+#define atomic_read(v)	READ_ONCE((v)->counter)
+
+static inline void atomic_set(atomic_t *v, int i)
+{
+	int result, tmp;
+
+	__asm__ __volatile__ (
+		/* load conditional address in %2 to %0 */
+		"1:	lwx	%0, %2, r0;\n"
+		/* attempt store */
+		"	swx	%3, %2, r0;\n"
+		/* checking msr carry flag */
+		"	addic	%1, r0, 0;\n"
+		/* store failed (MSR[C] set)? try again */
+		"	bnei	%1, 1b;\n"
+		/* Outputs: result value */
+		: "=&r" (result), "=&r" (tmp)
+		/* Inputs: counter address */
+		: "r" (&v->counter), "r" (i)
+		: "cc", "memory"
+	);
+}
+#define atomic_set	atomic_set
+
+/* Atomically perform op with v->counter and i, return result */
+#define ATOMIC_OP_RETURN(op, asm)					\
+static inline int atomic_##op##_return_relaxed(int i, atomic_t *v)	\
+{									\
+	int result, tmp;						\
+									\
+	__asm__ __volatile__ (						\
+		/* load conditional address in %2 to %0 */		\
+		"1:	lwx	%0, %2, r0;\n"				\
+		/* perform operation and save it to result */		\
+		#asm		" %0, %3, %0;\n"			\
+		/* attempt store */					\
+		"	swx	%0, %2, r0;\n"				\
+		/* checking msr carry flag */				\
+		"	addic	%1, r0, 0;\n"				\
+		/* store failed (MSR[C] set)? try again */		\
+		"	bnei	%1, 1b;\n"				\
+		/* Outputs: result value */				\
+		: "=&r" (result), "=&r" (tmp)				\
+		/* Inputs: counter address */				\
+		: "r"   (&v->counter), "r" (i)				\
+		: "cc", "memory"					\
+	);								\
+									\
+	return result;							\
+}									\
+									\
+static inline void atomic_##op(int i, atomic_t *v)			\
+{									\
+	atomic_##op##_return_relaxed(i, v);				\
+}
+
+/* Atomically perform op with v->counter and i, return orig v->counter */
+#define ATOMIC_FETCH_OP_RELAXED(op, asm)				\
+static inline int atomic_fetch_##op##_relaxed(int i, atomic_t *v)	\
+{									\
+	int old, tmp;							\
+									\
+	__asm__ __volatile__ (						\
+		/* load conditional address in %2 to %0 */		\
+		"1:	lwx	%0, %2, r0;\n"				\
+		/* perform operation and save it to tmp */		\
+		#asm		" %1, %3, %0;\n"			\
+		/* attempt store */					\
+		"	swx	%1, %2, r0;\n"				\
+		/* checking msr carry flag */				\
+		"	addic	%1, r0, 0;\n"				\
+		/* store failed (MSR[C] set)? try again */		\
+		"	bnei	%1, 1b;\n"				\
+		/* Outputs: old value */				\
+		: "=&r" (old), "=&r" (tmp)				\
+		/* Inputs: counter address */				\
+		: "r"   (&v->counter), "r" (i)				\
+		: "cc", "memory"					\
+	);								\
+									\
+	return old;							\
+}
+
+#define ATOMIC_OPS(op, asm) \
+	ATOMIC_FETCH_OP_RELAXED(op, asm) \
+	ATOMIC_OP_RETURN(op, asm)
+
+ATOMIC_OPS(and, and)
+#define atomic_and			atomic_and
+#define atomic_and_return_relaxed	atomic_and_return_relaxed
+#define atomic_fetch_and_relaxed	atomic_fetch_and_relaxed
+
+ATOMIC_OPS(add, add)
+#define atomic_add			atomic_add
+#define atomic_add_return_relaxed	atomic_add_return_relaxed
+#define atomic_fetch_add_relaxed	atomic_fetch_add_relaxed
+
+ATOMIC_OPS(xor, xor)
+#define atomic_xor			atomic_xor
+#define atomic_xor_return_relaxed	atomic_xor_return_relaxed
+#define atomic_fetch_xor_relaxed	atomic_fetch_xor_relaxed
+
+ATOMIC_OPS(or, or)
+#define atomic_or			atomic_or
+#define atomic_or_return_relaxed	atomic_or_return_relaxed
+#define atomic_fetch_or_relaxed		atomic_fetch_or_relaxed
+
+ATOMIC_OPS(sub, rsub)
+#define atomic_sub			atomic_sub
+#define atomic_sub_return_relaxed	atomic_sub_return_relaxed
+#define atomic_fetch_sub_relaxed	atomic_fetch_sub_relaxed
+
+static inline int atomic_inc_return_relaxed(atomic_t *v)
+{
+	int result, tmp;
+
+	__asm__ __volatile__ (
+		/* load conditional address in %2 to %0 */
+		"1:	lwx	%0, %2, r0;\n"
+		/* increment counter by 1 */
+		"	addi	%0, %0, 1;\n"
+		/* attempt store */
+		"	swx	%0, %2, r0;\n"
+		/* checking msr carry flag */
+		"	addic	%1, r0, 0;\n"
+		/* store failed (MSR[C] set)? try again */
+		"	bnei	%1, 1b;\n"
+		/* Outputs: result value */
+		: "=&r" (result), "=&r" (tmp)
+		/* Inputs: counter address */
+		: "r"   (&v->counter)
+		: "cc", "memory"
+	);
+
+	return result;
+}
+#define atomic_inc_return_relaxed	atomic_inc_return_relaxed
+
+#define atomic_inc_and_test(v)	(atomic_inc_return(v) == 0)
+
+static inline int atomic_dec_return(atomic_t *v)
+{
+	int result, tmp;
+
+	__asm__ __volatile__ (
+		/* load conditional address in %2 to %0 */
+		"1:	lwx	%0, %2, r0;\n"
+		/* increment counter by -1 */
+		"	addi	%0, %0, -1;\n"
+		/* attempt store */
+		"	swx	%0, %2, r0;\n"
+		/* checking msr carry flag */
+		"	addic	%1, r0, 0;\n"
+		/* store failed (MSR[C] set)? try again */
+		"	bnei	%1, 1b;\n"
+		/* Outputs: result value */
+		: "=&r" (result), "=&r" (tmp)
+		/* Inputs: counter address */
+		: "r"   (&v->counter)
+		: "cc", "memory"
+	);
+
+	return result;
+}
+#define atomic_dec_return	atomic_dec_return
+
+static inline void atomic_dec(atomic_t *v)
+{
+	atomic_dec_return(v);
+}
+#define atomic_dec	atomic_dec
+
+#define atomic_sub_and_test(a, v)	(atomic_sub_return((a), (v)) == 0)
+#define atomic_dec_and_test(v)		(atomic_dec_return((v)) == 0)
+
+#define atomic_cmpxchg(v, o, n)	(cmpxchg(&((v)->counter), (o), (n)))
+#define atomic_xchg(v, new)	(xchg(&((v)->counter), new))
+
+/**
+ * atomic_add_unless - add unless the number is a given value
+ * @v: pointer of type atomic_t
+ * @a: the amount to add to v...
+ * @u: ...unless v is equal to u.
+ *
+ * Atomically adds @a to @v, so long as it was not @u.
+ * Returns the old value of @v.
+ */
+static inline int __atomic_add_unless(atomic_t *v, int a, int u)
+{
+	int result, tmp;
+
+	__asm__ __volatile__ (
+		/* load conditional address in %2 to %0 */
+		"1: lwx	 %0, %2, r0;\n"
+		/* compare loaded value with old value*/
+		"   cmp   %1, %0, %3;\n"
+		/* equal to u, don't increment */
+		"   beqid %1, 2f;\n"
+		/* increment counter by i */
+		"   add   %1, %0, %4;\n"
+		/* attempt store of new value*/
+		"   swx   %1, %2, r0;\n"
+		/* checking msr carry flag */
+		"   addic %1, r0, 0;\n"
+		/* store failed (MSR[C] set)? try again */
+		"   bnei  %1, 1b;\n"
+		"2:"
+		/* Outputs: result value */
+		: "=&r" (result), "=&r" (tmp)
+		/* Inputs: counter address, old, new */
+		: "r"   (&v->counter), "r" (u), "r" (a)
+		: "cc", "memory"
+	);
+
+	return result;
+}
 
 /*
  * Atomically test *v and decrement if it is greater than 0.
- * The function returns the old value of *v minus 1.
+ * The function returns the old value of *v minus 1, even if
+ * the atomic variable, v, was not decremented.
  */
 static inline int atomic_dec_if_positive(atomic_t *v)
 {
-	unsigned long flags;
-	int res;
+	int result, tmp;
 
-	local_irq_save(flags);
-	res = v->counter - 1;
-	if (res >= 0)
-		v->counter = res;
-	local_irq_restore(flags);
+	__asm__ __volatile__ (
+		/* load conditional address in %2 to %0 */
+		"1:	lwx	%0, %2, r0;\n"
+		/* decrement counter by 1*/
+		"	addi	%0, %0, -1;\n"
+		/* if < 0 abort (*v was <= 0)*/
+		"	blti	%0, 2f;\n"
+		/* attempt store of new value*/
+		"	swx	%0, %2, r0;\n"
+		/* checking msr carry flag */
+		"	addic	%1, r0, 0;\n"
+		/* store failed (MSR[C] set)? try again */
+		"	bnei	%1, 1b;\n"
+		"2: "
+		/* Outputs: result value */
+		: "=&r" (result), "=&r" (tmp)
+		/* Inputs: counter address */
+		: "r"   (&v->counter)
+		: "cc", "memory"
+	);
 
-	return res;
+	return result;
 }
-#define atomic_dec_if_positive atomic_dec_if_positive
+#define atomic_dec_if_positive	atomic_dec_if_positive
+
+#define atomic_add_negative(i, v)	(atomic_add_return(i, v) < 0)
+
+#include <asm-generic/atomic64.h>
 
 #endif /* _ASM_MICROBLAZE_ATOMIC_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/barrier.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/barrier.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2015 - 2020 Xilinx, Inc. All rights reserved.
+ */
+
+#ifndef _ASM_MICROBLAZE_BARRIER_H
+#define _ASM_MICROBLAZE_BARRIER_H
+
+#define mb()	__asm__ __volatile__ ("mbar 1" : : : "memory")
+
+#include <asm-generic/barrier.h>
+
+#endif /* _ASM_MICROBLAZE_BARRIER_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/bitops.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/bitops.h
@@ -0,0 +1,189 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Microblaze atomic bit operations.
+ *
+ * Copyright (C) 2013 - 2020 Xilinx, Inc.
+ *
+ * Merged version by David Gibson <david@gibson.dropbear.id.au>.
+ * Based on ppc64 versions by: Dave Engebretsen, Todd Inglett, Don
+ * Reed, Pat McCarthy, Peter Bergner, Anton Blanchard.  They
+ * originally took it from the ppc32 code.
+ *
+ * Within a word, bits are numbered LSB first.  Lot's of places make
+ * this assumption by directly testing bits with (val & (1<<nr)).
+ * This can cause confusion for large (> 1 word) bitmaps on a
+ * big-endian system because, unlike little endian, the number of each
+ * bit depends on the word size.
+ *
+ * The bitop functions are defined to work on unsigned longs, so for a
+ * ppc64 system the bits end up numbered:
+ *   |63..............0|127............64|191...........128|255...........196|
+ * and on ppc32:
+ *   |31.....0|63....31|95....64|127...96|159..128|191..160|223..192|255..224|
+ *
+ * There are a few little-endian macros used mostly for filesystem
+ * bitmaps, these work on similar bit arrays layouts, but
+ * byte-oriented:
+ *   |7...0|15...8|23...16|31...24|39...32|47...40|55...48|63...56|
+ *
+ * The main difference is that bit 3-5 (64b) or 3-4 (32b) in the bit
+ * number field needs to be reversed compared to the big-endian bit
+ * fields. This can be achieved by XOR with 0x38 (64b) or 0x18 (32b).
+ */
+
+#ifndef _ASM_MICROBLAZE_BITOPS_H
+#define _ASM_MICROBLAZE_BITOPS_H
+
+#ifndef _LINUX_BITOPS_H
+#error only <linux/bitops.h> can be included directly
+#endif
+
+#include <asm/types.h>
+#include <linux/compiler.h>
+#include <asm/asm-compat.h>
+#include <linux/stringify.h>
+
+/*
+ * clear_bit doesn't imply a memory barrier
+ */
+#define smp_mb__before_clear_bit()	smp_mb()
+#define smp_mb__after_clear_bit()	smp_mb()
+
+#define BITOP_MASK(nr)		(1UL << ((nr) % BITS_PER_LONG))
+#define BITOP_WORD(nr)		((nr) / BITS_PER_LONG)
+
+/* Macro for generating the ***_bits() functions */
+#define DEFINE_BITOP(fn, op)						\
+static inline void fn(unsigned long mask, volatile unsigned long *_p)	\
+{									\
+	unsigned long tmp;						\
+	unsigned long *p = (unsigned long *)_p;				\
+									\
+	__asm__ __volatile__ (						\
+		/* load conditional address in %2 to %0 */		\
+		"1:	lwx		%0, %3, r0;\n"			\
+		/* perform bit operation with mask */			\
+		stringify_in_c(op)"	%0, %0, %2;\n"			\
+		/* attempt store */					\
+		"	swx		%0, %3, r0;\n"			\
+		/* checking msr carry flag */				\
+		"	addic		%0, r0, 0;\n"			\
+		/* store failed (MSR[C] set)? try again */		\
+		"	bnei		%0, 1b;\n"			\
+		: "=&r" (tmp), "+m" (*p)  /* Outputs: tmp, p */		\
+		: "r" (mask), "r" (p)     /* Inputs: mask, p */		\
+		: "cc", "memory"					\
+	);								\
+}
+
+DEFINE_BITOP(set_bits, or)
+DEFINE_BITOP(clear_bits, andn)
+DEFINE_BITOP(clear_bits_unlock, andn)
+DEFINE_BITOP(change_bits, xor)
+
+static inline void set_bit(int nr, volatile unsigned long *addr)
+{
+	set_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr));
+}
+
+static inline void clear_bit(int nr, volatile unsigned long *addr)
+{
+	clear_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr));
+}
+
+static inline void clear_bit_unlock(int nr, volatile unsigned long *addr)
+{
+	clear_bits_unlock(BITOP_MASK(nr), addr + BITOP_WORD(nr));
+}
+
+static inline void change_bit(int nr, volatile unsigned long *addr)
+{
+	change_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr));
+}
+
+/*
+ * Like DEFINE_BITOP(), with changes to the arguments to 'op' and the output
+ * operands.
+ */
+#define DEFINE_TESTOP(fn, op)						\
+static inline unsigned long fn(unsigned long mask,			\
+			       volatile unsigned long *_p)		\
+{									\
+	unsigned long old, tmp;						\
+	unsigned long *p = (unsigned long *)_p;				\
+									\
+	__asm__ __volatile__ (						\
+		/* load conditional address in %4 to %0 */		\
+		"1:	lwx		%0, %4, r0;\n"			\
+		/* perform bit operation with mask */			\
+		stringify_in_c(op)"	%1, %0, %3;\n"			\
+		/* attempt store */					\
+		"	swx		%1, %4, r0;\n"			\
+		/* checking msr carry flag */				\
+		"	addic		%1, r0, 0;\n"			\
+		/* store failed (MSR[C] set)? try again */		\
+		"	bnei		%1, 1b;\n"			\
+		/* Outputs: old, tmp, p */				\
+		: "=&r" (old), "=&r" (tmp), "+m" (*p)			\
+		 /* Inputs: mask, p */					\
+		: "r" (mask), "r" (p)					\
+		: "cc", "memory"					\
+	);								\
+	return (old & mask);						\
+}
+
+DEFINE_TESTOP(test_and_set_bits, or)
+DEFINE_TESTOP(test_and_set_bits_lock, or)
+DEFINE_TESTOP(test_and_clear_bits, andn)
+DEFINE_TESTOP(test_and_change_bits, xor)
+
+static inline int test_and_set_bit(unsigned long nr,
+				       volatile unsigned long *addr)
+{
+	return test_and_set_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr)) != 0;
+}
+
+static inline int test_and_set_bit_lock(unsigned long nr,
+				       volatile unsigned long *addr)
+{
+	return test_and_set_bits_lock(BITOP_MASK(nr),
+				addr + BITOP_WORD(nr)) != 0;
+}
+
+static inline int test_and_clear_bit(unsigned long nr,
+					 volatile unsigned long *addr)
+{
+	return test_and_clear_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr)) != 0;
+}
+
+static inline int test_and_change_bit(unsigned long nr,
+					  volatile unsigned long *addr)
+{
+	return test_and_change_bits(BITOP_MASK(nr), addr + BITOP_WORD(nr)) != 0;
+}
+
+#include <asm-generic/bitops/non-atomic.h>
+
+static inline void __clear_bit_unlock(int nr, volatile unsigned long *addr)
+{
+	__clear_bit(nr, addr);
+}
+
+#include <asm-generic/bitops/ffz.h>
+#include <asm-generic/bitops/__fls.h>
+#include <asm-generic/bitops/__ffs.h>
+#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/ffs.h>
+#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/find.h>
+#include <asm-generic/bitops/fls64.h>
+
+/* Little-endian versions */
+#include <asm-generic/bitops/le.h>
+
+/* Bitmap functions for the ext2 filesystem */
+#include <asm-generic/bitops/ext2-atomic-setbit.h>
+
+#include <asm-generic/bitops/sched.h>
+
+#endif /* _ASM_MICROBLAZE_BITOPS_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/cache.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/cache.h
@@ -1,13 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Cache operations
  *
  * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu>
  * Copyright (C) 2007-2009 PetaLogix
  * Copyright (C) 2003 John Williams <jwilliams@itee.uq.edu.au>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License. See the file COPYING in the main directory of this
- * archive for more details.
  */
 
 #ifndef _ASM_MICROBLAZE_CACHE_H
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/cacheflush.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/cacheflush.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu>
  * Copyright (C) 2007-2009 PetaLogix
@@ -5,11 +6,6 @@
  * based on v850 version which was
  * Copyright (C) 2001,02,03 NEC Electronics Corporation
  * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License. See the file COPYING in the main directory of this
- * archive for more details.
- *
  */
 
 #ifndef _ASM_MICROBLAZE_CACHEFLUSH_H
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/checksum.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/checksum.h
@@ -1,10 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2008 Michal Simek <monstr@monstr.eu>
  * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #ifndef _ASM_MICROBLAZE_CHECKSUM_H
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/cmpxchg.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/cmpxchg.h
@@ -2,42 +2,95 @@
 #ifndef _ASM_MICROBLAZE_CMPXCHG_H
 #define _ASM_MICROBLAZE_CMPXCHG_H
 
-#include <linux/irqflags.h>
+#ifndef CONFIG_SMP
+# include <asm-generic/cmpxchg.h>
+#else
 
-void __bad_xchg(volatile void *ptr, int size);
+extern void __xchg_called_with_bad_pointer(void);
+
+static inline unsigned long __xchg_u32(volatile void *p, unsigned long val)
+{
+	unsigned long prev, temp;
+
+	__asm__ __volatile__ (
+		/* load conditional address in %3 to %0 */
+		"1:	lwx	%0, %3, r0;\n"
+		/* attempt store of new value */
+		"	swx	%4, %3, r0;\n"
+		/* checking msr carry flag */
+		"	addic	%1, r0, 0;\n"
+		/* store failed (MSR[C] set)? try again */
+		"	bnei	%1, 1b;\n"
+		/* Outputs: result value */
+		: "=&r" (prev), "=&r" (temp), "+m" (*(volatile unsigned int *)p)
+		/* Inputs: counter address */
+		: "r"   (p), "r" (val)
+		: "cc", "memory"
+	);
+
+	return prev;
+}
 
 static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
 								int size)
 {
-	unsigned long ret;
-	unsigned long flags;
+	if (size == 4)
+		return __xchg_u32(ptr, x);
+
+	__xchg_called_with_bad_pointer();
+	return x;
+}
 
-	switch (size) {
-	case 1:
-		local_irq_save(flags);
-		ret = *(volatile unsigned char *)ptr;
-		*(volatile unsigned char *)ptr = x;
-		local_irq_restore(flags);
-		break;
-
-	case 4:
-		local_irq_save(flags);
-		ret = *(volatile unsigned long *)ptr;
-		*(volatile unsigned long *)ptr = x;
-		local_irq_restore(flags);
-		break;
-	default:
-		__bad_xchg(ptr, size), ret = 0;
-		break;
-	}
+#define xchg(ptr, x) ({							\
+	((__typeof__(*(ptr)))						\
+		__xchg((unsigned long)(x), (ptr), sizeof(*(ptr))));	\
+})
 
-	return ret;
+static inline unsigned long __cmpxchg_u32(volatile unsigned int *p,
+					  unsigned long old, unsigned long new)
+{
+	int result, tmp;
+
+	__asm__ __volatile__ (
+		/* load conditional address in %3 to %0 */
+		"1:	lwx	%0, %3, r0;\n"
+		/* compare loaded value with old value */
+		"	cmp	%2, %0, %4;\n"
+		/* not equal to old value, write old value */
+		"	bnei	%2, 2f;\n"
+		/* attempt store of new value*/
+		"	swx	%5, %3, r0;\n"
+		/* checking msr carry flag */
+		"	addic	%2, r0, 0;\n"
+		/* store failed (MSR[C] set)? try again */
+		"	bnei	%2, 1b;\n"
+		"2: "
+		/* Outputs : result value */
+		: "=&r" (result), "+m" (*p), "=&r" (tmp)
+		/* Inputs  : counter address, old, new */
+		: "r"   (p), "r" (old), "r" (new), "r" (&tmp)
+		: "cc", "memory"
+	);
+
+	return result;
 }
 
-#define xchg(ptr, x) \
-	((__typeof__(*(ptr))) __xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
+static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
+				      unsigned long new, unsigned int size)
+{
+	if (size == 4)
+		return __cmpxchg_u32(ptr, old, new);
+
+	__xchg_called_with_bad_pointer();
+	return old;
+}
+
+#define cmpxchg(ptr, o, n) ({						\
+	((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o),	\
+			(unsigned long)(n), sizeof(*(ptr))));		\
+})
+
 
-#include <asm-generic/cmpxchg.h>
-#include <asm-generic/cmpxchg-local.h>
+#endif
 
 #endif /* _ASM_MICROBLAZE_CMPXCHG_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/cpuinfo.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/cpuinfo.h
@@ -1,13 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Generic support for queying CPU info
  *
  * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu>
  * Copyright (C) 2007-2009 PetaLogix
  * Copyright (C) 2007 John Williams <jwilliams@itee.uq.edu.au>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License. See the file COPYING in the main directory of this
- * archive for more details.
  */
 
 #ifndef _ASM_MICROBLAZE_CPUINFO_H
@@ -87,7 +84,7 @@
 	u32 pvr_user2;
 };
 
-extern struct cpuinfo cpuinfo;
+DECLARE_PER_CPU(struct cpuinfo, cpu_info);
 
 /* fwd declarations of the various CPUinfo populators */
 void setup_cpuinfo(void);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/current.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/current.h
@@ -1,11 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
  * Copyright (C) 2008-2009 PetaLogix
  * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #ifndef _ASM_MICROBLAZE_CURRENT_H
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/delay.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/delay.h
@@ -1,10 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
- * include/asm-microblaze/delay.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
  * Copyright (C) 2008 Michal Simek
  * Copyright (C) 2007 John Williams
  * Copyright (C) 2006 Atmark Techno, Inc.
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/dma.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/dma.h
@@ -1,9 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #ifndef _ASM_MICROBLAZE_DMA_H
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/elf.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/elf.h
@@ -1,11 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
  * Copyright (C) 2008-2009 PetaLogix
  * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef _ASM_MICROBLAZE_ELF_H
 #define _ASM_MICROBLAZE_ELF_H
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/entry.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/entry.h
@@ -1,19 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Definitions used by low-level trap handlers
  *
  * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
  * Copyright (C) 2007-2009 PetaLogix
  * Copyright (C) 2007 John Williams <john.williams@petalogix.com>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License. See the file COPYING in the main directory of this
- * archive for more details.
  */
 
 #ifndef _ASM_MICROBLAZE_ENTRY_H
 #define _ASM_MICROBLAZE_ENTRY_H
 
-#include <asm/percpu.h>
 #include <asm/ptrace.h>
 #include <linux/linkage.h>
 
@@ -24,12 +20,23 @@
 
 #define PER_CPU(var) var
 
+#ifdef CONFIG_SMP
+/* Addresses in BRAM */
+#define CURRENT_SAVE_ADDR	0x50
+#define ENTRY_SP_ADDR		0x54
+#define PT_POOL_SPACE_ADDR	0x100
+#endif /* CONFIG_SMP */
+
 # ifndef __ASSEMBLY__
+#include <asm/percpu.h>
+
+#ifndef CONFIG_SMP
 DECLARE_PER_CPU(unsigned int, KSP); /* Saved kernel stack pointer */
 DECLARE_PER_CPU(unsigned int, KM); /* Kernel/user mode */
 DECLARE_PER_CPU(unsigned int, ENTRY_SP); /* Saved SP on kernel entry */
 DECLARE_PER_CPU(unsigned int, R11_SAVE); /* Temp variable for entry */
 DECLARE_PER_CPU(unsigned int, CURRENT_SAVE); /* Saved current pointer */
+#endif /* CONFIG_SMP */
 
 extern asmlinkage void do_notify_resume(struct pt_regs *regs, int in_syscall);
 # endif /* __ASSEMBLY__ */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/exceptions.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/exceptions.h
@@ -1,13 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Preliminary support for HW exception handing for Microblaze
  *
  * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
  * Copyright (C) 2008-2009 PetaLogix
  * Copyright (C) 2005 John Williams <jwilliams@itee.uq.edu.au>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License. See the file COPYING in the main directory of this
- * archive for more details.
  */
 
 #ifndef _ASM_MICROBLAZE_EXCEPTIONS_H
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/fixmap.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/fixmap.h
@@ -1,10 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * fixmap.h: compile-time virtual memory allocation
  *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
  * Copyright (C) 1998 Ingo Molnar
  *
  * Copyright 2008 Freescale Semiconductor Inc.
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/flat.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/flat.h
@@ -1,11 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * uClinux flat-format executables
  *
  * Copyright (C) 2005 John Williams <jwilliams@itee.uq.edu.au>
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License. See the file COPYING in the main directory of this
- * archive for more details.
  */
 
 #ifndef _ASM_MICROBLAZE_FLAT_H
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/hardirq.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/hardirq.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2020 Xilinx, Inc.
+ * Copyright (C) 2012 ARM Ltd.
+ */
+#ifndef _ASM_MICROBLAZE_HARDIRQ_H
+#define _ASM_MICROBLAZE_HARDIRQ_H
+
+# ifndef CONFIG_SMP
+#include <asm-generic/hardirq.h>
+# else
+#include <linux/cache.h>
+#include <linux/percpu.h>
+#include <linux/threads.h>
+#include <asm/irq.h>
+#include <linux/irq.h>
+
+typedef struct {
+	unsigned int __softirq_pending;
+	unsigned int ipi_irqs[MICROBLAZE_NUM_IPIS];
+} ____cacheline_aligned irq_cpustat_t;
+
+#include <linux/irq_cpustat.h>	/* Standard mappings for irq_cpustat_t above */
+
+#define __inc_irq_stat(cpu, member)	__IRQ_STAT(cpu, member)++
+#define __get_irq_stat(cpu, member)	__IRQ_STAT(cpu, member)
+
+u64 smp_irq_stat_cpu(unsigned int cpu);
+#define arch_irq_stat_cpu	smp_irq_stat_cpu
+
+extern unsigned long irq_err_count;
+
+static inline void ack_bad_irq(unsigned int irq)
+{
+	irq_err_count++;
+}
+# endif /* CONFIG_MMU */
+
+#endif /* _ASM_MICROBLAZE_HARDIRQ_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/io.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/io.h
@@ -1,11 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu>
  * Copyright (C) 2007-2009 PetaLogix
  * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #ifndef _ASM_MICROBLAZE_IO_H
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/irq.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/irq.h
@@ -1,21 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #ifndef _ASM_MICROBLAZE_IRQ_H
 #define _ASM_MICROBLAZE_IRQ_H
 
-#define NR_IRQS		(32 + 1)
 #include <asm-generic/irq.h>
 
 struct pt_regs;
 extern void do_IRQ(struct pt_regs *regs);
 
-/* should be defined in each interrupt controller driver */
-extern unsigned int xintc_get_irq(void);
-
 #endif /* _ASM_MICROBLAZE_IRQ_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/irqflags.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/irqflags.h
@@ -1,9 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #ifndef _ASM_MICROBLAZE_IRQFLAGS_H
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/mmu.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/mmu.h
@@ -1,11 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
  * Copyright (C) 2008-2009 PetaLogix
  * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #ifndef _ASM_MICROBLAZE_MMU_H
@@ -18,7 +15,10 @@
 #   ifndef __ASSEMBLY__
 
 /* Default "unsigned long" context */
-typedef unsigned long mm_context_t;
+typedef struct {
+	unsigned int	id;
+	unsigned int	active;
+} mm_context_t;
 
 /* Hardware Page Table Entry */
 typedef struct _PTE {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/mmu_context_mm.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/mmu_context_mm.h
@@ -1,11 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
+ * Copyright (C) 2013-2020 Xilinx, Inc
  * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
  * Copyright (C) 2008-2009 PetaLogix
  * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #ifndef _ASM_MICROBLAZE_MMU_CONTEXT_H
@@ -16,10 +14,13 @@
 #include <linux/sched.h>
 
 #include <asm/bitops.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
 #include <asm/mmu.h>
 #include <asm-generic/mm_hooks.h>
 
-# ifdef __KERNEL__
 /*
  * This function defines the mapping from contexts to VSIDs (virtual
  * segment IDs).  We use a skew on both the context and the high 4 bits
@@ -46,7 +47,7 @@
 
 /*
  * Set the current MMU context.
- * This is done byloading up the segment registers for the user part of the
+ * This is done by loading up the segment registers for the user part of the
  * address space.
  *
  * Since the PGD is immediately available, it is much faster to simply
@@ -54,75 +55,42 @@
  * can be used for debugging on all processors (if you happen to have
  * an Abatron).
  */
-extern void set_context(mm_context_t context, pgd_t *pgd);
-
-/*
- * Bitmap of contexts in use.
- * The size of this bitmap is LAST_CONTEXT + 1 bits.
- */
-extern unsigned long context_map[];
-
-/*
- * This caches the next context number that we expect to be free.
- * Its use is an optimization only, we can't rely on this context
- * number to be free, but it usually will be.
- */
-extern mm_context_t next_mmu_context;
+extern void set_context(unsigned long id, pgd_t *pgd);
 
 /*
  * Since we don't have sufficient contexts to give one to every task
  * that could be in the system, we need to be able to steal contexts.
- * These variables support that.
  */
-extern atomic_t nr_free_contexts;
-extern struct mm_struct *context_mm[LAST_CONTEXT+1];
 extern void steal_context(void);
 
 /*
- * Get a new mmu context for the address space described by `mm'.
+ * Set up the context for a new address space.
  */
-static inline void get_mmu_context(struct mm_struct *mm)
-{
-	mm_context_t ctx;
-
-	if (mm->context != NO_CONTEXT)
-		return;
-	while (atomic_dec_if_positive(&nr_free_contexts) < 0)
-		steal_context();
-	ctx = next_mmu_context;
-	while (test_and_set_bit(ctx, context_map)) {
-		ctx = find_next_zero_bit(context_map, LAST_CONTEXT+1, ctx);
-		if (ctx > LAST_CONTEXT)
-			ctx = 0;
-	}
-	next_mmu_context = (ctx + 1) & LAST_CONTEXT;
-	mm->context = ctx;
-	context_mm[ctx] = mm;
-}
+extern int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
 
 /*
- * Set up the context for a new address space.
+ * We're finished using the context for an address space.
  */
-# define init_new_context(tsk, mm)	(((mm)->context = NO_CONTEXT), 0)
+extern void destroy_context(struct mm_struct *mm);
 
 /*
- * We're finished using the context for an address space.
+ * Switch context
  */
-static inline void destroy_context(struct mm_struct *mm)
-{
-	if (mm->context != NO_CONTEXT) {
-		clear_bit(mm->context, context_map);
-		mm->context = NO_CONTEXT;
-		atomic_inc(&nr_free_contexts);
-	}
-}
+extern void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next);
 
 static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
 			     struct task_struct *tsk)
 {
+	/* Mark this context has been used on the new CPU */
+	cpumask_set_cpu(smp_processor_id(), mm_cpumask(next));
 	tsk->thread.pgdir = next->pgd;
-	get_mmu_context(next);
-	set_context(next->context, next->pgd);
+
+	/* Nothing else to do if we aren't actually switching */
+	if (prev == next)
+		return;
+
+	/* Out of line for now */
+	switch_mmu_context(prev, next);
 }
 
 /*
@@ -132,12 +100,13 @@
 static inline void activate_mm(struct mm_struct *active_mm,
 			struct mm_struct *mm)
 {
-	current->thread.pgdir = mm->pgd;
-	get_mmu_context(mm);
-	set_context(mm->context, mm->pgd);
+	unsigned long flags;
+
+	local_irq_save(flags);
+	switch_mm(active_mm, mm, current);
+	local_irq_restore(flags);
 }
 
 extern void mmu_context_init(void);
 
-# endif /* __KERNEL__ */
 #endif /* _ASM_MICROBLAZE_MMU_CONTEXT_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/module.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/module.h
@@ -1,9 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #ifndef _ASM_MICROBLAZE_MODULE_H
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/page.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/page.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * VM ops
  *
@@ -6,10 +7,6 @@
  * Copyright (C) 2006 Atmark Techno, Inc.
  * Changes for MMU support:
  *    Copyright (C) 2007 Xilinx, Inc.  All rights reserved.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #ifndef _ASM_MICROBLAZE_PAGE_H
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/pgalloc.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/pgalloc.h
@@ -1,11 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
  * Copyright (C) 2008-2009 PetaLogix
  * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #ifndef _ASM_MICROBLAZE_PGALLOC_H
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/pgtable.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/pgtable.h
@@ -1,11 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
  * Copyright (C) 2008-2009 PetaLogix
  * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #ifndef _ASM_MICROBLAZE_PGTABLE_H
@@ -397,20 +394,19 @@
 static inline unsigned long pte_update(pte_t *p, unsigned long clr,
 				unsigned long set)
 {
-	unsigned long flags, old, tmp;
-
-	raw_local_irq_save(flags);
+	unsigned long old, tmp;
 
-	__asm__ __volatile__(	"lw	%0, %2, r0	\n"
-				"andn	%1, %0, %3	\n"
-				"or	%1, %1, %4	\n"
-				"sw	%1, %2, r0	\n"
+	__asm__ __volatile__(
+			"1:	lwx	%0, %2, r0;\n"
+			"	andn	%1, %0, %3;\n"
+			"	or	%1, %1, %4;\n"
+			"	swx	%1, %2, r0;\n"
+			"	addic	%1, r0, 0;\n"
+			"	bnei	%1, 1b;\n"
 			: "=&r" (old), "=&r" (tmp)
 			: "r" ((unsigned long)(p + 1) - 4), "r" (clr), "r" (set)
 			: "cc");
 
-	raw_local_irq_restore(flags);
-
 	return old;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/processor.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/processor.h
@@ -1,11 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
  * Copyright (C) 2008-2009 PetaLogix
  * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #ifndef _ASM_MICROBLAZE_PROCESSOR_H
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/ptrace.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/ptrace.h
@@ -1,9 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef _ASM_MICROBLAZE_PTRACE_H
 #define _ASM_MICROBLAZE_PTRACE_H
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/pvr.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/pvr.h
@@ -1,13 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Support for the MicroBlaze PVR (Processor Version Register)
  *
  * Copyright (C) 2009 - 2011 Michal Simek <monstr@monstr.eu>
  * Copyright (C) 2007 John Williams <john.williams@petalogix.com>
  * Copyright (C) 2007 - 2011 PetaLogix
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License. See the file COPYING in the main directory of this
- * archive for more details.
  */
 
 #ifndef _ASM_MICROBLAZE_PVR_H
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/registers.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/registers.h
@@ -1,11 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
  * Copyright (C) 2008-2009 PetaLogix
  * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #ifndef _ASM_MICROBLAZE_REGISTERS_H
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/sections.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/sections.h
@@ -1,11 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
  * Copyright (C) 2008-2009 PetaLogix
  * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #ifndef _ASM_MICROBLAZE_SECTIONS_H
@@ -17,6 +14,9 @@
 extern char _ssbss[], _esbss[];
 extern unsigned long __ivt_start[], __ivt_end[];
 
+extern char __initramfs_end[];
+extern char _end_tlb_mapping[];
+
 extern u32 _fdt_start[], _fdt_end[];
 
 # endif /* !__ASSEMBLY__ */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/setup.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/setup.h
@@ -1,11 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu>
  * Copyright (C) 2007-2009 PetaLogix
  * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef _ASM_MICROBLAZE_SETUP_H
 #define _ASM_MICROBLAZE_SETUP_H
@@ -13,8 +10,6 @@
 #include <uapi/asm/setup.h>
 
 # ifndef __ASSEMBLY__
-extern unsigned int boot_cpuid; /* move to smp.h */
-
 extern char cmd_line[COMMAND_LINE_SIZE];
 
 extern char *klimit;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/smp.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/smp.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * smp.h: MicroBlaze-specific SMP code
+ *
+ * Original was a copy of PowerPC smp.h, which was a copy of
+ * sparc smp.h.  Now heavily modified for PPC.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996-2001 Cort Dougan <cort@fsmlabs.com>
+ * Copyright (C) 2013-2020 Xilinx, Inc.
+ */
+
+#ifndef _ASM_MICROBLAZE_SMP_H
+#define _ASM_MICROBLAZE_SMP_H
+
+#include <linux/threads.h>
+#include <linux/cpumask.h>
+#include <linux/kernel.h>
+
+#include <asm/percpu.h>
+
+void handle_IPI(int ipinr, struct pt_regs *regs);
+
+void set_smp_cross_call(void (*)(unsigned int, unsigned int));
+
+void smp_send_debugger_break(void);
+
+#define raw_smp_processor_id()		(current_thread_info()->cpu)
+
+enum microblaze_msg {
+	MICROBLAZE_MSG_RESCHEDULE = 0,
+	MICROBLAZE_MSG_CALL_FUNCTION,
+	MICROBLAZE_MSG_CALL_FUNCTION_SINGLE,
+	MICROBLAZE_MSG_DEBUGGER_BREAK,
+	MICROBLAZE_NUM_IPIS
+};
+
+void start_secondary(void);
+extern struct thread_info *secondary_ti;
+void secondary_machine_init(void);
+
+void arch_send_call_function_single_ipi(int cpu);
+void arch_send_call_function_ipi_mask(const struct cpumask *mask);
+
+#endif /* _ASM_MICROBLAZE_SMP_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/spinlock.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/spinlock.h
@@ -0,0 +1,240 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2013-2020 Xilinx, Inc.
+ */
+
+#ifndef _ASM_MICROBLAZE_SPINLOCK_H
+#define _ASM_MICROBLAZE_SPINLOCK_H
+
+/*
+ * Unlocked value: 0
+ * Locked value: 1
+ */
+#define arch_spin_is_locked(x)	(READ_ONCE((x)->lock) != 0)
+
+static inline void arch_spin_lock(arch_spinlock_t *lock)
+{
+	unsigned long tmp;
+
+	__asm__ __volatile__ (
+		/* load conditional address in %1 to %0 */
+		"1:	lwx	 %0, %1, r0;\n"
+		/* not zero? try again */
+		"	bnei	%0, 1b;\n"
+		/* increment lock by 1 */
+		"	addi	%0, r0, 1;\n"
+		/* attempt store */
+		"	swx	%0, %1, r0;\n"
+		/* checking msr carry flag */
+		"	addic	%0, r0, 0;\n"
+		/* store failed (MSR[C] set)? try again */
+		"	bnei	%0, 1b;\n"
+		/* Outputs: temp variable for load result */
+		: "=&r" (tmp)
+		/* Inputs: lock address */
+		: "r" (&lock->lock)
+		: "cc", "memory"
+	);
+}
+
+static inline int arch_spin_trylock(arch_spinlock_t *lock)
+{
+	unsigned long prev, tmp;
+
+	__asm__ __volatile__ (
+		/* load conditional address in %2 to %0 */
+		"1:	lwx	 %0, %2, r0;\n"
+		/* not zero? clear reservation */
+		"	bneid	%0, 2f;\n"
+		/* increment lock by one if lwx was sucessful */
+		"	addi	%1, r0, 1;\n"
+		/* attempt store */
+		"	swx	%1, %2, r0;\n"
+		/* checking msr carry flag */
+		"	addic	%1, r0, 0;\n"
+		/* store failed (MSR[C] set)? try again */
+		"	bnei	%1, 1b;\n"
+		"2:"
+		/* Outputs: temp variable for load result */
+		: "=&r" (prev), "=&r" (tmp)
+		/* Inputs: lock address */
+		: "r" (&lock->lock)
+		: "cc", "memory"
+	);
+
+	return (prev == 0);
+}
+
+static inline void arch_spin_unlock(arch_spinlock_t *lock)
+{
+	unsigned long tmp;
+
+	__asm__ __volatile__ (
+		/* load conditional address in %1 to %0 */
+		"1:	lwx	%0, %1, r0;\n"
+		/* clear */
+		"	swx	r0, %1, r0;\n"
+		/* checking msr carry flag */
+		"	addic	%0, r0, 0;\n"
+		/* store failed (MSR[C] set)? try again */
+		"	bnei	%0, 1b;\n"
+		/* Outputs: temp variable for load result */
+		: "=&r" (tmp)
+		/* Inputs: lock address */
+		: "r" (&lock->lock)
+		: "cc", "memory"
+	);
+}
+
+/* RWLOCKS */
+static inline void arch_write_lock(arch_rwlock_t *rw)
+{
+	unsigned long tmp;
+
+	__asm__ __volatile__ (
+		/* load conditional address in %1 to %0 */
+		"1:	lwx	 %0, %1, r0;\n"
+		/* not zero? try again */
+		"	bneid	%0, 1b;\n"
+		/* set tmp to -1 */
+		"	addi	%0, r0, -1;\n"
+		/* attempt store */
+		"	swx	%0, %1, r0;\n"
+		/* checking msr carry flag */
+		"	addic	%0, r0, 0;\n"
+		/* store failed (MSR[C] set)? try again */
+		"	bnei	%0, 1b;\n"
+		/* Outputs: temp variable for load result */
+		: "=&r" (tmp)
+		/* Inputs: lock address */
+		: "r" (&rw->lock)
+		: "cc", "memory"
+	);
+}
+
+static inline int arch_write_trylock(arch_rwlock_t *rw)
+{
+	unsigned long prev, tmp;
+
+	__asm__ __volatile__ (
+		/* load conditional address in %1 to tmp */
+		"1:	lwx	%0, %2, r0;\n"
+		/* not zero? abort */
+		"	bneid	%0, 2f;\n"
+		/* set tmp to -1 */
+		"	addi	%1, r0, -1;\n"
+		/* attempt store */
+		"	swx	%1, %2, r0;\n"
+		/* checking msr carry flag */
+		"	addic	%1, r0, 0;\n"
+		/* store failed (MSR[C] set)? try again */
+		"	bnei	%1, 1b;\n"
+		"2:"
+		/* Outputs: temp variable for load result */
+		: "=&r" (prev), "=&r" (tmp)
+		/* Inputs: lock address */
+		: "r" (&rw->lock)
+		: "cc", "memory"
+	);
+	/* prev value should be zero and MSR should be clear */
+	return (prev == 0);
+}
+
+static inline void arch_write_unlock(arch_rwlock_t *rw)
+{
+	unsigned long tmp;
+
+	__asm__ __volatile__ (
+		/* load conditional address in %1 to %0 */
+		"1:	lwx	%0, %1, r0;\n"
+		/* clear */
+		"	swx	r0, %1, r0;\n"
+		/* checking msr carry flag */
+		"	addic	%0, r0, 0;\n"
+		/* store failed (MSR[C] set)? try again */
+		"	bnei	%0, 1b;\n"
+		/* Outputs: temp variable for load result */
+		: "=&r" (tmp)
+		/* Inputs: lock address */
+		: "r" (&rw->lock)
+		: "cc", "memory"
+	);
+}
+
+/* Read locks */
+static inline void arch_read_lock(arch_rwlock_t *rw)
+{
+	unsigned long tmp;
+
+	__asm__ __volatile__ (
+		/* load conditional address in %1 to %0 */
+		"1:	lwx	%0, %1, r0;\n"
+		/* < 0 (WRITE LOCK active) try again */
+		"	bltid	%0, 1b;\n"
+		/* increment lock by 1 if lwx was sucessful */
+		"	addi	%0, %0, 1;\n"
+		/* attempt store */
+		"	swx	%0, %1, r0;\n"
+		/* checking msr carry flag */
+		"	addic	%0, r0, 0;\n"
+		/* store failed (MSR[C] set)? try again */
+		"	bnei	%0, 1b;\n"
+		/* Outputs: temp variable for load result */
+		: "=&r" (tmp)
+		/* Inputs: lock address */
+		: "r" (&rw->lock)
+		: "cc", "memory"
+	);
+}
+
+static inline void arch_read_unlock(arch_rwlock_t *rw)
+{
+	unsigned long tmp;
+
+	__asm__ __volatile__ (
+		/* load conditional address in %1 to tmp */
+		"1:	lwx	%0, %1, r0;\n"
+		/* tmp = tmp - 1 */
+		"	addi	%0, %0, -1;\n"
+		/* attempt store */
+		"	swx	%0, %1, r0;\n"
+		/* checking msr carry flag */
+		"	addic	%0, r0, 0;\n"
+		/* store failed (MSR[C] set)? try again */
+		"	bnei	%0, 1b;\n"
+		/* Outputs: temp variable for load result */
+		: "=&r" (tmp)
+		/* Inputs: lock address */
+		: "r" (&rw->lock)
+		: "cc", "memory"
+	);
+}
+
+static inline int arch_read_trylock(arch_rwlock_t *rw)
+{
+	unsigned long prev, tmp;
+
+	__asm__ __volatile__ (
+		/* load conditional address in %1 to %0 */
+		"1:	lwx	%0, %2, r0;\n"
+		/* < 0 bail, release lock */
+		"	bltid	%0, 2f;\n"
+		/* increment lock by 1 */
+		"	addi	%1, %0, 1;\n"
+		/* attempt store */
+		"	swx	%1, %2, r0;\n"
+		/* checking msr carry flag */
+		"	addic	%1, r0, 0;\n"
+		/* store failed (MSR[C] set)? try again */
+		"	bnei	%1, 1b;\n"
+		"2:"
+		/* Outputs: temp variable for load result */
+		: "=&r" (prev), "=&r" (tmp)
+		/* Inputs: lock address */
+		: "r" (&rw->lock)
+		: "cc", "memory"
+	);
+	return (prev >= 0);
+}
+
+#endif /* _ASM_MICROBLAZE_SPINLOCK_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/spinlock_types.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/spinlock_types.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2013-2020 Xilinx, Inc.
+ */
+
+#ifndef __ASM_MICROBLAZE_SPINLOCK_TYPES_H
+#define __ASM_MICROBLAZE_SPINLOCK_TYPES_H
+
+#ifndef __LINUX_SPINLOCK_TYPES_H
+# error "please don't include this file directly"
+#endif
+
+typedef struct {
+	volatile unsigned int lock;
+} arch_spinlock_t;
+
+#define __ARCH_SPIN_LOCK_UNLOCKED	{ 0 }
+
+typedef struct {
+	volatile signed int lock;
+} arch_rwlock_t;
+
+#define __ARCH_RW_LOCK_UNLOCKED		{ 0 }
+
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/string.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/string.h
@@ -1,9 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #ifndef _ASM_MICROBLAZE_STRING_H
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/switch_to.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/switch_to.h
@@ -1,9 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #ifndef _ASM_MICROBLAZE_SWITCH_TO_H
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/thread_info.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/thread_info.h
@@ -1,9 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #ifndef _ASM_MICROBLAZE_THREAD_INFO_H
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/timex.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/timex.h
@@ -1,9 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #ifndef _ASM_MICROBLAZE_TIMEX_H
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/tlbflush.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/tlbflush.h
@@ -1,11 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
  * Copyright (C) 2008-2009 PetaLogix
  * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #ifndef _ASM_MICROBLAZE_TLBFLUSH_H
@@ -20,6 +17,8 @@
 #include <asm/page.h>
 #include <asm/pgalloc.h>
 
+#define MMU_NO_CONTEXT		((unsigned int)-1)
+
 extern void _tlbie(unsigned long address);
 extern void _tlbia(void);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/uaccess.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/uaccess.h
@@ -1,11 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu>
  * Copyright (C) 2008-2009 PetaLogix
  * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #ifndef _ASM_MICROBLAZE_UACCESS_H
@@ -171,27 +168,27 @@
 
 #define __get_user(x, ptr)						\
 ({									\
-	unsigned long __gu_val = 0;					\
 	long __gu_err;							\
 	switch (sizeof(*(ptr))) {					\
 	case 1:								\
-		__get_user_asm("lbu", (ptr), __gu_val, __gu_err);	\
+		__get_user_asm("lbu", (ptr), x, __gu_err);		\
 		break;							\
 	case 2:								\
-		__get_user_asm("lhu", (ptr), __gu_val, __gu_err);	\
+		__get_user_asm("lhu", (ptr), x, __gu_err);		\
 		break;							\
 	case 4:								\
-		__get_user_asm("lw", (ptr), __gu_val, __gu_err);	\
+		__get_user_asm("lw", (ptr), x, __gu_err);		\
 		break;							\
-	case 8:								\
-		__gu_err = __copy_from_user(&__gu_val, ptr, 8);		\
-		if (__gu_err)						\
-			__gu_err = -EFAULT;				\
+	case 8: {							\
+		__u64 __x = 0;						\
+		__gu_err = raw_copy_from_user(&__x, ptr, 8) ?		\
+							-EFAULT : 0;	\
+		(x) = (typeof(x))(typeof((x) - (x)))__x;		\
 		break;							\
+	}								\
 	default:							\
 		/* __gu_val = 0; __gu_err = -EINVAL;*/ __gu_err = __user_bad();\
 	}								\
-	x = (__force __typeof__(*(ptr))) __gu_val;			\
 	__gu_err;							\
 })
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/unaligned.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/unaligned.h
@@ -1,10 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2008 Michal Simek <monstr@monstr.eu>
  * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #ifndef _ASM_MICROBLAZE_UNALIGNED_H
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/unistd.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/unistd.h
@@ -1,10 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) 2007-2008 Michal Simek <monstr@monstr.eu>
  * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 #ifndef _ASM_MICROBLAZE_UNISTD_H
 #define _ASM_MICROBLAZE_UNISTD_H
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/include/asm/unwind.h
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/include/asm/unwind.h
@@ -1,11 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Backtrace support for Microblaze
  *
  * Copyright (C) 2010  Digital Design Corporation
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
  */
 
 #ifndef __MICROBLAZE_UNWIND_H
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/kernel/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/kernel/Makefile
@@ -7,7 +7,6 @@
 # Do not trace early boot code and low level code
 CFLAGS_REMOVE_timer.o = -pg
 CFLAGS_REMOVE_intc.o = -pg
-CFLAGS_REMOVE_early_printk.o = -pg
 CFLAGS_REMOVE_ftrace.o = -pg
 CFLAGS_REMOVE_process.o = -pg
 endif
@@ -26,5 +25,6 @@
 obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
 obj-$(CONFIG_FUNCTION_TRACER)	+= ftrace.o mcount.o
 obj-$(CONFIG_KGDB)		+= kgdb.o
+obj-$(CONFIG_SMP)		+= smp.o
 
 obj-y	+= entry$(MMU).o
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/kernel/cpu/cache.c
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/kernel/cpu/cache.c
@@ -12,6 +12,7 @@
 
 #include <asm/cacheflush.h>
 #include <linux/cache.h>
+#include <linux/smp.h>
 #include <asm/cpuinfo.h>
 #include <asm/pvr.h>
 
@@ -92,7 +93,8 @@
 #define CACHE_LOOP_LIMITS(start, end, cache_line_length, cache_size)	\
 do {									\
 	int align = ~(cache_line_length - 1);				\
-	end = min(start + cache_size, end);				\
+	if (start <  UINT_MAX - cache_size)				\
+		end = min(start + cache_size, end);			\
 	start &= align;							\
 } while (0)
 
@@ -157,6 +159,8 @@
 
 static void __flush_icache_range_msr_irq(unsigned long start, unsigned long end)
 {
+	unsigned int cpu = smp_processor_id();
+	struct cpuinfo *cpuinfo = per_cpu_ptr(&cpu_info, cpu);
 	unsigned long flags;
 #ifndef ASM_LOOP
 	int i;
@@ -165,15 +169,15 @@
 				(unsigned int)start, (unsigned int) end);
 
 	CACHE_LOOP_LIMITS(start, end,
-			cpuinfo.icache_line_length, cpuinfo.icache_size);
+			cpuinfo->icache_line_length, cpuinfo->icache_size);
 
 	local_irq_save(flags);
 	__disable_icache_msr();
 
 #ifdef ASM_LOOP
-	CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic);
+	CACHE_RANGE_LOOP_1(start, end, cpuinfo->icache_line_length, wic);
 #else
-	for (i = start; i < end; i += cpuinfo.icache_line_length)
+	for (i = start; i < end; i += cpuinfo->icache_line_length)
 		__asm__ __volatile__ ("wic	%0, r0;"	\
 				: : "r" (i));
 #endif
@@ -184,6 +188,8 @@
 static void __flush_icache_range_nomsr_irq(unsigned long start,
 				unsigned long end)
 {
+	unsigned int cpu = smp_processor_id();
+	struct cpuinfo *cpuinfo = per_cpu_ptr(&cpu_info, cpu);
 	unsigned long flags;
 #ifndef ASM_LOOP
 	int i;
@@ -192,15 +198,15 @@
 				(unsigned int)start, (unsigned int) end);
 
 	CACHE_LOOP_LIMITS(start, end,
-			cpuinfo.icache_line_length, cpuinfo.icache_size);
+			cpuinfo->icache_line_length, cpuinfo->icache_size);
 
 	local_irq_save(flags);
 	__disable_icache_nomsr();
 
 #ifdef ASM_LOOP
-	CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic);
+	CACHE_RANGE_LOOP_1(start, end, cpuinfo->icache_line_length, wic);
 #else
-	for (i = start; i < end; i += cpuinfo.icache_line_length)
+	for (i = start; i < end; i += cpuinfo->icache_line_length)
 		__asm__ __volatile__ ("wic	%0, r0;"	\
 				: : "r" (i));
 #endif
@@ -212,6 +218,8 @@
 static void __flush_icache_range_noirq(unsigned long start,
 				unsigned long end)
 {
+	unsigned int cpu = smp_processor_id();
+	struct cpuinfo *cpuinfo = per_cpu_ptr(&cpu_info, cpu);
 #ifndef ASM_LOOP
 	int i;
 #endif
@@ -219,11 +227,11 @@
 				(unsigned int)start, (unsigned int) end);
 
 	CACHE_LOOP_LIMITS(start, end,
-			cpuinfo.icache_line_length, cpuinfo.icache_size);
+			cpuinfo->icache_line_length, cpuinfo->icache_size);
 #ifdef ASM_LOOP
-	CACHE_RANGE_LOOP_1(start, end, cpuinfo.icache_line_length, wic);
+	CACHE_RANGE_LOOP_1(start, end, cpuinfo->icache_line_length, wic);
 #else
-	for (i = start; i < end; i += cpuinfo.icache_line_length)
+	for (i = start; i < end; i += cpuinfo->icache_line_length)
 		__asm__ __volatile__ ("wic	%0, r0;"	\
 				: : "r" (i));
 #endif
@@ -231,6 +239,8 @@
 
 static void __flush_icache_all_msr_irq(void)
 {
+	unsigned int cpu = smp_processor_id();
+	struct cpuinfo *cpuinfo = per_cpu_ptr(&cpu_info, cpu);
 	unsigned long flags;
 #ifndef ASM_LOOP
 	int i;
@@ -240,11 +250,10 @@
 	local_irq_save(flags);
 	__disable_icache_msr();
 #ifdef ASM_LOOP
-	CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic);
+	CACHE_ALL_LOOP(cpuinfo->icache_size, cpuinfo->icache_line_length, wic);
 #else
-	for (i = 0; i < cpuinfo.icache_size;
-		 i += cpuinfo.icache_line_length)
-			__asm__ __volatile__ ("wic	%0, r0;" \
+	for (i = 0; i < cpuinfo->icache_size; i += cpuinfo->icache_line_length)
+		__asm__ __volatile__ ("wic	%0, r0;" \
 					: : "r" (i));
 #endif
 	__enable_icache_msr();
@@ -253,6 +262,8 @@
 
 static void __flush_icache_all_nomsr_irq(void)
 {
+	unsigned int cpu = smp_processor_id();
+	struct cpuinfo *cpuinfo = per_cpu_ptr(&cpu_info, cpu);
 	unsigned long flags;
 #ifndef ASM_LOOP
 	int i;
@@ -262,11 +273,10 @@
 	local_irq_save(flags);
 	__disable_icache_nomsr();
 #ifdef ASM_LOOP
-	CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic);
+	CACHE_ALL_LOOP(cpuinfo->icache_size, cpuinfo->icache_line_length, wic);
 #else
-	for (i = 0; i < cpuinfo.icache_size;
-		 i += cpuinfo.icache_line_length)
-			__asm__ __volatile__ ("wic	%0, r0;" \
+	for (i = 0; i < cpuinfo->icache_size; i += cpuinfo->icache_line_length)
+		__asm__ __volatile__ ("wic	%0, r0;" \
 					: : "r" (i));
 #endif
 	__enable_icache_nomsr();
@@ -275,22 +285,25 @@
 
 static void __flush_icache_all_noirq(void)
 {
+	unsigned int cpu = smp_processor_id();
+	struct cpuinfo *cpuinfo = per_cpu_ptr(&cpu_info, cpu);
 #ifndef ASM_LOOP
 	int i;
 #endif
 	pr_debug("%s\n", __func__);
 #ifdef ASM_LOOP
-	CACHE_ALL_LOOP(cpuinfo.icache_size, cpuinfo.icache_line_length, wic);
+	CACHE_ALL_LOOP(cpuinfo->icache_size, cpuinfo->icache_line_length, wic);
 #else
-	for (i = 0; i < cpuinfo.icache_size;
-		 i += cpuinfo.icache_line_length)
-			__asm__ __volatile__ ("wic	%0, r0;" \
+	for (i = 0; i < cpuinfo->icache_size; i += cpuinfo->icache_line_length)
+		__asm__ __volatile__ ("wic	%0, r0;" \
 					: : "r" (i));
 #endif
 }
 
 static void __invalidate_dcache_all_msr_irq(void)
 {
+	unsigned int cpu = smp_processor_id();
+	struct cpuinfo *cpuinfo = per_cpu_ptr(&cpu_info, cpu);
 	unsigned long flags;
 #ifndef ASM_LOOP
 	int i;
@@ -300,11 +313,10 @@
 	local_irq_save(flags);
 	__disable_dcache_msr();
 #ifdef ASM_LOOP
-	CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc);
+	CACHE_ALL_LOOP(cpuinfo->dcache_size, cpuinfo->dcache_line_length, wdc);
 #else
-	for (i = 0; i < cpuinfo.dcache_size;
-		 i += cpuinfo.dcache_line_length)
-			__asm__ __volatile__ ("wdc	%0, r0;" \
+	for (i = 0; i < cpuinfo->dcache_size; i += cpuinfo->dcache_line_length)
+		__asm__ __volatile__ ("wdc	%0, r0;" \
 					: : "r" (i));
 #endif
 	__enable_dcache_msr();
@@ -313,6 +325,8 @@
 
 static void __invalidate_dcache_all_nomsr_irq(void)
 {
+	unsigned int cpu = smp_processor_id();
+	struct cpuinfo *cpuinfo = per_cpu_ptr(&cpu_info, cpu);
 	unsigned long flags;
 #ifndef ASM_LOOP
 	int i;
@@ -322,11 +336,10 @@
 	local_irq_save(flags);
 	__disable_dcache_nomsr();
 #ifdef ASM_LOOP
-	CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc);
+	CACHE_ALL_LOOP(cpuinfo->dcache_size, cpuinfo->dcache_line_length, wdc);
 #else
-	for (i = 0; i < cpuinfo.dcache_size;
-		 i += cpuinfo.dcache_line_length)
-			__asm__ __volatile__ ("wdc	%0, r0;" \
+	for (i = 0; i < cpuinfo->dcache_size; i += cpuinfo->dcache_line_length)
+		__asm__ __volatile__ ("wdc	%0, r0;" \
 					: : "r" (i));
 #endif
 	__enable_dcache_nomsr();
@@ -335,16 +348,17 @@
 
 static void __invalidate_dcache_all_noirq_wt(void)
 {
+	unsigned int cpu = smp_processor_id();
+	struct cpuinfo *cpuinfo = per_cpu_ptr(&cpu_info, cpu);
 #ifndef ASM_LOOP
 	int i;
 #endif
 	pr_debug("%s\n", __func__);
 #ifdef ASM_LOOP
-	CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length, wdc);
+	CACHE_ALL_LOOP(cpuinfo->dcache_size, cpuinfo->dcache_line_length, wdc);
 #else
-	for (i = 0; i < cpuinfo.dcache_size;
-		 i += cpuinfo.dcache_line_length)
-			__asm__ __volatile__ ("wdc	%0, r0;" \
+	for (i = 0; i < cpuinfo->dcache_size; i += cpuinfo->dcache_line_length)
+		__asm__ __volatile__ ("wdc	%0, r0;" \
 					: : "r" (i));
 #endif
 }
@@ -358,17 +372,18 @@
  */
 static void __invalidate_dcache_all_wb(void)
 {
+	unsigned int cpu = smp_processor_id();
+	struct cpuinfo *cpuinfo = per_cpu_ptr(&cpu_info, cpu);
 #ifndef ASM_LOOP
 	int i;
 #endif
 	pr_debug("%s\n", __func__);
 #ifdef ASM_LOOP
-	CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length,
+	CACHE_ALL_LOOP(cpuinfo->dcache_size, cpuinfo->dcache_line_length,
 					wdc);
 #else
-	for (i = 0; i < cpuinfo.dcache_size;
-		 i += cpuinfo.dcache_line_length)
-			__asm__ __volatile__ ("wdc	%0, r0;" \
+	for (i = 0; i < cpuinfo->dcache_size; i += cpuinfo->dcache_line_length)
+		__asm__ __volatile__ ("wdc	%0, r0;" \
 					: : "r" (i));
 #endif
 }
@@ -376,6 +391,8 @@
 static void __invalidate_dcache_range_wb(unsigned long start,
 						unsigned long end)
 {
+	unsigned int cpu = smp_processor_id();
+	struct cpuinfo *cpuinfo = per_cpu_ptr(&cpu_info, cpu);
 #ifndef ASM_LOOP
 	int i;
 #endif
@@ -383,11 +400,11 @@
 				(unsigned int)start, (unsigned int) end);
 
 	CACHE_LOOP_LIMITS(start, end,
-			cpuinfo.dcache_line_length, cpuinfo.dcache_size);
+			cpuinfo->dcache_line_length, cpuinfo->dcache_size);
 #ifdef ASM_LOOP
-	CACHE_RANGE_LOOP_2(start, end, cpuinfo.dcache_line_length, wdc.clear);
+	CACHE_RANGE_LOOP_2(start, end, cpuinfo->dcache_line_length, wdc.clear);
 #else
-	for (i = start; i < end; i += cpuinfo.dcache_line_length)
+	for (i = start; i < end; i += cpuinfo->dcache_line_length)
 		__asm__ __volatile__ ("wdc.clear	%0, r0;"	\
 				: : "r" (i));
 #endif
@@ -396,18 +413,20 @@
 static void __invalidate_dcache_range_nomsr_wt(unsigned long start,
 							unsigned long end)
 {
+	unsigned int cpu = smp_processor_id();
+	struct cpuinfo *cpuinfo = per_cpu_ptr(&cpu_info, cpu);
 #ifndef ASM_LOOP
 	int i;
 #endif
 	pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
 				(unsigned int)start, (unsigned int) end);
 	CACHE_LOOP_LIMITS(start, end,
-			cpuinfo.dcache_line_length, cpuinfo.dcache_size);
+			cpuinfo->dcache_line_length, cpuinfo->dcache_size);
 
 #ifdef ASM_LOOP
-	CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc);
+	CACHE_RANGE_LOOP_1(start, end, cpuinfo->dcache_line_length, wdc);
 #else
-	for (i = start; i < end; i += cpuinfo.dcache_line_length)
+	for (i = start; i < end; i += cpuinfo->dcache_line_length)
 		__asm__ __volatile__ ("wdc	%0, r0;"	\
 				: : "r" (i));
 #endif
@@ -416,6 +435,8 @@
 static void __invalidate_dcache_range_msr_irq_wt(unsigned long start,
 							unsigned long end)
 {
+	unsigned int cpu = smp_processor_id();
+	struct cpuinfo *cpuinfo = per_cpu_ptr(&cpu_info, cpu);
 	unsigned long flags;
 #ifndef ASM_LOOP
 	int i;
@@ -423,15 +444,15 @@
 	pr_debug("%s: start 0x%x, end 0x%x\n", __func__,
 				(unsigned int)start, (unsigned int) end);
 	CACHE_LOOP_LIMITS(start, end,
-			cpuinfo.dcache_line_length, cpuinfo.dcache_size);
+			cpuinfo->dcache_line_length, cpuinfo->dcache_size);
 
 	local_irq_save(flags);
 	__disable_dcache_msr();
 
 #ifdef ASM_LOOP
-	CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc);
+	CACHE_RANGE_LOOP_1(start, end, cpuinfo->dcache_line_length, wdc);
 #else
-	for (i = start; i < end; i += cpuinfo.dcache_line_length)
+	for (i = start; i < end; i += cpuinfo->dcache_line_length)
 		__asm__ __volatile__ ("wdc	%0, r0;"	\
 				: : "r" (i));
 #endif
@@ -443,6 +464,8 @@
 static void __invalidate_dcache_range_nomsr_irq(unsigned long start,
 							unsigned long end)
 {
+	unsigned int cpu = smp_processor_id();
+	struct cpuinfo *cpuinfo = per_cpu_ptr(&cpu_info, cpu);
 	unsigned long flags;
 #ifndef ASM_LOOP
 	int i;
@@ -451,15 +474,15 @@
 				(unsigned int)start, (unsigned int) end);
 
 	CACHE_LOOP_LIMITS(start, end,
-			cpuinfo.dcache_line_length, cpuinfo.dcache_size);
+			cpuinfo->dcache_line_length, cpuinfo->dcache_size);
 
 	local_irq_save(flags);
 	__disable_dcache_nomsr();
 
 #ifdef ASM_LOOP
-	CACHE_RANGE_LOOP_1(start, end, cpuinfo.dcache_line_length, wdc);
+	CACHE_RANGE_LOOP_1(start, end, cpuinfo->dcache_line_length, wdc);
 #else
-	for (i = start; i < end; i += cpuinfo.dcache_line_length)
+	for (i = start; i < end; i += cpuinfo->dcache_line_length)
 		__asm__ __volatile__ ("wdc	%0, r0;"	\
 				: : "r" (i));
 #endif
@@ -470,23 +493,26 @@
 
 static void __flush_dcache_all_wb(void)
 {
+	unsigned int cpu = smp_processor_id();
+	struct cpuinfo *cpuinfo = per_cpu_ptr(&cpu_info, cpu);
 #ifndef ASM_LOOP
 	int i;
 #endif
 	pr_debug("%s\n", __func__);
 #ifdef ASM_LOOP
-	CACHE_ALL_LOOP(cpuinfo.dcache_size, cpuinfo.dcache_line_length,
+	CACHE_ALL_LOOP(cpuinfo->dcache_size, cpuinfo->dcache_line_length,
 				wdc.flush);
 #else
-	for (i = 0; i < cpuinfo.dcache_size;
-		 i += cpuinfo.dcache_line_length)
-			__asm__ __volatile__ ("wdc.flush	%0, r0;" \
+	for (i = 0; i < cpuinfo->dcache_size; i += cpuinfo->dcache_line_length)
+		__asm__ __volatile__ ("wdc.flush	%0, r0;" \
 					: : "r" (i));
 #endif
 }
 
 static void __flush_dcache_range_wb(unsigned long start, unsigned long end)
 {
+	unsigned int cpu = smp_processor_id();
+	struct cpuinfo *cpuinfo = per_cpu_ptr(&cpu_info, cpu);
 #ifndef ASM_LOOP
 	int i;
 #endif
@@ -494,11 +520,11 @@
 				(unsigned int)start, (unsigned int) end);
 
 	CACHE_LOOP_LIMITS(start, end,
-			cpuinfo.dcache_line_length, cpuinfo.dcache_size);
+			cpuinfo->dcache_line_length, cpuinfo->dcache_size);
 #ifdef ASM_LOOP
-	CACHE_RANGE_LOOP_2(start, end, cpuinfo.dcache_line_length, wdc.flush);
+	CACHE_RANGE_LOOP_2(start, end, cpuinfo->dcache_line_length, wdc.flush);
 #else
-	for (i = start; i < end; i += cpuinfo.dcache_line_length)
+	for (i = start; i < end; i += cpuinfo->dcache_line_length)
 		__asm__ __volatile__ ("wdc.flush	%0, r0;"	\
 				: : "r" (i));
 #endif
@@ -607,16 +633,19 @@
 
 void microblaze_cache_init(void)
 {
-	if (cpuinfo.use_instr & PVR2_USE_MSR_INSTR) {
-		if (cpuinfo.dcache_wb) {
+	unsigned int cpu = smp_processor_id();
+	struct cpuinfo *cpuinfo = per_cpu_ptr(&cpu_info, cpu);
+
+	if (cpuinfo->use_instr & PVR2_USE_MSR_INSTR) {
+		if (cpuinfo->dcache_wb) {
 			pr_info("wb_msr\n");
 			mbc = (struct scache *)&wb_msr;
-			if (cpuinfo.ver_code <= CPUVER_7_20_D) {
+			if (cpuinfo->ver_code <= CPUVER_7_20_D) {
 				/* MS: problem with signal handling - hw bug */
 				pr_info("WB won't work properly\n");
 			}
 		} else {
-			if (cpuinfo.ver_code >= CPUVER_7_20_A) {
+			if (cpuinfo->ver_code >= CPUVER_7_20_A) {
 				pr_info("wt_msr_noirq\n");
 				mbc = (struct scache *)&wt_msr_noirq;
 			} else {
@@ -625,15 +654,15 @@
 			}
 		}
 	} else {
-		if (cpuinfo.dcache_wb) {
+		if (cpuinfo->dcache_wb) {
 			pr_info("wb_nomsr\n");
 			mbc = (struct scache *)&wb_nomsr;
-			if (cpuinfo.ver_code <= CPUVER_7_20_D) {
+			if (cpuinfo->ver_code <= CPUVER_7_20_D) {
 				/* MS: problem with signal handling - hw bug */
 				pr_info("WB won't work properly\n");
 			}
 		} else {
-			if (cpuinfo.ver_code >= CPUVER_7_20_A) {
+			if (cpuinfo->ver_code >= CPUVER_7_20_A) {
 				pr_info("wt_nomsr_noirq\n");
 				mbc = (struct scache *)&wt_nomsr_noirq;
 			} else {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c
@@ -22,13 +22,8 @@
 
 #define CI(c, p) { ci->c = PVR_##p(pvr); }
 
-#if defined(CONFIG_EARLY_PRINTK) && defined(CONFIG_SERIAL_UARTLITE_CONSOLE)
 #define err_printk(x) \
-	early_printk("ERROR: Microblaze " x "-different for PVR and DTS\n");
-#else
-#define err_printk(x) \
-	pr_info("ERROR: Microblaze " x "-different for PVR and DTS\n");
-#endif
+	pr_err("ERROR: Microblaze " x "-different for PVR and DTS\n");
 
 void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/kernel/cpu/cpuinfo-static.c
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/kernel/cpu/cpuinfo-static.c
@@ -18,7 +18,7 @@
 static const char cpu_ver_string[] = CONFIG_XILINX_MICROBLAZE0_HW_VER;
 
 #define err_printk(x) \
-	early_printk("ERROR: Microblaze " x "-different for kernel and DTS\n");
+	pr_err("ERROR: Microblaze " x "-different for kernel and DTS\n");
 
 void __init set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/kernel/cpu/cpuinfo.c
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/kernel/cpu/cpuinfo.c
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2013-2020 Xilinx, Inc. All rights reserved.
  * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu>
  * Copyright (C) 2007-2009 PetaLogix
  * Copyright (C) 2007 John Williams <john.williams@petalogix.com>
@@ -10,6 +11,7 @@
 
 #include <linux/clk.h>
 #include <linux/init.h>
+#include <linux/smp.h>
 #include <asm/cpuinfo.h>
 #include <asm/pvr.h>
 
@@ -51,11 +53,12 @@
 	{"9.5", 0x22},
 	{"9.6", 0x23},
 	{"10.0", 0x24},
+	{"11.0", 0x25},
 	{NULL, 0},
 };
 
 /*
- * FIXME Not sure if the actual key is defined by Xilinx in the PVR
+ * The actual key is defined by Xilinx in the PVR
  */
 const struct family_string_key family_string_lookup[] = {
 	{"virtex2", 0x4},
@@ -84,37 +87,40 @@
 	{NULL, 0},
 };
 
-struct cpuinfo cpuinfo;
-static struct device_node *cpu;
+DEFINE_PER_CPU(struct cpuinfo, cpu_info);
 
 void __init setup_cpuinfo(void)
 {
-	cpu = of_get_cpu_node(0, NULL);
+	struct device_node *cpu;
+	unsigned int cpu_id = smp_processor_id();
+	struct cpuinfo *cpuinfo = per_cpu_ptr(&cpu_info, cpu_id);
+
+	cpu = of_get_cpu_node(cpu_id, NULL);
 	if (!cpu)
 		pr_err("You don't have cpu or are missing cpu reg property!!!\n");
 
-	pr_info("%s: initialising\n", __func__);
+	pr_info("%s: initialising cpu %d\n", __func__, cpu_id);
 
 	switch (cpu_has_pvr()) {
 	case 0:
 		pr_warn("%s: No PVR support. Using static CPU info from FDT\n",
 			__func__);
-		set_cpuinfo_static(&cpuinfo, cpu);
+		set_cpuinfo_static(cpuinfo, cpu);
 		break;
 /* FIXME I found weird behavior with MB 7.00.a/b 7.10.a
  * please do not use FULL PVR with MMU */
 	case 1:
 		pr_info("%s: Using full CPU PVR support\n",
 			__func__);
-		set_cpuinfo_static(&cpuinfo, cpu);
-		set_cpuinfo_pvr_full(&cpuinfo, cpu);
+		set_cpuinfo_static(cpuinfo, cpu);
+		set_cpuinfo_pvr_full(cpuinfo, cpu);
 		break;
 	default:
 		pr_warn("%s: Unsupported PVR setting\n", __func__);
-		set_cpuinfo_static(&cpuinfo, cpu);
+		set_cpuinfo_static(cpuinfo, cpu);
 	}
 
-	if (cpuinfo.mmu_privins)
+	if (cpuinfo->mmu_privins)
 		pr_warn("%s: Stream instructions enabled"
 			" - USERSPACE CAN LOCK THIS KERNEL!\n", __func__);
 
@@ -124,17 +130,24 @@
 void __init setup_cpuinfo_clk(void)
 {
 	struct clk *clk;
+	struct device_node *cpu;
+	unsigned int cpu_id = smp_processor_id();
+	struct cpuinfo *cpuinfo = per_cpu_ptr(&cpu_info, cpu_id);
+
+	cpu = of_get_cpu_node(cpu_id, NULL);
+	if (!cpu)
+		pr_err("You don't have cpu or are missing cpu reg property!!!\n");
 
 	clk = of_clk_get(cpu, 0);
 	if (IS_ERR(clk)) {
 		pr_err("ERROR: CPU CCF input clock not found\n");
 		/* take timebase-frequency from DTS */
-		cpuinfo.cpu_clock_freq = fcpu(cpu, "timebase-frequency");
+		cpuinfo->cpu_clock_freq = fcpu(cpu, "timebase-frequency");
 	} else {
-		cpuinfo.cpu_clock_freq = clk_get_rate(clk);
+		cpuinfo->cpu_clock_freq = clk_get_rate(clk);
 	}
 
-	if (!cpuinfo.cpu_clock_freq) {
+	if (!cpuinfo->cpu_clock_freq) {
 		pr_err("ERROR: CPU clock frequency not setup\n");
 		BUG();
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/kernel/cpu/mb.c
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/kernel/cpu/mb.c
@@ -1,6 +1,7 @@
 /*
  * CPU-version specific code
  *
+ * Copyright (C) 2013-2020 Xilinx, Inc. All rights reserved
  * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu>
  * Copyright (C) 2006-2009 PetaLogix
  *
@@ -27,117 +28,135 @@
 
 static int show_cpuinfo(struct seq_file *m, void *v)
 {
-	char *fpga_family = "Unknown";
-	char *cpu_ver = "Unknown";
-	int i;
-
-	/* Denormalised to get the fpga family string */
-	for (i = 0; family_string_lookup[i].s != NULL; i++) {
-		if (cpuinfo.fpga_family_code == family_string_lookup[i].k) {
-			fpga_family = (char *)family_string_lookup[i].s;
-			break;
+	unsigned int cpu;
+
+	for_each_online_cpu(cpu) {
+		struct cpuinfo *cpuinfo = per_cpu_ptr(&cpu_info, cpu);
+		char *fpga_family = "Unknown";
+		char *cpu_ver = "Unknown";
+		int i;
+
+		/* Denormalised to get the fpga family string */
+		for (i = 0; family_string_lookup[i].s != NULL; i++) {
+			if (cpuinfo->fpga_family_code ==
+			    family_string_lookup[i].k) {
+				fpga_family = (char *)family_string_lookup[i].s;
+				break;
+			}
 		}
-	}
 
-	/* Denormalised to get the hw version string */
-	for (i = 0; cpu_ver_lookup[i].s != NULL; i++) {
-		if (cpuinfo.ver_code == cpu_ver_lookup[i].k) {
-			cpu_ver = (char *)cpu_ver_lookup[i].s;
-			break;
+		/* Denormalised to get the hw version string */
+		for (i = 0; cpu_ver_lookup[i].s != NULL; i++) {
+			if (cpuinfo->ver_code == cpu_ver_lookup[i].k) {
+				cpu_ver = (char *)cpu_ver_lookup[i].s;
+				break;
+			}
 		}
-	}
 
-	seq_printf(m,
-		   "CPU-Family:	MicroBlaze\n"
-		   "FPGA-Arch:	%s\n"
-		   "CPU-Ver:	%s, %s endian\n"
-		   "CPU-MHz:	%d.%02d\n"
-		   "BogoMips:	%lu.%02lu\n",
-		   fpga_family,
-		   cpu_ver,
-		   cpuinfo.endian ? "little" : "big",
-		   cpuinfo.cpu_clock_freq / 1000000,
-		   cpuinfo.cpu_clock_freq % 1000000,
-		   loops_per_jiffy / (500000 / HZ),
-		   (loops_per_jiffy / (5000 / HZ)) % 100);
-
-	seq_printf(m,
-		   "HW:\n Shift:\t\t%s\n"
-		   " MSR:\t\t%s\n"
-		   " PCMP:\t\t%s\n"
-		   " DIV:\t\t%s\n",
-		   (cpuinfo.use_instr & PVR0_USE_BARREL_MASK) ? "yes" : "no",
-		   (cpuinfo.use_instr & PVR2_USE_MSR_INSTR) ? "yes" : "no",
-		   (cpuinfo.use_instr & PVR2_USE_PCMP_INSTR) ? "yes" : "no",
-		   (cpuinfo.use_instr & PVR0_USE_DIV_MASK) ? "yes" : "no");
-
-	seq_printf(m, " MMU:\t\t%x\n", cpuinfo.mmu);
-
-	seq_printf(m,
-		   " MUL:\t\t%s\n"
-		   " FPU:\t\t%s\n",
-		   (cpuinfo.use_mult & PVR2_USE_MUL64_MASK) ? "v2" :
-		   (cpuinfo.use_mult & PVR0_USE_HW_MUL_MASK) ? "v1" : "no",
-		   (cpuinfo.use_fpu & PVR2_USE_FPU2_MASK) ? "v2" :
-		   (cpuinfo.use_fpu & PVR0_USE_FPU_MASK) ? "v1" : "no");
-
-	seq_printf(m,
-		   " Exc:\t\t%s%s%s%s%s%s%s%s\n",
-		   (cpuinfo.use_exc & PVR2_OPCODE_0x0_ILL_MASK) ? "op0x0 " : "",
-		   (cpuinfo.use_exc & PVR2_UNALIGNED_EXC_MASK) ? "unal " : "",
-		   (cpuinfo.use_exc & PVR2_ILL_OPCODE_EXC_MASK) ? "ill " : "",
-		   (cpuinfo.use_exc & PVR2_IOPB_BUS_EXC_MASK) ? "iopb " : "",
-		   (cpuinfo.use_exc & PVR2_DOPB_BUS_EXC_MASK) ? "dopb " : "",
-		   (cpuinfo.use_exc & PVR2_DIV_ZERO_EXC_MASK) ? "zero " : "",
-		   (cpuinfo.use_exc & PVR2_FPU_EXC_MASK) ? "fpu " : "",
-		   (cpuinfo.use_exc & PVR2_USE_FSL_EXC) ? "fsl " : "");
-
-	seq_printf(m,
-		   "Stream-insns:\t%sprivileged\n",
-		   cpuinfo.mmu_privins ? "un" : "");
-
-	if (cpuinfo.use_icache)
-		seq_printf(m,
-			   "Icache:\t\t%ukB\tline length:\t%dB\n",
-			   cpuinfo.icache_size >> 10,
-			   cpuinfo.icache_line_length);
-	else
-		seq_puts(m, "Icache:\t\tno\n");
-
-	if (cpuinfo.use_dcache) {
-		seq_printf(m,
-			   "Dcache:\t\t%ukB\tline length:\t%dB\n",
-			   cpuinfo.dcache_size >> 10,
-			   cpuinfo.dcache_line_length);
-		seq_puts(m, "Dcache-Policy:\t");
-		if (cpuinfo.dcache_wb)
-			seq_puts(m, "write-back\n");
+		seq_printf(m,
+			"Processor:	%u\n"
+			"CPU-Family:	MicroBlaze\n"
+			"FPGA-Arch:	%s\n"
+			"CPU-Ver:	%s, %s endian\n"
+			"CPU-MHz:	%d.%02d\n"
+			"BogoMips:	%lu.%02lu\n",
+			cpu,
+			fpga_family,
+			cpu_ver,
+			cpuinfo->endian ? "little" : "big",
+			cpuinfo->cpu_clock_freq / 1000000,
+			cpuinfo->cpu_clock_freq % 1000000,
+			loops_per_jiffy / (500000 / HZ),
+			(loops_per_jiffy / (5000 / HZ)) % 100);
+
+		seq_printf(m,
+			"HW:\n Shift:\t\t%s\n"
+			" MSR:\t\t%s\n"
+			" PCMP:\t\t%s\n"
+			" DIV:\t\t%s\n",
+			(cpuinfo->use_instr & PVR0_USE_BARREL_MASK) ?
+			"yes" : "no",
+			(cpuinfo->use_instr & PVR2_USE_MSR_INSTR) ?
+			"yes" : "no",
+			(cpuinfo->use_instr & PVR2_USE_PCMP_INSTR) ?
+			"yes" : "no",
+			(cpuinfo->use_instr & PVR0_USE_DIV_MASK) ?
+			"yes" : "no");
+
+		seq_printf(m, " MMU:\t\t%x\n", cpuinfo->mmu);
+
+		seq_printf(m,
+			" MUL:\t\t%s\n"
+			" FPU:\t\t%s\n",
+			(cpuinfo->use_mult & PVR2_USE_MUL64_MASK) ? "v2" :
+			(cpuinfo->use_mult & PVR0_USE_HW_MUL_MASK) ?
+			"v1" : "no",
+			(cpuinfo->use_fpu & PVR2_USE_FPU2_MASK) ? "v2" :
+			(cpuinfo->use_fpu & PVR0_USE_FPU_MASK) ? "v1" : "no");
+
+		seq_printf(m,
+			" Exc:\t\t%s%s%s%s%s%s%s%s\n",
+			(cpuinfo->use_exc & PVR2_OPCODE_0x0_ILL_MASK) ?
+			"op0x0 " : "",
+			(cpuinfo->use_exc & PVR2_UNALIGNED_EXC_MASK) ?
+			"unal " : "",
+			(cpuinfo->use_exc & PVR2_ILL_OPCODE_EXC_MASK) ?
+			"ill " : "",
+			(cpuinfo->use_exc & PVR2_IOPB_BUS_EXC_MASK) ?
+			"iopb " : "",
+			(cpuinfo->use_exc & PVR2_DOPB_BUS_EXC_MASK) ?
+			"dopb " : "",
+			(cpuinfo->use_exc & PVR2_DIV_ZERO_EXC_MASK) ?
+			"zero " : "",
+			(cpuinfo->use_exc & PVR2_FPU_EXC_MASK) ? "fpu " : "",
+			(cpuinfo->use_exc & PVR2_USE_FSL_EXC) ? "fsl " : "");
+
+		seq_printf(m,
+			"Stream-insns:\t%sprivileged\n",
+			cpuinfo->mmu_privins ? "un" : "");
+
+		if (cpuinfo->use_icache)
+			seq_printf(m,
+				"Icache:\t\t%ukB\tline length:\t%dB\n",
+				cpuinfo->icache_size >> 10,
+				cpuinfo->icache_line_length);
 		else
-			seq_puts(m, "write-through\n");
-	} else {
-		seq_puts(m, "Dcache:\t\tno\n");
-	}
+			seq_puts(m, "Icache:\t\tno\n");
 
-	seq_printf(m,
-		   "HW-Debug:\t%s\n",
-		   cpuinfo.hw_debug ? "yes" : "no");
-
-	seq_printf(m,
-		   "PVR-USR1:\t%02x\n"
-		   "PVR-USR2:\t%08x\n",
-		   cpuinfo.pvr_user1,
-		   cpuinfo.pvr_user2);
+		if (cpuinfo->use_dcache) {
+			seq_printf(m,
+				"Dcache:\t\t%ukB\tline length:\t%dB\n",
+				cpuinfo->dcache_size >> 10,
+				cpuinfo->dcache_line_length);
+			seq_puts(m, "Dcache-Policy:\t");
+			if (cpuinfo->dcache_wb)
+				seq_puts(m, "write-back\n");
+			else
+				seq_puts(m, "write-through\n");
+		} else {
+			seq_puts(m, "Dcache:\t\tno\n");
+		}
 
-	seq_printf(m, "Page size:\t%lu\n", PAGE_SIZE);
+		seq_printf(m,
+			"HW-Debug:\t%s\n",
+			cpuinfo->hw_debug ? "yes" : "no");
+
+		seq_printf(m,
+			"PVR-USR1:\t%02x\n"
+			"PVR-USR2:\t%08x\n",
+			cpuinfo->pvr_user1,
+			cpuinfo->pvr_user2);
+
+		seq_printf(m, "Page size:\t%lu\n", PAGE_SIZE);
+		seq_puts(m, "\n");
+	}
 
 	return 0;
 }
 
 static void *c_start(struct seq_file *m, loff_t *pos)
 {
-	int i = *pos;
-
-	return i < NR_CPUS ? (void *) (i + 1) : NULL;
+	return *pos < 1 ? (void *) 1 : NULL;
 }
 
 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/kernel/cpu/pvr.c
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/kernel/cpu/pvr.c
@@ -14,6 +14,7 @@
 #include <linux/compiler.h>
 #include <asm/exceptions.h>
 #include <asm/pvr.h>
+#include <linux/irqflags.h>
 
 /*
  * Until we get an assembler that knows about the pvr registers,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/kernel/dma.c
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/kernel/dma.c
@@ -15,7 +15,7 @@
 #include <linux/bug.h>
 #include <asm/cacheflush.h>
 
-static void __dma_sync(struct device *dev, phys_addr_t paddr, size_t size,
+static void __dma_sync(phys_addr_t paddr, size_t size,
 		enum dma_data_direction direction)
 {
 	switch (direction) {
@@ -31,14 +31,14 @@
 	}
 }
 
-void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr,
-		size_t size, enum dma_data_direction dir)
+void arch_sync_dma_for_device(phys_addr_t paddr, size_t size,
+		enum dma_data_direction dir)
 {
-	__dma_sync(dev, paddr, size, dir);
+	__dma_sync(paddr, size, dir);
 }
 
-void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr,
-		size_t size, enum dma_data_direction dir)
+void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size,
+		enum dma_data_direction dir)
 {
-	__dma_sync(dev, paddr, size, dir);
+	__dma_sync(paddr, size, dir);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/kernel/entry.S
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/kernel/entry.S
@@ -42,6 +42,11 @@
 	.space	(__NR_syscalls * 4)
 #endif /* DEBUG */
 
+#ifdef CONFIG_SMP
+#define CURRENT_SAVE	CURRENT_SAVE_ADDR
+#define ENTRY_SP	ENTRY_SP_ADDR
+#endif /* CONFIG_SMP */
+
 #define C_ENTRY(name)	.globl name; .align 4; name
 
 /*
@@ -91,6 +96,10 @@
 	.macro	clear_vms_ums
 	msrclr	r0, MSR_VMS | MSR_UMS
 	.endm
+
+	.macro	save_clear_vm
+	msrclr	r11, MSR_VM
+	.endm
 #else
 	.macro	clear_bip
 	mfs	r11, rmsr
@@ -153,6 +162,12 @@
 	andni	r11, r11, (MSR_VMS|MSR_UMS)
 	mts	rmsr,r11
 	.endm
+
+	.macro	save_clear_vm
+	mfs	r11, rmsr
+	andni	r11, r11, MSR_VM
+	mts	rmsr,r11
+	.endm
 #endif
 
 /* Define how to call high-level functions. With MMU, virtual mode must be
@@ -252,15 +267,32 @@
 	mts	rmsr , r11;						\
 	RESTORE_REGS_GP
 
+#ifndef CONFIG_SMP
+#define LOAD_PER_CPU(reg, addr)		lwi reg, r0, TOPHYS(PER_CPU(addr));
+#define STORE_PER_CPU(reg, addr)	swi reg, r0, TOPHYS(PER_CPU(addr));
+#define STORE_PER_CPU_VM(reg, addr)	swi reg, r0, PER_CPU(addr);
+#else
+#define LOAD_PER_CPU(reg, addr)		lwi reg, r0, PER_CPU(addr);
+#define STORE_PER_CPU(reg, addr)	swi reg, r0, PER_CPU(addr);
+#define STORE_PER_CPU_VM(reg, addr)	\
+	save_clear_vm;			\
+	bri	TOPHYS(1f);		\
+1:					\
+	swi	reg, r0, PER_CPU(addr);	\
+	mts	rmsr, r11;		\
+	bri	__phys_to_virt(2f);	\
+2:
+#endif /* CONFIG_SMP */
+
 #define SAVE_STATE	\
-	swi	r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* save stack */	\
+	STORE_PER_CPU(r1, ENTRY_SP) /* save stack */			\
 	/* See if already in kernel mode.*/				\
 	mfs	r1, rmsr;						\
 	andi	r1, r1, MSR_UMS;					\
 	bnei	r1, 1f;						\
 	/* Kernel-mode state save.  */					\
 	/* Reload kernel stack-ptr. */					\
-	lwi	r1, r0, TOPHYS(PER_CPU(ENTRY_SP));			\
+	LOAD_PER_CPU(r1, ENTRY_SP)					\
 	/* FIXME: I can add these two lines to one */			\
 	/* tophys(r1,r1); */						\
 	/* addik	r1, r1, -PT_SIZE; */				\
@@ -269,7 +301,7 @@
 	brid	2f;							\
 	swi	r1, r1, PT_MODE; 	 				\
 1:	/* User-mode state save.  */					\
-	lwi	r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */\
+	LOAD_PER_CPU(r1, CURRENT_SAVE)	/* get saved current */		\
 	tophys(r1,r1);							\
 	lwi	r1, r1, TS_THREAD_INFO;	/* get the thread info */	\
 	/* MS these three instructions can be added to one */		\
@@ -278,12 +310,12 @@
 	/* addik	r1, r1, -PT_SIZE; */			\
 	addik r1, r1, THREAD_SIZE + CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - PT_SIZE; \
 	SAVE_REGS							\
-	lwi	r11, r0, TOPHYS(PER_CPU(ENTRY_SP));			\
+	LOAD_PER_CPU(r11, ENTRY_SP)					\
 	swi	r11, r1, PT_R1; /* Store user SP.  */		\
 	swi	r0, r1, PT_MODE; /* Was in user-mode.  */		\
 	/* MS: I am clearing UMS even in case when I come from kernel space */ \
 	clear_ums; 							\
-2:	lwi	CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
+2:	LOAD_PER_CPU(CURRENT_TASK, CURRENT_SAVE)
 
 .text
 
@@ -300,10 +332,10 @@
  * are masked. This is nice, means we don't have to CLI before state save
  */
 C_ENTRY(_user_exception):
-	swi	r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */
+	STORE_PER_CPU(r1, ENTRY_SP) /* save stack */
 	addi	r14, r14, 4	/* return address is 4 byte after call */
 
-	lwi	r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */
+	LOAD_PER_CPU(r1, CURRENT_SAVE); /* get saved current */
 	tophys(r1,r1);
 	lwi	r1, r1, TS_THREAD_INFO;	/* get stack from task_struct */
 /* calculate kernel stack pointer from task struct 8k */
@@ -316,10 +348,10 @@
 	swi	r0, r1, PT_R4
 
 	swi	r0, r1, PT_MODE;			/* Was in user-mode. */
-	lwi	r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
+	LOAD_PER_CPU(r11, ENTRY_SP);
 	swi	r11, r1, PT_R1;		/* Store user SP.  */
 	clear_ums;
-2:	lwi	CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
+2:	LOAD_PER_CPU(CURRENT_TASK, CURRENT_SAVE);
 	/* Save away the syscall number.  */
 	swi	r12, r1, PT_R0;
 	tovirt(r1,r1)
@@ -434,8 +466,8 @@
 
 /* Finally, return to user state.  */
 4:	set_bip;			/*  Ints masked for state restore */
-	swi	CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */
 	VM_OFF;
+	STORE_PER_CPU(CURRENT_TASK, CURRENT_SAVE); /* save current */
 	tophys(r1,r1);
 	RESTORE_REGS_RTBD;
 	addik	r1, r1, PT_SIZE		/* Clean up stack space.  */
@@ -462,8 +494,8 @@
    saved context).  */
 C_ENTRY(ret_from_fork):
 	bralid	r15, schedule_tail; /* ...which is schedule_tail's arg */
-	add	r5, r3, r0;	/* switch_thread returns the prev task */
-				/* ( in the delay slot ) */
+	add	r5, r3, r0;	/* Arg 0: _switch_to places prev task struct */
+				/* pointer in r3 in the delay slot ) */
 	brid	ret_from_trap;	/* Do normal trap return */
 	add	r3, r0, r0;	/* Child's fork call should return 0. */
 
@@ -519,11 +551,11 @@
 	 * are used and they use r0 instead of r11.
 	 * I am using ENTRY_SP which should be primary used only for stack
 	 * pointer saving. */
-	swi	r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
+	STORE_PER_CPU(r11, ENTRY_SP);
 	set_bip;        /* equalize initial state for all possible entries */
 	clear_eip;
 	set_ee;
-	lwi	r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
+	LOAD_PER_CPU(r11, ENTRY_SP);
 	SAVE_STATE		/* Save registers.*/
 	/* PC, before IRQ/trap - this is one instruction above */
 	swi	r17, r1, PT_PC;
@@ -618,8 +650,8 @@
 
 /* Finally, return to user state.  */
 4:	set_bip;			/* Ints masked for state restore */
-	swi	CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */
 	VM_OFF;
+	STORE_PER_CPU(CURRENT_TASK, CURRENT_SAVE); /* save current */
 	tophys(r1,r1);
 
 	RESTORE_REGS_RTBD;
@@ -653,7 +685,7 @@
 C_ENTRY(_interrupt):
 /* MS: we are in physical address */
 /* Save registers, switch to proper stack, convert SP to virtual.*/
-	swi	r1, r0, TOPHYS(PER_CPU(ENTRY_SP))
+	STORE_PER_CPU(r1, ENTRY_SP)
 	/* MS: See if already in kernel mode. */
 	mfs	r1, rmsr
 	nop
@@ -661,7 +693,7 @@
 	bnei	r1, 1f
 
 /* Kernel-mode state save. */
-	lwi	r1, r0, TOPHYS(PER_CPU(ENTRY_SP))
+	LOAD_PER_CPU(r1, ENTRY_SP)
 	tophys(r1,r1); /* MS: I have in r1 physical address where stack is */
 	/* save registers */
 /* MS: Make room on the stack -> activation record */
@@ -672,7 +704,7 @@
 1:
 /* User-mode state save. */
  /* MS: get the saved current */
-	lwi	r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
+	LOAD_PER_CPU(r1, CURRENT_SAVE);
 	tophys(r1,r1);
 	lwi	r1, r1, TS_THREAD_INFO;
 	addik	r1, r1, THREAD_SIZE;
@@ -682,11 +714,11 @@
 	SAVE_REGS
 	/* calculate mode */
 	swi	r0, r1, PT_MODE;
-	lwi	r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
+	LOAD_PER_CPU(r11, ENTRY_SP);
 	swi	r11, r1, PT_R1;
 	clear_ums;
 2:
-	lwi	CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
+	LOAD_PER_CPU(CURRENT_TASK, CURRENT_SAVE);
 	tovirt(r1,r1)
 	addik	r15, r0, irq_call;
 irq_call:rtbd	r0, do_IRQ;
@@ -719,8 +751,8 @@
 no_intr_resched:
     /* Disable interrupts, we are now committed to the state restore */
 	disable_irq
-	swi	CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE);
 	VM_OFF;
+	STORE_PER_CPU(CURRENT_TASK, CURRENT_SAVE);
 	tophys(r1,r1);
 	RESTORE_REGS
 	addik	r1, r1, PT_SIZE /* MS: Clean up stack space. */
@@ -738,14 +770,9 @@
 	andi	r5, r5, _TIF_NEED_RESCHED;
 	beqi	r5, restore /* if zero jump over */
 
-preempt:
 	/* interrupts are off that's why I am calling preempt_chedule_irq */
 	bralid	r15, preempt_schedule_irq
 	nop
-	lwi	r11, CURRENT_TASK, TS_THREAD_INFO;	/* get thread info */
-	lwi	r5, r11, TI_FLAGS;		/* get flags in thread info */
-	andi	r5, r5, _TIF_NEED_RESCHED;
-	bnei	r5, preempt /* if non zero jump to resched */
 restore:
 #endif
 	VM_OFF /* MS: turn off MMU */
@@ -764,14 +791,14 @@
  */
 C_ENTRY(_debug_exception):
 	/* BIP bit is set on entry, no interrupts can occur */
-	swi	r1, r0, TOPHYS(PER_CPU(ENTRY_SP))
+	STORE_PER_CPU(r1, ENTRY_SP)
 
 	mfs	r1, rmsr
 	nop
 	andi	r1, r1, MSR_UMS
 	bnei	r1, 1f
 /* MS: Kernel-mode state save - kgdb */
-	lwi	r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/
+	LOAD_PER_CPU(r1, ENTRY_SP); /* Reload kernel stack-ptr*/
 
 	/* BIP bit is set on entry, no interrupts can occur */
 	addik   r1, r1, CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - PT_SIZE;
@@ -805,7 +832,7 @@
 	bri 0
 
 /* MS: User-mode state save - gdb */
-1:	lwi	r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */
+1:	LOAD_PER_CPU(r1, CURRENT_SAVE); /* get saved current */
 	tophys(r1,r1);
 	lwi	r1, r1, TS_THREAD_INFO;	/* get the thread info */
 	addik	r1, r1, THREAD_SIZE;	/* calculate kernel stack pointer */
@@ -815,9 +842,9 @@
 	SAVE_REGS;
 	swi	r16, r1, PT_PC;	/* Save LP */
 	swi	r0, r1, PT_MODE; /* Was in user-mode.  */
-	lwi	r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
+	LOAD_PER_CPU(r11, ENTRY_SP);
 	swi	r11, r1, PT_R1; /* Store user SP.  */
-	lwi	CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
+	LOAD_PER_CPU(CURRENT_TASK, CURRENT_SAVE);
 	tovirt(r1,r1)
 	set_vms;
 	addik	r5, r1, 0;
@@ -853,8 +880,8 @@
 	bri	1b
 
 /* Finally, return to user state.  */
-4:	swi	CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */
-	VM_OFF;
+4:	VM_OFF;
+	STORE_PER_CPU(CURRENT_TASK, CURRENT_SAVE); /* save current */
 	tophys(r1,r1);
 	/* MS: Restore all regs */
 	RESTORE_REGS_RTBD
@@ -923,7 +950,7 @@
 	/* update r31, the current-give me pointer to task which will be next */
 	lwi	CURRENT_TASK, r6, TI_TASK
 	/* stored it to current_save too */
-	swi	CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE)
+	STORE_PER_CPU_VM(CURRENT_TASK, CURRENT_SAVE)
 
 	/* get new process' cpu context and restore */
 	/* give me start where start context of next task */
@@ -963,6 +990,7 @@
 	nop
 
 ENTRY(_reset)
+	VM_OFF
 	brai	0; /* Jump to reset vector */
 
 	/* These are compiled and loaded into high memory, then
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/kernel/exceptions.c
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/kernel/exceptions.c
@@ -44,10 +44,10 @@
 	pr_warn("Oops: %s, sig: %ld\n", str, err);
 	show_regs(fp);
 	spin_unlock_irq(&die_lock);
-	/* do_exit() should take care of panic'ing from an interrupt
+	/* make_task_dead() should take care of panic'ing from an interrupt
 	 * context so we don't handle it here
 	 */
-	do_exit(err);
+	make_task_dead(err);
 }
 
 /* for user application debugging */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/kernel/head.S
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/kernel/head.S
@@ -30,6 +30,7 @@
 
 #include <linux/init.h>
 #include <linux/linkage.h>
+#include <asm/entry.h>
 #include <asm/thread_info.h>
 #include <asm/page.h>
 #include <linux/of_fdt.h>		/* for OF_DT_HEADER */
@@ -38,6 +39,7 @@
 #include <asm/setup.h> /* COMMAND_LINE_SIZE */
 #include <asm/mmu.h>
 #include <asm/processor.h>
+#include <asm/asm-offsets.h>
 
 .section .data
 .global empty_zero_page
@@ -47,7 +49,11 @@
 .global swapper_pg_dir
 swapper_pg_dir:
 	.space	PAGE_SIZE
-
+#ifdef CONFIG_SMP
+temp_boot_stack:
+	.space	1024
+#define CURRENT_SAVE	CURRENT_SAVE_ADDR
+#endif /* CONFIG_SMP */
 #endif /* CONFIG_MMU */
 
 .section .rodata
@@ -79,6 +85,13 @@
 	msrclr	r8, 0 /* clear nothing - just read msr for test */
 	cmpu	r8, r8, r1 /* r1 must contain msr reg content */
 
+#ifdef CONFIG_SMP
+	/* skip FDT copy if secondary */
+	mfs	r11, rpvr0
+	andi	r11, r11, 0xFF
+	bnei	r11, _setup_initial_mmu
+#endif /* CONFIG_SMP */
+
 /* r7 may point to an FDT, or there may be one linked in.
    if it's in r7, we've got to save it away ASAP.
    We ensure r7 points to a valid FDT, just in case the bootloader
@@ -99,7 +112,7 @@
 _prepare_copy_fdt:
 	or	r11, r0, r0 /* incremment */
 	ori	r4, r0, TOPHYS(_fdt_start)
-	ori	r3, r0, (0x8000 - 4)
+	ori	r3, r0, (0x10000 - 4)
 _copy_fdt:
 	lw	r12, r7, r11 /* r12 = r7 + r11 */
 	sw	r12, r4, r11 /* addr[r4 + r11] = r12 */
@@ -121,10 +134,10 @@
 	tophys(r4,r4)			/* convert to phys address */
 	ori	r3, r0, COMMAND_LINE_SIZE - 1 /* number of loops */
 _copy_command_line:
-	/* r2=r5+r6 - r5 contain pointer to command line */
+	/* r2=r5+r11 - r5 contain pointer to command line */
 	lbu	r2, r5, r11
 	beqid	r2, skip		/* Skip if no data */
-	sb	r2, r4, r11		/* addr[r4+r6]= r2 */
+	sb	r2, r4, r11		/* addr[r4+r11]= r2 */
 	addik	r11, r11, 1		/* increment counting */
 	bgtid	r3, _copy_command_line	/* loop for all entries       */
 	addik	r3, r3, -1		/* decrement loop */
@@ -139,14 +152,15 @@
 	ori	r4, r0, TOPHYS(_bram_load_start)	/* save bram context */
 	ori	r3, r0, (LMB_SIZE - 4)
 _copy_bram:
-	lw	r7, r0, r11		/* r7 = r0 + r6 */
-	sw	r7, r4, r11		/* addr[r4 + r6] = r7 */
+	lw	r7, r0, r11		/* r7 = r0 + r11 */
+	sw	r7, r4, r11		/* addr[r4 + r11] = r7 */
 	addik	r11, r11, 4		/* increment counting */
 	bgtid	r3, _copy_bram		/* loop for all entries */
 	addik	r3, r3, -4		/* descrement loop */
 #endif
 	/* We have to turn on the MMU right away. */
 
+_setup_initial_mmu:
 	/*
 	 * Set up the initial MMU state so we can do the first level of
 	 * kernel initialization.  This maps the first 16 MBytes of memory 1:1
@@ -178,9 +192,8 @@
 	tophys(r4,r3)			/* Load the kernel physical address */
 
 	/* start to do TLB calculation */
-	addik	r12, r0, _end
+	addik	r12, r0, _end_tlb_mapping
 	rsub	r12, r3, r12
-	addik	r12, r12, CONFIG_LOWMEM_SIZE >> PTE_SHIFT /* that's the pad */
 
 	or r9, r0, r0 /* TLB0 = 0 */
 	or r10, r0, r0 /* TLB1 = 0 */
@@ -322,6 +335,18 @@
 	 */
 turn_on_mmu:
 	ori	r15,r0,start_here
+#ifdef CONFIG_SMP
+	/*
+	 * Read PVR and mask off all but CPU id bits to use to select
+	 * boot sequence
+	 */
+	mfs	r4, rpvr0
+	andi	r4, r4, 0xFF
+
+	beqi	r4, finish
+	ori	r15, r0, start_secondary_cpu
+finish:
+#endif /* CONFIG_SMP */
 	ori	r4,r0,MSR_KERNEL_VMS
 	mts	rmsr,r4
 	nop
@@ -340,6 +365,10 @@
 
 	/* Initialize r31 with current task address */
 	addik	r31, r0, init_task
+#ifdef CONFIG_MMU
+	/* save current for CPU 0 */
+	swi	CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE);
+#endif
 
 	addik	r11, r0, machine_early_init
 	brald	r15, r11
@@ -384,3 +413,61 @@
 	rted	r17, 0		/* enable MMU and jump to start_kernel */
 	nop
 #endif /* CONFIG_MMU */
+
+#ifdef CONFIG_SMP
+/* Entry point for secondary processors */
+start_secondary_cpu:
+
+	/* Initialize small data anchors */
+	addik	r13, r0, _KERNEL_SDA_BASE_
+	addik	r2, r0, _KERNEL_SDA2_BASE_
+
+	/* Initialize stack pointer */
+	addik	r1, r0, temp_boot_stack + 1024 - 4
+
+	/*
+	 * Initialize the exception table.
+	 */
+	addik	r11, r0, secondary_machine_init
+	brald	r15, r11
+	nop
+
+	lwi	r1, r0, secondary_ti
+
+	/* Initialize r31 with current task address */
+	lwi	CURRENT_TASK, r1, TI_TASK
+	/* save current for secondary CPU */
+	swi	CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE);
+
+	/* Initialize stack pointer */
+	addi	r1, r1, THREAD_SIZE - 4
+	swi	r0, r1, 0
+
+	/* Initialize MMU */
+	ori	r11, r0, 0x10000000
+	mts	rzpr, r11
+
+	ori	r15, r0, TOPHYS(kernel_load_context_secondary)
+	ori	r4, r0, MSR_KERNEL
+	mts	rmsr, r4
+	nop
+	bri	4
+	rted	r15, 0
+	nop
+
+	/* Load up the kernel context */
+kernel_load_context_secondary:
+	# Keep entry 0 and 1 valid. Entry 3 mapped to LMB can go away.
+	ori	r5, r0, MICROBLAZE_LMB_TLB_ID
+	mts     rtlbx, r5
+	nop
+	mts	rtlbhi, r0
+	nop
+	addi	r15, r0, machine_halt
+	ori	r17, r0, start_secondary
+	ori	r4, r0, MSR_KERNEL_VMS
+	mts	rmsr, r4
+	nop
+	rted	r17, 0		/* enable MMU and jump to start_kernel */
+	nop
+#endif /* CONFIG_SMP */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/kernel/hw_exception_handler.S
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/kernel/hw_exception_handler.S
@@ -252,10 +252,15 @@
 
 /* wrappers to restore state before coming to entry.S */
 #ifdef CONFIG_MMU
+#ifdef CONFIG_SMP
+#define CURRENT_SAVE  __phys_to_virt(CURRENT_SAVE_ADDR)
+#define pt_pool_space __phys_to_virt(PT_POOL_SPACE_ADDR)
+#else
 .section .data
 .align 4
 pt_pool_space:
 	.space	PT_SIZE
+#endif /* CONFIG_SMP */
 
 #ifdef DEBUG
 /* Create space for exception counting. */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/kernel/irq.c
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/kernel/irq.c
@@ -20,29 +20,10 @@
 #include <linux/irqchip.h>
 #include <linux/of_irq.h>
 
-static u32 concurrent_irq;
-
 void __irq_entry do_IRQ(struct pt_regs *regs)
 {
-	unsigned int irq;
-	struct pt_regs *old_regs = set_irq_regs(regs);
 	trace_hardirqs_off();
-
-	irq_enter();
-	irq = xintc_get_irq();
-next_irq:
-	BUG_ON(!irq);
-	generic_handle_irq(irq);
-
-	irq = xintc_get_irq();
-	if (irq != -1U) {
-		pr_debug("next irq: %d\n", irq);
-		++concurrent_irq;
-		goto next_irq;
-	}
-
-	irq_exit();
-	set_irq_regs(old_regs);
+	handle_arch_irq(regs);
 	trace_hardirqs_on();
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/kernel/kgdb.c
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/kernel/kgdb.c
@@ -8,6 +8,7 @@
 
 #include <linux/kgdb.h>
 #include <linux/kdebug.h>
+#include <linux/smp.h>
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <asm/cacheflush.h>
@@ -105,6 +106,13 @@
 		gdb_regs[GDB_PVR + i] = pvr.pvr[i];
 }
 
+#ifdef CONFIG_SMP
+void kgdb_roundup_cpus(void)
+{
+	smp_send_debugger_break();
+}
+#endif
+
 void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip)
 {
 	regs->pc = ip;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/kernel/misc.S
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/kernel/misc.S
@@ -39,7 +39,7 @@
 	rsubi	r11, r12, MICROBLAZE_TLB_SIZE - 1
 	bneid	r11, _tlbia_1 /* loop for all entries */
 	addik	r12, r12, 1
-	/* sync */
+	mbar	1 /* sync */
 	rtsd	r15, 8
 	nop
 	.size  _tlbia, . - _tlbia
@@ -58,6 +58,7 @@
 	blti	r12, _tlbie_1 /* Check if found */
 	mts	rtlbhi, r0 /* flush: ensure V is clear */
 	nop
+	mbar	1 /* sync */
 _tlbie_1:
 	rtsd	r15, 8
 	nop
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/kernel/setup.c
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/kernel/setup.c
@@ -28,6 +28,7 @@
 #include <linux/pci.h>
 #include <linux/cache.h>
 #include <linux/of.h>
+#include <linux/smp.h>
 #include <linux/dma-mapping.h>
 #include <asm/cacheflush.h>
 #include <asm/entry.h>
@@ -35,13 +36,24 @@
 
 #include <asm/pgtable.h>
 
+#ifdef CONFIG_SMP
+static void __init smp_setup_cpu_maps(void)
+{
+	int i;
+
+	for (i = 0; i < NR_CPUS; i++) {
+		set_cpu_present(i, true);
+		set_cpu_possible(i, true);
+	}
+}
+#else
 DEFINE_PER_CPU(unsigned int, KSP);	/* Saved kernel stack pointer */
 DEFINE_PER_CPU(unsigned int, KM);	/* Kernel/user mode */
 DEFINE_PER_CPU(unsigned int, ENTRY_SP);	/* Saved SP on kernel entry */
 DEFINE_PER_CPU(unsigned int, R11_SAVE);	/* Temp variable for entry */
 DEFINE_PER_CPU(unsigned int, CURRENT_SAVE);	/* Saved current pointer */
+#endif /* CONFIG_SMP */
 
-unsigned int boot_cpuid;
 /*
  * Placed cmd_line to .data section because can be initialized from
  * ASM code. Default position is BSS section which is cleared
@@ -54,7 +66,6 @@
 	*cmdline_p = boot_command_line;
 
 	setup_memory();
-	parse_early_param();
 
 	console_verbose();
 
@@ -66,6 +77,10 @@
 
 	xilinx_pci_init();
 
+#ifdef CONFIG_SMP
+	smp_setup_cpu_maps();
+#endif
+
 #if defined(CONFIG_DUMMY_CONSOLE)
 	conswitchp = &dummy_con;
 #endif
@@ -138,7 +153,7 @@
 	if (fdt)
 		pr_info("FDT at 0x%08x\n", fdt);
 	else
-		pr_info("Compiled-in FDT at %p\n", _fdt_start);
+		pr_info("Compiled-in FDT at 0x%08x\n", (unsigned)&_fdt_start);
 
 #ifdef CONFIG_MTD_UCLINUX
 	pr_info("Found romfs @ 0x%08x (0x%08x)\n",
@@ -175,8 +190,10 @@
 		*dst = *src;
 
 	/* Initialize global data */
+#ifndef CONFIG_SMP
 	per_cpu(KM, 0) = 0x1;	/* We start in kernel mode */
 	per_cpu(CURRENT_SAVE, 0) = (unsigned long)current;
+#endif
 }
 
 void __init time_init(void)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/kernel/smp.c
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/kernel/smp.c
@@ -0,0 +1,331 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * SMP support for MicroBlaze, borrowing a great
+ * deal of code from the PowerPC implementation
+ *
+ * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
+ * Copyright (C) 2013-2020 Xilinx, Inc.
+ */
+
+#include <linux/atomic.h>
+#include <linux/cpu.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/profile.h>
+#include <linux/sched/task.h>
+#include <linux/seq_file.h>
+#include <linux/smp.h>
+
+#include <asm/barrier.h>
+#include <asm/cpuinfo.h>
+#include <asm/tlbflush.h>
+
+struct thread_info *secondary_ti;
+
+static struct thread_info *current_set[NR_CPUS];
+
+unsigned long irq_err_count;
+
+static unsigned int boot_cpuid;
+
+static DEFINE_PER_CPU(cpumask_var_t, cpu_core_map);
+
+static volatile unsigned int cpu_callin_map[NR_CPUS];
+
+static void (*crash_ipi_function_ptr)(struct pt_regs *);
+
+static const char * const smp_ipi_name[] = {
+	[MICROBLAZE_MSG_RESCHEDULE] = "ipi reschedule",
+	[MICROBLAZE_MSG_CALL_FUNCTION] = "ipi call function",
+	[MICROBLAZE_MSG_CALL_FUNCTION_SINGLE] = "ipi call function single",
+	[MICROBLAZE_MSG_DEBUGGER_BREAK] = "ipi debugger",
+};
+
+/* Functions for recording IPI handler */
+static void (*__smp_cross_call)(unsigned int, unsigned int);
+
+void __init set_smp_cross_call(void (*fn)(unsigned int, unsigned int))
+{
+	if (!__smp_cross_call)
+		__smp_cross_call = fn;
+}
+
+static inline struct cpumask *cpu_core_mask(int cpu)
+{
+	return per_cpu(cpu_core_map, cpu);
+}
+
+u64 smp_irq_stat_cpu(unsigned int cpu)
+{
+	u64 sum = 0;
+	int i;
+
+	for (i = 0; i < MICROBLAZE_NUM_IPIS; i++)
+		sum += __get_irq_stat(cpu, ipi_irqs[i]);
+
+	return sum;
+}
+
+static void show_ipi_list(struct seq_file *p, int prec)
+{
+	unsigned int cpu, i;
+
+	for (i = 0; i < MICROBLAZE_NUM_IPIS; i++) {
+		seq_printf(p, "%*s%u:%s", prec - 1, "IPI", i,
+			prec >= 4 ? " " : "");
+		for_each_online_cpu(cpu)
+			seq_printf(p, "%10u ",
+				__get_irq_stat(cpu, ipi_irqs[i]));
+		seq_printf(p, " %s\n", smp_ipi_name[i]);
+	}
+}
+
+int arch_show_interrupts(struct seq_file *p, int prec)
+{
+	show_ipi_list(p, prec);
+	seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count);
+	return 0;
+}
+
+void handle_IPI(int ipinr, struct pt_regs *regs)
+{
+	struct pt_regs *old_regs = set_irq_regs(regs);
+	unsigned int cpu = smp_processor_id();
+
+	pr_debug("%s: cpu: %d got IPI: %d\n", __func__, cpu, ipinr);
+
+	__inc_irq_stat(cpu, ipi_irqs[ipinr]);
+
+	switch (ipinr) {
+	case MICROBLAZE_MSG_RESCHEDULE:
+		scheduler_ipi();
+		break;
+	case MICROBLAZE_MSG_CALL_FUNCTION:
+		generic_smp_call_function_interrupt();
+		break;
+	case MICROBLAZE_MSG_CALL_FUNCTION_SINGLE:
+		generic_smp_call_function_single_interrupt();
+		break;
+	case MICROBLAZE_MSG_DEBUGGER_BREAK:
+		if (crash_ipi_function_ptr)
+			crash_ipi_function_ptr(get_irq_regs());
+		break;
+	default:
+		BUG();
+	}
+
+	set_irq_regs(old_regs);
+}
+
+void smp_send_reschedule(int cpu)
+{
+	if (cpu_online(cpu))
+		__smp_cross_call(cpu, MICROBLAZE_MSG_RESCHEDULE);
+}
+
+void arch_send_call_function_single_ipi(int cpu)
+{
+	if (cpu_online(cpu))
+		__smp_cross_call(cpu, MICROBLAZE_MSG_CALL_FUNCTION_SINGLE);
+}
+
+void arch_send_call_function_ipi_mask(const struct cpumask *mask)
+{
+	unsigned int cpu;
+
+	for_each_cpu(cpu, mask)
+		__smp_cross_call(cpu, MICROBLAZE_MSG_CALL_FUNCTION);
+}
+
+#ifdef CONFIG_KGDB
+void smp_send_debugger_break(void)
+{
+	int cpu;
+	int me = raw_smp_processor_id();
+
+	for_each_online_cpu(cpu)
+		if (cpu != me)
+			__smp_cross_call(cpu, MICROBLAZE_MSG_DEBUGGER_BREAK);
+}
+
+void crash___smp_cross_call(void (*crash_ipi_callback)(struct pt_regs *))
+{
+	crash_ipi_function_ptr = crash_ipi_callback;
+	if (crash_ipi_callback) {
+		mb();
+		smp_send_debugger_break();
+	}
+}
+#endif
+
+static void stop_this_cpu(void *dummy)
+{
+	/* Remove this CPU */
+	set_cpu_online(smp_processor_id(), false);
+
+	local_irq_disable();
+	while (1)
+		;
+}
+
+void smp_send_stop(void)
+{
+	smp_call_function(stop_this_cpu, NULL, 0);
+}
+
+static void __init smp_create_idle(unsigned int cpu)
+{
+	struct task_struct *p;
+
+	/* create a process for the processor */
+	p = fork_idle(cpu);
+	if (IS_ERR(p)) {
+		panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p));
+		pr_alert("failed to create cpu %d idle\n", cpu);
+	}
+
+	task_thread_info(p)->cpu = cpu;
+	current_set[cpu] = task_thread_info(p);
+
+}
+
+void __init smp_prepare_cpus(unsigned int max_cpus)
+{
+	unsigned int cpu;
+
+	/*
+	 * setup_cpu may need to be called on the boot cpu. We havent
+	 * spun any cpus up but lets be paranoid.
+	 */
+	BUG_ON(boot_cpuid != smp_processor_id());
+
+	/* Fixup boot cpu */
+	cpu_callin_map[boot_cpuid] = 1;
+
+	for_each_possible_cpu(cpu) {
+		zalloc_cpumask_var_node(&per_cpu(cpu_core_map, cpu),
+					GFP_KERNEL, cpu_to_node(cpu));
+	}
+
+	cpumask_set_cpu(boot_cpuid, cpu_core_mask(boot_cpuid));
+
+	max_cpus = NR_CPUS;
+
+	for_each_possible_cpu(cpu) {
+		if (cpu != boot_cpuid)
+			smp_create_idle(cpu);
+	}
+}
+
+void __init smp_prepare_boot_cpu(void)
+{
+	BUG_ON(smp_processor_id() != boot_cpuid);
+	current_set[boot_cpuid] = task_thread_info(current);
+}
+
+int __cpu_up(unsigned int cpu, struct task_struct *tidle)
+{
+	int c;
+
+	secondary_ti = current_set[cpu];
+
+	/*
+	 * Make sure callin-map entry is 0 (can be leftover a CPU
+	 * hotplug
+	 */
+	cpu_callin_map[cpu] = 0;
+
+	/*
+	 * The information for processor bringup must
+	 * be written out to main store before we release
+	 * the processor.
+	 */
+	smp_mb();
+
+	/* wake up cpu */
+	pr_alert("From cpu %d: Waking CPU %d\n", smp_processor_id(), cpu);
+
+	__smp_cross_call(cpu, 0);
+
+	if (system_state < SYSTEM_RUNNING)
+		for (c = 10000; c && !cpu_callin_map[cpu]; c--)
+			udelay(100);
+
+	if (!cpu_callin_map[cpu]) {
+		pr_err("Processor %u is stuck.\n", cpu);
+		return -ENOENT;
+	}
+
+	while (!cpu_online(cpu))
+		cpu_relax();
+
+	pr_alert("Processor %u found.\n", cpu);
+
+	return 0;
+}
+
+asmlinkage void __init secondary_machine_init(void)
+{
+	unsigned long *src, *dst;
+	unsigned int offset = 0;
+
+	/*
+	 * Do not copy reset vectors. offset = 0x2 means skip the first
+	 * two instructions. dst is pointer to MB vectors which are placed
+	 * in block ram. If you want to copy reset vector setup offset to 0x0
+	 */
+#if !CONFIG_MANUAL_RESET_VECTOR
+	offset = 0x2;
+#endif
+	dst = (unsigned long *) (offset * sizeof(u32));
+	for (src = __ivt_start + offset; src < __ivt_end; src++, dst++)
+		*dst = *src;
+}
+
+/* Activate a secondary processor. */
+void __init start_secondary(void) // FIXME this is not __init
+{
+	unsigned int cpu = smp_processor_id();
+	int i;
+
+	atomic_inc(&init_mm.mm_count);
+	current->active_mm = &init_mm;
+	cpumask_set_cpu(cpu, mm_cpumask(&init_mm));
+	local_flush_tlb_mm(&init_mm);
+
+	pr_alert("cpu: %d alive\n", cpu);
+
+	setup_cpuinfo();
+	microblaze_cache_init();
+
+	preempt_disable();
+
+	/* calibrate_delay(); */
+
+	cpu_callin_map[cpu] = 1;
+
+	notify_cpu_starting(cpu);
+
+	set_cpu_online(cpu, true);
+
+	for_each_online_cpu(i) {
+		cpumask_set_cpu(cpu, cpu_core_mask(i));
+		cpumask_set_cpu(i, cpu_core_mask(cpu));
+	}
+	local_irq_enable();
+
+	cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
+
+	BUG();
+}
+
+#ifdef CONFIG_PROFILING
+int setup_profiling_timer(unsigned int multiplier)
+{
+	return 0;
+}
+#endif
+
+void __init smp_cpus_done(unsigned int max_cpus)
+{ }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/kernel/syscalls/syscallhdr.sh
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/kernel/syscalls/syscallhdr.sh
@@ -33,4 +33,5 @@
 	printf "#endif\n"
 	printf "\n"
 	printf "#endif /* %s */" "${fileguard}"
+	printf "\n"
 ) > "$out"
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/kernel/timer.c
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/kernel/timer.c
@@ -16,15 +16,22 @@
 #include <linux/sched_clock.h>
 #include <linux/clk.h>
 #include <linux/clockchips.h>
+#include <linux/cpuhotplug.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/timecounter.h>
 #include <asm/cpuinfo.h>
 
-static void __iomem *timer_baseaddr;
+static void __iomem *clocksource_baseaddr;
 
-static unsigned int freq_div_hz;
-static unsigned int timer_clock_freq;
+struct xilinx_timer {
+	void __iomem *timer_baseaddr;
+	u32 irq;
+	unsigned int freq_div_hz;
+	unsigned int timer_clock_freq;
+};
+
+static DEFINE_PER_CPU(struct xilinx_timer, timer_priv);
 
 #define TCSR0	(0x00)
 #define TLR0	(0x04)
@@ -70,12 +77,21 @@
 
 static inline void xilinx_timer0_stop(void)
 {
+	int cpu = smp_processor_id();
+	struct xilinx_timer *timer = per_cpu_ptr(&timer_priv, cpu);
+	void __iomem *timer_baseaddr = timer->timer_baseaddr;
+
 	write_fn(read_fn(timer_baseaddr + TCSR0) & ~TCSR_ENT,
 		 timer_baseaddr + TCSR0);
 }
 
-static inline void xilinx_timer0_start_periodic(unsigned long load_val)
+static inline void xilinx_timer0_start_periodic(void)
 {
+	int cpu = smp_processor_id();
+	struct xilinx_timer *timer = per_cpu_ptr(&timer_priv, cpu);
+	void __iomem *timer_baseaddr = timer->timer_baseaddr;
+	unsigned long load_val = timer->freq_div_hz;
+
 	if (!load_val)
 		load_val = 1;
 	/* loading value to timer reg */
@@ -103,6 +119,10 @@
 
 static inline void xilinx_timer0_start_oneshot(unsigned long load_val)
 {
+	int cpu = smp_processor_id();
+	struct xilinx_timer *timer = per_cpu_ptr(&timer_priv, cpu);
+	void __iomem *timer_baseaddr = timer->timer_baseaddr;
+
 	if (!load_val)
 		load_val = 1;
 	/* loading value to timer reg */
@@ -133,11 +153,11 @@
 static int xilinx_timer_set_periodic(struct clock_event_device *evt)
 {
 	pr_info("%s\n", __func__);
-	xilinx_timer0_start_periodic(freq_div_hz);
+	xilinx_timer0_start_periodic();
 	return 0;
 }
 
-static struct clock_event_device clockevent_xilinx_timer = {
+static DEFINE_PER_CPU(struct clock_event_device, clockevent_xilinx_timer) = {
 	.name			= "xilinx_clockevent",
 	.features		= CLOCK_EVT_FEAT_ONESHOT |
 				  CLOCK_EVT_FEAT_PERIODIC,
@@ -150,44 +170,75 @@
 
 static inline void timer_ack(void)
 {
+	int cpu = smp_processor_id();
+	struct xilinx_timer *timer = per_cpu_ptr(&timer_priv, cpu);
+	void __iomem *timer_baseaddr = timer->timer_baseaddr;
+
 	write_fn(read_fn(timer_baseaddr + TCSR0), timer_baseaddr + TCSR0);
 }
 
 static irqreturn_t timer_interrupt(int irq, void *dev_id)
 {
-	struct clock_event_device *evt = &clockevent_xilinx_timer;
+	struct clock_event_device *evt = dev_id;
+
 	timer_ack();
 	evt->event_handler(evt);
 	return IRQ_HANDLED;
 }
 
-static struct irqaction timer_irqaction = {
-	.handler = timer_interrupt,
-	.flags = IRQF_TIMER,
-	.name = "timer",
-	.dev_id = &clockevent_xilinx_timer,
-};
+static __init int xilinx_clockevent_init(int cpu, struct xilinx_timer *timer)
+{
+	struct clock_event_device *ce = per_cpu_ptr(&clockevent_xilinx_timer,
+						    cpu);
+
+	ce->mult = div_sc(timer->timer_clock_freq, NSEC_PER_SEC, ce->shift);
+	ce->max_delta_ns = clockevent_delta2ns((u32)~0, ce);
+	ce->max_delta_ticks = (u32)~0;
+	ce->min_delta_ns = clockevent_delta2ns(1, ce);
+	ce->min_delta_ticks = 1;
+	ce->cpumask = cpumask_of(cpu);
+	clockevents_register_device(ce);
+
+	return 0;
+}
 
-static __init int xilinx_clockevent_init(void)
+static int microblaze_timer_starting(unsigned int cpu)
 {
-	clockevent_xilinx_timer.mult =
-		div_sc(timer_clock_freq, NSEC_PER_SEC,
-				clockevent_xilinx_timer.shift);
-	clockevent_xilinx_timer.max_delta_ns =
-		clockevent_delta2ns((u32)~0, &clockevent_xilinx_timer);
-	clockevent_xilinx_timer.max_delta_ticks = (u32)~0;
-	clockevent_xilinx_timer.min_delta_ns =
-		clockevent_delta2ns(1, &clockevent_xilinx_timer);
-	clockevent_xilinx_timer.min_delta_ticks = 1;
-	clockevent_xilinx_timer.cpumask = cpumask_of(0);
-	clockevents_register_device(&clockevent_xilinx_timer);
+	int ret;
+	struct xilinx_timer *timer = per_cpu_ptr(&timer_priv, cpu);
+	struct clock_event_device *ce = per_cpu_ptr(&clockevent_xilinx_timer,
+						    cpu);
+
+	pr_debug("%s: cpu %d\n", __func__, cpu);
+
+	if (!timer->timer_baseaddr) {
+		/* It should never fail */
+		pr_err("%s: clockevent timer for cpu %d failed\n",
+		       __func__, cpu);
+		return -EINVAL;
+	}
+
+	ret = request_irq(timer->irq, timer_interrupt, IRQF_TIMER |
+			  IRQF_PERCPU | IRQF_NOBALANCING,
+			  "timer", ce);
+	if (ret) {
+		pr_err("%s: request_irq failed\n", __func__);
+		return ret;
+	}
+
+	return xilinx_clockevent_init(cpu, timer);
+}
+
+static int microblaze_timer_dying(unsigned int cpu)
+{
+	pr_debug("%s: cpu %d\n", __func__, cpu);
 
 	return 0;
 }
 
 static u64 xilinx_clock_read(void)
 {
-	return read_fn(timer_baseaddr + TCR1);
+	return read_fn(clocksource_baseaddr + TCR0);
 }
 
 static u64 xilinx_read(struct clocksource *cs)
@@ -211,16 +262,6 @@
 	.shift = 8,
 };
 
-static int __init init_xilinx_timecounter(void)
-{
-	xilinx_cc.mult = div_sc(timer_clock_freq, NSEC_PER_SEC,
-				xilinx_cc.shift);
-
-	timecounter_init(&xilinx_tc, &xilinx_cc, sched_clock());
-
-	return 0;
-}
-
 static struct clocksource clocksource_microblaze = {
 	.name		= "xilinx_clocksource",
 	.rating		= 300,
@@ -229,7 +270,7 @@
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
-static int __init xilinx_clocksource_init(void)
+static int __init xilinx_clocksource_init(unsigned int timer_clock_freq)
 {
 	int ret;
 
@@ -241,27 +282,54 @@
 	}
 
 	/* stop timer1 */
-	write_fn(read_fn(timer_baseaddr + TCSR1) & ~TCSR_ENT,
-		 timer_baseaddr + TCSR1);
+	write_fn(read_fn(clocksource_baseaddr + TCSR0) & ~TCSR_ENT,
+		 clocksource_baseaddr + TCSR0);
 	/* start timer1 - up counting without interrupt */
-	write_fn(TCSR_TINT|TCSR_ENT|TCSR_ARHT, timer_baseaddr + TCSR1);
+	write_fn(TCSR_TINT|TCSR_ENT|TCSR_ARHT, clocksource_baseaddr + TCSR0);
 
 	/* register timecounter - for ftrace support */
-	return init_xilinx_timecounter();
+	xilinx_cc.mult = div_sc(timer_clock_freq, NSEC_PER_SEC,
+				xilinx_cc.shift);
+
+	timecounter_init(&xilinx_tc, &xilinx_cc, sched_clock());
+
+	sched_clock_register(xilinx_clock_read, 32, timer_clock_freq);
+
+	return 0;
 }
 
 static int __init xilinx_timer_init(struct device_node *timer)
 {
 	struct clk *clk;
 	static int initialized;
-	u32 irq;
 	u32 timer_num = 1;
-	int ret;
-
-	if (initialized)
-		return -EINVAL;
+	int ret = 0, cpu_id = 0;
+	void __iomem *timer_baseaddr;
+	unsigned int timer_clock_freq;
+	bool clocksource = false;
+	bool clockevent = false;
+
+	ret = of_property_read_u32(timer, "cpu-id", &cpu_id);
+	if (!ret && NR_CPUS > 1) {
+		/* cpu_id will say if this is clocksource or clockevent */
+		if (cpu_id >= NR_CPUS)
+			clocksource = true;
+		else
+			clockevent = true;
+	} else {
+		/* No cpu_id property continue to work in old style */
+		clocksource = true;
+		clockevent = true;
+	}
 
-	initialized = 1;
+	if (clocksource) {
+		/* TODO Add support for clocksource from one timer only */
+		of_property_read_u32(timer, "xlnx,one-timer-only", &timer_num);
+		if (timer_num) {
+			pr_err("%pOF: Please enable two timers in HW\n", timer);
+			return -EINVAL;
+		}
+	}
 
 	timer_baseaddr = of_iomap(timer, 0);
 	if (!timer_baseaddr) {
@@ -278,20 +346,6 @@
 		read_fn = timer_read32_be;
 	}
 
-	irq = irq_of_parse_and_map(timer, 0);
-	if (irq <= 0) {
-		pr_err("Failed to parse and map irq");
-		return -EINVAL;
-	}
-
-	of_property_read_u32(timer, "xlnx,one-timer-only", &timer_num);
-	if (timer_num) {
-		pr_err("Please enable two timers in HW\n");
-		return -EINVAL;
-	}
-
-	pr_info("%pOF: irq=%d\n", timer, irq);
-
 	clk = of_clk_get(timer, 0);
 	if (IS_ERR(clk)) {
 		pr_err("ERROR: timer CCF input clock not found\n");
@@ -304,28 +358,65 @@
 
 	if (!timer_clock_freq) {
 		pr_err("ERROR: Using CPU clock frequency\n");
-		timer_clock_freq = cpuinfo.cpu_clock_freq;
+		return -EINVAL;
 	}
 
-	freq_div_hz = timer_clock_freq / HZ;
-
-	ret = setup_irq(irq, &timer_irqaction);
-	if (ret) {
-		pr_err("Failed to setup IRQ");
-		return ret;
+	if (clocksource) {
+		if (clocksource_baseaddr) {
+			pr_err("%s: cpu %d has already clocksource timer\n",
+			       __func__, cpu_id);
+			return -EINVAL;
+		}
+
+		/* At this point we know that clocksource timer is second one */
+		clocksource_baseaddr = timer_baseaddr + TCSR1;
+		pr_info("%s: Timer base: 0x%x, Clocksource base: 0x%x\n",
+			__func__, (u32)timer_baseaddr,
+			(u32)clocksource_baseaddr);
+
+		ret = xilinx_clocksource_init(timer_clock_freq);
+		if (ret)
+			return ret;
 	}
 
-	ret = xilinx_clocksource_init();
-	if (ret)
-		return ret;
-
-	ret = xilinx_clockevent_init();
-	if (ret)
-		return ret;
+	if (clockevent) {
+		struct xilinx_timer *timer_st;
 
-	sched_clock_register(xilinx_clock_read, 32, timer_clock_freq);
+		/* Record what we know already */
+		timer_st = per_cpu_ptr(&timer_priv, cpu_id);
+		if (timer_st->timer_baseaddr) {
+			pr_err("%s: cpu %d has already clockevent timer\n",
+			       __func__, cpu_id);
+			return -EINVAL;
+		}
+
+		timer_st->timer_baseaddr = timer_baseaddr;
+
+		timer_st->irq = irq_of_parse_and_map(timer, 0);
+		if (timer_st->irq <= 0) {
+			pr_err("Failed to parse and map irq");
+			return -EINVAL;
+		}
+
+		pr_info("%pOF: irq=%d, cpu_id %d\n",
+			timer, timer_st->irq, cpu_id);
+
+		timer_st->timer_clock_freq = timer_clock_freq;
+
+		timer_st->freq_div_hz = timer_clock_freq / HZ;
+
+		/* Can't call it several times */
+		if (!initialized && !cpu_id) {
+			ret = cpuhp_setup_state(CPUHP_AP_MICROBLAZE_TIMER_STARTING,
+					"clockevents/microblaze/arch_timer:starting",
+					microblaze_timer_starting,
+					microblaze_timer_dying);
+			if (!ret)
+				initialized++;
+		}
+	}
 
-	return 0;
+	return ret;
 }
 
 TIMER_OF_DECLARE(xilinx_timer, "xlnx,xps-timer-1.00.a",
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/kernel/vmlinux.lds.S
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/kernel/vmlinux.lds.S
@@ -11,6 +11,7 @@
 OUTPUT_ARCH(microblaze)
 ENTRY(microblaze_start)
 
+#include <asm/cache.h>
 #include <asm/page.h>
 #include <asm-generic/vmlinux.lds.h>
 #include <asm/thread_info.h>
@@ -46,7 +47,7 @@
 	__fdt_blob : AT(ADDR(__fdt_blob) - LOAD_OFFSET) {
 		_fdt_start = . ;		/* place for fdt blob */
 		*(__fdt_blob) ;			/* Any link-placed DTB */
-	        . = _fdt_start + 0x8000;	/* Pad up to 32kbyte */
+	        . = _fdt_start + 0x10000;	/* Pad up to 64kbyte */
 		_fdt_end = . ;
 	}
 
@@ -89,6 +90,8 @@
 		_KERNEL_SDA_BASE_ = _ssro + (_ssro_size / 2) ;
 	}
 
+	PERCPU_SECTION(L1_CACHE_BYTES)
+
 	. = ALIGN(PAGE_SIZE);
 	__init_begin = .;
 
@@ -117,12 +120,6 @@
 		CON_INITCALL
 	}
 
-	__init_end_before_initramfs = .;
-
-	.init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) {
-		INIT_RAM_FS
-	}
-
 	__init_end = .;
 
 	.bss ALIGN (PAGE_SIZE) : AT(ADDR(.bss) - LOAD_OFFSET) {
@@ -135,6 +132,15 @@
 	}
 	. = ALIGN(PAGE_SIZE);
 	_end = .;
+	/* Add space in TLB mapping for early free pages mapping */
+	. = . + 0x100000; /* CONFIG_LOWMEM_SIZE >> PTE_SHIFT + space */
+
+	_end_tlb_mapping = . ;
+
+	.init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) {
+		INIT_RAM_FS
+	}
+	__initramfs_end = . ;
 
 	DISCARDS
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/mm/consistent.c
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/mm/consistent.c
@@ -35,7 +35,7 @@
  * I have to use dcache values because I can't relate on ram size:
  */
 #ifdef CONFIG_XILINX_UNCACHED_SHADOW
-#define UNCACHED_SHADOW_MASK (cpuinfo.dcache_high - cpuinfo.dcache_base + 1)
+#define UNCACHED_SHADOW_MASK (cpuinfo->dcache_high - cpuinfo->dcache_base + 1)
 #else
 #define UNCACHED_SHADOW_MASK 0
 #endif /* CONFIG_XILINX_UNCACHED_SHADOW */
@@ -43,9 +43,11 @@
 void *uncached_kernel_address(void *ptr)
 {
 	unsigned long addr = (unsigned long)ptr;
+	unsigned int cpu = smp_processor_id();
+	struct cpuinfo *cpuinfo = per_cpu_ptr(&cpu_info, cpu);
 
 	addr |= UNCACHED_SHADOW_MASK;
-	if (addr > cpuinfo.dcache_base && addr < cpuinfo.dcache_high)
+	if (addr > cpuinfo->dcache_base && addr < cpuinfo->dcache_high)
 		pr_warn("ERROR: Your cache coherent area is CACHED!!!\n");
 	return (void *)addr;
 }
@@ -53,6 +55,8 @@
 void *cached_kernel_address(void *ptr)
 {
 	unsigned long addr = (unsigned long)ptr;
+	unsigned int cpu = smp_processor_id();
+	struct cpuinfo *cpuinfo = per_cpu_ptr(&cpu_info, cpu);
 
 	return (void *)(addr & ~UNCACHED_SHADOW_MASK);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/mm/init.c
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/mm/init.c
@@ -7,6 +7,7 @@
  * for more details.
  */
 
+#include <linux/dma-contiguous.h>
 #include <linux/memblock.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -275,11 +276,7 @@
 asmlinkage void __init mmu_init(void)
 {
 	unsigned int kstart, ksize;
-
-	if (!memblock.reserved.cnt) {
-		pr_emerg("Error memory count\n");
-		machine_restart(NULL);
-	}
+	phys_addr_t __maybe_unused size;
 
 	if ((u32) memblock.memory.regions[0].size < 0x400000) {
 		pr_emerg("Memory must be greater than 4MB\n");
@@ -316,10 +313,14 @@
 #if defined(CONFIG_BLK_DEV_INITRD)
 	/* Remove the init RAM disk from the available memory. */
 	if (initrd_start) {
-		unsigned long size;
 		size = initrd_end - initrd_start;
 		memblock_reserve(__virt_to_phys(initrd_start), size);
 	}
+
+	size = __initramfs_end - __initramfs_start;
+	if (size)
+		memblock_reserve((phys_addr_t)__virt_to_phys(__initramfs_start),
+				 size);
 #endif /* CONFIG_BLK_DEV_INITRD */
 
 	/* Initialize the MMU hardware */
@@ -342,6 +343,11 @@
 	/* This will also cause that unflatten device tree will be allocated
 	 * inside 768MB limit */
 	memblock_set_current_limit(memory_start + lowmem_size - 1);
+
+	parse_early_param();
+
+	/* CMA initialization */
+	dma_contiguous_reserve(memory_start + lowmem_size - 1);
 }
 
 /* This is only called until mem_init is done. */
@@ -352,7 +358,8 @@
 	 * because of mem mapping from head.S
 	 */
 	return memblock_alloc_try_nid_raw(PAGE_SIZE, PAGE_SIZE,
-				MEMBLOCK_LOW_LIMIT, memory_start + kernel_tlb,
+				memory_start,
+				(phys_addr_t)__virt_to_phys(_end_tlb_mapping),
 				NUMA_NO_NODE);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/mm/mmu_context.c
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/mm/mmu_context.c
@@ -2,7 +2,11 @@
 /*
  * This file contains the routines for handling the MMU.
  *
- *    Copyright (C) 2007 Xilinx, Inc.  All rights reserved.
+ *    Copyright (C) 2007,2013-2020 Xilinx, Inc.  All rights reserved.
+ *
+ *  Derived from arch/powerpc/mm/mmu_context_nohash.c
+ *    Copyright 2008 Ben Herrenschmidt <benh@kernel.crashing.org>
+ *                IBM Corp.
  *
  *  Derived from arch/ppc/mm/4xx_mmu.c:
  *  -- paulus
@@ -19,47 +23,248 @@
  *    Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
  */
 
+#include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/notifier.h>
+#include <linux/cpu.h>
+#include <linux/slab.h>
 
 #include <asm/tlbflush.h>
 #include <asm/mmu_context.h>
 
-mm_context_t next_mmu_context;
-unsigned long context_map[LAST_CONTEXT / BITS_PER_LONG + 1];
-atomic_t nr_free_contexts;
-struct mm_struct *context_mm[LAST_CONTEXT+1];
+static unsigned int next_context, nr_free_contexts;
+static unsigned long context_map[LAST_CONTEXT / BITS_PER_LONG + 1];
+#ifdef CONFIG_SMP
+static unsigned long stale_map[LAST_CONTEXT / BITS_PER_LONG + 1][NR_CPUS];
+#endif
+static struct mm_struct *context_mm[LAST_CONTEXT + 1];
+static DEFINE_RAW_SPINLOCK(context_lock);
 
 /*
- * Initialize the context management stuff.
+ * Steal a context from a task that has one at the moment.
+ *
+ * This is used when we are running out of available PID numbers
+ * on the processors.
+ *
+ * This isn't an LRU system, it just frees up each context in
+ * turn (sort-of pseudo-random replacement :).  This would be the
+ * place to implement an LRU scheme if anyone were motivated to do it.
+ *
+ * For context stealing, we use a slightly different approach for
+ * SMP and UP. Basically, the UP one is simpler and doesn't use
+ * the stale map as we can just flush the local CPU.
  */
-void __init mmu_context_init(void)
+#ifdef CONFIG_SMP
+static unsigned int steal_context_smp(unsigned int id)
 {
-	/*
-	 * The use of context zero is reserved for the kernel.
-	 * This code assumes FIRST_CONTEXT < 32.
+	struct mm_struct *mm;
+	unsigned int cpu, max;
+
+	max = LAST_CONTEXT - FIRST_CONTEXT;
+
+	/* Attempt to free next_context first and then loop until we manage */
+	while (max--) {
+		/* Pick up the victim mm */
+		mm = context_mm[id];
+
+		/* We have a candidate victim, check if it's active, on SMP
+		 * we cannot steal active contexts
+		 */
+		if (mm->context.active) {
+			id++;
+			if (id > LAST_CONTEXT)
+				id = FIRST_CONTEXT;
+			continue;
+		}
+
+		/* Mark this mm has having no context anymore */
+		mm->context.id = MMU_NO_CONTEXT;
+
+		/* Mark it stale on all CPUs that used this mm. */
+		for_each_cpu(cpu, mm_cpumask(mm)) {
+			__set_bit(id, stale_map[cpu]);
+		}
+		return id;
+	}
+
+	/* This will happen if you have more CPUs than available contexts,
+	 * all we can do here is wait a bit and try again
 	 */
-	context_map[0] = (1 << FIRST_CONTEXT) - 1;
-	next_mmu_context = FIRST_CONTEXT;
-	atomic_set(&nr_free_contexts, LAST_CONTEXT - FIRST_CONTEXT + 1);
+	raw_spin_unlock(&context_lock);
+	cpu_relax();
+	raw_spin_lock(&context_lock);
+
+	/* This will cause the caller to try again */
+	return MMU_NO_CONTEXT;
 }
+#endif  /* CONFIG_SMP */
 
 /*
- * Steal a context from a task that has one at the moment.
- *
- * This isn't an LRU system, it just frees up each context in
- * turn (sort-of pseudo-random replacement :).  This would be the
- * place to implement an LRU scheme if anyone were motivated to do it.
+ * Note that this will also be called on SMP if all other CPUs are
+ * offlined, which means that it may be called for cpu != 0. For
+ * this to work, we somewhat assume that CPUs that are onlined
+ * come up with a fully clean TLB (or are cleaned when offlined)
  */
-void steal_context(void)
+static unsigned int steal_context_up(unsigned int id)
 {
 	struct mm_struct *mm;
+	unsigned int cpu = smp_processor_id();
+
+	/* Pick up the victim mm */
+	mm = context_mm[id];
+
+	pr_debug("[%d] steal context %d from mm @%p\n", cpu, id, mm);
+
+	/* Flush the TLB for that context */
+	local_flush_tlb_mm(mm);
+
+	/* Mark this mm has having no context anymore */
+	mm->context.id = MMU_NO_CONTEXT;
+
+	/* TODO: This clear should ultimately be part of local_flush_tlb_mm */
+#ifdef CONFIG_SMP
+	__clear_bit(id, stale_map[cpu]);
+#endif
+
+	return id;
+}
+
+void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next)
+{
+	unsigned int id;
+#ifdef CONFIG_SMP
+	unsigned int cpu = smp_processor_id();
+#endif
+	unsigned long *map;
+
+	/* No lockless fast path .. yet */
+	raw_spin_lock(&context_lock);
+
+#ifdef CONFIG_SMP
+	/* Mark us active and the previous one not anymore */
+	next->context.active++;
+	if (prev) {
+		WARN_ON(prev->context.active < 1);
+		prev->context.active--;
+	}
 
-	/* free up context `next_mmu_context' */
-	/* if we shouldn't free context 0, don't... */
-	if (next_mmu_context < FIRST_CONTEXT)
-		next_mmu_context = FIRST_CONTEXT;
-	mm = context_mm[next_mmu_context];
-	flush_tlb_mm(mm);
-	destroy_context(mm);
+ again:
+#endif /* CONFIG_SMP */
+
+	/* If we already have a valid assigned context, skip all that */
+	id = next->context.id;
+	if (likely(id != MMU_NO_CONTEXT))
+		goto ctxt_ok;
+
+	/* We really don't have a context, let's try to acquire one */
+	id = next_context;
+	if (id > LAST_CONTEXT)
+		id = FIRST_CONTEXT;
+	map = context_map;
+
+	/* No more free contexts, let's try to steal one */
+	if (nr_free_contexts == 0) {
+#ifdef CONFIG_SMP
+		if (num_online_cpus() > 1) {
+			id = steal_context_smp(id);
+			if (id == MMU_NO_CONTEXT)
+				goto again;
+			goto stolen;
+		}
+#endif /* CONFIG_SMP */
+		id = steal_context_up(id);
+		goto stolen;
+	}
+	nr_free_contexts--;
+
+	/* We know there's at least one free context, try to find it */
+	while (__test_and_set_bit(id, map)) {
+		id = find_next_zero_bit(map, LAST_CONTEXT + 1, id);
+		if (id > LAST_CONTEXT)
+			id = FIRST_CONTEXT;
+	}
+ stolen:
+	next_context = id + 1;
+	context_mm[id] = next;
+	next->context.id = id;
+
+ ctxt_ok:
+
+	/* If that context got marked stale on this CPU, then flush the
+	 * local TLB for it and unmark it before we use it
+	 */
+#ifdef CONFIG_SMP
+	if (test_bit(id, stale_map[cpu])) {
+		local_flush_tlb_mm(next);
+
+		/*
+		 * TODO: This clear should ultimately be part of
+		 * local_flush_tlb_mm
+		 */
+		__clear_bit(id, stale_map[cpu]);
+	}
+#endif
+
+	/* Flick the MMU and release lock */
+	set_context(id, next->pgd);
+	raw_spin_unlock(&context_lock);
+}
+
+/*
+ * Set up the context for a new address space.
+ */
+int init_new_context(struct task_struct *t, struct mm_struct *mm)
+{
+	mm->context.id = MMU_NO_CONTEXT;
+	mm->context.active = 0;
+
+	return 0;
+}
+
+/*
+ * We're finished using the context for an address space.
+ */
+void destroy_context(struct mm_struct *mm)
+{
+	unsigned long flags;
+	unsigned int id;
+
+	if (mm->context.id == MMU_NO_CONTEXT)
+		return;
+
+	WARN_ON(mm->context.active != 0);
+
+	raw_spin_lock_irqsave(&context_lock, flags);
+	id = mm->context.id;
+	if (id != MMU_NO_CONTEXT) {
+		__clear_bit(id, context_map);
+		mm->context.id = MMU_NO_CONTEXT;
+		mm->context.active = 0;
+		context_mm[id] = NULL;
+		nr_free_contexts++;
+	}
+	raw_spin_unlock_irqrestore(&context_lock, flags);
+}
+
+/*
+ * Initialize the context management stuff.
+ */
+void __init mmu_context_init(void)
+{
+	/*
+	 * Mark init_mm as being active on all possible CPUs since
+	 * we'll get called with prev == init_mm the first time
+	 * we schedule on a given CPU
+	 */
+	init_mm.context.active = NR_CPUS;
+
+	/*
+	 * The use of context zero is reserved for the kernel.
+	 * This code assumes FIRST_CONTEXT < 32.
+	 */
+	context_map[0] = (1 << FIRST_CONTEXT) - 1;
+	next_context = FIRST_CONTEXT;
+	nr_free_contexts = LAST_CONTEXT - FIRST_CONTEXT + 1;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/microblaze/pci/pci-common.c
+++ linux-xilinx-zynqmp-5.4.0/arch/microblaze/pci/pci-common.c
@@ -141,7 +141,7 @@
 	return NULL;
 }
 
-void pcibios_set_master(struct pci_dev *dev)
+void __weak pcibios_set_master(struct pci_dev *dev)
 {
 	/* No special bus mastering setup handling */
 }
@@ -559,37 +559,7 @@
  */
 static void pcibios_fixup_resources(struct pci_dev *dev)
 {
-	struct pci_controller *hose = pci_bus_to_host(dev->bus);
-	int i;
-
-	if (!hose) {
-		pr_err("No host bridge for PCI dev %s !\n",
-		       pci_name(dev));
-		return;
-	}
-	for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
-		struct resource *res = dev->resource + i;
-		if (!res->flags)
-			continue;
-		if (res->start == 0) {
-			pr_debug("PCI:%s Resource %d %016llx-%016llx [%x]",
-				 pci_name(dev), i,
-				 (unsigned long long)res->start,
-				 (unsigned long long)res->end,
-				 (unsigned int)res->flags);
-			pr_debug("is unassigned\n");
-			res->end -= res->start;
-			res->start = 0;
-			res->flags |= IORESOURCE_UNSET;
-			continue;
-		}
 
-		pr_debug("PCI:%s Resource %d %016llx-%016llx [%x]\n",
-			 pci_name(dev), i,
-			 (unsigned long long)res->start,
-			 (unsigned long long)res->end,
-			 (unsigned int)res->flags);
-	}
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/Kconfig
@@ -5,6 +5,7 @@
 	select ARCH_32BIT_OFF_T if !64BIT
 	select ARCH_BINFMT_ELF_STATE if MIPS_FP_SUPPORT
 	select ARCH_CLOCKSOURCE_DATA
+	select ARCH_HAS_CPU_FINALIZE_INIT
 	select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
 	select ARCH_HAS_UBSAN_SANITIZE_ALL
 	select ARCH_SUPPORTS_UPROBES
@@ -46,7 +47,8 @@
 	select HAVE_ARCH_TRACEHOOK
 	select HAVE_ARCH_TRANSPARENT_HUGEPAGE if CPU_SUPPORTS_HUGEPAGES
 	select HAVE_ASM_MODVERSIONS
-	select HAVE_EBPF_JIT if (!CPU_MICROMIPS)
+	select HAVE_CBPF_JIT if !64BIT && !CPU_MICROMIPS
+	select HAVE_EBPF_JIT if 64BIT && !CPU_MICROMIPS && TARGET_ISA_REV >= 2
 	select HAVE_CONTEXT_TRACKING
 	select HAVE_COPY_THREAD_TLS
 	select HAVE_C_RECORDMCOUNT
@@ -293,6 +295,9 @@
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_BIG_ENDIAN
 	select SYS_HAS_EARLY_PRINTK
+	select SYS_HAS_CPU_BMIPS32_3300
+	select SYS_HAS_CPU_BMIPS4350
+	select SYS_HAS_CPU_BMIPS4380
 	select SWAP_IO_SPACE
 	select GPIOLIB
 	select HAVE_CLK
@@ -862,6 +867,7 @@
 	select I8253
 	select I8259
 	select ISA
+	select MIPS_L1_CACHE_SHIFT_6
 	select SWAP_IO_SPACE if CPU_BIG_ENDIAN
 	select SYS_HAS_CPU_R4X00
 	select SYS_HAS_CPU_R5000
@@ -1391,6 +1397,7 @@
 	select WEAK_REORDERING_BEYOND_LLSC
 	select MIPS_PGD_C0_CONTEXT
 	select MIPS_L1_CACHE_SHIFT_6
+	select MIPS_FP_SUPPORT
 	select GPIOLIB
 	select SWIOTLB
 	help
@@ -3053,7 +3060,7 @@
 config PGTABLE_LEVELS
 	int
 	default 4 if PAGE_SIZE_4KB && MIPS_VA_BITS_48
-	default 3 if 64BIT && !PAGE_SIZE_64KB
+	default 3 if 64BIT && (!PAGE_SIZE_64KB || MIPS_VA_BITS_48)
 	default 2
 
 config MIPS_AUTO_PFN_OFFSET
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/Makefile
@@ -272,7 +272,7 @@
 ifdef CONFIG_64BIT
   ifndef KBUILD_SYM32
     ifeq ($(shell expr $(load-y) \< 0xffffffff80000000), 0)
-      KBUILD_SYM32 = y
+      KBUILD_SYM32 = $(call cc-option-yn, -msym32)
     endif
   endif
 
@@ -285,12 +285,23 @@
   endif
 endif
 
+# When linking a 32-bit executable the LLVM linker cannot cope with a
+# 32-bit load address that has been sign-extended to 64 bits.  Simply
+# remove the upper 32 bits then, as it is safe to do so with other
+# linkers.
+ifdef CONFIG_64BIT
+	load-ld			= $(load-y)
+else
+	load-ld			= $(subst 0xffffffff,0x,$(load-y))
+endif
+
 KBUILD_AFLAGS	+= $(cflags-y)
 KBUILD_CFLAGS	+= $(cflags-y)
-KBUILD_CPPFLAGS += -DVMLINUX_LOAD_ADDRESS=$(load-y)
+KBUILD_CPPFLAGS += -DVMLINUX_LOAD_ADDRESS=$(load-y) -DLINKER_LOAD_ADDRESS=$(load-ld)
 KBUILD_CPPFLAGS += -DDATAOFFSET=$(if $(dataoffset-y),$(dataoffset-y),0)
 
 bootvars-y	= VMLINUX_LOAD_ADDRESS=$(load-y) \
+		  LINKER_LOAD_ADDRESS=$(load-ld) \
 		  VMLINUX_ENTRY_ADDRESS=$(entry-y) \
 		  PLATFORM="$(platform-y)" \
 		  ITS_INPUTS="$(its-y)"
@@ -309,7 +320,7 @@
 
 ifdef CONFIG_MIPS
 CHECKFLAGS += $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -x c /dev/null | \
-	egrep -vw '__GNUC_(|MINOR_|PATCHLEVEL_)_' | \
+	egrep -vw '__GNUC_(MINOR_|PATCHLEVEL_)?_' | \
 	sed -e "s/^\#define /-D'/" -e "s/ /'='/" -e "s/$$/'/" -e 's/\$$/&&/g')
 endif
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/Makefile.postlink
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/Makefile.postlink
@@ -12,7 +12,7 @@
 include scripts/Kbuild.include
 
 CMD_RELOCS = arch/mips/boot/tools/relocs
-quiet_cmd_relocs = RELOCS $@
+quiet_cmd_relocs = RELOCS  $@
       cmd_relocs = $(CMD_RELOCS) $@
 
 # `@true` prevents complaint when there is nothing to be done
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/alchemy/board-xxs1500.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/alchemy/board-xxs1500.c
@@ -18,6 +18,7 @@
 #include <asm/reboot.h>
 #include <asm/setup.h>
 #include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/gpio-au1000.h>
 #include <prom.h>
 
 const char *get_system_type(void)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/alchemy/common/clock.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/alchemy/common/clock.c
@@ -152,6 +152,7 @@
 {
 	struct clk_init_data id;
 	struct clk_hw *h;
+	struct clk *clk;
 
 	h = kzalloc(sizeof(*h), GFP_KERNEL);
 	if (!h)
@@ -164,7 +165,13 @@
 	id.ops = &alchemy_clkops_cpu;
 	h->init = &id;
 
-	return clk_register(NULL, h);
+	clk = clk_register(NULL, h);
+	if (IS_ERR(clk)) {
+		pr_err("failed to register clock\n");
+		kfree(h);
+	}
+
+	return clk;
 }
 
 /* AUXPLLs ************************************************************/
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/alchemy/devboards/db1000.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/alchemy/devboards/db1000.c
@@ -14,7 +14,6 @@
 #include <linux/interrupt.h>
 #include <linux/leds.h>
 #include <linux/mmc/host.h>
-#include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/pm.h>
 #include <linux/spi/spi.h>
@@ -165,14 +164,10 @@
 
 /******************************************************************************/
 
+#ifdef CONFIG_MMC_AU1X
 static irqreturn_t db1100_mmc_cd(int irq, void *ptr)
 {
-	void (*mmc_cd)(struct mmc_host *, unsigned long);
-	/* link against CONFIG_MMC=m */
-	mmc_cd = symbol_get(mmc_detect_change);
-	mmc_cd(ptr, msecs_to_jiffies(500));
-	symbol_put(mmc_detect_change);
-
+	mmc_detect_change(ptr, msecs_to_jiffies(500));
 	return IRQ_HANDLED;
 }
 
@@ -375,6 +370,7 @@
 	.num_resources	= ARRAY_SIZE(au1100_mmc1_res),
 	.resource	= au1100_mmc1_res,
 };
+#endif /* CONFIG_MMC_AU1X */
 
 /******************************************************************************/
 
@@ -438,8 +434,10 @@
 
 static struct platform_device *db1100_devs[] = {
 	&au1100_lcd_device,
+#ifdef CONFIG_MMC_AU1X
 	&db1100_mmc0_dev,
 	&db1100_mmc1_dev,
+#endif
 };
 
 int __init db1000_dev_setup(void)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/alchemy/devboards/db1200.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/alchemy/devboards/db1200.c
@@ -10,7 +10,6 @@
 #include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <linux/init.h>
-#include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/leds.h>
@@ -327,6 +326,7 @@
 
 /**********************************************************************/
 
+#ifdef CONFIG_MMC_AU1X
 /* SD carddetects:  they're supposed to be edge-triggered, but ack
  * doesn't seem to work (CPLD Rev 2).  Instead, the screaming one
  * is disabled and its counterpart enabled.  The 200ms timeout is
@@ -340,14 +340,7 @@
 
 static irqreturn_t db1200_mmc_cdfn(int irq, void *ptr)
 {
-	void (*mmc_cd)(struct mmc_host *, unsigned long);
-
-	/* link against CONFIG_MMC=m */
-	mmc_cd = symbol_get(mmc_detect_change);
-	if (mmc_cd) {
-		mmc_cd(ptr, msecs_to_jiffies(200));
-		symbol_put(mmc_detect_change);
-	}
+	mmc_detect_change(ptr, msecs_to_jiffies(200));
 
 	msleep(100);	/* debounce */
 	if (irq == DB1200_SD0_INSERT_INT)
@@ -431,14 +424,7 @@
 
 static irqreturn_t pb1200_mmc1_cdfn(int irq, void *ptr)
 {
-	void (*mmc_cd)(struct mmc_host *, unsigned long);
-
-	/* link against CONFIG_MMC=m */
-	mmc_cd = symbol_get(mmc_detect_change);
-	if (mmc_cd) {
-		mmc_cd(ptr, msecs_to_jiffies(200));
-		symbol_put(mmc_detect_change);
-	}
+	mmc_detect_change(ptr, msecs_to_jiffies(200));
 
 	msleep(100);	/* debounce */
 	if (irq == PB1200_SD1_INSERT_INT)
@@ -599,6 +585,7 @@
 	.num_resources	= ARRAY_SIZE(au1200_mmc1_res),
 	.resource	= au1200_mmc1_res,
 };
+#endif /* CONFIG_MMC_AU1X */
 
 /**********************************************************************/
 
@@ -766,7 +753,9 @@
 static struct platform_device *db1200_devs[] __initdata = {
 	NULL,		/* PSC0, selected by S6.8 */
 	&db1200_ide_dev,
+#ifdef CONFIG_MMC_AU1X
 	&db1200_mmc0_dev,
+#endif
 	&au1200_lcd_dev,
 	&db1200_eth_dev,
 	&db1200_nand_dev,
@@ -777,7 +766,9 @@
 };
 
 static struct platform_device *pb1200_devs[] __initdata = {
+#ifdef CONFIG_MMC_AU1X
 	&pb1200_mmc1_dev,
+#endif
 };
 
 /* Some peripheral base addresses differ on the PB1200 */
@@ -856,7 +847,7 @@
 	i2c_register_board_info(0, db1200_i2c_devs,
 				ARRAY_SIZE(db1200_i2c_devs));
 	spi_register_board_info(db1200_spi_devs,
-				ARRAY_SIZE(db1200_i2c_devs));
+				ARRAY_SIZE(db1200_spi_devs));
 
 	/* SWITCHES:	S6.8 I2C/SPI selector  (OFF=I2C	 ON=SPI)
 	 *		S6.7 AC97/I2S selector (OFF=AC97 ON=I2S)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/alchemy/devboards/db1300.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/alchemy/devboards/db1300.c
@@ -17,7 +17,6 @@
 #include <linux/interrupt.h>
 #include <linux/ata_platform.h>
 #include <linux/mmc/host.h>
-#include <linux/module.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/platnand.h>
 #include <linux/platform_device.h>
@@ -451,6 +450,7 @@
 
 /**********************************************************************/
 
+#ifdef CONFIG_MMC_AU1X
 static irqreturn_t db1300_mmc_cd(int irq, void *ptr)
 {
 	disable_irq_nosync(irq);
@@ -459,14 +459,7 @@
 
 static irqreturn_t db1300_mmc_cdfn(int irq, void *ptr)
 {
-	void (*mmc_cd)(struct mmc_host *, unsigned long);
-
-	/* link against CONFIG_MMC=m.  We can only be called once MMC core has
-	 * initialized the controller, so symbol_get() should always succeed.
-	 */
-	mmc_cd = symbol_get(mmc_detect_change);
-	mmc_cd(ptr, msecs_to_jiffies(200));
-	symbol_put(mmc_detect_change);
+	mmc_detect_change(ptr, msecs_to_jiffies(200));
 
 	msleep(100);	/* debounce */
 	if (irq == DB1300_SD1_INSERT_INT)
@@ -640,6 +633,7 @@
 	.resource	= au1300_sd0_res,
 	.num_resources	= ARRAY_SIZE(au1300_sd0_res),
 };
+#endif /* CONFIG_MMC_AU1X */
 
 /**********************************************************************/
 
@@ -777,8 +771,10 @@
 	&db1300_5waysw_dev,
 	&db1300_nand_dev,
 	&db1300_ide_dev,
+#ifdef CONFIG_MMC_AU1X
 	&db1300_sd0_dev,
 	&db1300_sd1_dev,
+#endif
 	&db1300_lcd_dev,
 	&db1300_ac97_dev,
 	&db1300_i2s_dev,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/alchemy/devboards/db1550.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/alchemy/devboards/db1550.c
@@ -588,7 +588,7 @@
 	i2c_register_board_info(0, db1550_i2c_devs,
 				ARRAY_SIZE(db1550_i2c_devs));
 	spi_register_board_info(db1550_spi_devs,
-				ARRAY_SIZE(db1550_i2c_devs));
+				ARRAY_SIZE(db1550_spi_devs));
 
 	c = clk_get(NULL, "psc0_intclk");
 	if (!IS_ERR(c)) {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/bcm47xx/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/bcm47xx/Kconfig
@@ -27,6 +27,7 @@
 	select BCMA
 	select BCMA_HOST_SOC
 	select BCMA_DRIVER_MIPS
+	select BCMA_DRIVER_PCI if PCI
 	select BCMA_DRIVER_PCI_HOSTMODE if PCI
 	select BCMA_DRIVER_GPIO
 	default y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/bcm47xx/prom.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/bcm47xx/prom.c
@@ -85,7 +85,7 @@
 			pr_debug("Assume 128MB RAM\n");
 			break;
 		}
-		if (!memcmp(prom_init, prom_init + mem, 32))
+		if (!memcmp((void *)prom_init, (void *)prom_init + mem, 32))
 			break;
 	}
 	lowmem = mem;
@@ -162,7 +162,7 @@
 
 	off = EXTVBASE + __pa(off);
 	for (extmem = 128 << 20; extmem < 512 << 20; extmem <<= 1) {
-		if (!memcmp(prom_init, (void *)(off + extmem), 16))
+		if (!memcmp((void *)prom_init, (void *)(off + extmem), 16))
 			break;
 	}
 	extmem -= lowmem;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/bcm63xx/clk.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/bcm63xx/clk.c
@@ -361,6 +361,8 @@
  */
 int clk_enable(struct clk *clk)
 {
+	if (!clk)
+		return 0;
 	mutex_lock(&clocks_mutex);
 	clk_enable_unlocked(clk);
 	mutex_unlock(&clocks_mutex);
@@ -381,6 +383,18 @@
 
 EXPORT_SYMBOL(clk_disable);
 
+struct clk *clk_get_parent(struct clk *clk)
+{
+	return NULL;
+}
+EXPORT_SYMBOL(clk_get_parent);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	return 0;
+}
+EXPORT_SYMBOL(clk_set_parent);
+
 unsigned long clk_get_rate(struct clk *clk)
 {
 	if (!clk)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/bmips/dma.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/bmips/dma.c
@@ -64,7 +64,9 @@
 	return dma_addr;
 }
 
-void arch_sync_dma_for_cpu_all(struct device *dev)
+bool bmips_rac_flush_disable;
+
+void arch_sync_dma_for_cpu_all(void)
 {
 	void __iomem *cbr = BMIPS_GET_CBR();
 	u32 cfg;
@@ -74,6 +76,9 @@
 	    boot_cpu_type() != CPU_BMIPS4380)
 		return;
 
+	if (unlikely(bmips_rac_flush_disable))
+		return;
+
 	/* Flush stale data out of the readahead cache */
 	cfg = __raw_readl(cbr + BMIPS_RAC_CONFIG);
 	__raw_writel(cfg | 0x100, cbr + BMIPS_RAC_CONFIG);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/bmips/setup.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/bmips/setup.c
@@ -34,6 +34,8 @@
 #define REG_BCM6328_OTP		((void __iomem *)CKSEG1ADDR(0x1000062c))
 #define BCM6328_TP1_DISABLED	BIT(9)
 
+extern bool bmips_rac_flush_disable;
+
 static const unsigned long kbase = VMLINUX_LOAD_ADDRESS & 0xfff00000;
 
 struct bmips_quirk {
@@ -103,6 +105,13 @@
 	 * disable SMP for now
 	 */
 	bmips_smp_enabled = 0;
+
+	/*
+	 * RAC flush causes kernel panics on BCM6358 when booting from TP1
+	 * because the bootloader is not initializing it properly.
+	 */
+	bmips_rac_flush_disable = !!(read_c0_brcm_cmt_local() & (1 << 31)) ||
+				  !!BMIPS_GET_CBR();
 }
 
 static void bcm6368_quirks(void)
@@ -167,7 +176,7 @@
 		dtb = phys_to_virt(fw_arg2);
 	else if (fw_passed_dtb) /* UHI interface or appended dtb */
 		dtb = (void *)fw_passed_dtb;
-	else if (__dtb_start != __dtb_end)
+	else if (&__dtb_start != &__dtb_end)
 		dtb = (void *)__dtb_start;
 	else
 		panic("no dtb found");
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/boot/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/boot/Makefile
@@ -123,7 +123,7 @@
 targets += vmlinux.its
 targets += vmlinux.gz.its
 targets += vmlinux.bz2.its
-targets += vmlinux.lzmo.its
+targets += vmlinux.lzma.its
 targets += vmlinux.lzo.its
 
 quiet_cmd_cpp_its_S = ITS     $@
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/boot/compressed/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/boot/compressed/Makefile
@@ -29,8 +29,11 @@
 	-DBOOT_HEAP_SIZE=$(BOOT_HEAP_SIZE) \
 	-DKERNEL_ENTRY=$(VMLINUX_ENTRY_ADDRESS)
 
+# Prevents link failures: __sanitizer_cov_trace_pc() is not linked in.
+KCOV_INSTRUMENT		:= n
+
 # decompressor objects (linked with vmlinuz)
-vmlinuzobjs-y := $(obj)/head.o $(obj)/decompress.o $(obj)/string.o
+vmlinuzobjs-y := $(obj)/head.o $(obj)/decompress.o $(obj)/string.o $(obj)/bswapsi.o
 
 ifdef CONFIG_DEBUG_ZBOOT
 vmlinuzobjs-$(CONFIG_DEBUG_ZBOOT)		   += $(obj)/dbg.o
@@ -44,7 +47,7 @@
 $(obj)/uart-ath79.c: $(srctree)/arch/mips/ath79/early_printk.c
 	$(call cmd,shipped)
 
-vmlinuzobjs-$(CONFIG_KERNEL_XZ) += $(obj)/ashldi3.o $(obj)/bswapsi.o
+vmlinuzobjs-$(CONFIG_KERNEL_XZ) += $(obj)/ashldi3.o
 
 extra-y += ashldi3.c
 $(obj)/ashldi3.c: $(obj)/%.c: $(srctree)/lib/%.c FORCE
@@ -87,7 +90,7 @@
 VMLINUZ_LOAD_ADDRESS := $(zload-y)
 else
 VMLINUZ_LOAD_ADDRESS = $(shell $(obj)/calc_vmlinuz_load_addr \
-		$(obj)/vmlinux.bin $(VMLINUX_LOAD_ADDRESS))
+		$(obj)/vmlinux.bin $(LINKER_LOAD_ADDRESS))
 endif
 UIMAGE_LOADADDR = $(VMLINUZ_LOAD_ADDRESS)
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/boot/compressed/decompress.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/boot/compressed/decompress.c
@@ -7,12 +7,15 @@
  * Author: Wu Zhangjin <wuzhangjin@gmail.com>
  */
 
+#define DISABLE_BRANCH_PROFILING
+
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/libfdt.h>
 
 #include <asm/addrspace.h>
+#include <asm/unaligned.h>
 
 /*
  * These two variables specify the free mem region
@@ -113,7 +116,7 @@
 		dtb_size = fdt_totalsize((void *)&__appended_dtb);
 
 		/* last four bytes is always image size in little endian */
-		image_size = le32_to_cpup((void *)&__image_end - 4);
+		image_size = get_unaligned_le32((void *)&__image_end - 4);
 
 		/* copy dtb to where the booted kernel will expect it */
 		memcpy((void *)VMLINUX_LOAD_ADDRESS_ULL + image_size,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/boot/compressed/string.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/boot/compressed/string.c
@@ -5,6 +5,7 @@
  * Very small subset of simple string routines
  */
 
+#include <linux/compiler_attributes.h>
 #include <linux/types.h>
 
 void *memcpy(void *dest, const void *src, size_t n)
@@ -27,3 +28,19 @@
 		ss[i] = c;
 	return s;
 }
+
+void * __weak memmove(void *dest, const void *src, size_t n)
+{
+	unsigned int i;
+	const char *s = src;
+	char *d = dest;
+
+	if ((uintptr_t)dest < (uintptr_t)src) {
+		for (i = 0; i < n; i++)
+			d[i] = s[i];
+	} else {
+		for (i = n; i > 0; i--)
+			d[i - 1] = s[i - 1];
+	}
+	return dest;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/boot/dts/brcm/bcm3368.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/boot/dts/brcm/bcm3368.dtsi
@@ -59,7 +59,7 @@
 
 		periph_cntl: syscon@fff8c008 {
 			compatible = "syscon";
-			reg = <0xfff8c000 0x4>;
+			reg = <0xfff8c008 0x4>;
 			native-endian;
 		};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/boot/dts/brcm/bcm63268.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/boot/dts/brcm/bcm63268.dtsi
@@ -59,7 +59,7 @@
 
 		periph_cntl: syscon@10000008 {
 			compatible = "syscon";
-			reg = <0x10000000 0xc>;
+			reg = <0x10000008 0x4>;
 			native-endian;
 		};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/boot/dts/brcm/bcm6358.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/boot/dts/brcm/bcm6358.dtsi
@@ -59,7 +59,7 @@
 
 		periph_cntl: syscon@fffe0008 {
 			compatible = "syscon";
-			reg = <0xfffe0000 0x4>;
+			reg = <0xfffe0008 0x4>;
 			native-endian;
 		};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/boot/dts/brcm/bcm6362.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/boot/dts/brcm/bcm6362.dtsi
@@ -59,7 +59,7 @@
 
 		periph_cntl: syscon@10000008 {
 			compatible = "syscon";
-			reg = <0x10000000 0xc>;
+			reg = <0x10000008 0x4>;
 			native-endian;
 		};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/boot/dts/brcm/bcm6368.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/boot/dts/brcm/bcm6368.dtsi
@@ -59,7 +59,7 @@
 
 		periph_cntl: syscon@100000008 {
 			compatible = "syscon";
-			reg = <0x10000000 0xc>;
+			reg = <0x10000008 0x4>;
 			native-endian;
 		};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/boot/dts/ingenic/qi_lb60.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/boot/dts/ingenic/qi_lb60.dts
@@ -69,7 +69,7 @@
 			"Speaker", "OUTL",
 			"Speaker", "OUTR",
 			"INL", "LOUT",
-			"INL", "ROUT";
+			"INR", "ROUT";
 
 		simple-audio-card,aux-devs = <&amp>;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/cavium-octeon/executive/cvmx-helper-board.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/cavium-octeon/executive/cvmx-helper-board.c
@@ -211,7 +211,7 @@
 {
 	cvmx_helper_link_info_t result;
 
-	WARN(!octeon_is_simulation(),
+	WARN_ONCE(!octeon_is_simulation(),
 	     "Using deprecated link status - please update your DT");
 
 	/* Unless we fix it later, all links are defaulted to down */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/cavium-octeon/executive/cvmx-helper.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/cavium-octeon/executive/cvmx-helper.c
@@ -1100,7 +1100,7 @@
 		if (index == 0)
 			result = __cvmx_helper_rgmii_link_get(ipd_port);
 		else {
-			WARN(1, "Using deprecated link status - please update your DT");
+			WARN_ONCE(1, "Using deprecated link status - please update your DT");
 			result.s.full_duplex = 1;
 			result.s.link_up = 1;
 			result.s.speed = 1000;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/cavium-octeon/octeon-irq.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/cavium-octeon/octeon-irq.c
@@ -127,6 +127,16 @@
 static int octeon_irq_force_ciu_mapping(struct irq_domain *domain,
 					int irq, int line, int bit)
 {
+	struct device_node *of_node;
+	int ret;
+
+	of_node = irq_domain_get_of_node(domain);
+	if (!of_node)
+		return -EINVAL;
+	ret = irq_alloc_desc_at(irq, of_node_to_nid(of_node));
+	if (ret < 0)
+		return ret;
+
 	return irq_domain_associate(domain, irq, line << 6 | bit);
 }
 
@@ -2199,6 +2209,9 @@
 	}
 
 	cd = kzalloc(sizeof(*cd), GFP_KERNEL);
+	if (!cd)
+		return -ENOMEM;
+
 	cd->host_data = host_data;
 	cd->bit = hw;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/cavium-octeon/octeon-platform.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/cavium-octeon/octeon-platform.c
@@ -86,11 +86,12 @@
 					 "refclk-frequency", &clock_rate);
 		if (i) {
 			dev_err(dev, "No UCTL \"refclk-frequency\"\n");
+			of_node_put(uctl_node);
 			goto exit;
 		}
 		i = of_property_read_string(uctl_node,
 					    "refclk-type", &clock_type);
-
+		of_node_put(uctl_node);
 		if (!i && strcmp("crystal", clock_type) == 0)
 			is_crystal_clock = true;
 	}
@@ -328,6 +329,7 @@
 
 	pd->dev.platform_data = &octeon_ehci_pdata;
 	octeon_ehci_hw_start(&pd->dev);
+	put_device(&pd->dev);
 
 	return ret;
 }
@@ -391,6 +393,7 @@
 
 	pd->dev.platform_data = &octeon_ohci_pdata;
 	octeon_ohci_hw_start(&pd->dev);
+	put_device(&pd->dev);
 
 	return ret;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/cavium-octeon/octeon-usb.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/cavium-octeon/octeon-usb.c
@@ -518,6 +518,7 @@
 
 			res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 			if (res == NULL) {
+				put_device(&pdev->dev);
 				dev_err(&pdev->dev, "No memory resources\n");
 				return -ENXIO;
 			}
@@ -529,8 +530,10 @@
 			 * know the difference.
 			 */
 			base = devm_ioremap_resource(&pdev->dev, res);
-			if (IS_ERR(base))
+			if (IS_ERR(base)) {
+				put_device(&pdev->dev);
 				return PTR_ERR(base);
+			}
 
 			mutex_lock(&dwc3_octeon_clocks_mutex);
 			dwc3_octeon_clocks_start(&pdev->dev, (u64)base);
@@ -541,6 +544,7 @@
 			devm_iounmap(&pdev->dev, base);
 			devm_release_mem_region(&pdev->dev, res->start,
 						resource_size(res));
+			put_device(&pdev->dev);
 		}
 	} while (node != NULL);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/configs/bigsur_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/configs/bigsur_defconfig
@@ -112,7 +112,6 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
 CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_CHR_DEV_SCH=m
 CONFIG_ATA=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/configs/decstation_64_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/configs/decstation_64_defconfig
@@ -53,8 +53,6 @@
 CONFIG_NETWORK_SECMARK=y
 CONFIG_IP_SCTP=m
 CONFIG_VLAN_8021Q=m
-CONFIG_DECNET=m
-CONFIG_DECNET_ROUTER=y
 # CONFIG_WIRELESS is not set
 # CONFIG_UEVENT_HELPER is not set
 # CONFIG_FW_LOADER is not set
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/configs/decstation_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/configs/decstation_defconfig
@@ -49,8 +49,6 @@
 CONFIG_NETWORK_SECMARK=y
 CONFIG_IP_SCTP=m
 CONFIG_VLAN_8021Q=m
-CONFIG_DECNET=m
-CONFIG_DECNET_ROUTER=y
 # CONFIG_WIRELESS is not set
 # CONFIG_UEVENT_HELPER is not set
 # CONFIG_FW_LOADER is not set
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/configs/decstation_r4k_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/configs/decstation_r4k_defconfig
@@ -48,8 +48,6 @@
 CONFIG_NETWORK_SECMARK=y
 CONFIG_IP_SCTP=m
 CONFIG_VLAN_8021Q=m
-CONFIG_DECNET=m
-CONFIG_DECNET_ROUTER=y
 # CONFIG_WIRELESS is not set
 # CONFIG_UEVENT_HELPER is not set
 # CONFIG_FW_LOADER is not set
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/configs/fuloong2e_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/configs/fuloong2e_defconfig
@@ -99,7 +99,6 @@
 CONFIG_ATA_OVER_ETH=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=y
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOWLEVEL is not set
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/configs/gpr_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/configs/gpr_defconfig
@@ -69,7 +69,6 @@
 CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
-CONFIG_DECNET_NF_GRABULATOR=m
 CONFIG_BRIDGE_NF_EBTABLES=m
 CONFIG_BRIDGE_EBT_BROUTE=m
 CONFIG_BRIDGE_EBT_T_FILTER=m
@@ -99,7 +98,6 @@
 CONFIG_ATM_BR2684=m
 CONFIG_BRIDGE=m
 CONFIG_VLAN_8021Q=m
-CONFIG_DECNET=m
 CONFIG_LLC2=m
 CONFIG_ATALK=m
 CONFIG_DEV_APPLETALK=m
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/configs/ip27_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/configs/ip27_defconfig
@@ -99,7 +99,6 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
 CONFIG_BLK_DEV_SR=m
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_CHR_DEV_SCH=m
 CONFIG_SCSI_CONSTANTS=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/configs/ip32_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/configs/ip32_defconfig
@@ -50,7 +50,6 @@
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/configs/jazz_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/configs/jazz_defconfig
@@ -106,7 +106,6 @@
 CONFIG_IP6_NF_TARGET_REJECT=m
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_RAW=m
-CONFIG_DECNET_NF_GRABULATOR=m
 CONFIG_BRIDGE_NF_EBTABLES=m
 CONFIG_BRIDGE_EBT_BROUTE=m
 CONFIG_BRIDGE_EBT_T_FILTER=m
@@ -127,7 +126,6 @@
 CONFIG_BRIDGE_EBT_SNAT=m
 CONFIG_BRIDGE_EBT_LOG=m
 CONFIG_BRIDGE=m
-CONFIG_DECNET=m
 CONFIG_NET_SCHED=y
 CONFIG_NET_SCH_CBQ=m
 CONFIG_NET_SCH_HTB=m
@@ -191,7 +189,6 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_BLK_DEV_SR=m
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_SCAN_ASYNC=y
 CONFIG_SCSI_FC_ATTRS=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/configs/loongson3_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/configs/loongson3_defconfig
@@ -231,7 +231,7 @@
 CONFIG_MEDIA_USB_SUPPORT=y
 CONFIG_USB_VIDEO_CLASS=m
 CONFIG_DRM=y
-CONFIG_DRM_RADEON=y
+CONFIG_DRM_RADEON=m
 CONFIG_FB_RADEON=y
 CONFIG_LCD_CLASS_DEVICE=y
 CONFIG_LCD_PLATFORM=m
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/configs/malta_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/configs/malta_defconfig
@@ -239,7 +239,6 @@
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
 CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/configs/malta_kvm_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/configs/malta_kvm_defconfig
@@ -247,7 +247,6 @@
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
 CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/configs/malta_kvm_guest_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/configs/malta_kvm_guest_defconfig
@@ -245,7 +245,6 @@
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
 CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/configs/maltaup_xpa_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/configs/maltaup_xpa_defconfig
@@ -245,7 +245,6 @@
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
 CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/configs/mtx1_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/configs/mtx1_defconfig
@@ -117,7 +117,6 @@
 CONFIG_IP6_NF_TARGET_REJECT=m
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_RAW=m
-CONFIG_DECNET_NF_GRABULATOR=m
 CONFIG_BRIDGE_NF_EBTABLES=m
 CONFIG_BRIDGE_EBT_BROUTE=m
 CONFIG_BRIDGE_EBT_T_FILTER=m
@@ -147,7 +146,6 @@
 CONFIG_ATM_BR2684=m
 CONFIG_BRIDGE=m
 CONFIG_VLAN_8021Q=m
-CONFIG_DECNET=m
 CONFIG_LLC2=m
 CONFIG_ATALK=m
 CONFIG_DEV_APPLETALK=m
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/configs/nlm_xlp_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/configs/nlm_xlp_defconfig
@@ -200,7 +200,6 @@
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_RAW=m
 CONFIG_IP6_NF_SECURITY=m
-CONFIG_DECNET_NF_GRABULATOR=m
 CONFIG_BRIDGE_NF_EBTABLES=m
 CONFIG_BRIDGE_EBT_BROUTE=m
 CONFIG_BRIDGE_EBT_T_FILTER=m
@@ -234,7 +233,6 @@
 CONFIG_BRIDGE=m
 CONFIG_VLAN_8021Q=m
 CONFIG_VLAN_8021Q_GVRP=y
-CONFIG_DECNET=m
 CONFIG_LLC2=m
 CONFIG_ATALK=m
 CONFIG_DEV_APPLETALK=m
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/configs/nlm_xlr_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/configs/nlm_xlr_defconfig
@@ -198,7 +198,6 @@
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_RAW=m
 CONFIG_IP6_NF_SECURITY=m
-CONFIG_DECNET_NF_GRABULATOR=m
 CONFIG_BRIDGE_NF_EBTABLES=m
 CONFIG_BRIDGE_EBT_BROUTE=m
 CONFIG_BRIDGE_EBT_T_FILTER=m
@@ -232,7 +231,6 @@
 CONFIG_BRIDGE=m
 CONFIG_VLAN_8021Q=m
 CONFIG_VLAN_8021Q_GVRP=y
-CONFIG_DECNET=m
 CONFIG_LLC2=m
 CONFIG_ATALK=m
 CONFIG_DEV_APPLETALK=m
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/configs/rm200_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/configs/rm200_defconfig
@@ -116,7 +116,6 @@
 CONFIG_IP6_NF_TARGET_REJECT=m
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_RAW=m
-CONFIG_DECNET_NF_GRABULATOR=m
 CONFIG_BRIDGE_NF_EBTABLES=m
 CONFIG_BRIDGE_EBT_BROUTE=m
 CONFIG_BRIDGE_EBT_T_FILTER=m
@@ -137,7 +136,6 @@
 CONFIG_BRIDGE_EBT_SNAT=m
 CONFIG_BRIDGE_EBT_LOG=m
 CONFIG_BRIDGE=m
-CONFIG_DECNET=m
 CONFIG_NET_SCHED=y
 CONFIG_NET_SCH_CBQ=m
 CONFIG_NET_SCH_HTB=m
@@ -203,7 +201,6 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_BLK_DEV_SR=m
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_SCAN_ASYNC=y
 CONFIG_SCSI_FC_ATTRS=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/dec/int-handler.S
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/dec/int-handler.S
@@ -131,7 +131,7 @@
 		 */
 		mfc0	t0,CP0_CAUSE		# get pending interrupts
 		mfc0	t1,CP0_STATUS
-#ifdef CONFIG_32BIT
+#if defined(CONFIG_32BIT) && defined(CONFIG_MIPS_FP_SUPPORT)
 		lw	t2,cpu_fpu_mask
 #endif
 		andi	t0,ST0_IM		# CAUSE.CE may be non-zero!
@@ -139,7 +139,7 @@
 
 		beqz	t0,spurious
 
-#ifdef CONFIG_32BIT
+#if defined(CONFIG_32BIT) && defined(CONFIG_MIPS_FP_SUPPORT)
 		 and	t2,t0
 		bnez	t2,fpu			# handle FPU immediately
 #endif
@@ -280,7 +280,7 @@
 		j	dec_irq_dispatch
 		 nop
 
-#ifdef CONFIG_32BIT
+#if defined(CONFIG_32BIT) && defined(CONFIG_MIPS_FP_SUPPORT)
 fpu:
 		lw	t0,fpu_kstat_irq
 		nop
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/dec/prom/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/dec/prom/Makefile
@@ -6,4 +6,4 @@
 
 lib-y			+= init.o memory.o cmdline.o identify.o console.o
 
-lib-$(CONFIG_32BIT)	+= locore.o
+lib-$(CONFIG_CPU_R3000)	+= locore.o
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/dec/setup.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/dec/setup.c
@@ -6,7 +6,7 @@
  * for more details.
  *
  * Copyright (C) 1998 Harald Koerfgen
- * Copyright (C) 2000, 2001, 2002, 2003, 2005  Maciej W. Rozycki
+ * Copyright (C) 2000, 2001, 2002, 2003, 2005, 2020  Maciej W. Rozycki
  */
 #include <linux/console.h>
 #include <linux/export.h>
@@ -15,6 +15,7 @@
 #include <linux/ioport.h>
 #include <linux/irq.h>
 #include <linux/irqnr.h>
+#include <linux/memblock.h>
 #include <linux/param.h>
 #include <linux/percpu-defs.h>
 #include <linux/sched.h>
@@ -22,6 +23,7 @@
 #include <linux/types.h>
 #include <linux/pm.h>
 
+#include <asm/addrspace.h>
 #include <asm/bootinfo.h>
 #include <asm/cpu.h>
 #include <asm/cpu-features.h>
@@ -29,7 +31,9 @@
 #include <asm/irq.h>
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
+#include <asm/page.h>
 #include <asm/reboot.h>
+#include <asm/sections.h>
 #include <asm/time.h>
 #include <asm/traps.h>
 #include <asm/wbflush.h>
@@ -166,6 +170,9 @@
 
 	ioport_resource.start = ~0UL;
 	ioport_resource.end = 0UL;
+
+	/* Stay away from the firmware working memory area for now. */
+	memblock_reserve(PHYS_OFFSET, __pa_symbol(&_text) - PHYS_OFFSET);
 }
 
 /*
@@ -759,7 +766,8 @@
 		dec_interrupt[DEC_IRQ_HALT] = -1;
 
 	/* Register board interrupts: FPU and cascade. */
-	if (dec_interrupt[DEC_IRQ_FPU] >= 0 && cpu_has_fpu) {
+	if (IS_ENABLED(CONFIG_MIPS_FP_SUPPORT) &&
+	    dec_interrupt[DEC_IRQ_FPU] >= 0 && cpu_has_fpu) {
 		struct irq_desc *desc_fpu;
 		int irq_fpu;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/fw/lib/cmdline.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/fw/lib/cmdline.c
@@ -51,7 +51,7 @@
 {
 	char *result = NULL;
 
-	if (_fw_envp != NULL) {
+	if (_fw_envp != NULL && fw_envp(0) != NULL) {
 		/*
 		 * Return a pointer to the given environment variable.
 		 * YAMON uses "name", "value" pairs, while U-Boot uses
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/generic/board-boston.its.S
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/generic/board-boston.its.S
@@ -1,22 +1,22 @@
 / {
 	images {
-		fdt@boston {
+		fdt-boston {
 			description = "img,boston Device Tree";
 			data = /incbin/("boot/dts/img/boston.dtb");
 			type = "flat_dt";
 			arch = "mips";
 			compression = "none";
-			hash@0 {
+			hash {
 				algo = "sha1";
 			};
 		};
 	};
 
 	configurations {
-		conf@boston {
+		conf-boston {
 			description = "Boston Linux kernel";
-			kernel = "kernel@0";
-			fdt = "fdt@boston";
+			kernel = "kernel";
+			fdt = "fdt-boston";
 		};
 	};
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/generic/board-ni169445.its.S
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/generic/board-ni169445.its.S
@@ -1,22 +1,22 @@
 / {
 	images {
-		fdt@ni169445 {
+		fdt-ni169445 {
 			description = "NI 169445 device tree";
 			data = /incbin/("boot/dts/ni/169445.dtb");
 			type = "flat_dt";
 			arch = "mips";
 			compression = "none";
-			hash@0 {
+			hash {
 				algo = "sha1";
 			};
 		};
 	};
 
 	configurations {
-		conf@ni169445 {
+		conf-ni169445 {
 			description = "NI 169445 Linux Kernel";
-			kernel = "kernel@0";
-			fdt = "fdt@ni169445";
+			kernel = "kernel";
+			fdt = "fdt-ni169445";
 		};
 	};
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/generic/board-ocelot.its.S
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/generic/board-ocelot.its.S
@@ -1,40 +1,40 @@
 /* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
 / {
 	images {
-		fdt@ocelot_pcb123 {
+		fdt-ocelot_pcb123 {
 			description = "MSCC Ocelot PCB123 Device Tree";
 			data = /incbin/("boot/dts/mscc/ocelot_pcb123.dtb");
 			type = "flat_dt";
 			arch = "mips";
 			compression = "none";
-			hash@0 {
+			hash {
 				algo = "sha1";
 			};
 		};
 
-		fdt@ocelot_pcb120 {
+		fdt-ocelot_pcb120 {
 			description = "MSCC Ocelot PCB120 Device Tree";
 			data = /incbin/("boot/dts/mscc/ocelot_pcb120.dtb");
 			type = "flat_dt";
 			arch = "mips";
 			compression = "none";
-			hash@0 {
+			hash {
 				algo = "sha1";
 			};
 		};
 	};
 
 	configurations {
-		conf@ocelot_pcb123 {
+		conf-ocelot_pcb123 {
 			description = "Ocelot Linux kernel";
-			kernel = "kernel@0";
-			fdt = "fdt@ocelot_pcb123";
+			kernel = "kernel";
+			fdt = "fdt-ocelot_pcb123";
 		};
 
-		conf@ocelot_pcb120 {
+		conf-ocelot_pcb120 {
 			description = "Ocelot Linux kernel";
-			kernel = "kernel@0";
-			fdt = "fdt@ocelot_pcb120";
+			kernel = "kernel";
+			fdt = "fdt-ocelot_pcb120";
 		};
 	};
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/generic/board-xilfpga.its.S
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/generic/board-xilfpga.its.S
@@ -1,22 +1,22 @@
 / {
 	images {
-		fdt@xilfpga {
+		fdt-xilfpga {
 			description = "MIPSfpga (xilfpga) Device Tree";
 			data = /incbin/("boot/dts/xilfpga/nexys4ddr.dtb");
 			type = "flat_dt";
 			arch = "mips";
 			compression = "none";
-			hash@0 {
+			hash {
 				algo = "sha1";
 			};
 		};
 	};
 
 	configurations {
-		conf@xilfpga {
+		conf-xilfpga {
 			description = "MIPSfpga Linux kernel";
-			kernel = "kernel@0";
-			fdt = "fdt@xilfpga";
+			kernel = "kernel";
+			fdt = "fdt-xilfpga";
 		};
 	};
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/generic/vmlinux.its.S
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/generic/vmlinux.its.S
@@ -6,7 +6,7 @@
 	#address-cells = <ADDR_CELLS>;
 
 	images {
-		kernel@0 {
+		kernel {
 			description = KERNEL_NAME;
 			data = /incbin/(VMLINUX_BINARY);
 			type = "kernel";
@@ -15,18 +15,18 @@
 			compression = VMLINUX_COMPRESSION;
 			load = /bits/ ADDR_BITS <VMLINUX_LOAD_ADDRESS>;
 			entry = /bits/ ADDR_BITS <VMLINUX_ENTRY_ADDRESS>;
-			hash@0 {
+			hash {
 				algo = "sha1";
 			};
 		};
 	};
 
 	configurations {
-		default = "conf@default";
+		default = "conf-default";
 
-		conf@default {
+		conf-default {
 			description = "Generic Linux kernel";
-			kernel = "kernel@0";
+			kernel = "kernel";
 		};
 	};
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/generic/yamon-dt.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/generic/yamon-dt.c
@@ -75,7 +75,7 @@
 __init int yamon_dt_append_memory(void *fdt,
 				  const struct yamon_mem_region *regions)
 {
-	unsigned long phys_memsize, memsize;
+	unsigned long phys_memsize = 0, memsize;
 	__be32 mem_array[2 * MAX_MEM_ARRAY_ENTRIES];
 	unsigned int mem_entries;
 	int i, err, mem_off;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/include/asm/Kbuild
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/include/asm/Kbuild
@@ -6,14 +6,12 @@
 generated-y += syscall_table_64_o32.h
 generic-y += current.h
 generic-y += device.h
-generic-y += dma-contiguous.h
 generic-y += emergency-restart.h
 generic-y += export.h
 generic-y += irq_work.h
 generic-y += local64.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
-generic-y += msi.h
 generic-y += parport.h
 generic-y += percpu.h
 generic-y += preempt.h
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/include/asm/asm.h
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/include/asm/asm.h
@@ -20,10 +20,27 @@
 #include <asm/sgidefs.h>
 #include <asm/asm-eva.h>
 
+#ifndef __VDSO__
+/*
+ * Emit CFI data in .debug_frame sections, not .eh_frame sections.
+ * We don't do DWARF unwinding at runtime, so only the offline DWARF
+ * information is useful to anyone. Note we should change this if we
+ * ever decide to enable DWARF unwinding at runtime.
+ */
+#define CFI_SECTIONS	.cfi_sections .debug_frame
+#else
+ /*
+  * For the vDSO, emit both runtime unwind information and debug
+  * symbols for the .dbg file.
+  */
+#define CFI_SECTIONS
+#endif
+
 /*
  * LEAF - declare leaf routine
  */
 #define LEAF(symbol)					\
+		CFI_SECTIONS;				\
 		.globl	symbol;				\
 		.align	2;				\
 		.type	symbol, @function;		\
@@ -36,6 +53,7 @@
  * NESTED - declare nested routine entry point
  */
 #define NESTED(symbol, framesize, rpc)			\
+		CFI_SECTIONS;				\
 		.globl	symbol;				\
 		.align	2;				\
 		.type	symbol, @function;		\
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/include/asm/bugs.h
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/include/asm/bugs.h
@@ -1,17 +1,11 @@
 /* SPDX-License-Identifier: GPL-2.0 */
 /*
- * This is included by init/main.c to check for architecture-dependent bugs.
- *
  * Copyright (C) 2007  Maciej W. Rozycki
- *
- * Needs:
- *	void check_bugs(void);
  */
 #ifndef _ASM_BUGS_H
 #define _ASM_BUGS_H
 
 #include <linux/bug.h>
-#include <linux/delay.h>
 #include <linux/smp.h>
 
 #include <asm/cpu.h>
@@ -31,17 +25,6 @@
 #endif
 }
 
-static inline void check_bugs(void)
-{
-	unsigned int cpu = smp_processor_id();
-
-	cpu_data[cpu].udelay_val = loops_per_jiffy;
-	check_bugs32();
-#ifdef CONFIG_64BIT
-	check_bugs64();
-#endif
-}
-
 static inline int r4k_daddiu_bug(void)
 {
 #ifdef CONFIG_64BIT
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/include/asm/checksum.h
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/include/asm/checksum.h
@@ -276,7 +276,8 @@
 	"	.set	pop"
 	: "=&r" (sum), "=&r" (tmp)
 	: "r" (saddr), "r" (daddr),
-	  "0" (htonl(len)), "r" (htonl(proto)), "r" (sum));
+	  "0" (htonl(len)), "r" (htonl(proto)), "r" (sum)
+	: "memory");
 
 	return csum_fold(sum);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/include/asm/cmpxchg.h
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/include/asm/cmpxchg.h
@@ -239,6 +239,7 @@
 	"	.set	" MIPS_ISA_ARCH_LEVEL "		\n"
 	/* Load 64 bits from ptr */
 	"1:	lld	%L0, %3		# __cmpxchg64	\n"
+	"	.set	pop				\n"
 	/*
 	 * Split the 64 bit value we loaded into the 2 registers that hold the
 	 * ret variable.
@@ -266,6 +267,8 @@
 	"	or	%L1, %L1, $at			\n"
 	"	.set	at				\n"
 #  endif
+	"	.set	push				\n"
+	"	.set	" MIPS_ISA_ARCH_LEVEL "		\n"
 	/* Attempt to store new at ptr */
 	"	scd	%L1, %2				\n"
 	/* If we failed, loop! */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/include/asm/cpu-features.h
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/include/asm/cpu-features.h
@@ -124,7 +124,24 @@
 #define cpu_has_tx39_cache	__opt(MIPS_CPU_TX39_CACHE)
 #endif
 #ifndef cpu_has_octeon_cache
-#define cpu_has_octeon_cache	0
+#define cpu_has_octeon_cache						\
+({									\
+	int __res;							\
+									\
+	switch (boot_cpu_type()) {					\
+	case CPU_CAVIUM_OCTEON:						\
+	case CPU_CAVIUM_OCTEON_PLUS:					\
+	case CPU_CAVIUM_OCTEON2:					\
+	case CPU_CAVIUM_OCTEON3:					\
+		__res = 1;						\
+		break;							\
+									\
+	default:							\
+		__res = 0;						\
+	}								\
+									\
+	__res;								\
+})
 #endif
 /* Don't override `cpu_has_fpu' to 1 or the "nofpu" option won't work.  */
 #ifndef cpu_has_fpu
@@ -288,10 +305,12 @@
 # define cpu_has_mips32r6	__isa_ge_or_flag(6, MIPS_CPU_ISA_M32R6)
 #endif
 #ifndef cpu_has_mips64r1
-# define cpu_has_mips64r1	__isa_range_or_flag(1, 6, MIPS_CPU_ISA_M64R1)
+# define cpu_has_mips64r1	(cpu_has_64bits && \
+				 __isa_range_or_flag(1, 6, MIPS_CPU_ISA_M64R1))
 #endif
 #ifndef cpu_has_mips64r2
-# define cpu_has_mips64r2	__isa_range_or_flag(2, 6, MIPS_CPU_ISA_M64R2)
+# define cpu_has_mips64r2	(cpu_has_64bits && \
+				 __isa_range_or_flag(2, 6, MIPS_CPU_ISA_M64R2))
 #endif
 #ifndef cpu_has_mips64r6
 # define cpu_has_mips64r6	__isa_ge_and_flag(6, MIPS_CPU_ISA_M64R6)
@@ -339,7 +358,7 @@
 ({									\
 	int __res;							\
 									\
-	switch (current_cpu_type()) {					\
+	switch (boot_cpu_type()) {					\
 	case CPU_M14KC:							\
 	case CPU_74K:							\
 	case CPU_1074K:							\
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/include/asm/cpu-type.h
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/include/asm/cpu-type.h
@@ -47,6 +47,7 @@
 	case CPU_34K:
 	case CPU_1004K:
 	case CPU_74K:
+	case CPU_1074K:
 	case CPU_M14KC:
 	case CPU_M14KEC:
 	case CPU_INTERAPTIV:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/include/asm/dec/prom.h
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/include/asm/dec/prom.h
@@ -43,16 +43,11 @@
  */
 #define REX_PROM_MAGIC		0x30464354
 
-#ifdef CONFIG_64BIT
-
-#define prom_is_rex(magic)	1	/* KN04 and KN05 are REX PROMs.  */
-
-#else /* !CONFIG_64BIT */
-
-#define prom_is_rex(magic)	((magic) == REX_PROM_MAGIC)
-
-#endif /* !CONFIG_64BIT */
-
+/* KN04 and KN05 are REX PROMs, so only do the check for R3k systems.  */
+static inline bool prom_is_rex(u32 magic)
+{
+	return !IS_ENABLED(CONFIG_CPU_R3000) || magic == REX_PROM_MAGIC;
+}
 
 /*
  * 3MIN/MAXINE PROM entry points for DS5000/1xx's, DS5000/xx's and
@@ -75,7 +70,7 @@
  */
 typedef struct {
 	int pagesize;
-	unsigned char bitmap[0];
+	unsigned char bitmap[];
 } memmap;
 
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/include/asm/div64.h
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/include/asm/div64.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2000, 2004  Maciej W. Rozycki
+ * Copyright (C) 2000, 2004, 2021  Maciej W. Rozycki
  * Copyright (C) 2003, 07 Ralf Baechle (ralf@linux-mips.org)
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -9,25 +9,18 @@
 #ifndef __ASM_DIV64_H
 #define __ASM_DIV64_H
 
-#include <asm-generic/div64.h>
-
-#if BITS_PER_LONG == 64
+#include <asm/bitsperlong.h>
 
-#include <linux/types.h>
+#if BITS_PER_LONG == 32
 
 /*
  * No traps on overflows for any of these...
  */
 
-#define __div64_32(n, base)						\
-({									\
+#define do_div64_32(res, high, low, base) ({				\
 	unsigned long __cf, __tmp, __tmp2, __i;				\
 	unsigned long __quot32, __mod32;				\
-	unsigned long __high, __low;					\
-	unsigned long long __n;						\
 									\
-	__high = *__n >> 32;						\
-	__low = __n;							\
 	__asm__(							\
 	"	.set	push					\n"	\
 	"	.set	noat					\n"	\
@@ -51,18 +44,48 @@
 	"	subu	%0, %0, %z6				\n"	\
 	"	addiu	%2, %2, 1				\n"	\
 	"3:							\n"	\
-	"	bnez	%4, 0b\n\t"					\
-	"	 srl	%5, %1, 0x1f\n\t"				\
+	"	bnez	%4, 0b					\n"	\
+	"	 srl	%5, %1, 0x1f				\n"	\
 	"	.set	pop"						\
 	: "=&r" (__mod32), "=&r" (__tmp),				\
 	  "=&r" (__quot32), "=&r" (__cf),				\
 	  "=&r" (__i), "=&r" (__tmp2)					\
-	: "Jr" (base), "0" (__high), "1" (__low));			\
+	: "Jr" (base), "0" (high), "1" (low));				\
 									\
-	(__n) = __quot32;						\
+	(res) = __quot32;						\
 	__mod32;							\
 })
 
-#endif /* BITS_PER_LONG == 64 */
+#define __div64_32(n, base) ({						\
+	unsigned long __upper, __low, __high, __radix;			\
+	unsigned long long __quot;					\
+	unsigned long long __div;					\
+	unsigned long __mod;						\
+									\
+	__div = (*n);							\
+	__radix = (base);						\
+									\
+	__high = __div >> 32;						\
+	__low = __div;							\
+									\
+	if (__high < __radix) {						\
+		__upper = __high;					\
+		__high = 0;						\
+	} else {							\
+		__upper = __high % __radix;				\
+		__high /= __radix;					\
+	}								\
+									\
+	__mod = do_div64_32(__low, __upper, __low, __radix);		\
+									\
+	__quot = __high;						\
+	__quot = __quot << 32 | __low;					\
+	(*n) = __quot;							\
+	__mod;								\
+})
+
+#endif /* BITS_PER_LONG == 32 */
+
+#include <asm-generic/div64.h>
 
 #endif /* __ASM_DIV64_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/include/asm/fw/fw.h
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/include/asm/fw/fw.h
@@ -26,6 +26,6 @@
 extern void fw_meminit(void);
 extern char *fw_getenv(char *name);
 extern unsigned long fw_getenvl(char *name);
-extern void fw_init_early_console(char port);
+extern void fw_init_early_console(void);
 
 #endif /* __ASM_FW_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/include/asm/highmem.h
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/include/asm/highmem.h
@@ -36,7 +36,7 @@
  * easily, subsequent pte tables have to be allocated in one physical
  * chunk of RAM.
  */
-#ifdef CONFIG_PHYS_ADDR_T_64BIT
+#if defined(CONFIG_PHYS_ADDR_T_64BIT) || defined(CONFIG_MIPS_HUGE_TLB_SUPPORT)
 #define LAST_PKMAP 512
 #else
 #define LAST_PKMAP 1024
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/include/asm/hugetlb.h
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/include/asm/hugetlb.h
@@ -53,7 +53,13 @@
 static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
 					 unsigned long addr, pte_t *ptep)
 {
-	flush_tlb_page(vma, addr & huge_page_mask(hstate_vma(vma)));
+	/*
+	 * clear the huge pte entry firstly, so that the other smp threads will
+	 * not get old pte entry after finishing flush_tlb_page and before
+	 * setting new huge pte entry
+	 */
+	huge_ptep_get_and_clear(vma->vm_mm, addr, ptep);
+	flush_tlb_page(vma, addr);
 }
 
 #define __HAVE_ARCH_HUGE_PTE_NONE
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/include/asm/kvm_host.h
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/include/asm/kvm_host.h
@@ -274,8 +274,12 @@
 #define MIPS3_PG_SHIFT		6
 #define MIPS3_PG_FRAME		0x3fffffc0
 
+#if defined(CONFIG_64BIT)
+#define VPN2_MASK		GENMASK(cpu_vmbits - 1, 13)
+#else
 #define VPN2_MASK		0xffffe000
-#define KVM_ENTRYHI_ASID	MIPS_ENTRYHI_ASID
+#endif
+#define KVM_ENTRYHI_ASID	cpu_asid_mask(&boot_cpu_data)
 #define TLB_IS_GLOBAL(x)	((x).tlb_lo[0] & (x).tlb_lo[1] & ENTRYLO_G)
 #define TLB_VPN2(x)		((x).tlb_hi & VPN2_MASK)
 #define TLB_ASID(x)		((x).tlb_hi & KVM_ENTRYHI_ASID)
@@ -935,7 +939,7 @@
 
 #define KVM_ARCH_WANT_MMU_NOTIFIER
 int kvm_unmap_hva_range(struct kvm *kvm,
-			unsigned long start, unsigned long end);
+			unsigned long start, unsigned long end, unsigned flags);
 int kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte);
 int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end);
 int kvm_test_age_hva(struct kvm *kvm, unsigned long hva);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/include/asm/mach-ip27/cpu-feature-overrides.h
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/include/asm/mach-ip27/cpu-feature-overrides.h
@@ -28,7 +28,6 @@
 #define cpu_has_6k_cache		0
 #define cpu_has_8k_cache		0
 #define cpu_has_tx39_cache		0
-#define cpu_has_fpu			1
 #define cpu_has_nofpuex			0
 #define cpu_has_32fpr			1
 #define cpu_has_counter			1
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/include/asm/mach-rc32434/pci.h
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/include/asm/mach-rc32434/pci.h
@@ -377,7 +377,7 @@
 				 PCI_CFG04_STAT_SSE | \
 				 PCI_CFG04_STAT_PE)
 
-#define KORINA_CNFG1		((KORINA_STAT<<16)|KORINA_CMD)
+#define KORINA_CNFG1		(KORINA_STAT | KORINA_CMD)
 
 #define KORINA_REVID		0
 #define KORINA_CLASS_CODE	0
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/include/asm/mips-cm.h
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/include/asm/mips-cm.h
@@ -11,6 +11,7 @@
 #ifndef __MIPS_ASM_MIPS_CM_H__
 #define __MIPS_ASM_MIPS_CM_H__
 
+#include <linux/bitfield.h>
 #include <linux/bitops.h>
 #include <linux/errno.h>
 
@@ -153,8 +154,8 @@
 #define CM_GCR_REV_MINOR			GENMASK(7, 0)
 
 #define CM_ENCODE_REV(major, minor) \
-		(((major) << __ffs(CM_GCR_REV_MAJOR)) | \
-		 ((minor) << __ffs(CM_GCR_REV_MINOR)))
+		(FIELD_PREP(CM_GCR_REV_MAJOR, major) | \
+		 FIELD_PREP(CM_GCR_REV_MINOR, minor))
 
 #define CM_REV_CM2				CM_ENCODE_REV(6, 0)
 #define CM_REV_CM2_5				CM_ENCODE_REV(7, 0)
@@ -227,6 +228,10 @@
 GCR_ACCESSOR_RO(32, 0x0f0, cpc_status)
 #define CM_GCR_CPC_STATUS_EX			BIT(0)
 
+/* GCR_ACCESS - Controls core/IOCU access to GCRs */
+GCR_ACCESSOR_RW(32, 0x120, access_cm3)
+#define CM_GCR_ACCESS_ACCESSEN			GENMASK(7, 0)
+
 /* GCR_L2_CONFIG - Indicates L2 cache configuration when Config5.L2C=1 */
 GCR_ACCESSOR_RW(32, 0x130, l2_config)
 #define CM_GCR_L2_CONFIG_BYPASS			BIT(20)
@@ -362,10 +367,10 @@
 static inline unsigned int mips_cm_max_vp_width(void)
 {
 	extern int smp_num_siblings;
-	uint32_t cfg;
 
 	if (mips_cm_revision() >= CM_REV_CM3)
-		return read_gcr_sys_config2() & CM_GCR_SYS_CONFIG2_MAXVPW;
+		return FIELD_GET(CM_GCR_SYS_CONFIG2_MAXVPW,
+				 read_gcr_sys_config2());
 
 	if (mips_cm_present()) {
 		/*
@@ -373,8 +378,7 @@
 		 * number of VP(E)s, and if that ever changes then this will
 		 * need revisiting.
 		 */
-		cfg = read_gcr_cl_config() & CM_GCR_Cx_CONFIG_PVPE;
-		return (cfg >> __ffs(CM_GCR_Cx_CONFIG_PVPE)) + 1;
+		return FIELD_GET(CM_GCR_Cx_CONFIG_PVPE, read_gcr_cl_config()) + 1;
 	}
 
 	if (IS_ENABLED(CONFIG_SMP))
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/include/asm/mipsregs.h
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/include/asm/mipsregs.h
@@ -750,7 +750,7 @@
 
 /* MAAR bit definitions */
 #define MIPS_MAAR_VH		(_U64CAST_(1) << 63)
-#define MIPS_MAAR_ADDR		((BIT_ULL(BITS_PER_LONG - 12) - 1) << 12)
+#define MIPS_MAAR_ADDR		GENMASK_ULL(55, 12)
 #define MIPS_MAAR_ADDR_SHIFT	12
 #define MIPS_MAAR_S		(_ULCAST_(1) << 1)
 #define MIPS_MAAR_VL		(_ULCAST_(1) << 0)
@@ -2007,7 +2007,7 @@
 ({ int __res;								\
 	__asm__ __volatile__(						\
 		".set\tpush\n\t"					\
-		".set\tmips32r2\n\t"					\
+		".set\tmips32r5\n\t"					\
 		_ASM_SET_VIRT						\
 		"mfgc0\t%0, " #source ", %1\n\t"			\
 		".set\tpop"						\
@@ -2020,7 +2020,7 @@
 ({ unsigned long long __res;						\
 	__asm__ __volatile__(						\
 		".set\tpush\n\t"					\
-		".set\tmips64r2\n\t"					\
+		".set\tmips64r5\n\t"					\
 		_ASM_SET_VIRT						\
 		"dmfgc0\t%0, " #source ", %1\n\t"			\
 		".set\tpop"						\
@@ -2033,7 +2033,7 @@
 do {									\
 	__asm__ __volatile__(						\
 		".set\tpush\n\t"					\
-		".set\tmips32r2\n\t"					\
+		".set\tmips32r5\n\t"					\
 		_ASM_SET_VIRT						\
 		"mtgc0\t%z0, " #register ", %1\n\t"			\
 		".set\tpop"						\
@@ -2045,7 +2045,7 @@
 do {									\
 	__asm__ __volatile__(						\
 		".set\tpush\n\t"					\
-		".set\tmips64r2\n\t"					\
+		".set\tmips64r5\n\t"					\
 		_ASM_SET_VIRT						\
 		"dmtgc0\t%z0, " #register ", %1\n\t"			\
 		".set\tpop"						\
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/include/asm/mmzone.h
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/include/asm/mmzone.h
@@ -20,10 +20,4 @@
 #define nid_to_addrbase(nid) 0
 #endif
 
-#ifdef CONFIG_DISCONTIGMEM
-
-#define pfn_to_nid(pfn)		pa_to_nid((pfn) << PAGE_SHIFT)
-
-#endif /* CONFIG_DISCONTIGMEM */
-
 #endif /* _ASM_MMZONE_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/include/asm/octeon/cvmx-bootinfo.h
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/include/asm/octeon/cvmx-bootinfo.h
@@ -315,7 +315,7 @@
 
 /* Functions to return string based on type */
 #define ENUM_BRD_TYPE_CASE(x) \
-	case x: return(#x + 16);	/* Skip CVMX_BOARD_TYPE_ */
+	case x: return (&#x[16]);	/* Skip CVMX_BOARD_TYPE_ */
 static inline const char *cvmx_board_type_to_string(enum
 						    cvmx_board_types_enum type)
 {
@@ -404,7 +404,7 @@
 }
 
 #define ENUM_CHIP_TYPE_CASE(x) \
-	case x: return(#x + 15);	/* Skip CVMX_CHIP_TYPE */
+	case x: return (&#x[15]);	/* Skip CVMX_CHIP_TYPE */
 static inline const char *cvmx_chip_type_to_string(enum
 						   cvmx_chip_types_enum type)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/include/asm/pgtable-32.h
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/include/asm/pgtable-32.h
@@ -155,6 +155,7 @@
 
 #if defined(CONFIG_XPA)
 
+#define MAX_POSSIBLE_PHYSMEM_BITS 40
 #define pte_pfn(x)		(((unsigned long)((x).pte_high >> _PFN_SHIFT)) | (unsigned long)((x).pte_low << _PAGE_PRESENT_SHIFT))
 static inline pte_t
 pfn_pte(unsigned long pfn, pgprot_t prot)
@@ -170,6 +171,7 @@
 
 #elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
 
+#define MAX_POSSIBLE_PHYSMEM_BITS 36
 #define pte_pfn(x)		((unsigned long)((x).pte_high >> 6))
 
 static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot)
@@ -184,6 +186,7 @@
 
 #else
 
+#define MAX_POSSIBLE_PHYSMEM_BITS 32
 #ifdef CONFIG_CPU_VR41XX
 #define pte_pfn(x)		((unsigned long)((x).pte >> (PAGE_SHIFT + 2)))
 #define pfn_pte(pfn, prot)	__pte(((pfn) << (PAGE_SHIFT + 2)) | pgprot_val(prot))
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/include/asm/pgtable-64.h
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/include/asm/pgtable-64.h
@@ -18,10 +18,12 @@
 #include <asm/fixmap.h>
 
 #define __ARCH_USE_5LEVEL_HACK
-#if defined(CONFIG_PAGE_SIZE_64KB) && !defined(CONFIG_MIPS_VA_BITS_48)
+#if CONFIG_PGTABLE_LEVELS == 2
 #include <asm-generic/pgtable-nopmd.h>
-#elif !(defined(CONFIG_PAGE_SIZE_4KB) && defined(CONFIG_MIPS_VA_BITS_48))
+#elif CONFIG_PGTABLE_LEVELS == 3
 #include <asm-generic/pgtable-nopud.h>
+#else
+#include <asm-generic/5level-fixup.h>
 #endif
 
 /*
@@ -216,6 +218,9 @@
 	return pgd_val(pgd);
 }
 
+#define pgd_phys(pgd)		virt_to_phys((void *)pgd_val(pgd))
+#define pgd_page(pgd)		(pfn_to_page(pgd_phys(pgd) >> PAGE_SHIFT))
+
 static inline pud_t *pud_offset(pgd_t *pgd, unsigned long address)
 {
 	return (pud_t *)pgd_page_vaddr(*pgd) + pud_index(address);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/include/asm/ptrace.h
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/include/asm/ptrace.h
@@ -60,6 +60,7 @@
                                            unsigned long val)
 {
 	regs->cp0_epc = val;
+	regs->cp0_cause &= ~CAUSEF_BD;
 }
 
 /* Query offset/name of register from its name/offset */
@@ -156,7 +157,7 @@
 #define instruction_pointer(regs) ((regs)->cp0_epc)
 #define profile_pc(regs) instruction_pointer(regs)
 
-extern asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall);
+extern asmlinkage long syscall_trace_enter(struct pt_regs *regs);
 extern asmlinkage void syscall_trace_leave(struct pt_regs *regs);
 
 extern void die(const char *, struct pt_regs *) __noreturn;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/include/asm/setup.h
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/include/asm/setup.h
@@ -16,7 +16,7 @@
 	unsigned int reg_shift, unsigned int timeout) {}
 #endif
 
-extern void set_handler(unsigned long offset, void *addr, unsigned long len);
+void set_handler(unsigned long offset, const void *addr, unsigned long len);
 extern void set_uncached_handler(unsigned long offset, void *addr, unsigned long len);
 
 typedef void (*vi_handler_t)(void);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/include/asm/string.h
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/include/asm/string.h
@@ -10,127 +10,6 @@
 #ifndef _ASM_STRING_H
 #define _ASM_STRING_H
 
-
-/*
- * Most of the inline functions are rather naive implementations so I just
- * didn't bother updating them for 64-bit ...
- */
-#ifdef CONFIG_32BIT
-
-#ifndef IN_STRING_C
-
-#define __HAVE_ARCH_STRCPY
-static __inline__ char *strcpy(char *__dest, __const__ char *__src)
-{
-  char *__xdest = __dest;
-
-  __asm__ __volatile__(
-	".set\tnoreorder\n\t"
-	".set\tnoat\n"
-	"1:\tlbu\t$1,(%1)\n\t"
-	"addiu\t%1,1\n\t"
-	"sb\t$1,(%0)\n\t"
-	"bnez\t$1,1b\n\t"
-	"addiu\t%0,1\n\t"
-	".set\tat\n\t"
-	".set\treorder"
-	: "=r" (__dest), "=r" (__src)
-	: "0" (__dest), "1" (__src)
-	: "memory");
-
-  return __xdest;
-}
-
-#define __HAVE_ARCH_STRNCPY
-static __inline__ char *strncpy(char *__dest, __const__ char *__src, size_t __n)
-{
-  char *__xdest = __dest;
-
-  if (__n == 0)
-    return __xdest;
-
-  __asm__ __volatile__(
-	".set\tnoreorder\n\t"
-	".set\tnoat\n"
-	"1:\tlbu\t$1,(%1)\n\t"
-	"subu\t%2,1\n\t"
-	"sb\t$1,(%0)\n\t"
-	"beqz\t$1,2f\n\t"
-	"addiu\t%0,1\n\t"
-	"bnez\t%2,1b\n\t"
-	"addiu\t%1,1\n"
-	"2:\n\t"
-	".set\tat\n\t"
-	".set\treorder"
-	: "=r" (__dest), "=r" (__src), "=r" (__n)
-	: "0" (__dest), "1" (__src), "2" (__n)
-	: "memory");
-
-  return __xdest;
-}
-
-#define __HAVE_ARCH_STRCMP
-static __inline__ int strcmp(__const__ char *__cs, __const__ char *__ct)
-{
-  int __res;
-
-  __asm__ __volatile__(
-	".set\tnoreorder\n\t"
-	".set\tnoat\n\t"
-	"lbu\t%2,(%0)\n"
-	"1:\tlbu\t$1,(%1)\n\t"
-	"addiu\t%0,1\n\t"
-	"bne\t$1,%2,2f\n\t"
-	"addiu\t%1,1\n\t"
-	"bnez\t%2,1b\n\t"
-	"lbu\t%2,(%0)\n\t"
-#if defined(CONFIG_CPU_R3000)
-	"nop\n\t"
-#endif
-	"move\t%2,$1\n"
-	"2:\tsubu\t%2,$1\n"
-	"3:\t.set\tat\n\t"
-	".set\treorder"
-	: "=r" (__cs), "=r" (__ct), "=r" (__res)
-	: "0" (__cs), "1" (__ct));
-
-  return __res;
-}
-
-#endif /* !defined(IN_STRING_C) */
-
-#define __HAVE_ARCH_STRNCMP
-static __inline__ int
-strncmp(__const__ char *__cs, __const__ char *__ct, size_t __count)
-{
-	int __res;
-
-	__asm__ __volatile__(
-	".set\tnoreorder\n\t"
-	".set\tnoat\n"
-	"1:\tlbu\t%3,(%0)\n\t"
-	"beqz\t%2,2f\n\t"
-	"lbu\t$1,(%1)\n\t"
-	"subu\t%2,1\n\t"
-	"bne\t$1,%3,3f\n\t"
-	"addiu\t%0,1\n\t"
-	"bnez\t%3,1b\n\t"
-	"addiu\t%1,1\n"
-	"2:\n\t"
-#if defined(CONFIG_CPU_R3000)
-	"nop\n\t"
-#endif
-	"move\t%3,$1\n"
-	"3:\tsubu\t%3,$1\n\t"
-	".set\tat\n\t"
-	".set\treorder"
-	: "=r" (__cs), "=r" (__ct), "=r" (__count), "=r" (__res)
-	: "0" (__cs), "1" (__ct), "2" (__count));
-
-	return __res;
-}
-#endif /* CONFIG_32BIT */
-
 #define __HAVE_ARCH_MEMSET
 extern void *memset(void *__s, int __c, size_t __count);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/include/asm/switch_to.h
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/include/asm/switch_to.h
@@ -97,7 +97,7 @@
 	}								\
 } while (0)
 #else
-# define __sanitize_fcr31(next)
+# define __sanitize_fcr31(next) do { (void) (next); } while (0)
 #endif
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/include/asm/syscall.h
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/include/asm/syscall.h
@@ -38,7 +38,7 @@
 static inline long syscall_get_nr(struct task_struct *task,
 				  struct pt_regs *regs)
 {
-	return current_thread_info()->syscall;
+	return task_thread_info(task)->syscall;
 }
 
 static inline void mips_syscall_update_nr(struct task_struct *task,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/include/asm/thread_info.h
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/include/asm/thread_info.h
@@ -49,8 +49,26 @@
 	.addr_limit	= KERNEL_DS,		\
 }
 
-/* How to get the thread information struct from C.  */
+/*
+ * A pointer to the struct thread_info for the currently executing thread is
+ * held in register $28/$gp.
+ *
+ * We declare __current_thread_info as a global register variable rather than a
+ * local register variable within current_thread_info() because clang doesn't
+ * support explicit local register variables.
+ *
+ * When building the VDSO we take care not to declare the global register
+ * variable because this causes GCC to not preserve the value of $28/$gp in
+ * functions that change its value (which is common in the PIC VDSO when
+ * accessing the GOT). Since the VDSO shouldn't be accessing
+ * __current_thread_info anyway we declare it extern in order to cause a link
+ * failure if it's referenced.
+ */
+#ifdef __VDSO__
+extern struct thread_info *__current_thread_info;
+#else
 register struct thread_info *__current_thread_info __asm__("$28");
+#endif
 
 static inline struct thread_info *current_thread_info(void)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/include/asm/timex.h
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/include/asm/timex.h
@@ -40,9 +40,9 @@
 typedef unsigned int cycles_t;
 
 /*
- * On R4000/R4400 before version 5.0 an erratum exists such that if the
- * cycle counter is read in the exact moment that it is matching the
- * compare register, no interrupt will be generated.
+ * On R4000/R4400 an erratum exists such that if the cycle counter is
+ * read in the exact moment that it is matching the compare register,
+ * no interrupt will be generated.
  *
  * There is a suggested workaround and also the erratum can't strike if
  * the compare interrupt isn't being used as the clock source device.
@@ -63,7 +63,7 @@
 	if (!__builtin_constant_p(cpu_has_counter))
 		asm volatile("" : "=m" (cpu_data[0].options));
 	if (likely(cpu_has_counter &&
-		   prid >= (PRID_IMP_R4000 | PRID_REV_ENCODE_44(5, 0))))
+		   prid > (PRID_IMP_R4000 | PRID_REV_ENCODE_44(15, 15))))
 		return 1;
 	else
 		return 0;
@@ -76,25 +76,24 @@
 	else
 		return 0;	/* no usable counter */
 }
+#define get_cycles get_cycles
 
 /*
  * Like get_cycles - but where c0_count is not available we desperately
  * use c0_random in an attempt to get at least a little bit of entropy.
- *
- * R6000 and R6000A neither have a count register nor a random register.
- * That leaves no entropy source in the CPU itself.
  */
 static inline unsigned long random_get_entropy(void)
 {
-	unsigned int prid = read_c0_prid();
-	unsigned int imp = prid & PRID_IMP_MASK;
+	unsigned int c0_random;
 
-	if (can_use_mips_counter(prid))
+	if (can_use_mips_counter(read_c0_prid()))
 		return read_c0_count();
-	else if (likely(imp != PRID_IMP_R6000 && imp != PRID_IMP_R6000A))
-		return read_c0_random();
+
+	if (cpu_has_3kex)
+		c0_random = (read_c0_random() >> 8) & 0x3f;
 	else
-		return 0;	/* no usable register */
+		c0_random = read_c0_random() & 0x3f;
+	return (random_get_entropy_fallback() << 6) | (0x3f - c0_random);
 }
 #define random_get_entropy random_get_entropy
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/include/asm/vdso/gettimeofday.h
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/include/asm/vdso/gettimeofday.h
@@ -26,7 +26,11 @@
 
 #define __VDSO_USE_SYSCALL		ULLONG_MAX
 
-#ifdef CONFIG_MIPS_CLOCK_VSYSCALL
+#if MIPS_ISA_REV < 6
+#define VDSO_SYSCALL_CLOBBERS "hi", "lo",
+#else
+#define VDSO_SYSCALL_CLOBBERS
+#endif
 
 static __always_inline long gettimeofday_fallback(
 				struct __kernel_old_timeval *_tv,
@@ -43,22 +47,13 @@
 	: "=r" (ret), "=r" (error)
 	: "r" (tv), "r" (tz), "r" (nr)
 	: "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13",
-	  "$14", "$15", "$24", "$25", "hi", "lo", "memory");
+	  "$14", "$15", "$24", "$25",
+	  VDSO_SYSCALL_CLOBBERS
+	  "memory");
 
 	return error ? -ret : ret;
 }
 
-#else
-
-static __always_inline long gettimeofday_fallback(
-				struct __kernel_old_timeval *_tv,
-				struct timezone *_tz)
-{
-	return -1;
-}
-
-#endif
-
 static __always_inline long clock_gettime_fallback(
 					clockid_t _clkid,
 					struct __kernel_timespec *_ts)
@@ -78,7 +73,9 @@
 	: "=r" (ret), "=r" (error)
 	: "r" (clkid), "r" (ts), "r" (nr)
 	: "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13",
-	  "$14", "$15", "$24", "$25", "hi", "lo", "memory");
+	  "$14", "$15", "$24", "$25",
+	  VDSO_SYSCALL_CLOBBERS
+	  "memory");
 
 	return error ? -ret : ret;
 }
@@ -102,7 +99,9 @@
 	: "=r" (ret), "=r" (error)
 	: "r" (clkid), "r" (ts), "r" (nr)
 	: "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13",
-	  "$14", "$15", "$24", "$25", "hi", "lo", "memory");
+	  "$14", "$15", "$24", "$25",
+	  VDSO_SYSCALL_CLOBBERS
+	  "memory");
 
 	return error ? -ret : ret;
 }
@@ -126,7 +125,9 @@
 	: "=r" (ret), "=r" (error)
 	: "r" (clkid), "r" (ts), "r" (nr)
 	: "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13",
-	  "$14", "$15", "$24", "$25", "hi", "lo", "memory");
+	  "$14", "$15", "$24", "$25",
+	  VDSO_SYSCALL_CLOBBERS
+	  "memory");
 
 	return error ? -ret : ret;
 }
@@ -146,7 +147,9 @@
 	: "=r" (ret), "=r" (error)
 	: "r" (clkid), "r" (ts), "r" (nr)
 	: "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13",
-	  "$14", "$15", "$24", "$25", "hi", "lo", "memory");
+	  "$14", "$15", "$24", "$25",
+	  VDSO_SYSCALL_CLOBBERS
+	  "memory");
 
 	return error ? -ret : ret;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/include/asm/vdso/vdso.h
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/include/asm/vdso/vdso.h
@@ -67,7 +67,7 @@
 
 static inline void __iomem *get_gic(const struct vdso_data *data)
 {
-	return (void __iomem *)data - PAGE_SIZE;
+	return (void __iomem *)((unsigned long)data & PAGE_MASK) - PAGE_SIZE;
 }
 
 #endif /* CONFIG_CLKSRC_MIPS_GIC */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/include/asm/vpe.h
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/include/asm/vpe.h
@@ -104,7 +104,6 @@
 	struct list_head tc_list;       /* Thread contexts */
 };
 
-extern unsigned long physical_memsize;
 extern struct vpe_control vpecontrol;
 extern const struct file_operations vpe_fops;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/jazz/jazzdma.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/jazz/jazzdma.c
@@ -592,7 +592,7 @@
 	phys_addr_t phys = page_to_phys(page) + offset;
 
 	if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
-		arch_sync_dma_for_device(dev, phys, size, dir);
+		arch_sync_dma_for_device(phys, size, dir);
 	return vdma_alloc(phys, size);
 }
 
@@ -600,7 +600,7 @@
 		size_t size, enum dma_data_direction dir, unsigned long attrs)
 {
 	if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
-		arch_sync_dma_for_cpu(dev, vdma_log2phys(dma_addr), size, dir);
+		arch_sync_dma_for_cpu(vdma_log2phys(dma_addr), size, dir);
 	vdma_free(dma_addr);
 }
 
@@ -612,7 +612,7 @@
 
 	for_each_sg(sglist, sg, nents, i) {
 		if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
-			arch_sync_dma_for_device(dev, sg_phys(sg), sg->length,
+			arch_sync_dma_for_device(sg_phys(sg), sg->length,
 				dir);
 		sg->dma_address = vdma_alloc(sg_phys(sg), sg->length);
 		if (sg->dma_address == DMA_MAPPING_ERROR)
@@ -631,8 +631,7 @@
 
 	for_each_sg(sglist, sg, nents, i) {
 		if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC))
-			arch_sync_dma_for_cpu(dev, sg_phys(sg), sg->length,
-				dir);
+			arch_sync_dma_for_cpu(sg_phys(sg), sg->length, dir);
 		vdma_free(sg->dma_address);
 	}
 }
@@ -640,13 +639,13 @@
 static void jazz_dma_sync_single_for_device(struct device *dev,
 		dma_addr_t addr, size_t size, enum dma_data_direction dir)
 {
-	arch_sync_dma_for_device(dev, vdma_log2phys(addr), size, dir);
+	arch_sync_dma_for_device(vdma_log2phys(addr), size, dir);
 }
 
 static void jazz_dma_sync_single_for_cpu(struct device *dev,
 		dma_addr_t addr, size_t size, enum dma_data_direction dir)
 {
-	arch_sync_dma_for_cpu(dev, vdma_log2phys(addr), size, dir);
+	arch_sync_dma_for_cpu(vdma_log2phys(addr), size, dir);
 }
 
 static void jazz_dma_sync_sg_for_device(struct device *dev,
@@ -656,7 +655,7 @@
 	int i;
 
 	for_each_sg(sgl, sg, nents, i)
-		arch_sync_dma_for_device(dev, sg_phys(sg), sg->length, dir);
+		arch_sync_dma_for_device(sg_phys(sg), sg->length, dir);
 }
 
 static void jazz_dma_sync_sg_for_cpu(struct device *dev,
@@ -666,7 +665,7 @@
 	int i;
 
 	for_each_sg(sgl, sg, nents, i)
-		arch_sync_dma_for_cpu(dev, sg_phys(sg), sg->length, dir);
+		arch_sync_dma_for_cpu(sg_phys(sg), sg->length, dir);
 }
 
 const struct dma_map_ops jazz_dma_ops = {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/jz4740/setup.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/jz4740/setup.c
@@ -61,7 +61,7 @@
 
 	jz4740_reset_init();
 
-	if (__dtb_start != __dtb_end)
+	if (&__dtb_start != &__dtb_end)
 		dtb = __dtb_start;
 	else
 		dtb = (void *)fw_passed_dtb;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/kernel/asm-offsets.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/kernel/asm-offsets.c
@@ -100,6 +100,7 @@
 	OFFSET(TI_PRE_COUNT, thread_info, preempt_count);
 	OFFSET(TI_ADDR_LIMIT, thread_info, addr_limit);
 	OFFSET(TI_REGS, thread_info, regs);
+	OFFSET(TI_SYSCALL, thread_info, syscall);
 	DEFINE(_THREAD_SIZE, THREAD_SIZE);
 	DEFINE(_THREAD_MASK, THREAD_MASK);
 	DEFINE(_IRQ_STACK_SIZE, IRQ_STACK_SIZE);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/kernel/cacheinfo.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/kernel/cacheinfo.c
@@ -17,7 +17,7 @@
 	leaf++;							\
 } while (0)
 
-static int __init_cache_level(unsigned int cpu)
+int init_cache_level(unsigned int cpu)
 {
 	struct cpuinfo_mips *c = &current_cpu_data;
 	struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
@@ -50,21 +50,46 @@
 	return 0;
 }
 
-static int __populate_cache_leaves(unsigned int cpu)
+static void fill_cpumask_siblings(int cpu, cpumask_t *cpu_map)
+{
+	int cpu1;
+
+	for_each_possible_cpu(cpu1)
+		if (cpus_are_siblings(cpu, cpu1))
+			cpumask_set_cpu(cpu1, cpu_map);
+}
+
+static void fill_cpumask_cluster(int cpu, cpumask_t *cpu_map)
+{
+	int cpu1;
+	int cluster = cpu_cluster(&cpu_data[cpu]);
+
+	for_each_possible_cpu(cpu1)
+		if (cpu_cluster(&cpu_data[cpu1]) == cluster)
+			cpumask_set_cpu(cpu1, cpu_map);
+}
+
+int populate_cache_leaves(unsigned int cpu)
 {
 	struct cpuinfo_mips *c = &current_cpu_data;
 	struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
 	struct cacheinfo *this_leaf = this_cpu_ci->info_list;
 
 	if (c->icache.waysize) {
+		/* L1 caches are per core */
+		fill_cpumask_siblings(cpu, &this_leaf->shared_cpu_map);
 		populate_cache(dcache, this_leaf, 1, CACHE_TYPE_DATA);
+		fill_cpumask_siblings(cpu, &this_leaf->shared_cpu_map);
 		populate_cache(icache, this_leaf, 1, CACHE_TYPE_INST);
 	} else {
 		populate_cache(dcache, this_leaf, 1, CACHE_TYPE_UNIFIED);
 	}
 
-	if (c->scache.waysize)
+	if (c->scache.waysize) {
+		/* L2 cache is per cluster */
+		fill_cpumask_cluster(cpu, &this_leaf->shared_cpu_map);
 		populate_cache(scache, this_leaf, 2, CACHE_TYPE_UNIFIED);
+	}
 
 	if (c->tcache.waysize)
 		populate_cache(tcache, this_leaf, 3, CACHE_TYPE_UNIFIED);
@@ -73,6 +98,3 @@
 
 	return 0;
 }
-
-DEFINE_SMP_CALL_CACHE_FUNCTION(init_cache_level)
-DEFINE_SMP_CALL_CACHE_FUNCTION(populate_cache_leaves)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/kernel/elf.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/kernel/elf.c
@@ -11,6 +11,7 @@
 
 #include <asm/cpu-features.h>
 #include <asm/cpu-info.h>
+#include <asm/fpu.h>
 
 #ifdef CONFIG_MIPS_FP_SUPPORT
 
@@ -309,6 +310,11 @@
 	struct cpuinfo_mips *c = &boot_cpu_data;
 	struct task_struct *t = current;
 
+	/* Do this early so t->thread.fpu.fcr31 won't be clobbered in case
+	 * we are preempted before the lose_fpu(0) in start_thread.
+	 */
+	lose_fpu(0);
+
 	t->thread.fpu.fcr31 = c->fpu_csr31;
 	switch (state->nan_2008) {
 	case 0:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/kernel/ftrace.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/kernel/ftrace.c
@@ -264,7 +264,7 @@
 #define S_R_SP	(0xafb0 << 16)	/* s{d,w} R, offset(sp) */
 #define OFFSET_MASK	0xffff	/* stack offset range: 0 ~ PT_SIZE */
 
-unsigned long ftrace_get_parent_ra_addr(unsigned long self_ra, unsigned long
+static unsigned long ftrace_get_parent_ra_addr(unsigned long self_ra, unsigned long
 		old_parent_ra, unsigned long parent_ra_addr, unsigned long fp)
 {
 	unsigned long sp, ip, tmp;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/kernel/genex.S
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/kernel/genex.S
@@ -474,20 +474,20 @@
 	.endm
 
 	.macro	__build_clear_fpe
+	CLI
+	TRACE_IRQS_OFF
 	.set	push
 	/* gas fails to assemble cfc1 for some archs (octeon).*/ \
 	.set	mips1
 	SET_HARDFLOAT
 	cfc1	a1, fcr31
 	.set	pop
-	CLI
-	TRACE_IRQS_OFF
 	.endm
 
 	.macro	__build_clear_msa_fpe
-	_cfcmsa	a1, MSA_CSR
 	CLI
 	TRACE_IRQS_OFF
+	_cfcmsa	a1, MSA_CSR
 	.endm
 
 	.macro	__build_clear_ade
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/kernel/jump_label.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/kernel/jump_label.c
@@ -56,7 +56,7 @@
 			 * The branch offset must fit in the instruction's 26
 			 * bit field.
 			 */
-			WARN_ON((offset >= BIT(25)) ||
+			WARN_ON((offset >= (long)BIT(25)) ||
 				(offset < -(long)BIT(25)));
 
 			insn.j_format.opcode = bc6_op;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/kernel/mips-cm.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/kernel/mips-cm.c
@@ -119,9 +119,9 @@
 	"COH_RD_ERR", "MMIO_WR_ERR", "MMIO_RD_ERR", "0x07",
 	"0x08", "0x09", "0x0a", "0x0b",
 	"0x0c", "0x0d", "0x0e", "0x0f",
-	"0x10", "0x11", "0x12", "0x13",
-	"0x14", "0x15", "0x16", "INTVN_WR_ERR",
-	"INTVN_RD_ERR", "0x19", "0x1a", "0x1b",
+	"0x10", "INTVN_WR_ERR", "INTVN_RD_ERR", "0x13",
+	"0x14", "0x15", "0x16", "0x17",
+	"0x18", "0x19", "0x1a", "0x1b",
 	"0x1c", "0x1d", "0x1e", "0x1f"
 };
 
@@ -179,8 +179,7 @@
 	phys_addr_t addr;
 
 	/* L2-only sync was introduced with CM major revision 6 */
-	major_rev = (read_gcr_rev() & CM_GCR_REV_MAJOR) >>
-		__ffs(CM_GCR_REV_MAJOR);
+	major_rev = FIELD_GET(CM_GCR_REV_MAJOR, read_gcr_rev());
 	if (major_rev < 6)
 		return;
 
@@ -263,13 +262,13 @@
 	preempt_disable();
 
 	if (cm_rev >= CM_REV_CM3) {
-		val = core << __ffs(CM3_GCR_Cx_OTHER_CORE);
-		val |= vp << __ffs(CM3_GCR_Cx_OTHER_VP);
+		val = FIELD_PREP(CM3_GCR_Cx_OTHER_CORE, core) |
+		      FIELD_PREP(CM3_GCR_Cx_OTHER_VP, vp);
 
 		if (cm_rev >= CM_REV_CM3_5) {
 			val |= CM_GCR_Cx_OTHER_CLUSTER_EN;
-			val |= cluster << __ffs(CM_GCR_Cx_OTHER_CLUSTER);
-			val |= block << __ffs(CM_GCR_Cx_OTHER_BLOCK);
+			val |= FIELD_PREP(CM_GCR_Cx_OTHER_CLUSTER, cluster);
+			val |= FIELD_PREP(CM_GCR_Cx_OTHER_BLOCK, block);
 		} else {
 			WARN_ON(cluster != 0);
 			WARN_ON(block != CM_GCR_Cx_OTHER_BLOCK_LOCAL);
@@ -299,7 +298,7 @@
 		spin_lock_irqsave(&per_cpu(cm_core_lock, curr_core),
 				  per_cpu(cm_core_lock_flags, curr_core));
 
-		val = core << __ffs(CM_GCR_Cx_OTHER_CORENUM);
+		val = FIELD_PREP(CM_GCR_Cx_OTHER_CORENUM, core);
 	}
 
 	write_gcr_cl_other(val);
@@ -343,8 +342,8 @@
 	cm_other = read_gcr_error_mult();
 
 	if (revision < CM_REV_CM3) { /* CM2 */
-		cause = cm_error >> __ffs(CM_GCR_ERROR_CAUSE_ERRTYPE);
-		ocause = cm_other >> __ffs(CM_GCR_ERROR_MULT_ERR2ND);
+		cause = FIELD_GET(CM_GCR_ERROR_CAUSE_ERRTYPE, cm_error);
+		ocause = FIELD_GET(CM_GCR_ERROR_MULT_ERR2ND, cm_other);
 
 		if (!cause)
 			return;
@@ -386,8 +385,8 @@
 		ulong core_id_bits, vp_id_bits, cmd_bits, cmd_group_bits;
 		ulong cm3_cca_bits, mcp_bits, cm3_tr_bits, sched_bit;
 
-		cause = cm_error >> __ffs64(CM3_GCR_ERROR_CAUSE_ERRTYPE);
-		ocause = cm_other >> __ffs(CM_GCR_ERROR_MULT_ERR2ND);
+		cause = FIELD_GET(CM3_GCR_ERROR_CAUSE_ERRTYPE, cm_error);
+		ocause = FIELD_GET(CM_GCR_ERROR_MULT_ERR2ND, cm_other);
 
 		if (!cause)
 			return;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/kernel/mips-cpc.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/kernel/mips-cpc.c
@@ -27,6 +27,7 @@
 	cpc_node = of_find_compatible_node(of_root, NULL, "mti,mips-cpc");
 	if (cpc_node) {
 		err = of_address_to_resource(cpc_node, 0, &res);
+		of_node_put(cpc_node);
 		if (!err)
 			return res.start;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/kernel/proc.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/kernel/proc.c
@@ -168,7 +168,7 @@
 {
 	unsigned long i = *pos;
 
-	return i < NR_CPUS ? (void *) (i + 1) : NULL;
+	return i < nr_cpu_ids ? (void *) (i + 1) : NULL;
 }
 
 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/kernel/ptrace.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/kernel/ptrace.c
@@ -1399,16 +1399,13 @@
  * Notification of system call entry/exit
  * - triggered by current->work.syscall_trace
  */
-asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall)
+asmlinkage long syscall_trace_enter(struct pt_regs *regs)
 {
 	user_exit();
 
-	current_thread_info()->syscall = syscall;
-
 	if (test_thread_flag(TIF_SYSCALL_TRACE)) {
 		if (tracehook_report_syscall_entry(regs))
 			return -1;
-		syscall = current_thread_info()->syscall;
 	}
 
 #ifdef CONFIG_SECCOMP
@@ -1417,7 +1414,7 @@
 		struct seccomp_data sd;
 		unsigned long args[6];
 
-		sd.nr = syscall;
+		sd.nr = current_thread_info()->syscall;
 		sd.arch = syscall_get_arch(current);
 		syscall_get_arguments(current, regs, args);
 		for (i = 0; i < 6; i++)
@@ -1427,23 +1424,23 @@
 		ret = __secure_computing(&sd);
 		if (ret == -1)
 			return ret;
-		syscall = current_thread_info()->syscall;
 	}
 #endif
 
 	if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
 		trace_sys_enter(regs, regs->regs[2]);
 
-	audit_syscall_entry(syscall, regs->regs[4], regs->regs[5],
+	audit_syscall_entry(current_thread_info()->syscall,
+			    regs->regs[4], regs->regs[5],
 			    regs->regs[6], regs->regs[7]);
 
 	/*
 	 * Negative syscall numbers are mistaken for rejected syscalls, but
 	 * won't have had the return value set appropriately, so we do so now.
 	 */
-	if (syscall < 0)
+	if (current_thread_info()->syscall < 0)
 		syscall_set_return_value(current, regs, -ENOSYS, 0);
-	return syscall;
+	return current_thread_info()->syscall;
 }
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/kernel/r2300_fpu.S
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/kernel/r2300_fpu.S
@@ -29,8 +29,8 @@
 #define EX2(a,b)						\
 9:	a,##b;							\
 	.section __ex_table,"a";				\
-	PTR	9b,bad_stack;					\
-	PTR	9b+4,bad_stack;					\
+	PTR	9b,fault;					\
+	PTR	9b+4,fault;					\
 	.previous
 
 	.set	mips1
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/kernel/relocate.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/kernel/relocate.c
@@ -187,8 +187,14 @@
 static inline __init unsigned long rotate_xor(unsigned long hash,
 					      const void *area, size_t size)
 {
-	size_t i;
-	unsigned long *ptr = (unsigned long *)area;
+	const typeof(hash) *ptr = PTR_ALIGN(area, sizeof(hash));
+	size_t diff, i;
+
+	diff = (void *)ptr - area;
+	if (unlikely(size < diff + sizeof(hash)))
+		return hash;
+
+	size = ALIGN_DOWN(size - diff, sizeof(hash));
 
 	for (i = 0; i < size / sizeof(hash); i++) {
 		/* Rotate by odd number of bits and XOR. */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/kernel/scall32-o32.S
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/kernel/scall32-o32.S
@@ -80,6 +80,18 @@
 	PTR	load_a7, bad_stack_a7
 	.previous
 
+	/*
+	 * syscall number is in v0 unless we called syscall(__NR_###)
+	 * where the real syscall number is in a0
+	 */
+	subu	t2, v0,  __NR_O32_Linux
+	bnez	t2, 1f /* __NR_syscall at offset 0 */
+	LONG_S	a0, TI_SYSCALL($28)	# Save a0 as syscall number
+	b	2f
+1:
+	LONG_S	v0, TI_SYSCALL($28)	# Save v0 as syscall number
+2:
+
 	lw	t0, TI_FLAGS($28)	# syscall tracing enabled?
 	li	t1, _TIF_WORK_SYSCALL_ENTRY
 	and	t0, t1
@@ -117,16 +129,7 @@
 	SAVE_STATIC
 	move	a0, sp
 
-	/*
-	 * syscall number is in v0 unless we called syscall(__NR_###)
-	 * where the real syscall number is in a0
-	 */
-	move	a1, v0
-	subu	t2, v0,  __NR_O32_Linux
-	bnez	t2, 1f /* __NR_syscall at offset 0 */
-	lw	a1, PT_R4(sp)
-
-1:	jal	syscall_trace_enter
+	jal	syscall_trace_enter
 
 	bltz	v0, 1f			# seccomp failed? Skip syscall
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/kernel/scall64-n32.S
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/kernel/scall64-n32.S
@@ -44,6 +44,8 @@
 
 	sd	a3, PT_R26(sp)		# save a3 for syscall restarting
 
+	LONG_S	v0, TI_SYSCALL($28)     # Store syscall number
+
 	li	t1, _TIF_WORK_SYSCALL_ENTRY
 	LONG_L	t0, TI_FLAGS($28)	# syscall tracing enabled?
 	and	t0, t1, t0
@@ -72,7 +74,6 @@
 n32_syscall_trace_entry:
 	SAVE_STATIC
 	move	a0, sp
-	move	a1, v0
 	jal	syscall_trace_enter
 
 	bltz	v0, 1f			# seccomp failed? Skip syscall
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/kernel/scall64-n64.S
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/kernel/scall64-n64.S
@@ -47,6 +47,8 @@
 
 	sd	a3, PT_R26(sp)		# save a3 for syscall restarting
 
+	LONG_S	v0, TI_SYSCALL($28)     # Store syscall number
+
 	li	t1, _TIF_WORK_SYSCALL_ENTRY
 	LONG_L	t0, TI_FLAGS($28)	# syscall tracing enabled?
 	and	t0, t1, t0
@@ -83,7 +85,6 @@
 syscall_trace_entry:
 	SAVE_STATIC
 	move	a0, sp
-	move	a1, v0
 	jal	syscall_trace_enter
 
 	bltz	v0, 1f			# seccomp failed? Skip syscall
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/kernel/scall64-o32.S
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/kernel/scall64-o32.S
@@ -79,6 +79,22 @@
 	PTR	load_a7, bad_stack_a7
 	.previous
 
+	/*
+	 * absolute syscall number is in v0 unless we called syscall(__NR_###)
+	 * where the real syscall number is in a0
+	 * note: NR_syscall is the first O32 syscall but the macro is
+	 * only defined when compiling with -mabi=32 (CONFIG_32BIT)
+	 * therefore __NR_O32_Linux is used (4000)
+	 */
+
+	subu	t2, v0,  __NR_O32_Linux
+	bnez	t2, 1f /* __NR_syscall at offset 0 */
+	LONG_S	a0, TI_SYSCALL($28)	# Save a0 as syscall number
+	b	2f
+1:
+	LONG_S	v0, TI_SYSCALL($28)	# Save v0 as syscall number
+2:
+
 	li	t1, _TIF_WORK_SYSCALL_ENTRY
 	LONG_L	t0, TI_FLAGS($28)	# syscall tracing enabled?
 	and	t0, t1, t0
@@ -113,22 +129,7 @@
 	sd	a7, PT_R11(sp)		# For indirect syscalls
 
 	move	a0, sp
-	/*
-	 * absolute syscall number is in v0 unless we called syscall(__NR_###)
-	 * where the real syscall number is in a0
-	 * note: NR_syscall is the first O32 syscall but the macro is
-	 * only defined when compiling with -mabi=32 (CONFIG_32BIT)
-	 * therefore __NR_O32_Linux is used (4000)
-	 */
-	.set	push
-	.set	reorder
-	subu	t1, v0,  __NR_O32_Linux
-	move	a1, v0
-	bnez	t1, 1f /* __NR_syscall at offset 0 */
-	ld	a1, PT_R4(sp) /* Arg1 for __NR_syscall case */
-	.set	pop
-
-1:	jal	syscall_trace_enter
+	jal	syscall_trace_enter
 
 	bltz	v0, 1f			# seccomp failed? Skip syscall
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/kernel/setup.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/kernel/setup.c
@@ -11,6 +11,8 @@
  * Copyright (C) 2000, 2001, 2002, 2007	 Maciej W. Rozycki
  */
 #include <linux/init.h>
+#include <linux/cpu.h>
+#include <linux/delay.h>
 #include <linux/ioport.h>
 #include <linux/export.h>
 #include <linux/screen_info.h>
@@ -190,10 +192,6 @@
 		pr_err("initrd start must be page aligned\n");
 		goto disable;
 	}
-	if (initrd_start < PAGE_OFFSET) {
-		pr_err("initrd start < PAGE_OFFSET\n");
-		goto disable;
-	}
 
 	/*
 	 * Sanitize initrd addresses. For example firmware
@@ -206,6 +204,11 @@
 	initrd_end = (unsigned long)__va(end);
 	initrd_start = (unsigned long)__va(__pa(initrd_start));
 
+	if (initrd_start < PAGE_OFFSET) {
+		pr_err("initrd start < PAGE_OFFSET\n");
+		goto disable;
+	}
+
 	ROOT_DEV = Root_RAM0;
 	return PFN_UP(end);
 disable:
@@ -359,11 +362,11 @@
 		panic("Incorrect memory mapping !!!");
 
 	if (max_pfn > PFN_DOWN(HIGHMEM_START)) {
+		max_low_pfn = PFN_DOWN(HIGHMEM_START);
 #ifdef CONFIG_HIGHMEM
-		highstart_pfn = PFN_DOWN(HIGHMEM_START);
+		highstart_pfn = max_low_pfn;
 		highend_pfn = max_pfn;
 #else
-		max_low_pfn = PFN_DOWN(HIGHMEM_START);
 		max_pfn = max_low_pfn;
 #endif
 	}
@@ -494,7 +497,7 @@
 	if (ret != 0 || crash_size <= 0)
 		return;
 
-	if (!memblock_find_in_range(crash_base, crash_base + crash_size, crash_size, 0)) {
+	if (!memblock_find_in_range(crash_base, crash_base + crash_size, crash_size, 1)) {
 		pr_warn("Invalid memory region reserved for crash kernel\n");
 		return;
 	}
@@ -529,8 +532,8 @@
 
 static void __init check_kernel_sections_mem(void)
 {
-	phys_addr_t start = PFN_PHYS(PFN_DOWN(__pa_symbol(&_text)));
-	phys_addr_t size = PFN_PHYS(PFN_UP(__pa_symbol(&_end))) - start;
+	phys_addr_t start = __pa_symbol(&_text);
+	phys_addr_t size = __pa_symbol(&_end) - start;
 
 	if (!memblock_is_region_memory(start, size)) {
 		pr_info("Kernel sections are not in the memory maps\n");
@@ -653,7 +656,17 @@
 				 crashk_res.end - crashk_res.start + 1);
 #endif
 	device_tree_init();
+
+	/*
+	 * In order to reduce the possibility of kernel panic when failed to
+	 * get IO TLB memory under CONFIG_SWIOTLB, it is better to allocate
+	 * low memory as small as possible before plat_swiotlb_setup(), so
+	 * make sparse_init() using top-down allocation.
+	 */
+	memblock_set_bottom_up(false);
 	sparse_init();
+	memblock_set_bottom_up(true);
+
 	plat_swiotlb_setup();
 
 	dma_contiguous_reserve(PFN_PHYS(max_low_pfn));
@@ -801,3 +814,14 @@
 }
 early_param("nocoherentio", setnocoherentio);
 #endif
+
+void __init arch_cpu_finalize_init(void)
+{
+	unsigned int cpu = smp_processor_id();
+
+	cpu_data[cpu].udelay_val = loops_per_jiffy;
+	check_bugs32();
+
+	if (IS_ENABLED(CONFIG_CPU_R4X00_BUGS64))
+		check_bugs64();
+}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/kernel/smp-bmips.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/kernel/smp-bmips.c
@@ -241,6 +241,8 @@
  */
 static void bmips_init_secondary(void)
 {
+	bmips_cpu_setup();
+
 	switch (current_cpu_type()) {
 	case CPU_BMIPS4350:
 	case CPU_BMIPS4380:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/kernel/smp-cps.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/kernel/smp-cps.c
@@ -229,7 +229,10 @@
 	write_gcr_co_reset_ext_base(CM_GCR_Cx_RESET_EXT_BASE_UEB);
 
 	/* Ensure the core can access the GCRs */
-	set_gcr_access(1 << core);
+	if (mips_cm_revision() < CM_REV_CM3)
+		set_gcr_access(1 << core);
+	else
+		set_gcr_access_cm3(1 << core);
 
 	if (mips_cpc_present()) {
 		/* Reset the core */
@@ -423,9 +426,11 @@
 			wmb();
 		}
 	} else {
-		pr_debug("Gating power to core %d\n", core);
-		/* Power down the core */
-		cps_pm_enter_state(CPS_PM_POWER_GATED);
+		if (IS_ENABLED(CONFIG_HOTPLUG_CPU)) {
+			pr_debug("Gating power to core %d\n", core);
+			/* Power down the core */
+			cps_pm_enter_state(CPS_PM_POWER_GATED);
+		}
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/kernel/smp.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/kernel/smp.c
@@ -361,6 +361,9 @@
 	cpu = smp_processor_id();
 	cpu_data[cpu].udelay_val = loops_per_jiffy;
 
+	set_cpu_sibling_map(cpu);
+	set_cpu_core_map(cpu);
+
 	cpumask_set_cpu(cpu, &cpu_coherent_mask);
 	notify_cpu_starting(cpu);
 
@@ -372,9 +375,6 @@
 	/* The CPU is running and counters synchronised, now mark it online */
 	set_cpu_online(cpu, true);
 
-	set_cpu_sibling_map(cpu);
-	set_cpu_core_map(cpu);
-
 	calculate_cpu_foreign_map();
 
 	/*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/kernel/syscall.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/kernel/syscall.c
@@ -239,12 +239,3 @@
 {
 	return -ENOSYS;
 }
-
-/*
- * If we ever come here the user sp is bad.  Zap the process right away.
- * Due to the bad stack signaling wouldn't work.
- */
-asmlinkage void bad_stack(void)
-{
-	do_exit(SIGSEGV);
-}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/kernel/syscalls/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/kernel/syscalls/Makefile
@@ -18,7 +18,7 @@
 		   '$(syshdr_pfx_$(basetarget))'		\
 		   '$(syshdr_offset_$(basetarget))'
 
-quiet_cmd_sysnr = SYSNR  $@
+quiet_cmd_sysnr = SYSNR   $@
       cmd_sysnr = $(CONFIG_SHELL) '$(sysnr)' '$<' '$@'		\
 		  '$(sysnr_abis_$(basetarget))'			\
 		  '$(sysnr_pfx_$(basetarget))'			\
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/kernel/syscalls/syscall_o32.tbl
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/kernel/syscalls/syscall_o32.tbl
@@ -27,7 +27,7 @@
 17	o32	break				sys_ni_syscall
 # 18 was sys_stat
 18	o32	unused18			sys_ni_syscall
-19	o32	lseek				sys_lseek
+19	o32	lseek				sys_lseek			compat_sys_lseek
 20	o32	getpid				sys_getpid
 21	o32	mount				sys_mount			compat_sys_mount
 22	o32	umount				sys_oldumount
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/kernel/time.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/kernel/time.c
@@ -18,12 +18,82 @@
 #include <linux/smp.h>
 #include <linux/spinlock.h>
 #include <linux/export.h>
+#include <linux/cpufreq.h>
+#include <linux/delay.h>
 
 #include <asm/cpu-features.h>
 #include <asm/cpu-type.h>
 #include <asm/div64.h>
 #include <asm/time.h>
 
+#ifdef CONFIG_CPU_FREQ
+
+static DEFINE_PER_CPU(unsigned long, pcp_lpj_ref);
+static DEFINE_PER_CPU(unsigned long, pcp_lpj_ref_freq);
+static unsigned long glb_lpj_ref;
+static unsigned long glb_lpj_ref_freq;
+
+static int cpufreq_callback(struct notifier_block *nb,
+			    unsigned long val, void *data)
+{
+	struct cpufreq_freqs *freq = data;
+	struct cpumask *cpus = freq->policy->cpus;
+	unsigned long lpj;
+	int cpu;
+
+	/*
+	 * Skip lpj numbers adjustment if the CPU-freq transition is safe for
+	 * the loops delay. (Is this possible?)
+	 */
+	if (freq->flags & CPUFREQ_CONST_LOOPS)
+		return NOTIFY_OK;
+
+	/* Save the initial values of the lpjes for future scaling. */
+	if (!glb_lpj_ref) {
+		glb_lpj_ref = boot_cpu_data.udelay_val;
+		glb_lpj_ref_freq = freq->old;
+
+		for_each_online_cpu(cpu) {
+			per_cpu(pcp_lpj_ref, cpu) =
+				cpu_data[cpu].udelay_val;
+			per_cpu(pcp_lpj_ref_freq, cpu) = freq->old;
+		}
+	}
+
+	/*
+	 * Adjust global lpj variable and per-CPU udelay_val number in
+	 * accordance with the new CPU frequency.
+	 */
+	if ((val == CPUFREQ_PRECHANGE  && freq->old < freq->new) ||
+	    (val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) {
+		loops_per_jiffy = cpufreq_scale(glb_lpj_ref,
+						glb_lpj_ref_freq,
+						freq->new);
+
+		for_each_cpu(cpu, cpus) {
+			lpj = cpufreq_scale(per_cpu(pcp_lpj_ref, cpu),
+					    per_cpu(pcp_lpj_ref_freq, cpu),
+					    freq->new);
+			cpu_data[cpu].udelay_val = (unsigned int)lpj;
+		}
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block cpufreq_notifier = {
+	.notifier_call  = cpufreq_callback,
+};
+
+static int __init register_cpufreq_notifier(void)
+{
+	return cpufreq_register_notifier(&cpufreq_notifier,
+					 CPUFREQ_TRANSITION_NOTIFIER);
+}
+core_initcall(register_cpufreq_notifier);
+
+#endif /* CONFIG_CPU_FREQ */
+
 /*
  * forward reference
  */
@@ -71,15 +141,10 @@
 	case CPU_R4400MC:
 		/*
 		 * The published errata for the R4400 up to 3.0 say the CPU
-		 * has the mfc0 from count bug.
+		 * has the mfc0 from count bug.  This seems the last version
+		 * produced.
 		 */
-		if ((current_cpu_data.processor_id & 0xff) <= 0x30)
-			return 1;
-
-		/*
-		 * we assume newer revisions are ok
-		 */
-		return 0;
+		return 1;
 	}
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/kernel/topology.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/kernel/topology.c
@@ -20,7 +20,7 @@
 	for_each_present_cpu(i) {
 		struct cpu *c = &per_cpu(cpu_devices, i);
 
-		c->hotpluggable = 1;
+		c->hotpluggable = !!i;
 		ret = register_cpu(c, i);
 		if (ret)
 			printk(KERN_WARNING "topology_init: register_cpu %d "
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/kernel/traps.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/kernel/traps.c
@@ -415,7 +415,7 @@
 	if (regs && kexec_should_crash(current))
 		crash_kexec(regs);
 
-	do_exit(sig);
+	make_task_dead(sig);
 }
 
 extern struct exception_table_entry __start___dbe_table[];
@@ -1240,6 +1240,18 @@
 		err = own_fpu_inatomic(1);
 		if (msa && !err) {
 			enable_msa();
+			/*
+			 * with MSA enabled, userspace can see MSACSR
+			 * and MSA regs, but the values in them are from
+			 * other task before current task, restore them
+			 * from saved fp/msa context
+			 */
+			write_msa_csr(current->thread.fpu.msacsr);
+			/*
+			 * own_fpu_inatomic(1) just restore low 64bit,
+			 * fix the high 64bit
+			 */
+			init_msa_upper();
 			set_thread_flag(TIF_USEDMSA);
 			set_thread_flag(TIF_MSA_CTX_LIVE);
 		}
@@ -2008,19 +2020,19 @@
 		 * If no shadow set is selected then use the default handler
 		 * that does normal register saving and standard interrupt exit
 		 */
-		extern char except_vec_vi, except_vec_vi_lui;
-		extern char except_vec_vi_ori, except_vec_vi_end;
-		extern char rollback_except_vec_vi;
-		char *vec_start = using_rollback_handler() ?
-			&rollback_except_vec_vi : &except_vec_vi;
+		extern const u8 except_vec_vi[], except_vec_vi_lui[];
+		extern const u8 except_vec_vi_ori[], except_vec_vi_end[];
+		extern const u8 rollback_except_vec_vi[];
+		const u8 *vec_start = using_rollback_handler() ?
+				      rollback_except_vec_vi : except_vec_vi;
 #if defined(CONFIG_CPU_MICROMIPS) || defined(CONFIG_CPU_BIG_ENDIAN)
-		const int lui_offset = &except_vec_vi_lui - vec_start + 2;
-		const int ori_offset = &except_vec_vi_ori - vec_start + 2;
+		const int lui_offset = except_vec_vi_lui - vec_start + 2;
+		const int ori_offset = except_vec_vi_ori - vec_start + 2;
 #else
-		const int lui_offset = &except_vec_vi_lui - vec_start;
-		const int ori_offset = &except_vec_vi_ori - vec_start;
+		const int lui_offset = except_vec_vi_lui - vec_start;
+		const int ori_offset = except_vec_vi_ori - vec_start;
 #endif
-		const int handler_len = &except_vec_vi_end - vec_start;
+		const int handler_len = except_vec_vi_end - vec_start;
 
 		if (handler_len > VECTORSPACING) {
 			/*
@@ -2126,6 +2138,7 @@
 
 	change_c0_status(ST0_CU|ST0_MX|ST0_RE|ST0_FR|ST0_BEV|ST0_TS|ST0_KX|ST0_SX|ST0_UX,
 			 status_set);
+	back_to_back_c0_hazard();
 }
 
 unsigned int hwrena;
@@ -2227,7 +2240,7 @@
 }
 
 /* Install CPU exception handler */
-void set_handler(unsigned long offset, void *addr, unsigned long size)
+void set_handler(unsigned long offset, const void *addr, unsigned long size)
 {
 #ifdef CONFIG_CPU_MICROMIPS
 	memcpy((void *)(ebase + offset), ((unsigned char *)addr - 1), size);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/kernel/vmlinux.lds.S
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/kernel/vmlinux.lds.S
@@ -10,6 +10,8 @@
  */
 #define BSS_FIRST_SECTIONS *(.bss..swapper_pg_dir)
 
+#define RUNTIME_DISCARD_EXIT
+
 #include <asm-generic/vmlinux.lds.h>
 
 #undef mips
@@ -50,7 +52,7 @@
 	/* . = 0xa800000000300000; */
 	. = 0xffffffff80300000;
 #endif
-	. = VMLINUX_LOAD_ADDRESS;
+	. = LINKER_LOAD_ADDRESS;
 	/* read-only */
 	_text = .;	/* Text and read-only data */
 	.text : {
@@ -93,6 +95,7 @@
 
 		INIT_TASK_DATA(THREAD_SIZE)
 		NOSAVE_DATA
+		PAGE_ALIGNED_DATA(PAGE_SIZE)
 		CACHELINE_ALIGNED_DATA(1 << CONFIG_MIPS_L1_CACHE_SHIFT)
 		READ_MOSTLY_DATA(1 << CONFIG_MIPS_L1_CACHE_SHIFT)
 		DATA_DATA
@@ -225,6 +228,5 @@
 		*(.options)
 		*(.pdr)
 		*(.reginfo)
-		*(.eh_frame)
 	}
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/kernel/vpe-cmp.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/kernel/vpe-cmp.c
@@ -75,7 +75,6 @@
 
 static void vpe_device_release(struct device *cd)
 {
-	kfree(cd);
 }
 
 static struct class vpe_class = {
@@ -157,6 +156,7 @@
 	device_del(&vpe_device);
 
 out_class:
+	put_device(&vpe_device);
 	class_unregister(&vpe_class);
 
 out_chrdev:
@@ -169,7 +169,7 @@
 {
 	struct vpe *v, *n;
 
-	device_del(&vpe_device);
+	device_unregister(&vpe_device);
 	class_unregister(&vpe_class);
 	unregister_chrdev(major, VPE_MODULE_NAME);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/kernel/vpe-mt.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/kernel/vpe-mt.c
@@ -92,12 +92,11 @@
 	write_tc_c0_tchalt(read_tc_c0_tchalt() & ~TCHALT_H);
 
 	/*
-	 * The sde-kit passes 'memsize' to __start in $a3, so set something
-	 * here...  Or set $a3 to zero and define DFLT_STACK_SIZE and
-	 * DFLT_HEAP_SIZE when you compile your program
+	 * We don't pass the memsize here, so VPE programs need to be
+	 * compiled with DFLT_STACK_SIZE and DFLT_HEAP_SIZE defined.
 	 */
+	mttgpr(7, 0);
 	mttgpr(6, v->ntcs);
-	mttgpr(7, physical_memsize);
 
 	/* set up VPE1 */
 	/*
@@ -313,7 +312,6 @@
 
 static void vpe_device_release(struct device *cd)
 {
-	kfree(cd);
 }
 
 static struct class vpe_class = {
@@ -497,6 +495,7 @@
 	device_del(&vpe_device);
 
 out_class:
+	put_device(&vpe_device);
 	class_unregister(&vpe_class);
 
 out_chrdev:
@@ -509,7 +508,7 @@
 {
 	struct vpe *v, *n;
 
-	device_del(&vpe_device);
+	device_unregister(&vpe_device);
 	class_unregister(&vpe_class);
 	unregister_chrdev(major, VPE_MODULE_NAME);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/kernel/vpe.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/kernel/vpe.c
@@ -134,7 +134,7 @@
 {
 	list_del(&v->list);
 	if (v->load_addr)
-		release_progmem(v);
+		release_progmem(v->load_addr);
 	kfree(v);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/kvm/mips.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/kvm/mips.c
@@ -131,6 +131,8 @@
 int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
 {
 	switch (type) {
+	case KVM_VM_MIPS_AUTO:
+		break;
 #ifdef CONFIG_KVM_MIPS_VZ
 	case KVM_VM_MIPS_VZ:
 #else
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/kvm/mmu.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/kvm/mmu.c
@@ -512,7 +512,8 @@
 	return 1;
 }
 
-int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end)
+int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end,
+			unsigned flags)
 {
 	handle_hva_to_gpa(kvm, start, end, &kvm_unmap_hva_handler, NULL);
 
@@ -692,7 +693,7 @@
 	gfn_t gfn = gpa >> PAGE_SHIFT;
 	int srcu_idx, err;
 	kvm_pfn_t pfn;
-	pte_t *ptep, entry, old_pte;
+	pte_t *ptep, entry;
 	bool writeable;
 	unsigned long prot_bits;
 	unsigned long mmu_seq;
@@ -765,7 +766,6 @@
 	entry = pfn_pte(pfn, __pgprot(prot_bits));
 
 	/* Write the PTE */
-	old_pte = *ptep;
 	set_pte(ptep, entry);
 
 	err = 0;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/lantiq/clk.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/lantiq/clk.c
@@ -50,6 +50,7 @@
 {
 	return &cpu_clk_generic[2];
 }
+EXPORT_SYMBOL_GPL(clk_get_io);
 
 struct clk *clk_get_ppe(void)
 {
@@ -158,6 +159,18 @@
 }
 EXPORT_SYMBOL(clk_deactivate);
 
+struct clk *clk_get_parent(struct clk *clk)
+{
+	return NULL;
+}
+EXPORT_SYMBOL(clk_get_parent);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	return 0;
+}
+EXPORT_SYMBOL(clk_set_parent);
+
 static inline u32 get_counter_resolution(void)
 {
 	u32 res;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/lantiq/falcon/sysctrl.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/lantiq/falcon/sysctrl.c
@@ -167,6 +167,8 @@
 {
 	struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
 
+	if (!clk)
+		return;
 	clk->cl.dev_id = dev;
 	clk->cl.con_id = NULL;
 	clk->cl.clk = clk;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/lantiq/irq.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/lantiq/irq.c
@@ -302,7 +302,7 @@
 	generic_handle_irq(irq_linear_revmap(ltq_domain, hwirq));
 
 	/* if this is a EBU irq, we need to ack it or get a deadlock */
-	if ((irq == LTQ_ICU_EBU_IRQ) && (module == 0) && LTQ_EBU_PCC_ISTAT)
+	if (irq == LTQ_ICU_EBU_IRQ && !module && LTQ_EBU_PCC_ISTAT != 0)
 		ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_ISTAT) | 0x10,
 			LTQ_EBU_PCC_ISTAT);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/lantiq/prom.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/lantiq/prom.c
@@ -23,12 +23,6 @@
 EXPORT_SYMBOL_GPL(ebu_lock);
 
 /*
- * This is needed by the VPE loader code, just set it to 0 and assume
- * that the firmware hardcodes this value to something useful.
- */
-unsigned long physical_memsize = 0L;
-
-/*
  * this struct is filled by the soc specific detection code and holds
  * information about the specific soc type, revision and name
  */
@@ -79,7 +73,7 @@
 
 	if (fw_passed_dtb) /* UHI interface */
 		dtb = (void *)fw_passed_dtb;
-	else if (__dtb_start != __dtb_end)
+	else if (&__dtb_start != &__dtb_end)
 		dtb = (void *)__dtb_start;
 	else
 		panic("no dtb found");
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/lantiq/xway/dma.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/lantiq/xway/dma.c
@@ -11,6 +11,7 @@
 #include <linux/export.h>
 #include <linux/spinlock.h>
 #include <linux/clk.h>
+#include <linux/delay.h>
 #include <linux/err.h>
 
 #include <lantiq_soc.h>
@@ -29,6 +30,7 @@
 #define LTQ_DMA_PCTRL		0x44
 #define LTQ_DMA_IRNEN		0xf4
 
+#define DMA_ID_CHNR		GENMASK(26, 20)	/* channel number */
 #define DMA_DESCPT		BIT(3)		/* descriptor complete irq */
 #define DMA_TX			BIT(8)		/* TX channel direction */
 #define DMA_CHAN_ON		BIT(0)		/* channel on / off bit */
@@ -39,7 +41,6 @@
 #define DMA_POLL		BIT(31)		/* turn on channel polling */
 #define DMA_CLK_DIV4		BIT(6)		/* polling clock divider */
 #define DMA_2W_BURST		BIT(1)		/* 2 word burst length */
-#define DMA_MAX_CHANNEL		20		/* the soc has 20 channels */
 #define DMA_ETOP_ENDIANNESS	(0xf << 8) /* endianness swap etop channels */
 #define DMA_WEIGHT	(BIT(17) | BIT(16))	/* default channel wheight */
 
@@ -205,7 +206,7 @@
 {
 	struct clk *clk;
 	struct resource *res;
-	unsigned id;
+	unsigned int id, nchannels;
 	int i;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -221,21 +222,24 @@
 	clk_enable(clk);
 	ltq_dma_w32_mask(0, DMA_RESET, LTQ_DMA_CTRL);
 
+	usleep_range(1, 10);
+
 	/* disable all interrupts */
 	ltq_dma_w32(0, LTQ_DMA_IRNEN);
 
 	/* reset/configure each channel */
-	for (i = 0; i < DMA_MAX_CHANNEL; i++) {
+	id = ltq_dma_r32(LTQ_DMA_ID);
+	nchannels = ((id & DMA_ID_CHNR) >> 20);
+	for (i = 0; i < nchannels; i++) {
 		ltq_dma_w32(i, LTQ_DMA_CS);
 		ltq_dma_w32(DMA_CHAN_RST, LTQ_DMA_CCTRL);
 		ltq_dma_w32(DMA_POLL | DMA_CLK_DIV4, LTQ_DMA_CPOLL);
 		ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL);
 	}
 
-	id = ltq_dma_r32(LTQ_DMA_ID);
 	dev_info(&pdev->dev,
 		"Init done - hw rev: %X, ports: %d, channels: %d\n",
-		id & 0x1f, (id >> 16) & 0xf, id >> 20);
+		id & 0x1f, (id >> 16) & 0xf, nchannels);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/lantiq/xway/gptu.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/lantiq/xway/gptu.c
@@ -122,6 +122,8 @@
 {
 	struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
 
+	if (!clk)
+		return;
 	clk->cl.dev_id = dev_name(dev);
 	clk->cl.con_id = con;
 	clk->cl.clk = clk;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/lantiq/xway/sysctrl.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/lantiq/xway/sysctrl.c
@@ -311,6 +311,8 @@
 {
 	struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
 
+	if (!clk)
+		return;
 	clk->cl.dev_id = dev;
 	clk->cl.con_id = con;
 	clk->cl.clk = clk;
@@ -334,6 +336,8 @@
 {
 	struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
 
+	if (!clk)
+		return;
 	clk->cl.dev_id = dev;
 	clk->cl.con_id = con;
 	clk->cl.clk = clk;
@@ -352,24 +356,28 @@
 	struct clk *clk_ext = kzalloc(sizeof(struct clk), GFP_KERNEL);
 
 	/* main pci clock */
-	clk->cl.dev_id = "17000000.pci";
-	clk->cl.con_id = NULL;
-	clk->cl.clk = clk;
-	clk->rate = CLOCK_33M;
-	clk->rates = valid_pci_rates;
-	clk->enable = pci_enable;
-	clk->disable = pmu_disable;
-	clk->module = 0;
-	clk->bits = PMU_PCI;
-	clkdev_add(&clk->cl);
+	if (clk) {
+		clk->cl.dev_id = "17000000.pci";
+		clk->cl.con_id = NULL;
+		clk->cl.clk = clk;
+		clk->rate = CLOCK_33M;
+		clk->rates = valid_pci_rates;
+		clk->enable = pci_enable;
+		clk->disable = pmu_disable;
+		clk->module = 0;
+		clk->bits = PMU_PCI;
+		clkdev_add(&clk->cl);
+	}
 
 	/* use internal/external bus clock */
-	clk_ext->cl.dev_id = "17000000.pci";
-	clk_ext->cl.con_id = "external";
-	clk_ext->cl.clk = clk_ext;
-	clk_ext->enable = pci_ext_enable;
-	clk_ext->disable = pci_ext_disable;
-	clkdev_add(&clk_ext->cl);
+	if (clk_ext) {
+		clk_ext->cl.dev_id = "17000000.pci";
+		clk_ext->cl.con_id = "external";
+		clk_ext->cl.clk = clk_ext;
+		clk_ext->enable = pci_ext_enable;
+		clk_ext->disable = pci_ext_disable;
+		clkdev_add(&clk_ext->cl);
+	}
 }
 
 /* xway socs can generate clocks on gpio pins */
@@ -389,9 +397,15 @@
 		char *name;
 
 		name = kzalloc(sizeof("clkout0"), GFP_KERNEL);
+		if (!name)
+			continue;
 		sprintf(name, "clkout%d", i);
 
 		clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
+		if (!clk) {
+			kfree(name);
+			continue;
+		}
 		clk->cl.dev_id = "1f103000.cgu";
 		clk->cl.con_id = name;
 		clk->cl.clk = clk;
@@ -514,8 +528,8 @@
 		clkdev_add_pmu("1e10b308.eth", NULL, 0, 0, PMU_SWITCH |
 			       PMU_PPE_DP | PMU_PPE_TC);
 		clkdev_add_pmu("1da00000.usif", "NULL", 1, 0, PMU_USIF);
-		clkdev_add_pmu("1e108000.gswip", "gphy0", 0, 0, PMU_GPHY);
-		clkdev_add_pmu("1e108000.gswip", "gphy1", 0, 0, PMU_GPHY);
+		clkdev_add_pmu("1e108000.switch", "gphy0", 0, 0, PMU_GPHY);
+		clkdev_add_pmu("1e108000.switch", "gphy1", 0, 0, PMU_GPHY);
 		clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU);
 		clkdev_add_pmu("1e116000.mei", "afe", 1, 2, PMU_ANALOG_DSL_AFE);
 		clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE);
@@ -538,8 +552,8 @@
 				PMU_SWITCH | PMU_PPE_DPLUS | PMU_PPE_DPLUM |
 				PMU_PPE_EMA | PMU_PPE_TC | PMU_PPE_SLL01 |
 				PMU_PPE_QSB | PMU_PPE_TOP);
-		clkdev_add_pmu("1e108000.gswip", "gphy0", 0, 0, PMU_GPHY);
-		clkdev_add_pmu("1e108000.gswip", "gphy1", 0, 0, PMU_GPHY);
+		clkdev_add_pmu("1e108000.switch", "gphy0", 0, 0, PMU_GPHY);
+		clkdev_add_pmu("1e108000.switch", "gphy1", 0, 0, PMU_GPHY);
 		clkdev_add_pmu("1e103000.sdio", NULL, 1, 0, PMU_SDIO);
 		clkdev_add_pmu("1e103100.deu", NULL, 1, 0, PMU_DEU);
 		clkdev_add_pmu("1e116000.mei", "dfe", 1, 0, PMU_DFE);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/lasat/picvue_proc.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/lasat/picvue_proc.c
@@ -39,7 +39,7 @@
 		pvc_write_string(pvc_lines[i], 0, i);
 }
 
-static DECLARE_TASKLET(pvc_display_tasklet, &pvc_display, 0);
+static DECLARE_TASKLET_OLD(pvc_display_tasklet, &pvc_display);
 
 static int pvc_line_proc_show(struct seq_file *m, void *v)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/lib/dump_tlb.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/lib/dump_tlb.c
@@ -80,7 +80,7 @@
 	unsigned int pagemask, guestctl1 = 0, c0, c1, i;
 	unsigned long asidmask = cpu_asid_mask(&current_cpu_data);
 	int asidwidth = DIV_ROUND_UP(ilog2(asidmask) + 1, 4);
-	unsigned long uninitialized_var(s_mmid);
+	unsigned long s_mmid;
 #ifdef CONFIG_32BIT
 	bool xpa = cpu_has_xpa && (read_c0_pagegrain() & PG_ELPA);
 	int pwidth = xpa ? 11 : 8;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/lib/mips-atomic.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/lib/mips-atomic.c
@@ -37,7 +37,7 @@
  */
 notrace void arch_local_irq_disable(void)
 {
-	preempt_disable();
+	preempt_disable_notrace();
 
 	__asm__ __volatile__(
 	"	.set	push						\n"
@@ -53,7 +53,7 @@
 	: /* no inputs */
 	: "memory");
 
-	preempt_enable();
+	preempt_enable_notrace();
 }
 EXPORT_SYMBOL(arch_local_irq_disable);
 
@@ -61,7 +61,7 @@
 {
 	unsigned long flags;
 
-	preempt_disable();
+	preempt_disable_notrace();
 
 	__asm__ __volatile__(
 	"	.set	push						\n"
@@ -78,7 +78,7 @@
 	: /* no inputs */
 	: "memory");
 
-	preempt_enable();
+	preempt_enable_notrace();
 
 	return flags;
 }
@@ -88,7 +88,7 @@
 {
 	unsigned long __tmp1;
 
-	preempt_disable();
+	preempt_disable_notrace();
 
 	__asm__ __volatile__(
 	"	.set	push						\n"
@@ -106,7 +106,7 @@
 	: "0" (flags)
 	: "memory");
 
-	preempt_enable();
+	preempt_enable_notrace();
 }
 EXPORT_SYMBOL(arch_local_irq_restore);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/lib/uncached.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/lib/uncached.c
@@ -37,10 +37,12 @@
  */
 unsigned long run_uncached(void *func)
 {
-	register long sp __asm__("$sp");
 	register long ret __asm__("$2");
 	long lfunc = (long)func, ufunc;
 	long usp;
+	long sp;
+
+	__asm__("move %0, $sp" : "=r" (sp));
 
 	if (sp >= (long)CKSEG0 && sp < (long)CKSEG2)
 		usp = CKSEG1ADDR(sp);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/loongson32/common/platform.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/loongson32/common/platform.c
@@ -98,7 +98,7 @@
 	if (plat_dat->bus_id) {
 		__raw_writel(__raw_readl(LS1X_MUX_CTRL0) | GMAC1_USE_UART1 |
 			     GMAC1_USE_UART0, LS1X_MUX_CTRL0);
-		switch (plat_dat->interface) {
+		switch (plat_dat->phy_interface) {
 		case PHY_INTERFACE_MODE_RGMII:
 			val &= ~(GMAC1_USE_TXCLK | GMAC1_USE_PWM23);
 			break;
@@ -107,12 +107,12 @@
 			break;
 		default:
 			pr_err("unsupported mii mode %d\n",
-			       plat_dat->interface);
+			       plat_dat->phy_interface);
 			return -ENOTSUPP;
 		}
 		val &= ~GMAC1_SHUT;
 	} else {
-		switch (plat_dat->interface) {
+		switch (plat_dat->phy_interface) {
 		case PHY_INTERFACE_MODE_RGMII:
 			val &= ~(GMAC0_USE_TXCLK | GMAC0_USE_PWM01);
 			break;
@@ -121,7 +121,7 @@
 			break;
 		default:
 			pr_err("unsupported mii mode %d\n",
-			       plat_dat->interface);
+			       plat_dat->phy_interface);
 			return -ENOTSUPP;
 		}
 		val &= ~GMAC0_SHUT;
@@ -131,7 +131,7 @@
 	plat_dat = dev_get_platdata(&pdev->dev);
 
 	val &= ~PHY_INTF_SELI;
-	if (plat_dat->interface == PHY_INTERFACE_MODE_RMII)
+	if (plat_dat->phy_interface == PHY_INTERFACE_MODE_RMII)
 		val |= 0x4 << PHY_INTF_SELI_SHIFT;
 	__raw_writel(val, LS1X_MUX_CTRL1);
 
@@ -146,9 +146,9 @@
 	.bus_id			= 0,
 	.phy_addr		= -1,
 #if defined(CONFIG_LOONGSON1_LS1B)
-	.interface		= PHY_INTERFACE_MODE_MII,
+	.phy_interface		= PHY_INTERFACE_MODE_MII,
 #elif defined(CONFIG_LOONGSON1_LS1C)
-	.interface		= PHY_INTERFACE_MODE_RMII,
+	.phy_interface		= PHY_INTERFACE_MODE_RMII,
 #endif
 	.mdio_bus_data		= &ls1x_mdio_bus_data,
 	.dma_cfg		= &ls1x_eth_dma_cfg,
@@ -186,7 +186,7 @@
 static struct plat_stmmacenet_data ls1x_eth1_pdata = {
 	.bus_id			= 1,
 	.phy_addr		= -1,
-	.interface		= PHY_INTERFACE_MODE_MII,
+	.phy_interface		= PHY_INTERFACE_MODE_MII,
 	.mdio_bus_data		= &ls1x_mdio_bus_data,
 	.dma_cfg		= &ls1x_eth_dma_cfg,
 	.has_gmac		= 1,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/loongson32/ls1c/board.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/loongson32/ls1c/board.c
@@ -15,7 +15,6 @@
 static int __init ls1c_platform_init(void)
 {
 	ls1x_serial_set_uartclk(&ls1x_uart_pdev);
-	ls1x_rtc_set_extclk(&ls1x_rtc_pdev);
 
 	return platform_add_devices(ls1c_platform_devices,
 				   ARRAY_SIZE(ls1c_platform_devices));
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/loongson64/loongson-3/numa.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/loongson64/loongson-3/numa.c
@@ -200,6 +200,9 @@
 		if (node_end_pfn(0) >= (0xffffffff >> PAGE_SHIFT))
 			memblock_reserve((node_addrspace_offset | 0xfe000000),
 					 32 << 20);
+
+		/* Reserve pfn range 0~node[0]->node_start_pfn */
+		memblock_reserve(0, PAGE_SIZE * start_pfn);
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/loongson64/loongson-3/platform.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/loongson64/loongson-3/platform.c
@@ -27,6 +27,9 @@
 			continue;
 
 		pdev = kzalloc(sizeof(struct platform_device), GFP_KERNEL);
+		if (!pdev)
+			return -ENOMEM;
+
 		pdev->name = loongson_sysconf.sensors[i].name;
 		pdev->id = loongson_sysconf.sensors[i].id;
 		pdev->dev.platform_data = &loongson_sysconf.sensors[i];
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/mm/c-r4k.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/mm/c-r4k.c
@@ -1560,7 +1560,7 @@
 	return 1;
 }
 
-static void __init loongson2_sc_init(void)
+static void loongson2_sc_init(void)
 {
 	struct cpuinfo_mips *c = &current_cpu_data;
 
@@ -1576,7 +1576,7 @@
 	c->options |= MIPS_CPU_INCLUSIVE_CACHES;
 }
 
-static void __init loongson3_sc_init(void)
+static void loongson3_sc_init(void)
 {
 	struct cpuinfo_mips *c = &current_cpu_data;
 	unsigned int config2, lsize;
@@ -1676,7 +1676,11 @@
 				printk("MIPS secondary cache %ldkB, %s, linesize %d bytes.\n",
 				       scache_size >> 10,
 				       way_string[c->scache.ways], c->scache.linesz);
+
+				if (current_cpu_type() == CPU_BMIPS5000)
+					c->options |= MIPS_CPU_INCLUSIVE_CACHES;
 			}
+
 #else
 			if (!(c->scache.flags & MIPS_CACHE_NOT_PRESENT))
 				panic("Dunno how to handle MIPS32 / MIPS64 second level cache");
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/mm/dma-noncoherent.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/mm/dma-noncoherent.c
@@ -27,7 +27,7 @@
  * R10000 and R12000 are used in such systems, the SGI IP28 Indigo² rsp.
  * SGI IP32 aka O2.
  */
-static inline bool cpu_needs_post_dma_flush(struct device *dev)
+static inline bool cpu_needs_post_dma_flush(void)
 {
 	switch (boot_cpu_type()) {
 	case CPU_R10000:
@@ -118,17 +118,17 @@
 	} while (left);
 }
 
-void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr,
-		size_t size, enum dma_data_direction dir)
+void arch_sync_dma_for_device(phys_addr_t paddr, size_t size,
+		enum dma_data_direction dir)
 {
 	dma_sync_phys(paddr, size, dir);
 }
 
 #ifdef CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU
-void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr,
-		size_t size, enum dma_data_direction dir)
+void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size,
+		enum dma_data_direction dir)
 {
-	if (cpu_needs_post_dma_flush(dev))
+	if (cpu_needs_post_dma_flush())
 		dma_sync_phys(paddr, size, dir);
 }
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/mm/init.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/mm/init.c
@@ -84,7 +84,7 @@
 static void *__kmap_pgprot(struct page *page, unsigned long addr, pgprot_t prot)
 {
 	enum fixed_addresses idx;
-	unsigned int uninitialized_var(old_mmid);
+	unsigned int old_mmid;
 	unsigned long vaddr, flags, entrylo;
 	unsigned long old_ctx;
 	pte_t pte;
@@ -416,7 +416,12 @@
 		       (highend_pfn - max_low_pfn) << (PAGE_SHIFT - 10));
 		max_zone_pfns[ZONE_HIGHMEM] = max_low_pfn;
 	}
+
+	max_mapnr = highend_pfn ? highend_pfn : max_low_pfn;
+#else
+	max_mapnr = max_low_pfn;
 #endif
+	high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT);
 
 	free_area_init_nodes(max_zone_pfns);
 }
@@ -452,16 +457,6 @@
 	 */
 	BUILD_BUG_ON(IS_ENABLED(CONFIG_32BIT) && (_PFN_SHIFT > PAGE_SHIFT));
 
-#ifdef CONFIG_HIGHMEM
-#ifdef CONFIG_DISCONTIGMEM
-#error "CONFIG_HIGHMEM and CONFIG_DISCONTIGMEM dont work together yet"
-#endif
-	max_mapnr = highend_pfn ? highend_pfn : max_low_pfn;
-#else
-	max_mapnr = max_low_pfn;
-#endif
-	high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT);
-
 	maar_init();
 	memblock_free_all();
 	setup_zero_pages();	/* Setup zeroed pages.  */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/mm/sc-mips.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/mm/sc-mips.c
@@ -147,7 +147,7 @@
 	return 1;
 }
 
-static int __init mips_sc_probe_cm3(void)
+static int mips_sc_probe_cm3(void)
 {
 	struct cpuinfo_mips *c = &current_cpu_data;
 	unsigned long cfg = read_gcr_l2_config();
@@ -181,7 +181,7 @@
 	return 0;
 }
 
-static inline int __init mips_sc_probe(void)
+static inline int mips_sc_probe(void)
 {
 	struct cpuinfo_mips *c = &current_cpu_data;
 	unsigned int config1, config2;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/mm/tlb-r4k.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/mm/tlb-r4k.c
@@ -120,7 +120,7 @@
 		if (size <= (current_cpu_data.tlbsizeftlbsets ?
 			     current_cpu_data.tlbsize / 8 :
 			     current_cpu_data.tlbsize / 2)) {
-			unsigned long old_entryhi, uninitialized_var(old_mmid);
+			unsigned long old_entryhi, old_mmid;
 			int newpid = cpu_asid(cpu, mm);
 
 			old_entryhi = read_c0_entryhi();
@@ -214,7 +214,7 @@
 	int cpu = smp_processor_id();
 
 	if (cpu_context(cpu, vma->vm_mm) != 0) {
-		unsigned long uninitialized_var(old_mmid);
+		unsigned long old_mmid;
 		unsigned long flags, old_entryhi;
 		int idx;
 
@@ -381,7 +381,7 @@
 #ifdef CONFIG_XPA
 	panic("Broken for XPA kernels");
 #else
-	unsigned int uninitialized_var(old_mmid);
+	unsigned int old_mmid;
 	unsigned long flags;
 	unsigned long wired;
 	unsigned long old_pagemask;
@@ -437,6 +437,7 @@
 	}
 	return mask == PM_HUGE_MASK;
 }
+EXPORT_SYMBOL(has_transparent_hugepage);
 
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE  */
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/mm/tlbex.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/mm/tlbex.c
@@ -629,7 +629,7 @@
 		return;
 	}
 
-	if (cpu_has_rixi && !!_PAGE_NO_EXEC) {
+	if (cpu_has_rixi && _PAGE_NO_EXEC != 0) {
 		if (fill_includes_sw_bits) {
 			UASM_i_ROTR(p, reg, reg, ilog2(_PAGE_GLOBAL));
 		} else {
@@ -1480,6 +1480,7 @@
 
 static void setup_pw(void)
 {
+	unsigned int pwctl;
 	unsigned long pgd_i, pgd_w;
 #ifndef __PAGETABLE_PMD_FOLDED
 	unsigned long pmd_i, pmd_w;
@@ -1506,6 +1507,7 @@
 
 	pte_i = ilog2(_PAGE_GLOBAL);
 	pte_w = 0;
+	pwctl = 1 << 30; /* Set PWDirExt */
 
 #ifndef __PAGETABLE_PMD_FOLDED
 	write_c0_pwfield(pgd_i << 24 | pmd_i << 12 | pt_i << 6 | pte_i);
@@ -1516,8 +1518,9 @@
 #endif
 
 #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
-	write_c0_pwctl(1 << 6 | psn);
+	pwctl |= (1 << 6 | psn);
 #endif
+	write_c0_pwctl(pwctl);
 	write_c0_kpgd((long)swapper_pg_dir);
 	kscratch_used_mask |= (1 << 7); /* KScratch6 is used for KPGD */
 }
@@ -2565,7 +2568,7 @@
 	unsigned long entry;
 	unsigned pabits, fillbits;
 
-	if (!cpu_has_rixi || !_PAGE_NO_EXEC) {
+	if (!cpu_has_rixi || _PAGE_NO_EXEC == 0) {
 		/*
 		 * We'll only be making use of the fact that we can rotate bits
 		 * into the fill if the CPU supports RIXI, so don't bother
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/mti-malta/malta-dtshim.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/mti-malta/malta-dtshim.c
@@ -22,7 +22,7 @@
 #define  ROCIT_CONFIG_GEN1_MEMMAP_SHIFT	8
 #define  ROCIT_CONFIG_GEN1_MEMMAP_MASK	(0xf << 8)
 
-static unsigned char fdt_buf[16 << 10] __initdata;
+static unsigned char fdt_buf[16 << 10] __initdata __aligned(8);
 
 /* determined physical memory size, not overridden by command line args	 */
 extern unsigned long physical_memsize;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/mti-malta/malta-platform.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/mti-malta/malta-platform.c
@@ -47,7 +47,8 @@
 		.mapbase	= 0x1f000900,	/* The CBUS UART */
 		.irq		= MIPS_CPU_IRQ_BASE + MIPSCPU_INT_MB2,
 		.uartclk	= 3686400,	/* Twice the usual clk! */
-		.iotype		= UPIO_MEM32,
+		.iotype		= IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) ?
+				  UPIO_MEM32BE : UPIO_MEM32,
 		.flags		= CBUS_UART_FLAGS,
 		.regshift	= 3,
 	},
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/net/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/net/Makefile
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
 # MIPS networking code
 
+obj-$(CONFIG_MIPS_CBPF_JIT) += bpf_jit.o bpf_jit_asm.o
 obj-$(CONFIG_MIPS_EBPF_JIT) += ebpf_jit.o
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/net/bpf_jit.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/net/bpf_jit.c
@@ -0,0 +1,1299 @@
+/*
+ * Just-In-Time compiler for BPF filters on MIPS
+ *
+ * Copyright (c) 2014 Imagination Technologies Ltd.
+ * Author: Markos Chandras <markos.chandras@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ */
+
+#include <linux/bitops.h>
+#include <linux/compiler.h>
+#include <linux/errno.h>
+#include <linux/filter.h>
+#include <linux/if_vlan.h>
+#include <linux/moduleloader.h>
+#include <linux/netdevice.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <asm/asm.h>
+#include <asm/bitops.h>
+#include <asm/cacheflush.h>
+#include <asm/cpu-features.h>
+#include <asm/uasm.h>
+
+#include "bpf_jit.h"
+
+/* ABI
+ * r_skb_hl	SKB header length
+ * r_data	SKB data pointer
+ * r_off	Offset
+ * r_A		BPF register A
+ * r_X		BPF register X
+ * r_skb	*skb
+ * r_M		*scratch memory
+ * r_skb_len	SKB length
+ *
+ * On entry (*bpf_func)(*skb, *filter)
+ * a0 = MIPS_R_A0 = skb;
+ * a1 = MIPS_R_A1 = filter;
+ *
+ * Stack
+ * ...
+ * M[15]
+ * M[14]
+ * M[13]
+ * ...
+ * M[0] <-- r_M
+ * saved reg k-1
+ * saved reg k-2
+ * ...
+ * saved reg 0 <-- r_sp
+ * <no argument area>
+ *
+ *                     Packet layout
+ *
+ * <--------------------- len ------------------------>
+ * <--skb-len(r_skb_hl)-->< ----- skb->data_len ------>
+ * ----------------------------------------------------
+ * |                  skb->data                       |
+ * ----------------------------------------------------
+ */
+
+#define ptr typeof(unsigned long)
+
+#define SCRATCH_OFF(k)		(4 * (k))
+
+/* JIT flags */
+#define SEEN_CALL		(1 << BPF_MEMWORDS)
+#define SEEN_SREG_SFT		(BPF_MEMWORDS + 1)
+#define SEEN_SREG_BASE		(1 << SEEN_SREG_SFT)
+#define SEEN_SREG(x)		(SEEN_SREG_BASE << (x))
+#define SEEN_OFF		SEEN_SREG(2)
+#define SEEN_A			SEEN_SREG(3)
+#define SEEN_X			SEEN_SREG(4)
+#define SEEN_SKB		SEEN_SREG(5)
+#define SEEN_MEM		SEEN_SREG(6)
+/* SEEN_SK_DATA also implies skb_hl an skb_len */
+#define SEEN_SKB_DATA		(SEEN_SREG(7) | SEEN_SREG(1) | SEEN_SREG(0))
+
+/* Arguments used by JIT */
+#define ARGS_USED_BY_JIT	2 /* only applicable to 64-bit */
+
+#define SBIT(x)			(1 << (x)) /* Signed version of BIT() */
+
+/**
+ * struct jit_ctx - JIT context
+ * @skf:		The sk_filter
+ * @prologue_bytes:	Number of bytes for prologue
+ * @idx:		Instruction index
+ * @flags:		JIT flags
+ * @offsets:		Instruction offsets
+ * @target:		Memory location for the compiled filter
+ */
+struct jit_ctx {
+	const struct bpf_prog *skf;
+	unsigned int prologue_bytes;
+	u32 idx;
+	u32 flags;
+	u32 *offsets;
+	u32 *target;
+};
+
+
+static inline int optimize_div(u32 *k)
+{
+	/* power of 2 divides can be implemented with right shift */
+	if (!(*k & (*k-1))) {
+		*k = ilog2(*k);
+		return 1;
+	}
+
+	return 0;
+}
+
+static inline void emit_jit_reg_move(ptr dst, ptr src, struct jit_ctx *ctx);
+
+/* Simply emit the instruction if the JIT memory space has been allocated */
+#define emit_instr(ctx, func, ...)			\
+do {							\
+	if ((ctx)->target != NULL) {			\
+		u32 *p = &(ctx)->target[ctx->idx];	\
+		uasm_i_##func(&p, ##__VA_ARGS__);	\
+	}						\
+	(ctx)->idx++;					\
+} while (0)
+
+/*
+ * Similar to emit_instr but it must be used when we need to emit
+ * 32-bit or 64-bit instructions
+ */
+#define emit_long_instr(ctx, func, ...)			\
+do {							\
+	if ((ctx)->target != NULL) {			\
+		u32 *p = &(ctx)->target[ctx->idx];	\
+		UASM_i_##func(&p, ##__VA_ARGS__);	\
+	}						\
+	(ctx)->idx++;					\
+} while (0)
+
+/* Determine if immediate is within the 16-bit signed range */
+static inline bool is_range16(s32 imm)
+{
+	return !(imm >= SBIT(15) || imm < -SBIT(15));
+}
+
+static inline void emit_addu(unsigned int dst, unsigned int src1,
+			     unsigned int src2, struct jit_ctx *ctx)
+{
+	emit_instr(ctx, addu, dst, src1, src2);
+}
+
+static inline void emit_nop(struct jit_ctx *ctx)
+{
+	emit_instr(ctx, nop);
+}
+
+/* Load a u32 immediate to a register */
+static inline void emit_load_imm(unsigned int dst, u32 imm, struct jit_ctx *ctx)
+{
+	if (ctx->target != NULL) {
+		/* addiu can only handle s16 */
+		if (!is_range16(imm)) {
+			u32 *p = &ctx->target[ctx->idx];
+			uasm_i_lui(&p, r_tmp_imm, (s32)imm >> 16);
+			p = &ctx->target[ctx->idx + 1];
+			uasm_i_ori(&p, dst, r_tmp_imm, imm & 0xffff);
+		} else {
+			u32 *p = &ctx->target[ctx->idx];
+			uasm_i_addiu(&p, dst, r_zero, imm);
+		}
+	}
+	ctx->idx++;
+
+	if (!is_range16(imm))
+		ctx->idx++;
+}
+
+static inline void emit_or(unsigned int dst, unsigned int src1,
+			   unsigned int src2, struct jit_ctx *ctx)
+{
+	emit_instr(ctx, or, dst, src1, src2);
+}
+
+static inline void emit_ori(unsigned int dst, unsigned src, u32 imm,
+			    struct jit_ctx *ctx)
+{
+	if (imm >= BIT(16)) {
+		emit_load_imm(r_tmp, imm, ctx);
+		emit_or(dst, src, r_tmp, ctx);
+	} else {
+		emit_instr(ctx, ori, dst, src, imm);
+	}
+}
+
+static inline void emit_daddiu(unsigned int dst, unsigned int src,
+			       int imm, struct jit_ctx *ctx)
+{
+	/*
+	 * Only used for stack, so the imm is relatively small
+	 * and it fits in 15-bits
+	 */
+	emit_instr(ctx, daddiu, dst, src, imm);
+}
+
+static inline void emit_addiu(unsigned int dst, unsigned int src,
+			      u32 imm, struct jit_ctx *ctx)
+{
+	if (!is_range16(imm)) {
+		emit_load_imm(r_tmp, imm, ctx);
+		emit_addu(dst, r_tmp, src, ctx);
+	} else {
+		emit_instr(ctx, addiu, dst, src, imm);
+	}
+}
+
+static inline void emit_and(unsigned int dst, unsigned int src1,
+			    unsigned int src2, struct jit_ctx *ctx)
+{
+	emit_instr(ctx, and, dst, src1, src2);
+}
+
+static inline void emit_andi(unsigned int dst, unsigned int src,
+			     u32 imm, struct jit_ctx *ctx)
+{
+	/* If imm does not fit in u16 then load it to register */
+	if (imm >= BIT(16)) {
+		emit_load_imm(r_tmp, imm, ctx);
+		emit_and(dst, src, r_tmp, ctx);
+	} else {
+		emit_instr(ctx, andi, dst, src, imm);
+	}
+}
+
+static inline void emit_xor(unsigned int dst, unsigned int src1,
+			    unsigned int src2, struct jit_ctx *ctx)
+{
+	emit_instr(ctx, xor, dst, src1, src2);
+}
+
+static inline void emit_xori(ptr dst, ptr src, u32 imm, struct jit_ctx *ctx)
+{
+	/* If imm does not fit in u16 then load it to register */
+	if (imm >= BIT(16)) {
+		emit_load_imm(r_tmp, imm, ctx);
+		emit_xor(dst, src, r_tmp, ctx);
+	} else {
+		emit_instr(ctx, xori, dst, src, imm);
+	}
+}
+
+static inline void emit_stack_offset(int offset, struct jit_ctx *ctx)
+{
+	emit_long_instr(ctx, ADDIU, r_sp, r_sp, offset);
+}
+
+static inline void emit_subu(unsigned int dst, unsigned int src1,
+			     unsigned int src2, struct jit_ctx *ctx)
+{
+	emit_instr(ctx, subu, dst, src1, src2);
+}
+
+static inline void emit_neg(unsigned int reg, struct jit_ctx *ctx)
+{
+	emit_subu(reg, r_zero, reg, ctx);
+}
+
+static inline void emit_sllv(unsigned int dst, unsigned int src,
+			     unsigned int sa, struct jit_ctx *ctx)
+{
+	emit_instr(ctx, sllv, dst, src, sa);
+}
+
+static inline void emit_sll(unsigned int dst, unsigned int src,
+			    unsigned int sa, struct jit_ctx *ctx)
+{
+	/* sa is 5-bits long */
+	if (sa >= BIT(5))
+		/* Shifting >= 32 results in zero */
+		emit_jit_reg_move(dst, r_zero, ctx);
+	else
+		emit_instr(ctx, sll, dst, src, sa);
+}
+
+static inline void emit_srlv(unsigned int dst, unsigned int src,
+			     unsigned int sa, struct jit_ctx *ctx)
+{
+	emit_instr(ctx, srlv, dst, src, sa);
+}
+
+static inline void emit_srl(unsigned int dst, unsigned int src,
+			    unsigned int sa, struct jit_ctx *ctx)
+{
+	/* sa is 5-bits long */
+	if (sa >= BIT(5))
+		/* Shifting >= 32 results in zero */
+		emit_jit_reg_move(dst, r_zero, ctx);
+	else
+		emit_instr(ctx, srl, dst, src, sa);
+}
+
+static inline void emit_slt(unsigned int dst, unsigned int src1,
+			    unsigned int src2, struct jit_ctx *ctx)
+{
+	emit_instr(ctx, slt, dst, src1, src2);
+}
+
+static inline void emit_sltu(unsigned int dst, unsigned int src1,
+			     unsigned int src2, struct jit_ctx *ctx)
+{
+	emit_instr(ctx, sltu, dst, src1, src2);
+}
+
+static inline void emit_sltiu(unsigned dst, unsigned int src,
+			      unsigned int imm, struct jit_ctx *ctx)
+{
+	/* 16 bit immediate */
+	if (!is_range16((s32)imm)) {
+		emit_load_imm(r_tmp, imm, ctx);
+		emit_sltu(dst, src, r_tmp, ctx);
+	} else {
+		emit_instr(ctx, sltiu, dst, src, imm);
+	}
+
+}
+
+/* Store register on the stack */
+static inline void emit_store_stack_reg(ptr reg, ptr base,
+					unsigned int offset,
+					struct jit_ctx *ctx)
+{
+	emit_long_instr(ctx, SW, reg, offset, base);
+}
+
+static inline void emit_store(ptr reg, ptr base, unsigned int offset,
+			      struct jit_ctx *ctx)
+{
+	emit_instr(ctx, sw, reg, offset, base);
+}
+
+static inline void emit_load_stack_reg(ptr reg, ptr base,
+				       unsigned int offset,
+				       struct jit_ctx *ctx)
+{
+	emit_long_instr(ctx, LW, reg, offset, base);
+}
+
+static inline void emit_load(unsigned int reg, unsigned int base,
+			     unsigned int offset, struct jit_ctx *ctx)
+{
+	emit_instr(ctx, lw, reg, offset, base);
+}
+
+static inline void emit_load_byte(unsigned int reg, unsigned int base,
+				  unsigned int offset, struct jit_ctx *ctx)
+{
+	emit_instr(ctx, lb, reg, offset, base);
+}
+
+static inline void emit_half_load(unsigned int reg, unsigned int base,
+				  unsigned int offset, struct jit_ctx *ctx)
+{
+	emit_instr(ctx, lh, reg, offset, base);
+}
+
+static inline void emit_half_load_unsigned(unsigned int reg, unsigned int base,
+					   unsigned int offset, struct jit_ctx *ctx)
+{
+	emit_instr(ctx, lhu, reg, offset, base);
+}
+
+static inline void emit_mul(unsigned int dst, unsigned int src1,
+			    unsigned int src2, struct jit_ctx *ctx)
+{
+	emit_instr(ctx, mul, dst, src1, src2);
+}
+
+static inline void emit_div(unsigned int dst, unsigned int src,
+			    struct jit_ctx *ctx)
+{
+	if (ctx->target != NULL) {
+		u32 *p = &ctx->target[ctx->idx];
+		uasm_i_divu(&p, dst, src);
+		p = &ctx->target[ctx->idx + 1];
+		uasm_i_mflo(&p, dst);
+	}
+	ctx->idx += 2; /* 2 insts */
+}
+
+static inline void emit_mod(unsigned int dst, unsigned int src,
+			    struct jit_ctx *ctx)
+{
+	if (ctx->target != NULL) {
+		u32 *p = &ctx->target[ctx->idx];
+		uasm_i_divu(&p, dst, src);
+		p = &ctx->target[ctx->idx + 1];
+		uasm_i_mfhi(&p, dst);
+	}
+	ctx->idx += 2; /* 2 insts */
+}
+
+static inline void emit_dsll(unsigned int dst, unsigned int src,
+			     unsigned int sa, struct jit_ctx *ctx)
+{
+	emit_instr(ctx, dsll, dst, src, sa);
+}
+
+static inline void emit_dsrl32(unsigned int dst, unsigned int src,
+			       unsigned int sa, struct jit_ctx *ctx)
+{
+	emit_instr(ctx, dsrl32, dst, src, sa);
+}
+
+static inline void emit_wsbh(unsigned int dst, unsigned int src,
+			     struct jit_ctx *ctx)
+{
+	emit_instr(ctx, wsbh, dst, src);
+}
+
+/* load pointer to register */
+static inline void emit_load_ptr(unsigned int dst, unsigned int src,
+				     int imm, struct jit_ctx *ctx)
+{
+	/* src contains the base addr of the 32/64-pointer */
+	emit_long_instr(ctx, LW, dst, imm, src);
+}
+
+/* load a function pointer to register */
+static inline void emit_load_func(unsigned int reg, ptr imm,
+				  struct jit_ctx *ctx)
+{
+	if (IS_ENABLED(CONFIG_64BIT)) {
+		/* At this point imm is always 64-bit */
+		emit_load_imm(r_tmp, (u64)imm >> 32, ctx);
+		emit_dsll(r_tmp_imm, r_tmp, 16, ctx); /* left shift by 16 */
+		emit_ori(r_tmp, r_tmp_imm, (imm >> 16) & 0xffff, ctx);
+		emit_dsll(r_tmp_imm, r_tmp, 16, ctx); /* left shift by 16 */
+		emit_ori(reg, r_tmp_imm, imm & 0xffff, ctx);
+	} else {
+		emit_load_imm(reg, imm, ctx);
+	}
+}
+
+/* Move to real MIPS register */
+static inline void emit_reg_move(ptr dst, ptr src, struct jit_ctx *ctx)
+{
+	emit_long_instr(ctx, ADDU, dst, src, r_zero);
+}
+
+/* Move to JIT (32-bit) register */
+static inline void emit_jit_reg_move(ptr dst, ptr src, struct jit_ctx *ctx)
+{
+	emit_addu(dst, src, r_zero, ctx);
+}
+
+/* Compute the immediate value for PC-relative branches. */
+static inline u32 b_imm(unsigned int tgt, struct jit_ctx *ctx)
+{
+	if (ctx->target == NULL)
+		return 0;
+
+	/*
+	 * We want a pc-relative branch. We only do forward branches
+	 * so tgt is always after pc. tgt is the instruction offset
+	 * we want to jump to.
+
+	 * Branch on MIPS:
+	 * I: target_offset <- sign_extend(offset)
+	 * I+1: PC += target_offset (delay slot)
+	 *
+	 * ctx->idx currently points to the branch instruction
+	 * but the offset is added to the delay slot so we need
+	 * to subtract 4.
+	 */
+	return ctx->offsets[tgt] -
+		(ctx->idx * 4 - ctx->prologue_bytes) - 4;
+}
+
+static inline void emit_bcond(int cond, unsigned int reg1, unsigned int reg2,
+			     unsigned int imm, struct jit_ctx *ctx)
+{
+	if (ctx->target != NULL) {
+		u32 *p = &ctx->target[ctx->idx];
+
+		switch (cond) {
+		case MIPS_COND_EQ:
+			uasm_i_beq(&p, reg1, reg2, imm);
+			break;
+		case MIPS_COND_NE:
+			uasm_i_bne(&p, reg1, reg2, imm);
+			break;
+		case MIPS_COND_ALL:
+			uasm_i_b(&p, imm);
+			break;
+		default:
+			pr_warn("%s: Unhandled branch conditional: %d\n",
+				__func__, cond);
+		}
+	}
+	ctx->idx++;
+}
+
+static inline void emit_b(unsigned int imm, struct jit_ctx *ctx)
+{
+	emit_bcond(MIPS_COND_ALL, r_zero, r_zero, imm, ctx);
+}
+
+static inline void emit_jalr(unsigned int link, unsigned int reg,
+			     struct jit_ctx *ctx)
+{
+	emit_instr(ctx, jalr, link, reg);
+}
+
+static inline void emit_jr(unsigned int reg, struct jit_ctx *ctx)
+{
+	emit_instr(ctx, jr, reg);
+}
+
+static inline u16 align_sp(unsigned int num)
+{
+	/* Double word alignment for 32-bit, quadword for 64-bit */
+	unsigned int align = IS_ENABLED(CONFIG_64BIT) ? 16 : 8;
+	num = (num + (align - 1)) & -align;
+	return num;
+}
+
+static void save_bpf_jit_regs(struct jit_ctx *ctx, unsigned offset)
+{
+	int i = 0, real_off = 0;
+	u32 sflags, tmp_flags;
+
+	/* Adjust the stack pointer */
+	if (offset)
+		emit_stack_offset(-align_sp(offset), ctx);
+
+	tmp_flags = sflags = ctx->flags >> SEEN_SREG_SFT;
+	/* sflags is essentially a bitmap */
+	while (tmp_flags) {
+		if ((sflags >> i) & 0x1) {
+			emit_store_stack_reg(MIPS_R_S0 + i, r_sp, real_off,
+					     ctx);
+			real_off += SZREG;
+		}
+		i++;
+		tmp_flags >>= 1;
+	}
+
+	/* save return address */
+	if (ctx->flags & SEEN_CALL) {
+		emit_store_stack_reg(r_ra, r_sp, real_off, ctx);
+		real_off += SZREG;
+	}
+
+	/* Setup r_M leaving the alignment gap if necessary */
+	if (ctx->flags & SEEN_MEM) {
+		if (real_off % (SZREG * 2))
+			real_off += SZREG;
+		emit_long_instr(ctx, ADDIU, r_M, r_sp, real_off);
+	}
+}
+
+static void restore_bpf_jit_regs(struct jit_ctx *ctx,
+				 unsigned int offset)
+{
+	int i, real_off = 0;
+	u32 sflags, tmp_flags;
+
+	tmp_flags = sflags = ctx->flags >> SEEN_SREG_SFT;
+	/* sflags is a bitmap */
+	i = 0;
+	while (tmp_flags) {
+		if ((sflags >> i) & 0x1) {
+			emit_load_stack_reg(MIPS_R_S0 + i, r_sp, real_off,
+					    ctx);
+			real_off += SZREG;
+		}
+		i++;
+		tmp_flags >>= 1;
+	}
+
+	/* restore return address */
+	if (ctx->flags & SEEN_CALL)
+		emit_load_stack_reg(r_ra, r_sp, real_off, ctx);
+
+	/* Restore the sp and discard the scrach memory */
+	if (offset)
+		emit_stack_offset(align_sp(offset), ctx);
+}
+
+static unsigned int get_stack_depth(struct jit_ctx *ctx)
+{
+	int sp_off = 0;
+
+
+	/* How may s* regs do we need to preserved? */
+	sp_off += hweight32(ctx->flags >> SEEN_SREG_SFT) * SZREG;
+
+	if (ctx->flags & SEEN_MEM)
+		sp_off += 4 * BPF_MEMWORDS; /* BPF_MEMWORDS are 32-bit */
+
+	if (ctx->flags & SEEN_CALL)
+		sp_off += SZREG; /* Space for our ra register */
+
+	return sp_off;
+}
+
+static void build_prologue(struct jit_ctx *ctx)
+{
+	int sp_off;
+
+	/* Calculate the total offset for the stack pointer */
+	sp_off = get_stack_depth(ctx);
+	save_bpf_jit_regs(ctx, sp_off);
+
+	if (ctx->flags & SEEN_SKB)
+		emit_reg_move(r_skb, MIPS_R_A0, ctx);
+
+	if (ctx->flags & SEEN_SKB_DATA) {
+		/* Load packet length */
+		emit_load(r_skb_len, r_skb, offsetof(struct sk_buff, len),
+			  ctx);
+		emit_load(r_tmp, r_skb, offsetof(struct sk_buff, data_len),
+			  ctx);
+		/* Load the data pointer */
+		emit_load_ptr(r_skb_data, r_skb,
+			      offsetof(struct sk_buff, data), ctx);
+		/* Load the header length */
+		emit_subu(r_skb_hl, r_skb_len, r_tmp, ctx);
+	}
+
+	if (ctx->flags & SEEN_X)
+		emit_jit_reg_move(r_X, r_zero, ctx);
+
+	/*
+	 * Do not leak kernel data to userspace, we only need to clear
+	 * r_A if it is ever used.  In fact if it is never used, we
+	 * will not save/restore it, so clearing it in this case would
+	 * corrupt the state of the caller.
+	 */
+	if (bpf_needs_clear_a(&ctx->skf->insns[0]) &&
+	    (ctx->flags & SEEN_A))
+		emit_jit_reg_move(r_A, r_zero, ctx);
+}
+
+static void build_epilogue(struct jit_ctx *ctx)
+{
+	unsigned int sp_off;
+
+	/* Calculate the total offset for the stack pointer */
+
+	sp_off = get_stack_depth(ctx);
+	restore_bpf_jit_regs(ctx, sp_off);
+
+	/* Return */
+	emit_jr(r_ra, ctx);
+	emit_nop(ctx);
+}
+
+#define CHOOSE_LOAD_FUNC(K, func) \
+	((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative : func) : \
+	 func##_positive)
+
+static bool is_bad_offset(int b_off)
+{
+	return b_off > 0x1ffff || b_off < -0x20000;
+}
+
+static int build_body(struct jit_ctx *ctx)
+{
+	const struct bpf_prog *prog = ctx->skf;
+	const struct sock_filter *inst;
+	unsigned int i, off, condt;
+	u32 k, b_off __maybe_unused;
+	u8 (*sk_load_func)(unsigned long *skb, int offset);
+
+	for (i = 0; i < prog->len; i++) {
+		u16 code;
+
+		inst = &(prog->insns[i]);
+		pr_debug("%s: code->0x%02x, jt->0x%x, jf->0x%x, k->0x%x\n",
+			 __func__, inst->code, inst->jt, inst->jf, inst->k);
+		k = inst->k;
+		code = bpf_anc_helper(inst);
+
+		if (ctx->target == NULL)
+			ctx->offsets[i] = ctx->idx * 4;
+
+		switch (code) {
+		case BPF_LD | BPF_IMM:
+			/* A <- k ==> li r_A, k */
+			ctx->flags |= SEEN_A;
+			emit_load_imm(r_A, k, ctx);
+			break;
+		case BPF_LD | BPF_W | BPF_LEN:
+			BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, len) != 4);
+			/* A <- len ==> lw r_A, offset(skb) */
+			ctx->flags |= SEEN_SKB | SEEN_A;
+			off = offsetof(struct sk_buff, len);
+			emit_load(r_A, r_skb, off, ctx);
+			break;
+		case BPF_LD | BPF_MEM:
+			/* A <- M[k] ==> lw r_A, offset(M) */
+			ctx->flags |= SEEN_MEM | SEEN_A;
+			emit_load(r_A, r_M, SCRATCH_OFF(k), ctx);
+			break;
+		case BPF_LD | BPF_W | BPF_ABS:
+			/* A <- P[k:4] */
+			sk_load_func = CHOOSE_LOAD_FUNC(k, sk_load_word);
+			goto load;
+		case BPF_LD | BPF_H | BPF_ABS:
+			/* A <- P[k:2] */
+			sk_load_func = CHOOSE_LOAD_FUNC(k, sk_load_half);
+			goto load;
+		case BPF_LD | BPF_B | BPF_ABS:
+			/* A <- P[k:1] */
+			sk_load_func = CHOOSE_LOAD_FUNC(k, sk_load_byte);
+load:
+			emit_load_imm(r_off, k, ctx);
+load_common:
+			ctx->flags |= SEEN_CALL | SEEN_OFF |
+				SEEN_SKB | SEEN_A | SEEN_SKB_DATA;
+
+			emit_load_func(r_s0, (ptr)sk_load_func, ctx);
+			emit_reg_move(MIPS_R_A0, r_skb, ctx);
+			emit_jalr(MIPS_R_RA, r_s0, ctx);
+			/* Load second argument to delay slot */
+			emit_reg_move(MIPS_R_A1, r_off, ctx);
+			/* Check the error value */
+			emit_bcond(MIPS_COND_EQ, r_ret, 0, b_imm(i + 1, ctx),
+				   ctx);
+			/* Load return register on DS for failures */
+			emit_reg_move(r_ret, r_zero, ctx);
+			/* Return with error */
+			b_off = b_imm(prog->len, ctx);
+			if (is_bad_offset(b_off))
+				return -E2BIG;
+			emit_b(b_off, ctx);
+			emit_nop(ctx);
+			break;
+		case BPF_LD | BPF_W | BPF_IND:
+			/* A <- P[X + k:4] */
+			sk_load_func = sk_load_word;
+			goto load_ind;
+		case BPF_LD | BPF_H | BPF_IND:
+			/* A <- P[X + k:2] */
+			sk_load_func = sk_load_half;
+			goto load_ind;
+		case BPF_LD | BPF_B | BPF_IND:
+			/* A <- P[X + k:1] */
+			sk_load_func = sk_load_byte;
+load_ind:
+			ctx->flags |= SEEN_OFF | SEEN_X;
+			emit_addiu(r_off, r_X, k, ctx);
+			goto load_common;
+		case BPF_LDX | BPF_IMM:
+			/* X <- k */
+			ctx->flags |= SEEN_X;
+			emit_load_imm(r_X, k, ctx);
+			break;
+		case BPF_LDX | BPF_MEM:
+			/* X <- M[k] */
+			ctx->flags |= SEEN_X | SEEN_MEM;
+			emit_load(r_X, r_M, SCRATCH_OFF(k), ctx);
+			break;
+		case BPF_LDX | BPF_W | BPF_LEN:
+			/* X <- len */
+			ctx->flags |= SEEN_X | SEEN_SKB;
+			off = offsetof(struct sk_buff, len);
+			emit_load(r_X, r_skb, off, ctx);
+			break;
+		case BPF_LDX | BPF_B | BPF_MSH:
+			/* X <- 4 * (P[k:1] & 0xf) */
+			ctx->flags |= SEEN_X | SEEN_CALL | SEEN_SKB;
+			/* Load offset to a1 */
+			emit_load_func(r_s0, (ptr)sk_load_byte, ctx);
+			/*
+			 * This may emit two instructions so it may not fit
+			 * in the delay slot. So use a0 in the delay slot.
+			 */
+			emit_load_imm(MIPS_R_A1, k, ctx);
+			emit_jalr(MIPS_R_RA, r_s0, ctx);
+			emit_reg_move(MIPS_R_A0, r_skb, ctx); /* delay slot */
+			/* Check the error value */
+			b_off = b_imm(prog->len, ctx);
+			if (is_bad_offset(b_off))
+				return -E2BIG;
+			emit_bcond(MIPS_COND_NE, r_ret, 0, b_off, ctx);
+			emit_reg_move(r_ret, r_zero, ctx);
+			/* We are good */
+			/* X <- P[1:K] & 0xf */
+			emit_andi(r_X, r_A, 0xf, ctx);
+			/* X << 2 */
+			emit_b(b_imm(i + 1, ctx), ctx);
+			emit_sll(r_X, r_X, 2, ctx); /* delay slot */
+			break;
+		case BPF_ST:
+			/* M[k] <- A */
+			ctx->flags |= SEEN_MEM | SEEN_A;
+			emit_store(r_A, r_M, SCRATCH_OFF(k), ctx);
+			break;
+		case BPF_STX:
+			/* M[k] <- X */
+			ctx->flags |= SEEN_MEM | SEEN_X;
+			emit_store(r_X, r_M, SCRATCH_OFF(k), ctx);
+			break;
+		case BPF_ALU | BPF_ADD | BPF_K:
+			/* A += K */
+			ctx->flags |= SEEN_A;
+			emit_addiu(r_A, r_A, k, ctx);
+			break;
+		case BPF_ALU | BPF_ADD | BPF_X:
+			/* A += X */
+			ctx->flags |= SEEN_A | SEEN_X;
+			emit_addu(r_A, r_A, r_X, ctx);
+			break;
+		case BPF_ALU | BPF_SUB | BPF_K:
+			/* A -= K */
+			ctx->flags |= SEEN_A;
+			emit_addiu(r_A, r_A, -k, ctx);
+			break;
+		case BPF_ALU | BPF_SUB | BPF_X:
+			/* A -= X */
+			ctx->flags |= SEEN_A | SEEN_X;
+			emit_subu(r_A, r_A, r_X, ctx);
+			break;
+		case BPF_ALU | BPF_MUL | BPF_K:
+			/* A *= K */
+			/* Load K to scratch register before MUL */
+			ctx->flags |= SEEN_A;
+			emit_load_imm(r_s0, k, ctx);
+			emit_mul(r_A, r_A, r_s0, ctx);
+			break;
+		case BPF_ALU | BPF_MUL | BPF_X:
+			/* A *= X */
+			ctx->flags |= SEEN_A | SEEN_X;
+			emit_mul(r_A, r_A, r_X, ctx);
+			break;
+		case BPF_ALU | BPF_DIV | BPF_K:
+			/* A /= k */
+			if (k == 1)
+				break;
+			if (optimize_div(&k)) {
+				ctx->flags |= SEEN_A;
+				emit_srl(r_A, r_A, k, ctx);
+				break;
+			}
+			ctx->flags |= SEEN_A;
+			emit_load_imm(r_s0, k, ctx);
+			emit_div(r_A, r_s0, ctx);
+			break;
+		case BPF_ALU | BPF_MOD | BPF_K:
+			/* A %= k */
+			if (k == 1) {
+				ctx->flags |= SEEN_A;
+				emit_jit_reg_move(r_A, r_zero, ctx);
+			} else {
+				ctx->flags |= SEEN_A;
+				emit_load_imm(r_s0, k, ctx);
+				emit_mod(r_A, r_s0, ctx);
+			}
+			break;
+		case BPF_ALU | BPF_DIV | BPF_X:
+			/* A /= X */
+			ctx->flags |= SEEN_X | SEEN_A;
+			/* Check if r_X is zero */
+			b_off = b_imm(prog->len, ctx);
+			if (is_bad_offset(b_off))
+				return -E2BIG;
+			emit_bcond(MIPS_COND_EQ, r_X, r_zero, b_off, ctx);
+			emit_load_imm(r_ret, 0, ctx); /* delay slot */
+			emit_div(r_A, r_X, ctx);
+			break;
+		case BPF_ALU | BPF_MOD | BPF_X:
+			/* A %= X */
+			ctx->flags |= SEEN_X | SEEN_A;
+			/* Check if r_X is zero */
+			b_off = b_imm(prog->len, ctx);
+			if (is_bad_offset(b_off))
+				return -E2BIG;
+			emit_bcond(MIPS_COND_EQ, r_X, r_zero, b_off, ctx);
+			emit_load_imm(r_ret, 0, ctx); /* delay slot */
+			emit_mod(r_A, r_X, ctx);
+			break;
+		case BPF_ALU | BPF_OR | BPF_K:
+			/* A |= K */
+			ctx->flags |= SEEN_A;
+			emit_ori(r_A, r_A, k, ctx);
+			break;
+		case BPF_ALU | BPF_OR | BPF_X:
+			/* A |= X */
+			ctx->flags |= SEEN_A;
+			emit_ori(r_A, r_A, r_X, ctx);
+			break;
+		case BPF_ALU | BPF_XOR | BPF_K:
+			/* A ^= k */
+			ctx->flags |= SEEN_A;
+			emit_xori(r_A, r_A, k, ctx);
+			break;
+		case BPF_ANC | SKF_AD_ALU_XOR_X:
+		case BPF_ALU | BPF_XOR | BPF_X:
+			/* A ^= X */
+			ctx->flags |= SEEN_A;
+			emit_xor(r_A, r_A, r_X, ctx);
+			break;
+		case BPF_ALU | BPF_AND | BPF_K:
+			/* A &= K */
+			ctx->flags |= SEEN_A;
+			emit_andi(r_A, r_A, k, ctx);
+			break;
+		case BPF_ALU | BPF_AND | BPF_X:
+			/* A &= X */
+			ctx->flags |= SEEN_A | SEEN_X;
+			emit_and(r_A, r_A, r_X, ctx);
+			break;
+		case BPF_ALU | BPF_LSH | BPF_K:
+			/* A <<= K */
+			ctx->flags |= SEEN_A;
+			emit_sll(r_A, r_A, k, ctx);
+			break;
+		case BPF_ALU | BPF_LSH | BPF_X:
+			/* A <<= X */
+			ctx->flags |= SEEN_A | SEEN_X;
+			emit_sllv(r_A, r_A, r_X, ctx);
+			break;
+		case BPF_ALU | BPF_RSH | BPF_K:
+			/* A >>= K */
+			ctx->flags |= SEEN_A;
+			emit_srl(r_A, r_A, k, ctx);
+			break;
+		case BPF_ALU | BPF_RSH | BPF_X:
+			ctx->flags |= SEEN_A | SEEN_X;
+			emit_srlv(r_A, r_A, r_X, ctx);
+			break;
+		case BPF_ALU | BPF_NEG:
+			/* A = -A */
+			ctx->flags |= SEEN_A;
+			emit_neg(r_A, ctx);
+			break;
+		case BPF_JMP | BPF_JA:
+			/* pc += K */
+			b_off = b_imm(i + k + 1, ctx);
+			if (is_bad_offset(b_off))
+				return -E2BIG;
+			emit_b(b_off, ctx);
+			emit_nop(ctx);
+			break;
+		case BPF_JMP | BPF_JEQ | BPF_K:
+			/* pc += ( A == K ) ? pc->jt : pc->jf */
+			condt = MIPS_COND_EQ | MIPS_COND_K;
+			goto jmp_cmp;
+		case BPF_JMP | BPF_JEQ | BPF_X:
+			ctx->flags |= SEEN_X;
+			/* pc += ( A == X ) ? pc->jt : pc->jf */
+			condt = MIPS_COND_EQ | MIPS_COND_X;
+			goto jmp_cmp;
+		case BPF_JMP | BPF_JGE | BPF_K:
+			/* pc += ( A >= K ) ? pc->jt : pc->jf */
+			condt = MIPS_COND_GE | MIPS_COND_K;
+			goto jmp_cmp;
+		case BPF_JMP | BPF_JGE | BPF_X:
+			ctx->flags |= SEEN_X;
+			/* pc += ( A >= X ) ? pc->jt : pc->jf */
+			condt = MIPS_COND_GE | MIPS_COND_X;
+			goto jmp_cmp;
+		case BPF_JMP | BPF_JGT | BPF_K:
+			/* pc += ( A > K ) ? pc->jt : pc->jf */
+			condt = MIPS_COND_GT | MIPS_COND_K;
+			goto jmp_cmp;
+		case BPF_JMP | BPF_JGT | BPF_X:
+			ctx->flags |= SEEN_X;
+			/* pc += ( A > X ) ? pc->jt : pc->jf */
+			condt = MIPS_COND_GT | MIPS_COND_X;
+jmp_cmp:
+			/* Greater or Equal */
+			if ((condt & MIPS_COND_GE) ||
+			    (condt & MIPS_COND_GT)) {
+				if (condt & MIPS_COND_K) { /* K */
+					ctx->flags |= SEEN_A;
+					emit_sltiu(r_s0, r_A, k, ctx);
+				} else { /* X */
+					ctx->flags |= SEEN_A |
+						SEEN_X;
+					emit_sltu(r_s0, r_A, r_X, ctx);
+				}
+				/* A < (K|X) ? r_scrach = 1 */
+				b_off = b_imm(i + inst->jf + 1, ctx);
+				emit_bcond(MIPS_COND_NE, r_s0, r_zero, b_off,
+					   ctx);
+				emit_nop(ctx);
+				/* A > (K|X) ? scratch = 0 */
+				if (condt & MIPS_COND_GT) {
+					/* Checking for equality */
+					ctx->flags |= SEEN_A | SEEN_X;
+					if (condt & MIPS_COND_K)
+						emit_load_imm(r_s0, k, ctx);
+					else
+						emit_jit_reg_move(r_s0, r_X,
+								  ctx);
+					b_off = b_imm(i + inst->jf + 1, ctx);
+					emit_bcond(MIPS_COND_EQ, r_A, r_s0,
+						   b_off, ctx);
+					emit_nop(ctx);
+					/* Finally, A > K|X */
+					b_off = b_imm(i + inst->jt + 1, ctx);
+					emit_b(b_off, ctx);
+					emit_nop(ctx);
+				} else {
+					/* A >= (K|X) so jump */
+					b_off = b_imm(i + inst->jt + 1, ctx);
+					emit_b(b_off, ctx);
+					emit_nop(ctx);
+				}
+			} else {
+				/* A == K|X */
+				if (condt & MIPS_COND_K) { /* K */
+					ctx->flags |= SEEN_A;
+					emit_load_imm(r_s0, k, ctx);
+					/* jump true */
+					b_off = b_imm(i + inst->jt + 1, ctx);
+					emit_bcond(MIPS_COND_EQ, r_A, r_s0,
+						   b_off, ctx);
+					emit_nop(ctx);
+					/* jump false */
+					b_off = b_imm(i + inst->jf + 1,
+						      ctx);
+					emit_bcond(MIPS_COND_NE, r_A, r_s0,
+						   b_off, ctx);
+					emit_nop(ctx);
+				} else { /* X */
+					/* jump true */
+					ctx->flags |= SEEN_A | SEEN_X;
+					b_off = b_imm(i + inst->jt + 1,
+						      ctx);
+					emit_bcond(MIPS_COND_EQ, r_A, r_X,
+						   b_off, ctx);
+					emit_nop(ctx);
+					/* jump false */
+					b_off = b_imm(i + inst->jf + 1, ctx);
+					emit_bcond(MIPS_COND_NE, r_A, r_X,
+						   b_off, ctx);
+					emit_nop(ctx);
+				}
+			}
+			break;
+		case BPF_JMP | BPF_JSET | BPF_K:
+			ctx->flags |= SEEN_A;
+			/* pc += (A & K) ? pc -> jt : pc -> jf */
+			emit_load_imm(r_s1, k, ctx);
+			emit_and(r_s0, r_A, r_s1, ctx);
+			/* jump true */
+			b_off = b_imm(i + inst->jt + 1, ctx);
+			emit_bcond(MIPS_COND_NE, r_s0, r_zero, b_off, ctx);
+			emit_nop(ctx);
+			/* jump false */
+			b_off = b_imm(i + inst->jf + 1, ctx);
+			emit_b(b_off, ctx);
+			emit_nop(ctx);
+			break;
+		case BPF_JMP | BPF_JSET | BPF_X:
+			ctx->flags |= SEEN_X | SEEN_A;
+			/* pc += (A & X) ? pc -> jt : pc -> jf */
+			emit_and(r_s0, r_A, r_X, ctx);
+			/* jump true */
+			b_off = b_imm(i + inst->jt + 1, ctx);
+			emit_bcond(MIPS_COND_NE, r_s0, r_zero, b_off, ctx);
+			emit_nop(ctx);
+			/* jump false */
+			b_off = b_imm(i + inst->jf + 1, ctx);
+			emit_b(b_off, ctx);
+			emit_nop(ctx);
+			break;
+		case BPF_RET | BPF_A:
+			ctx->flags |= SEEN_A;
+			if (i != prog->len - 1) {
+				/*
+				 * If this is not the last instruction
+				 * then jump to the epilogue
+				 */
+				b_off = b_imm(prog->len, ctx);
+				if (is_bad_offset(b_off))
+					return -E2BIG;
+				emit_b(b_off, ctx);
+			}
+			emit_reg_move(r_ret, r_A, ctx); /* delay slot */
+			break;
+		case BPF_RET | BPF_K:
+			/*
+			 * It can emit two instructions so it does not fit on
+			 * the delay slot.
+			 */
+			emit_load_imm(r_ret, k, ctx);
+			if (i != prog->len - 1) {
+				/*
+				 * If this is not the last instruction
+				 * then jump to the epilogue
+				 */
+				b_off = b_imm(prog->len, ctx);
+				if (is_bad_offset(b_off))
+					return -E2BIG;
+				emit_b(b_off, ctx);
+				emit_nop(ctx);
+			}
+			break;
+		case BPF_MISC | BPF_TAX:
+			/* X = A */
+			ctx->flags |= SEEN_X | SEEN_A;
+			emit_jit_reg_move(r_X, r_A, ctx);
+			break;
+		case BPF_MISC | BPF_TXA:
+			/* A = X */
+			ctx->flags |= SEEN_A | SEEN_X;
+			emit_jit_reg_move(r_A, r_X, ctx);
+			break;
+		/* AUX */
+		case BPF_ANC | SKF_AD_PROTOCOL:
+			/* A = ntohs(skb->protocol */
+			ctx->flags |= SEEN_SKB | SEEN_OFF | SEEN_A;
+			BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
+						  protocol) != 2);
+			off = offsetof(struct sk_buff, protocol);
+			emit_half_load(r_A, r_skb, off, ctx);
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+			/* This needs little endian fixup */
+			if (cpu_has_wsbh) {
+				/* R2 and later have the wsbh instruction */
+				emit_wsbh(r_A, r_A, ctx);
+			} else {
+				/* Get first byte */
+				emit_andi(r_tmp_imm, r_A, 0xff, ctx);
+				/* Shift it */
+				emit_sll(r_tmp, r_tmp_imm, 8, ctx);
+				/* Get second byte */
+				emit_srl(r_tmp_imm, r_A, 8, ctx);
+				emit_andi(r_tmp_imm, r_tmp_imm, 0xff, ctx);
+				/* Put everyting together in r_A */
+				emit_or(r_A, r_tmp, r_tmp_imm, ctx);
+			}
+#endif
+			break;
+		case BPF_ANC | SKF_AD_CPU:
+			ctx->flags |= SEEN_A | SEEN_OFF;
+			/* A = current_thread_info()->cpu */
+			BUILD_BUG_ON(FIELD_SIZEOF(struct thread_info,
+						  cpu) != 4);
+			off = offsetof(struct thread_info, cpu);
+			/* $28/gp points to the thread_info struct */
+			emit_load(r_A, 28, off, ctx);
+			break;
+		case BPF_ANC | SKF_AD_IFINDEX:
+			/* A = skb->dev->ifindex */
+		case BPF_ANC | SKF_AD_HATYPE:
+			/* A = skb->dev->type */
+			ctx->flags |= SEEN_SKB | SEEN_A;
+			off = offsetof(struct sk_buff, dev);
+			/* Load *dev pointer */
+			emit_load_ptr(r_s0, r_skb, off, ctx);
+			/* error (0) in the delay slot */
+			b_off = b_imm(prog->len, ctx);
+			if (is_bad_offset(b_off))
+				return -E2BIG;
+			emit_bcond(MIPS_COND_EQ, r_s0, r_zero, b_off, ctx);
+			emit_reg_move(r_ret, r_zero, ctx);
+			if (code == (BPF_ANC | SKF_AD_IFINDEX)) {
+				BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, ifindex) != 4);
+				off = offsetof(struct net_device, ifindex);
+				emit_load(r_A, r_s0, off, ctx);
+			} else { /* (code == (BPF_ANC | SKF_AD_HATYPE) */
+				BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, type) != 2);
+				off = offsetof(struct net_device, type);
+				emit_half_load_unsigned(r_A, r_s0, off, ctx);
+			}
+			break;
+		case BPF_ANC | SKF_AD_MARK:
+			ctx->flags |= SEEN_SKB | SEEN_A;
+			BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, mark) != 4);
+			off = offsetof(struct sk_buff, mark);
+			emit_load(r_A, r_skb, off, ctx);
+			break;
+		case BPF_ANC | SKF_AD_RXHASH:
+			ctx->flags |= SEEN_SKB | SEEN_A;
+			BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, hash) != 4);
+			off = offsetof(struct sk_buff, hash);
+			emit_load(r_A, r_skb, off, ctx);
+			break;
+		case BPF_ANC | SKF_AD_VLAN_TAG:
+			ctx->flags |= SEEN_SKB | SEEN_A;
+			BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
+						  vlan_tci) != 2);
+			off = offsetof(struct sk_buff, vlan_tci);
+			emit_half_load_unsigned(r_A, r_skb, off, ctx);
+			break;
+		case BPF_ANC | SKF_AD_VLAN_TAG_PRESENT:
+			ctx->flags |= SEEN_SKB | SEEN_A;
+			emit_load_byte(r_A, r_skb, PKT_VLAN_PRESENT_OFFSET(), ctx);
+			if (PKT_VLAN_PRESENT_BIT)
+				emit_srl(r_A, r_A, PKT_VLAN_PRESENT_BIT, ctx);
+			if (PKT_VLAN_PRESENT_BIT < 7)
+				emit_andi(r_A, r_A, 1, ctx);
+			break;
+		case BPF_ANC | SKF_AD_PKTTYPE:
+			ctx->flags |= SEEN_SKB;
+
+			emit_load_byte(r_tmp, r_skb, PKT_TYPE_OFFSET(), ctx);
+			/* Keep only the last 3 bits */
+			emit_andi(r_A, r_tmp, PKT_TYPE_MAX, ctx);
+#ifdef __BIG_ENDIAN_BITFIELD
+			/* Get the actual packet type to the lower 3 bits */
+			emit_srl(r_A, r_A, 5, ctx);
+#endif
+			break;
+		case BPF_ANC | SKF_AD_QUEUE:
+			ctx->flags |= SEEN_SKB | SEEN_A;
+			BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
+						  queue_mapping) != 2);
+			BUILD_BUG_ON(offsetof(struct sk_buff,
+					      queue_mapping) > 0xff);
+			off = offsetof(struct sk_buff, queue_mapping);
+			emit_half_load_unsigned(r_A, r_skb, off, ctx);
+			break;
+		default:
+			pr_debug("%s: Unhandled opcode: 0x%02x\n", __FILE__,
+				 inst->code);
+			return -1;
+		}
+	}
+
+	/* compute offsets only during the first pass */
+	if (ctx->target == NULL)
+		ctx->offsets[i] = ctx->idx * 4;
+
+	return 0;
+}
+
+void bpf_jit_compile(struct bpf_prog *fp)
+{
+	struct jit_ctx ctx;
+	unsigned int alloc_size, tmp_idx;
+
+	if (!bpf_jit_enable)
+		return;
+
+	memset(&ctx, 0, sizeof(ctx));
+
+	ctx.offsets = kcalloc(fp->len + 1, sizeof(*ctx.offsets), GFP_KERNEL);
+	if (ctx.offsets == NULL)
+		return;
+
+	ctx.skf = fp;
+
+	if (build_body(&ctx))
+		goto out;
+
+	tmp_idx = ctx.idx;
+	build_prologue(&ctx);
+	ctx.prologue_bytes = (ctx.idx - tmp_idx) * 4;
+	/* just to complete the ctx.idx count */
+	build_epilogue(&ctx);
+
+	alloc_size = 4 * ctx.idx;
+	ctx.target = module_alloc(alloc_size);
+	if (ctx.target == NULL)
+		goto out;
+
+	/* Clean it */
+	memset(ctx.target, 0, alloc_size);
+
+	ctx.idx = 0;
+
+	/* Generate the actual JIT code */
+	build_prologue(&ctx);
+	if (build_body(&ctx)) {
+		module_memfree(ctx.target);
+		goto out;
+	}
+	build_epilogue(&ctx);
+
+	/* Update the icache */
+	flush_icache_range((ptr)ctx.target, (ptr)(ctx.target + ctx.idx));
+
+	if (bpf_jit_enable > 1)
+		/* Dump JIT code */
+		bpf_jit_dump(fp->len, alloc_size, 2, ctx.target);
+
+	fp->bpf_func = (void *)ctx.target;
+	fp->jited = 1;
+
+out:
+	kfree(ctx.offsets);
+}
+
+void bpf_jit_free(struct bpf_prog *fp)
+{
+	if (fp->jited)
+		module_memfree(fp->bpf_func);
+
+	bpf_prog_unlock_free(fp);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/net/bpf_jit_asm.S
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/net/bpf_jit_asm.S
@@ -0,0 +1,285 @@
+/*
+ * bpf_jib_asm.S: Packet/header access helper functions for MIPS/MIPS64 BPF
+ * compiler.
+ *
+ * Copyright (C) 2015 Imagination Technologies Ltd.
+ * Author: Markos Chandras <markos.chandras@imgtec.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ */
+
+#include <asm/asm.h>
+#include <asm/isa-rev.h>
+#include <asm/regdef.h>
+#include "bpf_jit.h"
+
+/* ABI
+ *
+ * r_skb_hl	skb header length
+ * r_skb_data	skb data
+ * r_off(a1)	offset register
+ * r_A		BPF register A
+ * r_X		PF register X
+ * r_skb(a0)	*skb
+ * r_M		*scratch memory
+ * r_skb_le	skb length
+ * r_s0		Scratch register 0
+ * r_s1		Scratch register 1
+ *
+ * On entry:
+ * a0: *skb
+ * a1: offset (imm or imm + X)
+ *
+ * All non-BPF-ABI registers are free for use. On return, we only
+ * care about r_ret. The BPF-ABI registers are assumed to remain
+ * unmodified during the entire filter operation.
+ */
+
+#define skb	a0
+#define offset	a1
+#define SKF_LL_OFF  (-0x200000) /* Can't include linux/filter.h in assembly */
+
+	/* We know better :) so prevent assembler reordering etc */
+	.set 	noreorder
+
+#define is_offset_negative(TYPE)				\
+	/* If offset is negative we have more work to do */	\
+	slti	t0, offset, 0;					\
+	bgtz	t0, bpf_slow_path_##TYPE##_neg;			\
+	/* Be careful what follows in DS. */
+
+#define is_offset_in_header(SIZE, TYPE)				\
+	/* Reading from header? */				\
+	addiu	$r_s0, $r_skb_hl, -SIZE;			\
+	slt	t0, $r_s0, offset;				\
+	bgtz	t0, bpf_slow_path_##TYPE;			\
+
+LEAF(sk_load_word)
+	is_offset_negative(word)
+FEXPORT(sk_load_word_positive)
+	is_offset_in_header(4, word)
+	/* Offset within header boundaries */
+	PTR_ADDU t1, $r_skb_data, offset
+	.set	reorder
+	lw	$r_A, 0(t1)
+	.set	noreorder
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+# if MIPS_ISA_REV >= 2
+	wsbh	t0, $r_A
+	rotr	$r_A, t0, 16
+# else
+	sll	t0, $r_A, 24
+	srl	t1, $r_A, 24
+	srl	t2, $r_A, 8
+	or	t0, t0, t1
+	andi	t2, t2, 0xff00
+	andi	t1, $r_A, 0xff00
+	or	t0, t0, t2
+	sll	t1, t1, 8
+	or	$r_A, t0, t1
+# endif
+#endif
+	jr	$r_ra
+	 move	$r_ret, zero
+	END(sk_load_word)
+
+LEAF(sk_load_half)
+	is_offset_negative(half)
+FEXPORT(sk_load_half_positive)
+	is_offset_in_header(2, half)
+	/* Offset within header boundaries */
+	PTR_ADDU t1, $r_skb_data, offset
+	lhu	$r_A, 0(t1)
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+# if MIPS_ISA_REV >= 2
+	wsbh	$r_A, $r_A
+# else
+	sll	t0, $r_A, 8
+	srl	t1, $r_A, 8
+	andi	t0, t0, 0xff00
+	or	$r_A, t0, t1
+# endif
+#endif
+	jr	$r_ra
+	 move	$r_ret, zero
+	END(sk_load_half)
+
+LEAF(sk_load_byte)
+	is_offset_negative(byte)
+FEXPORT(sk_load_byte_positive)
+	is_offset_in_header(1, byte)
+	/* Offset within header boundaries */
+	PTR_ADDU t1, $r_skb_data, offset
+	lbu	$r_A, 0(t1)
+	jr	$r_ra
+	 move	$r_ret, zero
+	END(sk_load_byte)
+
+/*
+ * call skb_copy_bits:
+ * (prototype in linux/skbuff.h)
+ *
+ * int skb_copy_bits(sk_buff *skb, int offset, void *to, int len)
+ *
+ * o32 mandates we leave 4 spaces for argument registers in case
+ * the callee needs to use them. Even though we don't care about
+ * the argument registers ourselves, we need to allocate that space
+ * to remain ABI compliant since the callee may want to use that space.
+ * We also allocate 2 more spaces for $r_ra and our return register (*to).
+ *
+ * n64 is a bit different. The *caller* will allocate the space to preserve
+ * the arguments. So in 64-bit kernels, we allocate the 4-arg space for no
+ * good reason but it does not matter that much really.
+ *
+ * (void *to) is returned in r_s0
+ *
+ */
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+#define DS_OFFSET(SIZE) (4 * SZREG)
+#else
+#define DS_OFFSET(SIZE) ((4 * SZREG) + (4 - SIZE))
+#endif
+#define bpf_slow_path_common(SIZE)				\
+	/* Quick check. Are we within reasonable boundaries? */ \
+	LONG_ADDIU	$r_s1, $r_skb_len, -SIZE;		\
+	sltu		$r_s0, offset, $r_s1;			\
+	beqz		$r_s0, fault;				\
+	/* Load 4th argument in DS */				\
+	 LONG_ADDIU	a3, zero, SIZE;				\
+	PTR_ADDIU	$r_sp, $r_sp, -(6 * SZREG);		\
+	PTR_LA		t0, skb_copy_bits;			\
+	PTR_S		$r_ra, (5 * SZREG)($r_sp);		\
+	/* Assign low slot to a2 */				\
+	PTR_ADDIU	a2, $r_sp, DS_OFFSET(SIZE);		\
+	jalr		t0;					\
+	/* Reset our destination slot (DS but it's ok) */	\
+	 INT_S		zero, (4 * SZREG)($r_sp);		\
+	/*							\
+	 * skb_copy_bits returns 0 on success and -EFAULT	\
+	 * on error. Our data live in a2. Do not bother with	\
+	 * our data if an error has been returned.		\
+	 */							\
+	/* Restore our frame */					\
+	PTR_L		$r_ra, (5 * SZREG)($r_sp);		\
+	INT_L		$r_s0, (4 * SZREG)($r_sp);		\
+	bltz		v0, fault;				\
+	 PTR_ADDIU	$r_sp, $r_sp, 6 * SZREG;		\
+	move		$r_ret, zero;				\
+
+NESTED(bpf_slow_path_word, (6 * SZREG), $r_sp)
+	bpf_slow_path_common(4)
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+# if MIPS_ISA_REV >= 2
+	wsbh	t0, $r_s0
+	jr	$r_ra
+	 rotr	$r_A, t0, 16
+# else
+	sll	t0, $r_s0, 24
+	srl	t1, $r_s0, 24
+	srl	t2, $r_s0, 8
+	or	t0, t0, t1
+	andi	t2, t2, 0xff00
+	andi	t1, $r_s0, 0xff00
+	or	t0, t0, t2
+	sll	t1, t1, 8
+	jr	$r_ra
+	 or	$r_A, t0, t1
+# endif
+#else
+	jr	$r_ra
+	 move	$r_A, $r_s0
+#endif
+
+	END(bpf_slow_path_word)
+
+NESTED(bpf_slow_path_half, (6 * SZREG), $r_sp)
+	bpf_slow_path_common(2)
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+# if MIPS_ISA_REV >= 2
+	jr	$r_ra
+	 wsbh	$r_A, $r_s0
+# else
+	sll	t0, $r_s0, 8
+	andi	t1, $r_s0, 0xff00
+	andi	t0, t0, 0xff00
+	srl	t1, t1, 8
+	jr	$r_ra
+	 or	$r_A, t0, t1
+# endif
+#else
+	jr	$r_ra
+	 move	$r_A, $r_s0
+#endif
+
+	END(bpf_slow_path_half)
+
+NESTED(bpf_slow_path_byte, (6 * SZREG), $r_sp)
+	bpf_slow_path_common(1)
+	jr	$r_ra
+	 move	$r_A, $r_s0
+
+	END(bpf_slow_path_byte)
+
+/*
+ * Negative entry points
+ */
+	.macro bpf_is_end_of_data
+	li	t0, SKF_LL_OFF
+	/* Reading link layer data? */
+	slt	t1, offset, t0
+	bgtz	t1, fault
+	/* Be careful what follows in DS. */
+	.endm
+/*
+ * call skb_copy_bits:
+ * (prototype in linux/filter.h)
+ *
+ * void *bpf_internal_load_pointer_neg_helper(const struct sk_buff *skb,
+ *                                            int k, unsigned int size)
+ *
+ * see above (bpf_slow_path_common) for ABI restrictions
+ */
+#define bpf_negative_common(SIZE)					\
+	PTR_ADDIU	$r_sp, $r_sp, -(6 * SZREG);			\
+	PTR_LA		t0, bpf_internal_load_pointer_neg_helper;	\
+	PTR_S		$r_ra, (5 * SZREG)($r_sp);			\
+	jalr		t0;						\
+	 li		a2, SIZE;					\
+	PTR_L		$r_ra, (5 * SZREG)($r_sp);			\
+	/* Check return pointer */					\
+	beqz		v0, fault;					\
+	 PTR_ADDIU	$r_sp, $r_sp, 6 * SZREG;			\
+	/* Preserve our pointer */					\
+	move		$r_s0, v0;					\
+	/* Set return value */						\
+	move		$r_ret, zero;					\
+
+bpf_slow_path_word_neg:
+	bpf_is_end_of_data
+NESTED(sk_load_word_negative, (6 * SZREG), $r_sp)
+	bpf_negative_common(4)
+	jr	$r_ra
+	 lw	$r_A, 0($r_s0)
+	END(sk_load_word_negative)
+
+bpf_slow_path_half_neg:
+	bpf_is_end_of_data
+NESTED(sk_load_half_negative, (6 * SZREG), $r_sp)
+	bpf_negative_common(2)
+	jr	$r_ra
+	 lhu	$r_A, 0($r_s0)
+	END(sk_load_half_negative)
+
+bpf_slow_path_byte_neg:
+	bpf_is_end_of_data
+NESTED(sk_load_byte_negative, (6 * SZREG), $r_sp)
+	bpf_negative_common(1)
+	jr	$r_ra
+	 lbu	$r_A, 0($r_s0)
+	END(sk_load_byte_negative)
+
+fault:
+	jr	$r_ra
+	 addiu $r_ret, zero, 1
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/net/ebpf_jit.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/net/ebpf_jit.c
@@ -604,6 +604,7 @@
 static int emit_bpf_tail_call(struct jit_ctx *ctx, int this_idx)
 {
 	int off, b_off;
+	int tcc_reg;
 
 	ctx->flags |= EBPF_SEEN_TC;
 	/*
@@ -616,14 +617,14 @@
 	b_off = b_imm(this_idx + 1, ctx);
 	emit_instr(ctx, bne, MIPS_R_AT, MIPS_R_ZERO, b_off);
 	/*
-	 * if (--TCC < 0)
+	 * if (TCC-- < 0)
 	 *     goto out;
 	 */
 	/* Delay slot */
-	emit_instr(ctx, daddiu, MIPS_R_T5,
-		   (ctx->flags & EBPF_TCC_IN_V1) ? MIPS_R_V1 : MIPS_R_S4, -1);
+	tcc_reg = (ctx->flags & EBPF_TCC_IN_V1) ? MIPS_R_V1 : MIPS_R_S4;
+	emit_instr(ctx, daddiu, MIPS_R_T5, tcc_reg, -1);
 	b_off = b_imm(this_idx + 1, ctx);
-	emit_instr(ctx, bltz, MIPS_R_T5, b_off);
+	emit_instr(ctx, bltz, tcc_reg, b_off);
 	/*
 	 * prog = array->ptrs[index];
 	 * if (prog == NULL)
@@ -1354,6 +1355,9 @@
 		}
 		break;
 
+	case BPF_ST | BPF_NOSPEC: /* speculation barrier */
+		break;
+
 	case BPF_ST | BPF_B | BPF_MEM:
 	case BPF_ST | BPF_H | BPF_MEM:
 	case BPF_ST | BPF_W | BPF_MEM:
@@ -1803,7 +1807,7 @@
 	unsigned int image_size;
 	u8 *image_ptr;
 
-	if (!prog->jit_requested || MIPS_ISA_REV < 2)
+	if (!prog->jit_requested)
 		return prog;
 
 	tmp = bpf_jit_blind_constants(prog);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/pci/ops-rc32434.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/pci/ops-rc32434.c
@@ -112,8 +112,8 @@
 	 * gives them time to settle
 	 */
 	if (where == PCI_VENDOR_ID) {
-		if (ret == 0xffffffff || ret == 0x00000000 ||
-		    ret == 0x0000ffff || ret == 0xffff0000) {
+		if (*val == 0xffffffff || *val == 0x00000000 ||
+		    *val == 0x0000ffff || *val == 0xffff0000) {
 			if (delay > 4)
 				return 0;
 			delay *= 2;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/pci/pci-legacy.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/pci/pci-legacy.c
@@ -166,8 +166,13 @@
 			res = hose->mem_resource;
 			break;
 		}
-		if (res != NULL)
-			of_pci_range_to_resource(&range, node, res);
+		if (res != NULL) {
+			res->name = node->full_name;
+			res->flags = range.flags;
+			res->start = range.cpu_addr;
+			res->end = range.cpu_addr + range.size - 1;
+			res->parent = res->child = res->sibling = NULL;
+		}
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/pci/pci-mt7620.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/pci/pci-mt7620.c
@@ -30,6 +30,7 @@
 #define RALINK_GPIOMODE			0x60
 
 #define PPLL_CFG1			0x9c
+#define PPLL_LD				BIT(23)
 
 #define PPLL_DRV			0xa0
 #define PDRV_SW_SET			BIT(31)
@@ -239,8 +240,8 @@
 	rt_sysc_m32(0, RALINK_PCIE0_CLK_EN, RALINK_CLKCFG1);
 	mdelay(100);
 
-	if (!(rt_sysc_r32(PPLL_CFG1) & PDRV_SW_SET)) {
-		dev_err(&pdev->dev, "MT7620 PPLL unlock\n");
+	if (!(rt_sysc_r32(PPLL_CFG1) & PPLL_LD)) {
+		dev_err(&pdev->dev, "pcie PLL not locked, aborting init\n");
 		reset_control_assert(rstpcie0);
 		rt_sysc_m32(RALINK_PCIE0_CLK_EN, 0, RALINK_CLKCFG1);
 		return -1;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/pci/pci-rt2880.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/pci/pci-rt2880.c
@@ -180,7 +180,6 @@
 
 int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-	u16 cmd;
 	int irq = -1;
 
 	if (dev->bus->number != 0)
@@ -188,8 +187,6 @@
 
 	switch (PCI_SLOT(dev->devfn)) {
 	case 0x00:
-		rt2880_pci_write_u32(PCI_BASE_ADDRESS_0, 0x08000000);
-		(void) rt2880_pci_read_u32(PCI_BASE_ADDRESS_0);
 		break;
 	case 0x11:
 		irq = RT288X_CPU_IRQ_PCI;
@@ -201,16 +198,6 @@
 		break;
 	}
 
-	pci_write_config_byte((struct pci_dev *) dev,
-		PCI_CACHE_LINE_SIZE, 0x14);
-	pci_write_config_byte((struct pci_dev *) dev, PCI_LATENCY_TIMER, 0xFF);
-	pci_read_config_word((struct pci_dev *) dev, PCI_COMMAND, &cmd);
-	cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
-		PCI_COMMAND_INVALIDATE | PCI_COMMAND_FAST_BACK |
-		PCI_COMMAND_SERR | PCI_COMMAND_WAIT | PCI_COMMAND_PARITY;
-	pci_write_config_word((struct pci_dev *) dev, PCI_COMMAND, cmd);
-	pci_write_config_byte((struct pci_dev *) dev, PCI_INTERRUPT_LINE,
-			      dev->irq);
 	return irq;
 }
 
@@ -251,6 +238,30 @@
 
 int pcibios_plat_dev_init(struct pci_dev *dev)
 {
+	static bool slot0_init;
+
+	/*
+	 * Nobody seems to initialize slot 0, but this platform requires it, so
+	 * do it once when some other slot is being enabled. The PCI subsystem
+	 * should configure other slots properly, so no need to do anything
+	 * special for those.
+	 */
+	if (!slot0_init && dev->bus->number == 0) {
+		u16 cmd;
+		u32 bar0;
+
+		slot0_init = true;
+
+		pci_bus_write_config_dword(dev->bus, 0, PCI_BASE_ADDRESS_0,
+					   0x08000000);
+		pci_bus_read_config_dword(dev->bus, 0, PCI_BASE_ADDRESS_0,
+					  &bar0);
+
+		pci_bus_read_config_word(dev->bus, 0, PCI_COMMAND, &cmd);
+		cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
+		pci_bus_write_config_word(dev->bus, 0, PCI_COMMAND, cmd);
+	}
+
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/pci/pci-xtalk-bridge.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/pci/pci-xtalk-bridge.c
@@ -279,16 +279,15 @@
 	struct bridge_irq_chip_data *data = d->chip_data;
 	int bit = d->parent_data->hwirq;
 	int pin = d->hwirq;
-	nasid_t nasid;
 	int ret, cpu;
 
 	ret = irq_chip_set_affinity_parent(d, mask, force);
 	if (ret >= 0) {
 		cpu = cpumask_first_and(mask, cpu_online_mask);
-		nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu));
+		data->nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu));
 		bridge_write(data->bc, b_int_addr[pin].addr,
 			     (((data->bc->intr_addr >> 30) & 0x30000) |
-			      bit | (nasid << 8)));
+			      bit | (data->nasid << 8)));
 		bridge_read(data->bc, b_wid_tflush);
 	}
 	return ret;
@@ -445,9 +444,10 @@
 		return -ENOMEM;
 	domain = irq_domain_create_hierarchy(parent, 0, 8, fn,
 					     &bridge_domain_ops, NULL);
-	irq_domain_free_fwnode(fn);
-	if (!domain)
+	if (!domain) {
+		irq_domain_free_fwnode(fn);
 		return -ENOMEM;
+	}
 
 	pci_set_flags(PCI_PROBE_ONLY);
 
@@ -539,6 +539,7 @@
 	pci_free_resource_list(&host->windows);
 err_remove_domain:
 	irq_domain_remove(domain);
+	irq_domain_free_fwnode(fn);
 	return err;
 }
 
@@ -546,8 +547,10 @@
 {
 	struct pci_bus *bus = platform_get_drvdata(pdev);
 	struct bridge_controller *bc = BRIDGE_CONTROLLER(bus);
+	struct fwnode_handle *fn = bc->domain->fwnode;
 
 	irq_domain_remove(bc->domain);
+	irq_domain_free_fwnode(fn);
 	pci_lock_rescan_remove();
 	pci_stop_root_bus(bus);
 	pci_remove_root_bus(bus);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/pci/pcie-octeon.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/pci/pcie-octeon.c
@@ -230,12 +230,18 @@
 {
 	union cvmx_pcie_address pcie_addr;
 	union cvmx_pciercx_cfg006 pciercx_cfg006;
+	union cvmx_pciercx_cfg032 pciercx_cfg032;
 
 	pciercx_cfg006.u32 =
 	    cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG006(pcie_port));
 	if ((bus <= pciercx_cfg006.s.pbnum) && (dev != 0))
 		return 0;
 
+	pciercx_cfg032.u32 =
+		cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG032(pcie_port));
+	if ((pciercx_cfg032.s.dlla == 0) || (pciercx_cfg032.s.lt == 1))
+		return 0;
+
 	pcie_addr.u64 = 0;
 	pcie_addr.config.upper = 2;
 	pcie_addr.config.io = 1;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/pic32/pic32mzda/early_console.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/pic32/pic32mzda/early_console.c
@@ -27,7 +27,7 @@
 #define U_BRG(x)	(UART_BASE(x) + 0x40)
 
 static void __iomem *uart_base;
-static char console_port = -1;
+static int console_port = -1;
 
 static int __init configure_uart_pins(int port)
 {
@@ -47,7 +47,7 @@
 	return 0;
 }
 
-static void __init configure_uart(char port, int baud)
+static void __init configure_uart(int port, int baud)
 {
 	u32 pbclk;
 
@@ -60,7 +60,7 @@
 		     uart_base + PIC32_SET(U_STA(port)));
 }
 
-static void __init setup_early_console(char port, int baud)
+static void __init setup_early_console(int port, int baud)
 {
 	if (configure_uart_pins(port))
 		return;
@@ -130,16 +130,15 @@
 	return baud;
 }
 
-void __init fw_init_early_console(char port)
+void __init fw_init_early_console(void)
 {
 	char *arch_cmdline = pic32_getcmdline();
-	int baud = -1;
+	int baud, port;
 
 	uart_base = ioremap_nocache(PIC32_BASE_UART, 0xc00);
 
 	baud = get_baud_from_cmdline(arch_cmdline);
-	if (port == -1)
-		port = get_port_from_cmdline(arch_cmdline);
+	port = get_port_from_cmdline(arch_cmdline);
 
 	if (port == -1)
 		port = EARLY_CONSOLE_PORT;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/pic32/pic32mzda/init.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/pic32/pic32mzda/init.c
@@ -28,7 +28,7 @@
 	if (fw_passed_dtb && !fw_arg2 && !fw_arg3)
 		return (ulong)fw_passed_dtb;
 
-	if (__dtb_start < __dtb_end)
+	if (&__dtb_start < &__dtb_end)
 		ftaddr = (ulong)__dtb_start;
 
 	return ftaddr;
@@ -60,7 +60,7 @@
 		strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
 
 #ifdef CONFIG_EARLY_PRINTK
-	fw_init_early_console(-1);
+	fw_init_early_console();
 #endif
 	pic32_config_init();
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/ralink/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/ralink/Kconfig
@@ -51,6 +51,7 @@
 		select MIPS_GIC
 		select COMMON_CLK
 		select CLKSRC_MIPS_GIC
+		select HAVE_PCI if PCI_MT7621
 endchoice
 
 choice
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/ralink/ill_acc.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/ralink/ill_acc.c
@@ -61,6 +61,7 @@
 	pdev = of_find_device_by_node(np);
 	if (!pdev) {
 		pr_err("%pOFn: failed to lookup pdev\n", np);
+		of_node_put(np);
 		return -EINVAL;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/ralink/of.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/ralink/of.c
@@ -8,6 +8,7 @@
 
 #include <linux/io.h>
 #include <linux/clk.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/sizes.h>
 #include <linux/of_fdt.h>
@@ -25,6 +26,7 @@
 
 __iomem void *rt_sysc_membase;
 __iomem void *rt_memc_membase;
+EXPORT_SYMBOL_GPL(rt_sysc_membase);
 
 __iomem void *plat_of_remap_node(const char *node)
 {
@@ -75,7 +77,7 @@
 	 */
 	if (fw_passed_dtb)
 		dtb = (void *)fw_passed_dtb;
-	else if (__dtb_start != __dtb_end)
+	else if (&__dtb_start != &__dtb_end)
 		dtb = (void *)__dtb_start;
 
 	__dt_setup_arch(dtb);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/rb532/devices.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/rb532/devices.c
@@ -310,11 +310,9 @@
 static int __init setup_kmac(char *s)
 {
 	printk(KERN_INFO "korina mac = %s\n", s);
-	if (!mac_pton(s, korina_dev0_data.mac)) {
+	if (!mac_pton(s, korina_dev0_data.mac))
 		printk(KERN_ERR "Invalid mac\n");
-		return -EINVAL;
-	}
-	return 0;
+	return 1;
 }
 
 __setup("kmac=", setup_kmac);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/sgi-ip27/ip27-irq.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/sgi-ip27/ip27-irq.c
@@ -73,6 +73,9 @@
 	int cpu;
 
 	cpu = cpumask_first_and(mask, cpu_online_mask);
+	if (cpu >= nr_cpu_ids)
+		cpu = cpumask_any(cpu_online_mask);
+
 	nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu));
 	hd->cpu = cpu;
 	if (!cputoslice(cpu)) {
@@ -139,6 +142,7 @@
 	/* use CPU connected to nearest hub */
 	hub = hub_data(NASID_TO_COMPACT_NODEID(info->nasid));
 	setup_hub_mask(hd, &hub->h_cpus);
+	info->nasid = cpu_to_node(hd->cpu);
 
 	/* Make sure it's not already pending when we connect it. */
 	REMOTE_HUB_CLR_INTR(info->nasid, swlevel);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/sni/a20r.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/sni/a20r.c
@@ -143,7 +143,10 @@
 	},
 };
 
-static u32 a20r_ack_hwint(void)
+/*
+ * Trigger chipset to update CPU's CAUSE IP field
+ */
+static u32 a20r_update_cause_ip(void)
 {
 	u32 status = read_c0_status();
 
@@ -205,12 +208,14 @@
 	int irq;
 
 	clear_c0_status(IE_IRQ0);
-	status = a20r_ack_hwint();
+	status = a20r_update_cause_ip();
 	cause = read_c0_cause();
 
 	irq = ffs(((cause & status) >> 8) & 0xf8);
 	if (likely(irq > 0))
 		do_IRQ(SNI_A20R_IRQ_BASE + irq - 1);
+
+	a20r_update_cause_ip();
 	set_c0_status(IE_IRQ0);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/sni/time.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/sni/time.c
@@ -18,14 +18,14 @@
 {
 	*(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0x34;
 	wmb();
-	*(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = SNI_COUNTER0_DIV;
+	*(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = SNI_COUNTER0_DIV & 0xff;
 	wmb();
 	*(volatile u8 *)(A20R_PT_CLOCK_BASE + 0) = SNI_COUNTER0_DIV >> 8;
 	wmb();
 
 	*(volatile u8 *)(A20R_PT_CLOCK_BASE + 12) = 0xb4;
 	wmb();
-	*(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = SNI_COUNTER2_DIV;
+	*(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = SNI_COUNTER2_DIV & 0xff;
 	wmb();
 	*(volatile u8 *)(A20R_PT_CLOCK_BASE + 8) = SNI_COUNTER2_DIV >> 8;
 	wmb();
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/tools/elf-entry.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/tools/elf-entry.c
@@ -51,11 +51,14 @@
 	nread = fread(&hdr, 1, sizeof(hdr), file);
 	if (nread != sizeof(hdr)) {
 		perror("Unable to read input file");
+		fclose(file);
 		return EXIT_FAILURE;
 	}
 
-	if (memcmp(hdr.ehdr32.e_ident, ELFMAG, SELFMAG))
+	if (memcmp(hdr.ehdr32.e_ident, ELFMAG, SELFMAG)) {
+		fclose(file);
 		die("Input is not an ELF\n");
+	}
 
 	switch (hdr.ehdr32.e_ident[EI_CLASS]) {
 	case ELFCLASS32:
@@ -67,6 +70,7 @@
 			entry = be32toh(hdr.ehdr32.e_entry);
 			break;
 		default:
+			fclose(file);
 			die("Invalid ELF encoding\n");
 		}
 
@@ -83,14 +87,17 @@
 			entry = be64toh(hdr.ehdr64.e_entry);
 			break;
 		default:
+			fclose(file);
 			die("Invalid ELF encoding\n");
 		}
 		break;
 
 	default:
+		fclose(file);
 		die("Invalid ELF class\n");
 	}
 
 	printf("0x%016" PRIx64 "\n", entry);
+	fclose(file);
 	return EXIT_SUCCESS;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/vdso/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/vdso/Makefile
@@ -16,12 +16,9 @@
 	$(filter -march=%,$(KBUILD_CFLAGS)) \
 	$(filter -m%-float,$(KBUILD_CFLAGS)) \
 	$(filter -mno-loongson-%,$(KBUILD_CFLAGS)) \
+	$(CLANG_FLAGS) \
 	-D__VDSO__
 
-ifdef CONFIG_CC_IS_CLANG
-ccflags-vdso += $(filter --target=%,$(KBUILD_CFLAGS))
-endif
-
 #
 # The -fno-jump-tables flag only prevents the compiler from generating
 # jump tables but does not prevent the compiler from emitting absolute
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/vdso/genvdso.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/vdso/genvdso.c
@@ -122,6 +122,7 @@
 	if (fstat(fd, &stat) != 0) {
 		fprintf(stderr, "%s: Failed to stat '%s': %s\n", program_name,
 			path, strerror(errno));
+		close(fd);
 		return NULL;
 	}
 
@@ -130,6 +131,7 @@
 	if (addr == MAP_FAILED) {
 		fprintf(stderr, "%s: Failed to map '%s': %s\n", program_name,
 			path, strerror(errno));
+		close(fd);
 		return NULL;
 	}
 
@@ -139,6 +141,7 @@
 	if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0) {
 		fprintf(stderr, "%s: '%s' is not an ELF file\n", program_name,
 			path);
+		close(fd);
 		return NULL;
 	}
 
@@ -150,6 +153,7 @@
 	default:
 		fprintf(stderr, "%s: '%s' has invalid ELF class\n",
 			program_name, path);
+		close(fd);
 		return NULL;
 	}
 
@@ -161,6 +165,7 @@
 	default:
 		fprintf(stderr, "%s: '%s' has invalid ELF data order\n",
 			program_name, path);
+		close(fd);
 		return NULL;
 	}
 
@@ -168,15 +173,18 @@
 		fprintf(stderr,
 			"%s: '%s' has invalid ELF machine (expected EM_MIPS)\n",
 			program_name, path);
+		close(fd);
 		return NULL;
 	} else if (swap_uint16(ehdr->e_type) != ET_DYN) {
 		fprintf(stderr,
 			"%s: '%s' has invalid ELF type (expected ET_DYN)\n",
 			program_name, path);
+		close(fd);
 		return NULL;
 	}
 
 	*_size = stat.st_size;
+	close(fd);
 	return addr;
 }
 
@@ -280,10 +288,12 @@
 	/* Calculate and write symbol offsets to <output file> */
 	if (!get_symbols(dbg_vdso_path, dbg_vdso)) {
 		unlink(out_path);
+		fclose(out_file);
 		return EXIT_FAILURE;
 	}
 
 	fprintf(out_file, "};\n");
+	fclose(out_file);
 
 	return EXIT_SUCCESS;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/vdso/vgettimeofday.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/vdso/vgettimeofday.c
@@ -17,12 +17,22 @@
 	return __cvdso_clock_gettime32(clock, ts);
 }
 
+#ifdef CONFIG_MIPS_CLOCK_VSYSCALL
+
+/*
+ * This is behind the ifdef so that we don't provide the symbol when there's no
+ * possibility of there being a usable clocksource, because there's nothing we
+ * can do without it. When libc fails the symbol lookup it should fall back on
+ * the standard syscall path.
+ */
 int __vdso_gettimeofday(struct __kernel_old_timeval *tv,
 			struct timezone *tz)
 {
 	return __cvdso_gettimeofday(tv, tz);
 }
 
+#endif /* CONFIG_MIPS_CLOCK_VSYSCALL */
+
 int __vdso_clock_getres(clockid_t clock_id,
 			struct old_timespec32 *res)
 {
@@ -43,12 +53,22 @@
 	return __cvdso_clock_gettime(clock, ts);
 }
 
+#ifdef CONFIG_MIPS_CLOCK_VSYSCALL
+
+/*
+ * This is behind the ifdef so that we don't provide the symbol when there's no
+ * possibility of there being a usable clocksource, because there's nothing we
+ * can do without it. When libc fails the symbol lookup it should fall back on
+ * the standard syscall path.
+ */
 int __vdso_gettimeofday(struct __kernel_old_timeval *tv,
 			struct timezone *tz)
 {
 	return __cvdso_gettimeofday(tv, tz);
 }
 
+#endif /* CONFIG_MIPS_CLOCK_VSYSCALL */
+
 int __vdso_clock_getres(clockid_t clock_id,
 			struct __kernel_timespec *res)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/mips/vr41xx/common/icu.c
+++ linux-xilinx-zynqmp-5.4.0/arch/mips/vr41xx/common/icu.c
@@ -640,8 +640,6 @@
 
 	printk(KERN_ERR "spurious ICU interrupt: %04x,%04x\n", pend1, pend2);
 
-	atomic_inc(&irq_err_count);
-
 	return -1;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/nds32/include/asm/cacheflush.h
+++ linux-xilinx-zynqmp-5.4.0/arch/nds32/include/asm/cacheflush.h
@@ -9,7 +9,11 @@
 #define PG_dcache_dirty PG_arch_1
 
 void flush_icache_range(unsigned long start, unsigned long end);
+#define flush_icache_range flush_icache_range
+
 void flush_icache_page(struct vm_area_struct *vma, struct page *page);
+#define flush_icache_page flush_icache_page
+
 #ifdef CONFIG_CPU_CACHE_ALIASING
 void flush_cache_mm(struct mm_struct *mm);
 void flush_cache_dup_mm(struct mm_struct *mm);
@@ -40,12 +44,11 @@
 #define flush_dcache_mmap_unlock(mapping) xa_unlock_irq(&(mapping)->i_pages)
 
 #else
-#include <asm-generic/cacheflush.h>
-#undef flush_icache_range
-#undef flush_icache_page
-#undef flush_icache_user_range
 void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
 	                     unsigned long addr, int len);
+#define flush_icache_user_range flush_icache_user_range
+
+#include <asm-generic/cacheflush.h>
 #endif
 
 #endif /* __NDS32_CACHEFLUSH_H__ */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/nds32/include/asm/memory.h
+++ linux-xilinx-zynqmp-5.4.0/arch/nds32/include/asm/memory.h
@@ -76,18 +76,12 @@
  *  virt_to_page(k)	convert a _valid_ virtual address to struct page *
  *  virt_addr_valid(k)	indicates whether a virtual address is valid
  */
-#ifndef CONFIG_DISCONTIGMEM
-
 #define ARCH_PFN_OFFSET		PHYS_PFN_OFFSET
 #define pfn_valid(pfn)		((pfn) >= PHYS_PFN_OFFSET && (pfn) < (PHYS_PFN_OFFSET + max_mapnr))
 
 #define virt_to_page(kaddr)	(pfn_to_page(__pa(kaddr) >> PAGE_SHIFT))
 #define virt_addr_valid(kaddr)	((unsigned long)(kaddr) >= PAGE_OFFSET && (unsigned long)(kaddr) < (unsigned long)high_memory)
 
-#else /* CONFIG_DISCONTIGMEM */
-#error CONFIG_DISCONTIGMEM is not supported yet.
-#endif /* !CONFIG_DISCONTIGMEM */
-
 #define page_to_phys(page)	(page_to_pfn(page) << PAGE_SHIFT)
 
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/nds32/include/asm/uaccess.h
+++ linux-xilinx-zynqmp-5.4.0/arch/nds32/include/asm/uaccess.h
@@ -71,9 +71,7 @@
  * versions are void (ie, don't return a value as such).
  */
 
-#define get_user	__get_user					\
-
-#define __get_user(x, ptr)						\
+#define get_user(x, ptr)						\
 ({									\
 	long __gu_err = 0;						\
 	__get_user_check((x), (ptr), __gu_err);				\
@@ -86,6 +84,14 @@
 	(void)0;							\
 })
 
+#define __get_user(x, ptr)						\
+({									\
+	long __gu_err = 0;						\
+	const __typeof__(*(ptr)) __user *__p = (ptr);			\
+	__get_user_err((x), __p, (__gu_err));				\
+	__gu_err;							\
+})
+
 #define __get_user_check(x, ptr, err)					\
 ({									\
 	const __typeof__(*(ptr)) __user *__p = (ptr);			\
@@ -166,12 +172,18 @@
 		: "r"(addr), "i"(-EFAULT)				\
 		: "cc")
 
-#define put_user	__put_user					\
+#define put_user(x, ptr)						\
+({									\
+	long __pu_err = 0;						\
+	__put_user_check((x), (ptr), __pu_err);				\
+	__pu_err;							\
+})
 
 #define __put_user(x, ptr)						\
 ({									\
 	long __pu_err = 0;						\
-	__put_user_err((x), (ptr), __pu_err);				\
+	__typeof__(*(ptr)) __user *__p = (ptr);				\
+	__put_user_err((x), __p, __pu_err);				\
 	__pu_err;							\
 })
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/nds32/kernel/dma.c
+++ linux-xilinx-zynqmp-5.4.0/arch/nds32/kernel/dma.c
@@ -46,8 +46,8 @@
 	} while (left);
 }
 
-void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr,
-		size_t size, enum dma_data_direction dir)
+void arch_sync_dma_for_device(phys_addr_t paddr, size_t size,
+		enum dma_data_direction dir)
 {
 	switch (dir) {
 	case DMA_FROM_DEVICE:
@@ -61,8 +61,8 @@
 	}
 }
 
-void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr,
-		size_t size, enum dma_data_direction dir)
+void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size,
+		enum dma_data_direction dir)
 {
 	switch (dir) {
 	case DMA_TO_DEVICE:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/nds32/kernel/fpu.c
+++ linux-xilinx-zynqmp-5.4.0/arch/nds32/kernel/fpu.c
@@ -223,7 +223,7 @@
 		}
 	} else if (fpcsr & FPCSR_mskRIT) {
 		if (!user_mode(regs))
-			do_exit(SIGILL);
+			make_task_dead(SIGILL);
 		si_signo = SIGILL;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/nds32/kernel/perf_event_cpu.c
+++ linux-xilinx-zynqmp-5.4.0/arch/nds32/kernel/perf_event_cpu.c
@@ -1363,6 +1363,7 @@
 perf_callchain_user(struct perf_callchain_entry_ctx *entry,
 		    struct pt_regs *regs)
 {
+	struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs();
 	unsigned long fp = 0;
 	unsigned long gp = 0;
 	unsigned long lp = 0;
@@ -1371,7 +1372,7 @@
 
 	leaf_fp = 0;
 
-	if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
+	if (guest_cbs && guest_cbs->is_in_guest()) {
 		/* We don't support guest os callchain now */
 		return;
 	}
@@ -1479,9 +1480,10 @@
 perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
 		      struct pt_regs *regs)
 {
+	struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs();
 	struct stackframe fr;
 
-	if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
+	if (guest_cbs && guest_cbs->is_in_guest()) {
 		/* We don't support guest os callchain now */
 		return;
 	}
@@ -1493,20 +1495,23 @@
 
 unsigned long perf_instruction_pointer(struct pt_regs *regs)
 {
+	struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs();
+
 	/* However, NDS32 does not support virtualization */
-	if (perf_guest_cbs && perf_guest_cbs->is_in_guest())
-		return perf_guest_cbs->get_guest_ip();
+	if (guest_cbs && guest_cbs->is_in_guest())
+		return guest_cbs->get_guest_ip();
 
 	return instruction_pointer(regs);
 }
 
 unsigned long perf_misc_flags(struct pt_regs *regs)
 {
+	struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs();
 	int misc = 0;
 
 	/* However, NDS32 does not support virtualization */
-	if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
-		if (perf_guest_cbs->is_user_mode())
+	if (guest_cbs && guest_cbs->is_in_guest()) {
+		if (guest_cbs->is_user_mode())
 			misc |= PERF_RECORD_MISC_GUEST_USER;
 		else
 			misc |= PERF_RECORD_MISC_GUEST_KERNEL;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/nds32/kernel/traps.c
+++ linux-xilinx-zynqmp-5.4.0/arch/nds32/kernel/traps.c
@@ -184,7 +184,7 @@
 
 	bust_spinlocks(0);
 	spin_unlock_irq(&die_lock);
-	do_exit(SIGSEGV);
+	make_task_dead(SIGSEGV);
 }
 
 EXPORT_SYMBOL(die);
@@ -288,7 +288,7 @@
 	pr_emerg("unhandled_interruption\n");
 	show_regs(regs);
 	if (!user_mode(regs))
-		do_exit(SIGKILL);
+		make_task_dead(SIGKILL);
 	force_sig(SIGKILL);
 }
 
@@ -299,7 +299,7 @@
 		 addr, type);
 	show_regs(regs);
 	if (!user_mode(regs))
-		do_exit(SIGKILL);
+		make_task_dead(SIGKILL);
 	force_sig(SIGKILL);
 }
 
@@ -326,7 +326,7 @@
 	pr_emerg("Reserved Instruction\n");
 	show_regs(regs);
 	if (!user_mode(regs))
-		do_exit(SIGILL);
+		make_task_dead(SIGILL);
 	force_sig(SIGILL);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/nds32/mm/cacheflush.c
+++ linux-xilinx-zynqmp-5.4.0/arch/nds32/mm/cacheflush.c
@@ -239,7 +239,7 @@
 {
 	struct address_space *mapping;
 
-	mapping = page_mapping(page);
+	mapping = page_mapping_file(page);
 	if (mapping && !mapping_mapped(mapping))
 		set_bit(PG_dcache_dirty, &page->flags);
 	else {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/nds32/mm/mmap.c
+++ linux-xilinx-zynqmp-5.4.0/arch/nds32/mm/mmap.c
@@ -59,7 +59,7 @@
 
 		vma = find_vma(mm, addr);
 		if (TASK_SIZE - len >= addr &&
-		    (!vma || addr + len <= vma->vm_start))
+		    (!vma || addr + len <= vm_start_gap(vma)))
 			return addr;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/nios2/boot/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/nios2/boot/Makefile
@@ -20,7 +20,7 @@
 $(obj)/vmlinux.gz: $(obj)/vmlinux.bin FORCE
 	$(call if_changed,gzip)
 
-$(obj)/vmImage: $(obj)/vmlinux.gz
+$(obj)/vmImage: $(obj)/vmlinux.gz FORCE
 	$(call if_changed,uimage)
 	@$(kecho) 'Kernel: $@ is ready'
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/nios2/boot/dts/10m50_devboard.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/nios2/boot/dts/10m50_devboard.dts
@@ -97,7 +97,7 @@
 			rx-fifo-depth = <8192>;
 			tx-fifo-depth = <8192>;
 			address-bits = <48>;
-			max-frame-size = <1518>;
+			max-frame-size = <1500>;
 			local-mac-address = [00 00 00 00 00 00];
 			altr,has-supplementary-unicast;
 			altr,enable-sup-addr = <1>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/nios2/boot/dts/3c120_devboard.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/nios2/boot/dts/3c120_devboard.dts
@@ -106,7 +106,7 @@
 				interrupt-names = "rx_irq", "tx_irq";
 				rx-fifo-depth = <8192>;
 				tx-fifo-depth = <8192>;
-				max-frame-size = <1518>;
+				max-frame-size = <1500>;
 				local-mac-address = [ 00 00 00 00 00 00 ];
 				phy-mode = "rgmii-id";
 				phy-handle = <&phy0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/nios2/include/asm/entry.h
+++ linux-xilinx-zynqmp-5.4.0/arch/nios2/include/asm/entry.h
@@ -50,7 +50,8 @@
 	stw	r13, PT_R13(sp)
 	stw	r14, PT_R14(sp)
 	stw	r15, PT_R15(sp)
-	stw	r2, PT_ORIG_R2(sp)
+	movi	r24, -1
+	stw	r24, PT_ORIG_R2(sp)
 	stw	r7, PT_ORIG_R7(sp)
 
 	stw	ra, PT_RA(sp)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/nios2/include/asm/irqflags.h
+++ linux-xilinx-zynqmp-5.4.0/arch/nios2/include/asm/irqflags.h
@@ -9,7 +9,7 @@
 
 static inline unsigned long arch_local_save_flags(void)
 {
-	return RDCTL(CTL_STATUS);
+	return RDCTL(CTL_FSTATUS);
 }
 
 /*
@@ -18,7 +18,7 @@
  */
 static inline void arch_local_irq_restore(unsigned long flags)
 {
-	WRCTL(CTL_STATUS, flags);
+	WRCTL(CTL_FSTATUS, flags);
 }
 
 static inline void arch_local_irq_disable(void)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/nios2/include/asm/ptrace.h
+++ linux-xilinx-zynqmp-5.4.0/arch/nios2/include/asm/ptrace.h
@@ -74,6 +74,8 @@
 	((struct pt_regs *)((unsigned long)current_thread_info() + THREAD_SIZE)\
 		- 1)
 
+#define force_successful_syscall_return() (current_pt_regs()->orig_r2 = -1)
+
 int do_syscall_trace_enter(void);
 void do_syscall_trace_exit(void);
 #endif /* __ASSEMBLY__ */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/nios2/include/asm/registers.h
+++ linux-xilinx-zynqmp-5.4.0/arch/nios2/include/asm/registers.h
@@ -11,7 +11,7 @@
 #endif
 
 /* control register numbers */
-#define CTL_STATUS	0
+#define CTL_FSTATUS	0
 #define CTL_ESTATUS	1
 #define CTL_BSTATUS	2
 #define CTL_IENABLE	3
--- linux-xilinx-zynqmp-5.4.0.orig/arch/nios2/include/asm/timex.h
+++ linux-xilinx-zynqmp-5.4.0/arch/nios2/include/asm/timex.h
@@ -8,5 +8,8 @@
 typedef unsigned long cycles_t;
 
 extern cycles_t get_cycles(void);
+#define get_cycles get_cycles
+
+#define random_get_entropy() (((unsigned long)get_cycles()) ?: random_get_entropy_fallback())
 
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/nios2/include/asm/uaccess.h
+++ linux-xilinx-zynqmp-5.4.0/arch/nios2/include/asm/uaccess.h
@@ -89,6 +89,7 @@
 /* Optimized macros */
 #define __get_user_asm(val, insn, addr, err)				\
 {									\
+	unsigned long __gu_val;						\
 	__asm__ __volatile__(						\
 	"       movi    %0, %3\n"					\
 	"1:   " insn " %1, 0(%2)\n"					\
@@ -97,14 +98,20 @@
 	"       .section __ex_table,\"a\"\n"				\
 	"       .word 1b, 2b\n"						\
 	"       .previous"						\
-	: "=&r" (err), "=r" (val)					\
+	: "=&r" (err), "=r" (__gu_val)					\
 	: "r" (addr), "i" (-EFAULT));					\
+	val = (__force __typeof__(*(addr)))__gu_val;			\
 }
 
-#define __get_user_unknown(val, size, ptr, err) do {			\
+extern void __get_user_unknown(void);
+
+#define __get_user_8(val, ptr, err) do {				\
+	u64 __val = 0;							\
 	err = 0;							\
-	if (__copy_from_user(&(val), ptr, size)) {			\
+	if (raw_copy_from_user(&(__val), ptr, sizeof(val))) {		\
 		err = -EFAULT;						\
+	} else {							\
+		val = (typeof(val))(typeof((val) - (val)))__val;	\
 	}								\
 	} while (0)
 
@@ -120,8 +127,11 @@
 	case 4:								\
 		__get_user_asm(val, "ldw", ptr, err);			\
 		break;							\
+	case 8:								\
+		__get_user_8(val, ptr, err);				\
+		break;							\
 	default:							\
-		__get_user_unknown(val, size, ptr, err);		\
+		__get_user_unknown();					\
 		break;							\
 	}								\
 } while (0)
@@ -130,9 +140,7 @@
 	({								\
 	long __gu_err = -EFAULT;					\
 	const __typeof__(*(ptr)) __user *__gu_ptr = (ptr);		\
-	unsigned long __gu_val = 0;					\
-	__get_user_common(__gu_val, sizeof(*(ptr)), __gu_ptr, __gu_err);\
-	(x) = (__force __typeof__(x))__gu_val;				\
+	__get_user_common(x, sizeof(*(ptr)), __gu_ptr, __gu_err);	\
 	__gu_err;							\
 	})
 
@@ -140,11 +148,9 @@
 ({									\
 	long __gu_err = -EFAULT;					\
 	const __typeof__(*(ptr)) __user *__gu_ptr = (ptr);		\
-	unsigned long __gu_val = 0;					\
 	if (access_ok( __gu_ptr, sizeof(*__gu_ptr)))	\
-		__get_user_common(__gu_val, sizeof(*__gu_ptr),		\
+		__get_user_common(x, sizeof(*__gu_ptr),			\
 			__gu_ptr, __gu_err);				\
-	(x) = (__force __typeof__(x))__gu_val;				\
 	__gu_err;							\
 })
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/nios2/kernel/entry.S
+++ linux-xilinx-zynqmp-5.4.0/arch/nios2/kernel/entry.S
@@ -185,6 +185,7 @@
 	ldw	r5, PT_R5(sp)
 
 local_restart:
+	stw	r2, PT_ORIG_R2(sp)
 	/* Check that the requested system call is within limits */
 	movui	r1, __NR_syscalls
 	bgeu	r2, r1, ret_invsyscall
@@ -192,7 +193,6 @@
 	movhi	r11, %hiadj(sys_call_table)
 	add	r1, r1, r11
 	ldw	r1, %lo(sys_call_table)(r1)
-	beq	r1, r0, ret_invsyscall
 
 	/* Check if we are being traced */
 	GET_THREAD_INFO r11
@@ -213,6 +213,9 @@
 translate_rc_and_ret:
 	movi	r1, 0
 	bge	r2, zero, 3f
+	ldw	r1, PT_ORIG_R2(sp)
+	addi	r1, r1, 1
+	beq	r1, zero, 3f
 	sub	r2, zero, r2
 	movi	r1, 1
 3:
@@ -255,9 +258,9 @@
 	ldw	r6, PT_R6(sp)
 	ldw	r7, PT_R7(sp)
 
-	/* Fetch the syscall function, we don't need to check the boundaries
-	 * since this is already done.
-	 */
+	/* Fetch the syscall function. */
+	movui	r1, __NR_syscalls
+	bgeu	r2, r1, traced_invsyscall
 	slli	r1, r2, 2
 	movhi	r11,%hiadj(sys_call_table)
 	add	r1, r1, r11
@@ -276,6 +279,9 @@
 translate_rc_and_ret2:
 	movi	r1, 0
 	bge	r2, zero, 4f
+	ldw	r1, PT_ORIG_R2(sp)
+	addi	r1, r1, 1
+	beq	r1, zero, 4f
 	sub	r2, zero, r2
 	movi	r1, 1
 4:
@@ -287,6 +293,11 @@
 	RESTORE_SWITCH_STACK
 	br	ret_from_exception
 
+	/* If the syscall number was invalid return ENOSYS */
+traced_invsyscall:
+	movi	r2, -ENOSYS
+	br	translate_rc_and_ret2
+
 Luser_return:
 	GET_THREAD_INFO	r11			/* get thread_info pointer */
 	ldw	r10, TI_FLAGS(r11)		/* get thread_info->flags */
@@ -336,9 +347,6 @@
 	/* skip if no interrupt is pending */
 	beq	r12, r0, ret_from_interrupt
 
-	movi	r24, -1
-	stw	r24, PT_ORIG_R2(sp)
-
 	/*
 	 * Process an external hardware interrupt.
 	 */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/nios2/kernel/signal.c
+++ linux-xilinx-zynqmp-5.4.0/arch/nios2/kernel/signal.c
@@ -240,7 +240,7 @@
 	/*
 	 * If we were from a system call, check for system call restarting...
 	 */
-	if (regs->orig_r2 >= 0) {
+	if (regs->orig_r2 >= 0 && regs->r1) {
 		continue_addr = regs->ea;
 		restart_addr = continue_addr - 4;
 		retval = regs->r2;
@@ -261,6 +261,7 @@
 			regs->ea = restart_addr;
 			break;
 		}
+		regs->orig_r2 = -1;
 	}
 
 	if (get_signal(&ksig)) {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/nios2/kernel/syscall_table.c
+++ linux-xilinx-zynqmp-5.4.0/arch/nios2/kernel/syscall_table.c
@@ -13,5 +13,6 @@
 #define __SYSCALL(nr, call) [nr] = (call),
 
 void *sys_call_table[__NR_syscalls] = {
+	[0 ... __NR_syscalls-1] = sys_ni_syscall,
 #include <asm/unistd.h>
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/nios2/kernel/traps.c
+++ linux-xilinx-zynqmp-5.4.0/arch/nios2/kernel/traps.c
@@ -37,10 +37,10 @@
 	show_regs(regs);
 	spin_unlock_irq(&die_lock);
 	/*
-	 * do_exit() should take care of panic'ing from an interrupt
+	 * make_task_dead() should take care of panic'ing from an interrupt
 	 * context so we don't handle it here
 	 */
-	do_exit(err);
+	make_task_dead(err);
 }
 
 void _exception(int signo, struct pt_regs *regs, int code, unsigned long addr)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/nios2/mm/dma-mapping.c
+++ linux-xilinx-zynqmp-5.4.0/arch/nios2/mm/dma-mapping.c
@@ -18,8 +18,8 @@
 #include <linux/cache.h>
 #include <asm/cacheflush.h>
 
-void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr,
-		size_t size, enum dma_data_direction dir)
+void arch_sync_dma_for_device(phys_addr_t paddr, size_t size,
+		enum dma_data_direction dir)
 {
 	void *vaddr = phys_to_virt(paddr);
 
@@ -42,8 +42,8 @@
 	}
 }
 
-void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr,
-		size_t size, enum dma_data_direction dir)
+void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size,
+		enum dma_data_direction dir)
 {
 	void *vaddr = phys_to_virt(paddr);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/nios2/platform/Kconfig.platform
+++ linux-xilinx-zynqmp-5.4.0/arch/nios2/platform/Kconfig.platform
@@ -37,6 +37,7 @@
 
 config NIOS2_DTB_SOURCE_BOOL
 	bool "Compile and link device tree into kernel image"
+	depends on !COMPILE_TEST
 	help
 	  This allows you to specify a dts (device tree source) file
 	  which will be compiled and linked into the kernel image.
--- linux-xilinx-zynqmp-5.4.0.orig/arch/openrisc/include/asm/barrier.h
+++ linux-xilinx-zynqmp-5.4.0/arch/openrisc/include/asm/barrier.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ASM_BARRIER_H
+#define __ASM_BARRIER_H
+
+#define mb() asm volatile ("l.msync" ::: "memory")
+
+#include <asm-generic/barrier.h>
+
+#endif /* __ASM_BARRIER_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/openrisc/include/asm/timex.h
+++ linux-xilinx-zynqmp-5.4.0/arch/openrisc/include/asm/timex.h
@@ -23,6 +23,7 @@
 {
 	return mfspr(SPR_TTCR);
 }
+#define get_cycles get_cycles
 
 /* This isn't really used any more */
 #define CLOCK_TICK_RATE 1000
--- linux-xilinx-zynqmp-5.4.0.orig/arch/openrisc/include/asm/uaccess.h
+++ linux-xilinx-zynqmp-5.4.0/arch/openrisc/include/asm/uaccess.h
@@ -164,19 +164,19 @@
 
 #define __get_user_nocheck(x, ptr, size)			\
 ({								\
-	long __gu_err, __gu_val;				\
-	__get_user_size(__gu_val, (ptr), (size), __gu_err);	\
-	(x) = (__force __typeof__(*(ptr)))__gu_val;		\
+	long __gu_err;						\
+	__get_user_size((x), (ptr), (size), __gu_err);		\
 	__gu_err;						\
 })
 
 #define __get_user_check(x, ptr, size)					\
 ({									\
-	long __gu_err = -EFAULT, __gu_val = 0;				\
-	const __typeof__(*(ptr)) * __gu_addr = (ptr);			\
-	if (access_ok(__gu_addr, size))			\
-		__get_user_size(__gu_val, __gu_addr, (size), __gu_err);	\
-	(x) = (__force __typeof__(*(ptr)))__gu_val;			\
+	long __gu_err = -EFAULT;					\
+	const __typeof__(*(ptr)) *__gu_addr = (ptr);			\
+	if (access_ok(__gu_addr, size))					\
+		__get_user_size((x), __gu_addr, (size), __gu_err);	\
+	else								\
+		(x) = (__typeof__(*(ptr))) 0;				\
 	__gu_err;							\
 })
 
@@ -190,11 +190,13 @@
 	case 2: __get_user_asm(x, ptr, retval, "l.lhz"); break;		\
 	case 4: __get_user_asm(x, ptr, retval, "l.lwz"); break;		\
 	case 8: __get_user_asm2(x, ptr, retval); break;			\
-	default: (x) = __get_user_bad();				\
+	default: (x) = (__typeof__(*(ptr)))__get_user_bad();		\
 	}								\
 } while (0)
 
 #define __get_user_asm(x, addr, err, op)		\
+{							\
+	unsigned long __gu_tmp;				\
 	__asm__ __volatile__(				\
 		"1:	"op" %1,0(%2)\n"		\
 		"2:\n"					\
@@ -208,10 +210,14 @@
 		"	.align 2\n"			\
 		"	.long 1b,3b\n"			\
 		".previous"				\
-		: "=r"(err), "=r"(x)			\
-		: "r"(addr), "i"(-EFAULT), "0"(err))
+		: "=r"(err), "=r"(__gu_tmp)		\
+		: "r"(addr), "i"(-EFAULT), "0"(err));	\
+	(x) = (__typeof__(*(addr)))__gu_tmp;		\
+}
 
 #define __get_user_asm2(x, addr, err)			\
+{							\
+	unsigned long long __gu_tmp;			\
 	__asm__ __volatile__(				\
 		"1:	l.lwz %1,0(%2)\n"		\
 		"2:	l.lwz %H1,4(%2)\n"		\
@@ -228,8 +234,11 @@
 		"	.long 1b,4b\n"			\
 		"	.long 2b,4b\n"			\
 		".previous"				\
-		: "=r"(err), "=&r"(x)			\
-		: "r"(addr), "i"(-EFAULT), "0"(err))
+		: "=r"(err), "=&r"(__gu_tmp)		\
+		: "r"(addr), "i"(-EFAULT), "0"(err));	\
+	(x) = (__typeof__(*(addr)))(			\
+		(__typeof__((x)-(x)))__gu_tmp);		\
+}
 
 /* more complex routines */
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/openrisc/kernel/dma.c
+++ linux-xilinx-zynqmp-5.4.0/arch/openrisc/kernel/dma.c
@@ -125,7 +125,7 @@
 	free_pages_exact(vaddr, size);
 }
 
-void arch_sync_dma_for_device(struct device *dev, phys_addr_t addr, size_t size,
+void arch_sync_dma_for_device(phys_addr_t addr, size_t size,
 		enum dma_data_direction dir)
 {
 	unsigned long cl;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/openrisc/kernel/entry.S
+++ linux-xilinx-zynqmp-5.4.0/arch/openrisc/kernel/entry.S
@@ -173,7 +173,6 @@
 	l.sw    PT_GPR28(r1),r28					;\
 	l.sw    PT_GPR29(r1),r29					;\
 	/* r30 already save */					;\
-/*        l.sw    PT_GPR30(r1),r30*/					;\
 	l.sw    PT_GPR31(r1),r31					;\
 	TRACE_IRQS_OFF_ENTRY						;\
 	/* Store -1 in orig_gpr11 for non-syscall exceptions */	;\
@@ -211,9 +210,8 @@
 	l.sw    PT_GPR27(r1),r27					;\
 	l.sw    PT_GPR28(r1),r28					;\
 	l.sw    PT_GPR29(r1),r29					;\
-	/* r31 already saved */					;\
-	l.sw    PT_GPR30(r1),r30					;\
-/*        l.sw    PT_GPR31(r1),r31	*/				;\
+	/* r30 already saved */						;\
+	l.sw    PT_GPR31(r1),r31					;\
 	/* Store -1 in orig_gpr11 for non-syscall exceptions */	;\
 	l.addi	r30,r0,-1					;\
 	l.sw	PT_ORIG_GPR11(r1),r30				;\
@@ -547,6 +545,7 @@
 	l.bnf	1f			// ext irq enabled, all ok.
 	l.nop
 
+#ifdef CONFIG_PRINTK
 	l.addi  r1,r1,-0x8
 	l.movhi r3,hi(42f)
 	l.ori	r3,r3,lo(42f)
@@ -560,6 +559,7 @@
 		.string "\n\rESR interrupt bug: in _external_irq_handler (ESR %x)\n\r"
 		.align 4
 	.previous
+#endif
 
 	l.ori	r4,r4,SPR_SR_IEE	// fix the bug
 //	l.sw	PT_SR(r1),r4
@@ -1166,13 +1166,13 @@
 	l.movhi	r29,hi(sys_clone)
 	l.ori	r29,r29,lo(sys_clone)
 	l.j	_fork_save_extra_regs_and_call
-	 l.addi	r7,r1,0
+	 l.nop
 
 ENTRY(__sys_fork)
 	l.movhi	r29,hi(sys_fork)
 	l.ori	r29,r29,lo(sys_fork)
 	l.j	_fork_save_extra_regs_and_call
-	 l.addi	r3,r1,0
+	 l.nop
 
 ENTRY(sys_rt_sigreturn)
 	l.jal	_sys_rt_sigreturn
--- linux-xilinx-zynqmp-5.4.0.orig/arch/openrisc/kernel/head.S
+++ linux-xilinx-zynqmp-5.4.0/arch/openrisc/kernel/head.S
@@ -521,6 +521,15 @@
 	l.ori	r3,r0,0x1
 	l.mtspr	r0,r3,SPR_SR
 
+	/*
+	 * Start the TTCR as early as possible, so that the RNG can make use of
+	 * measurements of boot time from the earliest opportunity. Especially
+	 * important is that the TTCR does not return zero by the time we reach
+	 * rand_initialize().
+	 */
+	l.movhi r3,hi(SPR_TTMR_CR)
+	l.mtspr r0,r3,SPR_TTMR
+
 	CLEAR_GPR(r1)
 	CLEAR_GPR(r2)
 	CLEAR_GPR(r3)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/openrisc/kernel/setup.c
+++ linux-xilinx-zynqmp-5.4.0/arch/openrisc/kernel/setup.c
@@ -274,10 +274,15 @@
 	pr_cont("%lu.%02lu BogoMIPS (lpj=%lu)\n",
 		loops_per_jiffy / (500000 / HZ),
 		(loops_per_jiffy / (5000 / HZ)) % 100, loops_per_jiffy);
+
+	of_node_put(cpu);
 }
 
 void __init setup_arch(char **cmdline_p)
 {
+	/* setup memblock allocator */
+	setup_memory();
+
 	unflatten_and_copy_device_tree();
 
 	setup_cpuinfo();
@@ -302,9 +307,6 @@
 	initrd_below_start_ok = 1;
 #endif
 
-	/* setup memblock allocator */
-	setup_memory();
-
 	/* paging_init() sets up the MMU and marks all pages as reserved */
 	paging_init();
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/openrisc/kernel/stacktrace.c
+++ linux-xilinx-zynqmp-5.4.0/arch/openrisc/kernel/stacktrace.c
@@ -13,6 +13,7 @@
 #include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/sched/debug.h>
+#include <linux/sched/task_stack.h>
 #include <linux/stacktrace.h>
 
 #include <asm/processor.h>
@@ -68,12 +69,25 @@
 {
 	unsigned long *sp = NULL;
 
+	if (!try_get_task_stack(tsk))
+		return;
+
 	if (tsk == current)
 		sp = (unsigned long *) &sp;
-	else
-		sp = (unsigned long *) KSTK_ESP(tsk);
+	else {
+		unsigned long ksp;
+
+		/* Locate stack from kernel context */
+		ksp = task_thread_info(tsk)->ksp;
+		ksp += STACK_FRAME_OVERHEAD;	/* redzone */
+		ksp += sizeof(struct pt_regs);
+
+		sp = (unsigned long *) ksp;
+	}
 
 	unwind_stack(trace, sp, save_stack_address_nosched);
+
+	put_task_stack(tsk);
 }
 EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/openrisc/kernel/traps.c
+++ linux-xilinx-zynqmp-5.4.0/arch/openrisc/kernel/traps.c
@@ -218,7 +218,7 @@
 	__asm__ __volatile__("l.nop   1");
 	do {} while (1);
 #endif
-	do_exit(SIGSEGV);
+	make_task_dead(SIGSEGV);
 }
 
 /* This is normally the 'Oops' routine */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/openrisc/mm/cache.c
+++ linux-xilinx-zynqmp-5.4.0/arch/openrisc/mm/cache.c
@@ -16,7 +16,7 @@
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 
-static void cache_loop(struct page *page, const unsigned int reg)
+static __always_inline void cache_loop(struct page *page, const unsigned int reg)
 {
 	unsigned long paddr = page_to_pfn(page) << PAGE_SHIFT;
 	unsigned long line = paddr & ~(L1_CACHE_BYTES - 1);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/Kconfig
@@ -11,6 +11,7 @@
 	select ARCH_WANT_FRAME_POINTERS
 	select ARCH_HAS_ELF_RANDOMIZE
 	select ARCH_HAS_STRICT_KERNEL_RWX
+	select ARCH_HAS_STRICT_MODULE_RWX
 	select ARCH_HAS_UBSAN_SANITIZE_ALL
 	select ARCH_NO_SG_CHAIN
 	select ARCH_SUPPORTS_MEMORY_FAILURE
@@ -62,6 +63,7 @@
 	select HAVE_FTRACE_MCOUNT_RECORD if HAVE_DYNAMIC_FTRACE
 	select HAVE_KPROBES_ON_FTRACE
 	select HAVE_DYNAMIC_FTRACE_WITH_REGS
+	select HAVE_COPY_THREAD_TLS
 
 	help
 	  The PA-RISC microprocessor is designed by Hewlett-Packard and used
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/Makefile
@@ -17,7 +17,12 @@
 # Mike Shaver, Helge Deller and Martin K. Petersen
 #
 
+ifdef CONFIG_PARISC_SELF_EXTRACT
+boot := arch/parisc/boot
+KBUILD_IMAGE := $(boot)/bzImage
+else
 KBUILD_IMAGE := vmlinuz
+endif
 
 NM		= sh $(srctree)/arch/parisc/nm
 CHECKFLAGS	+= -D__hppa__=1
@@ -60,7 +65,6 @@
 		 -DFTRACE_PATCHABLE_FUNCTION_SIZE=$(NOP_COUNT)
 
 CC_FLAGS_FTRACE := -fpatchable-function-entry=$(NOP_COUNT),$(shell echo $$(($(NOP_COUNT)-1)))
-KBUILD_LDS_MODULE += $(srctree)/arch/parisc/kernel/module.lds
 endif
 
 OBJCOPY_FLAGS =-O binary -R .note -R .comment -S
@@ -156,7 +160,7 @@
 	$(OBJCOPY) $(boot)/bzImage $@
 else
 vmlinuz: vmlinux
-	@gzip -cf -9 $< > $@
+	@$(KGZIP) -cf -9 $< > $@
 endif
 
 install:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/include/asm/atomic.h
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/include/asm/atomic.h
@@ -212,6 +212,8 @@
 	_atomic_spin_unlock_irqrestore(v, flags);
 }
 
+#define atomic64_set_release(v, i)	atomic64_set((v), (i))
+
 static __inline__ s64
 atomic64_read(const atomic64_t *v)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/include/asm/barrier.h
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/include/asm/barrier.h
@@ -26,6 +26,67 @@
 #define __smp_rmb()	mb()
 #define __smp_wmb()	mb()
 
+#define __smp_store_release(p, v)					\
+do {									\
+	typeof(p) __p = (p);						\
+        union { typeof(*p) __val; char __c[1]; } __u =			\
+                { .__val = (__force typeof(*p)) (v) };			\
+	compiletime_assert_atomic_type(*p);				\
+	switch (sizeof(*p)) {						\
+	case 1:								\
+		asm volatile("stb,ma %0,0(%1)"				\
+				: : "r"(*(__u8 *)__u.__c), "r"(__p)	\
+				: "memory");				\
+		break;							\
+	case 2:								\
+		asm volatile("sth,ma %0,0(%1)"				\
+				: : "r"(*(__u16 *)__u.__c), "r"(__p)	\
+				: "memory");				\
+		break;							\
+	case 4:								\
+		asm volatile("stw,ma %0,0(%1)"				\
+				: : "r"(*(__u32 *)__u.__c), "r"(__p)	\
+				: "memory");				\
+		break;							\
+	case 8:								\
+		if (IS_ENABLED(CONFIG_64BIT))				\
+			asm volatile("std,ma %0,0(%1)"			\
+				: : "r"(*(__u64 *)__u.__c), "r"(__p)	\
+				: "memory");				\
+		break;							\
+	}								\
+} while (0)
+
+#define __smp_load_acquire(p)						\
+({									\
+	union { typeof(*p) __val; char __c[1]; } __u;			\
+	typeof(p) __p = (p);						\
+	compiletime_assert_atomic_type(*p);				\
+	switch (sizeof(*p)) {						\
+	case 1:								\
+		asm volatile("ldb,ma 0(%1),%0"				\
+				: "=r"(*(__u8 *)__u.__c) : "r"(__p)	\
+				: "memory");				\
+		break;							\
+	case 2:								\
+		asm volatile("ldh,ma 0(%1),%0"				\
+				: "=r"(*(__u16 *)__u.__c) : "r"(__p)	\
+				: "memory");				\
+		break;							\
+	case 4:								\
+		asm volatile("ldw,ma 0(%1),%0"				\
+				: "=r"(*(__u32 *)__u.__c) : "r"(__p)	\
+				: "memory");				\
+		break;							\
+	case 8:								\
+		if (IS_ENABLED(CONFIG_64BIT))				\
+			asm volatile("ldd,ma 0(%1),%0"			\
+				: "=r"(*(__u64 *)__u.__c) : "r"(__p)	\
+				: "memory");				\
+		break;							\
+	}								\
+	__u.__val;							\
+})
 #include <asm-generic/barrier.h>
 
 #endif /* !__ASSEMBLY__ */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/include/asm/cacheflush.h
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/include/asm/cacheflush.h
@@ -57,6 +57,11 @@
 
 #define flush_dcache_mmap_lock(mapping)		xa_lock_irq(&mapping->i_pages)
 #define flush_dcache_mmap_unlock(mapping)	xa_unlock_irq(&mapping->i_pages)
+#define flush_dcache_mmap_lock_irqsave(mapping, flags)		\
+		xa_lock_irqsave(&mapping->i_pages, flags)
+#define flush_dcache_mmap_unlock_irqrestore(mapping, flags)	\
+		xa_unlock_irqrestore(&mapping->i_pages, flags)
+
 
 #define flush_icache_page(vma,page)	do { 		\
 	flush_kernel_dcache_page(page);			\
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/include/asm/checksum.h
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/include/asm/checksum.h
@@ -42,31 +42,32 @@
 static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
 {
 	unsigned int sum;
+	unsigned long t0, t1, t2;
 
 	__asm__ __volatile__ (
 "	ldws,ma		4(%1), %0\n"
 "	addib,<=	-4, %2, 2f\n"
 "\n"
-"	ldws		4(%1), %%r20\n"
-"	ldws		8(%1), %%r21\n"
-"	add		%0, %%r20, %0\n"
-"	ldws,ma		12(%1), %%r19\n"
-"	addc		%0, %%r21, %0\n"
-"	addc		%0, %%r19, %0\n"
-"1:	ldws,ma		4(%1), %%r19\n"
-"	addib,<		0, %2, 1b\n"
-"	addc		%0, %%r19, %0\n"
+"	ldws		4(%1), %4\n"
+"	ldws		8(%1), %5\n"
+"	add		%0, %4, %0\n"
+"	ldws,ma		12(%1), %3\n"
+"	addc		%0, %5, %0\n"
+"	addc		%0, %3, %0\n"
+"1:	ldws,ma		4(%1), %3\n"
+"	addib,>		-1, %2, 1b\n"
+"	addc		%0, %3, %0\n"
 "\n"
-"	extru		%0, 31, 16, %%r20\n"
-"	extru		%0, 15, 16, %%r21\n"
-"	addc		%%r20, %%r21, %0\n"
-"	extru		%0, 15, 16, %%r21\n"
-"	add		%0, %%r21, %0\n"
+"	extru		%0, 31, 16, %4\n"
+"	extru		%0, 15, 16, %5\n"
+"	addc		%4, %5, %0\n"
+"	extru		%0, 15, 16, %5\n"
+"	add		%0, %5, %0\n"
 "	subi		-1, %0, %0\n"
 "2:\n"
-	: "=r" (sum), "=r" (iph), "=r" (ihl)
+	: "=r" (sum), "=r" (iph), "=r" (ihl), "=r" (t0), "=r" (t1), "=r" (t2)
 	: "1" (iph), "2" (ihl)
-	: "r19", "r20", "r21", "memory");
+	: "memory");
 
 	return (__force __sum16)sum;
 }
@@ -126,6 +127,10 @@
 					  __u32 len, __u8 proto,
 					  __wsum sum)
 {
+	unsigned long t0, t1, t2, t3;
+
+	len += proto;	/* add 16-bit proto + len */
+
 	__asm__ __volatile__ (
 
 #if BITS_PER_LONG > 32
@@ -136,20 +141,20 @@
 	** Try to keep 4 registers with "live" values ahead of the ALU.
 	*/
 
-"	ldd,ma		8(%1), %%r19\n"	/* get 1st saddr word */
-"	ldd,ma		8(%2), %%r20\n"	/* get 1st daddr word */
-"	add		%8, %3, %3\n"/* add 16-bit proto + len */
-"	add		%%r19, %0, %0\n"
-"	ldd,ma		8(%1), %%r21\n"	/* 2cd saddr */
-"	ldd,ma		8(%2), %%r22\n"	/* 2cd daddr */
-"	add,dc		%%r20, %0, %0\n"
-"	add,dc		%%r21, %0, %0\n"
-"	add,dc		%%r22, %0, %0\n"
+"	depdi		0, 31, 32, %0\n"/* clear upper half of incoming checksum */
+"	ldd,ma		8(%1), %4\n"	/* get 1st saddr word */
+"	ldd,ma		8(%2), %5\n"	/* get 1st daddr word */
+"	add		%4, %0, %0\n"
+"	ldd,ma		8(%1), %6\n"	/* 2nd saddr */
+"	ldd,ma		8(%2), %7\n"	/* 2nd daddr */
+"	add,dc		%5, %0, %0\n"
+"	add,dc		%6, %0, %0\n"
+"	add,dc		%7, %0, %0\n"
 "	add,dc		%3, %0, %0\n"  /* fold in proto+len | carry bit */
-"	extrd,u		%0, 31, 32, %%r19\n"	/* copy upper half down */
-"	depdi		0, 31, 32, %0\n"	/* clear upper half */
-"	add		%%r19, %0, %0\n"	/* fold into 32-bits */
-"	addc		0, %0, %0\n"		/* add carry */
+"	extrd,u		%0, 31, 32, %4\n"/* copy upper half down */
+"	depdi		0, 31, 32, %0\n"/* clear upper half */
+"	add,dc		%4, %0, %0\n"	/* fold into 32-bits, plus carry */
+"	addc		0, %0, %0\n"	/* add final carry */
 
 #else
 
@@ -158,30 +163,30 @@
 	** Insn stream is serialized on the carry bit here too.
 	** result from the previous operation (eg r0 + x)
 	*/
-
-"	ldw,ma		4(%1), %%r19\n"	/* get 1st saddr word */
-"	ldw,ma		4(%2), %%r20\n"	/* get 1st daddr word */
-"	add		%8, %3, %3\n"	/* add 16-bit proto + len */
-"	add		%%r19, %0, %0\n"
-"	ldw,ma		4(%1), %%r21\n"	/* 2cd saddr */
-"	addc		%%r20, %0, %0\n"
-"	ldw,ma		4(%2), %%r22\n"	/* 2cd daddr */
-"	addc		%%r21, %0, %0\n"
-"	ldw,ma		4(%1), %%r19\n"	/* 3rd saddr */
-"	addc		%%r22, %0, %0\n"
-"	ldw,ma		4(%2), %%r20\n"	/* 3rd daddr */
-"	addc		%%r19, %0, %0\n"
-"	ldw,ma		4(%1), %%r21\n"	/* 4th saddr */
-"	addc		%%r20, %0, %0\n"
-"	ldw,ma		4(%2), %%r22\n"	/* 4th daddr */
-"	addc		%%r21, %0, %0\n"
-"	addc		%%r22, %0, %0\n"
-"	addc		%3, %0, %0\n"	/* fold in proto+len, catch carry */
+"	ldw,ma		4(%1), %4\n"	/* get 1st saddr word */
+"	ldw,ma		4(%2), %5\n"	/* get 1st daddr word */
+"	add		%4, %0, %0\n"
+"	ldw,ma		4(%1), %6\n"	/* 2nd saddr */
+"	addc		%5, %0, %0\n"
+"	ldw,ma		4(%2), %7\n"	/* 2nd daddr */
+"	addc		%6, %0, %0\n"
+"	ldw,ma		4(%1), %4\n"	/* 3rd saddr */
+"	addc		%7, %0, %0\n"
+"	ldw,ma		4(%2), %5\n"	/* 3rd daddr */
+"	addc		%4, %0, %0\n"
+"	ldw,ma		4(%1), %6\n"	/* 4th saddr */
+"	addc		%5, %0, %0\n"
+"	ldw,ma		4(%2), %7\n"	/* 4th daddr */
+"	addc		%6, %0, %0\n"
+"	addc		%7, %0, %0\n"
+"	addc		%3, %0, %0\n"	/* fold in proto+len */
+"	addc		0, %0, %0\n"	/* add carry */
 
 #endif
-	: "=r" (sum), "=r" (saddr), "=r" (daddr), "=r" (len)
-	: "0" (sum), "1" (saddr), "2" (daddr), "3" (len), "r" (proto)
-	: "r19", "r20", "r21", "r22", "memory");
+	: "=r" (sum), "=r" (saddr), "=r" (daddr), "=r" (len),
+	  "=r" (t0), "=r" (t1), "=r" (t2), "=r" (t3)
+	: "0" (sum), "1" (saddr), "2" (daddr), "3" (len)
+	: "memory");
 	return csum_fold(sum);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/include/asm/cmpxchg.h
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/include/asm/cmpxchg.h
@@ -44,8 +44,14 @@
 **		if (((unsigned long)p & 0xf) == 0)
 **			return __ldcw(p);
 */
-#define xchg(ptr, x) \
-	((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
+#define xchg(ptr, x)							\
+({									\
+	__typeof__(*(ptr)) __ret;					\
+	__typeof__(*(ptr)) _x_ = (x);					\
+	__ret = (__typeof__(*(ptr)))					\
+		__xchg((unsigned long)_x_, (ptr), sizeof(*(ptr)));	\
+	__ret;								\
+})
 
 /* bug catcher for when unsupported size is used - won't link */
 extern void __cmpxchg_called_with_bad_pointer(void);
@@ -54,6 +60,7 @@
 extern unsigned long __cmpxchg_u32(volatile unsigned int *m, unsigned int old,
 				   unsigned int new_);
 extern u64 __cmpxchg_u64(volatile u64 *ptr, u64 old, u64 new_);
+extern u8 __cmpxchg_u8(volatile u8 *ptr, u8 old, u8 new_);
 
 /* don't worry...optimizer will get rid of most of this */
 static inline unsigned long
@@ -65,6 +72,7 @@
 #endif
 	case 4: return __cmpxchg_u32((unsigned int *)ptr,
 				     (unsigned int)old, (unsigned int)new_);
+	case 1: return __cmpxchg_u8((u8 *)ptr, old & 0xff, new_ & 0xff);
 	}
 	__cmpxchg_called_with_bad_pointer();
 	return old;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/include/asm/hardware.h
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/include/asm/hardware.h
@@ -10,12 +10,12 @@
 #define SVERSION_ANY_ID		PA_SVERSION_ANY_ID
 
 struct hp_hardware {
-	unsigned short	hw_type:5;	/* HPHW_xxx */
-	unsigned short	hversion;
-	unsigned long	sversion:28;
-	unsigned short	opt;
-	const char	name[80];	/* The hardware description */
-};
+	unsigned int	hw_type:8;	/* HPHW_xxx */
+	unsigned int	hversion:12;
+	unsigned int	sversion:12;
+	unsigned char	opt;
+	unsigned char	name[59];	/* The hardware description */
+} __packed;
 
 struct parisc_device;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/include/asm/kexec.h
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/include/asm/kexec.h
@@ -2,8 +2,6 @@
 #ifndef _ASM_PARISC_KEXEC_H
 #define _ASM_PARISC_KEXEC_H
 
-#ifdef CONFIG_KEXEC
-
 /* Maximum physical address we can use pages from */
 #define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
 /* Maximum address we can reach in physical address mode */
@@ -32,6 +30,4 @@
 
 #endif /* __ASSEMBLY__ */
 
-#endif /* CONFIG_KEXEC */
-
 #endif /* _ASM_PARISC_KEXEC_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/include/asm/ldcw.h
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/include/asm/ldcw.h
@@ -2,14 +2,28 @@
 #ifndef __PARISC_LDCW_H
 #define __PARISC_LDCW_H
 
-#ifndef CONFIG_PA20
 /* Because kmalloc only guarantees 8-byte alignment for kmalloc'd data,
    and GCC only guarantees 8-byte alignment for stack locals, we can't
    be assured of 16-byte alignment for atomic lock data even if we
    specify "__attribute ((aligned(16)))" in the type declaration.  So,
    we use a struct containing an array of four ints for the atomic lock
    type and dynamically select the 16-byte aligned int from the array
-   for the semaphore.  */
+   for the semaphore. */
+
+/* From: "Jim Hull" <jim.hull of hp.com>
+   I've attached a summary of the change, but basically, for PA 2.0, as
+   long as the ",CO" (coherent operation) completer is implemented, then the
+   16-byte alignment requirement for ldcw and ldcd is relaxed, and instead
+   they only require "natural" alignment (4-byte for ldcw, 8-byte for
+   ldcd).
+
+   Although the cache control hint is accepted by all PA 2.0 processors,
+   it is only implemented on PA8800/PA8900 CPUs. Prior PA8X00 CPUs still
+   require 16-byte alignment. If the address is unaligned, the operation
+   of the instruction is undefined. The ldcw instruction does not generate
+   unaligned data reference traps so misaligned accesses are not detected.
+   This hid the problem for years. So, restore the 16-byte alignment dropped
+   by Kyle McMartin in "Remove __ldcw_align for PA-RISC 2.0 processors". */
 
 #define __PA_LDCW_ALIGNMENT	16
 #define __PA_LDCW_ALIGN_ORDER	4
@@ -19,22 +33,12 @@
 		& ~(__PA_LDCW_ALIGNMENT - 1);			\
 	(volatile unsigned int *) __ret;			\
 })
-#define __LDCW	"ldcw"
 
-#else /*CONFIG_PA20*/
-/* From: "Jim Hull" <jim.hull of hp.com>
-   I've attached a summary of the change, but basically, for PA 2.0, as
-   long as the ",CO" (coherent operation) completer is specified, then the
-   16-byte alignment requirement for ldcw and ldcd is relaxed, and instead
-   they only require "natural" alignment (4-byte for ldcw, 8-byte for
-   ldcd). */
-
-#define __PA_LDCW_ALIGNMENT	4
-#define __PA_LDCW_ALIGN_ORDER	2
-#define __ldcw_align(a) (&(a)->slock)
+#ifdef CONFIG_PA20
 #define __LDCW	"ldcw,co"
-
-#endif /*!CONFIG_PA20*/
+#else
+#define __LDCW	"ldcw"
+#endif
 
 /* LDCW, the only atomic read-write operation PA-RISC has. *sigh*.
    We don't explicitly expose that "*a" may be written as reload
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/include/asm/led.h
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/include/asm/led.h
@@ -11,8 +11,8 @@
 #define	LED1		0x02
 #define	LED0		0x01		/* bottom (or furthest left) LED */
 
-#define	LED_LAN_TX	LED0		/* for LAN transmit activity */
-#define	LED_LAN_RCV	LED1		/* for LAN receive activity */
+#define	LED_LAN_RCV	LED0		/* for LAN receive activity */
+#define	LED_LAN_TX	LED1		/* for LAN transmit activity */
 #define	LED_DISK_IO	LED2		/* for disk activity */
 #define	LED_HEARTBEAT	LED3		/* heartbeat */
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/include/asm/page.h
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/include/asm/page.h
@@ -181,7 +181,7 @@
 #include <asm-generic/getorder.h>
 #include <asm/pdc.h>
 
-#define PAGE0   ((struct zeropage *)__PAGE_OFFSET)
+#define PAGE0   ((struct zeropage *)absolute_pointer(__PAGE_OFFSET))
 
 /* DEFINITION OF THE ZERO-PAGE (PAG0) */
 /* based on work by Jason Eckhardt (jason@equator.com) */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/include/asm/processor.h
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/include/asm/processor.h
@@ -97,7 +97,6 @@
 	unsigned long cpu_loc;      /* CPU location from PAT firmware */
 	unsigned int state;
 	struct parisc_device *dev;
-	unsigned long loops_per_jiffy;
 };
 
 extern struct system_cpuinfo_parisc boot_cpu_data;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/include/asm/ropes.h
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/include/asm/ropes.h
@@ -86,6 +86,9 @@
 	struct ioc		ioc[MAX_IOC];
 };
 
+/* list of SBA's in system, see drivers/parisc/sba_iommu.c */
+extern struct sba_device *sba_list;
+
 #define ASTRO_RUNWAY_PORT	0x582
 #define IKE_MERCED_PORT		0x803
 #define REO_MERCED_PORT		0x804
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/include/asm/spinlock.h
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/include/asm/spinlock.h
@@ -37,12 +37,8 @@
 	volatile unsigned int *a;
 
 	a = __ldcw_align(x);
-#ifdef CONFIG_SMP
-	(void) __ldcw(a);
-#else
-	mb();
-#endif
-	*a = 1;
+	/* Release with ordered store. */
+	__asm__ __volatile__("stw,ma %0,0(%1)" : : "r"(1), "r"(a) : "memory");
 }
 
 static inline int arch_spin_trylock(arch_spinlock_t *x)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/include/asm/spinlock_types.h
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/include/asm/spinlock_types.h
@@ -3,13 +3,8 @@
 #define __ASM_SPINLOCK_TYPES_H
 
 typedef struct {
-#ifdef CONFIG_PA20
-	volatile unsigned int slock;
-# define __ARCH_SPIN_LOCK_UNLOCKED { 1 }
-#else
 	volatile unsigned int lock[4];
 # define __ARCH_SPIN_LOCK_UNLOCKED	{ { 1, 1, 1, 1 } }
-#endif
 } arch_spinlock_t;
 
 typedef struct {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/include/asm/string.h
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/include/asm/string.h
@@ -8,19 +8,4 @@
 #define __HAVE_ARCH_MEMCPY
 void * memcpy(void * dest,const void *src,size_t count);
 
-#define __HAVE_ARCH_STRLEN
-extern size_t strlen(const char *s);
-
-#define __HAVE_ARCH_STRCPY
-extern char *strcpy(char *dest, const char *src);
-
-#define __HAVE_ARCH_STRNCPY
-extern char *strncpy(char *dest, const char *src, size_t count);
-
-#define __HAVE_ARCH_STRCAT
-extern char *strcat(char *dest, const char *src);
-
-#define __HAVE_ARCH_MEMSET
-extern void *memset(void *, int, size_t);
-
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/include/asm/timex.h
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/include/asm/timex.h
@@ -12,9 +12,10 @@
 
 typedef unsigned long cycles_t;
 
-static inline cycles_t get_cycles (void)
+static inline cycles_t get_cycles(void)
 {
 	return mfctl(16);
 }
+#define get_cycles get_cycles
 
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/include/uapi/asm/mman.h
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/include/uapi/asm/mman.h
@@ -48,28 +48,27 @@
 #define MADV_DONTFORK	10		/* don't inherit across fork */
 #define MADV_DOFORK	11		/* do inherit across fork */
 
-#define MADV_COLD	20		/* deactivate these pages */
-#define MADV_PAGEOUT	21		/* reclaim these pages */
-
-#define MADV_MERGEABLE   65		/* KSM may merge identical pages */
-#define MADV_UNMERGEABLE 66		/* KSM may not merge identical pages */
+#define MADV_MERGEABLE   12		/* KSM may merge identical pages */
+#define MADV_UNMERGEABLE 13		/* KSM may not merge identical pages */
 
-#define MADV_HUGEPAGE	67		/* Worth backing with hugepages */
-#define MADV_NOHUGEPAGE	68		/* Not worth backing with hugepages */
+#define MADV_HUGEPAGE	14		/* Worth backing with hugepages */
+#define MADV_NOHUGEPAGE 15		/* Not worth backing with hugepages */
 
-#define MADV_DONTDUMP   69		/* Explicity exclude from the core dump,
+#define MADV_DONTDUMP   16		/* Explicity exclude from the core dump,
 					   overrides the coredump filter bits */
-#define MADV_DODUMP	70		/* Clear the MADV_NODUMP flag */
+#define MADV_DODUMP	17		/* Clear the MADV_NODUMP flag */
 
-#define MADV_WIPEONFORK 71		/* Zero memory on fork, child only */
-#define MADV_KEEPONFORK 72		/* Undo MADV_WIPEONFORK */
+#define MADV_WIPEONFORK 18		/* Zero memory on fork, child only */
+#define MADV_KEEPONFORK 19		/* Undo MADV_WIPEONFORK */
+
+#define MADV_COLD	20		/* deactivate these pages */
+#define MADV_PAGEOUT	21		/* reclaim these pages */
 
 #define MADV_HWPOISON     100		/* poison a page for testing */
 #define MADV_SOFT_OFFLINE 101		/* soft offline page for testing */
 
 /* compatibility flags */
 #define MAP_FILE	0
-#define MAP_VARIABLE	0
 
 #define PKEY_DISABLE_ACCESS	0x1
 #define PKEY_DISABLE_WRITE	0x2
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/include/uapi/asm/pdc.h
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/include/uapi/asm/pdc.h
@@ -465,6 +465,7 @@
 	unsigned long arch_rev;
 	unsigned long pot_key;
 	unsigned long curr_key;
+	unsigned long width;	/* default of PSW_W bit (1=enabled) */
 };
 
 struct pdc_cache_cf {		/* for PDC_CACHE  (I/D-caches) */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/install.sh
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/install.sh
@@ -39,6 +39,7 @@
 if [ -n "${INSTALLKERNEL}" ]; then
   if [ -x ~/bin/${INSTALLKERNEL} ]; then exec ~/bin/${INSTALLKERNEL} "$@"; fi
   if [ -x /sbin/${INSTALLKERNEL} ]; then exec /sbin/${INSTALLKERNEL} "$@"; fi
+  if [ -x /usr/sbin/${INSTALLKERNEL} ]; then exec /usr/sbin/${INSTALLKERNEL} "$@"; fi
 fi
 
 # Default install
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/kernel/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/kernel/Makefile
@@ -37,5 +37,5 @@
 obj-$(CONFIG_JUMP_LABEL)		+= jump_label.o
 obj-$(CONFIG_KGDB)			+= kgdb.o
 obj-$(CONFIG_KPROBES)			+= kprobes.o
-obj-$(CONFIG_KEXEC)			+= kexec.o relocate_kernel.o
+obj-$(CONFIG_KEXEC_CORE)		+= kexec.o relocate_kernel.o
 obj-$(CONFIG_KEXEC_FILE)		+= kexec_file.o
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/kernel/cache.c
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/kernel/cache.c
@@ -328,6 +328,7 @@
 	struct vm_area_struct *mpnt;
 	unsigned long offset;
 	unsigned long addr, old_addr = 0;
+	unsigned long flags;
 	pgoff_t pgoff;
 
 	if (mapping && !mapping_mapped(mapping)) {
@@ -347,7 +348,7 @@
 	 * declared as MAP_PRIVATE or MAP_SHARED), so we only need
 	 * to flush one address here for them all to become coherent */
 
-	flush_dcache_mmap_lock(mapping);
+	flush_dcache_mmap_lock_irqsave(mapping, flags);
 	vma_interval_tree_foreach(mpnt, &mapping->i_mmap, pgoff, pgoff) {
 		offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
 		addr = mpnt->vm_start + offset;
@@ -370,7 +371,7 @@
 			old_addr = addr;
 		}
 	}
-	flush_dcache_mmap_unlock(mapping);
+	flush_dcache_mmap_unlock_irqrestore(mapping, flags);
 }
 EXPORT_SYMBOL(flush_dcache_page);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/kernel/drivers.c
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/kernel/drivers.c
@@ -520,7 +520,6 @@
 	dev->id.hversion_rev = iodc_data[1] & 0x0f;
 	dev->id.sversion = ((iodc_data[4] & 0x0f) << 16) |
 			(iodc_data[5] << 8) | iodc_data[6];
-	dev->hpa.name = parisc_pathname(dev);
 	dev->hpa.start = hpa;
 	/* This is awkward.  The STI spec says that gfx devices may occupy
 	 * 32MB or 64MB.  Unfortunately, we don't know how to tell whether
@@ -534,10 +533,10 @@
 		dev->hpa.end = hpa + 0xfff;
 	}
 	dev->hpa.flags = IORESOURCE_MEM;
-	name = parisc_hardware_description(&dev->id);
-	if (name) {
-		strlcpy(dev->name, name, sizeof(dev->name));
-	}
+	dev->hpa.name = dev->name;
+	name = parisc_hardware_description(&dev->id) ? : "unknown";
+	snprintf(dev->name, sizeof(dev->name), "%s [%s]",
+		name, parisc_pathname(dev));
 
 	/* Silently fail things like mouse ports which are subsumed within
 	 * the keyboard controller
@@ -810,7 +809,7 @@
 static void walk_native_bus(unsigned long io_io_low, unsigned long io_io_high,
                             struct device *parent);
 
-static void walk_lower_bus(struct parisc_device *dev)
+static void __init walk_lower_bus(struct parisc_device *dev)
 {
 	unsigned long io_io_low, io_io_high;
 
@@ -883,15 +882,13 @@
 			&root);
 }
 
-static void print_parisc_device(struct parisc_device *dev)
+static __init void print_parisc_device(struct parisc_device *dev)
 {
-	char hw_path[64];
-	static int count;
+	static int count __initdata;
 
-	print_pa_hwpath(dev, hw_path);
-	pr_info("%d. %s at 0x%px [%s] { %d, 0x%x, 0x%.3x, 0x%.5x }",
-		++count, dev->name, (void*) dev->hpa.start, hw_path, dev->id.hw_type,
-		dev->id.hversion_rev, dev->id.hversion, dev->id.sversion);
+	pr_info("%d. %s at %pap { type:%d, hv:%#x, sv:%#x, rev:%#x }",
+		++count, dev->name, &(dev->hpa.start), dev->id.hw_type,
+		dev->id.hversion, dev->id.sversion, dev->id.hversion_rev);
 
 	if (dev->num_addrs) {
 		int k;
@@ -927,9 +924,9 @@
 	pr_info("#define PARISC_MODEL \"%s\"\n\n",
 			boot_cpu_data.pdc.sys_model_name);
 
+	#define p ((unsigned long *)&boot_cpu_data.pdc.model)
 	pr_info("#define PARISC_PDC_MODEL 0x%lx, 0x%lx, 0x%lx, "
 		"0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx\n\n",
-	#define p ((unsigned long *)&boot_cpu_data.pdc.model)
 		p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8]);
 	#undef p
 
@@ -1080,7 +1077,7 @@
 
 
 
-static int print_one_device(struct device * dev, void * data)
+static __init int print_one_device(struct device * dev, void * data)
 {
 	struct parisc_device * pdev = to_parisc_device(dev);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/kernel/entry.S
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/kernel/entry.S
@@ -454,7 +454,6 @@
 	nop
 	LDREG		0(\ptp),\pte
 	bb,<,n		\pte,_PAGE_PRESENT_BIT,3f
-	LDCW		0(\tmp),\tmp1
 	b		\fault
 	stw		\spc,0(\tmp)
 99:	ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP)
@@ -464,23 +463,26 @@
 3:
 	.endm
 
-	/* Release pa_tlb_lock lock without reloading lock address. */
-	.macro		tlb_unlock0	spc,tmp,tmp1
+	/* Release pa_tlb_lock lock without reloading lock address.
+	   Note that the values in the register spc are limited to
+	   NR_SPACE_IDS (262144). Thus, the stw instruction always
+	   stores a nonzero value even when register spc is 64 bits.
+	   We use an ordered store to ensure all prior accesses are
+	   performed prior to releasing the lock. */
+	.macro		tlb_unlock0	spc,tmp
 #ifdef CONFIG_SMP
 98:	or,COND(=)	%r0,\spc,%r0
-	LDCW		0(\tmp),\tmp1
-	or,COND(=)	%r0,\spc,%r0
-	stw		\spc,0(\tmp)
+	stw,ma		\spc,0(\tmp)
 99:	ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP)
 #endif
 	.endm
 
 	/* Release pa_tlb_lock lock. */
-	.macro		tlb_unlock1	spc,tmp,tmp1
+	.macro		tlb_unlock1	spc,tmp
 #ifdef CONFIG_SMP
 98:	load_pa_tlb_lock \tmp
 99:	ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP)
-	tlb_unlock0	\spc,\tmp,\tmp1
+	tlb_unlock0	\spc,\tmp
 #endif
 	.endm
 
@@ -509,13 +511,13 @@
 	 * to a CPU TLB 4k PFN (4k => 12 bits to shift) */
 	#define PAGE_ADD_SHIFT		(PAGE_SHIFT-12)
 	#define PAGE_ADD_HUGE_SHIFT	(REAL_HPAGE_SHIFT-12)
+	#define PFN_START_BIT	(63-ASM_PFN_PTE_SHIFT+(63-58)-PAGE_ADD_SHIFT)
 
 	/* Drop prot bits and convert to page addr for iitlbt and idtlbt */
 	.macro		convert_for_tlb_insert20 pte,tmp
 #ifdef CONFIG_HUGETLB_PAGE
 	copy		\pte,\tmp
-	extrd,u		\tmp,(63-ASM_PFN_PTE_SHIFT)+(63-58)+PAGE_ADD_SHIFT,\
-				64-PAGE_SHIFT-PAGE_ADD_SHIFT,\pte
+	extrd,u		\tmp,PFN_START_BIT,PFN_START_BIT+1,\pte
 
 	depdi		_PAGE_SIZE_ENCODING_DEFAULT,63,\
 				(63-58)+PAGE_ADD_SHIFT,\pte
@@ -523,8 +525,7 @@
 	depdi		_HUGE_PAGE_SIZE_ENCODING_DEFAULT,63,\
 				(63-58)+PAGE_ADD_HUGE_SHIFT,\pte
 #else /* Huge pages disabled */
-	extrd,u		\pte,(63-ASM_PFN_PTE_SHIFT)+(63-58)+PAGE_ADD_SHIFT,\
-				64-PAGE_SHIFT-PAGE_ADD_SHIFT,\pte
+	extrd,u		\pte,PFN_START_BIT,PFN_START_BIT+1,\pte
 	depdi		_PAGE_SIZE_ENCODING_DEFAULT,63,\
 				(63-58)+PAGE_ADD_SHIFT,\pte
 #endif
@@ -1077,8 +1078,7 @@
 	STREG           %r16, PT_ISR(%r29)
 	STREG           %r17, PT_IOR(%r29)
 
-#if 0 && defined(CONFIG_64BIT)
-	/* Revisit when we have 64-bit code above 4Gb */
+#if defined(CONFIG_64BIT)
 	b,n		intr_save2
 
 skip_save_ior:
@@ -1086,8 +1086,7 @@
 	 * need to adjust iasq/iaoq here in the same way we adjusted isr/ior
 	 * above.
 	 */
-	extrd,u,*	%r8,PSW_W_BIT,1,%r1
-	cmpib,COND(=),n	1,%r1,intr_save2
+	bb,COND(>=),n	%r8,PSW_W_BIT,intr_save2
 	LDREG		PT_IASQ0(%r29), %r16
 	LDREG		PT_IAOQ0(%r29), %r17
 	/* adjust iasq/iaoq */
@@ -1163,7 +1162,7 @@
 	
 	idtlbt          pte,prot
 
-	tlb_unlock1	spc,t0,t1
+	tlb_unlock1	spc,t0
 	rfir
 	nop
 
@@ -1189,7 +1188,7 @@
 
 	idtlbt          pte,prot
 
-	tlb_unlock1	spc,t0,t1
+	tlb_unlock1	spc,t0
 	rfir
 	nop
 
@@ -1223,7 +1222,7 @@
 
 	mtsp		t1, %sr1	/* Restore sr1 */
 
-	tlb_unlock1	spc,t0,t1
+	tlb_unlock1	spc,t0
 	rfir
 	nop
 
@@ -1256,7 +1255,7 @@
 
 	mtsp		t1, %sr1	/* Restore sr1 */
 
-	tlb_unlock1	spc,t0,t1
+	tlb_unlock1	spc,t0
 	rfir
 	nop
 
@@ -1285,7 +1284,7 @@
 
 	idtlbt          pte,prot
 
-	tlb_unlock1	spc,t0,t1
+	tlb_unlock1	spc,t0
 	rfir
 	nop
 
@@ -1313,7 +1312,7 @@
 	
 	idtlbt		pte,prot
 
-	tlb_unlock1	spc,t0,t1
+	tlb_unlock1	spc,t0
 	rfir
 	nop
 
@@ -1420,7 +1419,7 @@
 	
 	iitlbt          pte,prot
 
-	tlb_unlock1	spc,t0,t1
+	tlb_unlock1	spc,t0
 	rfir
 	nop
 
@@ -1444,7 +1443,7 @@
 
 	iitlbt          pte,prot
 
-	tlb_unlock1	spc,t0,t1
+	tlb_unlock1	spc,t0
 	rfir
 	nop
 
@@ -1478,7 +1477,7 @@
 
 	mtsp		t1, %sr1	/* Restore sr1 */
 
-	tlb_unlock1	spc,t0,t1
+	tlb_unlock1	spc,t0
 	rfir
 	nop
 
@@ -1502,7 +1501,7 @@
 
 	mtsp		t1, %sr1	/* Restore sr1 */
 
-	tlb_unlock1	spc,t0,t1
+	tlb_unlock1	spc,t0
 	rfir
 	nop
 
@@ -1532,7 +1531,7 @@
 
 	iitlbt          pte,prot
 
-	tlb_unlock1	spc,t0,t1
+	tlb_unlock1	spc,t0
 	rfir
 	nop
 
@@ -1552,7 +1551,7 @@
 
 	iitlbt          pte,prot
 
-	tlb_unlock1	spc,t0,t1
+	tlb_unlock1	spc,t0
 	rfir
 	nop
 
@@ -1582,7 +1581,7 @@
 		
 	idtlbt          pte,prot
 
-	tlb_unlock0	spc,t0,t1
+	tlb_unlock0	spc,t0
 	rfir
 	nop
 #else
@@ -1608,7 +1607,7 @@
 
 	mtsp            t1, %sr1     /* Restore sr1 */
 
-	tlb_unlock0	spc,t0,t1
+	tlb_unlock0	spc,t0
 	rfir
 	nop
 
@@ -1628,7 +1627,7 @@
 	
 	idtlbt		pte,prot
 
-	tlb_unlock0	spc,t0,t1
+	tlb_unlock0	spc,t0
 	rfir
 	nop
 #endif
@@ -1839,8 +1838,8 @@
 	LDREG	TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
 
 	/* Are we being ptraced? */
-	ldw	TASK_FLAGS(%r1),%r19
-	ldi	_TIF_SYSCALL_TRACE_MASK,%r2
+	LDREG	TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19
+	ldi	_TIF_SINGLESTEP|_TIF_BLOCKSTEP,%r2
 	and,COND(=)	%r19,%r2,%r0
 	b,n	syscall_restore_rfi
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/kernel/firmware.c
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/kernel/firmware.c
@@ -122,10 +122,10 @@
 #ifdef CONFIG_64BIT
 	if(unlikely(parisc_narrow_firmware)) {
 		if((address & 0xff000000) == 0xf0000000)
-			return 0xf0f0f0f000000000UL | (u32)address;
+			return (0xfffffff0UL << 32) | (u32)address;
 
 		if((address & 0xf0000000) == 0xf0000000)
-			return 0xffffffff00000000UL | (u32)address;
+			return (0xffffffffUL << 32) | (u32)address;
 	}
 #endif
 	return address;
@@ -1229,7 +1229,7 @@
  */
 int pdc_iodc_print(const unsigned char *str, unsigned count)
 {
-	unsigned int i;
+	unsigned int i, found = 0;
 	unsigned long flags;
 
 	for (i = 0; i < count;) {
@@ -1238,6 +1238,7 @@
 			iodc_dbuf[i+0] = '\r';
 			iodc_dbuf[i+1] = '\n';
 			i += 2;
+			found = 1;
 			goto print;
 		default:
 			iodc_dbuf[i] = str[i];
@@ -1254,7 +1255,7 @@
                     __pa(iodc_retbuf), 0, __pa(iodc_dbuf), i, 0);
         spin_unlock_irqrestore(&pdc_lock, flags);
 
-	return i;
+	return i - found;
 }
 
 #if !defined(BOOTLOADER)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/kernel/ftrace.c
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/kernel/ftrace.c
@@ -80,7 +80,7 @@
 #endif
 }
 
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+#if defined(CONFIG_DYNAMIC_FTRACE) && defined(CONFIG_FUNCTION_GRAPH_TRACER)
 int ftrace_enable_ftrace_graph_caller(void)
 {
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/kernel/head.S
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/kernel/head.S
@@ -22,7 +22,7 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 
-	.level	PA_ASM_LEVEL
+	.level	1.1
 
 	__INITDATA
 ENTRY(boot_args)
@@ -69,6 +69,46 @@
 	stw,ma          %arg2,4(%r1)
 	stw,ma          %arg3,4(%r1)
 
+#if defined(CONFIG_PA20)
+	/* check for 64-bit capable CPU as required by current kernel */
+	ldi		32,%r10
+	mtctl		%r10,%cr11
+	.level 2.0
+	mfctl,w		%cr11,%r10
+	.level 1.1
+	comib,<>,n	0,%r10,$cpu_ok
+
+	load32		PA(msg1),%arg0
+	ldi		msg1_end-msg1,%arg1
+$iodc_panic:
+	copy		%arg0, %r10
+	copy		%arg1, %r11
+	load32		PA(init_stack),%sp
+#define MEM_CONS 0x3A0
+	ldw		MEM_CONS+32(%r0),%arg0	// HPA
+	ldi		ENTRY_IO_COUT,%arg1
+	ldw		MEM_CONS+36(%r0),%arg2	// SPA
+	ldw		MEM_CONS+8(%r0),%arg3	// layers
+	load32		PA(__bss_start),%r1
+	stw		%r1,-52(%sp)		// arg4
+	stw		%r0,-56(%sp)		// arg5
+	stw		%r10,-60(%sp)		// arg6 = ptr to text
+	stw		%r11,-64(%sp)		// arg7 = len
+	stw		%r0,-68(%sp)		// arg8
+	load32		PA(.iodc_panic_ret), %rp
+	ldw		MEM_CONS+40(%r0),%r1	// ENTRY_IODC
+	bv,n		(%r1)
+.iodc_panic_ret:
+	b .				/* wait endless with ... */
+	or		%r10,%r10,%r10	/* qemu idle sleep */
+msg1:	.ascii "Can't boot kernel which was built for PA8x00 CPUs on this machine.\r\n"
+msg1_end:
+
+$cpu_ok:
+#endif
+
+	.level	PA_ASM_LEVEL
+
 	/* Initialize startup VM. Just map first 16/32 MB of memory */
 	load32		PA(swapper_pg_dir),%r4
 	mtctl		%r4,%cr24	/* Initialize kernel root pointer */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/kernel/irq.c
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/kernel/irq.c
@@ -376,7 +376,11 @@
 /*
  * IRQ STACK - used for irq handler
  */
+#ifdef CONFIG_64BIT
+#define IRQ_STACK_SIZE      (4096 << 4) /* 64k irq stack size */
+#else
 #define IRQ_STACK_SIZE      (4096 << 3) /* 32k irq stack size */
+#endif
 
 union irq_stack_union {
 	unsigned long stack[IRQ_STACK_SIZE/sizeof(unsigned long)];
@@ -384,7 +388,7 @@
 	volatile unsigned int lock[1];
 };
 
-DEFINE_PER_CPU(union irq_stack_union, irq_stack_union) = {
+static DEFINE_PER_CPU(union irq_stack_union, irq_stack_union) = {
 		.slock = { 1,1,1,1 },
 	};
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/kernel/module.c
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/kernel/module.c
@@ -43,6 +43,7 @@
 #include <linux/elf.h>
 #include <linux/vmalloc.h>
 #include <linux/fs.h>
+#include <linux/ftrace.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/bug.h>
@@ -862,7 +863,7 @@
 	const char *strtab = NULL;
 	const Elf_Shdr *s;
 	char *secstrings;
-	int err, symindex = -1;
+	int symindex = -1;
 	Elf_Sym *newptr, *oldptr;
 	Elf_Shdr *symhdr = NULL;
 #ifdef DEBUG
@@ -946,11 +947,13 @@
 			/* patch .altinstructions */
 			apply_alternatives(aseg, aseg + s->sh_size, me->name);
 
+#ifdef CONFIG_DYNAMIC_FTRACE
 		/* For 32 bit kernels we're compiling modules with
 		 * -ffunction-sections so we must relocate the addresses in the
-		 *__mcount_loc section.
+		 *  ftrace callsite section.
 		 */
-		if (symindex != -1 && !strcmp(secname, "__mcount_loc")) {
+		if (symindex != -1 && !strcmp(secname, FTRACE_CALLSITE_SECTION)) {
+			int err;
 			if (s->sh_type == SHT_REL)
 				err = apply_relocate((Elf_Shdr *)sechdrs,
 							strtab, symindex,
@@ -962,6 +965,7 @@
 			if (err)
 				return err;
 		}
+#endif
 	}
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/kernel/parisc_ksyms.c
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/kernel/parisc_ksyms.c
@@ -17,14 +17,11 @@
 
 #include <linux/string.h>
 EXPORT_SYMBOL(memset);
-EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strcpy);
-EXPORT_SYMBOL(strncpy);
-EXPORT_SYMBOL(strcat);
 
 #include <linux/atomic.h>
 EXPORT_SYMBOL(__xchg8);
 EXPORT_SYMBOL(__xchg32);
+EXPORT_SYMBOL(__cmpxchg_u8);
 EXPORT_SYMBOL(__cmpxchg_u32);
 EXPORT_SYMBOL(__cmpxchg_u64);
 #ifdef CONFIG_SMP
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/kernel/patch.c
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/kernel/patch.c
@@ -40,10 +40,7 @@
 
 	*need_unmap = 1;
 	set_fixmap(fixmap, page_to_phys(page));
-	if (flags)
-		raw_spin_lock_irqsave(&patch_lock, *flags);
-	else
-		__acquire(&patch_lock);
+	raw_spin_lock_irqsave(&patch_lock, *flags);
 
 	return (void *) (__fix_to_virt(fixmap) + (uintaddr & ~PAGE_MASK));
 }
@@ -52,10 +49,7 @@
 {
 	clear_fixmap(fixmap);
 
-	if (flags)
-		raw_spin_unlock_irqrestore(&patch_lock, *flags);
-	else
-		__release(&patch_lock);
+	raw_spin_unlock_irqrestore(&patch_lock, *flags);
 }
 
 void __kprobes __patch_text_multiple(void *addr, u32 *insn, unsigned int len)
@@ -67,8 +61,9 @@
 	int mapped;
 
 	/* Make sure we don't have any aliases in cache */
-	flush_kernel_vmap_range(addr, len);
-	flush_icache_range(start, end);
+	flush_kernel_dcache_range_asm(start, end);
+	flush_kernel_icache_range_asm(start, end);
+	flush_tlb_kernel_range(start, end);
 
 	p = fixmap = patch_map(addr, FIX_TEXT_POKE0, &flags, &mapped);
 
@@ -81,8 +76,10 @@
 			 * We're crossing a page boundary, so
 			 * need to remap
 			 */
-			flush_kernel_vmap_range((void *)fixmap,
-						(p-fixmap) * sizeof(*p));
+			flush_kernel_dcache_range_asm((unsigned long)fixmap,
+						      (unsigned long)p);
+			flush_tlb_kernel_range((unsigned long)fixmap,
+					       (unsigned long)p);
 			if (mapped)
 				patch_unmap(FIX_TEXT_POKE0, &flags);
 			p = fixmap = patch_map(addr, FIX_TEXT_POKE0, &flags,
@@ -90,10 +87,10 @@
 		}
 	}
 
-	flush_kernel_vmap_range((void *)fixmap, (p-fixmap) * sizeof(*p));
+	flush_kernel_dcache_range_asm((unsigned long)fixmap, (unsigned long)p);
+	flush_tlb_kernel_range((unsigned long)fixmap, (unsigned long)p);
 	if (mapped)
 		patch_unmap(FIX_TEXT_POKE0, &flags);
-	flush_icache_range(start, end);
 }
 
 void __kprobes __patch_text(void *addr, u32 insn)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/kernel/pci-dma.c
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/kernel/pci-dma.c
@@ -439,16 +439,32 @@
 	free_pages((unsigned long)__va(dma_handle), order);
 }
 
-void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr,
-		size_t size, enum dma_data_direction dir)
+void arch_sync_dma_for_device(phys_addr_t paddr, size_t size,
+		enum dma_data_direction dir)
 {
+	/*
+	 * fdc: The data cache line is written back to memory, if and only if
+	 * it is dirty, and then invalidated from the data cache.
+	 */
 	flush_kernel_dcache_range((unsigned long)phys_to_virt(paddr), size);
 }
 
-void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr,
-		size_t size, enum dma_data_direction dir)
+void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size,
+		enum dma_data_direction dir)
 {
-	flush_kernel_dcache_range((unsigned long)phys_to_virt(paddr), size);
+	unsigned long addr = (unsigned long) phys_to_virt(paddr);
+
+	switch (dir) {
+	case DMA_TO_DEVICE:
+	case DMA_BIDIRECTIONAL:
+		flush_kernel_dcache_range(addr, size);
+		return;
+	case DMA_FROM_DEVICE:
+		purge_kernel_dcache_range_asm(addr, addr + size);
+		return;
+	default:
+		BUG();
+	}
 }
 
 void arch_dma_cache_sync(struct device *dev, void *vaddr, size_t size,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/kernel/process.c
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/kernel/process.c
@@ -124,13 +124,18 @@
 	/* It seems we have no way to power the system off via
 	 * software. The user has to press the button himself. */
 
-	printk(KERN_EMERG "System shut down completed.\n"
-	       "Please power this system off now.");
+	printk("Power off or press RETURN to reboot.\n");
 
 	/* prevent soft lockup/stalled CPU messages for endless loop. */
 	rcu_sysrq_start();
 	lockup_detector_soft_poweroff();
-	for (;;);
+	while (1) {
+		/* reboot if user presses RETURN key */
+		if (pdc_iodc_getc() == 13) {
+			printk("Rebooting...\n");
+			machine_restart(NULL);
+		}
+	}
 }
 
 void (*pm_power_off)(void);
@@ -208,8 +213,8 @@
  * Copy architecture-specific thread state
  */
 int
-copy_thread(unsigned long clone_flags, unsigned long usp,
-	    unsigned long kthread_arg, struct task_struct *p)
+copy_thread_tls(unsigned long clone_flags, unsigned long usp,
+	    unsigned long kthread_arg, struct task_struct *p, unsigned long tls)
 {
 	struct pt_regs *cregs = &(p->thread.regs);
 	void *stack = task_stack_page(p);
@@ -254,9 +259,9 @@
 		cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE;
 		cregs->kpc = (unsigned long) &child_return;
 
-		/* Setup thread TLS area from the 4th parameter in clone */
+		/* Setup thread TLS area */
 		if (clone_flags & CLONE_SETTLS)
-			cregs->cr27 = cregs->gr[23];
+			cregs->cr27 = tls;
 	}
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/kernel/processor.c
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/kernel/processor.c
@@ -163,7 +163,6 @@
 	if (cpuid)
 		memset(p, 0, sizeof(struct cpuinfo_parisc));
 
-	p->loops_per_jiffy = loops_per_jiffy;
 	p->dev = dev;		/* Save IODC data in case we need it */
 	p->hpa = dev->hpa.start;	/* save CPU hpa */
 	p->cpuid = cpuid;	/* save CPU id */
@@ -373,10 +372,18 @@
 show_cpuinfo (struct seq_file *m, void *v)
 {
 	unsigned long cpu;
+	char cpu_name[60], *p;
+
+	/* strip PA path from CPU name to not confuse lscpu */
+	strlcpy(cpu_name, per_cpu(cpu_data, 0).dev->name, sizeof(cpu_name));
+	p = strrchr(cpu_name, '[');
+	if (p)
+		*(--p) = 0;
 
 	for_each_online_cpu(cpu) {
-		const struct cpuinfo_parisc *cpuinfo = &per_cpu(cpu_data, cpu);
 #ifdef CONFIG_SMP
+		const struct cpuinfo_parisc *cpuinfo = &per_cpu(cpu_data, cpu);
+
 		if (0 == cpuinfo->hpa)
 			continue;
 #endif
@@ -419,11 +426,9 @@
 		}
 		seq_printf(m, " (0x%02lx)\n", boot_cpu_data.pdc.capabilities);
 
-		seq_printf(m, "model\t\t: %s\n"
-				"model name\t: %s\n",
+		seq_printf(m, "model\t\t: %s - %s\n",
 				 boot_cpu_data.pdc.sys_model_name,
-				 cpuinfo->dev ?
-				 cpuinfo->dev->name : "Unknown");
+				 cpu_name);
 
 		seq_printf(m, "hversion\t: 0x%08x\n"
 			        "sversion\t: 0x%08x\n",
@@ -434,8 +439,8 @@
 		show_cache_info(m);
 
 		seq_printf(m, "bogomips\t: %lu.%02lu\n",
-			     cpuinfo->loops_per_jiffy / (500000 / HZ),
-			     (cpuinfo->loops_per_jiffy / (5000 / HZ)) % 100);
+			     loops_per_jiffy / (500000 / HZ),
+			     loops_per_jiffy / (5000 / HZ) % 100);
 
 		seq_printf(m, "software id\t: %ld\n\n",
 				boot_cpu_data.pdc.model.sw_id);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/kernel/ptrace.c
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/kernel/ptrace.c
@@ -128,6 +128,12 @@
 	unsigned long tmp;
 	long ret = -EIO;
 
+	unsigned long user_regs_struct_size = sizeof(struct user_regs_struct);
+#ifdef CONFIG_64BIT
+	if (is_compat_task())
+		user_regs_struct_size /= 2;
+#endif
+
 	switch (request) {
 
 	/* Read the word at location addr in the USER area.  For ptraced
@@ -183,14 +189,14 @@
 		return copy_regset_to_user(child,
 					   task_user_regset_view(current),
 					   REGSET_GENERAL,
-					   0, sizeof(struct user_regs_struct),
+					   0, user_regs_struct_size,
 					   datap);
 
 	case PTRACE_SETREGS:	/* Set all gp regs in the child. */
 		return copy_regset_from_user(child,
 					     task_user_regset_view(current),
 					     REGSET_GENERAL,
-					     0, sizeof(struct user_regs_struct),
+					     0, user_regs_struct_size,
 					     datap);
 
 	case PTRACE_GETFPREGS:	/* Get the child FPU state. */
@@ -304,6 +310,11 @@
 			}
 		}
 		break;
+	case PTRACE_GETREGS:
+	case PTRACE_SETREGS:
+	case PTRACE_GETFPREGS:
+	case PTRACE_SETFPREGS:
+		return arch_ptrace(child, request, addr, data);
 
 	default:
 		ret = compat_ptrace_request(child, request, addr, data);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/kernel/real2.S
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/kernel/real2.S
@@ -248,9 +248,6 @@
 	/* save fn */
 	copy	%arg2, %r31
 
-	/* set up the new ap */
-	ldo	64(%arg1), %r29
-
 	/* load up the arg registers from the saved arg area */
 	/* 32-bit calling convention passes first 4 args in registers */
 	ldd	0*REG_SZ(%arg1), %arg0		/* note overwriting arg0 */
@@ -262,7 +259,9 @@
 	ldd	7*REG_SZ(%arg1), %r19
 	ldd	1*REG_SZ(%arg1), %arg1		/* do this one last! */
 
+	/* set up real-mode stack and real-mode ap */
 	tophys_r1 %sp
+	ldo	-16(%sp), %r29			/* Reference param save area */
 
 	b,l	rfi_virt2real,%r2
 	nop
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/kernel/signal.c
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/kernel/signal.c
@@ -238,6 +238,12 @@
 #endif
 	
 	usp = (regs->gr[30] & ~(0x01UL));
+#ifdef CONFIG_64BIT
+	if (is_compat_task()) {
+		/* The gcc alloca implementation leaves garbage in the upper 32 bits of sp */
+		usp = (compat_uint_t)usp;
+	}
+#endif
 	/*FIXME: frame_size parameter is unused, remove it. */
 	frame = get_sigframe(&ksig->ka, usp, sizeof(*frame));
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/kernel/smp.c
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/kernel/smp.c
@@ -29,6 +29,7 @@
 #include <linux/bitops.h>
 #include <linux/ftrace.h>
 #include <linux/cpu.h>
+#include <linux/kgdb.h>
 
 #include <linux/atomic.h>
 #include <asm/current.h>
@@ -71,7 +72,10 @@
 	IPI_CALL_FUNC,
 	IPI_CPU_START,
 	IPI_CPU_STOP,
-	IPI_CPU_TEST
+	IPI_CPU_TEST,
+#ifdef CONFIG_KGDB
+	IPI_ENTER_KGDB,
+#endif
 };
 
 
@@ -169,7 +173,12 @@
 			case IPI_CPU_TEST:
 				smp_debug(100, KERN_DEBUG "CPU%d is alive!\n", this_cpu);
 				break;
-
+#ifdef CONFIG_KGDB
+			case IPI_ENTER_KGDB:
+				smp_debug(100, KERN_DEBUG "CPU%d ENTER_KGDB\n", this_cpu);
+				kgdb_nmicallback(raw_smp_processor_id(), get_irq_regs());
+				break;
+#endif
 			default:
 				printk(KERN_CRIT "Unknown IPI num on CPU%d: %lu\n",
 					this_cpu, which);
@@ -225,6 +234,12 @@
 	}
 }
 
+#ifdef CONFIG_KGDB
+void kgdb_roundup_cpus(void)
+{
+	send_IPI_allbutself(IPI_ENTER_KGDB);
+}
+#endif
 
 inline void 
 smp_send_stop(void)	{ send_IPI_allbutself(IPI_CPU_STOP); }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/kernel/sys_parisc.c
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/kernel/sys_parisc.c
@@ -373,3 +373,30 @@
 
 	return err;
 }
+
+/*
+ * madvise() wrapper
+ *
+ * Up to kernel v6.1 parisc has different values than all other
+ * platforms for the MADV_xxx flags listed below.
+ * To keep binary compatibility with existing userspace programs
+ * translate the former values to the new values.
+ *
+ * XXX: Remove this wrapper in year 2025 (or later)
+ */
+
+asmlinkage notrace long parisc_madvise(unsigned long start, size_t len_in, int behavior)
+{
+	switch (behavior) {
+	case 65: behavior = MADV_MERGEABLE;	break;
+	case 66: behavior = MADV_UNMERGEABLE;	break;
+	case 67: behavior = MADV_HUGEPAGE;	break;
+	case 68: behavior = MADV_NOHUGEPAGE;	break;
+	case 69: behavior = MADV_DONTDUMP;	break;
+	case 70: behavior = MADV_DODUMP;	break;
+	case 71: behavior = MADV_WIPEONFORK;	break;
+	case 72: behavior = MADV_KEEPONFORK;	break;
+	}
+
+	return sys_madvise(start, len_in, behavior);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/kernel/syscall.S
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/kernel/syscall.S
@@ -217,10 +217,10 @@
 
 #ifdef CONFIG_64BIT
 	ldil	L%sys_call_table, %r1
-	or,=	%r2,%r2,%r2
-	addil	L%(sys_call_table64-sys_call_table), %r1
+	or,ev	%r2,%r2,%r2
+	ldil	L%sys_call_table64, %r1
 	ldo	R%sys_call_table(%r1), %r19
-	or,=	%r2,%r2,%r2
+	or,ev	%r2,%r2,%r2
 	ldo	R%sys_call_table64(%r1), %r19
 #else
 	load32	sys_call_table, %r19
@@ -355,10 +355,10 @@
 	extrd,u	%r19,63,1,%r2			/* W hidden in bottom bit */
 
 	ldil	L%sys_call_table, %r1
-	or,=	%r2,%r2,%r2
-	addil	L%(sys_call_table64-sys_call_table), %r1
+	or,ev	%r2,%r2,%r2
+	ldil	L%sys_call_table64, %r1
 	ldo	R%sys_call_table(%r1), %r19
-	or,=	%r2,%r2,%r2
+	or,ev	%r2,%r2,%r2
 	ldo	R%sys_call_table64(%r1), %r19
 #else
 	load32	sys_call_table, %r19
@@ -478,7 +478,7 @@
 	extrd,u	%r1,PSW_W_BIT,1,%r1
 	/* sp must be aligned on 4, so deposit the W bit setting into
 	 * the bottom of sp temporarily */
-	or,ev	%r1,%r30,%r30
+	or,od	%r1,%r30,%r30
 
 	/* Clip LWS number to a 32-bit value for 32-bit processes */
 	depdi	0, 31, 32, %r20
@@ -640,11 +640,7 @@
 	sub,<>	%r28, %r25, %r0
 2:	stw	%r24, 0(%r26)
 	/* Free lock */
-#ifdef CONFIG_SMP
-98:	LDCW	0(%sr2,%r20), %r1			/* Barrier */
-99:	ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP)
-#endif
-	stw	%r20, 0(%sr2,%r20)
+	stw,ma	%r20, 0(%sr2,%r20)
 #if ENABLE_LWS_DEBUG
 	/* Clear thread register indicator */
 	stw	%r0, 4(%sr2,%r20)
@@ -658,11 +654,7 @@
 3:		
 	/* Error occurred on load or store */
 	/* Free lock */
-#ifdef CONFIG_SMP
-98:	LDCW	0(%sr2,%r20), %r1			/* Barrier */
-99:	ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP)
-#endif
-	stw	%r20, 0(%sr2,%r20)
+	stw,ma	%r20, 0(%sr2,%r20)
 #if ENABLE_LWS_DEBUG
 	stw	%r0, 4(%sr2,%r20)
 #endif
@@ -863,11 +855,7 @@
 
 cas2_end:
 	/* Free lock */
-#ifdef CONFIG_SMP
-98:	LDCW	0(%sr2,%r20), %r1			/* Barrier */
-99:	ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP)
-#endif
-	stw	%r20, 0(%sr2,%r20)
+	stw,ma	%r20, 0(%sr2,%r20)
 	/* Enable interrupts */
 	ssm	PSW_SM_I, %r0
 	/* Return to userspace, set no error */
@@ -877,11 +865,7 @@
 22:
 	/* Error occurred on load or store */
 	/* Free lock */
-#ifdef CONFIG_SMP
-98:	LDCW	0(%sr2,%r20), %r1			/* Barrier */
-99:	ALTERNATIVE(98b, 99b, ALT_COND_NO_SMP, INSN_NOP)
-#endif
-	stw	%r20, 0(%sr2,%r20)
+	stw,ma	%r20, 0(%sr2,%r20)
 	ssm	PSW_SM_I, %r0
 	ldo	1(%r0),%r28
 	b	lws_exit
@@ -947,6 +931,8 @@
 END(sys_call_table)
 
 #ifdef CONFIG_64BIT
+#undef __SYSCALL_WITH_COMPAT
+#define __SYSCALL_WITH_COMPAT(nr, native, compat)	__SYSCALL(nr, native)
 	.align 8
 ENTRY(sys_call_table64)
 #include <asm/syscall_table_64.h>    /* 64-bit native syscalls */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/kernel/syscalls/syscall.tbl
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/kernel/syscalls/syscall.tbl
@@ -108,7 +108,7 @@
 95	common	fchown			sys_fchown
 96	common	getpriority		sys_getpriority
 97	common	setpriority		sys_setpriority
-98	common	recv			sys_recv
+98	common	recv			sys_recv			compat_sys_recv
 99	common	statfs			sys_statfs			compat_sys_statfs
 100	common	fstatfs			sys_fstatfs			compat_sys_fstatfs
 101	common	stat64			sys_stat64
@@ -131,11 +131,11 @@
 116	common	sysinfo			sys_sysinfo			compat_sys_sysinfo
 117	common	shutdown		sys_shutdown
 118	common	fsync			sys_fsync
-119	common	madvise			sys_madvise
+119	common	madvise			parisc_madvise
 120	common	clone			sys_clone_wrapper
 121	common	setdomainname		sys_setdomainname
 122	common	sendfile		sys_sendfile			compat_sys_sendfile
-123	common	recvfrom		sys_recvfrom
+123	common	recvfrom		sys_recvfrom			compat_sys_recvfrom
 124	32	adjtimex		sys_adjtimex_time32
 124	64	adjtimex		sys_adjtimex
 125	common	mprotect		sys_mprotect
@@ -413,7 +413,7 @@
 412	32	utimensat_time64		sys_utimensat			sys_utimensat
 413	32	pselect6_time64			sys_pselect6			compat_sys_pselect6_time64
 414	32	ppoll_time64			sys_ppoll			compat_sys_ppoll_time64
-416	32	io_pgetevents_time64		sys_io_pgetevents		sys_io_pgetevents
+416	32	io_pgetevents_time64		sys_io_pgetevents		compat_sys_io_pgetevents_time64
 417	32	recvmmsg_time64			sys_recvmmsg			compat_sys_recvmmsg_time64
 418	32	mq_timedsend_time64		sys_mq_timedsend		sys_mq_timedsend
 419	32	mq_timedreceive_time64		sys_mq_timedreceive		sys_mq_timedreceive
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/kernel/time.c
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/kernel/time.c
@@ -245,27 +245,13 @@
 static int __init init_cr16_clocksource(void)
 {
 	/*
-	 * The cr16 interval timers are not syncronized across CPUs on
-	 * different sockets, so mark them unstable and lower rating on
-	 * multi-socket SMP systems.
+	 * The cr16 interval timers are not syncronized across CPUs, even if
+	 * they share the same socket.
 	 */
 	if (num_online_cpus() > 1 && !running_on_qemu) {
-		int cpu;
-		unsigned long cpu0_loc;
-		cpu0_loc = per_cpu(cpu_data, 0).cpu_loc;
-
-		for_each_online_cpu(cpu) {
-			if (cpu == 0)
-				continue;
-			if ((cpu0_loc != 0) &&
-			    (cpu0_loc == per_cpu(cpu_data, cpu).cpu_loc))
-				continue;
-
-			clocksource_cr16.name = "cr16_unstable";
-			clocksource_cr16.flags = CLOCK_SOURCE_UNSTABLE;
-			clocksource_cr16.rating = 0;
-			break;
-		}
+		clocksource_cr16.name = "cr16_unstable";
+		clocksource_cr16.flags = CLOCK_SOURCE_UNSTABLE;
+		clocksource_cr16.rating = 0;
 	}
 
 	/* XXX: We may want to mark sched_clock stable here if cr16 clocks are
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/kernel/traps.c
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/kernel/traps.c
@@ -268,7 +268,7 @@
 		panic("Fatal exception");
 
 	oops_exit();
-	do_exit(SIGSEGV);
+	make_task_dead(SIGSEGV);
 }
 
 /* gdb uses break 4,8 */
@@ -305,8 +305,8 @@
 #endif
 
 #ifdef CONFIG_KGDB
-	if (unlikely(iir == PARISC_KGDB_COMPILED_BREAK_INSN ||
-		iir == PARISC_KGDB_BREAK_INSN)) {
+	if (unlikely((iir == PARISC_KGDB_COMPILED_BREAK_INSN ||
+		iir == PARISC_KGDB_BREAK_INSN)) && !user_mode(regs)) {
 		kgdb_handle_exception(9, SIGTRAP, 0, regs);
 		return;
 	}
@@ -783,7 +783,7 @@
 	     * unless pagefault_disable() was called before.
 	     */
 
-	    if (fault_space == 0 && !faulthandler_disabled())
+	    if (faulthandler_disabled() || fault_space == 0)
 	    {
 		/* Clean up and return if in exception table. */
 		if (fixup_exception(regs))
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/kernel/unaligned.c
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/kernel/unaligned.c
@@ -107,7 +107,7 @@
 #define R1(i) (((i)>>21)&0x1f)
 #define R2(i) (((i)>>16)&0x1f)
 #define R3(i) ((i)&0x1f)
-#define FR3(i) ((((i)<<1)&0x1f)|(((i)>>6)&1))
+#define FR3(i) ((((i)&0x1f)<<1)|(((i)>>6)&1))
 #define IM(i,n) (((i)>>1&((1<<(n-1))-1))|((i)&1?((0-1L)<<(n-1)):0))
 #define IM5_2(i) IM((i)>>16,5)
 #define IM5_3(i) IM((i),5)
@@ -340,7 +340,7 @@
 	: "r" (val), "r" (regs->ior), "r" (regs->isr)
 	: "r19", "r20", "r21", "r22", "r1", FIXUP_BRANCH_CLOBBER );
 
-	return 0;
+	return ret;
 }
 static int emulate_std(struct pt_regs *regs, int frreg, int flop)
 {
@@ -397,7 +397,7 @@
 	__asm__ __volatile__ (
 "	mtsp	%4, %%sr1\n"
 "	zdep	%2, 29, 2, %%r19\n"
-"	dep	%%r0, 31, 2, %2\n"
+"	dep	%%r0, 31, 2, %3\n"
 "	mtsar	%%r19\n"
 "	zvdepi	-2, 32, %%r19\n"
 "1:	ldw	0(%%sr1,%3),%%r20\n"
@@ -409,7 +409,7 @@
 "	andcm	%%r21, %%r19, %%r21\n"
 "	or	%1, %%r20, %1\n"
 "	or	%2, %%r21, %2\n"
-"3:	stw	%1,0(%%sr1,%1)\n"
+"3:	stw	%1,0(%%sr1,%3)\n"
 "4:	stw	%%r1,4(%%sr1,%3)\n"
 "5:	stw	%2,8(%%sr1,%3)\n"
 "	copy	%%r0, %0\n"
@@ -596,7 +596,6 @@
 		ret = ERR_NOTHANDLED;	/* "undefined", but lets kill them. */
 		break;
 	}
-#ifdef CONFIG_PA20
 	switch (regs->iir & OPCODE2_MASK)
 	{
 	case OPCODE_FLDD_L:
@@ -607,22 +606,23 @@
 		flop=1;
 		ret = emulate_std(regs, R2(regs->iir),1);
 		break;
+#ifdef CONFIG_PA20
 	case OPCODE_LDD_L:
 		ret = emulate_ldd(regs, R2(regs->iir),0);
 		break;
 	case OPCODE_STD_L:
 		ret = emulate_std(regs, R2(regs->iir),0);
 		break;
-	}
 #endif
+	}
 	switch (regs->iir & OPCODE3_MASK)
 	{
 	case OPCODE_FLDW_L:
 		flop=1;
-		ret = emulate_ldw(regs, R2(regs->iir),0);
+		ret = emulate_ldw(regs, R2(regs->iir), 1);
 		break;
 	case OPCODE_LDW_M:
-		ret = emulate_ldw(regs, R2(regs->iir),1);
+		ret = emulate_ldw(regs, R2(regs->iir), 0);
 		break;
 
 	case OPCODE_FSTW_L:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/kernel/unwind.c
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/kernel/unwind.c
@@ -21,6 +21,8 @@
 #include <asm/ptrace.h>
 
 #include <asm/unwind.h>
+#include <asm/switch_to.h>
+#include <asm/sections.h>
 
 /* #define DEBUG 1 */
 #ifdef DEBUG
@@ -203,6 +205,11 @@
 	return 0;
 }
 
+static bool pc_is_kernel_fn(unsigned long pc, void *fn)
+{
+	return (unsigned long)dereference_kernel_function_descriptor(fn) == pc;
+}
+
 static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int frame_size)
 {
 	/*
@@ -221,7 +228,7 @@
 	extern void * const _call_on_stack;
 #endif /* CONFIG_IRQSTACKS */
 
-	if (pc == (unsigned long) &handle_interruption) {
+	if (pc_is_kernel_fn(pc, handle_interruption)) {
 		struct pt_regs *regs = (struct pt_regs *)(info->sp - frame_size - PT_SZ_ALGN);
 		dbg("Unwinding through handle_interruption()\n");
 		info->prev_sp = regs->gr[30];
@@ -229,13 +236,13 @@
 		return 1;
 	}
 
-	if (pc == (unsigned long) &ret_from_kernel_thread ||
-	    pc == (unsigned long) &syscall_exit) {
+	if (pc_is_kernel_fn(pc, ret_from_kernel_thread) ||
+	    pc_is_kernel_fn(pc, syscall_exit)) {
 		info->prev_sp = info->prev_ip = 0;
 		return 1;
 	}
 
-	if (pc == (unsigned long) &intr_return) {
+	if (pc_is_kernel_fn(pc, intr_return)) {
 		struct pt_regs *regs;
 
 		dbg("Found intr_return()\n");
@@ -246,20 +253,20 @@
 		return 1;
 	}
 
-	if (pc == (unsigned long) &_switch_to_ret) {
+	if (pc_is_kernel_fn(pc, _switch_to) ||
+	    pc_is_kernel_fn(pc, _switch_to_ret)) {
 		info->prev_sp = info->sp - CALLEE_SAVE_FRAME_SIZE;
 		info->prev_ip = *(unsigned long *)(info->prev_sp - RP_OFFSET);
 		return 1;
 	}
 
 #ifdef CONFIG_IRQSTACKS
-	if (pc == (unsigned long) &_call_on_stack) {
+	if (pc_is_kernel_fn(pc, _call_on_stack)) {
 		info->prev_sp = *(unsigned long *)(info->sp - FRAME_SIZE - REG_SZ);
 		info->prev_ip = *(unsigned long *)(info->sp - FRAME_SIZE - RP_OFFSET);
 		return 1;
 	}
 #endif
-
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/lib/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/lib/Makefile
@@ -3,7 +3,7 @@
 # Makefile for parisc-specific library files
 #
 
-lib-y	:= lusercopy.o bitops.o checksum.o io.o memcpy.o \
-	   ucmpdi2.o delay.o string.o
+lib-y	:= lusercopy.o bitops.o checksum.o io.o memset.o memcpy.o \
+	   ucmpdi2.o delay.o
 
 obj-y	:= iomap.o
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/lib/bitops.c
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/lib/bitops.c
@@ -79,3 +79,15 @@
 	_atomic_spin_unlock_irqrestore(ptr, flags);
 	return (unsigned long)prev;
 }
+
+u8 __cmpxchg_u8(volatile u8 *ptr, u8 old, u8 new)
+{
+	unsigned long flags;
+	u8 prev;
+
+	_atomic_spin_lock_irqsave(ptr, flags);
+	if ((prev = *ptr) == old)
+		*ptr = new;
+	_atomic_spin_unlock_irqrestore(ptr, flags);
+	return prev;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/lib/memset.c
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/lib/memset.c
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#include <linux/types.h>
+#include <asm/string.h>
+
+#define OPSIZ (BITS_PER_LONG/8)
+typedef unsigned long op_t;
+
+void *
+memset (void *dstpp, int sc, size_t len)
+{
+  unsigned int c = sc;
+  long int dstp = (long int) dstpp;
+
+  if (len >= 8)
+    {
+      size_t xlen;
+      op_t cccc;
+
+      cccc = (unsigned char) c;
+      cccc |= cccc << 8;
+      cccc |= cccc << 16;
+      if (OPSIZ > 4)
+	/* Do the shift in two steps to avoid warning if long has 32 bits.  */
+	cccc |= (cccc << 16) << 16;
+
+      /* There are at least some bytes to set.
+	 No need to test for LEN == 0 in this alignment loop.  */
+      while (dstp % OPSIZ != 0)
+	{
+	  ((unsigned char *) dstp)[0] = c;
+	  dstp += 1;
+	  len -= 1;
+	}
+
+      /* Write 8 `op_t' per iteration until less than 8 `op_t' remain.  */
+      xlen = len / (OPSIZ * 8);
+      while (xlen > 0)
+	{
+	  ((op_t *) dstp)[0] = cccc;
+	  ((op_t *) dstp)[1] = cccc;
+	  ((op_t *) dstp)[2] = cccc;
+	  ((op_t *) dstp)[3] = cccc;
+	  ((op_t *) dstp)[4] = cccc;
+	  ((op_t *) dstp)[5] = cccc;
+	  ((op_t *) dstp)[6] = cccc;
+	  ((op_t *) dstp)[7] = cccc;
+	  dstp += 8 * OPSIZ;
+	  xlen -= 1;
+	}
+      len %= OPSIZ * 8;
+
+      /* Write 1 `op_t' per iteration until less than OPSIZ bytes remain.  */
+      xlen = len / OPSIZ;
+      while (xlen > 0)
+	{
+	  ((op_t *) dstp)[0] = cccc;
+	  dstp += OPSIZ;
+	  xlen -= 1;
+	}
+      len %= OPSIZ;
+    }
+
+  /* Write the last few bytes.  */
+  while (len > 0)
+    {
+      ((unsigned char *) dstp)[0] = c;
+      dstp += 1;
+      len -= 1;
+    }
+
+  return dstpp;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/math-emu/fpudispatch.c
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/math-emu/fpudispatch.c
@@ -310,12 +310,15 @@
 					r1 &= ~3;
 					fpregs[t+3] = fpregs[r1+3];
 					fpregs[t+2] = fpregs[r1+2];
+					fallthrough;
 				    case 1: /* double */
 					fpregs[t+1] = fpregs[r1+1];
+					fallthrough;
 				    case 0: /* single */
 					fpregs[t] = fpregs[r1];
 					return(NOEXCEPTION);
 				}
+				BUG();
 			case 3: /* FABS */
 				switch (fmt) {
 				    case 2: /* illegal */
@@ -325,13 +328,16 @@
 					r1 &= ~3;
 					fpregs[t+3] = fpregs[r1+3];
 					fpregs[t+2] = fpregs[r1+2];
+					fallthrough;
 				    case 1: /* double */
 					fpregs[t+1] = fpregs[r1+1];
+					fallthrough;
 				    case 0: /* single */
 					/* copy and clear sign bit */
 					fpregs[t] = fpregs[r1] & 0x7fffffff;
 					return(NOEXCEPTION);
 				}
+				BUG();
 			case 6: /* FNEG */
 				switch (fmt) {
 				    case 2: /* illegal */
@@ -341,13 +347,16 @@
 					r1 &= ~3;
 					fpregs[t+3] = fpregs[r1+3];
 					fpregs[t+2] = fpregs[r1+2];
+					fallthrough;
 				    case 1: /* double */
 					fpregs[t+1] = fpregs[r1+1];
+					fallthrough;
 				    case 0: /* single */
 					/* copy and invert sign bit */
 					fpregs[t] = fpregs[r1] ^ 0x80000000;
 					return(NOEXCEPTION);
 				}
+				BUG();
 			case 7: /* FNEGABS */
 				switch (fmt) {
 				    case 2: /* illegal */
@@ -357,13 +366,16 @@
 					r1 &= ~3;
 					fpregs[t+3] = fpregs[r1+3];
 					fpregs[t+2] = fpregs[r1+2];
+					fallthrough;
 				    case 1: /* double */
 					fpregs[t+1] = fpregs[r1+1];
+					fallthrough;
 				    case 0: /* single */
 					/* copy and set sign bit */
 					fpregs[t] = fpregs[r1] | 0x80000000;
 					return(NOEXCEPTION);
 				}
+				BUG();
 			case 4: /* FSQRT */
 				switch (fmt) {
 				    case 0:
@@ -376,6 +388,7 @@
 				    case 3: /* quad not implemented */
 					return(MAJOR_0C_EXCP);
 				}
+				BUG();
 			case 5: /* FRND */
 				switch (fmt) {
 				    case 0:
@@ -389,7 +402,7 @@
 					return(MAJOR_0C_EXCP);
 				}
 		} /* end of switch (subop) */
-
+		BUG();
 	case 1: /* class 1 */
 		df = extru(ir,fpdfpos,2); /* get dest format */
 		if ((df & 2) || (fmt & 2)) {
@@ -419,6 +432,7 @@
 				    case 3: /* dbl/dbl */
 					return(MAJOR_0C_EXCP);
 				}
+				BUG();
 			case 1: /* FCNVXF */
 				switch(fmt) {
 				    case 0: /* sgl/sgl */
@@ -434,6 +448,7 @@
 					return(dbl_to_dbl_fcnvxf(&fpregs[r1],0,
 						&fpregs[t],status));
 				}
+				BUG();
 			case 2: /* FCNVFX */
 				switch(fmt) {
 				    case 0: /* sgl/sgl */
@@ -449,6 +464,7 @@
 					return(dbl_to_dbl_fcnvfx(&fpregs[r1],0,
 						&fpregs[t],status));
 				}
+				BUG();
 			case 3: /* FCNVFXT */
 				switch(fmt) {
 				    case 0: /* sgl/sgl */
@@ -464,6 +480,7 @@
 					return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0,
 						&fpregs[t],status));
 				}
+				BUG();
 			case 5: /* FCNVUF (PA2.0 only) */
 				switch(fmt) {
 				    case 0: /* sgl/sgl */
@@ -479,6 +496,7 @@
 					return(dbl_to_dbl_fcnvuf(&fpregs[r1],0,
 						&fpregs[t],status));
 				}
+				BUG();
 			case 6: /* FCNVFU (PA2.0 only) */
 				switch(fmt) {
 				    case 0: /* sgl/sgl */
@@ -494,6 +512,7 @@
 					return(dbl_to_dbl_fcnvfu(&fpregs[r1],0,
 						&fpregs[t],status));
 				}
+				BUG();
 			case 7: /* FCNVFUT (PA2.0 only) */
 				switch(fmt) {
 				    case 0: /* sgl/sgl */
@@ -509,10 +528,11 @@
 					return(dbl_to_dbl_fcnvfut(&fpregs[r1],0,
 						&fpregs[t],status));
 				}
+				BUG();
 			case 4: /* undefined */
 				return(MAJOR_0C_EXCP);
 		} /* end of switch subop */
-
+		BUG();
 	case 2: /* class 2 */
 		fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS];
 		r2 = extru(ir, fpr2pos, 5) * sizeof(double)/sizeof(u_int);
@@ -590,6 +610,7 @@
 				    case 3: /* quad not implemented */
 					return(MAJOR_0C_EXCP);
 				}
+				BUG();
 			case 1: /* FTEST */
 				switch (fmt) {
 				    case 0:
@@ -609,8 +630,10 @@
 				    case 3:
 					return(MAJOR_0C_EXCP);
 				}
+				BUG();
 		    } /* end of switch subop */
 		} /* end of else for PA1.0 & PA1.1 */
+		BUG();
 	case 3: /* class 3 */
 		r2 = extru(ir,fpr2pos,5) * sizeof(double)/sizeof(u_int);
 		if (r2 == 0)
@@ -633,6 +656,7 @@
 				    case 3: /* quad not implemented */
 					return(MAJOR_0C_EXCP);
 				}
+				BUG();
 			case 1: /* FSUB */
 				switch (fmt) {
 				    case 0:
@@ -645,6 +669,7 @@
 				    case 3: /* quad not implemented */
 					return(MAJOR_0C_EXCP);
 				}
+				BUG();
 			case 2: /* FMPY */
 				switch (fmt) {
 				    case 0:
@@ -657,6 +682,7 @@
 				    case 3: /* quad not implemented */
 					return(MAJOR_0C_EXCP);
 				}
+				BUG();
 			case 3: /* FDIV */
 				switch (fmt) {
 				    case 0:
@@ -669,6 +695,7 @@
 				    case 3: /* quad not implemented */
 					return(MAJOR_0C_EXCP);
 				}
+				BUG();
 			case 4: /* FREM */
 				switch (fmt) {
 				    case 0:
@@ -681,6 +708,7 @@
 				    case 3: /* quad not implemented */
 					return(MAJOR_0C_EXCP);
 				}
+				BUG();
 		} /* end of class 3 switch */
 	} /* end of switch(class) */
 
@@ -736,10 +764,12 @@
 					return(MAJOR_0E_EXCP);
 				    case 1: /* double */
 					fpregs[t+1] = fpregs[r1+1];
+					fallthrough;
 				    case 0: /* single */
 					fpregs[t] = fpregs[r1];
 					return(NOEXCEPTION);
 				}
+				BUG();
 			case 3: /* FABS */
 				switch (fmt) {
 				    case 2:
@@ -747,10 +777,12 @@
 					return(MAJOR_0E_EXCP);
 				    case 1: /* double */
 					fpregs[t+1] = fpregs[r1+1];
+					fallthrough;
 				    case 0: /* single */
 					fpregs[t] = fpregs[r1] & 0x7fffffff;
 					return(NOEXCEPTION);
 				}
+				BUG();
 			case 6: /* FNEG */
 				switch (fmt) {
 				    case 2:
@@ -758,10 +790,12 @@
 					return(MAJOR_0E_EXCP);
 				    case 1: /* double */
 					fpregs[t+1] = fpregs[r1+1];
+					fallthrough;
 				    case 0: /* single */
 					fpregs[t] = fpregs[r1] ^ 0x80000000;
 					return(NOEXCEPTION);
 				}
+				BUG();
 			case 7: /* FNEGABS */
 				switch (fmt) {
 				    case 2:
@@ -769,10 +803,12 @@
 					return(MAJOR_0E_EXCP);
 				    case 1: /* double */
 					fpregs[t+1] = fpregs[r1+1];
+					fallthrough;
 				    case 0: /* single */
 					fpregs[t] = fpregs[r1] | 0x80000000;
 					return(NOEXCEPTION);
 				}
+				BUG();
 			case 4: /* FSQRT */
 				switch (fmt) {
 				    case 0:
@@ -785,6 +821,7 @@
 				    case 3:
 					return(MAJOR_0E_EXCP);
 				}
+				BUG();
 			case 5: /* FRMD */
 				switch (fmt) {
 				    case 0:
@@ -798,7 +835,7 @@
 					return(MAJOR_0E_EXCP);
 				}
 		} /* end of switch (subop */
-	
+		BUG();
 	case 1: /* class 1 */
 		df = extru(ir,fpdfpos,2); /* get dest format */
 		/*
@@ -826,6 +863,7 @@
 				    case 3: /* dbl/dbl */
 					return(MAJOR_0E_EXCP);
 				}
+				BUG();
 			case 1: /* FCNVXF */
 				switch(fmt) {
 				    case 0: /* sgl/sgl */
@@ -841,6 +879,7 @@
 					return(dbl_to_dbl_fcnvxf(&fpregs[r1],0,
 						&fpregs[t],status));
 				}
+				BUG();
 			case 2: /* FCNVFX */
 				switch(fmt) {
 				    case 0: /* sgl/sgl */
@@ -856,6 +895,7 @@
 					return(dbl_to_dbl_fcnvfx(&fpregs[r1],0,
 						&fpregs[t],status));
 				}
+				BUG();
 			case 3: /* FCNVFXT */
 				switch(fmt) {
 				    case 0: /* sgl/sgl */
@@ -871,6 +911,7 @@
 					return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0,
 						&fpregs[t],status));
 				}
+				BUG();
 			case 5: /* FCNVUF (PA2.0 only) */
 				switch(fmt) {
 				    case 0: /* sgl/sgl */
@@ -886,6 +927,7 @@
 					return(dbl_to_dbl_fcnvuf(&fpregs[r1],0,
 						&fpregs[t],status));
 				}
+				BUG();
 			case 6: /* FCNVFU (PA2.0 only) */
 				switch(fmt) {
 				    case 0: /* sgl/sgl */
@@ -901,6 +943,7 @@
 					return(dbl_to_dbl_fcnvfu(&fpregs[r1],0,
 						&fpregs[t],status));
 				}
+				BUG();
 			case 7: /* FCNVFUT (PA2.0 only) */
 				switch(fmt) {
 				    case 0: /* sgl/sgl */
@@ -916,9 +959,11 @@
 					return(dbl_to_dbl_fcnvfut(&fpregs[r1],0,
 						&fpregs[t],status));
 				}
+				BUG();
 			case 4: /* undefined */
 				return(MAJOR_0C_EXCP);
 		} /* end of switch subop */
+		BUG();
 	case 2: /* class 2 */
 		/*
 		 * Be careful out there.
@@ -994,6 +1039,7 @@
 				}
 		    } /* end of switch subop */
 		} /* end of else for PA1.0 & PA1.1 */
+		BUG();
 	case 3: /* class 3 */
 		/*
 		 * Be careful out there.
@@ -1026,6 +1072,7 @@
 					return(dbl_fadd(&fpregs[r1],&fpregs[r2],
 						&fpregs[t],status));
 				}
+				BUG();
 			case 1: /* FSUB */
 				switch (fmt) {
 				    case 0:
@@ -1035,6 +1082,7 @@
 					return(dbl_fsub(&fpregs[r1],&fpregs[r2],
 						&fpregs[t],status));
 				}
+				BUG();
 			case 2: /* FMPY or XMPYU */
 				/*
 				 * check for integer multiply (x bit set)
@@ -1071,6 +1119,7 @@
 					       &fpregs[r2],&fpregs[t],status));
 				    }
 				}
+				BUG();
 			case 3: /* FDIV */
 				switch (fmt) {
 				    case 0:
@@ -1080,6 +1129,7 @@
 					return(dbl_fdiv(&fpregs[r1],&fpregs[r2],
 						&fpregs[t],status));
 				}
+				BUG();
 			case 4: /* FREM */
 				switch (fmt) {
 				    case 0:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/mm/fixmap.c
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/mm/fixmap.c
@@ -18,12 +18,9 @@
 	pte_t *pte;
 
 	if (pmd_none(*pmd))
-		pmd = pmd_alloc(NULL, pgd, vaddr);
-
-	pte = pte_offset_kernel(pmd, vaddr);
-	if (pte_none(*pte))
 		pte = pte_alloc_kernel(pmd, vaddr);
 
+	pte = pte_offset_kernel(pmd, vaddr);
 	set_pte_at(&init_mm, vaddr, pte, __mk_pte(phys, PAGE_KERNEL_RWX));
 	flush_tlb_kernel_range(vaddr, vaddr + PAGE_SIZE);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/parisc/mm/init.c
+++ linux-xilinx-zynqmp-5.4.0/arch/parisc/mm/init.c
@@ -347,9 +347,9 @@
 
 static bool kernel_set_to_readonly;
 
-static void __init map_pages(unsigned long start_vaddr,
-			     unsigned long start_paddr, unsigned long size,
-			     pgprot_t pgprot, int force)
+static void __ref map_pages(unsigned long start_vaddr,
+			    unsigned long start_paddr, unsigned long size,
+			    pgprot_t pgprot, int force)
 {
 	pgd_t *pg_dir;
 	pmd_t *pmd;
@@ -485,7 +485,7 @@
 	flush_tlb_all();
 }
 
-void __ref free_initmem(void)
+void free_initmem(void)
 {
 	unsigned long init_begin = (unsigned long)__init_begin;
 	unsigned long init_end = (unsigned long)__init_end;
@@ -499,7 +499,6 @@
 	/* The init text pages are marked R-X.  We have to
 	 * flush the icache and mark them RW-
 	 *
-	 * This is tricky, because map_pages is in the init section.
 	 * Do a dummy remap of the data section first (the data
 	 * section is already PAGE_KERNEL) to pull in the TLB entries
 	 * for map_kernel */
@@ -588,7 +587,7 @@
 			> BITS_PER_LONG);
 
 	high_memory = __va((max_pfn << PAGE_SHIFT));
-	set_max_mapnr(page_to_pfn(virt_to_page(high_memory - 1)) + 1);
+	set_max_mapnr(max_low_pfn);
 	memblock_free_all();
 
 #ifdef CONFIG_PA11
@@ -892,9 +891,9 @@
 {
 	int do_recycle;
 
-	__inc_irq_stat(irq_tlb_count);
 	do_recycle = 0;
 	spin_lock(&sid_lock);
+	__inc_irq_stat(irq_tlb_count);
 	if (dirty_space_ids > RECYCLE_THRESHOLD) {
 	    BUG_ON(recycle_inuse);  /* FIXME: Use a semaphore/wait queue here */
 	    get_dirty_sids(&recycle_ndirty,recycle_dirty_array);
@@ -913,8 +912,8 @@
 #else
 void flush_tlb_all(void)
 {
-	__inc_irq_stat(irq_tlb_count);
 	spin_lock(&sid_lock);
+	__inc_irq_stat(irq_tlb_count);
 	flush_tlb_all_local(NULL);
 	recycle_sids();
 	spin_unlock(&sid_lock);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/Kconfig
@@ -133,7 +133,7 @@
 	select ARCH_HAS_PTE_SPECIAL
 	select ARCH_HAS_MEMBARRIER_CALLBACKS
 	select ARCH_HAS_SCALED_CPUTIME		if VIRT_CPU_ACCOUNTING_NATIVE && PPC_BOOK3S_64
-	select ARCH_HAS_STRICT_KERNEL_RWX	if ((PPC_BOOK3S_64 || PPC32) && !RELOCATABLE && !HIBERNATION)
+	select ARCH_HAS_STRICT_KERNEL_RWX	if (PPC32 && !HIBERNATION)
 	select ARCH_HAS_TICK_BROADCAST		if GENERIC_CLOCKEVENTS_BROADCAST
 	select ARCH_HAS_UACCESS_FLUSHCACHE
 	select ARCH_HAS_UACCESS_MCSAFE		if PPC64
@@ -147,6 +147,7 @@
 	select ARCH_USE_BUILTIN_BSWAP
 	select ARCH_USE_CMPXCHG_LOCKREF		if PPC64
 	select ARCH_WANT_IPC_PARSE_VERSION
+	select ARCH_WANT_IRQS_OFF_ACTIVATE_MM
 	select ARCH_WEAK_RELEASE_ACQUIRE
 	select BINFMT_ELF
 	select BUILDTIME_EXTABLE_SORT
@@ -171,7 +172,7 @@
 	select HAVE_ARCH_AUDITSYSCALL
 	select HAVE_ARCH_HUGE_VMAP		if PPC_BOOK3S_64 && PPC_RADIX_MMU
 	select HAVE_ARCH_JUMP_LABEL
-	select HAVE_ARCH_KASAN			if PPC32
+	select HAVE_ARCH_KASAN			if PPC32 && PPC_PAGE_SHIFT <= 14
 	select HAVE_ARCH_KGDB
 	select HAVE_ARCH_MMAP_RND_BITS
 	select HAVE_ARCH_MMAP_RND_COMPAT_BITS	if COMPAT
@@ -213,7 +214,7 @@
 	select HAVE_MEMBLOCK_NODE_MAP
 	select HAVE_MOD_ARCH_SPECIFIC
 	select HAVE_NMI				if PERF_EVENTS || (PPC64 && PPC_BOOK3S)
-	select HAVE_HARDLOCKUP_DETECTOR_ARCH	if (PPC64 && PPC_BOOK3S)
+	select HAVE_HARDLOCKUP_DETECTOR_ARCH	if PPC64 && PPC_BOOK3S && SMP
 	select HAVE_OPROFILE
 	select HAVE_OPTPROBES			if PPC64
 	select HAVE_PERF_EVENTS
@@ -221,8 +222,7 @@
 	select HAVE_HARDLOCKUP_DETECTOR_PERF	if PERF_EVENTS && HAVE_PERF_EVENTS_NMI && !HAVE_HARDLOCKUP_DETECTOR_ARCH
 	select HAVE_PERF_REGS
 	select HAVE_PERF_USER_STACK_DUMP
-	select HAVE_RCU_TABLE_FREE		if SMP
-	select HAVE_RCU_TABLE_NO_INVALIDATE	if HAVE_RCU_TABLE_FREE
+	select HAVE_RCU_TABLE_FREE
 	select HAVE_MMU_GATHER_PAGE_SIZE
 	select HAVE_REGS_AND_STACK_ACCESS_API
 	select HAVE_RELIABLE_STACKTRACE		if PPC_BOOK3S_64 && CPU_LITTLE_ENDIAN
@@ -237,6 +237,7 @@
 	select NEED_DMA_MAP_STATE		if PPC64 || NOT_COHERENT_CACHE
 	select NEED_SG_DMA_LENGTH
 	select OF
+	select OF_DMA_DEFAULT_COHERENT		if !NOT_COHERENT_CACHE
 	select OF_EARLY_FLATTREE
 	select OLD_SIGACTION			if PPC32
 	select OLD_SIGSUSPEND
@@ -722,7 +723,7 @@
 
 config PPC_256K_PAGES
 	bool "256k page size"
-	depends on 44x && !STDBINUTILS
+	depends on 44x && !STDBINUTILS && !PPC_47x
 	help
 	  Make the page size 256k.
 
@@ -747,6 +748,7 @@
 	range 13 15
 	default "15" if PPC_256K_PAGES
 	default "14" if PPC64
+	default "14" if KASAN
 	default "13"
 	help
 	  Used to define the stack size. The default is almost always what you
@@ -934,6 +936,28 @@
 
 	  If unsure, say y.
 
+config PPC_SECURE_BOOT
+	prompt "Enable secure boot support"
+	bool
+	depends on PPC_POWERNV
+	depends on IMA_ARCH_POLICY
+	help
+	  Systems with firmware secure boot enabled need to define security
+	  policies to extend secure boot to the OS. This config allows a user
+	  to enable OS secure boot on systems that have firmware support for
+	  it. If in doubt say N.
+
+config PPC_SECVAR_SYSFS
+	bool "Enable sysfs interface for POWER secure variables"
+	default y
+	depends on PPC_SECURE_BOOT
+	depends on SYSFS
+	help
+	  POWER secure variables are managed and controlled by firmware.
+	  These variables are exposed to userspace via sysfs to enable
+	  read/write operations on these variables. Say Y if you have
+	  secure boot enabled and want to expose variables to userspace.
+
 endmenu
 
 config ISA_DMA_API
@@ -1022,6 +1046,19 @@
 	  Include support for RapidIO controller on Freescale embedded
 	  processors (MPC8548, MPC8641, etc).
 
+config PPC_RTAS_FILTER
+	bool "Enable filtering of RTAS syscalls"
+	default y
+	depends on PPC_RTAS
+	help
+	  The RTAS syscall API has security issues that could be used to
+	  compromise system integrity. This option enforces restrictions on the
+	  RTAS calls and arguments passed by userspace programs to mitigate
+	  these issues.
+
+	  Say Y unless you know what you are doing and the filter is causing
+	  problems for you.
+
 endmenu
 
 config NONSTATIC_KERNEL
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/Kconfig.debug
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/Kconfig.debug
@@ -234,7 +234,7 @@
 
 config PPC_EARLY_DEBUG_CPM
 	bool "Early serial debugging for Freescale CPM-based serial ports"
-	depends on SERIAL_CPM
+	depends on SERIAL_CPM=y
 	help
 	  Select this to enable early debugging for Freescale chips
 	  using a CPM-based serial port.  This assumes that the bootwrapper
@@ -352,6 +352,7 @@
 config FAIL_IOMMU
 	bool "Fault-injection capability for IOMMU"
 	depends on FAULT_INJECTION
+	depends on PCI || IBMVIO
 	help
 	  Provide fault-injection capability for IOMMU. Each device can
 	  be selectively enabled via the fail_iommu property.
@@ -371,7 +372,7 @@
 
 config PPC_DEBUG_WX
 	bool "Warn on W+X mappings at boot"
-	depends on PPC_PTDUMP
+	depends on PPC_PTDUMP && STRICT_KERNEL_RWX
 	help
 	  Generate a warning if any W+X mappings are found at boot.
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/Makefile
@@ -17,23 +17,6 @@
 # Set default 32 bits cross compilers for vdso and boot wrapper
 CROSS32_COMPILE ?=
 
-ifeq ($(HAS_BIARCH),y)
-ifeq ($(CROSS32_COMPILE),)
-ifdef CONFIG_PPC32
-# These options will be overridden by any -mcpu option that the CPU
-# or platform code sets later on the command line, but they are needed
-# to set a sane 32-bit cpu target for the 64-bit cross compiler which
-# may default to the wrong ISA.
-KBUILD_CFLAGS		+= -mcpu=powerpc
-KBUILD_AFLAGS		+= -mcpu=powerpc
-endif
-endif
-endif
-
-ifdef CONFIG_PPC_BOOK3S_32
-KBUILD_CFLAGS		+= -mcpu=powerpc
-endif
-
 # If we're on a ppc/ppc64/ppc64le machine use that defconfig, otherwise just use
 # ppc64_defconfig because we have nothing better to go on.
 uname := $(shell uname -m)
@@ -91,11 +74,13 @@
 endif
 
 ifdef CONFIG_PPC64
+ifndef CONFIG_CC_IS_CLANG
 cflags-$(CONFIG_CPU_BIG_ENDIAN)		+= $(call cc-option,-mabi=elfv1)
 cflags-$(CONFIG_CPU_BIG_ENDIAN)		+= $(call cc-option,-mcall-aixdesc)
 aflags-$(CONFIG_CPU_BIG_ENDIAN)		+= $(call cc-option,-mabi=elfv1)
 aflags-$(CONFIG_CPU_LITTLE_ENDIAN)	+= -mabi=elfv2
 endif
+endif
 
 ifndef CONFIG_CC_IS_CLANG
   cflags-$(CONFIG_CPU_LITTLE_ENDIAN)	+= -mno-strict-align
@@ -108,7 +93,7 @@
 
 ifeq ($(HAS_BIARCH),y)
 KBUILD_CFLAGS	+= -m$(BITS)
-KBUILD_AFLAGS	+= -m$(BITS) -Wl,-a$(BITS)
+KBUILD_AFLAGS	+= -m$(BITS)
 KBUILD_LDFLAGS	+= -m elf$(BITS)$(LDEMULATION)
 endif
 
@@ -141,6 +126,7 @@
 endif
 
 CFLAGS-$(CONFIG_PPC64)	:= $(call cc-option,-mtraceback=no)
+ifndef CONFIG_CC_IS_CLANG
 ifdef CONFIG_CPU_LITTLE_ENDIAN
 CFLAGS-$(CONFIG_PPC64)	+= $(call cc-option,-mabi=elfv2,$(call cc-option,-mcall-aixdesc))
 AFLAGS-$(CONFIG_PPC64)	+= $(call cc-option,-mabi=elfv2)
@@ -149,6 +135,7 @@
 CFLAGS-$(CONFIG_PPC64)	+= $(call cc-option,-mcall-aixdesc)
 AFLAGS-$(CONFIG_PPC64)	+= $(call cc-option,-mabi=elfv1)
 endif
+endif
 CFLAGS-$(CONFIG_PPC64)	+= $(call cc-option,-mcmodel=medium,$(call cc-option,-mminimal-toc))
 CFLAGS-$(CONFIG_PPC64)	+= $(call cc-option,-mno-pointers-to-nested-functions)
 
@@ -168,9 +155,9 @@
 CFLAGS-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=power9,-mtune=power8)
 else
 CFLAGS-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=power7,$(call cc-option,-mtune=power5))
-CFLAGS-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mcpu=power5,-mcpu=power4)
+CFLAGS-$(CONFIG_GENERIC_CPU) += -mcpu=power4
 endif
-else
+else ifdef CONFIG_PPC_BOOK3E_64
 CFLAGS-$(CONFIG_GENERIC_CPU) += -mcpu=powerpc64
 endif
 
@@ -188,6 +175,7 @@
 endif
 
 CFLAGS-$(CONFIG_TARGET_CPU_BOOL) += $(call cc-option,-mcpu=$(CONFIG_TARGET_CPU))
+AFLAGS-$(CONFIG_TARGET_CPU_BOOL) += $(call cc-option,-mcpu=$(CONFIG_TARGET_CPU))
 
 # Altivec option not allowed with e500mc64 in GCC.
 ifdef CONFIG_ALTIVEC
@@ -198,14 +186,6 @@
 CFLAGS-$(CONFIG_E5500_CPU) += $(E5500_CPU)
 CFLAGS-$(CONFIG_E6500_CPU) += $(call cc-option,-mcpu=e6500,$(E5500_CPU))
 
-ifdef CONFIG_PPC32
-ifdef CONFIG_PPC_E500MC
-CFLAGS-y += $(call cc-option,-mcpu=e500mc,-mcpu=powerpc)
-else
-CFLAGS-$(CONFIG_E500) += $(call cc-option,-mcpu=8540 -msoft-float,-mcpu=powerpc)
-endif
-endif
-
 asinstr := $(call as-instr,lis 9$(comma)foo@high,-DHAVE_AS_ATHIGH=1)
 
 KBUILD_CPPFLAGS	+= -I $(srctree)/arch/$(ARCH) $(asinstr)
@@ -246,7 +226,6 @@
 
 cpu-as-$(CONFIG_4xx)		+= -Wa,-m405
 cpu-as-$(CONFIG_ALTIVEC)	+= $(call as-option,-Wa$(comma)-maltivec)
-cpu-as-$(CONFIG_E200)		+= -Wa,-me200
 cpu-as-$(CONFIG_E500)		+= -Wa,-me500
 
 # When using '-many -mpower4' gas will first try and find a matching power4
@@ -281,7 +260,7 @@
 all: zImage
 
 # With make 3.82 we cannot mix normal and wildcard targets
-BOOT_TARGETS1 := zImage zImage.initrd uImage
+BOOT_TARGETS1 := zImage zImage.initrd uImage vmlinux.strip
 BOOT_TARGETS2 := zImage% dtbImage% treeImage.% cuImage.% simpleImage.% uImage.%
 
 PHONY += $(BOOT_TARGETS1) $(BOOT_TARGETS2)
@@ -446,3 +425,11 @@
 		echo -n '*** Please use a different binutils version.' ; \
 		false ; \
 	fi
+	@if test "x${CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT}" = "xy" -a \
+		"x${CONFIG_LD_IS_BFD}" = "xy" -a \
+		"${CONFIG_LD_VERSION}" = "23700" ; then \
+		echo -n '*** binutils 2.37 drops unused section symbols, which recordmcount ' ; \
+		echo 'is unable to handle.' ; \
+		echo '*** Please use a different binutils version.' ; \
+		false ; \
+	fi
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/Makefile.postlink
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/Makefile.postlink
@@ -17,11 +17,11 @@
 quiet_cmd_relocs_check = CHKREL  $@
 ifdef CONFIG_PPC_BOOK3S_64
       cmd_relocs_check =						\
-	$(CONFIG_SHELL) $(srctree)/arch/powerpc/tools/relocs_check.sh "$(OBJDUMP)" "$@" ; \
+	$(CONFIG_SHELL) $(srctree)/arch/powerpc/tools/relocs_check.sh "$(OBJDUMP)" "$(NM)" "$@" ; \
 	$(BASH) $(srctree)/arch/powerpc/tools/unrel_branch_check.sh "$(OBJDUMP)" "$@"
 else
       cmd_relocs_check =						\
-	$(CONFIG_SHELL) $(srctree)/arch/powerpc/tools/relocs_check.sh "$(OBJDUMP)" "$@"
+	$(CONFIG_SHELL) $(srctree)/arch/powerpc/tools/relocs_check.sh "$(OBJDUMP)" "$(NM)" "$@"
 endif
 
 # `@true` prevents complaint when there is nothing to be done
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/4xx.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/4xx.c
@@ -228,7 +228,7 @@
 		dpath = 8; /* 64 bits */
 
 	/* get address pins (rows) */
- 	val = SDRAM0_READ(DDR0_42);
+	val = SDRAM0_READ(DDR0_42);
 
 	row = DDR_GET_VAL(val, DDR_APIN, DDR_APIN_SHIFT);
 	if (row > max_row)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/Makefile
@@ -30,6 +30,7 @@
 
 BOOTCFLAGS    := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
 		 -fno-strict-aliasing -O2 -msoft-float -mno-altivec -mno-vsx \
+		 $(call cc-option,-mno-spe) $(call cc-option,-mspe=no) \
 		 -pipe -fomit-frame-pointer -fno-builtin -fPIC -nostdinc \
 		 $(LINUXINCLUDE)
 
@@ -119,7 +120,7 @@
 		elf_util.c $(zlib-y) devtree.c stdlib.c \
 		oflib.c ofconsole.c cuboot.c
 
-src-wlib-$(CONFIG_PPC_MPC52XX) += mpc52xx-psc.c
+src-wlib-$(CONFIG_PPC_MPC52xx) += mpc52xx-psc.c
 src-wlib-$(CONFIG_PPC64_BOOT_WRAPPER) += opal-calls.S opal.c
 ifndef CONFIG_PPC64_BOOT_WRAPPER
 src-wlib-y += crtsavres.S
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/crt0.S
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/crt0.S
@@ -44,9 +44,6 @@
 p_pstack:	.long	_platform_stack_top
 #endif
 
-	.globl	_zimage_start
-	/* Clang appears to require the .weak directive to be after the symbol
-	 * is defined. See https://bugs.llvm.org/show_bug.cgi?id=38921  */
 	.weak	_zimage_start
 _zimage_start:
 	.globl	_zimage_start_lib
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/devtree.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/devtree.c
@@ -13,6 +13,7 @@
 #include "string.h"
 #include "stdio.h"
 #include "ops.h"
+#include "of.h"
 
 void dt_fixup_memory(u64 start, u64 size)
 {
@@ -23,21 +24,25 @@
 	root = finddevice("/");
 	if (getprop(root, "#address-cells", &naddr, sizeof(naddr)) < 0)
 		naddr = 2;
+	else
+		naddr = be32_to_cpu(naddr);
 	if (naddr < 1 || naddr > 2)
 		fatal("Can't cope with #address-cells == %d in /\n\r", naddr);
 
 	if (getprop(root, "#size-cells", &nsize, sizeof(nsize)) < 0)
 		nsize = 1;
+	else
+		nsize = be32_to_cpu(nsize);
 	if (nsize < 1 || nsize > 2)
 		fatal("Can't cope with #size-cells == %d in /\n\r", nsize);
 
 	i = 0;
 	if (naddr == 2)
-		memreg[i++] = start >> 32;
-	memreg[i++] = start & 0xffffffff;
+		memreg[i++] = cpu_to_be32(start >> 32);
+	memreg[i++] = cpu_to_be32(start & 0xffffffff);
 	if (nsize == 2)
-		memreg[i++] = size >> 32;
-	memreg[i++] = size & 0xffffffff;
+		memreg[i++] = cpu_to_be32(size >> 32);
+	memreg[i++] = cpu_to_be32(size & 0xffffffff);
 
 	memory = finddevice("/memory");
 	if (! memory) {
@@ -45,9 +50,9 @@
 		setprop_str(memory, "device_type", "memory");
 	}
 
-	printf("Memory <- <0x%x", memreg[0]);
+	printf("Memory <- <0x%x", be32_to_cpu(memreg[0]));
 	for (i = 1; i < (naddr + nsize); i++)
-		printf(" 0x%x", memreg[i]);
+		printf(" 0x%x", be32_to_cpu(memreg[i]));
 	printf("> (%ldMB)\n\r", (unsigned long)(size >> 20));
 
 	setprop(memory, "reg", memreg, (naddr + nsize)*sizeof(u32));
@@ -65,10 +70,10 @@
 		printf("CPU bus-frequency <- 0x%x (%dMHz)\n\r", bus, MHZ(bus));
 
 	while ((devp = find_node_by_devtype(devp, "cpu"))) {
-		setprop_val(devp, "clock-frequency", cpu);
-		setprop_val(devp, "timebase-frequency", tb);
+		setprop_val(devp, "clock-frequency", cpu_to_be32(cpu));
+		setprop_val(devp, "timebase-frequency", cpu_to_be32(tb));
 		if (bus > 0)
-			setprop_val(devp, "bus-frequency", bus);
+			setprop_val(devp, "bus-frequency", cpu_to_be32(bus));
 	}
 
 	timebase_period_ns = 1000000000 / tb;
@@ -80,7 +85,7 @@
 
 	if (devp) {
 		printf("%s: clock-frequency <- %x (%dMHz)\n\r", path, freq, MHZ(freq));
-		setprop_val(devp, "clock-frequency", freq);
+		setprop_val(devp, "clock-frequency", cpu_to_be32(freq));
 	}
 }
 
@@ -133,8 +138,12 @@
 {
 	if (getprop(node, "#address-cells", naddr, 4) != 4)
 		*naddr = 2;
+	else
+		*naddr = be32_to_cpu(*naddr);
 	if (getprop(node, "#size-cells", nsize, 4) != 4)
 		*nsize = 1;
+	else
+		*nsize = be32_to_cpu(*nsize);
 }
 
 static void copy_val(u32 *dest, u32 *src, int naddr)
@@ -163,9 +172,9 @@
 	int i, carry = 0;
 
 	for (i = MAX_ADDR_CELLS - 1; i >= MAX_ADDR_CELLS - naddr; i--) {
-		u64 tmp = (u64)reg[i] + add[i] + carry;
+		u64 tmp = (u64)be32_to_cpu(reg[i]) + be32_to_cpu(add[i]) + carry;
 		carry = tmp >> 32;
-		reg[i] = (u32)tmp;
+		reg[i] = cpu_to_be32((u32)tmp);
 	}
 
 	return !carry;
@@ -180,18 +189,18 @@
 	u32 end;
 
 	for (i = 0; i < MAX_ADDR_CELLS; i++) {
-		if (reg[i] < range[i])
+		if (be32_to_cpu(reg[i]) < be32_to_cpu(range[i]))
 			return 0;
-		if (reg[i] > range[i])
+		if (be32_to_cpu(reg[i]) > be32_to_cpu(range[i]))
 			break;
 	}
 
 	for (i = 0; i < MAX_ADDR_CELLS; i++) {
-		end = range[i] + rangesize[i];
+		end = be32_to_cpu(range[i]) + be32_to_cpu(rangesize[i]);
 
-		if (reg[i] < end)
+		if (be32_to_cpu(reg[i]) < end)
 			break;
-		if (reg[i] > end)
+		if (be32_to_cpu(reg[i]) > end)
 			return 0;
 	}
 
@@ -240,7 +249,6 @@
 		return 0;
 
 	dt_get_reg_format(parent, &naddr, &nsize);
-
 	if (nsize > 2)
 		return 0;
 
@@ -252,10 +260,10 @@
 
 	copy_val(last_addr, prop_buf + offset, naddr);
 
-	ret_size = prop_buf[offset + naddr];
+	ret_size = be32_to_cpu(prop_buf[offset + naddr]);
 	if (nsize == 2) {
 		ret_size <<= 32;
-		ret_size |= prop_buf[offset + naddr + 1];
+		ret_size |= be32_to_cpu(prop_buf[offset + naddr + 1]);
 	}
 
 	for (;;) {
@@ -278,7 +286,6 @@
 
 		offset = find_range(last_addr, prop_buf, prev_naddr,
 		                    naddr, prev_nsize, buflen / 4);
-
 		if (offset < 0)
 			return 0;
 
@@ -296,8 +303,7 @@
 	if (naddr > 2)
 		return 0;
 
-	ret_addr = ((u64)last_addr[2] << 32) | last_addr[3];
-
+	ret_addr = ((u64)be32_to_cpu(last_addr[2]) << 32) | be32_to_cpu(last_addr[3]);
 	if (sizeof(void *) == 4 &&
 	    (ret_addr >= 0x100000000ULL || ret_size > 0x100000000ULL ||
 	     ret_addr + ret_size > 0x100000000ULL))
@@ -350,11 +356,14 @@
 int dt_get_virtual_reg(void *node, void **addr, int nres)
 {
 	unsigned long xaddr;
-	int n;
+	int n, i;
 
 	n = getprop(node, "virtual-reg", addr, nres * 4);
-	if (n > 0)
+	if (n > 0) {
+		for (i = 0; i < n/4; i ++)
+			((u32 *)addr)[i] = be32_to_cpu(((u32 *)addr)[i]);
 		return n / 4;
+	}
 
 	for (n = 0; n < nres; n++) {
 		if (!dt_xlate_reg(node, n, &xaddr, NULL))
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/charon.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/charon.dts
@@ -35,7 +35,7 @@
 		};
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0x00000000 0x08000000>;	// 128MB
 	};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/digsy_mtc.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/digsy_mtc.dts
@@ -16,7 +16,7 @@
 	model = "intercontrol,digsy-mtc";
 	compatible = "intercontrol,digsy-mtc";
 
-	memory {
+	memory@0 {
 		reg = <0x00000000 0x02000000>;	// 32MB
 	};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/fsl/e500v1_power_isa.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/fsl/e500v1_power_isa.dtsi
@@ -0,0 +1,51 @@
+/*
+ * e500v1 Power ISA Device Tree Source (include)
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/ {
+	cpus {
+		power-isa-version = "2.03";
+		power-isa-b;		// Base
+		power-isa-e;		// Embedded
+		power-isa-atb;		// Alternate Time Base
+		power-isa-cs;		// Cache Specification
+		power-isa-e.le;		// Embedded.Little-Endian
+		power-isa-e.pm;		// Embedded.Performance Monitor
+		power-isa-ecl;		// Embedded Cache Locking
+		power-isa-mmc;		// Memory Coherence
+		power-isa-sp;		// Signal Processing Engine
+		power-isa-sp.fs;	// SPE.Embedded Float Scalar Single
+		power-isa-sp.fv;	// SPE.Embedded Float Vector
+		mmu-type = "power-embedded";
+	};
+};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/fsl/mpc8540ads.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/fsl/mpc8540ads.dts
@@ -7,7 +7,7 @@
 
 /dts-v1/;
 
-/include/ "e500v2_power_isa.dtsi"
+/include/ "e500v1_power_isa.dtsi"
 
 / {
 	model = "MPC8540ADS";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/fsl/mpc8541cds.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/fsl/mpc8541cds.dts
@@ -7,7 +7,7 @@
 
 /dts-v1/;
 
-/include/ "e500v2_power_isa.dtsi"
+/include/ "e500v1_power_isa.dtsi"
 
 / {
 	model = "MPC8541CDS";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/fsl/mpc8555cds.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/fsl/mpc8555cds.dts
@@ -7,7 +7,7 @@
 
 /dts-v1/;
 
-/include/ "e500v2_power_isa.dtsi"
+/include/ "e500v1_power_isa.dtsi"
 
 / {
 	model = "MPC8555CDS";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/fsl/mpc8560ads.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/fsl/mpc8560ads.dts
@@ -7,7 +7,7 @@
 
 /dts-v1/;
 
-/include/ "e500v2_power_isa.dtsi"
+/include/ "e500v1_power_isa.dtsi"
 
 / {
 	model = "MPC8560ADS";
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/fsl/p1010si-post.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/fsl/p1010si-post.dtsi
@@ -122,7 +122,15 @@
 	};
 
 /include/ "pq3-i2c-0.dtsi"
+	i2c@3000 {
+		fsl,i2c-erratum-a004447;
+	};
+
 /include/ "pq3-i2c-1.dtsi"
+	i2c@3100 {
+		fsl,i2c-erratum-a004447;
+	};
+
 /include/ "pq3-duart-0.dtsi"
 /include/ "pq3-espi-0.dtsi"
 	spi0: spi@7000 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/fsl/p2041si-post.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/fsl/p2041si-post.dtsi
@@ -371,7 +371,23 @@
 	};
 
 /include/ "qoriq-i2c-0.dtsi"
+	i2c@118000 {
+		fsl,i2c-erratum-a004447;
+	};
+
+	i2c@118100 {
+		fsl,i2c-erratum-a004447;
+	};
+
 /include/ "qoriq-i2c-1.dtsi"
+	i2c@119000 {
+		fsl,i2c-erratum-a004447;
+	};
+
+	i2c@119100 {
+		fsl,i2c-erratum-a004447;
+	};
+
 /include/ "qoriq-duart-0.dtsi"
 /include/ "qoriq-duart-1.dtsi"
 /include/ "qoriq-gpio-0.dtsi"
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-0-best-effort.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-0-best-effort.dtsi
@@ -63,6 +63,7 @@
 		#size-cells = <0>;
 		compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
 		reg = <0xe1000 0x1000>;
+		fsl,erratum-a011043; /* must ignore read errors */
 
 		pcsphy0: ethernet-phy@0 {
 			reg = <0x0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-0.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-0.dtsi
@@ -60,6 +60,7 @@
 		#size-cells = <0>;
 		compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
 		reg = <0xf1000 0x1000>;
+		fsl,erratum-a011043; /* must ignore read errors */
 
 		pcsphy6: ethernet-phy@0 {
 			reg = <0x0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-1-best-effort.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-1-best-effort.dtsi
@@ -63,6 +63,7 @@
 		#size-cells = <0>;
 		compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
 		reg = <0xe3000 0x1000>;
+		fsl,erratum-a011043; /* must ignore read errors */
 
 		pcsphy1: ethernet-phy@0 {
 			reg = <0x0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-1.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-1.dtsi
@@ -60,6 +60,7 @@
 		#size-cells = <0>;
 		compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
 		reg = <0xf3000 0x1000>;
+		fsl,erratum-a011043; /* must ignore read errors */
 
 		pcsphy7: ethernet-phy@0 {
 			reg = <0x0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-2.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-2.dtsi
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later
+/*
+ * QorIQ FMan v3 10g port #2 device tree stub [ controller @ offset 0x400000 ]
+ *
+ * Copyright 2022 Sean Anderson <sean.anderson@seco.com>
+ * Copyright 2012 - 2015 Freescale Semiconductor Inc.
+ */
+
+fman@400000 {
+	fman0_rx_0x08: port@88000 {
+		cell-index = <0x8>;
+		compatible = "fsl,fman-v3-port-rx";
+		reg = <0x88000 0x1000>;
+		fsl,fman-10g-port;
+	};
+
+	fman0_tx_0x28: port@a8000 {
+		cell-index = <0x28>;
+		compatible = "fsl,fman-v3-port-tx";
+		reg = <0xa8000 0x1000>;
+		fsl,fman-10g-port;
+	};
+
+	ethernet@e0000 {
+		cell-index = <0>;
+		compatible = "fsl,fman-memac";
+		reg = <0xe0000 0x1000>;
+		fsl,fman-ports = <&fman0_rx_0x08 &fman0_tx_0x28>;
+		ptp-timer = <&ptp_timer0>;
+		pcsphy-handle = <&pcsphy0>;
+	};
+
+	mdio@e1000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
+		reg = <0xe1000 0x1000>;
+		fsl,erratum-a011043; /* must ignore read errors */
+
+		pcsphy0: ethernet-phy@0 {
+			reg = <0x0>;
+		};
+	};
+};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-3.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-10g-3.dtsi
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later
+/*
+ * QorIQ FMan v3 10g port #3 device tree stub [ controller @ offset 0x400000 ]
+ *
+ * Copyright 2022 Sean Anderson <sean.anderson@seco.com>
+ * Copyright 2012 - 2015 Freescale Semiconductor Inc.
+ */
+
+fman@400000 {
+	fman0_rx_0x09: port@89000 {
+		cell-index = <0x9>;
+		compatible = "fsl,fman-v3-port-rx";
+		reg = <0x89000 0x1000>;
+		fsl,fman-10g-port;
+	};
+
+	fman0_tx_0x29: port@a9000 {
+		cell-index = <0x29>;
+		compatible = "fsl,fman-v3-port-tx";
+		reg = <0xa9000 0x1000>;
+		fsl,fman-10g-port;
+	};
+
+	ethernet@e2000 {
+		cell-index = <1>;
+		compatible = "fsl,fman-memac";
+		reg = <0xe2000 0x1000>;
+		fsl,fman-ports = <&fman0_rx_0x09 &fman0_tx_0x29>;
+		ptp-timer = <&ptp_timer0>;
+		pcsphy-handle = <&pcsphy1>;
+	};
+
+	mdio@e3000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
+		reg = <0xe3000 0x1000>;
+		fsl,erratum-a011043; /* must ignore read errors */
+
+		pcsphy1: ethernet-phy@0 {
+			reg = <0x0>;
+		};
+	};
+};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-0.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-0.dtsi
@@ -59,6 +59,7 @@
 		#size-cells = <0>;
 		compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
 		reg = <0xe1000 0x1000>;
+		fsl,erratum-a011043; /* must ignore read errors */
 
 		pcsphy0: ethernet-phy@0 {
 			reg = <0x0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-1.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-1.dtsi
@@ -59,6 +59,7 @@
 		#size-cells = <0>;
 		compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
 		reg = <0xe3000 0x1000>;
+		fsl,erratum-a011043; /* must ignore read errors */
 
 		pcsphy1: ethernet-phy@0 {
 			reg = <0x0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-2.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-2.dtsi
@@ -59,6 +59,7 @@
 		#size-cells = <0>;
 		compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
 		reg = <0xe5000 0x1000>;
+		fsl,erratum-a011043; /* must ignore read errors */
 
 		pcsphy2: ethernet-phy@0 {
 			reg = <0x0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-3.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-3.dtsi
@@ -59,6 +59,7 @@
 		#size-cells = <0>;
 		compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
 		reg = <0xe7000 0x1000>;
+		fsl,erratum-a011043; /* must ignore read errors */
 
 		pcsphy3: ethernet-phy@0 {
 			reg = <0x0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-4.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-4.dtsi
@@ -59,6 +59,7 @@
 		#size-cells = <0>;
 		compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
 		reg = <0xe9000 0x1000>;
+		fsl,erratum-a011043; /* must ignore read errors */
 
 		pcsphy4: ethernet-phy@0 {
 			reg = <0x0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-5.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/fsl/qoriq-fman3-0-1g-5.dtsi
@@ -59,6 +59,7 @@
 		#size-cells = <0>;
 		compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
 		reg = <0xeb000 0x1000>;
+		fsl,erratum-a011043; /* must ignore read errors */
 
 		pcsphy5: ethernet-phy@0 {
 			reg = <0x0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-10g-0.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-10g-0.dtsi
@@ -60,6 +60,7 @@
 		#size-cells = <0>;
 		compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
 		reg = <0xf1000 0x1000>;
+		fsl,erratum-a011043; /* must ignore read errors */
 
 		pcsphy14: ethernet-phy@0 {
 			reg = <0x0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-10g-1.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-10g-1.dtsi
@@ -60,6 +60,7 @@
 		#size-cells = <0>;
 		compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
 		reg = <0xf3000 0x1000>;
+		fsl,erratum-a011043; /* must ignore read errors */
 
 		pcsphy15: ethernet-phy@0 {
 			reg = <0x0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-0.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-0.dtsi
@@ -59,6 +59,7 @@
 		#size-cells = <0>;
 		compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
 		reg = <0xe1000 0x1000>;
+		fsl,erratum-a011043; /* must ignore read errors */
 
 		pcsphy8: ethernet-phy@0 {
 			reg = <0x0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-1.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-1.dtsi
@@ -59,6 +59,7 @@
 		#size-cells = <0>;
 		compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
 		reg = <0xe3000 0x1000>;
+		fsl,erratum-a011043; /* must ignore read errors */
 
 		pcsphy9: ethernet-phy@0 {
 			reg = <0x0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-2.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-2.dtsi
@@ -59,6 +59,7 @@
 		#size-cells = <0>;
 		compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
 		reg = <0xe5000 0x1000>;
+		fsl,erratum-a011043; /* must ignore read errors */
 
 		pcsphy10: ethernet-phy@0 {
 			reg = <0x0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-3.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-3.dtsi
@@ -59,6 +59,7 @@
 		#size-cells = <0>;
 		compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
 		reg = <0xe7000 0x1000>;
+		fsl,erratum-a011043; /* must ignore read errors */
 
 		pcsphy11: ethernet-phy@0 {
 			reg = <0x0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-4.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-4.dtsi
@@ -59,6 +59,7 @@
 		#size-cells = <0>;
 		compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
 		reg = <0xe9000 0x1000>;
+		fsl,erratum-a011043; /* must ignore read errors */
 
 		pcsphy12: ethernet-phy@0 {
 			reg = <0x0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-5.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/fsl/qoriq-fman3-1-1g-5.dtsi
@@ -59,6 +59,7 @@
 		#size-cells = <0>;
 		compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
 		reg = <0xeb000 0x1000>;
+		fsl,erratum-a011043; /* must ignore read errors */
 
 		pcsphy13: ethernet-phy@0 {
 			reg = <0x0>;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/fsl/qoriq-fman3l-0.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/fsl/qoriq-fman3l-0.dtsi
@@ -79,6 +79,7 @@
 		#size-cells = <0>;
 		compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
 		reg = <0xfc000 0x1000>;
+		fsl,erratum-a009885;
 	};
 
 	xmdio0: mdio@fd000 {
@@ -86,6 +87,7 @@
 		#size-cells = <0>;
 		compatible = "fsl,fman-memac-mdio", "fsl,fman-xmdio";
 		reg = <0xfd000 0x1000>;
+		fsl,erratum-a009885;
 	};
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/fsl/t1023rdb.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/fsl/t1023rdb.dts
@@ -154,7 +154,7 @@
 
 			fm1mac3: ethernet@e4000 {
 				phy-handle = <&sgmii_aqr_phy3>;
-				phy-connection-type = "sgmii-2500";
+				phy-connection-type = "2500base-x";
 				sleep = <&rcpm 0x20000000>;
 			};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/fsl/t104xrdb.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/fsl/t104xrdb.dtsi
@@ -139,12 +139,12 @@
 		fman@400000 {
 			ethernet@e6000 {
 				phy-handle = <&phy_rgmii_0>;
-				phy-connection-type = "rgmii";
+				phy-connection-type = "rgmii-id";
 			};
 
 			ethernet@e8000 {
 				phy-handle = <&phy_rgmii_1>;
-				phy-connection-type = "rgmii";
+				phy-connection-type = "rgmii-id";
 			};
 
 			mdio0: mdio@fc000 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/fsl/t2081si-post.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/fsl/t2081si-post.dtsi
@@ -609,8 +609,8 @@
 /include/ "qoriq-bman1.dtsi"
 
 /include/ "qoriq-fman3-0.dtsi"
-/include/ "qoriq-fman3-0-1g-0.dtsi"
-/include/ "qoriq-fman3-0-1g-1.dtsi"
+/include/ "qoriq-fman3-0-10g-2.dtsi"
+/include/ "qoriq-fman3-0-10g-3.dtsi"
 /include/ "qoriq-fman3-0-1g-2.dtsi"
 /include/ "qoriq-fman3-0-1g-3.dtsi"
 /include/ "qoriq-fman3-0-1g-4.dtsi"
@@ -659,3 +659,19 @@
 		interrupts = <16 2 1 9>;
 	};
 };
+
+&fman0_rx_0x08 {
+	/delete-property/ fsl,fman-10g-port;
+};
+
+&fman0_tx_0x28 {
+	/delete-property/ fsl,fman-10g-port;
+};
+
+&fman0_rx_0x09 {
+	/delete-property/ fsl,fman-10g-port;
+};
+
+&fman0_tx_0x29 {
+	/delete-property/ fsl,fman-10g-port;
+};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/lite5200.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/lite5200.dts
@@ -32,7 +32,7 @@
 		};
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0x00000000 0x04000000>;	// 64MB
 	};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/lite5200b.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/lite5200b.dts
@@ -31,7 +31,7 @@
 		led4 { gpios = <&gpio_simple 2 1>; };
 	};
 
-	memory {
+	memory@0 {
 		reg = <0x00000000 0x10000000>;	// 256MB
 	};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/media5200.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/media5200.dts
@@ -32,7 +32,7 @@
 		};
 	};
 
-	memory {
+	memory@0 {
 		reg = <0x00000000 0x08000000>;	// 128MB RAM
 	};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/mpc5200b.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/mpc5200b.dtsi
@@ -33,7 +33,7 @@
 		};
 	};
 
-	memory: memory {
+	memory: memory@0 {
 		device_type = "memory";
 		reg = <0x00000000 0x04000000>;	// 64MB
 	};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/o2d.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/o2d.dts
@@ -12,7 +12,7 @@
 	model = "ifm,o2d";
 	compatible = "ifm,o2d";
 
-	memory {
+	memory@0 {
 		reg = <0x00000000 0x08000000>;  // 128MB
 	};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/o2d.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/o2d.dtsi
@@ -19,7 +19,7 @@
 	model = "ifm,o2d";
 	compatible = "ifm,o2d";
 
-	memory {
+	memory@0 {
 		reg = <0x00000000 0x04000000>;	// 64MB
 	};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/o2dnt2.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/o2dnt2.dts
@@ -12,7 +12,7 @@
 	model = "ifm,o2dnt2";
 	compatible = "ifm,o2d";
 
-	memory {
+	memory@0 {
 		reg = <0x00000000 0x08000000>;  // 128MB
 	};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/o3dnt.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/o3dnt.dts
@@ -12,7 +12,7 @@
 	model = "ifm,o3dnt";
 	compatible = "ifm,o2d";
 
-	memory {
+	memory@0 {
 		reg = <0x00000000 0x04000000>;  // 64MB
 	};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/pcm032.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/pcm032.dts
@@ -22,7 +22,7 @@
 	model = "phytec,pcm032";
 	compatible = "phytec,pcm032";
 
-	memory {
+	memory@0 {
 		reg = <0x00000000 0x08000000>;	// 128MB
 	};
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/dts/tqm5200.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/dts/tqm5200.dts
@@ -32,7 +32,7 @@
 		};
 	};
 
-	memory {
+	memory@0 {
 		device_type = "memory";
 		reg = <0x00000000 0x04000000>;	// 64MB
 	};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/libfdt_env.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/libfdt_env.h
@@ -6,6 +6,8 @@
 #include <string.h>
 
 #define INT_MAX			((int)(~0U>>1))
+#define UINT32_MAX		((u32)~0U)
+#define INT32_MAX		((s32)(UINT32_MAX >> 1))
 
 #include "of.h"
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/ns16550.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/ns16550.c
@@ -15,6 +15,7 @@
 #include "stdio.h"
 #include "io.h"
 #include "ops.h"
+#include "of.h"
 
 #define UART_DLL	0	/* Out: Divisor Latch Low */
 #define UART_DLM	1	/* Out: Divisor Latch High */
@@ -58,16 +59,20 @@
 	int n;
 	u32 reg_offset;
 
-	if (dt_get_virtual_reg(devp, (void **)&reg_base, 1) < 1)
+	if (dt_get_virtual_reg(devp, (void **)&reg_base, 1) < 1) {
+		printf("virt reg parse fail...\r\n");
 		return -1;
+	}
 
 	n = getprop(devp, "reg-offset", &reg_offset, sizeof(reg_offset));
 	if (n == sizeof(reg_offset))
-		reg_base += reg_offset;
+		reg_base += be32_to_cpu(reg_offset);
 
 	n = getprop(devp, "reg-shift", &reg_shift, sizeof(reg_shift));
 	if (n != sizeof(reg_shift))
 		reg_shift = 0;
+	else
+		reg_shift = be32_to_cpu(reg_shift);
 
 	scdp->open = ns16550_open;
 	scdp->putc = ns16550_putc;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/serial.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/serial.c
@@ -128,7 +128,7 @@
 	         dt_is_compatible(devp, "fsl,cpm2-smc-uart"))
 		rc = cpm_console_init(devp, &serial_cd);
 #endif
-#ifdef CONFIG_PPC_MPC52XX
+#ifdef CONFIG_PPC_MPC52xx
 	else if (dt_is_compatible(devp, "fsl,mpc5200-psc-uart"))
 		rc = mpc5200_psc_console_init(devp, &serial_cd);
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/boot/simple_alloc.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/boot/simple_alloc.c
@@ -114,8 +114,11 @@
 		return ptr;
 
 	new = simple_malloc(size);
-	memcpy(new, ptr, p->size);
-	simple_free(ptr);
+	if (new) {
+		memcpy(new, ptr, p->size);
+		simple_free(ptr);
+	}
+
 	return new;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/configs/85xx-hw.config
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/configs/85xx-hw.config
@@ -2,7 +2,6 @@
 CONFIG_AT803X_PHY=y
 CONFIG_ATA=y
 CONFIG_BLK_DEV_SD=y
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_BLK_DEV_SR=y
 CONFIG_BROADCOM_PHY=y
 CONFIG_C293_PCIE=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/configs/amigaone_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/configs/amigaone_defconfig
@@ -47,7 +47,6 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
 CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_SYM53C8XX_2=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/configs/chrp32_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/configs/chrp32_defconfig
@@ -45,7 +45,6 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
 CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_SYM53C8XX_2=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/configs/g5_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/configs/g5_defconfig
@@ -62,7 +62,6 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
 CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_SPI_ATTRS=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/configs/maple_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/configs/maple_defconfig
@@ -41,7 +41,6 @@
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=y
 CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=y
 CONFIG_SCSI_IPR=y
 CONFIG_ATA=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/configs/mpc885_ads_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/configs/mpc885_ads_defconfig
@@ -39,6 +39,7 @@
 # CONFIG_MTD_CFI_I2 is not set
 CONFIG_MTD_CFI_I4=y
 CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_PHYSMAP=y
 CONFIG_MTD_PHYSMAP_OF=y
 # CONFIG_BLK_DEV is not set
 CONFIG_NETDEVICES=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/configs/pasemi_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/configs/pasemi_defconfig
@@ -60,7 +60,6 @@
 CONFIG_CHR_DEV_ST=y
 CONFIG_CHR_DEV_OSST=y
 CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=y
 CONFIG_CHR_DEV_SCH=y
 CONFIG_SCSI_CONSTANTS=y
@@ -110,7 +109,6 @@
 CONFIG_FB_NVIDIA_I2C=y
 CONFIG_FB_RADEON=y
 # CONFIG_LCD_CLASS_DEVICE is not set
-CONFIG_VGACON_SOFT_SCROLLBACK=y
 CONFIG_LOGO=y
 CONFIG_SOUND=y
 CONFIG_SND=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/configs/pmac32_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/configs/pmac32_defconfig
@@ -119,7 +119,6 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
 CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_FC_ATTRS=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/configs/powernv_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/configs/powernv_defconfig
@@ -111,7 +111,6 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_BLK_DEV_SR=m
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_SCAN_ASYNC=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/configs/ppc64_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/configs/ppc64_defconfig
@@ -110,7 +110,6 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_FC_ATTRS=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/configs/ppc64e_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/configs/ppc64e_defconfig
@@ -60,7 +60,6 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
 CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_FC_ATTRS=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/configs/ppc6xx_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/configs/ppc6xx_defconfig
@@ -253,8 +253,6 @@
 CONFIG_ATM_BR2684=m
 CONFIG_BRIDGE=m
 CONFIG_VLAN_8021Q=m
-CONFIG_DECNET=m
-CONFIG_DECNET_ROUTER=y
 CONFIG_IPX=m
 CONFIG_ATALK=m
 CONFIG_DEV_APPLETALK=m
@@ -372,7 +370,6 @@
 CONFIG_CHR_DEV_ST=m
 CONFIG_CHR_DEV_OSST=m
 CONFIG_BLK_DEV_SR=m
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=y
 CONFIG_CHR_DEV_SCH=m
 CONFIG_SCSI_ENCLOSURE=m
@@ -778,7 +775,6 @@
 CONFIG_FB_SM501=m
 CONFIG_FB_IBM_GXT4500=y
 CONFIG_LCD_PLATFORM=m
-CONFIG_VGACON_SOFT_SCROLLBACK=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
 CONFIG_LOGO=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/configs/pseries_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/configs/pseries_defconfig
@@ -97,7 +97,6 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=m
 CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_FC_ATTRS=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/configs/skiroot_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/configs/skiroot_defconfig
@@ -83,7 +83,6 @@
 # CONFIG_OCXL is not set
 CONFIG_BLK_DEV_SD=m
 CONFIG_BLK_DEV_SR=m
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_SCAN_ASYNC=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/Kbuild
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/Kbuild
@@ -10,4 +10,3 @@
 generic-y += mcs_spinlock.h
 generic-y += preempt.h
 generic-y += vtime.h
-generic-y += msi.h
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/archrandom.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/archrandom.h
@@ -6,44 +6,35 @@
 
 #include <asm/machdep.h>
 
-static inline int arch_get_random_long(unsigned long *v)
+static inline bool arch_get_random_long(unsigned long *v)
 {
-	return 0;
+	return false;
 }
 
-static inline int arch_get_random_int(unsigned int *v)
+static inline bool arch_get_random_int(unsigned int *v)
 {
-	return 0;
+	return false;
 }
 
-static inline int arch_get_random_seed_long(unsigned long *v)
+static inline bool arch_get_random_seed_long(unsigned long *v)
 {
 	if (ppc_md.get_random_seed)
 		return ppc_md.get_random_seed(v);
 
-	return 0;
+	return false;
 }
-static inline int arch_get_random_seed_int(unsigned int *v)
+
+static inline bool arch_get_random_seed_int(unsigned int *v)
 {
 	unsigned long val;
-	int rc;
+	bool rc;
 
-	rc = arch_get_random_long(&val);
+	rc = arch_get_random_seed_long(&val);
 	if (rc)
 		*v = val;
 
 	return rc;
 }
-
-static inline int arch_has_random(void)
-{
-	return 0;
-}
-
-static inline int arch_has_random_seed(void)
-{
-	return !!ppc_md.get_random_seed;
-}
 #endif /* CONFIG_ARCH_RANDOM */
 
 #ifdef CONFIG_PPC_POWERNV
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/asm-prototypes.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/asm-prototypes.h
@@ -152,9 +152,12 @@
 /* Patch sites */
 extern s32 patch__call_flush_count_cache;
 extern s32 patch__flush_count_cache_return;
+extern s32 patch__flush_link_stack_return;
+extern s32 patch__call_kvm_flush_link_stack;
 extern s32 patch__memset_nocache, patch__memcpy_nocache;
 
 extern long flush_count_cache;
+extern long kvm_flush_link_stack;
 
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
 void kvmppc_save_tm_hv(struct kvm_vcpu *vcpu, u64 msr, bool preserve_nv);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/barrier.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/barrier.h
@@ -44,6 +44,8 @@
 #    define SMPWMB      eieio
 #endif
 
+/* clang defines this macro for a builtin, which will not work with runtime patching */
+#undef __lwsync
 #define __lwsync()	__asm__ __volatile__ (stringify_in_c(LWSYNC) : : :"memory")
 #define dma_rmb()	__lwsync()
 #define dma_wmb()	__asm__ __volatile__ (stringify_in_c(SMPWMB) : : :"memory")
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/bitops.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/bitops.h
@@ -217,15 +217,34 @@
  */
 static __inline__ int fls(unsigned int x)
 {
-	return 32 - __builtin_clz(x);
+	int lz;
+
+	if (__builtin_constant_p(x))
+		return x ? 32 - __builtin_clz(x) : 0;
+	asm("cntlzw %0,%1" : "=r" (lz) : "r" (x));
+	return 32 - lz;
 }
 
 #include <asm-generic/bitops/builtin-__fls.h>
 
+/*
+ * 64-bit can do this using one cntlzd (count leading zeroes doubleword)
+ * instruction; for 32-bit we use the generic version, which does two
+ * 32-bit fls calls.
+ */
+#ifdef CONFIG_PPC64
 static __inline__ int fls64(__u64 x)
 {
-	return 64 - __builtin_clzll(x);
+	int lz;
+
+	if (__builtin_constant_p(x))
+		return x ? 64 - __builtin_clzll(x) : 0;
+	asm("cntlzd %0,%1" : "=r" (lz) : "r" (x));
+	return 64 - lz;
 }
+#else
+#include <asm-generic/bitops/fls64.h>
+#endif
 
 #ifdef CONFIG_PPC64
 unsigned int __arch_hweight8(unsigned int w);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/book3s/32/kup.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/book3s/32/kup.h
@@ -2,6 +2,7 @@
 #ifndef _ASM_POWERPC_BOOK3S_32_KUP_H
 #define _ASM_POWERPC_BOOK3S_32_KUP_H
 
+#include <asm/bug.h>
 #include <asm/book3s/32/mmu-hash.h>
 
 #ifdef __ASSEMBLY__
@@ -75,7 +76,7 @@
 
 .macro kuap_check	current, gpr
 #ifdef CONFIG_PPC_KUAP_DEBUG
-	lwz	\gpr2, KUAP(thread)
+	lwz	\gpr, THREAD + KUAP(\current)
 999:	twnei	\gpr, 0
 	EMIT_BUG_ENTRY 999b, __FILE__, __LINE__, (BUGFLAG_WARNING | BUGFLAG_ONCE)
 #endif
@@ -102,11 +103,13 @@
 	isync();	/* Context sync required after mtsrin() */
 }
 
-static inline void allow_user_access(void __user *to, const void __user *from, u32 size)
+static __always_inline void allow_user_access(void __user *to, const void __user *from,
+					      u32 size, unsigned long dir)
 {
 	u32 addr, end;
 
-	if (__builtin_constant_p(to) && to == NULL)
+	BUILD_BUG_ON(!__builtin_constant_p(dir));
+	if (!(dir & KUAP_WRITE))
 		return;
 
 	addr = (__force u32)to;
@@ -119,11 +122,16 @@
 	kuap_update_sr(mfsrin(addr) & ~SR_KS, addr, end);	/* Clear Ks */
 }
 
-static inline void prevent_user_access(void __user *to, const void __user *from, u32 size)
+static __always_inline void prevent_user_access(void __user *to, const void __user *from,
+						u32 size, unsigned long dir)
 {
 	u32 addr = (__force u32)to;
 	u32 end = min(addr + size, TASK_SIZE);
 
+	BUILD_BUG_ON(!__builtin_constant_p(dir));
+	if (!(dir & KUAP_WRITE))
+		return;
+
 	if (!addr || addr >= TASK_SIZE || !size)
 		return;
 
@@ -131,12 +139,17 @@
 	kuap_update_sr(mfsrin(addr) | SR_KS, addr, end);	/* set Ks */
 }
 
-static inline bool bad_kuap_fault(struct pt_regs *regs, bool is_write)
+static inline bool
+bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write)
 {
+	unsigned long begin = regs->kuap & 0xf0000000;
+	unsigned long end = regs->kuap << 28;
+
 	if (!is_write)
 		return false;
 
-	return WARN(!regs->kuap, "Bug: write fault blocked by segment registers !");
+	return WARN(address < begin || address >= end,
+		    "Bug: write fault blocked by segment registers !");
 }
 
 #endif /* CONFIG_PPC_KUAP */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/book3s/32/pgalloc.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/book3s/32/pgalloc.h
@@ -49,7 +49,6 @@
 
 #define get_hugepd_cache_index(x)  (x)
 
-#ifdef CONFIG_SMP
 static inline void pgtable_free_tlb(struct mmu_gather *tlb,
 				    void *table, int shift)
 {
@@ -66,13 +65,6 @@
 
 	pgtable_free(table, shift);
 }
-#else
-static inline void pgtable_free_tlb(struct mmu_gather *tlb,
-				    void *table, int shift)
-{
-	pgtable_free(table, shift);
-}
-#endif
 
 static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table,
 				  unsigned long address)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/book3s/32/pgtable.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/book3s/32/pgtable.h
@@ -37,8 +37,10 @@
  */
 #ifdef CONFIG_PTE_64BIT
 #define PTE_RPN_MASK	(~((1ULL << PTE_RPN_SHIFT) - 1))
+#define MAX_POSSIBLE_PHYSMEM_BITS 36
 #else
 #define PTE_RPN_MASK	(~((1UL << PTE_RPN_SHIFT) - 1))
+#define MAX_POSSIBLE_PHYSMEM_BITS 32
 #endif
 
 /*
@@ -555,9 +557,9 @@
 	if (pte_val(*ptep) & _PAGE_HASHPTE)
 		flush_hash_entry(mm, ptep, addr);
 	__asm__ __volatile__("\
-		stw%U0%X0 %2,%0\n\
+		stw%X0 %2,%0\n\
 		eieio\n\
-		stw%U0%X0 %L2,%1"
+		stw%X1 %L2,%1"
 	: "=m" (*ptep), "=m" (*((unsigned char *)ptep+4))
 	: "r" (pte) : "memory");
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/book3s/64/hash-4k.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/book3s/64/hash-4k.h
@@ -13,20 +13,19 @@
  */
 #define MAX_EA_BITS_PER_CONTEXT		46
 
-#define REGION_SHIFT		(MAX_EA_BITS_PER_CONTEXT - 2)
 
 /*
- * Our page table limit us to 64TB. Hence for the kernel mapping,
- * each MAP area is limited to 16 TB.
- * The four map areas are:  linear mapping, vmap, IO and vmemmap
+ * Our page table limit us to 64TB. For 64TB physical memory, we only need 64GB
+ * of vmemmap space. To better support sparse memory layout, we use 61TB
+ * linear map range, 1TB of vmalloc, 1TB of I/O and 1TB of vmememmap.
  */
+#define REGION_SHIFT		(40)
 #define H_KERN_MAP_SIZE		(ASM_CONST(1) << REGION_SHIFT)
 
 /*
- * Define the address range of the kernel non-linear virtual area
- * 16TB
+ * Define the address range of the kernel non-linear virtual area (61TB)
  */
-#define H_KERN_VIRT_START	ASM_CONST(0xc000100000000000)
+#define H_KERN_VIRT_START	ASM_CONST(0xc0003d0000000000)
 
 #ifndef __ASSEMBLY__
 #define H_PTE_TABLE_SIZE	(sizeof(pte_t) << H_PTE_INDEX_SIZE)
@@ -85,6 +84,34 @@
 #endif
 
 /*
+ * With 4K page size the real_pte machinery is all nops.
+ */
+static inline real_pte_t __real_pte(pte_t pte, pte_t *ptep, int offset)
+{
+	return (real_pte_t){pte};
+}
+
+#define __rpte_to_pte(r)	((r).pte)
+
+static inline unsigned long __rpte_to_hidx(real_pte_t rpte, unsigned long index)
+{
+	return pte_val(__rpte_to_pte(rpte)) >> H_PAGE_F_GIX_SHIFT;
+}
+
+#define pte_iterate_hashed_subpages(rpte, psize, va, index, shift)       \
+	do {							         \
+		index = 0;					         \
+		shift = mmu_psize_defs[psize].shift;		         \
+
+#define pte_iterate_hashed_end() } while(0)
+
+/*
+ * We expect this to be called only for user addresses or kernel virtual
+ * addresses other than the linear mapping.
+ */
+#define pte_pagesize_index(mm, addr, pte)	MMU_PAGE_4K
+
+/*
  * 4K PTE format is different from 64K PTE format. Saving the hash_slot is just
  * a matter of returning the PTE bits that need to be modified. On 64K PTE,
  * things are a little more involved and hence needs many more parameters to
@@ -156,6 +183,12 @@
 extern int hash__has_transparent_hugepage(void);
 #endif
 
+static inline pmd_t hash__pmd_mkdevmap(pmd_t pmd)
+{
+	BUG();
+	return pmd;
+}
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* _ASM_POWERPC_BOOK3S_64_HASH_4K_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/book3s/64/hash-64k.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/book3s/64/hash-64k.h
@@ -246,7 +246,7 @@
  */
 static inline int hash__pmd_trans_huge(pmd_t pmd)
 {
-	return !!((pmd_val(pmd) & (_PAGE_PTE | H_PAGE_THP_HUGE)) ==
+	return !!((pmd_val(pmd) & (_PAGE_PTE | H_PAGE_THP_HUGE | _PAGE_DEVMAP)) ==
 		  (_PAGE_PTE | H_PAGE_THP_HUGE));
 }
 
@@ -272,6 +272,12 @@
 				       unsigned long addr, pmd_t *pmdp);
 extern int hash__has_transparent_hugepage(void);
 #endif /*  CONFIG_TRANSPARENT_HUGEPAGE */
+
+static inline pmd_t hash__pmd_mkdevmap(pmd_t pmd)
+{
+	return __pmd(pmd_val(pmd) | (_PAGE_PTE | H_PAGE_THP_HUGE | _PAGE_DEVMAP));
+}
+
 #endif	/* __ASSEMBLY__ */
 
 #endif /* _ASM_POWERPC_BOOK3S_64_HASH_64K_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/book3s/64/kup-radix.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/book3s/64/kup-radix.h
@@ -11,13 +11,12 @@
 
 #ifdef __ASSEMBLY__
 
-.macro kuap_restore_amr	gpr
 #ifdef CONFIG_PPC_KUAP
+.macro kuap_restore_amr	gpr
 	BEGIN_MMU_FTR_SECTION_NESTED(67)
 	ld	\gpr, STACK_REGS_KUAP(r1)
 	mtspr	SPRN_AMR, \gpr
 	END_MMU_FTR_SECTION_NESTED_IFSET(MMU_FTR_RADIX_KUAP, 67)
-#endif
 .endm
 
 .macro kuap_check_amr gpr1, gpr2
@@ -31,6 +30,7 @@
 	END_MMU_FTR_SECTION_NESTED_IFSET(MMU_FTR_RADIX_KUAP, 67)
 #endif
 .endm
+#endif
 
 .macro kuap_save_amr_and_lock gpr1, gpr2, use_cr, msr_pr_cr
 #ifdef CONFIG_PPC_KUAP
@@ -54,6 +54,10 @@
 
 #else /* !__ASSEMBLY__ */
 
+#include <linux/jump_label.h>
+
+DECLARE_STATIC_KEY_FALSE(uaccess_flush_key);
+
 #ifdef CONFIG_PPC_KUAP
 
 #include <asm/reg.h>
@@ -77,32 +81,39 @@
 	isync();
 }
 
-static inline void allow_user_access(void __user *to, const void __user *from,
-				     unsigned long size)
+static inline bool
+bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write)
+{
+	return WARN(mmu_has_feature(MMU_FTR_RADIX_KUAP) &&
+		    (regs->kuap & (is_write ? AMR_KUAP_BLOCK_WRITE : AMR_KUAP_BLOCK_READ)),
+		    "Bug: %s fault blocked by AMR!", is_write ? "Write" : "Read");
+}
+#else /* CONFIG_PPC_KUAP */
+static inline void kuap_restore_amr(struct pt_regs *regs, unsigned long amr) { }
+static inline void set_kuap(unsigned long value) { }
+#endif /* !CONFIG_PPC_KUAP */
+
+static __always_inline void allow_user_access(void __user *to, const void __user *from,
+					      unsigned long size, unsigned long dir)
 {
 	// This is written so we can resolve to a single case at build time
-	if (__builtin_constant_p(to) && to == NULL)
+	BUILD_BUG_ON(!__builtin_constant_p(dir));
+	if (dir == KUAP_READ)
 		set_kuap(AMR_KUAP_BLOCK_WRITE);
-	else if (__builtin_constant_p(from) && from == NULL)
+	else if (dir == KUAP_WRITE)
 		set_kuap(AMR_KUAP_BLOCK_READ);
 	else
 		set_kuap(0);
 }
 
 static inline void prevent_user_access(void __user *to, const void __user *from,
-				       unsigned long size)
+				       unsigned long size, unsigned long dir)
 {
 	set_kuap(AMR_KUAP_BLOCKED);
+	if (static_branch_unlikely(&uaccess_flush_key))
+		do_uaccess_flush();
 }
 
-static inline bool bad_kuap_fault(struct pt_regs *regs, bool is_write)
-{
-	return WARN(mmu_has_feature(MMU_FTR_RADIX_KUAP) &&
-		    (regs->kuap & (is_write ? AMR_KUAP_BLOCK_WRITE : AMR_KUAP_BLOCK_READ)),
-		    "Bug: %s fault blocked by AMR!", is_write ? "Write" : "Read");
-}
-#endif /* CONFIG_PPC_KUAP */
-
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_POWERPC_BOOK3S_64_KUP_RADIX_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/book3s/64/mmu-hash.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/book3s/64/mmu-hash.h
@@ -600,8 +600,11 @@
  *
  */
 #define MAX_USER_CONTEXT	((ASM_CONST(1) << CONTEXT_BITS) - 2)
+
+// The + 2 accounts for INVALID_REGION and 1 more to avoid overlap with kernel
 #define MIN_USER_CONTEXT	(MAX_KERNEL_CTX_CNT + MAX_VMALLOC_CTX_CNT + \
-				 MAX_IO_CTX_CNT + MAX_VMEMMAP_CTX_CNT)
+				 MAX_IO_CTX_CNT + MAX_VMEMMAP_CTX_CNT + 2)
+
 /*
  * For platforms that support on 65bit VA we limit the context bits
  */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/book3s/64/mmu.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/book3s/64/mmu.h
@@ -225,14 +225,14 @@
 
 extern void hash__setup_initial_memory_limit(phys_addr_t first_memblock_base,
 					 phys_addr_t first_memblock_size);
-extern void radix__setup_initial_memory_limit(phys_addr_t first_memblock_base,
-					 phys_addr_t first_memblock_size);
 static inline void setup_initial_memory_limit(phys_addr_t first_memblock_base,
 					      phys_addr_t first_memblock_size)
 {
-	if (early_radix_enabled())
-		return radix__setup_initial_memory_limit(first_memblock_base,
-						   first_memblock_size);
+	/*
+	 * Hash has more strict restrictions. At this point we don't
+	 * know which translations we will pick. Hence go with hash
+	 * restrictions.
+	 */
 	return hash__setup_initial_memory_limit(first_memblock_base,
 					   first_memblock_size);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/book3s/64/pgalloc.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/book3s/64/pgalloc.h
@@ -19,9 +19,7 @@
 extern pmd_t *pmd_fragment_alloc(struct mm_struct *, unsigned long);
 extern void pmd_fragment_free(unsigned long *);
 extern void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int shift);
-#ifdef CONFIG_SMP
 extern void __tlb_remove_table(void *_table);
-#endif
 void pte_frag_destroy(void *pte_frag);
 
 static inline pgd_t *radix__pgd_alloc(struct mm_struct *mm)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/book3s/64/pgtable.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/book3s/64/pgtable.h
@@ -324,32 +324,6 @@
 
 #ifndef __ASSEMBLY__
 
-/*
- * This is the default implementation of various PTE accessors, it's
- * used in all cases except Book3S with 64K pages where we have a
- * concept of sub-pages
- */
-#ifndef __real_pte
-
-#define __real_pte(e, p, o)		((real_pte_t){(e)})
-#define __rpte_to_pte(r)	((r).pte)
-#define __rpte_to_hidx(r,index)	(pte_val(__rpte_to_pte(r)) >> H_PAGE_F_GIX_SHIFT)
-
-#define pte_iterate_hashed_subpages(rpte, psize, va, index, shift)       \
-	do {							         \
-		index = 0;					         \
-		shift = mmu_psize_defs[psize].shift;		         \
-
-#define pte_iterate_hashed_end() } while(0)
-
-/*
- * We expect this to be called only for user addresses or kernel virtual
- * addresses other than the linear mapping.
- */
-#define pte_pagesize_index(mm, addr, pte)	MMU_PAGE_4K
-
-#endif /* __real_pte */
-
 static inline unsigned long pte_update(struct mm_struct *mm, unsigned long addr,
 				       pte_t *ptep, unsigned long clr,
 				       unsigned long set, int huge)
@@ -998,10 +972,25 @@
 #define pud_page_vaddr(pud)	__va(pud_val(pud) & ~PUD_MASKED_BITS)
 #define pgd_page_vaddr(pgd)	__va(pgd_val(pgd) & ~PGD_MASKED_BITS)
 
-#define pgd_index(address) (((address) >> (PGDIR_SHIFT)) & (PTRS_PER_PGD - 1))
-#define pud_index(address) (((address) >> (PUD_SHIFT)) & (PTRS_PER_PUD - 1))
-#define pmd_index(address) (((address) >> (PMD_SHIFT)) & (PTRS_PER_PMD - 1))
-#define pte_index(address) (((address) >> (PAGE_SHIFT)) & (PTRS_PER_PTE - 1))
+static inline unsigned long pgd_index(unsigned long address)
+{
+	return (address >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1);
+}
+
+static inline unsigned long pud_index(unsigned long address)
+{
+	return (address >> PUD_SHIFT) & (PTRS_PER_PUD - 1);
+}
+
+static inline unsigned long pmd_index(unsigned long address)
+{
+	return (address >> PMD_SHIFT) & (PTRS_PER_PMD - 1);
+}
+
+static inline unsigned long pte_index(unsigned long address)
+{
+	return (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
+}
 
 /*
  * Find an entry in a page-table-directory.  We combine the address region
@@ -1303,7 +1292,9 @@
 
 static inline pmd_t pmd_mkdevmap(pmd_t pmd)
 {
-	return __pmd(pmd_val(pmd) | (_PAGE_PTE | _PAGE_DEVMAP));
+	if (radix_enabled())
+		return radix__pmd_mkdevmap(pmd);
+	return hash__pmd_mkdevmap(pmd);
 }
 
 static inline int pmd_devmap(pmd_t pmd)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/book3s/64/radix.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/book3s/64/radix.h
@@ -206,8 +206,10 @@
 	 * from ptesync, it should probably go into update_mmu_cache, rather
 	 * than set_pte_at (which is used to set ptes unrelated to faults).
 	 *
-	 * Spurious faults to vmalloc region are not tolerated, so there is
-	 * a ptesync in flush_cache_vmap.
+	 * Spurious faults from the kernel memory are not tolerated, so there
+	 * is a ptesync in flush_cache_vmap, and __map_kernel_page() follows
+	 * the pte update sequence from ISA Book III 6.10 Translation Table
+	 * Update Synchronization Requirements.
 	 */
 }
 
@@ -263,6 +265,11 @@
 }
 #endif
 
+static inline pmd_t radix__pmd_mkdevmap(pmd_t pmd)
+{
+	return __pmd(pmd_val(pmd) | (_PAGE_PTE | _PAGE_DEVMAP));
+}
+
 extern int __meminit radix__vmemmap_create_mapping(unsigned long start,
 					     unsigned long page_size,
 					     unsigned long phys);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/bpf_perf_event.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/bpf_perf_event.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_POWERPC_BPF_PERF_EVENT_H
+#define _ASM_POWERPC_BPF_PERF_EVENT_H
+
+#include <asm/ptrace.h>
+
+typedef struct user_pt_regs bpf_user_pt_regs_t;
+
+#endif /* _ASM_POWERPC_BPF_PERF_EVENT_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/cache.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/cache.h
@@ -55,42 +55,48 @@
 
 extern struct ppc64_caches ppc64_caches;
 
-static inline u32 l1_cache_shift(void)
+static inline u32 l1_dcache_shift(void)
 {
 	return ppc64_caches.l1d.log_block_size;
 }
 
-static inline u32 l1_cache_bytes(void)
+static inline u32 l1_dcache_bytes(void)
 {
 	return ppc64_caches.l1d.block_size;
 }
+
+static inline u32 l1_icache_shift(void)
+{
+	return ppc64_caches.l1i.log_block_size;
+}
+
+static inline u32 l1_icache_bytes(void)
+{
+	return ppc64_caches.l1i.block_size;
+}
 #else
-static inline u32 l1_cache_shift(void)
+static inline u32 l1_dcache_shift(void)
 {
 	return L1_CACHE_SHIFT;
 }
 
-static inline u32 l1_cache_bytes(void)
+static inline u32 l1_dcache_bytes(void)
 {
 	return L1_CACHE_BYTES;
 }
-#endif
-#endif /* ! __ASSEMBLY__ */
 
-#if defined(__ASSEMBLY__)
-/*
- * For a snooping icache, we still need a dummy icbi to purge all the
- * prefetched instructions from the ifetch buffers. We also need a sync
- * before the icbi to order the the actual stores to memory that might
- * have modified instructions with the icbi.
- */
-#define PURGE_PREFETCHED_INS	\
-	sync;			\
-	icbi	0,r3;		\
-	sync;			\
-	isync
+static inline u32 l1_icache_shift(void)
+{
+	return L1_CACHE_SHIFT;
+}
+
+static inline u32 l1_icache_bytes(void)
+{
+	return L1_CACHE_BYTES;
+}
+
+#endif
 
-#else
 #define __read_mostly __attribute__((__section__(".data..read_mostly")))
 
 #ifdef CONFIG_PPC_BOOK3S_32
@@ -124,6 +130,17 @@
 {
 	__asm__ __volatile__ ("dcbst 0, %0" : : "r"(addr) : "memory");
 }
+
+static inline void icbi(void *addr)
+{
+	asm volatile ("icbi 0, %0" : : "r"(addr) : "memory");
+}
+
+static inline void iccci(void *addr)
+{
+	asm volatile ("iccci 0, %0" : : "r"(addr) : "memory");
+}
+
 #endif /* !__ASSEMBLY__ */
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_CACHE_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/cacheflush.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/cacheflush.h
@@ -42,29 +42,25 @@
 #define flush_dcache_mmap_lock(mapping)		do { } while (0)
 #define flush_dcache_mmap_unlock(mapping)	do { } while (0)
 
-extern void flush_icache_range(unsigned long, unsigned long);
+void flush_icache_range(unsigned long start, unsigned long stop);
 extern void flush_icache_user_range(struct vm_area_struct *vma,
 				    struct page *page, unsigned long addr,
 				    int len);
-extern void __flush_dcache_icache(void *page_va);
 extern void flush_dcache_icache_page(struct page *page);
-#if defined(CONFIG_PPC32) && !defined(CONFIG_BOOKE)
-extern void __flush_dcache_icache_phys(unsigned long physaddr);
-#else
-static inline void __flush_dcache_icache_phys(unsigned long physaddr)
-{
-	BUG();
-}
-#endif
+void __flush_dcache_icache(void *page);
 
-/*
- * Write any modified data cache blocks out to memory and invalidate them.
- * Does not invalidate the corresponding instruction cache blocks.
+/**
+ * flush_dcache_range(): Write any modified data cache blocks out to memory and
+ * invalidate them. Does not invalidate the corresponding instruction cache
+ * blocks.
+ *
+ * @start: the start address
+ * @stop: the stop address (exclusive)
  */
 static inline void flush_dcache_range(unsigned long start, unsigned long stop)
 {
-	unsigned long shift = l1_cache_shift();
-	unsigned long bytes = l1_cache_bytes();
+	unsigned long shift = l1_dcache_shift();
+	unsigned long bytes = l1_dcache_bytes();
 	void *addr = (void *)(start & ~(bytes - 1));
 	unsigned long size = stop - (unsigned long)addr + (bytes - 1);
 	unsigned long i;
@@ -89,8 +85,8 @@
  */
 static inline void clean_dcache_range(unsigned long start, unsigned long stop)
 {
-	unsigned long shift = l1_cache_shift();
-	unsigned long bytes = l1_cache_bytes();
+	unsigned long shift = l1_dcache_shift();
+	unsigned long bytes = l1_dcache_bytes();
 	void *addr = (void *)(start & ~(bytes - 1));
 	unsigned long size = stop - (unsigned long)addr + (bytes - 1);
 	unsigned long i;
@@ -108,8 +104,8 @@
 static inline void invalidate_dcache_range(unsigned long start,
 					   unsigned long stop)
 {
-	unsigned long shift = l1_cache_shift();
-	unsigned long bytes = l1_cache_bytes();
+	unsigned long shift = l1_dcache_shift();
+	unsigned long bytes = l1_dcache_bytes();
 	void *addr = (void *)(start & ~(bytes - 1));
 	unsigned long size = stop - (unsigned long)addr + (bytes - 1);
 	unsigned long i;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/code-patching.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/code-patching.h
@@ -22,6 +22,7 @@
 #define BRANCH_ABSOLUTE	0x2
 
 bool is_offset_in_branch_range(long offset);
+bool is_offset_in_cond_branch_range(long offset);
 unsigned int create_branch(const unsigned int *addr,
 			   unsigned long target, int flags);
 unsigned int create_cond_branch(const unsigned int *addr,
@@ -72,7 +73,7 @@
 #endif
 
 #define OP_RT_RA_MASK	0xffff0000UL
-#define LIS_R2		0x3c020000UL
+#define LIS_R2		0x3c400000UL
 #define ADDIS_R2_R12	0x3c4c0000UL
 #define ADDI_R2_R2	0x38420000UL
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/cpm1.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/cpm1.h
@@ -68,6 +68,7 @@
 #define PROFF_SPI	((uint)0x0180)
 #define PROFF_SCC3	((uint)0x0200)
 #define PROFF_SMC1	((uint)0x0280)
+#define PROFF_DSP1	((uint)0x02c0)
 #define PROFF_SCC4	((uint)0x0300)
 #define PROFF_SMC2	((uint)0x0380)
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/cpu_has_feature.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/cpu_has_feature.h
@@ -7,7 +7,7 @@
 #include <linux/bug.h>
 #include <asm/cputable.h>
 
-static inline bool early_cpu_has_feature(unsigned long feature)
+static __always_inline bool early_cpu_has_feature(unsigned long feature)
 {
 	return !!((CPU_FTRS_ALWAYS & feature) ||
 		  (CPU_FTRS_POSSIBLE & cur_cpu_spec->cpu_features & feature));
@@ -46,7 +46,7 @@
 	return static_branch_likely(&cpu_feature_keys[i]);
 }
 #else
-static inline bool cpu_has_feature(unsigned long feature)
+static __always_inline bool cpu_has_feature(unsigned long feature)
 {
 	return early_cpu_has_feature(feature);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/cputable.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/cputable.h
@@ -367,7 +367,7 @@
 	    CPU_FTR_PPC_LE | CPU_FTR_NEED_PAIRED_STWCX)
 #define CPU_FTRS_82XX	(CPU_FTR_COMMON | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_NOEXECUTE)
 #define CPU_FTRS_G2_LE	(CPU_FTR_COMMON | CPU_FTR_MAYBE_CAN_DOZE | \
-	    CPU_FTR_MAYBE_CAN_NAP)
+	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_NOEXECUTE)
 #define CPU_FTRS_E300	(CPU_FTR_MAYBE_CAN_DOZE | \
 	    CPU_FTR_MAYBE_CAN_NAP | \
 	    CPU_FTR_COMMON  | CPU_FTR_NOEXECUTE)
@@ -407,7 +407,6 @@
 	    CPU_FTR_DBELL | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
 	    CPU_FTR_DEBUG_LVL_EXC | CPU_FTR_EMB_HV | CPU_FTR_ALTIVEC_COMP | \
 	    CPU_FTR_CELL_TB_BUG | CPU_FTR_SMT)
-#define CPU_FTRS_GENERIC_32	(CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN)
 
 /* 64-bit CPUs */
 #define CPU_FTRS_PPC970	(CPU_FTR_LWSYNC | \
@@ -507,8 +506,6 @@
 	    CPU_FTRS_7447 | CPU_FTRS_7447A | CPU_FTRS_82XX |
 	    CPU_FTRS_G2_LE | CPU_FTRS_E300 | CPU_FTRS_E300C2 |
 	    CPU_FTRS_CLASSIC32 |
-#else
-	    CPU_FTRS_GENERIC_32 |
 #endif
 #ifdef CONFIG_PPC_8xx
 	    CPU_FTRS_8XX |
@@ -585,8 +582,6 @@
 	    CPU_FTRS_7447 & CPU_FTRS_7447A & CPU_FTRS_82XX &
 	    CPU_FTRS_G2_LE & CPU_FTRS_E300 & CPU_FTRS_E300C2 &
 	    CPU_FTRS_CLASSIC32 &
-#else
-	    CPU_FTRS_GENERIC_32 &
 #endif
 #ifdef CONFIG_PPC_8xx
 	    CPU_FTRS_8XX &
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/cputhreads.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/cputhreads.h
@@ -3,6 +3,7 @@
 #define _ASM_POWERPC_CPUTHREADS_H
 
 #ifndef __ASSEMBLY__
+#include <asm/cpu_has_feature.h>
 #include <linux/cpumask.h>
 #include <asm/cpu_has_feature.h>
 
@@ -99,6 +100,36 @@
 	return cpu | (threads_per_core - 1);
 }
 
+/*
+ * tlb_thread_siblings are siblings which share a TLB. This is not
+ * architected, is not something a hypervisor could emulate and a future
+ * CPU may change behaviour even in compat mode, so this should only be
+ * used on PowerNV, and only with care.
+ */
+static inline int cpu_first_tlb_thread_sibling(int cpu)
+{
+	if (cpu_has_feature(CPU_FTR_ARCH_300) && (threads_per_core == 8))
+		return cpu & ~0x6;	/* Big Core */
+	else
+		return cpu_first_thread_sibling(cpu);
+}
+
+static inline int cpu_last_tlb_thread_sibling(int cpu)
+{
+	if (cpu_has_feature(CPU_FTR_ARCH_300) && (threads_per_core == 8))
+		return cpu | 0x6;	/* Big Core */
+	else
+		return cpu_last_thread_sibling(cpu);
+}
+
+static inline int cpu_tlb_thread_sibling_step(void)
+{
+	if (cpu_has_feature(CPU_FTR_ARCH_300) && (threads_per_core == 8))
+		return 2;		/* Big Core */
+	else
+		return 1;
+}
+
 static inline u32 get_tensr(void)
 {
 #ifdef	CONFIG_BOOKE
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/dcr-native.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/dcr-native.h
@@ -53,8 +53,8 @@
 #define mfdcr(rn)						\
 	({unsigned int rval;					\
 	if (__builtin_constant_p(rn) && rn < 1024)		\
-		asm volatile("mfdcr %0," __stringify(rn)	\
-		              : "=r" (rval));			\
+		asm volatile("mfdcr %0, %1" : "=r" (rval)	\
+			      : "n" (rn));			\
 	else if (likely(cpu_has_feature(CPU_FTR_INDEXED_DCR)))	\
 		rval = mfdcrx(rn);				\
 	else							\
@@ -64,8 +64,8 @@
 #define mtdcr(rn, v)						\
 do {								\
 	if (__builtin_constant_p(rn) && rn < 1024)		\
-		asm volatile("mtdcr " __stringify(rn) ",%0"	\
-			      : : "r" (v)); 			\
+		asm volatile("mtdcr %0, %1"			\
+			      : : "n" (rn), "r" (v));		\
 	else if (likely(cpu_has_feature(CPU_FTR_INDEXED_DCR)))	\
 		mtdcrx(rn, v);					\
 	else							\
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/drmem.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/drmem.h
@@ -8,31 +8,44 @@
 #ifndef _ASM_POWERPC_LMB_H
 #define _ASM_POWERPC_LMB_H
 
+#include <linux/sched.h>
+
 struct drmem_lmb {
 	u64     base_addr;
 	u32     drc_index;
 	u32     aa_index;
 	u32     flags;
-#ifdef CONFIG_MEMORY_HOTPLUG
-	int	nid;
-#endif
 };
 
 struct drmem_lmb_info {
 	struct drmem_lmb        *lmbs;
 	int                     n_lmbs;
-	u32                     lmb_size;
+	u64                     lmb_size;
 };
 
 extern struct drmem_lmb_info *drmem_info;
 
+static inline struct drmem_lmb *drmem_lmb_next(struct drmem_lmb *lmb,
+					       const struct drmem_lmb *start)
+{
+	/*
+	 * DLPAR code paths can take several milliseconds per element
+	 * when interacting with firmware. Ensure that we don't
+	 * unfairly monopolize the CPU.
+	 */
+	if (((++lmb - start) % 16) == 0)
+		cond_resched();
+
+	return lmb;
+}
+
 #define for_each_drmem_lmb_in_range(lmb, start, end)		\
-	for ((lmb) = (start); (lmb) <= (end); (lmb)++)
+	for ((lmb) = (start); (lmb) < (end); lmb = drmem_lmb_next(lmb, start))
 
 #define for_each_drmem_lmb(lmb)					\
 	for_each_drmem_lmb_in_range((lmb),			\
 		&drmem_info->lmbs[0],				\
-		&drmem_info->lmbs[drmem_info->n_lmbs - 1])
+		&drmem_info->lmbs[drmem_info->n_lmbs])
 
 /*
  * The of_drconf_cell_v1 struct defines the layout of the LMB data
@@ -66,7 +79,7 @@
 #define DRCONF_MEM_AI_INVALID	0x00000040
 #define DRCONF_MEM_RESERVED	0x00000080
 
-static inline u32 drmem_lmb_size(void)
+static inline u64 drmem_lmb_size(void)
 {
 	return drmem_info->lmb_size;
 }
@@ -103,22 +116,4 @@
 	lmb->aa_index = 0xffffffff;
 }
 
-#ifdef CONFIG_MEMORY_HOTPLUG
-static inline void lmb_set_nid(struct drmem_lmb *lmb)
-{
-	lmb->nid = memory_add_physaddr_to_nid(lmb->base_addr);
-}
-static inline void lmb_clear_nid(struct drmem_lmb *lmb)
-{
-	lmb->nid = -1;
-}
-#else
-static inline void lmb_set_nid(struct drmem_lmb *lmb)
-{
-}
-static inline void lmb_clear_nid(struct drmem_lmb *lmb)
-{
-}
-#endif
-
 #endif /* _ASM_POWERPC_LMB_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/exception-64s.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/exception-64s.h
@@ -61,11 +61,18 @@
 	nop;								\
 	nop
 
+#define ENTRY_FLUSH_SLOT						\
+	ENTRY_FLUSH_FIXUP_SECTION;					\
+	nop;								\
+	nop;								\
+	nop;
+
 /*
  * r10 must be free to use, r13 must be paca
  */
 #define INTERRUPT_TO_KERNEL						\
-	STF_ENTRY_BARRIER_SLOT
+	STF_ENTRY_BARRIER_SLOT;						\
+	ENTRY_FLUSH_SLOT
 
 /*
  * Macros for annotating the expected destination of (h)rfid
@@ -127,6 +134,9 @@
 	hrfid;								\
 	b	hrfi_flush_fallback
 
+#else /* __ASSEMBLY__ */
+/* Prototype for function defined in exceptions-64s.S */
+void do_uaccess_flush(void);
 #endif /* __ASSEMBLY__ */
 
 #endif	/* _ASM_POWERPC_EXCEPTION_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/fadump-internal.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/fadump-internal.h
@@ -64,12 +64,14 @@
 };
 
 /* fadump memory ranges info */
+#define RNG_NAME_SZ			16
 struct fadump_mrange_info {
-	char				name[16];
+	char				name[RNG_NAME_SZ];
 	struct fadump_memory_range	*mem_ranges;
 	u32				mem_ranges_sz;
 	u32				mem_range_cnt;
 	u32				max_mem_ranges;
+	bool				is_static;
 };
 
 /* Platform specific callback functions */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/feature-fixups.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/feature-fixups.h
@@ -205,6 +205,22 @@
 	FTR_ENTRY_OFFSET 955b-956b;			\
 	.popsection;
 
+#define UACCESS_FLUSH_FIXUP_SECTION			\
+959:							\
+	.pushsection __uaccess_flush_fixup,"a";		\
+	.align 2;					\
+960:							\
+	FTR_ENTRY_OFFSET 959b-960b;			\
+	.popsection;
+
+#define ENTRY_FLUSH_FIXUP_SECTION			\
+957:							\
+	.pushsection __entry_flush_fixup,"a";		\
+	.align 2;					\
+958:							\
+	FTR_ENTRY_OFFSET 957b-958b;			\
+	.popsection;
+
 #define RFI_FLUSH_FIXUP_SECTION				\
 951:							\
 	.pushsection __rfi_flush_fixup,"a";		\
@@ -237,8 +253,11 @@
 #include <linux/types.h>
 
 extern long stf_barrier_fallback;
+extern long entry_flush_fallback;
 extern long __start___stf_entry_barrier_fixup, __stop___stf_entry_barrier_fixup;
 extern long __start___stf_exit_barrier_fixup, __stop___stf_exit_barrier_fixup;
+extern long __start___uaccess_flush_fixup, __stop___uaccess_flush_fixup;
+extern long __start___entry_flush_fixup, __stop___entry_flush_fixup;
 extern long __start___rfi_flush_fixup, __stop___rfi_flush_fixup;
 extern long __start___barrier_nospec_fixup, __stop___barrier_nospec_fixup;
 extern long __start__btb_flush_fixup, __stop__btb_flush_fixup;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/fixmap.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/fixmap.h
@@ -77,7 +77,12 @@
 static inline void __set_fixmap(enum fixed_addresses idx,
 				phys_addr_t phys, pgprot_t flags)
 {
-	map_kernel_page(fix_to_virt(idx), phys, flags);
+	if (__builtin_constant_p(idx))
+		BUILD_BUG_ON(idx >= __end_of_fixed_addresses);
+	else if (WARN_ON(idx >= __end_of_fixed_addresses))
+		return;
+
+	map_kernel_page(__fix_to_virt(idx), phys, flags);
 }
 
 #endif /* !__ASSEMBLY__ */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/ftrace.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/ftrace.h
@@ -96,7 +96,7 @@
 #endif /* PPC64_ELF_ABI_v1 */
 #endif /* CONFIG_FTRACE_SYSCALLS */
 
-#ifdef CONFIG_PPC64
+#if defined(CONFIG_PPC64) && defined(CONFIG_FUNCTION_TRACER)
 #include <asm/paca.h>
 
 static inline void this_cpu_disable_ftrace(void)
@@ -108,9 +108,12 @@
 {
 	get_paca()->ftrace_enabled = 1;
 }
+
+void ftrace_free_init_tramp(void);
 #else /* CONFIG_PPC64 */
 static inline void this_cpu_disable_ftrace(void) { }
 static inline void this_cpu_enable_ftrace(void) { }
+static inline void ftrace_free_init_tramp(void) { }
 #endif /* CONFIG_PPC64 */
 #endif /* !__ASSEMBLY__ */
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/futex.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/futex.h
@@ -35,7 +35,7 @@
 {
 	int oldval = 0, ret;
 
-	allow_write_to_user(uaddr, sizeof(*uaddr));
+	allow_read_write_user(uaddr, uaddr, sizeof(*uaddr));
 	pagefault_disable();
 
 	switch (op) {
@@ -62,7 +62,7 @@
 
 	*oval = oldval;
 
-	prevent_write_to_user(uaddr, sizeof(*uaddr));
+	prevent_read_write_user(uaddr, uaddr, sizeof(*uaddr));
 	return ret;
 }
 
@@ -76,7 +76,8 @@
 	if (!access_ok(uaddr, sizeof(u32)))
 		return -EFAULT;
 
-	allow_write_to_user(uaddr, sizeof(*uaddr));
+	allow_read_write_user(uaddr, uaddr, sizeof(*uaddr));
+
         __asm__ __volatile__ (
         PPC_ATOMIC_ENTRY_BARRIER
 "1:     lwarx   %1,0,%3         # futex_atomic_cmpxchg_inatomic\n\
@@ -97,7 +98,8 @@
         : "cc", "memory");
 
 	*uval = prev;
-	prevent_write_to_user(uaddr, sizeof(*uaddr));
+	prevent_read_write_user(uaddr, uaddr, sizeof(*uaddr));
+
         return ret;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/hvcall.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/hvcall.h
@@ -403,7 +403,7 @@
  * Used for all but the craziest of phyp interfaces (see plpar_hcall9)
  */
 #define PLPAR_HCALL_BUFSIZE 4
-long plpar_hcall(unsigned long opcode, unsigned long *retbuf, ...);
+long plpar_hcall(unsigned long opcode, unsigned long retbuf[static PLPAR_HCALL_BUFSIZE], ...);
 
 /**
  * plpar_hcall_raw: - Make a hypervisor call without calculating hcall stats
@@ -417,7 +417,7 @@
  * plpar_hcall, but plpar_hcall_raw works in real mode and does not
  * calculate hypervisor call statistics.
  */
-long plpar_hcall_raw(unsigned long opcode, unsigned long *retbuf, ...);
+long plpar_hcall_raw(unsigned long opcode, unsigned long retbuf[static PLPAR_HCALL_BUFSIZE], ...);
 
 /**
  * plpar_hcall9: - Make a pseries hypervisor call with up to 9 return arguments
@@ -428,8 +428,8 @@
  * PLPAR_HCALL9_BUFSIZE to size the return argument buffer.
  */
 #define PLPAR_HCALL9_BUFSIZE 9
-long plpar_hcall9(unsigned long opcode, unsigned long *retbuf, ...);
-long plpar_hcall9_raw(unsigned long opcode, unsigned long *retbuf, ...);
+long plpar_hcall9(unsigned long opcode, unsigned long retbuf[static PLPAR_HCALL9_BUFSIZE], ...);
+long plpar_hcall9_raw(unsigned long opcode, unsigned long retbuf[static PLPAR_HCALL9_BUFSIZE], ...);
 
 struct hvcall_mpp_data {
 	unsigned long entitled_mem;
@@ -444,7 +444,7 @@
 	unsigned long backing_mem;
 };
 
-int h_get_mpp(struct hvcall_mpp_data *);
+long h_get_mpp(struct hvcall_mpp_data *mpp_data);
 
 struct hvcall_mpp_x_data {
 	unsigned long coalesced_bytes;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/imc-pmu.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/imc-pmu.h
@@ -132,7 +132,7 @@
  * are inited.
  */
 struct imc_pmu_ref {
-	struct mutex lock;
+	spinlock_t lock;
 	unsigned int id;
 	int refc;
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/io.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/io.h
@@ -46,7 +46,7 @@
  * define properly based on the platform
  */
 #ifndef CONFIG_PCI
-#define _IO_BASE	0
+#define _IO_BASE	POISON_POINTER_DELTA
 #define _ISA_MEM_BASE	0
 #define PCI_DRAM_OFFSET 0
 #elif defined(CONFIG_PPC32)
@@ -345,25 +345,37 @@
  */
 static inline void __raw_rm_writeb(u8 val, volatile void __iomem *paddr)
 {
-	__asm__ __volatile__("stbcix %0,0,%1"
+	__asm__ __volatile__(".machine push;   \
+			      .machine power6; \
+			      stbcix %0,0,%1;  \
+			      .machine pop;"
 		: : "r" (val), "r" (paddr) : "memory");
 }
 
 static inline void __raw_rm_writew(u16 val, volatile void __iomem *paddr)
 {
-	__asm__ __volatile__("sthcix %0,0,%1"
+	__asm__ __volatile__(".machine push;   \
+			      .machine power6; \
+			      sthcix %0,0,%1;  \
+			      .machine pop;"
 		: : "r" (val), "r" (paddr) : "memory");
 }
 
 static inline void __raw_rm_writel(u32 val, volatile void __iomem *paddr)
 {
-	__asm__ __volatile__("stwcix %0,0,%1"
+	__asm__ __volatile__(".machine push;   \
+			      .machine power6; \
+			      stwcix %0,0,%1;  \
+			      .machine pop;"
 		: : "r" (val), "r" (paddr) : "memory");
 }
 
 static inline void __raw_rm_writeq(u64 val, volatile void __iomem *paddr)
 {
-	__asm__ __volatile__("stdcix %0,0,%1"
+	__asm__ __volatile__(".machine push;   \
+			      .machine power6; \
+			      stdcix %0,0,%1;  \
+			      .machine pop;"
 		: : "r" (val), "r" (paddr) : "memory");
 }
 
@@ -375,7 +387,10 @@
 static inline u8 __raw_rm_readb(volatile void __iomem *paddr)
 {
 	u8 ret;
-	__asm__ __volatile__("lbzcix %0,0, %1"
+	__asm__ __volatile__(".machine push;   \
+			      .machine power6; \
+			      lbzcix %0,0, %1; \
+			      .machine pop;"
 			     : "=r" (ret) : "r" (paddr) : "memory");
 	return ret;
 }
@@ -383,7 +398,10 @@
 static inline u16 __raw_rm_readw(volatile void __iomem *paddr)
 {
 	u16 ret;
-	__asm__ __volatile__("lhzcix %0,0, %1"
+	__asm__ __volatile__(".machine push;   \
+			      .machine power6; \
+			      lhzcix %0,0, %1; \
+			      .machine pop;"
 			     : "=r" (ret) : "r" (paddr) : "memory");
 	return ret;
 }
@@ -391,7 +409,10 @@
 static inline u32 __raw_rm_readl(volatile void __iomem *paddr)
 {
 	u32 ret;
-	__asm__ __volatile__("lwzcix %0,0, %1"
+	__asm__ __volatile__(".machine push;   \
+			      .machine power6; \
+			      lwzcix %0,0, %1; \
+			      .machine pop;"
 			     : "=r" (ret) : "r" (paddr) : "memory");
 	return ret;
 }
@@ -399,7 +420,10 @@
 static inline u64 __raw_rm_readq(volatile void __iomem *paddr)
 {
 	u64 ret;
-	__asm__ __volatile__("ldcix %0,0, %1"
+	__asm__ __volatile__(".machine push;   \
+			      .machine power6; \
+			      ldcix %0,0, %1;  \
+			      .machine pop;"
 			     : "=r" (ret) : "r" (paddr) : "memory");
 	return ret;
 }
@@ -518,12 +542,12 @@
 #define __do_inw(port)		_rec_inw(port)
 #define __do_inl(port)		_rec_inl(port)
 #else /* CONFIG_PPC32 */
-#define __do_outb(val, port)	writeb(val,(PCI_IO_ADDR)_IO_BASE+port);
-#define __do_outw(val, port)	writew(val,(PCI_IO_ADDR)_IO_BASE+port);
-#define __do_outl(val, port)	writel(val,(PCI_IO_ADDR)_IO_BASE+port);
-#define __do_inb(port)		readb((PCI_IO_ADDR)_IO_BASE + port);
-#define __do_inw(port)		readw((PCI_IO_ADDR)_IO_BASE + port);
-#define __do_inl(port)		readl((PCI_IO_ADDR)_IO_BASE + port);
+#define __do_outb(val, port)	writeb(val,(PCI_IO_ADDR)(_IO_BASE+port));
+#define __do_outw(val, port)	writew(val,(PCI_IO_ADDR)(_IO_BASE+port));
+#define __do_outl(val, port)	writel(val,(PCI_IO_ADDR)(_IO_BASE+port));
+#define __do_inb(port)		readb((PCI_IO_ADDR)(_IO_BASE + port));
+#define __do_inw(port)		readw((PCI_IO_ADDR)(_IO_BASE + port));
+#define __do_inl(port)		readl((PCI_IO_ADDR)(_IO_BASE + port));
 #endif /* !CONFIG_PPC32 */
 
 #ifdef CONFIG_EEH
@@ -539,12 +563,12 @@
 #define __do_writesw(a, b, n)	_outsw(PCI_FIX_ADDR(a),(b),(n))
 #define __do_writesl(a, b, n)	_outsl(PCI_FIX_ADDR(a),(b),(n))
 
-#define __do_insb(p, b, n)	readsb((PCI_IO_ADDR)_IO_BASE+(p), (b), (n))
-#define __do_insw(p, b, n)	readsw((PCI_IO_ADDR)_IO_BASE+(p), (b), (n))
-#define __do_insl(p, b, n)	readsl((PCI_IO_ADDR)_IO_BASE+(p), (b), (n))
-#define __do_outsb(p, b, n)	writesb((PCI_IO_ADDR)_IO_BASE+(p),(b),(n))
-#define __do_outsw(p, b, n)	writesw((PCI_IO_ADDR)_IO_BASE+(p),(b),(n))
-#define __do_outsl(p, b, n)	writesl((PCI_IO_ADDR)_IO_BASE+(p),(b),(n))
+#define __do_insb(p, b, n)	readsb((PCI_IO_ADDR)(_IO_BASE+(p)), (b), (n))
+#define __do_insw(p, b, n)	readsw((PCI_IO_ADDR)(_IO_BASE+(p)), (b), (n))
+#define __do_insl(p, b, n)	readsl((PCI_IO_ADDR)(_IO_BASE+(p)), (b), (n))
+#define __do_outsb(p, b, n)	writesb((PCI_IO_ADDR)(_IO_BASE+(p)),(b),(n))
+#define __do_outsw(p, b, n)	writesw((PCI_IO_ADDR)(_IO_BASE+(p)),(b),(n))
+#define __do_outsl(p, b, n)	writesl((PCI_IO_ADDR)(_IO_BASE+(p)),(b),(n))
 
 #define __do_memset_io(addr, c, n)	\
 				_memset_io(PCI_FIX_ADDR(addr), c, n)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/kasan.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/kasan.h
@@ -23,9 +23,7 @@
 
 #define KASAN_SHADOW_OFFSET	ASM_CONST(CONFIG_KASAN_SHADOW_OFFSET)
 
-#define KASAN_SHADOW_END	0UL
-
-#define KASAN_SHADOW_SIZE	(KASAN_SHADOW_END - KASAN_SHADOW_START)
+#define KASAN_SHADOW_END	(-(-KASAN_SHADOW_START >> KASAN_SHADOW_SCALE_SHIFT))
 
 #ifdef CONFIG_KASAN
 void kasan_early_init(void);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/kup.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/kup.h
@@ -2,7 +2,11 @@
 #ifndef _ASM_POWERPC_KUP_H_
 #define _ASM_POWERPC_KUP_H_
 
-#ifdef CONFIG_PPC64
+#define KUAP_READ	1
+#define KUAP_WRITE	2
+#define KUAP_READ_WRITE	(KUAP_READ | KUAP_WRITE)
+
+#ifdef CONFIG_PPC_BOOK3S_64
 #include <asm/book3s/64/kup-radix.h>
 #endif
 #ifdef CONFIG_PPC_8xx
@@ -20,9 +24,15 @@
 .macro kuap_restore	sp, current, gpr1, gpr2, gpr3
 .endm
 
+.macro kuap_restore_amr gpr
+.endm
+
 .macro kuap_check	current, gpr
 .endm
 
+.macro kuap_check_amr	gpr1, gpr2
+.endm
+
 #endif
 
 #else /* !__ASSEMBLY__ */
@@ -41,33 +51,60 @@
 void setup_kuap(bool disabled);
 #else
 static inline void setup_kuap(bool disabled) { }
+
+static inline bool
+bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write)
+{
+	return false;
+}
+
+static inline void kuap_check_amr(void) { }
+
+/*
+ * book3s/64/kup-radix.h defines these functions for the !KUAP case to flush
+ * the L1D cache after user accesses. Only include the empty stubs for other
+ * platforms.
+ */
+#ifndef CONFIG_PPC_BOOK3S_64
 static inline void allow_user_access(void __user *to, const void __user *from,
-				     unsigned long size) { }
+				     unsigned long size, unsigned long dir) { }
 static inline void prevent_user_access(void __user *to, const void __user *from,
-				       unsigned long size) { }
-static inline bool bad_kuap_fault(struct pt_regs *regs, bool is_write) { return false; }
+				       unsigned long size, unsigned long dir) { }
+#endif /* CONFIG_PPC_BOOK3S_64 */
 #endif /* CONFIG_PPC_KUAP */
 
 static inline void allow_read_from_user(const void __user *from, unsigned long size)
 {
-	allow_user_access(NULL, from, size);
+	allow_user_access(NULL, from, size, KUAP_READ);
 }
 
 static inline void allow_write_to_user(void __user *to, unsigned long size)
 {
-	allow_user_access(to, NULL, size);
+	allow_user_access(to, NULL, size, KUAP_WRITE);
+}
+
+static inline void allow_read_write_user(void __user *to, const void __user *from,
+					 unsigned long size)
+{
+	allow_user_access(to, from, size, KUAP_READ_WRITE);
 }
 
 static inline void prevent_read_from_user(const void __user *from, unsigned long size)
 {
-	prevent_user_access(NULL, from, size);
+	prevent_user_access(NULL, from, size, KUAP_READ);
 }
 
 static inline void prevent_write_to_user(void __user *to, unsigned long size)
 {
-	prevent_user_access(to, NULL, size);
+	prevent_user_access(to, NULL, size, KUAP_WRITE);
+}
+
+static inline void prevent_read_write_user(void __user *to, const void __user *from,
+					   unsigned long size)
+{
+	prevent_user_access(to, from, size, KUAP_READ_WRITE);
 }
 
 #endif /* !__ASSEMBLY__ */
 
-#endif /* _ASM_POWERPC_KUP_H_ */
+#endif /* _ASM_POWERPC_KUAP_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/kvm_asm.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/kvm_asm.h
@@ -150,4 +150,7 @@
 
 #define KVM_INST_FETCH_FAILED	-1
 
+/* Extract PO and XOP opcode fields */
+#define PO_XOP_OPCODE_MASK 0xfc0007fe
+
 #endif /* __POWERPC_KVM_ASM_H__ */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/kvm_host.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/kvm_host.h
@@ -58,7 +58,8 @@
 #define KVM_ARCH_WANT_MMU_NOTIFIER
 
 extern int kvm_unmap_hva_range(struct kvm *kvm,
-			       unsigned long start, unsigned long end);
+			       unsigned long start, unsigned long end,
+			       unsigned flags);
 extern int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end);
 extern int kvm_test_age_hva(struct kvm *kvm, unsigned long hva);
 extern int kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/machdep.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/machdep.h
@@ -59,6 +59,9 @@
 	int		(*pcibios_root_bridge_prepare)(struct pci_host_bridge
 				*bridge);
 
+	/* finds all the pci_controllers present at boot */
+	void 		(*discover_phbs)(void);
+
 	/* To setup PHBs when using automatic OF platform driver for PCI */
 	int		(*pci_setup_phb)(struct pci_controller *host);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/mmu.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/mmu.h
@@ -375,5 +375,9 @@
 #include <asm/nohash/mmu.h>
 #endif
 
+#if defined(CONFIG_FA_DUMP) || defined(CONFIG_PRESERVE_FA_DUMP)
+#define __HAVE_ARCH_RESERVED_KERNEL_PAGES
+#endif
+
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_MMU_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/mmu_context.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/mmu_context.h
@@ -216,7 +216,7 @@
  */
 static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
 {
-	switch_mm(prev, next, current);
+	switch_mm_irqs_off(prev, next, current);
 }
 
 /* We don't currently use enter_lazy_tlb() for anything */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/mmzone.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/mmzone.h
@@ -42,9 +42,6 @@
 #else
 #define memory_hotplug_max() memblock_end_of_DRAM()
 #endif /* CONFIG_NEED_MULTIPLE_NODES */
-#ifdef CONFIG_FA_DUMP
-#define __HAVE_ARCH_RESERVED_KERNEL_PAGES
-#endif
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_MMZONE_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/nohash/32/kup-8xx.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/nohash/32/kup-8xx.h
@@ -34,18 +34,19 @@
 #include <asm/reg.h>
 
 static inline void allow_user_access(void __user *to, const void __user *from,
-				     unsigned long size)
+				     unsigned long size, unsigned long dir)
 {
 	mtspr(SPRN_MD_AP, MD_APG_INIT);
 }
 
 static inline void prevent_user_access(void __user *to, const void __user *from,
-				       unsigned long size)
+				       unsigned long size, unsigned long dir)
 {
 	mtspr(SPRN_MD_AP, MD_APG_KUAP);
 }
 
-static inline bool bad_kuap_fault(struct pt_regs *regs, bool is_write)
+static inline bool
+bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write)
 {
 	return WARN(!((regs->kuap ^ MD_APG_KUAP) & 0xf0000000),
 		    "Bug: fault blocked by AP register !");
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/nohash/32/pgtable.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/nohash/32/pgtable.h
@@ -148,8 +148,10 @@
  */
 #if defined(CONFIG_PPC32) && defined(CONFIG_PTE_64BIT)
 #define PTE_RPN_MASK	(~((1ULL << PTE_RPN_SHIFT) - 1))
+#define MAX_POSSIBLE_PHYSMEM_BITS 36
 #else
 #define PTE_RPN_MASK	(~((1UL << PTE_RPN_SHIFT) - 1))
+#define MAX_POSSIBLE_PHYSMEM_BITS 32
 #endif
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/nohash/32/pte-8xx.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/nohash/32/pte-8xx.h
@@ -91,6 +91,13 @@
 
 #define pte_wrprotect pte_wrprotect
 
+static inline int pte_read(pte_t pte)
+{
+	return (pte_val(pte) & _PAGE_RO) != _PAGE_NA;
+}
+
+#define pte_read pte_read
+
 static inline int pte_write(pte_t pte)
 {
 	return !(pte_val(pte) & _PAGE_RO);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/nohash/64/pgtable.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/nohash/64/pgtable.h
@@ -244,7 +244,7 @@
 {
 	unsigned long old;
 
-	if (pte_young(*ptep))
+	if (!pte_young(*ptep))
 		return 0;
 	old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0, 0);
 	return (old & _PAGE_ACCESSED) != 0;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/nohash/pgalloc.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/nohash/pgalloc.h
@@ -46,7 +46,6 @@
 
 #define get_hugepd_cache_index(x)	(x)
 
-#ifdef CONFIG_SMP
 static inline void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int shift)
 {
 	unsigned long pgf = (unsigned long)table;
@@ -64,13 +63,6 @@
 	pgtable_free(table, shift);
 }
 
-#else
-static inline void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int shift)
-{
-	pgtable_free(table, shift);
-}
-#endif
-
 static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table,
 				  unsigned long address)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/nohash/pgtable.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/nohash/pgtable.h
@@ -45,7 +45,9 @@
 	return pte_val(pte) & _PAGE_RW;
 }
 #endif
+#ifndef pte_read
 static inline int pte_read(pte_t pte)		{ return 1; }
+#endif
 static inline int pte_dirty(pte_t pte)		{ return pte_val(pte) & _PAGE_DIRTY; }
 static inline int pte_special(pte_t pte)	{ return pte_val(pte) & _PAGE_SPECIAL; }
 static inline int pte_none(pte_t pte)		{ return (pte_val(pte) & ~_PTE_NONE_MASK) == 0; }
@@ -199,9 +201,9 @@
 	 */
 	if (IS_ENABLED(CONFIG_PPC32) && IS_ENABLED(CONFIG_PTE_64BIT) && !percpu) {
 		__asm__ __volatile__("\
-			stw%U0%X0 %2,%0\n\
+			stw%X0 %2,%0\n\
 			eieio\n\
-			stw%U0%X0 %L2,%1"
+			stw%X1 %L2,%1"
 		: "=m" (*ptep), "=m" (*((unsigned char *)ptep+4))
 		: "r" (pte) : "memory");
 		return;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/opal-api.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/opal-api.h
@@ -211,7 +211,10 @@
 #define OPAL_MPIPL_UPDATE			173
 #define OPAL_MPIPL_REGISTER_TAG			174
 #define OPAL_MPIPL_QUERY_TAG			175
-#define OPAL_LAST				175
+#define OPAL_SECVAR_GET				176
+#define OPAL_SECVAR_GET_NEXT			177
+#define OPAL_SECVAR_ENQUEUE_UPDATE		178
+#define OPAL_LAST				178
 
 #define QUIESCE_HOLD			1 /* Spin all calls at entry */
 #define QUIESCE_REJECT			2 /* Fail all calls with OPAL_BUSY */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/opal.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/opal.h
@@ -298,6 +298,13 @@
 int opal_sensor_group_enable(u32 group_hndl, int token, bool enable);
 int opal_nx_coproc_init(uint32_t chip_id, uint32_t ct);
 
+int opal_secvar_get(const char *key, uint64_t key_len, u8 *data,
+		    uint64_t *data_size);
+int opal_secvar_get_next(const char *key, uint64_t *key_len,
+			 uint64_t key_buf_size);
+int opal_secvar_enqueue_update(const char *key, uint64_t key_len, u8 *data,
+			       uint64_t data_size);
+
 s64 opal_mpipl_update(enum opal_mpipl_ops op, u64 src, u64 dest, u64 size);
 s64 opal_mpipl_register_tag(enum opal_mpipl_tags tag, u64 addr);
 s64 opal_mpipl_query_tag(enum opal_mpipl_tags tag, u64 *addr);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/page.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/page.h
@@ -132,7 +132,11 @@
 #define virt_to_page(kaddr)	pfn_to_page(virt_to_pfn(kaddr))
 #define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT)
 
-#define virt_addr_valid(kaddr)	pfn_valid(virt_to_pfn(kaddr))
+#define virt_addr_valid(vaddr)	({					\
+	unsigned long _addr = (unsigned long)vaddr;			\
+	_addr >= PAGE_OFFSET && _addr < (unsigned long)high_memory &&	\
+	pfn_valid(virt_to_pfn(_addr));					\
+})
 
 /*
  * On Book-E parts we need __va to parse the device tree and we can't
@@ -212,6 +216,9 @@
 #define __pa(x) ((unsigned long)(x) - VIRT_PHYS_OFFSET)
 #else
 #ifdef CONFIG_PPC64
+
+#define VIRTUAL_WARN_ON(x)	WARN_ON(IS_ENABLED(CONFIG_DEBUG_VIRTUAL) && (x))
+
 /*
  * gcc miscompiles (unsigned long)(&static_var) - PAGE_OFFSET
  * with -mcmodel=medium, so we use & and | instead of - and + on 64-bit.
@@ -219,13 +226,13 @@
  */
 #define __va(x)								\
 ({									\
-	VIRTUAL_BUG_ON((unsigned long)(x) >= PAGE_OFFSET);		\
+	VIRTUAL_WARN_ON((unsigned long)(x) >= PAGE_OFFSET);		\
 	(void *)(unsigned long)((phys_addr_t)(x) | PAGE_OFFSET);	\
 })
 
 #define __pa(x)								\
 ({									\
-	VIRTUAL_BUG_ON((unsigned long)(x) < PAGE_OFFSET);		\
+	VIRTUAL_WARN_ON((unsigned long)(x) < PAGE_OFFSET);		\
 	(unsigned long)(x) & 0x0fffffffffffffffUL;			\
 })
 
@@ -295,8 +302,13 @@
 /*
  * Some number of bits at the level of the page table that points to
  * a hugepte are used to encode the size.  This masks those bits.
+ * On 8xx, HW assistance requires 4k alignment for the hugepte.
  */
+#ifdef CONFIG_PPC_8xx
+#define HUGEPD_SHIFT_MASK     0xfff
+#else
 #define HUGEPD_SHIFT_MASK     0x3f
+#endif
 
 #ifndef __ASSEMBLY__
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/percpu.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/percpu.h
@@ -10,8 +10,6 @@
 
 #ifdef CONFIG_SMP
 
-#include <asm/paca.h>
-
 #define __my_cpu_offset local_paca->data_offset
 
 #endif /* CONFIG_SMP */
@@ -19,4 +17,6 @@
 
 #include <asm-generic/percpu.h>
 
+#include <asm/paca.h>
+
 #endif /* _ASM_POWERPC_PERCPU_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/perf_event.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/perf_event.h
@@ -12,6 +12,8 @@
 
 #ifdef CONFIG_PPC_PERF_CTRS
 #include <asm/perf_event_server.h>
+#else
+static inline bool is_sier_available(void) { return false; }
 #endif
 
 #ifdef CONFIG_FSL_EMB_PERF_EVENT
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/pmc.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/pmc.h
@@ -34,6 +34,13 @@
 #endif
 }
 
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+static inline int ppc_get_pmu_inuse(void)
+{
+	return get_paca()->pmcregs_in_use;
+}
+#endif
+
 extern void power4_enable_pmcs(void);
 
 #else /* CONFIG_PPC64 */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/pnv-pci.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/pnv-pci.h
@@ -15,6 +15,7 @@
 #define PCI_SLOT_ID_PREFIX	(1UL << 63)
 #define PCI_SLOT_ID(phb_id, bdfn)	\
 	(PCI_SLOT_ID_PREFIX | ((uint64_t)(bdfn) << 16) | (phb_id))
+#define PCI_PHB_SLOT_ID(phb_id)		(phb_id)
 
 extern int pnv_pci_get_slot_id(struct device_node *np, uint64_t *id);
 extern int pnv_pci_get_device_tree(uint32_t phandle, void *buf, uint64_t len);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/ppc-opcode.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/ppc-opcode.h
@@ -204,6 +204,7 @@
 #define PPC_INST_ICBT			0x7c00002c
 #define PPC_INST_ICSWX			0x7c00032d
 #define PPC_INST_ICSWEPX		0x7c00076d
+#define PPC_INST_DSSALL			0x7e00066c
 #define PPC_INST_ISEL			0x7c00001e
 #define PPC_INST_ISEL_MASK		0xfc00003e
 #define PPC_INST_LDARX			0x7c0000a8
@@ -439,6 +440,7 @@
 					__PPC_RA(a) | __PPC_RB(b))
 #define	PPC_DCBZL(a, b)		stringify_in_c(.long PPC_INST_DCBZL | \
 					__PPC_RA(a) | __PPC_RB(b))
+#define PPC_DSSALL		stringify_in_c(.long PPC_INST_DSSALL)
 #define PPC_LQARX(t, a, b, eh)	stringify_in_c(.long PPC_INST_LQARX | \
 					___PPC_RT(t) | ___PPC_RA(a) | \
 					___PPC_RB(b) | __PPC_EH(eh))
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/processor.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/processor.h
@@ -291,7 +291,6 @@
 #else
 #define INIT_THREAD  { \
 	.ksp = INIT_SP, \
-	.regs = (struct pt_regs *)INIT_SP - 1, /* XXX bogus, I think */ \
 	.addr_limit = KERNEL_DS, \
 	.fpexc_mode = 0, \
 	.fscr = FSCR_TAR | FSCR_EBB \
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/ps3.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/ps3.h
@@ -71,6 +71,7 @@
  * @bus_addr: The 'translated' bus address of the region.
  * @len: The length in bytes of the region.
  * @offset: The offset from the start of memory of the region.
+ * @dma_mask: Device dma_mask.
  * @ioid: The IOID of the device who owns this region
  * @chunk_list: Opaque variable used by the ioc page manager.
  * @region_ops: struct ps3_dma_region_ops - dma region operations
@@ -85,6 +86,7 @@
 	enum ps3_dma_region_type region_type;
 	unsigned long len;
 	unsigned long offset;
+	u64 dma_mask;
 
 	/* driver variables  (set by ps3_dma_region_create) */
 	unsigned long bus_addr;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/ptrace.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/ptrace.h
@@ -62,6 +62,9 @@
 };
 #endif
 
+
+#define STACK_FRAME_WITH_PT_REGS (STACK_FRAME_OVERHEAD + sizeof(struct pt_regs))
+
 #ifdef __powerpc64__
 
 /*
@@ -203,7 +206,7 @@
 #endif /* __powerpc64__ */
 
 #define arch_has_single_step()	(1)
-#ifndef CONFIG_BOOK3S_601
+#ifndef CONFIG_PPC_BOOK3S_601
 #define arch_has_block_step()	(true)
 #else
 #define arch_has_block_step()	(false)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/reg.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/reg.h
@@ -796,7 +796,7 @@
 #define THRM1_TIN	(1 << 31)
 #define THRM1_TIV	(1 << 30)
 #define THRM1_THRES(x)	((x&0x7f)<<23)
-#define THRM3_SITV(x)	((x&0x3fff)<<1)
+#define THRM3_SITV(x)	((x & 0x1fff) << 1)
 #define THRM1_TID	(1<<2)
 #define THRM1_TIE	(1<<1)
 #define THRM1_V		(1<<0)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/reg_fsl_emb.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/reg_fsl_emb.h
@@ -12,9 +12,16 @@
 #ifndef __ASSEMBLY__
 /* Performance Monitor Registers */
 #define mfpmr(rn)	({unsigned int rval; \
-			asm volatile("mfpmr %0," __stringify(rn) \
+			asm volatile(".machine push; " \
+				     ".machine e300; " \
+				     "mfpmr %0," __stringify(rn) ";" \
+				     ".machine pop; " \
 				     : "=r" (rval)); rval;})
-#define mtpmr(rn, v)	asm volatile("mtpmr " __stringify(rn) ",%0" : : "r" (v))
+#define mtpmr(rn, v)	asm volatile(".machine push; " \
+				     ".machine e300; " \
+				     "mtpmr " __stringify(rn) ",%0; " \
+				     ".machine pop; " \
+				     : : "r" (v))
 #endif /* __ASSEMBLY__ */
 
 /* Freescale Book E Performance Monitor APU Registers */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/rtas.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/rtas.h
@@ -368,8 +368,6 @@
 extern void rtas_progress(char *s, unsigned short hex);
 extern int rtas_suspend_cpu(struct rtas_suspend_me_data *data);
 extern int rtas_suspend_last_cpu(struct rtas_suspend_me_data *data);
-extern int rtas_online_cpus_mask(cpumask_var_t cpus);
-extern int rtas_offline_cpus_mask(cpumask_var_t cpus);
 extern int rtas_ibm_suspend_me(u64 handle);
 
 struct rtc_time;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/sections.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/sections.h
@@ -5,8 +5,22 @@
 
 #include <linux/elf.h>
 #include <linux/uaccess.h>
+
+#define arch_is_kernel_initmem_freed arch_is_kernel_initmem_freed
+
 #include <asm-generic/sections.h>
 
+extern bool init_mem_is_free;
+
+static inline int arch_is_kernel_initmem_freed(unsigned long addr)
+{
+	if (!init_mem_is_free)
+		return 0;
+
+	return addr >= (unsigned long)__init_begin &&
+		addr < (unsigned long)__init_end;
+}
+
 extern char __head_end[];
 
 #ifdef __powerpc64__
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/secure_boot.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/secure_boot.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Secure boot definitions
+ *
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain
+ */
+#ifndef _ASM_POWER_SECURE_BOOT_H
+#define _ASM_POWER_SECURE_BOOT_H
+
+#ifdef CONFIG_PPC_SECURE_BOOT
+
+bool is_ppc_secureboot_enabled(void);
+bool is_ppc_trustedboot_enabled(void);
+
+#else
+
+static inline bool is_ppc_secureboot_enabled(void)
+{
+	return false;
+}
+
+static inline bool is_ppc_trustedboot_enabled(void)
+{
+	return false;
+}
+
+#endif
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/security_features.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/security_features.h
@@ -9,7 +9,7 @@
 #define _ASM_POWERPC_SECURITY_FEATURES_H
 
 
-extern unsigned long powerpc_security_features;
+extern u64 powerpc_security_features;
 extern bool rfi_flush;
 
 /* These are bit flags */
@@ -24,21 +24,26 @@
 void do_stf_barrier_fixups(enum stf_barrier_type types);
 void setup_count_cache_flush(void);
 
-static inline void security_ftr_set(unsigned long feature)
+static inline void security_ftr_set(u64 feature)
 {
 	powerpc_security_features |= feature;
 }
 
-static inline void security_ftr_clear(unsigned long feature)
+static inline void security_ftr_clear(u64 feature)
 {
 	powerpc_security_features &= ~feature;
 }
 
-static inline bool security_ftr_enabled(unsigned long feature)
+static inline bool security_ftr_enabled(u64 feature)
 {
 	return !!(powerpc_security_features & feature);
 }
 
+#ifdef CONFIG_PPC_BOOK3S_64
+enum stf_barrier_type stf_barrier_type_get(void);
+#else
+static inline enum stf_barrier_type stf_barrier_type_get(void) { return STF_BARRIER_NONE; }
+#endif
 
 // Features indicating support for Spectre/Meltdown mitigations
 
@@ -81,12 +86,22 @@
 // Software required to flush count cache on context switch
 #define SEC_FTR_FLUSH_COUNT_CACHE	0x0000000000000400ull
 
+// Software required to flush link stack on context switch
+#define SEC_FTR_FLUSH_LINK_STACK	0x0000000000001000ull
+
+// The L1-D cache should be flushed when entering the kernel
+#define SEC_FTR_L1D_FLUSH_ENTRY		0x0000000000004000ull
+
+// The L1-D cache should be flushed after user accesses from the kernel
+#define SEC_FTR_L1D_FLUSH_UACCESS	0x0000000000008000ull
 
 // Features enabled by default
 #define SEC_FTR_DEFAULT \
 	(SEC_FTR_L1D_FLUSH_HV | \
 	 SEC_FTR_L1D_FLUSH_PR | \
 	 SEC_FTR_BNDS_CHK_SPEC_BAR | \
+	 SEC_FTR_L1D_FLUSH_ENTRY | \
+	 SEC_FTR_L1D_FLUSH_UACCESS | \
 	 SEC_FTR_FAVOUR_SECURITY)
 
 #endif /* _ASM_POWERPC_SECURITY_FEATURES_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/secvar.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/secvar.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain
+ *
+ * PowerPC secure variable operations.
+ */
+#ifndef SECVAR_OPS_H
+#define SECVAR_OPS_H
+
+#include <linux/types.h>
+#include <linux/errno.h>
+
+extern const struct secvar_operations *secvar_ops;
+
+struct secvar_operations {
+	int (*get)(const char *key, uint64_t key_len, u8 *data,
+		   uint64_t *data_size);
+	int (*get_next)(const char *key, uint64_t *key_len,
+			uint64_t keybufsize);
+	int (*set)(const char *key, uint64_t key_len, u8 *data,
+		   uint64_t data_size);
+};
+
+#ifdef CONFIG_PPC_SECURE_BOOT
+
+extern void set_secvar_ops(const struct secvar_operations *ops);
+
+#else
+
+static inline void set_secvar_ops(const struct secvar_operations *ops) { }
+
+#endif
+
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/setjmp.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/setjmp.h
@@ -7,7 +7,9 @@
 
 #define JMP_BUF_LEN    23
 
-extern long setjmp(long *) __attribute__((returns_twice));
-extern void longjmp(long *, long) __attribute__((noreturn));
+typedef long jmp_buf[JMP_BUF_LEN];
+
+extern int setjmp(jmp_buf env) __attribute__((returns_twice));
+extern void longjmp(jmp_buf env, int val) __attribute__((noreturn));
 
 #endif /* _ASM_POWERPC_SETJMP_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/setup.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/setup.h
@@ -52,12 +52,16 @@
 };
 
 void setup_rfi_flush(enum l1d_flush_type, bool enable);
+void setup_entry_flush(bool enable);
+void setup_uaccess_flush(bool enable);
 void do_rfi_flush_fixups(enum l1d_flush_type types);
 #ifdef CONFIG_PPC_BARRIER_NOSPEC
 void setup_barrier_nospec(void);
 #else
 static inline void setup_barrier_nospec(void) { };
 #endif
+void do_uaccess_flush_fixups(enum l1d_flush_type types);
+void do_entry_flush_fixups(enum l1d_flush_type types);
 void do_barrier_nospec_fixups(bool enable);
 extern bool barrier_nospec_enabled;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/spinlock.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/spinlock.h
@@ -15,6 +15,7 @@
  *
  * (the type definitions are in asm/spinlock_types.h)
  */
+#include <linux/jump_label.h>
 #include <linux/irqflags.h>
 #ifdef CONFIG_PPC64
 #include <asm/paca.h>
@@ -36,10 +37,12 @@
 #endif
 
 #ifdef CONFIG_PPC_PSERIES
+DECLARE_STATIC_KEY_FALSE(shared_processor);
+
 #define vcpu_is_preempted vcpu_is_preempted
 static inline bool vcpu_is_preempted(int cpu)
 {
-	if (!firmware_has_feature(FW_FEATURE_SPLPAR))
+	if (!static_branch_unlikely(&shared_processor))
 		return false;
 	return !!(be32_to_cpu(lppaca_of(cpu).yield_count) & 1);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/sstep.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/sstep.h
@@ -160,9 +160,4 @@
  */
 extern int emulate_loadstore(struct pt_regs *regs, struct instruction_op *op);
 
-extern void emulate_vsx_load(struct instruction_op *op, union vsx_reg *reg,
-			     const void *mem, bool cross_endian);
-extern void emulate_vsx_store(struct instruction_op *op,
-			      const union vsx_reg *reg, void *mem,
-			      bool cross_endian);
 extern int emulate_dcbz(unsigned long ea, struct pt_regs *regs);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/timex.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/timex.h
@@ -17,11 +17,12 @@
 
 static inline cycles_t get_cycles(void)
 {
-	if (IS_ENABLED(CONFIG_BOOK3S_601))
+	if (IS_ENABLED(CONFIG_PPC_BOOK3S_601))
 		return 0;
 
 	return mftb();
 }
+#define get_cycles get_cycles
 
 #endif	/* __KERNEL__ */
 #endif	/* _ASM_POWERPC_TIMEX_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/tlb.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/tlb.h
@@ -26,6 +26,17 @@
 
 #define tlb_flush tlb_flush
 extern void tlb_flush(struct mmu_gather *tlb);
+/*
+ * book3s:
+ * Hash does not use the linux page-tables, so we can avoid
+ * the TLB invalidate for page-table freeing, Radix otoh does use the
+ * page-tables and needs the TLBI.
+ *
+ * nohash:
+ * We still do TLB invalidate in the __pte_free_tlb routine before we
+ * add the page table pages to mmu gather table batch.
+ */
+#define tlb_needs_table_invalidate()	radix_enabled()
 
 /* Get the generic bits... */
 #include <asm-generic/tlb.h>
@@ -56,19 +67,6 @@
 		return false;
 	return cpumask_test_cpu(smp_processor_id(), mm_cpumask(mm));
 }
-static inline void mm_reset_thread_local(struct mm_struct *mm)
-{
-	WARN_ON(atomic_read(&mm->context.copros) > 0);
-	/*
-	 * It's possible for mm_access to take a reference on mm_users to
-	 * access the remote mm from another thread, but it's not allowed
-	 * to set mm_cpumask, so mm_users may be > 1 here.
-	 */
-	WARN_ON(current->mm != mm);
-	atomic_set(&mm->context.active_cpus, 1);
-	cpumask_clear(mm_cpumask(mm));
-	cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm));
-}
 #else /* CONFIG_PPC_BOOK3S_64 */
 static inline int mm_is_thread_local(struct mm_struct *mm)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/uaccess.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/uaccess.h
@@ -191,8 +191,11 @@
  */
 #define __get_user_atomic_128_aligned(kaddr, uaddr, err)		\
 	__asm__ __volatile__(				\
+		".machine push\n"			\
+		".machine altivec\n"			\
 		"1:	lvx  0,0,%1	# get user\n"	\
 		" 	stvx 0,0,%2	# put kernel\n"	\
+		".machine pop\n"			\
 		"2:\n"					\
 		".section .fixup,\"ax\"\n"		\
 		"3:	li %0,%3\n"			\
@@ -313,9 +316,9 @@
 	unsigned long ret;
 
 	barrier_nospec();
-	allow_user_access(to, from, n);
+	allow_read_write_user(to, from, n);
 	ret = __copy_tofrom_user(to, from, n);
-	prevent_user_access(to, from, n);
+	prevent_read_write_user(to, from, n);
 	return ret;
 }
 #endif /* __powerpc64__ */
@@ -401,7 +404,7 @@
 	return n;
 }
 
-extern unsigned long __clear_user(void __user *addr, unsigned long size);
+unsigned long __arch_clear_user(void __user *addr, unsigned long size);
 
 static inline unsigned long clear_user(void __user *addr, unsigned long size)
 {
@@ -409,12 +412,17 @@
 	might_fault();
 	if (likely(access_ok(addr, size))) {
 		allow_write_to_user(addr, size);
-		ret = __clear_user(addr, size);
+		ret = __arch_clear_user(addr, size);
 		prevent_write_to_user(addr, size);
 	}
 	return ret;
 }
 
+static inline unsigned long __clear_user(void __user *addr, unsigned long size)
+{
+	return clear_user(addr, size);
+}
+
 extern long strncpy_from_user(char *dst, const char __user *src, long count);
 extern __must_check long strnlen_user(const char __user *str, long n);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/vdso.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/vdso.h
@@ -49,6 +49,7 @@
 
 #define V_FUNCTION_BEGIN(name)		\
 	.globl name;			\
+	.type name,@function; 		\
 	name:				\
 
 #define V_FUNCTION_END(name)		\
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/vdso_datapage.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/vdso_datapage.h
@@ -82,6 +82,7 @@
 	__s32 wtom_clock_nsec;			/* Wall to monotonic clock nsec */
 	__s64 wtom_clock_sec;			/* Wall to monotonic clock sec */
 	struct timespec stamp_xtime;		/* xtime as at tb_orig_stamp */
+	__u32 hrtimer_res;			/* hrtimer resolution */
    	__u32 syscall_map_64[SYSCALL_MAP_SIZE]; /* map of syscalls  */
    	__u32 syscall_map_32[SYSCALL_MAP_SIZE]; /* map of syscalls */
 };
@@ -103,6 +104,7 @@
 	__s32 wtom_clock_nsec;
 	struct timespec stamp_xtime;	/* xtime as at tb_orig_stamp */
 	__u32 stamp_sec_fraction;	/* fractional seconds of stamp_xtime */
+	__u32 hrtimer_res;		/* hrtimer resolution */
    	__u32 syscall_map_32[SYSCALL_MAP_SIZE]; /* map of syscalls */
 	__u32 dcache_block_size;	/* L1 d-cache block size     */
 	__u32 icache_block_size;	/* L1 i-cache block size     */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/word-at-a-time.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/word-at-a-time.h
@@ -34,7 +34,7 @@
 	return leading_zero_bits >> 3;
 }
 
-static inline bool has_zero(unsigned long val, unsigned long *data, const struct word_at_a_time *c)
+static inline unsigned long has_zero(unsigned long val, unsigned long *data, const struct word_at_a_time *c)
 {
 	unsigned long rhs = val | c->low_bits;
 	*data = rhs;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/asm/xive-regs.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/asm/xive-regs.h
@@ -39,6 +39,7 @@
 
 #define XIVE_ESB_VAL_P		0x2
 #define XIVE_ESB_VAL_Q		0x1
+#define XIVE_ESB_INVALID	0xFF
 
 /*
  * Thread Management (aka "TM") registers
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/include/uapi/asm/errno.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/include/uapi/asm/errno.h
@@ -2,6 +2,7 @@
 #ifndef _ASM_POWERPC_ERRNO_H
 #define _ASM_POWERPC_ERRNO_H
 
+#undef	EDEADLOCK
 #include <asm-generic/errno.h>
 
 #undef	EDEADLOCK
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/Makefile
@@ -5,9 +5,6 @@
 
 CFLAGS_ptrace.o		+= -DUTS_MACHINE='"$(UTS_MACHINE)"'
 
-# Disable clang warning for using setjmp without setjmp.h header
-CFLAGS_crash.o		+= $(call cc-disable-warning, builtin-requires-header)
-
 ifdef CONFIG_PPC64
 CFLAGS_prom_init.o	+= $(NO_MINIMAL_TOC)
 endif
@@ -16,12 +13,14 @@
 CFLAGS_btext.o		+= -fPIC
 endif
 
+CFLAGS_early_32.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
 CFLAGS_cputable.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
 CFLAGS_prom_init.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
 CFLAGS_btext.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
 CFLAGS_prom.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
 
 CFLAGS_prom_init.o += $(call cc-option, -fno-stack-protector)
+CFLAGS_prom_init.o += -DDISABLE_BRANCH_PROFILING
 
 ifdef CONFIG_FUNCTION_TRACER
 # Do not trace early boot code
@@ -39,7 +38,6 @@
 ifdef CONFIG_KASAN
 CFLAGS_early_32.o += -DDISABLE_BRANCH_PROFILING
 CFLAGS_cputable.o += -DDISABLE_BRANCH_PROFILING
-CFLAGS_prom_init.o += -DDISABLE_BRANCH_PROFILING
 CFLAGS_btext.o += -DDISABLE_BRANCH_PROFILING
 endif
 
@@ -161,6 +159,9 @@
 obj-y				+= ucall.o
 endif
 
+obj-$(CONFIG_PPC_SECURE_BOOT)	+= secure_boot.o ima_arch.o secvar-ops.o
+obj-$(CONFIG_PPC_SECVAR_SYSFS)	+= secvar-sysfs.o
+
 # Disable GCOV, KCOV & sanitizers in odd or sensitive code
 GCOV_PROFILE_prom_init.o := n
 KCOV_INSTRUMENT_prom_init.o := n
@@ -184,6 +185,9 @@
 KCOV_INSTRUMENT_setup_64.o := n
 KCOV_INSTRUMENT_paca.o := n
 
+CFLAGS_setup_64.o		+= -fno-stack-protector
+CFLAGS_paca.o			+= -fno-stack-protector
+
 extra-$(CONFIG_PPC_FPU)		+= fpu.o
 extra-$(CONFIG_ALTIVEC)		+= vector.o
 extra-$(CONFIG_PPC64)		+= entry_64.o
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/asm-offsets.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/asm-offsets.c
@@ -285,7 +285,7 @@
 
 	/* Interrupt register frame */
 	DEFINE(INT_FRAME_SIZE, STACK_INT_FRAME_SIZE);
-	DEFINE(SWITCH_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs));
+	DEFINE(SWITCH_FRAME_SIZE, STACK_FRAME_WITH_PT_REGS);
 	STACK_PT_REGS_OFFSET(GPR0, gpr[0]);
 	STACK_PT_REGS_OFFSET(GPR1, gpr[1]);
 	STACK_PT_REGS_OFFSET(GPR2, gpr[2]);
@@ -387,6 +387,7 @@
 	OFFSET(WTOM_CLOCK_NSEC, vdso_data, wtom_clock_nsec);
 	OFFSET(STAMP_XTIME, vdso_data, stamp_xtime);
 	OFFSET(STAMP_SEC_FRAC, vdso_data, stamp_sec_fraction);
+	OFFSET(CLOCK_HRTIMER_RES, vdso_data, hrtimer_res);
 	OFFSET(CFG_ICACHE_BLOCKSZ, vdso_data, icache_block_size);
 	OFFSET(CFG_DCACHE_BLOCKSZ, vdso_data, dcache_block_size);
 	OFFSET(CFG_ICACHE_LOGBLOCKSZ, vdso_data, icache_log_block_size);
@@ -417,7 +418,6 @@
 	DEFINE(CLOCK_REALTIME_COARSE, CLOCK_REALTIME_COARSE);
 	DEFINE(CLOCK_MONOTONIC_COARSE, CLOCK_MONOTONIC_COARSE);
 	DEFINE(NSEC_PER_SEC, NSEC_PER_SEC);
-	DEFINE(CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC);
 
 #ifdef CONFIG_BUG
 	DEFINE(BUG_ENTRY_SIZE, sizeof(struct bug_entry));
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/btext.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/btext.c
@@ -250,8 +250,10 @@
 			rc = btext_initialize(np);
 			printk("result: %d\n", rc);
 		}
-		if (rc == 0)
+		if (rc == 0) {
+			of_node_put(np);
 			break;
+		}
 	}
 	return rc;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/cpu_setup_power.S
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/cpu_setup_power.S
@@ -184,7 +184,7 @@
 
 __init_FSCR:
 	mfspr	r3,SPRN_FSCR
-	ori	r3,r3,FSCR_TAR|FSCR_DSCR|FSCR_EBB
+	ori	r3,r3,FSCR_TAR|FSCR_EBB
 	mtspr	SPRN_FSCR,r3
 	blr
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/cputable.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/cputable.c
@@ -2193,11 +2193,13 @@
 		 * oprofile_cpu_type already has a value, then we are
 		 * possibly overriding a real PVR with a logical one,
 		 * and, in that case, keep the current value for
-		 * oprofile_cpu_type.
+		 * oprofile_cpu_type. Futhermore, let's ensure that the
+		 * fix for the PMAO bug is enabled on compatibility mode.
 		 */
 		if (old.oprofile_cpu_type != NULL) {
 			t->oprofile_cpu_type = old.oprofile_cpu_type;
 			t->oprofile_type = old.oprofile_type;
+			t->cpu_features |= old.cpu_features & CPU_FTR_PMAO_BUG;
 		}
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/dma-iommu.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/dma-iommu.c
@@ -160,7 +160,8 @@
 			return bypass_mask;
 	}
 
-	mask = 1ULL < (fls_long(tbl->it_offset + tbl->it_size) - 1);
+	mask = 1ULL << (fls_long(tbl->it_offset + tbl->it_size) +
+			tbl->it_page_shift - 1);
 	mask += mask - 1;
 
 	return mask;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/dt_cpu_ftrs.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/dt_cpu_ftrs.c
@@ -139,7 +139,6 @@
 	/* Initialize the base environment -- clear FSCR/HFSCR.  */
 	hv_mode = !!(mfmsr() & MSR_HV);
 	if (hv_mode) {
-		/* CPU_FTR_HVMODE is used early in PACA setup */
 		cur_cpu_spec->cpu_features |= CPU_FTR_HVMODE;
 		mtspr(SPRN_HFSCR, 0);
 	}
@@ -347,6 +346,14 @@
 {
 	u64 lpcr;
 
+	/*
+	 * Linux relies on FSCR[DSCR] being clear, so that we can take the
+	 * facility unavailable interrupt and track the task's usage of DSCR.
+	 * See facility_unavailable_exception().
+	 * Clear the bit here so that feat_enable() doesn't set it.
+	 */
+	f->fscr_bit_nr = -1;
+
 	feat_enable(f);
 
 	lpcr = mfspr(SPRN_LPCR);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/eeh.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/eeh.c
@@ -368,14 +368,11 @@
 	pa = pte_pfn(*ptep);
 
 	/* On radix we can do hugepage mappings for io, so handle that */
-	if (hugepage_shift) {
-		pa <<= hugepage_shift;
-		pa |= token & ((1ul << hugepage_shift) - 1);
-	} else {
-		pa <<= PAGE_SHIFT;
-		pa |= token & (PAGE_SIZE - 1);
-	}
+	if (!hugepage_shift)
+		hugepage_shift = PAGE_SHIFT;
 
+	pa <<= PAGE_SHIFT;
+	pa |= token & ((1ul << hugepage_shift) - 1);
 	return pa;
 }
 
@@ -503,7 +500,7 @@
 	rc = 1;
 	if (pe->state & EEH_PE_ISOLATED) {
 		pe->check_count++;
-		if (pe->check_count % EEH_MAX_FAILS == 0) {
+		if (pe->check_count == EEH_MAX_FAILS) {
 			dn = pci_device_to_OF_node(dev);
 			if (dn)
 				location = of_get_property(dn, "ibm,loc-code",
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/eeh_cache.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/eeh_cache.c
@@ -272,8 +272,9 @@
 {
 	struct pci_io_addr_range *piar;
 	struct rb_node *n;
+	unsigned long flags;
 
-	spin_lock(&pci_io_addr_cache_root.piar_lock);
+	spin_lock_irqsave(&pci_io_addr_cache_root.piar_lock, flags);
 	for (n = rb_first(&pci_io_addr_cache_root.rb_root); n; n = rb_next(n)) {
 		piar = rb_entry(n, struct pci_io_addr_range, rb_node);
 
@@ -281,7 +282,7 @@
 		       (piar->flags & IORESOURCE_IO) ? "i/o" : "mem",
 		       &piar->addr_lo, &piar->addr_hi, pci_name(piar->pcidev));
 	}
-	spin_unlock(&pci_io_addr_cache_root.piar_lock);
+	spin_unlock_irqrestore(&pci_io_addr_cache_root.piar_lock, flags);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/eeh_driver.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/eeh_driver.c
@@ -541,12 +541,6 @@
 
 		pci_iov_remove_virtfn(edev->physfn, pdn->vf_index);
 		edev->pdev = NULL;
-
-		/*
-		 * We have to set the VF PE number to invalid one, which is
-		 * required to plug the VF successfully.
-		 */
-		pdn->pe_number = IODA_INVALID_PE;
 #endif
 		if (rmv_data)
 			list_add(&edev->rmv_entry, &rmv_data->removed_vf_list);
@@ -897,12 +891,12 @@
 
 	/* Log the event */
 	if (pe->type & EEH_PE_PHB) {
-		pr_err("EEH: PHB#%x failure detected, location: %s\n",
+		pr_err("EEH: Recovering PHB#%x, location: %s\n",
 			pe->phb->global_number, eeh_pe_loc_get(pe));
 	} else {
 		struct eeh_pe *phb_pe = eeh_phb_pe_get(pe->phb);
 
-		pr_err("EEH: Frozen PHB#%x-PE#%x detected\n",
+		pr_err("EEH: Recovering PHB#%x-PE#%x\n",
 		       pe->phb->global_number, pe->addr);
 		pr_err("EEH: PE location: %s, PHB location: %s\n",
 		       eeh_pe_loc_get(pe), eeh_pe_loc_get(phb_pe));
@@ -1078,45 +1072,46 @@
 		}
 
 		pr_info("EEH: Recovery successful.\n");
-	} else  {
-		/*
-		 * About 90% of all real-life EEH failures in the field
-		 * are due to poorly seated PCI cards. Only 10% or so are
-		 * due to actual, failed cards.
-		 */
-		pr_err("EEH: Unable to recover from failure from PHB#%x-PE#%x.\n"
-		       "Please try reseating or replacing it\n",
-			pe->phb->global_number, pe->addr);
-
-		eeh_slot_error_detail(pe, EEH_LOG_PERM);
+		goto out;
+	}
 
-		/* Notify all devices that they're about to go down. */
-		eeh_set_channel_state(pe, pci_channel_io_perm_failure);
-		eeh_set_irq_state(pe, false);
-		eeh_pe_report("error_detected(permanent failure)", pe,
-			      eeh_report_failure, NULL);
+	/*
+	 * About 90% of all real-life EEH failures in the field
+	 * are due to poorly seated PCI cards. Only 10% or so are
+	 * due to actual, failed cards.
+	 */
+	pr_err("EEH: Unable to recover from failure from PHB#%x-PE#%x.\n"
+		"Please try reseating or replacing it\n",
+		pe->phb->global_number, pe->addr);
+
+	eeh_slot_error_detail(pe, EEH_LOG_PERM);
+
+	/* Notify all devices that they're about to go down. */
+	eeh_set_irq_state(pe, false);
+	eeh_pe_report("error_detected(permanent failure)", pe,
+		      eeh_report_failure, NULL);
+	eeh_set_channel_state(pe, pci_channel_io_perm_failure);
 
-		/* Mark the PE to be removed permanently */
-		eeh_pe_state_mark(pe, EEH_PE_REMOVED);
+	/* Mark the PE to be removed permanently */
+	eeh_pe_state_mark(pe, EEH_PE_REMOVED);
 
-		/*
-		 * Shut down the device drivers for good. We mark
-		 * all removed devices correctly to avoid access
-		 * the their PCI config any more.
-		 */
-		if (pe->type & EEH_PE_VF) {
-			eeh_pe_dev_traverse(pe, eeh_rmv_device, NULL);
-			eeh_pe_dev_mode_mark(pe, EEH_DEV_REMOVED);
-		} else {
-			eeh_pe_state_clear(pe, EEH_PE_PRI_BUS, true);
-			eeh_pe_dev_mode_mark(pe, EEH_DEV_REMOVED);
+	/*
+	 * Shut down the device drivers for good. We mark
+	 * all removed devices correctly to avoid access
+	 * the their PCI config any more.
+	 */
+	if (pe->type & EEH_PE_VF) {
+		eeh_pe_dev_traverse(pe, eeh_rmv_device, NULL);
+		eeh_pe_dev_mode_mark(pe, EEH_DEV_REMOVED);
+	} else {
+		eeh_pe_state_clear(pe, EEH_PE_PRI_BUS, true);
+		eeh_pe_dev_mode_mark(pe, EEH_DEV_REMOVED);
 
-			pci_lock_rescan_remove();
-			pci_hp_remove_devices(bus);
-			pci_unlock_rescan_remove();
-			/* The passed PE should no longer be used */
-			return;
-		}
+		pci_lock_rescan_remove();
+		pci_hp_remove_devices(bus);
+		pci_unlock_rescan_remove();
+		/* The passed PE should no longer be used */
+		return;
 	}
 
 out:
@@ -1206,6 +1201,17 @@
 			eeh_pe_state_mark(pe, EEH_PE_RECOVERING);
 			eeh_handle_normal_event(pe);
 		} else {
+			eeh_for_each_pe(pe, tmp_pe)
+				eeh_pe_for_each_dev(tmp_pe, edev, tmp_edev)
+					edev->mode &= ~EEH_DEV_NO_HANDLER;
+
+			/* Notify all devices to be down */
+			eeh_pe_state_clear(pe, EEH_PE_PRI_BUS, true);
+			eeh_pe_report(
+				"error_detected(permanent failure)", pe,
+				eeh_report_failure, NULL);
+			eeh_set_channel_state(pe, pci_channel_io_perm_failure);
+
 			pci_lock_rescan_remove();
 			list_for_each_entry(hose, &hose_list, list_node) {
 				phb_pe = eeh_phb_pe_get(hose);
@@ -1214,16 +1220,6 @@
 				    (phb_pe->state & EEH_PE_RECOVERING))
 					continue;
 
-				eeh_for_each_pe(pe, tmp_pe)
-					eeh_pe_for_each_dev(tmp_pe, edev, tmp_edev)
-						edev->mode &= ~EEH_DEV_NO_HANDLER;
-
-				/* Notify all devices to be down */
-				eeh_pe_state_clear(pe, EEH_PE_PRI_BUS, true);
-				eeh_set_channel_state(pe, pci_channel_io_perm_failure);
-				eeh_pe_report(
-					"error_detected(permanent failure)", pe,
-					eeh_report_failure, NULL);
 				bus = eeh_pe_bus_get(phb_pe);
 				if (!bus) {
 					pr_err("%s: Cannot find PCI bus for "
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/eeh_pe.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/eeh_pe.c
@@ -922,6 +922,7 @@
 {
 	struct eeh_dev *edev;
 	struct pci_dev *pdev;
+	struct pci_bus *bus = NULL;
 
 	if (pe->type & EEH_PE_PHB)
 		return pe->phb->bus;
@@ -932,9 +933,11 @@
 
 	/* Retrieve the parent PCI bus of first (top) PCI device */
 	edev = list_first_entry_or_null(&pe->edevs, struct eeh_dev, entry);
+	pci_lock_rescan_remove();
 	pdev = eeh_dev_to_pci_dev(edev);
 	if (pdev)
-		return pdev->bus;
+		bus = pdev->bus;
+	pci_unlock_rescan_remove();
 
-	return NULL;
+	return bus;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/entry_32.S
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/entry_32.S
@@ -179,7 +179,7 @@
 2:	/* if from kernel, check interrupted DOZE/NAP mode and
          * check for stack overflow
          */
-	kuap_save_and_lock r11, r12, r9, r2, r0
+	kuap_save_and_lock r11, r12, r9, r2, r6
 	addi	r2, r12, -THREAD
 	lwz	r9,KSP_LIMIT(r12)
 	cmplw	r1,r9			/* if r1 <= ksp_limit */
@@ -284,6 +284,7 @@
 	rlwinm	r9,r9,0,~MSR_EE
 	lwz	r12,_LINK(r11)		/* and return to address in LR */
 	kuap_restore r11, r2, r3, r4, r5
+	lwz	r2, GPR2(r11)
 	b	fast_exception_return
 #endif
 
@@ -335,6 +336,9 @@
 
 	.globl	transfer_to_syscall
 transfer_to_syscall:
+#ifdef CONFIG_PPC_BOOK3S_32
+	kuep_lock r11, r12
+#endif
 #ifdef CONFIG_TRACE_IRQFLAGS
 	andi.	r12,r9,MSR_EE
 	beq-	trace_syscall_entry_irq_off
@@ -704,7 +708,7 @@
 	stw	r10,_CCR(r1)
 	stw	r1,KSP(r3)	/* Set old stack pointer */
 
-	kuap_check r2, r4
+	kuap_check r2, r0
 #ifdef CONFIG_SMP
 	/* We need a sync somewhere here to make sure that if the
 	 * previous task gets rescheduled on another CPU, it sees all
@@ -777,7 +781,7 @@
 1:	lis	r3,exc_exit_restart_end@ha
 	addi	r3,r3,exc_exit_restart_end@l
 	cmplw	r12,r3
-#if CONFIG_PPC_BOOK3S_601
+#ifdef CONFIG_PPC_BOOK3S_601
 	bge	2b
 #else
 	bge	3f
@@ -785,7 +789,7 @@
 	lis	r4,exc_exit_restart@ha
 	addi	r4,r4,exc_exit_restart@l
 	cmplw	r12,r4
-#if CONFIG_PPC_BOOK3S_601
+#ifdef CONFIG_PPC_BOOK3S_601
 	blt	2b
 #else
 	blt	3f
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/entry_64.S
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/entry_64.S
@@ -537,6 +537,7 @@
 	/* Save LR into r9 */
 	mflr	r9
 
+	// Flush the link stack
 	.rept 64
 	bl	.+4
 	.endr
@@ -546,6 +547,11 @@
 	.balign 32
 	/* Restore LR */
 1:	mtlr	r9
+
+	// If we're just flushing the link stack, return here
+3:	nop
+	patch_site 3b patch__flush_link_stack_return
+
 	li	r9,0x7fff
 	mtctr	r9
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/exceptions-64s.S
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/exceptions-64s.S
@@ -1090,17 +1090,19 @@
 	bl	machine_check_queue_event
 
 	/*
-	 * We have not used any non-volatile GPRs here, and as a rule
-	 * most exception code including machine check does not.
-	 * Therefore PACA_NAPSTATELOST does not need to be set. Idle
-	 * wakeup will restore volatile registers.
+	 * GPR-loss wakeups are relatively straightforward, because the
+	 * idle sleep code has saved all non-volatile registers on its
+	 * own stack, and r1 in PACAR1.
 	 *
-	 * Load the original SRR1 into r3 for pnv_powersave_wakeup_mce.
+	 * For no-loss wakeups the r1 and lr registers used by the
+	 * early machine check handler have to be restored first. r2 is
+	 * the kernel TOC, so no need to restore it.
 	 *
 	 * Then decrement MCE nesting after finishing with the stack.
 	 */
 	ld	r3,_MSR(r1)
 	ld	r4,_LINK(r1)
+	ld	r1,GPR1(r1)
 
 	lhz	r11,PACA_IN_MCE(r13)
 	subi	r11,r11,1
@@ -1109,7 +1111,7 @@
 	mtlr	r4
 	rlwinm	r10,r3,47-31,30,31
 	cmpwi	cr1,r10,2
-	bltlr	cr1	/* no state loss, return to idle caller */
+	bltlr	cr1	/* no state loss, return to idle caller with r3=SRR1 */
 	b	idle_return_gpr_loss
 #endif
 
@@ -1148,7 +1150,7 @@
 	INT_HANDLER data_access, 0x300, ool=1, dar=1, dsisr=1, kvm=1
 EXC_REAL_END(data_access, 0x300, 0x80)
 EXC_VIRT_BEGIN(data_access, 0x4300, 0x80)
-	INT_HANDLER data_access, 0x300, virt=1, dar=1, dsisr=1
+	INT_HANDLER data_access, 0x300, ool=1, virt=1, dar=1, dsisr=1
 EXC_VIRT_END(data_access, 0x4300, 0x80)
 INT_KVM_HANDLER data_access, 0x300, EXC_STD, PACA_EXGEN, 1
 EXC_COMMON_BEGIN(data_access_common)
@@ -1203,7 +1205,7 @@
 
 
 EXC_REAL_BEGIN(instruction_access, 0x400, 0x80)
-	INT_HANDLER instruction_access, 0x400, kvm=1
+	INT_HANDLER instruction_access, 0x400, ool=1, kvm=1
 EXC_REAL_END(instruction_access, 0x400, 0x80)
 EXC_VIRT_BEGIN(instruction_access, 0x4400, 0x80)
 	INT_HANDLER instruction_access, 0x400, virt=1
@@ -1223,7 +1225,7 @@
 
 
 EXC_REAL_BEGIN(instruction_access_slb, 0x480, 0x80)
-	INT_HANDLER instruction_access_slb, 0x480, area=PACA_EXSLB, kvm=1
+	INT_HANDLER instruction_access_slb, 0x480, ool=1, area=PACA_EXSLB, kvm=1
 EXC_REAL_END(instruction_access_slb, 0x480, 0x80)
 EXC_VIRT_BEGIN(instruction_access_slb, 0x4480, 0x80)
 	INT_HANDLER instruction_access_slb, 0x480, virt=1, area=PACA_EXSLB
@@ -1363,17 +1365,17 @@
 	INT_HANDLER decrementer, 0x900, ool=1, bitmask=IRQS_DISABLED, kvm=1
 EXC_REAL_END(decrementer, 0x900, 0x80)
 EXC_VIRT_BEGIN(decrementer, 0x4900, 0x80)
-	INT_HANDLER decrementer, 0x900, virt=1, bitmask=IRQS_DISABLED
+	INT_HANDLER decrementer, 0x900, ool=1, virt=1, bitmask=IRQS_DISABLED
 EXC_VIRT_END(decrementer, 0x4900, 0x80)
 INT_KVM_HANDLER decrementer, 0x900, EXC_STD, PACA_EXGEN, 0
 EXC_COMMON_ASYNC(decrementer_common, 0x900, timer_interrupt)
 
 
 EXC_REAL_BEGIN(hdecrementer, 0x980, 0x80)
-	INT_HANDLER hdecrementer, 0x980, hsrr=EXC_HV, kvm=1
+	INT_HANDLER hdecrementer, 0x980, ool=1, hsrr=EXC_HV, kvm=1
 EXC_REAL_END(hdecrementer, 0x980, 0x80)
 EXC_VIRT_BEGIN(hdecrementer, 0x4980, 0x80)
-	INT_HANDLER hdecrementer, 0x980, virt=1, hsrr=EXC_HV, kvm=1
+	INT_HANDLER hdecrementer, 0x980, ool=1, virt=1, hsrr=EXC_HV, kvm=1
 EXC_VIRT_END(hdecrementer, 0x4980, 0x80)
 INT_KVM_HANDLER hdecrementer, 0x980, EXC_HV, PACA_EXGEN, 0
 EXC_COMMON(hdecrementer_common, 0x980, hdec_interrupt)
@@ -2044,15 +2046,8 @@
 	.endr
 	blr
 
-TRAMP_REAL_BEGIN(rfi_flush_fallback)
-	SET_SCRATCH0(r13);
-	GET_PACA(r13);
-	std	r1,PACA_EXRFI+EX_R12(r13)
-	ld	r1,PACAKSAVE(r13)
-	std	r9,PACA_EXRFI+EX_R9(r13)
-	std	r10,PACA_EXRFI+EX_R10(r13)
-	std	r11,PACA_EXRFI+EX_R11(r13)
-	mfctr	r9
+/* Clobbers r10, r11, ctr */
+.macro L1D_DISPLACEMENT_FLUSH
 	ld	r10,PACA_RFI_FLUSH_FALLBACK_AREA(r13)
 	ld	r11,PACA_L1D_FLUSH_SIZE(r13)
 	srdi	r11,r11,(7 + 3) /* 128 byte lines, unrolled 8x */
@@ -2063,7 +2058,7 @@
 	sync
 
 	/*
-	 * The load adresses are at staggered offsets within cachelines,
+	 * The load addresses are at staggered offsets within cachelines,
 	 * which suits some pipelines better (on others it should not
 	 * hurt).
 	 */
@@ -2078,7 +2073,30 @@
 	ld	r11,(0x80 + 8)*7(r10)
 	addi	r10,r10,0x80*8
 	bdnz	1b
+.endm
 
+TRAMP_REAL_BEGIN(entry_flush_fallback)
+	std	r9,PACA_EXRFI+EX_R9(r13)
+	std	r10,PACA_EXRFI+EX_R10(r13)
+	std	r11,PACA_EXRFI+EX_R11(r13)
+	mfctr	r9
+	L1D_DISPLACEMENT_FLUSH
+	mtctr	r9
+	ld	r9,PACA_EXRFI+EX_R9(r13)
+	ld	r10,PACA_EXRFI+EX_R10(r13)
+	ld	r11,PACA_EXRFI+EX_R11(r13)
+	blr
+
+TRAMP_REAL_BEGIN(rfi_flush_fallback)
+	SET_SCRATCH0(r13);
+	GET_PACA(r13);
+	std	r1,PACA_EXRFI+EX_R12(r13)
+	ld	r1,PACAKSAVE(r13)
+	std	r9,PACA_EXRFI+EX_R9(r13)
+	std	r10,PACA_EXRFI+EX_R10(r13)
+	std	r11,PACA_EXRFI+EX_R11(r13)
+	mfctr	r9
+	L1D_DISPLACEMENT_FLUSH
 	mtctr	r9
 	ld	r9,PACA_EXRFI+EX_R9(r13)
 	ld	r10,PACA_EXRFI+EX_R10(r13)
@@ -2096,32 +2114,7 @@
 	std	r10,PACA_EXRFI+EX_R10(r13)
 	std	r11,PACA_EXRFI+EX_R11(r13)
 	mfctr	r9
-	ld	r10,PACA_RFI_FLUSH_FALLBACK_AREA(r13)
-	ld	r11,PACA_L1D_FLUSH_SIZE(r13)
-	srdi	r11,r11,(7 + 3) /* 128 byte lines, unrolled 8x */
-	mtctr	r11
-	DCBT_BOOK3S_STOP_ALL_STREAM_IDS(r11) /* Stop prefetch streams */
-
-	/* order ld/st prior to dcbt stop all streams with flushing */
-	sync
-
-	/*
-	 * The load adresses are at staggered offsets within cachelines,
-	 * which suits some pipelines better (on others it should not
-	 * hurt).
-	 */
-1:
-	ld	r11,(0x80 + 8)*0(r10)
-	ld	r11,(0x80 + 8)*1(r10)
-	ld	r11,(0x80 + 8)*2(r10)
-	ld	r11,(0x80 + 8)*3(r10)
-	ld	r11,(0x80 + 8)*4(r10)
-	ld	r11,(0x80 + 8)*5(r10)
-	ld	r11,(0x80 + 8)*6(r10)
-	ld	r11,(0x80 + 8)*7(r10)
-	addi	r10,r10,0x80*8
-	bdnz	1b
-
+	L1D_DISPLACEMENT_FLUSH
 	mtctr	r9
 	ld	r9,PACA_EXRFI+EX_R9(r13)
 	ld	r10,PACA_EXRFI+EX_R10(r13)
@@ -2130,6 +2123,19 @@
 	GET_SCRATCH0(r13);
 	hrfid
 
+USE_TEXT_SECTION()
+
+_GLOBAL(do_uaccess_flush)
+	UACCESS_FLUSH_FIXUP_SECTION
+	nop
+	nop
+	nop
+	blr
+	L1D_DISPLACEMENT_FLUSH
+	blr
+_ASM_NOKPROBE_SYMBOL(do_uaccess_flush)
+EXPORT_SYMBOL(do_uaccess_flush)
+
 /*
  * Real mode exceptions actually use this too, but alternate
  * instruction code patches (which end up in the common .text area)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/fadump.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/fadump.c
@@ -38,8 +38,17 @@
 
 #ifndef CONFIG_PRESERVE_FA_DUMP
 static DEFINE_MUTEX(fadump_mutex);
-struct fadump_mrange_info crash_mrange_info = { "crash", NULL, 0, 0, 0 };
-struct fadump_mrange_info reserved_mrange_info = { "reserved", NULL, 0, 0, 0 };
+struct fadump_mrange_info crash_mrange_info = { "crash", NULL, 0, 0, 0, false };
+
+#define RESERVED_RNGS_SZ	16384 /* 16K - 128 entries */
+#define RESERVED_RNGS_CNT	(RESERVED_RNGS_SZ / \
+				 sizeof(struct fadump_memory_range))
+static struct fadump_memory_range rngs[RESERVED_RNGS_CNT];
+struct fadump_mrange_info reserved_mrange_info = { "reserved", rngs,
+						   RESERVED_RNGS_SZ, 0,
+						   RESERVED_RNGS_CNT, true };
+
+static void __init early_init_dt_scan_reserved_ranges(unsigned long node);
 
 #ifdef CONFIG_CMA
 static struct cma *fadump_cma;
@@ -108,6 +117,11 @@
 int __init early_init_dt_scan_fw_dump(unsigned long node, const char *uname,
 				      int depth, void *data)
 {
+	if (depth == 0) {
+		early_init_dt_scan_reserved_ranges(node);
+		return 0;
+	}
+
 	if (depth != 1)
 		return 0;
 
@@ -265,7 +279,7 @@
  * that is required for a kernel to boot successfully.
  *
  */
-static inline u64 fadump_calculate_reserve_size(void)
+static __init u64 fadump_calculate_reserve_size(void)
 {
 	u64 base, size, bootmem_min;
 	int ret;
@@ -429,10 +443,72 @@
 	return ret;
 }
 
+/*
+ * Returns true, if the given range overlaps with reserved memory ranges
+ * starting at idx. Also, updates idx to index of overlapping memory range
+ * with the given memory range.
+ * False, otherwise.
+ */
+static bool overlaps_reserved_ranges(u64 base, u64 end, int *idx)
+{
+	bool ret = false;
+	int i;
+
+	for (i = *idx; i < reserved_mrange_info.mem_range_cnt; i++) {
+		u64 rbase = reserved_mrange_info.mem_ranges[i].base;
+		u64 rend = rbase + reserved_mrange_info.mem_ranges[i].size;
+
+		if (end <= rbase)
+			break;
+
+		if ((end > rbase) &&  (base < rend)) {
+			*idx = i;
+			ret = true;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+/*
+ * Locate a suitable memory area to reserve memory for FADump. While at it,
+ * lookup reserved-ranges & avoid overlap with them, as they are used by F/W.
+ */
+static u64 __init fadump_locate_reserve_mem(u64 base, u64 size)
+{
+	struct fadump_memory_range *mrngs;
+	phys_addr_t mstart, mend;
+	int idx = 0;
+	u64 i, ret = 0;
+
+	mrngs = reserved_mrange_info.mem_ranges;
+	for_each_free_mem_range(i, NUMA_NO_NODE, MEMBLOCK_NONE,
+				&mstart, &mend, NULL) {
+		pr_debug("%llu) mstart: %llx, mend: %llx, base: %llx\n",
+			 i, mstart, mend, base);
+
+		if (mstart > base)
+			base = PAGE_ALIGN(mstart);
+
+		while ((mend > base) && ((mend - base) >= size)) {
+			if (!overlaps_reserved_ranges(base, base+size, &idx)) {
+				ret = base;
+				goto out;
+			}
+
+			base = mrngs[idx].base + mrngs[idx].size;
+			base = PAGE_ALIGN(base);
+		}
+	}
+
+out:
+	return ret;
+}
+
 int __init fadump_reserve_mem(void)
 {
-	u64 base, size, mem_boundary, bootmem_min, align = PAGE_SIZE;
-	bool is_memblock_bottom_up = memblock_bottom_up();
+	u64 base, size, mem_boundary, bootmem_min;
 	int ret = 1;
 
 	if (!fw_dump.fadump_enabled)
@@ -453,9 +529,9 @@
 			PAGE_ALIGN(fadump_calculate_reserve_size());
 #ifdef CONFIG_CMA
 		if (!fw_dump.nocma) {
-			align = FADUMP_CMA_ALIGNMENT;
 			fw_dump.boot_memory_size =
-				ALIGN(fw_dump.boot_memory_size, align);
+				ALIGN(fw_dump.boot_memory_size,
+				      FADUMP_CMA_ALIGNMENT);
 		}
 #endif
 
@@ -523,13 +599,9 @@
 		 * Reserve memory at an offset closer to bottom of the RAM to
 		 * minimize the impact of memory hot-remove operation.
 		 */
-		memblock_set_bottom_up(true);
-		base = memblock_find_in_range(base, mem_boundary, size, align);
-
-		/* Restore the previous allocation mode */
-		memblock_set_bottom_up(is_memblock_bottom_up);
+		base = fadump_locate_reserve_mem(base, size);
 
-		if (!base) {
+		if (!base || (base + size > mem_boundary)) {
 			pr_err("Failed to find memory chunk for reservation!\n");
 			goto error_out;
 		}
@@ -557,6 +629,7 @@
 	return ret;
 error_out:
 	fw_dump.fadump_enabled = 0;
+	fw_dump.reserve_dump_area_size = 0;
 	return 0;
 }
 
@@ -726,10 +799,14 @@
 
 static void fadump_free_mem_ranges(struct fadump_mrange_info *mrange_info)
 {
+	if (mrange_info->is_static) {
+		mrange_info->mem_range_cnt = 0;
+		return;
+	}
+
 	kfree(mrange_info->mem_ranges);
-	mrange_info->mem_ranges = NULL;
-	mrange_info->mem_ranges_sz = 0;
-	mrange_info->max_mem_ranges = 0;
+	memset((void *)((u64)mrange_info + RNG_NAME_SZ), 0,
+	       (sizeof(struct fadump_mrange_info) - RNG_NAME_SZ));
 }
 
 /*
@@ -759,7 +836,6 @@
 				       sizeof(struct fadump_memory_range));
 	return 0;
 }
-
 static inline int fadump_add_mem_range(struct fadump_mrange_info *mrange_info,
 				       u64 base, u64 end)
 {
@@ -778,7 +854,12 @@
 		start = mem_ranges[mrange_info->mem_range_cnt - 1].base;
 		size  = mem_ranges[mrange_info->mem_range_cnt - 1].size;
 
-		if ((start + size) == base)
+		/*
+		 * Boot memory area needs separate PT_LOAD segment(s) as it
+		 * is moved to a different location at the time of crash.
+		 * So, fold only if the region is not boot memory area.
+		 */
+		if ((start + size) == base && start >= fw_dump.boot_mem_top)
 			is_adjacent = true;
 	}
 	if (!is_adjacent) {
@@ -786,6 +867,12 @@
 		if (mrange_info->mem_range_cnt == mrange_info->max_mem_ranges) {
 			int ret;
 
+			if (mrange_info->is_static) {
+				pr_err("Reached array size limit for %s memory ranges\n",
+				       mrange_info->name);
+				return -ENOSPC;
+			}
+
 			ret = fadump_alloc_mem_ranges(mrange_info);
 			if (ret)
 				return ret;
@@ -1202,20 +1289,19 @@
  * Scan reserved-ranges to consider them while reserving/releasing
  * memory for FADump.
  */
-static inline int fadump_scan_reserved_mem_ranges(void)
+static void __init early_init_dt_scan_reserved_ranges(unsigned long node)
 {
-	struct device_node *root;
 	const __be32 *prop;
 	int len, ret = -1;
 	unsigned long i;
 
-	root = of_find_node_by_path("/");
-	if (!root)
-		return ret;
+	/* reserved-ranges already scanned */
+	if (reserved_mrange_info.mem_range_cnt != 0)
+		return;
 
-	prop = of_get_property(root, "reserved-ranges", &len);
+	prop = of_get_flat_dt_prop(node, "reserved-ranges", &len);
 	if (!prop)
-		return ret;
+		return;
 
 	/*
 	 * Each reserved range is an (address,size) pair, 2 cells each,
@@ -1237,7 +1323,8 @@
 		}
 	}
 
-	return ret;
+	/* Compact reserved ranges */
+	sort_and_merge_mem_ranges(&reserved_mrange_info);
 }
 
 /*
@@ -1251,32 +1338,21 @@
 	u64 ra_start, ra_end, tstart;
 	int i, ret;
 
-	fadump_scan_reserved_mem_ranges();
-
 	ra_start = fw_dump.reserve_dump_area_start;
 	ra_end = ra_start + fw_dump.reserve_dump_area_size;
 
 	/*
-	 * Add reserved dump area to reserved ranges list
-	 * and exclude all these ranges while releasing memory.
+	 * If reserved ranges array limit is hit, overwrite the last reserved
+	 * memory range with reserved dump area to ensure it is excluded from
+	 * the memory being released (reused for next FADump registration).
 	 */
-	ret = fadump_add_mem_range(&reserved_mrange_info, ra_start, ra_end);
-	if (ret != 0) {
-		/*
-		 * Not enough memory to setup reserved ranges but the system is
-		 * running shortage of memory. So, release all the memory except
-		 * Reserved dump area (reused for next fadump registration).
-		 */
-		if (begin < ra_end && end > ra_start) {
-			if (begin < ra_start)
-				fadump_release_reserved_area(begin, ra_start);
-			if (end > ra_end)
-				fadump_release_reserved_area(ra_end, end);
-		} else
-			fadump_release_reserved_area(begin, end);
+	if (reserved_mrange_info.mem_range_cnt ==
+	    reserved_mrange_info.max_mem_ranges)
+		reserved_mrange_info.mem_range_cnt--;
 
+	ret = fadump_add_mem_range(&reserved_mrange_info, ra_start, ra_end);
+	if (ret != 0)
 		return;
-	}
 
 	/* Get the reserved ranges list in order first. */
 	sort_and_merge_mem_ranges(&reserved_mrange_info);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/fpu.S
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/fpu.S
@@ -24,6 +24,15 @@
 #include <asm/feature-fixups.h>
 
 #ifdef CONFIG_VSX
+#define __REST_1FPVSR(n,c,base)						\
+BEGIN_FTR_SECTION							\
+	b	2f;							\
+END_FTR_SECTION_IFSET(CPU_FTR_VSX);					\
+	REST_FPR(n,base);						\
+	b	3f;							\
+2:	REST_VSR(n,c,base);						\
+3:
+
 #define __REST_32FPVSRS(n,c,base)					\
 BEGIN_FTR_SECTION							\
 	b	2f;							\
@@ -42,9 +51,11 @@
 2:	SAVE_32VSRS(n,c,base);						\
 3:
 #else
+#define __REST_1FPVSR(n,b,base)		REST_FPR(n, base)
 #define __REST_32FPVSRS(n,b,base)	REST_32FPRS(n, base)
 #define __SAVE_32FPVSRS(n,b,base)	SAVE_32FPRS(n, base)
 #endif
+#define REST_1FPVSR(n,c,base)   __REST_1FPVSR(n,__REG_##c,__REG_##base)
 #define REST_32FPVSRS(n,c,base) __REST_32FPVSRS(n,__REG_##c,__REG_##base)
 #define SAVE_32FPVSRS(n,c,base) __SAVE_32FPVSRS(n,__REG_##c,__REG_##base)
 
@@ -68,6 +79,7 @@
 	SAVE_32FPVSRS(0, R4, R3)
 	mffs	fr0
 	stfd	fr0,FPSTATE_FPSCR(r3)
+	REST_1FPVSR(0, R4, R3)
 	blr
 EXPORT_SYMBOL(store_fp_state)
 
@@ -132,6 +144,7 @@
 2:	SAVE_32FPVSRS(0, R4, R6)
 	mffs	fr0
 	stfd	fr0,FPSTATE_FPSCR(r6)
+	REST_1FPVSR(0, R4, R6)
 	blr
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/head_32.S
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/head_32.S
@@ -418,14 +418,11 @@
 	cmplw	0,r1,r3
 #endif
 	mfspr	r2, SPRN_SPRG_PGDIR
-#ifdef CONFIG_SWAP
-	li	r1,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC
-#else
-	li	r1,_PAGE_PRESENT | _PAGE_EXEC
-#endif
+	li	r1,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC | _PAGE_USER
 #if defined(CONFIG_MODULES) || defined(CONFIG_DEBUG_PAGEALLOC)
 	bge-	112f
 	lis	r2, (swapper_pg_dir - PAGE_OFFSET)@ha	/* if kernel address, use */
+	li	r1,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC
 	addi	r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l	/* kernel page table */
 #endif
 112:	rlwimi	r2,r3,12,20,29		/* insert top 10 bits of address */
@@ -484,13 +481,10 @@
 	lis	r1,PAGE_OFFSET@h		/* check if kernel address */
 	cmplw	0,r1,r3
 	mfspr	r2, SPRN_SPRG_PGDIR
-#ifdef CONFIG_SWAP
-	li	r1, _PAGE_PRESENT | _PAGE_ACCESSED
-#else
-	li	r1, _PAGE_PRESENT
-#endif
+	li	r1, _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_USER
 	bge-	112f
 	lis	r2, (swapper_pg_dir - PAGE_OFFSET)@ha	/* if kernel address, use */
+	li	r1, _PAGE_PRESENT | _PAGE_ACCESSED
 	addi	r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l	/* kernel page table */
 112:	rlwimi	r2,r3,12,20,29		/* insert top 10 bits of address */
 	lwz	r2,0(r2)		/* get pmd entry */
@@ -564,13 +558,10 @@
 	lis	r1,PAGE_OFFSET@h		/* check if kernel address */
 	cmplw	0,r1,r3
 	mfspr	r2, SPRN_SPRG_PGDIR
-#ifdef CONFIG_SWAP
-	li	r1, _PAGE_RW | _PAGE_DIRTY | _PAGE_PRESENT | _PAGE_ACCESSED
-#else
-	li	r1, _PAGE_RW | _PAGE_DIRTY | _PAGE_PRESENT
-#endif
+	li	r1, _PAGE_RW | _PAGE_DIRTY | _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_USER
 	bge-	112f
 	lis	r2, (swapper_pg_dir - PAGE_OFFSET)@ha	/* if kernel address, use */
+	li	r1, _PAGE_RW | _PAGE_DIRTY | _PAGE_PRESENT | _PAGE_ACCESSED
 	addi	r2, r2, (swapper_pg_dir - PAGE_OFFSET)@l	/* kernel page table */
 112:	rlwimi	r2,r3,12,20,29		/* insert top 10 bits of address */
 	lwz	r2,0(r2)		/* get pmd entry */
@@ -843,7 +834,7 @@
 END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
 	blr
 
-load_segment_registers:
+_GLOBAL(load_segment_registers)
 	li	r0, NUM_USER_SEGMENTS /* load up user segment register values */
 	mtctr	r0		/* for context 0 */
 	li	r3, 0		/* Kp = 0, Ks = 0, VSID = 0 */
@@ -931,7 +922,7 @@
 	 */
 	lis	r5, abatron_pteptrs@h
 	ori	r5, r5, abatron_pteptrs@l
-	stw	r5, 0xf0(r0)	/* This much match your Abatron config */
+	stw	r5, 0xf0(0)	/* This much match your Abatron config */
 	lis	r6, swapper_pg_dir@h
 	ori	r6, r6, swapper_pg_dir@l
 	tophys(r5, r5)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/head_64.S
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/head_64.S
@@ -420,6 +420,10 @@
 	/* From now on, r24 is expected to be logical cpuid */
 	mr	r24,r5
 
+	/* Create a temp kernel stack for use before relocation is on.	*/
+	ld	r1,PACAEMERGSP(r13)
+	subi	r1,r1,STACK_FRAME_OVERHEAD
+
 	/* See if we need to call a cpu state restore handler */
 	LOAD_REG_ADDR(r23, cur_cpu_spec)
 	ld	r23,0(r23)
@@ -448,10 +452,6 @@
 	sync				/* order paca.run and cur_cpu_spec */
 	isync				/* In case code patching happened */
 
-	/* Create a temp kernel stack for use before relocation is on.	*/
-	ld	r1,PACAEMERGSP(r13)
-	subi	r1,r1,STACK_FRAME_OVERHEAD
-
 	b	__secondary_start
 #endif /* SMP */
 
@@ -945,15 +945,8 @@
 	std	r0,0(r4)
 #endif
 
-	/* The following gets the stack set up with the regs */
-	/* pointing to the real addr of the kernel stack.  This is   */
-	/* all done to support the C function call below which sets  */
-	/* up the htab.  This is done because we have relocated the  */
-	/* kernel but are still running in real mode. */
-
-	LOAD_REG_ADDR(r3,init_thread_union)
-
 	/* set up a stack pointer */
+	LOAD_REG_ADDR(r3,init_thread_union)
 	LOAD_REG_IMMEDIATE(r1,THREAD_SIZE)
 	add	r1,r3,r1
 	li	r0,0
@@ -999,7 +992,7 @@
 	bl	start_kernel
 
 	/* Not reached */
-	trap
+0:	trap
 	EMIT_BUG_ENTRY 0b, __FILE__, __LINE__, 0
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/head_8xx.S
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/head_8xx.S
@@ -191,7 +191,7 @@
 /* On the MPC8xx, this is a software emulation interrupt.  It occurs
  * for all unimplemented and illegal instructions.
  */
-	EXCEPTION(0x1000, SoftEmu, program_check_exception, EXC_XFER_STD)
+	EXCEPTION(0x1000, SoftEmu, emulation_assist_interrupt, EXC_XFER_STD)
 
 /* Called from DataStoreTLBMiss when perf TLB misses events are activated */
 #ifdef CONFIG_PERF_EVENTS
@@ -229,9 +229,7 @@
 
 InstructionTLBMiss:
 	mtspr	SPRN_SPRG_SCRATCH0, r10
-#if defined(ITLB_MISS_KERNEL) || defined(CONFIG_SWAP)
 	mtspr	SPRN_SPRG_SCRATCH1, r11
-#endif
 
 	/* If we are faulting a kernel address, we have to use the
 	 * kernel page tables.
@@ -278,27 +276,23 @@
 #ifdef ITLB_MISS_KERNEL
 	mtcr	r11
 #endif
-#ifdef CONFIG_SWAP
-	rlwinm	r11, r10, 32-5, _PAGE_PRESENT
+	rlwinm	r11, r10, 32-7, _PAGE_PRESENT
 	and	r11, r11, r10
 	rlwimi	r10, r11, 0, _PAGE_PRESENT
-#endif
 	/* The Linux PTE won't go exactly into the MMU TLB.
 	 * Software indicator bits 20 and 23 must be clear.
 	 * Software indicator bits 22, 24, 25, 26, and 27 must be
 	 * set.  All other Linux PTE bits control the behavior
 	 * of the MMU.
 	 */
-	rlwimi	r10, r10, 0, 0x0f00	/* Clear bits 20-23 */
+	rlwinm	r10, r10, 0, ~0x0f00	/* Clear bits 20-23 */
 	rlwimi	r10, r10, 4, 0x0400	/* Copy _PAGE_EXEC into bit 21 */
 	ori	r10, r10, RPN_PATTERN | 0x200 /* Set 22 and 24-27 */
 	mtspr	SPRN_MI_RPN, r10	/* Update TLB entry */
 
 	/* Restore registers */
 0:	mfspr	r10, SPRN_SPRG_SCRATCH0
-#if defined(ITLB_MISS_KERNEL) || defined(CONFIG_SWAP)
 	mfspr	r11, SPRN_SPRG_SCRATCH1
-#endif
 	rfi
 	patch_site	0b, patch__itlbmiss_exit_1
 
@@ -308,9 +302,7 @@
 	addi	r10, r10, 1
 	stw	r10, (itlb_miss_counter - PAGE_OFFSET)@l(0)
 	mfspr	r10, SPRN_SPRG_SCRATCH0
-#if defined(ITLB_MISS_KERNEL) || defined(CONFIG_SWAP)
 	mfspr	r11, SPRN_SPRG_SCRATCH1
-#endif
 	rfi
 #endif
 
@@ -394,11 +386,9 @@
 	 * r11 = ((r10 & PRESENT) & ((r10 & ACCESSED) >> 5));
 	 * r10 = (r10 & ~PRESENT) | r11;
 	 */
-#ifdef CONFIG_SWAP
-	rlwinm	r11, r10, 32-5, _PAGE_PRESENT
+	rlwinm	r11, r10, 32-7, _PAGE_PRESENT
 	and	r11, r11, r10
 	rlwimi	r10, r11, 0, _PAGE_PRESENT
-#endif
 	/* The Linux PTE won't go exactly into the MMU TLB.
 	 * Software indicator bits 24, 25, 26, and 27 must be
 	 * set.  All other Linux PTE bits control the behavior
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/head_fsl_booke.S
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/head_fsl_booke.S
@@ -238,6 +238,9 @@
 
 	bl	early_init
 
+#ifdef CONFIG_KASAN
+	bl	kasan_early_init
+#endif
 #ifdef CONFIG_RELOCATABLE
 	mr	r3,r30
 	mr	r4,r31
@@ -264,9 +267,6 @@
 /*
  * Decide what sort of machine this is and initialize the MMU.
  */
-#ifdef CONFIG_KASAN
-	bl	kasan_early_init
-#endif
 	mr	r3,r30
 	mr	r4,r31
 	bl	machine_init
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/hw_breakpoint.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/hw_breakpoint.c
@@ -247,6 +247,11 @@
 	return false;
 }
 
+/*
+ * Handle a DABR or DAWR exception.
+ *
+ * Called in atomic context.
+ */
 int hw_breakpoint_handler(struct die_args *args)
 {
 	int rc = NOTIFY_STOP;
@@ -315,6 +320,8 @@
 
 /*
  * Handle single-step exceptions following a DABR hit.
+ *
+ * Called in atomic context.
  */
 static int single_step_dabr_instruction(struct die_args *args)
 {
@@ -355,6 +362,8 @@
 
 /*
  * Handle debug exception notifications.
+ *
+ * Called in atomic context.
  */
 int hw_breakpoint_exceptions_notify(
 		struct notifier_block *unused, unsigned long val, void *data)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/idle.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/idle.c
@@ -37,7 +37,7 @@
 {
 	ppc_md.power_save = NULL;
 	cpuidle_disable = IDLE_POWERSAVE_OFF;
-	return 0;
+	return 1;
 }
 __setup("powersave=off", powersave_off);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/idle_6xx.S
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/idle_6xx.S
@@ -129,7 +129,7 @@
 END_FTR_SECTION_IFCLR(CPU_FTR_NO_DPM)
 	mtspr	SPRN_HID0,r4
 BEGIN_FTR_SECTION
-	DSSALL
+	PPC_DSSALL
 	sync
 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 	lwz	r8,TI_LOCAL_FLAGS(r2)	/* set napping bit */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/idle_book3s.S
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/idle_book3s.S
@@ -50,28 +50,32 @@
 	std	r1,PACAR1(r13)
 	mflr	r4
 	mfcr	r5
-	/* use stack red zone rather than a new frame for saving regs */
-	std	r2,-8*0(r1)
-	std	r14,-8*1(r1)
-	std	r15,-8*2(r1)
-	std	r16,-8*3(r1)
-	std	r17,-8*4(r1)
-	std	r18,-8*5(r1)
-	std	r19,-8*6(r1)
-	std	r20,-8*7(r1)
-	std	r21,-8*8(r1)
-	std	r22,-8*9(r1)
-	std	r23,-8*10(r1)
-	std	r24,-8*11(r1)
-	std	r25,-8*12(r1)
-	std	r26,-8*13(r1)
-	std	r27,-8*14(r1)
-	std	r28,-8*15(r1)
-	std	r29,-8*16(r1)
-	std	r30,-8*17(r1)
-	std	r31,-8*18(r1)
-	std	r4,-8*19(r1)
-	std	r5,-8*20(r1)
+	/*
+	 * Use the stack red zone rather than a new frame for saving regs since
+	 * in the case of no GPR loss the wakeup code branches directly back to
+	 * the caller without deallocating the stack frame first.
+	 */
+	std	r2,-8*1(r1)
+	std	r14,-8*2(r1)
+	std	r15,-8*3(r1)
+	std	r16,-8*4(r1)
+	std	r17,-8*5(r1)
+	std	r18,-8*6(r1)
+	std	r19,-8*7(r1)
+	std	r20,-8*8(r1)
+	std	r21,-8*9(r1)
+	std	r22,-8*10(r1)
+	std	r23,-8*11(r1)
+	std	r24,-8*12(r1)
+	std	r25,-8*13(r1)
+	std	r26,-8*14(r1)
+	std	r27,-8*15(r1)
+	std	r28,-8*16(r1)
+	std	r29,-8*17(r1)
+	std	r30,-8*18(r1)
+	std	r31,-8*19(r1)
+	std	r4,-8*20(r1)
+	std	r5,-8*21(r1)
 	/* 168 bytes */
 	PPC_STOP
 	b	.	/* catch bugs */
@@ -87,8 +91,8 @@
  */
 _GLOBAL(idle_return_gpr_loss)
 	ld	r1,PACAR1(r13)
-	ld	r4,-8*19(r1)
-	ld	r5,-8*20(r1)
+	ld	r4,-8*20(r1)
+	ld	r5,-8*21(r1)
 	mtlr	r4
 	mtcr	r5
 	/*
@@ -96,38 +100,40 @@
 	 * from PACATOC. This could be avoided for that less common case
 	 * if KVM saved its r2.
 	 */
-	ld	r2,-8*0(r1)
-	ld	r14,-8*1(r1)
-	ld	r15,-8*2(r1)
-	ld	r16,-8*3(r1)
-	ld	r17,-8*4(r1)
-	ld	r18,-8*5(r1)
-	ld	r19,-8*6(r1)
-	ld	r20,-8*7(r1)
-	ld	r21,-8*8(r1)
-	ld	r22,-8*9(r1)
-	ld	r23,-8*10(r1)
-	ld	r24,-8*11(r1)
-	ld	r25,-8*12(r1)
-	ld	r26,-8*13(r1)
-	ld	r27,-8*14(r1)
-	ld	r28,-8*15(r1)
-	ld	r29,-8*16(r1)
-	ld	r30,-8*17(r1)
-	ld	r31,-8*18(r1)
+	ld	r2,-8*1(r1)
+	ld	r14,-8*2(r1)
+	ld	r15,-8*3(r1)
+	ld	r16,-8*4(r1)
+	ld	r17,-8*5(r1)
+	ld	r18,-8*6(r1)
+	ld	r19,-8*7(r1)
+	ld	r20,-8*8(r1)
+	ld	r21,-8*9(r1)
+	ld	r22,-8*10(r1)
+	ld	r23,-8*11(r1)
+	ld	r24,-8*12(r1)
+	ld	r25,-8*13(r1)
+	ld	r26,-8*14(r1)
+	ld	r27,-8*15(r1)
+	ld	r28,-8*16(r1)
+	ld	r29,-8*17(r1)
+	ld	r30,-8*18(r1)
+	ld	r31,-8*19(r1)
 	blr
 
 /*
  * This is the sequence required to execute idle instructions, as
  * specified in ISA v2.07 (and earlier). MSR[IR] and MSR[DR] must be 0.
- *
- * The 0(r1) slot is used to save r2 in isa206, so use that here.
+ * We have to store a GPR somewhere, ptesync, then reload it, and create
+ * a false dependency on the result of the load. It doesn't matter which
+ * GPR we store, or where we store it. We have already stored r2 to the
+ * stack at -8(r1) in isa206_idle_insn_mayloss, so use that.
  */
 #define IDLE_STATE_ENTER_SEQ_NORET(IDLE_INST)			\
 	/* Magic NAP/SLEEP/WINKLE mode enter sequence */	\
-	std	r2,0(r1);					\
+	std	r2,-8(r1);					\
 	ptesync;						\
-	ld	r2,0(r1);					\
+	ld	r2,-8(r1);					\
 236:	cmpd	cr0,r2,r2;					\
 	bne	236b;						\
 	IDLE_INST;						\
@@ -152,28 +158,32 @@
 	std	r1,PACAR1(r13)
 	mflr	r4
 	mfcr	r5
-	/* use stack red zone rather than a new frame for saving regs */
-	std	r2,-8*0(r1)
-	std	r14,-8*1(r1)
-	std	r15,-8*2(r1)
-	std	r16,-8*3(r1)
-	std	r17,-8*4(r1)
-	std	r18,-8*5(r1)
-	std	r19,-8*6(r1)
-	std	r20,-8*7(r1)
-	std	r21,-8*8(r1)
-	std	r22,-8*9(r1)
-	std	r23,-8*10(r1)
-	std	r24,-8*11(r1)
-	std	r25,-8*12(r1)
-	std	r26,-8*13(r1)
-	std	r27,-8*14(r1)
-	std	r28,-8*15(r1)
-	std	r29,-8*16(r1)
-	std	r30,-8*17(r1)
-	std	r31,-8*18(r1)
-	std	r4,-8*19(r1)
-	std	r5,-8*20(r1)
+	/*
+	 * Use the stack red zone rather than a new frame for saving regs since
+	 * in the case of no GPR loss the wakeup code branches directly back to
+	 * the caller without deallocating the stack frame first.
+	 */
+	std	r2,-8*1(r1)
+	std	r14,-8*2(r1)
+	std	r15,-8*3(r1)
+	std	r16,-8*4(r1)
+	std	r17,-8*5(r1)
+	std	r18,-8*6(r1)
+	std	r19,-8*7(r1)
+	std	r20,-8*8(r1)
+	std	r21,-8*9(r1)
+	std	r22,-8*10(r1)
+	std	r23,-8*11(r1)
+	std	r24,-8*12(r1)
+	std	r25,-8*13(r1)
+	std	r26,-8*14(r1)
+	std	r27,-8*15(r1)
+	std	r28,-8*16(r1)
+	std	r29,-8*17(r1)
+	std	r30,-8*18(r1)
+	std	r31,-8*19(r1)
+	std	r4,-8*20(r1)
+	std	r5,-8*21(r1)
 	cmpwi	r3,PNV_THREAD_NAP
 	bne	1f
 	IDLE_STATE_ENTER_SEQ_NORET(PPC_NAP)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/ima_arch.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/ima_arch.c
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain
+ */
+
+#include <linux/ima.h>
+#include <asm/secure_boot.h>
+
+bool arch_ima_get_secureboot(void)
+{
+	return is_ppc_secureboot_enabled();
+}
+
+/*
+ * The "secure_rules" are enabled only on "secureboot" enabled systems.
+ * These rules verify the file signatures against known good values.
+ * The "appraise_type=imasig|modsig" option allows the known good signature
+ * to be stored as an xattr or as an appended signature.
+ *
+ * To avoid duplicate signature verification as much as possible, the IMA
+ * policy rule for module appraisal is added only if CONFIG_MODULE_SIG
+ * is not enabled.
+ */
+static const char *const secure_rules[] = {
+	"appraise func=KEXEC_KERNEL_CHECK appraise_flag=check_blacklist appraise_type=imasig|modsig",
+#ifndef CONFIG_MODULE_SIG
+	"appraise func=MODULE_CHECK appraise_flag=check_blacklist appraise_type=imasig|modsig",
+#endif
+	NULL
+};
+
+/*
+ * The "trusted_rules" are enabled only on "trustedboot" enabled systems.
+ * These rules add the kexec kernel image and kernel modules file hashes to
+ * the IMA measurement list.
+ */
+static const char *const trusted_rules[] = {
+	"measure func=KEXEC_KERNEL_CHECK",
+	"measure func=MODULE_CHECK",
+	NULL
+};
+
+/*
+ * The "secure_and_trusted_rules" contains rules for both the secure boot and
+ * trusted boot. The "template=ima-modsig" option includes the appended
+ * signature, when available, in the IMA measurement list.
+ */
+static const char *const secure_and_trusted_rules[] = {
+	"measure func=KEXEC_KERNEL_CHECK template=ima-modsig",
+	"measure func=MODULE_CHECK template=ima-modsig",
+	"appraise func=KEXEC_KERNEL_CHECK appraise_flag=check_blacklist appraise_type=imasig|modsig",
+#ifndef CONFIG_MODULE_SIG
+	"appraise func=MODULE_CHECK appraise_flag=check_blacklist appraise_type=imasig|modsig",
+#endif
+	NULL
+};
+
+/*
+ * Returns the relevant IMA arch-specific policies based on the system secure
+ * boot state.
+ */
+const char *const *arch_get_ima_policy(void)
+{
+	if (is_ppc_secureboot_enabled()) {
+		if (IS_ENABLED(CONFIG_MODULE_SIG))
+			set_module_sig_enforced();
+
+		if (is_ppc_trustedboot_enabled())
+			return secure_and_trusted_rules;
+		else
+			return secure_rules;
+	} else if (is_ppc_trustedboot_enabled()) {
+		return trusted_rules;
+	}
+
+	return NULL;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/iommu.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/iommu.c
@@ -133,17 +133,28 @@
 	return 0;
 }
 
-static struct notifier_block fail_iommu_bus_notifier = {
+/*
+ * PCI and VIO buses need separate notifier_block structs, since they're linked
+ * list nodes.  Sharing a notifier_block would mean that any notifiers later
+ * registered for PCI buses would also get called by VIO buses and vice versa.
+ */
+static struct notifier_block fail_iommu_pci_bus_notifier = {
 	.notifier_call = fail_iommu_bus_notify
 };
 
+#ifdef CONFIG_IBMVIO
+static struct notifier_block fail_iommu_vio_bus_notifier = {
+	.notifier_call = fail_iommu_bus_notify
+};
+#endif
+
 static int __init fail_iommu_setup(void)
 {
 #ifdef CONFIG_PCI
-	bus_register_notifier(&pci_bus_type, &fail_iommu_bus_notifier);
+	bus_register_notifier(&pci_bus_type, &fail_iommu_pci_bus_notifier);
 #endif
 #ifdef CONFIG_IBMVIO
-	bus_register_notifier(&vio_bus_type, &fail_iommu_bus_notifier);
+	bus_register_notifier(&vio_bus_type, &fail_iommu_vio_bus_notifier);
 #endif
 
 	return 0;
@@ -1057,7 +1068,7 @@
 
 	spin_lock_irqsave(&tbl->large_pool.lock, flags);
 	for (i = 0; i < tbl->nr_pools; i++)
-		spin_lock(&tbl->pools[i].lock);
+		spin_lock_nest_lock(&tbl->pools[i].lock, &tbl->large_pool.lock);
 
 	iommu_table_release_pages(tbl);
 
@@ -1085,7 +1096,7 @@
 
 	spin_lock_irqsave(&tbl->large_pool.lock, flags);
 	for (i = 0; i < tbl->nr_pools; i++)
-		spin_lock(&tbl->pools[i].lock);
+		spin_lock_nest_lock(&tbl->pools[i].lock, &tbl->large_pool.lock);
 
 	memset(tbl->it_map, 0, sz);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/irq.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/irq.c
@@ -619,8 +619,6 @@
 
 	trace_irq_entry(regs);
 
-	check_stack_overflow();
-
 	/*
 	 * Query the platform PIC for the interrupt & ack it.
 	 *
@@ -652,6 +650,8 @@
 	irqsp = hardirq_ctx[raw_smp_processor_id()];
 	sirqsp = softirq_ctx[raw_smp_processor_id()];
 
+	check_stack_overflow();
+
 	/* Already there ? */
 	if (unlikely(cursp == irqsp || cursp == sirqsp)) {
 		__do_irq(regs);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/kprobes.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/kprobes.c
@@ -264,6 +264,10 @@
 	if (user_mode(regs))
 		return 0;
 
+	if (!IS_ENABLED(CONFIG_BOOKE) &&
+	    (!(regs->msr & MSR_IR) || !(regs->msr & MSR_DR)))
+		return 0;
+
 	/*
 	 * We don't want to be preempted for the entire
 	 * duration of kprobe processing
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/kvm.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/kvm.c
@@ -669,7 +669,7 @@
 	on_each_cpu(kvm_map_magic_page, &features, 1);
 
 	/* Quick self-test to see if the mapping works */
-	if (!fault_in_pages_readable((const char *)KVM_MAGIC_PAGE, sizeof(u32))) {
+	if (fault_in_pages_readable((const char *)KVM_MAGIC_PAGE, sizeof(u32))) {
 		kvm_patching_worked = false;
 		return;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/l2cr_6xx.S
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/l2cr_6xx.S
@@ -96,7 +96,7 @@
 
 	/* Stop DST streams */
 BEGIN_FTR_SECTION
-	DSSALL
+	PPC_DSSALL
 	sync
 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 
@@ -293,7 +293,7 @@
 	isync
 
 	/* Stop DST streams */
-	DSSALL
+	PPC_DSSALL
 	sync
 
 	/* Get the current enable bit of the L3CR into r4 */
@@ -402,7 +402,7 @@
 _GLOBAL(__flush_disable_L1)
 	/* Stop pending alitvec streams and memory accesses */
 BEGIN_FTR_SECTION
-	DSSALL
+	PPC_DSSALL
 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
  	sync
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/machine_kexec.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/machine_kexec.c
@@ -114,11 +114,12 @@
 
 void __init reserve_crashkernel(void)
 {
-	unsigned long long crash_size, crash_base;
+	unsigned long long crash_size, crash_base, total_mem_sz;
 	int ret;
 
+	total_mem_sz = memory_limit ? memory_limit : memblock_phys_mem_size();
 	/* use common parsing */
-	ret = parse_crashkernel(boot_command_line, memblock_phys_mem_size(),
+	ret = parse_crashkernel(boot_command_line, total_mem_sz,
 			&crash_size, &crash_base);
 	if (ret == 0 && crash_size > 0) {
 		crashk_res.start = crash_base;
@@ -145,11 +146,18 @@
 	if (!crashk_res.start) {
 #ifdef CONFIG_PPC64
 		/*
-		 * On 64bit we split the RMO in half but cap it at half of
-		 * a small SLB (128MB) since the crash kernel needs to place
-		 * itself and some stacks to be in the first segment.
+		 * On the LPAR platform place the crash kernel to mid of
+		 * RMA size (512MB or more) to ensure the crash kernel
+		 * gets enough space to place itself and some stack to be
+		 * in the first segment. At the same time normal kernel
+		 * also get enough space to allocate memory for essential
+		 * system resource in the first segment. Keep the crash
+		 * kernel starts at 128MB offset on other platforms.
 		 */
-		crashk_res.start = min(0x8000000ULL, (ppc64_rma_size / 2));
+		if (firmware_has_feature(FW_FEATURE_LPAR))
+			crashk_res.start = ppc64_rma_size / 2;
+		else
+			crashk_res.start = min(0x8000000ULL, (ppc64_rma_size / 2));
 #else
 		crashk_res.start = KDUMP_KERNELBASE;
 #endif
@@ -177,6 +185,7 @@
 	/* Crash kernel trumps memory limit */
 	if (memory_limit && memory_limit <= crashk_res.end) {
 		memory_limit = crashk_res.end + 1;
+		total_mem_sz = memory_limit;
 		printk("Adjusted memory limit for crashkernel, now 0x%llx\n",
 		       memory_limit);
 	}
@@ -185,7 +194,7 @@
 			"for crashkernel (System RAM: %ldMB)\n",
 			(unsigned long)(crash_size >> 20),
 			(unsigned long)(crashk_res.start >> 20),
-			(unsigned long)(memblock_phys_mem_size() >> 20));
+			(unsigned long)(total_mem_sz >> 20));
 
 	if (!memblock_is_region_memory(crashk_res.start, crash_size) ||
 	    memblock_reserve(crashk_res.start, crash_size)) {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/misc_32.S
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/misc_32.S
@@ -317,126 +317,6 @@
 #endif /* CONFIG_PPC_8xx */
 
 /*
- * Write any modified data cache blocks out to memory
- * and invalidate the corresponding instruction cache blocks.
- * This is a no-op on the 601.
- *
- * flush_icache_range(unsigned long start, unsigned long stop)
- */
-_GLOBAL(flush_icache_range)
-#if defined(CONFIG_PPC_BOOK3S_601) || defined(CONFIG_E200)
-	PURGE_PREFETCHED_INS
-	blr				/* for 601 and e200, do nothing */
-#else
-	rlwinm	r3,r3,0,0,31 - L1_CACHE_SHIFT
-	subf	r4,r3,r4
-	addi	r4,r4,L1_CACHE_BYTES - 1
-	srwi.	r4,r4,L1_CACHE_SHIFT
-	beqlr
-	mtctr	r4
-	mr	r6,r3
-1:	dcbst	0,r3
-	addi	r3,r3,L1_CACHE_BYTES
-	bdnz	1b
-	sync				/* wait for dcbst's to get to ram */
-#ifndef CONFIG_44x
-	mtctr	r4
-2:	icbi	0,r6
-	addi	r6,r6,L1_CACHE_BYTES
-	bdnz	2b
-#else
-	/* Flash invalidate on 44x because we are passed kmapped addresses and
-	   this doesn't work for userspace pages due to the virtually tagged
-	   icache.  Sigh. */
-	iccci	0, r0
-#endif
-	sync				/* additional sync needed on g4 */
-	isync
-	blr
-#endif
-_ASM_NOKPROBE_SYMBOL(flush_icache_range)
-EXPORT_SYMBOL(flush_icache_range)
-
-/*
- * Flush a particular page from the data cache to RAM.
- * Note: this is necessary because the instruction cache does *not*
- * snoop from the data cache.
- * This is a no-op on the 601 and e200 which have a unified cache.
- *
- *	void __flush_dcache_icache(void *page)
- */
-_GLOBAL(__flush_dcache_icache)
-#if defined(CONFIG_PPC_BOOK3S_601) || defined(CONFIG_E200)
-	PURGE_PREFETCHED_INS
-	blr
-#else
-	rlwinm	r3,r3,0,0,31-PAGE_SHIFT		/* Get page base address */
-	li	r4,PAGE_SIZE/L1_CACHE_BYTES	/* Number of lines in a page */
-	mtctr	r4
-	mr	r6,r3
-0:	dcbst	0,r3				/* Write line to ram */
-	addi	r3,r3,L1_CACHE_BYTES
-	bdnz	0b
-	sync
-#ifdef CONFIG_44x
-	/* We don't flush the icache on 44x. Those have a virtual icache
-	 * and we don't have access to the virtual address here (it's
-	 * not the page vaddr but where it's mapped in user space). The
-	 * flushing of the icache on these is handled elsewhere, when
-	 * a change in the address space occurs, before returning to
-	 * user space
-	 */
-BEGIN_MMU_FTR_SECTION
-	blr
-END_MMU_FTR_SECTION_IFSET(MMU_FTR_TYPE_44x)
-#endif /* CONFIG_44x */
-	mtctr	r4
-1:	icbi	0,r6
-	addi	r6,r6,L1_CACHE_BYTES
-	bdnz	1b
-	sync
-	isync
-	blr
-#endif
-
-#ifndef CONFIG_BOOKE
-/*
- * Flush a particular page from the data cache to RAM, identified
- * by its physical address.  We turn off the MMU so we can just use
- * the physical address (this may be a highmem page without a kernel
- * mapping).
- *
- *	void __flush_dcache_icache_phys(unsigned long physaddr)
- */
-_GLOBAL(__flush_dcache_icache_phys)
-#if defined(CONFIG_PPC_BOOK3S_601) || defined(CONFIG_E200)
-	PURGE_PREFETCHED_INS
-	blr					/* for 601 and e200, do nothing */
-#else
-	mfmsr	r10
-	rlwinm	r0,r10,0,28,26			/* clear DR */
-	mtmsr	r0
-	isync
-	rlwinm	r3,r3,0,0,31-PAGE_SHIFT		/* Get page base address */
-	li	r4,PAGE_SIZE/L1_CACHE_BYTES	/* Number of lines in a page */
-	mtctr	r4
-	mr	r6,r3
-0:	dcbst	0,r3				/* Write line to ram */
-	addi	r3,r3,L1_CACHE_BYTES
-	bdnz	0b
-	sync
-	mtctr	r4
-1:	icbi	0,r6
-	addi	r6,r6,L1_CACHE_BYTES
-	bdnz	1b
-	sync
-	mtmsr	r10				/* restore DR */
-	isync
-	blr
-#endif
-#endif /* CONFIG_BOOKE */
-
-/*
  * Copy a whole page.  We use the dcbz instruction on the destination
  * to reduce memory traffic (it eliminates the unnecessary reads of
  * the destination into cache).  This requires that the destination
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/misc_64.S
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/misc_64.S
@@ -49,108 +49,6 @@
 	mtlr	r0
 	blr
 
-	.section	".toc","aw"
-PPC64_CACHES:
-	.tc		ppc64_caches[TC],ppc64_caches
-	.section	".text"
-
-/*
- * Write any modified data cache blocks out to memory
- * and invalidate the corresponding instruction cache blocks.
- *
- * flush_icache_range(unsigned long start, unsigned long stop)
- *
- *   flush all bytes from start through stop-1 inclusive
- */
-
-_GLOBAL_TOC(flush_icache_range)
-BEGIN_FTR_SECTION
-	PURGE_PREFETCHED_INS
-	blr
-END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
-/*
- * Flush the data cache to memory 
- * 
- * Different systems have different cache line sizes
- * and in some cases i-cache and d-cache line sizes differ from
- * each other.
- */
- 	ld	r10,PPC64_CACHES@toc(r2)
-	lwz	r7,DCACHEL1BLOCKSIZE(r10)/* Get cache block size */
-	addi	r5,r7,-1
-	andc	r6,r3,r5		/* round low to line bdy */
-	subf	r8,r6,r4		/* compute length */
-	add	r8,r8,r5		/* ensure we get enough */
-	lwz	r9,DCACHEL1LOGBLOCKSIZE(r10)	/* Get log-2 of cache block size */
-	srw.	r8,r8,r9		/* compute line count */
-	beqlr				/* nothing to do? */
-	mtctr	r8
-1:	dcbst	0,r6
-	add	r6,r6,r7
-	bdnz	1b
-	sync
-
-/* Now invalidate the instruction cache */
-	
-	lwz	r7,ICACHEL1BLOCKSIZE(r10)	/* Get Icache block size */
-	addi	r5,r7,-1
-	andc	r6,r3,r5		/* round low to line bdy */
-	subf	r8,r6,r4		/* compute length */
-	add	r8,r8,r5
-	lwz	r9,ICACHEL1LOGBLOCKSIZE(r10)	/* Get log-2 of Icache block size */
-	srw.	r8,r8,r9		/* compute line count */
-	beqlr				/* nothing to do? */
-	mtctr	r8
-2:	icbi	0,r6
-	add	r6,r6,r7
-	bdnz	2b
-	isync
-	blr
-_ASM_NOKPROBE_SYMBOL(flush_icache_range)
-EXPORT_SYMBOL(flush_icache_range)
-
-/*
- * Flush a particular page from the data cache to RAM.
- * Note: this is necessary because the instruction cache does *not*
- * snoop from the data cache.
- *
- *	void __flush_dcache_icache(void *page)
- */
-_GLOBAL(__flush_dcache_icache)
-/*
- * Flush the data cache to memory 
- * 
- * Different systems have different cache line sizes
- */
-
-BEGIN_FTR_SECTION
-	PURGE_PREFETCHED_INS
-	blr
-END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
-
-/* Flush the dcache */
- 	ld	r7,PPC64_CACHES@toc(r2)
-	clrrdi	r3,r3,PAGE_SHIFT           	    /* Page align */
-	lwz	r4,DCACHEL1BLOCKSPERPAGE(r7)	/* Get # dcache blocks per page */
-	lwz	r5,DCACHEL1BLOCKSIZE(r7)	/* Get dcache block size */
-	mr	r6,r3
-	mtctr	r4
-0:	dcbst	0,r6
-	add	r6,r6,r5
-	bdnz	0b
-	sync
-
-/* Now invalidate the icache */	
-
-	lwz	r4,ICACHEL1BLOCKSPERPAGE(r7)	/* Get # icache blocks per page */
-	lwz	r5,ICACHEL1BLOCKSIZE(r7)	/* Get icache block size */
-	mtctr	r4
-1:	icbi	0,r3
-	add	r3,r3,r5
-	bdnz	1b
-	isync
-	blr
-
 _GLOBAL(__bswapdi2)
 EXPORT_SYMBOL(__bswapdi2)
 	srdi	r8,r3,32
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/paca.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/paca.c
@@ -86,7 +86,7 @@
 	 * This is very early in boot, so no harm done if the kernel crashes at
 	 * this point.
 	 */
-	BUG_ON(shared_lppaca_size >= shared_lppaca_total_size);
+	BUG_ON(shared_lppaca_size > shared_lppaca_total_size);
 
 	return ptr;
 }
@@ -214,11 +214,15 @@
 	/* On Book3E, initialize the TLB miss exception frames */
 	mtspr(SPRN_SPRG_TLB_EXFRAME, local_paca->extlb);
 #else
-	/* In HV mode, we setup both HPACA and PACA to avoid problems
+	/*
+	 * In HV mode, we setup both HPACA and PACA to avoid problems
 	 * if we do a GET_PACA() before the feature fixups have been
-	 * applied
+	 * applied.
+	 *
+	 * Normally you should test against CPU_FTR_HVMODE, but CPU features
+	 * are not yet set up when we first reach here.
 	 */
-	if (early_cpu_has_feature(CPU_FTR_HVMODE))
+	if (mfmsr() & MSR_HV)
 		mtspr(SPRN_SPRG_HPACA, local_paca);
 #endif
 	mtspr(SPRN_SPRG_PACA, local_paca);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/pci-common.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/pci-common.c
@@ -66,23 +66,35 @@
 	pci_dma_ops = dma_ops;
 }
 
-/*
- * This function should run under locking protection, specifically
- * hose_spinlock.
- */
 static int get_phb_number(struct device_node *dn)
 {
 	int ret, phb_id = -1;
-	u32 prop_32;
 	u64 prop;
 
 	/*
 	 * Try fixed PHB numbering first, by checking archs and reading
-	 * the respective device-tree properties. Firstly, try powernv by
-	 * reading "ibm,opal-phbid", only present in OPAL environment.
+	 * the respective device-tree properties. Firstly, try reading
+	 * standard "linux,pci-domain", then try reading "ibm,opal-phbid"
+	 * (only present in powernv OPAL environment), then try device-tree
+	 * alias and as the last try to use lower bits of "reg" property.
 	 */
-	ret = of_property_read_u64(dn, "ibm,opal-phbid", &prop);
+	ret = of_get_pci_domain_nr(dn);
+	if (ret >= 0) {
+		prop = ret;
+		ret = 0;
+	}
+	if (ret)
+		ret = of_property_read_u64(dn, "ibm,opal-phbid", &prop);
+
+	if (ret) {
+		ret = of_alias_get_id(dn, "pci");
+		if (ret >= 0) {
+			prop = ret;
+			ret = 0;
+		}
+	}
 	if (ret) {
+		u32 prop_32;
 		ret = of_property_read_u32_index(dn, "reg", 1, &prop_32);
 		prop = prop_32;
 	}
@@ -90,18 +102,20 @@
 	if (!ret)
 		phb_id = (int)(prop & (MAX_PHBS - 1));
 
+	spin_lock(&hose_spinlock);
+
 	/* We need to be sure to not use the same PHB number twice. */
 	if ((phb_id >= 0) && !test_and_set_bit(phb_id, phb_bitmap))
-		return phb_id;
+		goto out_unlock;
 
-	/*
-	 * If not pseries nor powernv, or if fixed PHB numbering tried to add
-	 * the same PHB number twice, then fallback to dynamic PHB numbering.
-	 */
+	/* If everything fails then fallback to dynamic PHB numbering. */
 	phb_id = find_first_zero_bit(phb_bitmap, MAX_PHBS);
 	BUG_ON(phb_id >= MAX_PHBS);
 	set_bit(phb_id, phb_bitmap);
 
+out_unlock:
+	spin_unlock(&hose_spinlock);
+
 	return phb_id;
 }
 
@@ -112,10 +126,13 @@
 	phb = zalloc_maybe_bootmem(sizeof(struct pci_controller), GFP_KERNEL);
 	if (phb == NULL)
 		return NULL;
-	spin_lock(&hose_spinlock);
+
 	phb->global_number = get_phb_number(dev);
+
+	spin_lock(&hose_spinlock);
 	list_add_tail(&phb->list_node, &hose_list);
 	spin_unlock(&hose_spinlock);
+
 	phb->dn = dev;
 	phb->is_dynamic = slab_is_available();
 #ifdef CONFIG_PPC64
@@ -347,6 +364,7 @@
 	}
 	return NULL;
 }
+EXPORT_SYMBOL(pci_find_hose_for_OF_device);
 
 struct pci_controller *pci_find_controller_for_domain(int domain_nr)
 {
@@ -1577,6 +1595,7 @@
 {
 	return pci_bus_find_capability(fake_pci_bus(hose, bus), devfn, cap);
 }
+EXPORT_SYMBOL_GPL(early_find_capability);
 
 struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus)
 {
@@ -1669,3 +1688,13 @@
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MOTOROLA, PCI_ANY_ID, fixup_hide_host_resource_fsl);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_FREESCALE, PCI_ANY_ID, fixup_hide_host_resource_fsl);
+
+
+static int __init discover_phbs(void)
+{
+	if (ppc_md.discover_phbs)
+		ppc_md.discover_phbs();
+
+	return 0;
+}
+core_initcall(discover_phbs);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/pci_dn.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/pci_dn.c
@@ -244,9 +244,22 @@
 				continue;
 
 #ifdef CONFIG_EEH
-			/* Release EEH device for the VF */
+			/*
+			 * Release EEH state for this VF. The PCI core
+			 * has already torn down the pci_dev for this VF, but
+			 * we're responsible to removing the eeh_dev since it
+			 * has the same lifetime as the pci_dn that spawned it.
+			 */
 			edev = pdn_to_eeh_dev(pdn);
 			if (edev) {
+				/*
+				 * We allocate pci_dn's for the totalvfs count,
+				 * but only only the vfs that were activated
+				 * have a configured PE.
+				 */
+				if (edev->pe)
+					eeh_rmv_from_parent_pe(edev);
+
 				pdn->edev = NULL;
 				kfree(edev);
 			}
@@ -312,6 +325,7 @@
 	INIT_LIST_HEAD(&pdn->list);
 	parent = of_get_parent(dn);
 	pdn->parent = parent ? PCI_DN(parent) : NULL;
+	of_node_put(parent);
 	if (pdn->parent)
 		list_add_tail(&pdn->list, &pdn->parent->child_list);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/process.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/process.c
@@ -1218,29 +1218,31 @@
 static void show_instructions(struct pt_regs *regs)
 {
 	int i;
+	unsigned long nip = regs->nip;
 	unsigned long pc = regs->nip - (NR_INSN_TO_PRINT * 3 / 4 * sizeof(int));
 
 	printk("Instruction dump:");
 
+	/*
+	 * If we were executing with the MMU off for instructions, adjust pc
+	 * rather than printing XXXXXXXX.
+	 */
+	if (!IS_ENABLED(CONFIG_BOOKE) && !(regs->msr & MSR_IR)) {
+		pc = (unsigned long)phys_to_virt(pc);
+		nip = (unsigned long)phys_to_virt(regs->nip);
+	}
+
 	for (i = 0; i < NR_INSN_TO_PRINT; i++) {
 		int instr;
 
 		if (!(i % 8))
 			pr_cont("\n");
 
-#if !defined(CONFIG_BOOKE)
-		/* If executing with the IMMU off, adjust pc rather
-		 * than print XXXXXXXX.
-		 */
-		if (!(regs->msr & MSR_IR))
-			pc = (unsigned long)phys_to_virt(pc);
-#endif
-
 		if (!__kernel_text_address(pc) ||
 		    probe_kernel_address((const void *)pc, instr)) {
 			pr_cont("XXXXXXXX ");
 		} else {
-			if (regs->nip == pc)
+			if (nip == pc)
 				pr_cont("<%08x> ", instr);
 			else
 				pr_cont("%08x ", instr);
@@ -1717,7 +1719,7 @@
 		tm_reclaim_current(0);
 #endif
 
-	memset(regs->gpr, 0, sizeof(regs->gpr));
+	memset(&regs->gpr[1], 0, sizeof(regs->gpr) - sizeof(regs->gpr[0]));
 	regs->ctr = 0;
 	regs->link = 0;
 	regs->xer = 0;
@@ -1999,12 +2001,12 @@
 		return 0;
 
 	do {
-		sp = *(unsigned long *)sp;
+		sp = READ_ONCE_NOCHECK(*(unsigned long *)sp);
 		if (!validate_sp(sp, p, STACK_FRAME_OVERHEAD) ||
 		    p->state == TASK_RUNNING)
 			return 0;
 		if (count > 0) {
-			ip = ((unsigned long *)sp)[STACK_FRAME_LR_SAVE];
+			ip = READ_ONCE_NOCHECK(((unsigned long *)sp)[STACK_FRAME_LR_SAVE]);
 			if (!in_sched_functions(ip))
 				return ip;
 		}
@@ -2079,7 +2081,7 @@
 		 * See if this is an exception frame.
 		 * We look for the "regshere" marker in the current frame.
 		 */
-		if (validate_sp(sp, tsk, STACK_INT_FRAME_SIZE)
+		if (validate_sp(sp, tsk, STACK_FRAME_WITH_PT_REGS)
 		    && stack[STACK_FRAME_MARKER] == STACK_FRAME_REGS_MARKER) {
 			struct pt_regs *regs = (struct pt_regs *)
 				(sp + STACK_FRAME_OVERHEAD);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/prom.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/prom.c
@@ -266,7 +266,7 @@
 };
 
 #if defined(CONFIG_44x) && defined(CONFIG_PPC_FPU)
-static inline void identical_pvr_fixup(unsigned long node)
+static __init void identical_pvr_fixup(unsigned long node)
 {
 	unsigned int pvr;
 	const char *model = of_get_flat_dt_prop(node, "model", NULL);
@@ -685,6 +685,23 @@
 static void tm_init(void) { }
 #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
 
+#ifdef CONFIG_PPC64
+static void __init save_fscr_to_task(void)
+{
+	/*
+	 * Ensure the init_task (pid 0, aka swapper) uses the value of FSCR we
+	 * have configured via the device tree features or via __init_FSCR().
+	 * That value will then be propagated to pid 1 (init) and all future
+	 * processes.
+	 */
+	if (early_cpu_has_feature(CPU_FTR_ARCH_207S))
+		init_task.thread.fscr = mfspr(SPRN_FSCR);
+}
+#else
+static inline void save_fscr_to_task(void) {};
+#endif
+
+
 void __init early_init_devtree(void *params)
 {
 	phys_addr_t limit;
@@ -723,6 +740,13 @@
 	of_scan_flat_dt(early_init_dt_scan_root, NULL);
 	of_scan_flat_dt(early_init_dt_scan_memory_ppc, NULL);
 
+	/*
+	 * As generic code authors expect to be able to use static keys
+	 * in early_param() handlers, we initialize the static keys just
+	 * before parsing early params (it's fine to call jump_label_init()
+	 * more than once).
+	 */
+	jump_label_init();
 	parse_early_param();
 
 	/* make sure we've parsed cmdline for mem= before this */
@@ -773,6 +797,8 @@
 		BUG();
 	}
 
+	save_fscr_to_task();
+
 #if defined(CONFIG_SMP) && defined(CONFIG_PPC64)
 	/* We'll later wait for secondaries to check in; there are
 	 * NCPUS-1 non-boot CPUs  :-)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/prom_init.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/prom_init.c
@@ -1053,7 +1053,7 @@
 		.reserved2 = 0,
 		.reserved3 = 0,
 		.subprocessors = 1,
-		.byte22 = OV5_FEAT(OV5_DRMEM_V2),
+		.byte22 = OV5_FEAT(OV5_DRMEM_V2) | OV5_FEAT(OV5_DRC_INFO),
 		.intarch = 0,
 		.mmu = 0,
 		.hash_ext = 0,
@@ -1305,14 +1305,10 @@
 		if (prop_len > sizeof(vec))
 			prom_printf("WARNING: ibm,arch-vec-5-platform-support longer than expected (len: %d)\n",
 				    prop_len);
-		prom_getprop(prom.chosen, "ibm,arch-vec-5-platform-support",
-			     &vec, sizeof(vec));
-		for (i = 0; i < sizeof(vec); i += 2) {
-			prom_debug("%d: index = 0x%x val = 0x%x\n", i / 2
-								  , vec[i]
-								  , vec[i + 1]);
-			prom_parse_platform_support(vec[i], vec[i + 1],
-						    &supported);
+		prom_getprop(prom.chosen, "ibm,arch-vec-5-platform-support", &vec, sizeof(vec));
+		for (i = 0; i < prop_len; i += 2) {
+			prom_debug("%d: index = 0x%x val = 0x%x\n", i / 2, vec[i], vec[i + 1]);
+			prom_parse_platform_support(vec[i], vec[i + 1], &supported);
 		}
 	}
 
@@ -1761,6 +1757,9 @@
 	if (token == 0)
 		prom_panic("Could not get token for ibm,os-term\n");
 	os_term_args.token = cpu_to_be32(token);
+	os_term_args.nargs = cpu_to_be32(1);
+	os_term_args.nret = cpu_to_be32(1);
+	os_term_args.args[0] = cpu_to_be32(__pa(str));
 	prom_rtas_hcall((uint64_t)&os_term_args);
 }
 #endif /* CONFIG_PPC_SVM */
@@ -2857,7 +2856,7 @@
 #endif
 
 #if defined(CONFIG_PPC64) && defined(CONFIG_PPC_PMAC)
-static void __init fixup_device_tree_pmac(void)
+static void __init fixup_device_tree_pmac64(void)
 {
 	phandle u3, i2c, mpic;
 	u32 u3_rev;
@@ -2897,7 +2896,31 @@
 		     &parent, sizeof(parent));
 }
 #else
-#define fixup_device_tree_pmac()
+#define fixup_device_tree_pmac64()
+#endif
+
+#ifdef CONFIG_PPC_PMAC
+static void __init fixup_device_tree_pmac(void)
+{
+	__be32 val = 1;
+	char type[8];
+	phandle node;
+
+	// Some pmacs are missing #size-cells on escc nodes
+	for (node = 0; prom_next_node(&node); ) {
+		type[0] = '\0';
+		prom_getprop(node, "device_type", type, sizeof(type));
+		if (prom_strcmp(type, "escc"))
+			continue;
+
+		if (prom_getproplen(node, "#size-cells") != PROM_ERROR)
+			continue;
+
+		prom_setprop(node, NULL, "#size-cells", &val, sizeof(val));
+	}
+}
+#else
+static inline void fixup_device_tree_pmac(void) { }
 #endif
 
 #ifdef CONFIG_PPC_EFIKA
@@ -2920,7 +2943,7 @@
 
 	/* Check if the phy-handle property exists - bail if it does */
 	rv = prom_getprop(node, "phy-handle", prop, sizeof(prop));
-	if (!rv)
+	if (rv <= 0)
 		return;
 
 	/*
@@ -3122,6 +3145,7 @@
 	fixup_device_tree_maple_memory_controller();
 	fixup_device_tree_chrp();
 	fixup_device_tree_pmac();
+	fixup_device_tree_pmac64();
 	fixup_device_tree_efika();
 	fixup_device_tree_pasemi();
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/prom_init_check.sh
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/prom_init_check.sh
@@ -13,7 +13,7 @@
 # If you really need to reference something from prom_init.o add
 # it to the list below:
 
-grep "^CONFIG_KASAN=y$" .config >/dev/null
+grep "^CONFIG_KASAN=y$" ${KCONFIG_CONFIG} >/dev/null
 if [ $? -eq 0 ]
 then
 	MEM_FUNCS="__memcpy __memset"
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/ptrace.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/ptrace.c
@@ -3014,8 +3014,13 @@
 
 			flush_fp_to_thread(child);
 			if (fpidx < (PT_FPSCR - PT_FPR0))
-				memcpy(&tmp, &child->thread.TS_FPR(fpidx),
-				       sizeof(long));
+				if (IS_ENABLED(CONFIG_PPC32)) {
+					// On 32-bit the index we are passed refers to 32-bit words
+					tmp = ((u32 *)child->thread.fp_state.fpr)[fpidx];
+				} else {
+					memcpy(&tmp, &child->thread.TS_FPR(fpidx),
+					       sizeof(long));
+				}
 			else
 				tmp = child->thread.fp_state.fpscr;
 		}
@@ -3047,8 +3052,13 @@
 
 			flush_fp_to_thread(child);
 			if (fpidx < (PT_FPSCR - PT_FPR0))
-				memcpy(&child->thread.TS_FPR(fpidx), &data,
-				       sizeof(long));
+				if (IS_ENABLED(CONFIG_PPC32)) {
+					// On 32-bit the index we are passed refers to 32-bit words
+					((u32 *)child->thread.fp_state.fpr)[fpidx] = data;
+				} else {
+					memcpy(&child->thread.TS_FPR(fpidx), &data,
+					       sizeof(long));
+				}
 			else
 				child->thread.fp_state.fpscr = data;
 			ret = 0;
@@ -3398,4 +3408,7 @@
 		     offsetof(struct user_pt_regs, result));
 
 	BUILD_BUG_ON(sizeof(struct user_pt_regs) > sizeof(struct pt_regs));
+
+	// ptrace_get/put_fpr() rely on PPC32 and VSX being incompatible
+	BUILD_BUG_ON(IS_ENABLED(CONFIG_PPC32) && IS_ENABLED(CONFIG_VSX));
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/rtas.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/rtas.c
@@ -51,10 +51,10 @@
 EXPORT_SYMBOL(rtas);
 
 DEFINE_SPINLOCK(rtas_data_buf_lock);
-EXPORT_SYMBOL(rtas_data_buf_lock);
+EXPORT_SYMBOL_GPL(rtas_data_buf_lock);
 
-char rtas_data_buf[RTAS_DATA_BUF_SIZE] __cacheline_aligned;
-EXPORT_SYMBOL(rtas_data_buf);
+char rtas_data_buf[RTAS_DATA_BUF_SIZE] __aligned(SZ_4K);
+EXPORT_SYMBOL_GPL(rtas_data_buf);
 
 unsigned long rtas_rmo_buf;
 
@@ -63,7 +63,7 @@
  * This is done like this so rtas_flash can be a module.
  */
 void (*rtas_flash_term_hook)(int);
-EXPORT_SYMBOL(rtas_flash_term_hook);
+EXPORT_SYMBOL_GPL(rtas_flash_term_hook);
 
 /* RTAS use home made raw locking instead of spin_lock_irqsave
  * because those can be called from within really nasty contexts
@@ -311,7 +311,7 @@
  
 	spin_unlock(&progress_lock);
 }
-EXPORT_SYMBOL(rtas_progress);		/* needed by rtas_flash module */
+EXPORT_SYMBOL_GPL(rtas_progress);		/* needed by rtas_flash module */
 
 int rtas_token(const char *service)
 {
@@ -321,7 +321,7 @@
 	tokp = of_get_property(rtas.dev, service, NULL);
 	return tokp ? be32_to_cpu(*tokp) : RTAS_UNKNOWN_SERVICE;
 }
-EXPORT_SYMBOL(rtas_token);
+EXPORT_SYMBOL_GPL(rtas_token);
 
 int rtas_service_present(const char *service)
 {
@@ -398,7 +398,7 @@
 				buf = kmalloc(RTAS_ERROR_LOG_MAX, GFP_ATOMIC);
 		}
 		if (buf)
-			memcpy(buf, rtas_err_buf, RTAS_ERROR_LOG_MAX);
+			memmove(buf, rtas_err_buf, RTAS_ERROR_LOG_MAX);
 	}
 
 	return buf;
@@ -481,7 +481,7 @@
 	}
 	return ret;
 }
-EXPORT_SYMBOL(rtas_call);
+EXPORT_SYMBOL_GPL(rtas_call);
 
 /* For RTAS_BUSY (-2), delay for 1 millisecond.  For an extended busy status
  * code of 990n, perform the hinted delay of 10^n (last digit) milliseconds.
@@ -516,7 +516,7 @@
 
 	return ms;
 }
-EXPORT_SYMBOL(rtas_busy_delay);
+EXPORT_SYMBOL_GPL(rtas_busy_delay);
 
 static int rtas_error_rc(int rtas_rc)
 {
@@ -562,7 +562,7 @@
 		return rtas_error_rc(rc);
 	return rc;
 }
-EXPORT_SYMBOL(rtas_get_power_level);
+EXPORT_SYMBOL_GPL(rtas_get_power_level);
 
 int rtas_set_power_level(int powerdomain, int level, int *setlevel)
 {
@@ -580,7 +580,7 @@
 		return rtas_error_rc(rc);
 	return rc;
 }
-EXPORT_SYMBOL(rtas_set_power_level);
+EXPORT_SYMBOL_GPL(rtas_set_power_level);
 
 int rtas_get_sensor(int sensor, int index, int *state)
 {
@@ -598,7 +598,7 @@
 		return rtas_error_rc(rc);
 	return rc;
 }
-EXPORT_SYMBOL(rtas_get_sensor);
+EXPORT_SYMBOL_GPL(rtas_get_sensor);
 
 int rtas_get_sensor_fast(int sensor, int index, int *state)
 {
@@ -659,7 +659,7 @@
 		return rtas_error_rc(rc);
 	return rc;
 }
-EXPORT_SYMBOL(rtas_set_indicator);
+EXPORT_SYMBOL_GPL(rtas_set_indicator);
 
 /*
  * Ignoring RTAS extended delay
@@ -714,6 +714,7 @@
 
 /* Must be in the RMO region, so we place it here */
 static char rtas_os_term_buf[2048];
+static s32 ibm_os_term_token = RTAS_UNKNOWN_SERVICE;
 
 void rtas_os_term(char *str)
 {
@@ -725,16 +726,20 @@
 	 * this property may terminate the partition which we want to avoid
 	 * since it interferes with panic_timeout.
 	 */
-	if (RTAS_UNKNOWN_SERVICE == rtas_token("ibm,os-term") ||
-	    RTAS_UNKNOWN_SERVICE == rtas_token("ibm,extended-os-term"))
+	if (ibm_os_term_token == RTAS_UNKNOWN_SERVICE)
 		return;
 
 	snprintf(rtas_os_term_buf, 2048, "OS panic: %s", str);
 
+	/*
+	 * Keep calling as long as RTAS returns a "try again" status,
+	 * but don't use rtas_busy_delay(), which potentially
+	 * schedules.
+	 */
 	do {
-		status = rtas_call(rtas_token("ibm,os-term"), 1, 1, NULL,
+		status = rtas_call(ibm_os_term_token, 1, 1, NULL,
 				   __pa(rtas_os_term_buf));
-	} while (rtas_busy_delay(status));
+	} while (rtas_busy_delay_time(status));
 
 	if (status != 0)
 		printk(KERN_EMERG "ibm,os-term call failed %d\n", status);
@@ -842,96 +847,6 @@
 	__rtas_suspend_cpu((struct rtas_suspend_me_data *)info, 1);
 }
 
-enum rtas_cpu_state {
-	DOWN,
-	UP,
-};
-
-#ifndef CONFIG_SMP
-static int rtas_cpu_state_change_mask(enum rtas_cpu_state state,
-				cpumask_var_t cpus)
-{
-	if (!cpumask_empty(cpus)) {
-		cpumask_clear(cpus);
-		return -EINVAL;
-	} else
-		return 0;
-}
-#else
-/* On return cpumask will be altered to indicate CPUs changed.
- * CPUs with states changed will be set in the mask,
- * CPUs with status unchanged will be unset in the mask. */
-static int rtas_cpu_state_change_mask(enum rtas_cpu_state state,
-				cpumask_var_t cpus)
-{
-	int cpu;
-	int cpuret = 0;
-	int ret = 0;
-
-	if (cpumask_empty(cpus))
-		return 0;
-
-	for_each_cpu(cpu, cpus) {
-		struct device *dev = get_cpu_device(cpu);
-
-		switch (state) {
-		case DOWN:
-			cpuret = device_offline(dev);
-			break;
-		case UP:
-			cpuret = device_online(dev);
-			break;
-		}
-		if (cpuret < 0) {
-			pr_debug("%s: cpu_%s for cpu#%d returned %d.\n",
-					__func__,
-					((state == UP) ? "up" : "down"),
-					cpu, cpuret);
-			if (!ret)
-				ret = cpuret;
-			if (state == UP) {
-				/* clear bits for unchanged cpus, return */
-				cpumask_shift_right(cpus, cpus, cpu);
-				cpumask_shift_left(cpus, cpus, cpu);
-				break;
-			} else {
-				/* clear bit for unchanged cpu, continue */
-				cpumask_clear_cpu(cpu, cpus);
-			}
-		}
-		cond_resched();
-	}
-
-	return ret;
-}
-#endif
-
-int rtas_online_cpus_mask(cpumask_var_t cpus)
-{
-	int ret;
-
-	ret = rtas_cpu_state_change_mask(UP, cpus);
-
-	if (ret) {
-		cpumask_var_t tmp_mask;
-
-		if (!alloc_cpumask_var(&tmp_mask, GFP_KERNEL))
-			return ret;
-
-		/* Use tmp_mask to preserve cpus mask from first failure */
-		cpumask_copy(tmp_mask, cpus);
-		rtas_offline_cpus_mask(tmp_mask);
-		free_cpumask_var(tmp_mask);
-	}
-
-	return ret;
-}
-
-int rtas_offline_cpus_mask(cpumask_var_t cpus)
-{
-	return rtas_cpu_state_change_mask(DOWN, cpus);
-}
-
 int rtas_ibm_suspend_me(u64 handle)
 {
 	long state;
@@ -939,8 +854,6 @@
 	unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
 	struct rtas_suspend_me_data data;
 	DECLARE_COMPLETION_ONSTACK(done);
-	cpumask_var_t offline_mask;
-	int cpuret;
 
 	if (!rtas_service_present("ibm,suspend-me"))
 		return -ENOSYS;
@@ -961,9 +874,6 @@
 		return -EIO;
 	}
 
-	if (!alloc_cpumask_var(&offline_mask, GFP_KERNEL))
-		return -ENOMEM;
-
 	atomic_set(&data.working, 0);
 	atomic_set(&data.done, 0);
 	atomic_set(&data.error, 0);
@@ -972,24 +882,8 @@
 
 	lock_device_hotplug();
 
-	/* All present CPUs must be online */
-	cpumask_andnot(offline_mask, cpu_present_mask, cpu_online_mask);
-	cpuret = rtas_online_cpus_mask(offline_mask);
-	if (cpuret) {
-		pr_err("%s: Could not bring present CPUs online.\n", __func__);
-		atomic_set(&data.error, cpuret);
-		goto out;
-	}
-
 	cpu_hotplug_disable();
 
-	/* Check if we raced with a CPU-Offline Operation */
-	if (!cpumask_equal(cpu_present_mask, cpu_online_mask)) {
-		pr_info("%s: Raced against a concurrent CPU-Offline\n", __func__);
-		atomic_set(&data.error, -EAGAIN);
-		goto out_hotplug_enable;
-	}
-
 	/* Call function on all CPUs.  One of us will make the
 	 * rtas call
 	 */
@@ -1000,18 +894,11 @@
 	if (atomic_read(&data.error) != 0)
 		printk(KERN_ERR "Error doing global join\n");
 
-out_hotplug_enable:
-	cpu_hotplug_enable();
 
-	/* Take down CPUs not online prior to suspend */
-	cpuret = rtas_offline_cpus_mask(offline_mask);
-	if (cpuret)
-		pr_warn("%s: Could not restore CPUs to offline state.\n",
-				__func__);
+	cpu_hotplug_enable();
 
-out:
 	unlock_device_hotplug();
-	free_cpumask_var(offline_mask);
+
 	return atomic_read(&data.error);
 }
 #else /* CONFIG_PPC_PSERIES */
@@ -1058,6 +945,156 @@
 	return NULL;
 }
 
+#ifdef CONFIG_PPC_RTAS_FILTER
+
+/*
+ * The sys_rtas syscall, as originally designed, allows root to pass
+ * arbitrary physical addresses to RTAS calls. A number of RTAS calls
+ * can be abused to write to arbitrary memory and do other things that
+ * are potentially harmful to system integrity, and thus should only
+ * be used inside the kernel and not exposed to userspace.
+ *
+ * All known legitimate users of the sys_rtas syscall will only ever
+ * pass addresses that fall within the RMO buffer, and use a known
+ * subset of RTAS calls.
+ *
+ * Accordingly, we filter RTAS requests to check that the call is
+ * permitted, and that provided pointers fall within the RMO buffer.
+ * The rtas_filters list contains an entry for each permitted call,
+ * with the indexes of the parameters which are expected to contain
+ * addresses and sizes of buffers allocated inside the RMO buffer.
+ */
+struct rtas_filter {
+	const char *name;
+	int token;
+	/* Indexes into the args buffer, -1 if not used */
+	int buf_idx1;
+	int size_idx1;
+	int buf_idx2;
+	int size_idx2;
+
+	int fixed_size;
+};
+
+static struct rtas_filter rtas_filters[] __ro_after_init = {
+	{ "ibm,activate-firmware", -1, -1, -1, -1, -1 },
+	{ "ibm,configure-connector", -1, 0, -1, 1, -1, 4096 },	/* Special cased */
+	{ "display-character", -1, -1, -1, -1, -1 },
+	{ "ibm,display-message", -1, 0, -1, -1, -1 },
+	{ "ibm,errinjct", -1, 2, -1, -1, -1, 1024 },
+	{ "ibm,close-errinjct", -1, -1, -1, -1, -1 },
+	{ "ibm,open-errinjct", -1, -1, -1, -1, -1 },
+	{ "ibm,get-config-addr-info2", -1, -1, -1, -1, -1 },
+	{ "ibm,get-dynamic-sensor-state", -1, 1, -1, -1, -1 },
+	{ "ibm,get-indices", -1, 2, 3, -1, -1 },
+	{ "get-power-level", -1, -1, -1, -1, -1 },
+	{ "get-sensor-state", -1, -1, -1, -1, -1 },
+	{ "ibm,get-system-parameter", -1, 1, 2, -1, -1 },
+	{ "get-time-of-day", -1, -1, -1, -1, -1 },
+	{ "ibm,get-vpd", -1, 0, -1, 1, 2 },
+	{ "ibm,lpar-perftools", -1, 2, 3, -1, -1 },
+	{ "ibm,platform-dump", -1, 4, 5, -1, -1 },		/* Special cased */
+	{ "ibm,read-slot-reset-state", -1, -1, -1, -1, -1 },
+	{ "ibm,scan-log-dump", -1, 0, 1, -1, -1 },
+	{ "ibm,set-dynamic-indicator", -1, 2, -1, -1, -1 },
+	{ "ibm,set-eeh-option", -1, -1, -1, -1, -1 },
+	{ "set-indicator", -1, -1, -1, -1, -1 },
+	{ "set-power-level", -1, -1, -1, -1, -1 },
+	{ "set-time-for-power-on", -1, -1, -1, -1, -1 },
+	{ "ibm,set-system-parameter", -1, 1, -1, -1, -1 },
+	{ "set-time-of-day", -1, -1, -1, -1, -1 },
+	{ "ibm,suspend-me", -1, -1, -1, -1, -1 },
+	{ "ibm,update-nodes", -1, 0, -1, -1, -1, 4096 },
+	{ "ibm,update-properties", -1, 0, -1, -1, -1, 4096 },
+	{ "ibm,physical-attestation", -1, 0, 1, -1, -1 },
+};
+
+static bool in_rmo_buf(u32 base, u32 end)
+{
+	return base >= rtas_rmo_buf &&
+		base < (rtas_rmo_buf + RTAS_RMOBUF_MAX) &&
+		base <= end &&
+		end >= rtas_rmo_buf &&
+		end < (rtas_rmo_buf + RTAS_RMOBUF_MAX);
+}
+
+static bool block_rtas_call(int token, int nargs,
+			    struct rtas_args *args)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(rtas_filters); i++) {
+		struct rtas_filter *f = &rtas_filters[i];
+		u32 base, size, end;
+
+		if (token != f->token)
+			continue;
+
+		if (f->buf_idx1 != -1) {
+			base = be32_to_cpu(args->args[f->buf_idx1]);
+			if (f->size_idx1 != -1)
+				size = be32_to_cpu(args->args[f->size_idx1]);
+			else if (f->fixed_size)
+				size = f->fixed_size;
+			else
+				size = 1;
+
+			end = base + size - 1;
+
+			/*
+			 * Special case for ibm,platform-dump - NULL buffer
+			 * address is used to indicate end of dump processing
+			 */
+			if (!strcmp(f->name, "ibm,platform-dump") &&
+			    base == 0)
+				return false;
+
+			if (!in_rmo_buf(base, end))
+				goto err;
+		}
+
+		if (f->buf_idx2 != -1) {
+			base = be32_to_cpu(args->args[f->buf_idx2]);
+			if (f->size_idx2 != -1)
+				size = be32_to_cpu(args->args[f->size_idx2]);
+			else if (f->fixed_size)
+				size = f->fixed_size;
+			else
+				size = 1;
+			end = base + size - 1;
+
+			/*
+			 * Special case for ibm,configure-connector where the
+			 * address can be 0
+			 */
+			if (!strcmp(f->name, "ibm,configure-connector") &&
+			    base == 0)
+				return false;
+
+			if (!in_rmo_buf(base, end))
+				goto err;
+		}
+
+		return false;
+	}
+
+err:
+	pr_err_ratelimited("sys_rtas: RTAS call blocked - exploit attempt?\n");
+	pr_err_ratelimited("sys_rtas: token=0x%x, nargs=%d (called by %s)\n",
+			   token, nargs, current->comm);
+	return true;
+}
+
+#else
+
+static bool block_rtas_call(int token, int nargs,
+			    struct rtas_args *args)
+{
+	return false;
+}
+
+#endif /* CONFIG_PPC_RTAS_FILTER */
+
 /* We assume to be passed big endian arguments */
 SYSCALL_DEFINE1(rtas, struct rtas_args __user *, uargs)
 {
@@ -1095,6 +1132,9 @@
 	args.rets = &args.args[nargs];
 	memset(args.rets, 0, nret * sizeof(rtas_arg_t));
 
+	if (block_rtas_call(token, nargs, &args))
+		return -EINVAL;
+
 	/* Need to handle ibm,suspend_me call specially */
 	if (token == ibm_suspend_me_token) {
 
@@ -1156,6 +1196,9 @@
 	unsigned long rtas_region = RTAS_INSTANTIATE_MAX;
 	u32 base, size, entry;
 	int no_base, no_size, no_entry;
+#ifdef CONFIG_PPC_RTAS_FILTER
+	int i;
+#endif
 
 	/* Get RTAS dev node and fill up our "rtas" structure with infos
 	 * about it.
@@ -1177,6 +1220,13 @@
 	no_entry = of_property_read_u32(rtas.dev, "linux,rtas-entry", &entry);
 	rtas.entry = no_entry ? rtas.base : entry;
 
+	/*
+	 * Discover these now to avoid device tree lookups in the
+	 * panic path.
+	 */
+	if (of_property_read_bool(rtas.dev, "ibm,extended-os-term"))
+		ibm_os_term_token = rtas_token("ibm,os-term");
+
 	/* If RTAS was found, allocate the RMO buffer for it and look for
 	 * the stop-self token if any
 	 */
@@ -1195,6 +1245,12 @@
 #ifdef CONFIG_RTAS_ERROR_LOGGING
 	rtas_last_error_token = rtas_token("rtas-last-error");
 #endif
+
+#ifdef CONFIG_PPC_RTAS_FILTER
+	for (i = 0; i < ARRAY_SIZE(rtas_filters); i++) {
+		rtas_filters[i].token = rtas_token(rtas_filters[i].name);
+	}
+#endif
 }
 
 int __init early_init_dt_scan_rtas(unsigned long node,
@@ -1209,6 +1265,12 @@
 	entryp = of_get_flat_dt_prop(node, "linux,rtas-entry", NULL);
 	sizep  = of_get_flat_dt_prop(node, "rtas-size", NULL);
 
+#ifdef CONFIG_PPC64
+	/* need this feature to decide the crashkernel offset */
+	if (of_get_flat_dt_prop(node, "ibm,hypertas-functions", NULL))
+		powerpc_firmware_features |= FW_FEATURE_LPAR;
+#endif
+
 	if (basep && entryp && sizep) {
 		rtas.base = *basep;
 		rtas.entry = *entryp;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/rtas_flash.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/rtas_flash.c
@@ -710,9 +710,9 @@
 	if (!rtas_validate_flash_data.buf)
 		return -ENOMEM;
 
-	flash_block_cache = kmem_cache_create("rtas_flash_cache",
-					      RTAS_BLK_SIZE, RTAS_BLK_SIZE, 0,
-					      NULL);
+	flash_block_cache = kmem_cache_create_usercopy("rtas_flash_cache",
+						       RTAS_BLK_SIZE, RTAS_BLK_SIZE,
+						       0, 0, RTAS_BLK_SIZE, NULL);
 	if (!flash_block_cache) {
 		printk(KERN_ERR "%s: failed to create block cache\n",
 				__func__);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/secure_boot.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/secure_boot.c
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain
+ */
+#include <linux/types.h>
+#include <linux/of.h>
+#include <asm/secure_boot.h>
+
+static struct device_node *get_ppc_fw_sb_node(void)
+{
+	static const struct of_device_id ids[] = {
+		{ .compatible = "ibm,secureboot", },
+		{ .compatible = "ibm,secureboot-v1", },
+		{ .compatible = "ibm,secureboot-v2", },
+		{},
+	};
+
+	return of_find_matching_node(NULL, ids);
+}
+
+bool is_ppc_secureboot_enabled(void)
+{
+	struct device_node *node;
+	bool enabled = false;
+
+	node = get_ppc_fw_sb_node();
+	enabled = of_property_read_bool(node, "os-secureboot-enforcing");
+
+	of_node_put(node);
+
+	pr_info("Secure boot mode %s\n", enabled ? "enabled" : "disabled");
+
+	return enabled;
+}
+
+bool is_ppc_trustedboot_enabled(void)
+{
+	struct device_node *node;
+	bool enabled = false;
+
+	node = get_ppc_fw_sb_node();
+	enabled = of_property_read_bool(node, "trusted-enabled");
+
+	of_node_put(node);
+
+	pr_info("Trusted boot mode %s\n", enabled ? "enabled" : "disabled");
+
+	return enabled;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/security.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/security.c
@@ -16,7 +16,7 @@
 #include <asm/setup.h>
 
 
-unsigned long powerpc_security_features __read_mostly = SEC_FTR_DEFAULT;
+u64 powerpc_security_features __read_mostly = SEC_FTR_DEFAULT;
 
 enum count_cache_flush_type {
 	COUNT_CACHE_FLUSH_NONE	= 0x1,
@@ -24,6 +24,7 @@
 	COUNT_CACHE_FLUSH_HW	= 0x4,
 };
 static enum count_cache_flush_type count_cache_flush_type = COUNT_CACHE_FLUSH_NONE;
+static bool link_stack_flush_enabled;
 
 bool barrier_nospec_enabled;
 static bool no_nospec;
@@ -108,7 +109,7 @@
 static __init int security_feature_debugfs_init(void)
 {
 	debugfs_create_x64("security_features", 0400, powerpc_debugfs_root,
-			   (u64 *)&powerpc_security_features);
+			   &powerpc_security_features);
 	return 0;
 }
 device_initcall(security_feature_debugfs_init);
@@ -141,32 +142,33 @@
 
 	thread_priv = security_ftr_enabled(SEC_FTR_L1D_THREAD_PRIV);
 
-	if (rfi_flush || thread_priv) {
+	if (rfi_flush) {
 		struct seq_buf s;
 		seq_buf_init(&s, buf, PAGE_SIZE - 1);
 
-		seq_buf_printf(&s, "Mitigation: ");
-
-		if (rfi_flush)
-			seq_buf_printf(&s, "RFI Flush");
-
-		if (rfi_flush && thread_priv)
-			seq_buf_printf(&s, ", ");
-
+		seq_buf_printf(&s, "Mitigation: RFI Flush");
 		if (thread_priv)
-			seq_buf_printf(&s, "L1D private per thread");
+			seq_buf_printf(&s, ", L1D private per thread");
 
 		seq_buf_printf(&s, "\n");
 
 		return s.len;
 	}
 
+	if (thread_priv)
+		return sprintf(buf, "Vulnerable: L1D private per thread\n");
+
 	if (!security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV) &&
 	    !security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR))
 		return sprintf(buf, "Not affected\n");
 
 	return sprintf(buf, "Vulnerable\n");
 }
+
+ssize_t cpu_show_l1tf(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	return cpu_show_meltdown(dev, attr, buf);
+}
 #endif
 
 ssize_t cpu_show_spectre_v1(struct device *dev, struct device_attribute *attr, char *buf)
@@ -212,11 +214,19 @@
 
 		if (ccd)
 			seq_buf_printf(&s, "Indirect branch cache disabled");
+
+		if (link_stack_flush_enabled)
+			seq_buf_printf(&s, ", Software link stack flush");
+
 	} else if (count_cache_flush_type != COUNT_CACHE_FLUSH_NONE) {
 		seq_buf_printf(&s, "Mitigation: Software count cache flush");
 
 		if (count_cache_flush_type == COUNT_CACHE_FLUSH_HW)
 			seq_buf_printf(&s, " (hardware accelerated)");
+
+		if (link_stack_flush_enabled)
+			seq_buf_printf(&s, ", Software link stack flush");
+
 	} else if (btb_flush_enabled) {
 		seq_buf_printf(&s, "Mitigation: Branch predictor state flush");
 	} else {
@@ -246,6 +256,11 @@
 
 early_param("no_stf_barrier", handle_no_stf_barrier);
 
+enum stf_barrier_type stf_barrier_type_get(void)
+{
+	return stf_enabled_flush_types;
+}
+
 /* This is the generic flag used by other architectures */
 static int __init handle_ssbd(char *p)
 {
@@ -377,18 +392,49 @@
 device_initcall(stf_barrier_debugfs_init);
 #endif /* CONFIG_DEBUG_FS */
 
+static void no_count_cache_flush(void)
+{
+	count_cache_flush_type = COUNT_CACHE_FLUSH_NONE;
+	pr_info("count-cache-flush: software flush disabled.\n");
+}
+
 static void toggle_count_cache_flush(bool enable)
 {
-	if (!enable || !security_ftr_enabled(SEC_FTR_FLUSH_COUNT_CACHE)) {
+	if (!security_ftr_enabled(SEC_FTR_FLUSH_COUNT_CACHE) &&
+	    !security_ftr_enabled(SEC_FTR_FLUSH_LINK_STACK))
+		enable = false;
+
+	if (!enable) {
 		patch_instruction_site(&patch__call_flush_count_cache, PPC_INST_NOP);
-		count_cache_flush_type = COUNT_CACHE_FLUSH_NONE;
-		pr_info("count-cache-flush: software flush disabled.\n");
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+		patch_instruction_site(&patch__call_kvm_flush_link_stack, PPC_INST_NOP);
+#endif
+		pr_info("link-stack-flush: software flush disabled.\n");
+		link_stack_flush_enabled = false;
+		no_count_cache_flush();
 		return;
 	}
 
+	// This enables the branch from _switch to flush_count_cache
 	patch_branch_site(&patch__call_flush_count_cache,
 			  (u64)&flush_count_cache, BRANCH_SET_LINK);
 
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+	// This enables the branch from guest_exit_cont to kvm_flush_link_stack
+	patch_branch_site(&patch__call_kvm_flush_link_stack,
+			  (u64)&kvm_flush_link_stack, BRANCH_SET_LINK);
+#endif
+
+	pr_info("link-stack-flush: software flush enabled.\n");
+	link_stack_flush_enabled = true;
+
+	// If we just need to flush the link stack, patch an early return
+	if (!security_ftr_enabled(SEC_FTR_FLUSH_COUNT_CACHE)) {
+		patch_instruction_site(&patch__flush_link_stack_return, PPC_INST_BLR);
+		no_count_cache_flush();
+		return;
+	}
+
 	if (!security_ftr_enabled(SEC_FTR_BCCTR_FLUSH_ASSIST)) {
 		count_cache_flush_type = COUNT_CACHE_FLUSH_SW;
 		pr_info("count-cache-flush: full software flush sequence enabled.\n");
@@ -407,11 +453,20 @@
 	if (no_spectrev2 || cpu_mitigations_off()) {
 		if (security_ftr_enabled(SEC_FTR_BCCTRL_SERIALISED) ||
 		    security_ftr_enabled(SEC_FTR_COUNT_CACHE_DISABLED))
-			pr_warn("Spectre v2 mitigations not under software control, can't disable\n");
+			pr_warn("Spectre v2 mitigations not fully under software control, can't disable\n");
 
 		enable = false;
 	}
 
+	/*
+	 * There's no firmware feature flag/hypervisor bit to tell us we need to
+	 * flush the link stack on context switch. So we set it here if we see
+	 * either of the Spectre v2 mitigations that aim to protect userspace.
+	 */
+	if (security_ftr_enabled(SEC_FTR_COUNT_CACHE_DISABLED) ||
+	    security_ftr_enabled(SEC_FTR_FLUSH_COUNT_CACHE))
+		security_ftr_set(SEC_FTR_FLUSH_LINK_STACK);
+
 	toggle_count_cache_flush(enable);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/secvar-ops.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/secvar-ops.c
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Nayna Jain
+ *
+ * This file initializes secvar operations for PowerPC Secureboot
+ */
+
+#include <linux/cache.h>
+#include <asm/secvar.h>
+
+const struct secvar_operations *secvar_ops __ro_after_init;
+
+void set_secvar_ops(const struct secvar_operations *ops)
+{
+	secvar_ops = ops;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/secvar-sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/secvar-sysfs.c
@@ -0,0 +1,248 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 IBM Corporation <nayna@linux.ibm.com>
+ *
+ * This code exposes secure variables to user via sysfs
+ */
+
+#define pr_fmt(fmt) "secvar-sysfs: "fmt
+
+#include <linux/slab.h>
+#include <linux/compat.h>
+#include <linux/string.h>
+#include <linux/of.h>
+#include <asm/secvar.h>
+
+#define NAME_MAX_SIZE	   1024
+
+static struct kobject *secvar_kobj;
+static struct kset *secvar_kset;
+
+static ssize_t format_show(struct kobject *kobj, struct kobj_attribute *attr,
+			   char *buf)
+{
+	ssize_t rc = 0;
+	struct device_node *node;
+	const char *format;
+
+	node = of_find_compatible_node(NULL, NULL, "ibm,secvar-backend");
+	if (!of_device_is_available(node))
+		return -ENODEV;
+
+	rc = of_property_read_string(node, "format", &format);
+	if (rc)
+		return rc;
+
+	rc = sprintf(buf, "%s\n", format);
+
+	of_node_put(node);
+
+	return rc;
+}
+
+
+static ssize_t size_show(struct kobject *kobj, struct kobj_attribute *attr,
+			 char *buf)
+{
+	uint64_t dsize;
+	int rc;
+
+	rc = secvar_ops->get(kobj->name, strlen(kobj->name) + 1, NULL, &dsize);
+	if (rc) {
+		pr_err("Error retrieving %s variable size %d\n", kobj->name,
+		       rc);
+		return rc;
+	}
+
+	return sprintf(buf, "%llu\n", dsize);
+}
+
+static ssize_t data_read(struct file *filep, struct kobject *kobj,
+			 struct bin_attribute *attr, char *buf, loff_t off,
+			 size_t count)
+{
+	uint64_t dsize;
+	char *data;
+	int rc;
+
+	rc = secvar_ops->get(kobj->name, strlen(kobj->name) + 1, NULL, &dsize);
+	if (rc) {
+		pr_err("Error getting %s variable size %d\n", kobj->name, rc);
+		return rc;
+	}
+	pr_debug("dsize is %llu\n", dsize);
+
+	data = kzalloc(dsize, GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	rc = secvar_ops->get(kobj->name, strlen(kobj->name) + 1, data, &dsize);
+	if (rc) {
+		pr_err("Error getting %s variable %d\n", kobj->name, rc);
+		goto data_fail;
+	}
+
+	rc = memory_read_from_buffer(buf, count, &off, data, dsize);
+
+data_fail:
+	kfree(data);
+	return rc;
+}
+
+static ssize_t update_write(struct file *filep, struct kobject *kobj,
+			    struct bin_attribute *attr, char *buf, loff_t off,
+			    size_t count)
+{
+	int rc;
+
+	pr_debug("count is %ld\n", count);
+	rc = secvar_ops->set(kobj->name, strlen(kobj->name) + 1, buf, count);
+	if (rc) {
+		pr_err("Error setting the %s variable %d\n", kobj->name, rc);
+		return rc;
+	}
+
+	return count;
+}
+
+static struct kobj_attribute format_attr = __ATTR_RO(format);
+
+static struct kobj_attribute size_attr = __ATTR_RO(size);
+
+static struct bin_attribute data_attr = __BIN_ATTR_RO(data, 0);
+
+static struct bin_attribute update_attr = __BIN_ATTR_WO(update, 0);
+
+static struct bin_attribute *secvar_bin_attrs[] = {
+	&data_attr,
+	&update_attr,
+	NULL,
+};
+
+static struct attribute *secvar_attrs[] = {
+	&size_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group secvar_attr_group = {
+	.attrs = secvar_attrs,
+	.bin_attrs = secvar_bin_attrs,
+};
+__ATTRIBUTE_GROUPS(secvar_attr);
+
+static struct kobj_type secvar_ktype = {
+	.sysfs_ops	= &kobj_sysfs_ops,
+	.default_groups = secvar_attr_groups,
+};
+
+static int update_kobj_size(void)
+{
+
+	struct device_node *node;
+	u64 varsize;
+	int rc = 0;
+
+	node = of_find_compatible_node(NULL, NULL, "ibm,secvar-backend");
+	if (!of_device_is_available(node)) {
+		rc = -ENODEV;
+		goto out;
+	}
+
+	rc = of_property_read_u64(node, "max-var-size", &varsize);
+	if (rc)
+		goto out;
+
+	data_attr.size = varsize;
+	update_attr.size = varsize;
+
+out:
+	of_node_put(node);
+
+	return rc;
+}
+
+static int secvar_sysfs_load(void)
+{
+	char *name;
+	uint64_t namesize = 0;
+	struct kobject *kobj;
+	int rc;
+
+	name = kzalloc(NAME_MAX_SIZE, GFP_KERNEL);
+	if (!name)
+		return -ENOMEM;
+
+	do {
+		rc = secvar_ops->get_next(name, &namesize, NAME_MAX_SIZE);
+		if (rc) {
+			if (rc != -ENOENT)
+				pr_err("error getting secvar from firmware %d\n",
+				       rc);
+			break;
+		}
+
+		kobj = kzalloc(sizeof(*kobj), GFP_KERNEL);
+		if (!kobj) {
+			rc = -ENOMEM;
+			break;
+		}
+
+		kobject_init(kobj, &secvar_ktype);
+
+		rc = kobject_add(kobj, &secvar_kset->kobj, "%s", name);
+		if (rc) {
+			pr_warn("kobject_add error %d for attribute: %s\n", rc,
+				name);
+			kobject_put(kobj);
+			kobj = NULL;
+		}
+
+		if (kobj)
+			kobject_uevent(kobj, KOBJ_ADD);
+
+	} while (!rc);
+
+	kfree(name);
+	return rc;
+}
+
+static int secvar_sysfs_init(void)
+{
+	int rc;
+
+	if (!secvar_ops) {
+		pr_warn("secvar: failed to retrieve secvar operations.\n");
+		return -ENODEV;
+	}
+
+	secvar_kobj = kobject_create_and_add("secvar", firmware_kobj);
+	if (!secvar_kobj) {
+		pr_err("secvar: Failed to create firmware kobj\n");
+		return -ENOMEM;
+	}
+
+	rc = sysfs_create_file(secvar_kobj, &format_attr.attr);
+	if (rc) {
+		kobject_put(secvar_kobj);
+		return -ENOMEM;
+	}
+
+	secvar_kset = kset_create_and_add("vars", NULL, secvar_kobj);
+	if (!secvar_kset) {
+		pr_err("secvar: sysfs kobject registration failed.\n");
+		kobject_put(secvar_kobj);
+		return -ENOMEM;
+	}
+
+	rc = update_kobj_size();
+	if (rc) {
+		pr_err("Cannot read the size of the attribute\n");
+		return rc;
+	}
+
+	secvar_sysfs_load();
+
+	return 0;
+}
+
+late_initcall(secvar_sysfs_init);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/setup-common.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/setup-common.c
@@ -31,6 +31,7 @@
 #include <linux/memblock.h>
 #include <linux/of_platform.h>
 #include <linux/hugetlb.h>
+#include <linux/security.h>
 #include <asm/debugfs.h>
 #include <asm/io.h>
 #include <asm/paca.h>
@@ -64,6 +65,7 @@
 #include <asm/mmu_context.h>
 #include <asm/cpu_has_feature.h>
 #include <asm/kasan.h>
+#include <asm/secure_boot.h>
 
 #include "setup.h"
 
@@ -855,6 +857,16 @@
 	 */
 	initialize_cache_info();
 
+	/*
+	 * Lock down the kernel if booted in secure mode. This is required to
+	 * maintain kernel integrity.
+	 */
+	if (IS_ENABLED(CONFIG_LOCK_DOWN_IN_SECURE_BOOT)) {
+		if (is_ppc_secureboot_enabled())
+			security_lock_kernel_down("PowerNV Secure Boot mode",
+						  LOCKDOWN_INTEGRITY_MAX);
+	}
+
 	/* Initialize RTAS if available. */
 	rtas_initialize();
 
@@ -903,8 +915,6 @@
 
 	/* On BookE, setup per-core TLB data structures. */
 	setup_tlb_core_data();
-
-	smp_release_cpus();
 #endif
 
 	/* Print various info about the machine that has been gathered so far. */
@@ -925,6 +935,8 @@
 	exc_lvl_early_init();
 	emergency_stack_init();
 
+	smp_release_cpus();
+
 	initmem_init();
 
 	early_memtest(min_low_pfn << PAGE_SHIFT, max_low_pfn << PAGE_SHIFT);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/setup_64.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/setup_64.c
@@ -290,18 +290,36 @@
 
 	/* -------- printk is _NOT_ safe to use here ! ------- */
 
-	/* Try new device tree based feature discovery ... */
-	if (!dt_cpu_ftrs_init(__va(dt_ptr)))
-		/* Otherwise use the old style CPU table */
-		identify_cpu(0, mfspr(SPRN_PVR));
-
-	/* Assume we're on cpu 0 for now. Don't write to the paca yet! */
+	/*
+	 * Assume we're on cpu 0 for now.
+	 *
+	 * We need to load a PACA very early for a few reasons.
+	 *
+	 * The stack protector canary is stored in the paca, so as soon as we
+	 * call any stack protected code we need r13 pointing somewhere valid.
+	 *
+	 * If we are using kcov it will call in_task() in its instrumentation,
+	 * which relies on the current task from the PACA.
+	 *
+	 * dt_cpu_ftrs_init() calls into generic OF/fdt code, as well as
+	 * printk(), which can trigger both stack protector and kcov.
+	 *
+	 * percpu variables and spin locks also use the paca.
+	 *
+	 * So set up a temporary paca. It will be replaced below once we know
+	 * what CPU we are on.
+	 */
 	initialise_paca(&boot_paca, 0);
 	setup_paca(&boot_paca);
 	fixup_boot_paca();
 
 	/* -------- printk is now safe to use ------- */
 
+	/* Try new device tree based feature discovery ... */
+	if (!dt_cpu_ftrs_init(__va(dt_ptr)))
+		/* Otherwise use the old style CPU table */
+		identify_cpu(0, mfspr(SPRN_PVR));
+
 	/* Enable early debugging if any specified (see udbg.h) */
 	udbg_early_init();
 
@@ -523,6 +541,8 @@
 	lsizep = of_get_property(np, propnames[3], NULL);
 	if (bsizep == NULL)
 		bsizep = lsizep;
+	if (lsizep == NULL)
+		lsizep = bsizep;
 	if (lsizep != NULL)
 		lsize = be32_to_cpu(*lsizep);
 	if (bsizep != NULL)
@@ -839,7 +859,13 @@
 static enum l1d_flush_type enabled_flush_types;
 static void *l1d_flush_fallback_area;
 static bool no_rfi_flush;
+static bool no_entry_flush;
+static bool no_uaccess_flush;
 bool rfi_flush;
+bool entry_flush;
+bool uaccess_flush;
+DEFINE_STATIC_KEY_FALSE(uaccess_flush_key);
+EXPORT_SYMBOL(uaccess_flush_key);
 
 static int __init handle_no_rfi_flush(char *p)
 {
@@ -849,6 +875,22 @@
 }
 early_param("no_rfi_flush", handle_no_rfi_flush);
 
+static int __init handle_no_entry_flush(char *p)
+{
+	pr_info("entry-flush: disabled on command line.");
+	no_entry_flush = true;
+	return 0;
+}
+early_param("no_entry_flush", handle_no_entry_flush);
+
+static int __init handle_no_uaccess_flush(char *p)
+{
+	pr_info("uaccess-flush: disabled on command line.");
+	no_uaccess_flush = true;
+	return 0;
+}
+early_param("no_uaccess_flush", handle_no_uaccess_flush);
+
 /*
  * The RFI flush is not KPTI, but because users will see doco that says to use
  * nopti we hijack that option here to also disable the RFI flush.
@@ -880,6 +922,32 @@
 	rfi_flush = enable;
 }
 
+void entry_flush_enable(bool enable)
+{
+	if (enable) {
+		do_entry_flush_fixups(enabled_flush_types);
+		on_each_cpu(do_nothing, NULL, 1);
+	} else {
+		do_entry_flush_fixups(L1D_FLUSH_NONE);
+	}
+
+	entry_flush = enable;
+}
+
+void uaccess_flush_enable(bool enable)
+{
+	if (enable) {
+		do_uaccess_flush_fixups(enabled_flush_types);
+		static_branch_enable(&uaccess_flush_key);
+		on_each_cpu(do_nothing, NULL, 1);
+	} else {
+		static_branch_disable(&uaccess_flush_key);
+		do_uaccess_flush_fixups(L1D_FLUSH_NONE);
+	}
+
+	uaccess_flush = enable;
+}
+
 static void __ref init_fallback_flush(void)
 {
 	u64 l1d_size, limit;
@@ -938,10 +1006,28 @@
 
 	enabled_flush_types = types;
 
-	if (!no_rfi_flush && !cpu_mitigations_off())
+	if (!cpu_mitigations_off() && !no_rfi_flush)
 		rfi_flush_enable(enable);
 }
 
+void setup_entry_flush(bool enable)
+{
+	if (cpu_mitigations_off())
+		return;
+
+	if (!no_entry_flush)
+		entry_flush_enable(enable);
+}
+
+void setup_uaccess_flush(bool enable)
+{
+	if (cpu_mitigations_off())
+		return;
+
+	if (!no_uaccess_flush)
+		uaccess_flush_enable(enable);
+}
+
 #ifdef CONFIG_DEBUG_FS
 static int rfi_flush_set(void *data, u64 val)
 {
@@ -969,9 +1055,63 @@
 
 DEFINE_SIMPLE_ATTRIBUTE(fops_rfi_flush, rfi_flush_get, rfi_flush_set, "%llu\n");
 
+static int entry_flush_set(void *data, u64 val)
+{
+	bool enable;
+
+	if (val == 1)
+		enable = true;
+	else if (val == 0)
+		enable = false;
+	else
+		return -EINVAL;
+
+	/* Only do anything if we're changing state */
+	if (enable != entry_flush)
+		entry_flush_enable(enable);
+
+	return 0;
+}
+
+static int entry_flush_get(void *data, u64 *val)
+{
+	*val = entry_flush ? 1 : 0;
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(fops_entry_flush, entry_flush_get, entry_flush_set, "%llu\n");
+
+static int uaccess_flush_set(void *data, u64 val)
+{
+	bool enable;
+
+	if (val == 1)
+		enable = true;
+	else if (val == 0)
+		enable = false;
+	else
+		return -EINVAL;
+
+	/* Only do anything if we're changing state */
+	if (enable != uaccess_flush)
+		uaccess_flush_enable(enable);
+
+	return 0;
+}
+
+static int uaccess_flush_get(void *data, u64 *val)
+{
+	*val = uaccess_flush ? 1 : 0;
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(fops_uaccess_flush, uaccess_flush_get, uaccess_flush_set, "%llu\n");
+
 static __init int rfi_flush_debugfs_init(void)
 {
 	debugfs_create_file("rfi_flush", 0600, powerpc_debugfs_root, NULL, &fops_rfi_flush);
+	debugfs_create_file("entry_flush", 0600, powerpc_debugfs_root, NULL, &fops_entry_flush);
+	debugfs_create_file("uaccess_flush", 0600, powerpc_debugfs_root, NULL, &fops_uaccess_flush);
 	return 0;
 }
 device_initcall(rfi_flush_debugfs_init);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/signal.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/signal.c
@@ -200,14 +200,27 @@
 	 * normal/non-checkpointed stack pointer.
 	 */
 
+	unsigned long ret = tsk->thread.regs->gpr[1];
+
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
 	BUG_ON(tsk != current);
 
 	if (MSR_TM_ACTIVE(tsk->thread.regs->msr)) {
+		preempt_disable();
 		tm_reclaim_current(TM_CAUSE_SIGNAL);
 		if (MSR_TM_TRANSACTIONAL(tsk->thread.regs->msr))
-			return tsk->thread.ckpt_regs.gpr[1];
+			ret = tsk->thread.ckpt_regs.gpr[1];
+
+		/*
+		 * If we treclaim, we must clear the current thread's TM bits
+		 * before re-enabling preemption. Otherwise we might be
+		 * preempted and have the live MSR[TS] changed behind our back
+		 * (tm_recheckpoint_new_task() would recheckpoint). Besides, we
+		 * enter the signal handler in non-transactional state.
+		 */
+		tsk->thread.regs->msr &= ~MSR_TS_MASK;
+		preempt_enable();
 	}
 #endif
-	return tsk->thread.regs->gpr[1];
+	return ret;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/signal_32.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/signal_32.c
@@ -489,19 +489,11 @@
  */
 static int save_tm_user_regs(struct pt_regs *regs,
 			     struct mcontext __user *frame,
-			     struct mcontext __user *tm_frame, int sigret)
+			     struct mcontext __user *tm_frame, int sigret,
+			     unsigned long msr)
 {
-	unsigned long msr = regs->msr;
-
 	WARN_ON(tm_suspend_disabled);
 
-	/* Remove TM bits from thread's MSR.  The MSR in the sigcontext
-	 * just indicates to userland that we were doing a transaction, but we
-	 * don't want to return in transactional state.  This also ensures
-	 * that flush_fp_to_thread won't set TIF_RESTORE_TM again.
-	 */
-	regs->msr &= ~MSR_TS_MASK;
-
 	/* Save both sets of general registers */
 	if (save_general_regs(&current->thread.ckpt_regs, frame)
 	    || save_general_regs(regs, tm_frame))
@@ -912,6 +904,10 @@
 	int sigret;
 	unsigned long tramp;
 	struct pt_regs *regs = tsk->thread.regs;
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+	/* Save the thread's msr before get_tm_stackpointer() changes it */
+	unsigned long msr = regs->msr;
+#endif
 
 	BUG_ON(tsk != current);
 
@@ -944,13 +940,13 @@
 
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
 	tm_frame = &rt_sf->uc_transact.uc_mcontext;
-	if (MSR_TM_ACTIVE(regs->msr)) {
+	if (MSR_TM_ACTIVE(msr)) {
 		if (__put_user((unsigned long)&rt_sf->uc_transact,
 			       &rt_sf->uc.uc_link) ||
 		    __put_user((unsigned long)tm_frame,
 			       &rt_sf->uc_transact.uc_regs))
 			goto badframe;
-		if (save_tm_user_regs(regs, frame, tm_frame, sigret))
+		if (save_tm_user_regs(regs, frame, tm_frame, sigret, msr))
 			goto badframe;
 	}
 	else
@@ -1369,6 +1365,10 @@
 	int sigret;
 	unsigned long tramp;
 	struct pt_regs *regs = tsk->thread.regs;
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+	/* Save the thread's msr before get_tm_stackpointer() changes it */
+	unsigned long msr = regs->msr;
+#endif
 
 	BUG_ON(tsk != current);
 
@@ -1402,9 +1402,9 @@
 
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
 	tm_mctx = &frame->mctx_transact;
-	if (MSR_TM_ACTIVE(regs->msr)) {
+	if (MSR_TM_ACTIVE(msr)) {
 		if (save_tm_user_regs(regs, &frame->mctx, &frame->mctx_transact,
-				      sigret))
+				      sigret, msr))
 			goto badframe;
 	}
 	else
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/signal_64.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/signal_64.c
@@ -192,7 +192,8 @@
 static long setup_tm_sigcontexts(struct sigcontext __user *sc,
 				 struct sigcontext __user *tm_sc,
 				 struct task_struct *tsk,
-				 int signr, sigset_t *set, unsigned long handler)
+				 int signr, sigset_t *set, unsigned long handler,
+				 unsigned long msr)
 {
 	/* When CONFIG_ALTIVEC is set, we _always_ setup v_regs even if the
 	 * process never used altivec yet (MSR_VEC is zero in pt_regs of
@@ -207,12 +208,11 @@
 	elf_vrreg_t __user *tm_v_regs = sigcontext_vmx_regs(tm_sc);
 #endif
 	struct pt_regs *regs = tsk->thread.regs;
-	unsigned long msr = tsk->thread.regs->msr;
 	long err = 0;
 
 	BUG_ON(tsk != current);
 
-	BUG_ON(!MSR_TM_ACTIVE(regs->msr));
+	BUG_ON(!MSR_TM_ACTIVE(msr));
 
 	WARN_ON(tm_suspend_disabled);
 
@@ -222,13 +222,6 @@
 	 */
 	msr |= tsk->thread.ckpt_regs.msr & (MSR_FP | MSR_VEC | MSR_VSX);
 
-	/* Remove TM bits from thread's MSR.  The MSR in the sigcontext
-	 * just indicates to userland that we were doing a transaction, but we
-	 * don't want to return in transactional state.  This also ensures
-	 * that flush_fp_to_thread won't set TIF_RESTORE_TM again.
-	 */
-	regs->msr &= ~MSR_TS_MASK;
-
 #ifdef CONFIG_ALTIVEC
 	err |= __put_user(v_regs, &sc->v_regs);
 	err |= __put_user(tm_v_regs, &tm_sc->v_regs);
@@ -480,8 +473,10 @@
 	err |= __get_user(tsk->thread.ckpt_regs.ccr,
 			  &sc->gp_regs[PT_CCR]);
 
+	/* Don't allow userspace to set the trap value */
+	regs->trap = 0;
+
 	/* These regs are not checkpointed; they can go in 'regs'. */
-	err |= __get_user(regs->trap, &sc->gp_regs[PT_TRAP]);
 	err |= __get_user(regs->dar, &sc->gp_regs[PT_DAR]);
 	err |= __get_user(regs->dsisr, &sc->gp_regs[PT_DSISR]);
 	err |= __get_user(regs->result, &sc->gp_regs[PT_RESULT]);
@@ -824,6 +819,10 @@
 	unsigned long newsp = 0;
 	long err = 0;
 	struct pt_regs *regs = tsk->thread.regs;
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+	/* Save the thread's msr before get_tm_stackpointer() changes it */
+	unsigned long msr = regs->msr;
+#endif
 
 	BUG_ON(tsk != current);
 
@@ -841,7 +840,7 @@
 	err |= __put_user(0, &frame->uc.uc_flags);
 	err |= __save_altstack(&frame->uc.uc_stack, regs->gpr[1]);
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
-	if (MSR_TM_ACTIVE(regs->msr)) {
+	if (MSR_TM_ACTIVE(msr)) {
 		/* The ucontext_t passed to userland points to the second
 		 * ucontext_t (for transactional state) with its uc_link ptr.
 		 */
@@ -849,7 +848,8 @@
 		err |= setup_tm_sigcontexts(&frame->uc.uc_mcontext,
 					    &frame->uc_transact.uc_mcontext,
 					    tsk, ksig->sig, NULL,
-					    (unsigned long)ksig->ka.sa.sa_handler);
+					    (unsigned long)ksig->ka.sa.sa_handler,
+					    msr);
 	} else
 #endif
 	{
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/smp.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/smp.c
@@ -583,11 +583,43 @@
 #endif
 
 #ifdef CONFIG_NMI_IPI
+static void crash_stop_this_cpu(struct pt_regs *regs)
+#else
+static void crash_stop_this_cpu(void *dummy)
+#endif
+{
+	/*
+	 * Just busy wait here and avoid marking CPU as offline to ensure
+	 * register data is captured appropriately.
+	 */
+	while (1)
+		cpu_relax();
+}
+
+void crash_smp_send_stop(void)
+{
+	static bool stopped = false;
+
+	if (stopped)
+		return;
+
+	stopped = true;
+
+#ifdef CONFIG_NMI_IPI
+	smp_send_nmi_ipi(NMI_IPI_ALL_OTHERS, crash_stop_this_cpu, 1000000);
+#else
+	smp_call_function(crash_stop_this_cpu, NULL, 0);
+#endif /* CONFIG_NMI_IPI */
+}
+
+#ifdef CONFIG_NMI_IPI
 static void nmi_stop_this_cpu(struct pt_regs *regs)
 {
 	/*
 	 * IRQs are already hard disabled by the smp_handle_nmi_ipi.
 	 */
+	set_cpu_online(smp_processor_id(), false);
+
 	spin_begin();
 	while (1)
 		spin_cpu_relax();
@@ -603,6 +635,15 @@
 static void stop_this_cpu(void *dummy)
 {
 	hard_irq_disable();
+
+	/*
+	 * Offlining CPUs in stop_this_cpu can result in scheduler warnings,
+	 * (see commit de6e5d38417e), but printk_safe_flush_on_panic() wants
+	 * to know other CPUs are offline before it breaks locks to flush
+	 * printk buffers, in case we panic()ed while holding the lock.
+	 */
+	set_cpu_online(smp_processor_id(), false);
+
 	spin_begin();
 	while (1)
 		spin_cpu_relax();
@@ -1254,6 +1295,9 @@
 
 	vdso_getcpu_init();
 #endif
+	set_numa_node(numa_cpu_lookup_table[cpu]);
+	set_numa_mem(local_memory_node(numa_cpu_lookup_table[cpu]));
+
 	/* Update topology CPU masks */
 	add_cpu_to_masks(cpu);
 
@@ -1266,9 +1310,6 @@
 	if (!cpumask_equal(cpu_l2_cache_mask(cpu), sibling_mask(cpu)))
 		shared_caches = true;
 
-	set_numa_node(numa_cpu_lookup_table[cpu]);
-	set_numa_mem(local_memory_node(numa_cpu_lookup_table[cpu]));
-
 	smp_wmb();
 	notify_cpu_starting(cpu);
 	set_cpu_online(cpu, true);
@@ -1285,10 +1326,12 @@
 	BUG();
 }
 
+#ifdef CONFIG_PROFILING
 int setup_profiling_timer(unsigned int multiplier)
 {
 	return 0;
 }
+#endif
 
 #ifdef CONFIG_SCHED_SMT
 /* cpumask of CPUs with asymetric SMT dependancy */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/stacktrace.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/stacktrace.c
@@ -8,6 +8,7 @@
  * Copyright 2018 Nick Piggin, Michael Ellerman, IBM Corp.
  */
 
+#include <linux/delay.h>
 #include <linux/export.h>
 #include <linux/kallsyms.h>
 #include <linux/module.h>
@@ -19,6 +20,7 @@
 #include <asm/ptrace.h>
 #include <asm/processor.h>
 #include <linux/ftrace.h>
+#include <linux/delay.h>
 #include <asm/kprobes.h>
 
 #include <asm/paca.h>
@@ -230,17 +232,31 @@
 
 static void raise_backtrace_ipi(cpumask_t *mask)
 {
+	struct paca_struct *p;
 	unsigned int cpu;
+	u64 delay_us;
 
 	for_each_cpu(cpu, mask) {
-		if (cpu == smp_processor_id())
+		if (cpu == smp_processor_id()) {
 			handle_backtrace_ipi(NULL);
-		else
-			smp_send_safe_nmi_ipi(cpu, handle_backtrace_ipi, 5 * USEC_PER_SEC);
-	}
+			continue;
+		}
 
-	for_each_cpu(cpu, mask) {
-		struct paca_struct *p = paca_ptrs[cpu];
+		delay_us = 5 * USEC_PER_SEC;
+
+		if (smp_send_safe_nmi_ipi(cpu, handle_backtrace_ipi, delay_us)) {
+			// Now wait up to 5s for the other CPU to do its backtrace
+			while (cpumask_test_cpu(cpu, mask) && delay_us) {
+				udelay(1);
+				delay_us--;
+			}
+
+			// Other CPU cleared itself from the mask
+			if (delay_us)
+				continue;
+		}
+
+		p = paca_ptrs[cpu];
 
 		cpumask_clear_cpu(cpu, mask);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/swsusp_32.S
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/swsusp_32.S
@@ -181,7 +181,7 @@
 #ifdef CONFIG_ALTIVEC
 	/* Stop pending alitvec streams and memory accesses */
 BEGIN_FTR_SECTION
-	DSSALL
+	PPC_DSSALL
 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 #endif
  	sync
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/swsusp_asm64.S
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/swsusp_asm64.S
@@ -142,7 +142,7 @@
 _GLOBAL(swsusp_arch_resume)
 	/* Stop pending alitvec streams and memory accesses */
 BEGIN_FTR_SECTION
-	DSSALL
+	PPC_DSSALL
 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 	sync
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/sysfs.c
@@ -31,29 +31,27 @@
 
 static DEFINE_PER_CPU(struct cpu, cpu_devices);
 
-/*
- * SMT snooze delay stuff, 64-bit only for now
- */
-
 #ifdef CONFIG_PPC64
 
-/* Time in microseconds we delay before sleeping in the idle loop */
-static DEFINE_PER_CPU(long, smt_snooze_delay) = { 100 };
+/*
+ * Snooze delay has not been hooked up since 3fa8cad82b94 ("powerpc/pseries/cpuidle:
+ * smt-snooze-delay cleanup.") and has been broken even longer. As was foretold in
+ * 2014:
+ *
+ *  "ppc64_util currently utilises it. Once we fix ppc64_util, propose to clean
+ *  up the kernel code."
+ *
+ * powerpc-utils stopped using it as of 1.3.8. At some point in the future this
+ * code should be removed.
+ */
 
 static ssize_t store_smt_snooze_delay(struct device *dev,
 				      struct device_attribute *attr,
 				      const char *buf,
 				      size_t count)
 {
-	struct cpu *cpu = container_of(dev, struct cpu, dev);
-	ssize_t ret;
-	long snooze;
-
-	ret = sscanf(buf, "%ld", &snooze);
-	if (ret != 1)
-		return -EINVAL;
-
-	per_cpu(smt_snooze_delay, cpu->dev.id) = snooze;
+	pr_warn_once("%s (%d) stored to unsupported smt_snooze_delay, which has no effect.\n",
+		     current->comm, current->pid);
 	return count;
 }
 
@@ -61,9 +59,9 @@
 				     struct device_attribute *attr,
 				     char *buf)
 {
-	struct cpu *cpu = container_of(dev, struct cpu, dev);
-
-	return sprintf(buf, "%ld\n", per_cpu(smt_snooze_delay, cpu->dev.id));
+	pr_warn_once("%s (%d) read from unsupported smt_snooze_delay\n",
+		     current->comm, current->pid);
+	return sprintf(buf, "100\n");
 }
 
 static DEVICE_ATTR(smt_snooze_delay, 0644, show_smt_snooze_delay,
@@ -71,16 +69,10 @@
 
 static int __init setup_smt_snooze_delay(char *str)
 {
-	unsigned int cpu;
-	long snooze;
-
 	if (!cpu_has_feature(CPU_FTR_SMT))
 		return 1;
 
-	snooze = simple_strtol(str, NULL, 10);
-	for_each_possible_cpu(cpu)
-		per_cpu(smt_snooze_delay, cpu) = snooze;
-
+	pr_warn("smt-snooze-delay command line option has no effect\n");
 	return 1;
 }
 __setup("smt-snooze-delay=", setup_smt_snooze_delay);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/systbl.S
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/systbl.S
@@ -25,6 +25,7 @@
 #include <asm/syscall_table_64.h>
 #undef __SYSCALL
 #else
+	.p2align	2
 #define __SYSCALL(nr, entry)	.long entry
 #include <asm/syscall_table_32.h>
 #undef __SYSCALL
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/tau_6xx.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/tau_6xx.c
@@ -13,13 +13,14 @@
  */
 
 #include <linux/errno.h>
-#include <linux/jiffies.h>
 #include <linux/kernel.h>
 #include <linux/param.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/workqueue.h>
 
 #include <asm/io.h>
 #include <asm/reg.h>
@@ -39,9 +40,7 @@
 	unsigned char grew;
 } tau[NR_CPUS];
 
-struct timer_list tau_timer;
-
-#undef DEBUG
+static bool tau_int_enable;
 
 /* TODO: put these in a /proc interface, with some sanity checks, and maybe
  * dynamic adjustment to minimize # of interrupts */
@@ -50,72 +49,49 @@
 #define step_size		2	/* step size when temp goes out of range */
 #define window_expand		1	/* expand the window by this much */
 /* configurable values for shrinking the window */
-#define shrink_timer	2*HZ	/* period between shrinking the window */
+#define shrink_timer	2000	/* period between shrinking the window */
 #define min_window	2	/* minimum window size, degrees C */
 
 static void set_thresholds(unsigned long cpu)
 {
-#ifdef CONFIG_TAU_INT
-	/*
-	 * setup THRM1,
-	 * threshold, valid bit, enable interrupts, interrupt when below threshold
-	 */
-	mtspr(SPRN_THRM1, THRM1_THRES(tau[cpu].low) | THRM1_V | THRM1_TIE | THRM1_TID);
+	u32 maybe_tie = tau_int_enable ? THRM1_TIE : 0;
 
-	/* setup THRM2,
-	 * threshold, valid bit, enable interrupts, interrupt when above threshold
-	 */
-	mtspr (SPRN_THRM2, THRM1_THRES(tau[cpu].high) | THRM1_V | THRM1_TIE);
-#else
-	/* same thing but don't enable interrupts */
-	mtspr(SPRN_THRM1, THRM1_THRES(tau[cpu].low) | THRM1_V | THRM1_TID);
-	mtspr(SPRN_THRM2, THRM1_THRES(tau[cpu].high) | THRM1_V);
-#endif
+	/* setup THRM1, threshold, valid bit, interrupt when below threshold */
+	mtspr(SPRN_THRM1, THRM1_THRES(tau[cpu].low) | THRM1_V | maybe_tie | THRM1_TID);
+
+	/* setup THRM2, threshold, valid bit, interrupt when above threshold */
+	mtspr(SPRN_THRM2, THRM1_THRES(tau[cpu].high) | THRM1_V | maybe_tie);
 }
 
 static void TAUupdate(int cpu)
 {
-	unsigned thrm;
-
-#ifdef DEBUG
-	printk("TAUupdate ");
-#endif
+	u32 thrm;
+	u32 bits = THRM1_TIV | THRM1_TIN | THRM1_V;
 
 	/* if both thresholds are crossed, the step_sizes cancel out
 	 * and the window winds up getting expanded twice. */
-	if((thrm = mfspr(SPRN_THRM1)) & THRM1_TIV){ /* is valid? */
-		if(thrm & THRM1_TIN){ /* crossed low threshold */
-			if (tau[cpu].low >= step_size){
-				tau[cpu].low -= step_size;
-				tau[cpu].high -= (step_size - window_expand);
-			}
-			tau[cpu].grew = 1;
-#ifdef DEBUG
-			printk("low threshold crossed ");
-#endif
+	thrm = mfspr(SPRN_THRM1);
+	if ((thrm & bits) == bits) {
+		mtspr(SPRN_THRM1, 0);
+
+		if (tau[cpu].low >= step_size) {
+			tau[cpu].low -= step_size;
+			tau[cpu].high -= (step_size - window_expand);
 		}
+		tau[cpu].grew = 1;
+		pr_debug("%s: low threshold crossed\n", __func__);
 	}
-	if((thrm = mfspr(SPRN_THRM2)) & THRM1_TIV){ /* is valid? */
-		if(thrm & THRM1_TIN){ /* crossed high threshold */
-			if (tau[cpu].high <= 127-step_size){
-				tau[cpu].low += (step_size - window_expand);
-				tau[cpu].high += step_size;
-			}
-			tau[cpu].grew = 1;
-#ifdef DEBUG
-			printk("high threshold crossed ");
-#endif
+	thrm = mfspr(SPRN_THRM2);
+	if ((thrm & bits) == bits) {
+		mtspr(SPRN_THRM2, 0);
+
+		if (tau[cpu].high <= 127 - step_size) {
+			tau[cpu].low += (step_size - window_expand);
+			tau[cpu].high += step_size;
 		}
+		tau[cpu].grew = 1;
+		pr_debug("%s: high threshold crossed\n", __func__);
 	}
-
-#ifdef DEBUG
-	printk("grew = %d\n", tau[cpu].grew);
-#endif
-
-#ifndef CONFIG_TAU_INT /* tau_timeout will do this if not using interrupts */
-	set_thresholds(cpu);
-#endif
-
 }
 
 #ifdef CONFIG_TAU_INT
@@ -140,17 +116,16 @@
 static void tau_timeout(void * info)
 {
 	int cpu;
-	unsigned long flags;
 	int size;
 	int shrink;
 
-	/* disabling interrupts *should* be okay */
-	local_irq_save(flags);
 	cpu = smp_processor_id();
 
-#ifndef CONFIG_TAU_INT
-	TAUupdate(cpu);
-#endif
+	if (!tau_int_enable)
+		TAUupdate(cpu);
+
+	/* Stop thermal sensor comparisons and interrupts */
+	mtspr(SPRN_THRM3, 0);
 
 	size = tau[cpu].high - tau[cpu].low;
 	if (size > min_window && ! tau[cpu].grew) {
@@ -173,32 +148,26 @@
 
 	set_thresholds(cpu);
 
-	/*
-	 * Do the enable every time, since otherwise a bunch of (relatively)
-	 * complex sleep code needs to be added. One mtspr every time
-	 * tau_timeout is called is probably not a big deal.
-	 *
-	 * Enable thermal sensor and set up sample interval timer
-	 * need 20 us to do the compare.. until a nice 'cpu_speed' function
-	 * call is implemented, just assume a 500 mhz clock. It doesn't really
-	 * matter if we take too long for a compare since it's all interrupt
-	 * driven anyway.
-	 *
-	 * use a extra long time.. (60 us @ 500 mhz)
+	/* Restart thermal sensor comparisons and interrupts.
+	 * The "PowerPC 740 and PowerPC 750 Microprocessor Datasheet"
+	 * recommends that "the maximum value be set in THRM3 under all
+	 * conditions."
 	 */
-	mtspr(SPRN_THRM3, THRM3_SITV(500*60) | THRM3_E);
-
-	local_irq_restore(flags);
+	mtspr(SPRN_THRM3, THRM3_SITV(0x1fff) | THRM3_E);
 }
 
-static void tau_timeout_smp(struct timer_list *unused)
-{
+static struct workqueue_struct *tau_workq;
 
-	/* schedule ourselves to be run again */
-	mod_timer(&tau_timer, jiffies + shrink_timer) ;
+static void tau_work_func(struct work_struct *work)
+{
+	msleep(shrink_timer);
 	on_each_cpu(tau_timeout, NULL, 0);
+	/* schedule ourselves to be run again */
+	queue_work(tau_workq, work);
 }
 
+DECLARE_WORK(tau_work, tau_work_func);
+
 /*
  * setup the TAU
  *
@@ -231,21 +200,19 @@
 		return 1;
 	}
 
+	tau_int_enable = IS_ENABLED(CONFIG_TAU_INT) &&
+			 !strcmp(cur_cpu_spec->platform, "ppc750");
 
-	/* first, set up the window shrinking timer */
-	timer_setup(&tau_timer, tau_timeout_smp, 0);
-	tau_timer.expires = jiffies + shrink_timer;
-	add_timer(&tau_timer);
+	tau_workq = alloc_workqueue("tau", WQ_UNBOUND, 1, 0);
+	if (!tau_workq)
+		return -ENOMEM;
 
 	on_each_cpu(TAU_init_smp, NULL, 0);
 
-	printk("Thermal assist unit ");
-#ifdef CONFIG_TAU_INT
-	printk("using interrupts, ");
-#else
-	printk("using timers, ");
-#endif
-	printk("shrink_timer: %d jiffies\n", shrink_timer);
+	queue_work(tau_workq, &tau_work);
+
+	pr_info("Thermal assist unit using %s, shrink_timer: %d ms\n",
+		tau_int_enable ? "interrupts" : "workqueue", shrink_timer);
 	tau_initialized = 1;
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/time.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/time.c
@@ -232,7 +232,7 @@
  * Accumulate stolen time by scanning the dispatch trace log.
  * Called on entry from user mode.
  */
-void accumulate_stolen_time(void)
+void notrace accumulate_stolen_time(void)
 {
 	u64 sst, ust;
 	unsigned long save_irq_soft_mask = irq_soft_mask_return();
@@ -522,35 +522,6 @@
 		"i" (offsetof(struct paca_struct, irq_work_pending)));
 }
 
-void arch_irq_work_raise(void)
-{
-	preempt_disable();
-	set_irq_work_pending_flag();
-	/*
-	 * Non-nmi code running with interrupts disabled will replay
-	 * irq_happened before it re-enables interrupts, so setthe
-	 * decrementer there instead of causing a hardware exception
-	 * which would immediately hit the masked interrupt handler
-	 * and have the net effect of setting the decrementer in
-	 * irq_happened.
-	 *
-	 * NMI interrupts can not check this when they return, so the
-	 * decrementer hardware exception is raised, which will fire
-	 * when interrupts are next enabled.
-	 *
-	 * BookE does not support this yet, it must audit all NMI
-	 * interrupt handlers to ensure they call nmi_enter() so this
-	 * check would be correct.
-	 */
-	if (IS_ENABLED(CONFIG_BOOKE) || !irqs_disabled() || in_nmi()) {
-		set_dec(1);
-	} else {
-		hard_irq_disable();
-		local_paca->irq_happened |= PACA_IRQ_DEC;
-	}
-	preempt_enable();
-}
-
 #else /* 32-bit */
 
 DEFINE_PER_CPU(u8, irq_work_pending);
@@ -559,16 +530,27 @@
 #define test_irq_work_pending()		__this_cpu_read(irq_work_pending)
 #define clear_irq_work_pending()	__this_cpu_write(irq_work_pending, 0)
 
+#endif /* 32 vs 64 bit */
+
 void arch_irq_work_raise(void)
 {
+	/*
+	 * 64-bit code that uses irq soft-mask can just cause an immediate
+	 * interrupt here that gets soft masked, if this is called under
+	 * local_irq_disable(). It might be possible to prevent that happening
+	 * by noticing interrupts are disabled and setting decrementer pending
+	 * to be replayed when irqs are enabled. The problem there is that
+	 * tracing can call irq_work_raise, including in code that does low
+	 * level manipulations of irq soft-mask state (e.g., trace_hardirqs_on)
+	 * which could get tangled up if we're messing with the same state
+	 * here.
+	 */
 	preempt_disable();
 	set_irq_work_pending_flag();
 	set_dec(1);
 	preempt_enable();
 }
 
-#endif /* 32 vs 64 bit */
-
 #else  /* CONFIG_IRQ_WORK */
 
 #define test_irq_work_pending()	0
@@ -959,6 +941,7 @@
 	vdso_data->wtom_clock_nsec = tk->wall_to_monotonic.tv_nsec;
 	vdso_data->stamp_xtime = xt;
 	vdso_data->stamp_sec_fraction = frac_sec;
+	vdso_data->hrtimer_res = hrtimer_resolution;
 	smp_wmb();
 	++(vdso_data->tb_update_count);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/trace/ftrace.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/trace/ftrace.c
@@ -328,9 +328,7 @@
 
 	/* Is this a known long jump tramp? */
 	for (i = 0; i < NUM_FTRACE_TRAMPS; i++)
-		if (!ftrace_tramps[i])
-			break;
-		else if (ftrace_tramps[i] == tramp)
+		if (ftrace_tramps[i] == tramp)
 			return 0;
 
 	/* Is this a known plt tramp? */
@@ -868,6 +866,17 @@
 
 extern unsigned int ftrace_tramp_text[], ftrace_tramp_init[];
 
+void ftrace_free_init_tramp(void)
+{
+	int i;
+
+	for (i = 0; i < NUM_FTRACE_TRAMPS && ftrace_tramps[i]; i++)
+		if (ftrace_tramps[i] == (unsigned long)ftrace_tramp_init) {
+			ftrace_tramps[i] = 0;
+			return;
+		}
+}
+
 int __init ftrace_dyn_arch_init(void)
 {
 	int i;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/trace/ftrace_64_mprofile.S
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/trace/ftrace_64_mprofile.S
@@ -36,6 +36,9 @@
 	/* Save the original return address in A's stack frame */
 	std	r0,LRSAVE(r1)
 
+	/* Create a minimal stack frame for representing B */
+	stdu	r1, -STACK_FRAME_MIN_SIZE(r1)
+
 	/* Create our stack frame + pt_regs */
 	stdu	r1,-SWITCH_FRAME_SIZE(r1)
 
@@ -52,7 +55,7 @@
 	SAVE_10GPRS(22, r1)
 
 	/* Save previous stack pointer (r1) */
-	addi	r8, r1, SWITCH_FRAME_SIZE
+	addi	r8, r1, SWITCH_FRAME_SIZE+STACK_FRAME_MIN_SIZE
 	std	r8, GPR1(r1)
 
 	/* Load special regs for save below */
@@ -65,6 +68,8 @@
 	mflr	r7
 	/* Save it as pt_regs->nip */
 	std     r7, _NIP(r1)
+	/* Also save it in B's stackframe header for proper unwind */
+	std	r7, LRSAVE+SWITCH_FRAME_SIZE(r1)
 	/* Save the read LR in pt_regs->link */
 	std     r0, _LINK(r1)
 
@@ -121,7 +126,7 @@
 	ld	r2, 24(r1)
 
 	/* Pop our stack frame */
-	addi r1, r1, SWITCH_FRAME_SIZE
+	addi r1, r1, SWITCH_FRAME_SIZE+STACK_FRAME_MIN_SIZE
 
 #ifdef CONFIG_LIVEPATCH
         /* Based on the cmpd above, if the NIP was altered handle livepatch */
@@ -145,7 +150,7 @@
 	mflr	r3
 	mtctr	r3
 	REST_GPR(3, r1)
-	addi	r1, r1, SWITCH_FRAME_SIZE
+	addi	r1, r1, SWITCH_FRAME_SIZE+STACK_FRAME_MIN_SIZE
 	mtlr	r0
 	bctr
 
@@ -153,6 +158,9 @@
 	/* Save the original return address in A's stack frame */
 	std	r0, LRSAVE(r1)
 
+	/* Create a minimal stack frame for representing B */
+	stdu	r1, -STACK_FRAME_MIN_SIZE(r1)
+
 	/* Create our stack frame + pt_regs */
 	stdu	r1, -SWITCH_FRAME_SIZE(r1)
 
@@ -166,6 +174,7 @@
 	/* Get the _mcount() call site out of LR */
 	mflr	r7
 	std     r7, _NIP(r1)
+	std	r7, LRSAVE+SWITCH_FRAME_SIZE(r1)
 
 	/* Save callee's TOC in the ABI compliant location */
 	std	r2, 24(r1)
@@ -200,7 +209,7 @@
 	ld	r2, 24(r1)
 
 	/* Pop our stack frame */
-	addi	r1, r1, SWITCH_FRAME_SIZE
+	addi	r1, r1, SWITCH_FRAME_SIZE+STACK_FRAME_MIN_SIZE
 
 	/* Reload original LR */
 	ld	r0, LRSAVE(r1)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/traps.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/traps.c
@@ -246,19 +246,26 @@
 
 	if (panic_on_oops)
 		panic("Fatal exception");
-	do_exit(signr);
+	make_task_dead(signr);
 }
 NOKPROBE_SYMBOL(oops_end);
 
+static char *get_mmu_str(void)
+{
+	if (early_radix_enabled())
+		return " MMU=Radix";
+	if (early_mmu_has_feature(MMU_FTR_HPTE_TABLE))
+		return " MMU=Hash";
+	return "";
+}
+
 static int __die(const char *str, struct pt_regs *regs, long err)
 {
 	printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter);
 
-	printk("%s PAGE_SIZE=%luK%s%s%s%s%s%s%s %s\n",
+	printk("%s PAGE_SIZE=%luK%s%s%s%s%s%s %s\n",
 	       IS_ENABLED(CONFIG_CPU_LITTLE_ENDIAN) ? "LE" : "BE",
-	       PAGE_SIZE / 1024,
-	       early_radix_enabled() ? " MMU=Radix" : "",
-	       early_mmu_has_feature(MMU_FTR_HPTE_TABLE) ? " MMU=Hash" : "",
+	       PAGE_SIZE / 1024, get_mmu_str(),
 	       IS_ENABLED(CONFIG_PREEMPT) ? " PREEMPT" : "",
 	       IS_ENABLED(CONFIG_SMP) ? " SMP" : "",
 	       IS_ENABLED(CONFIG_SMP) ? (" NR_CPUS=" __stringify(NR_CPUS)) : "",
@@ -503,11 +510,14 @@
 #ifdef CONFIG_PPC_BOOK3S_64
 	BUG_ON(get_paca()->in_nmi == 0);
 	if (get_paca()->in_nmi > 1)
-		nmi_panic(regs, "Unrecoverable nested System Reset");
+		die("Unrecoverable nested System Reset", regs, SIGABRT);
 #endif
 	/* Must die if the interrupt is not recoverable */
-	if (!(regs->msr & MSR_RI))
-		nmi_panic(regs, "Unrecoverable System Reset");
+	if (!(regs->msr & MSR_RI)) {
+		/* For the reason explained in die_mce, nmi_exit before die */
+		nmi_exit();
+		die("Unrecoverable System Reset", regs, SIGABRT);
+	}
 
 	if (saved_hsrrs) {
 		mtspr(SPRN_HSRR0, hsrr0);
@@ -851,7 +861,7 @@
 
 	/* Must die if the interrupt is not recoverable */
 	if (!(regs->msr & MSR_RI))
-		nmi_panic(regs, "Unrecoverable Machine check");
+		die("Unrecoverable Machine check", regs, SIGBUS);
 
 	return;
 
@@ -870,7 +880,7 @@
 {
 	unsigned int ra, rb, t, i, sel, instr, rc;
 	const void __user *addr;
-	u8 vbuf[16], *vdst;
+	u8 vbuf[16] __aligned(16), *vdst;
 	unsigned long ea, msr, msr_mask;
 	bool swap;
 
@@ -1414,10 +1424,12 @@
 	return -EINVAL;
 }
 
+#ifdef CONFIG_GENERIC_BUG
 int is_valid_bugaddr(unsigned long addr)
 {
 	return is_kernel_addr(addr);
 }
+#endif
 
 #ifdef CONFIG_MATH_EMULATION
 static int emulate_math(struct pt_regs *regs)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/vdso.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/vdso.c
@@ -682,7 +682,7 @@
 	node = cpu_to_node(cpu);
 	WARN_ON_ONCE(node > 0xffff);
 
-	val = (cpu & 0xfff) | ((node & 0xffff) << 16);
+	val = (cpu & 0xffff) | ((node & 0xffff) << 16);
 	mtspr(SPRN_SPRG_VDSO_WRITE, val);
 	get_paca()->sprg_vdso = val;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/vdso32/gettimeofday.S
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/vdso32/gettimeofday.S
@@ -156,12 +156,15 @@
 	cror	cr0*4+eq,cr0*4+eq,cr1*4+eq
 	bne	cr0,99f
 
+	mflr	r12
+  .cfi_register lr,r12
+	bl	__get_datapage@local	/* get data page */
+	lwz	r5, CLOCK_HRTIMER_RES(r3)
+	mtlr	r12
 	li	r3,0
 	cmpli	cr0,r4,0
 	crclr	cr0*4+so
 	beqlr
-	lis	r5,CLOCK_REALTIME_RES@h
-	ori	r5,r5,CLOCK_REALTIME_RES@l
 	stw	r3,TSPC32_TV_SEC(r4)
 	stw	r5,TSPC32_TV_NSEC(r4)
 	blr
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/vdso64/cacheflush.S
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/vdso64/cacheflush.S
@@ -35,7 +35,7 @@
 	subf	r8,r6,r4		/* compute length */
 	add	r8,r8,r5		/* ensure we get enough */
 	lwz	r9,CFG_DCACHE_LOGBLOCKSZ(r10)
-	srw.	r8,r8,r9		/* compute line count */
+	srd.	r8,r8,r9		/* compute line count */
 	crclr	cr0*4+so
 	beqlr				/* nothing to do? */
 	mtctr	r8
@@ -52,7 +52,7 @@
 	subf	r8,r6,r4		/* compute length */
 	add	r8,r8,r5
 	lwz	r9,CFG_ICACHE_LOGBLOCKSZ(r10)
-	srw.	r8,r8,r9		/* compute line count */
+	srd.	r8,r8,r9		/* compute line count */
 	crclr	cr0*4+so
 	beqlr				/* nothing to do? */
 	mtctr	r8
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/vdso64/gettimeofday.S
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/vdso64/gettimeofday.S
@@ -186,12 +186,15 @@
 	cror	cr0*4+eq,cr0*4+eq,cr1*4+eq
 	bne	cr0,99f
 
+	mflr	r12
+  .cfi_register lr,r12
+	bl	V_LOCAL_FUNC(__get_datapage)
+	lwz	r5, CLOCK_HRTIMER_RES(r3)
+	mtlr	r12
 	li	r3,0
 	cmpldi	cr0,r4,0
 	crclr	cr0*4+so
 	beqlr
-	lis	r5,CLOCK_REALTIME_RES@h
-	ori	r5,r5,CLOCK_REALTIME_RES@l
 	std	r3,TSPC64_TV_SEC(r4)
 	std	r5,TSPC64_TV_NSEC(r4)
 	blr
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/vector.S
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/vector.S
@@ -32,6 +32,7 @@
 	mfvscr	v0
 	li	r4, VRSTATE_VSCR
 	stvx	v0, r4, r3
+	lvx	v0, 0, r3
 	blr
 EXPORT_SYMBOL(store_vr_state)
 
@@ -102,6 +103,7 @@
 	mfvscr	v0
 	li	r4,VRSTATE_VSCR
 	stvx	v0,r4,r7
+	lvx	v0,0,r7
 	blr
 
 #ifdef CONFIG_VSX
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/vmlinux.lds.S
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/vmlinux.lds.S
@@ -6,6 +6,7 @@
 #endif
 
 #define BSS_FIRST_SECTIONS *(.bss.prominit)
+#define RUNTIME_DISCARD_EXIT
 
 #include <asm/page.h>
 #include <asm-generic/vmlinux.lds.h>
@@ -98,10 +99,11 @@
 		ALIGN_FUNCTION();
 #endif
 		/* careful! __ftr_alt_* sections need to be close to .text */
-		*(.text.hot TEXT_MAIN .text.fixup .text.unlikely .fixup __ftr_alt_* .ref.text);
+		*(.text.hot .text.hot.* TEXT_MAIN .text.fixup .text.unlikely .text.unlikely.* .fixup __ftr_alt_* .ref.text);
 #ifdef CONFIG_PPC64
 		*(.tramp.ftrace.text);
 #endif
+		NOINSTR_TEXT
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
@@ -144,6 +146,20 @@
 	}
 
 	. = ALIGN(8);
+	__uaccess_flush_fixup : AT(ADDR(__uaccess_flush_fixup) - LOAD_OFFSET) {
+		__start___uaccess_flush_fixup = .;
+		*(__uaccess_flush_fixup)
+		__stop___uaccess_flush_fixup = .;
+	}
+
+	. = ALIGN(8);
+	__entry_flush_fixup : AT(ADDR(__entry_flush_fixup) - LOAD_OFFSET) {
+		__start___entry_flush_fixup = .;
+		*(__entry_flush_fixup)
+		__stop___entry_flush_fixup = .;
+	}
+
+	. = ALIGN(8);
 	__stf_exit_barrier_fixup : AT(ADDR(__stf_exit_barrier_fixup) - LOAD_OFFSET) {
 		__start___stf_exit_barrier_fixup = .;
 		*(__stf_exit_barrier_fixup)
@@ -196,6 +212,12 @@
 	.init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
 		_sinittext = .;
 		INIT_TEXT
+
+		/*
+		 *.init.text might be RO so we must ensure this section ends on
+		 * a page boundary.
+		 */
+		. = ALIGN(PAGE_SIZE);
 		_einittext = .;
 #ifdef CONFIG_PPC64
 		*(.tramp.ftrace.init);
@@ -209,21 +231,9 @@
 		EXIT_TEXT
 	}
 
-	.init.data : AT(ADDR(.init.data) - LOAD_OFFSET) {
-		INIT_DATA
-	}
-
-	.init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) {
-		INIT_SETUP(16)
-	}
-
-	.initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) {
-		INIT_CALLS
-	}
+	. = ALIGN(PAGE_SIZE);
 
-	.con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) {
-		CON_INITCALL
-	}
+	INIT_DATA_SECTION(16)
 
 	. = ALIGN(8);
 	__ftr_fixup : AT(ADDR(__ftr_fixup) - LOAD_OFFSET) {
@@ -251,9 +261,6 @@
 		__stop___fw_ftr_fixup = .;
 	}
 #endif
-	.init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) {
-		INIT_RAM_FS
-	}
 
 	PERCPU_SECTION(L1_CACHE_BYTES)
 
@@ -388,9 +395,12 @@
 	DISCARDS
 	/DISCARD/ : {
 		*(*.EMB.apuinfo)
-		*(.glink .iplt .plt .rela* .comment)
+		*(.glink .iplt .plt .comment)
 		*(.gnu.version*)
 		*(.gnu.attributes)
 		*(.eh_frame)
+#ifndef CONFIG_RELOCATABLE
+		*(.rela*)
+#endif
 	}
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kernel/watchdog.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kernel/watchdog.c
@@ -132,6 +132,10 @@
 {
 	cpumask_or(&wd_smp_cpus_stuck, &wd_smp_cpus_stuck, cpumask);
 	cpumask_andnot(&wd_smp_cpus_pending, &wd_smp_cpus_pending, cpumask);
+	/*
+	 * See wd_smp_clear_cpu_pending()
+	 */
+	smp_mb();
 	if (cpumask_empty(&wd_smp_cpus_pending)) {
 		wd_smp_last_reset_tb = tb;
 		cpumask_andnot(&wd_smp_cpus_pending,
@@ -217,13 +221,44 @@
 
 			cpumask_clear_cpu(cpu, &wd_smp_cpus_stuck);
 			wd_smp_unlock(&flags);
+		} else {
+			/*
+			 * The last CPU to clear pending should have reset the
+			 * watchdog so we generally should not find it empty
+			 * here if our CPU was clear. However it could happen
+			 * due to a rare race with another CPU taking the
+			 * last CPU out of the mask concurrently.
+			 *
+			 * We can't add a warning for it. But just in case
+			 * there is a problem with the watchdog that is causing
+			 * the mask to not be reset, try to kick it along here.
+			 */
+			if (unlikely(cpumask_empty(&wd_smp_cpus_pending)))
+				goto none_pending;
 		}
 		return;
 	}
+
 	cpumask_clear_cpu(cpu, &wd_smp_cpus_pending);
+
+	/*
+	 * Order the store to clear pending with the load(s) to check all
+	 * words in the pending mask to check they are all empty. This orders
+	 * with the same barrier on another CPU. This prevents two CPUs
+	 * clearing the last 2 pending bits, but neither seeing the other's
+	 * store when checking if the mask is empty, and missing an empty
+	 * mask, which ends with a false positive.
+	 */
+	smp_mb();
 	if (cpumask_empty(&wd_smp_cpus_pending)) {
 		unsigned long flags;
 
+none_pending:
+		/*
+		 * Double check under lock because more than one CPU could see
+		 * a clear mask with the lockless check after clearing their
+		 * pending bits.
+		 */
 		wd_smp_lock(&flags);
 		if (cpumask_empty(&wd_smp_cpus_pending)) {
 			wd_smp_last_reset_tb = tb;
@@ -314,8 +349,12 @@
 {
 	unsigned long ticks = tb_ticks_per_usec * wd_timer_period_ms * 1000;
 	int cpu = smp_processor_id();
-	u64 tb = get_tb();
+	u64 tb;
 
+	if (!cpumask_test_cpu(cpu, &watchdog_cpumask))
+		return;
+
+	tb = get_tb();
 	if (tb - per_cpu(wd_timer_tb, cpu) >= ticks) {
 		per_cpu(wd_timer_tb, cpu) = tb;
 		wd_smp_clear_cpu_pending(cpu, tb);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kvm/book3s.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kvm/book3s.c
@@ -867,7 +867,8 @@
 	kvm->arch.kvm_ops->commit_memory_region(kvm, mem, old, new, change);
 }
 
-int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end)
+int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end,
+			unsigned flags)
 {
 	return kvm->arch.kvm_ops->unmap_hva_range(kvm, start, end);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kvm/book3s_64_mmu_radix.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kvm/book3s_64_mmu_radix.c
@@ -31,14 +31,15 @@
 					      gva_t eaddr, void *to, void *from,
 					      unsigned long n)
 {
-	int uninitialized_var(old_pid), old_lpid;
+	int old_pid, old_lpid;
 	unsigned long quadrant, ret = n;
 	bool is_load = !!to;
 
 	/* Can't access quadrants 1 or 2 in non-HV mode, call the HV to do it */
 	if (kvmhv_on_pseries())
 		return plpar_hcall_norets(H_COPY_TOFROM_GUEST, lpid, pid, eaddr,
-					  __pa(to), __pa(from), n);
+					  (to != NULL) ? __pa(to): 0,
+					  (from != NULL) ? __pa(from): 0, n);
 
 	quadrant = 1;
 	if (!pid)
@@ -353,7 +354,13 @@
 
 static pte_t *kvmppc_pte_alloc(void)
 {
-	return kmem_cache_alloc(kvm_pte_cache, GFP_KERNEL);
+	pte_t *pte;
+
+	pte = kmem_cache_alloc(kvm_pte_cache, GFP_KERNEL);
+	/* pmd_populate() will only reference _pa(pte). */
+	kmemleak_ignore(pte);
+
+	return pte;
 }
 
 static void kvmppc_pte_free(pte_t *ptep)
@@ -363,7 +370,13 @@
 
 static pmd_t *kvmppc_pmd_alloc(void)
 {
-	return kmem_cache_alloc(kvm_pmd_cache, GFP_KERNEL);
+	pmd_t *pmd;
+
+	pmd = kmem_cache_alloc(kvm_pmd_cache, GFP_KERNEL);
+	/* pud_populate() will only reference _pa(pmd). */
+	kmemleak_ignore(pmd);
+
+	return pmd;
 }
 
 static void kvmppc_pmd_free(pmd_t *pmdp)
@@ -1091,6 +1104,11 @@
 					 kvm->arch.lpid);
 		gpa += PAGE_SIZE;
 	}
+	/*
+	 * Increase the mmu notifier sequence number to prevent any page
+	 * fault that read the memslot earlier from writing a PTE.
+	 */
+	kvm->mmu_notifier_seq++;
 	spin_unlock(&kvm->mmu_lock);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kvm/book3s_64_vio.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kvm/book3s_64_vio.c
@@ -74,6 +74,7 @@
 	struct kvmppc_spapr_tce_iommu_table *stit, *tmp;
 	struct iommu_table_group *table_group = NULL;
 
+	rcu_read_lock();
 	list_for_each_entry_rcu(stt, &kvm->arch.spapr_tce_tables, list) {
 
 		table_group = iommu_group_get_iommudata(grp);
@@ -88,7 +89,9 @@
 				kref_put(&stit->kref, kvm_spapr_tce_liobn_put);
 			}
 		}
+		cond_resched_rcu();
 	}
+	rcu_read_unlock();
 }
 
 extern long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd,
@@ -106,21 +109,25 @@
 	if (!f.file)
 		return -EBADF;
 
+	rcu_read_lock();
 	list_for_each_entry_rcu(stt, &kvm->arch.spapr_tce_tables, list) {
 		if (stt == f.file->private_data) {
 			found = true;
 			break;
 		}
 	}
+	rcu_read_unlock();
 
-	fdput(f);
-
-	if (!found)
+	if (!found) {
+		fdput(f);
 		return -EINVAL;
+	}
 
 	table_group = iommu_group_get_iommudata(grp);
-	if (WARN_ON(!table_group))
+	if (WARN_ON(!table_group)) {
+		fdput(f);
 		return -EFAULT;
+	}
 
 	for (i = 0; i < IOMMU_TABLE_GROUP_MAX_TABLES; ++i) {
 		struct iommu_table *tbltmp = table_group->tables[i];
@@ -141,9 +148,12 @@
 			break;
 		}
 	}
-	if (!tbl)
+	if (!tbl) {
+		fdput(f);
 		return -EINVAL;
+	}
 
+	rcu_read_lock();
 	list_for_each_entry_rcu(stit, &stt->iommu_tables, next) {
 		if (tbl != stit->tbl)
 			continue;
@@ -151,18 +161,24 @@
 		if (!kref_get_unless_zero(&stit->kref)) {
 			/* stit is being destroyed */
 			iommu_tce_table_put(tbl);
+			rcu_read_unlock();
+			fdput(f);
 			return -ENOTTY;
 		}
 		/*
 		 * The table is already known to this KVM, we just increased
 		 * its KVM reference counter and can return.
 		 */
+		rcu_read_unlock();
+		fdput(f);
 		return 0;
 	}
+	rcu_read_unlock();
 
 	stit = kzalloc(sizeof(*stit), GFP_KERNEL);
 	if (!stit) {
 		iommu_tce_table_put(tbl);
+		fdput(f);
 		return -ENOMEM;
 	}
 
@@ -171,6 +187,7 @@
 
 	list_add_rcu(&stit->next, &stt->iommu_tables);
 
+	fdput(f);
 	return 0;
 }
 
@@ -364,18 +381,19 @@
 	if (kvmppc_tce_to_ua(stt->kvm, tce, &ua))
 		return H_TOO_HARD;
 
+	rcu_read_lock();
 	list_for_each_entry_rcu(stit, &stt->iommu_tables, next) {
 		unsigned long hpa = 0;
 		struct mm_iommu_table_group_mem_t *mem;
 		long shift = stit->tbl->it_page_shift;
 
 		mem = mm_iommu_lookup(stt->kvm->mm, ua, 1ULL << shift);
-		if (!mem)
-			return H_TOO_HARD;
-
-		if (mm_iommu_ua_to_hpa(mem, ua, shift, &hpa))
+		if (!mem || mm_iommu_ua_to_hpa(mem, ua, shift, &hpa)) {
+			rcu_read_unlock();
 			return H_TOO_HARD;
+		}
 	}
+	rcu_read_unlock();
 
 	return H_SUCCESS;
 }
@@ -410,13 +428,19 @@
 	tbl[idx % TCES_PER_PAGE] = tce;
 }
 
-static void kvmppc_clear_tce(struct mm_struct *mm, struct iommu_table *tbl,
-		unsigned long entry)
+static void kvmppc_clear_tce(struct mm_struct *mm, struct kvmppc_spapr_tce_table *stt,
+		struct iommu_table *tbl, unsigned long entry)
 {
-	unsigned long hpa = 0;
-	enum dma_data_direction dir = DMA_NONE;
+	unsigned long i;
+	unsigned long subpages = 1ULL << (stt->page_shift - tbl->it_page_shift);
+	unsigned long io_entry = entry << (stt->page_shift - tbl->it_page_shift);
+
+	for (i = 0; i < subpages; ++i) {
+		unsigned long hpa = 0;
+		enum dma_data_direction dir = DMA_NONE;
 
-	iommu_tce_xchg_no_kill(mm, tbl, entry, &hpa, &dir);
+		iommu_tce_xchg_no_kill(mm, tbl, io_entry + i, &hpa, &dir);
+	}
 }
 
 static long kvmppc_tce_iommu_mapped_dec(struct kvm *kvm,
@@ -475,6 +499,8 @@
 			break;
 	}
 
+	iommu_tce_kill(tbl, io_entry, subpages);
+
 	return ret;
 }
 
@@ -534,6 +560,8 @@
 			break;
 	}
 
+	iommu_tce_kill(tbl, io_entry, subpages);
+
 	return ret;
 }
 
@@ -580,10 +608,9 @@
 			ret = kvmppc_tce_iommu_map(vcpu->kvm, stt, stit->tbl,
 					entry, ua, dir);
 
-		iommu_tce_kill(stit->tbl, entry, 1);
 
 		if (ret != H_SUCCESS) {
-			kvmppc_clear_tce(vcpu->kvm->mm, stit->tbl, entry);
+			kvmppc_clear_tce(vcpu->kvm->mm, stt, stit->tbl, entry);
 			goto unlock_exit;
 		}
 	}
@@ -659,13 +686,13 @@
 		 */
 		if (get_user(tce, tces + i)) {
 			ret = H_TOO_HARD;
-			goto invalidate_exit;
+			goto unlock_exit;
 		}
 		tce = be64_to_cpu(tce);
 
 		if (kvmppc_tce_to_ua(vcpu->kvm, tce, &ua)) {
 			ret = H_PARAMETER;
-			goto invalidate_exit;
+			goto unlock_exit;
 		}
 
 		list_for_each_entry_lockless(stit, &stt->iommu_tables, next) {
@@ -674,19 +701,15 @@
 					iommu_tce_direction(tce));
 
 			if (ret != H_SUCCESS) {
-				kvmppc_clear_tce(vcpu->kvm->mm, stit->tbl,
-						entry);
-				goto invalidate_exit;
+				kvmppc_clear_tce(vcpu->kvm->mm, stt, stit->tbl,
+						 entry + i);
+				goto unlock_exit;
 			}
 		}
 
 		kvmppc_tce_put(stt, entry + i, tce);
 	}
 
-invalidate_exit:
-	list_for_each_entry_lockless(stit, &stt->iommu_tables, next)
-		iommu_tce_kill(stit->tbl, entry, npages);
-
 unlock_exit:
 	srcu_read_unlock(&vcpu->kvm->srcu, idx);
 
@@ -725,20 +748,16 @@
 				continue;
 
 			if (ret == H_TOO_HARD)
-				goto invalidate_exit;
+				return ret;
 
 			WARN_ON_ONCE(1);
-			kvmppc_clear_tce(vcpu->kvm->mm, stit->tbl, entry);
+			kvmppc_clear_tce(vcpu->kvm->mm, stt, stit->tbl, entry + i);
 		}
 	}
 
 	for (i = 0; i < npages; ++i, ioba += (1ULL << stt->page_shift))
 		kvmppc_tce_put(stt, ioba >> stt->page_shift, tce_value);
 
-invalidate_exit:
-	list_for_each_entry_lockless(stit, &stt->iommu_tables, next)
-		iommu_tce_kill(stit->tbl, ioba >> stt->page_shift, npages);
-
 	return ret;
 }
 EXPORT_SYMBOL_GPL(kvmppc_h_stuff_tce);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kvm/book3s_64_vio_hv.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kvm/book3s_64_vio_hv.c
@@ -177,10 +177,13 @@
 	idx -= stt->offset;
 	page = stt->pages[idx / TCES_PER_PAGE];
 	/*
-	 * page must not be NULL in real mode,
-	 * kvmppc_rm_ioba_validate() must have taken care of this.
+	 * kvmppc_rm_ioba_validate() allows pages not be allocated if TCE is
+	 * being cleared, otherwise it returns H_TOO_HARD and we skip this.
 	 */
-	WARN_ON_ONCE_RM(!page);
+	if (!page) {
+		WARN_ON_ONCE_RM(tce != 0);
+		return;
+	}
 	tbl = kvmppc_page_address(page);
 
 	tbl[idx % TCES_PER_PAGE] = tce;
@@ -248,13 +251,19 @@
 		tbl->it_ops->tce_kill(tbl, entry, pages, true);
 }
 
-static void kvmppc_rm_clear_tce(struct kvm *kvm, struct iommu_table *tbl,
-		unsigned long entry)
+static void kvmppc_rm_clear_tce(struct kvm *kvm, struct kvmppc_spapr_tce_table *stt,
+		struct iommu_table *tbl, unsigned long entry)
 {
-	unsigned long hpa = 0;
-	enum dma_data_direction dir = DMA_NONE;
+	unsigned long i;
+	unsigned long subpages = 1ULL << (stt->page_shift - tbl->it_page_shift);
+	unsigned long io_entry = entry << (stt->page_shift - tbl->it_page_shift);
+
+	for (i = 0; i < subpages; ++i) {
+		unsigned long hpa = 0;
+		enum dma_data_direction dir = DMA_NONE;
 
-	iommu_tce_xchg_no_kill_rm(kvm->mm, tbl, entry, &hpa, &dir);
+		iommu_tce_xchg_no_kill_rm(kvm->mm, tbl, io_entry + i, &hpa, &dir);
+	}
 }
 
 static long kvmppc_rm_tce_iommu_mapped_dec(struct kvm *kvm,
@@ -317,6 +326,8 @@
 			break;
 	}
 
+	iommu_tce_kill_rm(tbl, io_entry, subpages);
+
 	return ret;
 }
 
@@ -380,6 +391,8 @@
 			break;
 	}
 
+	iommu_tce_kill_rm(tbl, io_entry, subpages);
+
 	return ret;
 }
 
@@ -425,10 +438,8 @@
 			ret = kvmppc_rm_tce_iommu_map(vcpu->kvm, stt,
 					stit->tbl, entry, ua, dir);
 
-		iommu_tce_kill_rm(stit->tbl, entry, 1);
-
 		if (ret != H_SUCCESS) {
-			kvmppc_rm_clear_tce(vcpu->kvm, stit->tbl, entry);
+			kvmppc_rm_clear_tce(vcpu->kvm, stt, stit->tbl, entry);
 			return ret;
 		}
 	}
@@ -568,7 +579,7 @@
 		ua = 0;
 		if (kvmppc_rm_tce_to_ua(vcpu->kvm, tce, &ua, NULL)) {
 			ret = H_PARAMETER;
-			goto invalidate_exit;
+			goto unlock_exit;
 		}
 
 		list_for_each_entry_lockless(stit, &stt->iommu_tables, next) {
@@ -577,19 +588,15 @@
 					iommu_tce_direction(tce));
 
 			if (ret != H_SUCCESS) {
-				kvmppc_rm_clear_tce(vcpu->kvm, stit->tbl,
-						entry);
-				goto invalidate_exit;
+				kvmppc_rm_clear_tce(vcpu->kvm, stt, stit->tbl,
+						entry + i);
+				goto unlock_exit;
 			}
 		}
 
 		kvmppc_rm_tce_put(stt, entry + i, tce);
 	}
 
-invalidate_exit:
-	list_for_each_entry_lockless(stit, &stt->iommu_tables, next)
-		iommu_tce_kill_rm(stit->tbl, entry, npages);
-
 unlock_exit:
 	if (rmap)
 		unlock_rmap(rmap);
@@ -632,20 +639,16 @@
 				continue;
 
 			if (ret == H_TOO_HARD)
-				goto invalidate_exit;
+				return ret;
 
 			WARN_ON_ONCE_RM(1);
-			kvmppc_rm_clear_tce(vcpu->kvm, stit->tbl, entry);
+			kvmppc_rm_clear_tce(vcpu->kvm, stt, stit->tbl, entry + i);
 		}
 	}
 
 	for (i = 0; i < npages; ++i, ioba += (1ULL << stt->page_shift))
 		kvmppc_rm_tce_put(stt, ioba >> stt->page_shift, tce_value);
 
-invalidate_exit:
-	list_for_each_entry_lockless(stit, &stt->iommu_tables, next)
-		iommu_tce_kill_rm(stit->tbl, ioba >> stt->page_shift, npages);
-
 	return ret;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kvm/book3s_hv.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kvm/book3s_hv.c
@@ -58,6 +58,7 @@
 #include <asm/kvm_book3s.h>
 #include <asm/mmu_context.h>
 #include <asm/lppaca.h>
+#include <asm/pmc.h>
 #include <asm/processor.h>
 #include <asm/cputhreads.h>
 #include <asm/page.h>
@@ -2306,8 +2307,10 @@
 		HFSCR_DSCR | HFSCR_VECVSX | HFSCR_FP;
 	if (cpu_has_feature(CPU_FTR_HVMODE)) {
 		vcpu->arch.hfscr &= mfspr(SPRN_HFSCR);
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
 		if (cpu_has_feature(CPU_FTR_P9_TM_HV_ASSIST))
 			vcpu->arch.hfscr |= HFSCR_TM;
+#endif
 	}
 	if (cpu_has_feature(CPU_FTR_TM_COMP))
 		vcpu->arch.hfscr |= HFSCR_TM;
@@ -2354,7 +2357,7 @@
 	mutex_unlock(&kvm->lock);
 
 	if (!vcore)
-		goto free_vcpu;
+		goto uninit_vcpu;
 
 	spin_lock(&vcore->lock);
 	++vcore->num_threads;
@@ -2371,6 +2374,8 @@
 
 	return vcpu;
 
+uninit_vcpu:
+	kvm_vcpu_uninit(vcpu);
 free_vcpu:
 	kmem_cache_free(kvm_vcpu_cache, vcpu);
 out:
@@ -2534,7 +2539,7 @@
 	cpumask_t *cpu_in_guest;
 	int i;
 
-	cpu = cpu_first_thread_sibling(cpu);
+	cpu = cpu_first_tlb_thread_sibling(cpu);
 	if (nested) {
 		cpumask_set_cpu(cpu, &nested->need_tlb_flush);
 		cpu_in_guest = &nested->cpu_in_guest;
@@ -2548,9 +2553,10 @@
 	 * the other side is the first smp_mb() in kvmppc_run_core().
 	 */
 	smp_mb();
-	for (i = 0; i < threads_per_core; ++i)
-		if (cpumask_test_cpu(cpu + i, cpu_in_guest))
-			smp_call_function_single(cpu + i, do_nothing, NULL, 1);
+	for (i = cpu; i <= cpu_last_tlb_thread_sibling(cpu);
+					i += cpu_tlb_thread_sibling_step())
+		if (cpumask_test_cpu(i, cpu_in_guest))
+			smp_call_function_single(i, do_nothing, NULL, 1);
 }
 
 static void kvmppc_prepare_radix_vcpu(struct kvm_vcpu *vcpu, int pcpu)
@@ -2581,8 +2587,8 @@
 	 */
 	if (prev_cpu != pcpu) {
 		if (prev_cpu >= 0 &&
-		    cpu_first_thread_sibling(prev_cpu) !=
-		    cpu_first_thread_sibling(pcpu))
+		    cpu_first_tlb_thread_sibling(prev_cpu) !=
+		    cpu_first_tlb_thread_sibling(pcpu))
 			radix_flush_cpu(kvm, prev_cpu, vcpu);
 		if (nested)
 			nested->prev_cpu[vcpu->arch.nested_vcpu_id] = pcpu;
@@ -3554,6 +3560,18 @@
 	    cpu_has_feature(CPU_FTR_P9_TM_HV_ASSIST))
 		kvmppc_restore_tm_hv(vcpu, vcpu->arch.shregs.msr, true);
 
+#ifdef CONFIG_PPC_PSERIES
+	if (kvmhv_on_pseries()) {
+		barrier();
+		if (vcpu->arch.vpa.pinned_addr) {
+			struct lppaca *lp = vcpu->arch.vpa.pinned_addr;
+			get_lppaca()->pmcregs_in_use = lp->pmcregs_in_use;
+		} else {
+			get_lppaca()->pmcregs_in_use = 1;
+		}
+		barrier();
+	}
+#endif
 	kvmhv_load_guest_pmu(vcpu);
 
 	msr_check_and_set(MSR_FP | MSR_VEC | MSR_VSX);
@@ -3621,6 +3639,7 @@
 		if (trap == BOOK3S_INTERRUPT_SYSCALL && !vcpu->arch.nested &&
 		    kvmppc_get_gpr(vcpu, 3) == H_CEDE) {
 			kvmppc_nested_cede(vcpu);
+			kvmppc_set_gpr(vcpu, 3, 0);
 			trap = 0;
 		}
 	} else {
@@ -3635,7 +3654,10 @@
 	vcpu->arch.dec_expires = dec + tb;
 	vcpu->cpu = -1;
 	vcpu->arch.thread_cpu = -1;
+	/* Save guest CTRL register, set runlatch to 1 */
 	vcpu->arch.ctrl = mfspr(SPRN_CTRLF);
+	if (!(vcpu->arch.ctrl & 1))
+		mtspr(SPRN_CTRLT, vcpu->arch.ctrl | 1);
 
 	vcpu->arch.iamr = mfspr(SPRN_IAMR);
 	vcpu->arch.pspb = mfspr(SPRN_PSPB);
@@ -3684,6 +3706,13 @@
 	save_pmu |= nesting_enabled(vcpu->kvm);
 
 	kvmhv_save_guest_pmu(vcpu, save_pmu);
+#ifdef CONFIG_PPC_PSERIES
+	if (kvmhv_on_pseries()) {
+		barrier();
+		get_lppaca()->pmcregs_in_use = ppc_get_pmu_inuse();
+		barrier();
+	}
+#endif
 
 	vc->entry_exit_map = 0x101;
 	vc->in_guest = 0;
@@ -5188,6 +5217,12 @@
 	case KVM_PPC_ALLOCATE_HTAB: {
 		u32 htab_order;
 
+		/* If we're a nested hypervisor, we currently only support radix */
+		if (kvmhv_on_pseries()) {
+			r = -EOPNOTSUPP;
+			break;
+		}
+
 		r = -EFAULT;
 		if (get_user(htab_order, (u32 __user *)argp))
 			break;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kvm/book3s_hv_builtin.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kvm/book3s_hv_builtin.c
@@ -821,6 +821,7 @@
 				       "r" (0) : "memory");
 		}
 		asm volatile("ptesync": : :"memory");
+		// POWER9 congruence-class TLBIEL leaves ERAT. Flush it now.
 		asm volatile(PPC_RADIX_INVALIDATE_ERAT_GUEST : : :"memory");
 	} else {
 		for (set = 0; set < kvm->arch.tlb_sets; ++set) {
@@ -831,7 +832,9 @@
 			rb += PPC_BIT(51);	/* increment set number */
 		}
 		asm volatile("ptesync": : :"memory");
-		asm volatile(PPC_ISA_3_0_INVALIDATE_ERAT : : :"memory");
+		// POWER9 congruence-class TLBIEL leaves ERAT. Flush it now.
+		if (cpu_has_feature(CPU_FTR_ARCH_300))
+			asm volatile(PPC_ISA_3_0_INVALIDATE_ERAT : : :"memory");
 	}
 }
 
@@ -847,7 +850,7 @@
 	 * Thus we make all 4 threads use the same bit.
 	 */
 	if (cpu_has_feature(CPU_FTR_ARCH_300))
-		pcpu = cpu_first_thread_sibling(pcpu);
+		pcpu = cpu_first_tlb_thread_sibling(pcpu);
 
 	if (nested)
 		need_tlb_flush = &nested->need_tlb_flush;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kvm/book3s_hv_nested.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kvm/book3s_hv_nested.c
@@ -51,7 +51,8 @@
 	hr->ppr = vcpu->arch.ppr;
 }
 
-static void byteswap_pt_regs(struct pt_regs *regs)
+/* Use noinline_for_stack due to https://bugs.llvm.org/show_bug.cgi?id=49610 */
+static noinline_for_stack void byteswap_pt_regs(struct pt_regs *regs)
 {
 	unsigned long *addr = (unsigned long *) regs;
 
@@ -231,6 +232,9 @@
 	if (vcpu->kvm->arch.l1_ptcr == 0)
 		return H_NOT_AVAILABLE;
 
+	if (MSR_TM_TRANSACTIONAL(vcpu->arch.shregs.msr))
+		return H_BAD_MODE;
+
 	/* copy parameters in */
 	hv_ptr = kvmppc_get_gpr(vcpu, 4);
 	err = kvm_vcpu_read_guest(vcpu, hv_ptr, &l2_hv,
@@ -252,6 +256,23 @@
 	if (l2_hv.vcpu_token >= NR_CPUS)
 		return H_PARAMETER;
 
+	/*
+	 * L1 must have set up a suspended state to enter the L2 in a
+	 * transactional state, and only in that case. These have to be
+	 * filtered out here to prevent causing a TM Bad Thing in the
+	 * host HRFID. We could synthesize a TM Bad Thing back to the L1
+	 * here but there doesn't seem like much point.
+	 */
+	if (MSR_TM_SUSPENDED(vcpu->arch.shregs.msr)) {
+		if (!MSR_TM_ACTIVE(l2_regs.msr))
+			return H_BAD_MODE;
+	} else {
+		if (l2_regs.msr & MSR_TS_MASK)
+			return H_BAD_MODE;
+		if (WARN_ON_ONCE(vcpu->arch.shregs.msr & MSR_TS_MASK))
+			return H_BAD_MODE;
+	}
+
 	/* translate lpid */
 	l2 = kvmhv_get_nested(vcpu->kvm, l2_hv.lpid, true);
 	if (!l2)
@@ -489,7 +510,7 @@
 	if (eaddr & (0xFFFUL << 52))
 		return H_PARAMETER;
 
-	buf = kzalloc(n, GFP_KERNEL);
+	buf = kzalloc(n, GFP_KERNEL | __GFP_NOWARN);
 	if (!buf)
 		return H_NO_MEM;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kvm/book3s_hv_rm_mmu.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kvm/book3s_hv_rm_mmu.c
@@ -67,7 +67,7 @@
 		 * so use the bit for the first thread to represent the core.
 		 */
 		if (cpu_has_feature(CPU_FTR_ARCH_300))
-			cpu = cpu_first_thread_sibling(cpu);
+			cpu = cpu_first_tlb_thread_sibling(cpu);
 		cpumask_clear_cpu(cpu, &kvm->arch.need_tlb_flush);
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -11,6 +11,7 @@
  */
 
 #include <asm/ppc_asm.h>
+#include <asm/code-patching-asm.h>
 #include <asm/kvm_asm.h>
 #include <asm/reg.h>
 #include <asm/mmu.h>
@@ -291,13 +292,16 @@
  * r3 contains the SRR1 wakeup value, SRR1 is trashed.
  */
 _GLOBAL(idle_kvm_start_guest)
-	ld	r4,PACAEMERGSP(r13)
 	mfcr	r5
 	mflr	r0
-	std	r1,0(r4)
-	std	r5,8(r4)
-	std	r0,16(r4)
-	subi	r1,r4,STACK_FRAME_OVERHEAD
+	std	r5, 8(r1)	// Save CR in caller's frame
+	std	r0, 16(r1)	// Save LR in caller's frame
+	// Create frame on emergency stack
+	ld	r4, PACAEMERGSP(r13)
+	stdu	r1, -SWITCH_FRAME_SIZE(r4)
+	// Switch to new frame on emergency stack
+	mr	r1, r4
+	std	r3, 32(r1)	// Save SRR1 wakeup value
 	SAVE_NVGPRS(r1)
 
 	/*
@@ -349,6 +353,10 @@
 
 kvm_secondary_got_guest:
 
+	// About to go to guest, clear saved SRR1
+	li	r0, 0
+	std	r0, 32(r1)
+
 	/* Set HSTATE_DSCR(r13) to something sensible */
 	ld	r6, PACA_DSCR_DEFAULT(r13)
 	std	r6, HSTATE_DSCR(r13)
@@ -440,13 +448,12 @@
 	mfspr	r4, SPRN_LPCR
 	rlwimi	r4, r3, 0, LPCR_PECE0 | LPCR_PECE1
 	mtspr	SPRN_LPCR, r4
-	/* set up r3 for return */
-	mfspr	r3,SPRN_SRR1
+	// Return SRR1 wakeup value, or 0 if we went into the guest
+	ld	r3, 32(r1)
 	REST_NVGPRS(r1)
-	addi	r1, r1, STACK_FRAME_OVERHEAD
-	ld	r0, 16(r1)
-	ld	r5, 8(r1)
-	ld	r1, 0(r1)
+	ld	r1, 0(r1)	// Switch back to caller stack
+	ld	r0, 16(r1)	// Reload LR
+	ld	r5, 8(r1)	// Reload CR
 	mtlr	r0
 	mtcr	r5
 	blr
@@ -1116,7 +1123,7 @@
 	ld	r7, VCPU_GPR(R7)(r4)
 	bne	ret_to_ultra
 
-	lwz	r0, VCPU_CR(r4)
+	ld	r0, VCPU_CR(r4)
 	mtcr	r0
 
 	ld	r0, VCPU_GPR(R0)(r4)
@@ -1136,7 +1143,7 @@
  *   R3 = UV_RETURN
  */
 ret_to_ultra:
-	lwz	r0, VCPU_CR(r4)
+	ld	r0, VCPU_CR(r4)
 	mtcr	r0
 
 	ld	r0, VCPU_GPR(R3)(r4)
@@ -1487,6 +1494,13 @@
 1:
 #endif /* CONFIG_KVM_XICS */
 
+	/*
+	 * Possibly flush the link stack here, before we do a blr in
+	 * guest_exit_short_path.
+	 */
+1:	nop
+	patch_site 1b patch__call_kvm_flush_link_stack
+
 	/* If we came in through the P9 short path, go back out to C now */
 	lwz	r0, STACK_SLOT_SHORT_PATH(r1)
 	cmpwi	r0, 0
@@ -1963,6 +1977,28 @@
 	mtlr	r0
 	blr
 
+.balign 32
+.global kvm_flush_link_stack
+kvm_flush_link_stack:
+	/* Save LR into r0 */
+	mflr	r0
+
+	/* Flush the link stack. On Power8 it's up to 32 entries in size. */
+	.rept 32
+	bl	.+4
+	.endr
+
+	/* And on Power9 it's up to 64. */
+BEGIN_FTR_SECTION
+	.rept 32
+	bl	.+4
+	.endr
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
+
+	/* Restore LR */
+	mtlr	r0
+	blr
+
 kvmppc_guest_external:
 	/* External interrupt, first check for host_ipi. If this is
 	 * set, we know the host wants us out so let's do it now
@@ -2499,7 +2535,7 @@
 	.globl	hcall_real_table_end
 hcall_real_table_end:
 
-_GLOBAL(kvmppc_h_set_xdabr)
+_GLOBAL_TOC(kvmppc_h_set_xdabr)
 EXPORT_SYMBOL_GPL(kvmppc_h_set_xdabr)
 	andi.	r0, r5, DABRX_USER | DABRX_KERNEL
 	beq	6f
@@ -2509,7 +2545,7 @@
 6:	li	r3, H_PARAMETER
 	blr
 
-_GLOBAL(kvmppc_h_set_dabr)
+_GLOBAL_TOC(kvmppc_h_set_dabr)
 EXPORT_SYMBOL_GPL(kvmppc_h_set_dabr)
 	li	r5, DABRX_USER | DABRX_KERNEL
 3:
@@ -3107,7 +3143,7 @@
 	/* The following code handles the fake_suspend = 1 case */
 	mflr	r0
 	std	r0, PPC_LR_STKOFF(r1)
-	stdu	r1, -PPC_MIN_STKFRM(r1)
+	stdu	r1, -TM_FRAME_SIZE(r1)
 
 	/* Turn on TM. */
 	mfmsr	r8
@@ -3122,10 +3158,42 @@
 END_FTR_SECTION_IFSET(CPU_FTR_P9_TM_XER_SO_BUG)
 	nop
 
+	/*
+	 * It's possible that treclaim. may modify registers, if we have lost
+	 * track of fake-suspend state in the guest due to it using rfscv.
+	 * Save and restore registers in case this occurs.
+	 */
+	mfspr	r3, SPRN_DSCR
+	mfspr	r4, SPRN_XER
+	mfspr	r5, SPRN_AMR
+	/* SPRN_TAR would need to be saved here if the kernel ever used it */
+	mfcr	r12
+	SAVE_NVGPRS(r1)
+	SAVE_GPR(2, r1)
+	SAVE_GPR(3, r1)
+	SAVE_GPR(4, r1)
+	SAVE_GPR(5, r1)
+	stw	r12, 8(r1)
+	std	r1, HSTATE_HOST_R1(r13)
+
 	/* We have to treclaim here because that's the only way to do S->N */
 	li	r3, TM_CAUSE_KVM_RESCHED
 	TRECLAIM(R3)
 
+	GET_PACA(r13)
+	ld	r1, HSTATE_HOST_R1(r13)
+	REST_GPR(2, r1)
+	REST_GPR(3, r1)
+	REST_GPR(4, r1)
+	REST_GPR(5, r1)
+	lwz	r12, 8(r1)
+	REST_NVGPRS(r1)
+	mtspr	SPRN_DSCR, r3
+	mtspr	SPRN_XER, r4
+	mtspr	SPRN_AMR, r5
+	mtcr	r12
+	HMT_MEDIUM
+
 	/*
 	 * We were in fake suspend, so we are not going to save the
 	 * register state as the guest checkpointed state (since
@@ -3153,7 +3221,7 @@
 	std	r5, VCPU_TFHAR(r9)
 	std	r6, VCPU_TFIAR(r9)
 
-	addi	r1, r1, PPC_MIN_STKFRM
+	addi	r1, r1, TM_FRAME_SIZE
 	ld	r0, PPC_LR_STKOFF(r1)
 	mtlr	r0
 	blr
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kvm/book3s_hv_tm.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kvm/book3s_hv_tm.c
@@ -3,6 +3,8 @@
  * Copyright 2017 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kvm_host.h>
 
 #include <asm/kvm_ppc.h>
@@ -44,7 +46,18 @@
 	u64 newmsr, bescr;
 	int ra, rs;
 
-	switch (instr & 0xfc0007ff) {
+	/*
+	 * rfid, rfebb, and mtmsrd encode bit 31 = 0 since it's a reserved bit
+	 * in these instructions, so masking bit 31 out doesn't change these
+	 * instructions. For treclaim., tsr., and trechkpt. instructions if bit
+	 * 31 = 0 then they are per ISA invalid forms, however P9 UM, in section
+	 * 4.6.10 Book II Invalid Forms, informs specifically that ignoring bit
+	 * 31 is an acceptable way to handle these invalid forms that have
+	 * bit 31 = 0. Moreover, for emulation purposes both forms (w/ and wo/
+	 * bit 31 set) can generate a softpatch interrupt. Hence both forms
+	 * are handled below for these instructions so they behave the same way.
+	 */
+	switch (instr & PO_XOP_OPCODE_MASK) {
 	case PPC_INST_RFID:
 		/* XXX do we need to check for PR=0 here? */
 		newmsr = vcpu->arch.shregs.srr1;
@@ -105,7 +118,8 @@
 		vcpu->arch.shregs.msr = newmsr;
 		return RESUME_GUEST;
 
-	case PPC_INST_TSR:
+	/* ignore bit 31, see comment above */
+	case (PPC_INST_TSR & PO_XOP_OPCODE_MASK):
 		/* check for PR=1 and arch 2.06 bit set in PCR */
 		if ((msr & MSR_PR) && (vcpu->arch.vcore->pcr & PCR_ARCH_206)) {
 			/* generate an illegal instruction interrupt */
@@ -140,7 +154,8 @@
 		vcpu->arch.shregs.msr = msr;
 		return RESUME_GUEST;
 
-	case PPC_INST_TRECLAIM:
+	/* ignore bit 31, see comment above */
+	case (PPC_INST_TRECLAIM & PO_XOP_OPCODE_MASK):
 		/* check for TM disabled in the HFSCR or MSR */
 		if (!(vcpu->arch.hfscr & HFSCR_TM)) {
 			/* generate an illegal instruction interrupt */
@@ -176,7 +191,8 @@
 		vcpu->arch.shregs.msr &= ~MSR_TS_MASK;
 		return RESUME_GUEST;
 
-	case PPC_INST_TRECHKPT:
+	/* ignore bit 31, see comment above */
+	case (PPC_INST_TRECHKPT & PO_XOP_OPCODE_MASK):
 		/* XXX do we need to check for PR=0 here? */
 		/* check for TM disabled in the HFSCR or MSR */
 		if (!(vcpu->arch.hfscr & HFSCR_TM)) {
@@ -208,6 +224,8 @@
 	}
 
 	/* What should we do here? We didn't recognize the instruction */
-	WARN_ON_ONCE(1);
+	kvmppc_core_queue_program(vcpu, SRR1_PROGILL);
+	pr_warn_ratelimited("Unrecognized TM-related instruction %#x for emulation", instr);
+
 	return RESUME_GUEST;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kvm/book3s_hv_tm_builtin.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kvm/book3s_hv_tm_builtin.c
@@ -23,7 +23,18 @@
 	u64 newmsr, msr, bescr;
 	int rs;
 
-	switch (instr & 0xfc0007ff) {
+	/*
+	 * rfid, rfebb, and mtmsrd encode bit 31 = 0 since it's a reserved bit
+	 * in these instructions, so masking bit 31 out doesn't change these
+	 * instructions. For the tsr. instruction if bit 31 = 0 then it is per
+	 * ISA an invalid form, however P9 UM, in section 4.6.10 Book II Invalid
+	 * Forms, informs specifically that ignoring bit 31 is an acceptable way
+	 * to handle TM-related invalid forms that have bit 31 = 0. Moreover,
+	 * for emulation purposes both forms (w/ and wo/ bit 31 set) can
+	 * generate a softpatch interrupt. Hence both forms are handled below
+	 * for tsr. to make them behave the same way.
+	 */
+	switch (instr & PO_XOP_OPCODE_MASK) {
 	case PPC_INST_RFID:
 		/* XXX do we need to check for PR=0 here? */
 		newmsr = vcpu->arch.shregs.srr1;
@@ -73,7 +84,8 @@
 		vcpu->arch.shregs.msr = newmsr;
 		return 1;
 
-	case PPC_INST_TSR:
+	/* ignore bit 31, see comment above */
+	case (PPC_INST_TSR & PO_XOP_OPCODE_MASK):
 		/* we know the MSR has the TS field = S (0b01) here */
 		msr = vcpu->arch.shregs.msr;
 		/* check for PR=1 and arch 2.06 bit set in PCR */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kvm/book3s_pr.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kvm/book3s_pr.c
@@ -1769,10 +1769,12 @@
 
 	err = kvmppc_mmu_init(vcpu);
 	if (err < 0)
-		goto uninit_vcpu;
+		goto free_shared_page;
 
 	return vcpu;
 
+free_shared_page:
+	free_page((unsigned long)vcpu->arch.shared);
 uninit_vcpu:
 	kvm_vcpu_uninit(vcpu);
 free_shadow_vcpu:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kvm/book3s_rtas.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kvm/book3s_rtas.c
@@ -240,6 +240,17 @@
 	 * value so we can restore it on the way out.
 	 */
 	orig_rets = args.rets;
+	if (be32_to_cpu(args.nargs) >= ARRAY_SIZE(args.args)) {
+		/*
+		 * Don't overflow our args array: ensure there is room for
+		 * at least rets[0] (even if the call specifies 0 nret).
+		 *
+		 * Each handler must then check for the correct nargs and nret
+		 * values, but they may always return failure in rets[0].
+		 */
+		rc = -EINVAL;
+		goto fail;
+	}
 	args.rets = &args.args[be32_to_cpu(args.nargs)];
 
 	mutex_lock(&vcpu->kvm->arch.rtas_token_lock);
@@ -267,9 +278,17 @@
 fail:
 	/*
 	 * We only get here if the guest has called RTAS with a bogus
-	 * args pointer. That means we can't get to the args, and so we
-	 * can't fail the RTAS call. So fail right out to userspace,
-	 * which should kill the guest.
+	 * args pointer or nargs/nret values that would overflow the
+	 * array. That means we can't get to the args, and so we can't
+	 * fail the RTAS call. So fail right out to userspace, which
+	 * should kill the guest.
+	 *
+	 * SLOF should actually pass the hcall return value from the
+	 * rtas handler call in r3, so enter_rtas could be modified to
+	 * return a failure indication in r3 and we could return such
+	 * errors to the guest rather than failing to host userspace.
+	 * However old guests that don't test for failure could then
+	 * continue silently after errors, so for now we won't do this.
 	 */
 	return rc;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kvm/book3s_xive.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kvm/book3s_xive.c
@@ -2005,6 +2005,10 @@
 
 	pr_devel("Creating xive for partition\n");
 
+	/* Already there ? */
+	if (kvm->arch.xive)
+		return -EEXIST;
+
 	xive = kvmppc_xive_get_device(kvm, type);
 	if (!xive)
 		return -ENOMEM;
@@ -2014,12 +2018,6 @@
 	xive->kvm = kvm;
 	mutex_init(&xive->lock);
 
-	/* Already there ? */
-	if (kvm->arch.xive)
-		ret = -EEXIST;
-	else
-		kvm->arch.xive = xive;
-
 	/* We use the default queue size set by the host */
 	xive->q_order = xive_native_default_eq_shift();
 	if (xive->q_order < PAGE_SHIFT)
@@ -2039,6 +2037,7 @@
 	if (ret)
 		return ret;
 
+	kvm->arch.xive = xive;
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kvm/book3s_xive_native.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kvm/book3s_xive_native.c
@@ -50,6 +50,24 @@
 	}
 }
 
+static int kvmppc_xive_native_configure_queue(u32 vp_id, struct xive_q *q,
+					      u8 prio, __be32 *qpage,
+					      u32 order, bool can_escalate)
+{
+	int rc;
+	__be32 *qpage_prev = q->qpage;
+
+	rc = xive_native_configure_queue(vp_id, q, prio, qpage, order,
+					 can_escalate);
+	if (rc)
+		return rc;
+
+	if (qpage_prev)
+		put_page(virt_to_page(qpage_prev));
+
+	return rc;
+}
+
 void kvmppc_xive_native_cleanup_vcpu(struct kvm_vcpu *vcpu)
 {
 	struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
@@ -234,6 +252,13 @@
 	}
 
 	state = &sb->irq_state[src];
+
+	/* Some sanity checking */
+	if (!state->valid) {
+		pr_devel("%s: source %lx invalid !\n", __func__, irq);
+		return VM_FAULT_SIGBUS;
+	}
+
 	kvmppc_xive_select_irq(state, &hw_num, &xd);
 
 	arch_spin_lock(&sb->lock);
@@ -582,19 +607,14 @@
 		q->guest_qaddr  = 0;
 		q->guest_qshift = 0;
 
-		rc = xive_native_configure_queue(xc->vp_id, q, priority,
-						 NULL, 0, true);
+		rc = kvmppc_xive_native_configure_queue(xc->vp_id, q, priority,
+							NULL, 0, true);
 		if (rc) {
 			pr_err("Failed to reset queue %d for VCPU %d: %d\n",
 			       priority, xc->server_num, rc);
 			return rc;
 		}
 
-		if (q->qpage) {
-			put_page(virt_to_page(q->qpage));
-			q->qpage = NULL;
-		}
-
 		return 0;
 	}
 
@@ -624,17 +644,18 @@
 
 	srcu_idx = srcu_read_lock(&kvm->srcu);
 	gfn = gpa_to_gfn(kvm_eq.qaddr);
-	page = gfn_to_page(kvm, gfn);
-	if (is_error_page(page)) {
+
+	page_size = kvm_host_page_size(vcpu, gfn);
+	if (1ull << kvm_eq.qshift > page_size) {
 		srcu_read_unlock(&kvm->srcu, srcu_idx);
-		pr_err("Couldn't get queue page %llx!\n", kvm_eq.qaddr);
+		pr_warn("Incompatible host page size %lx!\n", page_size);
 		return -EINVAL;
 	}
 
-	page_size = kvm_host_page_size(kvm, gfn);
-	if (1ull << kvm_eq.qshift > page_size) {
+	page = gfn_to_page(kvm, gfn);
+	if (is_error_page(page)) {
 		srcu_read_unlock(&kvm->srcu, srcu_idx);
-		pr_warn("Incompatible host page size %lx!\n", page_size);
+		pr_err("Couldn't get queue page %llx!\n", kvm_eq.qaddr);
 		return -EINVAL;
 	}
 
@@ -653,8 +674,8 @@
 	  * OPAL level because the use of END ESBs is not supported by
 	  * Linux.
 	  */
-	rc = xive_native_configure_queue(xc->vp_id, q, priority,
-					 (__be32 *) qaddr, kvm_eq.qshift, true);
+	rc = kvmppc_xive_native_configure_queue(xc->vp_id, q, priority,
+					(__be32 *) qaddr, kvm_eq.qshift, true);
 	if (rc) {
 		pr_err("Failed to configure queue %d for VCPU %d: %d\n",
 		       priority, xc->server_num, rc);
@@ -1081,7 +1102,6 @@
 	dev->private = xive;
 	xive->dev = dev;
 	xive->kvm = kvm;
-	kvm->arch.xive = xive;
 	mutex_init(&xive->mapping_lock);
 	mutex_init(&xive->lock);
 
@@ -1102,6 +1122,7 @@
 	if (ret)
 		return ret;
 
+	kvm->arch.xive = xive;
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kvm/e500_mmu_host.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kvm/e500_mmu_host.c
@@ -734,7 +734,8 @@
 	return 0;
 }
 
-int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end)
+int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end,
+			unsigned flags)
 {
 	/* kvm_unmap_hva flushes everything anyways */
 	kvm_unmap_hva(kvm, start);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kvm/emulate_loadstore.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kvm/emulate_loadstore.c
@@ -73,7 +73,6 @@
 {
 	struct kvm_run *run = vcpu->run;
 	u32 inst;
-	int ra, rs, rt;
 	enum emulation_result emulated = EMULATE_FAIL;
 	int advance = 1;
 	struct instruction_op op;
@@ -85,10 +84,6 @@
 	if (emulated != EMULATE_DONE)
 		return emulated;
 
-	ra = get_ra(inst);
-	rs = get_rs(inst);
-	rt = get_rt(inst);
-
 	vcpu->arch.mmio_vsx_copy_nums = 0;
 	vcpu->arch.mmio_vsx_offset = 0;
 	vcpu->arch.mmio_copy_type = KVMPPC_VSX_COPY_NONE;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/kvm/powerpc.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/kvm/powerpc.c
@@ -1495,7 +1495,7 @@
 {
 	enum emulation_result emulated = EMULATE_DONE;
 
-	if (vcpu->arch.mmio_vsx_copy_nums > 2)
+	if (vcpu->arch.mmio_vmx_copy_nums > 2)
 		return EMULATE_FAIL;
 
 	while (vcpu->arch.mmio_vmx_copy_nums) {
@@ -1513,7 +1513,7 @@
 	return emulated;
 }
 
-int kvmppc_get_vmx_dword(struct kvm_vcpu *vcpu, int index, u64 *val)
+static int kvmppc_get_vmx_dword(struct kvm_vcpu *vcpu, int index, u64 *val)
 {
 	union kvmppc_one_reg reg;
 	int vmx_offset = 0;
@@ -1531,7 +1531,7 @@
 	return result;
 }
 
-int kvmppc_get_vmx_word(struct kvm_vcpu *vcpu, int index, u64 *val)
+static int kvmppc_get_vmx_word(struct kvm_vcpu *vcpu, int index, u64 *val)
 {
 	union kvmppc_one_reg reg;
 	int vmx_offset = 0;
@@ -1549,7 +1549,7 @@
 	return result;
 }
 
-int kvmppc_get_vmx_hword(struct kvm_vcpu *vcpu, int index, u64 *val)
+static int kvmppc_get_vmx_hword(struct kvm_vcpu *vcpu, int index, u64 *val)
 {
 	union kvmppc_one_reg reg;
 	int vmx_offset = 0;
@@ -1567,7 +1567,7 @@
 	return result;
 }
 
-int kvmppc_get_vmx_byte(struct kvm_vcpu *vcpu, int index, u64 *val)
+static int kvmppc_get_vmx_byte(struct kvm_vcpu *vcpu, int index, u64 *val)
 {
 	union kvmppc_one_reg reg;
 	int vmx_offset = 0;
@@ -1592,7 +1592,7 @@
 	unsigned int index = rs & KVM_MMIO_REG_MASK;
 	enum emulation_result emulated = EMULATE_DONE;
 
-	if (vcpu->arch.mmio_vsx_copy_nums > 2)
+	if (vcpu->arch.mmio_vmx_copy_nums > 2)
 		return EMULATE_FAIL;
 
 	vcpu->arch.io_gpr = rs;
@@ -1950,8 +1950,10 @@
 			break;
 
 		r = -ENXIO;
-		if (!xive_enabled())
+		if (!xive_enabled()) {
+			fdput(f);
 			break;
+		}
 
 		r = -EPERM;
 		dev = kvm_device_from_filp(f.file);
@@ -2035,9 +2037,9 @@
 	{
 		struct kvm_enable_cap cap;
 		r = -EFAULT;
-		vcpu_load(vcpu);
 		if (copy_from_user(&cap, argp, sizeof(cap)))
 			goto out;
+		vcpu_load(vcpu);
 		r = kvm_vcpu_ioctl_enable_cap(vcpu, &cap);
 		vcpu_put(vcpu);
 		break;
@@ -2061,9 +2063,9 @@
 	case KVM_DIRTY_TLB: {
 		struct kvm_dirty_tlb dirty;
 		r = -EFAULT;
-		vcpu_load(vcpu);
 		if (copy_from_user(&dirty, argp, sizeof(dirty)))
 			goto out;
+		vcpu_load(vcpu);
 		r = kvm_vcpu_ioctl_dirty_tlb(vcpu, &dirty);
 		vcpu_put(vcpu);
 		break;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/lib/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/lib/Makefile
@@ -16,6 +16,9 @@
 CFLAGS_feature-fixups.o += -DDISABLE_BRANCH_PROFILING
 endif
 
+CFLAGS_code-patching.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
+CFLAGS_feature-fixups.o += $(DISABLE_LATENT_ENTROPY_PLUGIN)
+
 obj-y += alloc.o code-patching.o feature-fixups.o pmem.o
 
 ifndef CONFIG_KASAN
@@ -31,8 +34,8 @@
 # 64-bit linker creates .sfpr on demand for final link (vmlinux),
 # so it is only needed for modules, and only for older linkers which
 # do not support --save-restore-funcs
-ifeq ($(call ld-ifversion, -lt, 225000000, y),y)
-extra-$(CONFIG_PPC64)	+= crtsavres.o
+ifeq ($(call ld-ifversion, -lt, 225000000, y)$(CONFIG_PPC64),yy)
+always	+= crtsavres.o
 endif
 
 obj-$(CONFIG_PPC_BOOK3S_64) += copyuser_power7.o copypage_power7.o \
@@ -58,6 +61,6 @@
 obj-$(CONFIG_FTR_FIXUP_SELFTEST) += feature-fixups-test.o
 
 obj-$(CONFIG_ALTIVEC)	+= xor_vmx.o xor_vmx_glue.o
-CFLAGS_xor_vmx.o += -maltivec $(call cc-option,-mabi=altivec)
+CFLAGS_xor_vmx.o += -mhard-float -maltivec $(call cc-option,-mabi=altivec)
 
 obj-$(CONFIG_PPC64) += $(obj64-y)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/lib/code-patching.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/lib/code-patching.c
@@ -45,7 +45,7 @@
 {
 	struct vm_struct *area;
 
-	area = get_vm_area(PAGE_SIZE, VM_ALLOC);
+	area = get_vm_area(PAGE_SIZE, 0);
 	if (!area) {
 		WARN_ONCE(1, "Failed to create text area for cpu %d\n",
 			cpu);
@@ -221,6 +221,11 @@
 	return (offset >= -0x2000000 && offset <= 0x1fffffc && !(offset & 0x3));
 }
 
+bool is_offset_in_cond_branch_range(long offset)
+{
+	return offset >= -0x8000 && offset <= 0x7fff && !(offset & 0x3);
+}
+
 /*
  * Helper to check if a given instruction is a conditional branch
  * Derived from the conditional checks in analyse_instr()
@@ -274,7 +279,7 @@
 		offset = offset - (unsigned long)addr;
 
 	/* Check we can represent the target in the instruction format */
-	if (offset < -0x8000 || offset > 0x7FFF || offset & 0x3)
+	if (!is_offset_in_cond_branch_range(offset))
 		return 0;
 
 	/* Mask out the flags and target, so they don't step on each other. */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/lib/feature-fixups.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/lib/feature-fixups.c
@@ -14,6 +14,7 @@
 #include <linux/string.h>
 #include <linux/init.h>
 #include <linux/sched/mm.h>
+#include <linux/stop_machine.h>
 #include <asm/cputable.h>
 #include <asm/code-patching.h>
 #include <asm/page.h>
@@ -221,11 +222,143 @@
 		                                           : "unknown");
 }
 
+static int __do_stf_barrier_fixups(void *data)
+{
+	enum stf_barrier_type *types = data;
+
+	do_stf_entry_barrier_fixups(*types);
+	do_stf_exit_barrier_fixups(*types);
+
+	return 0;
+}
 
 void do_stf_barrier_fixups(enum stf_barrier_type types)
 {
-	do_stf_entry_barrier_fixups(types);
-	do_stf_exit_barrier_fixups(types);
+	/*
+	 * The call to the fallback entry flush, and the fallback/sync-ori exit
+	 * flush can not be safely patched in/out while other CPUs are executing
+	 * them. So call __do_stf_barrier_fixups() on one CPU while all other CPUs
+	 * spin in the stop machine core with interrupts hard disabled.
+	 */
+	stop_machine(__do_stf_barrier_fixups, &types, NULL);
+}
+
+void do_uaccess_flush_fixups(enum l1d_flush_type types)
+{
+	unsigned int instrs[4], *dest;
+	long *start, *end;
+	int i;
+
+	start = PTRRELOC(&__start___uaccess_flush_fixup);
+	end = PTRRELOC(&__stop___uaccess_flush_fixup);
+
+	instrs[0] = 0x60000000; /* nop */
+	instrs[1] = 0x60000000; /* nop */
+	instrs[2] = 0x60000000; /* nop */
+	instrs[3] = 0x4e800020; /* blr */
+
+	i = 0;
+	if (types == L1D_FLUSH_FALLBACK) {
+		instrs[3] = 0x60000000; /* nop */
+		/* fallthrough to fallback flush */
+	}
+
+	if (types & L1D_FLUSH_ORI) {
+		instrs[i++] = 0x63ff0000; /* ori 31,31,0 speculation barrier */
+		instrs[i++] = 0x63de0000; /* ori 30,30,0 L1d flush*/
+	}
+
+	if (types & L1D_FLUSH_MTTRIG)
+		instrs[i++] = 0x7c12dba6; /* mtspr TRIG2,r0 (SPR #882) */
+
+	for (i = 0; start < end; start++, i++) {
+		dest = (void *)start + *start;
+
+		pr_devel("patching dest %lx\n", (unsigned long)dest);
+
+		patch_instruction(dest, instrs[0]);
+
+		patch_instruction((dest + 1), instrs[1]);
+		patch_instruction((dest + 2), instrs[2]);
+		patch_instruction((dest + 3), instrs[3]);
+	}
+
+	printk(KERN_DEBUG "uaccess-flush: patched %d locations (%s flush)\n", i,
+		(types == L1D_FLUSH_NONE)       ? "no" :
+		(types == L1D_FLUSH_FALLBACK)   ? "fallback displacement" :
+		(types &  L1D_FLUSH_ORI)        ? (types & L1D_FLUSH_MTTRIG)
+							? "ori+mttrig type"
+							: "ori type" :
+		(types &  L1D_FLUSH_MTTRIG)     ? "mttrig type"
+						: "unknown");
+}
+
+static int __do_entry_flush_fixups(void *data)
+{
+	enum l1d_flush_type types = *(enum l1d_flush_type *)data;
+	unsigned int instrs[3], *dest;
+	long *start, *end;
+	int i;
+
+	start = PTRRELOC(&__start___entry_flush_fixup);
+	end = PTRRELOC(&__stop___entry_flush_fixup);
+
+	instrs[0] = 0x60000000; /* nop */
+	instrs[1] = 0x60000000; /* nop */
+	instrs[2] = 0x60000000; /* nop */
+
+	i = 0;
+	if (types == L1D_FLUSH_FALLBACK) {
+		instrs[i++] = 0x7d4802a6; /* mflr r10		*/
+		instrs[i++] = 0x60000000; /* branch patched below */
+		instrs[i++] = 0x7d4803a6; /* mtlr r10		*/
+	}
+
+	if (types & L1D_FLUSH_ORI) {
+		instrs[i++] = 0x63ff0000; /* ori 31,31,0 speculation barrier */
+		instrs[i++] = 0x63de0000; /* ori 30,30,0 L1d flush*/
+	}
+
+	if (types & L1D_FLUSH_MTTRIG)
+		instrs[i++] = 0x7c12dba6; /* mtspr TRIG2,r0 (SPR #882) */
+
+	for (i = 0; start < end; start++, i++) {
+		dest = (void *)start + *start;
+
+		pr_devel("patching dest %lx\n", (unsigned long)dest);
+
+		patch_instruction(dest, instrs[0]);
+
+		if (types == L1D_FLUSH_FALLBACK)
+			patch_branch((dest + 1), (unsigned long)&entry_flush_fallback,
+				     BRANCH_SET_LINK);
+		else
+			patch_instruction((dest + 1), instrs[1]);
+
+		patch_instruction((dest + 2), instrs[2]);
+	}
+
+	printk(KERN_DEBUG "entry-flush: patched %d locations (%s flush)\n", i,
+		(types == L1D_FLUSH_NONE)       ? "no" :
+		(types == L1D_FLUSH_FALLBACK)   ? "fallback displacement" :
+		(types &  L1D_FLUSH_ORI)        ? (types & L1D_FLUSH_MTTRIG)
+							? "ori+mttrig type"
+							: "ori type" :
+		(types &  L1D_FLUSH_MTTRIG)     ? "mttrig type"
+						: "unknown");
+
+	return 0;
+}
+
+void do_entry_flush_fixups(enum l1d_flush_type types)
+{
+	/*
+	 * The call to the fallback flush can not be safely patched in/out while
+	 * other CPUs are executing it. So call __do_entry_flush_fixups() on one
+	 * CPU while all other CPUs spin in the stop machine core with interrupts
+	 * hard disabled.
+	 */
+	stop_machine(__do_entry_flush_fixups, &types, NULL);
 }
 
 void do_rfi_flush_fixups(enum l1d_flush_type types)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/lib/sstep.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/lib/sstep.c
@@ -8,6 +8,7 @@
 #include <linux/kprobes.h>
 #include <linux/ptrace.h>
 #include <linux/prefetch.h>
+#include <asm/cpu_has_feature.h>
 #include <asm/sstep.h>
 #include <asm/processor.h>
 #include <linux/uaccess.h>
@@ -469,6 +470,8 @@
 	} u;
 
 	nb = GETSIZE(op->type);
+	if (nb > sizeof(u))
+		return -EINVAL;
 	if (!address_ok(regs, ea, nb))
 		return -EFAULT;
 	rn = op->reg;
@@ -519,6 +522,8 @@
 	} u;
 
 	nb = GETSIZE(op->type);
+	if (nb > sizeof(u))
+		return -EINVAL;
 	if (!address_ok(regs, ea, nb))
 		return -EFAULT;
 	rn = op->reg;
@@ -563,6 +568,9 @@
 		u8 b[sizeof(__vector128)];
 	} u = {};
 
+	if (size > sizeof(u))
+		return -EINVAL;
+
 	if (!address_ok(regs, ea & ~0xfUL, 16))
 		return -EFAULT;
 	/* align to multiple of size */
@@ -590,6 +598,9 @@
 		u8 b[sizeof(__vector128)];
 	} u;
 
+	if (size > sizeof(u))
+		return -EINVAL;
+
 	if (!address_ok(regs, ea & ~0xfUL, 16))
 		return -EFAULT;
 	/* align to multiple of size */
@@ -653,8 +664,8 @@
 #endif /* __powerpc64 */
 
 #ifdef CONFIG_VSX
-void emulate_vsx_load(struct instruction_op *op, union vsx_reg *reg,
-		      const void *mem, bool rev)
+static nokprobe_inline void emulate_vsx_load(struct instruction_op *op, union vsx_reg *reg,
+					     const void *mem, bool rev)
 {
 	int size, read_size;
 	int i, j;
@@ -734,11 +745,9 @@
 		break;
 	}
 }
-EXPORT_SYMBOL_GPL(emulate_vsx_load);
-NOKPROBE_SYMBOL(emulate_vsx_load);
 
-void emulate_vsx_store(struct instruction_op *op, const union vsx_reg *reg,
-		       void *mem, bool rev)
+static nokprobe_inline void emulate_vsx_store(struct instruction_op *op, const union vsx_reg *reg,
+					      void *mem, bool rev)
 {
 	int size, write_size;
 	int i, j;
@@ -810,8 +819,6 @@
 		break;
 	}
 }
-EXPORT_SYMBOL_GPL(emulate_vsx_store);
-NOKPROBE_SYMBOL(emulate_vsx_store);
 
 static nokprobe_inline int do_vsx_load(struct instruction_op *op,
 				       unsigned long ea, struct pt_regs *regs,
@@ -906,7 +913,10 @@
 
 #define __put_user_asmx(x, addr, err, op, cr)		\
 	__asm__ __volatile__(				\
+		".machine push\n"			\
+		".machine power8\n"			\
 		"1:	" op " %2,0,%3\n"		\
+		".machine pop\n"			\
 		"	mfcr	%1\n"			\
 		"2:\n"					\
 		".section .fixup,\"ax\"\n"		\
@@ -919,7 +929,10 @@
 
 #define __get_user_asmx(x, addr, err, op)		\
 	__asm__ __volatile__(				\
+		".machine push\n"			\
+		".machine power8\n"			\
 		"1:	"op" %1,0,%2\n"			\
+		".machine pop\n"			\
 		"2:\n"					\
 		".section .fixup,\"ax\"\n"		\
 		"3:	li	%0,%3\n"		\
@@ -2787,12 +2800,14 @@
 		case BARRIER_EIEIO:
 			eieio();
 			break;
+#ifdef CONFIG_PPC64
 		case BARRIER_LWSYNC:
 			asm volatile("lwsync" : : : "memory");
 			break;
 		case BARRIER_PTESYNC:
 			asm volatile("ptesync" : : : "memory");
 			break;
+#endif
 		}
 		break;
 
@@ -2910,7 +2925,7 @@
 			__put_user_asmx(op->val, ea, err, "stbcx.", cr);
 			break;
 		case 2:
-			__put_user_asmx(op->val, ea, err, "stbcx.", cr);
+			__put_user_asmx(op->val, ea, err, "sthcx.", cr);
 			break;
 #endif
 		case 4:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/lib/string_32.S
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/lib/string_32.S
@@ -17,7 +17,7 @@
 LG_CACHELINE_BYTES = L1_CACHE_SHIFT
 CACHELINE_MASK = (L1_CACHE_BYTES-1)
 
-_GLOBAL(__clear_user)
+_GLOBAL(__arch_clear_user)
 /*
  * Use dcbz on the complete cache lines in the destination
  * to set them to zero.  This requires that the destination
@@ -87,4 +87,4 @@
 	EX_TABLE(8b, 91b)
 	EX_TABLE(9b, 91b)
 
-EXPORT_SYMBOL(__clear_user)
+EXPORT_SYMBOL(__arch_clear_user)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/lib/string_64.S
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/lib/string_64.S
@@ -17,7 +17,7 @@
 	.section	".text"
 
 /**
- * __clear_user: - Zero a block of memory in user space, with less checking.
+ * __arch_clear_user: - Zero a block of memory in user space, with less checking.
  * @to:   Destination address, in user space.
  * @n:    Number of bytes to zero.
  *
@@ -58,7 +58,7 @@
 	mr	r3,r4
 	blr
 
-_GLOBAL_TOC(__clear_user)
+_GLOBAL_TOC(__arch_clear_user)
 	cmpdi	r4,32
 	neg	r6,r3
 	li	r0,0
@@ -181,4 +181,4 @@
 	cmpdi	r4,32
 	blt	.Lshort_clear
 	b	.Lmedium_clear
-EXPORT_SYMBOL(__clear_user)
+EXPORT_SYMBOL(__arch_clear_user)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/math-emu/math_efp.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/math-emu/math_efp.c
@@ -17,6 +17,7 @@
 
 #include <linux/types.h>
 #include <linux/prctl.h>
+#include <linux/module.h>
 
 #include <linux/uaccess.h>
 #include <asm/reg.h>
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/mm/book3s32/mmu.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/mm/book3s32/mmu.c
@@ -187,6 +187,7 @@
 	int i;
 	unsigned long base = (unsigned long)_stext - PAGE_OFFSET;
 	unsigned long top = (unsigned long)_etext - PAGE_OFFSET;
+	unsigned long border = (unsigned long)__init_begin - PAGE_OFFSET;
 	unsigned long size;
 
 	if (IS_ENABLED(CONFIG_PPC_BOOK3S_601))
@@ -201,9 +202,10 @@
 		size = block_size(base, top);
 		size = max(size, 128UL << 10);
 		if ((top - base) > size) {
-			if (strict_kernel_rwx_enabled())
-				pr_warn("Kernel _etext not properly aligned\n");
 			size <<= 1;
+			if (strict_kernel_rwx_enabled() && base + size > border)
+				pr_warn("Some RW data is getting mapped X. "
+					"Adjust CONFIG_DATA_SHIFT to avoid that.\n");
 		}
 		setibat(i++, PAGE_OFFSET + base, base, size, PAGE_KERNEL_TEXT);
 		base += size;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/mm/book3s64/hash_utils.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/mm/book3s64/hash_utils.c
@@ -294,10 +294,18 @@
 		ret = mmu_hash_ops.hpte_insert(hpteg, vpn, paddr, tprot,
 					       HPTE_V_BOLTED, psize, psize,
 					       ssize);
-
+		if (ret == -1) {
+			/* Try to remove a non bolted entry */
+			ret = mmu_hash_ops.hpte_remove(hpteg);
+			if (ret != -1)
+				ret = mmu_hash_ops.hpte_insert(hpteg, vpn, paddr, tprot,
+							       HPTE_V_BOLTED, psize, psize,
+							       ssize);
+		}
 		if (ret < 0)
 			break;
 
+		cond_resched();
 #ifdef CONFIG_DEBUG_PAGEALLOC
 		if (debug_pagealloc_enabled() &&
 			(paddr >> PAGE_SHIFT) < linear_map_hash_count)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/mm/book3s64/iommu_api.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/mm/book3s64/iommu_api.c
@@ -121,24 +121,6 @@
 		goto free_exit;
 	}
 
-	pageshift = PAGE_SHIFT;
-	for (i = 0; i < entries; ++i) {
-		struct page *page = mem->hpages[i];
-
-		/*
-		 * Allow to use larger than 64k IOMMU pages. Only do that
-		 * if we are backed by hugetlb.
-		 */
-		if ((mem->pageshift > PAGE_SHIFT) && PageHuge(page))
-			pageshift = page_shift(compound_head(page));
-		mem->pageshift = min(mem->pageshift, pageshift);
-		/*
-		 * We don't need struct page reference any more, switch
-		 * to physical address.
-		 */
-		mem->hpas[i] = page_to_pfn(page) << PAGE_SHIFT;
-	}
-
 good_exit:
 	atomic64_set(&mem->mapped, 1);
 	mem->used = 1;
@@ -158,6 +140,27 @@
 		}
 	}
 
+	if (mem->dev_hpa == MM_IOMMU_TABLE_INVALID_HPA) {
+		/*
+		 * Allow to use larger than 64k IOMMU pages. Only do that
+		 * if we are backed by hugetlb. Skip device memory as it is not
+		 * backed with page structs.
+		 */
+		pageshift = PAGE_SHIFT;
+		for (i = 0; i < entries; ++i) {
+			struct page *page = mem->hpages[i];
+
+			if ((mem->pageshift > PAGE_SHIFT) && PageHuge(page))
+				pageshift = page_shift(compound_head(page));
+			mem->pageshift = min(mem->pageshift, pageshift);
+			/*
+			 * We don't need struct page reference any more, switch
+			 * to physical address.
+			 */
+			mem->hpas[i] = page_to_pfn(page) << PAGE_SHIFT;
+		}
+	}
+
 	list_add_rcu(&mem->next, &mm->context.iommu_group_mem_list);
 
 	mutex_unlock(&mem_list_mutex);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/mm/book3s64/pgtable.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/mm/book3s64/pgtable.c
@@ -378,7 +378,6 @@
 	}
 }
 
-#ifdef CONFIG_SMP
 void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int index)
 {
 	unsigned long pgf = (unsigned long)table;
@@ -395,12 +394,6 @@
 
 	return pgtable_free(table, index);
 }
-#else
-void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int index)
-{
-	return pgtable_free(table, index);
-}
-#endif
 
 #ifdef CONFIG_PROC_FS
 atomic_long_t direct_pages_count[MMU_PAGE_COUNT];
@@ -449,6 +442,7 @@
 	set_pte_at(vma->vm_mm, addr, ptep, pte);
 }
 
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
 /*
  * For hash translation mode, we use the deposited table to store hash slot
  * information and they are stored at PTRS_PER_PMD offset from related pmd
@@ -470,6 +464,7 @@
 
 	return true;
 }
+#endif
 
 /*
  * Does the CPU support tlbie?
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/mm/book3s64/pkeys.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/mm/book3s64/pkeys.c
@@ -83,13 +83,17 @@
 	scan_pkey_feature();
 
 	/*
-	 * Let's assume 32 pkeys on P8 bare metal, if its not defined by device
-	 * tree. We make this exception since skiboot forgot to expose this
-	 * property on power8.
+	 * Let's assume 32 pkeys on P8/P9 bare metal, if its not defined by device
+	 * tree. We make this exception since some version of skiboot forgot to
+	 * expose this property on power8/9.
 	 */
-	if (!pkeys_devtree_defined && !firmware_has_feature(FW_FEATURE_LPAR) &&
-			cpu_has_feature(CPU_FTRS_POWER8))
-		pkeys_total = 32;
+	if (!pkeys_devtree_defined && !firmware_has_feature(FW_FEATURE_LPAR)) {
+		unsigned long pvr = mfspr(SPRN_PVR);
+
+		if (PVR_VER(pvr) == PVR_POWER8 || PVR_VER(pvr) == PVR_POWER8E ||
+		    PVR_VER(pvr) == PVR_POWER8NVL || PVR_VER(pvr) == PVR_POWER9)
+			pkeys_total = 32;
+	}
 
 	/*
 	 * Adjust the upper limit, based on the number of bits supported by
@@ -367,12 +371,14 @@
 		return true;
 
 	pkey_shift = pkeyshift(pkey);
-	if (execute && !(read_iamr() & (IAMR_EX_BIT << pkey_shift)))
-		return true;
+	if (execute)
+		return !(read_iamr() & (IAMR_EX_BIT << pkey_shift));
+
+	amr = read_amr();
+	if (write)
+		return !(amr & (AMR_WR_BIT << pkey_shift));
 
-	amr = read_amr(); /* Delay reading amr until absolutely needed */
-	return ((!write && !(amr & (AMR_RD_BIT << pkey_shift))) ||
-		(write &&  !(amr & (AMR_WR_BIT << pkey_shift))));
+	return !(amr & (AMR_RD_BIT << pkey_shift));
 }
 
 bool arch_pte_access_permitted(u64 pte, bool write, bool execute)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/mm/book3s64/radix_pgtable.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/mm/book3s64/radix_pgtable.c
@@ -97,7 +97,7 @@
 
 set_the_pte:
 	set_pte_at(&init_mm, ea, ptep, pfn_pte(pfn, flags));
-	smp_wmb();
+	asm volatile("ptesync": : :"memory");
 	return 0;
 }
 
@@ -155,7 +155,7 @@
 
 set_the_pte:
 	set_pte_at(&init_mm, ea, ptep, pfn_pte(pfn, flags));
-	smp_wmb();
+	asm volatile("ptesync": : :"memory");
 	return 0;
 }
 
@@ -643,21 +643,6 @@
 	}
 }
 
-void radix__setup_initial_memory_limit(phys_addr_t first_memblock_base,
-				phys_addr_t first_memblock_size)
-{
-	/*
-	 * We don't currently support the first MEMBLOCK not mapping 0
-	 * physical on those processors
-	 */
-	BUG_ON(first_memblock_base != 0);
-
-	/*
-	 * Radix mode is not limited by RMA / VRMA addressing.
-	 */
-	ppc64_rma_size = ULONG_MAX;
-}
-
 #ifdef CONFIG_MEMORY_HOTPLUG
 static void free_pte_table(pte_t *pte_start, pmd_t *pmd)
 {
@@ -1033,8 +1018,8 @@
 				  pte_t entry, unsigned long address, int psize)
 {
 	struct mm_struct *mm = vma->vm_mm;
-	unsigned long set = pte_val(entry) & (_PAGE_DIRTY | _PAGE_ACCESSED |
-					      _PAGE_RW | _PAGE_EXEC);
+	unsigned long set = pte_val(entry) & (_PAGE_DIRTY | _PAGE_SOFT_DIRTY |
+					      _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC);
 
 	unsigned long change = pte_val(entry) ^ pte_val(*ptep);
 	/*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/mm/book3s64/radix_tlb.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/mm/book3s64/radix_tlb.c
@@ -639,19 +639,29 @@
 	struct mm_struct *mm = arg;
 	unsigned long pid = mm->context.id;
 
+	/*
+	 * A kthread could have done a mmget_not_zero() after the flushing CPU
+	 * checked mm_is_singlethreaded, and be in the process of
+	 * kthread_use_mm when interrupted here. In that case, current->mm will
+	 * be set to mm, because kthread_use_mm() setting ->mm and switching to
+	 * the mm is done with interrupts off.
+	 */
 	if (current->mm == mm)
-		return; /* Local CPU */
+		goto out_flush;
 
 	if (current->active_mm == mm) {
-		/*
-		 * Must be a kernel thread because sender is single-threaded.
-		 */
-		BUG_ON(current->mm);
+		WARN_ON_ONCE(current->mm != NULL);
+		/* Is a kernel thread and is using mm as the lazy tlb */
 		mmgrab(&init_mm);
-		switch_mm(mm, &init_mm, current);
 		current->active_mm = &init_mm;
+		switch_mm_irqs_off(mm, &init_mm, current);
 		mmdrop(mm);
 	}
+
+	atomic_dec(&mm->context.active_cpus);
+	cpumask_clear_cpu(smp_processor_id(), mm_cpumask(mm));
+
+out_flush:
 	_tlbiel_pid(pid, RIC_FLUSH_ALL);
 }
 
@@ -666,7 +676,6 @@
 	 */
 	smp_call_function_many(mm_cpumask(mm), do_exit_flush_lazy_tlb,
 				(void *)mm, 1);
-	mm_reset_thread_local(mm);
 }
 
 void radix__flush_tlb_mm(struct mm_struct *mm)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/mm/dma-noncoherent.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/mm/dma-noncoherent.c
@@ -104,14 +104,14 @@
 #endif
 }
 
-void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr,
-		size_t size, enum dma_data_direction dir)
+void arch_sync_dma_for_device(phys_addr_t paddr, size_t size,
+		enum dma_data_direction dir)
 {
 	__dma_sync_page(paddr, size, dir);
 }
 
-void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr,
-		size_t size, enum dma_data_direction dir)
+void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size,
+		enum dma_data_direction dir)
 {
 	__dma_sync_page(paddr, size, dir);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/mm/drmem.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/mm/drmem.c
@@ -362,10 +362,8 @@
 	if (!drmem_info->lmbs)
 		return;
 
-	for_each_drmem_lmb(lmb) {
+	for_each_drmem_lmb(lmb)
 		read_drconf_v1_cell(lmb, &prop);
-		lmb_set_nid(lmb);
-	}
 }
 
 static void __init init_drmem_v2_lmbs(const __be32 *prop)
@@ -410,8 +408,6 @@
 
 			lmb->aa_index = dr_cell.aa_index;
 			lmb->flags = dr_cell.flags;
-
-			lmb_set_nid(lmb);
 		}
 	}
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/mm/fault.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/mm/fault.c
@@ -204,9 +204,7 @@
 {
 	int is_exec = TRAP(regs) == 0x400;
 
-	/* NX faults set DSISR_PROTFAULT on the 8xx, DSISR_NOEXEC_OR_G on others */
-	if (is_exec && (error_code & (DSISR_NOEXEC_OR_G | DSISR_KEYFAULT |
-				      DSISR_PROTFAULT))) {
+	if (is_exec) {
 		pr_crit_ratelimited("kernel tried to execute %s page (%lx) - exploit attempt? (uid: %d)\n",
 				    address >= TASK_SIZE ? "exec-protected" : "user",
 				    address,
@@ -233,7 +231,7 @@
 
 	// Read/write fault in a valid region (the exception table search passed
 	// above), but blocked by KUAP is bad, it can never succeed.
-	if (bad_kuap_fault(regs, is_write))
+	if (bad_kuap_fault(regs, address, is_write))
 		return true;
 
 	// What's left? Kernel fault on user in well defined regions (extable
@@ -241,6 +239,9 @@
 	return false;
 }
 
+// This comes from 64-bit struct rt_sigframe + __SIGNAL_FRAMESIZE
+#define SIGFRAME_MAX_SIZE	(4096 + 128)
+
 static bool bad_stack_expansion(struct pt_regs *regs, unsigned long address,
 				struct vm_area_struct *vma, unsigned int flags,
 				bool *must_retry)
@@ -248,7 +249,7 @@
 	/*
 	 * N.B. The POWER/Open ABI allows programs to access up to
 	 * 288 bytes below the stack pointer.
-	 * The kernel signal delivery code writes up to about 1.5kB
+	 * The kernel signal delivery code writes a bit over 4KB
 	 * below the stack pointer (r1) before decrementing it.
 	 * The exec code can write slightly over 640kB to the stack
 	 * before setting the user r1.  Thus we allow the stack to
@@ -273,7 +274,7 @@
 		 * between the last mapped region and the stack will
 		 * expand the stack rather than segfaulting.
 		 */
-		if (address + 2048 >= uregs->gpr[1])
+		if (address + SIGFRAME_MAX_SIZE >= uregs->gpr[1])
 			return false;
 
 		if ((flags & FAULT_FLAG_WRITE) && (flags & FAULT_FLAG_USER) &&
@@ -346,7 +347,6 @@
 static inline void cmo_account_page_fault(void) { }
 #endif /* CONFIG_PPC_SMLPAR */
 
-#ifdef CONFIG_PPC_BOOK3S
 static void sanity_check_fault(bool is_write, bool is_user,
 			       unsigned long error_code, unsigned long address)
 {
@@ -354,12 +354,18 @@
 	 * Userspace trying to access kernel address, we get PROTFAULT for that.
 	 */
 	if (is_user && address >= TASK_SIZE) {
+		if ((long)address == -1)
+			return;
+
 		pr_crit_ratelimited("%s[%d]: User access of kernel address (%lx) - exploit attempt? (uid: %d)\n",
 				   current->comm, current->pid, address,
 				   from_kuid(&init_user_ns, current_uid()));
 		return;
 	}
 
+	if (!IS_ENABLED(CONFIG_PPC_BOOK3S))
+		return;
+
 	/*
 	 * For hash translation mode, we should never get a
 	 * PROTFAULT. Any update to pte to reduce access will result in us
@@ -394,10 +400,6 @@
 
 	WARN_ON_ONCE(error_code & DSISR_PROTFAULT);
 }
-#else
-static void sanity_check_fault(bool is_write, bool is_user,
-			       unsigned long error_code, unsigned long address) { }
-#endif /* CONFIG_PPC_BOOK3S */
 
 /*
  * Define the correct "is_write" bit in error_code based
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/mm/hugetlbpage.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/mm/hugetlbpage.c
@@ -53,20 +53,24 @@
 	if (pshift >= pdshift) {
 		cachep = PGT_CACHE(PTE_T_ORDER);
 		num_hugepd = 1 << (pshift - pdshift);
+		new = NULL;
 	} else if (IS_ENABLED(CONFIG_PPC_8xx)) {
-		cachep = PGT_CACHE(PTE_INDEX_SIZE);
+		cachep = NULL;
 		num_hugepd = 1;
+		new = pte_alloc_one(mm);
 	} else {
 		cachep = PGT_CACHE(pdshift - pshift);
 		num_hugepd = 1;
+		new = NULL;
 	}
 
-	if (!cachep) {
+	if (!cachep && !new) {
 		WARN_ONCE(1, "No page table cache created for hugetlb tables");
 		return -ENOMEM;
 	}
 
-	new = kmem_cache_alloc(cachep, pgtable_gfp_flags(mm, GFP_KERNEL));
+	if (cachep)
+		new = kmem_cache_alloc(cachep, pgtable_gfp_flags(mm, GFP_KERNEL));
 
 	BUG_ON(pshift > HUGEPD_SHIFT_MASK);
 	BUG_ON((unsigned long)new & HUGEPD_SHIFT_MASK);
@@ -97,7 +101,10 @@
 	if (i < num_hugepd) {
 		for (i = i - 1 ; i >= 0; i--, hpdp--)
 			*hpdp = __hugepd(0);
-		kmem_cache_free(cachep, new);
+		if (cachep)
+			kmem_cache_free(cachep, new);
+		else
+			pte_free(mm, new);
 	} else {
 		kmemleak_ignore(new);
 	}
@@ -324,8 +331,7 @@
 	if (shift >= pdshift)
 		hugepd_free(tlb, hugepte);
 	else if (IS_ENABLED(CONFIG_PPC_8xx))
-		pgtable_free_tlb(tlb, hugepte,
-				 get_hugepd_cache_index(PTE_INDEX_SIZE));
+		pgtable_free_tlb(tlb, hugepte, 0);
 	else
 		pgtable_free_tlb(tlb, hugepte,
 				 get_hugepd_cache_index(pdshift - shift));
@@ -639,12 +645,13 @@
 		 * if we have pdshift and shift value same, we don't
 		 * use pgt cache for hugepd.
 		 */
-		if (pdshift > shift && IS_ENABLED(CONFIG_PPC_8xx))
-			pgtable_cache_add(PTE_INDEX_SIZE);
-		else if (pdshift > shift)
-			pgtable_cache_add(pdshift - shift);
-		else if (IS_ENABLED(CONFIG_PPC_FSL_BOOK3E) || IS_ENABLED(CONFIG_PPC_8xx))
+		if (pdshift > shift) {
+			if (!IS_ENABLED(CONFIG_PPC_8xx))
+				pgtable_cache_add(pdshift - shift);
+		} else if (IS_ENABLED(CONFIG_PPC_FSL_BOOK3E) ||
+			   IS_ENABLED(CONFIG_PPC_8xx)) {
 			pgtable_cache_add(PTE_T_ORDER);
+		}
 
 		configured = true;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/mm/init-common.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/mm/init-common.c
@@ -104,7 +104,7 @@
 	 * as to leave enough 0 bits in the address to contain it. */
 	unsigned long minalign = max(MAX_PGTABLE_INDEX_SIZE + 1,
 				     HUGEPD_SHIFT_MASK + 1);
-	struct kmem_cache *new;
+	struct kmem_cache *new = NULL;
 
 	/* It would be nice if this was a BUILD_BUG_ON(), but at the
 	 * moment, gcc doesn't seem to recognize is_power_of_2 as a
@@ -117,7 +117,8 @@
 
 	align = max_t(unsigned long, align, minalign);
 	name = kasprintf(GFP_KERNEL, "pgtable-2^%d", shift);
-	new = kmem_cache_create(name, table_size, align, 0, ctor(shift));
+	if (name)
+		new = kmem_cache_create(name, table_size, align, 0, ctor(shift));
 	if (!new)
 		panic("Could not allocate pgtable cache for order %d", shift);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/mm/init_64.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/mm/init_64.c
@@ -178,7 +178,7 @@
 	unsigned long nr_pfn = page_size / sizeof(struct page);
 	unsigned long start_pfn = page_to_pfn((struct page *)start);
 
-	if ((start_pfn + nr_pfn) > altmap->end_pfn)
+	if ((start_pfn + nr_pfn - 1) > altmap->end_pfn)
 		return true;
 
 	if (start_pfn < altmap->base_pfn)
@@ -279,8 +279,7 @@
 	start = _ALIGN_DOWN(start, page_size);
 	if (altmap) {
 		alt_start = altmap->base_pfn;
-		alt_end = altmap->base_pfn + altmap->reserve +
-			  altmap->free + altmap->alloc + altmap->align;
+		alt_end = altmap->base_pfn + altmap->reserve + altmap->free;
 	}
 
 	pr_debug("vmemmap_free %lx...%lx\n", start, end);
@@ -415,9 +414,16 @@
 	if (!(mfmsr() & MSR_HV))
 		early_check_vec5();
 
-	if (early_radix_enabled())
+	if (early_radix_enabled()) {
 		radix__early_init_devtree();
-	else
+		/*
+		 * We have finalized the translation we are going to use by now.
+		 * Radix mode is not limited by RMA / VRMA addressing.
+		 * Hence don't limit memblock allocations.
+		 */
+		ppc64_rma_size = ULONG_MAX;
+		memblock_set_current_limit(MEMBLOCK_ALLOC_ANYWHERE);
+	} else
 		hash__early_init_devtree();
 }
 #endif /* CONFIG_PPC_BOOK3S_64 */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/mm/kasan/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/mm/kasan/Makefile
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 
 KASAN_SANITIZE := n
+KCOV_INSTRUMENT := n
 
 obj-$(CONFIG_PPC32)           += kasan_init_32.o
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/mm/kasan/kasan_init_32.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/mm/kasan/kasan_init_32.c
@@ -90,8 +90,10 @@
 	if (ret)
 		return ret;
 
-	if (!slab_is_available())
+	if (!slab_is_available()) {
+		k_start = k_start & PAGE_MASK;
 		block = memblock_alloc(k_end - k_start, PAGE_SIZE);
+	}
 
 	for (k_cur = k_start & PAGE_MASK; k_cur < k_end; k_cur += PAGE_SIZE) {
 		pmd_t *pmd = pmd_offset(pud_offset(pgd_offset_k(k_cur), k_cur), k_cur);
@@ -117,11 +119,11 @@
 
 	kasan_populate_pte(kasan_early_shadow_pte, prot);
 
-	for (k_cur = k_start & PAGE_MASK; k_cur < k_end; k_cur += PAGE_SIZE) {
+	for (k_cur = k_start & PAGE_MASK; k_cur != k_end; k_cur += PAGE_SIZE) {
 		pmd_t *pmd = pmd_offset(pud_offset(pgd_offset_k(k_cur), k_cur), k_cur);
 		pte_t *ptep = pte_offset_kernel(pmd, k_cur);
 
-		if ((pte_val(*ptep) & PTE_RPN_MASK) != pa)
+		if (pte_page(*ptep) != virt_to_page(lm_alias(kasan_early_shadow_page)))
 			continue;
 
 		__set_pte_at(&init_mm, k_cur, ptep, pfn_pte(PHYS_PFN(pa), prot), 0);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/mm/mem.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/mm/mem.c
@@ -48,6 +48,7 @@
 #include <asm/fixmap.h>
 #include <asm/swiotlb.h>
 #include <asm/rtas.h>
+#include <asm/ftrace.h>
 
 #include <mm/mmu_decl.h>
 
@@ -104,6 +105,27 @@
 	return -ENODEV;
 }
 
+#define FLUSH_CHUNK_SIZE SZ_1G
+/**
+ * flush_dcache_range_chunked(): Write any modified data cache blocks out to
+ * memory and invalidate them, in chunks of up to FLUSH_CHUNK_SIZE
+ * Does not invalidate the corresponding instruction cache blocks.
+ *
+ * @start: the start address
+ * @stop: the stop address (exclusive)
+ * @chunk: the max size of the chunks
+ */
+static void flush_dcache_range_chunked(unsigned long start, unsigned long stop,
+				       unsigned long chunk)
+{
+	unsigned long i;
+
+	for (i = start; i < stop; i += chunk) {
+		flush_dcache_range(i, min(stop, i + chunk));
+		cond_resched();
+	}
+}
+
 int __ref arch_add_memory(int nid, u64 start, u64 size,
 			struct mhp_restrictions *restrictions)
 {
@@ -120,7 +142,8 @@
 			start, start + size, rc);
 		return -EFAULT;
 	}
-	flush_dcache_range(start, start + size);
+
+	flush_dcache_range_chunked(start, start + size, FLUSH_CHUNK_SIZE);
 
 	return __add_pages(nid, start_pfn, nr_pages, restrictions);
 }
@@ -130,14 +153,14 @@
 {
 	unsigned long start_pfn = start >> PAGE_SHIFT;
 	unsigned long nr_pages = size >> PAGE_SHIFT;
-	struct page *page = pfn_to_page(start_pfn) + vmem_altmap_offset(altmap);
 	int ret;
 
-	__remove_pages(page_zone(page), start_pfn, nr_pages, altmap);
+	__remove_pages(start_pfn, nr_pages, altmap);
 
 	/* Remove htab bolted mappings for this section of memory */
 	start = (unsigned long)__va(start);
-	flush_dcache_range(start, start + size);
+	flush_dcache_range_chunked(start, start + size, FLUSH_CHUNK_SIZE);
+
 	ret = remove_section_mapping(start, start + size);
 	WARN_ON_ONCE(ret);
 
@@ -260,6 +283,14 @@
 	BUILD_BUG_ON(MMU_PAGE_COUNT > 16);
 
 #ifdef CONFIG_SWIOTLB
+	/*
+	 * Some platforms (e.g. 85xx) limit DMA-able memory way below
+	 * 4G. We force memblock to bottom-up mode to ensure that the
+	 * memory allocated in swiotlb_init() is DMA-able.
+	 * As it's the last memblock allocation, no need to reset it
+	 * back to to-down.
+	 */
+	memblock_set_bottom_up(true);
 	swiotlb_init(0);
 #endif
 
@@ -316,7 +347,124 @@
 	mark_initmem_nx();
 	init_mem_is_free = true;
 	free_initmem_default(POISON_FREE_INITMEM);
+	ftrace_free_init_tramp();
+}
+
+/**
+ * flush_coherent_icache() - if a CPU has a coherent icache, flush it
+ * @addr: The base address to use (can be any valid address, the whole cache will be flushed)
+ * Return true if the cache was flushed, false otherwise
+ */
+static inline bool flush_coherent_icache(unsigned long addr)
+{
+	/*
+	 * For a snooping icache, we still need a dummy icbi to purge all the
+	 * prefetched instructions from the ifetch buffers. We also need a sync
+	 * before the icbi to order the the actual stores to memory that might
+	 * have modified instructions with the icbi.
+	 */
+	if (cpu_has_feature(CPU_FTR_COHERENT_ICACHE)) {
+		mb(); /* sync */
+		allow_read_from_user((const void __user *)addr, L1_CACHE_BYTES);
+		icbi((void *)addr);
+		prevent_read_from_user((const void __user *)addr, L1_CACHE_BYTES);
+		mb(); /* sync */
+		isync();
+		return true;
+	}
+
+	return false;
+}
+
+/**
+ * invalidate_icache_range() - Flush the icache by issuing icbi across an address range
+ * @start: the start address
+ * @stop: the stop address (exclusive)
+ */
+static void invalidate_icache_range(unsigned long start, unsigned long stop)
+{
+	unsigned long shift = l1_icache_shift();
+	unsigned long bytes = l1_icache_bytes();
+	char *addr = (char *)(start & ~(bytes - 1));
+	unsigned long size = stop - (unsigned long)addr + (bytes - 1);
+	unsigned long i;
+
+	for (i = 0; i < size >> shift; i++, addr += bytes)
+		icbi(addr);
+
+	mb(); /* sync */
+	isync();
+}
+
+/**
+ * flush_icache_range: Write any modified data cache blocks out to memory
+ * and invalidate the corresponding blocks in the instruction cache
+ *
+ * Generic code will call this after writing memory, before executing from it.
+ *
+ * @start: the start address
+ * @stop: the stop address (exclusive)
+ */
+void flush_icache_range(unsigned long start, unsigned long stop)
+{
+	if (flush_coherent_icache(start))
+		return;
+
+	clean_dcache_range(start, stop);
+
+	if (IS_ENABLED(CONFIG_44x)) {
+		/*
+		 * Flash invalidate on 44x because we are passed kmapped
+		 * addresses and this doesn't work for userspace pages due to
+		 * the virtually tagged icache.
+		 */
+		iccci((void *)start);
+		mb(); /* sync */
+		isync();
+	} else
+		invalidate_icache_range(start, stop);
+}
+EXPORT_SYMBOL(flush_icache_range);
+
+#if !defined(CONFIG_PPC_8xx) && !defined(CONFIG_PPC64)
+/**
+ * flush_dcache_icache_phys() - Flush a page by it's physical address
+ * @physaddr: the physical address of the page
+ */
+static void flush_dcache_icache_phys(unsigned long physaddr)
+{
+	unsigned long bytes = l1_dcache_bytes();
+	unsigned long nb = PAGE_SIZE / bytes;
+	unsigned long addr = physaddr & PAGE_MASK;
+	unsigned long msr, msr0;
+	unsigned long loop1 = addr, loop2 = addr;
+
+	msr0 = mfmsr();
+	msr = msr0 & ~MSR_DR;
+	/*
+	 * This must remain as ASM to prevent potential memory accesses
+	 * while the data MMU is disabled
+	 */
+	asm volatile(
+		"   mtctr %2;\n"
+		"   mtmsr %3;\n"
+		"   isync;\n"
+		"0: dcbst   0, %0;\n"
+		"   addi    %0, %0, %4;\n"
+		"   bdnz    0b;\n"
+		"   sync;\n"
+		"   mtctr %2;\n"
+		"1: icbi    0, %1;\n"
+		"   addi    %1, %1, %4;\n"
+		"   bdnz    1b;\n"
+		"   sync;\n"
+		"   mtmsr %5;\n"
+		"   isync;\n"
+		: "+&r" (loop1), "+&r" (loop2)
+		: "r" (nb), "r" (msr), "i" (bytes), "r" (msr0)
+		: "ctr", "memory");
 }
+#endif // !defined(CONFIG_PPC_8xx) && !defined(CONFIG_PPC64)
 
 /*
  * This is called when a page has been modified by the kernel.
@@ -350,12 +498,46 @@
 		__flush_dcache_icache(start);
 		kunmap_atomic(start);
 	} else {
-		__flush_dcache_icache_phys(page_to_pfn(page) << PAGE_SHIFT);
+		unsigned long addr = page_to_pfn(page) << PAGE_SHIFT;
+
+		if (flush_coherent_icache(addr))
+			return;
+		flush_dcache_icache_phys(addr);
 	}
 #endif
 }
 EXPORT_SYMBOL(flush_dcache_icache_page);
 
+/**
+ * __flush_dcache_icache(): Flush a particular page from the data cache to RAM.
+ * Note: this is necessary because the instruction cache does *not*
+ * snoop from the data cache.
+ *
+ * @page: the address of the page to flush
+ */
+void __flush_dcache_icache(void *p)
+{
+	unsigned long addr = (unsigned long)p;
+
+	if (flush_coherent_icache(addr))
+		return;
+
+	clean_dcache_range(addr, addr + PAGE_SIZE);
+
+	/*
+	 * We don't flush the icache on 44x. Those have a virtual icache and we
+	 * don't have access to the virtual address here (it's not the page
+	 * vaddr but where it's mapped in user space). The flushing of the
+	 * icache on these is handled elsewhere, when a change in the address
+	 * space occurs, before returning to user space.
+	 */
+
+	if (mmu_has_feature(MMU_FTR_TYPE_44x))
+		return;
+
+	invalidate_icache_range(addr, addr + PAGE_SIZE);
+}
+
 void clear_user_page(void *page, unsigned long vaddr, struct page *pg)
 {
 	clear_page(page);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/mm/mmu_context.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/mm/mmu_context.c
@@ -79,7 +79,7 @@
 	 * context
 	 */
 	if (cpu_has_feature(CPU_FTR_ALTIVEC))
-		asm volatile ("dssall");
+		asm volatile (PPC_DSSALL);
 
 	if (new_on_cpu)
 		radix_kvm_prefetch_workaround(next);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/mm/nohash/tlb_low.S
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/mm/nohash/tlb_low.S
@@ -397,7 +397,7 @@
  * extern void loadcam_entry(unsigned int index)
  *
  * Load TLBCAM[index] entry in to the L2 CAM MMU
- * Must preserve r7, r8, r9, and r10
+ * Must preserve r7, r8, r9, r10 and r11
  */
 _GLOBAL(loadcam_entry)
 	mflr	r5
@@ -433,6 +433,10 @@
  */
 _GLOBAL(loadcam_multi)
 	mflr	r8
+	/* Don't switch to AS=1 if already there */
+	mfmsr	r11
+	andi.	r11,r11,MSR_IS
+	bne	10f
 
 	/*
 	 * Set up temporary TLB entry that is the same as what we're
@@ -458,6 +462,7 @@
 	mtmsr	r6
 	isync
 
+10:
 	mr	r9,r3
 	add	r10,r3,r4
 2:	bl	loadcam_entry
@@ -466,6 +471,10 @@
 	mr	r3,r9
 	blt	2b
 
+	/* Don't return to AS=0 if we were in AS=1 at function start */
+	andi.	r11,r11,MSR_IS
+	bne	3f
+
 	/* Return to AS=0 and clear the temporary entry */
 	mfmsr	r6
 	rlwinm.	r6,r6,0,~(MSR_IS|MSR_DS)
@@ -481,6 +490,7 @@
 	tlbwe
 	isync
 
+3:
 	mtlr	r8
 	blr
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/mm/pgtable_32.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/mm/pgtable_32.c
@@ -207,7 +207,7 @@
 	unsigned long numpages = PFN_UP((unsigned long)_einittext) -
 				 PFN_DOWN((unsigned long)_sinittext);
 
-	if (v_block_mapped((unsigned long)_stext + 1))
+	if (v_block_mapped((unsigned long)_sinittext))
 		mmu_mark_initmem_nx();
 	else
 		change_page_attr(page, numpages, PAGE_KERNEL);
@@ -219,8 +219,9 @@
 	struct page *page;
 	unsigned long numpages;
 
-	if (v_block_mapped((unsigned long)_sinittext)) {
+	if (v_block_mapped((unsigned long)_stext + 1)) {
 		mmu_mark_rodata_ro();
+		ptdump_check_wx();
 		return;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/mm/ptdump/hashpagetable.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/mm/ptdump/hashpagetable.c
@@ -259,7 +259,7 @@
 	for (i = 0; i < HPTES_PER_GROUP; i += 4, hpte_group += 4) {
 		lpar_rc = plpar_pte_read_4(0, hpte_group, (void *)ptes);
 
-		if (lpar_rc != H_SUCCESS)
+		if (lpar_rc)
 			continue;
 		for (j = 0; j < 4; j++) {
 			if (HPTE_V_COMPARE(ptes[j].v, want_v) &&
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/mm/ptdump/ptdump.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/mm/ptdump/ptdump.c
@@ -58,6 +58,7 @@
 	unsigned long start_address;
 	unsigned long start_pa;
 	unsigned long last_pa;
+	unsigned long page_size;
 	unsigned int level;
 	u64 current_flags;
 	bool check_wx;
@@ -155,9 +156,9 @@
 #endif
 
 	pt_dump_seq_printf(st->seq, REG "-" REG " ", st->start_address, addr - 1);
-	if (st->start_pa == st->last_pa && st->start_address + PAGE_SIZE != addr) {
+	if (st->start_pa == st->last_pa && st->start_address + st->page_size != addr) {
 		pt_dump_seq_printf(st->seq, "[" REG "]", st->start_pa);
-		delta = PAGE_SIZE >> 10;
+		delta = st->page_size >> 10;
 	} else {
 		pt_dump_seq_printf(st->seq, " " REG " ", st->start_pa);
 		delta = (addr - st->start_address) >> 10;
@@ -173,10 +174,12 @@
 
 static void note_prot_wx(struct pg_state *st, unsigned long addr)
 {
+	pte_t pte = __pte(st->current_flags);
+
 	if (!IS_ENABLED(CONFIG_PPC_DEBUG_WX) || !st->check_wx)
 		return;
 
-	if (!((st->current_flags & pgprot_val(PAGE_KERNEL_X)) == pgprot_val(PAGE_KERNEL_X)))
+	if (!pte_write(pte) || !pte_exec(pte))
 		return;
 
 	WARN_ONCE(1, "powerpc/mm: Found insecure W+X mapping at address %p/%pS\n",
@@ -186,7 +189,7 @@
 }
 
 static void note_page(struct pg_state *st, unsigned long addr,
-	       unsigned int level, u64 val)
+	       unsigned int level, u64 val, unsigned long page_size)
 {
 	u64 flag = val & pg_level[level].mask;
 	u64 pa = val & PTE_RPN_MASK;
@@ -198,6 +201,7 @@
 		st->start_address = addr;
 		st->start_pa = pa;
 		st->last_pa = pa;
+		st->page_size = page_size;
 		pt_dump_seq_printf(st->seq, "---[ %s ]---\n", st->marker->name);
 	/*
 	 * Dump the section of virtual memory when:
@@ -209,7 +213,7 @@
 	 */
 	} else if (flag != st->current_flags || level != st->level ||
 		   addr >= st->marker[1].start_address ||
-		   (pa != st->last_pa + PAGE_SIZE &&
+		   (pa != st->last_pa + st->page_size &&
 		    (pa != st->start_pa || st->start_pa != st->last_pa))) {
 
 		/* Check the PTE flags */
@@ -237,6 +241,7 @@
 		st->start_address = addr;
 		st->start_pa = pa;
 		st->last_pa = pa;
+		st->page_size = page_size;
 		st->current_flags = flag;
 		st->level = level;
 	} else {
@@ -252,7 +257,7 @@
 
 	for (i = 0; i < PTRS_PER_PTE; i++, pte++) {
 		addr = start + i * PAGE_SIZE;
-		note_page(st, addr, 4, pte_val(*pte));
+		note_page(st, addr, 4, pte_val(*pte), PAGE_SIZE);
 
 	}
 }
@@ -269,7 +274,7 @@
 			/* pmd exists */
 			walk_pte(st, pmd, addr);
 		else
-			note_page(st, addr, 3, pmd_val(*pmd));
+			note_page(st, addr, 3, pmd_val(*pmd), PMD_SIZE);
 	}
 }
 
@@ -285,7 +290,7 @@
 			/* pud exists */
 			walk_pmd(st, pud, addr);
 		else
-			note_page(st, addr, 2, pud_val(*pud));
+			note_page(st, addr, 2, pud_val(*pud), PUD_SIZE);
 	}
 }
 
@@ -304,7 +309,7 @@
 			/* pgd exists */
 			walk_pud(st, pgd, addr);
 		else
-			note_page(st, addr, 1, pgd_val(*pgd));
+			note_page(st, addr, 1, pgd_val(*pgd), PGDIR_SIZE);
 	}
 }
 
@@ -359,7 +364,7 @@
 
 	/* Traverse kernel page tables */
 	walk_pagetables(&st);
-	note_page(&st, 0, 0, 0);
+	note_page(&st, 0, 0, 0, 0);
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/mm/ptdump/shared.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/mm/ptdump/shared.c
@@ -17,9 +17,9 @@
 		.clear	= "    ",
 	}, {
 		.mask	= _PAGE_RW,
-		.val	= _PAGE_RW,
-		.set	= "rw",
-		.clear	= "r ",
+		.val	= 0,
+		.set	= "r ",
+		.clear	= "rw",
 	}, {
 		.mask	= _PAGE_EXEC,
 		.val	= _PAGE_EXEC,
@@ -31,6 +31,11 @@
 		.set	= "present",
 		.clear	= "       ",
 	}, {
+		.mask	= _PAGE_COHERENT,
+		.val	= _PAGE_COHERENT,
+		.set	= "coherent",
+		.clear	= "        ",
+	}, {
 		.mask	= _PAGE_GUARDED,
 		.val	= _PAGE_GUARDED,
 		.set	= "guarded",
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/mm/slice.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/mm/slice.c
@@ -50,7 +50,7 @@
 
 #endif
 
-static inline bool slice_addr_is_low(unsigned long addr)
+static inline notrace bool slice_addr_is_low(unsigned long addr)
 {
 	u64 tmp = (u64)addr;
 
@@ -659,7 +659,7 @@
 				       mm_ctx_user_psize(&current->mm->context), 1);
 }
 
-unsigned int get_slice_psize(struct mm_struct *mm, unsigned long addr)
+unsigned int notrace get_slice_psize(struct mm_struct *mm, unsigned long addr)
 {
 	unsigned char *psizes;
 	int index, mask_index;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/net/bpf_jit.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/net/bpf_jit.h
@@ -11,6 +11,7 @@
 #ifndef __ASSEMBLY__
 
 #include <asm/types.h>
+#include <asm/code-patching.h>
 
 #ifdef PPC64_ELF_ABI_v1
 #define FUNCTION_DESCR_SIZE	24
@@ -180,13 +181,26 @@
 #define PPC_NEG(d, a)		EMIT(PPC_INST_NEG | ___PPC_RT(d) | ___PPC_RA(a))
 
 /* Long jump; (unconditional 'branch') */
-#define PPC_JMP(dest)		EMIT(PPC_INST_BRANCH |			      \
-				     (((dest) - (ctx->idx * 4)) & 0x03fffffc))
+#define PPC_JMP(dest)							      \
+	do {								      \
+		long offset = (long)(dest) - (ctx->idx * 4);		      \
+		if (!is_offset_in_branch_range(offset)) {		      \
+			pr_err_ratelimited("Branch offset 0x%lx (@%u) out of range\n", offset, ctx->idx);			\
+			return -ERANGE;					      \
+		}							      \
+		EMIT(PPC_INST_BRANCH | (offset & 0x03fffffc));		      \
+	} while (0)
 /* "cond" here covers BO:BI fields. */
-#define PPC_BCC_SHORT(cond, dest)	EMIT(PPC_INST_BRANCH_COND |	      \
-					     (((cond) & 0x3ff) << 16) |	      \
-					     (((dest) - (ctx->idx * 4)) &     \
-					      0xfffc))
+#define PPC_BCC_SHORT(cond, dest)					      \
+	do {								      \
+		long offset = (long)(dest) - (ctx->idx * 4);		      \
+		if (!is_offset_in_cond_branch_range(offset)) {		      \
+			pr_err_ratelimited("Conditional branch offset 0x%lx (@%u) out of range\n", offset, ctx->idx);		\
+			return -ERANGE;					      \
+		}							      \
+		EMIT(PPC_INST_BRANCH_COND | (((cond) & 0x3ff) << 16) | (offset & 0xfffc));					\
+	} while (0)
+
 /* Sign-extended 32-bit immediate load */
 #define PPC_LI32(d, i)		do {					      \
 		if ((int)(uintptr_t)(i) >= -32768 &&			      \
@@ -225,11 +239,6 @@
 #define PPC_FUNC_ADDR(d,i) do { PPC_LI32(d, i); } while(0)
 #endif
 
-static inline bool is_nearbranch(int offset)
-{
-	return (offset < 32768) && (offset >= -32768);
-}
-
 /*
  * The fly in the ointment of code size changing from pass to pass is
  * avoided by padding the short branch case with a NOP.	 If code size differs
@@ -238,7 +247,7 @@
  * state.
  */
 #define PPC_BCC(cond, dest)	do {					      \
-		if (is_nearbranch((dest) - (ctx->idx * 4))) {		      \
+		if (is_offset_in_cond_branch_range((long)(dest) - (ctx->idx * 4))) {	\
 			PPC_BCC_SHORT(cond, dest);			      \
 			PPC_NOP();					      \
 		} else {						      \
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/net/bpf_jit64.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/net/bpf_jit64.h
@@ -16,18 +16,18 @@
  * with our redzone usage.
  *
  *		[	prev sp		] <-------------
- *		[   nv gpr save area	] 6*8		|
+ *		[   nv gpr save area	] 5*8		|
  *		[    tail_call_cnt	] 8		|
- *		[    local_tmp_var	] 8		|
+ *		[    local_tmp_var	] 16		|
  * fp (r31) -->	[   ebpf stack space	] upto 512	|
  *		[     frame header	] 32/112	|
  * sp (r1) --->	[    stack pointer	] --------------
  */
 
 /* for gpr non volatile registers BPG_REG_6 to 10 */
-#define BPF_PPC_STACK_SAVE	(6*8)
+#define BPF_PPC_STACK_SAVE	(5*8)
 /* for bpf JIT code internal usage */
-#define BPF_PPC_STACK_LOCALS	16
+#define BPF_PPC_STACK_LOCALS	24
 /* stack frame excluding BPF stack, ensure this is quadword aligned */
 #define BPF_PPC_STACKFRAME	(STACK_FRAME_MIN_SIZE + \
 				 BPF_PPC_STACK_LOCALS + BPF_PPC_STACK_SAVE)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/net/bpf_jit_comp64.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/net/bpf_jit_comp64.c
@@ -15,6 +15,7 @@
 #include <linux/if_vlan.h>
 #include <asm/kprobes.h>
 #include <linux/bpf.h>
+#include <asm/security_features.h>
 
 #include "bpf_jit64.h"
 
@@ -56,9 +57,9 @@
  *		[	prev sp		] <-------------
  *		[	  ...       	] 		|
  * sp (r1) --->	[    stack pointer	] --------------
- *		[   nv gpr save area	] 6*8
+ *		[   nv gpr save area	] 5*8
  *		[    tail_call_cnt	] 8
- *		[    local_tmp_var	] 8
+ *		[    local_tmp_var	] 16
  *		[   unused red zone	] 208 bytes protected
  */
 static int bpf_jit_stack_local(struct codegen_context *ctx)
@@ -66,12 +67,12 @@
 	if (bpf_has_stack_frame(ctx))
 		return STACK_FRAME_MIN_SIZE + ctx->stack_size;
 	else
-		return -(BPF_PPC_STACK_SAVE + 16);
+		return -(BPF_PPC_STACK_SAVE + 24);
 }
 
 static int bpf_jit_stack_tailcallcnt(struct codegen_context *ctx)
 {
-	return bpf_jit_stack_local(ctx) + 8;
+	return bpf_jit_stack_local(ctx) + 16;
 }
 
 static int bpf_jit_stack_offsetof(struct codegen_context *ctx, int reg)
@@ -224,7 +225,7 @@
 	PPC_BLRL();
 }
 
-static void bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 out)
+static int bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 out)
 {
 	/*
 	 * By now, the eBPF program has already setup parameters in r3, r4 and r5
@@ -285,14 +286,39 @@
 	bpf_jit_emit_common_epilogue(image, ctx);
 
 	PPC_BCTR();
+
 	/* out: */
+	return 0;
 }
 
+/*
+ * We spill into the redzone always, even if the bpf program has its own stackframe.
+ * Offsets hardcoded based on BPF_PPC_STACK_SAVE -- see bpf_jit_stack_local()
+ */
+void bpf_stf_barrier(void);
+
+asm (
+"		.global bpf_stf_barrier		;"
+"	bpf_stf_barrier:			;"
+"		std	21,-64(1)		;"
+"		std	22,-56(1)		;"
+"		sync				;"
+"		ld	21,-64(1)		;"
+"		ld	22,-56(1)		;"
+"		ori	31,31,0			;"
+"		.rept 14			;"
+"		b	1f			;"
+"	1:					;"
+"		.endr				;"
+"		blr				;"
+);
+
 /* Assemble the body code between the prologue & epilogue */
 static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
 			      struct codegen_context *ctx,
 			      u32 *addrs, bool extra_pass)
 {
+	enum stf_barrier_type stf_barrier = stf_barrier_type_get();
 	const struct bpf_insn *insn = fp->insnsi;
 	int flen = fp->len;
 	int i, ret;
@@ -347,18 +373,25 @@
 			PPC_SUB(dst_reg, dst_reg, src_reg);
 			goto bpf_alu32_trunc;
 		case BPF_ALU | BPF_ADD | BPF_K: /* (u32) dst += (u32) imm */
-		case BPF_ALU | BPF_SUB | BPF_K: /* (u32) dst -= (u32) imm */
 		case BPF_ALU64 | BPF_ADD | BPF_K: /* dst += imm */
+			if (!imm) {
+				goto bpf_alu32_trunc;
+			} else if (imm >= -32768 && imm < 32768) {
+				PPC_ADDI(dst_reg, dst_reg, IMM_L(imm));
+			} else {
+				PPC_LI32(b2p[TMP_REG_1], imm);
+				PPC_ADD(dst_reg, dst_reg, b2p[TMP_REG_1]);
+			}
+			goto bpf_alu32_trunc;
+		case BPF_ALU | BPF_SUB | BPF_K: /* (u32) dst -= (u32) imm */
 		case BPF_ALU64 | BPF_SUB | BPF_K: /* dst -= imm */
-			if (BPF_OP(code) == BPF_SUB)
-				imm = -imm;
-			if (imm) {
-				if (imm >= -32768 && imm < 32768)
-					PPC_ADDI(dst_reg, dst_reg, IMM_L(imm));
-				else {
-					PPC_LI32(b2p[TMP_REG_1], imm);
-					PPC_ADD(dst_reg, dst_reg, b2p[TMP_REG_1]);
-				}
+			if (!imm) {
+				goto bpf_alu32_trunc;
+			} else if (imm > -32768 && imm <= 32768) {
+				PPC_ADDI(dst_reg, dst_reg, IMM_L(-imm));
+			} else {
+				PPC_LI32(b2p[TMP_REG_1], imm);
+				PPC_SUB(dst_reg, dst_reg, b2p[TMP_REG_1]);
 			}
 			goto bpf_alu32_trunc;
 		case BPF_ALU | BPF_MUL | BPF_X: /* (u32) dst *= (u32) src */
@@ -408,8 +441,14 @@
 		case BPF_ALU64 | BPF_DIV | BPF_K: /* dst /= imm */
 			if (imm == 0)
 				return -EINVAL;
-			else if (imm == 1)
-				goto bpf_alu32_trunc;
+			if (imm == 1) {
+				if (BPF_OP(code) == BPF_DIV) {
+					goto bpf_alu32_trunc;
+				} else {
+					PPC_LI(dst_reg, 0);
+					break;
+				}
+			}
 
 			PPC_LI32(b2p[TMP_REG_1], imm);
 			switch (BPF_CLASS(code)) {
@@ -645,6 +684,36 @@
 			break;
 
 		/*
+		 * BPF_ST NOSPEC (speculation barrier)
+		 */
+		case BPF_ST | BPF_NOSPEC:
+			if (!security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) ||
+					(!security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR) &&
+					(!security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV) || !cpu_has_feature(CPU_FTR_HVMODE))))
+				break;
+
+			switch (stf_barrier) {
+			case STF_BARRIER_EIEIO:
+				EMIT(0x7c0006ac | 0x02000000);
+				break;
+			case STF_BARRIER_SYNC_ORI:
+				EMIT(PPC_INST_SYNC);
+				PPC_LD(b2p[TMP_REG_1], 13, 0);
+				PPC_ORI(31, 31, 0);
+				break;
+			case STF_BARRIER_FALLBACK:
+				EMIT(PPC_INST_MFLR | ___PPC_RT(b2p[TMP_REG_1]));
+				PPC_LI64(12, dereference_kernel_function_descriptor(bpf_stf_barrier));
+				PPC_MTCTR(12);
+				EMIT(PPC_INST_BCTR | 0x1);
+				PPC_MTLR(b2p[TMP_REG_1]);
+				break;
+			case STF_BARRIER_NONE:
+				break;
+			}
+			break;
+
+		/*
 		 * BPF_ST(X)
 		 */
 		case BPF_STX | BPF_MEM | BPF_B: /* *(u8 *)(dst + off) = src */
@@ -989,7 +1058,9 @@
 		 */
 		case BPF_JMP | BPF_TAIL_CALL:
 			ctx->seen |= SEEN_TAILCALL;
-			bpf_jit_emit_tail_call(image, ctx, addrs[i + 1]);
+			ret = bpf_jit_emit_tail_call(image, ctx, addrs[i + 1]);
+			if (ret < 0)
+				return ret;
 			break;
 
 		default:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/perf/callchain.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/perf/callchain.c
@@ -64,6 +64,7 @@
 		next_sp = fp[0];
 
 		if (next_sp == sp + STACK_INT_FRAME_SIZE &&
+		    validate_sp(sp, current, STACK_INT_FRAME_SIZE) &&
 		    fp[STACK_FRAME_MARKER] == STACK_FRAME_REGS_MARKER) {
 			/*
 			 * This looks like an interrupt frame for an
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/perf/core-book3s.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/perf/core-book3s.c
@@ -133,6 +133,9 @@
 
 bool is_sier_available(void)
 {
+	if (!ppmu)
+		return false;
+
 	if (ppmu->flags & PPMU_HAS_SIER)
 		return true;
 
@@ -1522,9 +1525,16 @@
 	ret = 0;
  out:
 	if (has_branch_stack(event)) {
-		power_pmu_bhrb_enable(event);
-		cpuhw->bhrb_filter = ppmu->bhrb_filter_map(
-					event->attr.branch_sample_type);
+		u64 bhrb_filter = -1;
+
+		if (ppmu->bhrb_filter_map)
+			bhrb_filter = ppmu->bhrb_filter_map(
+				event->attr.branch_sample_type);
+
+		if (bhrb_filter != -1) {
+			cpuhw->bhrb_filter = bhrb_filter;
+			power_pmu_bhrb_enable(event);
+		}
 	}
 
 	perf_pmu_enable(event->pmu);
@@ -1846,7 +1856,6 @@
 	int n;
 	int err;
 	struct cpu_hw_events *cpuhw;
-	u64 bhrb_filter;
 
 	if (!ppmu)
 		return -ENOENT;
@@ -1952,7 +1961,10 @@
 	err = power_check_constraints(cpuhw, events, cflags, n + 1);
 
 	if (has_branch_stack(event)) {
-		bhrb_filter = ppmu->bhrb_filter_map(
+		u64 bhrb_filter = -1;
+
+		if (ppmu->bhrb_filter_map)
+			bhrb_filter = ppmu->bhrb_filter_map(
 					event->attr.branch_sample_type);
 
 		if (bhrb_filter == -1) {
@@ -2065,7 +2077,17 @@
 			left += period;
 			if (left <= 0)
 				left = period;
-			record = siar_valid(regs);
+
+			/*
+			 * If address is not requested in the sample via
+			 * PERF_SAMPLE_IP, just record that sample irrespective
+			 * of SIAR valid check.
+			 */
+			if (event->attr.sample_type & PERF_SAMPLE_IP)
+				record = siar_valid(regs);
+			else
+				record = 1;
+
 			event->hw.last_period = event->hw.sample_period;
 		}
 		if (left < 0x80000000LL)
@@ -2078,6 +2100,17 @@
 	perf_event_update_userpage(event);
 
 	/*
+	 * Due to hardware limitation, sometimes SIAR could sample a kernel
+	 * address even when freeze on supervisor state (kernel) is set in
+	 * MMCR2. Check attr.exclude_kernel and address to drop the sample in
+	 * these cases.
+	 */
+	if (event->attr.exclude_kernel &&
+	    (event->attr.sample_type & PERF_SAMPLE_IP) &&
+	    is_kernel_addr(mfspr(SPRN_SIAR)))
+		record = 0;
+
+	/*
 	 * Finally record data if requested.
 	 */
 	if (record) {
@@ -2106,6 +2139,10 @@
 
 		if (perf_event_overflow(event, &data, regs))
 			power_pmu_stop(event, 0);
+	} else if (period) {
+		/* Account for interrupt in case of invalid SIAR */
+		if (perf_event_account_interrupt(event))
+			power_pmu_stop(event, 0);
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/perf/hv-24x7.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/perf/hv-24x7.c
@@ -1313,7 +1313,7 @@
 	}
 
 	domain = event_get_domain(event);
-	if (domain >= HV_PERF_DOMAIN_MAX) {
+	if (domain  == 0 || domain >= HV_PERF_DOMAIN_MAX) {
 		pr_devel("invalid domain %d\n", domain);
 		return -EINVAL;
 	}
@@ -1400,16 +1400,6 @@
 			h24x7hw = &get_cpu_var(hv_24x7_hw);
 			h24x7hw->events[i] = event;
 			put_cpu_var(h24x7hw);
-			/*
-			 * Clear the event count so we can compute the _change_
-			 * in the 24x7 raw counter value at the end of the txn.
-			 *
-			 * Note that we could alternatively read the 24x7 value
-			 * now and save its value in event->hw.prev_count. But
-			 * that would require issuing a hcall, which would then
-			 * defeat the purpose of using the txn interface.
-			 */
-			local64_set(&event->count, 0);
 		}
 
 		put_cpu_var(hv_24x7_reqb);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/perf/hv-gpci-requests.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/perf/hv-gpci-requests.h
@@ -79,6 +79,7 @@
 )
 #include I(REQUEST_END)
 
+#ifdef ENABLE_EVENTS_COUNTERINFO_V6
 /*
  * Not available for counter_info_version >= 0x8, use
  * run_instruction_cycles_by_partition(0x100) instead.
@@ -92,10 +93,11 @@
 	__count(0x10,	8,	cycles)
 )
 #include I(REQUEST_END)
+#endif
 
 #define REQUEST_NAME system_performance_capabilities
 #define REQUEST_NUM 0x40
-#define REQUEST_IDX_KIND "starting_index=0xffffffffffffffff"
+#define REQUEST_IDX_KIND "starting_index=0xffffffff"
 #include I(REQUEST_BEGIN)
 REQUEST(__field(0,	1,	perf_collect_privileged)
 	__field(0x1,	1,	capability_mask)
@@ -103,6 +105,7 @@
 )
 #include I(REQUEST_END)
 
+#ifdef ENABLE_EVENTS_COUNTERINFO_V6
 #define REQUEST_NAME processor_bus_utilization_abc_links
 #define REQUEST_NUM 0x50
 #define REQUEST_IDX_KIND "hw_chip_id=?"
@@ -194,6 +197,7 @@
 	__count(0x28,	8,	instructions_completed)
 )
 #include I(REQUEST_END)
+#endif
 
 /* Processor_core_power_mode (0x95) skipped, no counters */
 /* Affinity_domain_information_by_virtual_processor (0xA0) skipped,
@@ -223,7 +227,7 @@
 
 #define REQUEST_NAME system_hypervisor_times
 #define REQUEST_NUM 0xF0
-#define REQUEST_IDX_KIND "starting_index=0xffffffffffffffff"
+#define REQUEST_IDX_KIND "starting_index=0xffffffff"
 #include I(REQUEST_BEGIN)
 REQUEST(__count(0,	8,	time_spent_to_dispatch_virtual_processors)
 	__count(0x8,	8,	time_spent_processing_virtual_processor_timers)
@@ -234,7 +238,7 @@
 
 #define REQUEST_NAME system_tlbie_count_and_time
 #define REQUEST_NUM 0xF4
-#define REQUEST_IDX_KIND "starting_index=0xffffffffffffffff"
+#define REQUEST_IDX_KIND "starting_index=0xffffffff"
 #include I(REQUEST_BEGIN)
 REQUEST(__count(0,	8,	tlbie_instructions_issued)
 	/*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/perf/hv-gpci.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/perf/hv-gpci.c
@@ -70,7 +70,7 @@
 
 static struct attribute_group event_group = {
 	.name  = "events",
-	.attrs = hv_gpci_event_attrs,
+	/* .attrs is set in init */
 };
 
 #define HV_CAPS_ATTR(_name, _format)				\
@@ -153,6 +153,20 @@
 
 	ret = plpar_hcall_norets(H_GET_PERF_COUNTER_INFO,
 			virt_to_phys(arg), HGPCI_REQ_BUFFER_SIZE);
+
+	/*
+	 * ret value as 'H_PARAMETER' with detail_rc as 'GEN_BUF_TOO_SMALL',
+	 * specifies that the current buffer size cannot accommodate
+	 * all the information and a partial buffer returned.
+	 * Since in this function we are only accessing data for a given starting index,
+	 * we don't need to accommodate whole data and can get required count by
+	 * accessing first entry data.
+	 * Hence hcall fails only incase the ret value is other than H_SUCCESS or
+	 * H_PARAMETER with detail_rc value as GEN_BUF_TOO_SMALL(0x1B).
+	 */
+	if (ret == H_PARAMETER && be32_to_cpu(arg->params.detail_rc) == 0x1B)
+		ret = 0;
+
 	if (ret) {
 		pr_devel("hcall failed: 0x%lx\n", ret);
 		goto out;
@@ -164,7 +178,7 @@
 	 */
 	count = 0;
 	for (i = offset; i < offset + length; i++)
-		count |= arg->bytes[i] << (i - offset);
+		count |= (u64)(arg->bytes[i]) << ((length - 1 - (i - offset)) * 8);
 
 	*value = count;
 out:
@@ -217,6 +231,7 @@
 {
 	u64 count;
 	u8 length;
+	unsigned long ret;
 
 	/* Not our event */
 	if (event->attr.type != event->pmu->type)
@@ -247,13 +262,23 @@
 	}
 
 	/* check if the request works... */
-	if (single_gpci_request(event_get_request(event),
+	ret = single_gpci_request(event_get_request(event),
 				event_get_starting_index(event),
 				event_get_secondary_index(event),
 				event_get_counter_info_version(event),
 				event_get_offset(event),
 				length,
-				&count)) {
+				&count);
+
+	/*
+	 * ret value as H_AUTHORITY implies that partition is not permitted to retrieve
+	 * performance information, and required to set
+	 * "Enable Performance Information Collection" option.
+	 */
+	if (ret == H_AUTHORITY)
+		return -EPERM;
+
+	if (ret) {
 		pr_devel("gpci hcall failed\n");
 		return -EINVAL;
 	}
@@ -280,6 +305,7 @@
 	int r;
 	unsigned long hret;
 	struct hv_perf_caps caps;
+	struct hv_gpci_request_buffer *arg;
 
 	hv_gpci_assert_offsets_correct();
 
@@ -298,6 +324,36 @@
 	/* sampling not supported */
 	h_gpci_pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
 
+	arg = (void *)get_cpu_var(hv_gpci_reqb);
+	memset(arg, 0, HGPCI_REQ_BUFFER_SIZE);
+
+	/*
+	 * hcall H_GET_PERF_COUNTER_INFO populates the output
+	 * counter_info_version value based on the system hypervisor.
+	 * Pass the counter request 0x10 corresponds to request type
+	 * 'Dispatch_timebase_by_processor', to get the supported
+	 * counter_info_version.
+	 */
+	arg->params.counter_request = cpu_to_be32(0x10);
+
+	r = plpar_hcall_norets(H_GET_PERF_COUNTER_INFO,
+			virt_to_phys(arg), HGPCI_REQ_BUFFER_SIZE);
+	if (r) {
+		pr_devel("hcall failed, can't get supported counter_info_version: 0x%x\n", r);
+		arg->params.counter_info_version_out = 0x8;
+	}
+
+	/*
+	 * Use counter_info_version_out value to assign
+	 * required hv-gpci event list.
+	 */
+	if (arg->params.counter_info_version_out >= 0x8)
+		event_group.attrs = hv_gpci_event_attrs;
+	else
+		event_group.attrs = hv_gpci_event_attrs_v6;
+
+	put_cpu_var(hv_gpci_reqb);
+
 	r = perf_pmu_register(&h_gpci_pmu, h_gpci_pmu.name, -1);
 	if (r)
 		return r;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/perf/hv-gpci.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/perf/hv-gpci.h
@@ -53,6 +53,7 @@
 #define REQUEST_FILE "../hv-gpci-requests.h"
 #define NAME_LOWER hv_gpci
 #define NAME_UPPER HV_GPCI
+#define ENABLE_EVENTS_COUNTERINFO_V6
 #include "req-gen/perf.h"
 #undef REQUEST_FILE
 #undef NAME_LOWER
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/perf/imc-pmu.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/perf/imc-pmu.c
@@ -13,6 +13,7 @@
 #include <asm/cputhreads.h>
 #include <asm/smp.h>
 #include <linux/string.h>
+#include <linux/spinlock.h>
 
 /* Nest IMC data structures and variables */
 
@@ -44,6 +45,16 @@
 static struct imc_pmu_ref *trace_imc_refc;
 static int trace_imc_mem_size;
 
+/*
+ * Global data structure used to avoid races between thread,
+ * core and trace-imc
+ */
+static struct imc_pmu_ref imc_global_refc = {
+	.lock = __SPIN_LOCK_UNLOCKED(imc_global_refc.lock),
+	.id = 0,
+	.refc = 0,
+};
+
 static struct imc_pmu *imc_event_to_pmu(struct perf_event *event)
 {
 	return container_of(event->pmu, struct imc_pmu, pmu);
@@ -281,6 +292,8 @@
 	attr_group->attrs = attrs;
 	do {
 		ev_val_str = kasprintf(GFP_KERNEL, "event=0x%x", pmu->events[i].value);
+		if (!ev_val_str)
+			continue;
 		dev_str = device_str_attr_create(pmu->events[i].name, ev_val_str);
 		if (!dev_str)
 			continue;
@@ -288,6 +301,8 @@
 		attrs[j++] = dev_str;
 		if (pmu->events[i].scale) {
 			ev_scale_str = kasprintf(GFP_KERNEL, "%s.scale", pmu->events[i].name);
+			if (!ev_scale_str)
+				continue;
 			dev_str = device_str_attr_create(ev_scale_str, pmu->events[i].scale);
 			if (!dev_str)
 				continue;
@@ -297,6 +312,8 @@
 
 		if (pmu->events[i].unit) {
 			ev_unit_str = kasprintf(GFP_KERNEL, "%s.unit", pmu->events[i].name);
+			if (!ev_unit_str)
+				continue;
 			dev_str = device_str_attr_create(ev_unit_str, pmu->events[i].unit);
 			if (!dev_str)
 				continue;
@@ -383,7 +400,7 @@
 				       get_hard_smp_processor_id(cpu));
 		/*
 		 * If this is the last cpu in this chip then, skip the reference
-		 * count mutex lock and make the reference count on this chip zero.
+		 * count lock and make the reference count on this chip zero.
 		 */
 		ref = get_nest_pmu_ref(cpu);
 		if (!ref)
@@ -445,15 +462,15 @@
 	/*
 	 * See if we need to disable the nest PMU.
 	 * If no events are currently in use, then we have to take a
-	 * mutex to ensure that we don't race with another task doing
+	 * lock to ensure that we don't race with another task doing
 	 * enable or disable the nest counters.
 	 */
 	ref = get_nest_pmu_ref(event->cpu);
 	if (!ref)
 		return;
 
-	/* Take the mutex lock for this node and then decrement the reference count */
-	mutex_lock(&ref->lock);
+	/* Take the lock for this node and then decrement the reference count */
+	spin_lock(&ref->lock);
 	if (ref->refc == 0) {
 		/*
 		 * The scenario where this is true is, when perf session is
@@ -465,7 +482,7 @@
 		 * an OPAL call to disable the engine in that node.
 		 *
 		 */
-		mutex_unlock(&ref->lock);
+		spin_unlock(&ref->lock);
 		return;
 	}
 	ref->refc--;
@@ -473,7 +490,7 @@
 		rc = opal_imc_counters_stop(OPAL_IMC_COUNTERS_NEST,
 					    get_hard_smp_processor_id(event->cpu));
 		if (rc) {
-			mutex_unlock(&ref->lock);
+			spin_unlock(&ref->lock);
 			pr_err("nest-imc: Unable to stop the counters for core %d\n", node_id);
 			return;
 		}
@@ -481,7 +498,7 @@
 		WARN(1, "nest-imc: Invalid event reference count\n");
 		ref->refc = 0;
 	}
-	mutex_unlock(&ref->lock);
+	spin_unlock(&ref->lock);
 }
 
 static int nest_imc_event_init(struct perf_event *event)
@@ -540,26 +557,25 @@
 
 	/*
 	 * Get the imc_pmu_ref struct for this node.
-	 * Take the mutex lock and then increment the count of nest pmu events
-	 * inited.
+	 * Take the lock and then increment the count of nest pmu events inited.
 	 */
 	ref = get_nest_pmu_ref(event->cpu);
 	if (!ref)
 		return -EINVAL;
 
-	mutex_lock(&ref->lock);
+	spin_lock(&ref->lock);
 	if (ref->refc == 0) {
 		rc = opal_imc_counters_start(OPAL_IMC_COUNTERS_NEST,
 					     get_hard_smp_processor_id(event->cpu));
 		if (rc) {
-			mutex_unlock(&ref->lock);
+			spin_unlock(&ref->lock);
 			pr_err("nest-imc: Unable to start the counters for node %d\n",
 									node_id);
 			return rc;
 		}
 	}
 	++ref->refc;
-	mutex_unlock(&ref->lock);
+	spin_unlock(&ref->lock);
 
 	event->destroy = nest_imc_counters_release;
 	return 0;
@@ -595,9 +611,8 @@
 		return -ENOMEM;
 	mem_info->vbase = page_address(page);
 
-	/* Init the mutex */
 	core_imc_refc[core_id].id = core_id;
-	mutex_init(&core_imc_refc[core_id].lock);
+	spin_lock_init(&core_imc_refc[core_id].lock);
 
 	rc = opal_imc_counters_init(OPAL_IMC_COUNTERS_CORE,
 				__pa((void *)mem_info->vbase),
@@ -686,9 +701,8 @@
 		perf_pmu_migrate_context(&core_imc_pmu->pmu, cpu, ncpu);
 	} else {
 		/*
-		 * If this is the last cpu in this core then, skip taking refernce
-		 * count mutex lock for this core and directly zero "refc" for
-		 * this core.
+		 * If this is the last cpu in this core then skip taking reference
+		 * count lock for this core and directly zero "refc" for this core.
 		 */
 		opal_imc_counters_stop(OPAL_IMC_COUNTERS_CORE,
 				       get_hard_smp_processor_id(cpu));
@@ -698,6 +712,16 @@
 			return -EINVAL;
 
 		ref->refc = 0;
+		/*
+		 * Reduce the global reference count, if this is the
+		 * last cpu in this core and core-imc event running
+		 * in this cpu.
+		 */
+		spin_lock(&imc_global_refc.lock);
+		if (imc_global_refc.id == IMC_DOMAIN_CORE)
+			imc_global_refc.refc--;
+
+		spin_unlock(&imc_global_refc.lock);
 	}
 	return 0;
 }
@@ -710,6 +734,23 @@
 				 ppc_core_imc_cpu_offline);
 }
 
+static void reset_global_refc(struct perf_event *event)
+{
+		spin_lock(&imc_global_refc.lock);
+		imc_global_refc.refc--;
+
+		/*
+		 * If no other thread is running any
+		 * event for this domain(thread/core/trace),
+		 * set the global id to zero.
+		 */
+		if (imc_global_refc.refc <= 0) {
+			imc_global_refc.refc = 0;
+			imc_global_refc.id = 0;
+		}
+		spin_unlock(&imc_global_refc.lock);
+}
+
 static void core_imc_counters_release(struct perf_event *event)
 {
 	int rc, core_id;
@@ -720,17 +761,17 @@
 	/*
 	 * See if we need to disable the IMC PMU.
 	 * If no events are currently in use, then we have to take a
-	 * mutex to ensure that we don't race with another task doing
+	 * lock to ensure that we don't race with another task doing
 	 * enable or disable the core counters.
 	 */
 	core_id = event->cpu / threads_per_core;
 
-	/* Take the mutex lock and decrement the refernce count for this core */
+	/* Take the lock and decrement the refernce count for this core */
 	ref = &core_imc_refc[core_id];
 	if (!ref)
 		return;
 
-	mutex_lock(&ref->lock);
+	spin_lock(&ref->lock);
 	if (ref->refc == 0) {
 		/*
 		 * The scenario where this is true is, when perf session is
@@ -742,7 +783,7 @@
 		 * an OPAL call to disable the engine in that core.
 		 *
 		 */
-		mutex_unlock(&ref->lock);
+		spin_unlock(&ref->lock);
 		return;
 	}
 	ref->refc--;
@@ -750,7 +791,7 @@
 		rc = opal_imc_counters_stop(OPAL_IMC_COUNTERS_CORE,
 					    get_hard_smp_processor_id(event->cpu));
 		if (rc) {
-			mutex_unlock(&ref->lock);
+			spin_unlock(&ref->lock);
 			pr_err("IMC: Unable to stop the counters for core %d\n", core_id);
 			return;
 		}
@@ -758,7 +799,9 @@
 		WARN(1, "core-imc: Invalid event reference count\n");
 		ref->refc = 0;
 	}
-	mutex_unlock(&ref->lock);
+	spin_unlock(&ref->lock);
+
+	reset_global_refc(event);
 }
 
 static int core_imc_event_init(struct perf_event *event)
@@ -794,7 +837,6 @@
 	if ((!pcmi->vbase))
 		return -ENODEV;
 
-	/* Get the core_imc mutex for this core */
 	ref = &core_imc_refc[core_id];
 	if (!ref)
 		return -EINVAL;
@@ -802,22 +844,45 @@
 	/*
 	 * Core pmu units are enabled only when it is used.
 	 * See if this is triggered for the first time.
-	 * If yes, take the mutex lock and enable the core counters.
+	 * If yes, take the lock and enable the core counters.
 	 * If not, just increment the count in core_imc_refc struct.
 	 */
-	mutex_lock(&ref->lock);
+	spin_lock(&ref->lock);
 	if (ref->refc == 0) {
 		rc = opal_imc_counters_start(OPAL_IMC_COUNTERS_CORE,
 					     get_hard_smp_processor_id(event->cpu));
 		if (rc) {
-			mutex_unlock(&ref->lock);
+			spin_unlock(&ref->lock);
 			pr_err("core-imc: Unable to start the counters for core %d\n",
 									core_id);
 			return rc;
 		}
 	}
 	++ref->refc;
-	mutex_unlock(&ref->lock);
+	spin_unlock(&ref->lock);
+
+	/*
+	 * Since the system can run either in accumulation or trace-mode
+	 * of IMC at a time, core-imc events are allowed only if no other
+	 * trace/thread imc events are enabled/monitored.
+	 *
+	 * Take the global lock, and check the refc.id
+	 * to know whether any other trace/thread imc
+	 * events are running.
+	 */
+	spin_lock(&imc_global_refc.lock);
+	if (imc_global_refc.id == 0 || imc_global_refc.id == IMC_DOMAIN_CORE) {
+		/*
+		 * No other trace/thread imc events are running in
+		 * the system, so set the refc.id to core-imc.
+		 */
+		imc_global_refc.id = IMC_DOMAIN_CORE;
+		imc_global_refc.refc++;
+	} else {
+		spin_unlock(&imc_global_refc.lock);
+		return -EBUSY;
+	}
+	spin_unlock(&imc_global_refc.lock);
 
 	event->hw.event_base = (u64)pcmi->vbase + (config & IMC_EVENT_OFFSET_MASK);
 	event->destroy = core_imc_counters_release;
@@ -877,7 +942,23 @@
 
 static int ppc_thread_imc_cpu_offline(unsigned int cpu)
 {
-	mtspr(SPRN_LDBAR, 0);
+	/*
+	 * Set the bit 0 of LDBAR to zero.
+	 *
+	 * If bit 0 of LDBAR is unset, it will stop posting
+	 * the counter data to memory.
+	 * For thread-imc, bit 0 of LDBAR will be set to 1 in the
+	 * event_add function. So reset this bit here, to stop the updates
+	 * to memory in the cpu_offline path.
+	 */
+	mtspr(SPRN_LDBAR, (mfspr(SPRN_LDBAR) & (~(1UL << 63))));
+
+	/* Reduce the refc if thread-imc event running on this cpu */
+	spin_lock(&imc_global_refc.lock);
+	if (imc_global_refc.id == IMC_DOMAIN_THREAD)
+		imc_global_refc.refc--;
+	spin_unlock(&imc_global_refc.lock);
+
 	return 0;
 }
 
@@ -916,7 +997,22 @@
 	if (!target)
 		return -EINVAL;
 
+	spin_lock(&imc_global_refc.lock);
+	/*
+	 * Check if any other trace/core imc events are running in the
+	 * system, if not set the global id to thread-imc.
+	 */
+	if (imc_global_refc.id == 0 || imc_global_refc.id == IMC_DOMAIN_THREAD) {
+		imc_global_refc.id = IMC_DOMAIN_THREAD;
+		imc_global_refc.refc++;
+	} else {
+		spin_unlock(&imc_global_refc.lock);
+		return -EBUSY;
+	}
+	spin_unlock(&imc_global_refc.lock);
+
 	event->pmu->task_ctx_nr = perf_sw_context;
+	event->destroy = reset_global_refc;
 	return 0;
 }
 
@@ -1035,25 +1131,25 @@
 	/*
 	 * imc pmus are enabled only when it is used.
 	 * See if this is triggered for the first time.
-	 * If yes, take the mutex lock and enable the counters.
+	 * If yes, take the lock and enable the counters.
 	 * If not, just increment the count in ref count struct.
 	 */
 	ref = &core_imc_refc[core_id];
 	if (!ref)
 		return -EINVAL;
 
-	mutex_lock(&ref->lock);
+	spin_lock(&ref->lock);
 	if (ref->refc == 0) {
 		if (opal_imc_counters_start(OPAL_IMC_COUNTERS_CORE,
 		    get_hard_smp_processor_id(smp_processor_id()))) {
-			mutex_unlock(&ref->lock);
+			spin_unlock(&ref->lock);
 			pr_err("thread-imc: Unable to start the counter\
 				for core %d\n", core_id);
 			return -EINVAL;
 		}
 	}
 	++ref->refc;
-	mutex_unlock(&ref->lock);
+	spin_unlock(&ref->lock);
 	return 0;
 }
 
@@ -1063,17 +1159,19 @@
 	int core_id;
 	struct imc_pmu_ref *ref;
 
-	mtspr(SPRN_LDBAR, 0);
-
 	core_id = smp_processor_id() / threads_per_core;
 	ref = &core_imc_refc[core_id];
+	if (!ref) {
+		pr_debug("imc: Failed to get event reference count\n");
+		return;
+	}
 
-	mutex_lock(&ref->lock);
+	spin_lock(&ref->lock);
 	ref->refc--;
 	if (ref->refc == 0) {
 		if (opal_imc_counters_stop(OPAL_IMC_COUNTERS_CORE,
 		    get_hard_smp_processor_id(smp_processor_id()))) {
-			mutex_unlock(&ref->lock);
+			spin_unlock(&ref->lock);
 			pr_err("thread-imc: Unable to stop the counters\
 				for core %d\n", core_id);
 			return;
@@ -1081,7 +1179,11 @@
 	} else if (ref->refc < 0) {
 		ref->refc = 0;
 	}
-	mutex_unlock(&ref->lock);
+	spin_unlock(&ref->lock);
+
+	/* Set bit 0 of LDBAR to zero, to stop posting updates to memory */
+	mtspr(SPRN_LDBAR, (mfspr(SPRN_LDBAR) & (~(1UL << 63))));
+
 	/*
 	 * Take a snapshot and calculate the delta and update
 	 * the event counter values.
@@ -1118,9 +1220,8 @@
 		}
 	}
 
-	/* Init the mutex, if not already */
 	trace_imc_refc[core_id].id = core_id;
-	mutex_init(&trace_imc_refc[core_id].lock);
+	spin_lock_init(&trace_imc_refc[core_id].lock);
 
 	mtspr(SPRN_LDBAR, 0);
 	return 0;
@@ -1133,7 +1234,18 @@
 
 static int ppc_trace_imc_cpu_offline(unsigned int cpu)
 {
-	mtspr(SPRN_LDBAR, 0);
+	/*
+	 * No need to set bit 0 of LDBAR to zero, as
+	 * it is set to zero for imc trace-mode
+	 *
+	 * Reduce the refc if any trace-imc event running
+	 * on this cpu.
+	 */
+	spin_lock(&imc_global_refc.lock);
+	if (imc_global_refc.id == IMC_DOMAIN_TRACE)
+		imc_global_refc.refc--;
+	spin_unlock(&imc_global_refc.lock);
+
 	return 0;
 }
 
@@ -1226,29 +1338,26 @@
 	local_mem = get_trace_imc_event_base_addr();
 	ldbar_value = ((u64)local_mem & THREAD_IMC_LDBAR_MASK) | TRACE_IMC_ENABLE;
 
-	if (core_imc_refc)
-		ref = &core_imc_refc[core_id];
+	/* trace-imc reference count */
+	if (trace_imc_refc)
+		ref = &trace_imc_refc[core_id];
 	if (!ref) {
-		/* If core-imc is not enabled, use trace-imc reference count */
-		if (trace_imc_refc)
-			ref = &trace_imc_refc[core_id];
-		if (!ref)
-			return -EINVAL;
+		pr_debug("imc: Failed to get the event reference count\n");
+		return -EINVAL;
 	}
+
 	mtspr(SPRN_LDBAR, ldbar_value);
-	mutex_lock(&ref->lock);
+	spin_lock(&ref->lock);
 	if (ref->refc == 0) {
 		if (opal_imc_counters_start(OPAL_IMC_COUNTERS_TRACE,
 				get_hard_smp_processor_id(smp_processor_id()))) {
-			mutex_unlock(&ref->lock);
+			spin_unlock(&ref->lock);
 			pr_err("trace-imc: Unable to start the counters for core %d\n", core_id);
-			mtspr(SPRN_LDBAR, 0);
 			return -EINVAL;
 		}
 	}
 	++ref->refc;
-	mutex_unlock(&ref->lock);
-
+	spin_unlock(&ref->lock);
 	return 0;
 }
 
@@ -1274,29 +1383,27 @@
 	int core_id = smp_processor_id() / threads_per_core;
 	struct imc_pmu_ref *ref = NULL;
 
-	if (core_imc_refc)
-		ref = &core_imc_refc[core_id];
+	if (trace_imc_refc)
+		ref = &trace_imc_refc[core_id];
 	if (!ref) {
-		/* If core-imc is not enabled, use trace-imc reference count */
-		if (trace_imc_refc)
-			ref = &trace_imc_refc[core_id];
-		if (!ref)
-			return;
+		pr_debug("imc: Failed to get event reference count\n");
+		return;
 	}
-	mtspr(SPRN_LDBAR, 0);
-	mutex_lock(&ref->lock);
+
+	spin_lock(&ref->lock);
 	ref->refc--;
 	if (ref->refc == 0) {
 		if (opal_imc_counters_stop(OPAL_IMC_COUNTERS_TRACE,
 				get_hard_smp_processor_id(smp_processor_id()))) {
-			mutex_unlock(&ref->lock);
+			spin_unlock(&ref->lock);
 			pr_err("trace-imc: Unable to stop the counters for core %d\n", core_id);
 			return;
 		}
 	} else if (ref->refc < 0) {
 		ref->refc = 0;
 	}
-	mutex_unlock(&ref->lock);
+	spin_unlock(&ref->lock);
+
 	trace_imc_event_stop(event, flags);
 }
 
@@ -1314,10 +1421,34 @@
 	if (event->attr.sample_period == 0)
 		return -ENOENT;
 
+	/*
+	 * Take the global lock, and make sure
+	 * no other thread is running any core/thread imc
+	 * events
+	 */
+	spin_lock(&imc_global_refc.lock);
+	if (imc_global_refc.id == 0 || imc_global_refc.id == IMC_DOMAIN_TRACE) {
+		/*
+		 * No core/thread imc events are running in the
+		 * system, so set the refc.id to trace-imc.
+		 */
+		imc_global_refc.id = IMC_DOMAIN_TRACE;
+		imc_global_refc.refc++;
+	} else {
+		spin_unlock(&imc_global_refc.lock);
+		return -EBUSY;
+	}
+	spin_unlock(&imc_global_refc.lock);
+
 	event->hw.idx = -1;
 	target = event->hw.target;
 
-	event->pmu->task_ctx_nr = perf_hw_context;
+	/*
+	 * There can only be a single PMU for perf_hw_context events which is assigned to
+	 * core PMU. Hence use "perf_sw_context" for trace_imc.
+	 */
+	event->pmu->task_ctx_nr = perf_sw_context;
+	event->destroy = reset_global_refc;
 	return 0;
 }
 
@@ -1380,10 +1511,10 @@
 	i = 0;
 	for_each_node(nid) {
 		/*
-		 * Mutex lock to avoid races while tracking the number of
+		 * Take the lock to avoid races while tracking the number of
 		 * sessions using the chip's nest pmu units.
 		 */
-		mutex_init(&nest_imc_refc[i].lock);
+		spin_lock_init(&nest_imc_refc[i].lock);
 
 		/*
 		 * Loop to init the "id" with the node_id. Variable "i" initialized to
@@ -1429,10 +1560,10 @@
 static void thread_imc_ldbar_disable(void *dummy)
 {
 	/*
-	 * By Zeroing LDBAR, we disable thread-imc
-	 * updates.
+	 * By setting 0th bit of LDBAR to zero, we disable thread-imc
+	 * updates to memory.
 	 */
-	mtspr(SPRN_LDBAR, 0);
+	mtspr(SPRN_LDBAR, (mfspr(SPRN_LDBAR) & (~(1UL << 63))));
 }
 
 void thread_imc_disable(void)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/perf/isa207-common.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/perf/isa207-common.c
@@ -269,6 +269,15 @@
 
 		mask  |= CNST_PMC_MASK(pmc);
 		value |= CNST_PMC_VAL(pmc);
+
+		/*
+		 * PMC5 and PMC6 are used to count cycles and instructions and
+		 * they do not support most of the constraint bits. Add a check
+		 * to exclude PMC5/6 from most of the constraints except for
+		 * EBB/BHRB.
+		 */
+		if (pmc >= 5)
+			goto ebb_bhrb;
 	}
 
 	if (pmc <= 4) {
@@ -317,7 +326,8 @@
 		if (event_is_threshold(event) && is_thresh_cmp_valid(event)) {
 			mask  |= CNST_THRESH_MASK;
 			value |= CNST_THRESH_VAL(event >> EVENT_THRESH_SHIFT);
-		}
+		} else if (event_is_threshold(event))
+			return -1;
 	} else {
 		/*
 		 * Special case for PM_MRK_FAB_RSP_MATCH and PM_MRK_FAB_RSP_MATCH_CYC,
@@ -335,6 +345,7 @@
 		}
 	}
 
+ebb_bhrb:
 	if (!pmc && ebb)
 		/* EBB events must specify the PMC */
 		return -1;
@@ -353,8 +364,8 @@
 	 * EBB events are pinned & exclusive, so this should never actually
 	 * hit, but we leave it as a fallback in case.
 	 */
-	mask  |= CNST_EBB_VAL(ebb);
-	value |= CNST_EBB_MASK;
+	mask  |= CNST_EBB_MASK;
+	value |= CNST_EBB_VAL(ebb);
 
 	*maskp = mask;
 	*valp = value;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/perf/power9-pmu.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/perf/power9-pmu.c
@@ -131,11 +131,11 @@
 
 /* Table of alternatives, sorted by column 0 */
 static const unsigned int power9_event_alternatives[][MAX_ALT] = {
-	{ PM_INST_DISP,			PM_INST_DISP_ALT },
-	{ PM_RUN_CYC_ALT,		PM_RUN_CYC },
-	{ PM_RUN_INST_CMPL_ALT,		PM_RUN_INST_CMPL },
-	{ PM_LD_MISS_L1,		PM_LD_MISS_L1_ALT },
 	{ PM_BR_2PATH,			PM_BR_2PATH_ALT },
+	{ PM_INST_DISP,			PM_INST_DISP_ALT },
+	{ PM_RUN_CYC_ALT,               PM_RUN_CYC },
+	{ PM_LD_MISS_L1,                PM_LD_MISS_L1_ALT },
+	{ PM_RUN_INST_CMPL_ALT,         PM_RUN_INST_CMPL },
 };
 
 static int power9_get_alternatives(u64 event, unsigned int flags, u64 alt[])
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/perf/req-gen/perf.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/perf/req-gen/perf.h
@@ -139,6 +139,26 @@
 #define REQUEST_(r_name, r_value, r_idx_1, r_fields)			\
 	r_fields
 
+/* Generate event list for platforms with counter_info_version 0x6 or below */
+static __maybe_unused struct attribute *hv_gpci_event_attrs_v6[] = {
+#include REQUEST_FILE
+	NULL
+};
+
+/*
+ * Based on getPerfCountInfo v1.018 documentation, some of the hv-gpci
+ * events were deprecated for platform firmware that supports
+ * counter_info_version 0x8 or above.
+ * Those deprecated events are still part of platform firmware that
+ * support counter_info_version 0x6 and below. As per the getPerfCountInfo
+ * v1.018 documentation there is no counter_info_version 0x7.
+ * Undefining macro ENABLE_EVENTS_COUNTERINFO_V6, to disable the addition of
+ * deprecated events in "hv_gpci_event_attrs" attribute group, for platforms
+ * that supports counter_info_version 0x8 or above.
+ */
+#undef ENABLE_EVENTS_COUNTERINFO_V6
+
+/* Generate event list for platforms with counter_info_version 0x8 or above*/
 static __maybe_unused struct attribute *hv_gpci_event_attrs[] = {
 #include REQUEST_FILE
 	NULL
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/44x/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/44x/Kconfig
@@ -178,6 +178,7 @@
 config CURRITUCK
 	bool "IBM Currituck (476fpe) Support"
 	depends on PPC_47x
+	select I2C
 	select SWIOTLB
 	select 476FPE
 	select FORCE_PCI
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/44x/fsp2.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/44x/fsp2.c
@@ -208,6 +208,7 @@
 		if (irq == NO_IRQ) {
 			pr_err("device tree node %pOFn is missing a interrupt",
 			      np);
+			of_node_put(np);
 			return;
 		}
 
@@ -215,6 +216,7 @@
 		if (rc) {
 			pr_err("fsp_of_probe: request_irq failed: np=%pOF rc=%d",
 			      np, rc);
+			of_node_put(np);
 			return;
 		}
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/4xx/cpm.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/4xx/cpm.c
@@ -327,6 +327,6 @@
 static int __init cpm_powersave_off(char *arg)
 {
 	cpm.powersave_off = 1;
-	return 0;
+	return 1;
 }
 __setup("powersave=off", cpm_powersave_off);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/4xx/pci.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/4xx/pci.c
@@ -1242,7 +1242,7 @@
 	if (mbase == NULL) {
 		printk(KERN_ERR "%pOF: Can't map internal config space !",
 			port->node);
-		goto done;
+		return;
 	}
 
 	while (attempt && (0 == (in_le32(mbase + PECFG_460SX_DLLSTA)
@@ -1252,9 +1252,7 @@
 	}
 	if (attempt)
 		port->link = 1;
-done:
 	iounmap(mbase);
-
 }
 
 static struct ppc4xx_pciex_hwops ppc460sx_pcie_hwops __initdata = {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/512x/clock-commonclk.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/512x/clock-commonclk.c
@@ -984,7 +984,7 @@
 
 #define NODE_PREP do { \
 	of_address_to_resource(np, 0, &res); \
-	snprintf(devname, sizeof(devname), "%08x.%s", res.start, np->name); \
+	snprintf(devname, sizeof(devname), "%pa.%s", &res.start, np->name); \
 } while (0)
 
 #define NODE_CHK(clkname, clkitem, regnode, regflag) do { \
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/52xx/lite5200_sleep.S
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/52xx/lite5200_sleep.S
@@ -181,7 +181,7 @@
   udelay: /* r11 - tb_ticks_per_usec, r12 - usecs, overwrites r13 */
 	mullw	r12, r12, r11
 	mftb	r13	/* start */
-	addi	r12, r13, r12 /* end */
+	add	r12, r13, r12 /* end */
     1:
 	mftb	r13	/* current */
 	cmp	cr0, r13, r12
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c
@@ -530,6 +530,7 @@
  err_bcom_rx_irq:
 	bcom_gen_bd_rx_release(lpbfifo.bcom_rx_task);
  err_bcom_rx:
+	free_irq(lpbfifo.irq, &lpbfifo);
  err_irq:
 	iounmap(lpbfifo.regs);
 	lpbfifo.regs = NULL;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/52xx/mpc52xx_pic.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/52xx/mpc52xx_pic.c
@@ -340,7 +340,7 @@
 {
 	int l1irq;
 	int l2irq;
-	struct irq_chip *uninitialized_var(irqchip);
+	struct irq_chip *irqchip;
 	void *hndlr;
 	int type;
 	u32 reg;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/83xx/mpc832x_rdb.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/83xx/mpc832x_rdb.c
@@ -107,7 +107,7 @@
 
 		goto next;
 unreg:
-		platform_device_del(pdev);
+		platform_device_put(pdev);
 err:
 		pr_err("%pOF: registration failed\n", np);
 next:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/85xx/mpc85xx_pm_ops.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/85xx/mpc85xx_pm_ops.c
@@ -94,9 +94,8 @@
 			pr_err("Could not map guts node address\n");
 			return -ENOMEM;
 		}
+		qoriq_pm_ops = &mpc85xx_pm_ops;
 	}
 
-	qoriq_pm_ops = &mpc85xx_pm_ops;
-
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/8xx/cpm1.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/8xx/cpm1.c
@@ -292,6 +292,7 @@
 		out_be32(bp, (((BRG_UART_CLK_DIV16 / rate) - 1) << 1) |
 			      CPM_BRG_EN | CPM_BRG_DIV16);
 }
+EXPORT_SYMBOL(cpm_setbrg);
 
 struct cpm_ioport16 {
 	__be16 dir, par, odr_sor, dat, intr;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/8xx/micropatch.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/8xx/micropatch.c
@@ -361,6 +361,17 @@
 	if (IS_ENABLED(CONFIG_SMC_UCODE_PATCH)) {
 		smc_uart_t *smp;
 
+		if (IS_ENABLED(CONFIG_PPC_EARLY_DEBUG_CPM)) {
+			int i;
+
+			for (i = 0; i < sizeof(*smp); i += 4) {
+				u32 __iomem *src = (u32 __iomem *)&cp->cp_dparam[PROFF_SMC1 + i];
+				u32 __iomem *dst = (u32 __iomem *)&cp->cp_dparam[PROFF_DSP1 + i];
+
+				out_be32(dst, in_be32(src));
+			}
+		}
+
 		smp = (smc_uart_t *)&cp->cp_dparam[PROFF_SMC1];
 		out_be16(&smp->smc_rpbase, 0x1ec0);
 		smp = (smc_uart_t *)&cp->cp_dparam[PROFF_SMC2];
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/8xx/pic.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/8xx/pic.c
@@ -153,6 +153,7 @@
 	if (mpc8xx_pic_host == NULL) {
 		printk(KERN_ERR "MPC8xx PIC: failed to allocate irq host!\n");
 		ret = -ENOMEM;
+		goto out;
 	}
 
 	ret = 0;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/Kconfig
@@ -219,12 +219,11 @@
 	  temperature within 2-4 degrees Celsius. This option shows the current
 	  on-die temperature in /proc/cpuinfo if the cpu supports it.
 
-	  Unfortunately, on some chip revisions, this sensor is very inaccurate
-	  and in many cases, does not work at all, so don't assume the cpu
-	  temp is actually what /proc/cpuinfo says it is.
+	  Unfortunately, this sensor is very inaccurate when uncalibrated, so
+	  don't assume the cpu temp is actually what /proc/cpuinfo says it is.
 
 config TAU_INT
-	bool "Interrupt driven TAU driver (DANGEROUS)"
+	bool "Interrupt driven TAU driver (EXPERIMENTAL)"
 	depends on TAU
 	---help---
 	  The TAU supports an interrupt driven mode which causes an interrupt
@@ -232,12 +231,7 @@
 	  to get notified the temp has exceeded a range. With this option off,
 	  a timer is used to re-check the temperature periodically.
 
-	  However, on some cpus it appears that the TAU interrupt hardware
-	  is buggy and can cause a situation which would lead unexplained hard
-	  lockups.
-
-	  Unless you are extending the TAU driver, or enjoy kernel/hardware
-	  debugging, leave this option off.
+	  If in doubt, say N here.
 
 config TAU_AVERAGE
 	bool "Average high and low temp"
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/Kconfig.cputype
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/Kconfig.cputype
@@ -118,9 +118,9 @@
 	depends on PPC64 && CPU_LITTLE_ENDIAN
 	select ARCH_HAS_FAST_MULTIPLIER
 
-config GENERIC_CPU
+config POWERPC_CPU
 	bool "Generic 32 bits powerpc"
-	depends on PPC32 && !PPC_8xx
+	depends on PPC32 && !PPC_8xx && !PPC_85xx
 
 config CELL_CPU
 	bool "Cell Broadband Engine"
@@ -151,11 +151,11 @@
 
 config E5500_CPU
 	bool "Freescale e5500"
-	depends on E500
+	depends on PPC64 && E500
 
 config E6500_CPU
 	bool "Freescale e6500"
-	depends on E500
+	depends on PPC64 && E500
 
 config 860_CPU
 	bool "8xx family"
@@ -174,11 +174,23 @@
 	depends on PPC_BOOK3S_32
 	select ALTIVEC
 
+config E500_CPU
+	bool "e500 (8540)"
+	depends on PPC_85xx && !PPC_E500MC
+
+config E500MC_CPU
+	bool "e500mc"
+	depends on PPC_85xx && PPC_E500MC
+
+config TOOLCHAIN_DEFAULT_CPU
+	bool "Rely on the toolchain's implicit default CPU"
+	depends on PPC32
+
 endchoice
 
 config TARGET_CPU_BOOL
 	bool
-	default !GENERIC_CPU
+	default !GENERIC_CPU && !TOOLCHAIN_DEFAULT_CPU
 
 config TARGET_CPU
 	string
@@ -193,6 +205,9 @@
 	default "e300c2" if E300C2_CPU
 	default "e300c3" if E300C3_CPU
 	default "G4" if G4_CPU
+	default "8540" if E500_CPU
+	default "e500mc" if E500MC_CPU
+	default "powerpc" if POWERPC_CPU
 
 config PPC_BOOK3S
 	def_bool y
@@ -389,7 +404,7 @@
 
 config PPC_KUAP_DEBUG
 	bool "Extra debugging for Kernel Userspace Access Protection"
-	depends on PPC_HAVE_KUAP && (PPC_RADIX_MMU || PPC_32)
+	depends on PPC_KUAP && (PPC_RADIX_MMU || PPC32)
 	help
 	  Add extra debugging for Kernel Userspace Access Protection (KUAP)
 	  If you're unsure, say N.
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/cell/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/cell/Kconfig
@@ -44,6 +44,7 @@
 	tristate "SPU file system"
 	default m
 	depends on PPC_CELL
+	depends on COREDUMP
 	select SPU_BASE
 	help
 	  The SPU file system is used to access Synergistic Processing
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/cell/axon_msi.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/cell/axon_msi.c
@@ -226,6 +226,7 @@
 	if (!prop) {
 		dev_dbg(&dev->dev,
 			"axon_msi: no msi-address-(32|64) properties found\n");
+		of_node_put(dn);
 		return -ENOENT;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/cell/iommu.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/cell/iommu.c
@@ -976,6 +976,7 @@
 			if (hbase < dbase || (hend > (dbase + dsize))) {
 				pr_debug("iommu: hash window doesn't fit in"
 					 "real DMA window\n");
+				of_node_put(np);
 				return -1;
 			}
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/cell/pervasive.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/cell/pervasive.c
@@ -77,6 +77,7 @@
 	switch (regs->msr & SRR1_WAKEMASK) {
 	case SRR1_WAKEDEC:
 		set_dec(1);
+		break;
 	case SRR1_WAKEEE:
 		/*
 		 * Handle these when interrupts get re-enabled and we take
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/cell/spufs/file.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/cell/spufs/file.c
@@ -1978,8 +1978,9 @@
 static ssize_t spufs_mbox_info_read(struct file *file, char __user *buf,
 				   size_t len, loff_t *pos)
 {
-	int ret;
 	struct spu_context *ctx = file->private_data;
+	u32 stat, data;
+	int ret;
 
 	if (!access_ok(buf, len))
 		return -EFAULT;
@@ -1988,11 +1989,16 @@
 	if (ret)
 		return ret;
 	spin_lock(&ctx->csa.register_lock);
-	ret = __spufs_mbox_info_read(ctx, buf, len, pos);
+	stat = ctx->csa.prob.mb_stat_R;
+	data = ctx->csa.prob.pu_mb_R;
 	spin_unlock(&ctx->csa.register_lock);
 	spu_release_saved(ctx);
 
-	return ret;
+	/* EOF if there's no entry in the mbox */
+	if (!(stat & 0x0000ff))
+		return 0;
+
+	return simple_read_from_buffer(buf, len, pos, &data, sizeof(data));
 }
 
 static const struct file_operations spufs_mbox_info_fops = {
@@ -2019,6 +2025,7 @@
 				   size_t len, loff_t *pos)
 {
 	struct spu_context *ctx = file->private_data;
+	u32 stat, data;
 	int ret;
 
 	if (!access_ok(buf, len))
@@ -2028,11 +2035,16 @@
 	if (ret)
 		return ret;
 	spin_lock(&ctx->csa.register_lock);
-	ret = __spufs_ibox_info_read(ctx, buf, len, pos);
+	stat = ctx->csa.prob.mb_stat_R;
+	data = ctx->csa.priv2.puint_mb_R;
 	spin_unlock(&ctx->csa.register_lock);
 	spu_release_saved(ctx);
 
-	return ret;
+	/* EOF if there's no entry in the ibox */
+	if (!(stat & 0xff0000))
+		return 0;
+
+	return simple_read_from_buffer(buf, len, pos, &data, sizeof(data));
 }
 
 static const struct file_operations spufs_ibox_info_fops = {
@@ -2041,6 +2053,11 @@
 	.llseek  = generic_file_llseek,
 };
 
+static size_t spufs_wbox_info_cnt(struct spu_context *ctx)
+{
+	return (4 - ((ctx->csa.prob.mb_stat_R & 0x00ff00) >> 8)) * sizeof(u32);
+}
+
 static ssize_t __spufs_wbox_info_read(struct spu_context *ctx,
 			char __user *buf, size_t len, loff_t *pos)
 {
@@ -2049,7 +2066,7 @@
 	u32 wbox_stat;
 
 	wbox_stat = ctx->csa.prob.mb_stat_R;
-	cnt = 4 - ((wbox_stat & 0x00ff00) >> 8);
+	cnt = spufs_wbox_info_cnt(ctx);
 	for (i = 0; i < cnt; i++) {
 		data[i] = ctx->csa.spu_mailbox_data[i];
 	}
@@ -2062,7 +2079,8 @@
 				   size_t len, loff_t *pos)
 {
 	struct spu_context *ctx = file->private_data;
-	int ret;
+	u32 data[ARRAY_SIZE(ctx->csa.spu_mailbox_data)];
+	int ret, count;
 
 	if (!access_ok(buf, len))
 		return -EFAULT;
@@ -2071,11 +2089,13 @@
 	if (ret)
 		return ret;
 	spin_lock(&ctx->csa.register_lock);
-	ret = __spufs_wbox_info_read(ctx, buf, len, pos);
+	count = spufs_wbox_info_cnt(ctx);
+	memcpy(&data, &ctx->csa.spu_mailbox_data, sizeof(data));
 	spin_unlock(&ctx->csa.register_lock);
 	spu_release_saved(ctx);
 
-	return ret;
+	return simple_read_from_buffer(buf, len, pos, &data,
+				count * sizeof(u32));
 }
 
 static const struct file_operations spufs_wbox_info_fops = {
@@ -2084,27 +2104,33 @@
 	.llseek  = generic_file_llseek,
 };
 
-static ssize_t __spufs_dma_info_read(struct spu_context *ctx,
-			char __user *buf, size_t len, loff_t *pos)
+static void spufs_get_dma_info(struct spu_context *ctx,
+		struct spu_dma_info *info)
 {
-	struct spu_dma_info info;
-	struct mfc_cq_sr *qp, *spuqp;
 	int i;
 
-	info.dma_info_type = ctx->csa.priv2.spu_tag_status_query_RW;
-	info.dma_info_mask = ctx->csa.lscsa->tag_mask.slot[0];
-	info.dma_info_status = ctx->csa.spu_chnldata_RW[24];
-	info.dma_info_stall_and_notify = ctx->csa.spu_chnldata_RW[25];
-	info.dma_info_atomic_command_status = ctx->csa.spu_chnldata_RW[27];
+	info->dma_info_type = ctx->csa.priv2.spu_tag_status_query_RW;
+	info->dma_info_mask = ctx->csa.lscsa->tag_mask.slot[0];
+	info->dma_info_status = ctx->csa.spu_chnldata_RW[24];
+	info->dma_info_stall_and_notify = ctx->csa.spu_chnldata_RW[25];
+	info->dma_info_atomic_command_status = ctx->csa.spu_chnldata_RW[27];
 	for (i = 0; i < 16; i++) {
-		qp = &info.dma_info_command_data[i];
-		spuqp = &ctx->csa.priv2.spuq[i];
+		struct mfc_cq_sr *qp = &info->dma_info_command_data[i];
+		struct mfc_cq_sr *spuqp = &ctx->csa.priv2.spuq[i];
 
 		qp->mfc_cq_data0_RW = spuqp->mfc_cq_data0_RW;
 		qp->mfc_cq_data1_RW = spuqp->mfc_cq_data1_RW;
 		qp->mfc_cq_data2_RW = spuqp->mfc_cq_data2_RW;
 		qp->mfc_cq_data3_RW = spuqp->mfc_cq_data3_RW;
 	}
+}
+
+static ssize_t __spufs_dma_info_read(struct spu_context *ctx,
+			char __user *buf, size_t len, loff_t *pos)
+{
+	struct spu_dma_info info;
+
+	spufs_get_dma_info(ctx, &info);
 
 	return simple_read_from_buffer(buf, len, pos, &info,
 				sizeof info);
@@ -2114,6 +2140,7 @@
 			      size_t len, loff_t *pos)
 {
 	struct spu_context *ctx = file->private_data;
+	struct spu_dma_info info;
 	int ret;
 
 	if (!access_ok(buf, len))
@@ -2123,11 +2150,12 @@
 	if (ret)
 		return ret;
 	spin_lock(&ctx->csa.register_lock);
-	ret = __spufs_dma_info_read(ctx, buf, len, pos);
+	spufs_get_dma_info(ctx, &info);
 	spin_unlock(&ctx->csa.register_lock);
 	spu_release_saved(ctx);
 
-	return ret;
+	return simple_read_from_buffer(buf, len, pos, &info,
+				sizeof(info));
 }
 
 static const struct file_operations spufs_dma_info_fops = {
@@ -2136,13 +2164,31 @@
 	.llseek = no_llseek,
 };
 
+static void spufs_get_proxydma_info(struct spu_context *ctx,
+		struct spu_proxydma_info *info)
+{
+	int i;
+
+	info->proxydma_info_type = ctx->csa.prob.dma_querytype_RW;
+	info->proxydma_info_mask = ctx->csa.prob.dma_querymask_RW;
+	info->proxydma_info_status = ctx->csa.prob.dma_tagstatus_R;
+
+	for (i = 0; i < 8; i++) {
+		struct mfc_cq_sr *qp = &info->proxydma_info_command_data[i];
+		struct mfc_cq_sr *puqp = &ctx->csa.priv2.puq[i];
+
+		qp->mfc_cq_data0_RW = puqp->mfc_cq_data0_RW;
+		qp->mfc_cq_data1_RW = puqp->mfc_cq_data1_RW;
+		qp->mfc_cq_data2_RW = puqp->mfc_cq_data2_RW;
+		qp->mfc_cq_data3_RW = puqp->mfc_cq_data3_RW;
+	}
+}
+
 static ssize_t __spufs_proxydma_info_read(struct spu_context *ctx,
 			char __user *buf, size_t len, loff_t *pos)
 {
 	struct spu_proxydma_info info;
-	struct mfc_cq_sr *qp, *puqp;
 	int ret = sizeof info;
-	int i;
 
 	if (len < ret)
 		return -EINVAL;
@@ -2150,18 +2196,7 @@
 	if (!access_ok(buf, len))
 		return -EFAULT;
 
-	info.proxydma_info_type = ctx->csa.prob.dma_querytype_RW;
-	info.proxydma_info_mask = ctx->csa.prob.dma_querymask_RW;
-	info.proxydma_info_status = ctx->csa.prob.dma_tagstatus_R;
-	for (i = 0; i < 8; i++) {
-		qp = &info.proxydma_info_command_data[i];
-		puqp = &ctx->csa.priv2.puq[i];
-
-		qp->mfc_cq_data0_RW = puqp->mfc_cq_data0_RW;
-		qp->mfc_cq_data1_RW = puqp->mfc_cq_data1_RW;
-		qp->mfc_cq_data2_RW = puqp->mfc_cq_data2_RW;
-		qp->mfc_cq_data3_RW = puqp->mfc_cq_data3_RW;
-	}
+	spufs_get_proxydma_info(ctx, &info);
 
 	return simple_read_from_buffer(buf, len, pos, &info,
 				sizeof info);
@@ -2171,17 +2206,19 @@
 				   size_t len, loff_t *pos)
 {
 	struct spu_context *ctx = file->private_data;
+	struct spu_proxydma_info info;
 	int ret;
 
 	ret = spu_acquire_saved(ctx);
 	if (ret)
 		return ret;
 	spin_lock(&ctx->csa.register_lock);
-	ret = __spufs_proxydma_info_read(ctx, buf, len, pos);
+	spufs_get_proxydma_info(ctx, &info);
 	spin_unlock(&ctx->csa.register_lock);
 	spu_release_saved(ctx);
 
-	return ret;
+	return simple_read_from_buffer(buf, len, pos, &info,
+				sizeof(info));
 }
 
 static const struct file_operations spufs_proxydma_info_fops = {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/cell/spufs/inode.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/cell/spufs/inode.c
@@ -189,8 +189,10 @@
 			return -ENOMEM;
 		ret = spufs_new_file(dir->d_sb, dentry, files->ops,
 					files->mode & mode, files->size, ctx);
-		if (ret)
+		if (ret) {
+			dput(dentry);
 			return ret;
+		}
 		files++;
 	}
 	return 0;
@@ -438,8 +440,11 @@
 	}
 
 	ret = spufs_mkdir(inode, dentry, flags, mode & 0777);
-	if (ret)
+	if (ret) {
+		if (neighbor)
+			put_spu_context(neighbor);
 		goto out_aff_unlock;
+	}
 
 	if (affinity) {
 		spufs_set_affinity(flags, SPUFS_I(d_inode(dentry))->i_ctx,
@@ -671,6 +676,7 @@
 		return;
 
 	loader = of_get_property(dn, "loader", &size);
+	of_node_put(dn);
 	if (!loader)
 		return;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/embedded6xx/flipper-pic.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/embedded6xx/flipper-pic.c
@@ -144,7 +144,7 @@
 	}
 	io_base = ioremap(res.start, resource_size(&res));
 
-	pr_info("controller at 0x%08x mapped to 0x%p\n", res.start, io_base);
+	pr_info("controller at 0x%pa mapped to 0x%p\n", &res.start, io_base);
 
 	__flipper_quiesce(io_base);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/embedded6xx/hlwd-pic.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/embedded6xx/hlwd-pic.c
@@ -173,7 +173,7 @@
 		return NULL;
 	}
 
-	pr_info("controller at 0x%08x mapped to 0x%p\n", res.start, io_base);
+	pr_info("controller at 0x%pa mapped to 0x%p\n", &res.start, io_base);
 
 	__hlwd_quiesce(io_base);
 
@@ -215,6 +215,7 @@
 			irq_set_chained_handler(cascade_virq,
 						hlwd_pic_irq_cascade);
 			hlwd_irq_host = host;
+			of_node_put(np);
 			break;
 		}
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/embedded6xx/linkstation.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/embedded6xx/linkstation.c
@@ -97,9 +97,6 @@
 	mpic_init(mpic);
 }
 
-extern void avr_uart_configure(void);
-extern void avr_uart_send(const char);
-
 static void __noreturn linkstation_restart(char *cmd)
 {
 	local_irq_disable();
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/embedded6xx/mpc10x.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/embedded6xx/mpc10x.h
@@ -156,4 +156,7 @@
 /* For MPC107 boards that use the built-in openpic */
 void mpc10x_set_openpic(void);
 
+void avr_uart_configure(void);
+void avr_uart_send(const char c);
+
 #endif	/* __PPC_KERNEL_MPC10X_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/embedded6xx/wii.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/embedded6xx/wii.c
@@ -89,8 +89,8 @@
 
 	hw_regs = ioremap(res.start, resource_size(&res));
 	if (hw_regs) {
-		pr_info("%s at 0x%08x mapped to 0x%p\n", name,
-			res.start, hw_regs);
+		pr_info("%s at 0x%pa mapped to 0x%p\n", name,
+			&res.start, hw_regs);
 	}
 
 out_put:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/maple/setup.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/maple/setup.c
@@ -294,23 +294,6 @@
 	return 1;
 }
 
-define_machine(maple) {
-	.name			= "Maple",
-	.probe			= maple_probe,
-	.setup_arch		= maple_setup_arch,
-	.init_IRQ		= maple_init_IRQ,
-	.pci_irq_fixup		= maple_pci_irq_fixup,
-	.pci_get_legacy_ide_irq	= maple_pci_get_legacy_ide_irq,
-	.restart		= maple_restart,
-	.halt			= maple_halt,
-       	.get_boot_time		= maple_get_boot_time,
-       	.set_rtc_time		= maple_set_rtc_time,
-       	.get_rtc_time		= maple_get_rtc_time,
-      	.calibrate_decr		= generic_calibrate_decr,
-	.progress		= maple_progress,
-	.power_save		= power4_idle,
-};
-
 #ifdef CONFIG_EDAC
 /*
  * Register a platform device for CPC925 memory controller on
@@ -367,3 +350,20 @@
 }
 machine_device_initcall(maple, maple_cpc925_edac_setup);
 #endif
+
+define_machine(maple) {
+	.name			= "Maple",
+	.probe			= maple_probe,
+	.setup_arch		= maple_setup_arch,
+	.init_IRQ		= maple_init_IRQ,
+	.pci_irq_fixup		= maple_pci_irq_fixup,
+	.pci_get_legacy_ide_irq	= maple_pci_get_legacy_ide_irq,
+	.restart		= maple_restart,
+	.halt			= maple_halt,
+	.get_boot_time		= maple_get_boot_time,
+	.set_rtc_time		= maple_set_rtc_time,
+	.get_rtc_time		= maple_get_rtc_time,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= maple_progress,
+	.power_save		= power4_idle,
+};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/powermac/cache.S
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/powermac/cache.S
@@ -48,7 +48,7 @@
 
 	/* Stop DST streams */
 BEGIN_FTR_SECTION
-	DSSALL
+	PPC_DSSALL
 	sync
 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 
@@ -196,7 +196,7 @@
 	isync
 
 	/* Stop prefetch streams */
-	DSSALL
+	PPC_DSSALL
 	sync
 
 	/* Disable L2 prefetching */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/powermac/low_i2c.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/powermac/low_i2c.c
@@ -582,6 +582,7 @@
 	bus->close = kw_i2c_close;
 	bus->xfer = kw_i2c_xfer;
 	mutex_init(&bus->mutex);
+	lockdep_register_key(&bus->lock_key);
 	lockdep_set_class(&bus->mutex, &bus->lock_key);
 	if (controller == busnode)
 		bus->flags = pmac_i2c_multibus;
@@ -811,6 +812,7 @@
 		bus->hostdata = bus + 1;
 		bus->xfer = pmu_i2c_xfer;
 		mutex_init(&bus->mutex);
+		lockdep_register_key(&bus->lock_key);
 		lockdep_set_class(&bus->mutex, &bus->lock_key);
 		bus->flags = pmac_i2c_multibus;
 		list_add(&bus->link, &pmac_i2c_busses);
@@ -934,6 +936,7 @@
 		bus->hostdata = bus + 1;
 		bus->xfer = smu_i2c_xfer;
 		mutex_init(&bus->mutex);
+		lockdep_register_key(&bus->lock_key);
 		lockdep_set_class(&bus->mutex, &bus->lock_key);
 		bus->flags = 0;
 		list_add(&bus->link, &pmac_i2c_busses);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/powermac/sleep.S
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/powermac/sleep.S
@@ -293,14 +293,7 @@
 	 * we do any r1 memory access as we are not sure they
 	 * are in a sane state above the first 256Mb region
 	 */
-	li	r0,16		/* load up segment register values */
-	mtctr	r0		/* for context 0 */
-	lis	r3,0x2000	/* Ku = 1, VSID = 0 */
-	li	r4,0
-3:	mtsrin	r3,r4
-	addi	r3,r3,0x111	/* increment VSID */
-	addis	r4,r4,0x1000	/* address of next segment */
-	bdnz	3b
+	bl	load_segment_registers
 	sync
 	isync
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/powermac/smp.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/powermac/smp.c
@@ -660,13 +660,13 @@
 
 #endif /* !CONFIG_PPC64 */
 
-/* L2 and L3 cache settings to pass from CPU0 to CPU1 on G4 cpus */
-volatile static long int core99_l2_cache;
-volatile static long int core99_l3_cache;
-
 static void core99_init_caches(int cpu)
 {
 #ifndef CONFIG_PPC64
+	/* L2 and L3 cache settings to pass from CPU0 to CPU1 on G4 cpus */
+	static long int core99_l2_cache;
+	static long int core99_l3_cache;
+
 	if (!cpu_has_feature(CPU_FTR_L2CR))
 		return;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/powernv/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/powernv/Makefile
@@ -20,3 +20,4 @@
 obj-$(CONFIG_PPC_VAS)	+= vas.o vas-window.o vas-debug.o
 obj-$(CONFIG_OCXL_BASE)	+= ocxl.o
 obj-$(CONFIG_SCOM_DEBUGFS) += opal-xscom.o
+obj-$(CONFIG_PPC_SECURE_BOOT) += opal-secvar.o
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/powernv/memtrace.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/powernv/memtrace.c
@@ -30,6 +30,7 @@
 	char name[16];
 };
 
+static DEFINE_MUTEX(memtrace_mutex);
 static u64 memtrace_size;
 
 static struct memtrace_entry *memtrace_array;
@@ -67,6 +68,23 @@
 	return 0;
 }
 
+static void memtrace_clear_range(unsigned long start_pfn,
+				 unsigned long nr_pages)
+{
+	unsigned long pfn;
+
+	/*
+	 * As pages are offline, we cannot trust the memmap anymore. As HIGHMEM
+	 * does not apply, avoid passing around "struct page" and use
+	 * clear_page() instead directly.
+	 */
+	for (pfn = start_pfn; pfn < start_pfn + nr_pages; pfn++) {
+		if (IS_ALIGNED(pfn, PAGES_PER_SECTION))
+			cond_resched();
+		clear_page(__va(PFN_PHYS(pfn)));
+	}
+}
+
 /* called with device_hotplug_lock held */
 static bool memtrace_offline_pages(u32 nid, u64 start_pfn, u64 nr_pages)
 {
@@ -112,6 +130,11 @@
 	for (base_pfn = end_pfn; base_pfn > start_pfn; base_pfn -= nr_pages) {
 		if (memtrace_offline_pages(nid, base_pfn, nr_pages) == true) {
 			/*
+			 * Clear the range while we still have a linear
+			 * mapping.
+			 */
+			memtrace_clear_range(base_pfn, nr_pages);
+			/*
 			 * Remove memory in memory block size chunks so that
 			 * iomem resources are always split to the same size and
 			 * we never try to remove memory that spans two iomem
@@ -268,6 +291,7 @@
 
 static int memtrace_enable_set(void *data, u64 val)
 {
+	int rc = -EAGAIN;
 	u64 bytes;
 
 	/*
@@ -280,25 +304,31 @@
 		return -EINVAL;
 	}
 
+	mutex_lock(&memtrace_mutex);
+
 	/* Re-add/online previously removed/offlined memory */
 	if (memtrace_size) {
 		if (memtrace_online())
-			return -EAGAIN;
+			goto out_unlock;
 	}
 
-	if (!val)
-		return 0;
+	if (!val) {
+		rc = 0;
+		goto out_unlock;
+	}
 
 	/* Offline and remove memory */
 	if (memtrace_init_regions_runtime(val))
-		return -EINVAL;
+		goto out_unlock;
 
 	if (memtrace_init_debugfs())
-		return -EINVAL;
+		goto out_unlock;
 
 	memtrace_size = val;
-
-	return 0;
+	rc = 0;
+out_unlock:
+	mutex_unlock(&memtrace_mutex);
+	return rc;
 }
 
 static int memtrace_enable_get(void *data, u64 *val)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/powernv/npu-dma.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/powernv/npu-dma.c
@@ -384,7 +384,8 @@
 	for (i = 0; i < npucomp->pe_num; ++i) {
 		struct pnv_ioda_pe *pe = npucomp->pe[i];
 
-		if (!pe->table_group.ops->take_ownership)
+		if (!pe->table_group.ops ||
+		    !pe->table_group.ops->take_ownership)
 			continue;
 		pe->table_group.ops->take_ownership(&pe->table_group);
 	}
@@ -400,7 +401,8 @@
 	for (i = 0; i < npucomp->pe_num; ++i) {
 		struct pnv_ioda_pe *pe = npucomp->pe[i];
 
-		if (!pe->table_group.ops->release_ownership)
+		if (!pe->table_group.ops ||
+		    !pe->table_group.ops->release_ownership)
 			continue;
 		pe->table_group.ops->release_ownership(&pe->table_group);
 	}
@@ -560,6 +562,11 @@
 		return -ENODEV;
 
 	hose = pci_bus_to_host(npdev->bus);
+	if (hose->npu == NULL) {
+		dev_info_once(&npdev->dev, "Nvlink1 does not support contexts");
+		return 0;
+	}
+
 	nphb = hose->private_data;
 
 	dev_dbg(&gpdev->dev, "Map LPAR opalid=%llu lparid=%u\n",
@@ -607,6 +614,11 @@
 		return -ENODEV;
 
 	hose = pci_bus_to_host(npdev->bus);
+	if (hose->npu == NULL) {
+		dev_info_once(&npdev->dev, "Nvlink1 does not support contexts");
+		return 0;
+	}
+
 	nphb = hose->private_data;
 
 	dev_dbg(&gpdev->dev, "destroy context opalid=%llu\n",
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/powernv/opal-call.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/powernv/opal-call.c
@@ -290,3 +290,6 @@
 OPAL_CALL(opal_mpipl_update,			OPAL_MPIPL_UPDATE);
 OPAL_CALL(opal_mpipl_register_tag,		OPAL_MPIPL_REGISTER_TAG);
 OPAL_CALL(opal_mpipl_query_tag,			OPAL_MPIPL_QUERY_TAG);
+OPAL_CALL(opal_secvar_get,			OPAL_SECVAR_GET);
+OPAL_CALL(opal_secvar_get_next,			OPAL_SECVAR_GET_NEXT);
+OPAL_CALL(opal_secvar_enqueue_update,		OPAL_SECVAR_ENQUEUE_UPDATE);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/powernv/opal-dump.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/powernv/opal-dump.c
@@ -318,15 +318,14 @@
 	return count;
 }
 
-static struct dump_obj *create_dump_obj(uint32_t id, size_t size,
-					uint32_t type)
+static void create_dump_obj(uint32_t id, size_t size, uint32_t type)
 {
 	struct dump_obj *dump;
 	int rc;
 
 	dump = kzalloc(sizeof(*dump), GFP_KERNEL);
 	if (!dump)
-		return NULL;
+		return;
 
 	dump->kobj.kset = dump_kset;
 
@@ -346,21 +345,39 @@
 	rc = kobject_add(&dump->kobj, NULL, "0x%x-0x%x", type, id);
 	if (rc) {
 		kobject_put(&dump->kobj);
-		return NULL;
+		return;
 	}
 
+	/*
+	 * As soon as the sysfs file for this dump is created/activated there is
+	 * a chance the opal_errd daemon (or any userspace) might read and
+	 * acknowledge the dump before kobject_uevent() is called. If that
+	 * happens then there is a potential race between
+	 * dump_ack_store->kobject_put() and kobject_uevent() which leads to a
+	 * use-after-free of a kernfs object resulting in a kernel crash.
+	 *
+	 * To avoid that, we need to take a reference on behalf of the bin file,
+	 * so that our reference remains valid while we call kobject_uevent().
+	 * We then drop our reference before exiting the function, leaving the
+	 * bin file to drop the last reference (if it hasn't already).
+	 */
+
+	/* Take a reference for the bin file */
+	kobject_get(&dump->kobj);
 	rc = sysfs_create_bin_file(&dump->kobj, &dump->dump_attr);
-	if (rc) {
+	if (rc == 0) {
+		kobject_uevent(&dump->kobj, KOBJ_ADD);
+
+		pr_info("%s: New platform dump. ID = 0x%x Size %u\n",
+			__func__, dump->id, dump->size);
+	} else {
+		/* Drop reference count taken for bin file */
 		kobject_put(&dump->kobj);
-		return NULL;
 	}
 
-	pr_info("%s: New platform dump. ID = 0x%x Size %u\n",
-		__func__, dump->id, dump->size);
-
-	kobject_uevent(&dump->kobj, KOBJ_ADD);
-
-	return dump;
+	/* Drop our reference */
+	kobject_put(&dump->kobj);
+	return;
 }
 
 static irqreturn_t process_dump(int irq, void *data)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/powernv/opal-elog.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/powernv/opal-elog.c
@@ -179,14 +179,14 @@
 	return count;
 }
 
-static struct elog_obj *create_elog_obj(uint64_t id, size_t size, uint64_t type)
+static void create_elog_obj(uint64_t id, size_t size, uint64_t type)
 {
 	struct elog_obj *elog;
 	int rc;
 
 	elog = kzalloc(sizeof(*elog), GFP_KERNEL);
 	if (!elog)
-		return NULL;
+		return;
 
 	elog->kobj.kset = elog_kset;
 
@@ -219,18 +219,37 @@
 	rc = kobject_add(&elog->kobj, NULL, "0x%llx", id);
 	if (rc) {
 		kobject_put(&elog->kobj);
-		return NULL;
+		return;
 	}
 
+	/*
+	 * As soon as the sysfs file for this elog is created/activated there is
+	 * a chance the opal_errd daemon (or any userspace) might read and
+	 * acknowledge the elog before kobject_uevent() is called. If that
+	 * happens then there is a potential race between
+	 * elog_ack_store->kobject_put() and kobject_uevent() which leads to a
+	 * use-after-free of a kernfs object resulting in a kernel crash.
+	 *
+	 * To avoid that, we need to take a reference on behalf of the bin file,
+	 * so that our reference remains valid while we call kobject_uevent().
+	 * We then drop our reference before exiting the function, leaving the
+	 * bin file to drop the last reference (if it hasn't already).
+	 */
+
+	/* Take a reference for the bin file */
+	kobject_get(&elog->kobj);
 	rc = sysfs_create_bin_file(&elog->kobj, &elog->raw_attr);
-	if (rc) {
+	if (rc == 0) {
+		kobject_uevent(&elog->kobj, KOBJ_ADD);
+	} else {
+		/* Drop the reference taken for the bin file */
 		kobject_put(&elog->kobj);
-		return NULL;
 	}
 
-	kobject_uevent(&elog->kobj, KOBJ_ADD);
+	/* Drop our reference */
+	kobject_put(&elog->kobj);
 
-	return elog;
+	return;
 }
 
 static irqreturn_t elog_event(int irq, void *data)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/powernv/opal-fadump.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/powernv/opal-fadump.c
@@ -60,7 +60,7 @@
 	addr = be64_to_cpu(addr);
 	pr_debug("Kernel metadata addr: %llx\n", addr);
 	opal_fdm_active = (void *)addr;
-	if (opal_fdm_active->registered_regions == 0)
+	if (be16_to_cpu(opal_fdm_active->registered_regions) == 0)
 		return;
 
 	ret = opal_mpipl_query_tag(OPAL_MPIPL_TAG_BOOT_MEM, &addr);
@@ -95,17 +95,17 @@
 static void opal_fadump_update_config(struct fw_dump *fadump_conf,
 				      const struct opal_fadump_mem_struct *fdm)
 {
-	pr_debug("Boot memory regions count: %d\n", fdm->region_cnt);
+	pr_debug("Boot memory regions count: %d\n", be16_to_cpu(fdm->region_cnt));
 
 	/*
 	 * The destination address of the first boot memory region is the
 	 * destination address of boot memory regions.
 	 */
-	fadump_conf->boot_mem_dest_addr = fdm->rgn[0].dest;
+	fadump_conf->boot_mem_dest_addr = be64_to_cpu(fdm->rgn[0].dest);
 	pr_debug("Destination address of boot memory regions: %#016llx\n",
 		 fadump_conf->boot_mem_dest_addr);
 
-	fadump_conf->fadumphdr_addr = fdm->fadumphdr_addr;
+	fadump_conf->fadumphdr_addr = be64_to_cpu(fdm->fadumphdr_addr);
 }
 
 /*
@@ -126,9 +126,9 @@
 	fadump_conf->boot_memory_size = 0;
 
 	pr_debug("Boot memory regions:\n");
-	for (i = 0; i < fdm->region_cnt; i++) {
-		base = fdm->rgn[i].src;
-		size = fdm->rgn[i].size;
+	for (i = 0; i < be16_to_cpu(fdm->region_cnt); i++) {
+		base = be64_to_cpu(fdm->rgn[i].src);
+		size = be64_to_cpu(fdm->rgn[i].size);
 		pr_debug("\t[%03d] base: 0x%lx, size: 0x%lx\n", i, base, size);
 
 		fadump_conf->boot_mem_addr[i] = base;
@@ -143,7 +143,7 @@
 	 * Start address of reserve dump area (permanent reservation) for
 	 * re-registering FADump after dump capture.
 	 */
-	fadump_conf->reserve_dump_area_start = fdm->rgn[0].dest;
+	fadump_conf->reserve_dump_area_start = be64_to_cpu(fdm->rgn[0].dest);
 
 	/*
 	 * Rarely, but it can so happen that system crashes before all
@@ -155,13 +155,14 @@
 	 * Hope the memory that could not be preserved only has pages
 	 * that are usually filtered out while saving the vmcore.
 	 */
-	if (fdm->region_cnt > fdm->registered_regions) {
+	if (be16_to_cpu(fdm->region_cnt) > be16_to_cpu(fdm->registered_regions)) {
 		pr_warn("Not all memory regions were saved!!!\n");
 		pr_warn("  Unsaved memory regions:\n");
-		i = fdm->registered_regions;
-		while (i < fdm->region_cnt) {
+		i = be16_to_cpu(fdm->registered_regions);
+		while (i < be16_to_cpu(fdm->region_cnt)) {
 			pr_warn("\t[%03d] base: 0x%llx, size: 0x%llx\n",
-				i, fdm->rgn[i].src, fdm->rgn[i].size);
+				i, be64_to_cpu(fdm->rgn[i].src),
+				be64_to_cpu(fdm->rgn[i].size));
 			i++;
 		}
 
@@ -170,7 +171,7 @@
 	}
 
 	fadump_conf->boot_mem_top = (fadump_conf->boot_memory_size + hole_size);
-	fadump_conf->boot_mem_regs_cnt = fdm->region_cnt;
+	fadump_conf->boot_mem_regs_cnt = be16_to_cpu(fdm->region_cnt);
 	opal_fadump_update_config(fadump_conf, fdm);
 }
 
@@ -178,35 +179,38 @@
 static void opal_fadump_init_metadata(struct opal_fadump_mem_struct *fdm)
 {
 	fdm->version = OPAL_FADUMP_VERSION;
-	fdm->region_cnt = 0;
-	fdm->registered_regions = 0;
-	fdm->fadumphdr_addr = 0;
+	fdm->region_cnt = cpu_to_be16(0);
+	fdm->registered_regions = cpu_to_be16(0);
+	fdm->fadumphdr_addr = cpu_to_be64(0);
 }
 
 static u64 opal_fadump_init_mem_struct(struct fw_dump *fadump_conf)
 {
 	u64 addr = fadump_conf->reserve_dump_area_start;
+	u16 reg_cnt;
 	int i;
 
 	opal_fdm = __va(fadump_conf->kernel_metadata);
 	opal_fadump_init_metadata(opal_fdm);
 
 	/* Boot memory regions */
+	reg_cnt = be16_to_cpu(opal_fdm->region_cnt);
 	for (i = 0; i < fadump_conf->boot_mem_regs_cnt; i++) {
-		opal_fdm->rgn[i].src	= fadump_conf->boot_mem_addr[i];
-		opal_fdm->rgn[i].dest	= addr;
-		opal_fdm->rgn[i].size	= fadump_conf->boot_mem_sz[i];
+		opal_fdm->rgn[i].src	= cpu_to_be64(fadump_conf->boot_mem_addr[i]);
+		opal_fdm->rgn[i].dest	= cpu_to_be64(addr);
+		opal_fdm->rgn[i].size	= cpu_to_be64(fadump_conf->boot_mem_sz[i]);
 
-		opal_fdm->region_cnt++;
+		reg_cnt++;
 		addr += fadump_conf->boot_mem_sz[i];
 	}
+	opal_fdm->region_cnt = cpu_to_be16(reg_cnt);
 
 	/*
 	 * Kernel metadata is passed to f/w and retrieved in capture kerenl.
 	 * So, use it to save fadump header address instead of calculating it.
 	 */
-	opal_fdm->fadumphdr_addr = (opal_fdm->rgn[0].dest +
-				    fadump_conf->boot_memory_size);
+	opal_fdm->fadumphdr_addr = cpu_to_be64(be64_to_cpu(opal_fdm->rgn[0].dest) +
+					       fadump_conf->boot_memory_size);
 
 	opal_fadump_update_config(fadump_conf, opal_fdm);
 
@@ -269,18 +273,21 @@
 static int opal_fadump_register(struct fw_dump *fadump_conf)
 {
 	s64 rc = OPAL_PARAMETER;
+	u16 registered_regs;
 	int i, err = -EIO;
 
-	for (i = 0; i < opal_fdm->region_cnt; i++) {
+	registered_regs = be16_to_cpu(opal_fdm->registered_regions);
+	for (i = 0; i < be16_to_cpu(opal_fdm->region_cnt); i++) {
 		rc = opal_mpipl_update(OPAL_MPIPL_ADD_RANGE,
-				       opal_fdm->rgn[i].src,
-				       opal_fdm->rgn[i].dest,
-				       opal_fdm->rgn[i].size);
+				       be64_to_cpu(opal_fdm->rgn[i].src),
+				       be64_to_cpu(opal_fdm->rgn[i].dest),
+				       be64_to_cpu(opal_fdm->rgn[i].size));
 		if (rc != OPAL_SUCCESS)
 			break;
 
-		opal_fdm->registered_regions++;
+		registered_regs++;
 	}
+	opal_fdm->registered_regions = cpu_to_be16(registered_regs);
 
 	switch (rc) {
 	case OPAL_SUCCESS:
@@ -291,7 +298,8 @@
 	case OPAL_RESOURCE:
 		/* If MAX regions limit in f/w is hit, warn and proceed. */
 		pr_warn("%d regions could not be registered for MPIPL as MAX limit is reached!\n",
-			(opal_fdm->region_cnt - opal_fdm->registered_regions));
+			(be16_to_cpu(opal_fdm->region_cnt) -
+			 be16_to_cpu(opal_fdm->registered_regions)));
 		fadump_conf->dump_registered = 1;
 		err = 0;
 		break;
@@ -312,7 +320,7 @@
 	 * If some regions were registered before OPAL_MPIPL_ADD_RANGE
 	 * OPAL call failed, unregister all regions.
 	 */
-	if ((err < 0) && (opal_fdm->registered_regions > 0))
+	if ((err < 0) && (be16_to_cpu(opal_fdm->registered_regions) > 0))
 		opal_fadump_unregister(fadump_conf);
 
 	return err;
@@ -328,7 +336,7 @@
 		return -EIO;
 	}
 
-	opal_fdm->registered_regions = 0;
+	opal_fdm->registered_regions = cpu_to_be16(0);
 	fadump_conf->dump_registered = 0;
 	return 0;
 }
@@ -563,19 +571,20 @@
 	else
 		fdm_ptr = opal_fdm;
 
-	for (i = 0; i < fdm_ptr->region_cnt; i++) {
+	for (i = 0; i < be16_to_cpu(fdm_ptr->region_cnt); i++) {
 		/*
 		 * Only regions that are registered for MPIPL
 		 * would have dump data.
 		 */
 		if ((fadump_conf->dump_active) &&
-		    (i < fdm_ptr->registered_regions))
-			dumped_bytes = fdm_ptr->rgn[i].size;
+		    (i < be16_to_cpu(fdm_ptr->registered_regions)))
+			dumped_bytes = be64_to_cpu(fdm_ptr->rgn[i].size);
 
 		seq_printf(m, "DUMP: Src: %#016llx, Dest: %#016llx, ",
-			   fdm_ptr->rgn[i].src, fdm_ptr->rgn[i].dest);
+			   be64_to_cpu(fdm_ptr->rgn[i].src),
+			   be64_to_cpu(fdm_ptr->rgn[i].dest));
 		seq_printf(m, "Size: %#llx, Dumped: %#llx bytes\n",
-			   fdm_ptr->rgn[i].size, dumped_bytes);
+			   be64_to_cpu(fdm_ptr->rgn[i].size), dumped_bytes);
 	}
 
 	/* Dump is active. Show reserved area start address. */
@@ -624,6 +633,7 @@
 {
 	const __be32 *prop;
 	unsigned long dn;
+	__be64 be_addr;
 	u64 addr = 0;
 	int i, len;
 	s64 ret;
@@ -680,13 +690,13 @@
 	if (!prop)
 		return;
 
-	ret = opal_mpipl_query_tag(OPAL_MPIPL_TAG_KERNEL, &addr);
-	if ((ret != OPAL_SUCCESS) || !addr) {
+	ret = opal_mpipl_query_tag(OPAL_MPIPL_TAG_KERNEL, &be_addr);
+	if ((ret != OPAL_SUCCESS) || !be_addr) {
 		pr_err("Failed to get Kernel metadata (%lld)\n", ret);
 		return;
 	}
 
-	addr = be64_to_cpu(addr);
+	addr = be64_to_cpu(be_addr);
 	pr_debug("Kernel metadata addr: %llx\n", addr);
 
 	opal_fdm_active = __va(addr);
@@ -697,14 +707,14 @@
 	}
 
 	/* Kernel regions not registered with f/w for MPIPL */
-	if (opal_fdm_active->registered_regions == 0) {
+	if (be16_to_cpu(opal_fdm_active->registered_regions) == 0) {
 		opal_fdm_active = NULL;
 		return;
 	}
 
-	ret = opal_mpipl_query_tag(OPAL_MPIPL_TAG_CPU, &addr);
-	if (addr) {
-		addr = be64_to_cpu(addr);
+	ret = opal_mpipl_query_tag(OPAL_MPIPL_TAG_CPU, &be_addr);
+	if (be_addr) {
+		addr = be64_to_cpu(be_addr);
 		pr_debug("CPU metadata addr: %llx\n", addr);
 		opal_cpu_metadata = __va(addr);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/powernv/opal-fadump.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/powernv/opal-fadump.h
@@ -31,14 +31,14 @@
  * OPAL FADump kernel metadata
  *
  * The address of this structure will be registered with f/w for retrieving
- * and processing during crash dump.
+ * in the capture kernel to process the crash dump.
  */
 struct opal_fadump_mem_struct {
 	u8	version;
 	u8	reserved[3];
-	u16	region_cnt;		/* number of regions */
-	u16	registered_regions;	/* Regions registered for MPIPL */
-	u64	fadumphdr_addr;
+	__be16	region_cnt;		/* number of regions */
+	__be16	registered_regions;	/* Regions registered for MPIPL */
+	__be64	fadumphdr_addr;
 	struct opal_mpipl_region	rgn[FADUMP_MAX_MEM_REGS];
 } __packed;
 
@@ -135,7 +135,7 @@
 	for (i = 0; i < regs_cnt; i++, bufp += reg_entry_size) {
 		reg_entry = (struct hdat_fadump_reg_entry *)bufp;
 		val = (cpu_endian ? be64_to_cpu(reg_entry->reg_val) :
-		       reg_entry->reg_val);
+		       (u64)(reg_entry->reg_val));
 		opal_fadump_set_regval_regnum(regs,
 					      be32_to_cpu(reg_entry->reg_type),
 					      be32_to_cpu(reg_entry->reg_num),
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/powernv/opal-imc.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/powernv/opal-imc.c
@@ -59,10 +59,6 @@
 
 	imc_debugfs_parent = debugfs_create_dir("imc", powerpc_debugfs_root);
 
-	/*
-	 * Return here, either because 'imc' directory already exists,
-	 * Or failed to create a new one.
-	 */
 	if (!imc_debugfs_parent)
 		return;
 
@@ -135,7 +131,6 @@
 	}
 
 	pmu_ptr->imc_counter_mmaped = true;
-	export_imc_mode_and_cmd(node, pmu_ptr);
 	kfree(base_addr_arr);
 	kfree(chipid_arr);
 	return 0;
@@ -151,7 +146,7 @@
  *		    and domain as the inputs.
  * Allocates memory for the struct imc_pmu, sets up its domain, size and offsets
  */
-static int imc_pmu_create(struct device_node *parent, int pmu_index, int domain)
+static struct imc_pmu *imc_pmu_create(struct device_node *parent, int pmu_index, int domain)
 {
 	int ret = 0;
 	struct imc_pmu *pmu_ptr;
@@ -159,27 +154,23 @@
 
 	/* Return for unknown domain */
 	if (domain < 0)
-		return -EINVAL;
+		return NULL;
 
 	/* memory for pmu */
 	pmu_ptr = kzalloc(sizeof(*pmu_ptr), GFP_KERNEL);
 	if (!pmu_ptr)
-		return -ENOMEM;
+		return NULL;
 
 	/* Set the domain */
 	pmu_ptr->domain = domain;
 
 	ret = of_property_read_u32(parent, "size", &pmu_ptr->counter_mem_size);
-	if (ret) {
-		ret = -EINVAL;
+	if (ret)
 		goto free_pmu;
-	}
 
 	if (!of_property_read_u32(parent, "offset", &offset)) {
-		if (imc_get_mem_addr_nest(parent, pmu_ptr, offset)) {
-			ret = -EINVAL;
+		if (imc_get_mem_addr_nest(parent, pmu_ptr, offset))
 			goto free_pmu;
-		}
 	}
 
 	/* Function to register IMC pmu */
@@ -190,14 +181,14 @@
 		if (pmu_ptr->domain == IMC_DOMAIN_NEST)
 			kfree(pmu_ptr->mem_info);
 		kfree(pmu_ptr);
-		return ret;
+		return NULL;
 	}
 
-	return 0;
+	return pmu_ptr;
 
 free_pmu:
 	kfree(pmu_ptr);
-	return ret;
+	return NULL;
 }
 
 static void disable_nest_pmu_counters(void)
@@ -254,6 +245,7 @@
 static int opal_imc_counters_probe(struct platform_device *pdev)
 {
 	struct device_node *imc_dev = pdev->dev.of_node;
+	struct imc_pmu *pmu;
 	int pmu_count = 0, domain;
 	bool core_imc_reg = false, thread_imc_reg = false;
 	u32 type;
@@ -269,6 +261,7 @@
 	}
 
 	for_each_compatible_node(imc_dev, NULL, IMC_DTB_UNIT_COMPAT) {
+		pmu = NULL;
 		if (of_property_read_u32(imc_dev, "type", &type)) {
 			pr_warn("IMC Device without type property\n");
 			continue;
@@ -285,7 +278,14 @@
 			domain = IMC_DOMAIN_THREAD;
 			break;
 		case IMC_TYPE_TRACE:
-			domain = IMC_DOMAIN_TRACE;
+			/*
+			 * FIXME. Using trace_imc events to monitor application
+			 * or KVM thread performance can cause a checkstop
+			 * (system crash).
+			 * Disable it for now.
+			 */
+			pr_info_once("IMC: disabling trace_imc PMU\n");
+			domain = -1;
 			break;
 		default:
 			pr_warn("IMC Unknown Device type \n");
@@ -293,9 +293,13 @@
 			break;
 		}
 
-		if (!imc_pmu_create(imc_dev, pmu_count, domain)) {
-			if (domain == IMC_DOMAIN_NEST)
+		pmu = imc_pmu_create(imc_dev, pmu_count, domain);
+		if (pmu != NULL) {
+			if (domain == IMC_DOMAIN_NEST) {
+				if (!imc_debugfs_parent)
+					export_imc_mode_and_cmd(imc_dev, pmu);
 				pmu_count++;
+			}
 			if (domain == IMC_DOMAIN_CORE)
 				core_imc_reg = true;
 			if (domain == IMC_DOMAIN_THREAD)
@@ -303,10 +307,6 @@
 		}
 	}
 
-	/* If none of the nest units are registered, remove debugfs interface */
-	if (pmu_count == 0)
-		debugfs_remove_recursive(imc_debugfs_parent);
-
 	/* If core imc is not registered, unregister thread-imc */
 	if (!core_imc_reg && thread_imc_reg)
 		unregister_thread_imc();
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/powernv/opal-irqchip.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/powernv/opal-irqchip.c
@@ -278,11 +278,14 @@
 		else
 			name = kasprintf(GFP_KERNEL, "opal");
 
+		if (!name)
+			continue;
 		/* Install interrupt handler */
 		rc = request_irq(r->start, opal_interrupt, r->flags & IRQD_TRIGGER_MASK,
 				 name, NULL);
 		if (rc) {
 			pr_warn("Error %d requesting OPAL irq %d\n", rc, (int)r->start);
+			kfree(name);
 			continue;
 		}
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/powernv/opal-lpc.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/powernv/opal-lpc.c
@@ -396,6 +396,7 @@
 		if (!of_get_property(np, "primary", NULL))
 			continue;
 		opal_lpc_chip_id = of_get_ibm_chip_id(np);
+		of_node_put(np);
 		break;
 	}
 	if (opal_lpc_chip_id < 0)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/powernv/opal-powercap.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/powernv/opal-powercap.c
@@ -196,6 +196,12 @@
 
 		j = 0;
 		pcaps[i].pg.name = kasprintf(GFP_KERNEL, "%pOFn", node);
+		if (!pcaps[i].pg.name) {
+			kfree(pcaps[i].pattrs);
+			kfree(pcaps[i].pg.attrs);
+			goto out_pcaps_pattrs;
+		}
+
 		if (has_min) {
 			powercap_add_attr(min, "powercap-min",
 					  &pcaps[i].pattrs[j]);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/powernv/opal-prd.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/powernv/opal-prd.c
@@ -372,6 +372,12 @@
 	.priority	= 0,
 };
 
+static struct notifier_block opal_prd_event_nb2 = {
+	.notifier_call	= opal_prd_msg_notifier,
+	.next		= NULL,
+	.priority	= 0,
+};
+
 static int opal_prd_probe(struct platform_device *pdev)
 {
 	int rc;
@@ -393,9 +399,10 @@
 		return rc;
 	}
 
-	rc = opal_message_notifier_register(OPAL_MSG_PRD2, &opal_prd_event_nb);
+	rc = opal_message_notifier_register(OPAL_MSG_PRD2, &opal_prd_event_nb2);
 	if (rc) {
 		pr_err("Couldn't register PRD2 event notifier\n");
+		opal_message_notifier_unregister(OPAL_MSG_PRD, &opal_prd_event_nb);
 		return rc;
 	}
 
@@ -404,6 +411,8 @@
 		pr_err("failed to register miscdev\n");
 		opal_message_notifier_unregister(OPAL_MSG_PRD,
 				&opal_prd_event_nb);
+		opal_message_notifier_unregister(OPAL_MSG_PRD2,
+				&opal_prd_event_nb2);
 		return rc;
 	}
 
@@ -414,6 +423,7 @@
 {
 	misc_deregister(&opal_prd_dev);
 	opal_message_notifier_unregister(OPAL_MSG_PRD, &opal_prd_event_nb);
+	opal_message_notifier_unregister(OPAL_MSG_PRD2, &opal_prd_event_nb2);
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/powernv/opal-secvar.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/powernv/opal-secvar.c
@@ -0,0 +1,140 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PowerNV code for secure variables
+ *
+ * Copyright (C) 2019 IBM Corporation
+ * Author: Claudio Carvalho
+ *         Nayna Jain
+ *
+ * APIs to access secure variables managed by OPAL.
+ */
+
+#define pr_fmt(fmt) "secvar: "fmt
+
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/of_platform.h>
+#include <asm/opal.h>
+#include <asm/secvar.h>
+#include <asm/secure_boot.h>
+
+static int opal_status_to_err(int rc)
+{
+	int err;
+
+	switch (rc) {
+	case OPAL_SUCCESS:
+		err = 0;
+		break;
+	case OPAL_UNSUPPORTED:
+		err = -ENXIO;
+		break;
+	case OPAL_PARAMETER:
+		err = -EINVAL;
+		break;
+	case OPAL_RESOURCE:
+		err = -ENOSPC;
+		break;
+	case OPAL_HARDWARE:
+		err = -EIO;
+		break;
+	case OPAL_NO_MEM:
+		err = -ENOMEM;
+		break;
+	case OPAL_EMPTY:
+		err = -ENOENT;
+		break;
+	case OPAL_PARTIAL:
+		err = -EFBIG;
+		break;
+	default:
+		err = -EINVAL;
+	}
+
+	return err;
+}
+
+static int opal_get_variable(const char *key, uint64_t ksize,
+			     u8 *data, uint64_t *dsize)
+{
+	int rc;
+
+	if (!key || !dsize)
+		return -EINVAL;
+
+	*dsize = cpu_to_be64(*dsize);
+
+	rc = opal_secvar_get(key, ksize, data, dsize);
+
+	*dsize = be64_to_cpu(*dsize);
+
+	return opal_status_to_err(rc);
+}
+
+static int opal_get_next_variable(const char *key, uint64_t *keylen,
+				  uint64_t keybufsize)
+{
+	int rc;
+
+	if (!key || !keylen)
+		return -EINVAL;
+
+	*keylen = cpu_to_be64(*keylen);
+
+	rc = opal_secvar_get_next(key, keylen, keybufsize);
+
+	*keylen = be64_to_cpu(*keylen);
+
+	return opal_status_to_err(rc);
+}
+
+static int opal_set_variable(const char *key, uint64_t ksize, u8 *data,
+			     uint64_t dsize)
+{
+	int rc;
+
+	if (!key || !data)
+		return -EINVAL;
+
+	rc = opal_secvar_enqueue_update(key, ksize, data, dsize);
+
+	return opal_status_to_err(rc);
+}
+
+static const struct secvar_operations opal_secvar_ops = {
+	.get = opal_get_variable,
+	.get_next = opal_get_next_variable,
+	.set = opal_set_variable,
+};
+
+static int opal_secvar_probe(struct platform_device *pdev)
+{
+	if (!opal_check_token(OPAL_SECVAR_GET)
+			|| !opal_check_token(OPAL_SECVAR_GET_NEXT)
+			|| !opal_check_token(OPAL_SECVAR_ENQUEUE_UPDATE)) {
+		pr_err("OPAL doesn't support secure variables\n");
+		return -ENODEV;
+	}
+
+	set_secvar_ops(&opal_secvar_ops);
+
+	return 0;
+}
+
+static const struct of_device_id opal_secvar_match[] = {
+	{ .compatible = "ibm,secvar-backend",},
+	{},
+};
+
+static struct platform_driver opal_secvar_driver = {
+	.driver = {
+		.name = "secvar",
+		.of_match_table = opal_secvar_match,
+	},
+};
+
+static int __init opal_secvar_init(void)
+{
+	return platform_driver_probe(&opal_secvar_driver, opal_secvar_probe);
+}
+device_initcall(opal_secvar_init);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/powernv/opal-xscom.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/powernv/opal-xscom.c
@@ -165,6 +165,11 @@
 	ent->chip = chip;
 	snprintf(ent->name, 16, "%08x", chip);
 	ent->path.data = (void *)kasprintf(GFP_KERNEL, "%pOF", dn);
+	if (!ent->path.data) {
+		kfree(ent);
+		return -ENOMEM;
+	}
+
 	ent->path.size = strlen((char *)ent->path.data);
 
 	dir = debugfs_create_dir(ent->name, root);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/powernv/opal.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/powernv/opal.c
@@ -776,6 +776,7 @@
 	kobj = kobject_create_and_add("exports", opal_kobj);
 	if (!kobj) {
 		pr_warn("kobject_create_and_add() of exports failed\n");
+		of_node_put(np);
 		return;
 	}
 
@@ -1002,6 +1003,9 @@
 	/* Initialise OPAL Power control interface */
 	opal_power_control_init();
 
+	/* Initialize OPAL secure variables */
+	opal_pdev_init("ibm,secvar-backend");
+
 	return 0;
 }
 machine_subsys_initcall(powernv, opal_init);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/powernv/pci-ioda.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -188,7 +188,7 @@
 	unsigned int pe_num = pe->pe_number;
 
 	WARN_ON(pe->pdev);
-	WARN_ON(pe->npucomp); /* NPUs are not supposed to be freed */
+	WARN_ON(pe->npucomp); /* NPUs for nvlink are not supposed to be freed */
 	kfree(pe->npucomp);
 	memset(pe, 0, sizeof(struct pnv_ioda_pe));
 	clear_bit(pe_num, phb->ioda.pe_alloc);
@@ -777,6 +777,34 @@
 	return 0;
 }
 
+static void pnv_ioda_unset_peltv(struct pnv_phb *phb,
+				 struct pnv_ioda_pe *pe,
+				 struct pci_dev *parent)
+{
+	int64_t rc;
+
+	while (parent) {
+		struct pci_dn *pdn = pci_get_pdn(parent);
+
+		if (pdn && pdn->pe_number != IODA_INVALID_PE) {
+			rc = opal_pci_set_peltv(phb->opal_id, pdn->pe_number,
+						pe->pe_number,
+						OPAL_REMOVE_PE_FROM_DOMAIN);
+			/* XXX What to do in case of error ? */
+		}
+		parent = parent->bus->self;
+	}
+
+	opal_pci_eeh_freeze_clear(phb->opal_id, pe->pe_number,
+				  OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
+
+	/* Disassociate PE in PELT */
+	rc = opal_pci_set_peltv(phb->opal_id, pe->pe_number,
+				pe->pe_number, OPAL_REMOVE_PE_FROM_DOMAIN);
+	if (rc)
+		pe_warn(pe, "OPAL error %lld remove self from PELTV\n", rc);
+}
+
 static int pnv_ioda_deconfigure_pe(struct pnv_phb *phb, struct pnv_ioda_pe *pe)
 {
 	struct pci_dev *parent;
@@ -827,25 +855,13 @@
 	for (rid = pe->rid; rid < rid_end; rid++)
 		phb->ioda.pe_rmap[rid] = IODA_INVALID_PE;
 
-	/* Release from all parents PELT-V */
-	while (parent) {
-		struct pci_dn *pdn = pci_get_pdn(parent);
-		if (pdn && pdn->pe_number != IODA_INVALID_PE) {
-			rc = opal_pci_set_peltv(phb->opal_id, pdn->pe_number,
-						pe->pe_number, OPAL_REMOVE_PE_FROM_DOMAIN);
-			/* XXX What to do in case of error ? */
-		}
-		parent = parent->bus->self;
-	}
-
-	opal_pci_eeh_freeze_clear(phb->opal_id, pe->pe_number,
-				  OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
+	/*
+	 * Release from all parents PELT-V. NPUs don't have a PELTV
+	 * table
+	 */
+	if (phb->type != PNV_PHB_NPU_NVLINK && phb->type != PNV_PHB_NPU_OCAPI)
+		pnv_ioda_unset_peltv(phb, pe, parent);
 
-	/* Disassociate PE in PELT */
-	rc = opal_pci_set_peltv(phb->opal_id, pe->pe_number,
-				pe->pe_number, OPAL_REMOVE_PE_FROM_DOMAIN);
-	if (rc)
-		pe_warn(pe, "OPAL error %lld remove self from PELTV\n", rc);
 	rc = opal_pci_set_pe(phb->opal_id, pe->pe_number, pe->rid,
 			     bcomp, dcomp, fcomp, OPAL_UNMAP_PE);
 	if (rc)
@@ -1062,20 +1078,20 @@
 		return NULL;
 	}
 
-	/* NOTE: We get only one ref to the pci_dev for the pdn, not for the
-	 * pointer in the PE data structure, both should be destroyed at the
-	 * same time. However, this needs to be looked at more closely again
-	 * once we actually start removing things (Hotplug, SR-IOV, ...)
+	/* NOTE: We don't get a reference for the pointer in the PE
+	 * data structure, both the device and PE structures should be
+	 * destroyed at the same time. However, removing nvlink
+	 * devices will need some work.
 	 *
 	 * At some point we want to remove the PDN completely anyways
 	 */
-	pci_dev_get(dev);
 	pdn->pe_number = pe->pe_number;
 	pe->flags = PNV_IODA_PE_DEV;
 	pe->pdev = dev;
 	pe->pbus = NULL;
 	pe->mve_number = -1;
 	pe->rid = dev->bus->number << 8 | pdn->devfn;
+	pe->device_count++;
 
 	pe_info(pe, "Associated device to PE\n");
 
@@ -1084,13 +1100,13 @@
 		pnv_ioda_free_pe(pe);
 		pdn->pe_number = IODA_INVALID_PE;
 		pe->pdev = NULL;
-		pci_dev_put(dev);
 		return NULL;
 	}
 
 	/* Put PE to the list */
+	mutex_lock(&phb->ioda.pe_list_mutex);
 	list_add_tail(&pe->list, &phb->ioda.pe_list);
-
+	mutex_unlock(&phb->ioda.pe_list_mutex);
 	return pe;
 }
 
@@ -1206,6 +1222,14 @@
 	struct pnv_phb *phb = hose->private_data;
 
 	/*
+	 * Intentionally leak a reference on the npu device (for
+	 * nvlink only; this is not an opencapi path) to make sure it
+	 * never goes away, as it's been the case all along and some
+	 * work is needed otherwise.
+	 */
+	pci_dev_get(npu_pdev);
+
+	/*
 	 * Due to a hardware errata PE#0 on the NPU is reserved for
 	 * error handling. This means we only have three PEs remaining
 	 * which need to be assigned to four links, implying some
@@ -1228,11 +1252,11 @@
 			 */
 			dev_info(&npu_pdev->dev,
 				"Associating to existing PE %x\n", pe_num);
-			pci_dev_get(npu_pdev);
 			npu_pdn = pci_get_pdn(npu_pdev);
 			rid = npu_pdev->bus->number << 8 | npu_pdn->devfn;
 			npu_pdn->pe_number = pe_num;
 			phb->ioda.pe_rmap[rid] = pe->pe_number;
+			pe->device_count++;
 
 			/* Map the PE to this link */
 			rc = opal_pci_set_pe(phb->opal_id, pe_num, rid,
@@ -1268,8 +1292,6 @@
 {
 	struct pci_controller *hose;
 	struct pnv_phb *phb;
-	struct pci_bus *bus;
-	struct pci_dev *pdev;
 	struct pnv_ioda_pe *pe;
 
 	list_for_each_entry(hose, &hose_list, list_node) {
@@ -1281,11 +1303,6 @@
 			if (phb->model == PNV_PHB_MODEL_NPU2)
 				WARN_ON_ONCE(pnv_npu2_init(hose));
 		}
-		if (phb->type == PNV_PHB_NPU_OCAPI) {
-			bus = hose->bus;
-			list_for_each_entry(pdev, &bus->devices, bus_list)
-				pnv_ioda_setup_dev_PE(pdev);
-		}
 	}
 	list_for_each_entry(hose, &hose_list, list_node) {
 		phb = hose->private_data;
@@ -1558,6 +1575,10 @@
 
 	/* Reserve PE for each VF */
 	for (vf_index = 0; vf_index < num_vfs; vf_index++) {
+		int vf_devfn = pci_iov_virtfn_devfn(pdev, vf_index);
+		int vf_bus = pci_iov_virtfn_bus(pdev, vf_index);
+		struct pci_dn *vf_pdn;
+
 		if (pdn->m64_single_mode)
 			pe_num = pdn->pe_num_map[vf_index];
 		else
@@ -1570,13 +1591,11 @@
 		pe->pbus = NULL;
 		pe->parent_dev = pdev;
 		pe->mve_number = -1;
-		pe->rid = (pci_iov_virtfn_bus(pdev, vf_index) << 8) |
-			   pci_iov_virtfn_devfn(pdev, vf_index);
+		pe->rid = (vf_bus << 8) | vf_devfn;
 
 		pe_info(pe, "VF %04d:%02d:%02d.%d associated with PE#%x\n",
 			hose->global_number, pdev->bus->number,
-			PCI_SLOT(pci_iov_virtfn_devfn(pdev, vf_index)),
-			PCI_FUNC(pci_iov_virtfn_devfn(pdev, vf_index)), pe_num);
+			PCI_SLOT(vf_devfn), PCI_FUNC(vf_devfn), pe_num);
 
 		if (pnv_ioda_configure_pe(phb, pe)) {
 			/* XXX What do we do here ? */
@@ -1590,6 +1609,15 @@
 		list_add_tail(&pe->list, &phb->ioda.pe_list);
 		mutex_unlock(&phb->ioda.pe_list_mutex);
 
+		/* associate this pe to it's pdn */
+		list_for_each_entry(vf_pdn, &pdn->parent->child_list, list) {
+			if (vf_pdn->busno == vf_bus &&
+			    vf_pdn->devfn == vf_devfn) {
+				vf_pdn->pe_number = pe_num;
+				break;
+			}
+		}
+
 		pnv_pci_ioda2_setup_dma_pe(phb, pe);
 #ifdef CONFIG_IOMMU_API
 		iommu_register_group(&pe->table_group,
@@ -2889,9 +2917,6 @@
 	struct pci_dn *pdn;
 	int mul, total_vfs;
 
-	if (!pdev->is_physfn || pci_dev_is_added(pdev))
-		return;
-
 	pdn = pci_get_pdn(pdev);
 	pdn->vfs_expanded = 0;
 	pdn->m64_single_mode = false;
@@ -2966,6 +2991,30 @@
 		res->end = res->start - 1;
 	}
 }
+
+static void pnv_pci_ioda_fixup_iov(struct pci_dev *pdev)
+{
+	if (WARN_ON(pci_dev_is_added(pdev)))
+		return;
+
+	if (pdev->is_virtfn) {
+		struct pnv_ioda_pe *pe = pnv_ioda_get_pe(pdev);
+
+		/*
+		 * VF PEs are single-device PEs so their pdev pointer needs to
+		 * be set. The pdev doesn't exist when the PE is allocated (in
+		 * (pcibios_sriov_enable()) so we fix it up here.
+		 */
+		pe->pdev = pdev;
+		WARN_ON(!(pe->flags & PNV_IODA_PE_VF));
+	} else if (pdev->is_physfn) {
+		/*
+		 * For PFs adjust their allocated IOV resources to match what
+		 * the PHB can support using it's M64 BAR table.
+		 */
+		pnv_pci_ioda_fixup_iov_resources(pdev);
+	}
+}
 #endif /* CONFIG_PCI_IOV */
 
 static void pnv_ioda_setup_pe_res(struct pnv_ioda_pe *pe,
@@ -2976,7 +3025,8 @@
 	int index;
 	int64_t rc;
 
-	if (!res || !res->flags || res->start > res->end)
+	if (!res || !res->flags || res->start > res->end ||
+	    res->flags & IORESOURCE_UNSET)
 		return;
 
 	if (res->flags & IORESOURCE_IO) {
@@ -3383,6 +3433,28 @@
 	return true;
 }
 
+static bool pnv_ocapi_enable_device_hook(struct pci_dev *dev)
+{
+	struct pci_controller *hose = pci_bus_to_host(dev->bus);
+	struct pnv_phb *phb = hose->private_data;
+	struct pci_dn *pdn;
+	struct pnv_ioda_pe *pe;
+
+	if (!phb->initialized)
+		return true;
+
+	pdn = pci_get_pdn(dev);
+	if (!pdn)
+		return false;
+
+	if (pdn->pe_number == IODA_INVALID_PE) {
+		pe = pnv_ioda_setup_dev_PE(dev);
+		if (!pe)
+			return false;
+	}
+	return true;
+}
+
 static long pnv_pci_ioda1_unset_window(struct iommu_table_group *table_group,
 				       int num)
 {
@@ -3512,7 +3584,10 @@
 	struct pnv_phb *phb = pe->phb;
 	struct pnv_ioda_pe *slave, *tmp;
 
+	mutex_lock(&phb->ioda.pe_list_mutex);
 	list_del(&pe->list);
+	mutex_unlock(&phb->ioda.pe_list_mutex);
+
 	switch (phb->type) {
 	case PNV_PHB_IODA1:
 		pnv_pci_ioda1_release_pe_dma(pe);
@@ -3520,6 +3595,8 @@
 	case PNV_PHB_IODA2:
 		pnv_pci_ioda2_release_pe_dma(pe);
 		break;
+	case PNV_PHB_NPU_OCAPI:
+		break;
 	default:
 		WARN_ON(1);
 	}
@@ -3620,7 +3697,8 @@
 };
 
 static const struct pci_controller_ops pnv_npu_ocapi_ioda_controller_ops = {
-	.enable_device_hook	= pnv_pci_enable_device_hook,
+	.enable_device_hook	= pnv_ocapi_enable_device_hook,
+	.release_device		= pnv_pci_release_device,
 	.window_alignment	= pnv_pci_window_alignment,
 	.reset_secondary_bus	= pnv_pci_reset_secondary_bus,
 	.shutdown		= pnv_pci_ioda_shutdown,
@@ -3862,7 +3940,7 @@
 	ppc_md.pcibios_default_alignment = pnv_pci_default_alignment;
 
 #ifdef CONFIG_PCI_IOV
-	ppc_md.pcibios_fixup_sriov = pnv_pci_ioda_fixup_iov_resources;
+	ppc_md.pcibios_fixup_sriov = pnv_pci_ioda_fixup_iov;
 	ppc_md.pcibios_iov_resource_alignment = pnv_pci_iov_resource_alignment;
 	ppc_md.pcibios_sriov_enable = pnv_pcibios_sriov_enable;
 	ppc_md.pcibios_sriov_disable = pnv_pcibios_sriov_disable;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/powernv/pci.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/powernv/pci.c
@@ -38,7 +38,7 @@
 
 int pnv_pci_get_slot_id(struct device_node *np, uint64_t *id)
 {
-	struct device_node *parent = np;
+	struct device_node *node = np;
 	u32 bdfn;
 	u64 phbid;
 	int ret;
@@ -48,25 +48,29 @@
 		return -ENXIO;
 
 	bdfn = ((bdfn & 0x00ffff00) >> 8);
-	while ((parent = of_get_parent(parent))) {
-		if (!PCI_DN(parent)) {
-			of_node_put(parent);
+	for (node = np; node; node = of_get_parent(node)) {
+		if (!PCI_DN(node)) {
+			of_node_put(node);
 			break;
 		}
 
-		if (!of_device_is_compatible(parent, "ibm,ioda2-phb") &&
-		    !of_device_is_compatible(parent, "ibm,ioda3-phb")) {
-			of_node_put(parent);
+		if (!of_device_is_compatible(node, "ibm,ioda2-phb") &&
+		    !of_device_is_compatible(node, "ibm,ioda3-phb") &&
+		    !of_device_is_compatible(node, "ibm,ioda2-npu2-opencapi-phb")) {
+			of_node_put(node);
 			continue;
 		}
 
-		ret = of_property_read_u64(parent, "ibm,opal-phbid", &phbid);
+		ret = of_property_read_u64(node, "ibm,opal-phbid", &phbid);
 		if (ret) {
-			of_node_put(parent);
+			of_node_put(node);
 			return -ENXIO;
 		}
 
-		*id = PCI_SLOT_ID(phbid, bdfn);
+		if (of_device_is_compatible(node, "ibm,ioda2-npu2-opencapi-phb"))
+			*id = PCI_PHB_SLOT_ID(phbid);
+		else
+			*id = PCI_SLOT_ID(phbid, bdfn);
 		return 0;
 	}
 
@@ -814,24 +818,6 @@
 {
 	struct pci_controller *hose = pci_bus_to_host(pdev->bus);
 	struct pnv_phb *phb = hose->private_data;
-#ifdef CONFIG_PCI_IOV
-	struct pnv_ioda_pe *pe;
-	struct pci_dn *pdn;
-
-	/* Fix the VF pdn PE number */
-	if (pdev->is_virtfn) {
-		pdn = pci_get_pdn(pdev);
-		WARN_ON(pdn->pe_number != IODA_INVALID_PE);
-		list_for_each_entry(pe, &phb->ioda.pe_list, list) {
-			if (pe->rid == ((pdev->bus->number << 8) |
-			    (pdev->devfn & 0xff))) {
-				pdn->pe_number = pe->pe_number;
-				pe->pdev = pdev;
-				break;
-			}
-		}
-	}
-#endif /* CONFIG_PCI_IOV */
 
 	if (phb && phb->dma_dev_setup)
 		phb->dma_dev_setup(phb, pdev);
@@ -945,6 +931,23 @@
 	if (!firmware_has_feature(FW_FEATURE_OPAL))
 		return;
 
+#ifdef CONFIG_PCIEPORTBUS
+	/*
+	 * On PowerNV PCIe devices are (currently) managed in cooperation
+	 * with firmware. This isn't *strictly* required, but there's enough
+	 * assumptions baked into both firmware and the platform code that
+	 * it's unwise to allow the portbus services to be used.
+	 *
+	 * We need to fix this eventually, but for now set this flag to disable
+	 * the portbus driver. The AER service isn't required since that AER
+	 * events are handled via EEH. The pciehp hotplug driver can't work
+	 * without kernel changes (and portbus binding breaks pnv_php). The
+	 * other services also require some thinking about how we're going
+	 * to integrate them.
+	 */
+	pcie_ports_disabled = true;
+#endif
+
 	/* Look for IODA IO-Hubs. */
 	for_each_compatible_node(np, NULL, "ibm,ioda-hub") {
 		pnv_pci_init_ioda_hub(np);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/powernv/powernv.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/powernv/powernv.h
@@ -35,4 +35,6 @@
 u32 memcons_get_size(struct memcons *mc);
 struct memcons *memcons_init(struct device_node *node, const char *mc_prop_name);
 
+void pnv_rng_init(void);
+
 #endif /* _POWERNV_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/powernv/rng.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/powernv/rng.c
@@ -17,6 +17,7 @@
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/smp.h>
+#include "powernv.h"
 
 #define DARN_ERR 0xFFFFFFFFFFFFFFFFul
 
@@ -28,7 +29,6 @@
 
 static DEFINE_PER_CPU(struct powernv_rng *, powernv_rng);
 
-
 int powernv_hwrng_present(void)
 {
 	struct powernv_rng *rng;
@@ -43,7 +43,11 @@
 	unsigned long parity;
 
 	/* Calculate the parity of the value */
-	asm ("popcntd %0,%1" : "=r" (parity) : "r" (val));
+	asm (".machine push;   \
+	      .machine power7; \
+	      popcntd %0,%1;   \
+	      .machine pop;"
+	     : "=r" (parity) : "r" (val));
 
 	/* xor our value with the previous mask */
 	val ^= rng->mask;
@@ -59,6 +63,8 @@
 	struct powernv_rng *rng;
 
 	rng = raw_cpu_read(powernv_rng);
+	if (!rng)
+		return 0;
 
 	*v = rng_whiten(rng, __raw_rm_readq(rng->regs_real));
 
@@ -94,9 +100,6 @@
 			return 0;
 		}
 	}
-
-	pr_warn("Unable to use DARN for get_random_seed()\n");
-
 	return -EIO;
 }
 
@@ -159,32 +162,59 @@
 
 	rng_init_per_cpu(rng, dn);
 
-	pr_info_once("Registering arch random hook.\n");
-
 	ppc_md.get_random_seed = powernv_get_random_long;
 
 	return 0;
 }
 
-static __init int rng_init(void)
+static int __init pnv_get_random_long_early(unsigned long *v)
 {
 	struct device_node *dn;
-	int rc;
 
-	for_each_compatible_node(dn, NULL, "ibm,power-rng") {
-		rc = rng_create(dn);
-		if (rc) {
-			pr_err("Failed creating rng for %pOF (%d).\n",
-				dn, rc);
-			continue;
-		}
+	if (!slab_is_available())
+		return 0;
 
-		/* Create devices for hwrng driver */
-		of_platform_device_create(dn, NULL, NULL);
-	}
+	if (cmpxchg(&ppc_md.get_random_seed, pnv_get_random_long_early,
+		    NULL) != pnv_get_random_long_early)
+		return 0;
 
-	initialise_darn();
+	for_each_compatible_node(dn, NULL, "ibm,power-rng")
+		rng_create(dn);
+
+	if (!ppc_md.get_random_seed)
+		return 0;
+	return ppc_md.get_random_seed(v);
+}
+
+void __init pnv_rng_init(void)
+{
+	struct device_node *dn;
+
+	/* Prefer darn over the rest. */
+	if (!initialise_darn())
+		return;
+
+	dn = of_find_compatible_node(NULL, NULL, "ibm,power-rng");
+	if (dn)
+		ppc_md.get_random_seed = pnv_get_random_long_early;
+
+	of_node_put(dn);
+}
+
+static int __init pnv_rng_late_init(void)
+{
+	struct device_node *dn;
+	unsigned long v;
+
+	/* In case it wasn't called during init for some other reason. */
+	if (ppc_md.get_random_seed == pnv_get_random_long_early)
+		pnv_get_random_long_early(&v);
+
+	if (ppc_md.get_random_seed == powernv_get_random_long) {
+		for_each_compatible_node(dn, NULL, "ibm,power-rng")
+			of_platform_device_create(dn, NULL, NULL);
+	}
 
 	return 0;
 }
-machine_subsys_initcall(powernv, rng_init);
+machine_subsys_initcall(powernv, pnv_rng_late_init);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/powernv/setup.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/powernv/setup.c
@@ -122,12 +122,29 @@
 			type = L1D_FLUSH_ORI;
 	}
 
+	/*
+	 * If we are non-Power9 bare metal, we don't need to flush on kernel
+	 * entry or after user access: they fix a P9 specific vulnerability.
+	 */
+	if (!pvr_version_is(PVR_POWER9)) {
+		security_ftr_clear(SEC_FTR_L1D_FLUSH_ENTRY);
+		security_ftr_clear(SEC_FTR_L1D_FLUSH_UACCESS);
+	}
+
 	enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) && \
 		 (security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR)   || \
 		  security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV));
 
 	setup_rfi_flush(type, enable);
 	setup_count_cache_flush();
+
+	enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) &&
+		 security_ftr_enabled(SEC_FTR_L1D_FLUSH_ENTRY);
+	setup_entry_flush(enable);
+
+	enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) &&
+		 security_ftr_enabled(SEC_FTR_L1D_FLUSH_UACCESS);
+	setup_uaccess_flush(enable);
 }
 
 static void __init pnv_setup_arch(void)
@@ -151,6 +168,8 @@
 	powersave_nap = 1;
 
 	/* XXX PMCS */
+
+	pnv_rng_init();
 }
 
 static void __init pnv_init(void)
@@ -169,11 +188,16 @@
 		add_preferred_console("hvc", 0, NULL);
 
 	if (!radix_enabled()) {
+		size_t size = sizeof(struct slb_entry) * mmu_slb_size;
 		int i;
 
 		/* Allocate per cpu area to save old slb contents during MCE */
-		for_each_possible_cpu(i)
-			paca_ptrs[i]->mce_faulty_slbs = memblock_alloc_node(mmu_slb_size, __alignof__(*paca_ptrs[i]->mce_faulty_slbs), cpu_to_node(i));
+		for_each_possible_cpu(i) {
+			paca_ptrs[i]->mce_faulty_slbs =
+					memblock_alloc_node(size,
+						__alignof__(struct slb_entry),
+						cpu_to_node(i));
+		}
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/powernv/smp.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/powernv/smp.c
@@ -43,7 +43,7 @@
 #include <asm/udbg.h>
 #define DBG(fmt...) udbg_printf(fmt)
 #else
-#define DBG(fmt...)
+#define DBG(fmt...) do { } while (0)
 #endif
 
 static void pnv_smp_setup_cpu(int cpu)
@@ -167,7 +167,6 @@
 	/* Standard hot unplug procedure */
 
 	idle_task_exit();
-	current->active_mm = NULL; /* for sanity */
 	cpu = smp_processor_id();
 	DBG("CPU%d offline\n", cpu);
 	generic_set_cpu_dead(cpu);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/powernv/ultravisor.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/powernv/ultravisor.c
@@ -55,6 +55,7 @@
 		return -ENODEV;
 
 	uv_memcons = memcons_init(node, "memcons");
+	of_node_put(node);
 	if (!uv_memcons)
 		return -ENOENT;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/ps3/mm.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/ps3/mm.c
@@ -6,6 +6,7 @@
  *  Copyright 2006 Sony Corp.
  */
 
+#include <linux/dma-mapping.h>
 #include <linux/kernel.h>
 #include <linux/export.h>
 #include <linux/memblock.h>
@@ -200,13 +201,14 @@
 {
 	int result;
 
-	DBG("%s:%d: map.vas_id    = %llu\n", __func__, __LINE__, map.vas_id);
-
 	if (map.vas_id) {
 		result = lv1_select_virtual_address_space(0);
-		BUG_ON(result);
-		result = lv1_destruct_virtual_address_space(map.vas_id);
-		BUG_ON(result);
+		result += lv1_destruct_virtual_address_space(map.vas_id);
+
+		if (result) {
+			lv1_panic(0);
+		}
+
 		map.vas_id = 0;
 	}
 }
@@ -304,19 +306,20 @@
 	int result;
 
 	if (!r->destroy) {
-		pr_info("%s:%d: Not destroying high region: %llxh %llxh\n",
-			__func__, __LINE__, r->base, r->size);
 		return;
 	}
 
-	DBG("%s:%d: r->base = %llxh\n", __func__, __LINE__, r->base);
-
 	if (r->base) {
 		result = lv1_release_memory(r->base);
-		BUG_ON(result);
+
+		if (result) {
+			lv1_panic(0);
+		}
+
 		r->size = r->base = r->offset = 0;
 		map.total = map.rm.size;
 	}
+
 	ps3_mm_set_repository_highmem(NULL);
 }
 
@@ -1116,6 +1119,7 @@
 	enum ps3_dma_region_type region_type, void *addr, unsigned long len)
 {
 	unsigned long lpar_addr;
+	int result;
 
 	lpar_addr = addr ? ps3_mm_phys_to_lpar(__pa(addr)) : 0;
 
@@ -1127,6 +1131,16 @@
 		r->offset -= map.r1.offset;
 	r->len = len ? len : _ALIGN_UP(map.total, 1 << r->page_size);
 
+	dev->core.dma_mask = &r->dma_mask;
+
+	result = dma_set_mask_and_coherent(&dev->core, DMA_BIT_MASK(32));
+
+	if (result < 0) {
+		dev_err(&dev->core, "%s:%d: dma_set_mask_and_coherent failed: %d\n",
+			__func__, __LINE__, result);
+		return result;
+	}
+
 	switch (dev->dev_type) {
 	case PS3_DEVICE_TYPE_SB:
 		r->region_ops =  (USE_DYNAMIC_DMA)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/pseries/cmm.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/pseries/cmm.c
@@ -411,6 +411,10 @@
 	.dev_name = "cmm",
 };
 
+static void cmm_release_device(struct device *dev)
+{
+}
+
 /**
  * cmm_sysfs_register - Register with sysfs
  *
@@ -426,6 +430,7 @@
 
 	dev->id = 0;
 	dev->bus = &cmm_subsys;
+	dev->release = cmm_release_device;
 
 	if ((rc = device_register(dev)))
 		goto subsys_unregister;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/pseries/dlpar.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/pseries/dlpar.c
@@ -127,7 +127,6 @@
 #define NEXT_PROPERTY   3
 #define PREV_PARENT     4
 #define MORE_MEMORY     5
-#define CALL_AGAIN	-2
 #define ERR_CFG_USE     -9003
 
 struct device_node *dlpar_configure_connector(__be32 drc_index,
@@ -168,6 +167,9 @@
 
 		spin_unlock(&rtas_data_buf_lock);
 
+		if (rtas_busy_delay(rc))
+			continue;
+
 		switch (rc) {
 		case COMPLETE:
 			break;
@@ -216,9 +218,6 @@
 			last_dn = last_dn->parent;
 			break;
 
-		case CALL_AGAIN:
-			break;
-
 		case MORE_MEMORY:
 		case ERR_CFG_USE:
 		default:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/pseries/eeh_pseries.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/pseries/eeh_pseries.c
@@ -472,8 +472,10 @@
 
 	switch(rets[0]) {
 	case 0:
-		result = EEH_STATE_MMIO_ACTIVE |
-			 EEH_STATE_DMA_ACTIVE;
+		result = EEH_STATE_MMIO_ACTIVE	|
+			 EEH_STATE_DMA_ACTIVE	|
+			 EEH_STATE_MMIO_ENABLED	|
+			 EEH_STATE_DMA_ENABLED;
 		break;
 	case 1:
 		result = EEH_STATE_RESET_ACTIVE |
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/pseries/hotplug-cpu.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/pseries/hotplug-cpu.c
@@ -91,9 +91,6 @@
 
 	BUG_ON(rtas_stop_self_token == RTAS_UNKNOWN_SERVICE);
 
-	printk("cpu %u (hwid %u) Ready to die...\n",
-	       smp_processor_id(), hard_smp_processor_id());
-
 	rtas_call_unlocked(&args, rtas_stop_self_token, 0, 1, NULL);
 
 	panic("Alas, I survived.\n");
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/pseries/hotplug-memory.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/pseries/hotplug-memory.c
@@ -27,7 +27,7 @@
 unsigned long pseries_memory_block_size(void)
 {
 	struct device_node *np;
-	unsigned int memblock_size = MIN_MEMORY_BLOCK_SIZE;
+	u64 memblock_size = MIN_MEMORY_BLOCK_SIZE;
 	struct resource r;
 
 	np = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
@@ -223,7 +223,7 @@
 			 struct drmem_lmb **end_lmb)
 {
 	struct drmem_lmb *lmb, *start, *end;
-	struct drmem_lmb *last_lmb;
+	struct drmem_lmb *limit;
 
 	start = NULL;
 	for_each_drmem_lmb(lmb) {
@@ -236,10 +236,10 @@
 	if (!start)
 		return -EINVAL;
 
-	end = &start[n_lmbs - 1];
+	end = &start[n_lmbs];
 
-	last_lmb = &drmem_info->lmbs[drmem_info->n_lmbs - 1];
-	if (end > last_lmb)
+	limit = &drmem_info->lmbs[drmem_info->n_lmbs];
+	if (end > limit)
 		return -EINVAL;
 
 	*start_lmb = start;
@@ -279,7 +279,7 @@
 	return dlpar_change_lmb_state(lmb, false);
 }
 
-static int pseries_remove_memblock(unsigned long base, unsigned int memblock_size)
+static int pseries_remove_memblock(unsigned long base, unsigned long memblock_size)
 {
 	unsigned long block_sz, start_pfn;
 	int sections_per_block;
@@ -310,10 +310,11 @@
 
 static int pseries_remove_mem_node(struct device_node *np)
 {
-	const __be32 *regs;
+	const __be32 *prop;
 	unsigned long base;
-	unsigned int lmb_size;
+	unsigned long lmb_size;
 	int ret = -EINVAL;
+	int addr_cells, size_cells;
 
 	/*
 	 * Check to see if we are actually removing memory
@@ -324,12 +325,19 @@
 	/*
 	 * Find the base address and size of the memblock
 	 */
-	regs = of_get_property(np, "reg", NULL);
-	if (!regs)
+	prop = of_get_property(np, "reg", NULL);
+	if (!prop)
 		return ret;
 
-	base = be64_to_cpu(*(unsigned long *)regs);
-	lmb_size = be32_to_cpu(regs[3]);
+	addr_cells = of_n_addr_cells(np);
+	size_cells = of_n_size_cells(np);
+
+	/*
+	 * "reg" property represents (addr,size) tuple.
+	 */
+	base = of_read_number(prop, addr_cells);
+	prop += addr_cells;
+	lmb_size = of_read_number(prop, size_cells);
 
 	pseries_remove_memblock(base, lmb_size);
 	return 0;
@@ -360,8 +368,10 @@
 
 	for (i = 0; i < scns_per_block; i++) {
 		pfn = PFN_DOWN(phys_addr);
-		if (!pfn_present(pfn))
+		if (!pfn_present(pfn)) {
+			phys_addr += MIN_MEMORY_BLOCK_SIZE;
 			continue;
+		}
 
 		rc &= is_mem_section_removable(pfn, PAGES_PER_SECTION);
 		phys_addr += MIN_MEMORY_BLOCK_SIZE;
@@ -374,25 +384,32 @@
 
 static int dlpar_remove_lmb(struct drmem_lmb *lmb)
 {
+	struct memory_block *mem_block;
 	unsigned long block_sz;
 	int rc;
 
 	if (!lmb_is_removable(lmb))
 		return -EINVAL;
 
+	mem_block = lmb_to_memblock(lmb);
+	if (mem_block == NULL)
+		return -EINVAL;
+
 	rc = dlpar_offline_lmb(lmb);
-	if (rc)
+	if (rc) {
+		put_device(&mem_block->dev);
 		return rc;
+	}
 
 	block_sz = pseries_memory_block_size();
 
-	__remove_memory(lmb->nid, lmb->base_addr, block_sz);
+	__remove_memory(mem_block->nid, lmb->base_addr, block_sz);
+	put_device(&mem_block->dev);
 
 	/* Update memory regions for memory remove */
 	memblock_remove(lmb->base_addr, block_sz);
 
 	invalidate_lmb_associativity_index(lmb);
-	lmb_clear_nid(lmb);
 	lmb->flags &= ~DRCONF_MEM_ASSIGNED;
 
 	return 0;
@@ -479,7 +496,7 @@
 	int lmb_found;
 	int rc;
 
-	pr_info("Attempting to hot-remove LMB, drc index %x\n", drc_index);
+	pr_debug("Attempting to hot-remove LMB, drc index %x\n", drc_index);
 
 	lmb_found = 0;
 	for_each_drmem_lmb(lmb) {
@@ -493,14 +510,15 @@
 		}
 	}
 
-	if (!lmb_found)
+	if (!lmb_found) {
+		pr_debug("Failed to look up LMB for drc index %x\n", drc_index);
 		rc = -EINVAL;
-
-	if (rc)
-		pr_info("Failed to hot-remove memory at %llx\n",
-			lmb->base_addr);
-	else
-		pr_info("Memory at %llx was hot-removed\n", lmb->base_addr);
+	} else if (rc) {
+		pr_debug("Failed to hot-remove memory at %llx\n",
+			 lmb->base_addr);
+	} else {
+		pr_debug("Memory at %llx was hot-removed\n", lmb->base_addr);
+	}
 
 	return rc;
 }
@@ -611,7 +629,7 @@
 
 #else
 static inline int pseries_remove_memblock(unsigned long base,
-					  unsigned int memblock_size)
+					  unsigned long memblock_size)
 {
 	return -EOPNOTSUPP;
 }
@@ -649,7 +667,7 @@
 static int dlpar_add_lmb(struct drmem_lmb *lmb)
 {
 	unsigned long block_sz;
-	int rc;
+	int nid, rc;
 
 	if (lmb->flags & DRCONF_MEM_ASSIGNED)
 		return -EINVAL;
@@ -660,11 +678,13 @@
 		return rc;
 	}
 
-	lmb_set_nid(lmb);
 	block_sz = memory_block_size_bytes();
 
+	/* Find the node id for this address. */
+	nid = memory_add_physaddr_to_nid(lmb->base_addr);
+
 	/* Add the memory */
-	rc = __add_memory(lmb->nid, lmb->base_addr, block_sz);
+	rc = __add_memory(nid, lmb->base_addr, block_sz);
 	if (rc) {
 		invalidate_lmb_associativity_index(lmb);
 		return rc;
@@ -672,9 +692,8 @@
 
 	rc = dlpar_online_lmb(lmb);
 	if (rc) {
-		__remove_memory(lmb->nid, lmb->base_addr, block_sz);
+		__remove_memory(nid, lmb->base_addr, block_sz);
 		invalidate_lmb_associativity_index(lmb);
-		lmb_clear_nid(lmb);
 	} else {
 		lmb->flags |= DRCONF_MEM_ASSIGNED;
 	}
@@ -752,8 +771,8 @@
 			if (!drmem_lmb_reserved(lmb))
 				continue;
 
-			pr_info("Memory at %llx (drc index %x) was hot-added\n",
-				lmb->base_addr, lmb->drc_index);
+			pr_debug("Memory at %llx (drc index %x) was hot-added\n",
+				 lmb->base_addr, lmb->drc_index);
 			drmem_remove_lmb_reservation(lmb);
 		}
 		rc = 0;
@@ -943,10 +962,11 @@
 
 static int pseries_add_mem_node(struct device_node *np)
 {
-	const __be32 *regs;
+	const __be32 *prop;
 	unsigned long base;
-	unsigned int lmb_size;
+	unsigned long lmb_size;
 	int ret = -EINVAL;
+	int addr_cells, size_cells;
 
 	/*
 	 * Check to see if we are actually adding memory
@@ -957,12 +977,18 @@
 	/*
 	 * Find the base and size of the memblock
 	 */
-	regs = of_get_property(np, "reg", NULL);
-	if (!regs)
+	prop = of_get_property(np, "reg", NULL);
+	if (!prop)
 		return ret;
 
-	base = be64_to_cpu(*(unsigned long *)regs);
-	lmb_size = be32_to_cpu(regs[3]);
+	addr_cells = of_n_addr_cells(np);
+	size_cells = of_n_size_cells(np);
+	/*
+	 * "reg" property represents (addr,size) tuple.
+	 */
+	base = of_read_number(prop, addr_cells);
+	prop += addr_cells;
+	lmb_size = of_read_number(prop, size_cells);
 
 	/*
 	 * Update memory region to represent the memory add
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/pseries/ibmebus.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/pseries/ibmebus.c
@@ -450,6 +450,7 @@
 	if (err) {
 		printk(KERN_WARNING "%s: device_register returned %i\n",
 		       __func__, err);
+		put_device(&ibmebus_bus_device);
 		bus_unregister(&ibmebus_bus_type);
 
 		return err;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/pseries/iommu.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/pseries/iommu.c
@@ -36,7 +36,6 @@
 #include <asm/udbg.h>
 #include <asm/mmzone.h>
 #include <asm/plpar_wrappers.h>
-#include <asm/svm.h>
 
 #include "pseries.h"
 
@@ -133,10 +132,10 @@
 	return be64_to_cpu(*tcep);
 }
 
-static void tce_free_pSeriesLP(struct iommu_table*, long, long);
+static void tce_free_pSeriesLP(unsigned long liobn, long, long);
 static void tce_freemulti_pSeriesLP(struct iommu_table*, long, long);
 
-static int tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum,
+static int tce_build_pSeriesLP(unsigned long liobn, long tcenum, long tceshift,
 				long npages, unsigned long uaddr,
 				enum dma_data_direction direction,
 				unsigned long attrs)
@@ -147,25 +146,25 @@
 	int ret = 0;
 	long tcenum_start = tcenum, npages_start = npages;
 
-	rpn = __pa(uaddr) >> TCE_SHIFT;
+	rpn = __pa(uaddr) >> tceshift;
 	proto_tce = TCE_PCI_READ;
 	if (direction != DMA_TO_DEVICE)
 		proto_tce |= TCE_PCI_WRITE;
 
 	while (npages--) {
-		tce = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
-		rc = plpar_tce_put((u64)tbl->it_index, (u64)tcenum << 12, tce);
+		tce = proto_tce | (rpn & TCE_RPN_MASK) << tceshift;
+		rc = plpar_tce_put((u64)liobn, (u64)tcenum << tceshift, tce);
 
 		if (unlikely(rc == H_NOT_ENOUGH_RESOURCES)) {
 			ret = (int)rc;
-			tce_free_pSeriesLP(tbl, tcenum_start,
+			tce_free_pSeriesLP(liobn, tcenum_start,
 			                   (npages_start - (npages + 1)));
 			break;
 		}
 
 		if (rc && printk_ratelimit()) {
 			printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%lld\n", rc);
-			printk("\tindex   = 0x%llx\n", (u64)tbl->it_index);
+			printk("\tindex   = 0x%llx\n", (u64)liobn);
 			printk("\ttcenum  = 0x%llx\n", (u64)tcenum);
 			printk("\ttce val = 0x%llx\n", tce );
 			dump_stack();
@@ -194,7 +193,8 @@
 	unsigned long flags;
 
 	if ((npages == 1) || !firmware_has_feature(FW_FEATURE_MULTITCE)) {
-		return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr,
+		return tce_build_pSeriesLP(tbl->it_index, tcenum,
+					   tbl->it_page_shift, npages, uaddr,
 		                           direction, attrs);
 	}
 
@@ -210,8 +210,9 @@
 		/* If allocation fails, fall back to the loop implementation */
 		if (!tcep) {
 			local_irq_restore(flags);
-			return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr,
-					    direction, attrs);
+			return tce_build_pSeriesLP(tbl->it_index, tcenum,
+					tbl->it_page_shift,
+					npages, uaddr, direction, attrs);
 		}
 		__this_cpu_write(tce_page, tcep);
 	}
@@ -262,16 +263,16 @@
 	return ret;
 }
 
-static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages)
+static void tce_free_pSeriesLP(unsigned long liobn, long tcenum, long npages)
 {
 	u64 rc;
 
 	while (npages--) {
-		rc = plpar_tce_put((u64)tbl->it_index, (u64)tcenum << 12, 0);
+		rc = plpar_tce_put((u64)liobn, (u64)tcenum << 12, 0);
 
 		if (rc && printk_ratelimit()) {
 			printk("tce_free_pSeriesLP: plpar_tce_put failed. rc=%lld\n", rc);
-			printk("\tindex   = 0x%llx\n", (u64)tbl->it_index);
+			printk("\tindex   = 0x%llx\n", (u64)liobn);
 			printk("\ttcenum  = 0x%llx\n", (u64)tcenum);
 			dump_stack();
 		}
@@ -286,7 +287,7 @@
 	u64 rc;
 
 	if (!firmware_has_feature(FW_FEATURE_MULTITCE))
-		return tce_free_pSeriesLP(tbl, tcenum, npages);
+		return tce_free_pSeriesLP(tbl->it_index, tcenum, npages);
 
 	rc = plpar_tce_stuff((u64)tbl->it_index, (u64)tcenum << 12, 0, npages);
 
@@ -401,6 +402,19 @@
 	u64 rc = 0;
 	long l, limit;
 
+	if (!firmware_has_feature(FW_FEATURE_MULTITCE)) {
+		unsigned long tceshift = be32_to_cpu(maprange->tce_shift);
+		unsigned long dmastart = (start_pfn << PAGE_SHIFT) +
+				be64_to_cpu(maprange->dma_base);
+		unsigned long tcenum = dmastart >> tceshift;
+		unsigned long npages = num_pfn << PAGE_SHIFT >> tceshift;
+		void *uaddr = __va(start_pfn << PAGE_SHIFT);
+
+		return tce_build_pSeriesLP(be32_to_cpu(maprange->liobn),
+				tcenum, tceshift, npages, (unsigned long) uaddr,
+				DMA_BIDIRECTIONAL, 0);
+	}
+
 	local_irq_disable();	/* to protect tcep and the page behind it */
 	tcep = __this_cpu_read(tce_page);
 
@@ -1320,15 +1334,7 @@
 	of_reconfig_notifier_register(&iommu_reconfig_nb);
 	register_memory_notifier(&iommu_mem_nb);
 
-	/*
-	 * Secure guest memory is inacessible to devices so regular DMA isn't
-	 * possible.
-	 *
-	 * In that case keep devices' dma_map_ops as NULL so that the generic
-	 * DMA code path will use SWIOTLB to bounce buffers for DMA.
-	 */
-	if (!is_secure_guest())
-		set_pci_dma_ops(&dma_iommu_ops);
+	set_pci_dma_ops(&dma_iommu_ops);
 }
 
 static int __init disable_multitce(char *str)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/pseries/lpar.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/pseries/lpar.c
@@ -522,8 +522,10 @@
 
 	if (cmd) {
 		rc = init_cpu_associativity();
-		if (rc)
+		if (rc) {
+			destroy_cpu_associativity();
 			goto out;
+		}
 
 		for_each_possible_cpu(cpu) {
 			disp = per_cpu_ptr(&vcpu_disp_data, cpu);
@@ -1416,22 +1418,22 @@
 
 void __init pseries_lpar_read_hblkrm_characteristics(void)
 {
+	const s32 token = rtas_token("ibm,get-system-parameter");
 	unsigned char local_buffer[SPLPAR_TLB_BIC_MAXLENGTH];
 	int call_status, len, idx, bpsize;
 
 	if (!firmware_has_feature(FW_FEATURE_BLOCK_REMOVE))
 		return;
 
-	spin_lock(&rtas_data_buf_lock);
-	memset(rtas_data_buf, 0, RTAS_DATA_BUF_SIZE);
-	call_status = rtas_call(rtas_token("ibm,get-system-parameter"), 3, 1,
-				NULL,
-				SPLPAR_TLB_BIC_TOKEN,
-				__pa(rtas_data_buf),
-				RTAS_DATA_BUF_SIZE);
-	memcpy(local_buffer, rtas_data_buf, SPLPAR_TLB_BIC_MAXLENGTH);
-	local_buffer[SPLPAR_TLB_BIC_MAXLENGTH - 1] = '\0';
-	spin_unlock(&rtas_data_buf_lock);
+	do {
+		spin_lock(&rtas_data_buf_lock);
+		memset(rtas_data_buf, 0, RTAS_DATA_BUF_SIZE);
+		call_status = rtas_call(token, 3, 1, NULL, SPLPAR_TLB_BIC_TOKEN,
+					__pa(rtas_data_buf), RTAS_DATA_BUF_SIZE);
+		memcpy(local_buffer, rtas_data_buf, SPLPAR_TLB_BIC_MAXLENGTH);
+		local_buffer[SPLPAR_TLB_BIC_MAXLENGTH - 1] = '\0';
+		spin_unlock(&rtas_data_buf_lock);
+	} while (rtas_busy_delay(call_status));
 
 	if (call_status != 0) {
 		pr_warn("%s %s Error calling get-system-parameter (0x%x)\n",
@@ -1869,10 +1871,10 @@
  * h_get_mpp
  * H_GET_MPP hcall returns info in 7 parms
  */
-int h_get_mpp(struct hvcall_mpp_data *mpp_data)
+long h_get_mpp(struct hvcall_mpp_data *mpp_data)
 {
-	int rc;
-	unsigned long retbuf[PLPAR_HCALL9_BUFSIZE];
+	unsigned long retbuf[PLPAR_HCALL9_BUFSIZE] = {0};
+	long rc;
 
 	rc = plpar_hcall9(H_GET_MPP, retbuf);
 
@@ -1992,7 +1994,7 @@
 {
 	char name[16];
 	long i;
-	static struct dentry *vpa_dir;
+	struct dentry *vpa_dir;
 
 	if (!firmware_has_feature(FW_FEATURE_SPLPAR))
 		return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/pseries/lparcfg.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/pseries/lparcfg.c
@@ -112,8 +112,8 @@
  */
 static unsigned int h_get_ppp(struct hvcall_ppp_data *ppp_data)
 {
-	unsigned long rc;
-	unsigned long retbuf[PLPAR_HCALL9_BUFSIZE];
+	unsigned long retbuf[PLPAR_HCALL9_BUFSIZE] = {0};
+	long rc;
 
 	rc = plpar_hcall9(H_GET_PPP, retbuf);
 
@@ -159,7 +159,7 @@
 	struct hvcall_ppp_data ppp_data;
 	struct device_node *root;
 	const __be32 *perf_level;
-	int rc;
+	long rc;
 
 	rc = h_get_ppp(&ppp_data);
 	if (rc)
@@ -289,6 +289,7 @@
  */
 static void parse_system_parameter_string(struct seq_file *m)
 {
+	const s32 token = rtas_token("ibm,get-system-parameter");
 	int call_status;
 
 	unsigned char *local_buffer = kmalloc(SPLPAR_MAXLENGTH, GFP_KERNEL);
@@ -298,16 +299,15 @@
 		return;
 	}
 
-	spin_lock(&rtas_data_buf_lock);
-	memset(rtas_data_buf, 0, SPLPAR_MAXLENGTH);
-	call_status = rtas_call(rtas_token("ibm,get-system-parameter"), 3, 1,
-				NULL,
-				SPLPAR_CHARACTERISTICS_TOKEN,
-				__pa(rtas_data_buf),
-				RTAS_DATA_BUF_SIZE);
-	memcpy(local_buffer, rtas_data_buf, SPLPAR_MAXLENGTH);
-	local_buffer[SPLPAR_MAXLENGTH - 1] = '\0';
-	spin_unlock(&rtas_data_buf_lock);
+	do {
+		spin_lock(&rtas_data_buf_lock);
+		memset(rtas_data_buf, 0, SPLPAR_MAXLENGTH);
+		call_status = rtas_call(token, 3, 1, NULL, SPLPAR_CHARACTERISTICS_TOKEN,
+					__pa(rtas_data_buf), RTAS_DATA_BUF_SIZE);
+		memcpy(local_buffer, rtas_data_buf, SPLPAR_MAXLENGTH);
+		local_buffer[SPLPAR_MAXLENGTH - 1] = '\0';
+		spin_unlock(&rtas_data_buf_lock);
+	} while (rtas_busy_delay(call_status));
 
 	if (call_status != 0) {
 		printk(KERN_INFO
@@ -435,10 +435,10 @@
 {
 	unsigned long maxmem = 0;
 
-	maxmem += drmem_info->n_lmbs * drmem_info->lmb_size;
+	maxmem += (unsigned long)drmem_info->n_lmbs * drmem_info->lmb_size;
 	maxmem += hugetlb_total_pages() * PAGE_SIZE;
 
-	seq_printf(m, "MaxMem=%ld\n", maxmem);
+	seq_printf(m, "MaxMem=%lu\n", maxmem);
 }
 
 static int pseries_lparcfg_data(struct seq_file *m, void *v)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/pseries/msi.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/pseries/msi.c
@@ -4,6 +4,7 @@
  * Copyright 2006-2007 Michael Ellerman, IBM Corp.
  */
 
+#include <linux/crash_dump.h>
 #include <linux/device.h>
 #include <linux/irq.h>
 #include <linux/msi.h>
@@ -458,7 +459,28 @@
 			return hwirq;
 		}
 
-		virq = irq_create_mapping(NULL, hwirq);
+		/*
+		 * Depending on the number of online CPUs in the original
+		 * kernel, it is likely for CPU #0 to be offline in a kdump
+		 * kernel. The associated IRQs in the affinity mappings
+		 * provided by irq_create_affinity_masks() are thus not
+		 * started by irq_startup(), as per-design for managed IRQs.
+		 * This can be a problem with multi-queue block devices driven
+		 * by blk-mq : such a non-started IRQ is very likely paired
+		 * with the single queue enforced by blk-mq during kdump (see
+		 * blk_mq_alloc_tag_set()). This causes the device to remain
+		 * silent and likely hangs the guest at some point.
+		 *
+		 * We don't really care for fine-grained affinity when doing
+		 * kdump actually : simply ignore the pre-computed affinity
+		 * masks in this case and let the default mask with all CPUs
+		 * be used when creating the IRQ mappings.
+		 */
+		if (is_kdump_kernel())
+			virq = irq_create_mapping(NULL, hwirq);
+		else
+			virq = irq_create_mapping_affinity(NULL, hwirq,
+							   entry->affinity);
 
 		if (!virq) {
 			pr_debug("rtas_msi: Failed mapping hwirq %d\n", hwirq);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/pseries/of_helpers.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/pseries/of_helpers.c
@@ -45,14 +45,14 @@
 int of_read_drc_info_cell(struct property **prop, const __be32 **curval,
 			struct of_drc_info *data)
 {
-	const char *p;
+	const char *p = (char *)(*curval);
 	const __be32 *p2;
 
 	if (!data)
 		return -EINVAL;
 
 	/* Get drc-type:encode-string */
-	p = data->drc_type = (char*) (*curval);
+	data->drc_type = (char *)p;
 	p = of_prop_next_string(*prop, p);
 	if (!p)
 		return -EINVAL;
@@ -65,9 +65,7 @@
 
 	/* Get drc-index-start:encode-int */
 	p2 = (const __be32 *)p;
-	p2 = of_prop_next_u32(*prop, p2, &data->drc_index_start);
-	if (!p2)
-		return -EINVAL;
+	data->drc_index_start = be32_to_cpu(*p2);
 
 	/* Get drc-name-suffix-start:encode-int */
 	p2 = of_prop_next_u32(*prop, p2, &data->drc_name_suffix_start);
@@ -90,7 +88,7 @@
 		return -EINVAL;
 
 	/* Should now know end of current entry */
-	(*curval) = (void *)p2;
+	(*curval) = (void *)(++p2);
 	data->last_drc_index = data->drc_index_start +
 		((data->num_sequential_elems - 1) * data->sequential_inc);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/pseries/papr_scm.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/pseries/papr_scm.c
@@ -152,7 +152,7 @@
 	int len, read;
 	int64_t ret;
 
-	if ((hdr->in_offset + hdr->in_length) >= p->metadata_size)
+	if ((hdr->in_offset + hdr->in_length) > p->metadata_size)
 		return -EINVAL;
 
 	for (len = hdr->in_length; len; len -= read) {
@@ -206,7 +206,7 @@
 	__be64 data_be;
 	int64_t ret;
 
-	if ((hdr->in_offset + hdr->in_length) >= p->metadata_size)
+	if ((hdr->in_offset + hdr->in_length) > p->metadata_size)
 		return -EINVAL;
 
 	for (len = hdr->in_length; len; len -= wrote) {
@@ -342,6 +342,7 @@
 	p->bus = nvdimm_bus_register(NULL, &p->bus_desc);
 	if (!p->bus) {
 		dev_err(dev, "Error creating nvdimm bus %pOF\n", p->dn);
+		kfree(p->bus_desc.provider_name);
 		return -ENXIO;
 	}
 
@@ -498,6 +499,7 @@
 
 	nvdimm_bus_unregister(p->bus);
 	drc_pmem_unbind(p);
+	kfree(p->bus_desc.provider_name);
 	kfree(p);
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/pseries/pci_dlpar.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/pseries/pci_dlpar.c
@@ -66,6 +66,7 @@
 int remove_phb_dynamic(struct pci_controller *phb)
 {
 	struct pci_bus *b = phb->bus;
+	struct pci_host_bridge *host_bridge = to_pci_host_bridge(b->bridge);
 	struct resource *res;
 	int rc, i;
 
@@ -92,7 +93,8 @@
 	/* Remove the PCI bus and unregister the bridge device from sysfs */
 	phb->bus = NULL;
 	pci_remove_bus(b);
-	device_unregister(b->bridge);
+	host_bridge->bus = NULL;
+	device_unregister(&host_bridge->dev);
 
 	/* Now release the IO resource */
 	if (res->flags & IORESOURCE_IO)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/pseries/pseries.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/pseries/pseries.h
@@ -114,4 +114,6 @@
 void pseries_setup_rfi_flush(void);
 void pseries_lpar_read_hblkrm_characteristics(void);
 
+void pseries_rng_init(void);
+
 #endif /* _PSERIES_PSERIES_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/pseries/ras.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/pseries/ras.c
@@ -184,7 +184,6 @@
 	case EPOW_SHUTDOWN_ON_UPS:
 		pr_emerg("Loss of system power detected. System is running on"
 			 " UPS/battery. Check RTAS error log for details\n");
-		orderly_poweroff(true);
 		break;
 
 	case EPOW_SHUTDOWN_LOSS_OF_CRITICAL_FUNCTIONS:
@@ -395,10 +394,11 @@
 /*
  * Some versions of FWNMI place the buffer inside the 4kB page starting at
  * 0x7000. Other versions place it inside the rtas buffer. We check both.
+ * Minimum size of the buffer is 16 bytes.
  */
 #define VALID_FWNMI_BUFFER(A) \
-	((((A) >= 0x7000) && ((A) < 0x7ff0)) || \
-	(((A) >= rtas.base) && ((A) < (rtas.base + rtas.size - 16))))
+	((((A) >= 0x7000) && ((A) <= 0x8000 - 16)) || \
+	(((A) >= rtas.base) && ((A) <= (rtas.base + rtas.size - 16))))
 
 static inline struct rtas_error_log *fwnmi_get_errlog(void)
 {
@@ -494,18 +494,55 @@
 	return 0; /* need to perform reset */
 }
 
+static int mce_handle_err_realmode(int disposition, u8 error_type)
+{
+#ifdef CONFIG_PPC_BOOK3S_64
+	if (disposition == RTAS_DISP_NOT_RECOVERED) {
+		switch (error_type) {
+		case	MC_ERROR_TYPE_SLB:
+		case	MC_ERROR_TYPE_ERAT:
+			/*
+			 * Store the old slb content in paca before flushing.
+			 * Print this when we go to virtual mode.
+			 * There are chances that we may hit MCE again if there
+			 * is a parity error on the SLB entry we trying to read
+			 * for saving. Hence limit the slb saving to single
+			 * level of recursion.
+			 */
+			if (local_paca->in_mce == 1)
+				slb_save_contents(local_paca->mce_faulty_slbs);
+			flush_and_reload_slb();
+			disposition = RTAS_DISP_FULLY_RECOVERED;
+			break;
+		default:
+			break;
+		}
+	} else if (disposition == RTAS_DISP_LIMITED_RECOVERY) {
+		/* Platform corrected itself but could be degraded */
+		pr_err("MCE: limited recovery, system may be degraded\n");
+		disposition = RTAS_DISP_FULLY_RECOVERED;
+	}
+#endif
+	return disposition;
+}
 
-static int mce_handle_error(struct pt_regs *regs, struct rtas_error_log *errp)
+static int mce_handle_err_virtmode(struct pt_regs *regs,
+				   struct rtas_error_log *errp,
+				   struct pseries_mc_errorlog *mce_log,
+				   int disposition)
 {
 	struct mce_error_info mce_err = { 0 };
-	unsigned long eaddr = 0, paddr = 0;
-	struct pseries_errorlog *pseries_log;
-	struct pseries_mc_errorlog *mce_log;
-	int disposition = rtas_error_disposition(errp);
 	int initiator = rtas_error_initiator(errp);
 	int severity = rtas_error_severity(errp);
+	unsigned long eaddr = 0, paddr = 0;
 	u8 error_type, err_sub_type;
 
+	if (!mce_log)
+		goto out;
+
+	error_type = mce_log->error_type;
+	err_sub_type = rtas_mc_error_sub_type(mce_log);
+
 	if (initiator == RTAS_INITIATOR_UNKNOWN)
 		mce_err.initiator = MCE_INITIATOR_UNKNOWN;
 	else if (initiator == RTAS_INITIATOR_CPU)
@@ -544,18 +581,7 @@
 	mce_err.error_type = MCE_ERROR_TYPE_UNKNOWN;
 	mce_err.error_class = MCE_ECLASS_UNKNOWN;
 
-	if (!rtas_error_extended(errp))
-		goto out;
-
-	pseries_log = get_pseries_errorlog(errp, PSERIES_ELOG_SECT_ID_MCE);
-	if (pseries_log == NULL)
-		goto out;
-
-	mce_log = (struct pseries_mc_errorlog *)pseries_log->data;
-	error_type = mce_log->error_type;
-	err_sub_type = rtas_mc_error_sub_type(mce_log);
-
-	switch (mce_log->error_type) {
+	switch (error_type) {
 	case MC_ERROR_TYPE_UE:
 		mce_err.error_type = MCE_ERROR_TYPE_UE;
 		switch (err_sub_type) {
@@ -652,40 +678,45 @@
 		mce_err.error_type = MCE_ERROR_TYPE_UNKNOWN;
 		break;
 	}
-
-#ifdef CONFIG_PPC_BOOK3S_64
-	if (disposition == RTAS_DISP_NOT_RECOVERED) {
-		switch (error_type) {
-		case	MC_ERROR_TYPE_SLB:
-		case	MC_ERROR_TYPE_ERAT:
-			/*
-			 * Store the old slb content in paca before flushing.
-			 * Print this when we go to virtual mode.
-			 * There are chances that we may hit MCE again if there
-			 * is a parity error on the SLB entry we trying to read
-			 * for saving. Hence limit the slb saving to single
-			 * level of recursion.
-			 */
-			if (local_paca->in_mce == 1)
-				slb_save_contents(local_paca->mce_faulty_slbs);
-			flush_and_reload_slb();
-			disposition = RTAS_DISP_FULLY_RECOVERED;
-			break;
-		default:
-			break;
-		}
-	} else if (disposition == RTAS_DISP_LIMITED_RECOVERY) {
-		/* Platform corrected itself but could be degraded */
-		printk(KERN_ERR "MCE: limited recovery, system may "
-		       "be degraded\n");
-		disposition = RTAS_DISP_FULLY_RECOVERED;
-	}
-#endif
-
 out:
 	save_mce_event(regs, disposition == RTAS_DISP_FULLY_RECOVERED,
-			&mce_err, regs->nip, eaddr, paddr);
+		       &mce_err, regs->nip, eaddr, paddr);
+	return disposition;
+}
+
+static int mce_handle_error(struct pt_regs *regs, struct rtas_error_log *errp)
+{
+	struct pseries_errorlog *pseries_log;
+	struct pseries_mc_errorlog *mce_log = NULL;
+	int disposition = rtas_error_disposition(errp);
+	u8 error_type;
+
+	if (!rtas_error_extended(errp))
+		goto out;
+
+	pseries_log = get_pseries_errorlog(errp, PSERIES_ELOG_SECT_ID_MCE);
+	if (!pseries_log)
+		goto out;
+
+	mce_log = (struct pseries_mc_errorlog *)pseries_log->data;
+	error_type = mce_log->error_type;
+
+	disposition = mce_handle_err_realmode(disposition, error_type);
 
+	/*
+	 * Enable translation as we will be accessing per-cpu variables
+	 * in save_mce_event() which may fall outside RMO region, also
+	 * leave it enabled because subsequently we will be queuing work
+	 * to workqueues where again per-cpu variables accessed, besides
+	 * fwnmi_release_errinfo() crashes when called in realmode on
+	 * pseries.
+	 * Note: All the realmode handling like flushing SLB entries for
+	 *       SLB multihit is done by now.
+	 */
+out:
+	mtmsr(mfmsr() | MSR_IR | MSR_DR);
+	disposition = mce_handle_err_virtmode(regs, errp, mce_log,
+					      disposition);
 	return disposition;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/pseries/rng.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/pseries/rng.c
@@ -10,6 +10,7 @@
 #include <asm/archrandom.h>
 #include <asm/machdep.h>
 #include <asm/plpar_wrappers.h>
+#include "pseries.h"
 
 
 static int pseries_get_random_long(unsigned long *v)
@@ -24,18 +25,13 @@
 	return 0;
 }
 
-static __init int rng_init(void)
+void __init pseries_rng_init(void)
 {
 	struct device_node *dn;
 
 	dn = of_find_compatible_node(NULL, NULL, "ibm,random");
 	if (!dn)
-		return -ENODEV;
-
-	pr_info("Registering arch random hook.\n");
-
+		return;
 	ppc_md.get_random_seed = pseries_get_random_long;
-
-	return 0;
+	of_node_put(dn);
 }
-machine_subsys_initcall(pseries, rng_init);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/pseries/setup.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/pseries/setup.c
@@ -74,6 +74,9 @@
 #include "pseries.h"
 #include "../../../../drivers/pci/pci.h"
 
+DEFINE_STATIC_KEY_FALSE(shared_processor);
+EXPORT_SYMBOL(shared_processor);
+
 int CMO_PrPSP = -1;
 int CMO_SecPSP = -1;
 unsigned long CMO_PageSize = (ASM_CONST(1) << IOMMU_PAGE_SHIFT_4K);
@@ -302,8 +305,8 @@
 {
 	void (*ctor)(void *) = get_dtl_cache_ctor();
 
-	dtl_cache = kmem_cache_create("dtl", DISPATCH_LOG_BYTES,
-						DISPATCH_LOG_BYTES, 0, ctor);
+	dtl_cache = kmem_cache_create_usercopy("dtl", DISPATCH_LOG_BYTES,
+						DISPATCH_LOG_BYTES, 0, 0, DISPATCH_LOG_BYTES, ctor);
 	if (!dtl_cache) {
 		pr_warn("Failed to create dispatch trace log buffer cache\n");
 		pr_warn("Stolen time statistics will be unreliable\n");
@@ -558,6 +561,14 @@
 
 	setup_rfi_flush(types, enable);
 	setup_count_cache_flush();
+
+	enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) &&
+		 security_ftr_enabled(SEC_FTR_L1D_FLUSH_ENTRY);
+	setup_entry_flush(enable);
+
+	enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) &&
+		 security_ftr_enabled(SEC_FTR_L1D_FLUSH_UACCESS);
+	setup_uaccess_flush(enable);
 }
 
 #ifdef CONFIG_PCI_IOV
@@ -758,6 +769,10 @@
 
 	if (firmware_has_feature(FW_FEATURE_LPAR)) {
 		vpa_init(boot_cpuid);
+
+		if (lppaca_shared_proc(get_lppaca()))
+			static_branch_enable(&shared_processor);
+
 		ppc_md.power_save = pseries_lpar_idle;
 		ppc_md.enable_pmcs = pseries_lpar_enable_pmcs;
 #ifdef CONFIG_PCI_IOV
@@ -777,6 +792,8 @@
 
 	if (swiotlb_force == SWIOTLB_FORCE)
 		ppc_swiotlb_enable = 1;
+
+	pseries_rng_init();
 }
 
 static void pseries_panic(char *str)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/pseries/suspend.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/pseries/suspend.c
@@ -13,7 +13,6 @@
 #include <asm/mmu.h>
 #include <asm/rtas.h>
 #include <asm/topology.h>
-#include "../../kernel/cacheinfo.h"
 
 static u64 stream_id;
 static struct device suspend_dev;
@@ -78,9 +77,7 @@
 	 * Update configuration which can be modified based on device tree
 	 * changes during resume.
 	 */
-	cacheinfo_cpu_offline(smp_processor_id());
 	post_mobility_fixup();
-	cacheinfo_cpu_online(smp_processor_id());
 }
 
 /**
@@ -132,15 +129,11 @@
 			       struct device_attribute *attr,
 			       const char *buf, size_t count)
 {
-	cpumask_var_t offline_mask;
 	int rc;
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 
-	if (!alloc_cpumask_var(&offline_mask, GFP_KERNEL))
-		return -ENOMEM;
-
 	stream_id = simple_strtoul(buf, NULL, 16);
 
 	do {
@@ -150,32 +143,16 @@
 	} while (rc == -EAGAIN);
 
 	if (!rc) {
-		/* All present CPUs must be online */
-		cpumask_andnot(offline_mask, cpu_present_mask,
-				cpu_online_mask);
-		rc = rtas_online_cpus_mask(offline_mask);
-		if (rc) {
-			pr_err("%s: Could not bring present CPUs online.\n",
-					__func__);
-			goto out;
-		}
-
 		stop_topology_update();
 		rc = pm_suspend(PM_SUSPEND_MEM);
 		start_topology_update();
-
-		/* Take down CPUs not online prior to suspend */
-		if (!rtas_offline_cpus_mask(offline_mask))
-			pr_warn("%s: Could not restore CPUs to offline "
-					"state.\n", __func__);
 	}
 
 	stream_id = 0;
 
 	if (!rc)
 		rc = count;
-out:
-	free_cpumask_var(offline_mask);
+
 	return rc;
 }
 
@@ -210,7 +187,6 @@
 
 static const struct platform_suspend_ops pseries_suspend_ops = {
 	.valid		= suspend_valid_only_mem,
-	.begin		= pseries_suspend_begin,
 	.prepare_late	= pseries_prepare_late,
 	.enter		= pseries_suspend_enter,
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/platforms/pseries/vio.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/platforms/pseries/vio.c
@@ -36,7 +36,6 @@
 	.name = "vio",
 	.type = "",
 	.dev.init_name = "vio",
-	.dev.bus = &vio_bus_type,
 };
 
 #ifdef CONFIG_PPC_SMLPAR
@@ -1176,6 +1175,8 @@
 	if (tbl == NULL)
 		return NULL;
 
+	kref_init(&tbl->it_kref);
+
 	of_parse_dma_window(dev->dev.of_node, dma_window,
 			    &tbl->it_index, &offset, &size);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/purgatory/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/purgatory/Makefile
@@ -4,6 +4,11 @@
 
 targets += trampoline.o purgatory.ro kexec-purgatory.c
 
+# When profile-guided optimization is enabled, llvm emits two different
+# overlapping text sections, which is not supported by kexec. Remove profile
+# optimization flags.
+KBUILD_CFLAGS := $(filter-out -fprofile-sample-use=% -fprofile-use=%,$(KBUILD_CFLAGS))
+
 LDFLAGS_purgatory.ro := -e purgatory_start -r --no-undefined
 
 $(obj)/purgatory.ro: $(obj)/trampoline.o FORCE
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/sysdev/dart_iommu.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/sysdev/dart_iommu.c
@@ -403,9 +403,10 @@
 	}
 
 	/* Initialize the DART HW */
-	if (dart_init(dn) != 0)
+	if (dart_init(dn) != 0) {
+		of_node_put(dn);
 		return;
-
+	}
 	/*
 	 * U4 supports a DART bypass, we use it for 64-bit capable devices to
 	 * improve performance.  However, that only works for devices connected
@@ -418,6 +419,7 @@
 
 	/* Setup pci_dma ops */
 	set_pci_dma_ops(&dma_iommu_ops);
+	of_node_put(dn);
 }
 
 #ifdef CONFIG_PM
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/sysdev/dcr-low.S
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/sysdev/dcr-low.S
@@ -11,7 +11,7 @@
 #include <asm/export.h>
 
 #define DCR_ACCESS_PROLOG(table) \
-	cmpli	cr0,r3,1024;	 \
+	cmplwi	cr0,r3,1024;	 \
 	rlwinm  r3,r3,4,18,27;   \
 	lis     r5,table@h;      \
 	ori     r5,r5,table@l;   \
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/sysdev/fsl_gtm.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/sysdev/fsl_gtm.c
@@ -86,7 +86,7 @@
  */
 struct gtm_timer *gtm_get_timer16(void)
 {
-	struct gtm *gtm = NULL;
+	struct gtm *gtm;
 	int i;
 
 	list_for_each_entry(gtm, &gtms, list_node) {
@@ -103,7 +103,7 @@
 		spin_unlock_irq(&gtm->lock);
 	}
 
-	if (gtm)
+	if (!list_empty(&gtms))
 		return ERR_PTR(-EBUSY);
 	return ERR_PTR(-ENODEV);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/sysdev/fsl_msi.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/sysdev/fsl_msi.c
@@ -211,8 +211,10 @@
 			dev_err(&pdev->dev,
 				"node %pOF has an invalid fsl,msi phandle %u\n",
 				hose->dn, np->phandle);
+			of_node_put(np);
 			return -EINVAL;
 		}
+		of_node_put(np);
 	}
 
 	for_each_pci_msi_entry(entry, pdev) {
@@ -571,10 +573,12 @@
 	.msiir_offset = 0x38,
 };
 
+#ifdef CONFIG_EPAPR_PARAVIRT
 static const struct fsl_msi_feature vmpic_msi_feature = {
 	.fsl_pic_ip = FSL_PIC_IP_VMPIC,
 	.msiir_offset = 0,
 };
+#endif
 
 static const struct of_device_id fsl_of_msi_ids[] = {
 	{
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/sysdev/fsl_pci.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/sysdev/fsl_pci.c
@@ -520,6 +520,7 @@
 	struct resource rsrc;
 	const int *bus_range;
 	u8 hdr_type, progif;
+	u32 class_code;
 	struct device_node *dev;
 	struct ccsr_pci __iomem *pci;
 	u16 temp;
@@ -593,6 +594,13 @@
 			PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS;
 		if (fsl_pcie_check_link(hose))
 			hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK;
+		/* Fix Class Code to PCI_CLASS_BRIDGE_PCI_NORMAL for pre-3.0 controller */
+		if (in_be32(&pci->block_rev1) < PCIE_IP_REV_3_0) {
+			early_read_config_dword(hose, 0, 0, PCIE_FSL_CSR_CLASSCODE, &class_code);
+			class_code &= 0xff;
+			class_code |= PCI_CLASS_BRIDGE_PCI_NORMAL << 8;
+			early_write_config_dword(hose, 0, 0, PCIE_FSL_CSR_CLASSCODE, class_code);
+		}
 	} else {
 		/*
 		 * Set PBFR(PCI Bus Function Register)[10] = 1 to
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/sysdev/fsl_pci.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/sysdev/fsl_pci.h
@@ -18,6 +18,7 @@
 
 #define PCIE_LTSSM	0x0404		/* PCIE Link Training and Status */
 #define PCIE_LTSSM_L0	0x16		/* L0 state */
+#define PCIE_FSL_CSR_CLASSCODE	0x474	/* FSL GPEX CSR */
 #define PCIE_IP_REV_2_2		0x02080202 /* PCIE IP block version Rev2.2 */
 #define PCIE_IP_REV_3_0		0x02080300 /* PCIE IP block version Rev3.0 */
 #define PIWAR_EN		0x80000000	/* Enable */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/sysdev/fsl_rio.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/sysdev/fsl_rio.c
@@ -505,8 +505,10 @@
 	if (rc) {
 		dev_err(&dev->dev, "Can't get %pOF property 'reg'\n",
 				rmu_node);
+		of_node_put(rmu_node);
 		goto err_rmu;
 	}
+	of_node_put(rmu_node);
 	rmu_regs_win = ioremap(rmu_regs.start, resource_size(&rmu_regs));
 	if (!rmu_regs_win) {
 		dev_err(&dev->dev, "Unable to map rmu register window\n");
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/sysdev/mpic_msgr.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/sysdev/mpic_msgr.c
@@ -191,7 +191,7 @@
 
 	/* IO map the message register block. */
 	of_address_to_resource(np, 0, &rsrc);
-	msgr_block_addr = ioremap(rsrc.start, resource_size(&rsrc));
+	msgr_block_addr = devm_ioremap(&dev->dev, rsrc.start, resource_size(&rsrc));
 	if (!msgr_block_addr) {
 		dev_err(&dev->dev, "Failed to iomap MPIC message registers");
 		return -EFAULT;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/sysdev/tsi108_pci.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/sysdev/tsi108_pci.c
@@ -216,9 +216,8 @@
 
 	(hose)->ops = &tsi108_direct_pci_ops;
 
-	printk(KERN_INFO "Found tsi108 PCI host bridge at 0x%08x. "
-	       "Firmware bus number: %d->%d\n",
-	       rsrc.start, hose->first_busno, hose->last_busno);
+	pr_info("Found tsi108 PCI host bridge at 0x%pa. Firmware bus number: %d->%d\n",
+		&rsrc.start, hose->first_busno, hose->last_busno);
 
 	/* Interpret the "ranges" property */
 	/* This also maps the I/O region and sets isa_io/mem_base */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/sysdev/xics/icp-hv.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/sysdev/xics/icp-hv.c
@@ -174,6 +174,7 @@
 
 	icp_ops = &icp_hv_ops;
 
+	of_node_put(np);
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/sysdev/xics/icp-native.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/sysdev/xics/icp-native.c
@@ -235,6 +235,8 @@
 	rname = kasprintf(GFP_KERNEL, "CPU %d [0x%x] Interrupt Presentation",
 			  cpu, hw_id);
 
+	if (!rname)
+		return -ENOMEM;
 	if (!request_mem_region(addr, size, rname)) {
 		pr_warn("icp_native: Could not reserve ICP MMIO for CPU %d, interrupt server #0x%x\n",
 			cpu, hw_id);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/sysdev/xics/icp-opal.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/sysdev/xics/icp-opal.c
@@ -195,6 +195,7 @@
 
 	printk("XICS: Using OPAL ICP fallbacks\n");
 
+	of_node_put(np);
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/sysdev/xive/common.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/sysdev/xive/common.c
@@ -19,6 +19,7 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/msi.h>
+#include <linux/vmalloc.h>
 
 #include <asm/prom.h>
 #include <asm/io.h>
@@ -68,13 +69,6 @@
 /* Xive state for each CPU */
 static DEFINE_PER_CPU(struct xive_cpu *, xive_cpu);
 
-/*
- * A "disabled" interrupt should never fire, to catch problems
- * we set its logical number to this
- */
-#define XIVE_BAD_IRQ		0x7fffffff
-#define XIVE_MAX_IRQ		(XIVE_BAD_IRQ - 1)
-
 /* An invalid CPU target */
 #define XIVE_INVALID_TARGET	(-1)
 
@@ -263,6 +257,13 @@
 	xmon_printf("\n");
 }
 
+static struct irq_data *xive_get_irq_data(u32 hw_irq)
+{
+	unsigned int irq = irq_find_mapping(xive_irq_domain, hw_irq);
+
+	return irq ? irq_get_irq_data(irq) : NULL;
+}
+
 int xmon_xive_get_irq_config(u32 hw_irq, struct irq_data *d)
 {
 	int rc;
@@ -279,6 +280,9 @@
 	xmon_printf("IRQ 0x%08x : target=0x%x prio=%02x lirq=0x%x ",
 		    hw_irq, target, prio, lirq);
 
+	if (!d)
+		d = xive_get_irq_data(hw_irq);
+
 	if (d) {
 		struct xive_irq_data *xd = irq_data_get_irq_handler_data(d);
 		u64 val = xive_esb_read(xd, XIVE_ESB_GET);
@@ -972,12 +976,22 @@
 				  enum irqchip_irq_state which, bool *state)
 {
 	struct xive_irq_data *xd = irq_data_get_irq_handler_data(data);
+	u8 pq;
 
 	switch (which) {
 	case IRQCHIP_STATE_ACTIVE:
-		*state = !xd->stale_p &&
-			 (xd->saved_p ||
-			  !!(xive_esb_read(xd, XIVE_ESB_GET) & XIVE_ESB_VAL_P));
+		pq = xive_esb_read(xd, XIVE_ESB_GET);
+
+		/*
+		 * The esb value being all 1's means we couldn't get
+		 * the PQ state of the interrupt through mmio. It may
+		 * happen, for example when querying a PHB interrupt
+		 * while the PHB is in an error state. We consider the
+		 * interrupt to be inactive in that case.
+		 */
+		*state = (pq != XIVE_ESB_INVALID) && !xd->stale_p &&
+			(xd->saved_p || (!!(pq & XIVE_ESB_VAL_P) &&
+			 !irqd_irq_disabled(data)));
 		return 0;
 	default:
 		return -EINVAL;
@@ -1007,12 +1021,16 @@
 void xive_cleanup_irq_data(struct xive_irq_data *xd)
 {
 	if (xd->eoi_mmio) {
+		unmap_kernel_range((unsigned long)xd->eoi_mmio,
+				   1u << xd->esb_shift);
 		iounmap(xd->eoi_mmio);
 		if (xd->eoi_mmio == xd->trig_mmio)
 			xd->trig_mmio = NULL;
 		xd->eoi_mmio = NULL;
 	}
 	if (xd->trig_mmio) {
+		unmap_kernel_range((unsigned long)xd->trig_mmio,
+				   1u << xd->esb_shift);
 		iounmap(xd->trig_mmio);
 		xd->trig_mmio = NULL;
 	}
@@ -1035,6 +1053,15 @@
 	xd->target = XIVE_INVALID_TARGET;
 	irq_set_handler_data(virq, xd);
 
+	/*
+	 * Turn OFF by default the interrupt being mapped. A side
+	 * effect of this check is the mapping the ESB page of the
+	 * interrupt in the Linux address space. This prevents page
+	 * fault issues in the crash handler which masks all
+	 * interrupts.
+	 */
+	xive_esb_read(xd, XIVE_ESB_SET_PQ_01);
+
 	return 0;
 }
 
@@ -1132,7 +1159,7 @@
 	xc = per_cpu(xive_cpu, cpu);
 
 	/* Check if we are already setup */
-	if (xc->hw_ipi != 0)
+	if (xc->hw_ipi != XIVE_BAD_IRQ)
 		return 0;
 
 	/* Grab an IPI from the backend, this will populate xc->hw_ipi */
@@ -1169,7 +1196,7 @@
 	/* Disable the IPI and free the IRQ data */
 
 	/* Already cleaned up ? */
-	if (xc->hw_ipi == 0)
+	if (xc->hw_ipi == XIVE_BAD_IRQ)
 		return;
 
 	/* Mask the IPI */
@@ -1325,6 +1352,7 @@
 		if (np)
 			xc->chip_id = of_get_ibm_chip_id(np);
 		of_node_put(np);
+		xc->hw_ipi = XIVE_BAD_IRQ;
 
 		per_cpu(xive_cpu, cpu) = xc;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/sysdev/xive/native.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/sysdev/xive/native.c
@@ -18,6 +18,7 @@
 #include <linux/delay.h>
 #include <linux/cpumask.h>
 #include <linux/mm.h>
+#include <linux/kmemleak.h>
 
 #include <asm/prom.h>
 #include <asm/io.h>
@@ -312,7 +313,7 @@
 	s64 rc;
 
 	/* Free the IPI */
-	if (!xc->hw_ipi)
+	if (xc->hw_ipi == XIVE_BAD_IRQ)
 		return;
 	for (;;) {
 		rc = opal_xive_free_irq(xc->hw_ipi);
@@ -320,7 +321,7 @@
 			msleep(OPAL_BUSY_DELAY_MS);
 			continue;
 		}
-		xc->hw_ipi = 0;
+		xc->hw_ipi = XIVE_BAD_IRQ;
 		break;
 	}
 }
@@ -646,6 +647,7 @@
 			pr_err("Failed to allocate provisioning page\n");
 			return false;
 		}
+		kmemleak_ignore(p);
 		opal_xive_donate_page(chip, __pa(p));
 	}
 	return true;
@@ -776,7 +778,7 @@
 	if (out_qpage)
 		*out_qpage = be64_to_cpu(qpage);
 	if (out_qsize)
-		*out_qsize = be32_to_cpu(qsize);
+		*out_qsize = be64_to_cpu(qsize);
 	if (out_qeoi_page)
 		*out_qeoi_page = be64_to_cpu(qeoi_page);
 	if (out_escalate_irq)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/sysdev/xive/spapr.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/sysdev/xive/spapr.c
@@ -392,20 +392,28 @@
 	data->esb_shift = esb_shift;
 	data->trig_page = trig_page;
 
+	data->hw_irq = hw_irq;
+
 	/*
 	 * No chip-id for the sPAPR backend. This has an impact how we
 	 * pick a target. See xive_pick_irq_target().
 	 */
 	data->src_chip = XIVE_INVALID_CHIP_ID;
 
+	/*
+	 * When the H_INT_ESB flag is set, the H_INT_ESB hcall should
+	 * be used for interrupt management. Skip the remapping of the
+	 * ESB pages which are not available.
+	 */
+	if (data->flags & XIVE_IRQ_FLAG_H_INT_ESB)
+		return 0;
+
 	data->eoi_mmio = ioremap(data->eoi_page, 1u << data->esb_shift);
 	if (!data->eoi_mmio) {
 		pr_err("Failed to map EOI page for irq 0x%x\n", hw_irq);
 		return -ENOMEM;
 	}
 
-	data->hw_irq = hw_irq;
-
 	/* Full function page supports trigger */
 	if (flags & XIVE_SRC_TRIGGER) {
 		data->trig_mmio = data->eoi_mmio;
@@ -414,6 +422,7 @@
 
 	data->trig_mmio = ioremap(data->trig_page, 1u << data->esb_shift);
 	if (!data->trig_mmio) {
+		iounmap(data->eoi_mmio);
 		pr_err("Failed to map trigger page for irq 0x%x\n", hw_irq);
 		return -ENOMEM;
 	}
@@ -552,11 +561,11 @@
 
 static void xive_spapr_put_ipi(unsigned int cpu, struct xive_cpu *xc)
 {
-	if (!xc->hw_ipi)
+	if (xc->hw_ipi == XIVE_BAD_IRQ)
 		return;
 
 	xive_irq_bitmap_free(xc->hw_ipi);
-	xc->hw_ipi = 0;
+	xc->hw_ipi = XIVE_BAD_IRQ;
 }
 #endif /* CONFIG_SMP */
 
@@ -675,6 +684,7 @@
 	}
 
 	reg = of_get_property(rootdn, "ibm,plat-res-int-priorities", &len);
+	of_node_put(rootdn);
 	if (!reg) {
 		pr_err("Failed to read 'ibm,plat-res-int-priorities' property\n");
 		return false;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/sysdev/xive/xive-internal.h
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/sysdev/xive/xive-internal.h
@@ -5,6 +5,13 @@
 #ifndef __XIVE_INTERNAL_H
 #define __XIVE_INTERNAL_H
 
+/*
+ * A "disabled" interrupt should never fire, to catch problems
+ * we set its logical number to this
+ */
+#define XIVE_BAD_IRQ		0x7fffffff
+#define XIVE_MAX_IRQ		(XIVE_BAD_IRQ - 1)
+
 /* Each CPU carry one of these with various per-CPU state */
 struct xive_cpu {
 #ifdef CONFIG_SMP
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/tools/relocs_check.sh
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/tools/relocs_check.sh
@@ -10,24 +10,29 @@
 # based on relocs_check.pl
 # Copyright © 2009 IBM Corporation
 
-if [ $# -lt 2 ]; then
-	echo "$0 [path to objdump] [path to vmlinux]" 1>&2
+if [ $# -lt 3 ]; then
+	echo "$0 [path to objdump] [path to nm] [path to vmlinux]" 1>&2
 	exit 1
 fi
 
-# Have Kbuild supply the path to objdump so we handle cross compilation.
+# Have Kbuild supply the path to objdump and nm so we handle cross compilation.
 objdump="$1"
-vmlinux="$2"
+nm="$2"
+vmlinux="$3"
+
+# Remove from the bad relocations those that match an undefined weak symbol
+# which will result in an absolute relocation to 0.
+# Weak unresolved symbols are of that form in nm output:
+# "                  w _binary__btf_vmlinux_bin_end"
+undef_weak_symbols=$($nm "$vmlinux" | awk '$1 ~ /w/ { print $2 }')
 
 bad_relocs=$(
-"$objdump" -R "$vmlinux" |
+$objdump -R "$vmlinux" |
 	# Only look at relocation lines.
 	grep -E '\<R_' |
 	# These relocations are okay
 	# On PPC64:
 	#	R_PPC64_RELATIVE, R_PPC64_NONE
-	#	R_PPC64_ADDR64 mach_<name>
-	#	R_PPC64_ADDR64 __crc_<name>
 	# On PPC:
 	#	R_PPC_RELATIVE, R_PPC_ADDR16_HI,
 	#	R_PPC_ADDR16_HA,R_PPC_ADDR16_LO,
@@ -39,8 +44,7 @@
 R_PPC_ADDR16_HA
 R_PPC_RELATIVE
 R_PPC_NONE' |
-	grep -E -v '\<R_PPC64_ADDR64[[:space:]]+mach_' |
-	grep -E -v '\<R_PPC64_ADDR64[[:space:]]+__crc_'
+	([ "$undef_weak_symbols" ] && grep -F -w -v "$undef_weak_symbols" || cat)
 )
 
 if [ -z "$bad_relocs" ]; then
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/tools/unrel_branch_check.sh
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/tools/unrel_branch_check.sh
@@ -18,14 +18,14 @@
 #__end_interrupts should be located within the first 64K
 
 end_intr=0x$(
-"$objdump" -R "$vmlinux" -d --start-address=0xc000000000000000		\
+$objdump -R "$vmlinux" -d --start-address=0xc000000000000000           \
 		 --stop-address=0xc000000000010000 |
 grep '\<__end_interrupts>:' |
 awk '{print $1}'
 )
 
 BRANCHES=$(
-"$objdump" -R "$vmlinux" -D --start-address=0xc000000000000000		\
+$objdump -R "$vmlinux" -D --start-address=0xc000000000000000           \
 		--stop-address=${end_intr} |
 grep -e "^c[0-9a-f]*:[[:space:]]*\([0-9a-f][0-9a-f][[:space:]]\)\{4\}[[:space:]]*b" |
 grep -v '\<__start_initialization_multiplatform>' |
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/xmon/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/xmon/Makefile
@@ -1,9 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 # Makefile for xmon
 
-# Disable clang warning for using setjmp without setjmp.h header
-subdir-ccflags-y := $(call cc-disable-warning, builtin-requires-header)
-
 GCOV_PROFILE := n
 KCOV_INSTRUMENT := n
 UBSAN_SANITIZE := n
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/xmon/nonstdio.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/xmon/nonstdio.c
@@ -178,7 +178,7 @@
 
 	if (n && rc == 0) {
 		/* No udbg hooks, fallback to printk() - dangerous */
-		printk("%s", xmon_outbuf);
+		pr_cont("%s", xmon_outbuf);
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/xmon/ppc-dis.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/xmon/ppc-dis.c
@@ -122,32 +122,21 @@
   bool insn_is_short;
   ppc_cpu_t dialect;
 
-  dialect = PPC_OPCODE_PPC | PPC_OPCODE_COMMON
-            | PPC_OPCODE_64 | PPC_OPCODE_POWER4 | PPC_OPCODE_ALTIVEC;
+  dialect = PPC_OPCODE_PPC | PPC_OPCODE_COMMON;
 
-  if (cpu_has_feature(CPU_FTRS_POWER5))
-    dialect |= PPC_OPCODE_POWER5;
+  if (IS_ENABLED(CONFIG_PPC64))
+    dialect |= PPC_OPCODE_64 | PPC_OPCODE_POWER4 | PPC_OPCODE_CELL |
+	PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 |
+	PPC_OPCODE_POWER9;
 
-  if (cpu_has_feature(CPU_FTRS_CELL))
-    dialect |= (PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC);
+  if (cpu_has_feature(CPU_FTR_TM))
+    dialect |= PPC_OPCODE_HTM;
 
-  if (cpu_has_feature(CPU_FTRS_POWER6))
-    dialect |= (PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC);
-
-  if (cpu_has_feature(CPU_FTRS_POWER7))
-    dialect |= (PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7
-                | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX);
-
-  if (cpu_has_feature(CPU_FTRS_POWER8))
-    dialect |= (PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7
-		| PPC_OPCODE_POWER8 | PPC_OPCODE_HTM
-		| PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2 | PPC_OPCODE_VSX);
-
-  if (cpu_has_feature(CPU_FTRS_POWER9))
-    dialect |= (PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7
-		| PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9 | PPC_OPCODE_HTM
-		| PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2
-		| PPC_OPCODE_VSX | PPC_OPCODE_VSX3);
+  if (cpu_has_feature(CPU_FTR_ALTIVEC))
+    dialect |= PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2;
+
+  if (cpu_has_feature(CPU_FTR_VSX))
+    dialect |= PPC_OPCODE_VSX | PPC_OPCODE_VSX3;
 
   /* Get the major opcode of the insn.  */
   opcode = NULL;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/powerpc/xmon/xmon.c
+++ linux-xilinx-zynqmp-5.4.0/arch/powerpc/xmon/xmon.c
@@ -25,6 +25,7 @@
 #include <linux/nmi.h>
 #include <linux/ctype.h>
 #include <linux/highmem.h>
+#include <linux/security.h>
 
 #include <asm/debugfs.h>
 #include <asm/ptrace.h>
@@ -187,6 +188,8 @@
 static void dump_tlb_book3e(void);
 #endif
 
+static void clear_all_bpt(void);
+
 #ifdef CONFIG_PPC64
 #define REG		"%.16lx"
 #else
@@ -283,10 +286,38 @@
 "  U	show uptime information\n"
 "  ?	help\n"
 "  # n	limit output to n lines per page (for dp, dpa, dl)\n"
-"  zr	reboot\n\
-  zh	halt\n"
+"  zr	reboot\n"
+"  zh	halt\n"
 ;
 
+#ifdef CONFIG_SECURITY
+static bool xmon_is_locked_down(void)
+{
+	static bool lockdown;
+
+	if (!lockdown) {
+		lockdown = !!security_locked_down(LOCKDOWN_XMON_RW);
+		if (lockdown) {
+			printf("xmon: Disabled due to kernel lockdown\n");
+			xmon_is_ro = true;
+		}
+	}
+
+	if (!xmon_is_ro) {
+		xmon_is_ro = !!security_locked_down(LOCKDOWN_XMON_WR);
+		if (xmon_is_ro)
+			printf("xmon: Read-only due to kernel lockdown\n");
+	}
+
+	return lockdown;
+}
+#else /* CONFIG_SECURITY */
+static inline bool xmon_is_locked_down(void)
+{
+	return false;
+}
+#endif
+
 static struct pt_regs *xmon_regs;
 
 static inline void sync(void)
@@ -438,7 +469,10 @@
 
 	return false;
 }
-#endif /* CONFIG_SMP */
+#else /* CONFIG_SMP */
+static inline void get_output_lock(void) {}
+static inline void release_output_lock(void) {}
+#endif
 
 static inline int unrecoverable_excp(struct pt_regs *regs)
 {
@@ -455,6 +489,7 @@
 	int cmd = 0;
 	struct bpt *bp;
 	long recurse_jmp[JMP_BUF_LEN];
+	bool locked_down;
 	unsigned long offset;
 	unsigned long flags;
 #ifdef CONFIG_SMP
@@ -465,6 +500,8 @@
 	local_irq_save(flags);
 	hard_irq_disable();
 
+	locked_down = xmon_is_locked_down();
+
 	if (!fromipi) {
 		tracing_enabled = tracing_is_on();
 		tracing_off();
@@ -518,7 +555,8 @@
 
 	if (!fromipi) {
 		get_output_lock();
-		excprint(regs);
+		if (!locked_down)
+			excprint(regs);
 		if (bp) {
 			printf("cpu 0x%x stopped at breakpoint 0x%tx (",
 			       cpu, BP_NUM(bp));
@@ -570,10 +608,14 @@
 		}
 		remove_bpts();
 		disable_surveillance();
-		/* for breakpoint or single step, print the current instr. */
-		if (bp || TRAP(regs) == 0xd00)
-			ppc_inst_dump(regs->nip, 1, 0);
-		printf("enter ? for help\n");
+
+		if (!locked_down) {
+			/* for breakpoint or single step, print curr insn */
+			if (bp || TRAP(regs) == 0xd00)
+				ppc_inst_dump(regs->nip, 1, 0);
+			printf("enter ? for help\n");
+		}
+
 		mb();
 		xmon_gate = 1;
 		barrier();
@@ -597,8 +639,9 @@
 			spin_cpu_relax();
 			touch_nmi_watchdog();
 		} else {
-			cmd = cmds(regs);
-			if (cmd != 0) {
+			if (!locked_down)
+				cmd = cmds(regs);
+			if (locked_down || cmd != 0) {
 				/* exiting xmon */
 				insert_bpts();
 				xmon_gate = 0;
@@ -635,13 +678,16 @@
 			       "can't continue\n");
 		remove_bpts();
 		disable_surveillance();
-		/* for breakpoint or single step, print the current instr. */
-		if (bp || TRAP(regs) == 0xd00)
-			ppc_inst_dump(regs->nip, 1, 0);
-		printf("enter ? for help\n");
+		if (!locked_down) {
+			/* for breakpoint or single step, print current insn */
+			if (bp || TRAP(regs) == 0xd00)
+				ppc_inst_dump(regs->nip, 1, 0);
+			printf("enter ? for help\n");
+		}
 	}
 
-	cmd = cmds(regs);
+	if (!locked_down)
+		cmd = cmds(regs);
 
 	insert_bpts();
 	in_xmon = 0;
@@ -670,7 +716,10 @@
 		}
 	}
 #endif
-	insert_cpu_bpts();
+	if (locked_down)
+		clear_all_bpt();
+	else
+		insert_cpu_bpts();
 
 	touch_nmi_watchdog();
 	local_irq_restore(flags);
@@ -1165,7 +1214,7 @@
 	unsigned long cpu, first_cpu, last_cpu;
 	int timeout;
 
-	if (!scanhex(&cpu)) {
+	if (!scanhex(&cpu) || cpu >= num_possible_cpus()) {
 		/* print cpus waiting or in xmon */
 		printf("cpus stopped:");
 		last_cpu = first_cpu = NR_CPUS;
@@ -1894,15 +1943,14 @@
 
 	printf("pidr   = %.16lx  tidr  = %.16lx\n",
 		mfspr(SPRN_PID), mfspr(SPRN_TIDR));
-	printf("asdr   = %.16lx  psscr = %.16lx\n",
-		mfspr(SPRN_ASDR), hv ? mfspr(SPRN_PSSCR)
-					: mfspr(SPRN_PSSCR_PR));
+	printf("psscr  = %.16lx\n",
+		hv ? mfspr(SPRN_PSSCR) : mfspr(SPRN_PSSCR_PR));
 
 	if (!hv)
 		return;
 
-	printf("ptcr   = %.16lx\n",
-		mfspr(SPRN_PTCR));
+	printf("ptcr   = %.16lx  asdr  = %.16lx\n",
+		mfspr(SPRN_PTCR), mfspr(SPRN_ASDR));
 #endif
 }
 
@@ -2523,7 +2571,7 @@
 
 	termch = c;	/* Put c back, it wasn't 'a' */
 
-	if (scanhex(&num))
+	if (scanhex(&num) && num < num_possible_cpus())
 		dump_one_paca(num);
 	else
 		dump_one_paca(xmon_owner);
@@ -2620,7 +2668,7 @@
 
 	termch = c;	/* Put c back, it wasn't 'a' */
 
-	if (scanhex(&num))
+	if (scanhex(&num) && num < num_possible_cpus())
 		dump_one_xive(num);
 	else
 		dump_one_xive(xmon_owner);
@@ -3762,6 +3810,11 @@
 #ifdef CONFIG_MAGIC_SYSRQ
 static void sysrq_handle_xmon(int key)
 {
+	if (xmon_is_locked_down()) {
+		clear_all_bpt();
+		xmon_init(0);
+		return;
+	}
 	/* ensure xmon is enabled */
 	xmon_init(1);
 	debugger(get_irq_regs());
@@ -3783,7 +3836,6 @@
 device_initcall(setup_xmon_sysrq);
 #endif /* CONFIG_MAGIC_SYSRQ */
 
-#ifdef CONFIG_DEBUG_FS
 static void clear_all_bpt(void)
 {
 	int i;
@@ -3801,18 +3853,22 @@
 		iabr = NULL;
 		dabr.enabled = 0;
 	}
-
-	printf("xmon: All breakpoints cleared\n");
 }
 
+#ifdef CONFIG_DEBUG_FS
 static int xmon_dbgfs_set(void *data, u64 val)
 {
 	xmon_on = !!val;
 	xmon_init(xmon_on);
 
 	/* make sure all breakpoints removed when disabling */
-	if (!xmon_on)
+	if (!xmon_on) {
 		clear_all_bpt();
+		get_output_lock();
+		printf("xmon: All breakpoints cleared\n");
+		release_output_lock();
+	}
+
 	return 0;
 }
 
@@ -3838,7 +3894,11 @@
 
 static int __init early_parse_xmon(char *p)
 {
-	if (!p || strncmp(p, "early", 5) == 0) {
+	if (xmon_is_locked_down()) {
+		xmon_init(0);
+		xmon_early = 0;
+		xmon_on = 0;
+	} else if (!p || strncmp(p, "early", 5) == 0) {
 		/* just "xmon" is equivalent to "xmon=early" */
 		xmon_init(1);
 		xmon_early = 1;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/Kconfig
@@ -31,6 +31,7 @@
 	select GENERIC_SMP_IDLE_THREAD
 	select GENERIC_ATOMIC64 if !64BIT
 	select HAVE_ARCH_AUDITSYSCALL
+	select HAVE_ARCH_SECCOMP_FILTER
 	select HAVE_ASM_MODVERSIONS
 	select HAVE_MEMBLOCK_NODE_MAP
 	select HAVE_DMA_CONTIGUOUS
@@ -51,16 +52,16 @@
 	select PCI_MSI if PCI
 	select RISCV_TIMER
 	select GENERIC_IRQ_MULTI_HANDLER
-	select GENERIC_ARCH_TOPOLOGY if SMP
+	select GENERIC_ARCH_TOPOLOGY
 	select ARCH_HAS_PTE_SPECIAL
 	select ARCH_HAS_MMIOWB
 	select HAVE_EBPF_JIT if 64BIT
 	select EDAC_SUPPORT
 	select ARCH_HAS_GIGANTIC_PAGE
 	select ARCH_WANT_HUGE_PMD_SHARE if 64BIT
-	select SPARSEMEM_STATIC if 32BIT
 	select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU
 	select HAVE_ARCH_MMAP_RND_BITS
+	select HAVE_COPY_THREAD_TLS
 
 config ARCH_MMAP_RND_BITS_MIN
 	default 18 if 64BIT
@@ -100,7 +101,9 @@
 
 config ARCH_SPARSEMEM_ENABLE
 	def_bool y
-	select SPARSEMEM_VMEMMAP_ENABLE
+	depends on MMU
+	select SPARSEMEM_STATIC if 32BIT && SPARSEMEM
+	select SPARSEMEM_VMEMMAP_ENABLE if 64BIT
 
 config ARCH_SELECT_MEMORY_MODEL
 	def_bool ARCH_SPARSEMEM_ENABLE
@@ -137,6 +140,11 @@
 config FIX_EARLYCON_MEM
 	def_bool y
 
+config ILLEGAL_POINTER_VALUE
+	hex
+	default 0 if 32BIT
+	default 0xdead000000000000 if 64BIT
+
 config PGTABLE_LEVELS
 	int
 	default 3 if 64BIT
@@ -272,6 +280,19 @@
 
 source "kernel/Kconfig.hz"
 
+config SECCOMP
+	bool "Enable seccomp to safely compute untrusted bytecode"
+	help
+	  This kernel feature is useful for number crunching applications
+	  that may need to compute untrusted bytecode during their
+	  execution. By using pipes or other transports made available to
+	  the process as file descriptors supporting the read/write
+	  syscalls, it's possible to isolate those applications in
+	  their own address space using seccomp. Once seccomp is
+	  enabled via prctl(PR_SET_SECCOMP), it cannot be disabled
+	  and the task is only allowed to execute a few safe syscalls
+	  defined by each seccomp mode.
+
 endmenu
 
 menu "Boot options"
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/Makefile
@@ -34,11 +34,28 @@
 	KBUILD_LDFLAGS += -melf32lriscv
 endif
 
+ifeq ($(CONFIG_LD_IS_LLD),y)
+ifeq ($(shell test $(CONFIG_LLD_VERSION) -lt 150000; echo $$?),0)
+	KBUILD_CFLAGS += -mno-relax
+	KBUILD_AFLAGS += -mno-relax
+ifneq ($(LLVM_IAS),1)
+	KBUILD_CFLAGS += -Wa,-mno-relax
+	KBUILD_AFLAGS += -Wa,-mno-relax
+endif
+endif
+endif
+
 # ISA string setting
 riscv-march-$(CONFIG_ARCH_RV32I)	:= rv32ima
 riscv-march-$(CONFIG_ARCH_RV64I)	:= rv64ima
 riscv-march-$(CONFIG_FPU)		:= $(riscv-march-y)fd
 riscv-march-$(CONFIG_RISCV_ISA_C)	:= $(riscv-march-y)c
+
+# Newer binutils versions default to ISA spec version 20191213 which moves some
+# instructions from the I extension to the Zicsr and Zifencei extensions.
+toolchain-need-zicsr-zifencei := $(call cc-option-yn, -march=$(riscv-march-y)_zicsr_zifencei)
+riscv-march-$(toolchain-need-zicsr-zifencei) := $(riscv-march-y)_zicsr_zifencei
+
 KBUILD_CFLAGS += -march=$(subst fd,,$(riscv-march-y))
 KBUILD_AFLAGS += -march=$(riscv-march-y)
 
@@ -58,7 +75,11 @@
         KBUILD_CFLAGS += -fno-omit-frame-pointer
 endif
 
+# Avoid generating .eh_frame sections.
+KBUILD_CFLAGS += -fno-asynchronous-unwind-tables -fno-unwind-tables
+
 KBUILD_CFLAGS_MODULE += $(call cc-option,-mno-relax)
+KBUILD_AFLAGS_MODULE += $(call as-option,-Wa$(comma)-mno-relax)
 
 # GCC versions that support the "-mstrict-align" option default to allowing
 # unaligned accesses.  While unaligned accesses are explicitly allowed in the
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts
@@ -83,6 +83,7 @@
 	phy-mode = "gmii";
 	phy-handle = <&phy0>;
 	phy0: ethernet-phy@0 {
+		compatible = "ethernet-phy-id0007.0771";
 		reg = <0>;
 	};
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/configs/defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/configs/defconfig
@@ -62,6 +62,8 @@
 CONFIG_HW_RANDOM_VIRTIO=y
 CONFIG_SPI=y
 CONFIG_SPI_SIFIVE=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SIFIVE=y
 # CONFIG_PTP_1588_CLOCK is not set
 CONFIG_DRM=y
 CONFIG_DRM_RADEON=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/include/asm/Kbuild
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/include/asm/Kbuild
@@ -7,7 +7,6 @@
 generic-y += extable.h
 generic-y += flat.h
 generic-y += dma.h
-generic-y += dma-contiguous.h
 generic-y += dma-mapping.h
 generic-y += emergency-restart.h
 generic-y += exec.h
@@ -22,7 +21,6 @@
 generic-y += local.h
 generic-y += local64.h
 generic-y += mm-arch-hooks.h
-generic-y += msi.h
 generic-y += percpu.h
 generic-y += preempt.h
 generic-y += sections.h
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/include/asm/asm-prototypes.h
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/include/asm/asm-prototypes.h
@@ -4,4 +4,8 @@
 #include <linux/ftrace.h>
 #include <asm-generic/asm-prototypes.h>
 
+long long __lshrti3(long long a, int b);
+long long __ashrti3(long long a, int b);
+long long __ashlti3(long long a, int b);
+
 #endif /* _ASM_RISCV_PROTOTYPES_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/include/asm/barrier.h
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/include/asm/barrier.h
@@ -58,8 +58,16 @@
  * The AQ/RL pair provides a RCpc critical section, but there's not really any
  * way we can take advantage of that here because the ordering is only enforced
  * on that one lock.  Thus, we're just doing a full fence.
+ *
+ * Since we allow writeX to be called from preemptive regions we need at least
+ * an "o" in the predecessor set to ensure device writes are visible before the
+ * task is marked as available for scheduling on a new hart.  While I don't see
+ * any concrete reason we need a full IO fence, it seems safer to just upgrade
+ * this in order to avoid any IO crossing a scheduling boundary.  In both
+ * instances the scheduler pairs this with an mb(), so nothing is necessary on
+ * the new hart.
  */
-#define smp_mb__after_spinlock()	RISCV_FENCE(rw,rw)
+#define smp_mb__after_spinlock()	RISCV_FENCE(iorw,iorw)
 
 #include <asm-generic/barrier.h>
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/include/asm/cmpxchg.h
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/include/asm/cmpxchg.h
@@ -179,7 +179,7 @@
 			"	bnez %1, 0b\n"				\
 			"1:\n"						\
 			: "=&r" (__ret), "=&r" (__rc), "+A" (*__ptr)	\
-			: "rJ" (__old), "rJ" (__new)			\
+			: "rJ" ((long)__old), "rJ" (__new)		\
 			: "memory");					\
 		break;							\
 	case 8:								\
@@ -224,7 +224,7 @@
 			RISCV_ACQUIRE_BARRIER				\
 			"1:\n"						\
 			: "=&r" (__ret), "=&r" (__rc), "+A" (*__ptr)	\
-			: "rJ" (__old), "rJ" (__new)			\
+			: "rJ" ((long)__old), "rJ" (__new)		\
 			: "memory");					\
 		break;							\
 	case 8:								\
@@ -270,7 +270,7 @@
 			"	bnez %1, 0b\n"				\
 			"1:\n"						\
 			: "=&r" (__ret), "=&r" (__rc), "+A" (*__ptr)	\
-			: "rJ" (__old), "rJ" (__new)			\
+			: "rJ" ((long)__old), "rJ" (__new)		\
 			: "memory");					\
 		break;							\
 	case 8:								\
@@ -316,7 +316,7 @@
 			"	fence rw, rw\n"				\
 			"1:\n"						\
 			: "=&r" (__ret), "=&r" (__rc), "+A" (*__ptr)	\
-			: "rJ" (__old), "rJ" (__new)			\
+			: "rJ" ((long)__old), "rJ" (__new)		\
 			: "memory");					\
 		break;							\
 	case 8:								\
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/include/asm/ftrace.h
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/include/asm/ftrace.h
@@ -10,9 +10,19 @@
 #endif
 #define HAVE_FUNCTION_GRAPH_RET_ADDR_PTR
 
+/*
+ * Clang prior to 13 had "mcount" instead of "_mcount":
+ * https://reviews.llvm.org/D98881
+ */
+#if defined(CONFIG_CC_IS_GCC) || CONFIG_CLANG_VERSION >= 130000
+#define MCOUNT_NAME _mcount
+#else
+#define MCOUNT_NAME mcount
+#endif
+
 #define ARCH_SUPPORTS_FTRACE_OPS 1
 #ifndef __ASSEMBLY__
-void _mcount(void);
+void MCOUNT_NAME(void);
 static inline unsigned long ftrace_call_adjust(unsigned long addr)
 {
 	return addr;
@@ -33,7 +43,7 @@
  * both auipc and jalr at the same time.
  */
 
-#define MCOUNT_ADDR		((unsigned long)_mcount)
+#define MCOUNT_ADDR		((unsigned long)MCOUNT_NAME)
 #define JALR_SIGN_MASK		(0x00000800)
 #define JALR_OFFSET_MASK	(0x00000fff)
 #define AUIPC_OFFSET_MASK	(0xfffff000)
@@ -63,4 +73,11 @@
  * Let auipc+jalr be the basic *mcount unit*, so we make it 8 bytes here.
  */
 #define MCOUNT_INSN_SIZE 8
+
+#ifndef __ASSEMBLY__
+struct dyn_ftrace;
+int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec);
+#define ftrace_init_nop ftrace_init_nop
+#endif
+
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/include/asm/io.h
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/include/asm/io.h
@@ -252,9 +252,9 @@
 __io_reads_ins(ins,  u8, b, __io_pbr(), __io_par(addr))
 __io_reads_ins(ins, u16, w, __io_pbr(), __io_par(addr))
 __io_reads_ins(ins, u32, l, __io_pbr(), __io_par(addr))
-#define insb(addr, buffer, count) __insb((void __iomem *)(long)addr, buffer, count)
-#define insw(addr, buffer, count) __insw((void __iomem *)(long)addr, buffer, count)
-#define insl(addr, buffer, count) __insl((void __iomem *)(long)addr, buffer, count)
+#define insb(addr, buffer, count) __insb(PCI_IOBASE + (addr), buffer, count)
+#define insw(addr, buffer, count) __insw(PCI_IOBASE + (addr), buffer, count)
+#define insl(addr, buffer, count) __insl(PCI_IOBASE + (addr), buffer, count)
 
 __io_writes_outs(writes,  u8, b, __io_bw(), __io_aw())
 __io_writes_outs(writes, u16, w, __io_bw(), __io_aw())
@@ -266,22 +266,22 @@
 __io_writes_outs(outs,  u8, b, __io_pbw(), __io_paw())
 __io_writes_outs(outs, u16, w, __io_pbw(), __io_paw())
 __io_writes_outs(outs, u32, l, __io_pbw(), __io_paw())
-#define outsb(addr, buffer, count) __outsb((void __iomem *)(long)addr, buffer, count)
-#define outsw(addr, buffer, count) __outsw((void __iomem *)(long)addr, buffer, count)
-#define outsl(addr, buffer, count) __outsl((void __iomem *)(long)addr, buffer, count)
+#define outsb(addr, buffer, count) __outsb(PCI_IOBASE + (addr), buffer, count)
+#define outsw(addr, buffer, count) __outsw(PCI_IOBASE + (addr), buffer, count)
+#define outsl(addr, buffer, count) __outsl(PCI_IOBASE + (addr), buffer, count)
 
 #ifdef CONFIG_64BIT
 __io_reads_ins(reads, u64, q, __io_br(), __io_ar(addr))
 #define readsq(addr, buffer, count) __readsq(addr, buffer, count)
 
 __io_reads_ins(ins, u64, q, __io_pbr(), __io_par(addr))
-#define insq(addr, buffer, count) __insq((void __iomem *)addr, buffer, count)
+#define insq(addr, buffer, count) __insq(PCI_IOBASE + (addr), buffer, count)
 
 __io_writes_outs(writes, u64, q, __io_bw(), __io_aw())
 #define writesq(addr, buffer, count) __writesq(addr, buffer, count)
 
 __io_writes_outs(outs, u64, q, __io_pbr(), __io_paw())
-#define outsq(addr, buffer, count) __outsq((void __iomem *)addr, buffer, count)
+#define outsq(addr, buffer, count) __outsq(PCI_IOBASE + (addr), buffer, count)
 #endif
 
 #include <asm-generic/io.h>
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/include/asm/page.h
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/include/asm/page.h
@@ -119,7 +119,10 @@
 
 #endif /* __ASSEMBLY__ */
 
-#define virt_addr_valid(vaddr)	(pfn_valid(virt_to_pfn(vaddr)))
+#define virt_addr_valid(vaddr)	({						\
+	unsigned long _addr = (unsigned long)vaddr;				\
+	(unsigned long)(_addr) >= PAGE_OFFSET && pfn_valid(virt_to_pfn(_addr));	\
+})
 
 #define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | \
 				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/include/asm/pgtable-32.h
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/include/asm/pgtable-32.h
@@ -14,4 +14,6 @@
 #define PGDIR_SIZE      (_AC(1, UL) << PGDIR_SHIFT)
 #define PGDIR_MASK      (~(PGDIR_SIZE - 1))
 
+#define MAX_POSSIBLE_PHYSMEM_BITS 34
+
 #endif /* _ASM_RISCV_PGTABLE_32_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/include/asm/processor.h
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/include/asm/processor.h
@@ -22,6 +22,8 @@
 
 #ifndef __ASSEMBLY__
 
+#include <asm/barrier.h>
+
 struct task_struct;
 struct pt_regs;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/include/asm/seccomp.h
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/include/asm/seccomp.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _ASM_SECCOMP_H
+#define _ASM_SECCOMP_H
+
+#include <asm/unistd.h>
+
+#include <asm-generic/seccomp.h>
+
+#endif /* _ASM_SECCOMP_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/include/asm/thread_info.h
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/include/asm/thread_info.h
@@ -12,7 +12,11 @@
 #include <linux/const.h>
 
 /* thread information allocation */
+#ifdef CONFIG_64BIT
+#define THREAD_SIZE_ORDER	(2)
+#else
 #define THREAD_SIZE_ORDER	(1)
+#endif
 #define THREAD_SIZE		(PAGE_SIZE << THREAD_SIZE_ORDER)
 
 #ifndef __ASSEMBLY__
@@ -75,6 +79,7 @@
 #define TIF_MEMDIE		5	/* is terminating due to OOM killer */
 #define TIF_SYSCALL_TRACEPOINT  6       /* syscall tracepoint instrumentation */
 #define TIF_SYSCALL_AUDIT	7	/* syscall auditing */
+#define TIF_SECCOMP		8	/* syscall secure computing */
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
@@ -82,11 +87,13 @@
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
 #define _TIF_SYSCALL_TRACEPOINT	(1 << TIF_SYSCALL_TRACEPOINT)
 #define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
+#define _TIF_SECCOMP		(1 << TIF_SECCOMP)
 
 #define _TIF_WORK_MASK \
 	(_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | _TIF_NEED_RESCHED)
 
 #define _TIF_SYSCALL_WORK \
-	(_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_SYSCALL_AUDIT)
+	(_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_SYSCALL_AUDIT | \
+	 _TIF_SECCOMP)
 
 #endif /* _ASM_RISCV_THREAD_INFO_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/include/asm/uaccess.h
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/include/asm/uaccess.h
@@ -235,7 +235,7 @@
 	might_fault();						\
 	access_ok(__p, sizeof(*__p)) ?		\
 		__get_user((x), __p) :				\
-		((x) = 0, -EFAULT);				\
+		((x) = (__force __typeof__(x))0, -EFAULT);	\
 })
 
 #define __put_user_asm(insn, x, ptr, err)			\
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/include/uapi/asm/auxvec.h
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/include/uapi/asm/auxvec.h
@@ -10,4 +10,7 @@
 /* vDSO location */
 #define AT_SYSINFO_EHDR 33
 
+/* entries in ARCH_DLINFO */
+#define AT_VECTOR_SIZE_ARCH	1
+
 #endif /* _UAPI_ASM_RISCV_AUXVEC_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/include/uapi/asm/setup.h
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/include/uapi/asm/setup.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
+
+#ifndef _UAPI_ASM_RISCV_SETUP_H
+#define _UAPI_ASM_RISCV_SETUP_H
+
+#define COMMAND_LINE_SIZE	1024
+
+#endif /* _UAPI_ASM_RISCV_SETUP_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/include/uapi/asm/unistd.h
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/include/uapi/asm/unistd.h
@@ -18,9 +18,10 @@
 #ifdef __LP64__
 #define __ARCH_WANT_NEW_STAT
 #define __ARCH_WANT_SET_GET_RLIMIT
-#define __ARCH_WANT_SYS_CLONE3
 #endif /* __LP64__ */
 
+#define __ARCH_WANT_SYS_CLONE3
+
 #include <asm-generic/unistd.h>
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/kernel/asm-offsets.c
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/kernel/asm-offsets.c
@@ -4,8 +4,6 @@
  * Copyright (C) 2017 SiFive
  */
 
-#define GENERATING_ASM_OFFSETS
-
 #include <linux/kbuild.h>
 #include <linux/sched.h>
 #include <asm/thread_info.h>
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/kernel/cacheinfo.c
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/kernel/cacheinfo.c
@@ -16,7 +16,7 @@
 	this_leaf->type = type;
 }
 
-static int __init_cache_level(unsigned int cpu)
+int init_cache_level(unsigned int cpu)
 {
 	struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
 	struct device_node *np = of_cpu_device_node_get(cpu);
@@ -58,7 +58,7 @@
 	return 0;
 }
 
-static int __populate_cache_leaves(unsigned int cpu)
+int populate_cache_leaves(unsigned int cpu)
 {
 	struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
 	struct cacheinfo *this_leaf = this_cpu_ci->info_list;
@@ -95,6 +95,3 @@
 
 	return 0;
 }
-
-DEFINE_SMP_CALL_CACHE_FUNCTION(init_cache_level)
-DEFINE_SMP_CALL_CACHE_FUNCTION(populate_cache_leaves)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/kernel/entry.S
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/kernel/entry.S
@@ -226,8 +226,26 @@
 	/* Check to make sure we don't jump to a bogus syscall number. */
 	li t0, __NR_syscalls
 	la s0, sys_ni_syscall
-	/* Syscall number held in a7 */
-	bgeu a7, t0, 1f
+	/*
+	 * The tracer can change syscall number to valid/invalid value.
+	 * We use syscall_set_nr helper in syscall_trace_enter thus we
+	 * cannot trust the current value in a7 and have to reload from
+	 * the current task pt_regs.
+	 */
+	REG_L a7, PT_A7(sp)
+	/*
+	 * Syscall number held in a7.
+	 * If syscall number is above allowed value, redirect to ni_syscall.
+	 */
+	bge a7, t0, 1f
+	/*
+	 * Check if syscall is rejected by tracer or seccomp, i.e., a7 == -1.
+	 * If yes, we pretend it was executed.
+	 */
+	li t1, -1
+	beq a7, t1, ret_from_syscall_rejected
+	blt a7, t1, 1f
+	/* Call syscall */
 	la s0, sys_call_table
 	slli t0, a7, RISCV_LGPTR
 	add s0, s0, t0
@@ -238,6 +256,12 @@
 ret_from_syscall:
 	/* Set user a0 to kernel a0 */
 	REG_S a0, PT_A0(sp)
+	/*
+	 * We didn't execute the actual syscall.
+	 * Seccomp already set return value for the current task pt_regs.
+	 * (If it was configured with SECCOMP_RET_ERRNO/TRACE)
+	 */
+ret_from_syscall_rejected:
 	/* Trace syscalls, but only if requested by the user. */
 	REG_L t0, TASK_TI_FLAGS(tp)
 	andi t0, t0, _TIF_SYSCALL_WORK
@@ -387,6 +411,7 @@
 ENDPROC(__switch_to)
 
 	.section ".rodata"
+	.align LGREG
 	/* Exception vector table */
 ENTRY(excp_vect_table)
 	RISCV_PTR do_trap_insn_misaligned
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/kernel/ftrace.c
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/kernel/ftrace.c
@@ -88,6 +88,25 @@
 	return __ftrace_modify_call(rec->ip, addr, false);
 }
 
+
+/*
+ * This is called early on, and isn't wrapped by
+ * ftrace_arch_code_modify_{prepare,post_process}() and therefor doesn't hold
+ * text_mutex, which triggers a lockdep failure.  SMP isn't running so we could
+ * just directly poke the text, but it's simpler to just take the lock
+ * ourselves.
+ */
+int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec)
+{
+	int out;
+
+	ftrace_arch_code_modify_prepare();
+	out = ftrace_make_nop(mod, rec, MCOUNT_ADDR);
+	ftrace_arch_code_modify_post_process();
+
+	return out;
+}
+
 int ftrace_update_ftrace_func(ftrace_func_t func)
 {
 	int ret = __ftrace_modify_call((unsigned long)&ftrace_call,
@@ -142,7 +161,7 @@
 	 */
 	old = *parent;
 
-	if (function_graph_enter(old, self_addr, frame_pointer, parent))
+	if (!function_graph_enter(old, self_addr, frame_pointer, parent))
 		*parent = return_hooker;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/kernel/head.S
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/kernel/head.S
@@ -26,6 +26,10 @@
 	/* reserved */
 	.word 0
 	.balign 8
+#ifdef CONFIG_RISCV_M_MODE
+	/* Image load offset (0MB) from start of RAM for M-mode */
+	.dword 0
+#else
 #if __riscv_xlen == 64
 	/* Image load offset(2MB) from start of RAM */
 	.dword 0x200000
@@ -33,6 +37,7 @@
 	/* Image load offset(4MB) from start of RAM */
 	.dword 0x400000
 #endif
+#endif
 	/* Effective size of kernel image */
 	.dword _end - _start
 	.dword __HEAD_FLAGS
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/kernel/mcount.S
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/kernel/mcount.S
@@ -47,8 +47,8 @@
 
 ENTRY(ftrace_stub)
 #ifdef CONFIG_DYNAMIC_FTRACE
-       .global _mcount
-       .set    _mcount, ftrace_stub
+       .global MCOUNT_NAME
+       .set    MCOUNT_NAME, ftrace_stub
 #endif
 	ret
 ENDPROC(ftrace_stub)
@@ -78,7 +78,7 @@
 #endif
 
 #ifndef CONFIG_DYNAMIC_FTRACE
-ENTRY(_mcount)
+ENTRY(MCOUNT_NAME)
 	la	t4, ftrace_stub
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 	la	t0, ftrace_graph_return
@@ -124,6 +124,6 @@
 	jalr	t5
 	RESTORE_ABI_STATE
 	ret
-ENDPROC(_mcount)
+ENDPROC(MCOUNT_NAME)
 #endif
-EXPORT_SYMBOL(_mcount)
+EXPORT_SYMBOL(MCOUNT_NAME)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/kernel/module.c
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/kernel/module.c
@@ -8,6 +8,23 @@
 #include <linux/err.h>
 #include <linux/errno.h>
 #include <linux/moduleloader.h>
+#include <linux/vmalloc.h>
+#include <linux/sizes.h>
+#include <asm/pgtable.h>
+#include <asm/sections.h>
+
+/*
+ * The auipc+jalr instruction pair can reach any PC-relative offset
+ * in the range [-2^31 - 2^11, 2^31 - 2^11)
+ */
+static bool riscv_insn_valid_32bit_offset(ptrdiff_t val)
+{
+#ifdef CONFIG_32BIT
+	return true;
+#else
+	return (-(1L << 31) - (1L << 11)) <= val && val < ((1L << 31) - (1L << 11));
+#endif
+}
 
 static int apply_r_riscv_32_rela(struct module *me, u32 *location, Elf_Addr v)
 {
@@ -91,7 +108,7 @@
 	ptrdiff_t offset = (void *)v - (void *)location;
 	s32 hi20;
 
-	if (offset != (s32)offset) {
+	if (!riscv_insn_valid_32bit_offset(offset)) {
 		pr_err(
 		  "%s: target %016llx can not be addressed by the 32-bit offset from PC = %p\n",
 		  me->name, (long long)v, location);
@@ -193,10 +210,9 @@
 				       Elf_Addr v)
 {
 	ptrdiff_t offset = (void *)v - (void *)location;
-	s32 fill_v = offset;
 	u32 hi20, lo12;
 
-	if (offset != fill_v) {
+	if (!riscv_insn_valid_32bit_offset(offset)) {
 		/* Only emit the plt entry if offset over 32-bit range */
 		if (IS_ENABLED(CONFIG_MODULE_SECTIONS)) {
 			offset = module_emit_plt_entry(me, v);
@@ -220,10 +236,9 @@
 				   Elf_Addr v)
 {
 	ptrdiff_t offset = (void *)v - (void *)location;
-	s32 fill_v = offset;
 	u32 hi20, lo12;
 
-	if (offset != fill_v) {
+	if (!riscv_insn_valid_32bit_offset(offset)) {
 		pr_err(
 		  "%s: target %016llx can not be addressed by the 32-bit offset from PC = %p\n",
 		  me->name, (long long)v, location);
@@ -386,3 +401,15 @@
 
 	return 0;
 }
+
+#if defined(CONFIG_MMU) && defined(CONFIG_64BIT)
+#define VMALLOC_MODULE_START \
+	 max(PFN_ALIGN((unsigned long)&_end - SZ_2G), VMALLOC_START)
+void *module_alloc(unsigned long size)
+{
+	return __vmalloc_node_range(size, 1, VMALLOC_MODULE_START,
+				    VMALLOC_END, GFP_KERNEL,
+				    PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE,
+				    __builtin_return_address(0));
+}
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/kernel/module.lds
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/kernel/module.lds
@@ -2,7 +2,7 @@
 /* Copyright (C) 2017 Andes Technology Corporation */
 
 SECTIONS {
-	.plt (NOLOAD) : { BYTE(0) }
-	.got (NOLOAD) : { BYTE(0) }
-	.got.plt (NOLOAD) : { BYTE(0) }
+	.plt : { BYTE(0) }
+	.got : { BYTE(0) }
+	.got.plt : { BYTE(0) }
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/kernel/perf_callchain.c
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/kernel/perf_callchain.c
@@ -60,23 +60,24 @@
 void perf_callchain_user(struct perf_callchain_entry_ctx *entry,
 			 struct pt_regs *regs)
 {
+	struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs();
 	unsigned long fp = 0;
 
 	/* RISC-V does not support perf in guest mode. */
-	if (perf_guest_cbs && perf_guest_cbs->is_in_guest())
+	if (guest_cbs && guest_cbs->is_in_guest())
 		return;
 
 	fp = regs->s0;
 	perf_callchain_store(entry, regs->sepc);
 
 	fp = user_backtrace(entry, fp, regs->ra);
-	while (fp && !(fp & 0x3) && entry->nr < entry->max_stack)
+	while (fp && !(fp & 0x7) && entry->nr < entry->max_stack)
 		fp = user_backtrace(entry, fp, 0);
 }
 
 bool fill_callchain(unsigned long pc, void *entry)
 {
-	return perf_callchain_store(entry, pc);
+	return perf_callchain_store(entry, pc) == 0;
 }
 
 void notrace walk_stackframe(struct task_struct *task,
@@ -84,8 +85,10 @@
 void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
 			   struct pt_regs *regs)
 {
+	struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs();
+
 	/* RISC-V does not support perf in guest mode. */
-	if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
+	if (guest_cbs && guest_cbs->is_in_guest()) {
 		pr_warn("RISC-V does not support perf in guest mode!");
 		return;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/kernel/process.c
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/kernel/process.c
@@ -99,11 +99,13 @@
 	return 0;
 }
 
-int copy_thread(unsigned long clone_flags, unsigned long usp,
-	unsigned long arg, struct task_struct *p)
+int copy_thread_tls(unsigned long clone_flags, unsigned long usp,
+	unsigned long arg, struct task_struct *p, unsigned long tls)
 {
 	struct pt_regs *childregs = task_pt_regs(p);
 
+	memset(&p->thread.s, 0, sizeof(p->thread.s));
+
 	/* p->thread holds context to be restored by __switch_to() */
 	if (unlikely(p->flags & PF_KTHREAD)) {
 		/* Kernel thread */
@@ -120,7 +122,7 @@
 		if (usp) /* User fork */
 			childregs->sp = usp;
 		if (clone_flags & CLONE_SETTLS)
-			childregs->tp = childregs->a5;
+			childregs->tp = tls;
 		childregs->a0 = 0; /* Return value of fork() */
 		p->thread.ra = (unsigned long)ret_from_fork;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/kernel/ptrace.c
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/kernel/ptrace.c
@@ -154,6 +154,16 @@
 		if (tracehook_report_syscall_entry(regs))
 			syscall_set_nr(current, regs, -1);
 
+	/*
+	 * Do the secure computing after ptrace; failures should be fast.
+	 * If this fails we might have return value in a0 from seccomp
+	 * (via SECCOMP_RET_ERRNO/TRACE).
+	 */
+	if (secure_computing(NULL) == -1) {
+		syscall_set_nr(current, regs, -1);
+		return;
+	}
+
 #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
 	if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
 		trace_sys_enter(regs, syscall_get_nr(current, regs));
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/kernel/smp.c
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/kernel/smp.c
@@ -51,7 +51,7 @@
 			return i;
 
 	pr_err("Couldn't find cpu id for hartid [%d]\n", hartid);
-	return i;
+	return -ENOENT;
 }
 
 void riscv_cpuid_to_hartid_mask(const struct cpumask *in, struct cpumask *out)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/kernel/smpboot.c
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/kernel/smpboot.c
@@ -46,6 +46,8 @@
 {
 	int cpuid;
 
+	store_cpu_topology(smp_processor_id());
+
 	/* This covers non-smp usecase mandated by "nosmp" option */
 	if (max_cpus == 0)
 		return;
@@ -142,8 +144,8 @@
 	current->active_mm = mm;
 
 	trap_init();
+	store_cpu_topology(smp_processor_id());
 	notify_cpu_starting(smp_processor_id());
-	update_siblings_masks(smp_processor_id());
 	set_cpu_online(smp_processor_id(), 1);
 	/*
 	 * Remote TLB flushes are ignored while the CPU is offline, so emit
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/kernel/stacktrace.c
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/kernel/stacktrace.c
@@ -63,7 +63,7 @@
 
 #else /* !CONFIG_FRAME_POINTER */
 
-static void notrace walk_stackframe(struct task_struct *task,
+void notrace walk_stackframe(struct task_struct *task,
 	struct pt_regs *regs, bool (*fn)(unsigned long, void *), void *arg)
 {
 	unsigned long sp, pc;
@@ -89,7 +89,7 @@
 	while (!kstack_end(ksp)) {
 		if (__kernel_text_address(pc) && unlikely(fn(pc, arg)))
 			break;
-		pc = (*ksp++) - 0x4;
+		pc = READ_ONCE_NOCHECK(*ksp++) - 0x4;
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/kernel/sys_riscv.c
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/kernel/sys_riscv.c
@@ -8,6 +8,7 @@
 #include <linux/syscalls.h>
 #include <asm/unistd.h>
 #include <asm/cacheflush.h>
+#include <asm-generic/mman-common.h>
 
 static long riscv_sys_mmap(unsigned long addr, unsigned long len,
 			   unsigned long prot, unsigned long flags,
@@ -16,6 +17,7 @@
 {
 	if (unlikely(offset & (~PAGE_MASK >> page_shift_offset)))
 		return -EINVAL;
+
 	return ksys_mmap_pgoff(addr, len, prot, flags, fd,
 			       offset >> (PAGE_SHIFT - page_shift_offset));
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/kernel/time.c
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/kernel/time.c
@@ -4,6 +4,8 @@
  * Copyright (C) 2017 SiFive
  */
 
+#include <linux/of_clk.h>
+#include <linux/clockchips.h>
 #include <linux/clocksource.h>
 #include <linux/delay.h>
 #include <asm/sbi.h>
@@ -24,5 +26,9 @@
 	riscv_timebase = prop;
 
 	lpj_fine = riscv_timebase / HZ;
+
+	of_clk_init(NULL);
 	timer_probe();
+
+	tick_setup_hrtimer_broadcast();
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/kernel/traps.c
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/kernel/traps.c
@@ -15,6 +15,7 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/irq.h>
+#include <linux/kexec.h>
 
 #include <asm/processor.h>
 #include <asm/ptrace.h>
@@ -43,6 +44,9 @@
 
 	ret = notify_die(DIE_OOPS, str, regs, 0, regs->scause, SIGSEGV);
 
+	if (regs && kexec_should_crash(current))
+		crash_kexec(regs);
+
 	bust_spinlocks(0);
 	add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
 	spin_unlock_irq(&die_lock);
@@ -53,7 +57,7 @@
 	if (panic_on_oops)
 		panic("Fatal exception");
 	if (ret != NOTIFY_STOP)
-		do_exit(SIGSEGV);
+		make_task_dead(SIGSEGV);
 }
 
 void do_trap(struct pt_regs *regs, int signo, int code, unsigned long addr)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/kernel/vdso/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/kernel/vdso/Makefile
@@ -20,6 +20,9 @@
 
 obj-y += vdso.o vdso-syms.o
 CPPFLAGS_vdso.lds += -P -C -U$(ARCH)
+ifneq ($(filter vgettimeofday, $(vdso-syms)),)
+CPPFLAGS_vdso.lds += -DHAS_VGETTIMEOFDAY
+endif
 
 # Disable gcov profiling for VDSO code
 GCOV_PROFILE := n
@@ -33,15 +36,15 @@
 	$(call if_changed,vdsold)
 
 # We also create a special relocatable object that should mirror the symbol
-# table and layout of the linked DSO.  With ld -R we can then refer to
-# these symbols in the kernel code rather than hand-coded addresses.
+# table and layout of the linked DSO. With ld --just-symbols we can then
+# refer to these symbols in the kernel code rather than hand-coded addresses.
 
 SYSCFLAGS_vdso.so.dbg = -shared -s -Wl,-soname=linux-vdso.so.1 \
 	-Wl,--build-id -Wl,--hash-style=both
 $(obj)/vdso-dummy.o: $(src)/vdso.lds $(obj)/rt_sigreturn.o FORCE
 	$(call if_changed,vdsold)
 
-LDFLAGS_vdso-syms.o := -r -R
+LDFLAGS_vdso-syms.o := -r --just-symbols
 $(obj)/vdso-syms.o: $(obj)/vdso-dummy.o FORCE
 	$(call if_changed,ld)
 
@@ -58,7 +61,8 @@
       cmd_vdsold = $(CC) $(KBUILD_CFLAGS) $(call cc-option, -no-pie) -nostdlib -nostartfiles $(SYSCFLAGS_$(@F)) \
                            -Wl,-T,$(filter-out FORCE,$^) -o $@.tmp && \
                    $(CROSS_COMPILE)objcopy \
-                           $(patsubst %, -G __vdso_%, $(vdso-syms)) $@.tmp $@
+                           $(patsubst %, -G __vdso_%, $(vdso-syms)) $@.tmp $@ && \
+                   rm $@.tmp
 
 # install commands for the unstripped file
 quiet_cmd_vdso_install = INSTALL $@
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/kernel/vdso/vdso.lds.S
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/kernel/vdso/vdso.lds.S
@@ -62,9 +62,11 @@
 	LINUX_4.15 {
 	global:
 		__vdso_rt_sigreturn;
+#ifdef HAS_VGETTIMEOFDAY
 		__vdso_gettimeofday;
 		__vdso_clock_gettime;
 		__vdso_clock_getres;
+#endif
 		__vdso_getcpu;
 		__vdso_flush_icache;
 	local: *;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/lib/tishift.S
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/lib/tishift.S
@@ -4,34 +4,73 @@
  */
 
 #include <linux/linkage.h>
+#include <asm-generic/export.h>
 
-ENTRY(__lshrti3)
+SYM_FUNC_START(__lshrti3)
 	beqz	a2, .L1
 	li	a5,64
 	sub	a5,a5,a2
-	addi	sp,sp,-16
 	sext.w	a4,a5
 	blez	a5, .L2
 	sext.w	a2,a2
-	sll	a4,a1,a4
 	srl	a0,a0,a2
-	srl	a1,a1,a2
+	sll	a4,a1,a4
+	srl	a2,a1,a2
 	or	a0,a0,a4
-	sd	a1,8(sp)
-	sd	a0,0(sp)
-	ld	a0,0(sp)
-	ld	a1,8(sp)
-	addi	sp,sp,16
-	ret
+	mv	a1,a2
 .L1:
 	ret
 .L2:
-	negw	a4,a4
-	srl	a1,a1,a4
-	sd	a1,0(sp)
-	sd	zero,8(sp)
-	ld	a0,0(sp)
-	ld	a1,8(sp)
-	addi	sp,sp,16
+	negw	a0,a4
+	li	a2,0
+	srl	a0,a1,a0
+	mv	a1,a2
+	ret
+SYM_FUNC_END(__lshrti3)
+EXPORT_SYMBOL(__lshrti3)
+
+SYM_FUNC_START(__ashrti3)
+	beqz	a2, .L3
+	li	a5,64
+	sub	a5,a5,a2
+	sext.w	a4,a5
+	blez	a5, .L4
+	sext.w	a2,a2
+	srl	a0,a0,a2
+	sll	a4,a1,a4
+	sra	a2,a1,a2
+	or	a0,a0,a4
+	mv	a1,a2
+.L3:
+	ret
+.L4:
+	negw	a0,a4
+	srai	a2,a1,0x3f
+	sra	a0,a1,a0
+	mv	a1,a2
+	ret
+SYM_FUNC_END(__ashrti3)
+EXPORT_SYMBOL(__ashrti3)
+
+SYM_FUNC_START(__ashlti3)
+	beqz	a2, .L5
+	li	a5,64
+	sub	a5,a5,a2
+	sext.w	a4,a5
+	blez	a5, .L6
+	sext.w	a2,a2
+	sll	a1,a1,a2
+	srl	a4,a0,a4
+	sll	a2,a0,a2
+	or	a1,a1,a4
+	mv	a0,a2
+.L5:
+	ret
+.L6:
+	negw	a1,a4
+	li	a2,0
+	sll	a1,a0,a1
+	mv	a0,a2
 	ret
-ENDPROC(__lshrti3)
+SYM_FUNC_END(__ashlti3)
+EXPORT_SYMBOL(__ashlti3)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/mm/cacheflush.c
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/mm/cacheflush.c
@@ -14,6 +14,7 @@
 {
 	sbi_remote_fence_i(NULL);
 }
+EXPORT_SYMBOL(flush_icache_all);
 
 /*
  * Performs an icache flush for the given MM context.  RISC-V has no direct
@@ -70,6 +71,8 @@
 {
 	struct page *page = pte_page(pte);
 
-	if (!test_and_set_bit(PG_dcache_clean, &page->flags))
+	if (!test_bit(PG_dcache_clean, &page->flags)) {
 		flush_icache_all();
+		set_bit(PG_dcache_clean, &page->flags);
+	}
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/mm/fault.c
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/mm/fault.c
@@ -189,7 +189,7 @@
 		(addr < PAGE_SIZE) ? "NULL pointer dereference" :
 		"paging request", addr);
 	die(regs, "Oops");
-	do_exit(SIGKILL);
+	make_task_dead(SIGKILL);
 
 	/*
 	 * We ran out of memory, call the OOM killer, and return the userspace
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/mm/init.c
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/mm/init.c
@@ -98,7 +98,7 @@
 	for_each_memblock(memory, reg) {
 		phys_addr_t end = reg->base + reg->size;
 
-		if (reg->base <= vmlinux_end && vmlinux_end <= end) {
+		if (reg->base <= vmlinux_start && vmlinux_end <= end) {
 			mem_size = min(reg->size, (phys_addr_t)-PAGE_OFFSET);
 
 			/*
@@ -115,8 +115,9 @@
 	/* Reserve from the start of the kernel to the end of the kernel */
 	memblock_reserve(vmlinux_start, vmlinux_end - vmlinux_start);
 
-	set_max_mapnr(PFN_DOWN(mem_size));
-	max_low_pfn = PFN_DOWN(memblock_end_of_DRAM());
+	max_pfn = PFN_DOWN(memblock_end_of_DRAM());
+	max_low_pfn = max_pfn;
+	set_max_mapnr(max_low_pfn);
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	setup_initrd();
@@ -166,12 +167,11 @@
 
 	ptep = &fixmap_pte[pte_index(addr)];
 
-	if (pgprot_val(prot)) {
+	if (pgprot_val(prot))
 		set_pte(ptep, pfn_pte(phys >> PAGE_SHIFT, prot));
-	} else {
+	else
 		pte_clear(&init_mm, addr, ptep);
-		local_flush_tlb_page(addr);
-	}
+	local_flush_tlb_page(addr);
 }
 
 static pte_t *__init get_pte_virt(phys_addr_t pa)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/mm/tlbflush.c
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/mm/tlbflush.c
@@ -2,6 +2,7 @@
 
 #include <linux/mm.h>
 #include <linux/smp.h>
+#include <linux/sched.h>
 #include <asm/sbi.h>
 
 void flush_tlb_all(void)
@@ -9,13 +10,33 @@
 	sbi_remote_sfence_vma(NULL, 0, -1);
 }
 
+/*
+ * This function must not be called with cmask being null.
+ * Kernel may panic if cmask is NULL.
+ */
 static void __sbi_tlb_flush_range(struct cpumask *cmask, unsigned long start,
 				  unsigned long size)
 {
 	struct cpumask hmask;
+	unsigned int cpuid;
 
-	riscv_cpuid_to_hartid_mask(cmask, &hmask);
-	sbi_remote_sfence_vma(hmask.bits, start, size);
+	if (cpumask_empty(cmask))
+		return;
+
+	cpuid = get_cpu();
+
+	if (cpumask_any_but(cmask, cpuid) >= nr_cpu_ids) {
+		/* local cpu is the only cpu present in cpumask */
+		if (size <= PAGE_SIZE)
+			local_flush_tlb_page(start);
+		else
+			local_flush_tlb_all();
+	} else {
+		riscv_cpuid_to_hartid_mask(cmask, &hmask);
+		sbi_remote_sfence_vma(cpumask_bits(&hmask), start, size);
+	}
+
+	put_cpu();
 }
 
 void flush_tlb_mm(struct mm_struct *mm)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/riscv/net/bpf_jit_comp.c
+++ linux-xilinx-zynqmp-5.4.0/arch/riscv/net/bpf_jit_comp.c
@@ -120,6 +120,11 @@
 	return false;
 }
 
+static void mark_fp(struct rv_jit_context *ctx)
+{
+	__set_bit(RV_CTX_F_SEEN_S5, &ctx->flags);
+}
+
 static void mark_call(struct rv_jit_context *ctx)
 {
 	__set_bit(RV_CTX_F_SEEN_CALL, &ctx->flags);
@@ -596,7 +601,8 @@
 
 	emit(rv_addi(RV_REG_SP, RV_REG_SP, stack_adjust), ctx);
 	/* Set return value. */
-	emit(rv_addi(RV_REG_A0, RV_REG_A5, 0), ctx);
+	if (reg == RV_REG_RA)
+		emit(rv_addi(RV_REG_A0, RV_REG_A5, 0), ctx);
 	emit(rv_jalr(RV_REG_ZERO, reg, 0), ctx);
 }
 
@@ -631,14 +637,14 @@
 		return -1;
 	emit(rv_bgeu(RV_REG_A2, RV_REG_T1, off >> 1), ctx);
 
-	/* if (--TCC < 0)
+	/* if (TCC-- < 0)
 	 *     goto out;
 	 */
 	emit(rv_addi(RV_REG_T1, tcc, -1), ctx);
 	off = (tc_ninsn - (ctx->ninsns - start_insn)) << 2;
 	if (is_13b_check(off, insn))
 		return -1;
-	emit(rv_blt(RV_REG_T1, RV_REG_ZERO, off >> 1), ctx);
+	emit(rv_blt(tcc, RV_REG_ZERO, off >> 1), ctx);
 
 	/* prog = array->ptrs[index];
 	 * if (!prog)
@@ -1307,6 +1313,10 @@
 		emit(rv_ld(rd, 0, RV_REG_T1), ctx);
 		break;
 
+	/* speculation barrier */
+	case BPF_ST | BPF_NOSPEC:
+		break;
+
 	/* ST: *(size *)(dst + off) = imm */
 	case BPF_ST | BPF_MEM | BPF_B:
 		emit_imm(RV_REG_T1, imm, ctx);
@@ -1426,6 +1436,10 @@
 {
 	int stack_adjust = 0, store_offset, bpf_stack_adjust;
 
+	bpf_stack_adjust = round_up(ctx->prog->aux->stack_depth, 16);
+	if (bpf_stack_adjust)
+		mark_fp(ctx);
+
 	if (seen_reg(RV_REG_RA, ctx))
 		stack_adjust += 8;
 	stack_adjust += 8; /* RV_REG_FP */
@@ -1443,7 +1457,6 @@
 		stack_adjust += 8;
 
 	stack_adjust = round_up(stack_adjust, 16);
-	bpf_stack_adjust = round_up(ctx->prog->aux->stack_depth, 16);
 	stack_adjust += bpf_stack_adjust;
 
 	store_offset = stack_adjust - 8;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/Kconfig
@@ -155,6 +155,7 @@
 	select HAVE_KERNEL_UNCOMPRESSED
 	select HAVE_KERNEL_XZ
 	select HAVE_KPROBES
+	select HAVE_KPROBES_ON_FTRACE
 	select HAVE_KRETPROBES
 	select HAVE_KVM
 	select HAVE_LIVEPATCH
@@ -541,7 +542,6 @@
 config KEXEC_FILE
 	bool "kexec file based system call"
 	select KEXEC_CORE
-	select BUILD_BIN2C
 	depends on CRYPTO
 	depends on CRYPTO_SHA256
 	depends on CRYPTO_SHA256_S390
@@ -920,7 +920,7 @@
 config APPLDATA_BASE
 	def_bool n
 	prompt "Linux - VM Monitor Stream, base infrastructure"
-	depends on PROC_FS
+	depends on PROC_SYSCTL
 	help
 	  This provides a kernel interface for creating and updating z/VM APPLDATA
 	  monitor records. The monitor records are updated at certain time
@@ -1006,3 +1006,11 @@
 	  the KVM hypervisor.
 
 endmenu
+
+config KMSG_IDS
+	def_bool y
+	prompt "Kernel message numbers"
+	help
+	  Select this option if you want to include a message number to the
+	  prefix for kernel messages issued by the s390 architecture and
+	  driver code. See "Documentation/s390/kmsg.txt" for more details.
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/Makefile
@@ -31,6 +31,16 @@
 KBUILD_CFLAGS_DECOMPRESSOR += $(call cc-disable-warning, address-of-packed-member)
 KBUILD_CFLAGS_DECOMPRESSOR += $(if $(CONFIG_DEBUG_INFO),-g)
 KBUILD_CFLAGS_DECOMPRESSOR += $(if $(CONFIG_DEBUG_INFO_DWARF4), $(call cc-option, -gdwarf-4,))
+
+ifdef CONFIG_CC_IS_GCC
+	ifeq ($(call cc-ifversion, -ge, 1200, y), y)
+		ifeq ($(call cc-ifversion, -lt, 1300, y), y)
+			KBUILD_CFLAGS += $(call cc-disable-warning, array-bounds)
+			KBUILD_CFLAGS_DECOMPRESSOR += $(call cc-disable-warning, array-bounds)
+		endif
+	endif
+endif
+
 UTS_MACHINE	:= s390x
 STACK_SIZE	:= $(if $(CONFIG_KASAN),65536,16384)
 CHECKFLAGS	+= -D__s390__ -D__s390x__
@@ -69,7 +79,7 @@
 #
 cflags-$(CONFIG_FRAME_POINTER) += -fno-optimize-sibling-calls
 
-ifeq ($(call cc-option-yn,-mpacked-stack),y)
+ifeq ($(call cc-option-yn,-mpacked-stack -mbackchain -msoft-float),y)
 cflags-$(CONFIG_PACK_STACK)  += -mpacked-stack -D__PACK_STACK
 aflags-$(CONFIG_PACK_STACK)  += -D__PACK_STACK
 endif
@@ -146,7 +156,7 @@
 #KBUILD_IMAGE is necessary for packaging targets like rpm-pkg, deb-pkg...
 KBUILD_IMAGE	:= $(boot)/bzImage
 
-install: vmlinux
+install:
 	$(Q)$(MAKE) $(build)=$(boot) $@
 
 bzImage: vmlinux
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/appldata/appldata_os.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/appldata/appldata_os.c
@@ -75,7 +75,7 @@
 				   (waiting for I/O)               */
 
 	/* per cpu data */
-	struct appldata_os_per_cpu os_cpu[0];
+	struct appldata_os_per_cpu os_cpu[];
 } __attribute__((packed));
 
 static struct appldata_os_data *appldata_os_data;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/boot/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/boot/Makefile
@@ -37,7 +37,7 @@
 obj-y	:= head.o als.o startup.o mem_detect.o ipl_parm.o ipl_report.o
 obj-y	+= string.o ebcdic.o sclp_early_core.o mem.o ipl_vmparm.o cmdline.o
 obj-y	+= version.o pgm_check_info.o ctype.o text_dma.o
-obj-$(CONFIG_PROTECTED_VIRTUALIZATION_GUEST)	+= uv.o
+obj-$(findstring y, $(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) $(CONFIG_PGSTE))	+= uv.o
 obj-$(CONFIG_RELOCATABLE)	+= machine_kexec_reloc.o
 obj-$(CONFIG_RANDOMIZE_BASE)	+= kaslr.o
 targets	:= bzImage startup.a section_cmp.boot.data section_cmp.boot.preserved.data $(obj-y)
@@ -70,7 +70,7 @@
 $(obj)/startup.a: $(OBJECTS) FORCE
 	$(call if_changed,ar)
 
-install: $(CONFIGURE) $(obj)/bzImage
+install:
 	sh -x  $(srctree)/$(obj)/install.sh $(KERNELRELEASE) $(obj)/bzImage \
 	      System.map "$(INSTALL_PATH)"
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/boot/compressed/decompressor.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/boot/compressed/decompressor.c
@@ -30,13 +30,13 @@
 extern unsigned char _compressed_end[];
 
 #ifdef CONFIG_HAVE_KERNEL_BZIP2
-#define HEAP_SIZE	0x400000
+#define BOOT_HEAP_SIZE	0x400000
 #else
-#define HEAP_SIZE	0x10000
+#define BOOT_HEAP_SIZE	0x10000
 #endif
 
 static unsigned long free_mem_ptr = (unsigned long) _end;
-static unsigned long free_mem_end_ptr = (unsigned long) _end + HEAP_SIZE;
+static unsigned long free_mem_end_ptr = (unsigned long) _end + BOOT_HEAP_SIZE;
 
 #ifdef CONFIG_KERNEL_GZIP
 #include "../../../../lib/decompress_inflate.c"
@@ -62,7 +62,7 @@
 #include "../../../../lib/decompress_unxz.c"
 #endif
 
-#define decompress_offset ALIGN((unsigned long)_end + HEAP_SIZE, PAGE_SIZE)
+#define decompress_offset ALIGN((unsigned long)_end + BOOT_HEAP_SIZE, PAGE_SIZE)
 
 unsigned long mem_safe_offset(void)
 {
@@ -80,6 +80,6 @@
 	void *output = (void *)decompress_offset;
 
 	__decompress(_compressed_start, _compressed_end - _compressed_start,
-		     NULL, NULL, output, 0, NULL, error);
+		     NULL, NULL, output, vmlinux.image_size, NULL, error);
 	return output;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/boot/compressed/vmlinux.lds.S
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/boot/compressed/vmlinux.lds.S
@@ -78,10 +78,19 @@
 		_compressed_start = .;
 		*(.vmlinux.bin.compressed)
 		_compressed_end = .;
-		FILL(0xff);
-		. = ALIGN(4096);
 	}
-	. = ALIGN(256);
+
+#define SB_TRAILER_SIZE 32
+	/* Trailer needed for Secure Boot */
+	. += SB_TRAILER_SIZE; /* make sure .sb.trailer does not overwrite the previous section */
+	. = ALIGN(4096) - SB_TRAILER_SIZE;
+	.sb.trailer : {
+		QUAD(0)
+		QUAD(0)
+		QUAD(0)
+		QUAD(0x000000207a49504c)
+	}
+
 	.bss : {
 		_bss = . ;
 		*(.bss)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/boot/head.S
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/boot/head.S
@@ -360,22 +360,23 @@
 # the save area and does disabled wait with a faulty address.
 #
 ENTRY(startup_pgm_check_handler)
-	stmg	%r0,%r15,__LC_SAVE_AREA_SYNC
-	la	%r1,4095
-	stctg	%c0,%c15,__LC_CREGS_SAVE_AREA-4095(%r1)
-	mvc	__LC_GPREGS_SAVE_AREA-4095(128,%r1),__LC_SAVE_AREA_SYNC
-	mvc	__LC_PSW_SAVE_AREA-4095(16,%r1),__LC_PGM_OLD_PSW
+	stmg	%r8,%r15,__LC_SAVE_AREA_SYNC
+	la	%r8,4095
+	stctg	%c0,%c15,__LC_CREGS_SAVE_AREA-4095(%r8)
+	stmg	%r0,%r7,__LC_GPREGS_SAVE_AREA-4095(%r8)
+	mvc	__LC_GPREGS_SAVE_AREA-4095+64(64,%r8),__LC_SAVE_AREA_SYNC
+	mvc	__LC_PSW_SAVE_AREA-4095(16,%r8),__LC_PGM_OLD_PSW
 	mvc	__LC_RETURN_PSW(16),__LC_PGM_OLD_PSW
 	ni	__LC_RETURN_PSW,0xfc	# remove IO and EX bits
 	ni	__LC_RETURN_PSW+1,0xfb	# remove MCHK bit
 	oi	__LC_RETURN_PSW+1,0x2	# set wait state bit
-	larl	%r2,.Lold_psw_disabled_wait
-	stg	%r2,__LC_PGM_NEW_PSW+8
-	l	%r15,.Ldump_info_stack-.Lold_psw_disabled_wait(%r2)
+	larl	%r9,.Lold_psw_disabled_wait
+	stg	%r9,__LC_PGM_NEW_PSW+8
+	l	%r15,.Ldump_info_stack-.Lold_psw_disabled_wait(%r9)
 	brasl	%r14,print_pgm_check_info
 .Lold_psw_disabled_wait:
-	la	%r1,4095
-	lmg	%r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)
+	la	%r8,4095
+	lmg	%r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r8)
 	lpswe	__LC_RETURN_PSW		# disabled wait
 .Ldump_info_stack:
 	.long	0x5000 + PAGE_SIZE - STACK_FRAME_OVERHEAD
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/boot/ipl_parm.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/boot/ipl_parm.c
@@ -14,6 +14,7 @@
 char __bootdata(early_command_line)[COMMAND_LINE_SIZE];
 struct ipl_parameter_block __bootdata_preserved(ipl_block);
 int __bootdata_preserved(ipl_block_valid);
+unsigned int __bootdata_preserved(zlib_dfltcc_support) = ZLIB_DFLTCC_FULL;
 
 unsigned long __bootdata(vmalloc_size) = VMALLOC_DEFAULT_SIZE;
 unsigned long __bootdata(memory_end);
@@ -27,22 +28,25 @@
 	register unsigned long _addr asm("0") = (unsigned long)addr;
 	register unsigned long _rc asm("1") = 0;
 	unsigned long reg1, reg2;
-	psw_t old = S390_lowcore.program_new_psw;
+	psw_t old;
 
 	asm volatile(
+		"	mvc	0(16,%[psw_old]),0(%[psw_pgm])\n"
 		"	epsw	%0,%1\n"
-		"	st	%0,%[psw_pgm]\n"
-		"	st	%1,%[psw_pgm]+4\n"
+		"	st	%0,0(%[psw_pgm])\n"
+		"	st	%1,4(%[psw_pgm])\n"
 		"	larl	%0,1f\n"
-		"	stg	%0,%[psw_pgm]+8\n"
+		"	stg	%0,8(%[psw_pgm])\n"
 		"	diag	%[addr],%[subcode],0x308\n"
-		"1:	nopr	%%r7\n"
+		"1:	mvc	0(16,%[psw_pgm]),0(%[psw_old])\n"
 		: "=&d" (reg1), "=&a" (reg2),
-		  [psw_pgm] "=Q" (S390_lowcore.program_new_psw),
+		  "+Q" (S390_lowcore.program_new_psw),
+		  "=Q" (old),
 		  [addr] "+d" (_addr), "+d" (_rc)
-		: [subcode] "d" (subcode)
+		: [subcode] "d" (subcode),
+		  [psw_old] "a" (&old),
+		  [psw_pgm] "a" (&S390_lowcore.program_new_psw)
 		: "cc", "memory");
-	S390_lowcore.program_new_psw = old;
 	return _rc;
 }
 
@@ -69,30 +73,44 @@
 static size_t ipl_block_get_ascii_scpdata(char *dest, size_t size,
 					  const struct ipl_parameter_block *ipb)
 {
-	size_t count;
-	size_t i;
+	const __u8 *scp_data;
+	__u32 scp_data_len;
 	int has_lowercase;
+	size_t count = 0;
+	size_t i;
+
+	switch (ipb->pb0_hdr.pbt) {
+	case IPL_PBT_FCP:
+		scp_data_len = ipb->fcp.scp_data_len;
+		scp_data = ipb->fcp.scp_data;
+		break;
+	case IPL_PBT_NVME:
+		scp_data_len = ipb->nvme.scp_data_len;
+		scp_data = ipb->nvme.scp_data;
+		break;
+	default:
+		goto out;
+	}
 
-	count = min(size - 1, scpdata_length(ipb->fcp.scp_data,
-					     ipb->fcp.scp_data_len));
+	count = min(size - 1, scpdata_length(scp_data, scp_data_len));
 	if (!count)
 		goto out;
 
 	has_lowercase = 0;
 	for (i = 0; i < count; i++) {
-		if (!isascii(ipb->fcp.scp_data[i])) {
+		if (!isascii(scp_data[i])) {
 			count = 0;
 			goto out;
 		}
-		if (!has_lowercase && islower(ipb->fcp.scp_data[i]))
+		if (!has_lowercase && islower(scp_data[i]))
 			has_lowercase = 1;
 	}
 
 	if (has_lowercase)
-		memcpy(dest, ipb->fcp.scp_data, count);
+		memcpy(dest, scp_data, count);
 	else
 		for (i = 0; i < count; i++)
-			dest[i] = tolower(ipb->fcp.scp_data[i]);
+			dest[i] = tolower(scp_data[i]);
 out:
 	dest[count] = '\0';
 	return count;
@@ -114,6 +132,7 @@
 			parm, COMMAND_LINE_SIZE - len - 1, &ipl_block);
 		break;
 	case IPL_PBT_FCP:
+	case IPL_PBT_NVME:
 		rc = ipl_block_get_ascii_scpdata(
 			parm, COMMAND_LINE_SIZE - len - 1, &ipl_block);
 		break;
@@ -229,6 +248,19 @@
 		if (!strcmp(param, "vmalloc") && val)
 			vmalloc_size = round_up(memparse(val, NULL), PAGE_SIZE);
 
+		if (!strcmp(param, "dfltcc")) {
+			if (!strcmp(val, "off"))
+				zlib_dfltcc_support = ZLIB_DFLTCC_DISABLED;
+			else if (!strcmp(val, "on"))
+				zlib_dfltcc_support = ZLIB_DFLTCC_FULL;
+			else if (!strcmp(val, "def_only"))
+				zlib_dfltcc_support = ZLIB_DFLTCC_DEFLATE_ONLY;
+			else if (!strcmp(val, "inf_only"))
+				zlib_dfltcc_support = ZLIB_DFLTCC_INFLATE_ONLY;
+			else if (!strcmp(val, "always"))
+				zlib_dfltcc_support = ZLIB_DFLTCC_FULL_DEBUG;
+		}
+
 		if (!strcmp(param, "noexec")) {
 			rc = kstrtobool(val, &enabled);
 			if (!rc && !enabled)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/boot/ipl_report.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/boot/ipl_report.c
@@ -57,11 +57,19 @@
 	if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && INITRD_START && INITRD_SIZE &&
 	    intersects(INITRD_START, INITRD_SIZE, safe_addr, size))
 		safe_addr = INITRD_START + INITRD_SIZE;
+	if (intersects(safe_addr, size, (unsigned long)comps, comps->len)) {
+		safe_addr = (unsigned long)comps + comps->len;
+		goto repeat;
+	}
 	for_each_rb_entry(comp, comps)
 		if (intersects(safe_addr, size, comp->addr, comp->len)) {
 			safe_addr = comp->addr + comp->len;
 			goto repeat;
 		}
+	if (intersects(safe_addr, size, (unsigned long)certs, certs->len)) {
+		safe_addr = (unsigned long)certs + certs->len;
+		goto repeat;
+	}
 	for_each_rb_entry(cert, certs)
 		if (intersects(safe_addr, size, cert->addr, cert->len)) {
 			safe_addr = cert->addr + cert->len;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/boot/kaslr.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/boot/kaslr.c
@@ -75,7 +75,7 @@
 		*(unsigned long *) prng.parm_block ^= seed;
 		for (i = 0; i < 16; i++) {
 			cpacf_kmc(CPACF_KMC_PRNG, prng.parm_block,
-				  (char *) entropy, (char *) entropy,
+				  (u8 *) entropy, (u8 *) entropy,
 				  sizeof(entropy));
 			memcpy(prng.parm_block, entropy, sizeof(entropy));
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/boot/mem_detect.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/boot/mem_detect.c
@@ -70,24 +70,27 @@
 	register unsigned long _ry asm("4") = 0x10; /* storage configuration */
 	int rc = -1;				    /* fail */
 	unsigned long reg1, reg2;
-	psw_t old = S390_lowcore.program_new_psw;
+	psw_t old;
 
 	asm volatile(
+		"	mvc	0(16,%[psw_old]),0(%[psw_pgm])\n"
 		"	epsw	%0,%1\n"
-		"	st	%0,%[psw_pgm]\n"
-		"	st	%1,%[psw_pgm]+4\n"
+		"	st	%0,0(%[psw_pgm])\n"
+		"	st	%1,4(%[psw_pgm])\n"
 		"	larl	%0,1f\n"
-		"	stg	%0,%[psw_pgm]+8\n"
+		"	stg	%0,8(%[psw_pgm])\n"
 		"	diag	%[rx],%[ry],0x260\n"
 		"	ipm	%[rc]\n"
 		"	srl	%[rc],28\n"
-		"1:\n"
+		"1:	mvc	0(16,%[psw_pgm]),0(%[psw_old])\n"
 		: "=&d" (reg1), "=&a" (reg2),
-		  [psw_pgm] "=Q" (S390_lowcore.program_new_psw),
+		  "+Q" (S390_lowcore.program_new_psw),
+		  "=Q" (old),
 		  [rc] "+&d" (rc), [ry] "+d" (_ry)
-		: [rx] "d" (_rx1), "d" (_rx2)
+		: [rx] "d" (_rx1), "d" (_rx2),
+		  [psw_old] "a" (&old),
+		  [psw_pgm] "a" (&S390_lowcore.program_new_psw)
 		: "cc", "memory");
-	S390_lowcore.program_new_psw = old;
 	return rc == 0 ? _ry : -1;
 }
 
@@ -112,24 +115,30 @@
 
 static int tprot(unsigned long addr)
 {
-	unsigned long pgm_addr;
+	unsigned long reg1, reg2;
 	int rc = -EFAULT;
-	psw_t old = S390_lowcore.program_new_psw;
+	psw_t old;
 
-	S390_lowcore.program_new_psw.mask = __extract_psw();
 	asm volatile(
-		"	larl	%[pgm_addr],1f\n"
-		"	stg	%[pgm_addr],%[psw_pgm_addr]\n"
+		"	mvc	0(16,%[psw_old]),0(%[psw_pgm])\n"
+		"	epsw	%[reg1],%[reg2]\n"
+		"	st	%[reg1],0(%[psw_pgm])\n"
+		"	st	%[reg2],4(%[psw_pgm])\n"
+		"	larl	%[reg1],1f\n"
+		"	stg	%[reg1],8(%[psw_pgm])\n"
 		"	tprot	0(%[addr]),0\n"
 		"	ipm	%[rc]\n"
 		"	srl	%[rc],28\n"
-		"1:\n"
-		: [pgm_addr] "=&d"(pgm_addr),
-		  [psw_pgm_addr] "=Q"(S390_lowcore.program_new_psw.addr),
-		  [rc] "+&d"(rc)
-		: [addr] "a"(addr)
+		"1:	mvc	0(16,%[psw_pgm]),0(%[psw_old])\n"
+		: [reg1] "=&d" (reg1),
+		  [reg2] "=&a" (reg2),
+		  [rc] "+&d" (rc),
+		  "=Q" (S390_lowcore.program_new_psw.addr),
+		  "=Q" (old)
+		: [psw_old] "a" (&old),
+		  [psw_pgm] "a" (&S390_lowcore.program_new_psw),
+		  [addr] "a" (addr)
 		: "cc", "memory");
-	S390_lowcore.program_new_psw = old;
 	return rc;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/boot/startup.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/boot/startup.c
@@ -170,6 +170,11 @@
 		handle_relocs(__kaslr_offset);
 
 	if (__kaslr_offset) {
+		/*
+		 * Save KASLR offset for early dumps, before vmcore_info is set.
+		 * Mark as uneven to distinguish from real vmcore_info pointer.
+		 */
+		S390_lowcore.vmcore_info = __kaslr_offset | 0x1UL;
 		/* Clear non-relocated kernel */
 		if (IS_ENABLED(CONFIG_KERNEL_UNCOMPRESSED))
 			memset(img, 0, vmlinux.image_size);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/boot/text_dma.S
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/boot/text_dma.S
@@ -9,16 +9,6 @@
 #include <asm/errno.h>
 #include <asm/sigp.h>
 
-#ifdef CC_USING_EXPOLINE
-	.pushsection .dma.text.__s390_indirect_jump_r14,"axG"
-__dma__s390_indirect_jump_r14:
-	larl	%r1,0f
-	ex	0,0(%r1)
-	j	.
-0:	br	%r14
-	.popsection
-#endif
-
 	.section .dma.text,"ax"
 /*
  * Simplified version of expoline thunk. The normal thunks can not be used here,
@@ -27,11 +17,10 @@
  * affects a few functions that are not performance-relevant.
  */
 	.macro BR_EX_DMA_r14
-#ifdef CC_USING_EXPOLINE
-	jg	__dma__s390_indirect_jump_r14
-#else
-	br	%r14
-#endif
+	larl	%r1,0f
+	ex	0,0(%r1)
+	j	.
+0:	br	%r14
 	.endm
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/boot/uv.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/boot/uv.c
@@ -3,7 +3,13 @@
 #include <asm/facility.h>
 #include <asm/sections.h>
 
+/* will be used in arch/s390/kernel/uv.c */
+#ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST
 int __bootdata_preserved(prot_virt_guest);
+#endif
+#if IS_ENABLED(CONFIG_KVM)
+struct uv_info __bootdata_preserved(uv_info);
+#endif
 
 void uv_query_info(void)
 {
@@ -15,10 +21,25 @@
 	if (!test_facility(158))
 		return;
 
-	if (uv_call(0, (uint64_t)&uvcb))
+	/* rc==0x100 means that there is additional data we do not process */
+	if (uv_call(0, (uint64_t)&uvcb) && uvcb.header.rc != 0x100)
 		return;
 
+	if (IS_ENABLED(CONFIG_KVM)) {
+		memcpy(uv_info.inst_calls_list, uvcb.inst_calls_list, sizeof(uv_info.inst_calls_list));
+		uv_info.uv_base_stor_len = uvcb.uv_base_stor_len;
+		uv_info.guest_base_stor_len = uvcb.conf_base_phys_stor_len;
+		uv_info.guest_virt_base_stor_len = uvcb.conf_base_virt_stor_len;
+		uv_info.guest_virt_var_stor_len = uvcb.conf_virt_var_stor_len;
+		uv_info.guest_cpu_stor_len = uvcb.cpu_stor_len;
+		uv_info.max_sec_stor_addr = ALIGN(uvcb.max_guest_stor_addr, PAGE_SIZE);
+		uv_info.max_num_sec_conf = uvcb.max_num_sec_conf;
+		uv_info.max_guest_cpus = uvcb.max_guest_cpus;
+	}
+
+#ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST
 	if (test_bit_inv(BIT_UVC_CMD_SET_SHARED_ACCESS, (unsigned long *)uvcb.inst_calls_list) &&
 	    test_bit_inv(BIT_UVC_CMD_REMOVE_SHARED_ACCESS, (unsigned long *)uvcb.inst_calls_list))
 		prot_virt_guest = 1;
+#endif
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/configs/debug_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/configs/debug_defconfig
@@ -62,7 +62,6 @@
 CONFIG_KPROBES=y
 CONFIG_JUMP_LABEL=y
 CONFIG_STATIC_KEYS_SELFTEST=y
-CONFIG_REFCOUNT_FULL=y
 CONFIG_LOCK_EVENT_COUNTS=y
 CONFIG_MODULES=y
 CONFIG_MODULE_FORCE_LOAD=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/crypto/aes_s390.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/crypto/aes_s390.c
@@ -861,7 +861,7 @@
 					     unsigned int nbytes)
 {
 	gw->walk_bytes_remain -= nbytes;
-	scatterwalk_unmap(&gw->walk);
+	scatterwalk_unmap(gw->walk_ptr);
 	scatterwalk_advance(&gw->walk, nbytes);
 	scatterwalk_done(&gw->walk, 0, gw->walk_bytes_remain);
 	gw->walk_ptr = NULL;
@@ -936,7 +936,7 @@
 		goto out;
 	}
 
-	scatterwalk_unmap(&gw->walk);
+	scatterwalk_unmap(gw->walk_ptr);
 	gw->walk_ptr = NULL;
 
 	gw->ptr = gw->buf;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/crypto/arch_random.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/crypto/arch_random.c
@@ -2,122 +2,17 @@
 /*
  * s390 arch random implementation.
  *
- * Copyright IBM Corp. 2017, 2018
+ * Copyright IBM Corp. 2017, 2020
  * Author(s): Harald Freudenberger
- *
- * The s390_arch_random_generate() function may be called from random.c
- * in interrupt context. So this implementation does the best to be very
- * fast. There is a buffer of random data which is asynchronously checked
- * and filled by a workqueue thread.
- * If there are enough bytes in the buffer the s390_arch_random_generate()
- * just delivers these bytes. Otherwise false is returned until the
- * worker thread refills the buffer.
- * The worker fills the rng buffer by pulling fresh entropy from the
- * high quality (but slow) true hardware random generator. This entropy
- * is then spread over the buffer with an pseudo random generator PRNG.
- * As the arch_get_random_seed_long() fetches 8 bytes and the calling
- * function add_interrupt_randomness() counts this as 1 bit entropy the
- * distribution needs to make sure there is in fact 1 bit entropy contained
- * in 8 bytes of the buffer. The current values pull 32 byte entropy
- * and scatter this into a 2048 byte buffer. So 8 byte in the buffer
- * will contain 1 bit of entropy.
- * The worker thread is rescheduled based on the charge level of the
- * buffer but at least with 500 ms delay to avoid too much CPU consumption.
- * So the max. amount of rng data delivered via arch_get_random_seed is
- * limited to 4k bytes per second.
  */
 
 #include <linux/kernel.h>
 #include <linux/atomic.h>
 #include <linux/random.h>
-#include <linux/slab.h>
 #include <linux/static_key.h>
-#include <linux/workqueue.h>
 #include <asm/cpacf.h>
 
 DEFINE_STATIC_KEY_FALSE(s390_arch_random_available);
 
 atomic64_t s390_arch_random_counter = ATOMIC64_INIT(0);
 EXPORT_SYMBOL(s390_arch_random_counter);
-
-#define ARCH_REFILL_TICKS (HZ/2)
-#define ARCH_PRNG_SEED_SIZE 32
-#define ARCH_RNG_BUF_SIZE 2048
-
-static DEFINE_SPINLOCK(arch_rng_lock);
-static u8 *arch_rng_buf;
-static unsigned int arch_rng_buf_idx;
-
-static void arch_rng_refill_buffer(struct work_struct *);
-static DECLARE_DELAYED_WORK(arch_rng_work, arch_rng_refill_buffer);
-
-bool s390_arch_random_generate(u8 *buf, unsigned int nbytes)
-{
-	/* lock rng buffer */
-	if (!spin_trylock(&arch_rng_lock))
-		return false;
-
-	/* try to resolve the requested amount of bytes from the buffer */
-	arch_rng_buf_idx -= nbytes;
-	if (arch_rng_buf_idx < ARCH_RNG_BUF_SIZE) {
-		memcpy(buf, arch_rng_buf + arch_rng_buf_idx, nbytes);
-		atomic64_add(nbytes, &s390_arch_random_counter);
-		spin_unlock(&arch_rng_lock);
-		return true;
-	}
-
-	/* not enough bytes in rng buffer, refill is done asynchronously */
-	spin_unlock(&arch_rng_lock);
-
-	return false;
-}
-EXPORT_SYMBOL(s390_arch_random_generate);
-
-static void arch_rng_refill_buffer(struct work_struct *unused)
-{
-	unsigned int delay = ARCH_REFILL_TICKS;
-
-	spin_lock(&arch_rng_lock);
-	if (arch_rng_buf_idx > ARCH_RNG_BUF_SIZE) {
-		/* buffer is exhausted and needs refill */
-		u8 seed[ARCH_PRNG_SEED_SIZE];
-		u8 prng_wa[240];
-		/* fetch ARCH_PRNG_SEED_SIZE bytes of entropy */
-		cpacf_trng(NULL, 0, seed, sizeof(seed));
-		/* blow this entropy up to ARCH_RNG_BUF_SIZE with PRNG */
-		memset(prng_wa, 0, sizeof(prng_wa));
-		cpacf_prno(CPACF_PRNO_SHA512_DRNG_SEED,
-			   &prng_wa, NULL, 0, seed, sizeof(seed));
-		cpacf_prno(CPACF_PRNO_SHA512_DRNG_GEN,
-			   &prng_wa, arch_rng_buf, ARCH_RNG_BUF_SIZE, NULL, 0);
-		arch_rng_buf_idx = ARCH_RNG_BUF_SIZE;
-	}
-	delay += (ARCH_REFILL_TICKS * arch_rng_buf_idx) / ARCH_RNG_BUF_SIZE;
-	spin_unlock(&arch_rng_lock);
-
-	/* kick next check */
-	queue_delayed_work(system_long_wq, &arch_rng_work, delay);
-}
-
-static int __init s390_arch_random_init(void)
-{
-	/* all the needed PRNO subfunctions available ? */
-	if (cpacf_query_func(CPACF_PRNO, CPACF_PRNO_TRNG) &&
-	    cpacf_query_func(CPACF_PRNO, CPACF_PRNO_SHA512_DRNG_GEN)) {
-
-		/* alloc arch random working buffer */
-		arch_rng_buf = kmalloc(ARCH_RNG_BUF_SIZE, GFP_KERNEL);
-		if (!arch_rng_buf)
-			return -ENOMEM;
-
-		/* kick worker queue job to fill the random buffer */
-		queue_delayed_work(system_long_wq,
-				   &arch_rng_work, ARCH_REFILL_TICKS);
-
-		/* enable arch random to the outside world */
-		static_branch_enable(&s390_arch_random_available);
-	}
-
-	return 0;
-}
-arch_initcall(s390_arch_random_init);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/crypto/paes_s390.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/crypto/paes_s390.c
@@ -5,7 +5,7 @@
  * s390 implementation of the AES Cipher Algorithm with protected keys.
  *
  * s390 Version:
- *   Copyright IBM Corp. 2017,2019
+ *   Copyright IBM Corp. 2017,2020
  *   Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
  *		Harald Freudenberger <freude@de.ibm.com>
  */
@@ -20,6 +20,7 @@
 #include <linux/module.h>
 #include <linux/cpufeature.h>
 #include <linux/init.h>
+#include <linux/mutex.h>
 #include <linux/spinlock.h>
 #include <crypto/xts.h>
 #include <asm/cpacf.h>
@@ -31,11 +32,11 @@
  * is called. As paes can handle different kinds of key blobs
  * and padding is also possible, the limits need to be generous.
  */
-#define PAES_MIN_KEYSIZE 64
-#define PAES_MAX_KEYSIZE 256
+#define PAES_MIN_KEYSIZE 16
+#define PAES_MAX_KEYSIZE 320
 
 static u8 *ctrblk;
-static DEFINE_SPINLOCK(ctrblk_lock);
+static DEFINE_MUTEX(ctrblk_lock);
 
 static cpacf_mask_t km_functions, kmc_functions, kmctr_functions;
 
@@ -52,19 +53,46 @@
 	unsigned int keylen;
 };
 
-static inline int _copy_key_to_kb(struct key_blob *kb,
-				  const u8 *key,
-				  unsigned int keylen)
-{
-	if (keylen <= sizeof(kb->keybuf))
+static inline int _key_to_kb(struct key_blob *kb,
+			     const u8 *key,
+			     unsigned int keylen)
+{
+	struct clearkey_header {
+		u8  type;
+		u8  res0[3];
+		u8  version;
+		u8  res1[3];
+		u32 keytype;
+		u32 len;
+	} __packed * h;
+
+	switch (keylen) {
+	case 16:
+	case 24:
+	case 32:
+		/* clear key value, prepare pkey clear key token in keybuf */
+		memset(kb->keybuf, 0, sizeof(kb->keybuf));
+		h = (struct clearkey_header *) kb->keybuf;
+		h->version = 0x02; /* TOKVER_CLEAR_KEY */
+		h->keytype = (keylen - 8) >> 3;
+		h->len = keylen;
+		memcpy(kb->keybuf + sizeof(*h), key, keylen);
+		kb->keylen = sizeof(*h) + keylen;
 		kb->key = kb->keybuf;
-	else {
-		kb->key = kmalloc(keylen, GFP_KERNEL);
-		if (!kb->key)
-			return -ENOMEM;
+		break;
+	default:
+		/* other key material, let pkey handle this */
+		if (keylen <= sizeof(kb->keybuf))
+			kb->key = kb->keybuf;
+		else {
+			kb->key = kmalloc(keylen, GFP_KERNEL);
+			if (!kb->key)
+				return -ENOMEM;
+		}
+		memcpy(kb->key, key, keylen);
+		kb->keylen = keylen;
+		break;
 	}
-	memcpy(kb->key, key, keylen);
-	kb->keylen = keylen;
 
 	return 0;
 }
@@ -81,16 +109,18 @@
 struct s390_paes_ctx {
 	struct key_blob kb;
 	struct pkey_protkey pk;
+	spinlock_t pk_lock;
 	unsigned long fc;
 };
 
 struct s390_pxts_ctx {
 	struct key_blob kb[2];
 	struct pkey_protkey pk[2];
+	spinlock_t pk_lock;
 	unsigned long fc;
 };
 
-static inline int __paes_convert_key(struct key_blob *kb,
+static inline int __paes_keyblob2pkey(struct key_blob *kb,
 				     struct pkey_protkey *pk)
 {
 	int i, ret;
@@ -105,22 +135,18 @@
 	return ret;
 }
 
-static int __paes_set_key(struct s390_paes_ctx *ctx)
+static inline int __paes_convert_key(struct s390_paes_ctx *ctx)
 {
-	unsigned long fc;
+	struct pkey_protkey pkey;
 
-	if (__paes_convert_key(&ctx->kb, &ctx->pk))
+	if (__paes_keyblob2pkey(&ctx->kb, &pkey))
 		return -EINVAL;
 
-	/* Pick the correct function code based on the protected key type */
-	fc = (ctx->pk.type == PKEY_KEYTYPE_AES_128) ? CPACF_KM_PAES_128 :
-		(ctx->pk.type == PKEY_KEYTYPE_AES_192) ? CPACF_KM_PAES_192 :
-		(ctx->pk.type == PKEY_KEYTYPE_AES_256) ? CPACF_KM_PAES_256 : 0;
-
-	/* Check if the function code is available */
-	ctx->fc = (fc && cpacf_test_func(&km_functions, fc)) ? fc : 0;
+	spin_lock_bh(&ctx->pk_lock);
+	memcpy(&ctx->pk, &pkey, sizeof(pkey));
+	spin_unlock_bh(&ctx->pk_lock);
 
-	return ctx->fc ? 0 : -EINVAL;
+	return 0;
 }
 
 static int ecb_paes_init(struct crypto_tfm *tfm)
@@ -128,6 +154,7 @@
 	struct s390_paes_ctx *ctx = crypto_tfm_ctx(tfm);
 
 	ctx->kb.key = NULL;
+	spin_lock_init(&ctx->pk_lock);
 
 	return 0;
 }
@@ -139,6 +166,24 @@
 	_free_kb_keybuf(&ctx->kb);
 }
 
+static inline int __ecb_paes_set_key(struct s390_paes_ctx *ctx)
+{
+	unsigned long fc;
+
+	if (__paes_convert_key(ctx))
+		return -EINVAL;
+
+	/* Pick the correct function code based on the protected key type */
+	fc = (ctx->pk.type == PKEY_KEYTYPE_AES_128) ? CPACF_KM_PAES_128 :
+		(ctx->pk.type == PKEY_KEYTYPE_AES_192) ? CPACF_KM_PAES_192 :
+		(ctx->pk.type == PKEY_KEYTYPE_AES_256) ? CPACF_KM_PAES_256 : 0;
+
+	/* Check if the function code is available */
+	ctx->fc = (fc && cpacf_test_func(&km_functions, fc)) ? fc : 0;
+
+	return ctx->fc ? 0 : -EINVAL;
+}
+
 static int ecb_paes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
 			    unsigned int key_len)
 {
@@ -146,13 +191,14 @@
 	struct s390_paes_ctx *ctx = crypto_tfm_ctx(tfm);
 
 	_free_kb_keybuf(&ctx->kb);
-	rc = _copy_key_to_kb(&ctx->kb, in_key, key_len);
+	rc = _key_to_kb(&ctx->kb, in_key, key_len);
 	if (rc)
 		return rc;
 
-	if (__paes_set_key(ctx)) {
+	if (__ecb_paes_set_key(ctx)) {
 		tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
 		return -EINVAL;
+
 	}
 	return 0;
 }
@@ -164,18 +210,31 @@
 	struct s390_paes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
 	unsigned int nbytes, n, k;
 	int ret;
+	struct {
+		u8 key[MAXPROTKEYSIZE];
+	} param;
 
 	ret = blkcipher_walk_virt(desc, walk);
+	if (ret)
+		return ret;
+
+	spin_lock_bh(&ctx->pk_lock);
+	memcpy(param.key, ctx->pk.protkey, MAXPROTKEYSIZE);
+	spin_unlock_bh(&ctx->pk_lock);
+
 	while ((nbytes = walk->nbytes) >= AES_BLOCK_SIZE) {
 		/* only use complete blocks */
 		n = nbytes & ~(AES_BLOCK_SIZE - 1);
-		k = cpacf_km(ctx->fc | modifier, ctx->pk.protkey,
+		k = cpacf_km(ctx->fc | modifier, &param,
 			     walk->dst.virt.addr, walk->src.virt.addr, n);
 		if (k)
 			ret = blkcipher_walk_done(desc, walk, nbytes - k);
 		if (k < n) {
-			if (__paes_set_key(ctx) != 0)
+			if (__paes_convert_key(ctx))
 				return blkcipher_walk_done(desc, walk, -EIO);
+			spin_lock_bh(&ctx->pk_lock);
+			memcpy(param.key, ctx->pk.protkey, MAXPROTKEYSIZE);
+			spin_unlock_bh(&ctx->pk_lock);
 		}
 	}
 	return ret;
@@ -229,6 +288,7 @@
 	struct s390_paes_ctx *ctx = crypto_tfm_ctx(tfm);
 
 	ctx->kb.key = NULL;
+	spin_lock_init(&ctx->pk_lock);
 
 	return 0;
 }
@@ -240,11 +300,11 @@
 	_free_kb_keybuf(&ctx->kb);
 }
 
-static int __cbc_paes_set_key(struct s390_paes_ctx *ctx)
+static inline int __cbc_paes_set_key(struct s390_paes_ctx *ctx)
 {
 	unsigned long fc;
 
-	if (__paes_convert_key(&ctx->kb, &ctx->pk))
+	if (__paes_convert_key(ctx))
 		return -EINVAL;
 
 	/* Pick the correct function code based on the protected key type */
@@ -265,7 +325,7 @@
 	struct s390_paes_ctx *ctx = crypto_tfm_ctx(tfm);
 
 	_free_kb_keybuf(&ctx->kb);
-	rc = _copy_key_to_kb(&ctx->kb, in_key, key_len);
+	rc = _key_to_kb(&ctx->kb, in_key, key_len);
 	if (rc)
 		return rc;
 
@@ -288,22 +348,31 @@
 	} param;
 
 	ret = blkcipher_walk_virt(desc, walk);
+	if (ret)
+		return ret;
+
 	memcpy(param.iv, walk->iv, AES_BLOCK_SIZE);
+	spin_lock_bh(&ctx->pk_lock);
 	memcpy(param.key, ctx->pk.protkey, MAXPROTKEYSIZE);
+	spin_unlock_bh(&ctx->pk_lock);
+
 	while ((nbytes = walk->nbytes) >= AES_BLOCK_SIZE) {
 		/* only use complete blocks */
 		n = nbytes & ~(AES_BLOCK_SIZE - 1);
 		k = cpacf_kmc(ctx->fc | modifier, &param,
 			      walk->dst.virt.addr, walk->src.virt.addr, n);
-		if (k)
+		if (k) {
+			memcpy(walk->iv, param.iv, AES_BLOCK_SIZE);
 			ret = blkcipher_walk_done(desc, walk, nbytes - k);
+		}
 		if (k < n) {
-			if (__cbc_paes_set_key(ctx) != 0)
+			if (__paes_convert_key(ctx))
 				return blkcipher_walk_done(desc, walk, -EIO);
+			spin_lock_bh(&ctx->pk_lock);
 			memcpy(param.key, ctx->pk.protkey, MAXPROTKEYSIZE);
+			spin_unlock_bh(&ctx->pk_lock);
 		}
 	}
-	memcpy(walk->iv, param.iv, AES_BLOCK_SIZE);
 	return ret;
 }
 
@@ -357,6 +426,7 @@
 
 	ctx->kb[0].key = NULL;
 	ctx->kb[1].key = NULL;
+	spin_lock_init(&ctx->pk_lock);
 
 	return 0;
 }
@@ -369,12 +439,27 @@
 	_free_kb_keybuf(&ctx->kb[1]);
 }
 
-static int __xts_paes_set_key(struct s390_pxts_ctx *ctx)
+static inline int __xts_paes_convert_key(struct s390_pxts_ctx *ctx)
+{
+	struct pkey_protkey pkey0, pkey1;
+
+	if (__paes_keyblob2pkey(&ctx->kb[0], &pkey0) ||
+	    __paes_keyblob2pkey(&ctx->kb[1], &pkey1))
+		return -EINVAL;
+
+	spin_lock_bh(&ctx->pk_lock);
+	memcpy(&ctx->pk[0], &pkey0, sizeof(pkey0));
+	memcpy(&ctx->pk[1], &pkey1, sizeof(pkey1));
+	spin_unlock_bh(&ctx->pk_lock);
+
+	return 0;
+}
+
+static inline int __xts_paes_set_key(struct s390_pxts_ctx *ctx)
 {
 	unsigned long fc;
 
-	if (__paes_convert_key(&ctx->kb[0], &ctx->pk[0]) ||
-	    __paes_convert_key(&ctx->kb[1], &ctx->pk[1]))
+	if (__xts_paes_convert_key(ctx))
 		return -EINVAL;
 
 	if (ctx->pk[0].type != ctx->pk[1].type)
@@ -406,10 +491,10 @@
 
 	_free_kb_keybuf(&ctx->kb[0]);
 	_free_kb_keybuf(&ctx->kb[1]);
-	rc = _copy_key_to_kb(&ctx->kb[0], in_key, key_len);
+	rc = _key_to_kb(&ctx->kb[0], in_key, key_len);
 	if (rc)
 		return rc;
-	rc = _copy_key_to_kb(&ctx->kb[1], in_key + key_len, key_len);
+	rc = _key_to_kb(&ctx->kb[1], in_key + key_len, key_len);
 	if (rc)
 		return rc;
 
@@ -449,15 +534,19 @@
 	} xts_param;
 
 	ret = blkcipher_walk_virt(desc, walk);
+	if (ret)
+		return ret;
+
 	keylen = (ctx->pk[0].type == PKEY_KEYTYPE_AES_128) ? 48 : 64;
 	offset = (ctx->pk[0].type == PKEY_KEYTYPE_AES_128) ? 16 : 0;
-retry:
+
 	memset(&pcc_param, 0, sizeof(pcc_param));
 	memcpy(pcc_param.tweak, walk->iv, sizeof(pcc_param.tweak));
+	spin_lock_bh(&ctx->pk_lock);
 	memcpy(pcc_param.key + offset, ctx->pk[1].protkey, keylen);
-	cpacf_pcc(ctx->fc, pcc_param.key + offset);
-
 	memcpy(xts_param.key + offset, ctx->pk[0].protkey, keylen);
+	spin_unlock_bh(&ctx->pk_lock);
+	cpacf_pcc(ctx->fc, pcc_param.key + offset);
 	memcpy(xts_param.init, pcc_param.xts, 16);
 
 	while ((nbytes = walk->nbytes) >= AES_BLOCK_SIZE) {
@@ -468,11 +557,15 @@
 		if (k)
 			ret = blkcipher_walk_done(desc, walk, nbytes - k);
 		if (k < n) {
-			if (__xts_paes_set_key(ctx) != 0)
+			if (__xts_paes_convert_key(ctx))
 				return blkcipher_walk_done(desc, walk, -EIO);
-			goto retry;
+			spin_lock_bh(&ctx->pk_lock);
+			memcpy(xts_param.key + offset,
+			       ctx->pk[0].protkey, keylen);
+			spin_unlock_bh(&ctx->pk_lock);
 		}
 	}
+
 	return ret;
 }
 
@@ -525,6 +618,7 @@
 	struct s390_paes_ctx *ctx = crypto_tfm_ctx(tfm);
 
 	ctx->kb.key = NULL;
+	spin_lock_init(&ctx->pk_lock);
 
 	return 0;
 }
@@ -536,11 +630,11 @@
 	_free_kb_keybuf(&ctx->kb);
 }
 
-static int __ctr_paes_set_key(struct s390_paes_ctx *ctx)
+static inline int __ctr_paes_set_key(struct s390_paes_ctx *ctx)
 {
 	unsigned long fc;
 
-	if (__paes_convert_key(&ctx->kb, &ctx->pk))
+	if (__paes_convert_key(ctx))
 		return -EINVAL;
 
 	/* Pick the correct function code based on the protected key type */
@@ -562,7 +656,7 @@
 	struct s390_paes_ctx *ctx = crypto_tfm_ctx(tfm);
 
 	_free_kb_keybuf(&ctx->kb);
-	rc = _copy_key_to_kb(&ctx->kb, in_key, key_len);
+	rc = _key_to_kb(&ctx->kb, in_key, key_len);
 	if (rc)
 		return rc;
 
@@ -595,47 +689,62 @@
 	u8 buf[AES_BLOCK_SIZE], *ctrptr;
 	unsigned int nbytes, n, k;
 	int ret, locked;
-
-	locked = spin_trylock(&ctrblk_lock);
+	struct {
+		u8 key[MAXPROTKEYSIZE];
+	} param;
 
 	ret = blkcipher_walk_virt_block(desc, walk, AES_BLOCK_SIZE);
+	if (ret)
+		return ret;
+
+	spin_lock_bh(&ctx->pk_lock);
+	memcpy(param.key, ctx->pk.protkey, MAXPROTKEYSIZE);
+	spin_unlock_bh(&ctx->pk_lock);
+
+	locked = mutex_trylock(&ctrblk_lock);
+
+
 	while ((nbytes = walk->nbytes) >= AES_BLOCK_SIZE) {
 		n = AES_BLOCK_SIZE;
 		if (nbytes >= 2*AES_BLOCK_SIZE && locked)
 			n = __ctrblk_init(ctrblk, walk->iv, nbytes);
 		ctrptr = (n > AES_BLOCK_SIZE) ? ctrblk : walk->iv;
-		k = cpacf_kmctr(ctx->fc | modifier, ctx->pk.protkey,
-				walk->dst.virt.addr, walk->src.virt.addr,
-				n, ctrptr);
+		k = cpacf_kmctr(ctx->fc | modifier, &param, walk->dst.virt.addr,
+				walk->src.virt.addr, n, ctrptr);
 		if (k) {
 			if (ctrptr == ctrblk)
 				memcpy(walk->iv, ctrptr + k - AES_BLOCK_SIZE,
 				       AES_BLOCK_SIZE);
 			crypto_inc(walk->iv, AES_BLOCK_SIZE);
-			ret = blkcipher_walk_done(desc, walk, nbytes - n);
+			ret = blkcipher_walk_done(desc, walk, nbytes - k);
 		}
 		if (k < n) {
-			if (__ctr_paes_set_key(ctx) != 0) {
+			if (__paes_convert_key(ctx)) {
 				if (locked)
-					spin_unlock(&ctrblk_lock);
+					mutex_unlock(&ctrblk_lock);
 				return blkcipher_walk_done(desc, walk, -EIO);
 			}
+			spin_lock_bh(&ctx->pk_lock);
+			memcpy(param.key, ctx->pk.protkey, MAXPROTKEYSIZE);
+			spin_unlock_bh(&ctx->pk_lock);
 		}
 	}
 	if (locked)
-		spin_unlock(&ctrblk_lock);
+		mutex_unlock(&ctrblk_lock);
 	/*
 	 * final block may be < AES_BLOCK_SIZE, copy only nbytes
 	 */
 	if (nbytes) {
 		while (1) {
-			if (cpacf_kmctr(ctx->fc | modifier,
-					ctx->pk.protkey, buf,
+			if (cpacf_kmctr(ctx->fc | modifier, &param, buf,
 					walk->src.virt.addr, AES_BLOCK_SIZE,
 					walk->iv) == AES_BLOCK_SIZE)
 				break;
-			if (__ctr_paes_set_key(ctx) != 0)
+			if (__paes_convert_key(ctx))
 				return blkcipher_walk_done(desc, walk, -EIO);
+			spin_lock_bh(&ctx->pk_lock);
+			memcpy(param.key, ctx->pk.protkey, MAXPROTKEYSIZE);
+			spin_unlock_bh(&ctx->pk_lock);
 		}
 		memcpy(walk->dst.virt.addr, buf, nbytes);
 		crypto_inc(walk->iv, AES_BLOCK_SIZE);
@@ -697,12 +806,12 @@
 
 static void paes_s390_fini(void)
 {
-	if (ctrblk)
-		free_page((unsigned long) ctrblk);
 	__crypto_unregister_alg(&ctr_paes_alg);
 	__crypto_unregister_alg(&xts_paes_alg);
 	__crypto_unregister_alg(&cbc_paes_alg);
 	__crypto_unregister_alg(&ecb_paes_alg);
+	if (ctrblk)
+		free_page((unsigned long) ctrblk);
 }
 
 static int __init paes_s390_init(void)
@@ -740,14 +849,14 @@
 	if (cpacf_test_func(&kmctr_functions, CPACF_KMCTR_PAES_128) ||
 	    cpacf_test_func(&kmctr_functions, CPACF_KMCTR_PAES_192) ||
 	    cpacf_test_func(&kmctr_functions, CPACF_KMCTR_PAES_256)) {
-		ret = crypto_register_alg(&ctr_paes_alg);
-		if (ret)
-			goto out_err;
 		ctrblk = (u8 *) __get_free_page(GFP_KERNEL);
 		if (!ctrblk) {
 			ret = -ENOMEM;
 			goto out_err;
 		}
+		ret = crypto_register_alg(&ctr_paes_alg);
+		if (ret)
+			goto out_err;
 	}
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/crypto/sha_common.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/crypto/sha_common.c
@@ -74,14 +74,17 @@
 	struct s390_sha_ctx *ctx = shash_desc_ctx(desc);
 	unsigned int bsize = crypto_shash_blocksize(desc->tfm);
 	u64 bits;
-	unsigned int n, mbl_offset;
+	unsigned int n;
+	int mbl_offset;
 
 	n = ctx->count % bsize;
 	bits = ctx->count * 8;
-	mbl_offset = s390_crypto_shash_parmsize(ctx->func) / sizeof(u32);
+	mbl_offset = s390_crypto_shash_parmsize(ctx->func);
 	if (mbl_offset < 0)
 		return -EINVAL;
 
+	mbl_offset = mbl_offset / sizeof(u32);
+
 	/* set total msg bit length (mbl) in CPACF parmblock */
 	switch (ctx->func) {
 	case CPACF_KLMD_SHA_1:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/hypfs/hypfs_diag.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/hypfs/hypfs_diag.c
@@ -437,7 +437,7 @@
 	int rc;
 
 	if (diag204_probe()) {
-		pr_err("The hardware system does not support hypfs\n");
+		pr_info("The hardware system does not support hypfs\n");
 		return -ENODATA;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/hypfs/hypfs_vm.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/hypfs/hypfs_vm.c
@@ -20,6 +20,7 @@
 
 static char local_guest[] = "        ";
 static char all_guests[] = "*       ";
+static char *all_groups = all_guests;
 static char *guest_query;
 
 struct diag2fc_data {
@@ -62,10 +63,11 @@
 
 	memcpy(parm_list.userid, query, NAME_LEN);
 	ASCEBC(parm_list.userid, NAME_LEN);
-	parm_list.addr = (unsigned long) addr ;
+	memcpy(parm_list.aci_grp, all_groups, NAME_LEN);
+	ASCEBC(parm_list.aci_grp, NAME_LEN);
+	parm_list.addr = (unsigned long)addr;
 	parm_list.size = size;
 	parm_list.fmt = 0x02;
-	memset(parm_list.aci_grp, 0x40, NAME_LEN);
 	rc = -1;
 
 	diag_stat_inc(DIAG_STAT_X2FC);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/hypfs/inode.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/hypfs/inode.c
@@ -501,9 +501,9 @@
 	hypfs_vm_exit();
 fail_hypfs_diag_exit:
 	hypfs_diag_exit();
+	pr_err("Initialization of hypfs failed with rc=%i\n", rc);
 fail_dbfs_exit:
 	hypfs_dbfs_exit();
-	pr_err("Initialization of hypfs failed with rc=%i\n", rc);
 	return rc;
 }
 device_initcall(hypfs_init)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/Kbuild
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/Kbuild
@@ -7,7 +7,6 @@
 generic-y += asm-offsets.h
 generic-y += cacheflush.h
 generic-y += device.h
-generic-y += dma-contiguous.h
 generic-y += dma-mapping.h
 generic-y += div64.h
 generic-y += emergency-restart.h
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/archrandom.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/archrandom.h
@@ -2,7 +2,7 @@
 /*
  * Kernel interface for the s390 arch_random_* functions
  *
- * Copyright IBM Corp. 2017
+ * Copyright IBM Corp. 2017, 2022
  *
  * Author: Harald Freudenberger <freude@de.ibm.com>
  *
@@ -14,47 +14,41 @@
 #ifdef CONFIG_ARCH_RANDOM
 
 #include <linux/static_key.h>
+#include <linux/preempt.h>
 #include <linux/atomic.h>
+#include <asm/cpacf.h>
 
 DECLARE_STATIC_KEY_FALSE(s390_arch_random_available);
 extern atomic64_t s390_arch_random_counter;
 
-bool s390_arch_random_generate(u8 *buf, unsigned int nbytes);
-
-static inline bool arch_has_random(void)
-{
-	return false;
-}
-
-static inline bool arch_has_random_seed(void)
-{
-	if (static_branch_likely(&s390_arch_random_available))
-		return true;
-	return false;
-}
-
-static inline bool arch_get_random_long(unsigned long *v)
+static inline bool __must_check arch_get_random_long(unsigned long *v)
 {
 	return false;
 }
 
-static inline bool arch_get_random_int(unsigned int *v)
+static inline bool __must_check arch_get_random_int(unsigned int *v)
 {
 	return false;
 }
 
-static inline bool arch_get_random_seed_long(unsigned long *v)
+static inline bool __must_check arch_get_random_seed_long(unsigned long *v)
 {
-	if (static_branch_likely(&s390_arch_random_available)) {
-		return s390_arch_random_generate((u8 *)v, sizeof(*v));
+	if (static_branch_likely(&s390_arch_random_available) &&
+	    in_task()) {
+		cpacf_trng(NULL, 0, (u8 *)v, sizeof(*v));
+		atomic64_add(sizeof(*v), &s390_arch_random_counter);
+		return true;
 	}
 	return false;
 }
 
-static inline bool arch_get_random_seed_int(unsigned int *v)
+static inline bool __must_check arch_get_random_seed_int(unsigned int *v)
 {
-	if (static_branch_likely(&s390_arch_random_available)) {
-		return s390_arch_random_generate((u8 *)v, sizeof(*v));
+	if (static_branch_likely(&s390_arch_random_available) &&
+	    in_task()) {
+		cpacf_trng(NULL, 0, (u8 *)v, sizeof(*v));
+		atomic64_add(sizeof(*v), &s390_arch_random_counter);
+		return true;
 	}
 	return false;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/cpu_mf.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/cpu_mf.h
@@ -109,7 +109,9 @@
 	unsigned int AS:2;	    /* 29-30 PSW address-space control	 */
 	unsigned int I:1;	    /* 31 entry valid or invalid	 */
 	unsigned int CL:2;	    /* 32-33 Configuration Level	 */
-	unsigned int:14;
+	unsigned int H:1;	    /* 34 Host Indicator		 */
+	unsigned int LS:1;	    /* 35 Limited Sampling		 */
+	unsigned int:12;
 	unsigned int prim_asn:16;   /* primary ASN			 */
 	unsigned long long ia;	    /* Instruction Address		 */
 	unsigned long long gpp;     /* Guest Program Parameter		 */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/ctl_reg.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/ctl_reg.h
@@ -11,6 +11,8 @@
 #include <linux/bits.h>
 
 #define CR0_CLOCK_COMPARATOR_SIGN	BIT(63 - 10)
+#define CR0_FETCH_PROTECTION_OVERRIDE	BIT(63 - 38)
+#define CR0_STORAGE_PROTECTION_OVERRIDE	BIT(63 - 39)
 #define CR0_EMERGENCY_SIGNAL_SUBMASK	BIT(63 - 49)
 #define CR0_EXTERNAL_CALL_SUBMASK	BIT(63 - 50)
 #define CR0_CLOCK_COMPARATOR_SUBMASK	BIT(63 - 52)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/debug.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/debug.h
@@ -4,8 +4,8 @@
  *
  *    Copyright IBM Corp. 1999, 2000
  */
-#ifndef DEBUG_H
-#define DEBUG_H
+#ifndef _ASM_S390_DEBUG_H
+#define _ASM_S390_DEBUG_H
 
 #include <linux/string.h>
 #include <linux/spinlock.h>
@@ -416,4 +416,4 @@
 #define PRINT_FATAL(x...)	printk(KERN_DEBUG PRINTK_HEADER x)
 #endif /* DASD_DEBUG */
 
-#endif /* DEBUG_H */
+#endif /* _ASM_S390_DEBUG_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/diag.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/diag.h
@@ -298,10 +298,8 @@
 union diag318_info {
 	unsigned long val;
 	struct {
-		unsigned int cpnc : 8;
-		unsigned int cpvc_linux : 24;
-		unsigned char cpvc_distro[3];
-		unsigned char zero;
+		unsigned long cpnc : 8;
+		unsigned long cpvc : 56;
 	};
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/facility.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/facility.h
@@ -53,8 +53,10 @@
 	unsigned long facilities_als[] = { FACILITIES_ALS };
 
 	if (__builtin_constant_p(nr) && nr < sizeof(facilities_als) * 8) {
-		if (__test_facility(nr, &facilities_als))
-			return 1;
+		if (__test_facility(nr, &facilities_als)) {
+			if (!__is_defined(__DECOMPRESSOR))
+				return 1;
+		}
 	}
 	return __test_facility(nr, &S390_lowcore.stfle_fac_list);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/fpu/api.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/fpu/api.h
@@ -76,7 +76,7 @@
 #define KERNEL_VXR_HIGH		(KERNEL_VXR_V16V23|KERNEL_VXR_V24V31)
 
 #define KERNEL_VXR		(KERNEL_VXR_LOW|KERNEL_VXR_HIGH)
-#define KERNEL_FPR		(KERNEL_FPC|KERNEL_VXR_V0V7)
+#define KERNEL_FPR		(KERNEL_FPC|KERNEL_VXR_LOW)
 
 struct kernel_fpu;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/ftrace.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/ftrace.h
@@ -27,6 +27,7 @@
 
 extern char ftrace_graph_caller_end;
 extern unsigned long ftrace_plt;
+extern void *ftrace_func;
 
 struct dyn_arch_ftrace { };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/futex.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/futex.h
@@ -16,7 +16,8 @@
 		"3: jl    1b\n"						\
 		"   lhi   %0,0\n"					\
 		"4: sacf  768\n"					\
-		EX_TABLE(0b,4b) EX_TABLE(2b,4b) EX_TABLE(3b,4b)		\
+		EX_TABLE(0b,4b) EX_TABLE(1b,4b)				\
+		EX_TABLE(2b,4b) EX_TABLE(3b,4b)				\
 		: "=d" (ret), "=&d" (oldval), "=&d" (newval),		\
 		  "=m" (*uaddr)						\
 		: "0" (-EFAULT), "d" (oparg), "a" (uaddr),		\
@@ -45,7 +46,7 @@
 		break;
 	case FUTEX_OP_ANDN:
 		__futex_atomic_op("lr %2,%1\nnr %2,%5\n",
-				  ret, oldval, newval, uaddr, oparg);
+				  ret, oldval, newval, uaddr, ~oparg);
 		break;
 	case FUTEX_OP_XOR:
 		__futex_atomic_op("lr %2,%1\nxr %2,%5\n",
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/gmap.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/gmap.h
@@ -9,6 +9,7 @@
 #ifndef _ASM_S390_GMAP_H
 #define _ASM_S390_GMAP_H
 
+#include <linux/radix-tree.h>
 #include <linux/refcount.h>
 
 /* Generic bits for GMAP notification on DAT table entry changes. */
@@ -31,6 +32,7 @@
  * @table: pointer to the page directory
  * @asce: address space control element for gmap page table
  * @pfault_enabled: defines if pfaults are applicable for the guest
+ * @guest_handle: protected virtual machine handle for the ultravisor
  * @host_to_rmap: radix tree with gmap_rmap lists
  * @children: list of shadow gmap structures
  * @pt_list: list of all page tables used in the shadow guest address space
@@ -54,6 +56,8 @@
 	unsigned long asce_end;
 	void *private;
 	bool pfault_enabled;
+	/* only set for protected virtual machines */
+	unsigned long guest_handle;
 	/* Additional data for shadow guest address spaces */
 	struct radix_tree_root host_to_rmap;
 	struct list_head children;
@@ -144,4 +148,6 @@
 
 void gmap_sync_dirty_log_pmd(struct gmap *gmap, unsigned long dirty_bitmap[4],
 			     unsigned long gaddr, unsigned long vmaddr);
+int gmap_mark_unmergeable(void);
+void s390_reset_acc(struct mm_struct *mm);
 #endif /* _ASM_S390_GMAP_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/hugetlb.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/hugetlb.h
@@ -35,9 +35,11 @@
 static inline int prepare_hugepage_range(struct file *file,
 			unsigned long addr, unsigned long len)
 {
-	if (len & ~HPAGE_MASK)
+	struct hstate *h = hstate_file(file);
+
+	if (len & ~huge_page_mask(h))
 		return -EINVAL;
-	if (addr & ~HPAGE_MASK)
+	if (addr & ~huge_page_mask(h))
 		return -EINVAL;
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/ipl.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/ipl.h
@@ -21,6 +21,7 @@
 		struct ipl_pb0_common common;
 		struct ipl_pb0_fcp fcp;
 		struct ipl_pb0_ccw ccw;
+		struct ipl_pb0_nvme nvme;
 		char raw[PAGE_SIZE - sizeof(struct ipl_pl_hdr)];
 	};
 } __packed __aligned(PAGE_SIZE);
@@ -30,6 +31,11 @@
 #define IPL_BP_FCP_LEN (sizeof(struct ipl_pl_hdr) + \
 			      sizeof(struct ipl_pb0_fcp))
 #define IPL_BP0_FCP_LEN (sizeof(struct ipl_pb0_fcp))
+
+#define IPL_BP_NVME_LEN (sizeof(struct ipl_pl_hdr) + \
+			      sizeof(struct ipl_pb0_nvme))
+#define IPL_BP0_NVME_LEN (sizeof(struct ipl_pb0_nvme))
+
 #define IPL_BP_CCW_LEN (sizeof(struct ipl_pl_hdr) + \
 			      sizeof(struct ipl_pb0_ccw))
 #define IPL_BP0_CCW_LEN (sizeof(struct ipl_pb0_ccw))
@@ -59,6 +65,7 @@
 	IPL_TYPE_FCP		= 4,
 	IPL_TYPE_FCP_DUMP	= 8,
 	IPL_TYPE_NSS		= 16,
+	IPL_TYPE_NVME		= 32,
 };
 
 struct ipl_info
@@ -74,6 +81,10 @@
 			u64 lun;
 		} fcp;
 		struct {
+			u32 fid;
+			u32 nsid;
+		} nvme;
+		struct {
 			char name[NSS_NAME_SIZE + 1];
 		} nss;
 	} data;
@@ -109,6 +120,7 @@
 			     unsigned char flags, unsigned short cert);
 int ipl_report_add_certificate(struct ipl_report *report, void *key,
 			       unsigned long addr, unsigned long len);
+bool ipl_get_secureboot(void);
 
 /*
  * DIAG 308 support
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/kexec.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/kexec.h
@@ -9,6 +9,8 @@
 #ifndef _S390_KEXEC_H
 #define _S390_KEXEC_H
 
+#include <linux/module.h>
+
 #include <asm/processor.h>
 #include <asm/page.h>
 #include <asm/setup.h>
@@ -74,7 +76,21 @@
 int arch_kexec_do_relocs(int r_type, void *loc, unsigned long val,
 			 unsigned long addr);
 
+#define ARCH_HAS_KIMAGE_ARCH
+
+struct kimage_arch {
+	void *ipl_buf;
+};
+
 extern const struct kexec_file_ops s390_kexec_image_ops;
 extern const struct kexec_file_ops s390_kexec_elf_ops;
 
+#ifdef CONFIG_KEXEC_FILE
+struct purgatory_info;
+int arch_kexec_apply_relocations_add(struct purgatory_info *pi,
+				     Elf_Shdr *section,
+				     const Elf_Shdr *relsec,
+				     const Elf_Shdr *symtab);
+#define arch_kexec_apply_relocations_add arch_kexec_apply_relocations_add
+#endif
 #endif /*_S390_KEXEC_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/kprobes.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/kprobes.h
@@ -54,7 +54,6 @@
 struct arch_specific_insn {
 	/* copy of original instruction */
 	kprobe_opcode_t *insn;
-	unsigned int is_ftrace_insn : 1;
 };
 
 struct prev_kprobe {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/kvm_host.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/kvm_host.h
@@ -31,12 +31,12 @@
 #define KVM_USER_MEM_SLOTS 32
 
 /*
- * These seem to be used for allocating ->chip in the routing table,
- * which we don't use. 4096 is an out-of-thin-air value. If we need
- * to look at ->chip later on, we'll need to revisit this.
+ * These seem to be used for allocating ->chip in the routing table, which we
+ * don't use. 1 is as small as we can get to reduce the needed memory. If we
+ * need to look at ->chip later on, we'll need to revisit this.
  */
 #define KVM_NR_IRQCHIPS 1
-#define KVM_IRQCHIP_NUM_PINS 4096
+#define KVM_IRQCHIP_NUM_PINS 1
 #define KVM_HALT_POLL_NS_DEFAULT 50000
 
 /* s390-specific vcpu->requests bit members */
@@ -122,6 +122,17 @@
 	__u32 reserved;
 };
 
+#define CR0_INITIAL_MASK (CR0_UNUSED_56 | CR0_INTERRUPT_KEY_SUBMASK | \
+			  CR0_MEASUREMENT_ALERT_SUBMASK)
+#define CR14_INITIAL_MASK (CR14_UNUSED_32 | CR14_UNUSED_33 | \
+			   CR14_EXTERNAL_DAMAGE_SUBMASK)
+
+#define SIDAD_SIZE_MASK		0xff
+#define sida_origin(sie_block) \
+	((sie_block)->sidad & PAGE_MASK)
+#define sida_size(sie_block) \
+	((((sie_block)->sidad & SIDAD_SIZE_MASK) + 1) * PAGE_SIZE)
+
 #define CPUSTAT_STOPPED    0x80000000
 #define CPUSTAT_WAIT       0x10000000
 #define CPUSTAT_ECALL_PEND 0x08000000
@@ -155,7 +166,13 @@
 	__u8	reserved08[4];		/* 0x0008 */
 #define PROG_IN_SIE (1<<0)
 	__u32	prog0c;			/* 0x000c */
-	__u8	reserved10[16];		/* 0x0010 */
+	union {
+		__u8	reserved10[16];		/* 0x0010 */
+		struct {
+			__u64	pv_handle_cpu;
+			__u64	pv_handle_config;
+		};
+	};
 #define PROG_BLOCK_SIE	(1<<0)
 #define PROG_REQUEST	(1<<1)
 	atomic_t prog20;		/* 0x0020 */
@@ -204,10 +221,23 @@
 #define ICPT_PARTEXEC	0x38
 #define ICPT_IOINST	0x40
 #define ICPT_KSS	0x5c
+#define ICPT_MCHKREQ	0x60
+#define ICPT_INT_ENABLE	0x64
+#define ICPT_PV_INSTR	0x68
+#define ICPT_PV_NOTIFY	0x6c
+#define ICPT_PV_PREF	0x70
 	__u8	icptcode;		/* 0x0050 */
 	__u8	icptstatus;		/* 0x0051 */
 	__u16	ihcpu;			/* 0x0052 */
-	__u8	reserved54[2];		/* 0x0054 */
+	__u8	reserved54;		/* 0x0054 */
+#define IICTL_CODE_NONE		 0x00
+#define IICTL_CODE_MCHK		 0x01
+#define IICTL_CODE_EXT		 0x02
+#define IICTL_CODE_IO		 0x03
+#define IICTL_CODE_RESTART	 0x04
+#define IICTL_CODE_SPECIFICATION 0x10
+#define IICTL_CODE_OPERAND	 0x11
+	__u8	iictl;			/* 0x0055 */
 	__u16	ipa;			/* 0x0056 */
 	__u32	ipb;			/* 0x0058 */
 	__u32	scaoh;			/* 0x005c */
@@ -228,9 +258,10 @@
 #define ECB3_RI  0x01
 	__u8    ecb3;			/* 0x0063 */
 	__u32	scaol;			/* 0x0064 */
-	__u8	reserved68;		/* 0x0068 */
+	__u8	sdf;			/* 0x0068 */
 	__u8    epdx;			/* 0x0069 */
-	__u8    reserved6a[2];		/* 0x006a */
+	__u8	cpnc;			/* 0x006a */
+	__u8	reserved6b;		/* 0x006b */
 	__u32	todpr;			/* 0x006c */
 #define GISA_FORMAT1 0x00000001
 	__u32	gd;			/* 0x0070 */
@@ -244,31 +275,58 @@
 #define HPID_KVM	0x4
 #define HPID_VSIE	0x5
 	__u8	hpid;			/* 0x00b8 */
-	__u8	reservedb9[11];		/* 0x00b9 */
-	__u16	extcpuaddr;		/* 0x00c4 */
-	__u16	eic;			/* 0x00c6 */
+	__u8	reservedb9[7];		/* 0x00b9 */
+	union {
+		struct {
+			__u32	eiparams;	/* 0x00c0 */
+			__u16	extcpuaddr;	/* 0x00c4 */
+			__u16	eic;		/* 0x00c6 */
+		};
+		__u64	mcic;			/* 0x00c0 */
+	} __packed;
 	__u32	reservedc8;		/* 0x00c8 */
-	__u16	pgmilc;			/* 0x00cc */
-	__u16	iprcc;			/* 0x00ce */
-	__u32	dxc;			/* 0x00d0 */
-	__u16	mcn;			/* 0x00d4 */
-	__u8	perc;			/* 0x00d6 */
-	__u8	peratmid;		/* 0x00d7 */
+	union {
+		struct {
+			__u16	pgmilc;		/* 0x00cc */
+			__u16	iprcc;		/* 0x00ce */
+		};
+		__u32	edc;			/* 0x00cc */
+	} __packed;
+	union {
+		struct {
+			__u32	dxc;		/* 0x00d0 */
+			__u16	mcn;		/* 0x00d4 */
+			__u8	perc;		/* 0x00d6 */
+			__u8	peratmid;	/* 0x00d7 */
+		};
+		__u64	faddr;			/* 0x00d0 */
+	} __packed;
 	__u64	peraddr;		/* 0x00d8 */
 	__u8	eai;			/* 0x00e0 */
 	__u8	peraid;			/* 0x00e1 */
 	__u8	oai;			/* 0x00e2 */
 	__u8	armid;			/* 0x00e3 */
 	__u8	reservede4[4];		/* 0x00e4 */
-	__u64	tecmc;			/* 0x00e8 */
-	__u8	reservedf0[12];		/* 0x00f0 */
+	union {
+		__u64	tecmc;		/* 0x00e8 */
+		struct {
+			__u16	subchannel_id;	/* 0x00e8 */
+			__u16	subchannel_nr;	/* 0x00ea */
+			__u32	io_int_parm;	/* 0x00ec */
+			__u32	io_int_word;	/* 0x00f0 */
+		};
+	} __packed;
+	__u8	reservedf4[8];		/* 0x00f4 */
 #define CRYCB_FORMAT_MASK 0x00000003
 #define CRYCB_FORMAT0 0x00000000
 #define CRYCB_FORMAT1 0x00000001
 #define CRYCB_FORMAT2 0x00000003
 	__u32	crycbd;			/* 0x00fc */
 	__u64	gcr[16];		/* 0x0100 */
-	__u64	gbea;			/* 0x0180 */
+	union {
+		__u64	gbea;		/* 0x0180 */
+		__u64	sidad;
+	};
 	__u8    reserved188[8];		/* 0x0188 */
 	__u64   sdnxo;			/* 0x0190 */
 	__u8    reserved198[8];		/* 0x0198 */
@@ -296,7 +354,9 @@
 struct sie_page {
 	struct kvm_s390_sie_block sie_block;
 	struct mcck_volatile_info mcck_info;	/* 0x0200 */
-	__u8 reserved218[1000];		/* 0x0218 */
+	__u8 reserved218[360];		/* 0x0218 */
+	__u64 pv_grregs[16];		/* 0x0380 */
+	__u8 reserved400[512];		/* 0x0400 */
 	struct kvm_s390_itdb itdb;	/* 0x0600 */
 	__u8 reserved700[2304];		/* 0x0700 */
 };
@@ -470,6 +530,7 @@
 	IRQ_PEND_PFAULT_INIT,
 	IRQ_PEND_EXT_HOST,
 	IRQ_PEND_EXT_SERVICE,
+	IRQ_PEND_EXT_SERVICE_EV,
 	IRQ_PEND_EXT_TIMING,
 	IRQ_PEND_EXT_CPU_TIMER,
 	IRQ_PEND_EXT_CLOCK_COMP,
@@ -514,6 +575,7 @@
 			   (1UL << IRQ_PEND_EXT_TIMING)     | \
 			   (1UL << IRQ_PEND_EXT_HOST)       | \
 			   (1UL << IRQ_PEND_EXT_SERVICE)    | \
+			   (1UL << IRQ_PEND_EXT_SERVICE_EV) | \
 			   (1UL << IRQ_PEND_VIRTIO)         | \
 			   (1UL << IRQ_PEND_PFAULT_INIT)    | \
 			   (1UL << IRQ_PEND_PFAULT_DONE))
@@ -530,6 +592,13 @@
 #define IRQ_PEND_MCHK_MASK ((1UL << IRQ_PEND_MCHK_REP) | \
 			    (1UL << IRQ_PEND_MCHK_EX))
 
+#define IRQ_PEND_EXT_II_MASK ((1UL << IRQ_PEND_EXT_CPU_TIMER)  | \
+			      (1UL << IRQ_PEND_EXT_CLOCK_COMP) | \
+			      (1UL << IRQ_PEND_EXT_EMERGENCY)  | \
+			      (1UL << IRQ_PEND_EXT_EXTERNAL)   | \
+			      (1UL << IRQ_PEND_EXT_SERVICE)    | \
+			      (1UL << IRQ_PEND_EXT_SERVICE_EV))
+
 struct kvm_s390_interrupt_info {
 	struct list_head list;
 	u64	type;
@@ -588,6 +657,7 @@
 
 struct kvm_s390_float_interrupt {
 	unsigned long pending_irqs;
+	unsigned long masked_irqs;
 	spinlock_t lock;
 	struct list_head lists[FIRQ_LIST_COUNT];
 	int counters[FIRQ_MAX_COUNT];
@@ -639,6 +709,11 @@
 	unsigned long last_bp;
 };
 
+struct kvm_s390_pv_vcpu {
+	u64 handle;
+	unsigned long stor_base;
+};
+
 struct kvm_vcpu_arch {
 	struct kvm_s390_sie_block *sie_block;
 	/* if vsie is active, currently executed shadow sie control block */
@@ -667,6 +742,8 @@
 	__u64 cputm_start;
 	bool gs_enabled;
 	bool skey_enabled;
+	struct kvm_s390_pv_vcpu pv;
+	union diag318_info diag318_info;
 };
 
 struct kvm_vm_stat {
@@ -695,9 +772,6 @@
 	bool masked;
 	bool swap;
 	bool suppressible;
-	struct rw_semaphore maps_lock;
-	struct list_head maps;
-	atomic_t nr_maps;
 };
 
 #define MAX_S390_IO_ADAPTERS ((MAX_ISC + 1) * 8)
@@ -840,6 +914,13 @@
 	DECLARE_BITMAP(kicked_mask, KVM_MAX_VCPUS);
 };
 
+struct kvm_s390_pv {
+	u64 handle;
+	u64 guest_len;
+	unsigned long stor_base;
+	void *stor_var;
+};
+
 struct kvm_arch{
 	void *sca;
 	int use_esca;
@@ -873,8 +954,10 @@
 	atomic64_t cmma_dirty_pages;
 	/* subset of available cpu features enabled by user space */
 	DECLARE_BITMAP(cpu_feat, KVM_S390_VM_CPU_FEAT_NR_BITS);
+	/* indexed by vcpu_idx */
 	DECLARE_BITMAP(idle_mask, KVM_MAX_VCPUS);
 	struct kvm_s390_gisa_interrupt gisa_int;
+	struct kvm_s390_pv pv;
 };
 
 #define KVM_HVA_ERR_BAD		(-1UL)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/lowcore.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/lowcore.h
@@ -141,7 +141,9 @@
 
 	/* br %r1 trampoline */
 	__u16	br_r1_trampoline;		/* 0x0400 */
-	__u8	pad_0x0402[0x0e00-0x0402];	/* 0x0402 */
+	__u32	return_lpswe;			/* 0x0402 */
+	__u32	return_mcck_lpswe;		/* 0x0406 */
+	__u8	pad_0x040a[0x0e00-0x040a];	/* 0x040a */
 
 	/*
 	 * 0xe00 contains the address of the IPL Parameter Information
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/mmu.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/mmu.h
@@ -16,6 +16,8 @@
 	unsigned long asce;
 	unsigned long asce_limit;
 	unsigned long vdso_base;
+	/* The mmu context belongs to a secure guest. */
+	atomic_t is_protected;
 	/*
 	 * The following bitfields need a down_write on the mm
 	 * semaphore when they are written to. As they are only
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/mmu_context.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/mmu_context.h
@@ -23,6 +23,7 @@
 	INIT_LIST_HEAD(&mm->context.gmap_list);
 	cpumask_clear(&mm->context.cpu_attach_mask);
 	atomic_set(&mm->context.flush_count, 0);
+	atomic_set(&mm->context.is_protected, 0);
 	mm->context.gmap_asce = 0;
 	mm->context.flush_mm = 0;
 	mm->context.compat_mm = test_thread_flag(TIF_31BIT);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/numa.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/numa.h
@@ -17,7 +17,6 @@
 
 void numa_setup(void);
 int numa_pfn_to_nid(unsigned long pfn);
-int __node_distance(int a, int b);
 void numa_update_cpu_topology(void);
 
 extern cpumask_t node_to_cpumask_map[MAX_NUMNODES];
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/page.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/page.h
@@ -20,6 +20,8 @@
 #define PAGE_SIZE	_PAGE_SIZE
 #define PAGE_MASK	_PAGE_MASK
 #define PAGE_DEFAULT_ACC	0
+/* storage-protection override */
+#define PAGE_SPO_ACC		9
 #define PAGE_DEFAULT_KEY	(PAGE_DEFAULT_ACC << 4)
 
 #define HPAGE_SHIFT	20
@@ -33,6 +35,8 @@
 #define ARCH_HAS_PREPARE_HUGEPAGE
 #define ARCH_HAS_HUGEPAGE_CLEAR_FLUSH
 
+#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
+
 #include <asm/setup.h>
 #ifndef __ASSEMBLY__
 
@@ -40,7 +44,7 @@
 
 static inline void storage_key_init_range(unsigned long start, unsigned long end)
 {
-	if (PAGE_DEFAULT_KEY)
+	if (PAGE_DEFAULT_KEY != 0)
 		__storage_key_init_range(start, end);
 }
 
@@ -151,6 +155,11 @@
 #define HAVE_ARCH_FREE_PAGE
 #define HAVE_ARCH_ALLOC_PAGE
 
+#if IS_ENABLED(CONFIG_PGSTE)
+int arch_make_page_accessible(struct page *page);
+#define HAVE_ARCH_MAKE_PAGE_ACCESSIBLE
+#endif
+
 #endif /* !__ASSEMBLY__ */
 
 #define __PAGE_OFFSET		0x0UL
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/pci.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/pci.h
@@ -8,6 +8,7 @@
 #include <linux/pci.h>
 #include <linux/mutex.h>
 #include <linux/iommu.h>
+#include <linux/pci_hotplug.h>
 #include <asm-generic/pci.h>
 #include <asm/pci_clp.h>
 #include <asm/pci_debug.h>
@@ -24,10 +25,16 @@
 int pci_proc_domain(struct pci_bus *);
 
 #define ZPCI_BUS_NR			0	/* default bus number */
-#define ZPCI_DEVFN			0	/* default device number */
 
 #define ZPCI_NR_DMA_SPACES		1
 #define ZPCI_NR_DEVICES			CONFIG_PCI_NR_FUNCTIONS
+#define ZPCI_DOMAIN_BITMAP_SIZE		(1 << 16)
+
+#ifdef PCI
+#if (ZPCI_NR_DEVICES > ZPCI_DOMAIN_BITMAP_SIZE)
+# error ZPCI_NR_DEVICES can not be bigger than ZPCI_DOMAIN_BITMAP_SIZE
+#endif
+#endif /* PCI */
 
 /* PCI Function Controls */
 #define ZPCI_FC_FN_ENABLED		0x80
@@ -95,10 +102,26 @@
 
 struct s390_domain;
 
+#define ZPCI_FUNCTIONS_PER_BUS 256
+struct zpci_bus {
+	struct kref		kref;
+	struct pci_bus		*bus;
+	struct zpci_dev		*function[ZPCI_FUNCTIONS_PER_BUS];
+	struct list_head	resources;
+	struct list_head	bus_next;
+	int			pchid;
+	int			domain_nr;
+	bool			multifunction;
+	enum pci_bus_speed	max_bus_speed;
+};
+
 /* Private data per function */
 struct zpci_dev {
-	struct pci_bus	*bus;
+	struct zpci_bus *zbus;
 	struct list_head entry;		/* list of all zpci_devices, needed for hotplug, etc. */
+	struct list_head bus_next;
+	struct kref kref;
+	struct hotplug_slot hotplug_slot;
 
 	enum zpci_state state;
 	u32		fid;		/* function ID, used by sclp */
@@ -107,7 +130,12 @@
 	u16		pchid;		/* physical channel ID */
 	u8		pfgid;		/* function group ID */
 	u8		pft;		/* pci function type */
-	u16		domain;
+	u8		port;
+	u8		rid_available	: 1;
+	u8		has_hp_slot	: 1;
+	u8		is_physfn	: 1;
+	u8		reserved	: 5;
+	unsigned int	devfn;		/* DEVFN part of the RID*/
 
 	struct mutex lock;
 	u8 pfip[CLP_PFIP_NR_SEGMENTS];	/* pci function internal path */
@@ -167,15 +195,19 @@
 
 extern const struct attribute_group *zpci_attr_groups[];
 extern unsigned int s390_pci_force_floating __initdata;
+extern unsigned int s390_pci_no_rid;
 
 /* -----------------------------------------------------------------------------
   Prototypes
 ----------------------------------------------------------------------------- */
 /* Base stuff */
-int zpci_create_device(struct zpci_dev *);
-void zpci_remove_device(struct zpci_dev *zdev);
+int zpci_create_device(struct zpci_dev *zdev);
+void zpci_remove_device(struct zpci_dev *zdev, bool set_error);
 int zpci_enable_device(struct zpci_dev *);
 int zpci_disable_device(struct zpci_dev *);
+void zpci_device_reserved(struct zpci_dev *zdev);
+bool zpci_is_device_configured(struct zpci_dev *zdev);
+
 int zpci_register_ioat(struct zpci_dev *, u8, u64, u64, u64);
 int zpci_unregister_ioat(struct zpci_dev *, u8);
 void zpci_remove_reserved_devices(void);
@@ -183,12 +215,15 @@
 /* CLP */
 int clp_scan_pci_devices(void);
 int clp_rescan_pci_devices(void);
-int clp_rescan_pci_devices_simple(void);
+int clp_rescan_pci_devices_simple(u32 *fid);
 int clp_add_pci_device(u32, u32, int);
 int clp_enable_fh(struct zpci_dev *, u8);
 int clp_disable_fh(struct zpci_dev *);
 int clp_get_state(u32 fid, enum zpci_state *state);
 
+/* UID */
+void update_uid_checking(bool new);
+
 /* IOMMU Interface */
 int zpci_init_iommu(struct zpci_dev *zdev);
 void zpci_destroy_iommu(struct zpci_dev *zdev);
@@ -224,7 +259,14 @@
 /* Helpers */
 static inline struct zpci_dev *to_zpci(struct pci_dev *pdev)
 {
-	return pdev->sysdata;
+	struct zpci_bus *zbus = pdev->sysdata;
+
+	return zbus->function[pdev->devfn];
+}
+
+static inline struct zpci_dev *to_zpci_dev(struct device *dev)
+{
+	return to_zpci(to_pci_dev(dev));
 }
 
 struct zpci_dev *get_zdev_by_fid(u32);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/pci_clp.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/pci_clp.h
@@ -93,7 +93,10 @@
 struct clp_rsp_query_pci {
 	struct clp_rsp_hdr hdr;
 	u16 vfn;			/* virtual fn number */
-	u16			:  6;
+	u16			:  3;
+	u16 rid_avail		:  1;
+	u16 is_physfn		:  1;
+	u16 reserved1		:  1;
 	u16 mio_addr_avail	:  1;
 	u16 util_str_avail	:  1;	/* utility string available? */
 	u16 pfgid		:  8;	/* pci function group id */
@@ -102,12 +105,16 @@
 	u16 pchid;
 	__le32 bar[PCI_BAR_COUNT];
 	u8 pfip[CLP_PFIP_NR_SEGMENTS];	/* pci function internal path */
-	u32			: 16;
+	u16			: 12;
+	u16 port		:  4;
 	u8 fmb_len;
 	u8 pft;				/* pci function type */
 	u64 sdma;			/* start dma as */
 	u64 edma;			/* end dma as */
-	u32 reserved[11];
+#define ZPCI_RID_MASK_DEVFN 0x00ff
+	u16 rid;			/* BUS/DEVFN PCI address */
+	u16 reserved0;
+	u32 reserved[10];
 	u32 uid;			/* user defined id */
 	u8 util_str[CLP_UTIL_STR_LEN];	/* utility string */
 	u32 reserved2[16];
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/pci_io.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/pci_io.h
@@ -8,14 +8,21 @@
 #include <linux/slab.h>
 #include <asm/pci_insn.h>
 
+/* I/O size constraints */
+#define ZPCI_MAX_READ_SIZE	8
+#define ZPCI_MAX_WRITE_SIZE	128
+#define ZPCI_BOUNDARY_SIZE	(1 << 12)
+#define ZPCI_BOUNDARY_MASK	(ZPCI_BOUNDARY_SIZE - 1)
+
 /* I/O Map */
 #define ZPCI_IOMAP_SHIFT		48
-#define ZPCI_IOMAP_ADDR_BASE		0x8000000000000000UL
+#define ZPCI_IOMAP_ADDR_SHIFT		62
+#define ZPCI_IOMAP_ADDR_BASE		(1UL << ZPCI_IOMAP_ADDR_SHIFT)
 #define ZPCI_IOMAP_ADDR_OFF_MASK	((1UL << ZPCI_IOMAP_SHIFT) - 1)
 #define ZPCI_IOMAP_MAX_ENTRIES							\
-	((ULONG_MAX - ZPCI_IOMAP_ADDR_BASE + 1) / (1UL << ZPCI_IOMAP_SHIFT))
+	(1UL << (ZPCI_IOMAP_ADDR_SHIFT - ZPCI_IOMAP_SHIFT))
 #define ZPCI_IOMAP_ADDR_IDX_MASK						\
-	(~ZPCI_IOMAP_ADDR_OFF_MASK - ZPCI_IOMAP_ADDR_BASE)
+	((ZPCI_IOMAP_ADDR_BASE - 1) & ~ZPCI_IOMAP_ADDR_OFF_MASK)
 
 struct zpci_iomap_entry {
 	u32 fh;
@@ -120,16 +127,18 @@
 int zpci_write_block(volatile void __iomem *dst, const void *src,
 		     unsigned long len);
 
-static inline u8 zpci_get_max_write_size(u64 src, u64 dst, int len, int max)
+static inline int zpci_get_max_io_size(u64 src, u64 dst, int len, int max)
 {
-	int count = len > max ? max : len, size = 1;
+	int offset = dst & ZPCI_BOUNDARY_MASK;
+	int size;
 
-	while (!(src & 0x1) && !(dst & 0x1) && ((size << 1) <= count)) {
-		dst = dst >> 1;
-		src = src >> 1;
-		size = size << 1;
-	}
-	return size;
+	size = min3(len, ZPCI_BOUNDARY_SIZE - offset, max);
+	if (IS_ALIGNED(src, 8) && IS_ALIGNED(dst, 8) && IS_ALIGNED(size, 8))
+		return size;
+
+	if (size >= 8)
+		return 8;
+	return rounddown_pow_of_two(size);
 }
 
 static inline int zpci_memcpy_fromio(void *dst,
@@ -139,8 +148,9 @@
 	int size, rc = 0;
 
 	while (n > 0) {
-		size = zpci_get_max_write_size((u64 __force) src,
-					       (u64) dst, n, 8);
+		size = zpci_get_max_io_size((u64 __force) src,
+					    (u64) dst, n,
+					    ZPCI_MAX_READ_SIZE);
 		rc = zpci_read_single(dst, src, size);
 		if (rc)
 			break;
@@ -160,8 +170,9 @@
 		return -EINVAL;
 
 	while (n > 0) {
-		size = zpci_get_max_write_size((u64 __force) dst,
-					       (u64) src, n, 128);
+		size = zpci_get_max_io_size((u64 __force) dst,
+					    (u64) src, n,
+					    ZPCI_MAX_WRITE_SIZE);
 		if (size > 8) /* main path */
 			rc = zpci_write_block(dst, src, size);
 		else
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/percpu.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/percpu.h
@@ -29,15 +29,15 @@
 	typedef typeof(pcp) pcp_op_T__;					\
 	pcp_op_T__ old__, new__, prev__;				\
 	pcp_op_T__ *ptr__;						\
-	preempt_disable();						\
+	preempt_disable_notrace();					\
 	ptr__ = raw_cpu_ptr(&(pcp));					\
-	prev__ = *ptr__;						\
+	prev__ = READ_ONCE(*ptr__);					\
 	do {								\
 		old__ = prev__;						\
 		new__ = old__ op (val);					\
 		prev__ = cmpxchg(ptr__, old__, new__);			\
 	} while (prev__ != old__);					\
-	preempt_enable();						\
+	preempt_enable_notrace();					\
 	new__;								\
 })
 
@@ -68,7 +68,7 @@
 	typedef typeof(pcp) pcp_op_T__; 				\
 	pcp_op_T__ val__ = (val);					\
 	pcp_op_T__ old__, *ptr__;					\
-	preempt_disable();						\
+	preempt_disable_notrace();					\
 	ptr__ = raw_cpu_ptr(&(pcp)); 				\
 	if (__builtin_constant_p(val__) &&				\
 	    ((szcast)val__ > -129) && ((szcast)val__ < 128)) {		\
@@ -84,7 +84,7 @@
 			: [val__] "d" (val__)				\
 			: "cc");					\
 	}								\
-	preempt_enable();						\
+	preempt_enable_notrace();					\
 }
 
 #define this_cpu_add_4(pcp, val) arch_this_cpu_add(pcp, val, "laa", "asi", int)
@@ -95,14 +95,14 @@
 	typedef typeof(pcp) pcp_op_T__; 				\
 	pcp_op_T__ val__ = (val);					\
 	pcp_op_T__ old__, *ptr__;					\
-	preempt_disable();						\
+	preempt_disable_notrace();					\
 	ptr__ = raw_cpu_ptr(&(pcp));	 				\
 	asm volatile(							\
 		op "    %[old__],%[val__],%[ptr__]\n"			\
 		: [old__] "=d" (old__), [ptr__] "+Q" (*ptr__)		\
 		: [val__] "d" (val__)					\
 		: "cc");						\
-	preempt_enable();						\
+	preempt_enable_notrace();						\
 	old__ + val__;							\
 })
 
@@ -114,14 +114,14 @@
 	typedef typeof(pcp) pcp_op_T__; 				\
 	pcp_op_T__ val__ = (val);					\
 	pcp_op_T__ old__, *ptr__;					\
-	preempt_disable();						\
+	preempt_disable_notrace();					\
 	ptr__ = raw_cpu_ptr(&(pcp));	 				\
 	asm volatile(							\
 		op "    %[old__],%[val__],%[ptr__]\n"			\
 		: [old__] "=d" (old__), [ptr__] "+Q" (*ptr__)		\
 		: [val__] "d" (val__)					\
 		: "cc");						\
-	preempt_enable();						\
+	preempt_enable_notrace();					\
 }
 
 #define this_cpu_and_4(pcp, val)	arch_this_cpu_to_op(pcp, val, "lan")
@@ -136,10 +136,10 @@
 	typedef typeof(pcp) pcp_op_T__;					\
 	pcp_op_T__ ret__;						\
 	pcp_op_T__ *ptr__;						\
-	preempt_disable();						\
+	preempt_disable_notrace();					\
 	ptr__ = raw_cpu_ptr(&(pcp));					\
 	ret__ = cmpxchg(ptr__, oval, nval);				\
-	preempt_enable();						\
+	preempt_enable_notrace();					\
 	ret__;								\
 })
 
@@ -152,10 +152,10 @@
 ({									\
 	typeof(pcp) *ptr__;						\
 	typeof(pcp) ret__;						\
-	preempt_disable();						\
+	preempt_disable_notrace();					\
 	ptr__ = raw_cpu_ptr(&(pcp));					\
 	ret__ = xchg(ptr__, nval);					\
-	preempt_enable();						\
+	preempt_enable_notrace();					\
 	ret__;								\
 })
 
@@ -171,11 +171,11 @@
 	typeof(pcp1) *p1__;						\
 	typeof(pcp2) *p2__;						\
 	int ret__;							\
-	preempt_disable();						\
+	preempt_disable_notrace();					\
 	p1__ = raw_cpu_ptr(&(pcp1));					\
 	p2__ = raw_cpu_ptr(&(pcp2));					\
 	ret__ = __cmpxchg_double(p1__, p2__, o1__, o2__, n1__, n2__);	\
-	preempt_enable();						\
+	preempt_enable_notrace();					\
 	ret__;								\
 })
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/pgalloc.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/pgalloc.h
@@ -56,7 +56,12 @@
 		crst_table_init(table, _REGION2_ENTRY_EMPTY);
 	return (p4d_t *) table;
 }
-#define p4d_free(mm, p4d) crst_table_free(mm, (unsigned long *) p4d)
+
+static inline void p4d_free(struct mm_struct *mm, p4d_t *p4d)
+{
+	if (!mm_p4d_folded(mm))
+		crst_table_free(mm, (unsigned long *) p4d);
+}
 
 static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address)
 {
@@ -65,7 +70,12 @@
 		crst_table_init(table, _REGION3_ENTRY_EMPTY);
 	return (pud_t *) table;
 }
-#define pud_free(mm, pud) crst_table_free(mm, (unsigned long *) pud)
+
+static inline void pud_free(struct mm_struct *mm, pud_t *pud)
+{
+	if (!mm_pud_folded(mm))
+		crst_table_free(mm, (unsigned long *) pud);
+}
 
 static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr)
 {
@@ -83,6 +93,8 @@
 
 static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
 {
+	if (mm_pmd_folded(mm))
+		return;
 	pgtable_pmd_page_dtor(virt_to_page(pmd));
 	crst_table_free(mm, (unsigned long *) pmd);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/pgtable.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/pgtable.h
@@ -19,6 +19,7 @@
 #include <linux/atomic.h>
 #include <asm/bug.h>
 #include <asm/page.h>
+#include <asm/uv.h>
 
 extern pgd_t swapper_pg_dir[];
 extern void paging_init(void);
@@ -522,6 +523,15 @@
 	return 0;
 }
 
+static inline int mm_is_protected(struct mm_struct *mm)
+{
+#ifdef CONFIG_PGSTE
+	if (unlikely(atomic_read(&mm->context.is_protected)))
+		return 1;
+#endif
+	return 0;
+}
+
 static inline int mm_alloc_pgste(struct mm_struct *mm)
 {
 #ifdef CONFIG_PGSTE
@@ -756,6 +766,12 @@
 	return (pmd_val(pmd) & _SEGMENT_ENTRY_WRITE) != 0;
 }
 
+#define pud_write pud_write
+static inline int pud_write(pud_t pud)
+{
+	return (pud_val(pud) & _REGION3_ENTRY_WRITE) != 0;
+}
+
 static inline int pmd_dirty(pmd_t pmd)
 {
 	int dirty = 1;
@@ -1071,7 +1087,12 @@
 static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
 				       unsigned long addr, pte_t *ptep)
 {
-	return ptep_xchg_lazy(mm, addr, ptep, __pte(_PAGE_INVALID));
+	pte_t res;
+
+	res = ptep_xchg_lazy(mm, addr, ptep, __pte(_PAGE_INVALID));
+	if (mm_is_protected(mm) && pte_present(res))
+		uv_convert_from_secure(pte_val(res) & PAGE_MASK);
+	return res;
 }
 
 #define __HAVE_ARCH_PTEP_MODIFY_PROT_TRANSACTION
@@ -1083,7 +1104,12 @@
 static inline pte_t ptep_clear_flush(struct vm_area_struct *vma,
 				     unsigned long addr, pte_t *ptep)
 {
-	return ptep_xchg_direct(vma->vm_mm, addr, ptep, __pte(_PAGE_INVALID));
+	pte_t res;
+
+	res = ptep_xchg_direct(vma->vm_mm, addr, ptep, __pte(_PAGE_INVALID));
+	if (mm_is_protected(vma->vm_mm) && pte_present(res))
+		uv_convert_from_secure(pte_val(res) & PAGE_MASK);
+	return res;
 }
 
 /*
@@ -1098,12 +1124,17 @@
 					    unsigned long addr,
 					    pte_t *ptep, int full)
 {
+	pte_t res;
+
 	if (full) {
-		pte_t pte = *ptep;
+		res = *ptep;
 		*ptep = __pte(_PAGE_INVALID);
-		return pte;
+	} else {
+		res = ptep_xchg_lazy(mm, addr, ptep, __pte(_PAGE_INVALID));
 	}
-	return ptep_xchg_lazy(mm, addr, ptep, __pte(_PAGE_INVALID));
+	if (mm_is_protected(mm) && pte_present(res))
+		uv_convert_from_secure(pte_val(res) & PAGE_MASK);
+	return res;
 }
 
 #define __HAVE_ARCH_PTEP_SET_WRPROTECT
@@ -1173,8 +1204,6 @@
 static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
 			      pte_t *ptep, pte_t entry)
 {
-	if (!MACHINE_HAS_NX)
-		pte_val(entry) &= ~_PAGE_NOEXEC;
 	if (pte_present(entry))
 		pte_val(entry) &= ~_PAGE_UNUSED;
 	if (mm_has_pgste(mm))
@@ -1191,6 +1220,8 @@
 {
 	pte_t __pte;
 	pte_val(__pte) = physpage + pgprot_val(pgprot);
+	if (!MACHINE_HAS_NX)
+		pte_val(__pte) &= ~_PAGE_NOEXEC;
 	return pte_mkyoung(__pte);
 }
 
@@ -1241,26 +1272,46 @@
 #define pgd_offset(mm, address) pgd_offset_raw(READ_ONCE((mm)->pgd), address)
 #define pgd_offset_k(address) pgd_offset(&init_mm, address)
 
-static inline p4d_t *p4d_offset(pgd_t *pgd, unsigned long address)
+static inline p4d_t *p4d_offset_lockless(pgd_t *pgdp, pgd_t pgd, unsigned long address)
+{
+	if ((pgd_val(pgd) & _REGION_ENTRY_TYPE_MASK) >= _REGION_ENTRY_TYPE_R1)
+		return (p4d_t *) pgd_deref(pgd) + p4d_index(address);
+	return (p4d_t *) pgdp;
+}
+#define p4d_offset_lockless p4d_offset_lockless
+
+static inline p4d_t *p4d_offset(pgd_t *pgdp, unsigned long address)
+{
+	return p4d_offset_lockless(pgdp, *pgdp, address);
+}
+
+static inline pud_t *pud_offset_lockless(p4d_t *p4dp, p4d_t p4d, unsigned long address)
+{
+	if ((p4d_val(p4d) & _REGION_ENTRY_TYPE_MASK) >= _REGION_ENTRY_TYPE_R2)
+		return (pud_t *) p4d_deref(p4d) + pud_index(address);
+	return (pud_t *) p4dp;
+}
+#define pud_offset_lockless pud_offset_lockless
+
+static inline pud_t *pud_offset(p4d_t *p4dp, unsigned long address)
 {
-	if ((pgd_val(*pgd) & _REGION_ENTRY_TYPE_MASK) >= _REGION_ENTRY_TYPE_R1)
-		return (p4d_t *) pgd_deref(*pgd) + p4d_index(address);
-	return (p4d_t *) pgd;
+	return pud_offset_lockless(p4dp, *p4dp, address);
 }
+#define pud_offset pud_offset
 
-static inline pud_t *pud_offset(p4d_t *p4d, unsigned long address)
+static inline pmd_t *pmd_offset_lockless(pud_t *pudp, pud_t pud, unsigned long address)
 {
-	if ((p4d_val(*p4d) & _REGION_ENTRY_TYPE_MASK) >= _REGION_ENTRY_TYPE_R2)
-		return (pud_t *) p4d_deref(*p4d) + pud_index(address);
-	return (pud_t *) p4d;
+	if ((pud_val(pud) & _REGION_ENTRY_TYPE_MASK) >= _REGION_ENTRY_TYPE_R3)
+		return (pmd_t *) pud_deref(pud) + pmd_index(address);
+	return (pmd_t *) pudp;
 }
+#define pmd_offset_lockless pmd_offset_lockless
 
-static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address)
+static inline pmd_t *pmd_offset(pud_t *pudp, unsigned long address)
 {
-	if ((pud_val(*pud) & _REGION_ENTRY_TYPE_MASK) >= _REGION_ENTRY_TYPE_R3)
-		return (pmd_t *) pud_deref(*pud) + pmd_index(address);
-	return (pmd_t *) pud;
+	return pmd_offset_lockless(pudp, *pudp, address);
 }
+#define pmd_offset pmd_offset
 
 static inline pte_t *pte_offset(pmd_t *pmd, unsigned long address)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/preempt.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/preempt.h
@@ -52,10 +52,17 @@
 
 static inline void __preempt_count_add(int val)
 {
-	if (__builtin_constant_p(val) && (val >= -128) && (val <= 127))
-		__atomic_add_const(val, &S390_lowcore.preempt_count);
-	else
-		__atomic_add(val, &S390_lowcore.preempt_count);
+	/*
+	 * With some obscure config options and CONFIG_PROFILE_ALL_BRANCHES
+	 * enabled, gcc 12 fails to handle __builtin_constant_p().
+	 */
+	if (!IS_ENABLED(CONFIG_PROFILE_ALL_BRANCHES)) {
+		if (__builtin_constant_p(val) && (val >= -128) && (val <= 127)) {
+			__atomic_add_const(val, &S390_lowcore.preempt_count);
+			return;
+		}
+	}
+	__atomic_add(val, &S390_lowcore.preempt_count);
 }
 
 static inline void __preempt_count_sub(int val)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/processor.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/processor.h
@@ -162,6 +162,7 @@
 #define INIT_THREAD {							\
 	.ksp = sizeof(init_stack) + (unsigned long) &init_stack,	\
 	.fpu.regs = (void *) init_task.thread.fpu.fprs,			\
+	.last_break = 1,						\
 }
 
 /*
@@ -214,7 +215,7 @@
 	return sp;
 }
 
-static __no_kasan_or_inline unsigned short stap(void)
+static __always_inline unsigned short stap(void)
 {
 	unsigned short cpu_address;
 
@@ -253,10 +254,10 @@
  * Set PSW mask to specified value, while leaving the
  * PSW addr pointing to the next instruction.
  */
-static __no_kasan_or_inline void __load_psw_mask(unsigned long mask)
+static __always_inline void __load_psw_mask(unsigned long mask)
 {
+	psw_t psw __uninitialized;
 	unsigned long addr;
-	psw_t psw;
 
 	psw.mask = mask;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/qdio.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/qdio.h
@@ -227,7 +227,7 @@
  * @sbal: absolute SBAL address
  */
 struct sl_element {
-	unsigned long sbal;
+	u64 sbal;
 } __attribute__ ((packed));
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/sclp.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/sclp.h
@@ -129,6 +129,8 @@
 int sclp_chp_read_info(struct sclp_chp_info *info);
 int sclp_pci_configure(u32 fid);
 int sclp_pci_deconfigure(u32 fid);
+int sclp_ap_configure(u32 apid);
+int sclp_ap_deconfigure(u32 apid);
 int sclp_pci_report(struct zpci_report_error_header *report, u32 fh, u32 fid);
 int memcpy_hsa_kernel(void *dest, unsigned long src, size_t count);
 int memcpy_hsa_user(void __user *dest, unsigned long src, size_t count);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/setup.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/setup.h
@@ -8,6 +8,7 @@
 
 #include <linux/bits.h>
 #include <uapi/asm/setup.h>
+#include <linux/build_bug.h>
 
 #define EP_OFFSET		0x10008
 #define EP_STRING		"S390EP"
@@ -38,6 +39,7 @@
 #define MACHINE_FLAG_NX		BIT(15)
 #define MACHINE_FLAG_GS		BIT(16)
 #define MACHINE_FLAG_SCC	BIT(17)
+#define MACHINE_FLAG_PCI_MIO	BIT(18)
 
 #define LPP_MAGIC		BIT(31)
 #define LPP_PID_MASK		_AC(0xffffffff, UL)
@@ -80,6 +82,13 @@
 	char command_line[ARCH_COMMAND_LINE_SIZE];	/* 0x10480 */
 };
 
+extern unsigned int zlib_dfltcc_support;
+#define ZLIB_DFLTCC_DISABLED		0
+#define ZLIB_DFLTCC_FULL		1
+#define ZLIB_DFLTCC_DEFLATE_ONLY	2
+#define ZLIB_DFLTCC_INFLATE_ONLY	3
+#define ZLIB_DFLTCC_FULL_DEBUG		4
+
 extern int noexec_disabled;
 extern int memory_end_set;
 extern unsigned long memory_end;
@@ -105,6 +114,7 @@
 #define MACHINE_HAS_NX		(S390_lowcore.machine_flags & MACHINE_FLAG_NX)
 #define MACHINE_HAS_GS		(S390_lowcore.machine_flags & MACHINE_FLAG_GS)
 #define MACHINE_HAS_SCC		(S390_lowcore.machine_flags & MACHINE_FLAG_SCC)
+#define MACHINE_HAS_PCI_MIO	(S390_lowcore.machine_flags & MACHINE_FLAG_PCI_MIO)
 
 /*
  * Console mode. Override with conmode=
@@ -157,6 +167,12 @@
 	return __kaslr_offset;
 }
 
+static inline u32 gen_lpswe(unsigned long addr)
+{
+	BUILD_BUG_ON(addr > 0xfff);
+	return 0xb2b20000 | addr;
+}
+
 #else /* __ASSEMBLY__ */
 
 #define IPL_DEVICE	(IPL_DEVICE_OFFSET)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/stacktrace.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/stacktrace.h
@@ -79,12 +79,16 @@
 	CALL_ARGS_4(arg1, arg2, arg3, arg4);				\
 	register unsigned long r4 asm("6") = (unsigned long)(arg5)
 
-#define CALL_FMT_0 "=&d" (r2) :
-#define CALL_FMT_1 "+&d" (r2) :
-#define CALL_FMT_2 CALL_FMT_1 "d" (r3),
-#define CALL_FMT_3 CALL_FMT_2 "d" (r4),
-#define CALL_FMT_4 CALL_FMT_3 "d" (r5),
-#define CALL_FMT_5 CALL_FMT_4 "d" (r6),
+/*
+ * To keep this simple mark register 2-6 as being changed (volatile)
+ * by the called function, even though register 6 is saved/nonvolatile.
+ */
+#define CALL_FMT_0 "=&d" (r2)
+#define CALL_FMT_1 "+&d" (r2)
+#define CALL_FMT_2 CALL_FMT_1, "+&d" (r3)
+#define CALL_FMT_3 CALL_FMT_2, "+&d" (r4)
+#define CALL_FMT_4 CALL_FMT_3, "+&d" (r5)
+#define CALL_FMT_5 CALL_FMT_4, "+&d" (r6)
 
 #define CALL_CLOBBER_5 "0", "1", "14", "cc", "memory"
 #define CALL_CLOBBER_4 CALL_CLOBBER_5
@@ -105,10 +109,118 @@
 		"	brasl	14,%[_fn]\n"				\
 		"	la	15,0(%[_prev])\n"			\
 		: [_prev] "=&a" (prev), CALL_FMT_##nr			\
-		  [_stack] "a" (stack),					\
+		: [_stack] "a" (stack),					\
 		  [_bc] "i" (offsetof(struct stack_frame, back_chain)),	\
 		  [_fn] "X" (fn) : CALL_CLOBBER_##nr);			\
 	r2;								\
 })
 
+#define CALL_LARGS_0(...)						\
+	long dummy = 0
+#define CALL_LARGS_1(t1, a1)						\
+	long arg1  = (long)(t1)(a1)
+#define CALL_LARGS_2(t1, a1, t2, a2)					\
+	CALL_LARGS_1(t1, a1);						\
+	long arg2 = (long)(t2)(a2)
+#define CALL_LARGS_3(t1, a1, t2, a2, t3, a3)				\
+	CALL_LARGS_2(t1, a1, t2, a2);					\
+	long arg3 = (long)(t3)(a3)
+#define CALL_LARGS_4(t1, a1, t2, a2, t3, a3, t4, a4)			\
+	CALL_LARGS_3(t1, a1, t2, a2, t3, a3);				\
+	long arg4  = (long)(t4)(a4)
+#define CALL_LARGS_5(t1, a1, t2, a2, t3, a3, t4, a4, t5, a5)		\
+	CALL_LARGS_4(t1, a1, t2, a2, t3, a3, t4, a4);			\
+	long arg5 = (long)(t5)(a5)
+
+#define CALL_REGS_0							\
+	register long r2 asm("2") = dummy
+#define CALL_REGS_1							\
+	register long r2 asm("2") = arg1
+#define CALL_REGS_2							\
+	CALL_REGS_1;							\
+	register long r3 asm("3") = arg2
+#define CALL_REGS_3							\
+	CALL_REGS_2;							\
+	register long r4 asm("4") = arg3
+#define CALL_REGS_4							\
+	CALL_REGS_3;							\
+	register long r5 asm("5") = arg4
+#define CALL_REGS_5							\
+	CALL_REGS_4;							\
+	register long r6 asm("6") = arg5
+
+#define CALL_TYPECHECK_0(...)
+#define CALL_TYPECHECK_1(t, a, ...)					\
+	typecheck(t, a)
+#define CALL_TYPECHECK_2(t, a, ...)					\
+	CALL_TYPECHECK_1(__VA_ARGS__);					\
+	typecheck(t, a)
+#define CALL_TYPECHECK_3(t, a, ...)					\
+	CALL_TYPECHECK_2(__VA_ARGS__);					\
+	typecheck(t, a)
+#define CALL_TYPECHECK_4(t, a, ...)					\
+	CALL_TYPECHECK_3(__VA_ARGS__);					\
+	typecheck(t, a)
+#define CALL_TYPECHECK_5(t, a, ...)					\
+	CALL_TYPECHECK_4(__VA_ARGS__);					\
+	typecheck(t, a)
+
+#define CALL_PARM_0(...) void
+#define CALL_PARM_1(t, a, ...) t
+#define CALL_PARM_2(t, a, ...) t, CALL_PARM_1(__VA_ARGS__)
+#define CALL_PARM_3(t, a, ...) t, CALL_PARM_2(__VA_ARGS__)
+#define CALL_PARM_4(t, a, ...) t, CALL_PARM_3(__VA_ARGS__)
+#define CALL_PARM_5(t, a, ...) t, CALL_PARM_4(__VA_ARGS__)
+#define CALL_PARM_6(t, a, ...) t, CALL_PARM_5(__VA_ARGS__)
+
+/*
+ * Use call_on_stack() to call a function switching to a specified
+ * stack. Proper sign and zero extension of function arguments is
+ * done. Usage:
+ *
+ * rc = call_on_stack(nr, stack, rettype, fn, t1, a1, t2, a2, ...)
+ *
+ * - nr specifies the number of function arguments of fn.
+ * - stack specifies the stack to be used.
+ * - fn is the function to be called.
+ * - rettype is the return type of fn.
+ * - t1, a1, ... are pairs, where t1 must match the type of the first
+ *   argument of fn, t2 the second, etc. a1 is the corresponding
+ *   first function argument (not name), etc.
+ */
+#define call_on_stack(nr, stack, rettype, fn, ...)			\
+({									\
+	rettype (*__fn)(CALL_PARM_##nr(__VA_ARGS__)) = fn;		\
+	unsigned long frame = current_frame_address();			\
+	unsigned long __stack = stack;					\
+	unsigned long prev;						\
+	CALL_LARGS_##nr(__VA_ARGS__);					\
+	CALL_REGS_##nr;							\
+									\
+	CALL_TYPECHECK_##nr(__VA_ARGS__);				\
+	asm volatile(							\
+		"	lgr	%[_prev],15\n"				\
+		"	lg	15,%[_stack]\n"				\
+		"	stg	%[_frame],%[_bc](15)\n"			\
+		"	brasl	14,%[_fn]\n"				\
+		"	lgr	15,%[_prev]\n"				\
+		: [_prev] "=&d" (prev), CALL_FMT_##nr			\
+		: [_stack] "R" (__stack),				\
+		  [_bc] "i" (offsetof(struct stack_frame, back_chain)),	\
+		  [_frame] "d" (frame),					\
+		  [_fn] "X" (__fn) : CALL_CLOBBER_##nr);		\
+	(rettype)r2;							\
+})
+
+#define CALL_ON_STACK_NORETURN(fn, stack)				\
+({									\
+	asm volatile(							\
+		"	la	15,0(%[_stack])\n"			\
+		"	xc	%[_bc](8,15),%[_bc](15)\n"		\
+		"	brasl	14,%[_fn]\n"				\
+		::[_bc] "i" (offsetof(struct stack_frame, back_chain)),	\
+		  [_stack] "a" (stack), [_fn] "X" (fn));		\
+	BUG();								\
+})
+
 #endif /* _ASM_S390_STACKTRACE_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/syscall.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/syscall.h
@@ -33,7 +33,17 @@
 static inline long syscall_get_error(struct task_struct *task,
 				     struct pt_regs *regs)
 {
-	return IS_ERR_VALUE(regs->gprs[2]) ? regs->gprs[2] : 0;
+	unsigned long error = regs->gprs[2];
+#ifdef CONFIG_COMPAT
+	if (test_tsk_thread_flag(task, TIF_31BIT)) {
+		/*
+		 * Sign-extend the value so (int)-EFOO becomes (long)-EFOO
+		 * and will match correctly in comparisons.
+		 */
+		error = (long)(int)error;
+	}
+#endif
+	return IS_ERR_VALUE(error) ? error : 0;
 }
 
 static inline long syscall_get_return_value(struct task_struct *task,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/timex.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/timex.h
@@ -10,8 +10,9 @@
 #ifndef _ASM_S390_TIMEX_H
 #define _ASM_S390_TIMEX_H
 
-#include <asm/lowcore.h>
+#include <linux/preempt.h>
 #include <linux/time64.h>
+#include <asm/lowcore.h>
 
 /* The value of the TOD clock for 1.1.1970. */
 #define TOD_UNIX_EPOCH 0x7d91048bca000000ULL
@@ -154,7 +155,7 @@
 
 static inline unsigned long long get_tod_clock(void)
 {
-	unsigned char clk[STORE_CLOCK_EXT_SIZE];
+	char clk[STORE_CLOCK_EXT_SIZE];
 
 	get_tod_clock_ext(clk);
 	return *((unsigned long long *)&clk[1]);
@@ -176,6 +177,7 @@
 {
 	return (cycles_t) get_tod_clock() >> 2;
 }
+#define get_cycles get_cycles
 
 int get_phys_clock(unsigned long *clock);
 void init_cpu_timer(void);
@@ -186,15 +188,18 @@
 /**
  * get_clock_monotonic - returns current time in clock rate units
  *
- * The caller must ensure that preemption is disabled.
  * The clock and tod_clock_base get changed via stop_machine.
- * Therefore preemption must be disabled when calling this
- * function, otherwise the returned value is not guaranteed to
- * be monotonic.
+ * Therefore preemption must be disabled, otherwise the returned
+ * value is not guaranteed to be monotonic.
  */
 static inline unsigned long long get_tod_clock_monotonic(void)
 {
-	return get_tod_clock() - *(unsigned long long *) &tod_clock_base[1];
+	unsigned long long tod;
+
+	preempt_disable_notrace();
+	tod = get_tod_clock() - *(unsigned long long *) &tod_clock_base[1];
+	preempt_enable_notrace();
+	return tod;
 }
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/topology.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/topology.h
@@ -68,11 +68,8 @@
 
 #ifdef CONFIG_NUMA
 
-#define cpu_to_node cpu_to_node
-static inline int cpu_to_node(int cpu)
-{
-	return cpu_topology[cpu].node_id;
-}
+extern int __cpu_to_node(int cpu);
+#define cpu_to_node __cpu_to_node
 
 /* Returns a pointer to the cpumask of CPUs on node 'node'. */
 #define cpumask_of_node cpumask_of_node
@@ -83,8 +80,6 @@
 
 #define pcibus_to_node(bus) __pcibus_to_node(bus)
 
-#define node_distance(a, b) __node_distance(a, b)
-
 #else /* !CONFIG_NUMA */
 
 #define numa_node_id numa_node_id
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/uaccess.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/uaccess.h
@@ -60,54 +60,109 @@
 #define INLINE_COPY_TO_USER
 #endif
 
+unsigned long __must_check
+_copy_from_user_key(void *to, const void __user *from, unsigned long n, unsigned long key);
+
+static __always_inline unsigned long __must_check
+copy_from_user_key(void *to, const void __user *from, unsigned long n, unsigned long key)
+{
+	if (likely(check_copy_size(to, n, false)))
+		n = _copy_from_user_key(to, from, n, key);
+	return n;
+}
+
+unsigned long __must_check
+_copy_to_user_key(void __user *to, const void *from, unsigned long n, unsigned long key);
+
+static __always_inline unsigned long __must_check
+copy_to_user_key(void __user *to, const void *from, unsigned long n, unsigned long key)
+{
+	if (likely(check_copy_size(from, n, true)))
+		n = _copy_to_user_key(to, from, n, key);
+	return n;
+}
+
+union oac {
+	unsigned int val;
+	struct {
+		struct {
+			unsigned short key : 4;
+			unsigned short	   : 4;
+			unsigned short as  : 2;
+			unsigned short	   : 4;
+			unsigned short k   : 1;
+			unsigned short a   : 1;
+		} oac1;
+		struct {
+			unsigned short key : 4;
+			unsigned short	   : 4;
+			unsigned short as  : 2;
+			unsigned short	   : 4;
+			unsigned short k   : 1;
+			unsigned short a   : 1;
+		} oac2;
+	};
+};
+
 #ifdef CONFIG_HAVE_MARCH_Z10_FEATURES
 
-#define __put_get_user_asm(to, from, size, spec)		\
-({								\
-	register unsigned long __reg0 asm("0") = spec;		\
-	int __rc;						\
-								\
-	asm volatile(						\
-		"0:	mvcos	%1,%3,%2\n"			\
-		"1:	xr	%0,%0\n"			\
-		"2:\n"						\
-		".pushsection .fixup, \"ax\"\n"			\
-		"3:	lhi	%0,%5\n"			\
-		"	jg	2b\n"				\
-		".popsection\n"					\
-		EX_TABLE(0b,3b) EX_TABLE(1b,3b)			\
-		: "=d" (__rc), "+Q" (*(to))			\
-		: "d" (size), "Q" (*(from)),			\
-		  "d" (__reg0), "K" (-EFAULT)			\
-		: "cc");					\
-	__rc;							\
+#define __put_get_user_asm(to, from, size, oac_spec)			\
+({									\
+	int __rc;							\
+									\
+	asm volatile(							\
+		"	lr	0,%[spec]\n"				\
+		"0:	mvcos	%[_to],%[_from],%[_size]\n"		\
+		"1:	xr	%[rc],%[rc]\n"				\
+		"2:\n"							\
+		".pushsection .fixup, \"ax\"\n"				\
+		"3:	lhi	%[rc],%[retval]\n"			\
+		"	jg	2b\n"					\
+		".popsection\n"						\
+		EX_TABLE(0b,3b) EX_TABLE(1b,3b)				\
+		: [rc] "=&d" (__rc), [_to] "+Q" (*(to))			\
+		: [_size] "d" (size), [_from] "Q" (*(from)),		\
+		  [retval] "K" (-EFAULT), [spec] "d" (oac_spec.val)	\
+		: "cc", "0");						\
+	__rc;								\
 })
 
+#define __put_user_asm(to, from, size)				\
+	__put_get_user_asm(to, from, size, ((union oac) {	\
+		.oac1.as = PSW_BITS_AS_PRIMARY,			\
+		.oac1.a = 1					\
+	}))
+
+#define __get_user_asm(to, from, size)				\
+	__put_get_user_asm(to, from, size, ((union oac) {	\
+		.oac2.as = PSW_BITS_AS_PRIMARY,			\
+		.oac2.a = 1					\
+	}))							\
+
 static __always_inline int __put_user_fn(void *x, void __user *ptr, unsigned long size)
 {
-	unsigned long spec = 0x010000UL;
 	int rc;
 
 	switch (size) {
 	case 1:
-		rc = __put_get_user_asm((unsigned char __user *)ptr,
-					(unsigned char *)x,
-					size, spec);
+		rc = __put_user_asm((unsigned char __user *)ptr,
+				    (unsigned char *)x,
+				    size);
 		break;
 	case 2:
-		rc = __put_get_user_asm((unsigned short __user *)ptr,
-					(unsigned short *)x,
-					size, spec);
+		rc = __put_user_asm((unsigned short __user *)ptr,
+				    (unsigned short *)x,
+				    size);
 		break;
 	case 4:
-		rc = __put_get_user_asm((unsigned int __user *)ptr,
-					(unsigned int *)x,
-					size, spec);
+		rc = __put_user_asm((unsigned int __user *)ptr,
+				    (unsigned int *)x,
+				    size);
 		break;
 	case 8:
-		rc = __put_get_user_asm((unsigned long __user *)ptr,
-					(unsigned long *)x,
-					size, spec);
+		rc = __put_user_asm((unsigned long __user *)ptr,
+				    (unsigned long *)x,
+				    size);
 		break;
 	}
 	return rc;
@@ -115,29 +170,28 @@
 
 static __always_inline int __get_user_fn(void *x, const void __user *ptr, unsigned long size)
 {
-	unsigned long spec = 0x01UL;
 	int rc;
 
 	switch (size) {
 	case 1:
-		rc = __put_get_user_asm((unsigned char *)x,
-					(unsigned char __user *)ptr,
-					size, spec);
+		rc = __get_user_asm((unsigned char *)x,
+				    (unsigned char __user *)ptr,
+				    size);
 		break;
 	case 2:
-		rc = __put_get_user_asm((unsigned short *)x,
-					(unsigned short __user *)ptr,
-					size, spec);
+		rc = __get_user_asm((unsigned short *)x,
+				    (unsigned short __user *)ptr,
+				    size);
 		break;
 	case 4:
-		rc = __put_get_user_asm((unsigned int *)x,
-					(unsigned int __user *)ptr,
-					size, spec);
+		rc = __get_user_asm((unsigned int *)x,
+				    (unsigned int __user *)ptr,
+				    size);
 		break;
 	case 8:
-		rc = __put_get_user_asm((unsigned long *)x,
-					(unsigned long __user *)ptr,
-					size, spec);
+		rc = __get_user_asm((unsigned long *)x,
+				    (unsigned long __user *)ptr,
+				    size);
 		break;
 	}
 	return rc;
@@ -276,6 +330,6 @@
 }
 
 int copy_to_user_real(void __user *dest, void *src, unsigned long count);
-void s390_kernel_write(void *dst, const void *src, size_t size);
+void *s390_kernel_write(void *dst, const void *src, size_t size);
 
 #endif /* __S390_UACCESS_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/uv.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/uv.h
@@ -14,23 +14,67 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/bug.h>
+#include <linux/sched.h>
 #include <asm/page.h>
+#include <asm/gmap.h>
+
+#define UVC_CC_OK	0
+#define UVC_CC_ERROR	1
+#define UVC_CC_BUSY	2
+#define UVC_CC_PARTIAL	3
 
 #define UVC_RC_EXECUTED		0x0001
 #define UVC_RC_INV_CMD		0x0002
 #define UVC_RC_INV_STATE	0x0003
 #define UVC_RC_INV_LEN		0x0005
 #define UVC_RC_NO_RESUME	0x0007
+#define UVC_RC_NEED_DESTROY	0x8000
 
 #define UVC_CMD_QUI			0x0001
+#define UVC_CMD_INIT_UV			0x000f
+#define UVC_CMD_CREATE_SEC_CONF		0x0100
+#define UVC_CMD_DESTROY_SEC_CONF	0x0101
+#define UVC_CMD_CREATE_SEC_CPU		0x0120
+#define UVC_CMD_DESTROY_SEC_CPU		0x0121
+#define UVC_CMD_CONV_TO_SEC_STOR	0x0200
+#define UVC_CMD_CONV_FROM_SEC_STOR	0x0201
+#define UVC_CMD_SET_SEC_CONF_PARAMS	0x0300
+#define UVC_CMD_UNPACK_IMG		0x0301
+#define UVC_CMD_VERIFY_IMG		0x0302
+#define UVC_CMD_CPU_RESET		0x0310
+#define UVC_CMD_CPU_RESET_INITIAL	0x0311
+#define UVC_CMD_PREPARE_RESET		0x0320
+#define UVC_CMD_CPU_RESET_CLEAR		0x0321
+#define UVC_CMD_CPU_SET_STATE		0x0330
+#define UVC_CMD_SET_UNSHARE_ALL		0x0340
+#define UVC_CMD_PIN_PAGE_SHARED		0x0341
+#define UVC_CMD_UNPIN_PAGE_SHARED	0x0342
 #define UVC_CMD_SET_SHARED_ACCESS	0x1000
 #define UVC_CMD_REMOVE_SHARED_ACCESS	0x1001
 
 /* Bits in installed uv calls */
 enum uv_cmds_inst {
 	BIT_UVC_CMD_QUI = 0,
+	BIT_UVC_CMD_INIT_UV = 1,
+	BIT_UVC_CMD_CREATE_SEC_CONF = 2,
+	BIT_UVC_CMD_DESTROY_SEC_CONF = 3,
+	BIT_UVC_CMD_CREATE_SEC_CPU = 4,
+	BIT_UVC_CMD_DESTROY_SEC_CPU = 5,
+	BIT_UVC_CMD_CONV_TO_SEC_STOR = 6,
+	BIT_UVC_CMD_CONV_FROM_SEC_STOR = 7,
 	BIT_UVC_CMD_SET_SHARED_ACCESS = 8,
 	BIT_UVC_CMD_REMOVE_SHARED_ACCESS = 9,
+	BIT_UVC_CMD_SET_SEC_PARMS = 11,
+	BIT_UVC_CMD_UNPACK_IMG = 13,
+	BIT_UVC_CMD_VERIFY_IMG = 14,
+	BIT_UVC_CMD_CPU_RESET = 15,
+	BIT_UVC_CMD_CPU_RESET_INITIAL = 16,
+	BIT_UVC_CMD_CPU_SET_STATE = 17,
+	BIT_UVC_CMD_PREPARE_RESET = 18,
+	BIT_UVC_CMD_CPU_PERFORM_CLEAR_RESET = 19,
+	BIT_UVC_CMD_UNSHARE_ALL = 20,
+	BIT_UVC_CMD_PIN_PAGE_SHARED = 21,
+	BIT_UVC_CMD_UNPIN_PAGE_SHARED = 22,
 };
 
 struct uv_cb_header {
@@ -40,13 +84,127 @@
 	u16 rrc;	/* Return Reason Code */
 } __packed __aligned(8);
 
+/* Query Ultravisor Information */
 struct uv_cb_qui {
 	struct uv_cb_header header;
 	u64 reserved08;
 	u64 inst_calls_list[4];
-	u64 reserved30[15];
+	u64 reserved30[2];
+	u64 uv_base_stor_len;
+	u64 reserved48;
+	u64 conf_base_phys_stor_len;
+	u64 conf_base_virt_stor_len;
+	u64 conf_virt_var_stor_len;
+	u64 cpu_stor_len;
+	u32 reserved70[3];
+	u32 max_num_sec_conf;
+	u64 max_guest_stor_addr;
+	u8  reserved88[158 - 136];
+	u16 max_guest_cpus;
+	u8  reserveda0[200 - 160];
+} __packed __aligned(8);
+
+/* Initialize Ultravisor */
+struct uv_cb_init {
+	struct uv_cb_header header;
+	u64 reserved08[2];
+	u64 stor_origin;
+	u64 stor_len;
+	u64 reserved28[4];
+} __packed __aligned(8);
+
+/* Create Guest Configuration */
+struct uv_cb_cgc {
+	struct uv_cb_header header;
+	u64 reserved08[2];
+	u64 guest_handle;
+	u64 conf_base_stor_origin;
+	u64 conf_virt_stor_origin;
+	u64 reserved30;
+	u64 guest_stor_origin;
+	u64 guest_stor_len;
+	u64 guest_sca;
+	u64 guest_asce;
+	u64 reserved58[5];
+} __packed __aligned(8);
+
+/* Create Secure CPU */
+struct uv_cb_csc {
+	struct uv_cb_header header;
+	u64 reserved08[2];
+	u64 cpu_handle;
+	u64 guest_handle;
+	u64 stor_origin;
+	u8  reserved30[6];
+	u16 num;
+	u64 state_origin;
+	u64 reserved40[4];
+} __packed __aligned(8);
+
+/* Convert to Secure */
+struct uv_cb_cts {
+	struct uv_cb_header header;
+	u64 reserved08[2];
+	u64 guest_handle;
+	u64 gaddr;
+} __packed __aligned(8);
+
+/* Convert from Secure / Pin Page Shared */
+struct uv_cb_cfs {
+	struct uv_cb_header header;
+	u64 reserved08[2];
+	u64 paddr;
+} __packed __aligned(8);
+
+/* Set Secure Config Parameter */
+struct uv_cb_ssc {
+	struct uv_cb_header header;
+	u64 reserved08[2];
+	u64 guest_handle;
+	u64 sec_header_origin;
+	u32 sec_header_len;
+	u32 reserved2c;
+	u64 reserved30[4];
 } __packed __aligned(8);
 
+/* Unpack */
+struct uv_cb_unp {
+	struct uv_cb_header header;
+	u64 reserved08[2];
+	u64 guest_handle;
+	u64 gaddr;
+	u64 tweak[2];
+	u64 reserved38[3];
+} __packed __aligned(8);
+
+#define PV_CPU_STATE_OPR	1
+#define PV_CPU_STATE_STP	2
+#define PV_CPU_STATE_CHKSTP	3
+#define PV_CPU_STATE_OPR_LOAD	5
+
+struct uv_cb_cpu_set_state {
+	struct uv_cb_header header;
+	u64 reserved08[2];
+	u64 cpu_handle;
+	u8  reserved20[7];
+	u8  state;
+	u64 reserved28[5];
+};
+
+/*
+ * A common UV call struct for calls that take no payload
+ * Examples:
+ * Destroy cpu/config
+ * Verify
+ */
+struct uv_cb_nodata {
+	struct uv_cb_header header;
+	u64 reserved08[2];
+	u64 handle;
+	u64 reserved20[4];
+} __packed __aligned(8);
+
+/* Set Shared Access */
 struct uv_cb_share {
 	struct uv_cb_header header;
 	u64 reserved08[3];
@@ -54,21 +212,76 @@
 	u64 reserved28;
 } __packed __aligned(8);
 
-static inline int uv_call(unsigned long r1, unsigned long r2)
+static inline int __uv_call(unsigned long r1, unsigned long r2)
 {
 	int cc;
 
 	asm volatile(
-		"0:	.insn rrf,0xB9A40000,%[r1],%[r2],0,0\n"
-		"		brc	3,0b\n"
-		"		ipm	%[cc]\n"
-		"		srl	%[cc],28\n"
+		"	.insn rrf,0xB9A40000,%[r1],%[r2],0,0\n"
+		"	ipm	%[cc]\n"
+		"	srl	%[cc],28\n"
 		: [cc] "=d" (cc)
 		: [r1] "a" (r1), [r2] "a" (r2)
 		: "memory", "cc");
 	return cc;
 }
 
+static inline int uv_call(unsigned long r1, unsigned long r2)
+{
+	int cc;
+
+	do {
+		cc = __uv_call(r1, r2);
+	} while (cc > 1);
+	return cc;
+}
+
+/* Low level uv_call that avoids stalls for long running busy conditions  */
+static inline int uv_call_sched(unsigned long r1, unsigned long r2)
+{
+	int cc;
+
+	do {
+		cc = __uv_call(r1, r2);
+		cond_resched();
+	} while (cc > 1);
+	return cc;
+}
+
+/*
+ * special variant of uv_call that only transports the cpu or guest
+ * handle and the command, like destroy or verify.
+ */
+static inline int uv_cmd_nodata(u64 handle, u16 cmd, u16 *rc, u16 *rrc)
+{
+	struct uv_cb_nodata uvcb = {
+		.header.cmd = cmd,
+		.header.len = sizeof(uvcb),
+		.handle = handle,
+	};
+	int cc;
+
+	WARN(!handle, "No handle provided to Ultravisor call cmd %x\n", cmd);
+	cc = uv_call_sched(0, (u64)&uvcb);
+	*rc = uvcb.header.rc;
+	*rrc = uvcb.header.rrc;
+	return cc ? -EINVAL : 0;
+}
+
+struct uv_info {
+	unsigned long inst_calls_list[4];
+	unsigned long uv_base_stor_len;
+	unsigned long guest_base_stor_len;
+	unsigned long guest_virt_base_stor_len;
+	unsigned long guest_virt_var_stor_len;
+	unsigned long guest_cpu_stor_len;
+	unsigned long max_sec_stor_addr;
+	unsigned int max_num_sec_conf;
+	unsigned short max_guest_cpus;
+};
+
+extern struct uv_info uv_info;
+
 #ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST
 extern int prot_virt_guest;
 
@@ -97,7 +310,10 @@
 
 	if (!uv_call(0, (u64)&uvcb))
 		return 0;
-	return -EINVAL;
+	pr_err("%s UVC failed (rc: 0x%x, rrc: 0x%x), possible hypervisor bug.\n",
+	       uvcb.header.cmd == UVC_CMD_SET_SHARED_ACCESS ? "Share" : "Unshare",
+	       uvcb.header.rc, uvcb.header.rrc);
+	panic("System security cannot be guaranteed unless the system panics now.\n");
 }
 
 /*
@@ -121,11 +337,40 @@
 	return share(addr, UVC_CMD_REMOVE_SHARED_ACCESS);
 }
 
-void uv_query_info(void);
 #else
 #define is_prot_virt_guest() 0
 static inline int uv_set_shared(unsigned long addr) { return 0; }
 static inline int uv_remove_shared(unsigned long addr) { return 0; }
+#endif
+
+#if IS_ENABLED(CONFIG_KVM)
+extern int prot_virt_host;
+
+static inline int is_prot_virt_host(void)
+{
+	return prot_virt_host;
+}
+
+int gmap_make_secure(struct gmap *gmap, unsigned long gaddr, void *uvcb);
+int uv_convert_from_secure(unsigned long paddr);
+int gmap_convert_to_secure(struct gmap *gmap, unsigned long gaddr);
+
+void setup_uv(void);
+void adjust_to_uv_max(unsigned long *vmax);
+#else
+#define is_prot_virt_host() 0
+static inline void setup_uv(void) {}
+static inline void adjust_to_uv_max(unsigned long *vmax) {}
+
+static inline int uv_convert_from_secure(unsigned long paddr)
+{
+	return 0;
+}
+#endif
+
+#if defined(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) || IS_ENABLED(CONFIG_KVM)
+void uv_query_info(void);
+#else
 static inline void uv_query_info(void) {}
 #endif
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/asm/vdso.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/asm/vdso.h
@@ -36,6 +36,7 @@
 	__u32 tk_shift;			/* Shift used for xtime_nsec	0x60 */
 	__u32 ts_dir;			/* TOD steering direction	0x64 */
 	__u64 ts_end;			/* TOD steering end		0x68 */
+	__u32 hrtimer_res;		/* hrtimer resolution		0x70 */
 };
 
 struct vdso_per_cpu_data {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/uapi/asm/ipl.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/uapi/asm/ipl.h
@@ -27,6 +27,7 @@
 	IPL_PBT_FCP = 0,
 	IPL_PBT_SCP_DATA = 1,
 	IPL_PBT_CCW = 2,
+	IPL_PBT_NVME = 4,
 };
 
 /* IPL Parameter Block 0 with common fields */
@@ -67,6 +68,30 @@
 #define IPL_PB0_FCP_OPT_IPL	0x10
 #define IPL_PB0_FCP_OPT_DUMP	0x20
 
+/* IPL Parameter Block 0 for NVMe */
+struct ipl_pb0_nvme {
+	__u32 len;
+	__u8  pbt;
+	__u8  reserved1[3];
+	__u8  loadparm[8];
+	__u8  reserved2[304];
+	__u8  opt;
+	__u8  reserved3[3];
+	__u32 fid;
+	__u8 reserved4[12];
+	__u32 nsid;
+	__u8 reserved5[4];
+	__u32 bootprog;
+	__u8 reserved6[12];
+	__u64 br_lba;
+	__u32 scp_data_len;
+	__u8  reserved7[260];
+	__u8  scp_data[];
+} __packed;
+
+#define IPL_PB0_NVME_OPT_IPL	0x10
+#define IPL_PB0_NVME_OPT_DUMP	0x20
+
 /* IPL Parameter Block 0 for CCW */
 struct ipl_pb0_ccw {
 	__u32 len;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/uapi/asm/kvm.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/uapi/asm/kvm.h
@@ -231,11 +231,13 @@
 #define KVM_SYNC_GSCB   (1UL << 9)
 #define KVM_SYNC_BPBC   (1UL << 10)
 #define KVM_SYNC_ETOKEN (1UL << 11)
+#define KVM_SYNC_DIAG318 (1UL << 12)
 
 #define KVM_SYNC_S390_VALID_FIELDS \
 	(KVM_SYNC_PREFIX | KVM_SYNC_GPRS | KVM_SYNC_ACRS | KVM_SYNC_CRS | \
 	 KVM_SYNC_ARCH0 | KVM_SYNC_PFAULT | KVM_SYNC_VRS | KVM_SYNC_RICCB | \
-	 KVM_SYNC_FPRS | KVM_SYNC_GSCB | KVM_SYNC_BPBC | KVM_SYNC_ETOKEN)
+	 KVM_SYNC_FPRS | KVM_SYNC_GSCB | KVM_SYNC_BPBC | KVM_SYNC_ETOKEN | \
+	 KVM_SYNC_DIAG318)
 
 /* length and alignment of the sdnx as a power of two */
 #define SDNXC 8
@@ -264,7 +266,8 @@
 	__u8 reserved2 : 7;
 	__u8 padding1[51];	/* riccb needs to be 64byte aligned */
 	__u8 riccb[64];		/* runtime instrumentation controls block */
-	__u8 padding2[192];	/* sdnx needs to be 256byte aligned */
+	__u64 diag318;		/* diagnose 0x318 info */
+	__u8 padding2[184];	/* sdnx needs to be 256byte aligned */
 	union {
 		__u8 sdnx[SDNXL];  /* state description annex */
 		struct {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/uapi/asm/pkey.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/uapi/asm/pkey.h
@@ -25,10 +25,11 @@
 #define MAXPROTKEYSIZE	64	/* a protected key blob may be up to 64 bytes */
 #define MAXCLRKEYSIZE	32	   /* a clear key value may be up to 32 bytes */
 #define MAXAESCIPHERKEYSIZE 136  /* our aes cipher keys have always 136 bytes */
+#define MINEP11AESKEYBLOBSIZE 256  /* min EP11 AES key blob size  */
+#define MAXEP11AESKEYBLOBSIZE 320  /* max EP11 AES key blob size */
 
-/* Minimum and maximum size of a key blob */
+/* Minimum size of a key blob */
 #define MINKEYBLOBSIZE	SECKEYBLOBSIZE
-#define MAXKEYBLOBSIZE	MAXAESCIPHERKEYSIZE
 
 /* defines for the type field within the pkey_protkey struct */
 #define PKEY_KEYTYPE_AES_128		      1
@@ -39,6 +40,7 @@
 enum pkey_key_type {
 	PKEY_TYPE_CCA_DATA   = (__u32) 1,
 	PKEY_TYPE_CCA_CIPHER = (__u32) 2,
+	PKEY_TYPE_EP11	     = (__u32) 3,
 };
 
 /* the newer ioctls use a pkey_key_size enum for key size information */
@@ -200,7 +202,7 @@
 
 /*
  * Generate secure key, version 2.
- * Generate either a CCA AES secure key or a CCA AES cipher key.
+ * Generate CCA AES secure key, CCA AES cipher key or EP11 AES secure key.
  * There needs to be a list of apqns given with at least one entry in there.
  * All apqns in the list need to be exact apqns, 0xFFFF as ANY card or domain
  * is not supported. The implementation walks through the list of apqns and
@@ -210,10 +212,13 @@
  * (return -1 with errno ENODEV). You may use the PKEY_APQNS4KT ioctl to
  * generate a list of apqns based on the key type to generate.
  * The keygenflags argument is passed to the low level generation functions
- * individual for the key type and has a key type specific meaning. Currently
- * only CCA AES cipher keys react to this parameter: Use one or more of the
- * PKEY_KEYGEN_* flags to widen the export possibilities. By default a cipher
- * key is only exportable for CPACF (PKEY_KEYGEN_XPRT_CPAC).
+ * individual for the key type and has a key type specific meaning. When
+ * generating CCA cipher keys you can use one or more of the PKEY_KEYGEN_*
+ * flags to widen the export possibilities. By default a cipher key is
+ * only exportable for CPACF (PKEY_KEYGEN_XPRT_CPAC).
+ * The keygenflag argument for generating an EP11 AES key should either be 0
+ * to use the defaults which are XCP_BLOB_ENCRYPT, XCP_BLOB_DECRYPT and
+ * XCP_BLOB_PROTKEY_EXTRACTABLE or a valid combination of XCP_BLOB_* flags.
  */
 struct pkey_genseck2 {
 	struct pkey_apqn __user *apqns; /* in: ptr to list of apqn targets*/
@@ -229,8 +234,8 @@
 
 /*
  * Generate secure key from clear key value, version 2.
- * Construct a CCA AES secure key or CCA AES cipher key from a given clear key
- * value.
+ * Construct an CCA AES secure key, CCA AES cipher key or EP11 AES secure
+ * key from a given clear key value.
  * There needs to be a list of apqns given with at least one entry in there.
  * All apqns in the list need to be exact apqns, 0xFFFF as ANY card or domain
  * is not supported. The implementation walks through the list of apqns and
@@ -240,10 +245,13 @@
  * (return -1 with errno ENODEV). You may use the PKEY_APQNS4KT ioctl to
  * generate a list of apqns based on the key type to generate.
  * The keygenflags argument is passed to the low level generation functions
- * individual for the key type and has a key type specific meaning. Currently
- * only CCA AES cipher keys react to this parameter: Use one or more of the
- * PKEY_KEYGEN_* flags to widen the export possibilities. By default a cipher
- * key is only exportable for CPACF (PKEY_KEYGEN_XPRT_CPAC).
+ * individual for the key type and has a key type specific meaning. When
+ * generating CCA cipher keys you can use one or more of the PKEY_KEYGEN_*
+ * flags to widen the export possibilities. By default a cipher key is
+ * only exportable for CPACF (PKEY_KEYGEN_XPRT_CPAC).
+ * The keygenflag argument for generating an EP11 AES key should either be 0
+ * to use the defaults which are XCP_BLOB_ENCRYPT, XCP_BLOB_DECRYPT and
+ * XCP_BLOB_PROTKEY_EXTRACTABLE or a valid combination of XCP_BLOB_* flags.
  */
 struct pkey_clr2seck2 {
 	struct pkey_apqn __user *apqns; /* in: ptr to list of apqn targets */
@@ -266,14 +274,19 @@
  * with one apqn able to handle this key.
  * The function also checks for the master key verification patterns
  * of the key matching to the current or alternate mkvp of the apqn.
- * Currently CCA AES secure keys and CCA AES cipher keys are supported.
- * The flags field is updated with some additional info about the apqn mkvp
+ * For CCA AES secure keys and CCA AES cipher keys this means to check
+ * the key's mkvp against the current or old mkvp of the apqns. The flags
+ * field is updated with some additional info about the apqn mkvp
  * match: If the current mkvp matches to the key's mkvp then the
  * PKEY_FLAGS_MATCH_CUR_MKVP bit is set, if the alternate mkvp matches to
  * the key's mkvp the PKEY_FLAGS_MATCH_ALT_MKVP is set. For CCA keys the
  * alternate mkvp is the old master key verification pattern.
  * CCA AES secure keys are also checked to have the CPACF export allowed
  * bit enabled (XPRTCPAC) in the kmf1 field.
+ * EP11 keys are also supported and the wkvp of the key is checked against
+ * the current wkvp of the apqns. There is no alternate for this type of
+ * key and so on a match the flag PKEY_FLAGS_MATCH_CUR_MKVP always is set.
+ * EP11 keys are also checked to have XCP_BLOB_PROTKEY_EXTRACTABLE set.
  * The ioctl returns 0 as long as the given or found apqn matches to
  * matches with the current or alternate mkvp to the key's mkvp. If the given
  * apqn does not match or there is no such apqn found, -1 with errno
@@ -313,16 +326,20 @@
 /*
  * Build a list of APQNs based on a key blob given.
  * Is able to find out which type of secure key is given (CCA AES secure
- * key or CCA AES cipher key) and tries to find all matching crypto cards
- * based on the MKVP and maybe other criterias (like CCA AES cipher keys
- * need a CEX5C or higher). The list of APQNs is further filtered by the key's
- * mkvp which needs to match to either the current mkvp or the alternate mkvp
- * (which is the old mkvp on CCA adapters) of the apqns. The flags argument may
- * be used to limit the matching apqns. If the PKEY_FLAGS_MATCH_CUR_MKVP is
- * given, only the current mkvp of each apqn is compared. Likewise with the
- * PKEY_FLAGS_MATCH_ALT_MKVP. If both are given, it is assumed to
- * return apqns where either the current or the alternate mkvp
+ * key, CCA AES cipher key or EP11 AES key) and tries to find all matching
+ * crypto cards based on the MKVP and maybe other criterias (like CCA AES
+ * cipher keys need a CEX5C or higher, EP11 keys with BLOB_PKEY_EXTRACTABLE
+ * need a CEX7 and EP11 api version 4). The list of APQNs is further filtered
+ * by the key's mkvp which needs to match to either the current mkvp (CCA and
+ * EP11) or the alternate mkvp (old mkvp, CCA adapters only) of the apqns. The
+ * flags argument may be used to limit the matching apqns. If the
+ * PKEY_FLAGS_MATCH_CUR_MKVP is given, only the current mkvp of each apqn is
+ * compared. Likewise with the PKEY_FLAGS_MATCH_ALT_MKVP. If both are given, it
+ * is assumed to return apqns where either the current or the alternate mkvp
  * matches. At least one of the matching flags needs to be given.
+ * The flags argument for EP11 keys has no further action and is currently
+ * ignored (but needs to be given as PKEY_FLAGS_MATCH_CUR_MKVP) as there is only
+ * the wkvp from the key to match against the apqn's wkvp.
  * The list of matching apqns is stored into the space given by the apqns
  * argument and the number of stored entries goes into apqn_entries. If the list
  * is empty (apqn_entries is 0) the apqn_entries field is updated to the number
@@ -356,6 +373,10 @@
  * If both are given, it is assumed to return apqns where either the
  * current or the alternate mkvp matches. If no match flag is given
  * (flags is 0) the mkvp values are ignored for the match process.
+ * For EP11 keys there is only the current wkvp. So if the apqns should also
+ * match to a given wkvp, then the PKEY_FLAGS_MATCH_CUR_MKVP flag should be
+ * set. The wkvp value is 32 bytes but only the leftmost 16 bytes are compared
+ * against the leftmost 16 byte of the wkvp of the apqn.
  * The list of matching apqns is stored into the space given by the apqns
  * argument and the number of stored entries goes into apqn_entries. If the list
  * is empty (apqn_entries is 0) the apqn_entries field is updated to the number
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/include/uapi/asm/zcrypt.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/include/uapi/asm/zcrypt.h
@@ -36,12 +36,12 @@
  * - length(n_modulus) = inputdatalength
  */
 struct ica_rsa_modexpo {
-	char __user  *inputdata;
-	unsigned int  inputdatalength;
-	char __user  *outputdata;
-	unsigned int  outputdatalength;
-	char __user  *b_key;
-	char __user  *n_modulus;
+	__u8 __user  *inputdata;
+	__u32	      inputdatalength;
+	__u8 __user  *outputdata;
+	__u32	      outputdatalength;
+	__u8 __user  *b_key;
+	__u8 __user  *n_modulus;
 };
 
 /**
@@ -59,15 +59,15 @@
  * - length(u_mult_inv) = inputdatalength/2 + 8
  */
 struct ica_rsa_modexpo_crt {
-	char __user  *inputdata;
-	unsigned int  inputdatalength;
-	char __user  *outputdata;
-	unsigned int  outputdatalength;
-	char __user  *bp_key;
-	char __user  *bq_key;
-	char __user  *np_prime;
-	char __user  *nq_prime;
-	char __user  *u_mult_inv;
+	__u8 __user  *inputdata;
+	__u32	      inputdatalength;
+	__u8 __user  *outputdata;
+	__u32	      outputdatalength;
+	__u8 __user  *bp_key;
+	__u8 __user  *bq_key;
+	__u8 __user  *np_prime;
+	__u8 __user  *nq_prime;
+	__u8 __user  *u_mult_inv;
 };
 
 /**
@@ -83,67 +83,67 @@
  *	    key block
  */
 struct CPRBX {
-	unsigned short	cprb_len;	/* CPRB length	      220	 */
-	unsigned char	cprb_ver_id;	/* CPRB version id.   0x02	 */
-	unsigned char	pad_000[3];	/* Alignment pad bytes		 */
-	unsigned char	func_id[2];	/* function id	      0x5432	 */
-	unsigned char	cprb_flags[4];	/* Flags			 */
-	unsigned int	req_parml;	/* request parameter buffer len	 */
-	unsigned int	req_datal;	/* request data buffer		 */
-	unsigned int	rpl_msgbl;	/* reply  message block length	 */
-	unsigned int	rpld_parml;	/* replied parameter block len	 */
-	unsigned int	rpl_datal;	/* reply data block len		 */
-	unsigned int	rpld_datal;	/* replied data block len	 */
-	unsigned int	req_extbl;	/* request extension block len	 */
-	unsigned char	pad_001[4];	/* reserved			 */
-	unsigned int	rpld_extbl;	/* replied extension block len	 */
-	unsigned char	padx000[16 - sizeof(char *)];
-	unsigned char  *req_parmb;	/* request parm block 'address'	 */
-	unsigned char	padx001[16 - sizeof(char *)];
-	unsigned char  *req_datab;	/* request data block 'address'	 */
-	unsigned char	padx002[16 - sizeof(char *)];
-	unsigned char  *rpl_parmb;	/* reply parm block 'address'	 */
-	unsigned char	padx003[16 - sizeof(char *)];
-	unsigned char  *rpl_datab;	/* reply data block 'address'	 */
-	unsigned char	padx004[16 - sizeof(char *)];
-	unsigned char  *req_extb;	/* request extension block 'addr'*/
-	unsigned char	padx005[16 - sizeof(char *)];
-	unsigned char  *rpl_extb;	/* reply extension block 'address'*/
-	unsigned short	ccp_rtcode;	/* server return code		 */
-	unsigned short	ccp_rscode;	/* server reason code		 */
-	unsigned int	mac_data_len;	/* Mac Data Length		 */
-	unsigned char	logon_id[8];	/* Logon Identifier		 */
-	unsigned char	mac_value[8];	/* Mac Value			 */
-	unsigned char	mac_content_flgs;/* Mac content flag byte	 */
-	unsigned char	pad_002;	/* Alignment			 */
-	unsigned short	domain;		/* Domain			 */
-	unsigned char	usage_domain[4];/* Usage domain			 */
-	unsigned char	cntrl_domain[4];/* Control domain		 */
-	unsigned char	S390enf_mask[4];/* S/390 enforcement mask	 */
-	unsigned char	pad_004[36];	/* reserved			 */
+	__u16	     cprb_len;		/* CPRB length	      220	 */
+	__u8	     cprb_ver_id;	/* CPRB version id.   0x02	 */
+	__u8	     pad_000[3];	/* Alignment pad bytes		 */
+	__u8	     func_id[2];	/* function id	      0x5432	 */
+	__u8	     cprb_flags[4];	/* Flags			 */
+	__u32	     req_parml;		/* request parameter buffer len	 */
+	__u32	     req_datal;		/* request data buffer		 */
+	__u32	     rpl_msgbl;		/* reply  message block length	 */
+	__u32	     rpld_parml;	/* replied parameter block len	 */
+	__u32	     rpl_datal;		/* reply data block len		 */
+	__u32	     rpld_datal;	/* replied data block len	 */
+	__u32	     req_extbl;		/* request extension block len	 */
+	__u8	     pad_001[4];	/* reserved			 */
+	__u32	     rpld_extbl;	/* replied extension block len	 */
+	__u8	     padx000[16 - sizeof(__u8 *)];
+	__u8 __user *req_parmb;		/* request parm block 'address'	 */
+	__u8	     padx001[16 - sizeof(__u8 *)];
+	__u8 __user *req_datab;		/* request data block 'address'	 */
+	__u8	     padx002[16 - sizeof(__u8 *)];
+	__u8 __user *rpl_parmb;		/* reply parm block 'address'	 */
+	__u8	     padx003[16 - sizeof(__u8 *)];
+	__u8 __user *rpl_datab;		/* reply data block 'address'	 */
+	__u8	     padx004[16 - sizeof(__u8 *)];
+	__u8 __user *req_extb;		/* request extension block 'addr'*/
+	__u8	     padx005[16 - sizeof(__u8 *)];
+	__u8 __user *rpl_extb;		/* reply extension block 'address'*/
+	__u16	     ccp_rtcode;	/* server return code		 */
+	__u16	     ccp_rscode;	/* server reason code		 */
+	__u32	     mac_data_len;	/* Mac Data Length		 */
+	__u8	     logon_id[8];	/* Logon Identifier		 */
+	__u8	     mac_value[8];	/* Mac Value			 */
+	__u8	     mac_content_flgs;	/* Mac content flag byte	 */
+	__u8	     pad_002;		/* Alignment			 */
+	__u16	     domain;		/* Domain			 */
+	__u8	     usage_domain[4];	/* Usage domain			 */
+	__u8	     cntrl_domain[4];	/* Control domain		 */
+	__u8	     S390enf_mask[4];	/* S/390 enforcement mask	 */
+	__u8	     pad_004[36];	/* reserved			 */
 } __attribute__((packed));
 
 /**
  * xcRB
  */
 struct ica_xcRB {
-	unsigned short	agent_ID;
-	unsigned int	user_defined;
-	unsigned short	request_ID;
-	unsigned int	request_control_blk_length;
-	unsigned char	padding1[16 - sizeof(char *)];
-	char __user    *request_control_blk_addr;
-	unsigned int	request_data_length;
-	char		padding2[16 - sizeof(char *)];
-	char __user    *request_data_address;
-	unsigned int	reply_control_blk_length;
-	char		padding3[16 - sizeof(char *)];
-	char __user    *reply_control_blk_addr;
-	unsigned int	reply_data_length;
-	char		padding4[16 - sizeof(char *)];
-	char __user    *reply_data_addr;
-	unsigned short	priority_window;
-	unsigned int	status;
+	__u16	      agent_ID;
+	__u32	      user_defined;
+	__u16	      request_ID;
+	__u32	      request_control_blk_length;
+	__u8	      _padding1[16 - sizeof(__u8 *)];
+	__u8 __user  *request_control_blk_addr;
+	__u32	      request_data_length;
+	__u8	      _padding2[16 - sizeof(__u8 *)];
+	__u8 __user  *request_data_address;
+	__u32	      reply_control_blk_length;
+	__u8	      _padding3[16 - sizeof(__u8 *)];
+	__u8 __user  *reply_control_blk_addr;
+	__u32	      reply_data_length;
+	__u8	      __padding4[16 - sizeof(__u8 *)];
+	__u8 __user  *reply_data_addr;
+	__u16	      priority_window;
+	__u32	      status;
 } __attribute__((packed));
 
 /**
@@ -161,17 +161,17 @@
  * @payload_len:	Payload length
  */
 struct ep11_cprb {
-	__u16		cprb_len;
-	unsigned char	cprb_ver_id;
-	unsigned char	pad_000[2];
-	unsigned char	flags;
-	unsigned char	func_id[2];
-	__u32		source_id;
-	__u32		target_id;
-	__u32		ret_code;
-	__u32		reserved1;
-	__u32		reserved2;
-	__u32		payload_len;
+	__u16	cprb_len;
+	__u8	cprb_ver_id;
+	__u8	pad_000[2];
+	__u8	flags;
+	__u8	func_id[2];
+	__u32	source_id;
+	__u32	target_id;
+	__u32	ret_code;
+	__u32	reserved1;
+	__u32	reserved2;
+	__u32	payload_len;
 } __attribute__((packed));
 
 /**
@@ -197,13 +197,13 @@
  */
 struct ep11_urb {
 	__u16		targets_num;
-	__u64		targets;
+	__u8 __user    *targets;
 	__u64		weight;
 	__u64		req_no;
 	__u64		req_len;
-	__u64		req;
+	__u8 __user    *req;
 	__u64		resp_len;
-	__u64		resp;
+	__u8 __user    *resp;
 } __attribute__((packed));
 
 /**
@@ -237,7 +237,9 @@
 	struct zcrypt_device_status_ext device[MAX_ZDEV_ENTRIES_EXT];
 };
 
-#define AUTOSELECT 0xFFFFFFFF
+#define AUTOSELECT  0xFFFFFFFF
+#define AUTOSEL_AP  ((__u16) 0xFFFF)
+#define AUTOSEL_DOM ((__u16) 0xFFFF)
 
 #define ZCRYPT_IOCTL_MAGIC 'z'
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/Makefile
@@ -78,7 +78,11 @@
 obj-$(CONFIG_PERF_EVENTS)	+= perf_cpum_cf_diag.o
 
 obj-$(CONFIG_TRACEPOINTS)	+= trace.o
+obj-$(findstring y, $(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) $(CONFIG_PGSTE))	+= uv.o
 
 # vdso
 obj-y				+= vdso64/
 obj-$(CONFIG_COMPAT_VDSO)	+= vdso32/
+
+# kernel message catalog
+obj-$(CONFIG_KMSG_IDS)		+= kmsg.o
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/asm-offsets.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/asm-offsets.c
@@ -76,6 +76,7 @@
 	OFFSET(__VDSO_TK_SHIFT, vdso_data, tk_shift);
 	OFFSET(__VDSO_TS_DIR, vdso_data, ts_dir);
 	OFFSET(__VDSO_TS_END, vdso_data, ts_end);
+	OFFSET(__VDSO_CLOCK_REALTIME_RES, vdso_data, hrtimer_res);
 	OFFSET(__VDSO_ECTG_BASE, vdso_per_cpu_data, ectg_timer_base);
 	OFFSET(__VDSO_ECTG_USER, vdso_per_cpu_data, ectg_user_time);
 	OFFSET(__VDSO_CPU_NR, vdso_per_cpu_data, cpu_nr);
@@ -87,7 +88,6 @@
 	DEFINE(__CLOCK_REALTIME_COARSE, CLOCK_REALTIME_COARSE);
 	DEFINE(__CLOCK_MONOTONIC_COARSE, CLOCK_MONOTONIC_COARSE);
 	DEFINE(__CLOCK_THREAD_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID);
-	DEFINE(__CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC);
 	DEFINE(__CLOCK_COARSE_RES, LOW_RES_NSEC);
 	BLANK();
 	/* idle data offsets */
@@ -125,6 +125,8 @@
 	OFFSET(__LC_EXT_DAMAGE_CODE, lowcore, external_damage_code);
 	OFFSET(__LC_MCCK_FAIL_STOR_ADDR, lowcore, failing_storage_address);
 	OFFSET(__LC_LAST_BREAK, lowcore, breaking_event_addr);
+	OFFSET(__LC_RETURN_LPSWE, lowcore, return_lpswe);
+	OFFSET(__LC_RETURN_MCCK_LPSWE, lowcore, return_mcck_lpswe);
 	OFFSET(__LC_RST_OLD_PSW, lowcore, restart_old_psw);
 	OFFSET(__LC_EXT_OLD_PSW, lowcore, external_old_psw);
 	OFFSET(__LC_SVC_OLD_PSW, lowcore, svc_old_psw);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/cpcmd.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/cpcmd.c
@@ -37,10 +37,12 @@
 
 static int diag8_response(int cmdlen, char *response, int *rlen)
 {
+	unsigned long _cmdlen = cmdlen | 0x40000000L;
+	unsigned long _rlen = *rlen;
 	register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf;
 	register unsigned long reg3 asm ("3") = (addr_t) response;
-	register unsigned long reg4 asm ("4") = cmdlen | 0x40000000L;
-	register unsigned long reg5 asm ("5") = *rlen;
+	register unsigned long reg4 asm ("4") = _cmdlen;
+	register unsigned long reg5 asm ("5") = _rlen;
 
 	asm volatile(
 		"	diag	%2,%0,0x8\n"
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/crash_dump.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/crash_dump.c
@@ -44,7 +44,7 @@
 	u64 fprs[16];
 	u32 fpc;
 	u32 prefix;
-	u64 todpreg;
+	u32 todpreg;
 	u64 timer;
 	u64 todcmp;
 	u64 vxrs_low[16];
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/debug.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/debug.c
@@ -198,9 +198,10 @@
 	if (!areas)
 		goto fail_malloc_areas;
 	for (i = 0; i < nr_areas; i++) {
+		/* GFP_NOWARN to avoid user triggerable WARN, we handle fails */
 		areas[i] = kmalloc_array(pages_per_area,
 					 sizeof(debug_entry_t *),
-					 GFP_KERNEL);
+					 GFP_KERNEL | __GFP_NOWARN);
 		if (!areas[i])
 			goto fail_malloc_areas2;
 		for (j = 0; j < pages_per_area; j++) {
@@ -326,24 +327,6 @@
 		goto out;
 
 	rc->mode = mode & ~S_IFMT;
-
-	/* create root directory */
-	rc->debugfs_root_entry = debugfs_create_dir(rc->name,
-						    debug_debugfs_root_entry);
-
-	/* append new element to linked list */
-	if (!debug_area_first) {
-		/* first element in list */
-		debug_area_first = rc;
-		rc->prev = NULL;
-	} else {
-		/* append element to end of list */
-		debug_area_last->next = rc;
-		rc->prev = debug_area_last;
-	}
-	debug_area_last = rc;
-	rc->next = NULL;
-
 	refcount_set(&rc->ref_count, 1);
 out:
 	return rc;
@@ -403,27 +386,10 @@
  */
 static void debug_info_put(debug_info_t *db_info)
 {
-	int i;
-
 	if (!db_info)
 		return;
-	if (refcount_dec_and_test(&db_info->ref_count)) {
-		for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
-			if (!db_info->views[i])
-				continue;
-			debugfs_remove(db_info->debugfs_entries[i]);
-		}
-		debugfs_remove(db_info->debugfs_root_entry);
-		if (db_info == debug_area_first)
-			debug_area_first = db_info->next;
-		if (db_info == debug_area_last)
-			debug_area_last = db_info->prev;
-		if (db_info->prev)
-			db_info->prev->next = db_info->next;
-		if (db_info->next)
-			db_info->next->prev = db_info->prev;
+	if (refcount_dec_and_test(&db_info->ref_count))
 		debug_info_free(db_info);
-	}
 }
 
 /*
@@ -647,6 +613,31 @@
 	return 0; /* success */
 }
 
+/* Create debugfs entries and add to internal list. */
+static void _debug_register(debug_info_t *id)
+{
+	/* create root directory */
+	id->debugfs_root_entry = debugfs_create_dir(id->name,
+						    debug_debugfs_root_entry);
+
+	/* append new element to linked list */
+	if (!debug_area_first) {
+		/* first element in list */
+		debug_area_first = id;
+		id->prev = NULL;
+	} else {
+		/* append element to end of list */
+		debug_area_last->next = id;
+		id->prev = debug_area_last;
+	}
+	debug_area_last = id;
+	id->next = NULL;
+
+	debug_register_view(id, &debug_level_view);
+	debug_register_view(id, &debug_flush_view);
+	debug_register_view(id, &debug_pages_view);
+}
+
 /**
  * debug_register_mode() - creates and initializes debug area.
  *
@@ -676,19 +667,16 @@
 	if ((uid != 0) || (gid != 0))
 		pr_warn("Root becomes the owner of all s390dbf files in sysfs\n");
 	BUG_ON(!initialized);
-	mutex_lock(&debug_mutex);
 
 	/* create new debug_info */
 	rc = debug_info_create(name, pages_per_area, nr_areas, buf_size, mode);
-	if (!rc)
-		goto out;
-	debug_register_view(rc, &debug_level_view);
-	debug_register_view(rc, &debug_flush_view);
-	debug_register_view(rc, &debug_pages_view);
-out:
-	if (!rc)
+	if (rc) {
+		mutex_lock(&debug_mutex);
+		_debug_register(rc);
+		mutex_unlock(&debug_mutex);
+	} else {
 		pr_err("Registering debug feature %s failed\n", name);
-	mutex_unlock(&debug_mutex);
+	}
 	return rc;
 }
 EXPORT_SYMBOL(debug_register_mode);
@@ -717,6 +705,27 @@
 }
 EXPORT_SYMBOL(debug_register);
 
+/* Remove debugfs entries and remove from internal list. */
+static void _debug_unregister(debug_info_t *id)
+{
+	int i;
+
+	for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
+		if (!id->views[i])
+			continue;
+		debugfs_remove(id->debugfs_entries[i]);
+	}
+	debugfs_remove(id->debugfs_root_entry);
+	if (id == debug_area_first)
+		debug_area_first = id->next;
+	if (id == debug_area_last)
+		debug_area_last = id->prev;
+	if (id->prev)
+		id->prev->next = id->next;
+	if (id->next)
+		id->next->prev = id->prev;
+}
+
 /**
  * debug_unregister() - give back debug area.
  *
@@ -730,8 +739,10 @@
 	if (!id)
 		return;
 	mutex_lock(&debug_mutex);
-	debug_info_put(id);
+	_debug_unregister(id);
 	mutex_unlock(&debug_mutex);
+
+	debug_info_put(id);
 }
 EXPORT_SYMBOL(debug_unregister);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/diag.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/diag.c
@@ -84,7 +84,7 @@
 
 static void *show_diag_stat_start(struct seq_file *m, loff_t *pos)
 {
-	return *pos <= nr_cpu_ids ? (void *)((unsigned long) *pos + 1) : NULL;
+	return *pos <= NR_DIAG_STAT ? (void *)((unsigned long) *pos + 1) : NULL;
 }
 
 static void *show_diag_stat_next(struct seq_file *m, void *v, loff_t *pos)
@@ -133,7 +133,7 @@
 }
 EXPORT_SYMBOL(diag_stat_inc);
 
-void diag_stat_inc_norecursion(enum diag_stat_enum nr)
+void notrace diag_stat_inc_norecursion(enum diag_stat_enum nr)
 {
 	this_cpu_inc(diag_stat.counter[nr]);
 	trace_s390_diagnose_norecursion(diag_map[nr].code);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/dis.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/dis.c
@@ -461,10 +461,11 @@
 				ptr += sprintf(ptr, "%%c%i", value);
 			else if (operand->flags & OPERAND_VR)
 				ptr += sprintf(ptr, "%%v%i", value);
-			else if (operand->flags & OPERAND_PCREL)
-				ptr += sprintf(ptr, "%lx", (signed int) value
-								      + addr);
-			else if (operand->flags & OPERAND_SIGNED)
+			else if (operand->flags & OPERAND_PCREL) {
+				void *pcrel = (void *)((int)value + addr);
+
+				ptr += sprintf(ptr, "%px", pcrel);
+			} else if (operand->flags & OPERAND_SIGNED)
 				ptr += sprintf(ptr, "%i", value);
 			else
 				ptr += sprintf(ptr, "%u", value);
@@ -536,7 +537,7 @@
 		else
 			*ptr++ = ' ';
 		addr = regs->psw.addr + start - 32;
-		ptr += sprintf(ptr, "%016lx: ", addr);
+		ptr += sprintf(ptr, "%px: ", (void *)addr);
 		if (start + opsize >= end)
 			break;
 		for (i = 0; i < opsize; i++)
@@ -556,7 +557,7 @@
 
 void print_fn_code(unsigned char *code, unsigned long len)
 {
-	char buffer[64], *ptr;
+	char buffer[128], *ptr;
 	int opsize, i;
 
 	while (len) {
@@ -564,7 +565,7 @@
 		opsize = insn_length(*code);
 		if (opsize > len)
 			break;
-		ptr += sprintf(ptr, "%p: ", code);
+		ptr += sprintf(ptr, "%px: ", code);
 		for (i = 0; i < opsize; i++)
 			ptr += sprintf(ptr, "%02x", code[i]);
 		*ptr++ = '\t';
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/dumpstack.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/dumpstack.c
@@ -210,5 +210,5 @@
 	if (panic_on_oops)
 		panic("Fatal exception: panic_on_oops");
 	oops_exit();
-	do_exit(SIGSEGV);
+	make_task_dead(SIGSEGV);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/early.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/early.c
@@ -169,6 +169,8 @@
 	psw_t psw;
 
 	psw.mask = PSW_MASK_BASE | PSW_DEFAULT_KEY | PSW_MASK_EA | PSW_MASK_BA;
+	if (IS_ENABLED(CONFIG_KASAN))
+		psw.mask |= PSW_MASK_DAT;
 	psw.addr = (unsigned long) s390_base_ext_handler;
 	S390_lowcore.external_new_psw = psw;
 	psw.addr = (unsigned long) s390_base_pgm_handler;
@@ -250,6 +252,10 @@
 		clock_comparator_max = -1ULL >> 1;
 		__ctl_set_bit(0, 53);
 	}
+	if (IS_ENABLED(CONFIG_PCI) && test_facility(153)) {
+		S390_lowcore.machine_flags |= MACHINE_FLAG_PCI_MIO;
+		/* the control bit is set during PCI initialization */
+	}
 }
 
 static inline void save_vector_registers(void)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/entry.S
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/entry.S
@@ -115,26 +115,29 @@
 
 	.macro	SWITCH_ASYNC savearea,timer
 	tmhh	%r8,0x0001		# interrupting from user ?
-	jnz	1f
+	jnz	2f
 	lgr	%r14,%r9
+	cghi	%r14,__LC_RETURN_LPSWE
+	je	0f
 	slg	%r14,BASED(.Lcritical_start)
 	clg	%r14,BASED(.Lcritical_length)
-	jhe	0f
+	jhe	1f
+0:
 	lghi	%r11,\savearea		# inside critical section, do cleanup
 	brasl	%r14,cleanup_critical
 	tmhh	%r8,0x0001		# retest problem state after cleanup
-	jnz	1f
-0:	lg	%r14,__LC_ASYNC_STACK	# are we already on the target stack?
+	jnz	2f
+1:	lg	%r14,__LC_ASYNC_STACK	# are we already on the target stack?
 	slgr	%r14,%r15
 	srag	%r14,%r14,STACK_SHIFT
-	jnz	2f
+	jnz	3f
 	CHECK_STACK \savearea
 	aghi	%r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
-	j	3f
-1:	UPDATE_VTIME %r14,%r15,\timer
+	j	4f
+2:	UPDATE_VTIME %r14,%r15,\timer
 	BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP
-2:	lg	%r15,__LC_ASYNC_STACK	# load async stack
-3:	la	%r11,STACK_FRAME_OVERHEAD(%r15)
+3:	lg	%r15,__LC_ASYNC_STACK	# load async stack
+4:	la	%r11,STACK_FRAME_OVERHEAD(%r15)
 	.endm
 
 	.macro UPDATE_VTIME w1,w2,enter_timer
@@ -365,9 +368,9 @@
 	jnz	.Lsysc_nr_ok
 	# svc 0: system call number in %r1
 	llgfr	%r1,%r1				# clear high word in r1
+	sth	%r1,__PT_INT_CODE+2(%r11)
 	cghi	%r1,NR_syscalls
 	jnl	.Lsysc_nr_ok
-	sth	%r1,__PT_INT_CODE+2(%r11)
 	slag	%r8,%r1,3
 .Lsysc_nr_ok:
 	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
@@ -401,7 +404,7 @@
 	stpt	__LC_EXIT_TIMER
 	mvc	__VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER
 	lmg	%r11,%r15,__PT_R11(%r11)
-	lpswe	__LC_RETURN_PSW
+	b	__LC_RETURN_LPSWE(%r0)
 .Lsysc_done:
 
 #
@@ -608,43 +611,50 @@
 	BPOFF
 	stmg	%r8,%r15,__LC_SAVE_AREA_SYNC
 	lg	%r10,__LC_LAST_BREAK
-	lg	%r12,__LC_CURRENT
+	srag	%r11,%r10,12
+	jnz	0f
+	/* if __LC_LAST_BREAK is < 4096, it contains one of
+	 * the lpswe addresses in lowcore. Set it to 1 (initial state)
+	 * to prevent leaking that address to userspace.
+	 */
+	lghi	%r10,1
+0:	lg	%r12,__LC_CURRENT
 	lghi	%r11,0
 	larl	%r13,cleanup_critical
 	lmg	%r8,%r9,__LC_PGM_OLD_PSW
 	tmhh	%r8,0x0001		# test problem state bit
-	jnz	2f			# -> fault in user space
+	jnz	3f			# -> fault in user space
 #if IS_ENABLED(CONFIG_KVM)
 	# cleanup critical section for program checks in sie64a
 	lgr	%r14,%r9
 	slg	%r14,BASED(.Lsie_critical_start)
 	clg	%r14,BASED(.Lsie_critical_length)
-	jhe	0f
+	jhe	1f
 	lg	%r14,__SF_SIE_CONTROL(%r15)	# get control block pointer
 	ni	__SIE_PROG0C+3(%r14),0xfe	# no longer in SIE
 	lctlg	%c1,%c1,__LC_USER_ASCE		# load primary asce
 	larl	%r9,sie_exit			# skip forward to sie_exit
 	lghi	%r11,_PIF_GUEST_FAULT
 #endif
-0:	tmhh	%r8,0x4000		# PER bit set in old PSW ?
-	jnz	1f			# -> enabled, can't be a double fault
+1:	tmhh	%r8,0x4000		# PER bit set in old PSW ?
+	jnz	2f			# -> enabled, can't be a double fault
 	tm	__LC_PGM_ILC+3,0x80	# check for per exception
 	jnz	.Lpgm_svcper		# -> single stepped svc
-1:	CHECK_STACK __LC_SAVE_AREA_SYNC
+2:	CHECK_STACK __LC_SAVE_AREA_SYNC
 	aghi	%r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
-	# CHECK_VMAP_STACK branches to stack_overflow or 4f
-	CHECK_VMAP_STACK __LC_SAVE_AREA_SYNC,4f
-2:	UPDATE_VTIME %r14,%r15,__LC_SYNC_ENTER_TIMER
+	# CHECK_VMAP_STACK branches to stack_overflow or 5f
+	CHECK_VMAP_STACK __LC_SAVE_AREA_SYNC,5f
+3:	UPDATE_VTIME %r14,%r15,__LC_SYNC_ENTER_TIMER
 	BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP
 	lg	%r15,__LC_KERNEL_STACK
 	lgr	%r14,%r12
 	aghi	%r14,__TASK_thread	# pointer to thread_struct
 	lghi	%r13,__LC_PGM_TDB
 	tm	__LC_PGM_ILC+2,0x02	# check for transaction abort
-	jz	3f
+	jz	4f
 	mvc	__THREAD_trap_tdb(256,%r14),0(%r13)
-3:	stg	%r10,__THREAD_last_break(%r14)
-4:	lgr	%r13,%r11
+4:	stg	%r10,__THREAD_last_break(%r14)
+5:	lgr	%r13,%r11
 	la	%r11,STACK_FRAME_OVERHEAD(%r15)
 	stmg	%r0,%r7,__PT_R0(%r11)
 	# clear user controlled registers to prevent speculative use
@@ -663,14 +673,14 @@
 	stg	%r13,__PT_FLAGS(%r11)
 	stg	%r10,__PT_ARGS(%r11)
 	tm	__LC_PGM_ILC+3,0x80	# check for per exception
-	jz	5f
+	jz	6f
 	tmhh	%r8,0x0001		# kernel per event ?
 	jz	.Lpgm_kprobe
 	oi	__PT_FLAGS+7(%r11),_PIF_PER_TRAP
 	mvc	__THREAD_per_address(8,%r14),__LC_PER_ADDRESS
 	mvc	__THREAD_per_cause(2,%r14),__LC_PER_CODE
 	mvc	__THREAD_per_paid(1,%r14),__LC_PER_ACCESS_ID
-5:	REENABLE_IRQS
+6:	REENABLE_IRQS
 	xc	__SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
 	larl	%r1,pgm_check_table
 	llgh	%r10,__PT_INT_CODE+2(%r11)
@@ -775,7 +785,7 @@
 	mvc	__VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER
 .Lio_exit_kernel:
 	lmg	%r11,%r15,__PT_R11(%r11)
-	lpswe	__LC_RETURN_PSW
+	b	__LC_RETURN_LPSWE(%r0)
 .Lio_done:
 
 #
@@ -983,6 +993,7 @@
  * Load idle PSW. The second "half" of this function is in .Lcleanup_idle.
  */
 ENTRY(psw_idle)
+	stg	%r14,(__SF_GPRS+8*8)(%r15)
 	stg	%r3,__SF_EMPTY(%r15)
 	larl	%r1,.Lpsw_idle_lpsw+4
 	stg	%r1,__SF_EMPTY+8(%r15)
@@ -1214,7 +1225,7 @@
 	stpt	__LC_EXIT_TIMER
 	mvc	__VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER
 0:	lmg	%r11,%r15,__PT_R11(%r11)
-	lpswe	__LC_RETURN_MCCK_PSW
+	b	__LC_RETURN_MCCK_LPSWE
 
 .Lmcck_panic:
 	lg	%r15,__LC_NODAT_STACK
@@ -1271,6 +1282,8 @@
 #endif
 
 ENTRY(cleanup_critical)
+	cghi	%r9,__LC_RETURN_LPSWE
+	je	.Lcleanup_lpswe
 #if IS_ENABLED(CONFIG_KVM)
 	clg	%r9,BASED(.Lcleanup_table_sie)	# .Lsie_gmap
 	jl	0f
@@ -1424,6 +1437,7 @@
 	mvc	__LC_RETURN_PSW(16),__PT_PSW(%r9)
 	mvc	0(64,%r11),__PT_R8(%r9)
 	lmg	%r0,%r7,__PT_R0(%r9)
+.Lcleanup_lpswe:
 1:	lmg	%r8,%r9,__LC_RETURN_PSW
 	BR_EX	%r14,%r11
 .Lcleanup_sysc_restore_insn:
@@ -1528,6 +1542,7 @@
 	.quad   .Lsie_skip - .Lsie_entry
 #endif
 	.section .rodata, "a"
+	.balign	8
 #define SYSCALL(esame,emu)	.quad __s390x_ ## esame
 	.globl	sys_call_table
 sys_call_table:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/entry.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/entry.h
@@ -24,6 +24,8 @@
 
 void do_protection_exception(struct pt_regs *regs);
 void do_dat_exception(struct pt_regs *regs);
+void do_secure_storage_access(struct pt_regs *regs);
+void do_non_secure_storage_access(struct pt_regs *regs);
 
 void addressing_exception(struct pt_regs *regs);
 void data_exception(struct pt_regs *regs);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/ftrace.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/ftrace.c
@@ -57,6 +57,7 @@
  * >	brasl	%r0,ftrace_caller	# offset 0
  */
 
+void *ftrace_func __read_mostly = ftrace_stub;
 unsigned long ftrace_plt;
 
 static inline void ftrace_generate_orig_insn(struct ftrace_insn *insn)
@@ -72,15 +73,6 @@
 #endif
 }
 
-static inline int is_kprobe_on_ftrace(struct ftrace_insn *insn)
-{
-#ifdef CONFIG_KPROBES
-	if (insn->opc == BREAKPOINT_INSTRUCTION)
-		return 1;
-#endif
-	return 0;
-}
-
 static inline void ftrace_generate_kprobe_nop_insn(struct ftrace_insn *insn)
 {
 #ifdef CONFIG_KPROBES
@@ -114,16 +106,6 @@
 		/* Initial code replacement */
 		ftrace_generate_orig_insn(&orig);
 		ftrace_generate_nop_insn(&new);
-	} else if (is_kprobe_on_ftrace(&old)) {
-		/*
-		 * If we find a breakpoint instruction, a kprobe has been
-		 * placed at the beginning of the function. We write the
-		 * constant KPROBE_ON_FTRACE_NOP into the remaining four
-		 * bytes of the original instruction so that the kprobes
-		 * handler can execute a nop, if it reaches this breakpoint.
-		 */
-		ftrace_generate_kprobe_call_insn(&orig);
-		ftrace_generate_kprobe_nop_insn(&new);
 	} else {
 		/* Replace ftrace call with a nop. */
 		ftrace_generate_call_insn(&orig, rec->ip);
@@ -142,21 +124,10 @@
 
 	if (probe_kernel_read(&old, (void *) rec->ip, sizeof(old)))
 		return -EFAULT;
-	if (is_kprobe_on_ftrace(&old)) {
-		/*
-		 * If we find a breakpoint instruction, a kprobe has been
-		 * placed at the beginning of the function. We write the
-		 * constant KPROBE_ON_FTRACE_CALL into the remaining four
-		 * bytes of the original instruction so that the kprobes
-		 * handler can execute a brasl if it reaches this breakpoint.
-		 */
-		ftrace_generate_kprobe_nop_insn(&orig);
-		ftrace_generate_kprobe_call_insn(&new);
-	} else {
-		/* Replace nop with an ftrace call. */
-		ftrace_generate_nop_insn(&orig);
-		ftrace_generate_call_insn(&new, rec->ip);
-	}
+	/* Replace nop with an ftrace call. */
+	ftrace_generate_nop_insn(&orig);
+	ftrace_generate_call_insn(&new, rec->ip);
+
 	/* Verify that the to be replaced code matches what we expect. */
 	if (memcmp(&orig, &old, sizeof(old)))
 		return -EINVAL;
@@ -166,6 +137,7 @@
 
 int ftrace_update_ftrace_func(ftrace_func_t func)
 {
+	ftrace_func = func;
 	return 0;
 }
 
@@ -241,3 +213,45 @@
 }
 
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+
+#ifdef CONFIG_KPROBES_ON_FTRACE
+void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
+		struct ftrace_ops *ops, struct pt_regs *regs)
+{
+	struct kprobe_ctlblk *kcb;
+	struct kprobe *p = get_kprobe((kprobe_opcode_t *)ip);
+
+	if (unlikely(!p) || kprobe_disabled(p))
+		return;
+
+	if (kprobe_running()) {
+		kprobes_inc_nmissed_count(p);
+		return;
+	}
+
+	__this_cpu_write(current_kprobe, p);
+
+	kcb = get_kprobe_ctlblk();
+	kcb->kprobe_status = KPROBE_HIT_ACTIVE;
+
+	instruction_pointer_set(regs, ip);
+
+	if (!p->pre_handler || !p->pre_handler(p, regs)) {
+
+		instruction_pointer_set(regs, ip + MCOUNT_INSN_SIZE);
+
+		if (unlikely(p->post_handler)) {
+			kcb->kprobe_status = KPROBE_HIT_SSDONE;
+			p->post_handler(p, regs, 0);
+		}
+	}
+	__this_cpu_write(current_kprobe, NULL);
+}
+NOKPROBE_SYMBOL(kprobe_ftrace_handler);
+
+int arch_prepare_kprobe_ftrace(struct kprobe *p)
+{
+	p->ainsn.insn = NULL;
+	return 0;
+}
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/ipl.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/ipl.c
@@ -39,6 +39,7 @@
 #define IPL_CCW_STR		"ccw"
 #define IPL_FCP_STR		"fcp"
 #define IPL_FCP_DUMP_STR	"fcp_dump"
+#define IPL_NVME_STR		"nvme"
 #define IPL_NSS_STR		"nss"
 
 #define DUMP_CCW_STR		"ccw"
@@ -93,6 +94,8 @@
 		return IPL_FCP_DUMP_STR;
 	case IPL_TYPE_NSS:
 		return IPL_NSS_STR;
+	case IPL_TYPE_NVME:
+		return IPL_NVME_STR;
 	case IPL_TYPE_UNKNOWN:
 	default:
 		return IPL_UNKNOWN_STR;
@@ -133,6 +136,7 @@
 
 static enum ipl_type reipl_type = IPL_TYPE_UNKNOWN;
 static struct ipl_parameter_block *reipl_block_fcp;
+static struct ipl_parameter_block *reipl_block_nvme;
 static struct ipl_parameter_block *reipl_block_ccw;
 static struct ipl_parameter_block *reipl_block_nss;
 static struct ipl_parameter_block *reipl_block_actual;
@@ -258,6 +262,8 @@
 			return IPL_TYPE_FCP_DUMP;
 		else
 			return IPL_TYPE_FCP;
+	case IPL_PBT_NVME:
+		return IPL_TYPE_NVME;
 	}
 	return IPL_TYPE_UNKNOWN;
 }
@@ -314,6 +320,8 @@
 	case IPL_TYPE_FCP:
 	case IPL_TYPE_FCP_DUMP:
 		return sprintf(page, "0.0.%04x\n", ipl_block.fcp.devno);
+	case IPL_TYPE_NVME:
+		return sprintf(page, "%08ux\n", ipl_block.nvme.fid);
 	default:
 		return 0;
 	}
@@ -342,15 +350,35 @@
 
 	return memory_read_from_buffer(buf, count, &off, scp_data, size);
 }
+
+static ssize_t ipl_nvme_scp_data_read(struct file *filp, struct kobject *kobj,
+				 struct bin_attribute *attr, char *buf,
+				 loff_t off, size_t count)
+{
+	unsigned int size = ipl_block.nvme.scp_data_len;
+	void *scp_data = &ipl_block.nvme.scp_data;
+
+	return memory_read_from_buffer(buf, count, &off, scp_data, size);
+}
+
 static struct bin_attribute ipl_scp_data_attr =
 	__BIN_ATTR(scp_data, S_IRUGO, ipl_scp_data_read, NULL, PAGE_SIZE);
 
+static struct bin_attribute ipl_nvme_scp_data_attr =
+	__BIN_ATTR(scp_data, S_IRUGO, ipl_nvme_scp_data_read, NULL, PAGE_SIZE);
+
 static struct bin_attribute *ipl_fcp_bin_attrs[] = {
 	&ipl_parameter_attr,
 	&ipl_scp_data_attr,
 	NULL,
 };
 
+static struct bin_attribute *ipl_nvme_bin_attrs[] = {
+	&ipl_parameter_attr,
+	&ipl_nvme_scp_data_attr,
+	NULL,
+};
+
 /* FCP ipl device attributes */
 
 DEFINE_IPL_ATTR_RO(ipl_fcp, wwpn, "0x%016llx\n",
@@ -362,6 +390,16 @@
 DEFINE_IPL_ATTR_RO(ipl_fcp, br_lba, "%lld\n",
 		   (unsigned long long)ipl_block.fcp.br_lba);
 
+/* NVMe ipl device attributes */
+DEFINE_IPL_ATTR_RO(ipl_nvme, fid, "0x%08llx\n",
+		   (unsigned long long)ipl_block.nvme.fid);
+DEFINE_IPL_ATTR_RO(ipl_nvme, nsid, "0x%08llx\n",
+		   (unsigned long long)ipl_block.nvme.nsid);
+DEFINE_IPL_ATTR_RO(ipl_nvme, bootprog, "%lld\n",
+		   (unsigned long long)ipl_block.nvme.bootprog);
+DEFINE_IPL_ATTR_RO(ipl_nvme, br_lba, "%lld\n",
+		   (unsigned long long)ipl_block.nvme.br_lba);
+
 static ssize_t ipl_ccw_loadparm_show(struct kobject *kobj,
 				     struct kobj_attribute *attr, char *page)
 {
@@ -396,6 +434,24 @@
 	.bin_attrs = ipl_fcp_bin_attrs,
 };
 
+static struct attribute *ipl_nvme_attrs[] = {
+	&sys_ipl_type_attr.attr,
+	&sys_ipl_nvme_fid_attr.attr,
+	&sys_ipl_nvme_nsid_attr.attr,
+	&sys_ipl_nvme_bootprog_attr.attr,
+	&sys_ipl_nvme_br_lba_attr.attr,
+	&sys_ipl_ccw_loadparm_attr.attr,
+	&sys_ipl_secure_attr.attr,
+	&sys_ipl_has_secure_attr.attr,
+	NULL,
+};
+
+static struct attribute_group ipl_nvme_attr_group = {
+	.attrs = ipl_nvme_attrs,
+	.bin_attrs = ipl_nvme_bin_attrs,
+};
+
+
 /* CCW ipl device attributes */
 
 static struct attribute *ipl_ccw_attrs_vm[] = {
@@ -429,6 +485,8 @@
 
 static struct attribute *ipl_unknown_attrs[] = {
 	&sys_ipl_type_attr.attr,
+	&sys_ipl_secure_attr.attr,
+	&sys_ipl_has_secure_attr.attr,
 	NULL,
 };
 
@@ -471,6 +529,9 @@
 	case IPL_TYPE_FCP_DUMP:
 		rc = sysfs_create_group(&ipl_kset->kobj, &ipl_fcp_attr_group);
 		break;
+	case IPL_TYPE_NVME:
+		rc = sysfs_create_group(&ipl_kset->kobj, &ipl_nvme_attr_group);
+		break;
 	default:
 		rc = sysfs_create_group(&ipl_kset->kobj,
 					&ipl_unknown_attr_group);
@@ -706,6 +767,93 @@
 	.bin_attrs = reipl_fcp_bin_attrs,
 };
 
+/* NVME reipl device attributes */
+
+static ssize_t reipl_nvme_scpdata_read(struct file *filp, struct kobject *kobj,
+				      struct bin_attribute *attr,
+				      char *buf, loff_t off, size_t count)
+{
+	size_t size = reipl_block_nvme->nvme.scp_data_len;
+	void *scp_data = reipl_block_nvme->nvme.scp_data;
+
+	return memory_read_from_buffer(buf, count, &off, scp_data, size);
+}
+
+static ssize_t reipl_nvme_scpdata_write(struct file *filp, struct kobject *kobj,
+				       struct bin_attribute *attr,
+				       char *buf, loff_t off, size_t count)
+{
+	size_t scpdata_len = count;
+	size_t padding;
+
+	if (off)
+		return -EINVAL;
+
+	memcpy(reipl_block_nvme->nvme.scp_data, buf, count);
+	if (scpdata_len % 8) {
+		padding = 8 - (scpdata_len % 8);
+		memset(reipl_block_nvme->nvme.scp_data + scpdata_len,
+		       0, padding);
+		scpdata_len += padding;
+	}
+
+	reipl_block_nvme->hdr.len = IPL_BP_FCP_LEN + scpdata_len;
+	reipl_block_nvme->nvme.len = IPL_BP0_FCP_LEN + scpdata_len;
+	reipl_block_nvme->nvme.scp_data_len = scpdata_len;
+
+	return count;
+}
+
+static struct bin_attribute sys_reipl_nvme_scp_data_attr =
+	__BIN_ATTR(scp_data, (S_IRUGO | S_IWUSR), reipl_nvme_scpdata_read,
+		   reipl_nvme_scpdata_write, DIAG308_SCPDATA_SIZE);
+
+static struct bin_attribute *reipl_nvme_bin_attrs[] = {
+	&sys_reipl_nvme_scp_data_attr,
+	NULL,
+};
+
+DEFINE_IPL_ATTR_RW(reipl_nvme, fid, "0x%08llx\n", "%llx\n",
+		   reipl_block_nvme->nvme.fid);
+DEFINE_IPL_ATTR_RW(reipl_nvme, nsid, "0x%08llx\n", "%llx\n",
+		   reipl_block_nvme->nvme.nsid);
+DEFINE_IPL_ATTR_RW(reipl_nvme, bootprog, "%lld\n", "%lld\n",
+		   reipl_block_nvme->nvme.bootprog);
+DEFINE_IPL_ATTR_RW(reipl_nvme, br_lba, "%lld\n", "%lld\n",
+		   reipl_block_nvme->nvme.br_lba);
+
+/* nvme wrapper */
+static ssize_t reipl_nvme_loadparm_show(struct kobject *kobj,
+				       struct kobj_attribute *attr, char *page)
+{
+	return reipl_generic_loadparm_show(reipl_block_nvme, page);
+}
+
+static ssize_t reipl_nvme_loadparm_store(struct kobject *kobj,
+					struct kobj_attribute *attr,
+					const char *buf, size_t len)
+{
+	return reipl_generic_loadparm_store(reipl_block_nvme, buf, len);
+}
+
+static struct kobj_attribute sys_reipl_nvme_loadparm_attr =
+	__ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_nvme_loadparm_show,
+					    reipl_nvme_loadparm_store);
+
+static struct attribute *reipl_nvme_attrs[] = {
+	&sys_reipl_nvme_fid_attr.attr,
+	&sys_reipl_nvme_nsid_attr.attr,
+	&sys_reipl_nvme_bootprog_attr.attr,
+	&sys_reipl_nvme_br_lba_attr.attr,
+	&sys_reipl_nvme_loadparm_attr.attr,
+	NULL,
+};
+
+static struct attribute_group reipl_nvme_attr_group = {
+	.attrs = reipl_nvme_attrs,
+	.bin_attrs = reipl_nvme_bin_attrs
+};
+
 /* CCW reipl device attributes */
 DEFINE_IPL_CCW_ATTR_RW(reipl_ccw, device, reipl_block_ccw->ccw);
 
@@ -850,6 +998,9 @@
 	case IPL_TYPE_FCP:
 		reipl_block_actual = reipl_block_fcp;
 		break;
+	case IPL_TYPE_NVME:
+		reipl_block_actual = reipl_block_nvme;
+		break;
 	case IPL_TYPE_NSS:
 		reipl_block_actual = reipl_block_nss;
 		break;
@@ -876,6 +1027,8 @@
 		rc = reipl_set_type(IPL_TYPE_CCW);
 	else if (strncmp(buf, IPL_FCP_STR, strlen(IPL_FCP_STR)) == 0)
 		rc = reipl_set_type(IPL_TYPE_FCP);
+	else if (strncmp(buf, IPL_NVME_STR, strlen(IPL_NVME_STR)) == 0)
+		rc = reipl_set_type(IPL_TYPE_NVME);
 	else if (strncmp(buf, IPL_NSS_STR, strlen(IPL_NSS_STR)) == 0)
 		rc = reipl_set_type(IPL_TYPE_NSS);
 	return (rc != 0) ? rc : len;
@@ -886,6 +1039,7 @@
 
 static struct kset *reipl_kset;
 static struct kset *reipl_fcp_kset;
+static struct kset *reipl_nvme_kset;
 
 static void __reipl_run(void *unused)
 {
@@ -898,6 +1052,10 @@
 		diag308(DIAG308_SET, reipl_block_fcp);
 		diag308(DIAG308_LOAD_CLEAR, NULL);
 		break;
+	case IPL_TYPE_NVME:
+		diag308(DIAG308_SET, reipl_block_nvme);
+		diag308(DIAG308_LOAD_CLEAR, NULL);
+		break;
 	case IPL_TYPE_NSS:
 		diag308(DIAG308_SET, reipl_block_nss);
 		diag308(DIAG308_LOAD_CLEAR, NULL);
@@ -1034,6 +1192,49 @@
 	return 0;
 }
 
+static int __init reipl_nvme_init(void)
+{
+	int rc;
+
+	reipl_block_nvme = (void *) get_zeroed_page(GFP_KERNEL);
+	if (!reipl_block_nvme)
+		return -ENOMEM;
+
+	/* sysfs: create kset for mixing attr group and bin attrs */
+	reipl_nvme_kset = kset_create_and_add(IPL_NVME_STR, NULL,
+					     &reipl_kset->kobj);
+	if (!reipl_nvme_kset) {
+		free_page((unsigned long) reipl_block_nvme);
+		return -ENOMEM;
+	}
+
+	rc = sysfs_create_group(&reipl_nvme_kset->kobj, &reipl_nvme_attr_group);
+	if (rc) {
+		kset_unregister(reipl_nvme_kset);
+		free_page((unsigned long) reipl_block_nvme);
+		return rc;
+	}
+
+	if (ipl_info.type == IPL_TYPE_NVME) {
+		memcpy(reipl_block_nvme, &ipl_block, sizeof(ipl_block));
+		/*
+		 * Fix loadparm: There are systems where the (SCSI) LOADPARM
+		 * is invalid in the IPL parameter block, so take it
+		 * always from sclp_ipl_info.
+		 */
+		memcpy(reipl_block_nvme->nvme.loadparm, sclp_ipl_info.loadparm,
+		       LOADPARM_LEN);
+	} else {
+		reipl_block_nvme->hdr.len = IPL_BP_NVME_LEN;
+		reipl_block_nvme->hdr.version = IPL_PARM_BLOCK_VERSION;
+		reipl_block_nvme->nvme.len = IPL_BP0_NVME_LEN;
+		reipl_block_nvme->nvme.pbt = IPL_PBT_NVME;
+		reipl_block_nvme->nvme.opt = IPL_PB0_NVME_OPT_IPL;
+	}
+	reipl_capabilities |= IPL_TYPE_NVME;
+	return 0;
+}
+
 static int __init reipl_type_init(void)
 {
 	enum ipl_type reipl_type = ipl_info.type;
@@ -1049,6 +1250,9 @@
 	if (reipl_block->pb0_hdr.pbt == IPL_PBT_FCP) {
 		memcpy(reipl_block_fcp, reipl_block, size);
 		reipl_type = IPL_TYPE_FCP;
+	} else if (reipl_block->pb0_hdr.pbt == IPL_PBT_NVME) {
+		memcpy(reipl_block_nvme, reipl_block, size);
+		reipl_type = IPL_TYPE_NVME;
 	} else if (reipl_block->pb0_hdr.pbt == IPL_PBT_CCW) {
 		memcpy(reipl_block_ccw, reipl_block, size);
 		reipl_type = IPL_TYPE_CCW;
@@ -1075,6 +1279,9 @@
 	rc = reipl_fcp_init();
 	if (rc)
 		return rc;
+	rc = reipl_nvme_init();
+	if (rc)
+		return rc;
 	rc = reipl_nss_init();
 	if (rc)
 		return rc;
@@ -1691,6 +1898,10 @@
 		ipl_info.data.fcp.wwpn = ipl_block.fcp.wwpn;
 		ipl_info.data.fcp.lun = ipl_block.fcp.lun;
 		break;
+	case IPL_TYPE_NVME:
+		ipl_info.data.nvme.fid = ipl_block.nvme.fid;
+		ipl_info.data.nvme.nsid = ipl_block.nvme.nsid;
+		break;
 	case IPL_TYPE_NSS:
 	case IPL_TYPE_UNKNOWN:
 		/* We have no info to copy */
@@ -1783,7 +1994,7 @@
 
 	buf = vzalloc(report->size);
 	if (!buf)
-		return ERR_PTR(-ENOMEM);
+		goto out;
 	ptr = buf;
 
 	memcpy(ptr, report->ipib, report->ipib->hdr.len);
@@ -1822,6 +2033,7 @@
 	}
 
 	BUG_ON(ptr > buf + report->size);
+out:
 	return buf;
 }
 
@@ -1842,3 +2054,8 @@
 }
 
 #endif
+
+bool ipl_get_secureboot(void)
+{
+	return !!ipl_secure_flag;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/irq.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/irq.c
@@ -294,11 +294,6 @@
 	return IRQ_HANDLED;
 }
 
-static struct irqaction external_interrupt = {
-	.name	 = "EXT",
-	.handler = do_ext_interrupt,
-};
-
 void __init init_ext_interrupts(void)
 {
 	int idx;
@@ -308,7 +303,8 @@
 
 	irq_set_chip_and_handler(EXT_INTERRUPT,
 				 &dummy_irq_chip, handle_percpu_irq);
-	setup_irq(EXT_INTERRUPT, &external_interrupt);
+	if (request_irq(EXT_INTERRUPT, do_ext_interrupt, 0, "EXT", NULL))
+		panic("Failed to register EXT interrupt\n");
 }
 
 static DEFINE_SPINLOCK(irq_subclass_lock);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/jump_label.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/jump_label.c
@@ -36,7 +36,7 @@
 	unsigned char *ipe = (unsigned char *)expected;
 	unsigned char *ipn = (unsigned char *)new;
 
-	pr_emerg("Jump label code mismatch at %pS [%p]\n", ipc, ipc);
+	pr_emerg("Jump label code mismatch at %pS [%px]\n", ipc, ipc);
 	pr_emerg("Found:    %6ph\n", ipc);
 	pr_emerg("Expected: %6ph\n", ipe);
 	pr_emerg("New:      %6ph\n", ipn);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/kmsg.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/kmsg.c
@@ -0,0 +1,114 @@
+/*
+ * Message printing with message catalog prefixes.
+ *
+ * Copyright IBM Corp. 2012
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/jhash.h>
+#include <linux/device.h>
+
+static inline u32 __printk_jhash(const void *key, u32 length)
+{
+	u32 a, b, c, len;
+	const u8 *k;
+	u8 zk[12];
+
+	a = b = 0x9e3779b9;
+	c = 0;
+	for (len = length + 12, k = key; len >= 12; len -= 12, k += 12) {
+		if (len >= 24) {
+			a += k[0] | k[1] << 8 | k[2] << 16 | k[3] << 24;
+			b += k[4] | k[5] << 8 | k[6] << 16 | k[7] << 24;
+			c += k[8] | k[9] << 8 | k[10] << 16 | k[11] << 24;
+		} else {
+			memset(zk, 0, 12);
+			memcpy(zk, k, len - 12);
+			a += zk[0] | zk[1] << 8 | zk[2] << 16 | zk[3] << 24;
+			b += zk[4] | zk[5] << 8 | zk[6] << 16 | zk[7] << 24;
+			c += (u32) zk[8] << 8;
+			c += (u32) zk[9] << 16;
+			c += (u32) zk[10] << 24;
+			c += length;
+		}
+		a -= b + c; a ^= (c>>13);
+		b -= a + c; b ^= (a<<8);
+		c -= a + b; c ^= (b>>13);
+		a -= b + c; a ^= (c>>12);
+		b -= a + c; b ^= (a<<16);
+		c -= a + b; c ^= (b>>5);
+		a -= b + c; a ^= (c>>3);
+		b -= a + c; b ^= (a<<10);
+		c -= a + b; c ^= (b>>15);
+	}
+	return c;
+}
+
+/**
+ * __jhash_string - calculate the six digit jhash of a string
+ * @str: string to calculate the jhash
+ */
+unsigned long long __jhash_string(const char *str)
+{
+	return __printk_jhash(str, strlen(str)) & 0xffffff;
+}
+EXPORT_SYMBOL(__jhash_string);
+
+static int __dev_printk_hash(const char *level, const struct device *dev,
+			     struct va_format *vaf)
+{
+	if (!dev)
+		return printk("%s(NULL device *): %pV", level, vaf);
+
+	return printk("%s%s.%06x: %pV", level, dev_driver_string(dev),
+		      __printk_jhash(vaf->fmt, strlen(vaf->fmt)) & 0xffffff,
+		      vaf);
+}
+
+int dev_printk_hash(const char *level, const struct device *dev,
+		    const char *fmt, ...)
+{
+	struct va_format vaf;
+	va_list args;
+	int r;
+
+	va_start(args, fmt);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	r = __dev_printk_hash(level, dev, &vaf);
+	va_end(args);
+
+	return r;
+}
+EXPORT_SYMBOL(dev_printk_hash);
+
+#define define_dev_printk_hash_level(func, kern_level)		\
+int func(const struct device *dev, const char *fmt, ...)	\
+{								\
+	struct va_format vaf;					\
+	va_list args;						\
+	int r;							\
+								\
+	va_start(args, fmt);					\
+								\
+	vaf.fmt = fmt;						\
+	vaf.va = &args;						\
+								\
+	r = __dev_printk_hash(kern_level, dev, &vaf);		\
+	va_end(args);						\
+								\
+	return r;						\
+}								\
+EXPORT_SYMBOL(func);
+
+define_dev_printk_hash_level(dev_emerg_hash, KERN_EMERG);
+define_dev_printk_hash_level(dev_alert_hash, KERN_ALERT);
+define_dev_printk_hash_level(dev_crit_hash, KERN_CRIT);
+define_dev_printk_hash_level(dev_err_hash, KERN_ERR);
+define_dev_printk_hash_level(dev_warn_hash, KERN_WARNING);
+define_dev_printk_hash_level(dev_notice_hash, KERN_NOTICE);
+define_dev_printk_hash_level(_dev_info_hash, KERN_INFO);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/kprobes.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/kprobes.c
@@ -56,21 +56,10 @@
 
 static void copy_instruction(struct kprobe *p)
 {
-	unsigned long ip = (unsigned long) p->addr;
 	s64 disp, new_disp;
 	u64 addr, new_addr;
 
-	if (ftrace_location(ip) == ip) {
-		/*
-		 * If kprobes patches the instruction that is morphed by
-		 * ftrace make sure that kprobes always sees the branch
-		 * "jg .+24" that skips the mcount block or the "brcl 0,0"
-		 * in case of hotpatch.
-		 */
-		ftrace_generate_nop_insn((struct ftrace_insn *)p->ainsn.insn);
-		p->ainsn.is_ftrace_insn = 1;
-	} else
-		memcpy(p->ainsn.insn, p->addr, insn_length(*p->addr >> 8));
+	memcpy(p->ainsn.insn, p->addr, insn_length(*p->addr >> 8));
 	p->opcode = p->ainsn.insn[0];
 	if (!probe_is_insn_relative_long(p->ainsn.insn))
 		return;
@@ -136,11 +125,6 @@
 }
 NOKPROBE_SYMBOL(arch_prepare_kprobe);
 
-int arch_check_ftrace_location(struct kprobe *p)
-{
-	return 0;
-}
-
 struct swap_insn_args {
 	struct kprobe *p;
 	unsigned int arm_kprobe : 1;
@@ -149,28 +133,11 @@
 static int swap_instruction(void *data)
 {
 	struct swap_insn_args *args = data;
-	struct ftrace_insn new_insn, *insn;
 	struct kprobe *p = args->p;
-	size_t len;
+	u16 opc;
 
-	new_insn.opc = args->arm_kprobe ? BREAKPOINT_INSTRUCTION : p->opcode;
-	len = sizeof(new_insn.opc);
-	if (!p->ainsn.is_ftrace_insn)
-		goto skip_ftrace;
-	len = sizeof(new_insn);
-	insn = (struct ftrace_insn *) p->addr;
-	if (args->arm_kprobe) {
-		if (is_ftrace_nop(insn))
-			new_insn.disp = KPROBE_ON_FTRACE_NOP;
-		else
-			new_insn.disp = KPROBE_ON_FTRACE_CALL;
-	} else {
-		ftrace_generate_call_insn(&new_insn, (unsigned long)p->addr);
-		if (insn->disp == KPROBE_ON_FTRACE_NOP)
-			ftrace_generate_nop_insn(&new_insn);
-	}
-skip_ftrace:
-	s390_kernel_write(p->addr, &new_insn, len);
+	opc = args->arm_kprobe ? BREAKPOINT_INSTRUCTION : p->opcode;
+	s390_kernel_write(p->addr, &opc, sizeof(opc));
 	return 0;
 }
 NOKPROBE_SYMBOL(swap_instruction);
@@ -255,6 +222,7 @@
 {
 	__this_cpu_write(current_kprobe, kcb->prev_kprobe.kp);
 	kcb->kprobe_status = kcb->prev_kprobe.status;
+	kcb->prev_kprobe.kp = NULL;
 }
 NOKPROBE_SYMBOL(pop_kprobe);
 
@@ -464,24 +432,6 @@
 	unsigned long ip = regs->psw.addr;
 	int fixup = probe_get_fixup_type(p->ainsn.insn);
 
-	/* Check if the kprobes location is an enabled ftrace caller */
-	if (p->ainsn.is_ftrace_insn) {
-		struct ftrace_insn *insn = (struct ftrace_insn *) p->addr;
-		struct ftrace_insn call_insn;
-
-		ftrace_generate_call_insn(&call_insn, (unsigned long) p->addr);
-		/*
-		 * A kprobe on an enabled ftrace call site actually single
-		 * stepped an unconditional branch (ftrace nop equivalent).
-		 * Now we need to fixup things and pretend that a brasl r0,...
-		 * was executed instead.
-		 */
-		if (insn->disp == KPROBE_ON_FTRACE_CALL) {
-			ip += call_insn.disp * 2 - MCOUNT_INSN_SIZE;
-			regs->gprs[0] = (unsigned long)p->addr + sizeof(*insn);
-		}
-	}
-
 	if (fixup & FIXUP_PSW_NORMAL)
 		ip += (unsigned long) p->addr - (unsigned long) p->ainsn.insn;
 
@@ -509,12 +459,11 @@
 	if (!p)
 		return 0;
 
+	resume_execution(p, regs);
 	if (kcb->kprobe_status != KPROBE_REENTER && p->post_handler) {
 		kcb->kprobe_status = KPROBE_HIT_SSDONE;
 		p->post_handler(p, regs, 0);
 	}
-
-	resume_execution(p, regs);
 	pop_kprobe(kcb);
 	preempt_enable_no_resched();
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/machine_kexec.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/machine_kexec.c
@@ -164,7 +164,9 @@
 #ifdef CONFIG_CRASH_DUMP
 	int rc;
 
+	preempt_disable();
 	rc = CALL_ON_STACK(do_start_kdump, S390_lowcore.nodat_stack, 1, image);
+	preempt_enable();
 	return rc == 0;
 #else
 	return false;
@@ -254,10 +256,10 @@
 	VMCOREINFO_SYMBOL(lowcore_ptr);
 	VMCOREINFO_SYMBOL(high_memory);
 	VMCOREINFO_LENGTH(lowcore_ptr, NR_CPUS);
-	mem_assign_absolute(S390_lowcore.vmcore_info, paddr_vmcoreinfo_note());
 	vmcoreinfo_append_str("SDMA=%lx\n", __sdma);
 	vmcoreinfo_append_str("EDMA=%lx\n", __edma);
 	vmcoreinfo_append_str("KERNELOFFSET=%lx\n", kaslr_offset());
+	mem_assign_absolute(S390_lowcore.vmcore_info, paddr_vmcoreinfo_note());
 }
 
 void machine_shutdown(void)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/machine_kexec_file.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/machine_kexec_file.c
@@ -12,6 +12,7 @@
 #include <linux/kexec.h>
 #include <linux/module_signature.h>
 #include <linux/verification.h>
+#include <linux/vmalloc.h>
 #include <asm/boot_data.h>
 #include <asm/ipl.h>
 #include <asm/setup.h>
@@ -28,6 +29,7 @@
 	const unsigned long marker_len = sizeof(MODULE_SIG_STRING) - 1;
 	struct module_signature *ms;
 	unsigned long sig_len;
+	int ret;
 
 	/* Skip signature verification when not secure IPLed. */
 	if (!ipl_secure_flag)
@@ -62,11 +64,18 @@
 		return -EBADMSG;
 	}
 
-	return verify_pkcs7_signature(kernel, kernel_len,
-				      kernel + kernel_len, sig_len,
-				      VERIFY_USE_PLATFORM_KEYRING,
-				      VERIFYING_MODULE_SIGNATURE,
-				      NULL, NULL);
+	ret = verify_pkcs7_signature(kernel, kernel_len,
+				     kernel + kernel_len, sig_len,
+				     VERIFY_USE_SECONDARY_KEYRING,
+				     VERIFYING_MODULE_SIGNATURE,
+				     NULL, NULL);
+	if (ret == -ENOKEY && IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING))
+		ret = verify_pkcs7_signature(kernel, kernel_len,
+					     kernel + kernel_len, sig_len,
+					     VERIFY_USE_PLATFORM_KEYRING,
+					     VERIFYING_MODULE_SIGNATURE,
+					     NULL, NULL);
+	return ret;
 }
 #endif /* CONFIG_KEXEC_SIG */
 
@@ -151,7 +160,7 @@
 		buf.mem += crashk_res.start;
 	buf.memsz = buf.bufsz;
 
-	data->parm->initrd_start = buf.mem;
+	data->parm->initrd_start = data->memsz;
 	data->parm->initrd_size = buf.memsz;
 	data->memsz += buf.memsz;
 
@@ -170,13 +179,12 @@
 	struct kexec_buf buf;
 	unsigned long addr;
 	void *ptr, *end;
+	int ret;
 
 	buf.image = image;
 
 	data->memsz = ALIGN(data->memsz, PAGE_SIZE);
 	buf.mem = data->memsz;
-	if (image->type == KEXEC_TYPE_CRASH)
-		buf.mem += crashk_res.start;
 
 	ptr = (void *)ipl_cert_list_addr;
 	end = ptr + ipl_cert_list_size;
@@ -199,9 +207,13 @@
 		ptr += len;
 	}
 
+	ret = -ENOMEM;
 	buf.buffer = ipl_report_finish(data->report);
+	if (!buf.buffer)
+		goto out;
 	buf.bufsz = data->report->size;
 	buf.memsz = buf.bufsz;
+	image->arch.ipl_buf = buf.buffer;
 
 	data->memsz += buf.memsz;
 
@@ -209,7 +221,12 @@
 		data->kernel_buf + offsetof(struct lowcore, ipl_parmblock_ptr);
 	*lc_ipl_parmblock_ptr = (__u32)buf.mem;
 
-	return kexec_add_buffer(&buf);
+	if (image->type == KEXEC_TYPE_CRASH)
+		buf.mem += crashk_res.start;
+
+	ret = kexec_add_buffer(&buf);
+out:
+	return ret;
 }
 
 void *kexec_file_add_components(struct kimage *image,
@@ -269,6 +286,7 @@
 {
 	Elf_Rela *relas;
 	int i, r_type;
+	int ret;
 
 	relas = (void *)pi->ehdr + relsec->sh_offset;
 
@@ -303,7 +321,11 @@
 		addr = section->sh_addr + relas[i].r_offset;
 
 		r_type = ELF64_R_TYPE(relas[i].r_info);
-		arch_kexec_do_relocs(r_type, loc, val, addr);
+		ret = arch_kexec_do_relocs(r_type, loc, val, addr);
+		if (ret) {
+			pr_err("Unknown rela relocation: %d\n", r_type);
+			return -ENOEXEC;
+		}
 	}
 	return 0;
 }
@@ -321,3 +343,11 @@
 
 	return kexec_image_probe_default(image, buf, buf_len);
 }
+
+int arch_kimage_file_post_load_cleanup(struct kimage *image)
+{
+	vfree(image->arch.ipl_buf);
+	image->arch.ipl_buf = NULL;
+
+	return kexec_image_post_load_cleanup_default(image);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/machine_kexec_reloc.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/machine_kexec_reloc.c
@@ -28,6 +28,7 @@
 		break;
 	case R_390_64:		/* Direct 64 bit.  */
 	case R_390_GLOB_DAT:
+	case R_390_JMP_SLOT:
 		*(u64 *)loc = val;
 		break;
 	case R_390_PC16:	/* PC relative 16 bit.	*/
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/mcount.S
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/mcount.S
@@ -26,6 +26,12 @@
 #define STACK_PTREGS	  (STACK_FRAME_OVERHEAD)
 #define STACK_PTREGS_GPRS (STACK_PTREGS + __PT_GPRS)
 #define STACK_PTREGS_PSW  (STACK_PTREGS + __PT_PSW)
+#ifdef __PACK_STACK
+/* allocate just enough for r14, r15 and backchain */
+#define TRACED_FUNC_FRAME_SIZE	24
+#else
+#define TRACED_FUNC_FRAME_SIZE	STACK_FRAME_OVERHEAD
+#endif
 
 ENTRY(_mcount)
 	BR_EX	%r14
@@ -35,25 +41,39 @@
 ENTRY(ftrace_caller)
 	.globl	ftrace_regs_caller
 	.set	ftrace_regs_caller,ftrace_caller
+	stg	%r14,(__SF_GPRS+8*8)(%r15)	# save traced function caller
+	lghi	%r14,0				# save condition code
+	ipm	%r14				# don't put any instructions
+	sllg	%r14,%r14,16			# clobbering CC before this point
 	lgr	%r1,%r15
 #if !(defined(CC_USING_HOTPATCH) || defined(CC_USING_NOP_MCOUNT))
 	aghi	%r0,MCOUNT_RETURN_FIXUP
 #endif
-	aghi	%r15,-STACK_FRAME_SIZE
+	# allocate stack frame for ftrace_caller to contain traced function
+	aghi	%r15,-TRACED_FUNC_FRAME_SIZE
 	stg	%r1,__SF_BACKCHAIN(%r15)
+	stg	%r0,(__SF_GPRS+8*8)(%r15)
+	stg	%r15,(__SF_GPRS+9*8)(%r15)
+	# allocate pt_regs and stack frame for ftrace_trace_function
+	aghi	%r15,-STACK_FRAME_SIZE
 	stg	%r1,(STACK_PTREGS_GPRS+15*8)(%r15)
+	stg	%r14,(STACK_PTREGS_PSW)(%r15)
+	lg	%r14,(__SF_GPRS+8*8)(%r1)	# restore original return address
+	stosm	(STACK_PTREGS_PSW)(%r15),0
+	aghi	%r1,-TRACED_FUNC_FRAME_SIZE
+	stg	%r1,__SF_BACKCHAIN(%r15)
 	stg	%r0,(STACK_PTREGS_PSW+8)(%r15)
 	stmg	%r2,%r14,(STACK_PTREGS_GPRS+2*8)(%r15)
 #ifdef CONFIG_HAVE_MARCH_Z196_FEATURES
 	aghik	%r2,%r0,-MCOUNT_INSN_SIZE
 	lgrl	%r4,function_trace_op
-	lgrl	%r1,ftrace_trace_function
+	lgrl	%r1,ftrace_func
 #else
 	lgr	%r2,%r0
 	aghi	%r2,-MCOUNT_INSN_SIZE
 	larl	%r4,function_trace_op
 	lg	%r4,0(%r4)
-	larl	%r1,ftrace_trace_function
+	larl	%r1,ftrace_func
 	lg	%r1,0(%r1)
 #endif
 	lgr	%r3,%r14
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/nmi.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/nmi.c
@@ -179,7 +179,7 @@
 		       "malfunction (code 0x%016lx).\n", mcck.mcck_code);
 		printk(KERN_EMERG "mcck: task: %s, pid: %d.\n",
 		       current->comm, current->pid);
-		do_exit(SIGSEGV);
+		make_task_dead(SIGSEGV);
 	}
 }
 EXPORT_SYMBOL_GPL(s390_handle_mcck);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/perf_cpum_cf.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/perf_cpum_cf.c
@@ -199,7 +199,7 @@
 	[PERF_COUNT_HW_BUS_CYCLES]	    = -1,
 };
 
-static int __hw_perf_event_init(struct perf_event *event)
+static int __hw_perf_event_init(struct perf_event *event, unsigned int type)
 {
 	struct perf_event_attr *attr = &event->attr;
 	struct hw_perf_event *hwc = &event->hw;
@@ -207,7 +207,7 @@
 	int err = 0;
 	u64 ev;
 
-	switch (attr->type) {
+	switch (type) {
 	case PERF_TYPE_RAW:
 		/* Raw events are used to access counters directly,
 		 * hence do not permit excludes */
@@ -292,19 +292,38 @@
 	return err;
 }
 
+/* Events CPU_CYLCES and INSTRUCTIONS can be submitted with two different
+ * attribute::type values:
+ * - PERF_TYPE_HARDWARE:
+ * - pmu->type:
+ * Handle both type of invocations identical. They address the same hardware.
+ * The result is different when event modifiers exclude_kernel and/or
+ * exclude_user are also set.
+ */
+static int cpumf_pmu_event_type(struct perf_event *event)
+{
+	u64 ev = event->attr.config;
+
+	if (cpumf_generic_events_basic[PERF_COUNT_HW_CPU_CYCLES] == ev ||
+	    cpumf_generic_events_basic[PERF_COUNT_HW_INSTRUCTIONS] == ev ||
+	    cpumf_generic_events_user[PERF_COUNT_HW_CPU_CYCLES] == ev ||
+	    cpumf_generic_events_user[PERF_COUNT_HW_INSTRUCTIONS] == ev)
+		return PERF_TYPE_HARDWARE;
+	return PERF_TYPE_RAW;
+}
+
 static int cpumf_pmu_event_init(struct perf_event *event)
 {
+	unsigned int type = event->attr.type;
 	int err;
 
-	switch (event->attr.type) {
-	case PERF_TYPE_HARDWARE:
-	case PERF_TYPE_HW_CACHE:
-	case PERF_TYPE_RAW:
-		err = __hw_perf_event_init(event);
-		break;
-	default:
+	if (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_RAW)
+		err = __hw_perf_event_init(event, type);
+	else if (event->pmu->type == type)
+		/* Registered as unknown PMU */
+		err = __hw_perf_event_init(event, cpumf_pmu_event_type(event));
+	else
 		return -ENOENT;
-	}
 
 	if (unlikely(err) && event->destroy)
 		event->destroy(event);
@@ -553,7 +572,7 @@
 		return -ENODEV;
 
 	cpumf_pmu.attr_groups = cpumf_cf_event_group();
-	rc = perf_pmu_register(&cpumf_pmu, "cpum_cf", PERF_TYPE_RAW);
+	rc = perf_pmu_register(&cpumf_pmu, "cpum_cf", -1);
 	if (rc)
 		pr_err("Registering the cpum_cf PMU failed with rc=%i\n", rc);
 	return rc;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/perf_cpum_cf_diag.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/perf_cpum_cf_diag.c
@@ -243,13 +243,13 @@
 	int err = -ENOENT;
 
 	debug_sprintf_event(cf_diag_dbg, 5,
-			    "%s event %p cpu %d config %#llx "
+			    "%s event %p cpu %d config %#llx type:%u "
 			    "sample_type %#llx cf_diag_events %d\n", __func__,
-			    event, event->cpu, attr->config, attr->sample_type,
-			    atomic_read(&cf_diag_events));
+			    event, event->cpu, attr->config, event->pmu->type,
+			    attr->sample_type, atomic_read(&cf_diag_events));
 
 	if (event->attr.config != PERF_EVENT_CPUM_CF_DIAG ||
-	    event->attr.type != PERF_TYPE_RAW)
+	    event->attr.type != event->pmu->type)
 		goto out;
 
 	/* Raw events are used to access counters directly,
@@ -308,7 +308,7 @@
 	case CPUMF_CTR_SET_CRYPTO:
 		if (info->csvn >= 1 && info->csvn <= 5)
 			ctrset_size = 16;
-		else if (info->csvn == 6)
+		else if (info->csvn == 6 || info->csvn == 7)
 			ctrset_size = 20;
 		break;
 	case CPUMF_CTR_SET_EXT:
@@ -318,7 +318,7 @@
 			ctrset_size = 48;
 		else if (info->csvn >= 3 && info->csvn <= 5)
 			ctrset_size = 128;
-		else if (info->csvn == 6)
+		else if (info->csvn == 6 || info->csvn == 7)
 			ctrset_size = 160;
 		break;
 	case CPUMF_CTR_SET_MT_DIAG:
@@ -693,7 +693,7 @@
 	}
 	debug_register_view(cf_diag_dbg, &debug_sprintf_view);
 
-	rc = perf_pmu_register(&cf_diag, "cpum_cf_diag", PERF_TYPE_RAW);
+	rc = perf_pmu_register(&cf_diag, "cpum_cf_diag", -1);
 	if (rc) {
 		debug_unregister_view(cf_diag_dbg, &debug_sprintf_view);
 		debug_unregister(cf_diag_dbg);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/perf_cpum_cf_events.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/perf_cpum_cf_events.c
@@ -238,6 +238,134 @@
 CPUMF_EVENT_ATTR(cf_z14, MT_DIAG_CYCLES_ONE_THR_ACTIVE, 0x01c0);
 CPUMF_EVENT_ATTR(cf_z14, MT_DIAG_CYCLES_TWO_THR_ACTIVE, 0x01c1);
 
+CPUMF_EVENT_ATTR(cf_z15, L1D_RO_EXCL_WRITES, 0x0080);
+CPUMF_EVENT_ATTR(cf_z15, DTLB2_WRITES, 0x0081);
+CPUMF_EVENT_ATTR(cf_z15, DTLB2_MISSES, 0x0082);
+CPUMF_EVENT_ATTR(cf_z15, DTLB2_HPAGE_WRITES, 0x0083);
+CPUMF_EVENT_ATTR(cf_z15, DTLB2_GPAGE_WRITES, 0x0084);
+CPUMF_EVENT_ATTR(cf_z15, L1D_L2D_SOURCED_WRITES, 0x0085);
+CPUMF_EVENT_ATTR(cf_z15, ITLB2_WRITES, 0x0086);
+CPUMF_EVENT_ATTR(cf_z15, ITLB2_MISSES, 0x0087);
+CPUMF_EVENT_ATTR(cf_z15, L1I_L2I_SOURCED_WRITES, 0x0088);
+CPUMF_EVENT_ATTR(cf_z15, TLB2_PTE_WRITES, 0x0089);
+CPUMF_EVENT_ATTR(cf_z15, TLB2_CRSTE_WRITES, 0x008a);
+CPUMF_EVENT_ATTR(cf_z15, TLB2_ENGINES_BUSY, 0x008b);
+CPUMF_EVENT_ATTR(cf_z15, TX_C_TEND, 0x008c);
+CPUMF_EVENT_ATTR(cf_z15, TX_NC_TEND, 0x008d);
+CPUMF_EVENT_ATTR(cf_z15, L1C_TLB2_MISSES, 0x008f);
+CPUMF_EVENT_ATTR(cf_z15, L1D_ONCHIP_L3_SOURCED_WRITES, 0x0090);
+CPUMF_EVENT_ATTR(cf_z15, L1D_ONCHIP_MEMORY_SOURCED_WRITES, 0x0091);
+CPUMF_EVENT_ATTR(cf_z15, L1D_ONCHIP_L3_SOURCED_WRITES_IV, 0x0092);
+CPUMF_EVENT_ATTR(cf_z15, L1D_ONCLUSTER_L3_SOURCED_WRITES, 0x0093);
+CPUMF_EVENT_ATTR(cf_z15, L1D_ONCLUSTER_MEMORY_SOURCED_WRITES, 0x0094);
+CPUMF_EVENT_ATTR(cf_z15, L1D_ONCLUSTER_L3_SOURCED_WRITES_IV, 0x0095);
+CPUMF_EVENT_ATTR(cf_z15, L1D_OFFCLUSTER_L3_SOURCED_WRITES, 0x0096);
+CPUMF_EVENT_ATTR(cf_z15, L1D_OFFCLUSTER_MEMORY_SOURCED_WRITES, 0x0097);
+CPUMF_EVENT_ATTR(cf_z15, L1D_OFFCLUSTER_L3_SOURCED_WRITES_IV, 0x0098);
+CPUMF_EVENT_ATTR(cf_z15, L1D_OFFDRAWER_L3_SOURCED_WRITES, 0x0099);
+CPUMF_EVENT_ATTR(cf_z15, L1D_OFFDRAWER_MEMORY_SOURCED_WRITES, 0x009a);
+CPUMF_EVENT_ATTR(cf_z15, L1D_OFFDRAWER_L3_SOURCED_WRITES_IV, 0x009b);
+CPUMF_EVENT_ATTR(cf_z15, L1D_ONDRAWER_L4_SOURCED_WRITES, 0x009c);
+CPUMF_EVENT_ATTR(cf_z15, L1D_OFFDRAWER_L4_SOURCED_WRITES, 0x009d);
+CPUMF_EVENT_ATTR(cf_z15, L1D_ONCHIP_L3_SOURCED_WRITES_RO, 0x009e);
+CPUMF_EVENT_ATTR(cf_z15, L1I_ONCHIP_L3_SOURCED_WRITES, 0x00a2);
+CPUMF_EVENT_ATTR(cf_z15, L1I_ONCHIP_MEMORY_SOURCED_WRITES, 0x00a3);
+CPUMF_EVENT_ATTR(cf_z15, L1I_ONCHIP_L3_SOURCED_WRITES_IV, 0x00a4);
+CPUMF_EVENT_ATTR(cf_z15, L1I_ONCLUSTER_L3_SOURCED_WRITES, 0x00a5);
+CPUMF_EVENT_ATTR(cf_z15, L1I_ONCLUSTER_MEMORY_SOURCED_WRITES, 0x00a6);
+CPUMF_EVENT_ATTR(cf_z15, L1I_ONCLUSTER_L3_SOURCED_WRITES_IV, 0x00a7);
+CPUMF_EVENT_ATTR(cf_z15, L1I_OFFCLUSTER_L3_SOURCED_WRITES, 0x00a8);
+CPUMF_EVENT_ATTR(cf_z15, L1I_OFFCLUSTER_MEMORY_SOURCED_WRITES, 0x00a9);
+CPUMF_EVENT_ATTR(cf_z15, L1I_OFFCLUSTER_L3_SOURCED_WRITES_IV, 0x00aa);
+CPUMF_EVENT_ATTR(cf_z15, L1I_OFFDRAWER_L3_SOURCED_WRITES, 0x00ab);
+CPUMF_EVENT_ATTR(cf_z15, L1I_OFFDRAWER_MEMORY_SOURCED_WRITES, 0x00ac);
+CPUMF_EVENT_ATTR(cf_z15, L1I_OFFDRAWER_L3_SOURCED_WRITES_IV, 0x00ad);
+CPUMF_EVENT_ATTR(cf_z15, L1I_ONDRAWER_L4_SOURCED_WRITES, 0x00ae);
+CPUMF_EVENT_ATTR(cf_z15, L1I_OFFDRAWER_L4_SOURCED_WRITES, 0x00af);
+CPUMF_EVENT_ATTR(cf_z15, BCD_DFP_EXECUTION_SLOTS, 0x00e0);
+CPUMF_EVENT_ATTR(cf_z15, VX_BCD_EXECUTION_SLOTS, 0x00e1);
+CPUMF_EVENT_ATTR(cf_z15, DECIMAL_INSTRUCTIONS, 0x00e2);
+CPUMF_EVENT_ATTR(cf_z15, LAST_HOST_TRANSLATIONS, 0x00e8);
+CPUMF_EVENT_ATTR(cf_z15, TX_NC_TABORT, 0x00f3);
+CPUMF_EVENT_ATTR(cf_z15, TX_C_TABORT_NO_SPECIAL, 0x00f4);
+CPUMF_EVENT_ATTR(cf_z15, TX_C_TABORT_SPECIAL, 0x00f5);
+CPUMF_EVENT_ATTR(cf_z15, DFLT_ACCESS, 0x00f7);
+CPUMF_EVENT_ATTR(cf_z15, DFLT_CYCLES, 0x00fc);
+CPUMF_EVENT_ATTR(cf_z15, DFLT_CC, 0x00108);
+CPUMF_EVENT_ATTR(cf_z15, DFLT_CCFINISH, 0x00109);
+CPUMF_EVENT_ATTR(cf_z15, MT_DIAG_CYCLES_ONE_THR_ACTIVE, 0x01c0);
+CPUMF_EVENT_ATTR(cf_z15, MT_DIAG_CYCLES_TWO_THR_ACTIVE, 0x01c1);
+CPUMF_EVENT_ATTR(cf_z16, L1D_RO_EXCL_WRITES, 0x0080);
+CPUMF_EVENT_ATTR(cf_z16, DTLB2_WRITES, 0x0081);
+CPUMF_EVENT_ATTR(cf_z16, DTLB2_MISSES, 0x0082);
+CPUMF_EVENT_ATTR(cf_z16, CRSTE_1MB_WRITES, 0x0083);
+CPUMF_EVENT_ATTR(cf_z16, DTLB2_GPAGE_WRITES, 0x0084);
+CPUMF_EVENT_ATTR(cf_z16, ITLB2_WRITES, 0x0086);
+CPUMF_EVENT_ATTR(cf_z16, ITLB2_MISSES, 0x0087);
+CPUMF_EVENT_ATTR(cf_z16, TLB2_PTE_WRITES, 0x0089);
+CPUMF_EVENT_ATTR(cf_z16, TLB2_CRSTE_WRITES, 0x008a);
+CPUMF_EVENT_ATTR(cf_z16, TLB2_ENGINES_BUSY, 0x008b);
+CPUMF_EVENT_ATTR(cf_z16, TX_C_TEND, 0x008c);
+CPUMF_EVENT_ATTR(cf_z16, TX_NC_TEND, 0x008d);
+CPUMF_EVENT_ATTR(cf_z16, L1C_TLB2_MISSES, 0x008f);
+CPUMF_EVENT_ATTR(cf_z16, DCW_REQ, 0x0091);
+CPUMF_EVENT_ATTR(cf_z16, DCW_REQ_IV, 0x0092);
+CPUMF_EVENT_ATTR(cf_z16, DCW_REQ_CHIP_HIT, 0x0093);
+CPUMF_EVENT_ATTR(cf_z16, DCW_REQ_DRAWER_HIT, 0x0094);
+CPUMF_EVENT_ATTR(cf_z16, DCW_ON_CHIP, 0x0095);
+CPUMF_EVENT_ATTR(cf_z16, DCW_ON_CHIP_IV, 0x0096);
+CPUMF_EVENT_ATTR(cf_z16, DCW_ON_CHIP_CHIP_HIT, 0x0097);
+CPUMF_EVENT_ATTR(cf_z16, DCW_ON_CHIP_DRAWER_HIT, 0x0098);
+CPUMF_EVENT_ATTR(cf_z16, DCW_ON_MODULE, 0x0099);
+CPUMF_EVENT_ATTR(cf_z16, DCW_ON_DRAWER, 0x009a);
+CPUMF_EVENT_ATTR(cf_z16, DCW_OFF_DRAWER, 0x009b);
+CPUMF_EVENT_ATTR(cf_z16, DCW_ON_CHIP_MEMORY, 0x009c);
+CPUMF_EVENT_ATTR(cf_z16, DCW_ON_MODULE_MEMORY, 0x009d);
+CPUMF_EVENT_ATTR(cf_z16, DCW_ON_DRAWER_MEMORY, 0x009e);
+CPUMF_EVENT_ATTR(cf_z16, DCW_OFF_DRAWER_MEMORY, 0x009f);
+CPUMF_EVENT_ATTR(cf_z16, IDCW_ON_MODULE_IV, 0x00a0);
+CPUMF_EVENT_ATTR(cf_z16, IDCW_ON_MODULE_CHIP_HIT, 0x00a1);
+CPUMF_EVENT_ATTR(cf_z16, IDCW_ON_MODULE_DRAWER_HIT, 0x00a2);
+CPUMF_EVENT_ATTR(cf_z16, IDCW_ON_DRAWER_IV, 0x00a3);
+CPUMF_EVENT_ATTR(cf_z16, IDCW_ON_DRAWER_CHIP_HIT, 0x00a4);
+CPUMF_EVENT_ATTR(cf_z16, IDCW_ON_DRAWER_DRAWER_HIT, 0x00a5);
+CPUMF_EVENT_ATTR(cf_z16, IDCW_OFF_DRAWER_IV, 0x00a6);
+CPUMF_EVENT_ATTR(cf_z16, IDCW_OFF_DRAWER_CHIP_HIT, 0x00a7);
+CPUMF_EVENT_ATTR(cf_z16, IDCW_OFF_DRAWER_DRAWER_HIT, 0x00a8);
+CPUMF_EVENT_ATTR(cf_z16, ICW_REQ, 0x00a9);
+CPUMF_EVENT_ATTR(cf_z16, ICW_REQ_IV, 0x00aa);
+CPUMF_EVENT_ATTR(cf_z16, ICW_REQ_CHIP_HIT, 0x00ab);
+CPUMF_EVENT_ATTR(cf_z16, ICW_REQ_DRAWER_HIT, 0x00ac);
+CPUMF_EVENT_ATTR(cf_z16, ICW_ON_CHIP, 0x00ad);
+CPUMF_EVENT_ATTR(cf_z16, ICW_ON_CHIP_IV, 0x00ae);
+CPUMF_EVENT_ATTR(cf_z16, ICW_ON_CHIP_CHIP_HIT, 0x00af);
+CPUMF_EVENT_ATTR(cf_z16, ICW_ON_CHIP_DRAWER_HIT, 0x00b0);
+CPUMF_EVENT_ATTR(cf_z16, ICW_ON_MODULE, 0x00b1);
+CPUMF_EVENT_ATTR(cf_z16, ICW_ON_DRAWER, 0x00b2);
+CPUMF_EVENT_ATTR(cf_z16, ICW_OFF_DRAWER, 0x00b3);
+CPUMF_EVENT_ATTR(cf_z16, ICW_ON_CHIP_MEMORY, 0x00b4);
+CPUMF_EVENT_ATTR(cf_z16, ICW_ON_MODULE_MEMORY, 0x00b5);
+CPUMF_EVENT_ATTR(cf_z16, ICW_ON_DRAWER_MEMORY, 0x00b6);
+CPUMF_EVENT_ATTR(cf_z16, ICW_OFF_DRAWER_MEMORY, 0x00b7);
+CPUMF_EVENT_ATTR(cf_z16, BCD_DFP_EXECUTION_SLOTS, 0x00e0);
+CPUMF_EVENT_ATTR(cf_z16, VX_BCD_EXECUTION_SLOTS, 0x00e1);
+CPUMF_EVENT_ATTR(cf_z16, DECIMAL_INSTRUCTIONS, 0x00e2);
+CPUMF_EVENT_ATTR(cf_z16, LAST_HOST_TRANSLATIONS, 0x00e8);
+CPUMF_EVENT_ATTR(cf_z16, TX_NC_TABORT, 0x00f4);
+CPUMF_EVENT_ATTR(cf_z16, TX_C_TABORT_NO_SPECIAL, 0x00f5);
+CPUMF_EVENT_ATTR(cf_z16, TX_C_TABORT_SPECIAL, 0x00f6);
+CPUMF_EVENT_ATTR(cf_z16, DFLT_ACCESS, 0x00f8);
+CPUMF_EVENT_ATTR(cf_z16, DFLT_CYCLES, 0x00fd);
+CPUMF_EVENT_ATTR(cf_z16, SORTL, 0x0100);
+CPUMF_EVENT_ATTR(cf_z16, DFLT_CC, 0x0109);
+CPUMF_EVENT_ATTR(cf_z16, DFLT_CCFINISH, 0x010a);
+CPUMF_EVENT_ATTR(cf_z16, NNPA_INVOCATIONS, 0x010b);
+CPUMF_EVENT_ATTR(cf_z16, NNPA_COMPLETIONS, 0x010c);
+CPUMF_EVENT_ATTR(cf_z16, NNPA_WAIT_LOCK, 0x010d);
+CPUMF_EVENT_ATTR(cf_z16, NNPA_HOLD_LOCK, 0x010e);
+CPUMF_EVENT_ATTR(cf_z16, MT_DIAG_CYCLES_ONE_THR_ACTIVE, 0x01c0);
+CPUMF_EVENT_ATTR(cf_z16, MT_DIAG_CYCLES_TWO_THR_ACTIVE, 0x01c1);
+
 static struct attribute *cpumcf_fvn1_pmu_event_attr[] __initdata = {
 	CPUMF_EVENT_PTR(cf_fvn1, CPU_CYCLES),
 	CPUMF_EVENT_PTR(cf_fvn1, INSTRUCTIONS),
@@ -286,7 +414,7 @@
 	NULL,
 };
 
-static struct attribute *cpumcf_svn_6_pmu_event_attr[] __initdata = {
+static struct attribute *cpumcf_svn_67_pmu_event_attr[] __initdata = {
 	CPUMF_EVENT_PTR(cf_svn_12345, PRNG_FUNCTIONS),
 	CPUMF_EVENT_PTR(cf_svn_12345, PRNG_CYCLES),
 	CPUMF_EVENT_PTR(cf_svn_12345, PRNG_BLOCKED_FUNCTIONS),
@@ -516,6 +644,141 @@
 	NULL,
 };
 
+static struct attribute *cpumcf_z15_pmu_event_attr[] __initdata = {
+	CPUMF_EVENT_PTR(cf_z15, L1D_RO_EXCL_WRITES),
+	CPUMF_EVENT_PTR(cf_z15, DTLB2_WRITES),
+	CPUMF_EVENT_PTR(cf_z15, DTLB2_MISSES),
+	CPUMF_EVENT_PTR(cf_z15, DTLB2_HPAGE_WRITES),
+	CPUMF_EVENT_PTR(cf_z15, DTLB2_GPAGE_WRITES),
+	CPUMF_EVENT_PTR(cf_z15, L1D_L2D_SOURCED_WRITES),
+	CPUMF_EVENT_PTR(cf_z15, ITLB2_WRITES),
+	CPUMF_EVENT_PTR(cf_z15, ITLB2_MISSES),
+	CPUMF_EVENT_PTR(cf_z15, L1I_L2I_SOURCED_WRITES),
+	CPUMF_EVENT_PTR(cf_z15, TLB2_PTE_WRITES),
+	CPUMF_EVENT_PTR(cf_z15, TLB2_CRSTE_WRITES),
+	CPUMF_EVENT_PTR(cf_z15, TLB2_ENGINES_BUSY),
+	CPUMF_EVENT_PTR(cf_z15, TX_C_TEND),
+	CPUMF_EVENT_PTR(cf_z15, TX_NC_TEND),
+	CPUMF_EVENT_PTR(cf_z15, L1C_TLB2_MISSES),
+	CPUMF_EVENT_PTR(cf_z15, L1D_ONCHIP_L3_SOURCED_WRITES),
+	CPUMF_EVENT_PTR(cf_z15, L1D_ONCHIP_MEMORY_SOURCED_WRITES),
+	CPUMF_EVENT_PTR(cf_z15, L1D_ONCHIP_L3_SOURCED_WRITES_IV),
+	CPUMF_EVENT_PTR(cf_z15, L1D_ONCLUSTER_L3_SOURCED_WRITES),
+	CPUMF_EVENT_PTR(cf_z15, L1D_ONCLUSTER_MEMORY_SOURCED_WRITES),
+	CPUMF_EVENT_PTR(cf_z15, L1D_ONCLUSTER_L3_SOURCED_WRITES_IV),
+	CPUMF_EVENT_PTR(cf_z15, L1D_OFFCLUSTER_L3_SOURCED_WRITES),
+	CPUMF_EVENT_PTR(cf_z15, L1D_OFFCLUSTER_MEMORY_SOURCED_WRITES),
+	CPUMF_EVENT_PTR(cf_z15, L1D_OFFCLUSTER_L3_SOURCED_WRITES_IV),
+	CPUMF_EVENT_PTR(cf_z15, L1D_OFFDRAWER_L3_SOURCED_WRITES),
+	CPUMF_EVENT_PTR(cf_z15, L1D_OFFDRAWER_MEMORY_SOURCED_WRITES),
+	CPUMF_EVENT_PTR(cf_z15, L1D_OFFDRAWER_L3_SOURCED_WRITES_IV),
+	CPUMF_EVENT_PTR(cf_z15, L1D_ONDRAWER_L4_SOURCED_WRITES),
+	CPUMF_EVENT_PTR(cf_z15, L1D_OFFDRAWER_L4_SOURCED_WRITES),
+	CPUMF_EVENT_PTR(cf_z15, L1D_ONCHIP_L3_SOURCED_WRITES_RO),
+	CPUMF_EVENT_PTR(cf_z15, L1I_ONCHIP_L3_SOURCED_WRITES),
+	CPUMF_EVENT_PTR(cf_z15, L1I_ONCHIP_MEMORY_SOURCED_WRITES),
+	CPUMF_EVENT_PTR(cf_z15, L1I_ONCHIP_L3_SOURCED_WRITES_IV),
+	CPUMF_EVENT_PTR(cf_z15, L1I_ONCLUSTER_L3_SOURCED_WRITES),
+	CPUMF_EVENT_PTR(cf_z15, L1I_ONCLUSTER_MEMORY_SOURCED_WRITES),
+	CPUMF_EVENT_PTR(cf_z15, L1I_ONCLUSTER_L3_SOURCED_WRITES_IV),
+	CPUMF_EVENT_PTR(cf_z15, L1I_OFFCLUSTER_L3_SOURCED_WRITES),
+	CPUMF_EVENT_PTR(cf_z15, L1I_OFFCLUSTER_MEMORY_SOURCED_WRITES),
+	CPUMF_EVENT_PTR(cf_z15, L1I_OFFCLUSTER_L3_SOURCED_WRITES_IV),
+	CPUMF_EVENT_PTR(cf_z15, L1I_OFFDRAWER_L3_SOURCED_WRITES),
+	CPUMF_EVENT_PTR(cf_z15, L1I_OFFDRAWER_MEMORY_SOURCED_WRITES),
+	CPUMF_EVENT_PTR(cf_z15, L1I_OFFDRAWER_L3_SOURCED_WRITES_IV),
+	CPUMF_EVENT_PTR(cf_z15, L1I_ONDRAWER_L4_SOURCED_WRITES),
+	CPUMF_EVENT_PTR(cf_z15, L1I_OFFDRAWER_L4_SOURCED_WRITES),
+	CPUMF_EVENT_PTR(cf_z15, BCD_DFP_EXECUTION_SLOTS),
+	CPUMF_EVENT_PTR(cf_z15, VX_BCD_EXECUTION_SLOTS),
+	CPUMF_EVENT_PTR(cf_z15, DECIMAL_INSTRUCTIONS),
+	CPUMF_EVENT_PTR(cf_z15, LAST_HOST_TRANSLATIONS),
+	CPUMF_EVENT_PTR(cf_z15, TX_NC_TABORT),
+	CPUMF_EVENT_PTR(cf_z15, TX_C_TABORT_NO_SPECIAL),
+	CPUMF_EVENT_PTR(cf_z15, TX_C_TABORT_SPECIAL),
+	CPUMF_EVENT_PTR(cf_z15, DFLT_ACCESS),
+	CPUMF_EVENT_PTR(cf_z15, DFLT_CYCLES),
+	CPUMF_EVENT_PTR(cf_z15, DFLT_CC),
+	CPUMF_EVENT_PTR(cf_z15, DFLT_CCFINISH),
+	CPUMF_EVENT_PTR(cf_z15, MT_DIAG_CYCLES_ONE_THR_ACTIVE),
+	CPUMF_EVENT_PTR(cf_z15, MT_DIAG_CYCLES_TWO_THR_ACTIVE),
+	NULL,
+};
+
+static struct attribute *cpumcf_z16_pmu_event_attr[] __initdata = {
+	CPUMF_EVENT_PTR(cf_z16, L1D_RO_EXCL_WRITES),
+	CPUMF_EVENT_PTR(cf_z16, DTLB2_WRITES),
+	CPUMF_EVENT_PTR(cf_z16, DTLB2_MISSES),
+	CPUMF_EVENT_PTR(cf_z16, CRSTE_1MB_WRITES),
+	CPUMF_EVENT_PTR(cf_z16, DTLB2_GPAGE_WRITES),
+	CPUMF_EVENT_PTR(cf_z16, ITLB2_WRITES),
+	CPUMF_EVENT_PTR(cf_z16, ITLB2_MISSES),
+	CPUMF_EVENT_PTR(cf_z16, TLB2_PTE_WRITES),
+	CPUMF_EVENT_PTR(cf_z16, TLB2_CRSTE_WRITES),
+	CPUMF_EVENT_PTR(cf_z16, TLB2_ENGINES_BUSY),
+	CPUMF_EVENT_PTR(cf_z16, TX_C_TEND),
+	CPUMF_EVENT_PTR(cf_z16, TX_NC_TEND),
+	CPUMF_EVENT_PTR(cf_z16, L1C_TLB2_MISSES),
+	CPUMF_EVENT_PTR(cf_z16, DCW_REQ),
+	CPUMF_EVENT_PTR(cf_z16, DCW_REQ_IV),
+	CPUMF_EVENT_PTR(cf_z16, DCW_REQ_CHIP_HIT),
+	CPUMF_EVENT_PTR(cf_z16, DCW_REQ_DRAWER_HIT),
+	CPUMF_EVENT_PTR(cf_z16, DCW_ON_CHIP),
+	CPUMF_EVENT_PTR(cf_z16, DCW_ON_CHIP_IV),
+	CPUMF_EVENT_PTR(cf_z16, DCW_ON_CHIP_CHIP_HIT),
+	CPUMF_EVENT_PTR(cf_z16, DCW_ON_CHIP_DRAWER_HIT),
+	CPUMF_EVENT_PTR(cf_z16, DCW_ON_MODULE),
+	CPUMF_EVENT_PTR(cf_z16, DCW_ON_DRAWER),
+	CPUMF_EVENT_PTR(cf_z16, DCW_OFF_DRAWER),
+	CPUMF_EVENT_PTR(cf_z16, DCW_ON_CHIP_MEMORY),
+	CPUMF_EVENT_PTR(cf_z16, DCW_ON_MODULE_MEMORY),
+	CPUMF_EVENT_PTR(cf_z16, DCW_ON_DRAWER_MEMORY),
+	CPUMF_EVENT_PTR(cf_z16, DCW_OFF_DRAWER_MEMORY),
+	CPUMF_EVENT_PTR(cf_z16, IDCW_ON_MODULE_IV),
+	CPUMF_EVENT_PTR(cf_z16, IDCW_ON_MODULE_CHIP_HIT),
+	CPUMF_EVENT_PTR(cf_z16, IDCW_ON_MODULE_DRAWER_HIT),
+	CPUMF_EVENT_PTR(cf_z16, IDCW_ON_DRAWER_IV),
+	CPUMF_EVENT_PTR(cf_z16, IDCW_ON_DRAWER_CHIP_HIT),
+	CPUMF_EVENT_PTR(cf_z16, IDCW_ON_DRAWER_DRAWER_HIT),
+	CPUMF_EVENT_PTR(cf_z16, IDCW_OFF_DRAWER_IV),
+	CPUMF_EVENT_PTR(cf_z16, IDCW_OFF_DRAWER_CHIP_HIT),
+	CPUMF_EVENT_PTR(cf_z16, IDCW_OFF_DRAWER_DRAWER_HIT),
+	CPUMF_EVENT_PTR(cf_z16, ICW_REQ),
+	CPUMF_EVENT_PTR(cf_z16, ICW_REQ_IV),
+	CPUMF_EVENT_PTR(cf_z16, ICW_REQ_CHIP_HIT),
+	CPUMF_EVENT_PTR(cf_z16, ICW_REQ_DRAWER_HIT),
+	CPUMF_EVENT_PTR(cf_z16, ICW_ON_CHIP),
+	CPUMF_EVENT_PTR(cf_z16, ICW_ON_CHIP_IV),
+	CPUMF_EVENT_PTR(cf_z16, ICW_ON_CHIP_CHIP_HIT),
+	CPUMF_EVENT_PTR(cf_z16, ICW_ON_CHIP_DRAWER_HIT),
+	CPUMF_EVENT_PTR(cf_z16, ICW_ON_MODULE),
+	CPUMF_EVENT_PTR(cf_z16, ICW_ON_DRAWER),
+	CPUMF_EVENT_PTR(cf_z16, ICW_OFF_DRAWER),
+	CPUMF_EVENT_PTR(cf_z16, ICW_ON_CHIP_MEMORY),
+	CPUMF_EVENT_PTR(cf_z16, ICW_ON_MODULE_MEMORY),
+	CPUMF_EVENT_PTR(cf_z16, ICW_ON_DRAWER_MEMORY),
+	CPUMF_EVENT_PTR(cf_z16, ICW_OFF_DRAWER_MEMORY),
+	CPUMF_EVENT_PTR(cf_z16, BCD_DFP_EXECUTION_SLOTS),
+	CPUMF_EVENT_PTR(cf_z16, VX_BCD_EXECUTION_SLOTS),
+	CPUMF_EVENT_PTR(cf_z16, DECIMAL_INSTRUCTIONS),
+	CPUMF_EVENT_PTR(cf_z16, LAST_HOST_TRANSLATIONS),
+	CPUMF_EVENT_PTR(cf_z16, TX_NC_TABORT),
+	CPUMF_EVENT_PTR(cf_z16, TX_C_TABORT_NO_SPECIAL),
+	CPUMF_EVENT_PTR(cf_z16, TX_C_TABORT_SPECIAL),
+	CPUMF_EVENT_PTR(cf_z16, DFLT_ACCESS),
+	CPUMF_EVENT_PTR(cf_z16, DFLT_CYCLES),
+	CPUMF_EVENT_PTR(cf_z16, SORTL),
+	CPUMF_EVENT_PTR(cf_z16, DFLT_CC),
+	CPUMF_EVENT_PTR(cf_z16, DFLT_CCFINISH),
+	CPUMF_EVENT_PTR(cf_z16, NNPA_INVOCATIONS),
+	CPUMF_EVENT_PTR(cf_z16, NNPA_COMPLETIONS),
+	CPUMF_EVENT_PTR(cf_z16, NNPA_WAIT_LOCK),
+	CPUMF_EVENT_PTR(cf_z16, NNPA_HOLD_LOCK),
+	CPUMF_EVENT_PTR(cf_z16, MT_DIAG_CYCLES_ONE_THR_ACTIVE),
+	CPUMF_EVENT_PTR(cf_z16, MT_DIAG_CYCLES_TWO_THR_ACTIVE),
+	NULL,
+};
+
 /* END: CPUM_CF COUNTER DEFINITIONS ===================================== */
 
 static struct attribute_group cpumcf_pmu_events_group = {
@@ -596,8 +859,8 @@
 	case 1 ... 5:
 		csvn = cpumcf_svn_12345_pmu_event_attr;
 		break;
-	case 6:
-		csvn = cpumcf_svn_6_pmu_event_attr;
+	case 6 ... 7:
+		csvn = cpumcf_svn_67_pmu_event_attr;
 		break;
 	default:
 		csvn = none;
@@ -624,9 +887,15 @@
 		break;
 	case 0x3906:
 	case 0x3907:
+		model = cpumcf_z14_pmu_event_attr;
+		break;
 	case 0x8561:
 	case 0x8562:
-		model = cpumcf_z14_pmu_event_attr;
+		model = cpumcf_z15_pmu_event_attr;
+		break;
+	case 0x3931:
+	case 0x3932:
+		model = cpumcf_z16_pmu_event_attr;
 		break;
 	default:
 		model = none;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/perf_cpum_sf.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/perf_cpum_sf.c
@@ -193,7 +193,7 @@
 				   unsigned long num_sdb, gfp_t gfp_flags)
 {
 	int i, rc;
-	unsigned long *new, *tail;
+	unsigned long *new, *tail, *tail_prev = NULL;
 
 	if (!sfb->sdbt || !sfb->tail)
 		return -EINVAL;
@@ -232,6 +232,7 @@
 			sfb->num_sdbt++;
 			/* Link current page to tail of chain */
 			*tail = (unsigned long)(void *) new + 1;
+			tail_prev = tail;
 			tail = new;
 		}
 
@@ -241,10 +242,22 @@
 		 * issue, a new realloc call (if required) might succeed.
 		 */
 		rc = alloc_sample_data_block(tail, gfp_flags);
-		if (rc)
+		if (rc) {
+			/* Undo last SDBT. An SDBT with no SDB at its first
+			 * entry but with an SDBT entry instead can not be
+			 * handled by the interrupt handler code.
+			 * Avoid this situation.
+			 */
+			if (tail_prev) {
+				sfb->num_sdbt--;
+				free_page((unsigned long) new);
+				tail = tail_prev;
+			}
 			break;
+		}
 		sfb->num_sdb++;
 		tail++;
+		tail_prev = new = NULL;	/* Allocated at least one SBD */
 	}
 
 	/* Link sampling buffer to its origin */
@@ -1169,7 +1182,7 @@
 	sample = (struct hws_basic_entry *) *sdbt;
 	while ((unsigned long *) sample < (unsigned long *) te) {
 		/* Check for an empty sample */
-		if (!sample->def)
+		if (!sample->def || sample->LS)
 			break;
 
 		/* Update perf event period */
@@ -1300,18 +1313,28 @@
 		 */
 		if (flush_all && done)
 			break;
-
-		/* If an event overflow happened, discard samples by
-		 * processing any remaining sample-data-blocks.
-		 */
-		if (event_overflow)
-			flush_all = 1;
 	}
 
 	/* Account sample overflows in the event hardware structure */
 	if (sampl_overflow)
 		OVERFLOW_REG(hwc) = DIV_ROUND_UP(OVERFLOW_REG(hwc) +
 						 sampl_overflow, 1 + num_sdb);
+
+	/* Perf_event_overflow() and perf_event_account_interrupt() limit
+	 * the interrupt rate to an upper limit. Roughly 1000 samples per
+	 * task tick.
+	 * Hitting this limit results in a large number
+	 * of throttled REF_REPORT_THROTTLE entries and the samples
+	 * are dropped.
+	 * Slightly increase the interval to avoid hitting this limit.
+	 */
+	if (event_overflow) {
+		SAMPL_RATE(hwc) += DIV_ROUND_UP(SAMPL_RATE(hwc), 10);
+		debug_sprintf_event(sfdbg, 1, "%s: rate adjustment %ld\n",
+				    __func__,
+				    DIV_ROUND_UP(SAMPL_RATE(hwc), 10));
+	}
+
 	if (sampl_overflow || event_overflow)
 		debug_sprintf_event(sfdbg, 4, "hw_perf_event_update: "
 				    "overflow stats: sample=%llu event=%llu\n",
@@ -1389,7 +1412,7 @@
 	unsigned long head, base, offset;
 	struct hws_trailer_entry *te;
 
-	if (WARN_ON_ONCE(handle->head & ~PAGE_MASK))
+	if (handle->head & ~PAGE_MASK)
 		return -EINVAL;
 
 	aux->head = handle->head >> PAGE_SHIFT;
@@ -1406,8 +1429,8 @@
 		idx = aux->empty_mark + 1;
 		for (i = 0; i < range_scan; i++, idx++) {
 			te = aux_sdb_trailer(aux, idx);
-			te->flags = te->flags & ~SDB_TE_BUFFER_FULL_MASK;
-			te->flags = te->flags & ~SDB_TE_ALERT_REQ_MASK;
+			te->flags &= ~(SDB_TE_BUFFER_FULL_MASK |
+				       SDB_TE_ALERT_REQ_MASK);
 			te->overflow = 0;
 		}
 		/* Save the position of empty SDBs */
@@ -1454,8 +1477,7 @@
 	te = aux_sdb_trailer(aux, alert_index);
 	do {
 		orig_flags = te->flags;
-		orig_overflow = te->overflow;
-		*overflow = orig_overflow;
+		*overflow = orig_overflow = te->overflow;
 		if (orig_flags & SDB_TE_BUFFER_FULL_MASK) {
 			/*
 			 * SDB is already set by hardware.
@@ -1558,7 +1580,7 @@
 	unsigned long num_sdb;
 
 	aux = perf_get_aux(handle);
-	if (WARN_ON_ONCE(!aux))
+	if (!aux)
 		return;
 
 	/* Inform user space new data arrived */
@@ -1566,6 +1588,7 @@
 	perf_aux_output_end(handle, size);
 	num_sdb = aux->sfb.num_sdb;
 
+	num_sdb = aux->sfb.num_sdb;
 	while (!done) {
 		/* Get an output handle */
 		aux = perf_aux_output_begin(handle, cpuhw->event);
@@ -1576,7 +1599,7 @@
 			debug_sprintf_event(sfdbg, 1, "AUX buffer used up\n");
 			break;
 		}
-		if (WARN_ON_ONCE(!aux))
+		if (!aux)
 			return;
 
 		/* Update head and alert_mark to new position */
@@ -1688,7 +1711,7 @@
 	}
 
 	/* Allocate aux_buffer struct for the event */
-	aux = kmalloc(sizeof(struct aux_buffer), GFP_KERNEL);
+	aux = kzalloc(sizeof(struct aux_buffer), GFP_KERNEL);
 	if (!aux)
 		goto no_aux;
 	sfb = &aux->sfb;
@@ -1813,12 +1836,8 @@
 {
 	struct cpu_hw_sf *cpuhw = this_cpu_ptr(&cpu_hw_sf);
 
-	if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED)))
+	if (!(event->hw.state & PERF_HES_STOPPED))
 		return;
-
-	if (flags & PERF_EF_RELOAD)
-		WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE));
-
 	perf_pmu_disable(event->pmu);
 	event->hw.state = 0;
 	cpuhw->lsctl.cs = 1;
@@ -1843,7 +1862,9 @@
 	event->hw.state |= PERF_HES_STOPPED;
 
 	if ((flags & PERF_EF_UPDATE) && !(event->hw.state & PERF_HES_UPTODATE)) {
-		hw_perf_event_update(event, 1);
+		/* CPU hotplug off removes SDBs. No samples to extract. */
+		if (cpuhw->flags & PMU_F_RESERVED)
+			hw_perf_event_update(event, 1);
 		event->hw.state |= PERF_HES_UPTODATE;
 	}
 	perf_pmu_enable(event->pmu);
@@ -2194,4 +2215,4 @@
 }
 
 arch_initcall(init_cpum_sampling_pmu);
-core_param(cpum_sfb_size, CPUM_SF_MAX_SDB, sfb_size, 0640);
+core_param(cpum_sfb_size, CPUM_SF_MAX_SDB, sfb_size, 0644);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/perf_event.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/perf_event.c
@@ -224,9 +224,13 @@
 			   struct pt_regs *regs)
 {
 	struct unwind_state state;
+	unsigned long addr;
 
-	unwind_for_each_frame(&state, current, regs, 0)
-		perf_callchain_store(entry, state.ip);
+	unwind_for_each_frame(&state, current, regs, 0) {
+		addr = unwind_get_return_address(&state);
+		if (!addr || perf_callchain_store(entry, addr))
+			return;
+	}
 }
 
 /* Perf definitions for PMU event attributes in sysfs */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/pgm_check.S
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/pgm_check.S
@@ -78,8 +78,8 @@
 PGM_CHECK(do_dat_exception)		/* 3a */
 PGM_CHECK(do_dat_exception)		/* 3b */
 PGM_CHECK_DEFAULT			/* 3c */
-PGM_CHECK_DEFAULT			/* 3d */
-PGM_CHECK_DEFAULT			/* 3e */
+PGM_CHECK(do_secure_storage_access)	/* 3d */
+PGM_CHECK(do_non_secure_storage_access)	/* 3e */
 PGM_CHECK_DEFAULT			/* 3f */
 PGM_CHECK_DEFAULT			/* 40 */
 PGM_CHECK_DEFAULT			/* 41 */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/process.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/process.c
@@ -76,6 +76,18 @@
 
 	memcpy(dst, src, arch_task_struct_size);
 	dst->thread.fpu.regs = dst->thread.fpu.fprs;
+
+	/*
+	 * Don't transfer over the runtime instrumentation or the guarded
+	 * storage control block pointers. These fields are cleared here instead
+	 * of in copy_thread() to avoid premature freeing of associated memory
+	 * on fork() failure. Wait to clear the RI flag because ->stack still
+	 * refers to the source thread.
+	 */
+	dst->thread.ri_cb = NULL;
+	dst->thread.gs_cb = NULL;
+	dst->thread.gs_bc_cb = NULL;
+
 	return 0;
 }
 
@@ -105,6 +117,7 @@
 	p->thread.system_timer = 0;
 	p->thread.hardirq_timer = 0;
 	p->thread.softirq_timer = 0;
+	p->thread.last_break = 1;
 
 	frame->sf.back_chain = 0;
 	/* new return point is ret_from_fork */
@@ -132,13 +145,11 @@
 	frame->childregs.flags = 0;
 	if (new_stackp)
 		frame->childregs.gprs[15] = new_stackp;
-
-	/* Don't copy runtime instrumentation info */
-	p->thread.ri_cb = NULL;
+	/*
+	 * Clear the runtime instrumentation flag after the above childregs
+	 * copy. The CB pointer was already cleared in arch_dup_task_struct().
+	 */
 	frame->childregs.psw.mask &= ~PSW_MASK_RI;
-	/* Don't copy guarded storage control block */
-	p->thread.gs_cb = NULL;
-	p->thread.gs_bc_cb = NULL;
 
 	/* Set a new TLS ?  */
 	if (clone_flags & CLONE_SETTLS) {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/processor.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/processor.c
@@ -165,8 +165,9 @@
 static int show_cpuinfo(struct seq_file *m, void *v)
 {
 	unsigned long n = (unsigned long) v - 1;
+	unsigned long first = cpumask_first(cpu_online_mask);
 
-	if (!n)
+	if (n == first)
 		show_cpu_summary(m, v);
 	if (!machine_has_cpu_mhz)
 		return 0;
@@ -179,6 +180,8 @@
 {
 	if (*pos)
 		*pos = cpumask_next(*pos - 1, cpu_online_mask);
+	else
+		*pos = cpumask_first(cpu_online_mask);
 	return *pos < nr_cpu_ids ? (void *)*pos + 1 : NULL;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/ptrace.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/ptrace.c
@@ -324,6 +324,25 @@
 		child->thread.per_user.end = data;
 }
 
+static void fixup_int_code(struct task_struct *child, addr_t data)
+{
+	struct pt_regs *regs = task_pt_regs(child);
+	int ilc = regs->int_code >> 16;
+	u16 insn;
+
+	if (ilc > 6)
+		return;
+
+	if (ptrace_access_vm(child, regs->psw.addr - (regs->int_code >> 16),
+			&insn, sizeof(insn), FOLL_FORCE) != sizeof(insn))
+		return;
+
+	/* double check that tracee stopped on svc instruction */
+	if ((insn >> 8) != 0xa)
+		return;
+
+	regs->int_code = 0x20000 | (data & 0xffff);
+}
 /*
  * Write a word to the user area of a process at location addr. This
  * operation does have an additional problem compared to peek_user.
@@ -335,7 +354,9 @@
 	struct user *dummy = NULL;
 	addr_t offset;
 
+
 	if (addr < (addr_t) &dummy->regs.acrs) {
+		struct pt_regs *regs = task_pt_regs(child);
 		/*
 		 * psw and gprs are stored on the stack
 		 */
@@ -353,7 +374,11 @@
 				/* Invalid addressing mode bits */
 				return -EINVAL;
 		}
-		*(addr_t *)((addr_t) &task_pt_regs(child)->psw + addr) = data;
+
+		if (test_pt_regs_flag(regs, PIF_SYSCALL) &&
+			addr == offsetof(struct user, regs.gprs[2]))
+			fixup_int_code(child, data);
+		*(addr_t *)((addr_t) &regs->psw + addr) = data;
 
 	} else if (addr < (addr_t) (&dummy->regs.orig_gpr2)) {
 		/*
@@ -388,6 +413,7 @@
 		/*
 		 * floating point control reg. is in the thread structure
 		 */
+		save_fpu_regs();
 		if ((unsigned int) data != 0 ||
 		    test_fp_ctl(data >> (BITS_PER_LONG - 32)))
 			return -EINVAL;
@@ -477,9 +503,7 @@
 		}
 		return 0;
 	case PTRACE_GET_LAST_BREAK:
-		put_user(child->thread.last_break,
-			 (unsigned long __user *) data);
-		return 0;
+		return put_user(child->thread.last_break, (unsigned long __user *)data);
 	case PTRACE_ENABLE_TE:
 		if (!MACHINE_HAS_TE)
 			return -EIO;
@@ -719,6 +743,10 @@
 			regs->psw.mask = (regs->psw.mask & ~PSW_MASK_BA) |
 				(__u64)(tmp & PSW32_ADDR_AMODE);
 		} else {
+
+			if (test_pt_regs_flag(regs, PIF_SYSCALL) &&
+				addr == offsetof(struct compat_user, regs.gprs[2]))
+				fixup_int_code(child, data);
 			/* gpr 0-15 */
 			*(__u32*)((addr_t) &regs->psw + addr*2 + 4) = tmp;
 		}
@@ -746,6 +774,7 @@
 		/*
 		 * floating point control reg. is in the thread structure
 		 */
+		save_fpu_regs();
 		if (test_fp_ctl(tmp))
 			return -EINVAL;
 		child->thread.fpu.fpc = data;
@@ -827,9 +856,7 @@
 		}
 		return 0;
 	case PTRACE_GET_LAST_BREAK:
-		put_user(child->thread.last_break,
-			 (unsigned int __user *) data);
-		return 0;
+		return put_user(child->thread.last_break, (unsigned int __user *)data);
 	}
 	return compat_ptrace_request(child, request, addr, data);
 }
@@ -838,40 +865,45 @@
 asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
 {
 	unsigned long mask = -1UL;
+	long ret = -1;
 
 	/*
 	 * The sysc_tracesys code in entry.S stored the system
 	 * call number to gprs[2].
 	 */
 	if (test_thread_flag(TIF_SYSCALL_TRACE) &&
-	    (tracehook_report_syscall_entry(regs) ||
-	     regs->gprs[2] >= NR_syscalls)) {
+	    tracehook_report_syscall_entry(regs)) {
 		/*
-		 * Tracing decided this syscall should not happen or the
-		 * debugger stored an invalid system call number. Skip
+		 * Tracing decided this syscall should not happen. Skip
 		 * the system call and the system call restart handling.
 		 */
-		clear_pt_regs_flag(regs, PIF_SYSCALL);
-		return -1;
+		goto skip;
 	}
 
 	/* Do the secure computing check after ptrace. */
 	if (secure_computing(NULL)) {
 		/* seccomp failures shouldn't expose any additional code. */
-		return -1;
+		goto skip;
 	}
 
 	if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
-		trace_sys_enter(regs, regs->gprs[2]);
+		trace_sys_enter(regs, regs->int_code & 0xffff);
 
 	if (is_compat_task())
 		mask = 0xffffffff;
 
-	audit_syscall_entry(regs->gprs[2], regs->orig_gpr2 & mask,
+	audit_syscall_entry(regs->int_code & 0xffff, regs->orig_gpr2 & mask,
 			    regs->gprs[3] &mask, regs->gprs[4] &mask,
 			    regs->gprs[5] &mask);
 
+	if ((signed long)regs->gprs[2] >= NR_syscalls) {
+		regs->gprs[2] = -ENOSYS;
+		ret = -ENOSYS;
+	}
 	return regs->gprs[2];
+skip:
+	clear_pt_regs_flag(regs, PIF_SYSCALL);
+	return ret;
 }
 
 asmlinkage void do_syscall_trace_exit(struct pt_regs *regs)
@@ -976,9 +1008,7 @@
 	int rc = 0;
 	freg_t fprs[__NUM_FPRS];
 
-	if (target == current)
-		save_fpu_regs();
-
+	save_fpu_regs();
 	if (MACHINE_HAS_VX)
 		convert_vx_to_fp(fprs, target->thread.fpu.vxrs);
 	else
@@ -1256,7 +1286,6 @@
 		cb->pc == 1 &&
 		cb->qc == 0 &&
 		cb->reserved2 == 0 &&
-		cb->key == PAGE_DEFAULT_KEY &&
 		cb->reserved3 == 0 &&
 		cb->reserved4 == 0 &&
 		cb->reserved5 == 0 &&
@@ -1320,7 +1349,11 @@
 		kfree(data);
 		return -EINVAL;
 	}
-
+	/*
+	 * Override access key in any case, since user space should
+	 * not be able to set it, nor should it care about it.
+	 */
+	ri_cb.key = PAGE_DEFAULT_KEY >> 4;
 	preempt_disable();
 	if (!target->thread.ri_cb)
 		target->thread.ri_cb = data;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/runtime_instr.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/runtime_instr.c
@@ -57,7 +57,7 @@
 	cb->k = 1;
 	cb->ps = 1;
 	cb->pc = 1;
-	cb->key = PAGE_DEFAULT_KEY;
+	cb->key = PAGE_DEFAULT_KEY >> 4;
 	cb->v = 1;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/setup.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/setup.c
@@ -49,6 +49,7 @@
 #include <linux/memory.h>
 #include <linux/compat.h>
 #include <linux/start_kernel.h>
+#include <linux/security.h>
 
 #include <asm/boot_data.h>
 #include <asm/ipl.h>
@@ -73,6 +74,7 @@
 #include <asm/nospec-branch.h>
 #include <asm/mem_detect.h>
 #include <asm/uv.h>
+#include <asm/asm-offsets.h>
 #include "entry.h"
 
 /*
@@ -92,10 +94,6 @@
 
 unsigned long int_hwcap = 0;
 
-#ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST
-int __bootdata_preserved(prot_virt_guest);
-#endif
-
 int __bootdata(noexec_disabled);
 int __bootdata(memory_end_set);
 unsigned long __bootdata(memory_end);
@@ -111,6 +109,8 @@
 unsigned long __bootdata_preserved(__sdma);
 unsigned long __bootdata_preserved(__edma);
 unsigned long __bootdata_preserved(__kaslr_offset);
+unsigned int __bootdata_preserved(zlib_dfltcc_support);
+EXPORT_SYMBOL(zlib_dfltcc_support);
 
 unsigned long VMALLOC_START;
 EXPORT_SYMBOL(VMALLOC_START);
@@ -161,7 +161,7 @@
 	else if (CONSOLE_IS_3270)
 		add_preferred_console("tty3270", 0, NULL);
 	else if (CONSOLE_IS_VT220)
-		add_preferred_console("ttyS", 1, NULL);
+		add_preferred_console("ttysclp", 0, NULL);
 	else if (CONSOLE_IS_HVC)
 		add_preferred_console("hvc", 0, NULL);
 }
@@ -355,7 +355,6 @@
 
 void __init arch_call_rest_init(void)
 {
-	struct stack_frame *frame;
 	unsigned long stack;
 
 	stack = stack_alloc();
@@ -368,13 +367,7 @@
 	set_task_stack_end_magic(current);
 	stack += STACK_INIT_OFFSET;
 	S390_lowcore.kernel_stack = stack;
-	frame = (struct stack_frame *) stack;
-	memset(frame, 0, sizeof(*frame));
-	/* Branch to rest_init on the new stack, never returns */
-	asm volatile(
-		"	la	15,0(%[_frame])\n"
-		"	jg	rest_init\n"
-		: : [_frame] "a" (frame));
+	CALL_ON_STACK_NORETURN(rest_init, stack);
 }
 
 static void __init setup_lowcore_dat_off(void)
@@ -457,6 +450,8 @@
 	lc->spinlock_index = 0;
 	arch_spin_lock_setup(0);
 	lc->br_r1_trampoline = 0x07f1;	/* br %r1 */
+	lc->return_lpswe = gen_lpswe(__LC_RETURN_PSW);
+	lc->return_mcck_lpswe = gen_lpswe(__LC_RETURN_MCCK_PSW);
 
 	set_prefix((u32)(unsigned long) lc);
 	lowcore_ptr[0] = lc;
@@ -571,6 +566,9 @@
 			vmax = _REGION1_SIZE; /* 4-level kernel page table */
 	}
 
+	if (is_prot_virt_host())
+		adjust_to_uv_max(&vmax);
+
 	/* module area is at the end of the kernel address space. */
 	MODULES_END = vmax;
 	MODULES_VADDR = MODULES_END - MODULES_LEN;
@@ -631,7 +629,7 @@
 /*
  * Make sure that the area behind memory_end is protected
  */
-static void reserve_memory_end(void)
+static void __init reserve_memory_end(void)
 {
 	if (memory_end_set)
 		memblock_reserve(memory_end, ULONG_MAX);
@@ -640,7 +638,7 @@
 /*
  * Make sure that oldmem, where the dump is stored, is protected
  */
-static void reserve_oldmem(void)
+static void __init reserve_oldmem(void)
 {
 #ifdef CONFIG_CRASH_DUMP
 	if (OLDMEM_BASE)
@@ -652,7 +650,7 @@
 /*
  * Make sure that oldmem, where the dump is stored, is protected
  */
-static void remove_oldmem(void)
+static void __init remove_oldmem(void)
 {
 #ifdef CONFIG_CRASH_DUMP
 	if (OLDMEM_BASE)
@@ -845,9 +843,6 @@
 		storage_key_init_range(reg->base, reg->base + reg->size);
 	}
 	psw_set_key(PAGE_DEFAULT_KEY);
-
-	/* Only cosmetics */
-	memblock_enforce_memory_limit(memblock_end_of_DRAM());
 }
 
 /*
@@ -926,9 +921,9 @@
 	if (MACHINE_HAS_VX) {
 		elf_hwcap |= HWCAP_S390_VXRS;
 		if (test_facility(134))
-			elf_hwcap |= HWCAP_S390_VXRS_EXT;
-		if (test_facility(135))
 			elf_hwcap |= HWCAP_S390_VXRS_BCD;
+		if (test_facility(135))
+			elf_hwcap |= HWCAP_S390_VXRS_EXT;
 		if (test_facility(148))
 			elf_hwcap |= HWCAP_S390_VXRS_EXT2;
 		if (test_facility(152))
@@ -1012,6 +1007,11 @@
 	if (stsi(vmms, 3, 2, 2) == 0 && vmms->count)
 		add_device_randomness(&vmms->vm, sizeof(vmms->vm[0]) * vmms->count);
 	memblock_free((unsigned long) vmms, PAGE_SIZE);
+
+#ifdef CONFIG_ARCH_RANDOM
+	if (cpacf_query_func(CPACF_PRNO, CPACF_PRNO_TRNG))
+		static_branch_enable(&s390_arch_random_available);
+#endif
 }
 
 /*
@@ -1038,8 +1038,7 @@
 {
 	union diag318_info diag318_info = {
 		.cpnc = CPNC_LINUX,
-		.cpvc_linux = 0,
-		.cpvc_distro = {0},
+		.cpvc = 0,
 	};
 
 	if (!sclp.has_diag318)
@@ -1059,7 +1058,7 @@
 
 	if (!early_ipl_comp_list_addr)
 		return;
-	if (ipl_block.hdr.flags & IPL_PL_FLAG_IPLSR)
+	if (ipl_block.hdr.flags & IPL_PL_FLAG_SIPL)
 		pr_info("Linux is running with Secure-IPL enabled\n");
 	else
 		pr_info("Linux is running with Secure-IPL disabled\n");
@@ -1103,6 +1102,12 @@
 
 	log_component_list();
 
+#ifdef CONFIG_LOCK_DOWN_IN_SECURE_BOOT
+	if (ipl_get_secureboot())
+		security_lock_kernel_down("Secure IPL",
+					  LOCKDOWN_INTEGRITY_MAX);
+#endif
+
 	/* Have one command line that is parsed and saved in /proc/cmdline */
 	/* boot_command_line has been already set up in early.c */
 	*cmdline_p = boot_command_line;
@@ -1117,6 +1122,7 @@
 	if (IS_ENABLED(CONFIG_EXPOLINE_AUTO))
 		nospec_auto_detect();
 
+	jump_label_init();
 	parse_early_param();
 #ifdef CONFIG_CRASH_DUMP
 	/* Deactivate elfcorehdr= kernel parameter */
@@ -1151,6 +1157,8 @@
 	 */
 	memblock_trim_memory(1UL << (MAX_ORDER - 1 + PAGE_SHIFT));
 
+	if (is_prot_virt_host())
+		setup_uv();
 	setup_memory_end();
 	setup_memory();
 	dma_contiguous_reserve(memory_end);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/smp.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/smp.c
@@ -145,7 +145,7 @@
 
 static inline int pcpu_stopped(struct pcpu *pcpu)
 {
-	u32 uninitialized_var(status);
+	u32 status;
 
 	if (__pcpu_sigp(pcpu->address, SIGP_SENSE,
 			0, &status) != SIGP_CC_STATUS_STORED)
@@ -212,6 +212,8 @@
 	lc->spinlock_lockval = arch_spin_lockval(cpu);
 	lc->spinlock_index = 0;
 	lc->br_r1_trampoline = 0x07f1;	/* br %r1 */
+	lc->return_lpswe = gen_lpswe(__LC_RETURN_PSW);
+	lc->return_mcck_lpswe = gen_lpswe(__LC_RETURN_MCCK_PSW);
 	if (nmi_alloc_per_cpu(lc))
 		goto out_async;
 	if (vdso_alloc_per_cpu(lc))
@@ -262,10 +264,13 @@
 	lc->spinlock_index = 0;
 	lc->percpu_offset = __per_cpu_offset[cpu];
 	lc->kernel_asce = S390_lowcore.kernel_asce;
+	lc->user_asce = S390_lowcore.kernel_asce;
 	lc->machine_flags = S390_lowcore.machine_flags;
 	lc->user_timer = lc->system_timer =
 		lc->steal_timer = lc->avg_steal_timer = 0;
 	__ctl_store(lc->cregs_save_area, 0, 15);
+	lc->cregs_save_area[1] = lc->kernel_asce;
+	lc->cregs_save_area[7] = lc->vdso_asce;
 	save_access_regs((unsigned int *) lc->access_regs_save_area);
 	memcpy(lc->stfle_fac_list, S390_lowcore.stfle_fac_list,
 	       sizeof(lc->stfle_fac_list));
@@ -398,7 +403,7 @@
 	return -1;
 }
 
-bool arch_vcpu_is_preempted(int cpu)
+bool notrace arch_vcpu_is_preempted(int cpu)
 {
 	if (test_cpu_flag_of(CIF_ENABLED_WAIT, cpu))
 		return false;
@@ -408,7 +413,7 @@
 }
 EXPORT_SYMBOL(arch_vcpu_is_preempted);
 
-void smp_yield_cpu(int cpu)
+void notrace smp_yield_cpu(int cpu)
 {
 	if (MACHINE_HAS_DIAG9C) {
 		diag_stat_inc_norecursion(DIAG_STAT_X09C);
@@ -724,39 +729,67 @@
 
 static int smp_add_present_cpu(int cpu);
 
-static int __smp_rescan_cpus(struct sclp_core_info *info, int sysfs_add)
+static int smp_add_core(struct sclp_core_entry *core, cpumask_t *avail,
+			bool configured, bool early)
 {
 	struct pcpu *pcpu;
-	cpumask_t avail;
-	int cpu, nr, i, j;
+	int cpu, nr, i;
 	u16 address;
 
 	nr = 0;
-	cpumask_xor(&avail, cpu_possible_mask, cpu_present_mask);
-	cpu = cpumask_first(&avail);
-	for (i = 0; (i < info->combined) && (cpu < nr_cpu_ids); i++) {
-		if (sclp.has_core_type && info->core[i].type != boot_core_type)
+	if (sclp.has_core_type && core->type != boot_core_type)
+		return nr;
+	cpu = cpumask_first(avail);
+	address = core->core_id << smp_cpu_mt_shift;
+	for (i = 0; (i <= smp_cpu_mtid) && (cpu < nr_cpu_ids); i++) {
+		if (pcpu_find_address(cpu_present_mask, address + i))
 			continue;
-		address = info->core[i].core_id << smp_cpu_mt_shift;
-		for (j = 0; j <= smp_cpu_mtid; j++) {
-			if (pcpu_find_address(cpu_present_mask, address + j))
-				continue;
-			pcpu = pcpu_devices + cpu;
-			pcpu->address = address + j;
-			pcpu->state =
-				(cpu >= info->configured*(smp_cpu_mtid + 1)) ?
-				CPU_STATE_STANDBY : CPU_STATE_CONFIGURED;
-			smp_cpu_set_polarization(cpu, POLARIZATION_UNKNOWN);
-			set_cpu_present(cpu, true);
-			if (sysfs_add && smp_add_present_cpu(cpu) != 0)
-				set_cpu_present(cpu, false);
-			else
-				nr++;
-			cpu = cpumask_next(cpu, &avail);
-			if (cpu >= nr_cpu_ids)
+		pcpu = pcpu_devices + cpu;
+		pcpu->address = address + i;
+		if (configured)
+			pcpu->state = CPU_STATE_CONFIGURED;
+		else
+			pcpu->state = CPU_STATE_STANDBY;
+		smp_cpu_set_polarization(cpu, POLARIZATION_UNKNOWN);
+		set_cpu_present(cpu, true);
+		if (!early && smp_add_present_cpu(cpu) != 0)
+			set_cpu_present(cpu, false);
+		else
+			nr++;
+		cpumask_clear_cpu(cpu, avail);
+		cpu = cpumask_next(cpu, avail);
+	}
+	return nr;
+}
+
+static int __smp_rescan_cpus(struct sclp_core_info *info, bool early)
+{
+	struct sclp_core_entry *core;
+	static cpumask_t avail;
+	bool configured;
+	u16 core_id;
+	int nr, i;
+
+	nr = 0;
+	cpumask_xor(&avail, cpu_possible_mask, cpu_present_mask);
+	/*
+	 * Add IPL core first (which got logical CPU number 0) to make sure
+	 * that all SMT threads get subsequent logical CPU numbers.
+	 */
+	if (early) {
+		core_id = pcpu_devices[0].address >> smp_cpu_mt_shift;
+		for (i = 0; i < info->configured; i++) {
+			core = &info->core[i];
+			if (core->core_id == core_id) {
+				nr += smp_add_core(core, &avail, true, early);
 				break;
+			}
 		}
 	}
+	for (i = 0; i < info->combined; i++) {
+		configured = i < info->configured;
+		nr += smp_add_core(&info->core[i], &avail, configured, early);
+	}
 	return nr;
 }
 
@@ -805,18 +838,21 @@
 
 	/* Add CPUs present at boot */
 	get_online_cpus();
-	__smp_rescan_cpus(info, 0);
+	__smp_rescan_cpus(info, true);
 	put_online_cpus();
 	memblock_free_early((unsigned long)info, sizeof(*info));
 }
 
 static void smp_init_secondary(void)
 {
-	int cpu = smp_processor_id();
+	int cpu = raw_smp_processor_id();
 
 	S390_lowcore.last_update_clock = get_tod_clock();
 	restore_access_regs(S390_lowcore.access_regs_save_area);
+	set_cpu_flag(CIF_ASCE_PRIMARY);
+	set_cpu_flag(CIF_ASCE_SECONDARY);
 	cpu_init();
+	rcu_cpu_starting(cpu);
 	preempt_disable();
 	init_cpu_timer();
 	vtime_init();
@@ -843,30 +879,18 @@
 	S390_lowcore.restart_source = -1UL;
 	__ctl_load(S390_lowcore.cregs_save_area, 0, 15);
 	__load_psw_mask(PSW_KERNEL_BITS | PSW_MASK_DAT);
-	CALL_ON_STACK(smp_init_secondary, S390_lowcore.kernel_stack, 0);
+	CALL_ON_STACK_NORETURN(smp_init_secondary, S390_lowcore.kernel_stack);
 }
 
 /* Upping and downing of CPUs */
 int __cpu_up(unsigned int cpu, struct task_struct *tidle)
 {
-	struct pcpu *pcpu;
-	int base, i, rc;
+	struct pcpu *pcpu = pcpu_devices + cpu;
+	int rc;
 
-	pcpu = pcpu_devices + cpu;
 	if (pcpu->state != CPU_STATE_CONFIGURED)
 		return -EIO;
-	base = smp_get_base_cpu(cpu);
-	for (i = 0; i <= smp_cpu_mtid; i++) {
-		if (base + i < nr_cpu_ids)
-			if (cpu_online(base + i))
-				break;
-	}
-	/*
-	 * If this is the first CPU of the core to get online
-	 * do an initial CPU reset.
-	 */
-	if (i > smp_cpu_mtid &&
-	    pcpu_sigp_retry(pcpu_devices + base, SIGP_INITIAL_CPU_RESET, 0) !=
+	if (pcpu_sigp_retry(pcpu, SIGP_INITIAL_CPU_RESET, 0) !=
 	    SIGP_CC_ORDER_CODE_ACCEPTED)
 		return -EIO;
 
@@ -1148,7 +1172,7 @@
 	smp_get_core_info(info, 0);
 	get_online_cpus();
 	mutex_lock(&smp_cpu_state_mutex);
-	nr = __smp_rescan_cpus(info, 1);
+	nr = __smp_rescan_cpus(info, false);
 	mutex_unlock(&smp_cpu_state_mutex);
 	put_online_cpus();
 	kfree(info);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/sthyi.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/sthyi.c
@@ -460,9 +460,9 @@
  *
  * Fills the destination with system information returned by the STHYI
  * instruction. The data is generated by emulation or execution of STHYI,
- * if available. The return value is the condition code that would be
- * returned, the rc parameter is the return code which is passed in
- * register R2 + 1.
+ * if available. The return value is either a negative error value or
+ * the condition code that would be returned, the rc parameter is the
+ * return code which is passed in register R2 + 1.
  */
 int sthyi_fill(void *dst, u64 *rc)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/syscalls/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/syscalls/Makefile
@@ -12,7 +12,7 @@
 uapi-hdrs-y := $(uapi)/unistd_32.h
 uapi-hdrs-y += $(uapi)/unistd_64.h
 
-targets += $(addprefix ../../../,$(gen-y) $(kapi-hdrs-y) $(uapi-hdrs-y))
+targets += $(addprefix ../../../../,$(gen-y) $(kapi-hdrs-y) $(uapi-hdrs-y))
 
 PHONY += kapi uapi
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/time.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/time.c
@@ -310,6 +310,7 @@
 
 	vdso_data->tk_mult = tk->tkr_mono.mult;
 	vdso_data->tk_shift = tk->tkr_mono.shift;
+	vdso_data->hrtimer_res = hrtimer_resolution;
 	smp_wmb();
 	++vdso_data->tb_update_count;
 }
@@ -353,8 +354,9 @@
 static DEFINE_MUTEX(clock_sync_mutex);
 static unsigned long clock_sync_flags;
 
-#define CLOCK_SYNC_HAS_STP	0
-#define CLOCK_SYNC_STP		1
+#define CLOCK_SYNC_HAS_STP		0
+#define CLOCK_SYNC_STP			1
+#define CLOCK_SYNC_STPINFO_VALID	2
 
 /*
  * The get_clock function for the physical clock. It will get the current
@@ -591,6 +593,22 @@
 	queue_work(time_sync_wq, &stp_work);
 }
 
+static int __store_stpinfo(void)
+{
+	int rc = chsc_sstpi(stp_page, &stp_info, sizeof(struct stp_sstpi));
+
+	if (rc)
+		clear_bit(CLOCK_SYNC_STPINFO_VALID, &clock_sync_flags);
+	else
+		set_bit(CLOCK_SYNC_STPINFO_VALID, &clock_sync_flags);
+	return rc;
+}
+
+static int stpinfo_valid(void)
+{
+	return stp_online && test_bit(CLOCK_SYNC_STPINFO_VALID, &clock_sync_flags);
+}
+
 static int stp_sync_clock(void *data)
 {
 	struct clock_sync_data *sync = data;
@@ -612,8 +630,7 @@
 			if (rc == 0) {
 				sync->clock_delta = clock_delta;
 				clock_sync_global(clock_delta);
-				rc = chsc_sstpi(stp_page, &stp_info,
-						sizeof(struct stp_sstpi));
+				rc = __store_stpinfo();
 				if (rc == 0 && stp_info.tmd != 2)
 					rc = -EAGAIN;
 			}
@@ -658,7 +675,7 @@
 	if (rc)
 		goto out_unlock;
 
-	rc = chsc_sstpi(stp_page, &stp_info, sizeof(struct stp_sstpi));
+	rc = __store_stpinfo();
 	if (rc || stp_info.c == 0)
 		goto out_unlock;
 
@@ -695,10 +712,14 @@
 				struct device_attribute *attr,
 				char *buf)
 {
-	if (!stp_online)
-		return -ENODATA;
-	return sprintf(buf, "%016llx\n",
-		       *(unsigned long long *) stp_info.ctnid);
+	ssize_t ret = -ENODATA;
+
+	mutex_lock(&stp_work_mutex);
+	if (stpinfo_valid())
+		ret = sprintf(buf, "%016llx\n",
+			      *(unsigned long long *) stp_info.ctnid);
+	mutex_unlock(&stp_work_mutex);
+	return ret;
 }
 
 static DEVICE_ATTR(ctn_id, 0400, stp_ctn_id_show, NULL);
@@ -707,9 +728,13 @@
 				struct device_attribute *attr,
 				char *buf)
 {
-	if (!stp_online)
-		return -ENODATA;
-	return sprintf(buf, "%i\n", stp_info.ctn);
+	ssize_t ret = -ENODATA;
+
+	mutex_lock(&stp_work_mutex);
+	if (stpinfo_valid())
+		ret = sprintf(buf, "%i\n", stp_info.ctn);
+	mutex_unlock(&stp_work_mutex);
+	return ret;
 }
 
 static DEVICE_ATTR(ctn_type, 0400, stp_ctn_type_show, NULL);
@@ -718,9 +743,13 @@
 				   struct device_attribute *attr,
 				   char *buf)
 {
-	if (!stp_online || !(stp_info.vbits & 0x2000))
-		return -ENODATA;
-	return sprintf(buf, "%i\n", (int)(s16) stp_info.dsto);
+	ssize_t ret = -ENODATA;
+
+	mutex_lock(&stp_work_mutex);
+	if (stpinfo_valid() && (stp_info.vbits & 0x2000))
+		ret = sprintf(buf, "%i\n", (int)(s16) stp_info.dsto);
+	mutex_unlock(&stp_work_mutex);
+	return ret;
 }
 
 static DEVICE_ATTR(dst_offset, 0400, stp_dst_offset_show, NULL);
@@ -729,9 +758,13 @@
 					struct device_attribute *attr,
 					char *buf)
 {
-	if (!stp_online || !(stp_info.vbits & 0x8000))
-		return -ENODATA;
-	return sprintf(buf, "%i\n", (int)(s16) stp_info.leaps);
+	ssize_t ret = -ENODATA;
+
+	mutex_lock(&stp_work_mutex);
+	if (stpinfo_valid() && (stp_info.vbits & 0x8000))
+		ret = sprintf(buf, "%i\n", (int)(s16) stp_info.leaps);
+	mutex_unlock(&stp_work_mutex);
+	return ret;
 }
 
 static DEVICE_ATTR(leap_seconds, 0400, stp_leap_seconds_show, NULL);
@@ -740,9 +773,13 @@
 				struct device_attribute *attr,
 				char *buf)
 {
-	if (!stp_online)
-		return -ENODATA;
-	return sprintf(buf, "%i\n", (int)(s16) stp_info.stratum);
+	ssize_t ret = -ENODATA;
+
+	mutex_lock(&stp_work_mutex);
+	if (stpinfo_valid())
+		ret = sprintf(buf, "%i\n", (int)(s16) stp_info.stratum);
+	mutex_unlock(&stp_work_mutex);
+	return ret;
 }
 
 static DEVICE_ATTR(stratum, 0400, stp_stratum_show, NULL);
@@ -751,9 +788,13 @@
 				struct device_attribute *attr,
 				char *buf)
 {
-	if (!stp_online || !(stp_info.vbits & 0x0800))
-		return -ENODATA;
-	return sprintf(buf, "%i\n", (int) stp_info.tto);
+	ssize_t ret = -ENODATA;
+
+	mutex_lock(&stp_work_mutex);
+	if (stpinfo_valid() && (stp_info.vbits & 0x0800))
+		ret = sprintf(buf, "%i\n", (int) stp_info.tto);
+	mutex_unlock(&stp_work_mutex);
+	return ret;
 }
 
 static DEVICE_ATTR(time_offset, 0400, stp_time_offset_show, NULL);
@@ -762,9 +803,13 @@
 				struct device_attribute *attr,
 				char *buf)
 {
-	if (!stp_online || !(stp_info.vbits & 0x4000))
-		return -ENODATA;
-	return sprintf(buf, "%i\n", (int)(s16) stp_info.tzo);
+	ssize_t ret = -ENODATA;
+
+	mutex_lock(&stp_work_mutex);
+	if (stpinfo_valid() && (stp_info.vbits & 0x4000))
+		ret = sprintf(buf, "%i\n", (int)(s16) stp_info.tzo);
+	mutex_unlock(&stp_work_mutex);
+	return ret;
 }
 
 static DEVICE_ATTR(time_zone_offset, 0400,
@@ -774,9 +819,13 @@
 				struct device_attribute *attr,
 				char *buf)
 {
-	if (!stp_online)
-		return -ENODATA;
-	return sprintf(buf, "%i\n", stp_info.tmd);
+	ssize_t ret = -ENODATA;
+
+	mutex_lock(&stp_work_mutex);
+	if (stpinfo_valid())
+		ret = sprintf(buf, "%i\n", stp_info.tmd);
+	mutex_unlock(&stp_work_mutex);
+	return ret;
 }
 
 static DEVICE_ATTR(timing_mode, 0400, stp_timing_mode_show, NULL);
@@ -785,9 +834,13 @@
 				struct device_attribute *attr,
 				char *buf)
 {
-	if (!stp_online)
-		return -ENODATA;
-	return sprintf(buf, "%i\n", stp_info.tst);
+	ssize_t ret = -ENODATA;
+
+	mutex_lock(&stp_work_mutex);
+	if (stpinfo_valid())
+		ret = sprintf(buf, "%i\n", stp_info.tst);
+	mutex_unlock(&stp_work_mutex);
+	return ret;
 }
 
 static DEVICE_ATTR(timing_state, 0400, stp_timing_state_show, NULL);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/topology.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/topology.c
@@ -65,6 +65,13 @@
 
 cpumask_t cpus_with_topology;
 
+int __cpu_to_node(int cpu)
+{
+	return cpu_topology[cpu].node_id;
+}
+
+EXPORT_SYMBOL(__cpu_to_node);
+
 static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu)
 {
 	cpumask_t mask;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/trace.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/trace.c
@@ -14,7 +14,7 @@
 
 static DEFINE_PER_CPU(unsigned int, diagnose_trace_depth);
 
-void trace_s390_diagnose_norecursion(int diag_nr)
+void notrace trace_s390_diagnose_norecursion(int diag_nr)
 {
 	unsigned long flags;
 	unsigned int *depth;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/unwind_bc.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/unwind_bc.c
@@ -60,6 +60,11 @@
 		ip = READ_ONCE_NOCHECK(sf->gprs[8]);
 		reliable = false;
 		regs = NULL;
+		if (!__kernel_text_address(ip)) {
+			/* skip bogus %r14 */
+			state->regs = NULL;
+			return unwind_next_frame(state);
+		}
 	} else {
 		sf = (struct stack_frame *) state->sp;
 		sp = READ_ONCE_NOCHECK(sf->back_chain);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/uv.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/uv.c
@@ -0,0 +1,472 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Common Ultravisor functions and initialization
+ *
+ * Copyright IBM Corp. 2019, 2020
+ */
+#define KMSG_COMPONENT "prot_virt"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/sizes.h>
+#include <linux/bitmap.h>
+#include <linux/memblock.h>
+#include <linux/pagemap.h>
+#include <linux/swap.h>
+#include <asm/facility.h>
+#include <asm/sections.h>
+#include <asm/uv.h>
+
+/* the bootdata_preserved fields come from ones in arch/s390/boot/uv.c */
+#ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST
+int __bootdata_preserved(prot_virt_guest);
+#endif
+
+#if IS_ENABLED(CONFIG_KVM)
+int prot_virt_host;
+EXPORT_SYMBOL(prot_virt_host);
+struct uv_info __bootdata_preserved(uv_info);
+EXPORT_SYMBOL(uv_info);
+
+static int __init prot_virt_setup(char *val)
+{
+	bool enabled;
+	int rc;
+
+	rc = kstrtobool(val, &enabled);
+	if (!rc && enabled)
+		prot_virt_host = 1;
+
+	if (is_prot_virt_guest() && prot_virt_host) {
+		prot_virt_host = 0;
+		pr_warn("Protected virtualization not available in protected guests.");
+	}
+
+	if (prot_virt_host && !test_facility(158)) {
+		prot_virt_host = 0;
+		pr_warn("Protected virtualization not supported by the hardware.");
+	}
+
+	return rc;
+}
+early_param("prot_virt", prot_virt_setup);
+
+static int __init uv_init(unsigned long stor_base, unsigned long stor_len)
+{
+	struct uv_cb_init uvcb = {
+		.header.cmd = UVC_CMD_INIT_UV,
+		.header.len = sizeof(uvcb),
+		.stor_origin = stor_base,
+		.stor_len = stor_len,
+	};
+
+	if (uv_call(0, (uint64_t)&uvcb)) {
+		pr_err("Ultravisor init failed with rc: 0x%x rrc: 0%x\n",
+		       uvcb.header.rc, uvcb.header.rrc);
+		return -1;
+	}
+	return 0;
+}
+
+void __init setup_uv(void)
+{
+	unsigned long uv_stor_base;
+
+	uv_stor_base = (unsigned long)memblock_alloc_try_nid(
+		uv_info.uv_base_stor_len, SZ_1M, SZ_2G,
+		MEMBLOCK_ALLOC_ACCESSIBLE, NUMA_NO_NODE);
+	if (!uv_stor_base) {
+		pr_warn("Failed to reserve %lu bytes for ultravisor base storage\n",
+			uv_info.uv_base_stor_len);
+		goto fail;
+	}
+
+	if (uv_init(uv_stor_base, uv_info.uv_base_stor_len)) {
+		memblock_free(uv_stor_base, uv_info.uv_base_stor_len);
+		goto fail;
+	}
+
+	pr_info("Reserving %luMB as ultravisor base storage\n",
+		uv_info.uv_base_stor_len >> 20);
+	return;
+fail:
+	pr_info("Disabling support for protected virtualization");
+	prot_virt_host = 0;
+}
+
+void adjust_to_uv_max(unsigned long *vmax)
+{
+	*vmax = min_t(unsigned long, *vmax, uv_info.max_sec_stor_addr);
+}
+
+/*
+ * Requests the Ultravisor to pin the page in the shared state. This will
+ * cause an intercept when the guest attempts to unshare the pinned page.
+ */
+static int uv_pin_shared(unsigned long paddr)
+{
+	struct uv_cb_cfs uvcb = {
+		.header.cmd = UVC_CMD_PIN_PAGE_SHARED,
+		.header.len = sizeof(uvcb),
+		.paddr = paddr,
+	};
+
+	if (uv_call(0, (u64)&uvcb))
+		return -EINVAL;
+	return 0;
+}
+
+/*
+ * Requests the Ultravisor to encrypt a guest page and make it
+ * accessible to the host for paging (export).
+ *
+ * @paddr: Absolute host address of page to be exported
+ */
+int uv_convert_from_secure(unsigned long paddr)
+{
+	struct uv_cb_cfs uvcb = {
+		.header.cmd = UVC_CMD_CONV_FROM_SEC_STOR,
+		.header.len = sizeof(uvcb),
+		.paddr = paddr
+	};
+
+	if (uv_call(0, (u64)&uvcb))
+		return -EINVAL;
+	return 0;
+}
+
+/*
+ * Calculate the expected ref_count for a page that would otherwise have no
+ * further pins. This was cribbed from similar functions in other places in
+ * the kernel, but with some slight modifications. We know that a secure
+ * page can not be a huge page for example.
+ */
+static int expected_page_refs(struct page *page)
+{
+	int res;
+
+	res = page_mapcount(page);
+	if (PageSwapCache(page)) {
+		res++;
+	} else if (page_mapping(page)) {
+		res++;
+		if (page_has_private(page))
+			res++;
+	}
+	return res;
+}
+
+static int make_secure_pte(pte_t *ptep, unsigned long addr,
+			   struct page *exp_page, struct uv_cb_header *uvcb)
+{
+	pte_t entry = READ_ONCE(*ptep);
+	struct page *page;
+	int expected, cc = 0;
+
+	if (!pte_present(entry))
+		return -ENXIO;
+	if (pte_val(entry) & _PAGE_INVALID)
+		return -ENXIO;
+
+	page = pte_page(entry);
+	if (page != exp_page)
+		return -ENXIO;
+	if (PageWriteback(page))
+		return -EAGAIN;
+	expected = expected_page_refs(page);
+	if (!page_ref_freeze(page, expected))
+		return -EBUSY;
+	set_bit(PG_arch_1, &page->flags);
+	/*
+	 * If the UVC does not succeed or fail immediately, we don't want to
+	 * loop for long, or we might get stall notifications.
+	 * On the other hand, this is a complex scenario and we are holding a lot of
+	 * locks, so we can't easily sleep and reschedule. We try only once,
+	 * and if the UVC returned busy or partial completion, we return
+	 * -EAGAIN and we let the callers deal with it.
+	 */
+	cc = __uv_call(0, (u64)uvcb);
+	page_ref_unfreeze(page, expected);
+	/*
+	 * Return -ENXIO if the page was not mapped, -EINVAL for other errors.
+	 * If busy or partially completed, return -EAGAIN.
+	 */
+	if (cc == UVC_CC_OK)
+		return 0;
+	else if (cc == UVC_CC_BUSY || cc == UVC_CC_PARTIAL)
+		return -EAGAIN;
+	return uvcb->rc == 0x10a ? -ENXIO : -EINVAL;
+}
+
+/*
+ * Requests the Ultravisor to make a page accessible to a guest.
+ * If it's brought in the first time, it will be cleared. If
+ * it has been exported before, it will be decrypted and integrity
+ * checked.
+ */
+int gmap_make_secure(struct gmap *gmap, unsigned long gaddr, void *uvcb)
+{
+	struct vm_area_struct *vma;
+	bool local_drain = false;
+	spinlock_t *ptelock;
+	unsigned long uaddr;
+	struct page *page;
+	pte_t *ptep;
+	int rc;
+
+again:
+	rc = -EFAULT;
+	down_read(&gmap->mm->mmap_sem);
+
+	uaddr = __gmap_translate(gmap, gaddr);
+	if (IS_ERR_VALUE(uaddr))
+		goto out;
+	vma = find_vma(gmap->mm, uaddr);
+	if (!vma)
+		goto out;
+	/*
+	 * Secure pages cannot be huge and userspace should not combine both.
+	 * In case userspace does it anyway this will result in an -EFAULT for
+	 * the unpack. The guest is thus never reaching secure mode. If
+	 * userspace is playing dirty tricky with mapping huge pages later
+	 * on this will result in a segmentation fault.
+	 */
+	if (is_vm_hugetlb_page(vma))
+		goto out;
+
+	rc = -ENXIO;
+	page = follow_page(vma, uaddr, FOLL_WRITE);
+	if (IS_ERR_OR_NULL(page))
+		goto out;
+
+	lock_page(page);
+	ptep = get_locked_pte(gmap->mm, uaddr, &ptelock);
+	rc = make_secure_pte(ptep, uaddr, page, uvcb);
+	pte_unmap_unlock(ptep, ptelock);
+	unlock_page(page);
+out:
+	up_read(&gmap->mm->mmap_sem);
+
+	if (rc == -EAGAIN) {
+		/*
+		 * If we are here because the UVC returned busy or partial
+		 * completion, this is just a useless check, but it is safe.
+		 */
+		wait_on_page_writeback(page);
+	} else if (rc == -EBUSY) {
+		/*
+		 * If we have tried a local drain and the page refcount
+		 * still does not match our expected safe value, try with a
+		 * system wide drain. This is needed if the pagevecs holding
+		 * the page are on a different CPU.
+		 */
+		if (local_drain) {
+			lru_add_drain_all();
+			/* We give up here, and let the caller try again */
+			return -EAGAIN;
+		}
+		/*
+		 * We are here if the page refcount does not match the
+		 * expected safe value. The main culprits are usually
+		 * pagevecs. With lru_add_drain() we drain the pagevecs
+		 * on the local CPU so that hopefully the refcount will
+		 * reach the expected safe value.
+		 */
+		lru_add_drain();
+		local_drain = true;
+		/* And now we try again immediately after draining */
+		goto again;
+	} else if (rc == -ENXIO) {
+		if (gmap_fault(gmap, gaddr, FAULT_FLAG_WRITE))
+			return -EFAULT;
+		return -EAGAIN;
+	}
+	return rc;
+}
+EXPORT_SYMBOL_GPL(gmap_make_secure);
+
+int gmap_convert_to_secure(struct gmap *gmap, unsigned long gaddr)
+{
+	struct uv_cb_cts uvcb = {
+		.header.cmd = UVC_CMD_CONV_TO_SEC_STOR,
+		.header.len = sizeof(uvcb),
+		.guest_handle = gmap->guest_handle,
+		.gaddr = gaddr,
+	};
+
+	return gmap_make_secure(gmap, gaddr, &uvcb);
+}
+EXPORT_SYMBOL_GPL(gmap_convert_to_secure);
+
+/*
+ * To be called with the page locked or with an extra reference! This will
+ * prevent gmap_make_secure from touching the page concurrently. Having 2
+ * parallel make_page_accessible is fine, as the UV calls will become a
+ * no-op if the page is already exported.
+ */
+int arch_make_page_accessible(struct page *page)
+{
+	int rc = 0;
+
+	/* Hugepage cannot be protected, so nothing to do */
+	if (PageHuge(page))
+		return 0;
+
+	/*
+	 * PG_arch_1 is used in 3 places:
+	 * 1. for kernel page tables during early boot
+	 * 2. for storage keys of huge pages and KVM
+	 * 3. As an indication that this page might be secure. This can
+	 *    overindicate, e.g. we set the bit before calling
+	 *    convert_to_secure.
+	 * As secure pages are never huge, all 3 variants can co-exists.
+	 */
+	if (!test_bit(PG_arch_1, &page->flags))
+		return 0;
+
+	rc = uv_pin_shared(page_to_phys(page));
+	if (!rc) {
+		clear_bit(PG_arch_1, &page->flags);
+		return 0;
+	}
+
+	rc = uv_convert_from_secure(page_to_phys(page));
+	if (!rc) {
+		clear_bit(PG_arch_1, &page->flags);
+		return 0;
+	}
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(arch_make_page_accessible);
+
+#endif
+
+#if defined(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) || IS_ENABLED(CONFIG_KVM)
+static ssize_t uv_query_facilities(struct kobject *kobj,
+				   struct kobj_attribute *attr, char *page)
+{
+	return snprintf(page, PAGE_SIZE, "%lx\n%lx\n%lx\n%lx\n",
+			uv_info.inst_calls_list[0],
+			uv_info.inst_calls_list[1],
+			uv_info.inst_calls_list[2],
+			uv_info.inst_calls_list[3]);
+}
+
+static struct kobj_attribute uv_query_facilities_attr =
+	__ATTR(facilities, 0444, uv_query_facilities, NULL);
+
+static ssize_t uv_query_max_guest_cpus(struct kobject *kobj,
+				       struct kobj_attribute *attr, char *page)
+{
+	return snprintf(page, PAGE_SIZE, "%d\n",
+			uv_info.max_guest_cpus);
+}
+
+static struct kobj_attribute uv_query_max_guest_cpus_attr =
+	__ATTR(max_cpus, 0444, uv_query_max_guest_cpus, NULL);
+
+static ssize_t uv_query_max_guest_vms(struct kobject *kobj,
+				      struct kobj_attribute *attr, char *page)
+{
+	return snprintf(page, PAGE_SIZE, "%d\n",
+			uv_info.max_num_sec_conf);
+}
+
+static struct kobj_attribute uv_query_max_guest_vms_attr =
+	__ATTR(max_guests, 0444, uv_query_max_guest_vms, NULL);
+
+static ssize_t uv_query_max_guest_addr(struct kobject *kobj,
+				       struct kobj_attribute *attr, char *page)
+{
+	return snprintf(page, PAGE_SIZE, "%lx\n",
+			uv_info.max_sec_stor_addr);
+}
+
+static struct kobj_attribute uv_query_max_guest_addr_attr =
+	__ATTR(max_address, 0444, uv_query_max_guest_addr, NULL);
+
+static struct attribute *uv_query_attrs[] = {
+	&uv_query_facilities_attr.attr,
+	&uv_query_max_guest_cpus_attr.attr,
+	&uv_query_max_guest_vms_attr.attr,
+	&uv_query_max_guest_addr_attr.attr,
+	NULL,
+};
+
+static struct attribute_group uv_query_attr_group = {
+	.attrs = uv_query_attrs,
+};
+
+static ssize_t uv_is_prot_virt_guest(struct kobject *kobj,
+				     struct kobj_attribute *attr, char *page)
+{
+	int val = 0;
+
+#ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST
+	val = prot_virt_guest;
+#endif
+	return scnprintf(page, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t uv_is_prot_virt_host(struct kobject *kobj,
+				    struct kobj_attribute *attr, char *page)
+{
+	int val = 0;
+
+#if IS_ENABLED(CONFIG_KVM)
+	val = prot_virt_host;
+#endif
+
+	return scnprintf(page, PAGE_SIZE, "%d\n", val);
+}
+
+static struct kobj_attribute uv_prot_virt_guest =
+	__ATTR(prot_virt_guest, 0444, uv_is_prot_virt_guest, NULL);
+
+static struct kobj_attribute uv_prot_virt_host =
+	__ATTR(prot_virt_host, 0444, uv_is_prot_virt_host, NULL);
+
+static const struct attribute *uv_prot_virt_attrs[] = {
+	&uv_prot_virt_guest.attr,
+	&uv_prot_virt_host.attr,
+	NULL,
+};
+
+static struct kset *uv_query_kset;
+static struct kobject *uv_kobj;
+
+static int __init uv_info_init(void)
+{
+	int rc = -ENOMEM;
+
+	if (!test_facility(158))
+		return 0;
+
+	uv_kobj = kobject_create_and_add("uv", firmware_kobj);
+	if (!uv_kobj)
+		return -ENOMEM;
+
+	rc = sysfs_create_files(uv_kobj, uv_prot_virt_attrs);
+	if (rc)
+		goto out_kobj;
+
+	uv_query_kset = kset_create_and_add("query", NULL, uv_kobj);
+	if (!uv_query_kset)
+		goto out_ind_files;
+
+	rc = sysfs_create_group(&uv_query_kset->kobj, &uv_query_attr_group);
+	if (!rc)
+		return 0;
+
+	kset_unregister(uv_query_kset);
+out_ind_files:
+	sysfs_remove_files(uv_kobj, uv_prot_virt_attrs);
+out_kobj:
+	kobject_del(uv_kobj);
+	kobject_put(uv_kobj);
+	return rc;
+}
+device_initcall(uv_info_init);
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/vdso64/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/vdso64/Makefile
@@ -18,8 +18,8 @@
 
 KBUILD_CFLAGS_64 := $(filter-out -m64,$(KBUILD_CFLAGS))
 KBUILD_CFLAGS_64 += -m64 -fPIC -shared -fno-common -fno-builtin
-KBUILD_CFLAGS_64 += -nostdlib -Wl,-soname=linux-vdso64.so.1 \
-		    -Wl,--hash-style=both
+ldflags-y := -fPIC -shared -nostdlib -soname=linux-vdso64.so.1 \
+	     --hash-style=both --build-id -T
 
 $(targets:%=$(obj)/%.dbg): KBUILD_CFLAGS = $(KBUILD_CFLAGS_64)
 $(targets:%=$(obj)/%.dbg): KBUILD_AFLAGS = $(KBUILD_AFLAGS_64)
@@ -37,8 +37,8 @@
 $(obj)/vdso64_wrapper.o : $(obj)/vdso64.so
 
 # link rule for the .so file, .lds has to be first
-$(obj)/vdso64.so.dbg: $(src)/vdso64.lds $(obj-vdso64) FORCE
-	$(call if_changed,vdso64ld)
+$(obj)/vdso64.so.dbg: $(obj)/vdso64.lds $(obj-vdso64) FORCE
+	$(call if_changed,ld)
 
 # strip rule for the .so file
 $(obj)/%.so: OBJCOPYFLAGS := -S
@@ -50,8 +50,6 @@
 	$(call if_changed_dep,vdso64as)
 
 # actual build commands
-quiet_cmd_vdso64ld = VDSO64L $@
-      cmd_vdso64ld = $(CC) $(c_flags) -Wl,-T $(filter %.lds %.o,$^) -o $@
 quiet_cmd_vdso64as = VDSO64A $@
       cmd_vdso64as = $(CC) $(a_flags) -c -o $@ $<
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/vdso64/clock_getres.S
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/vdso64/clock_getres.S
@@ -17,12 +17,14 @@
 	.type  __kernel_clock_getres,@function
 __kernel_clock_getres:
 	CFI_STARTPROC
-	larl	%r1,4f
+	larl	%r1,3f
+	lg	%r0,0(%r1)
 	cghi	%r2,__CLOCK_REALTIME_COARSE
 	je	0f
 	cghi	%r2,__CLOCK_MONOTONIC_COARSE
 	je	0f
-	larl	%r1,3f
+	larl	%r1,_vdso_data
+	llgf	%r0,__VDSO_CLOCK_REALTIME_RES(%r1)
 	cghi	%r2,__CLOCK_REALTIME
 	je	0f
 	cghi	%r2,__CLOCK_MONOTONIC
@@ -36,7 +38,6 @@
 	jz	2f
 0:	ltgr	%r3,%r3
 	jz	1f				/* res == NULL */
-	lg	%r0,0(%r1)
 	xc	0(8,%r3),0(%r3)			/* set tp->tv_sec to zero */
 	stg	%r0,8(%r3)			/* store tp->tv_usec */
 1:	lghi	%r2,0
@@ -45,6 +46,5 @@
 	svc	0
 	br	%r14
 	CFI_ENDPROC
-3:	.quad	__CLOCK_REALTIME_RES
-4:	.quad	__CLOCK_COARSE_RES
+3:	.quad	__CLOCK_COARSE_RES
 	.size	__kernel_clock_getres,.-__kernel_clock_getres
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/vmlinux.lds.S
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/vmlinux.lds.S
@@ -15,6 +15,8 @@
 /* Handle ro_after_init data on our own. */
 #define RO_AFTER_INIT_DATA
 
+#define RUNTIME_DISCARD_EXIT
+
 #include <asm-generic/vmlinux.lds.h>
 #include <asm/vmlinux.lds.h>
 
@@ -124,6 +126,7 @@
 	/*
 	 * Table with the patch locations to undo expolines
 	*/
+	. = ALIGN(4);
 	.nospec_call_table : {
 		__nospec_call_start = . ;
 		*(.s390_indirect*)
@@ -188,5 +191,6 @@
 	DISCARDS
 	/DISCARD/ : {
 		*(.eh_frame)
+		*(.interp)
 	}
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kernel/vtime.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kernel/vtime.c
@@ -136,7 +136,8 @@
 		"	stck	%1"	/* Store current tod clock value */
 #endif
 		: "=Q" (S390_lowcore.last_update_timer),
-		  "=Q" (S390_lowcore.last_update_clock));
+		  "=Q" (S390_lowcore.last_update_clock)
+		: : "cc");
 	clock = S390_lowcore.last_update_clock - clock;
 	timer -= S390_lowcore.last_update_timer;
 
@@ -213,13 +214,13 @@
 		virt_timer_expire();
 
 	steal = S390_lowcore.steal_timer;
-	avg_steal = S390_lowcore.avg_steal_timer / 2;
+	avg_steal = S390_lowcore.avg_steal_timer;
 	if ((s64) steal > 0) {
 		S390_lowcore.steal_timer = 0;
-		account_steal_time(steal);
+		account_steal_time(cputime_to_nsecs(steal));
 		avg_steal += steal;
 	}
-	S390_lowcore.avg_steal_timer = avg_steal;
+	S390_lowcore.avg_steal_timer = avg_steal / 2;
 }
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kvm/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kvm/Makefile
@@ -9,6 +9,6 @@
 ccflags-y := -Ivirt/kvm -Iarch/s390/kvm
 
 kvm-objs := $(common-objs) kvm-s390.o intercept.o interrupt.o priv.o sigp.o
-kvm-objs += diag.o gaccess.o guestdbg.o vsie.o
+kvm-objs += diag.o gaccess.o guestdbg.o vsie.o pv.o
 
 obj-$(CONFIG_KVM) += kvm.o
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kvm/diag.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kvm/diag.c
@@ -2,7 +2,7 @@
 /*
  * handling diagnose instructions
  *
- * Copyright IBM Corp. 2008, 2011
+ * Copyright IBM Corp. 2008, 2020
  *
  *    Author(s): Carsten Otte <cotte@de.ibm.com>
  *               Christian Borntraeger <borntraeger@de.ibm.com>
@@ -78,7 +78,7 @@
 	vcpu->stat.diagnose_258++;
 	if (vcpu->run->s.regs.gprs[rx] & 7)
 		return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
-	rc = read_guest(vcpu, vcpu->run->s.regs.gprs[rx], rx, &parm, sizeof(parm));
+	rc = read_guest_real(vcpu, vcpu->run->s.regs.gprs[rx], &parm, sizeof(parm));
 	if (rc)
 		return kvm_s390_inject_prog_cond(vcpu, rc);
 	if (parm.parm_version != 2 || parm.parm_len < 5 || parm.code != 0x258)
@@ -187,6 +187,10 @@
 		return -EOPNOTSUPP;
 	}
 
+	/*
+	 * no need to check the return value of vcpu_stop as it can only have
+	 * an error for protvirt, but protvirt means user cpu state
+	 */
 	if (!kvm_s390_user_cpu_state_ctrl(vcpu->kvm))
 		kvm_s390_vcpu_stop(vcpu);
 	vcpu->run->s390_reset_flags |= KVM_S390_RESET_SUBSYSTEM;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kvm/gaccess.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kvm/gaccess.c
@@ -9,6 +9,7 @@
 #include <linux/vmalloc.h>
 #include <linux/mm_types.h>
 #include <linux/err.h>
+#include <linux/bitfield.h>
 
 #include <asm/pgtable.h>
 #include <asm/gmap.h>
@@ -794,48 +795,270 @@
 	return 1;
 }
 
-static int guest_page_range(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar,
-			    unsigned long *pages, unsigned long nr_pages,
-			    const union asce asce, enum gacc_mode mode)
+static int vm_check_access_key(struct kvm *kvm, u8 access_key,
+			       enum gacc_mode mode, gpa_t gpa)
+{
+	u8 storage_key, access_control;
+	bool fetch_protected;
+	unsigned long hva;
+	int r;
+
+	if (access_key == 0)
+		return 0;
+
+	hva = gfn_to_hva(kvm, gpa_to_gfn(gpa));
+	if (kvm_is_error_hva(hva))
+		return PGM_ADDRESSING;
+
+	down_read(&current->mm->mmap_sem);
+	r = get_guest_storage_key(current->mm, hva, &storage_key);
+	up_read(&current->mm->mmap_sem);
+	if (r)
+		return r;
+	access_control = FIELD_GET(_PAGE_ACC_BITS, storage_key);
+	if (access_control == access_key)
+		return 0;
+	fetch_protected = storage_key & _PAGE_FP_BIT;
+	if ((mode == GACC_FETCH || mode == GACC_IFETCH) && !fetch_protected)
+		return 0;
+	return PGM_PROTECTION;
+}
+
+static bool fetch_prot_override_applicable(struct kvm_vcpu *vcpu, enum gacc_mode mode,
+					   union asce asce)
+{
+	psw_t *psw = &vcpu->arch.sie_block->gpsw;
+	unsigned long override;
+
+	if (mode == GACC_FETCH || mode == GACC_IFETCH) {
+		/* check if fetch protection override enabled */
+		override = vcpu->arch.sie_block->gcr[0];
+		override &= CR0_FETCH_PROTECTION_OVERRIDE;
+		/* not applicable if subject to DAT && private space */
+		override = override && !(psw_bits(*psw).dat && asce.p);
+		return override;
+	}
+	return false;
+}
+
+static bool fetch_prot_override_applies(unsigned long ga, unsigned int len)
+{
+	return ga < 2048 && ga + len <= 2048;
+}
+
+static bool storage_prot_override_applicable(struct kvm_vcpu *vcpu)
+{
+	/* check if storage protection override enabled */
+	return vcpu->arch.sie_block->gcr[0] & CR0_STORAGE_PROTECTION_OVERRIDE;
+}
+
+static bool storage_prot_override_applies(u8 access_control)
+{
+	/* matches special storage protection override key (9) -> allow */
+	return access_control == PAGE_SPO_ACC;
+}
+
+static int vcpu_check_access_key(struct kvm_vcpu *vcpu, u8 access_key,
+				 enum gacc_mode mode, union asce asce, gpa_t gpa,
+				 unsigned long ga, unsigned int len)
+{
+	u8 storage_key, access_control;
+	unsigned long hva;
+	int r;
+
+	/* access key 0 matches any storage key -> allow */
+	if (access_key == 0)
+		return 0;
+	/*
+	 * caller needs to ensure that gfn is accessible, so we can
+	 * assume that this cannot fail
+	 */
+	hva = gfn_to_hva(vcpu->kvm, gpa_to_gfn(gpa));
+	down_read(&current->mm->mmap_sem);
+	r = get_guest_storage_key(current->mm, hva, &storage_key);
+	up_read(&current->mm->mmap_sem);
+	if (r)
+		return r;
+	access_control = FIELD_GET(_PAGE_ACC_BITS, storage_key);
+	/* access key matches storage key -> allow */
+	if (access_control == access_key)
+		return 0;
+	if (mode == GACC_FETCH || mode == GACC_IFETCH) {
+		/* it is a fetch and fetch protection is off -> allow */
+		if (!(storage_key & _PAGE_FP_BIT))
+			return 0;
+		if (fetch_prot_override_applicable(vcpu, mode, asce) &&
+		    fetch_prot_override_applies(ga, len))
+			return 0;
+	}
+	if (storage_prot_override_applicable(vcpu) &&
+	    storage_prot_override_applies(access_control))
+		return 0;
+	return PGM_PROTECTION;
+}
+
+/**
+ * guest_range_to_gpas() - Calculate guest physical addresses of page fragments
+ * covering a logical range
+ * @vcpu: virtual cpu
+ * @ga: guest address, start of range
+ * @ar: access register
+ * @gpas: output argument, may be NULL
+ * @len: length of range in bytes
+ * @asce: address-space-control element to use for translation
+ * @mode: access mode
+ * @access_key: access key to mach the range's storage keys against
+ *
+ * Translate a logical range to a series of guest absolute addresses,
+ * such that the concatenation of page fragments starting at each gpa make up
+ * the whole range.
+ * The translation is performed as if done by the cpu for the given @asce, @ar,
+ * @mode and state of the @vcpu.
+ * If the translation causes an exception, its program interruption code is
+ * returned and the &struct kvm_s390_pgm_info pgm member of @vcpu is modified
+ * such that a subsequent call to kvm_s390_inject_prog_vcpu() will inject
+ * a correct exception into the guest.
+ * The resulting gpas are stored into @gpas, unless it is NULL.
+ *
+ * Note: All fragments except the first one start at the beginning of a page.
+ *	 When deriving the boundaries of a fragment from a gpa, all but the last
+ *	 fragment end at the end of the page.
+ *
+ * Return:
+ * * 0		- success
+ * * <0		- translation could not be performed, for example if  guest
+ *		  memory could not be accessed
+ * * >0		- an access exception occurred. In this case the returned value
+ *		  is the program interruption code and the contents of pgm may
+ *		  be used to inject an exception into the guest.
+ */
+static int guest_range_to_gpas(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar,
+			       unsigned long *gpas, unsigned long len,
+			       const union asce asce, enum gacc_mode mode,
+			       u8 access_key)
 {
 	psw_t *psw = &vcpu->arch.sie_block->gpsw;
+	unsigned int offset = offset_in_page(ga);
+	unsigned int fragment_len;
 	int lap_enabled, rc = 0;
 	enum prot_type prot;
+	unsigned long gpa;
 
 	lap_enabled = low_address_protection_enabled(vcpu, asce);
-	while (nr_pages) {
+	while (min(PAGE_SIZE - offset, len) > 0) {
+		fragment_len = min(PAGE_SIZE - offset, len);
 		ga = kvm_s390_logical_to_effective(vcpu, ga);
 		if (mode == GACC_STORE && lap_enabled && is_low_address(ga))
 			return trans_exc(vcpu, PGM_PROTECTION, ga, ar, mode,
 					 PROT_TYPE_LA);
-		ga &= PAGE_MASK;
 		if (psw_bits(*psw).dat) {
-			rc = guest_translate(vcpu, ga, pages, asce, mode, &prot);
+			rc = guest_translate(vcpu, ga, &gpa, asce, mode, &prot);
 			if (rc < 0)
 				return rc;
 		} else {
-			*pages = kvm_s390_real_to_abs(vcpu, ga);
-			if (kvm_is_error_gpa(vcpu->kvm, *pages))
+			gpa = kvm_s390_real_to_abs(vcpu, ga);
+			if (kvm_is_error_gpa(vcpu->kvm, gpa))
 				rc = PGM_ADDRESSING;
 		}
 		if (rc)
 			return trans_exc(vcpu, rc, ga, ar, mode, prot);
-		ga += PAGE_SIZE;
-		pages++;
-		nr_pages--;
+		rc = vcpu_check_access_key(vcpu, access_key, mode, asce, gpa, ga,
+					   fragment_len);
+		if (rc)
+			return trans_exc(vcpu, rc, ga, ar, mode, PROT_TYPE_KEYC);
+		if (gpas)
+			*gpas++ = gpa;
+		offset = 0;
+		ga += fragment_len;
+		len -= fragment_len;
+	}
+	return 0;
+}
+
+static int access_guest_page(struct kvm *kvm, enum gacc_mode mode, gpa_t gpa,
+			     void *data, unsigned int len)
+{
+	const unsigned int offset = offset_in_page(gpa);
+	const gfn_t gfn = gpa_to_gfn(gpa);
+	int rc;
+
+	if (!gfn_to_memslot(kvm, gfn))
+		return PGM_ADDRESSING;
+	if (mode == GACC_STORE)
+		rc = kvm_write_guest_page(kvm, gfn, data, offset, len);
+	else
+		rc = kvm_read_guest_page(kvm, gfn, data, offset, len);
+	return rc;
+}
+
+static int
+access_guest_page_with_key(struct kvm *kvm, enum gacc_mode mode, gpa_t gpa,
+			   void *data, unsigned int len, u8 access_key)
+{
+	struct kvm_memory_slot *slot;
+	bool writable;
+	gfn_t gfn;
+	hva_t hva;
+	int rc;
+
+	gfn = gpa >> PAGE_SHIFT;
+	slot = gfn_to_memslot(kvm, gfn);
+	hva = gfn_to_hva_memslot_prot(slot, gfn, &writable);
+
+	if (kvm_is_error_hva(hva))
+		return PGM_ADDRESSING;
+	/*
+	 * Check if it's a ro memslot, even tho that can't occur (they're unsupported).
+	 * Don't try to actually handle that case.
+	 */
+	if (!writable && mode == GACC_STORE)
+		return -EOPNOTSUPP;
+	hva += offset_in_page(gpa);
+	if (mode == GACC_STORE)
+		rc = copy_to_user_key((void __user *)hva, data, len, access_key);
+	else
+		rc = copy_from_user_key(data, (void __user *)hva, len, access_key);
+	if (rc)
+		return PGM_PROTECTION;
+	if (mode == GACC_STORE)
+		mark_page_dirty(kvm, gfn);
+	return 0;
+}
+
+int access_guest_abs_with_key(struct kvm *kvm, gpa_t gpa, void *data,
+			      unsigned long len, enum gacc_mode mode, u8 access_key)
+{
+	int offset = offset_in_page(gpa);
+	int fragment_len;
+	int rc;
+
+	while (min(PAGE_SIZE - offset, len) > 0) {
+		fragment_len = min(PAGE_SIZE - offset, len);
+		rc = access_guest_page_with_key(kvm, mode, gpa, data, fragment_len, access_key);
+		if (rc)
+			return rc;
+		offset = 0;
+		len -= fragment_len;
+		data += fragment_len;
+		gpa += fragment_len;
 	}
 	return 0;
 }
 
-int access_guest(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, void *data,
-		 unsigned long len, enum gacc_mode mode)
+int access_guest_with_key(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar,
+			  void *data, unsigned long len, enum gacc_mode mode,
+			  u8 access_key)
 {
 	psw_t *psw = &vcpu->arch.sie_block->gpsw;
-	unsigned long _len, nr_pages, gpa, idx;
-	unsigned long pages_array[2];
-	unsigned long *pages;
+	unsigned long nr_pages, idx;
+	unsigned long gpa_array[2];
+	unsigned int fragment_len;
+	unsigned long *gpas;
+	enum prot_type prot;
 	int need_ipte_lock;
 	union asce asce;
+	bool try_storage_prot_override;
+	bool try_fetch_prot_override;
 	int rc;
 
 	if (!len)
@@ -845,55 +1068,87 @@
 	if (rc)
 		return rc;
 	nr_pages = (((ga & ~PAGE_MASK) + len - 1) >> PAGE_SHIFT) + 1;
-	pages = pages_array;
-	if (nr_pages > ARRAY_SIZE(pages_array))
-		pages = vmalloc(array_size(nr_pages, sizeof(unsigned long)));
-	if (!pages)
+	gpas = gpa_array;
+	if (nr_pages > ARRAY_SIZE(gpa_array))
+		gpas = vmalloc(array_size(nr_pages, sizeof(unsigned long)));
+	if (!gpas)
 		return -ENOMEM;
+	try_fetch_prot_override = fetch_prot_override_applicable(vcpu, mode, asce);
+	try_storage_prot_override = storage_prot_override_applicable(vcpu);
 	need_ipte_lock = psw_bits(*psw).dat && !asce.r;
 	if (need_ipte_lock)
 		ipte_lock(vcpu);
-	rc = guest_page_range(vcpu, ga, ar, pages, nr_pages, asce, mode);
-	for (idx = 0; idx < nr_pages && !rc; idx++) {
-		gpa = *(pages + idx) + (ga & ~PAGE_MASK);
-		_len = min(PAGE_SIZE - (gpa & ~PAGE_MASK), len);
-		if (mode == GACC_STORE)
-			rc = kvm_write_guest(vcpu->kvm, gpa, data, _len);
-		else
-			rc = kvm_read_guest(vcpu->kvm, gpa, data, _len);
-		len -= _len;
-		ga += _len;
-		data += _len;
+	/*
+	 * Since we do the access further down ultimately via a move instruction
+	 * that does key checking and returns an error in case of a protection
+	 * violation, we don't need to do the check during address translation.
+	 * Skip it by passing access key 0, which matches any storage key,
+	 * obviating the need for any further checks. As a result the check is
+	 * handled entirely in hardware on access, we only need to take care to
+	 * forego key protection checking if fetch protection override applies or
+	 * retry with the special key 9 in case of storage protection override.
+	 */
+	rc = guest_range_to_gpas(vcpu, ga, ar, gpas, len, asce, mode, 0);
+	if (rc)
+		goto out_unlock;
+	for (idx = 0; idx < nr_pages; idx++) {
+		fragment_len = min(PAGE_SIZE - offset_in_page(gpas[idx]), len);
+		if (try_fetch_prot_override && fetch_prot_override_applies(ga, fragment_len)) {
+			rc = access_guest_page(vcpu->kvm, mode, gpas[idx],
+					       data, fragment_len);
+		} else {
+			rc = access_guest_page_with_key(vcpu->kvm, mode, gpas[idx],
+							data, fragment_len, access_key);
+		}
+		if (rc == PGM_PROTECTION && try_storage_prot_override)
+			rc = access_guest_page_with_key(vcpu->kvm, mode, gpas[idx],
+							data, fragment_len, PAGE_SPO_ACC);
+		if (rc == PGM_PROTECTION)
+			prot = PROT_TYPE_KEYC;
+		if (rc)
+			break;
+		len -= fragment_len;
+		data += fragment_len;
+		ga = kvm_s390_logical_to_effective(vcpu, ga + fragment_len);
 	}
+	if (rc > 0)
+		rc = trans_exc(vcpu, rc, ga, ar, mode, prot);
+out_unlock:
 	if (need_ipte_lock)
 		ipte_unlock(vcpu);
-	if (nr_pages > ARRAY_SIZE(pages_array))
-		vfree(pages);
+	if (nr_pages > ARRAY_SIZE(gpa_array))
+		vfree(gpas);
 	return rc;
 }
 
 int access_guest_real(struct kvm_vcpu *vcpu, unsigned long gra,
 		      void *data, unsigned long len, enum gacc_mode mode)
 {
-	unsigned long _len, gpa;
+	unsigned int fragment_len;
+	unsigned long gpa;
 	int rc = 0;
 
 	while (len && !rc) {
 		gpa = kvm_s390_real_to_abs(vcpu, gra);
-		_len = min(PAGE_SIZE - (gpa & ~PAGE_MASK), len);
-		if (mode)
-			rc = write_guest_abs(vcpu, gpa, data, _len);
-		else
-			rc = read_guest_abs(vcpu, gpa, data, _len);
-		len -= _len;
-		gra += _len;
-		data += _len;
+		fragment_len = min(PAGE_SIZE - offset_in_page(gpa), len);
+		rc = access_guest_page(vcpu->kvm, mode, gpa, data, fragment_len);
+		len -= fragment_len;
+		gra += fragment_len;
+		data += fragment_len;
 	}
+	if (rc > 0)
+		vcpu->arch.pgm.code = rc;
 	return rc;
 }
 
 /**
- * guest_translate_address - translate guest logical into guest absolute address
+ * guest_translate_address_with_key - translate guest logical into guest absolute address
+ * @vcpu: virtual cpu
+ * @gva: Guest virtual address
+ * @ar: Access register
+ * @gpa: Guest physical address
+ * @mode: Translation access mode
+ * @access_key: access key to mach the storage key with
  *
  * Parameter semantics are the same as the ones from guest_translate.
  * The memory contents at the guest address are not changed.
@@ -901,11 +1156,10 @@
  * Note: The IPTE lock is not taken during this function, so the caller
  * has to take care of this.
  */
-int guest_translate_address(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar,
-			    unsigned long *gpa, enum gacc_mode mode)
+int guest_translate_address_with_key(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar,
+				     unsigned long *gpa, enum gacc_mode mode,
+				     u8 access_key)
 {
-	psw_t *psw = &vcpu->arch.sie_block->gpsw;
-	enum prot_type prot;
 	union asce asce;
 	int rc;
 
@@ -913,47 +1167,59 @@
 	rc = get_vcpu_asce(vcpu, &asce, gva, ar, mode);
 	if (rc)
 		return rc;
-	if (is_low_address(gva) && low_address_protection_enabled(vcpu, asce)) {
-		if (mode == GACC_STORE)
-			return trans_exc(vcpu, PGM_PROTECTION, gva, 0,
-					 mode, PROT_TYPE_LA);
-	}
-
-	if (psw_bits(*psw).dat && !asce.r) {	/* Use DAT? */
-		rc = guest_translate(vcpu, gva, gpa, asce, mode, &prot);
-		if (rc > 0)
-			return trans_exc(vcpu, rc, gva, 0, mode, prot);
-	} else {
-		*gpa = kvm_s390_real_to_abs(vcpu, gva);
-		if (kvm_is_error_gpa(vcpu->kvm, *gpa))
-			return trans_exc(vcpu, rc, gva, PGM_ADDRESSING, mode, 0);
-	}
-
-	return rc;
+	return guest_range_to_gpas(vcpu, gva, ar, gpa, 1, asce, mode,
+				   access_key);
 }
 
 /**
  * check_gva_range - test a range of guest virtual addresses for accessibility
+ * @vcpu: virtual cpu
+ * @gva: Guest virtual address
+ * @ar: Access register
+ * @length: Length of test range
+ * @mode: Translation access mode
+ * @access_key: access key to mach the storage keys with
  */
 int check_gva_range(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar,
-		    unsigned long length, enum gacc_mode mode)
+		    unsigned long length, enum gacc_mode mode, u8 access_key)
 {
-	unsigned long gpa;
-	unsigned long currlen;
+	union asce asce;
 	int rc = 0;
 
+	rc = get_vcpu_asce(vcpu, &asce, gva, ar, mode);
+	if (rc)
+		return rc;
 	ipte_lock(vcpu);
-	while (length > 0 && !rc) {
-		currlen = min(length, PAGE_SIZE - (gva % PAGE_SIZE));
-		rc = guest_translate_address(vcpu, gva, ar, &gpa, mode);
-		gva += currlen;
-		length -= currlen;
-	}
+	rc = guest_range_to_gpas(vcpu, gva, ar, NULL, length, asce, mode,
+				 access_key);
 	ipte_unlock(vcpu);
 
 	return rc;
 }
 
+/**
+ * check_gpa_range - test a range of guest physical addresses for accessibility
+ * @kvm: virtual machine instance
+ * @gpa: guest physical address
+ * @length: length of test range
+ * @mode: access mode to test, relevant for storage keys
+ * @access_key: access key to mach the storage keys with
+ */
+int check_gpa_range(struct kvm *kvm, unsigned long gpa, unsigned long length,
+		    enum gacc_mode mode, u8 access_key)
+{
+	unsigned int fragment_len;
+	int rc = 0;
+
+	while (length && !rc) {
+		fragment_len = min(PAGE_SIZE - offset_in_page(gpa), length);
+		rc = vm_check_access_key(kvm, access_key, mode, gpa);
+		length -= fragment_len;
+		gpa += fragment_len;
+	}
+	return rc;
+}
+
 /**
  * kvm_s390_check_low_addr_prot_real - check for low-address protection
  * @gra: Guest real address
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kvm/gaccess.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kvm/gaccess.h
@@ -18,17 +18,14 @@
 
 /**
  * kvm_s390_real_to_abs - convert guest real address to guest absolute address
- * @vcpu - guest virtual cpu
+ * @prefix - guest prefix
  * @gra - guest real address
  *
  * Returns the guest absolute address that corresponds to the passed guest real
- * address @gra of a virtual guest cpu by applying its prefix.
+ * address @gra of by applying the given prefix.
  */
-static inline unsigned long kvm_s390_real_to_abs(struct kvm_vcpu *vcpu,
-						 unsigned long gra)
+static inline unsigned long _kvm_s390_real_to_abs(u32 prefix, unsigned long gra)
 {
-	unsigned long prefix  = kvm_s390_get_prefix(vcpu);
-
 	if (gra < 2 * PAGE_SIZE)
 		gra += prefix;
 	else if (gra >= prefix && gra < prefix + 2 * PAGE_SIZE)
@@ -37,6 +34,43 @@
 }
 
 /**
+ * kvm_s390_real_to_abs - convert guest real address to guest absolute address
+ * @vcpu - guest virtual cpu
+ * @gra - guest real address
+ *
+ * Returns the guest absolute address that corresponds to the passed guest real
+ * address @gra of a virtual guest cpu by applying its prefix.
+ */
+static inline unsigned long kvm_s390_real_to_abs(struct kvm_vcpu *vcpu,
+						 unsigned long gra)
+{
+	return _kvm_s390_real_to_abs(kvm_s390_get_prefix(vcpu), gra);
+}
+
+/**
+ * _kvm_s390_logical_to_effective - convert guest logical to effective address
+ * @psw: psw of the guest
+ * @ga: guest logical address
+ *
+ * Convert a guest logical address to an effective address by applying the
+ * rules of the addressing mode defined by bits 31 and 32 of the given PSW
+ * (extendended/basic addressing mode).
+ *
+ * Depending on the addressing mode, the upper 40 bits (24 bit addressing
+ * mode), 33 bits (31 bit addressing mode) or no bits (64 bit addressing
+ * mode) of @ga will be zeroed and the remaining bits will be returned.
+ */
+static inline unsigned long _kvm_s390_logical_to_effective(psw_t *psw,
+							   unsigned long ga)
+{
+	if (psw_bits(*psw).eaba == PSW_BITS_AMODE_64BIT)
+		return ga;
+	if (psw_bits(*psw).eaba == PSW_BITS_AMODE_31BIT)
+		return ga & ((1UL << 31) - 1);
+	return ga & ((1UL << 24) - 1);
+}
+
+/**
  * kvm_s390_logical_to_effective - convert guest logical to effective address
  * @vcpu: guest virtual cpu
  * @ga: guest logical address
@@ -52,13 +86,7 @@
 static inline unsigned long kvm_s390_logical_to_effective(struct kvm_vcpu *vcpu,
 							  unsigned long ga)
 {
-	psw_t *psw = &vcpu->arch.sie_block->gpsw;
-
-	if (psw_bits(*psw).eaba == PSW_BITS_AMODE_64BIT)
-		return ga;
-	if (psw_bits(*psw).eaba == PSW_BITS_AMODE_31BIT)
-		return ga & ((1UL << 31) - 1);
-	return ga & ((1UL << 24) - 1);
+	return _kvm_s390_logical_to_effective(&vcpu->arch.sie_block->gpsw, ga);
 }
 
 /*
@@ -158,24 +186,34 @@
 	GACC_IFETCH,
 };
 
-int guest_translate_address(struct kvm_vcpu *vcpu, unsigned long gva,
-			    u8 ar, unsigned long *gpa, enum gacc_mode mode);
+int guest_translate_address_with_key(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar,
+				     unsigned long *gpa, enum gacc_mode mode,
+				     u8 access_key);
+
 int check_gva_range(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar,
-		    unsigned long length, enum gacc_mode mode);
+		    unsigned long length, enum gacc_mode mode, u8 access_key);
+
+int check_gpa_range(struct kvm *kvm, unsigned long gpa, unsigned long length,
+		    enum gacc_mode mode, u8 access_key);
 
-int access_guest(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, void *data,
-		 unsigned long len, enum gacc_mode mode);
+int access_guest_abs_with_key(struct kvm *kvm, gpa_t gpa, void *data,
+			      unsigned long len, enum gacc_mode mode, u8 access_key);
+
+int access_guest_with_key(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar,
+			  void *data, unsigned long len, enum gacc_mode mode,
+			  u8 access_key);
 
 int access_guest_real(struct kvm_vcpu *vcpu, unsigned long gra,
 		      void *data, unsigned long len, enum gacc_mode mode);
 
 /**
- * write_guest - copy data from kernel space to guest space
+ * write_guest_with_key - copy data from kernel space to guest space
  * @vcpu: virtual cpu
  * @ga: guest address
  * @ar: access register
  * @data: source address in kernel space
  * @len: number of bytes to copy
+ * @access_key: access key the storage key needs to match
  *
  * Copy @len bytes from @data (kernel space) to @ga (guest address).
  * In order to copy data to guest space the PSW of the vcpu is inspected:
@@ -186,8 +224,8 @@
  * The addressing mode of the PSW is also inspected, so that address wrap
  * around is taken into account for 24-, 31- and 64-bit addressing mode,
  * if the to be copied data crosses page boundaries in guest address space.
- * In addition also low address and DAT protection are inspected before
- * copying any data (key protection is currently not implemented).
+ * In addition low address, DAT and key protection checks are performed before
+ * copying any data.
  *
  * This function modifies the 'struct kvm_s390_pgm_info pgm' member of @vcpu.
  * In case of an access exception (e.g. protection exception) pgm will contain
@@ -215,10 +253,53 @@
  *	 if data has been changed in guest space in case of an exception.
  */
 static inline __must_check
+int write_guest_with_key(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar,
+			 void *data, unsigned long len, u8 access_key)
+{
+	return access_guest_with_key(vcpu, ga, ar, data, len, GACC_STORE,
+				     access_key);
+}
+
+/**
+ * write_guest - copy data from kernel space to guest space
+ * @vcpu: virtual cpu
+ * @ga: guest address
+ * @ar: access register
+ * @data: source address in kernel space
+ * @len: number of bytes to copy
+ *
+ * The behaviour of write_guest is identical to write_guest_with_key, except
+ * that the PSW access key is used instead of an explicit argument.
+ */
+static inline __must_check
 int write_guest(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, void *data,
 		unsigned long len)
 {
-	return access_guest(vcpu, ga, ar, data, len, GACC_STORE);
+	u8 access_key = psw_bits(vcpu->arch.sie_block->gpsw).key;
+
+	return write_guest_with_key(vcpu, ga, ar, data, len, access_key);
+}
+
+/**
+ * read_guest_with_key - copy data from guest space to kernel space
+ * @vcpu: virtual cpu
+ * @ga: guest address
+ * @ar: access register
+ * @data: destination address in kernel space
+ * @len: number of bytes to copy
+ * @access_key: access key the storage key needs to match
+ *
+ * Copy @len bytes from @ga (guest address) to @data (kernel space).
+ *
+ * The behaviour of read_guest_with_key is identical to write_guest_with_key,
+ * except that data will be copied from guest space to kernel space.
+ */
+static inline __must_check
+int read_guest_with_key(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar,
+			void *data, unsigned long len, u8 access_key)
+{
+	return access_guest_with_key(vcpu, ga, ar, data, len, GACC_FETCH,
+				     access_key);
 }
 
 /**
@@ -231,14 +312,16 @@
  *
  * Copy @len bytes from @ga (guest address) to @data (kernel space).
  *
- * The behaviour of read_guest is identical to write_guest, except that
- * data will be copied from guest space to kernel space.
+ * The behaviour of read_guest is identical to read_guest_with_key, except
+ * that the PSW access key is used instead of an explicit argument.
  */
 static inline __must_check
 int read_guest(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, void *data,
 	       unsigned long len)
 {
-	return access_guest(vcpu, ga, ar, data, len, GACC_FETCH);
+	u8 access_key = psw_bits(vcpu->arch.sie_block->gpsw).key;
+
+	return read_guest_with_key(vcpu, ga, ar, data, len, access_key);
 }
 
 /**
@@ -259,7 +342,10 @@
 int read_guest_instr(struct kvm_vcpu *vcpu, unsigned long ga, void *data,
 		     unsigned long len)
 {
-	return access_guest(vcpu, ga, 0, data, len, GACC_IFETCH);
+	u8 access_key = psw_bits(vcpu->arch.sie_block->gpsw).key;
+
+	return access_guest_with_key(vcpu, ga, 0, data, len, GACC_IFETCH,
+				     access_key);
 }
 
 /**
@@ -316,11 +402,12 @@
  * @len: number of bytes to copy
  *
  * Copy @len bytes from @data (kernel space) to @gra (guest real address).
- * It is up to the caller to ensure that the entire guest memory range is
- * valid memory before calling this function.
  * Guest low address and key protection are not checked.
  *
- * Returns zero on success or -EFAULT on error.
+ * Returns zero on success, -EFAULT when copying from @data failed, or
+ * PGM_ADRESSING in case @gra is outside a memslot. In this case, pgm check info
+ * is also stored to allow injecting into the guest (if applicable) using
+ * kvm_s390_inject_prog_cond().
  *
  * If an error occurs data may have been copied partially to guest memory.
  */
@@ -339,11 +426,12 @@
  * @len: number of bytes to copy
  *
  * Copy @len bytes from @gra (guest real address) to @data (kernel space).
- * It is up to the caller to ensure that the entire guest memory range is
- * valid memory before calling this function.
  * Guest key protection is not checked.
  *
- * Returns zero on success or -EFAULT on error.
+ * Returns zero on success, -EFAULT when copying to @data failed, or
+ * PGM_ADRESSING in case @gra is outside a memslot. In this case, pgm check info
+ * is also stored to allow injecting into the guest (if applicable) using
+ * kvm_s390_inject_prog_cond().
  *
  * If an error occurs data may have been copied partially to kernel space.
  */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kvm/intercept.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kvm/intercept.c
@@ -2,7 +2,7 @@
 /*
  * in-kernel handling for sie intercepts
  *
- * Copyright IBM Corp. 2008, 2014
+ * Copyright IBM Corp. 2008, 2020
  *
  *    Author(s): Carsten Otte <cotte@de.ibm.com>
  *               Christian Borntraeger <borntraeger@de.ibm.com>
@@ -16,6 +16,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/irq.h>
 #include <asm/sysinfo.h>
+#include <asm/uv.h>
 
 #include "kvm-s390.h"
 #include "gaccess.h"
@@ -79,6 +80,10 @@
 			return rc;
 	}
 
+	/*
+	 * no need to check the return value of vcpu_stop as it can only have
+	 * an error for protvirt, but protvirt means user cpu state
+	 */
 	if (!kvm_s390_user_cpu_state_ctrl(vcpu->kvm))
 		kvm_s390_vcpu_stop(vcpu);
 	return -EOPNOTSUPP;
@@ -231,6 +236,13 @@
 
 	vcpu->stat.exit_program_interruption++;
 
+	/*
+	 * Intercept 8 indicates a loop of specification exceptions
+	 * for protected guests.
+	 */
+	if (kvm_s390_pv_cpu_is_protected(vcpu))
+		return -EOPNOTSUPP;
+
 	if (guestdbg_enabled(vcpu) && per_event(vcpu)) {
 		rc = kvm_s390_handle_per_event(vcpu);
 		if (rc)
@@ -318,18 +330,18 @@
 
 	kvm_s390_get_regs_rre(vcpu, &reg1, &reg2);
 
-	/* Make sure that the source is paged-in */
-	rc = guest_translate_address(vcpu, vcpu->run->s.regs.gprs[reg2],
-				     reg2, &srcaddr, GACC_FETCH);
+	/* Ensure that the source is paged-in, no actual access -> no key checking */
+	rc = guest_translate_address_with_key(vcpu, vcpu->run->s.regs.gprs[reg2],
+					      reg2, &srcaddr, GACC_FETCH, 0);
 	if (rc)
 		return kvm_s390_inject_prog_cond(vcpu, rc);
 	rc = kvm_arch_fault_in_page(vcpu, srcaddr, 0);
 	if (rc != 0)
 		return rc;
 
-	/* Make sure that the destination is paged-in */
-	rc = guest_translate_address(vcpu, vcpu->run->s.regs.gprs[reg1],
-				     reg1, &dstaddr, GACC_STORE);
+	/* Ensure that the source is paged-in, no actual access -> no key checking */
+	rc = guest_translate_address_with_key(vcpu, vcpu->run->s.regs.gprs[reg1],
+					      reg1, &dstaddr, GACC_STORE, 0);
 	if (rc)
 		return kvm_s390_inject_prog_cond(vcpu, rc);
 	rc = kvm_arch_fault_in_page(vcpu, dstaddr, 1);
@@ -360,8 +372,8 @@
  */
 int handle_sthyi(struct kvm_vcpu *vcpu)
 {
-	int reg1, reg2, r = 0;
-	u64 code, addr, cc = 0, rc = 0;
+	int reg1, reg2, cc = 0, r = 0;
+	u64 code, addr, rc = 0;
 	struct sthyi_sctns *sctns = NULL;
 
 	if (!test_kvm_facility(vcpu->kvm, 74))
@@ -384,7 +396,7 @@
 		goto out;
 	}
 
-	if (addr & ~PAGE_MASK)
+	if (!kvm_s390_pv_cpu_is_protected(vcpu) && (addr & ~PAGE_MASK))
 		return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
 
 	sctns = (void *)get_zeroed_page(GFP_KERNEL);
@@ -392,13 +404,21 @@
 		return -ENOMEM;
 
 	cc = sthyi_fill(sctns, &rc);
-
+	if (cc < 0) {
+		free_page((unsigned long)sctns);
+		return cc;
+	}
 out:
 	if (!cc) {
-		r = write_guest(vcpu, addr, reg2, sctns, PAGE_SIZE);
-		if (r) {
-			free_page((unsigned long)sctns);
-			return kvm_s390_inject_prog_cond(vcpu, r);
+		if (kvm_s390_pv_cpu_is_protected(vcpu)) {
+			memcpy((void *)(sida_origin(vcpu->arch.sie_block)),
+			       sctns, PAGE_SIZE);
+		} else {
+			r = write_guest(vcpu, addr, reg2, sctns, PAGE_SIZE);
+			if (r) {
+				free_page((unsigned long)sctns);
+				return kvm_s390_inject_prog_cond(vcpu, r);
+			}
 		}
 	}
 
@@ -444,6 +464,97 @@
 	return kvm_s390_inject_program_int(vcpu, PGM_OPERATION);
 }
 
+static int handle_pv_spx(struct kvm_vcpu *vcpu)
+{
+	u32 pref = *(u32 *)vcpu->arch.sie_block->sidad;
+
+	kvm_s390_set_prefix(vcpu, pref);
+	trace_kvm_s390_handle_prefix(vcpu, 1, pref);
+	return 0;
+}
+
+static int handle_pv_sclp(struct kvm_vcpu *vcpu)
+{
+	struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
+
+	spin_lock(&fi->lock);
+	/*
+	 * 2 cases:
+	 * a: an sccb answering interrupt was already pending or in flight.
+	 *    As the sccb value is not known we can simply set some value to
+	 *    trigger delivery of a saved SCCB. UV will then use its saved
+	 *    copy of the SCCB value.
+	 * b: an error SCCB interrupt needs to be injected so we also inject
+	 *    a fake SCCB address. Firmware will use the proper one.
+	 * This makes sure, that both errors and real sccb returns will only
+	 * be delivered after a notification intercept (instruction has
+	 * finished) but not after others.
+	 */
+	fi->srv_signal.ext_params |= 0x43000;
+	set_bit(IRQ_PEND_EXT_SERVICE, &fi->pending_irqs);
+	clear_bit(IRQ_PEND_EXT_SERVICE, &fi->masked_irqs);
+	spin_unlock(&fi->lock);
+	return 0;
+}
+
+static int handle_pv_uvc(struct kvm_vcpu *vcpu)
+{
+	struct uv_cb_share *guest_uvcb = (void *)vcpu->arch.sie_block->sidad;
+	struct uv_cb_cts uvcb = {
+		.header.cmd	= UVC_CMD_UNPIN_PAGE_SHARED,
+		.header.len	= sizeof(uvcb),
+		.guest_handle	= kvm_s390_pv_get_handle(vcpu->kvm),
+		.gaddr		= guest_uvcb->paddr,
+	};
+	int rc;
+
+	if (guest_uvcb->header.cmd != UVC_CMD_REMOVE_SHARED_ACCESS) {
+		WARN_ONCE(1, "Unexpected notification intercept for UVC 0x%x\n",
+			  guest_uvcb->header.cmd);
+		return 0;
+	}
+	rc = gmap_make_secure(vcpu->arch.gmap, uvcb.gaddr, &uvcb);
+	/*
+	 * If the unpin did not succeed, the guest will exit again for the UVC
+	 * and we will retry the unpin.
+	 */
+	if (rc == -EINVAL)
+		return 0;
+	/*
+	 * If we got -EAGAIN here, we simply return it. It will eventually
+	 * get propagated all the way to userspace, which should then try
+	 * again.
+	 */
+	return rc;
+}
+
+static int handle_pv_notification(struct kvm_vcpu *vcpu)
+{
+	int ret;
+
+	if (vcpu->arch.sie_block->ipa == 0xb210)
+		return handle_pv_spx(vcpu);
+	if (vcpu->arch.sie_block->ipa == 0xb220)
+		return handle_pv_sclp(vcpu);
+	if (vcpu->arch.sie_block->ipa == 0xb9a4)
+		return handle_pv_uvc(vcpu);
+	if (vcpu->arch.sie_block->ipa >> 8 == 0xae) {
+		/*
+		 * Besides external call, other SIGP orders also cause a
+		 * 108 (pv notify) intercept. In contrast to external call,
+		 * these orders need to be emulated and hence the appropriate
+		 * place to handle them is in handle_instruction().
+		 * So first try kvm_s390_handle_sigp_pei() and if that isn't
+		 * successful, go on with handle_instruction().
+		 */
+		ret = kvm_s390_handle_sigp_pei(vcpu);
+		if (!ret)
+			return ret;
+	}
+
+	return handle_instruction(vcpu);
+}
+
 int kvm_handle_sie_intercept(struct kvm_vcpu *vcpu)
 {
 	int rc, per_rc = 0;
@@ -480,6 +591,28 @@
 	case ICPT_KSS:
 		rc = kvm_s390_skey_check_enable(vcpu);
 		break;
+	case ICPT_MCHKREQ:
+	case ICPT_INT_ENABLE:
+		/*
+		 * PSW bit 13 or a CR (0, 6, 14) changed and we might
+		 * now be able to deliver interrupts. The pre-run code
+		 * will take care of this.
+		 */
+		rc = 0;
+		break;
+	case ICPT_PV_INSTR:
+		rc = handle_instruction(vcpu);
+		break;
+	case ICPT_PV_NOTIFY:
+		rc = handle_pv_notification(vcpu);
+		break;
+	case ICPT_PV_PREF:
+		rc = 0;
+		gmap_convert_to_secure(vcpu->arch.gmap,
+				       kvm_s390_get_prefix(vcpu));
+		gmap_convert_to_secure(vcpu->arch.gmap,
+				       kvm_s390_get_prefix(vcpu) + PAGE_SIZE);
+		break;
 	default:
 		return -EOPNOTSUPP;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kvm/interrupt.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kvm/interrupt.c
@@ -2,7 +2,7 @@
 /*
  * handling kvm guest interrupts
  *
- * Copyright IBM Corp. 2008, 2015
+ * Copyright IBM Corp. 2008, 2020
  *
  *    Author(s): Carsten Otte <cotte@de.ibm.com>
  */
@@ -81,8 +81,9 @@
 		struct esca_block *sca = vcpu->kvm->arch.sca;
 		union esca_sigp_ctrl *sigp_ctrl =
 			&(sca->cpu[vcpu->vcpu_id].sigp_ctrl);
-		union esca_sigp_ctrl new_val = {0}, old_val = *sigp_ctrl;
+		union esca_sigp_ctrl new_val = {0}, old_val;
 
+		old_val = READ_ONCE(*sigp_ctrl);
 		new_val.scn = src_id;
 		new_val.c = 1;
 		old_val.c = 0;
@@ -93,8 +94,9 @@
 		struct bsca_block *sca = vcpu->kvm->arch.sca;
 		union bsca_sigp_ctrl *sigp_ctrl =
 			&(sca->cpu[vcpu->vcpu_id].sigp_ctrl);
-		union bsca_sigp_ctrl new_val = {0}, old_val = *sigp_ctrl;
+		union bsca_sigp_ctrl new_val = {0}, old_val;
 
+		old_val = READ_ONCE(*sigp_ctrl);
 		new_val.scn = src_id;
 		new_val.c = 1;
 		old_val.c = 0;
@@ -124,16 +126,18 @@
 		struct esca_block *sca = vcpu->kvm->arch.sca;
 		union esca_sigp_ctrl *sigp_ctrl =
 			&(sca->cpu[vcpu->vcpu_id].sigp_ctrl);
-		union esca_sigp_ctrl old = *sigp_ctrl;
+		union esca_sigp_ctrl old;
 
+		old = READ_ONCE(*sigp_ctrl);
 		expect = old.value;
 		rc = cmpxchg(&sigp_ctrl->value, old.value, 0);
 	} else {
 		struct bsca_block *sca = vcpu->kvm->arch.sca;
 		union bsca_sigp_ctrl *sigp_ctrl =
 			&(sca->cpu[vcpu->vcpu_id].sigp_ctrl);
-		union bsca_sigp_ctrl old = *sigp_ctrl;
+		union bsca_sigp_ctrl old;
 
+		old = READ_ONCE(*sigp_ctrl);
 		expect = old.value;
 		rc = cmpxchg(&sigp_ctrl->value, old.value, 0);
 	}
@@ -324,8 +328,11 @@
 
 static inline unsigned long pending_irqs_no_gisa(struct kvm_vcpu *vcpu)
 {
-	return vcpu->kvm->arch.float_int.pending_irqs |
-		vcpu->arch.local_int.pending_irqs;
+	unsigned long pending = vcpu->kvm->arch.float_int.pending_irqs |
+				vcpu->arch.local_int.pending_irqs;
+
+	pending &= ~vcpu->kvm->arch.float_int.masked_irqs;
+	return pending;
 }
 
 static inline unsigned long pending_irqs(struct kvm_vcpu *vcpu)
@@ -383,10 +390,18 @@
 		__clear_bit(IRQ_PEND_EXT_CLOCK_COMP, &active_mask);
 	if (!(vcpu->arch.sie_block->gcr[0] & CR0_CPU_TIMER_SUBMASK))
 		__clear_bit(IRQ_PEND_EXT_CPU_TIMER, &active_mask);
-	if (!(vcpu->arch.sie_block->gcr[0] & CR0_SERVICE_SIGNAL_SUBMASK))
+	if (!(vcpu->arch.sie_block->gcr[0] & CR0_SERVICE_SIGNAL_SUBMASK)) {
 		__clear_bit(IRQ_PEND_EXT_SERVICE, &active_mask);
+		__clear_bit(IRQ_PEND_EXT_SERVICE_EV, &active_mask);
+	}
 	if (psw_mchk_disabled(vcpu))
 		active_mask &= ~IRQ_PEND_MCHK_MASK;
+	/* PV guest cpus can have a single interruption injected at a time. */
+	if (kvm_s390_pv_cpu_is_protected(vcpu) &&
+	    vcpu->arch.sie_block->iictl != IICTL_CODE_NONE)
+		active_mask &= ~(IRQ_PEND_EXT_II_MASK |
+				 IRQ_PEND_IO_MASK |
+				 IRQ_PEND_MCHK_MASK);
 	/*
 	 * Check both floating and local interrupt's cr14 because
 	 * bit IRQ_PEND_MCHK_REP could be set in both cases.
@@ -408,13 +423,13 @@
 static void __set_cpu_idle(struct kvm_vcpu *vcpu)
 {
 	kvm_s390_set_cpuflags(vcpu, CPUSTAT_WAIT);
-	set_bit(vcpu->vcpu_id, vcpu->kvm->arch.idle_mask);
+	set_bit(kvm_vcpu_get_idx(vcpu), vcpu->kvm->arch.idle_mask);
 }
 
 static void __unset_cpu_idle(struct kvm_vcpu *vcpu)
 {
 	kvm_s390_clear_cpuflags(vcpu, CPUSTAT_WAIT);
-	clear_bit(vcpu->vcpu_id, vcpu->kvm->arch.idle_mask);
+	clear_bit(kvm_vcpu_get_idx(vcpu), vcpu->kvm->arch.idle_mask);
 }
 
 static void __reset_intercept_indicators(struct kvm_vcpu *vcpu)
@@ -479,19 +494,23 @@
 static int __must_check __deliver_cpu_timer(struct kvm_vcpu *vcpu)
 {
 	struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
-	int rc;
+	int rc = 0;
 
 	vcpu->stat.deliver_cputm++;
 	trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_INT_CPU_TIMER,
 					 0, 0);
-
-	rc  = put_guest_lc(vcpu, EXT_IRQ_CPU_TIMER,
-			   (u16 *)__LC_EXT_INT_CODE);
-	rc |= put_guest_lc(vcpu, 0, (u16 *)__LC_EXT_CPU_ADDR);
-	rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW,
-			     &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
-	rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW,
-			    &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
+	if (kvm_s390_pv_cpu_is_protected(vcpu)) {
+		vcpu->arch.sie_block->iictl = IICTL_CODE_EXT;
+		vcpu->arch.sie_block->eic = EXT_IRQ_CPU_TIMER;
+	} else {
+		rc  = put_guest_lc(vcpu, EXT_IRQ_CPU_TIMER,
+				   (u16 *)__LC_EXT_INT_CODE);
+		rc |= put_guest_lc(vcpu, 0, (u16 *)__LC_EXT_CPU_ADDR);
+		rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW,
+				     &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
+		rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW,
+				    &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
+	}
 	clear_bit(IRQ_PEND_EXT_CPU_TIMER, &li->pending_irqs);
 	return rc ? -EFAULT : 0;
 }
@@ -499,19 +518,23 @@
 static int __must_check __deliver_ckc(struct kvm_vcpu *vcpu)
 {
 	struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
-	int rc;
+	int rc = 0;
 
 	vcpu->stat.deliver_ckc++;
 	trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_INT_CLOCK_COMP,
 					 0, 0);
-
-	rc  = put_guest_lc(vcpu, EXT_IRQ_CLK_COMP,
-			   (u16 __user *)__LC_EXT_INT_CODE);
-	rc |= put_guest_lc(vcpu, 0, (u16 *)__LC_EXT_CPU_ADDR);
-	rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW,
-			     &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
-	rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW,
-			    &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
+	if (kvm_s390_pv_cpu_is_protected(vcpu)) {
+		vcpu->arch.sie_block->iictl = IICTL_CODE_EXT;
+		vcpu->arch.sie_block->eic = EXT_IRQ_CLK_COMP;
+	} else {
+		rc  = put_guest_lc(vcpu, EXT_IRQ_CLK_COMP,
+				   (u16 __user *)__LC_EXT_INT_CODE);
+		rc |= put_guest_lc(vcpu, 0, (u16 *)__LC_EXT_CPU_ADDR);
+		rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW,
+				     &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
+		rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW,
+				    &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
+	}
 	clear_bit(IRQ_PEND_EXT_CLOCK_COMP, &li->pending_irqs);
 	return rc ? -EFAULT : 0;
 }
@@ -553,6 +576,20 @@
 	union mci mci;
 	int rc;
 
+	/*
+	 * All other possible payload for a machine check (e.g. the register
+	 * contents in the save area) will be handled by the ultravisor, as
+	 * the hypervisor does not not have the needed information for
+	 * protected guests.
+	 */
+	if (kvm_s390_pv_cpu_is_protected(vcpu)) {
+		vcpu->arch.sie_block->iictl = IICTL_CODE_MCHK;
+		vcpu->arch.sie_block->mcic = mchk->mcic;
+		vcpu->arch.sie_block->faddr = mchk->failing_storage_address;
+		vcpu->arch.sie_block->edc = mchk->ext_damage_code;
+		return 0;
+	}
+
 	mci.val = mchk->mcic;
 	/* take care of lazy register loading */
 	save_fpu_regs();
@@ -696,17 +733,21 @@
 static int __must_check __deliver_restart(struct kvm_vcpu *vcpu)
 {
 	struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
-	int rc;
+	int rc = 0;
 
 	VCPU_EVENT(vcpu, 3, "%s", "deliver: cpu restart");
 	vcpu->stat.deliver_restart_signal++;
 	trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_RESTART, 0, 0);
 
-	rc  = write_guest_lc(vcpu,
-			     offsetof(struct lowcore, restart_old_psw),
-			     &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
-	rc |= read_guest_lc(vcpu, offsetof(struct lowcore, restart_psw),
-			    &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
+	if (kvm_s390_pv_cpu_is_protected(vcpu)) {
+		vcpu->arch.sie_block->iictl = IICTL_CODE_RESTART;
+	} else {
+		rc  = write_guest_lc(vcpu,
+				     offsetof(struct lowcore, restart_old_psw),
+				     &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
+		rc |= read_guest_lc(vcpu, offsetof(struct lowcore, restart_psw),
+				    &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
+	}
 	clear_bit(IRQ_PEND_RESTART, &li->pending_irqs);
 	return rc ? -EFAULT : 0;
 }
@@ -748,6 +789,12 @@
 	vcpu->stat.deliver_emergency_signal++;
 	trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_INT_EMERGENCY,
 					 cpu_addr, 0);
+	if (kvm_s390_pv_cpu_is_protected(vcpu)) {
+		vcpu->arch.sie_block->iictl = IICTL_CODE_EXT;
+		vcpu->arch.sie_block->eic = EXT_IRQ_EMERGENCY_SIG;
+		vcpu->arch.sie_block->extcpuaddr = cpu_addr;
+		return 0;
+	}
 
 	rc  = put_guest_lc(vcpu, EXT_IRQ_EMERGENCY_SIG,
 			   (u16 *)__LC_EXT_INT_CODE);
@@ -776,6 +823,12 @@
 	trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id,
 					 KVM_S390_INT_EXTERNAL_CALL,
 					 extcall.code, 0);
+	if (kvm_s390_pv_cpu_is_protected(vcpu)) {
+		vcpu->arch.sie_block->iictl = IICTL_CODE_EXT;
+		vcpu->arch.sie_block->eic = EXT_IRQ_EXTERNAL_CALL;
+		vcpu->arch.sie_block->extcpuaddr = extcall.code;
+		return 0;
+	}
 
 	rc  = put_guest_lc(vcpu, EXT_IRQ_EXTERNAL_CALL,
 			   (u16 *)__LC_EXT_INT_CODE);
@@ -787,6 +840,21 @@
 	return rc ? -EFAULT : 0;
 }
 
+static int __deliver_prog_pv(struct kvm_vcpu *vcpu, u16 code)
+{
+	switch (code) {
+	case PGM_SPECIFICATION:
+		vcpu->arch.sie_block->iictl = IICTL_CODE_SPECIFICATION;
+		break;
+	case PGM_OPERAND:
+		vcpu->arch.sie_block->iictl = IICTL_CODE_OPERAND;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
 static int __must_check __deliver_prog(struct kvm_vcpu *vcpu)
 {
 	struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
@@ -807,6 +875,10 @@
 	trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_PROGRAM_INT,
 					 pgm_info.code, 0);
 
+	/* PER is handled by the ultravisor */
+	if (kvm_s390_pv_cpu_is_protected(vcpu))
+		return __deliver_prog_pv(vcpu, pgm_info.code & ~PGM_PER);
+
 	switch (pgm_info.code & ~PGM_PER) {
 	case PGM_AFX_TRANSLATION:
 	case PGM_ASX_TRANSLATION:
@@ -902,20 +974,49 @@
 	return rc ? -EFAULT : 0;
 }
 
+#define SCCB_MASK 0xFFFFFFF8
+#define SCCB_EVENT_PENDING 0x3
+
+static int write_sclp(struct kvm_vcpu *vcpu, u32 parm)
+{
+	int rc;
+
+	if (kvm_s390_pv_cpu_get_handle(vcpu)) {
+		vcpu->arch.sie_block->iictl = IICTL_CODE_EXT;
+		vcpu->arch.sie_block->eic = EXT_IRQ_SERVICE_SIG;
+		vcpu->arch.sie_block->eiparams = parm;
+		return 0;
+	}
+
+	rc  = put_guest_lc(vcpu, EXT_IRQ_SERVICE_SIG, (u16 *)__LC_EXT_INT_CODE);
+	rc |= put_guest_lc(vcpu, 0, (u16 *)__LC_EXT_CPU_ADDR);
+	rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW,
+			     &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
+	rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW,
+			    &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
+	rc |= put_guest_lc(vcpu, parm,
+			   (u32 *)__LC_EXT_PARAMS);
+
+	return rc ? -EFAULT : 0;
+}
+
 static int __must_check __deliver_service(struct kvm_vcpu *vcpu)
 {
 	struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
 	struct kvm_s390_ext_info ext;
-	int rc = 0;
 
 	spin_lock(&fi->lock);
-	if (!(test_bit(IRQ_PEND_EXT_SERVICE, &fi->pending_irqs))) {
+	if (test_bit(IRQ_PEND_EXT_SERVICE, &fi->masked_irqs) ||
+	    !(test_bit(IRQ_PEND_EXT_SERVICE, &fi->pending_irqs))) {
 		spin_unlock(&fi->lock);
 		return 0;
 	}
 	ext = fi->srv_signal;
 	memset(&fi->srv_signal, 0, sizeof(ext));
 	clear_bit(IRQ_PEND_EXT_SERVICE, &fi->pending_irqs);
+	clear_bit(IRQ_PEND_EXT_SERVICE_EV, &fi->pending_irqs);
+	if (kvm_s390_pv_cpu_is_protected(vcpu))
+		set_bit(IRQ_PEND_EXT_SERVICE, &fi->masked_irqs);
 	spin_unlock(&fi->lock);
 
 	VCPU_EVENT(vcpu, 4, "deliver: sclp parameter 0x%x",
@@ -924,16 +1025,31 @@
 	trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_INT_SERVICE,
 					 ext.ext_params, 0);
 
-	rc  = put_guest_lc(vcpu, EXT_IRQ_SERVICE_SIG, (u16 *)__LC_EXT_INT_CODE);
-	rc |= put_guest_lc(vcpu, 0, (u16 *)__LC_EXT_CPU_ADDR);
-	rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW,
-			     &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
-	rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW,
-			    &vcpu->arch.sie_block->gpsw, sizeof(psw_t));
-	rc |= put_guest_lc(vcpu, ext.ext_params,
-			   (u32 *)__LC_EXT_PARAMS);
+	return write_sclp(vcpu, ext.ext_params);
+}
 
-	return rc ? -EFAULT : 0;
+static int __must_check __deliver_service_ev(struct kvm_vcpu *vcpu)
+{
+	struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
+	struct kvm_s390_ext_info ext;
+
+	spin_lock(&fi->lock);
+	if (!(test_bit(IRQ_PEND_EXT_SERVICE_EV, &fi->pending_irqs))) {
+		spin_unlock(&fi->lock);
+		return 0;
+	}
+	ext = fi->srv_signal;
+	/* only clear the event bit */
+	fi->srv_signal.ext_params &= ~SCCB_EVENT_PENDING;
+	clear_bit(IRQ_PEND_EXT_SERVICE_EV, &fi->pending_irqs);
+	spin_unlock(&fi->lock);
+
+	VCPU_EVENT(vcpu, 4, "%s", "deliver: sclp parameter event");
+	vcpu->stat.deliver_service_signal++;
+	trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_INT_SERVICE,
+					 ext.ext_params, 0);
+
+	return write_sclp(vcpu, SCCB_EVENT_PENDING);
 }
 
 static int __must_check __deliver_pfault_done(struct kvm_vcpu *vcpu)
@@ -1028,6 +1144,15 @@
 {
 	int rc;
 
+	if (kvm_s390_pv_cpu_is_protected(vcpu)) {
+		vcpu->arch.sie_block->iictl = IICTL_CODE_IO;
+		vcpu->arch.sie_block->subchannel_id = io->subchannel_id;
+		vcpu->arch.sie_block->subchannel_nr = io->subchannel_nr;
+		vcpu->arch.sie_block->io_int_parm = io->io_int_parm;
+		vcpu->arch.sie_block->io_int_word = io->io_int_word;
+		return 0;
+	}
+
 	rc  = put_guest_lc(vcpu, io->subchannel_id, (u16 *)__LC_SUBCHANNEL_ID);
 	rc |= put_guest_lc(vcpu, io->subchannel_nr, (u16 *)__LC_SUBCHANNEL_NR);
 	rc |= put_guest_lc(vcpu, io->io_int_parm, (u32 *)__LC_IO_INT_PARM);
@@ -1329,6 +1454,9 @@
 		case IRQ_PEND_EXT_SERVICE:
 			rc = __deliver_service(vcpu);
 			break;
+		case IRQ_PEND_EXT_SERVICE_EV:
+			rc = __deliver_service_ev(vcpu);
+			break;
 		case IRQ_PEND_PFAULT_DONE:
 			rc = __deliver_pfault_done(vcpu);
 			break;
@@ -1421,7 +1549,7 @@
 	if (kvm_get_vcpu_by_id(vcpu->kvm, src_id) == NULL)
 		return -EINVAL;
 
-	if (sclp.has_sigpif)
+	if (sclp.has_sigpif && !kvm_s390_pv_cpu_get_handle(vcpu))
 		return sca_inject_ext_call(vcpu, src_id);
 
 	if (test_and_set_bit(IRQ_PEND_EXT_EXTERNAL, &li->pending_irqs))
@@ -1682,9 +1810,6 @@
 	return inti;
 }
 
-#define SCCB_MASK 0xFFFFFFF8
-#define SCCB_EVENT_PENDING 0x3
-
 static int __inject_service(struct kvm *kvm,
 			     struct kvm_s390_interrupt_info *inti)
 {
@@ -1693,6 +1818,11 @@
 	kvm->stat.inject_service_signal++;
 	spin_lock(&fi->lock);
 	fi->srv_signal.ext_params |= inti->ext.ext_params & SCCB_EVENT_PENDING;
+
+	/* We always allow events, track them separately from the sccb ints */
+	if (fi->srv_signal.ext_params & SCCB_EVENT_PENDING)
+		set_bit(IRQ_PEND_EXT_SERVICE_EV, &fi->pending_irqs);
+
 	/*
 	 * Early versions of the QEMU s390 bios will inject several
 	 * service interrupts after another without handling a
@@ -1774,7 +1904,14 @@
 	kvm->stat.inject_io++;
 	isc = int_word_to_isc(inti->io.io_int_word);
 
-	if (gi->origin && inti->type & KVM_S390_INT_IO_AI_MASK) {
+	/*
+	 * Do not make use of gisa in protected mode. We do not use the lock
+	 * checking variant as this is just a performance optimization and we
+	 * do not hold the lock here. This is ok as the code will pick
+	 * interrupts from both "lists" for delivery.
+	 */
+	if (!kvm_s390_pv_get_handle(kvm) &&
+	    gi->origin && inti->type & KVM_S390_INT_IO_AI_MASK) {
 		VM_EVENT(kvm, 4, "%s isc %1u", "inject: I/O (AI/gisa)", isc);
 		gisa_set_ipm_gisc(gi->origin, isc);
 		kfree(inti);
@@ -1835,7 +1972,8 @@
 		break;
 	case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
 		if (!(type & KVM_S390_INT_IO_AI_MASK &&
-		      kvm->arch.gisa_int.origin))
+		      kvm->arch.gisa_int.origin) ||
+		      kvm_s390_pv_cpu_get_handle(dst_vcpu))
 			kvm_s390_set_cpuflags(dst_vcpu, CPUSTAT_IO_INT);
 		break;
 	default:
@@ -1982,6 +2120,13 @@
 	return test_bit(IRQ_PEND_SIGP_STOP, &li->pending_irqs);
 }
 
+int kvm_s390_is_restart_irq_pending(struct kvm_vcpu *vcpu)
+{
+	struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
+
+	return test_bit(IRQ_PEND_RESTART, &li->pending_irqs);
+}
+
 void kvm_s390_clear_stop_irq(struct kvm_vcpu *vcpu)
 {
 	struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
@@ -2081,6 +2226,10 @@
 	struct kvm_s390_float_interrupt *fi = &kvm->arch.float_int;
 	int i;
 
+	mutex_lock(&kvm->lock);
+	if (!kvm_s390_pv_is_protected(kvm))
+		fi->masked_irqs = 0;
+	mutex_unlock(&kvm->lock);
 	spin_lock(&fi->lock);
 	fi->pending_irqs = 0;
 	memset(&fi->srv_signal, 0, sizeof(fi->srv_signal));
@@ -2147,7 +2296,8 @@
 			n++;
 		}
 	}
-	if (test_bit(IRQ_PEND_EXT_SERVICE, &fi->pending_irqs)) {
+	if (test_bit(IRQ_PEND_EXT_SERVICE, &fi->pending_irqs) ||
+	    test_bit(IRQ_PEND_EXT_SERVICE_EV, &fi->pending_irqs)) {
 		if (n == max_irqs) {
 			/* signal userspace to try again */
 			ret = -ENOMEM;
@@ -2191,7 +2341,7 @@
 		return -EINVAL;
 
 	if (!test_kvm_facility(kvm, 72))
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 
 	mutex_lock(&fi->ais_lock);
 	ais.simm = fi->simm;
@@ -2328,9 +2478,6 @@
 	if (!adapter)
 		return -ENOMEM;
 
-	INIT_LIST_HEAD(&adapter->maps);
-	init_rwsem(&adapter->maps_lock);
-	atomic_set(&adapter->nr_maps, 0);
 	adapter->id = adapter_info.id;
 	adapter->isc = adapter_info.isc;
 	adapter->maskable = adapter_info.maskable;
@@ -2355,87 +2502,12 @@
 	return ret;
 }
 
-static int kvm_s390_adapter_map(struct kvm *kvm, unsigned int id, __u64 addr)
-{
-	struct s390_io_adapter *adapter = get_io_adapter(kvm, id);
-	struct s390_map_info *map;
-	int ret;
-
-	if (!adapter || !addr)
-		return -EINVAL;
-
-	map = kzalloc(sizeof(*map), GFP_KERNEL);
-	if (!map) {
-		ret = -ENOMEM;
-		goto out;
-	}
-	INIT_LIST_HEAD(&map->list);
-	map->guest_addr = addr;
-	map->addr = gmap_translate(kvm->arch.gmap, addr);
-	if (map->addr == -EFAULT) {
-		ret = -EFAULT;
-		goto out;
-	}
-	ret = get_user_pages_fast(map->addr, 1, FOLL_WRITE, &map->page);
-	if (ret < 0)
-		goto out;
-	BUG_ON(ret != 1);
-	down_write(&adapter->maps_lock);
-	if (atomic_inc_return(&adapter->nr_maps) < MAX_S390_ADAPTER_MAPS) {
-		list_add_tail(&map->list, &adapter->maps);
-		ret = 0;
-	} else {
-		put_page(map->page);
-		ret = -EINVAL;
-	}
-	up_write(&adapter->maps_lock);
-out:
-	if (ret)
-		kfree(map);
-	return ret;
-}
-
-static int kvm_s390_adapter_unmap(struct kvm *kvm, unsigned int id, __u64 addr)
-{
-	struct s390_io_adapter *adapter = get_io_adapter(kvm, id);
-	struct s390_map_info *map, *tmp;
-	int found = 0;
-
-	if (!adapter || !addr)
-		return -EINVAL;
-
-	down_write(&adapter->maps_lock);
-	list_for_each_entry_safe(map, tmp, &adapter->maps, list) {
-		if (map->guest_addr == addr) {
-			found = 1;
-			atomic_dec(&adapter->nr_maps);
-			list_del(&map->list);
-			put_page(map->page);
-			kfree(map);
-			break;
-		}
-	}
-	up_write(&adapter->maps_lock);
-
-	return found ? 0 : -EINVAL;
-}
-
 void kvm_s390_destroy_adapters(struct kvm *kvm)
 {
 	int i;
-	struct s390_map_info *map, *tmp;
 
-	for (i = 0; i < MAX_S390_IO_ADAPTERS; i++) {
-		if (!kvm->arch.adapters[i])
-			continue;
-		list_for_each_entry_safe(map, tmp,
-					 &kvm->arch.adapters[i]->maps, list) {
-			list_del(&map->list);
-			put_page(map->page);
-			kfree(map);
-		}
+	for (i = 0; i < MAX_S390_IO_ADAPTERS; i++)
 		kfree(kvm->arch.adapters[i]);
-	}
 }
 
 static int modify_io_adapter(struct kvm_device *dev,
@@ -2457,11 +2529,14 @@
 		if (ret > 0)
 			ret = 0;
 		break;
+	/*
+	 * The following operations are no longer needed and therefore no-ops.
+	 * The gpa to hva translation is done when an IRQ route is set up. The
+	 * set_irq code uses get_user_pages_remote() to do the actual write.
+	 */
 	case KVM_S390_IO_ADAPTER_MAP:
-		ret = kvm_s390_adapter_map(dev->kvm, req.id, req.addr);
-		break;
 	case KVM_S390_IO_ADAPTER_UNMAP:
-		ret = kvm_s390_adapter_unmap(dev->kvm, req.id, req.addr);
+		ret = 0;
 		break;
 	default:
 		ret = -EINVAL;
@@ -2500,7 +2575,7 @@
 	int ret = 0;
 
 	if (!test_kvm_facility(kvm, 72))
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 
 	if (copy_from_user(&req, (void __user *)attr->addr, sizeof(req)))
 		return -EFAULT;
@@ -2580,7 +2655,7 @@
 	struct kvm_s390_ais_all ais;
 
 	if (!test_kvm_facility(kvm, 72))
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 
 	if (copy_from_user(&ais, (void __user *)attr->addr, sizeof(ais)))
 		return -EFAULT;
@@ -2700,19 +2775,15 @@
 	return swap ? (bit ^ (BITS_PER_LONG - 1)) : bit;
 }
 
-static struct s390_map_info *get_map_info(struct s390_io_adapter *adapter,
-					  u64 addr)
+static struct page *get_map_page(struct kvm *kvm, u64 uaddr)
 {
-	struct s390_map_info *map;
+	struct page *page = NULL;
 
-	if (!adapter)
-		return NULL;
-
-	list_for_each_entry(map, &adapter->maps, list) {
-		if (map->guest_addr == addr)
-			return map;
-	}
-	return NULL;
+	down_read(&kvm->mm->mmap_sem);
+	get_user_pages_remote(NULL, kvm->mm, uaddr, 1, FOLL_WRITE,
+			      &page, NULL, NULL);
+	up_read(&kvm->mm->mmap_sem);
+	return page;
 }
 
 static int adapter_indicators_set(struct kvm *kvm,
@@ -2721,30 +2792,35 @@
 {
 	unsigned long bit;
 	int summary_set, idx;
-	struct s390_map_info *info;
+	struct page *ind_page, *summary_page;
 	void *map;
 
-	info = get_map_info(adapter, adapter_int->ind_addr);
-	if (!info)
+	ind_page = get_map_page(kvm, adapter_int->ind_addr);
+	if (!ind_page)
 		return -1;
-	map = page_address(info->page);
-	bit = get_ind_bit(info->addr, adapter_int->ind_offset, adapter->swap);
-	set_bit(bit, map);
-	idx = srcu_read_lock(&kvm->srcu);
-	mark_page_dirty(kvm, info->guest_addr >> PAGE_SHIFT);
-	set_page_dirty_lock(info->page);
-	info = get_map_info(adapter, adapter_int->summary_addr);
-	if (!info) {
-		srcu_read_unlock(&kvm->srcu, idx);
+	summary_page = get_map_page(kvm, adapter_int->summary_addr);
+	if (!summary_page) {
+		put_page(ind_page);
 		return -1;
 	}
-	map = page_address(info->page);
-	bit = get_ind_bit(info->addr, adapter_int->summary_offset,
-			  adapter->swap);
+
+	idx = srcu_read_lock(&kvm->srcu);
+	map = page_address(ind_page);
+	bit = get_ind_bit(adapter_int->ind_addr,
+			  adapter_int->ind_offset, adapter->swap);
+	set_bit(bit, map);
+	mark_page_dirty(kvm, adapter_int->ind_addr >> PAGE_SHIFT);
+	set_page_dirty_lock(ind_page);
+	map = page_address(summary_page);
+	bit = get_ind_bit(adapter_int->summary_addr,
+			  adapter_int->summary_offset, adapter->swap);
 	summary_set = test_and_set_bit(bit, map);
-	mark_page_dirty(kvm, info->guest_addr >> PAGE_SHIFT);
-	set_page_dirty_lock(info->page);
+	mark_page_dirty(kvm, adapter_int->summary_addr >> PAGE_SHIFT);
+	set_page_dirty_lock(summary_page);
 	srcu_read_unlock(&kvm->srcu, idx);
+
+	put_page(ind_page);
+	put_page(summary_page);
 	return summary_set ? 0 : 1;
 }
 
@@ -2766,9 +2842,7 @@
 	adapter = get_io_adapter(kvm, e->adapter.adapter_id);
 	if (!adapter)
 		return -1;
-	down_read(&adapter->maps_lock);
 	ret = adapter_indicators_set(kvm, adapter, &e->adapter);
-	up_read(&adapter->maps_lock);
 	if ((ret > 0) && !adapter->masked) {
 		ret = kvm_s390_inject_airq(kvm, adapter);
 		if (ret == 0)
@@ -2819,23 +2893,27 @@
 			  struct kvm_kernel_irq_routing_entry *e,
 			  const struct kvm_irq_routing_entry *ue)
 {
-	int ret;
+	u64 uaddr;
 
 	switch (ue->type) {
+	/* we store the userspace addresses instead of the guest addresses */
 	case KVM_IRQ_ROUTING_S390_ADAPTER:
 		e->set = set_adapter_int;
-		e->adapter.summary_addr = ue->u.adapter.summary_addr;
-		e->adapter.ind_addr = ue->u.adapter.ind_addr;
+		uaddr =  gmap_translate(kvm->arch.gmap, ue->u.adapter.summary_addr);
+		if (uaddr == -EFAULT)
+			return -EFAULT;
+		e->adapter.summary_addr = uaddr;
+		uaddr =  gmap_translate(kvm->arch.gmap, ue->u.adapter.ind_addr);
+		if (uaddr == -EFAULT)
+			return -EFAULT;
+		e->adapter.ind_addr = uaddr;
 		e->adapter.summary_offset = ue->u.adapter.summary_offset;
 		e->adapter.ind_offset = ue->u.adapter.ind_offset;
 		e->adapter.adapter_id = ue->u.adapter.adapter_id;
-		ret = 0;
-		break;
+		return 0;
 	default:
-		ret = -EINVAL;
+		return -EINVAL;
 	}
-
-	return ret;
 }
 
 int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, struct kvm *kvm,
@@ -2984,18 +3062,19 @@
 
 static void __airqs_kick_single_vcpu(struct kvm *kvm, u8 deliverable_mask)
 {
-	int vcpu_id, online_vcpus = atomic_read(&kvm->online_vcpus);
+	int vcpu_idx, online_vcpus = atomic_read(&kvm->online_vcpus);
 	struct kvm_s390_gisa_interrupt *gi = &kvm->arch.gisa_int;
 	struct kvm_vcpu *vcpu;
+	u8 vcpu_isc_mask;
 
-	for_each_set_bit(vcpu_id, kvm->arch.idle_mask, online_vcpus) {
-		vcpu = kvm_get_vcpu(kvm, vcpu_id);
+	for_each_set_bit(vcpu_idx, kvm->arch.idle_mask, online_vcpus) {
+		vcpu = kvm_get_vcpu(kvm, vcpu_idx);
 		if (psw_ioint_disabled(vcpu))
 			continue;
-		deliverable_mask &= (u8)(vcpu->arch.sie_block->gcr[6] >> 24);
-		if (deliverable_mask) {
+		vcpu_isc_mask = (u8)(vcpu->arch.sie_block->gcr[6] >> 24);
+		if (deliverable_mask & vcpu_isc_mask) {
 			/* lately kicked but not yet running */
-			if (test_and_set_bit(vcpu_id, gi->kicked_mask))
+			if (test_and_set_bit(vcpu_idx, gi->kicked_mask))
 				return;
 			kvm_s390_vcpu_wakeup(vcpu);
 			return;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kvm/kvm-s390.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kvm/kvm-s390.c
@@ -2,7 +2,7 @@
 /*
  * hosting IBM Z kernel virtual machines (s390x)
  *
- * Copyright IBM Corp. 2008, 2018
+ * Copyright IBM Corp. 2008, 2020
  *
  *    Author(s): Carsten Otte <cotte@de.ibm.com>
  *               Christian Borntraeger <borntraeger@de.ibm.com>
@@ -44,6 +44,7 @@
 #include <asm/cpacf.h>
 #include <asm/timex.h>
 #include <asm/ap.h>
+#include <asm/uv.h>
 #include "kvm-s390.h"
 #include "gaccess.h"
 
@@ -219,6 +220,7 @@
 static struct gmap_notifier gmap_notifier;
 static struct gmap_notifier vsie_gmap_notifier;
 debug_info_t *kvm_s390_dbf;
+debug_info_t *kvm_s390_dbf_uv;
 
 /* Section: not file related */
 int kvm_arch_hardware_enable(void)
@@ -232,8 +234,10 @@
 	return 0;
 }
 
+/* forward declarations */
 static void kvm_gmap_notifier(struct gmap *gmap, unsigned long start,
 			      unsigned long end);
+static int sca_switch_to_extended(struct kvm *kvm);
 
 static void kvm_clock_sync_scb(struct kvm_s390_sie_block *scb, u64 delta)
 {
@@ -318,31 +322,31 @@
 
 static inline int plo_test_bit(unsigned char nr)
 {
-	register unsigned long r0 asm("0") = (unsigned long) nr | 0x100;
+	unsigned long function = (unsigned long)nr | 0x100;
 	int cc;
 
 	asm volatile(
+		"	lgr	0,%[function]\n"
 		/* Parameter registers are ignored for "test bit" */
 		"	plo	0,0,0,0(0)\n"
 		"	ipm	%0\n"
 		"	srl	%0,28\n"
 		: "=d" (cc)
-		: "d" (r0)
-		: "cc");
+		: [function] "d" (function)
+		: "cc", "0");
 	return cc == 0;
 }
 
 static __always_inline void __insn32_query(unsigned int opcode, u8 *query)
 {
-	register unsigned long r0 asm("0") = 0;	/* query function */
-	register unsigned long r1 asm("1") = (unsigned long) query;
-
 	asm volatile(
-		/* Parameter regs are ignored */
+		"	lghi	0,0\n"
+		"	lgr	1,%[query]\n"
+		/* Parameter registers are ignored */
 		"	.insn	rrf,%[opc] << 16,2,4,6,0\n"
 		:
-		: "d" (r0), "a" (r1), [opc] "i" (opcode)
-		: "cc", "memory");
+		: [query] "d" ((unsigned long)query), [opc] "i" (opcode)
+		: "cc", "memory", "0", "1");
 }
 
 #define INSN_SORTL 0xb938
@@ -453,16 +457,19 @@
 
 int kvm_arch_init(void *opaque)
 {
-	int rc;
+	int rc = -ENOMEM;
 
 	kvm_s390_dbf = debug_register("kvm-trace", 32, 1, 7 * sizeof(long));
 	if (!kvm_s390_dbf)
 		return -ENOMEM;
 
-	if (debug_register_view(kvm_s390_dbf, &debug_sprintf_view)) {
-		rc = -ENOMEM;
-		goto out_debug_unreg;
-	}
+	kvm_s390_dbf_uv = debug_register("kvm-uv", 32, 1, 7 * sizeof(long));
+	if (!kvm_s390_dbf_uv)
+		goto out;
+
+	if (debug_register_view(kvm_s390_dbf, &debug_sprintf_view) ||
+	    debug_register_view(kvm_s390_dbf_uv, &debug_sprintf_view))
+		goto out;
 
 	kvm_s390_cpu_feat_init();
 
@@ -470,19 +477,17 @@
 	rc = kvm_register_device_ops(&kvm_flic_ops, KVM_DEV_TYPE_FLIC);
 	if (rc) {
 		pr_err("A FLIC registration call failed with rc=%d\n", rc);
-		goto out_debug_unreg;
+		goto out;
 	}
 
 	rc = kvm_s390_gib_init(GAL_ISC);
 	if (rc)
-		goto out_gib_destroy;
+		goto out;
 
 	return 0;
 
-out_gib_destroy:
-	kvm_s390_gib_destroy();
-out_debug_unreg:
-	debug_unregister(kvm_s390_dbf);
+out:
+	kvm_arch_exit();
 	return rc;
 }
 
@@ -490,6 +495,7 @@
 {
 	kvm_s390_gib_destroy();
 	debug_unregister(kvm_s390_dbf);
+	debug_unregister(kvm_s390_dbf_uv);
 }
 
 /* Section: device related */
@@ -532,6 +538,9 @@
 	case KVM_CAP_S390_CMMA_MIGRATION:
 	case KVM_CAP_S390_AIS:
 	case KVM_CAP_S390_AIS_MIGRATION:
+	case KVM_CAP_S390_VCPU_RESETS:
+	case KVM_CAP_S390_DIAG318:
+	case KVM_CAP_S390_MEM_OP_EXTENSION:
 		r = 1;
 		break;
 	case KVM_CAP_S390_HPAGE_1M:
@@ -566,6 +575,9 @@
 	case KVM_CAP_S390_BPB:
 		r = test_facility(82);
 		break;
+	case KVM_CAP_S390_PROTECTED:
+		r = is_prot_virt_host();
+		break;
 	default:
 		r = 0;
 	}
@@ -1084,6 +1096,8 @@
 	return 0;
 }
 
+static void __kvm_s390_set_tod_clock(struct kvm *kvm, const struct kvm_s390_vm_tod_clock *gtod);
+
 static int kvm_s390_set_tod_ext(struct kvm *kvm, struct kvm_device_attr *attr)
 {
 	struct kvm_s390_vm_tod_clock gtod;
@@ -1093,7 +1107,7 @@
 
 	if (!test_kvm_facility(kvm, 139) && gtod.epoch_idx)
 		return -EINVAL;
-	kvm_s390_set_tod_clock(kvm, &gtod);
+	__kvm_s390_set_tod_clock(kvm, &gtod);
 
 	VM_EVENT(kvm, 3, "SET: TOD extension: 0x%x, TOD base: 0x%llx",
 		gtod.epoch_idx, gtod.tod);
@@ -1124,7 +1138,7 @@
 			   sizeof(gtod.tod)))
 		return -EFAULT;
 
-	kvm_s390_set_tod_clock(kvm, &gtod);
+	__kvm_s390_set_tod_clock(kvm, &gtod);
 	VM_EVENT(kvm, 3, "SET: TOD base: 0x%llx", gtod.tod);
 	return 0;
 }
@@ -1136,6 +1150,16 @@
 	if (attr->flags)
 		return -EINVAL;
 
+	mutex_lock(&kvm->lock);
+	/*
+	 * For protected guests, the TOD is managed by the ultravisor, so trying
+	 * to change it will never bring the expected results.
+	 */
+	if (kvm_s390_pv_is_protected(kvm)) {
+		ret = -EOPNOTSUPP;
+		goto out_unlock;
+	}
+
 	switch (attr->attr) {
 	case KVM_S390_VM_TOD_EXT:
 		ret = kvm_s390_set_tod_ext(kvm, attr);
@@ -1150,6 +1174,9 @@
 		ret = -ENXIO;
 		break;
 	}
+
+out_unlock:
+	mutex_unlock(&kvm->lock);
 	return ret;
 }
 
@@ -1932,6 +1959,9 @@
 			start = slot + 1;
 	}
 
+	if (start >= slots->used_slots)
+		return slots->used_slots - 1;
+
 	if (gfn >= memslots[start].base_gfn &&
 	    gfn < memslots[start].base_gfn + memslots[start].npages) {
 		atomic_set(&slots->lru_slot, start);
@@ -1979,6 +2009,10 @@
 		ms = slots->memslots + slotidx;
 		ofs = 0;
 	}
+
+	if (cur_gfn < ms->base_gfn)
+		ofs = 0;
+
 	ofs = find_next_bit(kvm_second_dirty_bitmap(ms), ms->npages, ofs);
 	while ((slotidx > 0) && (ofs >= ms->npages)) {
 		slotidx--;
@@ -2160,6 +2194,271 @@
 	return r;
 }
 
+static int kvm_s390_cpus_from_pv(struct kvm *kvm, u16 *rcp, u16 *rrcp)
+{
+	struct kvm_vcpu *vcpu;
+	u16 rc, rrc;
+	int ret = 0;
+	int i;
+
+	/*
+	 * We ignore failures and try to destroy as many CPUs as possible.
+	 * At the same time we must not free the assigned resources when
+	 * this fails, as the ultravisor has still access to that memory.
+	 * So kvm_s390_pv_destroy_cpu can leave a "wanted" memory leak
+	 * behind.
+	 * We want to return the first failure rc and rrc, though.
+	 */
+	kvm_for_each_vcpu(i, vcpu, kvm) {
+		mutex_lock(&vcpu->mutex);
+		if (kvm_s390_pv_destroy_cpu(vcpu, &rc, &rrc) && !ret) {
+			*rcp = rc;
+			*rrcp = rrc;
+			ret = -EIO;
+		}
+		mutex_unlock(&vcpu->mutex);
+	}
+	return ret;
+}
+
+static int kvm_s390_cpus_to_pv(struct kvm *kvm, u16 *rc, u16 *rrc)
+{
+	int i, r = 0;
+	u16 dummy;
+
+	struct kvm_vcpu *vcpu;
+
+	kvm_for_each_vcpu(i, vcpu, kvm) {
+		mutex_lock(&vcpu->mutex);
+		r = kvm_s390_pv_create_cpu(vcpu, rc, rrc);
+		mutex_unlock(&vcpu->mutex);
+		if (r)
+			break;
+	}
+	if (r)
+		kvm_s390_cpus_from_pv(kvm, &dummy, &dummy);
+	return r;
+}
+
+static int kvm_s390_handle_pv(struct kvm *kvm, struct kvm_pv_cmd *cmd)
+{
+	int r = 0;
+	u16 dummy;
+	void __user *argp = (void __user *)cmd->data;
+
+	switch (cmd->cmd) {
+	case KVM_PV_ENABLE: {
+		r = -EINVAL;
+		if (kvm_s390_pv_is_protected(kvm))
+			break;
+
+		/*
+		 *  FMT 4 SIE needs esca. As we never switch back to bsca from
+		 *  esca, we need no cleanup in the error cases below
+		 */
+		r = sca_switch_to_extended(kvm);
+		if (r)
+			break;
+
+		down_write(&current->mm->mmap_sem);
+		r = gmap_mark_unmergeable();
+		up_write(&current->mm->mmap_sem);
+		if (r)
+			break;
+
+		r = kvm_s390_pv_init_vm(kvm, &cmd->rc, &cmd->rrc);
+		if (r)
+			break;
+
+		r = kvm_s390_cpus_to_pv(kvm, &cmd->rc, &cmd->rrc);
+		if (r)
+			kvm_s390_pv_deinit_vm(kvm, &dummy, &dummy);
+
+		/* we need to block service interrupts from now on */
+		set_bit(IRQ_PEND_EXT_SERVICE, &kvm->arch.float_int.masked_irqs);
+		break;
+	}
+	case KVM_PV_DISABLE: {
+		r = -EINVAL;
+		if (!kvm_s390_pv_is_protected(kvm))
+			break;
+
+		r = kvm_s390_cpus_from_pv(kvm, &cmd->rc, &cmd->rrc);
+		/*
+		 * If a CPU could not be destroyed, destroy VM will also fail.
+		 * There is no point in trying to destroy it. Instead return
+		 * the rc and rrc from the first CPU that failed destroying.
+		 */
+		if (r)
+			break;
+		r = kvm_s390_pv_deinit_vm(kvm, &cmd->rc, &cmd->rrc);
+
+		/* no need to block service interrupts any more */
+		clear_bit(IRQ_PEND_EXT_SERVICE, &kvm->arch.float_int.masked_irqs);
+		break;
+	}
+	case KVM_PV_SET_SEC_PARMS: {
+		struct kvm_s390_pv_sec_parm parms = {};
+		void *hdr;
+
+		r = -EINVAL;
+		if (!kvm_s390_pv_is_protected(kvm))
+			break;
+
+		r = -EFAULT;
+		if (copy_from_user(&parms, argp, sizeof(parms)))
+			break;
+
+		/* Currently restricted to 8KB */
+		r = -EINVAL;
+		if (parms.length > PAGE_SIZE * 2)
+			break;
+
+		r = -ENOMEM;
+		hdr = vmalloc(parms.length);
+		if (!hdr)
+			break;
+
+		r = -EFAULT;
+		if (!copy_from_user(hdr, (void __user *)parms.origin,
+				    parms.length))
+			r = kvm_s390_pv_set_sec_parms(kvm, hdr, parms.length,
+						      &cmd->rc, &cmd->rrc);
+
+		vfree(hdr);
+		break;
+	}
+	case KVM_PV_UNPACK: {
+		struct kvm_s390_pv_unp unp = {};
+
+		r = -EINVAL;
+		if (!kvm_s390_pv_is_protected(kvm))
+			break;
+
+		r = -EFAULT;
+		if (copy_from_user(&unp, argp, sizeof(unp)))
+			break;
+
+		r = kvm_s390_pv_unpack(kvm, unp.addr, unp.size, unp.tweak,
+				       &cmd->rc, &cmd->rrc);
+		break;
+	}
+	case KVM_PV_VERIFY: {
+		r = -EINVAL;
+		if (!kvm_s390_pv_is_protected(kvm))
+			break;
+
+		r = uv_cmd_nodata(kvm_s390_pv_get_handle(kvm),
+				  UVC_CMD_VERIFY_IMG, &cmd->rc, &cmd->rrc);
+		KVM_UV_EVENT(kvm, 3, "PROTVIRT VERIFY: rc %x rrc %x", cmd->rc,
+			     cmd->rrc);
+		break;
+	}
+	case KVM_PV_PREP_RESET: {
+		r = -EINVAL;
+		if (!kvm_s390_pv_is_protected(kvm))
+			break;
+
+		r = uv_cmd_nodata(kvm_s390_pv_get_handle(kvm),
+				  UVC_CMD_PREPARE_RESET, &cmd->rc, &cmd->rrc);
+		KVM_UV_EVENT(kvm, 3, "PROTVIRT PREP RESET: rc %x rrc %x",
+			     cmd->rc, cmd->rrc);
+		break;
+	}
+	case KVM_PV_UNSHARE_ALL: {
+		r = -EINVAL;
+		if (!kvm_s390_pv_is_protected(kvm))
+			break;
+
+		r = uv_cmd_nodata(kvm_s390_pv_get_handle(kvm),
+				  UVC_CMD_SET_UNSHARE_ALL, &cmd->rc, &cmd->rrc);
+		KVM_UV_EVENT(kvm, 3, "PROTVIRT UNSHARE: rc %x rrc %x",
+			     cmd->rc, cmd->rrc);
+		break;
+	}
+	default:
+		r = -ENOTTY;
+	}
+	return r;
+}
+
+static bool access_key_invalid(u8 access_key)
+{
+	return access_key > 0xf;
+}
+
+static int kvm_s390_vm_mem_op(struct kvm *kvm, struct kvm_s390_mem_op *mop)
+{
+	void __user *uaddr = (void __user *)mop->buf;
+	u64 supported_flags;
+	void *tmpbuf = NULL;
+	int r, srcu_idx;
+
+	supported_flags = KVM_S390_MEMOP_F_SKEY_PROTECTION
+			  | KVM_S390_MEMOP_F_CHECK_ONLY;
+	if (mop->flags & ~supported_flags || !mop->size)
+		return -EINVAL;
+	if (mop->size > MEM_OP_MAX_SIZE)
+		return -E2BIG;
+	if (kvm_s390_pv_is_protected(kvm))
+		return -EINVAL;
+	if (mop->flags & KVM_S390_MEMOP_F_SKEY_PROTECTION) {
+		if (access_key_invalid(mop->key))
+			return -EINVAL;
+	} else {
+		mop->key = 0;
+	}
+	if (!(mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY)) {
+		tmpbuf = vmalloc(mop->size);
+		if (!tmpbuf)
+			return -ENOMEM;
+	}
+
+	srcu_idx = srcu_read_lock(&kvm->srcu);
+
+	if (kvm_is_error_gpa(kvm, mop->gaddr)) {
+		r = PGM_ADDRESSING;
+		goto out_unlock;
+	}
+
+	switch (mop->op) {
+	case KVM_S390_MEMOP_ABSOLUTE_READ: {
+		if (mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY) {
+			r = check_gpa_range(kvm, mop->gaddr, mop->size, GACC_FETCH, mop->key);
+		} else {
+			r = access_guest_abs_with_key(kvm, mop->gaddr, tmpbuf,
+						      mop->size, GACC_FETCH, mop->key);
+			if (r == 0) {
+				if (copy_to_user(uaddr, tmpbuf, mop->size))
+					r = -EFAULT;
+			}
+		}
+		break;
+	}
+	case KVM_S390_MEMOP_ABSOLUTE_WRITE: {
+		if (mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY) {
+			r = check_gpa_range(kvm, mop->gaddr, mop->size, GACC_STORE, mop->key);
+		} else {
+			if (copy_from_user(tmpbuf, uaddr, mop->size)) {
+				r = -EFAULT;
+				break;
+			}
+			r = access_guest_abs_with_key(kvm, mop->gaddr, tmpbuf,
+						      mop->size, GACC_STORE, mop->key);
+		}
+		break;
+	}
+	default:
+		r = -EINVAL;
+	}
+
+out_unlock:
+	srcu_read_unlock(&kvm->srcu, srcu_idx);
+
+	vfree(tmpbuf);
+	return r;
+}
+
 long kvm_arch_vm_ioctl(struct file *filp,
 		       unsigned int ioctl, unsigned long arg)
 {
@@ -2257,6 +2556,42 @@
 		mutex_unlock(&kvm->slots_lock);
 		break;
 	}
+	case KVM_S390_PV_COMMAND: {
+		struct kvm_pv_cmd args;
+
+		/* protvirt means user cpu state */
+		kvm_s390_set_user_cpu_state_ctrl(kvm);
+		r = 0;
+		if (!is_prot_virt_host()) {
+			r = -EINVAL;
+			break;
+		}
+		if (copy_from_user(&args, argp, sizeof(args))) {
+			r = -EFAULT;
+			break;
+		}
+		if (args.flags) {
+			r = -EINVAL;
+			break;
+		}
+		mutex_lock(&kvm->lock);
+		r = kvm_s390_handle_pv(kvm, &args);
+		mutex_unlock(&kvm->lock);
+		if (copy_to_user(argp, &args, sizeof(args))) {
+			r = -EFAULT;
+			break;
+		}
+		break;
+	}
+	case KVM_S390_MEM_OP: {
+		struct kvm_s390_mem_op mem_op;
+
+		if (copy_from_user(&mem_op, argp, sizeof(mem_op)) == 0)
+			r = kvm_s390_vm_mem_op(kvm, &mem_op);
+		else
+			r = -EFAULT;
+		break;
+	}
 	default:
 		r = -ENOTTY;
 	}
@@ -2520,6 +2855,8 @@
 
 void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
 {
+	u16 rc, rrc;
+
 	VCPU_EVENT(vcpu, 3, "%s", "free cpu");
 	trace_kvm_s390_destroy_vcpu(vcpu->vcpu_id);
 	kvm_s390_clear_local_irqs(vcpu);
@@ -2532,6 +2869,9 @@
 
 	if (vcpu->kvm->arch.use_cmma)
 		kvm_s390_vcpu_unsetup_cmma(vcpu);
+	/* We can not hold the vcpu mutex here, we are already dying */
+	if (kvm_s390_pv_cpu_get_handle(vcpu))
+		kvm_s390_pv_destroy_cpu(vcpu, &rc, &rrc);
 	free_page((unsigned long)(vcpu->arch.sie_block));
 
 	kvm_vcpu_uninit(vcpu);
@@ -2556,10 +2896,20 @@
 
 void kvm_arch_destroy_vm(struct kvm *kvm)
 {
+	u16 rc, rrc;
+
 	kvm_free_vcpus(kvm);
 	sca_dispose(kvm);
-	debug_unregister(kvm->arch.dbf);
 	kvm_s390_gisa_destroy(kvm);
+	/*
+	 * We are already at the end of life and kvm->lock is not taken.
+	 * This is ok as the file descriptor is closed by now and nobody
+	 * can mess with the pv state. To avoid lockdep_assert_held from
+	 * complaining we do not use kvm_s390_pv_is_protected.
+	 */
+	if (kvm_s390_pv_get_handle(kvm))
+		kvm_s390_pv_deinit_vm(kvm, &rc, &rrc);
+	debug_unregister(kvm->arch.dbf);
 	free_page((unsigned long)kvm->arch.sie_page2);
 	if (!kvm_is_ucontrol(kvm))
 		gmap_remove(kvm->arch.gmap);
@@ -2655,6 +3005,9 @@
 	unsigned int vcpu_idx;
 	u32 scaol, scaoh;
 
+	if (kvm->arch.use_esca)
+		return 0;
+
 	new_sca = alloc_pages_exact(sizeof(*new_sca), GFP_KERNEL|__GFP_ZERO);
 	if (!new_sca)
 		return -ENOMEM;
@@ -2715,7 +3068,8 @@
 				    KVM_SYNC_ACRS |
 				    KVM_SYNC_CRS |
 				    KVM_SYNC_ARCH0 |
-				    KVM_SYNC_PFAULT;
+				    KVM_SYNC_PFAULT |
+				    KVM_SYNC_DIAG318;
 	kvm_s390_set_prefix(vcpu, 0);
 	if (test_kvm_facility(vcpu->kvm, 64))
 		vcpu->run->kvm_valid_regs |= KVM_SYNC_RICCB;
@@ -2847,35 +3201,6 @@
 
 }
 
-static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
-{
-	/* this equals initial cpu reset in pop, but we don't switch to ESA */
-	vcpu->arch.sie_block->gpsw.mask = 0UL;
-	vcpu->arch.sie_block->gpsw.addr = 0UL;
-	kvm_s390_set_prefix(vcpu, 0);
-	kvm_s390_set_cpu_timer(vcpu, 0);
-	vcpu->arch.sie_block->ckc       = 0UL;
-	vcpu->arch.sie_block->todpr     = 0;
-	memset(vcpu->arch.sie_block->gcr, 0, 16 * sizeof(__u64));
-	vcpu->arch.sie_block->gcr[0]  = CR0_UNUSED_56 |
-					CR0_INTERRUPT_KEY_SUBMASK |
-					CR0_MEASUREMENT_ALERT_SUBMASK;
-	vcpu->arch.sie_block->gcr[14] = CR14_UNUSED_32 |
-					CR14_UNUSED_33 |
-					CR14_EXTERNAL_DAMAGE_SUBMASK;
-	/* make sure the new fpc will be lazily loaded */
-	save_fpu_regs();
-	current->thread.fpu.fpc = 0;
-	vcpu->arch.sie_block->gbea = 1;
-	vcpu->arch.sie_block->pp = 0;
-	vcpu->arch.sie_block->fpf &= ~FPF_BPBC;
-	vcpu->arch.pfault_token = KVM_S390_PFAULT_TOKEN_INVALID;
-	kvm_clear_async_pf_completion_queue(vcpu);
-	if (!kvm_s390_user_cpu_state_ctrl(vcpu->kvm))
-		kvm_s390_vcpu_stop(vcpu);
-	kvm_s390_clear_local_irqs(vcpu);
-}
-
 void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
 {
 	mutex_lock(&vcpu->kvm->lock);
@@ -2968,6 +3293,7 @@
 int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 {
 	int rc = 0;
+	u16 uvrc, uvrrc;
 
 	atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH |
 						    CPUSTAT_SM |
@@ -3035,6 +3361,14 @@
 
 	kvm_s390_vcpu_crypto_setup(vcpu);
 
+	mutex_lock(&vcpu->kvm->lock);
+	if (kvm_s390_pv_is_protected(vcpu->kvm)) {
+		rc = kvm_s390_pv_create_cpu(vcpu, &uvrc, &uvrrc);
+		if (rc)
+			kvm_s390_vcpu_unsetup_cmma(vcpu);
+	}
+	mutex_unlock(&vcpu->kvm->lock);
+
 	return rc;
 }
 
@@ -3091,6 +3425,7 @@
 
 int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
 {
+	clear_bit(vcpu->vcpu_idx, vcpu->kvm->arch.gisa_int.kicked_mask);
 	return kvm_s390_vcpu_has_irq(vcpu, 0);
 }
 
@@ -3290,10 +3625,60 @@
 	return r;
 }
 
-static int kvm_arch_vcpu_ioctl_initial_reset(struct kvm_vcpu *vcpu)
+static void kvm_arch_vcpu_ioctl_normal_reset(struct kvm_vcpu *vcpu)
 {
-	kvm_s390_vcpu_initial_reset(vcpu);
-	return 0;
+	vcpu->arch.sie_block->gpsw.mask &= ~PSW_MASK_RI;
+	vcpu->arch.pfault_token = KVM_S390_PFAULT_TOKEN_INVALID;
+	memset(vcpu->run->s.regs.riccb, 0, sizeof(vcpu->run->s.regs.riccb));
+
+	kvm_clear_async_pf_completion_queue(vcpu);
+	if (!kvm_s390_user_cpu_state_ctrl(vcpu->kvm))
+		kvm_s390_vcpu_stop(vcpu);
+	kvm_s390_clear_local_irqs(vcpu);
+}
+
+static void kvm_arch_vcpu_ioctl_initial_reset(struct kvm_vcpu *vcpu)
+{
+	/* Initial reset is a superset of the normal reset */
+	kvm_arch_vcpu_ioctl_normal_reset(vcpu);
+
+	/* this equals initial cpu reset in pop, but we don't switch to ESA */
+	vcpu->arch.sie_block->gpsw.mask = 0;
+	vcpu->arch.sie_block->gpsw.addr = 0;
+	kvm_s390_set_prefix(vcpu, 0);
+	kvm_s390_set_cpu_timer(vcpu, 0);
+	vcpu->arch.sie_block->ckc = 0;
+	memset(vcpu->arch.sie_block->gcr, 0, sizeof(vcpu->arch.sie_block->gcr));
+	vcpu->arch.sie_block->gcr[0] = CR0_INITIAL_MASK;
+	vcpu->arch.sie_block->gcr[14] = CR14_INITIAL_MASK;
+	vcpu->run->s.regs.fpc = 0;
+	/*
+	 * Do not reset these registers in the protected case, as some of
+	 * them are overlayed and they are not accessible in this case
+	 * anyway.
+	 */
+	if (!kvm_s390_pv_cpu_is_protected(vcpu)) {
+		vcpu->arch.sie_block->gbea = 1;
+		vcpu->arch.sie_block->pp = 0;
+		vcpu->arch.sie_block->fpf &= ~FPF_BPBC;
+		vcpu->arch.sie_block->todpr = 0;
+	}
+}
+
+static void kvm_arch_vcpu_ioctl_clear_reset(struct kvm_vcpu *vcpu)
+{
+	struct kvm_sync_regs *regs = &vcpu->run->s.regs;
+
+	/* Clear reset is a superset of the initial reset */
+	kvm_arch_vcpu_ioctl_initial_reset(vcpu);
+
+	memset(&regs->gprs, 0, sizeof(regs->gprs));
+	memset(&regs->vrs, 0, sizeof(regs->vrs));
+	memset(&regs->acrs, 0, sizeof(regs->acrs));
+	memset(&regs->gscb, 0, sizeof(regs->gscb));
+
+	regs->etoken = 0;
+	regs->etoken_extension = 0;
 }
 
 int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
@@ -3342,10 +3727,6 @@
 
 	vcpu_load(vcpu);
 
-	if (test_fp_ctl(fpu->fpc)) {
-		ret = -EINVAL;
-		goto out;
-	}
 	vcpu->run->s.regs.fpc = fpu->fpc;
 	if (MACHINE_HAS_VX)
 		convert_fp_to_vx((__vector128 *) vcpu->run->s.regs.vrs,
@@ -3353,7 +3734,6 @@
 	else
 		memcpy(vcpu->run->s.regs.fprs, &fpu->fprs, sizeof(fpu->fprs));
 
-out:
 	vcpu_put(vcpu);
 	return ret;
 }
@@ -3463,16 +3843,22 @@
 	vcpu_load(vcpu);
 
 	/* user space knows about this interface - let it control the state */
-	vcpu->kvm->arch.user_cpu_state_ctrl = 1;
+	kvm_s390_set_user_cpu_state_ctrl(vcpu->kvm);
 
 	switch (mp_state->mp_state) {
 	case KVM_MP_STATE_STOPPED:
-		kvm_s390_vcpu_stop(vcpu);
+		rc = kvm_s390_vcpu_stop(vcpu);
 		break;
 	case KVM_MP_STATE_OPERATING:
-		kvm_s390_vcpu_start(vcpu);
+		rc = kvm_s390_vcpu_start(vcpu);
 		break;
 	case KVM_MP_STATE_LOAD:
+		if (!kvm_s390_pv_cpu_is_protected(vcpu)) {
+			rc = -ENXIO;
+			break;
+		}
+		rc = kvm_s390_pv_set_cpu_state(vcpu, PV_CPU_STATE_OPR_LOAD);
+		break;
 	case KVM_MP_STATE_CHECK_STOP:
 		/* fall through - CHECK_STOP and LOAD are not supported yet */
 	default:
@@ -3568,14 +3954,12 @@
 	return 0;
 }
 
-void kvm_s390_set_tod_clock(struct kvm *kvm,
-			    const struct kvm_s390_vm_tod_clock *gtod)
+static void __kvm_s390_set_tod_clock(struct kvm *kvm, const struct kvm_s390_vm_tod_clock *gtod)
 {
 	struct kvm_vcpu *vcpu;
 	struct kvm_s390_tod_clock_ext htod;
 	int i;
 
-	mutex_lock(&kvm->lock);
 	preempt_disable();
 
 	get_tod_clock_ext((char *)&htod);
@@ -3596,7 +3980,15 @@
 
 	kvm_s390_vcpu_unblock_all(kvm);
 	preempt_enable();
+}
+
+int kvm_s390_try_set_tod_clock(struct kvm *kvm, const struct kvm_s390_vm_tod_clock *gtod)
+{
+	if (!mutex_trylock(&kvm->lock))
+		return 0;
+	__kvm_s390_set_tod_clock(kvm, gtod);
 	mutex_unlock(&kvm->lock);
+	return 1;
 }
 
 /**
@@ -3725,7 +4117,7 @@
 		kvm_s390_patch_guest_per_regs(vcpu);
 	}
 
-	clear_bit(vcpu->vcpu_id, vcpu->kvm->arch.gisa_int.kicked_mask);
+	clear_bit(kvm_vcpu_get_idx(vcpu), vcpu->kvm->arch.gisa_int.kicked_mask);
 
 	vcpu->arch.sie_block->icptcode = 0;
 	cpuflags = atomic_read(&vcpu->arch.sie_block->cpuflags);
@@ -3824,9 +4216,11 @@
 	return vcpu_post_run_fault_in_sie(vcpu);
 }
 
+#define PSW_INT_MASK (PSW_MASK_EXT | PSW_MASK_IO | PSW_MASK_MCHECK)
 static int __vcpu_run(struct kvm_vcpu *vcpu)
 {
 	int rc, exit_reason;
+	struct sie_page *sie_page = (struct sie_page *)vcpu->arch.sie_block;
 
 	/*
 	 * We try to hold kvm->srcu during most of vcpu_run (except when run-
@@ -3848,8 +4242,28 @@
 		guest_enter_irqoff();
 		__disable_cpu_timer_accounting(vcpu);
 		local_irq_enable();
+		if (kvm_s390_pv_cpu_is_protected(vcpu)) {
+			memcpy(sie_page->pv_grregs,
+			       vcpu->run->s.regs.gprs,
+			       sizeof(sie_page->pv_grregs));
+		}
 		exit_reason = sie64a(vcpu->arch.sie_block,
 				     vcpu->run->s.regs.gprs);
+		if (kvm_s390_pv_cpu_is_protected(vcpu)) {
+			memcpy(vcpu->run->s.regs.gprs,
+			       sie_page->pv_grregs,
+			       sizeof(sie_page->pv_grregs));
+			/*
+			 * We're not allowed to inject interrupts on intercepts
+			 * that leave the guest state in an "in-between" state
+			 * where the next SIE entry will do a continuation.
+			 * Fence interrupts in our "internal" PSW.
+			 */
+			if (vcpu->arch.sie_block->icptcode == ICPT_PV_INSTR ||
+			    vcpu->arch.sie_block->icptcode == ICPT_PV_PREF) {
+				vcpu->arch.sie_block->gpsw.mask &= ~PSW_INT_MASK;
+			}
+		}
 		local_irq_disable();
 		__enable_cpu_timer_accounting(vcpu);
 		guest_exit_irqoff();
@@ -3863,7 +4277,7 @@
 	return rc;
 }
 
-static void sync_regs(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+static void sync_regs_fmt2(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
 	struct runtime_instr_cb *riccb;
 	struct gs_cb *gscb;
@@ -3872,16 +4286,7 @@
 	gscb = (struct gs_cb *) &kvm_run->s.regs.gscb;
 	vcpu->arch.sie_block->gpsw.mask = kvm_run->psw_mask;
 	vcpu->arch.sie_block->gpsw.addr = kvm_run->psw_addr;
-	if (kvm_run->kvm_dirty_regs & KVM_SYNC_PREFIX)
-		kvm_s390_set_prefix(vcpu, kvm_run->s.regs.prefix);
-	if (kvm_run->kvm_dirty_regs & KVM_SYNC_CRS) {
-		memcpy(&vcpu->arch.sie_block->gcr, &kvm_run->s.regs.crs, 128);
-		/* some control register changes require a tlb flush */
-		kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
-	}
 	if (kvm_run->kvm_dirty_regs & KVM_SYNC_ARCH0) {
-		kvm_s390_set_cpu_timer(vcpu, kvm_run->s.regs.cputm);
-		vcpu->arch.sie_block->ckc = kvm_run->s.regs.ckc;
 		vcpu->arch.sie_block->todpr = kvm_run->s.regs.todpr;
 		vcpu->arch.sie_block->pp = kvm_run->s.regs.pp;
 		vcpu->arch.sie_block->gbea = kvm_run->s.regs.gbea;
@@ -3893,6 +4298,11 @@
 		if (vcpu->arch.pfault_token == KVM_S390_PFAULT_TOKEN_INVALID)
 			kvm_clear_async_pf_completion_queue(vcpu);
 	}
+	if (kvm_run->kvm_dirty_regs & KVM_SYNC_DIAG318) {
+		vcpu->arch.diag318_info.val = kvm_run->s.regs.diag318;
+		vcpu->arch.sie_block->cpnc = vcpu->arch.diag318_info.cpnc;
+		VCPU_EVENT(vcpu, 3, "setting cpnc to %d", vcpu->arch.diag318_info.cpnc);
+	}
 	/*
 	 * If userspace sets the riccb (e.g. after migration) to a valid state,
 	 * we should enable RI here instead of doing the lazy enablement.
@@ -3922,6 +4332,36 @@
 		vcpu->arch.sie_block->fpf &= ~FPF_BPBC;
 		vcpu->arch.sie_block->fpf |= kvm_run->s.regs.bpbc ? FPF_BPBC : 0;
 	}
+	if (MACHINE_HAS_GS) {
+		preempt_disable();
+		__ctl_set_bit(2, 4);
+		if (current->thread.gs_cb) {
+			vcpu->arch.host_gscb = current->thread.gs_cb;
+			save_gs_cb(vcpu->arch.host_gscb);
+		}
+		if (vcpu->arch.gs_enabled) {
+			current->thread.gs_cb = (struct gs_cb *)
+						&vcpu->run->s.regs.gscb;
+			restore_gs_cb(current->thread.gs_cb);
+		}
+		preempt_enable();
+	}
+	/* SIE will load etoken directly from SDNX and therefore kvm_run */
+}
+
+static void sync_regs(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+	if (kvm_run->kvm_dirty_regs & KVM_SYNC_PREFIX)
+		kvm_s390_set_prefix(vcpu, kvm_run->s.regs.prefix);
+	if (kvm_run->kvm_dirty_regs & KVM_SYNC_CRS) {
+		memcpy(&vcpu->arch.sie_block->gcr, &kvm_run->s.regs.crs, 128);
+		/* some control register changes require a tlb flush */
+		kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
+	}
+	if (kvm_run->kvm_dirty_regs & KVM_SYNC_ARCH0) {
+		kvm_s390_set_cpu_timer(vcpu, kvm_run->s.regs.cputm);
+		vcpu->arch.sie_block->ckc = kvm_run->s.regs.ckc;
+	}
 	save_access_regs(vcpu->arch.host_acrs);
 	restore_access_regs(vcpu->run->s.regs.acrs);
 	/* save host (userspace) fprs/vrs */
@@ -3936,23 +4376,48 @@
 	if (test_fp_ctl(current->thread.fpu.fpc))
 		/* User space provided an invalid FPC, let's clear it */
 		current->thread.fpu.fpc = 0;
+
+	/* Sync fmt2 only data */
+	if (likely(!kvm_s390_pv_cpu_is_protected(vcpu))) {
+		sync_regs_fmt2(vcpu, kvm_run);
+	} else {
+		/*
+		 * In several places we have to modify our internal view to
+		 * not do things that are disallowed by the ultravisor. For
+		 * example we must not inject interrupts after specific exits
+		 * (e.g. 112 prefix page not secure). We do this by turning
+		 * off the machine check, external and I/O interrupt bits
+		 * of our PSW copy. To avoid getting validity intercepts, we
+		 * do only accept the condition code from userspace.
+		 */
+		vcpu->arch.sie_block->gpsw.mask &= ~PSW_MASK_CC;
+		vcpu->arch.sie_block->gpsw.mask |= kvm_run->psw_mask &
+						   PSW_MASK_CC;
+	}
+
+	kvm_run->kvm_dirty_regs = 0;
+}
+
+static void store_regs_fmt2(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+	kvm_run->s.regs.todpr = vcpu->arch.sie_block->todpr;
+	kvm_run->s.regs.pp = vcpu->arch.sie_block->pp;
+	kvm_run->s.regs.gbea = vcpu->arch.sie_block->gbea;
+	kvm_run->s.regs.bpbc = (vcpu->arch.sie_block->fpf & FPF_BPBC) == FPF_BPBC;
+	kvm_run->s.regs.diag318 = vcpu->arch.diag318_info.val;
 	if (MACHINE_HAS_GS) {
 		preempt_disable();
 		__ctl_set_bit(2, 4);
-		if (current->thread.gs_cb) {
-			vcpu->arch.host_gscb = current->thread.gs_cb;
-			save_gs_cb(vcpu->arch.host_gscb);
-		}
-		if (vcpu->arch.gs_enabled) {
-			current->thread.gs_cb = (struct gs_cb *)
-						&vcpu->run->s.regs.gscb;
-			restore_gs_cb(current->thread.gs_cb);
-		}
+		if (vcpu->arch.gs_enabled)
+			save_gs_cb(current->thread.gs_cb);
+		current->thread.gs_cb = vcpu->arch.host_gscb;
+		restore_gs_cb(vcpu->arch.host_gscb);
+		if (!vcpu->arch.host_gscb)
+			__ctl_clear_bit(2, 4);
+		vcpu->arch.host_gscb = NULL;
 		preempt_enable();
 	}
-	/* SIE will load etoken directly from SDNX and therefore kvm_run */
-
-	kvm_run->kvm_dirty_regs = 0;
+	/* SIE will save etoken directly into SDNX and therefore kvm_run */
 }
 
 static void store_regs(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
@@ -3963,13 +4428,9 @@
 	memcpy(&kvm_run->s.regs.crs, &vcpu->arch.sie_block->gcr, 128);
 	kvm_run->s.regs.cputm = kvm_s390_get_cpu_timer(vcpu);
 	kvm_run->s.regs.ckc = vcpu->arch.sie_block->ckc;
-	kvm_run->s.regs.todpr = vcpu->arch.sie_block->todpr;
-	kvm_run->s.regs.pp = vcpu->arch.sie_block->pp;
-	kvm_run->s.regs.gbea = vcpu->arch.sie_block->gbea;
 	kvm_run->s.regs.pft = vcpu->arch.pfault_token;
 	kvm_run->s.regs.pfs = vcpu->arch.pfault_select;
 	kvm_run->s.regs.pfc = vcpu->arch.pfault_compare;
-	kvm_run->s.regs.bpbc = (vcpu->arch.sie_block->fpf & FPF_BPBC) == FPF_BPBC;
 	save_access_regs(vcpu->run->s.regs.acrs);
 	restore_access_regs(vcpu->arch.host_acrs);
 	/* Save guest register state */
@@ -3978,19 +4439,8 @@
 	/* Restore will be done lazily at return */
 	current->thread.fpu.fpc = vcpu->arch.host_fpregs.fpc;
 	current->thread.fpu.regs = vcpu->arch.host_fpregs.regs;
-	if (MACHINE_HAS_GS) {
-		__ctl_set_bit(2, 4);
-		if (vcpu->arch.gs_enabled)
-			save_gs_cb(current->thread.gs_cb);
-		preempt_disable();
-		current->thread.gs_cb = vcpu->arch.host_gscb;
-		restore_gs_cb(vcpu->arch.host_gscb);
-		preempt_enable();
-		if (!vcpu->arch.host_gscb)
-			__ctl_clear_bit(2, 4);
-		vcpu->arch.host_gscb = NULL;
-	}
-	/* SIE will save etoken directly into SDNX and therefore kvm_run */
+	if (likely(!kvm_s390_pv_cpu_is_protected(vcpu)))
+		store_regs_fmt2(vcpu, kvm_run);
 }
 
 int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
@@ -4014,6 +4464,10 @@
 
 	kvm_sigset_activate(vcpu);
 
+	/*
+	 * no need to check the return value of vcpu_start as it can only have
+	 * an error for protvirt, but protvirt means user cpu state
+	 */
 	if (!kvm_s390_user_cpu_state_ctrl(vcpu->kvm)) {
 		kvm_s390_vcpu_start(vcpu);
 	} else if (is_vcpu_stopped(vcpu)) {
@@ -4151,18 +4605,27 @@
 	kvm_s390_sync_request(KVM_REQ_ENABLE_IBS, vcpu);
 }
 
-void kvm_s390_vcpu_start(struct kvm_vcpu *vcpu)
+int kvm_s390_vcpu_start(struct kvm_vcpu *vcpu)
 {
-	int i, online_vcpus, started_vcpus = 0;
+	int i, online_vcpus, r = 0, started_vcpus = 0;
 
 	if (!is_vcpu_stopped(vcpu))
-		return;
+		return 0;
 
 	trace_kvm_s390_vcpu_start_stop(vcpu->vcpu_id, 1);
 	/* Only one cpu at a time may enter/leave the STOPPED state. */
 	spin_lock(&vcpu->kvm->arch.start_stop_lock);
 	online_vcpus = atomic_read(&vcpu->kvm->online_vcpus);
 
+	/* Let's tell the UV that we want to change into the operating state */
+	if (kvm_s390_pv_cpu_is_protected(vcpu)) {
+		r = kvm_s390_pv_set_cpu_state(vcpu, PV_CPU_STATE_OPR);
+		if (r) {
+			spin_unlock(&vcpu->kvm->arch.start_stop_lock);
+			return r;
+		}
+	}
+
 	for (i = 0; i < online_vcpus; i++) {
 		if (!is_vcpu_stopped(vcpu->kvm->vcpus[i]))
 			started_vcpus++;
@@ -4182,31 +4645,52 @@
 
 	kvm_s390_clear_cpuflags(vcpu, CPUSTAT_STOPPED);
 	/*
+	 * The real PSW might have changed due to a RESTART interpreted by the
+	 * ultravisor. We block all interrupts and let the next sie exit
+	 * refresh our view.
+	 */
+	if (kvm_s390_pv_cpu_is_protected(vcpu))
+		vcpu->arch.sie_block->gpsw.mask &= ~PSW_INT_MASK;
+	/*
 	 * Another VCPU might have used IBS while we were offline.
 	 * Let's play safe and flush the VCPU at startup.
 	 */
 	kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
 	spin_unlock(&vcpu->kvm->arch.start_stop_lock);
-	return;
+	return 0;
 }
 
-void kvm_s390_vcpu_stop(struct kvm_vcpu *vcpu)
+int kvm_s390_vcpu_stop(struct kvm_vcpu *vcpu)
 {
-	int i, online_vcpus, started_vcpus = 0;
+	int i, online_vcpus, r = 0, started_vcpus = 0;
 	struct kvm_vcpu *started_vcpu = NULL;
 
 	if (is_vcpu_stopped(vcpu))
-		return;
+		return 0;
 
 	trace_kvm_s390_vcpu_start_stop(vcpu->vcpu_id, 0);
 	/* Only one cpu at a time may enter/leave the STOPPED state. */
 	spin_lock(&vcpu->kvm->arch.start_stop_lock);
 	online_vcpus = atomic_read(&vcpu->kvm->online_vcpus);
 
-	/* SIGP STOP and SIGP STOP AND STORE STATUS has been fully processed */
-	kvm_s390_clear_stop_irq(vcpu);
+	/* Let's tell the UV that we want to change into the stopped state */
+	if (kvm_s390_pv_cpu_is_protected(vcpu)) {
+		r = kvm_s390_pv_set_cpu_state(vcpu, PV_CPU_STATE_STP);
+		if (r) {
+			spin_unlock(&vcpu->kvm->arch.start_stop_lock);
+			return r;
+		}
+	}
 
+	/*
+	 * Set the VCPU to STOPPED and THEN clear the interrupt flag,
+	 * now that the SIGP STOP and SIGP STOP AND STORE STATUS orders
+	 * have been fully processed. This will ensure that the VCPU
+	 * is kept BUSY if another VCPU is inquiring with SIGP SENSE.
+	 */
 	kvm_s390_set_cpuflags(vcpu, CPUSTAT_STOPPED);
+	kvm_s390_clear_stop_irq(vcpu);
+
 	__disable_ibs_on_vcpu(vcpu);
 
 	for (i = 0; i < online_vcpus; i++) {
@@ -4225,7 +4709,7 @@
 	}
 
 	spin_unlock(&vcpu->kvm->arch.start_stop_lock);
-	return;
+	return 0;
 }
 
 static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
@@ -4252,37 +4736,74 @@
 	return r;
 }
 
-static long kvm_s390_guest_mem_op(struct kvm_vcpu *vcpu,
+static long kvm_s390_vcpu_sida_op(struct kvm_vcpu *vcpu,
 				  struct kvm_s390_mem_op *mop)
 {
 	void __user *uaddr = (void __user *)mop->buf;
+	int r = 0;
+
+	if (mop->flags || !mop->size)
+		return -EINVAL;
+	if (mop->size + mop->sida_offset < mop->size)
+		return -EINVAL;
+	if (mop->size + mop->sida_offset > sida_size(vcpu->arch.sie_block))
+		return -E2BIG;
+	if (!kvm_s390_pv_cpu_is_protected(vcpu))
+		return -EINVAL;
+
+	switch (mop->op) {
+	case KVM_S390_MEMOP_SIDA_READ:
+		if (copy_to_user(uaddr, (void *)(sida_origin(vcpu->arch.sie_block) +
+				 mop->sida_offset), mop->size))
+			r = -EFAULT;
+
+		break;
+	case KVM_S390_MEMOP_SIDA_WRITE:
+		if (copy_from_user((void *)(sida_origin(vcpu->arch.sie_block) +
+				   mop->sida_offset), uaddr, mop->size))
+			r = -EFAULT;
+		break;
+	}
+	return r;
+}
+
+static long kvm_s390_vcpu_mem_op(struct kvm_vcpu *vcpu,
+				 struct kvm_s390_mem_op *mop)
+{
+	void __user *uaddr = (void __user *)mop->buf;
 	void *tmpbuf = NULL;
-	int r, srcu_idx;
+	int r = 0;
 	const u64 supported_flags = KVM_S390_MEMOP_F_INJECT_EXCEPTION
-				    | KVM_S390_MEMOP_F_CHECK_ONLY;
+				    | KVM_S390_MEMOP_F_CHECK_ONLY
+				    | KVM_S390_MEMOP_F_SKEY_PROTECTION;
 
 	if (mop->flags & ~supported_flags || mop->ar >= NUM_ACRS || !mop->size)
 		return -EINVAL;
-
 	if (mop->size > MEM_OP_MAX_SIZE)
 		return -E2BIG;
-
+	if (kvm_s390_pv_cpu_is_protected(vcpu))
+		return -EINVAL;
+	if (mop->flags & KVM_S390_MEMOP_F_SKEY_PROTECTION) {
+		if (access_key_invalid(mop->key))
+			return -EINVAL;
+	} else {
+		mop->key = 0;
+	}
 	if (!(mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY)) {
 		tmpbuf = vmalloc(mop->size);
 		if (!tmpbuf)
 			return -ENOMEM;
 	}
 
-	srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
-
 	switch (mop->op) {
 	case KVM_S390_MEMOP_LOGICAL_READ:
 		if (mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY) {
-			r = check_gva_range(vcpu, mop->gaddr, mop->ar,
-					    mop->size, GACC_FETCH);
+			r = check_gva_range(vcpu, mop->gaddr, mop->ar, mop->size,
+					    GACC_FETCH, mop->key);
 			break;
 		}
-		r = read_guest(vcpu, mop->gaddr, mop->ar, tmpbuf, mop->size);
+		r = read_guest_with_key(vcpu, mop->gaddr, mop->ar, tmpbuf,
+					mop->size, mop->key);
 		if (r == 0) {
 			if (copy_to_user(uaddr, tmpbuf, mop->size))
 				r = -EFAULT;
@@ -4290,22 +4811,19 @@
 		break;
 	case KVM_S390_MEMOP_LOGICAL_WRITE:
 		if (mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY) {
-			r = check_gva_range(vcpu, mop->gaddr, mop->ar,
-					    mop->size, GACC_STORE);
+			r = check_gva_range(vcpu, mop->gaddr, mop->ar, mop->size,
+					    GACC_STORE, mop->key);
 			break;
 		}
 		if (copy_from_user(tmpbuf, uaddr, mop->size)) {
 			r = -EFAULT;
 			break;
 		}
-		r = write_guest(vcpu, mop->gaddr, mop->ar, tmpbuf, mop->size);
+		r = write_guest_with_key(vcpu, mop->gaddr, mop->ar, tmpbuf,
+					 mop->size, mop->key);
 		break;
-	default:
-		r = -EINVAL;
 	}
 
-	srcu_read_unlock(&vcpu->kvm->srcu, srcu_idx);
-
 	if (r > 0 && (mop->flags & KVM_S390_MEMOP_F_INJECT_EXCEPTION) != 0)
 		kvm_s390_inject_prog_irq(vcpu, &vcpu->arch.pgm);
 
@@ -4313,6 +4831,31 @@
 	return r;
 }
 
+static long kvm_s390_vcpu_memsida_op(struct kvm_vcpu *vcpu,
+				     struct kvm_s390_mem_op *mop)
+{
+	int r, srcu_idx;
+
+	srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
+
+	switch (mop->op) {
+	case KVM_S390_MEMOP_LOGICAL_READ:
+	case KVM_S390_MEMOP_LOGICAL_WRITE:
+		r = kvm_s390_vcpu_mem_op(vcpu, mop);
+		break;
+	case KVM_S390_MEMOP_SIDA_READ:
+	case KVM_S390_MEMOP_SIDA_WRITE:
+		/* we are locked against sida going away by the vcpu->mutex */
+		r = kvm_s390_vcpu_sida_op(vcpu, mop);
+		break;
+	default:
+		r = -EINVAL;
+	}
+
+	srcu_read_unlock(&vcpu->kvm->srcu, srcu_idx);
+	return r;
+}
+
 long kvm_arch_vcpu_async_ioctl(struct file *filp,
 			       unsigned int ioctl, unsigned long arg)
 {
@@ -4348,13 +4891,14 @@
 	void __user *argp = (void __user *)arg;
 	int idx;
 	long r;
+	u16 rc, rrc;
 
 	vcpu_load(vcpu);
 
 	switch (ioctl) {
 	case KVM_S390_STORE_STATUS:
 		idx = srcu_read_lock(&vcpu->kvm->srcu);
-		r = kvm_s390_vcpu_store_status(vcpu, arg);
+		r = kvm_s390_store_status_unloaded(vcpu, arg);
 		srcu_read_unlock(&vcpu->kvm->srcu, idx);
 		break;
 	case KVM_S390_SET_INITIAL_PSW: {
@@ -4366,12 +4910,43 @@
 		r = kvm_arch_vcpu_ioctl_set_initial_psw(vcpu, psw);
 		break;
 	}
+	case KVM_S390_CLEAR_RESET:
+		r = 0;
+		kvm_arch_vcpu_ioctl_clear_reset(vcpu);
+		if (kvm_s390_pv_cpu_is_protected(vcpu)) {
+			r = uv_cmd_nodata(kvm_s390_pv_cpu_get_handle(vcpu),
+					  UVC_CMD_CPU_RESET_CLEAR, &rc, &rrc);
+			VCPU_EVENT(vcpu, 3, "PROTVIRT RESET CLEAR VCPU: rc %x rrc %x",
+				   rc, rrc);
+		}
+		break;
 	case KVM_S390_INITIAL_RESET:
-		r = kvm_arch_vcpu_ioctl_initial_reset(vcpu);
+		r = 0;
+		kvm_arch_vcpu_ioctl_initial_reset(vcpu);
+		if (kvm_s390_pv_cpu_is_protected(vcpu)) {
+			r = uv_cmd_nodata(kvm_s390_pv_cpu_get_handle(vcpu),
+					  UVC_CMD_CPU_RESET_INITIAL,
+					  &rc, &rrc);
+			VCPU_EVENT(vcpu, 3, "PROTVIRT RESET INITIAL VCPU: rc %x rrc %x",
+				   rc, rrc);
+		}
+		break;
+	case KVM_S390_NORMAL_RESET:
+		r = 0;
+		kvm_arch_vcpu_ioctl_normal_reset(vcpu);
+		if (kvm_s390_pv_cpu_is_protected(vcpu)) {
+			r = uv_cmd_nodata(kvm_s390_pv_cpu_get_handle(vcpu),
+					  UVC_CMD_CPU_RESET, &rc, &rrc);
+			VCPU_EVENT(vcpu, 3, "PROTVIRT RESET NORMAL VCPU: rc %x rrc %x",
+				   rc, rrc);
+		}
 		break;
 	case KVM_SET_ONE_REG:
 	case KVM_GET_ONE_REG: {
 		struct kvm_one_reg reg;
+		r = -EINVAL;
+		if (kvm_s390_pv_cpu_is_protected(vcpu))
+			break;
 		r = -EFAULT;
 		if (copy_from_user(&reg, argp, sizeof(reg)))
 			break;
@@ -4434,7 +5009,7 @@
 		struct kvm_s390_mem_op mem_op;
 
 		if (copy_from_user(&mem_op, argp, sizeof(mem_op)) == 0)
-			r = kvm_s390_guest_mem_op(vcpu, &mem_op);
+			r = kvm_s390_vcpu_memsida_op(vcpu, &mem_op);
 		else
 			r = -EFAULT;
 		break;
@@ -4520,6 +5095,26 @@
 	if (mem->guest_phys_addr + mem->memory_size > kvm->arch.mem_limit)
 		return -EINVAL;
 
+	/* When we are protected, we should not change the memory slots */
+	if (kvm_s390_pv_get_handle(kvm))
+		return -EINVAL;
+
+	if (!kvm->arch.migration_mode)
+		return 0;
+
+	/*
+	 * Turn off migration mode when:
+	 * - userspace creates a new memslot with dirty logging off,
+	 * - userspace modifies an existing memslot (MOVE or FLAGS_ONLY) and
+	 *   dirty logging is turned off.
+	 * Migration mode expects dirty page logging being enabled to store
+	 * its dirty bitmap.
+	 */
+	if (change != KVM_MR_DELETE &&
+	    !(mem->flags & KVM_MEM_LOG_DIRTY_PAGES))
+		WARN(kvm_s390_vm_stop_migration(kvm),
+		     "Failed to stop migration mode");
+
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kvm/kvm-s390.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kvm/kvm-s390.h
@@ -2,7 +2,7 @@
 /*
  * definition for kvm on s390
  *
- * Copyright IBM Corp. 2008, 2009
+ * Copyright IBM Corp. 2008, 2020
  *
  *    Author(s): Carsten Otte <cotte@de.ibm.com>
  *               Christian Borntraeger <borntraeger@de.ibm.com>
@@ -15,6 +15,7 @@
 #include <linux/hrtimer.h>
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
+#include <linux/lockdep.h>
 #include <asm/facility.h>
 #include <asm/processor.h>
 #include <asm/sclp.h>
@@ -25,6 +26,17 @@
 #define IS_ITDB_VALID(vcpu)	((*(char *)vcpu->arch.sie_block->itdba == TDB_FORMAT1))
 
 extern debug_info_t *kvm_s390_dbf;
+extern debug_info_t *kvm_s390_dbf_uv;
+
+#define KVM_UV_EVENT(d_kvm, d_loglevel, d_string, d_args...)\
+do { \
+	debug_sprintf_event((d_kvm)->arch.dbf, d_loglevel, d_string "\n", \
+	  d_args); \
+	debug_sprintf_event(kvm_s390_dbf_uv, d_loglevel, \
+			    "%d: " d_string "\n", (d_kvm)->userspace_pid, \
+			    d_args); \
+} while (0)
+
 #define KVM_EVENT(d_loglevel, d_string, d_args...)\
 do { \
 	debug_sprintf_event(kvm_s390_dbf, d_loglevel, d_string "\n", \
@@ -67,7 +79,7 @@
 
 static inline int is_vcpu_idle(struct kvm_vcpu *vcpu)
 {
-	return test_bit(vcpu->vcpu_id, vcpu->kvm->arch.idle_mask);
+	return test_bit(kvm_vcpu_get_idx(vcpu), vcpu->kvm->arch.idle_mask);
 }
 
 static inline int kvm_is_ucontrol(struct kvm *kvm)
@@ -196,6 +208,48 @@
 	return kvm->arch.user_cpu_state_ctrl != 0;
 }
 
+static inline void kvm_s390_set_user_cpu_state_ctrl(struct kvm *kvm)
+{
+	if (kvm->arch.user_cpu_state_ctrl)
+		return;
+
+	VM_EVENT(kvm, 3, "%s", "ENABLE: Userspace CPU state control");
+	kvm->arch.user_cpu_state_ctrl = 1;
+}
+
+/* implemented in pv.c */
+int kvm_s390_pv_destroy_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc);
+int kvm_s390_pv_create_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc);
+int kvm_s390_pv_deinit_vm(struct kvm *kvm, u16 *rc, u16 *rrc);
+int kvm_s390_pv_init_vm(struct kvm *kvm, u16 *rc, u16 *rrc);
+int kvm_s390_pv_set_sec_parms(struct kvm *kvm, void *hdr, u64 length, u16 *rc,
+			      u16 *rrc);
+int kvm_s390_pv_unpack(struct kvm *kvm, unsigned long addr, unsigned long size,
+		       unsigned long tweak, u16 *rc, u16 *rrc);
+int kvm_s390_pv_set_cpu_state(struct kvm_vcpu *vcpu, u8 state);
+
+static inline u64 kvm_s390_pv_get_handle(struct kvm *kvm)
+{
+	return kvm->arch.pv.handle;
+}
+
+static inline u64 kvm_s390_pv_cpu_get_handle(struct kvm_vcpu *vcpu)
+{
+	return vcpu->arch.pv.handle;
+}
+
+static inline bool kvm_s390_pv_is_protected(struct kvm *kvm)
+{
+	lockdep_assert_held(&kvm->lock);
+	return !!kvm_s390_pv_get_handle(kvm);
+}
+
+static inline bool kvm_s390_pv_cpu_is_protected(struct kvm_vcpu *vcpu)
+{
+	lockdep_assert_held(&vcpu->mutex);
+	return !!kvm_s390_pv_cpu_get_handle(vcpu);
+}
+
 /* implemented in interrupt.c */
 int kvm_s390_handle_wait(struct kvm_vcpu *vcpu);
 void kvm_s390_vcpu_wakeup(struct kvm_vcpu *vcpu);
@@ -281,13 +335,12 @@
 int kvm_s390_handle_sigp_pei(struct kvm_vcpu *vcpu);
 
 /* implemented in kvm-s390.c */
-void kvm_s390_set_tod_clock(struct kvm *kvm,
-			    const struct kvm_s390_vm_tod_clock *gtod);
+int kvm_s390_try_set_tod_clock(struct kvm *kvm, const struct kvm_s390_vm_tod_clock *gtod);
 long kvm_arch_fault_in_page(struct kvm_vcpu *vcpu, gpa_t gpa, int writable);
 int kvm_s390_store_status_unloaded(struct kvm_vcpu *vcpu, unsigned long addr);
 int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr);
-void kvm_s390_vcpu_start(struct kvm_vcpu *vcpu);
-void kvm_s390_vcpu_stop(struct kvm_vcpu *vcpu);
+int kvm_s390_vcpu_start(struct kvm_vcpu *vcpu);
+int kvm_s390_vcpu_stop(struct kvm_vcpu *vcpu);
 void kvm_s390_vcpu_block(struct kvm_vcpu *vcpu);
 void kvm_s390_vcpu_unblock(struct kvm_vcpu *vcpu);
 bool kvm_s390_vcpu_sie_inhibited(struct kvm_vcpu *vcpu);
@@ -373,6 +426,7 @@
 int kvm_s390_ext_call_pending(struct kvm_vcpu *vcpu);
 extern struct kvm_device_ops kvm_flic_ops;
 int kvm_s390_is_stop_irq_pending(struct kvm_vcpu *vcpu);
+int kvm_s390_is_restart_irq_pending(struct kvm_vcpu *vcpu);
 void kvm_s390_clear_stop_irq(struct kvm_vcpu *vcpu);
 int kvm_s390_set_irq_state(struct kvm_vcpu *vcpu,
 			   void __user *buf, int len);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kvm/priv.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kvm/priv.c
@@ -2,7 +2,7 @@
 /*
  * handling privileged instructions
  *
- * Copyright IBM Corp. 2008, 2018
+ * Copyright IBM Corp. 2008, 2020
  *
  *    Author(s): Carsten Otte <cotte@de.ibm.com>
  *               Christian Borntraeger <borntraeger@de.ibm.com>
@@ -103,7 +103,20 @@
 		return kvm_s390_inject_prog_cond(vcpu, rc);
 
 	VCPU_EVENT(vcpu, 3, "SCK: setting guest TOD to 0x%llx", gtod.tod);
-	kvm_s390_set_tod_clock(vcpu->kvm, &gtod);
+	/*
+	 * To set the TOD clock the kvm lock must be taken, but the vcpu lock
+	 * is already held in handle_set_clock. The usual lock order is the
+	 * opposite.  As SCK is deprecated and should not be used in several
+	 * cases, for example when the multiple epoch facility or TOD clock
+	 * steering facility is installed (see Principles of Operation),  a
+	 * slow path can be used.  If the lock can not be taken via try_lock,
+	 * the instruction will be retried via -EAGAIN at a later point in
+	 * time.
+	 */
+	if (!kvm_s390_try_set_tod_clock(vcpu->kvm, &gtod)) {
+		kvm_s390_retry_instr(vcpu);
+		return -EAGAIN;
+	}
 
 	kvm_s390_set_psw_cc(vcpu, 0);
 	return 0;
@@ -398,6 +411,8 @@
 		up_read(&current->mm->mmap_sem);
 		if (rc == -EFAULT)
 			return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
+		if (rc == -EAGAIN)
+			continue;
 		if (rc < 0)
 			return rc;
 		start += PAGE_SIZE;
@@ -626,10 +641,12 @@
 	 * available for the guest are AQIC and TAPQ with the t bit set
 	 * since we do not set IC.3 (FIII) we currently will only intercept
 	 * the AQIC function code.
+	 * Note: running nested under z/VM can result in intercepts for other
+	 * function codes, e.g. PQAP(QCI). We do not support this and bail out.
 	 */
 	reg0 = vcpu->run->s.regs.gprs[0];
 	fc = (reg0 >> 24) & 0xff;
-	if (WARN_ON_ONCE(fc != 0x03))
+	if (fc != 0x03)
 		return -EOPNOTSUPP;
 
 	/* PQAP instruction is allowed for guest kernel only */
@@ -872,7 +889,7 @@
 
 	operand2 = kvm_s390_get_base_disp_s(vcpu, &ar);
 
-	if (operand2 & 0xfff)
+	if (!kvm_s390_pv_cpu_is_protected(vcpu) && (operand2 & 0xfff))
 		return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
 
 	switch (fc) {
@@ -893,8 +910,13 @@
 		handle_stsi_3_2_2(vcpu, (void *) mem);
 		break;
 	}
-
-	rc = write_guest(vcpu, operand2, ar, (void *)mem, PAGE_SIZE);
+	if (kvm_s390_pv_cpu_is_protected(vcpu)) {
+		memcpy((void *)sida_origin(vcpu->arch.sie_block), (void *)mem,
+		       PAGE_SIZE);
+		rc = 0;
+	} else {
+		rc = write_guest(vcpu, operand2, ar, (void *)mem, PAGE_SIZE);
+	}
 	if (rc) {
 		rc = kvm_s390_inject_prog_cond(vcpu, rc);
 		goto out;
@@ -1432,10 +1454,11 @@
 
 static int handle_tprot(struct kvm_vcpu *vcpu)
 {
-	u64 address1, address2;
-	unsigned long hva, gpa;
-	int ret = 0, cc = 0;
+	u64 address, operand2;
+	unsigned long gpa;
+	u8 access_key;
 	bool writable;
+	int ret, cc;
 	u8 ar;
 
 	vcpu->stat.instruction_tprot++;
@@ -1443,43 +1466,46 @@
 	if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
 		return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
 
-	kvm_s390_get_base_disp_sse(vcpu, &address1, &address2, &ar, NULL);
+	kvm_s390_get_base_disp_sse(vcpu, &address, &operand2, &ar, NULL);
+	access_key = (operand2 & 0xf0) >> 4;
 
-	/* we only handle the Linux memory detection case:
-	 * access key == 0
-	 * everything else goes to userspace. */
-	if (address2 & 0xf0)
-		return -EOPNOTSUPP;
 	if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_DAT)
 		ipte_lock(vcpu);
-	ret = guest_translate_address(vcpu, address1, ar, &gpa, GACC_STORE);
-	if (ret == PGM_PROTECTION) {
+
+	ret = guest_translate_address_with_key(vcpu, address, ar, &gpa,
+					       GACC_STORE, access_key);
+	if (ret == 0) {
+		gfn_to_hva_prot(vcpu->kvm, gpa_to_gfn(gpa), &writable);
+	} else if (ret == PGM_PROTECTION) {
+		writable = false;
 		/* Write protected? Try again with read-only... */
-		cc = 1;
-		ret = guest_translate_address(vcpu, address1, ar, &gpa,
-					      GACC_FETCH);
+		ret = guest_translate_address_with_key(vcpu, address, ar, &gpa,
+						       GACC_FETCH, access_key);
 	}
-	if (ret) {
-		if (ret == PGM_ADDRESSING || ret == PGM_TRANSLATION_SPEC) {
-			ret = kvm_s390_inject_program_int(vcpu, ret);
-		} else if (ret > 0) {
-			/* Translation not available */
-			kvm_s390_set_psw_cc(vcpu, 3);
+	if (ret >= 0) {
+		cc = -1;
+
+		/* Fetching permitted; storing permitted */
+		if (ret == 0 && writable)
+			cc = 0;
+		/* Fetching permitted; storing not permitted */
+		else if (ret == 0 && !writable)
+			cc = 1;
+		/* Fetching not permitted; storing not permitted */
+		else if (ret == PGM_PROTECTION)
+			cc = 2;
+		/* Translation not available */
+		else if (ret != PGM_ADDRESSING && ret != PGM_TRANSLATION_SPEC)
+			cc = 3;
+
+		if (cc != -1) {
+			kvm_s390_set_psw_cc(vcpu, cc);
 			ret = 0;
+		} else {
+			ret = kvm_s390_inject_program_int(vcpu, ret);
 		}
-		goto out_unlock;
 	}
 
-	hva = gfn_to_hva_prot(vcpu->kvm, gpa_to_gfn(gpa), &writable);
-	if (kvm_is_error_hva(hva)) {
-		ret = kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
-	} else {
-		if (!writable)
-			cc = 1;		/* Write not permitted ==> read-only */
-		kvm_s390_set_psw_cc(vcpu, cc);
-		/* Note: CC2 only occurs for storage keys (not supported yet) */
-	}
-out_unlock:
 	if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_DAT)
 		ipte_unlock(vcpu);
 	return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kvm/pv.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kvm/pv.c
@@ -0,0 +1,303 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Hosting Protected Virtual Machines
+ *
+ * Copyright IBM Corp. 2019, 2020
+ *    Author(s): Janosch Frank <frankja@linux.ibm.com>
+ */
+#include <linux/kvm.h>
+#include <linux/kvm_host.h>
+#include <linux/pagemap.h>
+#include <linux/sched/signal.h>
+#include <asm/pgalloc.h>
+#include <asm/gmap.h>
+#include <asm/uv.h>
+#include <asm/mman.h>
+#include "kvm-s390.h"
+
+int kvm_s390_pv_destroy_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc)
+{
+	int cc = 0;
+
+	if (kvm_s390_pv_cpu_get_handle(vcpu)) {
+		cc = uv_cmd_nodata(kvm_s390_pv_cpu_get_handle(vcpu),
+				   UVC_CMD_DESTROY_SEC_CPU, rc, rrc);
+
+		KVM_UV_EVENT(vcpu->kvm, 3,
+			     "PROTVIRT DESTROY VCPU %d: rc %x rrc %x",
+			     vcpu->vcpu_id, *rc, *rrc);
+		WARN_ONCE(cc, "protvirt destroy cpu failed rc %x rrc %x",
+			  *rc, *rrc);
+	}
+	/* Intended memory leak for something that should never happen. */
+	if (!cc)
+		free_pages(vcpu->arch.pv.stor_base,
+			   get_order(uv_info.guest_cpu_stor_len));
+
+	free_page(sida_origin(vcpu->arch.sie_block));
+	vcpu->arch.sie_block->pv_handle_cpu = 0;
+	vcpu->arch.sie_block->pv_handle_config = 0;
+	memset(&vcpu->arch.pv, 0, sizeof(vcpu->arch.pv));
+	vcpu->arch.sie_block->sdf = 0;
+	/*
+	 * The sidad field (for sdf == 2) is now the gbea field (for sdf == 0).
+	 * Use the reset value of gbea to avoid leaking the kernel pointer of
+	 * the just freed sida.
+	 */
+	vcpu->arch.sie_block->gbea = 1;
+	kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
+
+	return cc ? EIO : 0;
+}
+
+int kvm_s390_pv_create_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc)
+{
+	struct uv_cb_csc uvcb = {
+		.header.cmd = UVC_CMD_CREATE_SEC_CPU,
+		.header.len = sizeof(uvcb),
+	};
+	int cc;
+
+	if (kvm_s390_pv_cpu_get_handle(vcpu))
+		return -EINVAL;
+
+	vcpu->arch.pv.stor_base = __get_free_pages(GFP_KERNEL,
+						   get_order(uv_info.guest_cpu_stor_len));
+	if (!vcpu->arch.pv.stor_base)
+		return -ENOMEM;
+
+	/* Input */
+	uvcb.guest_handle = kvm_s390_pv_get_handle(vcpu->kvm);
+	uvcb.num = vcpu->arch.sie_block->icpua;
+	uvcb.state_origin = (u64)vcpu->arch.sie_block;
+	uvcb.stor_origin = (u64)vcpu->arch.pv.stor_base;
+
+	/* Alloc Secure Instruction Data Area Designation */
+	vcpu->arch.sie_block->sidad = __get_free_page(GFP_KERNEL | __GFP_ZERO);
+	if (!vcpu->arch.sie_block->sidad) {
+		free_pages(vcpu->arch.pv.stor_base,
+			   get_order(uv_info.guest_cpu_stor_len));
+		return -ENOMEM;
+	}
+
+	cc = uv_call(0, (u64)&uvcb);
+	*rc = uvcb.header.rc;
+	*rrc = uvcb.header.rrc;
+	KVM_UV_EVENT(vcpu->kvm, 3,
+		     "PROTVIRT CREATE VCPU: cpu %d handle %llx rc %x rrc %x",
+		     vcpu->vcpu_id, uvcb.cpu_handle, uvcb.header.rc,
+		     uvcb.header.rrc);
+
+	if (cc) {
+		u16 dummy;
+
+		kvm_s390_pv_destroy_cpu(vcpu, &dummy, &dummy);
+		return -EIO;
+	}
+
+	/* Output */
+	vcpu->arch.pv.handle = uvcb.cpu_handle;
+	vcpu->arch.sie_block->pv_handle_cpu = uvcb.cpu_handle;
+	vcpu->arch.sie_block->pv_handle_config = kvm_s390_pv_get_handle(vcpu->kvm);
+	vcpu->arch.sie_block->sdf = 2;
+	kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
+	return 0;
+}
+
+/* only free resources when the destroy was successful */
+static void kvm_s390_pv_dealloc_vm(struct kvm *kvm)
+{
+	vfree(kvm->arch.pv.stor_var);
+	free_pages(kvm->arch.pv.stor_base,
+		   get_order(uv_info.guest_base_stor_len));
+	memset(&kvm->arch.pv, 0, sizeof(kvm->arch.pv));
+}
+
+static int kvm_s390_pv_alloc_vm(struct kvm *kvm)
+{
+	unsigned long base = uv_info.guest_base_stor_len;
+	unsigned long virt = uv_info.guest_virt_var_stor_len;
+	unsigned long npages = 0, vlen = 0;
+	struct kvm_memory_slot *memslot;
+
+	kvm->arch.pv.stor_var = NULL;
+	kvm->arch.pv.stor_base = __get_free_pages(GFP_KERNEL, get_order(base));
+	if (!kvm->arch.pv.stor_base)
+		return -ENOMEM;
+
+	/*
+	 * Calculate current guest storage for allocation of the
+	 * variable storage, which is based on the length in MB.
+	 *
+	 * Slots are sorted by GFN
+	 */
+	mutex_lock(&kvm->slots_lock);
+	memslot = kvm_memslots(kvm)->memslots;
+	npages = memslot->base_gfn + memslot->npages;
+	mutex_unlock(&kvm->slots_lock);
+
+	kvm->arch.pv.guest_len = npages * PAGE_SIZE;
+
+	/* Allocate variable storage */
+	vlen = ALIGN(virt * ((npages * PAGE_SIZE) / HPAGE_SIZE), PAGE_SIZE);
+	vlen += uv_info.guest_virt_base_stor_len;
+	kvm->arch.pv.stor_var = vzalloc(vlen);
+	if (!kvm->arch.pv.stor_var)
+		goto out_err;
+	return 0;
+
+out_err:
+	kvm_s390_pv_dealloc_vm(kvm);
+	return -ENOMEM;
+}
+
+/* this should not fail, but if it does, we must not free the donated memory */
+int kvm_s390_pv_deinit_vm(struct kvm *kvm, u16 *rc, u16 *rrc)
+{
+	int cc;
+
+	/* make all pages accessible before destroying the guest */
+	s390_reset_acc(kvm->mm);
+
+	cc = uv_cmd_nodata(kvm_s390_pv_get_handle(kvm),
+			   UVC_CMD_DESTROY_SEC_CONF, rc, rrc);
+	WRITE_ONCE(kvm->arch.gmap->guest_handle, 0);
+	atomic_set(&kvm->mm->context.is_protected, 0);
+	KVM_UV_EVENT(kvm, 3, "PROTVIRT DESTROY VM: rc %x rrc %x", *rc, *rrc);
+	WARN_ONCE(cc, "protvirt destroy vm failed rc %x rrc %x", *rc, *rrc);
+	/* Inteded memory leak on "impossible" error */
+	if (!cc)
+		kvm_s390_pv_dealloc_vm(kvm);
+	return cc ? -EIO : 0;
+}
+
+int kvm_s390_pv_init_vm(struct kvm *kvm, u16 *rc, u16 *rrc)
+{
+	struct uv_cb_cgc uvcb = {
+		.header.cmd = UVC_CMD_CREATE_SEC_CONF,
+		.header.len = sizeof(uvcb)
+	};
+	int cc, ret;
+	u16 dummy;
+
+	ret = kvm_s390_pv_alloc_vm(kvm);
+	if (ret)
+		return ret;
+
+	/* Inputs */
+	uvcb.guest_stor_origin = 0; /* MSO is 0 for KVM */
+	uvcb.guest_stor_len = kvm->arch.pv.guest_len;
+	uvcb.guest_asce = kvm->arch.gmap->asce;
+	uvcb.guest_sca = (unsigned long)kvm->arch.sca;
+	uvcb.conf_base_stor_origin = (u64)kvm->arch.pv.stor_base;
+	uvcb.conf_virt_stor_origin = (u64)kvm->arch.pv.stor_var;
+
+	cc = uv_call_sched(0, (u64)&uvcb);
+	*rc = uvcb.header.rc;
+	*rrc = uvcb.header.rrc;
+	KVM_UV_EVENT(kvm, 3, "PROTVIRT CREATE VM: handle %llx len %llx rc %x rrc %x",
+		     uvcb.guest_handle, uvcb.guest_stor_len, *rc, *rrc);
+
+	/* Outputs */
+	kvm->arch.pv.handle = uvcb.guest_handle;
+
+	if (cc) {
+		if (uvcb.header.rc & UVC_RC_NEED_DESTROY)
+			kvm_s390_pv_deinit_vm(kvm, &dummy, &dummy);
+		else
+			kvm_s390_pv_dealloc_vm(kvm);
+		return -EIO;
+	}
+	kvm->arch.gmap->guest_handle = uvcb.guest_handle;
+	atomic_set(&kvm->mm->context.is_protected, 1);
+	return 0;
+}
+
+int kvm_s390_pv_set_sec_parms(struct kvm *kvm, void *hdr, u64 length, u16 *rc,
+			      u16 *rrc)
+{
+	struct uv_cb_ssc uvcb = {
+		.header.cmd = UVC_CMD_SET_SEC_CONF_PARAMS,
+		.header.len = sizeof(uvcb),
+		.sec_header_origin = (u64)hdr,
+		.sec_header_len = length,
+		.guest_handle = kvm_s390_pv_get_handle(kvm),
+	};
+	int cc = uv_call(0, (u64)&uvcb);
+
+	*rc = uvcb.header.rc;
+	*rrc = uvcb.header.rrc;
+	KVM_UV_EVENT(kvm, 3, "PROTVIRT VM SET PARMS: rc %x rrc %x",
+		     *rc, *rrc);
+	return cc ? -EINVAL : 0;
+}
+
+static int unpack_one(struct kvm *kvm, unsigned long addr, u64 tweak,
+		      u64 offset, u16 *rc, u16 *rrc)
+{
+	struct uv_cb_unp uvcb = {
+		.header.cmd = UVC_CMD_UNPACK_IMG,
+		.header.len = sizeof(uvcb),
+		.guest_handle = kvm_s390_pv_get_handle(kvm),
+		.gaddr = addr,
+		.tweak[0] = tweak,
+		.tweak[1] = offset,
+	};
+	int ret = gmap_make_secure(kvm->arch.gmap, addr, &uvcb);
+
+	*rc = uvcb.header.rc;
+	*rrc = uvcb.header.rrc;
+
+	if (ret && ret != -EAGAIN)
+		KVM_UV_EVENT(kvm, 3, "PROTVIRT VM UNPACK: failed addr %llx with rc %x rrc %x",
+			     uvcb.gaddr, *rc, *rrc);
+	return ret;
+}
+
+int kvm_s390_pv_unpack(struct kvm *kvm, unsigned long addr, unsigned long size,
+		       unsigned long tweak, u16 *rc, u16 *rrc)
+{
+	u64 offset = 0;
+	int ret = 0;
+
+	if (addr & ~PAGE_MASK || !size || size & ~PAGE_MASK)
+		return -EINVAL;
+
+	KVM_UV_EVENT(kvm, 3, "PROTVIRT VM UNPACK: start addr %lx size %lx",
+		     addr, size);
+
+	while (offset < size) {
+		ret = unpack_one(kvm, addr, tweak, offset, rc, rrc);
+		if (ret == -EAGAIN) {
+			cond_resched();
+			if (fatal_signal_pending(current))
+				break;
+			continue;
+		}
+		if (ret)
+			break;
+		addr += PAGE_SIZE;
+		offset += PAGE_SIZE;
+	}
+	if (!ret)
+		KVM_UV_EVENT(kvm, 3, "%s", "PROTVIRT VM UNPACK: successful");
+	return ret;
+}
+
+int kvm_s390_pv_set_cpu_state(struct kvm_vcpu *vcpu, u8 state)
+{
+	struct uv_cb_cpu_set_state uvcb = {
+		.header.cmd	= UVC_CMD_CPU_SET_STATE,
+		.header.len	= sizeof(uvcb),
+		.cpu_handle	= kvm_s390_pv_cpu_get_handle(vcpu),
+		.state		= state,
+	};
+	int cc;
+
+	cc = uv_call(0, (u64)&uvcb);
+	KVM_UV_EVENT(vcpu->kvm, 3, "PROTVIRT SET CPU %d STATE %d rc %x rrc %x",
+		     vcpu->vcpu_id, state, uvcb.header.rc, uvcb.header.rrc);
+	if (cc)
+		return -EINVAL;
+	return 0;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kvm/sigp.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kvm/sigp.c
@@ -151,22 +151,10 @@
 static int __sigp_set_arch(struct kvm_vcpu *vcpu, u32 parameter,
 			   u64 *status_reg)
 {
-	unsigned int i;
-	struct kvm_vcpu *v;
-	bool all_stopped = true;
-
-	kvm_for_each_vcpu(i, v, vcpu->kvm) {
-		if (v == vcpu)
-			continue;
-		if (!is_vcpu_stopped(v))
-			all_stopped = false;
-	}
-
 	*status_reg &= 0xffffffff00000000UL;
 
 	/* Reject set arch order, with czam we're always in z/Arch mode. */
-	*status_reg |= (all_stopped ? SIGP_STATUS_INVALID_PARAMETER :
-					SIGP_STATUS_INCORRECT_STATE);
+	*status_reg |= SIGP_STATUS_INVALID_PARAMETER;
 	return SIGP_CC_STATUS_STORED;
 }
 
@@ -288,6 +276,34 @@
 	if (!dst_vcpu)
 		return SIGP_CC_NOT_OPERATIONAL;
 
+	/*
+	 * SIGP RESTART, SIGP STOP, and SIGP STOP AND STORE STATUS orders
+	 * are processed asynchronously. Until the affected VCPU finishes
+	 * its work and calls back into KVM to clear the (RESTART or STOP)
+	 * interrupt, we need to return any new non-reset orders "busy".
+	 *
+	 * This is important because a single VCPU could issue:
+	 *  1) SIGP STOP $DESTINATION
+	 *  2) SIGP SENSE $DESTINATION
+	 *
+	 * If the SIGP SENSE would not be rejected as "busy", it could
+	 * return an incorrect answer as to whether the VCPU is STOPPED
+	 * or OPERATING.
+	 */
+	if (order_code != SIGP_INITIAL_CPU_RESET &&
+	    order_code != SIGP_CPU_RESET) {
+		/*
+		 * Lockless check. Both SIGP STOP and SIGP (RE)START
+		 * properly synchronize everything while processing
+		 * their orders, while the guest cannot observe a
+		 * difference when issuing other orders from two
+		 * different VCPUs.
+		 */
+		if (kvm_s390_is_stop_irq_pending(dst_vcpu) ||
+		    kvm_s390_is_restart_irq_pending(dst_vcpu))
+			return SIGP_CC_BUSY;
+	}
+
 	switch (order_code) {
 	case SIGP_SENSE:
 		vcpu->stat.instruction_sigp_sense++;
@@ -464,9 +480,9 @@
 	struct kvm_vcpu *dest_vcpu;
 	u8 order_code = kvm_s390_get_base_disp_rs(vcpu, NULL);
 
-	trace_kvm_s390_handle_sigp_pei(vcpu, order_code, cpu_addr);
-
 	if (order_code == SIGP_EXTERNAL_CALL) {
+		trace_kvm_s390_handle_sigp_pei(vcpu, order_code, cpu_addr);
+
 		dest_vcpu = kvm_get_vcpu_by_id(vcpu->kvm, cpu_addr);
 		BUG_ON(dest_vcpu == NULL);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/kvm/vsie.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/kvm/vsie.c
@@ -168,7 +168,8 @@
 			    sizeof(struct kvm_s390_apcb0)))
 		return -EFAULT;
 
-	bitmap_and(apcb_s, apcb_s, apcb_h, sizeof(struct kvm_s390_apcb0));
+	bitmap_and(apcb_s, apcb_s, apcb_h,
+		   BITS_PER_BYTE * sizeof(struct kvm_s390_apcb0));
 
 	return 0;
 }
@@ -190,7 +191,8 @@
 			    sizeof(struct kvm_s390_apcb1)))
 		return -EFAULT;
 
-	bitmap_and(apcb_s, apcb_s, apcb_h, sizeof(struct kvm_s390_apcb1));
+	bitmap_and(apcb_s, apcb_s, apcb_h,
+		   BITS_PER_BYTE * sizeof(struct kvm_s390_apcb1));
 
 	return 0;
 }
@@ -540,14 +542,17 @@
 	if (test_kvm_cpu_feat(vcpu->kvm, KVM_S390_VM_CPU_FEAT_CEI))
 		scb_s->eca |= scb_o->eca & ECA_CEI;
 	/* Epoch Extension */
-	if (test_kvm_facility(vcpu->kvm, 139))
+	if (test_kvm_facility(vcpu->kvm, 139)) {
 		scb_s->ecd |= scb_o->ecd & ECD_MEF;
+		scb_s->epdx = scb_o->epdx;
+	}
 
 	/* etoken */
 	if (test_kvm_facility(vcpu->kvm, 156))
 		scb_s->ecd |= scb_o->ecd & ECD_ETOKENF;
 
 	scb_s->hpid = HPID_VSIE;
+	scb_s->cpnc = scb_o->cpnc;
 
 	prepare_ibc(vcpu, vsie_page);
 	rc = shadow_crycb(vcpu, vsie_page);
@@ -1110,7 +1115,6 @@
 	gmap = gmap_shadow(vcpu->arch.gmap, asce, edat);
 	if (IS_ERR(gmap))
 		return PTR_ERR(gmap);
-	gmap->private = vcpu->kvm;
 	WRITE_ONCE(vsie_page->gmap, gmap);
 	return 0;
 }
@@ -1202,6 +1206,7 @@
 		scb_s->iprcc = PGM_ADDRESSING;
 		scb_s->pgmilc = 4;
 		scb_s->gpsw.addr = __rewind_psw(scb_s->gpsw, 4);
+		rc = 1;
 	}
 	return rc;
 }
@@ -1223,8 +1228,14 @@
 	page = radix_tree_lookup(&kvm->arch.vsie.addr_to_page, addr >> 9);
 	rcu_read_unlock();
 	if (page) {
-		if (page_ref_inc_return(page) == 2)
-			return page_to_virt(page);
+		if (page_ref_inc_return(page) == 2) {
+			if (page->index == addr)
+				return page_to_virt(page);
+			/*
+			 * We raced with someone reusing + putting this vsie
+			 * page before we grabbed it.
+			 */
+		}
 		page_ref_dec(page);
 	}
 
@@ -1254,15 +1265,20 @@
 			kvm->arch.vsie.next++;
 			kvm->arch.vsie.next %= nr_vcpus;
 		}
-		radix_tree_delete(&kvm->arch.vsie.addr_to_page, page->index >> 9);
+		if (page->index != ULONG_MAX)
+			radix_tree_delete(&kvm->arch.vsie.addr_to_page,
+					  page->index >> 9);
 	}
-	page->index = addr;
-	/* double use of the same address */
+	/* Mark it as invalid until it resides in the tree. */
+	page->index = ULONG_MAX;
+
+	/* Double use of the same address or allocation failure. */
 	if (radix_tree_insert(&kvm->arch.vsie.addr_to_page, addr >> 9, page)) {
 		page_ref_dec(page);
 		mutex_unlock(&kvm->arch.vsie.mutex);
 		return NULL;
 	}
+	page->index = addr;
 	mutex_unlock(&kvm->arch.vsie.mutex);
 
 	vsie_page = page_to_virt(page);
@@ -1355,7 +1371,9 @@
 		vsie_page = page_to_virt(page);
 		release_gmap_shadow(vsie_page);
 		/* free the radix tree entry */
-		radix_tree_delete(&kvm->arch.vsie.addr_to_page, page->index >> 9);
+		if (page->index != ULONG_MAX)
+			radix_tree_delete(&kvm->arch.vsie.addr_to_page,
+					  page->index >> 9);
 		__free_page(page);
 	}
 	kvm->arch.vsie.page_count = 0;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/lib/string.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/lib/string.c
@@ -246,14 +246,13 @@
 #ifdef __HAVE_ARCH_STRRCHR
 char *strrchr(const char *s, int c)
 {
-       size_t len = __strend(s) - s;
+	ssize_t len = __strend(s) - s;
 
-       if (len)
-	       do {
-		       if (s[len] == (char) c)
-			       return (char *) s + len;
-	       } while (--len > 0);
-       return NULL;
+	do {
+		if (s[len] == (char)c)
+			return (char *)s + len;
+	} while (--len >= 0);
+	return NULL;
 }
 EXPORT_SYMBOL(strrchr);
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/lib/uaccess.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/lib/uaccess.c
@@ -64,10 +64,13 @@
 {
 	mm_segment_t old_fs;
 	unsigned long asce, cr;
+	unsigned long flags;
 
 	old_fs = current->thread.mm_segment;
 	if (old_fs & 1)
 		return old_fs;
+	/* protect against a concurrent page table upgrade */
+	local_irq_save(flags);
 	current->thread.mm_segment |= 1;
 	asce = S390_lowcore.kernel_asce;
 	if (likely(old_fs == USER_DS)) {
@@ -83,6 +86,7 @@
 		__ctl_load(asce, 7, 7);
 		set_cpu_flag(CIF_ASCE_SECONDARY);
 	}
+	local_irq_restore(flags);
 	return old_fs;
 }
 EXPORT_SYMBOL(enable_sacf_uaccess);
@@ -98,10 +102,16 @@
 EXPORT_SYMBOL(disable_sacf_uaccess);
 
 static inline unsigned long copy_from_user_mvcos(void *x, const void __user *ptr,
-						 unsigned long size)
+						 unsigned long size, unsigned long key)
 {
-	register unsigned long reg0 asm("0") = 0x01UL;
 	unsigned long tmp1, tmp2;
+	union oac spec = {
+		.oac2.key = key,
+		.oac2.as = PSW_BITS_AS_PRIMARY,
+		.oac2.k = 1,
+		.oac2.a = 1,
+	};
+	register unsigned long reg0 asm("0") = spec.val;
 
 	tmp1 = -4096UL;
 	asm volatile(
@@ -128,7 +138,7 @@
 }
 
 static inline unsigned long copy_from_user_mvcp(void *x, const void __user *ptr,
-						unsigned long size)
+						unsigned long size, unsigned long key)
 {
 	unsigned long tmp1, tmp2;
 	mm_segment_t old_fs;
@@ -137,12 +147,12 @@
 	tmp1 = -256UL;
 	asm volatile(
 		"   sacf  0\n"
-		"0: mvcp  0(%0,%2),0(%1),%3\n"
+		"0: mvcp  0(%0,%2),0(%1),%[key]\n"
 		"7: jz    5f\n"
 		"1: algr  %0,%3\n"
 		"   la    %1,256(%1)\n"
 		"   la    %2,256(%2)\n"
-		"2: mvcp  0(%0,%2),0(%1),%3\n"
+		"2: mvcp  0(%0,%2),0(%1),%[key]\n"
 		"8: jnz   1b\n"
 		"   j     5f\n"
 		"3: la    %4,255(%1)\n"	/* %4 = ptr + 255 */
@@ -151,7 +161,7 @@
 		"   slgr  %4,%1\n"
 		"   clgr  %0,%4\n"	/* copy crosses next page boundary? */
 		"   jnh   6f\n"
-		"4: mvcp  0(%4,%2),0(%1),%3\n"
+		"4: mvcp  0(%4,%2),0(%1),%[key]\n"
 		"9: slgr  %0,%4\n"
 		"   j     6f\n"
 		"5: slgr  %0,%0\n"
@@ -159,24 +169,53 @@
 		EX_TABLE(0b,3b) EX_TABLE(2b,3b) EX_TABLE(4b,6b)
 		EX_TABLE(7b,3b) EX_TABLE(8b,3b) EX_TABLE(9b,6b)
 		: "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
-		: : "cc", "memory");
+		: [key] "d" (key << 4)
+		: "cc", "memory");
 	disable_sacf_uaccess(old_fs);
 	return size;
 }
 
-unsigned long raw_copy_from_user(void *to, const void __user *from, unsigned long n)
+static unsigned long raw_copy_from_user_key(void *to, const void __user *from,
+					    unsigned long n, unsigned long key)
 {
 	if (copy_with_mvcos())
-		return copy_from_user_mvcos(to, from, n);
-	return copy_from_user_mvcp(to, from, n);
+		return copy_from_user_mvcos(to, from, n, key);
+	return copy_from_user_mvcp(to, from, n, key);
+}
+
+unsigned long raw_copy_from_user(void *to, const void __user *from, unsigned long n)
+{
+	return raw_copy_from_user_key(to, from, n, 0);
 }
 EXPORT_SYMBOL(raw_copy_from_user);
 
+unsigned long _copy_from_user_key(void *to, const void __user *from,
+				  unsigned long n, unsigned long key)
+{
+	unsigned long res = n;
+
+	might_fault();
+	if (likely(access_ok(from, n))) {
+		kasan_check_write(to, n);
+		res = raw_copy_from_user_key(to, from, n, key);
+	}
+	if (unlikely(res))
+		memset(to + (n - res), 0, res);
+	return res;
+}
+EXPORT_SYMBOL(_copy_from_user_key);
+
 static inline unsigned long copy_to_user_mvcos(void __user *ptr, const void *x,
-					       unsigned long size)
+					       unsigned long size, unsigned long key)
 {
-	register unsigned long reg0 asm("0") = 0x010000UL;
 	unsigned long tmp1, tmp2;
+	union oac spec = {
+		.oac1.key = key,
+		.oac1.as = PSW_BITS_AS_PRIMARY,
+		.oac1.k = 1,
+		.oac1.a = 1,
+	};
+	register unsigned long reg0 asm("0") = spec.val;
 
 	tmp1 = -4096UL;
 	asm volatile(
@@ -203,7 +242,7 @@
 }
 
 static inline unsigned long copy_to_user_mvcs(void __user *ptr, const void *x,
-					      unsigned long size)
+					      unsigned long size, unsigned long key)
 {
 	unsigned long tmp1, tmp2;
 	mm_segment_t old_fs;
@@ -212,12 +251,12 @@
 	tmp1 = -256UL;
 	asm volatile(
 		"   sacf  0\n"
-		"0: mvcs  0(%0,%1),0(%2),%3\n"
+		"0: mvcs  0(%0,%1),0(%2),%[key]\n"
 		"7: jz    5f\n"
 		"1: algr  %0,%3\n"
 		"   la    %1,256(%1)\n"
 		"   la    %2,256(%2)\n"
-		"2: mvcs  0(%0,%1),0(%2),%3\n"
+		"2: mvcs  0(%0,%1),0(%2),%[key]\n"
 		"8: jnz   1b\n"
 		"   j     5f\n"
 		"3: la    %4,255(%1)\n" /* %4 = ptr + 255 */
@@ -226,7 +265,7 @@
 		"   slgr  %4,%1\n"
 		"   clgr  %0,%4\n"	/* copy crosses next page boundary? */
 		"   jnh   6f\n"
-		"4: mvcs  0(%4,%1),0(%2),%3\n"
+		"4: mvcs  0(%4,%1),0(%2),%[key]\n"
 		"9: slgr  %0,%4\n"
 		"   j     6f\n"
 		"5: slgr  %0,%0\n"
@@ -234,24 +273,49 @@
 		EX_TABLE(0b,3b) EX_TABLE(2b,3b) EX_TABLE(4b,6b)
 		EX_TABLE(7b,3b) EX_TABLE(8b,3b) EX_TABLE(9b,6b)
 		: "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2)
-		: : "cc", "memory");
+		: [key] "d" (key << 4)
+		: "cc", "memory");
 	disable_sacf_uaccess(old_fs);
 	return size;
 }
 
-unsigned long raw_copy_to_user(void __user *to, const void *from, unsigned long n)
+static unsigned long raw_copy_to_user_key(void __user *to, const void *from,
+					  unsigned long n, unsigned long key)
 {
 	if (copy_with_mvcos())
-		return copy_to_user_mvcos(to, from, n);
-	return copy_to_user_mvcs(to, from, n);
+		return copy_to_user_mvcos(to, from, n, key);
+	return copy_to_user_mvcs(to, from, n, key);
+}
+
+unsigned long raw_copy_to_user(void __user *to, const void *from, unsigned long n)
+{
+	return raw_copy_to_user_key(to, from, n, 0);
 }
 EXPORT_SYMBOL(raw_copy_to_user);
 
+unsigned long _copy_to_user_key(void __user *to, const void *from,
+				unsigned long n, unsigned long key)
+{
+	might_fault();
+	if (access_ok(to, n)) {
+		kasan_check_read(from, n);
+		n = raw_copy_to_user_key(to, from, n, key);
+	}
+	return n;
+}
+EXPORT_SYMBOL(_copy_to_user_key);
+
 static inline unsigned long copy_in_user_mvcos(void __user *to, const void __user *from,
 					       unsigned long size)
 {
-	register unsigned long reg0 asm("0") = 0x010001UL;
 	unsigned long tmp1, tmp2;
+	union oac spec = {
+		.oac1.as = PSW_BITS_AS_PRIMARY,
+		.oac1.a = 1,
+		.oac2.as = PSW_BITS_AS_PRIMARY,
+		.oac2.a = 1,
+	};
+	register unsigned long reg0 asm("0") = spec.val;
 
 	tmp1 = -4096UL;
 	/* FIXME: copy with reduced length. */
@@ -314,8 +378,12 @@
 
 static inline unsigned long clear_user_mvcos(void __user *to, unsigned long size)
 {
-	register unsigned long reg0 asm("0") = 0x010000UL;
 	unsigned long tmp1, tmp2;
+	union oac spec = {
+		.oac1.as = PSW_BITS_AS_PRIMARY,
+		.oac1.a = 1,
+	};
+	register unsigned long reg0 asm("0") = spec.val;
 
 	tmp1 = -4096UL;
 	asm volatile(
@@ -335,7 +403,7 @@
 		"4: slgr  %0,%0\n"
 		"5:\n"
 		EX_TABLE(0b,2b) EX_TABLE(3b,5b)
-		: "+a" (size), "+a" (to), "+a" (tmp1), "=a" (tmp2)
+		: "+&a" (size), "+&a" (to), "+a" (tmp1), "=&a" (tmp2)
 		: "a" (empty_zero_page), "d" (reg0) : "cc", "memory");
 	return size;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/mm/cmm.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/mm/cmm.c
@@ -98,11 +98,12 @@
 		(*counter)++;
 		spin_unlock(&cmm_lock);
 		nr--;
+		cond_resched();
 	}
 	return nr;
 }
 
-static long cmm_free_pages(long nr, long *counter, struct cmm_page_array **list)
+static long __cmm_free_pages(long nr, long *counter, struct cmm_page_array **list)
 {
 	struct cmm_page_array *pa;
 	unsigned long addr;
@@ -126,6 +127,21 @@
 	return nr;
 }
 
+static long cmm_free_pages(long nr, long *counter, struct cmm_page_array **list)
+{
+	long inc = 0;
+
+	while (nr) {
+		inc = min(256L, nr);
+		nr -= inc;
+		inc = __cmm_free_pages(inc, counter, list);
+		if (inc)
+			break;
+		cond_resched();
+	}
+	return nr + inc;
+}
+
 static int cmm_oom_notify(struct notifier_block *self,
 			  unsigned long dummy, void *parm)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/mm/fault.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/mm/fault.c
@@ -38,6 +38,7 @@
 #include <asm/irq.h>
 #include <asm/mmu_context.h>
 #include <asm/facility.h>
+#include <asm/uv.h>
 #include "../kernel/entry.h"
 
 #define __FAIL_ADDR_MASK -4096L
@@ -432,7 +433,9 @@
 	flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
 	if (user_mode(regs))
 		flags |= FAULT_FLAG_USER;
-	if (access == VM_WRITE || (trans_exc_code & store_indication) == 0x400)
+	if ((trans_exc_code & store_indication) == 0x400)
+		access = VM_WRITE;
+	if (access == VM_WRITE)
 		flags |= FAULT_FLAG_WRITE;
 	down_read(&mm->mmap_sem);
 
@@ -816,3 +819,80 @@
 early_initcall(pfault_irq_init);
 
 #endif /* CONFIG_PFAULT */
+
+#if IS_ENABLED(CONFIG_PGSTE)
+void do_secure_storage_access(struct pt_regs *regs)
+{
+	unsigned long addr = regs->int_parm_long & __FAIL_ADDR_MASK;
+	struct vm_area_struct *vma;
+	struct mm_struct *mm;
+	struct page *page;
+	int rc;
+
+	switch (get_fault_type(regs)) {
+	case USER_FAULT:
+		mm = current->mm;
+		down_read(&mm->mmap_sem);
+		vma = find_vma(mm, addr);
+		if (!vma) {
+			up_read(&mm->mmap_sem);
+			do_fault_error(regs, VM_READ | VM_WRITE, VM_FAULT_BADMAP);
+			break;
+		}
+		page = follow_page(vma, addr, FOLL_WRITE | FOLL_GET);
+		if (IS_ERR_OR_NULL(page)) {
+			up_read(&mm->mmap_sem);
+			break;
+		}
+		if (arch_make_page_accessible(page))
+			send_sig(SIGSEGV, current, 0);
+		put_page(page);
+		up_read(&mm->mmap_sem);
+		break;
+	case KERNEL_FAULT:
+		page = phys_to_page(addr);
+		if (unlikely(!try_get_page(page)))
+			break;
+		rc = arch_make_page_accessible(page);
+		put_page(page);
+		if (rc)
+			BUG();
+		break;
+	case VDSO_FAULT:
+		/* fallthrough */
+	case GMAP_FAULT:
+		/* fallthrough */
+	default:
+		do_fault_error(regs, VM_READ | VM_WRITE, VM_FAULT_BADMAP);
+		WARN_ON_ONCE(1);
+	}
+}
+NOKPROBE_SYMBOL(do_secure_storage_access);
+
+void do_non_secure_storage_access(struct pt_regs *regs)
+{
+	unsigned long gaddr = regs->int_parm_long & __FAIL_ADDR_MASK;
+	struct gmap *gmap = (struct gmap *)S390_lowcore.gmap;
+
+	if (get_fault_type(regs) != GMAP_FAULT) {
+		do_fault_error(regs, VM_READ | VM_WRITE, VM_FAULT_BADMAP);
+		WARN_ON_ONCE(1);
+		return;
+	}
+
+	if (gmap_convert_to_secure(gmap, gaddr) == -EINVAL)
+		send_sig(SIGSEGV, current, 0);
+}
+NOKPROBE_SYMBOL(do_non_secure_storage_access);
+
+#else
+void do_secure_storage_access(struct pt_regs *regs)
+{
+	default_trap_handler(regs);
+}
+
+void do_non_secure_storage_access(struct pt_regs *regs)
+{
+	default_trap_handler(regs);
+}
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/mm/gmap.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/mm/gmap.c
@@ -684,9 +684,10 @@
 		vmaddr |= gaddr & ~PMD_MASK;
 		/* Get pointer to the page table entry */
 		ptep = get_locked_pte(gmap->mm, vmaddr, &ptl);
-		if (likely(ptep))
+		if (likely(ptep)) {
 			ptep_zap_unused(gmap->mm, vmaddr, ptep, 0);
-		pte_unmap_unlock(ptep, ptl);
+			pte_unmap_unlock(ptep, ptl);
+		}
 	}
 }
 EXPORT_SYMBOL_GPL(__gmap_zap);
@@ -787,14 +788,18 @@
 static inline unsigned long *gmap_table_walk(struct gmap *gmap,
 					     unsigned long gaddr, int level)
 {
+	const int asce_type = gmap->asce & _ASCE_TYPE_MASK;
 	unsigned long *table;
 
 	if ((gmap->asce & _ASCE_TYPE_MASK) + 4 < (level * 4))
 		return NULL;
 	if (gmap_is_shadow(gmap) && gmap->removed)
 		return NULL;
-	if (gaddr & (-1UL << (31 + ((gmap->asce & _ASCE_TYPE_MASK) >> 2)*11)))
+
+	if (asce_type != _ASCE_TYPE_REGION1 &&
+	    gaddr & (-1UL << (31 + (asce_type >> 2) * 11)))
 		return NULL;
+
 	table = gmap->table;
 	switch (gmap->asce & _ASCE_TYPE_MASK) {
 	case _ASCE_TYPE_REGION1:
@@ -1173,6 +1178,7 @@
 static inline void gmap_insert_rmap(struct gmap *sg, unsigned long vmaddr,
 				    struct gmap_rmap *rmap)
 {
+	struct gmap_rmap *temp;
 	void __rcu **slot;
 
 	BUG_ON(!gmap_is_shadow(sg));
@@ -1180,6 +1186,12 @@
 	if (slot) {
 		rmap->next = radix_tree_deref_slot_protected(slot,
 							&sg->guest_table_lock);
+		for (temp = rmap->next; temp; temp = temp->next) {
+			if (temp->raddr == rmap->raddr) {
+				kfree(rmap);
+				return;
+			}
+		}
 		radix_tree_replace_slot(&sg->host_to_rmap, slot, rmap);
 	} else {
 		rmap->next = NULL;
@@ -1658,6 +1670,7 @@
 		return ERR_PTR(-ENOMEM);
 	new->mm = parent->mm;
 	new->parent = gmap_get(parent);
+	new->private = parent->private;
 	new->orig_asce = asce;
 	new->edat_level = edat_level;
 	new->initialized = false;
@@ -1840,6 +1853,7 @@
 		goto out_free;
 	} else if (*table & _REGION_ENTRY_ORIGIN) {
 		rc = -EAGAIN;		/* Race with shadow */
+		goto out_free;
 	}
 	crst_table_init(s_r3t, _REGION3_ENTRY_EMPTY);
 	/* mark as invalid as long as the parent table is not protected */
@@ -2480,23 +2494,36 @@
 }
 EXPORT_SYMBOL_GPL(gmap_sync_dirty_log_pmd);
 
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+static int thp_split_walk_pmd_entry(pmd_t *pmd, unsigned long addr,
+				    unsigned long end, struct mm_walk *walk)
+{
+	struct vm_area_struct *vma = walk->vma;
+
+	split_huge_pmd(vma, pmd, addr);
+	return 0;
+}
+
+static const struct mm_walk_ops thp_split_walk_ops = {
+	.pmd_entry	= thp_split_walk_pmd_entry,
+};
+
 static inline void thp_split_mm(struct mm_struct *mm)
 {
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
 	struct vm_area_struct *vma;
-	unsigned long addr;
 
 	for (vma = mm->mmap; vma != NULL; vma = vma->vm_next) {
-		for (addr = vma->vm_start;
-		     addr < vma->vm_end;
-		     addr += PAGE_SIZE)
-			follow_page(vma, addr, FOLL_SPLIT);
 		vma->vm_flags &= ~VM_HUGEPAGE;
 		vma->vm_flags |= VM_NOHUGEPAGE;
+		walk_page_vma(vma, &thp_split_walk_ops, NULL);
 	}
 	mm->def_flags |= VM_NOHUGEPAGE;
-#endif
 }
+#else
+static inline void thp_split_mm(struct mm_struct *mm)
+{
+}
+#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
 
 /*
  * Remove all empty zero pages from the mapping for lazy refaulting
@@ -2548,6 +2575,22 @@
 }
 EXPORT_SYMBOL_GPL(s390_enable_sie);
 
+int gmap_mark_unmergeable(void)
+{
+	struct mm_struct *mm = current->mm;
+	struct vm_area_struct *vma;
+
+	for (vma = mm->mmap; vma; vma = vma->vm_next) {
+		if (ksm_madvise(vma, vma->vm_start, vma->vm_end,
+				MADV_UNMERGEABLE, &vma->vm_flags)) {
+			return -ENOMEM;
+		}
+	}
+	mm->def_flags &= ~VM_MERGEABLE;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(gmap_mark_unmergeable);
+
 /*
  * Enable storage key handling from now on and initialize the storage
  * keys with the default key.
@@ -2560,6 +2603,18 @@
 	return 0;
 }
 
+/*
+ * Give a chance to schedule after setting a key to 256 pages.
+ * We only hold the mm lock, which is a rwsem and the kvm srcu.
+ * Both can sleep.
+ */
+static int __s390_enable_skey_pmd(pmd_t *pmd, unsigned long addr,
+				  unsigned long next, struct mm_walk *walk)
+{
+	cond_resched();
+	return 0;
+}
+
 static int __s390_enable_skey_hugetlb(pte_t *pte, unsigned long addr,
 				      unsigned long hmask, unsigned long next,
 				      struct mm_walk *walk)
@@ -2579,21 +2634,22 @@
 		return 0;
 
 	start = pmd_val(*pmd) & HPAGE_MASK;
-	end = start + HPAGE_SIZE - 1;
+	end = start + HPAGE_SIZE;
 	__storage_key_init_range(start, end);
 	set_bit(PG_arch_1, &page->flags);
+	cond_resched();
 	return 0;
 }
 
 static const struct mm_walk_ops enable_skey_walk_ops = {
 	.hugetlb_entry		= __s390_enable_skey_hugetlb,
 	.pte_entry		= __s390_enable_skey_pte,
+	.pmd_entry		= __s390_enable_skey_pmd,
 };
 
 int s390_enable_skey(void)
 {
 	struct mm_struct *mm = current->mm;
-	struct vm_area_struct *vma;
 	int rc = 0;
 
 	down_write(&mm->mmap_sem);
@@ -2601,16 +2657,11 @@
 		goto out_up;
 
 	mm->context.uses_skeys = 1;
-	for (vma = mm->mmap; vma; vma = vma->vm_next) {
-		if (ksm_madvise(vma, vma->vm_start, vma->vm_end,
-				MADV_UNMERGEABLE, &vma->vm_flags)) {
-			mm->context.uses_skeys = 0;
-			rc = -ENOMEM;
-			goto out_up;
-		}
+	rc = gmap_mark_unmergeable();
+	if (rc) {
+		mm->context.uses_skeys = 0;
+		goto out_up;
 	}
-	mm->def_flags &= ~VM_MERGEABLE;
-
 	walk_page_range(mm, 0, TASK_SIZE, &enable_skey_walk_ops, NULL);
 
 out_up:
@@ -2640,3 +2691,38 @@
 	up_write(&mm->mmap_sem);
 }
 EXPORT_SYMBOL_GPL(s390_reset_cmma);
+
+/*
+ * make inaccessible pages accessible again
+ */
+static int __s390_reset_acc(pte_t *ptep, unsigned long addr,
+			    unsigned long next, struct mm_walk *walk)
+{
+	pte_t pte = READ_ONCE(*ptep);
+
+	if (pte_present(pte))
+		WARN_ON_ONCE(uv_convert_from_secure(pte_val(pte) & PAGE_MASK));
+	return 0;
+}
+
+static const struct mm_walk_ops reset_acc_walk_ops = {
+	.pte_entry		= __s390_reset_acc,
+};
+
+#include <linux/sched/mm.h>
+void s390_reset_acc(struct mm_struct *mm)
+{
+	/*
+	 * we might be called during
+	 * reset:                             we walk the pages and clear
+	 * close of all kvm file descriptors: we walk the pages and clear
+	 * exit of process on fd closure:     vma already gone, do nothing
+	 */
+	if (!mmget_not_zero(mm))
+		return;
+	down_read(&mm->mmap_sem);
+	walk_page_range(mm, 0, TASK_SIZE, &reset_acc_walk_ops, NULL);
+	up_read(&mm->mmap_sem);
+	mmput(mm);
+}
+EXPORT_SYMBOL_GPL(s390_reset_acc);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/mm/hugetlbpage.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/mm/hugetlbpage.c
@@ -2,7 +2,7 @@
 /*
  *  IBM System z Huge TLB Page Support for Kernel.
  *
- *    Copyright IBM Corp. 2007,2016
+ *    Copyright IBM Corp. 2007,2020
  *    Author(s): Gerald Schaefer <gerald.schaefer@de.ibm.com>
  */
 
@@ -11,6 +11,9 @@
 
 #include <linux/mm.h>
 #include <linux/hugetlb.h>
+#include <linux/mman.h>
+#include <linux/sched/mm.h>
+#include <linux/security.h>
 
 /*
  * If the bit selected by single-bit bitmask "a" is set within "x", move
@@ -114,7 +117,7 @@
 					     _PAGE_YOUNG);
 #ifdef CONFIG_MEM_SOFT_DIRTY
 		pte_val(pte) |= move_set_bit(rste, _SEGMENT_ENTRY_SOFT_DIRTY,
-					     _PAGE_DIRTY);
+					     _PAGE_SOFT_DIRTY);
 #endif
 		pte_val(pte) |= move_set_bit(rste, _SEGMENT_ENTRY_NOEXEC,
 					     _PAGE_NOEXEC);
@@ -143,7 +146,7 @@
 	}
 
 	if (!test_and_set_bit(PG_arch_1, &page->flags))
-		__storage_key_init_range(paddr, paddr + size - 1);
+		__storage_key_init_range(paddr, paddr + size);
 }
 
 void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
@@ -156,10 +159,13 @@
 		rste &= ~_SEGMENT_ENTRY_NOEXEC;
 
 	/* Set correct table type for 2G hugepages */
-	if ((pte_val(*ptep) & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R3)
-		rste |= _REGION_ENTRY_TYPE_R3 | _REGION3_ENTRY_LARGE;
-	else
+	if ((pte_val(*ptep) & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R3) {
+		if (likely(pte_present(pte)))
+			rste |= _REGION3_ENTRY_LARGE;
+		rste |= _REGION_ENTRY_TYPE_R3;
+	} else if (likely(pte_present(pte)))
 		rste |= _SEGMENT_ENTRY_LARGE;
+
 	clear_huge_pte_skeys(mm, rste);
 	pte_val(*ptep) = rste;
 }
@@ -267,3 +273,98 @@
 	return 1;
 }
 __setup("hugepagesz=", setup_hugepagesz);
+
+static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file,
+		unsigned long addr, unsigned long len,
+		unsigned long pgoff, unsigned long flags)
+{
+	struct hstate *h = hstate_file(file);
+	struct vm_unmapped_area_info info;
+
+	info.flags = 0;
+	info.length = len;
+	info.low_limit = current->mm->mmap_base;
+	info.high_limit = TASK_SIZE;
+	info.align_mask = PAGE_MASK & ~huge_page_mask(h);
+	info.align_offset = 0;
+	return vm_unmapped_area(&info);
+}
+
+static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file,
+		unsigned long addr0, unsigned long len,
+		unsigned long pgoff, unsigned long flags)
+{
+	struct hstate *h = hstate_file(file);
+	struct vm_unmapped_area_info info;
+	unsigned long addr;
+
+	info.flags = VM_UNMAPPED_AREA_TOPDOWN;
+	info.length = len;
+	info.low_limit = max(PAGE_SIZE, mmap_min_addr);
+	info.high_limit = current->mm->mmap_base;
+	info.align_mask = PAGE_MASK & ~huge_page_mask(h);
+	info.align_offset = 0;
+	addr = vm_unmapped_area(&info);
+
+	/*
+	 * A failed mmap() very likely causes application failure,
+	 * so fall back to the bottom-up function here. This scenario
+	 * can happen with large stack limits and large mmap()
+	 * allocations.
+	 */
+	if (addr & ~PAGE_MASK) {
+		VM_BUG_ON(addr != -ENOMEM);
+		info.flags = 0;
+		info.low_limit = TASK_UNMAPPED_BASE;
+		info.high_limit = TASK_SIZE;
+		addr = vm_unmapped_area(&info);
+	}
+
+	return addr;
+}
+
+unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
+		unsigned long len, unsigned long pgoff, unsigned long flags)
+{
+	struct hstate *h = hstate_file(file);
+	struct mm_struct *mm = current->mm;
+	struct vm_area_struct *vma;
+	int rc;
+
+	if (len & ~huge_page_mask(h))
+		return -EINVAL;
+	if (len > TASK_SIZE - mmap_min_addr)
+		return -ENOMEM;
+
+	if (flags & MAP_FIXED) {
+		if (prepare_hugepage_range(file, addr, len))
+			return -EINVAL;
+		goto check_asce_limit;
+	}
+
+	if (addr) {
+		addr = ALIGN(addr, huge_page_size(h));
+		vma = find_vma(mm, addr);
+		if (TASK_SIZE - len >= addr && addr >= mmap_min_addr &&
+		    (!vma || addr + len <= vm_start_gap(vma)))
+			goto check_asce_limit;
+	}
+
+	if (mm->get_unmapped_area == arch_get_unmapped_area)
+		addr = hugetlb_get_unmapped_area_bottomup(file, addr, len,
+				pgoff, flags);
+	else
+		addr = hugetlb_get_unmapped_area_topdown(file, addr, len,
+				pgoff, flags);
+	if (addr & ~PAGE_MASK)
+		return addr;
+
+check_asce_limit:
+	if (addr + len > current->mm->context.asce_limit &&
+	    addr + len <= TASK_SIZE) {
+		rc = crst_table_upgrade(mm, addr + len);
+		if (rc)
+			return (unsigned long) rc;
+	}
+	return addr;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/mm/init.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/mm/init.c
@@ -168,9 +168,9 @@
 		return;
 
 	/* make sure bounce buffers are shared */
+	swiotlb_force = SWIOTLB_FORCE;
 	swiotlb_init(1);
 	swiotlb_update_mem_attributes();
-	swiotlb_force = SWIOTLB_FORCE;
 }
 
 void __init mem_init(void)
@@ -291,10 +291,8 @@
 {
 	unsigned long start_pfn = start >> PAGE_SHIFT;
 	unsigned long nr_pages = size >> PAGE_SHIFT;
-	struct zone *zone;
 
-	zone = page_zone(pfn_to_page(start_pfn));
-	__remove_pages(zone, start_pfn, nr_pages, altmap);
+	__remove_pages(start_pfn, nr_pages, altmap);
 	vmem_remove_mapping(start, size);
 }
 #endif /* CONFIG_MEMORY_HOTPLUG */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/mm/kasan_init.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/mm/kasan_init.c
@@ -101,6 +101,9 @@
 	pgt_prot = pgprot_val(PAGE_KERNEL_EXEC);
 	sgt_prot = pgprot_val(SEGMENT_KERNEL_EXEC);
 
+	/*
+	 * The first 1MB of 1:1 mapping is mapped with 4KB pages
+	 */
 	while (address < end) {
 		pg_dir = pgd_offset_k(address);
 		if (pgd_none(*pg_dir)) {
@@ -146,30 +149,26 @@
 
 		pm_dir = pmd_offset(pu_dir, address);
 		if (pmd_none(*pm_dir)) {
-			if (mode == POPULATE_ZERO_SHADOW &&
-			    IS_ALIGNED(address, PMD_SIZE) &&
+			if (IS_ALIGNED(address, PMD_SIZE) &&
 			    end - address >= PMD_SIZE) {
-				pmd_populate(&init_mm, pm_dir,
-						kasan_early_shadow_pte);
-				address = (address + PMD_SIZE) & PMD_MASK;
-				continue;
-			}
-			/* the first megabyte of 1:1 is mapped with 4k pages */
-			if (has_edat && address && end - address >= PMD_SIZE &&
-			    mode != POPULATE_ZERO_SHADOW) {
-				void *page;
-
-				if (mode == POPULATE_ONE2ONE) {
-					page = (void *)address;
-				} else {
-					page = kasan_early_alloc_segment();
-					memset(page, 0, _SEGMENT_SIZE);
+				if (mode == POPULATE_ZERO_SHADOW) {
+					pmd_populate(&init_mm, pm_dir, kasan_early_shadow_pte);
+					address = (address + PMD_SIZE) & PMD_MASK;
+					continue;
+				} else if (has_edat && address) {
+					void *page;
+
+					if (mode == POPULATE_ONE2ONE) {
+						page = (void *)address;
+					} else {
+						page = kasan_early_alloc_segment();
+						memset(page, 0, _SEGMENT_SIZE);
+					}
+					pmd_val(*pm_dir) = __pa(page) | sgt_prot;
+					address = (address + PMD_SIZE) & PMD_MASK;
+					continue;
 				}
-				pmd_val(*pm_dir) = __pa(page) | sgt_prot;
-				address = (address + PMD_SIZE) & PMD_MASK;
-				continue;
 			}
-
 			pt_dir = kasan_early_pte_alloc();
 			pmd_populate(&init_mm, pm_dir, pt_dir);
 		} else if (pmd_large(*pm_dir)) {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/mm/maccess.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/mm/maccess.c
@@ -55,22 +55,29 @@
  */
 static DEFINE_SPINLOCK(s390_kernel_write_lock);
 
-void notrace s390_kernel_write(void *dst, const void *src, size_t size)
+notrace void *s390_kernel_write(void *dst, const void *src, size_t size)
 {
+	void *tmp = dst;
 	unsigned long flags;
 	long copied;
 
 	spin_lock_irqsave(&s390_kernel_write_lock, flags);
-	while (size) {
-		copied = s390_kernel_write_odd(dst, src, size);
-		dst += copied;
-		src += copied;
-		size -= copied;
+	if (!(flags & PSW_MASK_DAT)) {
+		memcpy(dst, src, size);
+	} else {
+		while (size) {
+			copied = s390_kernel_write_odd(tmp, src, size);
+			tmp += copied;
+			src += copied;
+			size -= copied;
+		}
 	}
 	spin_unlock_irqrestore(&s390_kernel_write_lock, flags);
+
+	return dst;
 }
 
-static int __memcpy_real(void *dest, void *src, size_t count)
+static int __no_sanitize_address __memcpy_real(void *dest, void *src, size_t count)
 {
 	register unsigned long _dest asm("2") = (unsigned long) dest;
 	register unsigned long _len1 asm("3") = (unsigned long) count;
@@ -91,19 +98,23 @@
 	return rc;
 }
 
-static unsigned long _memcpy_real(unsigned long dest, unsigned long src,
-				  unsigned long count)
+static unsigned long __no_sanitize_address _memcpy_real(unsigned long dest,
+							unsigned long src,
+							unsigned long count)
 {
 	int irqs_disabled, rc;
 	unsigned long flags;
 
 	if (!count)
 		return 0;
-	flags = __arch_local_irq_stnsm(0xf8UL);
+	flags = arch_local_irq_save();
 	irqs_disabled = arch_irqs_disabled_flags(flags);
 	if (!irqs_disabled)
 		trace_hardirqs_off();
+	__arch_local_irq_stnsm(0xf8); // disable DAT
 	rc = __memcpy_real((void *) dest, (void *) src, (size_t) count);
+	if (flags & PSW_MASK_DAT)
+		__arch_local_irq_stosm(0x04); // enable DAT
 	if (!irqs_disabled)
 		trace_hardirqs_on();
 	__arch_local_irq_ssm(flags);
@@ -115,9 +126,15 @@
  */
 int memcpy_real(void *dest, void *src, size_t count)
 {
-	if (S390_lowcore.nodat_stack != 0)
-		return CALL_ON_STACK(_memcpy_real, S390_lowcore.nodat_stack,
-				     3, dest, src, count);
+	int rc;
+
+	if (S390_lowcore.nodat_stack != 0) {
+		preempt_disable();
+		rc = CALL_ON_STACK(_memcpy_real, S390_lowcore.nodat_stack, 3,
+				   dest, src, count);
+		preempt_enable();
+		return rc;
+	}
 	/*
 	 * This is a really early memcpy_real call, the stacks are
 	 * not set up yet. Just call _memcpy_real on the early boot
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/mm/page-states.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/mm/page-states.c
@@ -112,7 +112,7 @@
 		next = pmd_addr_end(addr, end);
 		if (pmd_none(*pmd) || pmd_large(*pmd))
 			continue;
-		page = virt_to_page(pmd_val(*pmd));
+		page = phys_to_page(pmd_val(*pmd));
 		set_bit(PG_arch_1, &page->flags);
 	} while (pmd++, addr = next, addr != end);
 }
@@ -130,8 +130,8 @@
 		if (pud_none(*pud) || pud_large(*pud))
 			continue;
 		if (!pud_folded(*pud)) {
-			page = virt_to_page(pud_val(*pud));
-			for (i = 0; i < 3; i++)
+			page = phys_to_page(pud_val(*pud));
+			for (i = 0; i < 4; i++)
 				set_bit(PG_arch_1, &page[i].flags);
 		}
 		mark_kernel_pmd(pud, addr, next);
@@ -151,8 +151,8 @@
 		if (p4d_none(*p4d))
 			continue;
 		if (!p4d_folded(*p4d)) {
-			page = virt_to_page(p4d_val(*p4d));
-			for (i = 0; i < 3; i++)
+			page = phys_to_page(p4d_val(*p4d));
+			for (i = 0; i < 4; i++)
 				set_bit(PG_arch_1, &page[i].flags);
 		}
 		mark_kernel_pud(p4d, addr, next);
@@ -173,8 +173,8 @@
 		if (pgd_none(*pgd))
 			continue;
 		if (!pgd_folded(*pgd)) {
-			page = virt_to_page(pgd_val(*pgd));
-			for (i = 0; i < 3; i++)
+			page = phys_to_page(pgd_val(*pgd));
+			for (i = 0; i < 4; i++)
 				set_bit(PG_arch_1, &page[i].flags);
 		}
 		mark_kernel_p4d(pgd, addr, next);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/mm/pgalloc.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/mm/pgalloc.c
@@ -70,8 +70,20 @@
 {
 	struct mm_struct *mm = arg;
 
-	if (current->active_mm == mm)
-		set_user_asce(mm);
+	/* we must change all active ASCEs to avoid the creation of new TLBs */
+	if (current->active_mm == mm) {
+		S390_lowcore.user_asce = mm->context.asce;
+		if (current->thread.mm_segment == USER_DS) {
+			__ctl_load(S390_lowcore.user_asce, 1, 1);
+			/* Mark user-ASCE present in CR1 */
+			clear_cpu_flag(CIF_ASCE_PRIMARY);
+		}
+		if (current->thread.mm_segment == USER_DS_SACF) {
+			__ctl_load(S390_lowcore.user_asce, 7, 7);
+			/* enable_sacf_uaccess does all or nothing */
+			WARN_ON(!test_cpu_flag(CIF_ASCE_SECONDARY));
+		}
+	}
 	__tlb_flush_local();
 }
 
@@ -243,13 +255,15 @@
 		/* Free 2K page table fragment of a 4K page */
 		bit = (__pa(table) & ~PAGE_MASK)/(PTRS_PER_PTE*sizeof(pte_t));
 		spin_lock_bh(&mm->context.lock);
-		mask = atomic_xor_bits(&page->_refcount, 1U << (bit + 24));
+		mask = atomic_xor_bits(&page->_refcount, 0x11U << (bit + 24));
 		mask >>= 24;
 		if (mask & 3)
 			list_add(&page->lru, &mm->context.pgtable_list);
 		else
 			list_del(&page->lru);
 		spin_unlock_bh(&mm->context.lock);
+		mask = atomic_xor_bits(&page->_refcount, 0x10U << (bit + 24));
+		mask >>= 24;
 		if (mask != 0)
 			return;
 	} else {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/mm/pgtable.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/mm/pgtable.c
@@ -699,7 +699,7 @@
 		pte_clear(mm, addr, ptep);
 	}
 	if (reset)
-		pgste_val(pgste) &= ~_PGSTE_GPS_USAGE_MASK;
+		pgste_val(pgste) &= ~(_PGSTE_GPS_USAGE_MASK | _PGSTE_GPS_NODAT);
 	pgste_set_unlock(ptep, pgste);
 	preempt_enable();
 }
@@ -716,7 +716,7 @@
 	pgste_val(pgste) |= PGSTE_GR_BIT | PGSTE_GC_BIT;
 	ptev = pte_val(*ptep);
 	if (!(ptev & _PAGE_INVALID) && (ptev & _PAGE_WRITE))
-		page_set_storage_key(ptev & PAGE_MASK, PAGE_DEFAULT_KEY, 1);
+		page_set_storage_key(ptev & PAGE_MASK, PAGE_DEFAULT_KEY, 0);
 	pgste_set_unlock(ptep, pgste);
 	preempt_enable();
 }
@@ -970,6 +970,7 @@
 int pgste_perform_essa(struct mm_struct *mm, unsigned long hva, int orc,
 			unsigned long *oldpte, unsigned long *oldpgste)
 {
+	struct vm_area_struct *vma;
 	unsigned long pgstev;
 	spinlock_t *ptl;
 	pgste_t pgste;
@@ -979,6 +980,10 @@
 	WARN_ON_ONCE(orc > ESSA_MAX);
 	if (unlikely(orc > ESSA_MAX))
 		return -EINVAL;
+
+	vma = find_vma(mm, hva);
+	if (!vma || hva < vma->vm_start || is_vm_hugetlb_page(vma))
+		return -EFAULT;
 	ptep = get_locked_pte(mm, hva, &ptl);
 	if (unlikely(!ptep))
 		return -EFAULT;
@@ -1071,10 +1076,14 @@
 int set_pgste_bits(struct mm_struct *mm, unsigned long hva,
 			unsigned long bits, unsigned long value)
 {
+	struct vm_area_struct *vma;
 	spinlock_t *ptl;
 	pgste_t new;
 	pte_t *ptep;
 
+	vma = find_vma(mm, hva);
+	if (!vma || hva < vma->vm_start || is_vm_hugetlb_page(vma))
+		return -EFAULT;
 	ptep = get_locked_pte(mm, hva, &ptl);
 	if (unlikely(!ptep))
 		return -EFAULT;
@@ -1099,9 +1108,13 @@
  */
 int get_pgste(struct mm_struct *mm, unsigned long hva, unsigned long *pgstep)
 {
+	struct vm_area_struct *vma;
 	spinlock_t *ptl;
 	pte_t *ptep;
 
+	vma = find_vma(mm, hva);
+	if (!vma || hva < vma->vm_start || is_vm_hugetlb_page(vma))
+		return -EFAULT;
 	ptep = get_locked_pte(mm, hva, &ptl);
 	if (unlikely(!ptep))
 		return -EFAULT;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/mm/vmem.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/mm/vmem.c
@@ -415,6 +415,10 @@
 		     SET_MEMORY_RO | SET_MEMORY_X);
 	__set_memory(__stext_dma, (__etext_dma - __stext_dma) >> PAGE_SHIFT,
 		     SET_MEMORY_RO | SET_MEMORY_X);
+
+	/* we need lowcore executable for our LPSWE instructions */
+	set_memory_x(0, 1);
+
 	pr_info("Write protected kernel read-only data: %luk\n",
 		(unsigned long)(__end_rodata - _stext) >> 10);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/net/bpf_jit_comp.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/net/bpf_jit_comp.c
@@ -23,6 +23,7 @@
 #include <linux/filter.h>
 #include <linux/init.h>
 #include <linux/bpf.h>
+#include <linux/mm.h>
 #include <asm/cacheflush.h>
 #include <asm/dis.h>
 #include <asm/facility.h>
@@ -113,7 +114,7 @@
 {
 	u32 r1 = reg2hex[b1];
 
-	if (!jit->seen_reg[r1] && r1 >= 6 && r1 <= 15)
+	if (r1 >= 6 && r1 <= 15 && !jit->seen_reg[r1])
 		jit->seen_reg[r1] = 1;
 }
 
@@ -568,10 +569,10 @@
 		EMIT4(0xb9080000, dst_reg, src_reg);
 		break;
 	case BPF_ALU | BPF_ADD | BPF_K: /* dst = (u32) dst + (u32) imm */
-		if (!imm)
-			break;
-		/* alfi %dst,imm */
-		EMIT6_IMM(0xc20b0000, dst_reg, imm);
+		if (imm != 0) {
+			/* alfi %dst,imm */
+			EMIT6_IMM(0xc20b0000, dst_reg, imm);
+		}
 		EMIT_ZERO(dst_reg);
 		break;
 	case BPF_ALU64 | BPF_ADD | BPF_K: /* dst = dst + imm */
@@ -593,17 +594,22 @@
 		EMIT4(0xb9090000, dst_reg, src_reg);
 		break;
 	case BPF_ALU | BPF_SUB | BPF_K: /* dst = (u32) dst - (u32) imm */
-		if (!imm)
-			break;
-		/* alfi %dst,-imm */
-		EMIT6_IMM(0xc20b0000, dst_reg, -imm);
+		if (imm != 0) {
+			/* alfi %dst,-imm */
+			EMIT6_IMM(0xc20b0000, dst_reg, -imm);
+		}
 		EMIT_ZERO(dst_reg);
 		break;
 	case BPF_ALU64 | BPF_SUB | BPF_K: /* dst = dst - imm */
 		if (!imm)
 			break;
-		/* agfi %dst,-imm */
-		EMIT6_IMM(0xc2080000, dst_reg, -imm);
+		if (imm == -0x80000000) {
+			/* algfi %dst,0x80000000 */
+			EMIT6_IMM(0xc20a0000, dst_reg, 0x80000000);
+		} else {
+			/* agfi %dst,-imm */
+			EMIT6_IMM(0xc2080000, dst_reg, -imm);
+		}
 		break;
 	/*
 	 * BPF_MUL
@@ -618,10 +624,10 @@
 		EMIT4(0xb90c0000, dst_reg, src_reg);
 		break;
 	case BPF_ALU | BPF_MUL | BPF_K: /* dst = (u32) dst * (u32) imm */
-		if (imm == 1)
-			break;
-		/* msfi %r5,imm */
-		EMIT6_IMM(0xc2010000, dst_reg, imm);
+		if (imm != 1) {
+			/* msfi %r5,imm */
+			EMIT6_IMM(0xc2010000, dst_reg, imm);
+		}
 		EMIT_ZERO(dst_reg);
 		break;
 	case BPF_ALU64 | BPF_MUL | BPF_K: /* dst = dst * imm */
@@ -674,6 +680,8 @@
 			if (BPF_OP(insn->code) == BPF_MOD)
 				/* lhgi %dst,0 */
 				EMIT4_IMM(0xa7090000, dst_reg, 0);
+			else
+				EMIT_ZERO(dst_reg);
 			break;
 		}
 		/* lhi %w0,0 */
@@ -768,10 +776,10 @@
 		EMIT4(0xb9820000, dst_reg, src_reg);
 		break;
 	case BPF_ALU | BPF_XOR | BPF_K: /* dst = (u32) dst ^ (u32) imm */
-		if (!imm)
-			break;
-		/* xilf %dst,imm */
-		EMIT6_IMM(0xc0070000, dst_reg, imm);
+		if (imm != 0) {
+			/* xilf %dst,imm */
+			EMIT6_IMM(0xc0070000, dst_reg, imm);
+		}
 		EMIT_ZERO(dst_reg);
 		break;
 	case BPF_ALU64 | BPF_XOR | BPF_K: /* dst = dst ^ imm */
@@ -792,10 +800,10 @@
 		EMIT6_DISP_LH(0xeb000000, 0x000d, dst_reg, dst_reg, src_reg, 0);
 		break;
 	case BPF_ALU | BPF_LSH | BPF_K: /* dst = (u32) dst << (u32) imm */
-		if (imm == 0)
-			break;
-		/* sll %dst,imm(%r0) */
-		EMIT4_DISP(0x89000000, dst_reg, REG_0, imm);
+		if (imm != 0) {
+			/* sll %dst,imm(%r0) */
+			EMIT4_DISP(0x89000000, dst_reg, REG_0, imm);
+		}
 		EMIT_ZERO(dst_reg);
 		break;
 	case BPF_ALU64 | BPF_LSH | BPF_K: /* dst = dst << imm */
@@ -817,10 +825,10 @@
 		EMIT6_DISP_LH(0xeb000000, 0x000c, dst_reg, dst_reg, src_reg, 0);
 		break;
 	case BPF_ALU | BPF_RSH | BPF_K: /* dst = (u32) dst >> (u32) imm */
-		if (imm == 0)
-			break;
-		/* srl %dst,imm(%r0) */
-		EMIT4_DISP(0x88000000, dst_reg, REG_0, imm);
+		if (imm != 0) {
+			/* srl %dst,imm(%r0) */
+			EMIT4_DISP(0x88000000, dst_reg, REG_0, imm);
+		}
 		EMIT_ZERO(dst_reg);
 		break;
 	case BPF_ALU64 | BPF_RSH | BPF_K: /* dst = dst >> imm */
@@ -842,10 +850,10 @@
 		EMIT6_DISP_LH(0xeb000000, 0x000a, dst_reg, dst_reg, src_reg, 0);
 		break;
 	case BPF_ALU | BPF_ARSH | BPF_K: /* ((s32) dst >> imm */
-		if (imm == 0)
-			break;
-		/* sra %dst,imm(%r0) */
-		EMIT4_DISP(0x8a000000, dst_reg, REG_0, imm);
+		if (imm != 0) {
+			/* sra %dst,imm(%r0) */
+			EMIT4_DISP(0x8a000000, dst_reg, REG_0, imm);
+		}
 		EMIT_ZERO(dst_reg);
 		break;
 	case BPF_ALU64 | BPF_ARSH | BPF_K: /* ((s64) dst) >>= imm */
@@ -913,6 +921,11 @@
 		}
 		break;
 	/*
+	 * BPF_NOSPEC (speculation barrier)
+	 */
+	case BPF_ST | BPF_NOSPEC:
+		break;
+	/*
 	 * BPF_ST(X)
 	 */
 	case BPF_STX | BPF_MEM | BPF_B: /* *(u8 *)(dst + off) = src_reg */
@@ -1369,10 +1382,10 @@
 	}
 
 	memset(&jit, 0, sizeof(jit));
-	jit.addrs = kcalloc(fp->len + 1, sizeof(*jit.addrs), GFP_KERNEL);
+	jit.addrs = kvcalloc(fp->len + 1, sizeof(*jit.addrs), GFP_KERNEL);
 	if (jit.addrs == NULL) {
 		fp = orig_fp;
-		goto out;
+		goto free_addrs;
 	}
 	/*
 	 * Three initial passes:
@@ -1422,7 +1435,7 @@
 	if (!fp->is_func || extra_pass) {
 		bpf_prog_fill_jited_linfo(fp, jit.addrs + 1);
 free_addrs:
-		kfree(jit.addrs);
+		kvfree(jit.addrs);
 		kfree(jit_data);
 		fp->aux->jit_data = NULL;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/numa/numa.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/numa/numa.c
@@ -49,12 +49,6 @@
 		mode->update_cpu_topology();
 }
 
-int __node_distance(int a, int b)
-{
-	return mode->distance ? mode->distance(a, b) : 0;
-}
-EXPORT_SYMBOL(__node_distance);
-
 int numa_debug_enabled;
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/pci/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/pci/Makefile
@@ -4,4 +4,5 @@
 #
 
 obj-$(CONFIG_PCI)	+= pci.o pci_irq.o pci_dma.o pci_clp.o pci_sysfs.o \
-			   pci_event.o pci_debug.o pci_insn.o pci_mmio.o
+			   pci_event.o pci_debug.o pci_insn.o pci_mmio.o \
+			   pci_bus.o
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/pci/pci.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/pci/pci.c
@@ -35,17 +35,21 @@
 #include <asm/pci_clp.h>
 #include <asm/pci_dma.h>
 
+#include "pci_bus.h"
+
 /* list of all detected zpci devices */
 static LIST_HEAD(zpci_list);
 static DEFINE_SPINLOCK(zpci_list_lock);
 
-static DECLARE_BITMAP(zpci_domain, ZPCI_NR_DEVICES);
+static DECLARE_BITMAP(zpci_domain, ZPCI_DOMAIN_BITMAP_SIZE);
 static DEFINE_SPINLOCK(zpci_domain_lock);
 
 #define ZPCI_IOMAP_ENTRIES						\
 	min(((unsigned long) ZPCI_NR_DEVICES * PCI_BAR_COUNT / 2),	\
 	    ZPCI_IOMAP_MAX_ENTRIES)
 
+unsigned int s390_pci_no_rid;
+
 static DEFINE_SPINLOCK(zpci_iomap_lock);
 static unsigned long *zpci_iomap_bitmap;
 struct zpci_iomap_entry *zpci_iomap_start;
@@ -86,17 +90,12 @@
 	spin_unlock(&zpci_list_lock);
 
 	list_for_each_entry_safe(zdev, tmp, &remove, entry)
-		zpci_remove_device(zdev);
-}
-
-static struct zpci_dev *get_zdev_by_bus(struct pci_bus *bus)
-{
-	return (bus && bus->sysdata) ? (struct zpci_dev *) bus->sysdata : NULL;
+		zpci_device_reserved(zdev);
 }
 
 int pci_domain_nr(struct pci_bus *bus)
 {
-	return ((struct zpci_dev *) bus->sysdata)->domain;
+	return ((struct zpci_bus *) bus->sysdata)->domain_nr;
 }
 EXPORT_SYMBOL_GPL(pci_domain_nr);
 
@@ -223,7 +222,7 @@
 /* combine single writes by using store-block insn */
 void __iowrite64_copy(void __iomem *to, const void *from, size_t count)
 {
-       zpci_memcpy_toio(to, from, count);
+	zpci_memcpy_toio(to, from, count * 8);
 }
 
 void __iomem *ioremap(unsigned long ioaddr, unsigned long size)
@@ -371,29 +370,17 @@
 static int pci_read(struct pci_bus *bus, unsigned int devfn, int where,
 		    int size, u32 *val)
 {
-	struct zpci_dev *zdev = get_zdev_by_bus(bus);
-	int ret;
+	struct zpci_dev *zdev = get_zdev_by_bus(bus, devfn);
 
-	if (!zdev || devfn != ZPCI_DEVFN)
-		ret = -ENODEV;
-	else
-		ret = zpci_cfg_load(zdev, where, val, size);
-
-	return ret;
+	return (zdev) ? zpci_cfg_load(zdev, where, val, size) : -ENODEV;
 }
 
 static int pci_write(struct pci_bus *bus, unsigned int devfn, int where,
 		     int size, u32 val)
 {
-	struct zpci_dev *zdev = get_zdev_by_bus(bus);
-	int ret;
+	struct zpci_dev *zdev = get_zdev_by_bus(bus, devfn);
 
-	if (!zdev || devfn != ZPCI_DEVFN)
-		ret = -ENODEV;
-	else
-		ret = zpci_cfg_store(zdev, where, val, size);
-
-	return ret;
+	return (zdev) ? zpci_cfg_store(zdev, where, val, size) : -ENODEV;
 }
 
 static struct pci_ops pci_root_ops = {
@@ -423,7 +410,7 @@
 
 		if (zpci_use_mio(zdev))
 			pdev->resource[i].start =
-				(resource_size_t __force) zdev->bars[i].mio_wb;
+				(resource_size_t __force) zdev->bars[i].mio_wt;
 		else
 			pdev->resource[i].start = (resource_size_t __force)
 				pci_iomap_range_fh(pdev, i, 0, 0);
@@ -504,15 +491,15 @@
 	return r;
 }
 
-static int zpci_setup_bus_resources(struct zpci_dev *zdev,
-				    struct list_head *resources)
+int zpci_setup_bus_resources(struct zpci_dev *zdev,
+			     struct list_head *resources)
 {
 	unsigned long addr, size, flags;
 	struct resource *res;
 	int i, entry;
 
 	snprintf(zdev->res_name, sizeof(zdev->res_name),
-		 "PCI Bus %04x:%02x", zdev->domain, ZPCI_BUS_NR);
+		 "PCI Bus %04x:%02x", zdev->uid, ZPCI_BUS_NR);
 
 	for (i = 0; i < PCI_BAR_COUNT; i++) {
 		if (!zdev->bars[i].size)
@@ -530,7 +517,7 @@
 			flags |= IORESOURCE_MEM_64;
 
 		if (zpci_use_mio(zdev))
-			addr = (unsigned long) zdev->bars[i].mio_wb;
+			addr = (unsigned long) zdev->bars[i].mio_wt;
 		else
 			addr = ZPCI_ADDR(entry);
 		size = 1UL << zdev->bars[i].size;
@@ -563,9 +550,12 @@
 
 int pcibios_add_device(struct pci_dev *pdev)
 {
+	struct zpci_dev *zdev = to_zpci(pdev);
 	struct resource *res;
 	int i;
 
+	/* The pdev has a reference to the zdev via its bus */
+	zpci_zdev_get(zdev);
 	if (pdev->is_physfn)
 		pdev->no_vf_scan = 1;
 
@@ -585,7 +575,10 @@
 
 void pcibios_release_device(struct pci_dev *pdev)
 {
+	struct zpci_dev *zdev = to_zpci(pdev);
+
 	zpci_unmap_resources(pdev);
+	zpci_zdev_put(zdev);
 }
 
 int pcibios_enable_device(struct pci_dev *pdev, int mask)
@@ -649,86 +642,54 @@
 };
 #endif /* CONFIG_HIBERNATE_CALLBACKS */
 
-static int zpci_alloc_domain(struct zpci_dev *zdev)
+static int __zpci_register_domain(int domain)
 {
-	if (zpci_unique_uid) {
-		zdev->domain = (u16) zdev->uid;
-		if (zdev->domain >= ZPCI_NR_DEVICES)
-			return 0;
-
-		spin_lock(&zpci_domain_lock);
-		if (test_bit(zdev->domain, zpci_domain)) {
-			spin_unlock(&zpci_domain_lock);
-			return -EEXIST;
-		}
-		set_bit(zdev->domain, zpci_domain);
-		spin_unlock(&zpci_domain_lock);
-		return 0;
-	}
-
 	spin_lock(&zpci_domain_lock);
-	zdev->domain = find_first_zero_bit(zpci_domain, ZPCI_NR_DEVICES);
-	if (zdev->domain == ZPCI_NR_DEVICES) {
+	if (test_bit(domain, zpci_domain)) {
 		spin_unlock(&zpci_domain_lock);
-		return -ENOSPC;
+		pr_err("Domain %04x is already assigned\n", domain);
+		return -EEXIST;
 	}
-	set_bit(zdev->domain, zpci_domain);
+	set_bit(domain, zpci_domain);
 	spin_unlock(&zpci_domain_lock);
-	return 0;
+	return domain;
 }
 
-static void zpci_free_domain(struct zpci_dev *zdev)
+static int __zpci_alloc_domain(void)
 {
-	if (zdev->domain >= ZPCI_NR_DEVICES)
-		return;
+	int domain;
 
 	spin_lock(&zpci_domain_lock);
-	clear_bit(zdev->domain, zpci_domain);
+	/*
+	 * We can always auto allocate domains below ZPCI_NR_DEVICES.
+	 * There is either a free domain or we have reached the maximum in
+	 * which case we would have bailed earlier.
+	 */
+	domain = find_first_zero_bit(zpci_domain, ZPCI_NR_DEVICES);
+	set_bit(domain, zpci_domain);
 	spin_unlock(&zpci_domain_lock);
+	return domain;
 }
 
-void pcibios_remove_bus(struct pci_bus *bus)
+int zpci_alloc_domain(int domain)
 {
-	struct zpci_dev *zdev = get_zdev_by_bus(bus);
-
-	zpci_exit_slot(zdev);
-	zpci_cleanup_bus_resources(zdev);
-	zpci_destroy_iommu(zdev);
-	zpci_free_domain(zdev);
-
-	spin_lock(&zpci_list_lock);
-	list_del(&zdev->entry);
-	spin_unlock(&zpci_list_lock);
-
-	zpci_dbg(3, "rem fid:%x\n", zdev->fid);
-	kfree(zdev);
+	if (zpci_unique_uid) {
+		if (domain)
+			return __zpci_register_domain(domain);
+		pr_warn("UID checking was active but no UID is provided: switching to automatic domain allocation\n");
+		update_uid_checking(false);
+	}
+	return __zpci_alloc_domain();
 }
 
-static int zpci_scan_bus(struct zpci_dev *zdev)
+void zpci_free_domain(int domain)
 {
-	LIST_HEAD(resources);
-	int ret;
-
-	ret = zpci_setup_bus_resources(zdev, &resources);
-	if (ret)
-		goto error;
-
-	zdev->bus = pci_scan_root_bus(NULL, ZPCI_BUS_NR, &pci_root_ops,
-				      zdev, &resources);
-	if (!zdev->bus) {
-		ret = -EIO;
-		goto error;
-	}
-	zdev->bus->max_bus_speed = zdev->max_bus_speed;
-	pci_bus_add_devices(zdev->bus);
-	return 0;
-
-error:
-	zpci_cleanup_bus_resources(zdev);
-	pci_free_resource_list(&resources);
-	return ret;
+	spin_lock(&zpci_domain_lock);
+	clear_bit(domain, zpci_domain);
+	spin_unlock(&zpci_domain_lock);
 }
 
+
 int zpci_enable_device(struct zpci_dev *zdev)
 {
 	int rc;
@@ -754,21 +715,68 @@
 int zpci_disable_device(struct zpci_dev *zdev)
 {
 	zpci_dma_exit_device(zdev);
+	/*
+	 * The zPCI function may already be disabled by the platform, this is
+	 * detected in clp_disable_fh() which becomes a no-op.
+	 */
 	return clp_disable_fh(zdev);
 }
 EXPORT_SYMBOL_GPL(zpci_disable_device);
 
+bool zpci_is_device_configured(struct zpci_dev *zdev)
+{
+	enum zpci_state state = zdev->state;
+
+	return state != ZPCI_FN_STATE_RESERVED &&
+		state != ZPCI_FN_STATE_STANDBY;
+}
+
+/* zpci_remove_device - Removes the given zdev from the PCI core
+ * @zdev: the zdev to be removed from the PCI core
+ * @set_error: if true the device's error state is set to permanent failure
+ *
+ * Sets a zPCI device to a configured but offline state; the zPCI
+ * device is still accessible through its hotplug slot and the zPCI
+ * API but is removed from the common code PCI bus, making it
+ * no longer available to drivers.
+ */
+void zpci_remove_device(struct zpci_dev *zdev, bool set_error)
+{
+	struct zpci_bus *zbus = zdev->zbus;
+	struct pci_dev *pdev;
+
+	if (!zdev->zbus->bus)
+		return;
+
+	pdev = pci_get_slot(zbus->bus, zdev->devfn);
+	if (pdev) {
+		if (set_error)
+			pdev->error_state = pci_channel_io_perm_failure;
+		if (pdev->is_virtfn) {
+			zpci_remove_virtfn(pdev, zdev->vfn);
+			/* balance pci_get_slot */
+			pci_dev_put(pdev);
+			return;
+		}
+		pci_stop_and_remove_bus_device_locked(pdev);
+		/* balance pci_get_slot */
+		pci_dev_put(pdev);
+	}
+}
+
 int zpci_create_device(struct zpci_dev *zdev)
 {
 	int rc;
 
-	rc = zpci_alloc_domain(zdev);
-	if (rc)
-		goto out;
+	kref_init(&zdev->kref);
+
+	spin_lock(&zpci_list_lock);
+	list_add_tail(&zdev->entry, &zpci_list);
+	spin_unlock(&zpci_list_lock);
 
 	rc = zpci_init_iommu(zdev);
 	if (rc)
-		goto out_free;
+		goto out;
 
 	mutex_init(&zdev->lock);
 	if (zdev->state == ZPCI_FN_STATE_CONFIGURED) {
@@ -776,36 +784,81 @@
 		if (rc)
 			goto out_destroy_iommu;
 	}
-	rc = zpci_scan_bus(zdev);
+
+	rc = zpci_bus_device_register(zdev, &pci_root_ops);
 	if (rc)
 		goto out_disable;
 
-	spin_lock(&zpci_list_lock);
-	list_add_tail(&zdev->entry, &zpci_list);
-	spin_unlock(&zpci_list_lock);
-
-	zpci_init_slot(zdev);
-
 	return 0;
 
 out_disable:
 	if (zdev->state == ZPCI_FN_STATE_ONLINE)
 		zpci_disable_device(zdev);
+
 out_destroy_iommu:
 	zpci_destroy_iommu(zdev);
-out_free:
-	zpci_free_domain(zdev);
 out:
+	spin_lock(&zpci_list_lock);
+	list_del(&zdev->entry);
+	spin_unlock(&zpci_list_lock);
 	return rc;
 }
 
-void zpci_remove_device(struct zpci_dev *zdev)
+/**
+ * zpci_device_reserved() - Mark device as resverved
+ * @zdev: the zpci_dev that was reserved
+ *
+ * Handle the case that a given zPCI function was reserved by another system.
+ * After a call to this function the zpci_dev can not be found via
+ * get_zdev_by_fid() anymore but may still be accessible via existing
+ * references though it will not be functional anymore.
+ */
+void zpci_device_reserved(struct zpci_dev *zdev)
+{
+	if (zdev->has_hp_slot)
+		zpci_exit_slot(zdev);
+	/*
+	 * Remove device from zpci_list as it is going away. This also
+	 * makes sure we ignore subsequent zPCI events for this device.
+	 */
+	spin_lock(&zpci_list_lock);
+	list_del(&zdev->entry);
+	spin_unlock(&zpci_list_lock);
+	zdev->state = ZPCI_FN_STATE_RESERVED;
+	zpci_dbg(3, "rsv fid:%x\n", zdev->fid);
+	zpci_zdev_put(zdev);
+}
+
+void zpci_release_device(struct kref *kref)
 {
-	if (!zdev->bus)
-		return;
+	struct zpci_dev *zdev = container_of(kref, struct zpci_dev, kref);
 
-	pci_stop_root_bus(zdev->bus);
-	pci_remove_root_bus(zdev->bus);
+	if (zdev->zbus->bus)
+		zpci_remove_device(zdev, false);
+
+	switch (zdev->state) {
+	case ZPCI_FN_STATE_ONLINE:
+	case ZPCI_FN_STATE_CONFIGURED:
+		zpci_disable_device(zdev);
+		fallthrough;
+	case ZPCI_FN_STATE_STANDBY:
+		if (zdev->has_hp_slot)
+			zpci_exit_slot(zdev);
+		spin_lock(&zpci_list_lock);
+		list_del(&zdev->entry);
+		spin_unlock(&zpci_list_lock);
+		zpci_dbg(3, "rsv fid:%x\n", zdev->fid);
+		fallthrough;
+	case ZPCI_FN_STATE_RESERVED:
+		zpci_cleanup_bus_resources(zdev);
+		zpci_bus_device_unregister(zdev);
+		zpci_destroy_iommu(zdev);
+		fallthrough;
+	default:
+		break;
+	}
+	zpci_dbg(3, "rem fid:%x\n", zdev->fid);
+	kfree(zdev);
 }
 
 int zpci_report_error(struct pci_dev *pdev,
@@ -854,7 +907,6 @@
 }
 
 static unsigned int s390_pci_probe __initdata = 1;
-static unsigned int s390_pci_no_mio __initdata;
 unsigned int s390_pci_force_floating __initdata;
 static unsigned int s390_pci_initialized;
 
@@ -865,13 +917,17 @@
 		return NULL;
 	}
 	if (!strcmp(str, "nomio")) {
-		s390_pci_no_mio = 1;
+		S390_lowcore.machine_flags &= ~MACHINE_FLAG_PCI_MIO;
 		return NULL;
 	}
 	if (!strcmp(str, "force_floating")) {
 		s390_pci_force_floating = 1;
 		return NULL;
 	}
+	if (!strcmp(str, "norid")) {
+		s390_pci_no_rid = 1;
+		return NULL;
+	}
 	return str;
 }
 
@@ -890,7 +946,7 @@
 	if (!test_facility(69) || !test_facility(71))
 		return 0;
 
-	if (test_facility(153) && !s390_pci_no_mio) {
+	if (MACHINE_HAS_PCI_MIO) {
 		static_branch_enable(&have_mio);
 		ctl_set_bit(2, 5);
 	}
@@ -934,5 +990,5 @@
 void zpci_rescan(void)
 {
 	if (zpci_is_enabled())
-		clp_rescan_pci_devices_simple();
+		clp_rescan_pci_devices_simple(NULL);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/pci/pci_bus.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/pci/pci_bus.c
@@ -0,0 +1,332 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright IBM Corp. 2020
+ *
+ * Author(s):
+ *   Pierre Morel <pmorel@linux.ibm.com>
+ *
+ */
+
+#define KMSG_COMPONENT "zpci"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/jump_label.h>
+#include <linux/pci.h>
+#include <linux/printk.h>
+
+#include <asm/pci_clp.h>
+#include <asm/pci_dma.h>
+
+#include "pci_bus.h"
+
+static LIST_HEAD(zbus_list);
+static DEFINE_SPINLOCK(zbus_list_lock);
+static int zpci_nb_devices;
+
+/* zpci_bus_scan
+ * @zbus: the zbus holding the zdevices
+ * @ops: the pci operations
+ *
+ * The domain number must be set before pci_scan_root_bus is called.
+ * This function can be called once the domain is known, hence
+ * when the function_0 is dicovered.
+ */
+static int zpci_bus_scan(struct zpci_bus *zbus, int domain, struct pci_ops *ops)
+{
+	struct pci_bus *bus;
+	int rc;
+
+	rc = zpci_alloc_domain(domain);
+	if (rc < 0)
+		return rc;
+	zbus->domain_nr = rc;
+
+	bus = pci_scan_root_bus(NULL, ZPCI_BUS_NR, ops, zbus, &zbus->resources);
+	if (!bus) {
+		zpci_free_domain(zbus->domain_nr);
+		return -EFAULT;
+	}
+
+	zbus->bus = bus;
+	pci_bus_add_devices(bus);
+	return 0;
+}
+
+static void zpci_bus_release(struct kref *kref)
+{
+	struct zpci_bus *zbus = container_of(kref, struct zpci_bus, kref);
+
+	if (zbus->bus) {
+		pci_lock_rescan_remove();
+		pci_stop_root_bus(zbus->bus);
+
+		zpci_free_domain(zbus->domain_nr);
+		pci_free_resource_list(&zbus->resources);
+
+		pci_remove_root_bus(zbus->bus);
+		pci_unlock_rescan_remove();
+	}
+
+	spin_lock(&zbus_list_lock);
+	list_del(&zbus->bus_next);
+	spin_unlock(&zbus_list_lock);
+	kfree(zbus);
+}
+
+static void zpci_bus_put(struct zpci_bus *zbus)
+{
+	kref_put(&zbus->kref, zpci_bus_release);
+}
+
+static struct zpci_bus *zpci_bus_get(int pchid)
+{
+	struct zpci_bus *zbus;
+
+	spin_lock(&zbus_list_lock);
+	list_for_each_entry(zbus, &zbus_list, bus_next) {
+		if (pchid == zbus->pchid) {
+			kref_get(&zbus->kref);
+			goto out_unlock;
+		}
+	}
+	zbus = NULL;
+out_unlock:
+	spin_unlock(&zbus_list_lock);
+	return zbus;
+}
+
+static struct zpci_bus *zpci_bus_alloc(int pchid)
+{
+	struct zpci_bus *zbus;
+
+	zbus = kzalloc(sizeof(*zbus), GFP_KERNEL);
+	if (!zbus)
+		return NULL;
+
+	zbus->pchid = pchid;
+	INIT_LIST_HEAD(&zbus->bus_next);
+	spin_lock(&zbus_list_lock);
+	list_add_tail(&zbus->bus_next, &zbus_list);
+	spin_unlock(&zbus_list_lock);
+
+	kref_init(&zbus->kref);
+	INIT_LIST_HEAD(&zbus->resources);
+
+	return zbus;
+}
+
+#ifdef CONFIG_PCI_IOV
+static int zpci_bus_link_virtfn(struct pci_dev *pdev,
+		struct pci_dev *virtfn, int vfid)
+{
+	int rc;
+
+	rc = pci_iov_sysfs_link(pdev, virtfn, vfid);
+	if (rc)
+		return rc;
+
+	virtfn->is_virtfn = 1;
+	virtfn->multifunction = 0;
+	virtfn->physfn = pci_dev_get(pdev);
+
+	return 0;
+}
+
+static int zpci_bus_setup_virtfn(struct zpci_bus *zbus,
+		struct pci_dev *virtfn, int vfn)
+{
+	int i, cand_devfn;
+	struct zpci_dev *zdev;
+	struct pci_dev *pdev;
+	int vfid = vfn - 1; /* Linux' vfid's start at 0 vfn at 1*/
+	int rc = 0;
+
+	if (!zbus->multifunction)
+		return 0;
+
+	/* If the parent PF for the given VF is also configured in the
+	 * instance, it must be on the same zbus.
+	 * We can then identify the parent PF by checking what
+	 * devfn the VF would have if it belonged to that PF using the PF's
+	 * stride and offset. Only if this candidate devfn matches the
+	 * actual devfn will we link both functions.
+	 */
+	for (i = 0; i < ZPCI_FUNCTIONS_PER_BUS; i++) {
+		zdev = zbus->function[i];
+		if (zdev && zdev->is_physfn) {
+			pdev = pci_get_slot(zbus->bus, zdev->devfn);
+			if (!pdev)
+				continue;
+			cand_devfn = pci_iov_virtfn_devfn(pdev, vfid);
+			if (cand_devfn == virtfn->devfn) {
+				rc = zpci_bus_link_virtfn(pdev, virtfn, vfid);
+				/* balance pci_get_slot() */
+				pci_dev_put(pdev);
+				break;
+			}
+			/* balance pci_get_slot() */
+			pci_dev_put(pdev);
+		}
+	}
+	return rc;
+}
+#else
+static inline int zpci_bus_setup_virtfn(struct zpci_bus *zbus,
+		struct pci_dev *virtfn, int vfn)
+{
+	return 0;
+}
+#endif
+
+void pcibios_bus_add_device(struct pci_dev *pdev)
+{
+	struct zpci_dev *zdev = to_zpci(pdev);
+
+	/*
+	 * With pdev->no_vf_scan the common PCI probing code does not
+	 * perform PF/VF linking.
+	 */
+	if (zdev->vfn) {
+		zpci_bus_setup_virtfn(zdev->zbus, pdev, zdev->vfn);
+		pdev->no_command_memory = 1;
+	}
+}
+
+static int zpci_bus_add_device(struct zpci_bus *zbus, struct zpci_dev *zdev)
+{
+	struct pci_bus *bus;
+	struct resource_entry *window, *n;
+	struct resource *res;
+	struct pci_dev *pdev;
+	int rc;
+
+	bus = zbus->bus;
+	if (!bus)
+		return -EINVAL;
+
+	pdev = pci_get_slot(bus, zdev->devfn);
+	if (pdev) {
+		/* Device is already known. */
+		pci_dev_put(pdev);
+		return 0;
+	}
+
+	rc = zpci_init_slot(zdev);
+	if (rc)
+		return rc;
+	zdev->has_hp_slot = 1;
+
+	resource_list_for_each_entry_safe(window, n, &zbus->resources) {
+		res = window->res;
+		pci_bus_add_resource(bus, res, 0);
+	}
+
+	pdev = pci_scan_single_device(bus, zdev->devfn);
+	if (pdev)
+		pci_bus_add_device(pdev);
+
+	return 0;
+}
+
+static void zpci_bus_add_devices(struct zpci_bus *zbus)
+{
+	int i;
+
+	for (i = 1; i < ZPCI_FUNCTIONS_PER_BUS; i++)
+		if (zbus->function[i])
+			zpci_bus_add_device(zbus, zbus->function[i]);
+
+	pci_lock_rescan_remove();
+	pci_bus_add_devices(zbus->bus);
+	pci_unlock_rescan_remove();
+}
+
+int zpci_bus_device_register(struct zpci_dev *zdev, struct pci_ops *ops)
+{
+	struct zpci_bus *zbus = NULL;
+	int rc = -EBADF;
+
+	if (zpci_nb_devices == ZPCI_NR_DEVICES) {
+		pr_warn("Adding PCI function %08x failed because the configured limit of %d is reached\n",
+			zdev->fid, ZPCI_NR_DEVICES);
+		return -ENOSPC;
+	}
+	zpci_nb_devices++;
+
+	if (zdev->devfn >= ZPCI_FUNCTIONS_PER_BUS)
+		return -EINVAL;
+
+	if (!s390_pci_no_rid && zdev->rid_available)
+		zbus = zpci_bus_get(zdev->pchid);
+
+	if (!zbus) {
+		zbus = zpci_bus_alloc(zdev->pchid);
+		if (!zbus)
+			return -ENOMEM;
+	}
+
+	zdev->zbus = zbus;
+	if (zbus->function[zdev->devfn]) {
+		pr_err("devfn %04x is already assigned\n", zdev->devfn);
+		goto error; /* rc already set */
+	}
+	zbus->function[zdev->devfn] = zdev;
+
+	zpci_setup_bus_resources(zdev, &zbus->resources);
+
+	if (zbus->bus) {
+		if (!zbus->multifunction) {
+			WARN_ONCE(1, "zbus is not multifunction\n");
+			goto error_bus;
+		}
+		if (!zdev->rid_available) {
+			WARN_ONCE(1, "rid_available not set for multifunction\n");
+			goto error_bus;
+		}
+		rc = zpci_bus_add_device(zbus, zdev);
+		if (rc)
+			goto error_bus;
+	} else if (zdev->devfn == 0) {
+		if (zbus->multifunction && !zdev->rid_available) {
+			WARN_ONCE(1, "rid_available not set on function 0 for multifunction\n");
+			goto error_bus;
+		}
+		rc = zpci_bus_scan(zbus, (u16)zdev->uid, ops);
+		if (rc)
+			goto error_bus;
+		zpci_bus_add_devices(zbus);
+		rc = zpci_init_slot(zdev);
+		if (rc)
+			goto error_bus;
+		zdev->has_hp_slot = 1;
+		zbus->multifunction = zdev->rid_available;
+		zbus->max_bus_speed = zdev->max_bus_speed;
+	} else {
+		zbus->multifunction = 1;
+	}
+
+	return 0;
+
+error_bus:
+	zpci_nb_devices--;
+	zbus->function[zdev->devfn] = NULL;
+error:
+	pr_err("Adding PCI function %08x failed\n", zdev->fid);
+	zpci_bus_put(zbus);
+	return rc;
+}
+
+void zpci_bus_device_unregister(struct zpci_dev *zdev)
+{
+	struct zpci_bus *zbus = zdev->zbus;
+
+	zpci_nb_devices--;
+	zbus->function[zdev->devfn] = NULL;
+	zpci_bus_put(zbus);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/pci/pci_bus.h
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/pci/pci_bus.h
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright IBM Corp. 2020
+ *
+ * Author(s):
+ *   Pierre Morel <pmorel@linux.ibm.com>
+ *
+ */
+
+int zpci_bus_device_register(struct zpci_dev *zdev, struct pci_ops *ops);
+void zpci_bus_device_unregister(struct zpci_dev *zdev);
+int zpci_bus_init(void);
+
+void zpci_release_device(struct kref *kref);
+static inline void zpci_zdev_put(struct zpci_dev *zdev)
+{
+	kref_put(&zdev->kref, zpci_release_device);
+}
+
+static inline void zpci_zdev_get(struct zpci_dev *zdev)
+{
+	kref_get(&zdev->kref);
+}
+
+int zpci_alloc_domain(int domain);
+void zpci_free_domain(int domain);
+int zpci_setup_bus_resources(struct zpci_dev *zdev,
+			     struct list_head *resources);
+
+static inline struct zpci_dev *get_zdev_by_bus(struct pci_bus *bus,
+					       unsigned int devfn)
+{
+	struct zpci_bus *zbus = bus->sysdata;
+
+	return (devfn >= ZPCI_FUNCTIONS_PER_BUS) ? NULL : zbus->function[devfn];
+}
+
+#ifdef CONFIG_PCI_IOV
+static inline void zpci_remove_virtfn(struct pci_dev *pdev, int vfn)
+{
+
+	pci_lock_rescan_remove();
+	/* Linux' vfid's start at 0 vfn at 1 */
+	pci_iov_remove_virtfn(pdev->physfn, vfn - 1);
+	pci_unlock_rescan_remove();
+}
+#else /* CONFIG_PCI_IOV */
+static inline void zpci_remove_virtfn(struct pci_dev *pdev, int vfn) {}
+#endif /* CONFIG_PCI_IOV */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/pci/pci_clp.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/pci/pci_clp.c
@@ -24,7 +24,7 @@
 
 bool zpci_unique_uid;
 
-static void update_uid_checking(bool new)
+void update_uid_checking(bool new)
 {
 	if (zpci_unique_uid != new)
 		zpci_dbg(1, "uid checking:%d\n", new);
@@ -155,8 +155,13 @@
 	zdev->pfgid = response->pfgid;
 	zdev->pft = response->pft;
 	zdev->vfn = response->vfn;
+	zdev->port = response->port;
 	zdev->uid = response->uid;
 	zdev->fmb_length = sizeof(u32) * response->fmb_len;
+	zdev->rid_available = response->rid_avail;
+	zdev->is_physfn = response->is_physfn;
+	if (!s390_pci_no_rid && zdev->rid_available)
+		zdev->devfn = response->rid & ZPCI_RID_MASK_DEVFN;
 
 	memcpy(zdev->pfip, response->pfip, sizeof(zdev->pfip));
 	if (response->util_str_avail) {
@@ -240,12 +245,14 @@
 }
 
 /*
- * Enable/Disable a given PCI function defined by its function handle.
+ * Enable/Disable a given PCI function and update its function handle if
+ * necessary
  */
-static int clp_set_pci_fn(u32 *fh, u8 nr_dma_as, u8 command)
+static int clp_set_pci_fn(struct zpci_dev *zdev, u8 nr_dma_as, u8 command)
 {
 	struct clp_req_rsp_set_pci *rrb;
 	int rc, retries = 100;
+	u32 fid = zdev->fid;
 
 	rrb = clp_alloc_block(GFP_KERNEL);
 	if (!rrb)
@@ -256,7 +263,7 @@
 		rrb->request.hdr.len = sizeof(rrb->request);
 		rrb->request.hdr.cmd = CLP_SET_PCI_FN;
 		rrb->response.hdr.len = sizeof(rrb->response);
-		rrb->request.fh = *fh;
+		rrb->request.fh = zdev->fh;
 		rrb->request.oc = command;
 		rrb->request.ndas = nr_dma_as;
 
@@ -269,12 +276,17 @@
 		}
 	} while (rrb->response.hdr.rsp == CLP_RC_SETPCIFN_BUSY);
 
-	if (!rc && rrb->response.hdr.rsp == CLP_RC_OK)
-		*fh = rrb->response.fh;
-	else {
+	if (rc || rrb->response.hdr.rsp != CLP_RC_OK) {
 		zpci_err("Set PCI FN:\n");
 		zpci_err_clp(rrb->response.hdr.rsp, rc);
-		rc = -EIO;
+	}
+
+	if (!rc && rrb->response.hdr.rsp == CLP_RC_OK) {
+		zdev->fh = rrb->response.fh;
+	} else if (!rc && rrb->response.hdr.rsp == CLP_RC_SETPCIFN_ALRDY &&
+			rrb->response.fh == 0) {
+		/* Function is already in desired state - update handle */
+		rc = clp_rescan_pci_devices_simple(&fid);
 	}
 	clp_free_block(rrb);
 	return rc;
@@ -282,18 +294,17 @@
 
 int clp_enable_fh(struct zpci_dev *zdev, u8 nr_dma_as)
 {
-	u32 fh = zdev->fh;
 	int rc;
 
-	rc = clp_set_pci_fn(&fh, nr_dma_as, CLP_SET_ENABLE_PCI_FN);
-	zpci_dbg(3, "ena fid:%x, fh:%x, rc:%d\n", zdev->fid, fh, rc);
+	rc = clp_set_pci_fn(zdev, nr_dma_as, CLP_SET_ENABLE_PCI_FN);
+	zpci_dbg(3, "ena fid:%x, fh:%x, rc:%d\n", zdev->fid, zdev->fh, rc);
 	if (rc)
 		goto out;
 
-	zdev->fh = fh;
 	if (zpci_use_mio(zdev)) {
-		rc = clp_set_pci_fn(&fh, nr_dma_as, CLP_SET_ENABLE_MIO);
-		zpci_dbg(3, "ena mio fid:%x, fh:%x, rc:%d\n", zdev->fid, fh, rc);
+		rc = clp_set_pci_fn(zdev, nr_dma_as, CLP_SET_ENABLE_MIO);
+		zpci_dbg(3, "ena mio fid:%x, fh:%x, rc:%d\n",
+				zdev->fid, zdev->fh, rc);
 		if (rc)
 			clp_disable_fh(zdev);
 	}
@@ -303,17 +314,13 @@
 
 int clp_disable_fh(struct zpci_dev *zdev)
 {
-	u32 fh = zdev->fh;
 	int rc;
 
 	if (!zdev_enabled(zdev))
 		return 0;
 
-	rc = clp_set_pci_fn(&fh, 0, CLP_SET_DISABLE_PCI_FN);
-	zpci_dbg(3, "dis fid:%x, fh:%x, rc:%d\n", zdev->fid, fh, rc);
-	if (!rc)
-		zdev->fh = fh;
-
+	rc = clp_set_pci_fn(zdev, 0, CLP_SET_DISABLE_PCI_FN);
+	zpci_dbg(3, "dis fid:%x, fh:%x, rc:%d\n", zdev->fid, zdev->fh, rc);
 	return rc;
 }
 
@@ -370,10 +377,14 @@
 static void __clp_update(struct clp_fh_list_entry *entry, void *data)
 {
 	struct zpci_dev *zdev;
+	u32 *fid = data;
 
 	if (!entry->vendor_id)
 		return;
 
+	if (fid && *fid != entry->fid)
+		return;
+
 	zdev = get_zdev_by_fid(entry->fid);
 	if (!zdev)
 		return;
@@ -413,7 +424,10 @@
 	return rc;
 }
 
-int clp_rescan_pci_devices_simple(void)
+/* Rescan PCI functions and refresh function handles. If fid is non-NULL only
+ * refresh the handle of the function matching @fid
+ */
+int clp_rescan_pci_devices_simple(u32 *fid)
 {
 	struct clp_req_rsp_list_pci *rrb;
 	int rc;
@@ -422,7 +436,7 @@
 	if (!rrb)
 		return -ENOMEM;
 
-	rc = clp_list_pci(rrb, NULL, __clp_update);
+	rc = clp_list_pci(rrb, fid, __clp_update);
 
 	clp_free_block(rrb);
 	return rc;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/pci/pci_dma.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/pci/pci_dma.c
@@ -543,6 +543,17 @@
 		s->dma_length = 0;
 	}
 }
+
+static unsigned long *bitmap_vzalloc(size_t bits, gfp_t flags)
+{
+	size_t n = BITS_TO_LONGS(bits);
+	size_t bytes;
+
+	if (unlikely(check_mul_overflow(n, sizeof(unsigned long), &bytes)))
+		return NULL;
+
+	return vzalloc(bytes);
+}
 	
 int zpci_dma_init_device(struct zpci_dev *zdev)
 {
@@ -579,13 +590,13 @@
 				zdev->end_dma - zdev->start_dma + 1);
 	zdev->end_dma = zdev->start_dma + zdev->iommu_size - 1;
 	zdev->iommu_pages = zdev->iommu_size >> PAGE_SHIFT;
-	zdev->iommu_bitmap = vzalloc(zdev->iommu_pages / 8);
+	zdev->iommu_bitmap = bitmap_vzalloc(zdev->iommu_pages, GFP_KERNEL);
 	if (!zdev->iommu_bitmap) {
 		rc = -ENOMEM;
 		goto free_dma_table;
 	}
 	if (!s390_iommu_strict) {
-		zdev->lazy_bitmap = vzalloc(zdev->iommu_pages / 8);
+		zdev->lazy_bitmap = bitmap_vzalloc(zdev->iommu_pages, GFP_KERNEL);
 		if (!zdev->lazy_bitmap) {
 			rc = -ENOMEM;
 			goto free_bitmap;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/pci/pci_event.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/pci/pci_event.c
@@ -14,6 +14,8 @@
 #include <asm/pci_debug.h>
 #include <asm/sclp.h>
 
+#include "pci_bus.h"
+
 /* Content Code Description for PCI Function Error */
 struct zpci_ccdf_err {
 	u32 reserved1;
@@ -53,7 +55,7 @@
 	zpci_err_hex(ccdf, sizeof(*ccdf));
 
 	if (zdev)
-		pdev = pci_get_slot(zdev->bus, ZPCI_DEVFN);
+		pdev = pci_get_slot(zdev->zbus->bus, zdev->devfn);
 
 	pr_err("%s: Event 0x%x reports an error for PCI function 0x%x\n",
 	       pdev ? pci_name(pdev) : "n/a", ccdf->pec, ccdf->fid);
@@ -74,46 +76,52 @@
 static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
 {
 	struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid);
-	struct pci_dev *pdev = NULL;
 	enum zpci_state state;
+	struct pci_dev *pdev;
 	int ret;
 
-	if (zdev)
-		pdev = pci_get_slot(zdev->bus, ZPCI_DEVFN);
-
-	pr_info("%s: Event 0x%x reconfigured PCI function 0x%x\n",
-		pdev ? pci_name(pdev) : "n/a", ccdf->pec, ccdf->fid);
 	zpci_err("avail CCDF:\n");
 	zpci_err_hex(ccdf, sizeof(*ccdf));
 
 	switch (ccdf->pec) {
 	case 0x0301: /* Reserved|Standby -> Configured */
 		if (!zdev) {
-			ret = clp_add_pci_device(ccdf->fid, ccdf->fh, 0);
-			if (ret)
-				break;
-			zdev = get_zdev_by_fid(ccdf->fid);
+			ret = clp_add_pci_device(ccdf->fid, ccdf->fh, 1);
+			break;
 		}
-		if (!zdev || zdev->state != ZPCI_FN_STATE_STANDBY)
+		/* the configuration request may be stale */
+		if (zdev->state != ZPCI_FN_STATE_STANDBY)
 			break;
-		zdev->state = ZPCI_FN_STATE_CONFIGURED;
 		zdev->fh = ccdf->fh;
+		zdev->state = ZPCI_FN_STATE_CONFIGURED;
 		ret = zpci_enable_device(zdev);
 		if (ret)
 			break;
+
+		/* the PCI function will be scanned once function 0 appears */
+		if (!zdev->zbus->bus)
+			break;
+
+		pdev = pci_scan_single_device(zdev->zbus->bus, zdev->devfn);
+		if (!pdev)
+			break;
+
+		pci_bus_add_device(pdev);
 		pci_lock_rescan_remove();
-		pci_rescan_bus(zdev->bus);
+		pci_bus_add_devices(zdev->zbus->bus);
 		pci_unlock_rescan_remove();
 		break;
 	case 0x0302: /* Reserved -> Standby */
-		if (!zdev)
+		if (!zdev) {
 			clp_add_pci_device(ccdf->fid, ccdf->fh, 0);
+			break;
+		}
+		zdev->fh = ccdf->fh;
 		break;
 	case 0x0303: /* Deconfiguration requested */
 		if (!zdev)
 			break;
-		if (pdev)
-			pci_stop_and_remove_bus_device_locked(pdev);
+		zpci_remove_device(zdev, false);
 
 		ret = zpci_disable_device(zdev);
 		if (ret)
@@ -128,19 +136,17 @@
 	case 0x0304: /* Configured -> Standby|Reserved */
 		if (!zdev)
 			break;
-		if (pdev) {
-			/* Give the driver a hint that the function is
-			 * already unusable. */
-			pdev->error_state = pci_channel_io_perm_failure;
-			pci_stop_and_remove_bus_device_locked(pdev);
-		}
+		/* Give the driver a hint that the function is
+		 * already unusable.
+		 */
+		zpci_remove_device(zdev, true);
 
 		zdev->fh = ccdf->fh;
 		zpci_disable_device(zdev);
 		zdev->state = ZPCI_FN_STATE_STANDBY;
 		if (!clp_get_state(ccdf->fid, &state) &&
 		    state == ZPCI_FN_STATE_RESERVED) {
-			zpci_remove_device(zdev);
+			zpci_device_reserved(zdev);
 		}
 		break;
 	case 0x0306: /* 0x308 or 0x302 for multiple devices */
@@ -149,12 +155,11 @@
 	case 0x0308: /* Standby -> Reserved */
 		if (!zdev)
 			break;
-		zpci_remove_device(zdev);
+		zpci_device_reserved(zdev);
 		break;
 	default:
 		break;
 	}
-	pci_dev_put(pdev);
 }
 
 void zpci_event_availability(void *data)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/pci/pci_irq.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/pci/pci_irq.c
@@ -115,7 +115,6 @@
 	.name = "PCI-MSI",
 	.irq_unmask = pci_msi_unmask_irq,
 	.irq_mask = pci_msi_mask_irq,
-	.irq_set_affinity = zpci_set_irq_affinity,
 };
 
 static void zpci_handle_cpu_local_irq(bool rescan)
@@ -276,7 +275,9 @@
 		rc = -EIO;
 		if (hwirq - bit >= msi_vecs)
 			break;
-		irq = __irq_alloc_descs(-1, 0, 1, 0, THIS_MODULE, msi->affinity);
+		irq = __irq_alloc_descs(-1, 0, 1, 0, THIS_MODULE,
+				(irq_delivery == DIRECTED) ?
+				msi->affinity : NULL);
 		if (irq < 0)
 			return -ENOMEM;
 		rc = irq_set_msi_desc(irq, msi);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/pci/pci_mmio.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/pci/pci_mmio.c
@@ -11,6 +11,113 @@
 #include <linux/mm.h>
 #include <linux/errno.h>
 #include <linux/pci.h>
+#include <asm/pci_io.h>
+#include <asm/pci_debug.h>
+
+static inline void zpci_err_mmio(u8 cc, u8 status, u64 offset)
+{
+	struct {
+		u64 offset;
+		u8 cc;
+		u8 status;
+	} data = {offset, cc, status};
+
+	zpci_err_hex(&data, sizeof(data));
+}
+
+static inline int __pcistb_mio_inuser(
+		void __iomem *ioaddr, const void __user *src,
+		u64 len, u8 *status)
+{
+	int cc = -ENXIO;
+
+	asm volatile (
+		"       sacf 256\n"
+		"0:     .insn   rsy,0xeb00000000d4,%[len],%[ioaddr],%[src]\n"
+		"1:     ipm     %[cc]\n"
+		"       srl     %[cc],28\n"
+		"2:     sacf 768\n"
+		EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
+		: [cc] "+d" (cc), [len] "+d" (len)
+		: [ioaddr] "a" (ioaddr), [src] "Q" (*((u8 __force *)src))
+		: "cc", "memory");
+	*status = len >> 24 & 0xff;
+	return cc;
+}
+
+static inline int __pcistg_mio_inuser(
+		void __iomem *ioaddr, const void __user *src,
+		u64 ulen, u8 *status)
+{
+	register u64 addr asm("2") = (u64 __force) ioaddr;
+	register u64 len asm("3") = ulen;
+	int cc = -ENXIO;
+	u64 val = 0;
+	u64 cnt = ulen;
+	u8 tmp;
+
+	/*
+	 * copy 0 < @len <= 8 bytes from @src into the right most bytes of
+	 * a register, then store it to PCI at @ioaddr while in secondary
+	 * address space. pcistg then uses the user mappings.
+	 */
+	asm volatile (
+		"       sacf    256\n"
+		"0:     llgc    %[tmp],0(%[src])\n"
+		"4:	sllg	%[val],%[val],8\n"
+		"       aghi    %[src],1\n"
+		"       ogr     %[val],%[tmp]\n"
+		"       brctg   %[cnt],0b\n"
+		"1:     .insn   rre,0xb9d40000,%[val],%[ioaddr]\n"
+		"2:     ipm     %[cc]\n"
+		"       srl     %[cc],28\n"
+		"3:     sacf    768\n"
+		EX_TABLE(0b, 3b) EX_TABLE(4b, 3b) EX_TABLE(1b, 3b) EX_TABLE(2b, 3b)
+		:
+		[src] "+a" (src), [cnt] "+d" (cnt),
+		[val] "+d" (val), [tmp] "=d" (tmp),
+		[len] "+d" (len), [cc] "+d" (cc),
+		[ioaddr] "+a" (addr)
+		:: "cc", "memory");
+	*status = len >> 24 & 0xff;
+
+	/* did we read everything from user memory? */
+	if (!cc && cnt != 0)
+		cc = -EFAULT;
+
+	return cc;
+}
+
+static inline int __memcpy_toio_inuser(void __iomem *dst,
+				   const void __user *src, size_t n)
+{
+	int size, rc = 0;
+	u8 status = 0;
+	mm_segment_t old_fs;
+
+	if (!src)
+		return -EINVAL;
+
+	old_fs = enable_sacf_uaccess();
+	while (n > 0) {
+		size = zpci_get_max_io_size((u64 __force) dst,
+					    (u64 __force) src, n,
+					    ZPCI_MAX_WRITE_SIZE);
+		if (size > 8) /* main path */
+			rc = __pcistb_mio_inuser(dst, src, size, &status);
+		else
+			rc = __pcistg_mio_inuser(dst, src, size, &status);
+		if (rc)
+			break;
+		src += size;
+		dst += size;
+		n -= size;
+	}
+	disable_sacf_uaccess(old_fs);
+	if (rc)
+		zpci_err_mmio(rc, status, (__force u64) dst);
+	return rc;
+}
 
 static long get_pfn(unsigned long user_addr, unsigned long access,
 		    unsigned long *pfn)
@@ -21,7 +128,7 @@
 	down_read(&current->mm->mmap_sem);
 	ret = -EINVAL;
 	vma = find_vma(current->mm, user_addr);
-	if (!vma)
+	if (!vma || user_addr < vma->vm_start)
 		goto out;
 	ret = -EACCES;
 	if (!(vma->vm_flags & access))
@@ -46,6 +153,20 @@
 
 	if (length <= 0 || PAGE_SIZE - (mmio_addr & ~PAGE_MASK) < length)
 		return -EINVAL;
+
+	/*
+	 * Only support read access to MIO capable devices on a MIO enabled
+	 * system. Otherwise we would have to check for every address if it is
+	 * a special ZPCI_ADDR and we would have to do a get_pfn() which we
+	 * don't need for MIO capable devices.
+	 */
+	if (static_branch_likely(&have_mio)) {
+		ret = __memcpy_toio_inuser((void  __iomem *) mmio_addr,
+					user_buffer,
+					length);
+		return ret;
+	}
+
 	if (length > 64) {
 		buf = kmalloc(length, GFP_KERNEL);
 		if (!buf)
@@ -56,7 +177,8 @@
 	ret = get_pfn(mmio_addr, VM_WRITE, &pfn);
 	if (ret)
 		goto out;
-	io_addr = (void __iomem *)((pfn << PAGE_SHIFT) | (mmio_addr & ~PAGE_MASK));
+	io_addr = (void __iomem *)((pfn << PAGE_SHIFT) |
+			(mmio_addr & ~PAGE_MASK));
 
 	ret = -EFAULT;
 	if ((unsigned long) io_addr < ZPCI_IOMAP_ADDR_BASE)
@@ -72,6 +194,78 @@
 	return ret;
 }
 
+static inline int __pcilg_mio_inuser(
+		void __user *dst, const void __iomem *ioaddr,
+		u64 ulen, u8 *status)
+{
+	register u64 addr asm("2") = (u64 __force) ioaddr;
+	register u64 len asm("3") = ulen;
+	u64 cnt = ulen;
+	int shift = ulen * 8;
+	int cc = -ENXIO;
+	u64 val, tmp;
+
+	/*
+	 * read 0 < @len <= 8 bytes from the PCI memory mapped at @ioaddr (in
+	 * user space) into a register using pcilg then store these bytes at
+	 * user address @dst
+	 */
+	asm volatile (
+		"       sacf    256\n"
+		"0:     .insn   rre,0xb9d60000,%[val],%[ioaddr]\n"
+		"1:     ipm     %[cc]\n"
+		"       srl     %[cc],28\n"
+		"       ltr     %[cc],%[cc]\n"
+		"       jne     4f\n"
+		"2:     ahi     %[shift],-8\n"
+		"       srlg    %[tmp],%[val],0(%[shift])\n"
+		"3:     stc     %[tmp],0(%[dst])\n"
+		"5:	aghi	%[dst],1\n"
+		"       brctg   %[cnt],2b\n"
+		"4:     sacf    768\n"
+		EX_TABLE(0b, 4b) EX_TABLE(1b, 4b) EX_TABLE(3b, 4b) EX_TABLE(5b, 4b)
+		:
+		[cc] "+d" (cc), [val] "=d" (val), [len] "+d" (len),
+		[dst] "+a" (dst), [cnt] "+d" (cnt), [tmp] "=d" (tmp),
+		[shift] "+d" (shift)
+		:
+		[ioaddr] "a" (addr)
+		: "cc", "memory");
+
+	/* did we write everything to the user space buffer? */
+	if (!cc && cnt != 0)
+		cc = -EFAULT;
+
+	*status = len >> 24 & 0xff;
+	return cc;
+}
+
+static inline int __memcpy_fromio_inuser(void __user *dst,
+				     const void __iomem *src,
+				     unsigned long n)
+{
+	int size, rc = 0;
+	u8 status;
+	mm_segment_t old_fs;
+
+	old_fs = enable_sacf_uaccess();
+	while (n > 0) {
+		size = zpci_get_max_io_size((u64 __force) src,
+					    (u64 __force) dst, n,
+					    ZPCI_MAX_READ_SIZE);
+		rc = __pcilg_mio_inuser(dst, src, size, &status);
+		if (rc)
+			break;
+		src += size;
+		dst += size;
+		n -= size;
+	}
+	disable_sacf_uaccess(old_fs);
+	if (rc)
+		zpci_err_mmio(rc, status, (__force u64) dst);
+	return rc;
+}
+
 SYSCALL_DEFINE3(s390_pci_mmio_read, unsigned long, mmio_addr,
 		void __user *, user_buffer, size_t, length)
 {
@@ -86,12 +280,27 @@
 
 	if (length <= 0 || PAGE_SIZE - (mmio_addr & ~PAGE_MASK) < length)
 		return -EINVAL;
+
+	/*
+	 * Only support write access to MIO capable devices on a MIO enabled
+	 * system. Otherwise we would have to check for every address if it is
+	 * a special ZPCI_ADDR and we would have to do a get_pfn() which we
+	 * don't need for MIO capable devices.
+	 */
+	if (static_branch_likely(&have_mio)) {
+		ret = __memcpy_fromio_inuser(
+				user_buffer, (const void __iomem *)mmio_addr,
+				length);
+		return ret;
+	}
+
 	if (length > 64) {
 		buf = kmalloc(length, GFP_KERNEL);
 		if (!buf)
 			return -ENOMEM;
-	} else
+	} else {
 		buf = local_buf;
+	}
 
 	ret = get_pfn(mmio_addr, VM_READ, &pfn);
 	if (ret)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/pci/pci_sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/pci/pci_sysfs.c
@@ -13,6 +13,8 @@
 #include <linux/stat.h>
 #include <linux/pci.h>
 
+#include "../../../drivers/pci/pci.h"
+
 #include <asm/sclp.h>
 
 #define zpci_attr(name, fmt, member)					\
@@ -31,6 +33,7 @@
 zpci_attr(pfgid, "0x%02x\n", pfgid);
 zpci_attr(vfn, "0x%04x\n", vfn);
 zpci_attr(pft, "0x%02x\n", pft);
+zpci_attr(port, "%d\n", port);
 zpci_attr(uid, "0x%x\n", uid);
 zpci_attr(segment0, "0x%02x\n", pfip[0]);
 zpci_attr(segment1, "0x%02x\n", pfip[1]);
@@ -49,31 +52,50 @@
 static ssize_t recover_store(struct device *dev, struct device_attribute *attr,
 			     const char *buf, size_t count)
 {
+	struct kernfs_node *kn;
 	struct pci_dev *pdev = to_pci_dev(dev);
 	struct zpci_dev *zdev = to_zpci(pdev);
-	int ret;
-
-	if (!device_remove_file_self(dev, attr))
-		return count;
+	int ret = 0;
 
+	/* Can't use device_remove_self() here as that would lead us to lock
+	 * the pci_rescan_remove_lock while holding the device' kernfs lock.
+	 * This would create a possible deadlock with disable_slot() which is
+	 * not directly protected by the device' kernfs lock but takes it
+	 * during the device removal which happens under
+	 * pci_rescan_remove_lock.
+	 *
+	 * This is analogous to sdev_store_delete() in
+	 * drivers/scsi/scsi_sysfs.c
+	 */
+	kn = sysfs_break_active_protection(&dev->kobj, &attr->attr);
+	WARN_ON_ONCE(!kn);
+	/* device_remove_file() serializes concurrent calls ignoring all but
+	 * the first
+	 */
+	device_remove_file(dev, attr);
+
+	/* A concurrent call to recover_store() may slip between
+	 * sysfs_break_active_protection() and the sysfs file removal.
+	 * Once it unblocks from pci_lock_rescan_remove() the original pdev
+	 * will already be removed.
+	 */
 	pci_lock_rescan_remove();
-	pci_stop_and_remove_bus_device(pdev);
-	ret = zpci_disable_device(zdev);
-	if (ret)
-		goto error;
-
-	ret = zpci_enable_device(zdev);
-	if (ret)
-		goto error;
-
-	pci_rescan_bus(zdev->bus);
+	if (pci_dev_is_added(pdev)) {
+		pci_stop_and_remove_bus_device(pdev);
+		ret = zpci_disable_device(zdev);
+		if (ret)
+			goto out;
+
+		ret = zpci_enable_device(zdev);
+		if (ret)
+			goto out;
+		pci_rescan_bus(zdev->zbus->bus);
+	}
+out:
 	pci_unlock_rescan_remove();
-
-	return count;
-
-error:
-	pci_unlock_rescan_remove();
-	return ret;
+	if (kn)
+		sysfs_unbreak_active_protection(kn);
+	return ret ? ret : count;
 }
 static DEVICE_ATTR_WO(recover);
 
@@ -121,6 +143,7 @@
 	&dev_attr_pchid.attr,
 	&dev_attr_pfgid.attr,
 	&dev_attr_pft.attr,
+	&dev_attr_port.attr,
 	&dev_attr_vfn.attr,
 	&dev_attr_uid.attr,
 	&dev_attr_recover.attr,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/purgatory/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/purgatory/Makefile
@@ -15,8 +15,10 @@
 $(obj)/mem.o: $(srctree)/arch/s390/lib/mem.S FORCE
 	$(call if_changed_rule,as_o_S)
 
-$(obj)/string.o: $(srctree)/arch/s390/lib/string.c FORCE
-	$(call if_changed_rule,cc_o_c)
+KCOV_INSTRUMENT := n
+GCOV_PROFILE := n
+UBSAN_SANITIZE := n
+KASAN_SANITIZE := n
 
 KBUILD_CFLAGS := -fno-strict-aliasing -Wall -Wstrict-prototypes
 KBUILD_CFLAGS += -Wno-pointer-sign -Wno-sign-compare
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/purgatory/head.S
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/purgatory/head.S
@@ -62,14 +62,15 @@
 	jh	10b
 .endm
 
-.macro START_NEXT_KERNEL base
+.macro START_NEXT_KERNEL base subcode
 	lg	%r4,kernel_entry-\base(%r13)
 	lg	%r5,load_psw_mask-\base(%r13)
 	ogr	%r4,%r5
 	stg	%r4,0(%r0)
 
 	xgr	%r0,%r0
-	diag	%r0,%r0,0x308
+	lghi	%r1,\subcode
+	diag	%r0,%r1,0x308
 .endm
 
 .text
@@ -123,7 +124,7 @@
 	je	.start_crash_kernel
 
 	/* start normal kernel */
-	START_NEXT_KERNEL .base_crash
+	START_NEXT_KERNEL .base_crash 0
 
 .return_old_kernel:
 	lmg	%r6,%r15,gprregs-.base_crash(%r13)
@@ -227,7 +228,7 @@
 	MEMCPY	%r9,%r10,%r11
 
 	/* start crash kernel */
-	START_NEXT_KERNEL .base_dst
+	START_NEXT_KERNEL .base_dst 1
 
 
 load_psw_mask:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/s390/purgatory/string.c
+++ linux-xilinx-zynqmp-5.4.0/arch/s390/purgatory/string.c
@@ -0,0 +1,3 @@
+// SPDX-License-Identifier: GPL-2.0
+#define __HAVE_ARCH_MEMCMP	/* arch function */
+#include "../lib/string.c"
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/Kconfig
@@ -2,6 +2,7 @@
 config SUPERH
 	def_bool y
 	select ARCH_HAS_BINFMT_FLAT if !MMU
+	select ARCH_HAS_CPU_FINALIZE_INIT
 	select ARCH_HAS_PTE_SPECIAL
 	select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
 	select ARCH_MIGHT_HAVE_PC_PARPORT
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/Kconfig.debug
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/Kconfig.debug
@@ -26,6 +26,17 @@
 	  every function call and will therefore incur a major
 	  performance hit. Most users should say N.
 
+config EARLY_PRINTK
+	bool "Early printk"
+	depends on SH_STANDARD_BIOS
+	help
+	  Say Y here to redirect kernel printk messages to the serial port
+	  used by the SH-IPL bootloader, starting very early in the boot
+	  process and ending when the kernel's serial console is initialised.
+	  This option is only useful while porting the kernel to a new machine,
+	  when the kernel may crash or hang before the serial console is
+	  initialised.  If unsure, say N.
+
 config 4KSTACKS
 	bool "Use 4Kb for kernel stacks instead of 8Kb"
 	depends on DEBUG_KERNEL && (MMU || BROKEN) && !PAGE_SIZE_64KB
@@ -58,6 +69,7 @@
 
 config DWARF_UNWINDER
 	bool "Enable the DWARF unwinder for stacktraces"
+	depends on DEBUG_KERNEL
 	select FRAME_POINTER
 	depends on SUPERH32
 	default n
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/boards/mach-ap325rxa/setup.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/boards/mach-ap325rxa/setup.c
@@ -529,7 +529,7 @@
 	device_initialize(&ap325rxa_ceu_device.dev);
 	dma_declare_coherent_memory(&ap325rxa_ceu_device.dev,
 			ceu_dma_membase, ceu_dma_membase,
-			ceu_dma_membase + CEU_BUFFER_MEMORY_SIZE - 1);
+			CEU_BUFFER_MEMORY_SIZE);
 
 	platform_device_add(&ap325rxa_ceu_device);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/boards/mach-ecovec24/setup.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/boards/mach-ecovec24/setup.c
@@ -1442,15 +1442,13 @@
 	device_initialize(&ecovec_ceu_devices[0]->dev);
 	dma_declare_coherent_memory(&ecovec_ceu_devices[0]->dev,
 				    ceu0_dma_membase, ceu0_dma_membase,
-				    ceu0_dma_membase +
-				    CEU_BUFFER_MEMORY_SIZE - 1);
+				    CEU_BUFFER_MEMORY_SIZE);
 	platform_device_add(ecovec_ceu_devices[0]);
 
 	device_initialize(&ecovec_ceu_devices[1]->dev);
 	dma_declare_coherent_memory(&ecovec_ceu_devices[1]->dev,
 				    ceu1_dma_membase, ceu1_dma_membase,
-				    ceu1_dma_membase +
-				    CEU_BUFFER_MEMORY_SIZE - 1);
+				    CEU_BUFFER_MEMORY_SIZE);
 	platform_device_add(ecovec_ceu_devices[1]);
 
 	gpiod_add_lookup_table(&cn12_power_gpiod_table);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/boards/mach-kfr2r09/setup.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/boards/mach-kfr2r09/setup.c
@@ -603,7 +603,7 @@
 	device_initialize(&kfr2r09_ceu_device.dev);
 	dma_declare_coherent_memory(&kfr2r09_ceu_device.dev,
 			ceu_dma_membase, ceu_dma_membase,
-			ceu_dma_membase + CEU_BUFFER_MEMORY_SIZE - 1);
+			CEU_BUFFER_MEMORY_SIZE);
 
 	platform_device_add(&kfr2r09_ceu_device);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/boards/mach-landisk/setup.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/boards/mach-landisk/setup.c
@@ -82,6 +82,9 @@
 
 static void __init landisk_setup(char **cmdline_p)
 {
+	/* I/O port identity mapping */
+	__set_io_port_base(0);
+
 	/* LED ON */
 	__raw_writeb(__raw_readb(PA_LED) | 0x03, PA_LED);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/boards/mach-migor/setup.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/boards/mach-migor/setup.c
@@ -604,7 +604,7 @@
 	device_initialize(&migor_ceu_device.dev);
 	dma_declare_coherent_memory(&migor_ceu_device.dev,
 			ceu_dma_membase, ceu_dma_membase,
-			ceu_dma_membase + CEU_BUFFER_MEMORY_SIZE - 1);
+			CEU_BUFFER_MEMORY_SIZE);
 
 	platform_device_add(&migor_ceu_device);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/boards/mach-se/7724/setup.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/boards/mach-se/7724/setup.c
@@ -939,15 +939,13 @@
 	device_initialize(&ms7724se_ceu_devices[0]->dev);
 	dma_declare_coherent_memory(&ms7724se_ceu_devices[0]->dev,
 				    ceu0_dma_membase, ceu0_dma_membase,
-				    ceu0_dma_membase +
-				    CEU_BUFFER_MEMORY_SIZE - 1);
+				    CEU_BUFFER_MEMORY_SIZE);
 	platform_device_add(ms7724se_ceu_devices[0]);
 
 	device_initialize(&ms7724se_ceu_devices[1]->dev);
 	dma_declare_coherent_memory(&ms7724se_ceu_devices[1]->dev,
 				    ceu1_dma_membase, ceu1_dma_membase,
-				    ceu1_dma_membase +
-				    CEU_BUFFER_MEMORY_SIZE - 1);
+				    CEU_BUFFER_MEMORY_SIZE);
 	platform_device_add(ms7724se_ceu_devices[1]);
 
 	return platform_add_devices(ms7724se_devices,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/configs/sh03_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/configs/sh03_defconfig
@@ -46,7 +46,6 @@
 CONFIG_SCSI=m
 CONFIG_BLK_DEV_SD=m
 CONFIG_BLK_DEV_SR=m
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/drivers/dma/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/drivers/dma/Kconfig
@@ -63,8 +63,7 @@
 
 config G2_DMA
 	tristate "G2 Bus DMA support"
-	depends on SH_DREAMCAST
-	select SH_DMA_API
+	depends on SH_DREAMCAST && SH_DMA_API
 	help
 	  This enables support for the DMA controller for the Dreamcast's
 	  G2 bus. Drivers that want this will generally enable this on
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/drivers/dma/dma-sh.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/drivers/dma/dma-sh.c
@@ -19,6 +19,18 @@
 #include <cpu/dma.h>
 
 /*
+ * Some of the SoCs feature two DMAC modules. In such a case, the channels are
+ * distributed equally among them.
+ */
+#ifdef	SH_DMAC_BASE1
+#define	SH_DMAC_NR_MD_CH	(CONFIG_NR_ONCHIP_DMA_CHANNELS / 2)
+#else
+#define	SH_DMAC_NR_MD_CH	CONFIG_NR_ONCHIP_DMA_CHANNELS
+#endif
+
+#define	SH_DMAC_CH_SZ		0x10
+
+/*
  * Define the default configuration for dual address memory-memory transfer.
  * The 0x400 value represents auto-request, external->external.
  */
@@ -29,7 +41,7 @@
 	unsigned long base = SH_DMAC_BASE0;
 
 #ifdef SH_DMAC_BASE1
-	if (chan >= 6)
+	if (chan >= SH_DMAC_NR_MD_CH)
 		base = SH_DMAC_BASE1;
 #endif
 
@@ -40,13 +52,13 @@
 {
 	unsigned long base = dma_find_base(chan);
 
-	/* Normalize offset calculation */
-	if (chan >= 9)
-		chan -= 6;
-	if (chan >= 4)
-		base += 0x10;
+	chan = (chan % SH_DMAC_NR_MD_CH) * SH_DMAC_CH_SZ;
+
+	/* DMAOR is placed inside the channel register space. Step over it. */
+	if (chan >= DMAOR)
+		base += SH_DMAC_CH_SZ;
 
-	return base + (chan * 0x10);
+	return base + chan;
 }
 
 #ifdef CONFIG_SH_DMA_IRQ_MULTI
@@ -250,12 +262,11 @@
 #define NR_DMAOR	1
 #endif
 
-/*
- * DMAOR bases are broken out amongst channel groups. DMAOR0 manages
- * channels 0 - 5, DMAOR1 6 - 11 (optional).
- */
-#define dmaor_read_reg(n)		__raw_readw(dma_find_base((n)*6))
-#define dmaor_write_reg(n, data)	__raw_writew(data, dma_find_base(n)*6)
+#define dmaor_read_reg(n)		__raw_readw(dma_find_base((n) * \
+						    SH_DMAC_NR_MD_CH) + DMAOR)
+#define dmaor_write_reg(n, data)	__raw_writew(data, \
+						     dma_find_base((n) * \
+						     SH_DMAC_NR_MD_CH) + DMAOR)
 
 static inline int dmaor_reset(int no)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/drivers/push-switch.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/drivers/push-switch.c
@@ -101,8 +101,8 @@
 		device_remove_file(&pdev->dev, &dev_attr_switch);
 
 	platform_set_drvdata(pdev, NULL);
-	flush_work(&psw->work);
 	del_timer_sync(&psw->debounce);
+	flush_work(&psw->work);
 	free_irq(irq, pdev);
 
 	kfree(psw);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/include/asm/pgalloc.h
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/include/asm/pgalloc.h
@@ -12,6 +12,7 @@
 extern void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd);
 extern pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address);
 extern void pmd_free(struct mm_struct *mm, pmd_t *pmd);
+#define __pmd_free_tlb(tlb, pmdp, addr)		pmd_free((tlb)->mm, (pmdp))
 #endif
 
 static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd,
@@ -33,13 +34,4 @@
 	tlb_remove_page((tlb), (pte));			\
 } while (0)
 
-#if CONFIG_PGTABLE_LEVELS > 2
-#define __pmd_free_tlb(tlb, pmdp, addr)			\
-do {							\
-	struct page *page = virt_to_page(pmdp);		\
-	pgtable_pmd_page_dtor(page);			\
-	tlb_remove_page((tlb), page);			\
-} while (0);
-#endif
-
 #endif /* __ASM_SH_PGALLOC_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/include/asm/processor.h
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/include/asm/processor.h
@@ -173,6 +173,8 @@
 #define instruction_size(insn)	(4)
 #endif
 
+void select_idle_routine(void);
+
 #endif /* __ASSEMBLY__ */
 
 #ifdef CONFIG_SUPERH32
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/include/asm/processor_32.h
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/include/asm/processor_32.h
@@ -51,6 +51,7 @@
 #define SR_FD		0x00008000
 #define SR_MD		0x40000000
 
+#define SR_USER_MASK	0x00000303	// M, Q, S, T bits
 /*
  * DSP structure and data
  */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/include/asm/sections.h
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/include/asm/sections.h
@@ -4,7 +4,7 @@
 
 #include <asm-generic/sections.h>
 
-extern long __machvec_start, __machvec_end;
+extern char __machvec_start[], __machvec_end[];
 extern char __uncached_start, __uncached_end;
 extern char __start_eh_frame[], __stop_eh_frame[];
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/include/asm/sfp-machine.h
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/include/asm/sfp-machine.h
@@ -13,6 +13,14 @@
 #ifndef _SFP_MACHINE_H
 #define _SFP_MACHINE_H
 
+#ifdef __BIG_ENDIAN__
+#define __BYTE_ORDER __BIG_ENDIAN
+#define __LITTLE_ENDIAN 0
+#else
+#define __BYTE_ORDER __LITTLE_ENDIAN
+#define __BIG_ENDIAN 0
+#endif
+
 #define _FP_W_TYPE_SIZE		32
 #define _FP_W_TYPE		unsigned long
 #define _FP_WS_TYPE		signed long
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/include/cpu-sh2a/cpu/sh7269.h
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/include/cpu-sh2a/cpu/sh7269.h
@@ -78,8 +78,15 @@
 	GPIO_FN_WDTOVF,
 
 	/* CAN */
-	GPIO_FN_CTX1, GPIO_FN_CRX1, GPIO_FN_CTX0, GPIO_FN_CTX0_CTX1,
-	GPIO_FN_CRX0, GPIO_FN_CRX0_CRX1, GPIO_FN_CRX0_CRX1_CRX2,
+	GPIO_FN_CTX2, GPIO_FN_CRX2,
+	GPIO_FN_CTX1, GPIO_FN_CRX1,
+	GPIO_FN_CTX0, GPIO_FN_CRX0,
+	GPIO_FN_CTX0_CTX1, GPIO_FN_CRX0_CRX1,
+	GPIO_FN_CTX0_CTX1_CTX2, GPIO_FN_CRX0_CRX1_CRX2,
+	GPIO_FN_CTX2_PJ21, GPIO_FN_CRX2_PJ20,
+	GPIO_FN_CTX1_PJ23, GPIO_FN_CRX1_PJ22,
+	GPIO_FN_CTX0_CTX1_PJ23, GPIO_FN_CRX0_CRX1_PJ22,
+	GPIO_FN_CTX0_CTX1_CTX2_PJ21, GPIO_FN_CRX0_CRX1_CRX2_PJ20,
 
 	/* DMAC */
 	GPIO_FN_TEND0, GPIO_FN_DACK0, GPIO_FN_DREQ0,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/include/cpu-sh4/cpu/sh7734.h
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/include/cpu-sh4/cpu/sh7734.h
@@ -134,7 +134,7 @@
 	GPIO_FN_EX_WAIT1, GPIO_FN_SD1_DAT0_A, GPIO_FN_DREQ2, GPIO_FN_CAN1_TX_C,
 		GPIO_FN_ET0_LINK_C, GPIO_FN_ET0_ETXD5_A,
 	GPIO_FN_EX_WAIT0, GPIO_FN_TCLK1_B,
-	GPIO_FN_RD_WR, GPIO_FN_TCLK0,
+	GPIO_FN_RD_WR, GPIO_FN_TCLK0, GPIO_FN_CAN_CLK_B, GPIO_FN_ET0_ETXD4,
 	GPIO_FN_EX_CS5, GPIO_FN_SD1_CMD_A, GPIO_FN_ATADIR, GPIO_FN_QSSL_B,
 		GPIO_FN_ET0_ETXD3_A,
 	GPIO_FN_EX_CS4, GPIO_FN_SD1_WP_A, GPIO_FN_ATAWR, GPIO_FN_QMI_QIO1_B,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/kernel/cpu/fpu.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/kernel/cpu/fpu.c
@@ -62,18 +62,20 @@
 	}
 
 	if (!tsk_used_math(tsk)) {
-		local_irq_enable();
+		int ret;
 		/*
 		 * does a slab alloc which can sleep
 		 */
-		if (init_fpu(tsk)) {
+		local_irq_enable();
+		ret = init_fpu(tsk);
+		local_irq_disable();
+		if (ret) {
 			/*
 			 * ran out of memory!
 			 */
-			do_group_exit(SIGKILL);
+			force_sig(SIGKILL);
 			return;
 		}
-		local_irq_disable();
 	}
 
 	grab_fpu(regs);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/kernel/cpu/proc.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/kernel/cpu/proc.c
@@ -133,7 +133,7 @@
 
 static void *c_start(struct seq_file *m, loff_t *pos)
 {
-	return *pos < NR_CPUS ? cpu_data + *pos : NULL;
+	return *pos < nr_cpu_ids ? cpu_data + *pos : NULL;
 }
 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/kernel/cpu/sh2/probe.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/kernel/cpu/sh2/probe.c
@@ -21,7 +21,7 @@
 	if (!of_flat_dt_is_compatible(node, "jcore,cache"))
 		return 0;
 
-	j2_ccr_base = (u32 __iomem *)of_flat_dt_translate_address(node);
+	j2_ccr_base = ioremap(of_flat_dt_translate_address(node), 4);
 
 	return 1;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/kernel/cpu/sh4/sq.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/kernel/cpu/sh4/sq.c
@@ -380,7 +380,7 @@
 	if (unlikely(!sq_cache))
 		return ret;
 
-	sq_bitmap = kzalloc(size, GFP_KERNEL);
+	sq_bitmap = kcalloc(size, sizeof(long), GFP_KERNEL);
 	if (unlikely(!sq_bitmap))
 		goto out;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/kernel/cpu/sh4a/smp-shx3.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/kernel/cpu/sh4a/smp-shx3.c
@@ -73,8 +73,9 @@
 	BUILD_BUG_ON(SMP_MSG_NR >= 8);
 
 	for (i = 0; i < SMP_MSG_NR; i++)
-		request_irq(104 + i, ipi_interrupt_handler,
-			    IRQF_PERCPU, "IPI", (void *)(long)i);
+		if (request_irq(104 + i, ipi_interrupt_handler,
+			    IRQF_PERCPU, "IPI", (void *)(long)i))
+			pr_err("Failed to request irq %d\n", i);
 
 	for (i = 0; i < max_cpus; i++)
 		set_cpu_present(i, true);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/kernel/dma-coherent.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/kernel/dma-coherent.c
@@ -25,7 +25,7 @@
 	 * Pages from the page allocator may have data present in
 	 * cache. So flush the cache before using uncached memory.
 	 */
-	arch_sync_dma_for_device(dev, virt_to_phys(ret), size,
+	arch_sync_dma_for_device(virt_to_phys(ret), size,
 			DMA_BIDIRECTIONAL);
 
 	ret_nocache = (void __force *)ioremap_nocache(virt_to_phys(ret), size);
@@ -59,8 +59,8 @@
 	iounmap(vaddr);
 }
 
-void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr,
-		size_t size, enum dma_data_direction dir)
+void arch_sync_dma_for_device(phys_addr_t paddr, size_t size,
+		enum dma_data_direction dir)
 {
 	void *addr = sh_cacheop_vaddr(phys_to_virt(paddr));
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/kernel/entry-common.S
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/kernel/entry-common.S
@@ -199,7 +199,7 @@
 	mov.l	@(OFF_R7,r15), r7   ! arg3
 	mov.l	@(OFF_R3,r15), r3   ! syscall_nr
 	!
-	mov.l	2f, r10			! Number of syscalls
+	mov.l	6f, r10			! Number of syscalls
 	cmp/hs	r10, r3
 	bf	syscall_call
 	mov	#-ENOSYS, r0
@@ -353,7 +353,7 @@
 	tst	r9, r8
 	bf	syscall_trace_entry
 	!
-	mov.l	2f, r8			! Number of syscalls
+	mov.l	6f, r8			! Number of syscalls
 	cmp/hs	r8, r3
 	bt	syscall_badsys
 	!
@@ -392,7 +392,7 @@
 #if !defined(CONFIG_CPU_SH2)
 1:	.long	TRA
 #endif
-2:	.long	NR_syscalls
+6:	.long	NR_syscalls
 3:	.long	sys_call_table
 7:	.long	do_syscall_trace_enter
 8:	.long	do_syscall_trace_leave
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/kernel/head_32.S
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/kernel/head_32.S
@@ -64,7 +64,7 @@
 	ldc	r0, r6_bank
 #endif
 
-#ifdef CONFIG_OF_FLATTREE
+#ifdef CONFIG_OF_EARLY_FLATTREE
 	mov	r4, r12		! Store device tree blob pointer in r12
 #endif
 	
@@ -315,7 +315,7 @@
 10:		
 #endif
 
-#ifdef CONFIG_OF_FLATTREE
+#ifdef CONFIG_OF_EARLY_FLATTREE
 	mov.l	8f, r0		! Make flat device tree available early.
 	jsr	@r0
 	 mov	r12, r4
@@ -346,7 +346,7 @@
 5:	.long	start_kernel
 6:	.long	cpu_init
 7:	.long	init_thread_union
-#if defined(CONFIG_OF_FLATTREE)
+#if defined(CONFIG_OF_EARLY_FLATTREE)
 8:	.long	sh_fdt_init
 #endif
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/kernel/idle.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/kernel/idle.c
@@ -15,6 +15,7 @@
 #include <linux/smp.h>
 #include <linux/atomic.h>
 #include <asm/pgalloc.h>
+#include <asm/processor.h>
 #include <asm/smp.h>
 #include <asm/bl_bit.h>
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/kernel/kprobes.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/kernel/kprobes.c
@@ -44,17 +44,12 @@
 	if (OPCODE_RTE(opcode))
 		return -EFAULT;	/* Bad breakpoint */
 
+	memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
 	p->opcode = opcode;
 
 	return 0;
 }
 
-void __kprobes arch_copy_kprobe(struct kprobe *p)
-{
-	memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
-	p->opcode = *p->addr;
-}
-
 void __kprobes arch_arm_kprobe(struct kprobe *p)
 {
 	*p->addr = BREAKPOINT_INSTRUCTION;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/kernel/machvec.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/kernel/machvec.c
@@ -19,8 +19,8 @@
 #define MV_NAME_SIZE 32
 
 #define for_each_mv(mv) \
-	for ((mv) = (struct sh_machine_vector *)&__machvec_start; \
-	     (mv) && (unsigned long)(mv) < (unsigned long)&__machvec_end; \
+	for ((mv) = (struct sh_machine_vector *)__machvec_start; \
+	     (mv) && (unsigned long)(mv) < (unsigned long)__machvec_end; \
 	     (mv)++)
 
 static struct sh_machine_vector * __init get_mv_byname(const char *name)
@@ -86,8 +86,8 @@
 	if (!machvec_selected) {
 		unsigned long machvec_size;
 
-		machvec_size = ((unsigned long)&__machvec_end -
-				(unsigned long)&__machvec_start);
+		machvec_size = ((unsigned long)__machvec_end -
+				(unsigned long)__machvec_start);
 
 		/*
 		 * Sanity check for machvec section alignment. Ensure
@@ -101,7 +101,7 @@
 		 * vector (usually the only one) from .machvec.init.
 		 */
 		if (machvec_size >= sizeof(struct sh_machine_vector))
-			sh_mv = *(struct sh_machine_vector *)&__machvec_start;
+			sh_mv = *(struct sh_machine_vector *)__machvec_start;
 	}
 
 	printk(KERN_NOTICE "Booting machvec: %s\n", get_system_type());
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/kernel/nmi_debug.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/kernel/nmi_debug.c
@@ -49,7 +49,7 @@
 	register_die_notifier(&nmi_debug_nb);
 
 	if (*str != '=')
-		return 0;
+		return 1;
 
 	for (p = str + 1; *p; p = sep + 1) {
 		sep = strchr(p, ',');
@@ -70,6 +70,6 @@
 			break;
 	}
 
-	return 0;
+	return 1;
 }
 __setup("nmi_debug", nmi_debug_setup);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/kernel/setup.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/kernel/setup.c
@@ -43,6 +43,7 @@
 #include <asm/smp.h>
 #include <asm/mmu_context.h>
 #include <asm/mmzone.h>
+#include <asm/processor.h>
 #include <asm/sparsemem.h>
 
 /*
@@ -243,7 +244,7 @@
 {
 }
 
-#ifdef CONFIG_OF_FLATTREE
+#ifdef CONFIG_OF_EARLY_FLATTREE
 void __ref sh_fdt_init(phys_addr_t dt_phys)
 {
 	static int done = 0;
@@ -330,7 +331,7 @@
 	/* Let earlyprintk output early console messages */
 	early_platform_driver_probe("earlyprintk", 1, 1);
 
-#ifdef CONFIG_OF_FLATTREE
+#ifdef CONFIG_OF_EARLY_FLATTREE
 #ifdef CONFIG_USE_BUILTIN_DTB
 	unflatten_and_copy_device_tree();
 #else
@@ -362,3 +363,57 @@
 {
 	return sh_mv.mv_mode_pins() & pin;
 }
+
+void __init arch_cpu_finalize_init(void)
+{
+	char *p = &init_utsname()->machine[2]; /* "sh" */
+
+	select_idle_routine();
+
+	current_cpu_data.loops_per_jiffy = loops_per_jiffy;
+
+	switch (current_cpu_data.family) {
+	case CPU_FAMILY_SH2:
+		*p++ = '2';
+		break;
+	case CPU_FAMILY_SH2A:
+		*p++ = '2';
+		*p++ = 'a';
+		break;
+	case CPU_FAMILY_SH3:
+		*p++ = '3';
+		break;
+	case CPU_FAMILY_SH4:
+		*p++ = '4';
+		break;
+	case CPU_FAMILY_SH4A:
+		*p++ = '4';
+		*p++ = 'a';
+		break;
+	case CPU_FAMILY_SH4AL_DSP:
+		*p++ = '4';
+		*p++ = 'a';
+		*p++ = 'l';
+		*p++ = '-';
+		*p++ = 'd';
+		*p++ = 's';
+		*p++ = 'p';
+		break;
+	case CPU_FAMILY_UNKNOWN:
+		/*
+		 * Specifically use CPU_FAMILY_UNKNOWN rather than
+		 * default:, so we're able to have the compiler whine
+		 * about unhandled enumerations.
+		 */
+		break;
+	}
+
+	pr_info("CPU: %s\n", get_cpu_subtype(&current_cpu_data));
+
+#ifndef __LITTLE_ENDIAN__
+	/* 'eb' means 'Endian Big' */
+	*p++ = 'e';
+	*p++ = 'b';
+#endif
+	*p = '\0';
+}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/kernel/signal_32.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/kernel/signal_32.c
@@ -116,6 +116,7 @@
 restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *r0_p)
 {
 	unsigned int err = 0;
+	unsigned int sr = regs->sr & ~SR_USER_MASK;
 
 #define COPY(x)		err |= __get_user(regs->x, &sc->sc_##x)
 			COPY(regs[1]);
@@ -131,6 +132,8 @@
 	COPY(sr);	COPY(pc);
 #undef COPY
 
+	regs->sr = (regs->sr & SR_USER_MASK) | sr;
+
 #ifdef CONFIG_SH_FPU
 	if (boot_cpu_data.flags & CPU_HAS_FPU) {
 		int owned_fp;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/kernel/traps.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/kernel/traps.c
@@ -57,7 +57,7 @@
 	if (panic_on_oops)
 		panic("Fatal exception");
 
-	do_exit(SIGSEGV);
+	make_task_dead(SIGSEGV);
 }
 
 void die_if_kernel(const char *str, struct pt_regs *regs, long err)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/kernel/vmlinux.lds.S
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/kernel/vmlinux.lds.S
@@ -10,6 +10,7 @@
 #define LOAD_OFFSET	0
 OUTPUT_ARCH(sh)
 #endif
+#define RUNTIME_DISCARD_EXIT
 
 #include <asm/thread_info.h>
 #include <asm/cache.h>
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/lib/checksum.S
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/lib/checksum.S
@@ -33,7 +33,8 @@
  */
 
 /*	
- * asmlinkage __wsum csum_partial(const void *buf, int len, __wsum sum);
+ * unsigned int csum_partial(const unsigned char *buf, int len,
+ *                           unsigned int sum);
  */
 
 .text
@@ -45,31 +46,11 @@
 	   * Fortunately, it is easy to convert 2-byte alignment to 4-byte
 	   * alignment for the unrolled loop.
 	   */
+	mov	r5, r1
 	mov	r4, r0
-	tst	#3, r0		! Check alignment.
-	bt/s	2f		! Jump if alignment is ok.
-	 mov	r4, r7		! Keep a copy to check for alignment
+	tst	#2, r0		! Check alignment.
+	bt	2f		! Jump if alignment is ok.
 	!
-	tst	#1, r0		! Check alignment.
-	bt	21f		! Jump if alignment is boundary of 2bytes.
-
-	! buf is odd
-	tst	r5, r5
-	add	#-1, r5
-	bt	9f
-	mov.b	@r4+, r0
-	extu.b	r0, r0
-	addc	r0, r6		! t=0 from previous tst
-	mov	r6, r0
-	shll8	r6
-	shlr16	r0
-	shlr8	r0
-	or	r0, r6
-	mov	r4, r0
-	tst	#2, r0
-	bt	2f
-21:
-	! buf is 2 byte aligned (len could be 0)
 	add	#-2, r5		! Alignment uses up two bytes.
 	cmp/pz	r5		!
 	bt/s	1f		! Jump if we had at least two bytes.
@@ -77,17 +58,16 @@
 	bra	6f
 	 add	#2, r5		! r5 was < 2.  Deal with it.
 1:
+	mov	r5, r1		! Save new len for later use.
 	mov.w	@r4+, r0
 	extu.w	r0, r0
 	addc	r0, r6
 	bf	2f
 	add	#1, r6
 2:
-	! buf is 4 byte aligned (len could be 0)
-	mov	r5, r1
 	mov	#-5, r0
-	shld	r0, r1
-	tst	r1, r1
+	shld	r0, r5
+	tst	r5, r5
 	bt/s	4f		! if it's =0, go to 4f
 	 clrt
 	.align	2
@@ -109,31 +89,30 @@
 	addc	r0, r6
 	addc	r2, r6
 	movt	r0
-	dt	r1
+	dt	r5
 	bf/s	3b
 	 cmp/eq	#1, r0
-	! here, we know r1==0
-	addc	r1, r6			! add carry to r6
+	! here, we know r5==0
+	addc	r5, r6			! add carry to r6
 4:
-	mov	r5, r0
+	mov	r1, r0
 	and	#0x1c, r0
 	tst	r0, r0
-	bt	6f
-	! 4 bytes or more remaining
-	mov	r0, r1
-	shlr2	r1
+	bt/s	6f
+	 mov	r0, r5
+	shlr2	r5
 	mov	#0, r2
 5:
 	addc	r2, r6
 	mov.l	@r4+, r2
 	movt	r0
-	dt	r1
+	dt	r5
 	bf/s	5b
 	 cmp/eq	#1, r0
 	addc	r2, r6
-	addc	r1, r6		! r1==0 here, so it means add carry-bit
+	addc	r5, r6		! r5==0 here, so it means add carry-bit
 6:
-	! 3 bytes or less remaining
+	mov	r1, r5
 	mov	#3, r0
 	and	r0, r5
 	tst	r5, r5
@@ -159,16 +138,6 @@
 	mov	#0, r0
 	addc	r0, r6
 9:
-	! Check if the buffer was misaligned, if so realign sum
-	mov	r7, r0
-	tst	#1, r0
-	bt	10f
-	mov	r6, r0
-	shll8	r6
-	shlr16	r0
-	shlr8	r0
-	or	r0, r6
-10:
 	rts
 	 mov	r6, r0
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/math-emu/math.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/math-emu/math.c
@@ -468,109 +468,6 @@
 }
 
 /**
- *	denormal_to_double - Given denormalized float number,
- *	                     store double float
- *
- *	@fpu: Pointer to sh_fpu_soft structure
- *	@n: Index to FP register
- */
-static void denormal_to_double(struct sh_fpu_soft_struct *fpu, int n)
-{
-	unsigned long du, dl;
-	unsigned long x = fpu->fpul;
-	int exp = 1023 - 126;
-
-	if (x != 0 && (x & 0x7f800000) == 0) {
-		du = (x & 0x80000000);
-		while ((x & 0x00800000) == 0) {
-			x <<= 1;
-			exp--;
-		}
-		x &= 0x007fffff;
-		du |= (exp << 20) | (x >> 3);
-		dl = x << 29;
-
-		fpu->fp_regs[n] = du;
-		fpu->fp_regs[n+1] = dl;
-	}
-}
-
-/**
- *	ieee_fpe_handler - Handle denormalized number exception
- *
- *	@regs: Pointer to register structure
- *
- *	Returns 1 when it's handled (should not cause exception).
- */
-static int ieee_fpe_handler(struct pt_regs *regs)
-{
-	unsigned short insn = *(unsigned short *)regs->pc;
-	unsigned short finsn;
-	unsigned long nextpc;
-	int nib[4] = {
-		(insn >> 12) & 0xf,
-		(insn >> 8) & 0xf,
-		(insn >> 4) & 0xf,
-		insn & 0xf};
-
-	if (nib[0] == 0xb ||
-	    (nib[0] == 0x4 && nib[2] == 0x0 && nib[3] == 0xb)) /* bsr & jsr */
-		regs->pr = regs->pc + 4;
-
-	if (nib[0] == 0xa || nib[0] == 0xb) { /* bra & bsr */
-		nextpc = regs->pc + 4 + ((short) ((insn & 0xfff) << 4) >> 3);
-		finsn = *(unsigned short *) (regs->pc + 2);
-	} else if (nib[0] == 0x8 && nib[1] == 0xd) { /* bt/s */
-		if (regs->sr & 1)
-			nextpc = regs->pc + 4 + ((char) (insn & 0xff) << 1);
-		else
-			nextpc = regs->pc + 4;
-		finsn = *(unsigned short *) (regs->pc + 2);
-	} else if (nib[0] == 0x8 && nib[1] == 0xf) { /* bf/s */
-		if (regs->sr & 1)
-			nextpc = regs->pc + 4;
-		else
-			nextpc = regs->pc + 4 + ((char) (insn & 0xff) << 1);
-		finsn = *(unsigned short *) (regs->pc + 2);
-	} else if (nib[0] == 0x4 && nib[3] == 0xb &&
-		 (nib[2] == 0x0 || nib[2] == 0x2)) { /* jmp & jsr */
-		nextpc = regs->regs[nib[1]];
-		finsn = *(unsigned short *) (regs->pc + 2);
-	} else if (nib[0] == 0x0 && nib[3] == 0x3 &&
-		 (nib[2] == 0x0 || nib[2] == 0x2)) { /* braf & bsrf */
-		nextpc = regs->pc + 4 + regs->regs[nib[1]];
-		finsn = *(unsigned short *) (regs->pc + 2);
-	} else if (insn == 0x000b) { /* rts */
-		nextpc = regs->pr;
-		finsn = *(unsigned short *) (regs->pc + 2);
-	} else {
-		nextpc = regs->pc + 2;
-		finsn = insn;
-	}
-
-	if ((finsn & 0xf1ff) == 0xf0ad) { /* fcnvsd */
-		struct task_struct *tsk = current;
-
-		if ((tsk->thread.xstate->softfpu.fpscr & (1 << 17))) {
-			/* FPU error */
-			denormal_to_double (&tsk->thread.xstate->softfpu,
-					    (finsn >> 8) & 0xf);
-			tsk->thread.xstate->softfpu.fpscr &=
-				~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK);
-			task_thread_info(tsk)->status |= TS_USEDFPU;
-		} else {
-			force_sig_fault(SIGFPE, FPE_FLTINV,
-					(void __user *)regs->pc);
-		}
-
-		regs->pc = nextpc;
-		return 1;
-	}
-
-	return 0;
-}
-
-/**
  * fpu_init - Initialize FPU registers
  * @fpu: Pointer to software emulated FPU registers.
  */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/math-emu/sfp-util.h
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/math-emu/sfp-util.h
@@ -67,7 +67,3 @@
   } while (0)
 
 #define abort()	return 0
-
-#define __BYTE_ORDER __LITTLE_ENDIAN
-
-
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sh/mm/init.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sh/mm/init.c
@@ -434,9 +434,7 @@
 {
 	unsigned long start_pfn = PFN_DOWN(start);
 	unsigned long nr_pages = size >> PAGE_SHIFT;
-	struct zone *zone;
 
-	zone = page_zone(pfn_to_page(start_pfn));
-	__remove_pages(zone, start_pfn, nr_pages, altmap);
+	__remove_pages(start_pfn, nr_pages, altmap);
 }
 #endif /* CONFIG_MEMORY_HOTPLUG */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/Kconfig
@@ -52,6 +52,7 @@
 config SPARC32
 	def_bool !64BIT
 	select ARCH_32BIT_OFF_T
+	select ARCH_HAS_CPU_FINALIZE_INIT if !SMP
 	select ARCH_HAS_SYNC_DMA_FOR_CPU
 	select GENERIC_ATOMIC64
 	select CLZ_TAB
@@ -65,7 +66,6 @@
 	select HAVE_KRETPROBES
 	select HAVE_KPROBES
 	select HAVE_RCU_TABLE_FREE if SMP
-	select HAVE_RCU_TABLE_NO_INVALIDATE if HAVE_RCU_TABLE_FREE
 	select HAVE_MEMBLOCK_NODE_MAP
 	select HAVE_ARCH_TRANSPARENT_HUGEPAGE
 	select HAVE_DYNAMIC_FTRACE
@@ -322,7 +322,7 @@
 	  This config option is actually maximum order plus one. For example,
 	  a value of 13 means that the largest free memory block is 2^12 pages.
 
-if SPARC64
+if SPARC64 || COMPILE_TEST
 source "kernel/power/Kconfig"
 endif
 
@@ -525,7 +525,7 @@
 	bool
 	depends on SPARC64
 	default y
-	select COMPAT_BINFMT_ELF
+	select COMPAT_BINFMT_ELF if BINFMT_ELF
 	select HAVE_UID16
 	select ARCH_WANT_OLD_COMPAT_IPC
 	select COMPAT_OLD_SIGACTION
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/configs/sparc64_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/configs/sparc64_defconfig
@@ -73,7 +73,6 @@
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_BLK_DEV_SR=m
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=m
 CONFIG_SCSI_MULTI_LUN=y
 CONFIG_SCSI_CONSTANTS=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/include/asm/Kbuild
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/include/asm/Kbuild
@@ -18,7 +18,6 @@
 generic-y += mm-arch-hooks.h
 generic-y += mmiowb.h
 generic-y += module.h
-generic-y += msi.h
 generic-y += preempt.h
 generic-y += serial.h
 generic-y += trace_clock.h
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/include/asm/io_64.h
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/include/asm/io_64.h
@@ -407,6 +407,7 @@
 }
 
 #define ioremap_nocache(X,Y)		ioremap((X),(Y))
+#define ioremap_uc(X,Y)			ioremap((X),(Y))
 #define ioremap_wc(X,Y)			ioremap((X),(Y))
 #define ioremap_wt(X,Y)			ioremap((X),(Y))
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/include/asm/mman.h
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/include/asm/mman.h
@@ -57,35 +57,39 @@
 {
 	if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM | PROT_ADI))
 		return 0;
-	if (prot & PROT_ADI) {
-		if (!adi_capable())
-			return 0;
+	return 1;
+}
 
-		if (addr) {
-			struct vm_area_struct *vma;
+#define arch_validate_flags(vm_flags) arch_validate_flags(vm_flags)
+/* arch_validate_flags() - Ensure combination of flags is valid for a
+ *	VMA.
+ */
+static inline bool arch_validate_flags(unsigned long vm_flags)
+{
+	/* If ADI is being enabled on this VMA, check for ADI
+	 * capability on the platform and ensure VMA is suitable
+	 * for ADI
+	 */
+	if (vm_flags & VM_SPARC_ADI) {
+		if (!adi_capable())
+			return false;
 
-			vma = find_vma(current->mm, addr);
-			if (vma) {
-				/* ADI can not be enabled on PFN
-				 * mapped pages
-				 */
-				if (vma->vm_flags & (VM_PFNMAP | VM_MIXEDMAP))
-					return 0;
+		/* ADI can not be enabled on PFN mapped pages */
+		if (vm_flags & (VM_PFNMAP | VM_MIXEDMAP))
+			return false;
 
-				/* Mergeable pages can become unmergeable
-				 * if ADI is enabled on them even if they
-				 * have identical data on them. This can be
-				 * because ADI enabled pages with identical
-				 * data may still not have identical ADI
-				 * tags on them. Disallow ADI on mergeable
-				 * pages.
-				 */
-				if (vma->vm_flags & VM_MERGEABLE)
-					return 0;
-			}
-		}
+		/* Mergeable pages can become unmergeable
+		 * if ADI is enabled on them even if they
+		 * have identical data on them. This can be
+		 * because ADI enabled pages with identical
+		 * data may still not have identical ADI
+		 * tags on them. Disallow ADI on mergeable
+		 * pages.
+		 */
+		if (vm_flags & VM_MERGEABLE)
+			return false;
 	}
-	return 1;
+	return true;
 }
 #endif /* CONFIG_SPARC64 */
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/include/asm/oplib_64.h
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/include/asm/oplib_64.h
@@ -247,6 +247,7 @@
 int prom_ihandle2path(int handle, char *buffer, int bufsize);
 
 /* Client interface level routines. */
+void prom_cif_init(void *cif_handler);
 void p1275_cmd_direct(unsigned long *);
 
 #endif /* !(__SPARC64_OPLIB_H) */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/include/asm/smp_64.h
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/include/asm/smp_64.h
@@ -47,7 +47,6 @@
 int hard_smp_processor_id(void);
 #define raw_smp_processor_id() (current_thread_info()->cpu)
 
-void smp_fill_in_cpu_possible_map(void);
 void smp_fill_in_sib_core_maps(void);
 void cpu_play_dead(void);
 
@@ -77,7 +76,6 @@
 #define smp_fill_in_sib_core_maps() do { } while (0)
 #define smp_fetch_global_regs() do { } while (0)
 #define smp_fetch_global_pmu() do { } while (0)
-#define smp_fill_in_cpu_possible_map() do { } while (0)
 #define smp_init_cpu_poke() do { } while (0)
 #define scheduler_poke() do { } while (0)
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/include/asm/timex_32.h
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/include/asm/timex_32.h
@@ -9,8 +9,6 @@
 
 #define CLOCK_TICK_RATE	1193180 /* Underlying HZ */
 
-/* XXX Maybe do something better at some point... -DaveM */
-typedef unsigned long cycles_t;
-#define get_cycles()	(0)
+#include <asm-generic/timex.h>
 
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/include/asm/tlb_64.h
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/include/asm/tlb_64.h
@@ -28,6 +28,15 @@
 #define __tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0)
 #define tlb_flush(tlb)	flush_tlb_pending()
 
+/*
+ * SPARC64's hardware TLB fill does not use the Linux page-tables
+ * and therefore we don't need a TLBI when freeing page-table pages.
+ */
+
+#ifdef CONFIG_HAVE_RCU_TABLE_FREE
+#define tlb_needs_table_invalidate()	(false)
+#endif
+
 #include <asm-generic/tlb.h>
 
 #endif /* _SPARC64_TLB_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/include/uapi/asm/ipcbuf.h
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/include/uapi/asm/ipcbuf.h
@@ -15,19 +15,19 @@
 
 struct ipc64_perm
 {
-	__kernel_key_t	key;
-	__kernel_uid_t	uid;
-	__kernel_gid_t	gid;
-	__kernel_uid_t	cuid;
-	__kernel_gid_t	cgid;
+	__kernel_key_t		key;
+	__kernel_uid32_t	uid;
+	__kernel_gid32_t	gid;
+	__kernel_uid32_t	cuid;
+	__kernel_gid32_t	cgid;
 #ifndef __arch64__
-	unsigned short	__pad0;
+	unsigned short		__pad0;
 #endif
-	__kernel_mode_t	mode;
-	unsigned short	__pad1;
-	unsigned short	seq;
-	unsigned long long __unused1;
-	unsigned long long __unused2;
+	__kernel_mode_t		mode;
+	unsigned short		__pad1;
+	unsigned short		seq;
+	unsigned long long	__unused1;
+	unsigned long long	__unused2;
 };
 
 #endif /* __SPARC_IPCBUF_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/include/uapi/asm/termbits.h
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/include/uapi/asm/termbits.h
@@ -13,16 +13,6 @@
 typedef unsigned long   tcflag_t;
 #endif
 
-#define NCC 8
-struct termio {
-	unsigned short c_iflag;		/* input mode flags */
-	unsigned short c_oflag;		/* output mode flags */
-	unsigned short c_cflag;		/* control mode flags */
-	unsigned short c_lflag;		/* local mode flags */
-	unsigned char c_line;		/* line discipline */
-	unsigned char c_cc[NCC];	/* control characters */
-};
-
 #define NCCS 17
 struct termios {
 	tcflag_t c_iflag;		/* input mode flags */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/include/uapi/asm/termios.h
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/include/uapi/asm/termios.h
@@ -40,5 +40,14 @@
 	unsigned short ws_ypixel;
 };
 
+#define NCC 8
+struct termio {
+	unsigned short c_iflag;		/* input mode flags */
+	unsigned short c_oflag;		/* output mode flags */
+	unsigned short c_cflag;		/* control mode flags */
+	unsigned short c_lflag;		/* local mode flags */
+	unsigned char c_line;		/* line discipline */
+	unsigned char c_cc[NCC];	/* control characters */
+};
 
 #endif /* _UAPI_SPARC_TERMIOS_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/kernel/ioport.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/kernel/ioport.c
@@ -356,7 +356,9 @@
 void arch_dma_free(struct device *dev, size_t size, void *cpu_addr,
 		dma_addr_t dma_addr, unsigned long attrs)
 {
-	if (!sparc_dma_free_resource(cpu_addr, PAGE_ALIGN(size)))
+	size = PAGE_ALIGN(size);
+
+	if (!sparc_dma_free_resource(cpu_addr, size))
 		return;
 
 	dma_make_coherent(dma_addr, size);
@@ -366,8 +368,8 @@
 
 /* IIep is write-through, not flushing on cpu to device transfer. */
 
-void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr,
-		size_t size, enum dma_data_direction dir)
+void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size,
+		enum dma_data_direction dir)
 {
 	if (dir != PCI_DMA_TODEVICE)
 		dma_make_coherent(paddr, PAGE_ALIGN(size));
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/kernel/leon_pci_grpci1.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/kernel/leon_pci_grpci1.c
@@ -696,7 +696,7 @@
 	return err;
 }
 
-static const struct of_device_id grpci1_of_match[] __initconst = {
+static const struct of_device_id grpci1_of_match[] = {
 	{
 	 .name = "GAISLER_PCIFBRG",
 	 },
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/kernel/leon_pci_grpci2.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/kernel/leon_pci_grpci2.c
@@ -887,7 +887,7 @@
 	return err;
 }
 
-static const struct of_device_id grpci2_of_match[] __initconst = {
+static const struct of_device_id grpci2_of_match[] = {
 	{
 	 .name = "GAISLER_GRPCI2",
 	 },
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/kernel/mdesc.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/kernel/mdesc.c
@@ -39,6 +39,7 @@
 	u32	node_sz; /* node block size */
 	u32	name_sz; /* name block size */
 	u32	data_sz; /* data block size */
+	char	data[];
 } __attribute__((aligned(16)));
 
 struct mdesc_elem {
@@ -612,7 +613,7 @@
 
 static struct mdesc_elem *node_block(struct mdesc_hdr *mdesc)
 {
-	return (struct mdesc_elem *) (mdesc + 1);
+	return (struct mdesc_elem *) mdesc->data;
 }
 
 static void *name_block(struct mdesc_hdr *mdesc)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/kernel/nmi.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/kernel/nmi.c
@@ -274,7 +274,7 @@
 	if (!strncmp(str, "panic", 5))
 		panic_on_timeout = 1;
 
-	return 0;
+	return 1;
 }
 __setup("nmi_watchdog=", setup_nmi_watchdog);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/kernel/prom_64.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/kernel/prom_64.c
@@ -483,7 +483,9 @@
 	ncpus_probed++;
 #ifdef CONFIG_SMP
 	set_cpu_present(cpuid, true);
-	set_cpu_possible(cpuid, true);
+
+	if (num_possible_cpus() < nr_cpu_ids)
+		set_cpu_possible(cpuid, true);
 #endif
 	return NULL;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/kernel/ptrace_32.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/kernel/ptrace_32.c
@@ -46,82 +46,79 @@
 	REGSET_FP,
 };
 
+static int regwindow32_get(struct task_struct *target,
+			   const struct pt_regs *regs,
+			   u32 *uregs)
+{
+	unsigned long reg_window = regs->u_regs[UREG_I6];
+	int size = 16 * sizeof(u32);
+
+	if (target == current) {
+		if (copy_from_user(uregs, (void __user *)reg_window, size))
+			return -EFAULT;
+	} else {
+		if (access_process_vm(target, reg_window, uregs, size,
+				      FOLL_FORCE) != size)
+			return -EFAULT;
+	}
+	return 0;
+}
+
+static int regwindow32_set(struct task_struct *target,
+			   const struct pt_regs *regs,
+			   u32 *uregs)
+{
+	unsigned long reg_window = regs->u_regs[UREG_I6];
+	int size = 16 * sizeof(u32);
+
+	if (target == current) {
+		if (copy_to_user((void __user *)reg_window, uregs, size))
+			return -EFAULT;
+	} else {
+		if (access_process_vm(target, reg_window, uregs, size,
+				      FOLL_FORCE | FOLL_WRITE) != size)
+			return -EFAULT;
+	}
+	return 0;
+}
+
 static int genregs32_get(struct task_struct *target,
 			 const struct user_regset *regset,
 			 unsigned int pos, unsigned int count,
 			 void *kbuf, void __user *ubuf)
 {
 	const struct pt_regs *regs = target->thread.kregs;
-	unsigned long __user *reg_window;
-	unsigned long *k = kbuf;
-	unsigned long __user *u = ubuf;
-	unsigned long reg;
+	u32 uregs[16];
+	int ret;
 
 	if (target == current)
 		flush_user_windows();
 
-	pos /= sizeof(reg);
-	count /= sizeof(reg);
+	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				  regs->u_regs,
+				  0, 16 * sizeof(u32));
+	if (ret || !count)
+		return ret;
 
-	if (kbuf) {
-		for (; count > 0 && pos < 16; count--)
-			*k++ = regs->u_regs[pos++];
-
-		reg_window = (unsigned long __user *) regs->u_regs[UREG_I6];
-		reg_window -= 16;
-		for (; count > 0 && pos < 32; count--) {
-			if (get_user(*k++, &reg_window[pos++]))
-				return -EFAULT;
-		}
-	} else {
-		for (; count > 0 && pos < 16; count--) {
-			if (put_user(regs->u_regs[pos++], u++))
-				return -EFAULT;
-		}
-
-		reg_window = (unsigned long __user *) regs->u_regs[UREG_I6];
-		reg_window -= 16;
-		for (; count > 0 && pos < 32; count--) {
-			if (get_user(reg, &reg_window[pos++]) ||
-			    put_user(reg, u++))
-				return -EFAULT;
-		}
-	}
-	while (count > 0) {
-		switch (pos) {
-		case 32: /* PSR */
-			reg = regs->psr;
-			break;
-		case 33: /* PC */
-			reg = regs->pc;
-			break;
-		case 34: /* NPC */
-			reg = regs->npc;
-			break;
-		case 35: /* Y */
-			reg = regs->y;
-			break;
-		case 36: /* WIM */
-		case 37: /* TBR */
-			reg = 0;
-			break;
-		default:
-			goto finish;
-		}
-
-		if (kbuf)
-			*k++ = reg;
-		else if (put_user(reg, u++))
+	if (pos < 32 * sizeof(u32)) {
+		if (regwindow32_get(target, regs, uregs))
 			return -EFAULT;
-		pos++;
-		count--;
+		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+					  uregs,
+					  16 * sizeof(u32), 32 * sizeof(u32));
+		if (ret || !count)
+			return ret;
 	}
-finish:
-	pos *= sizeof(reg);
-	count *= sizeof(reg);
 
-	return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
-					38 * sizeof(reg), -1);
+	uregs[0] = regs->psr;
+	uregs[1] = regs->pc;
+	uregs[2] = regs->npc;
+	uregs[3] = regs->y;
+	uregs[4] = 0;	/* WIM */
+	uregs[5] = 0;	/* TBR */
+	return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+				  uregs,
+				  32 * sizeof(u32), 38 * sizeof(u32));
 }
 
 static int genregs32_set(struct task_struct *target,
@@ -130,82 +127,58 @@
 			 const void *kbuf, const void __user *ubuf)
 {
 	struct pt_regs *regs = target->thread.kregs;
-	unsigned long __user *reg_window;
-	const unsigned long *k = kbuf;
-	const unsigned long __user *u = ubuf;
-	unsigned long reg;
+	u32 uregs[16];
+	u32 psr;
+	int ret;
 
 	if (target == current)
 		flush_user_windows();
 
-	pos /= sizeof(reg);
-	count /= sizeof(reg);
-
-	if (kbuf) {
-		for (; count > 0 && pos < 16; count--)
-			regs->u_regs[pos++] = *k++;
-
-		reg_window = (unsigned long __user *) regs->u_regs[UREG_I6];
-		reg_window -= 16;
-		for (; count > 0 && pos < 32; count--) {
-			if (put_user(*k++, &reg_window[pos++]))
-				return -EFAULT;
-		}
-	} else {
-		for (; count > 0 && pos < 16; count--) {
-			if (get_user(reg, u++))
-				return -EFAULT;
-			regs->u_regs[pos++] = reg;
-		}
-
-		reg_window = (unsigned long __user *) regs->u_regs[UREG_I6];
-		reg_window -= 16;
-		for (; count > 0 && pos < 32; count--) {
-			if (get_user(reg, u++) ||
-			    put_user(reg, &reg_window[pos++]))
-				return -EFAULT;
-		}
-	}
-	while (count > 0) {
-		unsigned long psr;
-
-		if (kbuf)
-			reg = *k++;
-		else if (get_user(reg, u++))
-			return -EFAULT;
-
-		switch (pos) {
-		case 32: /* PSR */
-			psr = regs->psr;
-			psr &= ~(PSR_ICC | PSR_SYSCALL);
-			psr |= (reg & (PSR_ICC | PSR_SYSCALL));
-			regs->psr = psr;
-			break;
-		case 33: /* PC */
-			regs->pc = reg;
-			break;
-		case 34: /* NPC */
-			regs->npc = reg;
-			break;
-		case 35: /* Y */
-			regs->y = reg;
-			break;
-		case 36: /* WIM */
-		case 37: /* TBR */
-			break;
-		default:
-			goto finish;
-		}
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				 regs->u_regs,
+				 0, 16 * sizeof(u32));
+	if (ret || !count)
+		return ret;
 
-		pos++;
-		count--;
+	if (pos < 32 * sizeof(u32)) {
+		if (regwindow32_get(target, regs, uregs))
+			return -EFAULT;
+		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+					 uregs,
+					 16 * sizeof(u32), 32 * sizeof(u32));
+		if (ret)
+			return ret;
+		if (regwindow32_set(target, regs, uregs))
+			return -EFAULT;
+		if (!count)
+			return 0;
 	}
-finish:
-	pos *= sizeof(reg);
-	count *= sizeof(reg);
-
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				 &psr,
+				 32 * sizeof(u32), 33 * sizeof(u32));
+	if (ret)
+		return ret;
+	regs->psr = (regs->psr & ~(PSR_ICC | PSR_SYSCALL)) |
+		    (psr & (PSR_ICC | PSR_SYSCALL));
+	if (!count)
+		return 0;
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				 &regs->pc,
+				 33 * sizeof(u32), 34 * sizeof(u32));
+	if (ret || !count)
+		return ret;
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				 &regs->npc,
+				 34 * sizeof(u32), 35 * sizeof(u32));
+	if (ret || !count)
+		return ret;
+	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+				 &regs->y,
+				 35 * sizeof(u32), 36 * sizeof(u32));
+	if (ret || !count)
+		return ret;
 	return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
-					 38 * sizeof(reg), -1);
+					 36 * sizeof(u32), 38 * sizeof(u32));
 }
 
 static int fpregs32_get(struct task_struct *target,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/kernel/ptrace_64.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/kernel/ptrace_64.c
@@ -572,19 +572,13 @@
 			for (; count > 0 && pos < 32; count--) {
 				if (access_process_vm(target,
 						      (unsigned long)
-						      &reg_window[pos],
+						      &reg_window[pos++],
 						      &reg, sizeof(reg),
 						      FOLL_FORCE)
 				    != sizeof(reg))
 					return -EFAULT;
-				if (access_process_vm(target,
-						      (unsigned long) u,
-						      &reg, sizeof(reg),
-						      FOLL_FORCE | FOLL_WRITE)
-				    != sizeof(reg))
+				if (put_user(reg, u++))
 					return -EFAULT;
-				pos++;
-				u++;
 			}
 		}
 	}
@@ -684,12 +678,7 @@
 			}
 		} else {
 			for (; count > 0 && pos < 32; count--) {
-				if (access_process_vm(target,
-						      (unsigned long)
-						      u,
-						      &reg, sizeof(reg),
-						      FOLL_FORCE)
-				    != sizeof(reg))
+				if (get_user(reg, u++))
 					return -EFAULT;
 				if (access_process_vm(target,
 						      (unsigned long)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/kernel/setup_32.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/kernel/setup_32.c
@@ -422,3 +422,10 @@
 }
 
 subsys_initcall(topology_init);
+
+#if defined(CONFIG_SPARC32) && !defined(CONFIG_SMP)
+void __init arch_cpu_finalize_init(void)
+{
+	cpu_data(0).udelay_val = loops_per_jiffy;
+}
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/kernel/setup_64.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/kernel/setup_64.c
@@ -695,7 +695,6 @@
 
 	paging_init();
 	init_sparc64_elf_hwcap();
-	smp_fill_in_cpu_possible_map();
 	/*
 	 * Once the OF device tree and MDESC have been setup and nr_cpus has
 	 * been parsed, we know the list of possible cpus.  Therefore we can
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/kernel/smp_64.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/kernel/smp_64.c
@@ -1039,38 +1039,9 @@
  * are flush_tlb_*() routines, and these run after flush_cache_*()
  * which performs the flushw.
  *
- * The SMP TLB coherency scheme we use works as follows:
- *
- * 1) mm->cpu_vm_mask is a bit mask of which cpus an address
- *    space has (potentially) executed on, this is the heuristic
- *    we use to avoid doing cross calls.
- *
- *    Also, for flushing from kswapd and also for clones, we
- *    use cpu_vm_mask as the list of cpus to make run the TLB.
- *
- * 2) TLB context numbers are shared globally across all processors
- *    in the system, this allows us to play several games to avoid
- *    cross calls.
- *
- *    One invariant is that when a cpu switches to a process, and
- *    that processes tsk->active_mm->cpu_vm_mask does not have the
- *    current cpu's bit set, that tlb context is flushed locally.
- *
- *    If the address space is non-shared (ie. mm->count == 1) we avoid
- *    cross calls when we want to flush the currently running process's
- *    tlb state.  This is done by clearing all cpu bits except the current
- *    processor's in current->mm->cpu_vm_mask and performing the
- *    flush locally only.  This will force any subsequent cpus which run
- *    this task to flush the context from the local tlb if the process
- *    migrates to another cpu (again).
- *
- * 3) For shared address spaces (threads) and swapping we bite the
- *    bullet for most cases and perform the cross call (but only to
- *    the cpus listed in cpu_vm_mask).
- *
- *    The performance gain from "optimizing" away the cross call for threads is
- *    questionable (in theory the big win for threads is the massive sharing of
- *    address space state across processors).
+ * mm->cpu_vm_mask is a bit mask of which cpus an address
+ * space has (potentially) executed on, this is the heuristic
+ * we use to limit cross calls.
  */
 
 /* This currently is only used by the hugetlb arch pre-fault
@@ -1080,18 +1051,13 @@
 void smp_flush_tlb_mm(struct mm_struct *mm)
 {
 	u32 ctx = CTX_HWBITS(mm->context);
-	int cpu = get_cpu();
 
-	if (atomic_read(&mm->mm_users) == 1) {
-		cpumask_copy(mm_cpumask(mm), cpumask_of(cpu));
-		goto local_flush_and_out;
-	}
+	get_cpu();
 
 	smp_cross_call_masked(&xcall_flush_tlb_mm,
 			      ctx, 0, 0,
 			      mm_cpumask(mm));
 
-local_flush_and_out:
 	__flush_tlb_mm(ctx, SECONDARY_CONTEXT);
 
 	put_cpu();
@@ -1114,17 +1080,15 @@
 {
 	u32 ctx = CTX_HWBITS(mm->context);
 	struct tlb_pending_info info;
-	int cpu = get_cpu();
+
+	get_cpu();
 
 	info.ctx = ctx;
 	info.nr = nr;
 	info.vaddrs = vaddrs;
 
-	if (mm == current->mm && atomic_read(&mm->mm_users) == 1)
-		cpumask_copy(mm_cpumask(mm), cpumask_of(cpu));
-	else
-		smp_call_function_many(mm_cpumask(mm), tlb_pending_func,
-				       &info, 1);
+	smp_call_function_many(mm_cpumask(mm), tlb_pending_func,
+			       &info, 1);
 
 	__flush_tlb_pending(ctx, nr, vaddrs);
 
@@ -1134,14 +1098,13 @@
 void smp_flush_tlb_page(struct mm_struct *mm, unsigned long vaddr)
 {
 	unsigned long context = CTX_HWBITS(mm->context);
-	int cpu = get_cpu();
 
-	if (mm == current->mm && atomic_read(&mm->mm_users) == 1)
-		cpumask_copy(mm_cpumask(mm), cpumask_of(cpu));
-	else
-		smp_cross_call_masked(&xcall_flush_tlb_page,
-				      context, vaddr, 0,
-				      mm_cpumask(mm));
+	get_cpu();
+
+	smp_cross_call_masked(&xcall_flush_tlb_page,
+			      context, vaddr, 0,
+			      mm_cpumask(mm));
+
 	__flush_tlb_page(context, vaddr);
 
 	put_cpu();
@@ -1250,20 +1213,6 @@
 		xcall_deliver_impl = hypervisor_xcall_deliver;
 }
 
-void __init smp_fill_in_cpu_possible_map(void)
-{
-	int possible_cpus = num_possible_cpus();
-	int i;
-
-	if (possible_cpus > nr_cpu_ids)
-		possible_cpus = nr_cpu_ids;
-
-	for (i = 0; i < possible_cpus; i++)
-		set_cpu_possible(i, true);
-	for (; i < NR_CPUS; i++)
-		set_cpu_possible(i, false);
-}
-
 void smp_fill_in_sib_core_maps(void)
 {
 	unsigned int i;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/kernel/syscalls/syscall.tbl
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/kernel/syscalls/syscall.tbl
@@ -117,7 +117,7 @@
 90	common	dup2			sys_dup2
 91	32	setfsuid32		sys_setfsuid
 92	common	fcntl			sys_fcntl			compat_sys_fcntl
-93	common	select			sys_select
+93	common	select			sys_select			compat_sys_select
 94	32	setfsgid32		sys_setfsgid
 95	common	fsync			sys_fsync
 96	common	setpriority		sys_setpriority
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/kernel/traps_32.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/kernel/traps_32.c
@@ -86,9 +86,7 @@
 	}
 	printk("Instruction DUMP:");
 	instruction_dump ((unsigned long *) regs->pc);
-	if(regs->psr & PSR_PS)
-		do_exit(SIGKILL);
-	do_exit(SIGSEGV);
+	make_task_dead((regs->psr & PSR_PS) ? SIGKILL : SIGSEGV);
 }
 
 void do_hw_interrupt(struct pt_regs *regs, unsigned long type)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/kernel/traps_64.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/kernel/traps_64.c
@@ -275,14 +275,13 @@
 			asi = (regs->tstate >> 24); /* saved %asi       */
 		else
 			asi = (insn >> 5);	    /* immediate asi    */
-		if ((asi & 0xf2) == ASI_PNF) {
-			if (insn & 0x1000000) {     /* op3[5:4]=3       */
-				handle_ldf_stq(insn, regs);
-				return true;
-			} else if (insn & 0x200000) { /* op3[2], stores */
+		if ((asi & 0xf6) == ASI_PNF) {
+			if (insn & 0x200000)        /* op3[2], stores   */
 				return false;
-			}
-			handle_ld_nf(insn, regs);
+			if (insn & 0x1000000)       /* op3[5:4]=3 (fp)  */
+				handle_ldf_stq(insn, regs);
+			else
+				handle_ld_nf(insn, regs);
 			return true;
 		}
 	}
@@ -2565,9 +2564,7 @@
 	}
 	if (panic_on_oops)
 		panic("Fatal exception");
-	if (regs->tstate & TSTATE_PRIV)
-		do_exit(SIGKILL);
-	do_exit(SIGSEGV);
+	make_task_dead((regs->tstate & TSTATE_PRIV)? SIGKILL : SIGSEGV);
 }
 EXPORT_SYMBOL(die_if_kernel);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/kernel/vmlinux.lds.S
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/kernel/vmlinux.lds.S
@@ -172,12 +172,14 @@
 	}
 	PERCPU_SECTION(SMP_CACHE_BYTES)
 
-#ifdef CONFIG_JUMP_LABEL
 	. = ALIGN(PAGE_SIZE);
 	.exit.text : {
 		EXIT_TEXT
 	}
-#endif
+
+	.exit.data : {
+		EXIT_DATA
+	}
 
 	. = ALIGN(PAGE_SIZE);
 	__init_end = .;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/lib/iomap.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/lib/iomap.c
@@ -19,8 +19,10 @@
 EXPORT_SYMBOL(ioport_map);
 EXPORT_SYMBOL(ioport_unmap);
 
+#ifdef CONFIG_PCI
 void pci_iounmap(struct pci_dev *dev, void __iomem * addr)
 {
 	/* nothing to do */
 }
 EXPORT_SYMBOL(pci_iounmap);
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/lib/memset.S
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/lib/memset.S
@@ -142,6 +142,7 @@
 	ZERO_LAST_BLOCKS(%o0, 0x48, %g2)
 	ZERO_LAST_BLOCKS(%o0, 0x08, %g2)
 13:
+	EXT(12b, 13b, 21f)
 	be	8f
 	 andcc	%o1, 4, %g0
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/mm/init_32.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/mm/init_32.c
@@ -197,6 +197,9 @@
 	size = memblock_phys_mem_size() - memblock_reserved_size();
 	*pages_avail = (size >> PAGE_SHIFT) - high_pages;
 
+	/* Only allow low memory to be allocated via memblock allocation */
+	memblock_set_current_limit(max_low_pfn << PAGE_SHIFT);
+
 	return max_pfn;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/mm/init_64.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/mm/init_64.c
@@ -2904,7 +2904,7 @@
 	if (!page)
 		return NULL;
 	if (!pgtable_pte_page_ctor(page)) {
-		free_unref_page(page);
+		__free_page(page);
 		return NULL;
 	}
 	return (pte_t *) page_address(page);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/mm/srmmu.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/mm/srmmu.c
@@ -379,7 +379,6 @@
 		return NULL;
 	page = pfn_to_page(__nocache_pa(pte) >> PAGE_SHIFT);
 	if (!pgtable_pte_page_ctor(page)) {
-		__free_page(page);
 		return NULL;
 	}
 	return page;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/net/bpf_jit_comp_64.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/net/bpf_jit_comp_64.c
@@ -1287,6 +1287,9 @@
 			return 1;
 		break;
 	}
+	/* speculation barrier */
+	case BPF_ST | BPF_NOSPEC:
+		break;
 	/* ST: *(size *)(dst + off) = imm */
 	case BPF_ST | BPF_MEM | BPF_W:
 	case BPF_ST | BPF_MEM | BPF_H:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/prom/init_64.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/prom/init_64.c
@@ -26,9 +26,6 @@
  * routines in the prom library.
  * It gets passed the pointer to the PROM vector.
  */
-
-extern void prom_cif_init(void *);
-
 void __init prom_init(void *cif_handler)
 {
 	phandle node;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/prom/p1275.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/prom/p1275.c
@@ -49,7 +49,7 @@
 	local_irq_restore(flags);
 }
 
-void prom_cif_init(void *cif_handler, void *cif_stack)
+void prom_cif_init(void *cif_handler)
 {
 	p1275buf.prom_cif_handler = (void (*)(long *))cif_handler;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/sparc/vdso/vma.c
+++ linux-xilinx-zynqmp-5.4.0/arch/sparc/vdso/vma.c
@@ -449,9 +449,8 @@
 	unsigned long val;
 
 	err = kstrtoul(s, 10, &val);
-	if (err)
-		return err;
-	vdso_enabled = val;
-	return 0;
+	if (!err)
+		vdso_enabled = val;
+	return 1;
 }
 __setup("vdso=", vdso_setup);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/um/Kconfig
@@ -5,6 +5,7 @@
 config UML
 	bool
 	default y
+	select ARCH_HAS_CPU_FINALIZE_INIT
 	select ARCH_HAS_KCOV
 	select ARCH_NO_PREEMPT
 	select HAVE_ARCH_AUDITSYSCALL
@@ -14,6 +15,7 @@
 	select HAVE_FUTEX_CMPXCHG if FUTEX
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DEBUG_BUGVERBOSE
+	select HAVE_COPY_THREAD_TLS
 	select GENERIC_IRQ_SHOW
 	select GENERIC_CPU_DEVICES
 	select GENERIC_CLOCKEVENTS
@@ -83,6 +85,19 @@
 	depends on !LD_SCRIPT_STATIC
 	select MODULE_REL_CRCS if MODVERSIONS
 
+config LD_SCRIPT_DYN_RPATH
+	bool "set rpath in the binary" if EXPERT
+	default y
+	depends on LD_SCRIPT_DYN
+	help
+	  Add /lib (and /lib64 for 64-bit) to the linux binary's rpath
+	  explicitly.
+
+	  You may need to turn this off if compiling for nix systems
+	  that have their libraries in random /nix directories and
+	  might otherwise unexpected use libraries from /lib or /lib64
+	  instead of the desired ones.
+
 config HOSTFS
 	tristate "Host filesystem"
 	help
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/Kconfig.debug
+++ linux-xilinx-zynqmp-5.4.0/arch/um/Kconfig.debug
@@ -17,6 +17,7 @@
 	bool "Enable gcov support"
 	depends on DEBUG_INFO
 	depends on !KCOV
+	depends on !MODULES
 	help
 	  This option allows developers to retrieve coverage data from a UML
 	  session.
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/um/Makefile
@@ -118,7 +118,8 @@
 	$(Q)$(MAKE) $(build)=$(HOST_DIR)/um include/generated/user_constants.h
 
 LINK-$(CONFIG_LD_SCRIPT_STATIC) += -static
-LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib $(call cc-option, -no-pie)
+LINK-$(CONFIG_LD_SCRIPT_DYN) += $(call cc-option, -no-pie)
+LINK-$(CONFIG_LD_SCRIPT_DYN_RPATH) += -Wl,-rpath,/lib
 
 CFLAGS_NO_HARDENING := $(call cc-option, -fno-PIC,) $(call cc-option, -fno-pic,) \
 	$(call cc-option, -fno-stack-protector,) \
@@ -132,14 +133,23 @@
 # The wrappers will select whether using "malloc" or the kernel allocator.
 LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc
 
+# Avoid binutils 2.39+ warnings by marking the stack non-executable and
+# ignorning warnings for the kallsyms sections.
+LDFLAGS_EXECSTACK = -z noexecstack
+ifeq ($(CONFIG_LD_IS_BFD),y)
+LDFLAGS_EXECSTACK += $(call ld-option,--no-warn-rwx-segments)
+endif
+
 LD_FLAGS_CMDLINE = $(foreach opt,$(KBUILD_LDFLAGS),-Wl,$(opt))
 
 # Used by link-vmlinux.sh which has special support for um link
 export CFLAGS_vmlinux := $(LINK-y) $(LINK_WRAPS) $(LD_FLAGS_CMDLINE)
+export LDFLAGS_vmlinux := $(LDFLAGS_EXECSTACK)
 
 # When cleaning we don't include .config, so we don't include
 # TT or skas makefiles and don't clean skas_ptregs.h.
 CLEAN_FILES += linux x.i gmon.out
+MRPROPER_DIRS += arch/$(SUBARCH)/include/generated
 
 archclean:
 	@find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/configs/i386_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/um/configs/i386_defconfig
@@ -35,6 +35,7 @@
 CONFIG_XTERM_CHAN=y
 CONFIG_CON_CHAN="pts"
 CONFIG_SSL_CHAN="pts"
+CONFIG_SOUND=m
 CONFIG_UML_SOUND=m
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/configs/x86_64_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/um/configs/x86_64_defconfig
@@ -33,6 +33,7 @@
 CONFIG_XTERM_CHAN=y
 CONFIG_CON_CHAN="pts"
 CONFIG_SSL_CHAN="pts"
+CONFIG_SOUND=m
 CONFIG_UML_SOUND=m
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/drivers/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/um/drivers/Kconfig
@@ -104,24 +104,14 @@
 
 config UML_SOUND
 	tristate "Sound support"
+	depends on SOUND
+	select SOUND_OSS_CORE
 	help
 	  This option enables UML sound support.  If enabled, it will pull in
-	  soundcore and the UML hostaudio relay, which acts as a intermediary
+	  the UML hostaudio relay, which acts as a intermediary
 	  between the host's dsp and mixer devices and the UML sound system.
 	  It is safe to say 'Y' here.
 
-config SOUND
-	tristate
-	default UML_SOUND
-
-config SOUND_OSS_CORE
-	bool
-	default UML_SOUND
-
-config HOSTAUDIO
-	tristate
-	default UML_SOUND
-
 endmenu
 
 menu "UML Network Devices"
@@ -337,7 +327,7 @@
 endmenu
 
 config VIRTIO_UML
-	tristate "UML driver for virtio devices"
+	bool "UML driver for virtio devices"
 	select VIRTIO
 	help
 	  This driver provides support for virtio based paravirtual device
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/drivers/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/um/drivers/Makefile
@@ -52,7 +52,7 @@
 obj-$(CONFIG_MCONSOLE) += mconsole.o
 obj-$(CONFIG_MMAPPER) += mmapper_kern.o 
 obj-$(CONFIG_BLK_DEV_UBD) += ubd.o 
-obj-$(CONFIG_HOSTAUDIO) += hostaudio.o
+obj-$(CONFIG_UML_SOUND) += hostaudio.o
 obj-$(CONFIG_NULL_CHAN) += null.o 
 obj-$(CONFIG_PORT_CHAN) += port.o
 obj-$(CONFIG_PTY_CHAN) += pty.o
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/drivers/chan_user.c
+++ linux-xilinx-zynqmp-5.4.0/arch/um/drivers/chan_user.c
@@ -26,10 +26,10 @@
 	n = read(fd, c_out, sizeof(*c_out));
 	if (n > 0)
 		return n;
-	else if (errno == EAGAIN)
-		return 0;
 	else if (n == 0)
 		return -EIO;
+	else if (errno == EAGAIN)
+		return 0;
 	return -errno;
 }
 
@@ -220,7 +220,7 @@
 		       unsigned long *stack_out)
 {
 	struct winch_data data;
-	int fds[2], n, err;
+	int fds[2], n, err, pid;
 	char c;
 
 	err = os_pipe(fds, 1, 1);
@@ -238,8 +238,9 @@
 	 * problem with /dev/net/tun, which if held open by this
 	 * thread, prevents the TUN/TAP device from being reused.
 	 */
-	err = run_helper_thread(winch_thread, &data, CLONE_FILES, stack_out);
-	if (err < 0) {
+	pid = run_helper_thread(winch_thread, &data, CLONE_FILES, stack_out);
+	if (pid < 0) {
+		err = pid;
 		printk(UM_KERN_ERR "fork of winch_thread failed - errno = %d\n",
 		       -err);
 		goto out_close;
@@ -256,13 +257,14 @@
 		goto out_close;
 	}
 
-	if (os_set_fd_block(*fd_out, 0)) {
+	err = os_set_fd_block(*fd_out, 0);
+	if (err) {
 		printk(UM_KERN_ERR "winch_tramp: failed to set thread_fd "
 		       "non-blocking.\n");
 		goto out_close;
 	}
 
-	return err;
+	return pid;
 
  out_close:
 	close(fds[1]);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/drivers/line.c
+++ linux-xilinx-zynqmp-5.4.0/arch/um/drivers/line.c
@@ -383,6 +383,7 @@
 			parse_chan_pair(NULL, line, n, opts, error_out);
 			err = 0;
 		}
+		*error_out = "configured as 'none'";
 	} else {
 		char *new = kstrdup(init, GFP_KERNEL);
 		if (!new) {
@@ -406,6 +407,7 @@
 			}
 		}
 		if (err) {
+			*error_out = "failed to parse channel pair";
 			line->init_str = NULL;
 			line->valid = 0;
 			kfree(new);
@@ -673,24 +675,26 @@
 		goto cleanup;
 	}
 
-	*winch = ((struct winch) { .list  	= LIST_HEAD_INIT(winch->list),
-				   .fd  	= fd,
+	*winch = ((struct winch) { .fd  	= fd,
 				   .tty_fd 	= tty_fd,
 				   .pid  	= pid,
 				   .port 	= port,
 				   .stack	= stack });
 
+	spin_lock(&winch_handler_lock);
+	list_add(&winch->list, &winch_handlers);
+	spin_unlock(&winch_handler_lock);
+
 	if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
 			   IRQF_SHARED, "winch", winch) < 0) {
 		printk(KERN_ERR "register_winch_irq - failed to register "
 		       "IRQ\n");
+		spin_lock(&winch_handler_lock);
+		list_del(&winch->list);
+		spin_unlock(&winch_handler_lock);
 		goto out_free;
 	}
 
-	spin_lock(&winch_handler_lock);
-	list_add(&winch->list, &winch_handlers);
-	spin_unlock(&winch_handler_lock);
-
 	return;
 
  out_free:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/drivers/mconsole_kern.c
+++ linux-xilinx-zynqmp-5.4.0/arch/um/drivers/mconsole_kern.c
@@ -217,7 +217,7 @@
 
 void mconsole_stop(struct mc_request *req)
 {
-	deactivate_fd(req->originating_fd, MCONSOLE_IRQ);
+	block_signals();
 	os_set_fd_block(req->originating_fd, 1);
 	mconsole_reply(req, "stopped", 0, 0);
 	for (;;) {
@@ -240,6 +240,7 @@
 	}
 	os_set_fd_block(req->originating_fd, 0);
 	mconsole_reply(req, "", 0, 0);
+	unblock_signals();
 }
 
 static DEFINE_SPINLOCK(mc_devices_lock);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/drivers/net_kern.c
+++ linux-xilinx-zynqmp-5.4.0/arch/um/drivers/net_kern.c
@@ -204,7 +204,7 @@
 	return 0;
 }
 
-static int uml_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t uml_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct uml_net_private *lp = netdev_priv(dev);
 	unsigned long flags;
@@ -347,7 +347,7 @@
 
 static void net_device_release(struct device *dev)
 {
-	struct uml_net *device = dev_get_drvdata(dev);
+	struct uml_net *device = container_of(dev, struct uml_net, pdev.dev);
 	struct net_device *netdev = device->dev;
 	struct uml_net_private *lp = netdev_priv(netdev);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/drivers/slip_user.c
+++ linux-xilinx-zynqmp-5.4.0/arch/um/drivers/slip_user.c
@@ -145,7 +145,8 @@
 	}
 	sfd = err;
 
-	if (set_up_tty(sfd))
+	err = set_up_tty(sfd);
+	if (err)
 		goto out_close2;
 
 	pri->slave = sfd;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/drivers/ubd_kern.c
+++ linux-xilinx-zynqmp-5.4.0/arch/um/drivers/ubd_kern.c
@@ -47,18 +47,25 @@
 /* Max request size is determined by sector mask - 32K */
 #define UBD_MAX_REQUEST (8 * sizeof(long))
 
+struct io_desc {
+	char *buffer;
+	unsigned long length;
+	unsigned long sector_mask;
+	unsigned long long cow_offset;
+	unsigned long bitmap_words[2];
+};
+
 struct io_thread_req {
 	struct request *req;
 	int fds[2];
 	unsigned long offsets[2];
 	unsigned long long offset;
-	unsigned long length;
-	char *buffer;
 	int sectorsize;
-	unsigned long sector_mask;
-	unsigned long long cow_offset;
-	unsigned long bitmap_words[2];
 	int error;
+
+	int desc_cnt;
+	/* io_desc has to be the last element of the struct */
+	struct io_desc io_desc[];
 };
 
 
@@ -524,12 +531,7 @@
 				blk_queue_max_write_zeroes_sectors(io_req->req->q, 0);
 				blk_queue_flag_clear(QUEUE_FLAG_DISCARD, io_req->req->q);
 			}
-			if ((io_req->error) || (io_req->buffer == NULL))
-				blk_mq_end_request(io_req->req, io_req->error);
-			else {
-				if (!blk_update_request(io_req->req, io_req->error, io_req->length))
-					__blk_mq_end_request(io_req->req, io_req->error);
-			}
+			blk_mq_end_request(io_req->req, io_req->error);
 			kfree(io_req);
 		}
 	}
@@ -858,7 +860,7 @@
 
 static void ubd_device_release(struct device *dev)
 {
-	struct ubd *ubd_dev = dev_get_drvdata(dev);
+	struct ubd *ubd_dev = container_of(dev, struct ubd, pdev.dev);
 
 	blk_cleanup_queue(ubd_dev->queue);
 	blk_mq_free_tag_set(&ubd_dev->tag_set);
@@ -945,6 +947,7 @@
 	blk_queue_write_cache(ubd_dev->queue, true, false);
 
 	blk_queue_max_segments(ubd_dev->queue, MAX_SG);
+	blk_queue_segment_boundary(ubd_dev->queue, PAGE_SIZE - 1);
 	err = ubd_disk_register(UBD_MAJOR, ubd_dev->size, n, &ubd_gendisk[n]);
 	if(err){
 		*error_out = "Failed to register device";
@@ -1154,7 +1157,7 @@
 
 	if (irq_req_buffer == NULL) {
 		printk(KERN_ERR "Failed to initialize ubd buffering\n");
-		return -1;
+		return -ENOMEM;
 	}
 	io_req_buffer = kmalloc_array(UBD_REQ_BUFFER_SIZE,
 				      sizeof(struct io_thread_req *),
@@ -1165,7 +1168,7 @@
 
 	if (io_req_buffer == NULL) {
 		printk(KERN_ERR "Failed to initialize ubd buffering\n");
-		return -1;
+		return -ENOMEM;
 	}
 	platform_driver_register(&ubd_driver);
 	mutex_lock(&ubd_lock);
@@ -1288,37 +1291,74 @@
 	*cow_offset += bitmap_offset;
 }
 
-static void cowify_req(struct io_thread_req *req, unsigned long *bitmap,
+static void cowify_req(struct io_thread_req *req, struct io_desc *segment,
+		       unsigned long offset, unsigned long *bitmap,
 		       __u64 bitmap_offset, __u64 bitmap_len)
 {
-	__u64 sector = req->offset >> SECTOR_SHIFT;
+	__u64 sector = offset >> SECTOR_SHIFT;
 	int i;
 
-	if (req->length > (sizeof(req->sector_mask) * 8) << SECTOR_SHIFT)
+	if (segment->length > (sizeof(segment->sector_mask) * 8) << SECTOR_SHIFT)
 		panic("Operation too long");
 
 	if (req_op(req->req) == REQ_OP_READ) {
-		for (i = 0; i < req->length >> SECTOR_SHIFT; i++) {
+		for (i = 0; i < segment->length >> SECTOR_SHIFT; i++) {
 			if(ubd_test_bit(sector + i, (unsigned char *) bitmap))
 				ubd_set_bit(i, (unsigned char *)
-					    &req->sector_mask);
+					    &segment->sector_mask);
+		}
+	} else {
+		cowify_bitmap(offset, segment->length, &segment->sector_mask,
+			      &segment->cow_offset, bitmap, bitmap_offset,
+			      segment->bitmap_words, bitmap_len);
+	}
+}
+
+static void ubd_map_req(struct ubd *dev, struct io_thread_req *io_req,
+			struct request *req)
+{
+	struct bio_vec bvec;
+	struct req_iterator iter;
+	int i = 0;
+	unsigned long byte_offset = io_req->offset;
+	int op = req_op(req);
+
+	if (op == REQ_OP_WRITE_ZEROES || op == REQ_OP_DISCARD) {
+		io_req->io_desc[0].buffer = NULL;
+		io_req->io_desc[0].length = blk_rq_bytes(req);
+	} else {
+		rq_for_each_segment(bvec, req, iter) {
+			BUG_ON(i >= io_req->desc_cnt);
+
+			io_req->io_desc[i].buffer =
+				page_address(bvec.bv_page) + bvec.bv_offset;
+			io_req->io_desc[i].length = bvec.bv_len;
+			i++;
+		}
+	}
+
+	if (dev->cow.file) {
+		for (i = 0; i < io_req->desc_cnt; i++) {
+			cowify_req(io_req, &io_req->io_desc[i], byte_offset,
+				   dev->cow.bitmap, dev->cow.bitmap_offset,
+				   dev->cow.bitmap_len);
+			byte_offset += io_req->io_desc[i].length;
 		}
+
 	}
-	else cowify_bitmap(req->offset, req->length, &req->sector_mask,
-			   &req->cow_offset, bitmap, bitmap_offset,
-			   req->bitmap_words, bitmap_len);
 }
 
-static int ubd_queue_one_vec(struct blk_mq_hw_ctx *hctx, struct request *req,
-		u64 off, struct bio_vec *bvec)
+static struct io_thread_req *ubd_alloc_req(struct ubd *dev, struct request *req,
+					   int desc_cnt)
 {
-	struct ubd *dev = hctx->queue->queuedata;
 	struct io_thread_req *io_req;
-	int ret;
+	int i;
 
-	io_req = kmalloc(sizeof(struct io_thread_req), GFP_ATOMIC);
+	io_req = kmalloc(sizeof(*io_req) +
+			 (desc_cnt * sizeof(struct io_desc)),
+			 GFP_ATOMIC);
 	if (!io_req)
-		return -ENOMEM;
+		return NULL;
 
 	io_req->req = req;
 	if (dev->cow.file)
@@ -1326,26 +1366,41 @@
 	else
 		io_req->fds[0] = dev->fd;
 	io_req->error = 0;
-
-	if (bvec != NULL) {
-		io_req->buffer = page_address(bvec->bv_page) + bvec->bv_offset;
-		io_req->length = bvec->bv_len;
-	} else {
-		io_req->buffer = NULL;
-		io_req->length = blk_rq_bytes(req);
-	}
-
 	io_req->sectorsize = SECTOR_SIZE;
 	io_req->fds[1] = dev->fd;
-	io_req->cow_offset = -1;
-	io_req->offset = off;
-	io_req->sector_mask = 0;
+	io_req->offset = (u64) blk_rq_pos(req) << SECTOR_SHIFT;
 	io_req->offsets[0] = 0;
 	io_req->offsets[1] = dev->cow.data_offset;
 
-	if (dev->cow.file)
-		cowify_req(io_req, dev->cow.bitmap,
-			   dev->cow.bitmap_offset, dev->cow.bitmap_len);
+	for (i = 0 ; i < desc_cnt; i++) {
+		io_req->io_desc[i].sector_mask = 0;
+		io_req->io_desc[i].cow_offset = -1;
+	}
+
+	return io_req;
+}
+
+static int ubd_submit_request(struct ubd *dev, struct request *req)
+{
+	int segs = 0;
+	struct io_thread_req *io_req;
+	int ret;
+	int op = req_op(req);
+
+	if (op == REQ_OP_FLUSH)
+		segs = 0;
+	else if (op == REQ_OP_WRITE_ZEROES || op == REQ_OP_DISCARD)
+		segs = 1;
+	else
+		segs = blk_rq_nr_phys_segments(req);
+
+	io_req = ubd_alloc_req(dev, req, segs);
+	if (!io_req)
+		return -ENOMEM;
+
+	io_req->desc_cnt = segs;
+	if (segs)
+		ubd_map_req(dev, io_req, req);
 
 	ret = os_write_file(thread_fd, &io_req, sizeof(io_req));
 	if (ret != sizeof(io_req)) {
@@ -1356,22 +1411,6 @@
 	return ret;
 }
 
-static int queue_rw_req(struct blk_mq_hw_ctx *hctx, struct request *req)
-{
-	struct req_iterator iter;
-	struct bio_vec bvec;
-	int ret;
-	u64 off = (u64)blk_rq_pos(req) << SECTOR_SHIFT;
-
-	rq_for_each_segment(bvec, req, iter) {
-		ret = ubd_queue_one_vec(hctx, req, off, &bvec);
-		if (ret < 0)
-			return ret;
-		off += bvec.bv_len;
-	}
-	return 0;
-}
-
 static blk_status_t ubd_queue_rq(struct blk_mq_hw_ctx *hctx,
 				 const struct blk_mq_queue_data *bd)
 {
@@ -1384,17 +1423,12 @@
 	spin_lock_irq(&ubd_dev->lock);
 
 	switch (req_op(req)) {
-	/* operations with no lentgth/offset arguments */
 	case REQ_OP_FLUSH:
-		ret = ubd_queue_one_vec(hctx, req, 0, NULL);
-		break;
 	case REQ_OP_READ:
 	case REQ_OP_WRITE:
-		ret = queue_rw_req(hctx, req);
-		break;
 	case REQ_OP_DISCARD:
 	case REQ_OP_WRITE_ZEROES:
-		ret = ubd_queue_one_vec(hctx, req, (u64)blk_rq_pos(req) << 9, NULL);
+		ret = ubd_submit_request(ubd_dev, req);
 		break;
 	default:
 		WARN_ON_ONCE(1);
@@ -1482,22 +1516,22 @@
  * will result in unpredictable behaviour and/or crashes.
  */
 
-static int update_bitmap(struct io_thread_req *req)
+static int update_bitmap(struct io_thread_req *req, struct io_desc *segment)
 {
 	int n;
 
-	if(req->cow_offset == -1)
+	if (segment->cow_offset == -1)
 		return map_error(0);
 
-	n = os_pwrite_file(req->fds[1], &req->bitmap_words,
-			  sizeof(req->bitmap_words), req->cow_offset);
-	if (n != sizeof(req->bitmap_words))
+	n = os_pwrite_file(req->fds[1], &segment->bitmap_words,
+			  sizeof(segment->bitmap_words), segment->cow_offset);
+	if (n != sizeof(segment->bitmap_words))
 		return map_error(-n);
 
 	return map_error(0);
 }
 
-static void do_io(struct io_thread_req *req)
+static void do_io(struct io_thread_req *req, struct io_desc *desc)
 {
 	char *buf = NULL;
 	unsigned long len;
@@ -1512,21 +1546,20 @@
 		return;
 	}
 
-	nsectors = req->length / req->sectorsize;
+	nsectors = desc->length / req->sectorsize;
 	start = 0;
 	do {
-		bit = ubd_test_bit(start, (unsigned char *) &req->sector_mask);
+		bit = ubd_test_bit(start, (unsigned char *) &desc->sector_mask);
 		end = start;
 		while((end < nsectors) &&
-		      (ubd_test_bit(end, (unsigned char *)
-				    &req->sector_mask) == bit))
+		      (ubd_test_bit(end, (unsigned char *) &desc->sector_mask) == bit))
 			end++;
 
 		off = req->offset + req->offsets[bit] +
 			start * req->sectorsize;
 		len = (end - start) * req->sectorsize;
-		if (req->buffer != NULL)
-			buf = &req->buffer[start * req->sectorsize];
+		if (desc->buffer != NULL)
+			buf = &desc->buffer[start * req->sectorsize];
 
 		switch (req_op(req->req)) {
 		case REQ_OP_READ:
@@ -1566,7 +1599,8 @@
 		start = end;
 	} while(start < nsectors);
 
-	req->error = update_bitmap(req);
+	req->offset += len;
+	req->error = update_bitmap(req, desc);
 }
 
 /* Changed in start_io_thread, which is serialized by being called only
@@ -1599,14 +1633,21 @@
 		}
 
 		for (count = 0; count < n/sizeof(struct io_thread_req *); count++) {
+			struct io_thread_req *req = (*io_req_buffer)[count];
+			int i;
+
 			io_count++;
-			do_io((*io_req_buffer)[count]);
+			for (i = 0; !req->error && i < req->desc_cnt; i++)
+				do_io(req, &(req->io_desc[i]));
+
 		}
 
 		written = 0;
 
 		do {
-			res = os_write_file(kernel_fd, ((char *) io_req_buffer) + written, n);
+			res = os_write_file(kernel_fd,
+					    ((char *) io_req_buffer) + written,
+					    n - written);
 			if (res >= 0) {
 				written += res;
 			}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/drivers/vector_kern.c
+++ linux-xilinx-zynqmp-5.4.0/arch/um/drivers/vector_kern.c
@@ -746,6 +746,7 @@
 
 	if (parsed == NULL) {
 		*error_out = "vector_config failed to parse parameters";
+		kfree(params);
 		return -EINVAL;
 	}
 
@@ -801,7 +802,8 @@
 
 static void vector_device_release(struct device *dev)
 {
-	struct vector_device *device = dev_get_drvdata(dev);
+	struct vector_device *device =
+		container_of(dev, struct vector_device, pdev.dev);
 	struct net_device *netdev = device->dev;
 
 	list_del(&device->list);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/drivers/virtio_uml.c
+++ linux-xilinx-zynqmp-5.4.0/arch/um/drivers/virtio_uml.c
@@ -4,12 +4,12 @@
  *
  * Copyright(c) 2019 Intel Corporation
  *
- * This module allows virtio devices to be used over a vhost-user socket.
+ * This driver allows virtio devices to be used over a vhost-user socket.
  *
  * Guest devices can be instantiated by kernel module or command line
  * parameters. One device will be created for each parameter. Syntax:
  *
- *		[virtio_uml.]device=<socket>:<virtio_id>[:<platform_id>]
+ *		virtio_uml.device=<socket>:<virtio_id>[:<platform_id>]
  * where:
  *		<socket>	:= vhost-user socket path to connect
  *		<virtio_id>	:= virtio device id (as in virtio_ids.h)
@@ -83,7 +83,7 @@
 	return 0;
 }
 
-static int full_read(int fd, void *buf, int len)
+static int full_read(int fd, void *buf, int len, bool abortable)
 {
 	int rc;
 
@@ -93,7 +93,7 @@
 			buf += rc;
 			len -= rc;
 		}
-	} while (len && (rc > 0 || rc == -EINTR));
+	} while (len && (rc > 0 || rc == -EINTR || (!abortable && rc == -EAGAIN)));
 
 	if (rc < 0)
 		return rc;
@@ -104,7 +104,7 @@
 
 static int vhost_user_recv_header(int fd, struct vhost_user_msg *msg)
 {
-	return full_read(fd, msg, sizeof(msg->header));
+	return full_read(fd, msg, sizeof(msg->header), true);
 }
 
 static int vhost_user_recv(int fd, struct vhost_user_msg *msg,
@@ -118,7 +118,7 @@
 	size = msg->header.size;
 	if (size > max_payload_size)
 		return -EPROTO;
-	return full_read(fd, &msg->payload, size);
+	return full_read(fd, &msg->payload, size, false);
 }
 
 static int vhost_user_recv_resp(struct virtio_uml_device *vu_dev,
@@ -959,6 +959,7 @@
 	}
 
 	os_close_file(vu_dev->sock);
+	kfree(vu_dev);
 }
 
 /* Platform device */
@@ -977,7 +978,7 @@
 	if (!pdata)
 		return -EINVAL;
 
-	vu_dev = devm_kzalloc(&pdev->dev, sizeof(*vu_dev), GFP_KERNEL);
+	vu_dev = kzalloc(sizeof(*vu_dev), GFP_KERNEL);
 	if (!vu_dev)
 		return -ENOMEM;
 
@@ -993,7 +994,7 @@
 		rc = os_connect_socket(pdata->socket_path);
 	} while (rc == -EINTR);
 	if (rc < 0)
-		return rc;
+		goto error_free;
 	vu_dev->sock = rc;
 
 	rc = vhost_user_init(vu_dev);
@@ -1009,6 +1010,8 @@
 
 error_init:
 	os_close_file(vu_dev->sock);
+error_free:
+	kfree(vu_dev);
 	return rc;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/drivers/xterm.c
+++ linux-xilinx-zynqmp-5.4.0/arch/um/drivers/xterm.c
@@ -18,6 +18,7 @@
 struct xterm_chan {
 	int pid;
 	int helper_pid;
+	int chan_fd;
 	char *title;
 	int device;
 	int raw;
@@ -33,6 +34,7 @@
 		return NULL;
 	*data = ((struct xterm_chan) { .pid 		= -1,
 				       .helper_pid 	= -1,
+				       .chan_fd		= -1,
 				       .device 		= device,
 				       .title 		= opts->xterm_title,
 				       .raw  		= opts->raw } );
@@ -149,6 +151,7 @@
 		goto out_kill;
 	}
 
+	data->chan_fd = fd;
 	new = xterm_fd(fd, &data->helper_pid);
 	if (new < 0) {
 		err = new;
@@ -206,6 +209,8 @@
 		os_kill_process(data->helper_pid, 0);
 	data->helper_pid = -1;
 
+	if (data->chan_fd != -1)
+		os_close_file(data->chan_fd);
 	os_close_file(fd);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/include/asm/common.lds.S
+++ linux-xilinx-zynqmp-5.4.0/arch/um/include/asm/common.lds.S
@@ -83,8 +83,8 @@
 	__preinit_array_end = .;
   }
   .init_array : {
-        /* dummy - we call this ourselves */
 	__init_array_start = .;
+	*(.init_array)
 	__init_array_end = .;
   }
   .fini_array : {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/include/asm/mmu.h
+++ linux-xilinx-zynqmp-5.4.0/arch/um/include/asm/mmu.h
@@ -15,8 +15,6 @@
 	struct page *stub_pages[2];
 } mm_context_t;
 
-extern void __switch_mm(struct mm_id * mm_idp);
-
 /* Avoid tangled inclusion with asm/ldt.h */
 extern long init_new_ldt(struct mm_context *to_mm, struct mm_context *from_mm);
 extern void free_ldt(struct mm_context *mm);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/include/asm/ptrace-generic.h
+++ linux-xilinx-zynqmp-5.4.0/arch/um/include/asm/ptrace-generic.h
@@ -36,7 +36,7 @@
 extern unsigned long getreg(struct task_struct *child, int regno);
 extern int putreg(struct task_struct *child, int regno, unsigned long value);
 
-extern int arch_copy_tls(struct task_struct *new);
+extern int arch_set_tls(struct task_struct *new, unsigned long tls);
 extern void clear_flushed_tls(struct task_struct *task);
 extern int syscall_trace_enter(struct pt_regs *regs);
 extern void syscall_trace_leave(struct pt_regs *regs);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/include/asm/thread_info.h
+++ linux-xilinx-zynqmp-5.4.0/arch/um/include/asm/thread_info.h
@@ -63,6 +63,7 @@
 #define TIF_RESTORE_SIGMASK	7
 #define TIF_NOTIFY_RESUME	8
 #define TIF_SECCOMP		9	/* secure computing */
+#define TIF_SINGLESTEP		10	/* single stepping userspace */
 
 #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
@@ -70,5 +71,6 @@
 #define _TIF_MEMDIE		(1 << TIF_MEMDIE)
 #define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP		(1 << TIF_SECCOMP)
+#define _TIF_SINGLESTEP		(1 << TIF_SINGLESTEP)
 
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/include/asm/timex.h
+++ linux-xilinx-zynqmp-5.4.0/arch/um/include/asm/timex.h
@@ -2,13 +2,8 @@
 #ifndef __UM_TIMEX_H
 #define __UM_TIMEX_H
 
-typedef unsigned long cycles_t;
-
-static inline cycles_t get_cycles (void)
-{
-	return 0;
-}
-
 #define CLOCK_TICK_RATE (HZ)
 
+#include <asm-generic/timex.h>
+
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/include/shared/kern_util.h
+++ linux-xilinx-zynqmp-5.4.0/arch/um/include/shared/kern_util.h
@@ -49,7 +49,7 @@
  * Are we disallowed to sleep? Used to choose between GFP_KERNEL and
  * GFP_ATOMIC.
  */
-extern int __cant_sleep(void);
+extern int __uml_cant_sleep(void);
 extern int get_current_pid(void);
 extern int copy_from_user_proc(void *to, void *from, int size);
 extern int cpu(void);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/include/shared/registers.h
+++ linux-xilinx-zynqmp-5.4.0/arch/um/include/shared/registers.h
@@ -16,8 +16,8 @@
 extern int save_fpx_registers(int pid, unsigned long *fp_regs);
 extern int restore_fpx_registers(int pid, unsigned long *fp_regs);
 extern int save_registers(int pid, struct uml_pt_regs *regs);
-extern int restore_registers(int pid, struct uml_pt_regs *regs);
-extern int init_registers(int pid);
+extern int restore_pid_registers(int pid, struct uml_pt_regs *regs);
+extern int init_pid_registers(int pid);
 extern void get_safe_registers(unsigned long *regs, unsigned long *fp_regs);
 extern unsigned long get_thread_reg(int reg, jmp_buf *buf);
 extern int get_fp_registers(int pid, unsigned long *regs);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/include/shared/skas/mm_id.h
+++ linux-xilinx-zynqmp-5.4.0/arch/um/include/shared/skas/mm_id.h
@@ -14,4 +14,6 @@
 	unsigned long stack;
 };
 
+void __switch_mm(struct mm_id *mm_idp);
+
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/kernel/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/um/kernel/Makefile
@@ -21,7 +21,6 @@
 
 obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
 obj-$(CONFIG_GPROF)	+= gprof_syms.o
-obj-$(CONFIG_GCOV)	+= gmon_syms.o
 obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
 obj-$(CONFIG_STACKTRACE) += stacktrace.o
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/kernel/dyn.lds.S
+++ linux-xilinx-zynqmp-5.4.0/arch/um/kernel/dyn.lds.S
@@ -6,6 +6,12 @@
 ENTRY(_start)
 jiffies = jiffies_64;
 
+VERSION {
+  {
+    local: *;
+  };
+}
+
 SECTIONS
 {
   PROVIDE (__executable_start = START);
@@ -103,6 +109,7 @@
      be empty, which isn't pretty.  */
   . = ALIGN(32 / 8);
   .preinit_array     : { *(.preinit_array) }
+  .init_array     : { *(.init_array) }
   .fini_array     : { *(.fini_array) }
   .data           : {
     INIT_TASK_DATA(KERNEL_STACK_SIZE)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/kernel/exec.c
+++ linux-xilinx-zynqmp-5.4.0/arch/um/kernel/exec.c
@@ -44,7 +44,7 @@
 {
 	PT_REGS_IP(regs) = eip;
 	PT_REGS_SP(regs) = esp;
-	current->ptrace &= ~PT_DTRACE;
+	clear_thread_flag(TIF_SINGLESTEP);
 #ifdef SUBARCH_EXECVE1
 	SUBARCH_EXECVE1(regs->regs);
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/kernel/physmem.c
+++ linux-xilinx-zynqmp-5.4.0/arch/um/kernel/physmem.c
@@ -80,10 +80,10 @@
 			  unsigned long len, unsigned long long highmem)
 {
 	unsigned long reserve = reserve_end - start;
-	long map_size = len - reserve;
+	unsigned long map_size = len - reserve;
 	int err;
 
-	if(map_size <= 0) {
+	if (len <= reserve) {
 		os_warn("Too few physical memory! Needed=%lu, given=%lu\n",
 			reserve, len);
 		exit(1);
@@ -94,7 +94,7 @@
 	err = os_map_memory((void *) reserve_end, physmem_fd, reserve,
 			    map_size, 1, 1, 1);
 	if (err < 0) {
-		os_warn("setup_physmem - mapping %ld bytes of memory at 0x%p "
+		os_warn("setup_physmem - mapping %lu bytes of memory at 0x%p "
 			"failed - errno = %d\n", map_size,
 			(void *) reserve_end, err);
 		exit(1);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/kernel/process.c
+++ linux-xilinx-zynqmp-5.4.0/arch/um/kernel/process.c
@@ -153,8 +153,8 @@
 	userspace(&current->thread.regs.regs, current_thread_info()->aux_fp_regs);
 }
 
-int copy_thread(unsigned long clone_flags, unsigned long sp,
-		unsigned long arg, struct task_struct * p)
+int copy_thread_tls(unsigned long clone_flags, unsigned long sp,
+		unsigned long arg, struct task_struct * p, unsigned long tls)
 {
 	void (*handler)(void);
 	int kthread = current->flags & PF_KTHREAD;
@@ -188,7 +188,7 @@
 		 * Set a new TLS for the child thread?
 		 */
 		if (clone_flags & CLONE_SETTLS)
-			ret = arch_copy_tls(p);
+			ret = arch_set_tls(p, tls);
 	}
 
 	return ret;
@@ -258,7 +258,7 @@
 	local_irq_enable();
 }
 
-int __cant_sleep(void) {
+int __uml_cant_sleep(void) {
 	return in_atomic() || irqs_disabled() || in_interrupt();
 	/* Is in_interrupt() really needed? */
 }
@@ -380,7 +380,7 @@
 {
 	struct task_struct *task = t ? t : current;
 
-	if (!(task->ptrace & PT_DTRACE))
+	if (!test_thread_flag(TIF_SINGLESTEP))
 		return 0;
 
 	if (task->thread.singlestep_syscall)
@@ -444,6 +444,6 @@
 {
 	int cpu = current_thread_info()->cpu;
 
-	return save_i387_registers(userspace_pid[cpu], (unsigned long *) fpu);
+	return save_i387_registers(userspace_pid[cpu], (unsigned long *) fpu) == 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/kernel/ptrace.c
+++ linux-xilinx-zynqmp-5.4.0/arch/um/kernel/ptrace.c
@@ -12,7 +12,7 @@
 
 void user_enable_single_step(struct task_struct *child)
 {
-	child->ptrace |= PT_DTRACE;
+	set_tsk_thread_flag(child, TIF_SINGLESTEP);
 	child->thread.singlestep_syscall = 0;
 
 #ifdef SUBARCH_SET_SINGLESTEPPING
@@ -22,7 +22,7 @@
 
 void user_disable_single_step(struct task_struct *child)
 {
-	child->ptrace &= ~PT_DTRACE;
+	clear_tsk_thread_flag(child, TIF_SINGLESTEP);
 	child->thread.singlestep_syscall = 0;
 
 #ifdef SUBARCH_SET_SINGLESTEPPING
@@ -121,7 +121,7 @@
 }
 
 /*
- * XXX Check PT_DTRACE vs TIF_SINGLESTEP for singlestepping check and
+ * XXX Check TIF_SINGLESTEP for singlestepping check and
  * PT_PTRACED vs TIF_SYSCALL_TRACE for syscall tracing check
  */
 int syscall_trace_enter(struct pt_regs *regs)
@@ -145,7 +145,7 @@
 	audit_syscall_exit(regs);
 
 	/* Fake a debug trap */
-	if (ptraced & PT_DTRACE)
+	if (test_thread_flag(TIF_SINGLESTEP))
 		send_sigtrap(&regs->regs, 0);
 
 	if (!test_thread_flag(TIF_SYSCALL_TRACE))
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/kernel/sigio.c
+++ linux-xilinx-zynqmp-5.4.0/arch/um/kernel/sigio.c
@@ -35,14 +35,14 @@
 }
 
 /* These are called from os-Linux/sigio.c to protect its pollfds arrays. */
-static DEFINE_SPINLOCK(sigio_spinlock);
+static DEFINE_MUTEX(sigio_mutex);
 
 void sigio_lock(void)
 {
-	spin_lock(&sigio_spinlock);
+	mutex_lock(&sigio_mutex);
 }
 
 void sigio_unlock(void)
 {
-	spin_unlock(&sigio_spinlock);
+	mutex_unlock(&sigio_mutex);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/kernel/signal.c
+++ linux-xilinx-zynqmp-5.4.0/arch/um/kernel/signal.c
@@ -53,7 +53,7 @@
 	unsigned long sp;
 	int err;
 
-	if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
+	if (test_thread_flag(TIF_SINGLESTEP) && (current->ptrace & PT_PTRACED))
 		singlestep = 1;
 
 	/* Did we come from a system call? */
@@ -128,7 +128,7 @@
 	 * on the host.  The tracing thread will check this flag and
 	 * PTRACE_SYSCALL if necessary.
 	 */
-	if (current->ptrace & PT_DTRACE)
+	if (test_thread_flag(TIF_SINGLESTEP))
 		current->thread.singlestep_syscall =
 			is_syscall(PT_REGS_IP(&current->thread.regs));
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/kernel/sysrq.c
+++ linux-xilinx-zynqmp-5.4.0/arch/um/kernel/sysrq.c
@@ -17,7 +17,9 @@
 
 static void _print_addr(void *data, unsigned long address, int reliable)
 {
-	pr_info(" [<%08lx>] %s%pS\n", address, reliable ? "" : "? ",
+	const char *loglvl = data;
+
+	printk("%s [<%08lx>] %s%pS\n", loglvl, address, reliable ? "" : "? ",
 		(void *)address);
 }
 
@@ -25,9 +27,9 @@
 	.address = _print_addr
 };
 
-void show_stack(struct task_struct *task, unsigned long *stack)
+void show_stack_loglvl(struct task_struct *task, unsigned long *stack,
+		       const char *loglvl)
 {
-	unsigned long *sp = stack;
 	struct pt_regs *segv_regs = current->thread.segv_regs;
 	int i;
 
@@ -38,10 +40,9 @@
 	}
 
 	if (!stack)
-		sp = get_stack_pointer(task, segv_regs);
+		stack = get_stack_pointer(task, segv_regs);
 
-	pr_info("Stack:\n");
-	stack = sp;
+	printk("%sStack:\n", loglvl);
 	for (i = 0; i < 3 * STACKSLOTS_PER_LINE; i++) {
 		if (kstack_end(stack))
 			break;
@@ -49,9 +50,12 @@
 			pr_cont("\n");
 		pr_cont(" %08lx", *stack++);
 	}
-	pr_cont("\n");
 
-	pr_info("Call Trace:\n");
-	dump_trace(current, &stackops, NULL);
-	pr_info("\n");
+	printk("%sCall Trace:\n", loglvl);
+	dump_trace(task ?: current, &stackops, (void *)loglvl);
+}
+
+void show_stack(struct task_struct *task, unsigned long *stack)
+{
+	show_stack_loglvl(task, stack, KERN_INFO);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/kernel/time.c
+++ linux-xilinx-zynqmp-5.4.0/arch/um/kernel/time.c
@@ -256,9 +256,9 @@
 	return 1;
 }
 
-__setup("time-travel-start", setup_time_travel_start);
+__setup("time-travel-start=", setup_time_travel_start);
 __uml_help(setup_time_travel_start,
-"time-travel-start=<seconds>\n"
+"time-travel-start=<nanoseconds>\n"
 "Configure the UML instance's wall clock to start at this value rather than\n"
 "the host's wall clock at the time of UML boot.\n");
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/kernel/tlb.c
+++ linux-xilinx-zynqmp-5.4.0/arch/um/kernel/tlb.c
@@ -126,6 +126,9 @@
 	struct host_vm_op *last;
 	int fd = -1, ret = 0;
 
+	if (virt + len > STUB_START && virt < STUB_END)
+		return -EINVAL;
+
 	if (hvc->userspace)
 		fd = phys_mapping(phys, &offset);
 	else
@@ -163,7 +166,7 @@
 	struct host_vm_op *last;
 	int ret = 0;
 
-	if ((addr >= STUB_START) && (addr < STUB_END))
+	if (addr + len > STUB_START && addr < STUB_END)
 		return -EINVAL;
 
 	if (hvc->index != 0) {
@@ -193,6 +196,9 @@
 	struct host_vm_op *last;
 	int ret = 0;
 
+	if (addr + len > STUB_START && addr < STUB_END)
+		return -EINVAL;
+
 	if (hvc->index != 0) {
 		last = &hvc->ops[hvc->index - 1];
 		if ((last->type == MPROTECT) &&
@@ -433,6 +439,10 @@
 	struct mm_id *mm_id;
 
 	address &= PAGE_MASK;
+
+	if (address >= STUB_START && address < STUB_END)
+		goto kill;
+
 	pgd = pgd_offset(mm, address);
 	if (!pgd_present(*pgd))
 		goto kill;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/kernel/um_arch.c
+++ linux-xilinx-zynqmp-5.4.0/arch/um/kernel/um_arch.c
@@ -3,6 +3,7 @@
  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
  */
 
+#include <linux/cpu.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/mm.h>
@@ -77,7 +78,7 @@
 
 static void *c_start(struct seq_file *m, loff_t *pos)
 {
-	return *pos < NR_CPUS ? cpu_data + *pos : NULL;
+	return *pos < nr_cpu_ids ? cpu_data + *pos : NULL;
 }
 
 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
@@ -353,7 +354,7 @@
 	setup_hostinfo(host_info, sizeof host_info);
 }
 
-void __init check_bugs(void)
+void __init arch_cpu_finalize_init(void)
 {
 	arch_check_bugs();
 	os_check_bugs();
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/kernel/uml.lds.S
+++ linux-xilinx-zynqmp-5.4.0/arch/um/kernel/uml.lds.S
@@ -7,6 +7,12 @@
 ENTRY(_start)
 jiffies = jiffies_64;
 
+VERSION {
+  {
+    local: *;
+  };
+}
+
 SECTIONS
 {
   /* This must contain the right address - not quite the default ELF one.*/
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/kernel/vmlinux.lds.S
+++ linux-xilinx-zynqmp-5.4.0/arch/um/kernel/vmlinux.lds.S
@@ -1,4 +1,4 @@
-
+#define RUNTIME_DISCARD_EXIT
 KERNEL_STACK_SIZE = 4096 * (1 << CONFIG_KERNEL_STACK_ORDER);
 
 #ifdef CONFIG_LD_SCRIPT_STATIC
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/os-Linux/file.c
+++ linux-xilinx-zynqmp-5.4.0/arch/um/os-Linux/file.c
@@ -8,6 +8,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <signal.h>
+#include <linux/falloc.h>
 #include <sys/ioctl.h>
 #include <sys/mount.h>
 #include <sys/socket.h>
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/os-Linux/helper.c
+++ linux-xilinx-zynqmp-5.4.0/arch/um/os-Linux/helper.c
@@ -45,7 +45,7 @@
 	unsigned long stack, sp;
 	int pid, fds[2], ret, n;
 
-	stack = alloc_stack(0, __cant_sleep());
+	stack = alloc_stack(0, __uml_cant_sleep());
 	if (stack == 0)
 		return -ENOMEM;
 
@@ -69,7 +69,7 @@
 	data.pre_data = pre_data;
 	data.argv = argv;
 	data.fd = fds[1];
-	data.buf = __cant_sleep() ? uml_kmalloc(PATH_MAX, UM_GFP_ATOMIC) :
+	data.buf = __uml_cant_sleep() ? uml_kmalloc(PATH_MAX, UM_GFP_ATOMIC) :
 					uml_kmalloc(PATH_MAX, UM_GFP_KERNEL);
 	pid = clone(helper_child, (void *) sp, CLONE_VM, &data);
 	if (pid < 0) {
@@ -116,7 +116,7 @@
 	unsigned long stack, sp;
 	int pid, status, err;
 
-	stack = alloc_stack(0, __cant_sleep());
+	stack = alloc_stack(0, __uml_cant_sleep());
 	if (stack == 0)
 		return -ENOMEM;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/os-Linux/irq.c
+++ linux-xilinx-zynqmp-5.4.0/arch/um/os-Linux/irq.c
@@ -48,7 +48,7 @@
 int os_event_mask(int irq_type)
 {
 	if (irq_type == IRQ_READ)
-		return EPOLLIN | EPOLLPRI;
+		return EPOLLIN | EPOLLPRI | EPOLLERR | EPOLLHUP | EPOLLRDHUP;
 	if (irq_type == IRQ_WRITE)
 		return EPOLLOUT;
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/os-Linux/main.c
+++ linux-xilinx-zynqmp-5.4.0/arch/um/os-Linux/main.c
@@ -170,7 +170,7 @@
 	 * that they won't be delivered after the exec, when
 	 * they are definitely not expected.
 	 */
-	unblock_signals_trace();
+	unblock_signals();
 
 	os_info("\n");
 	/* Reboot */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/os-Linux/registers.c
+++ linux-xilinx-zynqmp-5.4.0/arch/um/os-Linux/registers.c
@@ -21,7 +21,7 @@
 	return 0;
 }
 
-int restore_registers(int pid, struct uml_pt_regs *regs)
+int restore_pid_registers(int pid, struct uml_pt_regs *regs)
 {
 	int err;
 
@@ -36,7 +36,7 @@
 static unsigned long exec_regs[MAX_REG_NR];
 static unsigned long exec_fp_regs[FP_SIZE];
 
-int init_registers(int pid)
+int init_pid_registers(int pid)
 {
 	int err;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/os-Linux/skas/process.c
+++ linux-xilinx-zynqmp-5.4.0/arch/um/os-Linux/skas/process.c
@@ -5,6 +5,7 @@
  */
 
 #include <stdlib.h>
+#include <stdbool.h>
 #include <unistd.h>
 #include <sched.h>
 #include <errno.h>
@@ -641,10 +642,24 @@
 	UML_LONGJMP(&initial_jmpbuf, INIT_JMP_HALT);
 }
 
+static bool noreboot;
+
+static int __init noreboot_cmd_param(char *str, int *add)
+{
+	noreboot = true;
+	return 0;
+}
+
+__uml_setup("noreboot", noreboot_cmd_param,
+"noreboot\n"
+"    Rather than rebooting, exit always, akin to QEMU's -no-reboot option.\n"
+"    This is useful if you're using CONFIG_PANIC_TIMEOUT in order to catch\n"
+"    crashes in CI\n");
+
 void reboot_skas(void)
 {
 	block_signals_trace();
-	UML_LONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT);
+	UML_LONGJMP(&initial_jmpbuf, noreboot ? INIT_JMP_HALT : INIT_JMP_REBOOT);
 }
 
 void __switch_mm(struct mm_id *mm_idp)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/os-Linux/start_up.c
+++ linux-xilinx-zynqmp-5.4.0/arch/um/os-Linux/start_up.c
@@ -336,7 +336,7 @@
 	check_tmpexec();
 
 	pid = start_ptraced_child();
-	if (init_registers(pid))
+	if (init_pid_registers(pid))
 		fatal("Failed to initialize default registers");
 	stop_ptraced_child(pid, 1, 1);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/os-Linux/umid.c
+++ linux-xilinx-zynqmp-5.4.0/arch/um/os-Linux/umid.c
@@ -137,20 +137,13 @@
 {
 	char pid[sizeof("nnnnn\0")], *end, *file;
 	int dead, fd, p, n, err;
-	size_t filelen;
+	size_t filelen = strlen(dir) + sizeof("/pid") + 1;
 
-	err = asprintf(&file, "%s/pid", dir);
-	if (err < 0)
-		return 0;
+	file = malloc(filelen);
+	if (!file)
+		return -ENOMEM;
 
-	filelen = strlen(file);
-
-	n = snprintf(file, filelen, "%s/pid", dir);
-	if (n >= filelen) {
-		printk(UM_KERN_ERR "is_umdir_used - pid filename too long\n");
-		err = -E2BIG;
-		goto out;
-	}
+	snprintf(file, filelen, "%s/pid", dir);
 
 	dead = 0;
 	fd = open(file, O_RDONLY);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/um/os-Linux/util.c
+++ linux-xilinx-zynqmp-5.4.0/arch/um/os-Linux/util.c
@@ -166,23 +166,38 @@
 "quiet\n"
 "    Turns off information messages during boot.\n\n");
 
+/*
+ * The os_info/os_warn functions will be called by helper threads. These
+ * have a very limited stack size and using the libc formatting functions
+ * may overflow the stack.
+ * So pull in the kernel vscnprintf and use that instead with a fixed
+ * on-stack buffer.
+ */
+int vscnprintf(char *buf, size_t size, const char *fmt, va_list args);
+
 void os_info(const char *fmt, ...)
 {
+	char buf[256];
 	va_list list;
+	int len;
 
 	if (quiet_info)
 		return;
 
 	va_start(list, fmt);
-	vfprintf(stderr, fmt, list);
+	len = vscnprintf(buf, sizeof(buf), fmt, list);
+	fwrite(buf, len, 1, stderr);
 	va_end(list);
 }
 
 void os_warn(const char *fmt, ...)
 {
+	char buf[256];
 	va_list list;
+	int len;
 
 	va_start(list, fmt);
-	vfprintf(stderr, fmt, list);
+	len = vscnprintf(buf, sizeof(buf), fmt, list);
+	fwrite(buf, len, 1, stderr);
 	va_end(list);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/Kconfig
@@ -60,6 +60,7 @@
 	select ARCH_CLOCKSOURCE_DATA
 	select ARCH_CLOCKSOURCE_INIT
 	select ARCH_HAS_ACPI_TABLE_UPGRADE	if ACPI
+	select ARCH_HAS_CPU_FINALIZE_INIT
 	select ARCH_HAS_DEBUG_VIRTUAL
 	select ARCH_HAS_DEVMEM_IS_ALLOWED
 	select ARCH_HAS_ELF_RANDOMIZE
@@ -73,7 +74,6 @@
 	select ARCH_HAS_PMEM_API		if X86_64
 	select ARCH_HAS_PTE_DEVMAP		if X86_64
 	select ARCH_HAS_PTE_SPECIAL
-	select ARCH_HAS_REFCOUNT
 	select ARCH_HAS_UACCESS_FLUSHCACHE	if X86_64
 	select ARCH_HAS_UACCESS_MCSAFE		if X86_64 && X86_MCE
 	select ARCH_HAS_SET_MEMORY
@@ -160,7 +160,7 @@
 	select HAVE_DYNAMIC_FTRACE_WITH_REGS
 	select HAVE_EBPF_JIT
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
-	select HAVE_EISA
+	select HAVE_EISA			if X86_32
 	select HAVE_EXIT_THREAD
 	select HAVE_FAST_GUP
 	select HAVE_FENTRY			if X86_64 || DYNAMIC_FTRACE
@@ -550,6 +550,7 @@
 	depends on X86_EXTENDED_PLATFORM
 	depends on NUMA
 	depends on EFI
+	depends on KEXEC_CORE
 	depends on X86_X2APIC
 	depends on PCI
 	---help---
@@ -1424,7 +1425,7 @@
 
 config HIGHMEM64G
 	bool "64GB"
-	depends on !M486 && !M586 && !M586TSC && !M586MMX && !MGEODE_LX && !MGEODEGX1 && !MCYRIXIII && !MELAN && !MWINCHIPC6 && !WINCHIP3D && !MK6
+	depends on !M486 && !M586 && !M586TSC && !M586MMX && !MGEODE_LX && !MGEODEGX1 && !MCYRIXIII && !MELAN && !MWINCHIPC6 && !MWINCHIP3D && !MK6
 	select X86_PAE
 	---help---
 	  Select this if you have a 32-bit processor and more than 4
@@ -1540,7 +1541,6 @@
 
 config AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT
 	bool "Activate AMD Secure Memory Encryption (SME) by default"
-	default y
 	depends on AMD_MEM_ENCRYPT
 	---help---
 	  Say yes to have system memory encrypted by default if running on
@@ -1990,6 +1990,7 @@
 	depends on ACPI
 	select UCS2_STRING
 	select EFI_RUNTIME_WRAPPERS
+	select ARCH_USE_MEMREMAP_PROT
 	---help---
 	  This enables the kernel to use EFI runtime services that are
 	  available (such as the EFI variable services).
@@ -2480,6 +2481,34 @@
 
 endmenu
 
+config GDS_FORCE_MITIGATION
+	bool "Force GDS Mitigation"
+	depends on CPU_SUP_INTEL
+	default n
+	help
+	  Gather Data Sampling (GDS) is a hardware vulnerability which allows
+	  unprivileged speculative access to data which was previously stored in
+	  vector registers.
+
+	  This option is equivalent to setting gather_data_sampling=force on the
+	  command line. The microcode mitigation is used if present, otherwise
+	  AVX is disabled as a mitigation. On affected systems that are missing
+	  the microcode any userspace code that unconditionally uses AVX will
+	  break with this option set.
+
+	  Setting this option on systems not vulnerable to GDS has no effect.
+
+	  If in doubt, say N.
+
+config MITIGATION_VMSCAPE
+	bool "Mitigate VMSCAPE"
+	depends on KVM
+	default y
+	help
+	  Enable mitigation for VMSCAPE attacks. VMSCAPE is a hardware security
+	  vulnerability on Intel and AMD CPUs that may allow a guest to do
+	  Spectre v2 style attacks on userspace hypervisor.
+
 config ARCH_HAS_ADD_PAGES
 	def_bool y
 	depends on X86_64 && ARCH_ENABLE_MEMORY_HOTPLUG
@@ -2500,6 +2529,31 @@
 	def_bool y
 	depends on X86_64 || X86_PAE
 
+choice
+	prompt "Clear branch history"
+	depends on CPU_SUP_INTEL
+	default SPECTRE_BHI_AUTO
+	help
+	  Enable BHI mitigations. BHI attacks are a form of Spectre V2 attacks
+	  where the branch history buffer is poisoned to speculatively steer
+	  indirect branches.
+	  See <file:Documentation/admin-guide/hw-vuln/spectre.rst>
+
+config SPECTRE_BHI_ON
+	bool "on"
+	help
+	  Equivalent to setting spectre_bhi=on command line parameter.
+config SPECTRE_BHI_OFF
+	bool "off"
+	help
+	  Equivalent to setting spectre_bhi=off command line parameter.
+config SPECTRE_BHI_AUTO
+	bool "auto"
+	help
+	  Equivalent to setting spectre_bhi=auto command line parameter.
+
+endchoice
+
 config ARCH_ENABLE_HUGEPAGE_MIGRATION
 	def_bool y
 	depends on X86_64 && HUGETLB_PAGE && MIGRATION
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/Kconfig.cpu
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/Kconfig.cpu
@@ -372,7 +372,7 @@
 config X86_MINIMUM_CPU_FAMILY
 	int
 	default "64" if X86_64
-	default "6" if X86_32 && (MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7 || MEFFICEON || MATOM || MCRUSOE || MCORE2 || MK7 || MK8)
+	default "6" if X86_32 && (MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7 || MEFFICEON || MATOM || MCORE2 || MK7 || MK8)
 	default "5" if X86_32 && X86_CMPXCHG64
 	default "4"
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/Kconfig.debug
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/Kconfig.debug
@@ -307,6 +307,7 @@
 
 config UNWINDER_FRAME_POINTER
 	bool "Frame pointer unwinder"
+	select ARCH_WANT_FRAME_POINTERS
 	select FRAME_POINTER
 	---help---
 	  This option enables the frame pointer unwinder for unwinding kernel
@@ -334,7 +335,3 @@
 	  overhead.
 
 endchoice
-
-config FRAME_POINTER
-	depends on !UNWINDER_ORC && !UNWINDER_GUESS
-	bool
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/Makefile
@@ -34,12 +34,13 @@
 REALMODE_CFLAGS	:= $(M16_CFLAGS) -g -Os -DDISABLE_BRANCH_PROFILING \
 		   -Wall -Wstrict-prototypes -march=i386 -mregparm=3 \
 		   -fno-strict-aliasing -fomit-frame-pointer -fno-pic \
-		   -mno-mmx -mno-sse
+		   -mno-mmx -mno-sse $(call cc-option,-fcf-protection=none)
 
 REALMODE_CFLAGS += $(call __cc-option, $(CC), $(REALMODE_CFLAGS), -ffreestanding)
 REALMODE_CFLAGS += $(call __cc-option, $(CC), $(REALMODE_CFLAGS), -fno-stack-protector)
 REALMODE_CFLAGS += $(call __cc-option, $(CC), $(REALMODE_CFLAGS), -Wno-address-of-packed-member)
 REALMODE_CFLAGS += $(call __cc-option, $(CC), $(REALMODE_CFLAGS), $(cc_stack_align4))
+REALMODE_CFLAGS += $(CLANG_FLAGS)
 export REALMODE_CFLAGS
 
 # BITS is used as extension for files which are available in a 32 bit
@@ -61,6 +62,9 @@
 KBUILD_CFLAGS += -mno-sse -mno-mmx -mno-sse2 -mno-3dnow
 KBUILD_CFLAGS += $(call cc-option,-mno-avx,)
 
+# Intel CET isn't enabled in the kernel
+KBUILD_CFLAGS += $(call cc-option,-fcf-protection=none)
+
 ifeq ($(CONFIG_X86_32),y)
         BITS := 32
         UTS_MACHINE := i386
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/Makefile.um
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/Makefile.um
@@ -44,7 +44,7 @@
 
 # Not on all 64-bit distros /lib is a symlink to /lib64. PLD is an example.
 
-LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib64
+LINK-$(CONFIG_LD_SCRIPT_DYN_RPATH) += -Wl,-rpath,/lib64
 LINK-y += -m64
 
 endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/boot/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/boot/Makefile
@@ -87,7 +87,7 @@
 
 SETUP_OBJS = $(addprefix $(obj)/,$(setup-y))
 
-sed-zoffset := -e 's/^\([0-9a-fA-F]*\) [ABCDGRSTVW] \(startup_32\|startup_64\|efi32_stub_entry\|efi64_stub_entry\|efi_pe_entry\|input_data\|_end\|_ehead\|_text\|z_.*\)$$/\#define ZO_\2 0x\1/p'
+sed-zoffset := -e 's/^\([0-9a-fA-F]*\) [a-zA-Z] \(startup_32\|startup_64\|efi32_stub_entry\|efi64_stub_entry\|efi_pe_entry\|input_data\|_end\|_ehead\|_text\|z_.*\)$$/\#define ZO_\2 0x\1/p'
 
 quiet_cmd_zoffset = ZOFFSET $@
       cmd_zoffset = $(NM) $< | sed -n $(sed-zoffset) > $@
@@ -100,7 +100,7 @@
 AFLAGS_header.o += -I$(objtree)/$(obj)
 $(obj)/header.o: $(obj)/zoffset.h
 
-LDFLAGS_setup.elf	:= -m elf_i386 -T
+LDFLAGS_setup.elf	:= -m elf_i386 -z noexecstack -T
 $(obj)/setup.elf: $(src)/setup.ld $(SETUP_OBJS) FORCE
 	$(call if_changed,ld)
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/boot/bioscall.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/boot/bioscall.S
@@ -32,7 +32,7 @@
 	movw	%dx, %si
 	movw	%sp, %di
 	movw	$11, %cx
-	rep; movsd
+	rep; movsl
 
 	/* Pop full state from the stack */
 	popal
@@ -67,7 +67,7 @@
 	jz	4f
 	movw	%sp, %si
 	movw	$11, %cx
-	rep; movsd
+	rep; movsl
 4:	addw	$44, %sp
 
 	/* Restore state and return */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/boot/boot.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/boot/boot.h
@@ -110,66 +110,78 @@
 
 static inline u8 rdfs8(addr_t addr)
 {
+	u8 *ptr = (u8 *)absolute_pointer(addr);
 	u8 v;
-	asm volatile("movb %%fs:%1,%0" : "=q" (v) : "m" (*(u8 *)addr));
+	asm volatile("movb %%fs:%1,%0" : "=q" (v) : "m" (*ptr));
 	return v;
 }
 static inline u16 rdfs16(addr_t addr)
 {
+	u16 *ptr = (u16 *)absolute_pointer(addr);
 	u16 v;
-	asm volatile("movw %%fs:%1,%0" : "=r" (v) : "m" (*(u16 *)addr));
+	asm volatile("movw %%fs:%1,%0" : "=r" (v) : "m" (*ptr));
 	return v;
 }
 static inline u32 rdfs32(addr_t addr)
 {
+	u32 *ptr = (u32 *)absolute_pointer(addr);
 	u32 v;
-	asm volatile("movl %%fs:%1,%0" : "=r" (v) : "m" (*(u32 *)addr));
+	asm volatile("movl %%fs:%1,%0" : "=r" (v) : "m" (*ptr));
 	return v;
 }
 
 static inline void wrfs8(u8 v, addr_t addr)
 {
-	asm volatile("movb %1,%%fs:%0" : "+m" (*(u8 *)addr) : "qi" (v));
+	u8 *ptr = (u8 *)absolute_pointer(addr);
+	asm volatile("movb %1,%%fs:%0" : "+m" (*ptr) : "qi" (v));
 }
 static inline void wrfs16(u16 v, addr_t addr)
 {
-	asm volatile("movw %1,%%fs:%0" : "+m" (*(u16 *)addr) : "ri" (v));
+	u16 *ptr = (u16 *)absolute_pointer(addr);
+	asm volatile("movw %1,%%fs:%0" : "+m" (*ptr) : "ri" (v));
 }
 static inline void wrfs32(u32 v, addr_t addr)
 {
-	asm volatile("movl %1,%%fs:%0" : "+m" (*(u32 *)addr) : "ri" (v));
+	u32 *ptr = (u32 *)absolute_pointer(addr);
+	asm volatile("movl %1,%%fs:%0" : "+m" (*ptr) : "ri" (v));
 }
 
 static inline u8 rdgs8(addr_t addr)
 {
+	u8 *ptr = (u8 *)absolute_pointer(addr);
 	u8 v;
-	asm volatile("movb %%gs:%1,%0" : "=q" (v) : "m" (*(u8 *)addr));
+	asm volatile("movb %%gs:%1,%0" : "=q" (v) : "m" (*ptr));
 	return v;
 }
 static inline u16 rdgs16(addr_t addr)
 {
+	u16 *ptr = (u16 *)absolute_pointer(addr);
 	u16 v;
-	asm volatile("movw %%gs:%1,%0" : "=r" (v) : "m" (*(u16 *)addr));
+	asm volatile("movw %%gs:%1,%0" : "=r" (v) : "m" (*ptr));
 	return v;
 }
 static inline u32 rdgs32(addr_t addr)
 {
+	u32 *ptr = (u32 *)absolute_pointer(addr);
 	u32 v;
-	asm volatile("movl %%gs:%1,%0" : "=r" (v) : "m" (*(u32 *)addr));
+	asm volatile("movl %%gs:%1,%0" : "=r" (v) : "m" (*ptr));
 	return v;
 }
 
 static inline void wrgs8(u8 v, addr_t addr)
 {
-	asm volatile("movb %1,%%gs:%0" : "+m" (*(u8 *)addr) : "qi" (v));
+	u8 *ptr = (u8 *)absolute_pointer(addr);
+	asm volatile("movb %1,%%gs:%0" : "+m" (*ptr) : "qi" (v));
 }
 static inline void wrgs16(u16 v, addr_t addr)
 {
-	asm volatile("movw %1,%%gs:%0" : "+m" (*(u16 *)addr) : "ri" (v));
+	u16 *ptr = (u16 *)absolute_pointer(addr);
+	asm volatile("movw %1,%%gs:%0" : "+m" (*ptr) : "ri" (v));
 }
 static inline void wrgs32(u32 v, addr_t addr)
 {
-	asm volatile("movl %1,%%gs:%0" : "+m" (*(u32 *)addr) : "ri" (v));
+	u32 *ptr = (u32 *)absolute_pointer(addr);
+	asm volatile("movl %1,%%gs:%0" : "+m" (*ptr) : "ri" (v));
 }
 
 /* Note: these only return true/false, not a signed return value! */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/boot/compressed/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/boot/compressed/Makefile
@@ -38,6 +38,8 @@
 KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member)
 KBUILD_CFLAGS += $(call cc-disable-warning, gnu)
 KBUILD_CFLAGS += -Wno-pointer-sign
+# Disable relocation relaxation in case the link is not PIE.
+KBUILD_CFLAGS += $(call as-option,-Wa$(comma)-mrelax-relocations=no)
 
 KBUILD_AFLAGS  := $(KBUILD_CFLAGS) -D__ASSEMBLY__
 GCOV_PROFILE := n
@@ -55,6 +57,10 @@
 KBUILD_LDFLAGS += $(shell $(LD) --help 2>&1 | grep -q "\-z noreloc-overflow" \
 	&& echo "-z noreloc-overflow -pie --no-dynamic-linker")
 endif
+
+KBUILD_LDFLAGS += -z noexecstack
+KBUILD_LDFLAGS += $(call ld-option,--no-warn-rwx-segments)
+
 LDFLAGS_vmlinux := -T
 
 hostprogs-y	:= mkpiggy
@@ -102,7 +108,7 @@
 quiet_cmd_check_data_rel = DATAREL $@
 define cmd_check_data_rel
 	for obj in $(filter %.o,$^); do \
-		${CROSS_COMPILE}readelf -S $$obj | grep -qF .rel.local && { \
+		$(READELF) -S $$obj | grep -qF .rel.local && { \
 			echo "error: $$obj has data relocations!" >&2; \
 			exit 1; \
 		} || true; \
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/boot/compressed/acpi.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/boot/compressed/acpi.c
@@ -393,7 +393,13 @@
 	table = table_addr + sizeof(struct acpi_table_srat);
 
 	while (table + sizeof(struct acpi_subtable_header) < table_end) {
+
 		sub_table = (struct acpi_subtable_header *)table;
+		if (!sub_table->length) {
+			debug_putstr("Invalid zero length SRAT subtable.\n");
+			return 0;
+		}
+
 		if (sub_table->type == ACPI_SRAT_TYPE_MEMORY_AFFINITY) {
 			struct acpi_srat_mem_affinity *ma;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/boot/compressed/head_32.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/boot/compressed/head_32.S
@@ -49,16 +49,17 @@
  * Position Independent Executable (PIE) so that linker won't optimize
  * R_386_GOT32X relocation to its fixed symbol address.  Older
  * linkers generate R_386_32 relocations against locally defined symbols,
- * _bss, _ebss, _got and _egot, in PIE.  It isn't wrong, just less
+ * _bss, _ebss, _got, _egot and _end, in PIE.  It isn't wrong, just less
  * optimal than R_386_RELATIVE.  But the x86 kernel fails to properly handle
  * R_386_32 relocations when relocating the kernel.  To generate
- * R_386_RELATIVE relocations, we mark _bss, _ebss, _got and _egot as
+ * R_386_RELATIVE relocations, we mark _bss, _ebss, _got, _egot and _end as
  * hidden:
  */
 	.hidden _bss
 	.hidden _ebss
 	.hidden _got
 	.hidden _egot
+	.hidden _end
 
 	__HEAD
 ENTRY(startup_32)
@@ -106,7 +107,7 @@
 	notl	%eax
 	andl    %eax, %ebx
 	cmpl	$LOAD_PHYSICAL_ADDR, %ebx
-	jge	1f
+	jae	1f
 #endif
 	movl	$LOAD_PHYSICAL_ADDR, %ebx
 1:
@@ -209,7 +210,7 @@
 #endif
 
 	.text
-.Lrelocated:
+SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated)
 
 /*
  * Clear BSS (stack is currently empty)
@@ -260,6 +261,7 @@
  */
 	xorl	%ebx, %ebx
 	jmp	*%eax
+SYM_FUNC_END(.Lrelocated)
 
 #ifdef CONFIG_EFI_STUB
 	.data
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/boot/compressed/head_64.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/boot/compressed/head_64.S
@@ -42,6 +42,7 @@
 	.hidden _ebss
 	.hidden _got
 	.hidden _egot
+	.hidden _end
 
 	__HEAD
 	.code32
@@ -106,7 +107,7 @@
 	notl	%eax
 	andl	%eax, %ebx
 	cmpl	$LOAD_PHYSICAL_ADDR, %ebx
-	jge	1f
+	jae	1f
 #endif
 	movl	$LOAD_PHYSICAL_ADDR, %ebx
 1:
@@ -244,6 +245,11 @@
 	leal	efi32_config(%ebp), %eax
 	movl	%eax, efi_config(%ebp)
 
+	/* Disable paging */
+	movl	%cr0, %eax
+	btrl	$X86_CR0_PG_BIT, %eax
+	movl	%eax, %cr0
+
 	jmp	startup_32
 ENDPROC(efi32_stub_entry)
 #endif
@@ -292,7 +298,7 @@
 	notq	%rax
 	andq	%rax, %rbp
 	cmpq	$LOAD_PHYSICAL_ADDR, %rbp
-	jge	1f
+	jae	1f
 #endif
 	movq	$LOAD_PHYSICAL_ADDR, %rbp
 1:
@@ -375,11 +381,25 @@
 	/* Save the trampoline address in RCX */
 	movq	%rax, %rcx
 
+	/* Set up 32-bit addressable stack */
+	leaq	TRAMPOLINE_32BIT_STACK_END(%rcx), %rsp
+
 	/*
-	 * Load the address of trampoline_return() into RDI.
-	 * It will be used by the trampoline to return to the main code.
+	 * Preserve live 64-bit registers on the stack: this is necessary
+	 * because the architecture does not guarantee that GPRs will retain
+	 * their full 64-bit values across a 32-bit mode switch.
+	 */
+	pushq	%rbp
+	pushq	%rbx
+	pushq	%rsi
+
+	/*
+	 * Push the 64-bit address of trampoline_return() onto the new stack.
+	 * It will be used by the trampoline to return to the main code. Due to
+	 * the 32-bit mode switch, it cannot be kept it in a register either.
 	 */
 	leaq	trampoline_return(%rip), %rdi
+	pushq	%rdi
 
 	/* Switch to compatibility mode (CS.L = 0 CS.D = 1) via far return */
 	pushq	$__KERNEL32_CS
@@ -387,6 +407,11 @@
 	pushq	%rax
 	lretq
 trampoline_return:
+	/* Restore live 64-bit registers */
+	popq	%rsi
+	popq	%rbx
+	popq	%rbp
+
 	/* Restore the stack, the 32-bit trampoline uses its own stack */
 	leaq	boot_stack_end(%rbx), %rsp
 
@@ -511,7 +536,7 @@
 #endif
 
 	.text
-.Lrelocated:
+SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated)
 
 /*
  * Clear BSS (stack is currently empty)
@@ -540,6 +565,7 @@
  * Jump to the decompressed kernel.
  */
 	jmp	*%rax
+SYM_FUNC_END(.Lrelocated)
 
 /*
  * Adjust the global offset table
@@ -566,7 +592,7 @@
 /*
  * This is the 32-bit trampoline that will be copied over to low memory.
  *
- * RDI contains the return address (might be above 4G).
+ * Return address is at the top of the stack (might be above 4G).
  * ECX contains the base address of the trampoline memory.
  * Non zero RDX means trampoline needs to enable 5-level paging.
  */
@@ -576,9 +602,6 @@
 	movl	%eax, %ds
 	movl	%eax, %ss
 
-	/* Set up new stack */
-	leal	TRAMPOLINE_32BIT_STACK_END(%ecx), %esp
-
 	/* Disable paging */
 	movl	%cr0, %eax
 	btrl	$X86_CR0_PG_BIT, %eax
@@ -635,9 +658,10 @@
 	lret
 
 	.code64
-.Lpaging_enabled:
+SYM_FUNC_START_LOCAL_NOALIGN(.Lpaging_enabled)
 	/* Return from the trampoline */
-	jmp	*%rdi
+	retq
+SYM_FUNC_END(.Lpaging_enabled)
 
 	/*
          * The trampoline code has a size limit.
@@ -647,11 +671,12 @@
 	.org	trampoline_32bit_src + TRAMPOLINE_32BIT_CODE_SIZE
 
 	.code32
-.Lno_longmode:
+SYM_FUNC_START_LOCAL_NOALIGN(.Lno_longmode)
 	/* This isn't an x86-64 CPU, so hang intentionally, we cannot continue */
 1:
 	hlt
 	jmp     1b
+SYM_FUNC_END(.Lno_longmode)
 
 #include "../../kernel/verify_cpu.S"
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/boot/compressed/kaslr_64.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/boot/compressed/kaslr_64.c
@@ -29,9 +29,6 @@
 #define __PAGE_OFFSET __PAGE_OFFSET_BASE
 #include "../../mm/ident_map.c"
 
-/* Used by pgtable.h asm code to force instruction serialization. */
-unsigned long __force_order;
-
 /* Used to track our page table allocation area. */
 struct alloc_pgt_data {
 	unsigned char *pgt_buf;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/boot/compressed/pgtable_64.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/boot/compressed/pgtable_64.c
@@ -5,15 +5,6 @@
 #include "pgtable.h"
 #include "../string.h"
 
-/*
- * __force_order is used by special_insns.h asm code to force instruction
- * serialization.
- *
- * It is not referenced from the code, but GCC < 5 with -fPIE would fail
- * due to an undefined symbol. Define it to make these ancient GCCs work.
- */
-unsigned long __force_order;
-
 #define BIOS_START_MIN		0x20000U	/* 128K, less than this is insane */
 #define BIOS_START_MAX		0x9f000U	/* 640K, absolute maximum */
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/boot/main.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/boot/main.c
@@ -33,7 +33,7 @@
 		u16 cl_offset;
 	};
 	const struct old_cmdline * const oldcmd =
-		(const struct old_cmdline *)OLD_CL_ADDRESS;
+		absolute_pointer(OLD_CL_ADDRESS);
 
 	BUILD_BUG_ON(sizeof(boot_params) != 4096);
 	memcpy(&boot_params.hdr, &hdr, sizeof(hdr));
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/boot/pmjump.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/boot/pmjump.S
@@ -40,13 +40,13 @@
 
 	# Transition to 32-bit mode
 	.byte	0x66, 0xea		# ljmpl opcode
-2:	.long	in_pm32			# offset
+2:	.long	.Lin_pm32		# offset
 	.word	__BOOT_CS		# segment
 ENDPROC(protected_mode_jump)
 
 	.code32
 	.section ".text32","ax"
-GLOBAL(in_pm32)
+SYM_FUNC_START_LOCAL_NOALIGN(.Lin_pm32)
 	# Set up data segments for flat 32-bit mode
 	movl	%ecx, %ds
 	movl	%ecx, %es
@@ -72,4 +72,4 @@
 	lldt	%cx
 
 	jmpl	*%eax			# Jump to the 32-bit entrypoint
-ENDPROC(in_pm32)
+SYM_FUNC_END(.Lin_pm32)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/boot/setup.ld
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/boot/setup.ld
@@ -20,7 +20,7 @@
 	.initdata	: { *(.initdata) }
 	__end_init = .;
 
-	.text		: { *(.text) }
+	.text		: { *(.text .text.*) }
 	.text32		: { *(.text32) }
 
 	. = ALIGN(16);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/boot/video-vga.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/boot/video-vga.c
@@ -188,7 +188,7 @@
 	vga_set_vertical_end(60*8);
 }
 
-static int vga_set_mode(struct mode_info *mode)
+static int __attribute__((optimize("no-jump-tables"))) vga_set_mode(struct mode_info *mode)
 {
 	/* Set the basic mode */
 	vga_set_basic_mode();
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/configs/i386_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/configs/i386_defconfig
@@ -137,7 +137,6 @@
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_SPI_ATTRS=y
@@ -205,7 +204,6 @@
 CONFIG_FB_TILEBLITTING=y
 CONFIG_FB_EFI=y
 # CONFIG_LCD_CLASS_DEVICE is not set
-CONFIG_VGACON_SOFT_SCROLLBACK=y
 CONFIG_LOGO=y
 # CONFIG_LOGO_LINUX_MONO is not set
 # CONFIG_LOGO_LINUX_VGA16 is not set
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/configs/x86_64_defconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/configs/x86_64_defconfig
@@ -136,7 +136,6 @@
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_CHR_DEV_SG=y
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_SPI_ATTRS=y
@@ -201,7 +200,6 @@
 CONFIG_FB_TILEBLITTING=y
 CONFIG_FB_EFI=y
 # CONFIG_LCD_CLASS_DEVICE is not set
-CONFIG_VGACON_SOFT_SCROLLBACK=y
 CONFIG_LOGO=y
 # CONFIG_LOGO_LINUX_MONO is not set
 # CONFIG_LOGO_LINUX_VGA16 is not set
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/crypto/aegis128-aesni-asm.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/crypto/aegis128-aesni-asm.S
@@ -20,7 +20,7 @@
 #define T1	%xmm7
 
 #define STATEP	%rdi
-#define LEN	%rsi
+#define LEN	%esi
 #define SRC	%rdx
 #define DST	%rcx
 
@@ -75,32 +75,32 @@
 	xor %r9d, %r9d
 	pxor MSG, MSG
 
-	mov LEN, %r8
+	mov LEN, %r8d
 	and $0x1, %r8
 	jz .Lld_partial_1
 
-	mov LEN, %r8
+	mov LEN, %r8d
 	and $0x1E, %r8
 	add SRC, %r8
 	mov (%r8), %r9b
 
 .Lld_partial_1:
-	mov LEN, %r8
+	mov LEN, %r8d
 	and $0x2, %r8
 	jz .Lld_partial_2
 
-	mov LEN, %r8
+	mov LEN, %r8d
 	and $0x1C, %r8
 	add SRC, %r8
 	shl $0x10, %r9
 	mov (%r8), %r9w
 
 .Lld_partial_2:
-	mov LEN, %r8
+	mov LEN, %r8d
 	and $0x4, %r8
 	jz .Lld_partial_4
 
-	mov LEN, %r8
+	mov LEN, %r8d
 	and $0x18, %r8
 	add SRC, %r8
 	shl $32, %r9
@@ -110,11 +110,11 @@
 .Lld_partial_4:
 	movq %r9, MSG
 
-	mov LEN, %r8
+	mov LEN, %r8d
 	and $0x8, %r8
 	jz .Lld_partial_8
 
-	mov LEN, %r8
+	mov LEN, %r8d
 	and $0x10, %r8
 	add SRC, %r8
 	pslldq $8, MSG
@@ -138,7 +138,7 @@
  *   %r10
  */
 __store_partial:
-	mov LEN, %r8
+	mov LEN, %r8d
 	mov DST, %r9
 
 	movq T0, %r10
@@ -676,7 +676,7 @@
 	call __store_partial
 
 	/* mask with byte count: */
-	movq LEN, T0
+	movd LEN, T0
 	punpcklbw T0, T0
 	punpcklbw T0, T0
 	punpcklbw T0, T0
@@ -701,7 +701,8 @@
 
 /*
  * void crypto_aegis128_aesni_final(void *state, void *tag_xor,
- *                                  u64 assoclen, u64 cryptlen);
+ *                                  unsigned int assoclen,
+ *                                  unsigned int cryptlen);
  */
 ENTRY(crypto_aegis128_aesni_final)
 	FRAME_BEGIN
@@ -714,8 +715,8 @@
 	movdqu 0x40(STATEP), STATE4
 
 	/* prepare length block: */
-	movq %rdx, MSG
-	movq %rcx, T0
+	movd %edx, MSG
+	movd %ecx, T0
 	pslldq $8, T0
 	pxor T0, MSG
 	psllq $3, MSG /* multiply by 8 (to get bit count) */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/crypto/aes_ctrby8_avx-x86_64.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/crypto/aes_ctrby8_avx-x86_64.S
@@ -127,10 +127,6 @@
 
 /* generate a unique variable for ddq_add_x */
 
-.macro setddq n
-	var_ddq_add = ddq_add_\n
-.endm
-
 /* generate a unique variable for xmm register */
 .macro setxdata n
 	var_xdata = %xmm\n
@@ -140,9 +136,7 @@
 
 .macro club name, id
 .altmacro
-	.if \name == DDQ_DATA
-		setddq %\id
-	.elseif \name == XDATA
+	.if \name == XDATA
 		setxdata %\id
 	.endif
 .noaltmacro
@@ -165,9 +159,8 @@
 
 	.set i, 1
 	.rept (by - 1)
-		club DDQ_DATA, i
 		club XDATA, i
-		vpaddq	var_ddq_add(%rip), xcounter, var_xdata
+		vpaddq	(ddq_add_1 + 16 * (i - 1))(%rip), xcounter, var_xdata
 		vptest	ddq_low_msk(%rip), var_xdata
 		jnz 1f
 		vpaddq	ddq_high_add_1(%rip), var_xdata, var_xdata
@@ -180,8 +173,7 @@
 	vmovdqa	1*16(p_keys), xkeyA
 
 	vpxor	xkey0, xdata0, xdata0
-	club DDQ_DATA, by
-	vpaddq	var_ddq_add(%rip), xcounter, xcounter
+	vpaddq	(ddq_add_1 + 16 * (by - 1))(%rip), xcounter, xcounter
 	vptest	ddq_low_msk(%rip), xcounter
 	jnz	1f
 	vpaddq	ddq_high_add_1(%rip), xcounter, xcounter
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/crypto/aesni-intel_asm.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/crypto/aesni-intel_asm.S
@@ -266,7 +266,7 @@
 	PSHUFB_XMM %xmm2, %xmm0
 	movdqu %xmm0, CurCount(%arg2) # ctx_data.current_counter = iv
 
-	PRECOMPUTE \SUBKEY, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
+	PRECOMPUTE \SUBKEY, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7
 	movdqu HashKey(%arg2), %xmm13
 
 	CALC_AAD_HASH %xmm13, \AAD, \AADLEN, %xmm0, %xmm1, %xmm2, %xmm3, \
@@ -319,7 +319,7 @@
 
 	# Main loop - Encrypt/Decrypt remaining blocks
 
-	cmp	$0, %r13
+	test	%r13, %r13
 	je	_zero_cipher_left_\@
 	sub	$64, %r13
 	je	_four_cipher_left_\@
@@ -438,7 +438,7 @@
 
 	mov PBlockLen(%arg2), %r12
 
-	cmp $0, %r12
+	test %r12, %r12
 	je _partial_done\@
 
 	GHASH_MUL %xmm8, %xmm13, %xmm9, %xmm10, %xmm11, %xmm5, %xmm6
@@ -475,7 +475,7 @@
 	add	$8, %r10
 	sub	$8, %r11
 	psrldq	$8, %xmm0
-	cmp	$0, %r11
+	test	%r11, %r11
 	je	_return_T_done_\@
 _T_4_\@:
 	movd	%xmm0, %eax
@@ -483,7 +483,7 @@
 	add	$4, %r10
 	sub	$4, %r11
 	psrldq	$4, %xmm0
-	cmp	$0, %r11
+	test	%r11, %r11
 	je	_return_T_done_\@
 _T_123_\@:
 	movd	%xmm0, %eax
@@ -620,7 +620,7 @@
 
 	/* read the last <16B of AAD */
 _get_AAD_rest\@:
-	cmp	   $0, %r11
+	test	   %r11, %r11
 	je	   _get_AAD_done\@
 
 	READ_PARTIAL_BLOCK %r10, %r11, \TMP1, \TMP7
@@ -641,7 +641,7 @@
 .macro PARTIAL_BLOCK CYPH_PLAIN_OUT PLAIN_CYPH_IN PLAIN_CYPH_LEN DATA_OFFSET \
 	AAD_HASH operation
 	mov 	PBlockLen(%arg2), %r13
-	cmp	$0, %r13
+	test	%r13, %r13
 	je	_partial_block_done_\@	# Leave Macro if no partial blocks
 	# Read in input data without over reading
 	cmp	$16, \PLAIN_CYPH_LEN
@@ -693,7 +693,7 @@
 	PSHUFB_XMM	%xmm2, %xmm3
 	pxor	%xmm3, \AAD_HASH
 
-	cmp	$0, %r10
+	test	%r10, %r10
 	jl	_partial_incomplete_1_\@
 
 	# GHASH computation for the last <16 Byte block
@@ -728,7 +728,7 @@
 	PSHUFB_XMM %xmm2, %xmm9
 	pxor	%xmm9, \AAD_HASH
 
-	cmp	$0, %r10
+	test	%r10, %r10
 	jl	_partial_incomplete_2_\@
 
 	# GHASH computation for the last <16 Byte block
@@ -748,7 +748,7 @@
 	PSHUFB_XMM	%xmm2, %xmm9
 .endif
 	# output encrypted Bytes
-	cmp	$0, %r10
+	test	%r10, %r10
 	jl	_partial_fill_\@
 	mov	%r13, %r12
 	mov	$16, %r13
@@ -978,7 +978,7 @@
 * arg1, %arg3, %arg4 are used as pointers only, not modified
 * %r11 is the data offset value
 */
-.macro GHASH_4_ENCRYPT_4_PARALLEL_ENC TMP1 TMP2 TMP3 TMP4 TMP5 \
+.macro GHASH_4_ENCRYPT_4_PARALLEL_enc TMP1 TMP2 TMP3 TMP4 TMP5 \
 TMP6 XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7 XMM8 operation
 
 	movdqa	  \XMM1, \XMM5
@@ -1186,7 +1186,7 @@
 * arg1, %arg3, %arg4 are used as pointers only, not modified
 * %r11 is the data offset value
 */
-.macro GHASH_4_ENCRYPT_4_PARALLEL_DEC TMP1 TMP2 TMP3 TMP4 TMP5 \
+.macro GHASH_4_ENCRYPT_4_PARALLEL_dec TMP1 TMP2 TMP3 TMP4 TMP5 \
 TMP6 XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7 XMM8 operation
 
 	movdqa	  \XMM1, \XMM5
@@ -1946,7 +1946,7 @@
 ENDPROC(aesni_set_key)
 
 /*
- * void aesni_enc(struct crypto_aes_ctx *ctx, u8 *dst, const u8 *src)
+ * void aesni_enc(const void *ctx, u8 *dst, const u8 *src)
  */
 ENTRY(aesni_enc)
 	FRAME_BEGIN
@@ -2137,7 +2137,7 @@
 ENDPROC(_aesni_enc4)
 
 /*
- * void aesni_dec (struct crypto_aes_ctx *ctx, u8 *dst, const u8 *src)
+ * void aesni_dec (const void *ctx, u8 *dst, const u8 *src)
  */
 ENTRY(aesni_dec)
 	FRAME_BEGIN
@@ -2726,25 +2726,18 @@
 	pxor CTR, IV;
 
 /*
- * void aesni_xts_crypt8(struct crypto_aes_ctx *ctx, const u8 *dst, u8 *src,
- *			 bool enc, u8 *iv)
+ * void aesni_xts_encrypt(const struct crypto_aes_ctx *ctx, u8 *dst,
+ *			  const u8 *src, unsigned int len, le128 *iv)
  */
-ENTRY(aesni_xts_crypt8)
+ENTRY(aesni_xts_encrypt)
 	FRAME_BEGIN
-	cmpb $0, %cl
-	movl $0, %ecx
-	movl $240, %r10d
-	leaq _aesni_enc4, %r11
-	leaq _aesni_dec4, %rax
-	cmovel %r10d, %ecx
-	cmoveq %rax, %r11
 
 	movdqa .Lgf128mul_x_ble_mask, GF128MUL_MASK
 	movups (IVP), IV
 
 	mov 480(KEYP), KLEN
-	addq %rcx, KEYP
 
+.Lxts_enc_loop4:
 	movdqa IV, STATE1
 	movdqu 0x00(INP), INC
 	pxor INC, STATE1
@@ -2768,71 +2761,103 @@
 	pxor INC, STATE4
 	movdqu IV, 0x30(OUTP)
 
-	CALL_NOSPEC %r11
+	call _aesni_enc4
 
 	movdqu 0x00(OUTP), INC
 	pxor INC, STATE1
 	movdqu STATE1, 0x00(OUTP)
 
-	_aesni_gf128mul_x_ble()
-	movdqa IV, STATE1
-	movdqu 0x40(INP), INC
-	pxor INC, STATE1
-	movdqu IV, 0x40(OUTP)
-
 	movdqu 0x10(OUTP), INC
 	pxor INC, STATE2
 	movdqu STATE2, 0x10(OUTP)
 
-	_aesni_gf128mul_x_ble()
-	movdqa IV, STATE2
-	movdqu 0x50(INP), INC
-	pxor INC, STATE2
-	movdqu IV, 0x50(OUTP)
-
 	movdqu 0x20(OUTP), INC
 	pxor INC, STATE3
 	movdqu STATE3, 0x20(OUTP)
 
-	_aesni_gf128mul_x_ble()
-	movdqa IV, STATE3
-	movdqu 0x60(INP), INC
-	pxor INC, STATE3
-	movdqu IV, 0x60(OUTP)
-
 	movdqu 0x30(OUTP), INC
 	pxor INC, STATE4
 	movdqu STATE4, 0x30(OUTP)
 
 	_aesni_gf128mul_x_ble()
-	movdqa IV, STATE4
-	movdqu 0x70(INP), INC
-	pxor INC, STATE4
-	movdqu IV, 0x70(OUTP)
 
-	_aesni_gf128mul_x_ble()
+	add $64, INP
+	add $64, OUTP
+	sub $64, LEN
+	ja .Lxts_enc_loop4
+
 	movups IV, (IVP)
 
-	CALL_NOSPEC %r11
+	FRAME_END
+	ret
+ENDPROC(aesni_xts_encrypt)
+
+/*
+ * void aesni_xts_decrypt(const struct crypto_aes_ctx *ctx, u8 *dst,
+ *			  const u8 *src, unsigned int len, le128 *iv)
+ */
+ENTRY(aesni_xts_decrypt)
+	FRAME_BEGIN
+
+	movdqa .Lgf128mul_x_ble_mask, GF128MUL_MASK
+	movups (IVP), IV
+
+	mov 480(KEYP), KLEN
+	add $240, KEYP
 
-	movdqu 0x40(OUTP), INC
+.Lxts_dec_loop4:
+	movdqa IV, STATE1
+	movdqu 0x00(INP), INC
 	pxor INC, STATE1
-	movdqu STATE1, 0x40(OUTP)
+	movdqu IV, 0x00(OUTP)
 
-	movdqu 0x50(OUTP), INC
+	_aesni_gf128mul_x_ble()
+	movdqa IV, STATE2
+	movdqu 0x10(INP), INC
+	pxor INC, STATE2
+	movdqu IV, 0x10(OUTP)
+
+	_aesni_gf128mul_x_ble()
+	movdqa IV, STATE3
+	movdqu 0x20(INP), INC
+	pxor INC, STATE3
+	movdqu IV, 0x20(OUTP)
+
+	_aesni_gf128mul_x_ble()
+	movdqa IV, STATE4
+	movdqu 0x30(INP), INC
+	pxor INC, STATE4
+	movdqu IV, 0x30(OUTP)
+
+	call _aesni_dec4
+
+	movdqu 0x00(OUTP), INC
+	pxor INC, STATE1
+	movdqu STATE1, 0x00(OUTP)
+
+	movdqu 0x10(OUTP), INC
 	pxor INC, STATE2
-	movdqu STATE2, 0x50(OUTP)
+	movdqu STATE2, 0x10(OUTP)
 
-	movdqu 0x60(OUTP), INC
+	movdqu 0x20(OUTP), INC
 	pxor INC, STATE3
-	movdqu STATE3, 0x60(OUTP)
+	movdqu STATE3, 0x20(OUTP)
 
-	movdqu 0x70(OUTP), INC
+	movdqu 0x30(OUTP), INC
 	pxor INC, STATE4
-	movdqu STATE4, 0x70(OUTP)
+	movdqu STATE4, 0x30(OUTP)
+
+	_aesni_gf128mul_x_ble()
+
+	add $64, INP
+	add $64, OUTP
+	sub $64, LEN
+	ja .Lxts_dec_loop4
+
+	movups IV, (IVP)
 
 	FRAME_END
 	ret
-ENDPROC(aesni_xts_crypt8)
+ENDPROC(aesni_xts_decrypt)
 
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/crypto/aesni-intel_avx-x86_64.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/crypto/aesni-intel_avx-x86_64.S
@@ -370,7 +370,7 @@
 
 
 _initial_blocks_encrypted\@:
-        cmp     $0, %r13
+        test    %r13, %r13
         je      _zero_cipher_left\@
 
         sub     $128, %r13
@@ -529,7 +529,7 @@
         vmovdqu HashKey(arg2), %xmm13
 
         mov PBlockLen(arg2), %r12
-        cmp $0, %r12
+        test %r12, %r12
         je _partial_done\@
 
 	#GHASH computation for the last <16 Byte block
@@ -574,7 +574,7 @@
         add     $8, %r10
         sub     $8, %r11
         vpsrldq $8, %xmm9, %xmm9
-        cmp     $0, %r11
+        test    %r11, %r11
         je     _return_T_done\@
 _T_4\@:
         vmovd   %xmm9, %eax
@@ -582,7 +582,7 @@
         add     $4, %r10
         sub     $4, %r11
         vpsrldq     $4, %xmm9, %xmm9
-        cmp     $0, %r11
+        test    %r11, %r11
         je     _return_T_done\@
 _T_123\@:
         vmovd     %xmm9, %eax
@@ -626,7 +626,7 @@
 	cmp     $16, %r11
 	jge     _get_AAD_blocks\@
 	vmovdqu \T8, \T7
-	cmp     $0, %r11
+	test    %r11, %r11
 	je      _get_AAD_done\@
 
 	vpxor   \T7, \T7, \T7
@@ -645,7 +645,7 @@
 	vpxor   \T1, \T7, \T7
 	jmp     _get_AAD_rest8\@
 _get_AAD_rest4\@:
-	cmp     $0, %r11
+	test    %r11, %r11
 	jle      _get_AAD_rest0\@
 	mov     (%r10), %eax
 	movq    %rax, \T1
@@ -750,7 +750,7 @@
 .macro PARTIAL_BLOCK GHASH_MUL CYPH_PLAIN_OUT PLAIN_CYPH_IN PLAIN_CYPH_LEN DATA_OFFSET \
         AAD_HASH ENC_DEC
         mov 	PBlockLen(arg2), %r13
-        cmp	$0, %r13
+        test	%r13, %r13
         je	_partial_block_done_\@	# Leave Macro if no partial blocks
         # Read in input data without over reading
         cmp	$16, \PLAIN_CYPH_LEN
@@ -802,7 +802,7 @@
         vpshufb	%xmm2, %xmm3, %xmm3
         vpxor	%xmm3, \AAD_HASH, \AAD_HASH
 
-        cmp	$0, %r10
+        test	%r10, %r10
         jl	_partial_incomplete_1_\@
 
         # GHASH computation for the last <16 Byte block
@@ -837,7 +837,7 @@
         vpshufb %xmm2, %xmm9, %xmm9
         vpxor	%xmm9, \AAD_HASH, \AAD_HASH
 
-        cmp	$0, %r10
+        test	%r10, %r10
         jl	_partial_incomplete_2_\@
 
         # GHASH computation for the last <16 Byte block
@@ -857,7 +857,7 @@
         vpshufb	%xmm2, %xmm9, %xmm9
 .endif
         # output encrypted Bytes
-        cmp	$0, %r10
+        test	%r10, %r10
         jl	_partial_fill_\@
         mov	%r13, %r12
         mov	$16, %r13
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/crypto/aesni-intel_glue.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/crypto/aesni-intel_glue.c
@@ -83,10 +83,8 @@
 
 asmlinkage int aesni_set_key(struct crypto_aes_ctx *ctx, const u8 *in_key,
 			     unsigned int key_len);
-asmlinkage void aesni_enc(struct crypto_aes_ctx *ctx, u8 *out,
-			  const u8 *in);
-asmlinkage void aesni_dec(struct crypto_aes_ctx *ctx, u8 *out,
-			  const u8 *in);
+asmlinkage void aesni_enc(const void *ctx, u8 *out, const u8 *in);
+asmlinkage void aesni_dec(const void *ctx, u8 *out, const u8 *in);
 asmlinkage void aesni_ecb_enc(struct crypto_aes_ctx *ctx, u8 *out,
 			      const u8 *in, unsigned int len);
 asmlinkage void aesni_ecb_dec(struct crypto_aes_ctx *ctx, u8 *out,
@@ -99,6 +97,12 @@
 #define AVX_GEN2_OPTSIZE 640
 #define AVX_GEN4_OPTSIZE 4096
 
+asmlinkage void aesni_xts_encrypt(const struct crypto_aes_ctx *ctx, u8 *out,
+				  const u8 *in, unsigned int len, u8 *iv);
+
+asmlinkage void aesni_xts_decrypt(const struct crypto_aes_ctx *ctx, u8 *out,
+				  const u8 *in, unsigned int len, u8 *iv);
+
 #ifdef CONFIG_X86_64
 
 static void (*aesni_ctr_enc_tfm)(struct crypto_aes_ctx *ctx, u8 *out,
@@ -106,9 +110,6 @@
 asmlinkage void aesni_ctr_enc(struct crypto_aes_ctx *ctx, u8 *out,
 			      const u8 *in, unsigned int len, u8 *iv);
 
-asmlinkage void aesni_xts_crypt8(struct crypto_aes_ctx *ctx, u8 *out,
-				 const u8 *in, bool enc, u8 *iv);
-
 /* asmlinkage void aesni_gcm_enc()
  * void *ctx,  AES Key schedule. Starts on a 16 byte boundary.
  * struct gcm_context_data.  May be uninitialized.
@@ -550,29 +551,24 @@
 }
 
 
-static void aesni_xts_tweak(void *ctx, u8 *out, const u8 *in)
-{
-	aesni_enc(ctx, out, in);
-}
-
-static void aesni_xts_enc(void *ctx, u128 *dst, const u128 *src, le128 *iv)
+static void aesni_xts_enc(const void *ctx, u8 *dst, const u8 *src, le128 *iv)
 {
-	glue_xts_crypt_128bit_one(ctx, dst, src, iv, GLUE_FUNC_CAST(aesni_enc));
+	glue_xts_crypt_128bit_one(ctx, dst, src, iv, aesni_enc);
 }
 
-static void aesni_xts_dec(void *ctx, u128 *dst, const u128 *src, le128 *iv)
+static void aesni_xts_dec(const void *ctx, u8 *dst, const u8 *src, le128 *iv)
 {
-	glue_xts_crypt_128bit_one(ctx, dst, src, iv, GLUE_FUNC_CAST(aesni_dec));
+	glue_xts_crypt_128bit_one(ctx, dst, src, iv, aesni_dec);
 }
 
-static void aesni_xts_enc8(void *ctx, u128 *dst, const u128 *src, le128 *iv)
+static void aesni_xts_enc32(const void *ctx, u8 *dst, const u8 *src, le128 *iv)
 {
-	aesni_xts_crypt8(ctx, (u8 *)dst, (const u8 *)src, true, (u8 *)iv);
+	aesni_xts_encrypt(ctx, dst, src, 32 * AES_BLOCK_SIZE, (u8 *)iv);
 }
 
-static void aesni_xts_dec8(void *ctx, u128 *dst, const u128 *src, le128 *iv)
+static void aesni_xts_dec32(const void *ctx, u8 *dst, const u8 *src, le128 *iv)
 {
-	aesni_xts_crypt8(ctx, (u8 *)dst, (const u8 *)src, false, (u8 *)iv);
+	aesni_xts_decrypt(ctx, dst, src, 32 * AES_BLOCK_SIZE, (u8 *)iv);
 }
 
 static const struct common_glue_ctx aesni_enc_xts = {
@@ -580,11 +576,11 @@
 	.fpu_blocks_limit = 1,
 
 	.funcs = { {
-		.num_blocks = 8,
-		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(aesni_xts_enc8) }
+		.num_blocks = 32,
+		.fn_u = { .xts = aesni_xts_enc32 }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(aesni_xts_enc) }
+		.fn_u = { .xts = aesni_xts_enc }
 	} }
 };
 
@@ -593,11 +589,11 @@
 	.fpu_blocks_limit = 1,
 
 	.funcs = { {
-		.num_blocks = 8,
-		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(aesni_xts_dec8) }
+		.num_blocks = 32,
+		.fn_u = { .xts = aesni_xts_dec32 }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(aesni_xts_dec) }
+		.fn_u = { .xts = aesni_xts_dec }
 	} }
 };
 
@@ -606,8 +602,7 @@
 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
 	struct aesni_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
 
-	return glue_xts_req_128bit(&aesni_enc_xts, req,
-				   XTS_TWEAK_CAST(aesni_xts_tweak),
+	return glue_xts_req_128bit(&aesni_enc_xts, req, aesni_enc,
 				   aes_ctx(ctx->raw_tweak_ctx),
 				   aes_ctx(ctx->raw_crypt_ctx),
 				   false);
@@ -618,8 +613,7 @@
 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
 	struct aesni_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
 
-	return glue_xts_req_128bit(&aesni_dec_xts, req,
-				   XTS_TWEAK_CAST(aesni_xts_tweak),
+	return glue_xts_req_128bit(&aesni_dec_xts, req, aesni_enc,
 				   aes_ctx(ctx->raw_tweak_ctx),
 				   aes_ctx(ctx->raw_crypt_ctx),
 				   true);
@@ -707,7 +701,8 @@
 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
 	unsigned long auth_tag_len = crypto_aead_authsize(tfm);
 	const struct aesni_gcm_tfm_s *gcm_tfm = aesni_gcm_tfm;
-	struct gcm_context_data data AESNI_ALIGN_ATTR;
+	u8 databuf[sizeof(struct gcm_context_data) + (AESNI_ALIGN - 8)] __aligned(8);
+	struct gcm_context_data *data = PTR_ALIGN((void *)databuf, AESNI_ALIGN);
 	struct scatter_walk dst_sg_walk = {};
 	unsigned long left = req->cryptlen;
 	unsigned long len, srclen, dstlen;
@@ -760,8 +755,7 @@
 	}
 
 	kernel_fpu_begin();
-	gcm_tfm->init(aes_ctx, &data, iv,
-		hash_subkey, assoc, assoclen);
+	gcm_tfm->init(aes_ctx, data, iv, hash_subkey, assoc, assoclen);
 	if (req->src != req->dst) {
 		while (left) {
 			src = scatterwalk_map(&src_sg_walk);
@@ -771,10 +765,10 @@
 			len = min(srclen, dstlen);
 			if (len) {
 				if (enc)
-					gcm_tfm->enc_update(aes_ctx, &data,
+					gcm_tfm->enc_update(aes_ctx, data,
 							     dst, src, len);
 				else
-					gcm_tfm->dec_update(aes_ctx, &data,
+					gcm_tfm->dec_update(aes_ctx, data,
 							     dst, src, len);
 			}
 			left -= len;
@@ -792,10 +786,10 @@
 			len = scatterwalk_clamp(&src_sg_walk, left);
 			if (len) {
 				if (enc)
-					gcm_tfm->enc_update(aes_ctx, &data,
+					gcm_tfm->enc_update(aes_ctx, data,
 							     src, src, len);
 				else
-					gcm_tfm->dec_update(aes_ctx, &data,
+					gcm_tfm->dec_update(aes_ctx, data,
 							     src, src, len);
 			}
 			left -= len;
@@ -804,7 +798,7 @@
 			scatterwalk_done(&src_sg_walk, 1, left);
 		}
 	}
-	gcm_tfm->finalize(aes_ctx, &data, authTag, auth_tag_len);
+	gcm_tfm->finalize(aes_ctx, data, authTag, auth_tag_len);
 	kernel_fpu_end();
 
 	if (!assocmem)
@@ -853,7 +847,8 @@
 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
 	struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(tfm);
 	void *aes_ctx = &(ctx->aes_key_expanded);
-	u8 iv[16] __attribute__ ((__aligned__(AESNI_ALIGN)));
+	u8 ivbuf[16 + (AESNI_ALIGN - 8)] __aligned(8);
+	u8 *iv = PTR_ALIGN(&ivbuf[0], AESNI_ALIGN);
 	unsigned int i;
 	__be32 counter = cpu_to_be32(1);
 
@@ -880,7 +875,8 @@
 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
 	struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(tfm);
 	void *aes_ctx = &(ctx->aes_key_expanded);
-	u8 iv[16] __attribute__ ((__aligned__(AESNI_ALIGN)));
+	u8 ivbuf[16 + (AESNI_ALIGN - 8)] __aligned(8);
+	u8 *iv = PTR_ALIGN(&ivbuf[0], AESNI_ALIGN);
 	unsigned int i;
 
 	if (unlikely(req->assoclen != 16 && req->assoclen != 20))
@@ -1010,7 +1006,8 @@
 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
 	struct generic_gcmaes_ctx *ctx = generic_gcmaes_ctx_get(tfm);
 	void *aes_ctx = &(ctx->aes_key_expanded);
-	u8 iv[16] __attribute__ ((__aligned__(AESNI_ALIGN)));
+	u8 ivbuf[16 + (AESNI_ALIGN - 8)] __aligned(8);
+	u8 *iv = PTR_ALIGN(&ivbuf[0], AESNI_ALIGN);
 	__be32 counter = cpu_to_be32(1);
 
 	memcpy(iv, req->iv, 12);
@@ -1026,7 +1023,8 @@
 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
 	struct generic_gcmaes_ctx *ctx = generic_gcmaes_ctx_get(tfm);
 	void *aes_ctx = &(ctx->aes_key_expanded);
-	u8 iv[16] __attribute__ ((__aligned__(AESNI_ALIGN)));
+	u8 ivbuf[16 + (AESNI_ALIGN - 8)] __aligned(8);
+	u8 *iv = PTR_ALIGN(&ivbuf[0], AESNI_ALIGN);
 
 	memcpy(iv, req->iv, 12);
 	*((__be32 *)(iv+12)) = counter;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/crypto/camellia_aesni_avx2_glue.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/crypto/camellia_aesni_avx2_glue.c
@@ -19,20 +19,17 @@
 #define CAMELLIA_AESNI_AVX2_PARALLEL_BLOCKS 32
 
 /* 32-way AVX2/AES-NI parallel cipher functions */
-asmlinkage void camellia_ecb_enc_32way(struct camellia_ctx *ctx, u8 *dst,
-				       const u8 *src);
-asmlinkage void camellia_ecb_dec_32way(struct camellia_ctx *ctx, u8 *dst,
-				       const u8 *src);
-
-asmlinkage void camellia_cbc_dec_32way(struct camellia_ctx *ctx, u8 *dst,
-				       const u8 *src);
-asmlinkage void camellia_ctr_32way(struct camellia_ctx *ctx, u8 *dst,
-				   const u8 *src, le128 *iv);
-
-asmlinkage void camellia_xts_enc_32way(struct camellia_ctx *ctx, u8 *dst,
-				       const u8 *src, le128 *iv);
-asmlinkage void camellia_xts_dec_32way(struct camellia_ctx *ctx, u8 *dst,
-				       const u8 *src, le128 *iv);
+asmlinkage void camellia_ecb_enc_32way(const void *ctx, u8 *dst, const u8 *src);
+asmlinkage void camellia_ecb_dec_32way(const void *ctx, u8 *dst, const u8 *src);
+
+asmlinkage void camellia_cbc_dec_32way(const void *ctx, u8 *dst, const u8 *src);
+asmlinkage void camellia_ctr_32way(const void *ctx, u8 *dst, const u8 *src,
+				   le128 *iv);
+
+asmlinkage void camellia_xts_enc_32way(const void *ctx, u8 *dst, const u8 *src,
+				       le128 *iv);
+asmlinkage void camellia_xts_dec_32way(const void *ctx, u8 *dst, const u8 *src,
+				       le128 *iv);
 
 static const struct common_glue_ctx camellia_enc = {
 	.num_funcs = 4,
@@ -40,16 +37,16 @@
 
 	.funcs = { {
 		.num_blocks = CAMELLIA_AESNI_AVX2_PARALLEL_BLOCKS,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(camellia_ecb_enc_32way) }
+		.fn_u = { .ecb = camellia_ecb_enc_32way }
 	}, {
 		.num_blocks = CAMELLIA_AESNI_PARALLEL_BLOCKS,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(camellia_ecb_enc_16way) }
+		.fn_u = { .ecb = camellia_ecb_enc_16way }
 	}, {
 		.num_blocks = 2,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(camellia_enc_blk_2way) }
+		.fn_u = { .ecb = camellia_enc_blk_2way }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(camellia_enc_blk) }
+		.fn_u = { .ecb = camellia_enc_blk }
 	} }
 };
 
@@ -59,16 +56,16 @@
 
 	.funcs = { {
 		.num_blocks = CAMELLIA_AESNI_AVX2_PARALLEL_BLOCKS,
-		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(camellia_ctr_32way) }
+		.fn_u = { .ctr = camellia_ctr_32way }
 	}, {
 		.num_blocks = CAMELLIA_AESNI_PARALLEL_BLOCKS,
-		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(camellia_ctr_16way) }
+		.fn_u = { .ctr = camellia_ctr_16way }
 	}, {
 		.num_blocks = 2,
-		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(camellia_crypt_ctr_2way) }
+		.fn_u = { .ctr = camellia_crypt_ctr_2way }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(camellia_crypt_ctr) }
+		.fn_u = { .ctr = camellia_crypt_ctr }
 	} }
 };
 
@@ -78,13 +75,13 @@
 
 	.funcs = { {
 		.num_blocks = CAMELLIA_AESNI_AVX2_PARALLEL_BLOCKS,
-		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(camellia_xts_enc_32way) }
+		.fn_u = { .xts = camellia_xts_enc_32way }
 	}, {
 		.num_blocks = CAMELLIA_AESNI_PARALLEL_BLOCKS,
-		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(camellia_xts_enc_16way) }
+		.fn_u = { .xts = camellia_xts_enc_16way }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(camellia_xts_enc) }
+		.fn_u = { .xts = camellia_xts_enc }
 	} }
 };
 
@@ -94,16 +91,16 @@
 
 	.funcs = { {
 		.num_blocks = CAMELLIA_AESNI_AVX2_PARALLEL_BLOCKS,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(camellia_ecb_dec_32way) }
+		.fn_u = { .ecb = camellia_ecb_dec_32way }
 	}, {
 		.num_blocks = CAMELLIA_AESNI_PARALLEL_BLOCKS,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(camellia_ecb_dec_16way) }
+		.fn_u = { .ecb = camellia_ecb_dec_16way }
 	}, {
 		.num_blocks = 2,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(camellia_dec_blk_2way) }
+		.fn_u = { .ecb = camellia_dec_blk_2way }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(camellia_dec_blk) }
+		.fn_u = { .ecb = camellia_dec_blk }
 	} }
 };
 
@@ -113,16 +110,16 @@
 
 	.funcs = { {
 		.num_blocks = CAMELLIA_AESNI_AVX2_PARALLEL_BLOCKS,
-		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(camellia_cbc_dec_32way) }
+		.fn_u = { .cbc = camellia_cbc_dec_32way }
 	}, {
 		.num_blocks = CAMELLIA_AESNI_PARALLEL_BLOCKS,
-		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(camellia_cbc_dec_16way) }
+		.fn_u = { .cbc = camellia_cbc_dec_16way }
 	}, {
 		.num_blocks = 2,
-		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(camellia_decrypt_cbc_2way) }
+		.fn_u = { .cbc = camellia_decrypt_cbc_2way }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(camellia_dec_blk) }
+		.fn_u = { .cbc = camellia_dec_blk }
 	} }
 };
 
@@ -132,13 +129,13 @@
 
 	.funcs = { {
 		.num_blocks = CAMELLIA_AESNI_AVX2_PARALLEL_BLOCKS,
-		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(camellia_xts_dec_32way) }
+		.fn_u = { .xts = camellia_xts_dec_32way }
 	}, {
 		.num_blocks = CAMELLIA_AESNI_PARALLEL_BLOCKS,
-		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(camellia_xts_dec_16way) }
+		.fn_u = { .xts = camellia_xts_dec_16way }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(camellia_xts_dec) }
+		.fn_u = { .xts = camellia_xts_dec }
 	} }
 };
 
@@ -161,8 +158,7 @@
 
 static int cbc_encrypt(struct skcipher_request *req)
 {
-	return glue_cbc_encrypt_req_128bit(GLUE_FUNC_CAST(camellia_enc_blk),
-					   req);
+	return glue_cbc_encrypt_req_128bit(camellia_enc_blk, req);
 }
 
 static int cbc_decrypt(struct skcipher_request *req)
@@ -180,8 +176,7 @@
 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
 	struct camellia_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
 
-	return glue_xts_req_128bit(&camellia_enc_xts, req,
-				   XTS_TWEAK_CAST(camellia_enc_blk),
+	return glue_xts_req_128bit(&camellia_enc_xts, req, camellia_enc_blk,
 				   &ctx->tweak_ctx, &ctx->crypt_ctx, false);
 }
 
@@ -190,8 +185,7 @@
 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
 	struct camellia_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
 
-	return glue_xts_req_128bit(&camellia_dec_xts, req,
-				   XTS_TWEAK_CAST(camellia_enc_blk),
+	return glue_xts_req_128bit(&camellia_dec_xts, req, camellia_enc_blk,
 				   &ctx->tweak_ctx, &ctx->crypt_ctx, true);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/crypto/camellia_aesni_avx_glue.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/crypto/camellia_aesni_avx_glue.c
@@ -18,41 +18,36 @@
 #define CAMELLIA_AESNI_PARALLEL_BLOCKS 16
 
 /* 16-way parallel cipher functions (avx/aes-ni) */
-asmlinkage void camellia_ecb_enc_16way(struct camellia_ctx *ctx, u8 *dst,
-				       const u8 *src);
+asmlinkage void camellia_ecb_enc_16way(const void *ctx, u8 *dst, const u8 *src);
 EXPORT_SYMBOL_GPL(camellia_ecb_enc_16way);
 
-asmlinkage void camellia_ecb_dec_16way(struct camellia_ctx *ctx, u8 *dst,
-				       const u8 *src);
+asmlinkage void camellia_ecb_dec_16way(const void *ctx, u8 *dst, const u8 *src);
 EXPORT_SYMBOL_GPL(camellia_ecb_dec_16way);
 
-asmlinkage void camellia_cbc_dec_16way(struct camellia_ctx *ctx, u8 *dst,
-				       const u8 *src);
+asmlinkage void camellia_cbc_dec_16way(const void *ctx, u8 *dst, const u8 *src);
 EXPORT_SYMBOL_GPL(camellia_cbc_dec_16way);
 
-asmlinkage void camellia_ctr_16way(struct camellia_ctx *ctx, u8 *dst,
-				   const u8 *src, le128 *iv);
+asmlinkage void camellia_ctr_16way(const void *ctx, u8 *dst, const u8 *src,
+				   le128 *iv);
 EXPORT_SYMBOL_GPL(camellia_ctr_16way);
 
-asmlinkage void camellia_xts_enc_16way(struct camellia_ctx *ctx, u8 *dst,
-				       const u8 *src, le128 *iv);
+asmlinkage void camellia_xts_enc_16way(const void *ctx, u8 *dst, const u8 *src,
+				       le128 *iv);
 EXPORT_SYMBOL_GPL(camellia_xts_enc_16way);
 
-asmlinkage void camellia_xts_dec_16way(struct camellia_ctx *ctx, u8 *dst,
-				       const u8 *src, le128 *iv);
+asmlinkage void camellia_xts_dec_16way(const void *ctx, u8 *dst, const u8 *src,
+				       le128 *iv);
 EXPORT_SYMBOL_GPL(camellia_xts_dec_16way);
 
-void camellia_xts_enc(void *ctx, u128 *dst, const u128 *src, le128 *iv)
+void camellia_xts_enc(const void *ctx, u8 *dst, const u8 *src, le128 *iv)
 {
-	glue_xts_crypt_128bit_one(ctx, dst, src, iv,
-				  GLUE_FUNC_CAST(camellia_enc_blk));
+	glue_xts_crypt_128bit_one(ctx, dst, src, iv, camellia_enc_blk);
 }
 EXPORT_SYMBOL_GPL(camellia_xts_enc);
 
-void camellia_xts_dec(void *ctx, u128 *dst, const u128 *src, le128 *iv)
+void camellia_xts_dec(const void *ctx, u8 *dst, const u8 *src, le128 *iv)
 {
-	glue_xts_crypt_128bit_one(ctx, dst, src, iv,
-				  GLUE_FUNC_CAST(camellia_dec_blk));
+	glue_xts_crypt_128bit_one(ctx, dst, src, iv, camellia_dec_blk);
 }
 EXPORT_SYMBOL_GPL(camellia_xts_dec);
 
@@ -62,13 +57,13 @@
 
 	.funcs = { {
 		.num_blocks = CAMELLIA_AESNI_PARALLEL_BLOCKS,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(camellia_ecb_enc_16way) }
+		.fn_u = { .ecb = camellia_ecb_enc_16way }
 	}, {
 		.num_blocks = 2,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(camellia_enc_blk_2way) }
+		.fn_u = { .ecb = camellia_enc_blk_2way }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(camellia_enc_blk) }
+		.fn_u = { .ecb = camellia_enc_blk }
 	} }
 };
 
@@ -78,13 +73,13 @@
 
 	.funcs = { {
 		.num_blocks = CAMELLIA_AESNI_PARALLEL_BLOCKS,
-		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(camellia_ctr_16way) }
+		.fn_u = { .ctr = camellia_ctr_16way }
 	}, {
 		.num_blocks = 2,
-		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(camellia_crypt_ctr_2way) }
+		.fn_u = { .ctr = camellia_crypt_ctr_2way }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(camellia_crypt_ctr) }
+		.fn_u = { .ctr = camellia_crypt_ctr }
 	} }
 };
 
@@ -94,10 +89,10 @@
 
 	.funcs = { {
 		.num_blocks = CAMELLIA_AESNI_PARALLEL_BLOCKS,
-		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(camellia_xts_enc_16way) }
+		.fn_u = { .xts = camellia_xts_enc_16way }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(camellia_xts_enc) }
+		.fn_u = { .xts = camellia_xts_enc }
 	} }
 };
 
@@ -107,13 +102,13 @@
 
 	.funcs = { {
 		.num_blocks = CAMELLIA_AESNI_PARALLEL_BLOCKS,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(camellia_ecb_dec_16way) }
+		.fn_u = { .ecb = camellia_ecb_dec_16way }
 	}, {
 		.num_blocks = 2,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(camellia_dec_blk_2way) }
+		.fn_u = { .ecb = camellia_dec_blk_2way }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(camellia_dec_blk) }
+		.fn_u = { .ecb = camellia_dec_blk }
 	} }
 };
 
@@ -123,13 +118,13 @@
 
 	.funcs = { {
 		.num_blocks = CAMELLIA_AESNI_PARALLEL_BLOCKS,
-		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(camellia_cbc_dec_16way) }
+		.fn_u = { .cbc = camellia_cbc_dec_16way }
 	}, {
 		.num_blocks = 2,
-		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(camellia_decrypt_cbc_2way) }
+		.fn_u = { .cbc = camellia_decrypt_cbc_2way }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(camellia_dec_blk) }
+		.fn_u = { .cbc = camellia_dec_blk }
 	} }
 };
 
@@ -139,10 +134,10 @@
 
 	.funcs = { {
 		.num_blocks = CAMELLIA_AESNI_PARALLEL_BLOCKS,
-		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(camellia_xts_dec_16way) }
+		.fn_u = { .xts = camellia_xts_dec_16way }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(camellia_xts_dec) }
+		.fn_u = { .xts = camellia_xts_dec }
 	} }
 };
 
@@ -165,8 +160,7 @@
 
 static int cbc_encrypt(struct skcipher_request *req)
 {
-	return glue_cbc_encrypt_req_128bit(GLUE_FUNC_CAST(camellia_enc_blk),
-					   req);
+	return glue_cbc_encrypt_req_128bit(camellia_enc_blk, req);
 }
 
 static int cbc_decrypt(struct skcipher_request *req)
@@ -206,8 +200,7 @@
 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
 	struct camellia_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
 
-	return glue_xts_req_128bit(&camellia_enc_xts, req,
-				   XTS_TWEAK_CAST(camellia_enc_blk),
+	return glue_xts_req_128bit(&camellia_enc_xts, req, camellia_enc_blk,
 				   &ctx->tweak_ctx, &ctx->crypt_ctx, false);
 }
 
@@ -216,8 +209,7 @@
 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
 	struct camellia_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
 
-	return glue_xts_req_128bit(&camellia_dec_xts, req,
-				   XTS_TWEAK_CAST(camellia_enc_blk),
+	return glue_xts_req_128bit(&camellia_dec_xts, req, camellia_enc_blk,
 				   &ctx->tweak_ctx, &ctx->crypt_ctx, true);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/crypto/camellia_glue.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/crypto/camellia_glue.c
@@ -18,19 +18,17 @@
 #include <asm/crypto/glue_helper.h>
 
 /* regular block cipher functions */
-asmlinkage void __camellia_enc_blk(struct camellia_ctx *ctx, u8 *dst,
-				   const u8 *src, bool xor);
+asmlinkage void __camellia_enc_blk(const void *ctx, u8 *dst, const u8 *src,
+				   bool xor);
 EXPORT_SYMBOL_GPL(__camellia_enc_blk);
-asmlinkage void camellia_dec_blk(struct camellia_ctx *ctx, u8 *dst,
-				 const u8 *src);
+asmlinkage void camellia_dec_blk(const void *ctx, u8 *dst, const u8 *src);
 EXPORT_SYMBOL_GPL(camellia_dec_blk);
 
 /* 2-way parallel cipher functions */
-asmlinkage void __camellia_enc_blk_2way(struct camellia_ctx *ctx, u8 *dst,
-					const u8 *src, bool xor);
+asmlinkage void __camellia_enc_blk_2way(const void *ctx, u8 *dst, const u8 *src,
+					bool xor);
 EXPORT_SYMBOL_GPL(__camellia_enc_blk_2way);
-asmlinkage void camellia_dec_blk_2way(struct camellia_ctx *ctx, u8 *dst,
-				      const u8 *src);
+asmlinkage void camellia_dec_blk_2way(const void *ctx, u8 *dst, const u8 *src);
 EXPORT_SYMBOL_GPL(camellia_dec_blk_2way);
 
 static void camellia_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
@@ -1267,8 +1265,10 @@
 	return camellia_setkey(&tfm->base, key, key_len);
 }
 
-void camellia_decrypt_cbc_2way(void *ctx, u128 *dst, const u128 *src)
+void camellia_decrypt_cbc_2way(const void *ctx, u8 *d, const u8 *s)
 {
+	u128 *dst = (u128 *)d;
+	const u128 *src = (const u128 *)s;
 	u128 iv = *src;
 
 	camellia_dec_blk_2way(ctx, (u8 *)dst, (u8 *)src);
@@ -1277,9 +1277,11 @@
 }
 EXPORT_SYMBOL_GPL(camellia_decrypt_cbc_2way);
 
-void camellia_crypt_ctr(void *ctx, u128 *dst, const u128 *src, le128 *iv)
+void camellia_crypt_ctr(const void *ctx, u8 *d, const u8 *s, le128 *iv)
 {
 	be128 ctrblk;
+	u128 *dst = (u128 *)d;
+	const u128 *src = (const u128 *)s;
 
 	if (dst != src)
 		*dst = *src;
@@ -1291,9 +1293,11 @@
 }
 EXPORT_SYMBOL_GPL(camellia_crypt_ctr);
 
-void camellia_crypt_ctr_2way(void *ctx, u128 *dst, const u128 *src, le128 *iv)
+void camellia_crypt_ctr_2way(const void *ctx, u8 *d, const u8 *s, le128 *iv)
 {
 	be128 ctrblks[2];
+	u128 *dst = (u128 *)d;
+	const u128 *src = (const u128 *)s;
 
 	if (dst != src) {
 		dst[0] = src[0];
@@ -1315,10 +1319,10 @@
 
 	.funcs = { {
 		.num_blocks = 2,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(camellia_enc_blk_2way) }
+		.fn_u = { .ecb = camellia_enc_blk_2way }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(camellia_enc_blk) }
+		.fn_u = { .ecb = camellia_enc_blk }
 	} }
 };
 
@@ -1328,10 +1332,10 @@
 
 	.funcs = { {
 		.num_blocks = 2,
-		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(camellia_crypt_ctr_2way) }
+		.fn_u = { .ctr = camellia_crypt_ctr_2way }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(camellia_crypt_ctr) }
+		.fn_u = { .ctr = camellia_crypt_ctr }
 	} }
 };
 
@@ -1341,10 +1345,10 @@
 
 	.funcs = { {
 		.num_blocks = 2,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(camellia_dec_blk_2way) }
+		.fn_u = { .ecb = camellia_dec_blk_2way }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(camellia_dec_blk) }
+		.fn_u = { .ecb = camellia_dec_blk }
 	} }
 };
 
@@ -1354,10 +1358,10 @@
 
 	.funcs = { {
 		.num_blocks = 2,
-		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(camellia_decrypt_cbc_2way) }
+		.fn_u = { .cbc = camellia_decrypt_cbc_2way }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(camellia_dec_blk) }
+		.fn_u = { .cbc = camellia_dec_blk }
 	} }
 };
 
@@ -1373,8 +1377,7 @@
 
 static int cbc_encrypt(struct skcipher_request *req)
 {
-	return glue_cbc_encrypt_req_128bit(GLUE_FUNC_CAST(camellia_enc_blk),
-					   req);
+	return glue_cbc_encrypt_req_128bit(camellia_enc_blk, req);
 }
 
 static int cbc_decrypt(struct skcipher_request *req)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/crypto/cast6_avx_glue.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/crypto/cast6_avx_glue.c
@@ -20,20 +20,17 @@
 
 #define CAST6_PARALLEL_BLOCKS 8
 
-asmlinkage void cast6_ecb_enc_8way(struct cast6_ctx *ctx, u8 *dst,
-				   const u8 *src);
-asmlinkage void cast6_ecb_dec_8way(struct cast6_ctx *ctx, u8 *dst,
-				   const u8 *src);
-
-asmlinkage void cast6_cbc_dec_8way(struct cast6_ctx *ctx, u8 *dst,
-				   const u8 *src);
-asmlinkage void cast6_ctr_8way(struct cast6_ctx *ctx, u8 *dst, const u8 *src,
+asmlinkage void cast6_ecb_enc_8way(const void *ctx, u8 *dst, const u8 *src);
+asmlinkage void cast6_ecb_dec_8way(const void *ctx, u8 *dst, const u8 *src);
+
+asmlinkage void cast6_cbc_dec_8way(const void *ctx, u8 *dst, const u8 *src);
+asmlinkage void cast6_ctr_8way(const void *ctx, u8 *dst, const u8 *src,
 			       le128 *iv);
 
-asmlinkage void cast6_xts_enc_8way(struct cast6_ctx *ctx, u8 *dst,
-				   const u8 *src, le128 *iv);
-asmlinkage void cast6_xts_dec_8way(struct cast6_ctx *ctx, u8 *dst,
-				   const u8 *src, le128 *iv);
+asmlinkage void cast6_xts_enc_8way(const void *ctx, u8 *dst, const u8 *src,
+				   le128 *iv);
+asmlinkage void cast6_xts_dec_8way(const void *ctx, u8 *dst, const u8 *src,
+				   le128 *iv);
 
 static int cast6_setkey_skcipher(struct crypto_skcipher *tfm,
 				 const u8 *key, unsigned int keylen)
@@ -41,21 +38,21 @@
 	return cast6_setkey(&tfm->base, key, keylen);
 }
 
-static void cast6_xts_enc(void *ctx, u128 *dst, const u128 *src, le128 *iv)
+static void cast6_xts_enc(const void *ctx, u8 *dst, const u8 *src, le128 *iv)
 {
-	glue_xts_crypt_128bit_one(ctx, dst, src, iv,
-				  GLUE_FUNC_CAST(__cast6_encrypt));
+	glue_xts_crypt_128bit_one(ctx, dst, src, iv, __cast6_encrypt);
 }
 
-static void cast6_xts_dec(void *ctx, u128 *dst, const u128 *src, le128 *iv)
+static void cast6_xts_dec(const void *ctx, u8 *dst, const u8 *src, le128 *iv)
 {
-	glue_xts_crypt_128bit_one(ctx, dst, src, iv,
-				  GLUE_FUNC_CAST(__cast6_decrypt));
+	glue_xts_crypt_128bit_one(ctx, dst, src, iv, __cast6_decrypt);
 }
 
-static void cast6_crypt_ctr(void *ctx, u128 *dst, const u128 *src, le128 *iv)
+static void cast6_crypt_ctr(const void *ctx, u8 *d, const u8 *s, le128 *iv)
 {
 	be128 ctrblk;
+	u128 *dst = (u128 *)d;
+	const u128 *src = (const u128 *)s;
 
 	le128_to_be128(&ctrblk, iv);
 	le128_inc(iv);
@@ -70,10 +67,10 @@
 
 	.funcs = { {
 		.num_blocks = CAST6_PARALLEL_BLOCKS,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(cast6_ecb_enc_8way) }
+		.fn_u = { .ecb = cast6_ecb_enc_8way }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(__cast6_encrypt) }
+		.fn_u = { .ecb = __cast6_encrypt }
 	} }
 };
 
@@ -83,10 +80,10 @@
 
 	.funcs = { {
 		.num_blocks = CAST6_PARALLEL_BLOCKS,
-		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(cast6_ctr_8way) }
+		.fn_u = { .ctr = cast6_ctr_8way }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(cast6_crypt_ctr) }
+		.fn_u = { .ctr = cast6_crypt_ctr }
 	} }
 };
 
@@ -96,10 +93,10 @@
 
 	.funcs = { {
 		.num_blocks = CAST6_PARALLEL_BLOCKS,
-		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(cast6_xts_enc_8way) }
+		.fn_u = { .xts = cast6_xts_enc_8way }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(cast6_xts_enc) }
+		.fn_u = { .xts = cast6_xts_enc }
 	} }
 };
 
@@ -109,10 +106,10 @@
 
 	.funcs = { {
 		.num_blocks = CAST6_PARALLEL_BLOCKS,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(cast6_ecb_dec_8way) }
+		.fn_u = { .ecb = cast6_ecb_dec_8way }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(__cast6_decrypt) }
+		.fn_u = { .ecb = __cast6_decrypt }
 	} }
 };
 
@@ -122,10 +119,10 @@
 
 	.funcs = { {
 		.num_blocks = CAST6_PARALLEL_BLOCKS,
-		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(cast6_cbc_dec_8way) }
+		.fn_u = { .cbc = cast6_cbc_dec_8way }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(__cast6_decrypt) }
+		.fn_u = { .cbc = __cast6_decrypt }
 	} }
 };
 
@@ -135,10 +132,10 @@
 
 	.funcs = { {
 		.num_blocks = CAST6_PARALLEL_BLOCKS,
-		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(cast6_xts_dec_8way) }
+		.fn_u = { .xts = cast6_xts_dec_8way }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(cast6_xts_dec) }
+		.fn_u = { .xts = cast6_xts_dec }
 	} }
 };
 
@@ -154,8 +151,7 @@
 
 static int cbc_encrypt(struct skcipher_request *req)
 {
-	return glue_cbc_encrypt_req_128bit(GLUE_FUNC_CAST(__cast6_encrypt),
-					   req);
+	return glue_cbc_encrypt_req_128bit(__cast6_encrypt, req);
 }
 
 static int cbc_decrypt(struct skcipher_request *req)
@@ -199,8 +195,7 @@
 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
 	struct cast6_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
 
-	return glue_xts_req_128bit(&cast6_enc_xts, req,
-				   XTS_TWEAK_CAST(__cast6_encrypt),
+	return glue_xts_req_128bit(&cast6_enc_xts, req, __cast6_encrypt,
 				   &ctx->tweak_ctx, &ctx->crypt_ctx, false);
 }
 
@@ -209,8 +204,7 @@
 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
 	struct cast6_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
 
-	return glue_xts_req_128bit(&cast6_dec_xts, req,
-				   XTS_TWEAK_CAST(__cast6_encrypt),
+	return glue_xts_req_128bit(&cast6_dec_xts, req, __cast6_encrypt,
 				   &ctx->tweak_ctx, &ctx->crypt_ctx, true);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/crypto/chacha-avx512vl-x86_64.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/crypto/chacha-avx512vl-x86_64.S
@@ -172,7 +172,7 @@
 	# xor remaining bytes from partial register into output
 	mov		%rcx,%rax
 	and		$0xf,%rcx
-	jz		.Ldone8
+	jz		.Ldone2
 	mov		%rax,%r9
 	and		$~0xf,%r9
 
@@ -438,7 +438,7 @@
 	# xor remaining bytes from partial register into output
 	mov		%rcx,%rax
 	and		$0xf,%rcx
-	jz		.Ldone8
+	jz		.Ldone4
 	mov		%rax,%r9
 	and		$~0xf,%r9
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/crypto/crc32c-pcl-intel-asm_64.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/crypto/crc32c-pcl-intel-asm_64.S
@@ -170,7 +170,7 @@
 
 	## branch into array
 	lea	jump_table(%rip), bufp
-	movzxw  (bufp, %rax, 2), len
+	movzwq  (bufp, %rax, 2), len
 	lea	crc_array(%rip), bufp
 	lea     (bufp, len, 1), bufp
 	JMP_NOSPEC bufp
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/crypto/ghash-clmulni-intel_glue.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/crypto/ghash-clmulni-intel_glue.c
@@ -19,6 +19,7 @@
 #include <crypto/internal/simd.h>
 #include <asm/cpu_device_id.h>
 #include <asm/simd.h>
+#include <asm/unaligned.h>
 
 #define GHASH_BLOCK_SIZE	16
 #define GHASH_DIGEST_SIZE	16
@@ -54,7 +55,6 @@
 			const u8 *key, unsigned int keylen)
 {
 	struct ghash_ctx *ctx = crypto_shash_ctx(tfm);
-	be128 *x = (be128 *)key;
 	u64 a, b;
 
 	if (keylen != GHASH_BLOCK_SIZE) {
@@ -63,8 +63,8 @@
 	}
 
 	/* perform multiplication by 'x' in GF(2^128) */
-	a = be64_to_cpu(x->a);
-	b = be64_to_cpu(x->b);
+	a = get_unaligned_be64(key);
+	b = get_unaligned_be64(key + 8);
 
 	ctx->shash.a = (b << 1) | (a >> 63);
 	ctx->shash.b = (a << 1) | (b >> 63);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/crypto/glue_helper.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/crypto/glue_helper.c
@@ -134,7 +134,8 @@
 				src -= num_blocks - 1;
 				dst -= num_blocks - 1;
 
-				gctx->funcs[i].fn_u.cbc(ctx, dst, src);
+				gctx->funcs[i].fn_u.cbc(ctx, (u8 *)dst,
+							(const u8 *)src);
 
 				nbytes -= func_bytes;
 				if (nbytes < bsize)
@@ -188,7 +189,9 @@
 
 			/* Process multi-block batch */
 			do {
-				gctx->funcs[i].fn_u.ctr(ctx, dst, src, &ctrblk);
+				gctx->funcs[i].fn_u.ctr(ctx, (u8 *)dst,
+							(const u8 *)src,
+							&ctrblk);
 				src += num_blocks;
 				dst += num_blocks;
 				nbytes -= func_bytes;
@@ -210,7 +213,8 @@
 
 		be128_to_le128(&ctrblk, (be128 *)walk.iv);
 		memcpy(&tmp, walk.src.virt.addr, nbytes);
-		gctx->funcs[gctx->num_funcs - 1].fn_u.ctr(ctx, &tmp, &tmp,
+		gctx->funcs[gctx->num_funcs - 1].fn_u.ctr(ctx, (u8 *)&tmp,
+							  (const u8 *)&tmp,
 							  &ctrblk);
 		memcpy(walk.dst.virt.addr, &tmp, nbytes);
 		le128_to_be128((be128 *)walk.iv, &ctrblk);
@@ -240,7 +244,8 @@
 
 		if (nbytes >= func_bytes) {
 			do {
-				gctx->funcs[i].fn_u.xts(ctx, dst, src,
+				gctx->funcs[i].fn_u.xts(ctx, (u8 *)dst,
+							(const u8 *)src,
 							walk->iv);
 
 				src += num_blocks;
@@ -354,8 +359,8 @@
 }
 EXPORT_SYMBOL_GPL(glue_xts_req_128bit);
 
-void glue_xts_crypt_128bit_one(void *ctx, u128 *dst, const u128 *src, le128 *iv,
-			       common_glue_func_t fn)
+void glue_xts_crypt_128bit_one(const void *ctx, u8 *dst, const u8 *src,
+			       le128 *iv, common_glue_func_t fn)
 {
 	le128 ivblk = *iv;
 
@@ -363,13 +368,13 @@
 	gf128mul_x_ble(iv, &ivblk);
 
 	/* CC <- T xor C */
-	u128_xor(dst, src, (u128 *)&ivblk);
+	u128_xor((u128 *)dst, (const u128 *)src, (u128 *)&ivblk);
 
 	/* PP <- D(Key2,CC) */
-	fn(ctx, (u8 *)dst, (u8 *)dst);
+	fn(ctx, dst, dst);
 
 	/* P <- T xor PP */
-	u128_xor(dst, dst, (u128 *)&ivblk);
+	u128_xor((u128 *)dst, (u128 *)dst, (u128 *)&ivblk);
 }
 EXPORT_SYMBOL_GPL(glue_xts_crypt_128bit_one);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/crypto/nhpoly1305-avx2-glue.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/crypto/nhpoly1305-avx2-glue.c
@@ -29,7 +29,7 @@
 		return crypto_nhpoly1305_update(desc, src, srclen);
 
 	do {
-		unsigned int n = min_t(unsigned int, srclen, PAGE_SIZE);
+		unsigned int n = min_t(unsigned int, srclen, SZ_4K);
 
 		kernel_fpu_begin();
 		crypto_nhpoly1305_update_helper(desc, src, n, _nh_avx2);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/crypto/nhpoly1305-sse2-glue.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/crypto/nhpoly1305-sse2-glue.c
@@ -29,7 +29,7 @@
 		return crypto_nhpoly1305_update(desc, src, srclen);
 
 	do {
-		unsigned int n = min_t(unsigned int, srclen, PAGE_SIZE);
+		unsigned int n = min_t(unsigned int, srclen, SZ_4K);
 
 		kernel_fpu_begin();
 		crypto_nhpoly1305_update_helper(desc, src, n, _nh_sse2);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/crypto/serpent_avx2_glue.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/crypto/serpent_avx2_glue.c
@@ -19,18 +19,16 @@
 #define SERPENT_AVX2_PARALLEL_BLOCKS 16
 
 /* 16-way AVX2 parallel cipher functions */
-asmlinkage void serpent_ecb_enc_16way(struct serpent_ctx *ctx, u8 *dst,
-				      const u8 *src);
-asmlinkage void serpent_ecb_dec_16way(struct serpent_ctx *ctx, u8 *dst,
-				      const u8 *src);
-asmlinkage void serpent_cbc_dec_16way(void *ctx, u128 *dst, const u128 *src);
+asmlinkage void serpent_ecb_enc_16way(const void *ctx, u8 *dst, const u8 *src);
+asmlinkage void serpent_ecb_dec_16way(const void *ctx, u8 *dst, const u8 *src);
+asmlinkage void serpent_cbc_dec_16way(const void *ctx, u8 *dst, const u8 *src);
 
-asmlinkage void serpent_ctr_16way(void *ctx, u128 *dst, const u128 *src,
+asmlinkage void serpent_ctr_16way(const void *ctx, u8 *dst, const u8 *src,
 				  le128 *iv);
-asmlinkage void serpent_xts_enc_16way(struct serpent_ctx *ctx, u8 *dst,
-				      const u8 *src, le128 *iv);
-asmlinkage void serpent_xts_dec_16way(struct serpent_ctx *ctx, u8 *dst,
-				      const u8 *src, le128 *iv);
+asmlinkage void serpent_xts_enc_16way(const void *ctx, u8 *dst, const u8 *src,
+				      le128 *iv);
+asmlinkage void serpent_xts_dec_16way(const void *ctx, u8 *dst, const u8 *src,
+				      le128 *iv);
 
 static int serpent_setkey_skcipher(struct crypto_skcipher *tfm,
 				   const u8 *key, unsigned int keylen)
@@ -44,13 +42,13 @@
 
 	.funcs = { {
 		.num_blocks = 16,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(serpent_ecb_enc_16way) }
+		.fn_u = { .ecb = serpent_ecb_enc_16way }
 	}, {
 		.num_blocks = 8,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(serpent_ecb_enc_8way_avx) }
+		.fn_u = { .ecb = serpent_ecb_enc_8way_avx }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(__serpent_encrypt) }
+		.fn_u = { .ecb = __serpent_encrypt }
 	} }
 };
 
@@ -60,13 +58,13 @@
 
 	.funcs = { {
 		.num_blocks = 16,
-		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(serpent_ctr_16way) }
+		.fn_u = { .ctr = serpent_ctr_16way }
 	},  {
 		.num_blocks = 8,
-		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(serpent_ctr_8way_avx) }
+		.fn_u = { .ctr = serpent_ctr_8way_avx }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(__serpent_crypt_ctr) }
+		.fn_u = { .ctr = __serpent_crypt_ctr }
 	} }
 };
 
@@ -76,13 +74,13 @@
 
 	.funcs = { {
 		.num_blocks = 16,
-		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(serpent_xts_enc_16way) }
+		.fn_u = { .xts = serpent_xts_enc_16way }
 	}, {
 		.num_blocks = 8,
-		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(serpent_xts_enc_8way_avx) }
+		.fn_u = { .xts = serpent_xts_enc_8way_avx }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(serpent_xts_enc) }
+		.fn_u = { .xts = serpent_xts_enc }
 	} }
 };
 
@@ -92,13 +90,13 @@
 
 	.funcs = { {
 		.num_blocks = 16,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(serpent_ecb_dec_16way) }
+		.fn_u = { .ecb = serpent_ecb_dec_16way }
 	}, {
 		.num_blocks = 8,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(serpent_ecb_dec_8way_avx) }
+		.fn_u = { .ecb = serpent_ecb_dec_8way_avx }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(__serpent_decrypt) }
+		.fn_u = { .ecb = __serpent_decrypt }
 	} }
 };
 
@@ -108,13 +106,13 @@
 
 	.funcs = { {
 		.num_blocks = 16,
-		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(serpent_cbc_dec_16way) }
+		.fn_u = { .cbc = serpent_cbc_dec_16way }
 	}, {
 		.num_blocks = 8,
-		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(serpent_cbc_dec_8way_avx) }
+		.fn_u = { .cbc = serpent_cbc_dec_8way_avx }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(__serpent_decrypt) }
+		.fn_u = { .cbc = __serpent_decrypt }
 	} }
 };
 
@@ -124,13 +122,13 @@
 
 	.funcs = { {
 		.num_blocks = 16,
-		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(serpent_xts_dec_16way) }
+		.fn_u = { .xts = serpent_xts_dec_16way }
 	}, {
 		.num_blocks = 8,
-		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(serpent_xts_dec_8way_avx) }
+		.fn_u = { .xts = serpent_xts_dec_8way_avx }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(serpent_xts_dec) }
+		.fn_u = { .xts = serpent_xts_dec }
 	} }
 };
 
@@ -146,8 +144,7 @@
 
 static int cbc_encrypt(struct skcipher_request *req)
 {
-	return glue_cbc_encrypt_req_128bit(GLUE_FUNC_CAST(__serpent_encrypt),
-					   req);
+	return glue_cbc_encrypt_req_128bit(__serpent_encrypt, req);
 }
 
 static int cbc_decrypt(struct skcipher_request *req)
@@ -166,8 +163,8 @@
 	struct serpent_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
 
 	return glue_xts_req_128bit(&serpent_enc_xts, req,
-				   XTS_TWEAK_CAST(__serpent_encrypt),
-				   &ctx->tweak_ctx, &ctx->crypt_ctx, false);
+				   __serpent_encrypt, &ctx->tweak_ctx,
+				   &ctx->crypt_ctx, false);
 }
 
 static int xts_decrypt(struct skcipher_request *req)
@@ -176,8 +173,8 @@
 	struct serpent_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
 
 	return glue_xts_req_128bit(&serpent_dec_xts, req,
-				   XTS_TWEAK_CAST(__serpent_encrypt),
-				   &ctx->tweak_ctx, &ctx->crypt_ctx, true);
+				   __serpent_encrypt, &ctx->tweak_ctx,
+				   &ctx->crypt_ctx, true);
 }
 
 static struct skcipher_alg serpent_algs[] = {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/crypto/serpent_avx_glue.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/crypto/serpent_avx_glue.c
@@ -20,33 +20,35 @@
 #include <asm/crypto/serpent-avx.h>
 
 /* 8-way parallel cipher functions */
-asmlinkage void serpent_ecb_enc_8way_avx(struct serpent_ctx *ctx, u8 *dst,
+asmlinkage void serpent_ecb_enc_8way_avx(const void *ctx, u8 *dst,
 					 const u8 *src);
 EXPORT_SYMBOL_GPL(serpent_ecb_enc_8way_avx);
 
-asmlinkage void serpent_ecb_dec_8way_avx(struct serpent_ctx *ctx, u8 *dst,
+asmlinkage void serpent_ecb_dec_8way_avx(const void *ctx, u8 *dst,
 					 const u8 *src);
 EXPORT_SYMBOL_GPL(serpent_ecb_dec_8way_avx);
 
-asmlinkage void serpent_cbc_dec_8way_avx(struct serpent_ctx *ctx, u8 *dst,
+asmlinkage void serpent_cbc_dec_8way_avx(const void *ctx, u8 *dst,
 					 const u8 *src);
 EXPORT_SYMBOL_GPL(serpent_cbc_dec_8way_avx);
 
-asmlinkage void serpent_ctr_8way_avx(struct serpent_ctx *ctx, u8 *dst,
-				     const u8 *src, le128 *iv);
+asmlinkage void serpent_ctr_8way_avx(const void *ctx, u8 *dst, const u8 *src,
+				     le128 *iv);
 EXPORT_SYMBOL_GPL(serpent_ctr_8way_avx);
 
-asmlinkage void serpent_xts_enc_8way_avx(struct serpent_ctx *ctx, u8 *dst,
+asmlinkage void serpent_xts_enc_8way_avx(const void *ctx, u8 *dst,
 					 const u8 *src, le128 *iv);
 EXPORT_SYMBOL_GPL(serpent_xts_enc_8way_avx);
 
-asmlinkage void serpent_xts_dec_8way_avx(struct serpent_ctx *ctx, u8 *dst,
+asmlinkage void serpent_xts_dec_8way_avx(const void *ctx, u8 *dst,
 					 const u8 *src, le128 *iv);
 EXPORT_SYMBOL_GPL(serpent_xts_dec_8way_avx);
 
-void __serpent_crypt_ctr(void *ctx, u128 *dst, const u128 *src, le128 *iv)
+void __serpent_crypt_ctr(const void *ctx, u8 *d, const u8 *s, le128 *iv)
 {
 	be128 ctrblk;
+	u128 *dst = (u128 *)d;
+	const u128 *src = (const u128 *)s;
 
 	le128_to_be128(&ctrblk, iv);
 	le128_inc(iv);
@@ -56,17 +58,15 @@
 }
 EXPORT_SYMBOL_GPL(__serpent_crypt_ctr);
 
-void serpent_xts_enc(void *ctx, u128 *dst, const u128 *src, le128 *iv)
+void serpent_xts_enc(const void *ctx, u8 *dst, const u8 *src, le128 *iv)
 {
-	glue_xts_crypt_128bit_one(ctx, dst, src, iv,
-				  GLUE_FUNC_CAST(__serpent_encrypt));
+	glue_xts_crypt_128bit_one(ctx, dst, src, iv, __serpent_encrypt);
 }
 EXPORT_SYMBOL_GPL(serpent_xts_enc);
 
-void serpent_xts_dec(void *ctx, u128 *dst, const u128 *src, le128 *iv)
+void serpent_xts_dec(const void *ctx, u8 *dst, const u8 *src, le128 *iv)
 {
-	glue_xts_crypt_128bit_one(ctx, dst, src, iv,
-				  GLUE_FUNC_CAST(__serpent_decrypt));
+	glue_xts_crypt_128bit_one(ctx, dst, src, iv, __serpent_decrypt);
 }
 EXPORT_SYMBOL_GPL(serpent_xts_dec);
 
@@ -102,10 +102,10 @@
 
 	.funcs = { {
 		.num_blocks = SERPENT_PARALLEL_BLOCKS,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(serpent_ecb_enc_8way_avx) }
+		.fn_u = { .ecb = serpent_ecb_enc_8way_avx }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(__serpent_encrypt) }
+		.fn_u = { .ecb = __serpent_encrypt }
 	} }
 };
 
@@ -115,10 +115,10 @@
 
 	.funcs = { {
 		.num_blocks = SERPENT_PARALLEL_BLOCKS,
-		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(serpent_ctr_8way_avx) }
+		.fn_u = { .ctr = serpent_ctr_8way_avx }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(__serpent_crypt_ctr) }
+		.fn_u = { .ctr = __serpent_crypt_ctr }
 	} }
 };
 
@@ -128,10 +128,10 @@
 
 	.funcs = { {
 		.num_blocks = SERPENT_PARALLEL_BLOCKS,
-		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(serpent_xts_enc_8way_avx) }
+		.fn_u = { .xts = serpent_xts_enc_8way_avx }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(serpent_xts_enc) }
+		.fn_u = { .xts = serpent_xts_enc }
 	} }
 };
 
@@ -141,10 +141,10 @@
 
 	.funcs = { {
 		.num_blocks = SERPENT_PARALLEL_BLOCKS,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(serpent_ecb_dec_8way_avx) }
+		.fn_u = { .ecb = serpent_ecb_dec_8way_avx }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(__serpent_decrypt) }
+		.fn_u = { .ecb = __serpent_decrypt }
 	} }
 };
 
@@ -154,10 +154,10 @@
 
 	.funcs = { {
 		.num_blocks = SERPENT_PARALLEL_BLOCKS,
-		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(serpent_cbc_dec_8way_avx) }
+		.fn_u = { .cbc = serpent_cbc_dec_8way_avx }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(__serpent_decrypt) }
+		.fn_u = { .cbc = __serpent_decrypt }
 	} }
 };
 
@@ -167,10 +167,10 @@
 
 	.funcs = { {
 		.num_blocks = SERPENT_PARALLEL_BLOCKS,
-		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(serpent_xts_dec_8way_avx) }
+		.fn_u = { .xts = serpent_xts_dec_8way_avx }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(serpent_xts_dec) }
+		.fn_u = { .xts = serpent_xts_dec }
 	} }
 };
 
@@ -186,8 +186,7 @@
 
 static int cbc_encrypt(struct skcipher_request *req)
 {
-	return glue_cbc_encrypt_req_128bit(GLUE_FUNC_CAST(__serpent_encrypt),
-					   req);
+	return glue_cbc_encrypt_req_128bit(__serpent_encrypt, req);
 }
 
 static int cbc_decrypt(struct skcipher_request *req)
@@ -206,8 +205,8 @@
 	struct serpent_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
 
 	return glue_xts_req_128bit(&serpent_enc_xts, req,
-				   XTS_TWEAK_CAST(__serpent_encrypt),
-				   &ctx->tweak_ctx, &ctx->crypt_ctx, false);
+				   __serpent_encrypt, &ctx->tweak_ctx,
+				   &ctx->crypt_ctx, false);
 }
 
 static int xts_decrypt(struct skcipher_request *req)
@@ -216,8 +215,8 @@
 	struct serpent_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
 
 	return glue_xts_req_128bit(&serpent_dec_xts, req,
-				   XTS_TWEAK_CAST(__serpent_encrypt),
-				   &ctx->tweak_ctx, &ctx->crypt_ctx, true);
+				   __serpent_encrypt, &ctx->tweak_ctx,
+				   &ctx->crypt_ctx, true);
 }
 
 static struct skcipher_alg serpent_algs[] = {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/crypto/serpent_sse2_glue.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/crypto/serpent_sse2_glue.c
@@ -31,9 +31,11 @@
 	return __serpent_setkey(crypto_skcipher_ctx(tfm), key, keylen);
 }
 
-static void serpent_decrypt_cbc_xway(void *ctx, u128 *dst, const u128 *src)
+static void serpent_decrypt_cbc_xway(const void *ctx, u8 *d, const u8 *s)
 {
 	u128 ivs[SERPENT_PARALLEL_BLOCKS - 1];
+	u128 *dst = (u128 *)d;
+	const u128 *src = (const u128 *)s;
 	unsigned int j;
 
 	for (j = 0; j < SERPENT_PARALLEL_BLOCKS - 1; j++)
@@ -45,9 +47,11 @@
 		u128_xor(dst + (j + 1), dst + (j + 1), ivs + j);
 }
 
-static void serpent_crypt_ctr(void *ctx, u128 *dst, const u128 *src, le128 *iv)
+static void serpent_crypt_ctr(const void *ctx, u8 *d, const u8 *s, le128 *iv)
 {
 	be128 ctrblk;
+	u128 *dst = (u128 *)d;
+	const u128 *src = (const u128 *)s;
 
 	le128_to_be128(&ctrblk, iv);
 	le128_inc(iv);
@@ -56,10 +60,12 @@
 	u128_xor(dst, src, (u128 *)&ctrblk);
 }
 
-static void serpent_crypt_ctr_xway(void *ctx, u128 *dst, const u128 *src,
+static void serpent_crypt_ctr_xway(const void *ctx, u8 *d, const u8 *s,
 				   le128 *iv)
 {
 	be128 ctrblks[SERPENT_PARALLEL_BLOCKS];
+	u128 *dst = (u128 *)d;
+	const u128 *src = (const u128 *)s;
 	unsigned int i;
 
 	for (i = 0; i < SERPENT_PARALLEL_BLOCKS; i++) {
@@ -79,10 +85,10 @@
 
 	.funcs = { {
 		.num_blocks = SERPENT_PARALLEL_BLOCKS,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(serpent_enc_blk_xway) }
+		.fn_u = { .ecb = serpent_enc_blk_xway }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(__serpent_encrypt) }
+		.fn_u = { .ecb = __serpent_encrypt }
 	} }
 };
 
@@ -92,10 +98,10 @@
 
 	.funcs = { {
 		.num_blocks = SERPENT_PARALLEL_BLOCKS,
-		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(serpent_crypt_ctr_xway) }
+		.fn_u = { .ctr = serpent_crypt_ctr_xway }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(serpent_crypt_ctr) }
+		.fn_u = { .ctr = serpent_crypt_ctr }
 	} }
 };
 
@@ -105,10 +111,10 @@
 
 	.funcs = { {
 		.num_blocks = SERPENT_PARALLEL_BLOCKS,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(serpent_dec_blk_xway) }
+		.fn_u = { .ecb = serpent_dec_blk_xway }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(__serpent_decrypt) }
+		.fn_u = { .ecb = __serpent_decrypt }
 	} }
 };
 
@@ -118,10 +124,10 @@
 
 	.funcs = { {
 		.num_blocks = SERPENT_PARALLEL_BLOCKS,
-		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(serpent_decrypt_cbc_xway) }
+		.fn_u = { .cbc = serpent_decrypt_cbc_xway }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(__serpent_decrypt) }
+		.fn_u = { .cbc = __serpent_decrypt }
 	} }
 };
 
@@ -137,7 +143,7 @@
 
 static int cbc_encrypt(struct skcipher_request *req)
 {
-	return glue_cbc_encrypt_req_128bit(GLUE_FUNC_CAST(__serpent_encrypt),
+	return glue_cbc_encrypt_req_128bit(__serpent_encrypt,
 					   req);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/crypto/twofish_avx_glue.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/crypto/twofish_avx_glue.c
@@ -22,20 +22,17 @@
 #define TWOFISH_PARALLEL_BLOCKS 8
 
 /* 8-way parallel cipher functions */
-asmlinkage void twofish_ecb_enc_8way(struct twofish_ctx *ctx, u8 *dst,
-				     const u8 *src);
-asmlinkage void twofish_ecb_dec_8way(struct twofish_ctx *ctx, u8 *dst,
-				     const u8 *src);
-
-asmlinkage void twofish_cbc_dec_8way(struct twofish_ctx *ctx, u8 *dst,
-				     const u8 *src);
-asmlinkage void twofish_ctr_8way(struct twofish_ctx *ctx, u8 *dst,
-				 const u8 *src, le128 *iv);
-
-asmlinkage void twofish_xts_enc_8way(struct twofish_ctx *ctx, u8 *dst,
-				     const u8 *src, le128 *iv);
-asmlinkage void twofish_xts_dec_8way(struct twofish_ctx *ctx, u8 *dst,
-				     const u8 *src, le128 *iv);
+asmlinkage void twofish_ecb_enc_8way(const void *ctx, u8 *dst, const u8 *src);
+asmlinkage void twofish_ecb_dec_8way(const void *ctx, u8 *dst, const u8 *src);
+
+asmlinkage void twofish_cbc_dec_8way(const void *ctx, u8 *dst, const u8 *src);
+asmlinkage void twofish_ctr_8way(const void *ctx, u8 *dst, const u8 *src,
+				 le128 *iv);
+
+asmlinkage void twofish_xts_enc_8way(const void *ctx, u8 *dst, const u8 *src,
+				     le128 *iv);
+asmlinkage void twofish_xts_dec_8way(const void *ctx, u8 *dst, const u8 *src,
+				     le128 *iv);
 
 static int twofish_setkey_skcipher(struct crypto_skcipher *tfm,
 				   const u8 *key, unsigned int keylen)
@@ -43,22 +40,19 @@
 	return twofish_setkey(&tfm->base, key, keylen);
 }
 
-static inline void twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst,
-					const u8 *src)
+static inline void twofish_enc_blk_3way(const void *ctx, u8 *dst, const u8 *src)
 {
 	__twofish_enc_blk_3way(ctx, dst, src, false);
 }
 
-static void twofish_xts_enc(void *ctx, u128 *dst, const u128 *src, le128 *iv)
+static void twofish_xts_enc(const void *ctx, u8 *dst, const u8 *src, le128 *iv)
 {
-	glue_xts_crypt_128bit_one(ctx, dst, src, iv,
-				  GLUE_FUNC_CAST(twofish_enc_blk));
+	glue_xts_crypt_128bit_one(ctx, dst, src, iv, twofish_enc_blk);
 }
 
-static void twofish_xts_dec(void *ctx, u128 *dst, const u128 *src, le128 *iv)
+static void twofish_xts_dec(const void *ctx, u8 *dst, const u8 *src, le128 *iv)
 {
-	glue_xts_crypt_128bit_one(ctx, dst, src, iv,
-				  GLUE_FUNC_CAST(twofish_dec_blk));
+	glue_xts_crypt_128bit_one(ctx, dst, src, iv, twofish_dec_blk);
 }
 
 struct twofish_xts_ctx {
@@ -93,13 +87,13 @@
 
 	.funcs = { {
 		.num_blocks = TWOFISH_PARALLEL_BLOCKS,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(twofish_ecb_enc_8way) }
+		.fn_u = { .ecb = twofish_ecb_enc_8way }
 	}, {
 		.num_blocks = 3,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(twofish_enc_blk_3way) }
+		.fn_u = { .ecb = twofish_enc_blk_3way }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(twofish_enc_blk) }
+		.fn_u = { .ecb = twofish_enc_blk }
 	} }
 };
 
@@ -109,13 +103,13 @@
 
 	.funcs = { {
 		.num_blocks = TWOFISH_PARALLEL_BLOCKS,
-		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(twofish_ctr_8way) }
+		.fn_u = { .ctr = twofish_ctr_8way }
 	}, {
 		.num_blocks = 3,
-		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(twofish_enc_blk_ctr_3way) }
+		.fn_u = { .ctr = twofish_enc_blk_ctr_3way }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .ctr = GLUE_CTR_FUNC_CAST(twofish_enc_blk_ctr) }
+		.fn_u = { .ctr = twofish_enc_blk_ctr }
 	} }
 };
 
@@ -125,10 +119,10 @@
 
 	.funcs = { {
 		.num_blocks = TWOFISH_PARALLEL_BLOCKS,
-		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(twofish_xts_enc_8way) }
+		.fn_u = { .xts = twofish_xts_enc_8way }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(twofish_xts_enc) }
+		.fn_u = { .xts = twofish_xts_enc }
 	} }
 };
 
@@ -138,13 +132,13 @@
 
 	.funcs = { {
 		.num_blocks = TWOFISH_PARALLEL_BLOCKS,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(twofish_ecb_dec_8way) }
+		.fn_u = { .ecb = twofish_ecb_dec_8way }
 	}, {
 		.num_blocks = 3,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(twofish_dec_blk_3way) }
+		.fn_u = { .ecb = twofish_dec_blk_3way }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(twofish_dec_blk) }
+		.fn_u = { .ecb = twofish_dec_blk }
 	} }
 };
 
@@ -154,13 +148,13 @@
 
 	.funcs = { {
 		.num_blocks = TWOFISH_PARALLEL_BLOCKS,
-		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(twofish_cbc_dec_8way) }
+		.fn_u = { .cbc = twofish_cbc_dec_8way }
 	}, {
 		.num_blocks = 3,
-		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(twofish_dec_blk_cbc_3way) }
+		.fn_u = { .cbc = twofish_dec_blk_cbc_3way }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(twofish_dec_blk) }
+		.fn_u = { .cbc = twofish_dec_blk }
 	} }
 };
 
@@ -170,10 +164,10 @@
 
 	.funcs = { {
 		.num_blocks = TWOFISH_PARALLEL_BLOCKS,
-		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(twofish_xts_dec_8way) }
+		.fn_u = { .xts = twofish_xts_dec_8way }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .xts = GLUE_XTS_FUNC_CAST(twofish_xts_dec) }
+		.fn_u = { .xts = twofish_xts_dec }
 	} }
 };
 
@@ -189,8 +183,7 @@
 
 static int cbc_encrypt(struct skcipher_request *req)
 {
-	return glue_cbc_encrypt_req_128bit(GLUE_FUNC_CAST(twofish_enc_blk),
-					   req);
+	return glue_cbc_encrypt_req_128bit(twofish_enc_blk, req);
 }
 
 static int cbc_decrypt(struct skcipher_request *req)
@@ -208,8 +201,7 @@
 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
 	struct twofish_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
 
-	return glue_xts_req_128bit(&twofish_enc_xts, req,
-				   XTS_TWEAK_CAST(twofish_enc_blk),
+	return glue_xts_req_128bit(&twofish_enc_xts, req, twofish_enc_blk,
 				   &ctx->tweak_ctx, &ctx->crypt_ctx, false);
 }
 
@@ -218,8 +210,7 @@
 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
 	struct twofish_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
 
-	return glue_xts_req_128bit(&twofish_dec_xts, req,
-				   XTS_TWEAK_CAST(twofish_enc_blk),
+	return glue_xts_req_128bit(&twofish_dec_xts, req, twofish_enc_blk,
 				   &ctx->tweak_ctx, &ctx->crypt_ctx, true);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/crypto/twofish_glue_3way.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/crypto/twofish_glue_3way.c
@@ -25,21 +25,22 @@
 	return twofish_setkey(&tfm->base, key, keylen);
 }
 
-static inline void twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst,
-					const u8 *src)
+static inline void twofish_enc_blk_3way(const void *ctx, u8 *dst, const u8 *src)
 {
 	__twofish_enc_blk_3way(ctx, dst, src, false);
 }
 
-static inline void twofish_enc_blk_xor_3way(struct twofish_ctx *ctx, u8 *dst,
+static inline void twofish_enc_blk_xor_3way(const void *ctx, u8 *dst,
 					    const u8 *src)
 {
 	__twofish_enc_blk_3way(ctx, dst, src, true);
 }
 
-void twofish_dec_blk_cbc_3way(void *ctx, u128 *dst, const u128 *src)
+void twofish_dec_blk_cbc_3way(const void *ctx, u8 *d, const u8 *s)
 {
 	u128 ivs[2];
+	u128 *dst = (u128 *)d;
+	const u128 *src = (const u128 *)s;
 
 	ivs[0] = src[0];
 	ivs[1] = src[1];
@@ -51,9 +52,11 @@
 }
 EXPORT_SYMBOL_GPL(twofish_dec_blk_cbc_3way);
 
-void twofish_enc_blk_ctr(void *ctx, u128 *dst, const u128 *src, le128 *iv)
+void twofish_enc_blk_ctr(const void *ctx, u8 *d, const u8 *s, le128 *iv)
 {
 	be128 ctrblk;
+	u128 *dst = (u128 *)d;
+	const u128 *src = (const u128 *)s;
 
 	if (dst != src)
 		*dst = *src;
@@ -66,10 +69,11 @@
 }
 EXPORT_SYMBOL_GPL(twofish_enc_blk_ctr);
 
-void twofish_enc_blk_ctr_3way(void *ctx, u128 *dst, const u128 *src,
-			      le128 *iv)
+void twofish_enc_blk_ctr_3way(const void *ctx, u8 *d, const u8 *s, le128 *iv)
 {
 	be128 ctrblks[3];
+	u128 *dst = (u128 *)d;
+	const u128 *src = (const u128 *)s;
 
 	if (dst != src) {
 		dst[0] = src[0];
@@ -94,10 +98,10 @@
 
 	.funcs = { {
 		.num_blocks = 3,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(twofish_enc_blk_3way) }
+		.fn_u = { .ecb = twofish_enc_blk_3way }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(twofish_enc_blk) }
+		.fn_u = { .ecb = twofish_enc_blk }
 	} }
 };
 
@@ -107,10 +111,10 @@
 
 	.funcs = { {
 		.num_blocks = 3,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(twofish_enc_blk_ctr_3way) }
+		.fn_u = { .ctr = twofish_enc_blk_ctr_3way }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(twofish_enc_blk_ctr) }
+		.fn_u = { .ctr = twofish_enc_blk_ctr }
 	} }
 };
 
@@ -120,10 +124,10 @@
 
 	.funcs = { {
 		.num_blocks = 3,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(twofish_dec_blk_3way) }
+		.fn_u = { .ecb = twofish_dec_blk_3way }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .ecb = GLUE_FUNC_CAST(twofish_dec_blk) }
+		.fn_u = { .ecb = twofish_dec_blk }
 	} }
 };
 
@@ -133,10 +137,10 @@
 
 	.funcs = { {
 		.num_blocks = 3,
-		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(twofish_dec_blk_cbc_3way) }
+		.fn_u = { .cbc = twofish_dec_blk_cbc_3way }
 	}, {
 		.num_blocks = 1,
-		.fn_u = { .cbc = GLUE_CBC_FUNC_CAST(twofish_dec_blk) }
+		.fn_u = { .cbc = twofish_dec_blk }
 	} }
 };
 
@@ -152,8 +156,7 @@
 
 static int cbc_encrypt(struct skcipher_request *req)
 {
-	return glue_cbc_encrypt_req_128bit(GLUE_FUNC_CAST(twofish_enc_blk),
-					   req);
+	return glue_cbc_encrypt_req_128bit(twofish_enc_blk, req);
 }
 
 static int cbc_decrypt(struct skcipher_request *req)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/entry/calling.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/entry/calling.h
@@ -6,6 +6,8 @@
 #include <asm/percpu.h>
 #include <asm/asm-offsets.h>
 #include <asm/processor-flags.h>
+#include <asm/msr.h>
+#include <asm/nospec-branch.h>
 
 /*
 
@@ -98,73 +100,69 @@
 #define SIZEOF_PTREGS	21*8
 
 .macro PUSH_AND_CLEAR_REGS rdx=%rdx rax=%rax save_ret=0
-	/*
-	 * Push registers and sanitize registers of values that a
-	 * speculation attack might otherwise want to exploit. The
-	 * lower registers are likely clobbered well before they
-	 * could be put to use in a speculative execution gadget.
-	 * Interleave XOR with PUSH for better uop scheduling:
-	 */
 	.if \save_ret
 	pushq	%rsi		/* pt_regs->si */
 	movq	8(%rsp), %rsi	/* temporarily store the return address in %rsi */
 	movq	%rdi, 8(%rsp)	/* pt_regs->di (overwriting original return address) */
+	/* We just clobbered the return address - use the IRET frame for unwinding: */
+	UNWIND_HINT_IRET_REGS offset=3*8
 	.else
 	pushq   %rdi		/* pt_regs->di */
 	pushq   %rsi		/* pt_regs->si */
 	.endif
 	pushq	\rdx		/* pt_regs->dx */
-	xorl	%edx, %edx	/* nospec   dx */
 	pushq   %rcx		/* pt_regs->cx */
-	xorl	%ecx, %ecx	/* nospec   cx */
 	pushq   \rax		/* pt_regs->ax */
 	pushq   %r8		/* pt_regs->r8 */
-	xorl	%r8d, %r8d	/* nospec   r8 */
 	pushq   %r9		/* pt_regs->r9 */
-	xorl	%r9d, %r9d	/* nospec   r9 */
 	pushq   %r10		/* pt_regs->r10 */
-	xorl	%r10d, %r10d	/* nospec   r10 */
 	pushq   %r11		/* pt_regs->r11 */
-	xorl	%r11d, %r11d	/* nospec   r11*/
 	pushq	%rbx		/* pt_regs->rbx */
-	xorl    %ebx, %ebx	/* nospec   rbx*/
 	pushq	%rbp		/* pt_regs->rbp */
-	xorl    %ebp, %ebp	/* nospec   rbp*/
 	pushq	%r12		/* pt_regs->r12 */
-	xorl	%r12d, %r12d	/* nospec   r12*/
 	pushq	%r13		/* pt_regs->r13 */
-	xorl	%r13d, %r13d	/* nospec   r13*/
 	pushq	%r14		/* pt_regs->r14 */
-	xorl	%r14d, %r14d	/* nospec   r14*/
 	pushq	%r15		/* pt_regs->r15 */
-	xorl	%r15d, %r15d	/* nospec   r15*/
 	UNWIND_HINT_REGS
+
 	.if \save_ret
 	pushq	%rsi		/* return address on top of stack */
 	.endif
+
+	/*
+	 * Sanitize registers of values that a speculation attack might
+	 * otherwise want to exploit. The lower registers are likely clobbered
+	 * well before they could be put to use in a speculative execution
+	 * gadget.
+	 */
+	xorl	%edx,  %edx	/* nospec dx  */
+	xorl	%ecx,  %ecx	/* nospec cx  */
+	xorl	%r8d,  %r8d	/* nospec r8  */
+	xorl	%r9d,  %r9d	/* nospec r9  */
+	xorl	%r10d, %r10d	/* nospec r10 */
+	xorl	%r11d, %r11d	/* nospec r11 */
+	xorl	%ebx,  %ebx	/* nospec rbx */
+	xorl	%ebp,  %ebp	/* nospec rbp */
+	xorl	%r12d, %r12d	/* nospec r12 */
+	xorl	%r13d, %r13d	/* nospec r13 */
+	xorl	%r14d, %r14d	/* nospec r14 */
+	xorl	%r15d, %r15d	/* nospec r15 */
+
 .endm
 
-.macro POP_REGS pop_rdi=1 skip_r11rcx=0
+.macro POP_REGS pop_rdi=1
 	popq %r15
 	popq %r14
 	popq %r13
 	popq %r12
 	popq %rbp
 	popq %rbx
-	.if \skip_r11rcx
-	popq %rsi
-	.else
 	popq %r11
-	.endif
 	popq %r10
 	popq %r9
 	popq %r8
 	popq %rax
-	.if \skip_r11rcx
-	popq %rsi
-	.else
 	popq %rcx
-	.endif
 	popq %rdx
 	popq %rsi
 	.if \pop_rdi
@@ -315,6 +313,62 @@
 #endif
 
 /*
+ * IBRS kernel mitigation for Spectre_v2.
+ *
+ * Assumes full context is established (PUSH_REGS, CR3 and GS) and it clobbers
+ * the regs it uses (AX, CX, DX). Must be called before the first RET
+ * instruction (NOTE! UNTRAIN_RET includes a RET instruction)
+ *
+ * The optional argument is used to save/restore the current value,
+ * which is used on the paranoid paths.
+ *
+ * Assumes x86_spec_ctrl_{base,current} to have SPEC_CTRL_IBRS set.
+ */
+.macro IBRS_ENTER save_reg
+	ALTERNATIVE "jmp .Lend_\@", "", X86_FEATURE_KERNEL_IBRS
+	movl	$MSR_IA32_SPEC_CTRL, %ecx
+
+.ifnb \save_reg
+	rdmsr
+	shl	$32, %rdx
+	or	%rdx, %rax
+	mov	%rax, \save_reg
+	test	$SPEC_CTRL_IBRS, %eax
+	jz	.Ldo_wrmsr_\@
+	lfence
+	jmp	.Lend_\@
+.Ldo_wrmsr_\@:
+.endif
+
+	movq	PER_CPU_VAR(x86_spec_ctrl_current), %rdx
+	movl	%edx, %eax
+	shr	$32, %rdx
+	wrmsr
+.Lend_\@:
+.endm
+
+/*
+ * Similar to IBRS_ENTER, requires KERNEL GS,CR3 and clobbers (AX, CX, DX)
+ * regs. Must be called after the last RET.
+ */
+.macro IBRS_EXIT save_reg
+	ALTERNATIVE "jmp .Lend_\@", "", X86_FEATURE_KERNEL_IBRS
+	movl	$MSR_IA32_SPEC_CTRL, %ecx
+
+.ifnb \save_reg
+	mov	\save_reg, %rdx
+.else
+	movq	PER_CPU_VAR(x86_spec_ctrl_current), %rdx
+	andl	$(~SPEC_CTRL_IBRS), %edx
+.endif
+
+	movl	%edx, %eax
+	shr	$32, %rdx
+	wrmsr
+.Lend_\@:
+.endm
+
+/*
  * Mitigate Spectre v1 for conditional swapgs code paths.
  *
  * FENCE_SWAPGS_USER_ENTRY is used in the user entry swapgs code path, to
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/entry/common.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/entry/common.c
@@ -218,6 +218,14 @@
 	user_enter_irqoff();
 
 	mds_user_clear_cpu_buffers();
+	amd_clear_divider();
+
+	/* Avoid unnecessary reads of 'x86_ibpb_exit_to_user' */
+	if (cpu_feature_enabled(X86_FEATURE_IBPB_EXIT_TO_USER) &&
+	    this_cpu_read(x86_ibpb_exit_to_user)) {
+		indirect_branch_prediction_barrier();
+		this_cpu_write(x86_ibpb_exit_to_user, false);
+	}
 }
 
 #define SYSCALL_EXIT_WORK_FLAGS				\
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/entry/entry_32.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/entry/entry_32.S
@@ -172,7 +172,7 @@
 	ALTERNATIVE "jmp .Lend_\@", "", X86_FEATURE_PTI
 	.if \no_user_check == 0
 	/* coming from usermode? */
-	testl	$SEGMENT_RPL_MASK, PT_CS(%esp)
+	testl	$USER_SEGMENT_RPL_MASK, PT_CS(%esp)
 	jz	.Lend_\@
 	.endif
 	/* On user-cr3? */
@@ -205,64 +205,76 @@
 #define CS_FROM_ENTRY_STACK	(1 << 31)
 #define CS_FROM_USER_CR3	(1 << 30)
 #define CS_FROM_KERNEL		(1 << 29)
+#define CS_FROM_ESPFIX		(1 << 28)
 
 .macro FIXUP_FRAME
 	/*
 	 * The high bits of the CS dword (__csh) are used for CS_FROM_*.
 	 * Clear them in case hardware didn't do this for us.
 	 */
-	andl	$0x0000ffff, 3*4(%esp)
+	andl	$0x0000ffff, 4*4(%esp)
 
 #ifdef CONFIG_VM86
-	testl	$X86_EFLAGS_VM, 4*4(%esp)
+	testl	$X86_EFLAGS_VM, 5*4(%esp)
 	jnz	.Lfrom_usermode_no_fixup_\@
 #endif
-	testl	$SEGMENT_RPL_MASK, 3*4(%esp)
+	testl	$USER_SEGMENT_RPL_MASK, 4*4(%esp)
 	jnz	.Lfrom_usermode_no_fixup_\@
 
-	orl	$CS_FROM_KERNEL, 3*4(%esp)
+	orl	$CS_FROM_KERNEL, 4*4(%esp)
 
 	/*
 	 * When we're here from kernel mode; the (exception) stack looks like:
 	 *
-	 *  5*4(%esp) - <previous context>
-	 *  4*4(%esp) - flags
-	 *  3*4(%esp) - cs
-	 *  2*4(%esp) - ip
-	 *  1*4(%esp) - orig_eax
-	 *  0*4(%esp) - gs / function
+	 *  6*4(%esp) - <previous context>
+	 *  5*4(%esp) - flags
+	 *  4*4(%esp) - cs
+	 *  3*4(%esp) - ip
+	 *  2*4(%esp) - orig_eax
+	 *  1*4(%esp) - gs / function
+	 *  0*4(%esp) - fs
 	 *
 	 * Lets build a 5 entry IRET frame after that, such that struct pt_regs
 	 * is complete and in particular regs->sp is correct. This gives us
-	 * the original 5 enties as gap:
+	 * the original 6 enties as gap:
 	 *
-	 * 12*4(%esp) - <previous context>
-	 * 11*4(%esp) - gap / flags
-	 * 10*4(%esp) - gap / cs
-	 *  9*4(%esp) - gap / ip
-	 *  8*4(%esp) - gap / orig_eax
-	 *  7*4(%esp) - gap / gs / function
-	 *  6*4(%esp) - ss
-	 *  5*4(%esp) - sp
-	 *  4*4(%esp) - flags
-	 *  3*4(%esp) - cs
-	 *  2*4(%esp) - ip
-	 *  1*4(%esp) - orig_eax
-	 *  0*4(%esp) - gs / function
+	 * 14*4(%esp) - <previous context>
+	 * 13*4(%esp) - gap / flags
+	 * 12*4(%esp) - gap / cs
+	 * 11*4(%esp) - gap / ip
+	 * 10*4(%esp) - gap / orig_eax
+	 *  9*4(%esp) - gap / gs / function
+	 *  8*4(%esp) - gap / fs
+	 *  7*4(%esp) - ss
+	 *  6*4(%esp) - sp
+	 *  5*4(%esp) - flags
+	 *  4*4(%esp) - cs
+	 *  3*4(%esp) - ip
+	 *  2*4(%esp) - orig_eax
+	 *  1*4(%esp) - gs / function
+	 *  0*4(%esp) - fs
 	 */
 
 	pushl	%ss		# ss
 	pushl	%esp		# sp (points at ss)
-	addl	$6*4, (%esp)	# point sp back at the previous context
-	pushl	6*4(%esp)	# flags
-	pushl	6*4(%esp)	# cs
-	pushl	6*4(%esp)	# ip
-	pushl	6*4(%esp)	# orig_eax
-	pushl	6*4(%esp)	# gs / function
+	addl	$7*4, (%esp)	# point sp back at the previous context
+	pushl	7*4(%esp)	# flags
+	pushl	7*4(%esp)	# cs
+	pushl	7*4(%esp)	# ip
+	pushl	7*4(%esp)	# orig_eax
+	pushl	7*4(%esp)	# gs / function
+	pushl	7*4(%esp)	# fs
 .Lfrom_usermode_no_fixup_\@:
 .endm
 
 .macro IRET_FRAME
+	/*
+	 * We're called with %ds, %es, %fs, and %gs from the interrupted
+	 * frame, so we shouldn't use them.  Also, we may be in ESPFIX
+	 * mode and therefore have a nonzero SS base and an offset ESP,
+	 * so any attempt to access the stack needs to use SS.  (except for
+	 * accesses through %esp, which automatically use SS.)
+	 */
 	testl $CS_FROM_KERNEL, 1*4(%esp)
 	jz .Lfinished_frame_\@
 
@@ -276,31 +288,40 @@
 	movl	5*4(%esp), %eax		# (modified) regs->sp
 
 	movl	4*4(%esp), %ecx		# flags
-	movl	%ecx, -4(%eax)
+	movl	%ecx, %ss:-1*4(%eax)
 
 	movl	3*4(%esp), %ecx		# cs
 	andl	$0x0000ffff, %ecx
-	movl	%ecx, -8(%eax)
+	movl	%ecx, %ss:-2*4(%eax)
 
 	movl	2*4(%esp), %ecx		# ip
-	movl	%ecx, -12(%eax)
+	movl	%ecx, %ss:-3*4(%eax)
 
 	movl	1*4(%esp), %ecx		# eax
-	movl	%ecx, -16(%eax)
+	movl	%ecx, %ss:-4*4(%eax)
 
 	popl	%ecx
-	lea	-16(%eax), %esp
+	lea	-4*4(%eax), %esp
 	popl	%eax
 .Lfinished_frame_\@:
 .endm
 
-.macro SAVE_ALL pt_regs_ax=%eax switch_stacks=0 skip_gs=0
+.macro SAVE_ALL pt_regs_ax=%eax switch_stacks=0 skip_gs=0 unwind_espfix=0
 	cld
 .if \skip_gs == 0
 	PUSH_GS
 .endif
-	FIXUP_FRAME
 	pushl	%fs
+
+	pushl	%eax
+	movl	$(__KERNEL_PERCPU), %eax
+	movl	%eax, %fs
+.if \unwind_espfix > 0
+	UNWIND_ESPFIX_STACK
+.endif
+	popl	%eax
+
+	FIXUP_FRAME
 	pushl	%es
 	pushl	%ds
 	pushl	\pt_regs_ax
@@ -313,8 +334,6 @@
 	movl	$(__USER_DS), %edx
 	movl	%edx, %ds
 	movl	%edx, %es
-	movl	$(__KERNEL_PERCPU), %edx
-	movl	%edx, %fs
 .if \skip_gs == 0
 	SET_KERNEL_GS %edx
 .endif
@@ -324,8 +343,8 @@
 .endif
 .endm
 
-.macro SAVE_ALL_NMI cr3_reg:req
-	SAVE_ALL
+.macro SAVE_ALL_NMI cr3_reg:req unwind_espfix=0
+	SAVE_ALL unwind_espfix=\unwind_espfix
 
 	BUG_IF_WRONG_CR3
 
@@ -357,6 +376,7 @@
 2:	popl	%es
 3:	popl	%fs
 	POP_GS \pop
+	IRET_FRAME
 .pushsection .fixup, "ax"
 4:	movl	$0, (%esp)
 	jmp	1b
@@ -395,7 +415,8 @@
 
 .macro CHECK_AND_APPLY_ESPFIX
 #ifdef CONFIG_X86_ESPFIX32
-#define GDT_ESPFIX_SS PER_CPU_VAR(gdt_page) + (GDT_ENTRY_ESPFIX_SS * 8)
+#define GDT_ESPFIX_OFFSET (GDT_ENTRY_ESPFIX_SS * 8)
+#define GDT_ESPFIX_SS PER_CPU_VAR(gdt_page) + GDT_ESPFIX_OFFSET
 
 	ALTERNATIVE	"jmp .Lend_\@", "", X86_BUG_ESPFIX
 
@@ -729,7 +750,6 @@
 	movl	%ebx, PER_CPU_VAR(stack_canary)+stack_canary_offset
 #endif
 
-#ifdef CONFIG_RETPOLINE
 	/*
 	 * When switching from a shallower to a deeper call stack
 	 * the RSB may either underflow or use entries populated
@@ -738,7 +758,6 @@
 	 * speculative execution to prevent attack.
 	 */
 	FILL_RETURN_BUFFER %ebx, RSB_CLEAR_LOOPS, X86_FEATURE_RSB_CTXSW
-#endif
 
 	/* restore callee-saved registers */
 	popfl
@@ -848,9 +867,10 @@
  * Xen doesn't set %esp to be precisely what the normal SYSENTER
  * entry point expects, so fix it up before using the normal path.
  */
-ENTRY(xen_sysenter_target)
+SYM_CODE_START(xen_sysenter_target)
 	addl	$5*4, %esp			/* remove xen-provided frame */
 	jmp	.Lsysenter_past_esp
+SYM_CODE_END(xen_sysenter_target)
 #endif
 
 /*
@@ -1075,7 +1095,6 @@
 	/* Restore user state */
 	RESTORE_REGS pop=4			# skip orig_eax/error_code
 .Lirq_return:
-	IRET_FRAME
 	/*
 	 * ARCH_HAS_MEMBARRIER_SYNC_CORE rely on IRET core serialization
 	 * when returning from IPI handler and when returning from
@@ -1128,30 +1147,43 @@
  * We can't call C functions using the ESPFIX stack. This code reads
  * the high word of the segment base from the GDT and swiches to the
  * normal stack and adjusts ESP with the matching offset.
+ *
+ * We might be on user CR3 here, so percpu data is not mapped and we can't
+ * access the GDT through the percpu segment.  Instead, use SGDT to find
+ * the cpu_entry_area alias of the GDT.
  */
 #ifdef CONFIG_X86_ESPFIX32
 	/* fixup the stack */
-	mov	GDT_ESPFIX_SS + 4, %al /* bits 16..23 */
-	mov	GDT_ESPFIX_SS + 7, %ah /* bits 24..31 */
+	pushl	%ecx
+	subl	$2*4, %esp
+	sgdt	(%esp)
+	movl	2(%esp), %ecx				/* GDT address */
+	/*
+	 * Careful: ECX is a linear pointer, so we need to force base
+	 * zero.  %cs is the only known-linear segment we have right now.
+	 */
+	mov	%cs:GDT_ESPFIX_OFFSET + 4(%ecx), %al	/* bits 16..23 */
+	mov	%cs:GDT_ESPFIX_OFFSET + 7(%ecx), %ah	/* bits 24..31 */
 	shl	$16, %eax
+	addl	$2*4, %esp
+	popl	%ecx
 	addl	%esp, %eax			/* the adjusted stack pointer */
 	pushl	$__KERNEL_DS
 	pushl	%eax
 	lss	(%esp), %esp			/* switch to the normal stack segment */
 #endif
 .endm
+
 .macro UNWIND_ESPFIX_STACK
+	/* It's safe to clobber %eax, all other regs need to be preserved */
 #ifdef CONFIG_X86_ESPFIX32
 	movl	%ss, %eax
 	/* see if on espfix stack */
 	cmpw	$__ESPFIX_SS, %ax
-	jne	27f
-	movl	$__KERNEL_DS, %eax
-	movl	%eax, %ds
-	movl	%eax, %es
+	jne	.Lno_fixup_\@
 	/* switch to normal stack */
 	FIXUP_ESPFIX_STACK
-27:
+.Lno_fixup_\@:
 #endif
 .endm
 
@@ -1341,11 +1373,6 @@
 
 #ifdef CONFIG_XEN_PV
 ENTRY(xen_hypervisor_callback)
-	pushl	$-1				/* orig_ax = -1 => not a system call */
-	SAVE_ALL
-	ENCODE_FRAME_POINTER
-	TRACE_IRQS_OFF
-
 	/*
 	 * Check to see if we got the event in the critical
 	 * region in xen_iret_direct, after we've reenabled
@@ -1353,16 +1380,17 @@
 	 * iret instruction's behaviour where it delivers a
 	 * pending interrupt when enabling interrupts:
 	 */
-	movl	PT_EIP(%esp), %eax
-	cmpl	$xen_iret_start_crit, %eax
+	cmpl	$xen_iret_start_crit, (%esp)
 	jb	1f
-	cmpl	$xen_iret_end_crit, %eax
+	cmpl	$xen_iret_end_crit, (%esp)
 	jae	1f
-
-	jmp	xen_iret_crit_fixup
-
-ENTRY(xen_do_upcall)
-1:	mov	%esp, %eax
+	call	xen_iret_crit_fixup
+1:
+	pushl	$-1				/* orig_ax = -1 => not a system call */
+	SAVE_ALL
+	ENCODE_FRAME_POINTER
+	TRACE_IRQS_OFF
+	mov	%esp, %eax
 	call	xen_evtchn_do_upcall
 #ifndef CONFIG_PREEMPTION
 	call	xen_maybe_preempt_hcall
@@ -1449,10 +1477,9 @@
 
 common_exception_read_cr2:
 	/* the function address is in %gs's slot on the stack */
-	SAVE_ALL switch_stacks=1 skip_gs=1
+	SAVE_ALL switch_stacks=1 skip_gs=1 unwind_espfix=1
 
 	ENCODE_FRAME_POINTER
-	UNWIND_ESPFIX_STACK
 
 	/* fixup %gs */
 	GS_TO_REG %ecx
@@ -1474,9 +1501,8 @@
 
 common_exception:
 	/* the function address is in %gs's slot on the stack */
-	SAVE_ALL switch_stacks=1 skip_gs=1
+	SAVE_ALL switch_stacks=1 skip_gs=1 unwind_espfix=1
 	ENCODE_FRAME_POINTER
-	UNWIND_ESPFIX_STACK
 
 	/* fixup %gs */
 	GS_TO_REG %ecx
@@ -1515,6 +1541,10 @@
 	ASM_CLAC
 
 #ifdef CONFIG_X86_ESPFIX32
+	/*
+	 * ESPFIX_SS is only ever set on the return to user path
+	 * after we've switched to the entry stack.
+	 */
 	pushl	%eax
 	movl	%ss, %eax
 	cmpw	$__ESPFIX_SS, %ax
@@ -1550,6 +1580,11 @@
 	movl	%ebx, %esp
 
 .Lnmi_return:
+#ifdef CONFIG_X86_ESPFIX32
+	testl	$CS_FROM_ESPFIX, PT_CS(%esp)
+	jnz	.Lnmi_from_espfix
+#endif
+
 	CHECK_AND_APPLY_ESPFIX
 	RESTORE_ALL_NMI cr3_reg=%edi pop=4
 	jmp	.Lirq_return
@@ -1557,23 +1592,42 @@
 #ifdef CONFIG_X86_ESPFIX32
 .Lnmi_espfix_stack:
 	/*
-	 * create the pointer to lss back
+	 * Create the pointer to LSS back
 	 */
 	pushl	%ss
 	pushl	%esp
 	addl	$4, (%esp)
-	/* copy the iret frame of 12 bytes */
-	.rept 3
-	pushl	16(%esp)
-	.endr
-	pushl	%eax
-	SAVE_ALL_NMI cr3_reg=%edi
+
+	/* Copy the (short) IRET frame */
+	pushl	4*4(%esp)	# flags
+	pushl	4*4(%esp)	# cs
+	pushl	4*4(%esp)	# ip
+
+	pushl	%eax		# orig_ax
+
+	SAVE_ALL_NMI cr3_reg=%edi unwind_espfix=1
 	ENCODE_FRAME_POINTER
-	FIXUP_ESPFIX_STACK			# %eax == %esp
+
+	/* clear CS_FROM_KERNEL, set CS_FROM_ESPFIX */
+	xorl	$(CS_FROM_ESPFIX | CS_FROM_KERNEL), PT_CS(%esp)
+
 	xorl	%edx, %edx			# zero error code
-	call	do_nmi
+	movl	%esp, %eax			# pt_regs pointer
+	jmp	.Lnmi_from_sysenter_stack
+
+.Lnmi_from_espfix:
 	RESTORE_ALL_NMI cr3_reg=%edi
-	lss	12+4(%esp), %esp		# back to espfix stack
+	/*
+	 * Because we cleared CS_FROM_KERNEL, IRET_FRAME 'forgot' to
+	 * fix up the gap and long frame:
+	 *
+	 *  3 - original frame	(exception)
+	 *  2 - ESPFIX block	(above)
+	 *  6 - gap		(FIXUP_FRAME)
+	 *  5 - long frame	(FIXUP_FRAME)
+	 *  1 - orig_ax
+	 */
+	lss	(1+5+6)*4(%esp), %esp			# back to espfix stack
 	jmp	.Lirq_return
 #endif
 END(nmi)
@@ -1592,6 +1646,7 @@
 END(int3)
 
 ENTRY(general_protection)
+	ASM_CLAC
 	pushl	$do_general_protection
 	jmp	common_exception
 END(general_protection)
@@ -1604,13 +1659,13 @@
 END(async_page_fault)
 #endif
 
-ENTRY(rewind_stack_do_exit)
+ENTRY(rewind_stack_and_make_dead)
 	/* Prevent any naive code from trying to unwind to our caller. */
 	xorl	%ebp, %ebp
 
 	movl	PER_CPU_VAR(cpu_current_top_of_stack), %esi
 	leal	-TOP_OF_KERNEL_STACK_PADDING-PTREGS_SIZE(%esi), %esp
 
-	call	do_exit
+	call	make_task_dead
 1:	jmp 1b
-END(rewind_stack_do_exit)
+END(rewind_stack_and_make_dead)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/entry/entry_64.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/entry/entry_64.S
@@ -172,6 +172,11 @@
 	/* IRQs are off. */
 	movq	%rax, %rdi
 	movq	%rsp, %rsi
+
+	/* clobbers %rax, make sure it is after saving the syscall nr */
+	IBRS_ENTER
+	CLEAR_BRANCH_HISTORY
+
 	call	do_syscall_64		/* returns with IRQs disabled */
 
 	TRACE_IRQS_IRETQ		/* we're about to change IF */
@@ -248,9 +253,8 @@
 	 * perf profiles. Nothing jumps here.
 	 */
 syscall_return_via_sysret:
-	/* rcx and r11 are already restored (see code above) */
-	UNWIND_HINT_EMPTY
-	POP_REGS pop_rdi=0 skip_r11rcx=1
+	IBRS_EXIT
+	POP_REGS pop_rdi=0
 
 	/*
 	 * Now all regs are restored except RSP and RDI.
@@ -258,6 +262,7 @@
 	 */
 	movq	%rsp, %rdi
 	movq	PER_CPU_VAR(cpu_tss_rw + TSS_sp0), %rsp
+	UNWIND_HINT_EMPTY
 
 	pushq	RSP-RDI(%rdi)	/* RSP */
 	pushq	(%rdi)		/* RDI */
@@ -301,7 +306,6 @@
 	movq	%rbx, PER_CPU_VAR(fixed_percpu_data) + stack_canary_offset
 #endif
 
-#ifdef CONFIG_RETPOLINE
 	/*
 	 * When switching from a shallower to a deeper call stack
 	 * the RSB may either underflow or use entries populated
@@ -310,7 +314,6 @@
 	 * speculative execution to prevent attack.
 	 */
 	FILL_RETURN_BUFFER %r12, RSB_CLEAR_LOOPS, X86_FEATURE_RSB_CTXSW
-#endif
 
 	/* restore callee-saved registers */
 	popq	%r15
@@ -512,7 +515,7 @@
  * +----------------------------------------------------+
  */
 ENTRY(interrupt_entry)
-	UNWIND_HINT_FUNC
+	UNWIND_HINT_IRET_REGS offset=16
 	ASM_CLAC
 	cld
 
@@ -544,9 +547,9 @@
 	pushq	5*8(%rdi)		/* regs->eflags */
 	pushq	4*8(%rdi)		/* regs->cs */
 	pushq	3*8(%rdi)		/* regs->ip */
+	UNWIND_HINT_IRET_REGS
 	pushq	2*8(%rdi)		/* regs->orig_ax */
 	pushq	8(%rdi)			/* return address */
-	UNWIND_HINT_FUNC
 
 	movq	(%rdi), %rdi
 	jmp	2f
@@ -616,12 +619,13 @@
 	jz	retint_kernel
 
 	/* Interrupt came from user space */
-GLOBAL(retint_user)
+.Lretint_user:
 	mov	%rsp,%rdi
 	call	prepare_exit_to_usermode
 	TRACE_IRQS_IRETQ
 
 GLOBAL(swapgs_restore_regs_and_return_to_usermode)
+	IBRS_EXIT
 #ifdef CONFIG_DEBUG_ENTRY
 	/* Assert that pt_regs indicates user mode. */
 	testb	$3, CS(%rsp)
@@ -637,6 +641,7 @@
 	 */
 	movq	%rsp, %rdi
 	movq	PER_CPU_VAR(cpu_tss_rw + TSS_sp0), %rsp
+	UNWIND_HINT_EMPTY
 
 	/* Copy the IRET frame to the trampoline stack. */
 	pushq	6*8(%rdi)	/* SS */
@@ -1247,7 +1252,13 @@
 	 */
 	FENCE_SWAPGS_KERNEL_ENTRY
 
-	ret
+	/*
+	 * Once we have CR3 and %GS setup save and set SPEC_CTRL. Just like
+	 * CR3 above, keep the old value in a callee saved register.
+	 */
+	IBRS_ENTER save_reg=%r15
+
+	RET
 END(paranoid_entry)
 
 /*
@@ -1275,12 +1286,20 @@
 	jmp	.Lparanoid_exit_restore
 .Lparanoid_exit_no_swapgs:
 	TRACE_IRQS_IRETQ_DEBUG
+
+	/*
+	 * Must restore IBRS state before both CR3 and %GS since we need access
+	 * to the per-CPU x86_spec_ctrl_shadow variable.
+	 */
+	IBRS_EXIT save_reg=%r15
+
 	/* Always restore stashed CR3 value (see paranoid_entry) */
 	RESTORE_CR3	scratch_reg=%rbx save_reg=%r14
 .Lparanoid_exit_restore:
 	jmp restore_regs_and_return_to_kernel
 END(paranoid_exit)
 
+
 /*
  * Save all registers in pt_regs, and switch GS if needed.
  */
@@ -1300,6 +1319,7 @@
 	FENCE_SWAPGS_USER_ENTRY
 	/* We have user CR3.  Change to kernel CR3. */
 	SWITCH_TO_KERNEL_CR3 scratch_reg=%rax
+	IBRS_ENTER
 
 .Lerror_entry_from_usermode_after_swapgs:
 	/* Put us onto the real thread stack. */
@@ -1355,6 +1375,7 @@
 	SWAPGS
 	FENCE_SWAPGS_USER_ENTRY
 	SWITCH_TO_KERNEL_CR3 scratch_reg=%rax
+	IBRS_ENTER
 
 	/*
 	 * Pretend that the exception came from user mode: set up pt_regs
@@ -1372,7 +1393,7 @@
 	TRACE_IRQS_OFF
 	testb	$3, CS(%rsp)
 	jz	retint_kernel
-	jmp	retint_user
+	jmp	.Lretint_user
 END(error_exit)
 
 /*
@@ -1460,6 +1481,8 @@
 	PUSH_AND_CLEAR_REGS rdx=(%rdx)
 	ENCODE_FRAME_POINTER
 
+	IBRS_ENTER
+
 	/*
 	 * At this point we no longer need to worry about stack damage
 	 * due to nesting -- we're on the normal thread stack and we're
@@ -1683,6 +1706,9 @@
 	movq	$-1, %rsi
 	call	do_nmi
 
+	/* Always restore stashed SPEC_CTRL value (see paranoid_entry) */
+	IBRS_EXIT save_reg=%r15
+
 	/* Always restore stashed CR3 value (see paranoid_entry) */
 	RESTORE_CR3 scratch_reg=%r15 save_reg=%r14
 
@@ -1732,14 +1758,71 @@
 END(ignore_sysret)
 #endif
 
-ENTRY(rewind_stack_do_exit)
+ENTRY(rewind_stack_and_make_dead)
 	UNWIND_HINT_FUNC
 	/* Prevent any naive code from trying to unwind to our caller. */
 	xorl	%ebp, %ebp
 
 	movq	PER_CPU_VAR(cpu_current_top_of_stack), %rax
 	leaq	-PTREGS_SIZE(%rax), %rsp
-	UNWIND_HINT_FUNC sp_offset=PTREGS_SIZE
+	UNWIND_HINT_REGS
 
-	call	do_exit
-END(rewind_stack_do_exit)
+	call	make_task_dead
+END(rewind_stack_and_make_dead)
+
+/*
+ * This sequence executes branches in order to remove user branch information
+ * from the branch history tracker in the Branch Predictor, therefore removing
+ * user influence on subsequent BTB lookups.
+ *
+ * It should be used on parts prior to Alder Lake. Newer parts should use the
+ * BHI_DIS_S hardware control instead. If a pre-Alder Lake part is being
+ * virtualized on newer hardware the VMM should protect against BHI attacks by
+ * setting BHI_DIS_S for the guests.
+ *
+ * CALLs/RETs are necessary to prevent Loop Stream Detector(LSD) from engaging
+ * and not clearing the branch history. The call tree looks like:
+ *
+ * call 1
+ *    call 2
+ *      call 2
+ *        call 2
+ *          call 2
+ * 	      call 2
+ * 	      ret
+ * 	    ret
+ *        ret
+ *      ret
+ *    ret
+ * ret
+ *
+ * This means that the stack is non-constant and ORC can't unwind it with %rsp
+ * alone.  Therefore we unconditionally set up the frame pointer, which allows
+ * ORC to unwind properly.
+ *
+ * The alignment is for performance and not for safety, and may be safely
+ * refactored in the future if needed.
+ */
+ENTRY(clear_bhb_loop)
+	push	%rbp
+	mov	%rsp, %rbp
+	movl	$5, %ecx
+	call	1f
+	jmp	5f
+	.align 64, 0xcc
+1:	call	2f
+	RET
+	.align 64, 0xcc
+2:	movl	$5, %eax
+3:	jmp	4f
+	nop
+4:	sub	$1, %eax
+	jnz	3b
+	sub	$1, %ecx
+	jnz	1b
+	RET
+5:	lfence
+	pop	%rbp
+	RET
+END(clear_bhb_loop)
+EXPORT_SYMBOL_GPL(clear_bhb_loop)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/entry/entry_64_compat.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/entry/entry_64_compat.S
@@ -4,7 +4,6 @@
  *
  * Copyright 2000-2002 Andi Kleen, SuSE Labs.
  */
-#include "calling.h"
 #include <asm/asm-offsets.h>
 #include <asm/current.h>
 #include <asm/errno.h>
@@ -17,6 +16,8 @@
 #include <linux/linkage.h>
 #include <linux/err.h>
 
+#include "calling.h"
+
 	.section .entry.text, "ax"
 
 /*
@@ -135,6 +136,15 @@
 	 */
 	TRACE_IRQS_OFF
 
+	/*
+	 * CPU bugs mitigations mechanisms can call other functions. They
+	 * should be invoked after making sure TF is cleared because
+	 * single-step is ignored only for instructions inside the
+	 * entry_SYSENTER_compat function.
+	 */
+	IBRS_ENTER
+	CLEAR_BRANCH_HISTORY
+
 	movq	%rsp, %rdi
 	call	do_fast_syscall_32
 	/* XEN PV guests always use IRET path */
@@ -253,6 +263,9 @@
 	 */
 	TRACE_IRQS_OFF
 
+	IBRS_ENTER
+	CLEAR_BRANCH_HISTORY
+
 	movq	%rsp, %rdi
 	call	do_fast_syscall_32
 	/* XEN PV guests always use IRET path */
@@ -267,6 +280,9 @@
 	 */
 	STACKLEAK_ERASE
 	TRACE_IRQS_ON			/* User mode traces as IRQs on. */
+
+	IBRS_EXIT
+
 	movq	RBX(%rsp), %rbx		/* pt_regs->rbx */
 	movq	RBP(%rsp), %rbp		/* pt_regs->rbp */
 	movq	EFLAGS(%rsp), %r11	/* pt_regs->flags (in r11) */
@@ -408,6 +424,8 @@
 	 * gate turned them off.
 	 */
 	TRACE_IRQS_OFF
+	IBRS_ENTER
+	CLEAR_BRANCH_HISTORY
 
 	movq	%rsp, %rdi
 	call	do_int80_syscall_32
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/entry/syscall_32.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/entry/syscall_32.c
@@ -10,13 +10,11 @@
 #ifdef CONFIG_IA32_EMULATION
 /* On X86_64, we use struct pt_regs * to pass parameters to syscalls */
 #define __SYSCALL_I386(nr, sym, qual) extern asmlinkage long sym(const struct pt_regs *);
-
-/* this is a lie, but it does not hurt as sys_ni_syscall just returns -EINVAL */
-extern asmlinkage long sys_ni_syscall(const struct pt_regs *);
-
+#define __sys_ni_syscall __ia32_sys_ni_syscall
 #else /* CONFIG_IA32_EMULATION */
 #define __SYSCALL_I386(nr, sym, qual) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
 extern asmlinkage long sys_ni_syscall(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
+#define __sys_ni_syscall sys_ni_syscall
 #endif /* CONFIG_IA32_EMULATION */
 
 #include <asm/syscalls_32.h>
@@ -29,6 +27,6 @@
 	 * Smells like a compiler bug -- it doesn't work
 	 * when the & below is removed.
 	 */
-	[0 ... __NR_syscall_compat_max] = &sys_ni_syscall,
+	[0 ... __NR_syscall_compat_max] = &__sys_ni_syscall,
 #include <asm/syscalls_32.h>
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/entry/syscall_64.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/entry/syscall_64.c
@@ -4,11 +4,17 @@
 #include <linux/linkage.h>
 #include <linux/sys.h>
 #include <linux/cache.h>
+#include <linux/syscalls.h>
 #include <asm/asm-offsets.h>
 #include <asm/syscall.h>
 
-/* this is a lie, but it does not hurt as sys_ni_syscall just returns -EINVAL */
-extern asmlinkage long sys_ni_syscall(const struct pt_regs *);
+extern asmlinkage long sys_ni_syscall(void);
+
+SYSCALL_DEFINE0(ni_syscall)
+{
+	return sys_ni_syscall();
+}
+
 #define __SYSCALL_64(nr, sym, qual) extern asmlinkage long sym(const struct pt_regs *);
 #define __SYSCALL_X32(nr, sym, qual) __SYSCALL_64(nr, sym, qual)
 #include <asm/syscalls_64.h>
@@ -23,7 +29,7 @@
 	 * Smells like a compiler bug -- it doesn't work
 	 * when the & below is removed.
 	 */
-	[0 ... __NR_syscall_max] = &sys_ni_syscall,
+	[0 ... __NR_syscall_max] = &__x64_sys_ni_syscall,
 #include <asm/syscalls_64.h>
 };
 
@@ -40,7 +46,7 @@
 	 * Smells like a compiler bug -- it doesn't work
 	 * when the & below is removed.
 	 */
-	[0 ... __NR_syscall_x32_max] = &sys_ni_syscall,
+	[0 ... __NR_syscall_x32_max] = &__x64_sys_ni_syscall,
 #include <asm/syscalls_64.h>
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/entry/syscalls/syscall_32.tbl
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/entry/syscalls/syscall_32.tbl
@@ -124,13 +124,13 @@
 110	i386	iopl			sys_iopl			__ia32_sys_iopl
 111	i386	vhangup			sys_vhangup			__ia32_sys_vhangup
 112	i386	idle
-113	i386	vm86old			sys_vm86old			sys_ni_syscall
+113	i386	vm86old			sys_vm86old			__ia32_sys_ni_syscall
 114	i386	wait4			sys_wait4			__ia32_compat_sys_wait4
 115	i386	swapoff			sys_swapoff			__ia32_sys_swapoff
 116	i386	sysinfo			sys_sysinfo			__ia32_compat_sys_sysinfo
 117	i386	ipc			sys_ipc				__ia32_compat_sys_ipc
 118	i386	fsync			sys_fsync			__ia32_sys_fsync
-119	i386	sigreturn		sys_sigreturn			sys32_sigreturn
+119	i386	sigreturn		sys_sigreturn			__ia32_compat_sys_sigreturn
 120	i386	clone			sys_clone			__ia32_compat_sys_x86_clone
 121	i386	setdomainname		sys_setdomainname		__ia32_sys_setdomainname
 122	i386	uname			sys_newuname			__ia32_sys_newuname
@@ -177,14 +177,14 @@
 163	i386	mremap			sys_mremap			__ia32_sys_mremap
 164	i386	setresuid		sys_setresuid16			__ia32_sys_setresuid16
 165	i386	getresuid		sys_getresuid16			__ia32_sys_getresuid16
-166	i386	vm86			sys_vm86			sys_ni_syscall
+166	i386	vm86			sys_vm86			__ia32_sys_ni_syscall
 167	i386	query_module
 168	i386	poll			sys_poll			__ia32_sys_poll
 169	i386	nfsservctl
 170	i386	setresgid		sys_setresgid16			__ia32_sys_setresgid16
 171	i386	getresgid		sys_getresgid16			__ia32_sys_getresgid16
 172	i386	prctl			sys_prctl			__ia32_sys_prctl
-173	i386	rt_sigreturn		sys_rt_sigreturn		sys32_rt_sigreturn
+173	i386	rt_sigreturn		sys_rt_sigreturn		__ia32_compat_sys_rt_sigreturn
 174	i386	rt_sigaction		sys_rt_sigaction		__ia32_compat_sys_rt_sigaction
 175	i386	rt_sigprocmask		sys_rt_sigprocmask		__ia32_compat_sys_rt_sigprocmask
 176	i386	rt_sigpending		sys_rt_sigpending		__ia32_compat_sys_rt_sigpending
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/entry/vdso/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/entry/vdso/Makefile
@@ -178,7 +178,7 @@
 		 sh $(srctree)/$(src)/checkundef.sh '$(NM)' '$@'
 
 VDSO_LDFLAGS = -shared --hash-style=both --build-id \
-	$(call ld-option, --eh-frame-hdr) -Bsymbolic
+	$(call ld-option, --eh-frame-hdr) -Bsymbolic -z noexecstack
 GCOV_PROFILE := n
 
 quiet_cmd_vdso_and_check = VDSO    $@
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/entry/vdso/vdso32-setup.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/entry/vdso/vdso32-setup.c
@@ -11,6 +11,7 @@
 #include <linux/smp.h>
 #include <linux/kernel.h>
 #include <linux/mm_types.h>
+#include <linux/elf.h>
 
 #include <asm/processor.h>
 #include <asm/vdso.h>
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/entry/vdso/vma.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/entry/vdso/vma.c
@@ -222,8 +222,8 @@
 
 	/* Round the lowest possible end address up to a PMD boundary. */
 	end = (start + len + PMD_SIZE - 1) & PMD_MASK;
-	if (end >= TASK_SIZE_MAX)
-		end = TASK_SIZE_MAX;
+	if (end >= DEFAULT_MAP_WINDOW)
+		end = DEFAULT_MAP_WINDOW;
 	end -= len;
 
 	if (end > start) {
@@ -323,7 +323,7 @@
 static __init int vdso_setup(char *s)
 {
 	vdso64_enabled = simple_strtoul(s, NULL, 0);
-	return 0;
+	return 1;
 }
 __setup("vdso=", vdso_setup);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/entry/vsyscall/vsyscall_64.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/entry/vsyscall/vsyscall_64.c
@@ -98,11 +98,6 @@
 
 static bool write_ok_or_segv(unsigned long ptr, size_t size)
 {
-	/*
-	 * XXX: if access_ok, get_user, and put_user handled
-	 * sig_on_uaccess_err, this could go away.
-	 */
-
 	if (!access_ok((void __user *)ptr, size)) {
 		struct thread_struct *thread = &current->thread;
 
@@ -120,10 +115,8 @@
 bool emulate_vsyscall(unsigned long error_code,
 		      struct pt_regs *regs, unsigned long address)
 {
-	struct task_struct *tsk;
 	unsigned long caller;
 	int vsyscall_nr, syscall_nr, tmp;
-	int prev_sig_on_uaccess_err;
 	long ret;
 	unsigned long orig_dx;
 
@@ -172,8 +165,6 @@
 		goto sigsegv;
 	}
 
-	tsk = current;
-
 	/*
 	 * Check for access_ok violations and find the syscall nr.
 	 *
@@ -233,12 +224,8 @@
 		goto do_ret;  /* skip requested */
 
 	/*
-	 * With a real vsyscall, page faults cause SIGSEGV.  We want to
-	 * preserve that behavior to make writing exploits harder.
+	 * With a real vsyscall, page faults cause SIGSEGV.
 	 */
-	prev_sig_on_uaccess_err = current->thread.sig_on_uaccess_err;
-	current->thread.sig_on_uaccess_err = 1;
-
 	ret = -EFAULT;
 	switch (vsyscall_nr) {
 	case 0:
@@ -261,23 +248,12 @@
 		break;
 	}
 
-	current->thread.sig_on_uaccess_err = prev_sig_on_uaccess_err;
-
 check_fault:
 	if (ret == -EFAULT) {
 		/* Bad news -- userspace fed a bad pointer to a vsyscall. */
 		warn_bad_vsyscall(KERN_INFO, regs,
 				  "vsyscall fault (exploit attempt?)");
-
-		/*
-		 * If we failed to generate a signal for any reason,
-		 * generate one here.  (This should be impossible.)
-		 */
-		if (WARN_ON_ONCE(!sigismember(&tsk->pending.signal, SIGBUS) &&
-				 !sigismember(&tsk->pending.signal, SIGSEGV)))
-			goto sigsegv;
-
-		return true;  /* Don't emulate the ret. */
+		goto sigsegv;
 	}
 
 	regs->ax = ret;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/events/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/events/Kconfig
@@ -10,11 +10,11 @@
 	available on NehalemEX and more modern processors.
 
 config PERF_EVENTS_INTEL_RAPL
-	tristate "Intel rapl performance events"
-	depends on PERF_EVENTS && CPU_SUP_INTEL && PCI
+	tristate "Intel/AMD rapl performance events"
+	depends on PERF_EVENTS && (CPU_SUP_INTEL || CPU_SUP_AMD) && PCI
 	default y
 	---help---
-	Include support for Intel rapl performance events for power
+	Include support for Intel and AMD rapl performance events for power
 	monitoring on modern processors.
 
 config PERF_EVENTS_INTEL_CSTATE
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/events/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/events/Makefile
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-y					+= core.o probe.o
+obj-$(CONFIG_PERF_EVENTS_INTEL_RAPL)	+= rapl.o
 obj-y					+= amd/
 obj-$(CONFIG_X86_LOCAL_APIC)            += msr.o
 obj-$(CONFIG_CPU_SUP_INTEL)		+= intel/
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/events/amd/core.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/events/amd/core.c
@@ -14,6 +14,10 @@
 static DEFINE_PER_CPU(unsigned long, perf_nmi_tstamp);
 static unsigned long perf_nmi_window;
 
+/* AMD Event 0xFFF: Merge.  Used with Large Increment per Cycle events */
+#define AMD_MERGE_EVENT ((0xFULL << 32) | 0xFFULL)
+#define AMD_MERGE_EVENT_ENABLE (AMD_MERGE_EVENT | ARCH_PERFMON_EVENTSEL_ENABLE)
+
 static __initconst const u64 amd_hw_cache_event_ids
 				[PERF_COUNT_HW_CACHE_MAX]
 				[PERF_COUNT_HW_CACHE_OP_MAX]
@@ -246,6 +250,7 @@
 	[PERF_COUNT_HW_CPU_CYCLES]		= 0x0076,
 	[PERF_COUNT_HW_INSTRUCTIONS]		= 0x00c0,
 	[PERF_COUNT_HW_CACHE_REFERENCES]	= 0xff60,
+	[PERF_COUNT_HW_CACHE_MISSES]		= 0x0964,
 	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS]	= 0x00c2,
 	[PERF_COUNT_HW_BRANCH_MISSES]		= 0x00c3,
 	[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND]	= 0x0287,
@@ -301,6 +306,25 @@
 	return offset;
 }
 
+/*
+ * AMD64 events are detected based on their event codes.
+ */
+static inline unsigned int amd_get_event_code(struct hw_perf_event *hwc)
+{
+	return ((hwc->config >> 24) & 0x0f00) | (hwc->config & 0x00ff);
+}
+
+static inline bool amd_is_pair_event_code(struct hw_perf_event *hwc)
+{
+	if (!(x86_pmu.flags & PMU_FL_PAIR))
+		return false;
+
+	switch (amd_get_event_code(hwc)) {
+	case 0x003:	return true;	/* Retired SSE/AVX FLOPs */
+	default:	return false;
+	}
+}
+
 static int amd_core_hw_config(struct perf_event *event)
 {
 	if (event->attr.exclude_host && event->attr.exclude_guest)
@@ -316,15 +340,10 @@
 	else if (event->attr.exclude_guest)
 		event->hw.config |= AMD64_EVENTSEL_HOSTONLY;
 
-	return 0;
-}
+	if ((x86_pmu.flags & PMU_FL_PAIR) && amd_is_pair_event_code(&event->hw))
+		event->hw.flags |= PERF_X86_EVENT_PAIR;
 
-/*
- * AMD64 events are detected based on their event codes.
- */
-static inline unsigned int amd_get_event_code(struct hw_perf_event *hwc)
-{
-	return ((hwc->config >> 24) & 0x0f00) | (hwc->config & 0x00ff);
+	return 0;
 }
 
 static inline int amd_is_nb_event(struct hw_perf_event *hwc)
@@ -864,6 +883,29 @@
 	}
 }
 
+static struct event_constraint pair_constraint;
+
+static struct event_constraint *
+amd_get_event_constraints_f17h(struct cpu_hw_events *cpuc, int idx,
+			       struct perf_event *event)
+{
+	struct hw_perf_event *hwc = &event->hw;
+
+	if (amd_is_pair_event_code(hwc))
+		return &pair_constraint;
+
+	return &unconstrained;
+}
+
+static void amd_put_event_constraints_f17h(struct cpu_hw_events *cpuc,
+					   struct perf_event *event)
+{
+	struct hw_perf_event *hwc = &event->hw;
+
+	if (is_counter_pair(hwc))
+		--cpuc->n_pair;
+}
+
 static ssize_t amd_event_sysfs_show(char *page, u64 config)
 {
 	u64 event = (config & ARCH_PERFMON_EVENTSEL_EVENT) |
@@ -907,33 +949,15 @@
 
 static int __init amd_core_pmu_init(void)
 {
+	u64 even_ctr_mask = 0ULL;
+	int i;
+
 	if (!boot_cpu_has(X86_FEATURE_PERFCTR_CORE))
 		return 0;
 
-	/* Avoid calulating the value each time in the NMI handler */
+	/* Avoid calculating the value each time in the NMI handler */
 	perf_nmi_window = msecs_to_jiffies(100);
 
-	switch (boot_cpu_data.x86) {
-	case 0x15:
-		pr_cont("Fam15h ");
-		x86_pmu.get_event_constraints = amd_get_event_constraints_f15h;
-		break;
-	case 0x17:
-		pr_cont("Fam17h ");
-		/*
-		 * In family 17h, there are no event constraints in the PMC hardware.
-		 * We fallback to using default amd_get_event_constraints.
-		 */
-		break;
-	case 0x18:
-		pr_cont("Fam18h ");
-		/* Using default amd_get_event_constraints. */
-		break;
-	default:
-		pr_err("core perfctr but no constraints; unknown hardware!\n");
-		return -ENODEV;
-	}
-
 	/*
 	 * If core performance counter extensions exists, we must use
 	 * MSR_F15H_PERF_CTL/MSR_F15H_PERF_CTR msrs. See also
@@ -948,6 +972,32 @@
 	 */
 	x86_pmu.amd_nb_constraints = 0;
 
+	if (boot_cpu_data.x86 == 0x15) {
+		pr_cont("Fam15h ");
+		x86_pmu.get_event_constraints = amd_get_event_constraints_f15h;
+	}
+	if (boot_cpu_data.x86 >= 0x17) {
+		pr_cont("Fam17h+ ");
+		/*
+		 * Family 17h and compatibles have constraints for Large
+		 * Increment per Cycle events: they may only be assigned an
+		 * even numbered counter that has a consecutive adjacent odd
+		 * numbered counter following it.
+		 */
+		for (i = 0; i < x86_pmu.num_counters - 1; i += 2)
+			even_ctr_mask |= BIT_ULL(i);
+
+		pair_constraint = (struct event_constraint)
+				    __EVENT_CONSTRAINT(0, even_ctr_mask, 0,
+				    x86_pmu.num_counters / 2, 0,
+				    PERF_X86_EVENT_PAIR);
+
+		x86_pmu.get_event_constraints = amd_get_event_constraints_f17h;
+		x86_pmu.put_event_constraints = amd_put_event_constraints_f17h;
+		x86_pmu.perf_ctr_pair_en = AMD_MERGE_EVENT_ENABLE;
+		x86_pmu.flags |= PMU_FL_PAIR;
+	}
+
 	pr_cont("core perfctr, ");
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/events/amd/ibs.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/events/amd/ibs.c
@@ -89,6 +89,8 @@
 	u64				max_period;
 	unsigned long			offset_mask[1];
 	int				offset_max;
+	unsigned int			fetch_count_reset_broken : 1;
+	unsigned int			fetch_ignore_if_zero_rip : 1;
 	struct cpu_perf_ibs __percpu	*pcpu;
 
 	struct attribute		**format_attrs;
@@ -310,6 +312,16 @@
 	hwc->config_base = perf_ibs->msr;
 	hwc->config = config;
 
+	/*
+	 * rip recorded by IbsOpRip will not be consistent with rsp and rbp
+	 * recorded as part of interrupt regs. Thus we need to use rip from
+	 * interrupt regs while unwinding call stack. Setting _EARLY flag
+	 * makes sure we unwind call-stack before perf sample rip is set to
+	 * IbsOpRip.
+	 */
+	if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN)
+		event->attr.sample_type |= __PERF_SAMPLE_CALLCHAIN_EARLY;
+
 	return 0;
 }
 
@@ -334,11 +346,15 @@
 {
 	u64 count = 0;
 
+	/*
+	 * If the internal 27-bit counter rolled over, the count is MaxCnt
+	 * and the lower 7 bits of CurCnt are randomized.
+	 * Otherwise CurCnt has the full 27-bit current counter value.
+	 */
 	if (config & IBS_OP_VAL)
-		count += (config & IBS_OP_MAX_CNT) << 4; /* cnt rolled over */
-
-	if (ibs_caps & IBS_CAPS_RDWROPCNT)
-		count += (config & IBS_OP_CUR_CNT) >> 32;
+		count = (config & IBS_OP_MAX_CNT) << 4;
+	else if (ibs_caps & IBS_CAPS_RDWROPCNT)
+		count = (config & IBS_OP_CUR_CNT) >> 32;
 
 	return count;
 }
@@ -363,7 +379,12 @@
 static inline void perf_ibs_enable_event(struct perf_ibs *perf_ibs,
 					 struct hw_perf_event *hwc, u64 config)
 {
-	wrmsrl(hwc->config_base, hwc->config | config | perf_ibs->enable_mask);
+	u64 tmp = hwc->config | config;
+
+	if (perf_ibs->fetch_count_reset_broken)
+		wrmsrl(hwc->config_base, tmp & ~perf_ibs->enable_mask);
+
+	wrmsrl(hwc->config_base, tmp | perf_ibs->enable_mask);
 }
 
 /*
@@ -551,6 +572,7 @@
 		.start		= perf_ibs_start,
 		.stop		= perf_ibs_stop,
 		.read		= perf_ibs_read,
+		.capabilities	= PERF_PMU_CAP_NO_EXCLUDE,
 	},
 	.msr			= MSR_AMD64_IBSOPCTL,
 	.config_mask		= IBS_OP_CONFIG_MASK,
@@ -626,18 +648,24 @@
 				       perf_ibs->offset_max,
 				       offset + 1);
 	} while (offset < offset_max);
+	/*
+	 * Read IbsBrTarget, IbsOpData4, and IbsExtdCtl separately
+	 * depending on their availability.
+	 * Can't add to offset_max as they are staggered
+	 */
 	if (event->attr.sample_type & PERF_SAMPLE_RAW) {
-		/*
-		 * Read IbsBrTarget and IbsOpData4 separately
-		 * depending on their availability.
-		 * Can't add to offset_max as they are staggered
-		 */
-		if (ibs_caps & IBS_CAPS_BRNTRGT) {
-			rdmsrl(MSR_AMD64_IBSBRTARGET, *buf++);
-			size++;
+		if (perf_ibs == &perf_ibs_op) {
+			if (ibs_caps & IBS_CAPS_BRNTRGT) {
+				rdmsrl(MSR_AMD64_IBSBRTARGET, *buf++);
+				size++;
+			}
+			if (ibs_caps & IBS_CAPS_OPDATA4) {
+				rdmsrl(MSR_AMD64_IBSOPDATA4, *buf++);
+				size++;
+			}
 		}
-		if (ibs_caps & IBS_CAPS_OPDATA4) {
-			rdmsrl(MSR_AMD64_IBSOPDATA4, *buf++);
+		if (perf_ibs == &perf_ibs_fetch && (ibs_caps & IBS_CAPS_FETCHCTLEXTD)) {
+			rdmsrl(MSR_AMD64_ICIBSEXTDCTL, *buf++);
 			size++;
 		}
 	}
@@ -647,6 +675,10 @@
 	if (check_rip && (ibs_data.regs[2] & IBS_RIP_INVALID)) {
 		regs.flags &= ~PERF_EFLAGS_EXACT;
 	} else {
+		/* Workaround for erratum #1197 */
+		if (perf_ibs->fetch_ignore_if_zero_rip && !(ibs_data.regs[1]))
+			goto out;
+
 		set_linear_ip(&regs, ibs_data.regs[1]);
 		regs.flags |= PERF_EFLAGS_EXACT;
 	}
@@ -661,6 +693,14 @@
 		data.raw = &raw;
 	}
 
+	/*
+	 * rip recorded by IbsOpRip will not be consistent with rsp and rbp
+	 * recorded as part of interrupt regs. Thus we need to use rip from
+	 * interrupt regs while unwinding call stack.
+	 */
+	if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN)
+		data.callchain = perf_callchain(event, iregs);
+
 	throttle = perf_event_overflow(event, &data, &regs);
 out:
 	if (throttle) {
@@ -733,6 +773,16 @@
 {
 	struct attribute **attr = ibs_op_format_attrs;
 
+	/*
+	 * Some chips fail to reset the fetch count when it is written; instead
+	 * they need a 0-1 transition of IbsFetchEn.
+	 */
+	if (boot_cpu_data.x86 >= 0x16 && boot_cpu_data.x86 <= 0x18)
+		perf_ibs_fetch.fetch_count_reset_broken = 1;
+
+	if (boot_cpu_data.x86 == 0x19 && boot_cpu_data.x86_model < 0x10)
+		perf_ibs_fetch.fetch_ignore_if_zero_rip = 1;
+
 	perf_ibs_pmu_init(&perf_ibs_fetch, "ibs_fetch");
 
 	if (ibs_caps & IBS_CAPS_OPCNT) {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/events/amd/iommu.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/events/amd/iommu.c
@@ -18,8 +18,6 @@
 #include "../perf_event.h"
 #include "iommu.h"
 
-#define COUNTER_SHIFT		16
-
 /* iommu pmu conf masks */
 #define GET_CSOURCE(x)     ((x)->conf & 0xFFULL)
 #define GET_DEVID(x)       (((x)->conf >> 8)  & 0xFFFFULL)
@@ -81,12 +79,12 @@
 };
 
 struct amd_iommu_event_desc {
-	struct kobj_attribute attr;
+	struct device_attribute attr;
 	const char *event;
 };
 
-static ssize_t _iommu_event_show(struct kobject *kobj,
-				struct kobj_attribute *attr, char *buf)
+static ssize_t _iommu_event_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
 {
 	struct amd_iommu_event_desc *event =
 		container_of(attr, struct amd_iommu_event_desc, attr);
@@ -285,22 +283,31 @@
 	WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
 	hwc->state = 0;
 
+	/*
+	 * To account for power-gating, which prevents write to
+	 * the counter, we need to enable the counter
+	 * before setting up counter register.
+	 */
+	perf_iommu_enable_event(event);
+
 	if (flags & PERF_EF_RELOAD) {
-		u64 prev_raw_count = local64_read(&hwc->prev_count);
+		u64 count = 0;
 		struct amd_iommu *iommu = perf_event_2_iommu(event);
 
+		/*
+		 * Since the IOMMU PMU only support counting mode,
+		 * the counter always start with value zero.
+		 */
 		amd_iommu_pc_set_reg(iommu, hwc->iommu_bank, hwc->iommu_cntr,
-				     IOMMU_PC_COUNTER_REG, &prev_raw_count);
+				     IOMMU_PC_COUNTER_REG, &count);
 	}
 
-	perf_iommu_enable_event(event);
 	perf_event_update_userpage(event);
-
 }
 
 static void perf_iommu_read(struct perf_event *event)
 {
-	u64 count, prev, delta;
+	u64 count;
 	struct hw_perf_event *hwc = &event->hw;
 	struct amd_iommu *iommu = perf_event_2_iommu(event);
 
@@ -311,14 +318,11 @@
 	/* IOMMU pc counter register is only 48 bits */
 	count &= GENMASK_ULL(47, 0);
 
-	prev = local64_read(&hwc->prev_count);
-	if (local64_cmpxchg(&hwc->prev_count, prev, count) != prev)
-		return;
-
-	/* Handle 48-bit counter overflow */
-	delta = (count << COUNTER_SHIFT) - (prev << COUNTER_SHIFT);
-	delta >>= COUNTER_SHIFT;
-	local64_add(delta, &event->count);
+	/*
+	 * Since the counter always start with value zero,
+	 * simply just accumulate the count for the event.
+	 */
+	local64_add(count, &event->count);
 }
 
 static void perf_iommu_stop(struct perf_event *event, int flags)
@@ -328,15 +332,16 @@
 	if (hwc->state & PERF_HES_UPTODATE)
 		return;
 
+	/*
+	 * To account for power-gating, in which reading the counter would
+	 * return zero, we need to read the register before disabling.
+	 */
+	perf_iommu_read(event);
+	hwc->state |= PERF_HES_UPTODATE;
+
 	perf_iommu_disable_event(event);
 	WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
 	hwc->state |= PERF_HES_STOPPED;
-
-	if (hwc->state & PERF_HES_UPTODATE)
-		return;
-
-	perf_iommu_read(event);
-	hwc->state |= PERF_HES_UPTODATE;
 }
 
 static int perf_iommu_add(struct perf_event *event, int flags)
@@ -379,7 +384,7 @@
 	while (amd_iommu_v2_event_descs[i].attr.attr.name)
 		i++;
 
-	attrs = kcalloc(i + 1, sizeof(struct attribute **), GFP_KERNEL);
+	attrs = kcalloc(i + 1, sizeof(*attrs), GFP_KERNEL);
 	if (!attrs)
 		return -ENOMEM;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/events/amd/power.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/events/amd/power.c
@@ -217,6 +217,7 @@
 	.stop		= pmu_event_stop,
 	.read		= pmu_event_read,
 	.capabilities	= PERF_PMU_CAP_NO_EXCLUDE,
+	.module		= THIS_MODULE,
 };
 
 static int power_cpu_exit(unsigned int cpu)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/events/amd/uncore.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/events/amd/uncore.c
@@ -190,15 +190,12 @@
 
 	/*
 	 * NB and Last level cache counters (MSRs) are shared across all cores
-	 * that share the same NB / Last level cache. Interrupts can be directed
-	 * to a single target core, however, event counts generated by processes
-	 * running on other cores cannot be masked out. So we do not support
-	 * sampling and per-thread events.
+	 * that share the same NB / Last level cache.  On family 16h and below,
+	 * Interrupts can be directed to a single target core, however, event
+	 * counts generated by processes running on other cores cannot be masked
+	 * out. So we do not support sampling and per-thread events via
+	 * CAP_NO_INTERRUPT, and we do not enable counter overflow interrupts:
 	 */
-	if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK)
-		return -EINVAL;
-
-	/* and we do not enable counter overflow interrupts */
 	hwc->config = event->attr.config & AMD64_RAW_EVENT_MASK_NB;
 	hwc->idx = -1;
 
@@ -306,7 +303,7 @@
 	.start		= amd_uncore_start,
 	.stop		= amd_uncore_stop,
 	.read		= amd_uncore_read,
-	.capabilities	= PERF_PMU_CAP_NO_EXCLUDE,
+	.capabilities	= PERF_PMU_CAP_NO_EXCLUDE | PERF_PMU_CAP_NO_INTERRUPT,
 };
 
 static struct pmu amd_llc_pmu = {
@@ -317,7 +314,7 @@
 	.start		= amd_uncore_start,
 	.stop		= amd_uncore_stop,
 	.read		= amd_uncore_read,
-	.capabilities	= PERF_PMU_CAP_NO_EXCLUDE,
+	.capabilities	= PERF_PMU_CAP_NO_EXCLUDE | PERF_PMU_CAP_NO_INTERRUPT,
 };
 
 static struct amd_uncore *amd_uncore_alloc(unsigned int cpu)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/events/core.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/events/core.c
@@ -375,7 +375,7 @@
 	 * LBR and BTS are still mutually exclusive.
 	 */
 	if (x86_pmu.lbr_pt_coexist && what == x86_lbr_exclusive_pt)
-		return 0;
+		goto out;
 
 	if (!atomic_inc_not_zero(&x86_pmu.lbr_exclusive[what])) {
 		mutex_lock(&pmc_reserve_mutex);
@@ -387,6 +387,7 @@
 		mutex_unlock(&pmc_reserve_mutex);
 	}
 
+out:
 	atomic_inc(&active_events);
 	return 0;
 
@@ -397,11 +398,15 @@
 
 void x86_del_exclusive(unsigned int what)
 {
+	atomic_dec(&active_events);
+
+	/*
+	 * See the comment in x86_add_exclusive().
+	 */
 	if (x86_pmu.lbr_pt_coexist && what == x86_lbr_exclusive_pt)
 		return;
 
 	atomic_dec(&x86_pmu.lbr_exclusive[what]);
-	atomic_dec(&active_events);
 }
 
 int x86_setup_perfctr(struct perf_event *event)
@@ -612,6 +617,7 @@
 	int idx;
 
 	for (idx = 0; idx < x86_pmu.num_counters; idx++) {
+		struct hw_perf_event *hwc = &cpuc->events[idx]->hw;
 		u64 val;
 
 		if (!test_bit(idx, cpuc->active_mask))
@@ -621,6 +627,8 @@
 			continue;
 		val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
 		wrmsrl(x86_pmu_config_addr(idx), val);
+		if (is_counter_pair(hwc))
+			wrmsrl(x86_pmu_config_addr(idx + 1), 0);
 	}
 }
 
@@ -693,7 +701,7 @@
 	int	counter;	/* counter index */
 	int	unassigned;	/* number of events to be assigned left */
 	int	nr_gp;		/* number of GP counters used */
-	unsigned long used[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
+	u64	used;
 };
 
 /* Total max is X86_PMC_IDX_MAX, but we are O(n!) limited */
@@ -750,8 +758,12 @@
 	sched->saved_states--;
 	sched->state = sched->saved[sched->saved_states];
 
-	/* continue with next counter: */
-	clear_bit(sched->state.counter++, sched->state.used);
+	/* this assignment didn't work out */
+	/* XXX broken vs EVENT_PAIR */
+	sched->state.used &= ~BIT_ULL(sched->state.counter);
+
+	/* try the next one */
+	sched->state.counter++;
 
 	return true;
 }
@@ -776,20 +788,32 @@
 	if (c->idxmsk64 & (~0ULL << INTEL_PMC_IDX_FIXED)) {
 		idx = INTEL_PMC_IDX_FIXED;
 		for_each_set_bit_from(idx, c->idxmsk, X86_PMC_IDX_MAX) {
-			if (!__test_and_set_bit(idx, sched->state.used))
-				goto done;
+			u64 mask = BIT_ULL(idx);
+
+			if (sched->state.used & mask)
+				continue;
+
+			sched->state.used |= mask;
+			goto done;
 		}
 	}
 
 	/* Grab the first unused counter starting with idx */
 	idx = sched->state.counter;
 	for_each_set_bit_from(idx, c->idxmsk, INTEL_PMC_IDX_FIXED) {
-		if (!__test_and_set_bit(idx, sched->state.used)) {
-			if (sched->state.nr_gp++ >= sched->max_gp)
-				return false;
+		u64 mask = BIT_ULL(idx);
 
-			goto done;
-		}
+		if (c->flags & PERF_X86_EVENT_PAIR)
+			mask |= mask << 1;
+
+		if (sched->state.used & mask)
+			continue;
+
+		if (sched->state.nr_gp++ >= sched->max_gp)
+			return false;
+
+		sched->state.used |= mask;
+		goto done;
 	}
 
 	return false;
@@ -866,12 +890,10 @@
 int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
 {
 	struct event_constraint *c;
-	unsigned long used_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
 	struct perf_event *e;
 	int n0, i, wmin, wmax, unsched = 0;
 	struct hw_perf_event *hwc;
-
-	bitmap_zero(used_mask, X86_PMC_IDX_MAX);
+	u64 used_mask = 0;
 
 	/*
 	 * Compute the number of events already present; see x86_pmu_add(),
@@ -914,6 +936,8 @@
 	 * fastpath, try to reuse previous register
 	 */
 	for (i = 0; i < n; i++) {
+		u64 mask;
+
 		hwc = &cpuc->event_list[i]->hw;
 		c = cpuc->event_constraint[i];
 
@@ -925,11 +949,16 @@
 		if (!test_bit(hwc->idx, c->idxmsk))
 			break;
 
+		mask = BIT_ULL(hwc->idx);
+		if (is_counter_pair(hwc))
+			mask |= mask << 1;
+
 		/* not already used */
-		if (test_bit(hwc->idx, used_mask))
+		if (used_mask & mask)
 			break;
 
-		__set_bit(hwc->idx, used_mask);
+		used_mask |= mask;
+
 		if (assign)
 			assign[i] = hwc->idx;
 	}
@@ -952,6 +981,15 @@
 		    READ_ONCE(cpuc->excl_cntrs->exclusive_present))
 			gpmax /= 2;
 
+		/*
+		 * Reduce the amount of available counters to allow fitting
+		 * the extra Merge events needed by large increment events.
+		 */
+		if (x86_pmu.flags & PMU_FL_PAIR) {
+			gpmax = x86_pmu.num_counters - cpuc->n_pair;
+			WARN_ON(gpmax <= 0);
+		}
+
 		unsched = perf_assign_events(cpuc->event_constraint, n, wmin,
 					     wmax, gpmax, assign);
 	}
@@ -1032,6 +1070,8 @@
 			return -EINVAL;
 		cpuc->event_list[n] = leader;
 		n++;
+		if (is_counter_pair(&leader->hw))
+			cpuc->n_pair++;
 	}
 	if (!dogrp)
 		return n;
@@ -1046,6 +1086,8 @@
 
 		cpuc->event_list[n] = event;
 		n++;
+		if (is_counter_pair(&event->hw))
+			cpuc->n_pair++;
 	}
 	return n;
 }
@@ -1232,6 +1274,13 @@
 	wrmsrl(hwc->event_base, (u64)(-left) & x86_pmu.cntval_mask);
 
 	/*
+	 * Clear the Merge event counter's upper 16 bits since
+	 * we currently declare a 48-bit counter width
+	 */
+	if (is_counter_pair(hwc))
+		wrmsrl(x86_pmu_event_addr(idx + 1), 0);
+
+	/*
 	 * Due to erratum on certan cpu we need
 	 * a second write to be sure the register
 	 * is updated properly
@@ -1641,9 +1690,12 @@
 
 ssize_t events_sysfs_show(struct device *dev, struct device_attribute *attr, char *page)
 {
-	struct perf_pmu_events_attr *pmu_attr = \
+	struct perf_pmu_events_attr *pmu_attr =
 		container_of(attr, struct perf_pmu_events_attr, attr);
-	u64 config = x86_pmu.event_map(pmu_attr->id);
+	u64 config = 0;
+
+	if (pmu_attr->id < x86_pmu.max_events)
+		config = x86_pmu.event_map(pmu_attr->id);
 
 	/* string trumps id */
 	if (pmu_attr->event_str)
@@ -1712,6 +1764,9 @@
 {
 	struct perf_pmu_events_attr *pmu_attr;
 
+	if (idx >= x86_pmu.max_events)
+		return 0;
+
 	pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr.attr);
 	/* str trumps id */
 	return pmu_attr->event_str || x86_pmu.event_map(idx) ? attr->mode : 0;
@@ -2097,6 +2152,7 @@
 	if (err) {
 		if (event->destroy)
 			event->destroy(event);
+		event->destroy = NULL;
 	}
 
 	if (READ_ONCE(x86_pmu.attr_rdpmc) &&
@@ -2354,10 +2410,11 @@
 void
 perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs)
 {
+	struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs();
 	struct unwind_state state;
 	unsigned long addr;
 
-	if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
+	if (guest_cbs && guest_cbs->is_in_guest()) {
 		/* TODO: We don't support guest os callchain now */
 		return;
 	}
@@ -2463,10 +2520,11 @@
 void
 perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs)
 {
+	struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs();
 	struct stack_frame frame;
 	const unsigned long __user *fp;
 
-	if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
+	if (guest_cbs && guest_cbs->is_in_guest()) {
 		/* TODO: We don't support guest os callchain now */
 		return;
 	}
@@ -2550,18 +2608,21 @@
 
 unsigned long perf_instruction_pointer(struct pt_regs *regs)
 {
-	if (perf_guest_cbs && perf_guest_cbs->is_in_guest())
-		return perf_guest_cbs->get_guest_ip();
+	struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs();
+
+	if (guest_cbs && guest_cbs->is_in_guest())
+		return guest_cbs->get_guest_ip();
 
 	return regs->ip + code_segment_base(regs);
 }
 
 unsigned long perf_misc_flags(struct pt_regs *regs)
 {
+	struct perf_guest_info_callbacks *guest_cbs = perf_get_guest_cbs();
 	int misc = 0;
 
-	if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) {
-		if (perf_guest_cbs->is_user_mode())
+	if (guest_cbs && guest_cbs->is_in_guest()) {
+		if (guest_cbs->is_user_mode())
 			misc |= PERF_RECORD_MISC_GUEST_USER;
 		else
 			misc |= PERF_RECORD_MISC_GUEST_KERNEL;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/events/intel/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/events/intel/Makefile
@@ -2,8 +2,6 @@
 obj-$(CONFIG_CPU_SUP_INTEL)		+= core.o bts.o
 obj-$(CONFIG_CPU_SUP_INTEL)		+= ds.o knc.o
 obj-$(CONFIG_CPU_SUP_INTEL)		+= lbr.o p4.o p6.o pt.o
-obj-$(CONFIG_PERF_EVENTS_INTEL_RAPL)	+= intel-rapl-perf.o
-intel-rapl-perf-objs			:= rapl.o
 obj-$(CONFIG_PERF_EVENTS_INTEL_UNCORE)	+= intel-uncore.o
 intel-uncore-objs			:= uncore.o uncore_nhmex.o uncore_snb.o uncore_snbep.o
 obj-$(CONFIG_PERF_EVENTS_INTEL_CSTATE)	+= intel-cstate.o
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/events/intel/bts.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/events/intel/bts.c
@@ -63,9 +63,17 @@
 
 static struct pmu bts_pmu;
 
+static int buf_nr_pages(struct page *page)
+{
+	if (!PagePrivate(page))
+		return 1;
+
+	return 1 << page_private(page);
+}
+
 static size_t buf_size(struct page *page)
 {
-	return 1 << (PAGE_SHIFT + page_private(page));
+	return buf_nr_pages(page) * PAGE_SIZE;
 }
 
 static void *
@@ -83,9 +91,7 @@
 	/* count all the high order buffers */
 	for (pg = 0, nbuf = 0; pg < nr_pages;) {
 		page = virt_to_page(pages[pg]);
-		if (WARN_ON_ONCE(!PagePrivate(page) && nr_pages > 1))
-			return NULL;
-		pg += 1 << page_private(page);
+		pg += buf_nr_pages(page);
 		nbuf++;
 	}
 
@@ -109,7 +115,7 @@
 		unsigned int __nr_pages;
 
 		page = virt_to_page(pages[pg]);
-		__nr_pages = PagePrivate(page) ? 1 << page_private(page) : 1;
+		__nr_pages = buf_nr_pages(page);
 		buf->buf[nbuf].page = page;
 		buf->buf[nbuf].offset = offset;
 		buf->buf[nbuf].displacement = (pad ? BTS_RECORD_SIZE - pad : 0);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/events/intel/core.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/events/intel/core.c
@@ -243,21 +243,23 @@
 
 static struct event_constraint intel_icl_event_constraints[] = {
 	FIXED_EVENT_CONSTRAINT(0x00c0, 0),	/* INST_RETIRED.ANY */
-	INTEL_UEVENT_CONSTRAINT(0x1c0, 0),	/* INST_RETIRED.PREC_DIST */
+	FIXED_EVENT_CONSTRAINT(0x01c0, 0),	/* INST_RETIRED.PREC_DIST */
 	FIXED_EVENT_CONSTRAINT(0x003c, 1),	/* CPU_CLK_UNHALTED.CORE */
 	FIXED_EVENT_CONSTRAINT(0x0300, 2),	/* CPU_CLK_UNHALTED.REF */
 	FIXED_EVENT_CONSTRAINT(0x0400, 3),	/* SLOTS */
 	INTEL_EVENT_CONSTRAINT_RANGE(0x03, 0x0a, 0xf),
 	INTEL_EVENT_CONSTRAINT_RANGE(0x1f, 0x28, 0xf),
 	INTEL_EVENT_CONSTRAINT(0x32, 0xf),	/* SW_PREFETCH_ACCESS.* */
-	INTEL_EVENT_CONSTRAINT_RANGE(0x48, 0x54, 0xf),
+	INTEL_EVENT_CONSTRAINT_RANGE(0x48, 0x56, 0xf),
 	INTEL_EVENT_CONSTRAINT_RANGE(0x60, 0x8b, 0xf),
 	INTEL_UEVENT_CONSTRAINT(0x04a3, 0xff),  /* CYCLE_ACTIVITY.STALLS_TOTAL */
-	INTEL_UEVENT_CONSTRAINT(0x10a3, 0xff),  /* CYCLE_ACTIVITY.STALLS_MEM_ANY */
+	INTEL_UEVENT_CONSTRAINT(0x10a3, 0xff),  /* CYCLE_ACTIVITY.CYCLES_MEM_ANY */
+	INTEL_UEVENT_CONSTRAINT(0x14a3, 0xff),  /* CYCLE_ACTIVITY.STALLS_MEM_ANY */
 	INTEL_EVENT_CONSTRAINT(0xa3, 0xf),      /* CYCLE_ACTIVITY.* */
 	INTEL_EVENT_CONSTRAINT_RANGE(0xa8, 0xb0, 0xf),
 	INTEL_EVENT_CONSTRAINT_RANGE(0xb7, 0xbd, 0xf),
 	INTEL_EVENT_CONSTRAINT_RANGE(0xd0, 0xe6, 0xf),
+	INTEL_EVENT_CONSTRAINT(0xef, 0xf),
 	INTEL_EVENT_CONSTRAINT_RANGE(0xf0, 0xf4, 0xf),
 	EVENT_CONSTRAINT_END
 };
@@ -1892,8 +1894,8 @@
 
 static struct extra_reg intel_tnt_extra_regs[] __read_mostly = {
 	/* must define OFFCORE_RSP_X first, see intel_fixup_er() */
-	INTEL_UEVENT_EXTRA_REG(0x01b7, MSR_OFFCORE_RSP_0, 0xffffff9fffull, RSP_0),
-	INTEL_UEVENT_EXTRA_REG(0x02b7, MSR_OFFCORE_RSP_1, 0xffffff9fffull, RSP_1),
+	INTEL_UEVENT_EXTRA_REG(0x01b7, MSR_OFFCORE_RSP_0, 0x800ff0ffffff9fffull, RSP_0),
+	INTEL_UEVENT_EXTRA_REG(0x02b7, MSR_OFFCORE_RSP_1, 0xff0ffffff9fffull, RSP_1),
 	EVENT_EXTRA_END
 };
 
@@ -2331,6 +2333,7 @@
 {
 	struct perf_sample_data data;
 	struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+	struct perf_guest_info_callbacks *guest_cbs;
 	int bit;
 	int handled = 0;
 
@@ -2384,9 +2387,11 @@
 	 */
 	if (__test_and_clear_bit(55, (unsigned long *)&status)) {
 		handled++;
-		if (unlikely(perf_guest_cbs && perf_guest_cbs->is_in_guest() &&
-			perf_guest_cbs->handle_intel_pt_intr))
-			perf_guest_cbs->handle_intel_pt_intr();
+
+		guest_cbs = perf_get_guest_cbs();
+		if (unlikely(guest_cbs && guest_cbs->is_in_guest() &&
+			     guest_cbs->handle_intel_pt_intr))
+			guest_cbs->handle_intel_pt_intr();
 		else
 			intel_pt_interrupt();
 	}
@@ -3998,9 +4003,13 @@
 	INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_D,		 3, 0x07000009),
 	INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_D,		 4, 0x0f000009),
 	INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_D,		 5, 0x0e000002),
-	INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_X,		 2, 0x0b000014),
+	INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_X,		 1, 0x0b000014),
 	INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE_X,		 3, 0x00000021),
 	INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE_X,		 4, 0x00000000),
+	INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE_X,		 5, 0x00000000),
+	INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE_X,		 6, 0x00000000),
+	INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE_X,		 7, 0x00000000),
+	INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE_X,		11, 0x00000000),
 	INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE_L,		 3, 0x0000007c),
 	INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE,		 3, 0x0000007c),
 	INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE,		 9, 0x0000004e),
@@ -4746,6 +4755,7 @@
 		break;
 
 	case INTEL_FAM6_ATOM_TREMONT_D:
+	case INTEL_FAM6_ATOM_TREMONT:
 		x86_pmu.late_ack = true;
 		memcpy(hw_cache_event_ids, glp_hw_cache_event_ids,
 		       sizeof(hw_cache_event_ids));
@@ -5056,7 +5066,7 @@
 		extra_skl_attr = skl_format_attr;
 		mem_attr = icl_events_attrs;
 		tsx_attr = icl_tsx_events_attrs;
-		x86_pmu.rtm_abort_event = X86_CONFIG(.event=0xca, .umask=0x02);
+		x86_pmu.rtm_abort_event = X86_CONFIG(.event=0xc9, .umask=0x04);
 		x86_pmu.lbr_pt_coexist = true;
 		intel_pmu_pebs_data_source_skl(pmem);
 		pr_cont("Icelake events, ");
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/events/intel/cstate.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/events/intel/cstate.c
@@ -40,17 +40,18 @@
  * Model specific counters:
  *	MSR_CORE_C1_RES: CORE C1 Residency Counter
  *			 perf code: 0x00
- *			 Available model: SLM,AMT,GLM,CNL
+ *			 Available model: SLM,AMT,GLM,CNL,TNT
  *			 Scope: Core (each processor core has a MSR)
  *	MSR_CORE_C3_RESIDENCY: CORE C3 Residency Counter
  *			       perf code: 0x01
  *			       Available model: NHM,WSM,SNB,IVB,HSW,BDW,SKL,GLM,
- *						CNL,KBL,CML
+ *						CNL,KBL,CML,TNT
  *			       Scope: Core
  *	MSR_CORE_C6_RESIDENCY: CORE C6 Residency Counter
  *			       perf code: 0x02
  *			       Available model: SLM,AMT,NHM,WSM,SNB,IVB,HSW,BDW,
- *						SKL,KNL,GLM,CNL,KBL,CML,ICL,TGL
+ *						SKL,KNL,GLM,CNL,KBL,CML,ICL,TGL,
+ *						TNT
  *			       Scope: Core
  *	MSR_CORE_C7_RESIDENCY: CORE C7 Residency Counter
  *			       perf code: 0x03
@@ -60,17 +61,18 @@
  *	MSR_PKG_C2_RESIDENCY:  Package C2 Residency Counter.
  *			       perf code: 0x00
  *			       Available model: SNB,IVB,HSW,BDW,SKL,KNL,GLM,CNL,
- *						KBL,CML,ICL,TGL
+ *						KBL,CML,ICL,TGL,TNT
  *			       Scope: Package (physical package)
  *	MSR_PKG_C3_RESIDENCY:  Package C3 Residency Counter.
  *			       perf code: 0x01
  *			       Available model: NHM,WSM,SNB,IVB,HSW,BDW,SKL,KNL,
- *						GLM,CNL,KBL,CML,ICL,TGL
+ *						GLM,CNL,KBL,CML,ICL,TGL,TNT
  *			       Scope: Package (physical package)
  *	MSR_PKG_C6_RESIDENCY:  Package C6 Residency Counter.
  *			       perf code: 0x02
- *			       Available model: SLM,AMT,NHM,WSM,SNB,IVB,HSW,BDW
- *						SKL,KNL,GLM,CNL,KBL,CML,ICL,TGL
+ *			       Available model: SLM,AMT,NHM,WSM,SNB,IVB,HSW,BDW,
+ *						SKL,KNL,GLM,CNL,KBL,CML,ICL,TGL,
+ *						TNT
  *			       Scope: Package (physical package)
  *	MSR_PKG_C7_RESIDENCY:  Package C7 Residency Counter.
  *			       perf code: 0x03
@@ -87,7 +89,8 @@
  *			       Scope: Package (physical package)
  *	MSR_PKG_C10_RESIDENCY: Package C10 Residency Counter.
  *			       perf code: 0x06
- *			       Available model: HSW ULT,KBL,GLM,CNL,CML,ICL,TGL
+ *			       Available model: HSW ULT,KBL,GLM,CNL,CML,ICL,TGL,
+ *						TNT
  *			       Scope: Package (physical package)
  *
  */
@@ -104,14 +107,14 @@
 MODULE_LICENSE("GPL");
 
 #define DEFINE_CSTATE_FORMAT_ATTR(_var, _name, _format)		\
-static ssize_t __cstate_##_var##_show(struct kobject *kobj,	\
-				struct kobj_attribute *attr,	\
+static ssize_t __cstate_##_var##_show(struct device *dev,	\
+				struct device_attribute *attr,	\
 				char *page)			\
 {								\
 	BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE);		\
 	return sprintf(page, _format "\n");			\
 }								\
-static struct kobj_attribute format_attr_##_var =		\
+static struct device_attribute format_attr_##_var =		\
 	__ATTR(_name, 0444, __cstate_##_var##_show, NULL)
 
 static ssize_t cstate_get_attr_cpumask(struct device *dev,
@@ -640,8 +643,9 @@
 
 	X86_CSTATES_MODEL(INTEL_FAM6_ATOM_GOLDMONT,   glm_cstates),
 	X86_CSTATES_MODEL(INTEL_FAM6_ATOM_GOLDMONT_D, glm_cstates),
-
 	X86_CSTATES_MODEL(INTEL_FAM6_ATOM_GOLDMONT_PLUS, glm_cstates),
+	X86_CSTATES_MODEL(INTEL_FAM6_ATOM_TREMONT_D, glm_cstates),
+	X86_CSTATES_MODEL(INTEL_FAM6_ATOM_TREMONT, glm_cstates),
 
 	X86_CSTATES_MODEL(INTEL_FAM6_ICELAKE_L, icl_cstates),
 	X86_CSTATES_MODEL(INTEL_FAM6_ICELAKE,   icl_cstates),
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/events/intel/ds.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/events/intel/ds.c
@@ -669,9 +669,7 @@
 
 static inline void intel_pmu_drain_pebs_buffer(void)
 {
-	struct pt_regs regs;
-
-	x86_pmu.drain_pebs(&regs);
+	x86_pmu.drain_pebs(NULL);
 }
 
 /*
@@ -854,8 +852,13 @@
 	INTEL_FLAGS_UEVENT_CONSTRAINT(0x0400, 0x800000000ULL),	/* SLOTS */
 
 	INTEL_PLD_CONSTRAINT(0x1cd, 0xff),			/* MEM_TRANS_RETIRED.LOAD_LATENCY */
-	INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x1d0, 0xf),	/* MEM_INST_RETIRED.LOAD */
-	INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x2d0, 0xf),	/* MEM_INST_RETIRED.STORE */
+	INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x11d0, 0xf),	/* MEM_INST_RETIRED.STLB_MISS_LOADS */
+	INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x12d0, 0xf),	/* MEM_INST_RETIRED.STLB_MISS_STORES */
+	INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x21d0, 0xf),	/* MEM_INST_RETIRED.LOCK_LOADS */
+	INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x41d0, 0xf),	/* MEM_INST_RETIRED.SPLIT_LOADS */
+	INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x42d0, 0xf),	/* MEM_INST_RETIRED.SPLIT_STORES */
+	INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x81d0, 0xf),	/* MEM_INST_RETIRED.ALL_LOADS */
+	INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x82d0, 0xf),	/* MEM_INST_RETIRED.ALL_STORES */
 
 	INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_LD_RANGE(0xd1, 0xd4, 0xf), /* MEM_LOAD_*_RETIRED.* */
 
@@ -1713,6 +1716,8 @@
 	old = ((s64)(prev_raw_count << shift) >> shift);
 	local64_add(new - old + count * period, &event->count);
 
+	local64_set(&hwc->period_left, -new);
+
 	perf_event_update_userpage(event);
 
 	return 0;
@@ -1734,6 +1739,7 @@
 	struct x86_perf_regs perf_regs;
 	struct pt_regs *regs = &perf_regs.regs;
 	void *at = get_next_pebs_record_by_bit(base, top, bit);
+	struct pt_regs dummy_iregs;
 
 	if (hwc->flags & PERF_X86_EVENT_AUTO_RELOAD) {
 		/*
@@ -1746,6 +1752,9 @@
 	} else if (!intel_pmu_save_and_restart(event))
 		return;
 
+	if (!iregs)
+		iregs = &dummy_iregs;
+
 	while (count > 1) {
 		setup_sample(event, iregs, at, &data, regs);
 		perf_event_output(event, &data, regs);
@@ -1755,16 +1764,22 @@
 	}
 
 	setup_sample(event, iregs, at, &data, regs);
-
-	/*
-	 * All but the last records are processed.
-	 * The last one is left to be able to call the overflow handler.
-	 */
-	if (perf_event_overflow(event, &data, regs)) {
-		x86_pmu_stop(event, 0);
-		return;
+	if (iregs == &dummy_iregs) {
+		/*
+		 * The PEBS records may be drained in the non-overflow context,
+		 * e.g., large PEBS + context switch. Perf should treat the
+		 * last record the same as other PEBS records, and doesn't
+		 * invoke the generic overflow handler.
+		 */
+		perf_event_output(event, &data, regs);
+	} else {
+		/*
+		 * All but the last records are processed.
+		 * The last one is left to be able to call the overflow handler.
+		 */
+		if (perf_event_overflow(event, &data, regs))
+			x86_pmu_stop(event, 0);
 	}
-
 }
 
 static void intel_pmu_drain_pebs_core(struct pt_regs *iregs)
@@ -1880,7 +1895,7 @@
 		 */
 		if (!pebs_status && cpuc->pebs_enabled &&
 			!(cpuc->pebs_enabled & (cpuc->pebs_enabled-1)))
-			pebs_status = cpuc->pebs_enabled;
+			pebs_status = p->status = cpuc->pebs_enabled;
 
 		bit = find_first_bit((unsigned long *)&pebs_status,
 					x86_pmu.max_pebs_events);
@@ -1902,7 +1917,7 @@
 		 * that caused the PEBS record. It's called collision.
 		 * If collision happened, the record will be dropped.
 		 */
-		if (p->status != (1ULL << bit)) {
+		if (pebs_status != (1ULL << bit)) {
 			for_each_set_bit(i, (unsigned long *)&pebs_status, size)
 				error[i]++;
 			continue;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/events/intel/pt.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/events/intel/pt.c
@@ -62,7 +62,7 @@
 	PT_CAP(single_range_output,	0, CPUID_ECX, BIT(2)),
 	PT_CAP(output_subsys,		0, CPUID_ECX, BIT(3)),
 	PT_CAP(payloads_lip,		0, CPUID_ECX, BIT(31)),
-	PT_CAP(num_address_ranges,	1, CPUID_EAX, 0x3),
+	PT_CAP(num_address_ranges,	1, CPUID_EAX, 0x7),
 	PT_CAP(mtc_periods,		1, CPUID_EAX, 0xffff0000),
 	PT_CAP(cycle_thresholds,	1, CPUID_EBX, 0xffff),
 	PT_CAP(psb_periods,		1, CPUID_EBX, 0xffff0000),
@@ -460,7 +460,7 @@
 			pt->filters.filter[range].msr_b = filter->msr_b;
 		}
 
-		rtit_ctl |= filter->config << pt_address_ranges[range].reg_off;
+		rtit_ctl |= (u64)filter->config << pt_address_ranges[range].reg_off;
 	}
 
 	return rtit_ctl;
@@ -782,11 +782,13 @@
 	buf->cur_idx++;
 
 	if (buf->cur_idx == buf->cur->last) {
-		if (buf->cur == buf->last)
+		if (buf->cur == buf->last) {
 			buf->cur = buf->first;
-		else
+			buf->wrapped = true;
+		} else {
 			buf->cur = list_entry(buf->cur->list.next, struct topa,
 					      list);
+		}
 		buf->cur_idx = 0;
 	}
 }
@@ -800,8 +802,11 @@
 static void pt_update_head(struct pt *pt)
 {
 	struct pt_buffer *buf = perf_get_aux(&pt->handle);
+	bool wrapped = buf->wrapped;
 	u64 topa_idx, base, old;
 
+	buf->wrapped = false;
+
 	/* offset of the first region in this table from the beginning of buf */
 	base = buf->cur->offset + buf->output_off;
 
@@ -814,7 +819,7 @@
 	} else {
 		old = (local64_xchg(&buf->head, base) &
 		       ((buf->nr_pages << PAGE_SHIFT) - 1));
-		if (base < old)
+		if (base < old || (base == old && wrapped))
 			base += buf->nr_pages << PAGE_SHIFT;
 
 		local_add(base - old, &buf->data_size);
@@ -827,7 +832,7 @@
  */
 static void *pt_buffer_region(struct pt_buffer *buf)
 {
-	return phys_to_virt(TOPA_ENTRY(buf->cur, buf->cur_idx)->base << TOPA_SHIFT);
+	return phys_to_virt((phys_addr_t)TOPA_ENTRY(buf->cur, buf->cur_idx)->base << TOPA_SHIFT);
 }
 
 /**
@@ -935,7 +940,7 @@
 	 * order allocations, there shouldn't be many of these.
 	 */
 	list_for_each_entry(topa, &buf->tables, list) {
-		if (topa->offset + topa->size > pg << PAGE_SHIFT)
+		if (topa->offset + topa->size > (unsigned long)pg << PAGE_SHIFT)
 			goto found;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/events/intel/pt.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/events/intel/pt.h
@@ -33,8 +33,8 @@
 	u64	rsvd2	: 1;
 	u64	size	: 4;
 	u64	rsvd3	: 2;
-	u64	base	: 36;
-	u64	rsvd4	: 16;
+	u64	base	: 40;
+	u64	rsvd4	: 12;
 };
 
 /* TSC to Core Crystal Clock Ratio */
@@ -64,6 +64,7 @@
  * @lost:	if data was lost/truncated
  * @head:	logical write offset inside the buffer
  * @snapshot:	if this is for a snapshot/overwrite counter
+ * @wrapped:	buffer advance wrapped back to the first topa table
  * @stop_pos:	STOP topa entry index
  * @intr_pos:	INT topa entry index
  * @stop_te:	STOP topa entry pointer
@@ -80,6 +81,7 @@
 	local_t			data_size;
 	local64_t		head;
 	bool			snapshot;
+	bool			wrapped;
 	long			stop_pos, intr_pos;
 	struct topa_entry	*stop_te, *intr_te;
 	void			**data_pages;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/events/intel/uncore.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/events/intel/uncore.c
@@ -92,8 +92,8 @@
 	return map;
 }
 
-ssize_t uncore_event_show(struct kobject *kobj,
-			  struct kobj_attribute *attr, char *buf)
+ssize_t uncore_event_show(struct device *dev,
+			  struct device_attribute *attr, char *buf)
 {
 	struct uncore_event_desc *event =
 		container_of(attr, struct uncore_event_desc, attr);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/events/intel/uncore.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/events/intel/uncore.h
@@ -144,7 +144,7 @@
 #define UNCORE_BOX_FLAG_CFL8_CBOX_MSR_OFFS	2
 
 struct uncore_event_desc {
-	struct kobj_attribute attr;
+	struct device_attribute attr;
 	const char *config;
 };
 
@@ -165,8 +165,8 @@
 struct pci2phy_map *__find_pci2phy_map(int segment);
 int uncore_pcibus_to_physid(struct pci_bus *bus);
 
-ssize_t uncore_event_show(struct kobject *kobj,
-			  struct kobj_attribute *attr, char *buf);
+ssize_t uncore_event_show(struct device *dev,
+			  struct device_attribute *attr, char *buf);
 
 #define INTEL_UNCORE_EVENT_DESC(_name, _config)			\
 {								\
@@ -175,14 +175,14 @@
 }
 
 #define DEFINE_UNCORE_FORMAT_ATTR(_var, _name, _format)			\
-static ssize_t __uncore_##_var##_show(struct kobject *kobj,		\
-				struct kobj_attribute *attr,		\
+static ssize_t __uncore_##_var##_show(struct device *dev,		\
+				struct device_attribute *attr,		\
 				char *page)				\
 {									\
 	BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE);			\
 	return sprintf(page, _format "\n");				\
 }									\
-static struct kobj_attribute format_attr_##_var =			\
+static struct device_attribute format_attr_##_var =			\
 	__ATTR(_name, 0444, __uncore_##_var##_show, NULL)
 
 static inline bool uncore_pmc_fixed(int idx)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/events/intel/uncore_snb.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/events/intel/uncore_snb.c
@@ -15,6 +15,7 @@
 #define PCI_DEVICE_ID_INTEL_SKL_HQ_IMC		0x1910
 #define PCI_DEVICE_ID_INTEL_SKL_SD_IMC		0x190f
 #define PCI_DEVICE_ID_INTEL_SKL_SQ_IMC		0x191f
+#define PCI_DEVICE_ID_INTEL_SKL_E3_IMC		0x1918
 #define PCI_DEVICE_ID_INTEL_KBL_Y_IMC		0x590c
 #define PCI_DEVICE_ID_INTEL_KBL_U_IMC		0x5904
 #define PCI_DEVICE_ID_INTEL_KBL_UQ_IMC		0x5914
@@ -109,6 +110,10 @@
 #define ICL_UNC_CBO_0_PER_CTR0			0x702
 #define ICL_UNC_CBO_MSR_OFFSET			0x8
 
+/* ICL ARB register */
+#define ICL_UNC_ARB_PER_CTR			0x3b1
+#define ICL_UNC_ARB_PERFEVTSEL			0x3b3
+
 DEFINE_UNCORE_FORMAT_ATTR(event, event, "config:0-7");
 DEFINE_UNCORE_FORMAT_ATTR(umask, umask, "config:8-15");
 DEFINE_UNCORE_FORMAT_ATTR(edge, edge, "config:18");
@@ -296,15 +301,21 @@
 	snb_uncore_arb.ops = &skl_uncore_msr_ops;
 }
 
+static struct intel_uncore_ops icl_uncore_msr_ops = {
+	.disable_event	= snb_uncore_msr_disable_event,
+	.enable_event	= snb_uncore_msr_enable_event,
+	.read_counter	= uncore_msr_read_counter,
+};
+
 static struct intel_uncore_type icl_uncore_cbox = {
 	.name		= "cbox",
-	.num_counters   = 4,
+	.num_counters   = 2,
 	.perf_ctr_bits	= 44,
 	.perf_ctr	= ICL_UNC_CBO_0_PER_CTR0,
 	.event_ctl	= SNB_UNC_CBO_0_PERFEVTSEL0,
 	.event_mask	= SNB_UNC_RAW_EVENT_MASK,
 	.msr_offset	= ICL_UNC_CBO_MSR_OFFSET,
-	.ops		= &skl_uncore_msr_ops,
+	.ops		= &icl_uncore_msr_ops,
 	.format_group	= &snb_uncore_format_group,
 };
 
@@ -333,13 +344,25 @@
 	.single_fixed	= 1,
 	.event_mask	= SNB_UNC_CTL_EV_SEL_MASK,
 	.format_group	= &icl_uncore_clock_format_group,
-	.ops		= &skl_uncore_msr_ops,
+	.ops		= &icl_uncore_msr_ops,
 	.event_descs	= icl_uncore_events,
 };
 
+static struct intel_uncore_type icl_uncore_arb = {
+	.name		= "arb",
+	.num_counters   = 1,
+	.num_boxes	= 1,
+	.perf_ctr_bits	= 44,
+	.perf_ctr	= ICL_UNC_ARB_PER_CTR,
+	.event_ctl	= ICL_UNC_ARB_PERFEVTSEL,
+	.event_mask	= SNB_UNC_RAW_EVENT_MASK,
+	.ops		= &icl_uncore_msr_ops,
+	.format_group	= &snb_uncore_format_group,
+};
+
 static struct intel_uncore_type *icl_msr_uncores[] = {
 	&icl_uncore_cbox,
-	&snb_uncore_arb,
+	&icl_uncore_arb,
 	&icl_uncore_clockbox,
 	NULL,
 };
@@ -357,7 +380,6 @@
 {
 	uncore_msr_uncores = icl_msr_uncores;
 	icl_uncore_cbox.num_boxes = icl_get_cbox_num();
-	snb_uncore_arb.ops = &skl_uncore_msr_ops;
 }
 
 enum {
@@ -553,6 +575,22 @@
 	return 0;
 }
 
+static u64 snb_uncore_imc_read_counter(struct intel_uncore_box *box, struct perf_event *event)
+{
+	struct hw_perf_event *hwc = &event->hw;
+
+	/*
+	 * SNB IMC counters are 32-bit and are laid out back to back
+	 * in MMIO space. Therefore we must use a 32-bit accessor function
+	 * using readq() from uncore_mmio_read_counter() causes problems
+	 * because it is reading 64-bit at a time. This is okay for the
+	 * uncore_perf_event_update() function because it drops the upper
+	 * 32-bits but not okay for plain uncore_read_counter() as invoked
+	 * in uncore_pmu_event_start().
+	 */
+	return (u64)readl(box->io_addr + hwc->event_base);
+}
+
 static struct pmu snb_uncore_imc_pmu = {
 	.task_ctx_nr	= perf_invalid_context,
 	.event_init	= snb_uncore_imc_event_init,
@@ -572,7 +610,7 @@
 	.disable_event	= snb_uncore_imc_disable_event,
 	.enable_event	= snb_uncore_imc_enable_event,
 	.hw_config	= snb_uncore_imc_hw_config,
-	.read_counter	= uncore_mmio_read_counter,
+	.read_counter	= snb_uncore_imc_read_counter,
 };
 
 static struct intel_uncore_type snb_uncore_imc = {
@@ -658,6 +696,10 @@
 		.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
 	},
 	{ /* IMC */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SKL_E3_IMC),
+		.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+	},
+	{ /* IMC */
 		PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_KBL_Y_IMC),
 		.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
 	},
@@ -826,6 +868,7 @@
 	IMC_DEV(SKL_HQ_IMC, &skl_uncore_pci_driver),  /* 6th Gen Core H Quad Core */
 	IMC_DEV(SKL_SD_IMC, &skl_uncore_pci_driver),  /* 6th Gen Core S Dual Core */
 	IMC_DEV(SKL_SQ_IMC, &skl_uncore_pci_driver),  /* 6th Gen Core S Quad Core */
+	IMC_DEV(SKL_E3_IMC, &skl_uncore_pci_driver),  /* Xeon E3 V5 Gen Core processor */
 	IMC_DEV(KBL_Y_IMC, &skl_uncore_pci_driver),  /* 7th Gen Core Y */
 	IMC_DEV(KBL_U_IMC, &skl_uncore_pci_driver),  /* 7th Gen Core U */
 	IMC_DEV(KBL_UQ_IMC, &skl_uncore_pci_driver),  /* 7th Gen Core U Quad Core */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/events/intel/uncore_snbep.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/events/intel/uncore_snbep.c
@@ -369,11 +369,6 @@
 #define SNR_M2M_PCI_PMON_BOX_CTL		0x438
 #define SNR_M2M_PCI_PMON_UMASK_EXT		0xff
 
-/* SNR PCIE3 */
-#define SNR_PCIE3_PCI_PMON_CTL0			0x508
-#define SNR_PCIE3_PCI_PMON_CTR0			0x4e8
-#define SNR_PCIE3_PCI_PMON_BOX_CTL		0x4e4
-
 /* SNR IMC */
 #define SNR_IMC_MMIO_PMON_FIXED_CTL		0x54
 #define SNR_IMC_MMIO_PMON_FIXED_CTR		0x38
@@ -1098,7 +1093,6 @@
 	SNBEP_PCI_QPI_PORT0_FILTER,
 	SNBEP_PCI_QPI_PORT1_FILTER,
 	BDX_PCI_QPI_PORT2_FILTER,
-	HSWEP_PCI_PCU_3,
 };
 
 static int snbep_qpi_hw_config(struct intel_uncore_box *box, struct perf_event *event)
@@ -2755,22 +2749,34 @@
 	NULL,
 };
 
-void hswep_uncore_cpu_init(void)
+#define HSWEP_PCU_DID			0x2fc0
+#define HSWEP_PCU_CAPID4_OFFET		0x94
+#define hswep_get_chop(_cap)		(((_cap) >> 6) & 0x3)
+
+static bool hswep_has_limit_sbox(unsigned int device)
 {
-	int pkg = boot_cpu_data.logical_proc_id;
+	struct pci_dev *dev = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL);
+	u32 capid4;
+
+	if (!dev)
+		return false;
+
+	pci_read_config_dword(dev, HSWEP_PCU_CAPID4_OFFET, &capid4);
+	pci_dev_put(dev);
+	if (!hswep_get_chop(capid4))
+		return true;
+
+	return false;
+}
 
+void hswep_uncore_cpu_init(void)
+{
 	if (hswep_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores)
 		hswep_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores;
 
 	/* Detect 6-8 core systems with only two SBOXes */
-	if (uncore_extra_pci_dev[pkg].dev[HSWEP_PCI_PCU_3]) {
-		u32 capid4;
-
-		pci_read_config_dword(uncore_extra_pci_dev[pkg].dev[HSWEP_PCI_PCU_3],
-				      0x94, &capid4);
-		if (((capid4 >> 6) & 0x3) == 0)
-			hswep_uncore_sbox.num_boxes = 2;
-	}
+	if (hswep_has_limit_sbox(HSWEP_PCU_DID))
+		hswep_uncore_sbox.num_boxes = 2;
 
 	uncore_msr_uncores = hswep_msr_uncores;
 }
@@ -3033,11 +3039,6 @@
 		.driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
 						   SNBEP_PCI_QPI_PORT1_FILTER),
 	},
-	{ /* PCU.3 (for Capability registers) */
-		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2fc0),
-		.driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
-						   HSWEP_PCI_PCU_3),
-	},
 	{ /* end: all zeroes */ }
 };
 
@@ -3129,27 +3130,18 @@
 	EVENT_CONSTRAINT_END
 };
 
+#define BDX_PCU_DID			0x6fc0
+
 void bdx_uncore_cpu_init(void)
 {
-	int pkg = topology_phys_to_logical_pkg(boot_cpu_data.phys_proc_id);
-
 	if (bdx_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores)
 		bdx_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores;
 	uncore_msr_uncores = bdx_msr_uncores;
 
-	/* BDX-DE doesn't have SBOX */
-	if (boot_cpu_data.x86_model == 86) {
-		uncore_msr_uncores[BDX_MSR_UNCORE_SBOX] = NULL;
 	/* Detect systems with no SBOXes */
-	} else if (uncore_extra_pci_dev[pkg].dev[HSWEP_PCI_PCU_3]) {
-		struct pci_dev *pdev;
-		u32 capid4;
-
-		pdev = uncore_extra_pci_dev[pkg].dev[HSWEP_PCI_PCU_3];
-		pci_read_config_dword(pdev, 0x94, &capid4);
-		if (((capid4 >> 6) & 0x3) == 0)
-			bdx_msr_uncores[BDX_MSR_UNCORE_SBOX] = NULL;
-	}
+	if ((boot_cpu_data.x86_model == 86) || hswep_has_limit_sbox(BDX_PCU_DID))
+		uncore_msr_uncores[BDX_MSR_UNCORE_SBOX] = NULL;
+
 	hswep_uncore_pcu.constraints = bdx_uncore_pcu_constraints;
 }
 
@@ -3370,11 +3362,6 @@
 		.driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
 						   BDX_PCI_QPI_PORT2_FILTER),
 	},
-	{ /* PCU.3 (for Capability registers) */
-		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6fc0),
-		.driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV,
-						   HSWEP_PCI_PCU_3),
-	},
 	{ /* end: all zeroes */ }
 };
 
@@ -3493,6 +3480,9 @@
 	struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
 	struct extra_reg *er;
 	int idx = 0;
+	/* Any of the CHA events may be filtered by Thread/Core-ID.*/
+	if (event->hw.config & SNBEP_CBO_PMON_CTL_TID_EN)
+		idx = SKX_CHA_MSR_PMON_BOX_FILTER_TID;
 
 	for (er = skx_uncore_cha_extra_regs; er->msr; er++) {
 		if (er->event != (event->hw.config & er->config_mask))
@@ -3560,6 +3550,7 @@
 	UNCORE_EVENT_CONSTRAINT(0xc0, 0xc),
 	UNCORE_EVENT_CONSTRAINT(0xc5, 0xc),
 	UNCORE_EVENT_CONSTRAINT(0xd4, 0xc),
+	UNCORE_EVENT_CONSTRAINT(0xd5, 0xc),
 	EVENT_CONSTRAINT_END
 };
 
@@ -4328,27 +4319,12 @@
 	.format_group	= &snr_m2m_uncore_format_group,
 };
 
-static struct intel_uncore_type snr_uncore_pcie3 = {
-	.name		= "pcie3",
-	.num_counters	= 4,
-	.num_boxes	= 1,
-	.perf_ctr_bits	= 48,
-	.perf_ctr	= SNR_PCIE3_PCI_PMON_CTR0,
-	.event_ctl	= SNR_PCIE3_PCI_PMON_CTL0,
-	.event_mask	= SNBEP_PMON_RAW_EVENT_MASK,
-	.box_ctl	= SNR_PCIE3_PCI_PMON_BOX_CTL,
-	.ops		= &ivbep_uncore_pci_ops,
-	.format_group	= &ivbep_uncore_format_group,
-};
-
 enum {
 	SNR_PCI_UNCORE_M2M,
-	SNR_PCI_UNCORE_PCIE3,
 };
 
 static struct intel_uncore_type *snr_pci_uncores[] = {
 	[SNR_PCI_UNCORE_M2M]		= &snr_uncore_m2m,
-	[SNR_PCI_UNCORE_PCIE3]		= &snr_uncore_pcie3,
 	NULL,
 };
 
@@ -4357,10 +4333,6 @@
 		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x344a),
 		.driver_data = UNCORE_PCI_DEV_FULL_DATA(12, 0, SNR_PCI_UNCORE_M2M, 0),
 	},
-	{ /* PCIe3 */
-		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x334a),
-		.driver_data = UNCORE_PCI_DEV_FULL_DATA(4, 0, SNR_PCI_UNCORE_PCIE3, 0),
-	},
 	{ /* end: all zeroes */ }
 };
 
@@ -4415,7 +4387,7 @@
 		return;
 
 	pci_read_config_dword(pdev, SNR_IMC_MMIO_BASE_OFFSET, &pci_dword);
-	addr = (pci_dword & SNR_IMC_MMIO_BASE_MASK) << 23;
+	addr = ((resource_size_t)pci_dword & SNR_IMC_MMIO_BASE_MASK) << 23;
 
 	pci_read_config_dword(pdev, SNR_IMC_MMIO_MEM0_OFFSET, &pci_dword);
 	addr |= (pci_dword & SNR_IMC_MMIO_MEM0_MASK) << 12;
@@ -4536,6 +4508,7 @@
 	INTEL_UNCORE_EVENT_DESC(write,		"event=0xff,umask=0x21"),
 	INTEL_UNCORE_EVENT_DESC(write.scale,	"3.814697266e-6"),
 	INTEL_UNCORE_EVENT_DESC(write.unit,	"MiB"),
+	{ /* end: all zeroes */ },
 };
 
 static struct intel_uncore_ops snr_uncore_imc_freerunning_ops = {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/events/msr.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/events/msr.c
@@ -75,8 +75,9 @@
 
 	case INTEL_FAM6_ATOM_GOLDMONT:
 	case INTEL_FAM6_ATOM_GOLDMONT_D:
-
 	case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
+	case INTEL_FAM6_ATOM_TREMONT_D:
+	case INTEL_FAM6_ATOM_TREMONT:
 
 	case INTEL_FAM6_XEON_PHI_KNL:
 	case INTEL_FAM6_XEON_PHI_KNM:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/events/perf_event.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/events/perf_event.h
@@ -77,6 +77,7 @@
 #define PERF_X86_EVENT_AUTO_RELOAD	0x0200 /* use PEBS auto-reload */
 #define PERF_X86_EVENT_LARGE_PEBS	0x0400 /* use large PEBS */
 #define PERF_X86_EVENT_PEBS_VIA_PT	0x0800 /* use PT buffer for PEBS */
+#define PERF_X86_EVENT_PAIR		0x1000 /* Large Increment per Cycle */
 
 struct amd_nb {
 	int nb_id;  /* NorthBridge id */
@@ -272,6 +273,7 @@
 	struct amd_nb			*amd_nb;
 	/* Inverted mask of bits to clear in the perf_ctr ctrl registers */
 	u64				perf_ctr_virt_mask;
+	int				n_pair; /* Large increment events */
 
 	void				*kfree_on_online[X86_PERF_KFREE_MAX];
 };
@@ -686,6 +688,7 @@
 	 * AMD bits
 	 */
 	unsigned int	amd_nb_constraints : 1;
+	u64		perf_ctr_pair_en;
 
 	/*
 	 * Extra registers for events
@@ -735,6 +738,7 @@
 #define PMU_FL_EXCL_ENABLED	0x8 /* exclusive counter active */
 #define PMU_FL_PEBS_ALL		0x10 /* all events are valid PEBS events */
 #define PMU_FL_TFA		0x20 /* deal with TSX force abort */
+#define PMU_FL_PAIR		0x40 /* merge counters for large incr. events */
 
 #define EVENT_VAR(_id)  event_attr_##_id
 #define EVENT_PTR(_id) &event_attr_##_id.attr.attr
@@ -830,6 +834,11 @@
 
 void x86_pmu_disable_all(void);
 
+static inline bool is_counter_pair(struct hw_perf_event *hwc)
+{
+	return hwc->flags & PERF_X86_EVENT_PAIR;
+}
+
 static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc,
 					  u64 enable_mask)
 {
@@ -837,6 +846,14 @@
 
 	if (hwc->extra_reg.reg)
 		wrmsrl(hwc->extra_reg.reg, hwc->extra_reg.config);
+
+	/*
+	 * Add enabled Merge event on next counter
+	 * if large increment event being enabled on this counter
+	 */
+	if (is_counter_pair(hwc))
+		wrmsrl(x86_pmu_config_addr(hwc->idx + 1), x86_pmu.perf_ctr_pair_en);
+
 	wrmsrl(hwc->config_base, (hwc->config | enable_mask) & ~disable_mask);
 }
 
@@ -850,9 +867,13 @@
 
 static inline void x86_pmu_disable_event(struct perf_event *event)
 {
+	u64 disable_mask = __this_cpu_read(cpu_hw_events.perf_ctr_virt_mask);
 	struct hw_perf_event *hwc = &event->hw;
 
-	wrmsrl(hwc->config_base, hwc->config);
+	wrmsrl(hwc->config_base, hwc->config & ~disable_mask);
+
+	if (is_counter_pair(hwc))
+		wrmsrl(x86_pmu_config_addr(hwc->idx + 1), 0);
 }
 
 void x86_pmu_enable_event(struct perf_event *event);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/events/rapl.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/events/rapl.c
@@ -0,0 +1,793 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Support Intel/AMD RAPL energy consumption counters
+ * Copyright (C) 2013 Google, Inc., Stephane Eranian
+ *
+ * Intel RAPL interface is specified in the IA-32 Manual Vol3b
+ * section 14.7.1 (September 2013)
+ *
+ * AMD RAPL interface for Fam17h is described in the public PPR:
+ * https://bugzilla.kernel.org/show_bug.cgi?id=206537
+ *
+ * RAPL provides more controls than just reporting energy consumption
+ * however here we only expose the 3 energy consumption free running
+ * counters (pp0, pkg, dram).
+ *
+ * Each of those counters increments in a power unit defined by the
+ * RAPL_POWER_UNIT MSR. On SandyBridge, this unit is 1/(2^16) Joules
+ * but it can vary.
+ *
+ * Counter to rapl events mappings:
+ *
+ *  pp0 counter: consumption of all physical cores (power plane 0)
+ * 	  event: rapl_energy_cores
+ *    perf code: 0x1
+ *
+ *  pkg counter: consumption of the whole processor package
+ *	  event: rapl_energy_pkg
+ *    perf code: 0x2
+ *
+ * dram counter: consumption of the dram domain (servers only)
+ *	  event: rapl_energy_dram
+ *    perf code: 0x3
+ *
+ * gpu counter: consumption of the builtin-gpu domain (client only)
+ *	  event: rapl_energy_gpu
+ *    perf code: 0x4
+ *
+ *  psys counter: consumption of the builtin-psys domain (client only)
+ *	  event: rapl_energy_psys
+ *    perf code: 0x5
+ *
+ * We manage those counters as free running (read-only). They may be
+ * use simultaneously by other tools, such as turbostat.
+ *
+ * The events only support system-wide mode counting. There is no
+ * sampling support because it does not make sense and is not
+ * supported by the RAPL hardware.
+ *
+ * Because we want to avoid floating-point operations in the kernel,
+ * the events are all reported in fixed point arithmetic (32.32).
+ * Tools must adjust the counts to convert them to Watts using
+ * the duration of the measurement. Tools may use a function such as
+ * ldexp(raw_count, -32);
+ */
+
+#define pr_fmt(fmt) "RAPL PMU: " fmt
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/perf_event.h>
+#include <linux/nospec.h>
+#include <asm/cpu_device_id.h>
+#include <asm/intel-family.h>
+#include "perf_event.h"
+#include "probe.h"
+
+MODULE_LICENSE("GPL");
+
+/*
+ * RAPL energy status counters
+ */
+enum perf_rapl_events {
+	PERF_RAPL_PP0 = 0,		/* all cores */
+	PERF_RAPL_PKG,			/* entire package */
+	PERF_RAPL_RAM,			/* DRAM */
+	PERF_RAPL_PP1,			/* gpu */
+	PERF_RAPL_PSYS,			/* psys */
+
+	PERF_RAPL_MAX,
+	NR_RAPL_DOMAINS = PERF_RAPL_MAX,
+};
+
+static const char *const rapl_domain_names[NR_RAPL_DOMAINS] __initconst = {
+	"pp0-core",
+	"package",
+	"dram",
+	"pp1-gpu",
+	"psys",
+};
+
+/*
+ * event code: LSB 8 bits, passed in attr->config
+ * any other bit is reserved
+ */
+#define RAPL_EVENT_MASK	0xFFULL
+#define RAPL_CNTR_WIDTH 32
+
+#define RAPL_EVENT_ATTR_STR(_name, v, str)					\
+static struct perf_pmu_events_attr event_attr_##v = {				\
+	.attr		= __ATTR(_name, 0444, perf_event_sysfs_show, NULL),	\
+	.id		= 0,							\
+	.event_str	= str,							\
+};
+
+struct rapl_pmu {
+	raw_spinlock_t		lock;
+	int			n_active;
+	int			cpu;
+	struct list_head	active_list;
+	struct pmu		*pmu;
+	ktime_t			timer_interval;
+	struct hrtimer		hrtimer;
+};
+
+struct rapl_pmus {
+	struct pmu		pmu;
+	unsigned int		maxdie;
+	struct rapl_pmu		*pmus[];
+};
+
+struct rapl_model {
+	unsigned long	events;
+	bool		apply_quirk;
+};
+
+ /* 1/2^hw_unit Joule */
+static int rapl_hw_unit[NR_RAPL_DOMAINS] __read_mostly;
+static struct rapl_pmus *rapl_pmus;
+static cpumask_t rapl_cpu_mask;
+static unsigned int rapl_cntr_mask;
+static u64 rapl_timer_ms;
+static struct perf_msr rapl_msrs[];
+
+static inline struct rapl_pmu *cpu_to_rapl_pmu(unsigned int cpu)
+{
+	unsigned int dieid = topology_logical_die_id(cpu);
+
+	/*
+	 * The unsigned check also catches the '-1' return value for non
+	 * existent mappings in the topology map.
+	 */
+	return dieid < rapl_pmus->maxdie ? rapl_pmus->pmus[dieid] : NULL;
+}
+
+static inline u64 rapl_read_counter(struct perf_event *event)
+{
+	u64 raw;
+	rdmsrl(event->hw.event_base, raw);
+	return raw;
+}
+
+static inline u64 rapl_scale(u64 v, int cfg)
+{
+	if (cfg > NR_RAPL_DOMAINS) {
+		pr_warn("Invalid domain %d, failed to scale data\n", cfg);
+		return v;
+	}
+	/*
+	 * scale delta to smallest unit (1/2^32)
+	 * users must then scale back: count * 1/(1e9*2^32) to get Joules
+	 * or use ldexp(count, -32).
+	 * Watts = Joules/Time delta
+	 */
+	return v << (32 - rapl_hw_unit[cfg - 1]);
+}
+
+static u64 rapl_event_update(struct perf_event *event)
+{
+	struct hw_perf_event *hwc = &event->hw;
+	u64 prev_raw_count, new_raw_count;
+	s64 delta, sdelta;
+	int shift = RAPL_CNTR_WIDTH;
+
+again:
+	prev_raw_count = local64_read(&hwc->prev_count);
+	rdmsrl(event->hw.event_base, new_raw_count);
+
+	if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
+			    new_raw_count) != prev_raw_count) {
+		cpu_relax();
+		goto again;
+	}
+
+	/*
+	 * Now we have the new raw value and have updated the prev
+	 * timestamp already. We can now calculate the elapsed delta
+	 * (event-)time and add that to the generic event.
+	 *
+	 * Careful, not all hw sign-extends above the physical width
+	 * of the count.
+	 */
+	delta = (new_raw_count << shift) - (prev_raw_count << shift);
+	delta >>= shift;
+
+	sdelta = rapl_scale(delta, event->hw.config);
+
+	local64_add(sdelta, &event->count);
+
+	return new_raw_count;
+}
+
+static void rapl_start_hrtimer(struct rapl_pmu *pmu)
+{
+       hrtimer_start(&pmu->hrtimer, pmu->timer_interval,
+		     HRTIMER_MODE_REL_PINNED);
+}
+
+static enum hrtimer_restart rapl_hrtimer_handle(struct hrtimer *hrtimer)
+{
+	struct rapl_pmu *pmu = container_of(hrtimer, struct rapl_pmu, hrtimer);
+	struct perf_event *event;
+	unsigned long flags;
+
+	if (!pmu->n_active)
+		return HRTIMER_NORESTART;
+
+	raw_spin_lock_irqsave(&pmu->lock, flags);
+
+	list_for_each_entry(event, &pmu->active_list, active_entry)
+		rapl_event_update(event);
+
+	raw_spin_unlock_irqrestore(&pmu->lock, flags);
+
+	hrtimer_forward_now(hrtimer, pmu->timer_interval);
+
+	return HRTIMER_RESTART;
+}
+
+static void rapl_hrtimer_init(struct rapl_pmu *pmu)
+{
+	struct hrtimer *hr = &pmu->hrtimer;
+
+	hrtimer_init(hr, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+	hr->function = rapl_hrtimer_handle;
+}
+
+static void __rapl_pmu_event_start(struct rapl_pmu *pmu,
+				   struct perf_event *event)
+{
+	if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED)))
+		return;
+
+	event->hw.state = 0;
+
+	list_add_tail(&event->active_entry, &pmu->active_list);
+
+	local64_set(&event->hw.prev_count, rapl_read_counter(event));
+
+	pmu->n_active++;
+	if (pmu->n_active == 1)
+		rapl_start_hrtimer(pmu);
+}
+
+static void rapl_pmu_event_start(struct perf_event *event, int mode)
+{
+	struct rapl_pmu *pmu = event->pmu_private;
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&pmu->lock, flags);
+	__rapl_pmu_event_start(pmu, event);
+	raw_spin_unlock_irqrestore(&pmu->lock, flags);
+}
+
+static void rapl_pmu_event_stop(struct perf_event *event, int mode)
+{
+	struct rapl_pmu *pmu = event->pmu_private;
+	struct hw_perf_event *hwc = &event->hw;
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&pmu->lock, flags);
+
+	/* mark event as deactivated and stopped */
+	if (!(hwc->state & PERF_HES_STOPPED)) {
+		WARN_ON_ONCE(pmu->n_active <= 0);
+		pmu->n_active--;
+		if (pmu->n_active == 0)
+			hrtimer_cancel(&pmu->hrtimer);
+
+		list_del(&event->active_entry);
+
+		WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
+		hwc->state |= PERF_HES_STOPPED;
+	}
+
+	/* check if update of sw counter is necessary */
+	if ((mode & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
+		/*
+		 * Drain the remaining delta count out of a event
+		 * that we are disabling:
+		 */
+		rapl_event_update(event);
+		hwc->state |= PERF_HES_UPTODATE;
+	}
+
+	raw_spin_unlock_irqrestore(&pmu->lock, flags);
+}
+
+static int rapl_pmu_event_add(struct perf_event *event, int mode)
+{
+	struct rapl_pmu *pmu = event->pmu_private;
+	struct hw_perf_event *hwc = &event->hw;
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&pmu->lock, flags);
+
+	hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
+
+	if (mode & PERF_EF_START)
+		__rapl_pmu_event_start(pmu, event);
+
+	raw_spin_unlock_irqrestore(&pmu->lock, flags);
+
+	return 0;
+}
+
+static void rapl_pmu_event_del(struct perf_event *event, int flags)
+{
+	rapl_pmu_event_stop(event, PERF_EF_UPDATE);
+}
+
+static int rapl_pmu_event_init(struct perf_event *event)
+{
+	u64 cfg = event->attr.config & RAPL_EVENT_MASK;
+	int bit, ret = 0;
+	struct rapl_pmu *pmu;
+
+	/* only look at RAPL events */
+	if (event->attr.type != rapl_pmus->pmu.type)
+		return -ENOENT;
+
+	/* check only supported bits are set */
+	if (event->attr.config & ~RAPL_EVENT_MASK)
+		return -EINVAL;
+
+	if (event->cpu < 0)
+		return -EINVAL;
+
+	event->event_caps |= PERF_EV_CAP_READ_ACTIVE_PKG;
+
+	if (!cfg || cfg >= NR_RAPL_DOMAINS + 1)
+		return -EINVAL;
+
+	cfg = array_index_nospec((long)cfg, NR_RAPL_DOMAINS + 1);
+	bit = cfg - 1;
+
+	/* check event supported */
+	if (!(rapl_cntr_mask & (1 << bit)))
+		return -EINVAL;
+
+	/* unsupported modes and filters */
+	if (event->attr.sample_period) /* no sampling */
+		return -EINVAL;
+
+	/* must be done before validate_group */
+	pmu = cpu_to_rapl_pmu(event->cpu);
+	if (!pmu)
+		return -EINVAL;
+	event->cpu = pmu->cpu;
+	event->pmu_private = pmu;
+	event->hw.event_base = rapl_msrs[bit].msr;
+	event->hw.config = cfg;
+	event->hw.idx = bit;
+
+	return ret;
+}
+
+static void rapl_pmu_event_read(struct perf_event *event)
+{
+	rapl_event_update(event);
+}
+
+static ssize_t rapl_get_attr_cpumask(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	return cpumap_print_to_pagebuf(true, buf, &rapl_cpu_mask);
+}
+
+static DEVICE_ATTR(cpumask, S_IRUGO, rapl_get_attr_cpumask, NULL);
+
+static struct attribute *rapl_pmu_attrs[] = {
+	&dev_attr_cpumask.attr,
+	NULL,
+};
+
+static struct attribute_group rapl_pmu_attr_group = {
+	.attrs = rapl_pmu_attrs,
+};
+
+RAPL_EVENT_ATTR_STR(energy-cores, rapl_cores, "event=0x01");
+RAPL_EVENT_ATTR_STR(energy-pkg  ,   rapl_pkg, "event=0x02");
+RAPL_EVENT_ATTR_STR(energy-ram  ,   rapl_ram, "event=0x03");
+RAPL_EVENT_ATTR_STR(energy-gpu  ,   rapl_gpu, "event=0x04");
+RAPL_EVENT_ATTR_STR(energy-psys,   rapl_psys, "event=0x05");
+
+RAPL_EVENT_ATTR_STR(energy-cores.unit, rapl_cores_unit, "Joules");
+RAPL_EVENT_ATTR_STR(energy-pkg.unit  ,   rapl_pkg_unit, "Joules");
+RAPL_EVENT_ATTR_STR(energy-ram.unit  ,   rapl_ram_unit, "Joules");
+RAPL_EVENT_ATTR_STR(energy-gpu.unit  ,   rapl_gpu_unit, "Joules");
+RAPL_EVENT_ATTR_STR(energy-psys.unit,   rapl_psys_unit, "Joules");
+
+/*
+ * we compute in 0.23 nJ increments regardless of MSR
+ */
+RAPL_EVENT_ATTR_STR(energy-cores.scale, rapl_cores_scale, "2.3283064365386962890625e-10");
+RAPL_EVENT_ATTR_STR(energy-pkg.scale,     rapl_pkg_scale, "2.3283064365386962890625e-10");
+RAPL_EVENT_ATTR_STR(energy-ram.scale,     rapl_ram_scale, "2.3283064365386962890625e-10");
+RAPL_EVENT_ATTR_STR(energy-gpu.scale,     rapl_gpu_scale, "2.3283064365386962890625e-10");
+RAPL_EVENT_ATTR_STR(energy-psys.scale,   rapl_psys_scale, "2.3283064365386962890625e-10");
+
+/*
+ * There are no default events, but we need to create
+ * "events" group (with empty attrs) before updating
+ * it with detected events.
+ */
+static struct attribute *attrs_empty[] = {
+	NULL,
+};
+
+static struct attribute_group rapl_pmu_events_group = {
+	.name = "events",
+	.attrs = attrs_empty,
+};
+
+PMU_FORMAT_ATTR(event, "config:0-7");
+static struct attribute *rapl_formats_attr[] = {
+	&format_attr_event.attr,
+	NULL,
+};
+
+static struct attribute_group rapl_pmu_format_group = {
+	.name = "format",
+	.attrs = rapl_formats_attr,
+};
+
+static const struct attribute_group *rapl_attr_groups[] = {
+	&rapl_pmu_attr_group,
+	&rapl_pmu_format_group,
+	&rapl_pmu_events_group,
+	NULL,
+};
+
+static struct attribute *rapl_events_cores[] = {
+	EVENT_PTR(rapl_cores),
+	EVENT_PTR(rapl_cores_unit),
+	EVENT_PTR(rapl_cores_scale),
+	NULL,
+};
+
+static struct attribute_group rapl_events_cores_group = {
+	.name  = "events",
+	.attrs = rapl_events_cores,
+};
+
+static struct attribute *rapl_events_pkg[] = {
+	EVENT_PTR(rapl_pkg),
+	EVENT_PTR(rapl_pkg_unit),
+	EVENT_PTR(rapl_pkg_scale),
+	NULL,
+};
+
+static struct attribute_group rapl_events_pkg_group = {
+	.name  = "events",
+	.attrs = rapl_events_pkg,
+};
+
+static struct attribute *rapl_events_ram[] = {
+	EVENT_PTR(rapl_ram),
+	EVENT_PTR(rapl_ram_unit),
+	EVENT_PTR(rapl_ram_scale),
+	NULL,
+};
+
+static struct attribute_group rapl_events_ram_group = {
+	.name  = "events",
+	.attrs = rapl_events_ram,
+};
+
+static struct attribute *rapl_events_gpu[] = {
+	EVENT_PTR(rapl_gpu),
+	EVENT_PTR(rapl_gpu_unit),
+	EVENT_PTR(rapl_gpu_scale),
+	NULL,
+};
+
+static struct attribute_group rapl_events_gpu_group = {
+	.name  = "events",
+	.attrs = rapl_events_gpu,
+};
+
+static struct attribute *rapl_events_psys[] = {
+	EVENT_PTR(rapl_psys),
+	EVENT_PTR(rapl_psys_unit),
+	EVENT_PTR(rapl_psys_scale),
+	NULL,
+};
+
+static struct attribute_group rapl_events_psys_group = {
+	.name  = "events",
+	.attrs = rapl_events_psys,
+};
+
+static bool test_msr(int idx, void *data)
+{
+	return test_bit(idx, (unsigned long *) data);
+}
+
+static struct perf_msr rapl_msrs[] = {
+	[PERF_RAPL_PP0]  = { MSR_PP0_ENERGY_STATUS,      &rapl_events_cores_group, test_msr },
+	[PERF_RAPL_PKG]  = { MSR_PKG_ENERGY_STATUS,      &rapl_events_pkg_group,   test_msr },
+	[PERF_RAPL_RAM]  = { MSR_DRAM_ENERGY_STATUS,     &rapl_events_ram_group,   test_msr },
+	[PERF_RAPL_PP1]  = { MSR_PP1_ENERGY_STATUS,      &rapl_events_gpu_group,   test_msr },
+	[PERF_RAPL_PSYS] = { MSR_PLATFORM_ENERGY_STATUS, &rapl_events_psys_group,  test_msr },
+};
+
+static int rapl_cpu_offline(unsigned int cpu)
+{
+	struct rapl_pmu *pmu = cpu_to_rapl_pmu(cpu);
+	int target;
+
+	/* Check if exiting cpu is used for collecting rapl events */
+	if (!cpumask_test_and_clear_cpu(cpu, &rapl_cpu_mask))
+		return 0;
+
+	pmu->cpu = -1;
+	/* Find a new cpu to collect rapl events */
+	target = cpumask_any_but(topology_die_cpumask(cpu), cpu);
+
+	/* Migrate rapl events to the new target */
+	if (target < nr_cpu_ids) {
+		cpumask_set_cpu(target, &rapl_cpu_mask);
+		pmu->cpu = target;
+		perf_pmu_migrate_context(pmu->pmu, cpu, target);
+	}
+	return 0;
+}
+
+static int rapl_cpu_online(unsigned int cpu)
+{
+	struct rapl_pmu *pmu = cpu_to_rapl_pmu(cpu);
+	int target;
+
+	if (!pmu) {
+		pmu = kzalloc_node(sizeof(*pmu), GFP_KERNEL, cpu_to_node(cpu));
+		if (!pmu)
+			return -ENOMEM;
+
+		raw_spin_lock_init(&pmu->lock);
+		INIT_LIST_HEAD(&pmu->active_list);
+		pmu->pmu = &rapl_pmus->pmu;
+		pmu->timer_interval = ms_to_ktime(rapl_timer_ms);
+		rapl_hrtimer_init(pmu);
+
+		rapl_pmus->pmus[topology_logical_die_id(cpu)] = pmu;
+	}
+
+	/*
+	 * Check if there is an online cpu in the package which collects rapl
+	 * events already.
+	 */
+	target = cpumask_any_and(&rapl_cpu_mask, topology_die_cpumask(cpu));
+	if (target < nr_cpu_ids)
+		return 0;
+
+	cpumask_set_cpu(cpu, &rapl_cpu_mask);
+	pmu->cpu = cpu;
+	return 0;
+}
+
+static int rapl_check_hw_unit(bool apply_quirk)
+{
+	u64 msr_rapl_power_unit_bits;
+	int i;
+
+	/* protect rdmsrl() to handle virtualization */
+	if (rdmsrl_safe(MSR_RAPL_POWER_UNIT, &msr_rapl_power_unit_bits))
+		return -1;
+	for (i = 0; i < NR_RAPL_DOMAINS; i++)
+		rapl_hw_unit[i] = (msr_rapl_power_unit_bits >> 8) & 0x1FULL;
+
+	/*
+	 * DRAM domain on HSW server and KNL has fixed energy unit which can be
+	 * different than the unit from power unit MSR. See
+	 * "Intel Xeon Processor E5-1600 and E5-2600 v3 Product Families, V2
+	 * of 2. Datasheet, September 2014, Reference Number: 330784-001 "
+	 */
+	if (apply_quirk)
+		rapl_hw_unit[PERF_RAPL_RAM] = 16;
+
+	/*
+	 * Calculate the timer rate:
+	 * Use reference of 200W for scaling the timeout to avoid counter
+	 * overflows. 200W = 200 Joules/sec
+	 * Divide interval by 2 to avoid lockstep (2 * 100)
+	 * if hw unit is 32, then we use 2 ms 1/200/2
+	 */
+	rapl_timer_ms = 2;
+	if (rapl_hw_unit[0] < 32) {
+		rapl_timer_ms = (1000 / (2 * 100));
+		rapl_timer_ms *= (1ULL << (32 - rapl_hw_unit[0] - 1));
+	}
+	return 0;
+}
+
+static void __init rapl_advertise(void)
+{
+	int i;
+
+	pr_info("API unit is 2^-32 Joules, %d fixed counters, %llu ms ovfl timer\n",
+		hweight32(rapl_cntr_mask), rapl_timer_ms);
+
+	for (i = 0; i < NR_RAPL_DOMAINS; i++) {
+		if (rapl_cntr_mask & (1 << i)) {
+			pr_info("hw unit of domain %s 2^-%d Joules\n",
+				rapl_domain_names[i], rapl_hw_unit[i]);
+		}
+	}
+}
+
+static void cleanup_rapl_pmus(void)
+{
+	int i;
+
+	for (i = 0; i < rapl_pmus->maxdie; i++)
+		kfree(rapl_pmus->pmus[i]);
+	kfree(rapl_pmus);
+}
+
+static const struct attribute_group *rapl_attr_update[] = {
+	&rapl_events_cores_group,
+	&rapl_events_pkg_group,
+	&rapl_events_ram_group,
+	&rapl_events_gpu_group,
+	&rapl_events_psys_group,
+	NULL,
+};
+
+static int __init init_rapl_pmus(void)
+{
+	int maxdie = topology_max_packages() * topology_max_die_per_package();
+	size_t size;
+
+	size = sizeof(*rapl_pmus) + maxdie * sizeof(struct rapl_pmu *);
+	rapl_pmus = kzalloc(size, GFP_KERNEL);
+	if (!rapl_pmus)
+		return -ENOMEM;
+
+	rapl_pmus->maxdie		= maxdie;
+	rapl_pmus->pmu.attr_groups	= rapl_attr_groups;
+	rapl_pmus->pmu.attr_update	= rapl_attr_update;
+	rapl_pmus->pmu.task_ctx_nr	= perf_invalid_context;
+	rapl_pmus->pmu.event_init	= rapl_pmu_event_init;
+	rapl_pmus->pmu.add		= rapl_pmu_event_add;
+	rapl_pmus->pmu.del		= rapl_pmu_event_del;
+	rapl_pmus->pmu.start		= rapl_pmu_event_start;
+	rapl_pmus->pmu.stop		= rapl_pmu_event_stop;
+	rapl_pmus->pmu.read		= rapl_pmu_event_read;
+	rapl_pmus->pmu.module		= THIS_MODULE;
+	rapl_pmus->pmu.capabilities	= PERF_PMU_CAP_NO_EXCLUDE;
+	return 0;
+}
+
+#define X86_RAPL_MODEL_MATCH(model, init)	\
+	{ X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long)&init }
+
+static struct rapl_model model_snb = {
+	.events		= BIT(PERF_RAPL_PP0) |
+			  BIT(PERF_RAPL_PKG) |
+			  BIT(PERF_RAPL_PP1),
+	.apply_quirk	= false,
+};
+
+static struct rapl_model model_snbep = {
+	.events		= BIT(PERF_RAPL_PP0) |
+			  BIT(PERF_RAPL_PKG) |
+			  BIT(PERF_RAPL_RAM),
+	.apply_quirk	= false,
+};
+
+static struct rapl_model model_hsw = {
+	.events		= BIT(PERF_RAPL_PP0) |
+			  BIT(PERF_RAPL_PKG) |
+			  BIT(PERF_RAPL_RAM) |
+			  BIT(PERF_RAPL_PP1),
+	.apply_quirk	= false,
+};
+
+static struct rapl_model model_hsx = {
+	.events		= BIT(PERF_RAPL_PP0) |
+			  BIT(PERF_RAPL_PKG) |
+			  BIT(PERF_RAPL_RAM),
+	.apply_quirk	= true,
+};
+
+static struct rapl_model model_knl = {
+	.events		= BIT(PERF_RAPL_PKG) |
+			  BIT(PERF_RAPL_RAM),
+	.apply_quirk	= true,
+};
+
+static struct rapl_model model_skl = {
+	.events		= BIT(PERF_RAPL_PP0) |
+			  BIT(PERF_RAPL_PKG) |
+			  BIT(PERF_RAPL_RAM) |
+			  BIT(PERF_RAPL_PP1) |
+			  BIT(PERF_RAPL_PSYS),
+	.apply_quirk	= false,
+};
+
+static const struct x86_cpu_id rapl_model_match[] __initconst = {
+	X86_RAPL_MODEL_MATCH(INTEL_FAM6_SANDYBRIDGE,		model_snb),
+	X86_RAPL_MODEL_MATCH(INTEL_FAM6_SANDYBRIDGE_X,		model_snbep),
+	X86_RAPL_MODEL_MATCH(INTEL_FAM6_IVYBRIDGE,		model_snb),
+	X86_RAPL_MODEL_MATCH(INTEL_FAM6_IVYBRIDGE_X,		model_snbep),
+	X86_RAPL_MODEL_MATCH(INTEL_FAM6_HASWELL,		model_hsw),
+	X86_RAPL_MODEL_MATCH(INTEL_FAM6_HASWELL_X,		model_hsx),
+	X86_RAPL_MODEL_MATCH(INTEL_FAM6_HASWELL_L,		model_hsw),
+	X86_RAPL_MODEL_MATCH(INTEL_FAM6_HASWELL_G,		model_hsw),
+	X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL,		model_hsw),
+	X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_G,		model_hsw),
+	X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_X,		model_hsx),
+	X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_D,		model_hsx),
+	X86_RAPL_MODEL_MATCH(INTEL_FAM6_XEON_PHI_KNL,		model_knl),
+	X86_RAPL_MODEL_MATCH(INTEL_FAM6_XEON_PHI_KNM,		model_knl),
+	X86_RAPL_MODEL_MATCH(INTEL_FAM6_SKYLAKE_L,		model_skl),
+	X86_RAPL_MODEL_MATCH(INTEL_FAM6_SKYLAKE,		model_skl),
+	X86_RAPL_MODEL_MATCH(INTEL_FAM6_SKYLAKE_X,		model_hsx),
+	X86_RAPL_MODEL_MATCH(INTEL_FAM6_KABYLAKE_L,		model_skl),
+	X86_RAPL_MODEL_MATCH(INTEL_FAM6_KABYLAKE,		model_skl),
+	X86_RAPL_MODEL_MATCH(INTEL_FAM6_CANNONLAKE_L,		model_skl),
+	X86_RAPL_MODEL_MATCH(INTEL_FAM6_ATOM_GOLDMONT,		model_hsw),
+	X86_RAPL_MODEL_MATCH(INTEL_FAM6_ATOM_GOLDMONT_D,	model_hsw),
+	X86_RAPL_MODEL_MATCH(INTEL_FAM6_ATOM_GOLDMONT_PLUS,	model_hsw),
+	X86_RAPL_MODEL_MATCH(INTEL_FAM6_ICELAKE_L,		model_skl),
+	X86_RAPL_MODEL_MATCH(INTEL_FAM6_ICELAKE,		model_skl),
+	{},
+};
+
+MODULE_DEVICE_TABLE(x86cpu, rapl_model_match);
+
+static int __init rapl_pmu_init(void)
+{
+	const struct x86_cpu_id *id;
+	struct rapl_model *rm;
+	int ret;
+
+	id = x86_match_cpu(rapl_model_match);
+	if (!id)
+		return -ENODEV;
+
+	rm = (struct rapl_model *) id->driver_data;
+	rapl_cntr_mask = perf_msr_probe(rapl_msrs, PERF_RAPL_MAX,
+					false, (void *) &rm->events);
+
+	ret = rapl_check_hw_unit(rm->apply_quirk);
+	if (ret)
+		return ret;
+
+	ret = init_rapl_pmus();
+	if (ret)
+		return ret;
+
+	/*
+	 * Install callbacks. Core will call them for each online cpu.
+	 */
+	ret = cpuhp_setup_state(CPUHP_AP_PERF_X86_RAPL_ONLINE,
+				"perf/x86/rapl:online",
+				rapl_cpu_online, rapl_cpu_offline);
+	if (ret)
+		goto out;
+
+	ret = perf_pmu_register(&rapl_pmus->pmu, "power", -1);
+	if (ret)
+		goto out1;
+
+	rapl_advertise();
+	return 0;
+
+out1:
+	cpuhp_remove_state(CPUHP_AP_PERF_X86_RAPL_ONLINE);
+out:
+	pr_warn("Initialization failed (%d), disabled\n", ret);
+	cleanup_rapl_pmus();
+	return ret;
+}
+module_init(rapl_pmu_init);
+
+static void __exit intel_rapl_exit(void)
+{
+	cpuhp_remove_state_nocalls(CPUHP_AP_PERF_X86_RAPL_ONLINE);
+	perf_pmu_unregister(&rapl_pmus->pmu);
+	cleanup_rapl_pmus();
+}
+module_exit(intel_rapl_exit);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/hyperv/hv_init.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/hyperv/hv_init.c
@@ -19,9 +19,18 @@
 #include <linux/mm.h>
 #include <linux/hyperv.h>
 #include <linux/slab.h>
+#include <linux/kernel.h>
 #include <linux/cpuhotplug.h>
 #include <clocksource/hyperv_timer.h>
 
+#ifndef PKG_ABI
+/*
+ * Preserve the ability to 'make deb-pkg' since PKG_ABI is provided
+ * by the Ubuntu build rules.
+ */
+#define PKG_ABI 0
+#endif
+
 void *hv_hypercall_pg;
 EXPORT_SYMBOL_GPL(hv_hypercall_pg);
 
@@ -154,7 +163,6 @@
 	struct hv_reenlightenment_control re_ctrl = {
 		.vector = HYPERV_REENLIGHTENMENT_VECTOR,
 		.enabled = 1,
-		.target_vp = hv_vp_index[smp_processor_id()]
 	};
 	struct hv_tsc_emulation_control emu_ctrl = {.enabled = 1};
 
@@ -163,13 +171,20 @@
 		return;
 	}
 
+	if (!hv_vp_index)
+		return;
+
 	hv_reenlightenment_cb = cb;
 
 	/* Make sure callback is registered before we write to MSRs */
 	wmb();
 
+	re_ctrl.target_vp = hv_vp_index[get_cpu()];
+
 	wrmsrl(HV_X64_MSR_REENLIGHTENMENT_CONTROL, *((u64 *)&re_ctrl));
 	wrmsrl(HV_X64_MSR_TSC_EMULATION_CONTROL, *((u64 *)&emu_ctrl));
+
+	put_cpu();
 }
 EXPORT_SYMBOL_GPL(set_hv_tscchange_cb);
 
@@ -297,7 +312,7 @@
 	 * 1. Register the guest ID
 	 * 2. Enable the hypercall and register the hypercall page
 	 */
-	guest_id = generate_guest_id(0, LINUX_VERSION_CODE, 0);
+	guest_id = generate_guest_id(0x80 /*Canonical*/, LINUX_VERSION_CODE, PKG_ABI);
 	wrmsrl(HV_X64_MSR_GUEST_OS_ID, guest_id);
 
 	hv_hypercall_pg  = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_RX);
@@ -354,11 +369,14 @@
 }
 EXPORT_SYMBOL_GPL(hyperv_cleanup);
 
-void hyperv_report_panic(struct pt_regs *regs, long err)
+void hyperv_report_panic(struct pt_regs *regs, long err, bool in_die)
 {
 	static bool panic_reported;
 	u64 guest_id;
 
+	if (in_die && !panic_on_oops)
+		return;
+
 	/*
 	 * We prefer to report panic on 'die' chain as we have proper
 	 * registers to report, but if we miss it (e.g. on BUG()) we need
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/hyperv/mmu.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/hyperv/mmu.c
@@ -66,11 +66,17 @@
 	if (!hv_hypercall_pg)
 		goto do_native;
 
-	if (cpumask_empty(cpus))
-		return;
-
 	local_irq_save(flags);
 
+	/*
+	 * Only check the mask _after_ interrupt has been disabled to avoid the
+	 * mask changing under our feet.
+	 */
+	if (cpumask_empty(cpus)) {
+		local_irq_restore(flags);
+		return;
+	}
+
 	flush_pcpu = (struct hv_tlb_flush **)
 		     this_cpu_ptr(hyperv_pcpu_input_arg);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/ia32/ia32_aout.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/ia32/ia32_aout.c
@@ -140,6 +140,7 @@
 	set_personality_ia32(false);
 
 	setup_new_exec(bprm);
+	install_exec_creds(bprm);
 
 	regs->cs = __USER32_CS;
 	regs->r8 = regs->r9 = regs->r10 = regs->r11 = regs->r12 =
@@ -156,8 +157,6 @@
 	if (retval < 0)
 		return retval;
 
-	install_exec_creds(bprm);
-
 	if (N_MAGIC(ex) == OMAGIC) {
 		unsigned long text_addr, map_size;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/ia32/ia32_signal.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/ia32/ia32_signal.c
@@ -21,6 +21,7 @@
 #include <linux/personality.h>
 #include <linux/compat.h>
 #include <linux/binfmts.h>
+#include <linux/syscalls.h>
 #include <asm/ucontext.h>
 #include <linux/uaccess.h>
 #include <asm/fpu/internal.h>
@@ -118,7 +119,7 @@
 	return err;
 }
 
-asmlinkage long sys32_sigreturn(void)
+COMPAT_SYSCALL_DEFINE0(sigreturn)
 {
 	struct pt_regs *regs = current_pt_regs();
 	struct sigframe_ia32 __user *frame = (struct sigframe_ia32 __user *)(regs->sp-8);
@@ -144,7 +145,7 @@
 	return 0;
 }
 
-asmlinkage long sys32_rt_sigreturn(void)
+COMPAT_SYSCALL_DEFINE0(rt_sigreturn)
 {
 	struct pt_regs *regs = current_pt_regs();
 	struct rt_sigframe_ia32 __user *frame;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/Kbuild
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/Kbuild
@@ -7,7 +7,6 @@
 generated-y += unistd_64_x32.h
 generated-y += xen-hypercalls.h
 
-generic-y += dma-contiguous.h
 generic-y += early_ioremap.h
 generic-y += export.h
 generic-y += mcs_spinlock.h
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/acenv.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/acenv.h
@@ -13,7 +13,19 @@
 
 /* Asm macros */
 
-#define ACPI_FLUSH_CPU_CACHE()	wbinvd()
+/*
+ * ACPI_FLUSH_CPU_CACHE() flushes caches on entering sleep states.
+ * It is required to prevent data loss.
+ *
+ * While running inside virtual machine, the kernel can bypass cache flushing.
+ * Changing sleep state in a virtual machine doesn't affect the host system
+ * sleep state and cannot lead to data loss.
+ */
+#define ACPI_FLUSH_CPU_CACHE()					\
+do {								\
+	if (!cpu_feature_enabled(X86_FEATURE_HYPERVISOR))	\
+		wbinvd();					\
+} while (0)
 
 int __acpi_acquire_global_lock(unsigned int *lock);
 int __acpi_release_global_lock(unsigned int *lock);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/amd_nb.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/amd_nb.h
@@ -118,7 +118,10 @@
 
 #define amd_nb_num(x)		0
 #define amd_nb_has_feature(x)	false
-#define node_to_amd_nb(x)	NULL
+static inline struct amd_northbridge *node_to_amd_nb(int node)
+{
+	return NULL;
+}
 #define amd_gart_present(x)	false
 
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/apic.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/apic.h
@@ -12,6 +12,7 @@
 #include <asm/mpspec.h>
 #include <asm/msr.h>
 #include <asm/hardirq.h>
+#include <asm/io.h>
 
 #define ARCH_APICTIMER_STOPS_ON_C3	1
 
@@ -111,7 +112,7 @@
 
 static inline u32 native_apic_mem_read(u32 reg)
 {
-	return *((volatile u32 *)(APIC_BASE + reg));
+	return readl((void __iomem *)(APIC_BASE + reg));
 }
 
 extern void native_apic_wait_icr_idle(void);
@@ -140,6 +141,7 @@
 extern void lapic_shutdown(void);
 extern void sync_Arb_IDs(void);
 extern void init_bsp_APIC(void);
+extern void apic_intr_mode_select(void);
 extern void apic_intr_mode_init(void);
 extern void init_apic_mappings(void);
 void register_lapic_address(unsigned long address);
@@ -173,6 +175,7 @@
 extern int setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask);
 extern void lapic_assign_system_vectors(void);
 extern void lapic_assign_legacy_vector(unsigned int isairq, bool replace);
+extern void lapic_update_legacy_vectors(void);
 extern void lapic_online(void);
 extern void lapic_offline(void);
 extern bool apic_needs_pit(void);
@@ -188,6 +191,7 @@
 # define setup_secondary_APIC_clock x86_init_noop
 static inline void lapic_update_tsc_freq(void) { }
 static inline void init_bsp_APIC(void) { }
+static inline void apic_intr_mode_select(void) { }
 static inline void apic_intr_mode_init(void) { }
 static inline void lapic_assign_system_vectors(void) { }
 static inline void lapic_assign_legacy_vector(unsigned int i, bool r) { }
@@ -195,16 +199,6 @@
 #endif /* !CONFIG_X86_LOCAL_APIC */
 
 #ifdef CONFIG_X86_X2APIC
-/*
- * Make previous memory operations globally visible before
- * sending the IPI through x2apic wrmsr. We need a serializing instruction or
- * mfence for this.
- */
-static inline void x2apic_wrmsr_fence(void)
-{
-	asm volatile("mfence" : : : "memory");
-}
-
 static inline void native_apic_msr_write(u32 reg, u32 v)
 {
 	if (reg == APIC_DFR || reg == APIC_ID || reg == APIC_LDR ||
@@ -257,6 +251,7 @@
 
 extern int x2apic_mode;
 extern int x2apic_phys;
+extern void __init x2apic_set_max_apicid(u32 apicid);
 extern void __init check_x2apic(void);
 extern void x2apic_setup(void);
 static inline int x2apic_enabled(void)
@@ -452,6 +447,14 @@
 	apic_eoi();
 }
 
+
+static inline bool lapic_vector_set_in_irr(unsigned int vector)
+{
+	u32 irr = apic_read(APIC_IRR + (vector / 32 * 0x10));
+
+	return !!(irr & (1U << (vector % 32)));
+}
+
 static inline unsigned default_get_apic_id(unsigned long x)
 {
 	unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR));
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/apm.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/apm.h
@@ -35,6 +35,7 @@
 	__asm__ __volatile__(APM_DO_ZERO_SEGS
 		"pushl %%edi\n\t"
 		"pushl %%ebp\n\t"
+		ANNOTATE_RETPOLINE_SAFE /* FRBS */
 		"lcall *%%cs:apm_bios_entry\n\t"
 		"setc %%al\n\t"
 		"popl %%ebp\n\t"
@@ -59,6 +60,7 @@
 	__asm__ __volatile__(APM_DO_ZERO_SEGS
 		"pushl %%edi\n\t"
 		"pushl %%ebp\n\t"
+		ANNOTATE_RETPOLINE_SAFE /* FRBS */
 		"lcall *%%cs:apm_bios_entry\n\t"
 		"setc %%bl\n\t"
 		"popl %%ebp\n\t"
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/archrandom.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/archrandom.h
@@ -73,10 +73,6 @@
 	return ok;
 }
 
-/* Conditional execution based on CPU type */
-#define arch_has_random()	static_cpu_has(X86_FEATURE_RDRAND)
-#define arch_has_random_seed()	static_cpu_has(X86_FEATURE_RDSEED)
-
 /*
  * These are the generic interfaces; they must not be declared if the
  * stubs in <linux/random.h> are to be invoked,
@@ -86,22 +82,22 @@
 
 static inline bool arch_get_random_long(unsigned long *v)
 {
-	return arch_has_random() ? rdrand_long(v) : false;
+	return static_cpu_has(X86_FEATURE_RDRAND) ? rdrand_long(v) : false;
 }
 
 static inline bool arch_get_random_int(unsigned int *v)
 {
-	return arch_has_random() ? rdrand_int(v) : false;
+	return static_cpu_has(X86_FEATURE_RDRAND) ? rdrand_int(v) : false;
 }
 
 static inline bool arch_get_random_seed_long(unsigned long *v)
 {
-	return arch_has_random_seed() ? rdseed_long(v) : false;
+	return static_cpu_has(X86_FEATURE_RDSEED) ? rdseed_long(v) : false;
 }
 
 static inline bool arch_get_random_seed_int(unsigned int *v)
 {
-	return arch_has_random_seed() ? rdseed_int(v) : false;
+	return static_cpu_has(X86_FEATURE_RDSEED) ? rdseed_int(v) : false;
 }
 
 extern void x86_init_rdrand(struct cpuinfo_x86 *c);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/asm.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/asm.h
@@ -7,9 +7,11 @@
 # define __ASM_FORM_RAW(x)     x
 # define __ASM_FORM_COMMA(x) x,
 #else
-# define __ASM_FORM(x)	" " #x " "
-# define __ASM_FORM_RAW(x)     #x
-# define __ASM_FORM_COMMA(x) " " #x ","
+#include <linux/stringify.h>
+
+# define __ASM_FORM(x)	" " __stringify(x) " "
+# define __ASM_FORM_RAW(x)     __stringify(x)
+# define __ASM_FORM_COMMA(x) " " __stringify(x) ","
 #endif
 
 #ifndef __x86_64__
@@ -139,9 +141,6 @@
 # define _ASM_EXTABLE_EX(from, to)				\
 	_ASM_EXTABLE_HANDLE(from, to, ex_handler_ext)
 
-# define _ASM_EXTABLE_REFCOUNT(from, to)			\
-	_ASM_EXTABLE_HANDLE(from, to, ex_handler_refcount)
-
 # define _ASM_NOKPROBE(entry)					\
 	.pushsection "_kprobe_blacklist","aw" ;			\
 	_ASM_ALIGN ;						\
@@ -170,9 +169,6 @@
 # define _ASM_EXTABLE_EX(from, to)				\
 	_ASM_EXTABLE_HANDLE(from, to, ex_handler_ext)
 
-# define _ASM_EXTABLE_REFCOUNT(from, to)			\
-	_ASM_EXTABLE_HANDLE(from, to, ex_handler_refcount)
-
 /* For C file, we already have NOKPROBE_SYMBOL macro */
 #endif
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/barrier.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/barrier.h
@@ -84,4 +84,22 @@
 
 #include <asm-generic/barrier.h>
 
+/*
+ * Make previous memory operations globally visible before
+ * a WRMSR.
+ *
+ * MFENCE makes writes visible, but only affects load/store
+ * instructions.  WRMSR is unfortunately not a load/store
+ * instruction and is unaffected by MFENCE.  The LFENCE ensures
+ * that the WRMSR is not reordered.
+ *
+ * Most WRMSRs are full serializing instructions themselves and
+ * do not require this barrier.  This is only required for the
+ * IA32_TSC_DEADLINE and X2APIC MSRs.
+ */
+static inline void weak_wrmsr_fence(void)
+{
+	asm volatile("mfence; lfence" : : : "memory");
+}
+
 #endif /* _ASM_X86_BARRIER_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/bugs.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/bugs.h
@@ -4,8 +4,6 @@
 
 #include <asm/processor.h>
 
-extern void check_bugs(void);
-
 #if defined(CONFIG_CPU_SUP_INTEL)
 void check_mpx_erratum(struct cpuinfo_x86 *c);
 #else
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/cacheinfo.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/cacheinfo.h
@@ -2,7 +2,7 @@
 #ifndef _ASM_X86_CACHEINFO_H
 #define _ASM_X86_CACHEINFO_H
 
-void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, int cpu, u8 node_id);
-void cacheinfo_hygon_init_llc_id(struct cpuinfo_x86 *c, int cpu, u8 node_id);
+void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, int cpu);
+void cacheinfo_hygon_init_llc_id(struct cpuinfo_x86 *c, int cpu);
 
 #endif /* _ASM_X86_CACHEINFO_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/compat.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/compat.h
@@ -31,15 +31,13 @@
 typedef u64 __attribute__((aligned(4))) compat_u64;
 
 struct compat_stat {
-	compat_dev_t	st_dev;
-	u16		__pad1;
+	u32		st_dev;
 	compat_ino_t	st_ino;
 	compat_mode_t	st_mode;
 	compat_nlink_t	st_nlink;
 	__compat_uid_t	st_uid;
 	__compat_gid_t	st_gid;
-	compat_dev_t	st_rdev;
-	u16		__pad2;
+	u32		st_rdev;
 	u32		st_size;
 	u32		st_blksize;
 	u32		st_blocks;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/cpu_device_id.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/cpu_device_id.h
@@ -5,9 +5,163 @@
 /*
  * Declare drivers belonging to specific x86 CPUs
  * Similar in spirit to pci_device_id and related PCI functions
+ *
+ * The wildcard initializers are in mod_devicetable.h because
+ * file2alias needs them. Sigh.
  */
-
 #include <linux/mod_devicetable.h>
+/* Get the INTEL_FAM* model defines */
+#include <asm/intel-family.h>
+/* And the X86_VENDOR_* ones */
+#include <asm/processor.h>
+
+/* Centaur FAM6 models */
+#define X86_CENTAUR_FAM6_C7_A		0xa
+#define X86_CENTAUR_FAM6_C7_D		0xd
+#define X86_CENTAUR_FAM6_NANO		0xf
+
+#define X86_STEPPINGS(mins, maxs)    GENMASK(maxs, mins)
+/**
+ * X86_MATCH_VENDOR_FAM_MODEL_STEPPINGS_FEATURE - Base macro for CPU matching
+ * @_vendor:	The vendor name, e.g. INTEL, AMD, HYGON, ..., ANY
+ *		The name is expanded to X86_VENDOR_@_vendor
+ * @_family:	The family number or X86_FAMILY_ANY
+ * @_model:	The model number, model constant or X86_MODEL_ANY
+ * @_steppings:	Bitmask for steppings, stepping constant or X86_STEPPING_ANY
+ * @_feature:	A X86_FEATURE bit or X86_FEATURE_ANY
+ * @_data:	Driver specific data or NULL. The internal storage
+ *		format is unsigned long. The supplied value, pointer
+ *		etc. is casted to unsigned long internally.
+ *
+ * Use only if you need all selectors. Otherwise use one of the shorter
+ * macros of the X86_MATCH_* family. If there is no matching shorthand
+ * macro, consider to add one. If you really need to wrap one of the macros
+ * into another macro at the usage site for good reasons, then please
+ * start this local macro with X86_MATCH to allow easy grepping.
+ */
+#define X86_MATCH_VENDOR_FAM_MODEL_STEPPINGS_FEATURE(_vendor, _family, _model, \
+						    _steppings, _feature, _data) { \
+	.vendor		= X86_VENDOR_##_vendor,				\
+	.family		= _family,					\
+	.model		= _model,					\
+	.steppings	= _steppings,					\
+	.feature	= _feature,					\
+	.driver_data	= (unsigned long) _data				\
+}
+
+/**
+ * X86_MATCH_VENDOR_FAM_MODEL_FEATURE - Macro for CPU matching
+ * @_vendor:	The vendor name, e.g. INTEL, AMD, HYGON, ..., ANY
+ *		The name is expanded to X86_VENDOR_@_vendor
+ * @_family:	The family number or X86_FAMILY_ANY
+ * @_model:	The model number, model constant or X86_MODEL_ANY
+ * @_feature:	A X86_FEATURE bit or X86_FEATURE_ANY
+ * @_data:	Driver specific data or NULL. The internal storage
+ *		format is unsigned long. The supplied value, pointer
+ *		etc. is casted to unsigned long internally.
+ *
+ * The steppings arguments of X86_MATCH_VENDOR_FAM_MODEL_STEPPINGS_FEATURE() is
+ * set to wildcards.
+ */
+#define X86_MATCH_VENDOR_FAM_MODEL_FEATURE(vendor, family, model, feature, data) \
+	X86_MATCH_VENDOR_FAM_MODEL_STEPPINGS_FEATURE(vendor, family, model, \
+						X86_STEPPING_ANY, feature, data)
+
+/**
+ * X86_MATCH_VENDOR_FAM_FEATURE - Macro for matching vendor, family and CPU feature
+ * @vendor:	The vendor name, e.g. INTEL, AMD, HYGON, ..., ANY
+ *		The name is expanded to X86_VENDOR_@vendor
+ * @family:	The family number or X86_FAMILY_ANY
+ * @feature:	A X86_FEATURE bit
+ * @data:	Driver specific data or NULL. The internal storage
+ *		format is unsigned long. The supplied value, pointer
+ *		etc. is casted to unsigned long internally.
+ *
+ * All other missing arguments of X86_MATCH_VENDOR_FAM_MODEL_FEATURE() are
+ * set to wildcards.
+ */
+#define X86_MATCH_VENDOR_FAM_FEATURE(vendor, family, feature, data)	\
+	X86_MATCH_VENDOR_FAM_MODEL_FEATURE(vendor, family,		\
+					   X86_MODEL_ANY, feature, data)
+
+/**
+ * X86_MATCH_VENDOR_FEATURE - Macro for matching vendor and CPU feature
+ * @vendor:	The vendor name, e.g. INTEL, AMD, HYGON, ..., ANY
+ *		The name is expanded to X86_VENDOR_@vendor
+ * @feature:	A X86_FEATURE bit
+ * @data:	Driver specific data or NULL. The internal storage
+ *		format is unsigned long. The supplied value, pointer
+ *		etc. is casted to unsigned long internally.
+ *
+ * All other missing arguments of X86_MATCH_VENDOR_FAM_MODEL_FEATURE() are
+ * set to wildcards.
+ */
+#define X86_MATCH_VENDOR_FEATURE(vendor, feature, data)			\
+	X86_MATCH_VENDOR_FAM_FEATURE(vendor, X86_FAMILY_ANY, feature, data)
+
+/**
+ * X86_MATCH_FEATURE - Macro for matching a CPU feature
+ * @feature:	A X86_FEATURE bit
+ * @data:	Driver specific data or NULL. The internal storage
+ *		format is unsigned long. The supplied value, pointer
+ *		etc. is casted to unsigned long internally.
+ *
+ * All other missing arguments of X86_MATCH_VENDOR_FAM_MODEL_FEATURE() are
+ * set to wildcards.
+ */
+#define X86_MATCH_FEATURE(feature, data)				\
+	X86_MATCH_VENDOR_FEATURE(ANY, feature, data)
+
+/* Transitional to keep the existing code working */
+#define X86_FEATURE_MATCH(feature)	X86_MATCH_FEATURE(feature, NULL)
+
+/**
+ * X86_MATCH_VENDOR_FAM_MODEL - Match vendor, family and model
+ * @vendor:	The vendor name, e.g. INTEL, AMD, HYGON, ..., ANY
+ *		The name is expanded to X86_VENDOR_@vendor
+ * @family:	The family number or X86_FAMILY_ANY
+ * @model:	The model number, model constant or X86_MODEL_ANY
+ * @data:	Driver specific data or NULL. The internal storage
+ *		format is unsigned long. The supplied value, pointer
+ *		etc. is casted to unsigned long internally.
+ *
+ * All other missing arguments of X86_MATCH_VENDOR_FAM_MODEL_FEATURE() are
+ * set to wildcards.
+ */
+#define X86_MATCH_VENDOR_FAM_MODEL(vendor, family, model, data)		\
+	X86_MATCH_VENDOR_FAM_MODEL_FEATURE(vendor, family, model,	\
+					   X86_FEATURE_ANY, data)
+
+/**
+ * X86_MATCH_VENDOR_FAM - Match vendor and family
+ * @vendor:	The vendor name, e.g. INTEL, AMD, HYGON, ..., ANY
+ *		The name is expanded to X86_VENDOR_@vendor
+ * @family:	The family number or X86_FAMILY_ANY
+ * @data:	Driver specific data or NULL. The internal storage
+ *		format is unsigned long. The supplied value, pointer
+ *		etc. is casted to unsigned long internally.
+ *
+ * All other missing arguments to X86_MATCH_VENDOR_FAM_MODEL_FEATURE() are
+ * set of wildcards.
+ */
+#define X86_MATCH_VENDOR_FAM(vendor, family, data)			\
+	X86_MATCH_VENDOR_FAM_MODEL(vendor, family, X86_MODEL_ANY, data)
+
+/**
+ * X86_MATCH_INTEL_FAM6_MODEL - Match vendor INTEL, family 6 and model
+ * @model:	The model name without the INTEL_FAM6_ prefix or ANY
+ *		The model name is expanded to INTEL_FAM6_@model internally
+ * @data:	Driver specific data or NULL. The internal storage
+ *		format is unsigned long. The supplied value, pointer
+ *		etc. is casted to unsigned long internally.
+ *
+ * The vendor is set to INTEL, the family to 6 and all other missing
+ * arguments of X86_MATCH_VENDOR_FAM_MODEL_FEATURE() are set to wildcards.
+ *
+ * See X86_MATCH_VENDOR_FAM_MODEL_FEATURE() for further information.
+ */
+#define X86_MATCH_INTEL_FAM6_MODEL(model, data)				\
+	X86_MATCH_VENDOR_FAM_MODEL(INTEL, 6, INTEL_FAM6_##model, data)
 
 /*
  * Match specific microcode revisions.
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/cpu_entry_area.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/cpu_entry_area.h
@@ -78,8 +78,12 @@
 
 	/*
 	 * The GDT is just below entry_stack and thus serves (on x86_64) as
-	 * a a read-only guard page.
+	 * a read-only guard page. On 32-bit the GDT must be writeable, so
+	 * it needs an extra guard page.
 	 */
+#ifdef CONFIG_X86_32
+	char guard_entry_stack[PAGE_SIZE];
+#endif
 	struct entry_stack_page entry_stack_page;
 
 	/*
@@ -94,7 +98,6 @@
 	 */
 	struct cea_exception_stacks estacks;
 #endif
-#ifdef CONFIG_CPU_SUP_INTEL
 	/*
 	 * Per CPU debug store for Intel performance monitoring. Wastes a
 	 * full page at the moment.
@@ -105,11 +108,9 @@
 	 * Reserve enough fixmap PTEs.
 	 */
 	struct debug_store_buffers cpu_debug_buffers;
-#endif
 };
 
-#define CPU_ENTRY_AREA_SIZE	(sizeof(struct cpu_entry_area))
-#define CPU_ENTRY_AREA_TOT_SIZE	(CPU_ENTRY_AREA_SIZE * NR_CPUS)
+#define CPU_ENTRY_AREA_SIZE		(sizeof(struct cpu_entry_area))
 
 DECLARE_PER_CPU(struct cpu_entry_area *, cpu_entry_area);
 DECLARE_PER_CPU(struct cea_exception_stacks *, cea_exception_stacks);
@@ -117,17 +118,23 @@
 extern void setup_cpu_entry_areas(void);
 extern void cea_set_pte(void *cea_vaddr, phys_addr_t pa, pgprot_t flags);
 
+/* Single page reserved for the readonly IDT mapping: */
 #define	CPU_ENTRY_AREA_RO_IDT		CPU_ENTRY_AREA_BASE
 #define CPU_ENTRY_AREA_PER_CPU		(CPU_ENTRY_AREA_RO_IDT + PAGE_SIZE)
 
 #define CPU_ENTRY_AREA_RO_IDT_VADDR	((void *)CPU_ENTRY_AREA_RO_IDT)
 
-#define CPU_ENTRY_AREA_MAP_SIZE			\
-	(CPU_ENTRY_AREA_PER_CPU + CPU_ENTRY_AREA_TOT_SIZE - CPU_ENTRY_AREA_BASE)
+#ifdef CONFIG_X86_32
+#define CPU_ENTRY_AREA_MAP_SIZE		(CPU_ENTRY_AREA_PER_CPU +		\
+					 (CPU_ENTRY_AREA_SIZE * NR_CPUS) -	\
+					 CPU_ENTRY_AREA_BASE)
+#else
+#define CPU_ENTRY_AREA_MAP_SIZE		P4D_SIZE
+#endif
 
 extern struct cpu_entry_area *get_cpu_entry_area(int cpu);
 
-static inline struct entry_stack *cpu_entry_stack(int cpu)
+static __always_inline struct entry_stack *cpu_entry_stack(int cpu)
 {
 	return &get_cpu_entry_area(cpu)->entry_stack_page.stack;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/cpufeature.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/cpufeature.h
@@ -30,6 +30,10 @@
 	CPUID_7_ECX,
 	CPUID_8000_0007_EBX,
 	CPUID_7_EDX,
+	CPUID_8000_001F_EAX,
+	CPUID_8000_0021_EAX,
+	CPUID_LNX_5,
+	NR_CPUID_WORDS,
 };
 
 #ifdef CONFIG_X86_FEATURE_NAMES
@@ -49,7 +53,7 @@
 extern const char * const x86_bug_flags[NBUGINTS*32];
 
 #define test_cpu_cap(c, bit)						\
-	 test_bit(bit, (unsigned long *)((c)->x86_capability))
+	 arch_test_bit(bit, (unsigned long *)((c)->x86_capability))
 
 /*
  * There are 32 bits/features in each mask word.  The high bits
@@ -88,8 +92,11 @@
 	   CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 16, feature_bit) ||	\
 	   CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 17, feature_bit) ||	\
 	   CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 18, feature_bit) ||	\
+	   CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 19, feature_bit) ||	\
+	   CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 20, feature_bit) ||	\
+	   CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 21, feature_bit) ||	\
 	   REQUIRED_MASK_CHECK					  ||	\
-	   BUILD_BUG_ON_ZERO(NCAPINTS != 19))
+	   BUILD_BUG_ON_ZERO(NCAPINTS != 22))
 
 #define DISABLED_MASK_BIT_SET(feature_bit)				\
 	 ( CHECK_BIT_IN_MASK_WORD(DISABLED_MASK,  0, feature_bit) ||	\
@@ -111,8 +118,11 @@
 	   CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 16, feature_bit) ||	\
 	   CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 17, feature_bit) ||	\
 	   CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 18, feature_bit) ||	\
+	   CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 19, feature_bit) ||	\
+	   CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 20, feature_bit) ||	\
+	   CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 21, feature_bit) ||	\
 	   DISABLED_MASK_CHECK					  ||	\
-	   BUILD_BUG_ON_ZERO(NCAPINTS != 19))
+	   BUILD_BUG_ON_ZERO(NCAPINTS != 22))
 
 #define cpu_has(c, bit)							\
 	(__builtin_constant_p(bit) && REQUIRED_MASK_BIT_SET(bit) ? 1 :	\
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/cpufeatures.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/cpufeatures.h
@@ -13,8 +13,8 @@
 /*
  * Defines x86 CPU feature bits
  */
-#define NCAPINTS			19	   /* N 32-bit words worth of info */
-#define NBUGINTS			1	   /* N 32-bit bug flags */
+#define NCAPINTS			22	   /* N 32-bit words worth of info */
+#define NBUGINTS			2	   /* N 32-bit bug flags */
 
 /*
  * Note: If the comment begins with a quoted string, that string is used
@@ -96,6 +96,7 @@
 #define X86_FEATURE_SYSCALL32		( 3*32+14) /* "" syscall in IA32 userspace */
 #define X86_FEATURE_SYSENTER32		( 3*32+15) /* "" sysenter in IA32 userspace */
 #define X86_FEATURE_REP_GOOD		( 3*32+16) /* REP microcode works well */
+/* FREE!                                ( 3*32+17) */
 #define X86_FEATURE_LFENCE_RDTSC	( 3*32+18) /* "" LFENCE synchronizes RDTSC */
 #define X86_FEATURE_ACC_POWER		( 3*32+19) /* AMD Accumulated Power Mechanism */
 #define X86_FEATURE_NOPL		( 3*32+20) /* The NOPL (0F 1F) instructions */
@@ -107,6 +108,7 @@
 #define X86_FEATURE_EXTD_APICID		( 3*32+26) /* Extended APICID (8 bits) */
 #define X86_FEATURE_AMD_DCM		( 3*32+27) /* AMD multi-node processor */
 #define X86_FEATURE_APERFMPERF		( 3*32+28) /* P-State hardware coordination feedback capability (APERF/MPERF MSRs) */
+/* free					( 3*32+29) */
 #define X86_FEATURE_NONSTOP_TSC_S3	( 3*32+30) /* TSC doesn't stop in S3 state */
 #define X86_FEATURE_TSC_KNOWN_FREQ	( 3*32+31) /* TSC has known frequency */
 
@@ -199,23 +201,23 @@
 #define X86_FEATURE_INVPCID_SINGLE	( 7*32+ 7) /* Effectively INVPCID && CR4.PCIDE=1 */
 #define X86_FEATURE_HW_PSTATE		( 7*32+ 8) /* AMD HW-PState */
 #define X86_FEATURE_PROC_FEEDBACK	( 7*32+ 9) /* AMD ProcFeedbackInterface */
-#define X86_FEATURE_SME			( 7*32+10) /* AMD Secure Memory Encryption */
+/* FREE!                                ( 7*32+10) */
 #define X86_FEATURE_PTI			( 7*32+11) /* Kernel Page Table Isolation enabled */
-#define X86_FEATURE_RETPOLINE		( 7*32+12) /* "" Generic Retpoline mitigation for Spectre variant 2 */
-#define X86_FEATURE_RETPOLINE_AMD	( 7*32+13) /* "" AMD Retpoline mitigation for Spectre variant 2 */
+#define X86_FEATURE_KERNEL_IBRS		( 7*32+12) /* "" Set/clear IBRS on kernel entry/exit */
+#define X86_FEATURE_RSB_VMEXIT		( 7*32+13) /* "" Fill RSB on VM-Exit */
 #define X86_FEATURE_INTEL_PPIN		( 7*32+14) /* Intel Processor Inventory Number */
 #define X86_FEATURE_CDP_L2		( 7*32+15) /* Code and Data Prioritization L2 */
 #define X86_FEATURE_MSR_SPEC_CTRL	( 7*32+16) /* "" MSR SPEC_CTRL is implemented */
 #define X86_FEATURE_SSBD		( 7*32+17) /* Speculative Store Bypass Disable */
 #define X86_FEATURE_MBA			( 7*32+18) /* Memory Bandwidth Allocation */
 #define X86_FEATURE_RSB_CTXSW		( 7*32+19) /* "" Fill RSB on context switches */
-#define X86_FEATURE_SEV			( 7*32+20) /* AMD Secure Encrypted Virtualization */
+/* FREE!                                ( 7*32+20) */
 #define X86_FEATURE_USE_IBPB		( 7*32+21) /* "" Indirect Branch Prediction Barrier enabled */
 #define X86_FEATURE_USE_IBRS_FW		( 7*32+22) /* "" Use IBRS during runtime firmware calls */
 #define X86_FEATURE_SPEC_STORE_BYPASS_DISABLE	( 7*32+23) /* "" Disable Speculative Store Bypass. */
 #define X86_FEATURE_LS_CFG_SSBD		( 7*32+24)  /* "" AMD SSBD implementation via LS_CFG MSR */
 #define X86_FEATURE_IBRS		( 7*32+25) /* Indirect Branch Restricted Speculation */
-#define X86_FEATURE_IBPB		( 7*32+26) /* Indirect Branch Prediction Barrier */
+#define X86_FEATURE_IBPB		( 7*32+26) /* "ibpb" Indirect Branch Prediction Barrier without a guaranteed RSB flush */
 #define X86_FEATURE_STIBP		( 7*32+27) /* Single Thread Indirect Branch Predictors */
 #define X86_FEATURE_ZEN			( 7*32+28) /* "" CPU is AMD family 0x17 (Zen) */
 #define X86_FEATURE_L1TF_PTEINV		( 7*32+29) /* "" L1TF workaround PTE inversion */
@@ -284,6 +286,11 @@
 #define X86_FEATURE_CQM_MBM_LOCAL	(11*32+ 3) /* LLC Local MBM monitoring */
 #define X86_FEATURE_FENCE_SWAPGS_USER	(11*32+ 4) /* "" LFENCE in user entry SWAPGS path */
 #define X86_FEATURE_FENCE_SWAPGS_KERNEL	(11*32+ 5) /* "" LFENCE in kernel entry SWAPGS path */
+#define X86_FEATURE_RRSBA_CTRL		(11*32+11) /* "" RET prediction control */
+#define X86_FEATURE_RETPOLINE		(11*32+12) /* "" Generic Retpoline mitigation for Spectre variant 2 */
+#define X86_FEATURE_RETPOLINE_LFENCE	(11*32+13) /* "" Use LFENCE for Spectre variant 2 */
+#define X86_FEATURE_RSB_VMEXIT_LITE	(11*32+17) /* "" Fill RSB on VM exit when EIBRS is enabled */
+#define X86_FEATURE_MSR_TSX_CTRL	(11*32+18) /* "" MSR IA32_TSX_CTRL (Intel) implemented */
 
 /* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */
 #define X86_FEATURE_AVX512_BF16		(12*32+ 5) /* AVX512 BFLOAT16 instructions */
@@ -300,6 +307,8 @@
 #define X86_FEATURE_AMD_SSBD		(13*32+24) /* "" Speculative Store Bypass Disable */
 #define X86_FEATURE_VIRT_SSBD		(13*32+25) /* Virtualized Speculative Store Bypass Disable */
 #define X86_FEATURE_AMD_SSB_NO		(13*32+26) /* "" Speculative Store Bypass is fixed in hardware. */
+#define X86_FEATURE_BTC_NO		(13*32+29) /* "" Not vulnerable to Branch Type Confusion */
+#define X86_FEATURE_AMD_IBPB_RET	(13*32+30) /* "" IBPB clears return address predictor */
 
 /* Thermal and Power Management Leaf, CPUID level 0x00000006 (EAX), word 14 */
 #define X86_FEATURE_DTHERM		(14*32+ 0) /* Digital Thermal Sensor */
@@ -357,6 +366,7 @@
 #define X86_FEATURE_AVX512_4VNNIW	(18*32+ 2) /* AVX-512 Neural Network Instructions */
 #define X86_FEATURE_AVX512_4FMAPS	(18*32+ 3) /* AVX-512 Multiply Accumulation Single precision */
 #define X86_FEATURE_AVX512_VP2INTERSECT (18*32+ 8) /* AVX-512 Intersect for D/Q */
+#define X86_FEATURE_SRBDS_CTRL		(18*32+ 9) /* "" SRBDS mitigation MSR available */
 #define X86_FEATURE_MD_CLEAR		(18*32+10) /* VERW clears CPU buffers */
 #define X86_FEATURE_TSX_FORCE_ABORT	(18*32+13) /* "" TSX_FORCE_ABORT */
 #define X86_FEATURE_PCONFIG		(18*32+18) /* Intel PCONFIG */
@@ -366,6 +376,27 @@
 #define X86_FEATURE_ARCH_CAPABILITIES	(18*32+29) /* IA32_ARCH_CAPABILITIES MSR (Intel) */
 #define X86_FEATURE_SPEC_CTRL_SSBD	(18*32+31) /* "" Speculative Store Bypass Disable */
 
+/* AMD-defined memory encryption features, CPUID level 0x8000001f (EAX), word 19 */
+#define X86_FEATURE_SME			(19*32+ 0) /* AMD Secure Memory Encryption */
+#define X86_FEATURE_SEV			(19*32+ 1) /* AMD Secure Encrypted Virtualization */
+#define X86_FEATURE_VM_PAGE_FLUSH	(19*32+ 2) /* "" VM Page Flush MSR is supported */
+#define X86_FEATURE_SEV_ES		(19*32+ 3) /* AMD Secure Encrypted Virtualization - Encrypted State */
+#define X86_FEATURE_SME_COHERENT	(19*32+10) /* "" AMD hardware-enforced cache coherency */
+
+#define X86_FEATURE_AUTOIBRS		(20*32+ 8) /* "" Automatic IBRS */
+
+/*
+ * Extended auxiliary flags: Linux defined - for features scattered in various
+ * CPUID levels like 0x80000022, etc and Linux defined features.
+ *
+ * Reuse free bits when adding new feature flags!
+ */
+#define X86_FEATURE_CLEAR_BHB_LOOP	(21*32+ 1) /* "" Clear branch history at syscall entry using SW loop */
+#define X86_FEATURE_BHI_CTRL		(21*32+ 2) /* "" BHI_DIS_S HW control available */
+#define X86_FEATURE_CLEAR_BHB_HW	(21*32+ 3) /* "" BHI_DIS_S HW control enabled */
+#define X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT (21*32+ 4) /* "" Clear branch history at vmexit using SW loop */
+#define X86_FEATURE_IBPB_EXIT_TO_USER  (21*32+14) /* Use IBPB on exit-to-userspace, see VMSCAPE bug */
+
 /*
  * BUG word(s)
  */
@@ -401,5 +432,16 @@
 #define X86_BUG_SWAPGS			X86_BUG(21) /* CPU is affected by speculation through SWAPGS */
 #define X86_BUG_TAA			X86_BUG(22) /* CPU is affected by TSX Async Abort(TAA) */
 #define X86_BUG_ITLB_MULTIHIT		X86_BUG(23) /* CPU may incur MCE during certain page attribute changes */
-
+#define X86_BUG_SRBDS			X86_BUG(24) /* CPU may leak RNG bits if not mitigated */
+#define X86_BUG_MMIO_STALE_DATA		X86_BUG(25) /* CPU is affected by Processor MMIO Stale Data vulnerabilities */
+#define X86_BUG_RETBLEED		X86_BUG(26) /* CPU is affected by RETBleed */
+#define X86_BUG_EIBRS_PBRSB		X86_BUG(27) /* EIBRS is vulnerable to Post Barrier RSB Predictions */
+#define X86_BUG_MMIO_UNKNOWN		X86_BUG(28) /* CPU is too old and its MMIO Stale Data status is unknown */
+#define X86_BUG_SMT_RSB			X86_BUG(29) /* CPU is vulnerable to Cross-Thread Return Address Predictions */
+#define X86_BUG_GDS			X86_BUG(30) /* CPU is affected by Gather Data Sampling */
+
+/* BUG word 2 */
+#define X86_BUG_DIV0			X86_BUG(1*32 + 1) /* AMD DIV0 speculation bug */
+#define X86_BUG_BHI			X86_BUG(1*32 + 3) /* CPU is affected by Branch History Injection */
+#define X86_BUG_VMSCAPE			X86_BUG( 1*32+10) /* "vmscape" CPU is affected by VMSCAPE attacks from guests */
 #endif /* _ASM_X86_CPUFEATURES_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/crash.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/crash.h
@@ -2,10 +2,18 @@
 #ifndef _ASM_X86_CRASH_H
 #define _ASM_X86_CRASH_H
 
+struct kimage;
+
 int crash_load_segments(struct kimage *image);
 int crash_copy_backup_region(struct kimage *image);
 int crash_setup_memmap_entries(struct kimage *image,
 		struct boot_params *params);
 void crash_smp_send_stop(void);
 
+#ifdef CONFIG_KEXEC_CORE
+void __init crash_reserve_low_1M(void);
+#else
+static inline void __init crash_reserve_low_1M(void) { }
+#endif
+
 #endif /* _ASM_X86_CRASH_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/crypto/camellia.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/crypto/camellia.h
@@ -32,65 +32,60 @@
 			       unsigned int keylen);
 
 /* regular block cipher functions */
-asmlinkage void __camellia_enc_blk(struct camellia_ctx *ctx, u8 *dst,
-				   const u8 *src, bool xor);
-asmlinkage void camellia_dec_blk(struct camellia_ctx *ctx, u8 *dst,
-				 const u8 *src);
+asmlinkage void __camellia_enc_blk(const void *ctx, u8 *dst, const u8 *src,
+				   bool xor);
+asmlinkage void camellia_dec_blk(const void *ctx, u8 *dst, const u8 *src);
 
 /* 2-way parallel cipher functions */
-asmlinkage void __camellia_enc_blk_2way(struct camellia_ctx *ctx, u8 *dst,
-					const u8 *src, bool xor);
-asmlinkage void camellia_dec_blk_2way(struct camellia_ctx *ctx, u8 *dst,
-				      const u8 *src);
+asmlinkage void __camellia_enc_blk_2way(const void *ctx, u8 *dst, const u8 *src,
+					bool xor);
+asmlinkage void camellia_dec_blk_2way(const void *ctx, u8 *dst, const u8 *src);
 
 /* 16-way parallel cipher functions (avx/aes-ni) */
-asmlinkage void camellia_ecb_enc_16way(struct camellia_ctx *ctx, u8 *dst,
-				       const u8 *src);
-asmlinkage void camellia_ecb_dec_16way(struct camellia_ctx *ctx, u8 *dst,
-				       const u8 *src);
-
-asmlinkage void camellia_cbc_dec_16way(struct camellia_ctx *ctx, u8 *dst,
-				       const u8 *src);
-asmlinkage void camellia_ctr_16way(struct camellia_ctx *ctx, u8 *dst,
-				   const u8 *src, le128 *iv);
-
-asmlinkage void camellia_xts_enc_16way(struct camellia_ctx *ctx, u8 *dst,
-				       const u8 *src, le128 *iv);
-asmlinkage void camellia_xts_dec_16way(struct camellia_ctx *ctx, u8 *dst,
-				       const u8 *src, le128 *iv);
+asmlinkage void camellia_ecb_enc_16way(const void *ctx, u8 *dst, const u8 *src);
+asmlinkage void camellia_ecb_dec_16way(const void *ctx, u8 *dst, const u8 *src);
 
-static inline void camellia_enc_blk(struct camellia_ctx *ctx, u8 *dst,
-				    const u8 *src)
+asmlinkage void camellia_cbc_dec_16way(const void *ctx, u8 *dst, const u8 *src);
+asmlinkage void camellia_ctr_16way(const void *ctx, u8 *dst, const u8 *src,
+				   le128 *iv);
+
+asmlinkage void camellia_xts_enc_16way(const void *ctx, u8 *dst, const u8 *src,
+				       le128 *iv);
+asmlinkage void camellia_xts_dec_16way(const void *ctx, u8 *dst, const u8 *src,
+				       le128 *iv);
+
+static inline void camellia_enc_blk(const void *ctx, u8 *dst, const u8 *src)
 {
 	__camellia_enc_blk(ctx, dst, src, false);
 }
 
-static inline void camellia_enc_blk_xor(struct camellia_ctx *ctx, u8 *dst,
-					const u8 *src)
+static inline void camellia_enc_blk_xor(const void *ctx, u8 *dst, const u8 *src)
 {
 	__camellia_enc_blk(ctx, dst, src, true);
 }
 
-static inline void camellia_enc_blk_2way(struct camellia_ctx *ctx, u8 *dst,
+static inline void camellia_enc_blk_2way(const void *ctx, u8 *dst,
 					 const u8 *src)
 {
 	__camellia_enc_blk_2way(ctx, dst, src, false);
 }
 
-static inline void camellia_enc_blk_xor_2way(struct camellia_ctx *ctx, u8 *dst,
+static inline void camellia_enc_blk_xor_2way(const void *ctx, u8 *dst,
 					     const u8 *src)
 {
 	__camellia_enc_blk_2way(ctx, dst, src, true);
 }
 
 /* glue helpers */
-extern void camellia_decrypt_cbc_2way(void *ctx, u128 *dst, const u128 *src);
-extern void camellia_crypt_ctr(void *ctx, u128 *dst, const u128 *src,
+extern void camellia_decrypt_cbc_2way(const void *ctx, u8 *dst, const u8 *src);
+extern void camellia_crypt_ctr(const void *ctx, u8 *dst, const u8 *src,
 			       le128 *iv);
-extern void camellia_crypt_ctr_2way(void *ctx, u128 *dst, const u128 *src,
+extern void camellia_crypt_ctr_2way(const void *ctx, u8 *dst, const u8 *src,
 				    le128 *iv);
 
-extern void camellia_xts_enc(void *ctx, u128 *dst, const u128 *src, le128 *iv);
-extern void camellia_xts_dec(void *ctx, u128 *dst, const u128 *src, le128 *iv);
+extern void camellia_xts_enc(const void *ctx, u8 *dst, const u8 *src,
+			     le128 *iv);
+extern void camellia_xts_dec(const void *ctx, u8 *dst, const u8 *src,
+			     le128 *iv);
 
 #endif /* ASM_X86_CAMELLIA_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/crypto/glue_helper.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/crypto/glue_helper.h
@@ -11,18 +11,13 @@
 #include <asm/fpu/api.h>
 #include <crypto/b128ops.h>
 
-typedef void (*common_glue_func_t)(void *ctx, u8 *dst, const u8 *src);
-typedef void (*common_glue_cbc_func_t)(void *ctx, u128 *dst, const u128 *src);
-typedef void (*common_glue_ctr_func_t)(void *ctx, u128 *dst, const u128 *src,
+typedef void (*common_glue_func_t)(const void *ctx, u8 *dst, const u8 *src);
+typedef void (*common_glue_cbc_func_t)(const void *ctx, u8 *dst, const u8 *src);
+typedef void (*common_glue_ctr_func_t)(const void *ctx, u8 *dst, const u8 *src,
 				       le128 *iv);
-typedef void (*common_glue_xts_func_t)(void *ctx, u128 *dst, const u128 *src,
+typedef void (*common_glue_xts_func_t)(const void *ctx, u8 *dst, const u8 *src,
 				       le128 *iv);
 
-#define GLUE_FUNC_CAST(fn) ((common_glue_func_t)(fn))
-#define GLUE_CBC_FUNC_CAST(fn) ((common_glue_cbc_func_t)(fn))
-#define GLUE_CTR_FUNC_CAST(fn) ((common_glue_ctr_func_t)(fn))
-#define GLUE_XTS_FUNC_CAST(fn) ((common_glue_xts_func_t)(fn))
-
 struct common_glue_func_entry {
 	unsigned int num_blocks; /* number of blocks that @fn will process */
 	union {
@@ -116,7 +111,8 @@
 			       common_glue_func_t tweak_fn, void *tweak_ctx,
 			       void *crypt_ctx, bool decrypt);
 
-extern void glue_xts_crypt_128bit_one(void *ctx, u128 *dst, const u128 *src,
-				      le128 *iv, common_glue_func_t fn);
+extern void glue_xts_crypt_128bit_one(const void *ctx, u8 *dst,
+				      const u8 *src, le128 *iv,
+				      common_glue_func_t fn);
 
 #endif /* _CRYPTO_GLUE_HELPER_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/crypto/serpent-avx.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/crypto/serpent-avx.h
@@ -15,26 +15,26 @@
 	struct serpent_ctx crypt_ctx;
 };
 
-asmlinkage void serpent_ecb_enc_8way_avx(struct serpent_ctx *ctx, u8 *dst,
+asmlinkage void serpent_ecb_enc_8way_avx(const void *ctx, u8 *dst,
 					 const u8 *src);
-asmlinkage void serpent_ecb_dec_8way_avx(struct serpent_ctx *ctx, u8 *dst,
+asmlinkage void serpent_ecb_dec_8way_avx(const void *ctx, u8 *dst,
 					 const u8 *src);
 
-asmlinkage void serpent_cbc_dec_8way_avx(struct serpent_ctx *ctx, u8 *dst,
+asmlinkage void serpent_cbc_dec_8way_avx(const void *ctx, u8 *dst,
 					 const u8 *src);
-asmlinkage void serpent_ctr_8way_avx(struct serpent_ctx *ctx, u8 *dst,
-				     const u8 *src, le128 *iv);
+asmlinkage void serpent_ctr_8way_avx(const void *ctx, u8 *dst, const u8 *src,
+				     le128 *iv);
 
-asmlinkage void serpent_xts_enc_8way_avx(struct serpent_ctx *ctx, u8 *dst,
+asmlinkage void serpent_xts_enc_8way_avx(const void *ctx, u8 *dst,
 					 const u8 *src, le128 *iv);
-asmlinkage void serpent_xts_dec_8way_avx(struct serpent_ctx *ctx, u8 *dst,
+asmlinkage void serpent_xts_dec_8way_avx(const void *ctx, u8 *dst,
 					 const u8 *src, le128 *iv);
 
-extern void __serpent_crypt_ctr(void *ctx, u128 *dst, const u128 *src,
+extern void __serpent_crypt_ctr(const void *ctx, u8 *dst, const u8 *src,
 				le128 *iv);
 
-extern void serpent_xts_enc(void *ctx, u128 *dst, const u128 *src, le128 *iv);
-extern void serpent_xts_dec(void *ctx, u128 *dst, const u128 *src, le128 *iv);
+extern void serpent_xts_enc(const void *ctx, u8 *dst, const u8 *src, le128 *iv);
+extern void serpent_xts_dec(const void *ctx, u8 *dst, const u8 *src, le128 *iv);
 
 extern int xts_serpent_setkey(struct crypto_skcipher *tfm, const u8 *key,
 			      unsigned int keylen);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/crypto/serpent-sse2.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/crypto/serpent-sse2.h
@@ -9,25 +9,23 @@
 
 #define SERPENT_PARALLEL_BLOCKS 4
 
-asmlinkage void __serpent_enc_blk_4way(struct serpent_ctx *ctx, u8 *dst,
+asmlinkage void __serpent_enc_blk_4way(const struct serpent_ctx *ctx, u8 *dst,
 				       const u8 *src, bool xor);
-asmlinkage void serpent_dec_blk_4way(struct serpent_ctx *ctx, u8 *dst,
+asmlinkage void serpent_dec_blk_4way(const struct serpent_ctx *ctx, u8 *dst,
 				     const u8 *src);
 
-static inline void serpent_enc_blk_xway(struct serpent_ctx *ctx, u8 *dst,
-					const u8 *src)
+static inline void serpent_enc_blk_xway(const void *ctx, u8 *dst, const u8 *src)
 {
 	__serpent_enc_blk_4way(ctx, dst, src, false);
 }
 
-static inline void serpent_enc_blk_xway_xor(struct serpent_ctx *ctx, u8 *dst,
-					    const u8 *src)
+static inline void serpent_enc_blk_xway_xor(const struct serpent_ctx *ctx,
+					    u8 *dst, const u8 *src)
 {
 	__serpent_enc_blk_4way(ctx, dst, src, true);
 }
 
-static inline void serpent_dec_blk_xway(struct serpent_ctx *ctx, u8 *dst,
-					const u8 *src)
+static inline void serpent_dec_blk_xway(const void *ctx, u8 *dst, const u8 *src)
 {
 	serpent_dec_blk_4way(ctx, dst, src);
 }
@@ -36,25 +34,23 @@
 
 #define SERPENT_PARALLEL_BLOCKS 8
 
-asmlinkage void __serpent_enc_blk_8way(struct serpent_ctx *ctx, u8 *dst,
+asmlinkage void __serpent_enc_blk_8way(const struct serpent_ctx *ctx, u8 *dst,
 				       const u8 *src, bool xor);
-asmlinkage void serpent_dec_blk_8way(struct serpent_ctx *ctx, u8 *dst,
+asmlinkage void serpent_dec_blk_8way(const struct serpent_ctx *ctx, u8 *dst,
 				     const u8 *src);
 
-static inline void serpent_enc_blk_xway(struct serpent_ctx *ctx, u8 *dst,
-				   const u8 *src)
+static inline void serpent_enc_blk_xway(const void *ctx, u8 *dst, const u8 *src)
 {
 	__serpent_enc_blk_8way(ctx, dst, src, false);
 }
 
-static inline void serpent_enc_blk_xway_xor(struct serpent_ctx *ctx, u8 *dst,
-				       const u8 *src)
+static inline void serpent_enc_blk_xway_xor(const struct serpent_ctx *ctx,
+					    u8 *dst, const u8 *src)
 {
 	__serpent_enc_blk_8way(ctx, dst, src, true);
 }
 
-static inline void serpent_dec_blk_xway(struct serpent_ctx *ctx, u8 *dst,
-				   const u8 *src)
+static inline void serpent_dec_blk_xway(const void *ctx, u8 *dst, const u8 *src)
 {
 	serpent_dec_blk_8way(ctx, dst, src);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/crypto/twofish.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/crypto/twofish.h
@@ -7,22 +7,19 @@
 #include <crypto/b128ops.h>
 
 /* regular block cipher functions from twofish_x86_64 module */
-asmlinkage void twofish_enc_blk(struct twofish_ctx *ctx, u8 *dst,
-				const u8 *src);
-asmlinkage void twofish_dec_blk(struct twofish_ctx *ctx, u8 *dst,
-				const u8 *src);
+asmlinkage void twofish_enc_blk(const void *ctx, u8 *dst, const u8 *src);
+asmlinkage void twofish_dec_blk(const void *ctx, u8 *dst, const u8 *src);
 
 /* 3-way parallel cipher functions */
-asmlinkage void __twofish_enc_blk_3way(struct twofish_ctx *ctx, u8 *dst,
-				       const u8 *src, bool xor);
-asmlinkage void twofish_dec_blk_3way(struct twofish_ctx *ctx, u8 *dst,
-				     const u8 *src);
+asmlinkage void __twofish_enc_blk_3way(const void *ctx, u8 *dst, const u8 *src,
+				       bool xor);
+asmlinkage void twofish_dec_blk_3way(const void *ctx, u8 *dst, const u8 *src);
 
 /* helpers from twofish_x86_64-3way module */
-extern void twofish_dec_blk_cbc_3way(void *ctx, u128 *dst, const u128 *src);
-extern void twofish_enc_blk_ctr(void *ctx, u128 *dst, const u128 *src,
+extern void twofish_dec_blk_cbc_3way(const void *ctx, u8 *dst, const u8 *src);
+extern void twofish_enc_blk_ctr(const void *ctx, u8 *dst, const u8 *src,
 				le128 *iv);
-extern void twofish_enc_blk_ctr_3way(void *ctx, u128 *dst, const u128 *src,
+extern void twofish_enc_blk_ctr_3way(const void *ctx, u8 *dst, const u8 *src,
 				     le128 *iv);
 
 #endif /* ASM_X86_TWOFISH_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/disabled-features.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/disabled-features.h
@@ -84,6 +84,9 @@
 #define DISABLED_MASK16	(DISABLE_PKU|DISABLE_OSPKE|DISABLE_LA57|DISABLE_UMIP)
 #define DISABLED_MASK17	0
 #define DISABLED_MASK18	0
-#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 19)
+#define DISABLED_MASK19	0
+#define DISABLED_MASK20	0
+#define DISABLED_MASK21	0
+#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 22)
 
 #endif /* _ASM_X86_DISABLED_FEATURES_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/dma.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/dma.h
@@ -74,7 +74,7 @@
 #define MAX_DMA_PFN   ((16UL * 1024 * 1024) >> PAGE_SHIFT)
 
 /* 4GB broken PCI/AGP hardware bus master zone */
-#define MAX_DMA32_PFN ((4UL * 1024 * 1024 * 1024) >> PAGE_SHIFT)
+#define MAX_DMA32_PFN (1UL << (32 - PAGE_SHIFT))
 
 #ifdef CONFIG_X86_32
 /* The maximum address that we can perform a DMA transfer to on this platform */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/emulate_prefix.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/emulate_prefix.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_X86_EMULATE_PREFIX_H
+#define _ASM_X86_EMULATE_PREFIX_H
+
+/*
+ * Virt escape sequences to trigger instruction emulation;
+ * ideally these would decode to 'whole' instruction and not destroy
+ * the instruction stream; sadly this is not true for the 'kvm' one :/
+ */
+
+#define __XEN_EMULATE_PREFIX  0x0f,0x0b,0x78,0x65,0x6e  /* ud2 ; .ascii "xen" */
+#define __KVM_EMULATE_PREFIX  0x0f,0x0b,0x6b,0x76,0x6d	/* ud2 ; .ascii "kvm" */
+
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/fixmap.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/fixmap.h
@@ -156,7 +156,7 @@
 extern pte_t *pkmap_page_table;
 
 void __native_set_fixmap(enum fixed_addresses idx, pte_t pte);
-void native_set_fixmap(enum fixed_addresses idx,
+void native_set_fixmap(unsigned /* enum fixed_addresses */ idx,
 		       phys_addr_t phys, pgprot_t flags);
 
 #ifndef CONFIG_PARAVIRT_XXL
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/fpu/api.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/fpu/api.h
@@ -16,14 +16,25 @@
  * Use kernel_fpu_begin/end() if you intend to use FPU in kernel context. It
  * disables preemption so be careful if you intend to use it for long periods
  * of time.
- * If you intend to use the FPU in softirq you need to check first with
+ * If you intend to use the FPU in irq/softirq you need to check first with
  * irq_fpu_usable() if it is possible.
  */
-extern void kernel_fpu_begin(void);
+
+/* Kernel FPU states to initialize in kernel_fpu_begin_mask() */
+#define KFPU_387	_BITUL(0)	/* 387 state will be initialized */
+#define KFPU_MXCSR	_BITUL(1)	/* MXCSR will be initialized */
+
+extern void kernel_fpu_begin_mask(unsigned int kfpu_mask);
 extern void kernel_fpu_end(void);
 extern bool irq_fpu_usable(void);
 extern void fpregs_mark_activate(void);
 
+/* Code that is unaware of kernel_fpu_begin_mask() can use this */
+static inline void kernel_fpu_begin(void)
+{
+	kernel_fpu_begin_mask(KFPU_387 | KFPU_MXCSR);
+}
+
 /*
  * Use fpregs_lock() while editing CPU's FPU registers or fpu->state.
  * A context switch will (and softirq might) save CPU's FPU registers to
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/fpu/internal.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/fpu/internal.h
@@ -41,7 +41,7 @@
 extern void fpu__init_cpu(void);
 extern void fpu__init_system_xstate(void);
 extern void fpu__init_cpu_xstate(void);
-extern void fpu__init_system(struct cpuinfo_x86 *c);
+extern void fpu__init_system(void);
 extern void fpu__init_check_bugs(void);
 extern void fpu__resume_cpu(void);
 extern u64 fpu__get_supported_xfeatures_mask(void);
@@ -102,6 +102,7 @@
 }
 extern void fpstate_sanitize_xstate(struct fpu *fpu);
 
+/* Returns 0 or the negated trap number, which results in -EFAULT for #PF */
 #define user_insn(insn, output, input...)				\
 ({									\
 	int err;							\
@@ -109,14 +110,14 @@
 	might_fault();							\
 									\
 	asm volatile(ASM_STAC "\n"					\
-		     "1:" #insn "\n\t"					\
+		     "1: " #insn "\n"					\
 		     "2: " ASM_CLAC "\n"				\
 		     ".section .fixup,\"ax\"\n"				\
-		     "3:  movl $-1,%[err]\n"				\
+		     "3:  negl %%eax\n"					\
 		     "    jmp  2b\n"					\
 		     ".previous\n"					\
-		     _ASM_EXTABLE(1b, 3b)				\
-		     : [err] "=r" (err), output				\
+		     _ASM_EXTABLE_FAULT(1b, 3b)				\
+		     : [err] "=a" (err), output				\
 		     : "0"(0), input);					\
 	err;								\
 })
@@ -203,6 +204,14 @@
 		asm volatile("fxsaveq %[fx]" : [fx] "=m" (fpu->state.fxsave));
 }
 
+static inline void fxsave(struct fxregs_state *fx)
+{
+	if (IS_ENABLED(CONFIG_X86_32))
+		asm volatile( "fxsave %[fx]" : [fx] "=m" (*fx));
+	else
+		asm volatile("fxsaveq %[fx]" : [fx] "=m" (*fx));
+}
+
 /* These macros all use (%edi)/(%rdi) as the single memory argument. */
 #define XSAVE		".byte " REX_PREFIX "0x0f,0xae,0x27"
 #define XSAVEOPT	".byte " REX_PREFIX "0x0f,0xae,0x37"
@@ -210,16 +219,20 @@
 #define XRSTOR		".byte " REX_PREFIX "0x0f,0xae,0x2f"
 #define XRSTORS		".byte " REX_PREFIX "0x0f,0xc7,0x1f"
 
+/*
+ * After this @err contains 0 on success or the negated trap number when
+ * the operation raises an exception. For faults this results in -EFAULT.
+ */
 #define XSTATE_OP(op, st, lmask, hmask, err)				\
 	asm volatile("1:" op "\n\t"					\
 		     "xor %[err], %[err]\n"				\
 		     "2:\n\t"						\
 		     ".pushsection .fixup,\"ax\"\n\t"			\
-		     "3: movl $-2,%[err]\n\t"				\
+		     "3: negl %%eax\n\t"				\
 		     "jmp 2b\n\t"					\
 		     ".popsection\n\t"					\
-		     _ASM_EXTABLE(1b, 3b)				\
-		     : [err] "=r" (err)					\
+		     _ASM_EXTABLE_FAULT(1b, 3b)				\
+		     : [err] "=a" (err)					\
 		     : "D" (st), "m" (*st), "a" (lmask), "d" (hmask)	\
 		     : "memory")
 
@@ -271,28 +284,6 @@
  * This function is called only during boot time when x86 caps are not set
  * up and alternative can not be used yet.
  */
-static inline void copy_xregs_to_kernel_booting(struct xregs_state *xstate)
-{
-	u64 mask = -1;
-	u32 lmask = mask;
-	u32 hmask = mask >> 32;
-	int err;
-
-	WARN_ON(system_state != SYSTEM_BOOTING);
-
-	if (boot_cpu_has(X86_FEATURE_XSAVES))
-		XSTATE_OP(XSAVES, xstate, lmask, hmask, err);
-	else
-		XSTATE_OP(XSAVE, xstate, lmask, hmask, err);
-
-	/* We should never fault when copying to a kernel buffer: */
-	WARN_ON_FPU(err);
-}
-
-/*
- * This function is called only during boot time when x86 caps are not set
- * up and alternative can not be used yet.
- */
 static inline void copy_kernel_to_xregs_booting(struct xregs_state *xstate)
 {
 	u64 mask = -1;
@@ -509,7 +500,7 @@
 
 static inline int fpregs_state_valid(struct fpu *fpu, unsigned int cpu)
 {
-	return fpu == this_cpu_read_stable(fpu_fpregs_owner_ctx) && cpu == fpu->last_cpu;
+	return fpu == this_cpu_read(fpu_fpregs_owner_ctx) && cpu == fpu->last_cpu;
 }
 
 /*
@@ -569,9 +560,11 @@
  * The FPU context is only stored/restored for a user task and
  * PF_KTHREAD is used to distinguish between kernel and user threads.
  */
-static inline void switch_fpu_prepare(struct fpu *old_fpu, int cpu)
+static inline void switch_fpu_prepare(struct task_struct *prev, int cpu)
 {
-	if (static_cpu_has(X86_FEATURE_FPU) && !(current->flags & PF_KTHREAD)) {
+	struct fpu *old_fpu = &prev->thread.fpu;
+
+	if (static_cpu_has(X86_FEATURE_FPU) && !(prev->flags & PF_KTHREAD)) {
 		if (!copy_fpregs_to_fpstate(old_fpu))
 			old_fpu->last_cpu = -1;
 		else
@@ -590,10 +583,11 @@
  * Load PKRU from the FPU context if available. Delay loading of the
  * complete FPU state until the return to userland.
  */
-static inline void switch_fpu_finish(struct fpu *new_fpu)
+static inline void switch_fpu_finish(struct task_struct *next)
 {
 	u32 pkru_val = init_pkru_value;
 	struct pkru_state *pk;
+	struct fpu *next_fpu = &next->thread.fpu;
 
 	if (!static_cpu_has(X86_FEATURE_FPU))
 		return;
@@ -607,10 +601,17 @@
 	 * PKRU state is switched eagerly because it needs to be valid before we
 	 * return to userland e.g. for a copy_to_user() operation.
 	 */
-	if (current->mm) {
-		pk = get_xsave_addr(&new_fpu->state.xsave, XFEATURE_PKRU);
-		if (pk)
-			pkru_val = pk->pkru;
+	if (!(next->flags & PF_KTHREAD)) {
+		/*
+		 * If the PKRU bit in xsave.header.xfeatures is not set,
+		 * then the PKRU component was in init state, which means
+		 * XRSTOR will set PKRU to 0. If the bit is not set then
+		 * get_xsave_addr() will return NULL because the PKRU value
+		 * in memory is not valid. This means pkru_val has to be
+		 * set to 0 and not to init_pkru_value.
+		 */
+		pk = get_xsave_addr(&next_fpu->state.xsave, XFEATURE_PKRU);
+		pkru_val = pk ? pk->pkru : 0;
 	}
 	__write_pkru(pkru_val);
 }
@@ -619,6 +620,11 @@
  * MXCSR and XCR definitions:
  */
 
+static inline void ldmxcsr(u32 mxcsr)
+{
+	asm volatile("ldmxcsr %0" :: "m" (mxcsr));
+}
+
 extern unsigned int mxcsr_feature_mask;
 
 #define XCR_XFEATURE_ENABLED_MASK	0x00000000
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/hyperv-tlfs.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/hyperv-tlfs.h
@@ -721,7 +721,7 @@
 	u64 guest_rip;
 
 	u32 hv_clean_fields;
-	u32 hv_padding_32;
+	u32 padding32_1;
 	u32 hv_synthetic_controls;
 	struct {
 		u32 nested_flush_hypercall:1;
@@ -729,7 +729,7 @@
 		u32 reserved:30;
 	}  __packed hv_enlightenments_control;
 	u32 hv_vp_id;
-
+	u32 padding32_2;
 	u64 hv_vm_id;
 	u64 partition_assist_page;
 	u64 padding64_4[4];
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/i8259.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/i8259.h
@@ -67,6 +67,8 @@
 	void (*make_irq)(unsigned int irq);
 };
 
+void legacy_pic_pcat_compat(void);
+
 extern struct legacy_pic *legacy_pic;
 extern struct legacy_pic null_legacy_pic;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/insn.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/insn.h
@@ -45,6 +45,7 @@
 		struct insn_field immediate2;	/* for 64bit imm or seg16 */
 	};
 
+	int	emulate_prefix_size;
 	insn_attr_t attr;
 	unsigned char opnd_bytes;
 	unsigned char addr_bytes;
@@ -128,6 +129,11 @@
 	return (insn->vex_prefix.nbytes == 4);
 }
 
+static inline int insn_has_emulate_prefix(struct insn *insn)
+{
+	return !!insn->emulate_prefix_size;
+}
+
 /* Ensure this instruction is decoded completely */
 static inline int insn_complete(struct insn *insn)
 {
@@ -195,6 +201,21 @@
 	return insn_offset_displacement(insn) + insn->displacement.nbytes;
 }
 
+/**
+ * for_each_insn_prefix() -- Iterate prefixes in the instruction
+ * @insn: Pointer to struct insn.
+ * @idx:  Index storage.
+ * @prefix: Prefix byte.
+ *
+ * Iterate prefix bytes of given @insn. Each prefix byte is stored in @prefix
+ * and the index is stored in @idx (note that this @idx is just for a cursor,
+ * do not change it.)
+ * Since prefixes.nbytes can be bigger than 4 if some prefixes
+ * are repeated, it cannot be used for looping over the prefixes.
+ */
+#define for_each_insn_prefix(insn, idx, prefix)	\
+	for (idx = 0; idx < ARRAY_SIZE(insn->prefixes.bytes) && (prefix = insn->prefixes.bytes[idx]) != 0; idx++)
+
 #define POP_SS_OPCODE 0x1f
 #define MOV_SREG_OPCODE 0x8e
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/intel-family.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/intel-family.h
@@ -35,6 +35,9 @@
  * The #define line may optionally include a comment including platform names.
  */
 
+/* Wildcard match for FAM6 so X86_MATCH_INTEL_FAM6_MODEL(ANY) works */
+#define INTEL_FAM6_ANY			X86_MODEL_ANY
+
 #define INTEL_FAM6_CORE_YONAH		0x0E
 
 #define INTEL_FAM6_CORE2_MEROM		0x0F
@@ -86,6 +89,19 @@
 #define INTEL_FAM6_COMETLAKE		0xA5
 #define INTEL_FAM6_COMETLAKE_L		0xA6
 
+#define INTEL_FAM6_ROCKETLAKE		0xA7
+
+/* Hybrid Core/Atom Processors */
+
+#define	INTEL_FAM6_LAKEFIELD		0x8A
+#define INTEL_FAM6_ALDERLAKE		0x97
+#define INTEL_FAM6_ALDERLAKE_L		0x9A
+#define INTEL_FAM6_ALDERLAKE_N		0xBE
+
+#define INTEL_FAM6_RAPTORLAKE		0xB7
+#define INTEL_FAM6_RAPTORLAKE_P		0xBA
+#define INTEL_FAM6_RAPTORLAKE_S		0xBF
+
 /* "Small Core" Processors (Atom) */
 
 #define INTEL_FAM6_ATOM_BONNELL		0x1C /* Diamondville, Pineview */
@@ -111,12 +127,16 @@
 
 #define INTEL_FAM6_ATOM_TREMONT_D	0x86 /* Jacobsville */
 #define INTEL_FAM6_ATOM_TREMONT		0x96 /* Elkhart Lake */
+#define INTEL_FAM6_ATOM_TREMONT_L	0x9C /* Jasper Lake */
 
 /* Xeon Phi */
 
 #define INTEL_FAM6_XEON_PHI_KNL		0x57 /* Knights Landing */
 #define INTEL_FAM6_XEON_PHI_KNM		0x85 /* Knights Mill */
 
+/* Family 5 */
+#define INTEL_FAM5_QUARK_X1000		0x09 /* Quark X1000 SoC */
+
 /* Useful macros */
 #define INTEL_CPU_FAM_ANY(_family, _model, _driver_data)	\
 {								\
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/kasan.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/kasan.h
@@ -28,9 +28,12 @@
 #ifdef CONFIG_KASAN
 void __init kasan_early_init(void);
 void __init kasan_init(void);
+void __init kasan_populate_shadow_for_vaddr(void *va, size_t size, int nid);
 #else
 static inline void kasan_early_init(void) { }
 static inline void kasan_init(void) { }
+static inline void kasan_populate_shadow_for_vaddr(void *va, size_t size,
+						   int nid) { }
 #endif
 
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/kexec.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/kexec.h
@@ -22,6 +22,7 @@
 
 #include <linux/string.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 
 #include <asm/page.h>
 #include <asm/ptrace.h>
@@ -201,6 +202,14 @@
 extern void arch_kexec_pre_free_pages(void *vaddr, unsigned int pages);
 #define arch_kexec_pre_free_pages arch_kexec_pre_free_pages
 
+#ifdef CONFIG_KEXEC_FILE
+struct purgatory_info;
+int arch_kexec_apply_relocations_add(struct purgatory_info *pi,
+				     Elf_Shdr *section,
+				     const Elf_Shdr *relsec,
+				     const Elf_Shdr *symtab);
+#define arch_kexec_apply_relocations_add arch_kexec_apply_relocations_add
+#endif
 #endif
 
 typedef void crash_vmclear_fn(void);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/kvm_host.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/kvm_host.h
@@ -380,19 +380,17 @@
 	void (*set_cr3)(struct kvm_vcpu *vcpu, unsigned long root);
 	unsigned long (*get_cr3)(struct kvm_vcpu *vcpu);
 	u64 (*get_pdptr)(struct kvm_vcpu *vcpu, int index);
-	int (*page_fault)(struct kvm_vcpu *vcpu, gva_t gva, u32 err,
+	int (*page_fault)(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, u32 err,
 			  bool prefault);
 	void (*inject_page_fault)(struct kvm_vcpu *vcpu,
 				  struct x86_exception *fault);
-	gpa_t (*gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t gva, u32 access,
-			    struct x86_exception *exception);
+	gpa_t (*gva_to_gpa)(struct kvm_vcpu *vcpu, gpa_t gva_or_gpa,
+			    u32 access, struct x86_exception *exception);
 	gpa_t (*translate_gpa)(struct kvm_vcpu *vcpu, gpa_t gpa, u32 access,
 			       struct x86_exception *exception);
 	int (*sync_page)(struct kvm_vcpu *vcpu,
 			 struct kvm_mmu_page *sp);
 	void (*invlpg)(struct kvm_vcpu *vcpu, gva_t gva, hpa_t root_hpa);
-	void (*update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
-			   u64 *spte, const void *pte);
 	hpa_t root_hpa;
 	gpa_t root_cr3;
 	union kvm_mmu_role mmu_role;
@@ -550,6 +548,7 @@
 	unsigned long cr4;
 	unsigned long cr4_guest_owned_bits;
 	unsigned long cr8;
+	u32 host_pkru;
 	u32 pkru;
 	u32 hflags;
 	u64 efer;
@@ -564,6 +563,7 @@
 	u64 ia32_misc_enable_msr;
 	u64 smbase;
 	u64 smi_count;
+	bool at_instruction_boundary;
 	bool tpr_access_reporting;
 	u64 ia32_xss;
 	u64 microcode_version;
@@ -667,10 +667,10 @@
 	bool pvclock_set_guest_stopped_request;
 
 	struct {
+		u8 preempted;
 		u64 msr_val;
 		u64 last_steal;
-		struct gfn_to_hva_cache stime;
-		struct kvm_steal_time steal;
+		struct gfn_to_pfn_cache cache;
 	} st;
 
 	u64 tsc_offset;
@@ -943,7 +943,6 @@
 struct kvm_vm_stat {
 	ulong mmu_shadow_zapped;
 	ulong mmu_pte_write;
-	ulong mmu_pte_updated;
 	ulong mmu_pde_zapped;
 	ulong mmu_flooded;
 	ulong mmu_recycled;
@@ -983,6 +982,8 @@
 	u64 irq_injections;
 	u64 nmi_injections;
 	u64 req_event;
+	u64 preemption_reported;
+	u64 preemption_other;
 };
 
 struct x86_instruction_info;
@@ -1098,7 +1099,7 @@
 	void (*load_eoi_exitmap)(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap);
 	void (*set_virtual_apic_mode)(struct kvm_vcpu *vcpu);
 	void (*set_apic_access_page_addr)(struct kvm_vcpu *vcpu, hpa_t hpa);
-	void (*deliver_posted_interrupt)(struct kvm_vcpu *vcpu, int vector);
+	int (*deliver_posted_interrupt)(struct kvm_vcpu *vcpu, int vector);
 	int (*sync_pir_to_irr)(struct kvm_vcpu *vcpu);
 	int (*set_tss_addr)(struct kvm *kvm, unsigned int addr);
 	int (*set_identity_map_addr)(struct kvm *kvm, u64 ident_addr);
@@ -1128,8 +1129,9 @@
 	bool (*xsaves_supported)(void);
 	bool (*umip_emulated)(void);
 	bool (*pt_supported)(void);
+	bool (*pku_supported)(void);
 
-	int (*check_nested_events)(struct kvm_vcpu *vcpu, bool external_intr);
+	int (*check_nested_events)(struct kvm_vcpu *vcpu);
 	void (*request_immediate_exit)(struct kvm_vcpu *vcpu);
 
 	void (*sched_in)(struct kvm_vcpu *kvm, int cpu);
@@ -1158,7 +1160,7 @@
 	void (*enable_log_dirty_pt_masked)(struct kvm *kvm,
 					   struct kvm_memory_slot *slot,
 					   gfn_t offset, unsigned long mask);
-	int (*write_log_dirty)(struct kvm_vcpu *vcpu);
+	int (*write_log_dirty)(struct kvm_vcpu *vcpu, gpa_t l2_gpa);
 
 	/* pmu operations of sub-arch */
 	const struct kvm_pmu_ops *pmu_ops;
@@ -1450,7 +1452,7 @@
 
 int kvm_emulate_hypercall(struct kvm_vcpu *vcpu);
 
-int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t gva, u64 error_code,
+int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, u64 error_code,
 		       void *insn, int insn_len);
 void kvm_mmu_invlpg(struct kvm_vcpu *vcpu, gva_t gva);
 void kvm_mmu_invpcid_gva(struct kvm_vcpu *vcpu, gva_t gva, unsigned long pcid);
@@ -1551,12 +1553,14 @@
 	_ASM_EXTABLE(666b, 667b)
 
 #define KVM_ARCH_WANT_MMU_NOTIFIER
-int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end);
+int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end,
+			unsigned flags);
 int kvm_age_hva(struct kvm *kvm, unsigned long start, unsigned long end);
 int kvm_test_age_hva(struct kvm *kvm, unsigned long hva);
 int kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte);
 int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v);
 int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu);
+int kvm_cpu_has_extint(struct kvm_vcpu *v);
 int kvm_arch_interrupt_allowed(struct kvm_vcpu *vcpu);
 int kvm_cpu_get_interrupt(struct kvm_vcpu *v);
 void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event);
@@ -1607,8 +1611,8 @@
 static inline bool kvm_irq_is_postable(struct kvm_lapic_irq *irq)
 {
 	/* We can only post Fixed and LowPrio IRQs */
-	return (irq->delivery_mode == dest_Fixed ||
-		irq->delivery_mode == dest_LowestPrio);
+	return (irq->delivery_mode == APIC_DM_FIXED ||
+		irq->delivery_mode == APIC_DM_LOWEST);
 }
 
 static inline void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/kvm_para.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/kvm_para.h
@@ -6,8 +6,6 @@
 #include <asm/alternative.h>
 #include <uapi/asm/kvm_para.h>
 
-extern void kvmclock_init(void);
-
 #ifdef CONFIG_KVM_GUEST
 bool kvm_check_and_clear_guest_paused(void);
 #else
@@ -85,13 +83,14 @@
 }
 
 #ifdef CONFIG_KVM_GUEST
+void kvmclock_init(void);
+void kvmclock_disable(void);
 bool kvm_para_available(void);
 unsigned int kvm_arch_para_features(void);
 unsigned int kvm_arch_para_hints(void);
 void kvm_async_pf_task_wait(u32 token, int interrupt_kernel);
 void kvm_async_pf_task_wake(u32 token);
 u32 kvm_read_and_reset_pf_reason(void);
-extern void kvm_disable_steal_time(void);
 void do_async_page_fault(struct pt_regs *regs, unsigned long error_code, unsigned long address);
 
 #ifdef CONFIG_PARAVIRT_SPINLOCKS
@@ -126,10 +125,6 @@
 	return 0;
 }
 
-static inline void kvm_disable_steal_time(void)
-{
-	return;
-}
 #endif
 
 #endif /* _ASM_X86_KVM_PARA_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/kvmclock.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/kvmclock.h
@@ -2,6 +2,20 @@
 #ifndef _ASM_X86_KVM_CLOCK_H
 #define _ASM_X86_KVM_CLOCK_H
 
+#include <linux/percpu.h>
+
 extern struct clocksource kvm_clock;
 
+DECLARE_PER_CPU(struct pvclock_vsyscall_time_info *, hv_clock_per_cpu);
+
+static inline struct pvclock_vcpu_time_info *this_cpu_pvti(void)
+{
+	return &this_cpu_read(hv_clock_per_cpu)->pvti;
+}
+
+static inline struct pvclock_vsyscall_time_info *this_cpu_hvclock(void)
+{
+	return this_cpu_read(hv_clock_per_cpu);
+}
+
 #endif /* _ASM_X86_KVM_CLOCK_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/linkage.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/linkage.h
@@ -13,9 +13,13 @@
 
 #ifdef __ASSEMBLY__
 
-#define GLOBAL(name)	\
-	.globl name;	\
-	name:
+/*
+ * GLOBAL is DEPRECATED
+ *
+ * use SYM_DATA_START, SYM_FUNC_START, SYM_INNER_LABEL, SYM_CODE_START, or
+ * similar
+ */
+#define GLOBAL(name)	SYM_ENTRY(name, SYM_L_GLOBAL, SYM_A_NONE)
 
 #if defined(CONFIG_X86_64) || defined(CONFIG_X86_ALIGNMENT_16)
 #define __ALIGN		.p2align 4, 0x90
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/mce.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/mce.h
@@ -290,6 +290,7 @@
 /* These may be used by multiple smca_hwid_mcatypes */
 enum smca_bank_types {
 	SMCA_LS = 0,	/* Load Store */
+	SMCA_LS_V2,	/* Load Store */
 	SMCA_IF,	/* Instruction Fetch */
 	SMCA_L2_CACHE,	/* L2 Cache */
 	SMCA_DE,	/* Decoder Unit */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/mem_encrypt.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/mem_encrypt.h
@@ -43,13 +43,13 @@
 int __init early_set_memory_decrypted(unsigned long vaddr, unsigned long size);
 int __init early_set_memory_encrypted(unsigned long vaddr, unsigned long size);
 
-/* Architecture __weak replacement functions */
-void __init mem_encrypt_init(void);
 void __init mem_encrypt_free_decrypted_mem(void);
 
 bool sme_active(void);
 bool sev_active(void);
 
+void __init mem_encrypt_init(void);
+
 #define __bss_decrypted __attribute__((__section__(".bss..decrypted")))
 
 #else	/* !CONFIG_AMD_MEM_ENCRYPT */
@@ -77,6 +77,8 @@
 static inline int __init
 early_set_memory_encrypted(unsigned long vaddr, unsigned long size) { return 0; }
 
+static inline void mem_encrypt_init(void) { }
+
 #define __bss_decrypted
 
 #endif	/* CONFIG_AMD_MEM_ENCRYPT */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/microcode.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/microcode.h
@@ -5,10 +5,12 @@
 #include <asm/cpu.h>
 #include <linux/earlycpio.h>
 #include <linux/initrd.h>
+#include <asm/microcode_amd.h>
 
 struct ucode_patch {
 	struct list_head plist;
 	void *data;		/* Intel uses only this one */
+	unsigned int size;
 	u32 patch_id;
 	u16 equiv_cpu;
 };
@@ -130,14 +132,16 @@
 int __init microcode_init(void);
 extern void __init load_ucode_bsp(void);
 extern void load_ucode_ap(void);
-void reload_early_microcode(void);
+void reload_early_microcode(unsigned int cpu);
 extern bool get_builtin_firmware(struct cpio_data *cd, const char *name);
 extern bool initrd_gone;
+void microcode_bsp_resume(void);
 #else
 static inline int __init microcode_init(void)			{ return 0; };
 static inline void __init load_ucode_bsp(void)			{ }
 static inline void load_ucode_ap(void)				{ }
-static inline void reload_early_microcode(void)			{ }
+static inline void reload_early_microcode(unsigned int cpu)	{ }
+static inline void microcode_bsp_resume(void)			{ }
 static inline bool
 get_builtin_firmware(struct cpio_data *cd, const char *name)	{ return false; }
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/microcode_amd.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/microcode_amd.h
@@ -41,18 +41,20 @@
 	unsigned int			mpb[0];
 };
 
-#define PATCH_MAX_SIZE PAGE_SIZE
+#define PATCH_MAX_SIZE (3 * PAGE_SIZE)
 
 #ifdef CONFIG_MICROCODE_AMD
 extern void __init load_ucode_amd_bsp(unsigned int family);
 extern void load_ucode_amd_ap(unsigned int family);
 extern int __init save_microcode_in_initrd_amd(unsigned int family);
-void reload_ucode_amd(void);
+void reload_ucode_amd(unsigned int cpu);
+extern void amd_check_microcode(void);
 #else
 static inline void __init load_ucode_amd_bsp(unsigned int family) {}
 static inline void load_ucode_amd_ap(unsigned int family) {}
 static inline int __init
 save_microcode_in_initrd_amd(unsigned int family) { return -EINVAL; }
-void reload_ucode_amd(void) {}
+static inline void reload_ucode_amd(unsigned int cpu) {}
+static inline void amd_check_microcode(void) {}
 #endif
 #endif /* _ASM_X86_MICROCODE_AMD_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/mmu_context.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/mmu_context.h
@@ -379,6 +379,15 @@
 	temp_mm_state_t temp_state;
 
 	lockdep_assert_irqs_disabled();
+
+	/*
+	 * Make sure not to be in TLB lazy mode, as otherwise we'll end up
+	 * with a stale address space WITHOUT being in lazy mode after
+	 * restoring the previous mm.
+	 */
+	if (this_cpu_read(cpu_tlbstate.is_lazy))
+		leave_mm(smp_processor_id());
+
 	temp_state.mm = this_cpu_read(cpu_tlbstate.loaded_mm);
 	switch_mm_irqs_off(NULL, mm, current);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/msr-index.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/msr-index.h
@@ -30,6 +30,7 @@
 #define _EFER_SVME		12 /* Enable virtualization */
 #define _EFER_LMSLE		13 /* Long Mode Segment Limit Enable */
 #define _EFER_FFXSR		14 /* Enable Fast FXSAVE/FXRSTOR */
+#define _EFER_AUTOIBRS		21 /* Enable Automatic IBRS */
 
 #define EFER_SCE		(1<<_EFER_SCE)
 #define EFER_LME		(1<<_EFER_LME)
@@ -38,6 +39,7 @@
 #define EFER_SVME		(1<<_EFER_SVME)
 #define EFER_LMSLE		(1<<_EFER_LMSLE)
 #define EFER_FFXSR		(1<<_EFER_FFXSR)
+#define EFER_AUTOIBRS		(1<<_EFER_AUTOIBRS)
 
 /* Intel MSRs. Some also available on other CPUs */
 
@@ -47,6 +49,15 @@
 #define SPEC_CTRL_STIBP			BIT(SPEC_CTRL_STIBP_SHIFT)	/* STIBP mask */
 #define SPEC_CTRL_SSBD_SHIFT		2	   /* Speculative Store Bypass Disable bit */
 #define SPEC_CTRL_SSBD			BIT(SPEC_CTRL_SSBD_SHIFT)	/* Speculative Store Bypass Disable */
+#define SPEC_CTRL_RRSBA_DIS_S_SHIFT	6	   /* Disable RRSBA behavior */
+#define SPEC_CTRL_RRSBA_DIS_S		BIT(SPEC_CTRL_RRSBA_DIS_S_SHIFT)
+#define SPEC_CTRL_BHI_DIS_S_SHIFT	10	   /* Disable Branch History Injection behavior */
+#define SPEC_CTRL_BHI_DIS_S		BIT(SPEC_CTRL_BHI_DIS_S_SHIFT)
+
+/* A mask for bits which the kernel toggles when controlling mitigations */
+#define SPEC_CTRL_MITIGATIONS_MASK	(SPEC_CTRL_IBRS | SPEC_CTRL_STIBP | SPEC_CTRL_SSBD \
+							| SPEC_CTRL_RRSBA_DIS_S \
+							| SPEC_CTRL_BHI_DIS_S)
 
 #define MSR_IA32_PRED_CMD		0x00000049 /* Prediction Command */
 #define PRED_CMD_IBPB			BIT(0)	   /* Indirect Branch Prediction Barrier */
@@ -82,6 +93,7 @@
 #define MSR_IA32_ARCH_CAPABILITIES	0x0000010a
 #define ARCH_CAP_RDCL_NO		BIT(0)	/* Not susceptible to Meltdown */
 #define ARCH_CAP_IBRS_ALL		BIT(1)	/* Enhanced IBRS support */
+#define ARCH_CAP_RSBA			BIT(2)	/* RET may use alternative branch predictors */
 #define ARCH_CAP_SKIP_VMENTRY_L1DFLUSH	BIT(3)	/* Skip L1D flush on vmentry */
 #define ARCH_CAP_SSB_NO			BIT(4)	/*
 						 * Not susceptible to Speculative Store Bypass
@@ -105,6 +117,54 @@
 						 * Not susceptible to
 						 * TSX Async Abort (TAA) vulnerabilities.
 						 */
+#define ARCH_CAP_SBDR_SSDP_NO		BIT(13)	/*
+						 * Not susceptible to SBDR and SSDP
+						 * variants of Processor MMIO stale data
+						 * vulnerabilities.
+						 */
+#define ARCH_CAP_FBSDP_NO		BIT(14)	/*
+						 * Not susceptible to FBSDP variant of
+						 * Processor MMIO stale data
+						 * vulnerabilities.
+						 */
+#define ARCH_CAP_PSDP_NO		BIT(15)	/*
+						 * Not susceptible to PSDP variant of
+						 * Processor MMIO stale data
+						 * vulnerabilities.
+						 */
+#define ARCH_CAP_FB_CLEAR		BIT(17)	/*
+						 * VERW clears CPU fill buffer
+						 * even on MDS_NO CPUs.
+						 */
+#define ARCH_CAP_FB_CLEAR_CTRL		BIT(18)	/*
+						 * MSR_IA32_MCU_OPT_CTRL[FB_CLEAR_DIS]
+						 * bit available to control VERW
+						 * behavior.
+						 */
+#define ARCH_CAP_RRSBA			BIT(19)	/*
+						 * Indicates RET may use predictors
+						 * other than the RSB. With eIBRS
+						 * enabled predictions in kernel mode
+						 * are restricted to targets in
+						 * kernel.
+						 */
+#define ARCH_CAP_BHI_NO			BIT(20)	/*
+						 * CPU is not affected by Branch
+						 * History Injection.
+						 */
+#define ARCH_CAP_PBRSB_NO		BIT(24)	/*
+						 * Not susceptible to Post-Barrier
+						 * Return Stack Buffer Predictions.
+						 */
+#define ARCH_CAP_GDS_CTRL		BIT(25)	/*
+						 * CPU is vulnerable to Gather
+						 * Data Sampling (GDS) and
+						 * has controls for mitigation.
+						 */
+#define ARCH_CAP_GDS_NO			BIT(26)	/*
+						 * CPU is not vulnerable to Gather
+						 * Data Sampling (GDS).
+						 */
 
 #define MSR_IA32_FLUSH_CMD		0x0000010b
 #define L1D_FLUSH			BIT(0)	/*
@@ -119,6 +179,13 @@
 #define TSX_CTRL_RTM_DISABLE		BIT(0)	/* Disable RTM feature */
 #define TSX_CTRL_CPUID_CLEAR		BIT(1)	/* Disable TSX enumeration */
 
+/* SRBDS support */
+#define MSR_IA32_MCU_OPT_CTRL		0x00000123
+#define RNGDS_MITG_DIS			BIT(0)
+#define FB_CLEAR_DIS			BIT(3)	/* CPU Fill buffer clear disable */
+#define GDS_MITG_DIS			BIT(4)	/* Disable GDS mitigation */
+#define GDS_MITG_LOCKED			BIT(5)	/* GDS mitigation locked */
+
 #define MSR_IA32_SYSENTER_CS		0x00000174
 #define MSR_IA32_SYSENTER_ESP		0x00000175
 #define MSR_IA32_SYSENTER_EIP		0x00000176
@@ -411,6 +478,13 @@
 #define MSR_AMD64_OSVW_STATUS		0xc0010141
 #define MSR_AMD64_LS_CFG		0xc0011020
 #define MSR_AMD64_DC_CFG		0xc0011022
+#define MSR_AMD64_TW_CFG		0xc0011023
+
+#define MSR_AMD64_DE_CFG		0xc0011029
+#define MSR_AMD64_DE_CFG_LFENCE_SERIALIZE_BIT	 1
+#define MSR_AMD64_DE_CFG_LFENCE_SERIALIZE	BIT_ULL(MSR_AMD64_DE_CFG_LFENCE_SERIALIZE_BIT)
+#define MSR_AMD64_DE_CFG_ZEN2_FP_BACKUP_FIX_BIT 9
+
 #define MSR_AMD64_BU_CFG2		0xc001102a
 #define MSR_AMD64_IBSFETCHCTL		0xc0011030
 #define MSR_AMD64_IBSFETCHLINAD		0xc0011031
@@ -428,14 +502,20 @@
 #define MSR_AMD64_IBSOP_REG_MASK	((1UL<<MSR_AMD64_IBSOP_REG_COUNT)-1)
 #define MSR_AMD64_IBSCTL		0xc001103a
 #define MSR_AMD64_IBSBRTARGET		0xc001103b
+#define MSR_AMD64_ICIBSEXTDCTL		0xc001103c
 #define MSR_AMD64_IBSOPDATA4		0xc001103d
 #define MSR_AMD64_IBS_REG_COUNT_MAX	8 /* includes MSR_AMD64_IBSBRTARGET */
+#define MSR_AMD64_VM_PAGE_FLUSH		0xc001011e
 #define MSR_AMD64_SEV			0xc0010131
 #define MSR_AMD64_SEV_ENABLED_BIT	0
 #define MSR_AMD64_SEV_ENABLED		BIT_ULL(MSR_AMD64_SEV_ENABLED_BIT)
 
 #define MSR_AMD64_VIRT_SPEC_CTRL	0xc001011f
 
+/* Zen4 */
+#define MSR_ZEN4_BP_CFG			0xc001102e
+#define MSR_ZEN4_BP_CFG_SHARED_BTB_FIX_BIT 5
+
 /* Fam 17h MSRs */
 #define MSR_F17H_IRPERF			0xc00000e9
 
@@ -478,9 +558,6 @@
 #define FAM10H_MMIO_CONF_BASE_MASK	0xfffffffULL
 #define FAM10H_MMIO_CONF_BASE_SHIFT	20
 #define MSR_FAM10H_NODE_ID		0xc001100c
-#define MSR_F10H_DECFG			0xc0011029
-#define MSR_F10H_DECFG_LFENCE_SERIALIZE_BIT	1
-#define MSR_F10H_DECFG_LFENCE_SERIALIZE		BIT_ULL(MSR_F10H_DECFG_LFENCE_SERIALIZE_BIT)
 
 /* K8 MSRs */
 #define MSR_K8_TOP_MEM1			0xc001001a
@@ -510,6 +587,8 @@
 #define MSR_K7_HWCR			0xc0010015
 #define MSR_K7_HWCR_SMMLOCK_BIT		0
 #define MSR_K7_HWCR_SMMLOCK		BIT_ULL(MSR_K7_HWCR_SMMLOCK_BIT)
+#define MSR_K7_HWCR_IRPERF_EN_BIT	30
+#define MSR_K7_HWCR_IRPERF_EN		BIT_ULL(MSR_K7_HWCR_IRPERF_EN_BIT)
 #define MSR_K7_FID_VID_CTL		0xc0010041
 #define MSR_K7_FID_VID_STATUS		0xc0010042
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/msr.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/msr.h
@@ -88,7 +88,7 @@
  * think of extending them - you will be slapped with a stinking trout or a frozen
  * shark will reach you, wherever you are! You've been warned.
  */
-static inline unsigned long long notrace __rdmsr(unsigned int msr)
+static __always_inline unsigned long long __rdmsr(unsigned int msr)
 {
 	DECLARE_ARGS(val, low, high);
 
@@ -100,7 +100,7 @@
 	return EAX_EDX_VAL(val, low, high);
 }
 
-static inline void notrace __wrmsr(unsigned int msr, u32 low, u32 high)
+static __always_inline void __wrmsr(unsigned int msr, u32 low, u32 high)
 {
 	asm volatile("1: wrmsr\n"
 		     "2:\n"
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/nmi.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/nmi.h
@@ -41,7 +41,6 @@
 	struct list_head	list;
 	nmi_handler_t		handler;
 	u64			max_duration;
-	struct irq_work		irq_work;
 	unsigned long		flags;
 	const char		*name;
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/nospec-branch.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/nospec-branch.h
@@ -4,12 +4,17 @@
 #define _ASM_X86_NOSPEC_BRANCH_H_
 
 #include <linux/static_key.h>
+#include <linux/frame.h>
 
 #include <asm/alternative.h>
 #include <asm/alternative-asm.h>
 #include <asm/cpufeatures.h>
 #include <asm/msr-index.h>
+#include <asm/unwind_hints.h>
+#include <asm/percpu.h>
 
+#include <linux/frame.h>
+#include <asm/unwind_hints.h>
 /*
  * This should be used immediately before a retpoline alternative. It tells
  * objtool where the retpolines are so that it can make sense of the control
@@ -44,24 +49,44 @@
  * the optimal version — two calls, each with their own speculation
  * trap should their return address end up getting used, in a loop.
  */
+#ifdef CONFIG_X86_64
 #define __FILL_RETURN_BUFFER(reg, nr, sp)	\
 	mov	$(nr/2), reg;			\
 771:						\
+	ANNOTATE_INTRA_FUNCTION_CALL;           \
 	call	772f;				\
 773:	/* speculation trap */			\
+	UNWIND_HINT_EMPTY;		\
 	pause;					\
 	lfence;					\
 	jmp	773b;				\
 772:						\
+	ANNOTATE_INTRA_FUNCTION_CALL;           \
 	call	774f;				\
 775:	/* speculation trap */			\
+	UNWIND_HINT_EMPTY;                      \
 	pause;					\
 	lfence;					\
 	jmp	775b;				\
 774:						\
+	add	$(BITS_PER_LONG/8) * 2, sp;	\
 	dec	reg;				\
 	jnz	771b;				\
+	/* barrier for jnz misprediction */	\
+	lfence;
+#else
+/*
+ * i386 doesn't unconditionally have LFENCE, as such it can't
+ * do a loop.
+ */
+#define __FILL_RETURN_BUFFER(reg, nr, sp)	\
+	.rept nr;				\
+	call	772f;				\
+	int3;					\
+772:;						\
+	.endr;					\
 	add	$(BITS_PER_LONG/8) * nr, sp;
+#endif
 
 #ifdef __ASSEMBLY__
 
@@ -115,7 +140,7 @@
 	ANNOTATE_NOSPEC_ALTERNATIVE
 	ALTERNATIVE_2 __stringify(ANNOTATE_RETPOLINE_SAFE; jmp *\reg),	\
 		__stringify(RETPOLINE_JMP \reg), X86_FEATURE_RETPOLINE,	\
-		__stringify(lfence; ANNOTATE_RETPOLINE_SAFE; jmp *\reg), X86_FEATURE_RETPOLINE_AMD
+		__stringify(lfence; ANNOTATE_RETPOLINE_SAFE; jmp *\reg), X86_FEATURE_RETPOLINE_LFENCE
 #else
 	jmp	*\reg
 #endif
@@ -126,26 +151,50 @@
 	ANNOTATE_NOSPEC_ALTERNATIVE
 	ALTERNATIVE_2 __stringify(ANNOTATE_RETPOLINE_SAFE; call *\reg),	\
 		__stringify(RETPOLINE_CALL \reg), X86_FEATURE_RETPOLINE,\
-		__stringify(lfence; ANNOTATE_RETPOLINE_SAFE; call *\reg), X86_FEATURE_RETPOLINE_AMD
+		__stringify(lfence; ANNOTATE_RETPOLINE_SAFE; call *\reg), X86_FEATURE_RETPOLINE_LFENCE
 #else
 	call	*\reg
 #endif
 .endm
 
+.macro ISSUE_UNBALANCED_RET_GUARD
+	ANNOTATE_INTRA_FUNCTION_CALL;
+	call .Lunbalanced_ret_guard_\@
+	int3
+.Lunbalanced_ret_guard_\@:
+	add $(BITS_PER_LONG/8), %_ASM_SP
+	lfence
+.endm
+
  /*
   * A simpler FILL_RETURN_BUFFER macro. Don't make people use the CPP
   * monstrosity above, manually.
   */
-.macro FILL_RETURN_BUFFER reg:req nr:req ftr:req
-#ifdef CONFIG_RETPOLINE
-	ANNOTATE_NOSPEC_ALTERNATIVE
-	ALTERNATIVE "jmp .Lskip_rsb_\@",				\
-		__stringify(__FILL_RETURN_BUFFER(\reg,\nr,%_ASM_SP))	\
-		\ftr
+.macro FILL_RETURN_BUFFER reg:req nr:req ftr:req ftr2
+.ifb \ftr2
+	ALTERNATIVE "jmp .Lskip_rsb_\@", "", \ftr
+.else
+	ALTERNATIVE_2 "jmp .Lskip_rsb_\@", "", \ftr, "jmp .Lunbalanced_\@", \ftr2
+.endif
+	__FILL_RETURN_BUFFER(\reg,\nr,%_ASM_SP)
+.Lunbalanced_\@:
+	ISSUE_UNBALANCED_RET_GUARD
 .Lskip_rsb_\@:
-#endif
 .endm
 
+#ifdef CONFIG_X86_64
+.macro CLEAR_BRANCH_HISTORY
+	ALTERNATIVE "", "call clear_bhb_loop", X86_FEATURE_CLEAR_BHB_LOOP
+.endm
+
+.macro CLEAR_BRANCH_HISTORY_VMEXIT
+	ALTERNATIVE "", "call clear_bhb_loop", X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT
+.endm
+#else
+#define CLEAR_BRANCH_HISTORY
+#define CLEAR_BRANCH_HISTORY_VMEXIT
+#endif
+
 #else /* __ASSEMBLY__ */
 
 #define ANNOTATE_RETPOLINE_SAFE					\
@@ -154,6 +203,10 @@
 	_ASM_PTR " 999b\n\t"					\
 	".popsection\n\t"
 
+#ifdef CONFIG_X86_64
+extern void clear_bhb_loop(void);
+#endif
+
 #ifdef CONFIG_RETPOLINE
 #ifdef CONFIG_X86_64
 
@@ -171,7 +224,7 @@
 	"lfence;\n"						\
 	ANNOTATE_RETPOLINE_SAFE					\
 	"call *%[thunk_target]\n",				\
-	X86_FEATURE_RETPOLINE_AMD)
+	X86_FEATURE_RETPOLINE_LFENCE)
 # define THUNK_TARGET(addr) [thunk_target] "r" (addr)
 
 #else /* CONFIG_X86_32 */
@@ -201,7 +254,7 @@
 	"lfence;\n"						\
 	ANNOTATE_RETPOLINE_SAFE					\
 	"call *%[thunk_target]\n",				\
-	X86_FEATURE_RETPOLINE_AMD)
+	X86_FEATURE_RETPOLINE_LFENCE)
 
 # define THUNK_TARGET(addr) [thunk_target] "rm" (addr)
 #endif
@@ -213,9 +266,12 @@
 /* The Spectre V2 mitigation variants */
 enum spectre_v2_mitigation {
 	SPECTRE_V2_NONE,
-	SPECTRE_V2_RETPOLINE_GENERIC,
-	SPECTRE_V2_RETPOLINE_AMD,
-	SPECTRE_V2_IBRS_ENHANCED,
+	SPECTRE_V2_RETPOLINE,
+	SPECTRE_V2_LFENCE,
+	SPECTRE_V2_EIBRS,
+	SPECTRE_V2_EIBRS_RETPOLINE,
+	SPECTRE_V2_EIBRS_LFENCE,
+	SPECTRE_V2_IBRS,
 };
 
 /* The indirect branch speculation control variants */
@@ -270,6 +326,8 @@
 		: "memory");
 }
 
+DECLARE_PER_CPU(bool, x86_ibpb_exit_to_user);
+
 static inline void indirect_branch_prediction_barrier(void)
 {
 	u64 val = PRED_CMD_IBPB;
@@ -279,6 +337,9 @@
 
 /* The Intel SPEC CTRL MSR base value cache */
 extern u64 x86_spec_ctrl_base;
+DECLARE_PER_CPU(u64, x86_spec_ctrl_current);
+extern void update_spec_ctrl_cond(u64 val);
+extern u64 spec_ctrl_current(void);
 
 /*
  * With retpoline, we must use IBRS to restrict branch prediction
@@ -288,18 +349,16 @@
  */
 #define firmware_restrict_branch_speculation_start()			\
 do {									\
-	u64 val = x86_spec_ctrl_base | SPEC_CTRL_IBRS;			\
-									\
 	preempt_disable();						\
-	alternative_msr_write(MSR_IA32_SPEC_CTRL, val,			\
+	alternative_msr_write(MSR_IA32_SPEC_CTRL,			\
+			      spec_ctrl_current() | SPEC_CTRL_IBRS,	\
 			      X86_FEATURE_USE_IBRS_FW);			\
 } while (0)
 
 #define firmware_restrict_branch_speculation_end()			\
 do {									\
-	u64 val = x86_spec_ctrl_base;					\
-									\
-	alternative_msr_write(MSR_IA32_SPEC_CTRL, val,			\
+	alternative_msr_write(MSR_IA32_SPEC_CTRL,			\
+			      spec_ctrl_current(),			\
 			      X86_FEATURE_USE_IBRS_FW);			\
 	preempt_enable();						\
 } while (0)
@@ -311,6 +370,8 @@
 DECLARE_STATIC_KEY_FALSE(mds_user_clear);
 DECLARE_STATIC_KEY_FALSE(mds_idle_clear);
 
+DECLARE_STATIC_KEY_FALSE(mmio_stale_data_clear);
+
 #include <asm/segment.h>
 
 /**
@@ -320,7 +381,7 @@
  * combination with microcode which triggers a CPU buffer flush when the
  * instruction is executed.
  */
-static inline void mds_clear_cpu_buffers(void)
+static __always_inline void mds_clear_cpu_buffers(void)
 {
 	static const u16 ds = __KERNEL_DS;
 
@@ -341,7 +402,7 @@
  *
  * Clear CPU buffers if the corresponding static key is enabled
  */
-static inline void mds_user_clear_cpu_buffers(void)
+static __always_inline void mds_user_clear_cpu_buffers(void)
 {
 	if (static_branch_likely(&mds_user_clear))
 		mds_clear_cpu_buffers();
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/numa.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/numa.h
@@ -11,13 +11,6 @@
 
 #define NR_NODE_MEMBLKS		(MAX_NUMNODES*2)
 
-/*
- * Too small node sizes may confuse the VM badly. Usually they
- * result from BIOS bugs. So dont recognize nodes as standalone
- * NUMA entities that have less than this amount of RAM listed:
- */
-#define NODE_MIN_SIZE (4*1024*1024)
-
 extern int numa_off;
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/page_64_types.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/page_64_types.h
@@ -15,7 +15,7 @@
 #define THREAD_SIZE_ORDER	(2 + KASAN_STACK_ORDER)
 #define THREAD_SIZE  (PAGE_SIZE << THREAD_SIZE_ORDER)
 
-#define EXCEPTION_STACK_ORDER (0 + KASAN_STACK_ORDER)
+#define EXCEPTION_STACK_ORDER (1 + KASAN_STACK_ORDER)
 #define EXCEPTION_STKSZ (PAGE_SIZE << EXCEPTION_STACK_ORDER)
 
 #define IRQ_STACK_ORDER (2 + KASAN_STACK_ORDER)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/pci-direct.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/pci-direct.h
@@ -10,9 +10,11 @@
 extern u32 read_pci_config(u8 bus, u8 slot, u8 func, u8 offset);
 extern u8 read_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset);
 extern u16 read_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset);
+extern u32 pci_early_find_cap(int bus, int slot, int func, int cap);
 extern void write_pci_config(u8 bus, u8 slot, u8 func, u8 offset, u32 val);
 extern void write_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset, u8 val);
 extern void write_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset, u16 val);
 
+extern unsigned int pci_early_clear_msi;
 extern int early_pci_allowed(void);
 #endif /* _ASM_X86_PCI_DIRECT_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/pgtable.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/pgtable.h
@@ -253,6 +253,7 @@
 }
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
+/* NOTE: when predicate huge page, consider also pmd_devmap, or use pmd_large */
 static inline int pmd_trans_huge(pmd_t pmd)
 {
 	return (pmd_val(pmd) & (_PAGE_PSE|_PAGE_DEVMAP)) == _PAGE_PSE;
@@ -624,12 +625,15 @@
 	return __pmd(val);
 }
 
-/* mprotect needs to preserve PAT bits when updating vm_page_prot */
+/*
+ * mprotect needs to preserve PAT and encryption bits when updating
+ * vm_page_prot
+ */
 #define pgprot_modify pgprot_modify
 static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot)
 {
 	pgprotval_t preservebits = pgprot_val(oldprot) & _PAGE_CHG_MASK;
-	pgprotval_t addbits = pgprot_val(newprot);
+	pgprotval_t addbits = pgprot_val(newprot) & ~_PAGE_CHG_MASK;
 	return __pgprot(preservebits | addbits);
 }
 
@@ -1371,8 +1375,8 @@
 #endif
 #endif
 
-#define PKRU_AD_BIT 0x1
-#define PKRU_WD_BIT 0x2
+#define PKRU_AD_BIT 0x1u
+#define PKRU_WD_BIT 0x2u
 #define PKRU_BITS_PER_PKEY 2
 
 #ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/pgtable_32_types.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/pgtable_32_types.h
@@ -44,11 +44,11 @@
  * Define this here and validate with BUILD_BUG_ON() in pgtable_32.c
  * to avoid include recursion hell
  */
-#define CPU_ENTRY_AREA_PAGES	(NR_CPUS * 40)
+#define CPU_ENTRY_AREA_PAGES	(NR_CPUS * 39)
 
-#define CPU_ENTRY_AREA_BASE						\
-	((FIXADDR_TOT_START - PAGE_SIZE * (CPU_ENTRY_AREA_PAGES + 1))   \
-	 & PMD_MASK)
+/* The +1 is for the readonly IDT page: */
+#define CPU_ENTRY_AREA_BASE	\
+	((FIXADDR_TOT_START - PAGE_SIZE*(CPU_ENTRY_AREA_PAGES+1)) & PMD_MASK)
 
 #define LDT_BASE_ADDR		\
 	((CPU_ENTRY_AREA_BASE - PAGE_SIZE) & PMD_MASK)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/pgtable_types.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/pgtable_types.h
@@ -123,7 +123,7 @@
  */
 #define _PAGE_CHG_MASK	(PTE_PFN_MASK | _PAGE_PCD | _PAGE_PWT |		\
 			 _PAGE_SPECIAL | _PAGE_ACCESSED | _PAGE_DIRTY |	\
-			 _PAGE_SOFT_DIRTY | _PAGE_DEVMAP)
+			 _PAGE_SOFT_DIRTY | _PAGE_DEVMAP | _PAGE_ENC)
 #define _HPAGE_CHG_MASK (_PAGE_CHG_MASK | _PAGE_PSE)
 
 /*
@@ -147,6 +147,7 @@
 #endif
 
 #define _PAGE_CACHE_MASK	(_PAGE_PAT | _PAGE_PCD | _PAGE_PWT)
+#define _PAGE_LARGE_CACHE_MASK	(_PAGE_PWT | _PAGE_PCD | _PAGE_PAT_LARGE)
 #define _PAGE_NOCACHE		(cachemode2protval(_PAGE_CACHE_MODE_UC))
 #define _PAGE_CACHE_WP		(cachemode2protval(_PAGE_CACHE_MODE_WP))
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/pkeys.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/pkeys.h
@@ -4,6 +4,11 @@
 
 #define ARCH_DEFAULT_PKEY	0
 
+/*
+ * If more than 16 keys are ever supported, a thorough audit
+ * will be necessary to ensure that the types that store key
+ * numbers and masks have sufficient capacity.
+ */
 #define arch_max_pkey() (boot_cpu_has(X86_FEATURE_OSPKE) ? 16 : 1)
 
 extern int arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/processor.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/processor.h
@@ -334,7 +334,7 @@
 #define INVALID_IO_BITMAP_OFFSET	0x8000
 
 struct entry_stack {
-	unsigned long		words[64];
+	char	stack[PAGE_SIZE];
 };
 
 struct entry_stack_page {
@@ -487,7 +487,6 @@
 
 	mm_segment_t		addr_limit;
 
-	unsigned int		sig_on_uaccess_err:1;
 	unsigned int		uaccess_err:1;	/* uaccess failed */
 
 	/* Floating point and extended processor state */
@@ -507,15 +506,6 @@
 }
 
 /*
- * Thread-synchronous status.
- *
- * This is different from the flags in that nobody else
- * ever touches our thread-synchronous status, so we don't
- * have to worry about atomic accesses.
- */
-#define TS_COMPAT		0x0002	/* 32bit syscall active (64BIT)*/
-
-/*
  * Set IOPL bits in EFLAGS from given mask
  */
 static inline void native_set_iopl_mask(unsigned mask)
@@ -936,9 +926,11 @@
 #ifdef CONFIG_CPU_SUP_AMD
 extern u16 amd_get_nb_id(int cpu);
 extern u32 amd_get_nodes_per_socket(void);
+extern void amd_clear_divider(void);
 #else
 static inline u16 amd_get_nb_id(int cpu)		{ return 0; }
 static inline u32 amd_get_nodes_per_socket(void)	{ return 0; }
+static inline void amd_clear_divider(void)		{ }
 #endif
 
 static inline uint32_t hypervisor_cpuid_base(const char *sig, uint32_t leaves)
@@ -995,4 +987,6 @@
 	TAA_MITIGATION_TSX_DISABLED,
 };
 
+extern bool gds_ucode_mitigated(void);
+
 #endif /* _ASM_X86_PROCESSOR_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/proto.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/proto.h
@@ -4,6 +4,8 @@
 
 #include <asm/ldt.h>
 
+struct task_struct;
+
 /* misc architecture specific prototypes */
 
 void syscall_init(void);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/ptrace.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/ptrace.h
@@ -309,8 +309,8 @@
 	static const unsigned int argument_offs[] = {
 #ifdef __i386__
 		offsetof(struct pt_regs, ax),
-		offsetof(struct pt_regs, cx),
 		offsetof(struct pt_regs, dx),
+		offsetof(struct pt_regs, cx),
 #define NR_REG_ARGUMENTS 3
 #else
 		offsetof(struct pt_regs, di),
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/realmode.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/realmode.h
@@ -82,6 +82,7 @@
 }
 
 void reserve_real_mode(void);
+void load_trampoline_pgtable(void);
 
 #endif /* __ASSEMBLY__ */
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/reboot.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/reboot.h
@@ -25,6 +25,8 @@
 #define MRR_BIOS	0
 #define MRR_APM		1
 
+void cpu_emergency_disable_virtualization(void);
+
 typedef void (*nmi_shootdown_cb)(int, struct pt_regs*);
 void nmi_panic_self_stop(struct pt_regs *regs);
 void nmi_shootdown_cpus(nmi_shootdown_cb callback);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/required-features.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/required-features.h
@@ -101,6 +101,9 @@
 #define REQUIRED_MASK16	0
 #define REQUIRED_MASK17	0
 #define REQUIRED_MASK18	0
-#define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 19)
+#define REQUIRED_MASK19	0
+#define REQUIRED_MASK20	0
+#define REQUIRED_MASK21	0
+#define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 22)
 
 #endif /* _ASM_X86_REQUIRED_FEATURES_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/resctrl_sched.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/resctrl_sched.h
@@ -51,24 +51,27 @@
  *   simple as possible.
  * Must be called with preemption disabled.
  */
-static void __resctrl_sched_in(void)
+static inline void __resctrl_sched_in(struct task_struct *tsk)
 {
 	struct resctrl_pqr_state *state = this_cpu_ptr(&pqr_state);
 	u32 closid = state->default_closid;
 	u32 rmid = state->default_rmid;
+	u32 tmp;
 
 	/*
 	 * If this task has a closid/rmid assigned, use it.
 	 * Else use the closid/rmid assigned to this cpu.
 	 */
 	if (static_branch_likely(&rdt_alloc_enable_key)) {
-		if (current->closid)
-			closid = current->closid;
+		tmp = READ_ONCE(tsk->closid);
+		if (tmp)
+			closid = tmp;
 	}
 
 	if (static_branch_likely(&rdt_mon_enable_key)) {
-		if (current->rmid)
-			rmid = current->rmid;
+		tmp = READ_ONCE(tsk->rmid);
+		if (tmp)
+			rmid = tmp;
 	}
 
 	if (closid != state->cur_closid || rmid != state->cur_rmid) {
@@ -78,15 +81,15 @@
 	}
 }
 
-static inline void resctrl_sched_in(void)
+static inline void resctrl_sched_in(struct task_struct *tsk)
 {
 	if (static_branch_likely(&rdt_enable_key))
-		__resctrl_sched_in();
+		__resctrl_sched_in(tsk);
 }
 
 #else
 
-static inline void resctrl_sched_in(void) {}
+static inline void resctrl_sched_in(struct task_struct *tsk) {}
 
 #endif /* CONFIG_X86_CPU_RESCTRL */
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/segment.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/segment.h
@@ -31,6 +31,18 @@
  */
 #define SEGMENT_RPL_MASK	0x3
 
+/*
+ * When running on Xen PV, the actual privilege level of the kernel is 1,
+ * not 0. Testing the Requested Privilege Level in a segment selector to
+ * determine whether the context is user mode or kernel mode with
+ * SEGMENT_RPL_MASK is wrong because the PV kernel's privilege level
+ * matches the 0x3 mask.
+ *
+ * Testing with USER_SEGMENT_RPL_MASK is valid for both native and Xen PV
+ * kernels because privilege level 2 is never used.
+ */
+#define USER_SEGMENT_RPL_MASK	0x2
+
 /* User mode is privilege level 3: */
 #define USER_RPL		0x3
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/set_memory.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/set_memory.h
@@ -85,28 +85,35 @@
 void set_kernel_text_ro(void);
 
 #ifdef CONFIG_X86_64
-static inline int set_mce_nospec(unsigned long pfn)
+/*
+ * Prevent speculative access to the page by either unmapping
+ * it (if we do not require access to any part of the page) or
+ * marking it uncacheable (if we want to try to retrieve data
+ * from non-poisoned lines in the page).
+ */
+static inline int set_mce_nospec(unsigned long pfn, bool unmap)
 {
 	unsigned long decoy_addr;
 	int rc;
 
 	/*
-	 * Mark the linear address as UC to make sure we don't log more
-	 * errors because of speculative access to the page.
 	 * We would like to just call:
-	 *      set_memory_uc((unsigned long)pfn_to_kaddr(pfn), 1);
+	 *      set_memory_XX((unsigned long)pfn_to_kaddr(pfn), 1);
 	 * but doing that would radically increase the odds of a
 	 * speculative access to the poison page because we'd have
 	 * the virtual address of the kernel 1:1 mapping sitting
 	 * around in registers.
 	 * Instead we get tricky.  We create a non-canonical address
 	 * that looks just like the one we want, but has bit 63 flipped.
-	 * This relies on set_memory_uc() properly sanitizing any __pa()
+	 * This relies on set_memory_XX() properly sanitizing any __pa()
 	 * results with __PHYSICAL_MASK or PTE_PFN_MASK.
 	 */
 	decoy_addr = (pfn << PAGE_SHIFT) + (PAGE_OFFSET ^ BIT(63));
 
-	rc = set_memory_uc(decoy_addr, 1);
+	if (unmap)
+		rc = set_memory_np(decoy_addr, 1);
+	else
+		rc = set_memory_uc(decoy_addr, 1);
 	if (rc)
 		pr_warn("Could not invalidate pfn=0x%lx from 1:1 map\n", pfn);
 	return rc;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/setup.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/setup.h
@@ -94,27 +94,16 @@
 void *extend_brk(size_t size, size_t align);
 
 /*
- * Reserve space in the brk section.  The name must be unique within
- * the file, and somewhat descriptive.  The size is in bytes.  Must be
- * used at file scope.
+ * Reserve space in the .brk section, which is a block of memory from which the
+ * caller is allowed to allocate very early (before even memblock is available)
+ * by calling extend_brk().  All allocated memory will be eventually converted
+ * to memblock.  Any leftover unallocated memory will be freed.
  *
- * (This uses a temp function to wrap the asm so we can pass it the
- * size parameter; otherwise we wouldn't be able to.  We can't use a
- * "section" attribute on a normal variable because it always ends up
- * being @progbits, which ends up allocating space in the vmlinux
- * executable.)
+ * The size is in bytes.
  */
-#define RESERVE_BRK(name,sz)						\
-	static void __section(.discard.text) __used notrace		\
-	__brk_reservation_fn_##name##__(void) {				\
-		asm volatile (						\
-			".pushsection .brk_reservation,\"aw\",@nobits;" \
-			".brk." #name ":"				\
-			" 1:.skip %c0;"					\
-			" .size .brk." #name ", . - 1b;"		\
-			" .popsection"					\
-			: : "i" (sz));					\
-	}
+#define RESERVE_BRK(name, size)					\
+	__section(.bss..brk) __aligned(1) __used	\
+	static char __brk_##name[size]
 
 /* Helper for reserving space for arrays of things */
 #define RESERVE_BRK_ARRAY(type, name, entries)		\
@@ -132,12 +121,19 @@
 
 #endif /* __i386__ */
 #endif /* _SETUP */
-#else
-#define RESERVE_BRK(name,sz)				\
-	.pushsection .brk_reservation,"aw",@nobits;	\
-.brk.name:						\
-1:	.skip sz;					\
-	.size .brk.name,.-1b;				\
+
+#else  /* __ASSEMBLY */
+
+.macro __RESERVE_BRK name, size
+	.pushsection .bss..brk, "aw"
+SYM_DATA_START(__brk_\name)
+	.skip \size
+SYM_DATA_END(__brk_\name)
 	.popsection
+.endm
+
+#define RESERVE_BRK(name, size) __RESERVE_BRK name, size
+
 #endif /* __ASSEMBLY__ */
+
 #endif /* _ASM_X86_SETUP_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/smap.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/smap.h
@@ -57,8 +57,10 @@
 {
 	unsigned long flags;
 
-	asm volatile (ALTERNATIVE("", "pushf; pop %0; " __ASM_CLAC,
-				  X86_FEATURE_SMAP)
+	asm volatile ("# smap_save\n\t"
+		      ALTERNATIVE("jmp 1f", "", X86_FEATURE_SMAP)
+		      "pushf; pop %0; " __ASM_CLAC "\n\t"
+		      "1:"
 		      : "=rm" (flags) : : "memory", "cc");
 
 	return flags;
@@ -66,7 +68,10 @@
 
 static __always_inline void smap_restore(unsigned long flags)
 {
-	asm volatile (ALTERNATIVE("", "push %0; popf", X86_FEATURE_SMAP)
+	asm volatile ("# smap_restore\n\t"
+		      ALTERNATIVE("jmp 1f", "", X86_FEATURE_SMAP)
+		      "push %0; popf\n\t"
+		      "1:"
 		      : : "g" (flags) : "memory", "cc");
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/special_insns.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/special_insns.h
@@ -10,45 +10,47 @@
 #include <linux/jump_label.h>
 
 /*
- * Volatile isn't enough to prevent the compiler from reordering the
- * read/write functions for the control registers and messing everything up.
- * A memory clobber would solve the problem, but would prevent reordering of
- * all loads stores around it, which can hurt performance. Solution is to
- * use a variable and mimic reads and writes to it to enforce serialization
+ * The compiler should not reorder volatile asm statements with respect to each
+ * other: they should execute in program order. However GCC 4.9.x and 5.x have
+ * a bug (which was fixed in 8.1, 7.3 and 6.5) where they might reorder
+ * volatile asm. The write functions are not affected since they have memory
+ * clobbers preventing reordering. To prevent reads from being reordered with
+ * respect to writes, use a dummy memory operand.
  */
-extern unsigned long __force_order;
+
+#define __FORCE_ORDER "m"(*(unsigned int *)0x1000UL)
 
 void native_write_cr0(unsigned long val);
 
 static inline unsigned long native_read_cr0(void)
 {
 	unsigned long val;
-	asm volatile("mov %%cr0,%0\n\t" : "=r" (val), "=m" (__force_order));
+	asm volatile("mov %%cr0,%0\n\t" : "=r" (val) : __FORCE_ORDER);
 	return val;
 }
 
 static inline unsigned long native_read_cr2(void)
 {
 	unsigned long val;
-	asm volatile("mov %%cr2,%0\n\t" : "=r" (val), "=m" (__force_order));
+	asm volatile("mov %%cr2,%0\n\t" : "=r" (val) : __FORCE_ORDER);
 	return val;
 }
 
 static inline void native_write_cr2(unsigned long val)
 {
-	asm volatile("mov %0,%%cr2": : "r" (val), "m" (__force_order));
+	asm volatile("mov %0,%%cr2": : "r" (val) : "memory");
 }
 
 static inline unsigned long __native_read_cr3(void)
 {
 	unsigned long val;
-	asm volatile("mov %%cr3,%0\n\t" : "=r" (val), "=m" (__force_order));
+	asm volatile("mov %%cr3,%0\n\t" : "=r" (val) : __FORCE_ORDER);
 	return val;
 }
 
 static inline void native_write_cr3(unsigned long val)
 {
-	asm volatile("mov %0,%%cr3": : "r" (val), "m" (__force_order));
+	asm volatile("mov %0,%%cr3": : "r" (val) : "memory");
 }
 
 static inline unsigned long native_read_cr4(void)
@@ -63,10 +65,10 @@
 	asm volatile("1: mov %%cr4, %0\n"
 		     "2:\n"
 		     _ASM_EXTABLE(1b, 2b)
-		     : "=r" (val), "=m" (__force_order) : "0" (0));
+		     : "=r" (val) : "0" (0), __FORCE_ORDER);
 #else
 	/* CR4 always exists on x86_64. */
-	asm volatile("mov %%cr4,%0\n\t" : "=r" (val), "=m" (__force_order));
+	asm volatile("mov %%cr4,%0\n\t" : "=r" (val) : __FORCE_ORDER);
 #endif
 	return val;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/stackprotector.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/stackprotector.h
@@ -55,8 +55,13 @@
 /*
  * Initialize the stackprotector canary value.
  *
- * NOTE: this must only be called from functions that never return,
+ * NOTE: this must only be called from functions that never return
  * and it must always be inlined.
+ *
+ * In addition, it should be called from a compilation unit for which
+ * stack protector is disabled. Alternatively, the caller should not end
+ * with a function call which gets tail-call optimized as that would
+ * lead to checking a modified canary value.
  */
 static __always_inline void boot_init_stack_canary(void)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/suspend_32.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/suspend_32.h
@@ -21,7 +21,6 @@
 #endif
 	unsigned long cr0, cr2, cr3, cr4;
 	u64 misc_enable;
-	bool misc_enable_saved;
 	struct saved_msrs saved_msrs;
 	struct desc_ptr gdt_desc;
 	struct desc_ptr idt;
@@ -30,6 +29,7 @@
 	unsigned long tr;
 	unsigned long safety;
 	unsigned long return_address;
+	bool misc_enable_saved;
 } __attribute__((packed));
 
 /* routines for saving/restoring kernel state */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/suspend_64.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/suspend_64.h
@@ -14,9 +14,13 @@
  * Image of the saved processor state, used by the low level ACPI suspend to
  * RAM code and by the low level hibernation code.
  *
- * If you modify it, fix arch/x86/kernel/acpi/wakeup_64.S and make sure that
- * __save/__restore_processor_state(), defined in arch/x86/kernel/suspend_64.c,
- * still work as required.
+ * If you modify it, check how it is used in arch/x86/kernel/acpi/wakeup_64.S
+ * and make sure that __save/__restore_processor_state(), defined in
+ * arch/x86/power/cpu.c, still work as required.
+ *
+ * Because the structure is packed, make sure to avoid unaligned members. For
+ * optimisation purposes but also because tools like kmemleak only search for
+ * pointers that are aligned.
  */
 struct saved_context {
 	struct pt_regs regs;
@@ -36,7 +40,6 @@
 
 	unsigned long cr0, cr2, cr3, cr4;
 	u64 misc_enable;
-	bool misc_enable_saved;
 	struct saved_msrs saved_msrs;
 	unsigned long efer;
 	u16 gdt_pad; /* Unused */
@@ -48,6 +51,7 @@
 	unsigned long tr;
 	unsigned long safety;
 	unsigned long return_address;
+	bool misc_enable_saved;
 } __attribute__((packed));
 
 #define loaddebug(thread,register) \
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/svm.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/svm.h
@@ -119,6 +119,8 @@
 #define V_IGN_TPR_SHIFT 20
 #define V_IGN_TPR_MASK (1 << V_IGN_TPR_SHIFT)
 
+#define V_IRQ_INJECTION_BITS_MASK (V_IRQ_MASK | V_INTR_PRIO_MASK | V_IGN_TPR_MASK)
+
 #define V_INTR_MASKING_SHIFT 24
 #define V_INTR_MASKING_MASK (1 << V_INTR_MASKING_SHIFT)
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/sync_core.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/sync_core.h
@@ -16,12 +16,13 @@
 	/* With PTI, we unconditionally serialize before running user code. */
 	if (static_cpu_has(X86_FEATURE_PTI))
 		return;
+
 	/*
-	 * Return from interrupt and NMI is done through iret, which is core
-	 * serializing.
+	 * Even if we're in an interrupt, we might reschedule before returning,
+	 * in which case we could switch to a different thread in the same mm
+	 * and return using SYSRET or SYSEXIT.  Instead of trying to keep
+	 * track of our need to sync the core, just sync right away.
 	 */
-	if (in_irq() || in_nmi())
-		return;
 	sync_core();
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/syscall.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/syscall.h
@@ -94,7 +94,12 @@
 					 struct pt_regs *regs,
 					 unsigned long *args)
 {
-	memcpy(args, &regs->bx, 6 * sizeof(args[0]));
+	args[0] = regs->bx;
+	args[1] = regs->cx;
+	args[2] = regs->dx;
+	args[3] = regs->si;
+	args[4] = regs->di;
+	args[5] = regs->bp;
 }
 
 static inline void syscall_set_arguments(struct task_struct *task,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/syscall_wrapper.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/syscall_wrapper.h
@@ -6,18 +6,37 @@
 #ifndef _ASM_X86_SYSCALL_WRAPPER_H
 #define _ASM_X86_SYSCALL_WRAPPER_H
 
+struct pt_regs;
+
 /* Mapping of registers to parameters for syscalls on x86-64 and x32 */
 #define SC_X86_64_REGS_TO_ARGS(x, ...)					\
 	__MAP(x,__SC_ARGS						\
 		,,regs->di,,regs->si,,regs->dx				\
 		,,regs->r10,,regs->r8,,regs->r9)			\
 
+
+/* SYSCALL_PT_ARGS is Adapted from s390x */
+#define SYSCALL_PT_ARG6(m, t1, t2, t3, t4, t5, t6)			\
+	SYSCALL_PT_ARG5(m, t1, t2, t3, t4, t5), m(t6, (regs->bp))
+#define SYSCALL_PT_ARG5(m, t1, t2, t3, t4, t5)				\
+	SYSCALL_PT_ARG4(m, t1, t2, t3, t4),  m(t5, (regs->di))
+#define SYSCALL_PT_ARG4(m, t1, t2, t3, t4)				\
+	SYSCALL_PT_ARG3(m, t1, t2, t3),  m(t4, (regs->si))
+#define SYSCALL_PT_ARG3(m, t1, t2, t3)					\
+	SYSCALL_PT_ARG2(m, t1, t2), m(t3, (regs->dx))
+#define SYSCALL_PT_ARG2(m, t1, t2)					\
+	SYSCALL_PT_ARG1(m, t1), m(t2, (regs->cx))
+#define SYSCALL_PT_ARG1(m, t1) m(t1, (regs->bx))
+#define SYSCALL_PT_ARGS(x, ...) SYSCALL_PT_ARG##x(__VA_ARGS__)
+
+#define __SC_COMPAT_CAST(t, a)						\
+	(__typeof(__builtin_choose_expr(__TYPE_IS_L(t), 0, 0U)))	\
+	(unsigned int)a
+
 /* Mapping of registers to parameters for syscalls on i386 */
 #define SC_IA32_REGS_TO_ARGS(x, ...)					\
-	__MAP(x,__SC_ARGS						\
-	      ,,(unsigned int)regs->bx,,(unsigned int)regs->cx		\
-	      ,,(unsigned int)regs->dx,,(unsigned int)regs->si		\
-	      ,,(unsigned int)regs->di,,(unsigned int)regs->bp)
+	SYSCALL_PT_ARGS(x, __SC_COMPAT_CAST,				\
+			__MAP(x, __SC_TYPE, __VA_ARGS__))		\
 
 #ifdef CONFIG_IA32_EMULATION
 /*
@@ -28,13 +47,21 @@
  * kernel/sys_ni.c and SYS_NI in kernel/time/posix-stubs.c to cover this
  * case as well.
  */
+#define __IA32_COMPAT_SYS_STUB0(x, name)				\
+	asmlinkage long __ia32_compat_sys_##name(const struct pt_regs *regs);\
+	ALLOW_ERROR_INJECTION(__ia32_compat_sys_##name, ERRNO);		\
+	asmlinkage long __ia32_compat_sys_##name(const struct pt_regs *regs)\
+	{								\
+		return __se_compat_sys_##name();			\
+	}
+
 #define __IA32_COMPAT_SYS_STUBx(x, name, ...)				\
 	asmlinkage long __ia32_compat_sys##name(const struct pt_regs *regs);\
 	ALLOW_ERROR_INJECTION(__ia32_compat_sys##name, ERRNO);		\
 	asmlinkage long __ia32_compat_sys##name(const struct pt_regs *regs)\
 	{								\
 		return __se_compat_sys##name(SC_IA32_REGS_TO_ARGS(x,__VA_ARGS__));\
-	}								\
+	}
 
 #define __IA32_SYS_STUBx(x, name, ...)					\
 	asmlinkage long __ia32_sys##name(const struct pt_regs *regs);	\
@@ -48,16 +75,23 @@
  * To keep the naming coherent, re-define SYSCALL_DEFINE0 to create an alias
  * named __ia32_sys_*()
  */
-#define SYSCALL_DEFINE0(sname)					\
-	SYSCALL_METADATA(_##sname, 0);				\
-	asmlinkage long __x64_sys_##sname(void);		\
-	ALLOW_ERROR_INJECTION(__x64_sys_##sname, ERRNO);	\
-	SYSCALL_ALIAS(__ia32_sys_##sname, __x64_sys_##sname);	\
-	asmlinkage long __x64_sys_##sname(void)
-
-#define COND_SYSCALL(name)						\
-	cond_syscall(__x64_sys_##name);					\
-	cond_syscall(__ia32_sys_##name)
+
+#define SYSCALL_DEFINE0(sname)						\
+	SYSCALL_METADATA(_##sname, 0);					\
+	asmlinkage long __x64_sys_##sname(const struct pt_regs *__unused);\
+	ALLOW_ERROR_INJECTION(__x64_sys_##sname, ERRNO);		\
+	SYSCALL_ALIAS(__ia32_sys_##sname, __x64_sys_##sname);		\
+	asmlinkage long __x64_sys_##sname(const struct pt_regs *__unused)
+
+#define COND_SYSCALL(name)							\
+	asmlinkage __weak long __x64_sys_##name(const struct pt_regs *__unused)	\
+	{									\
+		return sys_ni_syscall();					\
+	}									\
+	asmlinkage __weak long __ia32_sys_##name(const struct pt_regs *__unused)\
+	{									\
+		return sys_ni_syscall();					\
+	}
 
 #define SYS_NI(name)							\
 	SYSCALL_ALIAS(__x64_sys_##name, sys_ni_posix_timers);		\
@@ -75,15 +109,24 @@
  * of the x86-64-style parameter ordering of x32 syscalls. The syscalls common
  * with x86_64 obviously do not need such care.
  */
+#define __X32_COMPAT_SYS_STUB0(x, name, ...)				\
+	asmlinkage long __x32_compat_sys_##name(const struct pt_regs *regs);\
+	ALLOW_ERROR_INJECTION(__x32_compat_sys_##name, ERRNO);		\
+	asmlinkage long __x32_compat_sys_##name(const struct pt_regs *regs)\
+	{								\
+		return __se_compat_sys_##name();\
+	}
+
 #define __X32_COMPAT_SYS_STUBx(x, name, ...)				\
 	asmlinkage long __x32_compat_sys##name(const struct pt_regs *regs);\
 	ALLOW_ERROR_INJECTION(__x32_compat_sys##name, ERRNO);		\
 	asmlinkage long __x32_compat_sys##name(const struct pt_regs *regs)\
 	{								\
 		return __se_compat_sys##name(SC_X86_64_REGS_TO_ARGS(x,__VA_ARGS__));\
-	}								\
+	}
 
 #else /* CONFIG_X86_X32 */
+#define __X32_COMPAT_SYS_STUB0(x, name)
 #define __X32_COMPAT_SYS_STUBx(x, name, ...)
 #endif /* CONFIG_X86_X32 */
 
@@ -94,6 +137,17 @@
  * mapping of registers to parameters, we need to generate stubs for each
  * of them.
  */
+#define COMPAT_SYSCALL_DEFINE0(name)					\
+	static long __se_compat_sys_##name(void);			\
+	static inline long __do_compat_sys_##name(void);		\
+	__IA32_COMPAT_SYS_STUB0(x, name)				\
+	__X32_COMPAT_SYS_STUB0(x, name)					\
+	static long __se_compat_sys_##name(void)			\
+	{								\
+		return __do_compat_sys_##name();			\
+	}								\
+	static inline long __do_compat_sys_##name(void)
+
 #define COMPAT_SYSCALL_DEFINEx(x, name, ...)					\
 	static long __se_compat_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__));	\
 	static inline long __do_compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\
@@ -181,15 +235,19 @@
  * macros to work correctly.
  */
 #ifndef SYSCALL_DEFINE0
-#define SYSCALL_DEFINE0(sname)					\
-	SYSCALL_METADATA(_##sname, 0);				\
-	asmlinkage long __x64_sys_##sname(void);		\
-	ALLOW_ERROR_INJECTION(__x64_sys_##sname, ERRNO);	\
-	asmlinkage long __x64_sys_##sname(void)
+#define SYSCALL_DEFINE0(sname)						\
+	SYSCALL_METADATA(_##sname, 0);					\
+	asmlinkage long __x64_sys_##sname(const struct pt_regs *__unused);\
+	ALLOW_ERROR_INJECTION(__x64_sys_##sname, ERRNO);		\
+	asmlinkage long __x64_sys_##sname(const struct pt_regs *__unused)
 #endif
 
 #ifndef COND_SYSCALL
-#define COND_SYSCALL(name) cond_syscall(__x64_sys_##name)
+#define COND_SYSCALL(name) 							\
+	asmlinkage __weak long __x64_sys_##name(const struct pt_regs *__unused)	\
+	{									\
+		return sys_ni_syscall();					\
+	}
 #endif
 
 #ifndef SYS_NI
@@ -201,7 +259,6 @@
  * For VSYSCALLS, we need to declare these three syscalls with the new
  * pt_regs-based calling convention for in-kernel use.
  */
-struct pt_regs;
 asmlinkage long __x64_sys_getcpu(const struct pt_regs *regs);
 asmlinkage long __x64_sys_gettimeofday(const struct pt_regs *regs);
 asmlinkage long __x64_sys_time(const struct pt_regs *regs);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/thread_info.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/thread_info.h
@@ -221,10 +221,31 @@
 
 #endif
 
+/*
+ * Thread-synchronous status.
+ *
+ * This is different from the flags in that nobody else
+ * ever touches our thread-synchronous status, so we don't
+ * have to worry about atomic accesses.
+ */
+#define TS_COMPAT		0x0002	/* 32bit syscall active (64BIT)*/
+
+#ifndef __ASSEMBLY__
 #ifdef CONFIG_COMPAT
 #define TS_I386_REGS_POKED	0x0004	/* regs poked by 32-bit ptracer */
+#define TS_COMPAT_RESTART	0x0008
+
+#define arch_set_restart_data	arch_set_restart_data
+
+static inline void arch_set_restart_data(struct restart_block *restart)
+{
+	struct thread_info *ti = current_thread_info();
+	if (ti->status & TS_COMPAT)
+		ti->status |= TS_COMPAT_RESTART;
+	else
+		ti->status &= ~TS_COMPAT_RESTART;
+}
 #endif
-#ifndef __ASSEMBLY__
 
 #ifdef CONFIG_X86_32
 #define in_ia32_syscall() true
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/timex.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/timex.h
@@ -5,6 +5,15 @@
 #include <asm/processor.h>
 #include <asm/tsc.h>
 
+static inline unsigned long random_get_entropy(void)
+{
+	if (!IS_ENABLED(CONFIG_X86_TSC) &&
+	    !cpu_feature_enabled(X86_FEATURE_TSC))
+		return random_get_entropy_fallback();
+	return rdtsc();
+}
+#define random_get_entropy random_get_entropy
+
 /* Assume we use the PIT time source for the clock tick */
 #define CLOCK_TICK_RATE		PIT_TICK_RATE
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/tlbflush.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/tlbflush.h
@@ -572,7 +572,7 @@
 	flush_tlb_mm_range((vma)->vm_mm, start, end,			\
 			   ((vma)->vm_flags & VM_HUGETLB)		\
 				? huge_page_shift(hstate_vma(vma))	\
-				: PAGE_SHIFT, false)
+				: PAGE_SHIFT, true)
 
 extern void flush_tlb_all(void);
 extern void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/topology.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/topology.h
@@ -110,6 +110,8 @@
 #define topology_die_id(cpu)			(cpu_data(cpu).cpu_die_id)
 #define topology_core_id(cpu)			(cpu_data(cpu).cpu_core_id)
 
+extern unsigned int __max_die_per_package;
+
 #ifdef CONFIG_SMP
 #define topology_die_cpumask(cpu)		(per_cpu(cpu_die_map, cpu))
 #define topology_core_cpumask(cpu)		(per_cpu(cpu_core_map, cpu))
@@ -118,8 +120,6 @@
 extern unsigned int __max_logical_packages;
 #define topology_max_packages()			(__max_logical_packages)
 
-extern unsigned int __max_die_per_package;
-
 static inline int topology_max_die_per_package(void)
 {
 	return __max_die_per_package;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/tsc.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/tsc.h
@@ -22,13 +22,12 @@
 
 static inline cycles_t get_cycles(void)
 {
-#ifndef CONFIG_X86_TSC
-	if (!boot_cpu_has(X86_FEATURE_TSC))
+	if (!IS_ENABLED(CONFIG_X86_TSC) &&
+	    !cpu_feature_enabled(X86_FEATURE_TSC))
 		return 0;
-#endif
-
 	return rdtsc();
 }
+#define get_cycles get_cycles
 
 extern struct system_counterval_t convert_art_to_tsc(u64 art);
 extern struct system_counterval_t convert_art_ns_to_tsc(u64 art_ns);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/uaccess.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/uaccess.h
@@ -378,18 +378,6 @@
 		     : "=r" (err), ltype(x)				\
 		     : "m" (__m(addr)), "i" (errret), "0" (err))
 
-#define __get_user_asm_nozero(x, addr, err, itype, rtype, ltype, errret)	\
-	asm volatile("\n"						\
-		     "1:	mov"itype" %2,%"rtype"1\n"		\
-		     "2:\n"						\
-		     ".section .fixup,\"ax\"\n"				\
-		     "3:	mov %3,%0\n"				\
-		     "	jmp 2b\n"					\
-		     ".previous\n"					\
-		     _ASM_EXTABLE_UA(1b, 3b)				\
-		     : "=r" (err), ltype(x)				\
-		     : "m" (__m(addr)), "i" (errret), "0" (err))
-
 /*
  * This doesn't do __uaccess_begin/end - the exception handling
  * around it must do that.
@@ -453,6 +441,103 @@
 	__builtin_expect(__gu_err, 0);					\
 })
 
+#ifdef CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT
+#define __try_cmpxchg_user_asm(itype, ltype, _ptr, _pold, _new, label)	({ \
+	bool success;							\
+	__typeof__(_ptr) _old = (__typeof__(_ptr))(_pold);		\
+	__typeof__(*(_ptr)) __old = *_old;				\
+	__typeof__(*(_ptr)) __new = (_new);				\
+	asm_volatile_goto("\n"						\
+		     "1: " LOCK_PREFIX "cmpxchg"itype" %[new], %[ptr]\n"\
+		     _ASM_EXTABLE_UA(1b, %l[label])			\
+		     : CC_OUT(z) (success),				\
+		       [ptr] "+m" (*_ptr),				\
+		       [old] "+a" (__old)				\
+		     : [new] ltype (__new)				\
+		     : "memory"						\
+		     : label);						\
+	if (unlikely(!success))						\
+		*_old = __old;						\
+	likely(success);					})
+
+#ifdef CONFIG_X86_32
+#define __try_cmpxchg64_user_asm(_ptr, _pold, _new, label)	({	\
+	bool success;							\
+	__typeof__(_ptr) _old = (__typeof__(_ptr))(_pold);		\
+	__typeof__(*(_ptr)) __old = *_old;				\
+	__typeof__(*(_ptr)) __new = (_new);				\
+	asm_volatile_goto("\n"						\
+		     "1: " LOCK_PREFIX "cmpxchg8b %[ptr]\n"		\
+		     _ASM_EXTABLE_UA(1b, %l[label])			\
+		     : CC_OUT(z) (success),				\
+		       "+A" (__old),					\
+		       [ptr] "+m" (*_ptr)				\
+		     : "b" ((u32)__new),				\
+		       "c" ((u32)((u64)__new >> 32))			\
+		     : "memory"						\
+		     : label);						\
+	if (unlikely(!success))						\
+		*_old = __old;						\
+	likely(success);					})
+#endif // CONFIG_X86_32
+#else  // !CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT
+#define __try_cmpxchg_user_asm(itype, ltype, _ptr, _pold, _new, label)	({ \
+	int __err = 0;							\
+	bool success;							\
+	__typeof__(_ptr) _old = (__typeof__(_ptr))(_pold);		\
+	__typeof__(*(_ptr)) __old = *_old;				\
+	__typeof__(*(_ptr)) __new = (_new);				\
+	asm volatile("\n"						\
+		     "1: " LOCK_PREFIX "cmpxchg"itype" %[new], %[ptr]\n"\
+		     CC_SET(z)						\
+		     "2:\n"						\
+		     _ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_EFAULT_REG,	\
+					   %[errout])			\
+		     : CC_OUT(z) (success),				\
+		       [errout] "+r" (__err),				\
+		       [ptr] "+m" (*_ptr),				\
+		       [old] "+a" (__old)				\
+		     : [new] ltype (__new)				\
+		     : "memory");					\
+	if (unlikely(__err))						\
+		goto label;						\
+	if (unlikely(!success))						\
+		*_old = __old;						\
+	likely(success);					})
+
+#ifdef CONFIG_X86_32
+/*
+ * Unlike the normal CMPXCHG, hardcode ECX for both success/fail and error.
+ * There are only six GPRs available and four (EAX, EBX, ECX, and EDX) are
+ * hardcoded by CMPXCHG8B, leaving only ESI and EDI.  If the compiler uses
+ * both ESI and EDI for the memory operand, compilation will fail if the error
+ * is an input+output as there will be no register available for input.
+ */
+#define __try_cmpxchg64_user_asm(_ptr, _pold, _new, label)	({	\
+	int __result;							\
+	__typeof__(_ptr) _old = (__typeof__(_ptr))(_pold);		\
+	__typeof__(*(_ptr)) __old = *_old;				\
+	__typeof__(*(_ptr)) __new = (_new);				\
+	asm volatile("\n"						\
+		     "1: " LOCK_PREFIX "cmpxchg8b %[ptr]\n"		\
+		     "mov $0, %%ecx\n\t"				\
+		     "setz %%cl\n"					\
+		     "2:\n"						\
+		     _ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_EFAULT_REG, %%ecx) \
+		     : [result]"=c" (__result),				\
+		       "+A" (__old),					\
+		       [ptr] "+m" (*_ptr)				\
+		     : "b" ((u32)__new),				\
+		       "c" ((u32)((u64)__new >> 32))			\
+		     : "memory", "cc");					\
+	if (unlikely(__result < 0))					\
+		goto label;						\
+	if (unlikely(!__result))					\
+		*_old = __old;						\
+	likely(__result);					})
+#endif // CONFIG_X86_32
+#endif // CONFIG_CC_HAS_ASM_GOTO_TIED_OUTPUT
+
 /* FIXME: this hack is definitely wrong -AK */
 struct __large_struct { unsigned long buf[100]; };
 #define __m(x) (*(struct __large_struct __user *)(x))
@@ -734,6 +819,51 @@
 	if (unlikely(__gu_err)) goto err_label;					\
 } while (0)
 
+extern void __try_cmpxchg_user_wrong_size(void);
+
+#ifndef CONFIG_X86_32
+#define __try_cmpxchg64_user_asm(_ptr, _oldp, _nval, _label)		\
+	__try_cmpxchg_user_asm("q", "r", (_ptr), (_oldp), (_nval), _label)
+#endif
+
+/*
+ * Force the pointer to u<size> to match the size expected by the asm helper.
+ * clang/LLVM compiles all cases and only discards the unused paths after
+ * processing errors, which breaks i386 if the pointer is an 8-byte value.
+ */
+#define unsafe_try_cmpxchg_user(_ptr, _oldp, _nval, _label) ({			\
+	bool __ret;								\
+	__chk_user_ptr(_ptr);							\
+	switch (sizeof(*(_ptr))) {						\
+	case 1:	__ret = __try_cmpxchg_user_asm("b", "q",			\
+					       (__force u8 *)(_ptr), (_oldp),	\
+					       (_nval), _label);		\
+		break;								\
+	case 2:	__ret = __try_cmpxchg_user_asm("w", "r",			\
+					       (__force u16 *)(_ptr), (_oldp),	\
+					       (_nval), _label);		\
+		break;								\
+	case 4:	__ret = __try_cmpxchg_user_asm("l", "r",			\
+					       (__force u32 *)(_ptr), (_oldp),	\
+					       (_nval), _label);		\
+		break;								\
+	case 8:	__ret = __try_cmpxchg64_user_asm((__force u64 *)(_ptr), (_oldp),\
+						 (_nval), _label);		\
+		break;								\
+	default: __try_cmpxchg_user_wrong_size();				\
+	}									\
+	__ret;						})
+
+/* "Returns" 0 on success, 1 on failure, -EFAULT if the access faults. */
+#define __try_cmpxchg_user(_ptr, _oldp, _nval, _label)	({		\
+	int __ret = -EFAULT;						\
+	__uaccess_begin_nospec();					\
+	__ret = !unsafe_try_cmpxchg_user(_ptr, _oldp, _nval, _label);	\
+_label:									\
+	__uaccess_end();						\
+	__ret;								\
+							})
+
 /*
  * We want the unsafe accessors to always be inlined and use
  * the error labels - thus the macro games.
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/uaccess_32.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/uaccess_32.h
@@ -23,33 +23,6 @@
 static __always_inline unsigned long
 raw_copy_from_user(void *to, const void __user *from, unsigned long n)
 {
-	if (__builtin_constant_p(n)) {
-		unsigned long ret;
-
-		switch (n) {
-		case 1:
-			ret = 0;
-			__uaccess_begin_nospec();
-			__get_user_asm_nozero(*(u8 *)to, from, ret,
-					      "b", "b", "=q", 1);
-			__uaccess_end();
-			return ret;
-		case 2:
-			ret = 0;
-			__uaccess_begin_nospec();
-			__get_user_asm_nozero(*(u16 *)to, from, ret,
-					      "w", "w", "=r", 2);
-			__uaccess_end();
-			return ret;
-		case 4:
-			ret = 0;
-			__uaccess_begin_nospec();
-			__get_user_asm_nozero(*(u32 *)to, from, ret,
-					      "l", "k", "=r", 4);
-			__uaccess_end();
-			return ret;
-		}
-	}
 	return __copy_user_ll(to, (__force const void *)from, n);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/uaccess_64.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/uaccess_64.h
@@ -65,117 +65,13 @@
 static __always_inline __must_check unsigned long
 raw_copy_from_user(void *dst, const void __user *src, unsigned long size)
 {
-	int ret = 0;
-
-	if (!__builtin_constant_p(size))
-		return copy_user_generic(dst, (__force void *)src, size);
-	switch (size) {
-	case 1:
-		__uaccess_begin_nospec();
-		__get_user_asm_nozero(*(u8 *)dst, (u8 __user *)src,
-			      ret, "b", "b", "=q", 1);
-		__uaccess_end();
-		return ret;
-	case 2:
-		__uaccess_begin_nospec();
-		__get_user_asm_nozero(*(u16 *)dst, (u16 __user *)src,
-			      ret, "w", "w", "=r", 2);
-		__uaccess_end();
-		return ret;
-	case 4:
-		__uaccess_begin_nospec();
-		__get_user_asm_nozero(*(u32 *)dst, (u32 __user *)src,
-			      ret, "l", "k", "=r", 4);
-		__uaccess_end();
-		return ret;
-	case 8:
-		__uaccess_begin_nospec();
-		__get_user_asm_nozero(*(u64 *)dst, (u64 __user *)src,
-			      ret, "q", "", "=r", 8);
-		__uaccess_end();
-		return ret;
-	case 10:
-		__uaccess_begin_nospec();
-		__get_user_asm_nozero(*(u64 *)dst, (u64 __user *)src,
-			       ret, "q", "", "=r", 10);
-		if (likely(!ret))
-			__get_user_asm_nozero(*(u16 *)(8 + (char *)dst),
-				       (u16 __user *)(8 + (char __user *)src),
-				       ret, "w", "w", "=r", 2);
-		__uaccess_end();
-		return ret;
-	case 16:
-		__uaccess_begin_nospec();
-		__get_user_asm_nozero(*(u64 *)dst, (u64 __user *)src,
-			       ret, "q", "", "=r", 16);
-		if (likely(!ret))
-			__get_user_asm_nozero(*(u64 *)(8 + (char *)dst),
-				       (u64 __user *)(8 + (char __user *)src),
-				       ret, "q", "", "=r", 8);
-		__uaccess_end();
-		return ret;
-	default:
-		return copy_user_generic(dst, (__force void *)src, size);
-	}
+	return copy_user_generic(dst, (__force void *)src, size);
 }
 
 static __always_inline __must_check unsigned long
 raw_copy_to_user(void __user *dst, const void *src, unsigned long size)
 {
-	int ret = 0;
-
-	if (!__builtin_constant_p(size))
-		return copy_user_generic((__force void *)dst, src, size);
-	switch (size) {
-	case 1:
-		__uaccess_begin();
-		__put_user_asm(*(u8 *)src, (u8 __user *)dst,
-			      ret, "b", "b", "iq", 1);
-		__uaccess_end();
-		return ret;
-	case 2:
-		__uaccess_begin();
-		__put_user_asm(*(u16 *)src, (u16 __user *)dst,
-			      ret, "w", "w", "ir", 2);
-		__uaccess_end();
-		return ret;
-	case 4:
-		__uaccess_begin();
-		__put_user_asm(*(u32 *)src, (u32 __user *)dst,
-			      ret, "l", "k", "ir", 4);
-		__uaccess_end();
-		return ret;
-	case 8:
-		__uaccess_begin();
-		__put_user_asm(*(u64 *)src, (u64 __user *)dst,
-			      ret, "q", "", "er", 8);
-		__uaccess_end();
-		return ret;
-	case 10:
-		__uaccess_begin();
-		__put_user_asm(*(u64 *)src, (u64 __user *)dst,
-			       ret, "q", "", "er", 10);
-		if (likely(!ret)) {
-			asm("":::"memory");
-			__put_user_asm(4[(u16 *)src], 4 + (u16 __user *)dst,
-				       ret, "w", "w", "ir", 2);
-		}
-		__uaccess_end();
-		return ret;
-	case 16:
-		__uaccess_begin();
-		__put_user_asm(*(u64 *)src, (u64 __user *)dst,
-			       ret, "q", "", "er", 16);
-		if (likely(!ret)) {
-			asm("":::"memory");
-			__put_user_asm(1[(u64 *)src], 1 + (u64 __user *)dst,
-				       ret, "q", "", "er", 8);
-		}
-		__uaccess_end();
-		return ret;
-	default:
-		return copy_user_generic((__force void *)dst, src, size);
-	}
+	return copy_user_generic((__force void *)dst, src, size);
 }
 
 static __always_inline __must_check
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/unwind.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/unwind.h
@@ -19,7 +19,7 @@
 #if defined(CONFIG_UNWINDER_ORC)
 	bool signal, full_regs;
 	unsigned long sp, bp, ip;
-	struct pt_regs *regs;
+	struct pt_regs *regs, *prev_regs;
 #elif defined(CONFIG_UNWINDER_FRAME_POINTER)
 	bool got_irq;
 	unsigned long *bp, *orig_sp, ip;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/unwind_hints.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/unwind_hints.h
@@ -101,7 +101,7 @@
 	".popsection\n\t"
 
 #define UNWIND_HINT_SAVE UNWIND_HINT(0, 0, UNWIND_HINT_TYPE_SAVE, 0)
-
+#define UNWIND_HINT_EMPTY
 #define UNWIND_HINT_RESTORE UNWIND_HINT(0, 0, UNWIND_HINT_TYPE_RESTORE, 0)
 
 #endif /* __ASSEMBLY__ */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/virtext.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/virtext.h
@@ -30,15 +30,22 @@
 }
 
 
-/** Disable VMX on the current CPU
+/**
+ * cpu_vmxoff() - Disable VMX on the current CPU
  *
- * vmxoff causes a undefined-opcode exception if vmxon was not run
- * on the CPU previously. Only call this function if you know VMX
- * is enabled.
+ * Disable VMX and clear CR4.VMXE (even if VMXOFF faults)
+ *
+ * Note, VMXOFF causes a #UD if the CPU is !post-VMXON, but it's impossible to
+ * atomically track post-VMXON state, e.g. this may be called in NMI context.
+ * Eat all faults as all other faults on VMXOFF faults are mode related, i.e.
+ * faults are guaranteed to be due to the !post-VMXON check unless the CPU is
+ * magically in RM, VM86, compat mode, or at CPL>0.
  */
 static inline void cpu_vmxoff(void)
 {
-	asm volatile ("vmxoff");
+	asm_volatile_goto("1: vmxoff\n\t"
+			  _ASM_EXTABLE(1b, %l[fault]) :::: fault);
+fault:
 	cr4_clear_bits(X86_CR4_VMXE);
 }
 
@@ -88,12 +95,6 @@
 		return 0;
 	}
 
-	if (boot_cpu_data.extended_cpuid_level < SVM_CPUID_FUNC) {
-		if (msg)
-			*msg = "can't execute cpuid_8000000a";
-		return 0;
-	}
-
 	if (!boot_cpu_has(X86_FEATURE_SVM)) {
 		if (msg)
 			*msg = "svm not available";
@@ -113,7 +114,21 @@
 
 	wrmsrl(MSR_VM_HSAVE_PA, 0);
 	rdmsrl(MSR_EFER, efer);
-	wrmsrl(MSR_EFER, efer & ~EFER_SVME);
+	if (efer & EFER_SVME) {
+		/*
+		 * Force GIF=1 prior to disabling SVM to ensure INIT and NMI
+		 * aren't blocked, e.g. if a fatal error occurred between CLGI
+		 * and STGI.  Note, STGI may #UD if SVM is disabled from NMI
+		 * context between reading EFER and executing STGI.  In that
+		 * case, GIF must already be set, otherwise the NMI would have
+		 * been blocked, so just eat the fault.
+		 */
+		asm_volatile_goto("1: stgi\n\t"
+				  _ASM_EXTABLE(1b, %l[fault])
+				  ::: "memory" : fault);
+fault:
+		wrmsrl(MSR_EFER, efer & ~EFER_SVME);
+	}
 }
 
 /** Makes sure SVM is disabled, if it is supported on the CPU
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/vmx.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/vmx.h
@@ -19,8 +19,8 @@
 /*
  * Definitions of Primary Processor-Based VM-Execution Controls.
  */
-#define CPU_BASED_VIRTUAL_INTR_PENDING          0x00000004
-#define CPU_BASED_USE_TSC_OFFSETING             0x00000008
+#define CPU_BASED_INTR_WINDOW_EXITING           0x00000004
+#define CPU_BASED_USE_TSC_OFFSETTING            0x00000008
 #define CPU_BASED_HLT_EXITING                   0x00000080
 #define CPU_BASED_INVLPG_EXITING                0x00000200
 #define CPU_BASED_MWAIT_EXITING                 0x00000400
@@ -31,7 +31,7 @@
 #define CPU_BASED_CR8_LOAD_EXITING              0x00080000
 #define CPU_BASED_CR8_STORE_EXITING             0x00100000
 #define CPU_BASED_TPR_SHADOW                    0x00200000
-#define CPU_BASED_VIRTUAL_NMI_PENDING		0x00400000
+#define CPU_BASED_NMI_WINDOW_EXITING		0x00400000
 #define CPU_BASED_MOV_DR_EXITING                0x00800000
 #define CPU_BASED_UNCOND_IO_EXITING             0x01000000
 #define CPU_BASED_USE_IO_BITMAPS                0x02000000
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/x86_init.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/x86_init.h
@@ -51,12 +51,14 @@
  *				are set up.
  * @intr_init:			interrupt init code
  * @trap_init:			platform specific trap setup
+ * @intr_mode_select:		interrupt delivery mode selection
  * @intr_mode_init:		interrupt delivery mode setup
  */
 struct x86_init_irqs {
 	void (*pre_vector_init)(void);
 	void (*intr_init)(void);
 	void (*trap_init)(void);
+	void (*intr_mode_select)(void);
 	void (*intr_mode_init)(void);
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/asm/xen/interface.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/asm/xen/interface.h
@@ -379,12 +379,9 @@
  * Prefix forces emulation of some non-trapping instructions.
  * Currently only CPUID.
  */
-#ifdef __ASSEMBLY__
-#define XEN_EMULATE_PREFIX .byte 0x0f,0x0b,0x78,0x65,0x6e ;
-#define XEN_CPUID          XEN_EMULATE_PREFIX cpuid
-#else
-#define XEN_EMULATE_PREFIX ".byte 0x0f,0x0b,0x78,0x65,0x6e ; "
-#define XEN_CPUID          XEN_EMULATE_PREFIX "cpuid"
-#endif
+#include <asm/emulate_prefix.h>
+
+#define XEN_EMULATE_PREFIX __ASM_FORM(.byte __XEN_EMULATE_PREFIX ;)
+#define XEN_CPUID          XEN_EMULATE_PREFIX __ASM_FORM(cpuid)
 
 #endif /* _ASM_X86_XEN_INTERFACE_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/uapi/asm/unistd.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/uapi/asm/unistd.h
@@ -2,8 +2,15 @@
 #ifndef _UAPI_ASM_X86_UNISTD_H
 #define _UAPI_ASM_X86_UNISTD_H
 
-/* x32 syscall flag bit */
-#define __X32_SYSCALL_BIT	0x40000000UL
+/*
+ * x32 syscall flag bit.  Some user programs expect syscall NR macros
+ * and __X32_SYSCALL_BIT to have type int, even though syscall numbers
+ * are, for practical purposes, unsigned long.
+ *
+ * Fortunately, expressions like (nr & ~__X32_SYSCALL_BIT) do the right
+ * thing regardless.
+ */
+#define __X32_SYSCALL_BIT	0x40000000
 
 #ifndef __KERNEL__
 # ifdef __i386__
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/include/uapi/asm/vmx.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/include/uapi/asm/vmx.h
@@ -33,7 +33,7 @@
 #define EXIT_REASON_TRIPLE_FAULT        2
 #define EXIT_REASON_INIT_SIGNAL			3
 
-#define EXIT_REASON_PENDING_INTERRUPT   7
+#define EXIT_REASON_INTERRUPT_WINDOW    7
 #define EXIT_REASON_NMI_WINDOW          8
 #define EXIT_REASON_TASK_SWITCH         9
 #define EXIT_REASON_CPUID               10
@@ -94,7 +94,7 @@
 	{ EXIT_REASON_EXTERNAL_INTERRUPT,    "EXTERNAL_INTERRUPT" }, \
 	{ EXIT_REASON_TRIPLE_FAULT,          "TRIPLE_FAULT" }, \
 	{ EXIT_REASON_INIT_SIGNAL,           "INIT_SIGNAL" }, \
-	{ EXIT_REASON_PENDING_INTERRUPT,     "PENDING_INTERRUPT" }, \
+	{ EXIT_REASON_INTERRUPT_WINDOW,      "INTERRUPT_WINDOW" }, \
 	{ EXIT_REASON_NMI_WINDOW,            "NMI_WINDOW" }, \
 	{ EXIT_REASON_TASK_SWITCH,           "TASK_SWITCH" }, \
 	{ EXIT_REASON_CPUID,                 "CPUID" }, \
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/acpi/boot.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/acpi/boot.c
@@ -140,6 +140,9 @@
 		       madt->address);
 	}
 
+	if (madt->flags & ACPI_MADT_PCAT_COMPAT)
+		legacy_pic_pcat_compat();
+
 	default_acpi_madt_oem_check(madt->header.oem_id,
 				    madt->header.oem_table_id);
 
@@ -1339,6 +1342,17 @@
 	return 0;
 }
 
+static int __init disable_acpi_xsdt(const struct dmi_system_id *d)
+{
+	if (!acpi_force) {
+		pr_notice("%s detected: force use of acpi=rsdt\n", d->ident);
+		acpi_gbl_do_not_use_xsdt = TRUE;
+	} else {
+		pr_notice("Warning: DMI blacklist says broken, but acpi XSDT forced\n");
+	}
+	return 0;
+}
+
 static int __init dmi_disable_acpi(const struct dmi_system_id *d)
 {
 	if (!acpi_force) {
@@ -1463,6 +1477,19 @@
 		     DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
 		     },
 	 },
+	/*
+	 * Boxes that need ACPI XSDT use disabled due to corrupted tables
+	 */
+	{
+	 .callback = disable_acpi_xsdt,
+	 .ident = "Advantech DAC-BJ01",
+	 .matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "NEC"),
+		     DMI_MATCH(DMI_PRODUCT_NAME, "Bearlake CRB Board"),
+		     DMI_MATCH(DMI_BIOS_VERSION, "V1.12"),
+		     DMI_MATCH(DMI_BIOS_DATE, "02/01/2011"),
+		     },
+	 },
 	{}
 };
 
@@ -1553,10 +1580,18 @@
 	/*
 	 * Initialize the ACPI boot-time table parser.
 	 */
-	if (acpi_table_init()) {
+	if (acpi_locate_initial_tables())
 		disable_acpi();
-		return;
-	}
+	else
+		acpi_reserve_initial_tables();
+}
+
+int __init early_acpi_boot_init(void)
+{
+	if (acpi_disabled)
+		return 1;
+
+	acpi_table_init_complete();
 
 	acpi_table_parse(ACPI_SIG_BOOT, acpi_parse_sbf);
 
@@ -1569,18 +1604,9 @@
 		} else {
 			printk(KERN_WARNING PREFIX "Disabling ACPI support\n");
 			disable_acpi();
-			return;
+			return 1;
 		}
 	}
-}
-
-int __init early_acpi_boot_init(void)
-{
-	/*
-	 * If acpi_disabled, bail out
-	 */
-	if (acpi_disabled)
-		return 1;
 
 	/*
 	 * Process the Multiple APIC Description Table (MADT), if present
@@ -1740,7 +1766,7 @@
 		new = (((old & ~0x3) + 2) + ((old >> 1) & 0x1));
 		val = cmpxchg(lock, old, new);
 	} while (unlikely (val != old));
-	return (new < 3) ? -1 : 0;
+	return ((new & 0x3) < 3) ? -1 : 0;
 }
 
 int __acpi_release_global_lock(unsigned int *lock)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/acpi/cstate.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/acpi/cstate.c
@@ -161,7 +161,8 @@
 
 	/* Make sure we are running on right CPU */
 
-	retval = work_on_cpu(cpu, acpi_processor_ffh_cstate_probe_cpu, cx);
+	retval = call_on_cpu(cpu, acpi_processor_ffh_cstate_probe_cpu, cx,
+			     false);
 	if (retval == 0) {
 		/* Use the hint in CST */
 		percpu_entry->states[cx->index].eax = cx->address;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/acpi/wakeup_32.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/acpi/wakeup_32.S
@@ -3,14 +3,14 @@
 #include <linux/linkage.h>
 #include <asm/segment.h>
 #include <asm/page_types.h>
+#include <asm/nospec-branch.h>
 
 # Copyright 2003, 2008 Pavel Machek <pavel@suse.cz
 
 	.code32
 	ALIGN
 
-ENTRY(wakeup_pmode_return)
-wakeup_pmode_return:
+SYM_CODE_START(wakeup_pmode_return)
 	movw	$__KERNEL_DS, %ax
 	movw	%ax, %ss
 	movw	%ax, %fs
@@ -38,7 +38,9 @@
 
 	# jump to place where we left off
 	movl	saved_eip, %eax
+	ANNOTATE_RETPOLINE_SAFE
 	jmp	*%eax
+SYM_CODE_END(wakeup_pmode_return)
 
 bogus_magic:
 	jmp	bogus_magic
@@ -72,7 +74,7 @@
 	popfl
 	ret
 
-ENTRY(do_suspend_lowlevel)
+SYM_CODE_START(do_suspend_lowlevel)
 	call	save_processor_state
 	call	save_registers
 	pushl	$3
@@ -87,6 +89,7 @@
 	call	restore_registers
 	call	restore_processor_state
 	ret
+SYM_CODE_END(do_suspend_lowlevel)
 
 .data
 ALIGN
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/acpi/wakeup_64.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/acpi/wakeup_64.S
@@ -7,6 +7,7 @@
 #include <asm/msr.h>
 #include <asm/asm-offsets.h>
 #include <asm/frame.h>
+#include <asm/nospec-branch.h>
 
 # Copyright 2003 Pavel Machek <pavel@suse.cz
 
@@ -39,6 +40,7 @@
 	movq	saved_rbp, %rbp
 
 	movq	saved_rip, %rax
+	ANNOTATE_RETPOLINE_SAFE
 	jmp	*%rax
 ENDPROC(wakeup_long64)
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/alternative.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/alternative.c
@@ -374,6 +374,17 @@
 	u8 insn_buff[MAX_PATCH_LEN];
 
 	DPRINTK("alt table %px, -> %px", start, end);
+
+	/*
+	 * In the case CONFIG_X86_5LEVEL=y, KASAN_SHADOW_START is defined using
+	 * cpu_feature_enabled(X86_FEATURE_LA57) and is therefore patched here.
+	 * During the process, KASAN becomes confused seeing partial LA57
+	 * conversion and triggers a false-positive out-of-bound report.
+	 *
+	 * Disable KASAN until the patching is complete.
+	 */
+	kasan_disable_current();
+
 	/*
 	 * The scan order should be from start to end. A later scanned
 	 * alternative code can overwrite previously scanned alternative code.
@@ -434,6 +445,8 @@
 
 		text_poke_early(instr, insn_buff, insn_buff_sz);
 	}
+
+	kasan_enable_current();
 }
 
 #ifdef CONFIG_SMP
@@ -772,8 +785,8 @@
 	} else {
 		local_irq_save(flags);
 		memcpy(addr, opcode, len);
-		local_irq_restore(flags);
 		sync_core();
+		local_irq_restore(flags);
 
 		/*
 		 * Could also do a CLFLUSH here to speed up CPU recovery; but
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/amd_nb.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/amd_nb.c
@@ -18,10 +18,13 @@
 #define PCI_DEVICE_ID_AMD_17H_ROOT	0x1450
 #define PCI_DEVICE_ID_AMD_17H_M10H_ROOT	0x15d0
 #define PCI_DEVICE_ID_AMD_17H_M30H_ROOT	0x1480
+#define PCI_DEVICE_ID_AMD_17H_M60H_ROOT	0x1630
 #define PCI_DEVICE_ID_AMD_17H_DF_F4	0x1464
 #define PCI_DEVICE_ID_AMD_17H_M10H_DF_F4 0x15ec
 #define PCI_DEVICE_ID_AMD_17H_M30H_DF_F4 0x1494
+#define PCI_DEVICE_ID_AMD_17H_M60H_DF_F4 0x144c
 #define PCI_DEVICE_ID_AMD_17H_M70H_DF_F4 0x1444
+#define PCI_DEVICE_ID_AMD_19H_DF_F4	0x1654
 
 /* Protect the PCI config register pairs used for SMN and DF indirect access. */
 static DEFINE_MUTEX(smn_mutex);
@@ -32,6 +35,7 @@
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_ROOT) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M10H_ROOT) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M30H_ROOT) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M60H_ROOT) },
 	{}
 };
 
@@ -50,8 +54,10 @@
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_DF_F3) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M10H_DF_F3) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M30H_DF_F3) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M60H_DF_F3) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CNB17H_F3) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M70H_DF_F3) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_DF_F3) },
 	{}
 };
 EXPORT_SYMBOL_GPL(amd_nb_misc_ids);
@@ -65,7 +71,9 @@
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_DF_F4) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M10H_DF_F4) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M30H_DF_F4) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M60H_DF_F4) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M70H_DF_F4) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_DF_F4) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CNB17H_F4) },
 	{}
 };
@@ -158,7 +166,14 @@
 
 int amd_smn_read(u16 node, u32 address, u32 *value)
 {
-	return __amd_smn_rw(node, address, value, false);
+	int err = __amd_smn_rw(node, address, value, false);
+
+	if (PCI_POSSIBLE_ERROR(*value)) {
+		err = -ENODEV;
+		*value = 0;
+	}
+
+	return err;
 }
 EXPORT_SYMBOL_GPL(amd_smn_read);
 
@@ -523,6 +538,10 @@
 
 static __init int init_amd_nbs(void)
 {
+	if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD &&
+	    boot_cpu_data.x86_vendor != X86_VENDOR_HYGON)
+		return 0;
+
 	amd_cache_northbridges();
 	amd_cache_gart();
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/aperture_64.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/aperture_64.c
@@ -126,32 +126,6 @@
 }
 
 
-/* Find a PCI capability */
-static u32 __init find_cap(int bus, int slot, int func, int cap)
-{
-	int bytes;
-	u8 pos;
-
-	if (!(read_pci_config_16(bus, slot, func, PCI_STATUS) &
-						PCI_STATUS_CAP_LIST))
-		return 0;
-
-	pos = read_pci_config_byte(bus, slot, func, PCI_CAPABILITY_LIST);
-	for (bytes = 0; bytes < 48 && pos >= 0x40; bytes++) {
-		u8 id;
-
-		pos &= ~3;
-		id = read_pci_config_byte(bus, slot, func, pos+PCI_CAP_LIST_ID);
-		if (id == 0xff)
-			break;
-		if (id == cap)
-			return pos;
-		pos = read_pci_config_byte(bus, slot, func,
-						pos+PCI_CAP_LIST_NEXT);
-	}
-	return 0;
-}
-
 /* Read a standard AGPv3 bridge header */
 static u32 __init read_agp(int bus, int slot, int func, int cap, u32 *order)
 {
@@ -240,8 +214,8 @@
 				case PCI_CLASS_BRIDGE_HOST:
 				case PCI_CLASS_BRIDGE_OTHER: /* needed? */
 					/* AGP bridge? */
-					cap = find_cap(bus, slot, func,
-							PCI_CAP_ID_AGP);
+					cap = pci_early_find_cap(bus, slot,
+						 func, PCI_CAP_ID_AGP);
 					if (!cap)
 						break;
 					*valid_agp = 1;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/apic/apic.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/apic/apic.c
@@ -42,6 +42,7 @@
 #include <asm/x86_init.h>
 #include <asm/pgalloc.h>
 #include <linux/atomic.h>
+#include <asm/barrier.h>
 #include <asm/mpspec.h>
 #include <asm/i8259.h>
 #include <asm/proto.h>
@@ -167,7 +168,7 @@
 {
 	apic_calibrate_pmtmr = 1;
 	notsc_setup(NULL);
-	return 0;
+	return 1;
 }
 __setup("apicpmtimer", setup_apicpmtimer);
 #endif
@@ -352,8 +353,6 @@
 		 * According to Intel, MFENCE can do the serialization here.
 		 */
 		asm volatile("mfence" : : : "memory");
-
-		printk_once(KERN_DEBUG "TSC deadline timer enabled\n");
 		return;
 	}
 
@@ -411,10 +410,9 @@
 		if (vector && !eilvt_entry_is_changeable(vector, new))
 			/* may not change if vectors are different */
 			return rsvd;
-		rsvd = atomic_cmpxchg(&eilvt_offsets[offset], rsvd, new);
-	} while (rsvd != new);
+	} while (!atomic_try_cmpxchg(&eilvt_offsets[offset], &rsvd, new));
 
-	rsvd &= ~APIC_EILVT_MASKED;
+	rsvd = new & ~APIC_EILVT_MASKED;
 	if (rsvd && rsvd != vector)
 		pr_info("LVT offset %d assigned for vector 0x%02x\n",
 			offset, rsvd);
@@ -474,6 +472,9 @@
 {
 	u64 tsc;
 
+	/* This MSR is special and need a special fence: */
+	weak_wrmsr_fence();
+
 	tsc = rdtsc();
 	wrmsrl(MSR_IA32_TSC_DEADLINE, tsc + (((u64) delta) * TSC_DIVISOR));
 	return 0;
@@ -490,7 +491,19 @@
 	v = apic_read(APIC_LVTT);
 	v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
 	apic_write(APIC_LVTT, v);
-	apic_write(APIC_TMICT, 0);
+
+	/*
+	 * Setting APIC_LVT_MASKED (above) should be enough to tell
+	 * the hardware that this timer will never fire. But AMD
+	 * erratum 411 and some Intel CPU behavior circa 2024 say
+	 * otherwise.  Time for belt and suspenders programming: mask
+	 * the timer _and_ zero the counter registers:
+	 */
+	if (v & APIC_LVT_TIMER_TSCDEADLINE)
+		wrmsrl(MSR_IA32_TSC_DEADLINE, 0);
+	else
+		apic_write(APIC_TMICT, 0);
+
 	return 0;
 }
 
@@ -552,7 +565,7 @@
 #define DEADLINE_MODEL_MATCH_REV(model, rev)	\
 	{ X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long)rev }
 
-static u32 hsx_deadline_rev(void)
+static __init u32 hsx_deadline_rev(void)
 {
 	switch (boot_cpu_data.x86_stepping) {
 	case 0x02: return 0x3a; /* EP */
@@ -562,7 +575,7 @@
 	return ~0U;
 }
 
-static u32 bdx_deadline_rev(void)
+static __init u32 bdx_deadline_rev(void)
 {
 	switch (boot_cpu_data.x86_stepping) {
 	case 0x02: return 0x00000011;
@@ -574,7 +587,7 @@
 	return ~0U;
 }
 
-static u32 skx_deadline_rev(void)
+static __init u32 skx_deadline_rev(void)
 {
 	switch (boot_cpu_data.x86_stepping) {
 	case 0x03: return 0x01000136;
@@ -587,7 +600,7 @@
 	return ~0U;
 }
 
-static const struct x86_cpu_id deadline_match[] = {
+static const struct x86_cpu_id deadline_match[] __initconst = {
 	DEADLINE_MODEL_MATCH_FUNC( INTEL_FAM6_HASWELL_X,	hsx_deadline_rev),
 	DEADLINE_MODEL_MATCH_REV ( INTEL_FAM6_BROADWELL_X,	0x0b000020),
 	DEADLINE_MODEL_MATCH_FUNC( INTEL_FAM6_BROADWELL_D,	bdx_deadline_rev),
@@ -609,18 +622,19 @@
 	{},
 };
 
-static void apic_check_deadline_errata(void)
+static __init bool apic_validate_deadline_timer(void)
 {
 	const struct x86_cpu_id *m;
 	u32 rev;
 
-	if (!boot_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER) ||
-	    boot_cpu_has(X86_FEATURE_HYPERVISOR))
-		return;
+	if (!boot_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER))
+		return false;
+	if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
+		return true;
 
 	m = x86_match_cpu(deadline_match);
 	if (!m)
-		return;
+		return true;
 
 	/*
 	 * Function pointers will have the MSB set due to address layout,
@@ -632,11 +646,12 @@
 		rev = (u32)m->driver_data;
 
 	if (boot_cpu_data.microcode >= rev)
-		return;
+		return true;
 
 	setup_clear_cpu_cap(X86_FEATURE_TSC_DEADLINE_TIMER);
 	pr_err(FW_BUG "TSC_DEADLINE disabled due to Errata; "
 	       "please update microcode to version: 0x%x (or later)\n", rev);
+	return false;
 }
 
 /*
@@ -830,8 +845,17 @@
 	if (!tsc_khz || !cpu_khz)
 		return true;
 
-	/* Is there an APIC at all? */
-	if (!boot_cpu_has(X86_FEATURE_APIC))
+	/* Is there an APIC at all or is it disabled? */
+	if (!boot_cpu_has(X86_FEATURE_APIC) || disable_apic)
+		return true;
+
+	/*
+	 * If interrupt delivery mode is legacy PIC or virtual wire without
+	 * configuration, the local APIC timer wont be set up. Make sure
+	 * that the PIT is initialized.
+	 */
+	if (apic_intr_mode == APIC_PIC ||
+	    apic_intr_mode == APIC_VIRTUAL_WIRE_NO_CONFIG)
 		return true;
 
 	/* Virt guests may lack ARAT, but still have DEADLINE */
@@ -1322,7 +1346,7 @@
 
 enum apic_intr_mode_id apic_intr_mode __ro_after_init;
 
-static int __init apic_intr_mode_select(void)
+static int __init __apic_intr_mode_select(void)
 {
 	/* Check kernel option */
 	if (disable_apic) {
@@ -1384,6 +1408,12 @@
 	return APIC_SYMMETRIC_IO;
 }
 
+/* Select the interrupt delivery mode for the BSP */
+void __init apic_intr_mode_select(void)
+{
+	apic_intr_mode = __apic_intr_mode_select();
+}
+
 /*
  * An initial setup of the virtual wire mode.
  */
@@ -1440,8 +1470,6 @@
 {
 	bool upmode = IS_ENABLED(CONFIG_UP_LATE_INIT);
 
-	apic_intr_mode = apic_intr_mode_select();
-
 	switch (apic_intr_mode) {
 	case APIC_PIC:
 		pr_info("APIC: Keep in PIC mode(8259)\n");
@@ -1873,20 +1901,22 @@
 		return;
 
 	if (remap_mode != IRQ_REMAP_X2APIC_MODE) {
-		/* IR is required if there is APIC ID > 255 even when running
-		 * under KVM
+		/*
+		 * Using X2APIC without IR is not architecturally supported
+		 * on bare metal but may be supported in guests.
 		 */
-		if (max_physical_apicid > 255 ||
-		    !x86_init.hyper.x2apic_available()) {
+		if (!x86_init.hyper.x2apic_available()) {
 			pr_info("x2apic: IRQ remapping doesn't support X2APIC mode\n");
 			x2apic_disable();
 			return;
 		}
 
 		/*
-		 * without IR all CPUs can be addressed by IOAPIC/MSI
-		 * only in physical mode
+		 * Without IR, all CPUs can be addressed by IOAPIC/MSI only
+		 * in physical mode, and CPUs with an APIC ID that cannnot
+		 * be addressed must not be brought online.
 		 */
+		x2apic_set_max_apicid(255);
 		x2apic_phys = 1;
 	}
 	x2apic_enable();
@@ -2085,7 +2115,8 @@
 {
 	unsigned int new_apicid;
 
-	apic_check_deadline_errata();
+	if (apic_validate_deadline_timer())
+		pr_info("TSC deadline timer available\n");
 
 	if (x2apic_mode) {
 		boot_cpu_physical_apicid = read_apic_id();
@@ -2334,6 +2365,11 @@
 	[0 ... NR_CPUS - 1] = -1,
 };
 
+bool arch_match_cpu_phys_id(int cpu, u64 phys_id)
+{
+	return phys_id == cpuid_to_apicid[cpu];
+}
+
 #ifdef CONFIG_SMP
 /**
  * apic_id_is_primary_thread - Check whether APIC ID belongs to a primary thread
@@ -2554,6 +2590,7 @@
 	end_local_APIC_setup();
 	irq_remap_enable_fault_handling();
 	setup_IO_APIC();
+	lapic_update_legacy_vectors();
 }
 
 #ifdef CONFIG_UP_LATE_INIT
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/apic/io_apic.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/apic/io_apic.c
@@ -371,27 +371,26 @@
  * shared ISA-space IRQs, so we have to support them. We are super
  * fast in the common case, and fast for shared ISA-space IRQs.
  */
-static int __add_pin_to_irq_node(struct mp_chip_data *data,
-				 int node, int apic, int pin)
+static bool add_pin_to_irq_node(struct mp_chip_data *data, int node, int apic, int pin)
 {
 	struct irq_pin_list *entry;
 
-	/* don't allow duplicates */
-	for_each_irq_pin(entry, data->irq_2_pin)
+	/* Don't allow duplicates */
+	for_each_irq_pin(entry, data->irq_2_pin) {
 		if (entry->apic == apic && entry->pin == pin)
-			return 0;
+			return true;
+	}
 
 	entry = kzalloc_node(sizeof(struct irq_pin_list), GFP_ATOMIC, node);
 	if (!entry) {
-		pr_err("can not alloc irq_pin_list (%d,%d,%d)\n",
-		       node, apic, pin);
-		return -ENOMEM;
+		pr_err("Cannot allocate irq_pin_list (%d,%d,%d)\n", node, apic, pin);
+		return false;
 	}
+
 	entry->apic = apic;
 	entry->pin = pin;
 	list_add_tail(&entry->list, &data->irq_2_pin);
-
-	return 0;
+	return true;
 }
 
 static void __remove_pin_from_irq(struct mp_chip_data *data, int apic, int pin)
@@ -406,13 +405,6 @@
 		}
 }
 
-static void add_pin_to_irq_node(struct mp_chip_data *data,
-				int node, int apic, int pin)
-{
-	if (__add_pin_to_irq_node(data, node, apic, pin))
-		panic("IO-APIC: failed to add irq-pin. Can not proceed\n");
-}
-
 /*
  * Reroute an IRQ to a different pin.
  */
@@ -1014,8 +1006,7 @@
 	if (irq_data && irq_data->parent_data) {
 		if (!mp_check_pin_attr(irq, info))
 			return -EBUSY;
-		if (__add_pin_to_irq_node(irq_data->chip_data, node, ioapic,
-					  info->ioapic_pin))
+		if (!add_pin_to_irq_node(irq_data->chip_data, node, ioapic, info->ioapic_pin))
 			return -ENOMEM;
 	} else {
 		info->flags |= X86_IRQ_ALLOC_LEGACY;
@@ -1046,6 +1037,16 @@
 	if (idx >= 0 && test_bit(mp_irqs[idx].srcbus, mp_bus_not_pci)) {
 		irq = mp_irqs[idx].srcbusirq;
 		legacy = mp_is_legacy_irq(irq);
+		/*
+		 * IRQ2 is unusable for historical reasons on systems which
+		 * have a legacy PIC. See the comment vs. IRQ2 further down.
+		 *
+		 * If this gets removed at some point then the related code
+		 * in lapic_assign_system_vectors() needs to be adjusted as
+		 * well.
+		 */
+		if (legacy && irq == PIC_CASCADE_IR)
+			return -EINVAL;
 	}
 
 	mutex_lock(&ioapic_mutex);
@@ -1727,9 +1728,10 @@
 
 static inline bool ioapic_irqd_mask(struct irq_data *data)
 {
-	/* If we are moving the irq we need to mask it */
+	/* If we are moving the IRQ we need to mask it */
 	if (unlikely(irqd_is_setaffinity_pending(data))) {
-		mask_ioapic_irq(data);
+		if (!irqd_irq_masked(data))
+			mask_ioapic_irq(data);
 		return true;
 	}
 	return false;
@@ -1766,7 +1768,9 @@
 		 */
 		if (!io_apic_level_ack_pending(data->chip_data))
 			irq_move_masked_irq(data);
-		unmask_ioapic_irq(data);
+		/* If the IRQ is masked in the core, leave it: */
+		if (!irqd_irq_masked(data))
+			unmask_ioapic_irq(data);
 	}
 }
 #else
@@ -1948,7 +1952,8 @@
 	.irq_set_affinity	= ioapic_set_affinity,
 	.irq_retrigger		= irq_chip_retrigger_hierarchy,
 	.irq_get_irqchip_state	= ioapic_irq_get_chip_state,
-	.flags			= IRQCHIP_SKIP_SET_WAKE,
+	.flags			= IRQCHIP_SKIP_SET_WAKE |
+				  IRQCHIP_AFFINITY_PRE_STARTUP,
 };
 
 static struct irq_chip ioapic_ir_chip __read_mostly = {
@@ -1961,7 +1966,8 @@
 	.irq_set_affinity	= ioapic_set_affinity,
 	.irq_retrigger		= irq_chip_retrigger_hierarchy,
 	.irq_get_irqchip_state	= ioapic_irq_get_chip_state,
-	.flags			= IRQCHIP_SKIP_SET_WAKE,
+	.flags			= IRQCHIP_SKIP_SET_WAKE |
+				  IRQCHIP_AFFINITY_PRE_STARTUP,
 };
 
 static inline void init_IO_APIC_traps(void)
@@ -2253,6 +2259,7 @@
 	legacy_pic->init(0);
 	legacy_pic->make_irq(0);
 	apic_write(APIC_LVT0, APIC_DM_EXTINT);
+	legacy_pic->unmask(0);
 
 	unlock_ExtINT_logic();
 
@@ -2326,12 +2333,12 @@
 	ip->irqdomain = irq_domain_create_linear(fn, hwirqs, cfg->ops,
 						 (void *)(long)ioapic);
 
-	/* Release fw handle if it was allocated above */
-	if (!cfg->dev)
-		irq_domain_free_fwnode(fn);
-
-	if (!ip->irqdomain)
+	if (!ip->irqdomain) {
+		/* Release fw handle if it was allocated above */
+		if (!cfg->dev)
+			irq_domain_free_fwnode(fn);
 		return -ENOMEM;
+	}
 
 	ip->irqdomain->parent = parent;
 
@@ -2345,8 +2352,13 @@
 
 static void ioapic_destroy_irqdomain(int idx)
 {
+	struct ioapic_domain_cfg *cfg = &ioapics[idx].irqdomain_cfg;
+	struct fwnode_handle *fn = ioapics[idx].irqdomain->fwnode;
+
 	if (ioapics[idx].irqdomain) {
 		irq_domain_remove(ioapics[idx].irqdomain);
+		if (!cfg->dev)
+			irq_domain_free_fwnode(fn);
 		ioapics[idx].irqdomain = NULL;
 	}
 }
@@ -2434,17 +2446,21 @@
 
 unsigned int arch_dynirq_lower_bound(unsigned int from)
 {
+	unsigned int ret;
+
 	/*
 	 * dmar_alloc_hwirq() may be called before setup_IO_APIC(), so use
 	 * gsi_top if ioapic_dynirq_base hasn't been initialized yet.
 	 */
-	if (!ioapic_initialized)
-		return gsi_top;
+	ret = ioapic_dynirq_base ? : gsi_top;
+
 	/*
-	 * For DT enabled machines ioapic_dynirq_base is irrelevant and not
-	 * updated. So simply return @from if ioapic_dynirq_base == 0.
+	 * For DT enabled machines ioapic_dynirq_base is irrelevant and
+	 * always 0. gsi_top can be 0 if there is no IO/APIC registered.
+	 * 0 is an invalid interrupt number for dynamic allocations. Return
+	 * @from instead.
 	 */
-	return ioapic_dynirq_base ? : from;
+	return ret ? : from;
 }
 
 #ifdef CONFIG_X86_32
@@ -2995,10 +3011,8 @@
 
 	info->ioapic_entry = &data->entry;
 	ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, info);
-	if (ret < 0) {
-		kfree(data);
-		return ret;
-	}
+	if (ret < 0)
+		goto free_data;
 
 	INIT_LIST_HEAD(&data->irq_2_pin);
 	irq_data->hwirq = info->ioapic_pin;
@@ -3008,7 +3022,10 @@
 	mp_irqdomain_get_attr(mp_pin_to_gsi(ioapic, pin), data, info);
 
 	cfg = irqd_cfg(irq_data);
-	add_pin_to_irq_node(data, ioapic_alloc_attr_node(info), ioapic, pin);
+	if (!add_pin_to_irq_node(data, ioapic_alloc_attr_node(info), ioapic, pin)) {
+		ret = -ENOMEM;
+		goto free_irqs;
+	}
 
 	local_irq_save(flags);
 	if (info->ioapic_entry)
@@ -3024,6 +3041,12 @@
 		    virq, data->trigger, data->polarity, cfg->dest_apicid);
 
 	return 0;
+
+free_irqs:
+	irq_domain_free_irqs_parent(domain, virq, nr_irqs);
+free_data:
+	kfree(data);
+	return ret;
 }
 
 void mp_irqdomain_free(struct irq_domain *domain, unsigned int virq,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/apic/msi.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/apic/msi.c
@@ -23,10 +23,8 @@
 
 static struct irq_domain *msi_default_domain;
 
-static void irq_msi_compose_msg(struct irq_data *data, struct msi_msg *msg)
+static void __irq_msi_compose_msg(struct irq_cfg *cfg, struct msi_msg *msg)
 {
-	struct irq_cfg *cfg = irqd_cfg(data);
-
 	msg->address_hi = MSI_ADDR_BASE_HI;
 
 	if (x2apic_enabled())
@@ -47,6 +45,129 @@
 		MSI_DATA_VECTOR(cfg->vector);
 }
 
+static void irq_msi_compose_msg(struct irq_data *data, struct msi_msg *msg)
+{
+	__irq_msi_compose_msg(irqd_cfg(data), msg);
+}
+
+static void irq_msi_update_msg(struct irq_data *irqd, struct irq_cfg *cfg)
+{
+	struct msi_msg msg[2] = { [1] = { }, };
+
+	__irq_msi_compose_msg(cfg, msg);
+	irq_data_get_irq_chip(irqd)->irq_write_msi_msg(irqd, msg);
+}
+
+static int
+msi_set_affinity(struct irq_data *irqd, const struct cpumask *mask, bool force)
+{
+	struct irq_cfg old_cfg, *cfg = irqd_cfg(irqd);
+	struct irq_data *parent = irqd->parent_data;
+	unsigned int cpu;
+	int ret;
+
+	/* Save the current configuration */
+	cpu = cpumask_first(irq_data_get_effective_affinity_mask(irqd));
+	old_cfg = *cfg;
+
+	/* Allocate a new target vector */
+	ret = parent->chip->irq_set_affinity(parent, mask, force);
+	if (ret < 0 || ret == IRQ_SET_MASK_OK_DONE)
+		return ret;
+
+	/*
+	 * For non-maskable and non-remapped MSI interrupts the migration
+	 * to a different destination CPU and a different vector has to be
+	 * done careful to handle the possible stray interrupt which can be
+	 * caused by the non-atomic update of the address/data pair.
+	 *
+	 * Direct update is possible when:
+	 * - The MSI is maskable (remapped MSI does not use this code path)).
+	 *   The quirk bit is not set in this case.
+	 * - The new vector is the same as the old vector
+	 * - The old vector is MANAGED_IRQ_SHUTDOWN_VECTOR (interrupt starts up)
+	 * - The interrupt is not yet started up
+	 * - The new destination CPU is the same as the old destination CPU
+	 */
+	if (!irqd_msi_nomask_quirk(irqd) ||
+	    cfg->vector == old_cfg.vector ||
+	    old_cfg.vector == MANAGED_IRQ_SHUTDOWN_VECTOR ||
+	    !irqd_is_started(irqd) ||
+	    cfg->dest_apicid == old_cfg.dest_apicid) {
+		irq_msi_update_msg(irqd, cfg);
+		return ret;
+	}
+
+	/*
+	 * Paranoia: Validate that the interrupt target is the local
+	 * CPU.
+	 */
+	if (WARN_ON_ONCE(cpu != smp_processor_id())) {
+		irq_msi_update_msg(irqd, cfg);
+		return ret;
+	}
+
+	/*
+	 * Redirect the interrupt to the new vector on the current CPU
+	 * first. This might cause a spurious interrupt on this vector if
+	 * the device raises an interrupt right between this update and the
+	 * update to the final destination CPU.
+	 *
+	 * If the vector is in use then the installed device handler will
+	 * denote it as spurious which is no harm as this is a rare event
+	 * and interrupt handlers have to cope with spurious interrupts
+	 * anyway. If the vector is unused, then it is marked so it won't
+	 * trigger the 'No irq handler for vector' warning in do_IRQ().
+	 *
+	 * This requires to hold vector lock to prevent concurrent updates to
+	 * the affected vector.
+	 */
+	lock_vector_lock();
+
+	/*
+	 * Mark the new target vector on the local CPU if it is currently
+	 * unused. Reuse the VECTOR_RETRIGGERED state which is also used in
+	 * the CPU hotplug path for a similar purpose. This cannot be
+	 * undone here as the current CPU has interrupts disabled and
+	 * cannot handle the interrupt before the whole set_affinity()
+	 * section is done. In the CPU unplug case, the current CPU is
+	 * about to vanish and will not handle any interrupts anymore. The
+	 * vector is cleaned up when the CPU comes online again.
+	 */
+	if (IS_ERR_OR_NULL(this_cpu_read(vector_irq[cfg->vector])))
+		this_cpu_write(vector_irq[cfg->vector], VECTOR_RETRIGGERED);
+
+	/* Redirect it to the new vector on the local CPU temporarily */
+	old_cfg.vector = cfg->vector;
+	irq_msi_update_msg(irqd, &old_cfg);
+
+	/* Now transition it to the target CPU */
+	irq_msi_update_msg(irqd, cfg);
+
+	/*
+	 * All interrupts after this point are now targeted at the new
+	 * vector/CPU.
+	 *
+	 * Drop vector lock before testing whether the temporary assignment
+	 * to the local CPU was hit by an interrupt raised in the device,
+	 * because the retrigger function acquires vector lock again.
+	 */
+	unlock_vector_lock();
+
+	/*
+	 * Check whether the transition raced with a device interrupt and
+	 * is pending in the local APICs IRR. It is safe to do this outside
+	 * of vector lock as the irq_desc::lock of this interrupt is still
+	 * held and interrupts are disabled: The check is not accessing the
+	 * underlying vector store. It's just checking the local APIC's
+	 * IRR.
+	 */
+	if (lapic_vector_set_in_irr(cfg->vector))
+		irq_data_get_irq_chip(irqd)->irq_retrigger(irqd);
+
+	return ret;
+}
+
 /*
  * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices,
  * which implement the MSI or MSI-X Capability Structure.
@@ -58,7 +179,9 @@
 	.irq_ack		= irq_chip_ack_parent,
 	.irq_retrigger		= irq_chip_retrigger_hierarchy,
 	.irq_compose_msi_msg	= irq_msi_compose_msg,
-	.flags			= IRQCHIP_SKIP_SET_WAKE,
+	.irq_set_affinity	= msi_set_affinity,
+	.flags			= IRQCHIP_SKIP_SET_WAKE |
+				  IRQCHIP_AFFINITY_PRE_STARTUP,
 };
 
 int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
@@ -142,10 +265,13 @@
 		msi_default_domain =
 			pci_msi_create_irq_domain(fn, &pci_msi_domain_info,
 						  parent);
-		irq_domain_free_fwnode(fn);
 	}
-	if (!msi_default_domain)
+	if (!msi_default_domain) {
+		irq_domain_free_fwnode(fn);
 		pr_warn("failed to initialize irqdomain for MSI/MSI-x.\n");
+	} else {
+		msi_default_domain->flags |= IRQ_DOMAIN_MSI_NOMASK_QUIRK;
+	}
 }
 
 #ifdef CONFIG_IRQ_REMAP
@@ -156,7 +282,8 @@
 	.irq_ack		= irq_chip_ack_parent,
 	.irq_retrigger		= irq_chip_retrigger_hierarchy,
 	.irq_set_vcpu_affinity	= irq_chip_set_vcpu_affinity_parent,
-	.flags			= IRQCHIP_SKIP_SET_WAKE,
+	.flags			= IRQCHIP_SKIP_SET_WAKE |
+				  IRQCHIP_AFFINITY_PRE_STARTUP,
 };
 
 static struct msi_domain_info pci_msi_ir_domain_info = {
@@ -178,7 +305,8 @@
 	if (!fn)
 		return NULL;
 	d = pci_msi_create_irq_domain(fn, &pci_msi_ir_domain_info, parent);
-	irq_domain_free_fwnode(fn);
+	if (!d)
+		irq_domain_free_fwnode(fn);
 	return d;
 }
 #endif
@@ -198,7 +326,8 @@
 	.irq_retrigger		= irq_chip_retrigger_hierarchy,
 	.irq_compose_msi_msg	= irq_msi_compose_msg,
 	.irq_write_msi_msg	= dmar_msi_write_msg,
-	.flags			= IRQCHIP_SKIP_SET_WAKE,
+	.flags			= IRQCHIP_SKIP_SET_WAKE |
+				  IRQCHIP_AFFINITY_PRE_STARTUP,
 };
 
 static irq_hw_number_t dmar_msi_get_hwirq(struct msi_domain_info *info,
@@ -241,7 +370,8 @@
 	if (fn) {
 		dmar_domain = msi_create_irq_domain(fn, &dmar_msi_domain_info,
 						    x86_vector_domain);
-		irq_domain_free_fwnode(fn);
+		if (!dmar_domain)
+			irq_domain_free_fwnode(fn);
 	}
 out:
 	mutex_unlock(&dmar_lock);
@@ -295,7 +425,7 @@
 	.irq_retrigger = irq_chip_retrigger_hierarchy,
 	.irq_compose_msi_msg = irq_msi_compose_msg,
 	.irq_write_msi_msg = hpet_msi_write_msg,
-	.flags = IRQCHIP_SKIP_SET_WAKE,
+	.flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_AFFINITY_PRE_STARTUP,
 };
 
 static irq_hw_number_t hpet_msi_get_hwirq(struct msi_domain_info *info,
@@ -366,7 +496,10 @@
 	}
 
 	d = msi_create_irq_domain(fn, domain_info, parent);
-	irq_domain_free_fwnode(fn);
+	if (!d) {
+		irq_domain_free_fwnode(fn);
+		kfree(domain_info);
+	}
 	return d;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/apic/vector.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/apic/vector.c
@@ -272,20 +272,24 @@
 	const struct cpumask *affmsk = irq_data_get_affinity_mask(irqd);
 	int node = irq_data_get_node(irqd);
 
-	if (node == NUMA_NO_NODE)
-		goto all;
-	/* Try the intersection of @affmsk and node mask */
-	cpumask_and(vector_searchmask, cpumask_of_node(node), affmsk);
-	if (!assign_vector_locked(irqd, vector_searchmask))
-		return 0;
-	/* Try the node mask */
-	if (!assign_vector_locked(irqd, cpumask_of_node(node)))
-		return 0;
-all:
+	if (node != NUMA_NO_NODE) {
+		/* Try the intersection of @affmsk and node mask */
+		cpumask_and(vector_searchmask, cpumask_of_node(node), affmsk);
+		if (!assign_vector_locked(irqd, vector_searchmask))
+			return 0;
+	}
+
 	/* Try the full affinity mask */
 	cpumask_and(vector_searchmask, affmsk, cpu_online_mask);
 	if (!assign_vector_locked(irqd, vector_searchmask))
 		return 0;
+
+	if (node != NUMA_NO_NODE) {
+		/* Try the node mask */
+		if (!assign_vector_locked(irqd, cpumask_of_node(node)))
+			return 0;
+	}
+
 	/* Try the full online mask */
 	return assign_vector_locked(irqd, cpu_online_mask);
 }
@@ -446,12 +450,10 @@
 	trace_vector_activate(irqd->irq, apicd->is_managed,
 			      apicd->can_reserve, reserve);
 
-	/* Nothing to do for fixed assigned vectors */
-	if (!apicd->can_reserve && !apicd->is_managed)
-		return 0;
-
 	raw_spin_lock_irqsave(&vector_lock, flags);
-	if (reserve || irqd_is_managed_and_shutdown(irqd))
+	if (!apicd->can_reserve && !apicd->is_managed)
+		assign_irq_vector_any_locked(irqd);
+	else if (reserve || irqd_is_managed_and_shutdown(irqd))
 		vector_assign_managed_shutdown(irqd);
 	else if (apicd->is_managed)
 		ret = activate_managed(irqd);
@@ -556,6 +558,10 @@
 		irqd->chip_data = apicd;
 		irqd->hwirq = virq + i;
 		irqd_set_single_target(irqd);
+
+		/* Don't invoke affinity setter on deactivated interrupts */
+		irqd_set_affinity_on_activate(irqd);
+
 		/*
 		 * Legacy vectors are already assigned when the IOAPIC
 		 * takes them over. They stay on the same vector. This is
@@ -674,6 +680,26 @@
 	irq_matrix_assign_system(vector_matrix, ISA_IRQ_VECTOR(irq), replace);
 }
 
+void __init lapic_update_legacy_vectors(void)
+{
+	unsigned int i;
+
+	if (IS_ENABLED(CONFIG_X86_IO_APIC) && nr_ioapics > 0)
+		return;
+
+	/*
+	 * If the IO/APIC is disabled via config, kernel command line or
+	 * lack of enumeration then all legacy interrupts are routed
+	 * through the PIC. Make sure that they are marked as legacy
+	 * vectors. PIC_CASCADE_IRQ has already been marked in
+	 * lapic_assign_system_vectors().
+	 */
+	for (i = 0; i < nr_legacy_irqs(); i++) {
+		if (i != PIC_CASCADE_IR)
+			lapic_assign_legacy_vector(i, true);
+	}
+}
+
 void __init lapic_assign_system_vectors(void)
 {
 	unsigned int i, vector = 0;
@@ -703,7 +729,6 @@
 	x86_vector_domain = irq_domain_create_tree(fn, &x86_vector_domain_ops,
 						   NULL);
 	BUG_ON(x86_vector_domain == NULL);
-	irq_domain_free_fwnode(fn);
 	irq_set_default_host(x86_vector_domain);
 
 	arch_init_msi_domain(x86_vector_domain);
@@ -769,20 +794,10 @@
 static int apic_set_affinity(struct irq_data *irqd,
 			     const struct cpumask *dest, bool force)
 {
-	struct apic_chip_data *apicd = apic_chip_data(irqd);
 	int err;
 
-	/*
-	 * Core code can call here for inactive interrupts. For inactive
-	 * interrupts which use managed or reservation mode there is no
-	 * point in going through the vector assignment right now as the
-	 * activation will assign a vector which fits the destination
-	 * cpumask. Let the core code store the destination mask and be
-	 * done with it.
-	 */
-	if (!irqd_is_activated(irqd) &&
-	    (apicd->is_managed || apicd->can_reserve))
-		return IRQ_SET_MASK_OK;
+	if (WARN_ON_ONCE(!irqd_is_activated(irqd)))
+		return -EIO;
 
 	raw_spin_lock(&vector_lock);
 	cpumask_and(vector_searchmask, dest, cpu_online_mask);
@@ -898,7 +913,8 @@
 		hlist_add_head(&apicd->clist, per_cpu_ptr(&cleanup_list, cpu));
 		apic->send_IPI(cpu, IRQ_MOVE_CLEANUP_VECTOR);
 	} else {
-		apicd->prev_vector = 0;
+		pr_warn("IRQ %u schedule cleanup for offline CPU %u\n", apicd->irq, cpu);
+		free_moved_vector(apicd);
 	}
 	raw_spin_unlock(&vector_lock);
 }
@@ -934,6 +950,7 @@
  */
 void irq_force_complete_move(struct irq_desc *desc)
 {
+	unsigned int cpu = smp_processor_id();
 	struct apic_chip_data *apicd;
 	struct irq_data *irqd;
 	unsigned int vector;
@@ -958,10 +975,11 @@
 		goto unlock;
 
 	/*
-	 * If prev_vector is empty, no action required.
+	 * If prev_vector is empty or the descriptor is neither currently
+	 * nor previously on the outgoing CPU no action required.
 	 */
 	vector = apicd->prev_vector;
-	if (!vector)
+	if (!vector || (apicd->cpu != cpu && apicd->prev_cpu != cpu))
 		goto unlock;
 
 	/*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/apic/x2apic_cluster.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/apic/x2apic_cluster.c
@@ -29,7 +29,8 @@
 {
 	u32 dest = per_cpu(x86_cpu_to_logical_apicid, cpu);
 
-	x2apic_wrmsr_fence();
+	/* x2apic MSRs are special and need a special fence: */
+	weak_wrmsr_fence();
 	__x2apic_send_IPI_dest(dest, vector, APIC_DEST_LOGICAL);
 }
 
@@ -41,7 +42,8 @@
 	unsigned long flags;
 	u32 dest;
 
-	x2apic_wrmsr_fence();
+	/* x2apic MSRs are special and need a special fence: */
+	weak_wrmsr_fence();
 	local_irq_save(flags);
 
 	tmpmsk = this_cpu_cpumask_var_ptr(ipi_mask);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/apic/x2apic_phys.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/apic/x2apic_phys.c
@@ -8,6 +8,12 @@
 int x2apic_phys;
 
 static struct apic apic_x2apic_phys;
+static u32 x2apic_max_apicid __ro_after_init;
+
+void __init x2apic_set_max_apicid(u32 apicid)
+{
+	x2apic_max_apicid = apicid;
+}
 
 static int __init set_x2apic_phys_mode(char *arg)
 {
@@ -37,7 +43,8 @@
 {
 	u32 dest = per_cpu(x86_cpu_to_apicid, cpu);
 
-	x2apic_wrmsr_fence();
+	/* x2apic MSRs are special and need a special fence: */
+	weak_wrmsr_fence();
 	__x2apic_send_IPI_dest(dest, vector, APIC_DEST_PHYSICAL);
 }
 
@@ -48,7 +55,8 @@
 	unsigned long this_cpu;
 	unsigned long flags;
 
-	x2apic_wrmsr_fence();
+	/* x2apic MSRs are special and need a special fence: */
+	weak_wrmsr_fence();
 
 	local_irq_save(flags);
 
@@ -89,7 +97,10 @@
 
 static int x2apic_phys_probe(void)
 {
-	if (x2apic_mode && (x2apic_phys || x2apic_fadt_phys()))
+	if (!x2apic_mode)
+		return 0;
+
+	if (x2apic_phys || x2apic_fadt_phys())
 		return 1;
 
 	return apic == &apic_x2apic_phys;
@@ -98,6 +109,9 @@
 /* Common x2apic functions, also used by x2apic_cluster */
 int x2apic_apic_id_valid(u32 apicid)
 {
+	if (x2apic_max_apicid && apicid > x2apic_max_apicid)
+		return 0;
+
 	return 1;
 }
 
@@ -116,7 +130,8 @@
 {
 	unsigned long cfg = __prepare_ICR(which, vector, 0);
 
-	x2apic_wrmsr_fence();
+	/* x2apic MSRs are special and need a special fence: */
+	weak_wrmsr_fence();
 	native_x2apic_icr_write(cfg, 0);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/apm_32.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/apm_32.c
@@ -238,12 +238,6 @@
 #endif
 
 /*
- * The apm_bios device is one of the misc char devices.
- * This is its minor number.
- */
-#define	APM_MINOR_DEV	134
-
-/*
  * Various options can be changed at boot time as follows:
  * (We allow underscores for compatibility with the modules code)
  *	apm=on/off			enable/disable APM
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/cpu/amd.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/cpu/amd.c
@@ -26,10 +26,6 @@
 
 #include "cpu.h"
 
-static const int amd_erratum_383[];
-static const int amd_erratum_400[];
-static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum);
-
 /*
  * nodes_per_socket: Stores the number of nodes per socket.
  * Refer to Fam15h Models 00-0fh BKDG - CPUID Fn8000_001E_ECX
@@ -37,6 +33,87 @@
  */
 static u32 nodes_per_socket = 1;
 
+/*
+ * AMD errata checking
+ *
+ * Errata are defined as arrays of ints using the AMD_LEGACY_ERRATUM() or
+ * AMD_OSVW_ERRATUM() macros. The latter is intended for newer errata that
+ * have an OSVW id assigned, which it takes as first argument. Both take a
+ * variable number of family-specific model-stepping ranges created by
+ * AMD_MODEL_RANGE().
+ *
+ * Example:
+ *
+ * const int amd_erratum_319[] =
+ *	AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0x4, 0x2),
+ *			   AMD_MODEL_RANGE(0x10, 0x8, 0x0, 0x8, 0x0),
+ *			   AMD_MODEL_RANGE(0x10, 0x9, 0x0, 0x9, 0x0));
+ */
+
+#define AMD_LEGACY_ERRATUM(...)		{ -1, __VA_ARGS__, 0 }
+#define AMD_OSVW_ERRATUM(osvw_id, ...)	{ osvw_id, __VA_ARGS__, 0 }
+#define AMD_MODEL_RANGE(f, m_start, s_start, m_end, s_end) \
+	((f << 24) | (m_start << 16) | (s_start << 12) | (m_end << 4) | (s_end))
+#define AMD_MODEL_RANGE_FAMILY(range)	(((range) >> 24) & 0xff)
+#define AMD_MODEL_RANGE_START(range)	(((range) >> 12) & 0xfff)
+#define AMD_MODEL_RANGE_END(range)	((range) & 0xfff)
+
+static const int amd_erratum_400[] =
+	AMD_OSVW_ERRATUM(1, AMD_MODEL_RANGE(0xf, 0x41, 0x2, 0xff, 0xf),
+			    AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0xff, 0xf));
+
+static const int amd_erratum_383[] =
+	AMD_OSVW_ERRATUM(3, AMD_MODEL_RANGE(0x10, 0, 0, 0xff, 0xf));
+
+/* #1054: Instructions Retired Performance Counter May Be Inaccurate */
+static const int amd_erratum_1054[] =
+	AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x17, 0, 0, 0x2f, 0xf));
+
+static const int amd_zenbleed[] =
+	AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x17, 0x30, 0x0, 0x4f, 0xf),
+			   AMD_MODEL_RANGE(0x17, 0x60, 0x0, 0x7f, 0xf),
+			   AMD_MODEL_RANGE(0x17, 0x90, 0x0, 0x91, 0xf),
+			   AMD_MODEL_RANGE(0x17, 0xa0, 0x0, 0xaf, 0xf));
+
+static const int amd_div0[] =
+	AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x17, 0x00, 0x0, 0x2f, 0xf),
+			   AMD_MODEL_RANGE(0x17, 0x50, 0x0, 0x5f, 0xf));
+
+static const int amd_erratum_1485[] =
+	AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x19, 0x10, 0x0, 0x1f, 0xf),
+			   AMD_MODEL_RANGE(0x19, 0x60, 0x0, 0xaf, 0xf));
+
+static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum)
+{
+	int osvw_id = *erratum++;
+	u32 range;
+	u32 ms;
+
+	if (osvw_id >= 0 && osvw_id < 65536 &&
+	    cpu_has(cpu, X86_FEATURE_OSVW)) {
+		u64 osvw_len;
+
+		rdmsrl(MSR_AMD64_OSVW_ID_LENGTH, osvw_len);
+		if (osvw_id < osvw_len) {
+			u64 osvw_bits;
+
+			rdmsrl(MSR_AMD64_OSVW_STATUS + (osvw_id >> 6),
+			    osvw_bits);
+			return osvw_bits & (1ULL << (osvw_id & 0x3f));
+		}
+	}
+
+	/* OSVW unavailable or ID unknown, match family-model-stepping range */
+	ms = (cpu->x86_model << 4) | cpu->x86_stepping;
+	while ((range = *erratum++))
+		if ((cpu->x86 == AMD_MODEL_RANGE_FAMILY(range)) &&
+		    (ms >= AMD_MODEL_RANGE_START(range)) &&
+		    (ms <= AMD_MODEL_RANGE_END(range)))
+			return true;
+
+	return false;
+}
+
 static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p)
 {
 	u32 gprs[8] = { 0 };
@@ -334,7 +411,6 @@
  */
 static void amd_get_topology(struct cpuinfo_x86 *c)
 {
-	u8 node_id;
 	int cpu = smp_processor_id();
 
 	/* get information required for multi-node processors */
@@ -344,7 +420,7 @@
 
 		cpuid(0x8000001e, &eax, &ebx, &ecx, &edx);
 
-		node_id  = ecx & 0xff;
+		c->cpu_die_id  = ecx & 0xff;
 
 		if (c->x86 == 0x15)
 			c->cu_id = ebx & 0xff;
@@ -364,15 +440,15 @@
 		if (!err)
 			c->x86_coreid_bits = get_count_order(c->x86_max_cores);
 
-		cacheinfo_amd_init_llc_id(c, cpu, node_id);
+		cacheinfo_amd_init_llc_id(c, cpu);
 
 	} else if (cpu_has(c, X86_FEATURE_NODEID_MSR)) {
 		u64 value;
 
 		rdmsrl(MSR_FAM10H_NODE_ID, value);
-		node_id = value & 7;
+		c->cpu_die_id = value & 7;
 
-		per_cpu(cpu_llc_id, cpu) = node_id;
+		per_cpu(cpu_llc_id, cpu) = c->cpu_die_id;
 	} else
 		return;
 
@@ -397,7 +473,7 @@
 	/* Convert the initial APIC ID into the socket ID */
 	c->phys_proc_id = c->initial_apicid >> bits;
 	/* use socket ID also for last level cache */
-	per_cpu(cpu_llc_id, cpu) = c->phys_proc_id;
+	per_cpu(cpu_llc_id, cpu) = c->cpu_die_id = c->phys_proc_id;
 }
 
 u16 amd_get_nb_id(int cpu)
@@ -545,12 +621,12 @@
 		u32 ecx;
 
 		ecx = cpuid_ecx(0x8000001e);
-		nodes_per_socket = ((ecx >> 8) & 7) + 1;
+		__max_die_per_package = nodes_per_socket = ((ecx >> 8) & 7) + 1;
 	} else if (boot_cpu_has(X86_FEATURE_NODEID_MSR)) {
 		u64 value;
 
 		rdmsrl(MSR_FAM10H_NODE_ID, value);
-		nodes_per_socket = ((value >> 3) & 7) + 1;
+		__max_die_per_package = nodes_per_socket = ((value >> 3) & 7) + 1;
 	}
 
 	if (!boot_cpu_has(X86_FEATURE_AMD_SSBD) &&
@@ -587,7 +663,7 @@
 	 *	      If BIOS has not enabled SME then don't advertise the
 	 *	      SME feature (set in scattered.c).
 	 *   For SEV: If BIOS has not enabled SEV then don't advertise the
-	 *            SEV feature (set in scattered.c).
+	 *            SEV and SEV_ES feature (set in scattered.c).
 	 *
 	 *   In all cases, since support for SME and SEV requires long mode,
 	 *   don't advertise the feature under CONFIG_X86_32.
@@ -615,9 +691,10 @@
 		return;
 
 clear_all:
-		clear_cpu_cap(c, X86_FEATURE_SME);
+		setup_clear_cpu_cap(X86_FEATURE_SME);
 clear_sev:
-		clear_cpu_cap(c, X86_FEATURE_SEV);
+		setup_clear_cpu_cap(X86_FEATURE_SEV);
+		setup_clear_cpu_cap(X86_FEATURE_SEV_ES);
 	}
 }
 
@@ -794,8 +871,6 @@
 		set_cpu_bug(c, X86_BUG_AMD_TLB_MMATCH);
 }
 
-#define MSR_AMD64_DE_CFG	0xC0011029
-
 static void init_amd_ln(struct cpuinfo_x86 *c)
 {
 	/*
@@ -894,12 +969,73 @@
 	node_reclaim_distance = 32;
 #endif
 
+	/* Fix up CPUID bits, but only if not virtualised. */
+	if (!cpu_has(c, X86_FEATURE_HYPERVISOR)) {
+
+		/* Erratum 1076: CPB feature bit not being set in CPUID. */
+		if (!cpu_has(c, X86_FEATURE_CPB))
+			set_cpu_cap(c, X86_FEATURE_CPB);
+
+		/*
+		 * Zen3 (Fam19 model < 0x10) parts are not susceptible to
+		 * Branch Type Confusion, but predate the allocation of the
+		 * BTC_NO bit.
+		 */
+		if (c->x86 == 0x19 && !cpu_has(c, X86_FEATURE_BTC_NO))
+			set_cpu_cap(c, X86_FEATURE_BTC_NO);
+	}
+
 	/*
-	 * Fix erratum 1076: CPB feature bit not being set in CPUID.
-	 * Always set it, except when running under a hypervisor.
+	 * Work around Erratum 1386.  The XSAVES instruction malfunctions in
+	 * certain circumstances on Zen1/2 uarch, and not all parts have had
+	 * updated microcode at the time of writing (March 2023).
+	 *
+	 * Affected parts all have no supervisor XSAVE states, meaning that
+	 * the XSAVEC instruction (which works fine) is equivalent.
 	 */
-	if (!cpu_has(c, X86_FEATURE_HYPERVISOR) && !cpu_has(c, X86_FEATURE_CPB))
-		set_cpu_cap(c, X86_FEATURE_CPB);
+	if (c->x86 == 0x17)
+		clear_cpu_cap(c, X86_FEATURE_XSAVES);
+}
+
+static bool cpu_has_zenbleed_microcode(void)
+{
+	u32 good_rev = 0;
+
+	switch (boot_cpu_data.x86_model) {
+	case 0x30 ... 0x3f: good_rev = 0x0830107b; break;
+	case 0x60 ... 0x67: good_rev = 0x0860010c; break;
+	case 0x68 ... 0x6f: good_rev = 0x08608107; break;
+	case 0x70 ... 0x7f: good_rev = 0x08701033; break;
+	case 0xa0 ... 0xaf: good_rev = 0x08a00009; break;
+
+	default:
+		return false;
+		break;
+	}
+
+	if (boot_cpu_data.microcode < good_rev)
+		return false;
+
+	return true;
+}
+
+static void zenbleed_check(struct cpuinfo_x86 *c)
+{
+	if (!cpu_has_amd_erratum(c, amd_zenbleed))
+		return;
+
+	if (cpu_has(c, X86_FEATURE_HYPERVISOR))
+		return;
+
+	if (!cpu_has(c, X86_FEATURE_AVX))
+		return;
+
+	if (!cpu_has_zenbleed_microcode()) {
+		pr_notice_once("Zenbleed: please update your microcode for the most optimal fix\n");
+		msr_set_bit(MSR_AMD64_DE_CFG, MSR_AMD64_DE_CFG_ZEN2_FP_BACKUP_FIX_BIT);
+	} else {
+		msr_clear_bit(MSR_AMD64_DE_CFG, MSR_AMD64_DE_CFG_ZEN2_FP_BACKUP_FIX_BIT);
+	}
 }
 
 static void init_amd(struct cpuinfo_x86 *c)
@@ -956,8 +1092,8 @@
 		 * msr_set_bit() uses the safe accessors, too, even if the MSR
 		 * is not present.
 		 */
-		msr_set_bit(MSR_F10H_DECFG,
-			    MSR_F10H_DECFG_LFENCE_SERIALIZE_BIT);
+		msr_set_bit(MSR_AMD64_DE_CFG,
+			    MSR_AMD64_DE_CFG_LFENCE_SERIALIZE_BIT);
 
 		/* A serializing LFENCE stops RDTSC speculation */
 		set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC);
@@ -978,6 +1114,24 @@
 	/* AMD CPUs don't reset SS attributes on SYSRET, Xen does. */
 	if (!cpu_has(c, X86_FEATURE_XENPV))
 		set_cpu_bug(c, X86_BUG_SYSRET_SS_ATTRS);
+
+	/*
+	 * Turn on the Instructions Retired free counter on machines not
+	 * susceptible to erratum #1054 "Instructions Retired Performance
+	 * Counter May Be Inaccurate".
+	 */
+	if (cpu_has(c, X86_FEATURE_IRPERF) &&
+	    !cpu_has_amd_erratum(c, amd_erratum_1054))
+		msr_set_bit(MSR_K7_HWCR, MSR_K7_HWCR_IRPERF_EN_BIT);
+
+	check_null_seg_clears_base(c);
+
+	zenbleed_check(c);
+
+	if (cpu_has_amd_erratum(c, amd_div0)) {
+		pr_notice_once("AMD Zen1 DIV0 bug detected. Disable SMT for full protection.\n");
+		setup_force_cpu_bug(X86_BUG_DIV0);
+	}
 }
 
 #ifdef CONFIG_X86_32
@@ -1073,70 +1227,6 @@
 
 cpu_dev_register(amd_cpu_dev);
 
-/*
- * AMD errata checking
- *
- * Errata are defined as arrays of ints using the AMD_LEGACY_ERRATUM() or
- * AMD_OSVW_ERRATUM() macros. The latter is intended for newer errata that
- * have an OSVW id assigned, which it takes as first argument. Both take a
- * variable number of family-specific model-stepping ranges created by
- * AMD_MODEL_RANGE().
- *
- * Example:
- *
- * const int amd_erratum_319[] =
- *	AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0x4, 0x2),
- *			   AMD_MODEL_RANGE(0x10, 0x8, 0x0, 0x8, 0x0),
- *			   AMD_MODEL_RANGE(0x10, 0x9, 0x0, 0x9, 0x0));
- */
-
-#define AMD_LEGACY_ERRATUM(...)		{ -1, __VA_ARGS__, 0 }
-#define AMD_OSVW_ERRATUM(osvw_id, ...)	{ osvw_id, __VA_ARGS__, 0 }
-#define AMD_MODEL_RANGE(f, m_start, s_start, m_end, s_end) \
-	((f << 24) | (m_start << 16) | (s_start << 12) | (m_end << 4) | (s_end))
-#define AMD_MODEL_RANGE_FAMILY(range)	(((range) >> 24) & 0xff)
-#define AMD_MODEL_RANGE_START(range)	(((range) >> 12) & 0xfff)
-#define AMD_MODEL_RANGE_END(range)	((range) & 0xfff)
-
-static const int amd_erratum_400[] =
-	AMD_OSVW_ERRATUM(1, AMD_MODEL_RANGE(0xf, 0x41, 0x2, 0xff, 0xf),
-			    AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0xff, 0xf));
-
-static const int amd_erratum_383[] =
-	AMD_OSVW_ERRATUM(3, AMD_MODEL_RANGE(0x10, 0, 0, 0xff, 0xf));
-
-
-static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum)
-{
-	int osvw_id = *erratum++;
-	u32 range;
-	u32 ms;
-
-	if (osvw_id >= 0 && osvw_id < 65536 &&
-	    cpu_has(cpu, X86_FEATURE_OSVW)) {
-		u64 osvw_len;
-
-		rdmsrl(MSR_AMD64_OSVW_ID_LENGTH, osvw_len);
-		if (osvw_id < osvw_len) {
-			u64 osvw_bits;
-
-			rdmsrl(MSR_AMD64_OSVW_STATUS + (osvw_id >> 6),
-			    osvw_bits);
-			return osvw_bits & (1ULL << (osvw_id & 0x3f));
-		}
-	}
-
-	/* OSVW unavailable or ID unknown, match family-model-stepping range */
-	ms = (cpu->x86_model << 4) | cpu->x86_stepping;
-	while ((range = *erratum++))
-		if ((cpu->x86 == AMD_MODEL_RANGE_FAMILY(range)) &&
-		    (ms >= AMD_MODEL_RANGE_START(range)) &&
-		    (ms <= AMD_MODEL_RANGE_END(range)))
-			return true;
-
-	return false;
-}
-
 void set_dr_addr_mask(unsigned long mask, int dr)
 {
 	if (!boot_cpu_has(X86_FEATURE_BPEXT))
@@ -1155,3 +1245,33 @@
 		break;
 	}
 }
+
+static void zenbleed_check_cpu(void *unused)
+{
+	struct cpuinfo_x86 *c = &cpu_data(smp_processor_id());
+
+	zenbleed_check(c);
+
+	if (!cpu_has(c, X86_FEATURE_HYPERVISOR) &&
+	     cpu_has_amd_erratum(c, amd_erratum_1485))
+		msr_set_bit(MSR_ZEN4_BP_CFG, MSR_ZEN4_BP_CFG_SHARED_BTB_FIX_BIT);
+}
+
+void amd_check_microcode(void)
+{
+	if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
+		return;
+
+	on_each_cpu(zenbleed_check_cpu, NULL, 1);
+}
+
+/*
+ * Issue a DIV 0/1 insn to clear any division data from previous DIV
+ * operations.
+ */
+void noinstr amd_clear_divider(void)
+{
+	asm volatile(ALTERNATIVE("", "div %2\n\t", X86_BUG_DIV0)
+		     :: "a" (0), "d" (0), "r" (1));
+}
+EXPORT_SYMBOL_GPL(amd_clear_divider);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/cpu/bugs.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/cpu/bugs.c
@@ -9,7 +9,6 @@
  *	- Andrew D. Balsa (code cleanup).
  */
 #include <linux/init.h>
-#include <linux/utsname.h>
 #include <linux/cpu.h>
 #include <linux/module.h>
 #include <linux/nospec.h>
@@ -25,32 +24,80 @@
 #include <asm/msr.h>
 #include <asm/vmx.h>
 #include <asm/paravirt.h>
-#include <asm/alternative.h>
 #include <asm/pgtable.h>
-#include <asm/set_memory.h>
 #include <asm/intel-family.h>
 #include <asm/e820/api.h>
 #include <asm/hypervisor.h>
+#include <linux/bpf.h>
 
 #include "cpu.h"
 
 static void __init spectre_v1_select_mitigation(void);
 static void __init spectre_v2_select_mitigation(void);
+static void __init retbleed_select_mitigation(void);
+static void __init spectre_v2_user_select_mitigation(void);
 static void __init ssb_select_mitigation(void);
 static void __init l1tf_select_mitigation(void);
 static void __init mds_select_mitigation(void);
+static void __init md_clear_update_mitigation(void);
+static void __init md_clear_select_mitigation(void);
 static void __init taa_select_mitigation(void);
+static void __init mmio_select_mitigation(void);
+static void __init srbds_select_mitigation(void);
+static void __init gds_select_mitigation(void);
+static void __init vmscape_select_mitigation(void);
 
-/* The base value of the SPEC_CTRL MSR that always has to be preserved. */
+/* The base value of the SPEC_CTRL MSR without task-specific bits set */
 u64 x86_spec_ctrl_base;
 EXPORT_SYMBOL_GPL(x86_spec_ctrl_base);
+
+/* The current value of the SPEC_CTRL MSR with task-specific bits set */
+DEFINE_PER_CPU(u64, x86_spec_ctrl_current);
+EXPORT_SYMBOL_GPL(x86_spec_ctrl_current);
+
+static u64 __ro_after_init x86_arch_cap_msr;
+
+/*
+ * Set when the CPU has run a potentially malicious guest. An IBPB will
+ * be needed to before running userspace. That IBPB will flush the branch
+ * predictor content.
+ */
+DEFINE_PER_CPU(bool, x86_ibpb_exit_to_user);
+EXPORT_PER_CPU_SYMBOL_GPL(x86_ibpb_exit_to_user);
+
 static DEFINE_MUTEX(spec_ctrl_mutex);
 
+/* Update SPEC_CTRL MSR and its cached copy unconditionally */
+static void update_spec_ctrl(u64 val)
+{
+	this_cpu_write(x86_spec_ctrl_current, val);
+	wrmsrl(MSR_IA32_SPEC_CTRL, val);
+}
+
 /*
- * The vendor and possibly platform specific bits which can be modified in
- * x86_spec_ctrl_base.
+ * Keep track of the SPEC_CTRL MSR value for the current task, which may differ
+ * from x86_spec_ctrl_base due to STIBP/SSB in __speculation_ctrl_update().
  */
-static u64 __ro_after_init x86_spec_ctrl_mask = SPEC_CTRL_IBRS;
+void update_spec_ctrl_cond(u64 val)
+{
+	if (this_cpu_read(x86_spec_ctrl_current) == val)
+		return;
+
+	this_cpu_write(x86_spec_ctrl_current, val);
+
+	/*
+	 * When KERNEL_IBRS this MSR is written on return-to-user, unless
+	 * forced the update can be delayed until that time.
+	 */
+	if (!cpu_feature_enabled(X86_FEATURE_KERNEL_IBRS))
+		wrmsrl(MSR_IA32_SPEC_CTRL, val);
+}
+
+u64 spec_ctrl_current(void)
+{
+	return this_cpu_read(x86_spec_ctrl_current);
+}
+EXPORT_SYMBOL_GPL(spec_ctrl_current);
 
 /*
  * AMD specific MSR info for Speculative Store Bypass control.
@@ -73,100 +120,64 @@
 DEFINE_STATIC_KEY_FALSE(mds_idle_clear);
 EXPORT_SYMBOL_GPL(mds_idle_clear);
 
-void __init check_bugs(void)
-{
-	identify_boot_cpu();
-
-	/*
-	 * identify_boot_cpu() initialized SMT support information, let the
-	 * core code know.
-	 */
-	cpu_smt_check_topology();
-
-	if (!IS_ENABLED(CONFIG_SMP)) {
-		pr_info("CPU: ");
-		print_cpu_info(&boot_cpu_data);
-	}
+/* Controls CPU Fill buffer clear before KVM guest MMIO accesses */
+DEFINE_STATIC_KEY_FALSE(mmio_stale_data_clear);
+EXPORT_SYMBOL_GPL(mmio_stale_data_clear);
 
+void __init cpu_select_mitigations(void)
+{
 	/*
 	 * Read the SPEC_CTRL MSR to account for reserved bits which may
 	 * have unknown values. AMD64_LS_CFG MSR is cached in the early AMD
 	 * init code as it is not enumerated and depends on the family.
 	 */
-	if (boot_cpu_has(X86_FEATURE_MSR_SPEC_CTRL))
+	if (cpu_feature_enabled(X86_FEATURE_MSR_SPEC_CTRL)) {
 		rdmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base);
 
-	/* Allow STIBP in MSR_SPEC_CTRL if supported */
-	if (boot_cpu_has(X86_FEATURE_STIBP))
-		x86_spec_ctrl_mask |= SPEC_CTRL_STIBP;
+		/*
+		 * Previously running kernel (kexec), may have some controls
+		 * turned ON. Clear them and let the mitigations setup below
+		 * rediscover them based on configuration.
+		 */
+		x86_spec_ctrl_base &= ~SPEC_CTRL_MITIGATIONS_MASK;
+	}
+
+	x86_arch_cap_msr = x86_read_arch_cap_msr();
 
 	/* Select the proper CPU mitigations before patching alternatives: */
 	spectre_v1_select_mitigation();
 	spectre_v2_select_mitigation();
-	ssb_select_mitigation();
-	l1tf_select_mitigation();
-	mds_select_mitigation();
-	taa_select_mitigation();
-
-	arch_smt_update();
-
-#ifdef CONFIG_X86_32
 	/*
-	 * Check whether we are able to run this kernel safely on SMP.
-	 *
-	 * - i386 is no longer supported.
-	 * - In order to run on anything without a TSC, we need to be
-	 *   compiled for a i486.
+	 * retbleed_select_mitigation() relies on the state set by
+	 * spectre_v2_select_mitigation(); specifically it wants to know about
+	 * spectre_v2=ibrs.
 	 */
-	if (boot_cpu_data.x86 < 4)
-		panic("Kernel requires i486+ for 'invlpg' and other features");
-
-	init_utsname()->machine[1] =
-		'0' + (boot_cpu_data.x86 > 6 ? 6 : boot_cpu_data.x86);
-	alternative_instructions();
-
-	fpu__init_check_bugs();
-#else /* CONFIG_X86_64 */
-	alternative_instructions();
-
+	retbleed_select_mitigation();
 	/*
-	 * Make sure the first 2MB area is not mapped by huge pages
-	 * There are typically fixed size MTRRs in there and overlapping
-	 * MTRRs into large pages causes slow downs.
-	 *
-	 * Right now we don't do that with gbpages because there seems
-	 * very little benefit for that case.
+	 * spectre_v2_user_select_mitigation() relies on the state set by
+	 * retbleed_select_mitigation(); specifically the STIBP selection is
+	 * forced for UNRET.
 	 */
-	if (!direct_gbpages)
-		set_memory_4k((unsigned long)__va(0), 1);
-#endif
+	spectre_v2_user_select_mitigation();
+	ssb_select_mitigation();
+	l1tf_select_mitigation();
+	md_clear_select_mitigation();
+	srbds_select_mitigation();
+	gds_select_mitigation();
+	vmscape_select_mitigation();
 }
 
+/*
+ * NOTE: For VMX, this function is not called in the vmexit path.
+ * It uses vmx_spec_ctrl_restore_host() instead.
+ */
 void
 x86_virt_spec_ctrl(u64 guest_spec_ctrl, u64 guest_virt_spec_ctrl, bool setguest)
 {
-	u64 msrval, guestval, hostval = x86_spec_ctrl_base;
+	u64 msrval, guestval = guest_spec_ctrl, hostval = spec_ctrl_current();
 	struct thread_info *ti = current_thread_info();
 
-	/* Is MSR_SPEC_CTRL implemented ? */
 	if (static_cpu_has(X86_FEATURE_MSR_SPEC_CTRL)) {
-		/*
-		 * Restrict guest_spec_ctrl to supported values. Clear the
-		 * modifiable bits in the host base value and or the
-		 * modifiable bits from the guest value.
-		 */
-		guestval = hostval & ~x86_spec_ctrl_mask;
-		guestval |= guest_spec_ctrl & x86_spec_ctrl_mask;
-
-		/* SSBD controlled in MSR_SPEC_CTRL */
-		if (static_cpu_has(X86_FEATURE_SPEC_CTRL_SSBD) ||
-		    static_cpu_has(X86_FEATURE_AMD_SSBD))
-			hostval |= ssbd_tif_to_spec_ctrl(ti->flags);
-
-		/* Conditional STIBP enabled? */
-		if (static_branch_unlikely(&switch_to_cond_stibp))
-			hostval |= stibp_tif_to_spec_ctrl(ti->flags);
-
 		if (hostval != guestval) {
 			msrval = setguest ? guestval : hostval;
 			wrmsrl(MSR_IA32_SPEC_CTRL, msrval);
@@ -245,8 +256,6 @@
 		    (mds_nosmt || cpu_mitigations_auto_nosmt()))
 			cpu_smt_disable(false);
 	}
-
-	pr_info("%s\n", mds_strings[mds_mitigation]);
 }
 
 static int __init mds_cmdline(char *str)
@@ -286,8 +295,6 @@
 
 static void __init taa_select_mitigation(void)
 {
-	u64 ia32_cap;
-
 	if (!boot_cpu_has_bug(X86_BUG_TAA)) {
 		taa_mitigation = TAA_MITIGATION_OFF;
 		return;
@@ -296,7 +303,7 @@
 	/* TSX previously disabled by tsx=off */
 	if (!boot_cpu_has(X86_FEATURE_RTM)) {
 		taa_mitigation = TAA_MITIGATION_TSX_DISABLED;
-		goto out;
+		return;
 	}
 
 	if (cpu_mitigations_off()) {
@@ -304,9 +311,13 @@
 		return;
 	}
 
-	/* TAA mitigation is turned off on the cmdline (tsx_async_abort=off) */
-	if (taa_mitigation == TAA_MITIGATION_OFF)
-		goto out;
+	/*
+	 * TAA mitigation via VERW is turned off if both
+	 * tsx_async_abort=off and mds=off are specified.
+	 */
+	if (taa_mitigation == TAA_MITIGATION_OFF &&
+	    mds_mitigation == MDS_MITIGATION_OFF)
+		return;
 
 	if (boot_cpu_has(X86_FEATURE_MD_CLEAR))
 		taa_mitigation = TAA_MITIGATION_VERW;
@@ -322,9 +333,8 @@
 	 * On MDS_NO=1 CPUs if ARCH_CAP_TSX_CTRL_MSR is not set, microcode
 	 * update is required.
 	 */
-	ia32_cap = x86_read_arch_cap_msr();
-	if ( (ia32_cap & ARCH_CAP_MDS_NO) &&
-	    !(ia32_cap & ARCH_CAP_TSX_CTRL_MSR))
+	if ( (x86_arch_cap_msr & ARCH_CAP_MDS_NO) &&
+	    !(x86_arch_cap_msr & ARCH_CAP_TSX_CTRL_MSR))
 		taa_mitigation = TAA_MITIGATION_UCODE_NEEDED;
 
 	/*
@@ -338,9 +348,6 @@
 
 	if (taa_nosmt || cpu_mitigations_auto_nosmt())
 		cpu_smt_disable(false);
-
-out:
-	pr_info("%s\n", taa_strings[taa_mitigation]);
 }
 
 static int __init tsx_async_abort_parse_cmdline(char *str)
@@ -365,6 +372,383 @@
 early_param("tsx_async_abort", tsx_async_abort_parse_cmdline);
 
 #undef pr_fmt
+#define pr_fmt(fmt)	"MMIO Stale Data: " fmt
+
+enum mmio_mitigations {
+	MMIO_MITIGATION_OFF,
+	MMIO_MITIGATION_UCODE_NEEDED,
+	MMIO_MITIGATION_VERW,
+};
+
+/* Default mitigation for Processor MMIO Stale Data vulnerabilities */
+static enum mmio_mitigations mmio_mitigation __ro_after_init = MMIO_MITIGATION_VERW;
+static bool mmio_nosmt __ro_after_init = false;
+
+static const char * const mmio_strings[] = {
+	[MMIO_MITIGATION_OFF]		= "Vulnerable",
+	[MMIO_MITIGATION_UCODE_NEEDED]	= "Vulnerable: Clear CPU buffers attempted, no microcode",
+	[MMIO_MITIGATION_VERW]		= "Mitigation: Clear CPU buffers",
+};
+
+static void __init mmio_select_mitigation(void)
+{
+	if (!boot_cpu_has_bug(X86_BUG_MMIO_STALE_DATA) ||
+	     boot_cpu_has_bug(X86_BUG_MMIO_UNKNOWN) ||
+	     cpu_mitigations_off()) {
+		mmio_mitigation = MMIO_MITIGATION_OFF;
+		return;
+	}
+
+	if (mmio_mitigation == MMIO_MITIGATION_OFF)
+		return;
+
+	/*
+	 * Enable CPU buffer clear mitigation for host and VMM, if also affected
+	 * by MDS or TAA. Otherwise, enable mitigation for VMM only.
+	 */
+	if (boot_cpu_has_bug(X86_BUG_MDS) || (boot_cpu_has_bug(X86_BUG_TAA) &&
+					      boot_cpu_has(X86_FEATURE_RTM)))
+		static_branch_enable(&mds_user_clear);
+	else
+		static_branch_enable(&mmio_stale_data_clear);
+
+	/*
+	 * If Processor-MMIO-Stale-Data bug is present and Fill Buffer data can
+	 * be propagated to uncore buffers, clearing the Fill buffers on idle
+	 * is required irrespective of SMT state.
+	 */
+	if (!(x86_arch_cap_msr & ARCH_CAP_FBSDP_NO))
+		static_branch_enable(&mds_idle_clear);
+
+	/*
+	 * Check if the system has the right microcode.
+	 *
+	 * CPU Fill buffer clear mitigation is enumerated by either an explicit
+	 * FB_CLEAR or by the presence of both MD_CLEAR and L1D_FLUSH on MDS
+	 * affected systems.
+	 */
+	if ((x86_arch_cap_msr & ARCH_CAP_FB_CLEAR) ||
+	    (boot_cpu_has(X86_FEATURE_MD_CLEAR) &&
+	     boot_cpu_has(X86_FEATURE_FLUSH_L1D) &&
+	     !(x86_arch_cap_msr & ARCH_CAP_MDS_NO)))
+		mmio_mitigation = MMIO_MITIGATION_VERW;
+	else
+		mmio_mitigation = MMIO_MITIGATION_UCODE_NEEDED;
+
+	if (mmio_nosmt || cpu_mitigations_auto_nosmt())
+		cpu_smt_disable(false);
+}
+
+static int __init mmio_stale_data_parse_cmdline(char *str)
+{
+	if (!boot_cpu_has_bug(X86_BUG_MMIO_STALE_DATA))
+		return 0;
+
+	if (!str)
+		return -EINVAL;
+
+	if (!strcmp(str, "off")) {
+		mmio_mitigation = MMIO_MITIGATION_OFF;
+	} else if (!strcmp(str, "full")) {
+		mmio_mitigation = MMIO_MITIGATION_VERW;
+	} else if (!strcmp(str, "full,nosmt")) {
+		mmio_mitigation = MMIO_MITIGATION_VERW;
+		mmio_nosmt = true;
+	}
+
+	return 0;
+}
+early_param("mmio_stale_data", mmio_stale_data_parse_cmdline);
+
+#undef pr_fmt
+#define pr_fmt(fmt)     "" fmt
+
+static void __init md_clear_update_mitigation(void)
+{
+	if (cpu_mitigations_off())
+		return;
+
+	if (!static_key_enabled(&mds_user_clear))
+		goto out;
+
+	/*
+	 * mds_user_clear is now enabled. Update MDS, TAA and MMIO Stale Data
+	 * mitigation, if necessary.
+	 */
+	if (mds_mitigation == MDS_MITIGATION_OFF &&
+	    boot_cpu_has_bug(X86_BUG_MDS)) {
+		mds_mitigation = MDS_MITIGATION_FULL;
+		mds_select_mitigation();
+	}
+	if (taa_mitigation == TAA_MITIGATION_OFF &&
+	    boot_cpu_has_bug(X86_BUG_TAA)) {
+		taa_mitigation = TAA_MITIGATION_VERW;
+		taa_select_mitigation();
+	}
+	if (mmio_mitigation == MMIO_MITIGATION_OFF &&
+	    boot_cpu_has_bug(X86_BUG_MMIO_STALE_DATA)) {
+		mmio_mitigation = MMIO_MITIGATION_VERW;
+		mmio_select_mitigation();
+	}
+out:
+	if (boot_cpu_has_bug(X86_BUG_MDS))
+		pr_info("MDS: %s\n", mds_strings[mds_mitigation]);
+	if (boot_cpu_has_bug(X86_BUG_TAA))
+		pr_info("TAA: %s\n", taa_strings[taa_mitigation]);
+	if (boot_cpu_has_bug(X86_BUG_MMIO_STALE_DATA))
+		pr_info("MMIO Stale Data: %s\n", mmio_strings[mmio_mitigation]);
+	else if (boot_cpu_has_bug(X86_BUG_MMIO_UNKNOWN))
+		pr_info("MMIO Stale Data: Unknown: No mitigations\n");
+}
+
+static void __init md_clear_select_mitigation(void)
+{
+	mds_select_mitigation();
+	taa_select_mitigation();
+	mmio_select_mitigation();
+
+	/*
+	 * As MDS, TAA and MMIO Stale Data mitigations are inter-related, update
+	 * and print their mitigation after MDS, TAA and MMIO Stale Data
+	 * mitigation selection is done.
+	 */
+	md_clear_update_mitigation();
+}
+
+#undef pr_fmt
+#define pr_fmt(fmt)	"SRBDS: " fmt
+
+enum srbds_mitigations {
+	SRBDS_MITIGATION_OFF,
+	SRBDS_MITIGATION_UCODE_NEEDED,
+	SRBDS_MITIGATION_FULL,
+	SRBDS_MITIGATION_TSX_OFF,
+	SRBDS_MITIGATION_HYPERVISOR,
+};
+
+static enum srbds_mitigations srbds_mitigation __ro_after_init = SRBDS_MITIGATION_FULL;
+
+static const char * const srbds_strings[] = {
+	[SRBDS_MITIGATION_OFF]		= "Vulnerable",
+	[SRBDS_MITIGATION_UCODE_NEEDED]	= "Vulnerable: No microcode",
+	[SRBDS_MITIGATION_FULL]		= "Mitigation: Microcode",
+	[SRBDS_MITIGATION_TSX_OFF]	= "Mitigation: TSX disabled",
+	[SRBDS_MITIGATION_HYPERVISOR]	= "Unknown: Dependent on hypervisor status",
+};
+
+static bool srbds_off;
+
+void update_srbds_msr(void)
+{
+	u64 mcu_ctrl;
+
+	if (!boot_cpu_has_bug(X86_BUG_SRBDS))
+		return;
+
+	if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
+		return;
+
+	if (!boot_cpu_has(X86_FEATURE_SRBDS_CTRL))
+		return;
+
+	rdmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_ctrl);
+
+	switch (srbds_mitigation) {
+	case SRBDS_MITIGATION_OFF:
+	case SRBDS_MITIGATION_TSX_OFF:
+		mcu_ctrl |= RNGDS_MITG_DIS;
+		break;
+	case SRBDS_MITIGATION_FULL:
+		mcu_ctrl &= ~RNGDS_MITG_DIS;
+		break;
+	default:
+		break;
+	}
+
+	wrmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_ctrl);
+}
+
+static void __init srbds_select_mitigation(void)
+{
+	if (!boot_cpu_has_bug(X86_BUG_SRBDS))
+		return;
+
+	/*
+	 * Check to see if this is one of the MDS_NO systems supporting TSX that
+	 * are only exposed to SRBDS when TSX is enabled or when CPU is affected
+	 * by Processor MMIO Stale Data vulnerability.
+	 */
+	if ((x86_arch_cap_msr & ARCH_CAP_MDS_NO) && !boot_cpu_has(X86_FEATURE_RTM) &&
+	    !boot_cpu_has_bug(X86_BUG_MMIO_STALE_DATA))
+		srbds_mitigation = SRBDS_MITIGATION_TSX_OFF;
+	else if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
+		srbds_mitigation = SRBDS_MITIGATION_HYPERVISOR;
+	else if (!boot_cpu_has(X86_FEATURE_SRBDS_CTRL))
+		srbds_mitigation = SRBDS_MITIGATION_UCODE_NEEDED;
+	else if (cpu_mitigations_off() || srbds_off)
+		srbds_mitigation = SRBDS_MITIGATION_OFF;
+
+	update_srbds_msr();
+	pr_info("%s\n", srbds_strings[srbds_mitigation]);
+}
+
+static int __init srbds_parse_cmdline(char *str)
+{
+	if (!str)
+		return -EINVAL;
+
+	if (!boot_cpu_has_bug(X86_BUG_SRBDS))
+		return 0;
+
+	srbds_off = !strcmp(str, "off");
+	return 0;
+}
+early_param("srbds", srbds_parse_cmdline);
+
+#undef pr_fmt
+#define pr_fmt(fmt)	"GDS: " fmt
+
+enum gds_mitigations {
+	GDS_MITIGATION_OFF,
+	GDS_MITIGATION_UCODE_NEEDED,
+	GDS_MITIGATION_FORCE,
+	GDS_MITIGATION_FULL,
+	GDS_MITIGATION_FULL_LOCKED,
+	GDS_MITIGATION_HYPERVISOR,
+};
+
+#if IS_ENABLED(CONFIG_GDS_FORCE_MITIGATION)
+static enum gds_mitigations gds_mitigation __ro_after_init = GDS_MITIGATION_FORCE;
+#else
+static enum gds_mitigations gds_mitigation __ro_after_init = GDS_MITIGATION_FULL;
+#endif
+
+static const char * const gds_strings[] = {
+	[GDS_MITIGATION_OFF]		= "Vulnerable",
+	[GDS_MITIGATION_UCODE_NEEDED]	= "Vulnerable: No microcode",
+	[GDS_MITIGATION_FORCE]		= "Mitigation: AVX disabled, no microcode",
+	[GDS_MITIGATION_FULL]		= "Mitigation: Microcode",
+	[GDS_MITIGATION_FULL_LOCKED]	= "Mitigation: Microcode (locked)",
+	[GDS_MITIGATION_HYPERVISOR]	= "Unknown: Dependent on hypervisor status",
+};
+
+bool gds_ucode_mitigated(void)
+{
+	return (gds_mitigation == GDS_MITIGATION_FULL ||
+		gds_mitigation == GDS_MITIGATION_FULL_LOCKED);
+}
+EXPORT_SYMBOL_GPL(gds_ucode_mitigated);
+
+void update_gds_msr(void)
+{
+	u64 mcu_ctrl_after;
+	u64 mcu_ctrl;
+
+	switch (gds_mitigation) {
+	case GDS_MITIGATION_OFF:
+		rdmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_ctrl);
+		mcu_ctrl |= GDS_MITG_DIS;
+		break;
+	case GDS_MITIGATION_FULL_LOCKED:
+		/*
+		 * The LOCKED state comes from the boot CPU. APs might not have
+		 * the same state. Make sure the mitigation is enabled on all
+		 * CPUs.
+		 */
+	case GDS_MITIGATION_FULL:
+		rdmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_ctrl);
+		mcu_ctrl &= ~GDS_MITG_DIS;
+		break;
+	case GDS_MITIGATION_FORCE:
+	case GDS_MITIGATION_UCODE_NEEDED:
+	case GDS_MITIGATION_HYPERVISOR:
+		return;
+	};
+
+	wrmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_ctrl);
+
+	/*
+	 * Check to make sure that the WRMSR value was not ignored. Writes to
+	 * GDS_MITG_DIS will be ignored if this processor is locked but the boot
+	 * processor was not.
+	 */
+	rdmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_ctrl_after);
+	WARN_ON_ONCE(mcu_ctrl != mcu_ctrl_after);
+}
+
+static void __init gds_select_mitigation(void)
+{
+	u64 mcu_ctrl;
+
+	if (!boot_cpu_has_bug(X86_BUG_GDS))
+		return;
+
+	if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) {
+		gds_mitigation = GDS_MITIGATION_HYPERVISOR;
+		goto out;
+	}
+
+	if (cpu_mitigations_off())
+		gds_mitigation = GDS_MITIGATION_OFF;
+	/* Will verify below that mitigation _can_ be disabled */
+
+	/* No microcode */
+	if (!(x86_arch_cap_msr & ARCH_CAP_GDS_CTRL)) {
+		if (gds_mitigation == GDS_MITIGATION_FORCE) {
+			/*
+			 * This only needs to be done on the boot CPU so do it
+			 * here rather than in update_gds_msr()
+			 */
+			setup_clear_cpu_cap(X86_FEATURE_AVX);
+			pr_warn("Microcode update needed! Disabling AVX as mitigation.\n");
+		} else {
+			gds_mitigation = GDS_MITIGATION_UCODE_NEEDED;
+		}
+		goto out;
+	}
+
+	/* Microcode has mitigation, use it */
+	if (gds_mitigation == GDS_MITIGATION_FORCE)
+		gds_mitigation = GDS_MITIGATION_FULL;
+
+	rdmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_ctrl);
+	if (mcu_ctrl & GDS_MITG_LOCKED) {
+		if (gds_mitigation == GDS_MITIGATION_OFF)
+			pr_warn("Mitigation locked. Disable failed.\n");
+
+		/*
+		 * The mitigation is selected from the boot CPU. All other CPUs
+		 * _should_ have the same state. If the boot CPU isn't locked
+		 * but others are then update_gds_msr() will WARN() of the state
+		 * mismatch. If the boot CPU is locked update_gds_msr() will
+		 * ensure the other CPUs have the mitigation enabled.
+		 */
+		gds_mitigation = GDS_MITIGATION_FULL_LOCKED;
+	}
+
+	update_gds_msr();
+out:
+	pr_info("%s\n", gds_strings[gds_mitigation]);
+}
+
+static int __init gds_parse_cmdline(char *str)
+{
+	if (!str)
+		return -EINVAL;
+
+	if (!boot_cpu_has_bug(X86_BUG_GDS))
+		return 0;
+
+	if (!strcmp(str, "off"))
+		gds_mitigation = GDS_MITIGATION_OFF;
+	else if (!strcmp(str, "force"))
+		gds_mitigation = GDS_MITIGATION_FORCE;
+
+	return 0;
+}
+early_param("gather_data_sampling", gds_parse_cmdline);
+
+#undef pr_fmt
 #define pr_fmt(fmt)     "Spectre V1 : " fmt
 
 enum spectre_v1_mitigation {
@@ -456,13 +840,106 @@
 }
 early_param("nospectre_v1", nospectre_v1_cmdline);
 
-#undef pr_fmt
-#define pr_fmt(fmt)     "Spectre V2 : " fmt
-
 static enum spectre_v2_mitigation spectre_v2_enabled __ro_after_init =
 	SPECTRE_V2_NONE;
 
-static enum spectre_v2_user_mitigation spectre_v2_user __ro_after_init =
+#undef pr_fmt
+#define pr_fmt(fmt)     "RETBleed: " fmt
+
+enum retbleed_mitigation {
+	RETBLEED_MITIGATION_NONE,
+	RETBLEED_MITIGATION_IBRS,
+	RETBLEED_MITIGATION_EIBRS,
+};
+
+enum retbleed_mitigation_cmd {
+	RETBLEED_CMD_OFF,
+	RETBLEED_CMD_AUTO,
+};
+
+const char * const retbleed_strings[] = {
+	[RETBLEED_MITIGATION_NONE]	= "Vulnerable",
+	[RETBLEED_MITIGATION_IBRS]	= "Mitigation: IBRS",
+	[RETBLEED_MITIGATION_EIBRS]	= "Mitigation: Enhanced IBRS",
+};
+
+static enum retbleed_mitigation retbleed_mitigation __ro_after_init =
+	RETBLEED_MITIGATION_NONE;
+static enum retbleed_mitigation_cmd retbleed_cmd __ro_after_init =
+	RETBLEED_CMD_AUTO;
+
+static int __init retbleed_parse_cmdline(char *str)
+{
+	if (!str)
+		return -EINVAL;
+
+	if (!strcmp(str, "off"))
+		retbleed_cmd = RETBLEED_CMD_OFF;
+	else if (!strcmp(str, "auto"))
+		retbleed_cmd = RETBLEED_CMD_AUTO;
+	else
+		pr_err("Unknown retbleed option (%s). Defaulting to 'auto'\n", str);
+
+	return 0;
+}
+early_param("retbleed", retbleed_parse_cmdline);
+
+#define RETBLEED_UNTRAIN_MSG "WARNING: BTB untrained return thunk mitigation is only effective on AMD/Hygon!\n"
+#define RETBLEED_COMPILER_MSG "WARNING: kernel not compiled with RETPOLINE or -mfunction-return capable compiler!\n"
+#define RETBLEED_INTEL_MSG "WARNING: Spectre v2 mitigation leaves CPU vulnerable to RETBleed attacks, data leaks possible!\n"
+
+static void __init retbleed_select_mitigation(void)
+{
+	if (!boot_cpu_has_bug(X86_BUG_RETBLEED) || cpu_mitigations_off())
+		return;
+
+	switch (retbleed_cmd) {
+	case RETBLEED_CMD_OFF:
+		return;
+
+	case RETBLEED_CMD_AUTO:
+	default:
+		/*
+		 * The Intel mitigation (IBRS) was already selected in
+		 * spectre_v2_select_mitigation().
+		 */
+
+		break;
+	}
+
+	switch (retbleed_mitigation) {
+	default:
+		break;
+	}
+
+	/*
+	 * Let IBRS trump all on Intel without affecting the effects of the
+	 * retbleed= cmdline option.
+	 */
+	if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) {
+		switch (spectre_v2_enabled) {
+		case SPECTRE_V2_IBRS:
+			retbleed_mitigation = RETBLEED_MITIGATION_IBRS;
+			break;
+		case SPECTRE_V2_EIBRS:
+		case SPECTRE_V2_EIBRS_RETPOLINE:
+		case SPECTRE_V2_EIBRS_LFENCE:
+			retbleed_mitigation = RETBLEED_MITIGATION_EIBRS;
+			break;
+		default:
+			pr_err(RETBLEED_INTEL_MSG);
+		}
+	}
+
+	pr_info("%s\n", retbleed_strings[retbleed_mitigation]);
+}
+
+#undef pr_fmt
+#define pr_fmt(fmt)     "Spectre V2 : " fmt
+
+static enum spectre_v2_user_mitigation spectre_v2_user_stibp __ro_after_init =
+	SPECTRE_V2_USER_NONE;
+static enum spectre_v2_user_mitigation spectre_v2_user_ibpb __ro_after_init =
 	SPECTRE_V2_USER_NONE;
 
 #ifdef CONFIG_RETPOLINE
@@ -486,6 +963,33 @@
 static inline const char *spectre_v2_module_string(void) { return ""; }
 #endif
 
+#define SPECTRE_V2_LFENCE_MSG "WARNING: LFENCE mitigation is not recommended for this CPU, data leaks possible!\n"
+#define SPECTRE_V2_EIBRS_EBPF_MSG "WARNING: Unprivileged eBPF is enabled with eIBRS on, data leaks possible via Spectre v2 BHB attacks!\n"
+#define SPECTRE_V2_EIBRS_LFENCE_EBPF_SMT_MSG "WARNING: Unprivileged eBPF is enabled with eIBRS+LFENCE mitigation and SMT, data leaks possible via Spectre v2 BHB attacks!\n"
+#define SPECTRE_V2_IBRS_PERF_MSG "WARNING: IBRS mitigation selected on Enhanced IBRS CPU, this may cause unnecessary performance loss\n"
+
+#ifdef CONFIG_BPF_SYSCALL
+void unpriv_ebpf_notify(int new_state)
+{
+	if (new_state)
+		return;
+
+	/* Unprivileged eBPF is enabled */
+
+	switch (spectre_v2_enabled) {
+	case SPECTRE_V2_EIBRS:
+		pr_err(SPECTRE_V2_EIBRS_EBPF_MSG);
+		break;
+	case SPECTRE_V2_EIBRS_LFENCE:
+		if (sched_smt_active())
+			pr_err(SPECTRE_V2_EIBRS_LFENCE_EBPF_SMT_MSG);
+		break;
+	default:
+		break;
+	}
+}
+#endif
+
 static inline bool match_option(const char *arg, int arglen, const char *opt)
 {
 	int len = strlen(opt);
@@ -500,7 +1004,11 @@
 	SPECTRE_V2_CMD_FORCE,
 	SPECTRE_V2_CMD_RETPOLINE,
 	SPECTRE_V2_CMD_RETPOLINE_GENERIC,
-	SPECTRE_V2_CMD_RETPOLINE_AMD,
+	SPECTRE_V2_CMD_RETPOLINE_LFENCE,
+	SPECTRE_V2_CMD_EIBRS,
+	SPECTRE_V2_CMD_EIBRS_RETPOLINE,
+	SPECTRE_V2_CMD_EIBRS_LFENCE,
+	SPECTRE_V2_CMD_IBRS,
 };
 
 enum spectre_v2_user_cmd {
@@ -541,13 +1049,15 @@
 		pr_info("spectre_v2_user=%s forced on command line.\n", reason);
 }
 
+static __ro_after_init enum spectre_v2_mitigation_cmd spectre_v2_cmd;
+
 static enum spectre_v2_user_cmd __init
-spectre_v2_parse_user_cmdline(enum spectre_v2_mitigation_cmd v2_cmd)
+spectre_v2_parse_user_cmdline(void)
 {
 	char arg[20];
 	int ret, i;
 
-	switch (v2_cmd) {
+	switch (spectre_v2_cmd) {
 	case SPECTRE_V2_CMD_NONE:
 		return SPECTRE_V2_USER_CMD_NONE;
 	case SPECTRE_V2_CMD_FORCE:
@@ -573,8 +1083,20 @@
 	return SPECTRE_V2_USER_CMD_AUTO;
 }
 
+static inline bool spectre_v2_in_eibrs_mode(enum spectre_v2_mitigation mode)
+{
+	return mode == SPECTRE_V2_EIBRS ||
+	       mode == SPECTRE_V2_EIBRS_RETPOLINE ||
+	       mode == SPECTRE_V2_EIBRS_LFENCE;
+}
+
+static inline bool spectre_v2_in_ibrs_mode(enum spectre_v2_mitigation mode)
+{
+	return spectre_v2_in_eibrs_mode(mode) || mode == SPECTRE_V2_IBRS;
+}
+
 static void __init
-spectre_v2_user_select_mitigation(enum spectre_v2_mitigation_cmd v2_cmd)
+spectre_v2_user_select_mitigation(void)
 {
 	enum spectre_v2_user_mitigation mode = SPECTRE_V2_USER_NONE;
 	bool smt_possible = IS_ENABLED(CONFIG_SMP);
@@ -587,7 +1109,7 @@
 	    cpu_smt_control == CPU_SMT_NOT_SUPPORTED)
 		smt_possible = false;
 
-	cmd = spectre_v2_parse_user_cmdline(v2_cmd);
+	cmd = spectre_v2_parse_user_cmdline();
 	switch (cmd) {
 	case SPECTRE_V2_USER_CMD_NONE:
 		goto set_mode;
@@ -608,24 +1130,17 @@
 		break;
 	}
 
-	/*
-	 * At this point, an STIBP mode other than "off" has been set.
-	 * If STIBP support is not being forced, check if STIBP always-on
-	 * is preferred.
-	 */
-	if (mode != SPECTRE_V2_USER_STRICT &&
-	    boot_cpu_has(X86_FEATURE_AMD_STIBP_ALWAYS_ON))
-		mode = SPECTRE_V2_USER_STRICT_PREFERRED;
-
 	/* Initialize Indirect Branch Prediction Barrier */
 	if (boot_cpu_has(X86_FEATURE_IBPB)) {
 		setup_force_cpu_cap(X86_FEATURE_USE_IBPB);
 
+		spectre_v2_user_ibpb = mode;
 		switch (cmd) {
 		case SPECTRE_V2_USER_CMD_FORCE:
 		case SPECTRE_V2_USER_CMD_PRCTL_IBPB:
 		case SPECTRE_V2_USER_CMD_SECCOMP_IBPB:
 			static_branch_enable(&switch_mm_always_ibpb);
+			spectre_v2_user_ibpb = SPECTRE_V2_USER_STRICT;
 			break;
 		case SPECTRE_V2_USER_CMD_PRCTL:
 		case SPECTRE_V2_USER_CMD_AUTO:
@@ -641,28 +1156,47 @@
 			"always-on" : "conditional");
 	}
 
-	/* If enhanced IBRS is enabled no STIBP required */
-	if (spectre_v2_enabled == SPECTRE_V2_IBRS_ENHANCED)
+	/*
+	 * If no STIBP, Intel enhanced IBRS is enabled, or SMT impossible, STIBP
+	 * is not required.
+	 *
+	 * Intel's Enhanced IBRS also protects against cross-thread branch target
+	 * injection in user-mode as the IBRS bit remains always set which
+	 * implicitly enables cross-thread protections.  However, in legacy IBRS
+	 * mode, the IBRS bit is set only on kernel entry and cleared on return
+	 * to userspace.  AMD Automatic IBRS also does not protect userspace.
+	 * These modes therefore disable the implicit cross-thread protection,
+	 * so allow for STIBP to be selected in those cases.
+	 */
+	if (!boot_cpu_has(X86_FEATURE_STIBP) ||
+	    !smt_possible ||
+	    (spectre_v2_in_eibrs_mode(spectre_v2_enabled) &&
+	     !boot_cpu_has(X86_FEATURE_AUTOIBRS)))
 		return;
 
 	/*
-	 * If SMT is not possible or STIBP is not available clear the STIBP
-	 * mode.
+	 * At this point, an STIBP mode other than "off" has been set.
+	 * If STIBP support is not being forced, check if STIBP always-on
+	 * is preferred.
 	 */
-	if (!smt_possible || !boot_cpu_has(X86_FEATURE_STIBP))
-		mode = SPECTRE_V2_USER_NONE;
+	if (mode != SPECTRE_V2_USER_STRICT &&
+	    boot_cpu_has(X86_FEATURE_AMD_STIBP_ALWAYS_ON))
+		mode = SPECTRE_V2_USER_STRICT_PREFERRED;
+
+	spectre_v2_user_stibp = mode;
+
 set_mode:
-	spectre_v2_user = mode;
-	/* Only print the STIBP mode when SMT possible */
-	if (smt_possible)
-		pr_info("%s\n", spectre_v2_user_strings[mode]);
+	pr_info("%s\n", spectre_v2_user_strings[mode]);
 }
 
 static const char * const spectre_v2_strings[] = {
 	[SPECTRE_V2_NONE]			= "Vulnerable",
-	[SPECTRE_V2_RETPOLINE_GENERIC]		= "Mitigation: Full generic retpoline",
-	[SPECTRE_V2_RETPOLINE_AMD]		= "Mitigation: Full AMD retpoline",
-	[SPECTRE_V2_IBRS_ENHANCED]		= "Mitigation: Enhanced IBRS",
+	[SPECTRE_V2_RETPOLINE]			= "Mitigation: Retpolines",
+	[SPECTRE_V2_LFENCE]			= "Mitigation: LFENCE",
+	[SPECTRE_V2_EIBRS]			= "Mitigation: Enhanced / Automatic IBRS",
+	[SPECTRE_V2_EIBRS_LFENCE]		= "Mitigation: Enhanced / Automatic IBRS + LFENCE",
+	[SPECTRE_V2_EIBRS_RETPOLINE]		= "Mitigation: Enhanced / Automatic IBRS + Retpolines",
+	[SPECTRE_V2_IBRS]			= "Mitigation: IBRS",
 };
 
 static const struct {
@@ -673,9 +1207,14 @@
 	{ "off",		SPECTRE_V2_CMD_NONE,		  false },
 	{ "on",			SPECTRE_V2_CMD_FORCE,		  true  },
 	{ "retpoline",		SPECTRE_V2_CMD_RETPOLINE,	  false },
-	{ "retpoline,amd",	SPECTRE_V2_CMD_RETPOLINE_AMD,	  false },
+	{ "retpoline,amd",	SPECTRE_V2_CMD_RETPOLINE_LFENCE,  false },
+	{ "retpoline,lfence",	SPECTRE_V2_CMD_RETPOLINE_LFENCE,  false },
 	{ "retpoline,generic",	SPECTRE_V2_CMD_RETPOLINE_GENERIC, false },
+	{ "eibrs",		SPECTRE_V2_CMD_EIBRS,		  false },
+	{ "eibrs,lfence",	SPECTRE_V2_CMD_EIBRS_LFENCE,	  false },
+	{ "eibrs,retpoline",	SPECTRE_V2_CMD_EIBRS_RETPOLINE,	  false },
 	{ "auto",		SPECTRE_V2_CMD_AUTO,		  false },
+	{ "ibrs",		SPECTRE_V2_CMD_IBRS,              false },
 };
 
 static void __init spec_v2_print_cond(const char *reason, bool secure)
@@ -711,17 +1250,48 @@
 	}
 
 	if ((cmd == SPECTRE_V2_CMD_RETPOLINE ||
-	     cmd == SPECTRE_V2_CMD_RETPOLINE_AMD ||
-	     cmd == SPECTRE_V2_CMD_RETPOLINE_GENERIC) &&
+	     cmd == SPECTRE_V2_CMD_RETPOLINE_LFENCE ||
+	     cmd == SPECTRE_V2_CMD_RETPOLINE_GENERIC ||
+	     cmd == SPECTRE_V2_CMD_EIBRS_LFENCE ||
+	     cmd == SPECTRE_V2_CMD_EIBRS_RETPOLINE) &&
 	    !IS_ENABLED(CONFIG_RETPOLINE)) {
-		pr_err("%s selected but not compiled in. Switching to AUTO select\n", mitigation_options[i].option);
+		pr_err("%s selected but not compiled in. Switching to AUTO select\n",
+		       mitigation_options[i].option);
+		return SPECTRE_V2_CMD_AUTO;
+	}
+
+	if ((cmd == SPECTRE_V2_CMD_EIBRS ||
+	     cmd == SPECTRE_V2_CMD_EIBRS_LFENCE ||
+	     cmd == SPECTRE_V2_CMD_EIBRS_RETPOLINE) &&
+	    !boot_cpu_has(X86_FEATURE_IBRS_ENHANCED)) {
+		pr_err("%s selected but CPU doesn't have Enhanced or Automatic IBRS. Switching to AUTO select\n",
+		       mitigation_options[i].option);
 		return SPECTRE_V2_CMD_AUTO;
 	}
 
-	if (cmd == SPECTRE_V2_CMD_RETPOLINE_AMD &&
-	    boot_cpu_data.x86_vendor != X86_VENDOR_HYGON &&
-	    boot_cpu_data.x86_vendor != X86_VENDOR_AMD) {
-		pr_err("retpoline,amd selected but CPU is not AMD. Switching to AUTO select\n");
+	if ((cmd == SPECTRE_V2_CMD_RETPOLINE_LFENCE ||
+	     cmd == SPECTRE_V2_CMD_EIBRS_LFENCE) &&
+	    !boot_cpu_has(X86_FEATURE_LFENCE_RDTSC)) {
+		pr_err("%s selected, but CPU doesn't have a serializing LFENCE. Switching to AUTO select\n",
+		       mitigation_options[i].option);
+		return SPECTRE_V2_CMD_AUTO;
+	}
+
+	if (cmd == SPECTRE_V2_CMD_IBRS && boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) {
+		pr_err("%s selected but not Intel CPU. Switching to AUTO select\n",
+		       mitigation_options[i].option);
+		return SPECTRE_V2_CMD_AUTO;
+	}
+
+	if (cmd == SPECTRE_V2_CMD_IBRS && !boot_cpu_has(X86_FEATURE_IBRS)) {
+		pr_err("%s selected but CPU doesn't have IBRS. Switching to AUTO select\n",
+		       mitigation_options[i].option);
+		return SPECTRE_V2_CMD_AUTO;
+	}
+
+	if (cmd == SPECTRE_V2_CMD_IBRS && boot_cpu_has(X86_FEATURE_XENPV)) {
+		pr_err("%s selected but running as XenPV guest. Switching to AUTO select\n",
+		       mitigation_options[i].option);
 		return SPECTRE_V2_CMD_AUTO;
 	}
 
@@ -730,6 +1300,160 @@
 	return cmd;
 }
 
+static enum spectre_v2_mitigation __init spectre_v2_select_retpoline(void)
+{
+	if (!IS_ENABLED(CONFIG_RETPOLINE)) {
+		pr_err("Kernel not compiled with retpoline; no mitigation available!");
+		return SPECTRE_V2_NONE;
+	}
+
+	return SPECTRE_V2_RETPOLINE;
+}
+
+static bool __ro_after_init rrsba_disabled;
+
+/* Disable in-kernel use of non-RSB RET predictors */
+static void __init spec_ctrl_disable_kernel_rrsba(void)
+{
+	if (rrsba_disabled)
+		return;
+
+	if (!(x86_arch_cap_msr & ARCH_CAP_RRSBA)) {
+		rrsba_disabled = true;
+		return;
+	}
+
+	if (!boot_cpu_has(X86_FEATURE_RRSBA_CTRL))
+		return;
+
+	x86_spec_ctrl_base |= SPEC_CTRL_RRSBA_DIS_S;
+	update_spec_ctrl(x86_spec_ctrl_base);
+	rrsba_disabled = true;
+}
+
+static void __init spectre_v2_determine_rsb_fill_type_at_vmexit(enum spectre_v2_mitigation mode)
+{
+	/*
+	 * Similar to context switches, there are two types of RSB attacks
+	 * after VM exit:
+	 *
+	 * 1) RSB underflow
+	 *
+	 * 2) Poisoned RSB entry
+	 *
+	 * When retpoline is enabled, both are mitigated by filling/clearing
+	 * the RSB.
+	 *
+	 * When IBRS is enabled, while #1 would be mitigated by the IBRS branch
+	 * prediction isolation protections, RSB still needs to be cleared
+	 * because of #2.  Note that SMEP provides no protection here, unlike
+	 * user-space-poisoned RSB entries.
+	 *
+	 * eIBRS should protect against RSB poisoning, but if the EIBRS_PBRSB
+	 * bug is present then a LITE version of RSB protection is required,
+	 * just a single call needs to retire before a RET is executed.
+	 */
+	switch (mode) {
+	case SPECTRE_V2_NONE:
+		return;
+
+	case SPECTRE_V2_EIBRS_LFENCE:
+	case SPECTRE_V2_EIBRS:
+		if (boot_cpu_has_bug(X86_BUG_EIBRS_PBRSB)) {
+			setup_force_cpu_cap(X86_FEATURE_RSB_VMEXIT_LITE);
+			pr_info("Spectre v2 / PBRSB-eIBRS: Retire a single CALL on VMEXIT\n");
+		}
+		return;
+
+	case SPECTRE_V2_EIBRS_RETPOLINE:
+	case SPECTRE_V2_RETPOLINE:
+	case SPECTRE_V2_LFENCE:
+	case SPECTRE_V2_IBRS:
+		setup_force_cpu_cap(X86_FEATURE_RSB_VMEXIT);
+		pr_info("Spectre v2 / SpectreRSB : Filling RSB on VMEXIT\n");
+		return;
+	}
+
+	pr_warn_once("Unknown Spectre v2 mode, disabling RSB mitigation at VM exit");
+	dump_stack();
+}
+
+/*
+ * Set BHI_DIS_S to prevent indirect branches in kernel to be influenced by
+ * branch history in userspace. Not needed if BHI_NO is set.
+ */
+static bool __init spec_ctrl_bhi_dis(void)
+{
+	if (!boot_cpu_has(X86_FEATURE_BHI_CTRL))
+		return false;
+
+	x86_spec_ctrl_base |= SPEC_CTRL_BHI_DIS_S;
+	update_spec_ctrl(x86_spec_ctrl_base);
+	setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_HW);
+
+	return true;
+}
+
+enum bhi_mitigations {
+	BHI_MITIGATION_OFF,
+	BHI_MITIGATION_ON,
+	BHI_MITIGATION_AUTO,
+};
+
+static enum bhi_mitigations bhi_mitigation __ro_after_init =
+	IS_ENABLED(CONFIG_SPECTRE_BHI_ON)  ? BHI_MITIGATION_ON  :
+	IS_ENABLED(CONFIG_SPECTRE_BHI_OFF) ? BHI_MITIGATION_OFF :
+					     BHI_MITIGATION_AUTO;
+
+static int __init spectre_bhi_parse_cmdline(char *str)
+{
+	if (!str)
+		return -EINVAL;
+
+	if (!strcmp(str, "off"))
+		bhi_mitigation = BHI_MITIGATION_OFF;
+	else if (!strcmp(str, "on"))
+		bhi_mitigation = BHI_MITIGATION_ON;
+	else if (!strcmp(str, "auto"))
+		bhi_mitigation = BHI_MITIGATION_AUTO;
+	else
+		pr_err("Ignoring unknown spectre_bhi option (%s)", str);
+
+	return 0;
+}
+early_param("spectre_bhi", spectre_bhi_parse_cmdline);
+
+static void __init bhi_select_mitigation(void)
+{
+	if (bhi_mitigation == BHI_MITIGATION_OFF)
+		return;
+
+	/* Retpoline mitigates against BHI unless the CPU has RRSBA behavior */
+	if (boot_cpu_has(X86_FEATURE_RETPOLINE) &&
+	    !boot_cpu_has(X86_FEATURE_RETPOLINE_LFENCE)) {
+		spec_ctrl_disable_kernel_rrsba();
+		if (rrsba_disabled)
+			return;
+	}
+
+	if (spec_ctrl_bhi_dis())
+		return;
+
+	if (!IS_ENABLED(CONFIG_X86_64))
+		return;
+
+	/* Mitigate KVM by default */
+	setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT);
+	pr_info("Spectre BHI mitigation: SW BHB clearing on vm exit\n");
+
+	if (bhi_mitigation == BHI_MITIGATION_AUTO)
+		return;
+
+	/* Mitigate syscalls when the mitigation is forced =on */
+	setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_LOOP);
+	pr_info("Spectre BHI mitigation: SW BHB clearing on syscall\n");
+}
+
 static void __init spectre_v2_select_mitigation(void)
 {
 	enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline();
@@ -750,86 +1474,168 @@
 	case SPECTRE_V2_CMD_FORCE:
 	case SPECTRE_V2_CMD_AUTO:
 		if (boot_cpu_has(X86_FEATURE_IBRS_ENHANCED)) {
-			mode = SPECTRE_V2_IBRS_ENHANCED;
-			/* Force it so VMEXIT will restore correctly */
-			x86_spec_ctrl_base |= SPEC_CTRL_IBRS;
-			wrmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base);
-			goto specv2_set_mode;
+			mode = SPECTRE_V2_EIBRS;
+			break;
+		}
+
+		if (boot_cpu_has_bug(X86_BUG_RETBLEED) &&
+		    retbleed_cmd != RETBLEED_CMD_OFF &&
+		    boot_cpu_has(X86_FEATURE_IBRS) &&
+		    boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) {
+			mode = SPECTRE_V2_IBRS;
+			break;
 		}
-		if (IS_ENABLED(CONFIG_RETPOLINE))
-			goto retpoline_auto;
+
+		mode = spectre_v2_select_retpoline();
 		break;
-	case SPECTRE_V2_CMD_RETPOLINE_AMD:
-		if (IS_ENABLED(CONFIG_RETPOLINE))
-			goto retpoline_amd;
+
+	case SPECTRE_V2_CMD_RETPOLINE_LFENCE:
+		pr_err(SPECTRE_V2_LFENCE_MSG);
+		mode = SPECTRE_V2_LFENCE;
 		break;
+
 	case SPECTRE_V2_CMD_RETPOLINE_GENERIC:
-		if (IS_ENABLED(CONFIG_RETPOLINE))
-			goto retpoline_generic;
+		mode = SPECTRE_V2_RETPOLINE;
 		break;
+
 	case SPECTRE_V2_CMD_RETPOLINE:
-		if (IS_ENABLED(CONFIG_RETPOLINE))
-			goto retpoline_auto;
+		mode = spectre_v2_select_retpoline();
+		break;
+
+	case SPECTRE_V2_CMD_IBRS:
+		mode = SPECTRE_V2_IBRS;
+		break;
+
+	case SPECTRE_V2_CMD_EIBRS:
+		mode = SPECTRE_V2_EIBRS;
+		break;
+
+	case SPECTRE_V2_CMD_EIBRS_LFENCE:
+		mode = SPECTRE_V2_EIBRS_LFENCE;
+		break;
+
+	case SPECTRE_V2_CMD_EIBRS_RETPOLINE:
+		mode = SPECTRE_V2_EIBRS_RETPOLINE;
 		break;
 	}
-	pr_err("Spectre mitigation: kernel not compiled with retpoline; no mitigation available!");
-	return;
 
-retpoline_auto:
-	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD ||
-	    boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) {
-	retpoline_amd:
-		if (!boot_cpu_has(X86_FEATURE_LFENCE_RDTSC)) {
-			pr_err("Spectre mitigation: LFENCE not serializing, switching to generic retpoline\n");
-			goto retpoline_generic;
+	if (mode == SPECTRE_V2_EIBRS && unprivileged_ebpf_enabled())
+		pr_err(SPECTRE_V2_EIBRS_EBPF_MSG);
+
+	if (spectre_v2_in_ibrs_mode(mode)) {
+		if (boot_cpu_has(X86_FEATURE_AUTOIBRS)) {
+			msr_set_bit(MSR_EFER, _EFER_AUTOIBRS);
+		} else {
+			x86_spec_ctrl_base |= SPEC_CTRL_IBRS;
+			update_spec_ctrl(x86_spec_ctrl_base);
 		}
-		mode = SPECTRE_V2_RETPOLINE_AMD;
-		setup_force_cpu_cap(X86_FEATURE_RETPOLINE_AMD);
-		setup_force_cpu_cap(X86_FEATURE_RETPOLINE);
-	} else {
-	retpoline_generic:
-		mode = SPECTRE_V2_RETPOLINE_GENERIC;
+	}
+
+	switch (mode) {
+	case SPECTRE_V2_NONE:
+	case SPECTRE_V2_EIBRS:
+		break;
+
+	case SPECTRE_V2_IBRS:
+		setup_force_cpu_cap(X86_FEATURE_KERNEL_IBRS);
+		if (boot_cpu_has(X86_FEATURE_IBRS_ENHANCED))
+			pr_warn(SPECTRE_V2_IBRS_PERF_MSG);
+		break;
+
+	case SPECTRE_V2_LFENCE:
+	case SPECTRE_V2_EIBRS_LFENCE:
+		setup_force_cpu_cap(X86_FEATURE_RETPOLINE_LFENCE);
+		fallthrough;
+
+	case SPECTRE_V2_RETPOLINE:
+	case SPECTRE_V2_EIBRS_RETPOLINE:
 		setup_force_cpu_cap(X86_FEATURE_RETPOLINE);
+		break;
 	}
 
-specv2_set_mode:
+	/*
+	 * Disable alternate RSB predictions in kernel when indirect CALLs and
+	 * JMPs gets protection against BHI and Intramode-BTI, but RET
+	 * prediction from a non-RSB predictor is still a risk.
+	 */
+	if (mode == SPECTRE_V2_EIBRS_LFENCE ||
+	    mode == SPECTRE_V2_EIBRS_RETPOLINE ||
+	    mode == SPECTRE_V2_RETPOLINE)
+		spec_ctrl_disable_kernel_rrsba();
+
+	if (boot_cpu_has(X86_BUG_BHI))
+		bhi_select_mitigation();
+
 	spectre_v2_enabled = mode;
 	pr_info("%s\n", spectre_v2_strings[mode]);
 
 	/*
-	 * If spectre v2 protection has been enabled, unconditionally fill
-	 * RSB during a context switch; this protects against two independent
-	 * issues:
+	 * If Spectre v2 protection has been enabled, fill the RSB during a
+	 * context switch.  In general there are two types of RSB attacks
+	 * across context switches, for which the CALLs/RETs may be unbalanced.
+	 *
+	 * 1) RSB underflow
+	 *
+	 *    Some Intel parts have "bottomless RSB".  When the RSB is empty,
+	 *    speculated return targets may come from the branch predictor,
+	 *    which could have a user-poisoned BTB or BHB entry.
+	 *
+	 *    AMD has it even worse: *all* returns are speculated from the BTB,
+	 *    regardless of the state of the RSB.
+	 *
+	 *    When IBRS or eIBRS is enabled, the "user -> kernel" attack
+	 *    scenario is mitigated by the IBRS branch prediction isolation
+	 *    properties, so the RSB buffer filling wouldn't be necessary to
+	 *    protect against this type of attack.
+	 *
+	 *    The "user -> user" attack scenario is mitigated by RSB filling.
+	 *
+	 * 2) Poisoned RSB entry
+	 *
+	 *    If the 'next' in-kernel return stack is shorter than 'prev',
+	 *    'next' could be tricked into speculating with a user-poisoned RSB
+	 *    entry.
+	 *
+	 *    The "user -> kernel" attack scenario is mitigated by SMEP and
+	 *    eIBRS.
+	 *
+	 *    The "user -> user" scenario, also known as SpectreBHB, requires
+	 *    RSB clearing.
 	 *
-	 *	- RSB underflow (and switch to BTB) on Skylake+
-	 *	- SpectreRSB variant of spectre v2 on X86_BUG_SPECTRE_V2 CPUs
+	 * So to mitigate all cases, unconditionally fill RSB on context
+	 * switches.
+	 *
+	 * FIXME: Is this pointless for retbleed-affected AMD?
 	 */
 	setup_force_cpu_cap(X86_FEATURE_RSB_CTXSW);
 	pr_info("Spectre v2 / SpectreRSB mitigation: Filling RSB on context switch\n");
 
+	spectre_v2_determine_rsb_fill_type_at_vmexit(mode);
+
 	/*
-	 * Retpoline means the kernel is safe because it has no indirect
-	 * branches. Enhanced IBRS protects firmware too, so, enable restricted
-	 * speculation around firmware calls only when Enhanced IBRS isn't
-	 * supported.
+	 * Retpoline protects the kernel, but doesn't protect firmware.  IBRS
+	 * and Enhanced IBRS protect firmware too, so enable IBRS around
+	 * firmware calls only when IBRS / Enhanced / Automatic IBRS aren't
+	 * otherwise enabled.
 	 *
 	 * Use "mode" to check Enhanced IBRS instead of boot_cpu_has(), because
 	 * the user might select retpoline on the kernel command line and if
 	 * the CPU supports Enhanced IBRS, kernel might un-intentionally not
 	 * enable IBRS around firmware calls.
 	 */
-	if (boot_cpu_has(X86_FEATURE_IBRS) && mode != SPECTRE_V2_IBRS_ENHANCED) {
+	if (boot_cpu_has(X86_FEATURE_IBRS) && !spectre_v2_in_ibrs_mode(mode)) {
 		setup_force_cpu_cap(X86_FEATURE_USE_IBRS_FW);
 		pr_info("Enabling Restricted Speculation for firmware calls\n");
 	}
 
 	/* Set up IBPB and STIBP depending on the general spectre V2 command */
-	spectre_v2_user_select_mitigation(cmd);
+	spectre_v2_cmd = cmd;
 }
 
 static void update_stibp_msr(void * __unused)
 {
-	wrmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base);
+	u64 val = spec_ctrl_current() | (x86_spec_ctrl_base & SPEC_CTRL_STIBP);
+	update_spec_ctrl(val);
 }
 
 /* Update x86_spec_ctrl_base in case SMT state changed. */
@@ -875,55 +1681,12 @@
 	if (!boot_cpu_has_bug(X86_BUG_MSBDS_ONLY))
 		return;
 
-	if (sched_smt_active())
+	if (sched_smt_active()) {
 		static_branch_enable(&mds_idle_clear);
-	else
+	} else if (mmio_mitigation == MMIO_MITIGATION_OFF ||
+		   (x86_arch_cap_msr & ARCH_CAP_FBSDP_NO)) {
 		static_branch_disable(&mds_idle_clear);
-}
-
-#define MDS_MSG_SMT "MDS CPU bug present and SMT on, data leak possible. See https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/mds.html for more details.\n"
-#define TAA_MSG_SMT "TAA CPU bug present and SMT on, data leak possible. See https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/tsx_async_abort.html for more details.\n"
-
-void cpu_bugs_smt_update(void)
-{
-	mutex_lock(&spec_ctrl_mutex);
-
-	switch (spectre_v2_user) {
-	case SPECTRE_V2_USER_NONE:
-		break;
-	case SPECTRE_V2_USER_STRICT:
-	case SPECTRE_V2_USER_STRICT_PREFERRED:
-		update_stibp_strict();
-		break;
-	case SPECTRE_V2_USER_PRCTL:
-	case SPECTRE_V2_USER_SECCOMP:
-		update_indir_branch_cond();
-		break;
-	}
-
-	switch (mds_mitigation) {
-	case MDS_MITIGATION_FULL:
-	case MDS_MITIGATION_VMWERV:
-		if (sched_smt_active() && !boot_cpu_has(X86_BUG_MSBDS_ONLY))
-			pr_warn_once(MDS_MSG_SMT);
-		update_mds_branch_idle();
-		break;
-	case MDS_MITIGATION_OFF:
-		break;
-	}
-
-	switch (taa_mitigation) {
-	case TAA_MITIGATION_VERW:
-	case TAA_MITIGATION_UCODE_NEEDED:
-		if (sched_smt_active())
-			pr_warn_once(TAA_MSG_SMT);
-		break;
-	case TAA_MITIGATION_TSX_DISABLED:
-	case TAA_MITIGATION_OFF:
-		break;
 	}
-
-	mutex_unlock(&spec_ctrl_mutex);
 }
 
 #undef pr_fmt
@@ -1027,16 +1790,6 @@
 	}
 
 	/*
-	 * If SSBD is controlled by the SPEC_CTRL MSR, then set the proper
-	 * bit in the mask to allow guests to use the mitigation even in the
-	 * case where the host does not enable it.
-	 */
-	if (static_cpu_has(X86_FEATURE_SPEC_CTRL_SSBD) ||
-	    static_cpu_has(X86_FEATURE_AMD_SSBD)) {
-		x86_spec_ctrl_mask |= SPEC_CTRL_SSBD;
-	}
-
-	/*
 	 * We have three CPU feature flags that are in play here:
 	 *  - X86_BUG_SPEC_STORE_BYPASS - CPU is susceptible.
 	 *  - X86_FEATURE_SSBD - CPU is able to turn off speculative store bypass
@@ -1053,7 +1806,7 @@
 			x86_amd_ssb_disable();
 		} else {
 			x86_spec_ctrl_base |= SPEC_CTRL_SSBD;
-			wrmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base);
+			update_spec_ctrl(x86_spec_ctrl_base);
 		}
 	}
 
@@ -1127,19 +1880,40 @@
 	return 0;
 }
 
+static bool is_spec_ib_user_controlled(void)
+{
+	return spectre_v2_user_ibpb == SPECTRE_V2_USER_PRCTL ||
+		spectre_v2_user_ibpb == SPECTRE_V2_USER_SECCOMP ||
+		spectre_v2_user_stibp == SPECTRE_V2_USER_PRCTL ||
+		spectre_v2_user_stibp == SPECTRE_V2_USER_SECCOMP;
+}
+
 static int ib_prctl_set(struct task_struct *task, unsigned long ctrl)
 {
 	switch (ctrl) {
 	case PR_SPEC_ENABLE:
-		if (spectre_v2_user == SPECTRE_V2_USER_NONE)
+		if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE &&
+		    spectre_v2_user_stibp == SPECTRE_V2_USER_NONE)
 			return 0;
 		/*
-		 * Indirect branch speculation is always disabled in strict
-		 * mode.
+		 * With strict mode for both IBPB and STIBP, the instruction
+		 * code paths avoid checking this task flag and instead,
+		 * unconditionally run the instruction. However, STIBP and IBPB
+		 * are independent and either can be set to conditionally
+		 * enabled regardless of the mode of the other.
+		 *
+		 * If either is set to conditional, allow the task flag to be
+		 * updated, unless it was force-disabled by a previous prctl
+		 * call. Currently, this is possible on an AMD CPU which has the
+		 * feature X86_FEATURE_AMD_STIBP_ALWAYS_ON. In this case, if the
+		 * kernel is booted with 'spectre_v2_user=seccomp', then
+		 * spectre_v2_user_ibpb == SPECTRE_V2_USER_SECCOMP and
+		 * spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED.
 		 */
-		if (spectre_v2_user == SPECTRE_V2_USER_STRICT ||
-		    spectre_v2_user == SPECTRE_V2_USER_STRICT_PREFERRED)
+		if (!is_spec_ib_user_controlled() ||
+		    task_spec_ib_force_disable(task))
 			return -EPERM;
+
 		task_clear_spec_ib_disable(task);
 		task_update_spec_tif(task);
 		break;
@@ -1149,15 +1923,19 @@
 		 * Indirect branch speculation is always allowed when
 		 * mitigation is force disabled.
 		 */
-		if (spectre_v2_user == SPECTRE_V2_USER_NONE)
+		if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE &&
+		    spectre_v2_user_stibp == SPECTRE_V2_USER_NONE)
 			return -EPERM;
-		if (spectre_v2_user == SPECTRE_V2_USER_STRICT ||
-		    spectre_v2_user == SPECTRE_V2_USER_STRICT_PREFERRED)
+
+		if (!is_spec_ib_user_controlled())
 			return 0;
+
 		task_set_spec_ib_disable(task);
 		if (ctrl == PR_SPEC_FORCE_DISABLE)
 			task_set_spec_ib_force_disable(task);
 		task_update_spec_tif(task);
+		if (task == current)
+			indirect_branch_prediction_barrier();
 		break;
 	default:
 		return -ERANGE;
@@ -1183,7 +1961,8 @@
 {
 	if (ssb_mode == SPEC_STORE_BYPASS_SECCOMP)
 		ssb_prctl_set(task, PR_SPEC_FORCE_DISABLE);
-	if (spectre_v2_user == SPECTRE_V2_USER_SECCOMP)
+	if (spectre_v2_user_ibpb == SPECTRE_V2_USER_SECCOMP ||
+	    spectre_v2_user_stibp == SPECTRE_V2_USER_SECCOMP)
 		ib_prctl_set(task, PR_SPEC_FORCE_DISABLE);
 }
 #endif
@@ -1214,22 +1993,21 @@
 	if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V2))
 		return PR_SPEC_NOT_AFFECTED;
 
-	switch (spectre_v2_user) {
-	case SPECTRE_V2_USER_NONE:
+	if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE &&
+	    spectre_v2_user_stibp == SPECTRE_V2_USER_NONE)
 		return PR_SPEC_ENABLE;
-	case SPECTRE_V2_USER_PRCTL:
-	case SPECTRE_V2_USER_SECCOMP:
+	else if (is_spec_ib_user_controlled()) {
 		if (task_spec_ib_force_disable(task))
 			return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE;
 		if (task_spec_ib_disable(task))
 			return PR_SPEC_PRCTL | PR_SPEC_DISABLE;
 		return PR_SPEC_PRCTL | PR_SPEC_ENABLE;
-	case SPECTRE_V2_USER_STRICT:
-	case SPECTRE_V2_USER_STRICT_PREFERRED:
+	} else if (spectre_v2_user_ibpb == SPECTRE_V2_USER_STRICT ||
+	    spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT ||
+	    spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED)
 		return PR_SPEC_DISABLE;
-	default:
+	else
 		return PR_SPEC_NOT_AFFECTED;
-	}
 }
 
 int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which)
@@ -1247,7 +2025,7 @@
 void x86_spec_ctrl_setup_ap(void)
 {
 	if (boot_cpu_has(X86_FEATURE_MSR_SPEC_CTRL))
-		wrmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base);
+		update_spec_ctrl(x86_spec_ctrl_base);
 
 	if (ssb_mode == SPEC_STORE_BYPASS_DISABLE)
 		x86_amd_ssb_disable();
@@ -1379,8 +2157,146 @@
 early_param("l1tf", l1tf_cmdline);
 
 #undef pr_fmt
+#define pr_fmt(fmt)	"VMSCAPE: " fmt
+
+enum vmscape_mitigations {
+	VMSCAPE_MITIGATION_NONE,
+	VMSCAPE_MITIGATION_AUTO,
+	VMSCAPE_MITIGATION_IBPB_EXIT_TO_USER,
+};
+
+static const char * const vmscape_strings[] = {
+	[VMSCAPE_MITIGATION_NONE]		= "Vulnerable",
+	/* [VMSCAPE_MITIGATION_AUTO] */
+	[VMSCAPE_MITIGATION_IBPB_EXIT_TO_USER]	= "Mitigation: IBPB before exit to userspace",
+};
+
+static enum vmscape_mitigations vmscape_mitigation __ro_after_init =
+	IS_ENABLED(CONFIG_MITIGATION_VMSCAPE) ? VMSCAPE_MITIGATION_AUTO : VMSCAPE_MITIGATION_NONE;
+
+static int __init vmscape_parse_cmdline(char *str)
+{
+	if (!str)
+		return -EINVAL;
+
+	if (!strcmp(str, "off")) {
+		vmscape_mitigation = VMSCAPE_MITIGATION_NONE;
+	} else if (!strcmp(str, "ibpb")) {
+		vmscape_mitigation = VMSCAPE_MITIGATION_IBPB_EXIT_TO_USER;
+	} else if (!strcmp(str, "force")) {
+		setup_force_cpu_bug(X86_BUG_VMSCAPE);
+		vmscape_mitigation = VMSCAPE_MITIGATION_AUTO;
+	} else {
+		pr_err("Ignoring unknown vmscape=%s option.\n", str);
+	}
+
+	return 0;
+}
+early_param("vmscape", vmscape_parse_cmdline);
+
+static void __init vmscape_select_mitigation(void)
+{
+	if (cpu_mitigations_off() ||
+	    !boot_cpu_has_bug(X86_BUG_VMSCAPE) ||
+	    !boot_cpu_has(X86_FEATURE_IBPB)) {
+		vmscape_mitigation = VMSCAPE_MITIGATION_NONE;
+		return;
+	}
+
+	if (vmscape_mitigation == VMSCAPE_MITIGATION_AUTO)
+		vmscape_mitigation = VMSCAPE_MITIGATION_IBPB_EXIT_TO_USER;
+
+	if (vmscape_mitigation == VMSCAPE_MITIGATION_IBPB_EXIT_TO_USER)
+		setup_force_cpu_cap(X86_FEATURE_IBPB_EXIT_TO_USER);
+
+	pr_info("%s\n", vmscape_strings[vmscape_mitigation]);
+}
+
+#undef pr_fmt
 #define pr_fmt(fmt) fmt
 
+#define MDS_MSG_SMT "MDS CPU bug present and SMT on, data leak possible. See https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/mds.html for more details.\n"
+#define TAA_MSG_SMT "TAA CPU bug present and SMT on, data leak possible. See https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/tsx_async_abort.html for more details.\n"
+#define MMIO_MSG_SMT "MMIO Stale Data CPU bug present and SMT on, data leak possible. See https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/processor_mmio_stale_data.html for more details.\n"
+#define VMSCAPE_MSG_SMT "VMSCAPE: SMT on, STIBP is required for full protection. See https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/vmscape.html for more details.\n"
+
+void cpu_bugs_smt_update(void)
+{
+	mutex_lock(&spec_ctrl_mutex);
+
+	if (sched_smt_active() && unprivileged_ebpf_enabled() &&
+	    spectre_v2_enabled == SPECTRE_V2_EIBRS_LFENCE)
+		pr_warn_once(SPECTRE_V2_EIBRS_LFENCE_EBPF_SMT_MSG);
+
+	switch (spectre_v2_user_stibp) {
+	case SPECTRE_V2_USER_NONE:
+		break;
+	case SPECTRE_V2_USER_STRICT:
+	case SPECTRE_V2_USER_STRICT_PREFERRED:
+		update_stibp_strict();
+		break;
+	case SPECTRE_V2_USER_PRCTL:
+	case SPECTRE_V2_USER_SECCOMP:
+		update_indir_branch_cond();
+		break;
+	}
+
+	switch (mds_mitigation) {
+	case MDS_MITIGATION_FULL:
+	case MDS_MITIGATION_VMWERV:
+		if (sched_smt_active() && !boot_cpu_has(X86_BUG_MSBDS_ONLY))
+			pr_warn_once(MDS_MSG_SMT);
+		update_mds_branch_idle();
+		break;
+	case MDS_MITIGATION_OFF:
+		break;
+	}
+
+	switch (taa_mitigation) {
+	case TAA_MITIGATION_VERW:
+	case TAA_MITIGATION_UCODE_NEEDED:
+		if (sched_smt_active())
+			pr_warn_once(TAA_MSG_SMT);
+		break;
+	case TAA_MITIGATION_TSX_DISABLED:
+	case TAA_MITIGATION_OFF:
+		break;
+	}
+
+	switch (mmio_mitigation) {
+	case MMIO_MITIGATION_VERW:
+	case MMIO_MITIGATION_UCODE_NEEDED:
+		if (sched_smt_active())
+			pr_warn_once(MMIO_MSG_SMT);
+		break;
+	case MMIO_MITIGATION_OFF:
+		break;
+	}
+
+	switch (vmscape_mitigation) {
+	case VMSCAPE_MITIGATION_NONE:
+	case VMSCAPE_MITIGATION_AUTO:
+		break;
+	case VMSCAPE_MITIGATION_IBPB_EXIT_TO_USER:
+		/*
+		 * Hypervisors can be attacked across-threads, warn for SMT when
+		 * STIBP is not already enabled system-wide.
+		 *
+		 * Intel eIBRS (!AUTOIBRS) implies STIBP on.
+		 */
+		if (!sched_smt_active() ||
+		    spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT ||
+		    spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED ||
+		    (spectre_v2_in_eibrs_mode(spectre_v2_enabled) &&
+		     !boot_cpu_has(X86_FEATURE_AUTOIBRS)))
+			break;
+		pr_warn_once(VMSCAPE_MSG_SMT);
+		break;
+	}
+
+	mutex_unlock(&spec_ctrl_mutex);
+}
+
 #ifdef CONFIG_SYSFS
 
 #define L1TF_DEFAULT_MSG "Mitigation: PTE Inversion"
@@ -1398,87 +2314,105 @@
 static ssize_t l1tf_show_state(char *buf)
 {
 	if (l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_AUTO)
-		return sprintf(buf, "%s\n", L1TF_DEFAULT_MSG);
+		return sysfs_emit(buf, "%s\n", L1TF_DEFAULT_MSG);
 
 	if (l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_EPT_DISABLED ||
 	    (l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_NEVER &&
 	     sched_smt_active())) {
-		return sprintf(buf, "%s; VMX: %s\n", L1TF_DEFAULT_MSG,
-			       l1tf_vmx_states[l1tf_vmx_mitigation]);
+		return sysfs_emit(buf, "%s; VMX: %s\n", L1TF_DEFAULT_MSG,
+				  l1tf_vmx_states[l1tf_vmx_mitigation]);
 	}
 
-	return sprintf(buf, "%s; VMX: %s, SMT %s\n", L1TF_DEFAULT_MSG,
-		       l1tf_vmx_states[l1tf_vmx_mitigation],
-		       sched_smt_active() ? "vulnerable" : "disabled");
+	return sysfs_emit(buf, "%s; VMX: %s, SMT %s\n", L1TF_DEFAULT_MSG,
+			  l1tf_vmx_states[l1tf_vmx_mitigation],
+			  sched_smt_active() ? "vulnerable" : "disabled");
 }
 
 static ssize_t itlb_multihit_show_state(char *buf)
 {
 	if (itlb_multihit_kvm_mitigation)
-		return sprintf(buf, "KVM: Mitigation: Split huge pages\n");
+		return sysfs_emit(buf, "KVM: Mitigation: Split huge pages\n");
 	else
-		return sprintf(buf, "KVM: Vulnerable\n");
+		return sysfs_emit(buf, "KVM: Vulnerable\n");
 }
 #else
 static ssize_t l1tf_show_state(char *buf)
 {
-	return sprintf(buf, "%s\n", L1TF_DEFAULT_MSG);
+	return sysfs_emit(buf, "%s\n", L1TF_DEFAULT_MSG);
 }
 
 static ssize_t itlb_multihit_show_state(char *buf)
 {
-	return sprintf(buf, "Processor vulnerable\n");
+	return sysfs_emit(buf, "Processor vulnerable\n");
 }
 #endif
 
 static ssize_t mds_show_state(char *buf)
 {
 	if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) {
-		return sprintf(buf, "%s; SMT Host state unknown\n",
-			       mds_strings[mds_mitigation]);
+		return sysfs_emit(buf, "%s; SMT Host state unknown\n",
+				  mds_strings[mds_mitigation]);
 	}
 
 	if (boot_cpu_has(X86_BUG_MSBDS_ONLY)) {
-		return sprintf(buf, "%s; SMT %s\n", mds_strings[mds_mitigation],
-			       (mds_mitigation == MDS_MITIGATION_OFF ? "vulnerable" :
-			        sched_smt_active() ? "mitigated" : "disabled"));
+		return sysfs_emit(buf, "%s; SMT %s\n", mds_strings[mds_mitigation],
+				  (mds_mitigation == MDS_MITIGATION_OFF ? "vulnerable" :
+				   sched_smt_active() ? "mitigated" : "disabled"));
 	}
 
-	return sprintf(buf, "%s; SMT %s\n", mds_strings[mds_mitigation],
-		       sched_smt_active() ? "vulnerable" : "disabled");
+	return sysfs_emit(buf, "%s; SMT %s\n", mds_strings[mds_mitigation],
+			  sched_smt_active() ? "vulnerable" : "disabled");
 }
 
 static ssize_t tsx_async_abort_show_state(char *buf)
 {
 	if ((taa_mitigation == TAA_MITIGATION_TSX_DISABLED) ||
 	    (taa_mitigation == TAA_MITIGATION_OFF))
-		return sprintf(buf, "%s\n", taa_strings[taa_mitigation]);
+		return sysfs_emit(buf, "%s\n", taa_strings[taa_mitigation]);
+
+	if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) {
+		return sysfs_emit(buf, "%s; SMT Host state unknown\n",
+				  taa_strings[taa_mitigation]);
+	}
+
+	return sysfs_emit(buf, "%s; SMT %s\n", taa_strings[taa_mitigation],
+			  sched_smt_active() ? "vulnerable" : "disabled");
+}
+
+static ssize_t mmio_stale_data_show_state(char *buf)
+{
+	if (boot_cpu_has_bug(X86_BUG_MMIO_UNKNOWN))
+		return sysfs_emit(buf, "Unknown: No mitigations\n");
+
+	if (mmio_mitigation == MMIO_MITIGATION_OFF)
+		return sysfs_emit(buf, "%s\n", mmio_strings[mmio_mitigation]);
 
 	if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) {
-		return sprintf(buf, "%s; SMT Host state unknown\n",
-			       taa_strings[taa_mitigation]);
+		return sysfs_emit(buf, "%s; SMT Host state unknown\n",
+				  mmio_strings[mmio_mitigation]);
 	}
 
-	return sprintf(buf, "%s; SMT %s\n", taa_strings[taa_mitigation],
-		       sched_smt_active() ? "vulnerable" : "disabled");
+	return sysfs_emit(buf, "%s; SMT %s\n", mmio_strings[mmio_mitigation],
+			  sched_smt_active() ? "vulnerable" : "disabled");
 }
 
 static char *stibp_state(void)
 {
-	if (spectre_v2_enabled == SPECTRE_V2_IBRS_ENHANCED)
+	if (spectre_v2_in_eibrs_mode(spectre_v2_enabled) &&
+	    !boot_cpu_has(X86_FEATURE_AUTOIBRS))
 		return "";
 
-	switch (spectre_v2_user) {
+	switch (spectre_v2_user_stibp) {
 	case SPECTRE_V2_USER_NONE:
-		return ", STIBP: disabled";
+		return "; STIBP: disabled";
 	case SPECTRE_V2_USER_STRICT:
-		return ", STIBP: forced";
+		return "; STIBP: forced";
 	case SPECTRE_V2_USER_STRICT_PREFERRED:
-		return ", STIBP: always-on";
+		return "; STIBP: always-on";
 	case SPECTRE_V2_USER_PRCTL:
 	case SPECTRE_V2_USER_SECCOMP:
 		if (static_key_enabled(&switch_to_cond_stibp))
-			return ", STIBP: conditional";
+			return "; STIBP: conditional";
 	}
 	return "";
 }
@@ -1487,43 +2421,113 @@
 {
 	if (boot_cpu_has(X86_FEATURE_IBPB)) {
 		if (static_key_enabled(&switch_mm_always_ibpb))
-			return ", IBPB: always-on";
+			return "; IBPB: always-on";
 		if (static_key_enabled(&switch_mm_cond_ibpb))
-			return ", IBPB: conditional";
-		return ", IBPB: disabled";
+			return "; IBPB: conditional";
+		return "; IBPB: disabled";
 	}
 	return "";
 }
 
+static char *pbrsb_eibrs_state(void)
+{
+	if (boot_cpu_has_bug(X86_BUG_EIBRS_PBRSB)) {
+		if (boot_cpu_has(X86_FEATURE_RSB_VMEXIT_LITE) ||
+		    boot_cpu_has(X86_FEATURE_RSB_VMEXIT))
+			return "; PBRSB-eIBRS: SW sequence";
+		else
+			return "; PBRSB-eIBRS: Vulnerable";
+	} else {
+		return "; PBRSB-eIBRS: Not affected";
+	}
+}
+
+static const char * const spectre_bhi_state(void)
+{
+	if (!boot_cpu_has_bug(X86_BUG_BHI))
+		return "; BHI: Not affected";
+	else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_HW))
+		return "; BHI: BHI_DIS_S";
+	else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP))
+		return "; BHI: SW loop, KVM: SW loop";
+	else if (boot_cpu_has(X86_FEATURE_RETPOLINE) &&
+		 !boot_cpu_has(X86_FEATURE_RETPOLINE_LFENCE) &&
+		 rrsba_disabled)
+		return "; BHI: Retpoline";
+	else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT))
+		return "; BHI: Vulnerable, KVM: SW loop";
+
+	return "; BHI: Vulnerable";
+}
+
+static ssize_t spectre_v2_show_state(char *buf)
+{
+	if (spectre_v2_enabled == SPECTRE_V2_LFENCE)
+		return sysfs_emit(buf, "Vulnerable: LFENCE\n");
+
+	if (spectre_v2_enabled == SPECTRE_V2_EIBRS && unprivileged_ebpf_enabled())
+		return sysfs_emit(buf, "Vulnerable: eIBRS with unprivileged eBPF\n");
+
+	if (sched_smt_active() && unprivileged_ebpf_enabled() &&
+	    spectre_v2_enabled == SPECTRE_V2_EIBRS_LFENCE)
+		return sysfs_emit(buf, "Vulnerable: eIBRS+LFENCE with unprivileged eBPF and SMT\n");
+
+	return sprintf(buf, "%s%s%s%s%s%s%s%s\n",
+			  spectre_v2_strings[spectre_v2_enabled],
+			  ibpb_state(),
+			  boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? "; IBRS_FW" : "",
+			  stibp_state(),
+			  boot_cpu_has(X86_FEATURE_RSB_CTXSW) ? "; RSB filling" : "",
+			  pbrsb_eibrs_state(),
+			  spectre_bhi_state(),
+			  /* this should always be at the end */
+			  spectre_v2_module_string());
+}
+
+static ssize_t srbds_show_state(char *buf)
+{
+	return sysfs_emit(buf, "%s\n", srbds_strings[srbds_mitigation]);
+}
+
+static ssize_t retbleed_show_state(char *buf)
+{
+	return sysfs_emit(buf, "%s\n", retbleed_strings[retbleed_mitigation]);
+}
+
+static ssize_t gds_show_state(char *buf)
+{
+	return sysfs_emit(buf, "%s\n", gds_strings[gds_mitigation]);
+}
+
+static ssize_t vmscape_show_state(char *buf)
+{
+	return sysfs_emit(buf, "%s\n", vmscape_strings[vmscape_mitigation]);
+}
+
 static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr,
 			       char *buf, unsigned int bug)
 {
 	if (!boot_cpu_has_bug(bug))
-		return sprintf(buf, "Not affected\n");
+		return sysfs_emit(buf, "Not affected\n");
 
 	switch (bug) {
 	case X86_BUG_CPU_MELTDOWN:
 		if (boot_cpu_has(X86_FEATURE_PTI))
-			return sprintf(buf, "Mitigation: PTI\n");
+			return sysfs_emit(buf, "Mitigation: PTI\n");
 
 		if (hypervisor_is_type(X86_HYPER_XEN_PV))
-			return sprintf(buf, "Unknown (XEN PV detected, hypervisor mitigation required)\n");
+			return sysfs_emit(buf, "Unknown (XEN PV detected, hypervisor mitigation required)\n");
 
 		break;
 
 	case X86_BUG_SPECTRE_V1:
-		return sprintf(buf, "%s\n", spectre_v1_strings[spectre_v1_mitigation]);
+		return sysfs_emit(buf, "%s\n", spectre_v1_strings[spectre_v1_mitigation]);
 
 	case X86_BUG_SPECTRE_V2:
-		return sprintf(buf, "%s%s%s%s%s%s\n", spectre_v2_strings[spectre_v2_enabled],
-			       ibpb_state(),
-			       boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? ", IBRS_FW" : "",
-			       stibp_state(),
-			       boot_cpu_has(X86_FEATURE_RSB_CTXSW) ? ", RSB filling" : "",
-			       spectre_v2_module_string());
+		return spectre_v2_show_state(buf);
 
 	case X86_BUG_SPEC_STORE_BYPASS:
-		return sprintf(buf, "%s\n", ssb_strings[ssb_mode]);
+		return sysfs_emit(buf, "%s\n", ssb_strings[ssb_mode]);
 
 	case X86_BUG_L1TF:
 		if (boot_cpu_has(X86_FEATURE_L1TF_PTEINV))
@@ -1539,11 +2543,27 @@
 	case X86_BUG_ITLB_MULTIHIT:
 		return itlb_multihit_show_state(buf);
 
+	case X86_BUG_SRBDS:
+		return srbds_show_state(buf);
+
+	case X86_BUG_MMIO_STALE_DATA:
+	case X86_BUG_MMIO_UNKNOWN:
+		return mmio_stale_data_show_state(buf);
+
+	case X86_BUG_RETBLEED:
+		return retbleed_show_state(buf);
+
+	case X86_BUG_GDS:
+		return gds_show_state(buf);
+
+	case X86_BUG_VMSCAPE:
+		return vmscape_show_state(buf);
+
 	default:
 		break;
 	}
 
-	return sprintf(buf, "Vulnerable\n");
+	return sysfs_emit(buf, "Vulnerable\n");
 }
 
 ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, char *buf)
@@ -1585,4 +2605,31 @@
 {
 	return cpu_show_common(dev, attr, buf, X86_BUG_ITLB_MULTIHIT);
 }
+
+ssize_t cpu_show_srbds(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	return cpu_show_common(dev, attr, buf, X86_BUG_SRBDS);
+}
+
+ssize_t cpu_show_mmio_stale_data(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	if (boot_cpu_has_bug(X86_BUG_MMIO_UNKNOWN))
+		return cpu_show_common(dev, attr, buf, X86_BUG_MMIO_UNKNOWN);
+	else
+		return cpu_show_common(dev, attr, buf, X86_BUG_MMIO_STALE_DATA);
+}
+
+ssize_t cpu_show_retbleed(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	return cpu_show_common(dev, attr, buf, X86_BUG_RETBLEED);
+}
+
+ssize_t cpu_show_gds(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	return cpu_show_common(dev, attr, buf, X86_BUG_GDS);
+}
+ssize_t cpu_show_vmscape(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	return cpu_show_common(dev, attr, buf, X86_BUG_VMSCAPE);
+}
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/cpu/cacheinfo.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/cpu/cacheinfo.c
@@ -646,7 +646,7 @@
 	return i;
 }
 
-void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, int cpu, u8 node_id)
+void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, int cpu)
 {
 	/*
 	 * We may have multiple LLCs if L3 caches exist, so check if we
@@ -657,7 +657,7 @@
 
 	if (c->x86 < 0x17) {
 		/* LLC is at the node level. */
-		per_cpu(cpu_llc_id, cpu) = node_id;
+		per_cpu(cpu_llc_id, cpu) = c->cpu_die_id;
 	} else if (c->x86 == 0x17 && c->x86_model <= 0x1F) {
 		/*
 		 * LLC is at the core complex level.
@@ -684,7 +684,7 @@
 	}
 }
 
-void cacheinfo_hygon_init_llc_id(struct cpuinfo_x86 *c, int cpu, u8 node_id)
+void cacheinfo_hygon_init_llc_id(struct cpuinfo_x86 *c, int cpu)
 {
 	/*
 	 * We may have multiple LLCs if L3 caches exist, so check if we
@@ -795,7 +795,7 @@
 			cpuid(2, &regs[0], &regs[1], &regs[2], &regs[3]);
 
 			/* If bit 31 is set, this is an unknown format */
-			for (j = 0 ; j < 3 ; j++)
+			for (j = 0 ; j < 4 ; j++)
 				if (regs[j] & (1 << 31))
 					regs[j] = 0;
 
@@ -985,7 +985,7 @@
 	this_leaf->priv = base->nb;
 }
 
-static int __init_cache_level(unsigned int cpu)
+int init_cache_level(unsigned int cpu)
 {
 	struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
 
@@ -1014,7 +1014,7 @@
 	id4_regs->id = c->apicid >> index_msb;
 }
 
-static int __populate_cache_leaves(unsigned int cpu)
+int populate_cache_leaves(unsigned int cpu)
 {
 	unsigned int idx, ret;
 	struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
@@ -1033,6 +1033,3 @@
 
 	return 0;
 }
-
-DEFINE_SMP_CALL_CACHE_FUNCTION(init_cache_level)
-DEFINE_SMP_CALL_CACHE_FUNCTION(populate_cache_leaves)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/cpu/common.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/cpu/common.c
@@ -17,10 +17,14 @@
 #include <linux/init.h>
 #include <linux/kprobes.h>
 #include <linux/kgdb.h>
+#include <linux/mem_encrypt.h>
 #include <linux/smp.h>
+#include <linux/cpu.h>
 #include <linux/io.h>
 #include <linux/syscore_ops.h>
+#include <linux/utsname.h>
 
+#include <asm/alternative.h>
 #include <asm/stackprotector.h>
 #include <asm/perf_event.h>
 #include <asm/mmu_context.h>
@@ -57,6 +61,7 @@
 #ifdef CONFIG_X86_LOCAL_APIC
 #include <asm/uv/uv.h>
 #endif
+#include <asm/set_memory.h>
 
 #include "cpu.h"
 
@@ -366,6 +371,9 @@
 	cr4_clear_bits(X86_CR4_UMIP);
 }
 
+/* These bits should not change their value after CPU init is finished. */
+static const unsigned long cr4_pinned_mask =
+	X86_CR4_SMEP | X86_CR4_SMAP | X86_CR4_UMIP | X86_CR4_FSGSBASE;
 static DEFINE_STATIC_KEY_FALSE_RO(cr_pinning);
 static unsigned long cr4_pinned_bits __ro_after_init;
 
@@ -374,7 +382,7 @@
 	unsigned long bits_missing = 0;
 
 set_register:
-	asm volatile("mov %0,%%cr0": "+r" (val), "+m" (__force_order));
+	asm volatile("mov %0,%%cr0": "+r" (val) : : "memory");
 
 	if (static_branch_likely(&cr_pinning)) {
 		if (unlikely((val & X86_CR0_WP) != X86_CR0_WP)) {
@@ -390,20 +398,20 @@
 
 void native_write_cr4(unsigned long val)
 {
-	unsigned long bits_missing = 0;
+	unsigned long bits_changed = 0;
 
 set_register:
-	asm volatile("mov %0,%%cr4": "+r" (val), "+m" (cr4_pinned_bits));
+	asm volatile("mov %0,%%cr4": "+r" (val) : : "memory");
 
 	if (static_branch_likely(&cr_pinning)) {
-		if (unlikely((val & cr4_pinned_bits) != cr4_pinned_bits)) {
-			bits_missing = ~val & cr4_pinned_bits;
-			val |= bits_missing;
+		if (unlikely((val & cr4_pinned_mask) != cr4_pinned_bits)) {
+			bits_changed = (val & cr4_pinned_mask) ^ cr4_pinned_bits;
+			val = (val & ~cr4_pinned_mask) | cr4_pinned_bits;
 			goto set_register;
 		}
-		/* Warn after we've set the missing bits. */
-		WARN_ONCE(bits_missing, "CR4 bits went missing: %lx!?\n",
-			  bits_missing);
+		/* Warn after we've corrected the changed bits. */
+		WARN_ONCE(bits_changed, "pinned CR4 bits changed: 0x%lx!?\n",
+			  bits_changed);
 	}
 }
 EXPORT_SYMBOL(native_write_cr4);
@@ -415,7 +423,7 @@
 	if (boot_cpu_has(X86_FEATURE_PCID))
 		cr4 |= X86_CR4_PCIDE;
 	if (static_branch_likely(&cr_pinning))
-		cr4 |= cr4_pinned_bits;
+		cr4 = (cr4 & ~cr4_pinned_mask) | cr4_pinned_bits;
 
 	__write_cr4(cr4);
 
@@ -430,10 +438,7 @@
  */
 static void __init setup_cr_pinning(void)
 {
-	unsigned long mask;
-
-	mask = (X86_CR4_SMEP | X86_CR4_SMAP | X86_CR4_UMIP);
-	cr4_pinned_bits = this_cpu_read(cpu_tlbstate.cr4) & mask;
+	cr4_pinned_bits = this_cpu_read(cpu_tlbstate.cr4) & cr4_pinned_mask;
 	static_key_enable(&cr_pinning.key);
 }
 
@@ -444,8 +449,6 @@
 
 static __always_inline void setup_pku(struct cpuinfo_x86 *c)
 {
-	struct pkru_state *pk;
-
 	/* check the boot processor, plus compile options for PKU: */
 	if (!cpu_feature_enabled(X86_FEATURE_PKU))
 		return;
@@ -456,15 +459,12 @@
 		return;
 
 	cr4_set_bits(X86_CR4_PKE);
-	pk = get_xsave_addr(&init_fpstate.xsave, XFEATURE_PKRU);
-	if (pk)
-		pk->pkru = init_pkru_value;
 	/*
 	 * Seting X86_CR4_PKE will cause the X86_FEATURE_OSPKE
 	 * cpuid bit to be set.  We need to ensure that we
 	 * update that bit in this CPU's "cpu_info".
 	 */
-	get_cpu_cap(c);
+	set_cpu_cap(c, X86_FEATURE_OSPKE);
 }
 
 #ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
@@ -961,6 +961,12 @@
 	if (c->extended_cpuid_level >= 0x8000000a)
 		c->x86_capability[CPUID_8000_000A_EDX] = cpuid_edx(0x8000000a);
 
+	if (c->extended_cpuid_level >= 0x8000001f)
+		c->x86_capability[CPUID_8000_001F_EAX] = cpuid_eax(0x8000001f);
+
+	if (c->extended_cpuid_level >= 0x80000021)
+		c->x86_capability[CPUID_8000_0021_EAX] = cpuid_eax(0x80000021);
+
 	init_scattered_cpuid_features(c);
 	init_speculation_control(c);
 	init_cqm(c);
@@ -1024,6 +1030,10 @@
 #define MSBDS_ONLY		BIT(5)
 #define NO_SWAPGS		BIT(6)
 #define NO_ITLB_MULTIHIT	BIT(7)
+#define NO_SPECTRE_V2		BIT(8)
+#define NO_EIBRS_PBRSB		BIT(9)
+#define NO_MMIO			BIT(10)
+#define NO_BHI			BIT(11)
 
 #define VULNWL(_vendor, _family, _model, _whitelist)	\
 	{ X86_VENDOR_##_vendor, _family, _model, X86_FEATURE_ANY, _whitelist }
@@ -1044,6 +1054,11 @@
 	VULNWL(NSC,	5, X86_MODEL_ANY,	NO_SPECULATION),
 
 	/* Intel Family 6 */
+	VULNWL_INTEL(TIGERLAKE,			NO_MMIO),
+	VULNWL_INTEL(TIGERLAKE_L,		NO_MMIO),
+	VULNWL_INTEL(ALDERLAKE,			NO_MMIO),
+	VULNWL_INTEL(ALDERLAKE_L,		NO_MMIO),
+
 	VULNWL_INTEL(ATOM_SALTWELL,		NO_SPECULATION | NO_ITLB_MULTIHIT),
 	VULNWL_INTEL(ATOM_SALTWELL_TABLET,	NO_SPECULATION | NO_ITLB_MULTIHIT),
 	VULNWL_INTEL(ATOM_SALTWELL_MID,		NO_SPECULATION | NO_ITLB_MULTIHIT),
@@ -1062,9 +1077,9 @@
 	VULNWL_INTEL(ATOM_AIRMONT_MID,		NO_L1TF | MSBDS_ONLY | NO_SWAPGS | NO_ITLB_MULTIHIT),
 	VULNWL_INTEL(ATOM_AIRMONT_NP,		NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT),
 
-	VULNWL_INTEL(ATOM_GOLDMONT,		NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT),
-	VULNWL_INTEL(ATOM_GOLDMONT_D,		NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT),
-	VULNWL_INTEL(ATOM_GOLDMONT_PLUS,	NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT),
+	VULNWL_INTEL(ATOM_GOLDMONT,		NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO),
+	VULNWL_INTEL(ATOM_GOLDMONT_D,		NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO),
+	VULNWL_INTEL(ATOM_GOLDMONT_PLUS,	NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_EIBRS_PBRSB),
 
 	/*
 	 * Technically, swapgs isn't serializing on AMD (despite it previously
@@ -1074,65 +1089,166 @@
 	 * good enough for our purposes.
 	 */
 
-	VULNWL_INTEL(ATOM_TREMONT_D,		NO_ITLB_MULTIHIT),
+	VULNWL_INTEL(ATOM_TREMONT,		NO_EIBRS_PBRSB),
+	VULNWL_INTEL(ATOM_TREMONT_L,		NO_EIBRS_PBRSB),
+	VULNWL_INTEL(ATOM_TREMONT_D,		NO_ITLB_MULTIHIT | NO_EIBRS_PBRSB),
 
 	/* AMD Family 0xf - 0x12 */
-	VULNWL_AMD(0x0f,	NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT),
-	VULNWL_AMD(0x10,	NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT),
-	VULNWL_AMD(0x11,	NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT),
-	VULNWL_AMD(0x12,	NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT),
+	VULNWL_AMD(0x0f,	NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_BHI),
+	VULNWL_AMD(0x10,	NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_BHI),
+	VULNWL_AMD(0x11,	NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_BHI),
+	VULNWL_AMD(0x12,	NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_BHI),
 
 	/* FAMILY_ANY must be last, otherwise 0x0f - 0x12 matches won't work */
-	VULNWL_AMD(X86_FAMILY_ANY,	NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT),
-	VULNWL_HYGON(X86_FAMILY_ANY,	NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT),
+	VULNWL_AMD(X86_FAMILY_ANY,	NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_BHI | NO_EIBRS_PBRSB),
+	VULNWL_HYGON(X86_FAMILY_ANY,	NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_BHI | NO_EIBRS_PBRSB),
+
+	/* Zhaoxin Family 7 */
+	VULNWL(CENTAUR,	7, X86_MODEL_ANY,	NO_SPECTRE_V2 | NO_MMIO | NO_BHI),
+	VULNWL(ZHAOXIN,	7, X86_MODEL_ANY,	NO_SPECTRE_V2 | NO_MMIO | NO_BHI),
+	{}
+};
+
+#define VULNBL(vendor, family, model, blacklist)	\
+	X86_MATCH_VENDOR_FAM_MODEL(vendor, family, model, blacklist)
+
+#define VULNBL_INTEL_STEPPINGS(model, steppings, issues)		   \
+	X86_MATCH_VENDOR_FAM_MODEL_STEPPINGS_FEATURE(INTEL, 6,		   \
+					    INTEL_FAM6_##model, steppings, \
+					    X86_FEATURE_ANY, issues)
+
+#define VULNBL_AMD(family, blacklist)		\
+	VULNBL(AMD, family, X86_MODEL_ANY, blacklist)
+
+#define VULNBL_HYGON(family, blacklist)		\
+	VULNBL(HYGON, family, X86_MODEL_ANY, blacklist)
+
+#define SRBDS		BIT(0)
+/* CPU is affected by X86_BUG_MMIO_STALE_DATA */
+#define MMIO		BIT(1)
+/* CPU is affected by Shared Buffers Data Sampling (SBDS), a variant of X86_BUG_MMIO_STALE_DATA */
+#define MMIO_SBDS	BIT(2)
+/* CPU is affected by RETbleed, speculating where you would not expect it */
+#define RETBLEED	BIT(3)
+/* CPU is affected by SMT (cross-thread) return predictions */
+#define SMT_RSB		BIT(4)
+/* CPU is affected by GDS */
+#define GDS		BIT(5)
+/* CPU is affected by VMSCAPE */
+#define VMSCAPE		BIT(11)
+
+static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = {
+	VULNBL_INTEL_STEPPINGS(SANDYBRIDGE_X,	X86_STEPPING_ANY,		VMSCAPE),
+	VULNBL_INTEL_STEPPINGS(SANDYBRIDGE,	X86_STEPPING_ANY,		VMSCAPE),
+	VULNBL_INTEL_STEPPINGS(IVYBRIDGE_X,	X86_STEPPING_ANY,		VMSCAPE),
+	VULNBL_INTEL_STEPPINGS(IVYBRIDGE,	X86_STEPPING_ANY,		SRBDS | VMSCAPE),
+	VULNBL_INTEL_STEPPINGS(HASWELL,		X86_STEPPING_ANY,		SRBDS | VMSCAPE),
+	VULNBL_INTEL_STEPPINGS(HASWELL_L,	X86_STEPPING_ANY,		SRBDS | VMSCAPE),
+	VULNBL_INTEL_STEPPINGS(HASWELL_G,	X86_STEPPING_ANY,		SRBDS | VMSCAPE),
+	VULNBL_INTEL_STEPPINGS(HASWELL_X,	X86_STEPPING_ANY,		MMIO | VMSCAPE),
+	VULNBL_INTEL_STEPPINGS(BROADWELL_D,	X86_STEPPING_ANY,		MMIO | VMSCAPE),
+	VULNBL_INTEL_STEPPINGS(BROADWELL_X,	X86_STEPPING_ANY,		MMIO | VMSCAPE),
+	VULNBL_INTEL_STEPPINGS(BROADWELL_G,	X86_STEPPING_ANY,		SRBDS | VMSCAPE),
+	VULNBL_INTEL_STEPPINGS(BROADWELL,	X86_STEPPING_ANY,		SRBDS | VMSCAPE),
+	VULNBL_INTEL_STEPPINGS(SKYLAKE_X,	X86_STEPPING_ANY,		MMIO | RETBLEED | GDS | VMSCAPE),
+	VULNBL_INTEL_STEPPINGS(SKYLAKE_L,	X86_STEPPING_ANY,		MMIO | RETBLEED | GDS | SRBDS | VMSCAPE),
+	VULNBL_INTEL_STEPPINGS(SKYLAKE,		X86_STEPPING_ANY,		MMIO | RETBLEED | GDS | SRBDS | VMSCAPE),
+	VULNBL_INTEL_STEPPINGS(KABYLAKE_L,	X86_STEPPING_ANY,		MMIO | RETBLEED | GDS | SRBDS | VMSCAPE),
+	VULNBL_INTEL_STEPPINGS(KABYLAKE,	X86_STEPPING_ANY,		MMIO | RETBLEED | GDS | SRBDS | VMSCAPE),
+	VULNBL_INTEL_STEPPINGS(CANNONLAKE_L,	X86_STEPPING_ANY,		RETBLEED | VMSCAPE),
+	VULNBL_INTEL_STEPPINGS(ICELAKE_L,	X86_STEPPING_ANY,		MMIO | MMIO_SBDS | RETBLEED | GDS),
+	VULNBL_INTEL_STEPPINGS(ICELAKE_D,	X86_STEPPING_ANY,		MMIO | GDS),
+	VULNBL_INTEL_STEPPINGS(ICELAKE_X,	X86_STEPPING_ANY,		MMIO | GDS),
+	VULNBL_INTEL_STEPPINGS(COMETLAKE,	X86_STEPPING_ANY,		MMIO | MMIO_SBDS | RETBLEED | GDS | VMSCAPE),
+	VULNBL_INTEL_STEPPINGS(COMETLAKE_L,	X86_STEPPINGS(0x0, 0x0),	MMIO | RETBLEED | VMSCAPE),
+	VULNBL_INTEL_STEPPINGS(COMETLAKE_L,	X86_STEPPING_ANY,		MMIO | MMIO_SBDS | RETBLEED | GDS | VMSCAPE),
+	VULNBL_INTEL_STEPPINGS(TIGERLAKE_L,	X86_STEPPING_ANY,		GDS),
+	VULNBL_INTEL_STEPPINGS(TIGERLAKE,	X86_STEPPING_ANY,		GDS),
+	VULNBL_INTEL_STEPPINGS(LAKEFIELD,	X86_STEPPING_ANY,		MMIO | MMIO_SBDS | RETBLEED),
+	VULNBL_INTEL_STEPPINGS(ROCKETLAKE,	X86_STEPPING_ANY,		MMIO | RETBLEED | GDS),
+	VULNBL_INTEL_STEPPINGS(ALDERLAKE,	X86_STEPPING_ANY,		VMSCAPE),
+	VULNBL_INTEL_STEPPINGS(ALDERLAKE_L,	X86_STEPPING_ANY,		VMSCAPE),
+	VULNBL_INTEL_STEPPINGS(ALDERLAKE_N,	X86_STEPPING_ANY,		VMSCAPE),
+	VULNBL_INTEL_STEPPINGS(RAPTORLAKE,	X86_STEPPING_ANY,		VMSCAPE),
+	VULNBL_INTEL_STEPPINGS(RAPTORLAKE_P,	X86_STEPPING_ANY,		VMSCAPE),
+	VULNBL_INTEL_STEPPINGS(RAPTORLAKE_S,	X86_STEPPING_ANY,		VMSCAPE),
+	VULNBL_INTEL_STEPPINGS(ATOM_TREMONT,	X86_STEPPING_ANY,		MMIO | MMIO_SBDS),
+	VULNBL_INTEL_STEPPINGS(ATOM_TREMONT_D,	X86_STEPPING_ANY,		MMIO),
+	VULNBL_INTEL_STEPPINGS(ATOM_TREMONT_L,	X86_STEPPING_ANY,		MMIO | MMIO_SBDS),
+
+	VULNBL_AMD(0x15, RETBLEED),
+	VULNBL_AMD(0x16, RETBLEED),
+	VULNBL_AMD(0x17, RETBLEED | SMT_RSB | VMSCAPE),
+	VULNBL_HYGON(0x18, RETBLEED | SMT_RSB | VMSCAPE),
+	VULNBL_AMD(0x19, VMSCAPE),
 	{}
 };
 
-static bool __init cpu_matches(unsigned long which)
+static bool __init cpu_matches(const struct x86_cpu_id *table, unsigned long which)
 {
-	const struct x86_cpu_id *m = x86_match_cpu(cpu_vuln_whitelist);
+	const struct x86_cpu_id *m = x86_match_cpu(table);
 
 	return m && !!(m->driver_data & which);
 }
 
 u64 x86_read_arch_cap_msr(void)
 {
-	u64 ia32_cap = 0;
+	u64 x86_arch_cap_msr = 0;
 
 	if (boot_cpu_has(X86_FEATURE_ARCH_CAPABILITIES))
-		rdmsrl(MSR_IA32_ARCH_CAPABILITIES, ia32_cap);
+		rdmsrl(MSR_IA32_ARCH_CAPABILITIES, x86_arch_cap_msr);
+
+	return x86_arch_cap_msr;
+}
 
-	return ia32_cap;
+static bool arch_cap_mmio_immune(u64 x86_arch_cap_msr)
+{
+	return (x86_arch_cap_msr & ARCH_CAP_FBSDP_NO &&
+		x86_arch_cap_msr & ARCH_CAP_PSDP_NO &&
+		x86_arch_cap_msr & ARCH_CAP_SBDR_SSDP_NO);
 }
 
 static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
 {
-	u64 ia32_cap = x86_read_arch_cap_msr();
+	u64 x86_arch_cap_msr = x86_read_arch_cap_msr();
 
 	/* Set ITLB_MULTIHIT bug if cpu is not in the whitelist and not mitigated */
-	if (!cpu_matches(NO_ITLB_MULTIHIT) && !(ia32_cap & ARCH_CAP_PSCHANGE_MC_NO))
+	if (!cpu_matches(cpu_vuln_whitelist, NO_ITLB_MULTIHIT) &&
+	    !(x86_arch_cap_msr & ARCH_CAP_PSCHANGE_MC_NO))
 		setup_force_cpu_bug(X86_BUG_ITLB_MULTIHIT);
 
-	if (cpu_matches(NO_SPECULATION))
+	if (cpu_matches(cpu_vuln_whitelist, NO_SPECULATION))
 		return;
 
 	setup_force_cpu_bug(X86_BUG_SPECTRE_V1);
-	setup_force_cpu_bug(X86_BUG_SPECTRE_V2);
 
-	if (!cpu_matches(NO_SSB) && !(ia32_cap & ARCH_CAP_SSB_NO) &&
+	if (!cpu_matches(cpu_vuln_whitelist, NO_SPECTRE_V2))
+		setup_force_cpu_bug(X86_BUG_SPECTRE_V2);
+
+	if (!cpu_matches(cpu_vuln_whitelist, NO_SSB) &&
+	    !(x86_arch_cap_msr & ARCH_CAP_SSB_NO) &&
 	   !cpu_has(c, X86_FEATURE_AMD_SSB_NO))
 		setup_force_cpu_bug(X86_BUG_SPEC_STORE_BYPASS);
 
-	if (ia32_cap & ARCH_CAP_IBRS_ALL)
+	/*
+	 * AMD's AutoIBRS is equivalent to Intel's eIBRS - use the Intel feature
+	 * flag and protect from vendor-specific bugs via the whitelist.
+	 */
+	if ((x86_arch_cap_msr & ARCH_CAP_IBRS_ALL) || cpu_has(c, X86_FEATURE_AUTOIBRS)) {
 		setup_force_cpu_cap(X86_FEATURE_IBRS_ENHANCED);
+		if (!cpu_matches(cpu_vuln_whitelist, NO_EIBRS_PBRSB) &&
+		    !(x86_arch_cap_msr & ARCH_CAP_PBRSB_NO))
+			setup_force_cpu_bug(X86_BUG_EIBRS_PBRSB);
+	}
 
-	if (!cpu_matches(NO_MDS) && !(ia32_cap & ARCH_CAP_MDS_NO)) {
+	if (!cpu_matches(cpu_vuln_whitelist, NO_MDS) &&
+	    !(x86_arch_cap_msr & ARCH_CAP_MDS_NO)) {
 		setup_force_cpu_bug(X86_BUG_MDS);
-		if (cpu_matches(MSBDS_ONLY))
+		if (cpu_matches(cpu_vuln_whitelist, MSBDS_ONLY))
 			setup_force_cpu_bug(X86_BUG_MSBDS_ONLY);
 	}
 
-	if (!cpu_matches(NO_SWAPGS))
+	if (!cpu_matches(cpu_vuln_whitelist, NO_SWAPGS))
 		setup_force_cpu_bug(X86_BUG_SWAPGS);
 
 	/*
@@ -1145,21 +1261,84 @@
 	 * TSX_CTRL check alone is not sufficient for cases when the microcode
 	 * update is not present or running as guest that don't get TSX_CTRL.
 	 */
-	if (!(ia32_cap & ARCH_CAP_TAA_NO) &&
+	if (!(x86_arch_cap_msr & ARCH_CAP_TAA_NO) &&
 	    (cpu_has(c, X86_FEATURE_RTM) ||
-	     (ia32_cap & ARCH_CAP_TSX_CTRL_MSR)))
+	     (x86_arch_cap_msr & ARCH_CAP_TSX_CTRL_MSR)))
 		setup_force_cpu_bug(X86_BUG_TAA);
 
-	if (cpu_matches(NO_MELTDOWN))
+	/*
+	 * SRBDS affects CPUs which support RDRAND or RDSEED and are listed
+	 * in the vulnerability blacklist.
+	 *
+	 * Some of the implications and mitigation of Shared Buffers Data
+	 * Sampling (SBDS) are similar to SRBDS. Give SBDS same treatment as
+	 * SRBDS.
+	 */
+	if ((cpu_has(c, X86_FEATURE_RDRAND) ||
+	     cpu_has(c, X86_FEATURE_RDSEED)) &&
+	    cpu_matches(cpu_vuln_blacklist, SRBDS | MMIO_SBDS))
+		    setup_force_cpu_bug(X86_BUG_SRBDS);
+
+	/*
+	 * Processor MMIO Stale Data bug enumeration
+	 *
+	 * Affected CPU list is generally enough to enumerate the vulnerability,
+	 * but for virtualization case check for ARCH_CAP MSR bits also, VMM may
+	 * not want the guest to enumerate the bug.
+	 *
+	 * Set X86_BUG_MMIO_UNKNOWN for CPUs that are neither in the blacklist,
+	 * nor in the whitelist and also don't enumerate MSR ARCH_CAP MMIO bits.
+	 */
+	if (!arch_cap_mmio_immune(x86_arch_cap_msr)) {
+		if (cpu_matches(cpu_vuln_blacklist, MMIO))
+			setup_force_cpu_bug(X86_BUG_MMIO_STALE_DATA);
+		else if (!cpu_matches(cpu_vuln_whitelist, NO_MMIO))
+			setup_force_cpu_bug(X86_BUG_MMIO_UNKNOWN);
+	}
+
+	if (!cpu_has(c, X86_FEATURE_BTC_NO)) {
+		if (cpu_matches(cpu_vuln_blacklist, RETBLEED) || (x86_arch_cap_msr & ARCH_CAP_RSBA))
+			setup_force_cpu_bug(X86_BUG_RETBLEED);
+	}
+
+	if (cpu_matches(cpu_vuln_blacklist, SMT_RSB))
+		setup_force_cpu_bug(X86_BUG_SMT_RSB);
+
+	/*
+	 * Check if CPU is vulnerable to GDS. If running in a virtual machine on
+	 * an affected processor, the VMM may have disabled the use of GATHER by
+	 * disabling AVX2. The only way to do this in HW is to clear XCR0[2],
+	 * which means that AVX will be disabled.
+	 */
+	if (cpu_matches(cpu_vuln_blacklist, GDS) && !(x86_arch_cap_msr & ARCH_CAP_GDS_NO) &&
+	    boot_cpu_has(X86_FEATURE_AVX))
+		setup_force_cpu_bug(X86_BUG_GDS);
+
+	/* When virtualized, eIBRS could be hidden, assume vulnerable */
+	if (!(x86_arch_cap_msr & ARCH_CAP_BHI_NO) &&
+	    !cpu_matches(cpu_vuln_whitelist, NO_BHI) &&
+	    (boot_cpu_has(X86_FEATURE_IBRS_ENHANCED) ||
+	     boot_cpu_has(X86_FEATURE_HYPERVISOR)))
+		setup_force_cpu_bug(X86_BUG_BHI);
+
+	/*
+	 * Set the bug only on bare-metal. A nested hypervisor should already be
+	 * deploying IBPB to isolate itself from nested guests.
+	 */
+	if (cpu_matches(cpu_vuln_blacklist, VMSCAPE) &&
+	    !boot_cpu_has(X86_FEATURE_HYPERVISOR))
+		setup_force_cpu_bug(X86_BUG_VMSCAPE);
+
+	if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN))
 		return;
 
 	/* Rogue Data Cache Load? No! */
-	if (ia32_cap & ARCH_CAP_RDCL_NO)
+	if (x86_arch_cap_msr & ARCH_CAP_RDCL_NO)
 		return;
 
 	setup_force_cpu_bug(X86_BUG_CPU_MELTDOWN);
 
-	if (cpu_matches(NO_L1TF))
+	if (cpu_matches(cpu_vuln_whitelist, NO_L1TF))
 		return;
 
 	setup_force_cpu_bug(X86_BUG_L1TF);
@@ -1235,8 +1414,6 @@
 
 	cpu_set_bug_bits(c);
 
-	fpu__init_system(c);
-
 #ifdef CONFIG_X86_32
 	/*
 	 * Regardless of whether PCID is enumerated, the SDM says
@@ -1296,9 +1473,8 @@
 	early_identify_cpu(&boot_cpu_data);
 }
 
-static void detect_null_seg_behavior(struct cpuinfo_x86 *c)
+static bool detect_null_seg_behavior(void)
 {
-#ifdef CONFIG_X86_64
 	/*
 	 * Empirically, writing zero to a segment selector on AMD does
 	 * not clear the base, whereas writing zero to a segment
@@ -1319,10 +1495,43 @@
 	wrmsrl(MSR_FS_BASE, 1);
 	loadsegment(fs, 0);
 	rdmsrl(MSR_FS_BASE, tmp);
-	if (tmp != 0)
-		set_cpu_bug(c, X86_BUG_NULL_SEG);
 	wrmsrl(MSR_FS_BASE, old_base);
-#endif
+	return tmp == 0;
+}
+
+void check_null_seg_clears_base(struct cpuinfo_x86 *c)
+{
+	/* BUG_NULL_SEG is only relevant with 64bit userspace */
+	if (!IS_ENABLED(CONFIG_X86_64))
+		return;
+
+	/* Zen3 CPUs advertise Null Selector Clears Base in CPUID. */
+	if (c->extended_cpuid_level >= 0x80000021 &&
+	    cpuid_eax(0x80000021) & BIT(6))
+		return;
+
+	/*
+	 * CPUID bit above wasn't set. If this kernel is still running
+	 * as a HV guest, then the HV has decided not to advertize
+	 * that CPUID bit for whatever reason.	For example, one
+	 * member of the migration pool might be vulnerable.  Which
+	 * means, the bug is present: set the BUG flag and return.
+	 */
+	if (cpu_has(c, X86_FEATURE_HYPERVISOR)) {
+		set_cpu_bug(c, X86_BUG_NULL_SEG);
+		return;
+	}
+
+	/*
+	 * Zen2 CPUs also have this behaviour, but no CPUID bit.
+	 * 0x18 is the respective family for Hygon.
+	 */
+	if ((c->x86 == 0x17 || c->x86 == 0x18) &&
+	    detect_null_seg_behavior())
+		return;
+
+	/* All the remaining ones are affected */
+	set_cpu_bug(c, X86_BUG_NULL_SEG);
 }
 
 static void generic_identify(struct cpuinfo_x86 *c)
@@ -1358,8 +1567,6 @@
 
 	get_model_name(c); /* Default name */
 
-	detect_null_seg_behavior(c);
-
 	/*
 	 * ESPFIX is a strange bug.  All real CPUs have it.  Paravirt
 	 * systems that run Linux at CPL > 0 may or may not have the
@@ -1597,6 +1804,9 @@
 	mtrr_ap_init();
 	validate_apic_and_package_id(c);
 	x86_spec_ctrl_setup_ap();
+	update_srbds_msr();
+	if (boot_cpu_has_bug(X86_BUG_GDS))
+		update_gds_msr();
 }
 
 static __init int setup_noclflush(char *arg)
@@ -1785,7 +1995,7 @@
 	unsigned long cpudata = vdso_encode_cpunode(cpu, early_cpu_to_node(cpu));
 	struct desc_struct d = { };
 
-	if (boot_cpu_has(X86_FEATURE_RDTSCP))
+	if (boot_cpu_has(X86_FEATURE_RDTSCP) || boot_cpu_has(X86_FEATURE_RDPID))
 		write_rdtscp_aux(cpudata);
 
 	/* Store CPU and node number in limit. */
@@ -1895,8 +2105,6 @@
 	clear_all_debug_regs();
 	dbg_restore_debug_regs();
 
-	fpu__init_cpu();
-
 	if (is_uv_system())
 		uv_cpu_init();
 
@@ -1954,8 +2162,6 @@
 	clear_all_debug_regs();
 	dbg_restore_debug_regs();
 
-	fpu__init_cpu();
-
 	load_fixmap_gdt(cpu);
 }
 #endif
@@ -1974,6 +2180,8 @@
 	/* Reload CPUID max function as it might've changed. */
 	info.cpuid_level = cpuid_eax(0);
 
+	amd_check_microcode();
+
 	/*
 	 * Copy all capability leafs to pick up the synthetic ones so that
 	 * memcmp() below doesn't fail on that. The ones coming from CPUID will
@@ -2000,3 +2208,69 @@
 	/* Check whether IPI broadcasting can be enabled */
 	apic_smt_update();
 }
+
+void __init arch_cpu_finalize_init(void)
+{
+	identify_boot_cpu();
+
+	/*
+	 * identify_boot_cpu() initialized SMT support information, let the
+	 * core code know.
+	 */
+	cpu_smt_check_topology();
+
+	if (!IS_ENABLED(CONFIG_SMP)) {
+		pr_info("CPU: ");
+		print_cpu_info(&boot_cpu_data);
+	}
+
+	cpu_select_mitigations();
+
+	arch_smt_update();
+
+	if (IS_ENABLED(CONFIG_X86_32)) {
+		/*
+		 * Check whether this is a real i386 which is not longer
+		 * supported and fixup the utsname.
+		 */
+		if (boot_cpu_data.x86 < 4)
+			panic("Kernel requires i486+ for 'invlpg' and other features");
+
+		init_utsname()->machine[1] =
+			'0' + (boot_cpu_data.x86 > 6 ? 6 : boot_cpu_data.x86);
+	}
+
+	/*
+	 * Must be before alternatives because it might set or clear
+	 * feature bits.
+	 */
+	fpu__init_system();
+	fpu__init_cpu();
+
+	alternative_instructions();
+
+	if (IS_ENABLED(CONFIG_X86_64)) {
+		/*
+		 * Make sure the first 2MB area is not mapped by huge pages
+		 * There are typically fixed size MTRRs in there and overlapping
+		 * MTRRs into large pages causes slow downs.
+		 *
+		 * Right now we don't do that with gbpages because there seems
+		 * very little benefit for that case.
+		 */
+		if (!direct_gbpages)
+			set_memory_4k((unsigned long)__va(0), 1);
+	} else {
+		fpu__init_check_bugs();
+	}
+
+	/*
+	 * This needs to be called before any devices perform DMA
+	 * operations that might use the SWIOTLB bounce buffers. It will
+	 * mark the bounce buffers as decrypted so that their usage will
+	 * not cause "plain-text" data to be decrypted when accessed. It
+	 * must be called after late_time_init() so that Hyper-V x86/x64
+	 * hypercalls work when the SWIOTLB bounce buffers are decrypted.
+	 */
+	mem_encrypt_init();
+}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/cpu/cpu.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/cpu/cpu.h
@@ -73,10 +73,14 @@
 extern int detect_extended_topology(struct cpuinfo_x86 *c);
 extern int detect_ht_early(struct cpuinfo_x86 *c);
 extern void detect_ht(struct cpuinfo_x86 *c);
+extern void check_null_seg_clears_base(struct cpuinfo_x86 *c);
 
 unsigned int aperfmperf_get_khz(int cpu);
+void cpu_select_mitigations(void);
 
 extern void x86_spec_ctrl_setup_ap(void);
+extern void update_srbds_msr(void);
+extern void update_gds_msr(void);
 
 extern u64 x86_read_arch_cap_msr(void);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/cpu/cpuid-deps.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/cpu/cpuid-deps.c
@@ -44,7 +44,10 @@
 	{ X86_FEATURE_F16C,			X86_FEATURE_XMM2,     },
 	{ X86_FEATURE_AES,			X86_FEATURE_XMM2      },
 	{ X86_FEATURE_SHA_NI,			X86_FEATURE_XMM2      },
+	{ X86_FEATURE_GFNI,			X86_FEATURE_XMM2      },
 	{ X86_FEATURE_FMA,			X86_FEATURE_AVX       },
+	{ X86_FEATURE_VAES,			X86_FEATURE_AVX       },
+	{ X86_FEATURE_VPCLMULQDQ,		X86_FEATURE_AVX       },
 	{ X86_FEATURE_AVX2,			X86_FEATURE_AVX,      },
 	{ X86_FEATURE_AVX512F,			X86_FEATURE_AVX,      },
 	{ X86_FEATURE_AVX512IFMA,		X86_FEATURE_AVX512F   },
@@ -56,9 +59,6 @@
 	{ X86_FEATURE_AVX512VL,			X86_FEATURE_AVX512F   },
 	{ X86_FEATURE_AVX512VBMI,		X86_FEATURE_AVX512F   },
 	{ X86_FEATURE_AVX512_VBMI2,		X86_FEATURE_AVX512VL  },
-	{ X86_FEATURE_GFNI,			X86_FEATURE_AVX512VL  },
-	{ X86_FEATURE_VAES,			X86_FEATURE_AVX512VL  },
-	{ X86_FEATURE_VPCLMULQDQ,		X86_FEATURE_AVX512VL  },
 	{ X86_FEATURE_AVX512_VNNI,		X86_FEATURE_AVX512VL  },
 	{ X86_FEATURE_AVX512_BITALG,		X86_FEATURE_AVX512VL  },
 	{ X86_FEATURE_AVX512_4VNNIW,		X86_FEATURE_AVX512F   },
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/cpu/cyrix.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/cpu/cyrix.c
@@ -152,8 +152,8 @@
 	u8 ccr3;
 	local_irq_save(flags);
 
-	/* Suspend on halt power saving and enable #SUSP pin */
-	setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x88);
+	/* Suspend on halt power saving */
+	setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x08);
 
 	ccr3 = getCx86(CX86_CCR3);
 	setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10);	/* enable MAPEN */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/cpu/hygon.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/cpu/hygon.c
@@ -64,7 +64,6 @@
  */
 static void hygon_get_topology(struct cpuinfo_x86 *c)
 {
-	u8 node_id;
 	int cpu = smp_processor_id();
 
 	/* get information required for multi-node processors */
@@ -74,7 +73,7 @@
 
 		cpuid(0x8000001e, &eax, &ebx, &ecx, &edx);
 
-		node_id  = ecx & 0xff;
+		c->cpu_die_id  = ecx & 0xff;
 
 		c->cpu_core_id = ebx & 0xff;
 
@@ -89,17 +88,21 @@
 		if (!err)
 			c->x86_coreid_bits = get_count_order(c->x86_max_cores);
 
-		/* Socket ID is ApicId[6] for these processors. */
-		c->phys_proc_id = c->apicid >> APICID_SOCKET_ID_BIT;
+		/*
+		 * Socket ID is ApicId[6] for the processors with model <= 0x3
+		 * when running on host.
+		 */
+		if (!boot_cpu_has(X86_FEATURE_HYPERVISOR) && c->x86_model <= 0x3)
+			c->phys_proc_id = c->apicid >> APICID_SOCKET_ID_BIT;
 
-		cacheinfo_hygon_init_llc_id(c, cpu, node_id);
+		cacheinfo_hygon_init_llc_id(c, cpu);
 	} else if (cpu_has(c, X86_FEATURE_NODEID_MSR)) {
 		u64 value;
 
 		rdmsrl(MSR_FAM10H_NODE_ID, value);
-		node_id = value & 7;
+		c->cpu_die_id = value & 7;
 
-		per_cpu(cpu_llc_id, cpu) = node_id;
+		per_cpu(cpu_llc_id, cpu) = c->cpu_die_id;
 	} else
 		return;
 
@@ -122,7 +125,7 @@
 	/* Convert the initial APIC ID into the socket ID */
 	c->phys_proc_id = c->initial_apicid >> bits;
 	/* use socket ID also for last level cache */
-	per_cpu(cpu_llc_id, cpu) = c->phys_proc_id;
+	per_cpu(cpu_llc_id, cpu) = c->cpu_die_id = c->phys_proc_id;
 }
 
 static void srat_detect_node(struct cpuinfo_x86 *c)
@@ -336,8 +339,8 @@
 		 * msr_set_bit() uses the safe accessors, too, even if the MSR
 		 * is not present.
 		 */
-		msr_set_bit(MSR_F10H_DECFG,
-			    MSR_F10H_DECFG_LFENCE_SERIALIZE_BIT);
+		msr_set_bit(MSR_AMD64_DE_CFG,
+			    MSR_AMD64_DE_CFG_LFENCE_SERIALIZE_BIT);
 
 		/* A serializing LFENCE stops RDTSC speculation */
 		set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC);
@@ -351,6 +354,8 @@
 	/* Hygon CPUs don't reset SS attributes on SYSRET, Xen does. */
 	if (!cpu_has(c, X86_FEATURE_XENPV))
 		set_cpu_bug(c, X86_BUG_SYSRET_SS_ATTRS);
+
+	check_null_seg_clears_base(c);
 }
 
 static void cpu_detect_tlb_hygon(struct cpuinfo_x86 *c)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/cpu/intel.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/cpu/intel.c
@@ -97,7 +97,7 @@
 static int __init ring3mwait_disable(char *__unused)
 {
 	ring3mwait_disabled = true;
-	return 0;
+	return 1;
 }
 __setup("ring3mwait=disable", ring3mwait_disable);
 
@@ -187,6 +187,90 @@
 	return false;
 }
 
+#define MSR_IA32_TME_ACTIVATE		0x982
+
+/* Helpers to access TME_ACTIVATE MSR */
+#define TME_ACTIVATE_LOCKED(x)		(x & 0x1)
+#define TME_ACTIVATE_ENABLED(x)		(x & 0x2)
+
+#define TME_ACTIVATE_POLICY(x)		((x >> 4) & 0xf)	/* Bits 7:4 */
+#define TME_ACTIVATE_POLICY_AES_XTS_128	0
+
+#define TME_ACTIVATE_KEYID_BITS(x)	((x >> 32) & 0xf)	/* Bits 35:32 */
+
+#define TME_ACTIVATE_CRYPTO_ALGS(x)	((x >> 48) & 0xffff)	/* Bits 63:48 */
+#define TME_ACTIVATE_CRYPTO_AES_XTS_128	1
+
+/* Values for mktme_status (SW only construct) */
+#define MKTME_ENABLED			0
+#define MKTME_DISABLED			1
+#define MKTME_UNINITIALIZED		2
+static int mktme_status = MKTME_UNINITIALIZED;
+
+static void detect_tme_early(struct cpuinfo_x86 *c)
+{
+	u64 tme_activate, tme_policy, tme_crypto_algs;
+	int keyid_bits = 0, nr_keyids = 0;
+	static u64 tme_activate_cpu0 = 0;
+
+	rdmsrl(MSR_IA32_TME_ACTIVATE, tme_activate);
+
+	if (mktme_status != MKTME_UNINITIALIZED) {
+		if (tme_activate != tme_activate_cpu0) {
+			/* Broken BIOS? */
+			pr_err_once("x86/tme: configuration is inconsistent between CPUs\n");
+			pr_err_once("x86/tme: MKTME is not usable\n");
+			mktme_status = MKTME_DISABLED;
+
+			/* Proceed. We may need to exclude bits from x86_phys_bits. */
+		}
+	} else {
+		tme_activate_cpu0 = tme_activate;
+	}
+
+	if (!TME_ACTIVATE_LOCKED(tme_activate) || !TME_ACTIVATE_ENABLED(tme_activate)) {
+		pr_info_once("x86/tme: not enabled by BIOS\n");
+		mktme_status = MKTME_DISABLED;
+		return;
+	}
+
+	if (mktme_status != MKTME_UNINITIALIZED)
+		goto detect_keyid_bits;
+
+	pr_info("x86/tme: enabled by BIOS\n");
+
+	tme_policy = TME_ACTIVATE_POLICY(tme_activate);
+	if (tme_policy != TME_ACTIVATE_POLICY_AES_XTS_128)
+		pr_warn("x86/tme: Unknown policy is active: %#llx\n", tme_policy);
+
+	tme_crypto_algs = TME_ACTIVATE_CRYPTO_ALGS(tme_activate);
+	if (!(tme_crypto_algs & TME_ACTIVATE_CRYPTO_AES_XTS_128)) {
+		pr_err("x86/mktme: No known encryption algorithm is supported: %#llx\n",
+				tme_crypto_algs);
+		mktme_status = MKTME_DISABLED;
+	}
+detect_keyid_bits:
+	keyid_bits = TME_ACTIVATE_KEYID_BITS(tme_activate);
+	nr_keyids = (1UL << keyid_bits) - 1;
+	if (nr_keyids) {
+		pr_info_once("x86/mktme: enabled by BIOS\n");
+		pr_info_once("x86/mktme: %d KeyIDs available\n", nr_keyids);
+	} else {
+		pr_info_once("x86/mktme: disabled by BIOS\n");
+	}
+
+	if (mktme_status == MKTME_UNINITIALIZED) {
+		/* MKTME is usable */
+		mktme_status = MKTME_ENABLED;
+	}
+
+	/*
+	 * KeyID bits effectively lower the number of physical address
+	 * bits.  Update cpuinfo_x86::x86_phys_bits accordingly.
+	 */
+	c->x86_phys_bits -= keyid_bits;
+}
+
 static void early_init_intel(struct cpuinfo_x86 *c)
 {
 	u64 misc_enable;
@@ -339,6 +423,13 @@
 	 */
 	if (detect_extended_topology_early(c) < 0)
 		detect_ht_early(c);
+
+	/*
+	 * Adjust the number of physical bits early because it affects the
+	 * valid bits of the MTRR mask registers.
+	 */
+	if (cpu_has(c, X86_FEATURE_TME))
+		detect_tme_early(c);
 }
 
 #ifdef CONFIG_X86_32
@@ -540,90 +631,6 @@
 	}
 }
 
-#define MSR_IA32_TME_ACTIVATE		0x982
-
-/* Helpers to access TME_ACTIVATE MSR */
-#define TME_ACTIVATE_LOCKED(x)		(x & 0x1)
-#define TME_ACTIVATE_ENABLED(x)		(x & 0x2)
-
-#define TME_ACTIVATE_POLICY(x)		((x >> 4) & 0xf)	/* Bits 7:4 */
-#define TME_ACTIVATE_POLICY_AES_XTS_128	0
-
-#define TME_ACTIVATE_KEYID_BITS(x)	((x >> 32) & 0xf)	/* Bits 35:32 */
-
-#define TME_ACTIVATE_CRYPTO_ALGS(x)	((x >> 48) & 0xffff)	/* Bits 63:48 */
-#define TME_ACTIVATE_CRYPTO_AES_XTS_128	1
-
-/* Values for mktme_status (SW only construct) */
-#define MKTME_ENABLED			0
-#define MKTME_DISABLED			1
-#define MKTME_UNINITIALIZED		2
-static int mktme_status = MKTME_UNINITIALIZED;
-
-static void detect_tme(struct cpuinfo_x86 *c)
-{
-	u64 tme_activate, tme_policy, tme_crypto_algs;
-	int keyid_bits = 0, nr_keyids = 0;
-	static u64 tme_activate_cpu0 = 0;
-
-	rdmsrl(MSR_IA32_TME_ACTIVATE, tme_activate);
-
-	if (mktme_status != MKTME_UNINITIALIZED) {
-		if (tme_activate != tme_activate_cpu0) {
-			/* Broken BIOS? */
-			pr_err_once("x86/tme: configuration is inconsistent between CPUs\n");
-			pr_err_once("x86/tme: MKTME is not usable\n");
-			mktme_status = MKTME_DISABLED;
-
-			/* Proceed. We may need to exclude bits from x86_phys_bits. */
-		}
-	} else {
-		tme_activate_cpu0 = tme_activate;
-	}
-
-	if (!TME_ACTIVATE_LOCKED(tme_activate) || !TME_ACTIVATE_ENABLED(tme_activate)) {
-		pr_info_once("x86/tme: not enabled by BIOS\n");
-		mktme_status = MKTME_DISABLED;
-		return;
-	}
-
-	if (mktme_status != MKTME_UNINITIALIZED)
-		goto detect_keyid_bits;
-
-	pr_info("x86/tme: enabled by BIOS\n");
-
-	tme_policy = TME_ACTIVATE_POLICY(tme_activate);
-	if (tme_policy != TME_ACTIVATE_POLICY_AES_XTS_128)
-		pr_warn("x86/tme: Unknown policy is active: %#llx\n", tme_policy);
-
-	tme_crypto_algs = TME_ACTIVATE_CRYPTO_ALGS(tme_activate);
-	if (!(tme_crypto_algs & TME_ACTIVATE_CRYPTO_AES_XTS_128)) {
-		pr_err("x86/mktme: No known encryption algorithm is supported: %#llx\n",
-				tme_crypto_algs);
-		mktme_status = MKTME_DISABLED;
-	}
-detect_keyid_bits:
-	keyid_bits = TME_ACTIVATE_KEYID_BITS(tme_activate);
-	nr_keyids = (1UL << keyid_bits) - 1;
-	if (nr_keyids) {
-		pr_info_once("x86/mktme: enabled by BIOS\n");
-		pr_info_once("x86/mktme: %d KeyIDs available\n", nr_keyids);
-	} else {
-		pr_info_once("x86/mktme: disabled by BIOS\n");
-	}
-
-	if (mktme_status == MKTME_UNINITIALIZED) {
-		/* MKTME is usable */
-		mktme_status = MKTME_ENABLED;
-	}
-
-	/*
-	 * KeyID bits effectively lower the number of physical address
-	 * bits.  Update cpuinfo_x86::x86_phys_bits accordingly.
-	 */
-	c->x86_phys_bits -= keyid_bits;
-}
-
 static void init_cpuid_fault(struct cpuinfo_x86 *c)
 {
 	u64 msr;
@@ -758,9 +765,6 @@
 	if (cpu_has(c, X86_FEATURE_VMX))
 		detect_vmx_virtcap(c);
 
-	if (cpu_has(c, X86_FEATURE_TME))
-		detect_tme(c);
-
 	init_intel_misc_features(c);
 
 	if (tsx_ctrl_state == TSX_CTRL_ENABLE)
@@ -791,26 +795,37 @@
 }
 #endif
 
-#define TLB_INST_4K	0x01
-#define TLB_INST_4M	0x02
-#define TLB_INST_2M_4M	0x03
-
-#define TLB_INST_ALL	0x05
-#define TLB_INST_1G	0x06
-
-#define TLB_DATA_4K	0x11
-#define TLB_DATA_4M	0x12
-#define TLB_DATA_2M_4M	0x13
-#define TLB_DATA_4K_4M	0x14
-
-#define TLB_DATA_1G	0x16
-
-#define TLB_DATA0_4K	0x21
-#define TLB_DATA0_4M	0x22
-#define TLB_DATA0_2M_4M	0x23
+#define TLB_INST_4K		0x01
+#define TLB_INST_4M		0x02
+#define TLB_INST_2M_4M		0x03
+
+#define TLB_INST_ALL		0x05
+#define TLB_INST_1G		0x06
+
+#define TLB_DATA_4K		0x11
+#define TLB_DATA_4M		0x12
+#define TLB_DATA_2M_4M		0x13
+#define TLB_DATA_4K_4M		0x14
+
+#define TLB_DATA_1G		0x16
+#define TLB_DATA_1G_2M_4M	0x17
+
+#define TLB_DATA0_4K		0x21
+#define TLB_DATA0_4M		0x22
+#define TLB_DATA0_2M_4M		0x23
+
+#define STLB_4K			0x41
+#define STLB_4K_2M		0x42
 
-#define STLB_4K		0x41
-#define STLB_4K_2M	0x42
+/*
+ * All of leaf 0x2's one-byte TLB descriptors implies the same number of
+ * entries for their respective TLB types.  The 0x63 descriptor is an
+ * exception: it implies 4 dTLB entries for 1GB pages 32 dTLB entries
+ * for 2MB or 4MB pages.  Encode descriptor 0x63 dTLB entry count for
+ * 2MB/4MB pages here, as its count for dTLB 1GB pages is already at the
+ * intel_tlb_table[] mapping.
+ */
+#define TLB_0x63_2M_4M_ENTRIES	32
 
 static const struct _tlb_table intel_tlb_table[] = {
 	{ 0x01, TLB_INST_4K,		32,	" TLB_INST 4 KByte pages, 4-way set associative" },
@@ -832,7 +847,8 @@
 	{ 0x5c, TLB_DATA_4K_4M,		128,	" TLB_DATA 4 KByte and 4 MByte pages" },
 	{ 0x5d, TLB_DATA_4K_4M,		256,	" TLB_DATA 4 KByte and 4 MByte pages" },
 	{ 0x61, TLB_INST_4K,		48,	" TLB_INST 4 KByte pages, full associative" },
-	{ 0x63, TLB_DATA_1G,		4,	" TLB_DATA 1 GByte pages, 4-way set associative" },
+	{ 0x63, TLB_DATA_1G_2M_4M,	4,	" TLB_DATA 1 GByte pages, 4-way set associative"
+						" (plus 32 entries TLB_DATA 2 MByte or 4 MByte pages, not encoded here)" },
 	{ 0x6b, TLB_DATA_4K,		256,	" TLB_DATA 4 KByte pages, 8-way associative" },
 	{ 0x6c, TLB_DATA_2M_4M,		128,	" TLB_DATA 2 MByte or 4 MByte pages, 8-way associative" },
 	{ 0x6d, TLB_DATA_1G,		16,	" TLB_DATA 1 GByte pages, fully associative" },
@@ -932,6 +948,12 @@
 		if (tlb_lld_4m[ENTRIES] < intel_tlb_table[k].entries)
 			tlb_lld_4m[ENTRIES] = intel_tlb_table[k].entries;
 		break;
+	case TLB_DATA_1G_2M_4M:
+		if (tlb_lld_2m[ENTRIES] < TLB_0x63_2M_4M_ENTRIES)
+			tlb_lld_2m[ENTRIES] = TLB_0x63_2M_4M_ENTRIES;
+		if (tlb_lld_4m[ENTRIES] < TLB_0x63_2M_4M_ENTRIES)
+			tlb_lld_4m[ENTRIES] = TLB_0x63_2M_4M_ENTRIES;
+		fallthrough;
 	case TLB_DATA_1G:
 		if (tlb_lld_1g[ENTRIES] < intel_tlb_table[k].entries)
 			tlb_lld_1g[ENTRIES] = intel_tlb_table[k].entries;
@@ -955,7 +977,7 @@
 		cpuid(2, &regs[0], &regs[1], &regs[2], &regs[3]);
 
 		/* If bit 31 is set, this is an unknown format */
-		for (j = 0 ; j < 3 ; j++)
+		for (j = 0 ; j < 4 ; j++)
 			if (regs[j] & (1 << 31))
 				regs[j] = 0;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/cpu/match.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/cpu/match.c
@@ -16,12 +16,17 @@
  * respective wildcard entries.
  *
  * A typical table entry would be to match a specific CPU
- * { X86_VENDOR_INTEL, 6, 0x12 }
- * or to match a specific CPU feature
- * { X86_FEATURE_MATCH(X86_FEATURE_FOOBAR) }
+ *
+ * X86_MATCH_VENDOR_FAM_MODEL_FEATURE(INTEL, 6, INTEL_FAM6_BROADWELL,
+ *				      X86_FEATURE_ANY, NULL);
  *
  * Fields can be wildcarded with %X86_VENDOR_ANY, %X86_FAMILY_ANY,
- * %X86_MODEL_ANY, %X86_FEATURE_ANY or 0 (except for vendor)
+ * %X86_MODEL_ANY, %X86_FEATURE_ANY (except for vendor)
+ *
+ * asm/cpu_device_id.h contains a set of useful macros which are shortcuts
+ * for various common selections. The above can be shortened to:
+ *
+ * X86_MATCH_INTEL_FAM6_MODEL(BROADWELL, NULL);
  *
  * Arrays used to match for this should also be declared using
  * MODULE_DEVICE_TABLE(x86cpu, ...)
@@ -34,13 +39,18 @@
 	const struct x86_cpu_id *m;
 	struct cpuinfo_x86 *c = &boot_cpu_data;
 
-	for (m = match; m->vendor | m->family | m->model | m->feature; m++) {
+	for (m = match;
+	     m->vendor | m->family | m->model | m->steppings | m->feature;
+	     m++) {
 		if (m->vendor != X86_VENDOR_ANY && c->x86_vendor != m->vendor)
 			continue;
 		if (m->family != X86_FAMILY_ANY && c->x86 != m->family)
 			continue;
 		if (m->model != X86_MODEL_ANY && c->x86_model != m->model)
 			continue;
+		if (m->steppings != X86_STEPPING_ANY &&
+		    !(BIT(c->x86_stepping) & m->steppings))
+			continue;
 		if (m->feature != X86_FEATURE_ANY && !cpu_has(c, m->feature))
 			continue;
 		return m;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/cpu/mce/amd.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/cpu/mce/amd.c
@@ -78,6 +78,7 @@
 
 static struct smca_bank_name smca_names[] = {
 	[SMCA_LS]	= { "load_store",	"Load Store Unit" },
+	[SMCA_LS_V2]	= { "load_store",	"Load Store Unit" },
 	[SMCA_IF]	= { "insn_fetch",	"Instruction Fetch Unit" },
 	[SMCA_L2_CACHE]	= { "l2_cache",		"L2 Cache" },
 	[SMCA_DE]	= { "decode_unit",	"Decode Unit" },
@@ -138,6 +139,7 @@
 
 	/* ZN Core (HWID=0xB0) MCA types */
 	{ SMCA_LS,	 HWID_MCATYPE(0xB0, 0x0), 0x1FFFFF },
+	{ SMCA_LS_V2,	 HWID_MCATYPE(0xB0, 0x10), 0xFFFFFF },
 	{ SMCA_IF,	 HWID_MCATYPE(0xB0, 0x1), 0x3FFF },
 	{ SMCA_L2_CACHE, HWID_MCATYPE(0xB0, 0x2), 0xF },
 	{ SMCA_DE,	 HWID_MCATYPE(0xB0, 0x3), 0x1FF },
@@ -266,10 +268,10 @@
 	smca_set_misc_banks_map(bank, cpu);
 
 	/* Return early if this bank was already initialized. */
-	if (smca_banks[bank].hwid)
+	if (smca_banks[bank].hwid && smca_banks[bank].hwid->hwid_mcatype != 0)
 		return;
 
-	if (rdmsr_safe_on_cpu(cpu, MSR_AMD64_SMCA_MCx_IPID(bank), &low, &high)) {
+	if (rdmsr_safe(MSR_AMD64_SMCA_MCx_IPID(bank), &low, &high)) {
 		pr_warn("Failed to read MCA_IPID for bank %d\n", bank);
 		return;
 	}
@@ -1161,9 +1163,12 @@
 	.store			= store,
 };
 
+static void threshold_block_release(struct kobject *kobj);
+
 static struct kobj_type threshold_ktype = {
 	.sysfs_ops		= &threshold_ops,
 	.default_attrs		= default_attrs,
+	.release		= threshold_block_release,
 };
 
 static const char *get_name(unsigned int bank, struct threshold_block *b)
@@ -1196,8 +1201,9 @@
 	return buf_mcatype;
 }
 
-static int allocate_threshold_blocks(unsigned int cpu, unsigned int bank,
-				     unsigned int block, u32 address)
+static int allocate_threshold_blocks(unsigned int cpu, struct threshold_bank *tb,
+				     unsigned int bank, unsigned int block,
+				     u32 address)
 {
 	struct threshold_block *b = NULL;
 	u32 low, high;
@@ -1241,16 +1247,12 @@
 
 	INIT_LIST_HEAD(&b->miscj);
 
-	if (per_cpu(threshold_banks, cpu)[bank]->blocks) {
-		list_add(&b->miscj,
-			 &per_cpu(threshold_banks, cpu)[bank]->blocks->miscj);
-	} else {
-		per_cpu(threshold_banks, cpu)[bank]->blocks = b;
-	}
+	if (tb->blocks)
+		list_add(&b->miscj, &tb->blocks->miscj);
+	else
+		tb->blocks = b;
 
-	err = kobject_init_and_add(&b->kobj, &threshold_ktype,
-				   per_cpu(threshold_banks, cpu)[bank]->kobj,
-				   get_name(bank, b));
+	err = kobject_init_and_add(&b->kobj, &threshold_ktype, tb->kobj, get_name(bank, b));
 	if (err)
 		goto out_free;
 recurse:
@@ -1258,7 +1260,7 @@
 	if (!address)
 		return 0;
 
-	err = allocate_threshold_blocks(cpu, bank, block, address);
+	err = allocate_threshold_blocks(cpu, tb, bank, block, address);
 	if (err)
 		goto out_free;
 
@@ -1343,8 +1345,6 @@
 		goto out_free;
 	}
 
-	per_cpu(threshold_banks, cpu)[bank] = b;
-
 	if (is_shared_bank(bank)) {
 		refcount_set(&b->cpus, 1);
 
@@ -1355,9 +1355,13 @@
 		}
 	}
 
-	err = allocate_threshold_blocks(cpu, bank, 0, msr_ops.misc(bank));
-	if (!err)
-		goto out;
+	err = allocate_threshold_blocks(cpu, b, bank, 0, msr_ops.misc(bank));
+	if (err)
+		goto out_free;
+
+	per_cpu(threshold_banks, cpu)[bank] = b;
+
+	return 0;
 
  out_free:
 	kfree(b);
@@ -1366,8 +1370,12 @@
 	return err;
 }
 
-static void deallocate_threshold_block(unsigned int cpu,
-						 unsigned int bank)
+static void threshold_block_release(struct kobject *kobj)
+{
+	kfree(to_block(kobj));
+}
+
+static void deallocate_threshold_block(unsigned int cpu, unsigned int bank)
 {
 	struct threshold_block *pos = NULL;
 	struct threshold_block *tmp = NULL;
@@ -1377,13 +1385,11 @@
 		return;
 
 	list_for_each_entry_safe(pos, tmp, &head->blocks->miscj, miscj) {
-		kobject_put(&pos->kobj);
 		list_del(&pos->miscj);
-		kfree(pos);
+		kobject_put(&pos->kobj);
 	}
 
-	kfree(per_cpu(threshold_banks, cpu)[bank]->blocks);
-	per_cpu(threshold_banks, cpu)[bank]->blocks = NULL;
+	kobject_put(&head->blocks->kobj);
 }
 
 static void __threshold_remove_blocks(struct threshold_bank *b)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/cpu/mce/core.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/cpu/mce/core.c
@@ -42,6 +42,7 @@
 #include <linux/export.h>
 #include <linux/jump_label.h>
 #include <linux/set_memory.h>
+#include <linux/kexec.h>
 
 #include <asm/intel-family.h>
 #include <asm/processor.h>
@@ -310,11 +311,18 @@
 	panic("Panicing machine check CPU died");
 }
 
-static void mce_panic(const char *msg, struct mce *final, char *exp)
+static noinstr void mce_panic(const char *msg, struct mce *final, char *exp)
 {
-	int apei_err = 0;
 	struct llist_node *pending;
 	struct mce_evt_llist *l;
+	int apei_err = 0;
+	struct page *p;
+
+	/*
+	 * Allow instrumentation around external facilities usage. Not that it
+	 * matters a whole lot since the machine is going to panic anyway.
+	 */
+	instrumentation_begin();
 
 	if (!fake_panic) {
 		/*
@@ -329,7 +337,7 @@
 	} else {
 		/* Don't log too much for fake panic */
 		if (atomic_inc_return(&mce_fake_panicked) > 1)
-			return;
+			goto out;
 	}
 	pending = mce_gen_pool_prepare_records();
 	/* First print corrected ones that are still unlogged */
@@ -364,9 +372,26 @@
 	if (!fake_panic) {
 		if (panic_timeout == 0)
 			panic_timeout = mca_cfg.panic_timeout;
+
+		/*
+		 * Kdump skips the poisoned page in order to avoid
+		 * touching the error bits again. Poison the page even
+		 * if the error is fatal and the machine is about to
+		 * panic.
+		 */
+		if (kexec_crash_loaded()) {
+			if (final && (final->status & MCI_STATUS_ADDRV)) {
+				p = pfn_to_online_page(final->addr >> PAGE_SHIFT);
+				if (p)
+					SetPageHWPoison(p);
+			}
+		}
 		panic(msg);
 	} else
 		pr_emerg(HW_ERR "Fake kernel panic: %s\n", msg);
+
+out:
+	instrumentation_end();
 }
 
 /* Support code for software error injection */
@@ -388,10 +413,38 @@
 	return -1;
 }
 
+static void ex_handler_msr_mce(struct pt_regs *regs, bool wrmsr)
+{
+	if (wrmsr) {
+		pr_emerg("MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x) at rIP: 0x%lx (%pS)\n",
+			 (unsigned int)regs->cx, (unsigned int)regs->dx, (unsigned int)regs->ax,
+			 regs->ip, (void *)regs->ip);
+	} else {
+		pr_emerg("MSR access error: RDMSR from 0x%x at rIP: 0x%lx (%pS)\n",
+			 (unsigned int)regs->cx, regs->ip, (void *)regs->ip);
+	}
+
+	show_stack_regs(regs);
+
+	panic("MCA architectural violation!\n");
+
+	while (true)
+		cpu_relax();
+}
+
+__visible bool ex_handler_rdmsr_fault(const struct exception_table_entry *fixup,
+				      struct pt_regs *regs, int trapnr,
+				      unsigned long error_code,
+				      unsigned long fault_addr)
+{
+	ex_handler_msr_mce(regs, false);
+	return true;
+}
+
 /* MSR access wrappers used for error injection */
 static u64 mce_rdmsrl(u32 msr)
 {
-	u64 v;
+	DECLARE_ARGS(val, low, high);
 
 	if (__this_cpu_read(injectm.finished)) {
 		int offset = msr_to_offset(msr);
@@ -401,21 +454,33 @@
 		return *(u64 *)((char *)this_cpu_ptr(&injectm) + offset);
 	}
 
-	if (rdmsrl_safe(msr, &v)) {
-		WARN_ONCE(1, "mce: Unable to read MSR 0x%x!\n", msr);
-		/*
-		 * Return zero in case the access faulted. This should
-		 * not happen normally but can happen if the CPU does
-		 * something weird, or if the code is buggy.
-		 */
-		v = 0;
-	}
+	/*
+	 * RDMSR on MCA MSRs should not fault. If they do, this is very much an
+	 * architectural violation and needs to be reported to hw vendor. Panic
+	 * the box to not allow any further progress.
+	 */
+	asm volatile("1: rdmsr\n"
+		     "2:\n"
+		     _ASM_EXTABLE_HANDLE(1b, 2b, ex_handler_rdmsr_fault)
+		     : EAX_EDX_RET(val, low, high) : "c" (msr));
 
-	return v;
+
+	return EAX_EDX_VAL(val, low, high);
+}
+
+__visible bool ex_handler_wrmsr_fault(const struct exception_table_entry *fixup,
+				      struct pt_regs *regs, int trapnr,
+				      unsigned long error_code,
+				      unsigned long fault_addr)
+{
+	ex_handler_msr_mce(regs, true);
+	return true;
 }
 
 static void mce_wrmsrl(u32 msr, u64 v)
 {
+	u32 low, high;
+
 	if (__this_cpu_read(injectm.finished)) {
 		int offset = msr_to_offset(msr);
 
@@ -423,7 +488,15 @@
 			*(u64 *)((char *)this_cpu_ptr(&injectm) + offset) = v;
 		return;
 	}
-	wrmsrl(msr, v);
+
+	low  = (u32)v;
+	high = (u32)(v >> 32);
+
+	/* See comment in mce_rdmsrl() */
+	asm volatile("1: wrmsr\n"
+		     "2:\n"
+		     _ASM_EXTABLE_HANDLE(1b, 2b, ex_handler_wrmsr_fault)
+		     : : "c" (msr), "a"(low), "d" (high) : "memory");
 }
 
 /*
@@ -533,6 +606,13 @@
 }
 EXPORT_SYMBOL_GPL(mce_is_memory_error);
 
+static bool whole_page(struct mce *m)
+{
+	if (!mca_cfg.ser || !(m->status & MCI_STATUS_MISCV))
+		return true;
+	return MCI_MISC_ADDR_LSB(m->misc) >= PAGE_SHIFT;
+}
+
 bool mce_is_correctable(struct mce *m)
 {
 	if (m->cpuvendor == X86_VENDOR_AMD && m->status & MCI_STATUS_DEFERRED)
@@ -601,7 +681,7 @@
 	if (mce_usable_address(mce) && (mce->severity == MCE_AO_SEVERITY)) {
 		pfn = mce->addr >> PAGE_SHIFT;
 		if (!memory_failure(pfn, 0))
-			set_mce_nospec(pfn);
+			set_mce_nospec(pfn, whole_page(mce));
 	}
 
 	return NOTIFY_OK;
@@ -636,7 +716,7 @@
 /*
  * Read ADDR and MISC registers.
  */
-static void mce_read_aux(struct mce *m, int i)
+static noinstr void mce_read_aux(struct mce *m, int i)
 {
 	if (m->status & MCI_STATUS_MISCV)
 		m->misc = mce_rdmsrl(msr_ops.misc(i));
@@ -814,8 +894,8 @@
 		if (quirk_no_way_out)
 			quirk_no_way_out(i, m, regs);
 
+		m->bank = i;
 		if (mce_severity(m, mca_cfg.tolerant, &tmp, true) >= MCE_PANIC_SEVERITY) {
-			m->bank = i;
 			mce_read_aux(m, i);
 			*msg = tmp;
 			return 1;
@@ -1016,10 +1096,13 @@
  * Synchronize between CPUs after main scanning loop.
  * This invokes the bulk of the Monarch processing.
  */
-static int mce_end(int order)
+static noinstr int mce_end(int order)
 {
-	int ret = -1;
 	u64 timeout = (u64)mca_cfg.monarch_timeout * NSEC_PER_USEC;
+	int ret = -1;
+
+	/* Allow instrumentation around external facilities. */
+	instrumentation_begin();
 
 	if (!timeout)
 		goto reset;
@@ -1063,7 +1146,8 @@
 		/*
 		 * Don't reset anything. That's done by the Monarch.
 		 */
-		return 0;
+		ret = 0;
+		goto out;
 	}
 
 	/*
@@ -1078,6 +1162,10 @@
 	 * Let others run again.
 	 */
 	atomic_set(&mce_executing, 0);
+
+out:
+	instrumentation_end();
+
 	return ret;
 }
 
@@ -1103,7 +1191,7 @@
 	if (ret)
 		pr_err("Memory error not recovered");
 	else
-		set_mce_nospec(m->addr >> PAGE_SHIFT);
+		set_mce_nospec(m->addr >> PAGE_SHIFT, whole_page(m));
 	return ret;
 }
 
@@ -1306,8 +1394,10 @@
 	 * When there's any problem use only local no_way_out state.
 	 */
 	if (!lmce) {
-		if (mce_end(order) < 0)
-			no_way_out = worst >= MCE_PANIC_SEVERITY;
+		if (mce_end(order) < 0) {
+			if (!no_way_out)
+				no_way_out = worst >= MCE_PANIC_SEVERITY;
+		}
 	} else {
 		/*
 		 * If there was a fatal machine check we should have
@@ -2138,12 +2228,14 @@
 		return -EINVAL;
 
 	b = &per_cpu(mce_banks_array, s->id)[bank];
-
 	if (!b->init)
 		return -ENODEV;
 
 	b->ctl = new;
+
+	mutex_lock(&mce_sysfs_mutex);
 	mce_restart();
+	mutex_unlock(&mce_sysfs_mutex);
 
 	return size;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/cpu/mce/inject.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/cpu/mce/inject.c
@@ -347,7 +347,7 @@
 	char buf[MAX_FLAG_OPT_SIZE], *__buf;
 	int err;
 
-	if (cnt > MAX_FLAG_OPT_SIZE)
+	if (!cnt || cnt > MAX_FLAG_OPT_SIZE)
 		return -EINVAL;
 
 	if (copy_from_user(&buf, ubuf, cnt))
@@ -511,7 +511,7 @@
 	 */
 	if (inj_type == DFR_INT_INJ) {
 		i_mce.status |= MCI_STATUS_DEFERRED;
-		i_mce.status |= (i_mce.status & ~MCI_STATUS_UC);
+		i_mce.status &= ~MCI_STATUS_UC;
 	}
 
 	/*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/cpu/mce/intel.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/cpu/mce/intel.c
@@ -489,17 +489,18 @@
 			return;
 
 		if ((val & 3UL) == 1UL) {
-			/* PPIN available but disabled: */
+			/* PPIN locked in disabled mode */
 			return;
 		}
 
-		/* If PPIN is disabled, but not locked, try to enable: */
-		if (!(val & 3UL)) {
+		/* If PPIN is disabled, try to enable */
+		if (!(val & 2UL)) {
 			wrmsrl_safe(MSR_PPIN_CTL,  val | 2UL);
 			rdmsrl_safe(MSR_PPIN_CTL, &val);
 		}
 
-		if ((val & 3UL) == 2UL)
+		/* Is the enable bit set? */
+		if (val & 2UL)
 			set_cpu_cap(c, X86_FEATURE_INTEL_PPIN);
 	}
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/cpu/mce/internal.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/cpu/mce/internal.h
@@ -172,4 +172,14 @@
 static inline bool amd_filter_mce(struct mce *m)			{ return false; };
 #endif
 
+__visible bool ex_handler_rdmsr_fault(const struct exception_table_entry *fixup,
+				      struct pt_regs *regs, int trapnr,
+				      unsigned long error_code,
+				      unsigned long fault_addr);
+
+__visible bool ex_handler_wrmsr_fault(const struct exception_table_entry *fixup,
+				      struct pt_regs *regs, int trapnr,
+				      unsigned long error_code,
+				      unsigned long fault_addr);
+
 #endif /* __X86_MCE_INTERNAL_H__ */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/cpu/mce/severity.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/cpu/mce/severity.c
@@ -9,9 +9,11 @@
 #include <linux/seq_file.h>
 #include <linux/init.h>
 #include <linux/debugfs.h>
-#include <asm/mce.h>
 #include <linux/uaccess.h>
 
+#include <asm/mce.h>
+#include <asm/intel-family.h>
+
 #include "internal.h"
 
 /*
@@ -40,9 +42,14 @@
 	unsigned char context;
 	unsigned char excp;
 	unsigned char covered;
+	unsigned char cpu_model;
+	unsigned char cpu_minstepping;
+	unsigned char bank_lo, bank_hi;
 	char *msg;
 } severities[] = {
 #define MCESEV(s, m, c...) { .sev = MCE_ ## s ## _SEVERITY, .msg = m, ## c }
+#define BANK_RANGE(l, h) .bank_lo = l, .bank_hi = h
+#define MODEL_STEPPING(m, s) .cpu_model = m, .cpu_minstepping = s
 #define  KERNEL		.context = IN_KERNEL
 #define  USER		.context = IN_USER
 #define  KERNEL_RECOV	.context = IN_KERNEL_RECOV
@@ -97,7 +104,6 @@
 		KEEP, "Corrected error",
 		NOSER, BITCLR(MCI_STATUS_UC)
 		),
-
 	/*
 	 * known AO MCACODs reported via MCE or CMC:
 	 *
@@ -113,6 +119,18 @@
 		AO, "Action optional: last level cache writeback error",
 		SER, MASK(MCI_UC_AR|MCACOD, MCI_STATUS_UC|MCACOD_L3WB)
 		),
+	/*
+	 * Quirk for Skylake/Cascade Lake. Patrol scrubber may be configured
+	 * to report uncorrected errors using CMCI with a special signature.
+	 * UC=0, MSCOD=0x0010, MCACOD=binary(000X 0000 1100 XXXX) reported
+	 * in one of the memory controller banks.
+	 * Set severity to "AO" for same action as normal patrol scrub error.
+	 */
+	MCESEV(
+		AO, "Uncorrected Patrol Scrub Error",
+		SER, MASK(MCI_STATUS_UC|MCI_ADDR|0xffffeff0, MCI_ADDR|0x001000c0),
+		MODEL_STEPPING(INTEL_FAM6_SKYLAKE_X, 4), BANK_RANGE(13, 18)
+	),
 
 	/* ignore OVER for UCNA */
 	MCESEV(
@@ -320,6 +338,12 @@
 			continue;
 		if (s->excp && excp != s->excp)
 			continue;
+		if (s->cpu_model && boot_cpu_data.x86_model != s->cpu_model)
+			continue;
+		if (s->cpu_minstepping && boot_cpu_data.x86_stepping < s->cpu_minstepping)
+			continue;
+		if (s->bank_lo && (m->bank < s->bank_lo || m->bank > s->bank_hi))
+			continue;
 		if (msg)
 			*msg = s->msg;
 		s->covered = 1;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/cpu/mce/therm_throt.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/cpu/mce/therm_throt.c
@@ -188,7 +188,7 @@
 	/* if we just entered the thermal event */
 	if (new_event) {
 		if (event == THERMAL_THROTTLING_EVENT)
-			pr_crit("CPU%d: %s temperature above threshold, cpu clock throttled (total events = %lu)\n",
+			pr_warn("CPU%d: %s temperature above threshold, cpu clock throttled (total events = %lu)\n",
 				this_cpu,
 				level == CORE_LEVEL ? "Core" : "Package",
 				state->count);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/cpu/microcode/amd.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/cpu/microcode/amd.c
@@ -55,7 +55,9 @@
 };
 
 static u32 ucode_new_rev;
-static u8 amd_ucode_patch[PATCH_MAX_SIZE];
+
+/* One blob per node. */
+static u8 amd_ucode_patch[MAX_NUMNODES][PATCH_MAX_SIZE];
 
 /*
  * Microcode patch container file is prepended to the initrd in cpio
@@ -429,7 +431,7 @@
 	patch	= (u8 (*)[PATCH_MAX_SIZE])__pa_nodebug(&amd_ucode_patch);
 #else
 	new_rev = &ucode_new_rev;
-	patch	= &amd_ucode_patch;
+	patch	= &amd_ucode_patch[0];
 #endif
 
 	desc.cpuid_1_eax = cpuid_1_eax;
@@ -441,7 +443,13 @@
 		return ret;
 
 	native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
-	if (rev >= mc->hdr.patch_id)
+
+	/*
+	 * Allow application of the same revision to pick up SMT-specific
+	 * changes even if the revision of the other SMT thread is already
+	 * up-to-date.
+	 */
+	if (rev > mc->hdr.patch_id)
 		return ret;
 
 	if (!__apply_microcode_amd(mc)) {
@@ -523,8 +531,12 @@
 
 	native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
 
-	/* Check whether we have saved a new patch already: */
-	if (*new_rev && rev < mc->hdr.patch_id) {
+	/*
+	 * Check whether a new patch has been saved already. Also, allow application of
+	 * the same revision in order to pick up SMT-thread-specific configuration even
+	 * if the sibling SMT thread already has an up-to-date revision.
+	 */
+	if (*new_rev && rev <= mc->hdr.patch_id) {
 		if (!__apply_microcode_amd(mc)) {
 			*new_rev = mc->hdr.patch_id;
 			return;
@@ -538,8 +550,7 @@
 	apply_microcode_early_amd(cpuid_1_eax, cp.data, cp.size, false);
 }
 
-static enum ucode_state
-load_microcode_amd(bool save, u8 family, const u8 *data, size_t size);
+static enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size);
 
 int __init save_microcode_in_initrd_amd(unsigned int cpuid_1_eax)
 {
@@ -557,19 +568,19 @@
 	if (!desc.mc)
 		return -EINVAL;
 
-	ret = load_microcode_amd(true, x86_family(cpuid_1_eax), desc.data, desc.size);
+	ret = load_microcode_amd(x86_family(cpuid_1_eax), desc.data, desc.size);
 	if (ret > UCODE_UPDATED)
 		return -EINVAL;
 
 	return 0;
 }
 
-void reload_ucode_amd(void)
+void reload_ucode_amd(unsigned int cpu)
 {
-	struct microcode_amd *mc;
 	u32 rev, dummy;
+	struct microcode_amd *mc;
 
-	mc = (struct microcode_amd *)amd_ucode_patch;
+	mc = (struct microcode_amd *)amd_ucode_patch[cpu_to_node(cpu)];
 
 	rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
 
@@ -689,7 +700,7 @@
 	rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
 
 	/* need to apply patch? */
-	if (rev >= mc_amd->hdr.patch_id) {
+	if (rev > mc_amd->hdr.patch_id) {
 		ret = UCODE_OK;
 		goto out;
 	}
@@ -783,6 +794,7 @@
 		kfree(patch);
 		return -EINVAL;
 	}
+	patch->size = *patch_size;
 
 	mc_hdr      = (struct microcode_header_amd *)(fw + SECTION_HDR_SIZE);
 	proc_id     = mc_hdr->processor_rev_id;
@@ -834,9 +846,10 @@
 	return UCODE_OK;
 }
 
-static enum ucode_state
-load_microcode_amd(bool save, u8 family, const u8 *data, size_t size)
+static enum ucode_state load_microcode_amd(u8 family, const u8 *data, size_t size)
 {
+	struct cpuinfo_x86 *c;
+	unsigned int nid, cpu;
 	struct ucode_patch *p;
 	enum ucode_state ret;
 
@@ -849,22 +862,22 @@
 		return ret;
 	}
 
-	p = find_patch(0);
-	if (!p) {
-		return ret;
-	} else {
-		if (boot_cpu_data.microcode >= p->patch_id)
-			return ret;
+	for_each_node_with_cpus(nid) {
+		cpu = cpumask_first(cpumask_of_node(nid));
+		c = &cpu_data(cpu);
+
+		p = find_patch(cpu);
+		if (!p)
+			continue;
 
-		ret = UCODE_NEW;
-	}
+		if (c->microcode >= p->patch_id)
+			continue;
 
-	/* save BSP's matching patch for early load */
-	if (!save)
-		return ret;
+		ret = UCODE_NEW;
 
-	memset(amd_ucode_patch, 0, PATCH_MAX_SIZE);
-	memcpy(amd_ucode_patch, p->data, min_t(u32, ksize(p->data), PATCH_MAX_SIZE));
+		memset(&amd_ucode_patch[nid], 0, PATCH_MAX_SIZE);
+		memcpy(&amd_ucode_patch[nid], p->data, min_t(u32, p->size, PATCH_MAX_SIZE));
+	}
 
 	return ret;
 }
@@ -890,12 +903,11 @@
 {
 	char fw_name[36] = "amd-ucode/microcode_amd.bin";
 	struct cpuinfo_x86 *c = &cpu_data(cpu);
-	bool bsp = c->cpu_index == boot_cpu_data.cpu_index;
 	enum ucode_state ret = UCODE_NFOUND;
 	const struct firmware *fw;
 
 	/* reload ucode container only on the boot cpu */
-	if (!refresh_fw || !bsp)
+	if (!refresh_fw)
 		return UCODE_OK;
 
 	if (c->x86 >= 0x15)
@@ -910,7 +922,7 @@
 	if (!verify_container(fw->data, fw->size, false))
 		goto fw_release;
 
-	ret = load_microcode_amd(bsp, c->x86, fw->data, fw->size);
+	ret = load_microcode_amd(c->x86, fw->data, fw->size);
 
  fw_release:
 	release_firmware(fw);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/cpu/microcode/core.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/cpu/microcode/core.c
@@ -322,7 +322,7 @@
 #endif
 }
 
-void reload_early_microcode(void)
+void reload_early_microcode(unsigned int cpu)
 {
 	int vendor, family;
 
@@ -336,7 +336,7 @@
 		break;
 	case X86_VENDOR_AMD:
 		if (family >= 0x10)
-			reload_ucode_amd();
+			reload_ucode_amd(cpu);
 		break;
 	default:
 		break;
@@ -626,16 +626,16 @@
 	if (val != 1)
 		return size;
 
-	tmp_ret = microcode_ops->request_microcode_fw(bsp, &microcode_pdev->dev, true);
-	if (tmp_ret != UCODE_NEW)
-		return size;
-
 	get_online_cpus();
 
 	ret = check_online_cpus();
 	if (ret)
 		goto put;
 
+	tmp_ret = microcode_ops->request_microcode_fw(bsp, &microcode_pdev->dev, true);
+	if (tmp_ret != UCODE_NEW)
+		goto put;
+
 	mutex_lock(&microcode_mutex);
 	ret = microcode_reload_late();
 	mutex_unlock(&microcode_mutex);
@@ -772,9 +772,9 @@
 };
 
 /**
- * mc_bp_resume - Update boot CPU microcode during resume.
+ * microcode_bsp_resume - Update boot CPU microcode during resume.
  */
-static void mc_bp_resume(void)
+void microcode_bsp_resume(void)
 {
 	int cpu = smp_processor_id();
 	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
@@ -782,11 +782,11 @@
 	if (uci->valid && uci->mc)
 		microcode_ops->apply_microcode(cpu);
 	else if (!uci->mc)
-		reload_early_microcode();
+		reload_early_microcode(cpu);
 }
 
 static struct syscore_ops mc_syscore_ops = {
-	.resume			= mc_bp_resume,
+	.resume			= microcode_bsp_resume,
 };
 
 static int mc_cpu_starting(unsigned int cpu)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/cpu/microcode/intel.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/cpu/microcode/intel.c
@@ -100,53 +100,6 @@
 	return find_matching_signature(mc, csig, cpf);
 }
 
-/*
- * Given CPU signature and a microcode patch, this function finds if the
- * microcode patch has matching family and model with the CPU.
- *
- * %true - if there's a match
- * %false - otherwise
- */
-static bool microcode_matches(struct microcode_header_intel *mc_header,
-			      unsigned long sig)
-{
-	unsigned long total_size = get_totalsize(mc_header);
-	unsigned long data_size = get_datasize(mc_header);
-	struct extended_sigtable *ext_header;
-	unsigned int fam_ucode, model_ucode;
-	struct extended_signature *ext_sig;
-	unsigned int fam, model;
-	int ext_sigcount, i;
-
-	fam   = x86_family(sig);
-	model = x86_model(sig);
-
-	fam_ucode   = x86_family(mc_header->sig);
-	model_ucode = x86_model(mc_header->sig);
-
-	if (fam == fam_ucode && model == model_ucode)
-		return true;
-
-	/* Look for ext. headers: */
-	if (total_size <= data_size + MC_HEADER_SIZE)
-		return false;
-
-	ext_header   = (void *) mc_header + data_size + MC_HEADER_SIZE;
-	ext_sig      = (void *)ext_header + EXT_HEADER_SIZE;
-	ext_sigcount = ext_header->count;
-
-	for (i = 0; i < ext_sigcount; i++) {
-		fam_ucode   = x86_family(ext_sig->sig);
-		model_ucode = x86_model(ext_sig->sig);
-
-		if (fam == fam_ucode && model == model_ucode)
-			return true;
-
-		ext_sig++;
-	}
-	return false;
-}
-
 static struct ucode_patch *memdup_patch(void *data, unsigned int size)
 {
 	struct ucode_patch *p;
@@ -164,7 +117,7 @@
 	return p;
 }
 
-static void save_microcode_patch(void *data, unsigned int size)
+static void save_microcode_patch(struct ucode_cpu_info *uci, void *data, unsigned int size)
 {
 	struct microcode_header_intel *mc_hdr, *mc_saved_hdr;
 	struct ucode_patch *iter, *tmp, *p = NULL;
@@ -210,6 +163,9 @@
 	if (!p)
 		return;
 
+	if (!find_matching_signature(p->data, uci->cpu_sig.sig, uci->cpu_sig.pf))
+		return;
+
 	/*
 	 * Save for early loading. On 32-bit, that needs to be a physical
 	 * address as the APs are running from physical addresses, before
@@ -344,13 +300,14 @@
 
 		size -= mc_size;
 
-		if (!microcode_matches(mc_header, uci->cpu_sig.sig)) {
+		if (!find_matching_signature(data, uci->cpu_sig.sig,
+					     uci->cpu_sig.pf)) {
 			data += mc_size;
 			continue;
 		}
 
 		if (save) {
-			save_microcode_patch(data, mc_size);
+			save_microcode_patch(uci, data, mc_size);
 			goto next;
 		}
 
@@ -483,14 +440,14 @@
  * Save this microcode patch. It will be loaded early when a CPU is
  * hot-added or resumes.
  */
-static void save_mc_for_early(u8 *mc, unsigned int size)
+static void save_mc_for_early(struct ucode_cpu_info *uci, u8 *mc, unsigned int size)
 {
 	/* Synchronization during CPU hotplug. */
 	static DEFINE_MUTEX(x86_cpu_microcode_mutex);
 
 	mutex_lock(&x86_cpu_microcode_mutex);
 
-	save_microcode_patch(mc, size);
+	save_microcode_patch(uci, mc, size);
 	show_saved_mc();
 
 	mutex_unlock(&x86_cpu_microcode_mutex);
@@ -702,7 +659,6 @@
 	else
 		iup = &intel_ucode_patch;
 
-reget:
 	if (!*iup) {
 		patch = __load_ucode_intel(&uci);
 		if (!patch)
@@ -713,12 +669,7 @@
 
 	uci.mc = *iup;
 
-	if (apply_microcode_early(&uci, true)) {
-		/* Mixed-silicon system? Try to refetch the proper patch: */
-		*iup = NULL;
-
-		goto reget;
-	}
+	apply_microcode_early(&uci, true);
 }
 
 static struct microcode_intel *find_patch(struct ucode_cpu_info *uci)
@@ -934,7 +885,7 @@
 	 * permanent memory. So it will be loaded early when a CPU is hot added
 	 * or resumes.
 	 */
-	save_mc_for_early(new_mc, new_mc_size);
+	save_mc_for_early(uci, new_mc, new_mc_size);
 
 	pr_debug("CPU%d found a matching microcode update with version 0x%x (current=0x%x)\n",
 		 cpu, new_rev, uci->cpu_sig.rev);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/cpu/mshyperv.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/cpu/mshyperv.c
@@ -16,7 +16,6 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/kexec.h>
-#include <linux/i8253.h>
 #include <linux/random.h>
 #include <asm/processor.h>
 #include <asm/hypervisor.h>
@@ -82,7 +81,7 @@
 	inc_irq_stat(hyperv_stimer0_count);
 	if (hv_stimer0_handler)
 		hv_stimer0_handler();
-	add_interrupt_randomness(HYPERV_STIMER0_VECTOR, 0);
+	add_interrupt_randomness(HYPERV_STIMER0_VECTOR);
 	ack_APIC_irq();
 
 	exiting_irq();
@@ -227,8 +226,8 @@
 	ms_hyperv.misc_features = cpuid_edx(HYPERV_CPUID_FEATURES);
 	ms_hyperv.hints    = cpuid_eax(HYPERV_CPUID_ENLIGHTMENT_INFO);
 
-	pr_info("Hyper-V: features 0x%x, hints 0x%x\n",
-		ms_hyperv.features, ms_hyperv.hints);
+	pr_info("Hyper-V: features 0x%x, hints 0x%x, misc 0x%x\n",
+		ms_hyperv.features, ms_hyperv.hints, ms_hyperv.misc_features);
 
 	ms_hyperv.max_vp_index = cpuid_eax(HYPERV_CPUID_IMPLEMENT_LIMITS);
 	ms_hyperv.max_lp_index = cpuid_ebx(HYPERV_CPUID_IMPLEMENT_LIMITS);
@@ -256,6 +255,7 @@
 	    ms_hyperv.misc_features & HV_FEATURE_FREQUENCY_MSRS_AVAILABLE) {
 		x86_platform.calibrate_tsc = hv_get_tsc_khz;
 		x86_platform.calibrate_cpu = hv_get_tsc_khz;
+		setup_force_cpu_cap(X86_FEATURE_TSC_KNOWN_FREQ);
 	}
 
 	if (ms_hyperv.hints & HV_X64_ENLIGHTENED_VMCS_RECOMMENDED) {
@@ -263,6 +263,16 @@
 			cpuid_eax(HYPERV_CPUID_NESTED_FEATURES);
 	}
 
+	/*
+	 * Hyper-V expects to get crash register data or kmsg when
+	 * crash enlightment is available and system crashes. Set
+	 * crash_kexec_post_notifiers to be true to make sure that
+	 * calling crash enlightment interface before running kdump
+	 * kernel.
+	 */
+	if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE)
+		crash_kexec_post_notifiers = true;
+
 #ifdef CONFIG_X86_LOCAL_APIC
 	if (ms_hyperv.features & HV_X64_ACCESS_FREQUENCY_MSRS &&
 	    ms_hyperv.misc_features & HV_FEATURE_FREQUENCY_MSRS_AVAILABLE) {
@@ -299,16 +309,6 @@
 	if (efi_enabled(EFI_BOOT))
 		x86_platform.get_nmi_reason = hv_get_nmi_reason;
 
-	/*
-	 * Hyper-V VMs have a PIT emulation quirk such that zeroing the
-	 * counter register during PIT shutdown restarts the PIT. So it
-	 * continues to interrupt @18.2 HZ. Setting i8253_clear_counter
-	 * to false tells pit_shutdown() not to zero the counter so that
-	 * the PIT really is shutdown. Generation 2 VMs don't have a PIT,
-	 * and setting this value has no effect.
-	 */
-	i8253_clear_counter_on_shutdown = false;
-
 #if IS_ENABLED(CONFIG_HYPERV)
 	/*
 	 * Setup the hook to get control post apic initialization.
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/cpu/mtrr/generic.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/cpu/mtrr/generic.c
@@ -167,9 +167,6 @@
 	*repeat = 0;
 	*uniform = 1;
 
-	/* Make end inclusive instead of exclusive */
-	end--;
-
 	prev_match = MTRR_TYPE_INVALID;
 	for (i = 0; i < num_var_ranges; ++i) {
 		unsigned short start_state, end_state, inclusive;
@@ -261,6 +258,9 @@
 	int repeat;
 	u64 partial_end;
 
+	/* Make end inclusive instead of exclusive */
+	end--;
+
 	if (!mtrr_state_set)
 		return MTRR_TYPE_INVALID;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/cpu/mtrr/mtrr.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/cpu/mtrr/mtrr.c
@@ -794,8 +794,6 @@
 	if (!use_intel() || mtrr_aps_delayed_init)
 		return;
 
-	rcu_cpu_starting(smp_processor_id());
-
 	/*
 	 * Ideally we should hold mtrr_mutex here to avoid mtrr entries
 	 * changed, but this routine will be called in cpu boot time,
@@ -819,7 +817,7 @@
 {
 	int first_cpu;
 
-	if (!mtrr_enabled())
+	if (!mtrr_enabled() || !mtrr_state.have_fixed)
 		return;
 
 	first_cpu = cpumask_first(cpu_online_mask);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/cpu/resctrl/core.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/cpu/resctrl/core.c
@@ -250,7 +250,7 @@
 	return false;
 }
 
-static bool __get_mem_config_intel(struct rdt_resource *r)
+static __init bool __get_mem_config_intel(struct rdt_resource *r)
 {
 	union cpuid_0x10_3_eax eax;
 	union cpuid_0x10_x_edx edx;
@@ -260,6 +260,7 @@
 	r->num_closid = edx.split.cos_max + 1;
 	r->membw.max_delay = eax.split.max_delay + 1;
 	r->default_ctrl = MAX_MBA_BW;
+	r->membw.mbm_width = MBM_CNTR_WIDTH;
 	if (ecx & MBA_IS_LINEAR) {
 		r->membw.delay_linear = true;
 		r->membw.min_bw = MAX_MBA_BW - r->membw.max_delay;
@@ -276,7 +277,7 @@
 	return true;
 }
 
-static bool __rdt_get_mem_config_amd(struct rdt_resource *r)
+static __init bool __rdt_get_mem_config_amd(struct rdt_resource *r)
 {
 	union cpuid_0x10_3_eax eax;
 	union cpuid_0x10_x_edx edx;
@@ -289,6 +290,7 @@
 	/* AMD does not use delay */
 	r->membw.delay_linear = false;
 
+	r->membw.mbm_width = MBM_CNTR_WIDTH_AMD;
 	r->membw.min_bw = 0;
 	r->membw.bw_gran = 1;
 	/* Max value is 2048, Data width should be 4 in decimal */
@@ -578,12 +580,16 @@
 	d->id = id;
 	cpumask_set_cpu(cpu, &d->cpu_mask);
 
+	rdt_domain_reconfigure_cdp(r);
+
 	if (r->alloc_capable && domain_setup_ctrlval(r, d)) {
 		kfree(d);
 		return;
 	}
 
 	if (r->mon_capable && domain_setup_mon_state(r, d)) {
+		kfree(d->ctrl_val);
+		kfree(d->mbps_val);
 		kfree(d);
 		return;
 	}
@@ -618,7 +624,7 @@
 		if (static_branch_unlikely(&rdt_mon_enable_key))
 			rmdir_mondata_subdir_allrdtgrp(r, d->id);
 		list_del(&d->list);
-		if (is_mbm_enabled())
+		if (r->mon_capable && is_mbm_enabled())
 			cancel_delayed_work(&d->mbm_over);
 		if (is_llc_occupancy_enabled() &&  has_busy_rmid(r, d)) {
 			/*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/cpu/resctrl/internal.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/cpu/resctrl/internal.h
@@ -32,6 +32,7 @@
 #define CQM_LIMBOCHECK_INTERVAL	1000
 
 #define MBM_CNTR_WIDTH			24
+#define MBM_CNTR_WIDTH_AMD		44
 #define MBM_OVERFLOW_INTERVAL		1000
 #define MAX_MBA_BW			100u
 #define MBA_IS_LINEAR			0x4
@@ -57,6 +58,7 @@
 }
 
 DECLARE_STATIC_KEY_FALSE(rdt_enable_key);
+DECLARE_STATIC_KEY_FALSE(rdt_mon_enable_key);
 
 /**
  * struct mon_evt - Entry in the event list of a resource
@@ -274,7 +276,6 @@
  * struct mbm_state - status for each MBM counter in each domain
  * @chunks:	Total data moved (multiply by rdt_group.mon_scale to get bytes)
  * @prev_msr	Value of IA32_QM_CTR for this RMID last time we read it
- * @chunks_bw	Total local data moved. Used for bandwidth calculation
  * @prev_bw_msr:Value of previous IA32_QM_CTR for bandwidth counting
  * @prev_bw	The most recent bandwidth in MBps
  * @delta_bw	Difference between the current and previous bandwidth
@@ -283,7 +284,6 @@
 struct mbm_state {
 	u64	chunks;
 	u64	prev_msr;
-	u64	chunks_bw;
 	u64	prev_bw_msr;
 	u32	prev_bw;
 	u32	delta_bw;
@@ -367,6 +367,7 @@
  * @min_bw:		Minimum memory bandwidth percentage user can request
  * @bw_gran:		Granularity at which the memory bandwidth is allocated
  * @delay_linear:	True if memory B/W delay is in linear scale
+ * @mbm_width:		memory B/W monitor counter width
  * @mba_sc:		True if MBA software controller(mba_sc) is enabled
  * @mb_map:		Mapping of memory B/W percentage to memory B/W delay
  */
@@ -375,6 +376,7 @@
 	u32		min_bw;
 	u32		bw_gran;
 	u32		delay_linear;
+	u32		mbm_width;
 	bool		mba_sc;
 	u32		*mb_map;
 };
@@ -600,5 +602,6 @@
 void __check_limbo(struct rdt_domain *d, bool force_free);
 bool cbm_validate_intel(char *buf, u32 *data, struct rdt_resource *r);
 bool cbm_validate_amd(char *buf, u32 *data, struct rdt_resource *r);
+void rdt_domain_reconfigure_cdp(struct rdt_resource *r);
 
 #endif /* _ASM_X86_RESCTRL_INTERNAL_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/cpu/resctrl/monitor.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/cpu/resctrl/monitor.c
@@ -216,21 +216,21 @@
 
 static u64 mbm_overflow_count(u64 prev_msr, u64 cur_msr)
 {
-	u64 shift = 64 - MBM_CNTR_WIDTH, chunks;
+	u64 shift, chunks;
 
+	shift = 64 - rdt_resources_all[RDT_RESOURCE_MBA].membw.mbm_width;
 	chunks = (cur_msr << shift) - (prev_msr << shift);
 	return chunks >>= shift;
 }
 
-static int __mon_event_count(u32 rmid, struct rmid_read *rr)
+static u64 __mon_event_count(u32 rmid, struct rmid_read *rr)
 {
 	struct mbm_state *m;
 	u64 chunks, tval;
 
 	tval = __rmid_read(rmid, rr->evtid);
 	if (tval & (RMID_VAL_ERROR | RMID_VAL_UNAVAIL)) {
-		rr->val = tval;
-		return -EINVAL;
+		return tval;
 	}
 	switch (rr->evtid) {
 	case QOS_L3_OCCUP_EVENT_ID:
@@ -244,10 +244,10 @@
 		break;
 	default:
 		/*
-		 * Code would never reach here because
-		 * an invalid event id would fail the __rmid_read.
+		 * Code would never reach here because an invalid
+		 * event id would fail the __rmid_read.
 		 */
-		return -EINVAL;
+		return RMID_VAL_ERROR;
 	}
 
 	if (rr->first) {
@@ -279,8 +279,6 @@
 		return;
 
 	chunks = mbm_overflow_count(m->prev_bw_msr, tval);
-	m->chunks_bw += chunks;
-	m->chunks = m->chunks_bw;
 	cur_bw = (chunks * r->mon_scale) >> 20;
 
 	if (m->delta_comp)
@@ -299,23 +297,29 @@
 	struct rdtgroup *rdtgrp, *entry;
 	struct rmid_read *rr = info;
 	struct list_head *head;
+	u64 ret_val;
 
 	rdtgrp = rr->rgrp;
 
-	if (__mon_event_count(rdtgrp->mon.rmid, rr))
-		return;
+	ret_val = __mon_event_count(rdtgrp->mon.rmid, rr);
 
 	/*
-	 * For Ctrl groups read data from child monitor groups.
+	 * For Ctrl groups read data from child monitor groups and
+	 * add them together. Count events which are read successfully.
+	 * Discard the rmid_read's reporting errors.
 	 */
 	head = &rdtgrp->mon.crdtgrp_list;
 
 	if (rdtgrp->type == RDTCTRL_GROUP) {
 		list_for_each_entry(entry, head, mon.crdtgrp_list) {
-			if (__mon_event_count(entry->mon.rmid, rr))
-				return;
+			if (__mon_event_count(entry->mon.rmid, rr) == 0)
+				ret_val = 0;
 		}
 	}
+
+	/* Report error if none of rmid_reads are successful */
+	if (ret_val)
+		rr->val = ret_val;
 }
 
 /*
@@ -450,15 +454,14 @@
 	}
 	if (is_mbm_local_enabled()) {
 		rr.evtid = QOS_L3_MBM_LOCAL_EVENT_ID;
+		__mon_event_count(rmid, &rr);
 
 		/*
 		 * Call the MBA software controller only for the
 		 * control groups and when user has enabled
 		 * the software controller explicitly.
 		 */
-		if (!is_mba_sc(NULL))
-			__mon_event_count(rmid, &rr);
-		else
+		if (is_mba_sc(NULL))
 			mbm_bw_count(rmid, &rr);
 	}
 }
@@ -514,7 +517,7 @@
 
 	mutex_lock(&rdtgroup_mutex);
 
-	if (!static_branch_likely(&rdt_enable_key))
+	if (!static_branch_likely(&rdt_mon_enable_key))
 		goto out_unlock;
 
 	d = get_domain_from_cpu(cpu, &rdt_resources_all[RDT_RESOURCE_L3]);
@@ -543,7 +546,7 @@
 	unsigned long delay = msecs_to_jiffies(delay_ms);
 	int cpu;
 
-	if (!static_branch_likely(&rdt_enable_key))
+	if (!static_branch_likely(&rdt_mon_enable_key))
 		return;
 	cpu = cpumask_any(&dom->cpu_mask);
 	dom->mbm_work_cpu = cpu;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/cpu/resctrl/pseudo_lock.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/cpu/resctrl/pseudo_lock.c
@@ -416,6 +416,7 @@
 	struct pseudo_lock_region *plr = rdtgrp->plr;
 	u32 rmid_p, closid_p;
 	unsigned long i;
+	u64 saved_msr;
 #ifdef CONFIG_KASAN
 	/*
 	 * The registers used for local register variables are also used
@@ -459,6 +460,7 @@
 	 * the buffer and evict pseudo-locked memory read earlier from the
 	 * cache.
 	 */
+	saved_msr = __rdmsr(MSR_MISC_FEATURE_CONTROL);
 	__wrmsr(MSR_MISC_FEATURE_CONTROL, prefetch_disable_bits, 0x0);
 	closid_p = this_cpu_read(pqr_state.cur_closid);
 	rmid_p = this_cpu_read(pqr_state.cur_rmid);
@@ -510,7 +512,7 @@
 	__wrmsr(IA32_PQR_ASSOC, rmid_p, closid_p);
 
 	/* Re-enable the hardware prefetcher(s) */
-	wrmsr(MSR_MISC_FEATURE_CONTROL, 0x0, 0x0);
+	wrmsrl(MSR_MISC_FEATURE_CONTROL, saved_msr);
 	local_irq_enable();
 
 	plr->thread_done = 1;
@@ -867,6 +869,7 @@
 static int measure_cycles_lat_fn(void *_plr)
 {
 	struct pseudo_lock_region *plr = _plr;
+	u32 saved_low, saved_high;
 	unsigned long i;
 	u64 start, end;
 	void *mem_r;
@@ -875,6 +878,7 @@
 	/*
 	 * Disable hardware prefetchers.
 	 */
+	rdmsr(MSR_MISC_FEATURE_CONTROL, saved_low, saved_high);
 	wrmsr(MSR_MISC_FEATURE_CONTROL, prefetch_disable_bits, 0x0);
 	mem_r = READ_ONCE(plr->kmem);
 	/*
@@ -891,7 +895,7 @@
 		end = rdtsc_ordered();
 		trace_pseudo_lock_mem_latency((u32)(end - start));
 	}
-	wrmsr(MSR_MISC_FEATURE_CONTROL, 0x0, 0x0);
+	wrmsr(MSR_MISC_FEATURE_CONTROL, saved_low, saved_high);
 	local_irq_enable();
 	plr->thread_done = 1;
 	wake_up_interruptible(&plr->lock_thread_wq);
@@ -936,6 +940,7 @@
 	u64 hits_before = 0, hits_after = 0, miss_before = 0, miss_after = 0;
 	struct perf_event *miss_event, *hit_event;
 	int hit_pmcnum, miss_pmcnum;
+	u32 saved_low, saved_high;
 	unsigned int line_size;
 	unsigned int size;
 	unsigned long i;
@@ -969,6 +974,7 @@
 	/*
 	 * Disable hardware prefetchers.
 	 */
+	rdmsr(MSR_MISC_FEATURE_CONTROL, saved_low, saved_high);
 	wrmsr(MSR_MISC_FEATURE_CONTROL, prefetch_disable_bits, 0x0);
 
 	/* Initialize rest of local variables */
@@ -1027,7 +1033,7 @@
 	 */
 	rmb();
 	/* Re-enable hardware prefetchers */
-	wrmsr(MSR_MISC_FEATURE_CONTROL, 0x0, 0x0);
+	wrmsr(MSR_MISC_FEATURE_CONTROL, saved_low, saved_high);
 	local_irq_enable();
 out_hit:
 	perf_event_release_kernel(hit_event);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/cpu/resctrl/rdtgroup.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/cpu/resctrl/rdtgroup.c
@@ -311,7 +311,7 @@
 	 * executing task might have its own closid selected. Just reuse
 	 * the context switch code.
 	 */
-	resctrl_sched_in();
+	resctrl_sched_in(current);
 }
 
 /*
@@ -507,85 +507,102 @@
 	return ret ?: nbytes;
 }
 
-struct task_move_callback {
-	struct callback_head	work;
-	struct rdtgroup		*rdtgrp;
-};
-
-static void move_myself(struct callback_head *head)
+/**
+ * rdtgroup_remove - the helper to remove resource group safely
+ * @rdtgrp: resource group to remove
+ *
+ * On resource group creation via a mkdir, an extra kernfs_node reference is
+ * taken to ensure that the rdtgroup structure remains accessible for the
+ * rdtgroup_kn_unlock() calls where it is removed.
+ *
+ * Drop the extra reference here, then free the rdtgroup structure.
+ *
+ * Return: void
+ */
+static void rdtgroup_remove(struct rdtgroup *rdtgrp)
 {
-	struct task_move_callback *callback;
-	struct rdtgroup *rdtgrp;
-
-	callback = container_of(head, struct task_move_callback, work);
-	rdtgrp = callback->rdtgrp;
+	kernfs_put(rdtgrp->kn);
+	kfree(rdtgrp);
+}
 
+static void _update_task_closid_rmid(void *task)
+{
 	/*
-	 * If resource group was deleted before this task work callback
-	 * was invoked, then assign the task to root group and free the
-	 * resource group.
+	 * If the task is still current on this CPU, update PQR_ASSOC MSR.
+	 * Otherwise, the MSR is updated when the task is scheduled in.
 	 */
-	if (atomic_dec_and_test(&rdtgrp->waitcount) &&
-	    (rdtgrp->flags & RDT_DELETED)) {
-		current->closid = 0;
-		current->rmid = 0;
-		kfree(rdtgrp);
-	}
-
-	preempt_disable();
-	/* update PQR_ASSOC MSR to make resource group go into effect */
-	resctrl_sched_in();
-	preempt_enable();
+	if (task == current)
+		resctrl_sched_in(task);
+}
 
-	kfree(callback);
+static void update_task_closid_rmid(struct task_struct *t)
+{
+	if (IS_ENABLED(CONFIG_SMP) && task_curr(t))
+		smp_call_function_single(task_cpu(t), _update_task_closid_rmid, t, 1);
+	else
+		_update_task_closid_rmid(t);
 }
 
 static int __rdtgroup_move_task(struct task_struct *tsk,
 				struct rdtgroup *rdtgrp)
 {
-	struct task_move_callback *callback;
-	int ret;
-
-	callback = kzalloc(sizeof(*callback), GFP_KERNEL);
-	if (!callback)
-		return -ENOMEM;
-	callback->work.func = move_myself;
-	callback->rdtgrp = rdtgrp;
+	/* If the task is already in rdtgrp, no need to move the task. */
+	if ((rdtgrp->type == RDTCTRL_GROUP && tsk->closid == rdtgrp->closid &&
+	     tsk->rmid == rdtgrp->mon.rmid) ||
+	    (rdtgrp->type == RDTMON_GROUP && tsk->rmid == rdtgrp->mon.rmid &&
+	     tsk->closid == rdtgrp->mon.parent->closid))
+		return 0;
 
 	/*
-	 * Take a refcount, so rdtgrp cannot be freed before the
-	 * callback has been invoked.
+	 * Set the task's closid/rmid before the PQR_ASSOC MSR can be
+	 * updated by them.
+	 *
+	 * For ctrl_mon groups, move both closid and rmid.
+	 * For monitor groups, can move the tasks only from
+	 * their parent CTRL group.
 	 */
-	atomic_inc(&rdtgrp->waitcount);
-	ret = task_work_add(tsk, &callback->work, true);
-	if (ret) {
-		/*
-		 * Task is exiting. Drop the refcount and free the callback.
-		 * No need to check the refcount as the group cannot be
-		 * deleted before the write function unlocks rdtgroup_mutex.
-		 */
-		atomic_dec(&rdtgrp->waitcount);
-		kfree(callback);
-		rdt_last_cmd_puts("Task exited\n");
-	} else {
-		/*
-		 * For ctrl_mon groups move both closid and rmid.
-		 * For monitor groups, can move the tasks only from
-		 * their parent CTRL group.
-		 */
-		if (rdtgrp->type == RDTCTRL_GROUP) {
-			tsk->closid = rdtgrp->closid;
-			tsk->rmid = rdtgrp->mon.rmid;
-		} else if (rdtgrp->type == RDTMON_GROUP) {
-			if (rdtgrp->mon.parent->closid == tsk->closid) {
-				tsk->rmid = rdtgrp->mon.rmid;
-			} else {
-				rdt_last_cmd_puts("Can't move task to different control group\n");
-				ret = -EINVAL;
-			}
+
+	if (rdtgrp->type == RDTCTRL_GROUP) {
+		WRITE_ONCE(tsk->closid, rdtgrp->closid);
+		WRITE_ONCE(tsk->rmid, rdtgrp->mon.rmid);
+	} else if (rdtgrp->type == RDTMON_GROUP) {
+		if (rdtgrp->mon.parent->closid == tsk->closid) {
+			WRITE_ONCE(tsk->rmid, rdtgrp->mon.rmid);
+		} else {
+			rdt_last_cmd_puts("Can't move task to different control group\n");
+			return -EINVAL;
 		}
 	}
-	return ret;
+
+	/*
+	 * Ensure the task's closid and rmid are written before determining if
+	 * the task is current that will decide if it will be interrupted.
+	 * This pairs with the full barrier between the rq->curr update and
+	 * resctrl_sched_in() during context switch.
+	 */
+	smp_mb();
+
+	/*
+	 * By now, the task's closid and rmid are set. If the task is current
+	 * on a CPU, the PQR_ASSOC MSR needs to be updated to make the resource
+	 * group go into effect. If the task is not current, the MSR will be
+	 * updated when the task is scheduled in.
+	 */
+	update_task_closid_rmid(tsk);
+
+	return 0;
+}
+
+static bool is_closid_match(struct task_struct *t, struct rdtgroup *r)
+{
+	return (rdt_alloc_capable &&
+	       (r->type == RDTCTRL_GROUP) && (t->closid == r->closid));
+}
+
+static bool is_rmid_match(struct task_struct *t, struct rdtgroup *r)
+{
+	return (rdt_mon_capable &&
+	       (r->type == RDTMON_GROUP) && (t->rmid == r->mon.rmid));
 }
 
 /**
@@ -603,8 +620,7 @@
 
 	rcu_read_lock();
 	for_each_process_thread(p, t) {
-		if ((r->type == RDTCTRL_GROUP && t->closid == r->closid) ||
-		    (r->type == RDTMON_GROUP && t->rmid == r->mon.rmid)) {
+		if (is_closid_match(t, r) || is_rmid_match(t, r)) {
 			ret = 1;
 			break;
 		}
@@ -699,12 +715,15 @@
 static void show_rdt_tasks(struct rdtgroup *r, struct seq_file *s)
 {
 	struct task_struct *p, *t;
+	pid_t pid;
 
 	rcu_read_lock();
 	for_each_process_thread(p, t) {
-		if ((r->type == RDTCTRL_GROUP && t->closid == r->closid) ||
-		    (r->type == RDTMON_GROUP && t->rmid == r->mon.rmid))
-			seq_printf(s, "%d\n", t->pid);
+		if (is_closid_match(t, r) || is_rmid_match(t, r)) {
+			pid = task_pid_vnr(t);
+			if (pid)
+				seq_printf(s, "%d\n", pid);
+		}
 	}
 	rcu_read_unlock();
 }
@@ -1027,6 +1046,7 @@
 	_d_cdp = rdt_find_domain(_r_cdp, d->id, NULL);
 	if (WARN_ON(IS_ERR_OR_NULL(_d_cdp))) {
 		_r_cdp = NULL;
+		_d_cdp = NULL;
 		ret = -EINVAL;
 	}
 
@@ -1617,7 +1637,6 @@
 	if (IS_ERR(kn_subdir))
 		return PTR_ERR(kn_subdir);
 
-	kernfs_get(kn_subdir);
 	ret = rdtgroup_kn_set_ugid(kn_subdir);
 	if (ret)
 		return ret;
@@ -1640,7 +1659,6 @@
 	kn_info = kernfs_create_dir(parent_kn, "info", parent_kn->mode, NULL);
 	if (IS_ERR(kn_info))
 		return PTR_ERR(kn_info);
-	kernfs_get(kn_info);
 
 	ret = rdtgroup_add_files(kn_info, RF_TOP_INFO);
 	if (ret)
@@ -1661,12 +1679,6 @@
 			goto out_destroy;
 	}
 
-	/*
-	 * This extra ref will be put in kernfs_remove() and guarantees
-	 * that @rdtgrp->kn is always accessible.
-	 */
-	kernfs_get(kn_info);
-
 	ret = rdtgroup_kn_set_ugid(kn_info);
 	if (ret)
 		goto out_destroy;
@@ -1695,12 +1707,6 @@
 	if (dest_kn)
 		*dest_kn = kn;
 
-	/*
-	 * This extra ref will be put in kernfs_remove() and guarantees
-	 * that @rdtgrp->kn is always accessible.
-	 */
-	kernfs_get(kn);
-
 	ret = rdtgroup_kn_set_ugid(kn);
 	if (ret)
 		goto out_destroy;
@@ -1741,9 +1747,6 @@
 	struct rdt_domain *d;
 	int cpu;
 
-	if (!zalloc_cpumask_var(&cpu_mask, GFP_KERNEL))
-		return -ENOMEM;
-
 	if (level == RDT_RESOURCE_L3)
 		update = l3_qos_cfg_update;
 	else if (level == RDT_RESOURCE_L2)
@@ -1751,6 +1754,9 @@
 	else
 		return -EINVAL;
 
+	if (!zalloc_cpumask_var(&cpu_mask, GFP_KERNEL))
+		return -ENOMEM;
+
 	r_l = &rdt_resources_all[level];
 	list_for_each_entry(d, &r_l->domains, list) {
 		/* Pick one CPU from each domain instance to update MSR */
@@ -1769,6 +1775,19 @@
 	return 0;
 }
 
+/* Restore the qos cfg state when a domain comes online */
+void rdt_domain_reconfigure_cdp(struct rdt_resource *r)
+{
+	if (!r->alloc_capable)
+		return;
+
+	if (r == &rdt_resources_all[RDT_RESOURCE_L2DATA])
+		l2_qos_cfg_update(&r->alloc_enabled);
+
+	if (r == &rdt_resources_all[RDT_RESOURCE_L3DATA])
+		l3_qos_cfg_update(&r->alloc_enabled);
+}
+
 /*
  * Enable or disable the MBA software controller
  * which helps user specify bandwidth in MBps.
@@ -1914,8 +1933,7 @@
 		    rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED)
 			rdtgroup_pseudo_lock_remove(rdtgrp);
 		kernfs_unbreak_active_protection(kn);
-		kernfs_put(rdtgrp->kn);
-		kfree(rdtgrp);
+		rdtgroup_remove(rdtgrp);
 	} else {
 		kernfs_unbreak_active_protection(kn);
 	}
@@ -1970,17 +1988,15 @@
 
 	if (rdt_mon_capable) {
 		ret = mongroup_create_dir(rdtgroup_default.kn,
-					  NULL, "mon_groups",
+					  &rdtgroup_default, "mon_groups",
 					  &kn_mongrp);
 		if (ret < 0)
 			goto out_info;
-		kernfs_get(kn_mongrp);
 
 		ret = mkdir_mondata_all(rdtgroup_default.kn,
 					&rdtgroup_default, &kn_mondata);
 		if (ret < 0)
 			goto out_mongrp;
-		kernfs_get(kn_mondata);
 		rdtgroup_default.mon.mon_data_kn = kn_mondata;
 	}
 
@@ -2146,18 +2162,6 @@
 	return 0;
 }
 
-static bool is_closid_match(struct task_struct *t, struct rdtgroup *r)
-{
-	return (rdt_alloc_capable &&
-		(r->type == RDTCTRL_GROUP) && (t->closid == r->closid));
-}
-
-static bool is_rmid_match(struct task_struct *t, struct rdtgroup *r)
-{
-	return (rdt_mon_capable &&
-		(r->type == RDTMON_GROUP) && (t->rmid == r->mon.rmid));
-}
-
 /*
  * Move tasks from one to the other group. If @from is NULL, then all tasks
  * in the systems are moved unconditionally (used for teardown).
@@ -2175,22 +2179,26 @@
 	for_each_process_thread(p, t) {
 		if (!from || is_closid_match(t, from) ||
 		    is_rmid_match(t, from)) {
-			t->closid = to->closid;
-			t->rmid = to->mon.rmid;
+			WRITE_ONCE(t->closid, to->closid);
+			WRITE_ONCE(t->rmid, to->mon.rmid);
 
-#ifdef CONFIG_SMP
 			/*
-			 * This is safe on x86 w/o barriers as the ordering
-			 * of writing to task_cpu() and t->on_cpu is
-			 * reverse to the reading here. The detection is
-			 * inaccurate as tasks might move or schedule
-			 * before the smp function call takes place. In
-			 * such a case the function call is pointless, but
+			 * Order the closid/rmid stores above before the loads
+			 * in task_curr(). This pairs with the full barrier
+			 * between the rq->curr update and resctrl_sched_in()
+			 * during context switch.
+			 */
+			smp_mb();
+
+			/*
+			 * If the task is on a CPU, set the CPU in the mask.
+			 * The detection is inaccurate as tasks might move or
+			 * schedule before the smp function call takes place.
+			 * In such a case the function call is pointless, but
 			 * there is no other side effect.
 			 */
-			if (mask && t->on_cpu)
+			if (IS_ENABLED(CONFIG_SMP) && mask && task_curr(t))
 				cpumask_set_cpu(task_cpu(t), mask);
-#endif
 		}
 	}
 	read_unlock(&tasklist_lock);
@@ -2205,7 +2213,11 @@
 	list_for_each_entry_safe(sentry, stmp, head, mon.crdtgrp_list) {
 		free_rmid(sentry->mon.rmid);
 		list_del(&sentry->mon.crdtgrp_list);
-		kfree(sentry);
+
+		if (atomic_read(&sentry->waitcount) != 0)
+			sentry->flags = RDT_DELETED;
+		else
+			rdtgroup_remove(sentry);
 	}
 }
 
@@ -2243,7 +2255,11 @@
 
 		kernfs_remove(rdtgrp->kn);
 		list_del(&rdtgrp->rdtgroup_list);
-		kfree(rdtgrp);
+
+		if (atomic_read(&rdtgrp->waitcount) != 0)
+			rdtgrp->flags = RDT_DELETED;
+		else
+			rdtgroup_remove(rdtgrp);
 	}
 	/* Notify online CPUs to update per cpu storage and PQR_ASSOC MSR */
 	update_closid_rmid(cpu_online_mask, &rdtgroup_default);
@@ -2343,11 +2359,6 @@
 	if (IS_ERR(kn))
 		return PTR_ERR(kn);
 
-	/*
-	 * This extra ref will be put in kernfs_remove() and guarantees
-	 * that kn is always accessible.
-	 */
-	kernfs_get(kn);
 	ret = rdtgroup_kn_set_ugid(kn);
 	if (ret)
 		goto out_destroy;
@@ -2446,7 +2457,7 @@
 	/*
 	 * Create the mon_data directory first.
 	 */
-	ret = mongroup_create_dir(parent_kn, NULL, "mon_data", &kn);
+	ret = mongroup_create_dir(parent_kn, prgrp, "mon_data", &kn);
 	if (ret)
 		return ret;
 
@@ -2645,7 +2656,7 @@
 	uint files = 0;
 	int ret;
 
-	prdtgrp = rdtgroup_kn_lock_live(prgrp_kn);
+	prdtgrp = rdtgroup_kn_lock_live(parent_kn);
 	if (!prdtgrp) {
 		ret = -ENODEV;
 		goto out_unlock;
@@ -2683,8 +2694,8 @@
 	/*
 	 * kernfs_remove() will drop the reference count on "kn" which
 	 * will free it. But we still need it to stick around for the
-	 * rdtgroup_kn_unlock(kn} call below. Take one extra reference
-	 * here, which will be dropped inside rdtgroup_kn_unlock().
+	 * rdtgroup_kn_unlock(kn) call. Take one extra reference here,
+	 * which will be dropped by kernfs_put() in rdtgroup_remove().
 	 */
 	kernfs_get(kn);
 
@@ -2718,18 +2729,19 @@
 	kernfs_activate(kn);
 
 	/*
-	 * The caller unlocks the prgrp_kn upon success.
+	 * The caller unlocks the parent_kn upon success.
 	 */
 	return 0;
 
 out_idfree:
 	free_rmid(rdtgrp->mon.rmid);
 out_destroy:
+	kernfs_put(rdtgrp->kn);
 	kernfs_remove(rdtgrp->kn);
 out_free_rgrp:
 	kfree(rdtgrp);
 out_unlock:
-	rdtgroup_kn_unlock(prgrp_kn);
+	rdtgroup_kn_unlock(parent_kn);
 	return ret;
 }
 
@@ -2737,7 +2749,7 @@
 {
 	kernfs_remove(rgrp->kn);
 	free_rmid(rgrp->mon.rmid);
-	kfree(rgrp);
+	rdtgroup_remove(rgrp);
 }
 
 /*
@@ -2767,7 +2779,7 @@
 	 */
 	list_add_tail(&rdtgrp->mon.crdtgrp_list, &prgrp->mon.crdtgrp_list);
 
-	rdtgroup_kn_unlock(prgrp_kn);
+	rdtgroup_kn_unlock(parent_kn);
 	return ret;
 }
 
@@ -2810,7 +2822,7 @@
 		 * Create an empty mon_groups directory to hold the subset
 		 * of tasks and cpus to monitor.
 		 */
-		ret = mongroup_create_dir(kn, NULL, "mon_groups", NULL);
+		ret = mongroup_create_dir(kn, rdtgrp, "mon_groups", NULL);
 		if (ret) {
 			rdt_last_cmd_puts("kernfs subdir error\n");
 			goto out_del_list;
@@ -2826,7 +2838,7 @@
 out_common_fail:
 	mkdir_rdt_prepare_clean(rdtgrp);
 out_unlock:
-	rdtgroup_kn_unlock(prgrp_kn);
+	rdtgroup_kn_unlock(parent_kn);
 	return ret;
 }
 
@@ -2899,11 +2911,6 @@
 	WARN_ON(list_empty(&prdtgrp->mon.crdtgrp_list));
 	list_del(&rdtgrp->mon.crdtgrp_list);
 
-	/*
-	 * one extra hold on this, will drop when we kfree(rdtgrp)
-	 * in rdtgroup_kn_unlock()
-	 */
-	kernfs_get(kn);
 	kernfs_remove(rdtgrp->kn);
 
 	return 0;
@@ -2915,11 +2922,6 @@
 	rdtgrp->flags = RDT_DELETED;
 	list_del(&rdtgrp->rdtgroup_list);
 
-	/*
-	 * one extra hold on this, will drop when we kfree(rdtgrp)
-	 * in rdtgroup_kn_unlock()
-	 */
-	kernfs_get(kn);
 	kernfs_remove(rdtgrp->kn);
 	return 0;
 }
@@ -2952,13 +2954,13 @@
 	closid_free(rdtgrp->closid);
 	free_rmid(rdtgrp->mon.rmid);
 
+	rdtgroup_ctrl_remove(kn, rdtgrp);
+
 	/*
 	 * Free all the child monitor group rmids.
 	 */
 	free_all_child_rdtgrp(rdtgrp);
 
-	rdtgroup_ctrl_remove(kn, rdtgrp);
-
 	return 0;
 }
 
@@ -2985,7 +2987,8 @@
 	 * If the rdtgroup is a mon group and parent directory
 	 * is a valid "mon_groups" directory, remove the mon group.
 	 */
-	if (rdtgrp->type == RDTCTRL_GROUP && parent_kn == rdtgroup_default.kn) {
+	if (rdtgrp->type == RDTCTRL_GROUP && parent_kn == rdtgroup_default.kn &&
+	    rdtgrp != &rdtgroup_default) {
 		if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP ||
 		    rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED) {
 			ret = rdtgroup_ctrl_remove(kn, rdtgrp);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/cpu/scattered.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/cpu/scattered.c
@@ -26,6 +26,8 @@
 static const struct cpuid_bit cpuid_bits[] = {
 	{ X86_FEATURE_APERFMPERF,       CPUID_ECX,  0, 0x00000006, 0 },
 	{ X86_FEATURE_EPB,		CPUID_ECX,  3, 0x00000006, 0 },
+	{ X86_FEATURE_RRSBA_CTRL,	CPUID_EDX,  2, 0x00000007, 2 },
+	{ X86_FEATURE_BHI_CTRL,		CPUID_EDX,  4, 0x00000007, 2 },
 	{ X86_FEATURE_CQM_LLC,		CPUID_EDX,  1, 0x0000000f, 0 },
 	{ X86_FEATURE_CQM_OCCUP_LLC,	CPUID_EDX,  0, 0x0000000f, 1 },
 	{ X86_FEATURE_CQM_MBM_TOTAL,	CPUID_EDX,  1, 0x0000000f, 1 },
@@ -39,8 +41,6 @@
 	{ X86_FEATURE_CPB,		CPUID_EDX,  9, 0x80000007, 0 },
 	{ X86_FEATURE_PROC_FEEDBACK,    CPUID_EDX, 11, 0x80000007, 0 },
 	{ X86_FEATURE_MBA,		CPUID_EBX,  6, 0x80000008, 0 },
-	{ X86_FEATURE_SME,		CPUID_EAX,  0, 0x8000001f, 0 },
-	{ X86_FEATURE_SEV,		CPUID_EAX,  1, 0x8000001f, 0 },
 	{ 0, 0, 0, 0, 0 }
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/cpu/topology.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/cpu/topology.c
@@ -25,10 +25,10 @@
 #define BITS_SHIFT_NEXT_LEVEL(eax)	((eax) & 0x1f)
 #define LEVEL_MAX_SIBLINGS(ebx)		((ebx) & 0xffff)
 
-#ifdef CONFIG_SMP
 unsigned int __max_die_per_package __read_mostly = 1;
 EXPORT_SYMBOL(__max_die_per_package);
 
+#ifdef CONFIG_SMP
 /*
  * Check if given CPUID extended toplogy "leaf" is implemented
  */
@@ -79,7 +79,7 @@
 	 * initial apic id, which also represents 32-bit extended x2apic id.
 	 */
 	c->initial_apicid = edx;
-	smp_num_siblings = LEVEL_MAX_SIBLINGS(ebx);
+	smp_num_siblings = max_t(int, smp_num_siblings, LEVEL_MAX_SIBLINGS(ebx));
 #endif
 	return 0;
 }
@@ -107,7 +107,8 @@
 	 */
 	cpuid_count(leaf, SMT_LEVEL, &eax, &ebx, &ecx, &edx);
 	c->initial_apicid = edx;
-	core_level_siblings = smp_num_siblings = LEVEL_MAX_SIBLINGS(ebx);
+	core_level_siblings = LEVEL_MAX_SIBLINGS(ebx);
+	smp_num_siblings = max_t(int, smp_num_siblings, LEVEL_MAX_SIBLINGS(ebx));
 	core_plus_mask_width = ht_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
 	die_level_siblings = LEVEL_MAX_SIBLINGS(ebx);
 	die_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/cpu/tsx.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/cpu/tsx.c
@@ -55,24 +55,6 @@
 	wrmsrl(MSR_IA32_TSX_CTRL, tsx);
 }
 
-static bool __init tsx_ctrl_is_supported(void)
-{
-	u64 ia32_cap = x86_read_arch_cap_msr();
-
-	/*
-	 * TSX is controlled via MSR_IA32_TSX_CTRL.  However, support for this
-	 * MSR is enumerated by ARCH_CAP_TSX_MSR bit in MSR_IA32_ARCH_CAPABILITIES.
-	 *
-	 * TSX control (aka MSR_IA32_TSX_CTRL) is only available after a
-	 * microcode update on CPUs that have their MSR_IA32_ARCH_CAPABILITIES
-	 * bit MDS_NO=1. CPUs with MDS_NO=0 are not planned to get
-	 * MSR_IA32_TSX_CTRL support even after a microcode update. Thus,
-	 * tsx= cmdline requests will do nothing on CPUs without
-	 * MSR_IA32_TSX_CTRL support.
-	 */
-	return !!(ia32_cap & ARCH_CAP_TSX_CTRL_MSR);
-}
-
 static enum tsx_ctrl_states x86_get_tsx_auto_mode(void)
 {
 	if (boot_cpu_has_bug(X86_BUG_TAA))
@@ -86,9 +68,22 @@
 	char arg[5] = {};
 	int ret;
 
-	if (!tsx_ctrl_is_supported())
+	/*
+	 * TSX is controlled via MSR_IA32_TSX_CTRL.  However, support for this
+	 * MSR is enumerated by ARCH_CAP_TSX_MSR bit in MSR_IA32_ARCH_CAPABILITIES.
+	 *
+	 * TSX control (aka MSR_IA32_TSX_CTRL) is only available after a
+	 * microcode update on CPUs that have their MSR_IA32_ARCH_CAPABILITIES
+	 * bit MDS_NO=1. CPUs with MDS_NO=0 are not planned to get
+	 * MSR_IA32_TSX_CTRL support even after a microcode update. Thus,
+	 * tsx= cmdline requests will do nothing on CPUs without
+	 * MSR_IA32_TSX_CTRL support.
+	 */
+	if (!(x86_read_arch_cap_msr() & ARCH_CAP_TSX_CTRL_MSR))
 		return;
 
+	setup_force_cpu_cap(X86_FEATURE_MSR_TSX_CTRL);
+
 	ret = cmdline_find_option(boot_command_line, "tsx", arg, sizeof(arg));
 	if (ret >= 0) {
 		if (!strcmp(arg, "on")) {
@@ -115,11 +110,12 @@
 		tsx_disable();
 
 		/*
-		 * tsx_disable() will change the state of the
-		 * RTM CPUID bit.  Clear it here since it is now
-		 * expected to be not set.
+		 * tsx_disable() will change the state of the RTM and HLE CPUID
+		 * bits. Clear them here since they are now expected to be not
+		 * set.
 		 */
 		setup_clear_cpu_cap(X86_FEATURE_RTM);
+		setup_clear_cpu_cap(X86_FEATURE_HLE);
 	} else if (tsx_ctrl_state == TSX_CTRL_ENABLE) {
 
 		/*
@@ -131,10 +127,10 @@
 		tsx_enable();
 
 		/*
-		 * tsx_enable() will change the state of the
-		 * RTM CPUID bit.  Force it here since it is now
-		 * expected to be set.
+		 * tsx_enable() will change the state of the RTM and HLE CPUID
+		 * bits. Force them here since they are now expected to be set.
 		 */
 		setup_force_cpu_cap(X86_FEATURE_RTM);
+		setup_force_cpu_cap(X86_FEATURE_HLE);
 	}
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/cpu/umwait.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/cpu/umwait.c
@@ -17,12 +17,6 @@
  */
 static u32 umwait_control_cached = UMWAIT_CTRL_VAL(100000, UMWAIT_C02_ENABLE);
 
-u32 get_umwait_control_msr(void)
-{
-	return umwait_control_cached;
-}
-EXPORT_SYMBOL_GPL(get_umwait_control_msr);
-
 /*
  * Cache the original IA32_UMWAIT_CONTROL MSR value which is configured by
  * hardware or BIOS before kernel boot.
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/crash.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/crash.c
@@ -24,6 +24,7 @@
 #include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
+#include <linux/memblock.h>
 
 #include <asm/processor.h>
 #include <asm/hardirq.h>
@@ -36,9 +37,9 @@
 #include <linux/kdebug.h>
 #include <asm/cpu.h>
 #include <asm/reboot.h>
-#include <asm/virtext.h>
 #include <asm/intel_pt.h>
 #include <asm/crash.h>
+#include <asm/cmdline.h>
 
 /* Used while preparing memory map entries for second kernel */
 struct crash_memmap_data {
@@ -68,6 +69,19 @@
 	rcu_read_unlock();
 }
 
+/*
+ * When the crashkernel option is specified, only use the low
+ * 1M for the real mode trampoline.
+ */
+void __init crash_reserve_low_1M(void)
+{
+	if (cmdline_find_option(boot_command_line, "crashkernel", NULL, 0) < 0)
+		return;
+
+	memblock_reserve(0, 1<<20);
+	pr_info("Reserving the low 1M of memory for crashkernel\n");
+}
+
 #if defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC)
 
 static void kdump_nmi_callback(int cpu, struct pt_regs *regs)
@@ -79,15 +93,6 @@
 	 */
 	cpu_crash_vmclear_loaded_vmcss();
 
-	/* Disable VMX or SVM if needed.
-	 *
-	 * We need to disable virtualization on all CPUs.
-	 * Having VMX or SVM enabled on any CPU may break rebooting
-	 * after the kdump kernel has finished its task.
-	 */
-	cpu_emergency_vmxoff();
-	cpu_emergency_svm_disable();
-
 	/*
 	 * Disable Intel PT to stop its logging
 	 */
@@ -146,12 +151,7 @@
 	 */
 	cpu_crash_vmclear_loaded_vmcss();
 
-	/* Booting kdump kernel with VMX or SVM enabled won't work,
-	 * because (among other limitations) we can't disable paging
-	 * with the virt flags.
-	 */
-	cpu_emergency_vmxoff();
-	cpu_emergency_svm_disable();
+	cpu_emergency_disable_virtualization();
 
 	/*
 	 * Disable Intel PT to stop its logging
@@ -349,7 +349,7 @@
 	struct crash_memmap_data cmd;
 	struct crash_mem *cmem;
 
-	cmem = vzalloc(sizeof(struct crash_mem));
+	cmem = vzalloc(struct_size(cmem, ranges, 1));
 	if (!cmem)
 		return -ENOMEM;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/devicetree.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/devicetree.c
@@ -91,7 +91,7 @@
 
 	ret = pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
 	if (ret)
-		return ret;
+		return pcibios_err_to_errno(ret);
 	if (!pin)
 		return 0;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/doublefault.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/doublefault.c
@@ -65,6 +65,9 @@
 	.ss		= __KERNEL_DS,
 	.ds		= __USER_DS,
 	.fs		= __KERNEL_PERCPU,
+#ifndef CONFIG_X86_32_LAZY_GS
+	.gs		= __KERNEL_STACK_CANARY,
+#endif
 
 	.__cr3		= __pa_nodebug(swapper_pg_dir),
 };
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/dumpstack.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/dumpstack.c
@@ -171,7 +171,7 @@
 	printk("%sCall Trace:\n", log_lvl);
 
 	unwind_start(&state, task, regs, stack);
-	stack = stack ? : get_stack_pointer(task, regs);
+	stack = stack ?: get_stack_pointer(task, regs);
 	regs = unwind_get_entry_regs(&state, &partial);
 
 	/*
@@ -190,9 +190,11 @@
 	 * - hardirq stack
 	 * - entry stack
 	 */
-	for ( ; stack; stack = PTR_ALIGN(stack_info.next_sp, sizeof(long))) {
+	for (; stack; stack = stack_info.next_sp) {
 		const char *stack_name;
 
+		stack = PTR_ALIGN(stack, sizeof(long));
+
 		if (get_stack_info(stack, task, &stack_info, &visit_mask)) {
 			/*
 			 * We weren't on a valid stack.  It's possible that
@@ -326,7 +328,7 @@
 }
 NOKPROBE_SYMBOL(oops_begin);
 
-void __noreturn rewind_stack_do_exit(int signr);
+void __noreturn rewind_stack_and_make_dead(int signr);
 
 void oops_end(unsigned long flags, struct pt_regs *regs, int signr)
 {
@@ -361,7 +363,7 @@
 	 * reuse the task stack and that existing poisons are invalid.
 	 */
 	kasan_unpoison_task_stack(current);
-	rewind_stack_do_exit(signr);
+	rewind_stack_and_make_dead(signr);
 }
 NOKPROBE_SYMBOL(oops_end);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/early-quirks.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/early-quirks.c
@@ -28,6 +28,37 @@
 #include <asm/irq_remapping.h>
 #include <asm/early_ioremap.h>
 
+static void __init early_pci_clear_msi(int bus, int slot, int func)
+{
+	int pos;
+	u16 ctrl;
+
+	if (likely(!pci_early_clear_msi))
+		return;
+
+	pr_info_once("Clearing MSI/MSI-X enable bits early in boot (quirk)\n");
+
+	pos = pci_early_find_cap(bus, slot, func, PCI_CAP_ID_MSI);
+	if (pos) {
+		ctrl = read_pci_config_16(bus, slot, func, pos + PCI_MSI_FLAGS);
+		ctrl &= ~PCI_MSI_FLAGS_ENABLE;
+		write_pci_config_16(bus, slot, func, pos + PCI_MSI_FLAGS, ctrl);
+
+		/* Read again to flush previous write */
+		ctrl = read_pci_config_16(bus, slot, func, pos + PCI_MSI_FLAGS);
+	}
+
+	pos = pci_early_find_cap(bus, slot, func, PCI_CAP_ID_MSIX);
+	if (pos) {
+		ctrl = read_pci_config_16(bus, slot, func, pos + PCI_MSIX_FLAGS);
+		ctrl &= ~PCI_MSIX_FLAGS_ENABLE;
+		write_pci_config_16(bus, slot, func, pos + PCI_MSIX_FLAGS, ctrl);
+
+		/* Read again to flush previous write */
+		ctrl = read_pci_config_16(bus, slot, func, pos + PCI_MSIX_FLAGS);
+	}
+}
+
 static void __init fix_hypertransport_config(int num, int slot, int func)
 {
 	u32 htcfg;
@@ -515,6 +546,7 @@
 	.stolen_size = gen9_stolen_size,
 };
 
+/* Intel integrated GPUs for which we need to reserve "stolen memory" */
 static const struct pci_device_id intel_early_ids[] __initconst = {
 	INTEL_I830_IDS(&i830_early_ops),
 	INTEL_I845G_IDS(&i845_early_ops),
@@ -587,6 +619,13 @@
 	u16 device;
 	int i;
 
+	/*
+	 * Reserve "stolen memory" for an integrated GPU.  If we've already
+	 * found one, there's nothing to do for other (discrete) GPUs.
+	 */
+	if (resource_size(&intel_graphics_stolen_res))
+		return;
+
 	device = read_pci_config_16(num, slot, func, PCI_DEVICE_ID);
 
 	for (i = 0; i < ARRAY_SIZE(intel_early_ids); i++) {
@@ -699,7 +738,7 @@
 	{ PCI_VENDOR_ID_INTEL, 0x3406, PCI_CLASS_BRIDGE_HOST,
 	  PCI_BASE_CLASS_BRIDGE, 0, intel_remapping_check },
 	{ PCI_VENDOR_ID_INTEL, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA, PCI_ANY_ID,
-	  QFLAG_APPLY_ONCE, intel_graphics_quirks },
+	  0, intel_graphics_quirks },
 	/*
 	 * HPET on the current version of the Baytrail platform has accuracy
 	 * problems: it will halt in deep idle state - so we disable it.
@@ -710,10 +749,9 @@
 	 */
 	{ PCI_VENDOR_ID_INTEL, 0x0f00,
 		PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, 0, force_disable_hpet},
-	{ PCI_VENDOR_ID_INTEL, 0x3ec4,
-		PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, 0, force_disable_hpet},
 	{ PCI_VENDOR_ID_BROADCOM, 0x4331,
 	  PCI_CLASS_NETWORK_OTHER, PCI_ANY_ID, 0, apple_airport_reset},
+	{ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, early_pci_clear_msi},
 	{}
 };
 
@@ -766,6 +804,10 @@
 				    PCI_HEADER_TYPE);
 
 	if ((type & 0x7f) == PCI_HEADER_TYPE_BRIDGE) {
+		/* pci_early_clear_msi scans the buses differently. */
+		if (pci_early_clear_msi)
+			return -1;
+
 		sec = read_pci_config_byte(num, slot, func, PCI_SECONDARY_BUS);
 		if (sec > num)
 			early_pci_scan_bus(sec);
@@ -792,8 +834,13 @@
 
 void __init early_quirks(void)
 {
+	int bus;
+
 	if (!early_pci_allowed())
 		return;
 
 	early_pci_scan_bus(0);
+	/* pci_early_clear_msi scans more buses. */
+	for (bus = 1; pci_early_clear_msi && bus < 256; bus++)
+		early_pci_scan_bus(bus);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/fpu/core.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/fpu/core.c
@@ -82,7 +82,7 @@
 }
 EXPORT_SYMBOL(irq_fpu_usable);
 
-void kernel_fpu_begin(void)
+void kernel_fpu_begin_mask(unsigned int kfpu_mask)
 {
 	preempt_disable();
 
@@ -101,8 +101,15 @@
 		copy_fpregs_to_fpstate(&current->thread.fpu);
 	}
 	__cpu_invalidate_fpregs_state();
+
+	/* Put sane initial values into the control registers. */
+	if (likely(kfpu_mask & KFPU_MXCSR) && boot_cpu_has(X86_FEATURE_XMM))
+		ldmxcsr(MXCSR_DEFAULT);
+
+	if (unlikely(kfpu_mask & KFPU_387) && boot_cpu_has(X86_FEATURE_FPU))
+		asm volatile ("fninit");
 }
-EXPORT_SYMBOL_GPL(kernel_fpu_begin);
+EXPORT_SYMBOL_GPL(kernel_fpu_begin_mask);
 
 void kernel_fpu_end(void)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/fpu/init.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/fpu/init.c
@@ -50,7 +50,7 @@
 	fpu__init_cpu_xstate();
 }
 
-static bool fpu__probe_without_cpuid(void)
+static bool __init fpu__probe_without_cpuid(void)
 {
 	unsigned long cr0;
 	u16 fsw, fcw;
@@ -68,7 +68,7 @@
 	return fsw == 0 && (fcw & 0x103f) == 0x003f;
 }
 
-static void fpu__init_system_early_generic(struct cpuinfo_x86 *c)
+static void __init fpu__init_system_early_generic(void)
 {
 	if (!boot_cpu_has(X86_FEATURE_CPUID) &&
 	    !test_bit(X86_FEATURE_FPU, (unsigned long *)cpu_caps_cleared)) {
@@ -139,9 +139,6 @@
 unsigned int fpu_kernel_xstate_size;
 EXPORT_SYMBOL_GPL(fpu_kernel_xstate_size);
 
-/* Get alignment of the TYPE. */
-#define TYPE_ALIGN(TYPE) offsetof(struct { char x; TYPE test; }, test)
-
 /*
  * Enforce that 'MEMBER' is the last field of 'TYPE'.
  *
@@ -149,8 +146,8 @@
  * because that's how C aligns structs.
  */
 #define CHECK_MEMBER_AT_END_OF(TYPE, MEMBER) \
-	BUILD_BUG_ON(sizeof(TYPE) != ALIGN(offsetofend(TYPE, MEMBER), \
-					   TYPE_ALIGN(TYPE)))
+	BUILD_BUG_ON(sizeof(TYPE) !=         \
+		     ALIGN(offsetofend(TYPE, MEMBER), _Alignof(TYPE)))
 
 /*
  * We append the 'struct fpu' to the task_struct:
@@ -242,9 +239,9 @@
  */
 static void __init fpu__init_parse_early_param(void)
 {
-	char arg[32];
+	char arg[128];
 	char *argptr = arg;
-	int bit;
+	int arglen, res, bit;
 
 #ifdef CONFIG_X86_32
 	if (cmdline_find_option_bool(boot_command_line, "no387"))
@@ -267,22 +264,36 @@
 	if (cmdline_find_option_bool(boot_command_line, "noxsaves"))
 		setup_clear_cpu_cap(X86_FEATURE_XSAVES);
 
-	if (cmdline_find_option(boot_command_line, "clearcpuid", arg,
-				sizeof(arg)) &&
-	    get_option(&argptr, &bit) &&
-	    bit >= 0 &&
-	    bit < NCAPINTS * 32)
-		setup_clear_cpu_cap(bit);
+	arglen = cmdline_find_option(boot_command_line, "clearcpuid", arg, sizeof(arg));
+	if (arglen <= 0)
+		return;
+
+	pr_info("Clearing CPUID bits:");
+	do {
+		res = get_option(&argptr, &bit);
+		if (res == 0 || res == 3)
+			break;
+
+		/* If the argument was too long, the last bit may be cut off */
+		if (res == 1 && arglen >= sizeof(arg))
+			break;
+
+		if (bit >= 0 && bit < NCAPINTS * 32) {
+			pr_cont(" " X86_CAP_FMT, x86_cap_flag(bit));
+			setup_clear_cpu_cap(bit);
+		}
+	} while (res == 2);
+	pr_cont("\n");
 }
 
 /*
  * Called on the boot CPU once per system bootup, to set up the initial
  * FPU state that is later cloned into all processes:
  */
-void __init fpu__init_system(struct cpuinfo_x86 *c)
+void __init fpu__init_system(void)
 {
 	fpu__init_parse_early_param();
-	fpu__init_system_early_generic(c);
+	fpu__init_system_early_generic();
 
 	/*
 	 * The FPU has to be operational for some of the
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/fpu/regset.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/fpu/regset.c
@@ -124,7 +124,7 @@
 	/*
 	 * A whole standard-format XSAVE buffer is needed:
 	 */
-	if ((pos != 0) || (count < fpu_user_xstate_size))
+	if (pos != 0 || count != fpu_user_xstate_size)
 		return -EFAULT;
 
 	xsave = &fpu->state.xsave;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/fpu/signal.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/fpu/signal.c
@@ -289,13 +289,17 @@
 		return 0;
 	}
 
-	if (!access_ok(buf, size))
-		return -EACCES;
+	if (!access_ok(buf, size)) {
+		ret = -EACCES;
+		goto out;
+	}
 
-	if (!static_cpu_has(X86_FEATURE_FPU))
-		return fpregs_soft_set(current, NULL,
-				       0, sizeof(struct user_i387_ia32_struct),
-				       NULL, buf) != 0;
+	if (!static_cpu_has(X86_FEATURE_FPU)) {
+		ret = fpregs_soft_set(current, NULL, 0,
+				      sizeof(struct user_i387_ia32_struct),
+				      NULL, buf);
+		goto out;
+	}
 
 	if (use_xsave()) {
 		struct _fpx_sw_bytes fx_sw_user;
@@ -333,7 +337,7 @@
 	if (ia32_fxstate) {
 		ret = __copy_from_user(&env, buf, sizeof(env));
 		if (ret)
-			goto err_out;
+			goto out;
 		envp = &env;
 	} else {
 		/*
@@ -352,6 +356,7 @@
 			fpregs_unlock();
 			return 0;
 		}
+		fpregs_deactivate(fpu);
 		fpregs_unlock();
 	}
 
@@ -368,7 +373,7 @@
 				ret = validate_xstate_header(&fpu->state.xsave.header);
 		}
 		if (ret)
-			goto err_out;
+			goto out;
 
 		sanitize_restored_xstate(&fpu->state, envp, xfeatures, fx_only);
 
@@ -381,7 +386,7 @@
 		ret = __copy_from_user(&fpu->state.fxsave, buf_fx, state_size);
 		if (ret) {
 			ret = -EFAULT;
-			goto err_out;
+			goto out;
 		}
 
 		sanitize_restored_xstate(&fpu->state, envp, xfeatures, fx_only);
@@ -396,16 +401,18 @@
 	} else {
 		ret = __copy_from_user(&fpu->state.fsave, buf_fx, state_size);
 		if (ret)
-			goto err_out;
+			goto out;
 
 		fpregs_lock();
 		ret = copy_kernel_to_fregs_err(&fpu->state.fsave);
 	}
 	if (!ret)
 		fpregs_mark_activate();
+	else
+		fpregs_deactivate(fpu);
 	fpregs_unlock();
 
-err_out:
+out:
 	if (ret)
 		fpu__clear(fpu);
 	return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/fpu/xstate.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/fpu/xstate.c
@@ -399,12 +399,32 @@
 }
 
 /*
+ * All supported features have either init state all zeros or are
+ * handled in setup_init_fpu() individually. This is an explicit
+ * feature list and does not use XFEATURE_MASK*SUPPORTED to catch
+ * newly added supported features at build time and make people
+ * actually look at the init state for the new feature.
+ */
+#define XFEATURES_INIT_FPSTATE_HANDLED		\
+	(XFEATURE_MASK_FP |			\
+	 XFEATURE_MASK_SSE |			\
+	 XFEATURE_MASK_YMM |			\
+	 XFEATURE_MASK_OPMASK |			\
+	 XFEATURE_MASK_ZMM_Hi256 |		\
+	 XFEATURE_MASK_Hi16_ZMM	 |		\
+	 XFEATURE_MASK_PKRU |			\
+	 XFEATURE_MASK_BNDREGS |		\
+	 XFEATURE_MASK_BNDCSR)
+
+/*
  * setup the xstate image representing the init state
  */
 static void __init setup_init_fpu_buf(void)
 {
 	static int on_boot_cpu __initdata = 1;
 
+	BUILD_BUG_ON(XCNTXT_MASK != XFEATURES_INIT_FPSTATE_HANDLED);
+
 	WARN_ON_FPU(!on_boot_cpu);
 	on_boot_cpu = 0;
 
@@ -423,10 +443,22 @@
 	copy_kernel_to_xregs_booting(&init_fpstate.xsave);
 
 	/*
-	 * Dump the init state again. This is to identify the init state
-	 * of any feature which is not represented by all zero's.
+	 * All components are now in init state. Read the state back so
+	 * that init_fpstate contains all non-zero init state. This only
+	 * works with XSAVE, but not with XSAVEOPT and XSAVES because
+	 * those use the init optimization which skips writing data for
+	 * components in init state.
+	 *
+	 * XSAVE could be used, but that would require to reshuffle the
+	 * data when XSAVES is available because XSAVES uses xstate
+	 * compaction. But doing so is a pointless exercise because most
+	 * components have an all zeros init state except for the legacy
+	 * ones (FP and SSE). Those can be saved with FXSAVE into the
+	 * legacy area. Adding new features requires to ensure that init
+	 * state is all zeroes or if not to add the necessary handling
+	 * here.
 	 */
-	copy_xregs_to_kernel_booting(&init_fpstate.xsave);
+	fxsave(&init_fpstate.fxsave);
 }
 
 static int xfeature_uncompacted_offset(int xfeature_nr)
@@ -773,6 +805,14 @@
 	fpu__init_prepare_fx_sw_frame();
 	setup_init_fpu_buf();
 	setup_xstate_comp();
+
+	/*
+	 * CPU capabilities initialization runs before FPU init. So
+	 * X86_FEATURE_OSXSAVE is not set. Now that XSAVE is completely
+	 * functional, set the feature bit so depending code works.
+	 */
+	setup_force_cpu_cap(X86_FEATURE_OSXSAVE);
+
 	print_xstate_offset_size();
 
 	pr_info("x86/fpu: Enabled xstate features 0x%llx, context size is %d bytes, using '%s' format.\n",
@@ -895,8 +935,6 @@
 
 #ifdef CONFIG_ARCH_HAS_PKEYS
 
-#define NR_VALID_PKRU_BITS (CONFIG_NR_PROTECTION_KEYS * 2)
-#define PKRU_VALID_MASK (NR_VALID_PKRU_BITS - 1)
 /*
  * This will go out and modify PKRU register to set the access
  * rights for @pkey to @init_val.
@@ -915,6 +953,13 @@
 	if (!boot_cpu_has(X86_FEATURE_OSPKE))
 		return -EINVAL;
 
+	/*
+	 * This code should only be called with valid 'pkey'
+	 * values originating from in-kernel users.  Complain
+	 * if a bad value is observed.
+	 */
+	WARN_ON_ONCE(pkey >= arch_max_pkey());
+
 	/* Set the bits we need in PKRU:  */
 	if (init_val & PKEY_DISABLE_ACCESS)
 		new_pkru_bits |= PKRU_AD_BIT;
@@ -952,18 +997,31 @@
 	return true;
 }
 
-/*
- * This is similar to user_regset_copyout(), but will not add offset to
- * the source data pointer or increment pos, count, kbuf, and ubuf.
- */
-static inline void
-__copy_xstate_to_kernel(void *kbuf, const void *data,
-			unsigned int offset, unsigned int size, unsigned int size_total)
+static void fill_gap(unsigned to, void **kbuf, unsigned *pos, unsigned *count)
 {
-	if (offset < size_total) {
-		unsigned int copy = min(size, size_total - offset);
+	if (*pos < to) {
+		unsigned size = to - *pos;
+
+		if (size > *count)
+			size = *count;
+		memcpy(*kbuf, (void *)&init_fpstate.xsave + *pos, size);
+		*kbuf += size;
+		*pos += size;
+		*count -= size;
+	}
+}
 
-		memcpy(kbuf + offset, data, copy);
+static void copy_part(unsigned offset, unsigned size, void *from,
+			void **kbuf, unsigned *pos, unsigned *count)
+{
+	fill_gap(offset, kbuf, pos, count);
+	if (size > *count)
+		size = *count;
+	if (size) {
+		memcpy(*kbuf, from, size);
+		*kbuf += size;
+		*pos += size;
+		*count -= size;
 	}
 }
 
@@ -976,8 +1034,9 @@
  */
 int copy_xstate_to_kernel(void *kbuf, struct xregs_state *xsave, unsigned int offset_start, unsigned int size_total)
 {
-	unsigned int offset, size;
 	struct xstate_header header;
+	const unsigned off_mxcsr = offsetof(struct fxregs_state, mxcsr);
+	unsigned count = size_total;
 	int i;
 
 	/*
@@ -993,46 +1052,42 @@
 	header.xfeatures = xsave->header.xfeatures;
 	header.xfeatures &= ~XFEATURE_MASK_SUPERVISOR;
 
+	if (header.xfeatures & XFEATURE_MASK_FP)
+		copy_part(0, off_mxcsr,
+			  &xsave->i387, &kbuf, &offset_start, &count);
+	if (header.xfeatures & (XFEATURE_MASK_SSE | XFEATURE_MASK_YMM))
+		copy_part(off_mxcsr, MXCSR_AND_FLAGS_SIZE,
+			  &xsave->i387.mxcsr, &kbuf, &offset_start, &count);
+	if (header.xfeatures & XFEATURE_MASK_FP)
+		copy_part(offsetof(struct fxregs_state, st_space), 128,
+			  &xsave->i387.st_space, &kbuf, &offset_start, &count);
+	if (header.xfeatures & XFEATURE_MASK_SSE)
+		copy_part(xstate_offsets[XFEATURE_SSE], 256,
+			  &xsave->i387.xmm_space, &kbuf, &offset_start, &count);
+	/*
+	 * Fill xsave->i387.sw_reserved value for ptrace frame:
+	 */
+	copy_part(offsetof(struct fxregs_state, sw_reserved), 48,
+		  xstate_fx_sw_bytes, &kbuf, &offset_start, &count);
 	/*
 	 * Copy xregs_state->header:
 	 */
-	offset = offsetof(struct xregs_state, header);
-	size = sizeof(header);
+	copy_part(offsetof(struct xregs_state, header), sizeof(header),
+		  &header, &kbuf, &offset_start, &count);
 
-	__copy_xstate_to_kernel(kbuf, &header, offset, size, size_total);
-
-	for (i = 0; i < XFEATURE_MAX; i++) {
+	for (i = FIRST_EXTENDED_XFEATURE; i < XFEATURE_MAX; i++) {
 		/*
 		 * Copy only in-use xstates:
 		 */
 		if ((header.xfeatures >> i) & 1) {
 			void *src = __raw_xsave_addr(xsave, i);
 
-			offset = xstate_offsets[i];
-			size = xstate_sizes[i];
-
-			/* The next component has to fit fully into the output buffer: */
-			if (offset + size > size_total)
-				break;
-
-			__copy_xstate_to_kernel(kbuf, src, offset, size, size_total);
+			copy_part(xstate_offsets[i], xstate_sizes[i],
+				  src, &kbuf, &offset_start, &count);
 		}
 
 	}
-
-	if (xfeatures_mxcsr_quirk(header.xfeatures)) {
-		offset = offsetof(struct fxregs_state, mxcsr);
-		size = MXCSR_AND_FLAGS_SIZE;
-		__copy_xstate_to_kernel(kbuf, &xsave->i387.mxcsr, offset, size, size_total);
-	}
-
-	/*
-	 * Fill xsave->i387.sw_reserved value for ptrace frame:
-	 */
-	offset = offsetof(struct fxregs_state, sw_reserved);
-	size = sizeof(xstate_fx_sw_bytes);
-
-	__copy_xstate_to_kernel(kbuf, xstate_fx_sw_bytes, offset, size, size_total);
+	fill_gap(size_total, &kbuf, &offset_start, &count);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/ftrace_32.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/ftrace_32.S
@@ -89,7 +89,7 @@
 	ret
 END(ftrace_caller)
 
-ENTRY(ftrace_regs_caller)
+SYM_CODE_START(ftrace_regs_caller)
 	/*
 	 * We're here from an mcount/fentry CALL, and the stack frame looks like:
 	 *
@@ -163,6 +163,7 @@
 	popl	%eax
 
 	jmp	.Lftrace_ret
+SYM_CODE_END(ftrace_regs_caller)
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 ENTRY(ftrace_graph_caller)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/head64.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/head64.c
@@ -383,6 +383,8 @@
 {
 	memset(__bss_start, 0,
 	       (unsigned long) __bss_stop - (unsigned long) __bss_start);
+	memset(__brk_base, 0,
+	       (unsigned long) __brk_limit - (unsigned long) __brk_base);
 }
 
 static unsigned long get_cmd_line_ptr(void)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/head_32.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/head_32.S
@@ -26,6 +26,7 @@
 #include <asm/bootparam.h>
 #include <asm/export.h>
 #include <asm/pgtable_32.h>
+#include <asm/nospec-branch.h>
 
 /* Physical address */
 #define pa(X) ((X) - __PAGE_OFFSET)
@@ -64,7 +65,7 @@
  * can.
  */
 __HEAD
-ENTRY(startup_32)
+SYM_CODE_START(startup_32)
 	movl pa(initial_stack),%ecx
 	
 	/* test KEEP_SEGMENTS flag to see if the bootloader is asking
@@ -153,6 +154,7 @@
 
 	movl pa(subarch_entries)(,%eax,4), %eax
 	subl $__PAGE_OFFSET, %eax
+	ANNOTATE_RETPOLINE_SAFE
 	jmp *%eax
 
 .Lbad_subarch:
@@ -172,6 +174,7 @@
 #else
 	jmp .Ldefault_entry
 #endif /* CONFIG_PARAVIRT */
+SYM_CODE_END(startup_32)
 
 #ifdef CONFIG_HOTPLUG_CPU
 /*
@@ -302,6 +305,7 @@
 	movl setup_once_ref,%eax
 	andl %eax,%eax
 	jz 1f				# Did we do this already?
+	ANNOTATE_RETPOLINE_SAFE
 	call *%eax
 1:
 
@@ -571,6 +575,16 @@
 #  error "Kernel PMDs should be 1, 2 or 3"
 # endif
 	.align PAGE_SIZE		/* needs to be page-sized too */
+
+#ifdef CONFIG_PAGE_TABLE_ISOLATION
+	/*
+	 * PTI needs another page so sync_initial_pagetable() works correctly
+	 * and does not scribble over the data which is placed behind the
+	 * actual initial_page_table. See clone_pgd_range().
+	 */
+	.fill 1024, 4, 0
+#endif
+
 #endif
 
 .data
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/head_64.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/head_64.S
@@ -335,12 +335,6 @@
 	jmp restore_regs_and_return_to_kernel
 END(early_idt_handler_common)
 
-	__INITDATA
-
-	.balign 4
-GLOBAL(early_recursion_flag)
-	.long 0
-
 #define NEXT_PAGE(name) \
 	.balign	PAGE_SIZE; \
 GLOBAL(name)
@@ -375,6 +369,8 @@
 	.endr
 
 	__INITDATA
+	.balign 4
+
 NEXT_PGD_PAGE(early_top_pgt)
 	.fill	512,8,0
 	.fill	PTI_USER_PGD_FILL,8,0
@@ -382,6 +378,9 @@
 NEXT_PAGE(early_dynamic_pgts)
 	.fill	512*EARLY_DYNAMIC_PAGE_TABLES,8,0
 
+GLOBAL(early_recursion_flag)
+	.long 0
+
 	.data
 
 #if defined(CONFIG_XEN_PV) || defined(CONFIG_PVH)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/hpet.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/hpet.c
@@ -9,6 +9,7 @@
 
 #include <asm/hpet.h>
 #include <asm/time.h>
+#include <asm/mwait.h>
 
 #undef  pr_fmt
 #define pr_fmt(fmt) "hpet: " fmt
@@ -806,6 +807,83 @@
 	return false;
 }
 
+static bool __init mwait_pc10_supported(void)
+{
+	unsigned int eax, ebx, ecx, mwait_substates;
+
+	if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
+		return false;
+
+	if (!cpu_feature_enabled(X86_FEATURE_MWAIT))
+		return false;
+
+	if (boot_cpu_data.cpuid_level < CPUID_MWAIT_LEAF)
+		return false;
+
+	cpuid(CPUID_MWAIT_LEAF, &eax, &ebx, &ecx, &mwait_substates);
+
+	return (ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED) &&
+	       (ecx & CPUID5_ECX_INTERRUPT_BREAK) &&
+	       (mwait_substates & (0xF << 28));
+}
+
+/*
+ * Check whether the system supports PC10. If so force disable HPET as that
+ * stops counting in PC10. This check is overbroad as it does not take any
+ * of the following into account:
+ *
+ *	- ACPI tables
+ *	- Enablement of intel_idle
+ *	- Command line arguments which limit intel_idle C-state support
+ *
+ * That's perfectly fine. HPET is a piece of hardware designed by committee
+ * and the only reasons why it is still in use on modern systems is the
+ * fact that it is impossible to reliably query TSC and CPU frequency via
+ * CPUID or firmware.
+ *
+ * If HPET is functional it is useful for calibrating TSC, but this can be
+ * done via PMTIMER as well which seems to be the last remaining timer on
+ * X86/INTEL platforms that has not been completely wreckaged by feature
+ * creep.
+ *
+ * In theory HPET support should be removed altogether, but there are older
+ * systems out there which depend on it because TSC and APIC timer are
+ * dysfunctional in deeper C-states.
+ *
+ * It's only 20 years now that hardware people have been asked to provide
+ * reliable and discoverable facilities which can be used for timekeeping
+ * and per CPU timer interrupts.
+ *
+ * The probability that this problem is going to be solved in the
+ * forseeable future is close to zero, so the kernel has to be cluttered
+ * with heuristics to keep up with the ever growing amount of hardware and
+ * firmware trainwrecks. Hopefully some day hardware people will understand
+ * that the approach of "This can be fixed in software" is not sustainable.
+ * Hope dies last...
+ */
+static bool __init hpet_is_pc10_damaged(void)
+{
+	unsigned long long pcfg;
+
+	/* Check whether PC10 substates are supported */
+	if (!mwait_pc10_supported())
+		return false;
+
+	/* Check whether PC10 is enabled in PKG C-state limit */
+	rdmsrl(MSR_PKG_CST_CONFIG_CONTROL, pcfg);
+	if ((pcfg & 0xF) < 8)
+		return false;
+
+	if (hpet_force_user) {
+		pr_warn("HPET force enabled via command line, but dysfunctional in PC10.\n");
+		return false;
+	}
+
+	pr_info("HPET dysfunctional in PC10. Force disabled.\n");
+	boot_hpet_disable = true;
+	return true;
+}
+
 /**
  * hpet_enable - Try to setup the HPET timer. Returns 1 on success.
  */
@@ -819,6 +897,9 @@
 	if (!is_hpet_capable())
 		return 0;
 
+	if (hpet_is_pc10_damaged())
+		return 0;
+
 	hpet_set_mapping();
 	if (!hpet_virt_address)
 		return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/i8253.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/i8253.c
@@ -8,6 +8,7 @@
 #include <linux/timex.h>
 #include <linux/i8253.h>
 
+#include <asm/hypervisor.h>
 #include <asm/apic.h>
 #include <asm/hpet.h>
 #include <asm/time.h>
@@ -39,9 +40,15 @@
 
 bool __init pit_timer_init(void)
 {
-	if (!use_pit())
+	if (!use_pit()) {
+		/*
+		 * Don't just ignore the PIT. Ensure it's stopped, because
+		 * VMMs otherwise steal CPU time just to pointlessly waggle
+		 * the (masked) IRQ.
+		 */
+		clockevent_i8253_disable();
 		return false;
-
+	}
 	clockevent_i8253_init(true);
 	global_clock_event = &i8253_clockevent;
 	return true;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/i8259.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/i8259.c
@@ -32,6 +32,7 @@
  */
 static void init_8259A(int auto_eoi);
 
+static bool pcat_compat __ro_after_init;
 static int i8259A_auto_eoi;
 DEFINE_RAW_SPINLOCK(i8259A_lock);
 
@@ -114,6 +115,7 @@
 	disable_irq_nosync(irq);
 	io_apic_irqs &= ~(1<<irq);
 	irq_set_chip_and_handler(irq, &i8259A_chip, handle_level_irq);
+	irq_set_status_flags(irq, IRQ_LEVEL);
 	enable_irq(irq);
 	lapic_assign_legacy_vector(irq, true);
 }
@@ -207,7 +209,7 @@
 		 * lets ACK and report it. [once per IRQ]
 		 */
 		if (!(spurious_irq_mask & irqmask)) {
-			printk(KERN_DEBUG
+			printk_deferred(KERN_DEBUG
 			       "spurious 8259A interrupt: IRQ%d.\n", irq);
 			spurious_irq_mask |= irqmask;
 		}
@@ -300,15 +302,32 @@
 
 static int probe_8259A(void)
 {
+	unsigned char new_val, probe_val = ~(1 << PIC_CASCADE_IR);
 	unsigned long flags;
-	unsigned char probe_val = ~(1 << PIC_CASCADE_IR);
-	unsigned char new_val;
+
+	/*
+	 * If MADT has the PCAT_COMPAT flag set, then do not bother probing
+	 * for the PIC. Some BIOSes leave the PIC uninitialized and probing
+	 * fails.
+	 *
+	 * Right now this causes problems as quite some code depends on
+	 * nr_legacy_irqs() > 0 or has_legacy_pic() == true. This is silly
+	 * when the system has an IO/APIC because then PIC is not required
+	 * at all, except for really old machines where the timer interrupt
+	 * must be routed through the PIC. So just pretend that the PIC is
+	 * there and let legacy_pic->init() initialize it for nothing.
+	 *
+	 * Alternatively this could just try to initialize the PIC and
+	 * repeat the probe, but for cases where there is no PIC that's
+	 * just pointless.
+	 */
+	if (pcat_compat)
+		return nr_legacy_irqs();
+
 	/*
-	 * Check to see if we have a PIC.
-	 * Mask all except the cascade and read
-	 * back the value we just wrote. If we don't
-	 * have a PIC, we will read 0xff as opposed to the
-	 * value we wrote.
+	 * Check to see if we have a PIC.  Mask all except the cascade and
+	 * read back the value we just wrote. If we don't have a PIC, we
+	 * will read 0xff as opposed to the value we wrote.
 	 */
 	raw_spin_lock_irqsave(&i8259A_lock, flags);
 
@@ -430,5 +449,9 @@
 
 	return 0;
 }
-
 device_initcall(i8259A_init_ops);
+
+void __init legacy_pic_pcat_compat(void)
+{
+	pcat_compat = true;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/idt.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/idt.c
@@ -318,7 +318,11 @@
 
 #ifdef CONFIG_X86_LOCAL_APIC
 	for_each_clear_bit_from(i, system_vectors, NR_VECTORS) {
-		set_bit(i, system_vectors);
+		/*
+		 * Don't set the non assigned system vectors in the
+		 * system_vectors bitmap. Otherwise they show up in
+		 * /proc/interrupts.
+		 */
 		entry = spurious_entries_start + 8 * (i - FIRST_SYSTEM_VECTOR);
 		set_intr_gate(i, entry);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/ima_arch.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/ima_arch.c
@@ -10,8 +10,6 @@
 
 static enum efi_secureboot_mode get_sb_mode(void)
 {
-	efi_char16_t efi_SecureBoot_name[] = L"SecureBoot";
-	efi_char16_t efi_SetupMode_name[] = L"SecureBoot";
 	efi_guid_t efi_variable_guid = EFI_GLOBAL_VARIABLE_GUID;
 	efi_status_t status;
 	unsigned long size;
@@ -25,7 +23,7 @@
 	}
 
 	/* Get variable contents into buffer */
-	status = efi.get_variable(efi_SecureBoot_name, &efi_variable_guid,
+	status = efi.get_variable(L"SecureBoot", &efi_variable_guid,
 				  NULL, &size, &secboot);
 	if (status == EFI_NOT_FOUND) {
 		pr_info("ima: secureboot mode disabled\n");
@@ -38,7 +36,7 @@
 	}
 
 	size = sizeof(setupmode);
-	status = efi.get_variable(efi_SetupMode_name, &efi_variable_guid,
+	status = efi.get_variable(L"SetupMode", &efi_variable_guid,
 				  NULL, &size, &setupmode);
 
 	if (status != EFI_SUCCESS)	/* ignore unknown SetupMode */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/irq.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/irq.c
@@ -20,8 +20,10 @@
 #include <asm/hw_irq.h>
 #include <asm/desc.h>
 
+#if defined(CONFIG_X86_LOCAL_APIC) || defined(CONFIG_X86_THERMAL_VECTOR)
 #define CREATE_TRACE_POINTS
 #include <asm/trace/irq_vectors.h>
+#endif
 
 DEFINE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat);
 EXPORT_PER_CPU_SYMBOL(irq_stat);
@@ -295,8 +297,10 @@
 {
 	if (handler)
 		kvm_posted_intr_wakeup_handler = handler;
-	else
+	else {
 		kvm_posted_intr_wakeup_handler = dummy_handler;
+		synchronize_rcu();
+	}
 }
 EXPORT_SYMBOL_GPL(kvm_set_posted_intr_wakeup_handler);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/irq_64.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/irq_64.c
@@ -43,7 +43,7 @@
 		pages[i] = pfn_to_page(pa >> PAGE_SHIFT);
 	}
 
-	va = vmap(pages, IRQ_STACK_SIZE / PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL);
+	va = vmap(pages, IRQ_STACK_SIZE / PAGE_SIZE, VM_MAP, PAGE_KERNEL);
 	if (!va)
 		return -ENOMEM;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/irqinit.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/irqinit.c
@@ -72,8 +72,10 @@
 
 	legacy_pic->init(0);
 
-	for (i = 0; i < nr_legacy_irqs(); i++)
+	for (i = 0; i < nr_legacy_irqs(); i++) {
 		irq_set_chip_and_handler(i, chip, handle_level_irq);
+		irq_set_status_flags(i, IRQ_LEVEL);
+	}
 }
 
 void __init init_IRQ(void)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/kexec-bzimage64.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/kexec-bzimage64.c
@@ -210,8 +210,7 @@
 	params->hdr.hardware_subarch = boot_params.hdr.hardware_subarch;
 
 	/* Copying screen_info will do? */
-	memcpy(&params->screen_info, &boot_params.screen_info,
-				sizeof(struct screen_info));
+	memcpy(&params->screen_info, &screen_info, sizeof(struct screen_info));
 
 	/* Fill in memsize later */
 	params->screen_info.ext_mem_k = 0;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/kprobes/core.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/kprobes/core.c
@@ -157,6 +157,8 @@
 int can_boost(struct insn *insn, void *addr)
 {
 	kprobe_opcode_t opcode;
+	insn_byte_t prefix;
+	int i;
 
 	if (search_exception_tables((unsigned long)addr))
 		return 0;	/* Page fault may occur on this address. */
@@ -169,9 +171,14 @@
 	if (insn->opcode.nbytes != 1)
 		return 0;
 
-	/* Can't boost Address-size override prefix */
-	if (unlikely(inat_is_address_size_prefix(insn->attr)))
-		return 0;
+	for_each_insn_prefix(insn, i, prefix) {
+		insn_attr_t attr;
+
+		attr = inat_get_opcode_attribute(prefix);
+		/* Can't boost Address-size override prefix and CS override prefix */
+		if (prefix == 0x2e || inat_is_address_size_prefix(attr))
+			return 0;
+	}
 
 	opcode = insn->opcode.bytes[0];
 
@@ -196,8 +203,8 @@
 		/* clear and set flags are boostable */
 		return (opcode == 0xf5 || (0xf7 < opcode && opcode < 0xfe));
 	default:
-		/* CS override prefix and call are not boostable */
-		return (opcode != 0x2e && opcode != 0x9a);
+		/* call is not boostable */
+		return opcode != 0x9a;
 	}
 }
 
@@ -351,6 +358,10 @@
 	kernel_insn_init(insn, dest, MAX_INSN_SIZE);
 	insn_get_length(insn);
 
+	/* We can not probe force emulate prefixed instruction */
+	if (insn_has_emulate_prefix(insn))
+		return 0;
+
 	/* Another subsystem puts a breakpoint, failed to recover */
 	if (insn->opcode.bytes[0] == BREAKPOINT_INSTRUCTION)
 		return 0;
@@ -746,16 +757,11 @@
 NOKPROBE_SYMBOL(kretprobe_trampoline);
 STACK_FRAME_NON_STANDARD(kretprobe_trampoline);
 
-static struct kprobe kretprobe_kprobe = {
-	.addr = (void *)kretprobe_trampoline,
-};
-
 /*
  * Called from kretprobe_trampoline
  */
 __used __visible void *trampoline_handler(struct pt_regs *regs)
 {
-	struct kprobe_ctlblk *kcb;
 	struct kretprobe_instance *ri = NULL;
 	struct hlist_head *head, empty_rp;
 	struct hlist_node *tmp;
@@ -765,16 +771,12 @@
 	void *frame_pointer;
 	bool skipped = false;
 
-	preempt_disable();
-
 	/*
 	 * Set a dummy kprobe for avoiding kretprobe recursion.
 	 * Since kretprobe never run in kprobe handler, kprobe must not
 	 * be running at this point.
 	 */
-	kcb = get_kprobe_ctlblk();
-	__this_cpu_write(current_kprobe, &kretprobe_kprobe);
-	kcb->kprobe_status = KPROBE_HIT_ACTIVE;
+	kprobe_busy_begin();
 
 	INIT_HLIST_HEAD(&empty_rp);
 	kretprobe_hash_lock(current, &head, &flags);
@@ -850,7 +852,7 @@
 			__this_cpu_write(current_kprobe, &ri->rp->kp);
 			ri->ret_addr = correct_ret_addr;
 			ri->rp->handler(ri, regs);
-			__this_cpu_write(current_kprobe, &kretprobe_kprobe);
+			__this_cpu_write(current_kprobe, &kprobe_busy);
 		}
 
 		recycle_rp_inst(ri, &empty_rp);
@@ -866,8 +868,7 @@
 
 	kretprobe_hash_unlock(current, &flags);
 
-	__this_cpu_write(current_kprobe, NULL);
-	preempt_enable();
+	kprobe_busy_end();
 
 	hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) {
 		hlist_del(&ri->hlist);
@@ -1029,6 +1030,11 @@
 		 * So clear it by resetting the current kprobe:
 		 */
 		regs->flags &= ~X86_EFLAGS_TF;
+		/*
+		 * Since the single step (trap) has been cancelled,
+		 * we need to restore BTF here.
+		 */
+		restore_btf();
 
 		/*
 		 * If the TF flag was set before the kprobe hit,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/kprobes/opt.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/kprobes/opt.c
@@ -43,8 +43,8 @@
 		/* This function only handles jump-optimized kprobe */
 		if (kp && kprobe_optimized(kp)) {
 			op = container_of(kp, struct optimized_kprobe, kp);
-			/* If op->list is not empty, op is under optimizing */
-			if (list_empty(&op->list))
+			/* If op is optimized or under unoptimizing */
+			if (list_empty(&op->list) || optprobe_queued_unopt(op))
 				goto found;
 		}
 	}
@@ -314,7 +314,7 @@
 
 	for (i = 1; i < op->optinsn.size; i++) {
 		p = get_kprobe(op->kp.addr + i);
-		if (p && !kprobe_disabled(p))
+		if (p && !kprobe_disarmed(p))
 			return -EEXIST;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/kvm.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/kvm.c
@@ -24,6 +24,7 @@
 #include <linux/debugfs.h>
 #include <linux/nmi.h>
 #include <linux/swait.h>
+#include <linux/syscore_ops.h>
 #include <asm/timer.h>
 #include <asm/cpu.h>
 #include <asm/traps.h>
@@ -33,6 +34,7 @@
 #include <asm/apicdef.h>
 #include <asm/hypervisor.h>
 #include <asm/tlb.h>
+#include <asm/reboot.h>
 
 static int kvmapf = 1;
 
@@ -57,6 +59,7 @@
 DEFINE_PER_CPU_DECRYPTED(struct kvm_steal_time, steal_time) __aligned(64) __visible;
 static int has_steal_clock = 0;
 
+static int has_guest_poll = 0;
 /*
  * No need for any "IO delay" on KVM
  */
@@ -321,8 +324,7 @@
 
 		wrmsrl(MSR_KVM_ASYNC_PF_EN, pa);
 		__this_cpu_write(apf_reason.enabled, 1);
-		printk(KERN_INFO"KVM setup async PF for cpu %d\n",
-		       smp_processor_id());
+		pr_info("setup async PF for cpu %d\n", smp_processor_id());
 	}
 
 	if (kvm_para_has_feature(KVM_FEATURE_PV_EOI)) {
@@ -347,35 +349,17 @@
 	wrmsrl(MSR_KVM_ASYNC_PF_EN, 0);
 	__this_cpu_write(apf_reason.enabled, 0);
 
-	printk(KERN_INFO"Unregister pv shared memory for cpu %d\n",
-	       smp_processor_id());
+	pr_info("disable async PF for cpu %d\n", smp_processor_id());
 }
 
-static void kvm_pv_guest_cpu_reboot(void *unused)
+static void kvm_disable_steal_time(void)
 {
-	/*
-	 * We disable PV EOI before we load a new kernel by kexec,
-	 * since MSR_KVM_PV_EOI_EN stores a pointer into old kernel's memory.
-	 * New kernel can re-enable when it boots.
-	 */
-	if (kvm_para_has_feature(KVM_FEATURE_PV_EOI))
-		wrmsrl(MSR_KVM_PV_EOI_EN, 0);
-	kvm_pv_disable_apf();
-	kvm_disable_steal_time();
-}
+	if (!has_steal_clock)
+		return;
 
-static int kvm_pv_reboot_notify(struct notifier_block *nb,
-				unsigned long code, void *unused)
-{
-	if (code == SYS_RESTART)
-		on_each_cpu(kvm_pv_guest_cpu_reboot, NULL, 1);
-	return NOTIFY_DONE;
+	wrmsr(MSR_KVM_STEAL_TIME, 0, 0);
 }
 
-static struct notifier_block kvm_pv_reboot_nb = {
-	.notifier_call = kvm_pv_reboot_notify,
-};
-
 static u64 kvm_steal_clock(int cpu)
 {
 	u64 steal;
@@ -393,14 +377,6 @@
 	return steal;
 }
 
-void kvm_disable_steal_time(void)
-{
-	if (!has_steal_clock)
-		return;
-
-	wrmsr(MSR_KVM_STEAL_TIME, 0, 0);
-}
-
 static inline void __set_percpu_decrypted(void *ptr, unsigned long size)
 {
 	early_set_memory_decrypted((unsigned long) ptr, size);
@@ -428,6 +404,27 @@
 	}
 }
 
+static void kvm_guest_cpu_offline(bool shutdown)
+{
+	kvm_disable_steal_time();
+	if (kvm_para_has_feature(KVM_FEATURE_PV_EOI))
+		wrmsrl(MSR_KVM_PV_EOI_EN, 0);
+	kvm_pv_disable_apf();
+	if (!shutdown)
+		apf_task_wake_all();
+	kvmclock_disable();
+}
+
+static int kvm_cpu_online(unsigned int cpu)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	kvm_guest_cpu_init();
+	local_irq_restore(flags);
+	return 0;
+}
+
 #ifdef CONFIG_SMP
 #define KVM_IPI_CLUSTER_SIZE	(2 * BITS_PER_LONG)
 
@@ -464,7 +461,7 @@
 		} else if (apic_id < min && max - apic_id < KVM_IPI_CLUSTER_SIZE) {
 			ipi_bitmap <<= min - apic_id;
 			min = apic_id;
-		} else if (apic_id < min + KVM_IPI_CLUSTER_SIZE) {
+		} else if (apic_id > min && apic_id < min + KVM_IPI_CLUSTER_SIZE) {
 			max = apic_id < max ? max : apic_id;
 		} else {
 			ret = kvm_hypercall4(KVM_HC_SEND_IPI, (unsigned long)ipi_bitmap,
@@ -547,31 +544,46 @@
 	kvm_spinlock_init();
 }
 
-static void kvm_guest_cpu_offline(void)
+static int kvm_cpu_down_prepare(unsigned int cpu)
 {
-	kvm_disable_steal_time();
-	if (kvm_para_has_feature(KVM_FEATURE_PV_EOI))
-		wrmsrl(MSR_KVM_PV_EOI_EN, 0);
-	kvm_pv_disable_apf();
-	apf_task_wake_all();
-}
+	unsigned long flags;
 
-static int kvm_cpu_online(unsigned int cpu)
-{
-	local_irq_disable();
-	kvm_guest_cpu_init();
-	local_irq_enable();
+	local_irq_save(flags);
+	kvm_guest_cpu_offline(false);
+	local_irq_restore(flags);
 	return 0;
 }
 
-static int kvm_cpu_down_prepare(unsigned int cpu)
+#endif
+
+static int kvm_suspend(void)
 {
-	local_irq_disable();
-	kvm_guest_cpu_offline();
-	local_irq_enable();
+	u64 val = 0;
+
+	kvm_guest_cpu_offline(false);
+
+#ifdef CONFIG_ARCH_CPUIDLE_HALTPOLL
+	if (kvm_para_has_feature(KVM_FEATURE_POLL_CONTROL))
+		rdmsrl(MSR_KVM_POLL_CONTROL, val);
+	has_guest_poll = !(val & 1);
+#endif
 	return 0;
 }
+
+static void kvm_resume(void)
+{
+	kvm_cpu_online(raw_smp_processor_id());
+
+#ifdef CONFIG_ARCH_CPUIDLE_HALTPOLL
+	if (kvm_para_has_feature(KVM_FEATURE_POLL_CONTROL) && has_guest_poll)
+		wrmsrl(MSR_KVM_POLL_CONTROL, 0);
 #endif
+}
+
+static struct syscore_ops kvm_syscore_ops = {
+	.suspend	= kvm_suspend,
+	.resume		= kvm_resume,
+};
 
 static void __init kvm_apf_trap_init(void)
 {
@@ -606,6 +618,37 @@
 	native_flush_tlb_others(flushmask, info);
 }
 
+static void kvm_pv_guest_cpu_reboot(void *unused)
+{
+	kvm_guest_cpu_offline(true);
+}
+
+static int kvm_pv_reboot_notify(struct notifier_block *nb,
+				unsigned long code, void *unused)
+{
+	if (code == SYS_RESTART)
+		on_each_cpu(kvm_pv_guest_cpu_reboot, NULL, 1);
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block kvm_pv_reboot_nb = {
+	.notifier_call = kvm_pv_reboot_notify,
+};
+
+/*
+ * After a PV feature is registered, the host will keep writing to the
+ * registered memory location. If the guest happens to shutdown, this memory
+ * won't be valid. In cases like kexec, in which you install a new kernel, this
+ * means a random memory location will be kept being written.
+ */
+#ifdef CONFIG_KEXEC_CORE
+static void kvm_crash_shutdown(struct pt_regs *regs)
+{
+	kvm_guest_cpu_offline(true);
+	native_machine_crash_shutdown(regs);
+}
+#endif
+
 static void __init kvm_guest_init(void)
 {
 	int i;
@@ -649,6 +692,12 @@
 	kvm_guest_cpu_init();
 #endif
 
+#ifdef CONFIG_KEXEC_CORE
+	machine_ops.crash_shutdown = kvm_crash_shutdown;
+#endif
+
+	register_syscore_ops(&kvm_syscore_ops);
+
 	/*
 	 * Hard lockup detection is enabled by default. Disable it, as guests
 	 * can get false positives too easily, for example if the host is
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/kvmclock.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/kvmclock.c
@@ -20,13 +20,12 @@
 #include <asm/hypervisor.h>
 #include <asm/mem_encrypt.h>
 #include <asm/x86_init.h>
-#include <asm/reboot.h>
 #include <asm/kvmclock.h>
 
 static int kvmclock __initdata = 1;
 static int kvmclock_vsyscall __initdata = 1;
-static int msr_kvm_system_time __ro_after_init = MSR_KVM_SYSTEM_TIME;
-static int msr_kvm_wall_clock __ro_after_init = MSR_KVM_WALL_CLOCK;
+static int msr_kvm_system_time __ro_after_init;
+static int msr_kvm_wall_clock __ro_after_init;
 static u64 kvm_sched_clock_offset __ro_after_init;
 
 static int __init parse_no_kvmclock(char *arg)
@@ -51,18 +50,9 @@
 static struct pvclock_vsyscall_time_info
 			hv_clock_boot[HVC_BOOT_ARRAY_SIZE] __bss_decrypted __aligned(PAGE_SIZE);
 static struct pvclock_wall_clock wall_clock __bss_decrypted;
-static DEFINE_PER_CPU(struct pvclock_vsyscall_time_info *, hv_clock_per_cpu);
 static struct pvclock_vsyscall_time_info *hvclock_mem;
-
-static inline struct pvclock_vcpu_time_info *this_cpu_pvti(void)
-{
-	return &this_cpu_read(hv_clock_per_cpu)->pvti;
-}
-
-static inline struct pvclock_vsyscall_time_info *this_cpu_hvclock(void)
-{
-	return this_cpu_read(hv_clock_per_cpu);
-}
+DEFINE_PER_CPU(struct pvclock_vsyscall_time_info *, hv_clock_per_cpu);
+EXPORT_PER_CPU_SYMBOL_GPL(hv_clock_per_cpu);
 
 /*
  * The wallclock is the time of day when we booted. Since then, some time may
@@ -197,28 +187,10 @@
 }
 #endif
 
-/*
- * After the clock is registered, the host will keep writing to the
- * registered memory location. If the guest happens to shutdown, this memory
- * won't be valid. In cases like kexec, in which you install a new kernel, this
- * means a random memory location will be kept being written. So before any
- * kind of shutdown from our side, we unregister the clock by writing anything
- * that does not have the 'enable' bit set in the msr
- */
-#ifdef CONFIG_KEXEC_CORE
-static void kvm_crash_shutdown(struct pt_regs *regs)
-{
-	native_write_msr(msr_kvm_system_time, 0, 0);
-	kvm_disable_steal_time();
-	native_machine_crash_shutdown(regs);
-}
-#endif
-
-static void kvm_shutdown(void)
+void kvmclock_disable(void)
 {
-	native_write_msr(msr_kvm_system_time, 0, 0);
-	kvm_disable_steal_time();
-	native_machine_shutdown();
+	if (msr_kvm_system_time)
+		native_write_msr(msr_kvm_system_time, 0, 0);
 }
 
 static void __init kvmclock_init_mem(void)
@@ -315,7 +287,10 @@
 	if (kvm_para_has_feature(KVM_FEATURE_CLOCKSOURCE2)) {
 		msr_kvm_system_time = MSR_KVM_SYSTEM_TIME_NEW;
 		msr_kvm_wall_clock = MSR_KVM_WALL_CLOCK_NEW;
-	} else if (!kvm_para_has_feature(KVM_FEATURE_CLOCKSOURCE)) {
+	} else if (kvm_para_has_feature(KVM_FEATURE_CLOCKSOURCE)) {
+		msr_kvm_system_time = MSR_KVM_SYSTEM_TIME;
+		msr_kvm_wall_clock = MSR_KVM_WALL_CLOCK;
+	} else {
 		return;
 	}
 
@@ -346,10 +321,6 @@
 #endif
 	x86_platform.save_sched_clock_state = kvm_save_sched_clock_state;
 	x86_platform.restore_sched_clock_state = kvm_restore_sched_clock_state;
-	machine_ops.shutdown  = kvm_shutdown;
-#ifdef CONFIG_KEXEC_CORE
-	machine_ops.crash_shutdown  = kvm_crash_shutdown;
-#endif
 	kvm_get_preset_lpj();
 
 	/*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/module.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/module.c
@@ -114,6 +114,7 @@
 			*location += sym->st_value;
 			break;
 		case R_386_PC32:
+		case R_386_PLT32:
 			/* Add the value, subtract its position */
 			*location += sym->st_value - (uint32_t)location;
 			break;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/nmi.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/nmi.c
@@ -104,18 +104,21 @@
 }
 fs_initcall(nmi_warning_debugfs);
 
-static void nmi_max_handler(struct irq_work *w)
+static void nmi_check_duration(struct nmiaction *action, u64 duration)
 {
-	struct nmiaction *a = container_of(w, struct nmiaction, irq_work);
 	int remainder_ns, decimal_msecs;
-	u64 whole_msecs = READ_ONCE(a->max_duration);
 
-	remainder_ns = do_div(whole_msecs, (1000 * 1000));
+	if (duration < nmi_longest_ns || duration < action->max_duration)
+		return;
+
+	action->max_duration = duration;
+
+	remainder_ns = do_div(duration, (1000 * 1000));
 	decimal_msecs = remainder_ns / 1000;
 
 	printk_ratelimited(KERN_INFO
 		"INFO: NMI handler (%ps) took too long to run: %lld.%03d msecs\n",
-		a->handler, whole_msecs, decimal_msecs);
+		action->handler, duration, decimal_msecs);
 }
 
 static int nmi_handle(unsigned int type, struct pt_regs *regs)
@@ -142,11 +145,7 @@
 		delta = sched_clock() - delta;
 		trace_nmi_handler(a->handler, (int)delta, thishandled);
 
-		if (delta < nmi_longest_ns || delta < a->max_duration)
-			continue;
-
-		a->max_duration = delta;
-		irq_work_queue(&a->irq_work);
+		nmi_check_duration(a, delta);
 	}
 
 	rcu_read_unlock();
@@ -164,8 +163,6 @@
 	if (!action->handler)
 		return -EINVAL;
 
-	init_irq_work(&action->irq_work, nmi_max_handler);
-
 	raw_spin_lock_irqsave(&desc->lock, flags);
 
 	/*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/pmem.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/pmem.c
@@ -27,6 +27,11 @@
 	 * simply here to trigger the module to load on demand.
 	 */
 	pdev = platform_device_alloc("e820_pmem", -1);
-	return platform_device_add(pdev);
+
+	rc = platform_device_add(pdev);
+	if (rc)
+		platform_device_put(pdev);
+
+	return rc;
 }
 device_initcall(register_e820_pmem);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/process.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/process.c
@@ -96,7 +96,12 @@
  */
 int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
 {
-	memcpy(dst, src, arch_task_struct_size);
+	/* init_task is not dynamically sized (incomplete FPU state) */
+	if (unlikely(src == &init_task))
+		memcpy_and_pad(dst, arch_task_struct_size, src, sizeof(init_task), 0);
+	else
+		memcpy(dst, src, arch_task_struct_size);
+
 #ifdef CONFIG_VM86
 	dst->thread.vm86 = NULL;
 #endif
@@ -428,28 +433,20 @@
 
 	lockdep_assert_irqs_disabled();
 
-	/*
-	 * If TIF_SSBD is different, select the proper mitigation
-	 * method. Note that if SSBD mitigation is disabled or permanentely
-	 * enabled this branch can't be taken because nothing can set
-	 * TIF_SSBD.
-	 */
-	if (tif_diff & _TIF_SSBD) {
-		if (static_cpu_has(X86_FEATURE_VIRT_SSBD)) {
+	/* Handle change of TIF_SSBD depending on the mitigation method. */
+	if (static_cpu_has(X86_FEATURE_VIRT_SSBD)) {
+		if (tif_diff & _TIF_SSBD)
 			amd_set_ssb_virt_state(tifn);
-		} else if (static_cpu_has(X86_FEATURE_LS_CFG_SSBD)) {
+	} else if (static_cpu_has(X86_FEATURE_LS_CFG_SSBD)) {
+		if (tif_diff & _TIF_SSBD)
 			amd_set_core_ssb_state(tifn);
-		} else if (static_cpu_has(X86_FEATURE_SPEC_CTRL_SSBD) ||
-			   static_cpu_has(X86_FEATURE_AMD_SSBD)) {
-			msr |= ssbd_tif_to_spec_ctrl(tifn);
-			updmsr  = true;
-		}
+	} else if (static_cpu_has(X86_FEATURE_SPEC_CTRL_SSBD) ||
+		   static_cpu_has(X86_FEATURE_AMD_SSBD)) {
+		updmsr |= !!(tif_diff & _TIF_SSBD);
+		msr |= ssbd_tif_to_spec_ctrl(tifn);
 	}
 
-	/*
-	 * Only evaluate TIF_SPEC_IB if conditional STIBP is enabled,
-	 * otherwise avoid the MSR write.
-	 */
+	/* Only evaluate TIF_SPEC_IB if conditional STIBP is enabled. */
 	if (IS_ENABLED(CONFIG_SMP) &&
 	    static_branch_unlikely(&switch_to_cond_stibp)) {
 		updmsr |= !!(tif_diff & _TIF_SPEC_IB);
@@ -457,7 +454,7 @@
 	}
 
 	if (updmsr)
-		wrmsrl(MSR_IA32_SPEC_CTRL, msr);
+		update_spec_ctrl_cond(msr);
 }
 
 static unsigned long speculation_ctrl_update_tif(struct task_struct *tsk)
@@ -667,6 +664,10 @@
  */
 static int prefer_mwait_c1_over_halt(const struct cpuinfo_x86 *c)
 {
+	/* User has disallowed the use of MWAIT. Fallback to HALT */
+	if (boot_option_idle_override == IDLE_NOMWAIT)
+		return 0;
+
 	if (c->x86_vendor != X86_VENDOR_INTEL)
 		return 0;
 
@@ -777,9 +778,8 @@
 	} else if (!strcmp(str, "nomwait")) {
 		/*
 		 * If the boot option of "idle=nomwait" is added,
-		 * it means that mwait will be disabled for CPU C2/C3
-		 * states. In such case it won't touch the variable
-		 * of boot_option_idle_override.
+		 * it means that mwait will be disabled for CPU C1/C2/C3
+		 * states.
 		 */
 		boot_option_idle_override = IDLE_NOMWAIT;
 	} else
@@ -798,7 +798,10 @@
 
 unsigned long arch_randomize_brk(struct mm_struct *mm)
 {
-	return randomize_page(mm->brk, 0x02000000);
+	if (mmap_is_ia32())
+		return randomize_page(mm->brk, SZ_32M);
+
+	return randomize_page(mm->brk, SZ_1G);
 }
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/process_32.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/process_32.c
@@ -229,14 +229,12 @@
 {
 	struct thread_struct *prev = &prev_p->thread,
 			     *next = &next_p->thread;
-	struct fpu *prev_fpu = &prev->fpu;
-	struct fpu *next_fpu = &next->fpu;
 	int cpu = smp_processor_id();
 
 	/* never put a printk in __switch_to... printk() calls wake_up*() indirectly */
 
 	if (!test_thread_flag(TIF_NEED_FPU_LOAD))
-		switch_fpu_prepare(prev_fpu, cpu);
+		switch_fpu_prepare(prev_p, cpu);
 
 	/*
 	 * Save away %gs. No need to save %fs, as it was saved on the
@@ -292,10 +290,10 @@
 
 	this_cpu_write(current_task, next_p);
 
-	switch_fpu_finish(next_fpu);
+	switch_fpu_finish(next_p);
 
 	/* Load the Intel cache allocation PQR MSR. */
-	resctrl_sched_in();
+	resctrl_sched_in(next_p);
 
 	return prev_p;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/process_64.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/process_64.c
@@ -316,7 +316,7 @@
 		 */
 		mutex_lock(&task->mm->context.lock);
 		ldt = task->mm->context.ldt;
-		if (unlikely(idx >= ldt->nr_entries))
+		if (unlikely(!ldt || idx >= ldt->nr_entries))
 			base = 0;
 		else
 			base = get_desc_base(ldt->entries + idx);
@@ -505,15 +505,13 @@
 {
 	struct thread_struct *prev = &prev_p->thread;
 	struct thread_struct *next = &next_p->thread;
-	struct fpu *prev_fpu = &prev->fpu;
-	struct fpu *next_fpu = &next->fpu;
 	int cpu = smp_processor_id();
 
 	WARN_ON_ONCE(IS_ENABLED(CONFIG_DEBUG_ENTRY) &&
 		     this_cpu_read(irq_count) != -1);
 
 	if (!test_thread_flag(TIF_NEED_FPU_LOAD))
-		switch_fpu_prepare(prev_fpu, cpu);
+		switch_fpu_prepare(prev_p, cpu);
 
 	/* We must save %fs and %gs before load_TLS() because
 	 * %fs and %gs may be cleared by load_TLS().
@@ -565,7 +563,7 @@
 	this_cpu_write(current_task, next_p);
 	this_cpu_write(cpu_current_top_of_stack, task_top_of_stack(next_p));
 
-	switch_fpu_finish(next_fpu);
+	switch_fpu_finish(next_p);
 
 	/* Reload sp0. */
 	update_task_stack(next_p);
@@ -612,7 +610,7 @@
 	}
 
 	/* Load the Intel cache allocation PQR MSR. */
-	resctrl_sched_in();
+	resctrl_sched_in(next_p);
 
 	return prev_p;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/quirks.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/quirks.c
@@ -95,7 +95,7 @@
 static void ich_force_enable_hpet(struct pci_dev *dev)
 {
 	u32 val;
-	u32 uninitialized_var(rcba);
+	u32 rcba;
 	int err = 0;
 
 	if (hpet_address || force_hpet_address)
@@ -185,7 +185,7 @@
 static void old_ich_force_hpet_resume(void)
 {
 	u32 val;
-	u32 uninitialized_var(gen_cntl);
+	u32 gen_cntl;
 
 	if (!force_hpet_address || !cached_dev)
 		return;
@@ -207,7 +207,7 @@
 static void old_ich_force_enable_hpet(struct pci_dev *dev)
 {
 	u32 val;
-	u32 uninitialized_var(gen_cntl);
+	u32 gen_cntl;
 
 	if (hpet_address || force_hpet_address)
 		return;
@@ -298,7 +298,7 @@
 
 static void vt8237_force_enable_hpet(struct pci_dev *dev)
 {
-	u32 uninitialized_var(val);
+	u32 val;
 
 	if (hpet_address || force_hpet_address)
 		return;
@@ -429,7 +429,7 @@
 
 static void nvidia_force_enable_hpet(struct pci_dev *dev)
 {
-	u32 uninitialized_var(val);
+	u32 val;
 
 	if (hpet_address || force_hpet_address)
 		return;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/reboot.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/reboot.c
@@ -32,6 +32,7 @@
 #include <asm/realmode.h>
 #include <asm/x86_init.h>
 #include <asm/efi.h>
+#include <asm/nospec-branch.h>
 
 /*
  * Power off function, if any
@@ -113,25 +114,17 @@
 	spin_unlock(&rtc_lock);
 
 	/*
-	 * Switch back to the initial page table.
+	 * Switch to the trampoline page table.
 	 */
-#ifdef CONFIG_X86_32
-	load_cr3(initial_page_table);
-#else
-	write_cr3(real_mode_header->trampoline_pgd);
-
-	/* Exiting long mode will fail if CR4.PCIDE is set. */
-	if (boot_cpu_has(X86_FEATURE_PCID))
-		cr4_clear_bits(X86_CR4_PCIDE);
-#endif
+	load_trampoline_pgtable();
 
 	/* Jump to the identity-mapped low memory code */
 #ifdef CONFIG_X86_32
-	asm volatile("jmpl *%0" : :
+	asm volatile(ANNOTATE_RETPOLINE_SAFE "jmpl *%0" : :
 		     "rm" (real_mode_header->machine_real_restart_asm),
 		     "a" (type));
 #else
-	asm volatile("ljmpl *%0" : :
+	asm volatile(ANNOTATE_RETPOLINE_SAFE "ljmpl *%0" : :
 		     "m" (real_mode_header->machine_real_restart_asm),
 		     "D" (type));
 #endif
@@ -197,6 +190,14 @@
 			DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5"),
 		},
 	},
+	{	/* Handle problems with rebooting on Apple MacBook6,1 */
+		.callback = set_pci_reboot,
+		.ident = "Apple MacBook6,1",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "MacBook6,1"),
+		},
+	},
 	{	/* Handle problems with rebooting on Apple MacBookPro5 */
 		.callback = set_pci_reboot,
 		.ident = "Apple MacBookPro5",
@@ -380,10 +381,11 @@
 	},
 	{	/* Handle problems with rebooting on the OptiPlex 990. */
 		.callback = set_pci_reboot,
-		.ident = "Dell OptiPlex 990",
+		.ident = "Dell OptiPlex 990 BIOS A0x",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 990"),
+			DMI_MATCH(DMI_BIOS_VERSION, "A0"),
 		},
 	},
 	{	/* Handle problems with rebooting on Dell 300's */
@@ -469,6 +471,15 @@
 		},
 	},
 
+	{	/* PCIe Wifi card isn't detected after reboot otherwise */
+		.callback = set_pci_reboot,
+		.ident = "Zotac ZBOX CI327 nano",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "NA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "ZBOX-CI327NANO-GS-01"),
+		},
+	},
+
 	/* Sony */
 	{	/* Handle problems with rebooting on Sony VGN-Z540N */
 		.callback = set_bios_reboot,
@@ -478,7 +489,46 @@
 			DMI_MATCH(DMI_PRODUCT_NAME, "VGN-Z540N"),
 		},
 	},
-
+	{	/* Handle problems with rebooting on the Latitude E6520. */
+		.callback = set_pci_reboot,
+		.ident = "Dell Latitude E6520",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6520"),
+		},
+	},
+	{       /* Handle problems with rebooting on the OptiPlex 790. */
+		.callback = set_pci_reboot,
+		.ident = "Dell OptiPlex 790",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 790"),
+		},
+	},
+	{	/* Handle problems with rebooting on the OptiPlex 990. */
+		.callback = set_pci_reboot,
+		.ident = "Dell OptiPlex 990",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 990"),
+		},
+	},
+	{       /* Handle problems with rebooting on the Latitude E6220. */
+		.callback = set_pci_reboot,
+		.ident = "Dell Latitude E6220",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E6220"),
+		},
+	},
+	{	/* Handle problems with rebooting on the OptiPlex 390. */
+		.callback = set_pci_reboot,
+		.ident = "Dell OptiPlex 390",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 390"),
+		},
+	},
 	{ }
 };
 
@@ -518,42 +568,29 @@
 	}
 }
 
-static void vmxoff_nmi(int cpu, struct pt_regs *regs)
-{
-	cpu_emergency_vmxoff();
-}
+static inline void nmi_shootdown_cpus_on_restart(void);
 
-/* Use NMIs as IPIs to tell all CPUs to disable virtualization */
-static void emergency_vmx_disable_all(void)
+static void emergency_reboot_disable_virtualization(void)
 {
 	/* Just make sure we won't change CPUs while doing this */
 	local_irq_disable();
 
 	/*
-	 * We need to disable VMX on all CPUs before rebooting, otherwise
-	 * we risk hanging up the machine, because the CPU ignore INIT
-	 * signals when VMX is enabled.
+	 * Disable virtualization on all CPUs before rebooting to avoid hanging
+	 * the system, as VMX and SVM block INIT when running in the host.
 	 *
-	 * We can't take any locks and we may be on an inconsistent
-	 * state, so we use NMIs as IPIs to tell the other CPUs to disable
-	 * VMX and halt.
+	 * We can't take any locks and we may be on an inconsistent state, so
+	 * use NMIs as IPIs to tell the other CPUs to disable VMX/SVM and halt.
 	 *
-	 * For safety, we will avoid running the nmi_shootdown_cpus()
-	 * stuff unnecessarily, but we don't have a way to check
-	 * if other CPUs have VMX enabled. So we will call it only if the
-	 * CPU we are running on has VMX enabled.
-	 *
-	 * We will miss cases where VMX is not enabled on all CPUs. This
-	 * shouldn't do much harm because KVM always enable VMX on all
-	 * CPUs anyway. But we can miss it on the small window where KVM
-	 * is still enabling VMX.
-	 */
-	if (cpu_has_vmx() && cpu_vmx_enabled()) {
-		/* Disable VMX on this CPU. */
-		cpu_vmxoff();
+	 * Do the NMI shootdown even if virtualization is off on _this_ CPU, as
+	 * other CPUs may have virtualization enabled.
+	 */
+	if (cpu_has_vmx() || cpu_has_svm(NULL)) {
+		/* Safely force _this_ CPU out of VMX/SVM operation. */
+		cpu_emergency_disable_virtualization();
 
-		/* Halt and disable VMX on the other CPUs */
-		nmi_shootdown_cpus(vmxoff_nmi);
+		/* Disable VMX/SVM and halt on other CPUs. */
+		nmi_shootdown_cpus_on_restart();
 
 	}
 }
@@ -590,7 +627,7 @@
 	unsigned short mode;
 
 	if (reboot_emergency)
-		emergency_vmx_disable_all();
+		emergency_reboot_disable_virtualization();
 
 	tboot_shutdown(TB_SHUTDOWN_REBOOT);
 
@@ -795,6 +832,17 @@
 /* This is the CPU performing the emergency shutdown work. */
 int crashing_cpu = -1;
 
+/*
+ * Disable virtualization, i.e. VMX or SVM, to ensure INIT is recognized during
+ * reboot.  VMX blocks INIT if the CPU is post-VMXON, and SVM blocks INIT if
+ * GIF=0, i.e. if the crash occurred between CLGI and STGI.
+ */
+void cpu_emergency_disable_virtualization(void)
+{
+	cpu_emergency_vmxoff();
+	cpu_emergency_svm_disable();
+}
+
 #if defined(CONFIG_SMP)
 
 static nmi_shootdown_cb shootdown_callback;
@@ -817,7 +865,14 @@
 		return NMI_HANDLED;
 	local_irq_disable();
 
-	shootdown_callback(cpu, regs);
+	if (shootdown_callback)
+		shootdown_callback(cpu, regs);
+
+	/*
+	 * Prepare the CPU for reboot _after_ invoking the callback so that the
+	 * callback can safely use virtualization instructions, e.g. VMCLEAR.
+	 */
+	cpu_emergency_disable_virtualization();
 
 	atomic_dec(&waiting_for_crash_ipi);
 	/* Assume hlt works */
@@ -828,18 +883,32 @@
 	return NMI_HANDLED;
 }
 
-/*
- * Halt all other CPUs, calling the specified function on each of them
+/**
+ * nmi_shootdown_cpus - Stop other CPUs via NMI
+ * @callback:	Optional callback to be invoked from the NMI handler
+ *
+ * The NMI handler on the remote CPUs invokes @callback, if not
+ * NULL, first and then disables virtualization to ensure that
+ * INIT is recognized during reboot.
  *
- * This function can be used to halt all other CPUs on crash
- * or emergency reboot time. The function passed as parameter
- * will be called inside a NMI handler on all CPUs.
+ * nmi_shootdown_cpus() can only be invoked once. After the first
+ * invocation all other CPUs are stuck in crash_nmi_callback() and
+ * cannot respond to a second NMI.
  */
 void nmi_shootdown_cpus(nmi_shootdown_cb callback)
 {
 	unsigned long msecs;
+
 	local_irq_disable();
 
+	/*
+	 * Avoid certain doom if a shootdown already occurred; re-registering
+	 * the NMI handler will cause list corruption, modifying the callback
+	 * will do who knows what, etc...
+	 */
+	if (WARN_ON_ONCE(crash_ipi_issued))
+		return;
+
 	/* Make a note of crashing cpu. Will be used in NMI callback. */
 	crashing_cpu = safe_smp_processor_id();
 
@@ -867,7 +936,17 @@
 		msecs--;
 	}
 
-	/* Leave the nmi callback set */
+	/*
+	 * Leave the nmi callback set, shootdown is a one-time thing.  Clearing
+	 * the callback could result in a NULL pointer dereference if a CPU
+	 * (finally) responds after the timeout expires.
+	 */
+}
+
+static inline void nmi_shootdown_cpus_on_restart(void)
+{
+	if (!crash_ipi_issued)
+		nmi_shootdown_cpus(NULL);
 }
 
 /*
@@ -897,6 +976,8 @@
 	/* No other CPUs to shoot down */
 }
 
+static inline void nmi_shootdown_cpus_on_restart(void) { }
+
 void run_crash_ipi_callback(struct pt_regs *regs)
 {
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/relocate_kernel_32.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/relocate_kernel_32.S
@@ -8,6 +8,7 @@
 #include <asm/page_types.h>
 #include <asm/kexec.h>
 #include <asm/processor-flags.h>
+#include <asm/nospec-branch.h>
 
 /*
  * Must be relocatable PIC code callable as a C function
@@ -165,6 +166,7 @@
 	movl	CP_PA_SWAP_PAGE(%edi), %esp
 	addl	$PAGE_SIZE, %esp
 2:
+	ANNOTATE_RETPOLINE_SAFE
 	call	*%edx
 
 	/* get the re-entry point of the peer system */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/relocate_kernel_64.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/relocate_kernel_64.S
@@ -9,6 +9,7 @@
 #include <asm/kexec.h>
 #include <asm/processor-flags.h>
 #include <asm/pgtable_types.h>
+#include <asm/nospec-branch.h>
 
 /*
  * Must be relocatable PIC code callable as a C function
@@ -192,6 +193,7 @@
 1:
 	popq	%rdx
 	leaq	PAGE_SIZE(%r10), %rsp
+	ANNOTATE_RETPOLINE_SAFE
 	call	*%rdx
 
 	/* get the re-entry point of the peer system */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/setup.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/setup.c
@@ -73,6 +73,7 @@
 #include <linux/jiffies.h>
 #include <linux/mem_encrypt.h>
 #include <linux/sizes.h>
+#include <linux/security.h>
 
 #include <linux/usb/xhci-dbgp.h>
 #include <video/edid.h>
@@ -1027,6 +1028,13 @@
 	if (efi_enabled(EFI_BOOT))
 		efi_init();
 
+	efi_set_secure_boot(boot_params.secure_boot);
+
+#ifdef CONFIG_LOCK_DOWN_IN_SECURE_BOOT
+	if (efi_enabled(EFI_SECURE_BOOT))
+		security_lock_kernel_down("EFI Secure Boot mode", LOCKDOWN_INTEGRITY_MAX);
+#endif
+
 	dmi_setup();
 
 	/*
@@ -1126,6 +1134,7 @@
 		efi_fake_memmap();
 		efi_find_mirror();
 		efi_esrt_init();
+		efi_mokvar_table_init();
 
 		/*
 		 * The EFI specification says that boot service code won't be
@@ -1179,23 +1188,13 @@
 	/* Allocate bigger log buffer */
 	setup_log_buf(1);
 
-	if (efi_enabled(EFI_BOOT)) {
-		switch (boot_params.secure_boot) {
-		case efi_secureboot_mode_disabled:
-			pr_info("Secure boot disabled\n");
-			break;
-		case efi_secureboot_mode_enabled:
-			pr_info("Secure boot enabled\n");
-			break;
-		default:
-			pr_info("Secure boot could not be determined\n");
-			break;
-		}
-	}
+	efi_set_secure_boot(boot_params.secure_boot);
 
 	reserve_initrd();
 
 	acpi_table_upgrade();
+	/* Look for ACPI tables and reserve memory occupied by them. */
+	acpi_boot_table_init();
 
 	vsmp_init();
 
@@ -1203,11 +1202,6 @@
 
 	early_platform_quirks();
 
-	/*
-	 * Parse the ACPI tables for possible boot-time SMP configuration.
-	 */
-	acpi_boot_table_init();
-
 	early_acpi_boot_init();
 
 	initmem_init();
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/signal.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/signal.c
@@ -241,10 +241,11 @@
 	     void __user **fpstate)
 {
 	/* Default to using normal stack */
+	bool nested_altstack = on_sig_stack(regs->sp);
+	bool entering_altstack = false;
 	unsigned long math_size = 0;
 	unsigned long sp = regs->sp;
 	unsigned long buf_fx = 0;
-	int onsigstack = on_sig_stack(sp);
 	int ret;
 
 	/* redzone */
@@ -253,15 +254,23 @@
 
 	/* This is the X/Open sanctioned signal stack switching.  */
 	if (ka->sa.sa_flags & SA_ONSTACK) {
-		if (sas_ss_flags(sp) == 0)
+		/*
+		 * This checks nested_altstack via sas_ss_flags(). Sensible
+		 * programs use SS_AUTODISARM, which disables that check, and
+		 * programs that don't use SS_AUTODISARM get compatible.
+		 */
+		if (sas_ss_flags(sp) == 0) {
 			sp = current->sas_ss_sp + current->sas_ss_size;
+			entering_altstack = true;
+		}
 	} else if (IS_ENABLED(CONFIG_X86_32) &&
-		   !onsigstack &&
+		   !nested_altstack &&
 		   regs->ss != __USER_DS &&
 		   !(ka->sa.sa_flags & SA_RESTORER) &&
 		   ka->sa.sa_restorer) {
 		/* This is the legacy signal stack switching. */
 		sp = (unsigned long) ka->sa.sa_restorer;
+		entering_altstack = true;
 	}
 
 	sp = fpu__alloc_mathframe(sp, IS_ENABLED(CONFIG_X86_32),
@@ -274,8 +283,15 @@
 	 * If we are on the alternate signal stack and would overflow it, don't.
 	 * Return an always-bogus address instead so we will die with SIGSEGV.
 	 */
-	if (onsigstack && !likely(on_sig_stack(sp)))
+	if (unlikely((nested_altstack || entering_altstack) &&
+		     !__on_sig_stack(sp))) {
+
+		if (show_unhandled_signals && printk_ratelimit())
+			pr_info("%s[%d] overflowed sigaltstack\n",
+				current->comm, task_pid_nr(current));
+
 		return (void __user *)-1L;
+	}
 
 	/* save i387 and extended state */
 	ret = copy_fpstate_to_sigframe(*fpstate, (void __user *)buf_fx, math_size);
@@ -770,30 +786,8 @@
 
 static inline unsigned long get_nr_restart_syscall(const struct pt_regs *regs)
 {
-	/*
-	 * This function is fundamentally broken as currently
-	 * implemented.
-	 *
-	 * The idea is that we want to trigger a call to the
-	 * restart_block() syscall and that we want in_ia32_syscall(),
-	 * in_x32_syscall(), etc. to match whatever they were in the
-	 * syscall being restarted.  We assume that the syscall
-	 * instruction at (regs->ip - 2) matches whatever syscall
-	 * instruction we used to enter in the first place.
-	 *
-	 * The problem is that we can get here when ptrace pokes
-	 * syscall-like values into regs even if we're not in a syscall
-	 * at all.
-	 *
-	 * For now, we maintain historical behavior and guess based on
-	 * stored state.  We could do better by saving the actual
-	 * syscall arch in restart_block or (with caveats on x32) by
-	 * checking if regs->ip points to 'int $0x80'.  The current
-	 * behavior is incorrect if a tracer has a different bitness
-	 * than the tracee.
-	 */
 #ifdef CONFIG_IA32_EMULATION
-	if (current_thread_info()->status & (TS_COMPAT|TS_I386_REGS_POKED))
+	if (current_thread_info()->status & TS_COMPAT_RESTART)
 		return __NR_ia32_restart_syscall;
 #endif
 #ifdef CONFIG_X86_X32_ABI
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/smp.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/smp.c
@@ -31,7 +31,7 @@
 #include <asm/mce.h>
 #include <asm/trace/irq_vectors.h>
 #include <asm/kexec.h>
-#include <asm/virtext.h>
+#include <asm/reboot.h>
 
 /*
  *	Some notes on x86 processor bugs affecting SMP operation:
@@ -121,7 +121,7 @@
 	if (raw_smp_processor_id() == atomic_read(&stopping_cpu))
 		return NMI_HANDLED;
 
-	cpu_emergency_vmxoff();
+	cpu_emergency_disable_virtualization();
 	stop_this_cpu(NULL);
 
 	return NMI_HANDLED;
@@ -134,7 +134,7 @@
 asmlinkage __visible void smp_reboot_interrupt(void)
 {
 	ipi_entering_ack_irq();
-	cpu_emergency_vmxoff();
+	cpu_emergency_disable_virtualization();
 	stop_this_cpu(NULL);
 	irq_exit();
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/smpboot.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/smpboot.c
@@ -99,6 +99,17 @@
 DEFINE_PER_CPU_READ_MOSTLY(struct cpuinfo_x86, cpu_info);
 EXPORT_PER_CPU_SYMBOL(cpu_info);
 
+struct mwait_cpu_dead {
+	unsigned int	control;
+	unsigned int	status;
+};
+
+/*
+ * Cache line aligned data for mwait_play_dead(). Separate on purpose so
+ * that it's unlikely to be touched by other CPUs.
+ */
+static DEFINE_PER_CPU_ALIGNED(struct mwait_cpu_dead, mwait_cpu_dead);
+
 /* Logical package management. We might want to allocate that dynamically */
 unsigned int __max_logical_packages __read_mostly;
 EXPORT_SYMBOL(__max_logical_packages);
@@ -224,6 +235,8 @@
 #endif
 	load_current_idt();
 	cpu_init();
+	fpu__init_cpu();
+	rcu_cpu_starting(raw_smp_processor_id());
 	x86_cpuinit.early_percpu_clock_init();
 	preempt_disable();
 	smp_callin();
@@ -262,6 +275,14 @@
 
 	wmb();
 	cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
+
+	/*
+	 * Prevent tail call to cpu_startup_entry() because the stack protector
+	 * guard has been changed a couple of function calls up, in
+	 * boot_init_stack_canary() and must not be checked before tail calling
+	 * another function.
+	 */
+	prevent_tail_call_optimization();
 }
 
 /**
@@ -1591,14 +1612,28 @@
 	if (ret)
 		return ret;
 
-	/*
-	 * Disable the local APIC. Otherwise IPI broadcasts will reach
-	 * it. It still responds normally to INIT, NMI, SMI, and SIPI
-	 * messages.
-	 */
-	apic_soft_disable();
 	cpu_disable_common();
 
+        /*
+         * Disable the local APIC. Otherwise IPI broadcasts will reach
+         * it. It still responds normally to INIT, NMI, SMI, and SIPI
+         * messages.
+         *
+         * Disabling the APIC must happen after cpu_disable_common()
+         * which invokes fixup_irqs().
+         *
+         * Disabling the APIC preserves already set bits in IRR, but
+         * an interrupt arriving after disabling the local APIC does not
+         * set the corresponding IRR bit.
+         *
+         * fixup_irqs() scans IRR for set bits so it can raise a not
+         * yet handled interrupt on the new destination CPU via an IPI
+         * but obviously it can't do so for IRR bits which are not set.
+         * IOW, interrupts arriving after disabling the local APIC will
+         * be lost.
+         */
+	apic_soft_disable();
+
 	return 0;
 }
 
@@ -1652,10 +1687,10 @@
  */
 static inline void mwait_play_dead(void)
 {
+	struct mwait_cpu_dead *md = this_cpu_ptr(&mwait_cpu_dead);
 	unsigned int eax, ebx, ecx, edx;
 	unsigned int highest_cstate = 0;
 	unsigned int highest_subcstate = 0;
-	void *mwait_ptr;
 	int i;
 
 	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD ||
@@ -1690,13 +1725,6 @@
 			(highest_subcstate - 1);
 	}
 
-	/*
-	 * This should be a memory location in a cache line which is
-	 * unlikely to be touched by other processors.  The actual
-	 * content is immaterial as it is not actually modified in any way.
-	 */
-	mwait_ptr = &current_thread_info()->flags;
-
 	wbinvd();
 
 	while (1) {
@@ -1708,9 +1736,9 @@
 		 * case where we return around the loop.
 		 */
 		mb();
-		clflush(mwait_ptr);
+		clflush(md);
 		mb();
-		__monitor(mwait_ptr, 0, 0);
+		__monitor(md, 0, 0);
 		mb();
 		__mwait(eax, 0);
 		/*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/stacktrace.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/stacktrace.c
@@ -58,7 +58,6 @@
 			 * or a page fault), which can make frame pointers
 			 * unreliable.
 			 */
-
 			if (IS_ENABLED(CONFIG_FRAME_POINTER))
 				return -EINVAL;
 		}
@@ -81,10 +80,6 @@
 	if (unwind_error(&state))
 		return -EINVAL;
 
-	/* Success path for non-user tasks, i.e. kthreads and idle tasks */
-	if (!(task->flags & (PF_KTHREAD | PF_IDLE)))
-		return -EINVAL;
-
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/step.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/step.c
@@ -175,8 +175,7 @@
 	 *
 	 * NOTE: this means that set/clear TIF_BLOCKSTEP is only safe if
 	 * task is current or it can't be running, otherwise we can race
-	 * with __switch_to_xtra(). We rely on ptrace_freeze_traced() but
-	 * PTRACE_KILL is not safe.
+	 * with __switch_to_xtra(). We rely on ptrace_freeze_traced().
 	 */
 	local_irq_disable();
 	debugctl = get_debugctlmsr();
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/sys_x86_64.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/sys_x86_64.c
@@ -70,9 +70,6 @@
 	if (*str == 0)
 		return 1;
 
-	if (*str == '=')
-		str++;
-
 	if (!strcmp(str, "32"))
 		va_align.flags = ALIGN_VA_32;
 	else if (!strcmp(str, "64"))
@@ -82,11 +79,11 @@
 	else if (!strcmp(str, "on"))
 		va_align.flags = ALIGN_VA_32 | ALIGN_VA_64;
 	else
-		return 0;
+		pr_warn("invalid option value: 'align_va_addr=%s'\n", str);
 
 	return 1;
 }
-__setup("align_va_addr", control_va_addr_alignment);
+__setup("align_va_addr=", control_va_addr_alignment);
 
 SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len,
 		unsigned long, prot, unsigned long, flags,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/sysfb_efi.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/sysfb_efi.c
@@ -264,6 +264,22 @@
 					"Lenovo ideapad D330-10IGM"),
 		},
 	},
+	{
+		/* Lenovo IdeaPad Duet 3 10IGL5 with 1200x1920 portrait screen */
+		.matches = {
+			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+			DMI_EXACT_MATCH(DMI_PRODUCT_VERSION,
+					"IdeaPad Duet 3 10IGL5"),
+		},
+	},
+	{
+		/* Lenovo Yoga Book X91F / X91L */
+		.matches = {
+			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+			/* Non exact match to match F + L versions */
+			DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X91"),
+		},
+	},
 	{},
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/sysfb_simplefb.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/sysfb_simplefb.c
@@ -90,11 +90,11 @@
 	if (si->orig_video_isVGA == VIDEO_TYPE_VLFB)
 		size <<= 16;
 	length = mode->height * mode->stride;
-	length = PAGE_ALIGN(length);
 	if (length > size) {
 		printk(KERN_WARNING "sysfb: VRAM smaller than advertised\n");
 		return -EINVAL;
 	}
+	length = PAGE_ALIGN(length);
 
 	/* setup IORESOURCE_MEM as framebuffer memory */
 	memset(&res, 0, sizeof(res));
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/tboot.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/tboot.c
@@ -512,9 +512,6 @@
 	if (!tboot_enabled())
 		return 0;
 
-	if (intel_iommu_tboot_noforce)
-		return 1;
-
 	if (no_iommu || swiotlb || dmar_disabled)
 		pr_warning("Forcing Intel-IOMMU to enabled\n");
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/time.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/time.c
@@ -25,31 +25,9 @@
 #include <asm/hpet.h>
 #include <asm/time.h>
 
-#ifdef CONFIG_X86_64
-__visible volatile unsigned long jiffies __cacheline_aligned_in_smp = INITIAL_JIFFIES;
-#endif
-
 unsigned long profile_pc(struct pt_regs *regs)
 {
-	unsigned long pc = instruction_pointer(regs);
-
-	if (!user_mode(regs) && in_lock_functions(pc)) {
-#ifdef CONFIG_FRAME_POINTER
-		return *(unsigned long *)(regs->bp + sizeof(long));
-#else
-		unsigned long *sp = (unsigned long *)regs->sp;
-		/*
-		 * Return address is either directly at stack pointer
-		 * or above a saved flags. Eflags has bits 22-31 zero,
-		 * kernel addresses don't.
-		 */
-		if (sp[0] >> 22)
-			return sp[0];
-		if (sp[1] >> 22)
-			return sp[1];
-#endif
-	}
-	return pc;
+	return instruction_pointer(regs);
 }
 EXPORT_SYMBOL(profile_pc);
 
@@ -91,10 +69,18 @@
 
 static __init void x86_late_time_init(void)
 {
+	/*
+	 * Before PIT/HPET init, select the interrupt mode. This is required
+	 * to make the decision whether PIT should be initialized correct.
+	 */
+	x86_init.irqs.intr_mode_select();
+
+	/* Setup the legacy timers */
 	x86_init.timers.timer_init();
+
 	/*
-	 * After PIT/HPET timers init, select and setup
-	 * the final interrupt mode for delivering IRQs.
+	 * After PIT/HPET timers init, set up the final interrupt mode for
+	 * delivering IRQs.
 	 */
 	x86_init.irqs.intr_mode_init();
 	tsc_init();
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/tsc.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/tsc.c
@@ -912,7 +912,7 @@
 
 void tsc_save_sched_clock_state(void)
 {
-	if (!sched_clock_stable())
+	if (!static_branch_likely(&__use_tsc) && !sched_clock_stable())
 		return;
 
 	cyc2ns_suspend = sched_clock();
@@ -932,7 +932,7 @@
 	unsigned long flags;
 	int cpu;
 
-	if (!sched_clock_stable())
+	if (!static_branch_likely(&__use_tsc) && !sched_clock_stable())
 		return;
 
 	local_irq_save(flags);
@@ -1162,6 +1162,12 @@
 
 EXPORT_SYMBOL_GPL(mark_tsc_unstable);
 
+static void __init tsc_disable_clocksource_watchdog(void)
+{
+	clocksource_tsc_early.flags &= ~CLOCK_SOURCE_MUST_VERIFY;
+	clocksource_tsc.flags &= ~CLOCK_SOURCE_MUST_VERIFY;
+}
+
 static void __init check_system_tsc_reliable(void)
 {
 #if defined(CONFIG_MGEODEGX1) || defined(CONFIG_MGEODE_LX) || defined(CONFIG_X86_GENERIC)
@@ -1178,6 +1184,23 @@
 #endif
 	if (boot_cpu_has(X86_FEATURE_TSC_RELIABLE))
 		tsc_clocksource_reliable = 1;
+
+	/*
+	 * Disable the clocksource watchdog when the system has:
+	 *  - TSC running at constant frequency
+	 *  - TSC which does not stop in C-States
+	 *  - the TSC_ADJUST register which allows to detect even minimal
+	 *    modifications
+	 *  - not more than two sockets. As the number of sockets cannot be
+	 *    evaluated at the early boot stage where this has to be
+	 *    invoked, check the number of online memory nodes as a
+	 *    fallback solution which is an reasonable estimate.
+	 */
+	if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC) &&
+	    boot_cpu_has(X86_FEATURE_NONSTOP_TSC) &&
+	    boot_cpu_has(X86_FEATURE_TSC_ADJUST) &&
+	    nr_online_nodes <= 2)
+		tsc_disable_clocksource_watchdog();
 }
 
 /*
@@ -1369,9 +1392,6 @@
 	if (tsc_unstable)
 		goto unreg;
 
-	if (tsc_clocksource_reliable || no_tsc_watchdog)
-		clocksource_tsc.flags &= ~CLOCK_SOURCE_MUST_VERIFY;
-
 	if (boot_cpu_has(X86_FEATURE_NONSTOP_TSC_S3))
 		clocksource_tsc.flags |= CLOCK_SOURCE_SUSPEND_NONSTOP;
 
@@ -1506,7 +1526,7 @@
 	}
 
 	if (tsc_clocksource_reliable || no_tsc_watchdog)
-		clocksource_tsc_early.flags &= ~CLOCK_SOURCE_MUST_VERIFY;
+		tsc_disable_clocksource_watchdog();
 
 	clocksource_register_khz(&clocksource_tsc_early, tsc_khz);
 	detect_art();
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/tsc_msr.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/tsc_msr.c
@@ -15,18 +15,46 @@
 #include <asm/param.h>
 #include <asm/tsc.h>
 
-#define MAX_NUM_FREQS	9
+#define MAX_NUM_FREQS	16 /* 4 bits to select the frequency */
+
+/*
+ * The frequency numbers in the SDM are e.g. 83.3 MHz, which does not contain a
+ * lot of accuracy which leads to clock drift. As far as we know Bay Trail SoCs
+ * use a 25 MHz crystal and Cherry Trail uses a 19.2 MHz crystal, the crystal
+ * is the source clk for a root PLL which outputs 1600 and 100 MHz. It is
+ * unclear if the root PLL outputs are used directly by the CPU clock PLL or
+ * if there is another PLL in between.
+ * This does not matter though, we can model the chain of PLLs as a single PLL
+ * with a quotient equal to the quotients of all PLLs in the chain multiplied.
+ * So we can create a simplified model of the CPU clock setup using a reference
+ * clock of 100 MHz plus a quotient which gets us as close to the frequency
+ * from the SDM as possible.
+ * For the 83.3 MHz example from above this would give us 100 MHz * 5 / 6 =
+ * 83 and 1/3 MHz, which matches exactly what has been measured on actual hw.
+ */
+#define TSC_REFERENCE_KHZ 100000
+
+struct muldiv {
+	u32 multiplier;
+	u32 divider;
+};
 
 /*
  * If MSR_PERF_STAT[31] is set, the maximum resolved bus ratio can be
  * read in MSR_PLATFORM_ID[12:8], otherwise in MSR_PERF_STAT[44:40].
  * Unfortunately some Intel Atom SoCs aren't quite compliant to this,
  * so we need manually differentiate SoC families. This is what the
- * field msr_plat does.
+ * field use_msr_plat does.
  */
 struct freq_desc {
-	u8 msr_plat;	/* 1: use MSR_PLATFORM_INFO, 0: MSR_IA32_PERF_STATUS */
+	bool use_msr_plat;
+	struct muldiv muldiv[MAX_NUM_FREQS];
+	/*
+	 * Some CPU frequencies in the SDM do not map to known PLL freqs, in
+	 * that case the muldiv array is empty and the freqs array is used.
+	 */
 	u32 freqs[MAX_NUM_FREQS];
+	u32 mask;
 };
 
 /*
@@ -35,31 +63,86 @@
  * by MSR based on SDM.
  */
 static const struct freq_desc freq_desc_pnw = {
-	0, { 0, 0, 0, 0, 0, 99840, 0, 83200 }
+	.use_msr_plat = false,
+	.freqs = { 0, 0, 0, 0, 0, 99840, 0, 83200 },
+	.mask = 0x07,
 };
 
 static const struct freq_desc freq_desc_clv = {
-	0, { 0, 133200, 0, 0, 0, 99840, 0, 83200 }
+	.use_msr_plat = false,
+	.freqs = { 0, 133200, 0, 0, 0, 99840, 0, 83200 },
+	.mask = 0x07,
 };
 
+/*
+ * Bay Trail SDM MSR_FSB_FREQ frequencies simplified PLL model:
+ *  000:   100 *  5 /  6  =  83.3333 MHz
+ *  001:   100 *  1 /  1  = 100.0000 MHz
+ *  010:   100 *  4 /  3  = 133.3333 MHz
+ *  011:   100 *  7 /  6  = 116.6667 MHz
+ *  100:   100 *  4 /  5  =  80.0000 MHz
+ */
 static const struct freq_desc freq_desc_byt = {
-	1, { 83300, 100000, 133300, 116700, 80000, 0, 0, 0 }
+	.use_msr_plat = true,
+	.muldiv = { { 5, 6 }, { 1, 1 }, { 4, 3 }, { 7, 6 },
+		    { 4, 5 } },
+	.mask = 0x07,
 };
 
+/*
+ * Cherry Trail SDM MSR_FSB_FREQ frequencies simplified PLL model:
+ * 0000:   100 *  5 /  6  =  83.3333 MHz
+ * 0001:   100 *  1 /  1  = 100.0000 MHz
+ * 0010:   100 *  4 /  3  = 133.3333 MHz
+ * 0011:   100 *  7 /  6  = 116.6667 MHz
+ * 0100:   100 *  4 /  5  =  80.0000 MHz
+ * 0101:   100 * 14 / 15  =  93.3333 MHz
+ * 0110:   100 *  9 / 10  =  90.0000 MHz
+ * 0111:   100 *  8 /  9  =  88.8889 MHz
+ * 1000:   100 *  7 /  8  =  87.5000 MHz
+ */
 static const struct freq_desc freq_desc_cht = {
-	1, { 83300, 100000, 133300, 116700, 80000, 93300, 90000, 88900, 87500 }
+	.use_msr_plat = true,
+	.muldiv = { { 5, 6 }, {  1,  1 }, { 4,  3 }, { 7, 6 },
+		    { 4, 5 }, { 14, 15 }, { 9, 10 }, { 8, 9 },
+		    { 7, 8 } },
+	.mask = 0x0f,
 };
 
+/*
+ * Merriefield SDM MSR_FSB_FREQ frequencies simplified PLL model:
+ * 0001:   100 *  1 /  1  = 100.0000 MHz
+ * 0010:   100 *  4 /  3  = 133.3333 MHz
+ */
 static const struct freq_desc freq_desc_tng = {
-	1, { 0, 100000, 133300, 0, 0, 0, 0, 0 }
+	.use_msr_plat = true,
+	.muldiv = { { 0, 0 }, { 1, 1 }, { 4, 3 } },
+	.mask = 0x07,
 };
 
+/*
+ * Moorefield SDM MSR_FSB_FREQ frequencies simplified PLL model:
+ * 0000:   100 *  5 /  6  =  83.3333 MHz
+ * 0001:   100 *  1 /  1  = 100.0000 MHz
+ * 0010:   100 *  4 /  3  = 133.3333 MHz
+ * 0011:   100 *  1 /  1  = 100.0000 MHz
+ */
 static const struct freq_desc freq_desc_ann = {
-	1, { 83300, 100000, 133300, 100000, 0, 0, 0, 0 }
+	.use_msr_plat = true,
+	.muldiv = { { 5, 6 }, { 1, 1 }, { 4, 3 }, { 1, 1 } },
+	.mask = 0x0f,
 };
 
+/*
+ * 24 MHz crystal? : 24 * 13 / 4 = 78 MHz
+ * Frequency step for Lightning Mountain SoC is fixed to 78 MHz,
+ * so all the frequency entries are 78000.
+ */
 static const struct freq_desc freq_desc_lgm = {
-	1, { 78000, 78000, 78000, 78000, 78000, 78000, 78000, 78000 }
+	.use_msr_plat = true,
+	.freqs = { 78000, 78000, 78000, 78000, 78000, 78000, 78000, 78000,
+		   78000, 78000, 78000, 78000, 78000, 78000, 78000, 78000 },
+	.mask = 0x0f,
 };
 
 static const struct x86_cpu_id tsc_msr_cpu_ids[] = {
@@ -81,17 +164,19 @@
  */
 unsigned long cpu_khz_from_msr(void)
 {
-	u32 lo, hi, ratio, freq;
+	u32 lo, hi, ratio, freq, tscref;
 	const struct freq_desc *freq_desc;
 	const struct x86_cpu_id *id;
+	const struct muldiv *md;
 	unsigned long res;
+	int index;
 
 	id = x86_match_cpu(tsc_msr_cpu_ids);
 	if (!id)
 		return 0;
 
 	freq_desc = (struct freq_desc *)id->driver_data;
-	if (freq_desc->msr_plat) {
+	if (freq_desc->use_msr_plat) {
 		rdmsr(MSR_PLATFORM_INFO, lo, hi);
 		ratio = (lo >> 8) & 0xff;
 	} else {
@@ -101,12 +186,28 @@
 
 	/* Get FSB FREQ ID */
 	rdmsr(MSR_FSB_FREQ, lo, hi);
+	index = lo & freq_desc->mask;
+	md = &freq_desc->muldiv[index];
 
-	/* Map CPU reference clock freq ID(0-7) to CPU reference clock freq(KHz) */
-	freq = freq_desc->freqs[lo & 0x7];
+	/*
+	 * Note this also catches cases where the index points to an unpopulated
+	 * part of muldiv, in that case the else will set freq and res to 0.
+	 */
+	if (md->divider) {
+		tscref = TSC_REFERENCE_KHZ * md->multiplier;
+		freq = DIV_ROUND_CLOSEST(tscref, md->divider);
+		/*
+		 * Multiplying by ratio before the division has better
+		 * accuracy than just calculating freq * ratio.
+		 */
+		res = DIV_ROUND_CLOSEST(tscref * ratio, md->divider);
+	} else {
+		freq = freq_desc->freqs[index];
+		res = freq * ratio;
+	}
 
-	/* TSC frequency = maximum resolved freq * maximum resolved bus ratio */
-	res = freq * ratio;
+	if (freq == 0)
+		pr_err("Error MSR_FSB_FREQ index %d is unknown\n", index);
 
 #ifdef CONFIG_X86_LOCAL_APIC
 	lapic_timer_period = (freq * 1000) / HZ;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/tsc_sync.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/tsc_sync.c
@@ -30,6 +30,7 @@
 };
 
 static DEFINE_PER_CPU(struct tsc_adjust, tsc_adjust);
+static struct timer_list tsc_sync_check_timer;
 
 /*
  * TSC's on different sockets may be reset asynchronously.
@@ -77,6 +78,46 @@
 	}
 }
 
+/*
+ * Normally the tsc_sync will be checked every time system enters idle
+ * state, but there is still caveat that a system won't enter idle,
+ * either because it's too busy or configured purposely to not enter
+ * idle.
+ *
+ * So setup a periodic timer (every 10 minutes) to make sure the check
+ * is always on.
+ */
+
+#define SYNC_CHECK_INTERVAL		(HZ * 600)
+
+static void tsc_sync_check_timer_fn(struct timer_list *unused)
+{
+	int next_cpu;
+
+	tsc_verify_tsc_adjust(false);
+
+	/* Run the check for all onlined CPUs in turn */
+	next_cpu = cpumask_next(raw_smp_processor_id(), cpu_online_mask);
+	if (next_cpu >= nr_cpu_ids)
+		next_cpu = cpumask_first(cpu_online_mask);
+
+	tsc_sync_check_timer.expires += SYNC_CHECK_INTERVAL;
+	add_timer_on(&tsc_sync_check_timer, next_cpu);
+}
+
+static int __init start_sync_check_timer(void)
+{
+	if (!cpu_feature_enabled(X86_FEATURE_TSC_ADJUST) || tsc_clocksource_reliable)
+		return 0;
+
+	timer_setup(&tsc_sync_check_timer, tsc_sync_check_timer_fn, 0);
+	tsc_sync_check_timer.expires = jiffies + SYNC_CHECK_INTERVAL;
+	add_timer(&tsc_sync_check_timer);
+
+	return 0;
+}
+late_initcall(start_sync_check_timer);
+
 static void tsc_sanitize_first_cpu(struct tsc_adjust *cur, s64 bootval,
 				   unsigned int cpu, bool bootcpu)
 {
@@ -151,11 +192,9 @@
 	cur->warned = false;
 
 	/*
-	 * If a non-zero TSC value for socket 0 may be valid then the default
-	 * adjusted value cannot assumed to be zero either.
+	 * The default adjust value cannot be assumed to be zero on any socket.
 	 */
-	if (tsc_async_resets)
-		cur->adjusted = bootval;
+	cur->adjusted = bootval;
 
 	/*
 	 * Check whether this CPU is the first in a package to come up. In
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/unwind_orc.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/unwind_orc.c
@@ -90,22 +90,27 @@
 static struct orc_entry *orc_ftrace_find(unsigned long ip)
 {
 	struct ftrace_ops *ops;
-	unsigned long caller;
+	unsigned long tramp_addr, offset;
 
 	ops = ftrace_ops_trampoline(ip);
 	if (!ops)
 		return NULL;
 
+	/* Set tramp_addr to the start of the code copied by the trampoline */
 	if (ops->flags & FTRACE_OPS_FL_SAVE_REGS)
-		caller = (unsigned long)ftrace_regs_call;
+		tramp_addr = (unsigned long)ftrace_regs_caller;
 	else
-		caller = (unsigned long)ftrace_call;
+		tramp_addr = (unsigned long)ftrace_caller;
+
+	/* Now place tramp_addr to the location within the trampoline ip is at */
+	offset = ip - ops->trampoline;
+	tramp_addr += offset;
 
 	/* Prevent unlikely recursion */
-	if (ip == caller)
+	if (ip == tramp_addr)
 		return NULL;
 
-	return orc_find(caller);
+	return orc_find(tramp_addr);
 }
 #else
 static struct orc_entry *orc_ftrace_find(unsigned long ip)
@@ -142,9 +147,6 @@
 {
 	static struct orc_entry *orc;
 
-	if (!orc_init)
-		return NULL;
-
 	if (ip == 0)
 		return &null_orc_entry;
 
@@ -360,8 +362,8 @@
 	if (!stack_access_ok(state, addr, sizeof(struct pt_regs)))
 		return false;
 
-	*ip = regs->ip;
-	*sp = regs->sp;
+	*ip = READ_ONCE_NOCHECK(regs->ip);
+	*sp = READ_ONCE_NOCHECK(regs->sp);
 	return true;
 }
 
@@ -373,14 +375,43 @@
 	if (!stack_access_ok(state, addr, IRET_FRAME_SIZE))
 		return false;
 
-	*ip = regs->ip;
-	*sp = regs->sp;
+	*ip = READ_ONCE_NOCHECK(regs->ip);
+	*sp = READ_ONCE_NOCHECK(regs->sp);
 	return true;
 }
 
+/*
+ * If state->regs is non-NULL, and points to a full pt_regs, just get the reg
+ * value from state->regs.
+ *
+ * Otherwise, if state->regs just points to IRET regs, and the previous frame
+ * had full regs, it's safe to get the value from the previous regs.  This can
+ * happen when early/late IRQ entry code gets interrupted by an NMI.
+ */
+static bool get_reg(struct unwind_state *state, unsigned int reg_off,
+		    unsigned long *val)
+{
+	unsigned int reg = reg_off/8;
+
+	if (!state->regs)
+		return false;
+
+	if (state->full_regs) {
+		*val = READ_ONCE_NOCHECK(((unsigned long *)state->regs)[reg]);
+		return true;
+	}
+
+	if (state->prev_regs) {
+		*val = READ_ONCE_NOCHECK(((unsigned long *)state->prev_regs)[reg]);
+		return true;
+	}
+
+	return false;
+}
+
 bool unwind_next_frame(struct unwind_state *state)
 {
-	unsigned long ip_p, sp, orig_ip = state->ip, prev_sp = state->sp;
+	unsigned long ip_p, sp, tmp, orig_ip = state->ip, prev_sp = state->sp;
 	enum stack_type prev_type = state->stack_info.type;
 	struct orc_entry *orc;
 	bool indirect = false;
@@ -398,8 +429,11 @@
 	/*
 	 * Find the orc_entry associated with the text address.
 	 *
-	 * Decrement call return addresses by one so they work for sibling
-	 * calls and calls to noreturn functions.
+	 * For a call frame (as opposed to a signal frame), state->ip points to
+	 * the instruction after the call.  That instruction's stack layout
+	 * could be different from the call instruction's layout, for example
+	 * if the call was to a noreturn function.  So get the ORC data for the
+	 * call instruction itself.
 	 */
 	orc = orc_find(state->signal ? state->ip : state->ip - 1);
 	if (!orc) {
@@ -442,39 +476,35 @@
 		break;
 
 	case ORC_REG_R10:
-		if (!state->regs || !state->full_regs) {
+		if (!get_reg(state, offsetof(struct pt_regs, r10), &sp)) {
 			orc_warn("missing regs for base reg R10 at ip %pB\n",
 				 (void *)state->ip);
 			goto err;
 		}
-		sp = state->regs->r10;
 		break;
 
 	case ORC_REG_R13:
-		if (!state->regs || !state->full_regs) {
+		if (!get_reg(state, offsetof(struct pt_regs, r13), &sp)) {
 			orc_warn("missing regs for base reg R13 at ip %pB\n",
 				 (void *)state->ip);
 			goto err;
 		}
-		sp = state->regs->r13;
 		break;
 
 	case ORC_REG_DI:
-		if (!state->regs || !state->full_regs) {
+		if (!get_reg(state, offsetof(struct pt_regs, di), &sp)) {
 			orc_warn("missing regs for base reg DI at ip %pB\n",
 				 (void *)state->ip);
 			goto err;
 		}
-		sp = state->regs->di;
 		break;
 
 	case ORC_REG_DX:
-		if (!state->regs || !state->full_regs) {
+		if (!get_reg(state, offsetof(struct pt_regs, dx), &sp)) {
 			orc_warn("missing regs for base reg DX at ip %pB\n",
 				 (void *)state->ip);
 			goto err;
 		}
-		sp = state->regs->dx;
 		break;
 
 	default:
@@ -501,6 +531,7 @@
 
 		state->sp = sp;
 		state->regs = NULL;
+		state->prev_regs = NULL;
 		state->signal = false;
 		break;
 
@@ -512,6 +543,7 @@
 		}
 
 		state->regs = (struct pt_regs *)sp;
+		state->prev_regs = NULL;
 		state->full_regs = true;
 		state->signal = true;
 		break;
@@ -523,6 +555,8 @@
 			goto err;
 		}
 
+		if (state->full_regs)
+			state->prev_regs = state->regs;
 		state->regs = (void *)sp - IRET_FRAME_OFFSET;
 		state->full_regs = false;
 		state->signal = true;
@@ -531,14 +565,14 @@
 	default:
 		orc_warn("unknown .orc_unwind entry type %d for ip %pB\n",
 			 orc->type, (void *)orig_ip);
-		break;
+		goto err;
 	}
 
 	/* Find BP: */
 	switch (orc->bp_reg) {
 	case ORC_REG_UNDEFINED:
-		if (state->regs && state->full_regs)
-			state->bp = state->regs->bp;
+		if (get_reg(state, offsetof(struct pt_regs, bp), &tmp))
+			state->bp = tmp;
 		break;
 
 	case ORC_REG_PREV_SP:
@@ -585,17 +619,20 @@
 	memset(state, 0, sizeof(*state));
 	state->task = task;
 
+	if (!orc_init)
+		goto err;
+
 	/*
 	 * Refuse to unwind the stack of a task while it's executing on another
 	 * CPU.  This check is racy, but that's ok: the unwinder has other
 	 * checks to prevent it from going off the rails.
 	 */
 	if (task_on_another_cpu(task))
-		goto done;
+		goto err;
 
 	if (regs) {
 		if (user_mode(regs))
-			goto done;
+			goto the_end;
 
 		state->ip = regs->ip;
 		state->sp = regs->sp;
@@ -614,9 +651,10 @@
 	} else {
 		struct inactive_task_frame *frame = (void *)task->thread.sp;
 
-		state->sp = task->thread.sp;
+		state->sp = task->thread.sp + sizeof(*frame);
 		state->bp = READ_ONCE_NOCHECK(frame->bp);
 		state->ip = READ_ONCE_NOCHECK(frame->ret_addr);
+		state->signal = (void *)state->ip == ret_from_fork;
 	}
 
 	if (get_stack_info((unsigned long *)state->sp, state->task,
@@ -628,6 +666,7 @@
 		 * generate some kind of backtrace if this happens.
 		 */
 		void *next_page = (void *)PAGE_ALIGN((unsigned long)state->sp);
+		state->error = true;
 		if (get_stack_info(next_page, state->task, &state->stack_info,
 				   &state->stack_mask))
 			return;
@@ -653,8 +692,9 @@
 
 	return;
 
-done:
+err:
+	state->error = true;
+the_end:
 	state->stack_info.type = STACK_TYPE_UNKNOWN;
-	return;
 }
 EXPORT_SYMBOL_GPL(__unwind_start);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/uprobes.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/uprobes.c
@@ -255,12 +255,13 @@
 
 static bool is_prefix_bad(struct insn *insn)
 {
+	insn_byte_t p;
 	int i;
 
-	for (i = 0; i < insn->prefixes.nbytes; i++) {
+	for_each_insn_prefix(insn, i, p) {
 		insn_attr_t attr;
 
-		attr = inat_get_opcode_attribute(insn->prefixes.bytes[i]);
+		attr = inat_get_opcode_attribute(p);
 		switch (attr) {
 		case INAT_MAKE_PREFIX(INAT_PFX_ES):
 		case INAT_MAKE_PREFIX(INAT_PFX_CS):
@@ -715,13 +716,15 @@
 static int branch_setup_xol_ops(struct arch_uprobe *auprobe, struct insn *insn)
 {
 	u8 opc1 = OPCODE1(insn);
+	insn_byte_t p;
 	int i;
 
 	switch (opc1) {
 	case 0xeb:	/* jmp 8 */
 	case 0xe9:	/* jmp 32 */
-	case 0x90:	/* prefix* + nop; same as jmp with .offs = 0 */
 		break;
+	case 0x90:	/* prefix* + nop; same as jmp with .offs = 0 */
+		goto setup;
 
 	case 0xe8:	/* call relative */
 		branch_clear_offset(auprobe, insn);
@@ -746,11 +749,12 @@
 	 * Intel and AMD behavior differ in 64-bit mode: Intel ignores 66 prefix.
 	 * No one uses these insns, reject any branch insns with such prefix.
 	 */
-	for (i = 0; i < insn->prefixes.nbytes; i++) {
-		if (insn->prefixes.bytes[i] == 0x66)
+	for_each_insn_prefix(insn, i, p) {
+		if (p == 0x66)
 			return -ENOTSUPP;
 	}
 
+setup:
 	auprobe->branch.opc1 = opc1;
 	auprobe->branch.ilen = insn->length;
 	auprobe->branch.offs = insn->immediate.value;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/vmlinux.lds.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/vmlinux.lds.S
@@ -21,6 +21,8 @@
 #define LOAD_OFFSET __START_KERNEL_map
 #endif
 
+#define RUNTIME_DISCARD_EXIT
+
 #include <asm-generic/vmlinux.lds.h>
 #include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
@@ -36,13 +38,13 @@
 #ifdef CONFIG_X86_32
 OUTPUT_ARCH(i386)
 ENTRY(phys_startup_32)
-jiffies = jiffies_64;
 #else
 OUTPUT_ARCH(i386:x86-64)
 ENTRY(phys_startup_64)
-jiffies_64 = jiffies;
 #endif
 
+jiffies = jiffies_64;
+
 #if defined(CONFIG_X86_64)
 /*
  * On 64-bit, align RODATA to 2MB so we retain large page mappings for
@@ -362,6 +364,7 @@
 	.bss : AT(ADDR(.bss) - LOAD_OFFSET) {
 		__bss_start = .;
 		*(.bss..page_aligned)
+		. = ALIGN(PAGE_SIZE);
 		*(BSS_MAIN)
 		BSS_DECRYPTED
 		. = ALIGN(PAGE_SIZE);
@@ -380,7 +383,7 @@
 	.brk : AT(ADDR(.brk) - LOAD_OFFSET) {
 		__brk_base = .;
 		. += 64 * 1024;		/* 64k alignment slop space */
-		*(.brk_reservation)	/* areas brk users have reserved */
+		*(.bss..brk)		/* areas brk users have reserved */
 		__brk_limit = .;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kernel/x86_init.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kernel/x86_init.c
@@ -58,6 +58,7 @@
 		.pre_vector_init	= init_ISA_irqs,
 		.intr_init		= native_init_IRQ,
 		.trap_init		= x86_init_noop,
+		.intr_mode_select	= apic_intr_mode_select,
 		.intr_mode_init		= apic_intr_mode_init
 	},
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kvm/cpuid.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kvm/cpuid.c
@@ -352,6 +352,7 @@
 	unsigned f_umip = kvm_x86_ops->umip_emulated() ? F(UMIP) : 0;
 	unsigned f_intel_pt = kvm_x86_ops->pt_supported() ? F(INTEL_PT) : 0;
 	unsigned f_la57;
+	unsigned f_pku = kvm_x86_ops->pku_supported() ? F(PKU) : 0;
 
 	/* cpuid 7.0.ebx */
 	const u32 kvm_cpuid_7_0_ebx_x86_features =
@@ -363,7 +364,7 @@
 
 	/* cpuid 7.0.ecx*/
 	const u32 kvm_cpuid_7_0_ecx_x86_features =
-		F(AVX512VBMI) | F(LA57) | F(PKU) | 0 /*OSPKE*/ | F(RDPID) |
+		F(AVX512VBMI) | F(LA57) | 0 /*PKU*/ | 0 /*OSPKE*/ | F(RDPID) |
 		F(AVX512_VPOPCNTDQ) | F(UMIP) | F(AVX512_VBMI2) | F(GFNI) |
 		F(VAES) | F(VPCLMULQDQ) | F(AVX512_VNNI) | F(AVX512_BITALG) |
 		F(CLDEMOTE) | F(MOVDIRI) | F(MOVDIR64B) | 0 /*WAITPKG*/;
@@ -392,6 +393,7 @@
 		/* Set LA57 based on hardware capability. */
 		entry->ecx |= f_la57;
 		entry->ecx |= f_umip;
+		entry->ecx |= f_pku;
 		/* PKU is not yet implemented for shadow paging. */
 		if (!tdp_enabled || !boot_cpu_has(X86_FEATURE_OSPKE))
 			entry->ecx &= ~F(PKU);
@@ -402,7 +404,8 @@
 			entry->edx |= F(SPEC_CTRL);
 		if (boot_cpu_has(X86_FEATURE_STIBP))
 			entry->edx |= F(INTEL_STIBP);
-		if (boot_cpu_has(X86_FEATURE_SSBD))
+		if (boot_cpu_has(X86_FEATURE_SPEC_CTRL_SSBD) ||
+		    boot_cpu_has(X86_FEATURE_AMD_SSBD))
 			entry->edx |= F(SPEC_CTRL_SSBD);
 		/*
 		 * We emulate ARCH_CAPABILITIES in software even
@@ -504,7 +507,7 @@
 
 	r = -E2BIG;
 
-	if (*nent >= maxnent)
+	if (WARN_ON(*nent >= maxnent))
 		goto out;
 
 	do_host_cpuid(entry, function, 0);
@@ -589,6 +592,11 @@
 		union cpuid10_eax eax;
 		union cpuid10_edx edx;
 
+		if (!static_cpu_has(X86_FEATURE_ARCH_PERFMON)) {
+			entry->eax = entry->ebx = entry->ecx = entry->edx = 0;
+			break;
+		}
+
 		perf_get_x86_pmu_capability(&cap);
 
 		/*
@@ -742,9 +750,16 @@
 		unsigned virt_as = max((entry->eax >> 8) & 0xff, 48U);
 		unsigned phys_as = entry->eax & 0xff;
 
-		if (!g_phys_as)
+		/*
+		 * Use bare metal's MAXPHADDR if the CPU doesn't report guest
+		 * MAXPHYADDR separately, or if TDP (NPT) is disabled, as the
+		 * guest version "applies only to guests using nested paging".
+		 */
+		if (!g_phys_as || !tdp_enabled)
 			g_phys_as = phys_as;
+
 		entry->eax = g_phys_as | (virt_as << 8);
+		entry->ecx &= ~(GENMASK(31, 16) | GENMASK(11, 8));
 		entry->edx = 0;
 		entry->ebx &= kvm_cpuid_8000_0008_ebx_x86_features;
 		cpuid_mask(&entry->ebx, CPUID_8000_0008_EBX);
@@ -759,7 +774,8 @@
 			entry->ebx |= F(AMD_IBRS);
 		if (boot_cpu_has(X86_FEATURE_STIBP))
 			entry->ebx |= F(AMD_STIBP);
-		if (boot_cpu_has(X86_FEATURE_SSBD))
+		if (boot_cpu_has(X86_FEATURE_SPEC_CTRL_SSBD) ||
+		    boot_cpu_has(X86_FEATURE_AMD_SSBD))
 			entry->ebx |= F(AMD_SSBD);
 		if (!boot_cpu_has_bug(X86_BUG_SPEC_STORE_BYPASS))
 			entry->ebx |= F(AMD_SSB_NO);
@@ -776,6 +792,9 @@
 		entry->ecx = entry->edx = 0;
 		break;
 	case 0x8000001a:
+		entry->eax &= GENMASK(2, 0);
+		entry->ebx = entry->ecx = entry->edx = 0;
+		break;
 	case 0x8000001e:
 		break;
 	/*Add support for Centaur's CPUID instruction*/
@@ -810,6 +829,9 @@
 static int do_cpuid_func(struct kvm_cpuid_entry2 *entry, u32 func,
 			 int *nent, int maxnent, unsigned int type)
 {
+	if (*nent >= maxnent)
+		return -E2BIG;
+
 	if (type == KVM_GET_EMULATED_CPUID)
 		return __do_cpuid_func_emulated(entry, func, nent, maxnent);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kvm/cpuid.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kvm/cpuid.h
@@ -53,12 +53,15 @@
 	[CPUID_7_ECX]         = {         7, 0, CPUID_ECX},
 	[CPUID_8000_0007_EBX] = {0x80000007, 0, CPUID_EBX},
 	[CPUID_7_EDX]         = {         7, 0, CPUID_EDX},
+	[CPUID_8000_0021_EAX] = {0x80000021, 0, CPUID_EAX},
 };
 
 static __always_inline struct cpuid_reg x86_feature_cpuid(unsigned x86_feature)
 {
 	unsigned x86_leaf = x86_feature / 32;
 
+	BUILD_BUG_ON(NR_CPUID_WORDS != NCAPINTS);
+	BUILD_BUG_ON(x86_leaf == CPUID_LNX_5);
 	BUILD_BUG_ON(x86_leaf >= ARRAY_SIZE(reverse_cpuid));
 	BUILD_BUG_ON(reverse_cpuid[x86_leaf].function == 0);
 
@@ -154,6 +157,20 @@
 	return x86_stepping(best->eax);
 }
 
+static inline bool guest_has_spec_ctrl_msr(struct kvm_vcpu *vcpu)
+{
+	return (guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL) ||
+		guest_cpuid_has(vcpu, X86_FEATURE_AMD_STIBP) ||
+		guest_cpuid_has(vcpu, X86_FEATURE_AMD_IBRS) ||
+		guest_cpuid_has(vcpu, X86_FEATURE_AMD_SSBD));
+}
+
+static inline bool guest_has_pred_cmd_msr(struct kvm_vcpu *vcpu)
+{
+	return (guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL) ||
+		guest_cpuid_has(vcpu, X86_FEATURE_AMD_IBPB));
+}
+
 static inline bool supports_cpuid_fault(struct kvm_vcpu *vcpu)
 {
 	return vcpu->arch.msr_platform_info & MSR_PLATFORM_INFO_CPUID_FAULT;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kvm/emulate.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kvm/emulate.c
@@ -22,6 +22,7 @@
 #include "kvm_cache_regs.h"
 #include <asm/kvm_emulate.h>
 #include <linux/stringify.h>
+#include <asm/fpu/api.h>
 #include <asm/debugreg.h>
 #include <asm/nospec-branch.h>
 
@@ -775,8 +776,7 @@
 			   ctxt->mode, linear);
 }
 
-static inline int assign_eip(struct x86_emulate_ctxt *ctxt, ulong dst,
-			     enum x86emul_mode mode)
+static inline int assign_eip(struct x86_emulate_ctxt *ctxt, ulong dst)
 {
 	ulong linear;
 	int rc;
@@ -786,41 +786,71 @@
 
 	if (ctxt->op_bytes != sizeof(unsigned long))
 		addr.ea = dst & ((1UL << (ctxt->op_bytes << 3)) - 1);
-	rc = __linearize(ctxt, addr, &max_size, 1, false, true, mode, &linear);
+	rc = __linearize(ctxt, addr, &max_size, 1, false, true, ctxt->mode, &linear);
 	if (rc == X86EMUL_CONTINUE)
 		ctxt->_eip = addr.ea;
 	return rc;
 }
 
+static inline int emulator_recalc_and_set_mode(struct x86_emulate_ctxt *ctxt)
+{
+	u64 efer;
+	struct desc_struct cs;
+	u16 selector;
+	u32 base3;
+
+	ctxt->ops->get_msr(ctxt, MSR_EFER, &efer);
+
+	if (!(ctxt->ops->get_cr(ctxt, 0) & X86_CR0_PE)) {
+		/* Real mode. cpu must not have long mode active */
+		if (efer & EFER_LMA)
+			return X86EMUL_UNHANDLEABLE;
+		ctxt->mode = X86EMUL_MODE_REAL;
+		return X86EMUL_CONTINUE;
+	}
+
+	if (ctxt->eflags & X86_EFLAGS_VM) {
+		/* Protected/VM86 mode. cpu must not have long mode active */
+		if (efer & EFER_LMA)
+			return X86EMUL_UNHANDLEABLE;
+		ctxt->mode = X86EMUL_MODE_VM86;
+		return X86EMUL_CONTINUE;
+	}
+
+	if (!ctxt->ops->get_segment(ctxt, &selector, &cs, &base3, VCPU_SREG_CS))
+		return X86EMUL_UNHANDLEABLE;
+
+	if (efer & EFER_LMA) {
+		if (cs.l) {
+			/* Proper long mode */
+			ctxt->mode = X86EMUL_MODE_PROT64;
+		} else if (cs.d) {
+			/* 32 bit compatibility mode*/
+			ctxt->mode = X86EMUL_MODE_PROT32;
+		} else {
+			ctxt->mode = X86EMUL_MODE_PROT16;
+		}
+	} else {
+		/* Legacy 32 bit / 16 bit mode */
+		ctxt->mode = cs.d ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16;
+	}
+
+	return X86EMUL_CONTINUE;
+}
+
 static inline int assign_eip_near(struct x86_emulate_ctxt *ctxt, ulong dst)
 {
-	return assign_eip(ctxt, dst, ctxt->mode);
+	return assign_eip(ctxt, dst);
 }
 
-static int assign_eip_far(struct x86_emulate_ctxt *ctxt, ulong dst,
-			  const struct desc_struct *cs_desc)
+static int assign_eip_far(struct x86_emulate_ctxt *ctxt, ulong dst)
 {
-	enum x86emul_mode mode = ctxt->mode;
-	int rc;
+	int rc = emulator_recalc_and_set_mode(ctxt);
 
-#ifdef CONFIG_X86_64
-	if (ctxt->mode >= X86EMUL_MODE_PROT16) {
-		if (cs_desc->l) {
-			u64 efer = 0;
+	if (rc != X86EMUL_CONTINUE)
+		return rc;
 
-			ctxt->ops->get_msr(ctxt, MSR_EFER, &efer);
-			if (efer & EFER_LMA)
-				mode = X86EMUL_MODE_PROT64;
-		} else
-			mode = X86EMUL_MODE_PROT32; /* temporary value */
-	}
-#endif
-	if (mode == X86EMUL_MODE_PROT16 || mode == X86EMUL_MODE_PROT32)
-		mode = cs_desc->d ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16;
-	rc = assign_eip(ctxt, dst, mode);
-	if (rc == X86EMUL_CONTINUE)
-		ctxt->mode = mode;
-	return rc;
+	return assign_eip(ctxt, dst);
 }
 
 static inline int jmp_rel(struct x86_emulate_ctxt *ctxt, int rel)
@@ -1075,8 +1105,23 @@
 	}
 }
 
+static void emulator_get_fpu(void)
+{
+	fpregs_lock();
+
+	fpregs_assert_state_consistent();
+	if (test_thread_flag(TIF_NEED_FPU_LOAD))
+		switch_fpu_return();
+}
+
+static void emulator_put_fpu(void)
+{
+	fpregs_unlock();
+}
+
 static void read_sse_reg(struct x86_emulate_ctxt *ctxt, sse128_t *data, int reg)
 {
+	emulator_get_fpu();
 	switch (reg) {
 	case 0: asm("movdqa %%xmm0, %0" : "=m"(*data)); break;
 	case 1: asm("movdqa %%xmm1, %0" : "=m"(*data)); break;
@@ -1098,11 +1143,13 @@
 #endif
 	default: BUG();
 	}
+	emulator_put_fpu();
 }
 
 static void write_sse_reg(struct x86_emulate_ctxt *ctxt, sse128_t *data,
 			  int reg)
 {
+	emulator_get_fpu();
 	switch (reg) {
 	case 0: asm("movdqa %0, %%xmm0" : : "m"(*data)); break;
 	case 1: asm("movdqa %0, %%xmm1" : : "m"(*data)); break;
@@ -1124,10 +1171,12 @@
 #endif
 	default: BUG();
 	}
+	emulator_put_fpu();
 }
 
 static void read_mmx_reg(struct x86_emulate_ctxt *ctxt, u64 *data, int reg)
 {
+	emulator_get_fpu();
 	switch (reg) {
 	case 0: asm("movq %%mm0, %0" : "=m"(*data)); break;
 	case 1: asm("movq %%mm1, %0" : "=m"(*data)); break;
@@ -1139,10 +1188,12 @@
 	case 7: asm("movq %%mm7, %0" : "=m"(*data)); break;
 	default: BUG();
 	}
+	emulator_put_fpu();
 }
 
 static void write_mmx_reg(struct x86_emulate_ctxt *ctxt, u64 *data, int reg)
 {
+	emulator_get_fpu();
 	switch (reg) {
 	case 0: asm("movq %0, %%mm0" : : "m"(*data)); break;
 	case 1: asm("movq %0, %%mm1" : : "m"(*data)); break;
@@ -1154,6 +1205,7 @@
 	case 7: asm("movq %0, %%mm7" : : "m"(*data)); break;
 	default: BUG();
 	}
+	emulator_put_fpu();
 }
 
 static int em_fninit(struct x86_emulate_ctxt *ctxt)
@@ -1161,7 +1213,9 @@
 	if (ctxt->ops->get_cr(ctxt, 0) & (X86_CR0_TS | X86_CR0_EM))
 		return emulate_nm(ctxt);
 
+	emulator_get_fpu();
 	asm volatile("fninit");
+	emulator_put_fpu();
 	return X86EMUL_CONTINUE;
 }
 
@@ -1172,7 +1226,9 @@
 	if (ctxt->ops->get_cr(ctxt, 0) & (X86_CR0_TS | X86_CR0_EM))
 		return emulate_nm(ctxt);
 
+	emulator_get_fpu();
 	asm volatile("fnstcw %0": "+m"(fcw));
+	emulator_put_fpu();
 
 	ctxt->dst.val = fcw;
 
@@ -1186,7 +1242,9 @@
 	if (ctxt->ops->get_cr(ctxt, 0) & (X86_CR0_TS | X86_CR0_EM))
 		return emulate_nm(ctxt);
 
+	emulator_get_fpu();
 	asm volatile("fnstsw %0": "+m"(fsw));
+	emulator_put_fpu();
 
 	ctxt->dst.val = fsw;
 
@@ -1685,11 +1743,6 @@
 		goto exception;
 	}
 
-	if (!seg_desc.p) {
-		err_vec = (seg == VCPU_SREG_SS) ? SS_VECTOR : NP_VECTOR;
-		goto exception;
-	}
-
 	dpl = seg_desc.dpl;
 
 	switch (seg) {
@@ -1729,12 +1782,6 @@
 	case VCPU_SREG_TR:
 		if (seg_desc.s || (seg_desc.type != 1 && seg_desc.type != 9))
 			goto exception;
-		old_desc = seg_desc;
-		seg_desc.type |= 2; /* busy */
-		ret = ctxt->ops->cmpxchg_emulated(ctxt, desc_addr, &old_desc, &seg_desc,
-						  sizeof(seg_desc), &ctxt->exception);
-		if (ret != X86EMUL_CONTINUE)
-			return ret;
 		break;
 	case VCPU_SREG_LDTR:
 		if (seg_desc.s || seg_desc.type != 2)
@@ -1753,6 +1800,11 @@
 		break;
 	}
 
+	if (!seg_desc.p) {
+		err_vec = (seg == VCPU_SREG_SS) ? SS_VECTOR : NP_VECTOR;
+		goto exception;
+	}
+
 	if (seg_desc.s) {
 		/* mark segment as accessed */
 		if (!(seg_desc.type & 1)) {
@@ -1767,8 +1819,17 @@
 		if (ret != X86EMUL_CONTINUE)
 			return ret;
 		if (emul_is_noncanonical_address(get_desc_base(&seg_desc) |
-				((u64)base3 << 32), ctxt))
-			return emulate_gp(ctxt, 0);
+						 ((u64)base3 << 32), ctxt))
+			return emulate_gp(ctxt, err_code);
+	}
+
+	if (seg == VCPU_SREG_TR) {
+		old_desc = seg_desc;
+		seg_desc.type |= 2; /* busy */
+		ret = ctxt->ops->cmpxchg_emulated(ctxt, desc_addr, &old_desc, &seg_desc,
+						  sizeof(seg_desc), &ctxt->exception);
+		if (ret != X86EMUL_CONTINUE)
+			return ret;
 	}
 load:
 	ctxt->ops->set_segment(ctxt, selector, &seg_desc, base3, seg);
@@ -1988,7 +2049,7 @@
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
 
-	if (ctxt->modrm_reg == VCPU_SREG_SS)
+	if (seg == VCPU_SREG_SS)
 		ctxt->interruptibility = KVM_X86_SHADOW_INT_MOV_SS;
 	if (ctxt->op_bytes > 2)
 		rsp_increment(ctxt, ctxt->op_bytes - 2);
@@ -2205,7 +2266,7 @@
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
 
-	rc = assign_eip_far(ctxt, ctxt->src.val, &new_desc);
+	rc = assign_eip_far(ctxt, ctxt->src.val);
 	/* Error handling is not implemented. */
 	if (rc != X86EMUL_CONTINUE)
 		return X86EMUL_UNHANDLEABLE;
@@ -2286,7 +2347,7 @@
 				       &new_desc);
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
-	rc = assign_eip_far(ctxt, eip, &new_desc);
+	rc = assign_eip_far(ctxt, eip);
 	/* Error handling is not implemented. */
 	if (rc != X86EMUL_CONTINUE)
 		return X86EMUL_UNHANDLEABLE;
@@ -2861,6 +2922,8 @@
 	ops->get_msr(ctxt, MSR_IA32_SYSENTER_ESP, &msr_data);
 	*reg_write(ctxt, VCPU_REGS_RSP) = (efer & EFER_LMA) ? msr_data :
 							      (u32)msr_data;
+	if (efer & EFER_LMA)
+		ctxt->mode = X86EMUL_MODE_PROT64;
 
 	return X86EMUL_CONTINUE;
 }
@@ -2919,6 +2982,7 @@
 	ops->set_segment(ctxt, ss_sel, &ss, 0, VCPU_SREG_SS);
 
 	ctxt->_eip = rdx;
+	ctxt->mode = usermode;
 	*reg_write(ctxt, VCPU_REGS_RSP) = rcx;
 
 	return X86EMUL_CONTINUE;
@@ -3515,7 +3579,7 @@
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
 
-	rc = assign_eip_far(ctxt, ctxt->src.val, &new_desc);
+	rc = assign_eip_far(ctxt, ctxt->src.val);
 	if (rc != X86EMUL_CONTINUE)
 		goto fail;
 
@@ -3588,7 +3652,7 @@
 	u64 tsc_aux = 0;
 
 	if (ctxt->ops->get_msr(ctxt, MSR_TSC_AUX, &tsc_aux))
-		return emulate_gp(ctxt, 0);
+		return emulate_ud(ctxt);
 	ctxt->dst.val = tsc_aux;
 	return X86EMUL_CONTINUE;
 }
@@ -3662,11 +3726,25 @@
 
 static int em_cr_write(struct x86_emulate_ctxt *ctxt)
 {
-	if (ctxt->ops->set_cr(ctxt, ctxt->modrm_reg, ctxt->src.val))
+	int cr_num = ctxt->modrm_reg;
+	int r;
+
+	if (ctxt->ops->set_cr(ctxt, cr_num, ctxt->src.val))
 		return emulate_gp(ctxt, 0);
 
 	/* Disable writeback. */
 	ctxt->dst.type = OP_NONE;
+
+	if (cr_num == 0) {
+		/*
+		 * CR0 write might have updated CR0.PE and/or CR0.PG
+		 * which can affect the cpu's execution mode.
+		 */
+		r = emulator_recalc_and_set_mode(ctxt);
+		if (r != X86EMUL_CONTINUE)
+			return r;
+	}
+
 	return X86EMUL_CONTINUE;
 }
 
@@ -4021,6 +4099,12 @@
 	return X86EMUL_CONTINUE;
 }
 
+static int em_clflushopt(struct x86_emulate_ctxt *ctxt)
+{
+	/* emulating clflushopt regardless of cpuid */
+	return X86EMUL_CONTINUE;
+}
+
 static int em_movsxd(struct x86_emulate_ctxt *ctxt)
 {
 	ctxt->dst.val = (s32) ctxt->src.val;
@@ -4094,8 +4178,12 @@
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
 
+	emulator_get_fpu();
+
 	rc = asm_safe("fxsave %[fx]", , [fx] "+m"(fx_state));
 
+	emulator_put_fpu();
+
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
 
@@ -4138,6 +4226,8 @@
 	if (rc != X86EMUL_CONTINUE)
 		return rc;
 
+	emulator_get_fpu();
+
 	if (size < __fxstate_size(16)) {
 		rc = fxregs_fixup(&fx_state, size);
 		if (rc != X86EMUL_CONTINUE)
@@ -4153,6 +4243,8 @@
 		rc = asm_safe("fxrstor %[fx]", : [fx] "m"(fx_state));
 
 out:
+	emulator_put_fpu();
+
 	return rc;
 }
 
@@ -4555,7 +4647,7 @@
 };
 
 static const struct gprefix pfx_0f_ae_7 = {
-	I(SrcMem | ByteOp, em_clflush), N, N, N,
+	I(SrcMem | ByteOp, em_clflush), I(SrcMem | ByteOp, em_clflushopt), N, N,
 };
 
 static const struct group_dual group15 = { {
@@ -5160,6 +5252,7 @@
 	ctxt->fetch.ptr = ctxt->fetch.data;
 	ctxt->fetch.end = ctxt->fetch.data + insn_len;
 	ctxt->opcode_len = 1;
+	ctxt->intercept = x86_intercept_none;
 	if (insn_len > 0)
 		memcpy(ctxt->fetch.data, insn, insn_len);
 	else {
@@ -5212,16 +5305,28 @@
 				ctxt->ad_bytes = def_ad_bytes ^ 6;
 			break;
 		case 0x26:	/* ES override */
+			has_seg_override = true;
+			ctxt->seg_override = VCPU_SREG_ES;
+			break;
 		case 0x2e:	/* CS override */
+			has_seg_override = true;
+			ctxt->seg_override = VCPU_SREG_CS;
+			break;
 		case 0x36:	/* SS override */
+			has_seg_override = true;
+			ctxt->seg_override = VCPU_SREG_SS;
+			break;
 		case 0x3e:	/* DS override */
 			has_seg_override = true;
-			ctxt->seg_override = (ctxt->b >> 3) & 3;
+			ctxt->seg_override = VCPU_SREG_DS;
 			break;
 		case 0x64:	/* FS override */
+			has_seg_override = true;
+			ctxt->seg_override = VCPU_SREG_FS;
+			break;
 		case 0x65:	/* GS override */
 			has_seg_override = true;
-			ctxt->seg_override = ctxt->b & 7;
+			ctxt->seg_override = VCPU_SREG_GS;
 			break;
 		case 0x40 ... 0x4f: /* REX */
 			if (mode != X86EMUL_MODE_PROT64)
@@ -5305,10 +5410,15 @@
 			}
 			break;
 		case Escape:
-			if (ctxt->modrm > 0xbf)
-				opcode = opcode.u.esc->high[ctxt->modrm - 0xc0];
-			else
+			if (ctxt->modrm > 0xbf) {
+				size_t size = ARRAY_SIZE(opcode.u.esc->high);
+				u32 index = array_index_nospec(
+					ctxt->modrm - 0xc0, size);
+
+				opcode = opcode.u.esc->high[index];
+			} else {
 				opcode = opcode.u.esc->op[(ctxt->modrm >> 3) & 7];
+			}
 			break;
 		case InstrDual:
 			if ((ctxt->modrm >> 6) == 3)
@@ -5450,7 +5560,9 @@
 {
 	int rc;
 
+	emulator_get_fpu();
 	rc = asm_safe("fwait");
+	emulator_put_fpu();
 
 	if (unlikely(rc != X86EMUL_CONTINUE))
 		return emulate_exception(ctxt, MF_VECTOR, 0, false);
@@ -5779,6 +5891,8 @@
 	}
 
 	ctxt->eip = ctxt->_eip;
+	if (ctxt->mode != X86EMUL_MODE_PROT64)
+		ctxt->eip = (u32)ctxt->_eip;
 
 done:
 	if (rc == X86EMUL_PROPAGATE_FAULT) {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kvm/hyperv.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kvm/hyperv.c
@@ -205,7 +205,7 @@
 	struct kvm_vcpu *vcpu = synic_to_vcpu(synic);
 	int ret;
 
-	if (!synic->active && !host)
+	if (!synic->active && (!host || data))
 		return 1;
 
 	trace_kvm_hv_synic_set_msr(vcpu->vcpu_id, msr, data, host);
@@ -251,6 +251,9 @@
 	case HV_X64_MSR_EOM: {
 		int i;
 
+		if (!synic->active)
+			break;
+
 		for (i = 0; i < ARRAY_SIZE(synic->sint); i++)
 			kvm_hv_notify_acked_sint(vcpu, i);
 		break;
@@ -306,6 +309,9 @@
 	struct kvm_lapic_irq irq;
 	int ret, vector;
 
+	if (KVM_BUG_ON(!lapic_in_kernel(vcpu), vcpu->kvm))
+		return -EINVAL;
+
 	if (sint >= ARRAY_SIZE(synic->sint))
 		return -EINVAL;
 
@@ -514,6 +520,11 @@
 {
 	union hv_stimer_config new_config = {.as_uint64 = config},
 		old_config = {.as_uint64 = stimer->config.as_uint64};
+	struct kvm_vcpu *vcpu = stimer_to_vcpu(stimer);
+	struct kvm_vcpu_hv_synic *synic = vcpu_to_synic(vcpu);
+
+	if (!synic->active && (!host || config))
+		return 1;
 
 	trace_kvm_hv_stimer_set_config(stimer_to_vcpu(stimer)->vcpu_id,
 				       stimer->index, config, host);
@@ -533,15 +544,23 @@
 static int stimer_set_count(struct kvm_vcpu_hv_stimer *stimer, u64 count,
 			    bool host)
 {
+	struct kvm_vcpu *vcpu = stimer_to_vcpu(stimer);
+	struct kvm_vcpu_hv_synic *synic = vcpu_to_synic(vcpu);
+
+	if (!synic->active && (!host || count))
+		return 1;
+
 	trace_kvm_hv_stimer_set_count(stimer_to_vcpu(stimer)->vcpu_id,
 				      stimer->index, count, host);
 
 	stimer_cleanup(stimer);
 	stimer->count = count;
-	if (stimer->count == 0)
-		stimer->config.enable = 0;
-	else if (stimer->config.auto_enable)
-		stimer->config.enable = 1;
+	if (!host) {
+		if (stimer->count == 0)
+			stimer->config.enable = 0;
+		else if (stimer->config.auto_enable)
+			stimer->config.enable = 1;
+	}
 
 	if (stimer->config.enable)
 		stimer_mark_pending(stimer, false);
@@ -809,11 +828,12 @@
 				     u32 index, u64 *pdata)
 {
 	struct kvm_hv *hv = &vcpu->kvm->arch.hyperv;
+	size_t size = ARRAY_SIZE(hv->hv_crash_param);
 
-	if (WARN_ON_ONCE(index >= ARRAY_SIZE(hv->hv_crash_param)))
+	if (WARN_ON_ONCE(index >= size))
 		return -EINVAL;
 
-	*pdata = hv->hv_crash_param[index];
+	*pdata = hv->hv_crash_param[array_index_nospec(index, size)];
 	return 0;
 }
 
@@ -852,11 +872,12 @@
 				     u32 index, u64 data)
 {
 	struct kvm_hv *hv = &vcpu->kvm->arch.hyperv;
+	size_t size = ARRAY_SIZE(hv->hv_crash_param);
 
-	if (WARN_ON_ONCE(index >= ARRAY_SIZE(hv->hv_crash_param)))
+	if (WARN_ON_ONCE(index >= size))
 		return -EINVAL;
 
-	hv->hv_crash_param[index] = data;
+	hv->hv_crash_param[array_index_nospec(index, size)] = data;
 	return 0;
 }
 
@@ -1499,11 +1520,13 @@
 
 		all_cpus = send_ipi_ex.vp_set.format == HV_GENERIC_SET_ALL;
 
+		if (all_cpus)
+			goto check_and_send_ipi;
+
 		if (!sparse_banks_len)
 			goto ret_success;
 
-		if (!all_cpus &&
-		    kvm_read_guest(kvm,
+		if (kvm_read_guest(kvm,
 				   ingpa + offsetof(struct hv_send_ipi_ex,
 						    vp_set.bank_contents),
 				   sparse_banks,
@@ -1511,6 +1534,7 @@
 			return HV_STATUS_INVALID_HYPERCALL_INPUT;
 	}
 
+check_and_send_ipi:
 	if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR))
 		return HV_STATUS_INVALID_HYPERCALL_INPUT;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kvm/i8259.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kvm/i8259.c
@@ -460,10 +460,14 @@
 	switch (addr) {
 	case 0x20:
 	case 0x21:
+		pic_lock(s);
+		pic_ioport_write(&s->pics[0], addr, data);
+		pic_unlock(s);
+		break;
 	case 0xa0:
 	case 0xa1:
 		pic_lock(s);
-		pic_ioport_write(&s->pics[addr >> 7], addr, data);
+		pic_ioport_write(&s->pics[1], addr, data);
 		pic_unlock(s);
 		break;
 	case 0x4d0:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kvm/ioapic.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kvm/ioapic.c
@@ -36,6 +36,7 @@
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/export.h>
+#include <linux/nospec.h>
 #include <asm/processor.h>
 #include <asm/page.h>
 #include <asm/current.h>
@@ -68,13 +69,14 @@
 	default:
 		{
 			u32 redir_index = (ioapic->ioregsel - 0x10) >> 1;
-			u64 redir_content;
+			u64 redir_content = ~0ULL;
 
-			if (redir_index < IOAPIC_NUM_PINS)
-				redir_content =
-					ioapic->redirtbl[redir_index].bits;
-			else
-				redir_content = ~0ULL;
+			if (redir_index < IOAPIC_NUM_PINS) {
+				u32 index = array_index_nospec(
+					redir_index, IOAPIC_NUM_PINS);
+
+				redir_content = ioapic->redirtbl[index].bits;
+			}
 
 			result = (ioapic->ioregsel & 0x1) ?
 			    (redir_content >> 32) & 0xffffffff :
@@ -291,6 +293,7 @@
 
 		if (index >= IOAPIC_NUM_PINS)
 			return;
+		index = array_index_nospec(index, IOAPIC_NUM_PINS);
 		e = &ioapic->redirtbl[index];
 		mask_before = e->fields.mask;
 		/* Preserve read-only fields */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kvm/irq.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kvm/irq.c
@@ -40,29 +40,10 @@
  * check if there is pending interrupt from
  * non-APIC source without intack.
  */
-static int kvm_cpu_has_extint(struct kvm_vcpu *v)
-{
-	u8 accept = kvm_apic_accept_pic_intr(v);
-
-	if (accept) {
-		if (irqchip_split(v->kvm))
-			return pending_userspace_extint(v);
-		else
-			return v->kvm->arch.vpic->output;
-	} else
-		return 0;
-}
-
-/*
- * check if there is injectable interrupt:
- * when virtual interrupt delivery enabled,
- * interrupt from apic will handled by hardware,
- * we don't need to check it here.
- */
-int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v)
+int kvm_cpu_has_extint(struct kvm_vcpu *v)
 {
 	/*
-	 * FIXME: interrupt.injected represents an interrupt that it's
+	 * FIXME: interrupt.injected represents an interrupt whose
 	 * side-effects have already been applied (e.g. bit from IRR
 	 * already moved to ISR). Therefore, it is incorrect to rely
 	 * on interrupt.injected to know if there is a pending
@@ -75,6 +56,23 @@
 	if (!lapic_in_kernel(v))
 		return v->arch.interrupt.injected;
 
+	if (!kvm_apic_accept_pic_intr(v))
+		return 0;
+
+	if (irqchip_split(v->kvm))
+		return pending_userspace_extint(v);
+	else
+		return v->kvm->arch.vpic->output;
+}
+
+/*
+ * check if there is injectable interrupt:
+ * when virtual interrupt delivery enabled,
+ * interrupt from apic will handled by hardware,
+ * we don't need to check it here.
+ */
+int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v)
+{
 	if (kvm_cpu_has_extint(v))
 		return 1;
 
@@ -90,20 +88,6 @@
  */
 int kvm_cpu_has_interrupt(struct kvm_vcpu *v)
 {
-	/*
-	 * FIXME: interrupt.injected represents an interrupt that it's
-	 * side-effects have already been applied (e.g. bit from IRR
-	 * already moved to ISR). Therefore, it is incorrect to rely
-	 * on interrupt.injected to know if there is a pending
-	 * interrupt in the user-mode LAPIC.
-	 * This leads to nVMX/nSVM not be able to distinguish
-	 * if it should exit from L2 to L1 on EXTERNAL_INTERRUPT on
-	 * pending interrupt or should re-inject an injected
-	 * interrupt.
-	 */
-	if (!lapic_in_kernel(v))
-		return v->arch.interrupt.injected;
-
 	if (kvm_cpu_has_extint(v))
 		return 1;
 
@@ -117,16 +101,21 @@
  */
 static int kvm_cpu_get_extint(struct kvm_vcpu *v)
 {
-	if (kvm_cpu_has_extint(v)) {
-		if (irqchip_split(v->kvm)) {
-			int vector = v->arch.pending_external_vector;
-
-			v->arch.pending_external_vector = -1;
-			return vector;
-		} else
-			return kvm_pic_read_irq(v->kvm); /* PIC */
-	} else
+	if (!kvm_cpu_has_extint(v)) {
+		WARN_ON(!lapic_in_kernel(v));
 		return -1;
+	}
+
+	if (!lapic_in_kernel(v))
+		return v->arch.interrupt.nr;
+
+	if (irqchip_split(v->kvm)) {
+		int vector = v->arch.pending_external_vector;
+
+		v->arch.pending_external_vector = -1;
+		return vector;
+	} else
+		return kvm_pic_read_irq(v->kvm); /* PIC */
 }
 
 /*
@@ -134,13 +123,7 @@
  */
 int kvm_cpu_get_interrupt(struct kvm_vcpu *v)
 {
-	int vector;
-
-	if (!lapic_in_kernel(v))
-		return v->arch.interrupt.nr;
-
-	vector = kvm_cpu_get_extint(v);
-
+	int vector = kvm_cpu_get_extint(v);
 	if (vector != -1)
 		return vector;			/* PIC */
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kvm/irq_comm.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kvm/irq_comm.c
@@ -416,7 +416,7 @@
 
 			kvm_set_msi_irq(vcpu->kvm, entry, &irq);
 
-			if (irq.level && kvm_apic_match_dest(vcpu, NULL, 0,
+			if (irq.trig_mode && kvm_apic_match_dest(vcpu, NULL, 0,
 						irq.dest_id, irq.dest_mode))
 				__set_bit(irq.vector, ioapic_handled_vectors);
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kvm/kvm_cache_regs.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kvm/kvm_cache_regs.h
@@ -7,7 +7,7 @@
 #define KVM_POSSIBLE_CR0_GUEST_BITS X86_CR0_TS
 #define KVM_POSSIBLE_CR4_GUEST_BITS				  \
 	(X86_CR4_PVI | X86_CR4_DE | X86_CR4_PCE | X86_CR4_OSFXSR  \
-	 | X86_CR4_OSXMMEXCPT | X86_CR4_LA57 | X86_CR4_PGE)
+	 | X86_CR4_OSXMMEXCPT | X86_CR4_LA57 | X86_CR4_PGE | X86_CR4_TSD)
 
 #define BUILD_KVM_GPR_ACCESSORS(lname, uname)				      \
 static __always_inline unsigned long kvm_##lname##_read(struct kvm_vcpu *vcpu)\
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kvm/lapic.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kvm/lapic.c
@@ -118,7 +118,8 @@
 
 bool kvm_can_post_timer_interrupt(struct kvm_vcpu *vcpu)
 {
-	return pi_inject_timer && kvm_vcpu_apicv_active(vcpu);
+	return pi_inject_timer && kvm_vcpu_apicv_active(vcpu) &&
+		(kvm_mwait_in_guest(vcpu->kvm) || kvm_hlt_in_guest(vcpu->kvm));
 }
 EXPORT_SYMBOL_GPL(kvm_can_post_timer_interrupt);
 
@@ -637,9 +638,11 @@
 static bool pv_eoi_get_pending(struct kvm_vcpu *vcpu)
 {
 	u8 val;
-	if (pv_eoi_get_user(vcpu, &val) < 0)
+	if (pv_eoi_get_user(vcpu, &val) < 0) {
 		printk(KERN_WARNING "Can't read EOI MSR value: 0x%llx\n",
 			   (unsigned long long)vcpu->arch.pv_eoi.msr_val);
+		return false;
+	}
 	return val & 0x1;
 }
 
@@ -952,6 +955,10 @@
 	*r = -1;
 
 	if (irq->shorthand == APIC_DEST_SELF) {
+		if (KVM_BUG_ON(!src, kvm)) {
+			*r = 0;
+			return true;
+		}
 		*r = kvm_apic_set_irq(src->vcpu, irq, dest_map);
 		return true;
 	}
@@ -1056,11 +1063,8 @@
 						       apic->regs + APIC_TMR);
 		}
 
-		if (vcpu->arch.apicv_active)
-			kvm_x86_ops->deliver_posted_interrupt(vcpu, vector);
-		else {
+		if (kvm_x86_ops->deliver_posted_interrupt(vcpu, vector)) {
 			kvm_lapic_set_irr(vector, apic);
-
 			kvm_make_request(KVM_REQ_EVENT, vcpu);
 			kvm_vcpu_kick(vcpu);
 		}
@@ -1333,6 +1337,9 @@
 	if (!apic_x2apic_mode(apic))
 		valid_reg_mask |= APIC_REG_MASK(APIC_ARBPRI);
 
+	if (alignment + len > 4)
+		return 1;
+
 	if (offset > 0x3f0 || !(valid_reg_mask & APIC_REG_MASK(offset)))
 		return 1;
 
@@ -1685,7 +1692,7 @@
 
 	hrtimer_start(&apic->lapic_timer.timer,
 		apic->lapic_timer.target_expiration,
-		HRTIMER_MODE_ABS);
+		HRTIMER_MODE_ABS_HARD);
 }
 
 bool kvm_lapic_hv_timer_in_use(struct kvm_vcpu *vcpu)
@@ -1926,15 +1933,20 @@
 	case APIC_LVTTHMR:
 	case APIC_LVTPC:
 	case APIC_LVT1:
-	case APIC_LVTERR:
+	case APIC_LVTERR: {
 		/* TODO: Check vector */
+		size_t size;
+		u32 index;
+
 		if (!kvm_apic_sw_enabled(apic))
 			val |= APIC_LVT_MASKED;
-
-		val &= apic_lvt_mask[(reg - APIC_LVTT) >> 4];
+		size = ARRAY_SIZE(apic_lvt_mask);
+		index = array_index_nospec(
+				(reg - APIC_LVTT) >> 4, size);
+		val &= apic_lvt_mask[index];
 		kvm_lapic_set_reg(apic, reg, val);
-
 		break;
+	}
 
 	case APIC_LVTT:
 		if (!kvm_apic_sw_enabled(apic))
@@ -2081,7 +2093,7 @@
 {
 	struct kvm_lapic *apic = vcpu->arch.apic;
 
-	if (!lapic_in_kernel(vcpu) || apic_lvtt_oneshot(apic) ||
+	if (!kvm_apic_present(vcpu) || apic_lvtt_oneshot(apic) ||
 			apic_lvtt_period(apic))
 		return;
 
@@ -2092,10 +2104,7 @@
 
 void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8)
 {
-	struct kvm_lapic *apic = vcpu->arch.apic;
-
-	apic_set_tpr(apic, ((cr8 & 0x0f) << 4)
-		     | (kvm_lapic_get_reg(apic, APIC_TASKPRI) & 4));
+	apic_set_tpr(vcpu->arch.apic, (cr8 & 0x0f) << 4);
 }
 
 u64 kvm_lapic_get_cr8(struct kvm_vcpu *vcpu)
@@ -2235,13 +2244,17 @@
 {
 	u32 reg = kvm_lapic_get_reg(apic, lvt_type);
 	int vector, mode, trig_mode;
+	int r;
 
 	if (kvm_apic_hw_enabled(apic) && !(reg & APIC_LVT_MASKED)) {
 		vector = reg & APIC_VECTOR_MASK;
 		mode = reg & APIC_MODE_MASK;
 		trig_mode = reg & APIC_LVT_LEVEL_TRIGGER;
-		return __apic_accept_irq(apic, mode, vector, 1, trig_mode,
-					NULL);
+
+		r = __apic_accept_irq(apic, mode, vector, 1, trig_mode, NULL);
+		if (r && lvt_type == APIC_LVTPC)
+			kvm_lapic_set_reg(apic, APIC_LVTPC, reg | APIC_LVT_MASKED);
+		return r;
 	}
 	return 0;
 }
@@ -2326,7 +2339,7 @@
 	struct kvm_lapic *apic = vcpu->arch.apic;
 	u32 ppr;
 
-	if (!kvm_apic_hw_enabled(apic))
+	if (!kvm_apic_present(vcpu))
 		return -1;
 
 	__apic_update_ppr(apic, &ppr);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kvm/mmu.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kvm/mmu.c
@@ -343,6 +343,8 @@
 {
 	BUG_ON((u64)(unsigned)access_mask != access_mask);
 	BUG_ON((mmio_mask & mmio_value) != mmio_value);
+	WARN_ON(mmio_value & (shadow_nonpresent_or_rsvd_mask << shadow_nonpresent_or_rsvd_mask_len));
+	WARN_ON(mmio_value & shadow_nonpresent_or_rsvd_lower_gfn_mask);
 	shadow_mmio_value = mmio_value | SPTE_MMIO_MASK;
 	shadow_mmio_mask = mmio_mask | SPTE_SPECIAL_MASK;
 	shadow_mmio_access_mask = access_mask;
@@ -405,11 +407,11 @@
 }
 
 /*
- * Due to limited space in PTEs, the MMIO generation is a 19 bit subset of
+ * Due to limited space in PTEs, the MMIO generation is a 18 bit subset of
  * the memslots generation and is derived as follows:
  *
  * Bits 0-8 of the MMIO generation are propagated to spte bits 3-11
- * Bits 9-18 of the MMIO generation are propagated to spte bits 52-61
+ * Bits 9-17 of the MMIO generation are propagated to spte bits 54-62
  *
  * The KVM_MEMSLOT_GEN_UPDATE_IN_PROGRESS flag is intentionally not included in
  * the MMIO generation number, as doing so would require stealing a bit from
@@ -418,25 +420,38 @@
  * requires a full MMU zap).  The flag is instead explicitly queried when
  * checking for MMIO spte cache hits.
  */
-#define MMIO_SPTE_GEN_MASK		GENMASK_ULL(18, 0)
 
 #define MMIO_SPTE_GEN_LOW_START		3
 #define MMIO_SPTE_GEN_LOW_END		11
+
+#define MMIO_SPTE_GEN_HIGH_START	PT64_SECOND_AVAIL_BITS_SHIFT
+#define MMIO_SPTE_GEN_HIGH_END		62
+
 #define MMIO_SPTE_GEN_LOW_MASK		GENMASK_ULL(MMIO_SPTE_GEN_LOW_END, \
 						    MMIO_SPTE_GEN_LOW_START)
-
-#define MMIO_SPTE_GEN_HIGH_START	52
-#define MMIO_SPTE_GEN_HIGH_END		61
 #define MMIO_SPTE_GEN_HIGH_MASK		GENMASK_ULL(MMIO_SPTE_GEN_HIGH_END, \
 						    MMIO_SPTE_GEN_HIGH_START)
+
+#define MMIO_SPTE_GEN_LOW_BITS		(MMIO_SPTE_GEN_LOW_END - MMIO_SPTE_GEN_LOW_START + 1)
+#define MMIO_SPTE_GEN_HIGH_BITS		(MMIO_SPTE_GEN_HIGH_END - MMIO_SPTE_GEN_HIGH_START + 1)
+
+/* remember to adjust the comment above as well if you change these */
+static_assert(MMIO_SPTE_GEN_LOW_BITS == 9 && MMIO_SPTE_GEN_HIGH_BITS == 9);
+
+#define MMIO_SPTE_GEN_LOW_SHIFT		(MMIO_SPTE_GEN_LOW_START - 0)
+#define MMIO_SPTE_GEN_HIGH_SHIFT	(MMIO_SPTE_GEN_HIGH_START - MMIO_SPTE_GEN_LOW_BITS)
+
+#define MMIO_SPTE_GEN_MASK		GENMASK_ULL(MMIO_SPTE_GEN_LOW_BITS + MMIO_SPTE_GEN_HIGH_BITS - 1, 0)
+
 static u64 generation_mmio_spte_mask(u64 gen)
 {
 	u64 mask;
 
 	WARN_ON(gen & ~MMIO_SPTE_GEN_MASK);
+	BUILD_BUG_ON((MMIO_SPTE_GEN_HIGH_MASK | MMIO_SPTE_GEN_LOW_MASK) & SPTE_SPECIAL_MASK);
 
-	mask = (gen << MMIO_SPTE_GEN_LOW_START) & MMIO_SPTE_GEN_LOW_MASK;
-	mask |= (gen << MMIO_SPTE_GEN_HIGH_START) & MMIO_SPTE_GEN_HIGH_MASK;
+	mask = (gen << MMIO_SPTE_GEN_LOW_SHIFT) & MMIO_SPTE_GEN_LOW_MASK;
+	mask |= (gen << MMIO_SPTE_GEN_HIGH_SHIFT) & MMIO_SPTE_GEN_HIGH_MASK;
 	return mask;
 }
 
@@ -444,10 +459,8 @@
 {
 	u64 gen;
 
-	spte &= ~shadow_mmio_mask;
-
-	gen = (spte & MMIO_SPTE_GEN_LOW_MASK) >> MMIO_SPTE_GEN_LOW_START;
-	gen |= (spte & MMIO_SPTE_GEN_HIGH_MASK) >> MMIO_SPTE_GEN_HIGH_START;
+	gen = (spte & MMIO_SPTE_GEN_LOW_MASK) >> MMIO_SPTE_GEN_LOW_SHIFT;
+	gen |= (spte & MMIO_SPTE_GEN_HIGH_MASK) >> MMIO_SPTE_GEN_HIGH_SHIFT;
 	return gen;
 }
 
@@ -538,16 +551,20 @@
 static u8 kvm_get_shadow_phys_bits(void)
 {
 	/*
-	 * boot_cpu_data.x86_phys_bits is reduced when MKTME is detected
-	 * in CPU detection code, but MKTME treats those reduced bits as
-	 * 'keyID' thus they are not reserved bits. Therefore for MKTME
-	 * we should still return physical address bits reported by CPUID.
-	 */
-	if (!boot_cpu_has(X86_FEATURE_TME) ||
-	    WARN_ON_ONCE(boot_cpu_data.extended_cpuid_level < 0x80000008))
-		return boot_cpu_data.x86_phys_bits;
+	 * boot_cpu_data.x86_phys_bits is reduced when MKTME or SME are detected
+	 * in CPU detection code, but the processor treats those reduced bits as
+	 * 'keyID' thus they are not reserved bits. Therefore KVM needs to look at
+	 * the physical address bits reported by CPUID.
+	 */
+	if (likely(boot_cpu_data.extended_cpuid_level >= 0x80000008))
+		return cpuid_eax(0x80000008) & 0xff;
 
-	return cpuid_eax(0x80000008) & 0xff;
+	/*
+	 * Quite weird to have VMX or SVM but not MAXPHYADDR; probably a VM with
+	 * custom CPUID.  Proceed with whatever the kernel found since these features
+	 * aren't virtualizable (SME/SEV also require CPUIDs higher than 0x80000008).
+	 */
+	return boot_cpu_data.x86_phys_bits;
 }
 
 static void kvm_mmu_reset_all_pte_masks(void)
@@ -576,16 +593,15 @@
 	 * the most significant bits of legal physical address space.
 	 */
 	shadow_nonpresent_or_rsvd_mask = 0;
-	low_phys_bits = boot_cpu_data.x86_cache_bits;
-	if (boot_cpu_data.x86_cache_bits <
-	    52 - shadow_nonpresent_or_rsvd_mask_len) {
+	low_phys_bits = boot_cpu_data.x86_phys_bits;
+	if (boot_cpu_has_bug(X86_BUG_L1TF) &&
+	    !WARN_ON_ONCE(boot_cpu_data.x86_cache_bits >=
+			  52 - shadow_nonpresent_or_rsvd_mask_len)) {
+		low_phys_bits = boot_cpu_data.x86_cache_bits
+			- shadow_nonpresent_or_rsvd_mask_len;
 		shadow_nonpresent_or_rsvd_mask =
-			rsvd_bits(boot_cpu_data.x86_cache_bits -
-				  shadow_nonpresent_or_rsvd_mask_len,
-				  boot_cpu_data.x86_cache_bits - 1);
-		low_phys_bits -= shadow_nonpresent_or_rsvd_mask_len;
-	} else
-		WARN_ON_ONCE(boot_cpu_has_bug(X86_BUG_L1TF));
+			rsvd_bits(low_phys_bits, boot_cpu_data.x86_cache_bits - 1);
+	}
 
 	shadow_nonpresent_or_rsvd_lower_gfn_mask =
 		GENMASK_ULL(low_phys_bits - 1, PAGE_SHIFT);
@@ -1282,12 +1298,12 @@
 	return __mmu_gfn_lpage_is_disallowed(gfn, level, slot);
 }
 
-static int host_mapping_level(struct kvm *kvm, gfn_t gfn)
+static int host_mapping_level(struct kvm_vcpu *vcpu, gfn_t gfn)
 {
 	unsigned long page_size;
 	int i, ret = 0;
 
-	page_size = kvm_host_page_size(kvm, gfn);
+	page_size = kvm_host_page_size(vcpu, gfn);
 
 	for (i = PT_PAGE_TABLE_LEVEL; i <= PT_MAX_HUGEPAGE_LEVEL; ++i) {
 		if (page_size >= KVM_HPAGE_SIZE(i))
@@ -1337,7 +1353,7 @@
 	if (unlikely(*force_pt_level))
 		return PT_PAGE_TABLE_LEVEL;
 
-	host_level = host_mapping_level(vcpu->kvm, large_gfn);
+	host_level = host_mapping_level(vcpu, large_gfn);
 
 	if (host_level == PT_PAGE_TABLE_LEVEL)
 		return host_level;
@@ -1814,10 +1830,10 @@
  * Emulate arch specific page modification logging for the
  * nested hypervisor
  */
-int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu)
+int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu, gpa_t l2_gpa)
 {
 	if (kvm_x86_ops->write_log_dirty)
-		return kvm_x86_ops->write_log_dirty(vcpu);
+		return kvm_x86_ops->write_log_dirty(vcpu, l2_gpa);
 
 	return 0;
 }
@@ -2040,7 +2056,8 @@
 	return kvm_handle_hva_range(kvm, hva, hva + 1, data, handler);
 }
 
-int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end)
+int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end,
+			unsigned flags)
 {
 	return kvm_handle_hva_range(kvm, start, end, 0, kvm_unmap_rmapp);
 }
@@ -2126,7 +2143,7 @@
  * aggregate version in order to make the slab shrinker
  * faster
  */
-static inline void kvm_mod_used_mmu_pages(struct kvm *kvm, unsigned long nr)
+static inline void kvm_mod_used_mmu_pages(struct kvm *kvm, long nr)
 {
 	kvm->arch.n_used_mmu_pages += nr;
 	percpu_counter_add(&kvm_total_used_mmu_pages, nr);
@@ -2226,13 +2243,6 @@
 {
 }
 
-static void nonpaging_update_pte(struct kvm_vcpu *vcpu,
-				 struct kvm_mmu_page *sp, u64 *spte,
-				 const void *pte)
-{
-	WARN_ON(1);
-}
-
 #define KVM_PAGE_ARRAY_NR 16
 
 struct kvm_mmu_pages {
@@ -3528,7 +3538,7 @@
  * - true: let the vcpu to access on the same address again.
  * - false: let the real page fault path to fix it.
  */
-static bool fast_page_fault(struct kvm_vcpu *vcpu, gva_t gva, int level,
+static bool fast_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, int level,
 			    u32 error_code)
 {
 	struct kvm_shadow_walk_iterator iterator;
@@ -3548,7 +3558,7 @@
 	do {
 		u64 new_spte;
 
-		for_each_shadow_entry_lockless(vcpu, gva, iterator, spte)
+		for_each_shadow_entry_lockless(vcpu, cr2_or_gpa, iterator, spte)
 			if (!is_shadow_present_pte(spte) ||
 			    iterator.level < level)
 				break;
@@ -3626,7 +3636,7 @@
 
 	} while (true);
 
-	trace_fast_page_fault(vcpu, gva, error_code, iterator.sptep,
+	trace_fast_page_fault(vcpu, cr2_or_gpa, error_code, iterator.sptep,
 			      spte, fault_handled);
 	walk_shadow_page_lockless_end(vcpu);
 
@@ -3634,10 +3644,11 @@
 }
 
 static bool try_async_pf(struct kvm_vcpu *vcpu, bool prefault, gfn_t gfn,
-			 gva_t gva, kvm_pfn_t *pfn, bool write, bool *writable);
+			 gpa_t cr2_or_gpa, kvm_pfn_t *pfn, bool write,
+			 bool *writable);
 static int make_mmu_pages_available(struct kvm_vcpu *vcpu);
 
-static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, u32 error_code,
+static int nonpaging_map(struct kvm_vcpu *vcpu, gpa_t gpa, u32 error_code,
 			 gfn_t gfn, bool prefault)
 {
 	int r;
@@ -3663,16 +3674,16 @@
 		gfn &= ~(KVM_PAGES_PER_HPAGE(level) - 1);
 	}
 
-	if (fast_page_fault(vcpu, v, level, error_code))
+	if (fast_page_fault(vcpu, gpa, level, error_code))
 		return RET_PF_RETRY;
 
 	mmu_seq = vcpu->kvm->mmu_notifier_seq;
 	smp_rmb();
 
-	if (try_async_pf(vcpu, prefault, gfn, v, &pfn, write, &map_writable))
+	if (try_async_pf(vcpu, prefault, gfn, gpa, &pfn, write, &map_writable))
 		return RET_PF_RETRY;
 
-	if (handle_abnormal_pfn(vcpu, v, gfn, pfn, ACC_ALL, &r))
+	if (handle_abnormal_pfn(vcpu, gpa, gfn, pfn, ACC_ALL, &r))
 		return r;
 
 	r = RET_PF_RETRY;
@@ -3683,7 +3694,7 @@
 		goto out_unlock;
 	if (likely(!force_pt_level))
 		transparent_hugepage_adjust(vcpu, gfn, &pfn, &level);
-	r = __direct_map(vcpu, v, write, map_writable, level, pfn,
+	r = __direct_map(vcpu, gpa, write, map_writable, level, pfn,
 			 prefault, false);
 out_unlock:
 	spin_unlock(&vcpu->kvm->mmu_lock);
@@ -3981,7 +3992,7 @@
 }
 EXPORT_SYMBOL_GPL(kvm_mmu_sync_roots);
 
-static gpa_t nonpaging_gva_to_gpa(struct kvm_vcpu *vcpu, gva_t vaddr,
+static gpa_t nonpaging_gva_to_gpa(struct kvm_vcpu *vcpu, gpa_t vaddr,
 				  u32 access, struct x86_exception *exception)
 {
 	if (exception)
@@ -3989,7 +4000,7 @@
 	return vaddr;
 }
 
-static gpa_t nonpaging_gva_to_gpa_nested(struct kvm_vcpu *vcpu, gva_t vaddr,
+static gpa_t nonpaging_gva_to_gpa_nested(struct kvm_vcpu *vcpu, gpa_t vaddr,
 					 u32 access,
 					 struct x86_exception *exception)
 {
@@ -4149,13 +4160,14 @@
 	walk_shadow_page_lockless_end(vcpu);
 }
 
-static int nonpaging_page_fault(struct kvm_vcpu *vcpu, gva_t gva,
+static int nonpaging_page_fault(struct kvm_vcpu *vcpu, gpa_t gpa,
 				u32 error_code, bool prefault)
 {
-	gfn_t gfn = gva >> PAGE_SHIFT;
+	gfn_t gfn = gpa >> PAGE_SHIFT;
 	int r;
 
-	pgprintk("%s: gva %lx error %x\n", __func__, gva, error_code);
+	/* Note, paging is disabled, ergo gva == gpa. */
+	pgprintk("%s: gva %lx error %x\n", __func__, gpa, error_code);
 
 	if (page_fault_handle_page_track(vcpu, error_code, gfn))
 		return RET_PF_EMULATE;
@@ -4167,24 +4179,38 @@
 	MMU_WARN_ON(!VALID_PAGE(vcpu->arch.mmu->root_hpa));
 
 
-	return nonpaging_map(vcpu, gva & PAGE_MASK,
+	return nonpaging_map(vcpu, gpa & PAGE_MASK,
 			     error_code, gfn, prefault);
 }
 
-static int kvm_arch_setup_async_pf(struct kvm_vcpu *vcpu, gva_t gva, gfn_t gfn)
+static u32 alloc_apf_token(struct kvm_vcpu *vcpu)
+{
+	/* make sure the token value is not 0 */
+	u32 id = vcpu->arch.apf.id;
+
+	if (id << 12 == 0)
+		vcpu->arch.apf.id = 1;
+
+	return (vcpu->arch.apf.id++ << 12) | vcpu->vcpu_id;
+}
+
+static int kvm_arch_setup_async_pf(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
+				   gfn_t gfn)
 {
 	struct kvm_arch_async_pf arch;
 
-	arch.token = (vcpu->arch.apf.id++ << 12) | vcpu->vcpu_id;
+	arch.token = alloc_apf_token(vcpu);
 	arch.gfn = gfn;
 	arch.direct_map = vcpu->arch.mmu->direct_map;
 	arch.cr3 = vcpu->arch.mmu->get_cr3(vcpu);
 
-	return kvm_setup_async_pf(vcpu, gva, kvm_vcpu_gfn_to_hva(vcpu, gfn), &arch);
+	return kvm_setup_async_pf(vcpu, cr2_or_gpa,
+				  kvm_vcpu_gfn_to_hva(vcpu, gfn), &arch);
 }
 
 static bool try_async_pf(struct kvm_vcpu *vcpu, bool prefault, gfn_t gfn,
-			 gva_t gva, kvm_pfn_t *pfn, bool write, bool *writable)
+			 gpa_t cr2_or_gpa, kvm_pfn_t *pfn, bool write,
+			 bool *writable)
 {
 	struct kvm_memory_slot *slot;
 	bool async;
@@ -4204,12 +4230,12 @@
 		return false; /* *pfn has correct page already */
 
 	if (!prefault && kvm_can_do_async_pf(vcpu)) {
-		trace_kvm_try_async_get_page(gva, gfn);
+		trace_kvm_try_async_get_page(cr2_or_gpa, gfn);
 		if (kvm_find_async_pf_gfn(vcpu, gfn)) {
-			trace_kvm_async_pf_doublefault(gva, gfn);
+			trace_kvm_async_pf_doublefault(cr2_or_gpa, gfn);
 			kvm_make_request(KVM_REQ_APF_HALT, vcpu);
 			return true;
-		} else if (kvm_arch_setup_async_pf(vcpu, gva, gfn))
+		} else if (kvm_arch_setup_async_pf(vcpu, cr2_or_gpa, gfn))
 			return true;
 	}
 
@@ -4222,6 +4248,12 @@
 {
 	int r = 1;
 
+#ifndef CONFIG_X86_64
+	/* A 64-bit CR2 should be impossible on 32-bit KVM. */
+	if (WARN_ON_ONCE(fault_address >> 32))
+		return -EFAULT;
+#endif
+
 	vcpu->arch.l1tf_flush_l1d = true;
 	switch (vcpu->arch.apf.host_apf_reason) {
 	default:
@@ -4259,7 +4291,7 @@
 	return kvm_mtrr_check_gfn_range_consistency(vcpu, gfn, page_num);
 }
 
-static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa, u32 error_code,
+static int tdp_page_fault(struct kvm_vcpu *vcpu, gpa_t gpa, u32 error_code,
 			  bool prefault)
 {
 	kvm_pfn_t pfn;
@@ -4328,7 +4360,6 @@
 	context->gva_to_gpa = nonpaging_gva_to_gpa;
 	context->sync_page = nonpaging_sync_page;
 	context->invlpg = nonpaging_invlpg;
-	context->update_pte = nonpaging_update_pte;
 	context->root_level = 0;
 	context->shadow_root_level = PT32E_ROOT_LEVEL;
 	context->direct_map = true;
@@ -4564,7 +4595,7 @@
 			nonleaf_bit8_rsvd | rsvd_bits(7, 7) |
 			rsvd_bits(maxphyaddr, 51);
 		rsvd_check->rsvd_bits_mask[0][2] = exb_bit_rsvd |
-			nonleaf_bit8_rsvd | gbpages_bit_rsvd |
+			gbpages_bit_rsvd |
 			rsvd_bits(maxphyaddr, 51);
 		rsvd_check->rsvd_bits_mask[0][1] = exb_bit_rsvd |
 			rsvd_bits(maxphyaddr, 51);
@@ -4646,7 +4677,15 @@
 void
 reset_shadow_zero_bits_mask(struct kvm_vcpu *vcpu, struct kvm_mmu *context)
 {
-	bool uses_nx = context->nx ||
+	/*
+	 * KVM uses NX when TDP is disabled to handle a variety of scenarios,
+	 * notably for huge SPTEs if iTLB multi-hit mitigation is enabled and
+	 * to generate correct permissions for CR0.WP=0/CR4.SMEP=1/EFER.NX=0.
+	 * The iTLB multi-hit workaround can be toggled at any time, so assume
+	 * NX can be used by any non-nested shadow MMU to avoid having to reset
+	 * MMU contexts.  Note, KVM forces EFER.NX=1 when TDP is disabled.
+	 */
+	bool uses_nx = context->nx || !tdp_enabled ||
 		context->mmu_role.base.smep_andnot_wp;
 	struct rsvd_bits_validate *shadow_zero_check;
 	int i;
@@ -4907,7 +4946,6 @@
 	context->gva_to_gpa = paging64_gva_to_gpa;
 	context->sync_page = paging64_sync_page;
 	context->invlpg = paging64_invlpg;
-	context->update_pte = paging64_update_pte;
 	context->shadow_root_level = level;
 	context->direct_map = false;
 }
@@ -4936,7 +4974,6 @@
 	context->gva_to_gpa = paging32_gva_to_gpa;
 	context->sync_page = paging32_sync_page;
 	context->invlpg = paging32_invlpg;
-	context->update_pte = paging32_update_pte;
 	context->shadow_root_level = PT32E_ROOT_LEVEL;
 	context->direct_map = false;
 }
@@ -5011,7 +5048,6 @@
 	context->page_fault = tdp_page_fault;
 	context->sync_page = nonpaging_sync_page;
 	context->invlpg = nonpaging_invlpg;
-	context->update_pte = nonpaging_update_pte;
 	context->shadow_root_level = kvm_x86_ops->get_tdp_level(vcpu);
 	context->direct_map = true;
 	context->set_cr3 = kvm_x86_ops->set_tdp_cr3;
@@ -5144,7 +5180,6 @@
 	context->gva_to_gpa = ept_gva_to_gpa;
 	context->sync_page = ept_sync_page;
 	context->invlpg = ept_invlpg;
-	context->update_pte = ept_update_pte;
 	context->root_level = PT64_ROOT_4LEVEL;
 	context->direct_map = false;
 	context->mmu_role.as_u64 = new_role.as_u64;
@@ -5284,19 +5319,6 @@
 }
 EXPORT_SYMBOL_GPL(kvm_mmu_unload);
 
-static void mmu_pte_write_new_pte(struct kvm_vcpu *vcpu,
-				  struct kvm_mmu_page *sp, u64 *spte,
-				  const void *new)
-{
-	if (sp->role.level != PT_PAGE_TABLE_LEVEL) {
-		++vcpu->kvm->stat.mmu_pde_zapped;
-		return;
-        }
-
-	++vcpu->kvm->stat.mmu_pte_updated;
-	vcpu->arch.mmu->update_pte(vcpu, sp, spte, new);
-}
-
 static bool need_remote_flush(u64 old, u64 new)
 {
 	if (!is_shadow_present_pte(old))
@@ -5462,14 +5484,10 @@
 
 		local_flush = true;
 		while (npte--) {
-			u32 base_role = vcpu->arch.mmu->mmu_role.base.word;
-
 			entry = *spte;
 			mmu_page_zap_pte(vcpu->kvm, sp, spte);
-			if (gentry &&
-			      !((sp->role.word ^ base_role)
-			      & mmu_base_role_mask.word) && rmap_can_add(vcpu))
-				mmu_pte_write_new_pte(vcpu, sp, spte, &gentry);
+			if (gentry && sp->role.level != PG_LEVEL_4K)
+				++vcpu->kvm->stat.mmu_pde_zapped;
 			if (need_remote_flush(entry, *spte))
 				remote_flush = true;
 			++spte;
@@ -5516,7 +5534,7 @@
 	return 0;
 }
 
-int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t cr2, u64 error_code,
+int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, u64 error_code,
 		       void *insn, int insn_len)
 {
 	int r, emulation_type = 0;
@@ -5525,18 +5543,18 @@
 	/* With shadow page tables, fault_address contains a GVA or nGPA.  */
 	if (vcpu->arch.mmu->direct_map) {
 		vcpu->arch.gpa_available = true;
-		vcpu->arch.gpa_val = cr2;
+		vcpu->arch.gpa_val = cr2_or_gpa;
 	}
 
 	r = RET_PF_INVALID;
 	if (unlikely(error_code & PFERR_RSVD_MASK)) {
-		r = handle_mmio_page_fault(vcpu, cr2, direct);
+		r = handle_mmio_page_fault(vcpu, cr2_or_gpa, direct);
 		if (r == RET_PF_EMULATE)
 			goto emulate;
 	}
 
 	if (r == RET_PF_INVALID) {
-		r = vcpu->arch.mmu->page_fault(vcpu, cr2,
+		r = vcpu->arch.mmu->page_fault(vcpu, cr2_or_gpa,
 					       lower_32_bits(error_code),
 					       false);
 		WARN_ON(r == RET_PF_INVALID);
@@ -5556,7 +5574,7 @@
 	 */
 	if (vcpu->arch.mmu->direct_map &&
 	    (error_code & PFERR_NESTED_GUEST_PAGE) == PFERR_NESTED_GUEST_PAGE) {
-		kvm_mmu_unprotect_page(vcpu->kvm, gpa_to_gfn(cr2));
+		kvm_mmu_unprotect_page(vcpu->kvm, gpa_to_gfn(cr2_or_gpa));
 		return 1;
 	}
 
@@ -5571,7 +5589,7 @@
 	 * explicitly shadowing L1's page tables, i.e. unprotecting something
 	 * for L1 isn't going to magically fix whatever issue cause L2 to fail.
 	 */
-	if (!mmio_info_in_cache(vcpu, cr2, direct) && !is_guest_mode(vcpu))
+	if (!mmio_info_in_cache(vcpu, cr2_or_gpa, direct) && !is_guest_mode(vcpu))
 		emulation_type = EMULTYPE_ALLOW_RETRY;
 emulate:
 	/*
@@ -5586,7 +5604,7 @@
 			return 1;
 	}
 
-	return x86_emulate_instruction(vcpu, cr2, emulation_type, insn,
+	return x86_emulate_instruction(vcpu, cr2_or_gpa, emulation_type, insn,
 				       insn_len);
 }
 EXPORT_SYMBOL_GPL(kvm_mmu_page_fault);
@@ -5629,14 +5647,16 @@
 	uint i;
 
 	if (pcid == kvm_get_active_pcid(vcpu)) {
-		mmu->invlpg(vcpu, gva, mmu->root_hpa);
+		if (mmu->invlpg)
+			mmu->invlpg(vcpu, gva, mmu->root_hpa);
 		tlb_flush = true;
 	}
 
 	for (i = 0; i < KVM_MMU_NUM_PREV_ROOTS; i++) {
 		if (VALID_PAGE(mmu->prev_roots[i].hpa) &&
 		    pcid == kvm_get_pcid(vcpu, mmu->prev_roots[i].cr3)) {
-			mmu->invlpg(vcpu, gva, mmu->prev_roots[i].hpa);
+			if (mmu->invlpg)
+				mmu->invlpg(vcpu, gva, mmu->prev_roots[i].hpa);
 			tlb_flush = true;
 		}
 	}
@@ -5814,6 +5834,7 @@
 {
 	struct kvm_mmu_page *sp, *node;
 	int nr_zapped, batch = 0;
+	bool unstable;
 
 restart:
 	list_for_each_entry_safe_reverse(sp, node,
@@ -5846,11 +5867,12 @@
 			goto restart;
 		}
 
-		if (__kvm_mmu_prepare_zap_page(kvm, sp,
-				&kvm->arch.zapped_obsolete_pages, &nr_zapped)) {
-			batch += nr_zapped;
+		unstable = __kvm_mmu_prepare_zap_page(kvm, sp,
+				&kvm->arch.zapped_obsolete_pages, &nr_zapped);
+		batch += nr_zapped;
+
+		if (unstable)
 			goto restart;
-		}
 	}
 
 	/*
@@ -6232,25 +6254,16 @@
 	u64 mask;
 
 	/*
-	 * Set the reserved bits and the present bit of an paging-structure
-	 * entry to generate page fault with PFER.RSV = 1.
-	 */
-
-	/*
-	 * Mask the uppermost physical address bit, which would be reserved as
-	 * long as the supported physical address width is less than 52.
+	 * Set a reserved PA bit in MMIO SPTEs to generate page faults with
+	 * PFEC.RSVD=1 on MMIO accesses.  64-bit PTEs (PAE, x86-64, and EPT
+	 * paging) support a maximum of 52 bits of PA, i.e. if the CPU supports
+	 * 52-bit physical addresses then there are no reserved PA bits in the
+	 * PTEs and so the reserved PA approach must be disabled.
 	 */
-	mask = 1ull << 51;
-
-	/* Set the present bit. */
-	mask |= 1ull;
-
-	/*
-	 * If reserved bit is not supported, clear the present bit to disable
-	 * mmio page fault.
-	 */
-	if (IS_ENABLED(CONFIG_X86_64) && shadow_phys_bits == 52)
-		mask &= ~1ull;
+	if (shadow_phys_bits < 52)
+		mask = BIT_ULL(51) | PT_PRESENT_MASK;
+	else
+		mask = 0;
 
 	kvm_mmu_set_mmio_spte_mask(mask, mask, ACC_WRITE_MASK | ACC_USER_MASK);
 }
@@ -6445,6 +6458,7 @@
 				cond_resched_lock(&kvm->mmu_lock);
 		}
 	}
+	kvm_mmu_commit_zap_page(kvm, &invalid_list);
 
 	spin_unlock(&kvm->mmu_lock);
 	srcu_read_unlock(&kvm->srcu, rcu_idx);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kvm/mmu.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kvm/mmu.h
@@ -48,7 +48,7 @@
 	if (e < s)
 		return 0;
 
-	return ((1ULL << (e - s + 1)) - 1) << s;
+	return ((2ULL << (e - s)) - 1) << s;
 }
 
 void kvm_mmu_set_mmio_spte_mask(u64 mmio_mask, u64 mmio_value, u64 access_mask);
@@ -209,7 +209,7 @@
 void kvm_mmu_gfn_allow_lpage(struct kvm_memory_slot *slot, gfn_t gfn);
 bool kvm_mmu_slot_gfn_write_protect(struct kvm *kvm,
 				    struct kvm_memory_slot *slot, u64 gfn);
-int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu);
+int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu, gpa_t l2_gpa);
 
 int kvm_mmu_post_init_vm(struct kvm *kvm);
 void kvm_mmu_pre_destroy_vm(struct kvm *kvm);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kvm/mmutrace.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kvm/mmutrace.h
@@ -249,13 +249,13 @@
 
 TRACE_EVENT(
 	fast_page_fault,
-	TP_PROTO(struct kvm_vcpu *vcpu, gva_t gva, u32 error_code,
+	TP_PROTO(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa, u32 error_code,
 		 u64 *sptep, u64 old_spte, bool retry),
-	TP_ARGS(vcpu, gva, error_code, sptep, old_spte, retry),
+	TP_ARGS(vcpu, cr2_or_gpa, error_code, sptep, old_spte, retry),
 
 	TP_STRUCT__entry(
 		__field(int, vcpu_id)
-		__field(gva_t, gva)
+		__field(gpa_t, cr2_or_gpa)
 		__field(u32, error_code)
 		__field(u64 *, sptep)
 		__field(u64, old_spte)
@@ -265,7 +265,7 @@
 
 	TP_fast_assign(
 		__entry->vcpu_id = vcpu->vcpu_id;
-		__entry->gva = gva;
+		__entry->cr2_or_gpa = cr2_or_gpa;
 		__entry->error_code = error_code;
 		__entry->sptep = sptep;
 		__entry->old_spte = old_spte;
@@ -273,9 +273,9 @@
 		__entry->retry = retry;
 	),
 
-	TP_printk("vcpu %d gva %lx error_code %s sptep %p old %#llx"
+	TP_printk("vcpu %d gva %llx error_code %s sptep %p old %#llx"
 		  " new %llx spurious %d fixed %d", __entry->vcpu_id,
-		  __entry->gva, __print_flags(__entry->error_code, "|",
+		  __entry->cr2_or_gpa, __print_flags(__entry->error_code, "|",
 		  kvm_mmu_trace_pferr_flags), __entry->sptep,
 		  __entry->old_spte, __entry->new_spte,
 		  __spte_satisfied(old_spte), __spte_satisfied(new_spte)
@@ -339,7 +339,7 @@
 		/* These depend on page entry type, so compute them now.  */
 		__field(bool, r)
 		__field(bool, x)
-		__field(u8, u)
+		__field(signed char, u)
 	),
 
 	TP_fast_assign(
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kvm/mtrr.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kvm/mtrr.c
@@ -192,11 +192,15 @@
 		break;
 	case MSR_MTRRfix16K_80000 ... MSR_MTRRfix16K_A0000:
 		*seg = 1;
-		*unit = msr - MSR_MTRRfix16K_80000;
+		*unit = array_index_nospec(
+			msr - MSR_MTRRfix16K_80000,
+			MSR_MTRRfix16K_A0000 - MSR_MTRRfix16K_80000 + 1);
 		break;
 	case MSR_MTRRfix4K_C0000 ... MSR_MTRRfix4K_F8000:
 		*seg = 2;
-		*unit = msr - MSR_MTRRfix4K_C0000;
+		*unit = array_index_nospec(
+			msr - MSR_MTRRfix4K_C0000,
+			MSR_MTRRfix4K_F8000 - MSR_MTRRfix4K_C0000 + 1);
 		break;
 	default:
 		return false;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kvm/paging_tmpl.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kvm/paging_tmpl.h
@@ -33,10 +33,9 @@
 	#define PT_GUEST_ACCESSED_SHIFT PT_ACCESSED_SHIFT
 	#define PT_HAVE_ACCESSED_DIRTY(mmu) true
 	#ifdef CONFIG_X86_64
-	#define PT_MAX_FULL_LEVELS 4
-	#define CMPXCHG cmpxchg
+	#define PT_MAX_FULL_LEVELS PT64_ROOT_MAX_LEVEL
+	#define CMPXCHG "cmpxchgq"
 	#else
-	#define CMPXCHG cmpxchg64
 	#define PT_MAX_FULL_LEVELS 2
 	#endif
 #elif PTTYPE == 32
@@ -52,7 +51,7 @@
 	#define PT_GUEST_DIRTY_SHIFT PT_DIRTY_SHIFT
 	#define PT_GUEST_ACCESSED_SHIFT PT_ACCESSED_SHIFT
 	#define PT_HAVE_ACCESSED_DIRTY(mmu) true
-	#define CMPXCHG cmpxchg
+	#define CMPXCHG "cmpxchgl"
 #elif PTTYPE == PTTYPE_EPT
 	#define pt_element_t u64
 	#define guest_walker guest_walkerEPT
@@ -65,8 +64,10 @@
 	#define PT_GUEST_DIRTY_SHIFT 9
 	#define PT_GUEST_ACCESSED_SHIFT 8
 	#define PT_HAVE_ACCESSED_DIRTY(mmu) ((mmu)->ept_ad)
-	#define CMPXCHG cmpxchg64
 	#define PT_MAX_FULL_LEVELS 4
+	#ifdef CONFIG_X86_64
+	#define CMPXCHG "cmpxchgq"
+	#endif
 #else
 	#error Invalid PTTYPE value
 #endif
@@ -90,8 +91,8 @@
 	gpa_t pte_gpa[PT_MAX_FULL_LEVELS];
 	pt_element_t __user *ptep_user[PT_MAX_FULL_LEVELS];
 	bool pte_writable[PT_MAX_FULL_LEVELS];
-	unsigned pt_access;
-	unsigned pte_access;
+	unsigned int pt_access[PT_MAX_FULL_LEVELS];
+	unsigned int pte_access;
 	gfn_t gfn;
 	struct x86_exception fault;
 };
@@ -132,43 +133,39 @@
 			       pt_element_t __user *ptep_user, unsigned index,
 			       pt_element_t orig_pte, pt_element_t new_pte)
 {
-	int npages;
-	pt_element_t ret;
-	pt_element_t *table;
-	struct page *page;
-
-	npages = get_user_pages_fast((unsigned long)ptep_user, 1, FOLL_WRITE, &page);
-	if (likely(npages == 1)) {
-		table = kmap_atomic(page);
-		ret = CMPXCHG(&table[index], orig_pte, new_pte);
-		kunmap_atomic(table);
-
-		kvm_release_page_dirty(page);
-	} else {
-		struct vm_area_struct *vma;
-		unsigned long vaddr = (unsigned long)ptep_user & PAGE_MASK;
-		unsigned long pfn;
-		unsigned long paddr;
-
-		down_read(&current->mm->mmap_sem);
-		vma = find_vma_intersection(current->mm, vaddr, vaddr + PAGE_SIZE);
-		if (!vma || !(vma->vm_flags & VM_PFNMAP)) {
-			up_read(&current->mm->mmap_sem);
-			return -EFAULT;
-		}
-		pfn = ((vaddr - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
-		paddr = pfn << PAGE_SHIFT;
-		table = memremap(paddr, PAGE_SIZE, MEMREMAP_WB);
-		if (!table) {
-			up_read(&current->mm->mmap_sem);
-			return -EFAULT;
-		}
-		ret = CMPXCHG(&table[index], orig_pte, new_pte);
-		memunmap(table);
-		up_read(&current->mm->mmap_sem);
-	}
+	int r = -EFAULT;
+
+	if (!user_access_begin(ptep_user, sizeof(pt_element_t)))
+		return -EFAULT;
 
-	return (ret != orig_pte);
+#ifdef CMPXCHG
+	asm volatile("1:" LOCK_PREFIX CMPXCHG " %[new], %[ptr]\n"
+		     "mov $0, %[r]\n"
+		     "setnz %b[r]\n"
+		     "2:"
+		     _ASM_EXTABLE_UA(1b, 2b)
+		     : [ptr] "+m" (*ptep_user),
+		       [old] "+a" (orig_pte),
+		       [r] "+q" (r)
+		     : [new] "r" (new_pte)
+		     : "memory");
+#else
+	asm volatile("1:" LOCK_PREFIX "cmpxchg8b %[ptr]\n"
+		     "movl $0, %[r]\n"
+		     "jz 2f\n"
+		     "incl %[r]\n"
+		     "2:"
+		     _ASM_EXTABLE_UA(1b, 2b)
+		     : [ptr] "+m" (*ptep_user),
+		       [old] "+A" (orig_pte),
+		       [r] "+rm" (r)
+		     : [new_lo] "b" ((u32)new_pte),
+		       [new_hi] "c" ((u32)(new_pte >> 32))
+		     : "memory");
+#endif
+
+	user_access_end();
+	return r;
 }
 
 static bool FNAME(prefetch_invalid_gpte)(struct kvm_vcpu *vcpu,
@@ -220,7 +217,7 @@
 static int FNAME(update_accessed_dirty_bits)(struct kvm_vcpu *vcpu,
 					     struct kvm_mmu *mmu,
 					     struct guest_walker *walker,
-					     int write_fault)
+					     gpa_t addr, int write_fault)
 {
 	unsigned level, index;
 	pt_element_t pte, orig_pte;
@@ -245,7 +242,7 @@
 				!(pte & PT_GUEST_DIRTY_MASK)) {
 			trace_kvm_mmu_set_dirty_bit(table_gfn, index, sizeof(pte));
 #if PTTYPE == PTTYPE_EPT
-			if (kvm_arch_write_log_dirty(vcpu))
+			if (kvm_arch_write_log_dirty(vcpu, addr))
 				return -EINVAL;
 #endif
 			pte |= PT_GUEST_DIRTY_MASK;
@@ -291,11 +288,11 @@
 }
 
 /*
- * Fetch a guest pte for a guest virtual address
+ * Fetch a guest pte for a guest virtual address, or for an L2's GPA.
  */
 static int FNAME(walk_addr_generic)(struct guest_walker *walker,
 				    struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
-				    gva_t addr, u32 access)
+				    gpa_t addr, u32 access)
 {
 	int ret;
 	pt_element_t pte;
@@ -406,13 +403,15 @@
 		}
 
 		walker->ptes[walker->level - 1] = pte;
+
+		/* Convert to ACC_*_MASK flags for struct guest_walker.  */
+		walker->pt_access[walker->level - 1] = FNAME(gpte_access)(pt_access ^ walk_nx_mask);
 	} while (!is_last_gpte(mmu, walker->level, pte));
 
 	pte_pkey = FNAME(gpte_pkeys)(vcpu, pte);
 	accessed_dirty = have_ad ? pte_access & PT_GUEST_ACCESSED_MASK : 0;
 
 	/* Convert to ACC_*_MASK flags for struct guest_walker.  */
-	walker->pt_access = FNAME(gpte_access)(pt_access ^ walk_nx_mask);
 	walker->pte_access = FNAME(gpte_access)(pte_access ^ walk_nx_mask);
 	errcode = permission_fault(vcpu, mmu, walker->pte_access, pte_pkey, access);
 	if (unlikely(errcode))
@@ -442,7 +441,8 @@
 			(PT_GUEST_DIRTY_SHIFT - PT_GUEST_ACCESSED_SHIFT);
 
 	if (unlikely(!accessed_dirty)) {
-		ret = FNAME(update_accessed_dirty_bits)(vcpu, mmu, walker, write_fault);
+		ret = FNAME(update_accessed_dirty_bits)(vcpu, mmu, walker,
+							addr, write_fault);
 		if (unlikely(ret < 0))
 			goto error;
 		else if (ret)
@@ -450,7 +450,8 @@
 	}
 
 	pgprintk("%s: pte %llx pte_access %x pt_access %x\n",
-		 __func__, (u64)pte, walker->pte_access, walker->pt_access);
+		 __func__, (u64)pte, walker->pte_access,
+		 walker->pt_access[walker->level - 1]);
 	return 1;
 
 error:
@@ -496,7 +497,7 @@
 }
 
 static int FNAME(walk_addr)(struct guest_walker *walker,
-			    struct kvm_vcpu *vcpu, gva_t addr, u32 access)
+			    struct kvm_vcpu *vcpu, gpa_t addr, u32 access)
 {
 	return FNAME(walk_addr_generic)(walker, vcpu, vcpu->arch.mmu, addr,
 					access);
@@ -611,7 +612,7 @@
  * If the guest tries to write a write-protected page, we need to
  * emulate this operation, return 1 to indicate this case.
  */
-static int FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
+static int FNAME(fetch)(struct kvm_vcpu *vcpu, gpa_t addr,
 			 struct guest_walker *gw,
 			 int write_fault, int hlevel,
 			 kvm_pfn_t pfn, bool map_writable, bool prefault,
@@ -619,7 +620,7 @@
 {
 	struct kvm_mmu_page *sp = NULL;
 	struct kvm_shadow_walk_iterator it;
-	unsigned direct_access, access = gw->pt_access;
+	unsigned int direct_access, access;
 	int top_level, ret;
 	gfn_t gfn, base_gfn;
 
@@ -651,6 +652,7 @@
 		sp = NULL;
 		if (!is_shadow_present_pte(*it.sptep)) {
 			table_gfn = gw->table_gfn[it.level - 2];
+			access = gw->pt_access[it.level - 2];
 			sp = kvm_mmu_get_page(vcpu, table_gfn, addr, it.level-1,
 					      false, access);
 		}
@@ -765,7 +767,7 @@
  *  Returns: 1 if we need to emulate the instruction, 0 otherwise, or
  *           a negative value on error.
  */
-static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code,
+static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gpa_t addr, u32 error_code,
 			     bool prefault)
 {
 	int write_fault = error_code & PFERR_WRITE_MASK;
@@ -945,18 +947,19 @@
 	spin_unlock(&vcpu->kvm->mmu_lock);
 }
 
-static gpa_t FNAME(gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t vaddr, u32 access,
+/* Note, @addr is a GPA when gva_to_gpa() translates an L2 GPA to an L1 GPA. */
+static gpa_t FNAME(gva_to_gpa)(struct kvm_vcpu *vcpu, gpa_t addr, u32 access,
 			       struct x86_exception *exception)
 {
 	struct guest_walker walker;
 	gpa_t gpa = UNMAPPED_GVA;
 	int r;
 
-	r = FNAME(walk_addr)(&walker, vcpu, vaddr, access);
+	r = FNAME(walk_addr)(&walker, vcpu, addr, access);
 
 	if (r) {
 		gpa = gfn_to_gpa(walker.gfn);
-		gpa |= vaddr & ~PAGE_MASK;
+		gpa |= addr & ~PAGE_MASK;
 	} else if (exception)
 		*exception = walker.fault;
 
@@ -964,7 +967,8 @@
 }
 
 #if PTTYPE != PTTYPE_EPT
-static gpa_t FNAME(gva_to_gpa_nested)(struct kvm_vcpu *vcpu, gva_t vaddr,
+/* Note, gva_to_gpa_nested() is only used to translate L2 GVAs. */
+static gpa_t FNAME(gva_to_gpa_nested)(struct kvm_vcpu *vcpu, gpa_t vaddr,
 				      u32 access,
 				      struct x86_exception *exception)
 {
@@ -972,6 +976,11 @@
 	gpa_t gpa = UNMAPPED_GVA;
 	int r;
 
+#ifndef CONFIG_X86_64
+	/* A 64-bit GVA should be impossible on 32-bit KVM. */
+	WARN_ON_ONCE(vaddr >> 32);
+#endif
+
 	r = FNAME(walk_addr_nested)(&walker, vcpu, vaddr, access);
 
 	if (r) {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kvm/pmu.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kvm/pmu.c
@@ -143,7 +143,6 @@
 void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)
 {
 	unsigned config, type = PERF_TYPE_RAW;
-	u8 event_select, unit_mask;
 	struct kvm *kvm = pmc->vcpu->kvm;
 	struct kvm_pmu_event_filter *filter;
 	int i;
@@ -175,23 +174,18 @@
 	if (!allow_event)
 		return;
 
-	event_select = eventsel & ARCH_PERFMON_EVENTSEL_EVENT;
-	unit_mask = (eventsel & ARCH_PERFMON_EVENTSEL_UMASK) >> 8;
-
 	if (!(eventsel & (ARCH_PERFMON_EVENTSEL_EDGE |
 			  ARCH_PERFMON_EVENTSEL_INV |
 			  ARCH_PERFMON_EVENTSEL_CMASK |
 			  HSW_IN_TX |
 			  HSW_IN_TX_CHECKPOINTED))) {
-		config = kvm_x86_ops->pmu_ops->find_arch_event(pmc_to_pmu(pmc),
-						      event_select,
-						      unit_mask);
+		config = kvm_x86_ops->pmu_ops->pmc_perf_hw_id(pmc);
 		if (config != PERF_COUNT_HW_MAX)
 			type = PERF_TYPE_HARDWARE;
 	}
 
 	if (type == PERF_TYPE_RAW)
-		config = eventsel & X86_RAW_EVENT_MASK;
+		config = eventsel & AMD64_RAW_EVENT_MASK;
 
 	pmc_reprogram_counter(pmc, type, config,
 			      !(eventsel & ARCH_PERFMON_EVENTSEL_USR),
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kvm/pmu.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kvm/pmu.h
@@ -2,6 +2,8 @@
 #ifndef __KVM_X86_PMU_H
 #define __KVM_X86_PMU_H
 
+#include <linux/nospec.h>
+
 #define vcpu_to_pmu(vcpu) (&(vcpu)->arch.pmu)
 #define pmu_to_vcpu(pmu)  (container_of((pmu), struct kvm_vcpu, arch.pmu))
 #define pmc_to_pmu(pmc)   (&(pmc)->vcpu->arch.pmu)
@@ -20,8 +22,7 @@
 };
 
 struct kvm_pmu_ops {
-	unsigned (*find_arch_event)(struct kvm_pmu *pmu, u8 event_select,
-				    u8 unit_mask);
+	unsigned int (*pmc_perf_hw_id)(struct kvm_pmc *pmc);
 	unsigned (*find_fixed_event)(int idx);
 	bool (*pmc_is_enabled)(struct kvm_pmc *pmc);
 	struct kvm_pmc *(*pmc_idx_to_pmc)(struct kvm_pmu *pmu, int pmc_idx);
@@ -86,8 +87,12 @@
 static inline struct kvm_pmc *get_gp_pmc(struct kvm_pmu *pmu, u32 msr,
 					 u32 base)
 {
-	if (msr >= base && msr < base + pmu->nr_arch_gp_counters)
-		return &pmu->gp_counters[msr - base];
+	if (msr >= base && msr < base + pmu->nr_arch_gp_counters) {
+		u32 index = array_index_nospec(msr - base,
+					       pmu->nr_arch_gp_counters);
+
+		return &pmu->gp_counters[index];
+	}
 
 	return NULL;
 }
@@ -97,8 +102,12 @@
 {
 	int base = MSR_CORE_PERF_FIXED_CTR0;
 
-	if (msr >= base && msr < base + pmu->nr_arch_fixed_counters)
-		return &pmu->fixed_counters[msr - base];
+	if (msr >= base && msr < base + pmu->nr_arch_fixed_counters) {
+		u32 index = array_index_nospec(msr - base,
+					       pmu->nr_arch_fixed_counters);
+
+		return &pmu->fixed_counters[index];
+	}
 
 	return NULL;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kvm/pmu_amd.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kvm/pmu_amd.c
@@ -44,6 +44,22 @@
 	[7] = { 0xd1, 0x00, PERF_COUNT_HW_STALLED_CYCLES_BACKEND },
 };
 
+/* duplicated from amd_f17h_perfmon_event_map. */
+static struct kvm_event_hw_type_mapping amd_f17h_event_mapping[] = {
+	[0] = { 0x76, 0x00, PERF_COUNT_HW_CPU_CYCLES },
+	[1] = { 0xc0, 0x00, PERF_COUNT_HW_INSTRUCTIONS },
+	[2] = { 0x60, 0xff, PERF_COUNT_HW_CACHE_REFERENCES },
+	[3] = { 0x64, 0x09, PERF_COUNT_HW_CACHE_MISSES },
+	[4] = { 0xc2, 0x00, PERF_COUNT_HW_BRANCH_INSTRUCTIONS },
+	[5] = { 0xc3, 0x00, PERF_COUNT_HW_BRANCH_MISSES },
+	[6] = { 0x87, 0x02, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND },
+	[7] = { 0x87, 0x01, PERF_COUNT_HW_STALLED_CYCLES_BACKEND },
+};
+
+/* amd_pmc_perf_hw_id depends on these being the same size */
+static_assert(ARRAY_SIZE(amd_event_mapping) ==
+	     ARRAY_SIZE(amd_f17h_event_mapping));
+
 static unsigned int get_msr_base(struct kvm_pmu *pmu, enum pmu_type type)
 {
 	struct kvm_vcpu *vcpu = pmu_to_vcpu(pmu);
@@ -126,21 +142,27 @@
 	return &pmu->gp_counters[msr_to_index(msr)];
 }
 
-static unsigned amd_find_arch_event(struct kvm_pmu *pmu,
-				    u8 event_select,
-				    u8 unit_mask)
+static unsigned int amd_pmc_perf_hw_id(struct kvm_pmc *pmc)
 {
+	struct kvm_event_hw_type_mapping *event_mapping;
+	u8 event_select = pmc->eventsel & ARCH_PERFMON_EVENTSEL_EVENT;
+	u8 unit_mask = (pmc->eventsel & ARCH_PERFMON_EVENTSEL_UMASK) >> 8;
 	int i;
 
+	if (guest_cpuid_family(pmc->vcpu) >= 0x17)
+		event_mapping = amd_f17h_event_mapping;
+	else
+		event_mapping = amd_event_mapping;
+
 	for (i = 0; i < ARRAY_SIZE(amd_event_mapping); i++)
-		if (amd_event_mapping[i].eventsel == event_select
-		    && amd_event_mapping[i].unit_mask == unit_mask)
+		if (event_mapping[i].eventsel == event_select
+		    && event_mapping[i].unit_mask == unit_mask)
 			break;
 
 	if (i == ARRAY_SIZE(amd_event_mapping))
 		return PERF_COUNT_HW_MAX;
 
-	return amd_event_mapping[i].event_type;
+	return event_mapping[i].event_type;
 }
 
 /* return PERF_COUNT_HW_MAX as AMD doesn't have fixed events */
@@ -245,12 +267,10 @@
 	/* MSR_EVNTSELn */
 	pmc = get_gp_pmc_amd(pmu, msr, PMU_TYPE_EVNTSEL);
 	if (pmc) {
-		if (data == pmc->eventsel)
-			return 0;
-		if (!(data & pmu->reserved_bits)) {
+		data &= ~pmu->reserved_bits;
+		if (data != pmc->eventsel)
 			reprogram_gp_counter(pmc, data);
-			return 0;
-		}
+		return 0;
 	}
 
 	return 1;
@@ -266,7 +286,7 @@
 		pmu->nr_arch_gp_counters = AMD64_NUM_COUNTERS;
 
 	pmu->counter_bitmask[KVM_PMC_GP] = ((u64)1 << 48) - 1;
-	pmu->reserved_bits = 0xffffffff00200000ull;
+	pmu->reserved_bits = 0xfffffff000280000ull;
 	pmu->version = 1;
 	/* not applicable to AMD; but clean them to prevent any fall out */
 	pmu->counter_bitmask[KVM_PMC_FIXED] = 0;
@@ -302,7 +322,7 @@
 }
 
 struct kvm_pmu_ops amd_pmu_ops = {
-	.find_arch_event = amd_find_arch_event,
+	.pmc_perf_hw_id = amd_pmc_perf_hw_id,
 	.find_fixed_event = amd_find_fixed_event,
 	.pmc_is_enabled = amd_pmc_is_enabled,
 	.pmc_idx_to_pmc = amd_pmc_idx_to_pmc,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kvm/svm.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kvm/svm.c
@@ -47,6 +47,7 @@
 #include <asm/kvm_para.h>
 #include <asm/irq_remapping.h>
 #include <asm/spec-ctrl.h>
+#include <asm/cpu_device_id.h>
 
 #include <asm/virtext.h>
 #include "trace.h"
@@ -516,6 +517,9 @@
 	c->intercept_dr = h->intercept_dr | g->intercept_dr;
 	c->intercept_exceptions = h->intercept_exceptions | g->intercept_exceptions;
 	c->intercept = h->intercept | g->intercept;
+
+	c->intercept |= (1ULL << INTERCEPT_VMLOAD);
+	c->intercept |= (1ULL << INTERCEPT_VMSAVE);
 }
 
 static inline struct vmcb *get_host_vmcb(struct vcpu_svm *svm)
@@ -787,9 +791,6 @@
 		if (!kvm_emulate_instruction(vcpu, EMULTYPE_SKIP))
 			return 0;
 	} else {
-		if (svm->next_rip - kvm_rip_read(vcpu) > MAX_INST_SIZE)
-			pr_err("%s: ip 0x%lx next 0x%llx\n",
-			       __func__, kvm_rip_read(vcpu), svm->next_rip);
 		kvm_rip_write(vcpu, svm->next_rip);
 	}
 	svm_set_interrupt_shadow(vcpu, 0);
@@ -892,6 +893,11 @@
 		return 0;
 	}
 
+	if (sev_active()) {
+		pr_info("KVM is unsupported when running as an SEV guest\n");
+		return 0;
+	}
+
 	return 1;
 }
 
@@ -998,33 +1004,32 @@
 static int svm_cpu_init(int cpu)
 {
 	struct svm_cpu_data *sd;
-	int r;
 
 	sd = kzalloc(sizeof(struct svm_cpu_data), GFP_KERNEL);
 	if (!sd)
 		return -ENOMEM;
 	sd->cpu = cpu;
-	r = -ENOMEM;
 	sd->save_area = alloc_page(GFP_KERNEL);
 	if (!sd->save_area)
-		goto err_1;
+		goto free_cpu_data;
 
 	if (svm_sev_enabled()) {
-		r = -ENOMEM;
 		sd->sev_vmcbs = kmalloc_array(max_sev_asid + 1,
 					      sizeof(void *),
 					      GFP_KERNEL);
 		if (!sd->sev_vmcbs)
-			goto err_1;
+			goto free_save_area;
 	}
 
 	per_cpu(svm_data, cpu) = sd;
 
 	return 0;
 
-err_1:
+free_save_area:
+	__free_page(sd->save_area);
+free_cpu_data:
 	kfree(sd);
-	return r;
+	return -ENOMEM;
 
 }
 
@@ -1298,6 +1303,47 @@
 	}
 }
 
+/*
+ * The default MMIO mask is a single bit (excluding the present bit),
+ * which could conflict with the memory encryption bit. Check for
+ * memory encryption support and override the default MMIO mask if
+ * memory encryption is enabled.
+ */
+static __init void svm_adjust_mmio_mask(void)
+{
+	unsigned int enc_bit, mask_bit;
+	u64 msr, mask;
+
+	/* If there is no memory encryption support, use existing mask */
+	if (cpuid_eax(0x80000000) < 0x8000001f)
+		return;
+
+	/* If memory encryption is not enabled, use existing mask */
+	rdmsrl(MSR_K8_SYSCFG, msr);
+	if (!(msr & MSR_K8_SYSCFG_MEM_ENCRYPT))
+		return;
+
+	enc_bit = cpuid_ebx(0x8000001f) & 0x3f;
+	mask_bit = boot_cpu_data.x86_phys_bits;
+
+	/* Increment the mask bit if it is the same as the encryption bit */
+	if (enc_bit == mask_bit)
+		mask_bit++;
+
+	/*
+	 * If the mask bit location is below 52, then some bits above the
+	 * physical addressing limit will always be reserved, so use the
+	 * rsvd_bits() function to generate the mask. This mask, along with
+	 * the present bit, will be used to generate a page fault with
+	 * PFER.RSV = 1.
+	 *
+	 * If the mask bit location is 52 (or above), then clear the mask.
+	 */
+	mask = (mask_bit < 52) ? rsvd_bits(mask_bit, 51) | PT_PRESENT_MASK : 0;
+
+	kvm_mmu_set_mmio_spte_mask(mask, mask, PT_WRITABLE_MASK | PT_USER_MASK);
+}
+
 static __init int svm_hardware_setup(void)
 {
 	int cpu;
@@ -1352,6 +1398,8 @@
 		}
 	}
 
+	svm_adjust_mmio_mask();
+
 	for_each_possible_cpu(cpu) {
 		r = svm_cpu_init(cpu);
 		if (r)
@@ -1399,12 +1447,7 @@
 		}
 	}
 
-	if (vgif) {
-		if (!boot_cpu_has(X86_FEATURE_VGIF))
-			vgif = false;
-		else
-			pr_info("Virtual GIF supported\n");
-	}
+	vgif = false; /* Disabled for CVE-2021-3653 */
 
 	return 0;
 
@@ -1739,7 +1782,7 @@
 
 	for_each_possible_cpu(cpu) {
 		sd = per_cpu(svm_data, cpu);
-		sd->sev_vmcbs[pos] = NULL;
+		sd->sev_vmcbs[asid] = NULL;
 	}
 }
 
@@ -1750,9 +1793,25 @@
 	__sev_asid_free(sev->asid);
 }
 
-static void sev_unbind_asid(struct kvm *kvm, unsigned int handle)
+static void sev_decommission(unsigned int handle)
 {
 	struct sev_data_decommission *decommission;
+
+	if (!handle)
+		return;
+
+	decommission = kzalloc(sizeof(*decommission), GFP_KERNEL);
+	if (!decommission)
+		return;
+
+	decommission->handle = handle;
+	sev_guest_decommission(decommission, NULL);
+
+	kfree(decommission);
+}
+
+static void sev_unbind_asid(struct kvm *kvm, unsigned int handle)
+{
 	struct sev_data_deactivate *data;
 
 	if (!handle)
@@ -1770,15 +1829,7 @@
 	sev_guest_df_flush(NULL);
 	kfree(data);
 
-	decommission = kzalloc(sizeof(*decommission), GFP_KERNEL);
-	if (!decommission)
-		return;
-
-	/* decommission handle */
-	decommission->handle = handle;
-	sev_guest_decommission(decommission, NULL);
-
-	kfree(decommission);
+	sev_decommission(handle);
 }
 
 static struct page **sev_pin_memory(struct kvm *kvm, unsigned long uaddr,
@@ -1791,6 +1842,8 @@
 	struct page **pages;
 	unsigned long first, last;
 
+	lockdep_assert_held(&kvm->lock);
+
 	if (ulen == 0 || uaddr + ulen < uaddr)
 		return NULL;
 
@@ -1818,7 +1871,7 @@
 		return NULL;
 
 	/* Pin the user virtual address. */
-	npinned = get_user_pages_fast(uaddr, npages, FOLL_WRITE, pages);
+	npinned = get_user_pages_fast(uaddr, npages, write ? FOLL_WRITE : 0, pages);
 	if (npinned != npages) {
 		pr_err("SEV: Failure locking %lu pages.\n", npages);
 		goto err;
@@ -1852,7 +1905,8 @@
 	uint8_t *page_virtual;
 	unsigned long i;
 
-	if (npages == 0 || pages == NULL)
+	if (this_cpu_has(X86_FEATURE_SME_COHERENT) || npages == 0 ||
+	    pages == NULL)
 		return;
 
 	for (i = 0; i < npages; i++) {
@@ -1883,6 +1937,10 @@
 	struct kvm_svm *kvm_svm = __vmalloc(sizeof(struct kvm_svm),
 					    GFP_KERNEL_ACCOUNT | __GFP_ZERO,
 					    PAGE_KERNEL);
+
+	if (!kvm_svm)
+		return NULL;
+
 	return &kvm_svm->kvm;
 }
 
@@ -1910,6 +1968,7 @@
 		list_for_each_safe(pos, q, head) {
 			__unregister_enc_region_locked(kvm,
 				list_entry(pos, struct enc_region, list));
+			cond_resched();
 		}
 	}
 
@@ -3191,8 +3250,8 @@
 			return NESTED_EXIT_HOST;
 		break;
 	case SVM_EXIT_EXCP_BASE + PF_VECTOR:
-		/* When we're shadowing, trap PFs, but not async PF */
-		if (!npt_enabled && svm->vcpu.arch.apf.host_apf_reason == 0)
+		/* Trap async PF even if not shadowing */
+		if (!npt_enabled || svm->vcpu.arch.apf.host_apf_reason)
 			return NESTED_EXIT_HOST;
 		break;
 	default:
@@ -3281,7 +3340,7 @@
 	dst->iopm_base_pa         = from->iopm_base_pa;
 	dst->msrpm_base_pa        = from->msrpm_base_pa;
 	dst->tsc_offset           = from->tsc_offset;
-	dst->asid                 = from->asid;
+	/* asid not copied, it is handled manually for svm->vmcb.  */
 	dst->tlb_ctl              = from->tlb_ctl;
 	dst->int_ctl              = from->int_ctl;
 	dst->int_vector           = from->int_vector;
@@ -3548,7 +3607,13 @@
 	svm->nested.intercept            = nested_vmcb->control.intercept;
 
 	svm_flush_tlb(&svm->vcpu, true);
-	svm->vmcb->control.int_ctl = nested_vmcb->control.int_ctl | V_INTR_MASKING_MASK;
+
+	svm->vmcb->control.int_ctl &=
+			V_INTR_MASKING_MASK | V_GIF_ENABLE_MASK | V_GIF_MASK;
+
+	svm->vmcb->control.int_ctl |= nested_vmcb->control.int_ctl &
+			(V_TPR_MASK | V_IRQ_INJECTION_BITS_MASK);
+
 	if (nested_vmcb->control.int_ctl & V_INTR_MASKING_MASK)
 		svm->vcpu.arch.hflags |= HF_VINTR_MASK;
 	else
@@ -3924,6 +3989,12 @@
 	return 1;
 }
 
+static int invd_interception(struct vcpu_svm *svm)
+{
+	/* Treat an INVD instruction as a NOP and just skip it. */
+	return kvm_skip_emulated_instruction(&svm->vcpu);
+}
+
 static int invlpg_interception(struct vcpu_svm *svm)
 {
 	if (!static_cpu_has(X86_FEATURE_DECODEASSISTS))
@@ -4001,7 +4072,7 @@
 	err = 0;
 	if (cr >= 16) { /* mov to cr */
 		cr -= 16;
-		val = kvm_register_read(&svm->vcpu, reg);
+		val = kvm_register_readl(&svm->vcpu, reg);
 		switch (cr) {
 		case 0:
 			if (!check_selective_cr0_intercepted(svm, val))
@@ -4046,7 +4117,7 @@
 			kvm_queue_exception(&svm->vcpu, UD_VECTOR);
 			return 1;
 		}
-		kvm_register_write(&svm->vcpu, reg, val);
+		kvm_register_writel(&svm->vcpu, reg, val);
 	}
 	return kvm_complete_insn_gp(&svm->vcpu, err);
 }
@@ -4076,13 +4147,13 @@
 	if (dr >= 16) { /* mov to DRn */
 		if (!kvm_require_dr(&svm->vcpu, dr - 16))
 			return 1;
-		val = kvm_register_read(&svm->vcpu, reg);
+		val = kvm_register_readl(&svm->vcpu, reg);
 		kvm_set_dr(&svm->vcpu, dr - 16, val);
 	} else {
 		if (!kvm_require_dr(&svm->vcpu, dr))
 			return 1;
 		kvm_get_dr(&svm->vcpu, dr, &val);
-		kvm_register_write(&svm->vcpu, reg, val);
+		kvm_register_writel(&svm->vcpu, reg, val);
 	}
 
 	return kvm_skip_emulated_instruction(&svm->vcpu);
@@ -4109,9 +4180,9 @@
 	msr->data = 0;
 
 	switch (msr->index) {
-	case MSR_F10H_DECFG:
-		if (boot_cpu_has(X86_FEATURE_LFENCE_RDTSC))
-			msr->data |= MSR_F10H_DECFG_LFENCE_SERIALIZE;
+	case MSR_AMD64_DE_CFG:
+		if (cpu_feature_enabled(X86_FEATURE_LFENCE_RDTSC))
+			msr->data |= MSR_AMD64_DE_CFG_LFENCE_SERIALIZE;
 		break;
 	default:
 		return 1;
@@ -4184,8 +4255,7 @@
 		break;
 	case MSR_IA32_SPEC_CTRL:
 		if (!msr_info->host_initiated &&
-		    !guest_cpuid_has(vcpu, X86_FEATURE_AMD_IBRS) &&
-		    !guest_cpuid_has(vcpu, X86_FEATURE_AMD_SSBD))
+		    !guest_has_spec_ctrl_msr(vcpu))
 			return 1;
 
 		msr_info->data = svm->spec_ctrl;
@@ -4214,7 +4284,7 @@
 			msr_info->data = 0x1E;
 		}
 		break;
-	case MSR_F10H_DECFG:
+	case MSR_AMD64_DE_CFG:
 		msr_info->data = svm->msr_decfg;
 		break;
 	default:
@@ -4269,16 +4339,13 @@
 		break;
 	case MSR_IA32_SPEC_CTRL:
 		if (!msr->host_initiated &&
-		    !guest_cpuid_has(vcpu, X86_FEATURE_AMD_IBRS) &&
-		    !guest_cpuid_has(vcpu, X86_FEATURE_AMD_SSBD))
+		    !guest_has_spec_ctrl_msr(vcpu))
 			return 1;
 
-		/* The STIBP bit doesn't fault even if it's not advertised */
-		if (data & ~(SPEC_CTRL_IBRS | SPEC_CTRL_STIBP | SPEC_CTRL_SSBD))
+		if (kvm_spec_ctrl_test_value(data))
 			return 1;
 
 		svm->spec_ctrl = data;
-
 		if (!data)
 			break;
 
@@ -4297,18 +4364,17 @@
 		break;
 	case MSR_IA32_PRED_CMD:
 		if (!msr->host_initiated &&
-		    !guest_cpuid_has(vcpu, X86_FEATURE_AMD_IBPB))
+		    !guest_has_pred_cmd_msr(vcpu))
 			return 1;
 
 		if (data & ~PRED_CMD_IBPB)
 			return 1;
-
+		if (!boot_cpu_has(X86_FEATURE_IBPB))
+			return 1;
 		if (!data)
 			break;
 
 		wrmsrl(MSR_IA32_PRED_CMD, PRED_CMD_IBPB);
-		if (is_guest_mode(vcpu))
-			break;
 		set_msr_interception(svm->msrpm, MSR_IA32_PRED_CMD, 0, 1);
 		break;
 	case MSR_AMD64_VIRT_SPEC_CTRL:
@@ -4385,7 +4451,7 @@
 	case MSR_VM_IGNNE:
 		vcpu_unimpl(vcpu, "unimplemented wrmsr: 0x%x data 0x%llx\n", ecx, data);
 		break;
-	case MSR_F10H_DECFG: {
+	case MSR_AMD64_DE_CFG: {
 		struct kvm_msr_entry msr_entry;
 
 		msr_entry.index = msr->index;
@@ -4521,8 +4587,6 @@
 		break;
 	}
 	case AVIC_IPI_FAILURE_INVALID_TARGET:
-		WARN_ONCE(1, "Invalid IPI target: index=%u, vcpu=%d, icr=%#0x:%#0x\n",
-			  index, svm->vcpu.vcpu_id, icrh, icrl);
 		break;
 	case AVIC_IPI_FAILURE_INVALID_BACKING_PAGE:
 		WARN_ONCE(1, "Invalid backing page\n");
@@ -4776,7 +4840,7 @@
 	[SVM_EXIT_RDPMC]			= rdpmc_interception,
 	[SVM_EXIT_CPUID]			= cpuid_interception,
 	[SVM_EXIT_IRET]                         = iret_interception,
-	[SVM_EXIT_INVD]                         = emulate_on_interception,
+	[SVM_EXIT_INVD]                         = invd_interception,
 	[SVM_EXIT_PAUSE]			= pause_interception,
 	[SVM_EXIT_HLT]				= halt_interception,
 	[SVM_EXIT_INVLPG]			= invlpg_interception,
@@ -5074,8 +5138,6 @@
 {
 	struct vcpu_svm *svm = to_svm(vcpu);
 
-	BUG_ON(!(gif_set(svm)));
-
 	trace_kvm_inj_virq(vcpu->arch.interrupt.nr);
 	++vcpu->stat.irq_injections;
 
@@ -5141,8 +5203,11 @@
 	return;
 }
 
-static void svm_deliver_avic_intr(struct kvm_vcpu *vcpu, int vec)
+static int svm_deliver_avic_intr(struct kvm_vcpu *vcpu, int vec)
 {
+	if (!vcpu->arch.apicv_active)
+		return -1;
+
 	kvm_lapic_set_irr(vec, vcpu->arch.apic);
 	smp_mb__after_atomic();
 
@@ -5154,6 +5219,8 @@
 		put_cpu();
 	} else
 		kvm_vcpu_wake_up(vcpu);
+
+	return 0;
 }
 
 static bool svm_dy_apicv_has_pending_interrupt(struct kvm_vcpu *vcpu)
@@ -5329,6 +5396,7 @@
 			 * - Tell IOMMU to use legacy mode for this interrupt.
 			 * - Retrieve ga_tag of prior interrupt remapping data.
 			 */
+			pi.prev_ga_tag = 0;
 			pi.is_guest_mode = false;
 			ret = irq_set_vcpu_affinity(host_irq, &pi);
 
@@ -5650,6 +5718,8 @@
 
 	local_irq_enable();
 
+	amd_clear_divider();
+
 	asm volatile (
 		"push %%" _ASM_BP "; \n\t"
 		"mov %c[rbx](%[svm]), %%" _ASM_BX " \n\t"
@@ -5968,7 +6038,7 @@
 
 static bool svm_xsaves_supported(void)
 {
-	return false;
+	return boot_cpu_has(X86_FEATURE_XSAVES);
 }
 
 static bool svm_umip_emulated(void)
@@ -5986,6 +6056,11 @@
 	return true;
 }
 
+static bool svm_pku_supported(void)
+{
+	return false;
+}
+
 #define PRE_EX(exit)  { .exit_code = (exit), \
 			.stage = X86_ICPT_PRE_EXCEPT, }
 #define POST_EX(exit) { .exit_code = (exit), \
@@ -6173,7 +6248,8 @@
 
 static void svm_handle_exit_irqoff(struct kvm_vcpu *vcpu)
 {
-
+	if (to_svm(vcpu)->vmcb->control.exit_code == SVM_EXIT_INTR)
+		vcpu->arch.at_instruction_boundary = true;
 }
 
 static void svm_sched_in(struct kvm_vcpu *vcpu, int cpu)
@@ -6413,8 +6489,10 @@
 
 	/* Bind ASID to this guest */
 	ret = sev_bind_asid(kvm, start->handle, error);
-	if (ret)
+	if (ret) {
+		sev_decommission(start->handle);
 		goto e_free_session;
+	}
 
 	/* return handle to userspace */
 	params.handle = start->handle;
@@ -7031,12 +7109,20 @@
 	if (!region)
 		return -ENOMEM;
 
+	mutex_lock(&kvm->lock);
 	region->pages = sev_pin_memory(kvm, range->addr, range->size, &region->npages, 1);
 	if (!region->pages) {
 		ret = -ENOMEM;
+		mutex_unlock(&kvm->lock);
 		goto e_free;
 	}
 
+	region->uaddr = range->addr;
+	region->size = range->size;
+
+	list_add_tail(&region->list, &sev->regions_list);
+	mutex_unlock(&kvm->lock);
+
 	/*
 	 * The guest may change the memory encryption attribute from C=0 -> C=1
 	 * or vice versa for this memory range. Lets make sure caches are
@@ -7045,13 +7131,6 @@
 	 */
 	sev_clflush_pages(region->pages, region->npages);
 
-	region->uaddr = range->addr;
-	region->size = range->size;
-
-	mutex_lock(&kvm->lock);
-	list_add_tail(&region->list, &sev->regions_list);
-	mutex_unlock(&kvm->lock);
-
 	return ret;
 
 e_free:
@@ -7278,6 +7357,7 @@
 	.xsaves_supported = svm_xsaves_supported,
 	.umip_emulated = svm_umip_emulated,
 	.pt_supported = svm_pt_supported,
+	.pku_supported = svm_pku_supported,
 
 	.set_supported_cpuid = svm_set_supported_cpuid,
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kvm/trace.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kvm/trace.h
@@ -1483,16 +1483,16 @@
 	TP_ARGS(msg, err),
 
 	TP_STRUCT__entry(
-		__field(const char *, msg)
+		__string(msg, msg)
 		__field(u32, err)
 	),
 
 	TP_fast_assign(
-		__entry->msg = msg;
+		__assign_str(msg, msg);
 		__entry->err = err;
 	),
 
-	TP_printk("%s%s", __entry->msg, !__entry->err ? "" :
+	TP_printk("%s%s", __get_str(msg), !__entry->err ? "" :
 		__print_symbolic(__entry->err, VMX_VMENTER_INSTRUCTION_ERRORS))
 );
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kvm/vmx/capabilities.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kvm/vmx/capabilities.h
@@ -12,6 +12,7 @@
 extern bool __read_mostly enable_unrestricted_guest;
 extern bool __read_mostly enable_ept_ad_bits;
 extern bool __read_mostly enable_pml;
+extern bool __read_mostly enable_apicv;
 extern int __read_mostly pt_mode;
 
 #define PT_MODE_SYSTEM		0
@@ -145,6 +146,11 @@
 		SECONDARY_EXEC_DESC;
 }
 
+static inline bool vmx_pku_supported(void)
+{
+	return boot_cpu_has(X86_FEATURE_PKU);
+}
+
 static inline bool cpu_has_vmx_rdtscp(void)
 {
 	return vmcs_config.cpu_based_2nd_exec_ctrl &
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kvm/vmx/evmcs.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kvm/vmx/evmcs.c
@@ -303,14 +303,13 @@
 };
 const unsigned int nr_evmcs_1_fields = ARRAY_SIZE(vmcs_field_to_evmcs_1);
 
-void evmcs_sanitize_exec_ctrls(struct vmcs_config *vmcs_conf)
+__init void evmcs_sanitize_exec_ctrls(struct vmcs_config *vmcs_conf)
 {
 	vmcs_conf->pin_based_exec_ctrl &= ~EVMCS1_UNSUPPORTED_PINCTRL;
 	vmcs_conf->cpu_based_2nd_exec_ctrl &= ~EVMCS1_UNSUPPORTED_2NDEXEC;
 
 	vmcs_conf->vmexit_ctrl &= ~EVMCS1_UNSUPPORTED_VMEXIT_CTRL;
 	vmcs_conf->vmentry_ctrl &= ~EVMCS1_UNSUPPORTED_VMENTRY_CTRL;
-
 }
 #endif
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kvm/vmx/evmcs.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kvm/vmx/evmcs.h
@@ -58,7 +58,9 @@
 	 SECONDARY_EXEC_SHADOW_VMCS |					\
 	 SECONDARY_EXEC_TSC_SCALING |					\
 	 SECONDARY_EXEC_PAUSE_LOOP_EXITING)
-#define EVMCS1_UNSUPPORTED_VMEXIT_CTRL (VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL)
+#define EVMCS1_UNSUPPORTED_VMEXIT_CTRL					\
+	(VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL |				\
+	 VM_EXIT_SAVE_VMX_PREEMPTION_TIMER)
 #define EVMCS1_UNSUPPORTED_VMENTRY_CTRL (VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL)
 #define EVMCS1_UNSUPPORTED_VMFUNC (VMX_VMFUNC_EPTP_SWITCHING)
 
@@ -184,7 +186,7 @@
 	vp_ap->enlighten_vmentry = 1;
 }
 
-void evmcs_sanitize_exec_ctrls(struct vmcs_config *vmcs_conf);
+__init void evmcs_sanitize_exec_ctrls(struct vmcs_config *vmcs_conf);
 #else /* !IS_ENABLED(CONFIG_HYPERV) */
 static inline void evmcs_write64(unsigned long field, u64 value) {}
 static inline void evmcs_write32(unsigned long field, u32 value) {}
@@ -193,7 +195,6 @@
 static inline u32 evmcs_read32(unsigned long field) { return 0; }
 static inline u16 evmcs_read16(unsigned long field) { return 0; }
 static inline void evmcs_load(u64 phys_addr) {}
-static inline void evmcs_sanitize_exec_ctrls(struct vmcs_config *vmcs_conf) {}
 static inline void evmcs_touch_msr_bitmap(void) {}
 #endif /* IS_ENABLED(CONFIG_HYPERV) */
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kvm/vmx/nested.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kvm/vmx/nested.c
@@ -11,6 +11,7 @@
 #include "mmu.h"
 #include "nested.h"
 #include "trace.h"
+#include "vmx.h"
 #include "x86.h"
 
 static bool __read_mostly enable_shadow_vmcs = 1;
@@ -223,7 +224,7 @@
 		return;
 
 	kvm_vcpu_unmap(vcpu, &vmx->nested.hv_evmcs_map, true);
-	vmx->nested.hv_evmcs_vmptr = -1ull;
+	vmx->nested.hv_evmcs_vmptr = 0;
 	vmx->nested.hv_evmcs = NULL;
 }
 
@@ -302,7 +303,7 @@
 	cpu = get_cpu();
 	prev = vmx->loaded_vmcs;
 	vmx->loaded_vmcs = vmcs;
-	vmx_vcpu_load_vmcs(vcpu, cpu);
+	vmx_vcpu_load_vmcs(vcpu, cpu, prev);
 	vmx_sync_vmcs_host_state(vmx, prev);
 	put_cpu();
 
@@ -1060,7 +1061,7 @@
 		BIT_ULL(49) | BIT_ULL(54) | BIT_ULL(55) |
 		/* reserved */
 		BIT_ULL(31) | GENMASK_ULL(47, 45) | GENMASK_ULL(63, 56);
-	u64 vmx_basic = vmx->nested.msrs.basic;
+	u64 vmx_basic = vmcs_config.nested.basic;
 
 	if (!is_bitwise_subset(vmx_basic, data, feature_and_reserved))
 		return -EINVAL;
@@ -1083,36 +1084,42 @@
 	return 0;
 }
 
-static int
-vmx_restore_control_msr(struct vcpu_vmx *vmx, u32 msr_index, u64 data)
+static void vmx_get_control_msr(struct nested_vmx_msrs *msrs, u32 msr_index,
+				u32 **low, u32 **high)
 {
-	u64 supported;
-	u32 *lowp, *highp;
-
 	switch (msr_index) {
 	case MSR_IA32_VMX_TRUE_PINBASED_CTLS:
-		lowp = &vmx->nested.msrs.pinbased_ctls_low;
-		highp = &vmx->nested.msrs.pinbased_ctls_high;
+		*low = &msrs->pinbased_ctls_low;
+		*high = &msrs->pinbased_ctls_high;
 		break;
 	case MSR_IA32_VMX_TRUE_PROCBASED_CTLS:
-		lowp = &vmx->nested.msrs.procbased_ctls_low;
-		highp = &vmx->nested.msrs.procbased_ctls_high;
+		*low = &msrs->procbased_ctls_low;
+		*high = &msrs->procbased_ctls_high;
 		break;
 	case MSR_IA32_VMX_TRUE_EXIT_CTLS:
-		lowp = &vmx->nested.msrs.exit_ctls_low;
-		highp = &vmx->nested.msrs.exit_ctls_high;
+		*low = &msrs->exit_ctls_low;
+		*high = &msrs->exit_ctls_high;
 		break;
 	case MSR_IA32_VMX_TRUE_ENTRY_CTLS:
-		lowp = &vmx->nested.msrs.entry_ctls_low;
-		highp = &vmx->nested.msrs.entry_ctls_high;
+		*low = &msrs->entry_ctls_low;
+		*high = &msrs->entry_ctls_high;
 		break;
 	case MSR_IA32_VMX_PROCBASED_CTLS2:
-		lowp = &vmx->nested.msrs.secondary_ctls_low;
-		highp = &vmx->nested.msrs.secondary_ctls_high;
+		*low = &msrs->secondary_ctls_low;
+		*high = &msrs->secondary_ctls_high;
 		break;
 	default:
 		BUG();
 	}
+}
+
+static int
+vmx_restore_control_msr(struct vcpu_vmx *vmx, u32 msr_index, u64 data)
+{
+	u32 *lowp, *highp;
+	u64 supported;
+
+	vmx_get_control_msr(&vmcs_config.nested, msr_index, &lowp, &highp);
 
 	supported = vmx_control_msr(*lowp, *highp);
 
@@ -1124,6 +1131,7 @@
 	if (!is_bitwise_subset(supported, data, GENMASK_ULL(63, 32)))
 		return -EINVAL;
 
+	vmx_get_control_msr(&vmx->nested.msrs, msr_index, &lowp, &highp);
 	*lowp = data;
 	*highp = data >> 32;
 	return 0;
@@ -1137,10 +1145,8 @@
 		BIT_ULL(28) | BIT_ULL(29) | BIT_ULL(30) |
 		/* reserved */
 		GENMASK_ULL(13, 9) | BIT_ULL(31);
-	u64 vmx_misc;
-
-	vmx_misc = vmx_control_msr(vmx->nested.msrs.misc_low,
-				   vmx->nested.msrs.misc_high);
+	u64 vmx_misc = vmx_control_msr(vmcs_config.nested.misc_low,
+				       vmcs_config.nested.misc_high);
 
 	if (!is_bitwise_subset(vmx_misc, data, feature_and_reserved_bits))
 		return -EINVAL;
@@ -1168,10 +1174,8 @@
 
 static int vmx_restore_vmx_ept_vpid_cap(struct vcpu_vmx *vmx, u64 data)
 {
-	u64 vmx_ept_vpid_cap;
-
-	vmx_ept_vpid_cap = vmx_control_msr(vmx->nested.msrs.ept_caps,
-					   vmx->nested.msrs.vpid_caps);
+	u64 vmx_ept_vpid_cap = vmx_control_msr(vmcs_config.nested.ept_caps,
+					       vmcs_config.nested.vpid_caps);
 
 	/* Every bit is either reserved or a feature bit. */
 	if (!is_bitwise_subset(vmx_ept_vpid_cap, data, -1ULL))
@@ -1182,20 +1186,21 @@
 	return 0;
 }
 
-static int vmx_restore_fixed0_msr(struct vcpu_vmx *vmx, u32 msr_index, u64 data)
+static u64 *vmx_get_fixed0_msr(struct nested_vmx_msrs *msrs, u32 msr_index)
 {
-	u64 *msr;
-
 	switch (msr_index) {
 	case MSR_IA32_VMX_CR0_FIXED0:
-		msr = &vmx->nested.msrs.cr0_fixed0;
-		break;
+		return &msrs->cr0_fixed0;
 	case MSR_IA32_VMX_CR4_FIXED0:
-		msr = &vmx->nested.msrs.cr4_fixed0;
-		break;
+		return &msrs->cr4_fixed0;
 	default:
 		BUG();
 	}
+}
+
+static int vmx_restore_fixed0_msr(struct vcpu_vmx *vmx, u32 msr_index, u64 data)
+{
+	const u64 *msr = vmx_get_fixed0_msr(&vmcs_config.nested, msr_index);
 
 	/*
 	 * 1 bits (which indicates bits which "must-be-1" during VMX operation)
@@ -1204,7 +1209,7 @@
 	if (!is_bitwise_subset(data, *msr, -1ULL))
 		return -EINVAL;
 
-	*msr = data;
+	*vmx_get_fixed0_msr(&vmx->nested.msrs, msr_index) = data;
 	return 0;
 }
 
@@ -1265,7 +1270,7 @@
 		vmx->nested.msrs.vmcs_enum = data;
 		return 0;
 	case MSR_IA32_VMX_VMFUNC:
-		if (data & ~vmx->nested.msrs.vmfunc_controls)
+		if (data & ~vmcs_config.nested.vmfunc_controls)
 			return -EINVAL;
 		vmx->nested.msrs.vmfunc_controls = data;
 		return 0;
@@ -1828,7 +1833,8 @@
 	if (!nested_enlightened_vmentry(vcpu, &evmcs_gpa))
 		return 1;
 
-	if (unlikely(evmcs_gpa != vmx->nested.hv_evmcs_vmptr)) {
+	if (unlikely(!vmx->nested.hv_evmcs ||
+		     evmcs_gpa != vmx->nested.hv_evmcs_vmptr)) {
 		if (!vmx->nested.hv_evmcs)
 			vmx->nested.current_vmptr = -1ull;
 
@@ -2056,20 +2062,19 @@
 			 ~PIN_BASED_VMX_PREEMPTION_TIMER);
 
 	/* Posted interrupts setting is only taken from vmcs12.  */
-	if (nested_cpu_has_posted_intr(vmcs12)) {
+	vmx->nested.pi_pending = false;
+	if (nested_cpu_has_posted_intr(vmcs12))
 		vmx->nested.posted_intr_nv = vmcs12->posted_intr_nv;
-		vmx->nested.pi_pending = false;
-	} else {
+	else
 		exec_control &= ~PIN_BASED_POSTED_INTR;
-	}
 	pin_controls_set(vmx, exec_control);
 
 	/*
 	 * EXEC CONTROLS
 	 */
 	exec_control = vmx_exec_control(vmx); /* L0's desires */
-	exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING;
-	exec_control &= ~CPU_BASED_VIRTUAL_NMI_PENDING;
+	exec_control &= ~CPU_BASED_INTR_WINDOW_EXITING;
+	exec_control &= ~CPU_BASED_NMI_WINDOW_EXITING;
 	exec_control &= ~CPU_BASED_TPR_SHADOW;
 	exec_control |= vmcs12->cpu_based_vm_exec_control;
 
@@ -2230,6 +2235,8 @@
 		vmcs_writel(GUEST_TR_BASE, vmcs12->guest_tr_base);
 		vmcs_writel(GUEST_GDTR_BASE, vmcs12->guest_gdtr_base);
 		vmcs_writel(GUEST_IDTR_BASE, vmcs12->guest_idtr_base);
+
+		vmx->segment_cache.bitmask = 0;
 	}
 
 	if (!hv_evmcs || !(hv_evmcs->hv_clean_fields &
@@ -2418,6 +2425,16 @@
 				entry_failure_code))
 		return -EINVAL;
 
+	/*
+	 * Immediately write vmcs02.GUEST_CR3.  It will be propagated to vmcs12
+	 * on nested VM-Exit, which can occur without actually running L2 and
+	 * thus without hitting vmx_set_cr3(), e.g. if L1 is entering L2 with
+	 * vmcs12.GUEST_ACTIVITYSTATE=HLT, in which case KVM will intercept the
+	 * transition to HLT instead of running L2.
+	 */
+	if (enable_ept)
+		vmcs_writel(GUEST_CR3, vmcs12->guest_cr3);
+
 	/* Late preparation of GUEST_PDPTRs now that EFER and CRs are set. */
 	if (load_guest_pdptrs_vmcs12 && nested_cpu_has_ept(vmcs12) &&
 	    is_pae_paging(vcpu)) {
@@ -2442,7 +2459,7 @@
 		return -EINVAL;
 
 	if (CC(!nested_cpu_has_virtual_nmis(vmcs12) &&
-	       nested_cpu_has(vmcs12, CPU_BASED_VIRTUAL_NMI_PENDING)))
+	       nested_cpu_has(vmcs12, CPU_BASED_NMI_WINDOW_EXITING)))
 		return -EINVAL;
 
 	return 0;
@@ -2762,7 +2779,7 @@
 					struct vmcs12 *vmcs12,
 					u32 *exit_qual)
 {
-	bool ia32e;
+	bool ia32e = !!(vmcs12->vm_entry_controls & VM_ENTRY_IA32E_MODE);
 
 	*exit_qual = ENTRY_FAIL_DEFAULT;
 
@@ -2779,6 +2796,13 @@
 		return -EINVAL;
 	}
 
+	if (CC((vmcs12->guest_cr0 & (X86_CR0_PG | X86_CR0_PE)) == X86_CR0_PG))
+		return -EINVAL;
+
+	if (CC(ia32e && !(vmcs12->guest_cr4 & X86_CR4_PAE)) ||
+	    CC(ia32e && !(vmcs12->guest_cr0 & X86_CR0_PG)))
+		return -EINVAL;
+
 	/*
 	 * If the load IA32_EFER VM-entry control is 1, the following checks
 	 * are performed on the field for the IA32_EFER MSR:
@@ -2790,7 +2814,6 @@
 	 */
 	if (to_vmx(vcpu)->nested.nested_run_pending &&
 	    (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_EFER)) {
-		ia32e = (vmcs12->vm_entry_controls & VM_ENTRY_IA32E_MODE) != 0;
 		if (CC(!kvm_valid_efer(vcpu, vmcs12->guest_ia32_efer)) ||
 		    CC(ia32e != !!(vmcs12->guest_ia32_efer & EFER_LMA)) ||
 		    CC(((vmcs12->guest_cr0 & X86_CR0_PG) &&
@@ -2847,35 +2870,8 @@
 		vmx->loaded_vmcs->host_state.cr4 = cr4;
 	}
 
-	asm(
-		"sub $%c[wordsize], %%" _ASM_SP "\n\t" /* temporarily adjust RSP for CALL */
-		"cmp %%" _ASM_SP ", %c[host_state_rsp](%[loaded_vmcs]) \n\t"
-		"je 1f \n\t"
-		__ex("vmwrite %%" _ASM_SP ", %[HOST_RSP]") "\n\t"
-		"mov %%" _ASM_SP ", %c[host_state_rsp](%[loaded_vmcs]) \n\t"
-		"1: \n\t"
-		"add $%c[wordsize], %%" _ASM_SP "\n\t" /* un-adjust RSP */
-
-		/* Check if vmlaunch or vmresume is needed */
-		"cmpb $0, %c[launched](%[loaded_vmcs])\n\t"
-
-		/*
-		 * VMLAUNCH and VMRESUME clear RFLAGS.{CF,ZF} on VM-Exit, set
-		 * RFLAGS.CF on VM-Fail Invalid and set RFLAGS.ZF on VM-Fail
-		 * Valid.  vmx_vmenter() directly "returns" RFLAGS, and so the
-		 * results of VM-Enter is captured via CC_{SET,OUT} to vm_fail.
-		 */
-		"call vmx_vmenter\n\t"
-
-		CC_SET(be)
-	      : ASM_CALL_CONSTRAINT, CC_OUT(be) (vm_fail)
-	      :	[HOST_RSP]"r"((unsigned long)HOST_RSP),
-		[loaded_vmcs]"r"(vmx->loaded_vmcs),
-		[launched]"i"(offsetof(struct loaded_vmcs, launched)),
-		[host_state_rsp]"i"(offsetof(struct loaded_vmcs, host_state.rsp)),
-		[wordsize]"i"(sizeof(ulong))
-	      : "memory"
-	);
+	vm_fail = __vmx_vcpu_run(vmx, (unsigned long *)&vcpu->arch.regs,
+				 __vmx_vcpu_run_flags(vmx));
 
 	if (vmx->msr_autoload.host.nr)
 		vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, vmx->msr_autoload.host.nr);
@@ -3049,14 +3045,16 @@
 	u32 exit_qual;
 
 	evaluate_pending_interrupts = exec_controls_get(vmx) &
-		(CPU_BASED_VIRTUAL_INTR_PENDING | CPU_BASED_VIRTUAL_NMI_PENDING);
+		(CPU_BASED_INTR_WINDOW_EXITING | CPU_BASED_NMI_WINDOW_EXITING);
 	if (likely(!evaluate_pending_interrupts) && kvm_vcpu_apicv_active(vcpu))
 		evaluate_pending_interrupts |= vmx_has_apicv_interrupt(vcpu);
 
-	if (!(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS))
+	if (!vmx->nested.nested_run_pending ||
+	    !(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS))
 		vmx->nested.vmcs01_debugctl = vmcs_read64(GUEST_IA32_DEBUGCTL);
 	if (kvm_mpx_supported() &&
-		!(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS))
+	    (!vmx->nested.nested_run_pending ||
+	     !(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS)))
 		vmx->nested.vmcs01_guest_bndcfgs = vmcs_read64(GUEST_BNDCFGS);
 
 	/*
@@ -3083,8 +3081,10 @@
 	prepare_vmcs02_early(vmx, vmcs12);
 
 	if (from_vmentry) {
-		if (unlikely(!nested_get_vmcs12_pages(vcpu)))
+		if (unlikely(!nested_get_vmcs12_pages(vcpu))) {
+			vmx_switch_vmcs(vcpu, &vmx->vmcs01);
 			return NVMX_VMENTRY_KVM_INTERNAL_ERROR;
+		}
 
 		if (nested_vmx_check_vmentry_hw(vcpu)) {
 			vmx_switch_vmcs(vcpu, &vmx->vmcs01);
@@ -3096,7 +3096,7 @@
 	}
 
 	enter_guest_mode(vcpu);
-	if (vmcs12->cpu_based_vm_exec_control & CPU_BASED_USE_TSC_OFFSETING)
+	if (vmcs12->cpu_based_vm_exec_control & CPU_BASED_USE_TSC_OFFSETTING)
 		vcpu->arch.tsc_offset += vmcs12->tsc_offset;
 
 	if (prepare_vmcs02(vcpu, vmcs12, &exit_qual))
@@ -3160,7 +3160,7 @@
 	 * 26.7 "VM-entry failures during or after loading guest state".
 	 */
 vmentry_fail_vmexit_guest_mode:
-	if (vmcs12->cpu_based_vm_exec_control & CPU_BASED_USE_TSC_OFFSETING)
+	if (vmcs12->cpu_based_vm_exec_control & CPU_BASED_USE_TSC_OFFSETTING)
 		vcpu->arch.tsc_offset -= vmcs12->tsc_offset;
 	leave_guest_mode(vcpu);
 
@@ -3273,8 +3273,8 @@
 	 */
 	if ((vmcs12->guest_activity_state == GUEST_ACTIVITY_HLT) &&
 	    !(vmcs12->vm_entry_intr_info_field & INTR_INFO_VALID_MASK) &&
-	    !(vmcs12->cpu_based_vm_exec_control & CPU_BASED_VIRTUAL_NMI_PENDING) &&
-	    !((vmcs12->cpu_based_vm_exec_control & CPU_BASED_VIRTUAL_INTR_PENDING) &&
+	    !(vmcs12->cpu_based_vm_exec_control & CPU_BASED_NMI_WINDOW_EXITING) &&
+	    !((vmcs12->cpu_based_vm_exec_control & CPU_BASED_INTR_WINDOW_EXITING) &&
 	      (vmcs12->guest_rflags & X86_EFLAGS_IF))) {
 		vmx->nested.nested_run_pending = 0;
 		return kvm_vcpu_halt(vcpu);
@@ -3433,7 +3433,16 @@
 	u32 intr_info = nr | INTR_INFO_VALID_MASK;
 
 	if (vcpu->arch.exception.has_error_code) {
-		vmcs12->vm_exit_intr_error_code = vcpu->arch.exception.error_code;
+		/*
+		 * Intel CPUs do not generate error codes with bits 31:16 set,
+		 * and more importantly VMX disallows setting bits 31:16 in the
+		 * injected error code for VM-Entry.  Drop the bits to mimic
+		 * hardware and avoid inducing failure on nested VM-Entry if L1
+		 * chooses to inject the exception back to L2.  AMD CPUs _do_
+		 * generate "full" 32-bit error codes, so KVM allows userspace
+		 * to inject exception error codes with bits 31:16 set.
+		 */
+		vmcs12->vm_exit_intr_error_code = (u16)vcpu->arch.exception.error_code;
 		intr_info |= INTR_INFO_DELIVER_CODE_MASK;
 	}
 
@@ -3449,7 +3458,7 @@
 	nested_vmx_vmexit(vcpu, EXIT_REASON_EXCEPTION_NMI, intr_info, exit_qual);
 }
 
-static int vmx_check_nested_events(struct kvm_vcpu *vcpu, bool external_intr)
+static int vmx_check_nested_events(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
 	unsigned long exit_qual;
@@ -3496,8 +3505,7 @@
 		return 0;
 	}
 
-	if ((kvm_cpu_has_interrupt(vcpu) || external_intr) &&
-	    nested_exit_on_intr(vcpu)) {
+	if (kvm_cpu_has_interrupt(vcpu) && nested_exit_on_intr(vcpu)) {
 		if (block_nested_events)
 			return -EBUSY;
 		nested_vmx_vmexit(vcpu, EXIT_REASON_EXTERNAL_INTERRUPT, 0, 0);
@@ -3733,12 +3741,12 @@
 	/* update exit information fields: */
 	vmcs12->vm_exit_reason = exit_reason;
 	vmcs12->exit_qualification = exit_qualification;
-	vmcs12->vm_exit_intr_info = exit_intr_info;
-
-	vmcs12->idt_vectoring_info_field = 0;
-	vmcs12->vm_exit_instruction_len = vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
-	vmcs12->vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
 
+	/*
+	 * On VM-Exit due to a failed VM-Entry, the VMCS isn't marked launched
+	 * and only EXIT_REASON and EXIT_QUALIFICATION are updated, all other
+	 * exit info fields are unmodified.
+	 */
 	if (!(vmcs12->vm_exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY)) {
 		vmcs12->launch_state = 1;
 
@@ -3750,8 +3758,13 @@
 		 * Transfer the event that L0 or L1 may wanted to inject into
 		 * L2 to IDT_VECTORING_INFO_FIELD.
 		 */
+		vmcs12->idt_vectoring_info_field = 0;
 		vmcs12_save_pending_event(vcpu, vmcs12);
 
+		vmcs12->vm_exit_intr_info = exit_intr_info;
+		vmcs12->vm_exit_instruction_len = vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
+		vmcs12->vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
+
 		/*
 		 * According to spec, there's no need to store the guest's
 		 * MSRs if the exit is due to a VM-entry failure that occurs
@@ -3764,14 +3777,6 @@
 			nested_vmx_abort(vcpu,
 					 VMX_ABORT_SAVE_GUEST_MSR_FAIL);
 	}
-
-	/*
-	 * Drop what we picked up for L2 via vmx_complete_interrupts. It is
-	 * preserved above and would only end up incorrectly in L1.
-	 */
-	vcpu->arch.nmi_injected = false;
-	kvm_clear_exception_queue(vcpu);
-	kvm_clear_interrupt_queue(vcpu);
 }
 
 /*
@@ -3913,6 +3918,10 @@
 	};
 	vmx_set_segment(vcpu, &seg, VCPU_SREG_TR);
 
+	memset(&seg, 0, sizeof(seg));
+	seg.unusable = 1;
+	vmx_set_segment(vcpu, &seg, VCPU_SREG_LDTR);
+
 	kvm_set_dr(vcpu, 7, 0x400);
 	vmcs_write64(GUEST_IA32_DEBUGCTL, 0);
 
@@ -4074,7 +4083,7 @@
 	if (nested_cpu_has_preemption_timer(vmcs12))
 		hrtimer_cancel(&to_vmx(vcpu)->nested.preemption_timer);
 
-	if (vmcs12->cpu_based_vm_exec_control & CPU_BASED_USE_TSC_OFFSETING)
+	if (vmcs12->cpu_based_vm_exec_control & CPU_BASED_USE_TSC_OFFSETTING)
 		vcpu->arch.tsc_offset -= vmcs12->tsc_offset;
 
 	if (likely(!vmx->fail)) {
@@ -4106,8 +4115,30 @@
 		WARN_ON_ONCE(nested_early_check);
 	}
 
+	/*
+	 * Drop events/exceptions that were queued for re-injection to L2
+	 * (picked up via vmx_complete_interrupts()), as well as exceptions
+	 * that were pending for L2.  Note, this must NOT be hoisted above
+	 * prepare_vmcs12(), events/exceptions queued for re-injection need to
+	 * be captured in vmcs12 (see vmcs12_save_pending_event()).
+	 */
+	vcpu->arch.nmi_injected = false;
+	kvm_clear_exception_queue(vcpu);
+	kvm_clear_interrupt_queue(vcpu);
+
 	vmx_switch_vmcs(vcpu, &vmx->vmcs01);
 
+	/*
+	 * If IBRS is advertised to the vCPU, KVM must flush the indirect
+	 * branch predictors when transitioning from L2 to L1, as L1 expects
+	 * hardware (KVM in this case) to provide separate predictor modes.
+	 * Bare metal isolates VMX root (host) from VMX non-root (guest), but
+	 * doesn't isolate different VMCSs, i.e. in this case, doesn't provide
+	 * separate modes for L2 vs L1.
+	 */
+	if (guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL))
+		indirect_branch_prediction_barrier();
+
 	/* Update any VMCS fields that might have changed while L2 ran */
 	vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, vmx->msr_autoload.host.nr);
 	vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, vmx->msr_autoload.guest.nr);
@@ -4147,17 +4178,8 @@
 	vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
 
 	if (likely(!vmx->fail)) {
-		/*
-		 * TODO: SDM says that with acknowledge interrupt on
-		 * exit, bit 31 of the VM-exit interrupt information
-		 * (valid interrupt) is always set to 1 on
-		 * EXIT_REASON_EXTERNAL_INTERRUPT, so we shouldn't
-		 * need kvm_cpu_has_interrupt().  See the commit
-		 * message for details.
-		 */
-		if (nested_exit_intr_ack_set(vcpu) &&
-		    exit_reason == EXIT_REASON_EXTERNAL_INTERRUPT &&
-		    kvm_cpu_has_interrupt(vcpu)) {
+		if (exit_reason == EXIT_REASON_EXTERNAL_INTERRUPT &&
+		    nested_exit_intr_ack_set(vcpu)) {
 			int irq = kvm_cpu_get_interrupt(vcpu);
 			WARN_ON(irq < 0);
 			vmcs12->vm_exit_intr_info = irq |
@@ -4599,32 +4621,28 @@
 {
 	unsigned long field;
 	u64 field_value;
+	struct vcpu_vmx *vmx = to_vmx(vcpu);
 	unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
 	u32 vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
 	int len;
 	gva_t gva = 0;
-	struct vmcs12 *vmcs12;
+	struct vmcs12 *vmcs12 = is_guest_mode(vcpu) ? get_shadow_vmcs12(vcpu)
+						    : get_vmcs12(vcpu);
 	struct x86_exception e;
 	short offset;
 
 	if (!nested_vmx_check_permission(vcpu))
 		return 1;
 
-	if (to_vmx(vcpu)->nested.current_vmptr == -1ull)
+	/*
+	 * In VMX non-root operation, when the VMCS-link pointer is -1ull,
+	 * any VMREAD sets the ALU flags for VMfailInvalid.
+	 */
+	if (vmx->nested.current_vmptr == -1ull ||
+	    (is_guest_mode(vcpu) &&
+	     get_vmcs12(vcpu)->vmcs_link_pointer == -1ull))
 		return nested_vmx_failInvalid(vcpu);
 
-	if (!is_guest_mode(vcpu))
-		vmcs12 = get_vmcs12(vcpu);
-	else {
-		/*
-		 * When vmcs->vmcs_link_pointer is -1ull, any VMREAD
-		 * to shadowed-field sets the ALU flags for VMfailInvalid.
-		 */
-		if (get_vmcs12(vcpu)->vmcs_link_pointer == -1ull)
-			return nested_vmx_failInvalid(vcpu);
-		vmcs12 = get_shadow_vmcs12(vcpu);
-	}
-
 	/* Decode instruction info and find the field to read */
 	field = kvm_register_readl(vcpu, (((vmx_instruction_info) >> 28) & 0xf));
 
@@ -4653,8 +4671,10 @@
 				vmx_instruction_info, true, len, &gva))
 			return 1;
 		/* _system ok, nested_vmx_check_permission has verified cpl=0 */
-		if (kvm_write_guest_virt_system(vcpu, gva, &field_value, len, &e))
+		if (kvm_write_guest_virt_system(vcpu, gva, &field_value, len, &e)) {
 			kvm_inject_page_fault(vcpu, &e);
+			return 1;
+		}
 	}
 
 	return nested_vmx_succeed(vcpu);
@@ -4701,13 +4721,20 @@
 	 */
 	u64 field_value = 0;
 	struct x86_exception e;
-	struct vmcs12 *vmcs12;
+	struct vmcs12 *vmcs12 = is_guest_mode(vcpu) ? get_shadow_vmcs12(vcpu)
+						    : get_vmcs12(vcpu);
 	short offset;
 
 	if (!nested_vmx_check_permission(vcpu))
 		return 1;
 
-	if (vmx->nested.current_vmptr == -1ull)
+	/*
+	 * In VMX non-root operation, when the VMCS-link pointer is -1ull,
+	 * any VMWRITE sets the ALU flags for VMfailInvalid.
+	 */
+	if (vmx->nested.current_vmptr == -1ull ||
+	    (is_guest_mode(vcpu) &&
+	     get_vmcs12(vcpu)->vmcs_link_pointer == -1ull))
 		return nested_vmx_failInvalid(vcpu);
 
 	if (vmx_instruction_info & (1u << 10))
@@ -4726,6 +4753,12 @@
 
 
 	field = kvm_register_readl(vcpu, (((vmx_instruction_info) >> 28) & 0xf));
+
+	offset = vmcs_field_to_offset(field);
+	if (offset < 0)
+		return nested_vmx_failValid(vcpu,
+			VMXERR_UNSUPPORTED_VMCS_COMPONENT);
+
 	/*
 	 * If the vCPU supports "VMWRITE to any supported field in the
 	 * VMCS," then the "read-only" fields are actually read/write.
@@ -4735,29 +4768,12 @@
 		return nested_vmx_failValid(vcpu,
 			VMXERR_VMWRITE_READ_ONLY_VMCS_COMPONENT);
 
-	if (!is_guest_mode(vcpu)) {
-		vmcs12 = get_vmcs12(vcpu);
-
-		/*
-		 * Ensure vmcs12 is up-to-date before any VMWRITE that dirties
-		 * vmcs12, else we may crush a field or consume a stale value.
-		 */
-		if (!is_shadow_field_rw(field))
-			copy_vmcs02_to_vmcs12_rare(vcpu, vmcs12);
-	} else {
-		/*
-		 * When vmcs->vmcs_link_pointer is -1ull, any VMWRITE
-		 * to shadowed-field sets the ALU flags for VMfailInvalid.
-		 */
-		if (get_vmcs12(vcpu)->vmcs_link_pointer == -1ull)
-			return nested_vmx_failInvalid(vcpu);
-		vmcs12 = get_shadow_vmcs12(vcpu);
-	}
-
-	offset = vmcs_field_to_offset(field);
-	if (offset < 0)
-		return nested_vmx_failValid(vcpu,
-			VMXERR_UNSUPPORTED_VMCS_COMPONENT);
+	/*
+	 * Ensure vmcs12 is up-to-date before any VMWRITE that dirties
+	 * vmcs12, else we may crush a field or consume a stale value.
+	 */
+	if (!is_guest_mode(vcpu) && !is_shadow_field_rw(field))
+		copy_vmcs02_to_vmcs12_rare(vcpu, vmcs12);
 
 	/*
 	 * Some Intel CPUs intentionally drop the reserved bits of the AR byte
@@ -5100,7 +5116,7 @@
 	}
 
 	vmcs12 = get_vmcs12(vcpu);
-	if ((vmcs12->vm_function_control & (1 << function)) == 0)
+	if (!(vmcs12->vm_function_control & BIT_ULL(function)))
 		goto fail;
 
 	switch (function) {
@@ -5120,24 +5136,17 @@
 	return 1;
 }
 
-
-static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,
-				       struct vmcs12 *vmcs12)
+/*
+ * Return true if an IO instruction with the specified port and size should cause
+ * a VM-exit into L1.
+ */
+bool nested_vmx_check_io_bitmaps(struct kvm_vcpu *vcpu, unsigned int port,
+				 int size)
 {
-	unsigned long exit_qualification;
+	struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
 	gpa_t bitmap, last_bitmap;
-	unsigned int port;
-	int size;
 	u8 b;
 
-	if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
-		return nested_cpu_has(vmcs12, CPU_BASED_UNCOND_IO_EXITING);
-
-	exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
-
-	port = exit_qualification >> 16;
-	size = (exit_qualification & 7) + 1;
-
 	last_bitmap = (gpa_t)-1;
 	b = -1;
 
@@ -5164,6 +5173,24 @@
 	return false;
 }
 
+static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,
+				       struct vmcs12 *vmcs12)
+{
+	unsigned long exit_qualification;
+	unsigned short port;
+	int size;
+
+	if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
+		return nested_cpu_has(vmcs12, CPU_BASED_UNCOND_IO_EXITING);
+
+	exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+
+	port = exit_qualification >> 16;
+	size = (exit_qualification & 7) + 1;
+
+	return nested_vmx_check_io_bitmaps(vcpu, port, size);
+}
+
 /*
  * Return 1 if we should exit from L2 to L1 to handle an MSR access access,
  * rather than handle it ourselves in L0. I.e., check whether L1 expressed
@@ -5298,7 +5325,7 @@
 
 	/* Decode instruction info and find the field to access */
 	vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
-	field = kvm_register_read(vcpu, (((vmx_instruction_info) >> 28) & 0xf));
+	field = kvm_register_readl(vcpu, (((vmx_instruction_info) >> 28) & 0xf));
 
 	/* Out-of-range fields always cause a VM exit from L2 to L1 */
 	if (field >> 15)
@@ -5351,7 +5378,7 @@
 				vmcs_read32(VM_EXIT_INTR_ERROR_CODE),
 				KVM_ISA_VMX);
 
-	switch (exit_reason) {
+	switch ((u16)exit_reason) {
 	case EXIT_REASON_EXCEPTION_NMI:
 		if (is_nmi(intr_info))
 			return false;
@@ -5370,10 +5397,10 @@
 		return false;
 	case EXIT_REASON_TRIPLE_FAULT:
 		return true;
-	case EXIT_REASON_PENDING_INTERRUPT:
-		return nested_cpu_has(vmcs12, CPU_BASED_VIRTUAL_INTR_PENDING);
+	case EXIT_REASON_INTERRUPT_WINDOW:
+		return nested_cpu_has(vmcs12, CPU_BASED_INTR_WINDOW_EXITING);
 	case EXIT_REASON_NMI_WINDOW:
-		return nested_cpu_has(vmcs12, CPU_BASED_VIRTUAL_NMI_PENDING);
+		return nested_cpu_has(vmcs12, CPU_BASED_NMI_WINDOW_EXITING);
 	case EXIT_REASON_TASK_SWITCH:
 		return true;
 	case EXIT_REASON_CPUID:
@@ -5569,11 +5596,14 @@
 	if (is_guest_mode(vcpu)) {
 		sync_vmcs02_to_vmcs12(vcpu, vmcs12);
 		sync_vmcs02_to_vmcs12_rare(vcpu, vmcs12);
-	} else if (!vmx->nested.need_vmcs12_to_shadow_sync) {
-		if (vmx->nested.hv_evmcs)
-			copy_enlightened_to_vmcs12(vmx);
-		else if (enable_shadow_vmcs)
-			copy_shadow_to_vmcs12(vmx);
+	} else  {
+		copy_vmcs02_to_vmcs12_rare(vcpu, get_vmcs12(vcpu));
+		if (!vmx->nested.need_vmcs12_to_shadow_sync) {
+			if (vmx->nested.hv_evmcs)
+				copy_enlightened_to_vmcs12(vmx);
+			else if (enable_shadow_vmcs)
+				copy_shadow_to_vmcs12(vmx);
+		}
 	}
 
 	BUILD_BUG_ON(sizeof(user_vmx_nested_state->vmcs12) < VMCS12_SIZE);
@@ -5784,8 +5814,7 @@
  * bit in the high half is on if the corresponding bit in the control field
  * may be on. See also vmx_control_verify().
  */
-void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps,
-				bool apicv)
+void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps)
 {
 	/*
 	 * Note that as a general rule, the high half of the MSRs (bits in
@@ -5812,7 +5841,7 @@
 		PIN_BASED_EXT_INTR_MASK |
 		PIN_BASED_NMI_EXITING |
 		PIN_BASED_VIRTUAL_NMIS |
-		(apicv ? PIN_BASED_POSTED_INTR : 0);
+		(enable_apicv ? PIN_BASED_POSTED_INTR : 0);
 	msrs->pinbased_ctls_high |=
 		PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR |
 		PIN_BASED_VMX_PREEMPTION_TIMER;
@@ -5861,8 +5890,8 @@
 	msrs->procbased_ctls_low =
 		CPU_BASED_ALWAYSON_WITHOUT_TRUE_MSR;
 	msrs->procbased_ctls_high &=
-		CPU_BASED_VIRTUAL_INTR_PENDING |
-		CPU_BASED_VIRTUAL_NMI_PENDING | CPU_BASED_USE_TSC_OFFSETING |
+		CPU_BASED_INTR_WINDOW_EXITING |
+		CPU_BASED_NMI_WINDOW_EXITING | CPU_BASED_USE_TSC_OFFSETTING |
 		CPU_BASED_HLT_EXITING | CPU_BASED_INVLPG_EXITING |
 		CPU_BASED_MWAIT_EXITING | CPU_BASED_CR3_LOAD_EXITING |
 		CPU_BASED_CR3_STORE_EXITING |
@@ -5908,7 +5937,8 @@
 		SECONDARY_EXEC_RDRAND_EXITING |
 		SECONDARY_EXEC_ENABLE_INVPCID |
 		SECONDARY_EXEC_RDSEED_EXITING |
-		SECONDARY_EXEC_XSAVES;
+		SECONDARY_EXEC_XSAVES |
+		SECONDARY_EXEC_ENABLE_USR_WAIT_PAUSE;
 
 	/*
 	 * We can emulate "VMCS shadowing," even if the hardware
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kvm/vmx/nested.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kvm/vmx/nested.h
@@ -17,8 +17,7 @@
 };
 
 void vmx_leave_nested(struct kvm_vcpu *vcpu);
-void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps,
-				bool apicv);
+void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps);
 void nested_vmx_hardware_unsetup(void);
 __init int nested_vmx_hardware_setup(int (*exit_handlers[])(struct kvm_vcpu *));
 void nested_vmx_vcpu_setup(void);
@@ -33,6 +32,8 @@
 int vmx_get_vmx_msr(struct nested_vmx_msrs *msrs, u32 msr_index, u64 *pdata);
 int get_vmx_mem_address(struct kvm_vcpu *vcpu, unsigned long exit_qualification,
 			u32 vmx_instruction_info, bool wr, int len, gva_t *ret);
+bool nested_vmx_check_io_bitmaps(struct kvm_vcpu *vcpu, unsigned int port,
+				 int size);
 
 static inline struct vmcs12 *get_vmcs12(struct kvm_vcpu *vcpu)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kvm/vmx/ops.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kvm/vmx/ops.h
@@ -13,6 +13,8 @@
 #define __ex(x) __kvm_handle_fault_on_reboot(x)
 
 asmlinkage void vmread_error(unsigned long field, bool fault);
+__attribute__((regparm(0))) void vmread_error_trampoline(unsigned long field,
+							 bool fault);
 void vmwrite_error(unsigned long field, unsigned long value);
 void vmclear_error(struct vmcs *vmcs, u64 phys_addr);
 void vmptrld_error(struct vmcs *vmcs, u64 phys_addr);
@@ -70,15 +72,28 @@
 	asm volatile("1: vmread %2, %1\n\t"
 		     ".byte 0x3e\n\t" /* branch taken hint */
 		     "ja 3f\n\t"
-		     "mov %2, %%" _ASM_ARG1 "\n\t"
-		     "xor %%" _ASM_ARG2 ", %%" _ASM_ARG2 "\n\t"
-		     "2: call vmread_error\n\t"
-		     "xor %k1, %k1\n\t"
+
+		     /*
+		      * VMREAD failed.  Push '0' for @fault, push the failing
+		      * @field, and bounce through the trampoline to preserve
+		      * volatile registers.
+		      */
+		     "push $0\n\t"
+		     "push %2\n\t"
+		     "2:call vmread_error_trampoline\n\t"
+
+		     /*
+		      * Unwind the stack.  Note, the trampoline zeros out the
+		      * memory for @fault so that the result is '0' on error.
+		      */
+		     "pop %2\n\t"
+		     "pop %1\n\t"
 		     "3:\n\t"
 
+		     /* VMREAD faulted.  As above, except push '1' for @fault. */
 		     ".pushsection .fixup, \"ax\"\n\t"
-		     "4: mov %2, %%" _ASM_ARG1 "\n\t"
-		     "mov $1, %%" _ASM_ARG2 "\n\t"
+		     "4: push $1\n\t"
+		     "push %2\n\t"
 		     "jmp 2b\n\t"
 		     ".popsection\n\t"
 		     _ASM_EXTABLE(1b, 4b)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kvm/vmx/pmu_intel.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kvm/vmx/pmu_intel.c
@@ -26,7 +26,7 @@
 	[4] = { 0x2e, 0x41, PERF_COUNT_HW_CACHE_MISSES },
 	[5] = { 0xc4, 0x00, PERF_COUNT_HW_BRANCH_INSTRUCTIONS },
 	[6] = { 0xc5, 0x00, PERF_COUNT_HW_BRANCH_MISSES },
-	[7] = { 0x00, 0x30, PERF_COUNT_HW_REF_CPU_CYCLES },
+	[7] = { 0x00, 0x03, PERF_COUNT_HW_REF_CPU_CYCLES },
 };
 
 /* mapping between fixed pmc index and intel_arch_events array */
@@ -64,10 +64,11 @@
 		reprogram_counter(pmu, bit);
 }
 
-static unsigned intel_find_arch_event(struct kvm_pmu *pmu,
-				      u8 event_select,
-				      u8 unit_mask)
+static unsigned int intel_pmc_perf_hw_id(struct kvm_pmc *pmc)
 {
+	struct kvm_pmu *pmu = pmc_to_pmu(pmc);
+	u8 event_select = pmc->eventsel & ARCH_PERFMON_EVENTSEL_EVENT;
+	u8 unit_mask = (pmc->eventsel & ARCH_PERFMON_EVENTSEL_UMASK) >> 8;
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(intel_arch_events); i++)
@@ -84,10 +85,14 @@
 
 static unsigned intel_find_fixed_event(int idx)
 {
-	if (idx >= ARRAY_SIZE(fixed_pmc_events))
+	u32 event;
+	size_t size = ARRAY_SIZE(fixed_pmc_events);
+
+	if (idx >= size)
 		return PERF_COUNT_HW_MAX;
 
-	return intel_arch_events[fixed_pmc_events[idx]].event_type;
+	event = fixed_pmc_events[array_index_nospec(idx, size)];
+	return intel_arch_events[event].event_type;
 }
 
 /* check if a PMC is enabled by comparing it with globl_ctrl bits. */
@@ -128,16 +133,20 @@
 	struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
 	bool fixed = idx & (1u << 30);
 	struct kvm_pmc *counters;
+	unsigned int num_counters;
 
 	idx &= ~(3u << 30);
-	if (!fixed && idx >= pmu->nr_arch_gp_counters)
-		return NULL;
-	if (fixed && idx >= pmu->nr_arch_fixed_counters)
+	if (fixed) {
+		counters = pmu->fixed_counters;
+		num_counters = pmu->nr_arch_fixed_counters;
+	} else {
+		counters = pmu->gp_counters;
+		num_counters = pmu->nr_arch_gp_counters;
+	}
+	if (idx >= num_counters)
 		return NULL;
-	counters = fixed ? pmu->fixed_counters : pmu->gp_counters;
 	*mask &= pmu->counter_bitmask[fixed ? KVM_PMC_FIXED : KVM_PMC_GP];
-
-	return &counters[idx];
+	return &counters[array_index_nospec(idx, num_counters)];
 }
 
 static bool intel_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr)
@@ -288,7 +297,9 @@
 
 	pmu->nr_arch_gp_counters = min_t(int, eax.split.num_counters,
 					 x86_pmu.num_counters_gp);
+	eax.split.bit_width = min_t(int, eax.split.bit_width, x86_pmu.bit_width_gp);
 	pmu->counter_bitmask[KVM_PMC_GP] = ((u64)1 << eax.split.bit_width) - 1;
+	eax.split.mask_length = min_t(int, eax.split.mask_length, x86_pmu.events_mask_len);
 	pmu->available_event_types = ~entry->ebx &
 					((1ull << eax.split.mask_length) - 1);
 
@@ -298,6 +309,8 @@
 		pmu->nr_arch_fixed_counters =
 			min_t(int, edx.split.num_counters_fixed,
 			      x86_pmu.num_counters_fixed);
+		edx.split.bit_width_fixed = min_t(int,
+			edx.split.bit_width_fixed, x86_pmu.bit_width_fixed);
 		pmu->counter_bitmask[KVM_PMC_FIXED] =
 			((u64)1 << edx.split.bit_width_fixed) - 1;
 	}
@@ -362,7 +375,7 @@
 }
 
 struct kvm_pmu_ops intel_pmu_ops = {
-	.find_arch_event = intel_find_arch_event,
+	.pmc_perf_hw_id = intel_pmc_perf_hw_id,
 	.find_fixed_event = intel_find_fixed_event,
 	.pmc_is_enabled = intel_pmc_is_enabled,
 	.pmc_idx_to_pmc = intel_pmc_idx_to_pmc,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kvm/vmx/run_flags.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kvm/vmx/run_flags.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __KVM_X86_VMX_RUN_FLAGS_H
+#define __KVM_X86_VMX_RUN_FLAGS_H
+
+#define VMX_RUN_VMRESUME	(1 << 0)
+#define VMX_RUN_SAVE_SPEC_CTRL	(1 << 1)
+
+#endif /* __KVM_X86_VMX_RUN_FLAGS_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kvm/vmx/vmenter.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kvm/vmx/vmenter.S
@@ -4,6 +4,7 @@
 #include <asm/bitsperlong.h>
 #include <asm/kvm_vcpu_regs.h>
 #include <asm/nospec-branch.h>
+#include "run_flags.h"
 
 #define WORD_SIZE (BITS_PER_LONG / 8)
 
@@ -30,73 +31,11 @@
 	.text
 
 /**
- * vmx_vmenter - VM-Enter the current loaded VMCS
- *
- * %RFLAGS.ZF:	!VMCS.LAUNCHED, i.e. controls VMLAUNCH vs. VMRESUME
- *
- * Returns:
- *	%RFLAGS.CF is set on VM-Fail Invalid
- *	%RFLAGS.ZF is set on VM-Fail Valid
- *	%RFLAGS.{CF,ZF} are cleared on VM-Success, i.e. VM-Exit
- *
- * Note that VMRESUME/VMLAUNCH fall-through and return directly if
- * they VM-Fail, whereas a successful VM-Enter + VM-Exit will jump
- * to vmx_vmexit.
- */
-ENTRY(vmx_vmenter)
-	/* EFLAGS.ZF is set if VMCS.LAUNCHED == 0 */
-	je 2f
-
-1:	vmresume
-	ret
-
-2:	vmlaunch
-	ret
-
-3:	cmpb $0, kvm_rebooting
-	je 4f
-	ret
-4:	ud2
-
-	.pushsection .fixup, "ax"
-5:	jmp 3b
-	.popsection
-
-	_ASM_EXTABLE(1b, 5b)
-	_ASM_EXTABLE(2b, 5b)
-
-ENDPROC(vmx_vmenter)
-
-/**
- * vmx_vmexit - Handle a VMX VM-Exit
- *
- * Returns:
- *	%RFLAGS.{CF,ZF} are cleared on VM-Success, i.e. VM-Exit
- *
- * This is vmx_vmenter's partner in crime.  On a VM-Exit, control will jump
- * here after hardware loads the host's state, i.e. this is the destination
- * referred to by VMCS.HOST_RIP.
- */
-ENTRY(vmx_vmexit)
-#ifdef CONFIG_RETPOLINE
-	ALTERNATIVE "jmp .Lvmexit_skip_rsb", "", X86_FEATURE_RETPOLINE
-	/* Preserve guest's RAX, it's used to stuff the RSB. */
-	push %_ASM_AX
-
-	/* IMPORTANT: Stuff the RSB immediately after VM-Exit, before RET! */
-	FILL_RETURN_BUFFER %_ASM_AX, RSB_CLEAR_LOOPS, X86_FEATURE_RETPOLINE
-
-	pop %_ASM_AX
-.Lvmexit_skip_rsb:
-#endif
-	ret
-ENDPROC(vmx_vmexit)
-
-/**
  * __vmx_vcpu_run - Run a vCPU via a transition to VMX guest mode
- * @vmx:	struct vcpu_vmx * (forwarded to vmx_update_host_rsp)
+ * @vmx:	struct vcpu_vmx *
  * @regs:	unsigned long * (to guest registers)
- * @launched:	%true if the VMCS has been launched
+ * @flags:	VMX_RUN_VMRESUME:	use VMRESUME instead of VMLAUNCH
+ *		VMX_RUN_SAVE_SPEC_CTRL: save guest SPEC_CTRL into vmx->spec_ctrl
  *
  * Returns:
  *	0 on VM-Exit, 1 on VM-Fail
@@ -115,24 +54,29 @@
 #endif
 	push %_ASM_BX
 
+	/* Save @vmx for SPEC_CTRL handling */
+	push %_ASM_ARG1
+
+	/* Save @flags for SPEC_CTRL handling */
+	push %_ASM_ARG3
+
 	/*
 	 * Save @regs, _ASM_ARG2 may be modified by vmx_update_host_rsp() and
 	 * @regs is needed after VM-Exit to save the guest's register values.
 	 */
 	push %_ASM_ARG2
 
-	/* Copy @launched to BL, _ASM_ARG3 is volatile. */
+	/* Copy @flags to BL, _ASM_ARG3 is volatile. */
 	mov %_ASM_ARG3B, %bl
 
-	/* Adjust RSP to account for the CALL to vmx_vmenter(). */
-	lea -WORD_SIZE(%_ASM_SP), %_ASM_ARG2
+	lea (%_ASM_SP), %_ASM_ARG2
 	call vmx_update_host_rsp
 
 	/* Load @regs to RAX. */
 	mov (%_ASM_SP), %_ASM_AX
 
 	/* Check if vmlaunch or vmresume is needed */
-	cmpb $0, %bl
+	testb $VMX_RUN_VMRESUME, %bl
 
 	/* Load guest registers.  Don't clobber flags. */
 	mov VCPU_RBX(%_ASM_AX), %_ASM_BX
@@ -154,11 +98,25 @@
 	/* Load guest RAX.  This kills the @regs pointer! */
 	mov VCPU_RAX(%_ASM_AX), %_ASM_AX
 
-	/* Enter guest mode */
-	call vmx_vmenter
+	/* Check EFLAGS.ZF from 'testb' above */
+	jz .Lvmlaunch
+
+/*
+ * If VMRESUME/VMLAUNCH and corresponding vmexit succeed, execution resumes at
+ * the 'vmx_vmexit' label below.
+ */
+.Lvmresume:
+	vmresume
+	jmp .Lvmfail
+
+.Lvmlaunch:
+	vmlaunch
+	jmp .Lvmfail
+
+	_ASM_EXTABLE(.Lvmresume, .Lfixup)
+	_ASM_EXTABLE(.Lvmlaunch, .Lfixup)
 
-	/* Jump on VM-Fail. */
-	jbe 2f
+SYM_INNER_LABEL(vmx_vmexit, SYM_L_GLOBAL)
 
 	/* Temporarily save guest's RAX. */
 	push %_ASM_AX
@@ -185,19 +143,21 @@
 	mov %r15, VCPU_R15(%_ASM_AX)
 #endif
 
-	/* Clear RAX to indicate VM-Exit (as opposed to VM-Fail). */
-	xor %eax, %eax
+	/* Clear return value to indicate VM-Exit (as opposed to VM-Fail). */
+	xor %ebx, %ebx
 
+.Lclear_regs:
 	/*
-	 * Clear all general purpose registers except RSP and RAX to prevent
+	 * Clear all general purpose registers except RSP and RBX to prevent
 	 * speculative use of the guest's values, even those that are reloaded
 	 * via the stack.  In theory, an L1 cache miss when restoring registers
 	 * could lead to speculative execution with the guest's values.
 	 * Zeroing XORs are dirt cheap, i.e. the extra paranoia is essentially
 	 * free.  RSP and RAX are exempt as RSP is restored by hardware during
-	 * VM-Exit and RAX is explicitly loaded with 0 or 1 to return VM-Fail.
+	 * VM-Exit and RBX is explicitly loaded with 0 or 1 to hold the return
+	 * value.
 	 */
-1:	xor %ebx, %ebx
+	xor %eax, %eax
 	xor %ecx, %ecx
 	xor %edx, %edx
 	xor %esi, %esi
@@ -216,8 +176,34 @@
 
 	/* "POP" @regs. */
 	add $WORD_SIZE, %_ASM_SP
-	pop %_ASM_BX
 
+	/*
+	 * IMPORTANT: RSB filling and SPEC_CTRL handling must be done before
+	 * the first unbalanced RET after vmexit!
+	 *
+	 * For retpoline or IBRS, RSB filling is needed to prevent poisoned RSB
+	 * entries and (in some cases) RSB underflow.
+	 *
+	 * eIBRS has its own protection against poisoned RSB, so it doesn't
+	 * need the RSB filling sequence.  But it does need to be enabled, and a
+	 * single call to retire, before the first unbalanced RET.
+         */
+
+	FILL_RETURN_BUFFER %_ASM_CX, RSB_CLEAR_LOOPS, X86_FEATURE_RSB_VMEXIT,\
+			   X86_FEATURE_RSB_VMEXIT_LITE
+
+
+	pop %_ASM_ARG2	/* @flags */
+	pop %_ASM_ARG1	/* @vmx */
+
+	call vmx_spec_ctrl_restore_host
+
+	CLEAR_BRANCH_HISTORY_VMEXIT
+
+	/* Put return value in AX */
+	mov %_ASM_BX, %_ASM_AX
+
+	pop %_ASM_BX
 #ifdef CONFIG_X86_64
 	pop %r12
 	pop %r13
@@ -230,7 +216,74 @@
 	pop %_ASM_BP
 	ret
 
-	/* VM-Fail.  Out-of-line to avoid a taken Jcc after VM-Exit. */
-2:	mov $1, %eax
-	jmp 1b
+.Lfixup:
+	cmpb $0, kvm_rebooting
+	jne .Lvmfail
+	ud2
+.Lvmfail:
+	/* VM-Fail: set return value to 1 */
+	mov $1, %_ASM_BX
+	jmp .Lclear_regs
+
 ENDPROC(__vmx_vcpu_run)
+
+
+.section .text, "ax"
+
+/**
+ * vmread_error_trampoline - Trampoline from inline asm to vmread_error()
+ * @field:	VMCS field encoding that failed
+ * @fault:	%true if the VMREAD faulted, %false if it failed
+
+ * Save and restore volatile registers across a call to vmread_error().  Note,
+ * all parameters are passed on the stack.
+ */
+ENTRY(vmread_error_trampoline)
+	push %_ASM_BP
+	mov  %_ASM_SP, %_ASM_BP
+
+	push %_ASM_AX
+	push %_ASM_CX
+	push %_ASM_DX
+#ifdef CONFIG_X86_64
+	push %rdi
+	push %rsi
+	push %r8
+	push %r9
+	push %r10
+	push %r11
+#endif
+#ifdef CONFIG_X86_64
+	/* Load @field and @fault to arg1 and arg2 respectively. */
+	mov 3*WORD_SIZE(%rbp), %_ASM_ARG2
+	mov 2*WORD_SIZE(%rbp), %_ASM_ARG1
+#else
+	/* Parameters are passed on the stack for 32-bit (see asmlinkage). */
+	push 3*WORD_SIZE(%ebp)
+	push 2*WORD_SIZE(%ebp)
+#endif
+
+	call vmread_error
+
+#ifndef CONFIG_X86_64
+	add $8, %esp
+#endif
+
+	/* Zero out @fault, which will be popped into the result register. */
+	_ASM_MOV $0, 3*WORD_SIZE(%_ASM_BP)
+
+#ifdef CONFIG_X86_64
+	pop %r11
+	pop %r10
+	pop %r9
+	pop %r8
+	pop %rsi
+	pop %rdi
+#endif
+	pop %_ASM_DX
+	pop %_ASM_CX
+	pop %_ASM_AX
+	pop %_ASM_BP
+
+	ret
+ENDPROC(vmread_error_trampoline)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kvm/vmx/vmx.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kvm/vmx/vmx.c
@@ -31,6 +31,7 @@
 #include <asm/apic.h>
 #include <asm/asm.h>
 #include <asm/cpu.h>
+#include <asm/cpu_device_id.h>
 #include <asm/debugreg.h>
 #include <asm/desc.h>
 #include <asm/fpu/internal.h>
@@ -95,7 +96,7 @@
 static bool __read_mostly fasteoi = 1;
 module_param(fasteoi, bool, S_IRUGO);
 
-static bool __read_mostly enable_apicv = 1;
+bool __read_mostly enable_apicv = 1;
 module_param(enable_apicv, bool, S_IRUGO);
 
 /*
@@ -178,9 +179,11 @@
 static unsigned int ple_window_max        = KVM_VMX_DEFAULT_PLE_WINDOW_MAX;
 module_param(ple_window_max, uint, 0444);
 
-/* Default is SYSTEM mode, 1 for host-guest mode */
+/* Default is SYSTEM mode, 1 for host-guest mode (which is BROKEN) */
 int __read_mostly pt_mode = PT_MODE_SYSTEM;
+#ifdef CONFIG_BROKEN
 module_param(pt_mode, int, S_IRUGO);
+#endif
 
 static DEFINE_STATIC_KEY_FALSE(vmx_l1d_should_flush);
 static DEFINE_STATIC_KEY_FALSE(vmx_l1d_flush_cond);
@@ -204,6 +207,9 @@
 #define L1D_CACHE_ORDER 4
 static void *vmx_l1d_flush_pages;
 
+/* Control for disabling CPU Fill buffer clear */
+static bool __read_mostly vmx_fb_clear_ctrl_available;
+
 static int vmx_setup_l1d_flush(enum vmx_l1d_flush_state l1tf)
 {
 	struct page *page;
@@ -335,6 +341,60 @@
 	return sprintf(s, "%s\n", vmentry_l1d_param[l1tf_vmx_mitigation].option);
 }
 
+static void vmx_setup_fb_clear_ctrl(void)
+{
+	u64 msr;
+
+	if (boot_cpu_has(X86_FEATURE_ARCH_CAPABILITIES) &&
+	    !boot_cpu_has_bug(X86_BUG_MDS) &&
+	    !boot_cpu_has_bug(X86_BUG_TAA)) {
+		rdmsrl(MSR_IA32_ARCH_CAPABILITIES, msr);
+		if (msr & ARCH_CAP_FB_CLEAR_CTRL)
+			vmx_fb_clear_ctrl_available = true;
+	}
+}
+
+static __always_inline void vmx_disable_fb_clear(struct vcpu_vmx *vmx)
+{
+	u64 msr;
+
+	if (!vmx->disable_fb_clear)
+		return;
+
+	msr = __rdmsr(MSR_IA32_MCU_OPT_CTRL);
+	msr |= FB_CLEAR_DIS;
+	native_wrmsrl(MSR_IA32_MCU_OPT_CTRL, msr);
+	/* Cache the MSR value to avoid reading it later */
+	vmx->msr_ia32_mcu_opt_ctrl = msr;
+}
+
+static __always_inline void vmx_enable_fb_clear(struct vcpu_vmx *vmx)
+{
+	if (!vmx->disable_fb_clear)
+		return;
+
+	vmx->msr_ia32_mcu_opt_ctrl &= ~FB_CLEAR_DIS;
+	native_wrmsrl(MSR_IA32_MCU_OPT_CTRL, vmx->msr_ia32_mcu_opt_ctrl);
+}
+
+static void vmx_update_fb_clear_dis(struct kvm_vcpu *vcpu, struct vcpu_vmx *vmx)
+{
+	vmx->disable_fb_clear = vmx_fb_clear_ctrl_available;
+
+	/*
+	 * If guest will not execute VERW, there is no need to set FB_CLEAR_DIS
+	 * at VMEntry. Skip the MSR read/write when a guest has no use case to
+	 * execute VERW.
+	 */
+	if ((vcpu->arch.arch_capabilities & ARCH_CAP_FB_CLEAR) ||
+	   ((vcpu->arch.arch_capabilities & ARCH_CAP_MDS_NO) &&
+	    (vcpu->arch.arch_capabilities & ARCH_CAP_TAA_NO) &&
+	    (vcpu->arch.arch_capabilities & ARCH_CAP_PSDP_NO) &&
+	    (vcpu->arch.arch_capabilities & ARCH_CAP_FBSDP_NO) &&
+	    (vcpu->arch.arch_capabilities & ARCH_CAP_SBDR_SSDP_NO)))
+		vmx->disable_fb_clear = false;
+}
+
 static const struct kernel_param_ops vmentry_l1d_flush_ops = {
 	.set = vmentry_l1d_flush_set,
 	.get = vmentry_l1d_flush_get,
@@ -648,43 +708,15 @@
 }
 
 #ifdef CONFIG_KEXEC_CORE
-/*
- * This bitmap is used to indicate whether the vmclear
- * operation is enabled on all cpus. All disabled by
- * default.
- */
-static cpumask_t crash_vmclear_enabled_bitmap = CPU_MASK_NONE;
-
-static inline void crash_enable_local_vmclear(int cpu)
-{
-	cpumask_set_cpu(cpu, &crash_vmclear_enabled_bitmap);
-}
-
-static inline void crash_disable_local_vmclear(int cpu)
-{
-	cpumask_clear_cpu(cpu, &crash_vmclear_enabled_bitmap);
-}
-
-static inline int crash_local_vmclear_enabled(int cpu)
-{
-	return cpumask_test_cpu(cpu, &crash_vmclear_enabled_bitmap);
-}
-
 static void crash_vmclear_local_loaded_vmcss(void)
 {
 	int cpu = raw_smp_processor_id();
 	struct loaded_vmcs *v;
 
-	if (!crash_local_vmclear_enabled(cpu))
-		return;
-
 	list_for_each_entry(v, &per_cpu(loaded_vmcss_on_cpu, cpu),
 			    loaded_vmcss_on_cpu_link)
 		vmcs_clear(v->vmcs);
 }
-#else
-static inline void crash_enable_local_vmclear(int cpu) { }
-static inline void crash_disable_local_vmclear(int cpu) { }
 #endif /* CONFIG_KEXEC_CORE */
 
 static void __loaded_vmcs_clear(void *arg)
@@ -696,19 +728,24 @@
 		return; /* vcpu migration can race with cpu offline */
 	if (per_cpu(current_vmcs, cpu) == loaded_vmcs->vmcs)
 		per_cpu(current_vmcs, cpu) = NULL;
-	crash_disable_local_vmclear(cpu);
+
+	vmcs_clear(loaded_vmcs->vmcs);
+	if (loaded_vmcs->shadow_vmcs && loaded_vmcs->launched)
+		vmcs_clear(loaded_vmcs->shadow_vmcs);
+
 	list_del(&loaded_vmcs->loaded_vmcss_on_cpu_link);
 
 	/*
-	 * we should ensure updating loaded_vmcs->loaded_vmcss_on_cpu_link
-	 * is before setting loaded_vmcs->vcpu to -1 which is done in
-	 * loaded_vmcs_init. Otherwise, other cpu can see vcpu = -1 fist
-	 * then adds the vmcs into percpu list before it is deleted.
+	 * Ensure all writes to loaded_vmcs, including deleting it from its
+	 * current percpu list, complete before setting loaded_vmcs->vcpu to
+	 * -1, otherwise a different cpu can see vcpu == -1 first and add
+	 * loaded_vmcs to its percpu list before it's deleted from this cpu's
+	 * list. Pairs with the smp_rmb() in vmx_vcpu_load_vmcs().
 	 */
 	smp_wmb();
 
-	loaded_vmcs_init(loaded_vmcs);
-	crash_enable_local_vmclear(cpu);
+	loaded_vmcs->cpu = -1;
+	loaded_vmcs->launched = 0;
 }
 
 void loaded_vmcs_clear(struct loaded_vmcs *loaded_vmcs)
@@ -808,15 +845,15 @@
 /*
  * Check if MSR is intercepted for currently loaded MSR bitmap.
  */
-static bool msr_write_intercepted(struct kvm_vcpu *vcpu, u32 msr)
+static bool msr_write_intercepted(struct vcpu_vmx *vmx, u32 msr)
 {
 	unsigned long *msr_bitmap;
 	int f = sizeof(unsigned long);
 
-	if (!cpu_has_vmx_msr_bitmap())
+	if (!(exec_controls_get(vmx) & CPU_BASED_USE_MSR_BITMAPS))
 		return true;
 
-	msr_bitmap = to_vmx(vcpu)->loaded_vmcs->msr_bitmap;
+	msr_bitmap = vmx->loaded_vmcs->msr_bitmap;
 
 	if (msr <= 0x1fff) {
 		return !!test_bit(msr, msr_bitmap + 0x800 / f);
@@ -828,6 +865,24 @@
 	return true;
 }
 
+unsigned int __vmx_vcpu_run_flags(struct vcpu_vmx *vmx)
+{
+	unsigned int flags = 0;
+
+	if (vmx->loaded_vmcs->launched)
+		flags |= VMX_RUN_VMRESUME;
+
+	/*
+	 * If writes to the SPEC_CTRL MSR aren't intercepted, the guest is free
+	 * to change it directly without causing a vmexit.  In that case read
+	 * it after vmexit and store it in vmx->spec_ctrl.
+	 */
+	if (unlikely(!msr_write_intercepted(vmx, MSR_IA32_SPEC_CTRL)))
+		flags |= VMX_RUN_SAVE_SPEC_CTRL;
+
+	return flags;
+}
+
 static void clear_atomic_switch_msr_special(struct vcpu_vmx *vmx,
 		unsigned long entry, unsigned long exit)
 {
@@ -1153,6 +1208,10 @@
 					   vmx->guest_msrs[i].mask);
 
 	}
+
+    	if (vmx->nested.need_vmcs12_to_shadow_sync)
+		nested_sync_vmcs12_to_shadow(vcpu);
+
 	if (vmx->guest_state_loaded)
 		return;
 
@@ -1309,33 +1368,44 @@
 		pi_set_on(pi_desc);
 }
 
-void vmx_vcpu_load_vmcs(struct kvm_vcpu *vcpu, int cpu)
+void vmx_vcpu_load_vmcs(struct kvm_vcpu *vcpu, int cpu,
+			struct loaded_vmcs *buddy)
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
 	bool already_loaded = vmx->loaded_vmcs->cpu == cpu;
+	struct vmcs *prev;
 
 	if (!already_loaded) {
 		loaded_vmcs_clear(vmx->loaded_vmcs);
 		local_irq_disable();
-		crash_disable_local_vmclear(cpu);
 
 		/*
-		 * Read loaded_vmcs->cpu should be before fetching
-		 * loaded_vmcs->loaded_vmcss_on_cpu_link.
-		 * See the comments in __loaded_vmcs_clear().
+		 * Ensure loaded_vmcs->cpu is read before adding loaded_vmcs to
+		 * this cpu's percpu list, otherwise it may not yet be deleted
+		 * from its previous cpu's percpu list.  Pairs with the
+		 * smb_wmb() in __loaded_vmcs_clear().
 		 */
 		smp_rmb();
 
 		list_add(&vmx->loaded_vmcs->loaded_vmcss_on_cpu_link,
 			 &per_cpu(loaded_vmcss_on_cpu, cpu));
-		crash_enable_local_vmclear(cpu);
 		local_irq_enable();
 	}
 
-	if (per_cpu(current_vmcs, cpu) != vmx->loaded_vmcs->vmcs) {
+	prev = per_cpu(current_vmcs, cpu);
+	if (prev != vmx->loaded_vmcs->vmcs) {
 		per_cpu(current_vmcs, cpu) = vmx->loaded_vmcs->vmcs;
 		vmcs_load(vmx->loaded_vmcs->vmcs);
-		indirect_branch_prediction_barrier();
+
+		/*
+		 * No indirect branch prediction barrier needed when switching
+		 * the active VMCS within a vCPU, unless IBRS is advertised to
+		 * the vCPU.  To minimize the number of IBPBs executed, KVM
+		 * performs IBPB on nested VM-Exit (a single nested transition
+		 * may switch the active VMCS multiple times).
+		 */
+		if (!buddy || WARN_ON_ONCE(buddy->vmcs != prev))
+			indirect_branch_prediction_barrier();
 	}
 
 	if (!already_loaded) {
@@ -1380,11 +1450,10 @@
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
 
-	vmx_vcpu_load_vmcs(vcpu, cpu);
+	vmx_vcpu_load_vmcs(vcpu, cpu, NULL);
 
 	vmx_vcpu_pi_load(vcpu, cpu);
 
-	vmx->host_pkru = read_pkru();
 	vmx->host_debugctlmsr = get_debugctlmsr();
 }
 
@@ -1552,7 +1621,7 @@
 
 static int skip_emulated_instruction(struct kvm_vcpu *vcpu)
 {
-	unsigned long rip;
+	unsigned long rip, orig_rip;
 
 	/*
 	 * Using VMCS.VM_EXIT_INSTRUCTION_LEN on EPT misconfig depends on
@@ -1564,8 +1633,17 @@
 	 */
 	if (!static_cpu_has(X86_FEATURE_HYPERVISOR) ||
 	    to_vmx(vcpu)->exit_reason != EXIT_REASON_EPT_MISCONFIG) {
-		rip = kvm_rip_read(vcpu);
-		rip += vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
+		orig_rip = kvm_rip_read(vcpu);
+		rip = orig_rip + vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
+#ifdef CONFIG_X86_64
+		/*
+		 * We need to mask out the high 32 bits of RIP if not in 64-bit
+		 * mode, but just finding out that we are in 64-bit mode is
+		 * quite expensive.  Only do it if there was a carry.
+		 */
+		if (unlikely(((rip ^ orig_rip) >> 31) == 3) && !is_64_bit_mode(vcpu))
+			rip = (u32)rip;
+#endif
 		kvm_rip_write(vcpu, rip);
 	} else {
 		if (!kvm_emulate_instruction(vcpu, EMULTYPE_SKIP))
@@ -1602,7 +1680,17 @@
 	kvm_deliver_exception_payload(vcpu);
 
 	if (has_error_code) {
-		vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
+		/*
+		 * Despite the error code being architecturally defined as 32
+		 * bits, and the VMCS field being 32 bits, Intel CPUs and thus
+		 * VMX don't actually supporting setting bits 31:16.  Hardware
+		 * will (should) never provide a bogus error code, but AMD CPUs
+		 * do generate error codes with bits 31:16 set, and so KVM's
+		 * ABI lets userspace shove in arbitrary 32-bit values.  Drop
+		 * the upper bits to avoid VM-Fail, losing information that
+		 * does't really exist is preferable to killing the VM.
+		 */
+		vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, (u16)error_code);
 		intr_info |= INTR_INFO_DELIVER_CODE_MASK;
 	}
 
@@ -1696,7 +1784,7 @@
 	struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
 
 	if (is_guest_mode(vcpu) &&
-	    (vmcs12->cpu_based_vm_exec_control & CPU_BASED_USE_TSC_OFFSETING))
+	    (vmcs12->cpu_based_vm_exec_control & CPU_BASED_USE_TSC_OFFSETTING))
 		return vcpu->arch.tsc_offset - vmcs12->tsc_offset;
 
 	return vcpu->arch.tsc_offset;
@@ -1714,7 +1802,7 @@
 	 * to the newly set TSC to get L2's TSC.
 	 */
 	if (is_guest_mode(vcpu) &&
-	    (vmcs12->cpu_based_vm_exec_control & CPU_BASED_USE_TSC_OFFSETING))
+	    (vmcs12->cpu_based_vm_exec_control & CPU_BASED_USE_TSC_OFFSETTING))
 		g_tsc_offset = vmcs12->tsc_offset;
 
 	trace_kvm_write_tsc_offset(vcpu->vcpu_id,
@@ -1790,7 +1878,7 @@
 		break;
 	case MSR_IA32_SPEC_CTRL:
 		if (!msr_info->host_initiated &&
-		    !guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL))
+		    !guest_has_spec_ctrl_msr(vcpu))
 			return 1;
 
 		msr_info->data = to_vmx(vcpu)->spec_ctrl;
@@ -1973,15 +2061,13 @@
 		break;
 	case MSR_IA32_SPEC_CTRL:
 		if (!msr_info->host_initiated &&
-		    !guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL))
+		    !guest_has_spec_ctrl_msr(vcpu))
 			return 1;
 
-		/* The STIBP bit doesn't fault even if it's not advertised */
-		if (data & ~(SPEC_CTRL_IBRS | SPEC_CTRL_STIBP | SPEC_CTRL_SSBD))
+		if (kvm_spec_ctrl_test_value(data))
 			return 1;
 
 		vmx->spec_ctrl = data;
-
 		if (!data)
 			break;
 
@@ -2003,12 +2089,13 @@
 		break;
 	case MSR_IA32_PRED_CMD:
 		if (!msr_info->host_initiated &&
-		    !guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL))
+		    !guest_has_pred_cmd_msr(vcpu))
 			return 1;
 
 		if (data & ~PRED_CMD_IBPB)
 			return 1;
-
+		if (!boot_cpu_has(X86_FEATURE_IBPB))
+			return 1;
 		if (!data)
 			break;
 
@@ -2140,6 +2227,8 @@
 			(index >= 2 * intel_pt_validate_cap(vmx->pt_desc.caps,
 					PT_CAP_num_address_ranges)))
 			return 1;
+		if (is_noncanonical_address(data, vcpu))
+			return 1;
 		if (index % 2)
 			vmx->pt_desc.guest.addr_b[index / 2] = data;
 		else
@@ -2168,9 +2257,13 @@
 			}
 			break;
 		}
-		ret = kvm_set_msr_common(vcpu, msr_info);
+			ret = kvm_set_msr_common(vcpu, msr_info);
 	}
 
+	/* FB_CLEAR may have changed, also update the FB_CLEAR_DIS behavior */
+	if (msr_index == MSR_IA32_ARCH_CAPABILITIES)
+		vmx_update_fb_clear_dis(vcpu, vmx);
+
 	return ret;
 }
 
@@ -2250,21 +2343,6 @@
 	    !hv_get_vp_assist_page(cpu))
 		return -EFAULT;
 
-	INIT_LIST_HEAD(&per_cpu(loaded_vmcss_on_cpu, cpu));
-	INIT_LIST_HEAD(&per_cpu(blocked_vcpu_on_cpu, cpu));
-	spin_lock_init(&per_cpu(blocked_vcpu_on_cpu_lock, cpu));
-
-	/*
-	 * Now we can enable the vmclear operation in kdump
-	 * since the loaded_vmcss_on_cpu list on this cpu
-	 * has been initialized.
-	 *
-	 * Though the cpu is not in VMX operation now, there
-	 * is no problem to enable the vmclear operation
-	 * for the loaded_vmcss_on_cpu list is empty!
-	 */
-	crash_enable_local_vmclear(cpu);
-
 	rdmsrl(MSR_IA32_FEATURE_CONTROL, old);
 
 	test_bits = FEATURE_CONTROL_LOCKED;
@@ -2351,7 +2429,7 @@
 	      CPU_BASED_CR3_STORE_EXITING |
 	      CPU_BASED_UNCOND_IO_EXITING |
 	      CPU_BASED_MOV_DR_EXITING |
-	      CPU_BASED_USE_TSC_OFFSETING |
+	      CPU_BASED_USE_TSC_OFFSETTING |
 	      CPU_BASED_MWAIT_EXITING |
 	      CPU_BASED_MONITOR_EXITING |
 	      CPU_BASED_INVLPG_EXITING |
@@ -2521,8 +2599,10 @@
 	vmcs_conf->vmexit_ctrl         = _vmexit_control;
 	vmcs_conf->vmentry_ctrl        = _vmentry_control;
 
-	if (static_branch_unlikely(&enable_evmcs))
+#if IS_ENABLED(CONFIG_HYPERV)
+	if (enlightened_vmcs)
 		evmcs_sanitize_exec_ctrls(vmcs_conf);
+#endif
 
 	return 0;
 }
@@ -2973,6 +3053,9 @@
 
 static int get_ept_level(struct kvm_vcpu *vcpu)
 {
+	/* Nested EPT currently only supports 4-level walks. */
+	if (is_guest_mode(vcpu) && nested_cpu_has_ept(get_vmcs12(vcpu)))
+		return 4;
 	if (cpu_has_vmx_ept_5levels() && (cpuid_maxphyaddr(vcpu) > 48))
 		return 5;
 	return 4;
@@ -2995,6 +3078,7 @@
 void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
 {
 	struct kvm *kvm = vcpu->kvm;
+	bool update_guest_cr3 = true;
 	unsigned long guest_cr3;
 	u64 eptp;
 
@@ -3011,15 +3095,18 @@
 			spin_unlock(&to_kvm_vmx(kvm)->ept_pointer_lock);
 		}
 
-		if (enable_unrestricted_guest || is_paging(vcpu) ||
-		    is_guest_mode(vcpu))
+		/* Loading vmcs02.GUEST_CR3 is handled by nested VM-Enter. */
+		if (is_guest_mode(vcpu))
+			update_guest_cr3 = false;
+		else if (enable_unrestricted_guest || is_paging(vcpu))
 			guest_cr3 = kvm_read_cr3(vcpu);
 		else
 			guest_cr3 = to_kvm_vmx(kvm)->ept_identity_map_addr;
 		ept_load_pdptrs(vcpu);
 	}
 
-	vmcs_writel(GUEST_CR3, guest_cr3);
+	if (update_guest_cr3)
+		vmcs_writel(GUEST_CR3, guest_cr3);
 }
 
 int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
@@ -3160,18 +3247,15 @@
 {
 	u32 ar;
 
-	if (var->unusable || !var->present)
-		ar = 1 << 16;
-	else {
-		ar = var->type & 15;
-		ar |= (var->s & 1) << 4;
-		ar |= (var->dpl & 3) << 5;
-		ar |= (var->present & 1) << 7;
-		ar |= (var->avl & 1) << 12;
-		ar |= (var->l & 1) << 13;
-		ar |= (var->db & 1) << 14;
-		ar |= (var->g & 1) << 15;
-	}
+	ar = var->type & 15;
+	ar |= (var->s & 1) << 4;
+	ar |= (var->dpl & 3) << 5;
+	ar |= (var->present & 1) << 7;
+	ar |= (var->avl & 1) << 12;
+	ar |= (var->l & 1) << 13;
+	ar |= (var->db & 1) << 14;
+	ar |= (var->g & 1) << 15;
+	ar |= (var->unusable || !var->present) << 16;
 
 	return ar;
 }
@@ -3844,24 +3928,29 @@
  * 2. If target vcpu isn't running(root mode), kick it to pick up the
  * interrupt from PIR in next vmentry.
  */
-static void vmx_deliver_posted_interrupt(struct kvm_vcpu *vcpu, int vector)
+static int vmx_deliver_posted_interrupt(struct kvm_vcpu *vcpu, int vector)
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
 	int r;
 
 	r = vmx_deliver_nested_posted_interrupt(vcpu, vector);
 	if (!r)
-		return;
+		return 0;
+
+	if (!vcpu->arch.apicv_active)
+		return -1;
 
 	if (pi_test_and_set_pir(vector, &vmx->pi_desc))
-		return;
+		return 0;
 
 	/* If a previous notification has sent the IPI, nothing to do.  */
 	if (pi_test_and_set_on(&vmx->pi_desc))
-		return;
+		return 0;
 
 	if (!kvm_vcpu_trigger_posted_interrupt(vcpu, false))
 		kvm_vcpu_kick(vcpu);
+
+	return 0;
 }
 
 /*
@@ -3929,6 +4018,8 @@
 
 void set_cr4_guest_host_mask(struct vcpu_vmx *vmx)
 {
+	BUILD_BUG_ON(KVM_CR4_GUEST_OWNED_BITS & ~KVM_POSSIBLE_CR4_GUEST_BITS);
+
 	vmx->vcpu.arch.cr4_guest_owned_bits = KVM_CR4_GUEST_OWNED_BITS;
 	if (enable_ept)
 		vmx->vcpu.arch.cr4_guest_owned_bits |= X86_CR4_PGE;
@@ -4364,11 +4455,13 @@
 	vpid_sync_context(vmx->vpid);
 	if (init_event)
 		vmx_clear_hlt(vcpu);
+
+	vmx_update_fb_clear_dis(vcpu, vmx);
 }
 
 static void enable_irq_window(struct kvm_vcpu *vcpu)
 {
-	exec_controls_setbit(to_vmx(vcpu), CPU_BASED_VIRTUAL_INTR_PENDING);
+	exec_controls_setbit(to_vmx(vcpu), CPU_BASED_INTR_WINDOW_EXITING);
 }
 
 static void enable_nmi_window(struct kvm_vcpu *vcpu)
@@ -4379,7 +4472,7 @@
 		return;
 	}
 
-	exec_controls_setbit(to_vmx(vcpu), CPU_BASED_VIRTUAL_NMI_PENDING);
+	exec_controls_setbit(to_vmx(vcpu), CPU_BASED_NMI_WINDOW_EXITING);
 }
 
 static void vmx_inject_irq(struct kvm_vcpu *vcpu)
@@ -4491,8 +4584,13 @@
 
 static int vmx_interrupt_allowed(struct kvm_vcpu *vcpu)
 {
-	return (!to_vmx(vcpu)->nested.nested_run_pending &&
-		vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF) &&
+	if (to_vmx(vcpu)->nested.nested_run_pending)
+		return false;
+
+	if (is_guest_mode(vcpu) && nested_exit_on_intr(vcpu))
+		return true;
+
+	return (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF) &&
 		!(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) &
 			(GUEST_INTR_STATE_STI | GUEST_INTR_STATE_MOV_SS));
 }
@@ -4586,7 +4684,7 @@
  */
 static void kvm_machine_check(void)
 {
-#if defined(CONFIG_X86_MCE) && defined(CONFIG_X86_64)
+#if defined(CONFIG_X86_MCE)
 	struct pt_regs regs = {
 		.cs = 3, /* Fake ring 3 no matter what the guest ran on */
 		.flags = X86_EFLAGS_IF,
@@ -4707,7 +4805,7 @@
 	return 0;
 }
 
-static int handle_external_interrupt(struct kvm_vcpu *vcpu)
+static __always_inline int handle_external_interrupt(struct kvm_vcpu *vcpu)
 {
 	++vcpu->stat.irq_exits;
 	return 1;
@@ -4979,21 +5077,6 @@
 	vmcs_writel(GUEST_DR7, val);
 }
 
-static int handle_cpuid(struct kvm_vcpu *vcpu)
-{
-	return kvm_emulate_cpuid(vcpu);
-}
-
-static int handle_rdmsr(struct kvm_vcpu *vcpu)
-{
-	return kvm_emulate_rdmsr(vcpu);
-}
-
-static int handle_wrmsr(struct kvm_vcpu *vcpu)
-{
-	return kvm_emulate_wrmsr(vcpu);
-}
-
 static int handle_tpr_below_threshold(struct kvm_vcpu *vcpu)
 {
 	kvm_apic_update_ppr(vcpu);
@@ -5002,7 +5085,7 @@
 
 static int handle_interrupt_window(struct kvm_vcpu *vcpu)
 {
-	exec_controls_clearbit(to_vmx(vcpu), CPU_BASED_VIRTUAL_INTR_PENDING);
+	exec_controls_clearbit(to_vmx(vcpu), CPU_BASED_INTR_WINDOW_EXITING);
 
 	kvm_make_request(KVM_REQ_EVENT, vcpu);
 
@@ -5010,11 +5093,6 @@
 	return 1;
 }
 
-static int handle_halt(struct kvm_vcpu *vcpu)
-{
-	return kvm_emulate_halt(vcpu);
-}
-
 static int handle_vmcall(struct kvm_vcpu *vcpu)
 {
 	return kvm_emulate_hypercall(vcpu);
@@ -5220,7 +5298,7 @@
 static int handle_nmi_window(struct kvm_vcpu *vcpu)
 {
 	WARN_ON_ONCE(!enable_vnmi);
-	exec_controls_clearbit(to_vmx(vcpu), CPU_BASED_VIRTUAL_NMI_PENDING);
+	exec_controls_clearbit(to_vmx(vcpu), CPU_BASED_NMI_WINDOW_EXITING);
 	++vcpu->stat.nmi_window_exits;
 	kvm_make_request(KVM_REQ_EVENT, vcpu);
 
@@ -5241,7 +5319,7 @@
 	WARN_ON_ONCE(vmx->emulation_required && vmx->nested.nested_run_pending);
 
 	intr_window_requested = exec_controls_get(vmx) &
-				CPU_BASED_VIRTUAL_INTR_PENDING;
+				CPU_BASED_INTR_WINDOW_EXITING;
 
 	while (vmx->emulation_required && count-- != 0) {
 		if (intr_window_requested && vmx_interrupt_allowed(vcpu))
@@ -5562,11 +5640,11 @@
 	[EXIT_REASON_IO_INSTRUCTION]          = handle_io,
 	[EXIT_REASON_CR_ACCESS]               = handle_cr,
 	[EXIT_REASON_DR_ACCESS]               = handle_dr,
-	[EXIT_REASON_CPUID]                   = handle_cpuid,
-	[EXIT_REASON_MSR_READ]                = handle_rdmsr,
-	[EXIT_REASON_MSR_WRITE]               = handle_wrmsr,
-	[EXIT_REASON_PENDING_INTERRUPT]       = handle_interrupt_window,
-	[EXIT_REASON_HLT]                     = handle_halt,
+	[EXIT_REASON_CPUID]                   = kvm_emulate_cpuid,
+	[EXIT_REASON_MSR_READ]                = kvm_emulate_rdmsr,
+	[EXIT_REASON_MSR_WRITE]               = kvm_emulate_wrmsr,
+	[EXIT_REASON_INTERRUPT_WINDOW]        = handle_interrupt_window,
+	[EXIT_REASON_HLT]                     = kvm_emulate_halt,
 	[EXIT_REASON_INVD]		      = handle_invd,
 	[EXIT_REASON_INVLPG]		      = handle_invlpg,
 	[EXIT_REASON_RDPMC]                   = handle_rdpmc,
@@ -5904,6 +5982,7 @@
 			(exit_reason != EXIT_REASON_EXCEPTION_NMI &&
 			exit_reason != EXIT_REASON_EPT_VIOLATION &&
 			exit_reason != EXIT_REASON_PML_FULL &&
+			exit_reason != EXIT_REASON_APIC_ACCESS &&
 			exit_reason != EXIT_REASON_TASK_SWITCH)) {
 		vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
 		vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_DELIVERY_EV;
@@ -5939,9 +6018,23 @@
 	}
 
 	if (exit_reason < kvm_vmx_max_exit_handlers
-	    && kvm_vmx_exit_handlers[exit_reason])
+	    && kvm_vmx_exit_handlers[exit_reason]) {
+#ifdef CONFIG_RETPOLINE
+		if (exit_reason == EXIT_REASON_MSR_WRITE)
+			return kvm_emulate_wrmsr(vcpu);
+		else if (exit_reason == EXIT_REASON_PREEMPTION_TIMER)
+			return handle_preemption_timer(vcpu);
+		else if (exit_reason == EXIT_REASON_INTERRUPT_WINDOW)
+			return handle_interrupt_window(vcpu);
+		else if (exit_reason == EXIT_REASON_EXTERNAL_INTERRUPT)
+			return handle_external_interrupt(vcpu);
+		else if (exit_reason == EXIT_REASON_HLT)
+			return kvm_emulate_halt(vcpu);
+		else if (exit_reason == EXIT_REASON_EPT_MISCONFIG)
+			return handle_ept_misconfig(vcpu);
+#endif
 		return kvm_vmx_exit_handlers[exit_reason](vcpu);
-	else {
+	} else {
 		vcpu_unimpl(vcpu, "vmx: unexpected exit reason 0x%x\n",
 				exit_reason);
 		dump_vmcs();
@@ -6269,6 +6362,7 @@
 	);
 
 	kvm_after_interrupt(vcpu);
+	vcpu->arch.at_instruction_boundary = true;
 }
 STACK_FRAME_NON_STANDARD(handle_external_interrupt_irqoff);
 
@@ -6438,23 +6532,6 @@
 					msrs[i].host, false);
 }
 
-static void atomic_switch_umwait_control_msr(struct vcpu_vmx *vmx)
-{
-	u32 host_umwait_control;
-
-	if (!vmx_has_waitpkg(vmx))
-		return;
-
-	host_umwait_control = get_umwait_control_msr();
-
-	if (vmx->msr_ia32_umwait_control != host_umwait_control)
-		add_atomic_switch_msr(vmx, MSR_IA32_UMWAIT_CONTROL,
-			vmx->msr_ia32_umwait_control,
-			host_umwait_control, false);
-	else
-		clear_atomic_switch_msr(vmx, MSR_IA32_UMWAIT_CONTROL);
-}
-
 static void vmx_update_hv_timer(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -6489,7 +6566,30 @@
 	}
 }
 
-bool __vmx_vcpu_run(struct vcpu_vmx *vmx, unsigned long *regs, bool launched);
+void noinstr vmx_spec_ctrl_restore_host(struct vcpu_vmx *vmx,
+					unsigned int flags)
+{
+	u64 hostval = this_cpu_read(x86_spec_ctrl_current);
+
+	if (!cpu_feature_enabled(X86_FEATURE_MSR_SPEC_CTRL))
+		return;
+
+	if (flags & VMX_RUN_SAVE_SPEC_CTRL)
+		vmx->spec_ctrl = __rdmsr(MSR_IA32_SPEC_CTRL);
+
+	/*
+	 * If the guest/host SPEC_CTRL values differ, restore the host value.
+	 *
+	 * For legacy IBRS, the IBRS bit always needs to be written after
+	 * transitioning from a less privileged predictor mode, regardless of
+	 * whether the guest/host values differ.
+	 */
+	if (cpu_feature_enabled(X86_FEATURE_KERNEL_IBRS) ||
+	    vmx->spec_ctrl != hostval)
+		native_wrmsrl(MSR_IA32_SPEC_CTRL, hostval);
+
+	barrier_nospec();
+}
 
 static void vmx_vcpu_run(struct kvm_vcpu *vcpu)
 {
@@ -6511,8 +6611,11 @@
 		vmcs_write32(PLE_WINDOW, vmx->ple_window);
 	}
 
-	if (vmx->nested.need_vmcs12_to_shadow_sync)
-		nested_sync_vmcs12_to_shadow(vcpu);
+	/*
+	 * We did this in prepare_switch_to_guest, because it needs to
+	 * be within srcu_read_lock.
+	 */
+	WARN_ON_ONCE(vmx->nested.need_vmcs12_to_shadow_sync);
 
 	if (test_bit(VCPU_REGS_RSP, (unsigned long *)&vcpu->arch.regs_dirty))
 		vmcs_writel(GUEST_RSP, vcpu->arch.regs[VCPU_REGS_RSP]);
@@ -6541,15 +6644,9 @@
 
 	kvm_load_guest_xcr0(vcpu);
 
-	if (static_cpu_has(X86_FEATURE_PKU) &&
-	    kvm_read_cr4_bits(vcpu, X86_CR4_PKE) &&
-	    vcpu->arch.pkru != vmx->host_pkru)
-		__write_pkru(vcpu->arch.pkru);
-
 	pt_guest_enter(vmx);
 
 	atomic_switch_perf_msrs(vmx);
-	atomic_switch_umwait_control_msr(vmx);
 
 	if (enable_preemption_timer)
 		vmx_update_hv_timer(vcpu);
@@ -6571,34 +6668,21 @@
 		vmx_l1d_flush(vcpu);
 	else if (static_branch_unlikely(&mds_user_clear))
 		mds_clear_cpu_buffers();
+	else if (static_branch_unlikely(&mmio_stale_data_clear) &&
+		 kvm_arch_has_assigned_device(vcpu->kvm))
+		mds_clear_cpu_buffers();
+
+	vmx_disable_fb_clear(vmx);
 
 	if (vcpu->arch.cr2 != read_cr2())
 		write_cr2(vcpu->arch.cr2);
 
 	vmx->fail = __vmx_vcpu_run(vmx, (unsigned long *)&vcpu->arch.regs,
-				   vmx->loaded_vmcs->launched);
+				   __vmx_vcpu_run_flags(vmx));
 
 	vcpu->arch.cr2 = read_cr2();
 
-	/*
-	 * We do not use IBRS in the kernel. If this vCPU has used the
-	 * SPEC_CTRL MSR it may have left it on; save the value and
-	 * turn it off. This is much more efficient than blindly adding
-	 * it to the atomic save/restore list. Especially as the former
-	 * (Saving guest MSRs on vmexit) doesn't even exist in KVM.
-	 *
-	 * For non-nested case:
-	 * If the L01 MSR bitmap does not intercept the MSR, then we need to
-	 * save it.
-	 *
-	 * For nested case:
-	 * If the L02 MSR bitmap does not intercept the MSR, then we need to
-	 * save it.
-	 */
-	if (unlikely(!msr_write_intercepted(vcpu, MSR_IA32_SPEC_CTRL)))
-		vmx->spec_ctrl = native_read_msr(MSR_IA32_SPEC_CTRL);
-
-	x86_spec_ctrl_restore_host(vmx->spec_ctrl, 0);
+	vmx_enable_fb_clear(vmx);
 
 	/* All fields are clean at this point */
 	if (static_branch_unlikely(&enable_evmcs))
@@ -6634,18 +6718,6 @@
 
 	pt_guest_exit(vmx);
 
-	/*
-	 * eager fpu is enabled if PKEY is supported and CR4 is switched
-	 * back on host, so it is safe to read guest PKRU from current
-	 * XSAVE.
-	 */
-	if (static_cpu_has(X86_FEATURE_PKU) &&
-	    kvm_read_cr4_bits(vcpu, X86_CR4_PKE)) {
-		vcpu->arch.pkru = rdpkru();
-		if (vcpu->arch.pkru != vmx->host_pkru)
-			__write_pkru(vmx->host_pkru);
-	}
-
 	kvm_put_guest_xcr0(vcpu);
 
 	vmx->nested.nested_run_pending = 0;
@@ -6670,6 +6742,10 @@
 	struct kvm_vmx *kvm_vmx = __vmalloc(sizeof(struct kvm_vmx),
 					    GFP_KERNEL_ACCOUNT | __GFP_ZERO,
 					    PAGE_KERNEL);
+
+	if (!kvm_vmx)
+		return NULL;
+
 	return &kvm_vmx->kvm;
 }
 
@@ -6793,8 +6869,7 @@
 
 	if (nested)
 		nested_vmx_setup_ctls_msrs(&vmx->nested.msrs,
-					   vmx_capability.ept,
-					   kvm_vcpu_apicv_active(&vmx->vcpu));
+					   vmx_capability.ept);
 	else
 		memset(&vmx->nested.msrs, 0, sizeof(vmx->nested.msrs));
 
@@ -6876,8 +6951,7 @@
 	if (setup_vmcs_config(&vmcs_conf, &vmx_cap) < 0)
 		return -EIO;
 	if (nested)
-		nested_vmx_setup_ctls_msrs(&vmcs_conf.nested, vmx_cap.ept,
-					   enable_apicv);
+		nested_vmx_setup_ctls_msrs(&vmcs_conf.nested, vmx_cap.ept);
 	if (memcmp(&vmcs_config, &vmcs_conf, sizeof(struct vmcs_config)) != 0) {
 		printk(KERN_ERR "kvm: CPU %d feature inconsistency!\n",
 				smp_processor_id());
@@ -7123,6 +7197,40 @@
 	to_vmx(vcpu)->req_immediate_exit = true;
 }
 
+static int vmx_check_intercept_io(struct kvm_vcpu *vcpu,
+				  struct x86_instruction_info *info)
+{
+	struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+	unsigned short port;
+	bool intercept;
+	int size;
+
+	if (info->intercept == x86_intercept_in ||
+	    info->intercept == x86_intercept_ins) {
+		port = info->src_val;
+		size = info->dst_bytes;
+	} else {
+		port = info->dst_val;
+		size = info->src_bytes;
+	}
+
+	/*
+	 * If the 'use IO bitmaps' VM-execution control is 0, IO instruction
+	 * VM-exits depend on the 'unconditional IO exiting' VM-execution
+	 * control.
+	 *
+	 * Otherwise, IO instruction VM-exits are controlled by the IO bitmaps.
+	 */
+	if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
+		intercept = nested_cpu_has(vmcs12,
+					   CPU_BASED_UNCOND_IO_EXITING);
+	else
+		intercept = nested_vmx_check_io_bitmaps(vcpu, port, size);
+
+	/* FIXME: produce nested vmexit and return X86EMUL_INTERCEPTED.  */
+	return intercept ? X86EMUL_UNHANDLEABLE : X86EMUL_CONTINUE;
+}
+
 static int vmx_check_intercept(struct kvm_vcpu *vcpu,
 			       struct x86_instruction_info *info,
 			       enum x86_intercept_stage stage)
@@ -7130,19 +7238,60 @@
 	struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
 	struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
 
+	switch (info->intercept) {
 	/*
 	 * RDPID causes #UD if disabled through secondary execution controls.
 	 * Because it is marked as EmulateOnUD, we need to intercept it here.
 	 */
-	if (info->intercept == x86_intercept_rdtscp &&
-	    !nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDTSCP)) {
-		ctxt->exception.vector = UD_VECTOR;
-		ctxt->exception.error_code_valid = false;
-		return X86EMUL_PROPAGATE_FAULT;
-	}
+	case x86_intercept_rdtscp:
+		if (!nested_cpu_has2(vmcs12, SECONDARY_EXEC_RDTSCP)) {
+			ctxt->exception.vector = UD_VECTOR;
+			ctxt->exception.error_code_valid = false;
+			return X86EMUL_PROPAGATE_FAULT;
+		}
+		break;
+
+	case x86_intercept_in:
+	case x86_intercept_ins:
+	case x86_intercept_out:
+	case x86_intercept_outs:
+		return vmx_check_intercept_io(vcpu, info);
+
+	case x86_intercept_lgdt:
+	case x86_intercept_lidt:
+	case x86_intercept_lldt:
+	case x86_intercept_ltr:
+	case x86_intercept_sgdt:
+	case x86_intercept_sidt:
+	case x86_intercept_sldt:
+	case x86_intercept_str:
+		if (!nested_cpu_has2(vmcs12, SECONDARY_EXEC_DESC))
+			return X86EMUL_CONTINUE;
+
+		/* FIXME: produce nested vmexit and return X86EMUL_INTERCEPTED.  */
+		break;
+
+	case x86_intercept_pause:
+		/*
+		 * PAUSE is a single-byte NOP with a REPE prefix, i.e. collides
+		 * with vanilla NOPs in the emulator.  Apply the interception
+		 * check only to actual PAUSE instructions.  Don't check
+		 * PAUSE-loop-exiting, software can't expect a given PAUSE to
+		 * exit, i.e. KVM is within its rights to allow L2 to execute
+		 * the PAUSE.
+		 */
+		if ((info->rep_prefix != REPE_PREFIX) ||
+		    !nested_cpu_has2(vmcs12, CPU_BASED_PAUSE_EXITING))
+			return X86EMUL_CONTINUE;
+
+		break;
 
 	/* TODO: check more intercepts... */
-	return X86EMUL_CONTINUE;
+	default:
+		break;
+	}
+
+	return X86EMUL_UNHANDLEABLE;
 }
 
 #ifdef CONFIG_X86_64
@@ -7238,11 +7387,11 @@
 	kvm_flush_pml_buffers(kvm);
 }
 
-static int vmx_write_pml_buffer(struct kvm_vcpu *vcpu)
+static int vmx_write_pml_buffer(struct kvm_vcpu *vcpu, gpa_t gpa)
 {
 	struct vmcs12 *vmcs12;
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
-	gpa_t gpa, dst;
+	gpa_t dst;
 
 	if (is_guest_mode(vcpu)) {
 		WARN_ON_ONCE(vmx->nested.pml_full);
@@ -7261,7 +7410,7 @@
 			return 1;
 		}
 
-		gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS) & ~0xFFFull;
+		gpa &= ~0xFFFull;
 		dst = vmcs12->pml_address + sizeof(u64) * vmcs12->guest_pml_index;
 
 		if (kvm_write_guest_page(vcpu->kvm, gpa_to_gfn(dst), &gpa,
@@ -7727,7 +7876,7 @@
 
 	if (nested) {
 		nested_vmx_setup_ctls_msrs(&vmcs_config.nested,
-					   vmx_capability.ept, enable_apicv);
+					   vmx_capability.ept);
 
 		r = nested_vmx_hardware_setup(kvm_vmx_exit_handlers);
 		if (r)
@@ -7861,6 +8010,7 @@
 	.xsaves_supported = vmx_xsaves_supported,
 	.umip_emulated = vmx_umip_emulated,
 	.pt_supported = vmx_pt_supported,
+	.pku_supported = vmx_pku_supported,
 
 	.request_immediate_exit = vmx_request_immediate_exit,
 
@@ -7949,7 +8099,7 @@
 
 static int __init vmx_init(void)
 {
-	int r;
+	int r, cpu;
 
 #if IS_ENABLED(CONFIG_HYPERV)
 	/*
@@ -8003,6 +8153,15 @@
 		return r;
 	}
 
+	vmx_setup_fb_clear_ctrl();
+
+	for_each_possible_cpu(cpu) {
+		INIT_LIST_HEAD(&per_cpu(loaded_vmcss_on_cpu, cpu));
+
+		INIT_LIST_HEAD(&per_cpu(blocked_vcpu_on_cpu, cpu));
+		spin_lock_init(&per_cpu(blocked_vcpu_on_cpu_lock, cpu));
+	}
+
 #ifdef CONFIG_KEXEC_CORE
 	rcu_assign_pointer(crash_vmclear_loaded_vmcss,
 			   crash_vmclear_local_loaded_vmcss);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kvm/vmx/vmx.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kvm/vmx/vmx.h
@@ -10,12 +10,11 @@
 #include "capabilities.h"
 #include "ops.h"
 #include "vmcs.h"
+#include "run_flags.h"
 
 extern const u32 vmx_msr_index[];
 extern u64 host_efer;
 
-extern u32 get_umwait_control_msr(void);
-
 #define MSR_TYPE_R	1
 #define MSR_TYPE_W	2
 #define MSR_TYPE_RW	3
@@ -282,8 +281,11 @@
 	u64 msr_ia32_feature_control;
 	u64 msr_ia32_feature_control_valid_bits;
 	u64 ept_pointer;
+	u64 msr_ia32_mcu_opt_ctrl;
+	bool disable_fb_clear;
 
 	struct pt_desc pt_desc;
+
 };
 
 enum ept_pointers_status {
@@ -304,7 +306,8 @@
 };
 
 bool nested_vmx_allowed(struct kvm_vcpu *vcpu);
-void vmx_vcpu_load_vmcs(struct kvm_vcpu *vcpu, int cpu);
+void vmx_vcpu_load_vmcs(struct kvm_vcpu *vcpu, int cpu,
+			struct loaded_vmcs *buddy);
 void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu);
 int allocate_vpid(void);
 void free_vpid(int vpid);
@@ -334,6 +337,10 @@
 struct shared_msr_entry *find_msr_entry(struct vcpu_vmx *vmx, u32 msr);
 void pt_update_intercept_for_msr(struct vcpu_vmx *vmx);
 void vmx_update_host_rsp(struct vcpu_vmx *vmx, unsigned long host_rsp);
+void vmx_spec_ctrl_restore_host(struct vcpu_vmx *vmx, unsigned int flags);
+unsigned int __vmx_vcpu_run_flags(struct vcpu_vmx *vmx);
+bool __vmx_vcpu_run(struct vcpu_vmx *vmx, unsigned long *regs,
+		    unsigned int flags);
 
 #define POSTED_INTR_ON  0
 #define POSTED_INTR_SN  1
@@ -513,7 +520,7 @@
 
 static inline bool vmx_has_waitpkg(struct vcpu_vmx *vmx)
 {
-	return vmx->secondary_exec_control &
+	return secondary_exec_controls_get(vmx) &
 		SECONDARY_EXEC_ENABLE_USR_WAIT_PAUSE;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kvm/x86.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kvm/x86.c
@@ -68,6 +68,7 @@
 #include <asm/mshyperv.h>
 #include <asm/hypervisor.h>
 #include <asm/intel_pt.h>
+#include <asm/emulate_prefix.h>
 #include <clocksource/hyperv_timer.h>
 
 #define CREATE_TRACE_POINTS
@@ -92,6 +93,8 @@
 static u64 __read_mostly efer_reserved_bits = ~((u64)EFER_SCE);
 #endif
 
+static u64 __read_mostly cr4_reserved_bits = CR4_RESERVED_BITS;
+
 #define VM_STAT(x, ...) offsetof(struct kvm, stat.x), KVM_STAT_VM, ## __VA_ARGS__
 #define VCPU_STAT(x, ...) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU, ## __VA_ARGS__
 
@@ -100,6 +103,7 @@
 
 static void update_cr8_intercept(struct kvm_vcpu *vcpu);
 static void process_nmi(struct kvm_vcpu *vcpu);
+static void process_smi(struct kvm_vcpu *vcpu);
 static void enter_smm(struct kvm_vcpu *vcpu);
 static void __kvm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags);
 static void store_regs(struct kvm_vcpu *vcpu);
@@ -164,6 +168,10 @@
 	u32 msrs[KVM_NR_SHARED_MSRS];
 };
 
+/* Enable/disable SMT_RSB bug mitigation */
+bool __read_mostly mitigate_smt_rsb;
+module_param(mitigate_smt_rsb, bool, 0444);
+
 struct kvm_shared_msrs {
 	struct user_return_notifier urn;
 	bool registered;
@@ -203,9 +211,10 @@
 	{ "nmi_injections", VCPU_STAT(nmi_injections) },
 	{ "req_event", VCPU_STAT(req_event) },
 	{ "l1d_flush", VCPU_STAT(l1d_flush) },
+	{ "preemption_reported", VCPU_STAT(preemption_reported) },
+	{ "preemption_other", VCPU_STAT(preemption_other) },
 	{ "mmu_shadow_zapped", VM_STAT(mmu_shadow_zapped) },
 	{ "mmu_pte_write", VM_STAT(mmu_pte_write) },
-	{ "mmu_pte_updated", VM_STAT(mmu_pte_updated) },
 	{ "mmu_pde_zapped", VM_STAT(mmu_pde_zapped) },
 	{ "mmu_flooded", VM_STAT(mmu_flooded) },
 	{ "mmu_recycled", VM_STAT(mmu_recycled) },
@@ -300,13 +309,14 @@
 	struct kvm_shared_msrs *smsr = per_cpu_ptr(shared_msrs, cpu);
 	int err;
 
-	if (((value ^ smsr->values[slot].curr) & mask) == 0)
+	value = (value & mask) | (smsr->values[slot].host & ~mask);
+	if (value == smsr->values[slot].curr)
 		return 0;
-	smsr->values[slot].curr = value;
 	err = wrmsrl_safe(shared_msrs_global.msrs[slot], value);
 	if (err)
 		return 1;
 
+	smsr->values[slot].curr = value;
 	if (!smsr->registered) {
 		smsr->urn.on_user_return = kvm_on_user_return;
 		user_return_notifier_register(&smsr->urn);
@@ -442,6 +452,14 @@
 		 * for #DB exceptions under VMX.
 		 */
 		vcpu->arch.dr6 ^= payload & DR6_RTM;
+
+		/*
+		 * The #DB payload is defined as compatible with the 'pending
+		 * debug exceptions' field under VMX, not DR6. While bit 12 is
+		 * defined in the 'pending debug exceptions' field (enabled
+		 * breakpoint), it is reserved and must be zero in DR6.
+		 */
+		vcpu->arch.dr6 &= ~BIT(12);
 		break;
 	case PF_VECTOR:
 		vcpu->arch.cr2 = payload;
@@ -464,8 +482,6 @@
 
 	if (!vcpu->arch.exception.pending && !vcpu->arch.exception.injected) {
 	queue:
-		if (has_error && !is_protmode(vcpu))
-			has_error = false;
 		if (reinject) {
 			/*
 			 * On vmentry, vcpu->arch.exception.pending is only
@@ -821,11 +837,25 @@
 			xsetbv(XCR_XFEATURE_ENABLED_MASK, vcpu->arch.xcr0);
 		vcpu->guest_xcr0_loaded = 1;
 	}
+
+	if (static_cpu_has(X86_FEATURE_PKU) &&
+	    (kvm_read_cr4_bits(vcpu, X86_CR4_PKE) ||
+	     (vcpu->arch.xcr0 & XFEATURE_MASK_PKRU)) &&
+	    vcpu->arch.pkru != vcpu->arch.host_pkru)
+		__write_pkru(vcpu->arch.pkru);
 }
 EXPORT_SYMBOL_GPL(kvm_load_guest_xcr0);
 
 void kvm_put_guest_xcr0(struct kvm_vcpu *vcpu)
 {
+	if (static_cpu_has(X86_FEATURE_PKU) &&
+	    (kvm_read_cr4_bits(vcpu, X86_CR4_PKE) ||
+	     (vcpu->arch.xcr0 & XFEATURE_MASK_PKRU))) {
+		vcpu->arch.pkru = rdpkru();
+		if (vcpu->arch.pkru != vcpu->arch.host_pkru)
+			__write_pkru(vcpu->arch.host_pkru);
+	}
+
 	if (vcpu->guest_xcr0_loaded) {
 		if (vcpu->arch.xcr0 != host_xcr0)
 			xsetbv(XCR_XFEATURE_ENABLED_MASK, host_xcr0);
@@ -885,9 +915,38 @@
 }
 EXPORT_SYMBOL_GPL(kvm_set_xcr);
 
+static u64 kvm_host_cr4_reserved_bits(struct cpuinfo_x86 *c)
+{
+	u64 reserved_bits = CR4_RESERVED_BITS;
+
+	if (!cpu_has(c, X86_FEATURE_XSAVE))
+		reserved_bits |= X86_CR4_OSXSAVE;
+
+	if (!cpu_has(c, X86_FEATURE_SMEP))
+		reserved_bits |= X86_CR4_SMEP;
+
+	if (!cpu_has(c, X86_FEATURE_SMAP))
+		reserved_bits |= X86_CR4_SMAP;
+
+	if (!cpu_has(c, X86_FEATURE_FSGSBASE))
+		reserved_bits |= X86_CR4_FSGSBASE;
+
+	if (!cpu_has(c, X86_FEATURE_PKU))
+		reserved_bits |= X86_CR4_PKE;
+
+	if (!cpu_has(c, X86_FEATURE_LA57) &&
+	    !(cpuid_ecx(0x7) & bit(X86_FEATURE_LA57)))
+		reserved_bits |= X86_CR4_LA57;
+
+	if (!cpu_has(c, X86_FEATURE_UMIP) && !kvm_x86_ops->umip_emulated())
+		reserved_bits |= X86_CR4_UMIP;
+
+	return reserved_bits;
+}
+
 static int kvm_valid_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
 {
-	if (cr4 & CR4_RESERVED_BITS)
+	if (cr4 & cr4_reserved_bits)
 		return -EINVAL;
 
 	if (!guest_cpuid_has(vcpu, X86_FEATURE_XSAVE) && (cr4 & X86_CR4_OSXSAVE))
@@ -918,7 +977,8 @@
 {
 	unsigned long old_cr4 = kvm_read_cr4(vcpu);
 	unsigned long pdptr_bits = X86_CR4_PGE | X86_CR4_PSE | X86_CR4_PAE |
-				   X86_CR4_SMEP | X86_CR4_SMAP | X86_CR4_PKE;
+				   X86_CR4_SMEP;
+	unsigned long mmu_role_bits = pdptr_bits | X86_CR4_SMAP | X86_CR4_PKE;
 
 	if (kvm_valid_cr4(vcpu, cr4))
 		return 1;
@@ -926,6 +986,8 @@
 	if (is_long_mode(vcpu)) {
 		if (!(cr4 & X86_CR4_PAE))
 			return 1;
+		if ((cr4 ^ old_cr4) & X86_CR4_LA57)
+			return 1;
 	} else if (is_paging(vcpu) && (cr4 & X86_CR4_PAE)
 		   && ((cr4 ^ old_cr4) & pdptr_bits)
 		   && !load_pdptrs(vcpu, vcpu->arch.walk_mmu,
@@ -944,7 +1006,7 @@
 	if (kvm_x86_ops->set_cr4(vcpu, cr4))
 		return 1;
 
-	if (((cr4 ^ old_cr4) & pdptr_bits) ||
+	if (((cr4 ^ old_cr4) & mmu_role_bits) ||
 	    (!(cr4 & X86_CR4_PCIDE) && (old_cr4 & X86_CR4_PCIDE)))
 		kvm_mmu_reset_context(vcpu);
 
@@ -1053,9 +1115,11 @@
 
 static int __kvm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long val)
 {
+	size_t size = ARRAY_SIZE(vcpu->arch.db);
+
 	switch (dr) {
 	case 0 ... 3:
-		vcpu->arch.db[dr] = val;
+		vcpu->arch.db[array_index_nospec(dr, size)] = val;
 		if (!(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP))
 			vcpu->arch.eff_db[dr] = val;
 		break;
@@ -1092,9 +1156,11 @@
 
 int kvm_get_dr(struct kvm_vcpu *vcpu, int dr, unsigned long *val)
 {
+	size_t size = ARRAY_SIZE(vcpu->arch.db);
+
 	switch (dr) {
 	case 0 ... 3:
-		*val = vcpu->arch.db[dr];
+		*val = vcpu->arch.db[array_index_nospec(dr, size)];
 		break;
 	case 4:
 		/* fall through */
@@ -1159,7 +1225,7 @@
 	MSR_IA32_UMWAIT_CONTROL,
 
 	MSR_ARCH_PERFMON_FIXED_CTR0, MSR_ARCH_PERFMON_FIXED_CTR1,
-	MSR_ARCH_PERFMON_FIXED_CTR0 + 2, MSR_ARCH_PERFMON_FIXED_CTR0 + 3,
+	MSR_ARCH_PERFMON_FIXED_CTR0 + 2,
 	MSR_CORE_PERF_FIXED_CTR_CTRL, MSR_CORE_PERF_GLOBAL_STATUS,
 	MSR_CORE_PERF_GLOBAL_CTRL, MSR_CORE_PERF_GLOBAL_OVF_CTRL,
 	MSR_ARCH_PERFMON_PERFCTR0, MSR_ARCH_PERFMON_PERFCTR1,
@@ -1180,6 +1246,13 @@
 	MSR_ARCH_PERFMON_EVENTSEL0 + 12, MSR_ARCH_PERFMON_EVENTSEL0 + 13,
 	MSR_ARCH_PERFMON_EVENTSEL0 + 14, MSR_ARCH_PERFMON_EVENTSEL0 + 15,
 	MSR_ARCH_PERFMON_EVENTSEL0 + 16, MSR_ARCH_PERFMON_EVENTSEL0 + 17,
+
+	MSR_K7_EVNTSEL0, MSR_K7_EVNTSEL1, MSR_K7_EVNTSEL2, MSR_K7_EVNTSEL3,
+	MSR_K7_PERFCTR0, MSR_K7_PERFCTR1, MSR_K7_PERFCTR2, MSR_K7_PERFCTR3,
+	MSR_F15H_PERF_CTL0, MSR_F15H_PERF_CTL1, MSR_F15H_PERF_CTL2,
+	MSR_F15H_PERF_CTL3, MSR_F15H_PERF_CTL4, MSR_F15H_PERF_CTL5,
+	MSR_F15H_PERF_CTR0, MSR_F15H_PERF_CTR1, MSR_F15H_PERF_CTR2,
+	MSR_F15H_PERF_CTR3, MSR_F15H_PERF_CTR4, MSR_F15H_PERF_CTR5,
 };
 
 static u32 msrs_to_save[ARRAY_SIZE(msrs_to_save_all)];
@@ -1270,7 +1343,7 @@
 	MSR_IA32_VMX_EPT_VPID_CAP,
 	MSR_IA32_VMX_VMFUNC,
 
-	MSR_F10H_DECFG,
+	MSR_AMD64_DE_CFG,
 	MSR_IA32_UCODE_REV,
 	MSR_IA32_ARCH_CAPABILITIES,
 };
@@ -1327,10 +1400,22 @@
 	 * If TSX is disabled on the system, guests are also mitigated against
 	 * TAA and clear CPU buffer mitigation is not required for guests.
 	 */
-	if (boot_cpu_has_bug(X86_BUG_TAA) && boot_cpu_has(X86_FEATURE_RTM) &&
-	    (data & ARCH_CAP_TSX_CTRL_MSR))
+	if (!boot_cpu_has(X86_FEATURE_RTM))
+		data &= ~ARCH_CAP_TAA_NO;
+	else if (!boot_cpu_has_bug(X86_BUG_TAA))
+		data |= ARCH_CAP_TAA_NO;
+	else if (data & ARCH_CAP_TSX_CTRL_MSR)
 		data &= ~ARCH_CAP_MDS_NO;
 
+	/* KVM does not emulate MSR_IA32_TSX_CTRL.  */
+	data &= ~ARCH_CAP_TSX_CTRL_MSR;
+
+	/* Guests don't need to know "Fill buffer clear control" exists */
+	data &= ~ARCH_CAP_FB_CLEAR_CTRL;
+
+	if (!boot_cpu_has_bug(X86_BUG_GDS) || gds_ucode_mitigated())
+		data |= ARCH_CAP_GDS_NO;
+
 	return data;
 }
 
@@ -2484,7 +2569,10 @@
 	default:
 		if (msr >= MSR_IA32_MC0_CTL &&
 		    msr < MSR_IA32_MCx_CTL(bank_num)) {
-			u32 offset = msr - MSR_IA32_MC0_CTL;
+			u32 offset = array_index_nospec(
+				msr - MSR_IA32_MC0_CTL,
+				MSR_IA32_MCx_CTL(bank_num) - MSR_IA32_MC0_CTL);
+
 			/* only 0 or all 1s can be written to IA32_MCi_CTL
 			 * some Linux kernels though clear bit 10 in bank 4 to
 			 * workaround a BIOS/GART TBL issue on AMD K8s, ignore
@@ -2580,45 +2668,47 @@
 
 static void record_steal_time(struct kvm_vcpu *vcpu)
 {
+	struct kvm_host_map map;
+	struct kvm_steal_time *st;
+
 	if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED))
 		return;
 
-	if (unlikely(kvm_read_guest_cached(vcpu->kvm, &vcpu->arch.st.stime,
-		&vcpu->arch.st.steal, sizeof(struct kvm_steal_time))))
+	/* -EAGAIN is returned in atomic context so we can just return. */
+	if (kvm_map_gfn(vcpu, vcpu->arch.st.msr_val >> PAGE_SHIFT,
+			&map, &vcpu->arch.st.cache, false))
 		return;
 
+	st = map.hva +
+		offset_in_page(vcpu->arch.st.msr_val & KVM_STEAL_VALID_BITS);
+
 	/*
 	 * Doing a TLB flush here, on the guest's behalf, can avoid
 	 * expensive IPIs.
 	 */
 	trace_kvm_pv_tlb_flush(vcpu->vcpu_id,
-		vcpu->arch.st.steal.preempted & KVM_VCPU_FLUSH_TLB);
-	if (xchg(&vcpu->arch.st.steal.preempted, 0) & KVM_VCPU_FLUSH_TLB)
+		st->preempted & KVM_VCPU_FLUSH_TLB);
+	if (xchg(&st->preempted, 0) & KVM_VCPU_FLUSH_TLB)
 		kvm_vcpu_flush_tlb(vcpu, false);
 
-	if (vcpu->arch.st.steal.version & 1)
-		vcpu->arch.st.steal.version += 1;  /* first time write, random junk */
+	vcpu->arch.st.preempted = 0;
 
-	vcpu->arch.st.steal.version += 1;
+	if (st->version & 1)
+		st->version += 1;  /* first time write, random junk */
 
-	kvm_write_guest_cached(vcpu->kvm, &vcpu->arch.st.stime,
-		&vcpu->arch.st.steal, sizeof(struct kvm_steal_time));
+	st->version += 1;
 
 	smp_wmb();
 
-	vcpu->arch.st.steal.steal += current->sched_info.run_delay -
+	st->steal += current->sched_info.run_delay -
 		vcpu->arch.st.last_steal;
 	vcpu->arch.st.last_steal = current->sched_info.run_delay;
 
-	kvm_write_guest_cached(vcpu->kvm, &vcpu->arch.st.stime,
-		&vcpu->arch.st.steal, sizeof(struct kvm_steal_time));
-
 	smp_wmb();
 
-	vcpu->arch.st.steal.version += 1;
+	st->version += 1;
 
-	kvm_write_guest_cached(vcpu->kvm, &vcpu->arch.st.stime,
-		&vcpu->arch.st.steal, sizeof(struct kvm_steal_time));
+	kvm_unmap_gfn(vcpu, &map, &vcpu->arch.st.cache, true, false);
 }
 
 int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
@@ -2634,6 +2724,7 @@
 	case MSR_AMD64_PATCH_LOADER:
 	case MSR_AMD64_BU_CFG2:
 	case MSR_AMD64_DC_CFG:
+	case MSR_AMD64_TW_CFG:
 	case MSR_F15H_EX_CFG:
 		break;
 
@@ -2685,7 +2776,7 @@
 		return kvm_mtrr_set_msr(vcpu, msr, data);
 	case MSR_IA32_APICBASE:
 		return kvm_set_apic_base(vcpu, msr_info);
-	case APIC_BASE_MSR ... APIC_BASE_MSR + 0x3ff:
+	case APIC_BASE_MSR ... APIC_BASE_MSR + 0xff:
 		return kvm_x2apic_msr_write(vcpu, msr, data);
 	case MSR_IA32_TSCDEADLINE:
 		kvm_set_lapic_tscdeadline_msr(vcpu, data);
@@ -2695,6 +2786,10 @@
 			if (!msr_info->host_initiated) {
 				s64 adj = data - vcpu->arch.ia32_tsc_adjust_msr;
 				adjust_tsc_offset_guest(vcpu, adj);
+				/* Before back to guest, tsc_timestamp must be adjusted
+				 * as well, otherwise guest's percpu pvclock time could jump.
+				 */
+				kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);
 			}
 			vcpu->arch.ia32_tsc_adjust_msr = data;
 		}
@@ -2771,11 +2866,6 @@
 		if (data & KVM_STEAL_RESERVED_MASK)
 			return 1;
 
-		if (kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.st.stime,
-						data & KVM_STEAL_VALID_BITS,
-						sizeof(struct kvm_steal_time)))
-			return 1;
-
 		vcpu->arch.st.msr_val = data;
 
 		if (!(data & KVM_MSR_ENABLED))
@@ -2911,7 +3001,10 @@
 	default:
 		if (msr >= MSR_IA32_MC0_CTL &&
 		    msr < MSR_IA32_MCx_CTL(bank_num)) {
-			u32 offset = msr - MSR_IA32_MC0_CTL;
+			u32 offset = array_index_nospec(
+				msr - MSR_IA32_MC0_CTL,
+				MSR_IA32_MCx_CTL(bank_num) - MSR_IA32_MC0_CTL);
+
 			data = vcpu->arch.mce_banks[offset];
 			break;
 		}
@@ -2941,6 +3034,7 @@
 	case MSR_AMD64_BU_CFG2:
 	case MSR_IA32_PERF_CTL:
 	case MSR_AMD64_DC_CFG:
+	case MSR_AMD64_TW_CFG:
 	case MSR_F15H_EX_CFG:
 		msr_info->data = 0;
 		break;
@@ -2991,7 +3085,7 @@
 	case MSR_IA32_APICBASE:
 		msr_info->data = kvm_get_apic_base(vcpu);
 		break;
-	case APIC_BASE_MSR ... APIC_BASE_MSR + 0x3ff:
+	case APIC_BASE_MSR ... APIC_BASE_MSR + 0xff:
 		return kvm_x2apic_msr_read(vcpu, msr_info->index, &msr_info->data);
 		break;
 	case MSR_IA32_TSCDEADLINE:
@@ -3261,10 +3355,15 @@
 		r = KVM_CLOCK_TSC_STABLE;
 		break;
 	case KVM_CAP_X86_DISABLE_EXITS:
-		r |=  KVM_X86_DISABLE_EXITS_HLT | KVM_X86_DISABLE_EXITS_PAUSE |
-		      KVM_X86_DISABLE_EXITS_CSTATE;
-		if(kvm_can_mwait_in_guest())
-			r |= KVM_X86_DISABLE_EXITS_MWAIT;
+		r = KVM_X86_DISABLE_EXITS_PAUSE;
+
+		if (!mitigate_smt_rsb) {
+			r |= KVM_X86_DISABLE_EXITS_HLT |
+			     KVM_X86_DISABLE_EXITS_CSTATE;
+
+			if (kvm_can_mwait_in_guest())
+				r |= KVM_X86_DISABLE_EXITS_MWAIT;
+		}
 		break;
 	case KVM_CAP_X86_SMM:
 		/* SMBASE is usually relocated above 1M on modern chipsets,
@@ -3437,10 +3536,6 @@
 
 	kvm_x86_ops->vcpu_load(vcpu, cpu);
 
-	fpregs_assert_state_consistent();
-	if (test_thread_flag(TIF_NEED_FPU_LOAD))
-		switch_fpu_return();
-
 	/* Apply any externally detected TSC adjustments (due to suspend) */
 	if (unlikely(vcpu->arch.tsc_offset_adjustment)) {
 		adjust_tsc_offset_host(vcpu, vcpu->arch.tsc_offset_adjustment);
@@ -3480,15 +3575,38 @@
 
 static void kvm_steal_time_set_preempted(struct kvm_vcpu *vcpu)
 {
+	struct kvm_host_map map;
+	struct kvm_steal_time *st;
+
+	/*
+	 * The vCPU can be marked preempted if and only if the VM-Exit was on
+	 * an instruction boundary and will not trigger guest emulation of any
+	 * kind (see vcpu_run).  Vendor specific code controls (conservatively)
+	 * when this is true, for example allowing the vCPU to be marked
+	 * preempted if and only if the VM-Exit was due to a host interrupt.
+	 */
+	if (!vcpu->arch.at_instruction_boundary) {
+		vcpu->stat.preemption_other++;
+		return;
+	}
+
+	vcpu->stat.preemption_reported++;
 	if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED))
 		return;
 
-	vcpu->arch.st.steal.preempted = KVM_VCPU_PREEMPTED;
+	if (vcpu->arch.st.preempted)
+		return;
 
-	kvm_write_guest_offset_cached(vcpu->kvm, &vcpu->arch.st.stime,
-			&vcpu->arch.st.steal.preempted,
-			offsetof(struct kvm_steal_time, preempted),
-			sizeof(vcpu->arch.st.steal.preempted));
+	if (kvm_map_gfn(vcpu, vcpu->arch.st.msr_val >> PAGE_SHIFT, &map,
+			&vcpu->arch.st.cache, true))
+		return;
+
+	st = map.hva +
+		offset_in_page(vcpu->arch.st.msr_val & KVM_STEAL_VALID_BITS);
+
+	st->preempted = vcpu->arch.st.preempted = KVM_VCPU_PREEMPTED;
+
+	kvm_unmap_gfn(vcpu, &map, &vcpu->arch.st.cache, true, true);
 }
 
 void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
@@ -3549,22 +3667,33 @@
 
 static int kvm_cpu_accept_dm_intr(struct kvm_vcpu *vcpu)
 {
+	/*
+	 * We can accept userspace's request for interrupt injection
+	 * as long as we have a place to store the interrupt number.
+	 * The actual injection will happen when the CPU is able to
+	 * deliver the interrupt.
+	 */
+	if (kvm_cpu_has_extint(vcpu))
+		return false;
+
+	/* Acknowledging ExtINT does not happen if LINT0 is masked.  */
 	return (!lapic_in_kernel(vcpu) ||
 		kvm_apic_accept_pic_intr(vcpu));
 }
 
-/*
- * if userspace requested an interrupt window, check that the
- * interrupt window is open.
- *
- * No need to exit to userspace if we already have an interrupt queued.
- */
 static int kvm_vcpu_ready_for_interrupt_injection(struct kvm_vcpu *vcpu)
 {
-	return kvm_arch_interrupt_allowed(vcpu) &&
-		!kvm_cpu_has_interrupt(vcpu) &&
+	/*
+	 * Do not cause an interrupt window exit if an exception
+	 * is pending or an event needs reinjection; userspace
+	 * might want to inject the interrupt manually using KVM_SET_REGS
+	 * or KVM_SET_SREGS.  For that to work, we must be at an
+	 * instruction boundary and with no events half-injected.
+	 */
+	return (kvm_arch_interrupt_allowed(vcpu) &&
+		kvm_cpu_accept_dm_intr(vcpu) &&
 		!kvm_event_needs_reinjection(vcpu) &&
-		kvm_cpu_accept_dm_intr(vcpu);
+		!vcpu->arch.exception.pending);
 }
 
 static int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu,
@@ -3624,7 +3753,7 @@
 	unsigned bank_num = mcg_cap & 0xff, bank;
 
 	r = -EINVAL;
-	if (!bank_num || bank_num >= KVM_MAX_MCE_BANKS)
+	if (!bank_num || bank_num > KVM_MAX_MCE_BANKS)
 		goto out;
 	if (mcg_cap & ~(kvm_mce_cap_supported | 0xff | 0xff0000))
 		goto out;
@@ -3695,6 +3824,10 @@
 {
 	process_nmi(vcpu);
 
+
+	if (kvm_check_request(KVM_REQ_SMI, vcpu))
+		process_smi(vcpu);
+
 	/*
 	 * The API doesn't provide the instruction length for software
 	 * exceptions, so don't report them. As long as the guest RIP
@@ -3844,12 +3977,11 @@
 {
 	unsigned long val;
 
+	memset(dbgregs, 0, sizeof(*dbgregs));
 	memcpy(dbgregs->db, vcpu->arch.db, sizeof(vcpu->arch.db));
 	kvm_get_dr(vcpu, 6, &val);
 	dbgregs->dr6 = val;
 	dbgregs->dr7 = vcpu->arch.dr7;
-	dbgregs->flags = 0;
-	memset(&dbgregs->reserved, 0, sizeof(dbgregs->reserved));
 }
 
 static int kvm_vcpu_ioctl_x86_set_debugregs(struct kvm_vcpu *vcpu,
@@ -4421,6 +4553,7 @@
 	case KVM_SET_NESTED_STATE: {
 		struct kvm_nested_state __user *user_kvm_nested_state = argp;
 		struct kvm_nested_state kvm_state;
+		int idx;
 
 		r = -EINVAL;
 		if (!kvm_x86_ops->set_nested_state)
@@ -4444,7 +4577,9 @@
 		    && !(kvm_state.flags & KVM_STATE_NESTED_GUEST_MODE))
 			break;
 
+		idx = srcu_read_lock(&vcpu->kvm->srcu);
 		r = kvm_x86_ops->set_nested_state(vcpu, user_kvm_nested_state, &kvm_state);
+		srcu_read_unlock(&vcpu->kvm->srcu, idx);
 		break;
 	}
 	case KVM_GET_SUPPORTED_HV_CPUID: {
@@ -4786,15 +4921,26 @@
 		if (cap->args[0] & ~KVM_X86_DISABLE_VALID_EXITS)
 			break;
 
-		if ((cap->args[0] & KVM_X86_DISABLE_EXITS_MWAIT) &&
-			kvm_can_mwait_in_guest())
-			kvm->arch.mwait_in_guest = true;
-		if (cap->args[0] & KVM_X86_DISABLE_EXITS_HLT)
-			kvm->arch.hlt_in_guest = true;
 		if (cap->args[0] & KVM_X86_DISABLE_EXITS_PAUSE)
 			kvm->arch.pause_in_guest = true;
-		if (cap->args[0] & KVM_X86_DISABLE_EXITS_CSTATE)
-			kvm->arch.cstate_in_guest = true;
+
+#define SMT_RSB_MSG "This processor is affected by the Cross-Thread Return Predictions vulnerability. " \
+		    "KVM_CAP_X86_DISABLE_EXITS should only be used with SMT disabled or trusted guests."
+
+		if (!mitigate_smt_rsb) {
+			if (boot_cpu_has_bug(X86_BUG_SMT_RSB) && cpu_smt_possible() &&
+			    (cap->args[0] & ~KVM_X86_DISABLE_EXITS_PAUSE))
+				pr_warn_once(SMT_RSB_MSG);
+
+			if ((cap->args[0] & KVM_X86_DISABLE_EXITS_MWAIT) &&
+			    kvm_can_mwait_in_guest())
+				kvm->arch.mwait_in_guest = true;
+			if (cap->args[0] & KVM_X86_DISABLE_EXITS_HLT)
+				kvm->arch.hlt_in_guest = true;
+			if (cap->args[0] & KVM_X86_DISABLE_EXITS_CSTATE)
+				kvm->arch.cstate_in_guest = true;
+		}
+
 		r = 0;
 		break;
 	case KVM_CAP_MSR_PLATFORM_INFO:
@@ -4973,10 +5119,13 @@
 		r = -EFAULT;
 		if (copy_from_user(&u.ps, argp, sizeof(u.ps)))
 			goto out;
+		mutex_lock(&kvm->lock);
 		r = -ENXIO;
 		if (!kvm->arch.vpit)
-			goto out;
+			goto set_pit_out;
 		r = kvm_vm_ioctl_set_pit(kvm, &u.ps);
+set_pit_out:
+		mutex_unlock(&kvm->lock);
 		break;
 	}
 	case KVM_GET_PIT2: {
@@ -4996,10 +5145,13 @@
 		r = -EFAULT;
 		if (copy_from_user(&u.ps2, argp, sizeof(u.ps2)))
 			goto out;
+		mutex_lock(&kvm->lock);
 		r = -ENXIO;
 		if (!kvm->arch.vpit)
-			goto out;
+			goto set_pit2_out;
 		r = kvm_vm_ioctl_set_pit2(kvm, &u.ps2);
+set_pit2_out:
+		mutex_unlock(&kvm->lock);
 		break;
 	}
 	case KVM_REINJECT_CONTROL: {
@@ -5151,6 +5303,10 @@
 			if (!kvm_x86_ops->rdtscp_supported())
 				continue;
 			break;
+		case MSR_IA32_UMWAIT_CONTROL:
+			if (!boot_cpu_has(X86_FEATURE_WAITPKG))
+				continue;
+			break;
 		case MSR_IA32_RTIT_CTL:
 		case MSR_IA32_RTIT_STATUS:
 			if (!kvm_x86_ops->pt_supported())
@@ -5471,6 +5627,7 @@
 
 int handle_ud(struct kvm_vcpu *vcpu)
 {
+	static const char kvm_emulate_prefix[] = { __KVM_EMULATE_PREFIX };
 	int emul_type = EMULTYPE_TRAP_UD;
 	char sig[5]; /* ud2; .ascii "kvm" */
 	struct x86_exception e;
@@ -5478,7 +5635,7 @@
 	if (force_emulation_prefix &&
 	    kvm_read_guest_virt(vcpu, kvm_get_linear_rip(vcpu),
 				sig, sizeof(sig), &e) == 0 &&
-	    memcmp(sig, "\xf\xbkvm", sizeof(sig)) == 0) {
+	    memcmp(sig, kvm_emulate_prefix, sizeof(sig)) == 0) {
 		kvm_rip_write(vcpu, kvm_rip_read(vcpu) + sizeof(sig));
 		emul_type = EMULTYPE_TRAP_UD_FORCED;
 	}
@@ -6185,7 +6342,10 @@
 
 static void emulator_set_hflags(struct x86_emulate_ctxt *ctxt, unsigned emul_flags)
 {
-	emul_to_vcpu(ctxt)->arch.hflags = emul_flags;
+	struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
+
+	vcpu->arch.hflags = emul_flags;
+	kvm_mmu_reset_context(vcpu);
 }
 
 static int emulator_pre_leave_smm(struct x86_emulate_ctxt *ctxt,
@@ -6356,11 +6516,11 @@
 	return 1;
 }
 
-static bool reexecute_instruction(struct kvm_vcpu *vcpu, gva_t cr2,
+static bool reexecute_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
 				  bool write_fault_to_shadow_pgtable,
 				  int emulation_type)
 {
-	gpa_t gpa = cr2;
+	gpa_t gpa = cr2_or_gpa;
 	kvm_pfn_t pfn;
 
 	if (!(emulation_type & EMULTYPE_ALLOW_RETRY))
@@ -6374,7 +6534,7 @@
 		 * Write permission should be allowed since only
 		 * write access need to be emulated.
 		 */
-		gpa = kvm_mmu_gva_to_gpa_write(vcpu, cr2, NULL);
+		gpa = kvm_mmu_gva_to_gpa_write(vcpu, cr2_or_gpa, NULL);
 
 		/*
 		 * If the mapping is invalid in guest, let cpu retry
@@ -6431,10 +6591,10 @@
 }
 
 static bool retry_instruction(struct x86_emulate_ctxt *ctxt,
-			      unsigned long cr2,  int emulation_type)
+			      gpa_t cr2_or_gpa,  int emulation_type)
 {
 	struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
-	unsigned long last_retry_eip, last_retry_addr, gpa = cr2;
+	unsigned long last_retry_eip, last_retry_addr, gpa = cr2_or_gpa;
 
 	last_retry_eip = vcpu->arch.last_retry_eip;
 	last_retry_addr = vcpu->arch.last_retry_addr;
@@ -6463,14 +6623,14 @@
 	if (x86_page_table_writing_insn(ctxt))
 		return false;
 
-	if (ctxt->eip == last_retry_eip && last_retry_addr == cr2)
+	if (ctxt->eip == last_retry_eip && last_retry_addr == cr2_or_gpa)
 		return false;
 
 	vcpu->arch.last_retry_eip = ctxt->eip;
-	vcpu->arch.last_retry_addr = cr2;
+	vcpu->arch.last_retry_addr = cr2_or_gpa;
 
 	if (!vcpu->arch.mmu->direct_map)
-		gpa = kvm_mmu_gva_to_gpa_write(vcpu, cr2, NULL);
+		gpa = kvm_mmu_gva_to_gpa_write(vcpu, cr2_or_gpa, NULL);
 
 	kvm_mmu_unprotect_page(vcpu->kvm, gpa_to_gfn(gpa));
 
@@ -6616,11 +6776,8 @@
 	return false;
 }
 
-int x86_emulate_instruction(struct kvm_vcpu *vcpu,
-			    unsigned long cr2,
-			    int emulation_type,
-			    void *insn,
-			    int insn_len)
+int x86_emulate_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
+			    int emulation_type, void *insn, int insn_len)
 {
 	int r;
 	struct x86_emulate_ctxt *ctxt = &vcpu->arch.emulate_ctxt;
@@ -6666,10 +6823,13 @@
 				kvm_queue_exception(vcpu, UD_VECTOR);
 				return 1;
 			}
-			if (reexecute_instruction(vcpu, cr2, write_fault_to_spt,
-						emulation_type))
+			if (reexecute_instruction(vcpu, cr2_or_gpa,
+						  write_fault_to_spt,
+						  emulation_type))
 				return 1;
-			if (ctxt->have_exception) {
+
+			if (ctxt->have_exception &&
+			    !(emulation_type & EMULTYPE_SKIP)) {
 				/*
 				 * #UD should result in just EMULATION_FAILED, and trap-like
 				 * exception should not be encountered during decode.
@@ -6701,7 +6861,7 @@
 		return 1;
 	}
 
-	if (retry_instruction(ctxt, cr2, emulation_type))
+	if (retry_instruction(ctxt, cr2_or_gpa, emulation_type))
 		return 1;
 
 	/* this is needed for vmware backdoor interface to work since it
@@ -6713,7 +6873,7 @@
 
 restart:
 	/* Save the faulting GPA (cr2) in the address field */
-	ctxt->exception.address = cr2;
+	ctxt->exception.address = cr2_or_gpa;
 
 	r = x86_emulate_insn(ctxt);
 
@@ -6721,7 +6881,7 @@
 		return 1;
 
 	if (r == EMULATION_FAILED) {
-		if (reexecute_instruction(vcpu, cr2, write_fault_to_spt,
+		if (reexecute_instruction(vcpu, cr2_or_gpa, write_fault_to_spt,
 					emulation_type))
 			return 1;
 
@@ -6760,7 +6920,7 @@
 		if (!ctxt->have_exception ||
 		    exception_type(ctxt->exception.vector) == EXCPT_TRAP) {
 			kvm_rip_write(vcpu, ctxt->eip);
-			if (r && ctxt->tf)
+			if (r && (ctxt->tf || (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)))
 				r = kvm_vcpu_do_singlestep(vcpu);
 			__kvm_set_rflags(vcpu, ctxt->eflags);
 		}
@@ -7182,7 +7342,7 @@
 		goto out;
 	}
 	if (ops->disabled_by_bios()) {
-		printk(KERN_ERR "kvm: disabled by bios\n");
+		printk(KERN_WARNING "kvm: disabled by bios\n");
 		r = -EOPNOTSUPP;
 		goto out;
 	}
@@ -7217,6 +7377,8 @@
 	if (r)
 		goto out_free_percpu;
 
+	mitigate_smt_rsb &= boot_cpu_has_bug(X86_BUG_SMT_RSB) && cpu_smt_possible();
+
 	kvm_x86_ops = ops;
 
 	kvm_mmu_set_mask_ptes(PT_USER_MASK, PT_ACCESSED_MASK,
@@ -7264,6 +7426,7 @@
 	cpuhp_remove_state_nocalls(CPUHP_AP_X86_KVM_CLK_ONLINE);
 #ifdef CONFIG_X86_64
 	pvclock_gtod_unregister_notifier(&pvclock_gtod_notifier);
+	cancel_work_sync(&pvclock_gtod_work);
 #endif
 	kvm_x86_ops = NULL;
 	kvm_mmu_module_exit();
@@ -7496,14 +7659,21 @@
 	kvm_x86_ops->update_cr8_intercept(vcpu, tpr, max_irr);
 }
 
-static int inject_pending_event(struct kvm_vcpu *vcpu, bool req_int_win)
+static void kvm_inject_exception(struct kvm_vcpu *vcpu)
+{
+       if (vcpu->arch.exception.error_code && !is_protmode(vcpu))
+               vcpu->arch.exception.error_code = false;
+       kvm_x86_ops->queue_exception(vcpu);
+}
+
+static int inject_pending_event(struct kvm_vcpu *vcpu)
 {
 	int r;
 
 	/* try to reinject previous events if any */
 
 	if (vcpu->arch.exception.injected)
-		kvm_x86_ops->queue_exception(vcpu);
+		kvm_inject_exception(vcpu);
 	/*
 	 * Do not inject an NMI or interrupt if there is a pending
 	 * exception.  Exceptions and interrupts are recognized at
@@ -7532,7 +7702,7 @@
 	 * from L2 to L1.
 	 */
 	if (is_guest_mode(vcpu) && kvm_x86_ops->check_nested_events) {
-		r = kvm_x86_ops->check_nested_events(vcpu, req_int_win);
+		r = kvm_x86_ops->check_nested_events(vcpu);
 		if (r != 0)
 			return r;
 	}
@@ -7569,7 +7739,7 @@
 			}
 		}
 
-		kvm_x86_ops->queue_exception(vcpu);
+		kvm_inject_exception(vcpu);
 	}
 
 	/* Don't consider new event if we re-injected an event */
@@ -7594,7 +7764,7 @@
 		 * KVM_REQ_EVENT only on certain events and not unconditionally?
 		 */
 		if (is_guest_mode(vcpu) && kvm_x86_ops->check_nested_events) {
-			r = kvm_x86_ops->check_nested_events(vcpu, req_int_win);
+			r = kvm_x86_ops->check_nested_events(vcpu);
 			if (r != 0)
 				return r;
 		}
@@ -7905,9 +8075,8 @@
 	kvm_x86_ops->load_eoi_exitmap(vcpu, eoi_exit_bitmap);
 }
 
-int kvm_arch_mmu_notifier_invalidate_range(struct kvm *kvm,
-		unsigned long start, unsigned long end,
-		bool blockable)
+void kvm_arch_mmu_notifier_invalidate_range(struct kvm *kvm,
+					    unsigned long start, unsigned long end)
 {
 	unsigned long apic_address;
 
@@ -7918,8 +8087,6 @@
 	apic_address = gfn_to_hva(kvm, APIC_DEFAULT_PHYS_BASE >> PAGE_SHIFT);
 	if (start <= apic_address && apic_address < end)
 		kvm_make_all_cpus_request(kvm, KVM_REQ_APIC_PAGE_RELOAD);
-
-	return 0;
 }
 
 void kvm_vcpu_reload_apic_access_page(struct kvm_vcpu *vcpu)
@@ -8071,7 +8238,7 @@
 			goto out;
 		}
 
-		if (inject_pending_event(vcpu, req_int_win) != 0)
+		if (inject_pending_event(vcpu) != 0)
 			req_immediate_exit = true;
 		else {
 			/* Enable SMI/NMI/IRQ window open exits if needed.
@@ -8163,8 +8330,12 @@
 	trace_kvm_entry(vcpu->vcpu_id);
 	guest_enter_irqoff();
 
-	/* The preempt notifier should have taken care of the FPU already.  */
-	WARN_ON_ONCE(test_thread_flag(TIF_NEED_FPU_LOAD));
+	/* Save host pkru register if supported */
+	vcpu->arch.host_pkru = read_pkru();
+
+	fpregs_assert_state_consistent();
+	if (test_thread_flag(TIF_NEED_FPU_LOAD))
+		switch_fpu_return();
 
 	if (unlikely(vcpu->arch.switch_db_regs)) {
 		set_debugreg(0, 7);
@@ -8174,6 +8345,8 @@
 		set_debugreg(vcpu->arch.eff_db[3], 3);
 		set_debugreg(vcpu->arch.dr6, 6);
 		vcpu->arch.switch_db_regs &= ~KVM_DEBUGREG_RELOAD;
+	} else if (unlikely(hw_breakpoint_active())) {
+		set_debugreg(0, 7);
 	}
 
 	kvm_x86_ops->run(vcpu);
@@ -8211,6 +8384,15 @@
 	kvm_x86_ops->handle_exit_irqoff(vcpu);
 
 	/*
+	 * Mark this CPU as needing a branch predictor flush before running
+	 * userspace. Must be done before enabling preemption to ensure it gets
+	 * set for the CPU that actually ran the guest, and not the CPU that it
+	 * may migrate to.
+	 */
+	if (cpu_feature_enabled(X86_FEATURE_IBPB_EXIT_TO_USER))
+		this_cpu_write(x86_ibpb_exit_to_user, true);
+
+	/*
 	 * Consume any pending interrupts, including the possible source of
 	 * VM-Exit on SVM and any ticks that occur between VM-Exit and now.
 	 * An instruction is required after local_irq_enable() to fully unblock
@@ -8256,6 +8438,8 @@
 	return r;
 
 cancel_injection:
+	if (req_immediate_exit)
+		kvm_make_request(KVM_REQ_EVENT, vcpu);
 	kvm_x86_ops->cancel_injection(vcpu);
 	if (unlikely(vcpu->arch.apic_attention))
 		kvm_lapic_sync_from_vapic(vcpu);
@@ -8300,7 +8484,7 @@
 static inline bool kvm_vcpu_running(struct kvm_vcpu *vcpu)
 {
 	if (is_guest_mode(vcpu) && kvm_x86_ops->check_nested_events)
-		kvm_x86_ops->check_nested_events(vcpu, false);
+		kvm_x86_ops->check_nested_events(vcpu);
 
 	return (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE &&
 		!vcpu->arch.apf.halted);
@@ -8315,6 +8499,13 @@
 	vcpu->arch.l1tf_flush_l1d = true;
 
 	for (;;) {
+		/*
+		 * If another guest vCPU requests a PV TLB flush in the middle
+		 * of instruction emulation, the rest of the emulation could
+		 * use a stale page translation. Assume that any code after
+		 * this point can start executing an instruction.
+		 */
+		vcpu->arch.at_instruction_boundary = false;
 		if (kvm_vcpu_running(vcpu)) {
 			r = vcpu_enter_guest(vcpu);
 		} else {
@@ -8436,12 +8627,26 @@
 	return 0;
 }
 
+static void kvm_save_current_fpu(struct fpu *fpu)
+{
+	/*
+	 * If the target FPU state is not resident in the CPU registers, just
+	 * memcpy() from current, else save CPU state directly to the target.
+	 */
+	if (test_thread_flag(TIF_NEED_FPU_LOAD))
+		memcpy(&fpu->state, &current->thread.fpu.state,
+		       fpu_kernel_xstate_size);
+	else
+		copy_fpregs_to_fpstate(fpu);
+}
+
 /* Swap (qemu) user FPU context for the guest FPU context. */
 static void kvm_load_guest_fpu(struct kvm_vcpu *vcpu)
 {
 	fpregs_lock();
 
-	copy_fpregs_to_fpstate(vcpu->arch.user_fpu);
+	kvm_save_current_fpu(vcpu->arch.user_fpu);
+
 	/* PKRU is separately restored in kvm_x86_ops->run.  */
 	__copy_kernel_to_fpregs(&vcpu->arch.guest_fpu->state,
 				~XFEATURE_MASK_PKRU);
@@ -8457,7 +8662,8 @@
 {
 	fpregs_lock();
 
-	copy_fpregs_to_fpstate(vcpu->arch.guest_fpu);
+	kvm_save_current_fpu(vcpu->arch.guest_fpu);
+
 	copy_kernel_to_fpregs(&vcpu->arch.user_fpu->state);
 
 	fpregs_mark_activate();
@@ -8679,6 +8885,8 @@
 				    struct kvm_mp_state *mp_state)
 {
 	vcpu_load(vcpu);
+	if (kvm_mpx_supported())
+		kvm_load_guest_fpu(vcpu);
 
 	kvm_apic_accept_events(vcpu);
 	if (vcpu->arch.mp_state == KVM_MP_STATE_HALTED &&
@@ -8687,6 +8895,8 @@
 	else
 		mp_state->mp_state = vcpu->arch.mp_state;
 
+	if (kvm_mpx_supported())
+		kvm_put_guest_fpu(vcpu);
 	vcpu_put(vcpu);
 	return 0;
 }
@@ -9046,6 +9256,9 @@
 void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)
 {
 	void *wbinvd_dirty_mask = vcpu->arch.wbinvd_dirty_mask;
+	struct gfn_to_pfn_cache *cache = &vcpu->arch.st.cache;
+
+	kvm_release_pfn(cache->pfn, cache->dirty, cache);
 
 	kvmclock_reset(vcpu);
 
@@ -9110,17 +9323,13 @@
 
 void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
 {
-	vcpu->arch.apf.msr_val = 0;
-
-	vcpu_load(vcpu);
-	kvm_mmu_unload(vcpu);
-	vcpu_put(vcpu);
-
-	kvm_x86_ops->vcpu_free(vcpu);
+	kvm_arch_vcpu_free(vcpu);
 }
 
 void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
 {
+	unsigned long old_cr0 = kvm_read_cr0(vcpu);
+
 	kvm_lapic_reset(vcpu, init_event);
 
 	vcpu->arch.hflags = 0;
@@ -9190,6 +9399,17 @@
 	vcpu->arch.ia32_xss = 0;
 
 	kvm_x86_ops->vcpu_reset(vcpu, init_event);
+
+	/*
+	 * Reset the MMU context if paging was enabled prior to INIT (which is
+	 * implied if CR0.PG=1 as CR0 will be '0' prior to RESET).  Unlike the
+	 * standard CR0/CR4/EFER modification paths, only CR0.PG needs to be
+	 * checked because it is unconditionally cleared on INIT and all other
+	 * paging related bits are ignored if paging is disabled, i.e. CR0.WP,
+	 * CR4, and EFER changes are all irrelevant if CR0.PG was '0'.
+	 */
+	if (old_cr0 & X86_CR0_PG)
+		kvm_mmu_reset_context(vcpu);
 }
 
 void kvm_vcpu_deliver_sipi_vector(struct kvm_vcpu *vcpu, u8 vector)
@@ -9308,6 +9528,8 @@
 	if (r != 0)
 		return r;
 
+	cr4_reserved_bits = kvm_host_cr4_reserved_bits(&boot_cpu_data);
+
 	if (kvm_has_tsc_control) {
 		/*
 		 * Make sure the user can only configure tsc_khz values that
@@ -9648,6 +9870,13 @@
 {
 	int i;
 
+	/*
+	 * Clear out the previous array pointers for the KVM_MR_MOVE case.  The
+	 * old arrays will be freed by __kvm_set_memory_region() if installing
+	 * the new memslot is successful.
+	 */
+	memset(&slot->arch, 0, sizeof(slot->arch));
+
 	for (i = 0; i < KVM_NR_PAGE_SIZES; ++i) {
 		struct kvm_lpage_info *linfo;
 		unsigned long ugfn;
@@ -9710,11 +9939,18 @@
 
 void kvm_arch_memslots_updated(struct kvm *kvm, u64 gen)
 {
+	struct kvm_vcpu *vcpu;
+	int i;
+
 	/*
 	 * memslots->generation has been incremented.
 	 * mmio generation may have reached its maximum value.
 	 */
 	kvm_mmu_invalidate_mmio_sptes(kvm, gen);
+
+	/* Force re-initialization of steal_time cache */
+	kvm_for_each_vcpu(i, vcpu, kvm)
+		kvm_vcpu_kick(vcpu);
 }
 
 int kvm_arch_prepare_memory_region(struct kvm *kvm,
@@ -9722,6 +9958,10 @@
 				const struct kvm_userspace_memory_region *mem,
 				enum kvm_mr_change change)
 {
+	if (change == KVM_MR_MOVE)
+		return kvm_arch_create_memslot(kvm, memslot,
+					       mem->memory_size >> PAGE_SHIFT);
+
 	return 0;
 }
 
@@ -9966,7 +10206,7 @@
 	      work->arch.cr3 != vcpu->arch.mmu->get_cr3(vcpu))
 		return;
 
-	vcpu->arch.mmu->page_fault(vcpu, work->gva, 0, true);
+	vcpu->arch.mmu->page_fault(vcpu, work->cr2_or_gpa, 0, true);
 }
 
 static inline u32 kvm_async_pf_hash_fn(gfn_t gfn)
@@ -10079,7 +10319,7 @@
 {
 	struct x86_exception fault;
 
-	trace_kvm_async_pf_not_present(work->arch.token, work->gva);
+	trace_kvm_async_pf_not_present(work->arch.token, work->cr2_or_gpa);
 	kvm_add_async_pf_gfn(vcpu, work->arch.gfn);
 
 	if (kvm_can_deliver_async_pf(vcpu) &&
@@ -10114,7 +10354,7 @@
 		work->arch.token = ~0; /* broadcast wakeup */
 	else
 		kvm_del_async_pf_gfn(vcpu, work->arch.gfn);
-	trace_kvm_async_pf_ready(work->arch.token, work->gva);
+	trace_kvm_async_pf_ready(work->arch.token, work->cr2_or_gpa);
 
 	if (vcpu->arch.apf.msr_val & KVM_ASYNC_PF_ENABLED &&
 	    !apf_get_user(vcpu, &val)) {
@@ -10163,9 +10403,9 @@
 }
 EXPORT_SYMBOL_GPL(kvm_arch_end_assignment);
 
-bool kvm_arch_has_assigned_device(struct kvm *kvm)
+bool noinstr kvm_arch_has_assigned_device(struct kvm *kvm)
 {
-	return atomic_read(&kvm->arch.assigned_device_count);
+	return arch_atomic_read(&kvm->arch.assigned_device_count);
 }
 EXPORT_SYMBOL_GPL(kvm_arch_has_assigned_device);
 
@@ -10245,6 +10485,32 @@
 EXPORT_SYMBOL_GPL(kvm_arch_no_poll);
 
 
+int kvm_spec_ctrl_test_value(u64 value)
+{
+	/*
+	 * test that setting IA32_SPEC_CTRL to given value
+	 * is allowed by the host processor
+	 */
+
+	u64 saved_value;
+	unsigned long flags;
+	int ret = 0;
+
+	local_irq_save(flags);
+
+	if (rdmsrl_safe(MSR_IA32_SPEC_CTRL, &saved_value))
+		ret = 1;
+	else if (wrmsrl_safe(MSR_IA32_SPEC_CTRL, value))
+		ret = 1;
+	else
+		wrmsrl(MSR_IA32_SPEC_CTRL, saved_value);
+
+	local_irq_restore(flags);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(kvm_spec_ctrl_test_value);
+
 EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_exit);
 EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_fast_mmio);
 EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_inj_virq);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/kvm/x86.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/kvm/x86.h
@@ -286,7 +286,7 @@
 bool kvm_mtrr_check_gfn_range_consistency(struct kvm_vcpu *vcpu, gfn_t gfn,
 					  int page_num);
 bool kvm_vector_hashing_enabled(void);
-int x86_emulate_instruction(struct kvm_vcpu *vcpu, unsigned long cr2,
+int x86_emulate_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
 			    int emulation_type, void *insn, int insn_len);
 
 #define KVM_SUPPORTED_XCR0     (XFEATURE_MASK_FP | XFEATURE_MASK_SSE \
@@ -368,5 +368,6 @@
 
 void kvm_load_guest_xcr0(struct kvm_vcpu *vcpu);
 void kvm_put_guest_xcr0(struct kvm_vcpu *vcpu);
+int kvm_spec_ctrl_test_value(u64 value);
 
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/lib/delay.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/lib/delay.c
@@ -43,8 +43,8 @@
 		"	jnz 2b		\n"
 		"3:	dec %0		\n"
 
-		: /* we don't need output */
-		:"a" (loops)
+		: "+a" (loops)
+		:
 	);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/lib/insn-eval.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/lib/insn-eval.c
@@ -70,14 +70,15 @@
 {
 	int idx = INAT_SEG_REG_DEFAULT;
 	int num_overrides = 0, i;
+	insn_byte_t p;
 
 	insn_get_prefixes(insn);
 
 	/* Look for any segment override prefixes. */
-	for (i = 0; i < insn->prefixes.nbytes; i++) {
+	for_each_insn_prefix(insn, i, p) {
 		insn_attr_t attr;
 
-		attr = inat_get_opcode_attribute(insn->prefixes.bytes[i]);
+		attr = inat_get_opcode_attribute(p);
 		switch (attr) {
 		case INAT_MAKE_PREFIX(INAT_PFX_CS):
 			idx = INAT_SEG_REG_CS;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/lib/insn.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/lib/insn.c
@@ -13,6 +13,8 @@
 #include <asm/inat.h>
 #include <asm/insn.h>
 
+#include <asm/emulate_prefix.h>
+
 /* Verify next sizeof(t) bytes can be on the same instruction */
 #define validate_next(t, insn, n)	\
 	((insn)->next_byte + sizeof(t) + n <= (insn)->end_kaddr)
@@ -58,6 +60,36 @@
 		insn->addr_bytes = 4;
 }
 
+static const insn_byte_t xen_prefix[] = { __XEN_EMULATE_PREFIX };
+static const insn_byte_t kvm_prefix[] = { __KVM_EMULATE_PREFIX };
+
+static int __insn_get_emulate_prefix(struct insn *insn,
+				     const insn_byte_t *prefix, size_t len)
+{
+	size_t i;
+
+	for (i = 0; i < len; i++) {
+		if (peek_nbyte_next(insn_byte_t, insn, i) != prefix[i])
+			goto err_out;
+	}
+
+	insn->emulate_prefix_size = len;
+	insn->next_byte += len;
+
+	return 1;
+
+err_out:
+	return 0;
+}
+
+static void insn_get_emulate_prefix(struct insn *insn)
+{
+	if (__insn_get_emulate_prefix(insn, xen_prefix, sizeof(xen_prefix)))
+		return;
+
+	__insn_get_emulate_prefix(insn, kvm_prefix, sizeof(kvm_prefix));
+}
+
 /**
  * insn_get_prefixes - scan x86 instruction prefix bytes
  * @insn:	&struct insn containing instruction
@@ -76,6 +108,8 @@
 	if (prefixes->got)
 		return;
 
+	insn_get_emulate_prefix(insn);
+
 	nb = 0;
 	lb = 0;
 	b = peek_next(insn_byte_t, insn);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/lib/iomap_copy_64.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/lib/iomap_copy_64.S
@@ -10,6 +10,6 @@
  */
 ENTRY(__iowrite32_copy)
 	movl %edx,%ecx
-	rep movsd
+	rep movsl
 	ret
 ENDPROC(__iowrite32_copy)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/lib/iomem.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/lib/iomem.c
@@ -22,7 +22,7 @@
 		     : "memory");
 }
 
-void memcpy_fromio(void *to, const volatile void __iomem *from, size_t n)
+static void string_memcpy_fromio(void *to, const volatile void __iomem *from, size_t n)
 {
 	if (unlikely(!n))
 		return;
@@ -38,9 +38,8 @@
 	}
 	rep_movs(to, (const void *)from, n);
 }
-EXPORT_SYMBOL(memcpy_fromio);
 
-void memcpy_toio(volatile void __iomem *to, const void *from, size_t n)
+static void string_memcpy_toio(volatile void __iomem *to, const void *from, size_t n)
 {
 	if (unlikely(!n))
 		return;
@@ -56,14 +55,64 @@
 	}
 	rep_movs((void *)to, (const void *) from, n);
 }
+
+static void unrolled_memcpy_fromio(void *to, const volatile void __iomem *from, size_t n)
+{
+	const volatile char __iomem *in = from;
+	char *out = to;
+	int i;
+
+	for (i = 0; i < n; ++i)
+		out[i] = readb(&in[i]);
+}
+
+static void unrolled_memcpy_toio(volatile void __iomem *to, const void *from, size_t n)
+{
+	volatile char __iomem *out = to;
+	const char *in = from;
+	int i;
+
+	for (i = 0; i < n; ++i)
+		writeb(in[i], &out[i]);
+}
+
+static void unrolled_memset_io(volatile void __iomem *a, int b, size_t c)
+{
+	volatile char __iomem *mem = a;
+	int i;
+
+	for (i = 0; i < c; ++i)
+		writeb(b, &mem[i]);
+}
+
+void memcpy_fromio(void *to, const volatile void __iomem *from, size_t n)
+{
+	if (sev_key_active())
+		unrolled_memcpy_fromio(to, from, n);
+	else
+		string_memcpy_fromio(to, from, n);
+}
+EXPORT_SYMBOL(memcpy_fromio);
+
+void memcpy_toio(volatile void __iomem *to, const void *from, size_t n)
+{
+	if (sev_key_active())
+		unrolled_memcpy_toio(to, from, n);
+	else
+		string_memcpy_toio(to, from, n);
+}
 EXPORT_SYMBOL(memcpy_toio);
 
 void memset_io(volatile void __iomem *a, int b, size_t c)
 {
-	/*
-	 * TODO: memset can mangle the IO patterns quite a bit.
-	 * perhaps it would be better to use a dumb one:
-	 */
-	memset((void *)a, b, c);
+	if (sev_key_active()) {
+		unrolled_memset_io(a, b, c);
+	} else {
+		/*
+		 * TODO: memset can mangle the IO patterns quite a bit.
+		 * perhaps it would be better to use a dumb one:
+		 */
+		memset((void *)a, b, c);
+	}
 }
 EXPORT_SYMBOL(memset_io);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/lib/memcpy_64.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/lib/memcpy_64.S
@@ -15,8 +15,6 @@
  * to a jmp to memcpy_erms which does the REP; MOVSB mem copy.
  */
 
-.weak memcpy
-
 /*
  * memcpy - Copy a memory block.
  *
@@ -29,7 +27,7 @@
  * rax original destination
  */
 ENTRY(__memcpy)
-ENTRY(memcpy)
+SYM_FUNC_START_WEAK(memcpy)
 	ALTERNATIVE_2 "jmp memcpy_orig", "", X86_FEATURE_REP_GOOD, \
 		      "jmp memcpy_erms", X86_FEATURE_ERMS
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/lib/memmove_64.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/lib/memmove_64.S
@@ -24,9 +24,7 @@
  * Output:
  * rax: dest
  */
-.weak memmove
-
-ENTRY(memmove)
+SYM_FUNC_START_WEAK(memmove)
 ENTRY(__memmove)
 
 	/* Handle more 32 bytes in loop */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/lib/memset_64.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/lib/memset_64.S
@@ -6,8 +6,6 @@
 #include <asm/alternative-asm.h>
 #include <asm/export.h>
 
-.weak memset
-
 /*
  * ISO C memset - set a memory block to a byte value. This function uses fast
  * string to get better performance than the original function. The code is
@@ -19,7 +17,7 @@
  *
  * rax   original destination
  */
-ENTRY(memset)
+SYM_FUNC_START_WEAK(memset)
 ENTRY(__memset)
 	/*
 	 * Some CPUs support enhanced REP MOVSB/STOSB feature. It is recommended
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/lib/misc.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/lib/misc.c
@@ -6,7 +6,7 @@
  */
 int num_digits(int val)
 {
-	int m = 10;
+	long long m = 10;
 	int d = 1;
 
 	if (val < 0) {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/lib/mmx_32.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/lib/mmx_32.c
@@ -26,6 +26,16 @@
 #include <asm/fpu/api.h>
 #include <asm/asm.h>
 
+/*
+ * Use KFPU_387.  MMX instructions are not affected by MXCSR,
+ * but both AMD and Intel documentation states that even integer MMX
+ * operations will result in #MF if an exception is pending in FCW.
+ *
+ * EMMS is not needed afterwards because, after calling kernel_fpu_end(),
+ * any subsequent user of the 387 stack will reinitialize it using
+ * KFPU_387.
+ */
+
 void *_mmx_memcpy(void *to, const void *from, size_t len)
 {
 	void *p;
@@ -37,7 +47,7 @@
 	p = to;
 	i = len >> 6; /* len/64 */
 
-	kernel_fpu_begin();
+	kernel_fpu_begin_mask(KFPU_387);
 
 	__asm__ __volatile__ (
 		"1: prefetch (%0)\n"		/* This set is 28 bytes */
@@ -127,7 +137,7 @@
 {
 	int i;
 
-	kernel_fpu_begin();
+	kernel_fpu_begin_mask(KFPU_387);
 
 	__asm__ __volatile__ (
 		"  pxor %%mm0, %%mm0\n" : :
@@ -160,7 +170,7 @@
 {
 	int i;
 
-	kernel_fpu_begin();
+	kernel_fpu_begin_mask(KFPU_387);
 
 	/*
 	 * maybe the prefetch stuff can go before the expensive fnsave...
@@ -247,7 +257,7 @@
 {
 	int i;
 
-	kernel_fpu_begin();
+	kernel_fpu_begin_mask(KFPU_387);
 
 	__asm__ __volatile__ (
 		"  pxor %%mm0, %%mm0\n" : :
@@ -282,7 +292,7 @@
 {
 	int i;
 
-	kernel_fpu_begin();
+	kernel_fpu_begin_mask(KFPU_387);
 
 	__asm__ __volatile__ (
 		"1: prefetch (%0)\n"
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/lib/msr-smp.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/lib/msr-smp.c
@@ -253,7 +253,7 @@
 	rv->err = wrmsr_safe_regs(rv->regs);
 }
 
-int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 *regs)
+int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8])
 {
 	int err;
 	struct msr_regs_info rv;
@@ -266,7 +266,7 @@
 }
 EXPORT_SYMBOL(rdmsr_safe_regs_on_cpu);
 
-int wrmsr_safe_regs_on_cpu(unsigned int cpu, u32 *regs)
+int wrmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8])
 {
 	int err;
 	struct msr_regs_info rv;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/lib/usercopy_64.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/lib/usercopy_64.c
@@ -24,6 +24,7 @@
 	asm volatile(
 		"	testq  %[size8],%[size8]\n"
 		"	jz     4f\n"
+		"	.align 16\n"
 		"0:	movq $0,(%[dst])\n"
 		"	addq   $8,%[dst]\n"
 		"	decl %%ecx ; jnz   0b\n"
@@ -119,7 +120,7 @@
 	 */
 	if (size < 8) {
 		if (!IS_ALIGNED(dest, 4) || size != 4)
-			clean_cache_range(dst, 1);
+			clean_cache_range(dst, size);
 	} else {
 		if (!IS_ALIGNED(dest, 8)) {
 			dest = ALIGN(dest, boot_cpu_data.x86_clflush_size);
@@ -141,7 +142,7 @@
 
 	/* cache copy and flush to align dest */
 	if (!IS_ALIGNED(dest, 8)) {
-		unsigned len = min_t(unsigned, size, ALIGN(dest, 8) - dest);
+		size_t len = min_t(size_t, size, ALIGN(dest, 8) - dest);
 
 		memcpy((void *) dest, (void *) source, len);
 		clean_cache_range((void *) dest, len);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/lib/x86-opcode-map.txt
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/lib/x86-opcode-map.txt
@@ -148,7 +148,7 @@
 65: SEG=GS (Prefix)
 66: Operand-Size (Prefix)
 67: Address-Size (Prefix)
-68: PUSH Iz (d64)
+68: PUSH Iz
 69: IMUL Gv,Ev,Iz
 6a: PUSH Ib (d64)
 6b: IMUL Gv,Ev,Ib
@@ -333,7 +333,7 @@
 06: CLTS
 07: SYSRET (o64)
 08: INVD
-09: WBINVD
+09: WBINVD | WBNOINVD (F3)
 0a:
 0b: UD2 (1B)
 0c:
@@ -364,7 +364,7 @@
 # a ModR/M byte.
 1a: BNDCL Gv,Ev (F3) | BNDCU Gv,Ev (F2) | BNDMOV Gv,Ev (66) | BNDLDX Gv,Ev
 1b: BNDCN Gv,Ev (F2) | BNDMOV Ev,Gv (66) | BNDMK Gv,Ev (F3) | BNDSTX Ev,Gv
-1c:
+1c: Grp20 (1A),(1C)
 1d:
 1e:
 1f: NOP Ev
@@ -792,6 +792,8 @@
 f5: BZHI Gy,Ey,By (v) | PEXT Gy,By,Ey (F3),(v) | PDEP Gy,By,Ey (F2),(v)
 f6: ADCX Gy,Ey (66) | ADOX Gy,Ey (F3) | MULX By,Gy,rDX,Ey (F2),(v)
 f7: BEXTR Gy,Ey,By (v) | SHLX Gy,Ey,By (66),(v) | SARX Gy,Ey,By (F3),(v) | SHRX Gy,Ey,By (F2),(v)
+f8: MOVDIR64B Gv,Mdqq (66) | ENQCMD Gv,Mdqq (F2) | ENQCMDS Gv,Mdqq (F3)
+f9: MOVDIRI My,Gy
 EndTable
 
 Table: 3-byte opcode 2 (0x0f 0x3a)
@@ -907,7 +909,7 @@
 
 GrpTable: Grp3_2
 0: TEST Ev,Iz
-1:
+1: TEST Ev,Iz
 2: NOT Ev
 3: NEG Ev
 4: MUL rAX,Ev
@@ -943,9 +945,9 @@
 EndTable
 
 GrpTable: Grp7
-0: SGDT Ms | VMCALL (001),(11B) | VMLAUNCH (010),(11B) | VMRESUME (011),(11B) | VMXOFF (100),(11B)
-1: SIDT Ms | MONITOR (000),(11B) | MWAIT (001),(11B) | CLAC (010),(11B) | STAC (011),(11B)
-2: LGDT Ms | XGETBV (000),(11B) | XSETBV (001),(11B) | VMFUNC (100),(11B) | XEND (101)(11B) | XTEST (110)(11B)
+0: SGDT Ms | VMCALL (001),(11B) | VMLAUNCH (010),(11B) | VMRESUME (011),(11B) | VMXOFF (100),(11B) | PCONFIG (101),(11B) | ENCLV (000),(11B)
+1: SIDT Ms | MONITOR (000),(11B) | MWAIT (001),(11B) | CLAC (010),(11B) | STAC (011),(11B) | ENCLS (111),(11B)
+2: LGDT Ms | XGETBV (000),(11B) | XSETBV (001),(11B) | VMFUNC (100),(11B) | XEND (101)(11B) | XTEST (110)(11B) | ENCLU (111),(11B)
 3: LIDT Ms
 4: SMSW Mw/Rv
 5: rdpkru (110),(11B) | wrpkru (111),(11B)
@@ -1020,7 +1022,7 @@
 3: vstmxcsr Md (v1) | WRGSBASE Ry (F3),(11B)
 4: XSAVE | ptwrite Ey (F3),(11B)
 5: XRSTOR | lfence (11B)
-6: XSAVEOPT | clwb (66) | mfence (11B)
+6: XSAVEOPT | clwb (66) | mfence (11B) | TPAUSE Rd (66),(11B) | UMONITOR Rv (F3),(11B) | UMWAIT Rd (F2),(11B)
 7: clflush | clflushopt (66) | sfence (11B)
 EndTable
 
@@ -1051,6 +1053,10 @@
 6: vscatterpf1qps/d Wx (66),(ev)
 EndTable
 
+GrpTable: Grp20
+0: cldemote Mb
+EndTable
+
 # AMD's Prefetch Group
 GrpTable: GrpP
 0: PREFETCH
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/math-emu/fpu_system.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/math-emu/fpu_system.h
@@ -107,6 +107,8 @@
 #define FPU_access_ok(y,z)	if ( !access_ok(y,z) ) \
 				math_abort(FPU_info,SIGSEGV)
 #define FPU_abort		math_abort(FPU_info, SIGSEGV)
+#define FPU_copy_from_user(to, from, n)	\
+		do { if (copy_from_user(to, from, n)) FPU_abort; } while (0)
 
 #undef FPU_IGNORE_CODE_SEGV
 #ifdef FPU_IGNORE_CODE_SEGV
@@ -122,7 +124,7 @@
 #define	FPU_code_access_ok(z) FPU_access_ok((void __user *)FPU_EIP,z)
 #endif
 
-#define FPU_get_user(x,y)       get_user((x),(y))
-#define FPU_put_user(x,y)       put_user((x),(y))
+#define FPU_get_user(x,y) do { if (get_user((x),(y))) FPU_abort; } while (0)
+#define FPU_put_user(x,y) do { if (put_user((x),(y))) FPU_abort; } while (0)
 
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/math-emu/reg_ld_str.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/math-emu/reg_ld_str.c
@@ -85,7 +85,7 @@
 
 	RE_ENTRANT_CHECK_OFF;
 	FPU_access_ok(s, 10);
-	__copy_from_user(sti_ptr, s, 10);
+	FPU_copy_from_user(sti_ptr, s, 10);
 	RE_ENTRANT_CHECK_ON;
 
 	return FPU_tagof(sti_ptr);
@@ -1126,9 +1126,9 @@
 	/* Copy all registers in stack order. */
 	RE_ENTRANT_CHECK_OFF;
 	FPU_access_ok(s, 80);
-	__copy_from_user(register_base + offset, s, other);
+	FPU_copy_from_user(register_base + offset, s, other);
 	if (offset)
-		__copy_from_user(register_base, s + other, offset);
+		FPU_copy_from_user(register_base, s + other, offset);
 	RE_ENTRANT_CHECK_ON;
 
 	for (i = 0; i < 8; i++) {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/math-emu/wm_sqrt.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/math-emu/wm_sqrt.S
@@ -209,7 +209,7 @@
 
 #ifdef PARANOID
 /* It should be possible to get here only if the arg is ffff....ffff */
-	cmp	$0xffffffff,FPU_fsqrt_arg_1
+	cmpl	$0xffffffff,FPU_fsqrt_arg_1
 	jnz	sqrt_stage_2_error
 #endif /* PARANOID */
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/mm/cpu_entry_area.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/mm/cpu_entry_area.c
@@ -4,22 +4,72 @@
 #include <linux/percpu.h>
 #include <linux/kallsyms.h>
 #include <linux/kcore.h>
+#include <linux/prandom.h>
 
 #include <asm/cpu_entry_area.h>
 #include <asm/pgtable.h>
 #include <asm/fixmap.h>
 #include <asm/desc.h>
+#include <asm/kasan.h>
+#include <asm/setup.h>
 
 static DEFINE_PER_CPU_PAGE_ALIGNED(struct entry_stack_page, entry_stack_storage);
 
 #ifdef CONFIG_X86_64
 static DEFINE_PER_CPU_PAGE_ALIGNED(struct exception_stacks, exception_stacks);
 DEFINE_PER_CPU(struct cea_exception_stacks*, cea_exception_stacks);
+
+static DEFINE_PER_CPU_READ_MOSTLY(unsigned long, _cea_offset);
+
+static __always_inline unsigned int cea_offset(unsigned int cpu)
+{
+	return per_cpu(_cea_offset, cpu);
+}
+
+static __init void init_cea_offsets(void)
+{
+	unsigned int max_cea;
+	unsigned int i, j;
+
+	if (!kaslr_enabled()) {
+		for_each_possible_cpu(i)
+			per_cpu(_cea_offset, i) = i;
+		return;
+	}
+
+	max_cea = (CPU_ENTRY_AREA_MAP_SIZE - PAGE_SIZE) / CPU_ENTRY_AREA_SIZE;
+
+	/* O(sodding terrible) */
+	for_each_possible_cpu(i) {
+		unsigned int cea;
+
+again:
+		cea = prandom_u32_max(max_cea);
+
+		for_each_possible_cpu(j) {
+			if (cea_offset(j) == cea)
+				goto again;
+
+			if (i == j)
+				break;
+		}
+
+		per_cpu(_cea_offset, i) = cea;
+	}
+}
+#else /* !X86_64 */
+DECLARE_PER_CPU_PAGE_ALIGNED(struct doublefault_stack, doublefault_stack);
+
+static __always_inline unsigned int cea_offset(unsigned int cpu)
+{
+	return cpu;
+}
+static inline void init_cea_offsets(void) { }
 #endif
 
 struct cpu_entry_area *get_cpu_entry_area(int cpu)
 {
-	unsigned long va = CPU_ENTRY_AREA_PER_CPU + cpu * CPU_ENTRY_AREA_SIZE;
+	unsigned long va = CPU_ENTRY_AREA_PER_CPU + cea_offset(cpu) * CPU_ENTRY_AREA_SIZE;
 	BUILD_BUG_ON(sizeof(struct cpu_entry_area) % PAGE_SIZE != 0);
 
 	return (struct cpu_entry_area *) va;
@@ -135,6 +185,9 @@
 	pgprot_t tss_prot = PAGE_KERNEL;
 #endif
 
+	kasan_populate_shadow_for_vaddr(cea, CPU_ENTRY_AREA_SIZE,
+					early_cpu_to_node(cpu));
+
 	cea_set_pte(&cea->gdt, get_cpu_gdt_paddr(cpu), gdt_prot);
 
 	cea_map_percpu_pages(&cea->entry_stack_page,
@@ -178,7 +231,8 @@
 #ifdef CONFIG_X86_32
 	unsigned long start, end;
 
-	BUILD_BUG_ON(CPU_ENTRY_AREA_PAGES * PAGE_SIZE < CPU_ENTRY_AREA_MAP_SIZE);
+	/* The +1 is for the readonly IDT: */
+	BUILD_BUG_ON((CPU_ENTRY_AREA_PAGES+1)*PAGE_SIZE != CPU_ENTRY_AREA_MAP_SIZE);
 	BUG_ON(CPU_ENTRY_AREA_BASE & ~PMD_MASK);
 
 	start = CPU_ENTRY_AREA_BASE;
@@ -194,6 +248,8 @@
 {
 	unsigned int cpu;
 
+	init_cea_offsets();
+
 	setup_cpu_entry_area_ptes();
 
 	for_each_possible_cpu(cpu)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/mm/extable.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/mm/extable.c
@@ -45,55 +45,6 @@
 EXPORT_SYMBOL_GPL(ex_handler_fault);
 
 /*
- * Handler for UD0 exception following a failed test against the
- * result of a refcount inc/dec/add/sub.
- */
-__visible bool ex_handler_refcount(const struct exception_table_entry *fixup,
-				   struct pt_regs *regs, int trapnr,
-				   unsigned long error_code,
-				   unsigned long fault_addr)
-{
-	/* First unconditionally saturate the refcount. */
-	*(int *)regs->cx = INT_MIN / 2;
-
-	/*
-	 * Strictly speaking, this reports the fixup destination, not
-	 * the fault location, and not the actually overflowing
-	 * instruction, which is the instruction before the "js", but
-	 * since that instruction could be a variety of lengths, just
-	 * report the location after the overflow, which should be close
-	 * enough for finding the overflow, as it's at least back in
-	 * the function, having returned from .text.unlikely.
-	 */
-	regs->ip = ex_fixup_addr(fixup);
-
-	/*
-	 * This function has been called because either a negative refcount
-	 * value was seen by any of the refcount functions, or a zero
-	 * refcount value was seen by refcount_dec().
-	 *
-	 * If we crossed from INT_MAX to INT_MIN, OF (Overflow Flag: result
-	 * wrapped around) will be set. Additionally, seeing the refcount
-	 * reach 0 will set ZF (Zero Flag: result was zero). In each of
-	 * these cases we want a report, since it's a boundary condition.
-	 * The SF case is not reported since it indicates post-boundary
-	 * manipulations below zero or above INT_MAX. And if none of the
-	 * flags are set, something has gone very wrong, so report it.
-	 */
-	if (regs->flags & (X86_EFLAGS_OF | X86_EFLAGS_ZF)) {
-		bool zero = regs->flags & X86_EFLAGS_ZF;
-
-		refcount_error_report(regs, zero ? "hit zero" : "overflow");
-	} else if ((regs->flags & X86_EFLAGS_SF) == 0) {
-		/* Report if none of OF, ZF, nor SF are set. */
-		refcount_error_report(regs, "unexpected saturation");
-	}
-
-	return true;
-}
-EXPORT_SYMBOL(ex_handler_refcount);
-
-/*
  * Handler for when we fail to restore a task's FPU state.  We should never get
  * here because the FPU state of a task using the FPU (task->thread.fpu.state)
  * should always be valid.  However, past bugs have allowed userspace to set
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/mm/fault.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/mm/fault.c
@@ -189,7 +189,7 @@
 	return pmd_k;
 }
 
-void vmalloc_sync_all(void)
+static void vmalloc_sync(void)
 {
 	unsigned long address;
 
@@ -197,7 +197,7 @@
 		return;
 
 	for (address = VMALLOC_START & PMD_MASK;
-	     address >= TASK_SIZE_MAX && address < FIXADDR_TOP;
+	     address >= TASK_SIZE_MAX && address < VMALLOC_END;
 	     address += PMD_SIZE) {
 		struct page *page;
 
@@ -216,6 +216,16 @@
 	}
 }
 
+void vmalloc_sync_mappings(void)
+{
+	vmalloc_sync();
+}
+
+void vmalloc_sync_unmappings(void)
+{
+	vmalloc_sync();
+}
+
 /*
  * 32-bit:
  *
@@ -318,11 +328,23 @@
 
 #else /* CONFIG_X86_64: */
 
-void vmalloc_sync_all(void)
+void vmalloc_sync_mappings(void)
 {
+	/*
+	 * 64-bit mappings might allocate new p4d/pud pages
+	 * that need to be propagated to all tasks' PGDs.
+	 */
 	sync_global_pgds(VMALLOC_START & PGDIR_MASK, VMALLOC_END);
 }
 
+void vmalloc_sync_unmappings(void)
+{
+	/*
+	 * Unmappings never allocate or free p4d/pud pages.
+	 * No work is required here.
+	 */
+}
+
 /*
  * 64-bit:
  *
@@ -721,33 +743,8 @@
 	}
 
 	/* Are we prepared to handle this kernel fault? */
-	if (fixup_exception(regs, X86_TRAP_PF, error_code, address)) {
-		/*
-		 * Any interrupt that takes a fault gets the fixup. This makes
-		 * the below recursive fault logic only apply to a faults from
-		 * task context.
-		 */
-		if (in_interrupt())
-			return;
-
-		/*
-		 * Per the above we're !in_interrupt(), aka. task context.
-		 *
-		 * In this case we need to make sure we're not recursively
-		 * faulting through the emulate_vsyscall() logic.
-		 */
-		if (current->thread.sig_on_uaccess_err && signal) {
-			set_signal_archinfo(address, error_code);
-
-			/* XXX: hwpoison faults will set the wrong code. */
-			force_sig_fault(signal, si_code, (void __user *)address);
-		}
-
-		/*
-		 * Barring that, we can do the fixup and be happy.
-		 */
+	if (fixup_exception(regs, X86_TRAP_PF, error_code, address))
 		return;
-	}
 
 #ifdef CONFIG_VMAP_STACK
 	/*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/mm/ident_map.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/mm/ident_map.c
@@ -62,6 +62,7 @@
 			  unsigned long addr, unsigned long end)
 {
 	unsigned long next;
+	int result;
 
 	for (; addr < end; addr = next) {
 		p4d_t *p4d = p4d_page + p4d_index(addr);
@@ -73,13 +74,20 @@
 
 		if (p4d_present(*p4d)) {
 			pud = pud_offset(p4d, 0);
-			ident_pud_init(info, pud, addr, next);
+			result = ident_pud_init(info, pud, addr, next);
+			if (result)
+				return result;
+
 			continue;
 		}
 		pud = (pud_t *)info->alloc_pgt_page(info->context);
 		if (!pud)
 			return -ENOMEM;
-		ident_pud_init(info, pud, addr, next);
+
+		result = ident_pud_init(info, pud, addr, next);
+		if (result)
+			return result;
+
 		set_p4d(p4d, __p4d(__pa(pud) | info->kernpg_flag));
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/mm/init.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/mm/init.c
@@ -7,8 +7,10 @@
 #include <linux/swapops.h>
 #include <linux/kmemleak.h>
 #include <linux/sched/task.h>
+#include <linux/sched/mm.h>
 
 #include <asm/set_memory.h>
+#include <asm/cpu_device_id.h>
 #include <asm/e820/api.h>
 #include <asm/init.h>
 #include <asm/page.h>
@@ -25,6 +27,7 @@
 #include <asm/cpufeature.h>
 #include <asm/pti.h>
 #include <asm/text-patching.h>
+#include <asm/paravirt.h>
 
 /*
  * We need to define the tracepoints somewhere, and tlb.c
@@ -121,8 +124,6 @@
 	} else {
 		pfn = pgt_buf_end;
 		pgt_buf_end += num;
-		printk(KERN_DEBUG "BRK [%#010lx, %#010lx] PGTABLE\n",
-			pfn << PAGE_SHIFT, (pgt_buf_end << PAGE_SHIFT) - 1);
 	}
 
 	for (i = 0; i < num; i++) {
@@ -210,14 +211,44 @@
 	}
 }
 
+#define INTEL_MATCH(_model, ucode) { .vendor  = X86_VENDOR_INTEL,	\
+				     .family  = 6,			\
+				     .model = _model,			\
+				     .driver_data = ucode,		\
+				   }
+/*
+ * INVLPG may not properly flush Global entries on
+ * these CPUs.  New microcode fixes the issue.
+ */
+static const struct x86_cpu_id invlpg_miss_ids[] = {
+	INTEL_MATCH(INTEL_FAM6_ALDERLAKE,	0x2e),
+	INTEL_MATCH(INTEL_FAM6_ALDERLAKE_L,	0x42c),
+	INTEL_MATCH(INTEL_FAM6_ALDERLAKE_N,	0x11),
+	INTEL_MATCH(INTEL_FAM6_RAPTORLAKE,	0x118),
+	INTEL_MATCH(INTEL_FAM6_RAPTORLAKE_P,	0x4117),
+	INTEL_MATCH(INTEL_FAM6_RAPTORLAKE_S,	0x2e),
+	{}
+};
+
 static void setup_pcid(void)
 {
+	const struct x86_cpu_id *invlpg_miss_match;
+
 	if (!IS_ENABLED(CONFIG_X86_64))
 		return;
 
 	if (!boot_cpu_has(X86_FEATURE_PCID))
 		return;
 
+	invlpg_miss_match = x86_match_cpu(invlpg_miss_ids);
+
+	if (invlpg_miss_match &&
+	    boot_cpu_data.microcode < invlpg_miss_match->driver_data) {
+		pr_info("Incomplete global flushes, disabling PCID");
+		setup_clear_cpu_cap(X86_FEATURE_PCID);
+		return;
+	}
+
 	if (boot_cpu_has(X86_FEATURE_PGE)) {
 		/*
 		 * This can't be cr4_set_bits_and_update_boot() -- the
@@ -712,9 +743,12 @@
 	spinlock_t *ptl;
 	pte_t *ptep;
 
-	poking_mm = copy_init_mm();
+	poking_mm = mm_alloc();
 	BUG_ON(!poking_mm);
 
+	/* Xen PV guests need the PGD to be pinned. */
+	paravirt_arch_dup_mmap(NULL, poking_mm);
+
 	/*
 	 * Randomize the poking address, but make sure that the following page
 	 * will be mapped at the same PMD. We need 2 pages, so find space for 3,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/mm/init_32.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/mm/init_32.c
@@ -779,6 +779,9 @@
 	 * important here.
 	 */
 	set_highmem_pages_init();
+#ifdef CONFIG_HIGHMEM
+	set_default_mem_hotplug_zone(ZONE_HIGHMEM);
+#endif
 
 	/* this will put all low memory onto the freelists */
 	memblock_free_all();
@@ -865,10 +868,8 @@
 {
 	unsigned long start_pfn = start >> PAGE_SHIFT;
 	unsigned long nr_pages = size >> PAGE_SHIFT;
-	struct zone *zone;
 
-	zone = page_zone(pfn_to_page(start_pfn));
-	__remove_pages(zone, start_pfn, nr_pages, altmap);
+	__remove_pages(start_pfn, nr_pages, altmap);
 }
 #endif
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/mm/init_64.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/mm/init_64.c
@@ -1212,10 +1212,8 @@
 {
 	unsigned long start_pfn = start >> PAGE_SHIFT;
 	unsigned long nr_pages = size >> PAGE_SHIFT;
-	struct page *page = pfn_to_page(start_pfn) + vmem_altmap_offset(altmap);
-	struct zone *zone = page_zone(page);
 
-	__remove_pages(zone, start_pfn, nr_pages, altmap);
+	__remove_pages(start_pfn, nr_pages, altmap);
 	kernel_physical_mapping_remove(start, start + size);
 }
 #endif /* CONFIG_MEMORY_HOTPLUG */
@@ -1357,18 +1355,18 @@
 		return 0;
 
 	p4d = p4d_offset(pgd, addr);
-	if (p4d_none(*p4d))
+	if (!p4d_present(*p4d))
 		return 0;
 
 	pud = pud_offset(p4d, addr);
-	if (pud_none(*pud))
+	if (!pud_present(*pud))
 		return 0;
 
 	if (pud_large(*pud))
 		return pfn_valid(pud_pfn(*pud));
 
 	pmd = pmd_offset(pud, addr);
-	if (pmd_none(*pmd))
+	if (!pmd_present(*pmd))
 		return 0;
 
 	if (pmd_large(*pmd))
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/mm/ioremap.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/mm/ioremap.c
@@ -106,6 +106,24 @@
 	return 0;
 }
 
+/*
+ * The EFI runtime services data area is not covered by walk_mem_res(), but must
+ * be mapped encrypted when SEV is active.
+ */
+static void __ioremap_check_other(resource_size_t addr, struct ioremap_desc *desc)
+{
+	if (!sev_active())
+		return;
+
+	if (!IS_ENABLED(CONFIG_EFI))
+		return;
+
+	if (efi_mem_type(addr) == EFI_RUNTIME_SERVICES_DATA ||
+	    (efi_mem_type(addr) == EFI_BOOT_SERVICES_DATA &&
+	     efi_mem_attributes(addr) & EFI_MEMORY_RUNTIME))
+		desc->flags |= IORES_MAP_ENCRYPTED;
+}
+
 static int __ioremap_collect_map_flags(struct resource *res, void *arg)
 {
 	struct ioremap_desc *desc = arg;
@@ -124,6 +142,9 @@
  * To avoid multiple resource walks, this function walks resources marked as
  * IORESOURCE_MEM and IORESOURCE_BUSY and looking for system RAM and/or a
  * resource described not as IORES_DESC_NONE (e.g. IORES_DESC_ACPI_TABLES).
+ *
+ * After that, deal with misc other ranges in __ioremap_check_other() which do
+ * not fall into the above category.
  */
 static void __ioremap_check_mem(resource_size_t addr, unsigned long size,
 				struct ioremap_desc *desc)
@@ -135,6 +156,8 @@
 	memset(desc, 0, sizeof(struct ioremap_desc));
 
 	walk_mem_res(start, end, desc, __ioremap_collect_map_flags);
+
+	__ioremap_check_other(addr, desc);
 }
 
 /*
@@ -193,9 +216,15 @@
 	 * Mappings have to be page-aligned
 	 */
 	offset = phys_addr & ~PAGE_MASK;
-	phys_addr &= PHYSICAL_PAGE_MASK;
+	phys_addr &= PAGE_MASK;
 	size = PAGE_ALIGN(last_addr+1) - phys_addr;
 
+	/*
+	 * Mask out any bits not part of the actual physical
+	 * address, like memory encryption bits.
+	 */
+	phys_addr &= PHYSICAL_PAGE_MASK;
+
 	retval = reserve_memtype(phys_addr, (u64)phys_addr + size,
 						pcm, &new_pcm);
 	if (retval) {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/mm/kasan_init_64.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/mm/kasan_init_64.c
@@ -293,6 +293,18 @@
 	kasan_map_early_shadow(init_top_pgt);
 }
 
+void __init kasan_populate_shadow_for_vaddr(void *va, size_t size, int nid)
+{
+	unsigned long shadow_start, shadow_end;
+
+	shadow_start = (unsigned long)kasan_mem_to_shadow(va);
+	shadow_start = round_down(shadow_start, PAGE_SIZE);
+	shadow_end = (unsigned long)kasan_mem_to_shadow(va + size);
+	shadow_end = round_up(shadow_end, PAGE_SIZE);
+
+	kasan_populate_shadow(shadow_start, shadow_end, nid);
+}
+
 void __init kasan_init(void)
 {
 	int i;
@@ -356,9 +368,6 @@
 		kasan_mem_to_shadow((void *)PAGE_OFFSET + MAXMEM),
 		shadow_cpu_entry_begin);
 
-	kasan_populate_shadow((unsigned long)shadow_cpu_entry_begin,
-			      (unsigned long)shadow_cpu_entry_end, 0);
-
 	kasan_populate_early_shadow(shadow_cpu_entry_end,
 			kasan_mem_to_shadow((void *)__START_KERNEL_map));
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/mm/kaslr.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/mm/kaslr.c
@@ -182,11 +182,11 @@
 		set_p4d(p4d_tramp,
 			__p4d(_KERNPG_TABLE | __pa(pud_page_tramp)));
 
-		set_pgd(&trampoline_pgd_entry,
-			__pgd(_KERNPG_TABLE | __pa(p4d_page_tramp)));
+		trampoline_pgd_entry =
+			__pgd(_KERNPG_TABLE | __pa(p4d_page_tramp));
 	} else {
-		set_pgd(&trampoline_pgd_entry,
-			__pgd(_KERNPG_TABLE | __pa(pud_page_tramp)));
+		trampoline_pgd_entry =
+			__pgd(_KERNPG_TABLE | __pa(pud_page_tramp));
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/mm/mem_encrypt.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/mm/mem_encrypt.c
@@ -229,7 +229,7 @@
 	if (pgprot_val(old_prot) == pgprot_val(new_prot))
 		return;
 
-	pa = pfn << page_level_shift(level);
+	pa = pfn << PAGE_SHIFT;
 	size = page_level_size(level);
 
 	/*
@@ -375,6 +375,7 @@
 
 	return false;
 }
+EXPORT_SYMBOL_GPL(sev_active);
 
 /* Architecture __weak replacement functions */
 void __init mem_encrypt_free_decrypted_mem(void)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/mm/mem_encrypt_identity.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/mm/mem_encrypt_identity.c
@@ -27,6 +27,15 @@
 #undef CONFIG_PARAVIRT_XXL
 #undef CONFIG_PARAVIRT_SPINLOCKS
 
+/*
+ * This code runs before CPU feature bits are set. By default, the
+ * pgtable_l5_enabled() function uses bit X86_FEATURE_LA57 to determine if
+ * 5-level paging is active, so that won't work here. USE_EARLY_PGTABLE_L5
+ * is provided to handle this situation and, instead, use a variable that
+ * has been set by the early boot code.
+ */
+#define USE_EARLY_PGTABLE_L5
+
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/mem_encrypt.h>
@@ -45,8 +54,8 @@
 #define PMD_FLAGS_LARGE		(__PAGE_KERNEL_LARGE_EXEC & ~_PAGE_GLOBAL)
 
 #define PMD_FLAGS_DEC		PMD_FLAGS_LARGE
-#define PMD_FLAGS_DEC_WP	((PMD_FLAGS_DEC & ~_PAGE_CACHE_MASK) | \
-				 (_PAGE_PAT | _PAGE_PWT))
+#define PMD_FLAGS_DEC_WP	((PMD_FLAGS_DEC & ~_PAGE_LARGE_CACHE_MASK) | \
+				 (_PAGE_PAT_LARGE | _PAGE_PWT))
 
 #define PMD_FLAGS_ENC		(PMD_FLAGS_LARGE | _PAGE_ENC)
 
@@ -570,7 +579,8 @@
 	cmdline_ptr = (const char *)((u64)bp->hdr.cmd_line_ptr |
 				     ((u64)bp->ext_cmd_line_ptr << 32));
 
-	cmdline_find_option(cmdline_ptr, cmdline_arg, buffer, sizeof(buffer));
+	if (cmdline_find_option(cmdline_ptr, cmdline_arg, buffer, sizeof(buffer)) < 0)
+		return;
 
 	if (!strncmp(buffer, cmdline_on, sizeof(buffer)))
 		sme_me_mask = me_mask;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/mm/mmio-mod.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/mm/mmio-mod.c
@@ -372,7 +372,7 @@
 	int cpu;
 	int err;
 
-	if (downed_cpus == NULL &&
+	if (!cpumask_available(downed_cpus) &&
 	    !alloc_cpumask_var(&downed_cpus, GFP_KERNEL)) {
 		pr_notice("Failed to allocate mask\n");
 		goto out;
@@ -402,7 +402,7 @@
 	int cpu;
 	int err;
 
-	if (downed_cpus == NULL || cpumask_weight(downed_cpus) == 0)
+	if (!cpumask_available(downed_cpus) || cpumask_weight(downed_cpus) == 0)
 		return;
 	pr_notice("Re-enabling CPUs...\n");
 	for_each_cpu(cpu, downed_cpus) {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/mm/numa.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/mm/numa.c
@@ -581,13 +581,6 @@
 		if (start >= end)
 			continue;
 
-		/*
-		 * Don't confuse VM with a node that doesn't have the
-		 * minimum amount of memory:
-		 */
-		if (end && (end - start) < NODE_MIN_SIZE)
-			continue;
-
 		alloc_node_data(nid);
 	}
 
@@ -822,7 +815,7 @@
 		return;
 	}
 	mask = node_to_cpumask_map[node];
-	if (!mask) {
+	if (!cpumask_available(mask)) {
 		pr_err("node_to_cpumask_map[%i] NULL\n", node);
 		dump_stack();
 		return;
@@ -868,7 +861,7 @@
 		dump_stack();
 		return cpu_none_mask;
 	}
-	if (node_to_cpumask_map[node] == NULL) {
+	if (!cpumask_available(node_to_cpumask_map[node])) {
 		printk(KERN_WARNING
 			"cpumask_of_node(%d): no node_to_cpumask_map!\n",
 			node);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/mm/numa_emulation.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/mm/numa_emulation.c
@@ -321,7 +321,7 @@
 					      u64 addr, u64 max_addr, u64 size)
 {
 	return split_nodes_size_interleave_uniform(ei, pi, addr, max_addr, size,
-			0, NULL, NUMA_NO_NODE);
+			0, NULL, 0);
 }
 
 int __init setup_emu2phys_nid(int *dfl_phys_nid)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/mm/pageattr-test.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/mm/pageattr-test.c
@@ -184,7 +184,7 @@
 			break;
 
 		case 1:
-			err = change_page_attr_set(addrs, len[1], PAGE_CPA_TEST, 1);
+			err = change_page_attr_set(addrs, len[i], PAGE_CPA_TEST, 1);
 			break;
 
 		case 2:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/mm/pageattr.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/mm/pageattr.c
@@ -42,7 +42,8 @@
 	unsigned long	pfn;
 	unsigned int	flags;
 	unsigned int	force_split		: 1,
-			force_static_prot	: 1;
+			force_static_prot	: 1,
+			force_flush_all		: 1;
 	struct page	**pages;
 };
 
@@ -352,10 +353,10 @@
 		return;
 	}
 
-	if (cpa->numpages <= tlb_single_page_flush_ceiling)
-		on_each_cpu(__cpa_flush_tlb, cpa, 1);
-	else
+	if (cpa->force_flush_all || cpa->numpages > tlb_single_page_flush_ceiling)
 		flush_tlb_all();
+	else
+		on_each_cpu(__cpa_flush_tlb, cpa, 1);
 
 	if (!cache)
 		return;
@@ -1584,6 +1585,8 @@
 		alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY);
 		alias_cpa.curpage = 0;
 
+		cpa->force_flush_all = 1;
+
 		ret = __change_page_attr_set_clr(&alias_cpa, 0);
 		if (ret)
 			return ret;
@@ -1604,6 +1607,7 @@
 		alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY);
 		alias_cpa.curpage = 0;
 
+		cpa->force_flush_all = 1;
 		/*
 		 * The high mapping range is imprecise, so ignore the
 		 * return value.
@@ -1963,7 +1967,7 @@
 	/*
 	 * Before changing the encryption attribute, we need to flush caches.
 	 */
-	cpa_flush(&cpa, 1);
+	cpa_flush(&cpa, !this_cpu_has(X86_FEATURE_SME_COHERENT));
 
 	ret = __change_page_attr_set_clr(&cpa, 1);
 
@@ -2215,7 +2219,7 @@
 		.pgd = pgd,
 		.numpages = numpages,
 		.mask_set = __pgprot(0),
-		.mask_clr = __pgprot(0),
+		.mask_clr = __pgprot(~page_flags & (_PAGE_NX|_PAGE_RW)),
 		.flags = 0,
 	};
 
@@ -2224,12 +2228,6 @@
 	if (!(__supported_pte_mask & _PAGE_NX))
 		goto out;
 
-	if (!(page_flags & _PAGE_NX))
-		cpa.mask_clr = __pgprot(_PAGE_NX);
-
-	if (!(page_flags & _PAGE_RW))
-		cpa.mask_clr = __pgprot(_PAGE_RW);
-
 	if (!(page_flags & _PAGE_ENC))
 		cpa.mask_clr = pgprot_encrypted(cpa.mask_clr);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/mm/pat.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/mm/pat.c
@@ -34,6 +34,7 @@
 
 #include "pat_internal.h"
 #include "mm_internal.h"
+#include "../../mm/internal.h"	/* is_cow_mapping() */
 
 #undef pr_fmt
 #define pr_fmt(fmt) "" fmt
@@ -75,7 +76,7 @@
 static int __init pat_debug_setup(char *str)
 {
 	pat_debug_enable = 1;
-	return 0;
+	return 1;
 }
 __setup("debugpat", pat_debug_setup);
 
@@ -955,6 +956,38 @@
 		free_memtype(paddr, paddr + size);
 }
 
+static int get_pat_info(struct vm_area_struct *vma, resource_size_t *paddr,
+		pgprot_t *pgprot)
+{
+	unsigned long prot;
+
+	VM_WARN_ON_ONCE(!(vma->vm_flags & VM_PAT));
+
+	/*
+	 * We need the starting PFN and cachemode used for track_pfn_remap()
+	 * that covered the whole VMA. For most mappings, we can obtain that
+	 * information from the page tables. For COW mappings, we might now
+	 * suddenly have anon folios mapped and follow_phys() will fail.
+	 *
+	 * Fallback to using vma->vm_pgoff, see remap_pfn_range_notrack(), to
+	 * detect the PFN. If we need the cachemode as well, we're out of luck
+	 * for now and have to fail fork().
+	 */
+	if (!follow_phys(vma, vma->vm_start, 0, &prot, paddr)) {
+		if (pgprot)
+			*pgprot = __pgprot(prot);
+		return 0;
+	}
+	if (is_cow_mapping(vma->vm_flags)) {
+		if (pgprot)
+			return -EINVAL;
+		*paddr = (resource_size_t)vma->vm_pgoff << PAGE_SHIFT;
+		return 0;
+	}
+	WARN_ON_ONCE(1);
+	return -EINVAL;
+}
+
 /*
  * track_pfn_copy is called when vma that is covering the pfnmap gets
  * copied through copy_page_range().
@@ -965,20 +998,13 @@
 int track_pfn_copy(struct vm_area_struct *vma)
 {
 	resource_size_t paddr;
-	unsigned long prot;
 	unsigned long vma_size = vma->vm_end - vma->vm_start;
 	pgprot_t pgprot;
 
 	if (vma->vm_flags & VM_PAT) {
-		/*
-		 * reserve the whole chunk covered by vma. We need the
-		 * starting address and protection from pte.
-		 */
-		if (follow_phys(vma, vma->vm_start, 0, &prot, &paddr)) {
-			WARN_ON_ONCE(1);
+		if (get_pat_info(vma, &paddr, &pgprot))
 			return -EINVAL;
-		}
-		pgprot = __pgprot(prot);
+		/* reserve the whole chunk covered by vma. */
 		return reserve_pfn_range(paddr, vma_size, &pgprot, 1);
 	}
 
@@ -1053,7 +1079,6 @@
 		 unsigned long size)
 {
 	resource_size_t paddr;
-	unsigned long prot;
 
 	if (vma && !(vma->vm_flags & VM_PAT))
 		return;
@@ -1061,11 +1086,8 @@
 	/* free the chunk starting from pfn or the whole chunk */
 	paddr = (resource_size_t)pfn << PAGE_SHIFT;
 	if (!paddr && !size) {
-		if (follow_phys(vma, vma->vm_start, 0, &prot, &paddr)) {
-			WARN_ON_ONCE(1);
+		if (get_pat_info(vma, &paddr, NULL))
 			return;
-		}
-
 		size = vma->vm_end - vma->vm_start;
 	}
 	free_pfn_range(paddr, size);
@@ -1132,12 +1154,14 @@
 
 static void *memtype_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
+	kfree(v);
 	++*pos;
 	return memtype_get_idx(*pos);
 }
 
 static void memtype_seq_stop(struct seq_file *seq, void *v)
 {
+	kfree(v);
 }
 
 static int memtype_seq_show(struct seq_file *seq, void *v)
@@ -1146,7 +1170,6 @@
 
 	seq_printf(seq, "%s @ 0x%Lx-0x%Lx\n", cattr_name(print_entry->type),
 			print_entry->start, print_entry->end);
-	kfree(print_entry);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/mm/pgtable.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/mm/pgtable.c
@@ -643,8 +643,8 @@
 	fixmaps_set++;
 }
 
-void native_set_fixmap(enum fixed_addresses idx, phys_addr_t phys,
-		       pgprot_t flags)
+void native_set_fixmap(unsigned /* enum fixed_addresses */ idx,
+		       phys_addr_t phys, pgprot_t flags)
 {
 	/* Sanitize 'prot' against any unsupported bits: */
 	pgprot_val(flags) &= __default_kernel_pte_mask;
@@ -826,6 +826,8 @@
 	}
 
 	free_page((unsigned long)pmd_sv);
+
+	pgtable_pmd_page_dtor(virt_to_page(pmd));
 	free_page((unsigned long)pmd);
 
 	return 1;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/mm/pkeys.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/mm/pkeys.c
@@ -10,7 +10,6 @@
 
 #include <asm/cpufeature.h>             /* boot_cpu_has, ...            */
 #include <asm/mmu_context.h>            /* vma_pkey()                   */
-#include <asm/fpu/internal.h>		/* init_fpstate			*/
 
 int __execute_only_pkey(struct mm_struct *mm)
 {
@@ -154,7 +153,6 @@
 static ssize_t init_pkru_write_file(struct file *file,
 		 const char __user *user_buf, size_t count, loff_t *ppos)
 {
-	struct pkru_state *pk;
 	char buf[32];
 	ssize_t len;
 	u32 new_init_pkru;
@@ -177,10 +175,6 @@
 		return -EINVAL;
 
 	WRITE_ONCE(init_pkru_value, new_init_pkru);
-	pk = get_xsave_addr(&init_fpstate.xsave, XFEATURE_PKRU);
-	if (!pk)
-		return -EINVAL;
-	pk->pkru = new_init_pkru;
 	return count;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/mm/pti.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/mm/pti.c
@@ -375,14 +375,14 @@
 			 */
 			*target_pmd = *pmd;
 
-			addr += PMD_SIZE;
+			addr = round_up(addr + 1, PMD_SIZE);
 
 		} else if (level == PTI_CLONE_PTE) {
 
 			/* Walk the page-table down to the pte level */
 			pte = pte_offset_kernel(pmd, addr);
 			if (pte_none(*pte)) {
-				addr += PAGE_SIZE;
+				addr = round_up(addr + 1, PAGE_SIZE);
 				continue;
 			}
 
@@ -402,7 +402,7 @@
 			/* Clone the PTE */
 			*target_pte = *pte;
 
-			addr += PAGE_SIZE;
+			addr = round_up(addr + 1, PAGE_SIZE);
 
 		} else {
 			BUG();
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/mm/tlb.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/mm/tlb.c
@@ -327,8 +327,14 @@
 	/*
 	 * The membarrier system call requires a full memory barrier and
 	 * core serialization before returning to user-space, after
-	 * storing to rq->curr. Writing to CR3 provides that full
-	 * memory barrier and core serializing instruction.
+	 * storing to rq->curr, when changing mm.  This is because
+	 * membarrier() sends IPIs to all CPUs that are in the target mm
+	 * to make them issue memory barriers.  However, if another CPU
+	 * switches to/from the target mm concurrently with
+	 * membarrier(), it can cause that CPU not to receive an IPI
+	 * when it really should issue a memory barrier.  Writing to CR3
+	 * provides that full memory barrier and core serializing
+	 * instruction.
 	 */
 	if (real_prev == next) {
 		VM_WARN_ON(this_cpu_read(cpu_tlbstate.ctxs[prev_asid].ctx_id) !=
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/net/bpf_jit_comp.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/net/bpf_jit_comp.c
@@ -138,6 +138,19 @@
 			     BIT(BPF_REG_AX));
 }
 
+/*
+ * is_ereg_8l() == true if BPF register 'reg' is mapped to access x86-64
+ * lower 8-bit registers dil,sil,bpl,spl,r8b..r15b, which need extra byte
+ * of encoding. al,cl,dl,bl have simpler encoding.
+ */
+static bool is_ereg_8l(u32 reg)
+{
+	return is_ereg(reg) ||
+	    (1 << reg) & (BIT(BPF_REG_1) |
+			  BIT(BPF_REG_2) |
+			  BIT(BPF_REG_FP));
+}
+
 static bool is_axreg(u32 reg)
 {
 	return reg == BPF_REG_0;
@@ -715,6 +728,13 @@
 			}
 			break;
 
+			/* speculation barrier */
+		case BPF_ST | BPF_NOSPEC:
+			if (boot_cpu_has(X86_FEATURE_XMM2))
+				/* Emit 'lfence' */
+				EMIT3(0x0F, 0xAE, 0xE8);
+			break;
+
 			/* ST: *(u8*)(dst_reg + off) = imm */
 		case BPF_ST | BPF_MEM | BPF_B:
 			if (is_ereg(dst_reg))
@@ -748,9 +768,8 @@
 			/* STX: *(u8*)(dst_reg + off) = src_reg */
 		case BPF_STX | BPF_MEM | BPF_B:
 			/* Emit 'mov byte ptr [rax + off], al' */
-			if (is_ereg(dst_reg) || is_ereg(src_reg) ||
-			    /* We have to add extra byte for x86 SIL, DIL regs */
-			    src_reg == BPF_REG_1 || src_reg == BPF_REG_2)
+			if (is_ereg(dst_reg) || is_ereg_8l(src_reg))
+				/* Add extra byte for eregs or SIL,DIL,BPL in src_reg */
 				EMIT2(add_2mod(0x40, dst_reg, src_reg), 0x88);
 			else
 				EMIT1(0x88);
@@ -1038,7 +1057,16 @@
 		}
 
 		if (image) {
-			if (unlikely(proglen + ilen > oldproglen)) {
+			/*
+			 * When populating the image, assert that:
+			 *
+			 *  i) We do not write beyond the allocated space, and
+			 * ii) addrs[i] did not change from the prior run, in order
+			 *     to validate assumptions made for computing branch
+			 *     displacements.
+			 */
+			if (unlikely(proglen + ilen > oldproglen ||
+				     proglen + ilen != addrs[i])) {
 				pr_err("bpf_jit: fatal error\n");
 				return -EFAULT;
 			}
@@ -1106,7 +1134,7 @@
 		extra_pass = true;
 		goto skip_init_addrs;
 	}
-	addrs = kmalloc_array(prog->len + 1, sizeof(*addrs), GFP_KERNEL);
+	addrs = kvmalloc_array(prog->len + 1, sizeof(*addrs), GFP_KERNEL);
 	if (!addrs) {
 		prog = orig_prog;
 		goto out_addrs;
@@ -1183,7 +1211,7 @@
 		if (image)
 			bpf_prog_fill_jited_linfo(prog, addrs + 1);
 out_addrs:
-		kfree(addrs);
+		kvfree(addrs);
 		kfree(jit_data);
 		prog->aux->jit_data = NULL;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/net/bpf_jit_comp32.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/net/bpf_jit_comp32.c
@@ -1705,6 +1705,12 @@
 			i++;
 			break;
 		}
+		/* speculation barrier */
+		case BPF_ST | BPF_NOSPEC:
+			if (boot_cpu_has(X86_FEATURE_XMM2))
+				/* Emit 'lfence' */
+				EMIT3(0x0F, 0xAE, 0xE8);
+			break;
 		/* ST: *(u8*)(dst_reg + off) = imm */
 		case BPF_ST | BPF_MEM | BPF_H:
 		case BPF_ST | BPF_MEM | BPF_B:
@@ -1847,14 +1853,16 @@
 			case BPF_B:
 			case BPF_H:
 			case BPF_W:
-				if (!bpf_prog->aux->verifier_zext)
+				if (bpf_prog->aux->verifier_zext)
 					break;
 				if (dstk) {
 					EMIT3(0xC7, add_1reg(0x40, IA32_EBP),
 					      STACK_VAR(dst_hi));
 					EMIT(0x0, 4);
 				} else {
-					EMIT3(0xC7, add_1reg(0xC0, dst_hi), 0);
+					/* xor dst_hi,dst_hi */
+					EMIT2(0x33,
+					      add_2reg(0xC0, dst_hi, dst_hi));
 				}
 				break;
 			case BPF_DW:
@@ -2013,8 +2021,8 @@
 		case BPF_JMP | BPF_JSET | BPF_X:
 		case BPF_JMP32 | BPF_JSET | BPF_X: {
 			bool is_jmp64 = BPF_CLASS(insn->code) == BPF_JMP;
-			u8 dreg_lo = dstk ? IA32_EAX : dst_lo;
-			u8 dreg_hi = dstk ? IA32_EDX : dst_hi;
+			u8 dreg_lo = IA32_EAX;
+			u8 dreg_hi = IA32_EDX;
 			u8 sreg_lo = sstk ? IA32_ECX : src_lo;
 			u8 sreg_hi = sstk ? IA32_EBX : src_hi;
 
@@ -2026,6 +2034,13 @@
 					      add_2reg(0x40, IA32_EBP,
 						       IA32_EDX),
 					      STACK_VAR(dst_hi));
+			} else {
+				/* mov dreg_lo,dst_lo */
+				EMIT2(0x89, add_2reg(0xC0, dreg_lo, dst_lo));
+				if (is_jmp64)
+					/* mov dreg_hi,dst_hi */
+					EMIT2(0x89,
+					      add_2reg(0xC0, dreg_hi, dst_hi));
 			}
 
 			if (sstk) {
@@ -2039,17 +2054,19 @@
 			}
 			/* and dreg_lo,sreg_lo */
 			EMIT2(0x23, add_2reg(0xC0, sreg_lo, dreg_lo));
-			/* and dreg_hi,sreg_hi */
-			EMIT2(0x23, add_2reg(0xC0, sreg_hi, dreg_hi));
-			/* or dreg_lo,dreg_hi */
-			EMIT2(0x09, add_2reg(0xC0, dreg_lo, dreg_hi));
+			if (is_jmp64) {
+				/* and dreg_hi,sreg_hi */
+				EMIT2(0x23, add_2reg(0xC0, sreg_hi, dreg_hi));
+				/* or dreg_lo,dreg_hi */
+				EMIT2(0x09, add_2reg(0xC0, dreg_lo, dreg_hi));
+			}
 			goto emit_cond_jmp;
 		}
 		case BPF_JMP | BPF_JSET | BPF_K:
 		case BPF_JMP32 | BPF_JSET | BPF_K: {
 			bool is_jmp64 = BPF_CLASS(insn->code) == BPF_JMP;
-			u8 dreg_lo = dstk ? IA32_EAX : dst_lo;
-			u8 dreg_hi = dstk ? IA32_EDX : dst_hi;
+			u8 dreg_lo = IA32_EAX;
+			u8 dreg_hi = IA32_EDX;
 			u8 sreg_lo = IA32_ECX;
 			u8 sreg_hi = IA32_EBX;
 			u32 hi;
@@ -2062,6 +2079,13 @@
 					      add_2reg(0x40, IA32_EBP,
 						       IA32_EDX),
 					      STACK_VAR(dst_hi));
+			} else {
+				/* mov dreg_lo,dst_lo */
+				EMIT2(0x89, add_2reg(0xC0, dreg_lo, dst_lo));
+				if (is_jmp64)
+					/* mov dreg_hi,dst_hi */
+					EMIT2(0x89,
+					      add_2reg(0xC0, dreg_hi, dst_hi));
 			}
 
 			/* mov ecx,imm32 */
@@ -2260,7 +2284,16 @@
 		}
 
 		if (image) {
-			if (unlikely(proglen + ilen > oldproglen)) {
+			/*
+			 * When populating the image, assert that:
+			 *
+			 *  i) We do not write beyond the allocated space, and
+			 * ii) addrs[i] did not change from the prior run, in order
+			 *     to validate assumptions made for computing branch
+			 *     displacements.
+			 */
+			if (unlikely(proglen + ilen > oldproglen ||
+				     proglen + ilen != addrs[i])) {
 				pr_err("bpf_jit: fatal error\n");
 				return -EFAULT;
 			}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/pci/common.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/pci/common.c
@@ -33,6 +33,7 @@
 #endif
 int pcibios_last_bus = -1;
 unsigned long pirq_table_addr;
+unsigned int pci_early_clear_msi;
 const struct pci_raw_ops *__read_mostly raw_pci_ops;
 const struct pci_raw_ops *__read_mostly raw_pci_ext_ops;
 
@@ -605,6 +606,9 @@
 	} else if (!strcmp(str, "skip_isa_align")) {
 		pci_probe |= PCI_CAN_SKIP_ISA_ALIGN;
 		return NULL;
+	} else if (!strcmp(str, "clearmsi")) {
+		pci_early_clear_msi = 1;
+		return NULL;
 	} else if (!strcmp(str, "noioapicquirk")) {
 		noioapicquirk = 1;
 		return NULL;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/pci/early.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/pci/early.c
@@ -51,6 +51,31 @@
 	outw(val, 0xcfc + (offset&2));
 }
 
+u32 pci_early_find_cap(int bus, int slot, int func, int cap)
+{
+	int bytes;
+	u8 pos;
+
+	if (!(read_pci_config_16(bus, slot, func, PCI_STATUS) &
+						PCI_STATUS_CAP_LIST))
+		return 0;
+
+	pos = read_pci_config_byte(bus, slot, func, PCI_CAPABILITY_LIST);
+	for (bytes = 0; bytes < 48 && pos >= 0x40; bytes++) {
+		u8 id;
+
+		pos &= ~3;
+		id = read_pci_config_byte(bus, slot, func, pos+PCI_CAP_LIST_ID);
+		if (id == 0xff)
+			break;
+		if (id == cap)
+			return pos;
+		pos = read_pci_config_byte(bus, slot, func,
+						pos+PCI_CAP_LIST_NEXT);
+	}
+	return 0;
+}
+
 int early_pci_allowed(void)
 {
 	return (pci_probe & (PCI_PROBE_CONF1|PCI_PROBE_NOEARLY)) ==
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/pci/fixup.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/pci/fixup.c
@@ -7,6 +7,7 @@
 #include <linux/dmi.h>
 #include <linux/pci.h>
 #include <linux/vgaarb.h>
+#include <asm/amd_nb.h>
 #include <asm/hpet.h>
 #include <asm/pci_x86.h>
 
@@ -572,6 +573,10 @@
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6f60, pci_invalid_bar);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fa0, pci_invalid_bar);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fc0, pci_invalid_bar);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0xa1ec, pci_invalid_bar);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0xa1ed, pci_invalid_bar);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0xa26c, pci_invalid_bar);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0xa26d, pci_invalid_bar);
 
 /*
  * Device [1022:7808]
@@ -589,6 +594,17 @@
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x7808, pci_fixup_amd_ehci_pme);
 
 /*
+ * Device [1022:7914]
+ * When in D0, PME# doesn't get asserted when plugging USB 2.0 device.
+ */
+static void pci_fixup_amd_fch_xhci_pme(struct pci_dev *dev)
+{
+	dev_info(&dev->dev, "PME# does not work under D0, disabling it\n");
+	dev->pme_support &= ~(PCI_PM_CAP_PME_D0 >> PCI_PM_CAP_PME_SHIFT);
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x7914, pci_fixup_amd_fch_xhci_pme);
+
+/*
  * Apple MacBook Pro: Avoid [mem 0x7fa00000-0x7fbfffff]
  *
  * Using the [mem 0x7fa00000-0x7fbfffff] region, e.g., by assigning it to
@@ -764,4 +780,68 @@
 DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, 0x15b1, pci_amd_enable_64bit_bar);
 DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, 0x1601, pci_amd_enable_64bit_bar);
 
+#define RS690_LOWER_TOP_OF_DRAM2	0x30
+#define RS690_LOWER_TOP_OF_DRAM2_VALID	0x1
+#define RS690_UPPER_TOP_OF_DRAM2	0x31
+#define RS690_HTIU_NB_INDEX		0xA8
+#define RS690_HTIU_NB_INDEX_WR_ENABLE	0x100
+#define RS690_HTIU_NB_DATA		0xAC
+
+/*
+ * Some BIOS implementations support RAM above 4GB, but do not configure the
+ * PCI host to respond to bus master accesses for these addresses. These
+ * implementations set the TOP_OF_DRAM_SLOT1 register correctly, so PCI DMA
+ * works as expected for addresses below 4GB.
+ *
+ * Reference: "AMD RS690 ASIC Family Register Reference Guide" (pg. 2-57)
+ * https://www.amd.com/system/files/TechDocs/43372_rs690_rrg_3.00o.pdf
+ */
+static void rs690_fix_64bit_dma(struct pci_dev *pdev)
+{
+	u32 val = 0;
+	phys_addr_t top_of_dram = __pa(high_memory - 1) + 1;
+
+	if (top_of_dram <= (1ULL << 32))
+		return;
+
+	pci_write_config_dword(pdev, RS690_HTIU_NB_INDEX,
+				RS690_LOWER_TOP_OF_DRAM2);
+	pci_read_config_dword(pdev, RS690_HTIU_NB_DATA, &val);
+
+	if (val)
+		return;
+
+	pci_info(pdev, "Adjusting top of DRAM to %pa for 64-bit DMA support\n", &top_of_dram);
+
+	pci_write_config_dword(pdev, RS690_HTIU_NB_INDEX,
+		RS690_UPPER_TOP_OF_DRAM2 | RS690_HTIU_NB_INDEX_WR_ENABLE);
+	pci_write_config_dword(pdev, RS690_HTIU_NB_DATA, top_of_dram >> 32);
+
+	pci_write_config_dword(pdev, RS690_HTIU_NB_INDEX,
+		RS690_LOWER_TOP_OF_DRAM2 | RS690_HTIU_NB_INDEX_WR_ENABLE);
+	pci_write_config_dword(pdev, RS690_HTIU_NB_DATA,
+		top_of_dram | RS690_LOWER_TOP_OF_DRAM2_VALID);
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x7910, rs690_fix_64bit_dma);
+
+#endif
+
+#ifdef CONFIG_AMD_NB
+
+#define AMD_15B8_RCC_DEV2_EPF0_STRAP2                                  0x10136008
+#define AMD_15B8_RCC_DEV2_EPF0_STRAP2_NO_SOFT_RESET_DEV2_F0_MASK       0x00000080L
+
+static void quirk_clear_strap_no_soft_reset_dev2_f0(struct pci_dev *dev)
+{
+	u32 data;
+
+	if (!amd_smn_read(0, AMD_15B8_RCC_DEV2_EPF0_STRAP2, &data)) {
+		data &= ~AMD_15B8_RCC_DEV2_EPF0_STRAP2_NO_SOFT_RESET_DEV2_F0_MASK;
+		if (amd_smn_write(0, AMD_15B8_RCC_DEV2_EPF0_STRAP2, data))
+			pci_err(dev, "Failed to write data 0x%x\n", data);
+	} else {
+		pci_err(dev, "Failed to read data\n");
+	}
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x15b8, quirk_clear_strap_no_soft_reset_dev2_f0);
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/pci/intel_mid_pci.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/pci/intel_mid_pci.c
@@ -33,6 +33,7 @@
 #include <asm/hw_irq.h>
 #include <asm/io_apic.h>
 #include <asm/intel-mid.h>
+#include <asm/acpi.h>
 
 #define PCIE_CAP_OFFSET	0x100
 
@@ -222,9 +223,9 @@
 		return 0;
 
 	ret = pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &gsi);
-	if (ret < 0) {
+	if (ret) {
 		dev_warn(&dev->dev, "Failed to read interrupt line: %d\n", ret);
-		return ret;
+		return pcibios_err_to_errno(ret);
 	}
 
 	switch (intel_mid_identify_cpu()) {
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/pci/xen.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/pci/xen.c
@@ -26,6 +26,7 @@
 #include <asm/xen/pci.h>
 #include <asm/xen/cpuid.h>
 #include <asm/apic.h>
+#include <asm/acpi.h>
 #include <asm/i8259.h>
 
 static int xen_pcifront_enable_irq(struct pci_dev *dev)
@@ -36,10 +37,10 @@
 	u8 gsi;
 
 	rc = pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &gsi);
-	if (rc < 0) {
+	if (rc) {
 		dev_warn(&dev->dev, "Xen PCI: failed to read interrupt line: %d\n",
 			 rc);
-		return rc;
+		return pcibios_err_to_errno(rc);
 	}
 	/* In PV DomU the Xen PCI backend puts the PIRQ in the interrupt line.*/
 	pirq = gsi;
@@ -441,6 +442,11 @@
 
 	x86_msi.setup_msi_irqs = xen_hvm_setup_msi_irqs;
 	x86_msi.teardown_msi_irq = xen_teardown_msi_irq;
+	/*
+	 * With XEN PIRQ/Eventchannels in use PCI/MSI[-X] masking is solely
+	 * controlled by the hypervisor.
+	 */
+	pci_msi_ignore_mask = 1;
 }
 #endif
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/platform/efi/efi.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/platform/efi/efi.c
@@ -85,6 +85,11 @@
 #ifdef CONFIG_EFI_RCI2_TABLE
 	&rci2_table_phys,
 #endif
+	&efi.tpm_log,
+	&efi.tpm_final_log,
+#ifdef CONFIG_LOAD_UEFI_KEYS
+	&efi.mokvar_table,
+#endif
 };
 
 u64 efi_setup;		/* efi setup_data physical address */
@@ -504,7 +509,6 @@
 	efi_char16_t *c16;
 	char vendor[100] = "unknown";
 	int i = 0;
-	void *tmp;
 
 #ifdef CONFIG_X86_32
 	if (boot_params.efi_info.efi_systab_hi ||
@@ -529,14 +533,16 @@
 	/*
 	 * Show what we know for posterity
 	 */
-	c16 = tmp = early_memremap(efi.systab->fw_vendor, 2);
+	c16 = early_memremap_ro(efi.systab->fw_vendor,
+				sizeof(vendor) * sizeof(efi_char16_t));
 	if (c16) {
-		for (i = 0; i < sizeof(vendor) - 1 && *c16; ++i)
-			vendor[i] = *c16++;
+		for (i = 0; i < sizeof(vendor) - 1 && c16[i]; ++i)
+			vendor[i] = c16[i];
 		vendor[i] = '\0';
-	} else
+		early_memunmap(c16, sizeof(vendor) * sizeof(efi_char16_t));
+	} else {
 		pr_err("Could not map the firmware vendor!\n");
-	early_memunmap(tmp, 2);
+	}
 
 	pr_info("EFI v%u.%.02u by %s\n",
 		efi.systab->hdr.revision >> 16,
@@ -953,16 +959,14 @@
 
 	if (efi_alloc_page_tables()) {
 		pr_err("Failed to allocate EFI page tables\n");
-		clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
-		return;
+		goto err;
 	}
 
 	efi_merge_regions();
 	new_memmap = efi_map_regions(&count, &pg_shift);
 	if (!new_memmap) {
 		pr_err("Error reallocating memory, EFI runtime non-functional!\n");
-		clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
-		return;
+		goto err;
 	}
 
 	pa = __pa(new_memmap);
@@ -976,8 +980,7 @@
 
 	if (efi_memmap_init_late(pa, efi.memmap.desc_size * count)) {
 		pr_err("Failed to remap late EFI memory map\n");
-		clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
-		return;
+		goto err;
 	}
 
 	if (efi_enabled(EFI_DBG)) {
@@ -985,12 +988,11 @@
 		efi_print_memmap();
 	}
 
-	BUG_ON(!efi.systab);
+	if (WARN_ON(!efi.systab))
+		goto err;
 
-	if (efi_setup_page_tables(pa, 1 << pg_shift)) {
-		clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
-		return;
-	}
+	if (efi_setup_page_tables(pa, 1 << pg_shift))
+		goto err;
 
 	efi_sync_low_kernel_mappings();
 
@@ -1010,9 +1012,9 @@
 	}
 
 	if (status != EFI_SUCCESS) {
-		pr_alert("Unable to switch EFI into virtual mode (status=%lx)!\n",
-			 status);
-		panic("EFI call to SetVirtualAddressMap() failed!");
+		pr_err("Unable to switch EFI into virtual mode (status=%lx)!\n",
+		       status);
+		goto err;
 	}
 
 	efi_free_boot_services();
@@ -1041,6 +1043,10 @@
 
 	/* clean DUMMY object */
 	efi_delete_dummy_variable();
+	return;
+
+err:
+	clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
 }
 
 void __init efi_enter_virtual_mode(void)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/platform/efi/efi_64.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/platform/efi/efi_64.c
@@ -217,28 +217,30 @@
 	gfp_mask = GFP_KERNEL | __GFP_ZERO;
 	efi_pgd = (pgd_t *)__get_free_pages(gfp_mask, PGD_ALLOCATION_ORDER);
 	if (!efi_pgd)
-		return -ENOMEM;
+		goto fail;
 
 	pgd = efi_pgd + pgd_index(EFI_VA_END);
 	p4d = p4d_alloc(&init_mm, pgd, EFI_VA_END);
-	if (!p4d) {
-		free_page((unsigned long)efi_pgd);
-		return -ENOMEM;
-	}
+	if (!p4d)
+		goto free_pgd;
 
 	pud = pud_alloc(&init_mm, p4d, EFI_VA_END);
-	if (!pud) {
-		if (pgtable_l5_enabled())
-			free_page((unsigned long) pgd_page_vaddr(*pgd));
-		free_pages((unsigned long)efi_pgd, PGD_ALLOCATION_ORDER);
-		return -ENOMEM;
-	}
+	if (!pud)
+		goto free_p4d;
 
 	efi_mm.pgd = efi_pgd;
 	mm_init_cpumask(&efi_mm);
 	init_new_context(NULL, &efi_mm);
 
 	return 0;
+
+free_p4d:
+	if (pgtable_l5_enabled())
+		free_page((unsigned long)pgd_page_vaddr(*pgd));
+free_pgd:
+	free_pages((unsigned long)efi_pgd, PGD_ALLOCATION_ORDER);
+fail:
+	return -ENOMEM;
 }
 
 /*
@@ -316,7 +318,7 @@
 static inline phys_addr_t
 virt_to_phys_or_null_size(void *va, unsigned long size)
 {
-	bool bad_size;
+	phys_addr_t pa;
 
 	if (!va)
 		return 0;
@@ -324,16 +326,13 @@
 	if (virt_addr_valid(va))
 		return virt_to_phys(va);
 
-	/*
-	 * A fully aligned variable on the stack is guaranteed not to
-	 * cross a page bounary. Try to catch strings on the stack by
-	 * checking that 'size' is a power of two.
-	 */
-	bad_size = size > PAGE_SIZE || !is_power_of_2(size);
+	pa = slow_virt_to_phys(va);
 
-	WARN_ON(!IS_ALIGNED((unsigned long)va, size) || bad_size);
+	/* check if the object crosses a page boundary */
+	if (WARN_ON((pa ^ (pa + size - 1)) & PAGE_MASK))
+		return 0;
 
-	return slow_virt_to_phys(va);
+	return pa;
 }
 
 #define virt_to_phys_or_null(addr)				\
@@ -392,11 +391,12 @@
 		return 0;
 
 	page = alloc_page(GFP_KERNEL|__GFP_DMA32);
-	if (!page)
-		panic("Unable to allocate EFI runtime stack < 4GB\n");
+	if (!page) {
+		pr_err("Unable to allocate EFI runtime stack < 4GB\n");
+		return 1;
+	}
 
-	efi_scratch.phys_stack = virt_to_phys(page_address(page));
-	efi_scratch.phys_stack += PAGE_SIZE; /* stack grows down */
+	efi_scratch.phys_stack = page_to_phys(page + 1); /* stack grows down */
 
 	npages = (_etext - _text) >> PAGE_SHIFT;
 	text = __pa(_text);
@@ -790,6 +790,8 @@
 efi_thunk_get_variable(efi_char16_t *name, efi_guid_t *vendor,
 		       u32 *attr, unsigned long *data_size, void *data)
 {
+	u8 buf[24] __aligned(8);
+	efi_guid_t *vnd = PTR_ALIGN((efi_guid_t *)buf, sizeof(*vnd));
 	efi_status_t status;
 	u32 phys_name, phys_vendor, phys_attr;
 	u32 phys_data_size, phys_data;
@@ -797,14 +799,19 @@
 
 	spin_lock_irqsave(&efi_runtime_lock, flags);
 
+	*vnd = *vendor;
+
 	phys_data_size = virt_to_phys_or_null(data_size);
-	phys_vendor = virt_to_phys_or_null(vendor);
+	phys_vendor = virt_to_phys_or_null(vnd);
 	phys_name = virt_to_phys_or_null_size(name, efi_name_size(name));
 	phys_attr = virt_to_phys_or_null(attr);
 	phys_data = virt_to_phys_or_null_size(data, *data_size);
 
-	status = efi_thunk(get_variable, phys_name, phys_vendor,
-			   phys_attr, phys_data_size, phys_data);
+	if (!phys_name || (data && !phys_data))
+		status = EFI_INVALID_PARAMETER;
+	else
+		status = efi_thunk(get_variable, phys_name, phys_vendor,
+				   phys_attr, phys_data_size, phys_data);
 
 	spin_unlock_irqrestore(&efi_runtime_lock, flags);
 
@@ -815,19 +822,25 @@
 efi_thunk_set_variable(efi_char16_t *name, efi_guid_t *vendor,
 		       u32 attr, unsigned long data_size, void *data)
 {
+	u8 buf[24] __aligned(8);
+	efi_guid_t *vnd = PTR_ALIGN((efi_guid_t *)buf, sizeof(*vnd));
 	u32 phys_name, phys_vendor, phys_data;
 	efi_status_t status;
 	unsigned long flags;
 
 	spin_lock_irqsave(&efi_runtime_lock, flags);
 
+	*vnd = *vendor;
+
 	phys_name = virt_to_phys_or_null_size(name, efi_name_size(name));
-	phys_vendor = virt_to_phys_or_null(vendor);
+	phys_vendor = virt_to_phys_or_null(vnd);
 	phys_data = virt_to_phys_or_null_size(data, data_size);
 
-	/* If data_size is > sizeof(u32) we've got problems */
-	status = efi_thunk(set_variable, phys_name, phys_vendor,
-			   attr, data_size, phys_data);
+	if (!phys_name || (data && !phys_data))
+		status = EFI_INVALID_PARAMETER;
+	else
+		status = efi_thunk(set_variable, phys_name, phys_vendor,
+				   attr, data_size, phys_data);
 
 	spin_unlock_irqrestore(&efi_runtime_lock, flags);
 
@@ -839,6 +852,8 @@
 				   u32 attr, unsigned long data_size,
 				   void *data)
 {
+	u8 buf[24] __aligned(8);
+	efi_guid_t *vnd = PTR_ALIGN((efi_guid_t *)buf, sizeof(*vnd));
 	u32 phys_name, phys_vendor, phys_data;
 	efi_status_t status;
 	unsigned long flags;
@@ -846,13 +861,17 @@
 	if (!spin_trylock_irqsave(&efi_runtime_lock, flags))
 		return EFI_NOT_READY;
 
+	*vnd = *vendor;
+
 	phys_name = virt_to_phys_or_null_size(name, efi_name_size(name));
-	phys_vendor = virt_to_phys_or_null(vendor);
+	phys_vendor = virt_to_phys_or_null(vnd);
 	phys_data = virt_to_phys_or_null_size(data, data_size);
 
-	/* If data_size is > sizeof(u32) we've got problems */
-	status = efi_thunk(set_variable, phys_name, phys_vendor,
-			   attr, data_size, phys_data);
+	if (!phys_name || (data && !phys_data))
+		status = EFI_INVALID_PARAMETER;
+	else
+		status = efi_thunk(set_variable, phys_name, phys_vendor,
+				   attr, data_size, phys_data);
 
 	spin_unlock_irqrestore(&efi_runtime_lock, flags);
 
@@ -864,21 +883,29 @@
 			    efi_char16_t *name,
 			    efi_guid_t *vendor)
 {
+	u8 buf[24] __aligned(8);
+	efi_guid_t *vnd = PTR_ALIGN((efi_guid_t *)buf, sizeof(*vnd));
 	efi_status_t status;
 	u32 phys_name_size, phys_name, phys_vendor;
 	unsigned long flags;
 
 	spin_lock_irqsave(&efi_runtime_lock, flags);
 
+	*vnd = *vendor;
+
 	phys_name_size = virt_to_phys_or_null(name_size);
-	phys_vendor = virt_to_phys_or_null(vendor);
+	phys_vendor = virt_to_phys_or_null(vnd);
 	phys_name = virt_to_phys_or_null_size(name, *name_size);
 
-	status = efi_thunk(get_next_variable, phys_name_size,
-			   phys_name, phys_vendor);
+	if (!phys_name)
+		status = EFI_INVALID_PARAMETER;
+	else
+		status = efi_thunk(get_next_variable, phys_name_size,
+				   phys_name, phys_vendor);
 
 	spin_unlock_irqrestore(&efi_runtime_lock, flags);
 
+	*vendor = *vnd;
 	return status;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/platform/efi/efi_stub_32.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/platform/efi/efi_stub_32.S
@@ -8,6 +8,7 @@
 
 #include <linux/linkage.h>
 #include <asm/page_types.h>
+#include <asm/nospec-branch.h>
 
 /*
  * efi_call_phys(void *, ...) is a function with variable parameters.
@@ -39,6 +40,7 @@
 	 */
 	movl	$1f, %edx
 	subl	$__PAGE_OFFSET, %edx
+	ANNOTATE_RETPOLINE_SAFE /* FRBS */
 	jmp	*%edx
 1:
 
@@ -74,6 +76,7 @@
 	/*
 	 * 5. Call the physical function.
 	 */
+	ANNOTATE_RETPOLINE_SAFE /* FRBS */
 	jmp	*%ecx
 
 2:
@@ -96,6 +99,7 @@
 	 * adding EIP with PAGE_OFFSET.
 	 */
 	movl	$1f, %edx
+	ANNOTATE_RETPOLINE_SAFE /* FRBS */
 	jmp	*%edx
 1:
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/platform/efi/efi_stub_64.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/platform/efi/efi_stub_64.S
@@ -12,6 +12,7 @@
 #include <asm/msr.h>
 #include <asm/processor-flags.h>
 #include <asm/page_types.h>
+#include <asm/nospec-branch.h>
 
 #define SAVE_XMM			\
 	mov %rsp, %rax;			\
@@ -50,6 +51,7 @@
 	mov %r8, %r9
 	mov %rcx, %r8
 	mov %rsi, %rcx
+	ANNOTATE_RETPOLINE_SAFE /* FRBS */
 	call *%rdi
 	addq $48, %rsp
 	RESTORE_XMM
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/platform/efi/efi_thunk_64.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/platform/efi/efi_thunk_64.S
@@ -22,6 +22,7 @@
 #include <linux/linkage.h>
 #include <asm/page_types.h>
 #include <asm/segment.h>
+#include <asm/nospec-branch.h>
 
 	.text
 	.code64
@@ -54,6 +55,7 @@
 
 	leaq	__efi64_thunk(%rip), %rbx
 	subq	%rax, %rbx
+	ANNOTATE_RETPOLINE_SAFE /* FRBS */
 	call	*%rbx
 
 	movq	efi_saved_sp(%rip), %rsp
@@ -135,6 +137,7 @@
 	movl	%eax, %es
 	movl	%eax, %ss
 
+	ANNOTATE_RETPOLINE_SAFE /* FRBS */
 	call	*%edi
 
 	/* We must preserve return value */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/platform/efi/quirks.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/platform/efi/quirks.c
@@ -260,10 +260,6 @@
 		return;
 	}
 
-	/* No need to reserve regions that will never be freed. */
-	if (md.attribute & EFI_MEMORY_RUNTIME)
-		return;
-
 	size += addr % EFI_PAGE_SIZE;
 	size = round_up(size, EFI_PAGE_SIZE);
 	addr = round_down(addr, EFI_PAGE_SIZE);
@@ -283,7 +279,8 @@
 		return;
 	}
 
-	new = early_memremap(new_phys, new_size);
+	new = early_memremap_prot(new_phys, new_size,
+				  pgprot_val(pgprot_encrypted(FIXMAP_PAGE_NORMAL)));
 	if (!new) {
 		pr_err("Failed to map new boot services memmap\n");
 		return;
@@ -293,6 +290,8 @@
 	early_memunmap(new, new_size);
 
 	efi_memmap_install(new_phys, num_entries);
+	e820__range_update(addr, size, E820_TYPE_RAM, E820_TYPE_RESERVED);
+	e820__update_table(e820_table);
 }
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/platform/intel/iosf_mbi.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/platform/intel/iosf_mbi.c
@@ -62,7 +62,7 @@
 
 fail_read:
 	dev_err(&mbi_pdev->dev, "PCI config access failed with %d\n", result);
-	return result;
+	return pcibios_err_to_errno(result);
 }
 
 static int iosf_mbi_pci_write_mdr(u32 mcrx, u32 mcr, u32 mdr)
@@ -91,7 +91,7 @@
 
 fail_write:
 	dev_err(&mbi_pdev->dev, "PCI config access failed with %d\n", result);
-	return result;
+	return pcibios_err_to_errno(result);
 }
 
 int iosf_mbi_read(u8 port, u8 opcode, u32 offset, u32 *mdr)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/platform/olpc/olpc-xo1-sci.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/platform/olpc/olpc-xo1-sci.c
@@ -81,7 +81,7 @@
 		return;
 	}
 
-	if (!!test_bit(SW_TABLET_MODE, ebook_switch_idev->sw) == state)
+	if (test_bit(SW_TABLET_MODE, ebook_switch_idev->sw) == !!state)
 		return; /* Nothing new to report. */
 
 	input_report_switch(ebook_switch_idev, SW_TABLET_MODE, state);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/platform/olpc/olpc.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/platform/olpc/olpc.c
@@ -274,7 +274,7 @@
 
 static struct olpc_ec_driver ec_xo1_5_driver = {
 	.ec_cmd = olpc_xo1_ec_cmd,
-#ifdef CONFIG_OLPC_XO1_5_SCI
+#ifdef CONFIG_OLPC_XO15_SCI
 	/*
 	 * XO-1.5 EC wakeups are available when olpc-xo15-sci driver is
 	 * compiled in
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/platform/pvh/head.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/platform/pvh/head.S
@@ -16,6 +16,7 @@
 #include <asm/boot.h>
 #include <asm/processor-flags.h>
 #include <asm/msr.h>
+#include <asm/nospec-branch.h>
 #include <xen/interface/elfnote.h>
 
 	__HEAD
@@ -105,6 +106,7 @@
 	/* startup_64 expects boot_params in %rsi. */
 	mov $_pa(pvh_bootparams), %rsi
 	mov $_pa(startup_64), %rax
+	ANNOTATE_RETPOLINE_SAFE
 	jmp *%rax
 
 #else /* CONFIG_X86_64 */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/platform/uv/uv_irq.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/platform/uv/uv_irq.c
@@ -167,9 +167,10 @@
 		goto out;
 
 	uv_domain = irq_domain_create_tree(fn, &uv_domain_ops, NULL);
-	irq_domain_free_fwnode(fn);
 	if (uv_domain)
 		uv_domain->parent = x86_vector_domain;
+	else
+		irq_domain_free_fwnode(fn);
 out:
 	mutex_unlock(&uv_lock);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/power/cpu.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/power/cpu.c
@@ -25,6 +25,7 @@
 #include <asm/cpu.h>
 #include <asm/mmu_context.h>
 #include <asm/cpu_device_id.h>
+#include <asm/microcode.h>
 
 #ifdef CONFIG_X86_32
 __visible unsigned long saved_context_ebx;
@@ -40,7 +41,8 @@
 	struct saved_msr *end = msr + ctxt->saved_msrs.num;
 
 	while (msr < end) {
-		msr->valid = !rdmsrl_safe(msr->info.msr_no, &msr->info.reg.q);
+		if (msr->valid)
+			rdmsrl(msr->info.msr_no, msr->info.reg.q);
 		msr++;
 	}
 }
@@ -262,6 +264,13 @@
 	x86_platform.restore_sched_clock_state();
 	mtrr_bp_restore();
 	perf_restore_debug_store();
+
+	microcode_bsp_resume();
+
+	/*
+	 * This needs to happen after the microcode has been updated upon resume
+	 * because some of the MSRs are "emulated" in microcode.
+	 */
 	msr_restore_context(ctxt);
 }
 
@@ -421,8 +430,10 @@
 	}
 
 	for (i = saved_msrs->num, j = 0; i < total_num; i++, j++) {
+		u64 dummy;
+
 		msr_array[i].info.msr_no	= msr_id[j];
-		msr_array[i].valid		= false;
+		msr_array[i].valid		= !rdmsrl_safe(msr_id[j], &dummy);
 		msr_array[i].info.reg.q		= 0;
 	}
 	saved_msrs->num   = total_num;
@@ -509,10 +520,32 @@
 	return ret;
 }
 
+static void pm_save_spec_msr(void)
+{
+	struct msr_enumeration {
+		u32 msr_no;
+		u32 feature;
+	} msr_enum[] = {
+		{ MSR_IA32_SPEC_CTRL,	 X86_FEATURE_MSR_SPEC_CTRL },
+		{ MSR_IA32_TSX_CTRL,	 X86_FEATURE_MSR_TSX_CTRL },
+		{ MSR_TSX_FORCE_ABORT,	 X86_FEATURE_TSX_FORCE_ABORT },
+		{ MSR_IA32_MCU_OPT_CTRL, X86_FEATURE_SRBDS_CTRL },
+		{ MSR_AMD64_LS_CFG,	 X86_FEATURE_LS_CFG_SSBD },
+		{ MSR_AMD64_DE_CFG,	 X86_FEATURE_LFENCE_RDTSC },
+	};
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(msr_enum); i++) {
+		if (boot_cpu_has(msr_enum[i].feature))
+			msr_build_context(&msr_enum[i].msr_no, 1);
+	}
+}
+
 static int pm_check_save_msr(void)
 {
 	dmi_check_system(msr_save_dmi_table);
 	pm_cpu_check(msr_save_cpu_table);
+	pm_save_spec_msr();
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/power/hibernate_asm_32.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/power/hibernate_asm_32.S
@@ -35,7 +35,7 @@
 	ret
 ENDPROC(swsusp_arch_suspend)
 
-ENTRY(restore_image)
+SYM_CODE_START(restore_image)
 	/* prepare to jump to the image kernel */
 	movl	restore_jump_address, %ebx
 	movl	restore_cr3, %ebp
@@ -45,9 +45,10 @@
 	/* jump to relocated restore code */
 	movl	relocated_restore_code, %eax
 	jmpl	*%eax
+SYM_CODE_END(restore_image)
 
 /* code below has been relocated to a safe page */
-ENTRY(core_restore_code)
+SYM_CODE_START(core_restore_code)
 	movl	temp_pgt, %eax
 	movl	%eax, %cr3
 
@@ -77,6 +78,7 @@
 
 done:
 	jmpl	*%ebx
+SYM_CODE_END(core_restore_code)
 
 	/* code below belongs to the image kernel */
 	.align PAGE_SIZE
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/power/hibernate_asm_64.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/power/hibernate_asm_64.S
@@ -21,6 +21,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/processor-flags.h>
 #include <asm/frame.h>
+#include <asm/nospec-branch.h>
 
 ENTRY(swsusp_arch_suspend)
 	movq	$saved_context, %rax
@@ -66,6 +67,7 @@
 
 	/* jump to relocated restore code */
 	movq	relocated_restore_code(%rip), %rcx
+	ANNOTATE_RETPOLINE_SAFE
 	jmpq	*%rcx
 
 	/* code below has been relocated to a safe page */
@@ -96,6 +98,7 @@
 
 .Ldone:
 	/* jump to the restore_registers address from the image header */
+	ANNOTATE_RETPOLINE_SAFE
 	jmpq	*%r8
 
 	 /* code below belongs to the image kernel */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/purgatory/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/purgatory/Makefile
@@ -14,18 +14,27 @@
 
 CFLAGS_sha256.o := -D__DISABLE_EXPORTS
 
+# When profile-guided optimization is enabled, llvm emits two different
+# overlapping text sections, which is not supported by kexec. Remove profile
+# optimization flags.
+KBUILD_CFLAGS := $(filter-out -fprofile-sample-use=% -fprofile-use=%,$(KBUILD_CFLAGS))
+
 LDFLAGS_purgatory.ro := -e purgatory_start -r --no-undefined -nostdlib -z nodefaultlib
 targets += purgatory.ro
 
+# Sanitizer, etc. runtimes are unavailable and cannot be linked here.
+GCOV_PROFILE	:= n
 KASAN_SANITIZE	:= n
+UBSAN_SANITIZE	:= n
 KCOV_INSTRUMENT := n
 
 # These are adjustments to the compiler flags used for objects that
 # make up the standalone purgatory.ro
 
 PURGATORY_CFLAGS_REMOVE := -mcmodel=kernel
-PURGATORY_CFLAGS := -mcmodel=large -ffreestanding -fno-zero-initialized-in-bss
-PURGATORY_CFLAGS += $(DISABLE_STACKLEAK_PLUGIN)
+PURGATORY_CFLAGS := -mcmodel=small -ffreestanding -fno-zero-initialized-in-bss -g0
+PURGATORY_CFLAGS += -fpic -fvisibility=hidden
+PURGATORY_CFLAGS += $(DISABLE_STACKLEAK_PLUGIN) -DDISABLE_BRANCH_PROFILING
 
 # Default KBUILD_CFLAGS can have -pg option set when FTRACE is enabled. That
 # in turn leaves some undefined symbols like __fentry__ in purgatory and not
@@ -55,6 +64,9 @@
 CFLAGS_REMOVE_string.o		+= $(PURGATORY_CFLAGS_REMOVE)
 CFLAGS_string.o			+= $(PURGATORY_CFLAGS)
 
+AFLAGS_REMOVE_setup-x86_$(BITS).o	+= -g -Wa,-gdwarf-2
+AFLAGS_REMOVE_entry64.o			+= -g -Wa,-gdwarf-2
+
 $(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE
 		$(call if_changed,ld)
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/realmode/init.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/realmode/init.c
@@ -8,6 +8,7 @@
 #include <asm/pgtable.h>
 #include <asm/realmode.h>
 #include <asm/tlbflush.h>
+#include <asm/crash.h>
 
 struct real_mode_header *real_mode_header;
 u32 *trampoline_cr4_features;
@@ -15,6 +16,32 @@
 /* Hold the pgd entry used on booting additional CPUs */
 pgd_t trampoline_pgd_entry;
 
+void load_trampoline_pgtable(void)
+{
+#ifdef CONFIG_X86_32
+	load_cr3(initial_page_table);
+#else
+	/*
+	 * This function is called before exiting to real-mode and that will
+	 * fail with CR4.PCIDE still set.
+	 */
+	if (boot_cpu_has(X86_FEATURE_PCID))
+		cr4_clear_bits(X86_CR4_PCIDE);
+
+	write_cr3(real_mode_header->trampoline_pgd);
+#endif
+
+	/*
+	 * The CR3 write above will not flush global TLB entries.
+	 * Stale, global entries from previous page tables may still be
+	 * present.  Flush those stale entries.
+	 *
+	 * This ensures that memory accessed while running with
+	 * trampoline_pgd is *actually* mapped into trampoline_pgd.
+	 */
+	__flush_tlb_all();
+}
+
 void __init reserve_real_mode(void)
 {
 	phys_addr_t mem;
@@ -34,6 +61,7 @@
 
 	memblock_reserve(mem, size);
 	set_real_mode_mem(mem);
+	crash_reserve_low_1M();
 }
 
 static void __init setup_real_mode(void)
@@ -48,6 +76,7 @@
 #ifdef CONFIG_X86_64
 	u64 *trampoline_pgd;
 	u64 efer;
+	int i;
 #endif
 
 	base = (unsigned char *)real_mode_header;
@@ -106,8 +135,17 @@
 		trampoline_header->flags |= TH_FLAGS_SME_ACTIVE;
 
 	trampoline_pgd = (u64 *) __va(real_mode_header->trampoline_pgd);
+
+	/* Map the real mode stub as virtual == physical */
 	trampoline_pgd[0] = trampoline_pgd_entry.pgd;
-	trampoline_pgd[511] = init_top_pgt[511].pgd;
+
+	/*
+	 * Include the entirety of the kernel mapping into the trampoline
+	 * PGD.  This way, all mappings present in the normal kernel page
+	 * tables are usable while running on trampoline_pgd.
+	 */
+	for (i = pgd_index(__PAGE_OFFSET); i < PTRS_PER_PGD; i++)
+		trampoline_pgd[i] = init_top_pgt[i].pgd;
 #endif
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/realmode/rm/trampoline_32.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/realmode/rm/trampoline_32.S
@@ -23,13 +23,14 @@
 #include <linux/linkage.h>
 #include <asm/segment.h>
 #include <asm/page_types.h>
+#include <asm/nospec-branch.h>
 #include "realmode.h"
 
 	.text
 	.code16
 
 	.balign	PAGE_SIZE
-ENTRY(trampoline_start)
+SYM_CODE_START(trampoline_start)
 	wbinvd			# Needed for NUMA-Q should be harmless for others
 
 	LJMPW_RM(1f)
@@ -54,11 +55,14 @@
 	lmsw	%dx			# into protected mode
 
 	ljmpl	$__BOOT_CS, $pa_startup_32
+SYM_CODE_END(trampoline_start)
 
 	.section ".text32","ax"
 	.code32
-ENTRY(startup_32)			# note: also used from wakeup_asm.S
+SYM_CODE_START(startup_32)			# note: also used from wakeup_asm.S
+	ANNOTATE_RETPOLINE_SAFE
 	jmp	*%eax
+SYM_CODE_END(startup_32)
 
 	.bss
 	.balign 8
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/realmode/rm/wakeup_asm.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/realmode/rm/wakeup_asm.S
@@ -73,7 +73,7 @@
 	movw	%ax, %fs
 	movw	%ax, %gs
 
-	lidtl	wakeup_idt
+	lidtl	.Lwakeup_idt
 
 	/* Clear the EFLAGS */
 	pushl $0
@@ -171,8 +171,8 @@
 
 	/* This is the standard real-mode IDT */
 	.balign	16
-GLOBAL(wakeup_idt)
+.Lwakeup_idt:
 	.word	0xffff		/* limit */
 	.long	0		/* address */
 	.word	0
-END(wakeup_idt)
+END(.Lwakeup_idt)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/tools/chkobjdump.awk
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/tools/chkobjdump.awk
@@ -10,6 +10,7 @@
 
 /^GNU objdump/ {
 	verstr = ""
+	gsub(/\(.*\)/, "");
 	for (i = 3; i <= NF; i++)
 		if (match($(i), "^[0-9]")) {
 			verstr = $(i);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/tools/gen-insn-attr-x86.awk
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/tools/gen-insn-attr-x86.awk
@@ -69,7 +69,7 @@
 
 	lprefix1_expr = "\\((66|!F3)\\)"
 	lprefix2_expr = "\\(F3\\)"
-	lprefix3_expr = "\\((F2|!F3|66\\&F2)\\)"
+	lprefix3_expr = "\\((F2|!F3|66&F2)\\)"
 	lprefix_expr = "\\((66|F2|F3)\\)"
 	max_lprefix = 4
 
@@ -257,7 +257,7 @@
 	return add_flags(imm, mod)
 }
 
-/^[0-9a-f]+\:/ {
+/^[0-9a-f]+:/ {
 	if (NR == 1)
 		next
 	# get index
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/tools/relocs.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/tools/relocs.c
@@ -596,6 +596,14 @@
 		if (!(sec_applies->shdr.sh_flags & SHF_ALLOC)) {
 			continue;
 		}
+		/*
+		 * Do not perform relocations in .notes section; any
+		 * values there are meant for pre-boot consumption (e.g.
+		 * startup_xen).
+		 */
+		if (sec_applies->shdr.sh_type == SHT_NOTE) {
+			continue;
+		}
 		sh_symtab  = sec_symtab->symtab;
 		sym_strtab = sec_symtab->link->strtab;
 		for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Rel); j++) {
@@ -681,6 +689,15 @@
 		if (!(sec_applies->shdr.sh_flags & SHF_ALLOC)) {
 			continue;
 		}
+
+		/*
+		 * Do not perform relocations in .notes sections; any
+		 * values there are meant for pre-boot consumption (e.g.
+		 * startup_xen).
+		 */
+		if (sec_applies->shdr.sh_type == SHT_NOTE)
+			continue;
+
 		sh_symtab = sec_symtab->symtab;
 		sym_strtab = sec_symtab->link->strtab;
 		for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Rel); j++) {
@@ -867,9 +884,11 @@
 	case R_386_PC32:
 	case R_386_PC16:
 	case R_386_PC8:
+	case R_386_PLT32:
 		/*
-		 * NONE can be ignored and PC relative relocations don't
-		 * need to be adjusted.
+		 * NONE can be ignored and PC relative relocations don't need
+		 * to be adjusted. Because sym must be defined, R_386_PLT32 can
+		 * be treated the same way as R_386_PC32.
 		 */
 		break;
 
@@ -910,9 +929,11 @@
 	case R_386_PC32:
 	case R_386_PC16:
 	case R_386_PC8:
+	case R_386_PLT32:
 		/*
-		 * NONE can be ignored and PC relative relocations don't
-		 * need to be adjusted.
+		 * NONE can be ignored and PC relative relocations don't need
+		 * to be adjusted. Because sym must be defined, R_386_PLT32 can
+		 * be treated the same way as R_386_PC32.
 		 */
 		break;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/um/ldt.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/um/ldt.c
@@ -23,9 +23,11 @@
 {
 	long res;
 	void *stub_addr;
+
+	BUILD_BUG_ON(sizeof(*desc) % sizeof(long));
+
 	res = syscall_stub_data(mm_idp, (unsigned long *)desc,
-				(sizeof(*desc) + sizeof(long) - 1) &
-				    ~(sizeof(long) - 1),
+				sizeof(*desc) / sizeof(long),
 				addr, &stub_addr);
 	if (!res) {
 		unsigned long args[] = { func,
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/um/shared/sysdep/syscalls_32.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/um/shared/sysdep/syscalls_32.h
@@ -6,10 +6,9 @@
 #include <asm/unistd.h>
 #include <sysdep/ptrace.h>
 
-typedef long syscall_handler_t(struct pt_regs);
+typedef long syscall_handler_t(struct syscall_args);
 
 extern syscall_handler_t *sys_call_table[];
 
 #define EXECUTE_SYSCALL(syscall, regs) \
-	((long (*)(struct syscall_args)) \
-	 (*sys_call_table[syscall]))(SYSCALL_ARGS(&regs->regs))
+	((*sys_call_table[syscall]))(SYSCALL_ARGS(&regs->regs))
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/um/shared/sysdep/syscalls_64.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/um/shared/sysdep/syscalls_64.h
@@ -10,13 +10,12 @@
 #include <linux/msg.h>
 #include <linux/shm.h>
 
-typedef long syscall_handler_t(void);
+typedef long syscall_handler_t(long, long, long, long, long, long);
 
 extern syscall_handler_t *sys_call_table[];
 
 #define EXECUTE_SYSCALL(syscall, regs) \
-	(((long (*)(long, long, long, long, long, long)) \
-	  (*sys_call_table[syscall]))(UPT_SYSCALL_ARG1(&regs->regs), \
+	(((*sys_call_table[syscall]))(UPT_SYSCALL_ARG1(&regs->regs), \
 		 		      UPT_SYSCALL_ARG2(&regs->regs), \
 				      UPT_SYSCALL_ARG3(&regs->regs), \
 				      UPT_SYSCALL_ARG4(&regs->regs), \
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/um/syscalls_64.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/um/syscalls_64.c
@@ -11,6 +11,7 @@
 #include <linux/uaccess.h>
 #include <asm/prctl.h> /* XXX This should get the constants from libc */
 #include <os.h>
+#include <registers.h>
 
 long arch_prctl(struct task_struct *task, int option,
 		unsigned long __user *arg2)
@@ -35,7 +36,7 @@
 	switch (option) {
 	case ARCH_SET_FS:
 	case ARCH_SET_GS:
-		ret = restore_registers(pid, &current->thread.regs.regs);
+		ret = restore_pid_registers(pid, &current->thread.regs.regs);
 		if (ret)
 			return ret;
 		break;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/um/tls_32.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/um/tls_32.c
@@ -65,9 +65,6 @@
 	struct thread_struct *t = &task->thread;
 	int idx;
 
-	if (!t->arch.tls_array)
-		return GDT_ENTRY_TLS_MIN;
-
 	for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++)
 		if (!t->arch.tls_array[idx].present)
 			return idx + GDT_ENTRY_TLS_MIN;
@@ -215,14 +212,12 @@
 	return 0;
 }
 
-int arch_copy_tls(struct task_struct *new)
+int arch_set_tls(struct task_struct *new, unsigned long tls)
 {
 	struct user_desc info;
 	int idx, ret = -EFAULT;
 
-	if (copy_from_user(&info,
-			   (void __user *) UPT_SI(&new->thread.regs.regs),
-			   sizeof(info)))
+	if (copy_from_user(&info, (void __user *) tls, sizeof(info)))
 		goto out;
 
 	ret = -EINVAL;
@@ -242,9 +237,6 @@
 {
 	struct thread_struct *t = &task->thread;
 
-	if (!t->arch.tls_array)
-		goto clear;
-
 	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
 		return -EINVAL;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/um/tls_64.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/um/tls_64.c
@@ -6,14 +6,13 @@
 {
 }
 
-int arch_copy_tls(struct task_struct *t)
+int arch_set_tls(struct task_struct *t, unsigned long tls)
 {
 	/*
 	 * If CLONE_SETTLS is set, we need to save the thread id
-	 * (which is argument 5, child_tid, of clone) so it can be set
-	 * during context switches.
+	 * so it can be set during context switches.
 	 */
-	t->thread.arch.fs = t->thread.regs.regs.gp[R8 / sizeof(long)];
+	t->thread.arch.fs = tls;
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/um/vdso/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/um/vdso/Makefile
@@ -62,7 +62,7 @@
 		       -Wl,-T,$(filter %.lds,$^) $(filter %.o,$^) && \
 		 sh $(srctree)/$(src)/checkundef.sh '$(NM)' '$@'
 
-VDSO_LDFLAGS = -fPIC -shared -Wl,--hash-style=sysv
+VDSO_LDFLAGS = -fPIC -shared -Wl,--hash-style=sysv -z noexecstack
 GCOV_PROFILE := n
 
 #
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/um/vdso/um_vdso.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/um/vdso/um_vdso.c
@@ -17,8 +17,10 @@
 {
 	long ret;
 
-	asm("syscall" : "=a" (ret) :
-		"0" (__NR_clock_gettime), "D" (clock), "S" (ts) : "memory");
+	asm("syscall"
+		: "=a" (ret)
+		: "0" (__NR_clock_gettime), "D" (clock), "S" (ts)
+		: "rcx", "r11", "memory");
 
 	return ret;
 }
@@ -29,8 +31,10 @@
 {
 	long ret;
 
-	asm("syscall" : "=a" (ret) :
-		"0" (__NR_gettimeofday), "D" (tv), "S" (tz) : "memory");
+	asm("syscall"
+		: "=a" (ret)
+		: "0" (__NR_gettimeofday), "D" (tv), "S" (tz)
+		: "rcx", "r11", "memory");
 
 	return ret;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/xen/enlighten_hvm.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/xen/enlighten_hvm.c
@@ -175,6 +175,8 @@
        return 0;
 }
 
+static bool no_vector_callback __initdata;
+
 static void __init xen_hvm_guest_init(void)
 {
 	if (xen_pv_domain())
@@ -194,7 +196,7 @@
 
 	xen_panic_handler_init();
 
-	if (xen_feature(XENFEAT_hvm_callback_vector))
+	if (!no_vector_callback && xen_feature(XENFEAT_hvm_callback_vector))
 		xen_have_vector_callback = 1;
 
 	xen_hvm_smp_init();
@@ -220,6 +222,13 @@
 }
 early_param("xen_nopv", xen_parse_nopv);
 
+static __init int xen_parse_no_vector_callback(char *arg)
+{
+	no_vector_callback = true;
+	return 0;
+}
+early_param("xen_no_vector_callback", xen_parse_no_vector_callback);
+
 bool __init xen_hvm_need_lapic(void)
 {
 	if (xen_pv_domain())
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/xen/enlighten_pv.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/xen/enlighten_pv.c
@@ -727,8 +727,8 @@
 	preempt_enable();
 }
 
-static void xen_convert_trap_info(const struct desc_ptr *desc,
-				  struct trap_info *traps)
+static unsigned xen_convert_trap_info(const struct desc_ptr *desc,
+				      struct trap_info *traps, bool full)
 {
 	unsigned in, out, count;
 
@@ -738,17 +738,18 @@
 	for (in = out = 0; in < count; in++) {
 		gate_desc *entry = (gate_desc *)(desc->address) + in;
 
-		if (cvt_gate_to_trap(in, entry, &traps[out]))
+		if (cvt_gate_to_trap(in, entry, &traps[out]) || full)
 			out++;
 	}
-	traps[out].address = 0;
+
+	return out;
 }
 
 void xen_copy_trap_info(struct trap_info *traps)
 {
 	const struct desc_ptr *desc = this_cpu_ptr(&idt_desc);
 
-	xen_convert_trap_info(desc, traps);
+	xen_convert_trap_info(desc, traps, true);
 }
 
 /* Load a new IDT into Xen.  In principle this can be per-CPU, so we
@@ -758,6 +759,7 @@
 {
 	static DEFINE_SPINLOCK(lock);
 	static struct trap_info traps[257];
+	unsigned out;
 
 	trace_xen_cpu_load_idt(desc);
 
@@ -765,7 +767,8 @@
 
 	memcpy(this_cpu_ptr(&idt_desc), desc, sizeof(idt_desc));
 
-	xen_convert_trap_info(desc, traps);
+	out = xen_convert_trap_info(desc, traps, false);
+	memset(&traps[out], 0, sizeof(traps[0]));
 
 	xen_mc_flush();
 	if (HYPERVISOR_set_trap_table(traps))
@@ -905,14 +908,15 @@
 static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high)
 {
 	int ret;
+#ifdef CONFIG_X86_64
+	unsigned int which;
+	u64 base;
+#endif
 
 	ret = 0;
 
 	switch (msr) {
 #ifdef CONFIG_X86_64
-		unsigned which;
-		u64 base;
-
 	case MSR_FS_BASE:		which = SEGBASE_FS; goto set;
 	case MSR_KERNEL_GS_BASE:	which = SEGBASE_GS_USER; goto set;
 	case MSR_GS_BASE:		which = SEGBASE_GS_KERNEL; goto set;
@@ -1182,6 +1186,11 @@
 	x86_platform.legacy.rtc = 1;
 }
 
+static void __init xen_domu_set_legacy_features(void)
+{
+	x86_platform.legacy.rtc = 0;
+}
+
 /* First C function to be called on Xen boot */
 asmlinkage __visible void __init xen_start_kernel(void)
 {
@@ -1215,6 +1224,7 @@
 	x86_platform.get_nmi_reason = xen_get_nmi_reason;
 
 	x86_init.resources.memory_setup = xen_memory_setup;
+	x86_init.irqs.intr_mode_select	= x86_init_noop;
 	x86_init.irqs.intr_mode_init	= x86_init_noop;
 	x86_init.oem.arch_setup = xen_arch_setup;
 	x86_init.oem.banner = xen_banner;
@@ -1351,6 +1361,8 @@
 		add_preferred_console("xenboot", 0, NULL);
 		if (pci_xen)
 			x86_init.pci.arch_init = pci_xen_init;
+		x86_platform.set_legacy_features =
+				xen_domu_set_legacy_features;
 	} else {
 		const struct dom0_vga_console_info *info =
 			(void *)((char *)xen_start_info +
@@ -1380,6 +1392,15 @@
 		x86_init.mpparse.get_smp_config = x86_init_uint_noop;
 
 		xen_boot_params_init_edd();
+
+#ifdef CONFIG_ACPI
+		/*
+		 * Disable selecting "Firmware First mode" for correctable
+		 * memory errors, as this is the duty of the hypervisor to
+		 * decide.
+		 */
+		acpi_disable_cmcff = 1;
+#endif
 	}
 
 	if (!boot_params.screen_info.orig_video_isVGA)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/xen/mmu_pv.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/xen/mmu_pv.c
@@ -106,6 +106,51 @@
  */
 static DEFINE_SPINLOCK(xen_reservation_lock);
 
+/* Protected by xen_reservation_lock. */
+#define MIN_CONTIG_ORDER 9 /* 2MB */
+static unsigned int discontig_frames_order = MIN_CONTIG_ORDER;
+static unsigned long discontig_frames_early[1UL << MIN_CONTIG_ORDER] __initdata;
+static unsigned long *discontig_frames __refdata = discontig_frames_early;
+static bool discontig_frames_dyn;
+
+static int alloc_discontig_frames(unsigned int order)
+{
+	unsigned long *new_array, *old_array;
+	unsigned int old_order;
+	unsigned long flags;
+
+	BUG_ON(order < MIN_CONTIG_ORDER);
+	BUILD_BUG_ON(sizeof(discontig_frames_early) != PAGE_SIZE);
+
+	new_array = (unsigned long *)__get_free_pages(GFP_KERNEL,
+						      order - MIN_CONTIG_ORDER);
+	if (!new_array)
+		return -ENOMEM;
+
+	spin_lock_irqsave(&xen_reservation_lock, flags);
+
+	old_order = discontig_frames_order;
+
+	if (order > discontig_frames_order || !discontig_frames_dyn) {
+		if (!discontig_frames_dyn)
+			old_array = NULL;
+		else
+			old_array = discontig_frames;
+
+		discontig_frames = new_array;
+		discontig_frames_order = order;
+		discontig_frames_dyn = true;
+	} else {
+		old_array = new_array;
+	}
+
+	spin_unlock_irqrestore(&xen_reservation_lock, flags);
+
+	free_pages((unsigned long)old_array, old_order - MIN_CONTIG_ORDER);
+
+	return 0;
+}
+
 /*
  * Note about cr3 (pagetable base) values:
  *
@@ -842,6 +887,7 @@
 {
 	struct page *page;
 
+	spin_lock(&init_mm.page_table_lock);
 	spin_lock(&pgd_lock);
 
 	list_for_each_entry(page, &pgd_list, lru) {
@@ -852,6 +898,7 @@
 	}
 
 	spin_unlock(&pgd_lock);
+	spin_unlock(&init_mm.page_table_lock);
 }
 
 static int __init xen_mark_pinned(struct mm_struct *mm, struct page *page,
@@ -874,6 +921,9 @@
 	SetPagePinned(virt_to_page(level3_user_vsyscall));
 #endif
 	xen_pgd_walk(&init_mm, xen_mark_pinned, FIXADDR_TOP);
+
+	if (alloc_discontig_frames(MIN_CONTIG_ORDER))
+		BUG();
 }
 
 static int xen_unpin_page(struct mm_struct *mm, struct page *page,
@@ -961,6 +1011,7 @@
 {
 	struct page *page;
 
+	spin_lock(&init_mm.page_table_lock);
 	spin_lock(&pgd_lock);
 
 	list_for_each_entry(page, &pgd_list, lru) {
@@ -972,6 +1023,7 @@
 	}
 
 	spin_unlock(&pgd_lock);
+	spin_unlock(&init_mm.page_table_lock);
 }
 
 static void xen_activate_mm(struct mm_struct *prev, struct mm_struct *next)
@@ -2467,10 +2519,6 @@
 	memset(dummy_mapping, 0xff, PAGE_SIZE);
 }
 
-/* Protected by xen_reservation_lock. */
-#define MAX_CONTIG_ORDER 9 /* 2MB */
-static unsigned long discontig_frames[1<<MAX_CONTIG_ORDER];
-
 #define VOID_PTE (mfn_pte(0, __pgprot(0)))
 static void xen_zap_pfn_range(unsigned long vaddr, unsigned int order,
 				unsigned long *in_frames,
@@ -2587,24 +2635,25 @@
 				 unsigned int address_bits,
 				 dma_addr_t *dma_handle)
 {
-	unsigned long *in_frames = discontig_frames, out_frame;
+	unsigned long *in_frames, out_frame;
 	unsigned long  flags;
 	int            success;
 	unsigned long vstart = (unsigned long)phys_to_virt(pstart);
 
-	/*
-	 * Currently an auto-translated guest will not perform I/O, nor will
-	 * it require PAE page directories below 4GB. Therefore any calls to
-	 * this function are redundant and can be ignored.
-	 */
+	if (unlikely(order > discontig_frames_order)) {
+		if (!discontig_frames_dyn)
+			return -ENOMEM;
 
-	if (unlikely(order > MAX_CONTIG_ORDER))
-		return -ENOMEM;
+		if (alloc_discontig_frames(order))
+			return -ENOMEM;
+	}
 
 	memset((void *) vstart, 0, PAGE_SIZE << order);
 
 	spin_lock_irqsave(&xen_reservation_lock, flags);
 
+	in_frames = discontig_frames;
+
 	/* 1. Zap current PTEs, remembering MFNs. */
 	xen_zap_pfn_range(vstart, order, in_frames, NULL);
 
@@ -2628,12 +2677,12 @@
 
 void xen_destroy_contiguous_region(phys_addr_t pstart, unsigned int order)
 {
-	unsigned long *out_frames = discontig_frames, in_frame;
+	unsigned long *out_frames, in_frame;
 	unsigned long  flags;
 	int success;
 	unsigned long vstart;
 
-	if (unlikely(order > MAX_CONTIG_ORDER))
+	if (unlikely(order > discontig_frames_order))
 		return;
 
 	vstart = (unsigned long)phys_to_virt(pstart);
@@ -2641,6 +2690,8 @@
 
 	spin_lock_irqsave(&xen_reservation_lock, flags);
 
+	out_frames = discontig_frames;
+
 	/* 1. Find start MFN of contiguous extent. */
 	in_frame = virt_to_mfn(vstart);
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/xen/p2m.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/xen/p2m.c
@@ -622,8 +622,8 @@
 	}
 
 	/* Expanded the p2m? */
-	if (pfn > xen_p2m_last_pfn) {
-		xen_p2m_last_pfn = pfn;
+	if (pfn >= xen_p2m_last_pfn) {
+		xen_p2m_last_pfn = ALIGN(pfn + 1, P2M_PER_PAGE);
 		HYPERVISOR_shared_info->arch.max_pfn = xen_p2m_last_pfn;
 	}
 
@@ -714,9 +714,12 @@
 
 	for (i = 0; i < count; i++) {
 		unsigned long mfn, pfn;
+		struct gnttab_unmap_grant_ref unmap[2];
+		int rc;
 
 		/* Do not add to override if the map failed. */
-		if (map_ops[i].status)
+		if (map_ops[i].status != GNTST_okay ||
+		    (kmap_ops && kmap_ops[i].status != GNTST_okay))
 			continue;
 
 		if (map_ops[i].flags & GNTMAP_contains_pte) {
@@ -730,10 +733,46 @@
 
 		WARN(pfn_to_mfn(pfn) != INVALID_P2M_ENTRY, "page must be ballooned");
 
-		if (unlikely(!set_phys_to_machine(pfn, FOREIGN_FRAME(mfn)))) {
-			ret = -ENOMEM;
-			goto out;
+		if (likely(set_phys_to_machine(pfn, FOREIGN_FRAME(mfn))))
+			continue;
+
+		/*
+		 * Signal an error for this slot. This in turn requires
+		 * immediate unmapping.
+		 */
+		map_ops[i].status = GNTST_general_error;
+		unmap[0].host_addr = map_ops[i].host_addr;
+		unmap[0].handle = map_ops[i].handle;
+		map_ops[i].handle = ~0;
+		if (map_ops[i].flags & GNTMAP_device_map)
+			unmap[0].dev_bus_addr = map_ops[i].dev_bus_addr;
+		else
+			unmap[0].dev_bus_addr = 0;
+
+		if (kmap_ops) {
+			kmap_ops[i].status = GNTST_general_error;
+			unmap[1].host_addr = kmap_ops[i].host_addr;
+			unmap[1].handle = kmap_ops[i].handle;
+			kmap_ops[i].handle = ~0;
+			if (kmap_ops[i].flags & GNTMAP_device_map)
+				unmap[1].dev_bus_addr = kmap_ops[i].dev_bus_addr;
+			else
+				unmap[1].dev_bus_addr = 0;
 		}
+
+		/*
+		 * Pre-populate both status fields, to be recognizable in
+		 * the log message below.
+		 */
+		unmap[0].status = 1;
+		unmap[1].status = 1;
+
+		rc = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
+					       unmap, 1 + !!kmap_ops);
+		if (rc || unmap[0].status != GNTST_okay ||
+		    unmap[1].status != GNTST_okay)
+			pr_err_once("gnttab unmap failed: rc=%d st0=%d st1=%d\n",
+				    rc, unmap[0].status, unmap[1].status);
 	}
 
 out:
@@ -754,17 +793,15 @@
 		unsigned long mfn = __pfn_to_mfn(page_to_pfn(pages[i]));
 		unsigned long pfn = page_to_pfn(pages[i]);
 
-		if (mfn == INVALID_P2M_ENTRY || !(mfn & FOREIGN_FRAME_BIT)) {
+		if (mfn != INVALID_P2M_ENTRY && (mfn & FOREIGN_FRAME_BIT))
+			set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
+		else
 			ret = -EINVAL;
-			goto out;
-		}
-
-		set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
 	}
 	if (kunmap_ops)
 		ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref,
-						kunmap_ops, count);
-out:
+						kunmap_ops, count) ?: ret;
+
 	return ret;
 }
 EXPORT_SYMBOL_GPL(clear_foreign_p2m_mapping);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/xen/pmu.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/xen/pmu.c
@@ -512,10 +512,7 @@
 	return ret;
 }
 
-bool is_xen_pmu(int cpu)
-{
-	return (get_xenpmu_data() != NULL);
-}
+bool is_xen_pmu;
 
 void xen_pmu_init(int cpu)
 {
@@ -526,7 +523,7 @@
 
 	BUILD_BUG_ON(sizeof(struct xen_pmu_data) > PAGE_SIZE);
 
-	if (xen_hvm_domain())
+	if (xen_hvm_domain() || (cpu != 0 && !is_xen_pmu))
 		return;
 
 	xenpmu_data = (struct xen_pmu_data *)get_zeroed_page(GFP_KERNEL);
@@ -547,7 +544,8 @@
 	per_cpu(xenpmu_shared, cpu).xenpmu_data = xenpmu_data;
 	per_cpu(xenpmu_shared, cpu).flags = 0;
 
-	if (cpu == 0) {
+	if (!is_xen_pmu) {
+		is_xen_pmu = true;
 		perf_register_guest_info_callbacks(&xen_guest_cbs);
 		xen_pmu_arch_init();
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/xen/pmu.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/xen/pmu.h
@@ -4,6 +4,8 @@
 
 #include <xen/interface/xenpmu.h>
 
+extern bool is_xen_pmu;
+
 irqreturn_t xen_pmu_irq_handler(int irq, void *dev_id);
 #ifdef CONFIG_XEN_HAVE_VPMU
 void xen_pmu_init(int cpu);
@@ -12,7 +14,6 @@
 static inline void xen_pmu_init(int cpu) {}
 static inline void xen_pmu_finish(int cpu) {}
 #endif
-bool is_xen_pmu(int cpu);
 bool pmu_msr_read(unsigned int msr, uint64_t *val, int *err);
 bool pmu_msr_write(unsigned int msr, uint32_t low, uint32_t high, int *err);
 int pmu_apic_update(uint32_t reg);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/xen/setup.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/xen/setup.c
@@ -875,7 +875,7 @@
 	 * to relocating (and even reusing) pages with kernel text or data.
 	 */
 	if (xen_is_e820_reserved(__pa_symbol(_text),
-			__pa_symbol(__bss_stop) - __pa_symbol(_text))) {
+				 __pa_symbol(_end) - __pa_symbol(_text))) {
 		xen_raw_console_write("Xen hypervisor allocated kernel memory conflicts with E820 map\n");
 		BUG();
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/xen/smp.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/xen/smp.c
@@ -32,30 +32,30 @@
 
 void xen_smp_intr_free(unsigned int cpu)
 {
+	kfree(per_cpu(xen_resched_irq, cpu).name);
+	per_cpu(xen_resched_irq, cpu).name = NULL;
 	if (per_cpu(xen_resched_irq, cpu).irq >= 0) {
 		unbind_from_irqhandler(per_cpu(xen_resched_irq, cpu).irq, NULL);
 		per_cpu(xen_resched_irq, cpu).irq = -1;
-		kfree(per_cpu(xen_resched_irq, cpu).name);
-		per_cpu(xen_resched_irq, cpu).name = NULL;
 	}
+	kfree(per_cpu(xen_callfunc_irq, cpu).name);
+	per_cpu(xen_callfunc_irq, cpu).name = NULL;
 	if (per_cpu(xen_callfunc_irq, cpu).irq >= 0) {
 		unbind_from_irqhandler(per_cpu(xen_callfunc_irq, cpu).irq, NULL);
 		per_cpu(xen_callfunc_irq, cpu).irq = -1;
-		kfree(per_cpu(xen_callfunc_irq, cpu).name);
-		per_cpu(xen_callfunc_irq, cpu).name = NULL;
 	}
+	kfree(per_cpu(xen_debug_irq, cpu).name);
+	per_cpu(xen_debug_irq, cpu).name = NULL;
 	if (per_cpu(xen_debug_irq, cpu).irq >= 0) {
 		unbind_from_irqhandler(per_cpu(xen_debug_irq, cpu).irq, NULL);
 		per_cpu(xen_debug_irq, cpu).irq = -1;
-		kfree(per_cpu(xen_debug_irq, cpu).name);
-		per_cpu(xen_debug_irq, cpu).name = NULL;
 	}
+	kfree(per_cpu(xen_callfuncsingle_irq, cpu).name);
+	per_cpu(xen_callfuncsingle_irq, cpu).name = NULL;
 	if (per_cpu(xen_callfuncsingle_irq, cpu).irq >= 0) {
 		unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu).irq,
 				       NULL);
 		per_cpu(xen_callfuncsingle_irq, cpu).irq = -1;
-		kfree(per_cpu(xen_callfuncsingle_irq, cpu).name);
-		per_cpu(xen_callfuncsingle_irq, cpu).name = NULL;
 	}
 }
 
@@ -65,6 +65,9 @@
 	char *resched_name, *callfunc_name, *debug_name;
 
 	resched_name = kasprintf(GFP_KERNEL, "resched%d", cpu);
+	if (!resched_name)
+		goto fail_mem;
+	per_cpu(xen_resched_irq, cpu).name = resched_name;
 	rc = bind_ipi_to_irqhandler(XEN_RESCHEDULE_VECTOR,
 				    cpu,
 				    xen_reschedule_interrupt,
@@ -74,9 +77,11 @@
 	if (rc < 0)
 		goto fail;
 	per_cpu(xen_resched_irq, cpu).irq = rc;
-	per_cpu(xen_resched_irq, cpu).name = resched_name;
 
 	callfunc_name = kasprintf(GFP_KERNEL, "callfunc%d", cpu);
+	if (!callfunc_name)
+		goto fail_mem;
+	per_cpu(xen_callfunc_irq, cpu).name = callfunc_name;
 	rc = bind_ipi_to_irqhandler(XEN_CALL_FUNCTION_VECTOR,
 				    cpu,
 				    xen_call_function_interrupt,
@@ -86,18 +91,27 @@
 	if (rc < 0)
 		goto fail;
 	per_cpu(xen_callfunc_irq, cpu).irq = rc;
-	per_cpu(xen_callfunc_irq, cpu).name = callfunc_name;
 
-	debug_name = kasprintf(GFP_KERNEL, "debug%d", cpu);
-	rc = bind_virq_to_irqhandler(VIRQ_DEBUG, cpu, xen_debug_interrupt,
-				     IRQF_PERCPU | IRQF_NOBALANCING,
-				     debug_name, NULL);
-	if (rc < 0)
-		goto fail;
-	per_cpu(xen_debug_irq, cpu).irq = rc;
-	per_cpu(xen_debug_irq, cpu).name = debug_name;
+	if (!xen_fifo_events) {
+		debug_name = kasprintf(GFP_KERNEL, "debug%d", cpu);
+		if (!debug_name)
+			goto fail_mem;
+
+		per_cpu(xen_debug_irq, cpu).name = debug_name;
+		rc = bind_virq_to_irqhandler(VIRQ_DEBUG, cpu,
+					     xen_debug_interrupt,
+					     IRQF_PERCPU | IRQF_NOBALANCING,
+					     debug_name, NULL);
+		if (rc < 0)
+			goto fail;
+		per_cpu(xen_debug_irq, cpu).irq = rc;
+	}
 
 	callfunc_name = kasprintf(GFP_KERNEL, "callfuncsingle%d", cpu);
+	if (!callfunc_name)
+		goto fail_mem;
+
+	per_cpu(xen_callfuncsingle_irq, cpu).name = callfunc_name;
 	rc = bind_ipi_to_irqhandler(XEN_CALL_FUNCTION_SINGLE_VECTOR,
 				    cpu,
 				    xen_call_function_single_interrupt,
@@ -107,10 +121,11 @@
 	if (rc < 0)
 		goto fail;
 	per_cpu(xen_callfuncsingle_irq, cpu).irq = rc;
-	per_cpu(xen_callfuncsingle_irq, cpu).name = callfunc_name;
 
 	return 0;
 
+ fail_mem:
+	rc = -ENOMEM;
  fail:
 	xen_smp_intr_free(cpu);
 	return rc;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/xen/smp_hvm.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/xen/smp_hvm.c
@@ -19,6 +19,12 @@
 	xen_vcpu_setup(0);
 
 	/*
+	 * Called again in case the kernel boots on vcpu >= MAX_VIRT_CPUS.
+	 * Refer to comments in xen_hvm_init_time_ops().
+	 */
+	xen_hvm_init_time_ops();
+
+	/*
 	 * The alternative logic (which patches the unlock/lock) runs before
 	 * the smp bootup up code is activated. Hence we need to set this up
 	 * the core kernel is being patched. Otherwise we will have only
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/xen/smp_pv.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/xen/smp_pv.c
@@ -28,6 +28,7 @@
 #include <asm/desc.h>
 #include <asm/pgtable.h>
 #include <asm/cpu.h>
+#include <asm/fpu/internal.h>
 
 #include <xen/interface/xen.h>
 #include <xen/interface/vcpu.h>
@@ -53,6 +54,7 @@
 static DEFINE_PER_CPU(struct xen_common_irq, xen_pmu_irq) = { .irq = -1 };
 
 static irqreturn_t xen_irq_work_interrupt(int irq, void *dev_id);
+void asm_cpu_bringup_and_idle(void);
 
 static void cpu_bringup(void)
 {
@@ -60,6 +62,7 @@
 
 	cr4_init();
 	cpu_init();
+	fpu__init_cpu();
 	touch_softlockup_watchdog();
 	preempt_disable();
 
@@ -92,22 +95,23 @@
 	cpu_bringup();
 	boot_init_stack_canary();
 	cpu_startup_entry(CPUHP_AP_ONLINE_IDLE);
+	prevent_tail_call_optimization();
 }
 
 void xen_smp_intr_free_pv(unsigned int cpu)
 {
+	kfree(per_cpu(xen_irq_work, cpu).name);
+	per_cpu(xen_irq_work, cpu).name = NULL;
 	if (per_cpu(xen_irq_work, cpu).irq >= 0) {
 		unbind_from_irqhandler(per_cpu(xen_irq_work, cpu).irq, NULL);
 		per_cpu(xen_irq_work, cpu).irq = -1;
-		kfree(per_cpu(xen_irq_work, cpu).name);
-		per_cpu(xen_irq_work, cpu).name = NULL;
 	}
 
+	kfree(per_cpu(xen_pmu_irq, cpu).name);
+	per_cpu(xen_pmu_irq, cpu).name = NULL;
 	if (per_cpu(xen_pmu_irq, cpu).irq >= 0) {
 		unbind_from_irqhandler(per_cpu(xen_pmu_irq, cpu).irq, NULL);
 		per_cpu(xen_pmu_irq, cpu).irq = -1;
-		kfree(per_cpu(xen_pmu_irq, cpu).name);
-		per_cpu(xen_pmu_irq, cpu).name = NULL;
 	}
 }
 
@@ -117,6 +121,7 @@
 	char *callfunc_name, *pmu_name;
 
 	callfunc_name = kasprintf(GFP_KERNEL, "irqwork%d", cpu);
+	per_cpu(xen_irq_work, cpu).name = callfunc_name;
 	rc = bind_ipi_to_irqhandler(XEN_IRQ_WORK_VECTOR,
 				    cpu,
 				    xen_irq_work_interrupt,
@@ -126,10 +131,10 @@
 	if (rc < 0)
 		goto fail;
 	per_cpu(xen_irq_work, cpu).irq = rc;
-	per_cpu(xen_irq_work, cpu).name = callfunc_name;
 
-	if (is_xen_pmu(cpu)) {
+	if (is_xen_pmu) {
 		pmu_name = kasprintf(GFP_KERNEL, "pmu%d", cpu);
+		per_cpu(xen_pmu_irq, cpu).name = pmu_name;
 		rc = bind_virq_to_irqhandler(VIRQ_XENPMU, cpu,
 					     xen_pmu_irq_handler,
 					     IRQF_PERCPU|IRQF_NOBALANCING,
@@ -137,7 +142,6 @@
 		if (rc < 0)
 			goto fail;
 		per_cpu(xen_pmu_irq, cpu).irq = rc;
-		per_cpu(xen_pmu_irq, cpu).name = pmu_name;
 	}
 
 	return 0;
@@ -309,7 +313,7 @@
 	 * pointing just below where pt_regs would be if it were a normal
 	 * kernel entry.
 	 */
-	ctxt->user_regs.eip = (unsigned long)cpu_bringup_and_idle;
+	ctxt->user_regs.eip = (unsigned long)asm_cpu_bringup_and_idle;
 	ctxt->flags = VGCF_IN_KERNEL;
 	ctxt->user_regs.eflags = 0x1000; /* IOPL_RING1 */
 	ctxt->user_regs.ds = __USER_DS;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/xen/spinlock.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/xen/spinlock.c
@@ -75,6 +75,7 @@
 	     cpu, per_cpu(lock_kicker_irq, cpu));
 
 	name = kasprintf(GFP_KERNEL, "spinlock%d", cpu);
+	per_cpu(irq_name, cpu) = name;
 	irq = bind_ipi_to_irqhandler(XEN_SPIN_UNLOCK_VECTOR,
 				     cpu,
 				     dummy_handler,
@@ -85,7 +86,6 @@
 	if (irq >= 0) {
 		disable_irq(irq); /* make sure it's never delivered */
 		per_cpu(lock_kicker_irq, cpu) = irq;
-		per_cpu(irq_name, cpu) = name;
 	}
 
 	printk("cpu %d spinlock event irq %d\n", cpu, irq);
@@ -93,13 +93,23 @@
 
 void xen_uninit_lock_cpu(int cpu)
 {
+	int irq;
+
 	if (!xen_pvspin)
 		return;
 
-	unbind_from_irqhandler(per_cpu(lock_kicker_irq, cpu), NULL);
-	per_cpu(lock_kicker_irq, cpu) = -1;
 	kfree(per_cpu(irq_name, cpu));
 	per_cpu(irq_name, cpu) = NULL;
+	/*
+	 * When booting the kernel with 'mitigations=auto,nosmt', the secondary
+	 * CPUs are not activated, and lock_kicker_irq is not initialized.
+	 */
+	irq = per_cpu(lock_kicker_irq, cpu);
+	if (irq == -1)
+		return;
+
+	unbind_from_irqhandler(irq, NULL);
+	per_cpu(lock_kicker_irq, cpu) = -1;
 }
 
 PV_CALLEE_SAVE_REGS_THUNK(xen_vcpu_stolen);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/xen/time.c
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/xen/time.c
@@ -547,6 +547,11 @@
 
 void __init xen_hvm_init_time_ops(void)
 {
+	static bool hvm_time_initialized;
+
+	if (hvm_time_initialized)
+		return;
+
 	/*
 	 * vector callback is needed otherwise we cannot receive interrupts
 	 * on cpu > 0 and at this point we don't know how many cpus are
@@ -556,7 +561,22 @@
 		return;
 
 	if (!xen_feature(XENFEAT_hvm_safe_pvclock)) {
-		pr_info("Xen doesn't support pvclock on HVM, disable pv timer");
+		pr_info_once("Xen doesn't support pvclock on HVM, disable pv timer");
+		return;
+	}
+
+	/*
+	 * Only MAX_VIRT_CPUS 'vcpu_info' are embedded inside 'shared_info'.
+	 * The __this_cpu_read(xen_vcpu) is still NULL when Xen HVM guest
+	 * boots on vcpu >= MAX_VIRT_CPUS (e.g., kexec), To access
+	 * __this_cpu_read(xen_vcpu) via xen_clocksource_read() will panic.
+	 *
+	 * The xen_hvm_init_time_ops() should be called again later after
+	 * __this_cpu_read(xen_vcpu) is available.
+	 */
+	if (!__this_cpu_read(xen_vcpu)) {
+		pr_info("Delay xen_init_time_common() as kernel is running on vcpu=%d\n",
+			xen_vcpu_nr(0));
 		return;
 	}
 
@@ -568,6 +588,8 @@
 	x86_platform.calibrate_tsc = xen_tsc_khz;
 	x86_platform.get_wallclock = xen_get_wallclock;
 	x86_platform.set_wallclock = xen_set_wallclock;
+
+	hvm_time_initialized = true;
 }
 #endif
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/xen/xen-asm_32.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/xen/xen-asm_32.S
@@ -56,7 +56,7 @@
 	_ASM_EXTABLE(1b,2b)
 .endm
 
-ENTRY(xen_iret)
+SYM_CODE_START(xen_iret)
 	/* test eflags for special cases */
 	testl $(X86_EFLAGS_VM | XEN_EFLAGS_NMI), 8(%esp)
 	jnz hyper_iret
@@ -122,14 +122,14 @@
 hyper_iret:
 	/* put this out of line since its very rarely used */
 	jmp hypercall_page + __HYPERVISOR_iret * 32
+SYM_CODE_END(xen_iret)
 
 	.globl xen_iret_start_crit, xen_iret_end_crit
 
 /*
- * This is called by xen_hypervisor_callback in entry.S when it sees
+ * This is called by xen_hypervisor_callback in entry_32.S when it sees
  * that the EIP at the time of interrupt was between
- * xen_iret_start_crit and xen_iret_end_crit.  We're passed the EIP in
- * %eax so we can do a more refined determination of what to do.
+ * xen_iret_start_crit and xen_iret_end_crit.
  *
  * The stack format at this point is:
  *	----------------
@@ -138,70 +138,46 @@
  *	 eflags		}  outer exception info
  *	 cs		}
  *	 eip		}
- *	---------------- <- edi (copy dest)
- *	 eax		:  outer eax if it hasn't been restored
  *	----------------
- *	 eflags		}  nested exception info
- *	 cs		}   (no ss/esp because we're nested
- *	 eip		}    from the same ring)
- *	 orig_eax	}<- esi (copy src)
- *	 - - - - - - - -
- *	 fs		}
- *	 es		}
- *	 ds		}  SAVE_ALL state
- *	 eax		}
- *	  :		:
- *	 ebx		}<- esp
+ *	 eax		:  outer eax if it hasn't been restored
  *	----------------
+ *	 eflags		}
+ *	 cs		}  nested exception info
+ *	 eip		}
+ *	 return address	: (into xen_hypervisor_callback)
  *
- * In order to deliver the nested exception properly, we need to shift
- * everything from the return addr up to the error code so it sits
- * just under the outer exception info.  This means that when we
- * handle the exception, we do it in the context of the outer
- * exception rather than starting a new one.
+ * In order to deliver the nested exception properly, we need to discard the
+ * nested exception frame such that when we handle the exception, we do it
+ * in the context of the outer exception rather than starting a new one.
  *
- * The only caveat is that if the outer eax hasn't been restored yet
- * (ie, it's still on stack), we need to insert its value into the
- * SAVE_ALL state before going on, since it's usermode state which we
- * eventually need to restore.
+ * The only caveat is that if the outer eax hasn't been restored yet (i.e.
+ * it's still on stack), we need to restore its value here.
  */
-ENTRY(xen_iret_crit_fixup)
+SYM_CODE_START(xen_iret_crit_fixup)
 	/*
 	 * Paranoia: Make sure we're really coming from kernel space.
 	 * One could imagine a case where userspace jumps into the
 	 * critical range address, but just before the CPU delivers a
-	 * GP, it decides to deliver an interrupt instead.  Unlikely?
-	 * Definitely.  Easy to avoid?  Yes.  The Intel documents
-	 * explicitly say that the reported EIP for a bad jump is the
-	 * jump instruction itself, not the destination, but some
-	 * virtual environments get this wrong.
-	 */
-	movl PT_CS(%esp), %ecx
-	andl $SEGMENT_RPL_MASK, %ecx
-	cmpl $USER_RPL, %ecx
-	je 2f
-
-	lea PT_ORIG_EAX(%esp), %esi
-	lea PT_EFLAGS(%esp), %edi
+	 * PF, it decides to deliver an interrupt instead.  Unlikely?
+	 * Definitely.  Easy to avoid?  Yes.
+	 */
+	testb $2, 2*4(%esp)		/* nested CS */
+	jnz 2f
 
 	/*
 	 * If eip is before iret_restore_end then stack
 	 * hasn't been restored yet.
 	 */
-	cmp $iret_restore_end, %eax
+	cmpl $iret_restore_end, 1*4(%esp)
 	jae 1f
 
-	movl 0+4(%edi), %eax		/* copy EAX (just above top of frame) */
-	movl %eax, PT_EAX(%esp)
-
-	lea ESP_OFFSET(%edi), %edi	/* move dest up over saved regs */
-
-	/* set up the copy */
-1:	std
-	mov $PT_EIP / 4, %ecx		/* saved regs up to orig_eax */
-	rep movsl
-	cld
-
-	lea 4(%edi), %esp		/* point esp to new frame */
-2:	jmp xen_do_upcall
-
+	movl 4*4(%esp), %eax		/* load outer EAX */
+	ret $4*4			/* discard nested EIP, CS, and EFLAGS as
+					 * well as the just restored EAX */
+
+1:
+	ret $3*4			/* discard nested EIP, CS, and EFLAGS */
+
+2:
+	ret
+SYM_CODE_END(xen_iret_crit_fixup)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/xen/xen-head.S
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/xen/xen-head.S
@@ -35,7 +35,11 @@
 	rep __ASM_SIZE(stos)
 
 	mov %_ASM_SI, xen_start_info
-	mov $init_thread_union+THREAD_SIZE, %_ASM_SP
+#ifdef CONFIG_X86_64
+	mov initial_stack(%rip), %rsp
+#else
+	mov initial_stack, %esp
+#endif
 
 #ifdef CONFIG_X86_64
 	/* Set up %gs.
@@ -51,9 +55,19 @@
 	wrmsr
 #endif
 
-	jmp xen_start_kernel
+	call xen_start_kernel
 END(startup_xen)
 	__FINIT
+
+#ifdef CONFIG_XEN_PV_SMP
+.pushsection .text
+SYM_CODE_START(asm_cpu_bringup_and_idle)
+	UNWIND_HINT_EMPTY
+
+	call cpu_bringup_and_idle
+SYM_CODE_END(asm_cpu_bringup_and_idle)
+.popsection
+#endif
 #endif
 
 .pushsection .text
--- linux-xilinx-zynqmp-5.4.0.orig/arch/x86/xen/xen-ops.h
+++ linux-xilinx-zynqmp-5.4.0/arch/x86/xen/xen-ops.h
@@ -30,6 +30,8 @@
 extern struct shared_info xen_dummy_shared_info;
 extern struct shared_info *HYPERVISOR_shared_info;
 
+extern bool xen_fifo_events;
+
 void xen_setup_mfn_list_list(void);
 void xen_build_mfn_list_list(void);
 void xen_setup_machphys_mapping(void);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/Kconfig
@@ -22,11 +22,12 @@
 	select HAVE_ARCH_JUMP_LABEL
 	select HAVE_ARCH_KASAN if MMU
 	select HAVE_ARCH_TRACEHOOK
+	select HAVE_COPY_THREAD_TLS
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DMA_CONTIGUOUS
 	select HAVE_EXIT_THREAD
 	select HAVE_FUNCTION_TRACER
-	select HAVE_FUTEX_CMPXCHG if !MMU
+	select HAVE_FUTEX_CMPXCHG if !MMU && FUTEX
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS
 	select HAVE_IRQ_TIME_ACCOUNTING
 	select HAVE_OPROFILE
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/boot/Makefile
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/boot/Makefile
@@ -9,8 +9,7 @@
 
 
 # KBUILD_CFLAGS used when building rest of boot (takes effect recursively)
-KBUILD_CFLAGS	+= -fno-builtin -Iarch/$(ARCH)/boot/include
-HOSTFLAGS	+= -Iarch/$(ARCH)/boot/include
+KBUILD_CFLAGS	+= -fno-builtin
 
 BIG_ENDIAN	:= $(shell echo __XTENSA_EB__ | $(CC) -E - | grep -v "\#")
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/boot/dts/xtfpga-flash-128m.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/boot/dts/xtfpga-flash-128m.dtsi
@@ -8,19 +8,19 @@
 			reg = <0x00000000 0x08000000>;
 			bank-width = <2>;
 			device-width = <2>;
-			partition@0x0 {
+			partition@0 {
 				label = "data";
 				reg = <0x00000000 0x06000000>;
 			};
-			partition@0x6000000 {
+			partition@6000000 {
 				label = "boot loader area";
 				reg = <0x06000000 0x00800000>;
 			};
-			partition@0x6800000 {
+			partition@6800000 {
 				label = "kernel image";
 				reg = <0x06800000 0x017e0000>;
 			};
-			partition@0x7fe0000 {
+			partition@7fe0000 {
 				label = "boot environment";
 				reg = <0x07fe0000 0x00020000>;
 			};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/boot/dts/xtfpga-flash-16m.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/boot/dts/xtfpga-flash-16m.dtsi
@@ -8,19 +8,19 @@
 			reg = <0x08000000 0x01000000>;
 			bank-width = <2>;
 			device-width = <2>;
-			partition@0x0 {
+			partition@0 {
 				label = "boot loader area";
 				reg = <0x00000000 0x00400000>;
 			};
-			partition@0x400000 {
+			partition@400000 {
 				label = "kernel image";
 				reg = <0x00400000 0x00600000>;
 			};
-			partition@0xa00000 {
+			partition@a00000 {
 				label = "data";
 				reg = <0x00a00000 0x005e0000>;
 			};
-			partition@0xfe0000 {
+			partition@fe0000 {
 				label = "boot environment";
 				reg = <0x00fe0000 0x00020000>;
 			};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/boot/dts/xtfpga-flash-4m.dtsi
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/boot/dts/xtfpga-flash-4m.dtsi
@@ -8,11 +8,11 @@
 			reg = <0x08000000 0x00400000>;
 			bank-width = <2>;
 			device-width = <2>;
-			partition@0x0 {
+			partition@0 {
 				label = "boot loader area";
 				reg = <0x00000000 0x003f0000>;
 			};
-			partition@0x3f0000 {
+			partition@3f0000 {
 				label = "boot environment";
 				reg = <0x003f0000 0x00010000>;
 			};
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/boot/lib/zmem.c
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/boot/lib/zmem.c
@@ -4,13 +4,14 @@
 /* bits taken from ppc */
 
 extern void *avail_ram, *end_avail;
+void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp);
 
-void exit (void)
+static void exit(void)
 {
   for (;;);
 }
 
-void *zalloc(unsigned size)
+static void *zalloc(unsigned int size)
 {
         void *p = avail_ram;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/include/asm/Kbuild
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/include/asm/Kbuild
@@ -4,7 +4,6 @@
 generic-y += compat.h
 generic-y += device.h
 generic-y += div64.h
-generic-y += dma-contiguous.h
 generic-y += dma-mapping.h
 generic-y += emergency-restart.h
 generic-y += exec.h
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/include/asm/core.h
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/include/asm/core.h
@@ -6,6 +6,10 @@
 
 #include <variant/core.h>
 
+#ifndef XCHAL_HAVE_DIV32
+#define XCHAL_HAVE_DIV32 0
+#endif
+
 #ifndef XCHAL_HAVE_EXCLUSIVE
 #define XCHAL_HAVE_EXCLUSIVE 0
 #endif
@@ -18,4 +22,13 @@
 #define XCHAL_SPANNING_WAY 0
 #endif
 
+#ifndef XCHAL_HW_MIN_VERSION
+#if defined(XCHAL_HW_MIN_VERSION_MAJOR) && defined(XCHAL_HW_MIN_VERSION_MINOR)
+#define XCHAL_HW_MIN_VERSION (XCHAL_HW_MIN_VERSION_MAJOR * 100 + \
+			      XCHAL_HW_MIN_VERSION_MINOR)
+#else
+#define XCHAL_HW_MIN_VERSION 0
+#endif
+#endif
+
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/include/asm/kmem_layout.h
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/include/asm/kmem_layout.h
@@ -11,6 +11,7 @@
 #ifndef _XTENSA_KMEM_LAYOUT_H
 #define _XTENSA_KMEM_LAYOUT_H
 
+#include <asm/core.h>
 #include <asm/types.h>
 
 #ifdef CONFIG_MMU
@@ -65,6 +66,34 @@
 
 #endif
 
+/* KIO definition */
+
+#if XCHAL_HAVE_PTP_MMU
+#define XCHAL_KIO_CACHED_VADDR		0xe0000000
+#define XCHAL_KIO_BYPASS_VADDR		0xf0000000
+#define XCHAL_KIO_DEFAULT_PADDR		0xf0000000
+#else
+#define XCHAL_KIO_BYPASS_VADDR		XCHAL_KIO_PADDR
+#define XCHAL_KIO_DEFAULT_PADDR		0x90000000
+#endif
+#define XCHAL_KIO_SIZE			0x10000000
+
+#if (!XCHAL_HAVE_PTP_MMU || XCHAL_HAVE_SPANNING_WAY) && defined(CONFIG_USE_OF)
+#define XCHAL_KIO_PADDR			xtensa_get_kio_paddr()
+#ifndef __ASSEMBLY__
+extern unsigned long xtensa_kio_paddr;
+
+static inline unsigned long xtensa_get_kio_paddr(void)
+{
+	return xtensa_kio_paddr;
+}
+#endif
+#else
+#define XCHAL_KIO_PADDR			XCHAL_KIO_DEFAULT_PADDR
+#endif
+
+/* KERNEL_STACK definition */
+
 #ifndef CONFIG_KASAN
 #define KERNEL_STACK_SHIFT	13
 #else
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/include/asm/page.h
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/include/asm/page.h
@@ -181,10 +181,6 @@
 #define pfn_valid(pfn) \
 	((pfn) >= ARCH_PFN_OFFSET && ((pfn) - ARCH_PFN_OFFSET) < max_mapnr)
 
-#ifdef CONFIG_DISCONTIGMEM
-# error CONFIG_DISCONTIGMEM not supported
-#endif
-
 #define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
 #define page_to_virt(page)	__va(page_to_pfn(page) << PAGE_SHIFT)
 #define virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/include/asm/pgtable.h
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/include/asm/pgtable.h
@@ -70,7 +70,7 @@
  */
 #define VMALLOC_START		(XCHAL_KSEG_CACHED_VADDR - 0x10000000)
 #define VMALLOC_END		(VMALLOC_START + 0x07FEFFFF)
-#define TLBTEMP_BASE_1		(VMALLOC_END + 1)
+#define TLBTEMP_BASE_1		(VMALLOC_START + 0x08000000)
 #define TLBTEMP_BASE_2		(TLBTEMP_BASE_1 + DCACHE_WAY_SIZE)
 #if 2 * DCACHE_WAY_SIZE > ICACHE_WAY_SIZE
 #define TLBTEMP_SIZE		(2 * DCACHE_WAY_SIZE)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/include/asm/processor.h
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/include/asm/processor.h
@@ -225,8 +225,8 @@
 
 #define xtensa_set_sr(x, sr) \
 	({ \
-	 unsigned int v = (unsigned int)(x); \
-	 __asm__ __volatile__ ("wsr %0, "__stringify(sr) :: "a"(v)); \
+	 __asm__ __volatile__ ("wsr %0, "__stringify(sr) :: \
+			       "a"((unsigned int)(x))); \
 	 })
 
 #define xtensa_get_sr(sr) \
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/include/asm/syscall.h
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/include/asm/syscall.h
@@ -51,7 +51,7 @@
 					    struct pt_regs *regs,
 					    int error, long val)
 {
-	regs->areg[0] = (long) error ? error : val;
+	regs->areg[2] = (long) error ? error : val;
 }
 
 #define SYSCALL_MAX_ARGS 6
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/include/asm/thread_info.h
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/include/asm/thread_info.h
@@ -55,6 +55,10 @@
 	mm_segment_t		addr_limit;	/* thread address space */
 
 	unsigned long		cpenable;
+#if XCHAL_HAVE_EXCLUSIVE
+	/* result of the most recent exclusive store */
+	unsigned long		atomctl8;
+#endif
 
 	/* Allocate storage for extra user states and coprocessor states. */
 #if XTENSA_HAVE_COPROCESSORS
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/include/asm/timex.h
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/include/asm/timex.h
@@ -29,10 +29,6 @@
 
 extern unsigned long ccount_freq;
 
-typedef unsigned long long cycles_t;
-
-#define get_cycles()	(0)
-
 void local_timer_setup(unsigned cpu);
 
 /*
@@ -59,4 +55,6 @@
 	xtensa_set_sr(ccompare, SREG_CCOMPARE + LINUX_TIMER);
 }
 
+#include <asm-generic/timex.h>
+
 #endif	/* _XTENSA_TIMEX_H */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/include/asm/uaccess.h
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/include/asm/uaccess.h
@@ -300,7 +300,7 @@
 	return -EFAULT;
 }
 #else
-long strncpy_from_user(char *dst, const char *src, long count);
+long strncpy_from_user(char *dst, const char __user *src, long count);
 #endif
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/include/asm/vectors.h
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/include/asm/vectors.h
@@ -21,50 +21,14 @@
 #include <asm/core.h>
 #include <asm/kmem_layout.h>
 
-#if XCHAL_HAVE_PTP_MMU
-#define XCHAL_KIO_CACHED_VADDR		0xe0000000
-#define XCHAL_KIO_BYPASS_VADDR		0xf0000000
-#define XCHAL_KIO_DEFAULT_PADDR		0xf0000000
-#else
-#define XCHAL_KIO_BYPASS_VADDR		XCHAL_KIO_PADDR
-#define XCHAL_KIO_DEFAULT_PADDR		0x90000000
-#endif
-#define XCHAL_KIO_SIZE			0x10000000
-
-#if (!XCHAL_HAVE_PTP_MMU || XCHAL_HAVE_SPANNING_WAY) && defined(CONFIG_OF)
-#define XCHAL_KIO_PADDR			xtensa_get_kio_paddr()
-#ifndef __ASSEMBLY__
-extern unsigned long xtensa_kio_paddr;
-
-static inline unsigned long xtensa_get_kio_paddr(void)
-{
-	return xtensa_kio_paddr;
-}
-#endif
-#else
-#define XCHAL_KIO_PADDR			XCHAL_KIO_DEFAULT_PADDR
-#endif
-
-#if defined(CONFIG_MMU)
-
-#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY
-/* Image Virtual Start Address */
-#define KERNELOFFSET			(XCHAL_KSEG_CACHED_VADDR + \
-					 CONFIG_KERNEL_LOAD_ADDRESS - \
+#if defined(CONFIG_MMU) && XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY
+#define KERNELOFFSET			(CONFIG_KERNEL_LOAD_ADDRESS + \
+					 XCHAL_KSEG_CACHED_VADDR - \
 					 XCHAL_KSEG_PADDR)
 #else
 #define KERNELOFFSET			CONFIG_KERNEL_LOAD_ADDRESS
 #endif
 
-#else /* !defined(CONFIG_MMU) */
-  /* MMU Not being used - Virtual == Physical */
-
-/* Location of the start of the kernel text, _start */
-#define KERNELOFFSET			CONFIG_KERNEL_LOAD_ADDRESS
-
-
-#endif /* CONFIG_MMU */
-
 #define RESET_VECTOR1_VADDR		(XCHAL_RESET_VECTOR1_VADDR)
 #ifdef CONFIG_VECTORS_OFFSET
 #define VECBASE_VADDR			(KERNELOFFSET - CONFIG_VECTORS_OFFSET)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/kernel/asm-offsets.c
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/kernel/asm-offsets.c
@@ -93,6 +93,9 @@
 	DEFINE(THREAD_RA, offsetof (struct task_struct, thread.ra));
 	DEFINE(THREAD_SP, offsetof (struct task_struct, thread.sp));
 	DEFINE(THREAD_CPENABLE, offsetof (struct thread_info, cpenable));
+#if XCHAL_HAVE_EXCLUSIVE
+	DEFINE(THREAD_ATOMCTL8, offsetof (struct thread_info, atomctl8));
+#endif
 #if XTENSA_HAVE_COPROCESSORS
 	DEFINE(THREAD_XTREGS_CP0, offsetof(struct thread_info, xtregs_cp.cp0));
 	DEFINE(THREAD_XTREGS_CP1, offsetof(struct thread_info, xtregs_cp.cp1));
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/kernel/coprocessor.S
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/kernel/coprocessor.S
@@ -37,7 +37,7 @@
 	.if XTENSA_HAVE_COPROCESSOR(x);					\
 		.align 4;						\
 	.Lsave_cp_regs_cp##x:						\
-		xchal_cp##x##_store a2 a4 a5 a6 a7;			\
+		xchal_cp##x##_store a2 a3 a4 a5 a6;			\
 		jx	a0;						\
 	.endif
 
@@ -54,7 +54,7 @@
 	.if XTENSA_HAVE_COPROCESSOR(x);					\
 		.align 4;						\
 	.Lload_cp_regs_cp##x:						\
-		xchal_cp##x##_load a2 a4 a5 a6 a7;			\
+		xchal_cp##x##_load a2 a3 a4 a5 a6;			\
 		jx	a0;						\
 	.endif
 
@@ -109,37 +109,6 @@
 	.previous
 
 /*
- * coprocessor_flush(struct thread_info*, index)
- *                             a2        a3
- *
- * Save coprocessor registers for coprocessor 'index'.
- * The register values are saved to or loaded from the coprocessor area 
- * inside the task_info structure.
- *
- * Note that this function doesn't update the coprocessor_owner information!
- *
- */
-
-ENTRY(coprocessor_flush)
-
-	/* reserve 4 bytes on stack to save a0 */
-	abi_entry(4)
-
-	s32i	a0, a1, 0
-	movi	a0, .Lsave_cp_regs_jump_table
-	addx8	a3, a3, a0
-	l32i	a4, a3, 4
-	l32i	a3, a3, 0
-	add	a2, a2, a4
-	beqz	a3, 1f
-	callx0	a3
-1:	l32i	a0, a1, 0
-
-	abi_ret(4)
-
-ENDPROC(coprocessor_flush)
-
-/*
  * Entry condition:
  *
  *   a0:	trashed, original value saved on stack (PT_AREG0)
@@ -261,6 +230,39 @@
 
 ENDPROC(fast_coprocessor)
 
+	.text
+
+/*
+ * coprocessor_flush(struct thread_info*, index)
+ *                             a2        a3
+ *
+ * Save coprocessor registers for coprocessor 'index'.
+ * The register values are saved to or loaded from the coprocessor area
+ * inside the task_info structure.
+ *
+ * Note that this function doesn't update the coprocessor_owner information!
+ *
+ */
+
+ENTRY(coprocessor_flush)
+
+	/* reserve 4 bytes on stack to save a0 */
+	abi_entry(4)
+
+	s32i	a0, a1, 0
+	movi	a0, .Lsave_cp_regs_jump_table
+	addx8	a3, a3, a0
+	l32i	a4, a3, 4
+	l32i	a3, a3, 0
+	add	a2, a2, a4
+	beqz	a3, 1f
+	callx0	a3
+1:	l32i	a0, a1, 0
+
+	abi_ret(4)
+
+ENDPROC(coprocessor_flush)
+
 	.data
 
 ENTRY(coprocessor_owner)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/kernel/entry.S
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/kernel/entry.S
@@ -374,6 +374,11 @@
 	s32i	a2, a1, PT_LCOUNT
 #endif
 
+#if XCHAL_HAVE_EXCLUSIVE
+	/* Clear exclusive access monitor set by interrupted code */
+	clrex
+#endif
+
 	/* It is now save to restore the EXC_TABLE_FIXUP variable. */
 
 	rsr	a2, exccause
@@ -1892,6 +1897,7 @@
 
 	mov	a6, a2
 	call4	do_syscall_trace_enter
+	beqz	a6, .Lsyscall_exit
 	l32i	a7, a2, PT_SYSCALL
 
 1:
@@ -1906,8 +1912,6 @@
 
 	addx4	a4, a7, a4
 	l32i	a4, a4, 0
-	movi	a5, sys_ni_syscall;
-	beq	a4, a5, 1f
 
 	/* Load args: arg0 - arg5 are passed via regs. */
 
@@ -1927,6 +1931,7 @@
 
 	s32i	a6, a2, PT_AREG2
 	bnez	a3, 1f
+.Lsyscall_exit:
 	abi_ret(4)
 
 1:
@@ -2024,6 +2029,12 @@
 	s32i	a3, a4, THREAD_CPENABLE
 #endif
 
+#if XCHAL_HAVE_EXCLUSIVE
+	l32i	a3, a5, THREAD_ATOMCTL8
+	getex	a3
+	s32i	a3, a4, THREAD_ATOMCTL8
+#endif
+
 	/* Flush register file. */
 
 	spill_registers_kernel
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/kernel/irq.c
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/kernel/irq.c
@@ -145,7 +145,7 @@
 
 void __init init_IRQ(void)
 {
-#ifdef CONFIG_OF
+#ifdef CONFIG_USE_OF
 	irqchip_init();
 #else
 #ifdef CONFIG_HAVE_SMP
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/kernel/jump_label.c
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/kernel/jump_label.c
@@ -40,7 +40,7 @@
 {
 	struct patch *patch = data;
 
-	if (atomic_inc_return(&patch->cpu_count) == 1) {
+	if (atomic_inc_return(&patch->cpu_count) == num_online_cpus()) {
 		local_patch_text(patch->addr, patch->data, patch->sz);
 		atomic_inc(&patch->cpu_count);
 	} else {
@@ -61,7 +61,7 @@
 			.data = data,
 		};
 		stop_machine_cpuslocked(patch_text_stop_machine,
-					&patch, NULL);
+					&patch, cpu_online_mask);
 	} else {
 		unsigned long flags;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/kernel/pci-dma.c
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/kernel/pci-dma.c
@@ -44,8 +44,8 @@
 		}
 }
 
-void arch_sync_dma_for_cpu(struct device *dev, phys_addr_t paddr,
-		size_t size, enum dma_data_direction dir)
+void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size,
+		enum dma_data_direction dir)
 {
 	switch (dir) {
 	case DMA_BIDIRECTIONAL:
@@ -62,8 +62,8 @@
 	}
 }
 
-void arch_sync_dma_for_device(struct device *dev, phys_addr_t paddr,
-		size_t size, enum dma_data_direction dir)
+void arch_sync_dma_for_device(phys_addr_t paddr, size_t size,
+		enum dma_data_direction dir)
 {
 	switch (dir) {
 	case DMA_BIDIRECTIONAL:
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/kernel/perf_event.c
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/kernel/perf_event.c
@@ -13,17 +13,26 @@
 #include <linux/perf_event.h>
 #include <linux/platform_device.h>
 
+#include <asm/core.h>
 #include <asm/processor.h>
 #include <asm/stacktrace.h>
 
+#define XTENSA_HWVERSION_RG_2015_0	260000
+
+#if XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_RG_2015_0
+#define XTENSA_PMU_ERI_BASE		0x00101000
+#else
+#define XTENSA_PMU_ERI_BASE		0x00001000
+#endif
+
 /* Global control/status for all perf counters */
-#define XTENSA_PMU_PMG			0x1000
+#define XTENSA_PMU_PMG			XTENSA_PMU_ERI_BASE
 /* Perf counter values */
-#define XTENSA_PMU_PM(i)		(0x1080 + (i) * 4)
+#define XTENSA_PMU_PM(i)		(XTENSA_PMU_ERI_BASE + 0x80 + (i) * 4)
 /* Perf counter control registers */
-#define XTENSA_PMU_PMCTRL(i)		(0x1100 + (i) * 4)
+#define XTENSA_PMU_PMCTRL(i)		(XTENSA_PMU_ERI_BASE + 0x100 + (i) * 4)
 /* Perf counter status registers */
-#define XTENSA_PMU_PMSTAT(i)		(0x1180 + (i) * 4)
+#define XTENSA_PMU_PMSTAT(i)		(XTENSA_PMU_ERI_BASE + 0x180 + (i) * 4)
 
 #define XTENSA_PMU_PMG_PMEN		0x1
 
@@ -401,7 +410,7 @@
 	.read = xtensa_pmu_read,
 };
 
-static int xtensa_pmu_setup(int cpu)
+static int xtensa_pmu_setup(unsigned int cpu)
 {
 	unsigned i;
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/kernel/process.c
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/kernel/process.c
@@ -202,8 +202,9 @@
  * involved.  Much simpler to just not copy those live frames across.
  */
 
-int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn,
-		unsigned long thread_fn_arg, struct task_struct *p)
+int copy_thread_tls(unsigned long clone_flags, unsigned long usp_thread_fn,
+		unsigned long thread_fn_arg, struct task_struct *p,
+		unsigned long tls)
 {
 	struct pt_regs *childregs = task_pt_regs(p);
 
@@ -264,9 +265,8 @@
 			       &regs->areg[XCHAL_NUM_AREGS - len/4], len);
 		}
 
-		/* The thread pointer is passed in the '4th argument' (= a5) */
 		if (clone_flags & CLONE_SETTLS)
-			childregs->threadptr = childregs->areg[5];
+			childregs->threadptr = tls;
 	} else {
 		p->thread.ra = MAKE_RA_FOR_CALL(
 				(unsigned long)ret_from_kernel_thread, 1);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/kernel/ptrace.c
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/kernel/ptrace.c
@@ -225,12 +225,12 @@
 
 void user_enable_single_step(struct task_struct *child)
 {
-	child->ptrace |= PT_SINGLESTEP;
+	set_tsk_thread_flag(child, TIF_SINGLESTEP);
 }
 
 void user_disable_single_step(struct task_struct *child)
 {
-	child->ptrace &= ~PT_SINGLESTEP;
+	clear_tsk_thread_flag(child, TIF_SINGLESTEP);
 }
 
 /*
@@ -542,14 +542,28 @@
 	return ret;
 }
 
-void do_syscall_trace_enter(struct pt_regs *regs)
+void do_syscall_trace_leave(struct pt_regs *regs);
+int do_syscall_trace_enter(struct pt_regs *regs)
 {
+	if (regs->syscall == NO_SYSCALL)
+		regs->areg[2] = -ENOSYS;
+
 	if (test_thread_flag(TIF_SYSCALL_TRACE) &&
-	    tracehook_report_syscall_entry(regs))
+	    tracehook_report_syscall_entry(regs)) {
+		regs->areg[2] = -ENOSYS;
 		regs->syscall = NO_SYSCALL;
+		return 0;
+	}
+
+	if (regs->syscall == NO_SYSCALL) {
+		do_syscall_trace_leave(regs);
+		return 0;
+	}
 
 	if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
 		trace_sys_enter(regs, syscall_get_nr(current, regs));
+
+	return 1;
 }
 
 void do_syscall_trace_leave(struct pt_regs *regs)
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/kernel/setup.c
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/kernel/setup.c
@@ -64,7 +64,7 @@
 extern int initrd_below_start_ok;
 #endif
 
-#ifdef CONFIG_OF
+#ifdef CONFIG_USE_OF
 void *dtb_start = __dtb_start;
 #endif
 
@@ -126,7 +126,7 @@
 
 #endif /* CONFIG_BLK_DEV_INITRD */
 
-#ifdef CONFIG_OF
+#ifdef CONFIG_USE_OF
 
 static int __init parse_tag_fdt(const bp_tag_t *tag)
 {
@@ -136,7 +136,7 @@
 
 __tagtable(BP_TAG_FDT, parse_tag_fdt);
 
-#endif /* CONFIG_OF */
+#endif /* CONFIG_USE_OF */
 
 static int __init parse_tag_cmdline(const bp_tag_t* tag)
 {
@@ -184,7 +184,7 @@
 }
 #endif
 
-#ifdef CONFIG_OF
+#ifdef CONFIG_USE_OF
 
 #if !XCHAL_HAVE_PTP_MMU || XCHAL_HAVE_SPANNING_WAY
 unsigned long xtensa_kio_paddr = XCHAL_KIO_DEFAULT_PADDR;
@@ -233,7 +233,7 @@
 		strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
 }
 
-#endif /* CONFIG_OF */
+#endif /* CONFIG_USE_OF */
 
 /*
  * Initialize architecture. (Early stage)
@@ -254,7 +254,7 @@
 	if (bp_start)
 		parse_bootparam(bp_start);
 
-#ifdef CONFIG_OF
+#ifdef CONFIG_USE_OF
 	early_init_devtree(dtb_start);
 #endif
 
@@ -716,7 +716,8 @@
 static void *
 c_next(struct seq_file *f, void *v, loff_t *pos)
 {
-	return NULL;
+	++*pos;
+	return c_start(f, pos);
 }
 
 static void
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/kernel/signal.c
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/kernel/signal.c
@@ -465,7 +465,7 @@
 		/* Set up the stack frame */
 		ret = setup_frame(&ksig, sigmask_to_save(), regs);
 		signal_setup_done(ret, &ksig, 0);
-		if (current->ptrace & PT_SINGLESTEP)
+		if (test_thread_flag(TIF_SINGLESTEP))
 			task_pt_regs(current)->icountlevel = 1;
 
 		return;
@@ -491,7 +491,7 @@
 	/* If there's no signal to deliver, we just restore the saved mask.  */
 	restore_saved_sigmask();
 
-	if (current->ptrace & PT_SINGLESTEP)
+	if (test_thread_flag(TIF_SINGLESTEP))
 		task_pt_regs(current)->icountlevel = 1;
 	return;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/kernel/time.c
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/kernel/time.c
@@ -160,6 +160,7 @@
 	cpu = of_find_compatible_node(NULL, NULL, "cdns,xtensa-cpu");
 	if (cpu) {
 		clk = of_clk_get(cpu, 0);
+		of_node_put(cpu);
 		if (!IS_ERR(clk)) {
 			ccount_freq = clk_get_rate(clk);
 			return;
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/kernel/traps.c
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/kernel/traps.c
@@ -543,5 +543,5 @@
 	if (panic_on_oops)
 		panic("Fatal exception");
 
-	do_exit(err);
+	make_task_dead(err);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/kernel/xtensa_ksyms.c
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/kernel/xtensa_ksyms.c
@@ -87,13 +87,13 @@
 }
 EXPORT_SYMBOL(__xtensa_libgcc_window_spill);
 
-unsigned long __sync_fetch_and_and_4(unsigned long *p, unsigned long v)
+unsigned int __sync_fetch_and_and_4(volatile void *p, unsigned int v)
 {
 	BUG();
 }
 EXPORT_SYMBOL(__sync_fetch_and_and_4);
 
-unsigned long __sync_fetch_and_or_4(unsigned long *p, unsigned long v)
+unsigned int __sync_fetch_and_or_4(volatile void *p, unsigned int v)
 {
 	BUG();
 }
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/mm/cache.c
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/mm/cache.c
@@ -71,8 +71,10 @@
 			kvaddr = TLBTEMP_BASE_1 +
 				(page_to_phys(page) & DCACHE_ALIAS_MASK);
 
+			preempt_disable();
 			__invalidate_dcache_page_alias(kvaddr,
 						       page_to_phys(page));
+			preempt_enable();
 		}
 	}
 }
@@ -157,6 +159,7 @@
 		if (!alias && !mapping)
 			return;
 
+		preempt_disable();
 		virt = TLBTEMP_BASE_1 + (phys & DCACHE_ALIAS_MASK);
 		__flush_invalidate_dcache_page_alias(virt, phys);
 
@@ -167,6 +170,7 @@
 
 		if (mapping)
 			__invalidate_icache_page_alias(virt, phys);
+		preempt_enable();
 	}
 
 	/* There shouldn't be an entry in the cache for this page anymore. */
@@ -200,8 +204,10 @@
 	unsigned long phys = page_to_phys(pfn_to_page(pfn));
 	unsigned long virt = TLBTEMP_BASE_1 + (address & DCACHE_ALIAS_MASK);
 
+	preempt_disable();
 	__flush_invalidate_dcache_page_alias(virt, phys);
 	__invalidate_icache_page_alias(virt, phys);
+	preempt_enable();
 }
 EXPORT_SYMBOL(local_flush_cache_page);
 
@@ -228,11 +234,13 @@
 		unsigned long phys = page_to_phys(page);
 		unsigned long tmp;
 
+		preempt_disable();
 		tmp = TLBTEMP_BASE_1 + (phys & DCACHE_ALIAS_MASK);
 		__flush_invalidate_dcache_page_alias(tmp, phys);
 		tmp = TLBTEMP_BASE_1 + (addr & DCACHE_ALIAS_MASK);
 		__flush_invalidate_dcache_page_alias(tmp, phys);
 		__invalidate_icache_page_alias(tmp, phys);
+		preempt_enable();
 
 		clear_bit(PG_arch_1, &page->flags);
 	}
@@ -266,7 +274,9 @@
 
 	if (alias) {
 		unsigned long t = TLBTEMP_BASE_1 + (vaddr & DCACHE_ALIAS_MASK);
+		preempt_disable();
 		__flush_invalidate_dcache_page_alias(t, phys);
+		preempt_enable();
 	}
 
 	/* Copy data */
@@ -281,9 +291,11 @@
 	if (alias) {
 		unsigned long t = TLBTEMP_BASE_1 + (vaddr & DCACHE_ALIAS_MASK);
 
+		preempt_disable();
 		__flush_invalidate_dcache_range((unsigned long) dst, len);
 		if ((vma->vm_flags & VM_EXEC) != 0)
 			__invalidate_icache_page_alias(t, phys);
+		preempt_enable();
 
 	} else if ((vma->vm_flags & VM_EXEC) != 0) {
 		__flush_dcache_range((unsigned long)dst,len);
@@ -305,7 +317,9 @@
 
 	if (alias) {
 		unsigned long t = TLBTEMP_BASE_1 + (vaddr & DCACHE_ALIAS_MASK);
+		preempt_disable();
 		__flush_invalidate_dcache_page_alias(t, phys);
+		preempt_enable();
 	}
 
 	memcpy(dst, src, len);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/mm/kasan_init.c
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/mm/kasan_init.c
@@ -56,7 +56,9 @@
 
 		for (k = 0; k < PTRS_PER_PTE; ++k, ++j) {
 			phys_addr_t phys =
-				memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE);
+				memblock_phys_alloc_range(PAGE_SIZE, PAGE_SIZE,
+							  0,
+							  MEMBLOCK_ALLOC_ANYWHERE);
 
 			if (!phys)
 				panic("Failed to allocate page table page\n");
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/mm/mmu.c
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/mm/mmu.c
@@ -101,7 +101,7 @@
 
 void init_kio(void)
 {
-#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY && defined(CONFIG_OF)
+#if XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY && defined(CONFIG_USE_OF)
 	/*
 	 * Update the IO area mapping in case xtensa_kio_paddr has changed
 	 */
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/mm/tlb.c
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/mm/tlb.c
@@ -216,6 +216,8 @@
 	unsigned tlbidx = w | (e << PAGE_SHIFT);
 	unsigned r0 = dtlb ?
 		read_dtlb_virtual(tlbidx) : read_itlb_virtual(tlbidx);
+	unsigned r1 = dtlb ?
+		read_dtlb_translation(tlbidx) : read_itlb_translation(tlbidx);
 	unsigned vpn = (r0 & PAGE_MASK) | (e << PAGE_SHIFT);
 	unsigned pte = get_pte_for_vaddr(vpn);
 	unsigned mm_asid = (get_rasid_register() >> 8) & ASID_MASK;
@@ -231,8 +233,6 @@
 	}
 
 	if (tlb_asid == mm_asid) {
-		unsigned r1 = dtlb ? read_dtlb_translation(tlbidx) :
-			read_itlb_translation(tlbidx);
 		if ((pte ^ r1) & PAGE_MASK) {
 			pr_err("%cTLB: way: %u, entry: %u, mapping: %08x->%08x, PTE: %08x\n",
 					dtlb ? 'D' : 'I', w, e, r0, r1, pte);
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/platforms/iss/console.c
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/platforms/iss/console.c
@@ -168,9 +168,13 @@
 
 int __init rs_init(void)
 {
-	tty_port_init(&serial_port);
+	int ret;
 
 	serial_driver = alloc_tty_driver(SERIAL_MAX_NUM_LINES);
+	if (!serial_driver)
+		return -ENOMEM;
+
+	tty_port_init(&serial_port);
 
 	pr_info("%s %s\n", serial_name, serial_version);
 
@@ -190,8 +194,15 @@
 	tty_set_operations(serial_driver, &serial_ops);
 	tty_port_link_device(&serial_port, serial_driver, 0);
 
-	if (tty_register_driver(serial_driver))
-		panic("Couldn't register serial driver\n");
+	ret = tty_register_driver(serial_driver);
+	if (ret) {
+		pr_err("Couldn't register serial driver\n");
+		tty_driver_kref_put(serial_driver);
+		tty_port_destroy(&serial_port);
+
+		return ret;
+	}
+
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/platforms/iss/network.c
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/platforms/iss/network.c
@@ -204,7 +204,7 @@
 	return simc_write(lp->tp.info.tuntap.fd, (*skb)->data, (*skb)->len);
 }
 
-unsigned short tuntap_protocol(struct sk_buff *skb)
+static unsigned short tuntap_protocol(struct sk_buff *skb)
 {
 	return eth_type_trans(skb, skb->dev);
 }
@@ -231,7 +231,7 @@
 
 	init += sizeof(TRANSPORT_TUNTAP_NAME) - 1;
 	if (*init == ',') {
-		rem = split_if_spec(init + 1, &mac_str, &dev_name);
+		rem = split_if_spec(init + 1, &mac_str, &dev_name, NULL);
 		if (rem != NULL) {
 			pr_err("%s: extra garbage on specification : '%s'\n",
 			       dev->name, rem);
@@ -477,7 +477,7 @@
 	return -EINVAL;
 }
 
-void iss_net_user_timer_expire(struct timer_list *unused)
+static void iss_net_user_timer_expire(struct timer_list *unused)
 {
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/arch/xtensa/platforms/xtfpga/setup.c
+++ linux-xilinx-zynqmp-5.4.0/arch/xtensa/platforms/xtfpga/setup.c
@@ -50,8 +50,12 @@
 
 void platform_restart(void)
 {
-	/* Flush and reset the mmu, simulate a processor reset, and
-	 * jump to the reset vector. */
+	/* Try software reset first. */
+	WRITE_ONCE(*(u32 *)XTFPGA_SWRST_VADDR, 0xdead);
+
+	/* If software reset did not work, flush and reset the mmu,
+	 * simulate a processor reset, and jump to the reset vector.
+	 */
 	cpu_reset();
 	/* control never gets here */
 }
@@ -81,7 +85,7 @@
 
 #endif
 
-#ifdef CONFIG_OF
+#ifdef CONFIG_USE_OF
 
 static void __init xtfpga_clk_setup(struct device_node *np)
 {
@@ -144,6 +148,7 @@
 
 	if ((eth = of_find_compatible_node(eth, NULL, "opencores,ethoc")))
 		update_local_mac(eth);
+	of_node_put(eth);
 	return 0;
 }
 arch_initcall(machine_setup);
@@ -299,4 +304,4 @@
  */
 arch_initcall(xtavnet_init);
 
-#endif /* CONFIG_OF */
+#endif /* CONFIG_USE_OF */
--- linux-xilinx-zynqmp-5.4.0.orig/block/bfq-cgroup.c
+++ linux-xilinx-zynqmp-5.4.0/block/bfq-cgroup.c
@@ -536,6 +536,7 @@
 				   */
 	bfqg->bfqd = bfqd;
 	bfqg->active_entities = 0;
+	bfqg->online = true;
 	bfqg->rq_pos_tree = RB_ROOT;
 }
 
@@ -564,28 +565,11 @@
 	entity->sched_data = &parent->sched_data;
 }
 
-static struct bfq_group *bfq_lookup_bfqg(struct bfq_data *bfqd,
-					 struct blkcg *blkcg)
+static void bfq_link_bfqg(struct bfq_data *bfqd, struct bfq_group *bfqg)
 {
-	struct blkcg_gq *blkg;
-
-	blkg = blkg_lookup(blkcg, bfqd->queue);
-	if (likely(blkg))
-		return blkg_to_bfqg(blkg);
-	return NULL;
-}
-
-struct bfq_group *bfq_find_set_group(struct bfq_data *bfqd,
-				     struct blkcg *blkcg)
-{
-	struct bfq_group *bfqg, *parent;
+	struct bfq_group *parent;
 	struct bfq_entity *entity;
 
-	bfqg = bfq_lookup_bfqg(bfqd, blkcg);
-
-	if (unlikely(!bfqg))
-		return NULL;
-
 	/*
 	 * Update chain of bfq_groups as we might be handling a leaf group
 	 * which, along with some of its relatives, has not been hooked yet
@@ -593,16 +577,37 @@
 	 */
 	entity = &bfqg->entity;
 	for_each_entity(entity) {
-		bfqg = container_of(entity, struct bfq_group, entity);
-		if (bfqg != bfqd->root_group) {
-			parent = bfqg_parent(bfqg);
+		struct bfq_group *curr_bfqg = container_of(entity,
+						struct bfq_group, entity);
+		if (curr_bfqg != bfqd->root_group) {
+			parent = bfqg_parent(curr_bfqg);
 			if (!parent)
 				parent = bfqd->root_group;
-			bfq_group_set_parent(bfqg, parent);
+			bfq_group_set_parent(curr_bfqg, parent);
 		}
 	}
+}
 
-	return bfqg;
+struct bfq_group *bfq_bio_bfqg(struct bfq_data *bfqd, struct bio *bio)
+{
+	struct blkcg_gq *blkg = bio->bi_blkg;
+	struct bfq_group *bfqg;
+
+	while (blkg) {
+		if (!blkg->online) {
+			blkg = blkg->parent;
+			continue;
+		}
+		bfqg = blkg_to_bfqg(blkg);
+		if (bfqg->online) {
+			bio_associate_blkg_from_css(bio, &blkg->blkcg->css);
+			return bfqg;
+		}
+		blkg = blkg->parent;
+	}
+	bio_associate_blkg_from_css(bio,
+				&bfqg_to_blkg(bfqd->root_group)->blkcg->css);
+	return bfqd->root_group;
 }
 
 /**
@@ -624,6 +629,18 @@
 {
 	struct bfq_entity *entity = &bfqq->entity;
 
+	/*
+	 * oom_bfqq is not allowed to move, oom_bfqq will hold ref to root_group
+	 * until elevator exit.
+	 */
+	if (bfqq == &bfqd->oom_bfqq)
+		return;
+	/*
+	 * Get extra reference to prevent bfqq from being freed in
+	 * next possible expire or deactivate.
+	 */
+	bfqq->ref++;
+
 	/* If bfqq is empty, then bfq_bfqq_expire also invokes
 	 * bfq_del_bfqq_busy, thereby removing bfqq and its entity
 	 * from data structures related to current group. Otherwise we
@@ -653,6 +670,8 @@
 
 	if (!bfqd->in_service_queue && !bfqd->rq_in_driver)
 		bfq_schedule_dispatch(bfqd);
+	/* release extra ref taken above, bfqq may happen to be freed now */
+	bfq_put_queue(bfqq);
 }
 
 /**
@@ -664,41 +683,58 @@
  * Move bic to blkcg, assuming that bfqd->lock is held; which makes
  * sure that the reference to cgroup is valid across the call (see
  * comments in bfq_bic_update_cgroup on this issue)
- *
- * NOTE: an alternative approach might have been to store the current
- * cgroup in bfqq and getting a reference to it, reducing the lookup
- * time here, at the price of slightly more complex code.
  */
-static struct bfq_group *__bfq_bic_change_cgroup(struct bfq_data *bfqd,
-						struct bfq_io_cq *bic,
-						struct blkcg *blkcg)
+static void *__bfq_bic_change_cgroup(struct bfq_data *bfqd,
+				     struct bfq_io_cq *bic,
+				     struct bfq_group *bfqg)
 {
 	struct bfq_queue *async_bfqq = bic_to_bfqq(bic, 0);
 	struct bfq_queue *sync_bfqq = bic_to_bfqq(bic, 1);
-	struct bfq_group *bfqg;
 	struct bfq_entity *entity;
 
-	bfqg = bfq_find_set_group(bfqd, blkcg);
-
-	if (unlikely(!bfqg))
-		bfqg = bfqd->root_group;
-
 	if (async_bfqq) {
 		entity = &async_bfqq->entity;
 
 		if (entity->sched_data != &bfqg->sched_data) {
 			bic_set_bfqq(bic, NULL, 0);
-			bfq_log_bfqq(bfqd, async_bfqq,
-				     "bic_change_group: %p %d",
-				     async_bfqq, async_bfqq->ref);
-			bfq_put_queue(async_bfqq);
+			bfq_release_process_ref(bfqd, async_bfqq);
 		}
 	}
 
 	if (sync_bfqq) {
-		entity = &sync_bfqq->entity;
-		if (entity->sched_data != &bfqg->sched_data)
-			bfq_bfqq_move(bfqd, sync_bfqq, bfqg);
+		if (!sync_bfqq->new_bfqq && !bfq_bfqq_coop(sync_bfqq)) {
+			/* We are the only user of this bfqq, just move it */
+			if (sync_bfqq->entity.sched_data != &bfqg->sched_data)
+				bfq_bfqq_move(bfqd, sync_bfqq, bfqg);
+		} else {
+			struct bfq_queue *bfqq;
+
+			/*
+			 * The queue was merged to a different queue. Check
+			 * that the merge chain still belongs to the same
+			 * cgroup.
+			 */
+			for (bfqq = sync_bfqq; bfqq; bfqq = bfqq->new_bfqq)
+				if (bfqq->entity.sched_data !=
+				    &bfqg->sched_data)
+					break;
+			if (bfqq) {
+				/*
+				 * Some queue changed cgroup so the merge is
+				 * not valid anymore. We cannot easily just
+				 * cancel the merge (by clearing new_bfqq) as
+				 * there may be other processes using this
+				 * queue and holding refs to all queues below
+				 * sync_bfqq->new_bfqq. Similarly if the merge
+				 * already happened, we need to detach from
+				 * bfqq now so that we cannot merge bio to a
+				 * request from the old cgroup.
+				 */
+				bfq_put_cooperator(sync_bfqq);
+				bfq_release_process_ref(bfqd, sync_bfqq);
+				bic_set_bfqq(bic, NULL, 1);
+			}
+		}
 	}
 
 	return bfqg;
@@ -707,20 +743,24 @@
 void bfq_bic_update_cgroup(struct bfq_io_cq *bic, struct bio *bio)
 {
 	struct bfq_data *bfqd = bic_to_bfqd(bic);
-	struct bfq_group *bfqg = NULL;
+	struct bfq_group *bfqg = bfq_bio_bfqg(bfqd, bio);
 	uint64_t serial_nr;
 
-	rcu_read_lock();
-	serial_nr = __bio_blkcg(bio)->css.serial_nr;
+	serial_nr = bfqg_to_blkg(bfqg)->blkcg->css.serial_nr;
 
 	/*
 	 * Check whether blkcg has changed.  The condition may trigger
 	 * spuriously on a newly created cic but there's no harm.
 	 */
 	if (unlikely(!bfqd) || likely(bic->blkcg_serial_nr == serial_nr))
-		goto out;
+		return;
 
-	bfqg = __bfq_bic_change_cgroup(bfqd, bic, __bio_blkcg(bio));
+	/*
+	 * New cgroup for this process. Make sure it is linked to bfq internal
+	 * cgroup hierarchy.
+	 */
+	bfq_link_bfqg(bfqd, bfqg);
+	__bfq_bic_change_cgroup(bfqd, bic, bfqg);
 	/*
 	 * Update blkg_path for bfq_log_* functions. We cache this
 	 * path, and update it here, for the following
@@ -773,8 +813,6 @@
 	 */
 	blkg_path(bfqg_to_blkg(bfqg), bfqg->blkg_path, sizeof(bfqg->blkg_path));
 	bic->blkcg_serial_nr = serial_nr;
-out:
-	rcu_read_unlock();
 }
 
 /**
@@ -792,39 +830,53 @@
 /**
  * bfq_reparent_leaf_entity - move leaf entity to the root_group.
  * @bfqd: the device data structure with the root group.
- * @entity: the entity to move.
+ * @entity: the entity to move, if entity is a leaf; or the parent entity
+ *	    of an active leaf entity to move, if entity is not a leaf.
  */
 static void bfq_reparent_leaf_entity(struct bfq_data *bfqd,
-				     struct bfq_entity *entity)
+				     struct bfq_entity *entity,
+				     int ioprio_class)
 {
-	struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity);
+	struct bfq_queue *bfqq;
+	struct bfq_entity *child_entity = entity;
+
+	while (child_entity->my_sched_data) { /* leaf not reached yet */
+		struct bfq_sched_data *child_sd = child_entity->my_sched_data;
+		struct bfq_service_tree *child_st = child_sd->service_tree +
+			ioprio_class;
+		struct rb_root *child_active = &child_st->active;
+
+		child_entity = bfq_entity_of(rb_first(child_active));
+
+		if (!child_entity)
+			child_entity = child_sd->in_service_entity;
+	}
 
+	bfqq = bfq_entity_to_bfqq(child_entity);
 	bfq_bfqq_move(bfqd, bfqq, bfqd->root_group);
 }
 
 /**
- * bfq_reparent_active_entities - move to the root group all active
- *                                entities.
+ * bfq_reparent_active_queues - move to the root group all active queues.
  * @bfqd: the device data structure with the root group.
  * @bfqg: the group to move from.
- * @st: the service tree with the entities.
+ * @st: the service tree to start the search from.
  */
-static void bfq_reparent_active_entities(struct bfq_data *bfqd,
-					 struct bfq_group *bfqg,
-					 struct bfq_service_tree *st)
+static void bfq_reparent_active_queues(struct bfq_data *bfqd,
+				       struct bfq_group *bfqg,
+				       struct bfq_service_tree *st,
+				       int ioprio_class)
 {
 	struct rb_root *active = &st->active;
-	struct bfq_entity *entity = NULL;
-
-	if (!RB_EMPTY_ROOT(&st->active))
-		entity = bfq_entity_of(rb_first(active));
+	struct bfq_entity *entity;
 
-	for (; entity ; entity = bfq_entity_of(rb_first(active)))
-		bfq_reparent_leaf_entity(bfqd, entity);
+	while ((entity = bfq_entity_of(rb_first(active))))
+		bfq_reparent_leaf_entity(bfqd, entity, ioprio_class);
 
 	if (bfqg->sched_data.in_service_entity)
 		bfq_reparent_leaf_entity(bfqd,
-			bfqg->sched_data.in_service_entity);
+					 bfqg->sched_data.in_service_entity,
+					 ioprio_class);
 }
 
 /**
@@ -857,13 +909,6 @@
 		st = bfqg->sched_data.service_tree + i;
 
 		/*
-		 * The idle tree may still contain bfq_queues belonging
-		 * to exited task because they never migrated to a different
-		 * cgroup from the one being destroyed now.
-		 */
-		bfq_flush_idle_tree(st);
-
-		/*
 		 * It may happen that some queues are still active
 		 * (busy) upon group destruction (if the corresponding
 		 * processes have been forced to terminate). We move
@@ -875,13 +920,27 @@
 		 * There is no need to put the sync queues, as the
 		 * scheduler has taken no reference.
 		 */
-		bfq_reparent_active_entities(bfqd, bfqg, st);
+		bfq_reparent_active_queues(bfqd, bfqg, st, i);
+
+		/*
+		 * The idle tree may still contain bfq_queues
+		 * belonging to exited task because they never
+		 * migrated to a different cgroup from the one being
+		 * destroyed now. In addition, even
+		 * bfq_reparent_active_queues() may happen to add some
+		 * entities to the idle tree. It happens if, in some
+		 * of the calls to bfq_bfqq_move() performed by
+		 * bfq_reparent_active_queues(), the queue to move is
+		 * empty and gets expired.
+		 */
+		bfq_flush_idle_tree(st);
 	}
 
 	__bfq_deactivate_entity(entity, false);
 
 put_async_queues:
 	bfq_put_async_queues(bfqd, bfqg);
+	bfqg->online = false;
 
 	spin_unlock_irqrestore(&bfqd->lock, flags);
 	/*
@@ -1370,7 +1429,7 @@
 	bfq_end_wr_async_queues(bfqd, bfqd->root_group);
 }
 
-struct bfq_group *bfq_find_set_group(struct bfq_data *bfqd, struct blkcg *blkcg)
+struct bfq_group *bfq_bio_bfqg(struct bfq_data *bfqd, struct bio *bio)
 {
 	return bfqd->root_group;
 }
@@ -1380,6 +1439,10 @@
 	return bfqq->bfqd->root_group;
 }
 
+void bfqg_and_blkg_get(struct bfq_group *bfqg) {}
+
+void bfqg_and_blkg_put(struct bfq_group *bfqg) {}
+
 struct bfq_group *bfq_create_group_hierarchy(struct bfq_data *bfqd, int node)
 {
 	struct bfq_group *bfqg;
--- linux-xilinx-zynqmp-5.4.0.orig/block/bfq-iosched.c
+++ linux-xilinx-zynqmp-5.4.0/block/bfq-iosched.c
@@ -123,6 +123,7 @@
 #include <linux/ioprio.h>
 #include <linux/sbitmap.h>
 #include <linux/delay.h>
+#include <linux/backing-dev.h>
 
 #include "blk.h"
 #include "blk-mq.h"
@@ -420,6 +421,8 @@
  */
 void bfq_schedule_dispatch(struct bfq_data *bfqd)
 {
+	lockdep_assert_held(&bfqd->lock);
+
 	if (bfqd->queued != 0) {
 		bfq_log(bfqd, "schedule dispatch");
 		blk_mq_run_hw_queues(bfqd->queue, true);
@@ -614,6 +617,10 @@
 		bfqq->pos_root = NULL;
 	}
 
+	/* oom_bfqq does not participate in queue merging */
+	if (bfqq == &bfqd->oom_bfqq)
+		return;
+
 	/*
 	 * bfqq cannot be merged any longer (see comments in
 	 * bfq_setup_cooperator): no point in adding bfqq into the
@@ -2206,10 +2213,9 @@
 
 }
 
-static bool bfq_bio_merge(struct blk_mq_hw_ctx *hctx, struct bio *bio,
+static bool bfq_bio_merge(struct request_queue *q, struct bio *bio,
 		unsigned int nr_segs)
 {
-	struct request_queue *q = hctx->queue;
 	struct bfq_data *bfqd = q->elevator->elevator_data;
 	struct request *free = NULL;
 	/*
@@ -2224,10 +2230,17 @@
 
 	spin_lock_irq(&bfqd->lock);
 
-	if (bic)
+	if (bic) {
+		/*
+		 * Make sure cgroup info is uptodate for current process before
+		 * considering the merge.
+		 */
+		bfq_bic_update_cgroup(bic, bio);
+
 		bfqd->bio_bfqq = bic_to_bfqq(bic, op_is_sync(bio->bi_opf));
-	else
+	} else {
 		bfqd->bio_bfqq = NULL;
+	}
 	bfqd->bio_bic = bic;
 
 	ret = blk_mq_sched_try_merge(q, bio, nr_segs, &free);
@@ -2248,14 +2261,15 @@
 	__rq = bfq_find_rq_fmerge(bfqd, bio, q);
 	if (__rq && elv_bio_merge_ok(__rq, bio)) {
 		*req = __rq;
+
+		if (blk_discard_mergable(__rq))
+			return ELEVATOR_DISCARD_MERGE;
 		return ELEVATOR_FRONT_MERGE;
 	}
 
 	return ELEVATOR_NO_MERGE;
 }
 
-static struct bfq_queue *bfq_init_rq(struct request *rq);
-
 static void bfq_request_merged(struct request_queue *q, struct request *req,
 			       enum elv_merge type)
 {
@@ -2264,7 +2278,7 @@
 	    blk_rq_pos(req) <
 	    blk_rq_pos(container_of(rb_prev(&req->rb_node),
 				    struct request, rb_node))) {
-		struct bfq_queue *bfqq = bfq_init_rq(req);
+		struct bfq_queue *bfqq = RQ_BFQQ(req);
 		struct bfq_data *bfqd;
 		struct request *prev, *next_rq;
 
@@ -2316,8 +2330,8 @@
 static void bfq_requests_merged(struct request_queue *q, struct request *rq,
 				struct request *next)
 {
-	struct bfq_queue *bfqq = bfq_init_rq(rq),
-		*next_bfqq = bfq_init_rq(next);
+	struct bfq_queue *bfqq = RQ_BFQQ(rq),
+		*next_bfqq = RQ_BFQQ(next);
 
 	if (!bfqq)
 		return;
@@ -2496,6 +2510,14 @@
 	if (process_refs == 0 || new_process_refs == 0)
 		return NULL;
 
+	/*
+	 * Make sure merged queues belong to the same parent. Parents could
+	 * have changed since the time we decided the two queues are suitable
+	 * for merging.
+	 */
+	if (new_bfqq->entity.parent != bfqq->entity.parent)
+		return NULL;
+
 	bfq_log_bfqq(bfqq->bfqd, bfqq, "scheduling merge with queue %d",
 		new_bfqq->pid);
 
@@ -2520,6 +2542,15 @@
 	 * are likely to increase the throughput.
 	 */
 	bfqq->new_bfqq = new_bfqq;
+	/*
+	 * The above assignment schedules the following redirections:
+	 * each time some I/O for bfqq arrives, the process that
+	 * generated that I/O is disassociated from bfqq and
+	 * associated with new_bfqq. Here we increases new_bfqq->ref
+	 * in advance, adding the number of processes that are
+	 * expected to be associated with new_bfqq as they happen to
+	 * issue I/O.
+	 */
 	new_bfqq->ref += process_refs;
 	return new_bfqq;
 }
@@ -2579,6 +2610,14 @@
 {
 	struct bfq_queue *in_service_bfqq, *new_bfqq;
 
+	/* if a merge has already been setup, then proceed with that first */
+	new_bfqq = bfqq->new_bfqq;
+	if (new_bfqq) {
+		while (new_bfqq->new_bfqq)
+			new_bfqq = new_bfqq->new_bfqq;
+		return new_bfqq;
+	}
+
 	/*
 	 * Do not perform queue merging if the device is non
 	 * rotational and performs internal queueing. In fact, such a
@@ -2633,9 +2672,6 @@
 	if (bfq_too_late_for_merging(bfqq))
 		return NULL;
 
-	if (bfqq->new_bfqq)
-		return bfqq->new_bfqq;
-
 	if (!io_struct || unlikely(bfqq == &bfqd->oom_bfqq))
 		return NULL;
 
@@ -2713,8 +2749,6 @@
 	}
 }
 
-
-static
 void bfq_release_process_ref(struct bfq_data *bfqd, struct bfq_queue *bfqq)
 {
 	/*
@@ -2935,6 +2969,7 @@
 	}
 
 	bfqd->in_service_queue = bfqq;
+	bfqd->in_serv_last_pos = 0;
 }
 
 /*
@@ -3444,6 +3479,10 @@
 static bool idling_needed_for_service_guarantees(struct bfq_data *bfqd,
 						 struct bfq_queue *bfqq)
 {
+	/* No point in idling for bfqq if it won't get requests any longer */
+	if (unlikely(!bfqq_process_refs(bfqq)))
+		return false;
+
 	return (bfqq->wr_coeff > 1 &&
 		(bfqd->wr_busy_queues <
 		 bfq_tot_busy_queues(bfqd) ||
@@ -4077,6 +4116,10 @@
 		bfqq_sequential_and_IO_bound,
 		idling_boosts_thr;
 
+	/* No point in idling for bfqq if it won't get requests any longer */
+	if (unlikely(!bfqq_process_refs(bfqq)))
+		return false;
+
 	bfqq_sequential_and_IO_bound = !BFQQ_SEEKY(bfqq) &&
 		bfq_bfqq_IO_bound(bfqq) && bfq_bfqq_has_short_ttime(bfqq);
 
@@ -4170,6 +4213,10 @@
 	struct bfq_data *bfqd = bfqq->bfqd;
 	bool idling_boosts_thr_with_no_issue, idling_needed_for_service_guar;
 
+	/* No point in idling for bfqq if it won't get requests any longer */
+	if (unlikely(!bfqq_process_refs(bfqq)))
+		return false;
+
 	if (unlikely(bfqd->strict_guarantees))
 		return true;
 
@@ -4779,7 +4826,7 @@
 	struct bfq_data *bfqd = hctx->queue->elevator->elevator_data;
 	struct request *rq;
 	struct bfq_queue *in_serv_queue;
-	bool waiting_rq, idle_timer_disabled;
+	bool waiting_rq, idle_timer_disabled = false;
 
 	spin_lock_irq(&bfqd->lock);
 
@@ -4787,14 +4834,15 @@
 	waiting_rq = in_serv_queue && bfq_bfqq_wait_request(in_serv_queue);
 
 	rq = __bfq_dispatch_request(hctx);
-
-	idle_timer_disabled =
-		waiting_rq && !bfq_bfqq_wait_request(in_serv_queue);
+	if (in_serv_queue == bfqd->in_service_queue) {
+		idle_timer_disabled =
+			waiting_rq && !bfq_bfqq_wait_request(in_serv_queue);
+	}
 
 	spin_unlock_irq(&bfqd->lock);
-
-	bfq_update_dispatch_stats(hctx->queue, rq, in_serv_queue,
-				  idle_timer_disabled);
+	bfq_update_dispatch_stats(hctx->queue, rq,
+			idle_timer_disabled ? in_serv_queue : NULL,
+				idle_timer_disabled);
 
 	return rq;
 }
@@ -4810,9 +4858,7 @@
 {
 	struct bfq_queue *item;
 	struct hlist_node *n;
-#ifdef CONFIG_BFQ_GROUP_IOSCHED
 	struct bfq_group *bfqg = bfqq_group(bfqq);
-#endif
 
 	if (bfqq->bfqd)
 		bfq_log_bfqq(bfqq->bfqd, bfqq, "put_queue: %p %d",
@@ -4885,12 +4931,10 @@
 		bfqq->bfqd->last_completed_rq_bfqq = NULL;
 
 	kmem_cache_free(bfq_pool, bfqq);
-#ifdef CONFIG_BFQ_GROUP_IOSCHED
 	bfqg_and_blkg_put(bfqg);
-#endif
 }
 
-static void bfq_put_cooperator(struct bfq_queue *bfqq)
+void bfq_put_cooperator(struct bfq_queue *bfqq)
 {
 	struct bfq_queue *__bfqq, *next;
 
@@ -4967,8 +5011,9 @@
 	ioprio_class = IOPRIO_PRIO_CLASS(bic->ioprio);
 	switch (ioprio_class) {
 	default:
-		dev_err(bfqq->bfqd->queue->backing_dev_info->dev,
-			"bfq: bad prio class %d\n", ioprio_class);
+		pr_err("bdi %s: bfq: bad prio class %d\n",
+				bdi_dev_name(bfqq->bfqd->queue->backing_dev_info),
+				ioprio_class);
 		/* fall through */
 	case IOPRIO_CLASS_NONE:
 		/*
@@ -4994,7 +5039,7 @@
 	if (bfqq->new_ioprio >= IOPRIO_BE_NR) {
 		pr_crit("bfq_set_next_ioprio_data: new_ioprio %d\n",
 			bfqq->new_ioprio);
-		bfqq->new_ioprio = IOPRIO_BE_NR;
+		bfqq->new_ioprio = IOPRIO_BE_NR - 1;
 	}
 
 	bfqq->entity.new_weight = bfq_ioprio_to_weight(bfqq->new_ioprio);
@@ -5121,14 +5166,7 @@
 	struct bfq_queue *bfqq;
 	struct bfq_group *bfqg;
 
-	rcu_read_lock();
-
-	bfqg = bfq_find_set_group(bfqd, __bio_blkcg(bio));
-	if (!bfqg) {
-		bfqq = &bfqd->oom_bfqq;
-		goto out;
-	}
-
+	bfqg = bfq_bio_bfqg(bfqd, bio);
 	if (!is_sync) {
 		async_bfqq = bfq_async_queue_prio(bfqd, bfqg, ioprio_class,
 						  ioprio);
@@ -5172,7 +5210,6 @@
 out:
 	bfqq->ref++; /* get a process reference to this queue */
 	bfq_log_bfqq(bfqd, bfqq, "get_queue, at end: %p, %d", bfqq, bfqq->ref);
-	rcu_read_unlock();
 	return bfqq;
 }
 
@@ -5475,6 +5512,8 @@
 					   unsigned int cmd_flags) {}
 #endif /* CONFIG_BFQ_CGROUP_DEBUG */
 
+static struct bfq_queue *bfq_init_rq(struct request *rq);
+
 static void bfq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
 			       bool at_head)
 {
@@ -5485,17 +5524,14 @@
 	unsigned int cmd_flags;
 
 	spin_lock_irq(&bfqd->lock);
+	bfqq = bfq_init_rq(rq);
 	if (blk_mq_sched_try_insert_merge(q, rq)) {
 		spin_unlock_irq(&bfqd->lock);
 		return;
 	}
 
-	spin_unlock_irq(&bfqd->lock);
-
 	blk_mq_sched_request_inserted(rq);
 
-	spin_lock_irq(&bfqd->lock);
-	bfqq = bfq_init_rq(rq);
 	if (!bfqq || at_head || blk_rq_is_passthrough(rq)) {
 		if (at_head)
 			list_add(&rq->queuelist, &bfqd->dispatch);
@@ -5881,18 +5917,6 @@
 	struct bfq_data *bfqd;
 
 	/*
-	 * Requeue and finish hooks are invoked in blk-mq without
-	 * checking whether the involved request is actually still
-	 * referenced in the scheduler. To handle this fact, the
-	 * following two checks make this function exit in case of
-	 * spurious invocations, for which there is nothing to do.
-	 *
-	 * First, check whether rq has nothing to do with an elevator.
-	 */
-	if (unlikely(!(rq->rq_flags & RQF_ELVPRIV)))
-		return;
-
-	/*
 	 * rq either is not associated with any icq, or is an already
 	 * requeued request that has not (yet) been re-inserted into
 	 * a bfq_queue.
@@ -5972,7 +5996,7 @@
 {
 	bfq_log_bfqq(bfqq->bfqd, bfqq, "splitting queue");
 
-	if (bfqq_process_refs(bfqq) == 1) {
+	if (bfqq_process_refs(bfqq) == 1 && !bfqq->new_bfqq) {
 		bfqq->pid = current->pid;
 		bfq_clear_bfqq_coop(bfqq);
 		bfq_clear_bfqq_split_coop(bfqq);
@@ -6157,7 +6181,8 @@
 	 * addition, if the queue has also just been split, we have to
 	 * resume its state.
 	 */
-	if (likely(bfqq != &bfqd->oom_bfqq) && bfqq_process_refs(bfqq) == 1) {
+	if (likely(bfqq != &bfqd->oom_bfqq) && !bfqq->new_bfqq &&
+	    bfqq_process_refs(bfqq) == 1) {
 		bfqq->bic = bic;
 		if (split) {
 			/*
@@ -6198,20 +6223,28 @@
 	return bfqq;
 }
 
-static void bfq_idle_slice_timer_body(struct bfq_queue *bfqq)
+static void
+bfq_idle_slice_timer_body(struct bfq_data *bfqd, struct bfq_queue *bfqq)
 {
-	struct bfq_data *bfqd = bfqq->bfqd;
 	enum bfqq_expiration reason;
 	unsigned long flags;
 
 	spin_lock_irqsave(&bfqd->lock, flags);
-	bfq_clear_bfqq_wait_request(bfqq);
 
+	/*
+	 * Considering that bfqq may be in race, we should firstly check
+	 * whether bfqq is in service before doing something on it. If
+	 * the bfqq in race is not in service, it has already been expired
+	 * through __bfq_bfqq_expire func and its wait_request flags has
+	 * been cleared in __bfq_bfqd_reset_in_service func.
+	 */
 	if (bfqq != bfqd->in_service_queue) {
 		spin_unlock_irqrestore(&bfqd->lock, flags);
 		return;
 	}
 
+	bfq_clear_bfqq_wait_request(bfqq);
+
 	if (bfq_bfqq_budget_timeout(bfqq))
 		/*
 		 * Also here the queue can be safely expired
@@ -6233,8 +6266,8 @@
 	bfq_bfqq_expire(bfqd, bfqq, true, reason);
 
 schedule_dispatch:
-	spin_unlock_irqrestore(&bfqd->lock, flags);
 	bfq_schedule_dispatch(bfqd);
+	spin_unlock_irqrestore(&bfqd->lock, flags);
 }
 
 /*
@@ -6256,7 +6289,7 @@
 	 * early.
 	 */
 	if (bfqq)
-		bfq_idle_slice_timer_body(bfqq);
+		bfq_idle_slice_timer_body(bfqd, bfqq);
 
 	return HRTIMER_NORESTART;
 }
@@ -6371,10 +6404,10 @@
 
 	hrtimer_cancel(&bfqd->idle_slice_timer);
 
-#ifdef CONFIG_BFQ_GROUP_IOSCHED
 	/* release oom-queue reference to root group */
 	bfqg_and_blkg_put(bfqd->root_group);
 
+#ifdef CONFIG_BFQ_GROUP_IOSCHED
 	blkcg_deactivate_policy(bfqd->queue, &blkcg_policy_bfq);
 #else
 	spin_lock_irq(&bfqd->lock);
@@ -6383,6 +6416,8 @@
 	spin_unlock_irq(&bfqd->lock);
 #endif
 
+	wbt_enable_default(bfqd->queue);
+
 	kfree(bfqd);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/block/bfq-iosched.h
+++ linux-xilinx-zynqmp-5.4.0/block/bfq-iosched.h
@@ -896,6 +896,8 @@
 
 	/* reference counter (see comments in bfq_bic_update_cgroup) */
 	int ref;
+	/* Is bfq_group still online? */
+	bool online;
 
 	struct bfq_entity entity;
 	struct bfq_sched_data sched_data;
@@ -916,6 +918,7 @@
 
 #else
 struct bfq_group {
+	struct bfq_entity entity;
 	struct bfq_sched_data sched_data;
 
 	struct bfq_queue *async_bfqq[2][IOPRIO_BE_NR];
@@ -948,7 +951,9 @@
 void bfq_bfqq_expire(struct bfq_data *bfqd, struct bfq_queue *bfqq,
 		     bool compensate, enum bfqq_expiration reason);
 void bfq_put_queue(struct bfq_queue *bfqq);
+void bfq_put_cooperator(struct bfq_queue *bfqq);
 void bfq_end_wr_async_queues(struct bfq_data *bfqd, struct bfq_group *bfqg);
+void bfq_release_process_ref(struct bfq_data *bfqd, struct bfq_queue *bfqq);
 void bfq_schedule_dispatch(struct bfq_data *bfqd);
 void bfq_put_async_queues(struct bfq_data *bfqd, struct bfq_group *bfqg);
 
@@ -973,8 +978,7 @@
 void bfq_init_entity(struct bfq_entity *entity, struct bfq_group *bfqg);
 void bfq_bic_update_cgroup(struct bfq_io_cq *bic, struct bio *bio);
 void bfq_end_wr_async(struct bfq_data *bfqd);
-struct bfq_group *bfq_find_set_group(struct bfq_data *bfqd,
-				     struct blkcg *blkcg);
+struct bfq_group *bfq_bio_bfqg(struct bfq_data *bfqd, struct bio *bio);
 struct blkcg_gq *bfqg_to_blkg(struct bfq_group *bfqg);
 struct bfq_group *bfqq_group(struct bfq_queue *bfqq);
 struct bfq_group *bfq_create_group_hierarchy(struct bfq_data *bfqd, int node);
--- linux-xilinx-zynqmp-5.4.0.orig/block/bio-integrity.c
+++ linux-xilinx-zynqmp-5.4.0/block/bio-integrity.c
@@ -24,6 +24,18 @@
 	flush_workqueue(kintegrityd_wq);
 }
 
+void __bio_integrity_free(struct bio_set *bs, struct bio_integrity_payload *bip)
+{
+	if (bs && mempool_initialized(&bs->bio_integrity_pool)) {
+		if (bip->bip_vec)
+			bvec_free(&bs->bvec_integrity_pool, bip->bip_vec,
+				  bip->bip_slab);
+		mempool_free(bip, &bs->bio_integrity_pool);
+	} else {
+		kfree(bip);
+	}
+}
+
 /**
  * bio_integrity_alloc - Allocate integrity payload and attach it to bio
  * @bio:	bio to attach integrity metadata to
@@ -75,7 +87,7 @@
 
 	return bip;
 err:
-	mempool_free(bip, &bs->bio_integrity_pool);
+	__bio_integrity_free(bs, bip);
 	return ERR_PTR(-ENOMEM);
 }
 EXPORT_SYMBOL(bio_integrity_alloc);
@@ -87,7 +99,7 @@
  * Description: Used to free the integrity portion of a bio. Usually
  * called from bio_free().
  */
-static void bio_integrity_free(struct bio *bio)
+void bio_integrity_free(struct bio *bio)
 {
 	struct bio_integrity_payload *bip = bio_integrity(bio);
 	struct bio_set *bs = bio->bi_pool;
@@ -96,14 +108,7 @@
 		kfree(page_address(bip->bip_vec->bv_page) +
 		      bip->bip_vec->bv_offset);
 
-	if (bs && mempool_initialized(&bs->bio_integrity_pool)) {
-		bvec_free(&bs->bvec_integrity_pool, bip->bip_vec, bip->bip_slab);
-
-		mempool_free(bip, &bs->bio_integrity_pool);
-	} else {
-		kfree(bip);
-	}
-
+	__bio_integrity_free(bs, bip);
 	bio->bi_integrity = NULL;
 	bio->bi_opf &= ~REQ_INTEGRITY;
 }
@@ -207,6 +212,7 @@
 	unsigned int bytes, offset, i;
 	unsigned int intervals;
 	blk_status_t status;
+	gfp_t gfp = GFP_NOIO;
 
 	if (!bi)
 		return true;
@@ -229,12 +235,20 @@
 		if (!bi->profile->generate_fn ||
 		    !(bi->flags & BLK_INTEGRITY_GENERATE))
 			return true;
+
+		/*
+		 * Zero the memory allocated to not leak uninitialized kernel
+		 * memory to disk.  For PI this only affects the app tag, but
+		 * for non-integrity metadata it affects the entire metadata
+		 * buffer.
+		 */
+		gfp |= __GFP_ZERO;
 	}
 	intervals = bio_integrity_intervals(bi, bio_sectors(bio));
 
 	/* Allocate kernel buffer for protection data */
 	len = intervals * bi->tuple_size;
-	buf = kmalloc(len, GFP_NOIO | q->bounce_gfp);
+	buf = kmalloc(len, gfp | q->bounce_gfp);
 	status = BLK_STS_RESOURCE;
 	if (unlikely(buf == NULL)) {
 		printk(KERN_ERR "could not allocate integrity buffer\n");
@@ -278,7 +292,6 @@
 
 		if (ret == 0) {
 			printk(KERN_ERR "could not attach integrity payload\n");
-			kfree(buf);
 			status = BLK_STS_RESOURCE;
 			goto err_end_io;
 		}
@@ -376,7 +389,7 @@
 	struct blk_integrity *bi = blk_get_integrity(bio->bi_disk);
 	unsigned bytes = bio_integrity_bytes(bi, bytes_done >> 9);
 
-	bip->bip_iter.bi_sector += bytes_done >> 9;
+	bip->bip_iter.bi_sector += bio_integrity_intervals(bi, bytes_done >> 9);
 	bvec_iter_advance(bip->bip_vec, &bip->bip_iter, bytes);
 }
 
@@ -420,6 +433,7 @@
 
 	bip->bip_vcnt = bip_src->bip_vcnt;
 	bip->bip_iter = bip_src->bip_iter;
+	bip->bip_flags = bip_src->bip_flags & ~BIP_BLOCK_INTEGRITY;
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/block/bio.c
+++ linux-xilinx-zynqmp-5.4.0/block/bio.c
@@ -53,7 +53,7 @@
 	struct kmem_cache *slab;
 	unsigned int slab_ref;
 	unsigned int slab_size;
-	char name[8];
+	char name[12];
 };
 static DEFINE_MUTEX(bio_slab_lock);
 static struct bio_slab *bio_slabs;
@@ -233,6 +233,9 @@
 void bio_uninit(struct bio *bio)
 {
 	bio_disassociate_blkg(bio);
+
+	if (bio_integrity(bio))
+		bio_integrity_free(bio);
 }
 EXPORT_SYMBOL(bio_uninit);
 
@@ -302,7 +305,7 @@
 {
 	struct bio *parent = bio->bi_private;
 
-	if (!parent->bi_status)
+	if (bio->bi_status && !parent->bi_status)
 		parent->bi_status = bio->bi_status;
 	bio_put(bio);
 	return parent;
@@ -536,6 +539,56 @@
 EXPORT_SYMBOL(zero_fill_bio_iter);
 
 /**
+ * bio_truncate - truncate the bio to small size of @new_size
+ * @bio:	the bio to be truncated
+ * @new_size:	new size for truncating the bio
+ *
+ * Description:
+ *   Truncate the bio to new size of @new_size. If bio_op(bio) is
+ *   REQ_OP_READ, zero the truncated part. This function should only
+ *   be used for handling corner cases, such as bio eod.
+ */
+void bio_truncate(struct bio *bio, unsigned new_size)
+{
+	struct bio_vec bv;
+	struct bvec_iter iter;
+	unsigned int done = 0;
+	bool truncated = false;
+
+	if (new_size >= bio->bi_iter.bi_size)
+		return;
+
+	if (bio_op(bio) != REQ_OP_READ)
+		goto exit;
+
+	bio_for_each_segment(bv, bio, iter) {
+		if (done + bv.bv_len > new_size) {
+			unsigned offset;
+
+			if (!truncated)
+				offset = new_size - done;
+			else
+				offset = 0;
+			zero_user(bv.bv_page, bv.bv_offset + offset,
+				  bv.bv_len - offset);
+			truncated = true;
+		}
+		done += bv.bv_len;
+	}
+
+ exit:
+	/*
+	 * Don't touch bvec table here and make it really immutable, since
+	 * fs bio user has to retrieve all pages via bio_for_each_segment_all
+	 * in its .end_bio() callback.
+	 *
+	 * It is enough to truncate bio by updating .bi_size since we can make
+	 * correct bvec with the updated .bi_size for drivers.
+	 */
+	bio->bi_iter.bi_size = new_size;
+}
+
+/**
  * bio_put - release a reference to a bio
  * @bio:   bio to release reference to
  *
@@ -631,8 +684,8 @@
 		struct page *page, unsigned int len, unsigned int off,
 		bool *same_page)
 {
-	phys_addr_t vec_end_addr = page_to_phys(bv->bv_page) +
-		bv->bv_offset + bv->bv_len - 1;
+	size_t bv_end = bv->bv_offset + bv->bv_len;
+	phys_addr_t vec_end_addr = page_to_phys(bv->bv_page) + bv_end - 1;
 	phys_addr_t page_addr = page_to_phys(page);
 
 	if (vec_end_addr + 1 != page_addr + off)
@@ -641,9 +694,9 @@
 		return false;
 
 	*same_page = ((vec_end_addr & PAGE_MASK) == page_addr);
-	if (!*same_page && pfn_to_page(PFN_DOWN(vec_end_addr)) + 1 != page)
-		return false;
-	return true;
+	if (*same_page)
+		return true;
+	return (bv->bv_page + bv_end / PAGE_SIZE) == (page + off / PAGE_SIZE);
 }
 
 static bool bio_try_merge_pc_page(struct request_queue *q, struct bio *bio,
@@ -657,7 +710,7 @@
 
 	if ((addr1 | mask) != (addr2 | mask))
 		return false;
-	if (bv->bv_len + len > queue_max_segment_size(q))
+	if (len > queue_max_segment_size(q) - bv->bv_len)
 		return false;
 	return __bio_try_merge_page(bio, page, len, offset, same_page);
 }
@@ -751,10 +804,14 @@
 	if (WARN_ON_ONCE(bio_flagged(bio, BIO_CLONED)))
 		return false;
 
-	if (bio->bi_vcnt > 0 && !bio_full(bio, len)) {
+	if (bio->bi_vcnt > 0) {
 		struct bio_vec *bv = &bio->bi_io_vec[bio->bi_vcnt - 1];
 
 		if (page_is_mergeable(bv, page, len, off, same_page)) {
+			if (bio->bi_iter.bi_size > UINT_MAX - len) {
+				*same_page = false;
+				return false;
+			}
 			bv->bv_len += len;
 			bio->bi_iter.bi_size += len;
 			return true;
@@ -827,7 +884,7 @@
 		return;
 
 	bio_for_each_segment_all(bvec, bio, iter_all) {
-		if (mark_dirty && !PageCompound(bvec->bv_page))
+		if (mark_dirty)
 			set_page_dirty_lock(bvec->bv_page);
 		put_page(bvec->bv_page);
 	}
@@ -1570,7 +1627,7 @@
 		if (bytes > len)
 			bytes = len;
 
-		page = alloc_page(q->bounce_gfp | gfp_mask);
+		page = alloc_page(q->bounce_gfp | __GFP_ZERO | gfp_mask);
 		if (!page)
 			goto cleanup;
 
@@ -1634,8 +1691,7 @@
 	struct bvec_iter_all iter_all;
 
 	bio_for_each_segment_all(bvec, bio, iter_all) {
-		if (!PageCompound(bvec->bv_page))
-			set_page_dirty_lock(bvec->bv_page);
+		set_page_dirty_lock(bvec->bv_page);
 	}
 }
 
@@ -1683,7 +1739,7 @@
 	struct bvec_iter_all iter_all;
 
 	bio_for_each_segment_all(bvec, bio, iter_all) {
-		if (!PageDirty(bvec->bv_page) && !PageCompound(bvec->bv_page))
+		if (!PageDirty(bvec->bv_page))
 			goto defer;
 	}
 
@@ -1698,14 +1754,14 @@
 	schedule_work(&bio_dirty_work);
 }
 
-void update_io_ticks(struct hd_struct *part, unsigned long now)
+void update_io_ticks(struct hd_struct *part, unsigned long now, bool end)
 {
 	unsigned long stamp;
 again:
 	stamp = READ_ONCE(part->stamp);
 	if (unlikely(stamp != now)) {
 		if (likely(cmpxchg(&part->stamp, stamp, now) == stamp)) {
-			__part_stat_add(part, io_ticks, 1);
+			__part_stat_add(part, io_ticks, end ? now - stamp : 1);
 		}
 	}
 	if (part->partno) {
@@ -1721,7 +1777,7 @@
 
 	part_stat_lock();
 
-	update_io_ticks(part, jiffies);
+	update_io_ticks(part, jiffies, false);
 	part_stat_inc(part, ios[sgrp]);
 	part_stat_add(part, sectors[sgrp], sectors);
 	part_inc_in_flight(q, part, op_is_write(op));
@@ -1739,7 +1795,7 @@
 
 	part_stat_lock();
 
-	update_io_ticks(part, now);
+	update_io_ticks(part, now, true);
 	part_stat_add(part, nsecs[sgrp], jiffies_to_nsecs(duration));
 	part_stat_add(part, time_in_queue, duration);
 	part_dec_in_flight(q, part, op_is_write(req_op));
@@ -2122,7 +2178,7 @@
 	rcu_read_lock();
 
 	if (src->bi_blkg)
-		__bio_associate_blkg(dst, src->bi_blkg);
+		bio_associate_blkg_from_css(dst, &bio_blkcg(src)->css);
 
 	rcu_read_unlock();
 }
--- linux-xilinx-zynqmp-5.4.0.orig/block/blk-cgroup.c
+++ linux-xilinx-zynqmp-5.4.0/block/blk-cgroup.c
@@ -495,7 +495,7 @@
 {
 	/* some drivers (floppy) instantiate a queue w/o disk registered */
 	if (blkg->q->backing_dev_info->dev)
-		return dev_name(blkg->q->backing_dev_info->dev);
+		return bdi_dev_name(blkg->q->backing_dev_info);
 	return NULL;
 }
 
@@ -855,13 +855,20 @@
 			goto fail;
 		}
 
+		if (radix_tree_preload(GFP_KERNEL)) {
+			blkg_free(new_blkg);
+			ret = -ENOMEM;
+			goto fail;
+		}
+
 		rcu_read_lock();
 		spin_lock_irq(&q->queue_lock);
 
 		blkg = blkg_lookup_check(pos, pol, q);
 		if (IS_ERR(blkg)) {
 			ret = PTR_ERR(blkg);
-			goto fail_unlock;
+			blkg_free(new_blkg);
+			goto fail_preloaded;
 		}
 
 		if (blkg) {
@@ -870,10 +877,12 @@
 			blkg = blkg_create(pos, q, new_blkg);
 			if (IS_ERR(blkg)) {
 				ret = PTR_ERR(blkg);
-				goto fail_unlock;
+				goto fail_preloaded;
 			}
 		}
 
+		radix_tree_preload_end();
+
 		if (pos == blkcg)
 			goto success;
 	}
@@ -883,6 +892,8 @@
 	ctx->body = input;
 	return 0;
 
+fail_preloaded:
+	radix_tree_preload_end();
 fail_unlock:
 	spin_unlock_irq(&q->queue_lock);
 	rcu_read_unlock();
@@ -1078,6 +1089,8 @@
  */
 void blkcg_destroy_blkgs(struct blkcg *blkcg)
 {
+	might_sleep();
+
 	spin_lock_irq(&blkcg->lock);
 
 	while (!hlist_empty(&blkcg->blkg_list)) {
@@ -1085,14 +1098,20 @@
 						struct blkcg_gq, blkcg_node);
 		struct request_queue *q = blkg->q;
 
-		if (spin_trylock(&q->queue_lock)) {
-			blkg_destroy(blkg);
-			spin_unlock(&q->queue_lock);
-		} else {
+		if (need_resched() || !spin_trylock(&q->queue_lock)) {
+			/*
+			 * Given that the system can accumulate a huge number
+			 * of blkgs in pathological cases, check to see if we
+			 * need to rescheduling to avoid softlockup.
+			 */
 			spin_unlock_irq(&blkcg->lock);
-			cpu_relax();
+			cond_resched();
 			spin_lock_irq(&blkcg->lock);
+			continue;
 		}
+
+		blkg_destroy(blkg);
+		spin_unlock(&q->queue_lock);
 	}
 
 	spin_unlock_irq(&blkcg->lock);
@@ -1219,13 +1238,15 @@
 	if (preloaded)
 		radix_tree_preload_end();
 
-	ret = blk_iolatency_init(q);
+	ret = blk_throtl_init(q);
 	if (ret)
 		goto err_destroy_all;
 
-	ret = blk_throtl_init(q);
-	if (ret)
+	ret = blk_iolatency_init(q);
+	if (ret) {
+		blk_throtl_exit(q);
 		goto err_destroy_all;
+	}
 	return 0;
 
 err_destroy_all:
@@ -1424,6 +1445,10 @@
 		list_for_each_entry_reverse(blkg, &q->blkg_list, q_node)
 			pol->pd_init_fn(blkg->pd[pol->plid]);
 
+	if (pol->pd_online_fn)
+		list_for_each_entry_reverse(blkg, &q->blkg_list, q_node)
+			pol->pd_online_fn(blkg->pd[pol->plid]);
+
 	__set_bit(pol->plid, q->blkcg_pols);
 	ret = 0;
 
@@ -1441,10 +1466,14 @@
 	/* alloc failed, nothing's initialized yet, free everything */
 	spin_lock_irq(&q->queue_lock);
 	list_for_each_entry(blkg, &q->blkg_list, q_node) {
+		struct blkcg *blkcg = blkg->blkcg;
+
+		spin_lock(&blkcg->lock);
 		if (blkg->pd[pol->plid]) {
 			pol->pd_free_fn(blkg->pd[pol->plid]);
 			blkg->pd[pol->plid] = NULL;
 		}
+		spin_unlock(&blkcg->lock);
 	}
 	spin_unlock_irq(&q->queue_lock);
 	ret = -ENOMEM;
@@ -1476,12 +1505,16 @@
 	__clear_bit(pol->plid, q->blkcg_pols);
 
 	list_for_each_entry(blkg, &q->blkg_list, q_node) {
+		struct blkcg *blkcg = blkg->blkcg;
+
+		spin_lock(&blkcg->lock);
 		if (blkg->pd[pol->plid]) {
 			if (pol->pd_offline_fn)
 				pol->pd_offline_fn(blkg->pd[pol->plid]);
 			pol->pd_free_fn(blkg->pd[pol->plid]);
 			blkg->pd[pol->plid] = NULL;
 		}
+		spin_unlock(&blkcg->lock);
 	}
 
 	spin_unlock_irq(&q->queue_lock);
--- linux-xilinx-zynqmp-5.4.0.orig/block/blk-core.c
+++ linux-xilinx-zynqmp-5.4.0/block/blk-core.c
@@ -502,6 +502,7 @@
 		goto fail_stats;
 
 	q->backing_dev_info->ra_pages = VM_READAHEAD_PAGES;
+	q->backing_dev_info->io_pages = VM_READAHEAD_PAGES;
 	q->backing_dev_info->capabilities = BDI_CAP_CGROUP_WRITEBACK;
 	q->backing_dev_info->name = "block";
 	q->node = node_id;
@@ -742,11 +743,10 @@
 {
 	char b[BDEVNAME_SIZE];
 
-	printk(KERN_INFO "attempt to access beyond end of device\n");
-	printk(KERN_INFO "%s: rw=%d, want=%Lu, limit=%Lu\n",
-			bio_devname(bio, b), bio->bi_opf,
-			(unsigned long long)bio_end_sector(bio),
-			(long long)maxsector);
+	pr_info_ratelimited("attempt to access beyond end of device\n"
+			    "%s: rw=%d, want=%llu, limit=%llu\n",
+			    bio_devname(bio, b), bio->bi_opf,
+			    bio_end_sector(bio), maxsector);
 }
 
 #ifdef CONFIG_FAIL_MAKE_REQUEST
@@ -793,10 +793,7 @@
 
 		if (op_is_flush(bio->bi_opf) && !bio_sectors(bio))
 			return false;
-
-		WARN_ONCE(1,
-		       "generic_make_request: Trying to write "
-			"to read-only block-device %s (partno %d)\n",
+		pr_warn("Trying to write to read-only block-device %s (partno %d)\n",
 			bio_devname(bio, b), part->partno);
 		/* Older lvm-tools actually trigger this */
 		return false;
@@ -886,11 +883,14 @@
 	}
 
 	/*
-	 * For a REQ_NOWAIT based request, return -EOPNOTSUPP
-	 * if queue is not a request based queue.
+	 * Non-mq queues do not honor REQ_NOWAIT, so complete a bio
+	 * with BLK_STS_AGAIN status in order to catch -EAGAIN and
+	 * to give a chance to the caller to repeat request gracefully.
 	 */
-	if ((bio->bi_opf & REQ_NOWAIT) && !queue_is_mq(q))
-		goto not_supported;
+	if ((bio->bi_opf & REQ_NOWAIT) && !queue_is_mq(q)) {
+		status = BLK_STS_AGAIN;
+		goto end_io;
+	}
 
 	if (should_fail_bio(bio))
 		goto end_io;
@@ -1333,7 +1333,7 @@
 		part_stat_lock();
 		part = req->part;
 
-		update_io_ticks(part, jiffies);
+		update_io_ticks(part, jiffies, true);
 		part_stat_inc(part, ios[sgrp]);
 		part_stat_add(part, nsecs[sgrp], now - req->start_time_ns);
 		part_stat_add(part, time_in_queue, nsecs_to_jiffies64(now - req->start_time_ns));
@@ -1375,7 +1375,7 @@
 		rq->part = part;
 	}
 
-	update_io_ticks(part, jiffies);
+	update_io_ticks(part, jiffies, false);
 
 	part_stat_unlock();
 }
--- linux-xilinx-zynqmp-5.4.0.orig/block/blk-flush.c
+++ linux-xilinx-zynqmp-5.4.0/block/blk-flush.c
@@ -69,6 +69,7 @@
 #include <linux/blkdev.h>
 #include <linux/gfp.h>
 #include <linux/blk-mq.h>
+#include <linux/lockdep.h>
 
 #include "blk.h"
 #include "blk-mq.h"
@@ -221,8 +222,10 @@
 		return;
 	}
 
-	if (fq->rq_status != BLK_STS_OK)
+	if (fq->rq_status != BLK_STS_OK) {
 		error = fq->rq_status;
+		fq->rq_status = BLK_STS_OK;
+	}
 
 	hctx = flush_rq->mq_hctx;
 	if (!q->elevator) {
@@ -398,7 +401,7 @@
 	 */
 	if ((policy & REQ_FSEQ_DATA) &&
 	    !(policy & (REQ_FSEQ_PREFLUSH | REQ_FSEQ_POSTFLUSH))) {
-		blk_mq_request_bypass_insert(rq, false);
+		blk_mq_request_bypass_insert(rq, false, false);
 		return;
 	}
 
@@ -492,6 +495,9 @@
 	INIT_LIST_HEAD(&fq->flush_queue[1]);
 	INIT_LIST_HEAD(&fq->flush_data_in_flight);
 
+	lockdep_register_key(&fq->key);
+	lockdep_set_class(&fq->mq_flush_lock, &fq->key);
+
 	return fq;
 
  fail_rq:
@@ -506,6 +512,7 @@
 	if (!fq)
 		return;
 
+	lockdep_unregister_key(&fq->key);
 	kfree(fq->flush_rq);
 	kfree(fq);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/block/blk-ioc.c
+++ linux-xilinx-zynqmp-5.4.0/block/blk-ioc.c
@@ -84,6 +84,7 @@
 	 * making it impossible to determine icq_cache.  Record it in @icq.
 	 */
 	icq->__rcu_icq_cache = et->icq_cache;
+	icq->flags |= ICQ_DESTROYED;
 	call_rcu(&icq->__rcu_head, icq_free_icq_rcu);
 }
 
@@ -212,15 +213,21 @@
 {
 	unsigned long flags;
 
+	rcu_read_lock();
 	while (!list_empty(icq_list)) {
 		struct io_cq *icq = list_entry(icq_list->next,
 						struct io_cq, q_node);
 		struct io_context *ioc = icq->ioc;
 
 		spin_lock_irqsave(&ioc->lock, flags);
+		if (icq->flags & ICQ_DESTROYED) {
+			spin_unlock_irqrestore(&ioc->lock, flags);
+			continue;
+		}
 		ioc_destroy_icq(icq);
 		spin_unlock_irqrestore(&ioc->lock, flags);
 	}
+	rcu_read_unlock();
 }
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/block/blk-iocost.c
+++ linux-xilinx-zynqmp-5.4.0/block/blk-iocost.c
@@ -248,7 +248,9 @@
 
 	/* 1/64k is granular enough and can easily be handled w/ u32 */
 	HWEIGHT_WHOLE		= 1 << 16,
+};
 
+enum {
 	/*
 	 * As vtime is used to calculate the cost of each IO, it needs to
 	 * be fairly high precision.  For example, it should be able to
@@ -271,6 +273,11 @@
 	VRATE_MIN		= VTIME_PER_USEC * VRATE_MIN_PPM / MILLION,
 	VRATE_CLAMP_ADJ_PCT	= 4,
 
+	/* switch iff the conditions are met for longer than this */
+	AUTOP_CYCLE_NSEC	= 10LLU * NSEC_PER_SEC,
+};
+
+enum {
 	/* if IOs end up waiting for requests, issue less */
 	RQ_WAIT_BUSY_PCT	= 5,
 
@@ -288,9 +295,6 @@
 	SURPLUS_SCALE_ABS	= HWEIGHT_WHOLE / 50,	/* + 2% */
 	SURPLUS_MIN_ADJ_DELTA	= HWEIGHT_WHOLE / 33,	/* 3% */
 
-	/* switch iff the conditions are met for longer than this */
-	AUTOP_CYCLE_NSEC	= 10LLU * NSEC_PER_SEC,
-
 	/*
 	 * Count IO size in 4k pages.  The 12bit shift helps keeping
 	 * size-proportional components of cost calculation in closer
@@ -469,7 +473,7 @@
 	 */
 	atomic64_t			vtime;
 	atomic64_t			done_vtime;
-	atomic64_t			abs_vdebt;
+	u64				abs_vdebt;
 	u64				last_vtime;
 
 	/*
@@ -785,9 +789,14 @@
 
 	*page = *seqio = *randio = 0;
 
-	if (bps)
-		*page = DIV64_U64_ROUND_UP(VTIME_PER_SEC,
-					   DIV_ROUND_UP_ULL(bps, IOC_PAGE_SIZE));
+	if (bps) {
+		u64 bps_pages = DIV_ROUND_UP_ULL(bps, IOC_PAGE_SIZE);
+
+		if (bps_pages)
+			*page = DIV64_U64_ROUND_UP(VTIME_PER_SEC, bps_pages);
+		else
+			*page = 1;
+	}
 
 	if (seqiops) {
 		v = DIV64_U64_ROUND_UP(VTIME_PER_SEC, seqiops);
@@ -898,7 +907,27 @@
 
 	lockdep_assert_held(&ioc->lock);
 
-	inuse = min(active, inuse);
+	/*
+	 * For an active leaf node, its inuse shouldn't be zero or exceed
+	 * @active. An active internal node's inuse is solely determined by the
+	 * inuse to active ratio of its children regardless of @inuse.
+	 */
+	if (list_empty(&iocg->active_list) && iocg->child_active_sum) {
+		inuse = DIV64_U64_ROUND_UP(active * iocg->child_inuse_sum,
+					   iocg->child_active_sum);
+	} else {
+		/*
+		 * It may be tempting to turn this into a clamp expression with
+		 * a lower limit of 1 but active may be 0, which cannot be used
+		 * as an upper limit in that situation. This expression allows
+		 * active to clamp inuse unless it is 0, in which case inuse
+		 * becomes 1.
+		 */
+		inuse = min(inuse, active) ?: 1;
+	}
+
+	if (active == iocg->active && inuse == iocg->inuse)
+		return;
 
 	for (lvl = iocg->level - 1; lvl >= 0; lvl--) {
 		struct ioc_gq *parent = iocg->ancestors[lvl];
@@ -908,7 +937,7 @@
 		/* update the level sums */
 		parent->child_active_sum += (s32)(active - child->active);
 		parent->child_inuse_sum += (s32)(inuse - child->inuse);
-		/* apply the udpates */
+		/* apply the updates */
 		child->active = active;
 		child->inuse = inuse;
 
@@ -1145,7 +1174,7 @@
 	struct iocg_wake_ctx ctx = { .iocg = iocg };
 	u64 margin_ns = (u64)(ioc->period_us *
 			      WAITQ_TIMER_MARGIN_PCT / 100) * NSEC_PER_USEC;
-	u64 abs_vdebt, vdebt, vshortage, expires, oexpires;
+	u64 vdebt, vshortage, expires, oexpires;
 	s64 vbudget;
 	u32 hw_inuse;
 
@@ -1155,18 +1184,15 @@
 	vbudget = now->vnow - atomic64_read(&iocg->vtime);
 
 	/* pay off debt */
-	abs_vdebt = atomic64_read(&iocg->abs_vdebt);
-	vdebt = abs_cost_to_cost(abs_vdebt, hw_inuse);
+	vdebt = abs_cost_to_cost(iocg->abs_vdebt, hw_inuse);
 	if (vdebt && vbudget > 0) {
 		u64 delta = min_t(u64, vbudget, vdebt);
 		u64 abs_delta = min(cost_to_abs_cost(delta, hw_inuse),
-				    abs_vdebt);
+				    iocg->abs_vdebt);
 
 		atomic64_add(delta, &iocg->vtime);
 		atomic64_add(delta, &iocg->done_vtime);
-		atomic64_sub(abs_delta, &iocg->abs_vdebt);
-		if (WARN_ON_ONCE(atomic64_read(&iocg->abs_vdebt) < 0))
-			atomic64_set(&iocg->abs_vdebt, 0);
+		iocg->abs_vdebt -= abs_delta;
 	}
 
 	/*
@@ -1212,7 +1238,7 @@
 	return HRTIMER_NORESTART;
 }
 
-static void iocg_kick_delay(struct ioc_gq *iocg, struct ioc_now *now, u64 cost)
+static bool iocg_kick_delay(struct ioc_gq *iocg, struct ioc_now *now, u64 cost)
 {
 	struct ioc *ioc = iocg->ioc;
 	struct blkcg_gq *blkg = iocg_to_blkg(iocg);
@@ -1222,18 +1248,24 @@
 	u64 expires, oexpires;
 	u32 hw_inuse;
 
+	lockdep_assert_held(&iocg->waitq.lock);
+
 	/* debt-adjust vtime */
 	current_hweight(iocg, NULL, &hw_inuse);
-	vtime += abs_cost_to_cost(atomic64_read(&iocg->abs_vdebt), hw_inuse);
+	vtime += abs_cost_to_cost(iocg->abs_vdebt, hw_inuse);
 
-	/* clear or maintain depending on the overage */
-	if (time_before_eq64(vtime, now->vnow)) {
+	/*
+	 * Clear or maintain depending on the overage. Non-zero vdebt is what
+	 * guarantees that @iocg is online and future iocg_kick_delay() will
+	 * clear use_delay. Don't leave it on when there's no vdebt.
+	 */
+	if (!iocg->abs_vdebt || time_before_eq64(vtime, now->vnow)) {
 		blkcg_clear_delay(blkg);
-		return;
+		return false;
 	}
 	if (!atomic_read(&blkg->use_delay) &&
 	    time_before_eq64(vtime, now->vnow + vmargin))
-		return;
+		return false;
 
 	/* use delay */
 	if (cost) {
@@ -1250,19 +1282,23 @@
 	oexpires = ktime_to_ns(hrtimer_get_softexpires(&iocg->delay_timer));
 	if (hrtimer_is_queued(&iocg->delay_timer) &&
 	    abs(oexpires - expires) <= margin_ns / 4)
-		return;
+		return true;
 
 	hrtimer_start_range_ns(&iocg->delay_timer, ns_to_ktime(expires),
 			       margin_ns / 4, HRTIMER_MODE_ABS);
+	return true;
 }
 
 static enum hrtimer_restart iocg_delay_timer_fn(struct hrtimer *timer)
 {
 	struct ioc_gq *iocg = container_of(timer, struct ioc_gq, delay_timer);
 	struct ioc_now now;
+	unsigned long flags;
 
+	spin_lock_irqsave(&iocg->waitq.lock, flags);
 	ioc_now(iocg->ioc, &now);
 	iocg_kick_delay(iocg, &now, 0);
+	spin_unlock_irqrestore(&iocg->waitq.lock, flags);
 
 	return HRTIMER_NORESTART;
 }
@@ -1317,7 +1353,7 @@
 		return false;
 
 	/* is something in flight? */
-	if (atomic64_read(&iocg->done_vtime) < atomic64_read(&iocg->vtime))
+	if (atomic64_read(&iocg->done_vtime) != atomic64_read(&iocg->vtime))
 		return false;
 
 	return true;
@@ -1370,14 +1406,13 @@
 	 * should have woken up in the last period and expire idle iocgs.
 	 */
 	list_for_each_entry_safe(iocg, tiocg, &ioc->active_iocgs, active_list) {
-		if (!waitqueue_active(&iocg->waitq) &&
-		    !atomic64_read(&iocg->abs_vdebt) && !iocg_is_idle(iocg))
+		if (!waitqueue_active(&iocg->waitq) && !iocg->abs_vdebt &&
+		    !iocg_is_idle(iocg))
 			continue;
 
 		spin_lock(&iocg->waitq.lock);
 
-		if (waitqueue_active(&iocg->waitq) ||
-		    atomic64_read(&iocg->abs_vdebt)) {
+		if (waitqueue_active(&iocg->waitq) || iocg->abs_vdebt) {
 			/* might be oversleeping vtime / hweight changes, kick */
 			iocg_kick_waitq(iocg, &now);
 			iocg_kick_delay(iocg, &now, 0);
@@ -1540,19 +1575,39 @@
 	if (rq_wait_pct > RQ_WAIT_BUSY_PCT ||
 	    missed_ppm[READ] > ppm_rthr ||
 	    missed_ppm[WRITE] > ppm_wthr) {
+		/* clearly missing QoS targets, slow down vrate */
 		ioc->busy_level = max(ioc->busy_level, 0);
 		ioc->busy_level++;
 	} else if (rq_wait_pct <= RQ_WAIT_BUSY_PCT * UNBUSY_THR_PCT / 100 &&
 		   missed_ppm[READ] <= ppm_rthr * UNBUSY_THR_PCT / 100 &&
 		   missed_ppm[WRITE] <= ppm_wthr * UNBUSY_THR_PCT / 100) {
-		/* take action iff there is contention */
-		if (nr_shortages && !nr_lagging) {
+		/* QoS targets are being met with >25% margin */
+		if (nr_shortages) {
+			/*
+			 * We're throttling while the device has spare
+			 * capacity.  If vrate was being slowed down, stop.
+			 */
 			ioc->busy_level = min(ioc->busy_level, 0);
-			/* redistribute surpluses first */
-			if (!nr_surpluses)
+
+			/*
+			 * If there are IOs spanning multiple periods, wait
+			 * them out before pushing the device harder.  If
+			 * there are surpluses, let redistribution work it
+			 * out first.
+			 */
+			if (!nr_lagging && !nr_surpluses)
 				ioc->busy_level--;
+		} else {
+			/*
+			 * Nobody is being throttled and the users aren't
+			 * issuing enough IOs to saturate the device.  We
+			 * simply don't know how close the device is to
+			 * saturation.  Coast.
+			 */
+			ioc->busy_level = 0;
 		}
 	} else {
+		/* inside the hysterisis margin, we're good */
 		ioc->busy_level = 0;
 	}
 
@@ -1593,7 +1648,7 @@
 				      vrate_min, vrate_max);
 		}
 
-		trace_iocost_ioc_vrate_adj(ioc, vrate, &missed_ppm, rq_wait_pct,
+		trace_iocost_ioc_vrate_adj(ioc, vrate, missed_ppm, rq_wait_pct,
 					   nr_lagging, nr_shortages,
 					   nr_surpluses);
 
@@ -1602,7 +1657,7 @@
 			ioc->period_us * vrate * INUSE_MARGIN_PCT, 100);
 	} else if (ioc->busy_level != prev_busy_level || nr_lagging) {
 		trace_iocost_ioc_vrate_adj(ioc, atomic64_read(&ioc->vtime_rate),
-					   &missed_ppm, rq_wait_pct, nr_lagging,
+					   missed_ppm, rq_wait_pct, nr_lagging,
 					   nr_shortages, nr_surpluses);
 	}
 
@@ -1720,26 +1775,49 @@
 	 * tests are racy but the races aren't systemic - we only miss once
 	 * in a while which is fine.
 	 */
-	if (!waitqueue_active(&iocg->waitq) &&
-	    !atomic64_read(&iocg->abs_vdebt) &&
+	if (!waitqueue_active(&iocg->waitq) && !iocg->abs_vdebt &&
 	    time_before_eq64(vtime + cost, now.vnow)) {
 		iocg_commit_bio(iocg, bio, cost);
 		return;
 	}
 
 	/*
-	 * We're over budget.  If @bio has to be issued regardless,
-	 * remember the abs_cost instead of advancing vtime.
-	 * iocg_kick_waitq() will pay off the debt before waking more IOs.
+	 * We activated above but w/o any synchronization. Deactivation is
+	 * synchronized with waitq.lock and we won't get deactivated as long
+	 * as we're waiting or has debt, so we're good if we're activated
+	 * here. In the unlikely case that we aren't, just issue the IO.
+	 */
+	spin_lock_irq(&iocg->waitq.lock);
+
+	if (unlikely(list_empty(&iocg->active_list))) {
+		spin_unlock_irq(&iocg->waitq.lock);
+		iocg_commit_bio(iocg, bio, cost);
+		return;
+	}
+
+	/*
+	 * We're over budget. If @bio has to be issued regardless, remember
+	 * the abs_cost instead of advancing vtime. iocg_kick_waitq() will pay
+	 * off the debt before waking more IOs.
+	 *
 	 * This way, the debt is continuously paid off each period with the
-	 * actual budget available to the cgroup.  If we just wound vtime,
-	 * we would incorrectly use the current hw_inuse for the entire
-	 * amount which, for example, can lead to the cgroup staying
-	 * blocked for a long time even with substantially raised hw_inuse.
+	 * actual budget available to the cgroup. If we just wound vtime, we
+	 * would incorrectly use the current hw_inuse for the entire amount
+	 * which, for example, can lead to the cgroup staying blocked for a
+	 * long time even with substantially raised hw_inuse.
+	 *
+	 * An iocg with vdebt should stay online so that the timer can keep
+	 * deducting its vdebt and [de]activate use_delay mechanism
+	 * accordingly. We don't want to race against the timer trying to
+	 * clear them and leave @iocg inactive w/ dangling use_delay heavily
+	 * penalizing the cgroup and its descendants.
 	 */
 	if (bio_issue_as_root_blkg(bio) || fatal_signal_pending(current)) {
-		atomic64_add(abs_cost, &iocg->abs_vdebt);
-		iocg_kick_delay(iocg, &now, cost);
+		iocg->abs_vdebt += abs_cost;
+		if (iocg_kick_delay(iocg, &now, cost))
+			blkcg_schedule_throttle(rqos->q,
+					(bio->bi_opf & REQ_SWAP) == REQ_SWAP);
+		spin_unlock_irq(&iocg->waitq.lock);
 		return;
 	}
 
@@ -1756,20 +1834,6 @@
 	 * All waiters are on iocg->waitq and the wait states are
 	 * synchronized using waitq.lock.
 	 */
-	spin_lock_irq(&iocg->waitq.lock);
-
-	/*
-	 * We activated above but w/o any synchronization.  Deactivation is
-	 * synchronized with waitq.lock and we won't get deactivated as
-	 * long as we're waiting, so we're good if we're activated here.
-	 * In the unlikely case that we are deactivated, just issue the IO.
-	 */
-	if (unlikely(list_empty(&iocg->active_list))) {
-		spin_unlock_irq(&iocg->waitq.lock);
-		iocg_commit_bio(iocg, bio, cost);
-		return;
-	}
-
 	init_waitqueue_func_entry(&wait.wait, iocg_wake_fn);
 	wait.wait.private = current;
 	wait.bio = bio;
@@ -1801,6 +1865,7 @@
 	struct ioc_now now;
 	u32 hw_inuse;
 	u64 abs_cost, cost;
+	unsigned long flags;
 
 	/* bypass if disabled or for root cgroup */
 	if (!ioc->enabled || !iocg->level)
@@ -1820,15 +1885,28 @@
 		iocg->cursor = bio_end;
 
 	/*
-	 * Charge if there's enough vtime budget and the existing request
-	 * has cost assigned.  Otherwise, account it as debt.  See debt
-	 * handling in ioc_rqos_throttle() for details.
+	 * Charge if there's enough vtime budget and the existing request has
+	 * cost assigned.
 	 */
 	if (rq->bio && rq->bio->bi_iocost_cost &&
-	    time_before_eq64(atomic64_read(&iocg->vtime) + cost, now.vnow))
+	    time_before_eq64(atomic64_read(&iocg->vtime) + cost, now.vnow)) {
 		iocg_commit_bio(iocg, bio, cost);
-	else
-		atomic64_add(abs_cost, &iocg->abs_vdebt);
+		return;
+	}
+
+	/*
+	 * Otherwise, account it as debt if @iocg is online, which it should
+	 * be for the vast majority of cases. See debt handling in
+	 * ioc_rqos_throttle() for details.
+	 */
+	spin_lock_irqsave(&iocg->waitq.lock, flags);
+	if (likely(!list_empty(&iocg->active_list))) {
+		iocg->abs_vdebt += abs_cost;
+		iocg_kick_delay(iocg, &now, cost);
+	} else {
+		iocg_commit_bio(iocg, bio, cost);
+	}
+	spin_unlock_irqrestore(&iocg->waitq.lock, flags);
 }
 
 static void ioc_rqos_done_bio(struct rq_qos *rqos, struct bio *bio)
@@ -1998,7 +2076,6 @@
 	iocg->ioc = ioc;
 	atomic64_set(&iocg->vtime, now.vnow);
 	atomic64_set(&iocg->done_vtime, now.vnow);
-	atomic64_set(&iocg->abs_vdebt, 0);
 	atomic64_set(&iocg->active_period, atomic64_read(&ioc->cur_period));
 	INIT_LIST_HEAD(&iocg->active_list);
 	iocg->hweight_active = HWEIGHT_WHOLE;
@@ -2026,14 +2103,15 @@
 {
 	struct ioc_gq *iocg = pd_to_iocg(pd);
 	struct ioc *ioc = iocg->ioc;
+	unsigned long flags;
 
 	if (ioc) {
-		spin_lock(&ioc->lock);
+		spin_lock_irqsave(&ioc->lock, flags);
 		if (!list_empty(&iocg->active_list)) {
 			propagate_active_weight(iocg, 0, 0);
 			list_del_init(&iocg->active_list);
 		}
-		spin_unlock(&ioc->lock);
+		spin_unlock_irqrestore(&ioc->lock, flags);
 
 		hrtimer_cancel(&iocg->waitq_timer);
 		hrtimer_cancel(&iocg->delay_timer);
--- linux-xilinx-zynqmp-5.4.0.orig/block/blk-iolatency.c
+++ linux-xilinx-zynqmp-5.4.0/block/blk-iolatency.c
@@ -86,7 +86,17 @@
 struct blk_iolatency {
 	struct rq_qos rqos;
 	struct timer_list timer;
-	atomic_t enabled;
+
+	/*
+	 * ->enabled is the master enable switch gating the throttling logic and
+	 * inflight tracking. The number of cgroups which have iolat enabled is
+	 * tracked in ->enable_cnt, and ->enable is flipped on/off accordingly
+	 * from ->enable_work with the request_queue frozen. For details, See
+	 * blkiolatency_enable_work_fn().
+	 */
+	bool enabled;
+	atomic_t enable_cnt;
+	struct work_struct enable_work;
 };
 
 static inline struct blk_iolatency *BLKIOLATENCY(struct rq_qos *rqos)
@@ -94,11 +104,6 @@
 	return container_of(rqos, struct blk_iolatency, rqos);
 }
 
-static inline bool blk_iolatency_enabled(struct blk_iolatency *blkiolat)
-{
-	return atomic_read(&blkiolat->enabled) > 0;
-}
-
 struct child_latency_info {
 	spinlock_t lock;
 
@@ -463,7 +468,7 @@
 	struct blkcg_gq *blkg = bio->bi_blkg;
 	bool issue_as_root = bio_issue_as_root_blkg(bio);
 
-	if (!blk_iolatency_enabled(blkiolat))
+	if (!blkiolat->enabled)
 		return;
 
 	while (blkg && blkg->parent) {
@@ -593,7 +598,6 @@
 	u64 window_start;
 	u64 now = ktime_to_ns(ktime_get());
 	bool issue_as_root = bio_issue_as_root_blkg(bio);
-	bool enabled = false;
 	int inflight = 0;
 
 	blkg = bio->bi_blkg;
@@ -604,8 +608,7 @@
 	if (!iolat)
 		return;
 
-	enabled = blk_iolatency_enabled(iolat->blkiolat);
-	if (!enabled)
+	if (!iolat->blkiolat->enabled)
 		return;
 
 	while (blkg && blkg->parent) {
@@ -643,6 +646,7 @@
 	struct blk_iolatency *blkiolat = BLKIOLATENCY(rqos);
 
 	del_timer_sync(&blkiolat->timer);
+	flush_work(&blkiolat->enable_work);
 	blkcg_deactivate_policy(rqos->q, &blkcg_policy_iolatency);
 	kfree(blkiolat);
 }
@@ -714,6 +718,44 @@
 	rcu_read_unlock();
 }
 
+/**
+ * blkiolatency_enable_work_fn - Enable or disable iolatency on the device
+ * @work: enable_work of the blk_iolatency of interest
+ *
+ * iolatency needs to keep track of the number of in-flight IOs per cgroup. This
+ * is relatively expensive as it involves walking up the hierarchy twice for
+ * every IO. Thus, if iolatency is not enabled in any cgroup for the device, we
+ * want to disable the in-flight tracking.
+ *
+ * We have to make sure that the counting is balanced - we don't want to leak
+ * the in-flight counts by disabling accounting in the completion path while IOs
+ * are in flight. This is achieved by ensuring that no IO is in flight by
+ * freezing the queue while flipping ->enabled. As this requires a sleepable
+ * context, ->enabled flipping is punted to this work function.
+ */
+static void blkiolatency_enable_work_fn(struct work_struct *work)
+{
+	struct blk_iolatency *blkiolat = container_of(work, struct blk_iolatency,
+						      enable_work);
+	bool enabled;
+
+	/*
+	 * There can only be one instance of this function running for @blkiolat
+	 * and it's guaranteed to be executed at least once after the latest
+	 * ->enabled_cnt modification. Acting on the latest ->enable_cnt is
+	 * sufficient.
+	 *
+	 * Also, we know @blkiolat is safe to access as ->enable_work is flushed
+	 * in blkcg_iolatency_exit().
+	 */
+	enabled = atomic_read(&blkiolat->enable_cnt);
+	if (enabled != blkiolat->enabled) {
+		blk_mq_freeze_queue(blkiolat->rqos.q);
+		blkiolat->enabled = enabled;
+		blk_mq_unfreeze_queue(blkiolat->rqos.q);
+	}
+}
+
 int blk_iolatency_init(struct request_queue *q)
 {
 	struct blk_iolatency *blkiolat;
@@ -739,17 +781,15 @@
 	}
 
 	timer_setup(&blkiolat->timer, blkiolatency_timer_fn, 0);
+	INIT_WORK(&blkiolat->enable_work, blkiolatency_enable_work_fn);
 
 	return 0;
 }
 
-/*
- * return 1 for enabling iolatency, return -1 for disabling iolatency, otherwise
- * return 0.
- */
-static int iolatency_set_min_lat_nsec(struct blkcg_gq *blkg, u64 val)
+static void iolatency_set_min_lat_nsec(struct blkcg_gq *blkg, u64 val)
 {
 	struct iolatency_grp *iolat = blkg_to_lat(blkg);
+	struct blk_iolatency *blkiolat = iolat->blkiolat;
 	u64 oldval = iolat->min_lat_nsec;
 
 	iolat->min_lat_nsec = val;
@@ -757,13 +797,15 @@
 	iolat->cur_win_nsec = min_t(u64, iolat->cur_win_nsec,
 				    BLKIOLATENCY_MAX_WIN_SIZE);
 
-	if (!oldval && val)
-		return 1;
+	if (!oldval && val) {
+		if (atomic_inc_return(&blkiolat->enable_cnt) == 1)
+			schedule_work(&blkiolat->enable_work);
+	}
 	if (oldval && !val) {
 		blkcg_clear_delay(blkg);
-		return -1;
+		if (atomic_dec_return(&blkiolat->enable_cnt) == 0)
+			schedule_work(&blkiolat->enable_work);
 	}
-	return 0;
 }
 
 static void iolatency_clear_scaling(struct blkcg_gq *blkg)
@@ -795,7 +837,6 @@
 	u64 lat_val = 0;
 	u64 oldval;
 	int ret;
-	int enable = 0;
 
 	ret = blkg_conf_prep(blkcg, &blkcg_policy_iolatency, buf, &ctx);
 	if (ret)
@@ -830,37 +871,12 @@
 	blkg = ctx.blkg;
 	oldval = iolat->min_lat_nsec;
 
-	enable = iolatency_set_min_lat_nsec(blkg, lat_val);
-	if (enable) {
-		WARN_ON_ONCE(!blk_get_queue(blkg->q));
-		blkg_get(blkg);
-	}
-
-	if (oldval != iolat->min_lat_nsec) {
+	iolatency_set_min_lat_nsec(blkg, lat_val);
+	if (oldval != iolat->min_lat_nsec)
 		iolatency_clear_scaling(blkg);
-	}
-
 	ret = 0;
 out:
 	blkg_conf_finish(&ctx);
-	if (ret == 0 && enable) {
-		struct iolatency_grp *tmp = blkg_to_lat(blkg);
-		struct blk_iolatency *blkiolat = tmp->blkiolat;
-
-		blk_mq_freeze_queue(blkg->q);
-
-		if (enable == 1)
-			atomic_inc(&blkiolat->enabled);
-		else if (enable == -1)
-			atomic_dec(&blkiolat->enabled);
-		else
-			WARN_ON_ONCE(1);
-
-		blk_mq_unfreeze_queue(blkg->q);
-
-		blkg_put(blkg);
-		blk_put_queue(blkg->q);
-	}
 	return ret ?: nbytes;
 }
 
@@ -1001,14 +1017,8 @@
 {
 	struct iolatency_grp *iolat = pd_to_lat(pd);
 	struct blkcg_gq *blkg = lat_to_blkg(iolat);
-	struct blk_iolatency *blkiolat = iolat->blkiolat;
-	int ret;
 
-	ret = iolatency_set_min_lat_nsec(blkg, 0);
-	if (ret == 1)
-		atomic_inc(&blkiolat->enabled);
-	if (ret == -1)
-		atomic_dec(&blkiolat->enabled);
+	iolatency_set_min_lat_nsec(blkg, 0);
 	iolatency_clear_scaling(blkg);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/block/blk-map.c
+++ linux-xilinx-zynqmp-5.4.0/block/blk-map.c
@@ -151,7 +151,7 @@
 	return 0;
 
 unmap_rq:
-	__blk_rq_unmap_user(bio);
+	blk_rq_unmap_user(bio);
 fail:
 	rq->bio = NULL;
 	return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/block/blk-merge.c
+++ linux-xilinx-zynqmp-5.4.0/block/blk-merge.c
@@ -7,6 +7,7 @@
 #include <linux/bio.h>
 #include <linux/blkdev.h>
 #include <linux/scatterlist.h>
+#include <linux/blk-cgroup.h>
 
 #include <trace/events/block.h>
 
@@ -154,20 +155,23 @@
 	if (max_sectors > start_offset)
 		return max_sectors - start_offset;
 
-	return sectors & (lbs - 1);
+	return sectors & ~(lbs - 1);
 }
 
-static unsigned get_max_segment_size(const struct request_queue *q,
-				     unsigned offset)
+static inline unsigned get_max_segment_size(const struct request_queue *q,
+					    struct page *start_page,
+					    unsigned long offset)
 {
 	unsigned long mask = queue_segment_boundary(q);
 
-	/* default segment boundary mask means no boundary limit */
-	if (mask == BLK_SEG_BOUNDARY_MASK)
-		return queue_max_segment_size(q);
+	offset = mask & (page_to_phys(start_page) + offset);
 
-	return min_t(unsigned long, mask - (mask & offset) + 1,
-		     queue_max_segment_size(q));
+	/*
+	 * overflow may be triggered in case of zero page physical address
+	 * on 32bit arch, use queue's max segment size when that happens.
+	 */
+	return min_not_zero(mask - offset + 1,
+			(unsigned long)queue_max_segment_size(q));
 }
 
 /**
@@ -201,7 +205,8 @@
 	unsigned seg_size = 0;
 
 	while (len && *nsegs < max_segs) {
-		seg_size = get_max_segment_size(q, bv->bv_offset + total_len);
+		seg_size = get_max_segment_size(q, bv->bv_page,
+						bv->bv_offset + total_len);
 		seg_size = min(seg_size, len);
 
 		(*nsegs)++;
@@ -366,6 +371,14 @@
 	switch (bio_op(rq->bio)) {
 	case REQ_OP_DISCARD:
 	case REQ_OP_SECURE_ERASE:
+		if (queue_max_discard_segments(rq->q) > 1) {
+			struct bio *bio = rq->bio;
+
+			for_each_bio(bio)
+				nr_phys_segs++;
+			return nr_phys_segs;
+		}
+		return 1;
 	case REQ_OP_WRITE_ZEROES:
 		return 0;
 	case REQ_OP_WRITE_SAME:
@@ -404,7 +417,8 @@
 
 	while (nbytes > 0) {
 		unsigned offset = bvec->bv_offset + total;
-		unsigned len = min(get_max_segment_size(q, offset), nbytes);
+		unsigned len = min(get_max_segment_size(q, bvec->bv_page,
+					offset), nbytes);
 		struct page *page = bvec->bv_page;
 
 		/*
@@ -463,7 +477,7 @@
 			     struct scatterlist *sglist,
 			     struct scatterlist **sg)
 {
-	struct bio_vec uninitialized_var(bvec), bvprv = { NULL };
+	struct bio_vec bvec, bvprv = { NULL };
 	struct bvec_iter iter;
 	int nsegs = 0;
 	bool new_bio = false;
@@ -548,15 +562,29 @@
 }
 EXPORT_SYMBOL(blk_rq_map_sg);
 
+static inline unsigned int blk_rq_get_max_segments(struct request *rq)
+{
+	if (req_op(rq) == REQ_OP_DISCARD)
+		return queue_max_discard_segments(rq->q);
+	return queue_max_segments(rq->q);
+}
+
 static inline int ll_new_hw_segment(struct request *req, struct bio *bio,
 		unsigned int nr_phys_segs)
 {
-	if (req->nr_phys_segments + nr_phys_segs > queue_max_segments(req->q))
+	if (!blk_cgroup_mergeable(req, bio))
 		goto no_merge;
 
 	if (blk_integrity_merge_bio(req->q, req, bio) == false)
 		goto no_merge;
 
+	/* discard request merge won't add new segment */
+	if (req_op(req) == REQ_OP_DISCARD)
+		return 1;
+
+	if (req->nr_phys_segments + nr_phys_segs > blk_rq_get_max_segments(req))
+		goto no_merge;
+
 	/*
 	 * This will form the start of a new hw segment.  Bump both
 	 * counters.
@@ -635,7 +663,10 @@
 		return 0;
 
 	total_phys_segments = req->nr_phys_segments + next->nr_phys_segments;
-	if (total_phys_segments > queue_max_segments(q))
+	if (total_phys_segments > blk_rq_get_max_segments(req))
+		return 0;
+
+	if (!blk_cgroup_mergeable(req, next->bio))
 		return 0;
 
 	if (blk_integrity_merge_rq(q, req, next) == false)
@@ -690,21 +721,6 @@
 		part_stat_unlock();
 	}
 }
-/*
- * Two cases of handling DISCARD merge:
- * If max_discard_segments > 1, the driver takes every bio
- * as a range and send them to controller together. The ranges
- * needn't to be contiguous.
- * Otherwise, the bios/requests will be handled as same as
- * others which should be contiguous.
- */
-static inline bool blk_discard_mergable(struct request *req)
-{
-	if (req_op(req) == REQ_OP_DISCARD &&
-	    queue_max_discard_segments(req->q) > 1)
-		return true;
-	return false;
-}
 
 static enum elv_merge blk_try_req_merge(struct request *req,
 					struct request *next)
@@ -861,6 +877,10 @@
 	if (rq->rq_disk != bio->bi_disk)
 		return false;
 
+	/* don't merge across cgroup boundaries */
+	if (!blk_cgroup_mergeable(rq, bio))
+		return false;
+
 	/* only merge integrity protected bio into ditto rq */
 	if (blk_integrity_merge_bio(rq->q, rq, bio) == false)
 		return false;
--- linux-xilinx-zynqmp-5.4.0.orig/block/blk-mq-debugfs.c
+++ linux-xilinx-zynqmp-5.4.0/block/blk-mq-debugfs.c
@@ -125,6 +125,9 @@
 	QUEUE_FLAG_NAME(REGISTERED),
 	QUEUE_FLAG_NAME(SCSI_PASSTHROUGH),
 	QUEUE_FLAG_NAME(QUIESCED),
+	QUEUE_FLAG_NAME(PCI_P2PDMA),
+	QUEUE_FLAG_NAME(ZONE_RESETALL),
+	QUEUE_FLAG_NAME(RQ_ALLOC_TIME),
 };
 #undef QUEUE_FLAG_NAME
 
@@ -880,6 +883,9 @@
 	char name[20];
 	int i;
 
+	if (!q->debugfs_dir)
+		return;
+
 	snprintf(name, sizeof(name), "hctx%u", hctx->queue_num);
 	hctx->debugfs_dir = debugfs_create_dir(name, q->debugfs_dir);
 
--- linux-xilinx-zynqmp-5.4.0.orig/block/blk-mq-sched.c
+++ linux-xilinx-zynqmp-5.4.0/block/blk-mq-sched.c
@@ -59,8 +59,7 @@
 }
 
 /*
- * Mark a hardware queue as needing a restart. For shared queues, maintain
- * a count of how many hardware queues are marked for restart.
+ * Mark a hardware queue as needing a restart.
  */
 void blk_mq_sched_mark_restart_hctx(struct blk_mq_hw_ctx *hctx)
 {
@@ -77,19 +76,32 @@
 		return;
 	clear_bit(BLK_MQ_S_SCHED_RESTART, &hctx->state);
 
+	/*
+	 * Order clearing SCHED_RESTART and list_empty_careful(&hctx->dispatch)
+	 * in blk_mq_run_hw_queue(). Its pair is the barrier in
+	 * blk_mq_dispatch_rq_list(). So dispatch code won't see SCHED_RESTART,
+	 * meantime new request added to hctx->dispatch is missed to check in
+	 * blk_mq_run_hw_queue().
+	 */
+	smp_mb();
+
 	blk_mq_run_hw_queue(hctx, true);
 }
 
 /*
  * Only SCSI implements .get_budget and .put_budget, and SCSI restarts
  * its queue by itself in its completion handler, so we don't need to
- * restart queue if .get_budget() returns BLK_STS_NO_RESOURCE.
+ * restart queue if .get_budget() fails to get the budget.
+ *
+ * Returns -EAGAIN if hctx->dispatch was found non-empty and run_work has to
+ * be run again.  This is necessary to avoid starving flushes.
  */
-static void blk_mq_do_dispatch_sched(struct blk_mq_hw_ctx *hctx)
+static int blk_mq_do_dispatch_sched(struct blk_mq_hw_ctx *hctx)
 {
 	struct request_queue *q = hctx->queue;
 	struct elevator_queue *e = q->elevator;
 	LIST_HEAD(rq_list);
+	int ret = 0;
 
 	do {
 		struct request *rq;
@@ -97,6 +109,11 @@
 		if (e->type->ops.has_work && !e->type->ops.has_work(hctx))
 			break;
 
+		if (!list_empty_careful(&hctx->dispatch)) {
+			ret = -EAGAIN;
+			break;
+		}
+
 		if (!blk_mq_get_dispatch_budget(hctx))
 			break;
 
@@ -113,6 +130,8 @@
 		 */
 		list_add(&rq->queuelist, &rq_list);
 	} while (blk_mq_dispatch_rq_list(q, &rq_list, true));
+
+	return ret;
 }
 
 static struct blk_mq_ctx *blk_mq_next_ctx(struct blk_mq_hw_ctx *hctx,
@@ -129,17 +148,26 @@
 /*
  * Only SCSI implements .get_budget and .put_budget, and SCSI restarts
  * its queue by itself in its completion handler, so we don't need to
- * restart queue if .get_budget() returns BLK_STS_NO_RESOURCE.
+ * restart queue if .get_budget() fails to get the budget.
+ *
+ * Returns -EAGAIN if hctx->dispatch was found non-empty and run_work has to
+ * to be run again.  This is necessary to avoid starving flushes.
  */
-static void blk_mq_do_dispatch_ctx(struct blk_mq_hw_ctx *hctx)
+static int blk_mq_do_dispatch_ctx(struct blk_mq_hw_ctx *hctx)
 {
 	struct request_queue *q = hctx->queue;
 	LIST_HEAD(rq_list);
 	struct blk_mq_ctx *ctx = READ_ONCE(hctx->dispatch_from);
+	int ret = 0;
 
 	do {
 		struct request *rq;
 
+		if (!list_empty_careful(&hctx->dispatch)) {
+			ret = -EAGAIN;
+			break;
+		}
+
 		if (!sbitmap_any_bit_set(&hctx->ctx_map))
 			break;
 
@@ -165,21 +193,17 @@
 	} while (blk_mq_dispatch_rq_list(q, &rq_list, true));
 
 	WRITE_ONCE(hctx->dispatch_from, ctx);
+	return ret;
 }
 
-void blk_mq_sched_dispatch_requests(struct blk_mq_hw_ctx *hctx)
+int __blk_mq_sched_dispatch_requests(struct blk_mq_hw_ctx *hctx)
 {
 	struct request_queue *q = hctx->queue;
 	struct elevator_queue *e = q->elevator;
 	const bool has_sched_dispatch = e && e->type->ops.dispatch_request;
+	int ret = 0;
 	LIST_HEAD(rq_list);
 
-	/* RCU or SRCU read lock is needed before checking quiesced flag */
-	if (unlikely(blk_mq_hctx_stopped(hctx) || blk_queue_quiesced(q)))
-		return;
-
-	hctx->run++;
-
 	/*
 	 * If we have previous entries on our dispatch list, grab them first for
 	 * more fair dispatch.
@@ -208,19 +232,41 @@
 		blk_mq_sched_mark_restart_hctx(hctx);
 		if (blk_mq_dispatch_rq_list(q, &rq_list, false)) {
 			if (has_sched_dispatch)
-				blk_mq_do_dispatch_sched(hctx);
+				ret = blk_mq_do_dispatch_sched(hctx);
 			else
-				blk_mq_do_dispatch_ctx(hctx);
+				ret = blk_mq_do_dispatch_ctx(hctx);
 		}
 	} else if (has_sched_dispatch) {
-		blk_mq_do_dispatch_sched(hctx);
+		ret = blk_mq_do_dispatch_sched(hctx);
 	} else if (hctx->dispatch_busy) {
 		/* dequeue request one by one from sw queue if queue is busy */
-		blk_mq_do_dispatch_ctx(hctx);
+		ret = blk_mq_do_dispatch_ctx(hctx);
 	} else {
 		blk_mq_flush_busy_ctxs(hctx, &rq_list);
 		blk_mq_dispatch_rq_list(q, &rq_list, false);
 	}
+
+	return ret;
+}
+
+void blk_mq_sched_dispatch_requests(struct blk_mq_hw_ctx *hctx)
+{
+	struct request_queue *q = hctx->queue;
+
+	/* RCU or SRCU read lock is needed before checking quiesced flag */
+	if (unlikely(blk_mq_hctx_stopped(hctx) || blk_queue_quiesced(q)))
+		return;
+
+	hctx->run++;
+
+	/*
+	 * A return of -EAGAIN is an indication that hctx->dispatch is not
+	 * empty and we must run again in order to avoid starving flushes.
+	 */
+	if (__blk_mq_sched_dispatch_requests(hctx) == -EAGAIN) {
+		if (__blk_mq_sched_dispatch_requests(hctx) == -EAGAIN)
+			blk_mq_run_hw_queue(hctx, true);
+	}
 }
 
 bool blk_mq_sched_try_merge(struct request_queue *q, struct bio *bio,
@@ -325,14 +371,16 @@
 		unsigned int nr_segs)
 {
 	struct elevator_queue *e = q->elevator;
-	struct blk_mq_ctx *ctx = blk_mq_get_ctx(q);
-	struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(q, bio->bi_opf, ctx);
+	struct blk_mq_ctx *ctx;
+	struct blk_mq_hw_ctx *hctx;
 	bool ret = false;
 	enum hctx_type type;
 
 	if (e && e->type->ops.bio_merge)
-		return e->type->ops.bio_merge(hctx, bio, nr_segs);
+		return e->type->ops.bio_merge(q, bio, nr_segs);
 
+	ctx = blk_mq_get_ctx(q);
+	hctx = blk_mq_map_queue(q, bio->bi_opf, ctx);
 	type = hctx->type;
 	if ((hctx->flags & BLK_MQ_F_SHOULD_MERGE) &&
 			!list_empty_careful(&ctx->rq_lists[type])) {
@@ -361,13 +409,19 @@
 				       bool has_sched,
 				       struct request *rq)
 {
-	/* dispatch flush rq directly */
-	if (rq->rq_flags & RQF_FLUSH_SEQ) {
-		spin_lock(&hctx->lock);
-		list_add(&rq->queuelist, &hctx->dispatch);
-		spin_unlock(&hctx->lock);
+	/*
+	 * dispatch flush and passthrough rq directly
+	 *
+	 * passthrough request has to be added to hctx->dispatch directly.
+	 * For some reason, device may be in one situation which can't
+	 * handle FS request, so STS_RESOURCE is always returned and the
+	 * FS request will be added to hctx->dispatch. However passthrough
+	 * request may be required at that time for fixing the problem. If
+	 * passthrough request is added to scheduler queue, there isn't any
+	 * chance to dispatch it given we prioritize requests in hctx->dispatch.
+	 */
+	if ((rq->rq_flags & RQF_FLUSH_SEQ) || blk_rq_is_passthrough(rq))
 		return true;
-	}
 
 	if (has_sched)
 		rq->rq_flags |= RQF_SORTED;
@@ -391,8 +445,32 @@
 
 	WARN_ON(e && (rq->tag != -1));
 
-	if (blk_mq_sched_bypass_insert(hctx, !!e, rq))
+	if (blk_mq_sched_bypass_insert(hctx, !!e, rq)) {
+		/*
+		 * Firstly normal IO request is inserted to scheduler queue or
+		 * sw queue, meantime we add flush request to dispatch queue(
+		 * hctx->dispatch) directly and there is at most one in-flight
+		 * flush request for each hw queue, so it doesn't matter to add
+		 * flush request to tail or front of the dispatch queue.
+		 *
+		 * Secondly in case of NCQ, flush request belongs to non-NCQ
+		 * command, and queueing it will fail when there is any
+		 * in-flight normal IO request(NCQ command). When adding flush
+		 * rq to the front of hctx->dispatch, it is easier to introduce
+		 * extra time to flush rq's latency because of S_SCHED_RESTART
+		 * compared with adding to the tail of dispatch queue, then
+		 * chance of flush merge is increased, and less flush requests
+		 * will be issued to controller. It is observed that ~10% time
+		 * is saved in blktests block/004 on disk attached to AHCI/NCQ
+		 * drive when adding flush rq to the front of hctx->dispatch.
+		 *
+		 * Simply queue flush rq to the front of hctx->dispatch so that
+		 * intensive flush workloads can benefit in case of NCQ HW.
+		 */
+		at_head = (rq->rq_flags & RQF_FLUSH_SEQ) ? true : at_head;
+		blk_mq_request_bypass_insert(rq, at_head, false);
 		goto run;
+	}
 
 	if (e && e->type->ops.insert_requests) {
 		LIST_HEAD(list);
--- linux-xilinx-zynqmp-5.4.0.orig/block/blk-mq-sched.h
+++ linux-xilinx-zynqmp-5.4.0/block/blk-mq-sched.h
@@ -66,7 +66,7 @@
 	struct request_queue *q = rq->q;
 	struct elevator_queue *e = q->elevator;
 
-	if (e && e->type->ops.requeue_request)
+	if ((rq->rq_flags & RQF_ELVPRIV) && e && e->type->ops.requeue_request)
 		e->type->ops.requeue_request(rq);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/block/blk-mq-sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/block/blk-mq-sysfs.c
@@ -36,8 +36,6 @@
 	struct blk_mq_hw_ctx *hctx = container_of(kobj, struct blk_mq_hw_ctx,
 						  kobj);
 
-	cancel_delayed_work_sync(&hctx->run_work);
-
 	if (hctx->flags & BLK_MQ_F_BLOCKING)
 		cleanup_srcu_struct(hctx->srcu);
 	blk_free_flush_queue(hctx->fq);
@@ -166,20 +164,25 @@
 
 static ssize_t blk_mq_hw_sysfs_cpus_show(struct blk_mq_hw_ctx *hctx, char *page)
 {
+	const size_t size = PAGE_SIZE - 1;
 	unsigned int i, first = 1;
-	ssize_t ret = 0;
+	int ret = 0, pos = 0;
 
 	for_each_cpu(i, hctx->cpumask) {
 		if (first)
-			ret += sprintf(ret + page, "%u", i);
+			ret = snprintf(pos + page, size - pos, "%u", i);
 		else
-			ret += sprintf(ret + page, ", %u", i);
+			ret = snprintf(pos + page, size - pos, ", %u", i);
+
+		if (ret >= size - pos)
+			break;
 
 		first = 0;
+		pos += ret;
 	}
 
-	ret += sprintf(ret + page, "\n");
-	return ret;
+	ret = snprintf(pos + page, size + 1 - pos, "\n");
+	return pos + ret;
 }
 
 static struct blk_mq_hw_ctx_sysfs_entry blk_mq_hw_sysfs_nr_tags = {
@@ -247,7 +250,7 @@
 {
 	struct request_queue *q = hctx->queue;
 	struct blk_mq_ctx *ctx;
-	int i, ret;
+	int i, j, ret;
 
 	if (!hctx->nr_ctx)
 		return 0;
@@ -259,9 +262,16 @@
 	hctx_for_each_ctx(hctx, ctx, i) {
 		ret = kobject_add(&ctx->kobj, &hctx->kobj, "cpu%u", ctx->cpu);
 		if (ret)
-			break;
+			goto out;
 	}
 
+	return 0;
+out:
+	hctx_for_each_ctx(hctx, ctx, j) {
+		if (j < i)
+			kobject_del(&ctx->kobj);
+	}
+	kobject_del(&hctx->kobj);
 	return ret;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/block/blk-mq.c
+++ linux-xilinx-zynqmp-5.4.0/block/blk-mq.c
@@ -579,7 +579,14 @@
 	q->mq_ops->complete(rq);
 }
 
-static void __blk_mq_complete_request(struct request *rq)
+/**
+ * blk_mq_complete_request - end I/O on a request
+ * @rq:		the request being processed
+ *
+ * Description:
+ *	Complete a request by scheduling the ->complete_rq operation.
+ **/
+void blk_mq_complete_request(struct request *rq)
 {
 	struct blk_mq_ctx *ctx = rq->mq_ctx;
 	struct request_queue *q = rq->q;
@@ -625,6 +632,7 @@
 	}
 	put_cpu();
 }
+EXPORT_SYMBOL(blk_mq_complete_request);
 
 static void hctx_unlock(struct blk_mq_hw_ctx *hctx, int srcu_idx)
 	__releases(hctx->srcu)
@@ -646,23 +654,6 @@
 		*srcu_idx = srcu_read_lock(hctx->srcu);
 }
 
-/**
- * blk_mq_complete_request - end I/O on a request
- * @rq:		the request being processed
- *
- * Description:
- *	Ends all I/O on a request. It does not handle partial completions.
- *	The actual completion happens out-of-order, through a IPI handler.
- **/
-bool blk_mq_complete_request(struct request *rq)
-{
-	if (unlikely(blk_should_fake_timeout(rq->q)))
-		return false;
-	__blk_mq_complete_request(rq);
-	return true;
-}
-EXPORT_SYMBOL(blk_mq_complete_request);
-
 int blk_mq_request_started(struct request *rq)
 {
 	return blk_mq_rq_state(rq) != MQ_RQ_IDLE;
@@ -733,7 +724,6 @@
 	/* this request will be re-inserted to io scheduler queue */
 	blk_mq_sched_requeue_request(rq);
 
-	BUG_ON(!list_empty(&rq->queuelist));
 	blk_mq_add_to_requeue_list(rq, true, kick_requeue_list);
 }
 EXPORT_SYMBOL(blk_mq_requeue_request);
@@ -761,7 +751,7 @@
 		 * merge.
 		 */
 		if (rq->rq_flags & RQF_DONTPREP)
-			blk_mq_request_bypass_insert(rq, false);
+			blk_mq_request_bypass_insert(rq, false, false);
 		else
 			blk_mq_sched_insert_request(rq, true, false, false);
 	}
@@ -829,10 +819,10 @@
 			       void *priv, bool reserved)
 {
 	/*
-	 * If we find a request that is inflight and the queue matches,
+	 * If we find a request that isn't idle and the queue matches,
 	 * we know the queue is busy. Return false to stop the iteration.
 	 */
-	if (rq->state == MQ_RQ_IN_FLIGHT && rq->q == hctx->queue) {
+	if (blk_mq_request_started(rq) && rq->q == hctx->queue) {
 		bool *busy = priv;
 
 		*busy = true;
@@ -1113,7 +1103,7 @@
 static bool blk_mq_mark_tag_wait(struct blk_mq_hw_ctx *hctx,
 				 struct request *rq)
 {
-	struct sbitmap_queue *sbq = &hctx->tags->bitmap_tags;
+	struct sbitmap_queue *sbq;
 	struct wait_queue_head *wq;
 	wait_queue_entry_t *wait;
 	bool ret;
@@ -1136,6 +1126,10 @@
 	if (!list_empty_careful(&wait->entry))
 		return false;
 
+	if (blk_mq_tag_is_reserved(rq->mq_hctx->sched_tags, rq->internal_tag))
+		sbq = &hctx->tags->breserved_tags;
+	else
+		sbq = &hctx->tags->bitmap_tags;
 	wq = &bt_wait_ptr(sbq, hctx)->wait;
 
 	spin_lock_irq(&wq->lock);
@@ -1151,6 +1145,22 @@
 	__add_wait_queue(wq, wait);
 
 	/*
+	 * Add one explicit barrier since blk_mq_get_driver_tag() may
+	 * not imply barrier in case of failure.
+	 *
+	 * Order adding us to wait queue and allocating driver tag.
+	 *
+	 * The pair is the one implied in sbitmap_queue_wake_up() which
+	 * orders clearing sbitmap tag bits and waitqueue_active() in
+	 * __sbitmap_queue_wake_up(), since waitqueue_active() is lockless
+	 *
+	 * Otherwise, re-order of adding wait queue and getting driver tag
+	 * may cause __sbitmap_queue_wake_up() to wake up nothing because
+	 * the waitqueue_active() may not observe us in wait queue.
+	 */
+	smp_mb();
+
+	/*
 	 * It's possible that a tag was freed in the window between the
 	 * allocation failure and adding the hardware queue to the wait
 	 * queue.
@@ -1205,6 +1215,23 @@
 
 #define BLK_MQ_RESOURCE_DELAY	3		/* ms units */
 
+static void blk_mq_handle_dev_resource(struct request *rq,
+				       struct list_head *list)
+{
+	struct request *next =
+		list_first_entry_or_null(list, struct request, queuelist);
+
+	/*
+	 * If an I/O scheduler has been configured and we got a driver tag for
+	 * the next request already, free it.
+	 */
+	if (next)
+		blk_mq_put_driver_tag(next);
+
+	list_add(&rq->queuelist, list);
+	__blk_mq_requeue_request(rq);
+}
+
 /*
  * Returns true if we did some work AND can potentially do more.
  */
@@ -1216,6 +1243,7 @@
 	bool no_tag = false;
 	int errors, queued;
 	blk_status_t ret = BLK_STS_OK;
+	bool no_budget_avail = false;
 
 	if (list_empty(list))
 		return false;
@@ -1232,8 +1260,11 @@
 		rq = list_first_entry(list, struct request, queuelist);
 
 		hctx = rq->mq_hctx;
-		if (!got_budget && !blk_mq_get_dispatch_budget(hctx))
+		if (!got_budget && !blk_mq_get_dispatch_budget(hctx)) {
+			blk_mq_put_driver_tag(rq);
+			no_budget_avail = true;
 			break;
+		}
 
 		if (!blk_mq_get_driver_tag(rq)) {
 			/*
@@ -1272,17 +1303,7 @@
 
 		ret = q->mq_ops->queue_rq(hctx, &bd);
 		if (ret == BLK_STS_RESOURCE || ret == BLK_STS_DEV_RESOURCE) {
-			/*
-			 * If an I/O scheduler has been configured and we got a
-			 * driver tag for the next request already, free it
-			 * again.
-			 */
-			if (!list_empty(list)) {
-				nxt = list_first_entry(list, struct request, queuelist);
-				blk_mq_put_driver_tag(nxt);
-			}
-			list_add(&rq->queuelist, list);
-			__blk_mq_requeue_request(rq);
+			blk_mq_handle_dev_resource(rq, list);
 			break;
 		}
 
@@ -1313,10 +1334,19 @@
 			q->mq_ops->commit_rqs(hctx);
 
 		spin_lock(&hctx->lock);
-		list_splice_init(list, &hctx->dispatch);
+		list_splice_tail_init(list, &hctx->dispatch);
 		spin_unlock(&hctx->lock);
 
 		/*
+		 * Order adding requests to hctx->dispatch and checking
+		 * SCHED_RESTART flag. The pair of this smp_mb() is the one
+		 * in blk_mq_sched_restart(). Avoid restart code path to
+		 * miss the new added requests to hctx->dispatch, meantime
+		 * SCHED_RESTART is observed here.
+		 */
+		smp_mb();
+
+		/*
 		 * If SCHED_RESTART was set by the caller of this function and
 		 * it is no longer set that means that it was cleared by another
 		 * thread and hence that a queue rerun is needed.
@@ -1338,13 +1368,15 @@
 		 *
 		 * If driver returns BLK_STS_RESOURCE and SCHED_RESTART
 		 * bit is set, run queue after a delay to avoid IO stalls
-		 * that could otherwise occur if the queue is idle.
+		 * that could otherwise occur if the queue is idle.  We'll do
+		 * similar if we couldn't get budget and SCHED_RESTART is set.
 		 */
 		needs_restart = blk_mq_sched_needs_restart(hctx);
 		if (!needs_restart ||
 		    (no_tag && list_empty_careful(&hctx->dispatch_wait.entry)))
 			blk_mq_run_hw_queue(hctx, true);
-		else if (needs_restart && (ret == BLK_STS_RESOURCE))
+		else if (needs_restart && (ret == BLK_STS_RESOURCE ||
+					   no_budget_avail))
 			blk_mq_delay_run_hw_queue(hctx, BLK_MQ_RESOURCE_DELAY);
 
 		blk_mq_update_dispatch_busy(hctx, true);
@@ -1607,6 +1639,12 @@
 		return;
 
 	clear_bit(BLK_MQ_S_STOPPED, &hctx->state);
+	/*
+	 * Pairs with the smp_mb() in blk_mq_hctx_stopped() to order the
+	 * clearing of BLK_MQ_S_STOPPED above and the checking of dispatch
+	 * list in the subsequent routine.
+	 */
+	smp_mb__after_atomic();
 	blk_mq_run_hw_queue(hctx, async);
 }
 EXPORT_SYMBOL_GPL(blk_mq_start_stopped_hw_queue);
@@ -1668,12 +1706,16 @@
  * Should only be used carefully, when the caller knows we want to
  * bypass a potential IO scheduler on the target device.
  */
-void blk_mq_request_bypass_insert(struct request *rq, bool run_queue)
+void blk_mq_request_bypass_insert(struct request *rq, bool at_head,
+				  bool run_queue)
 {
 	struct blk_mq_hw_ctx *hctx = rq->mq_hctx;
 
 	spin_lock(&hctx->lock);
-	list_add_tail(&rq->queuelist, &hctx->dispatch);
+	if (at_head)
+		list_add(&rq->queuelist, &hctx->dispatch);
+	else
+		list_add_tail(&rq->queuelist, &hctx->dispatch);
 	spin_unlock(&hctx->lock);
 
 	if (run_queue)
@@ -1863,7 +1905,8 @@
 	if (bypass_insert)
 		return BLK_STS_RESOURCE;
 
-	blk_mq_request_bypass_insert(rq, run_queue);
+	blk_mq_sched_insert_request(rq, false, run_queue, false);
+
 	return BLK_STS_OK;
 }
 
@@ -1879,7 +1922,7 @@
 
 	ret = __blk_mq_try_issue_directly(hctx, rq, cookie, false, true);
 	if (ret == BLK_STS_RESOURCE || ret == BLK_STS_DEV_RESOURCE)
-		blk_mq_request_bypass_insert(rq, true);
+		blk_mq_request_bypass_insert(rq, false, true);
 	else if (ret != BLK_STS_OK)
 		blk_mq_end_request(rq, ret);
 
@@ -1913,7 +1956,7 @@
 		if (ret != BLK_STS_OK) {
 			if (ret == BLK_STS_RESOURCE ||
 					ret == BLK_STS_DEV_RESOURCE) {
-				blk_mq_request_bypass_insert(rq,
+				blk_mq_request_bypass_insert(rq, false,
 							list_empty(list));
 				break;
 			}
@@ -2487,18 +2530,6 @@
 	 * If the cpu isn't present, the cpu is mapped to first hctx.
 	 */
 	for_each_possible_cpu(i) {
-		hctx_idx = set->map[HCTX_TYPE_DEFAULT].mq_map[i];
-		/* unmapped hw queue can be remapped after CPU topo changed */
-		if (!set->tags[hctx_idx] &&
-		    !__blk_mq_alloc_rq_map(set, hctx_idx)) {
-			/*
-			 * If tags initialization fail for some hctx,
-			 * that hctx won't be brought online.  In this
-			 * case, remap the current ctx to hctx[0] which
-			 * is guaranteed to always have tags allocated
-			 */
-			set->map[HCTX_TYPE_DEFAULT].mq_map[i] = 0;
-		}
 
 		ctx = per_cpu_ptr(q->queue_ctx, i);
 		for (j = 0; j < set->nr_maps; j++) {
@@ -2507,6 +2538,18 @@
 						HCTX_TYPE_DEFAULT, i);
 				continue;
 			}
+			hctx_idx = set->map[j].mq_map[i];
+			/* unmapped hw queue can be remapped after CPU topo changed */
+			if (!set->tags[hctx_idx] &&
+			    !__blk_mq_alloc_rq_map(set, hctx_idx)) {
+				/*
+				 * If tags initialization fail for some hctx,
+				 * that hctx won't be brought online.  In this
+				 * case, remap the current ctx to hctx[0] which
+				 * is guaranteed to always have tags allocated
+				 */
+				set->map[j].mq_map[i] = 0;
+			}
 
 			hctx = blk_mq_map_queue_type(q, j, i);
 			ctx->hctxs[j] = hctx;
@@ -2943,10 +2986,12 @@
 /* tags can _not_ be used after returning from blk_mq_exit_queue */
 void blk_mq_exit_queue(struct request_queue *q)
 {
-	struct blk_mq_tag_set	*set = q->tag_set;
+	struct blk_mq_tag_set *set = q->tag_set;
 
-	blk_mq_del_queue_tag_set(q);
+	/* Checks hctx->flags & BLK_MQ_F_TAG_QUEUE_SHARED. */
 	blk_mq_exit_hw_queues(q, set, set->nr_hw_queues);
+	/* May clear BLK_MQ_F_TAG_QUEUE_SHARED in hctx->flags. */
+	blk_mq_del_queue_tag_set(q);
 }
 
 static int __blk_mq_alloc_rq_maps(struct blk_mq_tag_set *set)
@@ -3003,6 +3048,14 @@
 
 static int blk_mq_update_queue_map(struct blk_mq_tag_set *set)
 {
+	/*
+	 * blk_mq_map_queues() and multiple .map_queues() implementations
+	 * expect that set->map[HCTX_TYPE_DEFAULT].nr_queues is set to the
+	 * number of hardware queues.
+	 */
+	if (set->nr_maps == 1)
+		set->map[HCTX_TYPE_DEFAULT].nr_queues = set->nr_hw_queues;
+
 	if (set->ops->map_queues && !is_kdump_kernel()) {
 		int i;
 
@@ -3265,7 +3318,9 @@
 
 	if (set->nr_maps == 1 && nr_hw_queues > nr_cpu_ids)
 		nr_hw_queues = nr_cpu_ids;
-	if (nr_hw_queues < 1 || nr_hw_queues == set->nr_hw_queues)
+	if (nr_hw_queues < 1)
+		return;
+	if (set->nr_maps == 1 && nr_hw_queues == set->nr_hw_queues)
 		return;
 
 	list_for_each_entry(q, &set->tag_list, tag_set_list)
@@ -3290,8 +3345,8 @@
 
 	prev_nr_hw_queues = set->nr_hw_queues;
 	set->nr_hw_queues = nr_hw_queues;
-	blk_mq_update_queue_map(set);
 fallback:
+	blk_mq_update_queue_map(set);
 	list_for_each_entry(q, &set->tag_list, tag_set_list) {
 		blk_mq_realloc_hw_ctxs(set, q);
 		if (q->nr_hw_queues != set->nr_hw_queues) {
--- linux-xilinx-zynqmp-5.4.0.orig/block/blk-mq.h
+++ linux-xilinx-zynqmp-5.4.0/block/blk-mq.h
@@ -66,7 +66,8 @@
  */
 void __blk_mq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
 				bool at_head);
-void blk_mq_request_bypass_insert(struct request *rq, bool run_queue);
+void blk_mq_request_bypass_insert(struct request *rq, bool at_head,
+				  bool run_queue);
 void blk_mq_insert_requests(struct blk_mq_hw_ctx *hctx, struct blk_mq_ctx *ctx,
 				struct list_head *list);
 
@@ -176,6 +177,19 @@
 
 static inline bool blk_mq_hctx_stopped(struct blk_mq_hw_ctx *hctx)
 {
+	/* Fast path: hardware queue is not stopped most of the time. */
+	if (likely(!test_bit(BLK_MQ_S_STOPPED, &hctx->state)))
+		return false;
+
+	/*
+	 * This barrier is used to order adding of dispatch list before and
+	 * the test of BLK_MQ_S_STOPPED below. Pairs with the memory barrier
+	 * in blk_mq_start_stopped_hw_queue() so that dispatch code could
+	 * either see BLK_MQ_S_STOPPED is cleared or dispatch list is not
+	 * empty to avoid missing dispatching requests.
+	 */
+	smp_mb();
+
 	return test_bit(BLK_MQ_S_STOPPED, &hctx->state);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/block/blk-pm.c
+++ linux-xilinx-zynqmp-5.4.0/block/blk-pm.c
@@ -67,6 +67,10 @@
 
 	WARN_ON_ONCE(q->rpm_status != RPM_ACTIVE);
 
+	spin_lock_irq(&q->queue_lock);
+	q->rpm_status = RPM_SUSPENDING;
+	spin_unlock_irq(&q->queue_lock);
+
 	/*
 	 * Increase the pm_only counter before checking whether any
 	 * non-PM blk_queue_enter() calls are in progress to avoid that any
@@ -89,15 +93,14 @@
 	/* Switch q_usage_counter back to per-cpu mode. */
 	blk_mq_unfreeze_queue(q);
 
-	spin_lock_irq(&q->queue_lock);
-	if (ret < 0)
+	if (ret < 0) {
+		spin_lock_irq(&q->queue_lock);
+		q->rpm_status = RPM_ACTIVE;
 		pm_runtime_mark_last_busy(q->dev);
-	else
-		q->rpm_status = RPM_SUSPENDING;
-	spin_unlock_irq(&q->queue_lock);
+		spin_unlock_irq(&q->queue_lock);
 
-	if (ret)
 		blk_clear_pm_only(q);
+	}
 
 	return ret;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/block/blk-rq-qos.c
+++ linux-xilinx-zynqmp-5.4.0/block/blk-rq-qos.c
@@ -225,8 +225,8 @@
 
 	data->got_token = true;
 	smp_wmb();
-	list_del_init(&curr->entry);
 	wake_up_process(data->task);
+	list_del_init_careful(&curr->entry);
 	return 1;
 }
 
@@ -266,8 +266,8 @@
 	if (!has_sleeper && acquire_inflight_cb(rqw, private_data))
 		return;
 
-	prepare_to_wait_exclusive(&rqw->wait, &data.wq, TASK_UNINTERRUPTIBLE);
-	has_sleeper = !wq_has_single_sleeper(&rqw->wait);
+	has_sleeper = !prepare_to_wait_exclusive(&rqw->wait, &data.wq,
+						 TASK_UNINTERRUPTIBLE);
 	do {
 		/* The memory barrier in set_task_state saves us here. */
 		if (data.got_token)
--- linux-xilinx-zynqmp-5.4.0.orig/block/blk-rq-qos.h
+++ linux-xilinx-zynqmp-5.4.0/block/blk-rq-qos.h
@@ -7,6 +7,7 @@
 #include <linux/blk_types.h>
 #include <linux/atomic.h>
 #include <linux/wait.h>
+#include <linux/blk-mq.h>
 
 #include "blk-mq-debugfs.h"
 
@@ -99,8 +100,21 @@
 
 static inline void rq_qos_add(struct request_queue *q, struct rq_qos *rqos)
 {
+	/*
+	 * No IO can be in-flight when adding rqos, so freeze queue, which
+	 * is fine since we only support rq_qos for blk-mq queue.
+	 *
+	 * Reuse ->queue_lock for protecting against other concurrent
+	 * rq_qos adding/deleting
+	 */
+	blk_mq_freeze_queue(q);
+
+	spin_lock_irq(&q->queue_lock);
 	rqos->next = q->rq_qos;
 	q->rq_qos = rqos;
+	spin_unlock_irq(&q->queue_lock);
+
+	blk_mq_unfreeze_queue(q);
 
 	if (rqos->ops->debugfs_attrs)
 		blk_mq_debugfs_register_rqos(rqos);
@@ -110,12 +124,22 @@
 {
 	struct rq_qos **cur;
 
+	/*
+	 * See comment in rq_qos_add() about freezing queue & using
+	 * ->queue_lock.
+	 */
+	blk_mq_freeze_queue(q);
+
+	spin_lock_irq(&q->queue_lock);
 	for (cur = &q->rq_qos; *cur; cur = &(*cur)->next) {
 		if (*cur == rqos) {
 			*cur = rqos->next;
 			break;
 		}
 	}
+	spin_unlock_irq(&q->queue_lock);
+
+	blk_mq_unfreeze_queue(q);
 
 	blk_mq_debugfs_unregister_rqos(rqos);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/block/blk-settings.c
+++ linux-xilinx-zynqmp-5.4.0/block/blk-settings.c
@@ -328,7 +328,7 @@
  *   storage device can address.  The default of 512 covers most
  *   hardware.
  **/
-void blk_queue_logical_block_size(struct request_queue *q, unsigned short size)
+void blk_queue_logical_block_size(struct request_queue *q, unsigned int size)
 {
 	q->limits.logical_block_size = size;
 
@@ -473,6 +473,14 @@
 }
 EXPORT_SYMBOL(blk_queue_stack_limits);
 
+static unsigned int blk_round_down_sectors(unsigned int sectors, unsigned int lbs)
+{
+	sectors = round_down(sectors, lbs >> SECTOR_SHIFT);
+	if (sectors < PAGE_SIZE >> SECTOR_SHIFT)
+		sectors = PAGE_SIZE >> SECTOR_SHIFT;
+	return sectors;
+}
+
 /**
  * blk_stack_limits - adjust queue_limits for stacked devices
  * @t:	the stacking driver limits (top device)
@@ -586,6 +594,10 @@
 		ret = -1;
 	}
 
+	t->max_sectors = blk_round_down_sectors(t->max_sectors, t->logical_block_size);
+	t->max_hw_sectors = blk_round_down_sectors(t->max_hw_sectors, t->logical_block_size);
+	t->max_dev_sectors = blk_round_down_sectors(t->max_dev_sectors, t->logical_block_size);
+
 	/* Discard alignment and granularity */
 	if (b->discard_granularity) {
 		alignment = queue_limit_discard_alignment(b, start);
@@ -664,6 +676,9 @@
 		printk(KERN_NOTICE "%s: Warning: Device %s is misaligned\n",
 		       top, bottom);
 	}
+
+	t->backing_dev_info->io_pages =
+		t->limits.max_sectors >> (PAGE_SHIFT - 9);
 }
 EXPORT_SYMBOL(disk_stack_limits);
 
--- linux-xilinx-zynqmp-5.4.0.orig/block/blk-stat.c
+++ linux-xilinx-zynqmp-5.4.0/block/blk-stat.c
@@ -28,7 +28,7 @@
 /* src is a per-cpu stat, mean isn't initialized */
 void blk_rq_stat_sum(struct blk_rq_stat *dst, struct blk_rq_stat *src)
 {
-	if (!src->nr_samples)
+	if (dst->nr_samples + src->nr_samples <= dst->nr_samples)
 		return;
 
 	dst->min = min(dst->min, src->min);
--- linux-xilinx-zynqmp-5.4.0.orig/block/blk-sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/block/blk-sysfs.c
@@ -891,9 +891,16 @@
 
 	blk_free_queue_stats(q->stats);
 
-	if (queue_is_mq(q))
+	if (queue_is_mq(q)) {
+		struct blk_mq_hw_ctx *hctx;
+		int i;
+
 		cancel_delayed_work_sync(&q->requeue_work);
 
+		queue_for_each_hw_ctx(q, hctx, i)
+			cancel_delayed_work_sync(&hctx->run_work);
+	}
+
 	blk_exit_queue(q);
 
 	blk_queue_free_zone_bitmaps(q);
@@ -1053,15 +1060,17 @@
 	 */
 	if (queue_is_mq(q))
 		blk_mq_unregister_dev(disk_to_dev(disk), q);
-
-	kobject_uevent(&q->kobj, KOBJ_REMOVE);
-	kobject_del(&q->kobj);
 	blk_trace_remove_sysfs(disk_to_dev(disk));
 
 	mutex_lock(&q->sysfs_lock);
 	if (q->elevator)
 		elv_unregister_queue(q);
 	mutex_unlock(&q->sysfs_lock);
+
+	/* Now that we've deleted all child objects, we can delete the queue. */
+	kobject_uevent(&q->kobj, KOBJ_REMOVE);
+	kobject_del(&q->kobj);
+
 	mutex_unlock(&q->sysfs_dir_lock);
 
 	kobject_put(&disk_to_dev(disk)->kobj);
--- linux-xilinx-zynqmp-5.4.0.orig/block/blk-throttle.c
+++ linux-xilinx-zynqmp-5.4.0/block/blk-throttle.c
@@ -1374,6 +1374,7 @@
 		   tg_bps_limit(tg, READ), tg_bps_limit(tg, WRITE),
 		   tg_iops_limit(tg, READ), tg_iops_limit(tg, WRITE));
 
+	rcu_read_lock();
 	/*
 	 * Update has_rules[] flags for the updated tg's subtree.  A tg is
 	 * considered to have rules if either the tg itself or any of its
@@ -1401,6 +1402,7 @@
 		this_tg->latency_target = max(this_tg->latency_target,
 				parent_tg->latency_target);
 	}
+	rcu_read_unlock();
 
 	/*
 	 * We're already holding queue_lock and know @tg is valid.  Let's
@@ -2414,6 +2416,7 @@
 void blk_throtl_exit(struct request_queue *q)
 {
 	BUG_ON(!q->td);
+	del_timer_sync(&q->td->service_queue.pending_timer);
 	throtl_shutdown_wq(q);
 	blkcg_deactivate_policy(q, &blkcg_policy_throtl);
 	free_percpu(q->td->latency_buckets[READ]);
--- linux-xilinx-zynqmp-5.4.0.orig/block/blk-timeout.c
+++ linux-xilinx-zynqmp-5.4.0/block/blk-timeout.c
@@ -20,13 +20,11 @@
 }
 __setup("fail_io_timeout=", setup_fail_io_timeout);
 
-int blk_should_fake_timeout(struct request_queue *q)
+bool __blk_should_fake_timeout(struct request_queue *q)
 {
-	if (!test_bit(QUEUE_FLAG_FAIL_IO, &q->queue_flags))
-		return 0;
-
 	return should_fail(&fail_io_timeout, 1);
 }
+EXPORT_SYMBOL_GPL(__blk_should_fake_timeout);
 
 static int __init fail_io_timeout_debugfs(void)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/block/blk-wbt.c
+++ linux-xilinx-zynqmp-5.4.0/block/blk-wbt.c
@@ -77,7 +77,8 @@
 
 static inline bool rwb_enabled(struct rq_wb *rwb)
 {
-	return rwb && rwb->wb_normal != 0;
+	return rwb && rwb->enable_state != WBT_STATE_OFF_DEFAULT &&
+		      rwb->wb_normal != 0;
 }
 
 static void wb_timestamp(struct rq_wb *rwb, unsigned long *var)
@@ -644,9 +645,13 @@
 void wbt_enable_default(struct request_queue *q)
 {
 	struct rq_qos *rqos = wbt_rq_qos(q);
+
 	/* Throttling already enabled? */
-	if (rqos)
+	if (rqos) {
+		if (RQWB(rqos)->enable_state == WBT_STATE_OFF_DEFAULT)
+			RQWB(rqos)->enable_state = WBT_STATE_ON_DEFAULT;
 		return;
+	}
 
 	/* Queue not registered? Maybe shutting down... */
 	if (!blk_queue_registered(q))
@@ -710,7 +715,7 @@
 	rwb = RQWB(rqos);
 	if (rwb->enable_state == WBT_STATE_ON_DEFAULT) {
 		blk_stat_deactivate(rwb->cb);
-		rwb->wb_normal = 0;
+		rwb->enable_state = WBT_STATE_OFF_DEFAULT;
 	}
 }
 EXPORT_SYMBOL_GPL(wbt_disable_default);
--- linux-xilinx-zynqmp-5.4.0.orig/block/blk-wbt.h
+++ linux-xilinx-zynqmp-5.4.0/block/blk-wbt.h
@@ -34,6 +34,7 @@
 enum {
 	WBT_STATE_ON_DEFAULT	= 1,
 	WBT_STATE_ON_MANUAL	= 2,
+	WBT_STATE_OFF_DEFAULT
 };
 
 struct rq_wb {
--- linux-xilinx-zynqmp-5.4.0.orig/block/blk-zoned.c
+++ linux-xilinx-zynqmp-5.4.0/block/blk-zoned.c
@@ -202,32 +202,14 @@
 }
 EXPORT_SYMBOL_GPL(blkdev_report_zones);
 
-/*
- * Special case of zone reset operation to reset all zones in one command,
- * useful for applications like mkfs.
- */
-static int __blkdev_reset_all_zones(struct block_device *bdev, gfp_t gfp_mask)
-{
-	struct bio *bio = bio_alloc(gfp_mask, 0);
-	int ret;
-
-	/* across the zones operations, don't need any sectors */
-	bio_set_dev(bio, bdev);
-	bio_set_op_attrs(bio, REQ_OP_ZONE_RESET_ALL, 0);
-
-	ret = submit_bio_wait(bio);
-	bio_put(bio);
-
-	return ret;
-}
-
 static inline bool blkdev_allow_reset_all_zones(struct block_device *bdev,
+						sector_t sector,
 						sector_t nr_sectors)
 {
 	if (!blk_queue_zone_resetall(bdev_get_queue(bdev)))
 		return false;
 
-	if (nr_sectors != part_nr_sects_read(bdev->bd_part))
+	if (sector || nr_sectors != part_nr_sects_read(bdev->bd_part))
 		return false;
 	/*
 	 * REQ_OP_ZONE_RESET_ALL can be executed only if the block device is
@@ -271,9 +253,6 @@
 		/* Out of range */
 		return -EINVAL;
 
-	if (blkdev_allow_reset_all_zones(bdev, nr_sectors))
-		return  __blkdev_reset_all_zones(bdev, gfp_mask);
-
 	/* Check alignment (handle eventual smaller last zone) */
 	zone_sectors = blk_queue_zone_sectors(q);
 	if (sector & (zone_sectors - 1))
@@ -285,17 +264,24 @@
 
 	blk_start_plug(&plug);
 	while (sector < end_sector) {
-
 		bio = blk_next_bio(bio, 0, gfp_mask);
-		bio->bi_iter.bi_sector = sector;
 		bio_set_dev(bio, bdev);
-		bio_set_op_attrs(bio, REQ_OP_ZONE_RESET, 0);
 
+		/*
+		 * Special case for the zone reset operation that reset all
+		 * zones, this is useful for applications like mkfs.
+		 */
+		if (blkdev_allow_reset_all_zones(bdev, sector, nr_sectors)) {
+			bio->bi_opf = REQ_OP_ZONE_RESET_ALL;
+			break;
+		}
+
+		bio->bi_opf = REQ_OP_ZONE_RESET;
+		bio->bi_iter.bi_sector = sector;
 		sector += zone_sectors;
 
 		/* This may take a while, so be nice to others */
 		cond_resched();
-
 	}
 
 	ret = submit_bio_wait(bio);
@@ -330,9 +316,6 @@
 	if (!blk_queue_is_zoned(q))
 		return -ENOTTY;
 
-	if (!capable(CAP_SYS_ADMIN))
-		return -EACCES;
-
 	if (copy_from_user(&rep, argp, sizeof(struct blk_zone_report)))
 		return -EFAULT;
 
@@ -388,9 +371,6 @@
 	if (!blk_queue_is_zoned(q))
 		return -ENOTTY;
 
-	if (!capable(CAP_SYS_ADMIN))
-		return -EACCES;
-
 	if (!(mode & FMODE_WRITE))
 		return -EBADF;
 
--- linux-xilinx-zynqmp-5.4.0.orig/block/blk.h
+++ linux-xilinx-zynqmp-5.4.0/block/blk.h
@@ -30,6 +30,7 @@
 	 * at the same time
 	 */
 	struct request		*orig_rq;
+	struct lock_class_key	key;
 	spinlock_t		mq_flush_lock;
 };
 
@@ -121,6 +122,7 @@
 #ifdef CONFIG_BLK_DEV_INTEGRITY
 void blk_flush_integrity(void);
 bool __bio_integrity_endio(struct bio *);
+void bio_integrity_free(struct bio *bio);
 static inline bool bio_integrity_endio(struct bio *bio)
 {
 	if (bio_integrity(bio))
@@ -166,6 +168,9 @@
 {
 	return true;
 }
+static inline void bio_integrity_free(struct bio *bio)
+{
+}
 #endif /* CONFIG_BLK_DEV_INTEGRITY */
 
 unsigned long blk_rq_timeout(unsigned long timeout);
@@ -209,17 +214,9 @@
 
 struct hd_struct *__disk_get_part(struct gendisk *disk, int partno);
 
-#ifdef CONFIG_FAIL_IO_TIMEOUT
-int blk_should_fake_timeout(struct request_queue *);
 ssize_t part_timeout_show(struct device *, struct device_attribute *, char *);
 ssize_t part_timeout_store(struct device *, struct device_attribute *,
 				const char *, size_t);
-#else
-static inline int blk_should_fake_timeout(struct request_queue *q)
-{
-	return 0;
-}
-#endif
 
 void __blk_queue_split(struct request_queue *q, struct bio **bio,
 		unsigned int *nr_segs);
--- linux-xilinx-zynqmp-5.4.0.orig/block/bsg-lib.c
+++ linux-xilinx-zynqmp-5.4.0/block/bsg-lib.c
@@ -181,9 +181,12 @@
 void bsg_job_done(struct bsg_job *job, int result,
 		  unsigned int reply_payload_rcv_len)
 {
+	struct request *rq = blk_mq_rq_from_pdu(job);
+
 	job->result = result;
 	job->reply_payload_rcv_len = reply_payload_rcv_len;
-	blk_mq_complete_request(blk_mq_rq_from_pdu(job));
+	if (likely(!blk_should_fake_timeout(rq->q)))
+		blk_mq_complete_request(rq);
 }
 EXPORT_SYMBOL_GPL(bsg_job_done);
 
@@ -266,7 +269,7 @@
 	struct request *req = bd->rq;
 	struct bsg_set *bset =
 		container_of(q->tag_set, struct bsg_set, tag_set);
-	int sts = BLK_STS_IOERR;
+	blk_status_t sts = BLK_STS_IOERR;
 	int ret;
 
 	blk_mq_start_request(req);
--- linux-xilinx-zynqmp-5.4.0.orig/block/bsg.c
+++ linux-xilinx-zynqmp-5.4.0/block/bsg.c
@@ -157,8 +157,10 @@
 		return PTR_ERR(rq);
 
 	ret = q->bsg_dev.ops->fill_hdr(rq, &hdr, mode);
-	if (ret)
+	if (ret) {
+		blk_put_request(rq);
 		return ret;
+	}
 
 	rq->timeout = msecs_to_jiffies(hdr.timeout);
 	if (!rq->timeout)
@@ -369,10 +371,13 @@
 	case SG_GET_RESERVED_SIZE:
 	case SG_SET_RESERVED_SIZE:
 	case SG_EMULATED_HOST:
-	case SCSI_IOCTL_SEND_COMMAND:
 		return scsi_cmd_ioctl(bd->queue, NULL, file->f_mode, cmd, uarg);
 	case SG_IO:
 		return bsg_sg_io(bd->queue, file->f_mode, uarg);
+	case SCSI_IOCTL_SEND_COMMAND:
+		pr_warn_ratelimited("%s: calling unsupported SCSI_IOCTL_SEND_COMMAND\n",
+				current->comm);
+		return -EINVAL;
 	default:
 		return -ENOTTY;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/block/compat_ioctl.c
+++ linux-xilinx-zynqmp-5.4.0/block/compat_ioctl.c
@@ -6,6 +6,7 @@
 #include <linux/compat.h>
 #include <linux/elevator.h>
 #include <linux/hdreg.h>
+#include <linux/pr.h>
 #include <linux/slab.h>
 #include <linux/syscalls.h>
 #include <linux/types.h>
@@ -354,6 +355,10 @@
 	 * but we call blkdev_ioctl, which gets the lock for us
 	 */
 	case BLKRRPART:
+	case BLKREPORTZONE:
+	case BLKRESETZONE:
+	case BLKGETZONESZ:
+	case BLKGETNRZONES:
 		return blkdev_ioctl(bdev, mode, cmd,
 				(unsigned long)compat_ptr(arg));
 	case BLKBSZSET_32:
@@ -388,7 +393,7 @@
 		return 0;
 	case BLKGETSIZE:
 		size = i_size_read(bdev->bd_inode);
-		if ((size >> 9) > ~0UL)
+		if ((size >> 9) > ~(compat_ulong_t)0)
 			return -EFBIG;
 		return compat_put_ulong(arg, size >> 9);
 
@@ -401,6 +406,14 @@
 	case BLKTRACETEARDOWN: /* compatible */
 		ret = blk_trace_ioctl(bdev, cmd, compat_ptr(arg));
 		return ret;
+	case IOC_PR_REGISTER:
+	case IOC_PR_RESERVE:
+	case IOC_PR_RELEASE:
+	case IOC_PR_PREEMPT:
+	case IOC_PR_PREEMPT_ABORT:
+	case IOC_PR_CLEAR:
+		return blkdev_ioctl(bdev, mode, cmd,
+				(unsigned long)compat_ptr(arg));
 	default:
 		if (disk->fops->compat_ioctl)
 			ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg);
--- linux-xilinx-zynqmp-5.4.0.orig/block/elevator.c
+++ linux-xilinx-zynqmp-5.4.0/block/elevator.c
@@ -337,6 +337,9 @@
 	__rq = elv_rqhash_find(q, bio->bi_iter.bi_sector);
 	if (__rq && elv_bio_merge_ok(__rq, bio)) {
 		*req = __rq;
+
+		if (blk_discard_mergable(__rq))
+			return ELEVATOR_DISCARD_MERGE;
 		return ELEVATOR_BACK_MERGE;
 	}
 
@@ -522,8 +525,6 @@
 		kobject_del(&e->kobj);
 
 		e->registered = 0;
-		/* Re-enable throttling in case elevator disabled it */
-		wbt_enable_default(q);
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/block/genhd.c
+++ linux-xilinx-zynqmp-5.4.0/block/genhd.c
@@ -222,14 +222,17 @@
 		part = rcu_dereference(ptbl->part[piter->idx]);
 		if (!part)
 			continue;
+		get_device(part_to_dev(part));
+		piter->part = part;
 		if (!part_nr_sects_read(part) &&
 		    !(piter->flags & DISK_PITER_INCL_EMPTY) &&
 		    !(piter->flags & DISK_PITER_INCL_EMPTY_PART0 &&
-		      piter->idx == 0))
+		      piter->idx == 0)) {
+			put_device(part_to_dev(part));
+			piter->part = NULL;
 			continue;
+		}
 
-		get_device(part_to_dev(part));
-		piter->part = part;
 		piter->idx += inc;
 		break;
 	}
@@ -634,10 +637,8 @@
 	disk->part0.holder_dir = kobject_create_and_add("holders", &ddev->kobj);
 	disk->slave_dir = kobject_create_and_add("slaves", &ddev->kobj);
 
-	if (disk->flags & GENHD_FL_HIDDEN) {
-		dev_set_uevent_suppress(ddev, 0);
+	if (disk->flags & GENHD_FL_HIDDEN)
 		return;
-	}
 
 	/* No minors to use for partitions */
 	if (!disk_part_scan_enabled(disk))
--- linux-xilinx-zynqmp-5.4.0.orig/block/ioctl.c
+++ linux-xilinx-zynqmp-5.4.0/block/ioctl.c
@@ -19,7 +19,7 @@
 	struct blkpg_ioctl_arg a;
 	struct blkpg_partition p;
 	struct disk_part_iter piter;
-	long long start, length;
+	sector_t start, length;
 	int partno;
 
 	if (!capable(CAP_SYS_ADMIN))
@@ -34,6 +34,13 @@
 	partno = p.pno;
 	if (partno <= 0)
 		return -EINVAL;
+	if (a.op != BLKPG_DEL_PARTITION) {
+		if (p.start < 0 || p.length <= 0 || p.start + p.length < 0)
+			return -EINVAL;
+		/* Check that the partition is aligned to the block size */
+		if (!IS_ALIGNED(p.start | p.length, bdev_logical_block_size(bdev)))
+			return -EINVAL;
+	}
 	switch (a.op) {
 		case BLKPG_ADD_PARTITION:
 			start = p.start >> 9;
@@ -46,9 +53,6 @@
 				    || pstart < 0 || plength < 0 || partno > 65535)
 					return -EINVAL;
 			}
-			/* check if partition is aligned to blocksize */
-			if (p.start & (bdev_logical_block_size(bdev) - 1))
-				return -EINVAL;
 
 			mutex_lock(&bdev->bd_mutex);
 
--- linux-xilinx-zynqmp-5.4.0.orig/block/ioprio.c
+++ linux-xilinx-zynqmp-5.4.0/block/ioprio.c
@@ -207,6 +207,7 @@
 				pgrp = task_pgrp(current);
 			else
 				pgrp = find_vpid(who);
+			read_lock(&tasklist_lock);
 			do_each_pid_thread(pgrp, PIDTYPE_PGID, p) {
 				tmpio = get_task_ioprio(p);
 				if (tmpio < 0)
@@ -216,6 +217,8 @@
 				else
 					ret = ioprio_best(ret, tmpio);
 			} while_each_pid_thread(pgrp, PIDTYPE_PGID, p);
+			read_unlock(&tasklist_lock);
+
 			break;
 		case IOPRIO_WHO_USER:
 			uid = make_kuid(current_user_ns(), who);
--- linux-xilinx-zynqmp-5.4.0.orig/block/kyber-iosched.c
+++ linux-xilinx-zynqmp-5.4.0/block/kyber-iosched.c
@@ -562,11 +562,12 @@
 	}
 }
 
-static bool kyber_bio_merge(struct blk_mq_hw_ctx *hctx, struct bio *bio,
+static bool kyber_bio_merge(struct request_queue *q, struct bio *bio,
 		unsigned int nr_segs)
 {
+	struct blk_mq_ctx *ctx = blk_mq_get_ctx(q);
+	struct blk_mq_hw_ctx *hctx = blk_mq_map_queue(q, bio->bi_opf, ctx);
 	struct kyber_hctx_data *khd = hctx->sched_data;
-	struct blk_mq_ctx *ctx = blk_mq_get_ctx(hctx->queue);
 	struct kyber_ctx_queue *kcq = &khd->kcqs[ctx->index_hw[hctx->type]];
 	unsigned int sched_domain = kyber_sched_domain(bio->bi_opf);
 	struct list_head *rq_list = &kcq->rq_list[sched_domain];
--- linux-xilinx-zynqmp-5.4.0.orig/block/mq-deadline.c
+++ linux-xilinx-zynqmp-5.4.0/block/mq-deadline.c
@@ -452,6 +452,8 @@
 
 		if (elv_bio_merge_ok(__rq, bio)) {
 			*rq = __rq;
+			if (blk_discard_mergable(__rq))
+				return ELEVATOR_DISCARD_MERGE;
 			return ELEVATOR_FRONT_MERGE;
 		}
 	}
@@ -459,10 +461,9 @@
 	return ELEVATOR_NO_MERGE;
 }
 
-static bool dd_bio_merge(struct blk_mq_hw_ctx *hctx, struct bio *bio,
+static bool dd_bio_merge(struct request_queue *q, struct bio *bio,
 		unsigned int nr_segs)
 {
-	struct request_queue *q = hctx->queue;
 	struct deadline_data *dd = q->elevator->elevator_data;
 	struct request *free = NULL;
 	bool ret;
--- linux-xilinx-zynqmp-5.4.0.orig/block/opal_proto.h
+++ linux-xilinx-zynqmp-5.4.0/block/opal_proto.h
@@ -65,6 +65,7 @@
 #define SHORT_ATOM_BYTE  0xBF
 #define MEDIUM_ATOM_BYTE 0xDF
 #define LONG_ATOM_BYTE   0xE3
+#define EMPTY_ATOM_BYTE  0xFF
 
 #define OPAL_INVAL_PARAM 12
 #define OPAL_MANUFACTURED_INACTIVE 0x08
--- linux-xilinx-zynqmp-5.4.0.orig/block/partition-generic.c
+++ linux-xilinx-zynqmp-5.4.0/block/partition-generic.c
@@ -272,6 +272,7 @@
 	struct disk_part_tbl *ptbl =
 		rcu_dereference_protected(disk->part_tbl, 1);
 	struct hd_struct *part;
+	struct block_device *bdev;
 
 	if (partno >= ptbl->len)
 		return;
@@ -292,6 +293,12 @@
 	 * "in-use" until we really free the gendisk.
 	 */
 	blk_invalidate_devt(part_devt(part));
+
+	bdev = bdget(part_devt(part));
+	if (bdev) {
+		remove_inode_hash(bdev->bd_inode);
+		bdput(bdev);
+	}
 	hd_struct_kill(part);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/block/partitions/amiga.c
+++ linux-xilinx-zynqmp-5.4.0/block/partitions/amiga.c
@@ -11,11 +11,19 @@
 #define pr_fmt(fmt) fmt
 
 #include <linux/types.h>
+#include <linux/mm_types.h>
+#include <linux/overflow.h>
 #include <linux/affs_hardblocks.h>
 
 #include "check.h"
 #include "amiga.h"
 
+/* magic offsets in partition DosEnvVec */
+#define NR_HD	3
+#define NR_SECT	5
+#define LO_CYL	9
+#define HI_CYL	10
+
 static __inline__ u32
 checksum_block(__be32 *m, int size)
 {
@@ -32,8 +40,12 @@
 	unsigned char *data;
 	struct RigidDiskBlock *rdb;
 	struct PartitionBlock *pb;
-	int start_sect, nr_sects, blk, part, res = 0;
-	int blksize = 1;	/* Multiplier for disk block size */
+	u64 start_sect, nr_sects;
+	sector_t blk, end_sect;
+	u32 cylblk;		/* rdb_CylBlocks = nr_heads*sect_per_track */
+	u32 nr_hd, nr_sect, lo_cyl, hi_cyl;
+	int part, res = 0;
+	unsigned int blksize = 1;	/* Multiplier for disk block size */
 	int slot = 1;
 	char b[BDEVNAME_SIZE];
 
@@ -43,7 +55,7 @@
 		data = read_part_sector(state, blk, &sect);
 		if (!data) {
 			if (warn_no_part)
-				pr_err("Dev %s: unable to read RDB block %d\n",
+				pr_err("Dev %s: unable to read RDB block %llu\n",
 				       bdevname(state->bdev, b), blk);
 			res = -1;
 			goto rdb_done;
@@ -60,12 +72,12 @@
 		*(__be32 *)(data+0xdc) = 0;
 		if (checksum_block((__be32 *)data,
 				be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F)==0) {
-			pr_err("Trashed word at 0xd0 in block %d ignored in checksum calculation\n",
+			pr_err("Trashed word at 0xd0 in block %llu ignored in checksum calculation\n",
 			       blk);
 			break;
 		}
 
-		pr_err("Dev %s: RDB in block %d has bad checksum\n",
+		pr_err("Dev %s: RDB in block %llu has bad checksum\n",
 		       bdevname(state->bdev, b), blk);
 	}
 
@@ -81,12 +93,17 @@
 	}
 	blk = be32_to_cpu(rdb->rdb_PartitionList);
 	put_dev_sector(sect);
-	for (part = 1; blk>0 && part<=16; part++, put_dev_sector(sect)) {
-		blk *= blksize;	/* Read in terms partition table understands */
+	for (part = 1; (s32) blk>0 && part<=16; part++, put_dev_sector(sect)) {
+		/* Read in terms partition table understands */
+		if (check_mul_overflow(blk, (sector_t) blksize, &blk)) {
+			pr_err("Dev %s: overflow calculating partition block %llu! Skipping partitions %u and beyond\n",
+				bdevname(state->bdev, b), blk, part);
+			break;
+		}
 		data = read_part_sector(state, blk, &sect);
 		if (!data) {
 			if (warn_no_part)
-				pr_err("Dev %s: unable to read partition block %d\n",
+				pr_err("Dev %s: unable to read partition block %llu\n",
 				       bdevname(state->bdev, b), blk);
 			res = -1;
 			goto rdb_done;
@@ -98,19 +115,70 @@
 		if (checksum_block((__be32 *)pb, be32_to_cpu(pb->pb_SummedLongs) & 0x7F) != 0 )
 			continue;
 
-		/* Tell Kernel about it */
+		/* RDB gives us more than enough rope to hang ourselves with,
+		 * many times over (2^128 bytes if all fields max out).
+		 * Some careful checks are in order, so check for potential
+		 * overflows.
+		 * We are multiplying four 32 bit numbers to one sector_t!
+		 */
+
+		nr_hd   = be32_to_cpu(pb->pb_Environment[NR_HD]);
+		nr_sect = be32_to_cpu(pb->pb_Environment[NR_SECT]);
+
+		/* CylBlocks is total number of blocks per cylinder */
+		if (check_mul_overflow(nr_hd, nr_sect, &cylblk)) {
+			pr_err("Dev %s: heads*sects %u overflows u32, skipping partition!\n",
+				bdevname(state->bdev, b), cylblk);
+			continue;
+		}
+
+		/* check for consistency with RDB defined CylBlocks */
+		if (cylblk > be32_to_cpu(rdb->rdb_CylBlocks)) {
+			pr_warn("Dev %s: cylblk %u > rdb_CylBlocks %u!\n",
+				bdevname(state->bdev, b), cylblk,
+				be32_to_cpu(rdb->rdb_CylBlocks));
+		}
+
+		/* RDB allows for variable logical block size -
+		 * normalize to 512 byte blocks and check result.
+		 */
+
+		if (check_mul_overflow(cylblk, blksize, &cylblk)) {
+			pr_err("Dev %s: partition %u bytes per cyl. overflows u32, skipping partition!\n",
+				bdevname(state->bdev, b), part);
+			continue;
+		}
+
+		/* Calculate partition start and end. Limit of 32 bit on cylblk
+		 * guarantees no overflow occurs if LBD support is enabled.
+		 */
+
+		lo_cyl = be32_to_cpu(pb->pb_Environment[LO_CYL]);
+		start_sect = ((u64) lo_cyl * cylblk);
+
+		hi_cyl = be32_to_cpu(pb->pb_Environment[HI_CYL]);
+		nr_sects = (((u64) hi_cyl - lo_cyl + 1) * cylblk);
 
-		nr_sects = (be32_to_cpu(pb->pb_Environment[10]) + 1 -
-			    be32_to_cpu(pb->pb_Environment[9])) *
-			   be32_to_cpu(pb->pb_Environment[3]) *
-			   be32_to_cpu(pb->pb_Environment[5]) *
-			   blksize;
 		if (!nr_sects)
 			continue;
-		start_sect = be32_to_cpu(pb->pb_Environment[9]) *
-			     be32_to_cpu(pb->pb_Environment[3]) *
-			     be32_to_cpu(pb->pb_Environment[5]) *
-			     blksize;
+
+		/* Warn user if partition end overflows u32 (AmigaDOS limit) */
+
+		if ((start_sect + nr_sects) > UINT_MAX) {
+			pr_warn("Dev %s: partition %u (%llu-%llu) needs 64 bit device support!\n",
+				bdevname(state->bdev, b), part,
+				start_sect, start_sect + nr_sects);
+		}
+
+		if (check_add_overflow(start_sect, nr_sects, &end_sect)) {
+			pr_err("Dev %s: partition %u (%llu-%llu) needs LBD device support, skipping partition!\n",
+				bdevname(state->bdev, b), part,
+				start_sect, end_sect);
+			continue;
+		}
+
+		/* Tell Kernel about it */
+
 		put_partition(state,slot++,start_sect,nr_sects);
 		{
 			/* Be even more informative to aid mounting */
--- linux-xilinx-zynqmp-5.4.0.orig/block/partitions/ldm.h
+++ linux-xilinx-zynqmp-5.4.0/block/partitions/ldm.h
@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
-/**
+/*
  * ldm - Part of the Linux-NTFS project.
  *
  * Copyright (C) 2001,2002 Richard Russon <ldm@flatcap.org>
--- linux-xilinx-zynqmp-5.4.0.orig/block/partitions/mac.c
+++ linux-xilinx-zynqmp-5.4.0/block/partitions/mac.c
@@ -51,13 +51,25 @@
 	}
 	secsize = be16_to_cpu(md->block_size);
 	put_dev_sector(sect);
+
+	/*
+	 * If the "block size" is not a power of 2, things get weird - we might
+	 * end up with a partition straddling a sector boundary, so we wouldn't
+	 * be able to read a partition entry with read_part_sector().
+	 * Real block sizes are probably (?) powers of two, so just require
+	 * that.
+	 */
+	if (!is_power_of_2(secsize))
+		return -1;
 	datasize = round_down(secsize, 512);
 	data = read_part_sector(state, datasize / 512, &sect);
 	if (!data)
 		return -1;
 	partoffset = secsize % 512;
-	if (partoffset + sizeof(*part) > datasize)
+	if (partoffset + sizeof(*part) > datasize) {
+		put_dev_sector(sect);
 		return -1;
+	}
 	part = (struct mac_partition *) (data + partoffset);
 	if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC) {
 		put_dev_sector(sect);
@@ -110,8 +122,8 @@
 				int i, l;
 
 				goodness++;
-				l = strlen(part->name);
-				if (strcmp(part->name, "/") == 0)
+				l = strnlen(part->name, sizeof(part->name));
+				if (strncmp(part->name, "/", sizeof(part->name)) == 0)
 					goodness++;
 				for (i = 0; i <= l - 4; ++i) {
 					if (strncasecmp(part->name + i, "root",
--- linux-xilinx-zynqmp-5.4.0.orig/block/sed-opal.c
+++ linux-xilinx-zynqmp-5.4.0/block/sed-opal.c
@@ -88,8 +88,8 @@
 	u64 lowest_lba;
 
 	size_t pos;
-	u8 cmd[IO_BUFFER_LENGTH];
-	u8 resp[IO_BUFFER_LENGTH];
+	u8 *cmd;
+	u8 *resp;
 
 	struct parsed_resp parsed;
 	size_t prev_d_len;
@@ -893,16 +893,20 @@
 			token_length = response_parse_medium(iter, pos);
 		else if (pos[0] <= LONG_ATOM_BYTE) /* long atom */
 			token_length = response_parse_long(iter, pos);
+		else if (pos[0] == EMPTY_ATOM_BYTE) /* empty atom */
+			token_length = 1;
 		else /* TOKEN */
 			token_length = response_parse_token(iter, pos);
 
 		if (token_length < 0)
 			return token_length;
 
+		if (pos[0] != EMPTY_ATOM_BYTE)
+			num_entries++;
+
 		pos += token_length;
 		total -= token_length;
 		iter++;
-		num_entries++;
 	}
 
 	resp->num = num_entries;
@@ -2019,6 +2023,8 @@
 		return;
 
 	clean_opal_dev(dev);
+	kfree(dev->resp);
+	kfree(dev->cmd);
 	kfree(dev);
 }
 EXPORT_SYMBOL(free_opal_dev);
@@ -2031,17 +2037,39 @@
 	if (!dev)
 		return NULL;
 
+	/*
+	 * Presumably DMA-able buffers must be cache-aligned. Kmalloc makes
+	 * sure the allocated buffer is DMA-safe in that regard.
+	 */
+	dev->cmd = kmalloc(IO_BUFFER_LENGTH, GFP_KERNEL);
+	if (!dev->cmd)
+		goto err_free_dev;
+
+	dev->resp = kmalloc(IO_BUFFER_LENGTH, GFP_KERNEL);
+	if (!dev->resp)
+		goto err_free_cmd;
+
 	INIT_LIST_HEAD(&dev->unlk_lst);
 	mutex_init(&dev->dev_lock);
 	dev->data = data;
 	dev->send_recv = send_recv;
 	if (check_opal_support(dev) != 0) {
 		pr_debug("Opal is not supported on this device\n");
-		kfree(dev);
-		return NULL;
+		goto err_free_resp;
 	}
 
 	return dev;
+
+err_free_resp:
+	kfree(dev->resp);
+
+err_free_cmd:
+	kfree(dev->cmd);
+
+err_free_dev:
+	kfree(dev);
+
+	return NULL;
 }
 EXPORT_SYMBOL(init_opal_dev);
 
--- linux-xilinx-zynqmp-5.4.0.orig/certs/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/certs/Kconfig
@@ -83,4 +83,21 @@
 	  wrapper to incorporate the list into the kernel.  Each <hash> should
 	  be a string of hex digits.
 
+config SYSTEM_REVOCATION_LIST
+	bool "Provide system-wide ring of revocation certificates"
+	depends on SYSTEM_BLACKLIST_KEYRING
+	depends on PKCS7_MESSAGE_PARSER=y
+	help
+	  If set, this allows revocation certificates to be stored in the
+	  blacklist keyring and implements a hook whereby a PKCS#7 message can
+	  be checked to see if it matches such a certificate.
+
+config SYSTEM_REVOCATION_KEYS
+	string "X.509 certificates to be preloaded into the system blacklist keyring"
+	depends on SYSTEM_REVOCATION_LIST
+	help
+	  If set, this option should be the filename of a PEM-formatted file
+	  containing X.509 certificates to be included in the default blacklist
+	  keyring.
+
 endmenu
--- linux-xilinx-zynqmp-5.4.0.orig/certs/Makefile
+++ linux-xilinx-zynqmp-5.4.0/certs/Makefile
@@ -3,8 +3,9 @@
 # Makefile for the linux kernel signature checking certificates.
 #
 
-obj-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += system_keyring.o system_certificates.o
-obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist.o
+obj-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += system_keyring.o system_certificates.o common.o
+obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist.o common.o
+obj-$(CONFIG_SYSTEM_REVOCATION_LIST) += revocation_certificates.o
 ifneq ($(CONFIG_SYSTEM_BLACKLIST_HASH_LIST),"")
 obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist_hashes.o
 else
@@ -29,7 +30,7 @@
 	$(call if_changed,extract_certs,$(SYSTEM_TRUSTED_KEYS_SRCPREFIX)$(CONFIG_SYSTEM_TRUSTED_KEYS))
 endif # CONFIG_SYSTEM_TRUSTED_KEYRING
 
-clean-files := x509_certificate_list .x509.list
+clean-files := x509_certificate_list .x509.list x509_revocation_list
 
 ifeq ($(CONFIG_MODULE_SIG),y)
 ###############################################################################
@@ -46,11 +47,19 @@
 redirect_openssl	= 2>&1
 quiet_redirect_openssl	= 2>&1
 silent_redirect_openssl = 2>/dev/null
+openssl_available       = $(shell openssl help 2>/dev/null && echo yes)
 
 # We do it this way rather than having a boolean option for enabling an
 # external private key, because 'make randconfig' might enable such a
 # boolean option and we unfortunately can't make it depend on !RANDCONFIG.
 ifeq ($(CONFIG_MODULE_SIG_KEY),"certs/signing_key.pem")
+
+ifeq ($(openssl_available),yes)
+X509TEXT=$(shell openssl x509 -in "certs/signing_key.pem" -text 2>/dev/null)
+
+$(if $(findstring rsaEncryption,$(X509TEXT)),,$(shell rm -f "certs/signing_key.pem"))
+endif
+
 $(obj)/signing_key.pem: $(obj)/x509.genkey
 	@$(kecho) "###"
 	@$(kecho) "### Now generating an X.509 key pair to be used for signing modules."
@@ -104,3 +113,17 @@
 $(obj)/signing_key.x509: scripts/extract-cert $(X509_DEP) FORCE
 	$(call if_changed,extract_certs,$(MODULE_SIG_KEY_SRCPREFIX)$(CONFIG_MODULE_SIG_KEY))
 endif # CONFIG_MODULE_SIG
+
+ifeq ($(CONFIG_SYSTEM_REVOCATION_LIST),y)
+
+$(eval $(call config_filename,SYSTEM_REVOCATION_KEYS))
+
+$(obj)/revocation_certificates.o: $(obj)/x509_revocation_list
+
+quiet_cmd_extract_certs  = EXTRACT_CERTS   $(patsubst "%",%,$(2))
+      cmd_extract_certs  = scripts/extract-cert $(2) $@
+
+targets += x509_revocation_list
+$(obj)/x509_revocation_list: scripts/extract-cert $(SYSTEM_REVOCATION_KEYS_SRCPREFIX)$(SYSTEM_REVOCATION_KEYS_FILENAME) FORCE
+	$(call if_changed,extract_certs,$(SYSTEM_REVOCATION_KEYS_SRCPREFIX)$(CONFIG_SYSTEM_REVOCATION_KEYS))
+endif
--- linux-xilinx-zynqmp-5.4.0.orig/certs/blacklist.c
+++ linux-xilinx-zynqmp-5.4.0/certs/blacklist.c
@@ -16,9 +16,15 @@
 #include <linux/seq_file.h>
 #include <keys/system_keyring.h>
 #include "blacklist.h"
+#include "common.h"
 
 static struct key *blacklist_keyring;
 
+#ifdef CONFIG_SYSTEM_REVOCATION_LIST
+extern __initconst const u8 revocation_certificate_list[];
+extern __initconst const unsigned long revocation_certificate_list_size;
+#endif
+
 /*
  * The description must be a type prefix, a colon and then an even number of
  * hex digits.  The hash is kept in the description.
@@ -135,6 +141,61 @@
 }
 EXPORT_SYMBOL_GPL(is_hash_blacklisted);
 
+int is_binary_blacklisted(const u8 *hash, size_t hash_len)
+{
+	if (is_hash_blacklisted(hash, hash_len, "bin") == -EKEYREJECTED)
+		return -EPERM;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(is_binary_blacklisted);
+
+#ifdef CONFIG_SYSTEM_REVOCATION_LIST
+/**
+ * add_key_to_revocation_list - Add a revocation certificate to the blacklist
+ * @data: The data blob containing the certificate
+ * @size: The size of data blob
+ */
+int add_key_to_revocation_list(const char *data, size_t size)
+{
+	key_ref_t key;
+
+	key = key_create_or_update(make_key_ref(blacklist_keyring, true),
+				   "asymmetric",
+				   NULL,
+				   data,
+				   size,
+				   ((KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW),
+				   KEY_ALLOC_NOT_IN_QUOTA | KEY_ALLOC_BUILT_IN);
+
+	if (IS_ERR(key)) {
+		pr_err("Problem with revocation key (%ld)\n", PTR_ERR(key));
+		return PTR_ERR(key);
+	} else {
+		pr_notice("Revoked X.509 cert '%s'\n",
+			  key_ref_to_ptr(key)->description);
+	}
+
+	return 0;
+}
+
+/**
+ * is_key_on_revocation_list - Determine if the key for a PKCS#7 message is revoked
+ * @pkcs7: The PKCS#7 message to check
+ */
+int is_key_on_revocation_list(struct pkcs7_message *pkcs7)
+{
+	int ret;
+
+	ret = pkcs7_validate_trust(pkcs7, blacklist_keyring);
+
+	if (ret == 0)
+		return -EKEYREJECTED;
+
+	return -ENOKEY;
+}
+#endif
+
 /*
  * Initialise the blacklist
  */
@@ -153,7 +214,7 @@
 			      KEY_USR_VIEW | KEY_USR_READ |
 			      KEY_USR_SEARCH,
 			      KEY_ALLOC_NOT_IN_QUOTA |
-			      KEY_FLAG_KEEP,
+			      KEY_ALLOC_SET_KEEP,
 			      NULL, NULL);
 	if (IS_ERR(blacklist_keyring))
 		panic("Can't allocate system blacklist keyring\n");
@@ -168,3 +229,18 @@
  * Must be initialised before we try and load the keys into the keyring.
  */
 device_initcall(blacklist_init);
+
+#ifdef CONFIG_SYSTEM_REVOCATION_LIST
+/*
+ * Load the compiled-in list of revocation X.509 certificates.
+ */
+static __init int load_revocation_certificate_list(void)
+{
+	if (revocation_certificate_list_size)
+		pr_notice("Loading compiled-in revocation X.509 certificates\n");
+
+	return load_certificate_list(revocation_certificate_list, revocation_certificate_list_size,
+				     blacklist_keyring);
+}
+late_initcall(load_revocation_certificate_list);
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/certs/blacklist.h
+++ linux-xilinx-zynqmp-5.4.0/certs/blacklist.h
@@ -1,3 +1,5 @@
 #include <linux/kernel.h>
+#include <linux/errno.h>
+#include <crypto/pkcs7.h>
 
 extern const char __initconst *const blacklist_hashes[];
--- linux-xilinx-zynqmp-5.4.0.orig/certs/blacklist_hashes.c
+++ linux-xilinx-zynqmp-5.4.0/certs/blacklist_hashes.c
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 #include "blacklist.h"
 
-const char __initdata *const blacklist_hashes[] = {
+const char __initconst *const blacklist_hashes[] = {
 #include CONFIG_SYSTEM_BLACKLIST_HASH_LIST
 	, NULL
 };
--- linux-xilinx-zynqmp-5.4.0.orig/certs/common.c
+++ linux-xilinx-zynqmp-5.4.0/certs/common.c
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <linux/kernel.h>
+#include <linux/key.h>
+#include "common.h"
+
+int load_certificate_list(const u8 cert_list[],
+			  const unsigned long list_size,
+			  const struct key *keyring)
+{
+	key_ref_t key;
+	const u8 *p, *end;
+	size_t plen;
+
+	p = cert_list;
+	end = p + list_size;
+	while (p < end) {
+		/* Each cert begins with an ASN.1 SEQUENCE tag and must be more
+		 * than 256 bytes in size.
+		 */
+		if (end - p < 4)
+			goto dodgy_cert;
+		if (p[0] != 0x30 &&
+		    p[1] != 0x82)
+			goto dodgy_cert;
+		plen = (p[2] << 8) | p[3];
+		plen += 4;
+		if (plen > end - p)
+			goto dodgy_cert;
+
+		key = key_create_or_update(make_key_ref(keyring, 1),
+					   "asymmetric",
+					   NULL,
+					   p,
+					   plen,
+					   ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
+					   KEY_USR_VIEW | KEY_USR_READ),
+					   KEY_ALLOC_NOT_IN_QUOTA |
+					   KEY_ALLOC_BUILT_IN |
+					   KEY_ALLOC_BYPASS_RESTRICTION);
+		if (IS_ERR(key)) {
+			pr_err("Problem loading in-kernel X.509 certificate (%ld)\n",
+			       PTR_ERR(key));
+			WARN_ON_ONCE(1);
+		} else {
+			pr_notice("Loaded X.509 cert '%s'\n",
+				  key_ref_to_ptr(key)->description);
+			key_ref_put(key);
+		}
+		p += plen;
+	}
+
+	return 0;
+
+dodgy_cert:
+	pr_err("Problem parsing in-kernel X.509 certificate list\n");
+	return 0;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/certs/common.h
+++ linux-xilinx-zynqmp-5.4.0/certs/common.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef _CERT_COMMON_H
+#define _CERT_COMMON_H
+
+int load_certificate_list(const u8 cert_list[], const unsigned long list_size,
+			  const struct key *keyring);
+
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/certs/revocation_certificates.S
+++ linux-xilinx-zynqmp-5.4.0/certs/revocation_certificates.S
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#include <linux/export.h>
+#include <linux/init.h>
+
+	__INITRODATA
+
+	.align 8
+	.globl revocation_certificate_list
+revocation_certificate_list:
+__revocation_list_start:
+	.incbin "certs/x509_revocation_list"
+__revocation_list_end:
+
+	.align 8
+	.globl revocation_certificate_list_size
+revocation_certificate_list_size:
+#ifdef CONFIG_64BIT
+	.quad __revocation_list_end - __revocation_list_start
+#else
+	.long __revocation_list_end - __revocation_list_start
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/certs/system_keyring.c
+++ linux-xilinx-zynqmp-5.4.0/certs/system_keyring.c
@@ -15,6 +15,7 @@
 #include <keys/asymmetric-type.h>
 #include <keys/system_keyring.h>
 #include <crypto/pkcs7.h>
+#include "common.h"
 
 static struct key *builtin_trusted_keys;
 #ifdef CONFIG_SECONDARY_TRUSTED_KEYRING
@@ -136,54 +137,10 @@
  */
 static __init int load_system_certificate_list(void)
 {
-	key_ref_t key;
-	const u8 *p, *end;
-	size_t plen;
-
 	pr_notice("Loading compiled-in X.509 certificates\n");
 
-	p = system_certificate_list;
-	end = p + system_certificate_list_size;
-	while (p < end) {
-		/* Each cert begins with an ASN.1 SEQUENCE tag and must be more
-		 * than 256 bytes in size.
-		 */
-		if (end - p < 4)
-			goto dodgy_cert;
-		if (p[0] != 0x30 &&
-		    p[1] != 0x82)
-			goto dodgy_cert;
-		plen = (p[2] << 8) | p[3];
-		plen += 4;
-		if (plen > end - p)
-			goto dodgy_cert;
-
-		key = key_create_or_update(make_key_ref(builtin_trusted_keys, 1),
-					   "asymmetric",
-					   NULL,
-					   p,
-					   plen,
-					   ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
-					   KEY_USR_VIEW | KEY_USR_READ),
-					   KEY_ALLOC_NOT_IN_QUOTA |
-					   KEY_ALLOC_BUILT_IN |
-					   KEY_ALLOC_BYPASS_RESTRICTION);
-		if (IS_ERR(key)) {
-			pr_err("Problem loading in-kernel X.509 certificate (%ld)\n",
-			       PTR_ERR(key));
-		} else {
-			pr_notice("Loaded X.509 cert '%s'\n",
-				  key_ref_to_ptr(key)->description);
-			key_ref_put(key);
-		}
-		p += plen;
-	}
-
-	return 0;
-
-dodgy_cert:
-	pr_err("Problem parsing in-kernel X.509 certificate list\n");
-	return 0;
+	return load_certificate_list(system_certificate_list, system_certificate_list_size,
+				     builtin_trusted_keys);
 }
 late_initcall(load_system_certificate_list);
 
@@ -241,6 +198,12 @@
 			pr_devel("PKCS#7 platform keyring is not available\n");
 			goto error;
 		}
+
+		ret = is_key_on_revocation_list(pkcs7);
+		if (ret != -ENOKEY) {
+			pr_devel("PKCS#7 platform key is on revocation list\n");
+			goto error;
+		}
 	}
 	ret = pkcs7_validate_trust(pkcs7, trusted_keys);
 	if (ret < 0) {
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/crypto/Kconfig
@@ -242,12 +242,12 @@
 
 config CRYPTO_ECC
 	tristate
+	select CRYPTO_RNG_DEFAULT
 
 config CRYPTO_ECDH
 	tristate "ECDH algorithm"
 	select CRYPTO_ECC
 	select CRYPTO_KPP
-	select CRYPTO_RNG_DEFAULT
 	help
 	  Generic implementation of the ECDH algorithm
 
@@ -309,6 +309,7 @@
 config CRYPTO_AEGIS128_SIMD
 	bool "Support SIMD acceleration for AEGIS-128"
 	depends on CRYPTO_AEGIS128 && ((ARM || ARM64) && KERNEL_MODE_NEON)
+	depends on !ARM || CC_IS_CLANG || GCC_VERSION >= 40800
 	default y
 
 config CRYPTO_AEGIS128_AESNI_SSE2
@@ -499,10 +500,10 @@
 	  encryption.
 
 	  This driver implements a crypto API template that can be
-	  instantiated either as a skcipher or as a aead (depending on the
+	  instantiated either as an skcipher or as an AEAD (depending on the
 	  type of the first template argument), and which defers encryption
 	  and decryption requests to the encapsulated cipher after applying
-	  ESSIV to the input IV. Note that in the aead case, it is assumed
+	  ESSIV to the input IV. Note that in the AEAD case, it is assumed
 	  that the keys are presented in the same format used by the authenc
 	  template, and that the IV appears at the end of the authenticated
 	  associated data (AAD) region (which is how dm-crypt uses it.)
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/Makefile
+++ linux-xilinx-zynqmp-5.4.0/crypto/Makefile
@@ -93,7 +93,7 @@
 aegis128-y := aegis128-core.o
 
 ifeq ($(ARCH),arm)
-CFLAGS_aegis128-neon-inner.o += -ffreestanding -march=armv7-a -mfloat-abi=softfp
+CFLAGS_aegis128-neon-inner.o += -ffreestanding -march=armv8-a -mfloat-abi=softfp
 CFLAGS_aegis128-neon-inner.o += -mfpu=crypto-neon-fp-armv8
 aegis128-$(CONFIG_CRYPTO_AEGIS128_SIMD) += aegis128-neon.o aegis128-neon-inner.o
 endif
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/aead.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/aead.c
@@ -40,8 +40,7 @@
 	alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
 	memcpy(alignbuffer, key, keylen);
 	ret = crypto_aead_alg(tfm)->setkey(tfm, alignbuffer, keylen);
-	memset(alignbuffer, 0, keylen);
-	kfree(buffer);
+	kzfree(buffer);
 	return ret;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/af_alg.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/af_alg.c
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/net.h>
 #include <linux/rwsem.h>
+#include <linux/sched.h>
 #include <linux/sched/signal.h>
 #include <linux/security.h>
 
@@ -128,19 +129,15 @@
 void af_alg_release_parent(struct sock *sk)
 {
 	struct alg_sock *ask = alg_sk(sk);
-	unsigned int nokey = ask->nokey_refcnt;
-	bool last = nokey && !ask->refcnt;
+	unsigned int nokey = atomic_read(&ask->nokey_refcnt);
 
 	sk = ask->parent;
 	ask = alg_sk(sk);
 
-	lock_sock(sk);
-	ask->nokey_refcnt -= nokey;
-	if (!last)
-		last = !--ask->refcnt;
-	release_sock(sk);
+	if (nokey)
+		atomic_dec(&ask->nokey_refcnt);
 
-	if (last)
+	if (atomic_dec_and_test(&ask->refcnt))
 		sock_put(sk);
 }
 EXPORT_SYMBOL_GPL(af_alg_release_parent);
@@ -150,7 +147,7 @@
 	const u32 allowed = CRYPTO_ALG_KERN_DRIVER_ONLY;
 	struct sock *sk = sock->sk;
 	struct alg_sock *ask = alg_sk(sk);
-	struct sockaddr_alg *sa = (void *)uaddr;
+	struct sockaddr_alg_new *sa = (void *)uaddr;
 	const struct af_alg_type *type;
 	void *private;
 	int err;
@@ -158,7 +155,11 @@
 	if (sock->state == SS_CONNECTED)
 		return -EINVAL;
 
-	if (addr_len < sizeof(*sa))
+	BUILD_BUG_ON(offsetof(struct sockaddr_alg_new, salg_name) !=
+		     offsetof(struct sockaddr_alg, salg_name));
+	BUILD_BUG_ON(offsetof(struct sockaddr_alg, salg_name) != sizeof(*sa));
+
+	if (addr_len < sizeof(*sa) + 1)
 		return -EINVAL;
 
 	/* If caller uses non-allowed flag, return error. */
@@ -166,7 +167,7 @@
 		return -EINVAL;
 
 	sa->salg_type[sizeof(sa->salg_type) - 1] = 0;
-	sa->salg_name[sizeof(sa->salg_name) + addr_len - sizeof(*sa) - 1] = 0;
+	sa->salg_name[addr_len - sizeof(*sa) - 1] = 0;
 
 	type = alg_get_type(sa->salg_type);
 	if (IS_ERR(type) && PTR_ERR(type) == -ENOENT) {
@@ -185,7 +186,7 @@
 
 	err = -EBUSY;
 	lock_sock(sk);
-	if (ask->refcnt | ask->nokey_refcnt)
+	if (atomic_read(&ask->refcnt))
 		goto unlock;
 
 	swap(ask->type, type);
@@ -234,7 +235,7 @@
 	int err = -EBUSY;
 
 	lock_sock(sk);
-	if (ask->refcnt)
+	if (atomic_read(&ask->refcnt) != atomic_read(&ask->nokey_refcnt))
 		goto unlock;
 
 	type = ask->type;
@@ -258,6 +259,13 @@
 		if (!type->setauthsize)
 			goto unlock;
 		err = type->setauthsize(ask->private, optlen);
+		break;
+	case ALG_SET_KEY_TYPE:
+		if (sock->state == SS_CONNECTED)
+			goto unlock;
+		if (!type->setkeytype)
+			goto unlock;
+		err = type->setkeytype(ask->private, optval, optlen);
 	}
 
 unlock:
@@ -299,12 +307,14 @@
 	if (err)
 		goto unlock;
 
-	if (nokey || !ask->refcnt++)
+	if (atomic_inc_return_relaxed(&ask->refcnt) == 1)
 		sock_hold(sk);
-	ask->nokey_refcnt += nokey;
+	if (nokey) {
+		atomic_inc(&ask->nokey_refcnt);
+		atomic_set(&alg_sk(sk2)->nokey_refcnt, 1);
+	}
 	alg_sk(sk2)->parent = sk;
 	alg_sk(sk2)->type = type;
-	alg_sk(sk2)->nokey_refcnt = nokey;
 
 	newsock->ops = type->ops;
 	newsock->state = SS_CONNECTED;
@@ -637,6 +647,7 @@
 
 	if (!ctx->used)
 		ctx->merge = 0;
+	ctx->init = ctx->more;
 }
 EXPORT_SYMBOL_GPL(af_alg_pull_tsgl);
 
@@ -736,9 +747,10 @@
  *
  * @sk socket of connection to user space
  * @flags If MSG_DONTWAIT is set, then only report if function would sleep
+ * @min Set to minimum request size if partial requests are allowed.
  * @return 0 when writable memory is available, < 0 upon error
  */
-int af_alg_wait_for_data(struct sock *sk, unsigned flags)
+int af_alg_wait_for_data(struct sock *sk, unsigned flags, unsigned min)
 {
 	DEFINE_WAIT_FUNC(wait, woken_wake_function);
 	struct alg_sock *ask = alg_sk(sk);
@@ -756,7 +768,9 @@
 		if (signal_pending(current))
 			break;
 		timeout = MAX_SCHEDULE_TIMEOUT;
-		if (sk_wait_event(sk, &timeout, (ctx->used || !ctx->more),
+		if (sk_wait_event(sk, &timeout,
+				  ctx->init && (!ctx->more ||
+						(min && ctx->used >= min)),
 				  &wait)) {
 			err = 0;
 			break;
@@ -845,10 +859,23 @@
 	}
 
 	lock_sock(sk);
-	if (!ctx->more && ctx->used) {
-		err = -EINVAL;
-		goto unlock;
+	if (ctx->write) {
+		release_sock(sk);
+		return -EBUSY;
+	}
+	ctx->write = true;
+
+	if (ctx->init && !ctx->more) {
+		if (ctx->used) {
+			err = -EINVAL;
+			goto unlock;
+		}
+
+		pr_info_once(
+			"%s sent an empty control message without MSG_MORE.\n",
+			current->comm);
 	}
+	ctx->init = true;
 
 	if (init) {
 		ctx->enc = enc;
@@ -945,6 +972,7 @@
 
 unlock:
 	af_alg_data_wakeup(sk);
+	ctx->write = false;
 	release_sock(sk);
 
 	return copied ?: err;
@@ -1015,9 +1043,13 @@
 void af_alg_free_resources(struct af_alg_async_req *areq)
 {
 	struct sock *sk = areq->sk;
+	struct af_alg_ctx *ctx;
 
 	af_alg_free_areq_sgls(areq);
 	sock_kfree_s(sk, areq, areq->areqlen);
+
+	ctx = alg_sk(sk)->private;
+	ctx->inflight = false;
 }
 EXPORT_SYMBOL_GPL(af_alg_free_resources);
 
@@ -1043,7 +1075,7 @@
 	af_alg_free_resources(areq);
 	sock_put(sk);
 
-	iocb->ki_complete(iocb, err ? err : resultlen, 0);
+	iocb->ki_complete(iocb, err ? err : (int)resultlen, 0);
 }
 EXPORT_SYMBOL_GPL(af_alg_async_cb);
 
@@ -1081,11 +1113,19 @@
 struct af_alg_async_req *af_alg_alloc_areq(struct sock *sk,
 					   unsigned int areqlen)
 {
-	struct af_alg_async_req *areq = sock_kmalloc(sk, areqlen, GFP_KERNEL);
+	struct af_alg_ctx *ctx = alg_sk(sk)->private;
+	struct af_alg_async_req *areq;
 
+	/* Only one AIO request can be in flight. */
+	if (ctx->inflight)
+		return ERR_PTR(-EBUSY);
+
+	areq = sock_kmalloc(sk, areqlen, GFP_KERNEL);
 	if (unlikely(!areq))
 		return ERR_PTR(-ENOMEM);
 
+	ctx->inflight = true;
+
 	areq->areqlen = areqlen;
 	areq->sk = sk;
 	areq->last_rsgl = NULL;
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/akcipher.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/akcipher.c
@@ -119,6 +119,12 @@
 	return -ENOSYS;
 }
 
+static int akcipher_default_set_key(struct crypto_akcipher *tfm,
+				     const void *key, unsigned int keylen)
+{
+	return -ENOSYS;
+}
+
 int crypto_register_akcipher(struct akcipher_alg *alg)
 {
 	struct crypto_alg *base = &alg->base;
@@ -131,6 +137,8 @@
 		alg->encrypt = akcipher_default_op;
 	if (!alg->decrypt)
 		alg->decrypt = akcipher_default_op;
+	if (!alg->set_priv_key)
+		alg->set_priv_key = akcipher_default_set_key;
 
 	akcipher_prepare_alg(alg);
 	return crypto_register_alg(base);
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/algapi.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/algapi.c
@@ -257,6 +257,7 @@
 	struct crypto_alg *alg;
 	struct crypto_alg *q;
 	LIST_HEAD(list);
+	bool best;
 
 	down_write(&crypto_alg_sem);
 	list_for_each_entry(q, &crypto_alg_list, cra_list) {
@@ -280,6 +281,21 @@
 
 	alg->cra_flags |= CRYPTO_ALG_TESTED;
 
+	/* Only satisfy larval waiters if we are the best. */
+	best = true;
+	list_for_each_entry(q, &crypto_alg_list, cra_list) {
+		if (crypto_is_moribund(q) || !crypto_is_larval(q))
+			continue;
+
+		if (strcmp(alg->cra_name, q->cra_name))
+			continue;
+
+		if (q->cra_priority > alg->cra_priority) {
+			best = false;
+			break;
+		}
+	}
+
 	list_for_each_entry(q, &crypto_alg_list, cra_list) {
 		if (q == alg)
 			continue;
@@ -303,10 +319,12 @@
 				continue;
 			if ((q->cra_flags ^ alg->cra_flags) & larval->mask)
 				continue;
-			if (!crypto_mod_get(alg))
-				continue;
 
-			larval->adult = alg;
+			if (best && crypto_mod_get(alg))
+				larval->adult = alg;
+			else
+				larval->adult = ERR_PTR(-EAGAIN);
+
 			continue;
 		}
 
@@ -356,7 +374,7 @@
 	err = wait_for_completion_killable(&larval->completion);
 	WARN_ON(err);
 	if (!err)
-		crypto_probing_notify(CRYPTO_MSG_ALG_LOADED, larval);
+		crypto_notify(CRYPTO_MSG_ALG_LOADED, larval);
 
 out:
 	crypto_larval_kill(&larval->alg);
@@ -669,11 +687,9 @@
 
 void crypto_drop_spawn(struct crypto_spawn *spawn)
 {
-	if (!spawn->alg)
-		return;
-
 	down_write(&crypto_alg_sem);
-	list_del(&spawn->list);
+	if (spawn->alg)
+		list_del(&spawn->list);
 	up_write(&crypto_alg_sem);
 }
 EXPORT_SYMBOL_GPL(crypto_drop_spawn);
@@ -681,22 +697,16 @@
 static struct crypto_alg *crypto_spawn_alg(struct crypto_spawn *spawn)
 {
 	struct crypto_alg *alg;
-	struct crypto_alg *alg2;
 
 	down_read(&crypto_alg_sem);
 	alg = spawn->alg;
-	alg2 = alg;
-	if (alg2)
-		alg2 = crypto_mod_get(alg2);
-	up_read(&crypto_alg_sem);
-
-	if (!alg2) {
-		if (alg)
-			crypto_shoot_alg(alg);
-		return ERR_PTR(-EAGAIN);
+	if (alg && !crypto_mod_get(alg)) {
+		alg->cra_flags |= CRYPTO_ALG_DYING;
+		alg = NULL;
 	}
+	up_read(&crypto_alg_sem);
 
-	return alg;
+	return alg ?: ERR_PTR(-EAGAIN);
 }
 
 struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn, u32 type,
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/algboss.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/algboss.c
@@ -188,8 +188,6 @@
 	if (IS_ERR(thread))
 		goto err_put_larval;
 
-	wait_for_completion_interruptible(&larval->completion);
-
 	return NOTIFY_STOP;
 
 err_put_larval:
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/algif_aead.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/algif_aead.c
@@ -78,7 +78,7 @@
 	SYNC_SKCIPHER_REQUEST_ON_STACK(skreq, null_tfm);
 
 	skcipher_request_set_sync_tfm(skreq, null_tfm);
-	skcipher_request_set_callback(skreq, CRYPTO_TFM_REQ_MAY_BACKLOG,
+	skcipher_request_set_callback(skreq, CRYPTO_TFM_REQ_MAY_SLEEP,
 				      NULL, NULL);
 	skcipher_request_set_crypt(skreq, src, dst, len, NULL);
 
@@ -106,8 +106,8 @@
 	size_t usedpages = 0;		/* [in]  RX bufs to be used from user */
 	size_t processed = 0;		/* [in]  TX bufs to be consumed */
 
-	if (!ctx->used) {
-		err = af_alg_wait_for_data(sk, flags);
+	if (!ctx->init || ctx->more) {
+		err = af_alg_wait_for_data(sk, flags, 0);
 		if (err)
 			return err;
 	}
@@ -291,19 +291,20 @@
 		areq->outlen = outlen;
 
 		aead_request_set_callback(&areq->cra_u.aead_req,
-					  CRYPTO_TFM_REQ_MAY_BACKLOG,
+					  CRYPTO_TFM_REQ_MAY_SLEEP,
 					  af_alg_async_cb, areq);
 		err = ctx->enc ? crypto_aead_encrypt(&areq->cra_u.aead_req) :
 				 crypto_aead_decrypt(&areq->cra_u.aead_req);
 
 		/* AIO operation in progress */
-		if (err == -EINPROGRESS || err == -EBUSY)
+		if (err == -EINPROGRESS)
 			return -EIOCBQUEUED;
 
 		sock_put(sk);
 	} else {
 		/* Synchronous operation */
 		aead_request_set_callback(&areq->cra_u.aead_req,
+					  CRYPTO_TFM_REQ_MAY_SLEEP |
 					  CRYPTO_TFM_REQ_MAY_BACKLOG,
 					  crypto_req_done, &ctx->wait);
 		err = crypto_wait_req(ctx->enc ?
@@ -384,7 +385,7 @@
 	struct alg_sock *ask = alg_sk(sk);
 
 	lock_sock(sk);
-	if (ask->refcnt)
+	if (!atomic_read(&ask->nokey_refcnt))
 		goto unlock_child;
 
 	psk = ask->parent;
@@ -396,11 +397,8 @@
 	if (crypto_aead_get_flags(tfm->aead) & CRYPTO_TFM_NEED_KEY)
 		goto unlock;
 
-	if (!pask->refcnt++)
-		sock_hold(psk);
-
-	ask->refcnt = 1;
-	sock_put(psk);
+	atomic_dec(&pask->nokey_refcnt);
+	atomic_set(&ask->nokey_refcnt, 0);
 
 	err = 0;
 
@@ -561,12 +559,6 @@
 
 	INIT_LIST_HEAD(&ctx->tsgl_list);
 	ctx->len = len;
-	ctx->used = 0;
-	atomic_set(&ctx->rcvused, 0);
-	ctx->more = 0;
-	ctx->merge = 0;
-	ctx->enc = 0;
-	ctx->aead_assoclen = 0;
 	crypto_init_wait(&ctx->wait);
 
 	ask->private = ctx;
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/algif_hash.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/algif_hash.c
@@ -301,7 +301,7 @@
 	struct alg_sock *ask = alg_sk(sk);
 
 	lock_sock(sk);
-	if (ask->refcnt)
+	if (!atomic_read(&ask->nokey_refcnt))
 		goto unlock_child;
 
 	psk = ask->parent;
@@ -313,11 +313,8 @@
 	if (crypto_ahash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
 		goto unlock;
 
-	if (!pask->refcnt++)
-		sock_hold(psk);
-
-	ask->refcnt = 1;
-	sock_put(psk);
+	atomic_dec(&pask->nokey_refcnt);
+	atomic_set(&ask->nokey_refcnt, 0);
 
 	err = 0;
 
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/algif_skcipher.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/algif_skcipher.c
@@ -56,13 +56,13 @@
 	struct alg_sock *pask = alg_sk(psk);
 	struct af_alg_ctx *ctx = ask->private;
 	struct crypto_skcipher *tfm = pask->private;
-	unsigned int bs = crypto_skcipher_blocksize(tfm);
+	unsigned int bs = crypto_skcipher_chunksize(tfm);
 	struct af_alg_async_req *areq;
 	int err = 0;
 	size_t len = 0;
 
-	if (!ctx->used) {
-		err = af_alg_wait_for_data(sk, flags);
+	if (!ctx->init || (ctx->more && ctx->used < bs)) {
+		err = af_alg_wait_for_data(sk, flags, bs);
 		if (err)
 			return err;
 	}
@@ -74,14 +74,10 @@
 		return PTR_ERR(areq);
 
 	/* convert iovecs of output buffers into RX SGL */
-	err = af_alg_get_rsgl(sk, msg, flags, areq, -1, &len);
+	err = af_alg_get_rsgl(sk, msg, flags, areq, ctx->used, &len);
 	if (err)
 		goto free;
 
-	/* Process only as much RX buffers for which we have TX data */
-	if (len > ctx->used)
-		len = ctx->used;
-
 	/*
 	 * If more buffers are to be expected to be processed, process only
 	 * full block size buffers.
@@ -127,7 +123,7 @@
 			crypto_skcipher_decrypt(&areq->cra_u.skcipher_req);
 
 		/* AIO operation in progress */
-		if (err == -EINPROGRESS || err == -EBUSY)
+		if (err == -EINPROGRESS)
 			return -EIOCBQUEUED;
 
 		sock_put(sk);
@@ -215,7 +211,7 @@
 	struct alg_sock *ask = alg_sk(sk);
 
 	lock_sock(sk);
-	if (ask->refcnt)
+	if (!atomic_read(&ask->nokey_refcnt))
 		goto unlock_child;
 
 	psk = ask->parent;
@@ -227,11 +223,8 @@
 	if (crypto_skcipher_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
 		goto unlock;
 
-	if (!pask->refcnt++)
-		sock_hold(psk);
-
-	ask->refcnt = 1;
-	sock_put(psk);
+	atomic_dec(&pask->nokey_refcnt);
+	atomic_set(&ask->nokey_refcnt, 0);
 
 	err = 0;
 
@@ -316,6 +309,12 @@
 	return crypto_skcipher_setkey(private, key, keylen);
 }
 
+static int skcipher_setkeytype(void *private, const u8 *key,
+			       unsigned int keylen)
+{
+	return crypto_skcipher_setkeytype(private, key, keylen);
+}
+
 static void skcipher_sock_destruct(struct sock *sk)
 {
 	struct alg_sock *ask = alg_sk(sk);
@@ -340,6 +339,7 @@
 	ctx = sock_kmalloc(sk, len, GFP_KERNEL);
 	if (!ctx)
 		return -ENOMEM;
+	memset(ctx, 0, len);
 
 	ctx->iv = sock_kmalloc(sk, crypto_skcipher_ivsize(tfm),
 			       GFP_KERNEL);
@@ -347,16 +347,10 @@
 		sock_kfree_s(sk, ctx, len);
 		return -ENOMEM;
 	}
-
 	memset(ctx->iv, 0, crypto_skcipher_ivsize(tfm));
 
 	INIT_LIST_HEAD(&ctx->tsgl_list);
 	ctx->len = len;
-	ctx->used = 0;
-	atomic_set(&ctx->rcvused, 0);
-	ctx->more = 0;
-	ctx->merge = 0;
-	ctx->enc = 0;
 	crypto_init_wait(&ctx->wait);
 
 	ask->private = ctx;
@@ -380,6 +374,7 @@
 	.bind		=	skcipher_bind,
 	.release	=	skcipher_release,
 	.setkey		=	skcipher_setkey,
+	.setkeytype	=	skcipher_setkeytype,
 	.accept		=	skcipher_accept_parent,
 	.accept_nokey	=	skcipher_accept_parent_nokey,
 	.ops		=	&algif_skcipher_ops,
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/api.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/api.c
@@ -97,7 +97,7 @@
 	struct crypto_larval *larval = (void *)alg;
 
 	BUG_ON(!crypto_is_larval(alg));
-	if (larval->adult)
+	if (!IS_ERR_OR_NULL(larval->adult))
 		crypto_mod_put(larval->adult);
 	kfree(larval);
 }
@@ -178,6 +178,8 @@
 		alg = ERR_PTR(-ETIMEDOUT);
 	else if (!alg)
 		alg = ERR_PTR(-ENOENT);
+	else if (IS_ERR(alg))
+		;
 	else if (crypto_is_test_larval(larval) &&
 		 !(alg->cra_flags & CRYPTO_ALG_TESTED))
 		alg = ERR_PTR(-EAGAIN);
@@ -344,13 +346,12 @@
 	return len;
 }
 
-void crypto_shoot_alg(struct crypto_alg *alg)
+static void crypto_shoot_alg(struct crypto_alg *alg)
 {
 	down_write(&crypto_alg_sem);
 	alg->cra_flags |= CRYPTO_ALG_DYING;
 	up_write(&crypto_alg_sem);
 }
-EXPORT_SYMBOL_GPL(crypto_shoot_alg);
 
 struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type,
 				      u32 mask)
@@ -567,7 +568,7 @@
 {
 	struct crypto_alg *alg;
 
-	if (unlikely(!mem))
+	if (IS_ERR_OR_NULL(mem))
 		return;
 
 	alg = tfm->__crt_alg;
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/asymmetric_keys/asym_tpm.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/asymmetric_keys/asym_tpm.c
@@ -370,7 +370,7 @@
 	memcpy(cur, e, sizeof(e));
 	cur += sizeof(e);
 	/* Zero parameters to satisfy set_pub_key ABI. */
-	memset(cur, 0, SETKEY_PARAMS_SIZE);
+	memzero_explicit(cur, SETKEY_PARAMS_SIZE);
 
 	return cur - buf;
 }
@@ -486,6 +486,7 @@
 	if (ret < 0)
 		goto error_free_tfm;
 
+	ret = -ENOMEM;
 	req = akcipher_request_alloc(tfm, GFP_KERNEL);
 	if (!req)
 		goto error_free_tfm;
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/asymmetric_keys/pkcs7_verify.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/asymmetric_keys/pkcs7_verify.c
@@ -79,16 +79,16 @@
 		}
 
 		if (sinfo->msgdigest_len != sig->digest_size) {
-			pr_debug("Sig %u: Invalid digest size (%u)\n",
-				 sinfo->index, sinfo->msgdigest_len);
+			pr_warn("Sig %u: Invalid digest size (%u)\n",
+				sinfo->index, sinfo->msgdigest_len);
 			ret = -EBADMSG;
 			goto error;
 		}
 
 		if (memcmp(sig->digest, sinfo->msgdigest,
 			   sinfo->msgdigest_len) != 0) {
-			pr_debug("Sig %u: Message digest doesn't match\n",
-				 sinfo->index);
+			pr_warn("Sig %u: Message digest doesn't match\n",
+				sinfo->index);
 			ret = -EKEYREJECTED;
 			goto error;
 		}
@@ -488,7 +488,7 @@
 			       const void *data, size_t datalen)
 {
 	if (pkcs7->data) {
-		pr_debug("Data already supplied\n");
+		pr_warn("Data already supplied\n");
 		return -EINVAL;
 	}
 	pkcs7->data = data;
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/asymmetric_keys/public_key.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/asymmetric_keys/public_key.c
@@ -119,6 +119,7 @@
 	if (IS_ERR(tfm))
 		return PTR_ERR(tfm);
 
+	ret = -ENOMEM;
 	key = kmalloc(pkey->keylen + sizeof(u32) * 2 + pkey->paramlen,
 		      GFP_KERNEL);
 	if (!key)
@@ -184,6 +185,7 @@
 	if (IS_ERR(tfm))
 		return PTR_ERR(tfm);
 
+	ret = -ENOMEM;
 	req = akcipher_request_alloc(tfm, GFP_KERNEL);
 	if (!req)
 		goto error_free_tfm;
@@ -253,9 +255,10 @@
 	struct crypto_wait cwait;
 	struct crypto_akcipher *tfm;
 	struct akcipher_request *req;
-	struct scatterlist src_sg[2];
+	struct scatterlist src_sg;
 	char alg_name[CRYPTO_MAX_ALG_NAME];
-	char *key, *ptr;
+	char *buf, *ptr;
+	size_t buf_len;
 	int ret;
 
 	pr_devel("==>%s()\n", __func__);
@@ -279,28 +282,31 @@
 	if (!req)
 		goto error_free_tfm;
 
-	key = kmalloc(pkey->keylen + sizeof(u32) * 2 + pkey->paramlen,
-		      GFP_KERNEL);
-	if (!key)
+	buf_len = max_t(size_t, pkey->keylen + sizeof(u32) * 2 + pkey->paramlen,
+			sig->s_size + sig->digest_size);
+
+	buf = kmalloc(buf_len, GFP_KERNEL);
+	if (!buf)
 		goto error_free_req;
 
-	memcpy(key, pkey->key, pkey->keylen);
-	ptr = key + pkey->keylen;
+	memcpy(buf, pkey->key, pkey->keylen);
+	ptr = buf + pkey->keylen;
 	ptr = pkey_pack_u32(ptr, pkey->algo);
 	ptr = pkey_pack_u32(ptr, pkey->paramlen);
 	memcpy(ptr, pkey->params, pkey->paramlen);
 
 	if (pkey->key_is_private)
-		ret = crypto_akcipher_set_priv_key(tfm, key, pkey->keylen);
+		ret = crypto_akcipher_set_priv_key(tfm, buf, pkey->keylen);
 	else
-		ret = crypto_akcipher_set_pub_key(tfm, key, pkey->keylen);
+		ret = crypto_akcipher_set_pub_key(tfm, buf, pkey->keylen);
 	if (ret)
-		goto error_free_key;
+		goto error_free_buf;
 
-	sg_init_table(src_sg, 2);
-	sg_set_buf(&src_sg[0], sig->s, sig->s_size);
-	sg_set_buf(&src_sg[1], sig->digest, sig->digest_size);
-	akcipher_request_set_crypt(req, src_sg, NULL, sig->s_size,
+	memcpy(buf, sig->s, sig->s_size);
+	memcpy(buf + sig->s_size, sig->digest, sig->digest_size);
+
+	sg_init_one(&src_sg, buf, sig->s_size + sig->digest_size);
+	akcipher_request_set_crypt(req, &src_sg, NULL, sig->s_size,
 				   sig->digest_size);
 	crypto_init_wait(&cwait);
 	akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
@@ -308,8 +314,8 @@
 				      crypto_req_done, &cwait);
 	ret = crypto_wait_req(crypto_akcipher_verify(req), &cwait);
 
-error_free_key:
-	kfree(key);
+error_free_buf:
+	kfree(buf);
 error_free_req:
 	akcipher_request_free(req);
 error_free_tfm:
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/asymmetric_keys/verify_pefile.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/asymmetric_keys/verify_pefile.c
@@ -74,7 +74,7 @@
 		break;
 
 	default:
-		pr_debug("Unknown PEOPT magic = %04hx\n", pe32->magic);
+		pr_warn("Unknown PEOPT magic = %04hx\n", pe32->magic);
 		return -ELIBBAD;
 	}
 
@@ -95,7 +95,7 @@
 	ctx->certs_size = ddir->certs.size;
 
 	if (!ddir->certs.virtual_address || !ddir->certs.size) {
-		pr_debug("Unsigned PE binary\n");
+		pr_warn("Unsigned PE binary\n");
 		return -ENODATA;
 	}
 
@@ -127,7 +127,7 @@
 	unsigned len;
 
 	if (ctx->sig_len < sizeof(wrapper)) {
-		pr_debug("Signature wrapper too short\n");
+		pr_warn("Signature wrapper too short\n");
 		return -ELIBBAD;
 	}
 
@@ -135,19 +135,23 @@
 	pr_debug("sig wrapper = { %x, %x, %x }\n",
 		 wrapper.length, wrapper.revision, wrapper.cert_type);
 
-	/* Both pesign and sbsign round up the length of certificate table
-	 * (in optional header data directories) to 8 byte alignment.
+	/* sbsign rounds up the length of certificate table (in optional
+	 * header data directories) to 8 byte alignment.  However, the PE
+	 * specification states that while entries are 8-byte aligned, this is
+	 * not included in their length, and as a result, pesign has not
+	 * rounded up since 0.110.
 	 */
-	if (round_up(wrapper.length, 8) != ctx->sig_len) {
-		pr_debug("Signature wrapper len wrong\n");
+	if (wrapper.length > ctx->sig_len) {
+		pr_warn("Signature wrapper bigger than sig len (%x > %x)\n",
+			ctx->sig_len, wrapper.length);
 		return -ELIBBAD;
 	}
 	if (wrapper.revision != WIN_CERT_REVISION_2_0) {
-		pr_debug("Signature is not revision 2.0\n");
+		pr_warn("Signature is not revision 2.0\n");
 		return -ENOTSUPP;
 	}
 	if (wrapper.cert_type != WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
-		pr_debug("Signature certificate type is not PKCS\n");
+		pr_warn("Signature certificate type is not PKCS\n");
 		return -ENOTSUPP;
 	}
 
@@ -160,7 +164,7 @@
 	ctx->sig_offset += sizeof(wrapper);
 	ctx->sig_len -= sizeof(wrapper);
 	if (ctx->sig_len < 4) {
-		pr_debug("Signature data missing\n");
+		pr_warn("Signature data missing\n");
 		return -EKEYREJECTED;
 	}
 
@@ -194,7 +198,7 @@
 		return 0;
 	}
 not_pkcs7:
-	pr_debug("Signature data not PKCS#7\n");
+	pr_warn("Signature data not PKCS#7\n");
 	return -ELIBBAD;
 }
 
@@ -337,8 +341,8 @@
 	digest_size = crypto_shash_digestsize(tfm);
 
 	if (digest_size != ctx->digest_len) {
-		pr_debug("Digest size mismatch (%zx != %x)\n",
-			 digest_size, ctx->digest_len);
+		pr_warn("Digest size mismatch (%zx != %x)\n",
+			digest_size, ctx->digest_len);
 		ret = -EBADMSG;
 		goto error_no_desc;
 	}
@@ -369,7 +373,7 @@
 	 * PKCS#7 certificate.
 	 */
 	if (memcmp(digest, ctx->digest, ctx->digest_len) != 0) {
-		pr_debug("Digest mismatch\n");
+		pr_warn("Digest mismatch\n");
 		ret = -EKEYREJECTED;
 	} else {
 		pr_debug("The digests match!\n");
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/asymmetric_keys/x509_public_key.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/asymmetric_keys/x509_public_key.c
@@ -129,6 +129,11 @@
 	if (strcmp(cert->pub->pkey_algo, cert->sig->pkey_algo) != 0)
 		goto out;
 
+	if (cert->unsupported_sig) {
+		ret = 0;
+		goto out;
+	}
+
 	ret = public_key_verify_signature(cert->pub, cert->sig);
 	if (ret < 0) {
 		if (ret == -ENOPKG) {
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/authenc.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/authenc.c
@@ -263,7 +263,7 @@
 		dst = scatterwalk_ffwd(areq_ctx->dst, req->dst, req->assoclen);
 
 	skcipher_request_set_tfm(skreq, ctx->enc);
-	skcipher_request_set_callback(skreq, aead_request_flags(req),
+	skcipher_request_set_callback(skreq, flags,
 				      req->base.complete, req->base.data);
 	skcipher_request_set_crypt(skreq, src, dst,
 				   req->cryptlen - authsize, req->iv);
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/authencesn.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/authencesn.c
@@ -201,6 +201,9 @@
 	struct scatterlist *src, *dst;
 	int err;
 
+	if (assoclen < 8)
+		return -EINVAL;
+
 	sg_init_table(areq_ctx->src, 2);
 	src = scatterwalk_ffwd(areq_ctx->src, req->src, assoclen);
 	dst = src;
@@ -294,6 +297,9 @@
 	u32 tmp[2];
 	int err;
 
+	if (assoclen < 8)
+		return -EINVAL;
+
 	cryptlen -= authsize;
 
 	if (req->src != dst) {
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/blkcipher.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/blkcipher.c
@@ -403,6 +403,14 @@
 	return cipher->setkey(tfm, key, keylen);
 }
 
+static int setkeytype(struct crypto_tfm *tfm, const u8 *key,
+		      unsigned int keylen)
+{
+	struct blkcipher_alg *cipher = &tfm->__crt_alg->cra_blkcipher;
+
+	return cipher->setkeytype(tfm, key, keylen);
+}
+
 static int async_setkey(struct crypto_ablkcipher *tfm, const u8 *key,
 			unsigned int keylen)
 {
@@ -473,6 +481,7 @@
 	unsigned long addr;
 
 	crt->setkey = setkey;
+	crt->setkeytype = setkeytype;
 	crt->encrypt = alg->encrypt;
 	crt->decrypt = alg->decrypt;
 
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/cast6_generic.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/cast6_generic.c
@@ -154,7 +154,7 @@
 EXPORT_SYMBOL_GPL(cast6_setkey);
 
 /*forward quad round*/
-static inline void Q(u32 *block, u8 *Kr, u32 *Km)
+static inline void Q(u32 *block, const u8 *Kr, const u32 *Km)
 {
 	u32 I;
 	block[2] ^= F1(block[3], Kr[0], Km[0]);
@@ -164,7 +164,7 @@
 }
 
 /*reverse quad round*/
-static inline void QBAR(u32 *block, u8 *Kr, u32 *Km)
+static inline void QBAR(u32 *block, const u8 *Kr, const u32 *Km)
 {
 	u32 I;
 	block[3] ^= F1(block[0], Kr[3], Km[3]);
@@ -173,13 +173,14 @@
 	block[2] ^= F1(block[3], Kr[0], Km[0]);
 }
 
-void __cast6_encrypt(struct cast6_ctx *c, u8 *outbuf, const u8 *inbuf)
+void __cast6_encrypt(const void *ctx, u8 *outbuf, const u8 *inbuf)
 {
+	const struct cast6_ctx *c = ctx;
 	const __be32 *src = (const __be32 *)inbuf;
 	__be32 *dst = (__be32 *)outbuf;
 	u32 block[4];
-	u32 *Km;
-	u8 *Kr;
+	const u32 *Km;
+	const u8 *Kr;
 
 	block[0] = be32_to_cpu(src[0]);
 	block[1] = be32_to_cpu(src[1]);
@@ -211,13 +212,14 @@
 	__cast6_encrypt(crypto_tfm_ctx(tfm), outbuf, inbuf);
 }
 
-void __cast6_decrypt(struct cast6_ctx *c, u8 *outbuf, const u8 *inbuf)
+void __cast6_decrypt(const void *ctx, u8 *outbuf, const u8 *inbuf)
 {
+	const struct cast6_ctx *c = ctx;
 	const __be32 *src = (const __be32 *)inbuf;
 	__be32 *dst = (__be32 *)outbuf;
 	u32 block[4];
-	u32 *Km;
-	u8 *Kr;
+	const u32 *Km;
+	const u8 *Kr;
 
 	block[0] = be32_to_cpu(src[0]);
 	block[1] = be32_to_cpu(src[1]);
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/cipher.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/cipher.c
@@ -33,8 +33,7 @@
 	alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
 	memcpy(alignbuffer, key, keylen);
 	ret = cia->cia_setkey(tfm, alignbuffer, keylen);
-	memset(alignbuffer, 0, keylen);
-	kfree(buffer);
+	kzfree(buffer);
 	return ret;
 
 }
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/cryptd.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/cryptd.c
@@ -39,6 +39,10 @@
 };
 
 struct cryptd_queue {
+	/*
+	 * Protected by disabling BH to allow enqueueing from softinterrupt and
+	 * dequeuing from kworker (cryptd_queue_worker()).
+	 */
 	struct cryptd_cpu_queue __percpu *cpu_queue;
 };
 
@@ -125,28 +129,28 @@
 static int cryptd_enqueue_request(struct cryptd_queue *queue,
 				  struct crypto_async_request *request)
 {
-	int cpu, err;
+	int err;
 	struct cryptd_cpu_queue *cpu_queue;
 	refcount_t *refcnt;
 
-	cpu = get_cpu();
+	local_bh_disable();
 	cpu_queue = this_cpu_ptr(queue->cpu_queue);
 	err = crypto_enqueue_request(&cpu_queue->queue, request);
 
 	refcnt = crypto_tfm_ctx(request->tfm);
 
 	if (err == -ENOSPC)
-		goto out_put_cpu;
+		goto out;
 
-	queue_work_on(cpu, cryptd_wq, &cpu_queue->work);
+	queue_work_on(smp_processor_id(), cryptd_wq, &cpu_queue->work);
 
 	if (!refcount_read(refcnt))
-		goto out_put_cpu;
+		goto out;
 
 	refcount_inc(refcnt);
 
-out_put_cpu:
-	put_cpu();
+out:
+	local_bh_enable();
 
 	return err;
 }
@@ -162,15 +166,10 @@
 	cpu_queue = container_of(work, struct cryptd_cpu_queue, work);
 	/*
 	 * Only handle one request at a time to avoid hogging crypto workqueue.
-	 * preempt_disable/enable is used to prevent being preempted by
-	 * cryptd_enqueue_request(). local_bh_disable/enable is used to prevent
-	 * cryptd_enqueue_request() being accessed from software interrupts.
 	 */
 	local_bh_disable();
-	preempt_disable();
 	backlog = crypto_get_backlog(&cpu_queue->queue);
 	req = crypto_dequeue_request(&cpu_queue->queue);
-	preempt_enable();
 	local_bh_enable();
 
 	if (!req)
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/crypto_user_base.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/crypto_user_base.c
@@ -213,8 +213,10 @@
 drop_alg:
 	crypto_mod_put(alg);
 
-	if (err)
+	if (err) {
+		kfree_skb(skb);
 		return err;
+	}
 
 	return nlmsg_unicast(net->crypto_nlsk, skb, NETLINK_CB(in_skb).portid);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/crypto_user_stat.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/crypto_user_stat.c
@@ -328,8 +328,10 @@
 drop_alg:
 	crypto_mod_put(alg);
 
-	if (err)
+	if (err) {
+		kfree_skb(skb);
 		return err;
+	}
 
 	return nlmsg_unicast(net->crypto_nlsk, skb, NETLINK_CB(in_skb).portid);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/drbg.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/drbg.c
@@ -1035,17 +1035,38 @@
  ******************************************************************/
 
 static inline int __drbg_seed(struct drbg_state *drbg, struct list_head *seed,
-			      int reseed)
+			      int reseed, enum drbg_seed_state new_seed_state)
 {
 	int ret = drbg->d_ops->update(drbg, seed, reseed);
 
 	if (ret)
 		return ret;
 
-	drbg->seeded = true;
+	drbg->seeded = new_seed_state;
 	/* 10.1.1.2 / 10.1.1.3 step 5 */
 	drbg->reseed_ctr = 1;
 
+	switch (drbg->seeded) {
+	case DRBG_SEED_STATE_UNSEEDED:
+		/* Impossible, but handle it to silence compiler warnings. */
+		fallthrough;
+	case DRBG_SEED_STATE_PARTIAL:
+		/*
+		 * Require frequent reseeds until the seed source is
+		 * fully initialized.
+		 */
+		drbg->reseed_threshold = 50;
+		break;
+
+	case DRBG_SEED_STATE_FULL:
+		/*
+		 * Seed source has become fully initialized, frequent
+		 * reseeds no longer required.
+		 */
+		drbg->reseed_threshold = drbg_max_requests(drbg);
+		break;
+	}
+
 	return ret;
 }
 
@@ -1065,12 +1086,10 @@
 	return 0;
 }
 
-static void drbg_async_seed(struct work_struct *work)
+static int drbg_seed_from_random(struct drbg_state *drbg)
 {
 	struct drbg_string data;
 	LIST_HEAD(seedlist);
-	struct drbg_state *drbg = container_of(work, struct drbg_state,
-					       seed_work);
 	unsigned int entropylen = drbg_sec_strength(drbg->core->flags);
 	unsigned char entropy[32];
 	int ret;
@@ -1081,30 +1100,15 @@
 	drbg_string_fill(&data, entropy, entropylen);
 	list_add_tail(&data.list, &seedlist);
 
-	mutex_lock(&drbg->drbg_mutex);
-
 	ret = drbg_get_random_bytes(drbg, entropy, entropylen);
 	if (ret)
-		goto unlock;
+		goto out;
 
-	/* If nonblocking pool is initialized, deactivate Jitter RNG */
-	crypto_free_rng(drbg->jent);
-	drbg->jent = NULL;
-
-	/* Set seeded to false so that if __drbg_seed fails the
-	 * next generate call will trigger a reseed.
-	 */
-	drbg->seeded = false;
-
-	__drbg_seed(drbg, &seedlist, true);
-
-	if (drbg->seeded)
-		drbg->reseed_threshold = drbg_max_requests(drbg);
-
-unlock:
-	mutex_unlock(&drbg->drbg_mutex);
+	ret = __drbg_seed(drbg, &seedlist, true, DRBG_SEED_STATE_FULL);
 
+out:
 	memzero_explicit(entropy, entropylen);
+	return ret;
 }
 
 /*
@@ -1126,6 +1130,7 @@
 	unsigned int entropylen = drbg_sec_strength(drbg->core->flags);
 	struct drbg_string data1;
 	LIST_HEAD(seedlist);
+	enum drbg_seed_state new_seed_state = DRBG_SEED_STATE_FULL;
 
 	/* 9.1 / 9.2 / 9.3.1 step 3 */
 	if (pers && pers->len > (drbg_max_addtl(drbg))) {
@@ -1153,6 +1158,9 @@
 		BUG_ON((entropylen * 2) > sizeof(entropy));
 
 		/* Get seed from in-kernel /dev/urandom */
+		if (!rng_is_initialized())
+			new_seed_state = DRBG_SEED_STATE_PARTIAL;
+
 		ret = drbg_get_random_bytes(drbg, entropy, entropylen);
 		if (ret)
 			goto out;
@@ -1168,7 +1176,23 @@
 						   entropylen);
 			if (ret) {
 				pr_devel("DRBG: jent failed with %d\n", ret);
-				goto out;
+
+				/*
+				 * Do not treat the transient failure of the
+				 * Jitter RNG as an error that needs to be
+				 * reported. The combined number of the
+				 * maximum reseed threshold times the maximum
+				 * number of Jitter RNG transient errors is
+				 * less than the reseed threshold required by
+				 * SP800-90A allowing us to treat the
+				 * transient errors as such.
+				 *
+				 * However, we mandate that at least the first
+				 * seeding operation must succeed with the
+				 * Jitter RNG.
+				 */
+				if (!reseed || ret != -EAGAIN)
+					goto out;
 			}
 
 			drbg_string_fill(&data1, entropy, entropylen * 2);
@@ -1193,7 +1217,7 @@
 		memset(drbg->C, 0, drbg_statelen(drbg));
 	}
 
-	ret = __drbg_seed(drbg, &seedlist, reseed);
+	ret = __drbg_seed(drbg, &seedlist, reseed, new_seed_state);
 
 out:
 	memzero_explicit(entropy, entropylen * 2);
@@ -1294,8 +1318,10 @@
 	if (IS_ENABLED(CONFIG_CRYPTO_FIPS)) {
 		drbg->prev = kzalloc(drbg_sec_strength(drbg->core->flags),
 				     GFP_KERNEL);
-		if (!drbg->prev)
+		if (!drbg->prev) {
+			ret = -ENOMEM;
 			goto fini;
+		}
 		drbg->fips_primed = false;
 	}
 
@@ -1371,19 +1397,25 @@
 	 * here. The spec is a bit convoluted here, we make it simpler.
 	 */
 	if (drbg->reseed_threshold < drbg->reseed_ctr)
-		drbg->seeded = false;
+		drbg->seeded = DRBG_SEED_STATE_UNSEEDED;
 
-	if (drbg->pr || !drbg->seeded) {
+	if (drbg->pr || drbg->seeded == DRBG_SEED_STATE_UNSEEDED) {
 		pr_devel("DRBG: reseeding before generation (prediction "
 			 "resistance: %s, state %s)\n",
 			 drbg->pr ? "true" : "false",
-			 drbg->seeded ? "seeded" : "unseeded");
+			 (drbg->seeded ==  DRBG_SEED_STATE_FULL ?
+			  "seeded" : "unseeded"));
 		/* 9.3.1 steps 7.1 through 7.3 */
 		len = drbg_seed(drbg, addtl, true);
 		if (len)
 			goto err;
 		/* 9.3.1 step 7.4 */
 		addtl = NULL;
+	} else if (rng_is_initialized() &&
+		   drbg->seeded == DRBG_SEED_STATE_PARTIAL) {
+		len = drbg_seed_from_random(drbg);
+		if (len)
+			goto err;
 	}
 
 	if (addtl && 0 < addtl->len)
@@ -1476,51 +1508,23 @@
 	return 0;
 }
 
-static void drbg_schedule_async_seed(struct random_ready_callback *rdy)
-{
-	struct drbg_state *drbg = container_of(rdy, struct drbg_state,
-					       random_ready);
-
-	schedule_work(&drbg->seed_work);
-}
-
 static int drbg_prepare_hrng(struct drbg_state *drbg)
 {
-	int err;
-
 	/* We do not need an HRNG in test mode. */
 	if (list_empty(&drbg->test_data.list))
 		return 0;
 
-	INIT_WORK(&drbg->seed_work, drbg_async_seed);
-
-	drbg->random_ready.owner = THIS_MODULE;
-	drbg->random_ready.func = drbg_schedule_async_seed;
-
-	err = add_random_ready_callback(&drbg->random_ready);
-
-	switch (err) {
-	case 0:
-		break;
-
-	case -EALREADY:
-		err = 0;
-		/* fall through */
-
-	default:
-		drbg->random_ready.func = NULL;
-		return err;
-	}
-
 	drbg->jent = crypto_alloc_rng("jitterentropy_rng", 0, 0);
+	if (IS_ERR(drbg->jent)) {
+		const int err = PTR_ERR(drbg->jent);
 
-	/*
-	 * Require frequent reseeds until the seed source is fully
-	 * initialized.
-	 */
-	drbg->reseed_threshold = 50;
+		drbg->jent = NULL;
+		if (fips_enabled)
+			return err;
+		pr_info("DRBG: Continuing without Jitter RNG\n");
+	}
 
-	return err;
+	return 0;
 }
 
 /*
@@ -1563,7 +1567,7 @@
 	if (!drbg->core) {
 		drbg->core = &drbg_cores[coreref];
 		drbg->pr = pr;
-		drbg->seeded = false;
+		drbg->seeded = DRBG_SEED_STATE_UNSEEDED;
 		drbg->reseed_threshold = drbg_max_requests(drbg);
 
 		ret = drbg_alloc_state(drbg);
@@ -1574,14 +1578,6 @@
 		if (ret)
 			goto free_everything;
 
-		if (IS_ERR(drbg->jent)) {
-			ret = PTR_ERR(drbg->jent);
-			drbg->jent = NULL;
-			if (fips_enabled || ret != -ENOENT)
-				goto free_everything;
-			pr_info("DRBG: Continuing without Jitter RNG\n");
-		}
-
 		reseed = false;
 	}
 
@@ -1614,12 +1610,9 @@
  */
 static int drbg_uninstantiate(struct drbg_state *drbg)
 {
-	if (drbg->random_ready.func) {
-		del_random_ready_callback(&drbg->random_ready);
-		cancel_work_sync(&drbg->seed_work);
+	if (!IS_ERR_OR_NULL(drbg->jent))
 		crypto_free_rng(drbg->jent);
-		drbg->jent = NULL;
-	}
+	drbg->jent = NULL;
 
 	if (drbg->d_ops)
 		drbg->d_ops->crypto_fini(drbg);
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/ecc.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/ecc.c
@@ -1284,10 +1284,11 @@
 static inline void ecc_swap_digits(const u64 *in, u64 *out,
 				   unsigned int ndigits)
 {
+	const __be64 *src = (__force __be64 *)in;
 	int i;
 
 	for (i = 0; i < ndigits; i++)
-		out[i] = __swab64(in[ndigits - 1 - i]);
+		out[i] = be64_to_cpu(src[ndigits - 1 - i]);
 }
 
 static int __ecc_is_key_valid(const struct ecc_curve *curve,
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/ecdh.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/ecdh.c
@@ -39,7 +39,8 @@
 	struct ecdh params;
 	unsigned int ndigits;
 
-	if (crypto_ecdh_decode_key(buf, len, &params) < 0)
+	if (crypto_ecdh_decode_key(buf, len, &params) < 0 ||
+	    params.key_size > sizeof(ctx->private_key))
 		return -EINVAL;
 
 	ndigits = ecdh_supported_curve(params.curve_id);
@@ -53,12 +54,13 @@
 		return ecc_gen_privkey(ctx->curve_id, ctx->ndigits,
 				       ctx->private_key);
 
-	if (ecc_is_key_valid(ctx->curve_id, ctx->ndigits,
-			     (const u64 *)params.key, params.key_size) < 0)
-		return -EINVAL;
-
 	memcpy(ctx->private_key, params.key, params.key_size);
 
+	if (ecc_is_key_valid(ctx->curve_id, ctx->ndigits,
+			     ctx->private_key, params.key_size) < 0) {
+		memzero_explicit(ctx->private_key, params.key_size);
+		return -EINVAL;
+	}
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/ecdh_helper.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/ecdh_helper.c
@@ -67,6 +67,9 @@
 	if (secret.type != CRYPTO_KPP_SECRET_TYPE_ECDH)
 		return -EINVAL;
 
+	if (unlikely(len < secret.len))
+		return -EINVAL;
+
 	ptr = ecdh_unpack_data(&params->curve_id, ptr, sizeof(params->curve_id));
 	ptr = ecdh_unpack_data(&params->key_size, ptr, sizeof(params->key_size));
 	if (secret.len != crypto_ecdh_key_len(params))
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/ecrdsa.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/ecrdsa.c
@@ -112,15 +112,15 @@
 
 	/* Step 1: verify that 0 < r < q, 0 < s < q */
 	if (vli_is_zero(r, ndigits) ||
-	    vli_cmp(r, ctx->curve->n, ndigits) == 1 ||
+	    vli_cmp(r, ctx->curve->n, ndigits) >= 0 ||
 	    vli_is_zero(s, ndigits) ||
-	    vli_cmp(s, ctx->curve->n, ndigits) == 1)
+	    vli_cmp(s, ctx->curve->n, ndigits) >= 0)
 		return -EKEYREJECTED;
 
 	/* Step 2: calculate hash (h) of the message (passed as input) */
 	/* Step 3: calculate e = h \mod q */
 	vli_from_le64(e, digest, ndigits);
-	if (vli_cmp(e, ctx->curve->n, ndigits) == 1)
+	if (vli_cmp(e, ctx->curve->n, ndigits) >= 0)
 		vli_sub(e, e, ctx->curve->n, ndigits);
 	if (vli_is_zero(e, ndigits))
 		e[0] = 1;
@@ -136,7 +136,7 @@
 	/* Step 6: calculate point C = z_1P + z_2Q, and R = x_c \mod q */
 	ecc_point_mult_shamir(&cc, z1, &ctx->curve->g, z2, &ctx->pub_key,
 			      ctx->curve);
-	if (vli_cmp(cc.x, ctx->curve->n, ndigits) == 1)
+	if (vli_cmp(cc.x, ctx->curve->n, ndigits) >= 0)
 		vli_sub(cc.x, cc.x, ctx->curve->n, ndigits);
 
 	/* Step 7: if R == r signature is valid */
@@ -293,4 +293,5 @@
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Vitaly Chikunov <vt@altlinux.org>");
 MODULE_DESCRIPTION("EC-RDSA generic algorithm");
+MODULE_ALIAS_CRYPTO("ecrdsa");
 MODULE_ALIAS_CRYPTO("ecrdsa-generic");
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/essiv.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/essiv.c
@@ -188,8 +188,12 @@
 	struct aead_request *req = areq->data;
 	struct essiv_aead_request_ctx *rctx = aead_request_ctx(req);
 
-	if (rctx->assoc)
-		kfree(rctx->assoc);
+	if (err == -EINPROGRESS)
+		goto out;
+
+	kfree(rctx->assoc);
+
+out:
 	aead_request_complete(req, err);
 }
 
@@ -199,9 +203,14 @@
 	const struct essiv_tfm_ctx *tctx = crypto_aead_ctx(tfm);
 	struct essiv_aead_request_ctx *rctx = aead_request_ctx(req);
 	struct aead_request *subreq = &rctx->aead_req;
+	int ivsize = crypto_aead_ivsize(tfm);
+	int ssize = req->assoclen - ivsize;
 	struct scatterlist *src = req->src;
 	int err;
 
+	if (ssize < 0)
+		return -EINVAL;
+
 	crypto_cipher_encrypt_one(tctx->essiv_cipher, req->iv, req->iv);
 
 	/*
@@ -211,19 +220,12 @@
 	 */
 	rctx->assoc = NULL;
 	if (req->src == req->dst || !enc) {
-		scatterwalk_map_and_copy(req->iv, req->dst,
-					 req->assoclen - crypto_aead_ivsize(tfm),
-					 crypto_aead_ivsize(tfm), 1);
+		scatterwalk_map_and_copy(req->iv, req->dst, ssize, ivsize, 1);
 	} else {
 		u8 *iv = (u8 *)aead_request_ctx(req) + tctx->ivoffset;
-		int ivsize = crypto_aead_ivsize(tfm);
-		int ssize = req->assoclen - ivsize;
 		struct scatterlist *sg;
 		int nents;
 
-		if (ssize < 0)
-			return -EINVAL;
-
 		nents = sg_nents_for_len(req->src, ssize);
 		if (nents < 0)
 			return -EINVAL;
@@ -265,7 +267,7 @@
 	err = enc ? crypto_aead_encrypt(subreq) :
 		    crypto_aead_decrypt(subreq);
 
-	if (rctx->assoc && err != -EINPROGRESS)
+	if (rctx->assoc && err != -EINPROGRESS && err != -EBUSY)
 		kfree(rctx->assoc);
 	return err;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/hash_info.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/hash_info.c
@@ -26,7 +26,7 @@
 	[HASH_ALGO_TGR_128]	= "tgr128",
 	[HASH_ALGO_TGR_160]	= "tgr160",
 	[HASH_ALGO_TGR_192]	= "tgr192",
-	[HASH_ALGO_SM3_256]	= "sm3-256",
+	[HASH_ALGO_SM3_256]	= "sm3",
 	[HASH_ALGO_STREEBOG_256] = "streebog256",
 	[HASH_ALGO_STREEBOG_512] = "streebog512",
 };
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/internal.h
+++ linux-xilinx-zynqmp-5.4.0/crypto/internal.h
@@ -68,7 +68,6 @@
 void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list,
 			  struct crypto_alg *nalg);
 void crypto_remove_final(struct list_head *list);
-void crypto_shoot_alg(struct crypto_alg *alg);
 struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type,
 				      u32 mask);
 void *crypto_create_tfm(struct crypto_alg *alg,
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/lrw.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/lrw.c
@@ -289,7 +289,7 @@
 	crypto_free_skcipher(ctx->child);
 }
 
-static void free(struct skcipher_instance *inst)
+static void free_inst(struct skcipher_instance *inst)
 {
 	crypto_drop_skcipher(skcipher_instance_ctx(inst));
 	kfree(inst);
@@ -401,7 +401,7 @@
 	inst->alg.encrypt = encrypt;
 	inst->alg.decrypt = decrypt;
 
-	inst->free = free;
+	inst->free = free_inst;
 
 	err = skcipher_register_instance(tmpl, inst);
 	if (err)
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/pcrypt.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/pcrypt.c
@@ -24,6 +24,8 @@
 
 struct pcrypt_instance_ctx {
 	struct crypto_aead_spawn spawn;
+	struct padata_shell *psenc;
+	struct padata_shell *psdec;
 	atomic_t tfm_count;
 };
 
@@ -32,6 +34,12 @@
 	unsigned int cb_cpu;
 };
 
+static inline struct pcrypt_instance_ctx *pcrypt_tfm_ictx(
+	struct crypto_aead *tfm)
+{
+	return aead_instance_ctx(aead_alg_instance(tfm));
+}
+
 static int pcrypt_aead_setkey(struct crypto_aead *parent,
 			      const u8 *key, unsigned int keylen)
 {
@@ -63,7 +71,6 @@
 	struct padata_priv *padata = pcrypt_request_padata(preq);
 
 	padata->info = err;
-	req->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
 
 	padata_do_serial(padata);
 }
@@ -72,12 +79,14 @@
 {
 	struct pcrypt_request *preq = pcrypt_padata_request(padata);
 	struct aead_request *req = pcrypt_request_ctx(preq);
+	int ret;
 
-	padata->info = crypto_aead_encrypt(req);
+	ret = crypto_aead_encrypt(req);
 
-	if (padata->info == -EINPROGRESS)
+	if (ret == -EINPROGRESS)
 		return;
 
+	padata->info = ret;
 	padata_do_serial(padata);
 }
 
@@ -90,6 +99,9 @@
 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
 	struct pcrypt_aead_ctx *ctx = crypto_aead_ctx(aead);
 	u32 flags = aead_request_flags(req);
+	struct pcrypt_instance_ctx *ictx;
+
+	ictx = pcrypt_tfm_ictx(aead);
 
 	memset(padata, 0, sizeof(struct padata_priv));
 
@@ -103,9 +115,13 @@
 			       req->cryptlen, req->iv);
 	aead_request_set_ad(creq, req->assoclen);
 
-	err = padata_do_parallel(pencrypt, padata, &ctx->cb_cpu);
+	err = padata_do_parallel(ictx->psenc, padata, &ctx->cb_cpu);
 	if (!err)
 		return -EINPROGRESS;
+	if (err == -EBUSY) {
+		/* try non-parallel mode */
+		return crypto_aead_encrypt(creq);
+	}
 
 	return err;
 }
@@ -114,12 +130,14 @@
 {
 	struct pcrypt_request *preq = pcrypt_padata_request(padata);
 	struct aead_request *req = pcrypt_request_ctx(preq);
+	int ret;
 
-	padata->info = crypto_aead_decrypt(req);
+	ret = crypto_aead_decrypt(req);
 
-	if (padata->info == -EINPROGRESS)
+	if (ret == -EINPROGRESS)
 		return;
 
+	padata->info = ret;
 	padata_do_serial(padata);
 }
 
@@ -132,6 +150,9 @@
 	struct crypto_aead *aead = crypto_aead_reqtfm(req);
 	struct pcrypt_aead_ctx *ctx = crypto_aead_ctx(aead);
 	u32 flags = aead_request_flags(req);
+	struct pcrypt_instance_ctx *ictx;
+
+	ictx = pcrypt_tfm_ictx(aead);
 
 	memset(padata, 0, sizeof(struct padata_priv));
 
@@ -145,9 +166,13 @@
 			       req->cryptlen, req->iv);
 	aead_request_set_ad(creq, req->assoclen);
 
-	err = padata_do_parallel(pdecrypt, padata, &ctx->cb_cpu);
+	err = padata_do_parallel(ictx->psdec, padata, &ctx->cb_cpu);
 	if (!err)
 		return -EINPROGRESS;
+	if (err == -EBUSY) {
+		/* try non-parallel mode */
+		return crypto_aead_decrypt(creq);
+	}
 
 	return err;
 }
@@ -192,6 +217,8 @@
 	struct pcrypt_instance_ctx *ctx = aead_instance_ctx(inst);
 
 	crypto_drop_aead(&ctx->spawn);
+	padata_free_shell(ctx->psdec);
+	padata_free_shell(ctx->psenc);
 	kfree(inst);
 }
 
@@ -233,12 +260,22 @@
 	if (!inst)
 		return -ENOMEM;
 
+	err = -ENOMEM;
+
 	ctx = aead_instance_ctx(inst);
+	ctx->psenc = padata_alloc_shell(pencrypt);
+	if (!ctx->psenc)
+		goto out_free_inst;
+
+	ctx->psdec = padata_alloc_shell(pdecrypt);
+	if (!ctx->psdec)
+		goto out_free_psenc;
+
 	crypto_set_aead_spawn(&ctx->spawn, aead_crypto_instance(inst));
 
 	err = crypto_grab_aead(&ctx->spawn, name, 0, 0);
 	if (err)
-		goto out_free_inst;
+		goto out_free_psdec;
 
 	alg = crypto_spawn_aead_alg(&ctx->spawn);
 	err = pcrypt_init_instance(aead_crypto_instance(inst), &alg->base);
@@ -271,6 +308,10 @@
 
 out_drop_aead:
 	crypto_drop_aead(&ctx->spawn);
+out_free_psdec:
+	padata_free_shell(ctx->psdec);
+out_free_psenc:
+	padata_free_shell(ctx->psenc);
 out_free_inst:
 	kfree(inst);
 	goto out;
@@ -362,11 +403,12 @@
 
 static void __exit pcrypt_exit(void)
 {
+	crypto_unregister_template(&pcrypt_tmpl);
+
 	pcrypt_fini_padata(pencrypt);
 	pcrypt_fini_padata(pdecrypt);
 
 	kset_unregister(pcrypt_kset);
-	crypto_unregister_template(&pcrypt_tmpl);
 }
 
 subsys_initcall(pcrypt_init);
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/rng.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/rng.c
@@ -34,7 +34,6 @@
 	u8 *buf = NULL;
 	int err;
 
-	crypto_stats_get(alg);
 	if (!seed && slen) {
 		buf = kmalloc(slen, GFP_KERNEL);
 		if (!buf)
@@ -46,6 +45,7 @@
 		seed = buf;
 	}
 
+	crypto_stats_get(alg);
 	err = crypto_rng_alg(tfm)->seed(tfm, seed, slen);
 	crypto_stats_rng_seed(alg, err);
 out:
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/rsa-pkcs1pad.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/rsa-pkcs1pad.c
@@ -213,16 +213,14 @@
 		struct crypto_async_request *child_async_req, int err)
 {
 	struct akcipher_request *req = child_async_req->data;
-	struct crypto_async_request async_req;
 
 	if (err == -EINPROGRESS)
-		return;
+		goto out;
 
-	async_req.data = req->base.data;
-	async_req.tfm = crypto_akcipher_tfm(crypto_akcipher_reqtfm(req));
-	async_req.flags = child_async_req->flags;
-	req->base.complete(&async_req,
-			pkcs1pad_encrypt_sign_complete(req, err));
+	err = pkcs1pad_encrypt_sign_complete(req, err);
+
+out:
+	akcipher_request_complete(req, err);
 }
 
 static int pkcs1pad_encrypt(struct akcipher_request *req)
@@ -331,15 +329,14 @@
 		struct crypto_async_request *child_async_req, int err)
 {
 	struct akcipher_request *req = child_async_req->data;
-	struct crypto_async_request async_req;
 
 	if (err == -EINPROGRESS)
-		return;
+		goto out;
+
+	err = pkcs1pad_decrypt_complete(req, err);
 
-	async_req.data = req->base.data;
-	async_req.tfm = crypto_akcipher_tfm(crypto_akcipher_reqtfm(req));
-	async_req.flags = child_async_req->flags;
-	req->base.complete(&async_req, pkcs1pad_decrypt_complete(req, err));
+out:
+	akcipher_request_complete(req, err);
 }
 
 static int pkcs1pad_decrypt(struct akcipher_request *req)
@@ -475,6 +472,8 @@
 	pos++;
 
 	if (digest_info) {
+		if (digest_info->size > dst_len - pos)
+			goto done;
 		if (crypto_memneq(out_buf + pos, digest_info->data,
 				  digest_info->size))
 			goto done;
@@ -494,7 +493,7 @@
 			   sg_nents_for_len(req->src,
 					    req->src_len + req->dst_len),
 			   req_ctx->out_buf + ctx->key_size,
-			   req->dst_len, ctx->key_size);
+			   req->dst_len, req->src_len);
 	/* Do the actual verification step. */
 	if (memcmp(req_ctx->out_buf + ctx->key_size, out_buf + pos,
 		   req->dst_len) != 0)
@@ -509,15 +508,14 @@
 		struct crypto_async_request *child_async_req, int err)
 {
 	struct akcipher_request *req = child_async_req->data;
-	struct crypto_async_request async_req;
 
 	if (err == -EINPROGRESS)
-		return;
+		goto out;
+
+	err = pkcs1pad_verify_complete(req, err);
 
-	async_req.data = req->base.data;
-	async_req.tfm = crypto_akcipher_tfm(crypto_akcipher_reqtfm(req));
-	async_req.flags = child_async_req->flags;
-	req->base.complete(&async_req, pkcs1pad_verify_complete(req, err));
+out:
+	akcipher_request_complete(req, err);
 }
 
 /*
@@ -537,7 +535,7 @@
 
 	if (WARN_ON(req->dst) ||
 	    WARN_ON(!req->dst_len) ||
-	    !ctx->key_size || req->src_len < ctx->key_size)
+	    !ctx->key_size || req->src_len != ctx->key_size)
 		return -EINVAL;
 
 	req_ctx->out_buf = kmalloc(ctx->key_size + req->dst_len, GFP_KERNEL);
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/scompress.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/scompress.c
@@ -124,6 +124,7 @@
 	struct crypto_scomp *scomp = *tfm_ctx;
 	void **ctx = acomp_request_ctx(req);
 	struct scomp_scratch *scratch;
+	unsigned int dlen;
 	int ret;
 
 	if (!req->src || !req->slen || req->slen > SCOMP_SCRATCH_SIZE)
@@ -135,6 +136,8 @@
 	if (!req->dlen || req->dlen > SCOMP_SCRATCH_SIZE)
 		req->dlen = SCOMP_SCRATCH_SIZE;
 
+	dlen = req->dlen;
+
 	scratch = raw_cpu_ptr(&scomp_scratch);
 	spin_lock(&scratch->lock);
 
@@ -152,6 +155,9 @@
 				ret = -ENOMEM;
 				goto out;
 			}
+		} else if (req->dlen > dlen) {
+			ret = -ENOSPC;
+			goto out;
 		}
 		scatterwalk_map_and_copy(scratch->dst, req->dst, 0, req->dlen,
 					 1);
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/seqiv.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/seqiv.c
@@ -25,7 +25,7 @@
 	struct aead_request *subreq = aead_request_ctx(req);
 	struct crypto_aead *geniv;
 
-	if (err == -EINPROGRESS)
+	if (err == -EINPROGRESS || err == -EBUSY)
 		return;
 
 	if (err)
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/serpent_generic.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/serpent_generic.c
@@ -449,8 +449,9 @@
 }
 EXPORT_SYMBOL_GPL(serpent_setkey);
 
-void __serpent_encrypt(struct serpent_ctx *ctx, u8 *dst, const u8 *src)
+void __serpent_encrypt(const void *c, u8 *dst, const u8 *src)
 {
+	const struct serpent_ctx *ctx = c;
 	const u32 *k = ctx->expkey;
 	const __le32 *s = (const __le32 *)src;
 	__le32	*d = (__le32 *)dst;
@@ -514,8 +515,9 @@
 	__serpent_encrypt(ctx, dst, src);
 }
 
-void __serpent_decrypt(struct serpent_ctx *ctx, u8 *dst, const u8 *src)
+void __serpent_decrypt(const void *c, u8 *dst, const u8 *src)
 {
+	const struct serpent_ctx *ctx = c;
 	const u32 *k = ctx->expkey;
 	const __le32 *s = (const __le32 *)src;
 	__le32	*d = (__le32 *)dst;
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/shash.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/shash.c
@@ -20,12 +20,24 @@
 
 static const struct crypto_type crypto_shash_type;
 
-int shash_no_setkey(struct crypto_shash *tfm, const u8 *key,
-		    unsigned int keylen)
+static int shash_no_setkey(struct crypto_shash *tfm, const u8 *key,
+			   unsigned int keylen)
 {
 	return -ENOSYS;
 }
-EXPORT_SYMBOL_GPL(shash_no_setkey);
+
+/*
+ * Check whether an shash algorithm has a setkey function.
+ *
+ * For CFI compatibility, this must not be an inline function.  This is because
+ * when CFI is enabled, modules won't get the same address for shash_no_setkey
+ * (if it were exported, which inlining would require) as the core kernel will.
+ */
+bool crypto_shash_alg_has_setkey(struct shash_alg *alg)
+{
+	return alg->setkey != shash_no_setkey;
+}
+EXPORT_SYMBOL_GPL(crypto_shash_alg_has_setkey);
 
 static int shash_setkey_unaligned(struct crypto_shash *tfm, const u8 *key,
 				  unsigned int keylen)
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/skcipher.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/skcipher.c
@@ -617,6 +617,23 @@
 	return 0;
 }
 
+static int skcipher_setkeytype_blkcipher(struct crypto_skcipher *tfm,
+					 const u8 *key, unsigned int keylen)
+{
+	struct crypto_blkcipher **ctx = crypto_skcipher_ctx(tfm);
+	struct crypto_blkcipher *blkcipher = *ctx;
+	int err;
+
+	crypto_blkcipher_clear_flags(blkcipher, ~0);
+	crypto_blkcipher_set_flags(blkcipher, crypto_skcipher_get_flags(tfm) &
+			CRYPTO_TFM_REQ_MASK);
+	err = crypto_blkcipher_setkeytype(blkcipher, key, keylen);
+	crypto_skcipher_set_flags(tfm, crypto_blkcipher_get_flags(blkcipher) &
+			CRYPTO_TFM_RES_MASK);
+
+	return err;
+}
+
 static int skcipher_crypt_blkcipher(struct skcipher_request *req,
 				    int (*crypt)(struct blkcipher_desc *,
 						 struct scatterlist *,
@@ -683,6 +700,7 @@
 	tfm->exit = crypto_exit_skcipher_ops_blkcipher;
 
 	skcipher->setkey = skcipher_setkey_blkcipher;
+	skcipher->setkeytype = skcipher_setkeytype_blkcipher;
 	skcipher->encrypt = skcipher_encrypt_blkcipher;
 	skcipher->decrypt = skcipher_decrypt_blkcipher;
 
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/tcrypt.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/tcrypt.c
@@ -198,8 +198,8 @@
 			goto out;
 	}
 
-	pr_cont("%d operations in %d seconds (%ld bytes)\n",
-		bcount * num_mb, secs, (long)bcount * blen * num_mb);
+	pr_cont("%d operations in %d seconds (%llu bytes)\n",
+		bcount * num_mb, secs, (u64)bcount * blen * num_mb);
 
 out:
 	kfree(rc);
@@ -468,8 +468,8 @@
 			return ret;
 	}
 
-	printk("%d operations in %d seconds (%ld bytes)\n",
-	       bcount, secs, (long)bcount * blen);
+	pr_cont("%d operations in %d seconds (%llu bytes)\n",
+	        bcount, secs, (u64)bcount * blen);
 	return 0;
 }
 
@@ -759,8 +759,8 @@
 			goto out;
 	}
 
-	pr_cont("%d operations in %d seconds (%ld bytes)\n",
-		bcount * num_mb, secs, (long)bcount * blen * num_mb);
+	pr_cont("%d operations in %d seconds (%llu bytes)\n",
+		bcount * num_mb, secs, (u64)bcount * blen * num_mb);
 
 out:
 	kfree(rc);
@@ -1196,8 +1196,8 @@
 			goto out;
 	}
 
-	pr_cont("%d operations in %d seconds (%ld bytes)\n",
-		bcount * num_mb, secs, (long)bcount * blen * num_mb);
+	pr_cont("%d operations in %d seconds (%llu bytes)\n",
+		bcount * num_mb, secs, (u64)bcount * blen * num_mb);
 
 out:
 	kfree(rc);
@@ -1281,15 +1281,6 @@
 			goto out_free_tfm;
 		}
 
-
-	for (i = 0; i < num_mb; ++i)
-		if (testmgr_alloc_buf(data[i].xbuf)) {
-			while (i--)
-				testmgr_free_buf(data[i].xbuf);
-			goto out_free_tfm;
-		}
-
-
 	for (i = 0; i < num_mb; ++i) {
 		data[i].req = skcipher_request_alloc(tfm, GFP_KERNEL);
 		if (!data[i].req) {
@@ -1434,8 +1425,8 @@
 			return ret;
 	}
 
-	pr_cont("%d operations in %d seconds (%ld bytes)\n",
-		bcount, secs, (long)bcount * blen);
+	pr_cont("%d operations in %d seconds (%llu bytes)\n",
+		bcount, secs, (u64)bcount * blen);
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/testmgr.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/testmgr.c
@@ -2102,6 +2102,7 @@
 	 * If the key or authentication tag size couldn't be set, no need to
 	 * continue to encrypt.
 	 */
+	vec->crypt_error = 0;
 	if (vec->setkey_error || vec->setauthsize_error)
 		goto done;
 
@@ -2245,10 +2246,12 @@
 					req, tsgls);
 		if (err)
 			goto out;
-		err = test_aead_vec_cfg(driver, DECRYPT, &vec, vec_name, cfg,
-					req, tsgls);
-		if (err)
-			goto out;
+		if (vec.crypt_error == 0) {
+			err = test_aead_vec_cfg(driver, DECRYPT, &vec, vec_name,
+						cfg, req, tsgls);
+			if (err)
+				goto out;
+		}
 		cond_resched();
 	}
 	err = 0;
@@ -2678,6 +2681,15 @@
 	skcipher_request_set_callback(req, 0, crypto_req_done, &wait);
 	skcipher_request_set_crypt(req, &src, &dst, vec->len, iv);
 	vec->crypt_error = crypto_wait_req(crypto_skcipher_encrypt(req), &wait);
+	if (vec->crypt_error != 0) {
+		/*
+		 * The only acceptable error here is for an invalid length, so
+		 * skcipher decryption should fail with the same error too.
+		 * We'll test for this.  But to keep the API usage well-defined,
+		 * explicitly initialize the ciphertext buffer too.
+		 */
+		memset((u8 *)vec->ctext, 0, vec->len);
+	}
 done:
 	snprintf(name, max_namelen, "\"random: len=%u klen=%u\"",
 		 vec->len, vec->klen);
@@ -4104,6 +4116,15 @@
 			.cipher = __VECS(tf_cbc_tv_template)
 		},
 	}, {
+#if IS_ENABLED(CONFIG_CRYPTO_PAES_S390)
+		.alg = "cbc-paes-s390",
+		.fips_allowed = 1,
+		.test = alg_test_skcipher,
+		.suite = {
+			.cipher = __VECS(aes_cbc_tv_template)
+		}
+	}, {
+#endif
 		.alg = "cbcmac(aes)",
 		.fips_allowed = 1,
 		.test = alg_test_hash,
@@ -4246,6 +4267,15 @@
 			.cipher = __VECS(tf_ctr_tv_template)
 		}
 	}, {
+#if IS_ENABLED(CONFIG_CRYPTO_PAES_S390)
+		.alg = "ctr-paes-s390",
+		.fips_allowed = 1,
+		.test = alg_test_skcipher,
+		.suite = {
+			.cipher = __VECS(aes_ctr_tv_template)
+		}
+	}, {
+#endif
 		.alg = "cts(cbc(aes))",
 		.test = alg_test_skcipher,
 		.fips_allowed = 1,
@@ -4532,6 +4562,15 @@
 			.cipher = __VECS(xtea_tv_template)
 		}
 	}, {
+#if IS_ENABLED(CONFIG_CRYPTO_PAES_S390)
+		.alg = "ecb-paes-s390",
+		.fips_allowed = 1,
+		.test = alg_test_skcipher,
+		.suite = {
+			.cipher = __VECS(aes_tv_template)
+		}
+	}, {
+#endif
 		.alg = "ecdh",
 		.test = alg_test_kpp,
 		.fips_allowed = 1,
@@ -5085,6 +5124,15 @@
 			.cipher = __VECS(tf_xts_tv_template)
 		}
 	}, {
+#if IS_ENABLED(CONFIG_CRYPTO_PAES_S390)
+		.alg = "xts-paes-s390",
+		.fips_allowed = 1,
+		.test = alg_test_skcipher,
+		.suite = {
+			.cipher = __VECS(aes_xts_tv_template)
+		}
+	}, {
+#endif
 		.alg = "xts4096(paes)",
 		.test = alg_test_null,
 		.fips_allowed = 1,
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/testmgr.h
+++ linux-xilinx-zynqmp-5.4.0/crypto/testmgr.h
@@ -177,8 +177,8 @@
 	{
 #ifndef CONFIG_CRYPTO_FIPS
 	.key =
-	"\x30\x81\x9A" /* sequence of 154 bytes */
-	"\x02\x01\x01" /* version - integer of 1 byte */
+	"\x30\x82\x01\x38" /* sequence of 312 bytes */
+	"\x02\x01\x00" /* version - integer of 1 byte */
 	"\x02\x41" /* modulus - integer of 65 bytes */
 	"\x00\xAA\x36\xAB\xCE\x88\xAC\xFD\xFF\x55\x52\x3C\x7F\xC4\x52\x3F"
 	"\x90\xEF\xA0\x0D\xF3\x77\x4A\x25\x9F\x2E\x62\xB4\xC5\xD9\x9C\xB5"
@@ -191,24 +191,37 @@
 	"\xC2\xCD\x2D\xFF\x43\x40\x98\xCD\x20\xD8\xA1\x38\xD0\x90\xBF\x64"
 	"\x79\x7C\x3F\xA7\xA2\xCD\xCB\x3C\xD1\xE0\xBD\xBA\x26\x54\xB4\xF9"
 	"\xDF\x8E\x8A\xE5\x9D\x73\x3D\x9F\x33\xB3\x01\x62\x4A\xFD\x1D\x51"
-	"\x02\x01\x00" /* prime1 - integer of 1 byte */
-	"\x02\x01\x00" /* prime2 - integer of 1 byte */
-	"\x02\x01\x00" /* exponent1 - integer of 1 byte */
-	"\x02\x01\x00" /* exponent2 - integer of 1 byte */
-	"\x02\x01\x00", /* coefficient - integer of 1 byte */
+	"\x02\x21" /* prime1 - integer of 33 bytes */
+	"\x00\xD8\x40\xB4\x16\x66\xB4\x2E\x92\xEA\x0D\xA3\xB4\x32\x04\xB5"
+	"\xCF\xCE\x33\x52\x52\x4D\x04\x16\xA5\xA4\x41\xE7\x00\xAF\x46\x12"
+	"\x0D"
+	"\x02\x21" /* prime2 - integer of 33 bytes */
+	"\x00\xC9\x7F\xB1\xF0\x27\xF4\x53\xF6\x34\x12\x33\xEA\xAA\xD1\xD9"
+	"\x35\x3F\x6C\x42\xD0\x88\x66\xB1\xD0\x5A\x0F\x20\x35\x02\x8B\x9D"
+	"\x89"
+	"\x02\x20" /* exponent1 - integer of 32 bytes */
+	"\x59\x0B\x95\x72\xA2\xC2\xA9\xC4\x06\x05\x9D\xC2\xAB\x2F\x1D\xAF"
+	"\xEB\x7E\x8B\x4F\x10\xA7\x54\x9E\x8E\xED\xF5\xB4\xFC\xE0\x9E\x05"
+	"\x02\x21" /* exponent2 - integer of 33 bytes */
+	"\x00\x8E\x3C\x05\x21\xFE\x15\xE0\xEA\x06\xA3\x6F\xF0\xF1\x0C\x99"
+	"\x52\xC3\x5B\x7A\x75\x14\xFD\x32\x38\xB8\x0A\xAD\x52\x98\x62\x8D"
+	"\x51"
+	"\x02\x20" /* coefficient - integer of 32 bytes */
+	"\x36\x3F\xF7\x18\x9D\xA8\xE9\x0B\x1D\x34\x1F\x71\xD0\x9B\x76\xA8"
+	"\xA9\x43\xE1\x1D\x10\xB2\x4D\x24\x9F\x2D\xEA\xFE\xF8\x0C\x18\x26",
 	.m = "\x54\x85\x9b\x34\x2c\x49\xea\x2a",
 	.c =
 	"\x63\x1c\xcd\x7b\xe1\x7e\xe4\xde\xc9\xa8\x89\xa1\x74\xcb\x3c\x63"
 	"\x7d\x24\xec\x83\xc3\x15\xe4\x7f\x73\x05\x34\xd1\xec\x22\xbb\x8a"
 	"\x5e\x32\x39\x6d\xc1\x1d\x7d\x50\x3b\x9f\x7a\xad\xf0\x2e\x25\x53"
 	"\x9f\x6e\xbd\x4c\x55\x84\x0c\x9b\xcf\x1a\x4b\x51\x1e\x9e\x0c\x06",
-	.key_len = 157,
+	.key_len = 316,
 	.m_size = 8,
 	.c_size = 64,
 	}, {
 	.key =
-	"\x30\x82\x01\x1D" /* sequence of 285 bytes */
-	"\x02\x01\x01" /* version - integer of 1 byte */
+	"\x30\x82\x02\x5B" /* sequence of 603 bytes */
+	"\x02\x01\x00" /* version - integer of 1 byte */
 	"\x02\x81\x81" /* modulus - integer of 129 bytes */
 	"\x00\xBB\xF8\x2F\x09\x06\x82\xCE\x9C\x23\x38\xAC\x2B\x9D\xA8\x71"
 	"\xF7\x36\x8D\x07\xEE\xD4\x10\x43\xA4\x40\xD6\xB6\xF0\x74\x54\xF5"
@@ -230,12 +243,35 @@
 	"\x93\x99\x26\xED\x4F\x74\xA1\x3E\xDD\xFB\xE1\xA1\xCE\xCC\x48\x94"
 	"\xAF\x94\x28\xC2\xB7\xB8\x88\x3F\xE4\x46\x3A\x4B\xC8\x5B\x1C\xB3"
 	"\xC1"
-	"\x02\x01\x00" /* prime1 - integer of 1 byte */
-	"\x02\x01\x00" /* prime2 - integer of 1 byte */
-	"\x02\x01\x00" /* exponent1 - integer of 1 byte */
-	"\x02\x01\x00" /* exponent2 - integer of 1 byte */
-	"\x02\x01\x00", /* coefficient - integer of 1 byte */
-	.key_len = 289,
+	"\x02\x41" /* prime1 - integer of 65 bytes */
+	"\x00\xEE\xCF\xAE\x81\xB1\xB9\xB3\xC9\x08\x81\x0B\x10\xA1\xB5\x60"
+	"\x01\x99\xEB\x9F\x44\xAE\xF4\xFD\xA4\x93\xB8\x1A\x9E\x3D\x84\xF6"
+	"\x32\x12\x4E\xF0\x23\x6E\x5D\x1E\x3B\x7E\x28\xFA\xE7\xAA\x04\x0A"
+	"\x2D\x5B\x25\x21\x76\x45\x9D\x1F\x39\x75\x41\xBA\x2A\x58\xFB\x65"
+	"\x99"
+	"\x02\x41" /* prime2 - integer of 65 bytes */
+	"\x00\xC9\x7F\xB1\xF0\x27\xF4\x53\xF6\x34\x12\x33\xEA\xAA\xD1\xD9"
+	"\x35\x3F\x6C\x42\xD0\x88\x66\xB1\xD0\x5A\x0F\x20\x35\x02\x8B\x9D"
+	"\x86\x98\x40\xB4\x16\x66\xB4\x2E\x92\xEA\x0D\xA3\xB4\x32\x04\xB5"
+	"\xCF\xCE\x33\x52\x52\x4D\x04\x16\xA5\xA4\x41\xE7\x00\xAF\x46\x15"
+	"\x03"
+	"\x02\x40" /* exponent1 - integer of 64 bytes */
+	"\x54\x49\x4C\xA6\x3E\xBA\x03\x37\xE4\xE2\x40\x23\xFC\xD6\x9A\x5A"
+	"\xEB\x07\xDD\xDC\x01\x83\xA4\xD0\xAC\x9B\x54\xB0\x51\xF2\xB1\x3E"
+	"\xD9\x49\x09\x75\xEA\xB7\x74\x14\xFF\x59\xC1\xF7\x69\x2E\x9A\x2E"
+	"\x20\x2B\x38\xFC\x91\x0A\x47\x41\x74\xAD\xC9\x3C\x1F\x67\xC9\x81"
+	"\x02\x40" /* exponent2 - integer of 64 bytes */
+	"\x47\x1E\x02\x90\xFF\x0A\xF0\x75\x03\x51\xB7\xF8\x78\x86\x4C\xA9"
+	"\x61\xAD\xBD\x3A\x8A\x7E\x99\x1C\x5C\x05\x56\xA9\x4C\x31\x46\xA7"
+	"\xF9\x80\x3F\x8F\x6F\x8A\xE3\x42\xE9\x31\xFD\x8A\xE4\x7A\x22\x0D"
+	"\x1B\x99\xA4\x95\x84\x98\x07\xFE\x39\xF9\x24\x5A\x98\x36\xDA\x3D"
+	"\x02\x41" /* coefficient - integer of 65 bytes */
+	"\x00\xB0\x6C\x4F\xDA\xBB\x63\x01\x19\x8D\x26\x5B\xDB\xAE\x94\x23"
+	"\xB3\x80\xF2\x71\xF7\x34\x53\x88\x50\x93\x07\x7F\xCD\x39\xE2\x11"
+	"\x9F\xC9\x86\x32\x15\x4F\x58\x83\xB1\x67\xA9\x67\xBF\x40\x2B\x4E"
+	"\x9E\x2E\x0F\x96\x56\xE6\x98\xEA\x36\x66\xED\xFB\x25\x79\x80\x39"
+	"\xF7",
+	.key_len = 607,
 	.m = "\x54\x85\x9b\x34\x2c\x49\xea\x2a",
 	.c =
 	"\x74\x1b\x55\xac\x47\xb5\x08\x0a\x6e\x2b\x2d\xf7\x94\xb8\x8a\x95"
@@ -251,9 +287,9 @@
 	}, {
 #endif
 	.key =
-	"\x30\x82\x02\x1F" /* sequence of 543 bytes */
-	"\x02\x01\x01" /* version - integer of 1 byte */
-	"\x02\x82\x01\x00" /* modulus - integer of 256 bytes */
+	"\x30\x82\x04\xA3" /* sequence of 1187 bytes */
+	"\x02\x01\x00" /* version - integer of 1 byte */
+	"\x02\x82\x01\x01\x00" /* modulus - integer of 256 bytes */
 	"\xDB\x10\x1A\xC2\xA3\xF1\xDC\xFF\x13\x6B\xED\x44\xDF\xF0\x02\x6D"
 	"\x13\xC7\x88\xDA\x70\x6B\x54\xF1\xE8\x27\xDC\xC3\x0F\x99\x6A\xFA"
 	"\xC6\x67\xFF\x1D\x1E\x3C\x1D\xC1\xB5\x5F\x6C\xC0\xB2\x07\x3A\x6D"
@@ -288,12 +324,55 @@
 	"\x62\xFF\xE9\x46\xB8\xD8\x44\xDB\xA5\xCC\x31\x54\x34\xCE\x3E\x82"
 	"\xD6\xBF\x7A\x0B\x64\x21\x6D\x88\x7E\x5B\x45\x12\x1E\x63\x8D\x49"
 	"\xA7\x1D\xD9\x1E\x06\xCD\xE8\xBA\x2C\x8C\x69\x32\xEA\xBE\x60\x71"
-	"\x02\x01\x00" /* prime1 - integer of 1 byte */
-	"\x02\x01\x00" /* prime2 - integer of 1 byte */
-	"\x02\x01\x00" /* exponent1 - integer of 1 byte */
-	"\x02\x01\x00" /* exponent2 - integer of 1 byte */
-	"\x02\x01\x00", /* coefficient - integer of 1 byte */
-	.key_len = 547,
+	"\x02\x81\x81" /* prime1 - integer of 129 bytes */
+	"\x00\xFA\xAC\xE1\x37\x5E\x32\x11\x34\xC6\x72\x58\x2D\x91\x06\x3E"
+	"\x77\xE7\x11\x21\xCD\x4A\xF8\xA4\x3F\x0F\xEF\x31\xE3\xF3\x55\xA0"
+	"\xB9\xAC\xB6\xCB\xBB\x41\xD0\x32\x81\x9A\x8F\x7A\x99\x30\x77\x6C"
+	"\x68\x27\xE2\x96\xB5\x72\xC9\xC3\xD4\x42\xAA\xAA\xCA\x95\x8F\xFF"
+	"\xC9\x9B\x52\x34\x30\x1D\xCF\xFE\xCF\x3C\x56\x68\x6E\xEF\xE7\x6C"
+	"\xD7\xFB\x99\xF5\x4A\xA5\x21\x1F\x2B\xEA\x93\xE8\x98\x26\xC4\x6E"
+	"\x42\x21\x5E\xA0\xA1\x2A\x58\x35\xBB\x10\xE7\xBA\x27\x0A\x3B\xB3"
+	"\xAF\xE2\x75\x36\x04\xAC\x56\xA0\xAB\x52\xDE\xCE\xDD\x2C\x28\x77"
+	"\x03"
+	"\x02\x81\x81" /* prime2 - integer of 129 bytes */
+	"\x00\xDF\xB7\x52\xB6\xD7\xC0\xE2\x96\xE7\xC9\xFE\x5D\x71\x5A\xC4"
+	"\x40\x96\x2F\xE5\x87\xEA\xF3\xA5\x77\x11\x67\x3C\x8D\x56\x08\xA7"
+	"\xB5\x67\xFA\x37\xA8\xB8\xCF\x61\xE8\x63\xD8\x38\x06\x21\x2B\x92"
+	"\x09\xA6\x39\x3A\xEA\xA8\xB4\x45\x4B\x36\x10\x4C\xE4\x00\x66\x71"
+	"\x65\xF8\x0B\x94\x59\x4F\x8C\xFD\xD5\x34\xA2\xE7\x62\x84\x0A\xA7"
+	"\xBB\xDB\xD9\x8A\xCD\x05\xE1\xCC\x57\x7B\xF1\xF1\x1F\x11\x9D\xBA"
+	"\x3E\x45\x18\x99\x1B\x41\x64\x43\xEE\x97\x5D\x77\x13\x5B\x74\x69"
+	"\x73\x87\x95\x05\x07\xBE\x45\x07\x17\x7E\x4A\x69\x22\xF3\xDB\x05"
+	"\x39"
+	"\x02\x81\x80" /* exponent1 - integer of 128 bytes */
+	"\x5E\xD8\xDC\xDA\x53\x44\xC4\x67\xE0\x92\x51\x34\xE4\x83\xA5\x4D"
+	"\x3E\xDB\xA7\x9B\x82\xBB\x73\x81\xFC\xE8\x77\x4B\x15\xBE\x17\x73"
+	"\x49\x9B\x5C\x98\xBC\xBD\x26\xEF\x0C\xE9\x2E\xED\x19\x7E\x86\x41"
+	"\x1E\x9E\x48\x81\xDD\x2D\xE4\x6F\xC2\xCD\xCA\x93\x9E\x65\x7E\xD5"
+	"\xEC\x73\xFD\x15\x1B\xA2\xA0\x7A\x0F\x0D\x6E\xB4\x53\x07\x90\x92"
+	"\x64\x3B\x8B\xA9\x33\xB3\xC5\x94\x9B\x4C\x5D\x9C\x7C\x46\xA4\xA5"
+	"\x56\xF4\xF3\xF8\x27\x0A\x7B\x42\x0D\x92\x70\x47\xE7\x42\x51\xA9"
+	"\xC2\x18\xB1\x58\xB1\x50\x91\xB8\x61\x41\xB6\xA9\xCE\xD4\x7C\xBB"
+	"\x02\x81\x80" /* exponent2 - integer of 128 bytes */
+	"\x54\x09\x1F\x0F\x03\xD8\xB6\xC5\x0C\xE8\xB9\x9E\x0C\x38\x96\x43"
+	"\xD4\xA6\xC5\x47\xDB\x20\x0E\xE5\xBD\x29\xD4\x7B\x1A\xF8\x41\x57"
+	"\x49\x69\x9A\x82\xCC\x79\x4A\x43\xEB\x4D\x8B\x2D\xF2\x43\xD5\xA5"
+	"\xBE\x44\xFD\x36\xAC\x8C\x9B\x02\xF7\x9A\x03\xE8\x19\xA6\x61\xAE"
+	"\x76\x10\x93\x77\x41\x04\xAB\x4C\xED\x6A\xCC\x14\x1B\x99\x8D\x0C"
+	"\x6A\x37\x3B\x86\x6C\x51\x37\x5B\x1D\x79\xF2\xA3\x43\x10\xC6\xA7"
+	"\x21\x79\x6D\xF9\xE9\x04\x6A\xE8\x32\xFF\xAE\xFD\x1C\x7B\x8C\x29"
+	"\x13\xA3\x0C\xB2\xAD\xEC\x6C\x0F\x8D\x27\x12\x7B\x48\xB2\xDB\x31"
+	"\x02\x81\x81" /* coefficient - integer of 129 bytes */
+	"\x00\x8D\x1B\x05\xCA\x24\x1F\x0C\x53\x19\x52\x74\x63\x21\xFA\x78"
+	"\x46\x79\xAF\x5C\xDE\x30\xA4\x6C\x20\x38\xE6\x97\x39\xB8\x7A\x70"
+	"\x0D\x8B\x6C\x6D\x13\x74\xD5\x1C\xDE\xA9\xF4\x60\x37\xFE\x68\x77"
+	"\x5E\x0B\x4E\x5E\x03\x31\x30\xDF\xD6\xAE\x85\xD0\x81\xBB\x61\xC7"
+	"\xB1\x04\x5A\xC4\x6D\x56\x1C\xD9\x64\xE7\x85\x7F\x88\x91\xC9\x60"
+	"\x28\x05\xE2\xC6\x24\x8F\xDD\x61\x64\xD8\x09\xDE\x7E\xD3\x4A\x61"
+	"\x1A\xD3\x73\x58\x4B\xD8\xA0\x54\x25\x48\x83\x6F\x82\x6C\xAF\x36"
+	"\x51\x2A\x5D\x14\x2F\x41\x25\x00\xDD\xF8\xF3\x95\xFE\x31\x25\x50"
+	"\x12",
+	.key_len = 1191,
 	.m = "\x54\x85\x9b\x34\x2c\x49\xea\x2a",
 	.c =
 	"\xb2\x97\x76\xb4\xae\x3e\x38\x3c\x7e\x64\x1f\xcc\xa2\x7f\xf6\xbe"
@@ -720,7 +799,7 @@
 static const struct akcipher_testvec pkcs1pad_rsa_tv_template[] = {
 	{
 	.key =
-	"\x30\x82\x03\x1f\x02\x01\x00\x02\x82\x01\x01\x00\xd7\x1e\x77\x82"
+	"\x30\x82\x04\xa5\x02\x01\x00\x02\x82\x01\x01\x00\xd7\x1e\x77\x82"
 	"\x8c\x92\x31\xe7\x69\x02\xa2\xd5\x5c\x78\xde\xa2\x0c\x8f\xfe\x28"
 	"\x59\x31\xdf\x40\x9c\x60\x61\x06\xb9\x2f\x62\x40\x80\x76\xcb\x67"
 	"\x4a\xb5\x59\x56\x69\x17\x07\xfa\xf9\x4c\xbd\x6c\x37\x7a\x46\x7d"
@@ -736,42 +815,66 @@
 	"\x9e\x49\x63\x6e\x02\xc1\xc9\x3a\x9b\xa5\x22\x1b\x07\x95\xd6\x10"
 	"\x02\x50\xfd\xfd\xd1\x9b\xbe\xab\xc2\xc0\x74\xd7\xec\x00\xfb\x11"
 	"\x71\xcb\x7a\xdc\x81\x79\x9f\x86\x68\x46\x63\x82\x4d\xb7\xf1\xe6"
-	"\x16\x6f\x42\x63\xf4\x94\xa0\xca\x33\xcc\x75\x13\x02\x82\x01\x00"
-	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
-	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
-	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
-	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
-	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
-	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
-	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
-	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
-	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
-	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
-	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
-	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
-	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
-	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
-	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
-	"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01"
-	"\x02\x82\x01\x00\x62\xb5\x60\x31\x4f\x3f\x66\x16\xc1\x60\xac\x47"
-	"\x2a\xff\x6b\x69\x00\x4a\xb2\x5c\xe1\x50\xb9\x18\x74\xa8\xe4\xdc"
-	"\xa8\xec\xcd\x30\xbb\xc1\xc6\xe3\xc6\xac\x20\x2a\x3e\x5e\x8b\x12"
-	"\xe6\x82\x08\x09\x38\x0b\xab\x7c\xb3\xcc\x9c\xce\x97\x67\xdd\xef"
-	"\x95\x40\x4e\x92\xe2\x44\xe9\x1d\xc1\x14\xfd\xa9\xb1\xdc\x71\x9c"
-	"\x46\x21\xbd\x58\x88\x6e\x22\x15\x56\xc1\xef\xe0\xc9\x8d\xe5\x80"
-	"\x3e\xda\x7e\x93\x0f\x52\xf6\xf5\xc1\x91\x90\x9e\x42\x49\x4f\x8d"
-	"\x9c\xba\x38\x83\xe9\x33\xc2\x50\x4f\xec\xc2\xf0\xa8\xb7\x6e\x28"
-	"\x25\x56\x6b\x62\x67\xfe\x08\xf1\x56\xe5\x6f\x0e\x99\xf1\xe5\x95"
-	"\x7b\xef\xeb\x0a\x2c\x92\x97\x57\x23\x33\x36\x07\xdd\xfb\xae\xf1"
-	"\xb1\xd8\x33\xb7\x96\x71\x42\x36\xc5\xa4\xa9\x19\x4b\x1b\x52\x4c"
-	"\x50\x69\x91\xf0\x0e\xfa\x80\x37\x4b\xb5\xd0\x2f\xb7\x44\x0d\xd4"
-	"\xf8\x39\x8d\xab\x71\x67\x59\x05\x88\x3d\xeb\x48\x48\x33\x88\x4e"
-	"\xfe\xf8\x27\x1b\xd6\x55\x60\x5e\x48\xb7\x6d\x9a\xa8\x37\xf9\x7a"
-	"\xde\x1b\xcd\x5d\x1a\x30\xd4\xe9\x9e\x5b\x3c\x15\xf8\x9c\x1f\xda"
-	"\xd1\x86\x48\x55\xce\x83\xee\x8e\x51\xc7\xde\x32\x12\x47\x7d\x46"
-	"\xb8\x35\xdf\x41\x02\x01\x00\x02\x01\x00\x02\x01\x00\x02\x01\x00"
-	"\x02\x01\x00",
-	.key_len = 804,
+	"\x16\x6f\x42\x63\xf4\x94\xa0\xca\x33\xcc\x75\x13\x02\x03\x01\x00"
+	"\x01\x02\x82\x01\x00\x62\xb5\x60\x31\x4f\x3f\x66\x16\xc1\x60\xac"
+	"\x47\x2a\xff\x6b\x69\x00\x4a\xb2\x5c\xe1\x50\xb9\x18\x74\xa8\xe4"
+	"\xdc\xa8\xec\xcd\x30\xbb\xc1\xc6\xe3\xc6\xac\x20\x2a\x3e\x5e\x8b"
+	"\x12\xe6\x82\x08\x09\x38\x0b\xab\x7c\xb3\xcc\x9c\xce\x97\x67\xdd"
+	"\xef\x95\x40\x4e\x92\xe2\x44\xe9\x1d\xc1\x14\xfd\xa9\xb1\xdc\x71"
+	"\x9c\x46\x21\xbd\x58\x88\x6e\x22\x15\x56\xc1\xef\xe0\xc9\x8d\xe5"
+	"\x80\x3e\xda\x7e\x93\x0f\x52\xf6\xf5\xc1\x91\x90\x9e\x42\x49\x4f"
+	"\x8d\x9c\xba\x38\x83\xe9\x33\xc2\x50\x4f\xec\xc2\xf0\xa8\xb7\x6e"
+	"\x28\x25\x56\x6b\x62\x67\xfe\x08\xf1\x56\xe5\x6f\x0e\x99\xf1\xe5"
+	"\x95\x7b\xef\xeb\x0a\x2c\x92\x97\x57\x23\x33\x36\x07\xdd\xfb\xae"
+	"\xf1\xb1\xd8\x33\xb7\x96\x71\x42\x36\xc5\xa4\xa9\x19\x4b\x1b\x52"
+	"\x4c\x50\x69\x91\xf0\x0e\xfa\x80\x37\x4b\xb5\xd0\x2f\xb7\x44\x0d"
+	"\xd4\xf8\x39\x8d\xab\x71\x67\x59\x05\x88\x3d\xeb\x48\x48\x33\x88"
+	"\x4e\xfe\xf8\x27\x1b\xd6\x55\x60\x5e\x48\xb7\x6d\x9a\xa8\x37\xf9"
+	"\x7a\xde\x1b\xcd\x5d\x1a\x30\xd4\xe9\x9e\x5b\x3c\x15\xf8\x9c\x1f"
+	"\xda\xd1\x86\x48\x55\xce\x83\xee\x8e\x51\xc7\xde\x32\x12\x47\x7d"
+	"\x46\xb8\x35\xdf\x41\x02\x81\x81\x00\xe4\x4c\xae\xde\x16\xfd\x9f"
+	"\x83\x55\x5b\x84\x4a\xcf\x1c\xf1\x37\x95\xad\xca\x29\x7f\x2d\x6e"
+	"\x32\x81\xa4\x2b\x26\x14\x96\x1d\x40\x05\xec\x0c\xaf\x3f\x2c\x6f"
+	"\x2c\xe8\xbf\x1d\xee\xd0\xb3\xef\x7c\x5b\x9e\x88\x4f\x2a\x8b\x0e"
+	"\x4a\xbd\xb7\x8c\xfa\x10\x0e\x3b\xda\x68\xad\x41\x2b\xe4\x96\xfa"
+	"\x7f\x80\x52\x5f\x07\x9f\x0e\x3b\x5e\x96\x45\x1a\x13\x2b\x94\xce"
+	"\x1f\x07\x69\x85\x35\xfc\x69\x63\x5b\xf8\xf8\x3f\xce\x9d\x40\x1e"
+	"\x7c\xad\xfb\x9e\xce\xe0\x01\xf8\xef\x59\x5d\xdc\x00\x79\xab\x8a"
+	"\x3f\x80\xa2\x76\x32\x94\xa9\xea\x65\x02\x81\x81\x00\xf1\x38\x60"
+	"\x90\x0d\x0c\x2e\x3d\x34\xe5\x90\xea\x21\x43\x1f\x68\x63\x16\x7b"
+	"\x25\x8d\xde\x82\x2b\x52\xf8\xa3\xfd\x0f\x39\xe7\xe9\x5e\x32\x75"
+	"\x15\x7d\xd0\xc9\xce\x06\xe5\xfb\xa9\xcb\x22\xe5\xdb\x49\x09\xf2"
+	"\xe6\xb7\xa5\xa7\x75\x2e\x91\x2d\x2b\x5d\xf1\x48\x61\x45\x43\xd7"
+	"\xbd\xfc\x11\x73\xb5\x11\x9f\xb2\x18\x3a\x6f\x36\xa7\xc2\xd3\x18"
+	"\x4d\xf0\xc5\x1f\x70\x8c\x9b\xc5\x1d\x95\xa8\x5a\x9e\x8c\xb1\x4b"
+	"\x6a\x2a\x84\x76\x2c\xd8\x4f\x47\xb0\x81\x84\x02\x45\xf0\x85\xf8"
+	"\x0c\x6d\xa7\x0c\x4d\x2c\xb2\x5b\x81\x70\xfd\x6e\x17\x02\x81\x81"
+	"\x00\x8d\x07\xc5\xfa\x92\x4f\x48\xcb\xd3\xdd\xfe\x02\x4c\xa1\x7f"
+	"\x6d\xab\xfc\x38\xe7\x9b\x95\xcf\xfe\x49\x51\xc6\x09\xf7\x2b\xa8"
+	"\x94\x15\x54\x75\x9d\x88\xb4\x05\x55\xc3\xcd\xd4\x4a\xe4\x08\x53"
+	"\xc8\x09\xbd\x0c\x4d\x83\x65\x75\x85\xbc\x5e\xf8\x2a\xbd\xe2\x5d"
+	"\x1d\x16\x0e\xf9\x34\x89\x38\xaf\x34\x36\x6c\x2c\x22\x44\x22\x81"
+	"\x90\x73\xd9\xea\x3a\xaf\x70\x74\x48\x7c\xc6\xb5\xb0\xdc\xe5\xa9"
+	"\xa8\x76\x4b\xbc\xf7\x00\xf3\x4c\x22\x0f\x44\x62\x1d\x40\x0a\x57"
+	"\xe2\x5b\xdd\x7c\x7b\x9a\xad\xda\x70\x52\x21\x8a\x4c\xc2\xc3\x98"
+	"\x75\x02\x81\x81\x00\xed\x24\x5c\xa2\x21\x81\xa1\x0f\xa1\x2a\x33"
+	"\x0e\x49\xc7\x00\x60\x92\x51\x6e\x9d\x9b\xdc\x6d\x22\x04\x7e\xd6"
+	"\x51\x19\x9f\xf6\xe3\x91\x2c\x8f\xb8\xa2\x29\x19\xcc\x47\x31\xdf"
+	"\xf8\xab\xf0\xd2\x02\x83\xca\x99\x16\xc2\xe2\xc3\x3f\x4b\x99\x83"
+	"\xcb\x87\x9e\x86\x66\xc2\x3e\x91\x21\x80\x66\xf3\xd6\xc5\xcd\xb6"
+	"\xbb\x64\xef\x22\xcf\x48\x94\x58\xe7\x7e\xd5\x7c\x34\x1c\xb7\xa2"
+	"\xd0\x93\xe9\x9f\xb5\x11\x61\xd7\x5f\x37\x0f\x64\x52\x70\x11\x78"
+	"\xcc\x08\x77\xeb\xf8\x30\x1e\xb4\x9e\x1b\x4a\xc7\xa8\x33\x51\xe0"
+	"\xed\xdf\x53\xf6\xdf\x02\x81\x81\x00\x86\xd9\x4c\xee\x65\x61\xc1"
+	"\x19\xa9\xd5\x74\x9b\xd5\xca\xf6\x83\x2b\x06\xb4\x20\xfe\x45\x29"
+	"\xe8\xe3\xfa\xe1\x4f\x28\x8e\x63\x2f\x74\xc3\x3a\x5c\x9a\xf5\x9e"
+	"\x0e\x0d\xc5\xfe\xa0\x4c\x00\xce\x7b\xa4\x19\x17\x59\xaf\x13\x3a"
+	"\x03\x8f\x54\xf5\x60\x39\x2e\xd9\x06\xb3\x7c\xd6\x90\x06\x41\x77"
+	"\xf3\x93\xe1\x7a\x01\x41\xc1\x8f\xfe\x4c\x88\x39\xdb\xde\x71\x9e"
+	"\x58\xd1\x49\x50\x80\xb2\x5a\x4f\x69\x8b\xb8\xfe\x63\xd4\x42\x3d"
+	"\x37\x61\xa8\x4c\xff\xb6\x99\x4c\xf4\x51\xe0\x44\xaa\x69\x79\x3f"
+	"\x81\xa4\x61\x3d\x26\xe9\x04\x52\x64",
+	.key_len = 1193,
 	/*
 	 * m is SHA256 hash of following message:
 	 * "\x49\x41\xbe\x0a\x0c\xc9\xf6\x35\x51\xe4\x27\x56\x13\x71\x4b\xd0"
--- linux-xilinx-zynqmp-5.4.0.orig/crypto/xts.c
+++ linux-xilinx-zynqmp-5.4.0/crypto/xts.c
@@ -328,7 +328,7 @@
 	crypto_free_cipher(ctx->tweak);
 }
 
-static void free(struct skcipher_instance *inst)
+static void free_inst(struct skcipher_instance *inst)
 {
 	crypto_drop_skcipher(skcipher_instance_ctx(inst));
 	kfree(inst);
@@ -439,7 +439,7 @@
 	inst->alg.encrypt = encrypt;
 	inst->alg.decrypt = decrypt;
 
-	inst->free = free;
+	inst->free = free_inst;
 
 	err = skcipher_register_instance(tmpl, inst);
 	if (err)
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/changelog
+++ linux-xilinx-zynqmp-5.4.0/debian.master/changelog
@@ -0,0 +1,46174 @@
+linux (5.4.0-228.248) focal; urgency=medium
+
+  * focal/linux: 5.4.0-228.248 -proposed tracker (LP: #2144157)
+
+  * CVE-2024-46816
+    - drm/amd/display: Stop amdgpu_dm initialize when link nums greater than
+      max_links
+
+  * CVE-2022-49046
+    - i2c: dev: check return value when calling dev_set_name()
+
+  * CVE-2025-37849
+    - KVM: arm/arm64: vgic: Reset base address on kvm_vgic_dist_destroy()
+    - KVM: arm64: vgic: Add a non-locking primitive for
+      kvm_vgic_vcpu_destroy()
+    - KVM: arm64: vgic: Force vcpu vgic teardown on vcpu destroy
+    - KVM: arm64: Tear down vGIC on failed vCPU creation
+
+  * CVE-2026-23074
+    - net/sched: Enforce that teql can only be used as root qdisc
+
+  * CVE-2026-23060
+    - crypto: authencesn - reject too-short AAD (assoclen<8) to match ESP/ESN
+      spec
+
+ -- Manuel Diewald <manuel.diewald@canonical.com>  Fri, 13 Mar 2026 13:34:39 +0100
+
+linux (5.4.0-227.247) focal; urgency=medium
+
+  * Miscellaneous upstream changes
+    - apparmor: validate DFA start states are in bounds in unpack_pdb
+    - apparmor: fix memory leak in verify_header
+    - apparmor: replace recursive profile removal with iterative approach
+    - apparmor: fix: limit the number of levels of policy namespaces
+    - apparmor: fix side-effect bug in match_char() macro usage
+    - apparmor: fix missing bounds check on DEFAULT table in verify_dfa()
+    - apparmor: fix unprivileged local user can do privileged policy
+      management
+    - apparmor: fix differential encoding verification
+    - apparmor: fix race on rawdata dereference
+    - apparmor: fix race between freeing data and fs accessing it
+
+ -- Manuel Diewald <manuel.diewald@canonical.com>  Tue, 10 Mar 2026 12:12:16 +0100
+
+linux (5.4.0-226.246) focal; urgency=medium
+
+  * focal/linux: 5.4.0-226.246 -proposed tracker (LP: #2140846)
+
+  * CVE-2022-49072
+    - gpio: Restrict usage of GPIO chip irq members before initialization
+    - gpio: Request interrupts after IRQ is initialized
+
+  * CVE-2021-47599
+    - btrfs: convert latest_bdev type to btrfs_device and rename
+    - btrfs: use latest_dev in btrfs_show_devname
+
+  * CVE-2022-48875
+    - wifi: mac80211: sdata can be NULL during AMPDU start
+
+  * ipsec_offload in rtnetlink.sh from kselftests.net fails on s390x
+    (LP: #1893921)
+    - SAUCE: Fix selftest/net/rtnetlink.sh for Big Endian
+    - SAUCE: Fix selftest/net/rtnetlink.sh for Big Endian (ip address)
+
+  * CVE-2024-56640
+    - net/smc: fix LGR and link use-after-free issue
+
+  * CVE-2025-21780
+    - drm/amdgpu: avoid buffer overflow attach in smu_sys_set_pp_table()
+
+  * CVE-2022-49267
+    - mmc: core: use sysfs_emit() instead of sprintf()
+
+  * CVE-2024-49927
+    - x86/ioapic: Handle allocation failures gracefully
+
+  * statx09 in ubuntu_ltp_syscalls failed on Focal 5.4 (LP: #1966620)
+    - docs: fs-verity: document first supported kernel version
+    - statx: define STATX_ATTR_VERITY
+    - ext4: support STATX_ATTR_VERITY
+    - f2fs: support STATX_ATTR_VERITY
+    - docs: fs-verity: mention statx() support
+
+  * CVE-2025-40215 // CVE-2025-40256
+    - xfrm: delete x->tunnel as we delete x
+    - xfrm: also call xfrm_state_delete_tunnel at destroy time for states that
+      were never added
+
+ -- Manuel Diewald <manuel.diewald@canonical.com>  Fri, 06 Feb 2026 18:52:24 +0100
+
+linux (5.4.0-225.245) focal; urgency=medium
+
+  * focal/linux: 5.4.0-225.245 -proposed tracker (LP: #2137983)
+
+  * CVE-2022-49698
+    - netfilter: use get_random_u32 instead of prandom
+
+  * CVE-2025-40019
+    - crypto: essiv - Check ssize for decryption and in-place encryption
+
+  * Focal generic kernel FTBFS when CONFIG_PROVE_LOCKING = y (LP: #2130776)
+    - SAUCE: Use current->hardirqs_enabled in lockdep preemption asserts
+
+  * CVE-2025-21726
+    - padata: add pd get/put refcnt helper
+    - padata: avoid UAF for reorder_work
+    - padata: do not leak refcount in reorder_work
+
+ -- Manuel Diewald <manuel.diewald@canonical.com>  Fri, 09 Jan 2026 18:15:38 +0100
+
+linux (5.4.0-224.244) focal; urgency=medium
+
+  * focal/linux: 5.4.0-224.244 -proposed tracker (LP: #2131368)
+
+  * CVE-2025-38666
+    - net: appletalk: fix kerneldoc warnings
+    - net: appletalk: Fix use-after-free in AARP proxy probe
+
+  * CVE-2024-50196
+    - pinctrl: ocelot: fix system hang on level based interrupts
+
+  * CVE-2024-49935
+    - ACPI: PAD: fix crash in exit_round_robin()
+
+  * CVE-2022-49390
+    - macsec: fix UAF bug for real_dev
+
+  * CVE-2025-37958
+    - mm/huge_memory: fix dereferencing invalid pmd migration entry
+
+  * CVE-2024-50095
+    - IB/mad: Issue complete whenever decrements agent refcount
+    - RDMA/mad: Improve handling of timed out WRs of mad agent
+
+  * CVE-2025-39964
+    - crypto: af_alg - Disallow concurrent writes in af_alg_sendmsg
+    - crypto: af_alg - Fix incorrect boolean values in af_alg_ctx
+
+  * CVE-2024-50067
+    - uprobes: encapsulate preparation of uprobe args buffer
+    - uprobe: avoid out-of-bounds memory access of fetching args
+
+  * CVE-2024-53090
+    - afs: Fix lock recursion
+
+  * CVE-2022-49026
+    - e100: Fix possible use after free in e100_xmit_prepare
+
+  * CVE-2025-21855
+    - ibmvnic: Don't reference skb after sending to VIOS
+
+  * CVE-2024-53218
+    - f2fs: fix race in concurrent f2fs_stop_gc_thread
+
+  * CVE-2024-47691
+    - f2fs: fix to avoid use-after-free in f2fs_stop_gc_thread()
+
+  * CVE-2025-40018
+    - ipvs: Defer ip_vs_ftp unregister during netns cleanup
+
+  * CVE-2025-39993
+    - media: imon: reorganize serialization
+    - media: rc: fix races with imon_disconnect()
+
+ -- Manuel Diewald <manuel.diewald@canonical.com>  Fri, 14 Nov 2025 17:45:56 +0100
+
+linux (5.4.0-223.243) focal; urgency=medium
+
+  * focal/linux: 5.4.0-223.243 -proposed tracker (LP: #2127329)
+
+  * VMSCAPE CVE-2025-40300 (LP: #2124105) // CVE-2025-40300
+    - Documentation/hw-vuln: Add VMSCAPE documentation
+    - x86/vmscape: Enumerate VMSCAPE bug
+    - x86/vmscape: Add conditional IBPB mitigation
+    - x86/vmscape: Enable the mitigation
+    - x86/bugs: Move cpu_bugs_smt_update() down
+    - x86/vmscape: Warn when STIBP is disabled with SMT
+    - x86/vmscape: Add old Intel CPUs to affected list
+
+  * VMSCAPE CVE-2025-40300 (LP: #2124105)
+    - [Config] Enable MITIGATION_VMSCAPE config
+
+  * CVE-2024-50061
+    - i3c: master: cdns: Fix use after free vulnerability in cdns_i3c_master
+      Driver Due to Race Condition
+
+  * CVE-2025-38352
+    - posix-cpu-timers: fix race between handle_posix_cpu_timers() and
+      posix_cpu_timer_del()
+
+  * CVE-2025-21727
+    - padata: fix UAF in padata_reorder
+
+  * CVE-2024-56664
+    - bpf, sockmap: Fix race between element replace and close()
+
+  * CVE-2023-52854
+    - padata: Fix refcnt handling in padata_free_shell()
+
+  * CVE-2025-37838
+    - HSI: ssi_protocol: Fix use after free vulnerability in ssi_protocol
+      Driver Due to Race Condition
+
+  * CVE-2024-35867
+    - smb: client: fix potential UAF in cifs_stats_proc_show()
+
+ -- Manuel Diewald <manuel.diewald@canonical.com>  Fri, 10 Oct 2025 21:12:25 +0200
+
+linux (5.4.0-222.242) focal; urgency=medium
+
+  * focal/linux: 5.4.0-222.242 -proposed tracker (LP: #2124155)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync git-ubuntu-log
+
+  * sources list generation using dwarfdump takes up to 0.5hr in build process
+    (LP: #2104911)
+    - [Packaging] Don't generate list of source files
+
+  * CVE-2025-37785
+    - ext4: optimize __ext4_check_dir_entry()
+    - ext4: fix OOB read when checking dotdot dir
+
+  * CVE-2025-21796
+    - nfsd: clear acl_access/acl_default after releasing them
+
+  * CVE-2025-38617
+    - net/packet: fix a race in packet_set_ring() and packet_notifier()
+
+  * CVE-2025-38618
+    - vsock: Do not allow binding to VMADDR_PORT_ANY
+
+  * CVE-2025-38477
+    - net/sched: sch_qfq: Fix race condition on qfq_aggregate
+    - net/sched: sch_qfq: Avoid triggering might_sleep in atomic context in
+      qfq_delete_class
+
+ -- Manuel Diewald <manuel.diewald@canonical.com>  Wed, 17 Sep 2025 21:22:58 +0200
+
+linux (5.4.0-221.241) focal; urgency=medium
+
+  * focal/linux: 5.4.0-221.241 -proposed tracker (LP: #2119818)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update annotations scripts
+
+  * CVE-2025-38350
+    - net/sched: Always pass notifications when child class becomes empty
+
+  * CVE-2024-57996 // CVE-2025-37752
+    - net_sched: sch_sfq: move the limit validation
+
+ -- Manuel Diewald <manuel.diewald@canonical.com>  Thu, 07 Aug 2025 16:44:03 +0200
+
+linux (5.4.0-220.240) focal; urgency=medium
+
+  * focal/linux: 5.4.0-220.240 -proposed tracker (LP: #2116506)
+
+  * CVE-2023-52975
+    - scsi: iscsi: Move pool freeing
+    - scsi: iscsi_tcp: Fix UAF during logout when accessing the shost
+      ipaddress
+
+  * CVE-2023-52757
+    - smb: client: fix potential deadlock when releasing mids
+
+  * CVE-2025-38083
+    - net_sched: prio: fix a race in prio_tune()
+
+  * CVE-2024-49950
+    - Bluetooth: L2CAP: Fix uaf in l2cap_connect
+    - Bluetooth: hci_core: Fix calling mgmt_device_connected
+
+  * CVE-2024-50073
+    - tty: n_gsm: Fix use-after-free in gsm_cleanup_mux
+
+  * CVE-2025-37797
+    - net_sched: hfsc: Fix a UAF vulnerability in class handling
+
+  * CVE-2024-38541
+    - of: module: add buffer overflow check in of_modalias()
+
+ -- Manuel Diewald <manuel.diewald@canonical.com>  Fri, 11 Jul 2025 14:40:02 +0200
+
+linux (5.4.0-219.239) focal; urgency=medium
+
+  * focal/linux: 5.4.0-219.239 -proposed tracker (LP: #2114448)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update variants
+    - [Packaging] update annotations scripts
+
+  * CVE-2025-37798
+    - sch_htb: make htb_qlen_notify() idempotent
+    - sch_htb: make htb_deactivate() idempotent
+    - sch_drr: make drr_qlen_notify() idempotent
+    - sch_hfsc: make hfsc_qlen_notify() idempotent
+    - sch_qfq: make qfq_qlen_notify() idempotent
+    - codel: remove sch->q.qlen check before qdisc_tree_reduce_backlog()
+
+  * CVE-2024-53051
+    - drm/i915/hdcp: Add encoder check in intel_hdcp_get_capability
+
+  * CVE-2025-37997
+    - netfilter: ipset: fix region locking in hash types
+
+  * CVE-2025-37890
+    - net_sched: hfsc: Fix a UAF vulnerability in class with netem as child
+      qdisc
+    - sch_hfsc: Fix qlen accounting bug when using peek in hfsc_enqueue()
+    - net_sched: hfsc: Address reentrant enqueue adding class to eltree twice
+
+  * CVE-2024-46787
+    - userfaultfd: fix checks for huge PMDs
+
+  * CVE-2025-37782
+    - Revert "UBUNTU: SAUCE: fs: hfs/hfsplus: add key_len boundary check to
+      hfs_bnode_read_key"
+    - hfs/hfsplus: fix slab-out-of-bounds in hfs_bnode_read_key
+
+  * CVE-2025-37750
+    - smb: client: fix UAF in decryption with multichannel
+
+  * CVE-2024-53185
+    - smb: client: fix NULL ptr deref in crypto_aead_setkey()
+
+  * CVE-2024-50047
+    - smb: client: fix UAF in async decryption
+
+  * CVE-2024-56662
+    - acpi: nfit: vmalloc-out-of-bounds Read in acpi_nfit_ctl
+
+ -- Manuel Diewald <manuel.diewald@canonical.com>  Fri, 13 Jun 2025 20:27:13 +0200
+
+linux (5.4.0-218.238) focal; urgency=medium
+
+  * focal/linux: 5.4.0-218.238 -proposed tracker (LP: #2110876)
+
+  * Rotate the Canonical Livepatch key (LP: #2111244)
+    - [Config] Prepare for Canonical Livepatch key rotation
+
+  * CVE-2025-2312 cifs.upcall could access incorrect kerberos credentials cache
+    (LP: #2099914) // CVE-2025-2312
+    - CIFS: New mount option for cifs.upcall namespace resolution
+
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357)
+    - vlan: fix memory leak in vlan_newlink()
+    - clockevents/drivers/i8253: Fix stop sequence for timer 0
+    - sched/isolation: Prevent boot crash when the boot CPU is nohz_full
+    - Revert "UBUNTU: SAUCE: sctp: sysctl: pass right argument to container_of"
+    - Revert "sctp: sysctl: cookie_hmac_alg: avoid using current->nsproxy"
+    - Revert "sctp: sysctl: auth_enable: avoid using current->nsproxy"
+    - sctp: sysctl: cookie_hmac_alg: avoid using current->nsproxy
+    - sctp: sysctl: auth_enable: avoid using current->nsproxy
+    - pinctrl: bcm281xx: Fix incorrect regmap max_registers value
+    - netpoll: Fix use correct return type for ndo_start_xmit()
+    - netpoll: remove dev argument from netpoll_send_skb_on_dev()
+    - netpoll: move netpoll_send_skb() out of line
+    - netpoll: netpoll_send_skb() returns transmit status
+    - netpoll: hold rcu read lock in __netpoll_send_skb()
+    - drivers/hv: Replace binary semaphore with mutex
+    - Drivers: hv: vmbus: Don't release fb_mmio resource in vmbus_free_mmio()
+    - ipvs: prevent integer overflow in do_ip_vs_get_ctl()
+    - netfilter: nft_exthdr: fix offset with ipv4_find_option()
+    - net/mlx5e: Prevent bridge link show failure for non-eswitch-allowed devices
+    - nvme-fc: go straight to connecting state when initializing
+    - hrtimers: Mark is_migration_base() with __always_inline
+    - powercap: call put_device() on an error path in
+      powercap_register_control_type()
+    - ACPI: resource: IRQ override for Eluktronics MECH-17
+    - HID: intel-ish-hid: fix the length of MNG_SYNC_FW_CLOCK in doorbell
+    - s390/cio: Fix CHPID "configure" attribute caching
+    - ASoC: rsnd: don't indicate warning on rsnd_kctrl_accept_runtime()
+    - nvmet-rdma: recheck queue state is LIVE in state lock in recv done
+    - sctp: Fix undefined behavior in left shift operation
+    - nvme: only allow entering LIVE from CONNECTING state
+    - fuse: don't truncate cached, mutated symlink
+    - x86/irq: Define trace events conditionally
+    - drm/nouveau: Do not override forced connector status
+    - block: fix 'kmem_cache of name 'bio-108' already exists'
+    - USB: serial: ftdi_sio: add support for Altera USB Blaster 3
+    - USB: serial: option: add Telit Cinterion FE990B compositions
+    - USB: serial: option: fix Telit Cinterion FE990A name
+    - USB: serial: option: match on interface class for Telit FN990B
+    - drm/atomic: Filter out redundant DPMS calls
+    - qlcnic: fix memory leak issues in qlcnic_sriov_common.c
+    - drm/gma500: Add NULL check for pci_gfx_root in mid_get_vbt_data()
+    - ASoC: codecs: wm0010: Fix error handling path in wm0010_spi_probe()
+    - i2c: ali1535: Fix an error handling path in ali1535_probe()
+    - i2c: ali15x3: Fix an error handling path in ali15x3_probe()
+    - i2c: sis630: Fix an error handling path in sis630_probe()
+    - firmware: imx-scu: fix OF node leak in .probe()
+    - xfrm_output: Force software GSO only in tunnel mode
+    - RDMA/bnxt_re: Avoid clearing VLAN_ID mask in modify qp path
+    - RDMA/hns: Fix wrong value of max_sge_rd
+    - ipv6: Set errno after ip_fib_metrics_init() in ip6_route_info_create().
+    - net/neighbor: add missing policy for NDTPA_QUEUE_LENBYTES
+    - i2c: omap: fix IRQ storms
+    - drm/v3d: Don't run jobs that have errors flagged in its fence
+    - mmc: atmel-mci: Add missing clk_disable_unprepare()
+    - ARM: shmobile: smp: Enforce shmobile_smp_* alignment
+    - batman-adv: Ignore own maximum aggregation size during RX
+    - ALSA: usb-audio: Add quirk for Plantronics headsets to fix control names
+    - HID: hid-plantronics: Add mic mute mapping and generalize quirks
+    - ARM: 9350/1: fault: Implement copy_from_kernel_nofault_allowed()
+    - ARM: 9351/1: fault: Add "cut here" line for prefetch aborts
+    - ARM: Remove address checking for MMUless devices
+    - counter: stm32-lptimer-cnt: fix error handling when enabling
+    - tty: serial: 8250: Add some more device IDs
+    - net: usb: qmi_wwan: add Telit Cinterion FN990B composition
+    - net: usb: qmi_wwan: add Telit Cinterion FE990B composition
+    - net: usb: usbnet: restore usb%d name exception for local mac addresses
+    - serial: 8250_dma: terminate correct DMA in tx_dma_flush()
+    - x86/mm/pat: cpa-test: fix length for CPA_ARRAY test
+    - cpufreq: governor: Fix negative 'idle_time' handling in dbs_update()
+    - x86/fpu: Avoid copying dynamic FP state from init_task in
+      arch_dup_task_struct()
+    - x86/platform: Only allow CONFIG_EISA for 32-bit
+    - [Config] updateconfigs for HAVE_EISA
+    - selinux: Chain up tool resolving errors in install_policy.sh
+    - EDAC/ie31200: Fix the size of EDAC_MC_LAYER_CHIP_SELECT layer
+    - EDAC/ie31200: Fix the DIMM size mask for several SoCs
+    - EDAC/ie31200: Fix the error path order of ie31200_init()
+    - PM: sleep: Fix handling devices with direct_complete set on errors
+    - lockdep: Don't disable interrupts on RT in disable_irq_nosync_lockdep.*()
+    - perf/ring_buffer: Allow the EPOLLRDNORM flag for poll
+    - ALSA: hda/realtek: Always honor no_shutup_pins
+    - drm/mediatek: mtk_hdmi: Fix typo for aud_sampe_size member
+    - PCI/portdrv: Only disable pciehp interrupts early when needed
+    - PCI: Remove stray put_device() in pci_register_host_bridge()
+    - PCI: pciehp: Don't enable HPIE when resuming in poll mode
+    - fbdev: au1100fb: Move a variable assignment behind a null pointer check
+    - mdacon: rework dependency list
+    - fbdev: sm501fb: Add some geometry checks.
+    - clk: amlogic: gxbb: drop incorrect flag on 32k clock
+    - bpf: Use preempt_count() directly in bpf_send_signal_common()
+    - lib: 842: Improve error handling in sw842_compress()
+    - pinctrl: renesas: rza2: Fix missing of_node_put() call
+    - clk: rockchip: rk3328: fix wrong clk_ref_usb3otg parent
+    - IB/mad: Check available slots before posting receive WRs
+    - clk: amlogic: g12b: fix cluster A parent data
+    - clk: amlogic: gxbb: drop non existing 32k clock parent
+    - clk: amlogic: g12a: fix mmc A peripheral clock
+    - x86/entry: Fix ORC unwinder for PUSH_REGS with save_ret=1
+    - power: supply: max77693: Fix wrong conversion of charge input threshold
+      value
+    - mfd: sm501: Switch to BIT() to mitigate integer overflows
+    - x86/dumpstack: Fix inaccurate unwinding from exception stacks due to
+      misplaced assignment
+    - isofs: fix KMSAN uninit-value bug in do_isofs_readdir()
+    - coresight: catu: Fix number of pages while using 64k pages
+    - iio: accel: mma8452: Ensure error return on failure to matching oversampling
+      ratio
+    - perf units: Fix insufficient array space
+    - kexec: initialize ELF lowest address to ULONG_MAX
+    - perf python: Fixup description of sample.id event member
+    - perf python: Decrement the refcount of just created event on failure
+    - perf python: Check if there is space to copy all the event
+    - fs/procfs: fix the comment above proc_pid_wchan()
+    - objtool, media: dib8000: Prevent divide-by-zero in dib8000_set_dds()
+    - ring-buffer: Fix bytes_dropped calculation issue
+    - octeontx2-af: Fix mbox INTR handler when num VFs > 64
+    - sched/smt: Always inline sched_smt_active()
+    - wifi: iwlwifi: fw: allocate chained SG tables for dump
+    - affs: generate OFS sequence numbers starting at 1
+    - affs: don't write overlarge OFS data block size fields
+    - sched/deadline: Use online cpus for validating runtime
+    - locking/semaphore: Use wake_q to wake up processes outside lock critical
+      section
+    - can: statistics: use atomic access in hot path
+    - hwmon: (nct6775-core) Fix out of bounds access for NCT679{8,9}
+    - ntb: intel: Fix using link status DB's
+    - vsock: avoid timeout during connect() if the socket is closing
+    - ipv6: fix omitted netlink attributes when using RTEXT_FILTER_SKIP_STATS
+    - net: dsa: mv88e6xxx: propperly shutdown PPU re-enable timer on destroy
+    - can: flexcan: only change CAN state when link up in system PM
+    - ntb_perf: Delete duplicate dmaengine_unmap_put() call in perf_copy_chunk()
+    - x86/tsc: Always save/restore TSC sched_clock() on suspend/resume
+    - ACPI: resource: Skip IRQ override on ASUS Vivobook 14 X1404VAP
+    - mmc: sdhci-pxav3: set NEED_RSP_BUSY capability
+    - jfs: add index corruption check to DT_GETPAGE()
+    - Linux 5.4.292
+
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-39735
+    - jfs: fix slab-out-of-bounds read in ea_get()
+
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22035
+    - tracing: Fix use-after-free in print_graph_function_flags during tracer
+      switching
+
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22045
+    - x86/mm: Fix flush_tlb_range() when used for zapping normal PMDs
+
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22054
+    - arcnet: Add NULL check in com20020pci_probe()
+
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-38637
+    - net_sched: skbprio: Remove overly strict queue assertions
+
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22063
+    - netlabel: Fix NULL pointer exception caused by CALIPSO on IPv4 sockets
+
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2023-53034
+    - ntb_hw_switchtec: Fix shift-out-of-bounds in switchtec_ntb_mw_set_trans
+
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22071
+    - spufs: fix a leak in spufs_create_context()
+
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22073
+    - spufs: fix a leak on spufs_new_file() failure
+
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22079
+    - ocfs2: validate l_tree_depth to avoid out-of-bounds access
+
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22086
+    - RDMA/mlx5: Fix mlx5_poll_one() cur_qp update flow
+
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2024-58093
+    - PCI/ASPM: Fix link state exit during switch upstream function removal
+
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-23136
+    - thermal: int340x: Add NULL check for adev
+
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22020
+    - memstick: rtsx_usb_ms: Fix slab-use-after-free in rtsx_usb_ms_drv_remove
+
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22021
+    - netfilter: socket: Lookup orig tuple for IPv6 SNAT
+
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22018
+    - atm: Fix NULL pointer dereference
+
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-21996
+    - drm/radeon: fix uninitialized size issue in radeon_vce_cs_parse()
+
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22004
+    - net: atm: fix use after free in lec_send()
+
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22005
+    - ipv6: Fix memleak of nhc_pcpu_rth_output in fib_check_nh_v6_gw().
+
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22007
+    - Bluetooth: Fix error code in chan_alloc_skb_cb()
+
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-21956
+    - drm/amd/display: Assign normalized_pix_clk when color depth = 14
+
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-21991
+    - x86/microcode/AMD: Fix out-of-bounds on systems with CPU-less NUMA nodes
+
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-21992
+    - HID: ignore non-functional sensor in HP 5MP Camera
+
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-21957
+    - scsi: qla1280: Fix kernel oops when debug level > 2
+
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-21993
+    - iscsi_ibft: Fix UBSAN shift-out-of-bounds warning in ibft_attr_show_nic()
+
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-21959
+    - netfilter: nf_conncount: Fully initialize struct nf_conncount_tuple in
+      insert_tree()
+
+  * CVE-2024-53168
+    - net: make sock_inuse_add() available
+    - sunrpc: fix one UAF issue caused by sunrpc kernel tcp socket
+
+  * CVE-2024-56551
+    - drm/amdgpu: fix usage slab after free
+
+  * CVE-2021-47211
+    - ALSA: usb-audio: fix null pointer dereference on pointer cs_desc
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update annotations scripts
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Mon, 19 May 2025 10:50:52 +0200
+
+linux (5.4.0-216.236) focal; urgency=medium
+
+  * focal/linux: 5.4.0-216.236 -proposed tracker (LP: #2106869)
+
+  * CVE-2023-52741
+    - cifs: Fix use-after-free in rdata->read_into_pages()
+
+  * CVE-2021-47191
+    - scsi: scsi_debug: Fix out-of-bound read in resp_readcap16()
+
+  * iommu/arm-smmu-v3: Don't reserve implementation defined register space
+    (LP: #2067864)
+    - iommu/arm-smmu-v3: Don't reserve implementation defined register space
+
+  * CVE-2025-21971
+    - net_sched: Prevent creation of classes with TC_H_ROOT
+
+  * CVE-2024-56599
+    - wifi: ath10k: avoid NULL pointer error during sdio remove
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002)
+    - perf cs-etm: Add missing variable in cs_etm__process_queues()
+    - udf: Fix use of check_add_overflow() with mixed type arguments
+    - overflow: Add __must_check attribute to check_*() helpers
+    - overflow: Correct check_shl_overflow() comment
+    - overflow: Allow mixed type arguments
+    - afs: Fix directory format encoding struct
+    - partitions: ldm: remove the initial kernel-doc notation
+    - drm/etnaviv: Fix page property being used for non writecombine buffers
+    - wifi: rtlwifi: do not complete firmware loading needlessly
+    - rtlwifi: rtl8192se Rename RT_TRACE to rtl_dbg
+    - wifi: rtlwifi: rtl8192se: rise completion of firmware loading as last step
+    - wifi: rtlwifi: usb: fix workqueue leak when probe fails
+    - dt-bindings: mmc: controller: clarify the address-cells description
+    - rtlwifi: replace usage of found with dedicated list iterator variable
+    - wifi: rtlwifi: remove unused timer and related code
+    - wifi: rtlwifi: remove unused dualmac control leftovers
+    - wifi: rtlwifi: pci: wait for firmware loading before releasing memory
+    - cpupower: fix TSC MHz calculation
+    - regulator: of: Implement the unwind path of of_regulator_match()
+    - wifi: wlcore: fix unbalanced pm_runtime calls
+    - selftests/harness: Display signed values correctly
+    - selftests: harness: fix printing of mismatch values in __EXPECT()
+    - clk: analogbits: Fix incorrect calculation of vco rate delta
+    - net/mlxfw: Drop hard coded max FW flash image size
+    - tools/testing/selftests/bpf/test_tc_tunnel.sh: Fix wait for server bind
+    - ASoC: sun4i-spdif: Add clock multiplier settings
+    - perf header: Fix one memory leakage in process_bpf_btf()
+    - perf header: Fix one memory leakage in process_bpf_prog_info()
+    - ktest.pl: Remove unused declarations in run_bisect_test function
+    - padata: fix sysfs store callback check
+    - perf top: Don't complain about lack of vmlinux when not resolving some
+      kernel samples
+    - perf report: Fix misleading help message about --demangle
+    - RDMA/mlx4: Avoid false error about access to uninitialized gids array
+    - arm64: dts: mediatek: mt8173-evb: Drop regulator-compatible property
+    - arm64: dts: mediatek: mt8173-evb: Fix MT6397 PMIC sub-node names
+    - ARM: dts: mediatek: mt7623: fix IR nodename
+    - fbdev: omapfb: Fix an OF node leak in dss_of_port_get_parent_device()
+    - media: rc: iguanair: handle timeouts
+    - media: lmedm04: Use GFP_KERNEL for URB allocation/submission.
+    - media: lmedm04: Handle errors for lme2510_int_read
+    - PCI: endpoint: Destroy the EPC device in devm_pci_epc_destroy()
+    - media: mipi-csis: Add check for clk_enable()
+    - media: camif-core: Add check for clk_enable()
+    - media: uvcvideo: Propagate buf->error to userspace
+    - staging: media: imx: fix OF node leak in imx_media_add_of_subdevs()
+    - scsi: mpt3sas: Set ioc->manu_pg11.EEDPTagMode directly to 1
+    - scsi: ufs: bsg: Delete bsg_dev when setting up bsg fails
+    - ocfs2: mark dquot as inactive if failed to start trans while releasing dquot
+    - module: Extend the preempt disabled section in
+      dereference_symbol_descriptor().
+    - dmaengine: ti: edma: fix OF node reference leaks in edma_driver
+    - net: fec: implement TSO descriptor cleanup
+    - PM: hibernate: Add error handling for syscore_suspend()
+    - perf trace: Fix runtime error of index out of bounds
+    - vsock: Allow retrying on connect() failure
+    - net: sh_eth: Fix missing rtnl lock in suspend/resume path
+    - genksyms: fix memory leak when the same symbol is added from source
+    - genksyms: fix memory leak when the same symbol is read from *.symref file
+    - hexagon: fix using plain integer as NULL pointer warning in cmpxchg
+    - hexagon: Fix unbalanced spinlock in die()
+    - NFSD: Reset cb_seq_status after NFS4ERR_DELAY
+    - ktest.pl: Check kernelrelease return in get_version
+    - drivers/card_reader/rtsx_usb: Restore interrupt based detection
+    - usb: typec: tcpm: set SRC_SEND_CAPABILITIES timeout to PD_T_SENDER_RESPONSE
+    - btrfs: output the reason for open_ctree() failure
+    - btrfs: convert BUG_ON in btrfs_reloc_cow_block() to proper error handling
+    - sched: Don't try to catch up excess steal time.
+    - x86/amd_nb: Restrict init function to AMD-based systems
+    - tun: fix group permission check
+    - mmc: core: Respect quirk_max_rate for non-UHS SDIO card
+    - mfd: lpc_ich: Add another Gemini Lake ISA bridge PCI device-id
+    - HID: Wacom: Add PCI Wacom device support
+    - APEI: GHES: Have GHES honor the panic= setting
+    - x86/mm: Don't disable PCID when INVLPG has been fixed by microcode
+    - spi-mxs: Fix chipselect glitch
+    - nilfs2: move page release outside of nilfs_delete_entry and nilfs_set_link
+    - nilfs2: eliminate staggered calls to kunmap in nilfs_rename
+    - media: uvcvideo: Only save async fh if success
+    - kbuild: userprogs: use correct lld when linking through clang
+    - tasklet: Introduce new initialization API
+    - net: usb: rtl8150: use new tasklet API
+    - usb: xhci: Add timeout argument in address_device USB HCD callback
+    - nvme: handle connectivity loss in nvme_set_queue_count
+    - firmware: iscsi_ibft: fix ISCSI_IBFT Kconfig entry
+    - gpu: drm_dp_cec: fix broken CEC adapter properties check
+    - tg3: Disable tg3 PCIe AER on system reboot
+    - udp: gso: do not drop small packets when PMTU reduces
+    - tun: revert fix group permission check
+    - cpufreq: s3c64xx: Fix compilation warning
+    - leds: lp8860: Write full EEPROM, not only half of it
+    - s390/futex: Fix FUTEX_OP_ANDN implementation
+    - m68k: vga: Fix I/O defines
+    - arm64: dts: rockchip: increase gmac rx_delay on rk3399-puma
+    - KVM: s390: vsie: fix some corner-cases when grabbing vsie pages
+    - drm/komeda: Add check for komeda_get_layer_fourcc_list()
+    - clk: qcom: clk-alpha-pll: fix alpha mode configuration
+    - clk: qcom: clk-rpmh: prevent integer overflow in recalc_rate
+    - perf bench: Fix undefined behavior in cmpworker()
+    - of: Correct child specifier used as input of the 2nd nexus node
+    - of: Fix of_find_node_opts_by_path() handling of alias+path+options
+    - of: reserved-memory: Fix using wrong number of cells to get property
+      'alignment'
+    - HID: hid-sensor-hub: don't use stale platform-data on remove
+    - usb: gadget: f_tcm: Translate error to sense
+    - usb: gadget: f_tcm: Decrement command ref count on cleanup
+    - usb: gadget: f_tcm: ep_autoconfig with fullspeed endpoint
+    - usb: gadget: f_tcm: Don't prepare BOT write request twice
+    - serial: sh-sci: Drop __initdata macro for port_cfg
+    - serial: sh-sci: Do not probe the serial port if its slot in sci_ports[] is
+      in use
+    - powerpc/pseries/eeh: Fix get PE state translation
+    - kbuild: Move -Wenum-enum-conversion to W=2
+    - soc: qcom: smem_state: fix missing of_node_put in error path
+    - media: ov5640: fix get_light_freq on auto
+    - media: uvcvideo: Fix event flags in uvc_ctrl_send_events
+    - media: uvcvideo: Remove redundant NULL assignment
+    - crypto: qce - fix goto jump in error path
+    - crypto: qce - unregister previously registered algos in error path
+    - nvmem: core: improve range check for nvmem_cell_write()
+    - vfio/platform: check the bounds of read/write syscalls
+    - ocfs2: fix incorrect CPU endianness conversion causing mount failure
+    - mtd: onenand: Fix uninitialized retlen in do_otp_read()
+    - misc: fastrpc: Fix registered buffer page address
+    - net/ncsi: wait for the last response to Deselect Package before configuring
+      channel
+    - MIPS: ftrace: Declare ftrace_get_parent_ra_addr() as static
+    - ocfs2: check dir i_size in ocfs2_find_entry
+    - ndisc: ndisc_send_redirect() must use dev_get_by_index_rcu()
+    - gpio: bcm-kona: Fix GPIO lock/unlock for banks above bank 0
+    - gpio: bcm-kona: Make sure GPIO bits are unlocked when requesting IRQ
+    - gpio: bcm-kona: Add missing newline to dev_err format string
+    - xen: remove a confusing comment on auto-translated guest I/O
+    - x86/xen: allow larger contiguous memory regions in PV guests
+    - media: cxd2841er: fix 64-bit division on gcc-9
+    - vfio/pci: Enable iowrite64 and ioread64 for vfio pci
+    - Grab mm lock before grabbing pt lock
+    - ASoC: Intel: bytcr_rt5640: Add DMI quirk for Vexia Edu Atla 10 tablet 5V
+    - usb: roles: set switch registered flag early on
+    - usb: gadget: udc: renesas_usb3: Fix compiler warning
+    - usb: dwc2: gadget: remove of_node reference upon udc_stop
+    - USB: pci-quirks: Fix HCCPARAMS register error for LS7A EHCI
+    - USB: quirks: add USB_QUIRK_NO_LPM quirk for Teclast dist
+    - USB: Add USB_QUIRK_NO_LPM quirk for sony xperia xz1 smartphone
+    - USB: cdc-acm: Fill in Renesas R-Car D3 USB Download mode quirk
+    - usb: cdc-acm: Fix handling of oversized fragments
+    - USB: serial: option: add MeiG Smart SLM828
+    - USB: serial: option: add Telit Cinterion FN990B compositions
+    - USB: serial: option: fix Telit Cinterion FN990A name
+    - USB: serial: option: drop MeiG Smart defines
+    - can: c_can: fix unbalanced runtime PM disable in error path
+    - can: j1939: j1939_sk_send_loop(): fix unable to send messages with data
+      length zero
+    - alpha: make stack 16-byte aligned (most cases)
+    - serial: 8250: Fix fifo underflow on flush
+    - alpha: align stack for page fault and user unaligned trap handlers
+    - gpio: stmpe: Check return value of stmpe_reg_read in
+      stmpe_gpio_irq_sync_unlock
+    - regmap-irq: Add missing kfree()
+    - net: treat possible_net_t net pointer as an RCU one and add read_pnet_rcu()
+    - net: add dev_net_rcu() helper
+    - ipv4: use RCU protection in rt_is_expired()
+    - ipv4: use RCU protection in inet_select_addr()
+    - neighbour: delete redundant judgment statements
+    - alpha: replace hardcoded stack offsets with autogenerated ones
+    - nilfs2: do not output warnings when clearing dirty buffers
+    - can: ems_pci: move ASIX AX99100 ids to pci_ids.h
+    - serial: 8250_pci: add support for ASIX AX99100
+    - parport_pc: add support for ASIX AX99100
+    - x86/i8253: Disable PIT timer 0 when not in use
+    - Revert "btrfs: avoid monopolizing a core when activating a swap file"
+    - btrfs: avoid monopolizing a core when activating a swap file
+    - vlan: introduce vlan_dev_free_egress_priority
+    - vlan: move dev_put into vlan_dev_uninit
+    - scsi: storvsc: Set correct data length for sending SCSI command without
+      payload
+    - crypto: testmgr - fix wrong key length for pkcs1pad
+    - crypto: testmgr - Fix wrong test case of RSA
+    - crypto: testmgr - fix version number of RSA tests
+    - crypto: testmgr - populate RSA CRT parameters in RSA test vectors
+    - crypto: testmgr - some more fixes to RSA test vectors
+    - mm: update mark_victim tracepoints fields
+    - usb: dwc3: Increase DWC3 controller halt timeout
+    - usb: dwc3: Fix timeout issue during controller enter/exit from halt state
+    - usb/gadget: f_midi: convert tasklets to use new tasklet_setup() API
+    - usb/gadget: f_midi: Replace tasklet with work
+    - powerpc/64s/mm: Move __real_pte stubs into hash-4k.h
+    - powerpc/64s: Rewrite __real_pte() and __rpte_to_hidx() as static inline
+    - ALSA: hda/realtek - Add type for ALC287
+    - ALSA: hda/realtek: Fixup ALC225 depop procedure
+    - geneve: Suppress list corruption splat in geneve_destroy_tunnels().
+    - net: extract port range fields from fl_flow_key
+    - flow_dissector: Fix handling of mixed port and port-range keys
+    - flow_dissector: Fix port range key handling in BPF conversion
+    - power: supply: da9150-fg: fix potential overflow
+    - ALSA: hda/conexant: Add quirk for HP ProBook 450 G4 mute LED
+    - acct: block access to kernel internal filesystems
+    - batman-adv: Ignore neighbor throughput metrics in error case
+    - sunrpc: suppress warnings for unused procfs functions
+    - net: loopback: Avoid sending IP packets without an Ethernet header
+    - net: cadence: macb: Synchronize stats calculations
+    - ASoC: es8328: fix route from DAC to output
+    - ipvs: Always clear ipvs_property flag in skb_scrub_packet()
+    - net: mvpp2: cls: Fixed Non IP flow, with vlan tag flow defination.
+    - x86/CPU: Fix warm boot hang regression on AMD SC1100 SoC systems
+    - ftrace: Avoid potential division by zero in function_stat_show()
+    - perf/core: Fix low freq setting via IOC_PERIOD
+    - phy: tegra: xusb: reset VBUS & ID OVERRIDE
+    - phy: exynos5-usbdrd: fix MPLL_MULTIPLIER and SSC_REFCLKSEL masks in refclk
+    - kernel/acct.c: use #elif instead of #end and #elif
+    - kernel/acct.c: use dedicated helper to access rlimit values
+    - drm/amdgpu: skip BAR resizing if the bios already did it
+    - drm/amdgpu: Check extended configuration space register when system uses
+      large bar
+    - drm/amdgpu: disable BAR resize on Dell G5 SE
+    - Revert "of: reserved-memory: Fix using wrong number of cells to get property
+      'alignment'"
+    - HID: appleir: Fix potential NULL dereference at raw event handle
+    - ALSA: hda: intel: Add Dell ALC3271 to power_save denylist
+    - ALSA: hda/realtek: update ALC222 depop optimize
+    - drm/radeon: Fix rs400_gpu_init for ATI mobility radeon Xpress 200M
+    - platform/x86: thinkpad_acpi: Add battery quirk for ThinkPad X131e
+    - x86/cacheinfo: Validate CPUID leaf 0x2 EDX output
+    - x86/cpu: Validate CPUID leaf 0x2 EDX output
+    - x86/cpu: Properly parse CPUID leaf 0x2 TLB descriptor 0x63
+    - wifi: cfg80211: regulatory: improve invalid hints checking
+    - wifi: nl80211: reject cooked mode if it is set along with other flags
+    - rapidio: add check for rio_add_net() in rio_scan_alloc_net()
+    - rapidio: fix an API misues when rio_add_net() fails
+    - mm/page_alloc: fix uninitialized variable
+    - wifi: iwlwifi: limit printed string from FW file
+    - HID: google: fix unused variable warning under !CONFIG_ACPI
+    - HID: intel-ish-hid: Fix use-after-free issue in ishtp_hid_remove()
+    - net: gso: fix ownership in __udp_gso_segment
+    - caif_virtio: fix wrong pointer check in cfv_probe()
+    - hwmon: (pmbus) Initialise page count in pmbus_identify()
+    - hwmon: (ntc_thermistor) Fix the ncpXXxh103 sensor table
+    - hwmon: (ad7314) Validate leading zero bits and return error
+    - llc: do not use skb_get() before dev_queue_xmit()
+    - hwmon: fix a NULL vs IS_ERR_OR_NULL() check in xgene_hwmon_probe()
+    - drm/sched: Fix preprocessor guard
+    - be2net: fix sleeping while atomic bugs in be_ndo_bridge_getlink
+    - ppp: Fix KMSAN uninit-value warning with bpf
+    - vlan: enforce underlying device type
+    - net-timestamp: support TCP GSO case for a few missing flags
+    - net: ipv6: fix dst ref loop in ila lwtunnel
+    - net: ipv6: fix missing dst ref drop in ila lwtunnel
+    - gpio: rcar: Fix missing of_node_put() call
+    - Revert "drivers/card_reader/rtsx_usb: Restore interrupt based detection"
+    - usb: renesas_usbhs: Call clk_put()
+    - usb: renesas_usbhs: Use devm_usb_get_phy()
+    - usb: quirks: Add DELAY_INIT and NO_LPM for Prolific Mass Storage Card Reader
+    - usb: renesas_usbhs: Flush the notify_hotplug_work
+    - usb: atm: cxacru: fix a flaw in existing endpoint checks
+    - usb: typec: ucsi: increase timeout for PPM reset operations
+    - usb: typec: tcpci_rt1711h: Unmask alert interrupts to fix functionality
+    - usb: gadget: Set self-powered based on MaxPower and bmAttributes
+    - usb: gadget: Fix setting self-powered state on suspend
+    - usb: gadget: Check bmAttributes only if configuration is valid
+    - xhci: pci: Fix indentation in the PCI device ID definitions
+    - intel_th: pci: Add Arrow Lake support
+    - intel_th: pci: Add Panther Lake-H support
+    - intel_th: pci: Add Panther Lake-P/U support
+    - slimbus: messaging: Free transaction ID in delayed interrupt scenario
+    - eeprom: digsy_mtc: Make GPIO lookup table match the device
+    - Linux 5.4.291
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-26982
+    - Squashfs: check the inode number is not the invalid value of zero
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21846
+    - acct: perform last write from workqueue
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21862
+    - drop_monitor: fix incorrect initialization order
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58090
+    - sched/core: Prevent rescheduling when interrupts are disabled
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21877
+    - usbnet: gl620a: fix endpoint checking in genelink_bind()
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21823
+    - batman-adv: Drop unmanaged ELP metric worker
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21848
+    - nfp: bpf: Add check for nfp_app_ctrl_msg_alloc()
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21871
+    - tee: optee: Fix supplicant wait loop
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21865
+    - gtp: Suppress list corruption splat in gtp_net_exit_batch_rtnl().
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21858
+    - geneve: Fix use-after-free in geneve_find_dev().
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21866
+    - powerpc/code-patching: Fix KASAN hit by not flagging text patching area as
+      VM_ALLOC
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21859
+    - USB: gadget: f_midi: f_midi_complete to call queue_work
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-57977
+    - memcg: fix soft lockup in the OOM process
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-50055
+    - driver core: bus: Fix double free in driver API bus_register()
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-57979
+    - pps: Fix a use-after-free
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21811
+    - nilfs2: protect access to buffers with no active references
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21722
+    - nilfs2: do not force clear folio if buffer is referenced
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21760
+    - ndisc: extend RCU protection in ndisc_send_skb()
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21761
+    - openvswitch: use RCU protection in ovs_vport_cmd_fill_info()
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21762
+    - arp: use RCU protection in arp_xmit()
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21763
+    - neighbour: use RCU protection in __neigh_notify()
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21764
+    - ndisc: use RCU protection in ndisc_alloc_skb()
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21765
+    - ipv6: use RCU protection in ip6_default_advmss()
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21772
+    - partitions: mac: fix handling of bogus partition table
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21704
+    - usb: cdc-acm: Check control transfer buffer size before access
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21776
+    - USB: hub: Ignore non-compliant devices with too many configs or interfaces
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21835
+    - usb: gadget: f_midi: fix MIDI Streaming descriptor lengths
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21781
+    - batman-adv: fix panic during interface removal
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21782
+    - orangefs: fix a oob in orangefs_debug_write
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21785
+    - arm64: cacheinfo: Avoid out-of-bounds write to cacheinfo array
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21787
+    - team: better TEAM_OPTION_TYPE_STRING validation
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21791
+    - vrf: use RCU protection in l3mdev_l3_out()
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58020
+    - HID: multitouch: Add NULL check in mt_input_configured
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21814
+    - ptp: Ensure info->enable callback is always set
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21735
+    - NFC: nci: Add bounds checking in nci_hci_create_pipe()
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21736
+    - nilfs2: fix possible int overflows in nilfs_fiemap()
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58001
+    - ocfs2: handle a symlink read error correctly
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58007
+    - soc: qcom: socinfo: Avoid out of bounds read of serial number
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21744
+    - wifi: brcmfmac: fix NULL pointer dereference in brcmf_txfinalize()
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58009
+    - Bluetooth: L2CAP: handle NULL sock pointer in l2cap_sock_alloc
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58083
+    - KVM: Explicitly verify target vCPU is online in kvm_get_vcpu()
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58010
+    - binfmt_flat: Fix integer overflow bug on 32 bit systems
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21749
+    - net: rose: lock the socket in rose_bind()
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-57981
+    - usb: xhci: Fix NULL pointer dereference on certain command aborts
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21708
+    - net: usb: rtl8150: enable basic endpoint checking
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21647
+    - sched: sch_cake: add bounds checks to host bulk flow fairness counts
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58002
+    - media: uvcvideo: Remove dangling pointers
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21721
+    - nilfs2: handle errors that nilfs_prepare_chunk() may return
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58085
+    - tomoyo: don't emit warning in tomoyo_write_control()
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58014
+    - wifi: brcmsmac: add gain range check to wlc_phy_iqcal_gainparams_nphy()
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58017
+    - printk: Fix signed integer overflow when defining LOG_BUF_LEN_MAX
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21753
+    - btrfs: fix use-after-free when attempting to join an aborted transaction
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58055
+    - usb: gadget: f_tcm: Don't free command immediately
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-57980
+    - media: uvcvideo: Fix double free in error path
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-57986
+    - HID: core: Fix assumption that Resolution Multipliers must be in Logical
+      Collections
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21715
+    - net: davicom: fix UAF in dm9000_drv_remove
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21718
+    - net: rose: fix timer races against user threads
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21719
+    - ipmr: do not call mr_mfc_uses_dev() for unres entries
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58058
+    - ubifs: skip dumping tnc tree when zroot is null
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58069
+    - rtc: pcf85063: fix potential OOB write in PCF85063 NVMEM read
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-57973
+    - rdma/cxgb4: Prevent potential integer overflow on 32bit
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21728
+    - bpf: Send signals asynchronously if !preemptible
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21806
+    - net: let net.core.dev_weight always be non-zero
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58071
+    - team: prevent adding a device which is already a team device lower
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58063
+    - wifi: rtlwifi: fix memory leaks and invalid access at probe error path
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58072
+    - wifi: rtlwifi: remove unused check_buddy_priv
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58051
+    - ipmi: ipmb: Add check devm_kasprintf() returned value
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58052
+    - drm/amdgpu: Fix potential NULL pointer dereference in
+      atomctrl_get_smc_sclk_range_table
+
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21731
+    - nbd: don't allow reconnect after disconnect
+
+  * CVE-2024-26996
+    - usb: gadget: f_ncm: Fix UAF ncm object at re-bind after usb ep transport
+      error
+
+  * CVE-2023-52664
+    - net: atlantic: eliminate double free in error handling logic
+
+  * CVE-2024-26689
+    - ceph: prevent use-after-free in encode_cap_msg()
+
+  * CVE-2023-52927
+    - netfilter: allow exp not to be removed in nf_ct_find_expectation
+
+ -- Mehmet Basaran <mehmet.basaran@canonical.com>  Fri, 11 Apr 2025 22:12:36 +0300
+
+linux (5.4.0-214.234) focal; urgency=medium
+
+  * focal/linux: 5.4.0-214.234 -proposed tracker (LP: #2102635)
+
+  * CVE-2024-50256
+    - netfilter: nf_reject_ipv6: fix potential crash in nf_send_reset6()
+
+  * CVE-2025-21702
+    - pfifo_tail_enqueue: Drop new packet when sch->limit == 0
+
+  * CVE-2025-21703
+    - netem: Update sch->q.qlen before qdisc_tree_reduce_backlog()
+
+  * CVE-2024-26915
+    - drm/amdgpu: Reset IH OVERFLOW_CLEAR bit
+
+  * CVE-2025-21700
+    - net: sched: Disallow replacing of child qdisc from one parent to another
+
+  * CVE-2024-46826
+    - ELF: fix kernel.randomize_va_space double read
+
+  * CVE-2024-56651
+    - can: hi311x: hi3110_can_ist(): fix potential use-after-free
+
+  * CVE-2024-53237
+    - driver core: Introduce device_find_any_child() helper
+    - Bluetooth: fix use-after-free in device_for_each_child()
+
+  * CVE-2024-35958
+    - net: ena: Fix incorrect descriptor free behavior
+
+  * CVE-2024-49974
+    - NFSD: Limit the number of concurrent async COPY operations
+
+  * CVE-2021-47119
+    - ext4: fix memory leak in ext4_fill_super
+
+  * CVE-2024-56658
+    - net: defer final 'struct net' free in netns dismantle
+
+  * CVE-2024-35864
+    - smb: client: fix potential UAF in smb2_is_valid_lease_break()
+
+  * CVE-2024-35864/CVE-2024-26928
+    - smb: client: fix potential UAF in cifs_debug_files_proc_show()
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Fri, 14 Mar 2025 15:42:15 +0100
+
+linux (5.4.0-211.231) focal; urgency=medium
+
+  * focal/linux: 5.4.0-211.231 -proposed tracker (LP: #2101996)
+
+  * cve-2018-5803 kernel panic (LP: #2101091)
+    - SAUCE: sctp: sysctl: pass right argument to container_of
+
+ -- Mehmet Basaran <mehmet.basaran@canonical.com>  Tue, 11 Mar 2025 18:01:48 +0300
+
+linux (5.4.0-210.230) focal; urgency=medium
+
+  * focal/linux: 5.4.0-210.230 -proposed tracker (LP: #2098353)
+
+  * Focal update: v5.4.290 upstream stable release (LP: #2098439)
+    - jbd2: flush filesystem device before updating tail sequence
+    - dm array: fix releasing a faulty array block twice in dm_array_cursor_end
+    - dm array: fix unreleased btree blocks on closing a faulty array cursor
+    - dm array: fix cursor index when skipping across block boundaries
+    - ieee802154: ca8210: Add missing check for kfifo_alloc() in ca8210_probe()
+    - net: 802: LLC+SNAP OID:PID lookup on start of skb data
+    - tcp/dccp: complete lockless accesses to sk->sk_max_ack_backlog
+    - tcp/dccp: allow a connection when sk_max_ack_backlog is zero
+    - net_sched: cls_flow: validate TCA_FLOW_RSHIFT attribute
+    - tls: Fix tls_sw_sendmsg error handling
+    - dm thin: make get_first_thin use rcu-safe list first function
+    - sctp: sysctl: cookie_hmac_alg: avoid using current->nsproxy
+    - sctp: sysctl: auth_enable: avoid using current->nsproxy
+    - drm/amd/display: Add check for granularity in dml ceil/floor helpers
+    - ACPI: resource: Add TongFang GM5HG0A to irq1_edge_low_force_override[]
+    - ACPI: resource: Add Asus Vivobook X1504VAP to irq1_level_low_skip_override[]
+    - drm/amd/display: increase MAX_SURFACES to the value supported by hw
+    - USB: serial: option: add MeiG Smart SRM815
+    - USB: serial: option: add Neoway N723-EA support
+    - staging: iio: ad9834: Correct phase range check
+    - staging: iio: ad9832: Correct phase range check
+    - usb-storage: Add max sectors quirk for Nokia 208
+    - USB: serial: cp210x: add Phoenix Contact UPS Device
+    - usb: gadget: u_serial: Disable ep before setting port to null to fix the
+      crash caused by port being null
+    - USB: usblp: return error when setting unsupported protocol
+    - USB: core: Disable LPM only for non-suspended ports
+    - usb: fix reference leak in usb_new_device()
+    - usb: gadget: f_fs: Remove WARN_ON in functionfs_bind
+    - iio: pressure: zpa2326: fix information leak in triggered buffer
+    - iio: dummy: iio_simply_dummy_buffer: fix information leak in triggered
+      buffer
+    - iio: light: vcnl4035: fix information leak in triggered buffer
+    - iio: imu: kmx61: fix information leak in triggered buffer
+    - iio: adc: ti-ads8688: fix information leak in triggered buffer
+    - iio: gyro: fxas21002c: Fix missing data update in trigger handler
+    - iio: adc: ti-ads124s08: Use gpiod_set_value_cansleep()
+    - iio: adc: at91: call input_free_device() on allocated iio_dev
+    - iio: inkern: call iio_device_put() only on mapped devices
+    - arm64: dts: rockchip: fix defines in pd_vio node for rk3399
+    - arm64: dts: rockchip: fix pd_tcpc0 and pd_tcpc1 node position on rk3399
+    - arm64: dts: rockchip: add #power-domain-cells to power domain nodes
+    - arm64: dts: rockchip: add hevc power domain clock to rk3328
+    - phy: core: fix code style in devm_of_phy_provider_unregister
+    - phy: core: Fix that API devm_of_phy_provider_unregister() fails to
+      unregister the phy provider
+    - ocfs2: correct return value of ocfs2_local_free_info()
+    - ocfs2: fix slab-use-after-free due to dangling pointer dqi_priv
+    - sctp: sysctl: rto_min/max: avoid using current->nsproxy
+    - net: ethernet: ti: cpsw_ale: Fix cpsw_ale_get_field()
+    - net: net_namespace: Optimize the code
+    - net: add exit_batch_rtnl() method
+    - gtp: use exit_batch_rtnl() method
+    - gtp: Use for_each_netdev_rcu() in gtp_genl_dump_pdp().
+    - gtp: Destroy device along with udp socket's netns dismantle.
+    - nfp: bpf: prevent integer overflow in nfp_bpf_event_output()
+    - drm/v3d: Ensure job pointer is set to NULL after job completion
+    - i2c: mux: demux-pinctrl: check initial mux selection, too
+    - mac802154: check local interfaces before deleting sdata list
+    - hfs: Sanity check the root record
+    - kheaders: Ignore silly-rename files
+    - poll_wait: add mb() to fix theoretical race between waitqueue_active() and
+      .poll()
+    - nvmet: propagate npwg topology
+    - net: ethernet: xgbe: re-add aneg to supported features in PHY quirks
+    - fs/proc: fix softlockup in __read_vmcore (part 2)
+    - irqchip/gic-v3: Handle CPU_PM_ENTER_FAILED correctly
+    - hrtimers: Handle CPU state correctly on hotplug
+    - ipv6: avoid possible NULL deref in rt6_uncached_list_flush_dev()
+    - scsi: sg: Fix slab-use-after-free read in sg_release()
+    - net: fix data-races around sk->sk_forward_alloc
+    - ASoC: wm8994: Add depends on MFD core
+    - scsi: iscsi: Fix redundant response for ISCSI_UEVENT_GET_HOST_STATS request
+    - irqchip/sunxi-nmi: Add missing SKIP_WAKE flag
+    - gfs2: Truncate address space when flipping GFS2_DIF_JDATA flag
+    - m68k: Update ->thread.esp0 before calling syscall_trace() in ret_from_signal
+    - m68k: Add missing mmap_read_lock() to sys_cacheflush()
+    - signal/m68k: Use force_sigsegv(SIGSEGV) in fpsp040_die
+    - net: xen-netback: hash.c: Use built-in RCU list checking
+    - net/xen-netback: prevent UAF in xenvif_flush_hash()
+    - vfio/platform: check the bounds of read/write syscalls
+    - ext4: avoid ext4_error()'s caused by ENOMEM in the truncate path
+    - ext4: fix slab-use-after-free in ext4_split_extent_at()
+    - USB: serial: quatech2: fix null-ptr-deref in qt2_process_read_urb()
+    - Revert "usb: gadget: u_serial: Disable ep before setting port to null to fix
+      the crash caused by port being null"
+    - Input: atkbd - map F23 key to support default copilot shortcut
+    - Input: xpad - add unofficial Xbox 360 wireless receiver clone
+    - Input: xpad - add support for wooting two he (arm)
+    - drm/v3d: Assign job pointer to NULL before signaling the fence
+    - xhci: use pm_ptr() instead of #ifdef for CONFIG_PM conditionals
+    - Partial revert of xhci: use pm_ptr() instead #ifdef for CONFIG_PM
+      conditionals
+    - Linux 5.4.290
+
+  * CVE-2021-47219
+    - scsi: scsi_debug: Fix out-of-bound read in resp_report_tgtpgs()
+
+  * CVE-2024-49925
+    - fbdev: efifb: Register sysfs groups through driver core
+
+  * CVE-2024-56614
+    - xsk: fix OOB map writes when deleting elements
+
+  * net: stmmac: kernel continually prints wol unbalance irq warning
+    (LP: #2095376)
+    - net: stmmac: ethtool: Fixed calltrace caused by unbalanced disable_irq_wake
+      calls
+
+  * CVE-2024-44938
+    - jfs: Fix shift-out-of-bounds in dbDiscardAG
+
+  * CVE-2024-43900
+    - media: xc2028: avoid use-after-free in load_firmware_cb()
+
+  * Focal update: v5.4.289 upstream stable release (LP: #2095437)
+    - usb: dwc2: gadget: Don't write invalid mapped sg entries into dma_desc with
+      iommu enabled
+    - PCI/AER: Disable AER service on suspend
+    - ALSA: usb: Fix UBSAN warning in parse_audio_unit()
+    - PCI: Add ACS quirk for Broadcom BCM5760X NIC
+    - i2c: pnx: Fix timeout in wait functions
+    - drm/i915: Fix memory leak by correcting cache object name in error handler
+    - erofs: fix order >= MAX_ORDER warning due to crafted negative i_size
+    - erofs: fix incorrect symlink detection in fast symlink
+    - net/smc: check sndbuf_space again after NOSPACE flag is set in smc_poll
+    - ionic: use ee->offset when returning sprom data
+    - net: hinic: Fix cleanup in create_rxqs/txqs()
+    - net: ethernet: bgmac-platform: fix an OF node reference leak
+    - netfilter: ipset: Fix for recursive locking warning
+    - mmc: sdhci-tegra: Remove SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC quirk
+    - chelsio/chtls: prevent potential integer overflow on 32bit
+    - i2c: riic: Always round-up when calculating bus period
+    - efivarfs: Fix error on non-existent file
+    - USB: serial: option: add TCL IK512 MBIM & ECM
+    - USB: serial: option: add MeiG Smart SLM770A
+    - USB: serial: option: add Netprisma LCUK54 modules for WWAN Ready
+    - USB: serial: option: add MediaTek T7XX compositions
+    - USB: serial: option: add Telit FE910C04 rmnet compositions
+    - sh: clk: Fix clk_enable() to return 0 on NULL clk
+    - zram: refuse to use zero sized block device as backing device
+    - btrfs: tree-checker: reject inline extent items with 0 ref count
+    - NFS/pnfs: Fix a live lock between recalled layouts and layoutget
+    - of/irq: Fix using uninitialized variable @addr_len in API of_irq_parse_one()
+    - nilfs2: prevent use of deleted inode
+    - udmabuf: also check for F_SEAL_FUTURE_WRITE
+    - of: Fix error path in of_parse_phandle_with_args_map()
+    - of: Fix refcount leakage for OF node returned by __of_get_dma_parent()
+    - media: dvb-frontends: dib3000mb: fix uninit-value in dib3000_write_reg
+    - bpf: Check negative offsets in __bpf_skb_min_len()
+    - nfsd: restore callback functionality for NFSv4.0
+    - mtd: diskonchip: Cast an operand to prevent potential overflow
+    - phy: core: Fix an OF node refcount leakage in _of_phy_get()
+    - phy: core: Fix an OF node refcount leakage in of_phy_provider_lookup()
+    - phy: core: Fix that API devm_phy_put() fails to release the phy
+    - phy: core: Fix that API devm_phy_destroy() fails to destroy the phy
+    - dmaengine: mv_xor: fix child node refcount handling in early exit
+    - dmaengine: at_xdmac: avoid null_prt_deref in at_xdmac_prep_dma_memset
+    - mtd: rawnand: fix double free in atmel_pmecc_create_user()
+    - tracing/kprobe: Make trace_kprobe's module callback called after jump_label
+      update
+    - scsi: qla1280: Fix hw revision numbering for ISP1020/1040
+    - scsi: megaraid_sas: Fix for a potential deadlock
+    - regmap: Use correct format specifier for logging range errors
+    - platform/x86: asus-nb-wmi: Ignore unknown event 0xCF
+    - scsi: mpt3sas: Diag-Reset when Doorbell-In-Use bit is set during driver load
+      time
+    - virtio-blk: don't keep queue frozen during system suspend
+    - epoll: Add synchronous wakeup support for ep_poll_callback
+    - MIPS: Probe toolchain support of -msym32
+    - ipv6: use skb_expand_head in ip6_finish_output2
+    - ipv6: use skb_expand_head in ip6_xmit
+    - ipv6: fix possible UAF in ip6_finish_output2()
+    - bpf: fix recursive lock when verdict program return SK_PASS
+    - tracing: Constify string literal data member in struct trace_event_call
+    - btrfs: avoid monopolizing a core when activating a swap file
+    - ipv6: prevent possible UAF in ip6_xmit()
+    - selinux: ignore unknown extended permissions
+    - Drivers: hv: util: Avoid accessing a ringbuffer not initialized yet
+    - IB/mlx5: Introduce and use mlx5_core_is_vf()
+    - net/mlx5: Make API mlx5_core_is_ecpf accept const pointer
+    - RDMA/mlx5: Enforce same type port association for multiport RoCE
+    - RDMA/bnxt_re: Add check for path mtu in modify_qp
+    - RDMA/bnxt_re: Fix reporting hw_ver in query_device
+    - RDMA/bnxt_re: Fix max_qp_wrs reported
+    - drm: bridge: adv7511: Enable SPDIF DAI
+    - drm/bridge: adv7511_audio: Update Audio InfoFrame properly
+    - netrom: check buffer length before accessing it
+    - netfilter: Replace zero-length array with flexible-array member
+    - netfilter: nft_set_hash: unaligned atomic read on struct nft_set_ext
+    - net: llc: reset skb->transport_header
+    - ALSA: usb-audio: US16x08: Initialize array before use
+    - af_packet: fix vlan_get_tci() vs MSG_PEEK
+    - af_packet: fix vlan_get_protocol_dgram() vs MSG_PEEK
+    - ila: serialize calls to nf_register_net_hooks()
+    - wifi: mac80211: wake the queues in case of failure in resume
+    - sound: usb: format: don't warn that raw DSD is unsupported
+    - bpf: fix potential error return
+    - net: usb: qmi_wwan: add Telit FE910C04 compositions
+    - irqchip/gic: Correct declaration of *percpu_base pointer in union gic_base
+    - ARC: build: Try to guess GCC variant of cross compiler
+    - modpost: fix input MODULE_DEVICE_TABLE() built for 64-bit on 32-bit host
+    - modpost: fix the missed iteration for the max bit in do_input()
+    - RDMA/uverbs: Prevent integer overflow issue
+    - pinctrl: mcp23s08: Fix sleeping in atomic context due to regmap locking
+    - sky2: Add device ID 11ab:4373 for Marvell 88E8075
+    - net/sctp: Prevent autoclose integer overflow in sctp_association_init()
+    - drm: adv7511: Drop dsi single lane support
+    - mm: vmscan: account for free pages to prevent infinite Loop in
+      throttle_direct_reclaim()
+    - ftrace: use preempt_enable/disable notrace macros to avoid double fault
+    - Linux 5.4.289
+
+  * Focal update: v5.4.289 upstream stable release (LP: #2095437) //
+    CVE-2024-38588
+    - ftrace: Fix possible use-after-free issue in ftrace_location()
+
+  * Focal update: v5.4.288 upstream stable release (LP: #2095199)
+    - usb: host: max3421-hcd: Correctly abort a USB request.
+    - ata: sata_highbank: fix OF node reference leak in highbank_initialize_phys()
+    - usb: dwc2: hcd: Fix GetPortStatus & SetPortFeature
+    - usb: ehci-hcd: fix call balance of clocks handling routines
+    - usb: gadget: u_serial: Fix the issue that gs_start_io crashed due to
+      accessing null pointer
+    - xfs: don't drop errno values when we fail to ficlone the entire range
+    - bpf, sockmap: Fix update element with same
+    - batman-adv: Do not send uninitialized TT changes
+    - batman-adv: Remove uninitialized data in full table TT response
+    - batman-adv: Do not let TT changes list grows indefinitely
+    - tipc: fix NULL deref in cleanup_bearer()
+    - net: lapb: increase LAPB_HEADER_LEN
+    - ACPI: resource: Fix memory resource type union access
+    - qca_spi: Fix clock speed for multiple QCA7000
+    - qca_spi: Make driver probing reliable
+    - net/sched: netem: account for backlog updates from child qdisc
+    - ACPICA: events/evxfregn: don't release the ContextMutex that was never
+      acquired
+    - blk-iocost: clamp inuse and skip noops in __propagate_weights()
+    - blk-iocost: fix weight updates of inner active iocgs
+    - blk-iocost: Avoid using clamp() on inuse in __propagate_weights()
+    - KVM: arm64: Ignore PMCNTENSET_EL0 while checking for overflow status
+    - tracing/kprobes: Skip symbol counting logic for module symbols in
+      create_local_trace_kprobe()
+    - xen/netfront: fix crash when removing device
+    - ALSA: usb-audio: Fix a DMA to stack memory bug
+    - Linux 5.4.288
+
+  * Focal update: v5.4.287 upstream stable release (LP: #2095145)
+    - netlink: terminate outstanding dump on socket close
+    - net/mlx5: fs, lock FTE when checking if active
+    - net/mlx5e: kTLS, Fix incorrect page refcounting
+    - ocfs2: uncache inode which has failed entering the group
+    - KVM: VMX: Bury Intel PT virtualization (guest/host mode) behind
+      CONFIG_BROKEN
+    - nilfs2: fix null-ptr-deref in block_touch_buffer tracepoint
+    - ocfs2: fix UBSAN warning in ocfs2_verify_volume()
+    - nilfs2: fix null-ptr-deref in block_dirty_buffer tracepoint
+    - Revert "mmc: dw_mmc: Fix IDMAC operation with pages bigger than 4K"
+    - media: dvbdev: fix the logic when DVB_DYNAMIC_MINORS is not set
+    - kbuild: Use uname for LINUX_COMPILE_HOST detection
+    - mm: revert "mm: shmem: fix data-race in shmem_getattr()"
+    - ASoC: Intel: bytcr_rt5640: Add DMI quirk for Vexia Edu Atla 10 tablet
+    - mac80211: fix user-power when emulating chanctx
+    - selftests/watchdog-test: Fix system accidentally reset after watchdog-test
+    - ALSA: hda/realtek: Add subwoofer quirk for Infinix ZERO BOOK 13
+    - x86/amd_nb: Fix compile-testing without CONFIG_AMD_NB
+    - net: usb: qmi_wwan: add Quectel RG650V
+    - soc: qcom: Add check devm_kasprintf() returned value
+    - regulator: rk808: Add apply_bit for BUCK3 on RK809
+    - ASoC: stm: Prevent potential division by zero in stm32_sai_mclk_round_rate()
+    - ASoC: stm: Prevent potential division by zero in stm32_sai_get_clk_div()
+    - proc/softirqs: replace seq_printf with seq_put_decimal_ull_width
+    - ipmr: Fix access to mfc_cache_list without lock held
+    - cifs: Fix buffer overflow when parsing NFS reparse points
+    - NFSD: Force all NFSv4.2 COPY requests to be synchronous
+    - nvme: fix metadata handling in nvme-passthrough
+    - mips: asm: fix warning when disabling MIPS_FP_SUPPORT
+    - initramfs: avoid filename buffer overrun
+    - nvme-pci: fix freeing of the HMB descriptor table
+    - m68k: mvme147: Fix SCSI controller IRQ numbers
+    - m68k: mvme16x: Add and use "mvme16x.h"
+    - m68k: mvme147: Reinstate early console
+    - acpi/arm64: Adjust error handling procedure in gtdt_parse_timer_block()
+    - s390/syscalls: Avoid creation of arch/arch/ directory
+    - hfsplus: don't query the device logical block size multiple times
+    - firmware: google: Unregister driver_info on failure and exit in gsmi
+    - firmware: google: Unregister driver_info on failure
+    - EDAC/bluefield: Fix potential integer overflow
+    - EDAC/fsl_ddr: Fix bad bit shift operations
+    - crypto: pcrypt - Call crypto layer directly when padata_do_parallel() return
+      -EBUSY
+    - crypto: cavium - Fix the if condition to exit loop after timeout
+    - crypto: bcm - add error check in the ahash_hmac_init function
+    - crypto: cavium - Fix an error handling path in cpt_ucode_load_fw()
+    - time: Fix references to _msecs_to_jiffies() handling of values
+    - soc: ti: smartreflex: Use IRQF_NO_AUTOEN flag in request_irq()
+    - soc: qcom: geni-se: fix array underflow in geni_se_clk_tbl_get()
+    - mmc: mmc_spi: drop buggy snprintf()
+    - efi/tpm: Pass correct address to memblock_reserve
+    - tpm: fix signed/unsigned bug when checking event logs
+    - ARM: dts: cubieboard4: Fix DCDC5 regulator constraints
+    - regmap: irq: Set lockdep class for hierarchical IRQ domains
+    - firmware: arm_scpi: Check the DVFS OPP count returned by the firmware
+    - drm/mm: Mark drm_mm_interval_tree*() functions with __maybe_unused
+    - wifi: ath9k: add range check for conn_rsp_epid in htc_connect_service()
+    - drm/omap: Fix locking in omap_gem_new_dmabuf()
+    - wifi: p54: Use IRQF_NO_AUTOEN flag in request_irq()
+    - wifi: mwifiex: Use IRQF_NO_AUTOEN flag in request_irq()
+    - drm/imx/ipuv3: Use IRQF_NO_AUTOEN flag in request_irq()
+    - dt-bindings: vendor-prefixes: Add NeoFidelity, Inc
+    - ASoC: fsl_micfil: Drop unnecessary register read
+    - ASoC: fsl_micfil: do not define SHIFT/MASK for single bits
+    - ASoC: fsl_micfil: use GENMASK to define register bit fields
+    - ASoC: fsl_micfil: fix regmap_write_bits usage
+    - bpf: Fix the xdp_adjust_tail sample prog issue
+    - wifi: mwifiex: Fix memcpy() field-spanning write warning in
+      mwifiex_config_scan()
+    - drm/panfrost: Remove unused id_mask from struct panfrost_model
+    - drm/msm/adreno: Use IRQF_NO_AUTOEN flag in request_irq()
+    - drm/etnaviv: dump: fix sparse warnings
+    - drm/etnaviv: fix power register offset on GC300
+    - drm/etnaviv: hold GPU lock across perfmon sampling
+    - bpf, sockmap: Several fixes to bpf_msg_push_data
+    - bpf, sockmap: Several fixes to bpf_msg_pop_data
+    - bpf, sockmap: Fix sk_msg_reset_curr
+    - selftests: net: really check for bg process completion
+    - net: rfkill: gpio: Add check for clk_enable()
+    - ALSA: us122l: Use snd_card_free_when_closed() at disconnection
+    - ALSA: caiaq: Use snd_card_free_when_closed() at disconnection
+    - ALSA: 6fire: Release resources at card release
+    - netpoll: Use rcu_access_pointer() in netpoll_poll_lock
+    - trace/trace_event_perf: remove duplicate samples on the first tracepoint
+      event
+    - powerpc/vdso: Flag VDSO64 entry points as functions
+    - mfd: tps65010: Use IRQF_NO_AUTOEN flag in request_irq() to fix race
+    - mfd: da9052-spi: Change read-mask to write-mask
+    - mfd: intel_soc_pmic_bxtwc: Use dev_err_probe()
+    - mfd: intel_soc_pmic_bxtwc: Use IRQ domain for USB Type-C device
+    - mfd: intel_soc_pmic_bxtwc: Use IRQ domain for TMU device
+    - mfd: intel_soc_pmic_bxtwc: Use IRQ domain for PMIC devices
+    - cpufreq: loongson2: Unregister platform_driver on failure
+    - mtd: rawnand: atmel: Fix possible memory leak
+    - RDMA/bnxt_re: Check cqe flags to know imm_data vs inv_irkey
+    - mfd: rt5033: Fix missing regmap_del_irq_chip()
+    - scsi: bfa: Fix use-after-free in bfad_im_module_exit()
+    - scsi: fusion: Remove unused variable 'rc'
+    - scsi: qedf: Fix a possible memory leak in qedf_alloc_and_init_sb()
+    - scsi: qedi: Fix a possible memory leak in qedi_alloc_and_init_sb()
+    - ocfs2: fix uninitialized value in ocfs2_file_read_iter()
+    - powerpc/sstep: make emulate_vsx_load and emulate_vsx_store static
+    - fbdev/sh7760fb: Alloc DMA memory from hardware device
+    - fbdev: sh7760fb: Fix a possible memory leak in sh7760fb_alloc_mem()
+    - dt-bindings: clock: adi,axi-clkgen: convert old binding to yaml format
+    - dt-bindings: clock: axi-clkgen: include AXI clk
+    - clk: axi-clkgen: use devm_platform_ioremap_resource() short-hand
+    - clk: clk-axi-clkgen: make sure to enable the AXI bus clock
+    - perf cs-etm: Don't flush when packet_queue fills up
+    - perf probe: Correct demangled symbols in C++ program
+    - PCI: cpqphp: Use PCI_POSSIBLE_ERROR() to check config reads
+    - PCI: cpqphp: Fix PCIBIOS_* return value confusion
+    - m68k: mcfgpio: Fix incorrect register offset for CONFIG_M5441x
+    - m68k: coldfire/device.c: only build FEC when HW macros are defined
+    - perf trace: Do not lose last events in a race
+    - perf trace: Avoid garbage when not printing a syscall's arguments
+    - rpmsg: glink: Add TX_DATA_CONT command while sending
+    - rpmsg: glink: Send READ_NOTIFY command in FIFO full case
+    - rpmsg: glink: Fix GLINK command prefix
+    - rpmsg: glink: use only lower 16-bits of param2 for CMD_OPEN name length
+    - NFSD: Prevent NULL dereference in nfsd4_process_cb_update()
+    - NFSD: Cap the number of bytes copied by nfs4_reset_recoverydir()
+    - NFSD: Fix nfsd4_shutdown_copy()
+    - vfio/pci: Properly hide first-in-list PCIe extended capability
+    - power: supply: core: Remove might_sleep() from power_supply_put()
+    - net: usb: lan78xx: Fix memory leak on device unplug by freeing PHY device
+    - tg3: Set coherent DMA mask bits to 31 for BCM57766 chipsets
+    - net: usb: lan78xx: Fix refcounting and autosuspend on invalid WoL
+      configuration
+    - marvell: pxa168_eth: fix call balance of pep->clk handling routines
+    - net: stmmac: dwmac-socfpga: Set RX watchdog interrupt as broken
+    - ipmr: convert /proc handlers to rcu_read_lock()
+    - ipmr: fix tables suspicious RCU usage
+    - usb: using mutex lock and supporting O_NONBLOCK flag in iowarrior_read()
+    - usb: yurex: make waiting on yurex_write interruptible
+    - USB: chaoskey: fail open after removal
+    - USB: chaoskey: Fix possible deadlock chaoskey_list_lock
+    - misc: apds990x: Fix missing pm_runtime_disable()
+    - staging: greybus: uart: clean up TIOCGSERIAL
+    - apparmor: fix 'Do simple duplicate message elimination'
+    - usb: ehci-spear: fix call balance of sehci clk handling routines
+    - cgroup: Make operations on the cgroup root_list RCU safe
+    - cgroup: Move rcu_head up near the top of cgroup_root
+    - soc: qcom: socinfo: fix revision check in qcom_socinfo_probe()
+    - ALSA: usb-audio: Fix potential out-of-bound accesses for Extigy and Mbox
+      devices
+    - ext4: supress data-race warnings in ext4_free_inodes_{count,set}()
+    - ext4: fix FS_IOC_GETFSMAP handling
+    - jfs: xattr: check invalid xattr size more strictly
+    - ASoC: codecs: Fix atomicity violation in snd_soc_component_get_drvdata()
+    - PCI: Fix use-after-free of slot->bus on hot remove
+    - comedi: Flush partial mappings in error case
+    - tty: ldsic: fix tty_ldisc_autoload sysctl's proc_handler
+    - Bluetooth: Fix type of len in rfcomm_sock_getsockopt{,_old}()
+    - Revert "usb: gadget: composite: fix OS descriptors w_value logic"
+    - serial: sh-sci: Clean sci_ports[0] after at earlycon exit
+    - Revert "serial: sh-sci: Clean sci_ports[0] after at earlycon exit"
+    - spi: Fix acpi deferred irq probe
+    - ubi: wl: Put source PEB into correct list if trying locking LEB failed
+    - um: ubd: Do not use drvdata in release
+    - um: net: Do not use drvdata in release
+    - serial: 8250: omap: Move pm_runtime_get_sync
+    - um: vector: Do not use drvdata in release
+    - sh: cpuinfo: Fix a warning for CONFIG_CPUMASK_OFFSTACK
+    - arm64: tls: Fix context-switching of tpidrro_el0 when kpti is enabled
+    - block: fix ordering between checking BLK_MQ_S_STOPPED request adding
+    - HID: wacom: Interpret tilt data from Intuos Pro BT as signed values
+    - media: wl128x: Fix atomicity violation in fmc_send_cmd()
+    - ALSA: hda/realtek: Update ALC225 depop procedure
+    - ALSA: hda/realtek: Set PCBeep to default value for ALC274
+    - ALSA: hda/realtek: Fix Internal Speaker and Mic boost of Infinix Y4 Max
+    - ALSA: hda/realtek: Apply quirk for Medion E15433
+    - usb: dwc3: gadget: Fix checking for number of TRBs left
+    - lib: string_helpers: silence snprintf() output truncation warning
+    - NFSD: Prevent a potential integer overflow
+    - SUNRPC: make sure cache entry active before cache_show
+    - rpmsg: glink: Propagate TX failures in intentless mode as well
+    - um: Fix potential integer overflow during physmem setup
+    - um: Fix the return value of elf_core_copy_task_fpregs
+    - um/sysrq: remove needless variable sp
+    - um: add show_stack_loglvl()
+    - um: Clean up stacktrace dump
+    - um: Always dump trace for specified task in show_stack
+    - NFSv4.0: Fix a use-after-free problem in the asynchronous open()
+    - rtc: st-lpc: Use IRQF_NO_AUTOEN flag in request_irq()
+    - rtc: abx80x: Fix WDT bit position of the status register
+    - rtc: check if __rtc_read_time was successful in rtc_timer_do_work()
+    - ubifs: Correct the total block count by deducting journal reservation
+    - ubi: fastmap: Fix duplicate slab cache names while attaching
+    - ubifs: authentication: Fix use-after-free in ubifs_tnc_end_commit
+    - jffs2: fix use of uninitialized variable
+    - block: return unsigned int from bdev_io_min
+    - 9p/xen: fix init sequence
+    - 9p/xen: fix release of IRQ
+    - rtc: ab-eoz9: don't fail temperature reads on undervoltage notification
+    - modpost: remove incorrect code in do_eisa_entry()
+    - SUNRPC: correct error code comment in xs_tcp_setup_socket()
+    - SUNRPC: Replace internal use of SOCKWQ_ASYNC_NOSPACE
+    - sunrpc: clear XPRT_SOCK_UPD_TIMEOUT when reset transport
+    - sh: intc: Fix use-after-free bug in register_intc_controller()
+    - ASoC: fsl_micfil: fix the naming style for mask definition
+    - quota: flush quota_release_work upon quota writeback
+    - btrfs: ref-verify: fix use-after-free after invalid ref action
+    - media: i2c: tc358743: Fix crash in the probe error path when using polling
+    - media: ts2020: fix null-ptr-deref in ts2020_probe()
+    - media: venus: Fix pm_runtime_set_suspended() with runtime pm enabled
+    - media: gspca: ov534-ov772x: Fix off-by-one error in set_frame_rate()
+    - media: platform: allegro-dvt: Fix possible memory leak in
+      allocate_buffers_internal()
+    - ovl: Filter invalid inodes with missing lookup function
+    - ftrace: Fix regression with module command in stack_trace_filter
+    - clk: qcom: gcc-qcs404: fix initial rate of GPLL3
+    - ad7780: fix division by zero in ad7780_write_raw()
+    - util_macros.h: fix/rework find_closest() macros
+    - i3c: master: Fix miss free init_dyn_addr at i3c_master_put_i3c_addrs()
+    - dm thin: Add missing destroy_work_on_stack()
+    - nfsd: make sure exp active before svc_export_show
+    - nfsd: fix nfs4_openowner leak when concurrent nfsd4_open occur
+    - drm/etnaviv: flush shader L1 cache after user commandstream
+    - iTCO_wdt: mask NMI_NOW bit for update_no_reboot_bit() call
+    - watchdog: mediatek: Make sure system reset gets asserted in
+      mtk_wdt_restart()
+    - can: sun4i_can: sun4i_can_err(): call can_change_state() even if cf is NULL
+    - can: sun4i_can: sun4i_can_err(): fix {rx,tx}_errors statistics
+    - ipvs: fix UB due to uninitialized stack access in ip_vs_protocol_init()
+    - netfilter: x_tables: fix LED ID check in led_tg_check()
+    - net/sched: tbf: correct backlog statistic for GSO packets
+    - can: j1939: j1939_session_new(): fix skb reference counting
+    - net/ipv6: release expired exception dst cached in socket
+    - dccp: Fix memory leak in dccp_feat_change_recv
+    - tipc: add reference counter to bearer
+    - tipc: enable creating a "preliminary" node
+    - tipc: add new AEAD key structure for user API
+    - tipc: Fix use-after-free of kernel socket in cleanup_bearer().
+    - net/qed: allow old cards not supporting "num_images" to work
+    - igb: Fix potential invalid memory access in igb_init_module()
+    - netfilter: ipset: Hold module reference while requesting a module
+    - netfilter: nft_set_hash: skip duplicated elements pending gc run
+    - xen/xenbus: reference count registered modules
+    - xenbus/backend: Add memory pressure handler callback
+    - xenbus/backend: Protect xenbus callback with lock
+    - xen/xenbus: fix locking
+    - xen: Fix the issue of resource not being properly released in
+      xenbus_dev_probe()
+    - x86/asm: Reorder early variables
+    - crypto: x86/aegis128 - access 32-bit arguments as 32-bit
+    - gpio: grgpio: use a helper variable to store the address of ofdev->dev
+    - gpio: grgpio: Add NULL check in grgpio_probe
+    - drm/sti: Add __iomem for mixer_dbg_mxn's parameter
+    - tcp_bpf: Fix the sk_mem_uncharge logic in tcp_bpf_sendmsg
+    - spi: mpc52xx: Add cancel_work_sync before module remove
+    - ocfs2: free inode when ocfs2_get_init_inode() fails
+    - bpf: Handle BPF_EXIST and BPF_NOEXIST for LPM trie
+    - bpf: Fix exact match conditions in trie_get_next_key()
+    - HID: wacom: fix when get product name maybe null pointer
+    - tracing: Fix cmp_entries_dup() to respect sort() comparison rules
+    - ocfs2: update seq_file index in ocfs2_dlm_seq_next
+    - scsi: qla2xxx: Fix NVMe and NPIV connect issue
+    - scsi: qla2xxx: Supported speed displayed incorrectly for VPorts
+    - scsi: qla2xxx: Remove check req_sg_cnt should be equal to rsp_sg_cnt
+    - nilfs2: fix potential out-of-bounds memory access in nilfs_find_entry()
+    - bcache: revert replacing IS_ERR_OR_NULL with IS_ERR again
+    - dma-buf: fix dma_fence_array_signaled v4
+    - regmap: detach regmap from dev on regmap_exit
+    - mmc: core: Further prevent card detect during shutdown
+    - s390/cpum_sf: Handle CPU hotplug remove during sampling
+    - media: uvcvideo: Add a quirk for the Kaiweets KTI-W02 infrared camera
+    - media: cx231xx: Add support for Dexatek USB Video Grabber 1d19:6108
+    - drm: panel-orientation-quirks: Add quirk for AYA NEO 2 model
+    - drm/mcde: Enable module autoloading
+    - drm/radeon/r600_cs: Fix possible int overflow in r600_packet3_check()
+    - samples/bpf: Fix a resource leak
+    - net: fec_mpc52xx_phy: Use %pa to format resource_size_t
+    - net: ethernet: fs_enet: Use %pa to format resource_size_t
+    - net/sched: cbs: Fix integer overflow in cbs_set_port_rate()
+    - af_packet: avoid erroring out after sock_init_data() in packet_create()
+    - Bluetooth: L2CAP: do not leave dangling sk pointer on error in
+      l2cap_sock_create()
+    - net: af_can: do not leave a dangling sk pointer in can_create()
+    - net: ieee802154: do not leave a dangling sk pointer in ieee802154_create()
+    - net: inet: do not leave a dangling sk pointer in inet_create()
+    - net: inet6: do not leave a dangling sk pointer in inet6_create()
+    - wifi: ath5k: add PCI ID for SX76X
+    - wifi: ath5k: add PCI ID for Arcadyan devices
+    - jfs: array-index-out-of-bounds fix in dtReadFirst
+    - jfs: fix shift-out-of-bounds in dbSplit
+    - jfs: fix array-index-out-of-bounds in jfs_readdir
+    - jfs: add a check to prevent array-index-out-of-bounds in dbAdjTree
+    - drm/amdgpu: set the right AMDGPU sg segment limitation
+    - wifi: ipw2x00: libipw_rx_any(): fix bad alignment
+    - wifi: brcmfmac: Fix oops due to NULL pointer dereference in
+      brcmf_sdiod_sglist_rw()
+    - Bluetooth: btusb: Add RTL8852BE device 0489:e123 to device tables
+    - ASoC: hdmi-codec: reorder channel allocation list
+    - rocker: fix link status detection in rocker_carrier_init()
+    - net/neighbor: clear error in case strict check is not set
+    - netpoll: Use rcu_access_pointer() in __netpoll_setup
+    - tracing: Use atomic64_inc_return() in trace_clock_counter()
+    - leds: class: Protect brightness_show() with led_cdev->led_access mutex
+    - scsi: st: Don't modify unknown block number in MTIOCGET
+    - scsi: st: Add MTIOCGET and MTLOAD to ioctls allowed after device reset
+    - pinctrl: qcom-pmic-gpio: add support for PM8937
+    - nvdimm: rectify the illogical code within nd_dax_probe()
+    - f2fs: fix f2fs_bug_on when uninstalling filesystem call f2fs_evict_inode.
+    - PCI: Add 'reset_subordinate' to reset hierarchy below bridge
+    - PCI: Add ACS quirk for Wangxun FF5xxx NICs
+    - i3c: Use i3cdev->desc->info instead of calling i3c_device_get_info() to
+      avoid deadlock
+    - usb: chipidea: udc: handle USB Error Interrupt if IOC not set
+    - powerpc/prom_init: Fixup missing powermac #size-cells
+    - misc: eeprom: eeprom_93cx6: Add quirk for extra read clock cycle
+    - xdp: Simplify devmap cleanup
+    - bpf: fix OOB devmap writes when deleting elements
+    - Revert "unicode: Don't special case ignorable code points"
+    - perf/x86/intel/pt: Fix buffer full but size is 0 case
+    - KVM: arm64: vgic-its: Add a data length check in vgic_its_save_*
+    - KVM: arm64: vgic-its: Clear DTE when MAPD unmaps a device
+    - KVM: arm64: vgic-its: Clear ITE when DISCARD frees an ITE
+    - jffs2: Prevent rtime decompress memory corruption
+    - jffs2: Fix rtime decompressor
+    - ocfs2: Revert "ocfs2: fix the la space leak when unmounting an ocfs2 volume"
+    - modpost: Add .irqentry.text to OTHER_SECTIONS
+    - Revert "drm/amdgpu: add missing size check in amdgpu_debugfs_gprwave_read()"
+    - PCI: rockchip-ep: Fix address translation unit programming
+    - ALSA: usb-audio: Fix out of bounds reads when finding clock sources
+    - bpf, xdp: Update devmap comments to reflect napi/rcu usage
+    - Linux 5.4.287
+
+  * CVE-2024-23848
+    - media: cec: abort if the current transmit was canceled
+    - media: cec: core: avoid recursive cec_claim_log_addrs
+    - media: cec: core: avoid confusing "transmit timed out" message
+
+ -- Mehmet Basaran <mehmet.basaran@canonical.com>  Fri, 14 Feb 2025 16:51:18 +0300
+
+linux (5.4.0-208.228) focal; urgency=medium
+
+  * CVE-2025-0927
+    - SAUCE: fs: hfs/hfsplus: add key_len boundary check to hfs_bnode_read_key
+
+ -- Manuel Diewald <manuel.diewald@canonical.com>  Fri, 07 Feb 2025 18:31:32 +0100
+
+linux (5.4.0-207.227) focal; urgency=medium
+
+  * focal/linux: 5.4.0-207.227 -proposed tracker (LP: #2095347)
+
+  * Remove "ftrace: Fix possible use-after-free issue in ftrace_location()" bad
+    commit from focal (LP: #2095348)
+    - Revert "ftrace: Fix possible use-after-free issue in ftrace_location()"
+
+ -- Mehmet Basaran <mehmet.basaran@canonical.com>  Mon, 20 Jan 2025 18:03:51 +0300
+
+linux (5.4.0-206.226) focal; urgency=medium
+
+  * focal/linux: 5.4.0-206.226 -proposed tracker (LP: #2093785)
+
+  * nouveau keeps showing `disp: ctrl 00000080` and crippling the system
+    (LP: #2078011)
+    - drm/nouveau/disp/gv100-: halt NV_PDISP_FE_RM_INTR_STAT_CTRL_DISP_ERROR
+      storms
+    - drm/nouveau/kms/gv100-: move window ownership setup into modesetting path
+    - drm/nouveau/kms/gv100-: avoid sending a core update until the first modeset
+
+  * CVE-2024-43863
+    - drm/vmwgfx: Fix a deadlock in dma buf fence polling
+
+  * CVE-2024-40911
+    - wifi: cfg80211: Lock wiphy in cfg80211_get_station
+
+  * CVE-2024-35896
+    - netfilter: validate user input for expected length
+    - netfilter: complete validation of user input
+
+  * CVE-2023-52458
+    - block: add check that partition length needs to be aligned with block size
+
+  * kernel:nft "Could not process rule: Device or resource busy" on unreferenced
+    chain (LP: #2089699)
+    - SAUCE: netfilter: nf_tables: Fix EBUSY on deleting unreferenced chain
+
+  * CVE-2024-35887
+    - lockdep: Add preemption enabled/disabled assertion APIs
+    - timers: Don't block on ->expiry_lock for TIMER_IRQSAFE timers
+    - Documentation: Remove bogus claim about del_timer_sync()
+    - ARM: spear: Do not use timer namespace for timer_shutdown() function
+    - clocksource/drivers/arm_arch_timer: Do not use timer namespace for
+      timer_shutdown() function
+    - clocksource/drivers/sp804: Do not use timer namespace for timer_shutdown()
+      function
+    - timers: Get rid of del_singleshot_timer_sync()
+    - timers: Replace BUG_ON()s
+    - timers: Rename del_timer() to timer_delete()
+    - Documentation: Replace del_timer/del_timer_sync()
+    - timers: Silently ignore timers with a NULL function
+    - timers: Split [try_to_]del_timer[_sync]() to prepare for shutdown mode
+    - timers: Add shutdown mechanism to the internal functions
+    - timers: Provide timer_shutdown[_sync]()
+    - timers: Update the documentation to reflect on the new timer_shutdown() API
+    - ax25: fix use-after-free bugs caused by ax25_ds_del_timer
+
+  * CVE-2024-40965
+    - clk: Add a devm variant of clk_rate_exclusive_get()
+    - clk: Provide !COMMON_CLK dummy for devm_clk_rate_exclusive_get()
+    - i2c: lpi2c: Avoid calling clk_get_rate during transfer
+
+  * CVE-2024-40982
+    - ssb: Fix potential NULL pointer dereference in ssb_device_uevent()
+
+  * CVE-2024-41066
+    - ibmvnic: Add tx check to prevent skb leak
+
+  * CVE-2024-42252
+    - closures: Change BUG_ON() to WARN_ON()
+
+  * CVE-2024-46731
+    - drm/amd/pm: fix the Out-of-bounds read warning
+
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558)
+    - arm64: dts: rockchip: Fix rt5651 compatible value on rk3399-sapphire-
+      excavator
+    - arm64: dts: rockchip: Remove hdmi's 2nd interrupt on rk3328
+    - arm64: dts: rockchip: Fix bluetooth properties on Rock960 boards
+    - arm64: dts: rockchip: Remove #cooling-cells from fan on Theobroma lion
+    - ARM: dts: rockchip: fix rk3036 acodec node
+    - ARM: dts: rockchip: drop grf reference from rk3036 hdmi
+    - ARM: dts: rockchip: Fix the spi controller on rk3036
+    - ARM: dts: rockchip: Fix the realtek audio codec on rk3036-kylin
+    - enetc: simplify the return expression of enetc_vf_set_mac_addr()
+    - net: enetc: set MAC address to the VF net_device
+    - can: c_can: fix {rx,tx}_errors statistics
+    - media: stb0899_algo: initialize cfr before using it
+    - media: dvb_frontend: don't play tricks with underflow values
+    - media: adv7604: prevent underflow condition when reporting colorspace
+    - ALSA: firewire-lib: fix return value on fail in amdtp_tscm_init()
+    - pwm: imx-tpm: Use correct MODULO value for EPWM mode
+    - drm/amdgpu: prevent NULL pointer dereference if ATIF is not supported
+    - dm cache: correct the number of origin blocks to match the target length
+    - dm cache: optimize dirty bit checking with find_next_bit when resizing
+    - dm-unstriped: cast an operand to sector_t to prevent potential uint32_t
+      overflow
+    - mtd: rawnand: protect access to rawnand devices while in suspend
+    - spi: fix use-after-free of the add_lock mutex
+    - media: uvcvideo: Skip parsing frames of type UVC_VS_UNDEFINED in
+      uvc_parse_format
+    - fs/proc: fix compile warning about variable 'vmcore_mmap_ops'
+    - USB: serial: qcserial: add support for Sierra Wireless EM86xx
+    - USB: serial: option: add Fibocom FG132 0x0112 composition
+    - USB: serial: option: add Quectel RG650V
+    - irqchip/gic-v3: Force propagation of the active state with a read-back
+    - ALSA: usb-audio: Support jack detection on Dell dock
+    - ALSA: usb-audio: Add quirks for Dell WD19 dock
+    - NFSD: Fix NFSv4's PUTPUBFH operation
+    - ALSA: usb-audio: Add endianness annotations
+    - 9p: Avoid creating multiple slab caches with the same name
+    - HID: multitouch: Add quirk for HONOR MagicBook Art 14 touchpad
+    - bpf: use kvzmalloc to allocate BPF verifier environment
+    - sound: Make CONFIG_SND depend on INDIRECT_IOMEM instead of UML
+    - powerpc/powernv: Free name on error in opal_event_init()
+    - fs: Fix uninitialized value issue in from_kuid and from_kgid
+    - net: usb: qmi_wwan: add Fibocom FG132 0x0112 composition
+    - md/raid10: improve code of mrdev in raid10_sync_request
+    - mm: clarify a confusing comment for remap_pfn_range()
+    - mm: fix ambiguous comments for better code readability
+    - mm/memory.c: make remap_pfn_range() reject unaligned addr
+    - mm: add remap_pfn_range_notrack
+    - 9p: fix slab cache name creation for real
+    - Linux 5.4.286
+
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-47674
+    - mm: avoid leaving partial pfn mappings around in error case
+
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-38588
+    - ftrace: Fix possible use-after-free issue in ftrace_location()
+
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50265
+    - ocfs2: remove entry once instead of null-ptr-dereference in
+      ocfs2_xa_remove()
+
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50267
+    - USB: serial: io_edgeport: fix use after free in debug printk
+
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50269
+    - usb: musb: sunxi: Fix accessing an released usb phy
+
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2021-47469
+    - spi: Fix deadlock when adding SPI controllers on SPI buses
+
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50273
+    - btrfs: reinitialize delayed ref list after deleting it from the list
+
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-53066
+    - nfs: Fix KMSAN warning in decode_getfattr_attrs()
+
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50278
+    - dm cache: fix potential out-of-bounds access on the first resume
+
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50279
+    - dm cache: fix out-of-bounds access to the dirty bitset when resizing
+
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50282
+    - drm/amdgpu: add missing size check in amdgpu_debugfs_gprwave_read()
+
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50287
+    - media: v4l2-tpg: prevent the risk of a division by zero
+
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50290
+    - media: cx24116: prevent overflows on SNR calculus
+
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-53061
+    - media: s5p-jpeg: prevent buffer overflows
+
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-53063
+    - media: dvbdev: prevent the risk of out of memory access
+
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50296
+    - net: hns3: fix kernel crash when uninstalling driver
+
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50299
+    - sctp: properly validate chunk size in sctp_sf_ootb()
+
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50301
+    - security/keys: fix slab-out-of-bounds in key_task_permission
+
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50302
+    - HID: core: zero-initialize the report buffer
+
+  * Add list of source files to linux-buildinfo (LP: #2086606)
+    - [Packaging] Sort build dependencies alphabetically
+    - [Packaging] Add list of used source files to buildinfo package
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233)
+    - usbnet: ipheth: fix carrier detection in modes 1 and 4
+    - net: ethernet: use ip_hdrlen() instead of bit shift
+    - net: phy: vitesse: repair vsc73xx autonegotiation
+    - scripts: kconfig: merge_config: config files: add a trailing newline
+    - arm64: dts: rockchip: override BIOS_DISABLE signal via GPIO hog on RK3399
+      Puma
+    - ice: fix accounting for filters shared by multiple VSIs
+    - net/mlx5e: Add missing link modes to ptys2ethtool_map
+    - net: ftgmac100: Enable TX interrupt to avoid TX timeout
+    - soundwire: stream: Revert "soundwire: stream: fix programming slave ports
+      for non-continous port maps"
+    - selftests: breakpoints: Fix a typo of function name
+    - ASoC: allow module autoloading for table db1200_pids
+    - ALSA: hda/realtek - Fixed ALC256 headphone no sound
+    - ALSA: hda/realtek - FIxed ALC285 headphone no sound
+    - pinctrl: at91: make it work with current gpiolib
+    - microblaze: don't treat zero reserved memory regions as error
+    - net: ftgmac100: Ensure tx descriptor updates are visible
+    - wifi: iwlwifi: mvm: fix iwl_mvm_max_scan_ie_fw_cmd_room()
+    - ASoC: tda7419: fix module autoloading
+    - drm: komeda: Fix an issue related to normalized zpos
+    - spi: bcm63xx: Enable module autoloading
+    - x86/hyperv: Set X86_FEATURE_TSC_KNOWN_FREQ when Hyper-V provides frequency
+    - USB: serial: pl2303: add device id for Macrosilicon MS3020
+    - ACPI: PMIC: Remove unneeded check in tps68470_pmic_opregion_probe()
+    - wifi: ath9k: fix parameter check in ath9k_init_debug()
+    - wifi: ath9k: Remove error checks when creating debugfs entries
+    - fs: explicitly unregister per-superblock BDIs
+    - mount: warn only once about timestamp range expiration
+    - fs/namespace: fnic: Switch to use %ptTd
+    - mount: handle OOM on mnt_warn_timestamp_expiry
+    - can: j1939: use correct function name in comment
+    - netfilter: nf_tables: elements with timeout below CONFIG_HZ never expire
+    - netfilter: nf_tables: reject element expiration with no timeout
+    - netfilter: nf_tables: reject expiration higher than timeout
+    - wifi: cfg80211: fix UBSAN noise in cfg80211_wext_siwscan()
+    - wifi: cfg80211: fix two more possible UBSAN-detected off-by-one errors
+    - mac80211: parse radiotap header when selecting Tx queue
+    - Bluetooth: btusb: Fix not handling ZPL/short-transfer
+    - net: tipc: avoid possible garbage value
+    - block, bfq: choose the last bfqq from merge chain in bfq_setup_cooperator()
+    - block, bfq: don't break merge chain in bfq_split_bfqq()
+    - spi: ppc4xx: handle irq_of_parse_and_map() errors
+    - spi: ppc4xx: Avoid returning 0 when failed to parse and map IRQ
+    - ARM: dts: imx7d-zii-rmu2: fix Ethernet PHY pinctrl property
+    - ARM: versatile: fix OF node leak in CPUs prepare
+    - reset: berlin: fix OF node leak in probe() error path
+    - clocksource/drivers/qcom: Add missing iounmap() on errors in
+      msm_dt_timer_init()
+    - hwmon: (max16065) Fix overflows seen when writing limits
+    - mtd: slram: insert break after errors in parsing the map
+    - hwmon: (ntc_thermistor) fix module autoloading
+    - power: supply: axp20x_battery: allow disabling battery charging
+    - power: supply: axp20x_battery: Remove design from min and max voltage
+    - power: supply: max17042_battery: Fix SOC threshold calc w/ no current sense
+    - fbdev: hpfb: Fix an error handling path in hpfb_dio_probe()
+    - mtd: powernv: Add check devm_kasprintf() returned value
+    - drm/stm: Fix an error handling path in stm_drm_platform_probe()
+    - drm/amdgpu: Replace one-element array with flexible-array member
+    - drm/amdgpu: properly handle vbios fake edid sizing
+    - drm/radeon: Replace one-element array with flexible-array member
+    - drm/radeon: properly handle vbios fake edid sizing
+    - drm/rockchip: vop: Allow 4096px width scaling
+    - drm/rockchip: dw_hdmi: Fix reading EDID when using a forced mode
+    - drm/radeon/evergreen_cs: fix int overflow errors in cs track offsets
+    - drm/msm: Fix incorrect file name output in adreno_request_fw()
+    - drm/msm/a5xx: disable preemption in submits by default
+    - drm/msm/a5xx: properly clear preemption records on resume
+    - drm/msm/a5xx: fix races in preemption evaluation stage
+    - ipmi: docs: don't advertise deprecated sysfs entries
+    - drm/msm: fix %s null argument error
+    - drivers:drm:exynos_drm_gsc:Fix wrong assignment in gsc_bind()
+    - xen: use correct end address of kernel for conflict checking
+    - xen/swiotlb: add alignment check for dma buffers
+    - selftests/bpf: Fix compile error from rlim_t in sk_storage_map.c
+    - selftests/bpf: Fix compiling flow_dissector.c with musl-libc
+    - selftests/bpf: Fix compiling tcp_rtt.c with musl-libc
+    - selftests/bpf: Fix error compiling test_lru_map.c
+    - xz: cleanup CRC32 edits from 2018
+    - kthread: add kthread_work tracepoints
+    - kthread: fix task state in kthread worker if being frozen
+    - ext4: clear EXT4_GROUP_INFO_WAS_TRIMMED_BIT even mount with discard
+    - smackfs: Use rcu_assign_pointer() to ensure safe assignment in smk_set_cipso
+    - ext4: avoid negative min_clusters in find_group_orlov()
+    - ext4: return error on ext4_find_inline_entry
+    - nilfs2: determine empty node blocks as corrupted
+    - bpf: Fix bpf_strtol and bpf_strtoul helpers for 32bit
+    - perf sched timehist: Fix missing free of session in perf_sched__timehist()
+    - perf sched timehist: Fixed timestamp error when unable to confirm event
+      sched_in time
+    - perf time-utils: Fix 32-bit nsec parsing
+    - clk: rockchip: Set parent rate for DCLK_VOP clock on RK3228
+    - PCI: xilinx-nwl: Fix register misspelling
+    - pinctrl: single: fix missing error code in pcs_probe()
+    - clk: ti: dra7-atl: Fix leak of of_nodes
+    - pinctrl: mvebu: Fix devinit_dove_pinctrl_probe function
+    - watchdog: imx_sc_wdt: Don't disable WDT in suspend
+    - RDMA/hns: Optimize hem allocation performance
+    - riscv: Fix fp alignment bug in perf_callchain_user()
+    - f2fs: enhance to update i_mode and acl atomically in f2fs_setattr()
+    - f2fs: fix typo
+    - f2fs: fix to update i_ctime in __f2fs_setxattr()
+    - f2fs: remove unneeded check condition in __f2fs_setxattr()
+    - f2fs: reduce expensive checkpoint trigger frequency
+    - iio: adc: ad7606: fix oversampling gpio array
+    - iio: adc: ad7606: fix standby gpio state to match the documentation
+    - coresight: tmc: sg: Do not leak sg_table
+    - net: qrtr: Update packets cloning when broadcasting
+    - netfilter: ctnetlink: compile ctnetlink_label_size with
+      CONFIG_NF_CONNTRACK_EVENTS
+    - Remove *.orig pattern from .gitignore
+    - soc: versatile: integrator: fix OF node leak in probe() error path
+    - drm/amd/display: Round calculated vtotal
+    - USB: appledisplay: close race between probe and completion handler
+    - USB: misc: cypress_cy7c63: check for short transfer
+    - USB: class: CDC-ACM: fix race between get_serial and set_serial
+    - tty: rp2: Fix reset with non forgiving PCIe host bridges
+    - drbd: Fix atomicity violation in drbd_uuid_set_bm()
+    - drbd: Add NULL check for net_conf to prevent dereference in state validation
+    - ACPI: resource: Add another DMI match for the TongFang GMxXGxx
+    - wifi: rtw88: 8822c: Fix reported RX band width
+    - debugobjects: Fix conditions in fill_pool()
+    - f2fs: prevent possible int overflow in dir_block_index()
+    - f2fs: avoid potential int overflow in sanity_check_area_boundary()
+    - hwrng: mtk - Use devm_pm_runtime_enable
+    - fs: Fix file_set_fowner LSM hook inconsistencies
+    - nfs: fix memory leak in error path of nfs4_do_reclaim
+    - ASoC: meson: axg: extract sound card utils
+    - [Config] updateconfigs for SND_MESON_CARD_UTILS
+    - PCI: xilinx-nwl: Use irq_data_get_irq_chip_data()
+    - PCI: xilinx-nwl: Fix off-by-one in INTx IRQ handler
+    - soc: versatile: realview: fix memory leak during device remove
+    - soc: versatile: realview: fix soc_dev leak during device remove
+    - usb: yurex: Replace snprintf() with the safer scnprintf() variant
+    - USB: misc: yurex: fix race between read and write
+    - pps: remove usage of the deprecated ida_simple_xx() API
+    - pps: add an error check in parport_attach
+    - mm: only enforce minimum stack gap size if it's sensible
+    - i2c: aspeed: Update the stop sw state when the bus recovery occurs
+    - i2c: isch: Add missed 'else'
+    - usb: yurex: Fix inconsistent locking bug in yurex_read()
+    - mailbox: rockchip: fix a typo in module autoloading
+    - Minor fixes to the CAIF Transport drivers Kconfig file
+    - drivers: net: Fix Kconfig indentation, continued
+    - ieee802154: Fix build error
+    - net/mlx5: Added cond_resched() to crdump collection
+    - netfilter: uapi: NFTA_FLOWTABLE_HOOK is NLA_NESTED
+    - net: ieee802154: mcr20a: Use IRQF_NO_AUTOEN flag in request_irq()
+    - Bluetooth: btmrvl_sdio: Refactor irq wakeup
+    - Bluetooth: btmrvl: Use IRQF_NO_AUTOEN flag in request_irq()
+    - ipv4: ip_gre: Fix drops of small packets in ipgre_xmit
+    - ALSA: hda/realtek: Fix the push button function for the ALC257
+    - ALSA: hda/generic: Unconditionally prefer preferred_dacs pairs
+    - ALSA: hda/conexant: Fix conflicting quirk for System76 Pangolin
+    - wifi: ath9k: fix possible integer overflow in ath9k_get_et_stats()
+    - ice: Adjust over allocation of memory in ice_sched_add_root_node() and
+      ice_sched_add_node()
+    - net: hisilicon: hip04: fix OF node leak in probe()
+    - net: hisilicon: hns_dsaf_mac: fix OF node leak in hns_mac_get_info()
+    - net: hisilicon: hns_mdio: fix OF node leak in probe()
+    - ACPICA: Fix memory leak if acpi_ps_get_next_namepath() fails
+    - ACPICA: Fix memory leak if acpi_ps_get_next_field() fails
+    - net: sched: consistently use rcu_replace_pointer() in taprio_change()
+    - wifi: rtw88: select WANT_DEV_COREDUMP
+    - ACPI: EC: Do not release locks during operation region accesses
+    - net: mvpp2: Increase size of queue_name buffer
+    - ipv4: Check !in_dev earlier for ioctl(SIOCSIFADDR).
+    - ipv4: Mask upper DSCP bits and ECN bits in NETLINK_FIB_LOOKUP family
+    - tcp: avoid reusing FIN_WAIT2 when trying to find port in connect() process
+    - ACPICA: iasl: handle empty connection_node
+    - proc: add config & param to block forcing mem writes
+    - [Config] updateconfigs to select PROC_MEM_ALWAYS_FORCE
+    - nfp: Use IRQF_NO_AUTOEN flag in request_irq()
+    - signal: Replace BUG_ON()s
+    - ALSA: hdsp: Break infinite MIDI input flush loop
+    - x86/syscall: Avoid memcpy() for ia32 syscall_get_arguments()
+    - power: reset: brcmstb: Do not go into infinite loop if reset fails
+    - ata: sata_sil: Rename sil_blacklist to sil_quirks
+    - jfs: UBSAN: shift-out-of-bounds in dbFindBits
+    - drm/printer: Allow NULL data in devcoredump printer
+    - scsi: aacraid: Rearrange order of struct aac_srb_unit
+    - drm/radeon/r100: Handle unknown family in r100_cp_init_microcode()
+    - of/irq: Refer to actual buffer size in of_irq_parse_one()
+    - ext4: ext4_search_dir should return a proper error
+    - spi: s3c64xx: fix timeout counters in flush_fifo
+    - selftests: breakpoints: use remaining time to check if suspend succeed
+    - selftests: vDSO: fix vDSO symbols lookup for powerpc64
+    - i2c: xiic: Wait for TX empty to avoid missed TX NAKs
+    - firmware: tegra: bpmp: Drop unused mbox_client_to_bpmp()
+    - spi: bcm63xx: Fix module autoloading
+    - perf/core: Fix small negative period being ignored
+    - parisc: Fix itlb miss handler for 64-bit programs
+    - drm: Consistently use struct drm_mode_rect for FB_DAMAGE_CLIPS
+    - ALSA: core: add isascii() check to card ID generator
+    - ext4: propagate errors from ext4_find_extent() in ext4_insert_range()
+    - ext4: fix incorrect tid assumption in __jbd2_log_wait_for_space()
+    - ext4: fix incorrect tid assumption in ext4_wait_for_tail_page_commit()
+    - parisc: Fix 64-bit userspace syscall path
+    - parisc: Fix stack start for ADDR_NO_RANDOMIZE personality
+    - of/irq: Support #msi-cells=<0> in of_msi_get_domain
+    - mm: krealloc: consider spare memory for __GFP_ZERO
+    - ocfs2: fix the la space leak when unmounting an ocfs2 volume
+    - ocfs2: fix uninit-value in ocfs2_get_block()
+    - riscv: define ILLEGAL_POINTER_VALUE for 64bit
+    - clk: rockchip: fix error for unknown clocks
+    - media: sun4i_csi: Implement link validate for sun4i_csi subdev
+    - media: uapi/linux/cec.h: cec_msg_set_reply_to: zero flags
+    - iio: magnetometer: ak8975: Fix reading for ak099xx sensors
+    - tomoyo: fallback to realpath if symlink's pathname does not exist
+    - rtc: at91sam9: fix OF node leak in probe() error path
+    - Input: adp5589-keys - fix adp5589_gpio_get_value()
+    - ACPI: resource: Add Asus Vivobook X1704VAP to irq1_level_low_skip_override[]
+    - ACPI: resource: Add Asus ExpertBook B2502CVA to
+      irq1_level_low_skip_override[]
+    - gpio: davinci: fix lazy disable
+    - i2c: qcom-geni: Let firmware specify irq trigger flags
+    - i2c: qcom-geni: Grow a dev pointer to simplify code
+    - i2c: qcom-geni: Use IRQF_NO_AUTOEN flag in request_irq()
+    - arm64: Add Cortex-715 CPU part definition
+    - arm64: cputype: Add Neoverse-N3 definitions
+    - arm64: errata: Expand speculative SSBS workaround once more
+    - nfsd: use ktime_get_seconds() for timestamps
+    - nfsd: fix delegation_blocked() to block correctly for at least 30 seconds
+    - clk: qcom: rpmh: Simplify clk_rpmh_bcm_send_cmd()
+    - clk: qcom: clk-rpmh: Fix overflow in BCM vote
+    - r8169: Fix spelling mistake: "tx_underun" -> "tx_underrun"
+    - ACPI: battery: Simplify battery hook locking
+    - ext4: fix inode tree inconsistency caused by ENOMEM
+    - net: ethernet: cortina: Drop TSO support
+    - tracing: Remove precision vsnprintf() check from print event
+    - drm/crtc: fix uninitialized variable use even harder
+    - tracing: Have saved_cmdlines arrays all in one allocation
+    - virtio_console: fix misc probe bugs
+    - Input: synaptics-rmi4 - fix UAF of IRQ domain on driver removal
+    - bpf: Check percpu map value size first
+    - s390/facility: Disable compile time optimization for decompressor code
+    - s390/mm: Add cond_resched() to cmm_alloc/free_pages()
+    - ext4: nested locking for xattr inode
+    - s390/cpum_sf: Remove WARN_ON_ONCE statements
+    - ktest.pl: Avoid false positives with grub2 skip regex
+    - clk: bcm: bcm53573: fix OF node leak in init
+    - PCI: Add ACS quirk for Qualcomm SA8775P
+    - i2c: i801: Use a different adapter-name for IDF adapters
+    - PCI: Mark Creative Labs EMU20k2 INTx masking as broken
+    - media: videobuf2-core: clear memory related fields in
+      __vb2_plane_dmabuf_put()
+    - usb: chipidea: udc: enable suspend interrupt after usb reset
+    - usb: dwc2: Adjust the timing of USB Driver Interrupt Registration in the
+      Crashkernel Scenario
+    - tools/iio: Add memory allocation failure check for trigger_name
+    - driver core: bus: Return -EIO instead of 0 when show/store invalid bus
+      attribute
+    - ice: fix VLAN replay after reset
+    - SUNRPC: Fix integer overflow in decode_rc_list()
+    - tcp: fix to allow timestamp undo if no retransmits were sent
+    - tcp: fix tcp_enter_recovery() to zero retrans_stamp when it's safe
+    - gpio: aspeed: Add the flush write to ensure the write complete.
+    - gpio: aspeed: Use devm_clk api to manage clock source
+    - net: ibm: emac: mal: fix wrong goto
+    - net: annotate lockless accesses to sk->sk_ack_backlog
+    - net: annotate lockless accesses to sk->sk_max_ack_backlog
+    - sctp: ensure sk_state is set to CLOSED if hashing fails in sctp_listen_start
+    - locking/lockdep: Fix bad recursion pattern
+    - locking/lockdep: Rework lockdep_lock
+    - locking/lockdep: Avoid potential access of invalid memory in lock_class
+    - lockdep: fix deadlock issue between lockdep and rcu
+    - HID: plantronics: Workaround for an unexcepted opposite volume key
+    - Revert "usb: yurex: Replace snprintf() with the safer scnprintf() variant"
+    - usb: dwc3: core: Stop processing of pending events if controller is halted
+    - usb: xhci: Fix problem with xhci resume from suspend
+    - usb: storage: ignore bogus device raised by JieLi BR21 USB sound chip
+    - hid: intel-ish-hid: Fix uninitialized variable 'rv' in
+      ish_fw_xfer_direct_dma
+    - arm64: probes: Fix simulate_ldr*_literal()
+    - tracing/kprobes: Return EADDRNOTAVAIL when func matches several symbols
+    - tracing/kprobes: Fix symbol counting logic by looking at modules as well
+    - PCI: Add function 0 DMA alias quirk for Glenfly Arise chip
+    - fat: fix uninitialized variable
+    - s390/sclp_vt220: Convert newlines to CRLF instead of LFCR
+    - KVM: s390: Change virtual to physical address access in diag 0x258 handler
+    - x86/cpufeatures: Define X86_FEATURE_AMD_IBPB_RET
+    - drm/vmwgfx: Handle surface check failure correctly
+    - iio: dac: ltc1660: add missing select REGMAP_SPI in Kconfig
+    - iio: dac: stm32-dac-core: add missing select REGMAP_MMIO in Kconfig
+    - iio: adc: ti-ads8688: add missing select IIO_(TRIGGERED_)BUFFER in Kconfig
+    - iio: hid-sensors: Fix an error handling path in
+      _hid_sensor_set_report_latency()
+    - iio: light: opt3001: add missing full-scale range value
+    - iio: proximity: mb1232: add missing select IIO_(TRIGGERED_)BUFFER in Kconfig
+    - iio: adc: ti-ads124s08: add missing select IIO_(TRIGGERED_)BUFFER in Kconfig
+    - Bluetooth: Remove debugfs directory on module init failure
+    - Bluetooth: btusb: Fix regression with fake CSR controllers 0a12:0001
+    - xhci: Fix incorrect stream context type macro
+    - USB: serial: option: add support for Quectel EG916Q-GL
+    - USB: serial: option: add Telit FN920C04 MBIM compositions
+    - x86/resctrl: Annotate get_mem_config() functions as __init
+    - x86/apic: Always explicitly disarm TSC-deadline timer
+    - mac80211: Fix NULL ptr deref for injected rate info
+    - RDMA/bnxt_re: Fix incorrect AVID type in WQE structure
+    - ARM: dts: bcm2837-rpi-cm3-io3: Fix HDMI hpd-gpio pin
+    - RDMA/cxgb4: Fix RDMA_CM_EVENT_UNREACHABLE error for iWARP
+    - ipv4: give an IPv4 dev to blackhole_netdev
+    - RDMA/bnxt_re: Return more meaningful error
+    - drm/msm/dsi: fix 32-bit signed integer extension in pclk_rate calculation
+    - macsec: don't increment counters for an unrelated SA
+    - net: ethernet: aeroflex: fix potential memory leak in
+      greth_start_xmit_gbit()
+    - genetlink: hold RCU in genlmsg_mcast()
+    - arm64:uprobe fix the uprobe SWBP_INSN in big-endian
+    - KVM: s390: gaccess: Check if guest address is in memslot
+    - jfs: Fix sanity check in dbMount
+    - net: usb: usbnet: fix name regression
+    - r8169: avoid unsolicited interrupts
+    - posix-clock: posix-clock: Fix unbalanced locking in pc_clock_settime()
+    - ALSA: hda/realtek: Update default depop procedure
+    - ACPI: resource: Add LG 16T90SP to irq1_level_low_skip_override[]
+    - ACPI: button: Add DMI quirk for Samsung Galaxy Book2 to fix initial lid
+      detection issue
+    - ALSA: hda/realtek: Add subwoofer quirk for Acer Predator G9-593
+    - hv_netvsc: Fix VF namespace also in synthetic NIC NETDEV_REGISTER event
+    - selinux: improve error checking in sel_write_load()
+    - arm64/uprobes: change the uprobe_opcode_t typedef to fix the sparse warning
+    - cgroup: Fix potential overflow issue when checking max_depth
+    - wifi: mac80211: skip non-uploaded keys in ieee80211_iter_keys
+    - mac80211: do drv_reconfig_complete() before restarting all
+    - mac80211: Add support to trigger sta disconnect on hardware restart
+    - wifi: iwlwifi: mvm: disconnect station vifs if recovery failed
+    - ASoC: cs42l51: Fix some error handling paths in cs42l51_probe()
+    - dt-bindings: gpu: Convert Samsung Image Rotator to dt-schema
+    - gtp: simplify error handling code in 'gtp_encap_enable()'
+    - gtp: allow -1 to be specified as file description from userspace
+    - net: support ip generic csum processing in skb_csum_hwoffload_help
+    - net: skip offload for NETIF_F_IPV6_CSUM if ipv6 header contains extension
+    - drivers/misc: ti-st: Remove unneeded variable in st_tty_open
+    - firmware: arm_sdei: Fix the input parameter of cpuhp_remove_state()
+    - net: amd: mvme147: Fix probe banner message
+    - misc: sgi-gru: Don't disable preemption in GRU driver
+    - usbip: tools: Fix detach_port() invalid port error path
+    - usb: phy: Fix API devm_usb_put_phy() can not release the phy
+    - xhci: Fix Link TRB DMA in command ring stopped completion event
+    - Revert "driver core: Fix uevent_show() vs driver detach race"
+    - riscv: Remove unused GENERATING_ASM_OFFSETS
+    - Revert "drm/mipi-dsi: Set the fwnode for mipi_dsi_device"
+    - vt: prevent kernel-infoleak in con_font_get()
+    - mac80211: always have ieee80211_sta_restart()
+    - mm: krealloc: Fix MTE false alarm in __do_krealloc
+    - Linux 5.4.285
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50228
+    - mm: shmem: fix data-race in shmem_getattr()
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50230
+    - nilfs2: fix kernel bug due to missing clearing of checked flag
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50218
+    - ocfs2: pass u64 to ocfs2_truncate_inline maybe overflow
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50229
+    - nilfs2: fix potential deadlock with newly created symlinks
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50233
+    - staging: iio: frequency: ad9832: fix division by zero in
+      ad9832_calc_freqreg()
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50234
+    - wifi: iwlegacy: Clear stale interrupts before resuming device
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50236
+    - wifi: ath10k: Fix memory leak in management tx
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50237
+    - wifi: mac80211: do not pass a stopped vif to the driver in .get_txpower
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50251
+    - netfilter: nft_payload: sanitize offset and length before calling
+      skb_checksum()
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50262
+    - bpf: Fix out-of-bounds write in trie_get_next_key()
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-53059
+    - wifi: iwlwifi: mvm: Fix response handling in iwl_mvm_send_recovery_cmd()
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50142
+    - xfrm: validate new SA's prefixlen using SA family when sel.family is unset
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50116
+    - nilfs2: fix kernel bug due to missing clearing of buffer delay flag
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50117
+    - drm/amd: Guard against bad data for ATIF ACPI method
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50205
+    - ALSA: firewire-lib: Avoid division by zero in apply_constraint_to_size()
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50127
+    - net: sched: fix use-after-free in taprio_change()
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50167
+    - be2net: fix potential memory leak in be_xmit()
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50168
+    - net/sun3_82586: fix potential memory leak in sun3_82586_send_packet()
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50131
+    - tracing: Consider the NULL character when validating the event length
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50143
+    - udf: fix uninit-value use in udf_get_fileshortad
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50134
+    - drm/vboxvideo: Replace fake VLA at end of vbva_mouse_pointer_shape with real
+      VLA
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50194
+    - arm64: probes: Fix uprobes for big-endian kernels
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50148
+    - Bluetooth: bnep: fix wild-memory-access in proto_unregister
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50150
+    - usb: typec: altmode should keep reference to parent
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50151
+    - smb: client: fix OOBs when building SMB2_IOCTL request
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50171
+    - net: systemport: fix potential memory leak in bcm_sysport_xmit()
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50202
+    - nilfs2: propagate directory read errors from nilfs_find_entry()
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50074
+    - parport: Proper fix for array out-of-bounds access
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50082
+    - blk-rq-qos: fix crash on rq_qos_wait vs. rq_qos_wake_function race
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-40953
+    - KVM: Fix a data race on last_boosted_vcpu in kvm_vcpu_on_spin()
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50199
+    - mm/swapfile: skip HugeTLB pages for unuse_vma
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50099
+    - arm64: probes: Remove broken LDR (literal) uprobe support
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50195
+    - posix-clock: Fix missing timespec64 check in pc_clock_settime()
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50096
+    - nouveau/dmem: Fix vulnerability in migrate_to_ram upon copy error
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50024
+    - net: Fix an unsafe loop on the list
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49878
+    - resource: fix region_intersects() vs add_memory_driver_managed()
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50033
+    - slip: make slhc_remember() more robust against malicious packets
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50035
+    - ppp: fix ppp_async_encode() illegal access
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50039
+    - net/sched: accept TCA_STAB only for root qdisc
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50040
+    - igb: Do not bring the device up after non-fatal error
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50044
+    - Bluetooth: RFCOMM: FIX possible deadlock in rfcomm_sk_state_change
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50045
+    - netfilter: br_netfilter: fix panic with metadata_dst skb
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-38544
+    - RDMA/rxe: Fix seg fault in rxe_comp_queue_pkt
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50180
+    - fbdev: sisfb: Fix strbuf array overflow
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50184
+    - virtio_pmem: Check device status before requesting flush
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50059
+    - ntb: ntb_hw_switchtec: Fix use after free vulnerability in
+      switchtec_ntb_remove due to race condition
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50089
+    - unicode: Don't special case ignorable code points
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49955
+    - ACPI: battery: Fix possible crash when unregistering a battery hook
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49973
+    - r8169: add tally counter fields added with RTL8125
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49975
+    - uprobes: fix kernel info leak via "[uprobes]" vma
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49867
+    - btrfs: wait for fixup workers before stopping cleaner kthread during umount
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49868
+    - btrfs: fix a NULL pointer dereference when failed to start a new trasacntion
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49981
+    - media: venus: fix use after free bug in venus_remove due to race condition
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49982
+    - aoe: fix the potential use-after-free problem in more places
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49877
+    - ocfs2: fix possible null-ptr-deref in ocfs2_set_buffer_uptodate
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49957
+    - ocfs2: fix null-ptr-deref when journal load failed.
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49965
+    - ocfs2: remove unreasonable unlock in ocfs2_read_blocks
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49966
+    - ocfs2: cancel dqi_sync_work before freeing oinfo
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49958
+    - ocfs2: reserve space for inline xattr before attaching reflink tree
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49959
+    - jbd2: stop waiting for space when jbd2_cleanup_journal_tail() returns error
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49879
+    - drm: omapdrm: Add missing check for alloc_ordered_workqueue
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49882
+    - ext4: fix double brelse() the buffer of the extents path
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49883
+    - ext4: aovid use-after-free in ext4_ext_insert_extent()
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49985
+    - i2c: stm32f7: Do not prepare/unprepare clock during runtime suspend/resume
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50006
+    - ext4: fix i_data_sem unlock order in ext4_ind_migrate()
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49892
+    - drm/amd/display: Initialize get_bytes_per_element's default to 1
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49894
+    - drm/amd/display: Fix index out of bounds in degamma hardware format
+      translation
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49896
+    - drm/amd/display: Check stream before comparing them
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49900
+    - jfs: Fix uninit-value access of new_ea in ea_buffer
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49902
+    - jfs: check if leafidx greater than num leaves per dmap tree
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49903
+    - jfs: Fix uaf in dbFreeBits
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49924
+    - fbdev: pxafb: Fix possible use after free in pxafb_task()
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50007
+    - ALSA: asihpi: Fix potential OOB array access
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50008
+    - wifi: mwifiex: Fix memcpy() field-spanning write warning in
+      mwifiex_cmd_802_11_scan_ext()
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49995
+    - tipc: guard against string buffer overrun
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49962
+    - ACPICA: check null return of ACPI_ALLOCATE_ZEROED() in
+      acpi_db_convert_to_package()
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49938
+    - wifi: ath9k_htc: Use __skb_set_length() for resetting urb before resubmit
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47740
+    - f2fs: Require FMODE_WRITE for atomic write ioctls
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49944
+    - sctp: set sk_state back to CLOSED if autobind fails in sctp_listen_start
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49948
+    - net: add more sanity checks to qdisc_pkt_len_init()
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49949
+    - net: avoid potential underflow in qdisc_pkt_len_init() with UFO
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49997
+    - net: ethernet: lantiq_etop: fix memory disclosure
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49952
+    - netfilter: nf_tables: prevent nf_skb_duplicated corruption
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50179
+    - ceph: remove the incorrect Fw reference check when dirtying pages
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49963
+    - mailbox: bcm2835: Fix timeout during suspend mode
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-46849
+    - ASoC: meson: axg-card: fix 'use-after-free'
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47679
+    - vfs: fix race between evice_inodes() and find_inode()&iput()
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49860
+    - ACPI: sysfs: validate return type of _STR method
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47742
+    - firmware_loader: Block path traversal
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47684
+    - tcp: check skb is non-NULL in tcp_rto_delta_us()
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47747
+    - net: seeq: Fix use after free vulnerability in ether3 Driver Due to Race
+      Condition
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47685
+    - netfilter: nf_reject_ipv6: fix nf_reject_ip6_tcphdr_put()
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47692
+    - nfsd: return -EINVAL when namelen is 0
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47737
+    - nfsd: call cache_put if xdr_reserve_space returns NULL
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2023-52917
+    - ntb: intel: Fix the NULL vs IS_ERR() bug for debugfs_create_dir()
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47749
+    - RDMA/cxgb4: Added NULL check for lookup_atid
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47696
+    - RDMA/iwcm: Fix WARNING:at_kernel/workqueue.c:#check_flush_dependency
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47756
+    - PCI: keystone: Fix if-statement expression in ks_pcie_quirk()
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47697
+    - drivers: media: dvb-frontends/rtl2830: fix an out-of-bounds write error
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47698
+    - drivers: media: dvb-frontends/rtl2832: fix an out-of-bounds write error
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47757
+    - nilfs2: fix potential oob read in nilfs_btree_check_delete()
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47699
+    - nilfs2: fix potential null-ptr-deref in nilfs_btree_insert()
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47701
+    - ext4: avoid OOB when system.data xattr changes underneath the filesystem
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49851
+    - tpm: Clean up TPM space after command failure
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47723
+    - jfs: fix out-of-bounds in dbNextAG() and diAlloc()
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47706
+    - block, bfq: fix possible UAF for bfqq->bic with merge chain
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47709
+    - can: bcm: Clear bo->bcm_proc_read after remove_proc_entry().
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47710
+    - sock_map: Add a cond_resched() in sock_hash_free()
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47712
+    - wifi: wilc1000: fix potential RCU dereference issue in
+      wilc_parse_join_bss_param
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47713
+    - wifi: mac80211: use two-phase skb reclamation in ieee80211_do_stop()
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47671
+    - USB: usbtmc: prevent kernel-usb-infoleak
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-44931
+    - gpio: prevent potential speculation leaks in gpio_device_get_desc()
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-41016
+    - ocfs2: strict bound check before memcmp in ocfs2_xattr_find_entry()
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47670
+    - ocfs2: add bounds checking to ocfs2_xattr_find_entry()
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47672
+    - wifi: iwlwifi: mvm: don't wait for tx queues if firmware is dead
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-46853
+    - spi: nxp-fspi: fix the KASAN report out-of-bounds bug
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-46854
+    - net: dpaa: Pad packets to ETH_ZLEN
+
+ -- Mehmet Basaran <mehmet.basaran@canonical.com>  Mon, 13 Jan 2025 04:39:17 +0300
+
+linux (5.4.0-205.225) focal; urgency=medium
+
+  * focal/linux: 5.4.0-205.225 -proposed tracker (LP: #2093621)
+
+  * Hold IOPOLL locks when triggering io_uring's deferred work (LP: #2078659) //
+    CVE-2023-21400
+    - io_uring: remove extra check in __io_commit_cqring
+    - io_uring: dont kill fasync under completion_lock
+    - io_uring: ensure IOPOLL locks around deferred work
+
+  * CVE-2024-40967
+    - iopoll: introduce read_poll_timeout macro
+    - iopoll: Introduce read_poll_timeout_atomic macro
+    - serial: imx: Introduce timeout when waiting on transmitter empty
+
+  * CVE-2024-53164
+    - net: sched: fix ordering of qlen adjustment
+
+  * CVE-2024-53141
+    - netfilter: ipset: add missing range check in bitmap_ip_uadt
+
+  * CVE-2024-53103
+    - hv_sock: Initializing vsk->trans to NULL to prevent a dangling pointer
+
+ -- Manuel Diewald <manuel.diewald@canonical.com>  Fri, 10 Jan 2025 22:28:21 +0100
+
+linux (5.4.0-204.224) focal; urgency=medium
+
+  * focal/linux: 5.4.0-204.224 -proposed tracker (LP: #2091090)
+
+  * CVE-2024-50264
+    - vsock/virtio: Initialization of the dangling pointer occurring in vsk->trans
+
+  * CVE-2024-53057
+    - net/sched: stop qdisc_tree_reduce_backlog on TC_H_ROOT
+
+  * CVE-2024-49967
+    - ext4: no need to continue when the number of entries is 1
+
+  * CVE-2024-43892
+    - memcg: protect concurrent access to mem_cgroup_idr
+
+  * CVE-2024-38553
+    - net: fec: remove .ndo_poll_controller to avoid deadlocks
+
+  * CVE-2024-38597
+    - eth: sungem: remove .ndo_poll_controller to avoid deadlocks
+
+  * CVE-2023-52821
+    - drm/panel: fix a possible null pointer dereference
+
+  * CVE-2024-36952
+    - scsi: lpfc: Move NPIV's transport unregistration to after resource clean up
+
+  * CVE-2024-40910
+    - ax25: Fix refcount imbalance on inbound connections
+
+  * CVE-2024-35963
+    - Bluetooth: hci_sock: Fix not validating setsockopt user input
+
+  * CVE-2024-35965
+    - Bluetooth: L2CAP: uninitialized variables in l2cap_sock_setsockopt()
+    - Bluetooth: L2CAP: Fix not validating setsockopt user input
+
+  * CVE-2024-35966
+    - Bluetooth: RFCOMM: Fix not validating setsockopt user input
+
+  * CVE-2024-35967
+    - Bluetooth: SCO: Fix not validating setsockopt user input
+
+  * CVE-2021-47101
+    - net: asix: fix uninit value bugs
+    - asix: fix wrong return value in asix_check_host_enable()
+    - asix: fix uninit-value in asix_mdio_read()
+
+  * CVE-2022-38096
+    - drm/vmwgfx: Fix possible null pointer derefence with invalid contexts
+
+  * CVE-2021-47001
+    - xprtrdma: Fix cwnd update ordering
+
+ -- Manuel Diewald <manuel.diewald@canonical.com>  Thu, 05 Dec 2024 12:35:34 +0100
+
+linux (5.4.0-202.222) focal; urgency=medium
+
+  * focal/linux: 5.4.0-202.222 -proposed tracker (LP: #2086451)
+    - [Packaging] resync git-ubuntu-log
+
+  * CVE-2021-47501
+    - i40e: Fix NULL pointer dereference in i40e_dbg_dump_desc
+
+  * CVE-2024-46724
+    - drm/amdgpu: Fix out-of-bounds read of df_v1_7_channel_number
+
+  * CVE-2024-42240
+    - x86/bhi: Avoid warning in #DB handler due to BHI mitigation
+
+  * CVE-2024-42077
+    - ocfs2: fix DIO failure due to insufficient transaction credits
+
+  * CVE-2024-42068
+    - bpf: Take return from set_memory_ro() into account with bpf_prog_lock_ro()
+
+  * CVE-2024-36968
+    - Bluetooth: L2CAP: Fix div-by-zero in l2cap_le_flowctl_init()
+
+  * CVE-2024-35904
+    - selinux: avoid dereference of garbage after mount failure
+
+  * CVE-2023-52498
+    - PM: sleep: Avoid calling put_device() under dpm_list_mtx
+    - PM: sleep: Fix error handling in dpm_prepare()
+    - async: Split async_schedule_node_domain()
+    - async: Introduce async_schedule_dev_nocall()
+    - PM: sleep: Fix possible deadlocks in core system-wide PM code
+
+  * CVE-2023-52488
+    - serial: sc16is7xx: convert from _raw_ to _noinc_ regmap functions for FIFO
+
+  * CVE-2022-48938
+    - CDC-NCM: avoid overflow in sanity checking
+
+  * CVE-2024-42156
+    - s390/pkey: Wipe copies of clear-key structures on failure
+
+  * CVE-2024-44942
+    - f2fs: fix to do sanity check on F2FS_INLINE_DATA flag in inode during GC
+
+  * CVE-2024-38538
+    - net: bridge: xmit: make sure we have at least eth header len bytes
+
+  * CVE-2021-47076
+    - RDMA/rxe: Return CQE error if invalid lkey was supplied
+
+  * CVE-2024-36938
+    - bpf, skmsg: Fix NULL pointer dereference in sk_psock_skb_ingress_enqueue
+
+  * CVE-2024-44940
+    - fou: remove warn in gue_gro_receive on unsupported protocol
+
+  * CVE-2024-35951
+    - drm/panfrost: Fix the error path in panfrost_mmu_map_fault_addr()
+
+  * CVE-2023-52497
+    - erofs: fix lz4 inplace decompression
+
+  * CVE-2024-36953
+    - KVM: arm64: vgic-v2: Check for non-NULL vCPU in vgic_v2_parse_attr()
+
+  * CVE-2022-48943
+    - KVM: x86/mmu: make apf token non-zero to fix bug
+
+  * CVE-2024-26947
+    - ARM: 9359/1: flush: check if the folio is reserved for no-mapping addresses
+
+  * CVE-2022-48733
+    - btrfs: fix use-after-free after failure to create a snapshot
+
+  * CVE-2023-52639
+    - KVM: s390: vsie: fix race during shadow creation
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Fri, 08 Nov 2024 15:14:23 +0100
+
+linux (5.4.0-200.220) focal; urgency=medium
+
+  * focal/linux: 5.4.0-200.220 -proposed tracker (LP: #2082937)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] debian.master/dkms-versions -- update from kernel-versions
+      (main/2024.09.30)
+
+  * CVE-2024-26800
+    - tls: rx: coalesce exit paths in tls_decrypt_sg()
+    - tls: separate no-async decryption request handling from async
+    - tls: fix use-after-free on failed backlog decryption
+
+  * CVE-2024-26641
+    - ip6_tunnel: make sure to pull inner header in __ip6_tnl_rcv()
+
+  * CVE-2021-47212
+    - net/mlx5: Update error handler for UCTX and UMEM
+
+  * wbt:wbt_* trace event NULL pointer dereference with GENHD_FL_HIDDEN disks
+    (LP: #2081085)
+    - bdi: use bdi_dev_name() to get device name
+
+  * Focal update: v5.4.284 upstream stable release (LP: #2081278)
+    - drm: panel-orientation-quirks: Add quirk for OrangePi Neo
+    - i2c: Fix conditional for substituting empty ACPI functions
+    - net: usb: qmi_wwan: add MeiG Smart SRM825L
+    - drm/amdgpu: Fix uninitialized variable warning in amdgpu_afmt_acr
+    - drm/amdgpu: fix overflowed array index read warning
+    - drm/amd/display: Check gpio_id before used as array index
+    - drm/amd/display: Stop amdgpu_dm initialize when stream nums greater than 6
+    - drm/amd/display: Check num_valid_sets before accessing reader_wm_sets[]
+    - drm/amd/display: Fix Coverity INTEGER_OVERFLOW within
+      dal_gpio_service_create
+    - drm/amdgpu: fix ucode out-of-bounds read warning
+    - drm/amdgpu: fix mc_data out-of-bounds read warning
+    - drm/amdkfd: Reconcile the definition and use of oem_id in struct
+      kfd_topology_device
+    - apparmor: fix possible NULL pointer dereference
+    - ionic: fix potential irq name truncation
+    - usbip: Don't submit special requests twice
+    - usb: typec: ucsi: Fix null pointer dereference in trace
+    - smack: tcp: ipv4, fix incorrect labeling
+    - wifi: cfg80211: make hash table duplicates more survivable
+    - drm/amd/display: Skip wbscl_set_scaler_filter if filter is null
+    - media: uvcvideo: Enforce alignment of frame and interval
+    - block: initialize integrity buffer to zero before writing it to media
+    - net: set SOCK_RCU_FREE before inserting socket into hashtable
+    - virtio_net: Fix napi_skb_cache_put warning
+    - udf: Limit file size to 4TB
+    - i2c: Use IS_REACHABLE() for substituting empty ACPI functions
+    - sch/netem: fix use after free in netem_dequeue
+    - ASoC: dapm: Fix UAF for snd_soc_pcm_runtime object
+    - ALSA: hda/conexant: Add pincfg quirk to enable top speakers on Sirius
+      devices
+    - ata: libata: Fix memory leak for error path in ata_host_alloc()
+    - irqchip/gic-v2m: Fix refcount leak in gicv2m_of_init()
+    - mmc: dw_mmc: Fix IDMAC operation with pages bigger than 4K
+    - mmc: sdhci-of-aspeed: fix module autoloading
+    - fuse: update stats for pages in dropped aux writeback list
+    - fuse: use unsigned type for getxattr/listxattr size truncation
+    - reset: hi6220: Add support for AO reset controller
+    - clk: hi6220: use CLK_OF_DECLARE_DRIVER
+    - clk: qcom: clk-alpha-pll: Fix the pll post div mask
+    - clk: qcom: clk-alpha-pll: Fix the trion pll postdiv set rate API
+    - ila: call nf_unregister_net_hooks() sooner
+    - sched: sch_cake: fix bulk flow accounting logic for host fairness
+    - nilfs2: fix missing cleanup on rollforward recovery error
+    - nilfs2: fix state management in error path of log writing function
+    - ALSA: hda: Add input value sanity checks to HDMI channel map controls
+    - smack: unix sockets: fix accept()ed socket label
+    - irqchip/armada-370-xp: Do not allow mapping IRQ 0 and 1
+    - af_unix: Remove put_pid()/put_cred() in copy_peercred().
+    - netfilter: nf_conncount: fix wrong variable type
+    - udf: Avoid excessive partition lengths
+    - wifi: brcmsmac: advertise MFP_CAPABLE to enable WPA3
+    - usb: uas: set host status byte on data completion error
+    - PCI: keystone: Add workaround for Errata #i2037 (AM65x SR 1.0)
+    - media: qcom: camss: Add check for v4l2_fwnode_endpoint_parse
+    - pcmcia: Use resource_size function on resource object
+    - can: bcm: Remove proc entry when dev is unregistered.
+    - igb: Fix not clearing TimeSync interrupts for 82580
+    - platform/x86: dell-smbios: Fix error path in dell_smbios_init()
+    - tcp_bpf: fix return value of tcp_bpf_sendmsg()
+    - cx82310_eth: re-enable ethernet mode after router reboot
+    - drivers/net/usb: Remove all strcpy() uses
+    - net: usb: don't write directly to netdev->dev_addr
+    - usbnet: modern method to get random MAC
+    - net: bridge: fdb: convert is_local to bitops
+    - net: bridge: fdb: convert is_static to bitops
+    - net: bridge: fdb: convert is_sticky to bitops
+    - net: bridge: fdb: convert added_by_user to bitops
+    - net: bridge: fdb: convert added_by_external_learn to use bitops
+    - net: bridge: br_fdb_external_learn_add(): always set EXT_LEARN
+    - net: dsa: vsc73xx: fix possible subblocks range of CAPT block
+    - ASoC: topology: Properly initialize soc_enum values
+    - dm init: Handle minors larger than 255
+    - iommu/vt-d: Handle volatile descriptor status read
+    - cgroup: Protect css->cgroup write under css_set_lock
+    - um: line: always fill *error_out in setup_one_line()
+    - devres: Initialize an uninitialized struct member
+    - pci/hotplug/pnv_php: Fix hotplug driver crash on Powernv
+    - hwmon: (adc128d818) Fix underflows seen when writing limit attributes
+    - hwmon: (lm95234) Fix underflows seen when writing limit attributes
+    - hwmon: (nct6775-core) Fix underflows seen when writing limit attributes
+    - hwmon: (w83627ehf) Fix underflows seen when writing limit attributes
+    - libbpf: Add NULL checks to bpf_object__{prev_map,next_map}
+    - wifi: mwifiex: Do not return unused priv in mwifiex_get_priv_by_id()
+    - smp: Add missing destroy_work_on_stack() call in smp_call_on_cpu()
+    - btrfs: replace BUG_ON with ASSERT in walk_down_proc()
+    - btrfs: clean up our handling of refs == 0 in snapshot delete
+    - PCI: Add missing bridge lock to pci_bus_lock()
+    - btrfs: initialize location to fix -Wmaybe-uninitialized in
+      btrfs_lookup_dentry()
+    - HID: cougar: fix slab-out-of-bounds Read in cougar_report_fixup
+    - Input: uinput - reject requests with unreasonable number of slots
+    - usbnet: ipheth: race between ipheth_close and error handling
+    - Squashfs: sanity check symbolic link size
+    - of/irq: Prevent device address out-of-bounds read in interrupt map walk
+    - lib/generic-radix-tree.c: Fix rare race in __genradix_ptr_alloc()
+    - ata: pata_macio: Use WARN instead of BUG
+    - NFSv4: Add missing rescheduling points in
+      nfs_client_return_marked_delegations
+    - staging: iio: frequency: ad9834: Validate frequency parameter value
+    - iio: buffer-dmaengine: fix releasing dma channel on error
+    - iio: fix scale application in iio_convert_raw_to_processed_unlocked
+    - binder: fix UAF caused by offsets overwrite
+    - nvmem: Fix return type of devm_nvmem_device_get() in kerneldoc
+    - uio_hv_generic: Fix kernel NULL pointer dereference in hv_uio_rescind
+    - Drivers: hv: vmbus: Fix rescind handling in uio_hv_generic
+    - VMCI: Fix use-after-free when removing resource in vmci_resource_remove()
+    - clocksource/drivers/imx-tpm: Fix return -ETIME when delta exceeds INT_MAX
+    - clocksource/drivers/imx-tpm: Fix next event not taking effect sometime
+    - clocksource/drivers/timer-of: Remove percpu irq related code
+    - uprobes: Use kzalloc to allocate xol area
+    - ring-buffer: Rename ring_buffer_read() to read_buffer_iter_advance()
+    - tracing: Avoid possible softlockup in tracing_iter_reset()
+    - nilfs2: replace snprintf in show functions with sysfs_emit
+    - nilfs2: protect references to superblock parameters exposed in sysfs
+    - ACPI: processor: Return an error if acpi_processor_get_info() fails in
+      processor_add()
+    - ACPI: processor: Fix memory leaks in error paths of processor_add()
+    - arm64: acpi: Move get_cpu_for_acpi_id() to a header
+    - arm64: acpi: Harden get_cpu_for_acpi_id() against missing CPU entry
+    - nvmet-tcp: fix kernel crash if commands allocation fails
+    - drm/i915/fence: Mark debug_fence_init_onstack() with __maybe_unused
+    - drm/i915/fence: Mark debug_fence_free() with __maybe_unused
+    - rtmutex: Drop rt_mutex::wait_lock before scheduling
+    - net, sunrpc: Remap EPERM in case of connection failure in
+      xs_tcp_setup_socket
+    - cx82310_eth: fix error return code in cx82310_bind()
+    - Linux 5.4.284
+
+  * CVE-2024-42244
+    - USB: serial: mos7840: fix crash on resume
+
+  * CVE-2024-40929
+    - wifi: iwlwifi: mvm: check n_ssids before accessing the ssids
+
+  * CVE-2024-41073
+    - nvme: avoid double free special payload
+
+  * CVE-2024-41071
+    - wifi: mac80211: Avoid address calculations via out of bounds array indexing
+
+  * CVE-2024-42229
+    - crypto: aead, cipher - zeroize key buffer after use
+
+  * CVE-2024-38611
+    - media: i2c: et8ek8: Don't strip remove function when driver is builtin
+
+  * CVE-2024-38602
+    - ax25: Fix reference count leak issues of ax25_dev
+
+  * CVE-2024-35848
+    - misc: eeprom: at24: fix regulator underflow
+    - misc: eeprom: at24: register nvmem only after eeprom is ready to use
+    - eeprom: at24: fix memory corruption race condition
+
+  * CVE-2024-26669
+    - net/sched: flower: Fix chain template offload
+
+  * CVE-2024-26668
+    - netfilter: nft_limit: rename stateful structure
+    - netfilter: nft_limit: reject configurations that cause integer overflow
+
+  * CVE-2024-26640
+    - net-zerocopy: Refactor frag-is-remappable test.
+    - tcp: add sanity checks to rx zerocopy
+
+  * CVE-2024-26607
+    - drm/bridge: sii902x: Fix probing race issue
+
+  * CVE-2023-52614
+    - PM / devfreq: Fix buffer overflow in trans_stat_show
+
+  * CVE-2023-52531
+    - wifi: iwlwifi: mvm: Fix a memory corruption issue
+
+  * CVE-2022-36402
+    - drm/vmwgfx: Use enum to represent graphics context capabilities
+    - drm/vmwgfx: Fix shader stage validation
+
+  * Focal update: v5.4.283 upstream stable release (LP: #2080595)
+    - fuse: Initialize beyond-EOF page contents before setting uptodate
+    - ALSA: usb-audio: Support Yamaha P-125 quirk entry
+    - xhci: Fix Panther point NULL pointer deref at full-speed re-enumeration
+    - s390/dasd: fix error recovery leading to data corruption on ESE devices
+    - arm64: ACPI: NUMA: initialize all values of acpi_early_node_map to
+      NUMA_NO_NODE
+    - dm resume: don't return EINVAL when signalled
+    - dm persistent data: fix memory allocation failure
+    - vfs: Don't evict inode under the inode lru traversing context
+    - bitmap: introduce generic optimized bitmap_size()
+    - fix bitmap corruption on close_range() with CLOSE_RANGE_UNSHARE
+    - selinux: fix potential counting error in avc_add_xperms_decision()
+    - drm/amdgpu: Actually check flags for all context ops.
+    - memcg_write_event_control(): fix a user-triggerable oops
+    - overflow.h: Add flex_array_size() helper
+    - overflow: Implement size_t saturating arithmetic helpers
+    - s390/cio: rename bitmap_size() -> idset_bitmap_size()
+    - btrfs: rename bitmap_set_bits() -> btrfs_bitmap_set_bits()
+    - s390/uv: Panic for set and remove shared access UVC errors
+    - net/mlx5e: Correctly report errors for ethtool rx flows
+    - atm: idt77252: prevent use after free in dequeue_rx()
+    - net: axienet: Fix DMA descriptor cleanup path
+    - net: axienet: Improve DMA error handling
+    - net: axienet: Factor out TX descriptor chain cleanup
+    - net: axienet: Check for DMA mapping errors
+    - net: axienet: Drop MDIO interrupt registers from ethtools dump
+    - net: axienet: Wrap DMA pointer writes to prepare for 64 bit
+    - net: axienet: Upgrade descriptors to hold 64-bit addresses
+    - net: axienet: Autodetect 64-bit DMA capability
+    - net: axienet: Fix register defines comment description
+    - net: dsa: vsc73xx: pass value in phy_write operation
+    - net: hns3: fix a deadlock problem when config TC during resetting
+    - ALSA: hda/realtek: Fix noise from speakers on Lenovo IdeaPad 3 15IAU7
+    - ssb: Fix division by zero issue in ssb_calc_clock_rate
+    - wifi: cw1200: Avoid processing an invalid TIM IE
+    - i2c: riic: avoid potential division by zero
+    - media: radio-isa: use dev_name to fill in bus_info
+    - staging: ks7010: disable bh on tx_dev_lock
+    - binfmt_misc: cleanup on filesystem umount
+    - scsi: spi: Fix sshdr use
+    - gfs2: setattr_chown: Add missing initialization
+    - wifi: iwlwifi: abort scan when rfkill on but device enabled
+    - IB/hfi1: Fix potential deadlock on &irq_src_lock and &dd->uctxt_lock
+    - powerpc/xics: Check return value of kasprintf in icp_native_map_one_cpu
+    - nvmet-trace: avoid dereferencing pointer too early
+    - ext4: do not trim the group with corrupted block bitmap
+    - quota: Remove BUG_ON from dqget()
+    - media: pci: cx23885: check cx23885_vdev_init() return
+    - fs: binfmt_elf_efpic: don't use missing interpreter's properties
+    - scsi: lpfc: Initialize status local variable in lpfc_sli4_repost_sgl_list()
+    - net/sun3_82586: Avoid reading past buffer in debug output
+    - drm/lima: set gp bus_stop bit before hard reset
+    - virtiofs: forbid newlines in tags
+    - md: clean up invalid BUG_ON in md_ioctl
+    - x86: Increase brk randomness entropy for 64-bit systems
+    - powerpc/boot: Handle allocation failure in simple_realloc()
+    - powerpc/boot: Only free if realloc() succeeds
+    - btrfs: change BUG_ON to assertion when checking for delayed_node root
+    - btrfs: handle invalid root reference found in may_destroy_subvol()
+    - btrfs: send: handle unexpected data in header buffer in begin_cmd()
+    - btrfs: delete pointless BUG_ON check on quota root in
+      btrfs_qgroup_account_extent()
+    - f2fs: fix to do sanity check in update_sit_entry
+    - usb: gadget: fsl: Increase size of name buffer for endpoints
+    - nvme: clear caller pointer on identify failure
+    - Bluetooth: bnep: Fix out-of-bound access
+    - nvmet-tcp: do not continue for invalid icreq
+    - NFS: avoid infinite loop in pnfs_update_layout.
+    - openrisc: Call setup_memory() earlier in the init sequence
+    - s390/iucv: fix receive buffer virtual vs physical address confusion
+    - usb: dwc3: core: Skip setting event buffers for host only controllers
+    - irqchip/gic-v3-its: Remove BUG_ON in its_vpe_irq_domain_alloc
+    - ext4: set the type of max_zeroout to unsigned int to avoid overflow
+    - nvmet-rdma: fix possible bad dereference when freeing rsps
+    - hrtimer: Prevent queuing of hrtimer without a function callback
+    - gtp: pull network headers in gtp_dev_xmit()
+    - block: use "unsigned long" for blk_validate_block_size().
+    - media: solo6x10: replace max(a, min(b, c)) by clamp(b, a, c)
+    - dm mpath: pass IO start time to path selector
+    - dm: do not use waitqueue for request-based DM
+    - dm suspend: return -ERESTARTSYS instead of -EINTR
+    - Bluetooth: Make use of __check_timeout on hci_sched_le
+    - Bluetooth: hci_core: Fix not handling link timeouts propertly
+    - Bluetooth: hci_core: Fix LE quote calculation
+    - tc-testing: don't access non-existent variable on exception
+    - kcm: Serialise kcm_sendmsg() for the same socket.
+    - netfilter: nft_counter: Synchronize nft_counter_reset() against reader.
+    - net: dsa: mv88e6xxx: global2: Expose ATU stats register
+    - net: dsa: mv88e6xxx: global1_atu: Add helper for get next
+    - net: dsa: mv88e6xxx: read FID when handling ATU violations
+    - net: dsa: mv88e6xxx: replace ATU violation prints with trace points
+    - net: dsa: mv88e6xxx: Fix out-of-bound access
+    - ipv6: prevent UAF in ip6_send_skb()
+    - net: xilinx: axienet: Always disable promiscuous mode
+    - net: xilinx: axienet: Fix dangling multicast addresses
+    - drm/msm: use drm_debug_enabled() to check for debug categories
+    - drm/msm/dpu: don't play tricks with debug macros
+    - mmc: mmc_test: Fix NULL dereference on allocation failure
+    - Bluetooth: MGMT: Add error handling to pair_device()
+    - HID: wacom: Defer calculation of resolution until resolution_code is known
+    - HID: microsoft: Add rumble support to latest xbox controllers
+    - cxgb4: add forgotten u64 ivlan cast before shift
+    - mmc: dw_mmc: allow biu and ciu clocks to defer
+    - ALSA: timer: Relax start tick time check for slave timer elements
+    - Input: MT - limit max slots
+    - tools: move alignment-related macros to new <linux/align.h>
+    - pinctrl: single: fix potential NULL dereference in pcs_get_function()
+    - wifi: mwifiex: duplicate static structs used in driver instances
+    - drm/amdkfd: don't allow mapping the MMIO HDP page with large pages
+    - filelock: Correct the filelock owner in fcntl_setlk/fcntl_setlk64
+    - media: uvcvideo: Fix integer overflow calculating timestamp
+    - ata: libata-core: Fix null pointer dereference on error
+    - cgroup/cpuset: Prevent UAF in proc_cpuset_show()
+    - net:rds: Fix possible deadlock in rds_message_put
+    - soundwire: stream: fix programming slave ports for non-continous port maps
+    - r8152: Factor out OOB link list waits
+    - ethtool: check device is present when getting link settings
+    - gtp: fix a potential NULL pointer dereference
+    - net: busy-poll: use ktime_get_ns() instead of local_clock()
+    - nfc: pn533: Add dev_up/dev_down hooks to phy_ops
+    - nfc: pn533: Add autopoll capability
+    - nfc: pn533: Add poll mod list filling check
+    - soc: qcom: cmd-db: Map shared memory as WC, not WB
+    - cdc-acm: Add DISABLE_ECHO quirk for GE HealthCare UI Controller
+    - USB: serial: option: add MeiG Smart SRM825L
+    - usb: dwc3: omap: add missing depopulate in probe error path
+    - usb: dwc3: core: Prevent USB core invalid event buffer address access
+    - usb: dwc3: st: fix probed platform device ref count on probe error path
+    - usb: dwc3: st: add missing depopulate in probe error path
+    - usb: core: sysfs: Unmerge @usb3_hardware_lpm_attr_group in
+      remove_power_attributes()
+    - net: dsa: mv8e6xxx: Fix stub function parameters
+    - scsi: aacraid: Fix double-free on probe failure
+    - Linux 5.4.283
+
+  * CVE-2024-27051
+    - cpufreq: brcmstb-avs-cpufreq: add check for cpufreq_cpu_get's return value
+    - cpufreq: brcmstb-avs-cpufreq: ISO C90 forbids mixed declarations
+
+  * CVE-2024-26891
+    - PCI: Make pci_dev_is_disconnected() helper public for other drivers
+    - iommu/vt-d: Don't issue ATS Invalidation request when device is disconnected
+
+  * Focal update: v5.4.282 upstream stable release (LP: #2078388)
+    - EDAC, skx_common: Refactor so that we initialize "dev" in result of adxl
+      decode.
+    - EDAC, skx: Retrieve and print retry_rd_err_log registers
+    - EDAC/skx_common: Add new ADXL components for 2-level memory
+    - EDAC, i10nm: make skx_common.o a separate module
+    - platform/chrome: cros_ec_debugfs: fix wrong EC message version
+    - hfsplus: fix to avoid false alarm of circular locking
+    - x86/of: Return consistent error type from x86_of_pci_irq_enable()
+    - x86/pci/intel_mid_pci: Fix PCIBIOS_* return code handling
+    - x86/pci/xen: Fix PCIBIOS_* return code handling
+    - x86/platform/iosf_mbi: Convert PCIBIOS_* return codes to errnos
+    - hwmon: (adt7475) Fix default duty on fan is disabled
+    - pwm: stm32: Always do lazy disabling
+    - hwmon: (max6697) Fix underflow when writing limit attributes
+    - hwmon: (max6697) Fix swapped temp{1,8} critical alarms
+    - arm64: dts: qcom: sdm845: add power-domain to UFS PHY
+    - arm64: dts: qcom: msm8996: specify UFS core_clk frequencies
+    - arm64: dts: rockchip: Increase VOP clk rate on RK3328
+    - ARM: dts: imx6qdl-kontron-samx6i: move phy reset into phy-node
+    - ARM: dts: imx6qdl-kontron-samx6i: fix PHY reset
+    - ARM: dts: imx6qdl-kontron-samx6i: fix board reset
+    - ARM: dts: imx6qdl-kontron-samx6i: fix PCIe reset polarity
+    - arm64: dts: mediatek: mt7622: fix "emmc" pinctrl mux
+    - arm64: dts: amlogic: gx: correct hdmi clocks
+    - m68k: atari: Fix TT bootup freeze / unexpected (SCU) interrupt messages
+    - x86/xen: Convert comma to semicolon
+    - m68k: cmpxchg: Fix return value for default case in __arch_xchg()
+    - firmware: turris-mox-rwtm: Fix checking return value of
+      wait_for_completion_timeout()
+    - firmware: turris-mox-rwtm: Initialize completion before mailbox
+    - wifi: brcmsmac: LCN PHY code is used for BCM4313 2G-only device
+    - net/smc: Allow SMC-D 1MB DMB allocations
+    - net/smc: set rmb's SG_MAX_SINGLE_ALLOC limitation only when
+      CONFIG_ARCH_NO_SG_CHAIN is defined
+    - selftests/bpf: Check length of recv in test_sockmap
+    - lib: objagg: Fix general protection fault
+    - mlxsw: spectrum_acl_erp: Fix object nesting warning
+    - wifi: cfg80211: fix typo in cfg80211_calculate_bitrate_he()
+    - wifi: cfg80211: handle 2x996 RU allocation in
+      cfg80211_calculate_bitrate_he()
+    - net: fec: Refactor: #define magic constants
+    - net: fec: Fix FEC_ECR_EN1588 being cleared on link-down
+    - ipvs: Avoid unnecessary calls to skb_is_gso_sctp
+    - netfilter: nf_tables: rise cap on SELinux secmark context
+    - perf/x86/intel/pt: Fix pt_topa_entry_for_page() address calculation
+    - perf: Fix perf_aux_size() for greater-than 32-bit size
+    - perf: Prevent passing zero nr_pages to rb_alloc_aux()
+    - qed: Improve the stack space of filter_config()
+    - wifi: virt_wifi: avoid reporting connection success with wrong SSID
+    - gss_krb5: Fix the error handling path for crypto_sync_skcipher_setkey
+    - wifi: virt_wifi: don't use strlen() in const context
+    - bna: adjust 'name' buf size of bna_tcb and bna_ccb structures
+    - selftests: forwarding: devlink_lib: Wait for udev events after reloading
+    - media: dvb-usb: Fix unexpected infinite loop in
+      dvb_usb_read_remote_control()
+    - media: imon: Fix race getting ictx->lock
+    - saa7134: Unchecked i2c_transfer function result fixed
+    - media: uvcvideo: Allow entity-defined get_info and get_cur
+    - media: uvcvideo: Override default flags
+    - media: renesas: vsp1: Fix _irqsave and _irq mix
+    - media: renesas: vsp1: Store RPF partition configuration per RPF instance
+    - leds: trigger: Unregister sysfs attributes before calling deactivate()
+    - perf report: Fix condition in sort__sym_cmp()
+    - drm/etnaviv: fix DMA direction handling for cached RW buffers
+    - drm/qxl: Add check for drm_cvt_mode
+    - mfd: omap-usb-tll: Use struct_size to allocate tll
+    - SUNRPC: avoid soft lockup when transmitting UDP to reachable server.
+    - ext4: avoid writing unitialized memory to disk in EA inodes
+    - sparc64: Fix incorrect function signature and add prototype for
+      prom_cif_init
+    - SUNRPC: Fixup gss_status tracepoint error output
+    - PCI: Fix resource double counting on remove & rescan
+    - Input: qt1050 - handle CHIP_ID reading error
+    - RDMA/mlx4: Fix truncated output warning in mad.c
+    - RDMA/mlx4: Fix truncated output warning in alias_GUID.c
+    - RDMA/rxe: Don't set BTH_ACK_MASK for UC or UD QPs
+    - ASoC: max98088: Check for clk_prepare_enable() error
+    - mtd: make mtd_test.c a separate module
+    - RDMA/device: Return error earlier if port in not valid
+    - Input: elan_i2c - do not leave interrupt disabled on suspend failure
+    - MIPS: Octeron: remove source file executable bit
+    - powerpc/xmon: Fix disassembly CPU feature checks
+    - macintosh/therm_windtunnel: fix module unload.
+    - bnxt_re: Fix imm_data endianness
+    - netfilter: ctnetlink: use helper function to calculate expect ID
+    - pinctrl: core: fix possible memory leak when pinctrl_enable() fails
+    - pinctrl: single: fix possible memory leak when pinctrl_enable() fails
+    - pinctrl: ti: ti-iodelay: Drop if block with always false condition
+    - pinctrl: ti: ti-iodelay: fix possible memory leak when pinctrl_enable()
+      fails
+    - pinctrl: freescale: mxs: Fix refcount of child
+    - fs/nilfs2: remove some unused macros to tame gcc
+    - nilfs2: avoid undefined behavior in nilfs_cnt32_ge macro
+    - rtc: interface: Add RTC offset to alarm after fix-up
+    - tick/broadcast: Make takeover of broadcast hrtimer reliable
+    - net: netconsole: Disable target before netpoll cleanup
+    - af_packet: Handle outgoing VLAN packets without hardware offloading
+    - ipv6: take care of scope when choosing the src addr
+    - char: tpm: Fix possible memory leak in tpm_bios_measurements_open()
+    - media: venus: fix use after free in vdec_close
+    - hfs: fix to initialize fields of hfs_inode_info after hfs_alloc_inode()
+    - drm/gma500: fix null pointer dereference in cdv_intel_lvds_get_modes
+    - drm/gma500: fix null pointer dereference in psb_intel_lvds_get_modes
+    - drm/amd/display: Check for NULL pointer
+    - udf: Avoid using corrupted block bitmap buffer
+    - m68k: amiga: Turn off Warp1260 interrupts during boot
+    - ext4: check dot and dotdot of dx_root before making dir indexed
+    - ext4: make sure the first directory block is not a hole
+    - wifi: mwifiex: Fix interface type change
+    - leds: ss4200: Convert PCIBIOS_* return codes to errnos
+    - tools/memory-model: Fix bug in lock.cat
+    - hwrng: amd - Convert PCIBIOS_* return codes to errnos
+    - PCI: hv: Return zero, not garbage, when reading PCI_INTERRUPT_PIN
+    - binder: fix hang of unregistered readers
+    - scsi: qla2xxx: Return ENOBUFS if sg_cnt is more than one for ELS cmds
+    - f2fs: fix to don't dirty inode for readonly filesystem
+    - clk: davinci: da8xx-cfgchip: Initialize clk_init_data before use
+    - ubi: eba: properly rollback inside self_check_eba
+    - decompress_bunzip2: fix rare decompression failure
+    - kobject_uevent: Fix OOB access within zap_modalias_env()
+    - rtc: cmos: Fix return value of nvmem callbacks
+    - scsi: qla2xxx: During vport delete send async logout explicitly
+    - scsi: qla2xxx: Fix for possible memory corruption
+    - scsi: qla2xxx: Complete command early within lock
+    - scsi: qla2xxx: validate nvme_local_port correctly
+    - perf/x86/intel/pt: Fix topa_entry base length
+    - perf/x86/intel/pt: Fix a topa_entry base address calculation
+    - rtc: isl1208: Fix return value of nvmem callbacks
+    - watchdog/perf: properly initialize the turbo mode timestamp and rearm
+      counter
+    - platform: mips: cpu_hwmon: Disable driver on unsupported hardware
+    - RDMA/iwcm: Fix a use-after-free related to destroying CM IDs
+    - selftests/sigaltstack: Fix ppc64 GCC build
+    - rbd: don't assume rbd_is_lock_owner() for exclusive mappings
+    - drm/panfrost: Mark simple_ondemand governor as softdep
+    - rbd: rename RBD_LOCK_STATE_RELEASING and releasing_wait
+    - rbd: don't assume RBD_LOCK_STATE_LOCKED for exclusive mappings
+    - Bluetooth: btusb: Add RTL8852BE device 0489:e125 to device tables
+    - Bluetooth: btusb: Add Realtek RTL8852BE support ID 0x13d3:0x3591
+    - nilfs2: handle inconsistent state in nilfs_btnode_create_block()
+    - kdb: address -Wformat-security warnings
+    - kdb: Use the passed prompt in kdb_position_cursor()
+    - jfs: Fix array-index-out-of-bounds in diFree
+    - um: time-travel: fix time-travel-start option
+    - libbpf: Fix no-args func prototype BTF dumping syntax
+    - dma: fix call order in dmam_free_coherent
+    - MIPS: SMP-CPS: Fix address for GCR_ACCESS register for CM3 and later
+    - ipv4: Fix incorrect source address in Record Route option
+    - net: bonding: correctly annotate RCU in bond_should_notify_peers()
+    - tipc: Return non-zero value from tipc_udp_addr2str() on error
+    - net: nexthop: Initialize all fields in dumped nexthops
+    - bpf: Fix a segment issue when downgrading gso_size
+    - mISDN: Fix a use after free in hfcmulti_tx()
+    - powerpc: fix a file leak in kvm_vcpu_ioctl_enable_cap()
+    - ASoC: Intel: Convert to new X86 CPU match macros
+    - ASoC: Intel: Move soc_intel_is_foo() helpers to a generic header
+    - ASoC: Intel: use soc_intel_is_byt_cr() only when IOSF_MBI is reachable
+    - nvme-pci: add missing condition check for existence of mapped data
+    - mm: avoid overflows in dirty throttling logic
+    - PCI: rockchip: Make 'ep-gpios' DT property optional
+    - PCI: rockchip: Use GPIOD_OUT_LOW flag while requesting ep_gpio
+    - parport: Convert printk(KERN_<LEVEL> to pr_<level>(
+    - parport: Standardize use of printmode
+    - dev/parport: fix the array out-of-bounds risk
+    - driver core: Cast to (void *) with __force for __percpu pointer
+    - devres: Fix memory leakage caused by driver API devm_free_percpu()
+    - genirq: Allow the PM device to originate from irq domain
+    - irqchip/imx-irqsteer: Constify irq_chip struct
+    - irqchip/imx-irqsteer: Add runtime PM support
+    - irqchip/imx-irqsteer: Handle runtime power management correctly
+    - remoteproc: imx_rproc: ignore mapping vdev regions
+    - remoteproc: imx_rproc: Fix ignoring mapping vdev regions
+    - remoteproc: imx_rproc: Skip over memory region when node value is NULL
+    - drm/nouveau: prime: fix refcount underflow
+    - drm/vmwgfx: Fix overlay when using Screen Targets
+    - net/iucv: fix use after free in iucv_sock_close()
+    - net/mlx5e: Add a check for the return value from mlx5_port_set_eth_ptys
+    - ipv6: fix ndisc_is_useropt() handling for PIO
+    - HID: wacom: Modify pen IDs
+    - protect the fetch of ->fd[fd] in do_dup2() from mispredictions
+    - ALSA: usb-audio: Correct surround channels in UAC1 channel map
+    - net: usb: sr9700: fix uninitialized variable use in sr_mdio_read
+    - netfilter: ipset: Add list flush to cancel_gc
+    - genirq: Allow irq_chip registration functions to take a const irq_chip
+    - irqchip/mbigen: Fix mbigen node address layout
+    - x86/mm: Fix pti_clone_pgtable() alignment assumption
+    - sctp: move hlist_node and hashent out of sctp_ep_common
+    - sctp: Fix null-ptr-deref in reuseport_add_sock().
+    - net: usb: qmi_wwan: fix memory leak for not ip packets
+    - net: linkwatch: use system_unbound_wq
+    - Bluetooth: l2cap: always unlock channel in l2cap_conless_channel()
+    - net: fec: Stop PPS on driver remove
+    - md/raid5: avoid BUG_ON() while continue reshape after reassembling
+    - clocksource/drivers/sh_cmt: Address race condition for clock events
+    - ACPI: battery: create alarm sysfs attribute atomically
+    - ACPI: SBS: manage alarm sysfs attribute through psy core
+    - selftests/bpf: Fix send_signal test with nested CONFIG_PARAVIRT
+    - PCI: Add Edimax Vendor ID to pci_ids.h
+    - udf: prevent integer overflow in udf_bitmap_free_blocks()
+    - wifi: nl80211: don't give key data to userspace
+    - btrfs: fix bitmap leak when loading free space cache on duplicate entry
+    - drm/amdgpu: Fix the null pointer dereference to ras_manager
+    - media: uvcvideo: Ignore empty TS packets
+    - media: uvcvideo: Fix the bandwdith quirk on USB 3.x
+    - jbd2: avoid memleak in jbd2_journal_write_metadata_buffer
+    - s390/sclp: Prevent release of buffer in I/O
+    - SUNRPC: Fix a race to wake a sync task
+    - ext4: fix wrong unit use in ext4_mb_find_by_goal
+    - arm64: cpufeature: Force HWCAP to be based on the sysreg visible to user-
+      space
+    - arm64: Add Neoverse-V2 part
+    - arm64: cputype: Add Cortex-X4 definitions
+    - arm64: cputype: Add Neoverse-V3 definitions
+    - arm64: errata: Add workaround for Arm errata 3194386 and 3312417
+    - [Config] Set ARM64_ERRATUM_3194386=y
+    - arm64: cputype: Add Cortex-X3 definitions
+    - arm64: cputype: Add Cortex-A720 definitions
+    - arm64: cputype: Add Cortex-X925 definitions
+    - arm64: errata: Unify speculative SSBS errata logic
+    - arm64: errata: Expand speculative SSBS workaround
+    - arm64: cputype: Add Cortex-X1C definitions
+    - arm64: cputype: Add Cortex-A725 definitions
+    - arm64: errata: Expand speculative SSBS workaround (again)
+    - i2c: smbus: Don't filter out duplicate alerts
+    - i2c: smbus: Improve handling of stuck alerts
+    - i2c: smbus: Send alert notifications to all devices if source not found
+    - bpf: kprobe: remove unused declaring of bpf_kprobe_override
+    - spi: fsl-lpspi: remove unneeded array
+    - spi: spi-fsl-lpspi: Fix scldiv calculation
+    - drm/client: fix null pointer dereference in drm_client_modeset_probe
+    - ALSA: line6: Fix racy access to midibuf
+    - ALSA: hda: Add HP MP9 G4 Retail System AMS to force connect list
+    - ALSA: hda/hdmi: Yet more pin fix for HP EliteDesk 800 G4
+    - usb: vhci-hcd: Do not drop references before new references are gained
+    - USB: serial: debug: do not echo input by default
+    - usb: gadget: core: Check for unset descriptor
+    - scsi: ufs: core: Fix hba->last_dme_cmd_tstamp timestamp updating logic
+    - tick/broadcast: Move per CPU pointer access into the atomic section
+    - ntp: Clamp maxerror and esterror to operating range
+    - driver core: Fix uevent_show() vs driver detach race
+    - ntp: Safeguard against time_constant overflow
+    - scsi: mpt3sas: Remove scsi_dma_map() error messages
+    - scsi: mpt3sas: Avoid IOMMU page faults on REPORT ZONES
+    - serial: core: check uartclk for zero to avoid divide by zero
+    - genirq/irqdesc: Honor caller provided affinity in alloc_desc()
+    - power: supply: axp288_charger: Fix constant_charge_voltage writes
+    - power: supply: axp288_charger: Round constant_charge_voltage writes down
+    - tracing: Fix overflow in get_free_elt()
+    - x86/mtrr: Check if fixed MTRRs exist before saving them
+    - drm/bridge: analogix_dp: properly handle zero sized AUX transactions
+    - drm/mgag200: Set DDC timeout in milliseconds
+    - Fix gcc 4.9 build issue in 5.4.y
+    - kbuild: Fix '-S -c' in x86 stack protector scripts
+    - netfilter: nf_tables: set element extended ACK reporting support
+    - netfilter: nf_tables: prefer nft_chain_validate
+    - drm/i915/gem: Fix Virtual Memory mapping boundaries calculation
+    - arm64: cpufeature: Fix the visibility of compat hwcaps
+    - media: uvcvideo: Use entity get_cur in uvc_ctrl_set
+    - exec: Fix ToCToU between perm check and set-uid/gid usage
+    - nvme/pci: Add APST quirk for Lenovo N60z laptop
+    - ARM: dts: imx6qdl-kontron-samx6i: fix phy-mode
+    - media: Revert "media: dvb-usb: Fix unexpected infinite loop in
+      dvb_usb_read_remote_control()"
+    - Linux 5.4.282
+
+  * CVE-2024-26885
+    - bpf: Fix DEVMAP_HASH overflow check on 32-bit arches
+
+  * Focal update: v5.4.281 upstream stable release (LP: #2076097)
+    - gcc-plugins: Rename last_stmt() for GCC 14+
+    - filelock: Remove locks reliably when fcntl/close race is detected
+    - scsi: qedf: Set qed_slowpath_params to zero before use
+    - ACPI: EC: Abort address space access upon error
+    - ACPI: EC: Avoid returning AE_OK on errors in address space handler
+    - wifi: mac80211: mesh: init nonpeer_pm to active by default in mesh sdata
+    - wifi: mac80211: fix UBSAN noise in ieee80211_prep_hw_scan()
+    - Input: silead - Always support 10 fingers
+    - ila: block BH in ila_output()
+    - kconfig: gconf: give a proper initial state to the Save button
+    - kconfig: remove wrong expr_trans_bool()
+    - fs/file: fix the check in find_next_fd()
+    - mei: demote client disconnect warning on suspend to debug
+    - wifi: cfg80211: wext: add extra SIOCSIWSCAN data check
+    - KVM: PPC: Book3S HV: Prevent UAF in kvm_spapr_tce_attach_iommu_group()
+    - ALSA: hda/realtek: Add more codec ID to no shutup pins list
+    - mips: fix compat_sys_lseek syscall
+    - Input: elantech - fix touchpad state on resume for Lenovo N24
+    - bytcr_rt5640 : inverse jack detect for Archos 101 cesium
+    - ASoC: ti: davinci-mcasp: Set min period size using FIFO config
+    - ASoC: ti: omap-hdmi: Fix too long driver name
+    - can: kvaser_usb: fix return value for hif_usb_send_regout
+    - s390/sclp: Fix sclp_init() cleanup on failure
+    - ALSA: dmaengine_pcm: terminate dmaengine before synchronize
+    - net: usb: qmi_wwan: add Telit FN912 compositions
+    - net: mac802154: Fix racy device stats updates by DEV_STATS_INC() and
+      DEV_STATS_ADD()
+    - powerpc/pseries: Whitelist dtl slub object for copying to userspace
+    - powerpc/eeh: avoid possible crash when edev->pdev changes
+    - scsi: libsas: Fix exp-attached device scan after probe failure scanned in
+      again after probe failed
+    - Bluetooth: hci_core: cancel all works upon hci_unregister_dev()
+    - fs: better handle deep ancestor chains in is_subdir()
+    - spi: imx: Don't expect DMA for i.MX{25,35,50,51,53} cspi devices
+    - selftests/vDSO: fix clang build errors and warnings
+    - hfsplus: fix uninit-value in copy_name
+    - ARM: 9324/1: fix get_user() broken with veneer
+    - ACPI: processor_idle: Fix invalid comparison with insertion sort for latency
+    - drm/amdgpu: Fix signedness bug in sdma_v4_0_process_trap_irq()
+    - net: relax socket state check at accept time.
+    - ocfs2: add bounds checking to ocfs2_check_dir_entry()
+    - jfs: don't walk off the end of ealist
+    - ALSA: hda/realtek: Enable headset mic on Positivo SU C1400
+    - filelock: Fix fcntl/close race recovery compat path
+    - tun: add missing verification for short frame
+    - tap: add missing verification for short frame
+    - Linux 5.4.281
+
+  * Focal update: v5.4.283 upstream stable release (LP: #2080595) //
+    CVE-2024-45016
+    - netem: fix return value if duplicate enqueue fails
+
+  * CVE-2024-38630
+    - watchdog: cpu5wdt.c: Fix use-after-free bug caused by cpu5wdt_trigger
+
+  * CVE-2024-27397
+    - netfilter: nf_tables: use timestamp to check for set element timeout
+
+  * CVE-2024-26960
+    - mm: swap: fix race between free_swap_and_cache() and swapoff()
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Fri, 27 Sep 2024 14:40:47 +0200
+
+linux (5.4.0-196.216) focal; urgency=medium
+
+  * focal/linux: 5.4.0-196.216 -proposed tracker (LP: #2078205)
+
+  * CVE-2024-39494
+    - ima: Fix use-after-free on a dentry's dname.name
+
+  * CVE-2024-42160
+    - f2fs: check validation of fault attrs in f2fs_build_fault_attr()
+    - f2fs: Add inline to f2fs_build_fault_attr() stub
+
+  * CVE-2024-38570
+    - gfs2: Rename sd_{ glock => kill }_wait
+    - gfs2: Fix potential glock use-after-free on unmount
+
+  * CVE-2024-42228
+    - drm/amdgpu: Using uninitialized value *size when calling amdgpu_vce_cs_reloc
+
+  * CVE-2022-48791
+    - scsi: pm80xx: Fix TMF task completion race condition
+    - scsi: pm8001: Fix use-after-free for aborted TMF sas_task
+
+  * CVE-2024-26787
+    - mmc: mmci_sdmmc: Rename sdmmc_priv struct to sdmmc_idma
+    - mmc: mmci: stm32: use a buffer for unaligned DMA requests
+    - mmc: mmci: stm32: fix DMA API overlapping mappings warning
+
+  * CVE-2024-27012
+    - netfilter: nf_tables: restore set elements when delete set fails
+
+  * CVE-2022-48863
+    - mISDN: Fix memory leak in dsp_pipeline_build()
+
+  * CVE-2021-47188
+    - scsi: ufs: core: Improve SCSI abort handling
+
+  * CVE-2024-26677
+    - rxrpc: Fix delayed ACKs to not set the reference serial number
+
+ -- Manuel Diewald <manuel.diewald@canonical.com>  Thu, 29 Aug 2024 14:06:16 +0200
+
+linux (5.4.0-195.215) focal; urgency=medium
+
+  * focal/linux: 5.4.0-195.215 -proposed tracker (LP: #2075954)
+
+  * Focal update: v5.4.280 upstream stable release (LP: #2075175)
+    - Compiler Attributes: Add __uninitialized macro
+    - drm/lima: fix shared irq handling on driver remove
+    - media: dvb: as102-fe: Fix as10x_register_addr packing
+    - media: dvb-usb: dib0700_devices: Add missing release_firmware()
+    - IB/core: Implement a limit on UMAD receive List
+    - scsi: qedf: Make qedf_execute_tmf() non-preemptible
+    - drm/amdgpu: Initialize timestamp for some legacy SOCs
+    - drm/amd/display: Skip finding free audio for unknown engine_id
+    - media: dw2102: Don't translate i2c read into write
+    - sctp: prefer struct_size over open coded arithmetic
+    - firmware: dmi: Stop decoding on broken entry
+    - Input: ff-core - prefer struct_size over open coded arithmetic
+    - net: dsa: mv88e6xxx: Correct check for empty list
+    - media: dvb-frontends: tda18271c2dd: Remove casting during div
+    - media: s2255: Use refcount_t instead of atomic_t for num_channels
+    - media: dvb-frontends: tda10048: Fix integer overflow
+    - i2c: i801: Annotate apanel_addr as __ro_after_init
+    - powerpc/64: Set _IO_BASE to POISON_POINTER_DELTA not 0 for CONFIG_PCI=n
+    - orangefs: fix out-of-bounds fsid access
+    - powerpc/xmon: Check cpu id in commands "c#", "dp#" and "dx#"
+    - jffs2: Fix potential illegal address access in jffs2_free_inode
+    - s390/pkey: Wipe sensitive data on failure
+    - tcp: tcp_mark_head_lost is only valid for sack-tcp
+    - tcp: add ece_ack flag to reno sack functions
+    - net: tcp better handling of reordering then loss cases
+    - UPSTREAM: tcp: fix DSACK undo in fast recovery to call tcp_try_to_open()
+    - tcp_metrics: validate source addr length
+    - wifi: wilc1000: fix ies_len type in connect path
+    - bonding: Fix out-of-bounds read in bond_option_arp_ip_targets_set()
+    - selftests: fix OOM in msg_zerocopy selftest
+    - selftests: make order checking verbose in msg_zerocopy selftest
+    - inet_diag: Initialize pad field in struct inet_diag_req_v2
+    - nilfs2: fix inode number range checks
+    - nilfs2: add missing check for inode numbers on directory entries
+    - mm: optimize the redundant loop of mm_update_owner_next()
+    - can: kvaser_usb: Explicitly initialize family in leafimx driver_info struct
+    - fsnotify: Do not generate events for O_PATH file descriptors
+    - Revert "mm/writeback: fix possible divide-by-zero in wb_dirty_limits(),
+      again"
+    - drm/nouveau: fix null pointer dereference in nouveau_connector_get_modes
+    - drm/amdgpu/atomfirmware: silence UBSAN warning
+    - media: dw2102: fix a potential buffer overflow
+    - i2c: pnx: Fix potential deadlock warning from del_timer_sync() call in isr
+    - ALSA: hda/realtek: Enable headset mic of JP-IK LEAP W502 with ALC897
+    - nvme-multipath: find NUMA path only for online numa-node
+    - nilfs2: fix incorrect inode allocation from reserved inodes
+    - filelock: fix potential use-after-free in posix_lock_inode
+    - fs/dcache: Re-use value stored to dentry->d_flags instead of re-reading
+    - vfs: don't mod negative dentry count when on shrinker list
+    - tcp: add TCP_INFO status for failed client TFO
+    - tcp: fix incorrect undo caused by DSACK of TLP retransmit
+    - octeontx2-af: Fix incorrect value output on error path in
+      rvu_check_rsrc_availability()
+    - net: lantiq_etop: add blank line after declaration
+    - net: ethernet: lantiq_etop: fix double free in detach
+    - ppp: reject claimed-as-LCP but actually malformed packets
+    - udp: Set SOCK_RCU_FREE earlier in udp_lib_get_port().
+    - s390: Mark psw in __load_psw_mask() as __unitialized
+    - ARM: davinci: Convert comma to semicolon
+    - octeontx2-af: fix detection of IP layer
+    - USB: serial: option: add Telit generic core-dump composition
+    - USB: serial: option: add Telit FN912 rmnet compositions
+    - USB: serial: option: add Fibocom FM350-GL
+    - USB: serial: option: add support for Foxconn T99W651
+    - USB: serial: option: add Netprisma LCUK54 series modules
+    - USB: serial: option: add Rolling RW350-GL variants
+    - USB: Add USB_QUIRK_NO_SET_INTF quirk for START BP-850k
+    - usb: gadget: configfs: Prevent OOB read/write in usb_string_copy()
+    - USB: core: Fix duplicate endpoint bug by clearing reserved bits in the
+      descriptor
+    - hpet: Support 32-bit userspace
+    - nvmem: meson-efuse: Fix return value of nvmem callbacks
+    - ALSA: hda/realtek: Limit mic boost on VAIO PRO PX
+    - libceph: fix race between delayed_work() and ceph_monc_stop()
+    - SUNRPC: Fix RPC client cleaned up the freed pipefs dentries
+    - tcp: refactor tcp_retransmit_timer()
+    - net: tcp: fix unexcepted socket die when snd_wnd is 0
+    - tcp: use signed arithmetic in tcp_rtx_probe0_timed_out()
+    - tcp: avoid too many retransmit packets
+    - nilfs2: fix kernel bug on rename operation of broken directory
+    - i2c: rcar: bring hardware to known state when probing
+    - Linux 5.4.280
+
+  * [SRU] UBSAN warnings in bnx2x kernel driver (LP: #2074215) // Focal update:
+    v5.4.280 upstream stable release (LP: #2075175)
+    - bnx2x: Fix multiple UBSAN array-index-out-of-bounds
+
+  * Focal update: v5.4.279 upstream stable release (LP: #2073621)
+    - wifi: mac80211: mesh: Fix leak of mesh_preq_queue objects
+    - wifi: mac80211: Fix deadlock in ieee80211_sta_ps_deliver_wakeup()
+    - wifi: cfg80211: pmsr: use correct nla_get_uX functions
+    - wifi: iwlwifi: mvm: revert gen2 TX A-MPDU size to 64
+    - wifi: iwlwifi: dbg_ini: move iwl_dbg_tlv_free outside of debugfs ifdef
+    - wifi: iwlwifi: mvm: don't read past the mfuart notifcation
+    - ipv6: sr: block BH in seg6_output_core() and seg6_input_core()
+    - net: sched: sch_multiq: fix possible OOB write in multiq_tune()
+    - vxlan: Fix regression when dropping packets due to invalid src addresses
+    - tcp: count CLOSE-WAIT sockets for TCP_MIB_CURRESTAB
+    - net/mlx5: Stop waiting for PCI if pci channel is offline
+    - net/sched: taprio: always validate TCA_TAPRIO_ATTR_PRIOMAP
+    - ptp: Fix error message on failed pin verification
+    - af_unix: Annotate data-race of sk->sk_state in unix_inq_len().
+    - af_unix: Annotate data-races around sk->sk_state in unix_write_space() and
+      poll().
+    - af_unix: Annotate data-races around sk->sk_state in sendmsg() and recvmsg().
+    - af_unix: Annotate data-races around sk->sk_state in UNIX_DIAG.
+    - af_unix: Annotate data-race of net->unx.sysctl_max_dgram_qlen.
+    - af_unix: Use unix_recvq_full_lockless() in unix_stream_connect().
+    - af_unix: Use skb_queue_len_lockless() in sk_diag_show_rqlen().
+    - af_unix: Annotate data-race of sk->sk_shutdown in sk_diag_fill().
+    - ipv6: fix possible race in __fib6_drop_pcpu_from()
+    - usb: gadget: f_fs: Fix race between aio_cancel() and AIO request complete
+    - ASoC: ti: davinci-mcasp: remove redundant assignment to variable ret
+    - ASoC: ti: davinci-mcasp: remove always zero of davinci_mcasp_get_dt_params
+    - ASoC: ti: davinci-mcasp: Use platform_get_irq_byname_optional
+    - ASoC: ti: davinci-mcasp: Remove legacy dma_request parsing
+    - ASoC: ti: davinci-mcasp: Simplify the configuration parameter handling
+    - ASoC: ti: davinci-mcasp: Handle missing required DT properties
+    - ASoC: ti: davinci-mcasp: Fix race condition during probe
+    - drm/amd/display: Handle Y carry-over in VCP X.Y calculation
+    - serial: sc16is7xx: replace hardcoded divisor value with BIT() macro
+    - serial: sc16is7xx: fix bug in sc16is7xx_set_baud() when using prescaler
+    - selftests/mm: compaction_test: fix incorrect write of zero to nr_hugepages
+    - selftests/mm: conform test to TAP format output
+    - selftests/mm: compaction_test: fix bogus test success on Aarch64
+    - nilfs2: Remove check for PageError
+    - nilfs2: return the mapped address from nilfs_get_page()
+    - nilfs2: fix nilfs_empty_dir() misjudgment and long loop on I/O errors
+    - USB: class: cdc-wdm: Fix CPU lockup caused by excessive log messages
+    - mei: me: release irq in mei_me_pci_resume error path
+    - jfs: xattr: fix buffer overflow for invalid xattr
+    - xhci: Set correct transferred length for cancelled bulk transfers
+    - xhci: Apply reset resume quirk to Etron EJ188 xHCI host
+    - xhci: Apply broken streams quirk to Etron EJ188 xHCI host
+    - scsi: mpt3sas: Avoid test/set_bit() operating in non-allocated memory
+    - Input: try trimming too long modalias strings
+    - SUNRPC: return proper error from gss_wrap_req_priv
+    - gpio: tqmx86: fix typo in Kconfig label
+    - HID: core: remove unnecessary WARN_ON() in implement()
+    - iommu/amd: Fix sysfs leak in iommu init
+    - iommu: Return right value in iommu_sva_bind_device()
+    - HID: logitech-dj: Fix memory leak in logi_dj_recv_switch_to_dj_mode()
+    - liquidio: Adjust a NULL pointer handling path in lio_vf_rep_copy_packet
+    - drm/komeda: check for error-valued pointer
+    - drm/bridge/panel: Fix runtime warning on panel bridge release
+    - tcp: fix race in tcp_v6_syn_recv_sock()
+    - net/mlx5e: Fix features validation check for tunneled UDP (non-VXLAN)
+      packets
+    - Bluetooth: L2CAP: Fix rejecting L2CAP_CONN_PARAM_UPDATE_REQ
+    - netfilter: ipset: Fix race between namespace cleanup and gc in the list:set
+      type
+    - net/ipv6: Fix the RT cache flush via sysctl using a previous delay
+    - ionic: fix use after netif_napi_del()
+    - drivers: core: synchronize really_probe() and dev_uevent()
+    - drm/exynos/vidi: fix memory leak in .get_modes()
+    - drm/exynos: hdmi: report safe 640x480 mode as a fallback when no EDID found
+    - tracing/selftests: Fix kprobe event name test for .isra. functions
+    - vmci: prevent speculation leaks by sanitizing event in event_deliver()
+    - fs/proc: fix softlockup in __read_vmcore
+    - ocfs2: use coarse time for new created files
+    - ocfs2: fix races between hole punching and AIO+DIO
+    - PCI: rockchip-ep: Remove wrong mask on subsys_vendor_id
+    - dmaengine: axi-dmac: fix possible race in remove()
+    - intel_th: pci: Add Granite Rapids support
+    - intel_th: pci: Add Granite Rapids SOC support
+    - intel_th: pci: Add Sapphire Rapids SOC support
+    - intel_th: pci: Add Meteor Lake-S support
+    - intel_th: pci: Add Lunar Lake support
+    - nilfs2: fix potential kernel bug due to lack of writeback flag waiting
+    - tick/nohz_full: Don't abuse smp_call_function_single() in
+      tick_setup_device()
+    - hv_utils: drain the timesync packets on onchannelcallback
+    - hugetlb_encode.h: fix undefined behaviour (34 << 26)
+    - greybus: Fix use-after-free bug in gb_interface_release due to race
+      condition.
+    - usb-storage: alauda: Check whether the media is initialized
+    - i2c: at91: Fix the functionality flags of the slave-only interface
+    - rcutorture: Fix rcu_torture_one_read() pipe_count overflow comment
+    - selftests/bpf: Prevent client connect before server bind in
+      test_tc_tunnel.sh
+    - batman-adv: bypass empty buckets in batadv_purge_orig_ref()
+    - drop_monitor: replace spin_lock by raw_spin_lock
+    - scsi: qedi: Fix crash while reading debugfs attribute
+    - Bluetooth: ath3k: Fix multiple issues reported by checkpatch.pl
+    - powerpc/pseries: Enforce hcall result buffer validity and size
+    - powerpc/io: Avoid clang null pointer arithmetic warnings
+    - usb: misc: uss720: check for incompatible versions of the Belkin F5U002
+    - udf: udftime: prevent overflow in udf_disk_stamp_to_time()
+    - PCI/PM: Avoid D3cold for HP Pavilion 17 PC/1972 PCIe Ports
+    - MIPS: Octeon: Add PCIe link status check
+    - MIPS: Routerboard 532: Fix vendor retry check code
+    - mips: bmips: BCM6358: make sure CBR is correctly set
+    - cipso: fix total option length computation
+    - netrom: Fix a memory leak in nr_heartbeat_expiry()
+    - ipv6: prevent possible NULL deref in fib6_nh_init()
+    - ipv6: prevent possible NULL dereference in rt6_probe()
+    - xfrm6: check ip6_dst_idev() return value in xfrm6_get_saddr()
+    - netns: Make get_net_ns() handle zero refcount net
+    - net/sched: act_api: rely on rcu in tcf_idr_check_alloc
+    - net/sched: act_api: fix possible infinite loop in tcf_idr_check_alloc()
+    - virtio_net: checksum offloading handling fix
+    - netfilter: ipset: Fix suspicious rcu_dereference_protected()
+    - net: usb: rtl8150 fix unintiatilzed variables in rtl8150_get_link_ksettings
+    - regulator: core: Fix modpost error "regulator_get_regmap" undefined
+    - dmaengine: ioatdma: Fix missing kmem_cache_destroy()
+    - ACPICA: Revert "ACPICA: avoid Info: mapping multiple BARs. Your kernel is
+      fine."
+    - drm/radeon: fix UBSAN warning in kv_dpm.c
+    - gcov: add support for GCC 14
+    - i2c: ocores: set IACK bit after core is enabled
+    - ARM: dts: samsung: smdkv310: fix keypad no-autorepeat
+    - ARM: dts: samsung: exynos4412-origen: fix keypad no-autorepeat
+    - ARM: dts: samsung: smdk4412: fix keypad no-autorepeat
+    - arm64: dts: qcom: qcs404: fix bluetooth device address
+    - tracing: Add MODULE_DESCRIPTION() to preemptirq_delay_test
+    - Revert "kheaders: substituting --sort in archive creation"
+    - kheaders: explicitly define file modes for archived headers
+    - perf/core: Fix missing wakeup when waiting for context reference
+    - PCI: Add PCI_ERROR_RESPONSE and related definitions
+    - x86/amd_nb: Check for invalid SMN reads
+    - iio: dac: ad5592r-base: Replace indio_dev->mlock with own device lock
+    - iio: dac: ad5592r: un-indent code-block for scale read
+    - iio: dac: ad5592r: fix temperature channel scaling value
+    - pinctrl: fix deadlock in create_pinctrl() when handling -EPROBE_DEFER
+    - pinctrl: rockchip: fix pinmux bits for RK3328 GPIO2-B pins
+    - pinctrl: rockchip: fix pinmux bits for RK3328 GPIO3-B pins
+    - pinctrl: rockchip: fix pinmux reset in rockchip_pmx_set
+    - drm/amdgpu: fix UBSAN warning in kv_dpm.c
+    - netfilter: nf_tables: validate family when identifying table via handle
+    - ASoC: fsl-asoc-card: set priv->pdev before using it
+    - net: dsa: microchip: fix initial port flush problem
+    - net: phy: mchp: Add support for LAN8814 QUAD PHY
+    - net: phy: micrel: add Microchip KSZ 9477 to the device table
+    - sparc: fix old compat_sys_select()
+    - parisc: use correct compat recv/recvfrom syscalls
+    - netfilter: nf_tables: fully validate NFT_DATA_VALUE on store to data
+      registers
+    - drm/panel: ilitek-ili9881c: Fix warning with GPIO controllers that sleep
+    - mtd: partitions: redboot: Added conversion of operands to a larger type
+    - net/iucv: Avoid explicit cpumask var allocation on stack
+    - net/dpaa2: Avoid explicit cpumask var allocation on stack
+    - ALSA: emux: improve patch ioctl data validation
+    - media: dvbdev: Initialize sbuf
+    - soc: ti: wkup_m3_ipc: Send NULL dummy message instead of pointer message
+    - nvme: fixup comment for nvme RDMA Provider Type
+    - gpio: davinci: Validate the obtained number of IRQs
+    - x86: stop playing stack games in profile_pc()
+    - mmc: sdhci-pci: Convert PCIBIOS_* return codes to errnos
+    - mmc: sdhci: Do not invert write-protect twice
+    - mmc: sdhci: Do not lock spinlock around mmc_gpio_get_ro()
+    - iio: adc: ad7266: Fix variable checking bug
+    - iio: chemical: bme680: Fix pressure value output
+    - iio: chemical: bme680: Fix calibration data variable
+    - iio: chemical: bme680: Fix overflows in compensate() functions
+    - iio: chemical: bme680: Fix sensor data read operation
+    - net: usb: ax88179_178a: improve link status logs
+    - usb: gadget: printer: SS+ support
+    - usb: musb: da8xx: fix a resource leak in probe()
+    - usb: atm: cxacru: fix endpoint checking in cxacru_bind()
+    - tty: mcf: MCF54418 has 10 UARTS
+    - net: can: j1939: Initialize unused data in j1939_send_one()
+    - net: can: j1939: recover socket queue on CAN bus error during BAM
+      transmission
+    - net: can: j1939: enhanced error handling for tightly received RTS messages
+      in xtp_rx_rts_session_new
+    - csky, hexagon: fix broken sys_sync_file_range
+    - hexagon: fix fadvise64_64 calling conventions
+    - drm/nouveau/dispnv04: fix null pointer dereference in nv17_tv_get_ld_modes
+    - drm/nouveau/dispnv04: fix null pointer dereference in nv17_tv_get_hd_modes
+    - batman-adv: Don't accept TT entries for out-of-spec VIDs
+    - ata: libata-core: Fix double free on error
+    - ftruncate: pass a signed offset
+    - mtd: spinand: macronix: Add support for serial NAND flash
+    - pwm: stm32: Refuse too small period requests
+    - nfs: Leave pages in the pagecache if readpage failed
+    - ARM: dts: rockchip: rk3066a: add #sound-dai-cells to hdmi node
+    - arm64: dts: rockchip: Add sound-dai-cells for RK3368
+    - Linux 5.4.279
+
+  * CVE-2024-26921
+    - skbuff: introduce skb_expand_head()
+    - skb_expand_head() adjust skb->truesize incorrectly
+    - inet: inet_defrag: prevent sk release while still in use
+
+  * CVE-2024-26929
+    - scsi: qla2xxx: Fix double free of fcport
+
+  * CVE-2024-39484
+    - mmc: davinci: Don't strip remove function when driver is builtin
+
+  * CVE-2024-36901
+    - ipv6: prevent NULL dereference in ip6_output()
+
+  * CVE-2024-26830
+    - i40e: Refactoring VF MAC filters counting to make more reliable
+    - i40e: Fix MAC address setting for a VF via Host/VM
+    - i40e: Do not allow untrusted VF to remove administratively set MAC
+
+  * CVE-2024-24860
+    - Bluetooth: Fix atomicity violation in {min, max}_key_size_set
+
+  * CVE-2023-52760
+    - gfs2: Fix slab-use-after-free in gfs2_qd_dealloc
+
+  * CVE-2024-2201
+    - [Config] Set SPECTRE_BHI_ON=y
+
+  * CVE-2023-52629
+    - sh: push-switch: Reorder cleanup operations to avoid use-after-free bug
+
+  * CVE-2021-46926
+    - ALSA: hda: intel-sdw-acpi: harden detection of controller
+
+ -- Roxana Nicolescu <roxana.nicolescu@canonical.com>  Fri, 02 Aug 2024 20:11:01 +0200
+
+linux (5.4.0-192.212) focal; urgency=medium
+
+  * focal/linux: 5.4.0-192.212 -proposed tracker (LP: #2072305)
+
+  * Focal update: v5.4.278 upstream stable release (LP: #2071668)
+    - x86/tsc: Trust initial offset in architectural TSC-adjust MSRs
+    - speakup: Fix sizeof() vs ARRAY_SIZE() bug
+    - ring-buffer: Fix a race between readers and resize checks
+    - net: smc91x: Fix m68k kernel compilation for ColdFire CPU
+    - nilfs2: fix unexpected freezing of nilfs_segctor_sync()
+    - nilfs2: fix potential hang in nilfs_detach_log_writer()
+    - wifi: cfg80211: fix the order of arguments for trace events of the tx_rx_evt
+      class
+    - net: usb: qmi_wwan: add Telit FN920C04 compositions
+    - drm/amd/display: Set color_mgmt_changed to true on unsuspend
+    - ASoC: rt5645: Fix the electric noise due to the CBJ contacts floating
+    - ASoC: dt-bindings: rt5645: add cbj sleeve gpio property
+    - ASoC: da7219-aad: fix usage of device_get_named_child_node()
+    - drm/amdkfd: Flush the process wq before creating a kfd_process
+    - nvme: find numa distance only if controller has valid numa id
+    - openpromfs: finish conversion to the new mount API
+    - crypto: bcm - Fix pointer arithmetic
+    - firmware: raspberrypi: Use correct device for DMA mappings
+    - ecryptfs: Fix buffer size for tag 66 packet
+    - nilfs2: fix out-of-range warning
+    - parisc: add missing export of __cmpxchg_u8()
+    - crypto: ccp - drop platform ifdef checks
+    - s390/cio: fix tracepoint subchannel type field
+    - jffs2: prevent xattr node from overflowing the eraseblock
+    - null_blk: Fix missing mutex_destroy() at module removal
+    - md: fix resync softlockup when bitmap size is less than array size
+    - wifi: ath10k: poll service ready message before failing
+    - x86/boot: Ignore relocations in .notes sections in walk_relocs() too
+    - qed: avoid truncating work queue length
+    - scsi: ufs: qcom: Perform read back after writing reset bit
+    - scsi: ufs: cdns-pltfrm: Perform read back after writing HCLKDIV
+    - scsi: ufs: core: Perform read back after disabling interrupts
+    - scsi: ufs: core: Perform read back after disabling UIC_COMMAND_COMPL
+    - irqchip/alpine-msi: Fix off-by-one in allocation error path
+    - ACPI: disable -Wstringop-truncation
+    - cpufreq: Reorganize checks in cpufreq_offline()
+    - cpufreq: Split cpufreq_offline()
+    - cpufreq: Rearrange locking in cpufreq_remove_dev()
+    - cpufreq: exit() callback is optional
+    - scsi: libsas: Fix the failure of adding phy with zero-address to port
+    - scsi: hpsa: Fix allocation size for Scsi_Host private data
+    - x86/purgatory: Switch to the position-independent small code model
+    - wifi: ath10k: Fix an error code problem in
+      ath10k_dbg_sta_write_peer_debug_trigger()
+    - wifi: ath10k: populate board data for WCN3990
+    - tcp: minor optimization in tcp_add_backlog()
+    - tcp: fix a signed-integer-overflow bug in tcp_add_backlog()
+    - tcp: avoid premature drops in tcp_add_backlog()
+    - macintosh/via-macii: Fix "BUG: sleeping function called from invalid
+      context"
+    - wifi: carl9170: add a proper sanity check for endpoints
+    - wifi: ar5523: enable proper endpoint verification
+    - sh: kprobes: Merge arch_copy_kprobe() into arch_prepare_kprobe()
+    - Revert "sh: Handle calling csum_partial with misaligned data"
+    - HID: intel-ish-hid: ipc: Add check for pci_alloc_irq_vectors
+    - scsi: bfa: Ensure the copied buf is NUL terminated
+    - scsi: qedf: Ensure the copied buf is NUL terminated
+    - wifi: mwl8k: initialize cmd->addr[] properly
+    - usb: aqc111: stop lying about skb->truesize
+    - net: usb: sr9700: stop lying about skb->truesize
+    - m68k: Fix spinlock race in kernel thread creation
+    - m68k: mac: Fix reboot hang on Mac IIci
+    - net: ethernet: cortina: Locking fixes
+    - af_unix: Fix data races in unix_release_sock/unix_stream_sendmsg
+    - net: usb: smsc95xx: stop lying about skb->truesize
+    - net: openvswitch: fix overwriting ct original tuple for ICMPv6
+    - ipv6: sr: add missing seg6_local_exit
+    - ipv6: sr: fix incorrect unregister order
+    - ipv6: sr: fix invalid unregister error path
+    - drm/amd/display: Fix potential index out of bounds in color transformation
+      function
+    - mtd: rawnand: hynix: fixed typo
+    - fbdev: shmobile: fix snprintf truncation
+    - drm/mediatek: Add 0 size check to mtk_drm_gem_obj
+    - powerpc/fsl-soc: hide unused const variable
+    - fbdev: sisfb: hide unused variables
+    - media: ngene: Add dvb_ca_en50221_init return value check
+    - media: radio-shark2: Avoid led_names truncations
+    - platform/x86: wmi: Make two functions static
+    - fbdev: sh7760fb: allow modular build
+    - drm/arm/malidp: fix a possible null pointer dereference
+    - ASoC: tracing: Export SND_SOC_DAPM_DIR_OUT to its value
+    - drm/panel: simple: Add missing Innolux G121X1-L03 format, flags, connector
+    - RDMA/hns: Use complete parentheses in macros
+    - x86/insn: Fix PUSH instruction in x86 instruction decoder opcode map
+    - ext4: avoid excessive credit estimate in ext4_tmpfile()
+    - sunrpc: removed redundant procp check
+    - SUNRPC: Fix gss_free_in_token_pages()
+    - selftests/kcmp: Make the test output consistent and clear
+    - selftests/kcmp: remove unused open mode
+    - RDMA/IPoIB: Fix format truncation compilation errors
+    - netrom: fix possible dead-lock in nr_rt_ioctl()
+    - af_packet: do not call packet_read_pending() from tpacket_destruct_skb()
+    - sched/topology: Don't set SD_BALANCE_WAKE on cpuset domain relax
+    - sched/fair: Allow disabling sched_balance_newidle with
+      sched_relax_domain_level
+    - greybus: lights: check return of get_channel_from_mode
+    - soundwire: cadence/intel: simplify PDI/port mapping
+    - soundwire: intel: don't filter out PDI0/1
+    - soundwire: cadence_master: improve PDI allocation
+    - soundwire: cadence: fix invalid PDI offset
+    - dmaengine: idma64: Add check for dma_set_max_seg_size
+    - firmware: dmi-id: add a release callback function
+    - serial: max3100: Lock port->lock when calling uart_handle_cts_change()
+    - serial: max3100: Update uart_driver_registered on driver removal
+    - serial: max3100: Fix bitwise types
+    - greybus: arche-ctrl: move device table to its right location
+    - iio: pressure: dps310: support negative temperature values
+    - microblaze: Remove gcc flag for non existing early_printk.c file
+    - microblaze: Remove early printk call from cpuinfo-static.c
+    - usb: gadget: u_audio: Clear uac pointer when freed.
+    - stm class: Fix a double free in stm_register_device()
+    - ppdev: Remove usage of the deprecated ida_simple_xx() API
+    - ppdev: Add an error check in register_device
+    - extcon: max8997: select IRQ_DOMAIN instead of depending on it
+    - f2fs: fix to release node block count in error path of f2fs_new_node_page()
+    - serial: sh-sci: protect invalidating RXDMA on shutdown
+    - libsubcmd: Fix parse-options memory leak
+    - Input: ims-pcu - fix printf string overflow
+    - Input: pm8xxx-vibrator - correct VIB_MAX_LEVELS calculation
+    - drm/msm/dpu: Always flush the slave INTF on the CTL
+    - um: Fix return value in ubd_init()
+    - um: Add winch to winch_handlers before registering winch IRQ
+    - media: stk1160: fix bounds checking in stk1160_copy_video()
+    - scsi: qla2xxx: Replace all non-returning strlcpy() with strscpy()
+    - powerpc/pseries: Add failure related checks for h_get_mpp and h_get_ppp
+    - um: Fix the -Wmissing-prototypes warning for __switch_mm
+    - media: cec: cec-adap: always cancel work in cec_transmit_msg_fh
+    - media: cec: cec-api: add locking in cec_release()
+    - null_blk: Fix the WARNING: modpost: missing MODULE_DESCRIPTION()
+    - x86/kconfig: Select ARCH_WANT_FRAME_POINTERS again when
+      UNWINDER_FRAME_POINTER=y
+    - [Config] Update CONFIG_ARCH_WANT_FRAME_POINTERS
+    - nfc: nci: Fix uninit-value in nci_rx_work
+    - sunrpc: fix NFSACL RPC retry on soft mount
+    - ipv6: sr: fix memleak in seg6_hmac_init_algo
+    - params: lift param_set_uint_minmax to common code
+    - tcp: Fix shift-out-of-bounds in dctcp_update_alpha().
+    - openvswitch: Set the skbuff pkt_type for proper pmtud support.
+    - arm64: asm-bug: Add .align 2 to the end of __BUG_ENTRY
+    - virtio: delete vq in vp_find_vqs_msix() when request_irq() fails
+    - net: fec: avoid lock evasion when reading pps_enable
+    - nfc: nci: Fix kcov check in nci_rx_work()
+    - nfc: nci: Fix handling of zero-length payload packets in nci_rx_work()
+    - netfilter: nfnetlink_queue: acquire rcu_read_lock() in
+      instance_destroy_rcu()
+    - spi: Don't mark message DMA mapped when no transfer in it is
+    - nvmet: fix ns enable/disable possible hang
+    - net/mlx5e: Use rx_missed_errors instead of rx_dropped for reporting buffer
+      exhaustion
+    - dma-buf/sw-sync: don't enable IRQ from sync_print_obj()
+    - enic: Validate length of nl attributes in enic_set_vf_port
+    - smsc95xx: remove redundant function arguments
+    - smsc95xx: use usbnet->driver_priv
+    - net: usb: smsc95xx: fix changing LED_SEL bit value updated from EEPROM
+    - net:fec: Add fec_enet_deinit()
+    - netfilter: tproxy: bail out if IP has been disabled on the device
+    - kconfig: fix comparison to constant symbols, 'm', 'n'
+    - spi: stm32: Don't warn about spurious interrupts
+    - ipvlan: Dont Use skb->sk in ipvlan_process_v{4,6}_outbound
+    - ALSA: timer: Set lower bound of start tick time
+    - genirq/cpuhotplug, x86/vector: Prevent vector leak during CPU offline
+    - SUNRPC: Fix loop termination condition in gss_free_in_token_pages()
+    - binder: fix max_thread type inconsistency
+    - mmc: core: Do not force a retune before RPMB switch
+    - io_uring: fail NOP if non-zero op flags is passed in
+    - afs: Don't cross .backup mountpoint from backup volume
+    - nilfs2: fix use-after-free of timer for log writer thread
+    - vxlan: Fix regression when dropping packets due to invalid src addresses
+    - x86/mm: Remove broken vsyscall emulation code from the page fault code
+    - f2fs: fix to do sanity check on i_xattr_nid in sanity_check_inode()
+    - media: lgdt3306a: Add a check against null-pointer-def
+    - drm/amdgpu: add error handle to avoid out-of-bounds
+    - ata: pata_legacy: make legacy_exit() work again
+    - ACPI: resource: Do IRQ override on TongFang GXxHRXx and GMxHGxx
+    - arm64: tegra: Correct Tegra132 I2C alias
+    - md/raid5: fix deadlock that raid5d() wait for itself to clear
+      MD_SB_CHANGE_PENDING
+    - wifi: rtl8xxxu: Fix the TX power of RTL8192CU, RTL8723AU
+    - arm64: dts: hi3798cv200: fix the size of GICR
+    - media: mc: mark the media devnode as registered from the, start
+    - media: mxl5xx: Move xpt structures off stack
+    - media: v4l2-core: hold videodev_lock until dev reg, finishes
+    - fbdev: savage: Handle err return when savagefb_check_var failed
+    - KVM: arm64: Allow AArch32 PSTATE.M to be restored as System mode
+    - crypto: ecrdsa - Fix module auto-load on add_key
+    - crypto: qat - Fix ADF_DEV_RESET_SYNC memory leak
+    - net/ipv6: Fix route deleting failure when metric equals 0
+    - net/9p: fix uninit-value in p9_client_rpc()
+    - intel_th: pci: Add Meteor Lake-S CPU support
+    - sparc64: Fix number of online CPUs
+    - kdb: Fix buffer overflow during tab-complete
+    - kdb: Use format-strings rather than '\0' injection in kdb_read()
+    - kdb: Fix console handling when editing and tab-completing commands
+    - kdb: Merge identical case statements in kdb_read()
+    - kdb: Use format-specifiers rather than memset() for padding in kdb_read()
+    - net: fix __dst_negative_advice() race
+    - xsk: validate user input for XDP_{UMEM|COMPLETION}_FILL_RING
+    - sparc: move struct termio to asm/termios.h
+    - ext4: fix mb_cache_entry's e_refcnt leak in ext4_xattr_block_cache_find()
+    - s390/ap: Fix crash in AP internal function modify_bitmap()
+    - nfs: fix undefined behavior in nfs_block_bits()
+    - Linux 5.4.278
+
+  * CVE-2024-27019
+    - netfilter: nf_tables: restrict tunnel object to NFPROTO_NETDEV
+    - netfilter: nf_tables: Fix potential data-race in __nft_obj_type_get()
+
+  * CVE-2024-26886
+    - Bluetooth: af_bluetooth: Fix deadlock
+
+  * CVE-2023-52752
+    - smb: client: fix use-after-free bug in cifs_debug_data_proc_show()
+
+  * CVE-2022-48674
+    - erofs: fix pcluster use-after-free on UP platforms
+
+  * Focal update: v5.4.277 upstream stable release (LP: #2070179)
+    - pinctrl: core: handle radix_tree_insert() errors in
+      pinctrl_register_one_pin()
+    - ext4: fix bug_on in __es_tree_search
+    - Revert "selftests: mm: fix map_hugetlb failure on 64K page size systems"
+    - Revert "net: bcmgenet: use RGMII loopback for MAC reset"
+    - net: bcmgenet: keep MAC in reset until PHY is up
+    - net: bcmgenet: synchronize EXT_RGMII_OOB_CTRL access
+    - net: bcmgenet: synchronize use of bcmgenet_set_rx_mode()
+    - net: bcmgenet: synchronize UMAC_CMD access
+    - smb: client: fix potential OOBs in smb2_parse_contexts()
+    - arm64: dts: qcom: Fix 'interrupt-map' parent address cells
+    - btrfs: add missing mutex_unlock in btrfs_relocate_sys_chunks()
+    - drm/amdgpu: Fix possible NULL dereference in
+      amdgpu_ras_query_error_status_helper()
+    - usb: typec: ucsi: displayport: Fix potential deadlock
+    - serial: kgdboc: Fix NMI-safety problems from keyboard reset code
+    - docs: kernel_include.py: Cope with docutils 0.21
+    - Linux 5.4.277
+
+  * Focal update: v5.4.276 upstream stable release (LP: #2069758)
+    - dmaengine: pl330: issue_pending waits until WFP state
+    - dmaengine: Revert "dmaengine: pl330: issue_pending waits until WFP state"
+    - wifi: nl80211: don't free NULL coalescing rule
+    - pinctrl: core: delete incorrect free in pinctrl_enable()
+    - pinctrl: mediatek: Check gpio pin number and use binary search in
+      mtk_hw_pin_field_lookup()
+    - pinctrl: mediatek: Supporting driving setting without mapping current to
+      register value
+    - pinctrl: mediatek: Refine mtk_pinconf_get() and mtk_pinconf_set()
+    - pinctrl: mediatek: Refine mtk_pinconf_get()
+    - pinctrl: mediatek: Backward compatible to previous Mediatek's bias-pull
+      usage
+    - pinctrl: mediatek: remove shadow variable declaration
+    - pinctrl: mediatek: paris: Fix PIN_CONFIG_BIAS_* readback
+    - pinctrl: mediatek: paris: Rework mtk_pinconf_{get,set} switch/case logic
+    - pinctrl: mediatek: paris: Rework support for
+      PIN_CONFIG_{INPUT,OUTPUT}_ENABLE
+    - sunrpc: add a struct rpc_stats arg to rpc_create_args
+    - nfs: expose /proc/net/sunrpc/nfs in net namespaces
+    - nfs: make the rpc_stat per net namespace
+    - nfs: Handle error of rpc_proc_register() in nfs_net_init().
+    - power: rt9455: hide unused rt9455_boost_voltage_values
+    - pinctrl: devicetree: fix refcount leak in pinctrl_dt_to_map()
+    - s390/mm: Fix storage key clearing for guest huge pages
+    - s390/mm: Fix clearing storage keys for huge pages
+    - bna: ensure the copied buf is NUL terminated
+    - nsh: Restore skb->{protocol,data,mac_header} for outer header in
+      nsh_gso_segment().
+    - net l2tp: drop flow hash on forward
+    - net: qede: use return from qede_parse_flow_attr() for flow_spec
+    - net: dsa: mv88e6xxx: Add number of MACs in the ATU
+    - net: dsa: mv88e6xxx: Fix number of databases for 88E6141 / 88E6341
+    - net: bridge: fix multicast-to-unicast with fraglist GSO
+    - tipc: fix a possible memleak in tipc_buf_append
+    - clk: sunxi-ng: h6: Reparent CPUX during PLL CPUX rate change
+    - scsi: lpfc: Update lpfc_ramp_down_queue_handler() logic
+    - gfs2: Fix invalid metadata access in punch_hole
+    - wifi: mac80211: fix ieee80211_bss_*_flags kernel-doc
+    - wifi: cfg80211: fix rdev_dump_mpp() arguments order
+    - net: mark racy access on sk->sk_rcvbuf
+    - scsi: bnx2fc: Remove spin_lock_bh while releasing resources after upload
+    - ALSA: line6: Zero-initialize message buffers
+    - net: bcmgenet: Reset RBUF on first open
+    - ata: sata_gemini: Check clk_enable() result
+    - firewire: ohci: mask bus reset interrupts between ISR and bottom half
+    - tools/power turbostat: Fix added raw MSR output
+    - tools/power turbostat: Fix Bzy_MHz documentation typo
+    - btrfs: make btrfs_clear_delalloc_extent() free delalloc reserve
+    - btrfs: always clear PERTRANS metadata during commit
+    - scsi: target: Fix SELinux error when systemd-modules loads the target module
+    - gpu: host1x: Do not setup DMA for virtual devices
+    - MIPS: scall: Save thread_info.syscall unconditionally on entry
+    - selftests: timers: Fix valid-adjtimex signed left-shift undefined behavior
+    - fs/9p: only translate RWX permissions for plain 9P2000
+    - fs/9p: translate O_TRUNC into OTRUNC
+    - 9p: explicitly deny setlease attempts
+    - gpio: wcove: Use -ENOTSUPP consistently
+    - gpio: crystalcove: Use -ENOTSUPP consistently
+    - clk: Don't hold prepare_lock when calling kref_put()
+    - fs/9p: drop inodes immediately on non-.L too
+    - net:usb:qmi_wwan: support Rolling modules
+    - pinctrl: mediatek: Fix fallback call path
+    - xfrm: Preserve vlan tags for transport mode software GRO
+    - tcp: defer shutdown(SEND_SHUTDOWN) for TCP_SYN_RECV sockets
+    - tcp: Use refcount_inc_not_zero() in tcp_twsk_unique().
+    - Bluetooth: Fix use-after-free bugs caused by sco_sock_timeout
+    - Bluetooth: l2cap: fix null-ptr-deref in l2cap_chan_timeout
+    - rtnetlink: Correct nested IFLA_VF_VLAN_LIST attribute validation
+    - phonet: fix rtm_phonet_notify() skb allocation
+    - net: bridge: fix corrupted ethernet header on multicast-to-unicast
+    - ipv6: fib6_rules: avoid possible NULL dereference in fib6_rule_action()
+    - net: qede: sanitize 'rc' in qede_add_tc_flower_fltr()
+    - net: qede: use return from qede_parse_flow_attr() for flower
+    - firewire: nosy: ensure user_length is taken into account when fetching
+      packet contents
+    - usb: gadget: composite: fix OS descriptors w_value logic
+    - usb: gadget: f_fs: Fix a race condition when processing setup packets.
+    - tipc: fix UAF in error path
+    - dyndbg: fix old BUG_ON in >control parser
+    - drm/vmwgfx: Fix invalid reads in fence signaled events
+    - net: fix out-of-bounds access in ops_init
+    - regulator: core: fix debugfs creation regression
+    - pinctrl: mediatek: Fix fallback behavior for bias_set_combo
+    - pinctrl: mediatek: Fix some off by one bugs
+    - pinctrl: mediatek: remove set but not used variable 'e'
+    - pinctrl: mediatek: paris: Fix PIN_CONFIG_INPUT_SCHMITT_ENABLE readback
+    - Linux 5.4.276
+
+  * Freezing user space processes failed after 20.008 seconds (1 tasks refusing
+    to freeze, wq_busy=0) (LP: #2061091)
+    - ALSA: Fix deadlocks with kctl removals at disconnection
+
+  * CVE-2024-36016
+    - tty: n_gsm: fix possible out-of-bounds in gsm0_receive()
+
+  * CVE-2022-48655
+    - firmware: arm_scmi: Harden accesses to the reset domains
+
+  * CVE-2024-26907
+    - RDMA/mlx5: Fix fortify source warning while accessing Eth segment
+
+  * CVE-2024-26585
+    - tls: fix race between tx work scheduling and socket close
+
+  * CVE-2024-26584
+    - net: tls: handle backlogging of crypto requests
+
+  * CVE-2024-26583
+    - net/tls: Replace TLS_RX_SYNC_RUNNING with RCU
+    - net/tls: Fix use-after-free after the TLS device goes down and up
+    - tls: splice_read: fix record type check
+    - tls splice: remove inappropriate flags checking for MSG_PEEK
+    - tls: splice_read: fix accessing pre-processed records
+    - tls: Fix context leak on tls_device_down
+    - net/tls: Check for errors in tls_device_init
+    - net/tls: Remove the context from the list in tls_device_down
+    - net/tls: pass context to tls_device_decrypted()
+    - net/tls: Perform immediate device ctx cleanup when possible
+    - net/tls: Multi-threaded calls to TX tls_dev_del
+    - net: tls: avoid discarding data on record close
+    - tls: rx: don't store the record type in socket context
+    - tls: rx: don't store the decryption status in socket context
+    - tls: rx: don't issue wake ups when data is decrypted
+    - tls: rx: refactor decrypt_skb_update()
+    - tls: hw: rx: use return value of tls_device_decrypted() to carry status
+    - tls: rx: drop unnecessary arguments from tls_setup_from_iter()
+    - tls: rx: don't report text length from the bowels of decrypt
+    - tls: rx: wrap decryption arguments in a structure
+    - tls: rx: factor out writing ContentType to cmsg
+    - tls: rx: don't track the async count
+    - tls: rx: assume crypto always calls our callback
+    - tls: rx: use async as an in-out argument
+    - tls: decrement decrypt_pending if no async completion will be called
+    - net: tls: fix async vs NIC crypto offload
+    - tls: rx: simplify async wait
+    - tls: extract context alloc/initialization out of tls_set_sw_offload
+    - net: tls: factor out tls_*crypt_async_wait()
+    - tls: fix race between async notify and socket close
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Fri, 05 Jul 2024 11:00:53 +0200
+
+linux (5.4.0-189.209) focal; urgency=medium
+
+  * focal/linux: 5.4.0-189.209 -proposed tracker (LP: #2068454)
+
+  * Focal update: v5.4.275 upstream stable release (LP: #2067865)
+    - batman-adv: Avoid infinite loop trying to resize local TT
+    - Bluetooth: Fix memory leak in hci_req_sync_complete()
+    - nouveau: fix function cast warning
+    - net: openvswitch: fix unwanted error log on timeout policy probing
+    - u64_stats: fix u64_stats_init() for lockdep when used repeatedly in one file
+    - geneve: fix header validation in geneve[6]_xmit_skb
+    - ipv6: fib: hide unused 'pn' variable
+    - ipv4/route: avoid unused-but-set-variable warning
+    - ipv6: fix race condition between ipv6_get_ifaddr and ipv6_del_addr
+    - net/mlx5: Properly link new fs rules into the tree
+    - net: ena: Fix potential sign extension issue
+    - btrfs: qgroup: correctly model root qgroup rsv in convert
+    - drm/client: Fully protect modes[] with dev->mode_config.mutex
+    - vhost: Add smp_rmb() in vhost_vq_avail_empty()
+    - selftests: timers: Fix abs() warning in posix_timers test
+    - x86/apic: Force native_apic_mem_read() to use the MOV instruction
+    - btrfs: record delayed inode root in transaction
+    - selftests/ftrace: Limit length in subsystem-enable tests
+    - kprobes: Fix possible use-after-free issue on kprobe registration
+    - Revert "tracing/trigger: Fix to return error if failed to alloc snapshot"
+    - netfilter: nf_tables: Fix potential data-race in __nft_expr_type_get()
+    - tun: limit printing rate when illegal packet received by tun dev
+    - RDMA/rxe: Fix the problem "mutex_destroy missing"
+    - RDMA/mlx5: Fix port number for counter query in multi-port configuration
+    - drm: nv04: Fix out of bounds access
+    - clk: Remove prepare_lock hold assertion in __clk_release()
+    - clk: Mark 'all_lists' as const
+    - clk: remove extra empty line
+    - clk: Print an info line before disabling unused clocks
+    - clk: Initialize struct clk_core kref earlier
+    - clk: Get runtime PM before walking tree during disable_unused
+    - x86/cpufeatures: Fix dependencies for GFNI, VAES, and VPCLMULQDQ
+    - comedi: vmk80xx: fix incomplete endpoint checking
+    - serial/pmac_zilog: Remove flawed mitigation for rx irq flood
+    - USB: serial: option: add Fibocom FM135-GL variants
+    - USB: serial: option: add support for Fibocom FM650/FG650
+    - USB: serial: option: add Lonsung U8300/U9300 product
+    - USB: serial: option: support Quectel EM060K sub-models
+    - USB: serial: option: add Rolling RW101-GL and RW135-GL support
+    - USB: serial: option: add Telit FN920C04 rmnet compositions
+    - usb: dwc2: host: Fix dereference issue in DDMA completion flow.
+    - speakup: Avoid crash on very long word
+    - fs: sysfs: Fix reference leak in sysfs_break_active_protection()
+    - nouveau: fix instmem race condition around ptr stores
+    - nilfs2: fix OOB in nilfs_set_de_type
+    - KVM: async_pf: Cleanup kvm_setup_async_pf()
+    - arm64: dts: rockchip: fix alphabetical ordering RK3399 puma
+    - arm64: dts: rockchip: enable internal pull-up on PCIE_WAKE# for RK3399 Puma
+    - arm64: dts: mediatek: mt7622: fix IR nodename
+    - arm64: dts: mediatek: mt7622: fix ethernet controller "compatible"
+    - arm64: dts: mediatek: mt7622: drop "reset-names" from thermal block
+    - arm64: dts: mt2712: add ethernet device node
+    - arm64: dts: mediatek: mt2712: fix validation errors
+    - ARC: [plat-hsdk]: Remove misplaced interrupt-cells property
+    - vxlan: drop packets from invalid src-address
+    - mlxsw: core: Unregister EMAD trap using FORWARD action
+    - NFC: trf7970a: disable all regulators on removal
+    - net: usb: ax88179_178a: stop lying about skb->truesize
+    - net: gtp: Fix Use-After-Free in gtp_dellink
+    - ipvs: Fix checksumming on GSO of SCTP packets
+    - net: openvswitch: Fix Use-After-Free in ovs_ct_exit
+    - mlxsw: spectrum_acl_tcam: Fix race during rehash delayed work
+    - mlxsw: spectrum_acl_tcam: Fix possible use-after-free during activity update
+    - mlxsw: spectrum_acl_tcam: Fix possible use-after-free during rehash
+    - mlxsw: spectrum_acl_tcam: Rate limit error message
+    - mlxsw: spectrum_acl_tcam: Fix memory leak during rehash
+    - mlxsw: spectrum_acl_tcam: Fix warning during rehash
+    - mlxsw: spectrum_acl_tcam: Fix incorrect list API usage
+    - mlxsw: spectrum_acl_tcam: Fix memory leak when canceling rehash work
+    - i40e: Do not use WQ_MEM_RECLAIM flag for workqueue
+    - iavf: Fix TC config comparison with existing adapter TC config
+    - af_unix: Suppress false-positive lockdep splat for spin_lock() in
+      __unix_gc().
+    - serial: core: Provide port lock wrappers
+    - serial: mxs-auart: add spinlock around changing cts state
+    - Revert "crypto: api - Disallow identical driver names"
+    - net/mlx5e: Fix a race in command alloc flow
+    - tracing: Show size of requested perf buffer
+    - tracing: Increase PERF_MAX_TRACE_SIZE to handle Sentinel1 and docker
+      together
+    - Bluetooth: Fix type of len in {l2cap,sco}_sock_getsockopt_old()
+    - Bluetooth: btusb: Add Realtek RTL8852BE support ID 0x0bda:0x4853
+    - btrfs: fix information leak in btrfs_ioctl_logical_to_ino()
+    - arm64: dts: rockchip: enable internal pull-up for Q7_THRM# on RK3399 Puma
+    - drm/amdgpu: Fix leak when GPU memory allocation fails
+    - irqchip/gic-v3-its: Prevent double free on error
+    - ethernet: Add helper for assigning packet type when dest address does not
+      match device address
+    - net: b44: set pause params only when interface is up
+    - stackdepot: respect __GFP_NOLOCKDEP allocation flag
+    - mtd: diskonchip: work around ubsan link failure
+    - tcp: Clean up kernel listener's reqsk in inet_twsk_purge()
+    - tcp: Fix NEW_SYN_RECV handling in inet_twsk_purge()
+    - dmaengine: owl: fix register access functions
+    - idma64: Don't try to serve interrupts when device is powered off
+    - i2c: smbus: fix NULL function pointer dereference
+    - HID: i2c-hid: remove I2C_HID_READ_PENDING flag to prevent lock-up
+    - bounds: Use the right number of bits for power-of-two CONFIG_NR_CPUS
+    - udp: preserve the connected status if only UDP cmsg
+    - serial: core: fix kernel-doc for uart_port_unlock_irqrestore()
+    - Linux 5.4.275
+
+  * Focal update: v5.4.274 upstream stable release (LP: #2067857)
+    - amdkfd: use calloc instead of kzalloc to avoid integer overflow
+    - Documentation/hw-vuln: Update spectre doc
+    - x86/cpu: Support AMD Automatic IBRS
+    - x86/bugs: Use sysfs_emit()
+    - timers: Update kernel-doc for various functions
+    - timers: Use del_timer_sync() even on UP
+    - timers: Rename del_timer_sync() to timer_delete_sync()
+    - media: staging: ipu3-imgu: Set fields before media_entity_pads_init()
+    - clk: qcom: gcc-sdm845: Add soft dependency on rpmhpd
+    - smack: Set SMACK64TRANSMUTE only for dirs in smack_inode_setxattr()
+    - smack: Handle SMACK64TRANSMUTE in smack_inode_setsecurity()
+    - ARM: dts: mmp2-brownstone: Don't redeclare phandle references
+    - arm: dts: marvell: Fix maxium->maxim typo in brownstone dts
+    - serial: max310x: fix NULL pointer dereference in I2C instantiation
+    - KVM: Always flush async #PF workqueue when vCPU is being destroyed
+    - sparc64: NMI watchdog: fix return value of __setup handler
+    - sparc: vDSO: fix return value of __setup handler
+    - crypto: qat - fix double free during reset
+    - crypto: qat - resolve race condition during AER recovery
+    - selftests/mqueue: Set timeout to 180 seconds
+    - ext4: correct best extent lstart adjustment logic
+    - fat: fix uninitialized field in nostale filehandles
+    - ubifs: Set page uptodate in the correct place
+    - ubi: Check for too small LEB size in VTBL code
+    - ubi: correct the calculation of fastmap size
+    - mtd: rawnand: meson: fix scrambling mode value in command macro
+    - parisc: Do not hardcode registers in checksum functions
+    - parisc: Fix ip_fast_csum
+    - parisc: Fix csum_ipv6_magic on 32-bit systems
+    - parisc: Fix csum_ipv6_magic on 64-bit systems
+    - parisc: Strip upper 32 bit of sum in csum_ipv6_magic for 64-bit builds
+    - PM: suspend: Set mem_sleep_current during kernel command line setup
+    - clk: qcom: gcc-ipq8074: fix terminating of frequency table arrays
+    - clk: qcom: mmcc-apq8084: fix terminating of frequency table arrays
+    - clk: qcom: mmcc-msm8974: fix terminating of frequency table arrays
+    - powerpc/fsl: Fix mfpmr build errors with newer binutils
+    - USB: serial: ftdi_sio: add support for GMC Z216C Adapter IR-USB
+    - USB: serial: add device ID for VeriFone adapter
+    - USB: serial: cp210x: add ID for MGP Instruments PDS100
+    - USB: serial: option: add MeiG Smart SLM320 product
+    - USB: serial: cp210x: add pid/vid for TDK NC0110013M and MM0110113M
+    - PM: sleep: wakeirq: fix wake irq warning in system suspend
+    - mmc: tmio: avoid concurrent runs of mmc_request_done()
+    - fuse: don't unhash root
+    - btrfs: fix off-by-one chunk length calculation at contains_pending_extent()
+    - PCI: Drop pci_device_remove() test of pci_dev->driver
+    - PCI/PM: Drain runtime-idle callbacks before driver removal
+    - Revert "Revert "md/raid5: Wait for MD_SB_CHANGE_PENDING in raid5d""
+    - dm-raid: fix lockdep waring in "pers->hot_add_disk"
+    - mmc: core: Fix switch on gp3 partition
+    - hwmon: (amc6821) add of_match table
+    - ext4: fix corruption during on-line resize
+    - firmware: meson_sm: Rework driver as a proper platform driver
+    - nvmem: meson-efuse: fix function pointer type mismatch
+    - slimbus: core: Remove usage of the deprecated ida_simple_xx() API
+    - speakup: Fix 8bit characters from direct synth
+    - kbuild: Move -Wenum-{compare-conditional,enum-conversion} into W=1
+    - vfio/platform: Disable virqfds on cleanup
+    - ring-buffer: Fix resetting of shortest_full
+    - ring-buffer: Fix full_waiters_pending in poll
+    - soc: fsl: qbman: Always disable interrupts when taking cgr_lock
+    - soc: fsl: qbman: Add helper for sanity checking cgr ops
+    - soc: fsl: qbman: Add CGR update function
+    - soc: fsl: qbman: Use raw spinlock for cgr_lock
+    - s390/zcrypt: fix reference counting on zcrypt card objects
+    - drm/exynos: do not return negative values from .get_modes()
+    - drm/imx/ipuv3: do not return negative values from .get_modes()
+    - drm/vc4: hdmi: do not return negative values from .get_modes()
+    - memtest: use {READ,WRITE}_ONCE in memory scanning
+    - nilfs2: fix failure to detect DAT corruption in btree and direct mappings
+    - nilfs2: use a more common logging style
+    - nilfs2: prevent kernel bug at submit_bh_wbc()
+    - x86/CPU/AMD: Update the Zenbleed microcode revisions
+    - ahci: asm1064: correct count of reported ports
+    - ahci: asm1064: asm1166: don't limit reported ports
+    - dm snapshot: fix lockup in dm_exception_table_exit
+    - comedi: comedi_test: Prevent timers rescheduling during deletion
+    - netfilter: nf_tables: reject constant set with timeout
+    - xfrm: Avoid clang fortify warning in copy_to_user_tmpl()
+    - ALSA: hda/realtek - Fix headset Mic no show at resume back for Lenovo ALC897
+      platform
+    - USB: usb-storage: Prevent divide-by-0 error in isd200_ata_command
+    - usb: gadget: ncm: Fix handling of zero block length packets
+    - usb: port: Don't try to peer unused USB ports based on location
+    - tty: serial: fsl_lpuart: avoid idle preamble pending if CTS is enabled
+    - vt: fix unicode buffer corruption when deleting characters
+    - fs/aio: Check IOCB_AIO_RW before the struct aio_kiocb conversion
+    - objtool: is_fentry_call() crashes if call has no destination
+    - objtool: Add support for intra-function calls
+    - x86/speculation: Support intra-function call validation
+    - xen/events: close evtchn after mapping cleanup
+    - printk: Update @console_may_schedule in console_trylock_spinning()
+    - btrfs: allocate btrfs_ioctl_defrag_range_args on stack
+    - Revert "loop: Check for overflow while configuring loop"
+    - loop: Call loop_config_discard() only after new config is applied
+    - loop: Remove sector_t truncation checks
+    - loop: Factor out setting loop device size
+    - loop: Refactor loop_set_status() size calculation
+    - loop: Factor out configuring loop from status
+    - loop: Check for overflow while configuring loop
+    - loop: loop_set_status_from_info() check before assignment
+    - perf/core: Fix reentry problem in perf_output_read_group()
+    - efivarfs: Request at most 512 bytes for variable names
+    - powerpc: xor_vmx: Add '-mhard-float' to CFLAGS
+    - bounds: support non-power-of-two CONFIG_NR_CPUS
+    - vt: fix memory overlapping when deleting chars in the buffer
+    - mm/memory-failure: fix an incorrect use of tail pages
+    - mm/migrate: set swap entry values of THP tail pages properly.
+    - wifi: mac80211: check/clear fast rx for non-4addr sta VLAN changes
+    - exec: Fix NOMMU linux_binprm::exec in transfer_args_to_stack()
+    - mmc: core: Initialize mmc_blk_ioc_data
+    - mmc: core: Avoid negative index with array access
+    - ALSA: sh: aica: reorder cleanup operations to avoid UAF bugs
+    - scsi: core: Fix unremoved procfs host directory regression
+    - usb: dwc2: host: Fix remote wakeup from hibernation
+    - usb: dwc2: host: Fix hibernation flow
+    - usb: dwc2: host: Fix ISOC flow in DDMA mode
+    - usb: dwc2: gadget: LPM flow fix
+    - usb: udc: remove warning when queue disabled ep
+    - scsi: qla2xxx: Fix command flush on cable pull
+    - x86/cpu: Enable STIBP on AMD if Automatic IBRS is enabled
+    - scsi: lpfc: Correct size for wqe for memset()
+    - USB: core: Fix deadlock in usb_deauthorize_interface()
+    - nfc: nci: Fix uninit-value in nci_dev_up and nci_ntf_packet
+    - ixgbe: avoid sleeping allocation in ixgbe_ipsec_vf_add_sa()
+    - tcp: properly terminate timers for kernel sockets
+    - dm integrity: fix out-of-range warning
+    - r8169: fix issue caused by buggy BIOS on certain boards with RTL8168d
+    - Bluetooth: hci_event: set the conn encrypted before conn establishes
+    - Bluetooth: Fix TOCTOU in HCI debugfs implementation
+    - netfilter: nf_tables: disallow timeout for anonymous sets
+    - net/rds: fix possible cp null dereference
+    - vfio/pci: Disable auto-enable of exclusive INTx IRQ
+    - vfio/pci: Lock external INTx masking ops
+    - vfio: Introduce interface to flush virqfd inject workqueue
+    - vfio/pci: Create persistent INTx handler
+    - vfio/platform: Create persistent IRQ handlers
+    - Revert "x86/mm/ident_map: Use gbpages only where full GB page should be
+      mapped."
+    - mm, vmscan: prevent infinite loop for costly GFP_NOIO | __GFP_RETRY_MAYFAIL
+      allocations
+    - netfilter: nf_tables: flush pending destroy work before exit_net release
+    - netfilter: nf_tables: Fix potential data-race in __nft_flowtable_type_get()
+    - bpf, sockmap: Prevent lock inversion deadlock in map delete elem
+    - net/sched: act_skbmod: prevent kernel-infoleak
+    - net: stmmac: fix rx queue priority assignment
+    - selftests: reuseaddr_conflict: add missing new line at the end of the output
+    - ipv6: Fix infinite recursion in fib6_dump_done().
+    - i40e: fix vf may be used uninitialized in this function warning
+    - staging: mmal-vchiq: Allocate and free components as required
+    - staging: mmal-vchiq: Fix client_component for 64 bit kernel
+    - staging: vc04_services: changen strncpy() to strscpy_pad()
+    - staging: vc04_services: fix information leak in create_component()
+    - fs: add a vfs_fchown helper
+    - fs: add a vfs_fchmod helper
+    - initramfs: switch initramfs unpacking to struct file based APIs
+    - init: open /initrd.image with O_LARGEFILE
+    - erspan: Add type I version 0 support.
+    - erspan: make sure erspan_base_hdr is present in skb->head
+    - net: ravb: Always process TX descriptor ring
+    - ASoC: ops: Fix wraparound for mask in snd_soc_get_volsw
+    - ata: sata_sx4: fix pdc20621_get_from_dimm() on 64-bit
+    - scsi: mylex: Fix sysfs buffer lengths
+    - ata: sata_mv: Fix PCI device ID table declaration compilation warning
+    - ALSA: hda/realtek: Update Panasonic CF-SZ6 quirk to support headset with
+      microphone
+    - x86/mce: Make sure to grab mce_sysfs_mutex in set_bank()
+    - s390/entry: align system call table on 8 bytes
+    - wifi: ath9k: fix LNA selection in ath_ant_try_scan()
+    - VMCI: Fix memcpy() run-time warning in dg_dispatch_as_host()
+    - panic: Flush kernel log buffer at the end
+    - arm64: dts: rockchip: fix rk3328 hdmi ports node
+    - arm64: dts: rockchip: fix rk3399 hdmi ports node
+    - ionic: set adminq irq affinity
+    - tools/power x86_energy_perf_policy: Fix file leak in get_pkg_num()
+    - btrfs: handle chunk tree lookup error in btrfs_relocate_sys_chunks()
+    - btrfs: export: handle invalid inode or root reference in btrfs_get_parent()
+    - btrfs: send: handle path ref underflow in header iterate_inode_ref()
+    - Bluetooth: btintel: Fix null ptr deref in btintel_read_version
+    - Input: synaptics-rmi4 - fail probing if memory allocation for "phys" fails
+    - sysv: don't call sb_bread() with pointers_lock held
+    - scsi: lpfc: Fix possible memory leak in lpfc_rcv_padisc()
+    - isofs: handle CDs with bad root inode but good Joliet root directory
+    - media: sta2x11: fix irq handler cast
+    - drm/amd/display: Fix nanosec stat overflow
+    - SUNRPC: increase size of rpc_wait_queue.qlen from unsigned short to unsigned
+      int
+    - Revert "ACPI: PM: Block ASUS B1400CEAE from suspend to idle by default"
+    - block: prevent division by zero in blk_rq_stat_sum()
+    - Input: allocate keycode for Display refresh rate toggle
+    - ktest: force $buildonly = 1 for 'make_warnings_file' test type
+    - tools: iio: replace seekdir() in iio_generic_buffer
+    - usb: typec: tcpci: add generic tcpci fallback compatible
+    - usb: sl811-hcd: only defined function checkdone if QUIRK2 is defined
+    - fbdev: viafb: fix typo in hw_bitblt_1 and hw_bitblt_2
+    - fbmon: prevent division by zero in fb_videomode_from_videomode()
+    - netfilter: nf_tables: reject new basechain after table flag update
+    - netfilter: nf_tables: discard table flag update with pending basechain
+      deletion
+    - tty: n_gsm: require CAP_NET_ADMIN to attach N_GSM0710 ldisc
+    - drm/vkms: call drm_atomic_helper_shutdown before drm_dev_put()
+    - virtio: reenable config if freezing device failed
+    - x86/mm/pat: fix VM_PAT handling in COW mappings
+    - drm/i915/gt: Reset queue_priority_hint on parking
+    - x86/alternative: Don't call text_poke() in lazy TLB mode
+    - Bluetooth: btintel: Fixe build regression
+    - VMCI: Fix possible memcpy() run-time warning in
+      vmci_datagram_invoke_guest_handler()
+    - erspan: Check IFLA_GRE_ERSPAN_VER is set.
+    - ip_gre: do not report erspan version on GRE interface
+    - firmware: meson_sm: fix to avoid potential NULL pointer dereference
+    - Linux 5.4.274
+
+  * CVE-2024-26586
+    - mlxsw: spectrum_acl_tcam: Fix stack corruption
+
+  * CVE-2024-26923
+    - af_unix: Do not use atomic ops for unix_sk(sk)->inflight.
+    - af_unix: Fix garbage collector racing against connect()
+
+  * Focal update: v5.4.273 upstream stable release (LP: #2064561)
+    - io_uring/unix: drop usage of io_uring socket
+    - io_uring: drop any code related to SCM_RIGHTS
+    - selftests: tls: use exact comparison in recv_partial
+    - ASoC: rt5645: Make LattePanda board DMI match more precise
+    - x86/xen: Add some null pointer checking to smp.c
+    - MIPS: Clear Cause.BD in instruction_pointer_set
+    - HID: multitouch: Add required quirk for Synaptics 0xcddc device
+    - RDMA/mlx5: Relax DEVX access upon modify commands
+    - net/iucv: fix the allocation size of iucv_path_table array
+    - parisc/ftrace: add missing CONFIG_DYNAMIC_FTRACE check
+    - block: sed-opal: handle empty atoms when parsing response
+    - dm-verity, dm-crypt: align "struct bvec_iter" correctly
+    - btrfs: fix data race at btrfs_use_block_rsv() when accessing block reserve
+    - scsi: mpt3sas: Prevent sending diag_reset when the controller is ready
+    - Bluetooth: rfcomm: Fix null-ptr-deref in rfcomm_check_security
+    - firewire: core: use long bus reset on gap count error
+    - ASoC: Intel: bytcr_rt5640: Add an extra entry for the Chuwi Vi8 tablet
+    - Input: gpio_keys_polled - suppress deferred probe error for gpio
+    - ASoC: wm8962: Enable oscillator if selecting WM8962_FLL_OSC
+    - ASoC: wm8962: Enable both SPKOUTR_ENA and SPKOUTL_ENA in mono mode
+    - ASoC: wm8962: Fix up incorrect error message in wm8962_set_fll
+    - do_sys_name_to_handle(): use kzalloc() to fix kernel-infoleak
+    - fs/select: rework stack allocation hack for clang
+    - timekeeping: Fix cross-timestamp interpolation on counter wrap
+    - timekeeping: Fix cross-timestamp interpolation corner case decision
+    - timekeeping: Fix cross-timestamp interpolation for non-x86
+    - wifi: ath10k: fix NULL pointer dereference in
+      ath10k_wmi_tlv_op_pull_mgmt_tx_compl_ev()
+    - b43: dma: Fix use true/false for bool type variable
+    - wifi: b43: Stop/wake correct queue in DMA Tx path when QoS is disabled
+    - wifi: b43: Stop/wake correct queue in PIO Tx path when QoS is disabled
+    - b43: main: Fix use true/false for bool type
+    - wifi: b43: Stop correct queue in DMA worker when QoS is disabled
+    - wifi: b43: Disable QoS for bcm4331
+    - wifi: wilc1000: fix declarations ordering
+    - wifi: wilc1000: fix RCU usage in connect path
+    - wifi: mwifiex: debugfs: Drop unnecessary error check for
+      debugfs_create_dir()
+    - sock_diag: annotate data-races around sock_diag_handlers[family]
+    - af_unix: Annotate data-race of gc_in_progress in wait_for_unix_gc().
+    - net: blackhole_dev: fix build warning for ethh set but not used
+    - wifi: libertas: fix some memleaks in lbs_allocate_cmd_buffer()
+    - arm64: dts: mediatek: mt7622: add missing "device_type" to memory nodes
+    - bpf: Add typecast to bpf helpers to help BTF generation
+    - bpf: Factor out bpf_spin_lock into helpers.
+    - bpf: Mark bpf_spin_{lock,unlock}() helpers with notrace correctly
+    - arm64: dts: qcom: db820c: Move non-soc entries out of /soc
+    - arm64: dts: qcom: msm8996: Use node references in db820c
+    - arm64: dts: qcom: msm8996: Move regulator consumers to db820c
+    - arm64: dts: qcom: msm8996: Pad addresses
+    - ACPI: processor_idle: Fix memory leak in acpi_processor_power_exit()
+    - bus: tegra-aconnect: Update dependency to ARCH_TEGRA
+    - [Config]: Update tegra configs
+    - iommu/amd: Mark interrupt as managed
+    - wifi: brcmsmac: avoid function pointer casts
+    - net: ena: Remove ena_select_queue
+    - ARM: dts: arm: realview: Fix development chip ROM compatible value
+    - ARM: dts: imx6dl-yapp4: Move phy reset into switch node
+    - ARM: dts: imx6dl-yapp4: Fix typo in the QCA switch register address
+    - ARM: dts: imx6dl-yapp4: Move the internal switch PHYs under the switch node
+    - ACPI: scan: Fix device check notification handling
+    - x86, relocs: Ignore relocations in .notes section
+    - SUNRPC: fix some memleaks in gssx_dec_option_array
+    - mmc: wmt-sdmmc: remove an incorrect release_mem_region() call in the .remove
+      function
+    - igb: move PEROUT and EXTTS isr logic to separate functions
+    - igb: Fix missing time sync events
+    - Bluetooth: Remove superfluous call to hci_conn_check_pending()
+    - sr9800: Add check for usbnet_get_endpoints
+    - bpf: Fix hashtab overflow check on 32-bit arches
+    - bpf: Fix stackmap overflow check on 32-bit arches
+    - ipv6: fib6_rules: flush route cache when rule is changed
+    - net: ip_tunnel: make sure to pull inner header in ip_tunnel_rcv()
+    - net: hns3: fix port duplex configure error in IMP reset
+    - tcp: fix incorrect parameter validation in the do_tcp_getsockopt() function
+    - l2tp: fix incorrect parameter validation in the pppol2tp_getsockopt()
+      function
+    - udp: fix incorrect parameter validation in the udp_lib_getsockopt() function
+    - net: kcm: fix incorrect parameter validation in the kcm_getsockopt) function
+    - net/x25: fix incorrect parameter validation in the x25_getsockopt() function
+    - nfp: flower: handle acti_netdevs allocation failure
+    - dm raid: fix false positive for requeue needed during reshape
+    - dm: call the resume method on internal suspend
+    - drm/tegra: dsi: Add missing check for of_find_device_by_node
+    - gpu: host1x: mipi: Update tegra_mipi_request() to be node based
+    - drm/tegra: dsi: Make use of the helper function dev_err_probe()
+    - drm/tegra: dsi: Fix some error handling paths in tegra_dsi_probe()
+    - drm/tegra: dsi: Fix missing pm_runtime_disable() in the error handling path
+      of tegra_dsi_probe()
+    - drm/tegra: output: Fix missing i2c_put_adapter() in the error handling paths
+      of tegra_output_probe()
+    - drm/rockchip: inno_hdmi: Fix video timing
+    - drm: Don't treat 0 as -1 in drm_fixp2int_ceil
+    - drm/rockchip: lvds: do not overwrite error code
+    - dmaengine: tegra210-adma: Update dependency to ARCH_TEGRA
+    - media: tc358743: register v4l2 async device only after successful setup
+    - PCI/DPC: Print all TLP Prefixes, not just the first
+    - perf record: Fix possible incorrect free in record__switch_output()
+    - drm/amd/display: Fix potential NULL pointer dereferences in
+      'dcn10_set_output_transfer_func()'
+    - perf evsel: Fix duplicate initialization of data->id in
+      evsel__parse_sample()
+    - media: em28xx: annotate unchecked call to media_device_register()
+    - media: v4l2-tpg: fix some memleaks in tpg_alloc
+    - media: v4l2-mem2mem: fix a memleak in v4l2_m2m_register_entity
+    - media: edia: dvbdev: fix a use-after-free
+    - clk: qcom: reset: Allow specifying custom reset delay
+    - clk: qcom: reset: support resetting multiple bits
+    - clk: qcom: reset: Commonize the de/assert functions
+    - clk: qcom: reset: Ensure write completion on reset de/assertion
+    - quota: simplify drop_dquot_ref()
+    - quota: Fix potential NULL pointer dereference
+    - quota: Fix rcu annotations of inode dquot pointers
+    - PCI: switchtec: Fix an error handling path in switchtec_pci_probe()
+    - perf thread_map: Free strlist on normal path in thread_map__new_by_tid_str()
+    - drm/radeon/ni: Fix wrong firmware size logging in ni_init_microcode()
+    - ALSA: seq: fix function cast warnings
+    - perf stat: Avoid metric-only segv
+    - media: imx: csc/scaler: fix v4l2_ctrl_handler memory leak
+    - media: go7007: add check of return value of go7007_read_addr()
+    - media: pvrusb2: remove redundant NULL check
+    - media: pvrusb2: fix pvr2_stream_callback casts
+    - clk: qcom: dispcc-sdm845: Adjust internal GDSC wait times
+    - drm/mediatek: dsi: Fix DSI RGB666 formats and definitions
+    - PCI: Mark 3ware-9650SE Root Port Extended Tags as broken
+    - clk: hisilicon: hi3519: Release the correct number of gates in
+      hi3519_clk_unregister()
+    - drm/tegra: put drm_gem_object ref on error in tegra_fb_create
+    - mfd: syscon: Call of_node_put() only when of_parse_phandle() takes a ref
+    - mfd: altera-sysmgr: Call of_node_put() only when of_parse_phandle() takes a
+      ref
+    - crypto: arm/sha - fix function cast warnings
+    - mtd: maps: physmap-core: fix flash size larger than 32-bit
+    - mtd: rawnand: lpc32xx_mlc: fix irq handler prototype
+    - ASoC: meson: axg-tdm-interface: fix mclk setup without mclk-fs
+    - drm/amdgpu: Fix missing break in ATOM_ARG_IMM Case of atom_get_src_int()
+    - media: pvrusb2: fix uaf in pvr2_context_set_notify
+    - media: dvb-frontends: avoid stack overflow warnings with clang
+    - media: go7007: fix a memleak in go7007_load_encoder
+    - media: v4l2-core: correctly validate video and metadata ioctls
+    - media: rename VFL_TYPE_GRABBER to _VIDEO
+    - media: media/pci: rename VFL_TYPE_GRABBER to _VIDEO
+    - media: ttpci: fix two memleaks in budget_av_attach
+    - drm/mediatek: Fix a null pointer crash in mtk_drm_crtc_finish_page_flip
+    - powerpc/hv-gpci: Fix the H_GET_PERF_COUNTER_INFO hcall return value checks
+    - drm/msm/dpu: add division of drm_display_mode's hskew parameter
+    - powerpc/embedded6xx: Fix no previous prototype for avr_uart_send() etc.
+    - backlight: lm3630a: Initialize backlight_properties on init
+    - backlight: lm3630a: Don't set bl->props.brightness in get_brightness
+    - backlight: da9052: Fully initialize backlight_properties during probe
+    - backlight: lm3639: Fully initialize backlight_properties during probe
+    - backlight: lp8788: Fully initialize backlight_properties during probe
+    - sparc32: Fix section mismatch in leon_pci_grpci
+    - clk: Fix clk_core_get NULL dereference
+    - ALSA: usb-audio: Stop parsing channels bits when all channels are found.
+    - scsi: csiostor: Avoid function pointer casts
+    - RDMA/device: Fix a race between mad_client and cm_client init
+    - scsi: bfa: Fix function pointer type mismatch for hcb_qe->cbfn
+    - net: sunrpc: Fix an off by one in rpc_sockaddr2uaddr()
+    - watchdog: stm32_iwdg: initialize default timeout
+    - NFS: Fix an off by one in root_nfs_cat()
+    - afs: Revert "afs: Hide silly-rename files from userspace"
+    - tty: vt: fix 20 vs 0x20 typo in EScsiignore
+    - serial: max310x: fix syntax error in IRQ error message
+    - tty: serial: samsung: fix tx_empty() to return TIOCSER_TEMT
+    - kconfig: fix infinite loop when expanding a macro at the end of file
+    - rtc: mt6397: select IRQ_DOMAIN instead of depending on it
+    - serial: 8250_exar: Don't remove GPIO device on suspend
+    - staging: greybus: fix get_channel_from_mode() failure path
+    - usb: gadget: net2272: Use irqflags in the call to net2272_probe_fin
+    - octeontx2-af: Use matching wake_up API variant in CGX command interface
+    - s390/vtime: fix average steal time calculation
+    - hsr: Fix uninit-value access in hsr_get_node()
+    - packet: annotate data-races around ignore_outgoing
+    - rds: introduce acquire/release ordering in acquire/release_in_xmit()
+    - hsr: Handle failures in module init
+    - net/bnx2x: Prevent access to a freed page in page_pool
+    - octeontx2-af: Use separate handlers for interrupts
+    - ARM: dts: sun8i-h2-plus-bananapi-m2-zero: add regulator nodes vcc-dram and
+      vcc1v2
+    - netfilter: nf_tables: do not compare internal table flags on updates
+    - rcu: add a helper to report consolidated flavor QS
+    - bpf: report RCU QS in cpumap kthread
+    - spi: spi-mt65xx: Fix NULL pointer access in interrupt handler
+    - regmap: Add missing map->bus check
+    - Linux 5.4.273
+
+  * Focal update: v5.4.272 upstream stable release (LP: #2064555)
+    - lan78xx: Fix white space and style issues
+    - lan78xx: Add missing return code checks
+    - lan78xx: Fix partial packet errors on suspend/resume
+    - lan78xx: Fix race conditions in suspend/resume handling
+    - net: lan78xx: fix runtime PM count underflow on link stop
+    - ixgbe: {dis, en}able irqs in ixgbe_txrx_ring_{dis, en}able
+    - geneve: make sure to pull inner header in geneve_rx()
+    - net: ice: Fix potential NULL pointer dereference in ice_bridge_setlink()
+    - net/ipv6: avoid possible UAF in ip6_route_mpath_notify()
+    - net/rds: fix WARNING in rds_conn_connect_if_down
+    - netfilter: nft_ct: fix l3num expectations with inet pseudo family
+    - netfilter: nf_conntrack_h323: Add protection for bmp length out of range
+    - netrom: Fix a data-race around sysctl_netrom_default_path_quality
+    - netrom: Fix a data-race around sysctl_netrom_obsolescence_count_initialiser
+    - netrom: Fix data-races around sysctl_netrom_network_ttl_initialiser
+    - netrom: Fix a data-race around sysctl_netrom_transport_timeout
+    - netrom: Fix a data-race around sysctl_netrom_transport_maximum_tries
+    - netrom: Fix a data-race around sysctl_netrom_transport_acknowledge_delay
+    - netrom: Fix a data-race around sysctl_netrom_transport_busy_delay
+    - netrom: Fix a data-race around sysctl_netrom_transport_requested_window_size
+    - netrom: Fix a data-race around sysctl_netrom_transport_no_activity_timeout
+    - netrom: Fix a data-race around sysctl_netrom_routing_control
+    - netrom: Fix a data-race around sysctl_netrom_link_fails_count
+    - netrom: Fix data-races around sysctl_net_busy_read
+    - selftests: mm: fix map_hugetlb failure on 64K page size systems
+    - um: allow not setting extra rpaths in the linux binary
+    - serial: max310x: Use devm_clk_get_optional() to get the input clock
+    - serial: max310x: Try to get crystal clock rate from property
+    - serial: max310x: fail probe if clock crystal is unstable
+    - serial: max310x: Make use of device properties
+    - serial: max310x: use regmap methods for SPI batch operations
+    - serial: max310x: use a separate regmap for each port
+    - serial: max310x: prevent infinite while() loop in port startup
+    - Input: i8042 - fix strange behavior of touchpad on Clevo NS70PU
+    - hv_netvsc: Make netvsc/VF binding check both MAC and serial number
+    - hv_netvsc: use netif_is_bond_master() instead of open code
+    - hv_netvsc: Register VF in netvsc_probe if NET_DEVICE_REGISTER missed
+    - y2038: rusage: use __kernel_old_timeval
+    - getrusage: add the "signal_struct *sig" local variable
+    - getrusage: move thread_group_cputime_adjusted() outside of
+      lock_task_sighand()
+    - getrusage: use __for_each_thread()
+    - getrusage: use sig->stats_lock rather than lock_task_sighand()
+    - serial: max310x: Unprepare and disable clock in error path
+    - regmap: allow to define reg_update_bits for no bus configuration
+    - regmap: Add bulk read/write callbacks into regmap_config
+    - serial: max310x: make accessing revision id interface-agnostic
+    - serial: max310x: implement I2C support
+    - serial: max310x: fix IO data corruption in batched operations
+    - arm64: dts: qcom: add PDC interrupt controller for SDM845
+    - arm64: dts: qcom: sdm845: fix USB DP/DM HS PHY interrupts
+    - Linux 5.4.272
+
+  * CVE-2024-23307
+    - md/raid5: fix atomicity violation in raid5_cache_count
+
+  * CVE-2024-26889
+    - Bluetooth: hci_core: Fix possible buffer overflow
+
+  * CVE-2024-26828
+    - cifs: fix underflow in parse_server_interfaces()
+
+  * CVE-2024-24861
+    - media: xc4000: Fix atomicity violation in xc4000_get_frequency
+
+  * CVE-2023-6270
+    - aoe: fix the potential use-after-free problem in aoecmd_cfg_pkts
+
+  * CVE-2024-26642
+    - netfilter: nf_tables: disallow anonymous set with timeout flag
+
+  * CVE-2024-26926
+    - binder: check offset alignment in binder_get_object()
+
+  * CVE-2024-26922
+    - drm/amdgpu: validate the parameters of bo mapping operations more clearly
+
+  * CVE-2024-26925
+    - netfilter: Cleanup nft_net->module_list from nf_tables_exit_net()
+    - netfilter: nf_tables: release batch on table validation from abort path
+    - netfilter: nf_tables: release mutex after nft_gc_seq_end from abort path
+
+  * CVE-2024-26643
+    - netfilter: nf_tables: mark set as dead when unbinding anonymous set with
+      timeout
+
+  * CVE-2024-2201
+    - x86/cpufeatures: Add new word for scattered features
+    - x86/cpufeatures: Add CPUID_LNX_5 to track recently added Linux-defined word
+    - x86/bugs: Change commas to semicolons in 'spectre_v2' sysfs file
+    - x86/bhi: Add support for clearing branch history at syscall entry
+    - x86/bhi: Define SPEC_CTRL_BHI_DIS_S
+    - x86/bhi: Enumerate Branch History Injection (BHI) bug
+    - x86/bhi: Add BHI mitigation knob
+    - x86/bhi: Mitigate KVM by default
+    - [Config] updateconfigs for CONFIG_BHI_{AUTO|ON|OFF}
+    - x86/bugs: Fix BHI documentation
+    - x86/bugs: Cache the value of MSR_IA32_ARCH_CAPABILITIES
+    - x86/bugs: Rename various 'ia32_cap' variables to 'x86_arch_cap_msr'
+    - x86/bugs: Fix BHI handling of RRSBA
+    - x86/bugs: Clarify that syscall hardening isn't a BHI mitigation
+    - x86/bugs: Fix BHI retpoline check
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Fri, 07 Jun 2024 15:07:46 +0200
+
+linux (5.4.0-186.206) focal; urgency=medium
+
+  * focal/linux: 5.4.0-186.206 -proposed tracker (LP: #2063812)
+
+  * Mount CIFS fails with Permission denied (LP: #2061986)
+    - cifs: fix ntlmssp auth when there is no key exchange
+
+  * USB stick can't be detected (LP: #2040948)
+    - usb: Disable USB3 LPM at shutdown
+
+  * CVE-2024-26733
+    - net: dev: Convert sa_data to flexible array in struct sockaddr
+    - arp: Prevent overflow in arp_req_get().
+    - stddef: Introduce DECLARE_FLEX_ARRAY() helper
+
+  * CVE-2024-26712
+    - powerpc/kasan: Fix addr error caused by page alignment
+
+  * CVE-2023-52530
+    - wifi: mac80211: fix potential key use-after-free
+
+  * CVE-2021-47063
+    - drm: bridge/panel: Cleanup connector on bridge detach
+
+  * [Ubuntu 22.04.4/linux-image-6.5.0-26-generic] Kernel output "UBSAN: array-
+    index-out-of-bounds in /build/linux-hwe-6.5-34pCLi/linux-
+    hwe-6.5-6.5.0/drivers/net/hyperv/netvsc.c:1445:41" multiple times,
+    especially during boot. (LP: #2058477)
+    - hv: hyperv.h: Replace one-element array with flexible-array member
+
+  * CVE-2024-26614
+    - tcp: make sure init the accept_queue's spinlocks once
+    - ipv6: init the accept_queue's spinlocks in inet6_create
+
+  * Focal update: v5.4.271 upstream stable release (LP: #2060216)
+    - netlink: Fix kernel-infoleak-after-free in __skb_datagram_iter
+    - net: ip_tunnel: prevent perpetual headroom growth
+    - tun: Fix xdp_rxq_info's queue_index when detaching
+    - ipv6: fix potential "struct net" leak in inet6_rtm_getaddr()
+    - lan78xx: enable auto speed configuration for LAN7850 if no EEPROM is
+      detected
+    - net: usb: dm9601: fix wrong return value in dm9601_mdio_read
+    - Bluetooth: Avoid potential use-after-free in hci_error_reset
+    - Bluetooth: hci_event: Fix handling of HCI_EV_IO_CAPA_REQUEST
+    - Bluetooth: Enforce validation on max value of connection interval
+    - netfilter: nf_tables: allow NFPROTO_INET in nft_(match/target)_validate()
+    - rtnetlink: fix error logic of IFLA_BRIDGE_FLAGS writing back
+    - efi/capsule-loader: fix incorrect allocation size
+    - power: supply: bq27xxx-i2c: Do not free non existing IRQ
+    - ALSA: Drop leftover snd-rtctimer stuff from Makefile
+    - afs: Fix endless loop in directory parsing
+    - gtp: fix use-after-free and null-ptr-deref in gtp_newlink()
+    - wifi: nl80211: reject iftype change with mesh ID change
+    - btrfs: dev-replace: properly validate device names
+    - dmaengine: fsl-qdma: fix SoC may hang on 16 byte unaligned read
+    - dmaengine: fsl-qdma: init irq after reg initialization
+    - mmc: core: Fix eMMC initialization with 1-bit bus connection
+    - x86/cpu/intel: Detect TME keyid bits before setting MTRR mask registers
+    - cachefiles: fix memory leak in cachefiles_add_cache()
+    - fs,hugetlb: fix NULL pointer dereference in hugetlbs_fill_super
+    - gpio: 74x164: Enable output pins after registers are reset
+    - Linux 5.4.271
+
+  * Focal update: v5.4.270 upstream stable release (LP: #2060019)
+    - KVM: arm64: vgic-its: Test for valid IRQ in its_sync_lpi_pending_table()
+    - KVM: arm64: vgic-its: Test for valid IRQ in MOVALL handler
+    - net/sched: Retire CBQ qdisc
+    - [Config] updateconfigs for NET_SCH_CBQ
+    - net/sched: Retire ATM qdisc
+    - [Config] updateconfigs for NET_SCH_ATM
+    - net/sched: Retire dsmark qdisc
+    - [Config] updateconfigs for NET_SCH_DSMARK
+    - sched/rt: sysctl_sched_rr_timeslice show default timeslice after reset
+    - memcg: add refcnt for pcpu stock to avoid UAF problem in drain_all_stock()
+    - nilfs2: replace WARN_ONs for invalid DAT metadata block requests
+    - userfaultfd: fix mmap_changing checking in mfill_atomic_hugetlb
+    - sched/rt: Fix sysctl_sched_rr_timeslice intial value
+    - sched/rt: Disallow writing invalid values to sched_rt_period_us
+    - scsi: target: core: Add TMF to tmr_list handling
+    - dmaengine: shdma: increase size of 'dev_id'
+    - dmaengine: fsl-qdma: increase size of 'irq_name'
+    - wifi: cfg80211: fix missing interfaces when dumping
+    - wifi: mac80211: fix race condition on enabling fast-xmit
+    - fbdev: savage: Error out if pixclock equals zero
+    - fbdev: sis: Error out if pixclock equals zero
+    - ahci: asm1166: correct count of reported ports
+    - ahci: add 43-bit DMA address quirk for ASMedia ASM1061 controllers
+    - ext4: avoid allocating blocks from corrupted group in
+      ext4_mb_try_best_found()
+    - ext4: avoid allocating blocks from corrupted group in ext4_mb_find_by_goal()
+    - regulator: pwm-regulator: Add validity checks in continuous .get_voltage
+    - nvmet-tcp: fix nvme tcp ida memory leak
+    - ASoC: sunxi: sun4i-spdif: Add support for Allwinner H616
+    - netfilter: conntrack: check SCTP_CID_SHUTDOWN_ACK for vtag setting in
+      sctp_new
+    - nvmet-fc: abort command when there is no binding
+    - hwmon: (coretemp) Enlarge per package core count limit
+    - scsi: lpfc: Use unsigned type for num_sge
+    - firewire: core: send bus reset promptly on gap count error
+    - virtio-blk: Ensure no requests in virtqueues before deleting vqs.
+    - s390/qeth: Fix potential loss of L3-IP@ in case of network issues
+    - pmdomain: renesas: r8a77980-sysc: CR7 must be always on
+    - tcp: factor out __tcp_close() helper
+    - tcp: return EPOLLOUT from tcp_poll only when notsent_bytes is half the limit
+    - tcp: add annotations around sk->sk_shutdown accesses
+    - pinctrl: pinctrl-rockchip: Fix a bunch of kerneldoc misdemeanours
+    - pinctrl: rockchip: Fix refcount leak in rockchip_pinctrl_parse_groups
+    - spi: mt7621: Fix an error message in mt7621_spi_probe()
+    - net: bridge: clear bridge's private skb space on xmit
+    - selftests/bpf: Avoid running unprivileged tests with alignment requirements
+    - Revert "drm/sun4i: dsi: Change the start delay calculation"
+    - drm/amdgpu: Check for valid number of registers to read
+    - x86/alternatives: Disable KASAN in apply_alternatives()
+    - dm-integrity: don't modify bio's immutable bio_vec in integrity_metadata()
+    - iomap: Set all uptodate bits for an Uptodate page
+    - drm/amdgpu: Fix type of second parameter in trans_msg() callback
+    - arm64: dts: qcom: msm8916: Fix typo in pronto remoteproc node
+    - PCI: tegra: Fix reporting GPIO error value
+    - PCI: tegra: Fix OF node reference leak
+    - IB/hfi1: Fix sdma.h tx->num_descs off-by-one error
+    - dm-crypt: don't modify the data when using authenticated encryption
+    - gtp: fix use-after-free and null-ptr-deref in gtp_genl_dump_pdp()
+    - PCI/MSI: Prevent MSI hardware interrupt number truncation
+    - l2tp: pass correct message length to ip6_append_data
+    - ARM: ep93xx: Add terminator to gpiod_lookup_table
+    - usb: cdns3: fixed memory use after free at cdns3_gadget_ep_disable()
+    - usb: cdns3: fix memory double free when handle zero packet
+    - usb: gadget: ncm: Avoid dropping datagrams of properly parsed NTBs
+    - usb: roles: don't get/set_role() when usb_role_switch is unregistered
+    - IB/hfi1: Fix a memleak in init_credit_return
+    - RDMA/bnxt_re: Return error for SRQ resize
+    - RDMA/srpt: Make debug output more detailed
+    - RDMA/srpt: fix function pointer cast warnings
+    - scripts/bpf: teach bpf_helpers_doc.py to dump BPF helper definitions
+    - bpf, scripts: Correct GPL license name
+    - scsi: jazz_esp: Only build if SCSI core is builtin
+    - nouveau: fix function cast warnings
+    - ipv4: properly combine dev_base_seq and ipv4.dev_addr_genid
+    - ipv6: properly combine dev_base_seq and ipv6.dev_addr_genid
+    - afs: Increase buffer size in afs_update_volume_status()
+    - ipv6: sr: fix possible use-after-free and null-ptr-deref
+    - packet: move from strlcpy with unused retval to strscpy
+    - s390: use the correct count for __iowrite64_copy()
+    - tls: rx: jump to a more appropriate label
+    - tls: rx: drop pointless else after goto
+    - tls: stop recv() if initial process_rx_list gave us non-DATA
+    - netfilter: nf_tables: set dormant flag on hook register failure
+    - drm/syncobj: make lockdep complain on WAIT_FOR_SUBMIT v3
+    - drm/syncobj: call drm_syncobj_fence_add_wait when WAIT_AVAILABLE flag is set
+    - fs/aio: Restrict kiocb_set_cancel_fn() to I/O submitted via libaio
+    - scripts/bpf: Fix xdp_md forward declaration typo
+    - Linux 5.4.270
+
+  * CVE-2023-47233
+    - wifi: brcmfmac: Fix use-after-free bug in brcmf_cfg80211_detach
+
+  * CVE-2021-47070
+    - uio: uio_hv_generic: use devm_kzalloc() for private data alloc
+    - uio_hv_generic: Fix another memory leak in error handling paths
+
+  * CVE-2024-26622
+    - tomoyo: fix UAF write bug in tomoyo_write_control()
+
+ -- Roxana Nicolescu <roxana.nicolescu@canonical.com>  Fri, 26 Apr 2024 14:01:17 +0200
+
+linux (5.4.0-181.201) focal; urgency=medium
+
+  * focal/linux: 5.4.0-181.201 -proposed tracker (LP: #2059549)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] drop getabis data
+
+  * Drop fips-checks script from trees (LP: #2055083)
+    - [Packaging] Remove fips-checks script
+
+  * Remove getabis scripts (LP: #2059143)
+    - [Packaging] Remove getabis
+
+  * Focal update: v5.4.269 upstream stable release (LP: #2058948)
+    - PCI: mediatek: Clear interrupt status before dispatching handler
+    - include/linux/units.h: add helpers for kelvin to/from Celsius conversion
+    - units: Add Watt units
+    - units: change from 'L' to 'UL'
+    - units: add the HZ macros
+    - serial: sc16is7xx: set safe default SPI clock frequency
+    - spi: introduce SPI_MODE_X_MASK macro
+    - serial: sc16is7xx: add check for unsupported SPI modes during probe
+    - ext4: allow for the last group to be marked as trimmed
+    - crypto: api - Disallow identical driver names
+    - PM: hibernate: Enforce ordering during image compression/decompression
+    - hwrng: core - Fix page fault dead lock on mmap-ed hwrng
+    - rpmsg: virtio: Free driver_override when rpmsg_remove()
+    - parisc/firmware: Fix F-extend for PDC addresses
+    - arm64: dts: qcom: sdm845: fix USB wakeup interrupt types
+    - mmc: core: Use mrq.sbc in close-ended ffu
+    - nouveau/vmm: don't set addr on the fail path to avoid warning
+    - ubifs: ubifs_symlink: Fix memleak of inode->i_link in error path
+    - rename(): fix the locking of subdirectories
+    - block: Remove special-casing of compound pages
+    - mtd: spinand: macronix: Fix MX35LFxGE4AD page size
+    - fs: add mode_strip_sgid() helper
+    - fs: move S_ISGID stripping into the vfs_*() helpers
+    - powerpc: Use always instead of always-y in for crtsavres.o
+    - x86/CPU/AMD: Fix disabling XSAVES on AMD family 0x17 due to erratum
+    - net/smc: fix illegal rmb_desc access in SMC-D connection dump
+    - vlan: skip nested type that is not IFLA_VLAN_QOS_MAPPING
+    - llc: make llc_ui_sendmsg() more robust against bonding changes
+    - llc: Drop support for ETH_P_TR_802_2.
+    - net/rds: Fix UBSAN: array-index-out-of-bounds in rds_cmsg_recv
+    - tracing: Ensure visibility when inserting an element into tracing_map
+    - afs: Hide silly-rename files from userspace
+    - tcp: Add memory barrier to tcp_push()
+    - netlink: fix potential sleeping issue in mqueue_flush_file
+    - net/mlx5: DR, Use the right GVMI number for drop action
+    - net/mlx5: Use kfree(ft->g) in arfs_create_groups()
+    - net/mlx5e: fix a double-free in arfs_create_groups
+    - netfilter: nf_tables: restrict anonymous set and map names to 16 bytes
+    - netfilter: nf_tables: validate NFPROTO_* family
+    - fjes: fix memleaks in fjes_hw_setup
+    - net: fec: fix the unhandled context fault from smmu
+    - btrfs: ref-verify: free ref cache before clearing mount opt
+    - btrfs: tree-checker: fix inline ref size in error messages
+    - btrfs: don't warn if discard range is not aligned to sector
+    - btrfs: defrag: reject unknown flags of btrfs_ioctl_defrag_range_args
+    - rbd: don't move requests to the running list on errors
+    - gpiolib: acpi: Ignore touchpad wakeup on GPD G1619-04
+    - drm: Don't unref the same fb many times by mistake due to deadlock handling
+    - drm/bridge: nxp-ptn3460: fix i2c_master_send() error checking
+    - drm/bridge: nxp-ptn3460: simplify some error checking
+    - drm/exynos: fix accidental on-stack copy of exynos_drm_plane
+    - drm/exynos: gsc: minor fix for loop iteration in gsc_runtime_resume
+    - gpio: eic-sprd: Clear interrupt after set the interrupt type
+    - spi: bcm-qspi: fix SFDP BFPT read by usig mspi read
+    - mips: Call lose_fpu(0) before initializing fcr31 in mips_set_personality_nan
+    - tick/sched: Preserve number of idle sleeps across CPU hotplug events
+    - x86/entry/ia32: Ensure s32 is sign extended to s64
+    - powerpc/mm: Fix null-pointer dereference in pgtable_cache_add
+    - powerpc: Fix build error due to is_valid_bugaddr()
+    - powerpc/mm: Fix build failures due to arch_reserved_kernel_pages()
+    - powerpc: pmd_move_must_withdraw() is only needed for
+      CONFIG_TRANSPARENT_HUGEPAGE
+    - powerpc/lib: Validate size for vector operations
+    - x86/mce: Mark fatal MCE's page as poison to avoid panic in the kdump kernel
+    - perf/core: Fix narrow startup race when creating the perf nr_addr_filters
+      sysfs file
+    - regulator: core: Only increment use_count when enable_count changes
+    - audit: Send netlink ACK before setting connection in auditd_set
+    - ACPI: video: Add quirk for the Colorful X15 AT 23 Laptop
+    - PNP: ACPI: fix fortify warning
+    - ACPI: extlog: fix NULL pointer dereference check
+    - FS:JFS:UBSAN:array-index-out-of-bounds in dbAdjTree
+    - jfs: fix slab-out-of-bounds Read in dtSearch
+    - jfs: fix array-index-out-of-bounds in dbAdjTree
+    - pstore/ram: Fix crash when setting number of cpus to an odd number
+    - crypto: stm32/crc32 - fix parsing list of devices
+    - afs: fix the usage of read_seqbegin_or_lock() in afs_find_server*()
+    - rxrpc_find_service_conn_rcu: fix the usage of read_seqbegin_or_lock()
+    - jfs: fix array-index-out-of-bounds in diNewExt
+    - s390/ptrace: handle setting of fpc register correctly
+    - KVM: s390: fix setting of fpc register
+    - SUNRPC: Fix a suspicious RCU usage warning
+    - ecryptfs: Reject casefold directory inodes
+    - ext4: fix inconsistent between segment fstrim and full fstrim
+    - ext4: unify the type of flexbg_size to unsigned int
+    - ext4: remove unnecessary check from alloc_flex_gd()
+    - ext4: avoid online resizing failures due to oversized flex bg
+    - wifi: rt2x00: restart beacon queue when hardware reset
+    - selftests/bpf: satisfy compiler by having explicit return in btf test
+    - selftests/bpf: Fix pyperf180 compilation failure with clang18
+    - scsi: lpfc: Fix possible file string name overflow when updating firmware
+    - PCI: Add no PM reset quirk for NVIDIA Spectrum devices
+    - bonding: return -ENOMEM instead of BUG in alb_upper_dev_walk
+    - ARM: dts: imx7d: Fix coresight funnel ports
+    - ARM: dts: imx7s: Fix lcdif compatible
+    - ARM: dts: imx7s: Fix nand-controller #size-cells
+    - wifi: ath9k: Fix potential array-index-out-of-bounds read in
+      ath9k_htc_txstatus()
+    - bpf: Add map and need_defer parameters to .map_fd_put_ptr()
+    - scsi: libfc: Don't schedule abort twice
+    - scsi: libfc: Fix up timeout error in fc_fcp_rec_error()
+    - ARM: dts: rockchip: fix rk3036 hdmi ports node
+    - ARM: dts: imx25/27-eukrea: Fix RTC node name
+    - ARM: dts: imx: Use flash@0,0 pattern
+    - ARM: dts: imx27: Fix sram node
+    - ARM: dts: imx1: Fix sram node
+    - ARM: dts: imx25/27: Pass timing0
+    - ARM: dts: imx27-apf27dev: Fix LED name
+    - ARM: dts: imx23-sansa: Use preferred i2c-gpios properties
+    - ARM: dts: imx23/28: Fix the DMA controller node name
+    - block: prevent an integer overflow in bvec_try_merge_hw_page
+    - md: Whenassemble the array, consult the superblock of the freshest device
+    - arm64: dts: qcom: msm8996: Fix 'in-ports' is a required property
+    - arm64: dts: qcom: msm8998: Fix 'out-ports' is a required property
+    - wifi: rtl8xxxu: Add additional USB IDs for RTL8192EU devices
+    - wifi: rtlwifi: rtl8723{be,ae}: using calculate_bit_shift()
+    - wifi: cfg80211: free beacon_ies when overridden from hidden BSS
+    - f2fs: fix to check return value of f2fs_reserve_new_block()
+    - ASoC: doc: Fix undefined SND_SOC_DAPM_NOPM argument
+    - fast_dput(): handle underflows gracefully
+    - RDMA/IPoIB: Fix error code return in ipoib_mcast_join
+    - drm/drm_file: fix use of uninitialized variable
+    - drm/framebuffer: Fix use of uninitialized variable
+    - drm/mipi-dsi: Fix detach call without attach
+    - media: stk1160: Fixed high volume of stk1160_dbg messages
+    - media: rockchip: rga: fix swizzling for RGB formats
+    - PCI: add INTEL_HDA_ARL to pci_ids.h
+    - ALSA: hda: Intel: add HDA_ARL PCI ID support
+    - drm/exynos: Call drm_atomic_helper_shutdown() at shutdown/unbind time
+    - IB/ipoib: Fix mcast list locking
+    - media: ddbridge: fix an error code problem in ddb_probe
+    - drm/msm/dpu: Ratelimit framedone timeout msgs
+    - clk: hi3620: Fix memory leak in hi3620_mmc_clk_init()
+    - clk: mmp: pxa168: Fix memory leak in pxa168_clk_init()
+    - drm/amdgpu: Let KFD sync with VM fences
+    - drm/amdgpu: Drop 'fence' check in 'to_amdgpu_amdkfd_fence()'
+    - leds: trigger: panic: Don't register panic notifier if creating the trigger
+      failed
+    - um: Fix naming clash between UML and scheduler
+    - um: Don't use vfprintf() for os_info()
+    - um: net: Fix return type of uml_net_start_xmit()
+    - i3c: master: cdns: Update maximum prescaler value for i2c clock
+    - mfd: ti_am335x_tscadc: Fix TI SoC dependencies
+    - [Config] updateconfigs for MFD_TI_AM335X_TSCADC
+    - PCI: Only override AMD USB controller if required
+    - PCI: switchtec: Fix stdev_release() crash after surprise hot remove
+    - usb: hub: Replace hardcoded quirk value with BIT() macro
+    - fs/kernfs/dir: obey S_ISGID
+    - PCI/AER: Decode Requester ID when no error info found
+    - libsubcmd: Fix memory leak in uniq()
+    - virtio_net: Fix "‘%d’ directive writing between 1 and 11 bytes into a region
+      of size 10" warnings
+    - blk-mq: fix IO hang from sbitmap wakeup race
+    - ceph: fix deadlock or deadcode of misusing dget()
+    - drm/amdgpu: Release 'adev->pm.fw' before return in
+      'amdgpu_device_need_post()'
+    - perf: Fix the nr_addr_filters fix
+    - wifi: cfg80211: fix RCU dereference in __cfg80211_bss_update
+    - scsi: isci: Fix an error code problem in isci_io_request_build()
+    - net: remove unneeded break
+    - ixgbe: Remove non-inclusive language
+    - ixgbe: Refactor returning internal error codes
+    - ixgbe: Refactor overtemp event handling
+    - ixgbe: Fix an error handling path in ixgbe_read_iosf_sb_reg_x550()
+    - ipv6: Ensure natural alignment of const ipv6 loopback and router addresses
+    - llc: call sock_orphan() at release time
+    - netfilter: nf_log: replace BUG_ON by WARN_ON_ONCE when putting logger
+    - netfilter: nft_ct: sanitize layer 3 and 4 protocol number in custom
+      expectations
+    - net: ipv4: fix a memleak in ip_setup_cork
+    - af_unix: fix lockdep positive in sk_diag_dump_icons()
+    - SAUCE: Sync apparmor copy of af_unix.c
+    - net: sysfs: Fix /sys/class/net/<iface> path
+    - HID: apple: Add support for the 2021 Magic Keyboard
+    - HID: apple: Swap the Fn and Left Control keys on Apple keyboards
+    - HID: apple: Add 2021 magic keyboard FN key mapping
+    - bonding: remove print in bond_verify_device_path
+    - dmaengine: fsl-qdma: Fix a memory leak related to the status queue DMA
+    - dmaengine: fsl-qdma: Fix a memory leak related to the queue command DMA
+    - phy: renesas: rcar-gen3-usb2: Fix returning wrong error code
+    - dmaengine: fix is_slave_direction() return false when DMA_DEV_TO_DEV
+    - phy: ti: phy-omap-usb2: Fix NULL pointer dereference for SRP
+    - net: stmmac: xgmac: fix handling of DPP safety error for DMA channels
+    - selftests: net: avoid just another constant wait
+    - atm: idt77252: fix a memleak in open_card_ubr0
+    - hwmon: (aspeed-pwm-tacho) mutex for tach reading
+    - hwmon: (coretemp) Fix out-of-bounds memory access
+    - hwmon: (coretemp) Fix bogus core_id to attr name mapping
+    - inet: read sk->sk_family once in inet_recv_error()
+    - rxrpc: Fix response to PING RESPONSE ACKs to a dead call
+    - tipc: Check the bearer type before calling tipc_udp_nl_bearer_add()
+    - ppp_async: limit MRU to 64K
+    - netfilter: nft_compat: reject unused compat flag
+    - netfilter: nft_compat: restrict match/target protocol to u16
+    - netfilter: nft_ct: reject direction for ct id
+    - net/af_iucv: clean up a try_then_request_module()
+    - USB: serial: qcserial: add new usb-id for Dell Wireless DW5826e
+    - USB: serial: option: add Fibocom FM101-GL variant
+    - USB: serial: cp210x: add ID for IMST iM871A-USB
+    - hrtimer: Report offline hrtimer enqueue
+    - Input: atkbd - skip ATKBD_CMD_SETLEDS when skipping ATKBD_CMD_GETID
+    - net: stmmac: xgmac: use #define for string constants
+    - net: stmmac: xgmac: fix a typo of register name in DPP safety handling
+    - btrfs: forbid creating subvol qgroups
+    - btrfs: forbid deleting live subvol qgroup
+    - btrfs: send: return EOPNOTSUPP on unknown flags
+    - of: unittest: add overlay gpio test to catch gpio hog problem
+    - of: unittest: Fix compile in the non-dynamic case
+    - spi: ppc4xx: Drop write-only variable
+    - ASoC: rt5645: Fix deadlock in rt5645_jack_detect_work()
+    - MIPS: Add 'memory' clobber to csum_ipv6_magic() inline assembler
+    - i40e: Fix waiting for queues of all VSIs to be disabled
+    - tracing/trigger: Fix to return error if failed to alloc snapshot
+    - mm/writeback: fix possible divide-by-zero in wb_dirty_limits(), again
+    - HID: wacom: generic: Avoid reporting a serial of '0' to userspace
+    - HID: wacom: Do not register input devices until after hid_hw_start
+    - USB: hub: check for alternate port before enabling A_ALT_HNP_SUPPORT
+    - usb: f_mass_storage: forbid async queue when shutdown happen
+    - i2c: i801: Remove i801_set_block_buffer_mode
+    - i2c: i801: Fix block process call transactions
+    - scsi: Revert "scsi: fcoe: Fix potential deadlock on &fip->ctlr_lock"
+    - firewire: core: correct documentation of fw_csr_string() kernel API
+    - kbuild: Fix changing ELF file type for output of gen_btf for big endian
+    - nfc: nci: free rx_data_reassembly skb on NCI device cleanup
+    - xen-netback: properly sync TX responses
+    - ALSA: hda/realtek: Enable headset mic on Vaio VJFE-ADL
+    - binder: signal epoll threads of self-work
+    - misc: fastrpc: Mark all sessions as invalid in cb_remove
+    - ext4: fix double-free of blocks due to wrong extents moved_len
+    - tracing: Fix wasted memory in saved_cmdlines logic
+    - staging: iio: ad5933: fix type mismatch regression
+    - iio: magnetometer: rm3100: add boundary check for the value read from
+      RM3100_REG_TMRC
+    - ring-buffer: Clean ring_buffer_poll_wait() error return
+    - serial: max310x: set default value when reading clock ready bit
+    - serial: max310x: improve crystal stable clock detection
+    - x86/Kconfig: Transmeta Crusoe is CPU family 5, not 6
+    - x86/mm/ident_map: Use gbpages only where full GB page should be mapped.
+    - mmc: slot-gpio: Allow non-sleeping GPIO ro
+    - ALSA: hda/conexant: Add quirk for SWS JS201D
+    - nilfs2: fix data corruption in dsync block recovery for small block sizes
+    - nilfs2: fix hang in nilfs_lookup_dirty_data_buffers()
+    - nfp: use correct macro for LengthSelect in BAR config
+    - nfp: flower: prevent re-adding mac index for bonded port
+    - irqchip/irq-brcmstb-l2: Add write memory barrier before exit
+    - can: j1939: Fix UAF in j1939_sk_match_filter during
+      setsockopt(SO_J1939_FILTER)
+    - pmdomain: core: Move the unused cleanup to a _sync initcall
+    - tracing: Inform kmemleak of saved_cmdlines allocation
+    - Revert "md/raid5: Wait for MD_SB_CHANGE_PENDING in raid5d"
+    - bus: moxtet: Add spi device table
+    - arch, mm: remove stale mentions of DISCONIGMEM
+    - mips: Fix max_mapnr being uninitialized on early stages
+    - KVM: arm64: vgic-its: Avoid potential UAF in LPI translation cache
+    - netfilter: ipset: fix performance regression in swap operation
+    - netfilter: ipset: Missing gc cancellations fixed
+    - net: prevent mss overflow in skb_segment()
+    - sched/membarrier: reduce the ability to hammer on sys_membarrier
+    - nilfs2: fix potential bug in end_buffer_async_write
+    - PM: runtime: add devm_pm_runtime_enable helper
+    - PM: runtime: Have devm_pm_runtime_enable() handle
+      pm_runtime_dont_use_autosuspend()
+    - drm/msm/dsi: Enable runtime PM
+    - lsm: new security_file_ioctl_compat() hook
+    - Revert "Revert "mtd: rawnand: gpmi: Fix setting busy timeout setting""
+    - net: bcmgenet: Fix EEE implementation
+    - of: unittest: fix EXPECT text for gpio hog errors
+    - of: gpio unittest kfree() wrong object
+    - Linux 5.4.269
+
+  * Focal update: v5.4.269 upstream stable release (LP: #2058948) //
+    CVE-2023-52603
+    - UBSAN: array-index-out-of-bounds in dtSplitRoot
+
+  * CVE-2023-52600
+    - jfs: fix uaf in jfs_evict_inode
+
+  * CVE-2023-24023
+    - Bluetooth: Add more enc key size check
+
+  * CVE-2024-26581
+    - netfilter: nf_tables: nft_set_rbtree: fix spurious insertion failure
+    - netfilter: nft_set_rbtree: skip end interval element from gc
+
+  * CVE-2024-26589
+    - bpf: Reject variable offset alu on PTR_TO_FLOW_KEYS
+
+ -- Roxana Nicolescu <roxana.nicolescu@canonical.com>  Thu, 28 Mar 2024 15:36:38 +0100
+
+linux (5.4.0-176.196) focal; urgency=medium
+
+  * focal/linux: 5.4.0-176.196 -proposed tracker (LP: #2058756)
+
+  * Problems with HVCS and hotplugging (LP: #2056373)
+    - powerpc/pseries: Fix bad drc_index_start value parsing of drc-info entry
+    - powerpc/pseries: Fix of_read_drc_info_cell() to point at next record
+    - hvcs: Fix hvcs port reference counting
+    - hvcs: Use dev_groups to manage hvcs device attributes
+    - hvcs: Use driver groups to manage driver attributes
+    - hvcs: Get reference to tty in remove
+    - hvcs: Use vhangup in hotplug remove
+    - hvcs: Synchronize hotplug remove with port free
+
+ -- Roxana Nicolescu <roxana.nicolescu@canonical.com>  Fri, 22 Mar 2024 17:05:57 +0100
+
+linux (5.4.0-175.195) focal; urgency=medium
+
+  * focal/linux: 5.4.0-175.195 -proposed tracker (LP: #2055684)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] drop ABI data
+    - [Packaging] update annotations scripts
+    - debian.master/dkms-versions -- update from kernel-versions (main/2024.03.04)
+
+  * Drop ABI checks from kernel build (LP: #2055686)
+    - [Packaging] Remove in-tree abi checks
+    - [Packaging] Bring back install-<flavour> prerequisite for checks-<flavour>
+    - [Packaging] Remove abi-check from final-checks
+
+  * Cranky update-dkms-versions rollout (LP: #2055685)
+    - [Packaging] remove update-dkms-versions
+    - Move debian/dkms-versions to debian.master/dkms-versions
+    - [Packaging] Replace debian/dkms-versions with $(DEBIAN)/dkms-versions
+    - [Packaging] remove update-version-dkms
+
+  * linux-tools-common: man page of usbip[d] is misplaced (LP: #2054094)
+    - [Packaging] rules: Put usbip manpages in the correct directory
+
+  * CVE-2024-23851
+    - dm ioctl: log an error if the ioctl structure is corrupted
+    - dm: limit the number of targets and parameter size area
+
+  * Focal update: v5.4.268 upstream stable release (LP: #2055075)
+    - f2fs: explicitly null-terminate the xattr list
+    - pinctrl: lochnagar: Don't build on MIPS
+    - ALSA: hda - Fix speaker and headset mic pin config for CHUWI CoreBook XPro
+    - ASoC: Intel: Skylake: Fix mem leak in few functions
+    - ASoC: nau8822: Fix incorrect type in assignment and cast to restricted
+      __be16
+    - ASoC: Intel: Skylake: mem leak in skl register function
+    - ASoC: cs43130: Fix the position of const qualifier
+    - ASoC: cs43130: Fix incorrect frame delay configuration
+    - ASoC: rt5650: add mutex to avoid the jack detection failure
+    - nouveau/tu102: flush all pdbs on vmm flush
+    - net/tg3: fix race condition in tg3_reset_task()
+    - ASoC: da7219: Support low DC impedance headset
+    - nvme: introduce helper function to get ctrl state
+    - drm/exynos: fix a potential error pointer dereference
+    - drm/exynos: fix a wrong error checking
+    - clk: rockchip: rk3128: Fix HCLK_OTG gate register
+    - jbd2: correct the printing of write_flags in jbd2_write_superblock()
+    - drm/crtc: Fix uninit-value bug in drm_mode_setcrtc
+    - neighbour: Don't let neigh_forced_gc() disable preemption for long
+    - tracing: Have large events show up as '[LINE TOO BIG]' instead of nothing
+    - tracing: Add size check when printing trace_marker output
+    - ring-buffer: Do not record in NMI if the arch does not support cmpxchg in
+      NMI
+    - reset: hisilicon: hi6220: fix Wvoid-pointer-to-enum-cast warning
+    - Input: atkbd - skip ATKBD_CMD_GETID in translated mode
+    - Input: i8042 - add nomux quirk for Acer P459-G2-M
+    - s390/scm: fix virtual vs physical address confusion
+    - ARC: fix spare error
+    - Input: xpad - add Razer Wolverine V2 support
+    - ARM: sun9i: smp: fix return code check of of_property_match_string
+    - drm/crtc: fix uninitialized variable use
+    - ACPI: resource: Add another DMI match for the TongFang GMxXGxx
+    - binder: use EPOLLERR from eventpoll.h
+    - binder: fix trivial typo of binder_free_buf_locked()
+    - binder: fix comment on binder_alloc_new_buf() return value
+    - uio: Fix use-after-free in uio_open
+    - parport: parport_serial: Add Brainboxes BAR details
+    - parport: parport_serial: Add Brainboxes device IDs and geometry
+    - coresight: etm4x: Fix width of CCITMIN field
+    - x86/lib: Fix overflow when counting digits
+    - EDAC/thunderx: Fix possible out-of-bounds string access
+    - powerpc: add crtsavres.o to always-y instead of extra-y
+    - powerpc/44x: select I2C for CURRITUCK
+    - powerpc/pseries/memhotplug: Quieten some DLPAR operations
+    - powerpc/pseries/memhp: Fix access beyond end of drmem array
+    - selftests/powerpc: Fix error handling in FPU/VMX preemption tests
+    - powerpc/powernv: Add a null pointer check to scom_debug_init_one()
+    - powerpc/powernv: Add a null pointer check in opal_event_init()
+    - powerpc/powernv: Add a null pointer check in opal_powercap_init()
+    - powerpc/imc-pmu: Add a null pointer check in update_events_in_group()
+    - mtd: rawnand: Increment IFC_TIMEOUT_MSECS for nand controller response
+    - ACPI: video: check for error while searching for backlight device parent
+    - ACPI: LPIT: Avoid u32 multiplication overflow
+    - net: netlabel: Fix kerneldoc warnings
+    - netlabel: remove unused parameter in netlbl_netlink_auditinfo()
+    - calipso: fix memory leak in netlbl_calipso_add_pass()
+    - spi: sh-msiof: Enforce fixed DTDL for R-Car H3
+    - mtd: Fix gluebi NULL pointer dereference caused by ftl notifier
+    - selinux: Fix error priority for bind with AF_UNSPEC on PF_INET6 socket
+    - crypto: virtio - Handle dataq logic with tasklet
+    - crypto: virtio - don't use 'default m'
+    - virtio_crypto: Introduce VIRTIO_CRYPTO_NOSPC
+    - crypto: ccp - fix memleak in ccp_init_dm_workarea
+    - crypto: af_alg - Disallow multiple in-flight AIO requests
+    - crypto: sahara - remove FLAGS_NEW_KEY logic
+    - crypto: sahara - fix ahash selftest failure
+    - crypto: sahara - fix processing requests with cryptlen < sg->length
+    - crypto: sahara - fix error handling in sahara_hw_descriptor_create()
+    - pstore: ram_core: fix possible overflow in persistent_ram_init_ecc()
+    - gfs2: Fix kernel NULL pointer dereference in gfs2_rgrp_dump
+    - crypto: virtio - Wait for tasklet to complete on device remove
+    - crypto: sahara - fix ahash reqsize
+    - crypto: sahara - fix wait_for_completion_timeout() error handling
+    - crypto: sahara - improve error handling in sahara_sha_process()
+    - crypto: sahara - fix processing hash requests with req->nbytes < sg->length
+    - crypto: sahara - do not resize req->src when doing hash operations
+    - crypto: scomp - fix req->dst buffer overflow
+    - blocklayoutdriver: Fix reference leak of pnfs_device_node
+    - NFSv4.1/pnfs: Ensure we handle the error NFS4ERR_RETURNCONFLICT
+    - wifi: rtw88: fix RX filter in FIF_ALLMULTI flag
+    - bpf, lpm: Fix check prefixlen before walking trie
+    - wifi: libertas: stop selecting wext
+    - ARM: dts: qcom: apq8064: correct XOADC register address
+    - ncsi: internal.h: Fix a spello
+    - net/ncsi: Fix netlink major/minor version numbers
+    - firmware: ti_sci: Fix an off-by-one in ti_sci_debugfs_create()
+    - rtlwifi: Use ffs in <foo>_phy_calculate_bit_shift
+    - wifi: rtlwifi: rtl8821ae: phy: fix an undefined bitwise shift behavior
+    - scsi: fnic: Return error if vmalloc() failed
+    - arm64: dts: qcom: sdm845-db845c: correct LED panic indicator
+    - scsi: hisi_sas: Replace with standard error code return value
+    - selftests/net: fix grep checking for fib_nexthop_multiprefix
+    - virtio/vsock: fix logic which reduces credit update messages
+    - dma-mapping: clear dev->dma_mem to NULL after freeing it
+    - wifi: rtlwifi: add calculate_bit_shift()
+    - wifi: rtlwifi: rtl8188ee: phy: using calculate_bit_shift()
+    - wifi: rtlwifi: rtl8192c: using calculate_bit_shift()
+    - wifi: rtlwifi: rtl8192cu: using calculate_bit_shift()
+    - wifi: rtlwifi: rtl8192ce: using calculate_bit_shift()
+    - rtlwifi: rtl8192de: make arrays static const, makes object smaller
+    - wifi: rtlwifi: rtl8192de: using calculate_bit_shift()
+    - wifi: rtlwifi: rtl8192ee: using calculate_bit_shift()
+    - wifi: rtlwifi: rtl8192se: using calculate_bit_shift()
+    - netfilter: nf_tables: mark newset as dead on transaction abort
+    - Bluetooth: Fix bogus check for re-auth no supported with non-ssp
+    - Bluetooth: btmtkuart: fix recv_buf() return value
+    - ip6_tunnel: fix NEXTHDR_FRAGMENT handling in ip6_tnl_parse_tlv_enc_lim()
+    - ARM: davinci: always select CONFIG_CPU_ARM926T
+    - RDMA/usnic: Silence uninitialized symbol smatch warnings
+    - media: pvrusb2: fix use after free on context disconnection
+    - drm/bridge: Fix typo in post_disable() description
+    - f2fs: fix to avoid dirent corruption
+    - drm/radeon/r600_cs: Fix possible int overflows in r600_cs_check_reg()
+    - drm/radeon/r100: Fix integer overflow issues in r100_cs_track_check()
+    - drm/radeon: check return value of radeon_ring_lock()
+    - ASoC: cs35l33: Fix GPIO name and drop legacy include
+    - ASoC: cs35l34: Fix GPIO name and drop legacy include
+    - drm/msm/mdp4: flush vblank event on disable
+    - drm/msm/dsi: Use pm_runtime_resume_and_get to prevent refcnt leaks
+    - drm/drv: propagate errors from drm_modeset_register_all()
+    - drm/radeon: check the alloc_workqueue return value in radeon_crtc_init()
+    - drm/radeon/dpm: fix a memleak in sumo_parse_power_table
+    - drm/radeon/trinity_dpm: fix a memleak in trinity_parse_power_table
+    - drm/bridge: tc358767: Fix return value on error case
+    - media: cx231xx: fix a memleak in cx231xx_init_isoc
+    - media: dvbdev: drop refcount on error path in dvb_device_open()
+    - drm/amdgpu/debugfs: fix error code when smc register accessors are NULL
+    - drm/amd/pm: fix a double-free in si_dpm_init
+    - drivers/amd/pm: fix a use-after-free in kv_parse_power_table
+    - gpu/drm/radeon: fix two memleaks in radeon_vm_init
+    - drivers: clk: zynqmp: calculate closest mux rate
+    - watchdog: set cdev owner before adding
+    - watchdog/hpwdt: Only claim UNKNOWN NMI if from iLO
+    - watchdog: bcm2835_wdt: Fix WDIOC_SETTIMEOUT handling
+    - clk: si5341: fix an error code problem in si5341_output_clk_set_rate
+    - mmc: sdhci_omap: Fix TI SoC dependencies
+    - [Config] update annotations for CONFIG_MMC_SDHCI_OMAP
+    - [Config] remove sdhci-omap module for arm64/ppc64el
+    - of: Fix double free in of_parse_phandle_with_args_map
+    - of: unittest: Fix of_count_phandle_with_args() expected value message
+    - binder: fix async space check for 0-sized buffers
+    - binder: fix use-after-free in shinker's callback
+    - Input: atkbd - use ab83 as id when skipping the getid command
+    - Revert "ASoC: atmel: Remove system clock tree configuration for
+      at91sam9g20ek"
+    - binder: fix race between mmput() and do_exit()
+    - binder: fix unused alloc->free_async_space
+    - tick-sched: Fix idle and iowait sleeptime accounting vs CPU hotplug
+    - usb: phy: mxs: remove CONFIG_USB_OTG condition for mxs_phy_is_otg_host()
+    - usb: dwc: ep0: Update request status in dwc3_ep0_stall_restart
+    - Revert "usb: dwc3: Soft reset phy on probe for host"
+    - Revert "usb: dwc3: don't reset device side if dwc3 was configured as host-
+      only"
+    - usb: chipidea: wait controller resume finished for wakeup irq
+    - Revert "usb: typec: class: fix typec_altmode_put_partner to put plugs"
+    - usb: typec: class: fix typec_altmode_put_partner to put plugs
+    - usb: mon: Fix atomicity violation in mon_bin_vma_fault
+    - ALSA: oxygen: Fix right channel of capture volume mixer
+    - fbdev: flush deferred work in fb_deferred_io_fsync()
+    - rootfs: Fix support for rootfstype= when root= is given
+    - wifi: rtlwifi: Remove bogus and dangerous ASPM disable/enable code
+    - wifi: rtlwifi: Convert LNKCTL change to PCIe cap RMW accessors
+    - wifi: mwifiex: configure BSSID consistently when starting AP
+    - x86/kvm: Do not try to disable kvmclock if it was not enabled
+    - HID: wacom: Correct behavior when processing some confidence == false
+      touches
+    - mips: Fix incorrect max_low_pfn adjustment
+    - MIPS: Alchemy: Fix an out-of-bound access in db1200_dev_setup()
+    - MIPS: Alchemy: Fix an out-of-bound access in db1550_dev_setup()
+    - serial: 8250: omap: Don't skip resource freeing if
+      pm_runtime_resume_and_get() failed
+    - acpi: property: Let args be NULL in __acpi_node_get_property_reference
+    - software node: Let args be NULL in software_node_get_reference_args
+    - perf genelf: Set ELF program header addresses properly
+    - nvmet-tcp: Fix a kernel panic when host sends an invalid H2C PDU length
+    - nvmet-tcp: fix a crash in nvmet_req_complete()
+    - perf env: Add perf_env__numa_node()
+    - perf record: Move sb_evlist to 'struct record'
+    - perf top: Move sb_evlist to 'struct perf_top'
+    - perf bpf: Decouple creating the evlist from adding the SB event
+    - perf env: Avoid recursively taking env->bpf_progs.lock
+    - apparmor: avoid crash when parsed profile name is empty
+    - serial: imx: Correct clock error message in function probe()
+    - nvmet-tcp: Fix the H2C expected PDU len calculation
+    - PCI: keystone: Fix race condition when initializing PHYs
+    - s390/pci: fix max size calculation in zpci_memcpy_toio()
+    - net: qualcomm: rmnet: fix global oob in rmnet_policy
+    - net: phy: micrel: populate .soft_reset for KSZ9131
+    - net: ravb: Fix dma_addr_t truncation in error case
+    - net: dsa: vsc73xx: Add null pointer check to vsc73xx_gpio_probe
+    - netfilter: nf_tables: skip dead set elements in netlink dump
+    - ipvs: avoid stat macros calls from preemptible context
+    - kdb: Censor attempts to set PROMPT without ENABLE_MEM_READ
+    - kdb: Fix a potential buffer overflow in kdb_local()
+    - mlxsw: spectrum_acl_erp: Fix error flow of pool allocation failure
+    - i2c: s3c24xx: fix read transfers in polling mode
+    - i2c: s3c24xx: fix transferring more than one message in polling mode
+    - perf top: Skip side-band event setup if HAVE_LIBBPF_SUPPORT is not set
+    - arm64: dts: armada-3720-turris-mox: set irq type for RTC
+    - Linux 5.4.268
+
+  * CVE-2024-24855
+    - scsi: lpfc: Fix a possible data race in lpfc_unregister_fcf_rescan()
+
+  * Focal update: v5.4.267 upstream stable release (LP: #2054406)
+    - nfc: llcp_core: Hold a ref to llcp_local->dev when holding a ref to
+      llcp_local
+    - i40e: Fix filter input checks to prevent config with invalid values
+    - net: sched: em_text: fix possible memory leak in em_text_destroy()
+    - can: raw: add support for SO_TXTIME/SCM_TXTIME
+    - can: raw: add support for SO_MARK
+    - net-timestamp: extend SOF_TIMESTAMPING_OPT_ID to HW timestamps
+    - ARM: sun9i: smp: Fix array-index-out-of-bounds read in sunxi_mc_smp_init
+    - net: bcmgenet: Fix FCS generation for fragmented skbuffs
+    - net: Save and restore msg_namelen in sock_sendmsg
+    - i40e: fix use-after-free in i40e_aqc_add_filters()
+    - ASoC: meson: g12a: extract codec-to-codec utils
+    - [Config] Update annotations for CONFIG_SND_MESON_CODEC_GLUE
+    - ASoC: meson: g12a-tohdmitx: Validate written enum values
+    - ASoC: meson: g12a-tohdmitx: Fix event generation for S/PDIF mux
+    - i40e: Restore VF MSI-X state during PCI reset
+    - net/qla3xxx: switch from 'pci_' to 'dma_' API
+    - net/qla3xxx: fix potential memleak in ql_alloc_buffer_queues
+    - asix: Add check for usbnet_get_endpoints
+    - bnxt_en: Remove mis-applied code from bnxt_cfg_ntp_filters()
+    - net: Implement missing SO_TIMESTAMPING_NEW cmsg support
+    - mm/memory-failure: check the mapcount of the precise page
+    - firewire: ohci: suppress unexpected system reboot in AMD Ryzen machines and
+      ASM108x/VT630x PCIe cards
+    - i2c: core: Fix atomic xfer check for non-preempt config
+    - mm: fix unmap_mapping_range high bits shift bug
+    - mmc: rpmb: fixes pause retune on all RPMB partitions.
+    - mmc: core: Cancel delayed work before releasing host
+    - mmc: sdhci-sprd: Fix eMMC init failure after hw reset
+    - ath10k: Wait until copy complete is actually done before completing
+    - ath10k: Add interrupt summary based CE processing
+    - ath10k: Keep track of which interrupts fired, don't poll them
+    - ath10k: Get rid of "per_ce_irq" hw param
+    - PCI: Extract ATS disabling to a helper function
+    - PCI: Disable ATS for specific Intel IPU E2000 devices
+    - net/dst: use a smaller percpu_counter batch for dst entries accounting
+    - ipv6: make ip6_rt_gc_expire an atomic_t
+    - ipv6: remove max_size check inline with ipv4
+    - ASoC: meson: codec-glue: fix pcm format cast warning
+    - Linux 5.4.267
+
+  * CVE-2023-23000
+    - phy: tegra: xusb: Fix return value of tegra_xusb_find_port_node function
+
+  * CVE-2023-23004
+    - malidp: Fix NULL vs IS_ERR() checking
+
+  * CVE-2023-46838
+    - xen-netback: don't produce zero-size SKB frags
+
+  * CVE-2024-1086
+    - netfilter: nf_tables: reject QUEUE/DROP verdict parameters
+
+  * Focal update: v5.4.266 upstream stable release (LP: #2051655)
+    - ALSA: hda/realtek: Enable headset on Lenovo M90 Gen5
+    - ksmbd: fix wrong name of SMB2_CREATE_ALLOCATION_SIZE
+    - ARM: OMAP2+: Fix null pointer dereference and memory leak in
+      omap_soc_device_init
+    - reset: Fix crash when freeing non-existent optional resets
+    - s390/vx: fix save/restore of fpu kernel context
+    - wifi: mac80211: mesh_plink: fix matches_local logic
+    - net/mlx5: improve some comments
+    - net/mlx5: Fix fw tracer first block check
+    - net/mlx5e: Correct snprintf truncation handling for fw_version buffer used
+      by representors
+    - net: sched: ife: fix potential use-after-free
+    - ethernet: atheros: fix a memleak in atl1e_setup_ring_resources
+    - net/rose: fix races in rose_kill_by_device()
+    - net: check vlan filter feature in vlan_vids_add_by_dev() and
+      vlan_vids_del_by_dev()
+    - afs: Fix the dynamic root's d_delete to always delete unused dentries
+    - afs: Fix dynamic root lookup DNS check
+    - net: warn if gso_type isn't set for a GSO SKB
+    - net: check dev->gso_max_size in gso_features_check()
+    - afs: Fix overwriting of result of DNS query
+    - i2c: aspeed: Handle the coalesced stop conditions with the start conditions.
+    - pinctrl: at91-pio4: use dedicated lock class for IRQ
+    - ALSA: hda/hdmi: Add quirk to force pin connectivity on NUC10
+    - ALSA: hda/hdmi: add force-connect quirk for NUC5CPYB
+    - smb: client: fix NULL deref in asn1_ber_decoder()
+    - btrfs: do not allow non subvolume root targets for snapshot
+    - interconnect: Treat xlate() returning NULL node as an error
+    - iio: imu: inv_mpu6050: fix an error code problem in inv_mpu6050_read_raw
+    - Input: ipaq-micro-keys - add error handling for devm_kmemdup
+    - scsi: bnx2fc: Fix skb double free in bnx2fc_rcv()
+    - iio: common: ms_sensors: ms_sensors_i2c: fix humidity conversion time table
+    - iio: adc: ti_am335x_adc: Fix return value check of tiadc_request_dma()
+    - wifi: cfg80211: Add my certificate
+    - wifi: cfg80211: fix certs build to not depend on file order
+    - USB: serial: ftdi_sio: update Actisense PIDs constant names
+    - USB: serial: option: add Quectel EG912Y module support
+    - USB: serial: option: add Foxconn T99W265 with new baseline
+    - USB: serial: option: add Quectel RM500Q R13 firmware support
+    - Bluetooth: hci_event: Fix not checking if HCI_OP_INQUIRY has been sent
+    - net: 9p: avoid freeing uninit memory in p9pdu_vreadf
+    - net: rfkill: gpio: set GPIO direction
+    - x86/alternatives: Sync core before enabling interrupts
+    - usb: fotg210-hcd: delete an incorrect bounds test
+    - ring-buffer: Fix wake ups when buffer_percent is set to 100
+    - block: Don't invalidate pagecache for invalid falloc modes
+    - Linux 5.4.266
+
+  * CVE-2024-0607
+    - netfilter: nf_tables: fix pointer math issue in nft_byteorder_eval()
+
+ -- Roxana Nicolescu <roxana.nicolescu@canonical.com>  Thu, 07 Mar 2024 17:43:37 +0100
+
+linux (5.4.0-173.191) focal; urgency=medium
+
+  * focal/linux: 5.4.0-173.191 -proposed tracker (LP: #2052135)
+
+  * Packaging resync (LP: #1786013)
+    - debian/dkms-versions -- update from kernel-versions (main/2024.02.05)
+
+  * CVE-2023-0340
+    - vhost: use kzalloc() instead of kmalloc() followed by memset()
+
+  * CVE-2023-6915
+    - ida: Fix crash in ida_free when the bitmap is empty
+
+  * Focal update: v5.4.265 upstream stable release (LP: #2051644)
+    - afs: Fix refcount underflow from error handling race
+    - net: ipv6: support reporting otherwise unknown prefix flags in RTM_NEWPREFIX
+    - qca_debug: Prevent crash on TX ring changes
+    - qca_debug: Fix ethtool -G iface tx behavior
+    - qca_spi: Fix reset behavior
+    - atm: solos-pci: Fix potential deadlock on &cli_queue_lock
+    - atm: solos-pci: Fix potential deadlock on &tx_queue_lock
+    - atm: Fix Use-After-Free in do_vcc_ioctl
+    - qed: Fix a potential use-after-free in qed_cxt_tables_alloc
+    - net: Remove acked SYN flag from packet in the transmit queue correctly
+    - sign-file: Fix incorrect return values check
+    - vsock/virtio: Fix unsigned integer wrap around in
+      virtio_transport_has_space()
+    - net: stmmac: use dev_err_probe() for reporting mdio bus registration failure
+    - net: stmmac: Handle disabled MDIO busses from devicetree
+    - cred: switch to using atomic_long_t
+    - ALSA: hda/hdmi: add force-connect quirks for ASUSTeK Z170 variants
+    - usb: aqc111: check packet for fixup for true limit
+    - blk-throttle: fix lockdep warning of "cgroup_mutex or RCU read lock
+      required!"
+    - bcache: avoid oversize memory allocation by small stripe_size
+    - bcache: add code comments for bch_btree_node_get() and
+      __bch_btree_node_alloc()
+    - bcache: avoid NULL checking to c->root in run_cache_set()
+    - platform/x86: intel_telemetry: Fix kernel doc descriptions
+    - HID: add ALWAYS_POLL quirk for Apple kb
+    - HID: hid-asus: reset the backlight brightness level on resume
+    - HID: multitouch: Add quirk for HONOR GLO-GXXX touchpad
+    - asm-generic: qspinlock: fix queued_spin_value_unlocked() implementation
+    - net: usb: qmi_wwan: claim interface 4 for ZTE MF290
+    - HID: hid-asus: add const to read-only outgoing usb buffer
+    - soundwire: stream: fix NULL pointer dereference for multi_link
+    - ext4: prevent the normalized size from exceeding EXT_MAX_BLOCKS
+    - arm64: mm: Always make sw-dirty PTEs hw-dirty in pte_modify
+    - team: Fix use-after-free when an option instance allocation fails
+    - ring-buffer: Fix memory leak of free page
+    - mmc: block: Be sure to wait while busy in CQE error recovery
+    - powerpc/ftrace: Create a dummy stackframe to fix stack unwind
+    - powerpc/ftrace: Fix stack teardown in ftrace_no_trace
+    - Linux 5.4.265
+
+  * Focal update: v5.4.264 upstream stable release (LP: #2049935)
+    - hrtimers: Push pending hrtimers away from outgoing CPU earlier
+    - netfilter: ipset: fix race condition between swap/destroy and kernel side
+      add/del/test
+    - tg3: Move the [rt]x_dropped counters to tg3_napi
+    - tg3: Increment tx_dropped in tg3_tso_bug()
+    - kconfig: fix memory leak from range properties
+    - drm/amdgpu: correct chunk_ptr to a pointer to chunk.
+    - of: base: Add of_get_cpu_state_node() to get idle states for a CPU node
+    - ACPI/IORT: Make iort_get_device_domain IRQ domain agnostic
+    - ACPI/IORT: Make iort_msi_map_rid() PCI agnostic
+    - of/iommu: Make of_map_rid() PCI agnostic
+    - of/irq: make of_msi_map_get_device_domain() bus agnostic
+    - of/irq: Make of_msi_map_rid() PCI bus agnostic
+    - of: base: Fix some formatting issues and provide missing descriptions
+    - of: Fix kerneldoc output formatting
+    - of: Add missing 'Return' section in kerneldoc comments
+    - of: dynamic: Fix of_reconfig_get_state_change() return value documentation
+    - ipv6: fix potential NULL deref in fib6_add()
+    - hv_netvsc: rndis_filter needs to select NLS
+    - net: arcnet: Fix RESET flag handling
+    - net: arcnet: com20020 fix error handling
+    - arcnet: restoring support for multiple Sohard Arcnet cards
+    - ipv4: ip_gre: Avoid skb_pull() failure in ipgre_xmit()
+    - net: hns: fix fake link up on xge port
+    - netfilter: xt_owner: Fix for unsafe access of sk->sk_socket
+    - tcp: do not accept ACK of bytes we never sent
+    - bpf: sockmap, updating the sg structure should also update curr
+    - RDMA/bnxt_re: Correct module description string
+    - hwmon: (acpi_power_meter) Fix 4.29 MW bug
+    - ASoC: wm_adsp: fix memleak in wm_adsp_buffer_populate
+    - tracing: Fix a warning when allocating buffered events fails
+    - scsi: be2iscsi: Fix a memleak in beiscsi_init_wrb_handle()
+    - ARM: imx: Check return value of devm_kasprintf in imx_mmdc_perf_init
+    - ARM: dts: imx: make gpt node name generic
+    - ARM: dts: imx7: Declare timers compatible with fsl,imx6dl-gpt
+    - ALSA: pcm: fix out-of-bounds in snd_pcm_state_names
+    - nilfs2: prevent WARNING in nilfs_sufile_set_segment_usage()
+    - tracing: Always update snapshot buffer size
+    - tracing: Fix incomplete locking when disabling buffered events
+    - tracing: Fix a possible race when disabling buffered events
+    - packet: Move reference count in packet_sock to atomic_long_t
+    - arm64: dts: mediatek: mt7622: fix memory node warning check
+    - arm64: dts: mediatek: mt8173-evb: Fix regulator-fixed node names
+    - gpiolib: sysfs: Fix error handling on failed export
+    - mmc: core: add helpers mmc_regulator_enable/disable_vqmmc
+    - mmc: sdhci-sprd: Fix vqmmc not shutting down after the card was pulled
+    - usb: gadget: f_hid: fix report descriptor allocation
+    - parport: Add support for Brainboxes IX/UC/PX parallel cards
+    - usb: typec: class: fix typec_altmode_put_partner to put plugs
+    - ARM: PL011: Fix DMA support
+    - serial: sc16is7xx: address RX timeout interrupt errata
+    - serial: 8250_omap: Add earlycon support for the AM654 UART controller
+    - x86/CPU/AMD: Check vendor in the AMD microcode callback
+    - KVM: s390/mm: Properly reset no-dat
+    - nilfs2: fix missing error check for sb_set_blocksize call
+    - io_uring/af_unix: disable sending io_uring over sockets
+    - netlink: don't call ->netlink_bind with table lock held
+    - genetlink: add CAP_NET_ADMIN test for multicast bind
+    - psample: Require 'CAP_NET_ADMIN' when joining "packets" group
+    - drop_monitor: Require 'CAP_SYS_ADMIN' when joining "events" group
+    - tools headers UAPI: Sync linux/perf_event.h with the kernel sources
+    - cifs: Fix non-availability of dedup breaking generic/304
+    - smb: client: fix potential NULL deref in parse_dfs_referrals()
+    - devcoredump : Serialize devcd_del work
+    - devcoredump: Send uevent once devcd is ready
+    - Linux 5.4.264
+
+  * CVE-2024-0646
+    - net: tls, update curr on splice as well
+
+  * CVE-2024-0565
+    - smb: client: fix OOB in receive_encrypted_standard()
+
+  * CVE-2023-51781
+    - appletalk: Fix Use-After-Free in atalk_ioctl
+
+  * CVE-2023-51782
+    - net/rose: Fix Use-After-Free in rose_ioctl
+
+  * Focal update: v5.4.263 upstream stable release (LP: #2049084)
+    - driver core: Release all resources during unbind before updating device
+      links
+    - RDMA/irdma: Prevent zero-length STAG registration
+    - PCI: keystone: Drop __init from ks_pcie_add_pcie_{ep,port}()
+    - afs: Make error on cell lookup failure consistent with OpenAFS
+    - drm/panel: simple: Fix Innolux G101ICE-L01 bus flags
+    - drm/panel: simple: Fix Innolux G101ICE-L01 timings
+    - ata: pata_isapnp: Add missing error check for devm_ioport_map()
+    - drm/rockchip: vop: Fix color for RGB888/BGR888 format on VOP full
+    - HID: core: store the unique system identifier in hid_device
+    - HID: fix HID device resource race between HID core and debugging support
+    - ipv4: Correct/silence an endian warning in __ip_do_redirect
+    - net: usb: ax88179_178a: fix failed operations during ax88179_reset
+    - arm/xen: fix xen_vcpu_info allocation alignment
+    - amd-xgbe: handle corner-case during sfp hotplug
+    - amd-xgbe: handle the corner-case during tx completion
+    - amd-xgbe: propagate the correct speed and duplex status
+    - net: axienet: Fix check for partial TX checksum
+    - afs: Return ENOENT if no cell DNS record can be found
+    - afs: Fix file locking on R/O volumes to operate in local mode
+    - nvmet: remove unnecessary ctrl parameter
+    - nvmet: nul-terminate the NQNs passed in the connect command
+    - MIPS: KVM: Fix a build warning about variable set but not used
+    - ext4: add a new helper to check if es must be kept
+    - ext4: factor out __es_alloc_extent() and __es_free_extent()
+    - ext4: use pre-allocated es in __es_insert_extent()
+    - ext4: use pre-allocated es in __es_remove_extent()
+    - ext4: using nofail preallocation in ext4_es_remove_extent()
+    - ext4: using nofail preallocation in ext4_es_insert_delayed_block()
+    - ext4: using nofail preallocation in ext4_es_insert_extent()
+    - ext4: fix slab-use-after-free in ext4_es_insert_extent()
+    - ext4: make sure allocate pending entry not fail
+    - arm64: cpufeature: Extract capped perfmon fields
+    - KVM: arm64: limit PMU version to PMUv3 for ARMv8.1
+    - ACPI: resource: Skip IRQ override on ASUS ExpertBook B1402CVA
+    - bcache: replace a mistaken IS_ERR() by IS_ERR_OR_NULL() in
+      btree_gc_coalesce()
+    - s390/dasd: protect device queue against concurrent access
+    - USB: serial: option: add Luat Air72*U series products
+    - hv_netvsc: Fix race of register_netdevice_notifier and VF register
+    - hv_netvsc: Mark VF as slave before exposing it to user-mode
+    - dm-delay: fix a race between delay_presuspend and delay_bio
+    - bcache: check return value from btree_node_alloc_replacement()
+    - bcache: prevent potential division by zero error
+    - USB: serial: option: add Fibocom L7xx modules
+    - USB: serial: option: fix FM101R-GL defines
+    - USB: serial: option: don't claim interface 4 for ZTE MF290
+    - USB: dwc2: write HCINT with INTMASK applied
+    - usb: dwc3: set the dma max_seg_size
+    - USB: dwc3: qcom: fix resource leaks on probe deferral
+    - USB: dwc3: qcom: fix wakeup after probe deferral
+    - io_uring: fix off-by one bvec index
+    - pinctrl: avoid reload of p state in list iteration
+    - firewire: core: fix possible memory leak in create_units()
+    - mmc: block: Do not lose cache flush during CQE error recovery
+    - ALSA: hda: Disable power-save on KONTRON SinglePC
+    - ALSA: hda/realtek: Headset Mic VREF to 100%
+    - ALSA: hda/realtek: Add supported ALC257 for ChromeOS
+    - dm-verity: align struct dm_verity_fec_io properly
+    - dm verity: don't perform FEC for failed readahead IO
+    - bcache: revert replacing IS_ERR_OR_NULL with IS_ERR
+    - powerpc: Don't clobber f0/vs0 during fp|altivec register save
+    - btrfs: fix off-by-one when checking chunk map includes logical address
+    - btrfs: send: ensure send_fd is writable
+    - btrfs: make error messages more clear when getting a chunk map
+    - Input: xpad - add HyperX Clutch Gladiate Support
+    - net: stmmac: xgmac: Disable FPE MMC interrupts
+    - ravb: Fix races between ravb_tx_timeout_work() and net related ops
+    - net: ravb: Use pm_runtime_resume_and_get()
+    - net: ravb: Start TX queues after HW initialization succeeded
+    - smb3: fix touch -h of symlink
+    - s390/mm: fix phys vs virt confusion in mark_kernel_pXd() functions family
+    - s390/cmma: fix detection of DAT pages
+    - mtd: cfi_cmdset_0001: Support the absence of protection registers
+    - mtd: cfi_cmdset_0001: Byte swap OTP info
+    - fbdev: stifb: Make the STI next font pointer a 32-bit signed offset
+    - ima: annotate iint mutex to avoid lockdep false positive warnings
+    - ovl: skip overlayfs superblocks at global sync
+    - ima: detect changes to the backing overlay file
+    - scsi: qla2xxx: Simplify the code for aborting SCSI commands
+    - scsi: core: Introduce the scsi_cmd_to_rq() function
+    - scsi: qla2xxx: Use scsi_cmd_to_rq() instead of scsi_cmnd.request
+    - scsi: qla2xxx: Fix system crash due to bad pointer access
+    - cpufreq: imx6q: don't warn for disabling a non-existing frequency
+    - cpufreq: imx6q: Don't disable 792 Mhz OPP unnecessarily
+    - mmc: cqhci: Increase recovery halt timeout
+    - mmc: cqhci: Warn of halt or task clear failure
+    - mmc: cqhci: Fix task clearing in CQE error recovery
+    - mmc: core: convert comma to semicolon
+    - mmc: block: Retry commands in CQE error recovery
+    - Linux 5.4.263
+
+  * Focal update: v5.4.262 upstream stable release (LP: #2049069)
+    - locking/ww_mutex/test: Fix potential workqueue corruption
+    - perf/core: Bail out early if the request AUX area is out of bound
+    - clocksource/drivers/timer-imx-gpt: Fix potential memory leak
+    - clocksource/drivers/timer-atmel-tcb: Fix initialization on SAM9 hardware
+    - x86/mm: Drop the 4 MB restriction on minimal NUMA node memory size
+    - wifi: mac80211_hwsim: fix clang-specific fortify warning
+    - wifi: mac80211: don't return unset power in ieee80211_get_tx_power()
+    - wifi: ath9k: fix clang-specific fortify warnings
+    - wifi: ath10k: fix clang-specific fortify warning
+    - net: annotate data-races around sk->sk_tx_queue_mapping
+    - net: annotate data-races around sk->sk_dst_pending_confirm
+    - wifi: ath10k: Don't touch the CE interrupt registers after power up
+    - Bluetooth: Fix double free in hci_conn_cleanup
+    - platform/x86: thinkpad_acpi: Add battery quirk for Thinkpad X120e
+    - drm/komeda: drop all currently held locks if deadlock happens
+    - drm/amd: Fix UBSAN array-index-out-of-bounds for SMU7
+    - drm/amd: Fix UBSAN array-index-out-of-bounds for Polaris and Tonga
+    - drm/amdgpu: Fix a null pointer access when the smc_rreg pointer is NULL
+    - selftests/efivarfs: create-read: fix a resource leak
+    - crypto: pcrypt - Fix hungtask for PADATA_RESET
+    - RDMA/hfi1: Use FIELD_GET() to extract Link Width
+    - fs/jfs: Add check for negative db_l2nbperpage
+    - fs/jfs: Add validity check for db_maxag and db_agpref
+    - jfs: fix array-index-out-of-bounds in dbFindLeaf
+    - jfs: fix array-index-out-of-bounds in diAlloc
+    - ARM: 9320/1: fix stack depot IRQ stack filter
+    - ALSA: hda: Fix possible null-ptr-deref when assigning a stream
+    - PCI: tegra194: Use FIELD_GET()/FIELD_PREP() with Link Width fields
+    - atm: iphase: Do PCI error checks on own line
+    - scsi: libfc: Fix potential NULL pointer dereference in fc_lport_ptp_setup()
+    - HID: Add quirk for Dell Pro Wireless Keyboard and Mouse KM5221W
+    - tty: vcc: Add check for kstrdup() in vcc_probe()
+    - usb: gadget: f_ncm: Always set current gadget in ncm_bind()
+    - i2c: sun6i-p2wi: Prevent potential division by zero
+    - media: gspca: cpia1: shift-out-of-bounds in set_flicker
+    - media: vivid: avoid integer overflow
+    - gfs2: ignore negated quota changes
+    - media: cobalt: Use FIELD_GET() to extract Link Width
+    - drm/amd/display: Avoid NULL dereference of timing generator
+    - kgdb: Flush console before entering kgdb on panic
+    - ASoC: ti: omap-mcbsp: Fix runtime PM underflow warnings
+    - pwm: Fix double shift bug
+    - wifi: iwlwifi: Use FW rate for non-data frames
+    - NFSv4.1: fix SP4_MACH_CRED protection for pnfs IO
+    - ipvlan: add ipvlan_route_v6_outbound() helper
+    - tty: Fix uninit-value access in ppp_sync_receive()
+    - net: hns3: fix variable may not initialized problem in hns3_init_mac_addr()
+    - tipc: Fix kernel-infoleak due to uninitialized TLV value
+    - ppp: limit MRU to 64K
+    - xen/events: fix delayed eoi list handling
+    - ptp: annotate data-race around q->head and q->tail
+    - bonding: stop the device in bond_setup_by_slave()
+    - net: ethernet: cortina: Fix max RX frame define
+    - net: ethernet: cortina: Handle large frames
+    - net: ethernet: cortina: Fix MTU max setting
+    - netfilter: nf_conntrack_bridge: initialize err to 0
+    - net: stmmac: Rework stmmac_rx()
+    - net: stmmac: fix rx budget limit check
+    - net/mlx5_core: Clean driver version and name
+    - net/mlx5e: Check return value of snprintf writing to fw_version buffer for
+      representors
+    - macvlan: Don't propagate promisc change to lower dev in passthru
+    - tools/power/turbostat: Fix a knl bug
+    - cifs: spnego: add ';' in HOST_KEY_LEN
+    - media: venus: hfi: add checks to perform sanity on queue pointers
+    - randstruct: Fix gcc-plugin performance mode to stay in group
+    - bpf: Fix precision tracking for BPF_ALU | BPF_TO_BE | BPF_END
+    - scsi: megaraid_sas: Increase register read retry rount from 3 to 30 for
+      selected registers
+    - x86/cpu/hygon: Fix the CPU topology evaluation for real
+    - KVM: x86: hyper-v: Don't auto-enable stimer on write from user-space
+    - KVM: x86: Ignore MSR_AMD64_TW_CFG access
+    - audit: don't take task_lock() in audit_exe_compare() code path
+    - audit: don't WARN_ON_ONCE(!current->mm) in audit_exe_compare()
+    - hvc/xen: fix error path in xen_hvc_init() to always register frontend driver
+    - PCI/sysfs: Protect driver's D3cold preference from user space
+    - ACPI: resource: Do IRQ override on TongFang GMxXGxx
+    - mmc: meson-gx: Remove setting of CMD_CFG_ERROR
+    - genirq/generic_chip: Make irq_remove_generic_chip() irqdomain aware
+    - PCI: keystone: Don't discard .remove() callback
+    - PCI: keystone: Don't discard .probe() callback
+    - parisc/pdc: Add width field to struct pdc_model
+    - clk: qcom: ipq8074: drop the CLK_SET_RATE_PARENT flag from PLL clocks
+    - mmc: vub300: fix an error code
+    - PM: hibernate: Use __get_safe_page() rather than touching the list
+    - PM: hibernate: Clean up sync_read handling in snapshot_write_next()
+    - btrfs: don't arbitrarily slow down delalloc if we're committing
+    - jbd2: fix potential data lost in recovering journal raced with synchronizing
+      fs bdev
+    - quota: explicitly forbid quota files from being encrypted
+    - kernel/reboot: emergency_restart: Set correct system_state
+    - i2c: core: Run atomic i2c xfer when !preemptible
+    - mcb: fix error handling for different scenarios when parsing
+    - dmaengine: stm32-mdma: correct desc prep when channel running
+    - mm/cma: use nth_page() in place of direct struct page manipulation
+    - i3c: master: cdns: Fix reading status register
+    - parisc: Prevent booting 64-bit kernels on PA1.x machines
+    - parisc/pgtable: Do not drop upper 5 address bits of physical address
+    - ALSA: info: Fix potential deadlock at disconnection
+    - ALSA: hda/realtek - Enable internal speaker of ASUS K6500ZC
+    - serial: meson: remove redundant initialization of variable id
+    - tty: serial: meson: retrieve port FIFO size from DT
+    - serial: meson: Use platform_get_irq() to get the interrupt
+    - tty: serial: meson: fix hard LOCKUP on crtscts mode
+    - Bluetooth: btusb: add Realtek 8822CE to usb_device_id table
+    - Bluetooth: btusb: Add Realtek RTL8852BE support ID 0x0cb8:0xc559
+    - bluetooth: Add device 0bda:887b to device tables
+    - bluetooth: Add device 13d3:3571 to device tables
+    - Bluetooth: btusb: Add RTW8852BE device 13d3:3570 to device tables
+    - Bluetooth: btusb: Add 0bda:b85b for Fn-Link RTL8852BE
+    - Revert ncsi: Propagate carrier gain/loss events to the NCSI controller
+    - net: dsa: lan9303: consequently nested-lock physical MDIO
+    - i2c: i801: fix potential race in i801_block_transaction_byte_by_byte
+    - media: lirc: drop trailing space from scancode transmit
+    - media: sharp: fix sharp encoding
+    - media: venus: hfi_parser: Add check to keep the number of codecs within
+      range
+    - media: venus: hfi: fix the check to handle session buffer requirement
+    - media: venus: hfi: add checks to handle capabilities from firmware
+    - nfsd: fix file memleak on client_opens_release
+    - ext4: apply umask if ACL support is disabled
+    - ext4: correct offset of gdb backup in non meta_bg group to update_backups
+    - ext4: correct return value of ext4_convert_meta_bg
+    - ext4: correct the start block of counting reserved clusters
+    - ext4: remove gdb backup copy for meta bg in setup_new_flex_group_blocks
+    - drm/amdgpu: fix error handling in amdgpu_bo_list_get()
+    - tracing: Have trace_event_file have ref counters
+    - netfilter: nf_tables: pass context to nft_set_destroy()
+    - netfilter: nftables: rename set element data activation/deactivation
+      functions
+    - netfilter: nf_tables: drop map element references from preparation phase
+    - netfilter: nft_set_rbtree: Switch to node list walk for overlap detection
+    - netfilter: nft_set_rbtree: fix null deref on element insertion
+    - netfilter: nft_set_rbtree: fix overlap expiration walk
+    - netfilter: nf_tables: don't skip expired elements during walk
+    - netfilter: nf_tables: GC transaction API to avoid race with control plane
+    - netfilter: nf_tables: adapt set backend to use GC transaction API
+    - netfilter: nft_set_hash: mark set element as dead when deleting from packet
+      path
+    - netfilter: nf_tables: remove busy mark and gc batch API
+    - netfilter: nf_tables: fix GC transaction races with netns and netlink event
+      exit path
+    - netfilter: nf_tables: GC transaction race with netns dismantle
+    - netfilter: nf_tables: GC transaction race with abort path
+    - netfilter: nf_tables: use correct lock to protect gc_list
+    - netfilter: nf_tables: defer gc run if previous batch is still pending
+    - netfilter: nft_set_rbtree: skip sync GC for new elements in this transaction
+    - netfilter: nft_set_rbtree: use read spinlock to avoid datapath contention
+    - netfilter: nft_set_hash: try later when GC hits EAGAIN on iteration
+    - netfilter: nf_tables: fix memleak when more than 255 elements expired
+    - netfilter: nf_tables: unregister flowtable hooks on netns exit
+    - netfilter: nf_tables: double hook unregistration in netns path
+    - netfilter: nftables: update table flags from the commit phase
+    - netfilter: nf_tables: fix table flag updates
+    - netfilter: nf_tables: disable toggling dormant table state more than once
+    - netfilter: nf_tables: bogus EBUSY when deleting flowtable after flush (for
+      5.4)
+    - Linux 5.4.262
+
+  * Focal update: v5.4.261 upstream stable release (LP: #2049049)
+    - vfs: fix readahead(2) on block devices
+    - genirq/matrix: Exclude managed interrupts in irq_matrix_allocated()
+    - i40e: fix potential memory leaks in i40e_remove()
+    - tcp: call tcp_try_undo_recovery when an RTOd TFO SYNACK is ACKed
+    - wifi: rtw88: debug: Fix the NULL vs IS_ERR() bug for debugfs_create_file()
+    - wifi: mt76: mt7603: rework/fix rx pse hang check
+    - tcp_metrics: add missing barriers on delete
+    - tcp_metrics: properly set tp->snd_ssthresh in tcp_init_metrics()
+    - tcp_metrics: do not create an entry from tcp_init_metrics()
+    - wifi: rtlwifi: fix EDCA limit set by BT coexistence
+    - can: dev: can_restart(): don't crash kernel if carrier is OK
+    - can: dev: can_restart(): fix race condition between controller restart and
+      netif_carrier_on()
+    - thermal: core: prevent potential string overflow
+    - r8169: use tp_to_dev instead of open code
+    - r8169: fix rare issue with broken rx after link-down on RTL8125
+    - chtls: fix tp->rcv_tstamp initialization
+    - tcp: Remove one extra ktime_get_ns() from cookie_init_timestamp
+    - tcp: fix cookie_init_timestamp() overflows
+    - ACPI: sysfs: Fix create_pnp_modalias() and create_of_modalias()
+    - ipv6: avoid atomic fragment on GSO packets
+    - net: add DEV_STATS_READ() helper
+    - ipvlan: properly track tx_errors
+    - regmap: debugfs: Fix a erroneous check after snprintf()
+    - clk: qcom: clk-rcg2: Fix clock rate overflow for high parent frequencies
+    - clk: qcom: gcc-sm8150: use ARRAY_SIZE instead of specifying num_parents
+    - clk: qcom: gcc-sm8150: Fix gcc_sdcc2_apps_clk_src
+    - clk: imx: Select MXC_CLK for CLK_IMX8QXP
+    - clk: keystone: pll: fix a couple NULL vs IS_ERR() checks
+    - clk: npcm7xx: Fix incorrect kfree
+    - clk: mediatek: clk-mt6779: Add check for mtk_alloc_clk_data
+    - clk: mediatek: clk-mt6797: Add check for mtk_alloc_clk_data
+    - clk: mediatek: clk-mt7629-eth: Add check for mtk_alloc_clk_data
+    - clk: mediatek: clk-mt7629: Add check for mtk_alloc_clk_data
+    - clk: mediatek: clk-mt2701: Add check for mtk_alloc_clk_data
+    - platform/x86: wmi: Fix probe failure when failing to register WMI devices
+    - platform/x86: wmi: remove unnecessary initializations
+    - platform/x86: wmi: Fix opening of char device
+    - hwmon: (coretemp) Fix potentially truncated sysfs attribute name
+    - drm/rockchip: vop: Fix reset of state in duplicate state crtc funcs
+    - drm/rockchip: vop: Fix call to crtc reset helper
+    - drm/radeon: possible buffer overflow
+    - drm/rockchip: cdn-dp: Fix some error handling paths in cdn_dp_probe()
+    - arm64: dts: qcom: sdm845-mtp: fix WiFi configuration
+    - ARM: dts: qcom: mdm9615: populate vsdcc fixed regulator
+    - soc: qcom: llcc cleanup to get rid of sdm845 specific driver file
+    - [Config] remove CONFIG_QCOM_SDM845_LLCC
+    - soc: qcom: Rename llcc-slice to llcc-qcom
+    - [Config] remove llcc-slice module
+    - soc: qcom: llcc: Handle a second device without data corruption
+    - firmware: ti_sci: Replace HTTP links with HTTPS ones
+    - firmware: ti_sci: Mark driver as non removable
+    - clk: scmi: Free scmi_clk allocated when the clocks with invalid info are
+      skipped
+    - hwrng: geode - fix accessing registers
+    - libnvdimm/of_pmem: Use devm_kstrdup instead of kstrdup and check its return
+      value
+    - sched/rt: Provide migrate_disable/enable() inlines
+    - nd_btt: Make BTT lanes preemptible
+    - crypto: caam/qi2 - fix Chacha20 + Poly1305 self test failure
+    - crypto: caam/jr - fix Chacha20 + Poly1305 self test failure
+    - HID: cp2112: Use irqchip template
+    - hid: cp2112: Fix duplicate workqueue initialization
+    - ARM: 9321/1: memset: cast the constant byte to unsigned char
+    - ext4: move 'ix' sanity check to corrent position
+    - scsi: ufs: core: Leave space for '\0' in utf8 desc string
+    - RDMA/hfi1: Workaround truncation compilation error
+    - sh: bios: Revive earlyprintk support
+    - ASoC: Intel: Skylake: Fix mem leak when parsing UUIDs fails
+    - ASoC: ams-delta.c: use component after check
+    - mfd: dln2: Fix double put in dln2_probe
+    - leds: pwm: simplify if condition
+    - leds: pwm: convert to atomic PWM API
+    - leds: pwm: Don't disable the PWM when the LED should be off
+    - ledtrig-cpu: Limit to 8 CPUs
+    - leds: trigger: ledtrig-cpu:: Fix 'output may be truncated' issue for 'cpu'
+    - tty: tty_jobctrl: fix pid memleak in disassociate_ctty()
+    - usb: dwc2: fix possible NULL pointer dereference caused by driver
+      concurrency
+    - dmaengine: ti: edma: handle irq_of_parse_and_map() errors
+    - misc: st_core: Do not call kfree_skb() under spin_lock_irqsave()
+    - tools: iio: privatize globals and functions in iio_generic_buffer.c file
+    - tools: iio: iio_generic_buffer: Fix some integer type and calculation
+    - tools: iio: iio_generic_buffer ensure alignment
+    - USB: usbip: fix stub_dev hub disconnect
+    - dmaengine: pxa_dma: Remove an erroneous BUG_ON() in pxad_free_desc()
+    - f2fs: fix to initialize map.m_pblk in f2fs_precache_extents()
+    - modpost: fix tee MODULE_DEVICE_TABLE built on big-endian host
+    - powerpc/xive: Fix endian conversion size
+    - powerpc/imc-pmu: Use the correct spinlock initializer.
+    - powerpc/pseries: fix potential memory leak in init_cpu_associativity()
+    - i3c: Fix potential refcount leak in i3c_master_register_new_i3c_devs
+    - rtc: pcf85363: fix wrong mask/val parameters in regmap_update_bits call
+    - pcmcia: cs: fix possible hung task and memory leak pccardd()
+    - pcmcia: ds: fix refcount leak in pcmcia_device_add()
+    - pcmcia: ds: fix possible name leak in error path in pcmcia_device_add()
+    - media: bttv: fix use after free error due to btv->timeout timer
+    - media: s3c-camif: Avoid inappropriate kfree()
+    - media: dvb-usb-v2: af9035: fix missing unlock
+    - regmap: prevent noinc writes from clobbering cache
+    - pwm: sti: Avoid conditional gotos
+    - pwm: sti: Reduce number of allocations and drop usage of chip_data
+    - pwm: brcmstb: Utilize appropriate clock APIs in suspend/resume
+    - Input: synaptics-rmi4 - fix use after free in rmi_unregister_function()
+    - llc: verify mac len before reading mac header
+    - tipc: Change nla_policy for bearer-related names to NLA_NUL_STRING
+    - inet: shrink struct flowi_common
+    - dccp: Call security_inet_conn_request() after setting IPv4 addresses.
+    - dccp/tcp: Call security_inet_conn_request() after setting IPv6 addresses.
+    - Fix termination state for idr_for_each_entry_ul()
+    - net: stmmac: xgmac: Enable support for multiple Flexible PPS outputs
+    - net/smc: fix dangling sock under state SMC_APPFINCLOSEWAIT
+    - tg3: power down device only on SYSTEM_POWER_OFF
+    - r8169: respect userspace disabling IFF_MULTICAST
+    - netfilter: xt_recent: fix (increase) ipv6 literal buffer length
+    - netfilter: nft_redir: use `struct nf_nat_range2` throughout and deduplicate
+      eval call-backs
+    - netfilter: nat: fix ipv6 nat redirect with mapped and scoped addresses
+    - drm/syncobj: fix DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE
+    - spi: spi-zynq-qspi: add spi-mem to driver kconfig dependencies
+    - fbdev: imsttfb: Fix error path of imsttfb_probe()
+    - fbdev: imsttfb: fix a resource leak in probe
+    - fbdev: fsl-diu-fb: mark wr_reg_wa() static
+    - Revert "mmc: core: Capture correct oemid-bits for eMMC cards"
+    - btrfs: use u64 for buffer sizes in the tree search ioctls
+    - Linux 5.4.261
+
+  * Focal update: v5.4.260 upstream stable release (LP: #2049024)
+    - mtd: rawnand: marvell: Ensure program page operations are successful
+    - selftests/ftrace: Add new test case which checks non unique symbol
+    - mcb: Return actual parsed size when reading chameleon table
+    - mcb-lpc: Reallocate memory region to avoid memory overlapping
+    - virtio_balloon: Fix endless deflation and inflation on arm64
+    - virtio-mmio: fix memory leak of vm_dev
+    - r8169: fix the KCSAN reported data-race in rtl_tx while reading
+      TxDescArray[entry].opts1
+    - r8169: fix the KCSAN reported data race in rtl_rx while reading desc->opts1
+    - treewide: Spelling fix in comment
+    - igb: Fix potential memory leak in igb_add_ethtool_nfc_entry
+    - neighbour: fix various data-races
+    - igc: Fix ambiguity in the ethtool advertising
+    - net: ieee802154: adf7242: Fix some potential buffer overflow in
+      adf7242_stats_show()
+    - r8152: Increase USB control msg timeout to 5000ms as per spec
+    - r8152: Run the unload routine if we have errors during probe
+    - r8152: Cancel hw_phy_work if we have an error in probe
+    - tcp: fix wrong RTO timeout when received SACK reneging
+    - gtp: uapi: fix GTPA_MAX
+    - gtp: fix fragmentation needed check with gso
+    - iio: exynos-adc: request second interupt only when touchscreen mode is used
+    - i2c: muxes: i2c-mux-pinctrl: Use of_get_i2c_adapter_by_node()
+    - i2c: muxes: i2c-mux-gpmux: Use of_get_i2c_adapter_by_node()
+    - i2c: muxes: i2c-demux-pinctrl: Use of_get_i2c_adapter_by_node()
+    - i2c: stm32f7: Fix PEC handling in case of SMBUS transfers
+    - i2c: aspeed: Fix i2c bus hang in slave read
+    - nvmem: imx: correct nregs for i.MX6ULL
+    - nvmem: imx: correct nregs for i.MX6SLL
+    - nvmem: imx: correct nregs for i.MX6UL
+    - perf/core: Fix potential NULL deref
+    - clk: Sanitize possible_parent_show to Handle Return Value of
+      of_clk_get_parent_name
+    - i40e: Fix wrong check for I40E_TXR_FLAGS_WB_ON_ITR
+    - x86/i8259: Skip probing when ACPI/MADT advertises PCAT compatibility
+    - drm/dp_mst: Fix NULL deref in get_mst_branch_device_by_guid_helper()
+    - arm64: fix a concurrency issue in emulation_proc_handler()
+    - smbdirect: missing rc checks while waiting for rdma events
+    - f2fs: fix to do sanity check on inode type during garbage collection
+    - nfsd: lock_rename() needs both directories to live on the same fs
+    - x86/mm: Simplify RESERVE_BRK()
+    - x86/mm: Fix RESERVE_BRK() for older binutils
+    - ext4: add two helper functions extent_logical_end() and pa_logical_end()
+    - ext4: avoid overlapping preallocations due to overflow
+    - ext4: fix BUG in ext4_mb_new_inode_pa() due to overflow
+    - driver: platform: Add helper for safer setting of driver_override
+    - rpmsg: Constify local variable in field store macro
+    - rpmsg: Fix kfree() of static memory on setting driver_override
+    - rpmsg: Fix calling device_lock() on non-initialized device
+    - rpmsg: glink: Release driver_override
+    - rpmsg: Fix possible refcount leak in rpmsg_register_device_override()
+    - x86: Fix .brk attribute in linker script
+    - Input: i8042 - add Fujitsu Lifebook E5411 to i8042 quirk table
+    - irqchip/stm32-exti: add missing DT IRQ flag translation
+    - dmaengine: ste_dma40: Fix PM disable depth imbalance in d40_probe
+    - Input: synaptics-rmi4 - handle reset delay when using SMBus trsnsport
+    - fbdev: atyfb: only use ioremap_uc() on i386 and ia64
+    - spi: npcm-fiu: Fix UMA reads when dummy.nbytes == 0
+    - netfilter: nfnetlink_log: silence bogus compiler warning
+    - ASoC: rt5650: fix the wrong result of key button
+    - fbdev: uvesafb: Call cn_del_callback() at the end of uvesafb_exit()
+    - scsi: mpt3sas: Fix in error path
+    - platform/x86: asus-wmi: Change ASUS_WMI_BRN_DOWN code from 0x20 to 0x2e
+    - platform/mellanox: mlxbf-tmfifo: Fix a warning message
+    - net: chelsio: cxgb4: add an error code check in t4_load_phy_fw
+    - ata: ahci: fix enum constants for gcc-13
+    - remove the sx8 block driver
+    - [Config] remove CONFIG_BLK_DEV_SX8
+    - Revert "ARM: dts: Move am33xx and am43xx mmc nodes to sdhci-omap driver"
+    - PCI: Prevent xHCI driver from claiming AMD VanGogh USB3 DRD device
+    - usb: storage: set 1.50 as the lower bcdDevice for older "Super Top"
+      compatibility
+    - tty: 8250: Remove UC-257 and UC-431
+    - tty: 8250: Add support for additional Brainboxes UC cards
+    - tty: 8250: Add support for Brainboxes UP cards
+    - tty: 8250: Add support for Intashield IS-100
+    - Linux 5.4.260
+
+  * CVE-2023-51779
+    - Bluetooth: af_bluetooth: Fix Use-After-Free in bt_sock_recvmsg
+
+  * CVE-2023-22995
+    - usb: dwc3: dwc3-qcom: Add missing platform_device_put() in
+      dwc3_qcom_acpi_register_core
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Fri, 02 Feb 2024 14:22:27 +0100
+
+linux (5.4.0-171.189) focal; urgency=medium
+
+  * focal/linux: 5.4.0-171.189 -proposed tracker (LP: #2048282)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] remove helper scripts
+    - [Packaging] update annotations scripts
+    - debian/dkms-versions -- update from kernel-versions (main/2024.01.08)
+
+  * Page fault in RDMA ODP triggers BUG_ON during MMU notifier registration
+    (LP: #2046534)
+    - RDMA/odp: Ensure the mm is still alive before creating an implicit child
+
+  * Hotplugging SCSI disk in QEMU VM fails (LP: #2047382)
+    - Revert "PCI: acpiphp: Reassign resources on bridge if necessary"
+
+  * CVE-2023-6040
+    - netfilter: nf_tables: Reject tables of unsupported family
+
+  * kernel_selftests failures on kernel-P10d-LPAR10.ppc64el.10
+    (LP: #2032641)
+    - selftests: Skip TM tests on synthetic TM implementations
+
+  * [Debian] autoreconstruct - Do not generate chmod -x for deleted  files
+    (LP: #2045562)
+    - [Debian] autoreconstruct - Do not generate chmod -x for deleted files
+
+  * CVE-2023-6931
+    - perf/core: Add a new read format to get a number of lost samples
+    - perf: Fix perf_event_validate_size()
+    - perf: Fix perf_event_validate_size() lockdep splat
+
+  * CVE-2023-6932
+    - ipv4: igmp: fix refcnt uaf issue when receiving igmp query packet
+
+  * CVE-2023-6606
+    - smb: client: fix OOB in smbCalcSize()
+
+  * CVE-2023-45863
+    - kobject: Fix slab-out-of-bounds in fill_kobj_path()
+
+  * Focal update: v5.4.259 upstream stable release (LP: #2043724)
+    - RDMA/cxgb4: Check skb value for failure to allocate
+    - lib/test_meminit: fix off-by-one error in test_pages()
+    - pwm: hibvt: Explicitly set .polarity in .get_state()
+    - HID: logitech-hidpp: Fix kernel crash on receiver USB disconnect
+    - quota: Fix slow quotaoff
+    - net: prevent address rewrite in kernel_bind()
+    - drm: etvnaviv: fix bad backport leading to warning
+    - drm/msm/dsi: skip the wait for video mode done if not applicable
+    - ravb: Fix up dma_free_coherent() call in ravb_remove()
+    - ieee802154: ca8210: Fix a potential UAF in ca8210_probe
+    - mlxsw: fix mlxsw_sp2_nve_vxlan_learning_set() return type
+    - xen-netback: use default TX queue size for vifs
+    - drm/vmwgfx: fix typo of sizeof argument
+    - ixgbe: fix crash with empty VF macvlan list
+    - net: nfc: fix races in nfc_llcp_sock_get() and nfc_llcp_sock_get_sn()
+    - nfc: nci: assert requested protocol is valid
+    - workqueue: Override implicit ordered attribute in
+      workqueue_apply_unbound_cpumask()
+    - dmaengine: stm32-mdma: abort resume if no ongoing transfer
+    - usb: xhci: xhci-ring: Use sysdev for mapping bounce buffer
+    - net: usb: dm9601: fix uninitialized variable use in dm9601_mdio_read
+    - usb: dwc3: Soft reset phy on probe for host
+    - usb: musb: Get the musb_qh poniter after musb_giveback
+    - usb: musb: Modify the "HWVers" register address
+    - iio: pressure: bmp280: Fix NULL pointer exception
+    - iio: pressure: dps310: Adjust Timeout Settings
+    - iio: pressure: ms5611: ms5611_prom_is_valid false negative bug
+    - mcb: remove is_added flag from mcb_device struct
+    - libceph: use kernel_connect()
+    - ceph: fix incorrect revoked caps assert in ceph_fill_file_size()
+    - Input: powermate - fix use-after-free in powermate_config_complete
+    - Input: psmouse - fix fast_reconnect function for PS/2 mode
+    - Input: xpad - add PXN V900 support
+    - cgroup: Remove duplicates in cgroup v1 tasks file
+    - pinctrl: avoid unsafe code pattern in find_pinctrl()
+    - usb: gadget: udc-xilinx: replace memcpy with memcpy_toio
+    - usb: gadget: ncm: Handle decoding of multiple NTB's in unwrap call
+    - x86/cpu: Fix AMD erratum #1485 on Zen4-based CPUs
+    - dmaengine: mediatek: Fix deadlock caused by synchronize_irq()
+    - powerpc/8xx: Fix pte_access_permitted() for PAGE_NONE
+    - powerpc/64e: Fix wrong test in __ptep_test_and_clear_young()
+    - ravb: Fix use-after-free issue in ravb_tx_timeout_work()
+    - Documentation: sysctl: align cells in second content column
+    - usb: hub: Guard against accesses to uninitialized BOS descriptors
+    - Bluetooth: hci_event: Ignore NULL link key
+    - Bluetooth: Reject connection with the device which has same BD_ADDR
+    - Bluetooth: Fix a refcnt underflow problem for hci_conn
+    - Bluetooth: vhci: Fix race when opening vhci device
+    - Bluetooth: hci_event: Fix coding style
+    - Bluetooth: avoid memcmp() out of bounds warning
+    - ice: fix over-shifted variable
+    - nfc: nci: fix possible NULL pointer dereference in send_acknowledge()
+    - regmap: fix NULL deref on lookup
+    - KVM: x86: Mask LVTPC when handling a PMI
+    - netfilter: nft_payload: fix wrong mac header matching
+    - qed: fix LL2 RX buffer allocation
+    - xfrm: fix a data-race in xfrm_gen_index()
+    - xfrm: interface: use DEV_STATS_INC()
+    - net: ipv4: fix return value check in esp_remove_trailer
+    - net: ipv6: fix return value check in esp_remove_trailer
+    - net: rfkill: gpio: prevent value glitch during probe
+    - tcp: fix excessive TLP and RACK timeouts from HZ rounding
+    - tcp: tsq: relax tcp_small_queue_check() when rtx queue contains a single skb
+    - tun: prevent negative ifindex
+    - ipv4: fib: annotate races around nh->nh_saddr_genid and nh->nh_saddr
+    - net: usb: smsc95xx: Fix an error code in smsc95xx_reset()
+    - i40e: prevent crash on probe if hw registers have invalid values
+    - net/sched: sch_hfsc: upgrade 'rt' to 'sc' when it becomes a inner curve
+    - neighbor: tracing: Move pin6 inside CONFIG_IPV6=y section
+    - netfilter: nft_set_rbtree: .deactivate fails if element has expired
+    - net: pktgen: Fix interface flags printing
+    - resource: Add irqresource_disabled()
+    - ACPI: Drop acpi_dev_irqresource_disabled()
+    - ACPI: resource: Skip IRQ override on Asus Vivobook S5602ZA
+    - ACPI: resource: Add Asus ExpertBook B2502 to Asus quirks
+    - ACPI: resource: Skip IRQ override on Asus Expertbook B2402CBA
+    - ACPI: resource: Skip IRQ override on ASUS ExpertBook B1502CBA
+    - ACPI: resource: Skip IRQ override on ASUS ExpertBook B1402CBA
+    - ARM: dts: ti: omap: Fix noisy serial with overrun-throttle-ms for mapphone
+    - btrfs: return -EUCLEAN for delayed tree ref with a ref count not equals to 1
+    - btrfs: initialize start_slot in btrfs_log_prealloc_extents
+    - i2c: mux: Avoid potential false error message in i2c_mux_add_adapter
+    - overlayfs: set ctime when setting mtime and atime
+    - gpio: timberdale: Fix potential deadlock on &tgpio->lock
+    - ata: libata-eh: Fix compilation warning in ata_eh_link_report()
+    - tracing: relax trace_event_eval_update() execution with cond_resched()
+    - HID: holtek: fix slab-out-of-bounds Write in holtek_kbd_input_event
+    - Bluetooth: Avoid redundant authentication
+    - Bluetooth: hci_core: Fix build warnings
+    - wifi: mac80211: allow transmitting EAPOL frames with tainted key
+    - wifi: cfg80211: avoid leaking stack data into trace
+    - regulator/core: Revert "fix kobject release warning and memory leak in
+      regulator_register()"
+    - sky2: Make sure there is at least one frag_addr available
+    - drm: panel-orientation-quirks: Add quirk for One Mix 2S
+    - btrfs: fix some -Wmaybe-uninitialized warnings in ioctl.c
+    - HID: multitouch: Add required quirk for Synaptics 0xcd7e device
+    - Bluetooth: hci_event: Fix using memcmp when comparing keys
+    - mtd: rawnand: qcom: Unmap the right resource upon probe failure
+    - mtd: spinand: micron: correct bitmask for ecc status
+    - mtd: physmap-core: Restore map_rom fallback
+    - mmc: core: sdio: hold retuning if sdio in 1-bit mode
+    - mmc: core: Capture correct oemid-bits for eMMC cards
+    - Revert "pinctrl: avoid unsafe code pattern in find_pinctrl()"
+    - ACPI: irq: Fix incorrect return value in acpi_register_gsi()
+    - USB: serial: option: add Telit LE910C4-WWX 0x1035 composition
+    - USB: serial: option: add entry for Sierra EM9191 with new firmware
+    - USB: serial: option: add Fibocom to DELL custom modem FM101R-GL
+    - s390/pci: fix iommu bitmap allocation
+    - gpio: vf610: set value before the direction to avoid a glitch
+    - ASoC: pxa: fix a memory leak in probe()
+    - phy: mapphone-mdm6600: Fix runtime disable on probe
+    - phy: mapphone-mdm6600: Fix runtime PM for remove
+    - phy: mapphone-mdm6600: Fix pinctrl_pm handling for sleep pins
+    - Bluetooth: hci_sock: fix slab oob read in create_monitor_event
+    - Bluetooth: hci_sock: Correctly bounds check and pad HCI_MON_NEW_INDEX name
+    - xfrm6: fix inet6_dev refcount underflow problem
+    - Linux 5.4.259
+
+  * Focal update: v5.4.258 upstream stable release (LP: #2042107)
+    - NFS/pNFS: Report EINVAL errors from connect() to the server
+    - SUNRPC: Mark the cred for revalidation if the server rejects it
+    - tracing: Increase trace array ref count on enable and filter files
+    - ata: libahci: clear pending interrupt status
+    - ext4: remove the 'group' parameter of ext4_trim_extent
+    - ext4: add new helper interface ext4_try_to_trim_range()
+    - ext4: scope ret locally in ext4_try_to_trim_range()
+    - ext4: change s_last_trim_minblks type to unsigned long
+    - ext4: mark group as trimmed only if it was fully scanned
+    - ext4: replace the traditional ternary conditional operator with with
+      max()/min()
+    - ext4: move setting of trimmed bit into ext4_try_to_trim_range()
+    - ext4: do not let fstrim block system suspend
+    - ASoC: meson: spdifin: start hw on dai probe
+    - netfilter: nf_tables: disallow element removal on anonymous sets
+    - bpf: Avoid deadlock when using queue and stack maps from NMI
+    - selftests/tls: Add {} to avoid static checker warning
+    - selftests: tls: swap the TX and RX sockets in some tests
+    - ASoC: imx-audmix: Fix return error with devm_clk_get()
+    - i40e: Fix for persistent lldp support
+    - SAUCE: Revert "UBUNTU: SAUCE: i40e Fix GPF when deleting VMs"
+    - i40e: Remove scheduling while atomic possibility
+    - i40e: Fix warning message and call stack during rmmod i40e driver
+    - i40e: Fix VF VLAN offloading when port VLAN is configured
+    - powerpc/perf/hv-24x7: Update domain value check
+    - dccp: fix dccp_v4_err()/dccp_v6_err() again
+    - net: hns3: add 5ms delay before clear firmware reset irq source
+    - net: bridge: use DEV_STATS_INC()
+    - team: fix null-ptr-deref when team device type is changed
+    - net: rds: Fix possible NULL-pointer dereference
+    - gpio: tb10x: Fix an error handling path in tb10x_gpio_probe()
+    - i2c: mux: demux-pinctrl: check the return value of devm_kstrdup()
+    - Input: i8042 - add quirk for TUXEDO Gemini 17 Gen1/Clevo PD70PN
+    - scsi: qla2xxx: Fix update_fcport for current_topology
+    - scsi: qla2xxx: Fix deletion race condition
+    - drm/amd/display: Reinstate LFC optimization
+    - drm/amd/display: Fix LFC multiplier changing erratically
+    - drm/amd/display: prevent potential division by zero errors
+    - ata: libata: disallow dev-initiated LPM transitions to unsupported states
+    - MIPS: Alchemy: only build mmc support helpers if au1xmmc is enabled
+    - clk: tegra: fix error return case for recalc_rate
+    - ARM: dts: ti: omap: motorola-mapphone: Fix abe_clkctrl warning on boot
+    - bus: ti-sysc: Fix SYSC_QUIRK_SWSUP_SIDLE_ACT handling for uart wake-up
+    - xtensa: add default definition for XCHAL_HAVE_DIV32
+    - xtensa: iss/network: make functions static
+    - xtensa: boot: don't add include-dirs
+    - xtensa: boot/lib: fix function prototypes
+    - gpio: pmic-eic-sprd: Add can_sleep flag for PMIC EIC chip
+    - parisc: sba: Fix compile warning wrt list of SBA devices
+    - parisc: iosapic.c: Fix sparse warnings
+    - parisc: drivers: Fix sparse warning
+    - parisc: irq: Make irq_stack_union static to avoid sparse warning
+    - selftests/ftrace: Correctly enable event in instance-event.tc
+    - ring-buffer: Avoid softlockup in ring_buffer_resize()
+    - ata: libata-eh: do not clear ATA_PFLAG_EH_PENDING in ata_eh_reset()
+    - spi: nxp-fspi: reset the FLSHxCR1 registers
+    - bpf: Clarify error expectations from bpf_clone_redirect
+    - powerpc/watchpoints: Annotate atomic context in more places
+    - ncsi: Propagate carrier gain/loss events to the NCSI controller
+    - fbdev/sh7760fb: Depend on FB=y
+    - nvme-pci: do not set the NUMA node of device if it has none
+    - watchdog: iTCO_wdt: No need to stop the timer in probe
+    - watchdog: iTCO_wdt: Set NO_REBOOT if the watchdog is not already running
+    - i40e: improve locking of mac_filter_hash
+    - i40e: always propagate error value in i40e_set_vsi_promisc()
+    - i40e: fix return of uninitialized aq_ret in i40e_set_vsi_promisc
+    - smack: Record transmuting in smk_transmuted
+    - smack: Retrieve transmuting information in smack_inode_getsecurity()
+    - Smack:- Use overlay inode label in smack_inode_copy_up()
+    - serial: 8250_port: Check IRQ data before use
+    - nilfs2: fix potential use after free in nilfs_gccache_submit_read_data()
+    - ALSA: hda: Disable power save for solving pop issue on Lenovo ThinkCentre
+      M70q
+    - ata: libata-scsi: ignore reserved bits for REPORT SUPPORTED OPERATION CODES
+    - i2c: i801: unregister tco_pdev in i801_probe() error path
+    - ring-buffer: Update "shortest_full" in polling
+    - btrfs: properly report 0 avail for very full file systems
+    - net: thunderbolt: Fix TCPv6 GSO checksum calculation
+    - ata: libata-core: Fix ata_port_request_pm() locking
+    - ata: libata-core: Fix port and device removal
+    - ata: libata-core: Do not register PM operations for SAS ports
+    - ata: libata-sata: increase PMP SRST timeout to 10s
+    - fs: binfmt_elf_efpic: fix personality for ELF-FDPIC
+    - rbd: move rbd_dev_refresh() definition
+    - rbd: decouple header read-in from updating rbd_dev->header
+    - rbd: decouple parent info read-in from updating rbd_dev
+    - rbd: take header_rwsem in rbd_dev_refresh() only when updating
+    - Revert "PCI: qcom: Disable write access to read only registers for IP
+      v2.3.3"
+    - scsi: zfcp: Fix a double put in zfcp_port_enqueue()
+    - qed/red_ll2: Fix undefined behavior bug in struct qed_ll2_info
+    - wifi: mwifiex: Fix tlv_buf_left calculation
+    - net: replace calls to sock->ops->connect() with kernel_connect()
+    - net: prevent rewrite of msg_name in sock_sendmsg()
+    - wifi: iwlwifi: dbg_ini: fix structure packing
+    - wifi: mwifiex: Fix oob check condition in mwifiex_process_rx_packet
+    - drivers/net: process the result of hdlc_open() and add call of hdlc_close()
+      in uhdlc_close()
+    - wifi: mt76: mt76x02: fix MT76x0 external LNA gain handling
+    - regmap: rbtree: Fix wrong register marked as in-cache when creating new node
+    - ima: Finish deprecation of IMA_TRUSTED_KEYRING Kconfig
+    - scsi: target: core: Fix deadlock due to recursive locking
+    - NFS4: Trace state recovery operation
+    - NFS: Add a helper nfs_client_for_each_server()
+    - NFSv4: Fix a nfs4_state_manager() race
+    - modpost: add missing else to the "of" check
+    - net: fix possible store tearing in neigh_periodic_work()
+    - ipv4, ipv6: Fix handling of transhdrlen in __ip{,6}_append_data()
+    - net: dsa: mv88e6xxx: Avoid EEPROM timeout when EEPROM is absent
+    - net: usb: smsc75xx: Fix uninit-value access in __smsc75xx_read_reg
+    - net: nfc: llcp: Add lock when modifying device list
+    - netfilter: handle the connecting collision properly in
+      nf_conntrack_proto_sctp
+    - net: stmmac: dwmac-stm32: fix resume on STM32 MCU
+    - tcp: fix quick-ack counting to count actual ACKs of new data
+    - tcp: fix delayed ACKs for MSS boundary condition
+    - sctp: update transport state when processing a dupcook packet
+    - sctp: update hb timer immediately after users change hb_interval
+    - cpupower: add Makefile dependencies for install targets
+    - RDMA/core: Require admin capabilities to set system parameters
+    - IB/mlx4: Fix the size of a buffer in add_port_entries()
+    - gpio: aspeed: fix the GPIO number passed to pinctrl_gpio_set_config()
+    - gpio: pxa: disable pinctrl calls for MMP_GPIO
+    - RDMA/cma: Fix truncation compilation warning in make_cma_ports
+    - RDMA/uverbs: Fix typo of sizeof argument
+    - RDMA/siw: Fix connection failure handling
+    - RDMA/mlx5: Fix NULL string error
+    - parisc: Restore __ldcw_align for PA-RISC 2.0 processors
+    - NFS: Fix a race in __nfs_list_for_each_server()
+    - ima: rework CONFIG_IMA dependency block
+    - [Config] Update IMA_BLACKLIST_KEYRING and IMA_LOAD_X509
+    - xen/events: replace evtchn_rwlock with RCU
+    - Linux 5.4.258
+
+ -- Roxana Nicolescu <roxana.nicolescu@canonical.com>  Fri, 05 Jan 2024 14:59:41 +0100
+
+linux (5.4.0-169.187) focal; urgency=medium
+
+  * focal/linux: 5.4.0-169.187 -proposed tracker (LP: #2044375)
+
+  * USB bus error after upgrading to proposed kernel on lunar, jammy and focal
+    (LP: #2043197)
+    - USB: core: Fix oversight in SuperSpeed initialization
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync git-ubuntu-log
+    - [Packaging] resync update-dkms-versions helper
+    - [Packaging] update annotations scripts
+
+ -- Roxana Nicolescu <roxana.nicolescu@canonical.com>  Thu, 23 Nov 2023 14:04:39 +0100
+
+linux (5.4.0-168.186) focal; urgency=medium
+
+  * focal/linux: 5.4.0-168.186 -proposed tracker (LP: #2041652)
+
+  * Focal update: v5.4.257 upstream stable release (LP: #2040284)
+    - erofs: ensure that the post-EOF tails are all zeroed
+    - ARM: pxa: remove use of symbol_get()
+    - mmc: au1xmmc: force non-modular build and remove symbol_get usage
+    - net: enetc: use EXPORT_SYMBOL_GPL for enetc_phc_index
+    - rtc: ds1685: use EXPORT_SYMBOL_GPL for ds1685_rtc_poweroff
+    - modules: only allow symbol_get of EXPORT_SYMBOL_GPL modules
+    - USB: serial: option: add Quectel EM05G variant (0x030e)
+    - USB: serial: option: add FOXCONN T99W368/T99W373 product
+    - HID: wacom: remove the battery when the EKR is off
+    - staging: rtl8712: fix race condition
+    - Bluetooth: btsdio: fix use after free bug in btsdio_remove due to race
+      condition
+    - serial: sc16is7xx: fix bug when first setting GPIO direction
+    - firmware: stratix10-svc: Fix an NULL vs IS_ERR() bug in probe
+    - fsi: master-ast-cf: Add MODULE_FIRMWARE macro
+    - nilfs2: fix general protection fault in nilfs_lookup_dirty_data_buffers()
+    - nilfs2: fix WARNING in mark_buffer_dirty due to discarded buffer reuse
+    - pinctrl: amd: Don't show `Invalid config param` errors
+    - 9p: virtio: make sure 'offs' is initialized in zc_request
+    - ASoC: da7219: Flush pending AAD IRQ when suspending
+    - ASoC: da7219: Check for failure reading AAD IRQ events
+    - ethernet: atheros: fix return value check in atl1c_tso_csum()
+    - vxlan: generalize vxlan_parse_gpe_hdr and remove unused args
+    - m68k: Fix invalid .section syntax
+    - s390/dasd: use correct number of retries for ERP requests
+    - s390/dasd: fix hanging device after request requeue
+    - fs/nls: make load_nls() take a const parameter
+    - ASoc: codecs: ES8316: Fix DMIC config
+    - ASoC: atmel: Fix the 8K sample parameter in I2SC master
+    - platform/x86: intel: hid: Always call BTNL ACPI method
+    - platform/x86: huawei-wmi: Silence ambient light sensor
+    - security: keys: perform capable check only on privileged operations
+    - clk: fixed-mmio: make COMMON_CLK_FIXED_MMIO depend on HAS_IOMEM
+    - net: usb: qmi_wwan: add Quectel EM05GV2
+    - idmaengine: make FSL_EDMA and INTEL_IDMA64 depends on HAS_IOMEM
+    - scsi: qedi: Fix potential deadlock on &qedi_percpu->p_work_lock
+    - netlabel: fix shift wrapping bug in netlbl_catmap_setlong()
+    - bnx2x: fix page fault following EEH recovery
+    - sctp: handle invalid error codes without calling BUG()
+    - cifs: add a warning when the in-flight count goes negative
+    - scsi: storvsc: Always set no_report_opcodes
+    - ALSA: seq: oss: Fix racy open/close of MIDI devices
+    - platform/mellanox: Fix mlxbf-tmfifo not handling all virtio CONSOLE
+      notifications
+    - powerpc/32s: Fix assembler warning about r0
+    - udf: Check consistency of Space Bitmap Descriptor
+    - udf: Handle error when adding extent to a file
+    - Revert "net: macsec: preserve ingress frame ordering"
+    - reiserfs: Check the return value from __getblk()
+    - eventfd: Export eventfd_ctx_do_read()
+    - eventfd: prevent underflow for eventfd semaphores
+    - new helper: lookup_positive_unlocked()
+    - fs: Fix error checking for d_hash_and_lookup()
+    - tmpfs: verify {g,u}id mount options correctly
+    - OPP: Fix passing 0 to PTR_ERR in _opp_attach_genpd()
+    - x86/asm: Make more symbols local
+    - x86/boot: Annotate local functions
+    - x86/decompressor: Don't rely on upper 32 bits of GPRs being preserved
+    - perf/imx_ddr: don't enable counter0 if none of 4 counters are used
+    - cpufreq: powernow-k8: Use related_cpus instead of cpus in driver.exit()
+    - bpf: Clear the probe_addr for uprobe
+    - tcp: tcp_enter_quickack_mode() should be static
+    - regmap: rbtree: Use alloc_flags for memory allocations
+    - spi: tegra20-sflash: fix to check return value of platform_get_irq() in
+      tegra_sflash_probe()
+    - can: gs_usb: gs_usb_receive_bulk_callback(): count RX overflow errors also
+      in case of OOM
+    - wifi: mwifiex: Fix OOB and integer underflow when rx packets
+    - mwifiex: switch from 'pci_' to 'dma_' API
+    - wifi: mwifiex: fix error recovery in PCIE buffer descriptor management
+    - crypto: stm32 - Properly handle pm_runtime_get failing
+    - Bluetooth: nokia: fix value check in nokia_bluetooth_serdev_probe()
+    - crypto: caam - fix unchecked return value error
+    - hwrng: iproc-rng200 - use semicolons rather than commas to separate
+      statements
+    - hwrng: iproc-rng200 - Implement suspend and resume calls
+    - lwt: Fix return values of BPF xmit ops
+    - lwt: Check LWTUNNEL_XMIT_CONTINUE strictly
+    - fs: ocfs2: namei: check return value of ocfs2_add_entry()
+    - wifi: mwifiex: fix memory leak in mwifiex_histogram_read()
+    - wifi: mwifiex: Fix missed return in oob checks failed path
+    - wifi: ath9k: fix races between ath9k_wmi_cmd and ath9k_wmi_ctrl_rx
+    - wifi: ath9k: protect WMI command response buffer replacement with a lock
+    - wifi: mwifiex: avoid possible NULL skb pointer dereference
+    - wifi: ath9k: use IS_ERR() with debugfs_create_dir()
+    - net: arcnet: Do not call kfree_skb() under local_irq_disable()
+    - mlxsw: i2c: Fix chunk size setting in output mailbox buffer
+    - mlxsw: i2c: Limit single transaction buffer size
+    - netrom: Deny concurrent connect().
+    - drm/bridge: tc358764: Fix debug print parameter order
+    - quota: avoid increasing DQST_LOOKUPS when iterating over dirty/inuse list
+    - quota: factor out dquot_write_dquot()
+    - quota: rename dquot_active() to inode_quota_active()
+    - quota: add new helper dquot_active()
+    - quota: fix dqput() to follow the guarantees dquot_srcu should provide
+    - drm/amdgpu: avoid integer overflow warning in amdgpu_device_resize_fb_bar()
+    - ARM: dts: BCM53573: Drop nonexistent "default-off" LED trigger
+    - ARM: dts: BCM53573: Add cells sizes to PCIe node
+    - ARM: dts: BCM53573: Use updated "spi-gpio" binding properties
+    - drm/etnaviv: fix dumping of active MMU context
+    - ARM: dts: s3c6410: move fixed clocks under root node in Mini6410
+    - ARM: dts: s3c6410: align node SROM bus node name with dtschema in Mini6410
+    - ARM: dts: s3c64xx: align pinctrl with dtschema
+    - ARM: dts: samsung: s3c6410-mini6410: correct ethernet reg addresses (split)
+    - ARM: dts: s5pv210: add RTC 32 KHz clock in SMDKV210
+    - ARM: dts: s5pv210: use defines for IRQ flags in SMDKV210
+    - ARM: dts: s5pv210: correct ethernet unit address in SMDKV210
+    - ARM: dts: s5pv210: add dummy 5V regulator for backlight on SMDKv210
+    - ARM: dts: samsung: s5pv210-smdkv210: correct ethernet reg addresses (split)
+    - drm: adv7511: Fix low refresh rate register for ADV7533/5
+    - ARM: dts: BCM53573: Fix Ethernet info for Luxul devices
+    - arm64: dts: qcom: sdm845: Add missing RPMh power domain to GCC
+    - drm/amdgpu: Update min() to min_t() in 'amdgpu_info_ioctl'
+    - md/bitmap: don't set max_write_behind if there is no write mostly device
+    - md/md-bitmap: hold 'reconfig_mutex' in backlog_store()
+    - drm/tegra: Remove superfluous error messages around platform_get_irq()
+    - drm/tegra: dpaux: Fix incorrect return value of platform_get_irq
+    - of: unittest: fix null pointer dereferencing in
+      of_unittest_find_node_by_name()
+    - drm/armada: Fix off-by-one error in armada_overlay_get_property()
+    - drm/panel: simple: Add missing connector type and pixel format for AUO
+      T215HVN01
+    - ima: Remove deprecated IMA_TRUSTED_KEYRING Kconfig
+    - [Config] Update annotations after CONFIG_IMA_TRUSTED_KEYRING removal
+    - drm/msm/mdp5: Don't leak some plane state
+    - smackfs: Prevent underflow in smk_set_cipso()
+    - audit: fix possible soft lockup in __audit_inode_child()
+    - drm/mediatek: Fix potential memory leak if vmap() fail
+    - of: unittest: Fix overlay type in apply/revert check
+    - ALSA: ac97: Fix possible error value of *rac97
+    - ipmi:ssif: Add check for kstrdup
+    - ipmi:ssif: Fix a memory leak when scanning for an adapter
+    - drivers: clk: keystone: Fix parameter judgment in _of_pll_clk_init()
+    - clk: sunxi-ng: Modify mismatched function name
+    - PCI: Mark NVIDIA T4 GPUs to avoid bus reset
+    - PCI: pciehp: Use RMW accessors for changing LNKCTL
+    - PCI/ASPM: Use RMW accessors for changing LNKCTL
+    - clk: imx: composite-8m: fix clock pauses when set_rate would be a no-op
+    - powerpc/fadump: reset dump area size if fadump memory reserve fails
+    - PCI: Add #defines for Enter Compliance, Transmit Margin
+    - drm/amdgpu: Correct Transmit Margin masks
+    - drm/amdgpu: Replace numbers with PCI_EXP_LNKCTL2 definitions
+    - drm/amdgpu: Prefer pcie_capability_read_word()
+    - drm/amdgpu: Use RMW accessors for changing LNKCTL
+    - drm/radeon: Correct Transmit Margin masks
+    - drm/radeon: Replace numbers with PCI_EXP_LNKCTL2 definitions
+    - drm/radeon: Prefer pcie_capability_read_word()
+    - drm/radeon: Use RMW accessors for changing LNKCTL
+    - wifi: ath10k: Use RMW accessors for changing LNKCTL
+    - nfs/blocklayout: Use the passed in gfp flags
+    - powerpc/iommu: Fix notifiers being shared by PCI and VIO buses
+    - jfs: validate max amount of blocks before allocation.
+    - fs: lockd: avoid possible wrong NULL parameter
+    - NFSD: da_addr_body field missing in some GETDEVICEINFO replies
+    - NFS: Guard against READDIR loop when entry names exceed MAXNAMELEN
+    - media: v4l2-fwnode: fix v4l2_fwnode_parse_link handling
+    - media: v4l2-fwnode: simplify v4l2_fwnode_parse_link
+    - media: v4l2-core: Fix a potential resource leak in v4l2_fwnode_parse_link()
+    - drivers: usb: smsusb: fix error handling code in smsusb_init_device
+    - media: dib7000p: Fix potential division by zero
+    - media: dvb-usb: m920x: Fix a potential memory leak in m920x_i2c_xfer()
+    - media: cx24120: Add retval check for cx24120_message_send()
+    - media: mediatek: vcodec: Return NULL if no vdec_fb is found
+    - usb: phy: mxs: fix getting wrong state with mxs_phy_is_otg_host()
+    - scsi: iscsi: Add strlen() check in iscsi_if_set{_host}_param()
+    - scsi: be2iscsi: Add length check when parsing nlattrs
+    - scsi: qla4xxx: Add length check when parsing nlattrs
+    - serial: sprd: getting port index via serial aliases only
+    - serial: sprd: remove redundant sprd_port cleanup
+    - serial: sprd: Assign sprd_port after initialized to avoid wrong access
+    - serial: sprd: Fix DMA buffer leak issue
+    - x86/APM: drop the duplicate APM_MINOR_DEV macro
+    - scsi: qedf: Do not touch __user pointer in
+      qedf_dbg_stop_io_on_error_cmd_read() directly
+    - scsi: qedf: Do not touch __user pointer in qedf_dbg_debug_cmd_read()
+      directly
+    - scsi: qedf: Do not touch __user pointer in qedf_dbg_fp_int_cmd_read()
+      directly
+    - coresight: tmc: Explicit type conversions to prevent integer overflow
+    - dma-buf/sync_file: Fix docs syntax
+    - driver core: test_async: fix an error code
+    - IB/uverbs: Fix an potential error pointer dereference
+    - iommu/vt-d: Fix to flush cache of PASID directory table
+    - media: go7007: Remove redundant if statement
+    - USB: gadget: f_mass_storage: Fix unused variable warning
+    - media: i2c: ov5640: Configure HVP lines in s_power callback
+    - media: ov5640: Enable MIPI interface in ov5640_set_power_mipi()
+    - media: i2c: ov2680: Set V4L2_CTRL_FLAG_MODIFY_LAYOUT on flips
+    - media: ov2680: Remove auto-gain and auto-exposure controls
+    - media: ov2680: Fix ov2680_bayer_order()
+    - media: ov2680: Fix vflip / hflip set functions
+    - media: ov2680: Fix regulators being left enabled on ov2680_power_on() errors
+    - scsi: core: Use 32-bit hostnum in scsi_host_lookup()
+    - scsi: fcoe: Fix potential deadlock on &fip->ctlr_lock
+    - serial: tegra: handle clk prepare error in tegra_uart_hw_init()
+    - amba: bus: fix refcount leak
+    - Revert "IB/isert: Fix incorrect release of isert connection"
+    - RDMA/siw: Balance the reference of cep->kref in the error path
+    - RDMA/siw: Correct wrong debug message
+    - HID: logitech-dj: Fix error handling in logi_dj_recv_switch_to_dj_mode()
+    - HID: multitouch: Correct devm device reference for hidinput input_dev name
+    - x86/speculation: Mark all Skylake CPUs as vulnerable to GDS
+    - tracing: Fix race issue between cpu buffer write and swap
+    - phy/rockchip: inno-hdmi: use correct vco_div_5 macro on rk3328
+    - phy/rockchip: inno-hdmi: round fractal pixclock in rk3328 recalc_rate
+    - phy/rockchip: inno-hdmi: do not power on rk3328 post pll on reg write
+    - rpmsg: glink: Add check for kstrdup
+    - mtd: rawnand: fsmc: handle clk prepare error in fsmc_nand_resume()
+    - um: Fix hostaudio build errors
+    - dmaengine: ste_dma40: Add missing IRQ check in d40_probe
+    - cpufreq: Fix the race condition while updating the transition_task of policy
+    - virtio_ring: fix avail_wrap_counter in virtqueue_add_packed
+    - skbuff: skb_segment, Call zero copy functions before using skbuff frags
+    - PM / devfreq: Fix leak in devfreq_dev_release()
+    - ALSA: pcm: Fix missing fixup call in compat hw_refine ioctl
+    - ipmi_si: fix a memleak in try_smi_init()
+    - ARM: OMAP2+: Fix -Warray-bounds warning in _pwrdm_state_switch()
+    - backlight/gpio_backlight: Compare against struct fb_info.device
+    - backlight/bd6107: Compare against struct fb_info.device
+    - backlight/lv5207lp: Compare against struct fb_info.device
+    - xtensa: PMU: fix base address for the newer hardware
+    - media: dvb: symbol fixup for dvb_attach()
+    - ntb: Drop packets when qp link is down
+    - ntb: Clean up tx tail index on link down
+    - ntb: Fix calculation ntb_transport_tx_free_entry()
+    - Revert "PCI: Mark NVIDIA T4 GPUs to avoid bus reset"
+    - procfs: block chmod on /proc/thread-self/comm
+    - parisc: Fix /proc/cpuinfo output for lscpu
+    - dlm: fix plock lookup when using multiple lockspaces
+    - dccp: Fix out of bounds access in DCCP error handler
+    - X.509: if signature is unsupported skip validation
+    - net: handle ARPHRD_PPP in dev_is_mac_header_xmit()
+    - fsverity: skip PKCS#7 parser when keyring is empty
+    - pstore/ram: Check start of empty przs during init
+    - s390/ipl: add missing secure/has_secure file to ipl type 'unknown'
+    - crypto: stm32 - fix loop iterating through scatterlist for DMA
+    - cpufreq: brcmstb-avs-cpufreq: Fix -Warray-bounds bug
+    - sc16is7xx: Set iobase to device index
+    - serial: sc16is7xx: fix broken port 0 uart init
+    - usb: typec: tcpci: clear the fault status bit
+    - udf: initialize newblock to 0
+    - drm: fix double free for gbo in drm_gem_vram_init and drm_gem_vram_create
+    - net/ipv6: SKB symmetric hash should incorporate transport ports
+    - scsi: qla2xxx: fix inconsistent TMF timeout
+    - scsi: qla2xxx: Fix erroneous link up failure
+    - scsi: qla2xxx: Turn off noisy message log
+    - scsi: qla2xxx: Remove unsupported ql2xenabledif option
+    - fbdev/ep93xx-fb: Do not assign to struct fb_info.dev
+    - drm/ast: Fix DRAM init on AST2200
+    - lib/test_meminit: allocate pages up to order MAX_ORDER
+    - parisc: led: Fix LAN receive and transmit LEDs
+    - parisc: led: Reduce CPU overhead for disk & lan LED computation
+    - clk: qcom: gcc-mdm9615: use proper parent for pll0_vote clock
+    - soc: qcom: qmi_encdec: Restrict string length in decode
+    - NFSv4/pnfs: minor fix for cleanup path in nfs4_get_device_info
+    - kconfig: fix possible buffer overflow
+    - perf annotate bpf: Don't enclose non-debug code with an assert()
+    - x86/virt: Drop unnecessary check on extended CPUID level in cpu_has_svm()
+    - perf top: Don't pass an ERR_PTR() directly to perf_session__delete()
+    - watchdog: intel-mid_wdt: add MODULE_ALIAS() to allow auto-load
+    - pwm: lpc32xx: Remove handling of PWM channels
+    - sctp: annotate data-races around sk->sk_wmem_queued
+    - ipv4: annotate data-races around fi->fib_dead
+    - net: read sk->sk_family once in sk_mc_loop()
+    - igb: disable virtualization features on 82580
+    - veth: Fixing transmit return status for dropped packets
+    - net: ipv6/addrconf: avoid integer underflow in ipv6_create_tempaddr
+    - af_unix: Fix data-races around user->unix_inflight.
+    - af_unix: Fix data-race around unix_tot_inflight.
+    - af_unix: Fix data-races around sk->sk_shutdown.
+    - af_unix: Fix data race around sk->sk_err.
+    - kcm: Destroy mutex in kcm_exit_net()
+    - igc: Change IGC_MIN to allow set rx/tx value between 64 and 80
+    - igbvf: Change IGBVF_MIN to allow set rx/tx value between 64 and 80
+    - igb: Change IGB_MIN to allow set rx/tx value between 64 and 80
+    - s390/zcrypt: don't leak memory if dev_set_name() fails
+    - idr: fix param name in idr_alloc_cyclic() doc
+    - ip_tunnels: use DEV_STATS_INC()
+    - net: hns3: fix the port information display when sfp is absent
+    - sh: boards: Fix CEU buffer size passed to dma_declare_coherent_memory()
+    - ata: sata_gemini: Add missing MODULE_DESCRIPTION
+    - ata: pata_ftide010: Add missing MODULE_DESCRIPTION
+    - fuse: nlookup missing decrement in fuse_direntplus_link
+    - btrfs: don't start transaction when joining with TRANS_JOIN_NOSTART
+    - btrfs: use the correct superblock to compare fsid in btrfs_validate_super
+    - mtd: rawnand: brcmnand: Fix crash during the panic_write
+    - mtd: rawnand: brcmnand: Fix potential out-of-bounds access in oob write
+    - mtd: rawnand: brcmnand: Fix potential false time out warning
+    - perf hists browser: Fix hierarchy mode header
+    - perf tools: Handle old data in PERF_RECORD_ATTR
+    - usb: typec: tcpm: Refactor tcpm_handle_vdm_request payload handling
+    - usb: typec: tcpm: Refactor tcpm_handle_vdm_request
+    - usb: typec: bus: verify partner exists in typec_altmode_attention
+    - ARM: dts: BCM5301X: Extend RAM to full 256MB for Linksys EA6500 V2
+    - clk: imx8mm: Move 1443X/1416X PLL clock structure to common place
+    - net: ipv4: fix one memleak in __inet_del_ifa()
+    - net: ethernet: mvpp2_main: fix possible OOB write in
+      mvpp2_ethtool_get_rxnfc()
+    - net: ethernet: mtk_eth_soc: fix possible NULL pointer dereference in
+      mtk_hwlro_get_fdir_all()
+    - r8152: check budget for r8152_poll()
+    - kcm: Fix memory leak in error path of kcm_sendmsg()
+    - platform/mellanox: mlxbf-tmfifo: Drop the Rx packet if no more descriptors
+    - mlxbf-tmfifo: sparse tags for config access
+    - platform/mellanox: mlxbf-tmfifo: Drop jumbo frames
+    - net/tls: do not free tls_rec on async operation in bpf_exec_tx_verdict()
+    - ixgbe: fix timestamp configuration code
+    - kcm: Fix error handling for SOCK_DGRAM in kcm_sendmsg().
+    - drm/amd/display: Fix a bug when searching for insert_above_mpcc
+    - parisc: Drop loops_per_jiffy from per_cpu struct
+    - autofs: fix memory leak of waitqueues in autofs_catatonic_mode
+    - btrfs: output extra debug info if we failed to find an inline backref
+    - locks: fix KASAN: use-after-free in trace_event_raw_event_filelock_lock
+    - ACPICA: Add AML_NO_OPERAND_RESOLVE flag to Timer
+    - kernel/fork: beware of __put_task_struct() calling context
+    - ACPI: video: Add backlight=native DMI quirk for Lenovo Ideapad Z470
+    - perf/smmuv3: Enable HiSilicon Erratum 162001900 quirk for HIP08/09
+    - hw_breakpoint: fix single-stepping when using bpf_overflow_handler
+    - devlink: remove reload failed checks in params get/set callbacks
+    - wifi: ath9k: fix printk specifier
+    - wifi: mwifiex: fix fortify warning
+    - crypto: lib/mpi - avoid null pointer deref in mpi_cmp_ui()
+    - tpm_tis: Resend command to recover from data transfer errors
+    - mmc: sdhci-esdhc-imx: improve ESDHC_FLAG_ERR010450
+    - alx: fix OOB-read compiler warning
+    - wifi: mac80211_hwsim: drop short frames
+    - drm/exynos: fix a possible null-pointer dereference due to data race in
+      exynos_drm_crtc_atomic_disable()
+    - bus: ti-sysc: Configure uart quirks for k3 SoC
+    - md: raid1: fix potential OOB in raid1_remove_disk()
+    - ext2: fix datatype of block number in ext2_xattr_set2()
+    - fs/jfs: prevent double-free in dbUnmount() after failed jfs_remount()
+    - jfs: fix invalid free of JFS_IP(ipimap)->i_imap in diUnmount
+    - powerpc/pseries: fix possible memory leak in ibmebus_bus_init()
+    - media: dvb-usb-v2: af9035: Fix null-ptr-deref in af9035_i2c_master_xfer
+    - media: dw2102: Fix null-ptr-deref in dw2102_i2c_transfer()
+    - media: af9005: Fix null-ptr-deref in af9005_i2c_xfer
+    - media: anysee: fix null-ptr-deref in anysee_master_xfer
+    - media: az6007: Fix null-ptr-deref in az6007_i2c_xfer()
+    - media: tuners: qt1010: replace BUG_ON with a regular error
+    - media: pci: cx23885: replace BUG with error return
+    - usb: gadget: fsl_qe_udc: validate endpoint index for ch9 udc
+    - scsi: target: iscsi: Fix buffer overflow in lio_target_nacl_info_show()
+    - serial: cpm_uart: Avoid suspicious locking
+    - media: pci: ipu3-cio2: Initialise timing struct to avoid a compiler warning
+    - kobject: Add sanity check for kset->kobj.ktype in kset_register()
+    - tools features: Add feature test to check if libbfd has buildid support
+    - perf jevents: Make build dependency on test JSONs
+    - perf tools: Add an option to build without libbfd
+    - btrfs: move btrfs_pinned_by_swapfile prototype into volumes.h
+    - btrfs: add a helper to read the superblock metadata_uuid
+    - btrfs: compare the correct fsid/metadata_uuid in btrfs_validate_super
+    - selftests: tracing: Fix to unmount tracefs for recovering environment
+    - md/raid1: fix error: ISO C90 forbids mixed declarations
+    - attr: block mode changes of symlinks
+    - btrfs: fix lockdep splat and potential deadlock after failure running
+      delayed items
+    - tracing: Have current_trace inc the trace array ref count
+    - tracing: Have option files inc the trace array ref count
+    - nfsd: fix change_info in NFSv4 RENAME replies
+    - tracefs: Add missing lockdown check to tracefs_create_dir()
+    - i2c: aspeed: Reset the i2c controller when timeout occurs
+    - scsi: megaraid_sas: Fix deadlock on firmware crashdump
+    - ext4: fix rec_len verify error
+    - mtd: rawnand: brcmnand: Fix ECC level field setting for v7.2 controller
+    - drm/amdgpu: fix amdgpu_cs_p1_user_fence
+    - Linux 5.4.257
+
+  * Focal update: v5.4.257 upstream stable release (LP: #2040284) //
+    CVE-2023-39189
+    - netfilter: nfnetlink_osf: avoid OOB read
+
+  * CVE-2023-45871
+    - igb: set max size RX buffer when store bad packet is enabled
+
+  * CVE-2023-39193
+    - netfilter: xt_sctp: validate the flag_info count
+
+  * CVE-2023-39192
+    - netfilter: xt_u32: validate user space input
+
+  * CVE-2023-31085
+    - ubi: Refuse attaching if mtd's erasesize is 0
+
+  * CVE-2023-5717
+    - perf: Disallow mis-matched inherited group reads
+
+  * CVE-2023-5178
+    - nvmet-tcp: move send/recv error handling in the send/recv methods instead of
+      call-sites
+    - nvmet-tcp: Fix a possible UAF in queue intialization setup
+
+  * CVE-2023-42754
+    - ipv4: fix null-deref in ipv4_link_failure
+
+  * Focal update: v5.4.256 upstream stable release (LP: #2039446)
+    - powerpc/pmac/smp: Avoid unused-variable warnings
+    - powerpc/pmac/smp: Drop unnecessary volatile qualifier
+    - Revert "MIPS: Alchemy: fix dbdma2"
+    - Linux 5.4.256
+
+  * Focal update: v5.4.255 upstream stable release (LP: #2039440)
+    - mmc: sdhci_f_sdh30: convert to devm_platform_ioremap_resource
+    - mmc: sdhci-f-sdh30: Replace with sdhci_pltfm
+    - selftests: forwarding: tc_flower: Relax success criterion
+    - macsec: Fix traffic counters/statistics
+    - macsec: use DEV_STATS_INC()
+    - drm/radeon: Fix integer overflow in radeon_cs_parser_init
+    - ALSA: emu10k1: roll up loops in DSP setup code for Audigy
+    - quota: Properly disable quotas when add_dquot_ref() fails
+    - quota: fix warning in dqgrab()
+    - HID: add quirk for 03f0:464a HP Elite Presenter Mouse
+    - ovl: check type and offset of struct vfsmount in ovl_entry
+    - udf: Fix uninitialized array access for some pathnames
+    - fs: jfs: Fix UBSAN: array-index-out-of-bounds in dbAllocDmapLev
+    - MIPS: dec: prom: Address -Warray-bounds warning
+    - FS: JFS: Fix null-ptr-deref Read in txBegin
+    - FS: JFS: Check for read-only mounted filesystem in txBegin
+    - media: v4l2-mem2mem: add lock to protect parameter num_rdy
+    - media: platform: mediatek: vpu: fix NULL ptr dereference
+    - usb: chipidea: imx: don't request QoS for imx8ulp
+    - gfs2: Fix possible data races in gfs2_show_options()
+    - pcmcia: rsrc_nonstatic: Fix memory leak in nonstatic_release_resource_db()
+    - Bluetooth: L2CAP: Fix use-after-free
+    - drm/amdgpu: Fix potential fence use-after-free v2
+    - ALSA: hda/realtek: Add quirks for Unis H3C Desktop B760 & Q760
+    - ALSA: hda: fix a possible null-pointer dereference due to data race in
+      snd_hdac_regmap_sync()
+    - powerpc/kasan: Disable KCOV in KASAN code
+    - IMA: allow/fix UML builds
+    - iio: add addac subdirectory
+    - iio: adc: stx104: Utilize iomap interface
+    - iio: adc: stx104: Implement and utilize register structures
+    - iio: stx104: Move to addac subdirectory
+    - iio: addac: stx104: Fix race condition for stx104_write_raw()
+    - iio: addac: stx104: Fix race condition when converting analog-to-digital
+    - iommu/amd: Fix "Guest Virtual APIC Table Root Pointer" configuration in IRTE
+    - PM-runtime: add tracepoints for usage_count changes
+    - PM: runtime: Add pm_runtime_get_if_active()
+    - ALSA: hda: Fix unhandled register update during auto-suspend period
+    - irqchip/mips-gic: Get rid of the reliance on irq_cpu_online()
+    - irqchip/mips-gic: Use raw spinlock for gic_lock
+    - interconnect: Move internal structs into a separate file
+    - interconnect: Add helpers for enabling/disabling a path
+    - usb: dwc3: qcom: Add helper functions to enable,disable wake irqs
+    - USB: dwc3: qcom: fix NULL-deref on suspend
+    - mmc: bcm2835: fix deferred probing
+    - mmc: sunxi: fix deferred probing
+    - leds: trigger: netdev: Recheck NETDEV_LED_MODE_LINKUP on dev rename
+    - tracing/probes: Have process_fetch_insn() take a void * instead of pt_regs
+    - tracing/probes: Fix to update dynamic data counter if fetcharg uses it
+    - net/ncsi: Fix gma flag setting after response
+    - nfsd4: kill warnings on testing stateids with mismatched clientids
+    - nfsd: Remove incorrect check in nfsd4_validate_stateid
+    - virtio-mmio: convert to devm_platform_ioremap_resource
+    - virtio-mmio: Use to_virtio_mmio_device() to simply code
+    - virtio-mmio: don't break lifecycle of vm_dev
+    - i2c: bcm-iproc: Fix bcm_iproc_i2c_isr deadlock issue
+    - fbdev: mmp: fix value check in mmphw_probe()
+    - powerpc/rtas_flash: allow user copy to flash block cache objects
+    - tty: serial: fsl_lpuart: Clear the error flags by writing 1 for lpuart32
+      platforms
+    - btrfs: fix BUG_ON condition in btrfs_cancel_balance
+    - net: xfrm: Fix xfrm_address_filter OOB read
+    - net: af_key: fix sadb_x_filter validation
+    - xfrm: interface: rename xfrm_interface.c to xfrm_interface_core.c
+    - xfrm: fix slab-use-after-free in decode_session6
+    - ip6_vti: fix slab-use-after-free in decode_session6
+    - ip_vti: fix potential slab-use-after-free in decode_session6
+    - selftests: mirror_gre_changes: Tighten up the TTL test match
+    - ipvs: fix racy memcpy in proc_do_sync_threshold
+    - netfilter: nft_dynset: disallow object maps
+    - team: Fix incorrect deletion of ETH_P_8021AD protocol vid from slaves
+    - i40e: fix misleading debug logs
+    - net: dsa: mv88e6xxx: Wait for EEPROM done before HW reset
+    - sock: Fix misuse of sk_under_memory_pressure()
+    - net: do not allow gso_size to be set to GSO_BY_FRAGS
+    - bus: ti-sysc: Improve reset to work with modules with no sysconfig
+    - bus: ti-sysc: Flush posted write on enable before reset
+    - ARM: dts: imx7s: Drop dma-apb interrupt-names
+    - ARM: dts: imx: Adjust dma-apbh node name
+    - ARM: dts: imx: Set default tuning step for imx7d usdhc
+    - ARM: dts: imx: Set default tuning step for imx6sx usdhc
+    - ASoC: rt5665: add missed regulator_bulk_disable
+    - ASoC: meson: axg-tdm-formatter: fix channel slot allocation
+    - serial: 8250: Fix oops for port->pm on uart_change_pm()
+    - ALSA: usb-audio: Add support for Mythware XA001AU capture and playback
+      interfaces.
+    - cifs: Release folio lock on fscache read hit.
+    - mmc: wbsd: fix double mmc_free_host() in wbsd_init()
+    - mmc: block: Fix in_flight[issue_type] value error
+    - netfilter: set default timeout to 3 secs for sctp shutdown send and recv
+      state
+    - virtio-net: set queues after driver_ok
+    - net: fix the RTO timer retransmitting skb every 1ms if linear option is
+      enabled
+    - net: xfrm: Amend XFRMA_SEC_CTX nla_policy structure
+    - mmc: f-sdh30: fix order of function calls in sdhci_f_sdh30_remove
+    - net: phy: broadcom: stub c45 read/write for 54810
+    - PCI: acpiphp: Reassign resources on bridge if necessary
+    - dlm: improve plock logging if interrupted
+    - dlm: replace usage of found with dedicated list iterator variable
+    - fs: dlm: add pid to debug log
+    - fs: dlm: change plock interrupted message to debug again
+    - fs: dlm: use dlm_plock_info for do_unlock_close
+    - fs: dlm: fix mismatch of plock results from userspace
+    - MIPS: cpu-features: Enable octeon_cache by cpu_type
+    - MIPS: cpu-features: Use boot_cpu_type for CPU type based features
+    - fbdev: Improve performance of sys_imageblit()
+    - fbdev: Fix sys_imageblit() for arbitrary image widths
+    - fbdev: fix potential OOB read in fast_imageblit()
+    - dm integrity: increase RECALC_SECTORS to improve recalculate speed
+    - dm integrity: reduce vmalloc space footprint on 32-bit architectures
+    - ALSA: pcm: Set per-card upper limit of PCM buffer allocations
+    - ALSA: pcm: Use SG-buffer only when direct DMA is available
+    - ALSA: pcm: Fix potential data race at PCM memory allocation helpers
+    - regmap: Account for register length in SMBus I/O limits
+    - ASoC: fsl_sai: Refine enable/disable TE/RE sequence in trigger()
+    - ASoC: fsl_sai: Add new added registers and new bit definition
+    - ASoC: fsl_sai: Disable bit clock with transmitter
+    - drm/amd/display: do not wait for mpc idle if tg is disabled
+    - drm/amd/display: check TG is non-null before checking if enabled
+    - tracing: Fix memleak due to race between current_tracer and trace
+    - octeontx2-af: SDP: fix receive link config
+    - sock: annotate data-races around prot->memory_pressure
+    - dccp: annotate data-races in dccp_poll()
+    - ipvlan: Fix a reference count leak warning in ipvlan_ns_exit()
+    - net: bgmac: Fix return value check for fixed_phy_register()
+    - net: bcmgenet: Fix return value check for fixed_phy_register()
+    - net: validate veth and vxcan peer ifindexes
+    - igb: Avoid starting unnecessary workqueues
+    - net/sched: fix a qdisc modification with ambiguous command request
+    - net: remove bond_slave_has_mac_rcu()
+    - bonding: fix macvlan over alb bond support
+    - ibmveth: Use dcbf rather than dcbfl
+    - NFSv4: Fix dropped lock for racing OPEN and delegation return
+    - clk: Fix slab-out-of-bounds error in devm_clk_release()
+    - nfsd: Fix race to FREE_STATEID and cl_revoked
+    - batman-adv: Trigger events for auto adjusted MTU
+    - batman-adv: Don't increase MTU when set by user
+    - batman-adv: Do not get eth header before batadv_check_management_packet
+    - batman-adv: Fix TT global entry leak when client roamed back
+    - batman-adv: Fix batadv_v_ogm_aggr_send memory leak
+    - batman-adv: Hold rtnl lock during MTU update via netlink
+    - lib/clz_ctz.c: Fix __clzdi2() and __ctzdi2() for 32-bit kernels
+    - radix tree: remove unused variable
+    - media: vcodec: Fix potential array out-of-bounds in encoder queue_setup
+    - PCI: acpiphp: Use pci_assign_unassigned_bridge_resources() only for non-root
+      bus
+    - drm/display/dp: Fix the DP DSC Receiver cap size
+    - mm: allow a controlled amount of unfairness in the page lock
+    - rtnetlink: Reject negative ifindexes in RTM_NEWLINK
+    - ALSA: pcm: Fix build error on m68k and others
+    - Revert "ALSA: pcm: Use SG-buffer only when direct DMA is available"
+    - interconnect: Do not skip aggregation for disabled paths
+    - ALSA: pcm: Check for null pointer of pointer substream before dereferencing
+      it
+    - Documentation/sysctl: document page_lock_unfairness
+    - irqchip/mips-gic: Don't touch vl_map if a local interrupt is not routable
+    - scsi: snic: Fix double free in snic_tgt_create()
+    - scsi: core: raid_class: Remove raid_component_add()
+    - clk: Fix undefined reference to `clk_rate_exclusive_{get,put}'
+    - pinctrl: renesas: rza2: Add lock around
+      pinctrl_generic{{add,remove}_group,{add,remove}_function}
+    - dma-buf/sw_sync: Avoid recursive lock during fence signal
+    - Linux 5.4.255
+
+  * Focal update: v5.4.254 upstream stable release (LP: #2039291)
+    - mmc: moxart: read scr register without changing byte order
+    - ipv6: adjust ndisc_is_useropt() to also return true for PIO
+    - dmaengine: pl330: Return DMA_PAUSED when transaction is paused
+    - drm/nouveau/gr: enable memory loads on helper invocation on all channels
+    - radix tree test suite: fix incorrect allocation size for pthreads
+    - nilfs2: fix use-after-free of nilfs_root in dirtying inodes via iput
+    - iio: cros_ec: Fix the allocation size for cros_ec_command
+    - binder: fix memory leak in binder_init()
+    - usb-storage: alauda: Fix uninit-value in alauda_check_media()
+    - usb: dwc3: Properly handle processing of pending events
+    - usb: common: usb-conn-gpio: Prevent bailing out if initial role is none
+    - x86/cpu/amd: Enable Zenbleed fix for AMD Custom APU 0405
+    - x86/mm: Fix VDSO and VVAR placement on 5-level paging machines
+    - x86: Move gds_ucode_mitigated() declaration to header
+    - drm/nouveau/disp: Revert a NULL check inside nouveau_connector_get_modes
+    - selftests/rseq: Fix build with undefined __weak
+    - mISDN: Update parameter type of dsp_cmx_send()
+    - net/packet: annotate data-races around tp->status
+    - bonding: Fix incorrect deletion of ETH_P_8021AD protocol vid from slaves
+    - dccp: fix data-race around dp->dccps_mss_cache
+    - drivers: net: prevent tun_build_skb() to exceed the packet size limit
+    - IB/hfi1: Fix possible panic during hotplug remove
+    - wifi: cfg80211: fix sband iftype data lookup for AP_VLAN
+    - dmaengine: mcf-edma: Fix a potential un-allocated memory access
+    - net/mlx5: Allow 0 for total host VFs
+    - ibmvnic: Handle DMA unmapping of login buffs in release functions
+    - btrfs: don't stop integrity writeback too early
+    - btrfs: set cache_block_group_error if we find an error
+    - nvme-tcp: fix potential unbalanced freeze & unfreeze
+    - nvme-rdma: fix potential unbalanced freeze & unfreeze
+    - netfilter: nf_tables: report use refcount overflow
+    - scsi: core: Fix legacy /proc parsing buffer overflow
+    - scsi: storvsc: Fix handling of virtual Fibre Channel timeouts
+    - scsi: 53c700: Check that command slot is not NULL
+    - scsi: snic: Fix possible memory leak if device_add() fails
+    - scsi: core: Fix possible memory leak if device_add() fails
+    - alpha: remove __init annotation from exported page_is_ram()
+    - sch_netem: fix issues in netem_change() vs get_dist_table()
+    - Linux 5.4.254
+
+  * Focal update: v5.4.253 upstream stable release (LP: #2038652)
+    - jbd2: fix incorrect code style
+    - jbd2: fix kernel-doc markups
+    - jbd2: remove redundant buffer io error checks
+    - jbd2: recheck chechpointing non-dirty buffer
+    - jbd2: Fix wrongly judgement for buffer head removing while doing checkpoint
+    - gpio: tps68470: Make tps68470_gpio_output() always set the initial value
+    - bcache: remove 'int n' from parameter list of bch_bucket_alloc_set()
+    - bcache: Fix __bch_btree_node_alloc to make the failure behavior consistent
+    - btrfs: qgroup: catch reserved space leaks at unmount time
+    - btrfs: fix race between quota disable and relocation
+    - btrfs: fix extent buffer leak after tree mod log failure at split_node()
+    - ext4: rename journal_dev to s_journal_dev inside ext4_sb_info
+    - ext4: Fix reusing stale buffer heads from last failed mounting
+    - PCI/ASPM: Return 0 or -ETIMEDOUT from pcie_retrain_link()
+    - PCI/ASPM: Factor out pcie_wait_for_retrain()
+    - PCI/ASPM: Avoid link retraining race
+    - dlm: cleanup plock_op vs plock_xop
+    - dlm: rearrange async condition return
+    - fs: dlm: interrupt posix locks only when process is killed
+    - ftrace: Add information on number of page groups allocated
+    - ftrace: Check if pages were allocated before calling free_pages()
+    - ftrace: Store the order of pages allocated in ftrace_page
+    - ftrace: Fix possible warning on checking all pages used in
+      ftrace_process_locs()
+    - pwm: meson: Remove redundant assignment to variable fin_freq
+    - pwm: meson: Simplify duplicated per-channel tracking
+    - pwm: meson: fix handling of period/duty if greater than UINT_MAX
+    - scsi: qla2xxx: Fix inconsistent format argument type in qla_os.c
+    - scsi: qla2xxx: Array index may go out of bound
+    - uapi: General notification queue definitions
+    - keys: Fix linking a duplicate key to a keyring's assoc_array
+    - ext4: fix to check return value of freeze_bdev() in ext4_shutdown()
+    - i40e: Fix an NULL vs IS_ERR() bug for debugfs_create_dir()
+    - vxlan: calculate correct header length for GPE
+    - phy: hisilicon: Fix an out of bounds check in hisi_inno_phy_probe()
+    - ethernet: atheros: fix return value check in atl1e_tso_csum()
+    - ipv6 addrconf: fix bug where deleting a mngtmpaddr can create a new
+      temporary address
+    - bonding: reset bond's flags when down link is P2P device
+    - team: reset team's flags when down link is P2P device
+    - platform/x86: msi-laptop: Fix rfkill out-of-sync on MSI Wind U100
+    - net/sched: mqprio: refactor nlattr parsing to a separate function
+    - net/sched: mqprio: add extack to mqprio_parse_nlattr()
+    - net/sched: mqprio: Add length check for TCA_MQPRIO_{MAX/MIN}_RATE64
+    - benet: fix return value check in be_lancer_xmit_workarounds()
+    - RDMA/mlx4: Make check for invalid flags stricter
+    - drm/msm/dpu: drop enum dpu_core_perf_data_bus_id
+    - drm/msm/adreno: Fix snapshot BINDLESS_DATA size
+    - drm/msm: Fix IS_ERR_OR_NULL() vs NULL check in a5xx_submit_in_rb()
+    - ASoC: fsl_spdif: Silence output on stop
+    - block: Fix a source code comment in include/uapi/linux/blkzoned.h
+    - dm raid: fix missing reconfig_mutex unlock in raid_ctr() error paths
+    - ata: pata_ns87415: mark ns87560_tf_read static
+    - ring-buffer: Fix wrong stat of cpu_buffer->read
+    - tracing: Fix warning in trace_buffered_event_disable()
+    - serial: 8250_dw: Preserve original value of DLF register
+    - serial: sifive: Fix sifive_serial_console_setup() section
+    - USB: serial: option: support Quectel EM060K_128
+    - USB: serial: option: add Quectel EC200A module support
+    - USB: serial: simple: add Kaufmann RKS+CAN VCP
+    - USB: serial: simple: sort driver entries
+    - can: gs_usb: gs_can_close(): add missing set of CAN state to
+      CAN_STATE_STOPPED
+    - Revert "usb: dwc3: core: Enable AutoRetry feature in the controller"
+    - usb: dwc3: pci: skip BYT GPIO lookup table for hardwired phy
+    - usb: dwc3: don't reset device side if dwc3 was configured as host-only
+    - usb: ohci-at91: Fix the unhandle interrupt when resume
+    - USB: quirks: add quirk for Focusrite Scarlett
+    - usb: xhci-mtk: set the dma max_seg_size
+    - Revert "usb: xhci: tegra: Fix error check"
+    - Documentation: security-bugs.rst: update preferences when dealing with the
+      linux-distros group
+    - Documentation: security-bugs.rst: clarify CVE handling
+    - staging: ks7010: potential buffer overflow in ks_wlan_set_encode_ext()
+    - hwmon: (nct7802) Fix for temp6 (PECI1) processed even if PECI1 disabled
+    - btrfs: check for commit error at btrfs_attach_transaction_barrier()
+    - tpm_tis: Explicitly check for error code
+    - irq-bcm6345-l1: Do not assume a fixed block to cpu mapping
+    - btrfs: check if the transaction was aborted at btrfs_wait_for_commit()
+    - virtio-net: fix race between set queues and probe
+    - s390/dasd: fix hanging device after quiesce/resume
+    - ASoC: wm8904: Fill the cache for WM8904_ADC_TEST_0 register
+    - dm cache policy smq: ensure IO doesn't prevent cleaner policy progress
+    - ACPI: processor: perflib: Use the "no limit" frequency QoS
+    - ACPI: processor: perflib: Avoid updating frequency QoS unnecessarily
+    - cpufreq: intel_pstate: Drop ACPI _PSS states table patching
+    - btrfs: qgroup: remove one-time use variables for quota_root checks
+    - btrfs: qgroup: return ENOTCONN instead of EINVAL when quotas are not enabled
+    - ASoC: cs42l51: fix driver to properly autoload with automatic module loading
+    - arm64: Add AMPERE1 to the Spectre-BHB affected list
+    - arm64: Fix bit-shifting UB in the MIDR_CPU_MODEL() macro
+    - perf: Fix function pointer case
+    - loop: Select I/O scheduler 'none' from inside add_disk()
+    - word-at-a-time: use the same return type for has_zero regardless of
+      endianness
+    - KVM: s390: fix sthyi error handling
+    - net/mlx5: DR, fix memory leak in mlx5dr_cmd_create_reformat_ctx
+    - net/mlx5e: fix return value check in mlx5e_ipsec_remove_trailer()
+    - rtnetlink: let rtnl_bridge_setlink checks IFLA_BRIDGE_MODE length
+    - perf test uprobe_from_different_cu: Skip if there is no gcc
+    - net: sched: cls_u32: Fix match key mis-addressing
+    - mISDN: hfcpci: Fix potential deadlock on &hc->lock
+    - net: annotate data-races around sk->sk_max_pacing_rate
+    - net: add missing READ_ONCE(sk->sk_rcvlowat) annotation
+    - net: add missing READ_ONCE(sk->sk_sndbuf) annotation
+    - net: add missing READ_ONCE(sk->sk_rcvbuf) annotation
+    - net: add missing data-race annotations around sk->sk_peek_off
+    - net: add missing data-race annotation for sk_ll_usec
+    - bpf: sockmap: Remove preempt_disable in sock_map_sk_acquire
+    - driver core: add device probe log helper
+    - net: ll_temac: Switch to use dev_err_probe() helper
+    - net: ll_temac: fix error checking of irq_of_parse_and_map()
+    - net: dcb: choose correct policy to parse DCB_ATTR_BCN
+    - ip6mr: Fix skb_under_panic in ip6mr_cache_report()
+    - tcp_metrics: fix addr_same() helper
+    - tcp_metrics: annotate data-races around tm->tcpm_stamp
+    - tcp_metrics: annotate data-races around tm->tcpm_lock
+    - tcp_metrics: annotate data-races around tm->tcpm_vals[]
+    - tcp_metrics: annotate data-races around tm->tcpm_net
+    - tcp_metrics: fix data-race in tcpm_suck_dst() vs fastopen
+    - scsi: zfcp: Defer fc_rport blocking until after ADISC response
+    - libceph: fix potential hang in ceph_osdc_notify()
+    - USB: zaurus: Add ID for A-300/B-500/C-700
+    - mtd: spinand: toshiba: Fix ecc_get_status
+    - mtd: rawnand: meson: fix OOB available bytes for ECC
+    - fs/sysv: Null check to prevent null-ptr-deref bug
+    - net: usbnet: Fix WARNING in usbnet_start_xmit/usb_submit_urb
+    - fs: Protect reconfiguration of sb read-write from racing writes
+    - ext2: Drop fragment support
+    - test_firmware: prevent race conditions by a correct implementation of
+      locking
+    - test_firmware: return ENOMEM instead of ENOSPC on failed memory allocation
+    - mtd: rawnand: omap_elm: Fix incorrect type in assignment
+    - powerpc/mm/altmap: Fix altmap boundary check
+    - selftests/rseq: check if libc rseq support is registered
+    - selftests/rseq: Play nice with binaries statically linked against glibc
+      2.35+
+    - PM / wakeirq: support enabling wake-up irq after runtime_suspend called
+    - PM: sleep: wakeirq: fix wake irq arming
+    - ceph: show tasks waiting on caps in debugfs caps file
+    - ceph: use kill_anon_super helper
+    - ceph: defer stopping mdsc delayed_work
+    - arm64: dts: stratix10: fix incorrect I2C property for SCL signal
+    - ARM: dts: imx6sll: Make ssi node name same as other platforms
+    - ARM: dts: imx: Align L2 cache-controller nodename with dtschema
+    - ARM: dts: imx: add usb alias
+    - ARM: dts: imx6sll: fixup of operating points
+    - ARM: dts: nxp/imx6sll: fix wrong property name in usbphy node
+    - driver core: Annotate dev_err_probe() with __must_check
+    - driver code: print symbolic error code
+    - drivers: core: fix kernel-doc markup for dev_err_probe()
+    - Revert "driver core: Annotate dev_err_probe() with __must_check"
+    - Linux 5.4.253
+    - Upstream stable to v5.4.253
+
+  * CVE-2023-37453
+    - USB: hub: Clean up use of port initialization schemes and retries
+    - USB: hub: Add Kconfig option to reduce number of port initialization retries
+    - USB: core: Unite old scheme and new scheme descriptor reads
+    - usb: hub: Check device descriptor before resusciation
+    - USB: core: Change usb_get_device_descriptor() API
+    - USB: core: Fix race by not overwriting udev->descriptor in hub_port_init()
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update helper scripts
+
+ -- Roxana Nicolescu <roxana.nicolescu@canonical.com>  Mon, 30 Oct 2023 11:52:53 +0100
+
+linux (5.4.0-166.183) focal; urgency=medium
+
+  * focal/linux: 5.4.0-166.183 -proposed tracker (LP: #2038010)
+
+  * Use new annotations model (LP: #2019000)
+    - [Packaging] new annotations model infrastructure
+    - [Packaging] config-check: Handle new annotations format 4
+    - [Packaging] rules: Use old-kernelconfig for old configs
+    - [Config] sanitize annotations
+    - [Config] import generated configs into annotation file
+    - [Packaging] kernelconfig: add i386 as supported arch
+    - [Config] Remove all old configs files
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update helper scripts
+    - [Packaging] update annotations scripts
+
+  * fix typo in config-checks invocation (LP: #2020413)
+    - [Packaging] fix typo when calling the old config-check
+    - [Packaging] fix typo in 4-checks.mk
+
+  * support python < 3.9 with annotations (LP: #2020531)
+    - [Packaging] kconfig/annotations.py: support older way of merging dicts
+
+  * CVE-2023-42756
+    - netfilter: ipset: Fix race between IPSET_CMD_CREATE and IPSET_CMD_SWAP
+
+  * CVE-2023-4623
+    - net/sched: sch_hfsc: Ensure inner classes have fsc curve
+
+  * Focal update: v5.4.252 upstream stable release (LP: #2036240)
+    - ia64/cpu: Switch to arch_cpu_finalize_init()
+    - m68k/cpu: Switch to arch_cpu_finalize_init()
+    - mips/cpu: Switch to arch_cpu_finalize_init()
+    - sh/cpu: Switch to arch_cpu_finalize_init()
+    - x86/cpufeatures: Add SEV-ES CPU feature
+    - x86/cpu: Add VM page flush MSR availablility as a CPUID feature
+    - x86/cpufeatures: Assign dedicated feature word for CPUID_0x8000001F[EAX]
+    - tools headers cpufeatures: Sync with the kernel sources
+    - x86/cpu, kvm: Add support for CPUID_80000021_EAX
+    - Linux 5.4.252
+    - Upstream stable to v5.4.252
+
+  * CVE-2023-42755
+    - net/sched: Retire rsvp classifier
+    - [Config] remove NET_CLS_RSVP and NET_CLS_RSVP6
+
+  * CVE-2023-42753
+    - netfilter: ipset: add the missing IP_SET_HASH_WITH_NET0 macro for
+      ip_set_hash_netportnet.c
+
+  * CVE-2023-34319
+    - xen/netback: Fix buffer overrun triggered by unusual packet
+
+  * CVE-2023-4921
+    - net: sched: sch_qfq: Fix UAF in qfq_dequeue()
+
+  * CVE-2023-42752
+    - igmp: limit igmpv3_newpack() packet size to IP_MAX_MTU
+
+  * Avoid address overwrite in kernel_connect (LP: #2035163)
+    - net: Avoid address overwrite in kernel_connect
+
+  * [regression] Unable to initialize SGX enclaves with XFRM other than 3
+    (LP: #2034745)
+    - x86/fpu: Set X86_FEATURE_OSXSAVE feature after enabling OSXSAVE in CR4
+
+  * CVE-2023-4881
+    - netfilter: nftables: exthdr: fix 4-byte stack OOB write
+
+  * CVE-2023-4622
+    - af_unix: Fix null-ptr-deref in unix_stream_sendpage().
+
+  * Focal update: v5.4.251 upstream stable release (LP: #2034918)
+    - x86/smp: Use dedicated cache-line for mwait_play_dead()
+    - video: imsttfb: check for ioremap() failures
+    - fbdev: imsttfb: Fix use after free bug in imsttfb_probe
+    - HID: wacom: Use ktime_t rather than int when dealing with timestamps
+    - drm/i915: Initialise outparam for error return from wait_for_register
+    - scripts/tags.sh: Resolve gtags empty index generation
+    - drm/amdgpu: Validate VM ioctl flags.
+    - bgmac: fix *initial* chip reset to support BCM5358
+    - x86/resctrl: Use is_closid_match() in more places
+    - x86/resctrl: Only show tasks' pid in current pid namespace
+    - md/raid10: check slab-out-of-bounds in md_bitmap_get_counter
+    - md/raid10: fix overflow of md/safe_mode_delay
+    - md/raid10: fix wrong setting of max_corr_read_errors
+    - md/raid10: fix null-ptr-deref of mreplace in raid10_sync_request
+    - md/raid10: fix io loss while replacement replace rdev
+    - irqchip/jcore-aic: Kill use of irq_create_strict_mappings()
+    - irqchip/jcore-aic: Fix missing allocation of IRQ descriptors
+    - tracing/timer: Add missing hrtimer modes to decode_hrtimer_mode().
+    - clocksource/drivers/cadence-ttc: Use ttc driver as platform driver
+    - clocksource/drivers/cadence-ttc: Fix memory leak in ttc_timer_probe
+    - PM: domains: fix integer overflow issues in genpd_parse_state()
+    - powercap: RAPL: Fix CONFIG_IOSF_MBI dependency
+    - ARM: 9303/1: kprobes: avoid missing-declaration warnings
+    - evm: Complete description of evm_inode_setattr()
+    - pstore/ram: Add check for kstrdup
+    - ima: Fix build warnings
+    - wifi: ath9k: fix AR9003 mac hardware hang check register offset calculation
+    - wifi: ath9k: avoid referencing uninit memory in ath9k_wmi_ctrl_rx
+    - samples/bpf: Fix buffer overflow in tcp_basertt
+    - spi: spi-geni-qcom: Correct CS_TOGGLE bit in SPI_TRANS_CFG
+    - wifi: mwifiex: Fix the size of a memory allocation in
+      mwifiex_ret_802_11_scan()
+    - nfc: constify several pointers to u8, char and sk_buff
+    - nfc: llcp: fix possible use of uninitialized variable in
+      nfc_llcp_send_connect()
+    - regulator: core: Fix more error checking for debugfs_create_dir()
+    - regulator: core: Streamline debugfs operations
+    - wifi: orinoco: Fix an error handling path in spectrum_cs_probe()
+    - wifi: orinoco: Fix an error handling path in orinoco_cs_probe()
+    - wifi: atmel: Fix an error handling path in atmel_probe()
+    - wl3501_cs: Fix a bunch of formatting issues related to function docs
+    - wl3501_cs: Remove unnecessary NULL check
+    - wl3501_cs: Fix misspelling and provide missing documentation
+    - net: create netdev->dev_addr assignment helpers
+    - wl3501_cs: use eth_hw_addr_set()
+    - wifi: wl3501_cs: Fix an error handling path in wl3501_probe()
+    - wifi: ray_cs: Utilize strnlen() in parse_addr()
+    - wifi: ray_cs: Drop useless status variable in parse_addr()
+    - wifi: ray_cs: Fix an error handling path in ray_probe()
+    - wifi: ath9k: don't allow to overwrite ENDPOINT0 attributes
+    - wifi: rsi: Do not set MMC_PM_KEEP_POWER in shutdown
+    - watchdog/perf: define dummy watchdog_update_hrtimer_threshold() on correct
+      config
+    - watchdog/perf: more properly prevent false positives with turbo modes
+    - kexec: fix a memory leak in crash_shrink_memory()
+    - memstick r592: make memstick_debug_get_tpc_name() static
+    - wifi: ath9k: Fix possible stall on ath9k_txq_list_has_key()
+    - rtnetlink: extend RTEXT_FILTER_SKIP_STATS to IFLA_VF_INFO
+    - wifi: iwlwifi: pull from TXQs with softirqs disabled
+    - wifi: cfg80211: rewrite merging of inherited elements
+    - wifi: ath9k: convert msecs to jiffies where needed
+    - netlink: fix potential deadlock in netlink_set_err()
+    - netlink: do not hard code device address lenth in fdb dumps
+    - selftests: rtnetlink: remove netdevsim device after ipsec offload test
+    - gtp: Fix use-after-free in __gtp_encap_destroy().
+    - lib/ts_bm: reset initial match offset for every block of text
+    - netfilter: conntrack: dccp: copy entire header to stack buffer, not just
+      basic one
+    - netfilter: nf_conntrack_sip: fix the ct_sip_parse_numerical_param() return
+      value.
+    - ipvlan: Fix return value of ipvlan_queue_xmit()
+    - netlink: Add __sock_i_ino() for __netlink_diag_dump().
+    - radeon: avoid double free in ci_dpm_init()
+    - Input: drv260x - sleep between polling GO bit
+    - ARM: dts: BCM5301X: Drop "clock-names" from the SPI node
+    - Input: adxl34x - do not hardcode interrupt trigger type
+    - drm: sun4i_tcon: use devm_clk_get_enabled in `sun4i_tcon_init_clocks`
+    - RDMA/bnxt_re: Fix to remove an unnecessary log
+    - ARM: dts: gta04: Move model property out of pinctrl node
+    - arm64: dts: qcom: msm8916: correct camss unit address
+    - drm/panel: simple: fix active size for Ampire AM-480272H3TMQW-T01H
+    - ARM: ep93xx: fix missing-prototype warnings
+    - memory: brcmstb_dpfe: fix testing array offset after use
+    - ASoC: es8316: Increment max value for ALC Capture Target Volume control
+    - ASoC: es8316: Do not set rate constraints for unsupported MCLKs
+    - soc/fsl/qe: fix usb.c build errors
+    - IB/hfi1: Fix sdma.h tx->num_descs off-by-one errors
+    - arm64: dts: renesas: ulcb-kf: Remove flow control for SCIF1
+    - fbdev: omapfb: lcd_mipid: Fix an error handling path in mipid_spi_probe()
+    - drm/amdkfd: Fix potential deallocation of previously deallocated memory.
+    - drm/radeon: fix possible division-by-zero errors
+    - clk: tegra: tegra124-emc: Fix potential memory leak
+    - ALSA: ac97: Fix possible NULL dereference in snd_ac97_mixer
+    - clk: cdce925: check return value of kasprintf()
+    - clk: keystone: sci-clk: check return value of kasprintf()
+    - ASoC: imx-audmix: check return value of devm_kasprintf()
+    - scsi: qedf: Fix NULL dereference in error handling
+    - PCI/ASPM: Disable ASPM on MFD function removal to avoid use-after-free
+    - scsi: 3w-xxxx: Add error handling for initialization failure in tw_probe()
+    - PCI: pciehp: Cancel bringup sequence if card is not present
+    - PCI: ftpci100: Release the clock resources
+    - PCI: Add pci_clear_master() stub for non-CONFIG_PCI
+    - pinctrl: cherryview: Return correct value if pin in push-pull mode
+    - perf dwarf-aux: Fix off-by-one in die_get_varname()
+    - pinctrl: at91-pio4: check return value of devm_kasprintf()
+    - powerpc/mm/dax: Fix the condition when checking if altmap vmemap can cross-
+      boundary
+    - hwrng: virtio - add an internal buffer
+    - hwrng: virtio - don't wait on cleanup
+    - hwrng: virtio - don't waste entropy
+    - hwrng: virtio - always add a pending request
+    - hwrng: virtio - Fix race on data_avail and actual data
+    - crypto: nx - fix build warnings when DEBUG_FS is not enabled
+    - modpost: fix section mismatch message for R_ARM_ABS32
+    - modpost: fix section mismatch message for R_ARM_{PC24,CALL,JUMP24}
+    - crypto: marvell/cesa - Fix type mismatch warning
+    - modpost: fix off by one in is_executable_section()
+    - ARC: define ASM_NL and __ALIGN(_STR) outside #ifdef __ASSEMBLY__ guard
+    - NFSv4.1: freeze the session table upon receiving NFS4ERR_BADSESSION
+    - hwrng: st - Fix W=1 unused variable warning
+    - hwrng: st - keep clock enabled while hwrng is registered
+    - USB: serial: option: add LARA-R6 01B PIDs
+    - usb: dwc3: gadget: Propagate core init errors to UDC during pullup
+    - block: fix signed int overflow in Amiga partition support
+    - block: change all __u32 annotations to __be32 in affs_hardblocks.h
+    - w1: fix loop in w1_fini()
+    - sh: j2: Use ioremap() to translate device tree address into kernel memory
+    - media: usb: Check az6007_read() return value
+    - media: videodev2.h: Fix struct v4l2_input tuner index comment
+    - usb: dwc3: qcom: Fix potential memory leak
+    - extcon: Fix kernel doc of property fields to avoid warnings
+    - extcon: Fix kernel doc of property capability fields to avoid warnings
+    - usb: phy: phy-tahvo: fix memory leak in tahvo_usb_probe()
+    - usb: hide unused usbfs_notify_suspend/resume functions
+    - mfd: rt5033: Drop rt5033-battery sub-device
+    - KVM: s390: fix KVM_S390_GET_CMMA_BITS for GFNs in memslot holes
+    - usb: dwc3: qcom: Release the correct resources in dwc3_qcom_remove()
+    - mfd: intel-lpss: Add missing check for platform_get_resource
+    - serial: 8250_omap: Use force_suspend and resume for system suspend
+    - mfd: stmfx: Fix error path in stmfx_chip_init
+    - KVM: s390: vsie: fix the length of APCB bitmap
+    - mfd: stmpe: Only disable the regulators if they are enabled
+    - pwm: imx-tpm: force 'real_period' to be zero in suspend
+    - pwm: sysfs: Do not apply state to already disabled PWMs
+    - rtc: st-lpc: Release some resources in st_rtc_probe() in case of error
+    - sctp: fix potential deadlock on &net->sctp.addr_wq_lock
+    - Add MODULE_FIRMWARE() for FIRMWARE_TG357766.
+    - spi: bcm-qspi: return error if neither hif_mspi nor mspi is available
+    - mailbox: ti-msgmgr: Fill non-message tx data fields with 0x0
+    - f2fs: fix error path handling in truncate_dnode()
+    - powerpc: allow PPC_EARLY_DEBUG_CPM only when SERIAL_CPM=y
+    - net: bridge: keep ports without IFF_UNICAST_FLT in BR_PROMISC mode
+    - tcp: annotate data races in __tcp_oow_rate_limited()
+    - xsk: Improve documentation for AF_XDP
+    - xsk: Honor SO_BINDTODEVICE on bind
+    - net/sched: act_pedit: Add size check for TCA_PEDIT_PARMS_EX
+    - net: dsa: tag_sja1105: fix MAC DA patching from meta frames
+    - sh: dma: Fix DMA channel offset calculation
+    - i2c: xiic: Defer xiic_wakeup() and __xiic_start_xfer() in xiic_process()
+    - i2c: xiic: Don't try to handle more interrupt events after error
+    - ALSA: jack: Fix mutex call in snd_jack_report()
+    - NFSD: add encoding of op_recall flag for write delegation
+    - mmc: core: disable TRIM on Kingston EMMC04G-M627
+    - mmc: core: disable TRIM on Micron MTFC4GACAJCN-1M
+    - mmc: sdhci: fix DMA configure compatibility issue when 64bit DMA mode is
+      used.
+    - bcache: Remove unnecessary NULL point check in node allocations
+    - integrity: Fix possible multiple allocation in integrity_inode_get()
+    - jffs2: reduce stack usage in jffs2_build_xattr_subsystem()
+    - fs: avoid empty option when generating legacy mount string
+    - ext4: Remove ext4 locking of moved directory
+    - Revert "f2fs: fix potential corruption when moving a directory"
+    - fs: Establish locking order for unrelated directories
+    - fs: Lock moved directories
+    - btrfs: fix race when deleting quota root from the dirty cow roots list
+    - ARM: orion5x: fix d2net gpio initialization
+    - fs: no need to check source
+    - fanotify: disallow mount/sb marks on kernel internal pseudo fs
+    - block: add overflow checks for Amiga partition support
+    - netfilter: nf_tables: fix nat hook table deletion
+    - netfilter: nftables: add helper function to set the base sequence number
+    - netfilter: add helper function to set up the nfnetlink header and use it
+    - netfilter: nf_tables: use net_generic infra for transaction data
+    - netfilter: nf_tables: add rescheduling points during loop detection walks
+    - netfilter: nf_tables: add NFT_TRANS_PREPARE_ERROR to deal with bound
+      set/chain
+    - netfilter: nf_tables: reject unbound anonymous set before commit phase
+    - netfilter: nf_tables: unbind non-anonymous set if rule construction fails
+    - netfilter: nf_tables: fix scheduling-while-atomic splat
+    - netfilter: conntrack: Avoid nf_ct_helper_hash uses after free
+    - tty: serial: fsl_lpuart: add earlycon for imx8ulp platform
+    - block/partition: fix signedness issue for Amiga partitions
+    - net: lan743x: Don't sleep in atomic context
+    - workqueue: clean up WORK_* constant types, clarify masking
+    - drm/panel: Initialise panel dev and funcs through drm_panel_init()
+    - drm/panel: Add and fill drm_panel type field
+    - drm/panel: simple: Add connector_type for innolux_at043tn24
+    - igc: Remove delay during TX ring configuration
+    - igc: set TP bit in 'supported' and 'advertising' fields of
+      ethtool_link_ksettings
+    - scsi: qla2xxx: Fix error code in qla2x00_start_sp()
+    - net: mvneta: fix txq_map in case of txq_number==1
+    - ionic: improve irq numa locality
+    - ionic: clean irq affinity on queue deinit
+    - ionic: move irq request to qcq alloc
+    - ionic: ionic_intr_free parameter change
+    - ionic: remove WARN_ON to prevent panic_on_warn
+    - icmp6: Fix null-ptr-deref of ip6_null_entry->rt6i_idev in icmp6_dev().
+    - udp6: fix udp6_ehashfn() typo
+    - ntb: idt: Fix error handling in idt_pci_driver_init()
+    - NTB: amd: Fix error handling in amd_ntb_pci_driver_init()
+    - ntb: intel: Fix error handling in intel_ntb_pci_driver_init()
+    - NTB: ntb_transport: fix possible memory leak while device_register() fails
+    - NTB: ntb_tool: Add check for devm_kcalloc
+    - ipv6/addrconf: fix a potential refcount underflow for idev
+    - platform/x86: wmi: Replace UUID redefinitions by their originals
+    - platform/x86: wmi: Fix indentation in some cases
+    - platform/x86: wmi: remove unnecessary argument
+    - platform/x86: wmi: use guid_t and guid_equal()
+    - platform/x86: wmi: move variables
+    - platform/x86: wmi: Break possible infinite loop when parsing GUID
+    - erofs: avoid infinite loop in z_erofs_do_read_page() when reading beyond EOF
+    - wifi: airo: avoid uninitialized warning in airo_get_rate()
+    - cls_flower: Add extack support for src and dst port range options
+    - net/sched: flower: Ensure both minimum and maximum ports are specified
+    - net/sched: make psched_mtu() RTNL-less safe
+    - pinctrl: amd: Fix mistake in handling clearing pins at startup
+    - pinctrl: amd: Detect internal GPIO0 debounce handling
+    - pinctrl: amd: Only use special debounce behavior for GPIO 0
+    - tpm: tpm_vtpm_proxy: fix a race condition in /dev/vtpmx creation
+    - mtd: rawnand: meson: fix unaligned DMA buffers handling
+    - net: bcmgenet: Ensure MDIO unregistration has clocks enabled
+    - powerpc: Fail build if using recordmcount with binutils v2.37
+    - misc: fastrpc: Create fastrpc scalar with correct buffer count
+    - SUNRPC: Fix UAF in svc_tcp_listen_data_ready()
+    - erofs: fix compact 4B support for 16k block size
+    - ext4: fix wrong unit use in ext4_mb_clear_bb
+    - ext4: only update i_reserved_data_blocks on successful block allocation
+    - jfs: jfs_dmap: Validate db_l2nbperpage while mounting
+    - PCI/PM: Avoid putting EloPOS E2/S2/H2 PCIe Ports in D3cold
+    - PCI: Add function 1 DMA alias quirk for Marvell 88SE9235
+    - PCI: qcom: Disable write access to read only registers for IP v2.3.3
+    - PCI: rockchip: Assert PCI Configuration Enable bit after probe
+    - PCI: rockchip: Write PCI Device ID to correct register
+    - PCI: rockchip: Add poll and timeout to wait for PHY PLLs to be locked
+    - PCI: rockchip: Fix legacy IRQ generation for RK3399 PCIe endpoint core
+    - PCI: rockchip: Use u32 variable to access 32-bit registers
+    - PCI: rockchip: Set address alignment for endpoint mode
+    - misc: pci_endpoint_test: Free IRQs before removing the device
+    - misc: pci_endpoint_test: Re-init completion for every test
+    - md/raid0: add discard support for the 'original' layout
+    - fs: dlm: return positive pid value for F_GETLK
+    - drm/atomic: Allow vblank-enabled + self-refresh "disable"
+    - drm/rockchip: vop: Leave vblank enabled in self-refresh
+    - serial: atmel: don't enable IRQs prematurely
+    - firmware: stratix10-svc: Fix a potential resource leak in
+      svc_create_memory_pool()
+    - hwrng: imx-rngc - fix the timeout for init and self check
+    - ceph: don't let check_caps skip sending responses for revoke msgs
+    - meson saradc: fix clock divider mask length
+    - Revert "8250: add support for ASIX devices with a FIFO bug"
+    - tty: serial: samsung_tty: Fix a memory leak in s3c24xx_serial_getclk() in
+      case of error
+    - tty: serial: samsung_tty: Fix a memory leak in s3c24xx_serial_getclk() when
+      iterating clk
+    - tracing/histograms: Add histograms to hist_vars if they have referenced
+      variables
+    - ring-buffer: Fix deadloop issue on reading trace_pipe
+    - xtensa: ISS: fix call to split_if_spec
+    - tracing: Fix null pointer dereference in tracing_err_log_open()
+    - tracing/probes: Fix not to count error code to total length
+    - scsi: qla2xxx: Wait for io return on terminate rport
+    - scsi: qla2xxx: Fix potential NULL pointer dereference
+    - scsi: qla2xxx: Check valid rport returned by fc_bsg_to_rport()
+    - scsi: qla2xxx: Correct the index of array
+    - scsi: qla2xxx: Pointer may be dereferenced
+    - scsi: qla2xxx: Remove unused nvme_ls_waitq wait queue
+    - drm/atomic: Fix potential use-after-free in nonblocking commits
+    - perf probe: Add test for regression introduced by switch to
+      die_get_decl_file()
+    - btrfs: fix warning when putting transaction with qgroups enabled after abort
+    - fuse: revalidate: don't invalidate if interrupted
+    - selftests: tc: set timeout to 15 minutes
+    - can: bcm: Fix UAF in bcm_proc_show()
+    - drm/client: Fix memory leak in drm_client_target_cloned
+    - drm/client: Fix memory leak in drm_client_modeset_probe
+    - ext4: correct inline offset when handling xattrs in inode body
+    - debugobjects: Recheck debug_objects_enabled before reporting
+    - nbd: Add the maximum limit of allocated index in nbd_dev_add
+    - md: fix data corruption for raid456 when reshape restart while grow up
+    - md/raid10: prevent soft lockup while flush writes
+    - posix-timers: Ensure timer ID search-loop limit is valid
+    - arm64: mm: fix VA-range sanity check
+    - sched/fair: Don't balance task to its current running CPU
+    - bpf: Address KCSAN report on bpf_lru_list
+    - devlink: report devlink_port_type_warn source device
+    - wifi: wext-core: Fix -Wstringop-overflow warning in
+      ioctl_standard_iw_point()
+    - wifi: iwlwifi: mvm: avoid baid size integer overflow
+    - igb: Fix igb_down hung on surprise removal
+    - spi: bcm63xx: fix max prepend length
+    - fbdev: imxfb: warn about invalid left/right margin
+    - pinctrl: amd: Use amd_pinconf_set() for all config options
+    - net: ethernet: ti: cpsw_ale: Fix cpsw_ale_get_field()/cpsw_ale_set_field()
+    - iavf: Fix use-after-free in free_netdev
+    - net:ipv6: check return value of pskb_trim()
+    - Revert "tcp: avoid the lookup process failing to get sk in ehash table"
+    - fbdev: au1200fb: Fix missing IRQ check in au1200fb_drv_probe
+    - llc: Don't drop packet from non-root netns.
+    - netfilter: nf_tables: fix spurious set element insertion failure
+    - netfilter: nf_tables: can't schedule in nft_chain_validate
+    - tcp: annotate data-races around tp->tcp_tx_delay
+    - net: Replace the limit of TCP_LINGER2 with TCP_FIN_TIMEOUT_MAX
+    - tcp: annotate data-races around tp->linger2
+    - tcp: annotate data-races around rskq_defer_accept
+    - tcp: annotate data-races around tp->notsent_lowat
+    - tcp: annotate data-races around fastopenq.max_qlen
+    - tracing/histograms: Return an error if we fail to add histogram to hist_vars
+      list
+    - Linux 5.4.251
+
+  * Focal update: v5.4.250 upstream stable release (LP: #2033297)
+    - x86/microcode/AMD: Load late on both threads too
+    - Linux 5.4.250
+
+  * Focal update: v5.4.249 upstream stable release (LP: #2033278)
+    - nilfs2: reject devices with insufficient block count
+    - mm: rewrite wait_on_page_bit_common() logic
+    - list: add "list_del_init_careful()" to go with "list_empty_careful()"
+    - epoll: ep_autoremove_wake_function should use list_del_init_careful
+    - tracing: Add tracing_reset_all_online_cpus_unlocked() function
+    - x86/purgatory: remove PGO flags
+    - tick/common: Align tick period during sched_timer setup
+    - media: dvbdev: Fix memleak in dvb_register_device
+    - media: dvbdev: fix error logic at dvb_register_device()
+    - media: dvb-core: Fix use-after-free due to race at dvb_register_device()
+    - nilfs2: fix buffer corruption due to concurrent device reads
+    - Drivers: hv: vmbus: Fix vmbus_wait_for_unload() to scan present CPUs
+    - PCI: hv: Fix a race condition bug in hv_pci_query_relations()
+    - cgroup: Do not corrupt task iteration when rebinding subsystem
+    - mmc: meson-gx: remove redundant mmc_request_done() call from irq context
+    - ip_tunnels: allow VXLAN/GENEVE to inherit TOS/TTL from VLAN
+    - writeback: fix dereferencing NULL mapping->host on writeback_page_template
+    - nilfs2: prevent general protection fault in nilfs_clear_dirty_page()
+    - cifs: Clean up DFS referral cache
+    - cifs: Get rid of kstrdup_const()'d paths
+    - cifs: Introduce helpers for finding TCP connection
+    - cifs: Merge is_path_valid() into get_normalized_path()
+    - cifs: Fix potential deadlock when updating vol in cifs_reconnect()
+    - x86/mm: Avoid using set_pgd() outside of real PGD pages
+    - ieee802154: hwsim: Fix possible memory leaks
+    - xfrm: Linearize the skb after offloading if needed.
+    - net: qca_spi: Avoid high load if QCA7000 is not available
+    - mmc: mtk-sd: fix deferred probing
+    - mmc: mvsdio: convert to devm_platform_ioremap_resource
+    - mmc: mvsdio: fix deferred probing
+    - mmc: omap: fix deferred probing
+    - mmc: omap_hsmmc: fix deferred probing
+    - mmc: sdhci-acpi: fix deferred probing
+    - mmc: sh_mmcif: fix deferred probing
+    - mmc: usdhi60rol0: fix deferred probing
+    - ipvs: align inner_mac_header for encapsulation
+    - net: dsa: mt7530: fix trapping frames on non-MT7621 SoC MT7530 switch
+    - be2net: Extend xmit workaround to BE3 chip
+    - netfilter: nf_tables: disallow element updates of bound anonymous sets
+    - netfilter: nfnetlink_osf: fix module autoload
+    - Revert "net: phy: dp83867: perform soft reset and retain established link"
+    - sch_netem: acquire qdisc lock in netem_change()
+    - scsi: target: iscsi: Prevent login threads from racing between each other
+    - HID: wacom: Add error check to wacom_parse_and_register()
+    - arm64: Add missing Set/Way CMO encodings
+    - media: cec: core: don't set last_initiator if tx in progress
+    - nfcsim.c: Fix error checking for debugfs_create_dir
+    - usb: gadget: udc: fix NULL dereference in remove()
+    - s390/cio: unregister device when the only path is gone
+    - ASoC: nau8824: Add quirk to active-high jack-detect
+    - ARM: dts: Fix erroneous ADS touchscreen polarities
+    - drm/exynos: vidi: fix a wrong error return
+    - drm/exynos: fix race condition UAF in exynos_g2d_exec_ioctl
+    - drm/radeon: fix race condition UAF in radeon_gem_set_domain_ioctl
+    - x86/apic: Fix kernel panic when booting with intremap=off and x2apic_phys
+    - i2c: imx-lpi2c: fix type char overflow issue when calculating the clock
+      cycle
+    - mm: fix VM_BUG_ON(PageTail) and BUG_ON(PageWriteback)
+    - mm: make wait_on_page_writeback() wait for multiple pending writebacks
+    - Linux 5.4.249
+
+  * allow io_uring to be disabled in runtime (LP: #2035116)
+    - io_uring: add a sysctl to disable io_uring system-wide
+
+  * CVE-2023-31083
+    - Bluetooth: hci_ldisc: check HCI_UART_PROTO_READY flag in HCIUARTGETPROTO
+
+  * CVE-2023-4132
+    - media: usb: siano: Fix warning due to null work_func_t function pointer
+
+  * CVE-2023-3772
+    - xfrm: add NULL check in xfrm_update_ae_params
+
+  * CVE-2023-0597
+    - random32: add noise from network and scheduling activity
+    - x86/kasan: Map shadow for percpu pages on demand
+    - x86/mm: Randomize per-cpu entry area
+    - x86/mm: Recompute physical address for every page of per-CPU CEA mapping
+    - x86/mm: Populate KASAN shadow for entire per-CPU range of CPU entry area
+    - x86/mm: Do not shuffle CPU entry areas without KASLR
+
+ -- Roxana Nicolescu <roxana.nicolescu@canonical.com>  Mon, 02 Oct 2023 12:18:58 +0200
+
+linux (5.4.0-164.181) focal; urgency=medium
+
+  * focal/linux: 5.4.0-164.181 -proposed tracker (LP: #2033867)
+
+  * Please enable Renesas RZ platform serial installer (LP: #2022361)
+    - [Config] enable hihope RZ/G2M serial console
+
+  * Azure: hv_netvsc: add support for vlans in AF_PACKET mode (LP: #2030872)
+    - hv_netvsc: add support for vlans in AF_PACKET mode
+
+  * systemd mount units fail during boot, while file system is correctly mounted
+    (LP: #1837227)
+    - list: introduce list_for_each_continue()
+    - proc/mounts: add cursor
+
+  * CVE-2023-40283
+    - Bluetooth: L2CAP: Fix use-after-free in l2cap_sock_ready_cb
+
+  * CVE-2023-20588
+    - x86/bugs: Increase the x86 bugs vector size to two u32s
+    - x86/CPU/AMD: Do not leak quotient data after a division by 0
+    - x86/CPU/AMD: Fix the DIV(0) initial fix attempt
+
+  * CVE-2023-4194
+    - net: tun_chr_open(): set sk_uid from current_fsuid()
+    - net: tap_open(): set sk_uid from current_fsuid()
+
+  * CVE-2023-1206
+    - tcp: Reduce chance of collisions in inet6_hashfn().
+
+  * CVE-2021-4001
+    - bpf: Fix toctou on read-only map's constant scalar tracking
+
+  * Focal update: v5.4.248 upstream stable release (LP: #2031121)
+    - test_firmware: fix a memory leak with reqs buffer
+    - KEYS: asymmetric: Copy sig and digest in public_key_verify_signature()
+    - dasd: refactor dasd_ioctl_information
+    - s390/dasd: Use correct lock while counting channel queue length
+    - power: supply: ab8500: Fix external_power_changed race
+    - power: supply: sc27xx: Fix external_power_changed race
+    - power: supply: bq27xxx: Use mod_delayed_work() instead of cancel() +
+      schedule()
+    - ARM: dts: vexpress: add missing cache properties
+    - power: supply: Ratelimit no data debug output
+    - platform/x86: asus-wmi: Ignore WMI events with codes 0x7B, 0xC0
+    - regulator: Fix error checking for debugfs_create_dir
+    - irqchip/meson-gpio: Mark OF related data as maybe unused
+    - power: supply: Fix logic checking if system is running from battery
+    - btrfs: handle memory allocation failure in btrfs_csum_one_bio
+    - parisc: Improve cache flushing for PCXL in arch_sync_dma_for_cpu()
+    - parisc: Flush gatt writes and adjust gatt mask in parisc_agp_mask_memory()
+    - MIPS: Alchemy: fix dbdma2
+    - mips: Move initrd_start check after initrd address sanitisation.
+    - xen/blkfront: Only check REQ_FUA for writes
+    - drm:amd:amdgpu: Fix missing buffer object unlock in failure path
+    - ocfs2: fix use-after-free when unmounting read-only filesystem
+    - ocfs2: check new file size on fallocate call
+    - nios2: dts: Fix tse_mac "max-frame-size" property
+    - nilfs2: fix incomplete buffer cleanup in nilfs_btnode_abort_change_key()
+    - nilfs2: fix possible out-of-bounds segment allocation in resize ioctl
+    - kexec: support purgatories with .text.hot sections
+    - powerpc/purgatory: remove PGO flags
+    - nouveau: fix client work fence deletion race
+    - RDMA/uverbs: Restrict usage of privileged QKEYs
+    - net: usb: qmi_wwan: add support for Compal RXM-G1
+    - ALSA: hda/realtek: Add a quirk for Compaq N14JP6
+    - Remove DECnet support from kernel
+    - [Config] updateconfigs for DECNET
+    - USB: serial: option: add Quectel EM061KGL series
+    - serial: lantiq: add missing interrupt ack
+    - usb: dwc3: gadget: Reset num TRBs before giving back the request
+    - spi: spi-fsl-dspi: Remove unused chip->void_write_data
+    - spi: fsl-dspi: avoid SCK glitches with continuous transfers
+    - netfilter: nfnetlink: skip error delivery on batch in case of ENOMEM
+    - ping6: Fix send to link-local addresses with VRF.
+    - RDMA/rxe: Remove the unused variable obj
+    - RDMA/rxe: Removed unused name from rxe_task struct
+    - RDMA/rxe: Fix the use-before-initialization error of resp_pkts
+    - iavf: remove mask from iavf_irq_enable_queues()
+    - IB/uverbs: Fix to consider event queue closing also upon non-blocking mode
+    - IB/isert: Fix dead lock in ib_isert
+    - IB/isert: Fix possible list corruption in CMA handler
+    - IB/isert: Fix incorrect release of isert connection
+    - ipvlan: fix bound dev checking for IPv6 l3s mode
+    - sctp: fix an error code in sctp_sf_eat_auth()
+    - igb: fix nvm.ops.read() error handling
+    - drm/nouveau/dp: check for NULL nv_connector->native_mode
+    - drm/nouveau/kms: Don't change EDID when it hasn't actually changed
+    - drm/nouveau: add nv_encoder pointer check for NULL
+    - net/sched: cls_api: Fix lockup on flushing explicitly created chain
+    - net: lapbether: only support ethernet devices
+    - net: tipc: resize nlattr array to correct size
+    - selftests/ptp: Fix timestamp printf format for PTP_SYS_OFFSET
+    - afs: Fix vlserver probe RTT handling
+    - neighbour: Remove unused inline function neigh_key_eq16()
+    - net: Remove unused inline function dst_hold_and_use()
+    - neighbour: delete neigh_lookup_nodev as not used
+    - drm/nouveau/kms: Fix NULL pointer dereference in
+      nouveau_connector_detect_depth
+    - mmc: block: ensure error propagation for non-blk
+    - Linux 5.4.248
+
+  * Focal update: v5.4.247 upstream stable release (LP: #2030818)
+    - blk-iocost: avoid 64-bit division in ioc_timer_fn
+    - block/blk-iocost (gcc13): keep large values in a new enum
+    - i40iw: fix build warning in i40iw_manage_apbvt()
+    - i40e: fix build warnings in i40e_alloc.h
+    - spi: qup: Request DMA before enabling clocks
+    - neighbour: Replace zero-length array with flexible-array member
+    - neighbour: fix unaligned access to pneigh_entry
+    - net: dsa: lan9303: allow vid != 0 in port_fdb_{add|del} methods
+    - Bluetooth: Fix l2cap_disconnect_req deadlock
+    - Bluetooth: L2CAP: Add missing checks for invalid DCID
+    - netfilter: conntrack: fix NULL pointer dereference in nf_confirm_cthelper
+    - netfilter: ipset: Add schedule point in call_ad().
+    - rfs: annotate lockless accesses to sk->sk_rxhash
+    - rfs: annotate lockless accesses to RFS sock flow table
+    - net: sched: move rtm_tca_policy declaration to include file
+    - net: sched: fix possible refcount leak in tc_chain_tmplt_add()
+    - lib: cpu_rmap: Fix potential use-after-free in irq_cpu_rmap_release()
+    - bnxt_en: Query default VLAN before VNIC setup on a VF
+    - batman-adv: Broken sync while rescheduling delayed work
+    - Input: xpad - delete a Razer DeathAdder mouse VID/PID entry
+    - Input: psmouse - fix OOB access in Elantech protocol
+    - ALSA: hda/realtek: Add a quirk for HP Slim Desktop S01
+    - ALSA: hda/realtek: Add Lenovo P3 Tower platform
+    - drm/amdgpu: fix xclk freq on CHIP_STONEY
+    - can: j1939: j1939_sk_send_loop_abort(): improved error queue handling in
+      J1939 Socket
+    - can: j1939: change j1939_netdev_lock type to mutex
+    - can: j1939: avoid possible use-after-free when j1939_can_rx_register fails
+    - ceph: fix use-after-free bug for inodes when flushing capsnaps
+    - Bluetooth: Fix use-after-free in hci_remove_ltk/hci_remove_irk
+    - rbd: move RBD_OBJ_FLAG_COPYUP_ENABLED flag setting
+    - pinctrl: meson-axg: add missing GPIOA_18 gpio group
+    - usb: usbfs: Enforce page requirements for mmap
+    - usb: usbfs: Use consistent mmap functions
+    - bonding (gcc13): synchronize bond_{a,t}lb_xmit() types
+    - i2c: sprd: Delete i2c adapter in .remove's error path
+    - eeprom: at24: also select REGMAP
+    - ext4: only check dquot_initialize_needed() when debugging
+    - drm/atomic: Don't pollute crtc_state->mode_blob with error pointers
+    - rbd: get snapshot context after exclusive lock is ensured to be held
+    - mtd: spinand: macronix: Add support for MX35LFxGE4AD
+    - Linux 5.4.247
+
+  * CVE-2023-4128
+    - net/sched: cls_u32: No longer copy tcf_result on update to avoid use-after-
+      free
+    - net/sched: cls_fw: No longer copy tcf_result on update to avoid use-after-
+      free
+    - net/sched: cls_route: No longer copy tcf_result on update to avoid use-
+      after-free
+
+  * CVE-2023-3863
+    - nfc: llcp: simplify llcp_sock_connect() error paths
+    - net: nfc: Fix use-after-free caused by nfc_llcp_find_local
+
+  * CVE-2023-3212
+    - gfs2: Don't deref jdesc in evict
+
+ -- Roxana Nicolescu <roxana.nicolescu@canonical.com>  Fri, 01 Sep 2023 15:09:25 +0200
+
+linux (5.4.0-162.179) focal; urgency=medium
+
+  * focal/linux: 5.4.0-162.179 -proposed tracker (LP: #2031128)
+
+  * libgnutls report "trap invalid opcode" when trying to install packages over
+    https (LP: #2031093)
+    - [Config]: disable CONFIG_GDS_FORCE_MITIGATION
+
+ -- Roxana Nicolescu <roxana.nicolescu@canonical.com>  Mon, 14 Aug 2023 10:20:38 +0200
+
+linux (5.4.0-160.177) focal; urgency=medium
+
+  * focal/linux: 5.4.0-160.177 -proposed tracker (LP: #2031017)
+
+  * Fix boot test warning for log_check "CPU: 0 PID: 0 at
+    arch/x86/kernel/fpu/xstate.c:878 get_xsave_addr+0x98/0xb0" (LP: #2031022)
+    - x86/pkeys: Revert a5eff7259790 ("x86/pkeys: Add PKRU value to init_fpstate")
+
+ -- Roxana Nicolescu <roxana.nicolescu@canonical.com>  Thu, 10 Aug 2023 18:25:48 +0200
+
+linux (5.4.0-158.175) focal; urgency=medium
+
+  * focal/linux: 5.4.0-158.175 -proposed tracker (LP: #2030466)
+
+  * CVE-2022-40982
+    - x86/mm: Initialize text poking earlier
+    - x86/mm: fix poking_init() for Xen PV guests
+    - x86/mm: Use mm_alloc() in poking_init()
+    - mm: Move mm_cachep initialization to mm_init()
+    - init: Provide arch_cpu_finalize_init()
+    - x86/cpu: Switch to arch_cpu_finalize_init()
+    - ARM: cpu: Switch to arch_cpu_finalize_init()
+    - sparc/cpu: Switch to arch_cpu_finalize_init()
+    - um/cpu: Switch to arch_cpu_finalize_init()
+    - init: Remove check_bugs() leftovers
+    - init: Invoke arch_cpu_finalize_init() earlier
+    - init, x86: Move mem_encrypt_init() into arch_cpu_finalize_init()
+    - x86/fpu: Remove cpuinfo argument from init functions
+    - x86/fpu: Mark init functions __init
+    - x86/fpu: Move FPU initialization into arch_cpu_finalize_init()
+    - x86/xen: Fix secondary processors' FPU initialization
+    - x86/speculation: Add Gather Data Sampling mitigation
+    - x86/speculation: Add force option to GDS mitigation
+    - x86/speculation: Add Kconfig option for GDS
+    - KVM: Add GDS_NO support to KVM
+    - Documentation/x86: Fix backwards on/off logic about YMM support
+    - [Config]: Enable CONFIG_ARCH_HAS_CPU_FINALIZE_INIT and
+      CONFIG_GDS_FORCE_MITIGATION
+
+  * CVE-2023-3609
+    - net/sched: cls_u32: Fix reference counter leak leading to overflow
+
+  * CVE-2023-20593
+    - x86/cpu/amd: Move the errata checking functionality up
+    - x86/cpu/amd: Add a Zenbleed fix
+
+  * CVE-2023-3611
+    - net/sched: sch_qfq: account for stab overhead in qfq_enqueue
+
+  * stacked overlay file system mounts that have chroot() called against them
+    appear to be getting locked (by the kernel most likely?) (LP: #2016398)
+    - SAUCE: overlayfs: fix reference count mismatch
+
+  * Focal update: v5.4.246 upstream stable release (LP: #2028981)
+    - RDMA/efa: Fix unsupported page sizes in device
+    - RDMA/bnxt_re: Enable SRIOV VF support on Broadcom's 57500 adapter series
+    - RDMA/bnxt_re: Refactor queue pair creation code
+    - RDMA/bnxt_re: Fix return value of bnxt_re_process_raw_qp_pkt_rx
+    - iommu/rockchip: Fix unwind goto issue
+    - iommu/amd: Don't block updates to GATag if guest mode is on
+    - dmaengine: pl330: rename _start to prevent build error
+    - net/mlx5: fw_tracer, Fix event handling
+    - netrom: fix info-leak in nr_write_internal()
+    - af_packet: Fix data-races of pkt_sk(sk)->num.
+    - amd-xgbe: fix the false linkup in xgbe_phy_status
+    - mtd: rawnand: ingenic: fix empty stub helper definitions
+    - af_packet: do not use READ_ONCE() in packet_bind()
+    - tcp: deny tcp_disconnect() when threads are waiting
+    - tcp: Return user_mss for TCP_MAXSEG in CLOSE/LISTEN state if user_mss set
+    - net/sched: sch_ingress: Only create under TC_H_INGRESS
+    - net/sched: sch_clsact: Only create under TC_H_CLSACT
+    - net/sched: Reserve TC_H_INGRESS (TC_H_CLSACT) for ingress (clsact) Qdiscs
+    - net/sched: Prohibit regrafting ingress or clsact Qdiscs
+    - net: sched: fix NULL pointer dereference in mq_attach
+    - ocfs2/dlm: move BITS_TO_BYTES() to bitops.h for wider use
+    - net/netlink: fix NETLINK_LIST_MEMBERSHIPS length report
+    - udp6: Fix race condition in udp6_sendmsg & connect
+    - net: dsa: mv88e6xxx: Increase wait after reset deactivation
+    - mtd: rawnand: marvell: ensure timing values are written
+    - mtd: rawnand: marvell: don't set the NAND frequency select
+    - watchdog: menz069_wdt: fix watchdog initialisation
+    - mailbox: mailbox-test: Fix potential double-free in
+      mbox_test_message_write()
+    - ARM: 9295/1: unwind:fix unwind abort for uleb128 case
+    - media: rcar-vin: Select correct interrupt mode for V4L2_FIELD_ALTERNATE
+    - fbdev: modedb: Add 1920x1080 at 60 Hz video mode
+    - fbdev: stifb: Fix info entry in sti_struct on error path
+    - nbd: Fix debugfs_create_dir error checking
+    - ASoC: dwc: limit the number of overrun messages
+    - xfrm: Check if_id in inbound policy/secpath match
+    - ASoC: ssm2602: Add workaround for playback distortions
+    - media: dvb_demux: fix a bug for the continuity counter
+    - media: dvb-usb: az6027: fix three null-ptr-deref in az6027_i2c_xfer()
+    - media: dvb-usb-v2: ec168: fix null-ptr-deref in ec168_i2c_xfer()
+    - media: dvb-usb-v2: ce6230: fix null-ptr-deref in ce6230_i2c_master_xfer()
+    - media: dvb-usb-v2: rtl28xxu: fix null-ptr-deref in rtl28xxu_i2c_xfer
+    - media: dvb-usb: digitv: fix null-ptr-deref in digitv_i2c_xfer()
+    - media: dvb-usb: dw2102: fix uninit-value in su3000_read_mac_address
+    - media: netup_unidvb: fix irq init by register it at the end of probe
+    - media: dvb_ca_en50221: fix a size write bug
+    - media: ttusb-dec: fix memory leak in ttusb_dec_exit_dvb()
+    - media: mn88443x: fix !CONFIG_OF error by drop of_match_ptr from ID table
+    - media: dvb-core: Fix use-after-free due on race condition at dvb_net
+    - media: dvb-core: Fix use-after-free due to race condition at dvb_ca_en50221
+    - wifi: rtl8xxxu: fix authentication timeout due to incorrect RCR value
+    - ARM: dts: stm32: add pin map for CAN controller on stm32f7
+    - arm64/mm: mark private VM_FAULT_X defines as vm_fault_t
+    - scsi: core: Decrease scsi_device's iorequest_cnt if dispatch failed
+    - wifi: b43: fix incorrect __packed annotation
+    - netfilter: conntrack: define variables exp_nat_nla_policy and any_addr with
+      CONFIG_NF_NAT
+    - ALSA: oss: avoid missing-prototype warnings
+    - atm: hide unused procfs functions
+    - mailbox: mailbox-test: fix a locking issue in mbox_test_message_write()
+    - iio: adc: mxs-lradc: fix the order of two cleanup operations
+    - HID: google: add jewel USB id
+    - HID: wacom: avoid integer overflow in wacom_intuos_inout()
+    - iio: light: vcnl4035: fixed chip ID check
+    - iio: dac: mcp4725: Fix i2c_master_send() return value handling
+    - iio: dac: build ad5758 driver when AD5758 is selected
+    - net: usb: qmi_wwan: Set DTR quirk for BroadMobi BM818
+    - usb: gadget: f_fs: Add unbind event before functionfs_unbind
+    - misc: fastrpc: return -EPIPE to invocations on device removal
+    - misc: fastrpc: reject new invocations during device removal
+    - scsi: stex: Fix gcc 13 warnings
+    - ata: libata-scsi: Use correct device no in ata_find_dev()
+    - flow_dissector: work around stack frame size warning
+    - x86/boot: Wrap literal addresses in absolute_pointer()
+    - ACPI: thermal: drop an always true check
+    - gcc-12: disable '-Wdangling-pointer' warning for now
+    - eth: sun: cassini: remove dead code
+    - kernel/extable.c: use address-of operator on section symbols
+    - treewide: Remove uninitialized_var() usage
+    - lib/dynamic_debug.c: use address-of operator on section symbols
+    - wifi: rtlwifi: remove always-true condition pointed out by GCC 12
+    - mmc: vub300: fix invalid response handling
+    - tty: serial: fsl_lpuart: use UARTCTRL_TXINV to send break instead of
+      UARTCTRL_SBK
+    - selinux: don't use make's grouped targets feature yet
+    - tracing/probe: trace_probe_primary_from_call(): checked list_first_entry
+    - ext4: add EA_INODE checking to ext4_iget()
+    - ext4: set lockdep subclass for the ea_inode in ext4_xattr_inode_cache_find()
+    - ext4: disallow ea_inodes with extended attributes
+    - ext4: add lockdep annotations for i_data_sem for ea_inode's
+    - fbcon: Fix null-ptr-deref in soft_cursor
+    - test_firmware: fix the memory leak of the allocated firmware buffer
+    - regmap: Account for register length when chunking
+    - scsi: dpt_i2o: Remove broken pass-through ioctl (I2OUSERCMD)
+    - scsi: dpt_i2o: Do not process completions with invalid addresses
+    - [Config] updateconfigs for SCSI_DPT_I2O
+    - RDMA/bnxt_re: Remove set but not used variable 'dev_attr'
+    - RDMA/bnxt_re: Remove the qp from list only if the qp destroy succeeds
+    - drm/edid: Fix uninitialized variable in drm_cvt_modes()
+    - wifi: rtlwifi: 8192de: correct checking of IQK reload
+    - drm/edid: fix objtool warning in drm_cvt_modes()
+    - Linux 5.4.246
+
+  * Focal update: v5.4.245 upstream stable release (LP: #2028980)
+    - cdc_ncm: Implement the 32-bit version of NCM Transfer Block
+    - net: cdc_ncm: Deal with too low values of dwNtbOutMaxSize
+    - power: supply: bq27xxx: After charger plug in/out wait 0.5s for things to
+      stabilize
+    - power: supply: core: Refactor
+      power_supply_set_input_current_limit_from_supplier()
+    - power: supply: bq24190: Call power_supply_changed() after updating input
+      current
+    - fs: fix undefined behavior in bit shift for SB_NOUSER
+    - net/mlx5: devcom only supports 2 ports
+    - net/mlx5: Devcom, serialize devcom registration
+    - cdc_ncm: Fix the build warning
+    - io_uring: always grab lock in io_cancel_async_work()
+    - io_uring: don't drop completion lock before timer is fully initialized
+    - io_uring: have io_kill_timeout() honor the request references
+    - bluetooth: Add cmd validity checks at the start of hci_sock_ioctl()
+    - binder: fix UAF caused by faulty buffer cleanup
+    - ipv{4,6}/raw: fix output xfrm lookup wrt protocol
+    - netfilter: ctnetlink: Support offloaded conntrack entry deletion
+    - Linux 5.4.245
+
+  * Focal update: v5.4.244 upstream stable release (LP: #2028697)
+    - driver core: add a helper to setup both the of_node and fwnode of a device
+    - drm/mipi-dsi: Set the fwnode for mipi_dsi_device
+    - ARM: 9296/1: HP Jornada 7XX: fix kernel-doc warnings
+    - linux/dim: Do nothing if no time delta between samples
+    - net: Fix load-tearing on sk->sk_stamp in sock_recv_cmsgs().
+    - netfilter: conntrack: fix possible bug_on with enable_hooks=1
+    - netlink: annotate accesses to nlk->cb_running
+    - net: annotate sk->sk_err write from do_recvmmsg()
+    - net: tap: check vlan with eth_type_vlan() method
+    - net: add vlan_get_protocol_and_depth() helper
+    - net: datagram: fix data-races in datagram_poll()
+    - af_unix: Fix a data race of sk->sk_receive_queue->qlen.
+    - af_unix: Fix data races around sk->sk_shutdown.
+    - fs: hfsplus: remove WARN_ON() from hfsplus_cat_{read,write}_inode()
+    - drm/amd/display: Use DC_LOG_DC in the trasform pixel function
+    - regmap: cache: Return error in cache sync operations for REGCACHE_NONE
+    - firmware: arm_sdei: Fix sleep from invalid context BUG
+    - ACPI: EC: Fix oops when removing custom query handlers
+    - drm/tegra: Avoid potential 32-bit integer overflow
+    - ACPICA: Avoid undefined behavior: applying zero offset to null pointer
+    - ACPICA: ACPICA: check null return of ACPI_ALLOCATE_ZEROED in
+      acpi_db_display_objects
+    - wifi: brcmfmac: cfg80211: Pass the PMK in binary instead of hex
+    - ext2: Check block size validity during mount
+    - scsi: lpfc: Prevent lpfc_debugfs_lockstat_write() buffer overflow
+    - net: pasemi: Fix return type of pasemi_mac_start_tx()
+    - net: Catch invalid index in XPS mapping
+    - scsi: target: iscsit: Free cmds before session free
+    - lib: cpu_rmap: Avoid use after free on rmap->obj array entries
+    - scsi: message: mptlan: Fix use after free bug in mptlan_remove() due to race
+      condition
+    - gfs2: Fix inode height consistency check
+    - ext4: set goal start correctly in ext4_mb_normalize_request
+    - ext4: Fix best extent lstart adjustment logic in ext4_mb_new_inode_pa()
+    - f2fs: fix to drop all dirty pages during umount() if cp_error is set
+    - samples/bpf: Fix fout leak in hbm's run_bpf_prog
+    - wifi: iwlwifi: pcie: fix possible NULL pointer dereference
+    - wifi: iwlwifi: pcie: Fix integer overflow in iwl_write_to_user_buf
+    - wifi: iwlwifi: dvm: Fix memcpy: detected field-spanning write backtrace
+    - Bluetooth: L2CAP: fix "bad unlock balance" in l2cap_disconnect_rsp
+    - HID: logitech-hidpp: Don't use the USB serial for USB devices
+    - HID: logitech-hidpp: Reconcile USB and Unifying serials
+    - spi: spi-imx: fix MX51_ECSPI_* macros when cs > 3
+    - HID: wacom: generic: Set battery quirk only when we see battery data
+    - usb: typec: tcpm: fix multiple times discover svids error
+    - serial: 8250: Reinit port->pm on port specific driver unbind
+    - mcb-pci: Reallocate memory region to avoid memory overlapping
+    - sched: Fix KCSAN noinstr violation
+    - recordmcount: Fix memory leaks in the uwrite function
+    - RDMA/core: Fix multiple -Warray-bounds warnings
+    - clk: tegra20: fix gcc-7 constant overflow warning
+    - iommu/arm-smmu-v3: Acknowledge pri/event queue overflow if any
+    - Input: xpad - add constants for GIP interface numbers
+    - phy: st: miphy28lp: use _poll_timeout functions for waits
+    - mfd: dln2: Fix memory leak in dln2_probe()
+    - btrfs: replace calls to btrfs_find_free_ino with btrfs_find_free_objectid
+    - btrfs: fix space cache inconsistency after error loading it from disk
+    - ASoC: fsl_micfil: register platform component before registering cpu dai
+    - cpupower: Make TSC read per CPU for Mperf monitor
+    - af_key: Reject optional tunnel/BEET mode templates in outbound policies
+    - net: fec: Better handle pm_runtime_get() failing in .remove()
+    - ALSA: firewire-digi00x: prevent potential use after free
+    - vsock: avoid to close connected socket after the timeout
+    - serial: arc_uart: fix of_iomap leak in `arc_serial_probe`
+    - ip6_gre: Fix skb_under_panic in __gre6_xmit()
+    - ip6_gre: Make o_seqno start from 0 in native mode
+    - ip_gre, ip6_gre: Fix race condition on o_seqno in collect_md mode
+    - erspan: get the proto with the md version for collect_md
+    - net: hns3: fix sending pfc frames after reset issue
+    - net: hns3: fix reset delay time to avoid configuration timeout
+    - media: netup_unidvb: fix use-after-free at del_timer()
+    - drm/exynos: fix g2d_open/close helper function definitions
+    - net: nsh: Use correct mac_offset to unwind gso skb in nsh_gso_segment()
+    - net: bcmgenet: Remove phy_stop() from bcmgenet_netif_stop()
+    - net: bcmgenet: Restore phy_stop() depending upon suspend/close
+    - wifi: iwlwifi: mvm: don't trust firmware n_channels
+    - cassini: Fix a memory leak in the error handling path of cas_init_one()
+    - igb: fix bit_shift to be in [1..8] range
+    - vlan: fix a potential uninit-value in vlan_dev_hard_start_xmit()
+    - USB: usbtmc: Fix direction for 0-length ioctl control messages
+    - usb-storage: fix deadlock when a scsi command timeouts more than once
+    - USB: UHCI: adjust zhaoxin UHCI controllers OverCurrent bit value
+    - usb: dwc3: debugfs: Resume dwc3 before accessing registers
+    - usb: typec: altmodes/displayport: fix pin_assignment_show
+    - ALSA: hda: Fix Oops by 9.1 surround channel names
+    - ALSA: hda: Add NVIDIA codec IDs a3 through a7 to patch table
+    - ALSA: hda/realtek: Add a quirk for HP EliteDesk 805
+    - ALSA: hda/realtek: Add quirk for 2nd ASUS GU603
+    - can: j1939: recvmsg(): allow MSG_CMSG_COMPAT flag
+    - can: kvaser_pciefd: Set CAN_STATE_STOPPED in kvaser_pciefd_stop()
+    - can: kvaser_pciefd: Call request_irq() before enabling interrupts
+    - can: kvaser_pciefd: Empty SRB buffer in probe
+    - can: kvaser_pciefd: Clear listen-only bit if not explicitly requested
+    - can: kvaser_pciefd: Do not send EFLUSH command on TFD interrupt
+    - can: kvaser_pciefd: Disable interrupts in probe error path
+    - KVM: x86: do not report a vCPU as preempted outside instruction boundaries
+    - statfs: enforce statfs[64] structure initialization
+    - serial: Add support for Advantech PCI-1611U card
+    - ceph: force updating the msg pointer in non-split case
+    - tpm/tpm_tis: Disable interrupts for more Lenovo devices
+    - powerpc/64s/radix: Fix soft dirty tracking
+    - nilfs2: fix use-after-free bug of nilfs_root in nilfs_evict_inode()
+    - netfilter: nftables: add nft_parse_register_load() and use it
+    - netfilter: nftables: add nft_parse_register_store() and use it
+    - netfilter: nftables: statify nft_parse_register()
+    - netfilter: nf_tables: validate registers coming from userspace.
+    - netfilter: nf_tables: add nft_setelem_parse_key()
+    - netfilter: nf_tables: allow up to 64 bytes in the set element data area
+    - netfilter: nf_tables: stricter validation of element data
+    - netfilter: nf_tables: validate NFTA_SET_ELEM_OBJREF based on NFT_SET_OBJECT
+      flag
+    - netfilter: nf_tables: hold mutex on netns pre_exit path
+    - HID: wacom: Force pen out of prox if no events have been received in a while
+    - HID: wacom: Add new Intuos Pro Small (PTH-460) device IDs
+    - HID: wacom: add three styli to wacom_intuos_get_tool_type
+    - lib/string_helpers: Introduce string_upper() and string_lower() helpers
+    - usb: gadget: u_ether: Convert prints to device prints
+    - usb: gadget: u_ether: Fix host MAC address case
+    - vc_screen: rewrite vcs_size to accept vc, not inode
+    - vc_screen: reload load of struct vc_data pointer in vcs_write() to avoid UAF
+    - s390/qdio: get rid of register asm
+    - s390/qdio: fix do_sqbs() inline assembly constraint
+    - watchdog: sp5100_tco: Immediately trigger upon starting.
+    - spi: fsl-spi: Re-organise transfer bits_per_word adaptation
+    - spi: fsl-cpm: Use 16 bit mode for large transfers with even size
+    - mt76: mt7615: Fix build with older compilers
+    - ALSA: hda/ca0132: add quirk for EVGA X299 DARK
+    - ALSA: hda/realtek: Enable headset onLenovo M70/M90
+    - m68k: Move signal frame following exception on 68020/030
+    - parisc: Handle kgdb breakpoints only in kernel context
+    - parisc: Allow to reboot machine after system halt
+    - gpio: mockup: Fix mode of debugfs files
+    - btrfs: use nofs when cleaning up aborted transactions
+    - selftests/memfd: Fix unknown type name build failure
+    - parisc: Fix flush_dcache_page() for usage from irq context
+    - x86/topology: Fix erroneous smp_num_siblings on Intel Hybrid platforms
+    - debugobjects: Don't wake up kswapd from fill_pool()
+    - fbdev: udlfb: Fix endpoint check
+    - net: fix stack overflow when LRO is disabled for virtual interfaces
+    - udplite: Fix NULL pointer dereference in __sk_mem_raise_allocated().
+    - USB: core: Add routines for endpoint checks in old drivers
+    - USB: sisusbvga: Add endpoint checks
+    - media: radio-shark: Add endpoint checks
+    - net: fix skb leak in __skb_tstamp_tx()
+    - selftests: fib_tests: mute cleanup error message
+    - bpf: Fix mask generation for 32-bit narrow loads of 64-bit fields
+    - ipv6: Fix out-of-bounds access in ipv6_find_tlv()
+    - power: supply: leds: Fix blink to LED on transition
+    - power: supply: bq27xxx: Fix bq27xxx_battery_update() race condition
+    - power: supply: bq27xxx: Fix I2C IRQ race on remove
+    - power: supply: bq27xxx: Fix poll_interval handling and races on remove
+    - power: supply: sbs-charger: Fix INHIBITED bit for Status reg
+    - coresight: Fix signedness bug in tmc_etr_buf_insert_barrier_packet()
+    - xen/pvcalls-back: fix double frees with pvcalls_new_active_socket()
+    - x86/show_trace_log_lvl: Ensure stack pointer is aligned, again
+    - ASoC: Intel: Skylake: Fix declaration of enum skl_ch_cfg
+    - forcedeth: Fix an error handling path in nv_probe()
+    - net/mlx5: Fix error message when failing to allocate device memory
+    - net/mlx5: Devcom, fix error flow in mlx5_devcom_register_device
+    - 3c589_cs: Fix an error handling path in tc589_probe()
+    - Linux 5.4.244
+
+  * Focal update: v5.4.243 upstream stable release (LP: #2025387)
+    - counter: 104-quad-8: Fix race condition between FLAG and CNTR reads
+    - drm/fb-helper: set x/yres_virtual in drm_fb_helper_check_var
+    - bluetooth: Perform careful capability checks in hci_sock_ioctl()
+    - USB: serial: option: add UNISOC vendor and TOZED LT70C product
+    - iio: adc: palmas_gpadc: fix NULL dereference on rmmod
+    - ASoC: Intel: bytcr_rt5640: Add quirk for the Acer Iconia One 7 B1-750
+    - asm-generic/io.h: suppress endianness warnings for readq() and writeq()
+    - USB: dwc3: fix runtime pm imbalance on probe errors
+    - USB: dwc3: fix runtime pm imbalance on unbind
+    - perf sched: Cast PTHREAD_STACK_MIN to int as it may turn into
+      sysconf(__SC_THREAD_STACK_MIN_VALUE)
+    - staging: iio: resolver: ads1210: fix config mode
+    - debugfs: regset32: Add Runtime PM support
+    - xhci: fix debugfs register accesses while suspended
+    - MIPS: fw: Allow firmware to pass a empty env
+    - ipmi:ssif: Add send_retries increment
+    - ipmi: fix SSIF not responding under certain cond.
+    - kheaders: Use array declaration instead of char
+    - pwm: meson: Fix axg ao mux parents
+    - pwm: meson: Fix g12a ao clk81 name
+    - ring-buffer: Sync IRQ works before buffer destruction
+    - reiserfs: Add security prefix to xattr name in reiserfs_security_write()
+    - KVM: nVMX: Emulate NOPs in L2, and PAUSE if it's not intercepted
+    - i2c: omap: Fix standard mode false ACK readings
+    - Revert "ubifs: dirty_cow_znode: Fix memleak in error handling path"
+    - ubifs: Fix memleak when insert_old_idx() failed
+    - ubi: Fix return value overwrite issue in try_write_vid_and_data()
+    - ubifs: Free memory for tmpfile name
+    - selinux: fix Makefile dependencies of flask.h
+    - selinux: ensure av_permissions.h is built when needed
+    - tpm, tpm_tis: Do not skip reset of original interrupt vector
+    - erofs: stop parsing non-compact HEAD index if clusterofs is invalid
+    - erofs: fix potential overflow calculating xattr_isize
+    - drm/rockchip: Drop unbalanced obj unref
+    - drm/vgem: add missing mutex_destroy
+    - drm/probe-helper: Cancel previous job before starting new one
+    - arm64: dts: renesas: r8a77990: Remove bogus voltages from OPP table
+    - arm64: dts: renesas: r8a774c0: Remove bogus voltages from OPP table
+    - EDAC/skx: Fix overflows on the DRAM row address mapping arrays
+    - ARM: dts: qcom: ipq4019: Fix the PCI I/O port range
+    - ARM: dts: qcom: ipq8064: reduce pci IO size to 64K
+    - ARM: dts: qcom: ipq8064: Fix the PCI I/O port range
+    - media: bdisp: Add missing check for create_workqueue
+    - media: uapi: add MEDIA_BUS_FMT_METADATA_FIXED media bus format.
+    - media: av7110: prevent underflow in write_ts_to_decoder()
+    - firmware: qcom_scm: Clear download bit during reboot
+    - drm/msm: fix unbalanced pm_runtime_enable in adreno_gpu_{init, cleanup}
+    - drm/msm/adreno: Defer enabling runpm until hw_init()
+    - drm/msm/adreno: drop bogus pm_runtime_set_active()
+    - mmc: sdhci-of-esdhc: fix quirk to ignore command inhibit for data
+    - drm/lima/lima_drv: Add missing unwind goto in lima_pdev_probe()
+    - regulator: core: Consistently set mutex_owner when using
+      ww_mutex_lock_slow()
+    - regulator: core: Avoid lockdep reports when resolving supplies
+    - x86/apic: Fix atomic update of offset in reserve_eilvt_offset()
+    - media: dm1105: Fix use after free bug in dm1105_remove due to race condition
+    - media: saa7134: fix use after free bug in saa7134_finidev due to race
+      condition
+    - media: rcar_fdp1: simplify error check logic at fdp_open()
+    - media: rcar_fdp1: fix pm_runtime_get_sync() usage count
+    - media: rcar_fdp1: Make use of the helper function
+      devm_platform_ioremap_resource()
+    - media: rcar_fdp1: Fix the correct variable assignments
+    - media: rcar_fdp1: Fix refcount leak in probe and remove function
+    - media: rc: gpio-ir-recv: Fix support for wake-up
+    - regulator: stm32-pwr: fix of_iomap leak
+    - x86/ioapic: Don't return 0 from arch_dynirq_lower_bound()
+    - arm64: kgdb: Set PSTATE.SS to 1 to re-enable single-step
+    - debugobject: Prevent init race with static objects
+    - timekeeping: Split jiffies seqlock
+    - tick/sched: Use tick_next_period for lockless quick check
+    - tick/sched: Reduce seqcount held scope in tick_do_update_jiffies64()
+    - tick/sched: Optimize tick_do_update_jiffies64() further
+    - tick: Get rid of tick_period
+    - tick/common: Align tick period with the HZ tick.
+    - wifi: ath6kl: minor fix for allocation size
+    - wifi: ath9k: hif_usb: fix memory leak of remain_skbs
+    - wifi: ath5k: fix an off by one check in ath5k_eeprom_read_freq_list()
+    - wifi: ath6kl: reduce WARN to dev_dbg() in callback
+    - tools: bpftool: Remove invalid \' json escape
+    - wifi: rtw88: mac: Return the original error from rtw_pwr_seq_parser()
+    - wifi: rtw88: mac: Return the original error from rtw_mac_power_switch()
+    - scm: fix MSG_CTRUNC setting condition for SO_PASSSEC
+    - vlan: partially enable SIOCSHWTSTAMP in container
+    - net/packet: annotate accesses to po->xmit
+    - net/packet: convert po->origdev to an atomic flag
+    - net/packet: convert po->auxdata to an atomic flag
+    - scsi: target: iscsit: Fix TAS handling during conn cleanup
+    - scsi: megaraid: Fix mega_cmd_done() CMDID_INT_CMDS
+    - f2fs: handle dqget error in f2fs_transfer_project_quota()
+    - rtlwifi: Start changing RT_TRACE into rtl_dbg
+    - rtlwifi: Replace RT_TRACE with rtl_dbg
+    - wifi: rtlwifi: fix incorrect error codes in rtl_debugfs_set_write_rfreg()
+    - wifi: rtlwifi: fix incorrect error codes in rtl_debugfs_set_write_reg()
+    - bpftool: Fix bug for long instructions in program CFG dumps
+    - crypto: drbg - make drbg_prepare_hrng() handle jent instantiation errors
+    - crypto: drbg - Only fail when jent is unavailable in FIPS mode
+    - scsi: lpfc: Fix ioremap issues in lpfc_sli4_pci_mem_setup()
+    - bpf, sockmap: fix deadlocks in the sockhash and sockmap
+    - nvme: handle the persistent internal error AER
+    - nvme: fix async event trace event
+    - nvme-fcloop: fix "inconsistent {IN-HARDIRQ-W} -> {HARDIRQ-ON-W} usage"
+    - bpf, sockmap: Revert buggy deadlock fix in the sockhash and sockmap
+    - md/raid10: fix leak of 'r10bio->remaining' for recovery
+    - md/raid10: fix memleak for 'conf->bio_split'
+    - md: update the optimal I/O size on reshape
+    - md/raid10: fix memleak of md thread
+    - wifi: iwlwifi: make the loop for card preparation effective
+    - wifi: iwlwifi: mvm: check firmware response size
+    - ixgbe: Allow flow hash to be set via ethtool
+    - ixgbe: Enable setting RSS table to default values
+    - bpf: Don't EFAULT for getsockopt with optval=NULL
+    - netfilter: nf_tables: don't write table validation state without mutex
+    - ipv4: Fix potential uninit variable access bug in __ip_make_skb()
+    - netlink: Use copy_to_user() for optval in netlink_getsockopt().
+    - net: amd: Fix link leak when verifying config failed
+    - tcp/udp: Fix memleaks of sk and zerocopy skbs with TX timestamp.
+    - pstore: Revert pmsg_lock back to a normal mutex
+    - usb: host: xhci-rcar: remove leftover quirk handling
+    - fpga: bridge: fix kernel-doc parameter description
+    - iio: light: max44009: add missing OF device matching
+    - usb: gadget: udc: renesas_usb3: Fix use after free bug in
+      renesas_usb3_remove due to race condition
+    - PCI: imx6: Install the fault handler only on compatible match
+    - genirq: Add IRQF_NO_AUTOEN for request_irq/nmi()
+    - ASoC: es8316: Use IRQF_NO_AUTOEN when requesting the IRQ
+    - ASoC: es8316: Handle optional IRQ assignment
+    - linux/vt_buffer.h: allow either builtin or modular for macros
+    - spi: qup: Don't skip cleanup in remove's error path
+    - spi: fsl-spi: Fix CPM/QE mode Litte Endian
+    - vmci_host: fix a race condition in vmci_host_poll() causing GPF
+    - of: Fix modalias string generation
+    - ia64: mm/contig: fix section mismatch warning/error
+    - ia64: salinfo: placate defined-but-not-used warning
+    - scripts/gdb: bail early if there are no clocks
+    - PM: domains: Fix up terminology with parent/child
+    - scripts/gdb: bail early if there are no generic PD
+    - mtd: spi-nor: cadence-quadspi: Make driver independent of flash geometry
+    - mtd: spi-nor: cadence-quadspi: Provide a way to disable DAC mode
+    - mtd: spi-nor: cadence-quadspi: Don't initialize rx_dma_complete on failure
+    - mtd: spi-nor: cadence-quadspi: Handle probe deferral while requesting DMA
+      channel
+    - spi: cadence-quadspi: fix suspend-resume implementations
+    - uapi/linux/const.h: prefer ISO-friendly __typeof__
+    - sh: sq: Fix incorrect element size for allocating bitmap buffer
+    - usb: chipidea: fix missing goto in `ci_hdrc_probe`
+    - usb: mtu3: fix kernel panic at qmu transfer done irq handler
+    - firmware: stratix10-svc: Fix an NULL vs IS_ERR() bug in probe
+    - tty: serial: fsl_lpuart: adjust buffer length to the intended size
+    - serial: 8250: Add missing wakeup event reporting
+    - staging: rtl8192e: Fix W_DISABLE# does not work after stop/start
+    - spmi: Add a check for remove callback when removing a SPMI driver
+    - macintosh/windfarm_smu_sat: Add missing of_node_put()
+    - powerpc/mpc512x: fix resource printk format warning
+    - powerpc/wii: fix resource printk format warnings
+    - powerpc/sysdev/tsi108: fix resource printk format warnings
+    - macintosh: via-pmu-led: requires ATA to be set
+    - powerpc/rtas: use memmove for potentially overlapping buffer copy
+    - perf/core: Fix hardlockup failure caused by perf throttle
+    - RDMA/siw: Fix potential page_array out of range access
+    - RDMA/rdmavt: Delete unnecessary NULL check
+    - rtc: omap: include header for omap_rtc_power_off_program prototype
+    - RDMA/mlx4: Prevent shift wrapping in set_user_sq_size()
+    - rtc: meson-vrtc: Use ktime_get_real_ts64() to get the current time
+    - power: supply: generic-adc-battery: fix unit scaling
+    - clk: add missing of_node_put() in "assigned-clocks" property parsing
+    - RDMA/siw: Remove namespace check from siw_netdev_event()
+    - IB/hfi1: Fix SDMA mmu_rb_node not being evicted in LRU order
+    - NFSv4.1: Always send a RECLAIM_COMPLETE after establishing lease
+    - firmware: raspberrypi: Keep count of all consumers
+    - firmware: raspberrypi: Introduce devm_rpi_firmware_get()
+    - input: raspberrypi-ts: Release firmware handle when not needed
+    - Input: raspberrypi-ts - fix refcount leak in rpi_ts_probe
+    - SUNRPC: remove the maximum number of retries in call_bind_status
+    - RDMA/mlx5: Use correct device num_ports when modify DC
+    - clocksource/drivers/davinci: Avoid trailing '\n' hidden in pr_fmt()
+    - clocksource: davinci: axe a pointless __GFP_NOFAIL
+    - clocksource/drivers/davinci: Fix memory leak in davinci_timer_register when
+      init fails
+    - openrisc: Properly store r31 to pt_regs on unhandled exceptions
+    - ext4: fix use-after-free read in ext4_find_extent for bigalloc + inline
+    - leds: TI_LMU_COMMON: select REGMAP instead of depending on it
+    - dmaengine: mv_xor_v2: Fix an error code.
+    - pwm: mtk-disp: Don't check the return code of pwmchip_remove()
+    - pwm: mtk-disp: Adjust the clocks to avoid them mismatch
+    - pwm: mtk-disp: Disable shadow registers before setting backlight values
+    - phy: tegra: xusb: Add missing tegra_xusb_port_unregister for usb2_port and
+      ulpi_port
+    - dmaengine: dw-edma: Fix to change for continuous transfer
+    - dmaengine: dw-edma: Fix to enable to issue dma request on DMA processing
+    - dmaengine: at_xdmac: do not enable all cyclic channels
+    - afs: Fix updating of i_size with dv jump from server
+    - parisc: Fix argument pointer in real64_call_asm()
+    - nilfs2: do not write dirty data after degenerating to read-only
+    - nilfs2: fix infinite loop in nilfs_mdt_get_block()
+    - md/raid10: fix null-ptr-deref in raid10_sync_request
+    - mailbox: zynqmp: Fix IPI isr handling
+    - mailbox: zynqmp: Fix typo in IPI documentation
+    - wifi: rtl8xxxu: RTL8192EU always needs full init
+    - clk: rockchip: rk3399: allow clk_cifout to force clk_cifout_src to reparent
+    - scripts/gdb: fix lx-timerlist for Python3
+    - btrfs: scrub: reject unsupported scrub flags
+    - s390/dasd: fix hanging blockdevice after request requeue
+    - dm clone: call kmem_cache_destroy() in dm_clone_init() error path
+    - dm integrity: call kmem_cache_destroy() in dm_integrity_init() error path
+    - dm flakey: fix a crash with invalid table line
+    - perf auxtrace: Fix address filter entire kernel size
+    - perf intel-pt: Fix CYC timestamps after standalone CBR
+    - debugobject: Ensure pool refill (again)
+    - nohz: Add TICK_DEP_BIT_RCU
+    - tick/nohz: Fix cpu_is_hotpluggable() by checking with nohz subsystem
+    - mailbox: zynq: Switch to flexible array to simplify code
+    - mailbox: zynqmp: Fix counts of child nodes
+    - dm verity: skip redundant verity_handle_err() on I/O errors
+    - dm verity: fix error handling for check_at_most_once on FEC
+    - crypto: inside-secure - irq balance
+    - crypto: safexcel - Cleanup ring IRQ workqueues on load failure
+    - net/ncsi: clear Tx enable mode when handling a Config required AEN
+    - net/sched: cls_api: remove block_cb from driver_list before freeing
+    - sit: update dev->needed_headroom in ipip6_tunnel_bind_dev()
+    - net: dsa: mv88e6xxx: add mv88e6321 rsvd2cpu
+    - writeback: fix call of incorrect macro
+    - net/sched: act_mirred: Add carrier check
+    - rxrpc: Fix hard call timeout units
+    - ionic: remove noise from ethtool rxnfc error msg
+    - af_packet: Don't send zero-byte data in packet_sendmsg_spkt().
+    - drm/amdgpu: add a missing lock for AMDGPU_SCHED
+    - ALSA: caiaq: input: Add error handling for unsupported input methods in
+      `snd_usb_caiaq_input_init`
+    - net: dsa: mt7530: fix corrupt frames using trgmii on 40 MHz XTAL MT7621
+    - virtio_net: split free_unused_bufs()
+    - virtio_net: suppress cpu stall when free_unused_bufs
+    - perf vendor events power9: Remove UTF-8 characters from JSON files
+    - perf map: Delete two variable initialisations before null pointer checks in
+      sort__sym_from_cmp()
+    - perf symbols: Fix return incorrect build_id size in elf_read_build_id()
+    - btrfs: fix btrfs_prev_leaf() to not return the same key twice
+    - btrfs: don't free qgroup space unless specified
+    - btrfs: print-tree: parent bytenr must be aligned to sector size
+    - cifs: fix pcchunk length type in smb2_copychunk_range
+    - platform/x86: touchscreen_dmi: Add info for the Dexp Ursus KX210i
+    - inotify: Avoid reporting event with invalid wd
+    - sh: math-emu: fix macro redefined warning
+    - sh: init: use OF_EARLY_FLATTREE for early init
+    - sh: nmi_debug: fix return value of __setup handler
+    - remoteproc: stm32: Call of_node_put() on iteration error
+    - remoteproc: st: Call of_node_put() on iteration error
+    - ARM: dts: exynos: fix WM8960 clock name in Itop Elite
+    - ARM: dts: s5pv210: correct MIPI CSIS clock name
+    - f2fs: fix potential corruption when moving a directory
+    - drm/panel: otm8009a: Set backlight parent to panel device
+    - drm/amdgpu: fix an amdgpu_irq_put() issue in gmc_v9_0_hw_fini()
+    - drm/amdgpu/gfx: disable gfx9 cp_ecc_error_irq only when enabling legacy gfx
+      ras
+    - drm/amdgpu: disable sdma ecc irq only when sdma RAS is enabled in suspend
+    - HID: wacom: Set a default resolution for older tablets
+    - HID: wacom: insert timestamp to packed Bluetooth (BT) events
+    - ext4: fix WARNING in mb_find_extent
+    - ext4: avoid a potential slab-out-of-bounds in ext4_group_desc_csum
+    - ext4: fix data races when using cached status extents
+    - ext4: improve error recovery code paths in __ext4_remount()
+    - ext4: fix deadlock when converting an inline directory in nojournal mode
+    - ext4: add bounds checking in get_max_inline_xattr_value_size()
+    - ext4: bail out of ext4_xattr_ibody_get() fails for any reason
+    - ext4: remove a BUG_ON in ext4_mb_release_group_pa()
+    - ext4: fix invalid free tracking in ext4_xattr_move_to_block()
+    - tty: Prevent writing chars during tcsetattr TCSADRAIN/FLUSH
+    - serial: 8250: Fix serial8250_tx_empty() race with DMA Tx
+    - drbd: correctly submit flush bio on barrier
+    - PCI: pciehp: Use down_read/write_nested(reset_lock) to fix lockdep errors
+    - PCI: pciehp: Fix AB-BA deadlock between reset_lock and device_lock
+    - printk: declare printk_deferred_{enter,safe}() in include/linux/printk.h
+    - PM: domains: Restore comment indentation for generic_pm_domain.child_links
+    - drm/msm: Fix double pm_runtime_disable() call
+    - firmware: raspberrypi: fix possible memory leak in rpi_firmware_probe()
+    - drm/msm/adreno: Fix null ptr access in adreno_gpu_cleanup()
+    - drm/exynos: move to use request_irq by IRQF_NO_AUTOEN flag
+    - mm/page_alloc: fix potential deadlock on zonelist_update_seq seqlock
+    - drm/amd/display: Fix hang when skipping modeset
+    - Linux 5.4.243
+    - Upstream stable to v5.4.243
+
+  * Focal update: v5.4.243 upstream stable release (LP: #2025387) //
+    CVE-2023-2269
+    - dm ioctl: fix nested locking in table_clear() to remove deadlock concern
+
+  * Focal update: v5.4.242 upstream stable release (LP: #2025094)
+    - ARM: dts: rockchip: fix a typo error for rk3288 spdif node
+    - arm64: dts: meson-g12-common: specify full DMC range
+    - netfilter: br_netfilter: fix recent physdev match breakage
+    - regulator: fan53555: Explicitly include bits header
+    - virtio_net: bugfix overflow inside xdp_linearize_page()
+    - netfilter: nf_tables: fix ifdef to also consider nf_tables=m
+    - i40e: fix accessing vsi->active_filters without holding lock
+    - i40e: fix i40e_setup_misc_vector() error handling
+    - mlxfw: fix null-ptr-deref in mlxfw_mfa2_tlv_next()
+    - bpf: Fix incorrect verifier pruning due to missing register precision taints
+    - e1000e: Disable TSO on i219-LM card to increase speed
+    - f2fs: Fix f2fs_truncate_partial_nodes ftrace event
+    - Input: i8042 - add quirk for Fujitsu Lifebook A574/H
+    - selftests: sigaltstack: fix -Wuninitialized
+    - scsi: megaraid_sas: Fix fw_crash_buffer_show()
+    - scsi: core: Improve scsi_vpd_inquiry() checks
+    - net: dsa: b53: mmap: add phy ops
+    - s390/ptrace: fix PTRACE_GET_LAST_BREAK error handling
+    - nvme-tcp: fix a possible UAF when failing to allocate an io queue
+    - xen/netback: use same error messages for same errors
+    - iio: light: tsl2772: fix reading proximity-diodes from device tree
+    - nilfs2: initialize unused bytes in segment summary blocks
+    - memstick: fix memory leak if card device is never registered
+    - mmc: sdhci_am654: Set HIGH_SPEED_ENA for SDR12 and SDR25
+    - MIPS: Define RUNTIME_DISCARD_EXIT in LD script
+    - x86/purgatory: Don't generate debug info for purgatory.ro
+    - Revert "ext4: fix use-after-free in ext4_xattr_set_entry"
+    - ext4: remove duplicate definition of ext4_xattr_ibody_inline_set()
+    - ext4: fix use-after-free in ext4_xattr_set_entry
+    - udp: Call inet6_destroy_sock() in setsockopt(IPV6_ADDRFORM).
+    - tcp/udp: Call inet6_destroy_sock() in IPv6 sk->sk_destruct().
+    - inet6: Remove inet6_destroy_sock() in sk->sk_prot->destroy().
+    - dccp: Call inet6_destroy_sock() via sk->sk_destruct().
+    - sctp: Call inet6_destroy_sock() via sk->sk_destruct().
+    - xfs: fix forkoff miscalculation related to XFS_LITINO(mp)
+    - pwm: meson: Explicitly set .polarity in .get_state()
+    - iio: adc: at91-sama5d2_adc: fix an error code in at91_adc_allocate_trigger()
+    - ASN.1: Fix check for strdup() success
+    - Linux 5.4.242
+    - Upstream stable to v5.4.242
+
+  * CVE-2023-31084 // CVE-2023-31084 was assigned to this bug.
+    - media: dvb-core: Fix kernel WARNING for blocking operation in wait_event*()
+
+  * CVE-2023-3776
+    - net/sched: cls_fw: Fix improper refcount update leads to use-after-free
+
+  * CVE-2023-3268
+    - kernel/relay.c: fix read_pos error when multiple readers
+    - relayfs: fix out-of-bounds access in relay_file_read
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync update-dkms-versions helper
+    - [Packaging] resync getabis
+
+ -- Roxana Nicolescu <roxana.nicolescu@canonical.com>  Wed, 09 Aug 2023 12:45:40 +0200
+
+linux (5.4.0-156.173) focal; urgency=medium
+
+  * focal/linux: 5.4.0-156.173 -proposed tracker (LP: #2026585)
+
+  * CVE-2023-3390
+    - netfilter: nf_tables: incorrect error path handling with NFT_MSG_NEWRULE
+
+  * Focal update: v5.4.241 upstream stable release (LP: #2023930)
+    - scsi: ses: Handle enclosure with just a primary component gracefully
+    - x86/PCI: Add quirk for AMD XHCI controller that loses MSI-X state in D3hot
+    - cgroup/cpuset: Wake up cpuset_attach_wq tasks in cpuset_cancel_attach()
+    - treewide: Replace DECLARE_TASKLET() with DECLARE_TASKLET_OLD()
+    - smb3: fix problem with null cifs super block with previous patch
+    - pinctrl: amd: Use irqchip template
+    - pinctrl: amd: disable and mask interrupts on probe
+    - pinctrl: amd: Disable and mask interrupts on resume
+    - pwm: cros-ec: Explicitly set .polarity in .get_state()
+    - pwm: sprd: Explicitly set .polarity in .get_state()
+    - wifi: mac80211: fix invalid drv_sta_pre_rcu_remove calls for non-uploaded
+      sta
+    - icmp: guard against too small mtu
+    - net: don't let netpoll invoke NAPI if in xmit context
+    - sctp: check send stream number after wait_for_sndbuf
+    - ipv6: Fix an uninit variable access bug in __ip6_make_skb()
+    - gpio: davinci: Add irq chip flag to skip set wake
+    - sunrpc: only free unix grouplist after RCU settles
+    - NFSD: callback request does not use correct credential for AUTH_SYS
+    - xhci: also avoid the XHCI_ZERO_64B_REGS quirk with a passthrough iommu
+    - USB: serial: cp210x: add Silicon Labs IFS-USB-DATACABLE IDs
+    - usb: typec: altmodes/displayport: Fix configure initial pin assignment
+    - USB: serial: option: add Telit FE990 compositions
+    - USB: serial: option: add Quectel RM500U-CN modem
+    - iio: adc: ti-ads7950: Set `can_sleep` flag for GPIO chip
+    - iio: dac: cio-dac: Fix max DAC write value check for 12-bit
+    - tty: serial: sh-sci: Fix transmit end interrupt handler
+    - tty: serial: sh-sci: Fix Rx on RZ/G2L SCI
+    - tty: serial: fsl_lpuart: avoid checking for transfer complete when
+      UARTCTRL_SBK is asserted in lpuart32_tx_empty
+    - nilfs2: fix potential UAF of struct nilfs_sc_info in nilfs_segctor_thread()
+    - nilfs2: fix sysfs interface lifetime
+    - ALSA: hda/realtek: Add quirk for Clevo X370SNW
+    - perf/core: Fix the same task check in perf_event_set_output
+    - ftrace: Mark get_lock_parent_ip() __always_inline
+    - can: j1939: j1939_tp_tx_dat_new(): fix out-of-bounds memory access
+    - tracing: Free error logs of tracing instances
+    - net_sched: prevent NULL dereference if default qdisc setup failed
+    - drm/panfrost: Fix the panfrost_mmu_map_fault_addr() error path
+    - ring-buffer: Fix race while reader and writer are on the same page
+    - mm/swap: fix swap_info_struct race between swapoff and get_swap_pages()
+    - irqdomain: Look for existing mapping only once
+    - irqdomain: Refactor __irq_domain_alloc_irqs()
+    - irqdomain: Fix mapping-creation race
+    - Revert "pinctrl: amd: Disable and mask interrupts on resume"
+    - ALSA: emu10k1: fix capture interrupt handler unlinking
+    - ALSA: hda/sigmatel: add pin overrides for Intel DP45SG motherboard
+    - ALSA: i2c/cs8427: fix iec958 mixer control deactivation
+    - ALSA: firewire-tascam: add missing unwind goto in
+      snd_tscm_stream_start_duplex()
+    - ALSA: hda/sigmatel: fix S/PDIF out on Intel D*45* motherboards
+    - Bluetooth: L2CAP: Fix use-after-free in l2cap_disconnect_{req,rsp}
+    - Bluetooth: Fix race condition in hidp_session_thread
+    - btrfs: print checksum type and implementation at mount time
+    - btrfs: fix fast csum implementation detection
+    - mtdblock: tolerate corrected bit-flips
+    - mtd: rawnand: meson: fix bitmask for length in command word
+    - mtd: rawnand: stm32_fmc2: remove unsupported EDO mode
+    - niu: Fix missing unwind goto in niu_alloc_channels()
+    - qlcnic: check pci_reset_function result
+    - sctp: fix a potential overflow in sctp_ifwdtsn_skip
+    - RDMA/core: Fix GID entry ref leak when create_ah fails
+    - udp6: fix potential access to stale information
+    - net: macb: fix a memory corruption in extended buffer descriptor mode
+    - power: supply: cros_usbpd: reclassify "default case!" as debug
+    - i2c: imx-lpi2c: clean rx/tx buffers upon new message
+    - efi: sysfb_efi: Add quirk for Lenovo Yoga Book X91F/L
+    - drm: panel-orientation-quirks: Add quirk for Lenovo Yoga Book X90F
+    - verify_pefile: relax wrapper length check
+    - asymmetric_keys: log on fatal failures in PE/pkcs7
+    - ubi: Fix failure attaching when vid_hdr offset equals to (sub)page size
+    - mtd: ubi: wl: Fix a couple of kernel-doc issues
+    - ubi: Fix deadlock caused by recursively holding work_sem
+    - i2c: ocores: generate stop condition after timeout in polling mode
+    - watchdog: sbsa_wdog: Make sure the timeout programming is within the limits
+    - coresight-etm4: Fix for() loop drvdata->nr_addr_cmp range bug
+    - xfs: show the proper user quota options
+    - xfs: remove the kuid/kgid conversion wrappers
+    - xfs: add a new xfs_sb_version_has_v3inode helper
+    - xfs: only check the superblock version for dinode size calculation
+    - xfs: simplify di_flags2 inheritance in xfs_ialloc
+    - xfs: simplify a check in xfs_ioctl_setattr_check_cowextsize
+    - xfs: remove the di_version field from struct icdinode
+    - xfs: set inode size after creating symlink
+    - xfs: report corruption only as a regular error
+    - xfs: shut down the filesystem if we screw up quota reservation
+    - xfs: consider shutdown in bmapbt cursor delete assert
+    - xfs: don't reuse busy extents on extent trim
+    - xfs: force log and push AIL to clear pinned inodes when aborting mount
+    - Linux 5.4.241
+
+  * [UBUNTU 20.04] [HPS] Kernel panic with "refcount_t: underflow" in mlx5
+    driver (LP: #2019011)
+    - net/mlx5: cmdif, Avoid skipping reclaim pages if FW is not accessible
+    - net/mlx5: Fix handling of entry refcount when command is not issued to FW
+
+  * Disable hv-kvp-daemon if /dev/vmbus/hv_kvp is not present (LP: #2024900)
+    - [Packaging] disable hv-kvp-daemon if needed
+
+  * CVE-2023-35001
+    - netfilter: nf_tables: prevent OOB access in nft_byteorder_eval
+
+  * CVE-2023-32629
+    - ovl: adhere to the vfs_ vs. ovl_do_ conventions for xattrs
+
+  * CVE-2023-3141
+    - memstick: r592: Fix UAF bug in r592_remove due to race condition
+
+  * CVE-2023-3111
+    - btrfs: check return value of btrfs_commit_transaction in relocation
+    - btrfs: unset reloc control if transaction commit fails in
+      prepare_to_relocate()
+
+  * CVE-2023-3090
+    - ipvlan:Fix out-of-bounds caused by unclear skb->cb
+
+  * CVE-2023-1611
+    - btrfs: fix race between quota disable and quota assign ioctls
+
+  * CVE-2022-0168
+    - cifs: move some variables off the stack in smb2_ioctl_query_info
+    - cifs: prevent bad output lengths in smb2_ioctl_query_info()
+    - cifs: fix NULL ptr dereference in smb2_ioctl_query_info()
+
+  * CVE-2022-27672
+    - x86/speculation: Identify processors vulnerable to SMT RSB predictions
+    - KVM: x86: Mitigate the cross-thread return address predictions bug
+    - Documentation/hw-vuln: Add documentation for Cross-Thread Return Predictions
+
+  * Severe NFS performance degradation after LP #2003053 (LP: #2022098)
+    - SAUCE: Make NFS file-access stale cache behaviour opt-in
+
+  * Encountering an issue with memcpy_fromio causing failed boot of SEV-enabled
+    guest (LP: #2020319)
+    - x86/sev: Unroll string mmio with CC_ATTR_GUEST_UNROLL_STRING_IO
+
+  * Focal update: v5.4.240 upstream stable release (LP: #2023601)
+    - net: tls: fix possible race condition between do_tls_getsockopt_conf() and
+      do_tls_setsockopt_conf()
+    - power: supply: da9150: Fix use after free bug in da9150_charger_remove due
+      to race condition
+    - iavf: fix inverted Rx hash condition leading to disabled hash
+    - iavf: fix non-tunneled IPv6 UDP packet type and hashing
+    - intel/igbvf: free irq on the error path in igbvf_request_msix()
+    - igbvf: Regard vf reset nack as success
+    - i2c: imx-lpi2c: check only for enabled interrupt flags
+    - scsi: scsi_dh_alua: Fix memleak for 'qdata' in alua_activate()
+    - net: usb: smsc95xx: Limit packet length to skb->len
+    - qed/qed_sriov: guard against NULL derefs from qed_iov_get_vf_info
+    - net: qcom/emac: Fix use after free bug in emac_remove due to race condition
+    - net/ps3_gelic_net: Fix RX sk_buff length
+    - net/ps3_gelic_net: Use dma_mapping_error
+    - keys: Do not cache key in task struct if key is requested from kernel thread
+    - bpf: Adjust insufficient default bpf_jit_limit
+    - net/mlx5: Read the TC mapping of all priorities on ETS query
+    - atm: idt77252: fix kmemleak when rmmod idt77252
+    - erspan: do not use skb_mac_header() in ndo_start_xmit()
+    - net/sonic: use dma_mapping_error() for error check
+    - nvme-tcp: fix nvme_tcp_term_pdu to match spec
+    - hvc/xen: prevent concurrent accesses to the shared ring
+    - net: mdio: thunder: Add missing fwnode_handle_put()
+    - Bluetooth: btqcomsmd: Fix command timeout after setting BD address
+    - platform/chrome: cros_ec_chardev: fix kernel data leak from ioctl
+    - hwmon (it87): Fix voltage scaling for chips with 10.9mV ADCs
+    - scsi: qla2xxx: Perform lockless command completion in abort path
+    - uas: Add US_FL_NO_REPORT_OPCODES for JMicron JMS583Gen 2
+    - thunderbolt: Use const qualifier for `ring_interrupt_index`
+    - riscv: Bump COMMAND_LINE_SIZE value to 1024
+    - ca8210: fix mac_len negative array access
+    - m68k: Only force 030 bus error if PC not in exception table
+    - selftests/bpf: check that modifier resolves after pointer
+    - scsi: target: iscsi: Fix an error message in iscsi_check_key()
+    - scsi: ufs: core: Add soft dependency on governor_simpleondemand
+    - scsi: lpfc: Avoid usage of list iterator variable after loop
+    - net: usb: cdc_mbim: avoid altsetting toggling for Telit FE990
+    - net: usb: qmi_wwan: add Telit 0x1080 composition
+    - sh: sanitize the flags on sigreturn
+    - cifs: empty interface list when server doesn't support query interfaces
+    - scsi: core: Add BLIST_SKIP_VPD_PAGES for SKhynix H28U74301AMR
+    - usb: gadget: u_audio: don't let userspace block driver unbind
+    - fsverity: Remove WQ_UNBOUND from fsverity read workqueue
+    - igb: revert rtnl_lock() that causes deadlock
+    - dm thin: fix deadlock when swapping to thin device
+    - usb: cdns3: Fix issue with using incorrect PCI device function
+    - usb: chipdea: core: fix return -EINVAL if request role is the same with
+      current role
+    - usb: chipidea: core: fix possible concurrent when switch role
+    - wifi: mac80211: fix qos on mesh interfaces
+    - nilfs2: fix kernel-infoleak in nilfs_ioctl_wrap_copy()
+    - i2c: xgene-slimpro: Fix out-of-bounds bug in xgene_slimpro_i2c_xfer()
+    - dm stats: check for and propagate alloc_percpu failure
+    - dm crypt: add cond_resched() to dmcrypt_write()
+    - sched/fair: sanitize vruntime of entity being placed
+    - sched/fair: Sanitize vruntime of entity being migrated
+    - tun: avoid double free in tun_free_netdev
+    - ocfs2: fix data corruption after failed write
+    - fsverity: don't drop pagecache at end of FS_IOC_ENABLE_VERITY
+    - bus: imx-weim: fix branch condition evaluates to a garbage value
+    - md: avoid signed overflow in slot_store()
+    - ALSA: asihpi: check pao in control_message()
+    - ALSA: hda/ca0132: fixup buffer overrun at tuning_ctl_set()
+    - fbdev: tgafb: Fix potential divide by zero
+    - sched_getaffinity: don't assume 'cpumask_size()' is fully initialized
+    - fbdev: nvidia: Fix potential divide by zero
+    - fbdev: intelfb: Fix potential divide by zero
+    - fbdev: lxfb: Fix potential divide by zero
+    - fbdev: au1200fb: Fix potential divide by zero
+    - ca8210: Fix unsigned mac_len comparison with zero in ca8210_skb_tx()
+    - dma-mapping: drop the dev argument to arch_sync_dma_for_*
+    - mips: bmips: BCM6358: disable RAC flush for TP1
+    - mtd: rawnand: meson: invalidate cache on polling ECC bit
+    - scsi: megaraid_sas: Fix crash after a double completion
+    - ptp_qoriq: fix memory leak in probe()
+    - regulator: fix spelling mistake "Cant" -> "Can't"
+    - regulator: Handle deferred clk
+    - net/net_failover: fix txq exceeding warning
+    - can: bcm: bcm_tx_setup(): fix KMSAN uninit-value in vfs_write
+    - s390/vfio-ap: fix memory leak in vfio_ap device driver
+    - i40e: fix registers dump after run ethtool adapter self test
+    - bnxt_en: Fix typo in PCI id to device description string mapping
+    - net: dsa: mv88e6xxx: Enable IGMP snooping on user ports only
+    - net: mvneta: make tx buffer array agnostic
+    - pinctrl: ocelot: Fix alt mode for ocelot
+    - Input: alps - fix compatibility with -funsigned-char
+    - Input: focaltech - use explicitly signed char type
+    - cifs: prevent infinite recursion in CIFSGetDFSRefer()
+    - cifs: fix DFS traversal oops without CONFIG_CIFS_DFS_UPCALL
+    - Input: goodix - add Lenovo Yoga Book X90F to nine_bytes_report DMI table
+    - xen/netback: don't do grant copy across page boundary
+    - pinctrl: at91-pio4: fix domain name assignment
+    - NFSv4: Fix hangs when recovering open state after a server reboot
+    - ALSA: hda/conexant: Partial revert of a quirk for Lenovo
+    - ALSA: usb-audio: Fix regression on detection of Roland VS-100
+    - drm/etnaviv: fix reference leak when mmaping imported buffer
+    - btrfs: scan device in non-exclusive mode
+    - ext4: fix kernel BUG in 'ext4_write_inline_data_end()'
+    - net_sched: add __rcu annotation to netdev->qdisc
+    - net: sched: fix race condition in qdisc_graft()
+    - firmware: arm_scmi: Fix device node validation for mailbox transport
+    - gfs2: Always check inode size of inline inodes
+    - Linux 5.4.240
+
+  * Focal update: v5.4.239 upstream stable release (LP: #2023600)
+    - Linux 5.4.239
+
+  * CVE-2023-2124
+    - xfs: verify buffer contents when we skip log replay
+
+  * CVE-2020-36691
+    - netlink: limit recursion depth in policy validation
+
+  * CVE-2022-1184
+    - ext4: check if directory block is within i_size
+    - ext4: fix check for block being out of directory size
+
+  * CVE-2022-4269
+    - net: sched: extract qstats update code into functions
+    - net: sched: don't expose action qstats to skb_tc_reinsert()
+    - net/sched: act_mirred: refactor the handle of xmit
+    - net: sched: remove unused tcf_result extension
+    - net/sched: act_mirred: better wording on protection against excessive stack
+      growth
+    - act_mirred: use the backlog for nested calls to mirred ingress
+
+  * Focal update: v5.4.238 upstream stable release (LP: #2023427)
+    - ext4: fix cgroup writeback accounting with fs-layer encryption
+    - xfrm: Allow transport-mode states with AF_UNSPEC selector
+    - drm/panfrost: Don't sync rpm suspension after mmu flushing
+    - cifs: Move the in_send statistic to __smb_send_rqst()
+    - drm/meson: fix 1px pink line on GXM when scaling video overlay
+    - clk: HI655X: select REGMAP instead of depending on it
+    - docs: Correct missing "d_" prefix for dentry_operations member
+      d_weak_revalidate
+    - scsi: mpt3sas: Fix NULL pointer access in mpt3sas_transport_port_add()
+    - ALSA: hda - add Intel DG1 PCI and HDMI ids
+    - ALSA: hda - controller is in GPU on the DG1
+    - ALSA: hda: Add Alderlake-S PCI ID and HDMI codec vid
+    - ALSA: hda: Add Intel DG2 PCI ID and HDMI codec vid
+    - ALSA: hda: Match only Intel devices with CONTROLLER_IN_GPU()
+    - netfilter: nft_redir: correct value of inet type `.maxattrs`
+    - scsi: core: Fix a comment in function scsi_host_dev_release()
+    - scsi: core: Fix a procfs host directory removal regression
+    - tcp: tcp_make_synack() can be called from process context
+    - nfc: pn533: initialize struct pn533_out_arg properly
+    - ipvlan: Make skb->skb_iif track skb->dev for l3s mode
+    - i40e: Fix kernel crash during reboot when adapter is in recovery mode
+    - qed/qed_dev: guard against a possible division by zero
+    - net: tunnels: annotate lockless accesses to dev->needed_headroom
+    - net: phy: smsc: bail out in lan87xx_read_status if genphy_read_status fails
+    - nfc: st-nci: Fix use after free bug in ndlc_remove due to race condition
+    - net: usb: smsc75xx: Limit packet length to skb->len
+    - nvmet: avoid potential UAF in nvmet_req_complete()
+    - block: sunvdc: add check for mdesc_grab() returning NULL
+    - ipv4: Fix incorrect table ID in IOCTL path
+    - net: usb: smsc75xx: Move packet length check to prevent kernel panic in
+      skb_pull
+    - net/iucv: Fix size of interrupt data
+    - ethernet: sun: add check for the mdesc_grab()
+    - hwmon: (adt7475) Display smoothing attributes in correct order
+    - hwmon: (adt7475) Fix masking of hysteresis registers
+    - hwmon: (xgene) Fix use after free bug in xgene_hwmon_remove due to race
+      condition
+    - hwmon: (ina3221) return prober error code
+    - media: m5mols: fix off-by-one loop termination error
+    - mmc: atmel-mci: fix race between stop command and start of next command
+    - jffs2: correct logic when creating a hole in jffs2_write_begin
+    - ext4: fail ext4_iget if special inode unallocated
+    - ext4: fix task hung in ext4_xattr_delete_inode
+    - drm/amdkfd: Fix an illegal memory access
+    - sh: intc: Avoid spurious sizeof-pointer-div warning
+    - ext4: fix possible double unlock when moving a directory
+    - tty: serial: fsl_lpuart: skip waiting for transmission complete when
+      UARTCTRL_SBK is asserted
+    - interconnect: fix mem leak when freeing nodes
+    - tracing: Check field value in hist_field_name()
+    - tracing: Make tracepoint lockdep check actually test something
+    - ftrace: Fix invalid address access in lookup_rec() when index is 0
+    - fbdev: stifb: Provide valid pixelclock and add fb_check_var() checks
+    - x86/mm: Fix use of uninitialized buffer in sme_enable()
+    - drm/i915: Don't use stolen memory for ring buffers with LLC
+    - serial: 8250_em: Fix UART port type
+    - s390/ipl: add missing intersection check to ipl_report handling
+    - PCI: Unify delay handling for reset and resume
+    - HID: core: Provide new max_buffer_size attribute to over-ride the default
+    - HID: uhid: Over-ride the default maximum data buffer value with our own
+    - Linux 5.4.238
+
+  * Focal update: v5.4.237 upstream stable release (LP: #2023420)
+    - fs: prevent out-of-bounds array speculation when closing a file descriptor
+    - x86/CPU/AMD: Disable XSAVES on AMD family 0x17
+    - drm/connector: print max_requested_bpc in state debugfs
+    - ext4: fix RENAME_WHITEOUT handling for inline directories
+    - ext4: fix another off-by-one fsmap error on 1k block filesystems
+    - ext4: move where set the MAY_INLINE_DATA flag is set
+    - ext4: fix WARNING in ext4_update_inline_data
+    - ext4: zero i_disksize when initializing the bootloader inode
+    - nfc: change order inside nfc_se_io error path
+    - iommu/amd: Add PCI segment support for ivrs_[ioapic/hpet/acpihid] commands
+    - iommu/amd: Fix ill-formed ivrs_ioapic, ivrs_hpet and ivrs_acpihid options
+    - iommu/amd: Add a length limitation for the ivrs_acpihid command-line
+      parameter
+    - ipmi:ssif: make ssif_i2c_send() void
+    - ipmi:ssif: resend_msg() cannot fail
+    - ipmi:ssif: Remove rtc_us_timer
+    - ipmi:ssif: Increase the message retry time
+    - ipmi:ssif: Add a timer between request retries
+    - irqdomain: Change the type of 'size' in __irq_domain_add() to be consistent
+    - irqdomain: Fix domain registration race
+    - iommu/vt-d: Fix PASID directory pointer coherency
+    - SMB3: Backup intent flag missing from some more ops
+    - cifs: Fix uninitialized memory read in smb3_qfs_tcon()
+    - scsi: core: Remove the /proc/scsi/${proc_name} directory earlier
+    - ext4: Fix possible corruption when moving a directory
+    - drm/msm/a5xx: fix setting of the CP_PREEMPT_ENABLE_LOCAL register
+    - nfc: fdp: add null check of devm_kmalloc_array in
+      fdp_nci_i2c_read_device_properties
+    - ila: do not generate empty messages in ila_xlat_nl_cmd_get_mapping()
+    - selftests: nft_nat: ensuring the listening side is up before starting the
+      client
+    - net: usb: lan78xx: Remove lots of set but unused 'ret' variables
+    - net: lan78xx: fix accessing the LAN7800's internal phy specific registers
+      from the MAC driver
+    - net: caif: Fix use-after-free in cfusbl_device_notify()
+    - bnxt_en: Avoid order-5 memory allocation for TPA data
+    - netfilter: tproxy: fix deadlock due to missing BH disable
+    - btf: fix resolving BTF_KIND_VAR after ARRAY, STRUCT, UNION, PTR
+    - scsi: megaraid_sas: Update max supported LD IDs to 240
+    - net/smc: fix fallback failed while sendmsg with fastopen
+    - riscv: Use READ_ONCE_NOCHECK in imprecise unwinding stack mode
+    - ext4: Fix deadlock during directory rename
+    - MIPS: Fix a compilation issue
+    - alpha: fix R_ALPHA_LITERAL reloc for large modules
+    - macintosh: windfarm: Use unsigned type for 1-bit bitfields
+    - PCI: Add SolidRun vendor ID
+    - media: ov5640: Fix analogue gain control
+    - ipmi/watchdog: replace atomic_add() and atomic_sub()
+    - ipmi:watchdog: Set panic count to proper value on a panic
+    - drm/i915: Don't use BAR mappings for ring buffers with LLC
+    - x86, vmlinux.lds: Add RUNTIME_DISCARD_EXIT to generic DISCARDS
+    - arch: fix broken BuildID for arm64 and riscv
+    - powerpc/vmlinux.lds: Define RUNTIME_DISCARD_EXIT
+    - powerpc/vmlinux.lds: Don't discard .rela* for relocatable builds
+    - s390: define RUNTIME_DISCARD_EXIT to fix link error with GNU ld < 2.36
+    - sh: define RUNTIME_DISCARD_EXIT
+    - UML: define RUNTIME_DISCARD_EXIT
+    - s390/dasd: add missing discipline function
+    - Linux 5.4.237
+
+  * Focal update: v5.4.236 upstream stable release (LP: #2020390)
+    - staging: rtl8192e: Remove function ..dm_check_ac_dc_power calling a script
+    - staging: rtl8192e: Remove call_usermodehelper starting RadioPower.sh
+    - Linux 5.4.236
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync update-dkms-versions helper
+
+ -- Roxana Nicolescu <roxana.nicolescu@canonical.com>  Mon, 10 Jul 2023 17:38:56 +0200
+
+linux (5.4.0-153.170) focal; urgency=medium
+
+  * focal/linux: 5.4.0-153.170 -proposed tracker (LP: #2024108)
+
+  * cls_flower: off-by-one in fl_set_geneve_opt (LP: #2023577)
+    - net/sched: flower: fix possible OOB write in fl_set_geneve_opt()
+
+  * Some INVLPG implementations can leave Global translations unflushed when
+    PCIDs are enabled (LP: #2023220)
+    - x86/mm: Avoid incomplete Global INVLPG flushes
+
+ -- Thadeu Lima de Souza Cascardo <cascardo@canonical.com>  Fri, 16 Jun 2023 10:20:20 -0300
+
+linux (5.4.0-152.169) focal; urgency=medium
+
+  * focal/linux: 5.4.0-152.169 -proposed tracker (LP: #2023070)
+
+  * Focal update: v5.4.236 upstream stable release (LP: #2020390)
+    - wifi: cfg80211: Partial revert "wifi: cfg80211: Fix use after free for wext"
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync git-ubuntu-log
+    - [Packaging] resync getabis
+
+ -- Luke Nowakowski-Krijger <luke.nowakowskikrijger@canonical.com>  Tue, 06 Jun 2023 14:45:17 -0700
+
+linux (5.4.0-151.168) focal; urgency=medium
+
+  * focal/linux: 5.4.0-151.168 -proposed tracker (LP: #2019375)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update helper scripts
+    - debian/dkms-versions -- update from kernel-versions (main/2023.05.15)
+
+  * CVE-2023-32233
+    - netfilter: nf_tables: deactivate anonymous set from preparation phase
+
+  * CVE-2023-2612
+    - SAUCE: shiftfs: prevent lock unbalance in shiftfs_create_object()
+
+  * CVE-2023-31436
+    - net: sched: sch_qfq: prevent slab-out-of-bounds in qfq_activate_agg
+
+  * CVE-2023-1380
+    - wifi: brcmfmac: slab-out-of-bounds read in brcmf_get_assoc_ies()
+
+  * Focal update: Focal update: v5.4.235 upstream stable release (LP: #2017706)
+    - HID: asus: Remove check for same LED brightness on set
+    - HID: asus: use spinlock to protect concurrent accesses
+    - HID: asus: use spinlock to safely schedule workers
+    - ARM: OMAP2+: Fix memory leak in realtime_counter_init()
+    - arm64: dts: qcom: qcs404: use symbol names for PCIe resets
+    - ARM: zynq: Fix refcount leak in zynq_early_slcr_init
+    - arm64: dts: meson-gx: Fix Ethernet MAC address unit name
+    - arm64: dts: meson-g12a: Fix internal Ethernet PHY unit name
+    - arm64: dts: meson-gx: Fix the SCPI DVFS node name and unit address
+    - arm64: dts: meson: remove CPU opps below 1GHz for G12A boards
+    - ARM: OMAP1: call platform_device_put() in error case in
+      omap1_dm_timer_init()
+    - ARM: dts: exynos: correct wr-active property in Exynos3250 Rinato
+    - ARM: imx: Call ida_simple_remove() for ida_simple_get
+    - arm64: dts: amlogic: meson-gx: fix SCPI clock dvfs node name
+    - arm64: dts: amlogic: meson-axg: fix SCPI clock dvfs node name
+    - arm64: dts: amlogic: meson-gx: add missing SCPI sensors compatible
+    - arm64: dts: amlogic: meson-gx: add missing unit address to rng node name
+    - arm64: dts: amlogic: meson-gxl: add missing unit address to eth-phy-mux node
+      name
+    - arm64: dts: amlogic: meson-gxl-s905d-phicomm-n1: fix led node name
+    - ARM: dts: imx7s: correct iomuxc gpr mux controller cells
+    - arm64: dts: mediatek: mt7622: Add missing pwm-cells to pwm node
+    - Revert "scsi: core: run queue if SCSI device queue isn't ready and queue is
+      idle"
+    - block: Limit number of items taken from the I/O scheduler in one go
+    - blk-mq: remove stale comment for blk_mq_sched_mark_restart_hctx
+    - blk-mq: wait on correct sbitmap_queue in blk_mq_mark_tag_wait
+    - blk-mq: correct stale comment of .get_budget
+    - s390/dasd: Prepare for additional path event handling
+    - s390/dasd: Fix potential memleak in dasd_eckd_init()
+    - sched/deadline,rt: Remove unused parameter from pick_next_[rt|dl]_entity()
+    - sched/rt: pick_next_rt_entity(): check list_entry
+    - block: bio-integrity: Copy flags when bio_integrity_payload is cloned
+    - wifi: rsi: Fix memory leak in rsi_coex_attach()
+    - net/wireless: Delete unnecessary checks before the macro call
+      “dev_kfree_skb”
+    - wifi: iwlegacy: common: don't call dev_kfree_skb() under spin_lock_irqsave()
+    - wifi: libertas: fix memory leak in lbs_init_adapter()
+    - wifi: rtl8xxxu: don't call dev_kfree_skb() under spin_lock_irqsave()
+    - rtlwifi: fix -Wpointer-sign warning
+    - wifi: rtlwifi: Fix global-out-of-bounds bug in
+      _rtl8812ae_phy_set_txpower_limit()
+    - ipw2x00: switch from 'pci_' to 'dma_' API
+    - wifi: ipw2x00: don't call dev_kfree_skb() under spin_lock_irqsave()
+    - wifi: ipw2200: fix memory leak in ipw_wdev_init()
+    - wilc1000: let wilc_mac_xmit() return NETDEV_TX_OK
+    - wifi: wilc1000: fix potential memory leak in wilc_mac_xmit()
+    - wifi: brcmfmac: fix potential memory leak in brcmf_netdev_start_xmit()
+    - wifi: brcmfmac: unmap dma buffer in brcmf_msgbuf_alloc_pktid()
+    - wifi: libertas_tf: don't call kfree_skb() under spin_lock_irqsave()
+    - wifi: libertas: if_usb: don't call kfree_skb() under spin_lock_irqsave()
+    - wifi: libertas: main: don't call kfree_skb() under spin_lock_irqsave()
+    - wifi: libertas: cmdresp: don't call kfree_skb() under spin_lock_irqsave()
+    - wifi: wl3501_cs: don't call kfree_skb() under spin_lock_irqsave()
+    - crypto: x86/ghash - fix unaligned access in ghash_setkey()
+    - ACPICA: Drop port I/O validation for some regions
+    - genirq: Fix the return type of kstat_cpu_irqs_sum()
+    - lib/mpi: Fix buffer overrun when SG is too long
+    - ACPICA: nsrepair: handle cases without a return value correctly
+    - wifi: orinoco: check return value of hermes_write_wordrec()
+    - wifi: ath9k: htc_hst: free skb in ath9k_htc_rx_msg() if there is no callback
+      function
+    - ath9k: hif_usb: simplify if-if to if-else
+    - ath9k: htc: clean up statistics macros
+    - wifi: ath9k: hif_usb: clean up skbs if ath9k_hif_usb_rx_stream() fails
+    - wifi: ath9k: Fix potential stack-out-of-bounds write in
+      ath9k_wmi_rsp_callback()
+    - ACPI: battery: Fix missing NUL-termination with large strings
+    - crypto: ccp - Failure on re-initialization due to duplicate sysfs filename
+    - crypto: essiv - remove redundant null pointer check before kfree
+    - crypto: essiv - Handle EBUSY correctly
+    - crypto: seqiv - Handle EBUSY correctly
+    - powercap: fix possible name leak in powercap_register_zone()
+    - net/mlx5: Enhance debug print in page allocation failure
+    - irqchip/alpine-msi: Fix refcount leak in alpine_msix_init_domains
+    - irqchip/irq-mvebu-gicp: Fix refcount leak in mvebu_gicp_probe
+    - irqchip/ti-sci: Fix refcount leak in ti_sci_intr_irq_domain_probe
+    - mptcp: add sk_stop_timer_sync helper
+    - net: add sock_init_data_uid()
+    - tun: tun_chr_open(): correctly initialize socket uid
+    - tap: tap_open(): correctly initialize socket uid
+    - OPP: fix error checking in opp_migrate_dentry()
+    - Bluetooth: L2CAP: Fix potential user-after-free
+    - libbpf: Fix alen calculation in libbpf_nla_dump_errormsg()
+    - rds: rds_rm_zerocopy_callback() correct order for list_add_tail()
+    - crypto: rsa-pkcs1pad - Use akcipher_request_complete
+    - m68k: /proc/hardware should depend on PROC_FS
+    - RISC-V: time: initialize hrtimer based broadcast clock event device
+    - usb: gadget: udc: Avoid tasklet passing a global
+    - wifi: iwl3945: Add missing check for create_singlethread_workqueue
+    - wifi: iwl4965: Add missing check for create_singlethread_workqueue()
+    - wifi: mwifiex: fix loop iterator in mwifiex_update_ampdu_txwinsize()
+    - crypto: crypto4xx - Call dma_unmap_page when done
+    - wifi: mac80211: make rate u32 in sta_set_rate_info_rx()
+    - thermal/drivers/hisi: Drop second sensor hi3660
+    - can: esd_usb: Move mislocated storage of SJA1000_ECC_SEG bits in case of a
+      bus error
+    - irqchip/irq-brcmstb-l2: Set IRQ_LEVEL for level triggered interrupts
+    - irqchip/irq-bcm7120-l2: Set IRQ_LEVEL for level triggered interrupts
+    - selftests/net: Interpret UDP_GRO cmsg data as an int value
+    - drm/fourcc: Add missing big-endian XRGB1555 and RGB565 formats
+    - drm: mxsfb: DRM_MXSFB should depend on ARCH_MXS || ARCH_MXC
+    - drm/bridge: megachips: Fix error handling in i2c_register_driver()
+    - drm/vc4: dpi: Add option for inverting pixel clock and output enable
+    - drm/vc4: dpi: Fix format mapping for RGB565
+    - gpu: ipu-v3: common: Add of_node_put() for reference returned by
+      of_graph_get_port_by_id()
+    - drm/msm/hdmi: Add missing check for alloc_ordered_workqueue
+    - pinctrl: stm32: Fix refcount leak in stm32_pctrl_get_irq_domain
+    - ASoC: fsl_sai: initialize is_dsp_mode flag
+    - ALSA: hda/ca0132: minor fix for allocation size
+    - drm/mipi-dsi: Fix byte order of 16-bit DCS set/get brightness
+    - drm/msm: use strscpy instead of strncpy
+    - drm/msm/dpu: Add check for cstate
+    - drm/msm/dpu: Add check for pstates
+    - drm/exynos: Don't reset bridge->next
+    - drm/bridge: Rename bridge helpers targeting a bridge chain
+    - drm/bridge: Introduce drm_bridge_get_next_bridge()
+    - drm: Initialize struct drm_crtc_state.no_vblank from device settings
+    - drm/msm/mdp5: Add check for kzalloc
+    - gpu: host1x: Don't skip assigning syncpoints to channels
+    - drm/mediatek: remove cast to pointers passed to kfree
+    - drm/mediatek: Use NULL instead of 0 for NULL pointer
+    - drm/mediatek: Drop unbalanced obj unref
+    - drm/mediatek: Clean dangling pointer on bind error path
+    - ASoC: soc-compress.c: fixup private_data on snd_soc_new_compress()
+    - gpio: vf610: connect GPIO label to dev name
+    - hwmon: (ltc2945) Handle error case in ltc2945_value_store
+    - scsi: aic94xx: Add missing check for dma_map_single()
+    - spi: bcm63xx-hsspi: fix pm_runtime
+    - spi: bcm63xx-hsspi: Fix multi-bit mode setting
+    - hwmon: (mlxreg-fan) Return zero speed for broken fan
+    - dm: remove flush_scheduled_work() during local_exit()
+    - spi: synquacer: Fix timeout handling in synquacer_spi_transfer_one()
+    - ASoC: dapm: declare missing structure prototypes
+    - ASoC: soc-dapm.h: fixup warning struct snd_pcm_substream not declared
+    - HID: bigben: use spinlock to protect concurrent accesses
+    - HID: bigben_worker() remove unneeded check on report_field
+    - HID: bigben: use spinlock to safely schedule workers
+    - HID: asus: Only set EV_REP if we are adding a mapping
+    - HID: asus: Add report_size to struct asus_touchpad_info
+    - HID: asus: Add support for multi-touch touchpad on Medion Akoya E1239T
+    - HID: asus: Fix mute and touchpad-toggle keys on Medion Akoya E1239T
+    - hid: bigben_probe(): validate report count
+    - nfsd: fix race to check ls_layouts
+    - cifs: Fix lost destroy smbd connection when MR allocate failed
+    - cifs: Fix warning and UAF when destroy the MR list
+    - gfs2: jdata writepage fix
+    - perf llvm: Fix inadvertent file creation
+    - perf tools: Fix auto-complete on aarch64
+    - sparc: allow PM configs for sparc32 COMPILE_TEST
+    - mfd: pcf50633-adc: Fix potential memleak in pcf50633_adc_async_read()
+    - clk: qcom: gcc-qcs404: disable gpll[04]_out_aux parents
+    - clk: qcom: gcc-qcs404: fix names of the DSI clocks used as parents
+    - mtd: rawnand: sunxi: Fix the size of the last OOB region
+    - clk: renesas: cpg-mssr: Fix use after free if cpg_mssr_common_init() failed
+    - clk: renesas: cpg-mssr: Use enum clk_reg_layout instead of a boolean flag
+    - clk: renesas: cpg-mssr: Remove superfluous check in resume code
+    - Input: ads7846 - don't report pressure for ads7845
+    - Input: ads7846 - don't check penirq immediately for 7845
+    - clk: qcom: gpucc-sdm845: fix clk_dis_wait being programmed for CX GDSC
+    - powerpc/powernv/ioda: Skip unallocated resources when mapping to PE
+    - clk: Honor CLK_OPS_PARENT_ENABLE in clk_core_is_enabled()
+    - powerpc/pseries/lpar: add missing RTAS retry status handling
+    - powerpc/pseries/lparcfg: add missing RTAS retry status handling
+    - powerpc/rtas: make all exports GPL
+    - powerpc/rtas: ensure 4KB alignment for rtas_data_buf
+    - powerpc/eeh: Small refactor of eeh_handle_normal_event()
+    - powerpc/eeh: Set channel state after notifying the drivers
+    - MIPS: SMP-CPS: fix build error when HOTPLUG_CPU not set
+    - MIPS: vpe-mt: drop physical_memsize
+    - remoteproc: qcom_q6v5_mss: Use a carveout to authenticate modem headers
+    - media: platform: ti: Add missing check for devm_regulator_get
+    - powerpc: Remove linker flag from KBUILD_AFLAGS
+    - media: ov5675: Fix memleak in ov5675_init_controls()
+    - media: i2c: ov772x: Fix memleak in ov772x_probe()
+    - media: i2c: ov7670: 0 instead of -EINVAL was returned
+    - media: usb: siano: Fix use after free bugs caused by do_submit_urb
+    - rpmsg: glink: Avoid infinite loop on intent for missing channel
+    - udf: Define EFSCORRUPTED error code
+    - ARM: dts: exynos: Use Exynos5420 compatible for the MIPI video phy
+    - blk-iocost: fix divide by 0 error in calc_lcoefs()
+    - wifi: brcmfmac: Fix potential stack-out-of-bounds in brcmf_c_preinit_dcmds()
+    - rcu: Suppress smp_processor_id() complaint in
+      synchronize_rcu_expedited_wait()
+    - thermal: intel: Fix unsigned comparison with less than zero
+    - timers: Prevent union confusion from unexpected restart_syscall()
+    - x86/bugs: Reset speculation control settings on init
+    - wifi: brcmfmac: ensure CLM version is null-terminated to prevent stack-out-
+      of-bounds
+    - wifi: mt7601u: fix an integer underflow
+    - inet: fix fast path in __inet_hash_connect()
+    - ice: add missing checks for PF vsi type
+    - ACPI: Don't build ACPICA with '-Os'
+    - net: bcmgenet: Add a check for oversized packets
+    - m68k: Check syscall_trace_enter() return code
+    - wifi: mt76: dma: free rx_head in mt76_dma_rx_cleanup
+    - ACPI: video: Fix Lenovo Ideapad Z570 DMI match
+    - net/mlx5: fw_tracer: Fix debug print
+    - coda: Avoid partial allocation of sig_inputArgs
+    - uaccess: Add minimum bounds check on kernel buffer size
+    - drm/amd/display: Fix potential null-deref in dm_resume
+    - drm/omap: dsi: Fix excessive stack usage
+    - HID: Add Mapping for System Microphone Mute
+    - drm/radeon: free iio for atombios when driver shutdown
+    - drm/msm/dsi: Add missing check for alloc_ordered_workqueue
+    - docs/scripts/gdb: add necessary make scripts_gdb step
+    - ASoC: kirkwood: Iterate over array indexes instead of using pointer math
+    - regulator: max77802: Bounds check regulator id against opmode
+    - regulator: s5m8767: Bounds check id indexing into arrays
+    - hwmon: (coretemp) Simplify platform device handling
+    - pinctrl: at91: use devm_kasprintf() to avoid potential leaks
+    - drm: panel-orientation-quirks: Add quirk for Lenovo IdeaPad Duet 3 10IGL5
+    - dm thin: add cond_resched() to various workqueue loops
+    - dm cache: add cond_resched() to various workqueue loops
+    - nfsd: zero out pointers after putting nfsd_files on COPY setup error
+    - wifi: rtl8xxxu: fixing transmisison failure for rtl8192eu
+    - firmware: coreboot: framebuffer: Ignore reserved pixel color bits
+    - rtc: pm8xxx: fix set-alarm race
+    - ipmi_ssif: Rename idle state and check
+    - s390: discard .interp section
+    - s390/kprobes: fix irq mask clobbering on kprobe reenter from post_handler
+    - s390/kprobes: fix current_kprobe never cleared after kprobes reenter
+    - ARM: dts: exynos: correct HDMI phy compatible in Exynos4
+    - hfs: fix missing hfs_bnode_get() in __hfs_bnode_create
+    - fs: hfsplus: fix UAF issue in hfsplus_put_super
+    - f2fs: fix information leak in f2fs_move_inline_dirents()
+    - f2fs: fix cgroup writeback accounting with fs-layer encryption
+    - ocfs2: fix defrag path triggering jbd2 ASSERT
+    - ocfs2: fix non-auto defrag path not working issue
+    - udf: Truncate added extents on failed expansion
+    - udf: Do not bother merging very long extents
+    - udf: Do not update file length for failed writes to inline files
+    - udf: Preserve link count of system files
+    - udf: Detect system inodes linked into directory hierarchy
+    - udf: Fix file corruption when appending just after end of preallocated
+      extent
+    - KVM: Destroy target device if coalesced MMIO unregistration fails
+    - KVM: s390: disable migration mode when dirty tracking is disabled
+    - x86/virt: Force GIF=1 prior to disabling SVM (for reboot flows)
+    - x86/crash: Disable virt in core NMI crash handler to avoid double shootdown
+    - x86/reboot: Disable virtualization in an emergency if SVM is supported
+    - x86/reboot: Disable SVM, not just VMX, when stopping CPUs
+    - x86/kprobes: Fix __recover_optprobed_insn check optimizing logic
+    - x86/kprobes: Fix arch_check_optimized_kprobe check within optimized_kprobe
+      range
+    - x86/microcode/amd: Remove load_microcode_amd()'s bsp parameter
+    - x86/microcode/AMD: Add a @cpu parameter to the reloading functions
+    - x86/microcode/AMD: Fix mixed steppings support
+    - x86/speculation: Allow enabling STIBP with legacy IBRS
+    - Documentation/hw-vuln: Document the interaction between IBRS and STIBP
+    - ima: Align ima_file_mmap() parameters with mmap_file LSM hook
+    - irqdomain: Fix association race
+    - irqdomain: Fix disassociation race
+    - irqdomain: Drop bogus fwspec-mapping error handling
+    - ALSA: ice1712: Do not left ice->gpio_mutex locked in aureon_add_controls()
+    - ALSA: hda/realtek: Add quirk for HP EliteDesk 800 G6 Tower PC
+    - ext4: optimize ea_inode block expansion
+    - ext4: refuse to create ea block when umounted
+    - wifi: rtl8xxxu: Use a longer retry limit of 48
+    - wifi: cfg80211: Fix use after free for wext
+    - thermal: intel: powerclamp: Fix cur_state for multi package system
+    - dm flakey: fix logic when corrupting a bio
+    - dm flakey: don't corrupt the zero page
+    - ARM: dts: exynos: correct TMU phandle in Exynos4
+    - ARM: dts: exynos: correct TMU phandle in Odroid XU
+    - rbd: avoid use-after-free in do_rbd_add() when rbd_dev_create() fails
+    - alpha: fix FEN fault handling
+    - mips: fix syscall_get_nr
+    - media: ipu3-cio2: Fix PM runtime usage_count in driver unbind
+    - mm: memcontrol: deprecate charge moving
+    - mm/thp: check and bail out if page in deferred queue already
+    - ktest.pl: Give back console on Ctrt^C on monitor
+    - ktest.pl: Fix missing "end_monitor" when machine check fails
+    - ktest.pl: Add RUN_TIMEOUT option with default unlimited
+    - scsi: qla2xxx: Fix link failure in NPIV environment
+    - scsi: qla2xxx: Fix DMA-API call trace on NVMe LS requests
+    - scsi: qla2xxx: Fix erroneous link down
+    - scsi: ses: Don't attach if enclosure has no components
+    - scsi: ses: Fix slab-out-of-bounds in ses_enclosure_data_process()
+    - scsi: ses: Fix possible addl_desc_ptr out-of-bounds accesses
+    - scsi: ses: Fix possible desc_ptr out-of-bounds accesses
+    - scsi: ses: Fix slab-out-of-bounds in ses_intf_remove()
+    - PCI/PM: Observe reset delay irrespective of bridge_d3
+    - PCI: hotplug: Allow marking devices as disconnected during bind/unbind
+    - PCI: Avoid FLR for AMD FCH AHCI adapters
+    - drm/i915/quirks: Add inverted backlight quirk for HP 14-r206nv
+    - drm/radeon: Fix eDP for single-display iMac11,2
+    - wifi: ath9k: use proper statements in conditionals
+    - kbuild: Port silent mode detection to future gnu make.
+    - fs/jfs: fix shift exponent db_agl2size negative
+    - pwm: sifive: Reduce time the controller lock is held
+    - pwm: sifive: Always let the first pwm_apply_state succeed
+    - pwm: stm32-lp: fix the check on arr and cmp registers update
+    - f2fs: use memcpy_{to,from}_page() where possible
+    - fs: f2fs: initialize fsdata in pagecache_write()
+    - um: vector: Fix memory leak in vector_config
+    - ubi: ensure that VID header offset + VID header size <= alloc, size
+    - ubifs: Fix build errors as symbol undefined
+    - ubifs: Rectify space budget for ubifs_symlink() if symlink is encrypted
+    - ubifs: Rectify space budget for ubifs_xrename()
+    - ubifs: Fix wrong dirty space budget for dirty inode
+    - ubifs: do_rename: Fix wrong space budget when target inode's nlink > 1
+    - ubifs: Reserve one leb for each journal head while doing budget
+    - ubi: Fix use-after-free when volume resizing failed
+    - ubi: Fix unreferenced object reported by kmemleak in ubi_resize_volume()
+    - ubifs: Fix memory leak in alloc_wbufs()
+    - ubi: Fix possible null-ptr-deref in ubi_free_volume()
+    - ubifs: Re-statistic cleaned znode count if commit failed
+    - ubifs: dirty_cow_znode: Fix memleak in error handling path
+    - ubifs: ubifs_writepage: Mark page dirty after writing inode failed
+    - ubi: Fix UAF wear-leveling entry in eraseblk_count_seq_show()
+    - ubi: ubi_wl_put_peb: Fix infinite loop when wear-leveling work failed
+    - x86: um: vdso: Add '%rcx' and '%r11' to the syscall clobber list
+    - watchdog: at91sam9_wdt: use devm_request_irq to avoid missing free_irq() in
+      error path
+    - watchdog: Fix kmemleak in watchdog_cdev_register
+    - watchdog: pcwd_usb: Fix attempting to access uninitialized memory
+    - netfilter: ctnetlink: fix possible refcount leak in
+      ctnetlink_create_conntrack()
+    - ipv6: Add lwtunnel encap size of all siblings in nexthop calculation
+    - sctp: add a refcnt in sctp_stream_priorities to avoid a nested loop
+    - net: fix __dev_kfree_skb_any() vs drop monitor
+    - 9p/xen: fix version parsing
+    - 9p/xen: fix connection sequence
+    - 9p/rdma: unmap receive dma buffer in rdma_request()/post_recv()
+    - net/mlx5: Geneve, Fix handling of Geneve object id as error code
+    - nfc: fix memory leak of se_io context in nfc_genl_se_io
+    - net/sched: act_sample: fix action bind logic
+    - ARM: dts: spear320-hmi: correct STMPE GPIO compatible
+    - tcp: tcp_check_req() can be called from process context
+    - vc_screen: modify vcs_size() handling in vcs_read()
+    - rtc: sun6i: Make external 32k oscillator optional
+    - rtc: sun6i: Always export the internal oscillator
+    - scsi: ipr: Work around fortify-string warning
+    - thermal: intel: quark_dts: fix error pointer dereference
+    - thermal: intel: BXT_PMIC: select REGMAP instead of depending on it
+    - tracing: Add NULL checks for buffer in ring_buffer_free_read_page()
+    - firmware/efi sysfb_efi: Add quirk for Lenovo IdeaPad Duet 3
+    - mfd: arizona: Use pm_runtime_resume_and_get() to prevent refcnt leak
+    - media: uvcvideo: Handle cameras with invalid descriptors
+    - media: uvcvideo: Handle errors from calls to usb_string
+    - media: uvcvideo: Quirk for autosuspend in Logitech B910 and C910
+    - media: uvcvideo: Silence memcpy() run-time false positive warnings
+    - staging: emxx_udc: Add checks for dma_alloc_coherent()
+    - tty: fix out-of-bounds access in tty_driver_lookup_tty()
+    - tty: serial: fsl_lpuart: disable the CTS when send break signal
+    - mei: bus-fixup:upon error print return values of send and receive
+    - tools/iio/iio_utils:fix memory leak
+    - iio: accel: mma9551_core: Prevent uninitialized variable in
+      mma9551_read_status_word()
+    - iio: accel: mma9551_core: Prevent uninitialized variable in
+      mma9551_read_config_word()
+    - usb: host: xhci: mvebu: Iterate over array indexes instead of using pointer
+      math
+    - USB: ene_usb6250: Allocate enough memory for full object
+    - usb: uvc: Enumerate valid values for color matching
+    - kernel/fail_function: fix memory leak with using debugfs_lookup()
+    - PCI: Add ACS quirk for Wangxun NICs
+    - phy: rockchip-typec: Fix unsigned comparison with less than zero
+    - net: tls: avoid hanging tasks on the tx_lock
+    - x86/resctrl: Apply READ_ONCE/WRITE_ONCE to task_struct.{rmid,closid}
+    - x86/resctl: fix scheduler confusion with 'current'
+    - Bluetooth: hci_sock: purge socket queues in the destruct() callback
+    - SAUCE: Revert "UBUNTU: SAUCE: Fix inet_csk_listen_start after CVE-2023-0461"
+    - tcp: Fix listen() regression in 5.4.229.
+    - media: uvcvideo: Provide sync and async uvc_ctrl_status_event
+    - media: uvcvideo: Fix race condition with usb_kill_urb
+    - dt-bindings: rtc: sun6i-a31-rtc: Loosen the requirements on the clocks
+    - Linux 5.4.235
+    - [Config] Drop mxsfb for armhf:generic-lpae
+
+  * Focal update: v5.4.234 upstream stable release (LP: #2017691)
+    - arm64: dts: rockchip: drop unused LED mode property from rk3328-roc-cc
+    - ARM: dts: rockchip: add power-domains property to dp node on rk3288
+    - ACPI: NFIT: fix a potential deadlock during NFIT teardown
+    - btrfs: send: limit number of clones and allocated memory size
+    - IB/hfi1: Assign npages earlier
+    - neigh: make sure used and confirmed times are valid
+    - HID: core: Fix deadloop in hid_apply_multiplier.
+    - bpf: bpf_fib_lookup should not return neigh in NUD_FAILED state
+    - net: Remove WARN_ON_ONCE(sk->sk_forward_alloc) from sk_stream_kill_queues().
+    - vc_screen: don't clobber return value in vcs_read
+    - dmaengine: sh: rcar-dmac: Check for error num after dma_set_max_seg_size
+    - USB: serial: option: add support for VW/Skoda "Carstick LTE"
+    - USB: core: Don't hold device lock while reading the "descriptors" sysfs file
+    - Linux 5.4.234
+
+  * CVE-2023-30456
+    - KVM: nVMX: add missing consistency checks for CR0 and CR4
+
+  * CVE-2023-1859
+    - 9p/xen : Fix use after free bug in xen_9pfs_front_remove due to race
+      condition
+
+  * CVE-2023-1670
+    - xirc2ps_cs: Fix use after free bug in xirc2ps_detach
+
+ -- Roxana Nicolescu <roxana.nicolescu@canonical.com>  Fri, 12 May 2023 17:21:29 +0200
+
+linux (5.4.0-149.166) focal; urgency=medium
+
+  * focal/linux: 5.4.0-149.166 -proposed tracker (LP: #2016591)
+
+  * Focal update: v5.4.233 upstream stable release (LP: #2015909)
+    - dma-mapping: add generic helpers for mapping sgtable objects
+    - scatterlist: add generic wrappers for iterating over sgtable objects
+    - drm: etnaviv: fix common struct sg_table related issues
+    - drm/etnaviv: don't truncate physical page address
+    - wifi: rtl8xxxu: gen2: Turn on the rate control
+    - powerpc: dts: t208x: Mark MAC1 and MAC2 as 10G
+    - random: always mix cycle counter in add_latent_entropy()
+    - KVM: x86: Fail emulation during EMULTYPE_SKIP on any exception
+    - can: kvaser_usb: hydra: help gcc-13 to figure out cmd_len
+    - powerpc: dts: t208x: Disable 10G on MAC1 and MAC2
+    - alarmtimer: Prevent starvation by small intervals and SIG_IGN
+    - drm/i915/gvt: fix double free bug in split_2MB_gtt_entry
+    - mac80211: mesh: embedd mesh_paths and mpp_paths into ieee80211_if_mesh
+    - uaccess: Add speculation barrier to copy_from_user()
+    - wifi: mwifiex: Add missing compatible string for SD8787
+    - ext4: Fix function prototype mismatch for ext4_feat_ktype
+    - Revert "net/sched: taprio: make qdisc_leaf() see the per-netdev-queue pfifo
+      child qdiscs"
+    - bpf: add missing header file include
+    - Linux 5.4.233
+
+  *  selftest: fib_tests: Always cleanup before exit  (LP: #2015956)
+    - selftest: fib_tests: Always cleanup before exit
+
+  * fib_tests.sh in ubuntu_kernel_selftests was skipped silently on Focal
+    (LP: #2015440)
+    - selftests: Fix the executable permissions for fib_tests.sh
+
+  * Debian autoreconstruct Fix restoration of execute permissions (LP: #2015498)
+    - [Debian] autoreconstruct - fix restoration of execute permissions
+
+  * kernel: fix __clear_user() inline assembly constraints (LP: #2013088)
+    - s390/uaccess: add missing earlyclobber annotations to __clear_user()
+
+  * i/o error if next unused loop device is queried (LP: #1856871)
+    - loop: fix I/O error on fsync() in detached loop devices
+
+  * CVE-2023-1075
+    - net/tls: tls_is_tx_ready() checked list_entry
+
+  * Focal update: v5.4.232 upstream stable release (LP: #2011625)
+    - firewire: fix memory leak for payload of request subaction to IEC 61883-1
+      FCP region
+    - bus: sunxi-rsb: Fix error handling in sunxi_rsb_init()
+    - ASoC: Intel: bytcr_rt5651: Drop reference count of ACPI device after use
+    - ALSA: hda/via: Avoid potential array out-of-bound in add_secret_dac_path()
+    - arm64: dts: imx8mm: Fix pad control for UART1_DTE_RX
+    - scsi: Revert "scsi: core: map PQ=1, PDT=other values to
+      SCSI_SCAN_TARGET_PRESENT"
+    - WRITE is "data source", not destination...
+    - fix iov_iter_bvec() "direction" argument
+    - fix "direction" argument of iov_iter_kvec()
+    - netrom: Fix use-after-free caused by accept on already connected socket
+    - netfilter: br_netfilter: disable sabotage_in hook after first suppression
+    - squashfs: harden sanity check in squashfs_read_xattr_id_table
+    - net: phy: meson-gxl: Add generic dummy stubs for MMD register access
+    - can: j1939: fix errant WARN_ON_ONCE in j1939_session_deactivate
+    - ata: libata: Fix sata_down_spd_limit() when no link speed is reported
+    - selftests: net: udpgso_bench_rx: Fix 'used uninitialized' compiler warning
+    - selftests: net: udpgso_bench_rx/tx: Stop when wrong CLI args are provided
+    - selftests: net: udpgso_bench_tx: Cater for pending datagrams zerocopy
+      benchmarking
+    - virtio-net: Keep stop() to follow mirror sequence of open()
+    - net: openvswitch: fix flow memory leak in ovs_flow_cmd_new
+    - efi: fix potential NULL deref in efi_mem_reserve_persistent
+    - scsi: target: core: Fix warning on RT kernels
+    - scsi: iscsi_tcp: Fix UAF during login when accessing the shost ipaddress
+    - i2c: rk3x: fix a bunch of kernel-doc warnings
+    - net/x25: Fix to not accept on connected socket
+    - iio: adc: stm32-dfsdm: fill module aliases
+    - usb: dwc3: dwc3-qcom: Fix typo in the dwc3 vbus override API
+    - usb: dwc3: qcom: enable vbus override when in OTG dr-mode
+    - usb: gadget: f_fs: Fix unbalanced spinlock in __ffs_ep0_queue_wait
+    - vc_screen: move load of struct vc_data pointer in vcs_read() to avoid UAF
+    - Input: i8042 - move __initconst to fix code styling warning
+    - Input: i8042 - merge quirk tables
+    - Input: i8042 - add TUXEDO devices to i8042 quirk tables
+    - Input: i8042 - add Clevo PCX0DX to i8042 quirk table
+    - fbcon: Check font dimension limits
+    - watchdog: diag288_wdt: do not use stack buffers for hardware data
+    - watchdog: diag288_wdt: fix __diag288() inline assembly
+    - efi: Accept version 2 of memory attributes table
+    - iio: hid: fix the retval in accel_3d_capture_sample
+    - iio: adc: berlin2-adc: Add missing of_node_put() in error path
+    - iio:adc:twl6030: Enable measurements of VUSB, VBAT and others
+    - parisc: Fix return code of pdc_iodc_print()
+    - parisc: Wire up PTRACE_GETREGS/PTRACE_SETREGS for compat case
+    - riscv: disable generation of unwind tables
+    - mm: hugetlb: proc: check for hugetlb shared PMD in /proc/PID/smaps
+    - fpga: stratix10-soc: Fix return value check in s10_ops_write_init()
+    - mm/swapfile: add cond_resched() in get_swap_pages()
+    - Squashfs: fix handling and sanity checking of xattr_ids count
+    - nvmem: core: fix cell removal on error
+    - mm: swap: properly update readahead statistics in unuse_pte_range()
+    - xprtrdma: Fix regbuf data not freed in rpcrdma_req_create()
+    - serial: 8250_dma: Fix DMA Rx completion race
+    - serial: 8250_dma: Fix DMA Rx rearm race
+    - powerpc/imc-pmu: Revert nest_init_lock to being a mutex
+    - fbdev: smscufx: fix error handling code in ufx_usb_probe
+    - f2fs: fix to do sanity check on i_extra_isize in is_alive()
+    - wifi: brcmfmac: Check the count value of channel spec to prevent out-of-
+      bounds reads
+    - iio:adc:twl6030: Enable measurement of VAC
+    - btrfs: limit device extents to the device size
+    - btrfs: zlib: zero-initialize zlib workspace
+    - ALSA: emux: Avoid potential array out-of-bound in snd_emux_xg_control()
+    - tracing: Fix poll() and select() do not work on per_cpu trace_pipe and
+      trace_pipe_raw
+    - can: j1939: do not wait 250 ms if the same addr was already claimed
+    - IB/hfi1: Restore allocated resources on failed copyout
+    - IB/IPoIB: Fix legacy IPoIB due to wrong number of queues
+    - iommu: Add gfp parameter to iommu_ops::map
+    - RDMA/usnic: use iommu_map_atomic() under spin_lock()
+    - xfrm: fix bug with DSCP copy to v6 from v4 tunnel
+    - bonding: fix error checking in bond_debug_reregister()
+    - net: phy: meson-gxl: use MMD access dummy stubs for GXL, internal PHY
+    - ionic: clean interrupt before enabling queue to avoid credit race
+    - ice: Do not use WQ_MEM_RECLAIM flag for workqueue
+    - rds: rds_rm_zerocopy_callback() use list_first_entry()
+    - selftests: forwarding: lib: quote the sysctl values
+    - ALSA: pci: lx6464es: fix a debug loop
+    - pinctrl: aspeed: Fix confusing types in return value
+    - pinctrl: single: fix potential NULL dereference
+    - pinctrl: intel: Restore the pins that used to be in Direct IRQ mode
+    - net: USB: Fix wrong-direction WARNING in plusb.c
+    - usb: core: add quirk for Alcor Link AK9563 smartcard reader
+    - usb: typec: altmodes/displayport: Fix probe pin assign check
+    - ceph: flush cap releases when the session is flushed
+    - riscv: Fixup race condition on PG_dcache_clean in flush_icache_pte
+    - arm64: dts: meson-gx: Make mmc host controller interrupts level-sensitive
+    - arm64: dts: meson-g12-common: Make mmc host controller interrupts level-
+      sensitive
+    - arm64: dts: meson-axg: Make mmc host controller interrupts level-sensitive
+    - nvme-pci: Move enumeration by class to be last in the table
+    - bpf: Always return target ifindex in bpf_fib_lookup
+    - migrate: hugetlb: check for hugetlb shared PMD in node migration
+    - selftests/bpf: Verify copy_register_state() preserves parent/live fields
+    - ASoC: cs42l56: fix DT probe
+    - tools/virtio: fix the vringh test for virtio ring changes
+    - net/rose: Fix to not accept on connected socket
+    - net: stmmac: do not stop RX_CLK in Rx LPI state for qcs404 SoC
+    - net: sched: sch: Bounds check priority
+    - s390/decompressor: specify __decompress() buf len to avoid overflow
+    - nvme-fc: fix a missing queue put in nvmet_fc_ls_create_association
+    - aio: fix mremap after fork null-deref
+    - btrfs: free device in btrfs_close_devices for a single device filesystem
+    - netfilter: nft_tproxy: restrict to prerouting hook
+    - xfs: remove the xfs_efi_log_item_t typedef
+    - xfs: remove the xfs_efd_log_item_t typedef
+    - xfs: remove the xfs_inode_log_item_t typedef
+    - xfs: factor out a xfs_defer_create_intent helper
+    - xfs: merge the ->log_item defer op into ->create_intent
+    - xfs: merge the ->diff_items defer op into ->create_intent
+    - xfs: turn dfp_intent into a xfs_log_item
+    - xfs: refactor xfs_defer_finish_noroll
+    - xfs: log new intent items created as part of finishing recovered intent
+      items
+    - xfs: fix finobt btree block recovery ordering
+    - xfs: proper replay of deferred ops queued during log recovery
+    - xfs: xfs_defer_capture should absorb remaining block reservations
+    - xfs: xfs_defer_capture should absorb remaining transaction reservation
+    - xfs: clean up bmap intent item recovery checking
+    - xfs: clean up xfs_bui_item_recover iget/trans_alloc/ilock ordering
+    - xfs: fix an incore inode UAF in xfs_bui_recover
+    - xfs: change the order in which child and parent defer ops are finished
+    - xfs: periodically relog deferred intent items
+    - xfs: expose the log push threshold
+    - xfs: only relog deferred intent items if free space in the log gets low
+    - xfs: fix missing CoW blocks writeback conversion retry
+    - xfs: ensure inobt record walks always make forward progress
+    - xfs: fix the forward progress assertion in xfs_iwalk_run_callbacks
+    - xfs: prevent UAF in xfs_log_item_in_current_chkpt
+    - xfs: sync lazy sb accounting on quiesce of read-only mounts
+    - Revert "ipv4: Fix incorrect route flushing when source address is deleted"
+    - ipv4: Fix incorrect route flushing when source address is deleted
+    - mmc: sdio: fix possible resource leaks in some error paths
+    - mmc: mmc_spi: fix error handling in mmc_spi_probe()
+    - ALSA: hda/conexant: add a new hda codec SN6180
+    - ALSA: hda/realtek - fixed wrong gpio assigned
+    - sched/psi: Fix use-after-free in ep_remove_wait_queue()
+    - hugetlb: check for undefined shift on 32 bit architectures
+    - Revert "mm: Always release pages to the buddy allocator in
+      memblock_free_late()."
+    - net: Fix unwanted sign extension in netdev_stats_to_stats64()
+    - revert "squashfs: harden sanity check in squashfs_read_xattr_id_table"
+    - ixgbe: allow to increase MTU to 3K with XDP enabled
+    - i40e: add double of VLAN header when computing the max MTU
+    - net: bgmac: fix BCM5358 support by setting correct flags
+    - sctp: sctp_sock_filter(): avoid list_entry() on possibly empty list
+    - dccp/tcp: Avoid negative sk_forward_alloc by ipv6_pinfo.pktoptions.
+    - net/usb: kalmia: Don't pass act_len in usb_bulk_msg error path
+    - net: stmmac: fix order of dwmac5 FlexPPS parametrization sequence
+    - bnxt_en: Fix mqprio and XDP ring checking logic
+    - net: stmmac: Restrict warning on disabling DMA store and fwd mode
+    - ixgbe: add double of VLAN header when computing the max MTU
+    - ipv6: Fix datagram socket connection with DSCP.
+    - ipv6: Fix tcp socket connection with DSCP.
+    - i40e: Add checking for null for nlmsg_find_attr()
+    - kvm: initialize all of the kvm_debugregs structure before sending it to
+      userspace
+    - nilfs2: fix underflow in second superblock position calculations
+    - ASoC: SOF: Intel: hda-dai: fix possible stream_tag leak
+    - net: sched: sch: Fix off by one in htb_activate_prios()
+    - iommu/amd: Pass gfp flags to iommu_map_page() in amd_iommu_map()
+    - Linux 5.4.232
+
+  * CVE-2023-1118
+    - media: rc: Fix use-after-free bugs caused by ene_tx_irqsim()
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Tue, 18 Apr 2023 17:54:42 +0200
+
+linux (5.4.0-148.165) focal; urgency=medium
+
+  * focal/linux: 5.4.0-148.165 -proposed tracker (LP: #2016777)
+
+  * CVE-2023-1829
+    - net/sched: Retire tcindex classifier
+    - [Config]: Make sure CONFIG_NET_CLS_TCINDEX is not available
+
+ -- Thadeu Lima de Souza Cascardo <cascardo@canonical.com>  Tue, 18 Apr 2023 05:31:58 -0300
+
+linux (5.4.0-147.164) focal; urgency=medium
+
+  * focal/linux: 5.4.0-147.164 -proposed tracker (LP: #2011959)
+
+  * CVE-2023-26545
+    - net: mpls: fix stale pointer if allocation fails during device rename
+
+  * CVE-2023-1281
+    - rcu: Upgrade rcu_swap_protected() to rcu_replace_pointer()
+    - net/sched: tcindex: update imperfect hash filters respecting rcu
+
+  * Focal update: v5.4.231 upstream stable release (LP: #2011226)
+    - clk: generalize devm_clk_get() a bit
+    - clk: Provide new devm_clk helpers for prepared and enabled clocks
+    - memory: atmel-sdramc: Fix missing clk_disable_unprepare in
+      atmel_ramc_probe()
+    - memory: mvebu-devbus: Fix missing clk_disable_unprepare in
+      mvebu_devbus_probe()
+    - ARM: dts: imx6qdl-gw560x: Remove incorrect 'uart-has-rtscts'
+    - ARM: imx27: Retrieve the SYSCTRL base address from devicetree
+    - ARM: imx31: Retrieve the IIM base address from devicetree
+    - ARM: imx35: Retrieve the IIM base address from devicetree
+    - ARM: imx: add missing of_node_put()
+    - HID: intel_ish-hid: Add check for ishtp_dma_tx_map
+    - EDAC/highbank: Fix memory leak in highbank_mc_probe()
+    - tomoyo: fix broken dependency on *.conf.default
+    - RDMA/core: Fix ib block iterator counter overflow
+    - IB/hfi1: Reject a zero-length user expected buffer
+    - IB/hfi1: Reserve user expected TIDs
+    - IB/hfi1: Fix expected receive setup error exit issues
+    - affs: initialize fsdata in affs_truncate()
+    - amd-xgbe: TX Flow Ctrl Registers are h/w ver dependent
+    - amd-xgbe: Delay AN timeout during KR training
+    - bpf: Fix pointer-leak due to insufficient speculative store bypass
+      mitigation
+    - phy: rockchip-inno-usb2: Fix missing clk_disable_unprepare() in
+      rockchip_usb2phy_power_on()
+    - net: nfc: Fix use-after-free in local_cleanup()
+    - net: wan: Add checks for NULL for utdm in undo_uhdlc_init and unmap_si_regs
+    - gpio: mxc: Always set GPIOs used as interrupt source to INPUT mode
+    - net/sched: sch_taprio: fix possible use-after-free
+    - net: fix a concurrency bug in l2tp_tunnel_register()
+    - l2tp: Serialize access to sk_user_data with sk_callback_lock
+    - l2tp: Don't sleep and disable BH under writer-side sk_callback_lock
+    - net: usb: sr9700: Handle negative len
+    - net: mdio: validate parameter addr in mdiobus_get_phy()
+    - HID: check empty report_list in hid_validate_values()
+    - HID: check empty report_list in bigben_probe()
+    - net: stmmac: fix invalid call to mdiobus_get_phy()
+    - HID: revert CHERRY_MOUSE_000C quirk
+    - usb: gadget: f_fs: Prevent race during ffs_ep0_queue_wait
+    - usb: gadget: f_fs: Ensure ep0req is dequeued before free_request
+    - net: mlx5: eliminate anonymous module_init & module_exit
+    - drm/panfrost: fix GENERIC_ATOMIC64 dependency
+    - dmaengine: Fix double increment of client_count in dma_chan_get()
+    - net: macb: fix PTP TX timestamp failure due to packet padding
+    - HID: betop: check shape of output reports
+    - dmaengine: xilinx_dma: use devm_platform_ioremap_resource()
+    - dmaengine: xilinx_dma: Fix devm_platform_ioremap_resource error handling
+    - dmaengine: xilinx_dma: call of_node_put() when breaking out of
+      for_each_child_of_node()
+    - tcp: avoid the lookup process failing to get sk in ehash table
+    - w1: fix deadloop in __w1_remove_master_device()
+    - w1: fix WARNING after calling w1_process()
+    - driver core: Fix test_async_probe_init saves device in wrong array
+    - net: dsa: microchip: ksz9477: port map correction in ALU table entry
+      register
+    - tcp: fix rate_app_limited to default to 1
+    - cpufreq: Add Tegra234 to cpufreq-dt-platdev blocklist
+    - ASoC: fsl_micfil: Correct the number of steps on SX controls
+    - drm: Add orientation quirk for Lenovo ideapad D330-10IGL
+    - s390/debug: add _ASM_S390_ prefix to header guard
+    - cpufreq: armada-37xx: stop using 0 as NULL pointer
+    - ASoC: fsl_ssi: Rename AC'97 streams to avoid collisions with AC'97 CODEC
+    - ASoC: fsl-asoc-card: Fix naming of AC'97 CODEC widgets
+    - spi: spidev: remove debug messages that access spidev->spi without locking
+    - KVM: s390: interrupt: use READ_ONCE() before cmpxchg()
+    - scsi: hisi_sas: Set a port invalid only if there are no devices attached
+      when refreshing port id
+    - platform/x86: touchscreen_dmi: Add info for the CSL Panther Tab HD
+    - platform/x86: asus-nb-wmi: Add alternate mapping for KEY_SCREENLOCK
+    - lockref: stop doing cpu_relax in the cmpxchg loop
+    - mmc: sdhci-esdhc-imx: clear pending interrupt and halt cqhci
+    - mmc: sdhci-esdhc-imx: disable the CMD CRC check for standard tuning
+    - mmc: sdhci-esdhc-imx: correct the tuning start tap and step setting
+    - netfilter: conntrack: do not renew entry stuck in tcp SYN_SENT state
+    - fs: reiserfs: remove useless new_opts in reiserfs_remount
+    - Bluetooth: hci_sync: cancel cmd_timer if hci_open failed
+    - scsi: hpsa: Fix allocation size for scsi_host_alloc()
+    - module: Don't wait for GOING modules
+    - tracing: Make sure trace_printk() can output as soon as it can be used
+    - trace_events_hist: add check for return value of 'create_hist_field'
+    - ftrace/scripts: Update the instructions for ftrace-bisect.sh
+    - cifs: Fix oops due to uncleared server->smbd_conn in reconnect
+    - KVM: x86/vmx: Do not skip segment attributes if unusable bit is set
+    - thermal: intel: int340x: Protect trip temperature from concurrent updates
+    - ARM: 9280/1: mm: fix warning on phys_addr_t to void pointer assignment
+    - EDAC/device: Respect any driver-supplied workqueue polling value
+    - EDAC/qcom: Do not pass llcc_driv_data as edac_device_ctl_info's pvt_info
+    - netlink: prevent potential spectre v1 gadgets
+    - net: fix UaF in netns ops registration error path
+    - netfilter: nft_set_rbtree: skip elements in transaction from garbage
+      collection
+    - netlink: annotate data races around nlk->portid
+    - netlink: annotate data races around dst_portid and dst_group
+    - netlink: annotate data races around sk_state
+    - ipv4: prevent potential spectre v1 gadget in ip_metrics_convert()
+    - ipv4: prevent potential spectre v1 gadget in fib_metrics_match()
+    - netfilter: conntrack: fix vtag checks for ABORT/SHUTDOWN_COMPLETE
+    - netrom: Fix use-after-free of a listening socket.
+    - net/sched: sch_taprio: do not schedule in taprio_reset()
+    - sctp: fail if no bound addresses can be used for a given scope
+    - net: ravb: Fix possible hang if RIS2_QFF1 happen
+    - thermal: intel: int340x: Add locking to int340x_thermal_get_trip_type()
+    - net/tg3: resolve deadlock in tg3_reset_task() during EEH
+    - net/phy/mdio-i2c: Move header file to include/linux/mdio
+    - net: xgene: Move shared header file into include/linux
+    - net: mdio-mux-meson-g12a: force internal PHY off on mux switch
+    - Revert "Input: synaptics - switch touchpad on HP Laptop 15-da3001TU to RMI
+      mode"
+    - nfsd: Ensure knfsd shuts down when the "nfsd" pseudofs is unmounted
+    - block: fix and cleanup bio_check_ro
+    - x86/i8259: Mark legacy PIC interrupts with IRQ_LEVEL
+    - netfilter: conntrack: unify established states for SCTP paths
+    - perf/x86/amd: fix potential integer overflow on shift of a int
+    - clk: Fix pointer casting to prevent oops in devm_clk_release()
+    - x86/asm: Fix an assembler warning with current binutils
+    - ARM: dts: imx: Fix pca9547 i2c-mux node name
+    - bpf: Skip task with pid=1 in send_signal_common()
+    - blk-cgroup: fix missing pd_online_fn() while activating policy
+    - dmaengine: imx-sdma: Fix a possible memory leak in sdma_transfer_init
+    - sysctl: add a new register_sysctl_init() interface
+    - panic: unset panic_on_warn inside panic()
+    - mm: kasan: do not panic if both panic_on_warn and kasan_multishot set
+    - exit: Add and use make_task_dead.
+    - objtool: Add a missing comma to avoid string concatenation
+    - hexagon: Fix function name in die()
+    - h8300: Fix build errors from do_exit() to make_task_dead() transition
+    - csky: Fix function name in csky_alignment() and die()
+    - ia64: make IA64_MCA_RECOVERY bool instead of tristate
+    - exit: Put an upper limit on how often we can oops
+    - exit: Expose "oops_count" to sysfs
+    - exit: Allow oops_limit to be disabled
+    - panic: Consolidate open-coded panic_on_warn checks
+    - panic: Introduce warn_limit
+    - panic: Expose "warn_count" to sysfs
+    - docs: Fix path paste-o for /sys/kernel/warn_count
+    - exit: Use READ_ONCE() for all oops/warn limit reads
+    - ipv6: ensure sane device mtu in tunnels
+    - Bluetooth: fix null ptr deref on hci_sync_conn_complete_evt
+    - usb: host: xhci-plat: add wakeup entry at sysfs
+    - Revert "xprtrdma: Fix regbuf data not freed in rpcrdma_req_create()"
+    - Linux 5.4.231
+
+  * CVE-2022-3903
+    - USB: add usb_control_msg_send() and usb_control_msg_recv()
+    - USB: correct API of usb_control_msg_send/recv
+    - USB: move snd_usb_pipe_sanity_check into the USB core
+    - media: mceusb: Use new usb_control_msg_*() routines
+
+  * CVE-2022-3108
+    - drm/amdkfd: Check for null pointer after calling kmemdup
+
+  * Focal update: v5.4.230 upstream stable release (LP: #2008946)
+    - pNFS/filelayout: Fix coalescing test for single DS
+    - net/ethtool/ioctl: return -EOPNOTSUPP if we have no phy stats
+    - RDMA/srp: Move large values to a new enum for gcc13
+    - f2fs: let's avoid panic if extent_tree is not created
+    - wifi: brcmfmac: fix regression for Broadcom PCIe wifi devices
+    - Add exception protection processing for vd in axi_chan_handle_err function
+    - nilfs2: fix general protection fault in nilfs_btree_insert()
+    - efi: fix userspace infinite retry read efivars after EFI runtime services
+      page fault
+    - drm/i915/gt: Reset twice
+    - ALSA: hda/realtek - Turn on power early
+    - xhci-pci: set the dma max_seg_size
+    - usb: xhci: Check endpoint is valid before dereferencing it
+    - xhci: Fix null pointer dereference when host dies
+    - xhci: Add update_hub_device override for PCI xHCI hosts
+    - xhci: Add a flag to disable USB3 lpm on a xhci root port level.
+    - usb: acpi: add helper to check port lpm capability using acpi _DSM
+    - xhci: Detect lpm incapable xHC USB3 roothub ports from ACPI tables
+    - prlimit: do_prlimit needs to have a speculation check
+    - USB: serial: option: add Quectel EM05-G (GR) modem
+    - USB: serial: option: add Quectel EM05-G (CS) modem
+    - USB: serial: option: add Quectel EM05-G (RS) modem
+    - USB: serial: option: add Quectel EC200U modem
+    - USB: serial: option: add Quectel EM05CN (SG) modem
+    - USB: serial: option: add Quectel EM05CN modem
+    - USB: misc: iowarrior: fix up header size for USB_DEVICE_ID_CODEMERCS_IOW100
+    - misc: fastrpc: Don't remove map on creater_process and device_release
+    - misc: fastrpc: Fix use-after-free race condition for maps
+    - usb: core: hub: disable autosuspend for TI TUSB8041
+    - comedi: adv_pci1760: Fix PWM instruction handling
+    - mmc: sunxi-mmc: Fix clock refcount imbalance during unbind
+    - btrfs: fix race between quota rescan and disable leading to NULL pointer
+      deref
+    - cifs: do not include page data when checking signature
+    - USB: serial: cp210x: add SCALANCE LPE-9000 device id
+    - usb: host: ehci-fsl: Fix module alias
+    - usb: typec: altmodes/displayport: Add pin assignment helper
+    - usb: typec: altmodes/displayport: Fix pin assignment calculation
+    - usb: gadget: g_webcam: Send color matching descriptor per frame
+    - usb: gadget: f_ncm: fix potential NULL ptr deref in ncm_bitrate()
+    - usb-storage: apply IGNORE_UAS only for HIKSEMI MD202 on RTL9210
+    - dt-bindings: phy: g12a-usb3-pcie-phy: fix compatible string documentation
+    - serial: pch_uart: Pass correct sg to dma_unmap_sg()
+    - dmaengine: tegra210-adma: fix global intr clear
+    - serial: atmel: fix incorrect baudrate setup
+    - gsmi: fix null-deref in gsmi_get_variable
+    - drm/i915: re-disable RC6p on Sandy Bridge
+    - drm/amd/display: Fix set scaling doesn's work
+    - drm/amd/display: Fix COLOR_SPACE_YCBCR2020_TYPE matrix
+    - x86/fpu: Use _Alignof to avoid undefined behavior in TYPE_ALIGN
+    - mm/khugepaged: fix collapse_pte_mapped_thp() to allow anon_vma
+    - Linux 5.4.230
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Tue, 21 Mar 2023 10:50:49 +0100
+
+linux (5.4.0-146.163) focal; urgency=medium
+
+  * focal/linux: 5.4.0-146.163 -proposed tracker (LP: #2012094)
+
+  * NFS deathlock with last Kernel 5.4.0-144.161 and 5.15.0-67.74 (LP: #2009325)
+    - NFS: Correct timing for assigning access cache timestamp
+
+ -- Luke Nowakowski-Krijger <luke.nowakowskikrijger@canonical.com>  Fri, 17 Mar 2023 11:08:20 -0700
+
+linux (5.4.0-145.162) focal; urgency=medium
+
+  * focal/linux: 5.4.0-145.162 -proposed tracker (LP: #2008389)
+
+  * [SRU]Update ice driver to support E823 devices (LP: #1986717)
+    - ice: Add device ids for E822 devices
+    - ice: add support for E823 devices
+
+  * btrfs/154: rename fails with EOVERFLOW when calculating item size during
+    item key collision (LP: #2004132)
+    - btrfs: correctly calculate item size used when item key collision happens
+
+  * rtcpie in timers from ubuntu_kernel_selftests randomly failing
+    (LP: #1814234)
+    - SAUCE: selftest: rtcpie: Force passing unreliable subtest
+
+  * [UBUNTU 20.04] KVM: s390: pv: don't allow userspace to set the clock under
+    PV - kernel part (LP: #1999882)
+    - KVM: s390x: fix SCK locking
+    - KVM: s390: pv: don't allow userspace to set the clock under PV
+
+  * CVE-2021-3669
+    - ipc: replace costly bailout check in sysvipc_find_ipc()
+
+  * net:fcnal-test.sh 'nettest' command not found on F/K (LP: #2006391)
+    - selftests/net: Find nettest in current directory
+
+  * xfs: Preallocated ioend transactions cause deadlock due to log buffer
+    exhaustion (LP: #2007219)
+    - xfs: drop submit side trans alloc for append ioends
+
+  * CVE-2022-4382
+    - USB: gadgetfs: Fix race between mounting and unmounting
+
+  * CVE-2022-2196
+    - KVM: VMX: Execute IBPB on emulated VM-exit when guest has IBRS
+
+  * ubuntu_kernel_selftests: net:udpgso_bench.sh failed (LP: #1951447)
+    - selftests: net: udpgso_bench: Fix racing bug between the rx/tx programs
+
+  * net:fcnal-test.sh didn't return a non-zero value even with some sub-tests
+    failed (LP: #2006692)
+    - selftests: net/fcnal-test.sh: add exit code
+
+  * Fix selftests/ftracetests/Meta-selftests in Focal (LP: #2006453)
+    - SAUCE: Fix ftrace/Meta-selftests bashism check
+
+  * CVE-2023-23559
+    - wifi: rndis_wlan: Prevent buffer overflow in rndis_query_oid
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Fri, 24 Feb 2023 14:09:22 +0100
+
+linux (5.4.0-144.161) focal; urgency=medium
+
+  * focal/linux: 5.4.0-144.161 -proposed tracker (LP: #2004653)
+
+  * CVE-2023-0461
+    - SAUCE: Fix inet_csk_listen_start after CVE-2023-0461
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Fri, 03 Feb 2023 15:30:55 +0100
+
+linux (5.4.0-143.160) focal; urgency=medium
+
+  * focal/linux: 5.4.0-143.160 -proposed tracker (LP: #2004385)
+
+  * NFS: client permission error after adding user to permissible group
+    (LP: #2003053)
+    - NFS: Clear the file access cache upon login
+    - NFS: Judge the file access cache's timestamp in rcu path
+    - NFS: Fix up a sparse warning
+
+  * Focal update: v5.4.229 upstream stable release (LP: #2003914)
+    - tracing/ring-buffer: Only do full wait when cpu != RING_BUFFER_ALL_CPUS
+    - udf: Discard preallocation before extending file with a hole
+    - udf: Fix preallocation discarding at indirect extent boundary
+    - udf: Do not bother looking for prealloc extents if i_lenExtents matches
+      i_size
+    - udf: Fix extending file within last block
+    - usb: gadget: uvc: Prevent buffer overflow in setup handler
+    - USB: serial: option: add Quectel EM05-G modem
+    - USB: serial: cp210x: add Kamstrup RF sniffer PIDs
+    - USB: serial: f81232: fix division by zero on line-speed change
+    - USB: serial: f81534: fix division by zero on line-speed change
+    - igb: Initialize mailbox message for VF reset
+    - xen-netback: move removal of "hotplug-status" to the right place
+    - HID: ite: Add support for Acer S1002 keyboard-dock
+    - HID: ite: Enable QUIRK_TOUCHPAD_ON_OFF_REPORT on Acer Aspire Switch 10E
+    - HID: ite: Enable QUIRK_TOUCHPAD_ON_OFF_REPORT on Acer Aspire Switch V 10
+    - HID: uclogic: Add HID_QUIRK_HIDINPUT_FORCE quirk
+    - net: loopback: use NET_NAME_PREDICTABLE for name_assign_type
+    - usb: musb: remove extra check in musb_gadget_vbus_draw
+    - ARM: dts: qcom: apq8064: fix coresight compatible
+    - arm64: dts: qcom: sdm845-cheza: fix AP suspend pin bias
+    - drivers: soc: ti: knav_qmss_queue: Mark knav_acc_firmwares as static
+    - arm: dts: spear600: Fix clcd interrupt
+    - soc: ti: knav_qmss_queue: Use pm_runtime_resume_and_get instead of
+      pm_runtime_get_sync
+    - soc: ti: knav_qmss_queue: Fix PM disable depth imbalance in knav_queue_probe
+    - soc: ti: smartreflex: Fix PM disable depth imbalance in omap_sr_probe
+    - perf: arm_dsu: Fix hotplug callback leak in dsu_pmu_init()
+    - perf/smmuv3: Fix hotplug callback leak in arm_smmu_pmu_init()
+    - arm64: dts: mt2712e: Fix unit_address_vs_reg warning for oscillators
+    - arm64: dts: mt2712e: Fix unit address for pinctrl node
+    - arm64: dts: mt2712-evb: Fix vproc fixed regulators unit names
+    - arm64: dts: mt2712-evb: Fix usb vbus regulators unit names
+    - arm64: dts: mediatek: mt6797: Fix 26M oscillator unit name
+    - ARM: dts: dove: Fix assigned-addresses for every PCIe Root Port
+    - ARM: dts: armada-370: Fix assigned-addresses for every PCIe Root Port
+    - ARM: dts: armada-xp: Fix assigned-addresses for every PCIe Root Port
+    - ARM: dts: armada-375: Fix assigned-addresses for every PCIe Root Port
+    - ARM: dts: armada-38x: Fix assigned-addresses for every PCIe Root Port
+    - ARM: dts: armada-39x: Fix assigned-addresses for every PCIe Root Port
+    - ARM: dts: turris-omnia: Add ethernet aliases
+    - ARM: dts: turris-omnia: Add switch port 6 node
+    - arm64: dts: armada-3720-turris-mox: Add missing interrupt for RTC
+    - pstore/ram: Fix error return code in ramoops_probe()
+    - ARM: mmp: fix timer_read delay
+    - pstore: Avoid kcore oops by vmap()ing with VM_IOREMAP
+    - tpm/tpm_crb: Fix error message in __crb_relinquish_locality()
+    - cpuidle: dt: Return the correct numbers of parsed idle states
+    - alpha: fix syscall entry in !AUDUT_SYSCALL case
+    - PM: hibernate: Fix mistake in kerneldoc comment
+    - fs: don't audit the capability check in simple_xattr_list()
+    - selftests/ftrace: event_triggers: wait longer for test_event_enable
+    - perf: Fix possible memleak in pmu_dev_alloc()
+    - timerqueue: Use rb_entry_safe() in timerqueue_getnext()
+    - proc: fixup uptime selftest
+    - lib/fonts: fix undefined behavior in bit shift for get_default_font
+    - ocfs2: fix memory leak in ocfs2_stack_glue_init()
+    - MIPS: vpe-mt: fix possible memory leak while module exiting
+    - MIPS: vpe-cmp: fix possible memory leak while module exiting
+    - selftests/efivarfs: Add checking of the test return value
+    - PNP: fix name memory leak in pnp_alloc_dev()
+    - perf/x86/intel/uncore: Fix reference count leak in hswep_has_limit_sbox()
+    - irqchip: gic-pm: Use pm_runtime_resume_and_get() in gic_probe()
+    - EDAC/i10nm: fix refcount leak in pci_get_dev_wrapper()
+    - nfsd: don't call nfsd_file_put from client states seqfile display
+    - genirq/irqdesc: Don't try to remove non-existing sysfs files
+    - cpufreq: amd_freq_sensitivity: Add missing pci_dev_put()
+    - libfs: add DEFINE_SIMPLE_ATTRIBUTE_SIGNED for signed value
+    - lib/notifier-error-inject: fix error when writing -errno to debugfs file
+    - docs: fault-injection: fix non-working usage of negative values
+    - debugfs: fix error when writing negative value to atomic_t debugfs file
+    - ocfs2: ocfs2_mount_volume does cleanup job before return error
+    - ocfs2: rewrite error handling of ocfs2_fill_super
+    - ocfs2: fix memory leak in ocfs2_mount_volume()
+    - rapidio: fix possible name leaks when rio_add_device() fails
+    - rapidio: rio: fix possible name leak in rio_register_mport()
+    - clocksource/drivers/sh_cmt: Make sure channel clock supply is enabled
+    - ACPICA: Fix use-after-free in acpi_ut_copy_ipackage_to_ipackage()
+    - uprobes/x86: Allow to probe a NOP instruction with 0x66 prefix
+    - xen/events: only register debug interrupt for 2-level events
+    - x86/xen: Fix memory leak in xen_smp_intr_init{_pv}()
+    - x86/xen: Fix memory leak in xen_init_lock_cpu()
+    - xen/privcmd: Fix a possible warning in privcmd_ioctl_mmap_resource()
+    - PM: runtime: Improve path in rpm_idle() when no callback
+    - PM: runtime: Do not call __rpm_callback() from rpm_idle()
+    - platform/x86: mxm-wmi: fix memleak in mxm_wmi_call_mx[ds|mx]()
+    - MIPS: BCM63xx: Add check for NULL for clk in clk_enable
+    - MIPS: OCTEON: warn only once if deprecated link status is being used
+    - fs: sysv: Fix sysv_nblocks() returns wrong value
+    - rapidio: fix possible UAF when kfifo_alloc() fails
+    - eventfd: change int to __u64 in eventfd_signal() ifndef CONFIG_EVENTFD
+    - relay: fix type mismatch when allocating memory in relay_create_buf()
+    - hfs: Fix OOB Write in hfs_asc2mac
+    - rapidio: devices: fix missing put_device in mport_cdev_open
+    - wifi: ath9k: hif_usb: fix memory leak of urbs in
+      ath9k_hif_usb_dealloc_tx_urbs()
+    - wifi: ath9k: hif_usb: Fix use-after-free in ath9k_hif_usb_reg_in_cb()
+    - wifi: rtl8xxxu: Fix reading the vendor of combo chips
+    - pata_ipx4xx_cf: Fix unsigned comparison with less than zero
+    - media: i2c: ad5820: Fix error path
+    - can: kvaser_usb: do not increase tx statistics when sending error message
+      frames
+    - can: kvaser_usb: kvaser_usb_leaf: Get capabilities from device
+    - can: kvaser_usb: kvaser_usb_leaf: Rename {leaf,usbcan}_cmd_error_event to
+      {leaf,usbcan}_cmd_can_error_event
+    - can: kvaser_usb: kvaser_usb_leaf: Handle CMD_ERROR_EVENT
+    - can: kvaser_usb_leaf: Set Warning state even without bus errors
+    - can: kvaser_usb_leaf: Fix improved state not being reported
+    - can: kvaser_usb_leaf: Fix wrong CAN state after stopping
+    - can: kvaser_usb_leaf: Fix bogus restart events
+    - can: kvaser_usb: Add struct kvaser_usb_busparams
+    - can: kvaser_usb: Compare requested bittiming parameters with actual
+      parameters in do_set_{,data}_bittiming
+    - clk: renesas: r9a06g032: Repair grave increment error
+    - spi: Update reference to struct spi_controller
+    - drm/panel/panel-sitronix-st7701: Remove panel on DSI attach failure
+    - ima: Rename internal filter rule functions
+    - ima: Fix fall-through warnings for Clang
+    - ima: Handle -ESTALE returned by ima_filter_rule_match()
+    - media: vivid: fix compose size exceed boundary
+    - bpf: propagate precision in ALU/ALU64 operations
+    - mtd: Fix device name leak when register device failed in add_mtd_device()
+    - wifi: rsi: Fix handling of 802.3 EAPOL frames sent via control port
+    - media: camss: Clean up received buffers on failed start of streaming
+    - net, proc: Provide PROC_FS=n fallback for proc_create_net_single_write()
+    - rxrpc: Fix ack.bufferSize to be 0 when generating an ack
+    - drm/radeon: Add the missed acpi_put_table() to fix memory leak
+    - drm/mediatek: Modify dpi power on/off sequence.
+    - ASoC: pxa: fix null-pointer dereference in filter()
+    - regulator: core: fix unbalanced of node refcount in regulator_dev_lookup()
+    - amdgpu/pm: prevent array underflow in vega20_odn_edit_dpm_table()
+    - integrity: Fix memory leakage in keyring allocation error path
+    - ima: Fix misuse of dereference of pointer in template_desc_init_fields()
+    - wifi: ath10k: Fix return value in ath10k_pci_init()
+    - mtd: lpddr2_nvm: Fix possible null-ptr-deref
+    - Input: elants_i2c - properly handle the reset GPIO when power is off
+    - media: solo6x10: fix possible memory leak in solo_sysfs_init()
+    - media: platform: exynos4-is: Fix error handling in fimc_md_init()
+    - media: videobuf-dma-contig: use dma_mmap_coherent
+    - bpf: Move skb->len == 0 checks into __bpf_redirect
+    - HID: hid-sensor-custom: set fixed size for custom attributes
+    - ALSA: pcm: fix undefined behavior in bit shift for SNDRV_PCM_RATE_KNOT
+    - ALSA: seq: fix undefined behavior in bit shift for
+      SNDRV_SEQ_FILTER_USE_EVENT
+    - regulator: core: use kfree_const() to free space conditionally
+    - clk: rockchip: Fix memory leak in rockchip_clk_register_pll()
+    - bonding: Export skip slave logic to function
+    - bonding: Rename slave_arr to usable_slaves
+    - bonding: fix link recovery in mode 2 when updelay is nonzero
+    - mtd: maps: pxa2xx-flash: fix memory leak in probe
+    - media: imon: fix a race condition in send_packet()
+    - clk: imx8mn: correct the usb1_ctrl parent to be usb_bus
+    - clk: imx: replace osc_hdmi with dummy
+    - pinctrl: pinconf-generic: add missing of_node_put()
+    - media: dvb-core: Fix ignored return value in dvb_register_frontend()
+    - media: dvb-usb: az6027: fix null-ptr-deref in az6027_i2c_xfer()
+    - media: s5p-mfc: Add variant data for MFC v7 hardware for Exynos 3250 SoC
+    - drm/tegra: Add missing clk_disable_unprepare() in tegra_dc_probe()
+    - ASoC: dt-bindings: wcd9335: fix reset line polarity in example
+    - ASoC: mediatek: mtk-btcvsd: Add checks for write and read of mtk_btcvsd_snd
+    - NFSv4.2: Clear FATTR4_WORD2_SECURITY_LABEL when done decoding
+    - NFSv4.2: Fix a memory stomp in decode_attr_security_label
+    - NFSv4.2: Fix initialisation of struct nfs4_label
+    - NFSv4: Fix a deadlock between nfs4_open_recover_helper() and delegreturn
+    - ALSA: asihpi: fix missing pci_disable_device()
+    - wifi: iwlwifi: mvm: fix double free on tx path.
+    - ASoC: mediatek: mt8173: Enable IRQ when pdata is ready
+    - drm/radeon: Fix PCI device refcount leak in radeon_atrm_get_bios()
+    - drm/amdgpu: Fix PCI device refcount leak in amdgpu_atrm_get_bios()
+    - ASoC: pcm512x: Fix PM disable depth imbalance in pcm512x_probe
+    - netfilter: conntrack: set icmpv6 redirects as RELATED
+    - bpf, sockmap: Fix repeated calls to sock_put() when msg has more_data
+    - bpf, sockmap: Fix data loss caused by using apply_bytes on ingress redirect
+    - bonding: uninitialized variable in bond_miimon_inspect()
+    - spi: spidev: mask SPI_CS_HIGH in SPI_IOC_RD_MODE
+    - wifi: cfg80211: Fix not unregister reg_pdev when load_builtin_regdb_keys()
+      fails
+    - regulator: core: fix module refcount leak in set_supply()
+    - clk: qcom: clk-krait: fix wrong div2 functions
+    - hsr: Avoid double remove of a node.
+    - configfs: fix possible memory leak in configfs_create_dir()
+    - regulator: core: fix resource leak in regulator_register()
+    - bpf, sockmap: fix race in sock_map_free()
+    - media: saa7164: fix missing pci_disable_device()
+    - ALSA: mts64: fix possible null-ptr-defer in snd_mts64_interrupt
+    - xprtrdma: Fix regbuf data not freed in rpcrdma_req_create()
+    - SUNRPC: Fix missing release socket in rpc_sockname()
+    - NFSv4.x: Fail client initialisation if state manager thread can't run
+    - mmc: alcor: fix return value check of mmc_add_host()
+    - mmc: moxart: fix return value check of mmc_add_host()
+    - mmc: mxcmmc: fix return value check of mmc_add_host()
+    - mmc: pxamci: fix return value check of mmc_add_host()
+    - mmc: rtsx_usb_sdmmc: fix return value check of mmc_add_host()
+    - mmc: toshsd: fix return value check of mmc_add_host()
+    - mmc: vub300: fix return value check of mmc_add_host()
+    - mmc: wmt-sdmmc: fix return value check of mmc_add_host()
+    - mmc: atmel-mci: fix return value check of mmc_add_host()
+    - mmc: omap_hsmmc: fix return value check of mmc_add_host()
+    - mmc: meson-gx: fix return value check of mmc_add_host()
+    - mmc: via-sdmmc: fix return value check of mmc_add_host()
+    - mmc: wbsd: fix return value check of mmc_add_host()
+    - mmc: mmci: fix return value check of mmc_add_host()
+    - media: c8sectpfe: Add of_node_put() when breaking out of loop
+    - media: coda: Add check for dcoda_iram_alloc
+    - media: coda: Add check for kmalloc
+    - clk: samsung: Fix memory leak in _samsung_clk_register_pll()
+    - spi: spi-gpio: Don't set MOSI as an input if not 3WIRE mode
+    - wifi: rtl8xxxu: Add __packed to struct rtl8723bu_c2h
+    - wifi: brcmfmac: Fix error return code in brcmf_sdio_download_firmware()
+    - blktrace: Fix output non-blktrace event when blk_classic option enabled
+    - clk: socfpga: clk-pll: Remove unused variable 'rc'
+    - clk: socfpga: use clk_hw_register for a5/c5
+    - clk: socfpga: Fix memory leak in socfpga_gate_init()
+    - net: vmw_vsock: vmci: Check memcpy_from_msg()
+    - net: defxx: Fix missing err handling in dfx_init()
+    - net: stmmac: selftests: fix potential memleak in stmmac_test_arpoffload()
+    - drivers: net: qlcnic: Fix potential memory leak in qlcnic_sriov_init()
+    - of: overlay: fix null pointer dereferencing in find_dup_cset_node_entry()
+      and find_dup_cset_prop()
+    - ethernet: s2io: don't call dev_kfree_skb() under spin_lock_irqsave()
+    - net: farsync: Fix kmemleak when rmmods farsync
+    - net/tunnel: wait until all sk_user_data reader finish before releasing the
+      sock
+    - net: apple: mace: don't call dev_kfree_skb() under spin_lock_irqsave()
+    - net: apple: bmac: don't call dev_kfree_skb() under spin_lock_irqsave()
+    - net: emaclite: don't call dev_kfree_skb() under spin_lock_irqsave()
+    - net: ethernet: dnet: don't call dev_kfree_skb() under spin_lock_irqsave()
+    - hamradio: don't call dev_kfree_skb() under spin_lock_irqsave()
+    - net: amd: lance: don't call dev_kfree_skb() under spin_lock_irqsave()
+    - net: amd-xgbe: Fix logic around active and passive cables
+    - net: amd-xgbe: Check only the minimum speed for active/passive cables
+    - can: tcan4x5x: Remove invalid write in clear_interrupts
+    - net: lan9303: Fix read error execution path
+    - ntb_netdev: Use dev_kfree_skb_any() in interrupt context
+    - Bluetooth: btusb: don't call kfree_skb() under spin_lock_irqsave()
+    - Bluetooth: hci_qca: don't call kfree_skb() under spin_lock_irqsave()
+    - Bluetooth: hci_ll: don't call kfree_skb() under spin_lock_irqsave()
+    - Bluetooth: hci_h5: don't call kfree_skb() under spin_lock_irqsave()
+    - Bluetooth: hci_bcsp: don't call kfree_skb() under spin_lock_irqsave()
+    - Bluetooth: hci_core: don't call kfree_skb() under spin_lock_irqsave()
+    - Bluetooth: RFCOMM: don't call kfree_skb() under spin_lock_irqsave()
+    - stmmac: fix potential division by 0
+    - apparmor: fix a memleak in multi_transaction_new()
+    - apparmor: fix lockdep warning when removing a namespace
+    - apparmor: Fix abi check to include v8 abi
+    - apparmor: Use pointer to struct aa_label for lbs_cred
+    - RDMA/core: Fix order of nldev_exit call
+    - f2fs: fix normal discard process
+    - RDMA/siw: Fix immediate work request flush to completion queue
+    - RDMA/nldev: Return "-EAGAIN" if the cm_id isn't from expected port
+    - RDMA/siw: Set defined status for work completion with undefined status
+    - scsi: scsi_debug: Fix a warning in resp_write_scat()
+    - crypto: ccree - swap SHA384 and SHA512 larval hashes at build time
+    - crypto: ccree - Remove debugfs when platform_driver_register failed
+    - PCI: Check for alloc failure in pci_request_irq()
+    - RDMA/hfi: Decrease PCI device reference count in error path
+    - crypto: ccree - Make cc_debugfs_global_fini() available for module init
+      function
+    - RDMA/rxe: Fix NULL-ptr-deref in rxe_qp_do_cleanup() when socket create
+      failed
+    - scsi: hpsa: Fix possible memory leak in hpsa_init_one()
+    - crypto: tcrypt - Fix multibuffer skcipher speed test mem leak
+    - scsi: mpt3sas: Fix possible resource leaks in mpt3sas_transport_port_add()
+    - scsi: hpsa: Fix error handling in hpsa_add_sas_host()
+    - scsi: hpsa: Fix possible memory leak in hpsa_add_sas_device()
+    - scsi: fcoe: Fix possible name leak when device_register() fails
+    - scsi: ipr: Fix WARNING in ipr_init()
+    - scsi: fcoe: Fix transport not deattached when fcoe_if_init() fails
+    - scsi: snic: Fix possible UAF in snic_tgt_create()
+    - RDMA/nldev: Add checks for nla_nest_start() in fill_stat_counter_qps()
+    - f2fs: avoid victim selection from previous victim section
+    - crypto: omap-sham - Use pm_runtime_resume_and_get() in omap_sham_probe()
+    - RDMA/hfi1: Fix error return code in parse_platform_config()
+    - orangefs: Fix sysfs not cleanup when dev init failed
+    - crypto: img-hash - Fix variable dereferenced before check 'hdev->req'
+    - hwrng: amd - Fix PCI device refcount leak
+    - hwrng: geode - Fix PCI device refcount leak
+    - IB/IPoIB: Fix queue count inconsistency for PKEY child interfaces
+    - drivers: dio: fix possible memory leak in dio_init()
+    - tty: serial: tegra: Activate RX DMA transfer by request
+    - serial: tegra: Read DMA status before terminating
+    - class: fix possible memory leak in __class_register()
+    - vfio: platform: Do not pass return buffer to ACPI _RST method
+    - uio: uio_dmem_genirq: Fix missing unlock in irq configuration
+    - uio: uio_dmem_genirq: Fix deadlock between irq config and handling
+    - usb: fotg210-udc: Fix ages old endianness issues
+    - staging: vme_user: Fix possible UAF in tsi148_dma_list_add
+    - usb: typec: Check for ops->exit instead of ops->enter in altmode_exit
+    - usb: typec: tcpci: fix of node refcount leak in tcpci_register_port()
+    - serial: amba-pl011: avoid SBSA UART accessing DMACR register
+    - serial: pl011: Do not clear RX FIFO & RX interrupt in unthrottle.
+    - serial: pch: Fix PCI device refcount leak in pch_request_dma()
+    - tty: serial: clean up stop-tx part in altera_uart_tx_chars()
+    - tty: serial: altera_uart_{r,t}x_chars() need only uart_port
+    - serial: altera_uart: fix locking in polling mode
+    - serial: sunsab: Fix error handling in sunsab_init()
+    - test_firmware: fix memory leak in test_firmware_init()
+    - misc: ocxl: fix possible name leak in ocxl_file_register_afu()
+    - misc: tifm: fix possible memory leak in tifm_7xx1_switch_media()
+    - misc: sgi-gru: fix use-after-free error in gru_set_context_option, gru_fault
+      and gru_handle_user_call_os
+    - cxl: fix possible null-ptr-deref in cxl_guest_init_afu|adapter()
+    - cxl: fix possible null-ptr-deref in cxl_pci_init_afu|adapter()
+    - counter: stm32-lptimer-cnt: fix the check on arr and cmp registers update
+    - usb: roles: fix of node refcount leak in usb_role_switch_is_parent()
+    - usb: gadget: f_hid: optional SETUP/SET_REPORT mode
+    - usb: gadget: f_hid: fix f_hidg lifetime vs cdev
+    - usb: gadget: f_hid: fix refcount leak on error path
+    - drivers: mcb: fix resource leak in mcb_probe()
+    - mcb: mcb-parse: fix error handing in chameleon_parse_gdd()
+    - chardev: fix error handling in cdev_device_add()
+    - i2c: pxa-pci: fix missing pci_disable_device() on error in ce4100_i2c_probe
+    - staging: rtl8192u: Fix use after free in ieee80211_rx()
+    - staging: rtl8192e: Fix potential use-after-free in rtllib_rx_Monitor()
+    - vme: Fix error not catched in fake_init()
+    - i2c: ismt: Fix an out-of-bounds bug in ismt_access()
+    - usb: storage: Add check for kcalloc
+    - tracing/hist: Fix issue of losting command info in error_log
+    - samples: vfio-mdev: Fix missing pci_disable_device() in mdpy_fb_probe()
+    - fbdev: ssd1307fb: Drop optional dependency
+    - fbdev: pm2fb: fix missing pci_disable_device()
+    - fbdev: via: Fix error in via_core_init()
+    - fbdev: vermilion: decrease reference count in error path
+    - fbdev: uvesafb: Fixes an error handling path in uvesafb_probe()
+    - HSI: omap_ssi_core: fix unbalanced pm_runtime_disable()
+    - HSI: omap_ssi_core: fix possible memory leak in ssi_probe()
+    - power: supply: fix residue sysfs file in error handle route of
+      __power_supply_register()
+    - perf trace: Return error if a system call doesn't exist
+    - perf trace: Separate 'struct syscall_fmt' definition from syscall_fmts
+      variable
+    - perf trace: Factor out the initialization of syscal_arg_fmt->scnprintf
+    - perf trace: Add the syscall_arg_fmt pointer to syscall_arg
+    - perf trace: Allow associating scnprintf routines with well known arg names
+    - perf trace: Add a strtoul() method to 'struct syscall_arg_fmt'
+    - perf trace: Use macro RAW_SYSCALL_ARGS_NUM to replace number
+    - perf trace: Handle failure when trace point folder is missed
+    - perf symbol: correction while adjusting symbol
+    - HSI: omap_ssi_core: Fix error handling in ssi_init()
+    - power: supply: fix null pointer dereferencing in
+      power_supply_get_battery_info
+    - RDMA/siw: Fix pointer cast warning
+    - include/uapi/linux/swab: Fix potentially missing __always_inline
+    - rtc: snvs: Allow a time difference on clock register read
+    - rtc: pcf85063: Fix reading alarm
+    - iommu/amd: Fix pci device refcount leak in ppr_notifier()
+    - iommu/fsl_pamu: Fix resource leak in fsl_pamu_probe()
+    - macintosh: fix possible memory leak in macio_add_one_device()
+    - macintosh/macio-adb: check the return value of ioremap()
+    - powerpc/52xx: Fix a resource leak in an error handling path
+    - cxl: Fix refcount leak in cxl_calc_capp_routing
+    - powerpc/xive: add missing iounmap() in error path in
+      xive_spapr_populate_irq_data()
+    - powerpc/perf: callchain validate kernel stack pointer bounds
+    - powerpc/83xx/mpc832x_rdb: call platform_device_put() in error case in
+      of_fsl_spi_probe()
+    - powerpc/hv-gpci: Fix hv_gpci event list
+    - selftests/powerpc: Fix resource leaks
+    - pwm: sifive: Call pwm_sifive_update_clock() while mutex is held
+    - remoteproc: sysmon: fix memory leak in qcom_add_sysmon_subdev()
+    - remoteproc: qcom_q6v5_pas: Fix missing of_node_put() in
+      adsp_alloc_memory_region()
+    - rtc: st-lpc: Add missing clk_disable_unprepare in st_rtc_probe()
+    - rtc: pic32: Move devm_rtc_allocate_device earlier in pic32_rtc_probe()
+    - nfsd: Define the file access mode enum for tracing
+    - NFSD: Add tracepoints to NFSD's duplicate reply cache
+    - nfsd: under NFSv4.1, fix double svc_xprt_put on rpc_create failure
+    - mISDN: hfcsusb: don't call dev_kfree_skb/kfree_skb() under
+      spin_lock_irqsave()
+    - mISDN: hfcpci: don't call dev_kfree_skb/kfree_skb() under
+      spin_lock_irqsave()
+    - mISDN: hfcmulti: don't call dev_kfree_skb/kfree_skb() under
+      spin_lock_irqsave()
+    - nfc: pn533: Clear nfc_target before being used
+    - r6040: Fix kmemleak in probe and remove
+    - rtc: mxc_v2: Add missing clk_disable_unprepare()
+    - openvswitch: Fix flow lookup to use unmasked key
+    - skbuff: Account for tail adjustment during pull operations
+    - mailbox: zynq-ipi: fix error handling while device_register() fails
+    - net_sched: reject TCF_EM_SIMPLE case for complex ematch module
+    - rxrpc: Fix missing unlock in rxrpc_do_sendmsg()
+    - myri10ge: Fix an error handling path in myri10ge_probe()
+    - net: stream: purge sk_error_queue in sk_stream_kill_queues()
+    - rcu: Fix __this_cpu_read() lockdep warning in rcu_force_quiescent_state()
+    - binfmt_misc: fix shift-out-of-bounds in check_special_flags
+    - fs: jfs: fix shift-out-of-bounds in dbAllocAG
+    - udf: Avoid double brelse() in udf_rename()
+    - fs: jfs: fix shift-out-of-bounds in dbDiscardAG
+    - ACPICA: Fix error code path in acpi_ds_call_control_method()
+    - nilfs2: fix shift-out-of-bounds/overflow in nilfs_sb2_bad_offset()
+    - acct: fix potential integer overflow in encode_comp_t()
+    - hfs: fix OOB Read in __hfs_brec_find
+    - drm/etnaviv: add missing quirks for GC300
+    - brcmfmac: return error when getting invalid max_flowrings from dongle
+    - wifi: ath9k: verify the expected usb_endpoints are present
+    - wifi: ar5523: Fix use-after-free on ar5523_cmd() timed out
+    - ASoC: codecs: rt298: Add quirk for KBL-R RVP platform
+    - ipmi: fix memleak when unload ipmi driver
+    - bpf: make sure skb->len != 0 when redirecting to a tunneling device
+    - net: ethernet: ti: Fix return type of netcp_ndo_start_xmit()
+    - hamradio: baycom_epp: Fix return type of baycom_send_packet()
+    - wifi: brcmfmac: Fix potential shift-out-of-bounds in
+      brcmf_fw_alloc_request()
+    - igb: Do not free q_vector unless new one was allocated
+    - s390/ctcm: Fix return type of ctc{mp,}m_tx()
+    - s390/netiucv: Fix return type of netiucv_tx()
+    - s390/lcs: Fix return type of lcs_start_xmit()
+    - drm/rockchip: Use drm_mode_copy()
+    - drm/sti: Use drm_mode_copy()
+    - drivers/md/md-bitmap: check the return value of md_bitmap_get_counter()
+    - md/raid1: stop mdx_raid1 thread when raid1 array run failed
+    - net: add atomic_long_t to net_device_stats fields
+    - mrp: introduce active flags to prevent UAF when applicant uninit
+    - ppp: associate skb with a device at tx
+    - bpf: Prevent decl_tag from being referenced in func_proto arg
+    - media: dvb-frontends: fix leak of memory fw
+    - media: dvbdev: adopts refcnt to avoid UAF
+    - media: dvb-usb: fix memory leak in dvb_usb_adapter_init()
+    - blk-mq: fix possible memleak when register 'hctx' failed
+    - regulator: core: fix use_count leakage when handling boot-on
+    - mmc: f-sdh30: Add quirks for broken timeout clock capability
+    - media: si470x: Fix use-after-free in si470x_int_in_callback()
+    - clk: st: Fix memory leak in st_of_quadfs_setup()
+    - hugetlbfs: fix null-ptr-deref in hugetlbfs_parse_param()
+    - drm/fsl-dcu: Fix return type of fsl_dcu_drm_connector_mode_valid()
+    - drm/sti: Fix return type of sti_{dvo,hda,hdmi}_connector_mode_valid()
+    - orangefs: Fix kmemleak in orangefs_prepare_debugfs_help_string()
+    - orangefs: Fix kmemleak in orangefs_{kernel,client}_debug_init()
+    - ALSA/ASoC: hda: move/rename snd_hdac_ext_stop_streams to hdac_stream.c
+    - ALSA: hda: add snd_hdac_stop_streams() helper
+    - ASoC: Intel: Skylake: Fix driver hang during shutdown
+    - ASoC: mediatek: mt8173-rt5650-rt5514: fix refcount leak in
+      mt8173_rt5650_rt5514_dev_probe()
+    - ASoC: audio-graph-card: fix refcount leak of cpu_ep in
+      __graph_for_each_link()
+    - ASoC: rockchip: pdm: Add missing clk_disable_unprepare() in
+      rockchip_pdm_runtime_resume()
+    - ASoC: wm8994: Fix potential deadlock
+    - ASoC: rockchip: spdif: Add missing clk_disable_unprepare() in
+      rk_spdif_runtime_resume()
+    - ASoC: rt5670: Remove unbalanced pm_runtime_put()
+    - pstore: Switch pmsg_lock to an rt_mutex to avoid priority inversion
+    - pstore: Make sure CONFIG_PSTORE_PMSG selects CONFIG_RT_MUTEXES
+    - ALSA: hda/realtek: Add quirk for Lenovo TianYi510Pro-14IOB
+    - ALSA: hda/hdmi: Add HP Device 0x8711 to force connect list
+    - usb: dwc3: core: defer probe on ulpi_read_id timeout
+    - HID: wacom: Ensure bootloader PID is usable in hidraw mode
+    - reiserfs: Add missing calls to reiserfs_security_free()
+    - iio: adc: ad_sigma_delta: do not use internal iio_dev lock
+    - iio: adc128s052: add proper .data members in adc128_of_match table
+    - regulator: core: fix deadlock on regulator enable
+    - gcov: add support for checksum field
+    - media: dvbdev: fix build warning due to comments
+    - media: dvbdev: fix refcnt bug
+    - cifs: fix oops during encryption
+    - nvme-pci: fix doorbell buffer value endianness
+    - ata: ahci: Fix PCS quirk application for suspend
+    - nvme: fix the NVME_CMD_EFFECTS_CSE_MASK definition
+    - objtool: Fix SEGFAULT
+    - powerpc/rtas: avoid device tree lookups in rtas_os_term()
+    - powerpc/rtas: avoid scheduling in rtas_os_term()
+    - HID: multitouch: fix Asus ExpertBook P2 P2451FA trackpoint
+    - HID: plantronics: Additional PIDs for double volume key presses quirk
+    - hfsplus: fix bug causing custom uid and gid being unable to be assigned with
+      mount
+    - ovl: Use ovl mounter's fsuid and fsgid in ovl_link()
+    - ALSA: line6: correct midi status byte when receiving data from podxt
+    - ALSA: line6: fix stack overflow in line6_midi_transmit
+    - pnode: terminate at peers of source
+    - md: fix a crash in mempool_free
+    - mm, compaction: fix fast_isolate_around() to stay within boundaries
+    - f2fs: should put a page when checking the summary info
+    - mmc: vub300: fix warning - do not call blocking ops when !TASK_RUNNING
+    - tpm: tpm_crb: Add the missed acpi_put_table() to fix memory leak
+    - tpm: tpm_tis: Add the missed acpi_put_table() to fix memory leak
+    - SUNRPC: Don't leak netobj memory when gss_read_proxy_verf() fails
+    - net/af_packet: add VLAN support for AF_PACKET SOCK_RAW GSO
+    - net/af_packet: make sure to pull mac header
+    - media: stv0288: use explicitly signed char
+    - soc: qcom: Select REMAP_MMIO for LLCC driver
+    - kest.pl: Fix grub2 menu handling for rebooting
+    - ktest.pl minconfig: Unset configs instead of just removing them
+    - mmc: sdhci-sprd: Disable CLK_AUTO when the clock is less than 400K
+    - btrfs: fix resolving backrefs for inline extent followed by prealloc
+    - ARM: ux500: do not directly dereference __iomem
+    - arm64: dts: qcom: sdm850-lenovo-yoga-c630: correct I2C12 pins drive strength
+    - selftests: Use optional USERCFLAGS and USERLDFLAGS
+    - cpufreq: Init completion before kobject_init_and_add()
+    - binfmt: Move install_exec_creds after setup_new_exec to match binfmt_elf
+    - binfmt: Fix error return code in load_elf_fdpic_binary()
+    - dm cache: Fix ABBA deadlock between shrink_slab and dm_cache_metadata_abort
+    - dm thin: Fix ABBA deadlock between shrink_slab and dm_pool_abort_metadata
+    - dm thin: Use last transaction's pmd->root when commit failed
+    - dm thin: Fix UAF in run_timer_softirq()
+    - dm integrity: Fix UAF in dm_integrity_dtr()
+    - dm clone: Fix UAF in clone_dtr()
+    - dm cache: Fix UAF in destroy()
+    - dm cache: set needs_check flag after aborting metadata
+    - tracing/hist: Fix out-of-bound write on 'action_data.var_ref_idx'
+    - x86/microcode/intel: Do not retry microcode reloading on the APs
+    - tracing/hist: Fix wrong return value in parse_action_params()
+    - tracing: Fix infinite loop in tracing_read_pipe on overflowed
+      print_trace_line
+    - ARM: 9256/1: NWFPE: avoid compiler-generated __aeabi_uldivmod
+    - media: dvb-core: Fix double free in dvb_register_device()
+    - cifs: fix confusing debug message
+    - cifs: fix missing display of three mount options
+    - md/bitmap: Fix bitmap chunk size overflow issues
+    - efi: Add iMac Pro 2017 to uefi skip cert quirk
+    - ipmi: fix long wait in unload when IPMI disconnect
+    - mtd: spi-nor: Check for zero erase size in spi_nor_find_best_erase_type()
+    - ima: Fix a potential NULL pointer access in ima_restore_measurement_list
+    - ipmi: fix use after free in _ipmi_destroy_user()
+    - PCI: Fix pci_device_is_present() for VFs by checking PF
+    - PCI/sysfs: Fix double free in error path
+    - crypto: n2 - add missing hash statesize
+    - iommu/amd: Fix ivrs_acpihid cmdline parsing code
+    - parisc: led: Fix potential null-ptr-deref in start_task()
+    - device_cgroup: Roll back to original exceptions after copy failure
+    - drm/connector: send hotplug uevent on connector cleanup
+    - drm/vmwgfx: Validate the box size for the snooped cursor
+    - ext4: add inode table check in __ext4_get_inode_loc to aovid possible
+      infinite loop
+    - ext4: fix undefined behavior in bit shift for ext4_check_flag_values
+    - ext4: add EXT4_IGET_BAD flag to prevent unexpected bad inode
+    - ext4: add helper to check quota inums
+    - ext4: fix reserved cluster accounting in __es_remove_extent()
+    - ext4: fix bug_on in __es_tree_search caused by bad boot loader inode
+    - ext4: init quota for 'old.inode' in 'ext4_rename'
+    - ext4: fix delayed allocation bug in ext4_clu_mapped for bigalloc + inline
+    - ext4: fix corruption when online resizing a 1K bigalloc fs
+    - ext4: fix error code return to user-space in ext4_get_branch()
+    - ext4: avoid BUG_ON when creating xattrs
+    - ext4: fix inode leak in ext4_xattr_inode_create() on an error path
+    - ext4: initialize quota before expanding inode in setproject ioctl
+    - ext4: avoid unaccounted block allocation when expanding inode
+    - ext4: allocate extended attribute value in vmalloc area
+    - btrfs: replace strncpy() with strscpy()
+    - PM/devfreq: governor: Add a private governor_data for governor
+    - media: s5p-mfc: Fix to handle reference queue during finishing
+    - media: s5p-mfc: Clear workbit to handle error condition
+    - media: s5p-mfc: Fix in register read and write for H264
+    - dm thin: resume even if in FAIL mode
+    - perf probe: Use dwarf_attr_integrate as generic DWARF attr accessor
+    - perf probe: Fix to get the DW_AT_decl_file and DW_AT_call_file as unsinged
+      data
+    - KVM: x86: optimize more exit handlers in vmx.c
+    - KVM: retpolines: x86: eliminate retpoline from vmx.c exit handlers
+    - KVM: VMX: Rename INTERRUPT_PENDING to INTERRUPT_WINDOW
+    - KVM: VMX: Rename NMI_PENDING to NMI_WINDOW
+    - KVM: VMX: Fix the spelling of CPU_BASED_USE_TSC_OFFSETTING
+    - KVM: nVMX: Properly expose ENABLE_USR_WAIT_PAUSE control to L1
+    - ravb: Fix "failed to switch device to config mode" message during unbind
+    - ext4: goto right label 'failed_mount3a'
+    - ext4: correct inconsistent error msg in nojournal mode
+    - mm/highmem: Lift memcpy_[to|from]_page to core
+    - ext4: use memcpy_to_page() in pagecache_write()
+    - fs: ext4: initialize fsdata in pagecache_write()
+    - ext4: use kmemdup() to replace kmalloc + memcpy
+    - mbcache: don't reclaim used entries
+    - mbcache: add functions to delete entry if unused
+    - ext4: remove EA inode entry from mbcache on inode eviction
+    - ext4: unindent codeblock in ext4_xattr_block_set()
+    - ext4: fix race when reusing xattr blocks
+    - mbcache: automatically delete entries from cache on freeing
+    - ext4: fix deadlock due to mbcache entry corruption
+    - SUNRPC: ensure the matching upcall is in-flight upon downcall
+    - bpf: pull before calling skb_postpull_rcsum()
+    - nfsd: shut down the NFSv4 state objects before the filecache
+    - net: hns3: add interrupts re-initialization while doing VF FLR
+    - net: sched: fix memory leak in tcindex_set_parms
+    - qlcnic: prevent ->dcb use-after-free on qlcnic_dcb_enable() failure
+    - nfc: Fix potential resource leaks
+    - vhost: fix range used in translate_desc()
+    - net: amd-xgbe: add missed tasklet_kill
+    - net: phy: xgmiitorgmii: Fix refcount leak in xgmiitorgmii_probe
+    - RDMA/uverbs: Silence shiftTooManyBitsSigned warning
+    - RDMA/mlx5: Fix validation of max_rd_atomic caps for DC
+    - net: sched: atm: dont intepret cls results when asked to drop
+    - net: sched: cbq: dont intepret cls results when asked to drop
+    - perf tools: Fix resources leak in perf_data__open_dir()
+    - drivers/net/bonding/bond_3ad: return when there's no aggregator
+    - usb: rndis_host: Secure rndis_query check against int overflow
+    - drm/i915: unpin on error in intel_vgpu_shadow_mm_pin()
+    - caif: fix memory leak in cfctrl_linkup_request()
+    - udf: Fix extension of the last extent in the file
+    - ASoC: Intel: bytcr_rt5640: Add quirk for the Advantech MICA-071 tablet
+    - x86/bugs: Flush IBP in ib_prctl_set()
+    - nfsd: fix handling of readdir in v4root vs. mount upcall timeout
+    - riscv: uaccess: fix type of 0 variable on error in get_user()
+    - ext4: don't allow journal inode to have encrypt flag
+    - hfs/hfsplus: use WARN_ON for sanity check
+    - hfs/hfsplus: avoid WARN_ON() for sanity check, use proper error handling
+    - mbcache: Avoid nesting of cache->c_list_lock under bit locks
+    - parisc: Align parisc MADV_XXX constants with all other architectures
+    - selftests: Fix kselftest O=objdir build from cluttering top level objdir
+    - selftests: set the BUILD variable to absolute path
+    - driver core: Fix bus_type.match() error handling in __driver_attach()
+    - net: sched: disallow noqueue for qdisc classes
+    - KVM: arm64: Fix S1PTW handling on RO memslots
+    - efi: tpm: Avoid READ_ONCE() for accessing the event log
+    - docs: Fix the docs build with Sphinx 6.0
+    - perf auxtrace: Fix address filter duplicate symbol selection
+    - s390/kexec: fix ipl report address for kdump
+    - s390/percpu: add READ_ONCE() to arch_this_cpu_to_op_simple()
+    - net/ulp: prevent ULP without clone op from entering the LISTEN status
+    - ALSA: hda/hdmi: Add a HP device 0x8715 to force connect list
+    - cifs: Fix uninitialized memory read for smb311 posix symlink create
+    - drm/msm/adreno: Make adreno quirks not overwrite each other
+    - platform/x86: sony-laptop: Don't turn off 0x153 keyboard backlight during
+      probe
+    - ixgbe: fix pci device refcount leak
+    - ipv6: raw: Deduct extension header length in rawv6_push_pending_frames
+    - wifi: wilc1000: sdio: fix module autoloading
+    - usb: ulpi: defer ulpi_register on ulpi_read_id timeout
+    - jbd2: use the correct print format
+    - quota: Factor out setup of quota inode
+    - ext4: fix bug_on in __es_tree_search caused by bad quota inode
+    - ext4: lost matching-pair of trace in ext4_truncate
+    - ext4: fix use-after-free in ext4_orphan_cleanup
+    - ext4: fix uninititialized value in 'ext4_evict_inode'
+    - netfilter: ipset: Fix overflow before widen in the bitmap_ip_create()
+      function.
+    - powerpc/imc-pmu: Fix use of mutex in IRQs disabled section
+    - x86/boot: Avoid using Intel mnemonics in AT&T syntax asm
+    - EDAC/device: Fix period calculation in edac_device_reset_delay_period()
+    - regulator: da9211: Use irq handler when ready
+    - tipc: improve throughput between nodes in netns
+    - tipc: eliminate checking netns if node established
+    - tipc: fix unexpected link reset due to discovery messages
+    - hvc/xen: lock console list traversal
+    - nfc: pn533: Wait for out_urb's completion in pn533_usb_send_frame()
+    - net/sched: act_mpls: Fix warning during failed attribute validation
+    - net/mlx5: Rename ptp clock info
+    - net/mlx5: Fix ptp max frequency adjustment range
+    - iommu/mediatek-v1: Add error handle for mtk_iommu_probe
+    - iommu/mediatek-v1: Fix an error handling path in mtk_iommu_v1_probe()
+    - x86/resctrl: Use task_curr() instead of task_struct->on_cpu to prevent
+      unnecessary IPI
+    - x86/resctrl: Fix task CLOSID/RMID update race
+    - drm/virtio: Fix GEM handle creation UAF
+    - arm64: atomics: format whitespace consistently
+    - arm64: atomics: remove LL/SC trampolines
+    - arm64: cmpxchg_double*: hazard against entire exchange variable
+    - efi: fix NULL-deref in init error path
+    - mm: Always release pages to the buddy allocator in memblock_free_late().
+    - Revert "usb: ulpi: defer ulpi_register on ulpi_read_id timeout"
+    - tipc: fix use-after-free in tipc_disc_rcv()
+    - tty: serial: tegra: Handle RX transfer in PIO mode if DMA wasn't started
+    - tipc: Add a missing case of TIPC_DIRECT_MSG type
+    - ocfs2: fix freeing uninitialized resource on ocfs2_dlm_shutdown
+    - tipc: call tipc_lxc_xmit without holding node_read_lock
+    - Linux 5.4.229
+
+  * Focal update: v5.4.229 upstream stable release (LP: #2003914) //
+    CVE-2023-0266 was assigned for this issue.
+    - ALSA: pcm: Move rwsem lock inside snd_ctl_elem_read to prevent UAF
+
+  * Focal update: v5.4.229 upstream stable release (LP: #2003914) //
+    CVE-2022-41218 is assigned to those bugs above.
+    - media: dvb-core: Fix UAF due to refcount races at releasing
+
+  * Focal update: v5.4.228 upstream stable release (LP: #2003904)
+    - x86/smpboot: Move rcu_cpu_starting() earlier
+    - mm/hugetlb: fix races when looking up a CONT-PTE/PMD size hugetlb page
+    - block: unhash blkdev part inode when the part is deleted
+    - ASoC: ops: Check bounds for second channel in snd_soc_put_volsw_sx()
+    - pinctrl: meditatek: Startup with the IRQs disabled
+    - can: sja1000: fix size of OCR_MODE_MASK define
+    - can: mcba_usb: Fix termination command argument
+    - ASoC: ops: Correct bounds check for second channel on SX controls
+    - Linux 5.4.228
+
+  * Focal update: v5.4.227 upstream stable release (LP: #2003901)
+    - arm64: dts: rockchip: keep I2S1 disabled for GPIO function on ROCK Pi 4
+      series
+    - arm: dts: rockchip: fix node name for hym8563 rtc
+    - ARM: dts: rockchip: fix ir-receiver node names
+    - ARM: dts: rockchip: rk3188: fix lcdc1-rgb24 node name
+    - ARM: 9251/1: perf: Fix stacktraces for tracepoint events in THUMB2 kernels
+    - ARM: 9266/1: mm: fix no-MMU ZERO_PAGE() implementation
+    - ARM: dts: rockchip: disable arm_global_timer on rk3066 and rk3188
+    - 9p/fd: Use P9_HDRSZ for header size
+    - regulator: slg51000: Wait after asserting CS pin
+    - ALSA: seq: Fix function prototype mismatch in snd_seq_expand_var_event
+    - btrfs: send: avoid unaligned encoded writes when attempting to clone range
+    - ASoC: soc-pcm: Add NULL check in BE reparenting
+    - regulator: twl6030: fix get status of twl6032 regulators
+    - fbcon: Use kzalloc() in fbcon_prepare_logo()
+    - 9p/xen: check logical size for buffer size
+    - net: usb: qmi_wwan: add u-blox 0x1342 composition
+    - mm/khugepaged: take the right locks for page table retraction
+    - mm/khugepaged: fix GUP-fast interaction by sending IPI
+    - mm/khugepaged: invoke MMU notifiers in shmem/file collapse paths
+    - xen/netback: do some code cleanup
+    - xen/netback: don't call kfree_skb() with interrupts disabled
+    - Revert "net: dsa: b53: Fix valid setting for MDB entries"
+    - media: v4l2-dv-timings.c: fix too strict blanking sanity checks
+    - memcg: fix possible use-after-free in memcg_write_event_control()
+    - mm/gup: fix gup_pud_range() for dax
+    - KVM: s390: vsie: Fix the initialization of the epoch extension (epdx) field
+    - drm/shmem-helper: Remove errant put in error path
+    - HID: usbhid: Add ALWAYS_POLL quirk for some mice
+    - HID: hid-lg4ff: Add check for empty lbuf
+    - HID: core: fix shift-out-of-bounds in hid_report_raw_event
+    - can: af_can: fix NULL pointer dereference in can_rcv_filter
+    - ieee802154: cc2520: Fix error return code in cc2520_hw_init()
+    - ca8210: Fix crash by zero initializing data
+    - drm/bridge: ti-sn65dsi86: Fix output polarity setting bug
+    - gpio: amd8111: Fix PCI device reference count leak
+    - e1000e: Fix TX dispatch condition
+    - igb: Allocate MSI-X vector when testing
+    - af_unix: Get user_ns from in_skb in unix_diag_get_exact().
+    - Bluetooth: 6LoWPAN: add missing hci_dev_put() in get_l2cap_conn()
+    - Bluetooth: Fix not cleanup led when bt_init fails
+    - net: dsa: ksz: Check return value
+    - selftests: rtnetlink: correct xfrm policy rule in kci_test_ipsec_offload
+    - mac802154: fix missing INIT_LIST_HEAD in ieee802154_if_add()
+    - net: encx24j600: Add parentheses to fix precedence
+    - net: encx24j600: Fix invalid logic in reading of MISTAT register
+    - xen-netfront: Fix NULL sring after live migration
+    - net: mvneta: Prevent out of bounds read in mvneta_config_rss()
+    - i40e: Fix not setting default xps_cpus after reset
+    - i40e: Fix for VF MAC address 0
+    - i40e: Disallow ip4 and ip6 l4_4_bytes
+    - NFC: nci: Bounds check struct nfc_target arrays
+    - nvme initialize core quirks before calling nvme_init_subsystem
+    - net: stmmac: fix "snps,axi-config" node property parsing
+    - net: thunderx: Fix missing destroy_workqueue of nicvf_rx_mode_wq
+    - net: hisilicon: Fix potential use-after-free in hisi_femac_rx()
+    - net: hisilicon: Fix potential use-after-free in hix5hd2_rx()
+    - tipc: Fix potential OOB in tipc_link_proto_rcv()
+    - ipv4: Fix incorrect route flushing when source address is deleted
+    - ipv4: Fix incorrect route flushing when table ID 0 is used
+    - ethernet: aeroflex: fix potential skb leak in greth_init_rings()
+    - net: plip: don't call kfree_skb/dev_kfree_skb() under spin_lock_irq()
+    - ipv6: avoid use-after-free in ip6_fragment()
+    - net: mvneta: Fix an out of bounds check
+    - can: esd_usb: Allow REC and TEC to return to zero
+    - Linux 5.4.227
+
+  * 5.15.0-58.64 breaks xen bridge networking (pvh domU) (LP: #2002889) // Focal
+    update: v5.4.227 upstream stable release (LP: #2003901)
+    - xen/netback: fix build warning
+
+  * Focal update: v5.4.226 upstream stable release (LP: #2003896)
+    - wifi: mac80211: fix memory free error when registering wiphy fail
+    - wifi: mac80211_hwsim: fix debugfs attribute ps with rc table support
+    - audit: fix undefined behavior in bit shift for AUDIT_BIT
+    - wifi: mac80211: Fix ack frame idr leak when mesh has no route
+    - spi: stm32: fix stm32_spi_prepare_mbr() that halves spi clk for every run
+    - drm: panel-orientation-quirks: Add quirk for Acer Switch V 10 (SW5-017)
+    - block, bfq: fix null pointer dereference in bfq_bio_bfqg()
+    - arm64/syscall: Include asm/ptrace.h in syscall_wrapper header.
+    - RISC-V: vdso: Do not add missing symbols to version section in linker script
+    - MIPS: pic32: treat port as signed integer
+    - af_key: Fix send_acquire race with pfkey_register
+    - ARM: dts: am335x-pcm-953: Define fixed regulators in root node
+    - ASoC: sgtl5000: Reset the CHIP_CLK_CTRL reg on remove
+    - regulator: core: fix kobject release warning and memory leak in
+      regulator_register()
+    - regulator: core: fix UAF in destroy_regulator()
+    - bus: sunxi-rsb: Support atomic transfers
+    - tee: optee: fix possible memory leak in optee_register_device()
+    - ARM: dts: at91: sam9g20ek: enable udc vbus gpio pinctrl
+    - net: liquidio: simplify if expression
+    - nfc/nci: fix race with opening and closing
+    - net: pch_gbe: fix potential memleak in pch_gbe_tx_queue()
+    - 9p/fd: fix issue of list_del corruption in p9_fd_cancel()
+    - ARM: mxs: fix memory leak in mxs_machine_init()
+    - net/mlx4: Check retval of mlx4_bitmap_init
+    - net/qla3xxx: fix potential memleak in ql3xxx_send()
+    - net: pch_gbe: fix pci device refcount leak while module exiting
+    - nfp: add port from netdev validation for EEPROM access
+    - Drivers: hv: vmbus: fix double free in the error path of
+      vmbus_add_channel_work()
+    - Drivers: hv: vmbus: fix possible memory leak in vmbus_device_register()
+    - net/mlx5: Fix FW tracer timestamp calculation
+    - tipc: set con sock in tipc_conn_alloc
+    - tipc: add an extra conn_get in tipc_conn_alloc
+    - tipc: check skb_linearize() return value in tipc_disc_rcv()
+    - xfrm: Fix ignored return value in xfrm6_init()
+    - NFC: nci: fix memory leak in nci_rx_data_packet()
+    - regulator: twl6030: re-add TWL6032_SUBCLASS
+    - bnx2x: fix pci device refcount leak in bnx2x_vf_is_pcie_pending()
+    - dccp/tcp: Reset saddr on failure after inet6?_hash_connect().
+    - s390/dasd: fix no record found for raw_track_access
+    - nfc: st-nci: fix incorrect validating logic in EVT_TRANSACTION
+    - nfc: st-nci: fix memory leaks in EVT_TRANSACTION
+    - net: thunderx: Fix the ACPI memory leak
+    - s390/crashdump: fix TOD programmable field size
+    - lib/vdso: use "grep -E" instead of "egrep"
+    - usb: dwc3: exynos: Fix remove() function
+    - arm64: dts: rockchip: lower rk3399-puma-haikou SD controller clock frequency
+    - iio: light: apds9960: fix wrong register for gesture gain
+    - iio: core: Fix entry not deleted when iio_register_sw_trigger_type() fails
+    - init/Kconfig: fix CC_HAS_ASM_GOTO_TIED_OUTPUT test with dash
+    - nios2: add FORCE for vmlinuz.gz
+    - iio: ms5611: Simplify IO callback parameters
+    - iio: pressure: ms5611: fixed value compensation bug
+    - ceph: do not update snapshot context when there is no new snapshot
+    - ceph: avoid putting the realm twice when decoding snaps fails
+    - firmware: google: Release devices before unregistering the bus
+    - firmware: coreboot: Register bus in module init
+    - nilfs2: fix nilfs_sufile_mark_dirty() not set segment usage as dirty
+    - gcov: clang: fix the buffer overflow issue
+    - Input: synaptics - switch touchpad on HP Laptop 15-da3001TU to RMI mode
+    - ASoC: Intel: bytcht_es8316: Add quirk for the Nanote UMPC-01
+    - serial: 8250: 8250_omap: Avoid RS485 RTS glitch on ->set_termios()
+    - xen/platform-pci: add missing free_irq() in error path
+    - platform/x86: asus-wmi: add missing pci_dev_put() in asus_wmi_set_xusb2pr()
+    - platform/x86: acer-wmi: Enable SW_TABLET_MODE on Switch V 10 (SW5-017)
+    - platform/x86: hp-wmi: Ignore Smart Experience App event
+    - [Config] updateconfigs for INET_TABLE_PERTURB_ORDER
+    - tcp: configurable source port perturb table size
+    - net: usb: qmi_wwan: add Telit 0x103a composition
+    - dm integrity: flush the journal on suspend
+    - binder: avoid potential data leakage when copying txn
+    - binder: read pre-translated fds from sender buffer
+    - binder: defer copies of pre-patched txn data
+    - binder: fix pointer cast warning
+    - binder: Address corner cases in deferred copy and fixup
+    - binder: Gracefully handle BINDER_TYPE_FDA objects with num_fds=0
+    - btrfs: free btrfs_path before copying root refs to userspace
+    - btrfs: free btrfs_path before copying fspath to userspace
+    - btrfs: free btrfs_path before copying subvol info to userspace
+    - btrfs: sysfs: normalize the error handling branch in btrfs_init_sysfs()
+    - drm/amd/dc/dce120: Fix audio register mapping, stop triggering KASAN
+    - drm/amdgpu: always register an MMU notifier for userptr
+    - fuse: lock inode unconditionally in fuse_fallocate()
+    - btrfs: free btrfs_path before copying inodes to userspace
+    - spi: spi-imx: Fix spi_bus_clk if requested clock is higher than input clock
+    - btrfs: move QUOTA_ENABLED check to rescan_should_stop from
+      btrfs_qgroup_rescan_worker
+    - drm/amdgpu: update drm_display_info correctly when the edid is read
+    - drm/amdgpu: Partially revert "drm/amdgpu: update drm_display_info correctly
+      when the edid is read"
+    - btrfs: qgroup: fix sleep from invalid context bug in btrfs_qgroup_inherit()
+    - iio: health: afe4403: Fix oob read in afe4403_read_raw
+    - iio: health: afe4404: Fix oob read in afe4404_[read|write]_raw
+    - iio: light: rpr0521: add missing Kconfig dependencies
+    - scripts/faddr2line: Fix regression in name resolution on ppc64le
+    - hwmon: (i5500_temp) fix missing pci_disable_device()
+    - hwmon: (ibmpex) Fix possible UAF when ibmpex_register_bmc() fails
+    - of: property: decrement node refcount in of_fwnode_get_reference_args()
+    - net/mlx5: Fix uninitialized variable bug in outlen_write()
+    - net/mlx5e: Fix use-after-free when reverting termination table
+    - can: sja1000_isa: sja1000_isa_probe(): add missing free_sja1000dev()
+    - can: cc770: cc770_isa_probe(): add missing free_cc770dev()
+    - qlcnic: fix sleep-in-atomic-context bugs caused by msleep
+    - wifi: cfg80211: fix buffer overflow in elem comparison
+    - net: phy: fix null-ptr-deref while probe() failed
+    - net: net_netdev: Fix error handling in ntb_netdev_init_module()
+    - net/9p: Fix a potential socket leak in p9_socket_open
+    - net: ethernet: nixge: fix NULL dereference
+    - dsa: lan9303: Correct stat name
+    - net: hsr: Fix potential use-after-free
+    - afs: Fix fileserver probe RTT handling
+    - net: tun: Fix use-after-free in tun_detach()
+    - packet: do not set TP_STATUS_CSUM_VALID on CHECKSUM_COMPLETE
+    - sctp: fix memory leak in sctp_stream_outq_migrate()
+    - net: ethernet: renesas: ravb: Fix promiscuous mode after system resumed
+    - hwmon: (coretemp) Check for null before removing sysfs attrs
+    - hwmon: (coretemp) fix pci device refcount leak in nv1a_ram_new()
+    - net/mlx5: DR, Fix uninitialized var warning
+    - error-injection: Add prompt for function error injection
+    - tools/vm/slabinfo-gnuplot: use "grep -E" instead of "egrep"
+    - nilfs2: fix NULL pointer dereference in nilfs_palloc_commit_free_entry()
+    - x86/bugs: Make sure MSR_SPEC_CTRL is updated properly upon resume from S3
+    - pinctrl: intel: Save and restore pins in "direct IRQ" mode
+    - mmc: mmc_test: Fix removal of debugfs file
+    - mmc: core: Fix ambiguous TRIM and DISCARD arg
+    - mmc: sdhci-esdhc-imx: correct CQHCI exit halt state check
+    - mmc: sdhci-sprd: Fix no reset data and command after voltage switch
+    - tracing: Free buffers when a used dynamic event is removed
+    - arm64: Fix panic() when Spectre-v2 causes Spectre-BHB to re-allocate KVM
+      vectors
+    - arm64: errata: Fix KVM Spectre-v2 mitigation selection for Cortex-A57/A72
+    - mm: Fix '.data.once' orphan section warning
+    - ASoC: ops: Fix bounds check for _sx controls
+    - pinctrl: single: Fix potential division by zero
+    - iommu/vt-d: Fix PCI device refcount leak in dmar_dev_scope_init()
+    - parisc: Increase size of gcc stack frame check
+    - xtensa: increase size of gcc stack frame check
+    - parisc: Increase FRAME_WARN to 2048 bytes on parisc
+    - Kconfig.debug: provide a little extra FRAME_WARN leeway when KASAN is
+      enabled
+    - selftests: net: add delete nexthop route warning test
+    - selftests: net: fix nexthop warning cleanup double ip typo
+    - ipv4: Handle attempt to delete multipath route when fib_info contains an nh
+      reference
+    - ipv4: Fix route deletion when nexthop info is not specified
+    - tracing/ring-buffer: Have polling block on watermark
+    - nvme: restrict management ioctls to admin
+    - nvme: ensure subsystem reset is single threaded
+    - x86/tsx: Add a feature bit for TSX control MSR support
+    - x86/pm: Add enumeration check before spec MSRs save/restore setup
+    - x86/ioremap: Fix page aligned size calculation in __ioremap_caller()
+    - Revert "clocksource/drivers/riscv: Events are stopped during CPU suspend"
+    - char: tpm: Protect tpm_pm_suspend with locks
+    - mmc: sdhci: use FIELD_GET for preset value bit masks
+    - mmc: sdhci: Fix voltage switch delay
+    - proc: avoid integer type confusion in get_proc_long
+    - proc: proc_skip_spaces() shouldn't think it is working on C strings
+    - v4l2: don't fall back to follow_pfn() if pin_user_pages_fast() fails
+    - ipc/sem: Fix dangling sem_array access in semtimedop race
+    - Linux 5.4.226
+
+  * CVE-2022-4139
+    - drm/i915: fix TLB invalidation for Gen12 video and compute engines
+
+  * Focal update: v5.4.225 upstream stable release (LP: #2002347)
+    - xfs: preserve rmapbt swapext block reservation from freed blocks
+    - xfs: rename xfs_bmap_is_real_extent to is_written_extent
+    - xfs: redesign the reflink remap loop to fix blkres depletion crash
+    - xfs: use MMAPLOCK around filemap_map_pages()
+    - xfs: preserve inode versioning across remounts
+    - xfs: drain the buf delwri queue before xfsaild idles
+    - phy: stm32: fix an error code in probe
+    - wifi: cfg80211: silence a sparse RCU warning
+    - wifi: cfg80211: fix memory leak in query_regdb_file()
+    - bpf, sockmap: Fix the sk->sk_forward_alloc warning of sk_stream_kill_queues
+    - HID: hyperv: fix possible memory leak in mousevsc_probe()
+    - net: gso: fix panic on frag_list with mixed head alloc types
+    - net: tun: Fix memory leaks of napi_get_frags
+    - bnxt_en: Fix possible crash in bnxt_hwrm_set_coal()
+    - bnxt_en: fix potentially incorrect return value for ndo_rx_flow_steer
+    - net: fman: Unregister ethernet device on removal
+    - capabilities: fix undefined behavior in bit shift for CAP_TO_MASK
+    - net: lapbether: fix issue of dev reference count leakage in
+      lapbeth_device_event()
+    - hamradio: fix issue of dev reference count leakage in bpq_device_event()
+    - drm/vc4: Fix missing platform_unregister_drivers() call in
+      vc4_drm_register()
+    - ipv6: addrlabel: fix infoleak when sending struct ifaddrlblmsg to network
+    - can: af_can: fix NULL pointer dereference in can_rx_register()
+    - tipc: fix the msg->req tlv len check in
+      tipc_nl_compat_name_table_dump_header
+    - dmaengine: pxa_dma: use platform_get_irq_optional
+    - dmaengine: mv_xor_v2: Fix a resource leak in mv_xor_v2_remove()
+    - drivers: net: xgene: disable napi when register irq failed in
+      xgene_enet_open()
+    - perf stat: Fix printing os->prefix in CSV metrics output
+    - net: nixge: disable napi when enable interrupts failed in nixge_open()
+    - net/mlx5: Allow async trigger completion execution on single CPU systems
+    - net: cpsw: disable napi in cpsw_ndo_open()
+    - net: cxgb3_main: disable napi when bind qsets failed in cxgb_up()
+    - cxgb4vf: shut down the adapter when t4vf_update_port_info() failed in
+      cxgb4vf_open()
+    - ethernet: s2io: disable napi when start nic failed in s2io_card_up()
+    - net: mv643xx_eth: disable napi when init rxq or txq failed in
+      mv643xx_eth_open()
+    - ethernet: tundra: free irq when alloc ring failed in tsi108_open()
+    - net: macvlan: fix memory leaks of macvlan_common_newlink
+    - riscv: process: fix kernel info leakage
+    - arm64: efi: Fix handling of misaligned runtime regions and drop warning
+    - MIPS: jump_label: Fix compat branch range check
+    - mmc: cqhci: Provide helper for resetting both SDHCI and CQHCI
+    - mmc: sdhci-of-arasan: Fix SDHCI_RESET_ALL for CQHCI
+    - mmc: sdhci-tegra: Fix SDHCI_RESET_ALL for CQHCI
+    - ALSA: hda/ca0132: add quirk for EVGA Z390 DARK
+    - ALSA: hda: fix potential memleak in 'add_widget_node'
+    - ALSA: usb-audio: Add quirk entry for M-Audio Micro
+    - ALSA: usb-audio: Add DSD support for Accuphase DAC-60
+    - vmlinux.lds.h: Fix placement of '.data..decrypted' section
+    - nilfs2: fix deadlock in nilfs_count_free_blocks()
+    - nilfs2: fix use-after-free bug of ns_writer on remount
+    - drm/i915/dmabuf: fix sg_table handling in map_dma_buf
+    - btrfs: selftests: fix wrong error check in btrfs_free_dummy_root()
+    - udf: Fix a slab-out-of-bounds write bug in udf_find_entry()
+    - can: j1939: j1939_send_one(): fix missing CAN header initialization
+    - cert host tools: Stop complaining about deprecated OpenSSL functions
+    - dmaengine: at_hdmac: Fix at_lli struct definition
+    - dmaengine: at_hdmac: Don't start transactions at tx_submit level
+    - dmaengine: at_hdmac: Fix completion of unissued descriptor in case of errors
+    - dmaengine: at_hdmac: Don't allow CPU to reorder channel enable
+    - dmaengine: at_hdmac: Fix impossible condition
+    - dmaengine: at_hdmac: Check return code of dma_async_device_register
+    - net: tun: call napi_schedule_prep() to ensure we own a napi
+    - x86/cpu: Restore AMD's DE_CFG MSR after resume
+    - ASoC: wm5102: Revert "ASoC: wm5102: Fix PM disable depth imbalance in
+      wm5102_probe"
+    - ASoC: wm5110: Revert "ASoC: wm5110: Fix PM disable depth imbalance in
+      wm5110_probe"
+    - ASoC: wm8997: Revert "ASoC: wm8997: Fix PM disable depth imbalance in
+      wm8997_probe"
+    - ASoC: wm8962: Add an event handler for TEMP_HP and TEMP_SPK
+    - spi: intel: Fix the offset to get the 64K erase opcode
+    - ASoC: codecs: jz4725b: add missed Line In power control bit
+    - ASoC: codecs: jz4725b: fix reported volume for Master ctl
+    - ASoC: codecs: jz4725b: use right control for Capture Volume
+    - ASoC: codecs: jz4725b: fix capture selector naming
+    - selftests/futex: fix build for clang
+    - selftests/intel_pstate: fix build for ARCH=x86_64
+    - NFSv4: Retry LOCK on OLD_STATEID during delegation return
+    - i2c: i801: add lis3lv02d's I2C address for Vostro 5568
+    - drm/imx: imx-tve: Fix return type of imx_tve_connector_mode_valid
+    - btrfs: remove pointless and double ulist frees in error paths of qgroup
+      tests
+    - ASoC: codecs: jz4725b: Fix spelling mistake "Sourc" -> "Source", "Routee" ->
+      "Route"
+    - spi: stm32: Print summary 'callbacks suppressed' message
+    - ASoC: core: Fix use-after-free in snd_soc_exit()
+    - serial: 8250_omap: remove wait loop from Errata i202 workaround
+    - serial: 8250: omap: Fix unpaired pm_runtime_put_sync() in omap8250_remove()
+    - serial: 8250: omap: Flush PM QOS work on remove
+    - serial: imx: Add missing .thaw_noirq hook
+    - tty: n_gsm: fix sleep-in-atomic-context bug in gsm_control_send
+    - ASoC: soc-utils: Remove __exit for snd_soc_util_exit()
+    - block: sed-opal: kmalloc the cmd/resp buffers
+    - siox: fix possible memory leak in siox_device_add()
+    - parport_pc: Avoid FIFO port location truncation
+    - pinctrl: devicetree: fix null pointer dereferencing in pinctrl_dt_to_map
+    - arm64: dts: imx8mm: Fix NAND controller size-cells
+    - arm64: dts: imx8mn: Fix NAND controller size-cells
+    - ata: libata-transport: fix double ata_host_put() in ata_tport_add()
+    - net: bgmac: Drop free_netdev() from bgmac_enet_remove()
+    - mISDN: fix possible memory leak in mISDN_dsp_element_register()
+    - net: liquidio: release resources when liquidio driver open failed
+    - mISDN: fix misuse of put_device() in mISDN_register_device()
+    - net: macvlan: Use built-in RCU list checking
+    - net: caif: fix double disconnect client in chnl_net_open()
+    - bnxt_en: Remove debugfs when pci_register_driver failed
+    - xen/pcpu: fix possible memory leak in register_pcpu()
+    - drbd: use after free in drbd_create_device()
+    - platform/x86/intel: pmc: Don't unconditionally attach Intel PMC when
+      virtualized
+    - net/x25: Fix skb leak in x25_lapb_receive_frame()
+    - cifs: Fix wrong return value checking when GETFLAGS
+    - net: thunderbolt: Fix error handling in tbnet_init()
+    - cifs: add check for returning value of SMB2_set_info_init
+    - ftrace: Fix the possible incorrect kernel message
+    - ftrace: Optimize the allocation for mcount entries
+    - ftrace: Fix null pointer dereference in ftrace_add_mod()
+    - ring_buffer: Do not deactivate non-existant pages
+    - ALSA: usb-audio: Drop snd_BUG_ON() from snd_usbmidi_output_open()
+    - Revert "usb: dwc3: disable USB core PHY management"
+    - slimbus: stream: correct presence rate frequencies
+    - speakup: fix a segfault caused by switching consoles
+    - USB: serial: option: add Sierra Wireless EM9191
+    - USB: serial: option: remove old LARA-R6 PID
+    - USB: serial: option: add u-blox LARA-R6 00B modem
+    - USB: serial: option: add u-blox LARA-L6 modem
+    - USB: serial: option: add Fibocom FM160 0x0111 composition
+    - usb: add NO_LPM quirk for Realforce 87U Keyboard
+    - usb: chipidea: fix deadlock in ci_otg_del_timer
+    - iio: adc: at91_adc: fix possible memory leak in at91_adc_allocate_trigger()
+    - iio: trigger: sysfs: fix possible memory leak in iio_sysfs_trig_init()
+    - iio: pressure: ms5611: changed hardcoded SPI speed to value limited
+    - dm ioctl: fix misbehavior if list_versions races with module loading
+    - serial: 8250: Fall back to non-DMA Rx if IIR_RDI occurs
+    - serial: 8250_lpss: Configure DMA also w/o DMA filter
+    - Input: iforce - invert valid length check when fetching device IDs
+    - scsi: zfcp: Fix double free of FSF request when qdio send fails
+    - mmc: core: properly select voltage range without power cycle
+    - mmc: sdhci-pci-o2micro: fix card detect fail issue caused by CD# debounce
+      timeout
+    - mmc: sdhci-pci: Fix possible memory leak caused by missing pci_dev_put()
+    - docs: update mediator contact information in CoC doc
+    - misc/vmw_vmci: fix an infoleak in vmci_host_do_receive_datagram()
+    - serial: 8250: Flush DMA Rx on RLSI
+    - ring-buffer: Include dropped pages in counting dirty patches
+    - scsi: target: tcm_loop: Fix possible name leak in tcm_loop_setup_hba_bus()
+    - kprobes: Skip clearing aggrprobe's post_handler in kprobe-on-ftrace case
+    - Input: i8042 - fix leaking of platform device on module removal
+    - macvlan: enforce a consistent minimal mtu
+    - tcp: cdg: allow tcp_cdg_release() to be called multiple times
+    - kcm: avoid potential race in kcm_tx_work
+    - bpf, test_run: Fix alignment problem in bpf_prog_test_run_skb()
+    - kcm: close race conditions on sk_receive_queue
+    - 9p: trans_fd/p9_conn_cancel: drop client lock earlier
+    - gfs2: Check sb_bsize_shift after reading superblock
+    - gfs2: Switch from strlcpy to strscpy
+    - 9p/trans_fd: always use O_NONBLOCK read/write
+    - mm: fs: initialize fsdata passed to write_begin/write_end interface
+    - ntfs: fix use-after-free in ntfs_attr_find()
+    - ntfs: fix out-of-bounds read in ntfs_attr_find()
+    - ntfs: check overflow when iterating ATTR_RECORDs
+    - Linux 5.4.225
+
+  * CVE-2022-47520
+    - wifi: wilc1000: validate pairwise and authentication suite offsets
+
+  * CVE-2022-3545
+    - nfp: fix use-after-free in area_cache_get()
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Wed, 01 Feb 2023 15:33:59 +0100
+
+linux (5.4.0-139.156) focal; urgency=medium
+
+  * focal/linux: 5.4.0-139.156 -proposed tracker (LP: #2003486)
+
+  * Revoke & rotate to new signing key (LP: #2002812)
+    - [Packaging] Revoke and rotate to new signing key
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Fri, 20 Jan 2023 15:39:15 +0100
+
+linux (5.4.0-138.155) focal; urgency=medium
+
+  * focal/linux: 5.4.0-138.155 -proposed tracker (LP: #2001845)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update helper scripts
+
+  * Focal update: v5.4.224 upstream stable release (LP: #1999273)
+    - RDMA/cma: Use output interface for net_dev check
+    - IB/hfi1: Correctly move list in sc_disable()
+    - NFSv4.1: Handle RECLAIM_COMPLETE trunking errors
+    - NFSv4.1: We must always send RECLAIM_COMPLETE after a reboot
+    - nfs4: Fix kmemleak when allocate slot failed
+    - net: dsa: Fix possible memory leaks in dsa_loop_init()
+    - RDMA/core: Fix null-ptr-deref in ib_core_cleanup()
+    - RDMA/qedr: clean up work queue on failure in qedr_alloc_resources()
+    - nfc: s3fwrn5: Fix potential memory leak in s3fwrn5_nci_send()
+    - nfc: nfcmrvl: Fix potential memory leak in nfcmrvl_i2c_nci_send()
+    - net: fec: fix improper use of NETDEV_TX_BUSY
+    - ata: pata_legacy: fix pdc20230_set_piomode()
+    - net: sched: Fix use after free in red_enqueue()
+    - net: tun: fix bugs for oversize packet when napi frags enabled
+    - netfilter: nf_tables: release flow rule object from commit path
+    - ipvs: use explicitly signed chars
+    - ipvs: fix WARNING in __ip_vs_cleanup_batch()
+    - ipvs: fix WARNING in ip_vs_app_net_cleanup()
+    - rose: Fix NULL pointer dereference in rose_send_frame()
+    - mISDN: fix possible memory leak in mISDN_register_device()
+    - isdn: mISDN: netjet: fix wrong check of device registration
+    - btrfs: fix inode list leak during backref walking at resolve_indirect_refs()
+    - btrfs: fix inode list leak during backref walking at find_parent_nodes()
+    - btrfs: fix ulist leaks in error paths of qgroup self tests
+    - Bluetooth: L2CAP: fix use-after-free in l2cap_conn_del()
+    - net: mdio: fix undefined behavior in bit shift for __mdiobus_register
+    - net, neigh: Fix null-ptr-deref in neigh_table_clear()
+    - ipv6: fix WARNING in ip6_route_net_exit_late()
+    - media: s5p_cec: limit msg.len to CEC_MAX_MSG_SIZE
+    - media: cros-ec-cec: limit msg.len to CEC_MAX_MSG_SIZE
+    - media: dvb-frontends/drxk: initialize err to 0
+    - media: meson: vdec: fix possible refcount leak in vdec_probe()
+    - scsi: core: Restrict legal sdev_state transitions via sysfs
+    - HID: saitek: add madcatz variant of MMO7 mouse device ID
+    - i2c: xiic: Add platform module alias
+    - xfs: don't fail verifier on empty attr3 leaf block
+    - xfs: use ordered buffers to initialize dquot buffers during quotacheck
+    - xfs: gut error handling in xfs_trans_unreserve_and_mod_sb()
+    - xfs: group quota should return EDQUOT when prj quota enabled
+    - xfs: don't fail unwritten extent conversion on writeback due to edquot
+    - xfs: Add the missed xfs_perag_put() for xfs_ifree_cluster()
+    - Bluetooth: L2CAP: Fix attempting to access uninitialized memory
+    - block, bfq: protect 'bfqd->queued' by 'bfqd->lock'
+    - binder: fix UAF of alloc->vma in race with munmap()
+    - btrfs: fix type of parameter generation in btrfs_get_dentry
+    - tcp/udp: Make early_demux back namespacified.
+    - kprobe: reverse kp->flags when arm_kprobe failed
+    - tools/nolibc/string: Fix memcmp() implementation
+    - tracing/histogram: Update document for KEYS_MAX size
+    - capabilities: fix potential memleak on error path from vfs_getxattr_alloc()
+    - fuse: add file_modified() to fallocate
+    - efi: random: reduce seed size to 32 bytes
+    - perf/x86/intel: Fix pebs event constraints for ICL
+    - perf/x86/intel: Add Cooper Lake stepping to isolation_ucodes[]
+    - ALSA: usb-audio: Add quirks for MacroSilicon MS2100/MS2106 devices
+    - parisc: Make 8250_gsc driver dependend on CONFIG_PARISC
+    - parisc: Export iosapic_serial_irq() symbol for serial port driver
+    - parisc: Avoid printing the hardware path twice
+    - ext4: fix warning in 'ext4_da_release_space'
+    - ext4: fix BUG_ON() when directory entry has invalid rec_len
+    - KVM: x86: Mask off reserved bits in CPUID.8000001AH
+    - KVM: x86: Mask off reserved bits in CPUID.80000008H
+    - KVM: x86: emulator: em_sysexit should update ctxt->mode
+    - KVM: x86: emulator: introduce emulator_recalc_and_set_mode
+    - KVM: x86: emulator: update the emulation mode after CR0 write
+    - mtd: rawnand: gpmi: Set WAIT_FOR_READY timeout based on program/erase times
+    - drm/rockchip: dsi: Force synchronous probe
+    - drm/i915/sdvo: Filter out invalid outputs more sensibly
+    - drm/i915/sdvo: Setup DDC fully before output init
+    - wifi: brcmfmac: Fix potential buffer overflow in brcmf_fweh_event_worker()
+    - ipc: remove memcg accounting for sops objects in do_semtimedop()
+    - Linux 5.4.224
+
+  * Focal update: v5.4.223 upstream stable release (LP: #1999179)
+    - can: j1939: transport: j1939_session_skb_drop_old():
+      spin_unlock_irqrestore() before kfree_skb()
+    - can: kvaser_usb: Fix possible completions during init_completion
+    - ALSA: Use del_timer_sync() before freeing timer
+    - ALSA: au88x0: use explicitly signed char
+    - USB: add RESET_RESUME quirk for NVIDIA Jetson devices in RCM
+    - usb: dwc3: gadget: Stop processing more requests on IMI
+    - usb: dwc3: gadget: Don't set IMI for no_interrupt
+    - usb: bdc: change state when port disconnected
+    - usb: xhci: add XHCI_SPURIOUS_SUCCESS to ASM1042 despite being a V0.96
+      controller
+    - mtd: rawnand: marvell: Use correct logic for nand-keep-config
+    - xhci: Remove device endpoints from bandwidth list when freeing the device
+    - tools: iio: iio_utils: fix digit calculation
+    - iio: light: tsl2583: Fix module unloading
+    - fbdev: smscufx: Fix several use-after-free bugs
+    - mac802154: Fix LQI recording
+    - drm/msm/dsi: fix memory corruption with too many bridges
+    - drm/msm/hdmi: fix memory corruption with too many bridges
+    - mmc: core: Fix kernel panic when remove non-standard SDIO card
+    - kernfs: fix use-after-free in __kernfs_remove
+    - perf auxtrace: Fix address filter symbol name match for modules
+    - s390/futex: add missing EX_TABLE entry to __futex_atomic_op()
+    - s390/pci: add missing EX_TABLE entries to
+      __pcistg_mio_inuser()/__pcilg_mio_inuser()
+    - xfs: finish dfops on every insert range shift iteration
+    - xfs: clear XFS_DQ_FREEING if we can't lock the dquot buffer to flush
+    - xfs: force the log after remapping a synchronous-writes file
+    - Xen/gntdev: don't ignore kernel unmapping error
+    - xen/gntdev: Prevent leaking grants
+    - mm,hugetlb: take hugetlb_lock before decrementing h->resv_huge_pages
+    - net: ieee802154: fix error return code in dgram_bind()
+    - media: v4l2: Fix v4l2_i2c_subdev_set_name function documentation
+    - drm/msm: Fix return type of mdp4_lvds_connector_mode_valid
+    - arc: iounmap() arg is volatile
+    - ALSA: ac97: fix possible memory leak in snd_ac97_dev_register()
+    - tipc: fix a null-ptr-deref in tipc_topsrv_accept
+    - net: netsec: fix error handling in netsec_register_mdio()
+    - x86/unwind/orc: Fix unreliable stack dump with gcov
+    - amd-xgbe: fix the SFP compliance codes check for DAC cables
+    - amd-xgbe: add the bit rate quirk for Molex cables
+    - kcm: annotate data-races around kcm->rx_psock
+    - kcm: annotate data-races around kcm->rx_wait
+    - net: fix UAF issue in nfqnl_nf_hook_drop() when ops_init() failed
+    - net: lantiq_etop: don't free skb when returning NETDEV_TX_BUSY
+    - tcp: fix indefinite deferral of RTO with SACK reneging
+    - can: mscan: mpc5xxx: mpc5xxx_can_probe(): add missing put_clock() in error
+      path
+    - PM: hibernate: Allow hybrid sleep to work with s2idle
+    - media: vivid: s_fbuf: add more sanity checks
+    - media: vivid: dev->bitmap_cap wasn't freed in all cases
+    - media: v4l2-dv-timings: add sanity checks for blanking values
+    - media: videodev2.h: V4L2_DV_BT_BLANKING_HEIGHT should check 'interlaced'
+    - i40e: Fix ethtool rx-flow-hash setting for X722
+    - i40e: Fix VF hang when reset is triggered on another VF
+    - i40e: Fix flow-type by setting GL_HASH_INSET registers
+    - net: ksz884x: fix missing pci_disable_device() on error in pcidev_init()
+    - PM: domains: Fix handling of unavailable/disabled idle states
+    - ALSA: aoa: i2sbus: fix possible memory leak in i2sbus_add_dev()
+    - ALSA: aoa: Fix I2S device accounting
+    - openvswitch: switch from WARN to pr_warn
+    - net: ehea: fix possible memory leak in ehea_register_port()
+    - nh: fix scope used to find saddr when adding non gw nh
+    - net/mlx5e: Do not increment ESN when updating IPsec ESN state
+    - net/mlx5: Fix possible use-after-free in async command interface
+    - net: enetc: survive memory pressure without crashing
+    - can: rcar_canfd: rcar_canfd_handle_global_receive(): fix IRQ storm on global
+      FIFO receive
+    - Linux 5.4.223
+
+  * Focal update: v5.4.222 upstream stable release (LP: #1997994)
+    - once: fix section mismatch on clang builds
+    - Linux 5.4.222
+
+  * Focal update: v5.4.221 upstream stable release (LP: #1997993)
+    - xfs: open code insert range extent split helper
+    - xfs: rework insert range into an atomic operation
+    - xfs: rework collapse range into an atomic operation
+    - xfs: add a function to deal with corrupt buffers post-verifiers
+    - xfs: xfs_buf_corruption_error should take __this_address
+    - xfs: fix buffer corruption reporting when xfs_dir3_free_header_check fails
+    - xfs: check owner of dir3 data blocks
+    - xfs: check owner of dir3 blocks
+    - xfs: Use scnprintf() for avoiding potential buffer overflow
+    - xfs: remove the xfs_disk_dquot_t and xfs_dquot_t
+    - xfs: remove the xfs_dq_logitem_t typedef
+    - xfs: remove the xfs_qoff_logitem_t typedef
+    - xfs: Replace function declaration by actual definition
+    - xfs: factor out quotaoff intent AIL removal and memory free
+    - xfs: fix unmount hang and memory leak on shutdown during quotaoff
+    - xfs: preserve default grace interval during quotacheck
+    - xfs: Lower CIL flush limit for large logs
+    - xfs: Throttle commits on delayed background CIL push
+    - xfs: factor common AIL item deletion code
+    - xfs: tail updates only need to occur when LSN changes
+    - xfs: don't write a corrupt unmount record to force summary counter recalc
+    - xfs: trylock underlying buffer on dquot flush
+    - xfs: factor out a new xfs_log_force_inode helper
+    - xfs: reflink should force the log out if mounted with wsync
+    - xfs: move inode flush to the sync workqueue
+    - xfs: fix use-after-free on CIL context on shutdown
+    - ocfs2: clear dinode links count in case of error
+    - ocfs2: fix BUG when iput after ocfs2_mknod fails
+    - x86/microcode/AMD: Apply the patch early on every logical thread
+    - hwmon/coretemp: Handle large core ID value
+    - ata: ahci-imx: Fix MODULE_ALIAS
+    - ata: ahci: Match EM_MAX_SLOTS with SATA_PMP_MAX_PORTS
+    - KVM: arm64: vgic: Fix exit condition in scan_its_table()
+    - media: venus: dec: Handle the case where find_format fails
+    - [Config] updateconfigs for ARM64_ERRATUM_1742098
+    - arm64: errata: Remove AES hwcap for COMPAT tasks
+    - r8152: add PID for the Lenovo OneLink+ Dock
+    - btrfs: fix processing of delayed data refs during backref walking
+    - btrfs: fix processing of delayed tree block refs during backref walking
+    - ACPI: extlog: Handle multiple records
+    - tipc: Fix recognition of trial period
+    - tipc: fix an information leak in tipc_topsrv_kern_subscr
+    - HID: magicmouse: Do not set BTN_MOUSE on double report
+    - net/atm: fix proc_mpc_write incorrect return value
+    - net: phy: dp83867: Extend RX strap quirk for SGMII mode
+    - net: sched: cake: fix null pointer access issue when cake_init() fails
+    - net: hns: fix possible memory leak in hnae_ae_register()
+    - iommu/vt-d: Clean up si_domain in the init_dmars() error path
+    - arm64: topology: move store_cpu_topology() to shared code
+    - riscv: topology: fix default topology reporting
+    - ACPI: video: Force backlight native for more TongFang devices
+    - Makefile.debug: re-enable debug info for .S files
+    - hv_netvsc: Fix race between VF offering and VF association message from host
+    - mm: /proc/pid/smaps_rollup: fix no vma's null-deref
+    - Linux 5.4.221
+
+  * Focal update: v5.4.220 upstream stable release (LP: #1996812)
+    - ALSA: oss: Fix potential deadlock at unregistration
+    - ALSA: rawmidi: Drop register_mutex in snd_rawmidi_free()
+    - ALSA: usb-audio: Fix potential memory leaks
+    - ALSA: usb-audio: Fix NULL dererence at error path
+    - ALSA: hda/realtek: remove ALC289_FIXUP_DUAL_SPK for Dell 5530
+    - ALSA: hda/realtek: Correct pin configs for ASUS G533Z
+    - ALSA: hda/realtek: Add quirk for ASUS GV601R laptop
+    - ALSA: hda/realtek: Add Intel Reference SSID to support headset keys
+    - mtd: rawnand: atmel: Unmap streaming DMA mappings
+    - cifs: destage dirty pages before re-reading them for cache=none
+    - cifs: Fix the error length of VALIDATE_NEGOTIATE_INFO message
+    - iio: dac: ad5593r: Fix i2c read protocol requirements
+    - iio: pressure: dps310: Refactor startup procedure
+    - iio: pressure: dps310: Reset chip after timeout
+    - usb: add quirks for Lenovo OneLink+ Dock
+    - can: kvaser_usb: Fix use of uninitialized completion
+    - can: kvaser_usb_leaf: Fix overread with an invalid command
+    - can: kvaser_usb_leaf: Fix TX queue out of sync after restart
+    - can: kvaser_usb_leaf: Fix CAN state after restart
+    - mmc: sdhci-sprd: Fix minimum clock limit
+    - fs: dlm: fix race between test_bit() and queue_work()
+    - fs: dlm: handle -EBUSY first in lock arg validation
+    - HID: multitouch: Add memory barriers
+    - quota: Check next/prev free block number after reading from quota file
+    - ASoC: wcd9335: fix order of Slimbus unprepare/disable
+    - regulator: qcom_rpm: Fix circular deferral regression
+    - RISC-V: Make port I/O string accessors actually work
+    - parisc: fbdev/stifb: Align graphics memory size to 4MB
+    - riscv: Allow PROT_WRITE-only mmap()
+    - riscv: Pass -mno-relax only on lld < 15.0.0
+    - UM: cpuinfo: Fix a warning for CONFIG_CPUMASK_OFFSTACK
+    - PCI: Sanitise firmware BAR assignments behind a PCI-PCI bridge
+    - powerpc/boot: Explicitly disable usage of SPE instructions
+    - fbdev: smscufx: Fix use-after-free in ufx_ops_open()
+    - btrfs: fix race between quota enable and quota rescan ioctl
+    - f2fs: increase the limit for reserve_root
+    - f2fs: fix to do sanity check on destination blkaddr during recovery
+    - f2fs: fix to do sanity check on summary info
+    - nilfs2: fix use-after-free bug of struct nilfs_root
+    - jbd2: wake up journal waiters in FIFO order, not LIFO
+    - ext4: avoid crash when inline data creation follows DIO write
+    - ext4: fix null-ptr-deref in ext4_write_info
+    - ext4: make ext4_lazyinit_thread freezable
+    - ext4: place buffer head allocation before handle start
+    - livepatch: fix race between fork and KLP transition
+    - ftrace: Properly unset FTRACE_HASH_FL_MOD
+    - ring-buffer: Allow splice to read previous partially read pages
+    - ring-buffer: Have the shortest_full queue be the shortest not longest
+    - ring-buffer: Check pending waiters when doing wake ups as well
+    - ring-buffer: Fix race between reset page and reading page
+    - media: cedrus: Set the platform driver data earlier
+    - KVM: x86/emulator: Fix handing of POP SS to correctly set interruptibility
+    - KVM: nVMX: Unconditionally purge queued/injected events on nested "exit"
+    - KVM: VMX: Drop bits 31:16 when shoving exception error code into VMCS
+    - gcov: support GCC 12.1 and newer compilers
+    - drm/nouveau: fix a use-after-free in nouveau_gem_prime_import_sg_table()
+    - selinux: use "grep -E" instead of "egrep"
+    - tracing: Disable interrupt or preemption before acquiring arch_spinlock_t
+    - userfaultfd: open userfaultfds with O_RDONLY
+    - sh: machvec: Use char[] for section boundaries
+    - ARM: 9247/1: mm: set readonly for MT_MEMORY_RO with ARM_LPAE
+    - nfsd: Fix a memory leak in an error handling path
+    - wifi: ath10k: add peer map clean up for peer delete in ath10k_sta_state()
+    - wifi: mac80211: allow bw change during channel switch in mesh
+    - bpftool: Fix a wrong type cast in btf_dumper_int
+    - x86/resctrl: Fix to restore to original value when re-enabling hardware
+      prefetch register
+    - wifi: rtl8xxxu: tighten bounds checking in rtl8xxxu_read_efuse()
+    - spi: qup: add missing clk_disable_unprepare on error in spi_qup_resume()
+    - spi: qup: add missing clk_disable_unprepare on error in
+      spi_qup_pm_resume_runtime()
+    - wifi: rtl8xxxu: Fix skb misuse in TX queue selection
+    - bpf: btf: fix truncated last_member_type_id in btf_struct_resolve
+    - wifi: rtl8xxxu: gen2: Fix mistake in path B IQ calibration
+    - net: fs_enet: Fix wrong check in do_pd_setup
+    - bpf: Ensure correct locking around vulnerable function find_vpid()
+    - x86/microcode/AMD: Track patch allocation size explicitly
+    - spi/omap100k:Fix PM disable depth imbalance in omap1_spi100k_probe
+    - netfilter: nft_fib: Fix for rpath check with VRF devices
+    - spi: s3c64xx: Fix large transfers with DMA
+    - vhost/vsock: Use kvmalloc/kvfree for larger packets.
+    - sctp: handle the error returned from sctp_auth_asoc_init_active_key
+    - tcp: fix tcp_cwnd_validate() to not forget is_cwnd_limited
+    - net: rds: don't hold sock lock when cancelling work from
+      rds_tcp_reset_callbacks()
+    - bnx2x: fix potential memory leak in bnx2x_tpa_stop()
+    - net/ieee802154: reject zero-sized raw_sendmsg()
+    - once: add DO_ONCE_SLOW() for sleepable contexts
+    - net: mvpp2: fix mvpp2 debugfs leak
+    - drm: bridge: adv7511: fix CEC power down control register offset
+    - drm/mipi-dsi: Detach devices when removing the host
+    - platform/chrome: fix double-free in chromeos_laptop_prepare()
+    - platform/chrome: fix memory corruption in ioctl
+    - platform/x86: msi-laptop: Fix old-ec check for backlight registering
+    - platform/x86: msi-laptop: Fix resource cleanup
+    - drm: fix drm_mipi_dbi build errors
+    - drm/bridge: megachips: Fix a null pointer dereference bug
+    - ASoC: rsnd: Add check for rsnd_mod_power_on
+    - ALSA: hda: beep: Simplify keep-power-at-enable behavior
+    - drm/omap: dss: Fix refcount leak bugs
+    - mmc: au1xmmc: Fix an error handling path in au1xmmc_probe()
+    - ASoC: eureka-tlv320: Hold reference returned from of_find_xxx API
+    - drm/msm/dpu: index dpu_kms->hw_vbif using vbif_idx
+    - ALSA: dmaengine: increment buffer pointer atomically
+    - mmc: wmt-sdmmc: Fix an error handling path in wmt_mci_probe()
+    - ASoC: wm8997: Fix PM disable depth imbalance in wm8997_probe
+    - ASoC: wm5110: Fix PM disable depth imbalance in wm5110_probe
+    - ASoC: wm5102: Fix PM disable depth imbalance in wm5102_probe
+    - ALSA: hda/hdmi: Don't skip notification handling during PM operation
+    - memory: pl353-smc: Fix refcount leak bug in pl353_smc_probe()
+    - memory: of: Fix refcount leak bug in of_get_ddr_timings()
+    - soc: qcom: smsm: Fix refcount leak bugs in qcom_smsm_probe()
+    - soc: qcom: smem_state: Add refcounting for the 'state->of_node'
+    - ARM: dts: turris-omnia: Fix mpp26 pin name and comment
+    - ARM: dts: kirkwood: lsxl: fix serial line
+    - ARM: dts: kirkwood: lsxl: remove first ethernet port
+    - ARM: dts: exynos: correct s5k6a3 reset polarity on Midas family
+    - ARM: Drop CMDLINE_* dependency on ATAGS
+    - ARM: dts: exynos: fix polarity of VBUS GPIO of Origen
+    - iio: adc: at91-sama5d2_adc: fix AT91_SAMA5D2_MR_TRACKTIM_MAX
+    - iio: adc: at91-sama5d2_adc: check return status for pressure and touch
+    - iio: adc: at91-sama5d2_adc: lock around oversampling and sample freq
+    - iio: inkern: only release the device node when done with it
+    - iio: ABI: Fix wrong format of differential capacitance channel ABI.
+    - clk: meson: Hold reference returned by of_get_parent()
+    - clk: oxnas: Hold reference returned by of_get_parent()
+    - clk: berlin: Add of_node_put() for of_get_parent()
+    - clk: tegra: Fix refcount leak in tegra210_clock_init
+    - clk: tegra: Fix refcount leak in tegra114_clock_init
+    - clk: tegra20: Fix refcount leak in tegra20_clock_init
+    - HSI: omap_ssi: Fix refcount leak in ssi_probe
+    - HSI: omap_ssi_port: Fix dma_map_sg error check
+    - media: exynos4-is: fimc-is: Add of_node_put() when breaking out of loop
+    - tty: xilinx_uartps: Fix the ignore_status
+    - media: xilinx: vipp: Fix refcount leak in xvip_graph_dma_init
+    - RDMA/rxe: Fix "kernel NULL pointer dereference" error
+    - RDMA/rxe: Fix the error caused by qp->sk
+    - misc: ocxl: fix possible refcount leak in afu_ioctl()
+    - dyndbg: fix module.dyndbg handling
+    - dyndbg: let query-modname override actual module name
+    - mtd: devices: docg3: check the return value of devm_ioremap() in the probe
+    - RDMA/siw: Always consume all skbuf data in sk_data_ready() upcall.
+    - ata: fix ata_id_sense_reporting_enabled() and ata_id_has_sense_reporting()
+    - ata: fix ata_id_has_devslp()
+    - ata: fix ata_id_has_ncq_autosense()
+    - ata: fix ata_id_has_dipm()
+    - mtd: rawnand: meson: fix bit map use in meson_nfc_ecc_correct()
+    - md/raid5: Ensure stripe_fill happens on non-read IO with journal
+    - xhci: Don't show warning for reinit on known broken suspend
+    - usb: gadget: function: fix dangling pnp_string in f_printer.c
+    - drivers: serial: jsm: fix some leaks in probe
+    - tty: serial: fsl_lpuart: disable dma rx/tx use flags in lpuart_dma_shutdown
+    - phy: qualcomm: call clk_disable_unprepare in the error handling
+    - staging: vt6655: fix some erroneous memory clean-up loops
+    - firmware: google: Test spinlock on panic path to avoid lockups
+    - serial: 8250: Fix restoring termios speed after suspend
+    - scsi: libsas: Fix use-after-free bug in smp_execute_task_sg()
+    - fsi: core: Check error number after calling ida_simple_get
+    - mfd: intel_soc_pmic: Fix an error handling path in
+      intel_soc_pmic_i2c_probe()
+    - mfd: fsl-imx25: Fix an error handling path in mx25_tsadc_setup_irq()
+    - mfd: lp8788: Fix an error handling path in lp8788_probe()
+    - mfd: lp8788: Fix an error handling path in lp8788_irq_init() and
+      lp8788_irq_init()
+    - mfd: fsl-imx25: Fix check for platform_get_irq() errors
+    - mfd: sm501: Add check for platform_driver_register()
+    - clk: mediatek: mt8183: mfgcfg: Propagate rate changes to parent
+    - dmaengine: ioat: stop mod_timer from resurrecting deleted timer in
+      __cleanup()
+    - spmi: pmic-arb: correct duplicate APID to PPID mapping logic
+    - clk: bcm2835: fix bcm2835_clock_rate_from_divisor declaration
+    - clk: ti: dra7-atl: Fix reference leak in of_dra7_atl_clk_probe
+    - clk: ast2600: BCLK comes from EPLL
+    - mailbox: bcm-ferxrm-mailbox: Fix error check for dma_map_sg
+    - powerpc/math_emu/efp: Include module.h
+    - powerpc/sysdev/fsl_msi: Add missing of_node_put()
+    - powerpc/pci_dn: Add missing of_node_put()
+    - powerpc/powernv: add missing of_node_put() in opal_export_attrs()
+    - x86/hyperv: Fix 'struct hv_enlightened_vmcs' definition
+    - powerpc/64s: Fix GENERIC_CPU build flags for PPC970 / G5
+    - powerpc: Fix SPE Power ISA properties for e500v1 platforms
+    - cgroup/cpuset: Enable update_tasks_cpumask() on top_cpuset
+    - iommu/omap: Fix buffer overflow in debugfs
+    - crypto: akcipher - default implementation for setting a private key
+    - crypto: ccp - Release dma channels before dmaengine unrgister
+    - iommu/iova: Fix module config properly
+    - kbuild: remove the target in signal traps when interrupted
+    - crypto: cavium - prevent integer overflow loading firmware
+    - f2fs: fix race condition on setting FI_NO_EXTENT flag
+    - ACPI: video: Add Toshiba Satellite/Portege Z830 quirk
+    - MIPS: BCM47XX: Cast memcmp() of function to (void *)
+    - powercap: intel_rapl: fix UBSAN shift-out-of-bounds issue
+    - thermal: intel_powerclamp: Use get_cpu() instead of smp_processor_id() to
+      avoid crash
+    - NFSD: Return nfserr_serverfault if splice_ok but buf->pages have data
+    - wifi: brcmfmac: fix invalid address access when enabling SCAN log level
+    - bpftool: Clear errno after libcap's checks
+    - openvswitch: Fix double reporting of drops in dropwatch
+    - openvswitch: Fix overreporting of drops in dropwatch
+    - tcp: annotate data-race around tcp_md5sig_pool_populated
+    - wifi: ath9k: avoid uninit memory read in ath9k_htc_rx_msg()
+    - xfrm: Update ipcomp_scratches with NULL when freed
+    - wifi: brcmfmac: fix use-after-free bug in brcmf_netdev_start_xmit()
+    - Bluetooth: L2CAP: initialize delayed works at l2cap_chan_create()
+    - Bluetooth: hci_sysfs: Fix attempting to call device_add multiple times
+    - can: bcm: check the result of can_send() in bcm_can_tx()
+    - wifi: rt2x00: don't run Rt5592 IQ calibration on MT7620
+    - wifi: rt2x00: set correct TX_SW_CFG1 MAC register for MT7620
+    - wifi: rt2x00: set VGC gain for both chains of MT7620
+    - wifi: rt2x00: set SoC wmac clock register
+    - wifi: rt2x00: correctly set BBP register 86 for MT7620
+    - net: If sock is dead don't access sock's sk_wq in sk_stream_wait_memory
+    - Bluetooth: L2CAP: Fix user-after-free
+    - drm/nouveau/nouveau_bo: fix potential memory leak in nouveau_bo_alloc()
+    - drm: Use size_t type for len variable in drm_copy_field()
+    - drm: Prevent drm_copy_field() to attempt copying a NULL pointer
+    - drm/amd/display: fix overflow on MIN_I64 definition
+    - drm/vc4: vec: Fix timings for VEC modes
+    - drm: panel-orientation-quirks: Add quirk for Anbernic Win600
+    - platform/x86: msi-laptop: Change DMI match / alias strings to fix module
+      autoloading
+    - drm/amdgpu: fix initial connector audio value
+    - mmc: sdhci-msm: add compatible string check for sdm670
+    - ARM: dts: imx7d-sdb: config the max pressure for tsc2046
+    - ARM: dts: imx6q: add missing properties for sram
+    - ARM: dts: imx6dl: add missing properties for sram
+    - ARM: dts: imx6qp: add missing properties for sram
+    - ARM: dts: imx6sl: add missing properties for sram
+    - ARM: dts: imx6sll: add missing properties for sram
+    - ARM: dts: imx6sx: add missing properties for sram
+    - btrfs: scrub: try to fix super block errors
+    - clk: zynqmp: Fix stack-out-of-bounds in strncpy`
+    - media: cx88: Fix a null-ptr-deref bug in buffer_prepare()
+    - clk: zynqmp: pll: rectify rate rounding in zynqmp_pll_round_rate
+    - scsi: 3w-9xxx: Avoid disabling device if failing to enable it
+    - nbd: Fix hung when signal interrupts nbd_start_device_ioctl()
+    - power: supply: adp5061: fix out-of-bounds read in adp5061_get_chg_type()
+    - staging: vt6655: fix potential memory leak
+    - ata: libahci_platform: Sanity check the DT child nodes number
+    - bcache: fix set_at_max_writeback_rate() for multiple attached devices
+    - HID: roccat: Fix use-after-free in roccat_read()
+    - md/raid5: Wait for MD_SB_CHANGE_PENDING in raid5d
+    - usb: host: xhci: Fix potential memory leak in xhci_alloc_stream_info()
+    - usb: musb: Fix musb_gadget.c rxstate overflow bug
+    - Revert "usb: storage: Add quirk for Samsung Fit flash"
+    - staging: rtl8723bs: fix a potential memory leak in rtw_init_cmd_priv()
+    - nvme: copy firmware_rev on each init
+    - nvmet-tcp: add bounds check on Transfer Tag
+    - usb: idmouse: fix an uninit-value in idmouse_open
+    - clk: bcm2835: Make peripheral PLLC critical
+    - perf intel-pt: Fix segfault in intel_pt_print_info() with uClibc
+    - net: ieee802154: return -EINVAL for unknown addr type
+    - Revert "net/ieee802154: reject zero-sized raw_sendmsg()"
+    - net/ieee802154: don't warn zero-sized raw_sendmsg()
+    - ext4: continue to expand file system when the target size doesn't reach
+    - efi: libstub: drop pointless get_memory_map() call
+    - inet: fully convert sk->sk_rx_dst to RCU rules
+    - thermal: intel_powerclamp: Use first online CPU as control_cpu
+    - Linux 5.4.220
+
+  * Focal update: v5.4.219 upstream stable release (LP: #1996804)
+    - Linux 5.4.219
+
+ -- Luke Nowakowski-Krijger <luke.nowakowskikrijger@canonical.com>  Fri, 06 Jan 2023 08:50:27 -0800
+
+linux (5.4.0-137.154) focal; urgency=medium
+
+  * focal/linux: 5.4.0-137.154 -proposed tracker (LP: #2001969)
+
+  * CVE-2022-3643
+    - xen/netback: Ensure protocol headers don't fall in the non-linear area
+
+  * CVE-2022-43945
+    - NFSD: Cap rsize_bop result based on send buffer size
+
+  * CVE-2022-45934
+    - Bluetooth: L2CAP: Fix u8 overflow
+
+  * CVE-2022-42896
+    - Bluetooth: L2CAP: Fix accepting connection request for invalid SPSM
+    - Bluetooth: L2CAP: Fix l2cap_global_chan_by_psm
+
+ -- Thadeu Lima de Souza Cascardo <cascardo@canonical.com>  Thu, 05 Jan 2023 13:08:58 -0300
+
+linux (5.4.0-136.153) focal; urgency=medium
+
+  * focal/linux: 5.4.0-136.153 -proposed tracker (LP: #1997835)
+
+  * Expose built-in trusted and revoked certificates (LP: #1996892)
+    - [Packaging] Expose built-in trusted and revoked certificates
+
+  * [UBUNTU 20.04] KVM: PV: ext call delivered twice when receiver in PSW wait
+    (LP: #1995941)
+    - KVM: s390: pv: don't present the ecall interrupt twice
+
+  * [UBUNTU 20.04] boot: Add s390x secure boot trailer (LP: #1996071)
+    - s390/boot: add secure boot trailer
+
+  * Fix rfkill causing soft blocked wifi (LP: #1996198)
+    - platform/x86: hp_wmi: Fix rfkill causing soft blocked wifi
+
+  * md: Replace snprintf with scnprintf (LP: #1993315)
+    - md: Replace snprintf with scnprintf
+
+  * input/keyboard: the keyboard on some Asus laptops can't work (LP: #1992266)
+    - ACPI: resource: Skip IRQ override on Asus Vivobook K3402ZA/K3502ZA
+    - ACPI: resource: Add ASUS model S5402ZA to quirks
+
+  * Focal update: v5.4.218 upstream stable release (LP: #1995530)
+    - mm: pagewalk: Fix race between unmap and page walker
+    - perf tools: Fixup get_current_dir_name() compilation
+    - firmware: arm_scmi: Add SCMI PM driver remove routine
+    - dmaengine: xilinx_dma: cleanup for fetching xlnx,num-fstores property
+    - dmaengine: xilinx_dma: Report error in case of dma_set_mask_and_coherent API
+      failure
+    - ARM: dts: fix Moxa SDIO 'compatible', remove 'sdhci' misnomer
+    - scsi: qedf: Fix a UAF bug in __qedf_probe()
+    - net/ieee802154: fix uninit value bug in dgram_sendmsg
+    - um: Cleanup syscall_handler_t cast in syscalls_32.h
+    - um: Cleanup compiler warning in arch/x86/um/tls_32.c
+    - arch: um: Mark the stack non-executable to fix a binutils warning
+    - usb: mon: make mmapped memory read only
+    - USB: serial: ftdi_sio: fix 300 bps rate for SIO
+    - mmc: core: Replace with already defined values for readability
+    - mmc: core: Terminate infinite loop in SD-UHS voltage switch
+    - rpmsg: qcom: glink: replace strncpy() with strscpy_pad()
+    - nilfs2: fix leak of nilfs_root in case of writer thread creation failure
+    - nilfs2: replace WARN_ONs by nilfs_error for checkpoint acquisition failure
+    - ceph: don't truncate file in atomic_open
+    - random: clamp credited irq bits to maximum mixed
+    - ALSA: hda: Fix position reporting on Poulsbo
+    - efi: Correct Macmini DMI match in uefi cert quirk
+    - USB: serial: qcserial: add new usb-id for Dell branded EM7455
+    - random: restore O_NONBLOCK support
+    - random: avoid reading two cache lines on irq randomness
+    - random: use expired timer rather than wq for mixing fast pool
+    - Input: xpad - add supported devices as contributed on github
+    - Input: xpad - fix wireless 360 controller breaking after suspend
+    - Linux 5.4.218
+
+  * Focal update: v5.4.217 upstream stable release (LP: #1995528)
+    - xfs: fix misuse of the XFS_ATTR_INCOMPLETE flag
+    - xfs: introduce XFS_MAX_FILEOFF
+    - xfs: truncate should remove all blocks, not just to the end of the page
+      cache
+    - xfs: fix s_maxbytes computation on 32-bit kernels
+    - xfs: fix IOCB_NOWAIT handling in xfs_file_dio_aio_read
+    - xfs: refactor remote attr value buffer invalidation
+    - xfs: fix memory corruption during remote attr value buffer invalidation
+    - xfs: move incore structures out of xfs_da_format.h
+    - xfs: streamline xfs_attr3_leaf_inactive
+    - xfs: fix uninitialized variable in xfs_attr3_leaf_inactive
+    - xfs: remove unused variable 'done'
+    - Makefile.extrawarn: Move -Wcast-function-type-strict to W=1
+    - docs: update mediator information in CoC docs
+    - Linux 5.4.217
+
+  * Focal update: v5.4.216 upstream stable release (LP: #1995526)
+    - uas: add no-uas quirk for Hiksemi usb_disk
+    - usb-storage: Add Hiksemi USB3-FW to IGNORE_UAS
+    - uas: ignore UAS for Thinkplus chips
+    - net: usb: qmi_wwan: Add new usb-id for Dell branded EM7455
+    - clk: ingenic-tcu: Properly enable registers before accessing timers
+    - ARM: dts: integrator: Tag PCI host with device_type
+    - ntfs: fix BUG_ON in ntfs_lookup_inode_by_name()
+    - libata: add ATA_HORKAGE_NOLPM for Pioneer BDR-207M and BDR-205
+    - mmc: moxart: fix 4-bit bus width and remove 8-bit bus width
+    - mm/page_alloc: fix race condition between build_all_zonelists and page
+      allocation
+    - mm: prevent page_frag_alloc() from corrupting the memory
+    - mm/migrate_device.c: flush TLB while holding PTL
+    - mm: fix madivse_pageout mishandling on non-LRU page
+    - media: dvb_vb2: fix possible out of bound access
+    - ARM: dts: Move am33xx and am43xx mmc nodes to sdhci-omap driver
+    - ARM: dts: am33xx: Fix MMCHS0 dma properties
+    - soc: sunxi: sram: Actually claim SRAM regions
+    - soc: sunxi: sram: Prevent the driver from being unbound
+    - soc: sunxi_sram: Make use of the helper function
+      devm_platform_ioremap_resource()
+    - soc: sunxi: sram: Fix probe function ordering issues
+    - soc: sunxi: sram: Fix debugfs info for A64 SRAM C
+    - Revert "drm: bridge: analogix/dp: add panel prepare/unprepare in
+      suspend/resume time"
+    - Input: melfas_mip4 - fix return value check in mip4_probe()
+    - usbnet: Fix memory leak in usbnet_disconnect()
+    - nvme: add new line after variable declatation
+    - nvme: Fix IOC_PR_CLEAR and IOC_PR_RELEASE ioctls for nvme devices
+    - selftests: Fix the if conditions of in test_extra_filter()
+    - clk: imx: imx6sx: remove the SET_RATE_PARENT flag for QSPI clocks
+    - clk: iproc: Do not rely on node name for correct PLL setup
+    - Linux 5.4.216
+
+  * Focal update: v5.4.215 upstream stable release (LP: #1993203)
+    - of: fdt: fix off-by-one error in unflatten_dt_nodes()
+    - NFSv4: Turn off open-by-filehandle and NFS re-export for NFSv4.0
+    - gpio: mpc8xxx: Fix support for IRQ_TYPE_LEVEL_LOW flow_type in mpc85xx
+    - drm/meson: Correct OSD1 global alpha value
+    - drm/meson: Fix OSD1 RGB to YCbCr coefficient
+    - parisc: ccio-dma: Add missing iounmap in error path in ccio_probe()
+    - ALSA: pcm: oss: Fix race at SNDCTL_DSP_SYNC
+    - task_stack, x86/cea: Force-inline stack helpers
+    - tracing: hold caller_addr to hardirq_{enable,disable}_ip
+    - cifs: revalidate mapping when doing direct writes
+    - cifs: don't send down the destination address to sendmsg for a SOCK_STREAM
+    - MAINTAINERS: add Chandan as xfs maintainer for 5.4.y
+    - iomap: iomap that extends beyond EOF should be marked dirty
+    - ASoC: nau8824: Fix semaphore unbalance at error paths
+    - regulator: pfuze100: Fix the global-out-of-bounds access in
+      pfuze100_regulator_probe()
+    - rxrpc: Fix local destruction being repeated
+    - rxrpc: Fix calc of resend age
+    - ALSA: hda/sigmatel: Keep power up while beep is enabled
+    - ALSA: hda/tegra: Align BDL entry to 4KB boundary
+    - net: usb: qmi_wwan: add Quectel RM520N
+    - afs: Return -EAGAIN, not -EREMOTEIO, when a file already locked
+    - MIPS: OCTEON: irq: Fix octeon_irq_force_ciu_mapping()
+    - mksysmap: Fix the mismatch of 'L0' symbols in System.map
+    - video: fbdev: pxa3xx-gcu: Fix integer overflow in pxa3xx_gcu_write
+    - cgroup: Add missing cpus_read_lock() to cgroup_attach_task_all()
+    - ALSA: hda/sigmatel: Fix unused variable warning for beep power change
+    - usb: dwc3: gadget: Avoid starting DWC3 gadget during UDC unbind
+    - usb: dwc3: Issue core soft reset before enabling run/stop
+    - usb: dwc3: gadget: Prevent repeat pullup()
+    - usb: dwc3: gadget: Refactor pullup()
+    - usb: dwc3: gadget: Don't modify GEVNTCOUNT in pullup()
+    - usb: dwc3: gadget: Avoid duplicate requests to enable Run/Stop
+    - usb: xhci-mtk: get the microframe boundary for ESIT
+    - usb: xhci-mtk: add only one extra CS for FS/LS INTR
+    - usb: xhci-mtk: use @sch_tt to check whether need do TT schedule
+    - usb: xhci-mtk: add a function to (un)load bandwidth info
+    - usb: xhci-mtk: add some schedule error number
+    - usb: xhci-mtk: allow multiple Start-Split in a microframe
+    - usb: xhci-mtk: relax TT periodic bandwidth allocation
+    - wifi: mac80211: Fix UAF in ieee80211_scan_rx()
+    - tty/serial: atmel: RS485 & ISO7816: wait for TXRDY before sending data
+    - serial: atmel: remove redundant assignment in rs485_config
+    - tty: serial: atmel: Preserve previous USART mode if RS485 disabled
+    - usb: add quirks for Lenovo OneLink+ Dock
+    - usb: gadget: udc-xilinx: replace memcpy with memcpy_toio
+    - usb: cdns3: fix issue with rearming ISO OUT endpoint
+    - Revert "usb: add quirks for Lenovo OneLink+ Dock"
+    - Revert "usb: gadget: udc-xilinx: replace memcpy with memcpy_toio"
+    - USB: core: Fix RST error in hub.c
+    - USB: serial: option: add Quectel BG95 0x0203 composition
+    - USB: serial: option: add Quectel RM520N
+    - ALSA: hda/tegra: set depop delay for tegra
+    - ALSA: hda: add Intel 5 Series / 3400 PCI DID
+    - ALSA: hda/realtek: Add quirk for Huawei WRT-WX9
+    - ALSA: hda/realtek: Re-arrange quirk table entries
+    - ALSA: hda/realtek: Add pincfg for ASUS G513 HP jack
+    - ALSA: hda/realtek: Add pincfg for ASUS G533Z HP jack
+    - ALSA: hda/realtek: Add quirk for ASUS GA503R laptop
+    - ALSA: hda/realtek: Enable 4-speaker output Dell Precision 5530 laptop
+    - efi: libstub: check Shim mode using MokSBStateRT
+    - mm/slub: fix to return errno if kmalloc() fails
+    - arm64: dts: rockchip: Pull up wlan wake# on Gru-Bob
+    - arm64: dts: rockchip: Set RK3399-Gru PCLK_EDP to 24 MHz
+    - arm64: dts: rockchip: Remove 'enable-active-low' from rk3399-puma
+    - netfilter: nf_conntrack_sip: fix ct_sip_walk_headers
+    - netfilter: nf_conntrack_irc: Tighten matching on DCC message
+    - netfilter: nfnetlink_osf: fix possible bogus match in nf_osf_find()
+    - iavf: Fix cached head and tail value for iavf_get_tx_pending
+    - ipvlan: Fix out-of-bound bugs caused by unset skb->mac_header
+    - net: team: Unsync device addresses on ndo_stop
+    - MIPS: lantiq: export clk_get_io() for lantiq_wdt.ko
+    - MIPS: Loongson32: Fix PHY-mode being left unspecified
+    - iavf: Fix bad page state
+    - i40e: Fix set max_tx_rate when it is lower than 1 Mbps
+    - of: mdio: Add of_node_put() when breaking out of for_each_xx
+    - net/sched: taprio: avoid disabling offload when it was never enabled
+    - net/sched: taprio: make qdisc_leaf() see the per-netdev-queue pfifo child
+      qdiscs
+    - netfilter: ebtables: fix memory leak when blob is malformed
+    - can: gs_usb: gs_can_open(): fix race dev->can.state condition
+    - perf jit: Include program header in ELF files
+    - perf kcore_copy: Do not check /proc/modules is unchanged
+    - net: sunhme: Fix packet reception for len < RX_COPY_THRESHOLD
+    - net: sched: fix possible refcount leak in tc_new_tfilter()
+    - serial: Create uart_xmit_advance()
+    - serial: tegra: Use uart_xmit_advance(), fixes icount.tx accounting
+    - serial: tegra-tcu: Use uart_xmit_advance(), fixes icount.tx accounting
+    - s390/dasd: fix Oops in dasd_alias_get_start_dev due to missing pavgroup
+    - usb: xhci-mtk: fix issue of out-of-bounds array access
+    - cifs: always initialize struct msghdr smb_msg completely
+    - Drivers: hv: Never allocate anything besides framebuffer from framebuffer
+      memory region
+    - drm/amd/display: Limit user regamma to a valid value
+    - drm/rockchip: Fix return type of cdn_dp_connector_mode_valid
+    - workqueue: don't skip lockdep work dependency in cancel_work_sync()
+    - ext4: fix bug in extents parsing when eh_entries == 0 and eh_depth > 0
+    - xfs: replace -EIO with -EFSCORRUPTED for corrupt metadata
+    - xfs: slightly tweak an assert in xfs_fs_map_blocks
+    - xfs: add missing assert in xfs_fsmap_owner_from_rmap
+    - xfs: range check ri_cnt when recovering log items
+    - xfs: attach dquots and reserve quota blocks during unwritten conversion
+    - xfs: convert EIO to EFSCORRUPTED when log contents are invalid
+    - xfs: constify the buffer pointer arguments to error functions
+    - xfs: always log corruption errors
+    - xfs: fix some memory leaks in log recovery
+    - xfs: stabilize insert range start boundary to avoid COW writeback race
+    - xfs: use bitops interface for buf log item AIL flag check
+    - xfs: refactor agfl length computation function
+    - xfs: split the sunit parameter update into two parts
+    - xfs: don't commit sunit/swidth updates to disk if that would cause repair
+      failures
+    - xfs: fix an ABBA deadlock in xfs_rename
+    - xfs: fix use-after-free when aborting corrupt attr inactivation
+    - ext4: make directory inode spreading reflect flexbg size
+    - Linux 5.4.215
+
+  * Focal update: v5.4.214 upstream stable release (LP: #1993196)
+    - drm/msm/rd: Fix FIFO-full deadlock
+    - HID: ishtp-hid-clientHID: ishtp-hid-client: Fix comment typo
+    - hid: intel-ish-hid: ishtp: Fix ishtp client sending disordered message
+    - tg3: Disable tg3 device on system reboot to avoid triggering AER
+    - ieee802154: cc2520: add rc code in cc2520_tx()
+    - Input: iforce - add support for Boeder Force Feedback Wheel
+    - nvmet-tcp: fix unhandled tcp states in nvmet_tcp_state_change()
+    - perf/arm_pmu_platform: fix tests for platform_get_irq() failure
+    - platform/x86: acer-wmi: Acer Aspire One AOD270/Packard Bell Dot keymap fixes
+    - usb: storage: Add ASUS <0x0b05:0x1932> to IGNORE_UAS
+    - mm: Fix TLB flush for not-first PFNMAP mappings in unmap_region()
+    - net: dp83822: disable rx error interrupt
+    - soc: fsl: select FSL_GUTS driver for DPIO
+    - tracefs: Only clobber mode/uid/gid on remount if asked
+    - Linux 5.4.214
+
+  * Focal update: v5.4.213 upstream stable release (LP: #1992211)
+    - efi: capsule-loader: Fix use-after-free in efi_capsule_write
+    - wifi: iwlegacy: 4965: corrected fix for potential off-by-one overflow in
+      il4965_rs_fill_link_cmd()
+    - fs: only do a memory barrier for the first set_buffer_uptodate()
+    - Revert "mm: kmemleak: take a full lowmem check in kmemleak_*_phys()"
+    - net: dp83822: disable false carrier interrupt
+    - drm/msm/dsi: fix the inconsistent indenting
+    - drm/msm/dsi: Fix number of regulators for msm8996_dsi_cfg
+    - platform/x86: pmc_atom: Fix SLP_TYPx bitfield mask
+    - iio: adc: mcp3911: make use of the sign bit
+    - ieee802154/adf7242: defer destroy_workqueue call
+    - wifi: cfg80211: debugfs: fix return type in ht40allow_map_read()
+    - Revert "xhci: turn off port power in shutdown"
+    - net: sched: tbf: don't call qdisc_put() while holding tree lock
+    - ethernet: rocker: fix sleep in atomic context bug in neigh_timer_handler
+    - kcm: fix strp_init() order and cleanup
+    - sch_cake: Return __NET_XMIT_STOLEN when consuming enqueued skb
+    - tcp: annotate data-race around challenge_timestamp
+    - Revert "sch_cake: Return __NET_XMIT_STOLEN when consuming enqueued skb"
+    - net/smc: Remove redundant refcount increase
+    - serial: fsl_lpuart: RS485 RTS polariy is inverse
+    - staging: rtl8712: fix use after free bugs
+    - powerpc: align syscall table for ppc32
+    - vt: Clear selection before changing the font
+    - tty: serial: lpuart: disable flow control while waiting for the transmit
+      engine to complete
+    - Input: iforce - wake up after clearing IFORCE_XMIT_RUNNING flag
+    - iio: adc: mcp3911: use correct formula for AD conversion
+    - misc: fastrpc: fix memory corruption on probe
+    - misc: fastrpc: fix memory corruption on open
+    - USB: serial: ftdi_sio: add Omron CS1W-CIF31 device id
+    - binder: fix UAF of ref->proc caused by race condition
+    - usb: dwc3: qcom: fix use-after-free on runtime-PM wakeup
+    - drm/i915/reg: Fix spelling mistake "Unsupport" -> "Unsupported"
+    - clk: core: Honor CLK_OPS_PARENT_ENABLE for clk gate ops
+    - Revert "clk: core: Honor CLK_OPS_PARENT_ENABLE for clk gate ops"
+    - clk: core: Fix runtime PM sequence in clk_core_unprepare()
+    - Input: rk805-pwrkey - fix module autoloading
+    - clk: bcm: rpi: Fix error handling of raspberrypi_fw_get_rate
+    - hwmon: (gpio-fan) Fix array out of bounds access
+    - gpio: pca953x: Add mutex_lock for regcache sync in PM
+    - thunderbolt: Use the actual buffer in tb_async_error()
+    - xhci: Add grace period after xHC start to prevent premature runtime suspend.
+    - USB: serial: cp210x: add Decagon UCA device id
+    - USB: serial: option: add support for OPPO R11 diag port
+    - USB: serial: option: add Quectel EM060K modem
+    - USB: serial: option: add support for Cinterion MV32-WA/WB RmNet mode
+    - usb: typec: altmodes/displayport: correct pin assignment for UFP receptacles
+    - usb: dwc2: fix wrong order of phy_power_on and phy_init
+    - USB: cdc-acm: Add Icom PMR F3400 support (0c26:0020)
+    - usb-storage: Add ignore-residue quirk for NXP PN7462AU
+    - s390/hugetlb: fix prepare_hugepage_range() check for 2 GB hugepages
+    - s390: fix nospec table alignments
+    - USB: core: Prevent nested device-reset calls
+    - usb: gadget: mass_storage: Fix cdrom data transfers on MAC-OS
+    - driver core: Don't probe devices after bus_type.match() probe deferral
+    - wifi: mac80211: Don't finalize CSA in IBSS mode if state is disconnected
+    - net: mac802154: Fix a condition in the receive path
+    - ALSA: seq: oss: Fix data-race for max_midi_devs access
+    - ALSA: seq: Fix data-race at module auto-loading
+    - drm/i915/glk: ECS Liva Q2 needs GLK HDMI port timing quirk
+    - btrfs: harden identification of a stale device
+    - usb: dwc3: fix PHY disable sequence
+    - usb: dwc3: disable USB core PHY management
+    - USB: serial: ch341: fix lost character on LCR updates
+    - USB: serial: ch341: fix disabled rx timer on older devices
+    - scsi: megaraid_sas: Fix double kfree()
+    - drm/gem: Fix GEM handle release errors
+    - drm/amdgpu: Check num_gfx_rings for gfx v9_0 rb setup.
+    - drm/radeon: add a force flush to delay work when radeon
+    - parisc: ccio-dma: Handle kmalloc failure in ccio_init_resources()
+    - parisc: Add runtime check to prevent PA2.0 kernels on PA1.x machines
+    - arm64: cacheinfo: Fix incorrect assignment of signed error value to unsigned
+      fw_level
+    - fbdev: chipsfb: Add missing pci_disable_device() in chipsfb_pci_init()
+    - drm/amdgpu: mmVM_L2_CNTL3 register not initialized correctly
+    - ALSA: emu10k1: Fix out of bounds access in snd_emu10k1_pcm_channel_alloc()
+    - ALSA: aloop: Fix random zeros in capture data when using jiffies timer
+    - ALSA: usb-audio: Fix an out-of-bounds bug in
+      __snd_usb_parse_audio_interface()
+    - kprobes: Prohibit probes in gate area
+    - debugfs: add debugfs_lookup_and_remove()
+    - nvmet: fix a use-after-free
+    - scsi: mpt3sas: Fix use-after-free warning
+    - scsi: lpfc: Add missing destroy_workqueue() in error path
+    - cgroup: Optimize single thread migration
+    - cgroup: Elide write-locking threadgroup_rwsem when updating csses on an
+      empty subtree
+    - cgroup: Fix threadgroup_rwsem <-> cpus_read_lock() deadlock
+    - smb3: missing inode locks in punch hole
+    - ARM: dts: imx6qdl-kontron-samx6i: remove duplicated node
+    - regulator: core: Clean up on enable failure
+    - RDMA/cma: Fix arguments order in net device validation
+    - soc: brcmstb: pm-arm: Fix refcount leak and __iomem leak bugs
+    - RDMA/hns: Fix supported page size
+    - netfilter: br_netfilter: Drop dst references before setting.
+    - rxrpc: Fix an insufficiently large sglist in rxkad_verify_packet_2()
+    - afs: Use the operation issue time instead of the reply time for callbacks
+    - sch_sfb: Don't assume the skb is still around after enqueueing to child
+    - tipc: fix shift wrapping bug in map_get()
+    - i40e: Fix kernel crash during module removal
+    - RDMA/siw: Pass a pointer to virt_to_page()
+    - ipv6: sr: fix out-of-bounds read when setting HMAC data.
+    - RDMA/mlx5: Set local port to one when accessing counters
+    - nvme-tcp: fix UAF when detecting digest errors
+    - tcp: fix early ETIMEDOUT after spurious non-SACK RTO
+    - sch_sfb: Also store skb len before calling child enqueue
+    - x86/nospec: Fix i386 RSB stuffing
+    - MIPS: loongson32: ls1c: Fix hang during startup
+    - Linux 5.4.213
+
+  * CVE-2022-2663
+    - netfilter: nf_conntrack_irc: Fix forged IP logic
+
+  * CVE-2022-3061
+    - video: fbdev: i740fb: Error out if 'pixclock' equals zero
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Thu, 24 Nov 2022 16:40:01 +0100
+
+linux (5.4.0-135.152) focal; urgency=medium
+
+  * focal/linux: 5.4.0-135.152 -proposed tracker (LP: #1997412)
+
+  * containerd sporadic timeouts (LP: #1996678)
+    - epoll: call final ep_events_available() check under the lock
+    - epoll: check for events when removing a timed out thread from the wait queue
+    - Revert "fs: check FMODE_LSEEK to control internal pipe splicing"
+
+  * CVE-2022-3621
+    - nilfs2: fix NULL pointer dereference at nilfs_bmap_lookup_at_level()
+
+  * CVE-2022-3565
+    - mISDN: fix use-after-free bugs in l1oip timer handlers
+
+  * CVE-2022-3566
+    - tcp: Fix data races around icsk->icsk_af_ops.
+
+  * CVE-2022-3567
+    - ipv6: annotate some data-races around sk->sk_prot
+    - ipv6: Fix data races around sk->sk_prot.
+
+  * CVE-2022-3564
+    - Bluetooth: L2CAP: Fix use-after-free caused by l2cap_reassemble_sdu
+
+  * CVE-2022-3524
+    - tcp/udp: Fix memory leak in ipv6_renew_options().
+
+  * CVE-2022-3594
+    - r8152: Rate limit overflow messages
+
+  * CVE-2022-42703
+    - mm/rmap.c: don't reuse anon_vma if we just want a copy
+
+ -- Thadeu Lima de Souza Cascardo <cascardo@canonical.com>  Wed, 23 Nov 2022 16:51:44 -0300
+
+linux (5.4.0-132.148) focal; urgency=medium
+
+  * CVE-2022-42719
+    - mac80211: mlme: find auth challenge directly
+    - wifi: mac80211: don't parse mbssid in assoc response
+    - wifi: mac80211: fix MBSSID parsing use-after-free
+
+  * iavf: SR-IOV VFs error with no traffic flow when MTU greater than 1500
+    (LP: #1983656)
+    - iavf: Fix set max MTU size with port VLAN and jumbo frames
+    - i40e: Fix VF set max MTU size
+
+  * fib_nexthop_nongw.sh from ubuntu_kernel_selftests failed on B-5.4
+    (LP: #1990800)
+    - SAUCE: selftests/net: skipping tests for older ip command releases
+
+  * CVE-2022-29901
+    - Revert "x86/speculation: Add RSB VM Exit protections"
+    - Revert "x86/cpu: Add a steppings field to struct x86_cpu_id"
+    - x86/devicetable: Move x86 specific macro out of generic code
+    - x86/cpu: Add consistent CPU match macros
+    - x86/cpu: Add a steppings field to struct x86_cpu_id
+    - x86/kvm/vmx: Make noinstr clean
+    - x86/cpufeatures: Move RETPOLINE flags to word 11
+    - x86/bugs: Report AMD retbleed vulnerability
+    - x86/bugs: Add AMD retbleed= boot parameter
+    - x86/bugs: Keep a per-CPU IA32_SPEC_CTRL value
+    - x86/entry: Remove skip_r11rcx
+    - x86/entry: Add kernel IBRS implementation
+    - x86/bugs: Optimize SPEC_CTRL MSR writes
+    - x86/speculation: Add spectre_v2=ibrs option to support Kernel IBRS
+    - x86/bugs: Split spectre_v2_select_mitigation() and
+      spectre_v2_user_select_mitigation()
+    - x86/bugs: Report Intel retbleed vulnerability
+    - intel_idle: Disable IBRS during long idle
+    - x86/speculation: Change FILL_RETURN_BUFFER to work with objtool
+    - x86/speculation: Fix RSB filling with CONFIG_RETPOLINE=n
+    - x86/speculation: Fix firmware entry SPEC_CTRL handling
+    - x86/speculation: Fix SPEC_CTRL write on SMT state change
+    - x86/speculation: Use cached host SPEC_CTRL value for guest entry/exit
+    - x86/speculation: Remove x86_spec_ctrl_mask
+    - KVM/VMX: Use TEST %REG,%REG instead of CMP $0,%REG in vmenter.S
+    - KVM/nVMX: Use __vmx_vcpu_run in nested_vmx_check_vmentry_hw
+    - KVM: VMX: Flatten __vmx_vcpu_run()
+    - KVM: VMX: Convert launched argument to flags
+    - KVM: VMX: Prevent guest RSB poisoning attacks with eIBRS
+    - KVM: VMX: Fix IBRS handling after vmexit
+    - x86/speculation: Fill RSB on vmexit for IBRS
+    - x86/common: Stamp out the stepping madness
+    - x86/cpu/amd: Enumerate BTC_NO
+    - x86/bugs: Add Cannon lake to RETBleed affected CPU list
+    - x86/speculation: Disable RRSBA behavior
+    - x86/speculation: Use DECLARE_PER_CPU for x86_spec_ctrl_current
+    - x86/bugs: Warn when "ibrs" mitigation is selected on Enhanced IBRS parts
+    - x86/speculation: Add RSB VM Exit protections
+
+  * ACPI: processor idle: Practically limit "Dummy wait" workaround to old Intel
+    systems (LP: #1990985)
+    - ACPI: processor_idle: Skip dummy wait if kernel is in guest
+    - ACPI: processor idle: Practically limit "Dummy wait" workaround to old Intel
+      systems
+
+  * cgroup: all controllers mounted when using 'cgroup_no_v1=' (LP: #1988584)
+    - cgroup-v1: add disabled controller check in cgroup1_parse_param()
+
+  * Focal update: v5.4.212 upstream stable release (LP: #1991156)
+    - audit: fix potential double free on error path from fsnotify_add_inode_mark
+    - parisc: Fix exception handler for fldw and fstw instructions
+    - kernel/sys_ni: add compat entry for fadvise64_64
+    - usb: cdns3: Fix issue for clear halt endpoint
+    - pinctrl: amd: Don't save/restore interrupt status and wake status bits
+    - sched/deadline: Unthrottle PI boosted threads while enqueuing
+    - sched/deadline: Fix stale throttling on de-/boosted tasks
+    - sched/deadline: Fix priority inheritance with multiple scheduling classes
+    - kernel/sched: Remove dl_boosted flag comment
+    - xfrm: fix refcount leak in __xfrm_policy_check()
+    - SUNRPC: RPC level errors should set task->tk_rpc_status
+    - rose: check NULL rose_loopback_neigh->loopback
+    - net/mlx5e: Properly disable vlan strip on non-UL reps
+    - net: moxa: get rid of asymmetry in DMA mapping/unmapping
+    - bonding: 802.3ad: fix no transmission of LACPDUs
+    - net: ipvtap - add __init/__exit annotations to module init/exit funcs
+    - netfilter: ebtables: reject blobs that don't provide all entry points
+    - bnxt_en: fix NQ resource accounting during vf creation on 57500 chips
+    - netfilter: nft_payload: report ERANGE for too long offset and length
+    - netfilter: nft_payload: do not truncate csum_offset and csum_type
+    - netfilter: nft_osf: restrict osf to ipv4, ipv6 and inet families
+    - netfilter: nft_tunnel: restrict it to netdev family
+    - net: Fix data-races around weight_p and dev_weight_[rt]x_bias.
+    - net: Fix data-races around netdev_tstamp_prequeue.
+    - ratelimit: Fix data-races in ___ratelimit().
+    - net: Fix a data-race around sysctl_tstamp_allow_data.
+    - net: Fix a data-race around sysctl_net_busy_poll.
+    - net: Fix a data-race around sysctl_net_busy_read.
+    - net: Fix a data-race around netdev_budget.
+    - net: Fix a data-race around netdev_budget_usecs.
+    - net: Fix a data-race around sysctl_somaxconn.
+    - ixgbe: stop resetting SYSTIME in ixgbe_ptp_start_cyclecounter
+    - btrfs: fix silent failure when deleting root reference
+    - btrfs: replace: drop assert for suspended replace
+    - btrfs: add info when mount fails due to stale replace target
+    - btrfs: check if root is readonly while setting security xattr
+    - x86/unwind/orc: Unwind ftrace trampolines with correct ORC entry
+    - loop: Check for overflow while configuring loop
+    - asm-generic: sections: refactor memory_intersects
+    - s390: fix double free of GS and RI CBs on fork() failure
+    - ACPI: processor: Remove freq Qos request for all CPUs
+    - mm/hugetlb: fix hugetlb not supporting softdirty tracking
+    - md: call __md_stop_writes in md_stop
+    - perf/x86/intel/uncore: Fix broken read_counter() for SNB IMC PMU
+    - scsi: storvsc: Remove WQ_MEM_RECLAIM from storvsc_error_wq
+    - mm: Force TLB flush for PFNMAP mappings before unlink_file_vma()
+    - s390/mm: do not trigger write fault when vma does not allow VM_WRITE
+    - x86/bugs: Add "unknown" reporting for MMIO Stale Data
+    - kbuild: Fix include path in scripts/Makefile.modpost
+    - Bluetooth: L2CAP: Fix build errors in some archs
+    - HID: steam: Prevent NULL pointer dereference in steam_{recv,send}_report
+    - udmabuf: Set the DMA mask for the udmabuf device (v2)
+    - media: pvrusb2: fix memory leak in pvr_probe
+    - HID: hidraw: fix memory leak in hidraw_release()
+    - fbdev: fb_pm2fb: Avoid potential divide by zero error
+    - ftrace: Fix NULL pointer dereference in is_ftrace_trampoline when ftrace is
+      dead
+    - bpf: Don't redirect packets with invalid pkt_len
+    - mm/rmap: Fix anon_vma->degree ambiguity leading to double-reuse
+    - btrfs: introduce btrfs_lookup_match_dir
+    - btrfs: do not pin logs too early during renames
+    - btrfs: unify lookup return value when dir entry is missing
+    - drm/amd/display: Avoid MPC infinite loop
+    - drm/amd/display: clear optc underflow before turn off odm clock
+    - neigh: fix possible DoS due to net iface start/stop loop
+    - s390/hypfs: avoid error message under KVM
+    - drm/amd/display: Fix pixel clock programming
+    - netfilter: conntrack: NF_CONNTRACK_PROCFS should no longer default to y
+    - btrfs: tree-checker: check for overlapping extent items
+    - lib/vdso: Let do_coarse() return 0 to simplify the callsite
+    - lib/vdso: Mark do_hres() and do_coarse() as __always_inline
+    - kprobes: don't call disarm_kprobe() for disabled kprobes
+    - net/af_packet: check len when min_header_len equals to 0
+    - net: neigh: don't call kfree_skb() under spin_lock_irqsave()
+    - Linux 5.4.212
+
+  * Focal update: v5.4.211 upstream stable release (LP: #1990190)
+    - Makefile: link with -z noexecstack --no-warn-rwx-segments
+    - x86: link vdso and boot with -z noexecstack --no-warn-rwx-segments
+    - scsi: Revert "scsi: qla2xxx: Fix disk failure to rediscover"
+    - ALSA: bcd2000: Fix a UAF bug on the error path of probing
+    - igc: Remove _I_PHY_ID checking
+    - wifi: mac80211_hwsim: fix race condition in pending packet
+    - wifi: mac80211_hwsim: add back erroneously removed cast
+    - wifi: mac80211_hwsim: use 32-bit skb cookie
+    - add barriers to buffer_uptodate and set_buffer_uptodate
+    - HID: wacom: Only report rotation for art pen
+    - HID: wacom: Don't register pad_input for touch switch
+    - KVM: nVMX: Snapshot pre-VM-Enter BNDCFGS for !nested_run_pending case
+    - KVM: nVMX: Snapshot pre-VM-Enter DEBUGCTL for !nested_run_pending case
+    - KVM: SVM: Don't BUG if userspace injects an interrupt with GIF=0
+    - KVM: nVMX: Let userspace set nVMX MSR to any _host_ supported value
+    - KVM: x86: Mark TSS busy during LTR emulation _after_ all fault checks
+    - KVM: x86: Set error code to segment selector on LLDT/LTR non-canonical #GP
+    - mm/mremap: hold the rmap lock in write mode when moving page table entries.
+    - ALSA: hda/conexant: Add quirk for LENOVO 20149 Notebook model
+    - ALSA: hda/cirrus - support for iMac 12,1 model
+    - ALSA: hda/realtek: Add quirk for another Asus K42JZ model
+    - tty: vt: initialize unicode screen buffer
+    - vfs: Check the truncate maximum size in inode_newsize_ok()
+    - fs: Add missing umask strip in vfs_tmpfile
+    - thermal: sysfs: Fix cooling_device_stats_setup() error code path
+    - fbcon: Fix boundary checks for fbcon=vc:n1-n2 parameters
+    - usbnet: Fix linkwatch use-after-free on disconnect
+    - ovl: drop WARN_ON() dentry is NULL in ovl_encode_fh()
+    - parisc: Fix device names in /proc/iomem
+    - parisc: io_pgetevents_time64() needs compat syscall in 32-bit compat mode
+    - drm/gem: Properly annotate WW context on drm_gem_lock_reservations() error
+    - drm/nouveau: fix another off-by-one in nvbios_addr
+    - drm/amdgpu: Check BO's requested pinning domains against its
+      preferred_domains
+    - iio: light: isl29028: Fix the warning in isl29028_remove()
+    - fuse: limit nsec
+    - serial: mvebu-uart: uart2 error bits clearing
+    - md-raid10: fix KASAN warning
+    - ia64, processor: fix -Wincompatible-pointer-types in ia64_get_irr()
+    - PCI: Add defines for normal and subtractive PCI bridges
+    - powerpc/fsl-pci: Fix Class Code of PCIe Root Port
+    - powerpc/ptdump: Fix display of RW pages on FSL_BOOK3E
+    - powerpc/powernv: Avoid crashing if rng is NULL
+    - MIPS: cpuinfo: Fix a warning for CONFIG_CPUMASK_OFFSTACK
+    - coresight: Clear the connection field properly
+    - USB: HCD: Fix URB giveback issue in tasklet function
+    - ARM: dts: uniphier: Fix USB interrupts for PXs2 SoC
+    - arm64: dts: uniphier: Fix USB interrupts for PXs3 SoC
+    - netfilter: nf_tables: fix null deref due to zeroed list head
+    - epoll: autoremove wakers even more aggressively
+    - x86: Handle idle=nomwait cmdline properly for x86_idle
+    - arm64: Do not forget syscall when starting a new thread.
+    - arm64: fix oops in concurrently setting insn_emulation sysctls
+    - ext2: Add more validity checks for inode counts
+    - genirq: Don't return error on missing optional irq_request_resources()
+    - wait: Fix __wait_event_hrtimeout for RT/DL tasks
+    - ARM: dts: imx6ul: add missing properties for sram
+    - ARM: dts: imx6ul: change operating-points to uint32-matrix
+    - ARM: dts: imx6ul: fix csi node compatible
+    - ARM: dts: imx6ul: fix lcdif node compatible
+    - ARM: dts: imx6ul: fix qspi node compatible
+    - spi: synquacer: Add missing clk_disable_unprepare()
+    - ARM: OMAP2+: display: Fix refcount leak bug
+    - ACPI: EC: Remove duplicate ThinkPad X1 Carbon 6th entry from DMI quirks
+    - ACPI: PM: save NVS memory for Lenovo G40-45
+    - ACPI: LPSS: Fix missing check in register_device_clock()
+    - arm64: dts: qcom: ipq8074: fix NAND node name
+    - arm64: dts: allwinner: a64: orangepi-win: Fix LED node name
+    - ARM: shmobile: rcar-gen2: Increase refcount for new reference
+    - PM: hibernate: defer device probing when resuming from hibernation
+    - selinux: Add boundary check in put_entry()
+    - spi: spi-rspi: Fix PIO fallback on RZ platforms
+    - ARM: findbit: fix overflowing offset
+    - meson-mx-socinfo: Fix refcount leak in meson_mx_socinfo_init
+    - ARM: bcm: Fix refcount leak in bcm_kona_smc_init
+    - x86/pmem: Fix platform-device leak in error path
+    - ARM: dts: ast2500-evb: fix board compatible
+    - ARM: dts: ast2600-evb: fix board compatible
+    - soc: fsl: guts: machine variable might be unset
+    - ARM: dts: qcom: mdm9615: add missing PMIC GPIO reg
+    - ARM: OMAP2+: Fix refcount leak in omapdss_init_of
+    - ARM: OMAP2+: Fix refcount leak in omap3xxx_prm_late_init
+    - cpufreq: zynq: Fix refcount leak in zynq_get_revision
+    - soc: qcom: aoss: Fix refcount leak in qmp_cooling_devices_register
+    - ARM: dts: qcom: pm8841: add required thermal-sensor-cells
+    - bus: hisi_lpc: fix missing platform_device_put() in hisi_lpc_acpi_probe()
+    - arm64: dts: mt7622: fix BPI-R64 WPS button
+    - erofs: avoid consecutive detection for Highmem memory
+    - blk-mq: don't create hctx debugfs dir until q->debugfs_dir is created
+    - regulator: of: Fix refcount leak bug in of_get_regulation_constraints()
+    - nohz/full, sched/rt: Fix missed tick-reenabling bug in dequeue_task_rt()
+    - thermal/tools/tmon: Include pthread and time headers in tmon.h
+    - dm: return early from dm_pr_call() if DM device is suspended
+    - ath10k: do not enforce interrupt trigger type
+    - wifi: rtlwifi: fix error codes in rtl_debugfs_set_write_h2c()
+    - drm/mipi-dbi: align max_chunk to 2 in spi_transfer
+    - drm/radeon: fix potential buffer overflow in ni_set_mc_special_registers()
+    - drm/mediatek: Add pull-down MIPI operation in mtk_dsi_poweroff function
+    - drm: adv7511: override i2c address of cec before accessing it
+    - i2c: Fix a potential use after free
+    - media: tw686x: Register the irq at the end of probe
+    - wifi: iwlegacy: 4965: fix potential off-by-one overflow in
+      il4965_rs_fill_link_cmd()
+    - drm: bridge: adv7511: Add check for mipi_dsi_driver_register
+    - drm/mcde: Fix refcount leak in mcde_dsi_bind
+    - media: hdpvr: fix error value returns in hdpvr_read
+    - drm/vc4: plane: Remove subpixel positioning check
+    - drm/vc4: plane: Fix margin calculations for the right/bottom edges
+    - drm/vc4: dsi: Correct DSI divider calculations
+    - crypto: arm64/gcm - Select AEAD for GHASH_ARM64_CE
+    - drm/rockchip: vop: Don't crash for invalid duplicate_state()
+    - drm/rockchip: Fix an error handling path rockchip_dp_probe()
+    - drm/mediatek: dpi: Remove output format of YUV
+    - drm/mediatek: dpi: Only enable dpi after the bridge is enabled
+    - drm: bridge: sii8620: fix possible off-by-one
+    - drm/msm/mdp5: Fix global state lock backoff
+    - crypto: hisilicon - Kunpeng916 crypto driver don't sleep when in softirq
+    - media: platform: mtk-mdp: Fix mdp_ipi_comm structure alignment
+    - mediatek: mt76: mac80211: Fix missing of_node_put() in mt76_led_init()
+    - drm/exynos/exynos7_drm_decon: free resources when clk_set_parent() failed.
+    - tcp: make retransmitted SKB fit into the send window
+    - libbpf: Fix the name of a reused map
+    - selftests: timers: valid-adjtimex: build fix for newer toolchains
+    - selftests: timers: clocksource-switch: fix passing errors from child
+    - fs: check FMODE_LSEEK to control internal pipe splicing
+    - wifi: wil6210: debugfs: fix info leak in wil_write_file_wmi()
+    - wifi: p54: Fix an error handling path in p54spi_probe()
+    - wifi: p54: add missing parentheses in p54_flush()
+    - selftests/bpf: fix a test for snprintf() overflow
+    - can: pch_can: do not report txerr and rxerr during bus-off
+    - can: rcar_can: do not report txerr and rxerr during bus-off
+    - can: sja1000: do not report txerr and rxerr during bus-off
+    - can: hi311x: do not report txerr and rxerr during bus-off
+    - can: sun4i_can: do not report txerr and rxerr during bus-off
+    - can: kvaser_usb_hydra: do not report txerr and rxerr during bus-off
+    - can: kvaser_usb_leaf: do not report txerr and rxerr during bus-off
+    - can: usb_8dev: do not report txerr and rxerr during bus-off
+    - can: error: specify the values of data[5..7] of CAN error frames
+    - can: pch_can: pch_can_error(): initialize errc before using it
+    - Bluetooth: hci_intel: Add check for platform_driver_register
+    - i2c: cadence: Support PEC for SMBus block read
+    - i2c: mux-gpmux: Add of_node_put() when breaking out of loop
+    - wifi: wil6210: debugfs: fix uninitialized variable use in
+      `wil_write_file_wmi()`
+    - wifi: iwlwifi: mvm: fix double list_add at iwl_mvm_mac_wake_tx_queue
+    - wifi: libertas: Fix possible refcount leak in if_usb_probe()
+    - net/mlx5e: Fix the value of MLX5E_MAX_RQ_NUM_MTTS
+    - crypto: inside-secure - Add missing MODULE_DEVICE_TABLE for of
+    - iavf: Fix max_rate limiting
+    - netdevsim: Avoid allocation warnings triggered from user space
+    - net: rose: fix netdev reference changes
+    - dccp: put dccp_qpolicy_full() and dccp_qpolicy_push() in the same lock
+    - clk: renesas: r9a06g032: Fix UART clkgrp bitsel
+    - mtd: maps: Fix refcount leak in of_flash_probe_versatile
+    - mtd: maps: Fix refcount leak in ap_flash_init
+    - mtd: rawnand: meson: Fix a potential double free issue
+    - HID: cp2112: prevent a buffer overflow in cp2112_xfer()
+    - mtd: sm_ftl: Fix deadlock caused by cancel_work_sync in sm_release
+    - mtd: partitions: Fix refcount leak in parse_redboot_of
+    - mtd: st_spi_fsm: Add a clk_disable_unprepare() in .probe()'s error path
+    - fpga: altera-pr-ip: fix unsigned comparison with less than zero
+    - usb: host: Fix refcount leak in ehci_hcd_ppc_of_probe
+    - usb: ohci-nxp: Fix refcount leak in ohci_hcd_nxp_probe
+    - usb: xhci: tegra: Fix error check
+    - clk: mediatek: reset: Fix written reset bit offset
+    - misc: rtsx: Fix an error handling path in rtsx_pci_probe()
+    - driver core: fix potential deadlock in __driver_attach
+    - clk: qcom: clk-krait: unlock spin after mux completion
+    - usb: host: xhci: use snprintf() in xhci_decode_trb()
+    - clk: qcom: ipq8074: fix NSS port frequency tables
+    - clk: qcom: ipq8074: set BRANCH_HALT_DELAY flag for UBI clocks
+    - clk: qcom: camcc-sdm845: Fix topology around titan_top power domain
+    - soundwire: bus_type: fix remove and shutdown support
+    - intel_th: Fix a resource leak in an error handling path
+    - intel_th: msu-sink: Potential dereference of null pointer
+    - intel_th: msu: Fix vmalloced buffers
+    - staging: rtl8192u: Fix sleep in atomic context bug in
+      dm_fsync_timer_callback
+    - mmc: sdhci-of-esdhc: Fix refcount leak in esdhc_signal_voltage_switch
+    - memstick/ms_block: Fix some incorrect memory allocation
+    - memstick/ms_block: Fix a memory leak
+    - mmc: sdhci-of-at91: fix set_uhs_signaling rewriting of MC1R
+    - scsi: smartpqi: Fix DMA direction for RAID requests
+    - usb: gadget: udc: amd5536 depends on HAS_DMA
+    - RDMA/hns: Fix incorrect clearing of interrupt status register
+    - RDMA/siw: Fix duplicated reported IW_CM_EVENT_CONNECT_REPLY event
+    - RDMA/hfi1: fix potential memory leak in setup_base_ctxt()
+    - gpio: gpiolib-of: Fix refcount bugs in of_mm_gpiochip_add_data()
+    - mmc: cavium-octeon: Add of_node_put() when breaking out of loop
+    - mmc: cavium-thunderx: Add of_node_put() when breaking out of loop
+    - HID: alps: Declare U1_UNICORN_LEGACY support
+    - PCI: tegra194: Fix Root Port interrupt handling
+    - PCI: tegra194: Fix link up retry sequence
+    - USB: serial: fix tty-port initialized comments
+    - platform/olpc: Fix uninitialized data in debugfs write
+    - mm/mmap.c: fix missing call to vm_unacct_memory in mmap_region
+    - RDMA/rxe: Fix error unwind in rxe_create_qp()
+    - null_blk: fix ida error handling in null_add_dev()
+    - jbd2: fix outstanding credits assert in jbd2_journal_commit_transaction()
+    - ext4: recover csum seed of tmp_inode after migrating to extents
+    - jbd2: fix assertion 'jh->b_frozen_data == NULL' failure when journal aborted
+    - opp: Fix error check in dev_pm_opp_attach_genpd()
+    - ASoC: mediatek: mt8173: Fix refcount leak in mt8173_rt5650_rt5676_dev_probe
+    - ASoC: mt6797-mt6351: Fix refcount leak in mt6797_mt6351_dev_probe
+    - ASoC: codecs: da7210: add check for i2c_add_driver
+    - ASoC: mediatek: mt8173-rt5650: Fix refcount leak in mt8173_rt5650_dev_probe
+    - serial: 8250_dw: Store LSR into lsr_saved_flags in dw8250_tx_wait_empty()
+    - ASoC: codecs: msm8916-wcd-digital: move gains from SX_TLV to S8_TLV
+    - ASoC: codecs: wcd9335: move gains from SX_TLV to S8_TLV
+    - profiling: fix shift too large makes kernel panic
+    - tty: n_gsm: fix non flow control frames during mux flow off
+    - tty: n_gsm: fix packet re-transmission without open control channel
+    - tty: n_gsm: fix race condition in gsmld_write()
+    - remoteproc: qcom: wcnss: Fix handling of IRQs
+    - vfio/ccw: Do not change FSM state in subchannel event
+    - tty: n_gsm: fix wrong T1 retry count handling
+    - tty: n_gsm: fix DM command
+    - tty: n_gsm: fix missing corner cases in gsmld_poll()
+    - iommu/exynos: Handle failed IOMMU device registration properly
+    - rpmsg: qcom_smd: Fix refcount leak in qcom_smd_parse_edge
+    - kfifo: fix kfifo_to_user() return type
+    - mfd: t7l66xb: Drop platform disable callback
+    - mfd: max77620: Fix refcount leak in max77620_initialise_fps
+    - iommu/arm-smmu: qcom_iommu: Add of_node_put() when breaking out of loop
+    - s390/zcore: fix race when reading from hardware system area
+    - ASoC: qcom: q6dsp: Fix an off-by-one in q6adm_alloc_copp()
+    - fuse: Remove the control interface for virtio-fs
+    - ASoC: audio-graph-card: Add of_node_put() in fail path
+    - watchdog: armada_37xx_wdt: check the return value of devm_ioremap() in
+      armada_37xx_wdt_probe()
+    - video: fbdev: amba-clcd: Fix refcount leak bugs
+    - video: fbdev: sis: fix typos in SiS_GetModeID()
+    - powerpc/32: Do not allow selection of e5500 or e6500 CPUs on PPC32
+    - powerpc/pci: Prefer PCI domain assignment via DT 'linux,pci-domain' and
+      alias
+    - powerpc/spufs: Fix refcount leak in spufs_init_isolated_loader
+    - powerpc/xive: Fix refcount leak in xive_get_max_prio
+    - powerpc/cell/axon_msi: Fix refcount leak in setup_msi_msg_address
+    - perf symbol: Fail to read phdr workaround
+    - kprobes: Forbid probing on trampoline and BPF code areas
+    - powerpc/pci: Fix PHB numbering when using opal-phbid
+    - genelf: Use HAVE_LIBCRYPTO_SUPPORT, not the never defined HAVE_LIBCRYPTO
+    - scripts/faddr2line: Fix vmlinux detection on arm64
+    - x86/numa: Use cpumask_available instead of hardcoded NULL check
+    - video: fbdev: arkfb: Fix a divide-by-zero bug in ark_set_pixclock()
+    - tools/thermal: Fix possible path truncations
+    - video: fbdev: vt8623fb: Check the size of screen before memset_io()
+    - video: fbdev: arkfb: Check the size of screen before memset_io()
+    - video: fbdev: s3fb: Check the size of screen before memset_io()
+    - scsi: zfcp: Fix missing auto port scan and thus missing target ports
+    - scsi: qla2xxx: Fix discovery issues in FC-AL topology
+    - scsi: qla2xxx: Turn off multi-queue for 8G adapters
+    - scsi: qla2xxx: Fix erroneous mailbox timeout after PCI error injection
+    - x86/olpc: fix 'logical not is only applied to the left hand side'
+    - spmi: trace: fix stack-out-of-bound access in SPMI tracing functions
+    - kexec, KEYS, s390: Make use of built-in and secondary keyring for signature
+      verification
+    - tpm: eventlog: Fix section mismatch for DEBUG_SECTION_MISMATCH
+    - btrfs: reset block group chunk force if we have to wait
+    - ext4: add EXT4_INODE_HAS_XATTR_SPACE macro in xattr.h
+    - ext4: make sure ext4_append() always allocates new block
+    - ext4: fix use-after-free in ext4_xattr_set_entry
+    - ext4: update s_overhead_clusters in the superblock during an on-line resize
+    - ext4: fix extent status tree race in writeback error recovery path
+    - ext4: correct max_inline_xattr_value_size computing
+    - ext4: correct the misjudgment in ext4_iget_extra_inode
+    - intel_th: pci: Add Raptor Lake-S CPU support
+    - intel_th: pci: Add Raptor Lake-S PCH support
+    - intel_th: pci: Add Meteor Lake-P support
+    - dm raid: fix address sanitizer warning in raid_resume
+    - dm raid: fix address sanitizer warning in raid_status
+    - dm thin: fix use-after-free crash in dm_sm_register_threshold_callback
+    - dm writecache: set a default MAX_WRITEBACK_JOBS
+    - ACPI: CPPC: Do not prevent CPPC from working in the future
+    - timekeeping: contribute wall clock to rng on time change
+    - firmware: arm_scpi: Ensure scpi_info is not assigned if the probe fails
+    - iommu/vt-d: avoid invalid memory access via node_online(NUMA_NO_NODE)
+    - btrfs: reject log replay if there is unsupported RO compat flag
+    - KVM: Add infrastructure and macro to mark VM as bugged
+    - KVM: x86: Check lapic_in_kernel() before attempting to set a SynIC irq
+    - KVM: x86: Avoid theoretical NULL pointer dereference in
+      kvm_irq_delivery_to_apic_fast()
+    - tcp: fix over estimation in sk_forced_mem_schedule()
+    - scsi: sg: Allow waiting for commands to complete on removed device
+    - Bluetooth: L2CAP: Fix l2cap_global_chan_by_psm regression
+    - net/9p: Initialize the iounit field during fid creation
+    - net_sched: cls_route: disallow handle of 0
+    - ALSA: info: Fix llseek return value when using callback
+    - rds: add missing barrier to release_refill
+    - ata: libata-eh: Add missing command name
+    - mmc: pxamci: Fix another error handling path in pxamci_probe()
+    - mmc: pxamci: Fix an error handling path in pxamci_probe()
+    - btrfs: fix lost error handling when looking up extended ref on log replay
+    - tracing: Have filter accept "common_cpu" to be consistent
+    - can: ems_usb: fix clang's -Wunaligned-access warning
+    - apparmor: fix quiet_denied for file rules
+    - apparmor: fix absroot causing audited secids to begin with =
+    - apparmor: Fix failed mount permission check error message
+    - apparmor: fix aa_label_asxprint return check
+    - apparmor: fix overlapping attachment computation
+    - apparmor: fix reference count leak in aa_pivotroot()
+    - apparmor: Fix memleak in aa_simple_write_to_buffer()
+    - Documentation: ACPI: EINJ: Fix obsolete example
+    - NFSv4.1: Don't decrease the value of seq_nr_highest_sent
+    - NFSv4.1: Handle NFS4ERR_DELAY replies to OP_SEQUENCE correctly
+    - NFSv4: Fix races in the legacy idmapper upcall
+    - NFSv4.1: RECLAIM_COMPLETE must handle EACCES
+    - NFSv4/pnfs: Fix a use-after-free bug in open
+    - can: mcp251x: Fix race condition on receive interrupt
+    - sunrpc: fix expiry of auth creds
+    - SUNRPC: Reinitialise the backchannel request buffers before reuse
+    - devlink: Fix use-after-free after a failed reload
+    - net: bgmac: Fix a BUG triggered by wrong bytes_compl
+    - pinctrl: nomadik: Fix refcount leak in nmk_pinctrl_dt_subnode_to_map
+    - pinctrl: qcom: msm8916: Allow CAMSS GP clocks to be muxed
+    - pinctrl: sunxi: Add I/O bias setting for H6 R-PIO
+    - ACPI: property: Return type of acpi_add_nondev_subnodes() should be bool
+    - geneve: do not use RT_TOS for IPv6 flowlabel
+    - plip: avoid rcu debug splat
+    - vsock: Fix memory leak in vsock_connect()
+    - vsock: Set socket state back to SS_UNCONNECTED in vsock_connect_timeout()
+    - dt-bindings: arm: qcom: fix MSM8916 MTP compatibles
+    - tools/vm/slabinfo: use alphabetic order when two values are equal
+    - tools build: Switch to new openssl API for test-libcrypto
+    - NTB: ntb_tool: uninitialized heap data in tool_fn_write()
+    - nfp: ethtool: fix the display error of `ethtool -m DEVNAME`
+    - xen/xenbus: fix return type in xenbus_file_read()
+    - atm: idt77252: fix use-after-free bugs caused by tst_timer
+    - dpaa2-eth: trace the allocated address instead of page struct
+    - tee: add overflow check in register_shm_helper()
+    - nios2: page fault et.al. are *not* restartable syscalls...
+    - nios2: don't leave NULLs in sys_call_table[]
+    - nios2: traced syscall does need to check the syscall number
+    - nios2: fix syscall restart checks
+    - nios2: restarts apply only to the first sigframe we build...
+    - nios2: add force_successful_syscall_return()
+    - iavf: Fix adminq error handling
+    - clk: rockchip: add sclk_mac_lbtest to rk3188_critical_clocks
+    - netfilter: nf_tables: really skip inactive sets when allocating name
+    - powerpc/pci: Fix get_phb_number() locking
+    - net: dsa: mv88e6060: prevent crash on an unused port
+    - net: moxa: pass pdev instead of ndev to DMA functions
+    - net: dsa: microchip: ksz9477: fix fdb_dump last invalid entry
+    - ice: Ignore EEXIST when setting promisc mode
+    - i40e: Fix to stop tx_timeout recovery if GLOBR fails
+    - fec: Fix timer capture timing in `fec_ptp_enable_pps()`
+    - igb: Add lock to avoid data race
+    - gcc-plugins: Undefine LATENT_ENTROPY_PLUGIN when plugin disabled for a file
+    - locking/atomic: Make test_and_*_bit() ordered on failure
+    - drm/meson: Fix refcount bugs in meson_vpu_has_available_connectors()
+    - PCI: Add ACS quirk for Broadcom BCM5750x NICs
+    - usb: cdns3 fix use-after-free at workaround 2
+    - usb: gadget: uvc: call uvc uvcg_warn on completed status instead of
+      uvcg_info
+    - irqchip/tegra: Fix overflow implicit truncation warnings
+    - drm/meson: Fix overflow implicit truncation warnings
+    - usb: host: ohci-ppc-of: Fix refcount leak bug
+    - usb: renesas: Fix refcount leak bug
+    - vboxguest: Do not use devm for irq
+    - clk: qcom: ipq8074: dont disable gcc_sleep_clk_src
+    - scsi: lpfc: Prevent buffer overflow crashes in debugfs with malformed user
+      input
+    - gadgetfs: ep_io - wait until IRQ finishes
+    - cxl: Fix a memory leak in an error handling path
+    - PCI/ACPI: Guard ARM64-specific mcfg_quirks
+    - um: add "noreboot" command line option for PANIC_TIMEOUT=-1 setups
+    - selftests/kprobe: Do not test for GRP/ without event failures
+    - dmaengine: sprd: Cleanup in .remove() after pm_runtime_get_sync() failed
+    - nvmet-tcp: fix lockdep complaint on nvmet_tcp_wq flush during queue teardown
+    - drivers:md:fix a potential use-after-free bug
+    - ext4: avoid remove directory when directory is corrupted
+    - ext4: avoid resizing to a partial cluster size
+    - lib/list_debug.c: Detect uninitialized lists
+    - tty: serial: Fix refcount leak bug in ucc_uart.c
+    - vfio: Clear the caps->buf to NULL after free
+    - mips: cavium-octeon: Fix missing of_node_put() in octeon2_usb_clocks_start
+    - riscv: mmap with PROT_WRITE but no PROT_READ is invalid
+    - RISC-V: Add fast call path of crash_kexec()
+    - watchdog: export lockup_detector_reconfigure
+    - powerpc/32: Don't always pass -mcpu=powerpc to the compiler
+    - ALSA: core: Add async signal helpers
+    - ALSA: timer: Use deferred fasync helper
+    - f2fs: fix to avoid use f2fs_bug_on() in f2fs_new_node_page()
+    - smb3: check xattr value length earlier
+    - powerpc/64: Init jump labels before parse_early_param()
+    - video: fbdev: i740fb: Check the argument of i740_calc_vclk()
+    - MIPS: tlbex: Explicitly compare _PAGE_NO_EXEC against 0
+    - tracing/probes: Have kprobes and uprobes use $COMM too
+    - can: j1939: j1939_sk_queue_activate_next_locked(): replace WARN_ON_ONCE with
+      netdev_warn_once()
+    - can: j1939: j1939_session_destroy(): fix memory leak of skbs
+    - btrfs: only write the sectors in the vertical stripe which has data stripes
+    - btrfs: raid56: don't trust any cached sector in __raid56_parity_recover()
+    - Linux 5.4.211
+
+  * CVE-2022-3028
+    - af_key: Do not call xfrm_probe_algs in parallel
+
+  * CVE-2022-2978
+    - fs: fix UAF/GPF bug in nilfs_mdt_destroy
+
+  * CVE-2022-40768
+    - scsi: stex: Properly zero out the passthrough command structure
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Mon, 17 Oct 2022 17:19:41 +0200
+
+linux (5.4.0-131.147) focal; urgency=medium
+
+  * CVE-2022-2602
+    - SAUCE: io_uring/af_unix: defer registered files gc to io_uring release
+    - SAUCE: io_uring/af_unix: fix memleak during unix GC
+
+  * CVE-2022-41674
+    - SAUCE: wifi: cfg80211: fix u8 overflow in
+      cfg80211_update_notlisted_nontrans()
+    - SAUCE: wifi: cfg80211/mac80211: reject bad MBSSID elements
+    - SAUCE: wifi: cfg80211: ensure length byte is present before access
+    - SAUCE: wifi: mac80211_hwsim: avoid mac80211 warning on bad rate
+    - SAUCE: wifi: cfg80211: update hidden BSSes to avoid WARN_ON
+
+  * CVE-2022-42721
+    - SAUCE: wifi: cfg80211: avoid nontransmitted BSS list corruption
+
+  * CVE-2022-42720
+    - SAUCE: wifi: cfg80211: fix BSS refcounting bugs
+
+ -- Thadeu Lima de Souza Cascardo <cascardo@canonical.com>  Fri, 14 Oct 2022 13:32:31 -0300
+
+linux (5.4.0-128.144) focal; urgency=medium
+
+  * focal/linux: 5.4.0-128.144 -proposed tracker (LP: #1990152)
+
+  * CVE-2022-3176
+    - io_uring: disable polling pollfree files
+
+  * ip/nexthop: fix default address selection for connected nexthop
+    (LP: #1988809)
+    - selftests/net: test nexthop without gw
+
+  * ip/nexthop: fix default address selection for connected nexthop
+    (LP: #1988809) // icmp_redirect.sh in ubuntu_kernel_selftests failed on
+    Jammy 5.15.0-49.55 (LP: #1990124)
+    - ip: fix triggering of 'icmp redirect'
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Tue, 20 Sep 2022 11:19:18 +0200
+
+linux (5.4.0-127.143) focal; urgency=medium
+
+  * focal/linux: 5.4.0-127.143 -proposed tracker (LP: #1989892)
+
+  * Packaging resync (LP: #1786013)
+    - debian/dkms-versions -- update from kernel-versions (main/2022.09.19)
+
+  * [UBUNTU 20.04] mlx5 driver crashes on accessing device attributes during
+    recovery (LP: #1987287)
+    - net/mlx5: Avoid processing commands before cmdif is ready
+
+  * Focal update: v5.4.210 upstream stable release (LP: #1989230)
+    - thermal: Fix NULL pointer dereferences in of_thermal_ functions
+    - ACPI: video: Force backlight native for some TongFang devices
+    - ACPI: video: Shortening quirk list by identifying Clevo by board_name only
+    - ACPI: APEI: Better fix to avoid spamming the console with old error logs
+    - bpf: Verifer, adjust_scalar_min_max_vals to always call update_reg_bounds()
+    - selftests/bpf: Extend verifier and bpf_sock tests for dst_port loads
+    - bpf: Test_verifier, #70 error message updates for 32-bit right shift
+    - KVM: Don't null dereference ops->destroy
+    - selftests: KVM: Handle compiler optimizations in ucall
+    - media: v4l2-mem2mem: Apply DST_QUEUE_OFF_BASE on MMAP buffers across ioctls
+    - macintosh/adb: fix oob read in do_adb_query() function
+    - x86/speculation: Add RSB VM Exit protections
+    - x86/speculation: Add LFENCE to RSB fill sequence
+    - Linux 5.4.210
+
+  * Focal update: v5.4.209 upstream stable release (LP: #1989228)
+    - Bluetooth: L2CAP: Fix use-after-free caused by l2cap_chan_put
+    - ntfs: fix use-after-free in ntfs_ucsncmp()
+    - s390/archrandom: prevent CPACF trng invocations in interrupt context
+    - tcp: Fix data-races around sysctl_tcp_dsack.
+    - tcp: Fix a data-race around sysctl_tcp_app_win.
+    - tcp: Fix a data-race around sysctl_tcp_adv_win_scale.
+    - tcp: Fix a data-race around sysctl_tcp_frto.
+    - tcp: Fix a data-race around sysctl_tcp_nometrics_save.
+    - ice: check (DD | EOF) bits on Rx descriptor rather than (EOP | RS)
+    - ice: do not setup vlan for loopback VSI
+    - scsi: ufs: host: Hold reference returned by of_parse_phandle()
+    - tcp: Fix a data-race around sysctl_tcp_limit_output_bytes.
+    - tcp: Fix a data-race around sysctl_tcp_challenge_ack_limit.
+    - net: ping6: Fix memleak in ipv6_renew_options().
+    - ipv6/addrconf: fix a null-ptr-deref bug for ip6_ptr
+    - igmp: Fix data-races around sysctl_igmp_qrv.
+    - net: sungem_phy: Add of_node_put() for reference returned by of_get_parent()
+    - tcp: Fix a data-race around sysctl_tcp_min_tso_segs.
+    - tcp: Fix a data-race around sysctl_tcp_min_rtt_wlen.
+    - tcp: Fix a data-race around sysctl_tcp_autocorking.
+    - tcp: Fix a data-race around sysctl_tcp_invalid_ratelimit.
+    - Documentation: fix sctp_wmem in ip-sysctl.rst
+    - tcp: Fix a data-race around sysctl_tcp_comp_sack_delay_ns.
+    - tcp: Fix a data-race around sysctl_tcp_comp_sack_nr.
+    - i40e: Fix interface init with MSI interrupts (no MSI-X)
+    - sctp: fix sleep in atomic context bug in timer handlers
+    - virtio-net: fix the race between refill work and close
+    - perf symbol: Correct address for bss symbols
+    - sfc: disable softirqs for ptp TX
+    - sctp: leave the err path free in sctp_stream_init to sctp_stream_free
+    - ARM: crypto: comment out gcc warning that breaks clang builds
+    - mt7601u: add USB device ID for some versions of XiaoDu WiFi Dongle.
+    - scsi: core: Fix race between handling STS_RESOURCE and completion
+    - Linux 5.4.209
+
+  * Focal update: v5.4.208 upstream stable release (LP: #1988225)
+    - pinctrl: stm32: fix optional IRQ support to gpios
+    - riscv: add as-options for modules with assembly compontents
+    - mlxsw: spectrum_router: Fix IPv4 nexthop gateway indication
+    - lockdown: Fix kexec lockdown bypass with ima policy
+    - xen/gntdev: Ignore failure to unmap INVALID_GRANT_HANDLE
+    - PCI: hv: Fix multi-MSI to allow more than one MSI vector
+    - PCI: hv: Fix hv_arch_irq_unmask() for multi-MSI
+    - PCI: hv: Reuse existing IRTE allocation in compose_msi_msg()
+    - PCI: hv: Fix interrupt mapping for multi-MSI
+    - serial: mvebu-uart: correctly report configured baudrate value
+    - xfrm: xfrm_policy: fix a possible double xfrm_pols_put() in
+      xfrm_bundle_lookup()
+    - power/reset: arm-versatile: Fix refcount leak in versatile_reboot_probe
+    - pinctrl: ralink: Check for null return of devm_kcalloc
+    - perf/core: Fix data race between perf_event_set_output() and
+      perf_mmap_close()
+    - igc: Reinstate IGC_REMOVED logic and implement it properly
+    - ip: Fix data-races around sysctl_ip_no_pmtu_disc.
+    - ip: Fix data-races around sysctl_ip_fwd_use_pmtu.
+    - ip: Fix data-races around sysctl_ip_nonlocal_bind.
+    - ip: Fix a data-race around sysctl_fwmark_reflect.
+    - tcp/dccp: Fix a data-race around sysctl_tcp_fwmark_accept.
+    - tcp: Fix data-races around sysctl_tcp_mtu_probing.
+    - tcp: Fix data-races around sysctl_tcp_base_mss.
+    - tcp: Fix data-races around sysctl_tcp_min_snd_mss.
+    - tcp: Fix a data-race around sysctl_tcp_mtu_probe_floor.
+    - tcp: Fix a data-race around sysctl_tcp_probe_threshold.
+    - tcp: Fix a data-race around sysctl_tcp_probe_interval.
+    - i2c: cadence: Change large transfer count reset logic to be unconditional
+    - net: stmmac: fix dma queue left shift overflow issue
+    - net/tls: Fix race in TLS device down flow
+    - igmp: Fix data-races around sysctl_igmp_llm_reports.
+    - igmp: Fix a data-race around sysctl_igmp_max_memberships.
+    - tcp: Fix data-races around sysctl_tcp_syncookies.
+    - tcp: Fix data-races around sysctl_tcp_reordering.
+    - tcp: Fix data-races around some timeout sysctl knobs.
+    - tcp: Fix a data-race around sysctl_tcp_notsent_lowat.
+    - tcp: Fix a data-race around sysctl_tcp_tw_reuse.
+    - tcp: Fix data-races around sysctl_max_syn_backlog.
+    - tcp: Fix data-races around sysctl_tcp_fastopen.
+    - iavf: Fix handling of dummy receive descriptors
+    - i40e: Fix erroneous adapter reinitialization during recovery process
+    - ixgbe: Add locking to prevent panic when setting sriov_numvfs to zero
+    - gpio: pca953x: only use single read/write for No AI mode
+    - be2net: Fix buffer overflow in be_get_module_eeprom
+    - ipv4: Fix a data-race around sysctl_fib_multipath_use_neigh.
+    - udp: Fix a data-race around sysctl_udp_l3mdev_accept.
+    - tcp: Fix data-races around sysctl knobs related to SYN option.
+    - tcp: Fix a data-race around sysctl_tcp_early_retrans.
+    - tcp: Fix data-races around sysctl_tcp_recovery.
+    - tcp: Fix a data-race around sysctl_tcp_thin_linear_timeouts.
+    - tcp: Fix data-races around sysctl_tcp_slow_start_after_idle.
+    - tcp: Fix a data-race around sysctl_tcp_retrans_collapse.
+    - tcp: Fix a data-race around sysctl_tcp_stdurg.
+    - tcp: Fix a data-race around sysctl_tcp_rfc1337.
+    - tcp: Fix data-races around sysctl_tcp_max_reordering.
+    - spi: bcm2835: bcm2835_spi_handle_err(): fix NULL pointer deref for non DMA
+      transfers
+    - mm/mempolicy: fix uninit-value in mpol_rebind_policy()
+    - bpf: Make sure mac_header was set before using it
+    - dlm: fix pending remove if msg allocation fails
+    - ima: remove the IMA_TEMPLATE Kconfig option
+    - [Config] updateconfigs for IMA_TEMPLATE
+    - locking/refcount: Define constants for saturation and max refcount values
+    - locking/refcount: Ensure integer operands are treated as signed
+    - locking/refcount: Remove unused refcount_*_checked() variants
+    - locking/refcount: Move the bulk of the REFCOUNT_FULL implementation into the
+      <linux/refcount.h> header
+    - locking/refcount: Improve performance of generic REFCOUNT_FULL code
+    - locking/refcount: Move saturation warnings out of line
+    - locking/refcount: Consolidate REFCOUNT_{MAX,SATURATED} definitions
+    - locking/refcount: Consolidate implementations of refcount_t
+    - [Config] updateconfigs for REFCOUNT_FULL
+    - x86: get rid of small constant size cases in raw_copy_{to,from}_user()
+    - x86/uaccess: Implement macros for CMPXCHG on user addresses
+    - mmap locking API: initial implementation as rwsem wrappers
+    - x86/mce: Deduplicate exception handling
+    - bitfield.h: Fix "type of reg too small for mask" test
+    - ALSA: memalloc: Align buffer allocations in page size
+    - Bluetooth: Add bt_skb_sendmsg helper
+    - Bluetooth: Add bt_skb_sendmmsg helper
+    - Bluetooth: SCO: Replace use of memcpy_from_msg with bt_skb_sendmsg
+    - Bluetooth: RFCOMM: Replace use of memcpy_from_msg with bt_skb_sendmmsg
+    - Bluetooth: Fix passing NULL to PTR_ERR
+    - Bluetooth: SCO: Fix sco_send_frame returning skb->len
+    - Bluetooth: Fix bt_skb_sendmmsg not allocating partial chunks
+    - tty: drivers/tty/, stop using tty_schedule_flip()
+    - tty: the rest, stop using tty_schedule_flip()
+    - tty: drop tty_schedule_flip()
+    - tty: extract tty_flip_buffer_commit() from tty_flip_buffer_push()
+    - tty: use new tty_insert_flip_string_and_push_buffer() in pty_write()
+    - x86: drop bogus "cc" clobber from __try_cmpxchg_user_asm()
+    - Linux 5.4.208
+
+  * Focal update: v5.4.207 upstream stable release (LP: #1988219)
+    - ALSA: hda - Add fixup for Dell Latitidue E5430
+    - ALSA: hda/conexant: Apply quirk for another HP ProDesk 600 G3 model
+    - ALSA: hda/realtek - Fix headset mic problem for a HP machine with alc671
+    - ALSA: hda/realtek - Fix headset mic problem for a HP machine with alc221
+    - ALSA: hda/realtek - Enable the headset-mic on a Xiaomi's laptop
+    - xen/netback: avoid entering xenvif_rx_next_skb() with an empty rx queue
+    - tracing/histograms: Fix memory leak problem
+    - net: sock: tracing: Fix sock_exceed_buf_limit not to dereference stale
+      pointer
+    - ip: fix dflt addr selection for connected nexthop
+    - ARM: 9213/1: Print message about disabled Spectre workarounds only once
+    - ARM: 9214/1: alignment: advance IT state after emulating Thumb instruction
+    - wifi: mac80211: fix queue selection for mesh/OCB interfaces
+    - cgroup: Use separate src/dst nodes when preloading css_sets for migration
+    - drm/panfrost: Fix shrinker list corruption by madvise IOCTL
+    - nilfs2: fix incorrect masking of permission flags for symlinks
+    - Revert "evm: Fix memleak in init_desc"
+    - sched/rt: Disable RT_RUNTIME_SHARE by default
+    - ext4: fix race condition between ext4_write and ext4_convert_inline_data
+    - ARM: dts: imx6qdl-ts7970: Fix ngpio typo and count
+    - ARM: 9209/1: Spectre-BHB: avoid pr_info() every time a CPU comes out of idle
+    - ARM: 9210/1: Mark the FDT_FIXED sections as shareable
+    - drm/i915: fix a possible refcount leak in intel_dp_add_mst_connector()
+    - ima: Fix a potential integer overflow in ima_appraise_measurement
+    - ASoC: sgtl5000: Fix noise on shutdown/remove
+    - net: stmmac: dwc-qos: Disable split header for Tegra194
+    - inetpeer: Fix data-races around sysctl.
+    - net: Fix data-races around sysctl_mem.
+    - cipso: Fix data-races around sysctl.
+    - icmp: Fix data-races around sysctl.
+    - ipv4: Fix a data-race around sysctl_fib_sync_mem.
+    - ARM: dts: at91: sama5d2: Fix typo in i2s1 node
+    - ARM: dts: sunxi: Fix SPI NOR campatible on Orange Pi Zero
+    - drm/i915/gt: Serialize TLB invalidates with GT resets
+    - icmp: Fix a data-race around sysctl_icmp_ratelimit.
+    - icmp: Fix a data-race around sysctl_icmp_ratemask.
+    - raw: Fix a data-race around sysctl_raw_l3mdev_accept.
+    - ipv4: Fix data-races around sysctl_ip_dynaddr.
+    - net: ftgmac100: Hold reference returned by of_get_child_by_name()
+    - sfc: fix use after free when disabling sriov
+    - seg6: fix skb checksum evaluation in SRH encapsulation/insertion
+    - seg6: fix skb checksum in SRv6 End.B6 and End.B6.Encaps behaviors
+    - seg6: bpf: fix skb checksum in bpf_push_seg6_encap()
+    - sfc: fix kernel panic when creating VF
+    - mm: sysctl: fix missing numa_stat when !CONFIG_HUGETLB_PAGE
+    - virtio_mmio: Add missing PM calls to freeze/restore
+    - virtio_mmio: Restore guest page size on resume
+    - netfilter: br_netfilter: do not skip all hooks with 0 priority
+    - cpufreq: pmac32-cpufreq: Fix refcount leak bug
+    - platform/x86: hp-wmi: Ignore Sanitization Mode event
+    - net: tipc: fix possible refcount leak in tipc_sk_create()
+    - NFC: nxp-nci: don't print header length mismatch on i2c error
+    - nvme: fix regression when disconnect a recovering ctrl
+    - net: sfp: fix memory leak in sfp_probe()
+    - ASoC: ops: Fix off by one in range control validation
+    - ASoC: wm5110: Fix DRE control
+    - ASoC: cs47l15: Fix event generation for low power mux control
+    - ASoC: madera: Fix event generation for OUT1 demux
+    - ASoC: madera: Fix event generation for rate controls
+    - irqchip: or1k-pic: Undefine mask_ack for level triggered hardware
+    - x86: Clear .brk area at early boot
+    - soc: ixp4xx/npe: Fix unused match warning
+    - ARM: dts: stm32: use the correct clock source for CEC on stm32mp151
+    - signal handling: don't use BUG_ON() for debugging
+    - USB: serial: ftdi_sio: add Belimo device ids
+    - usb: typec: add missing uevent when partner support PD
+    - usb: dwc3: gadget: Fix event pending check
+    - tty: serial: samsung_tty: set dma burst_size to 1
+    - serial: 8250: fix return error code in serial8250_request_std_resource()
+    - serial: stm32: Clear prev values before setting RTS delays
+    - serial: pl011: UPSTAT_AUTORTS requires .throttle/unthrottle
+    - can: m_can: m_can_tx_handler(): fix use after free of skb
+    - Linux 5.4.207
+
+  * Focal update: v5.4.206 upstream stable release (LP: #1988215)
+    - Linux 5.4.206
+
+  * Focal update: v5.4.205 upstream stable release (LP: #1988214)
+    - esp: limit skb_page_frag_refill use to a single page
+    - mm/slub: add missing TID updates on slab deactivation
+    - can: bcm: use call_rcu() instead of costly synchronize_rcu()
+    - can: grcan: grcan_probe(): remove extra of_node_get()
+    - can: gs_usb: gs_usb_open/close(): fix memory leak
+    - usbnet: fix memory leak in error case
+    - net: rose: fix UAF bug caused by rose_t0timer_expiry
+    - iommu/vt-d: Fix PCI bus rescan device hot add
+    - fbdev: fbmem: Fix logo center image dx issue
+    - video: of_display_timing.h: include errno.h
+    - powerpc/powernv: delay rng platform device creation until later in boot
+    - can: kvaser_usb: replace run-time checks with struct kvaser_usb_driver_info
+    - can: kvaser_usb: kvaser_usb_leaf: fix CAN clock frequency regression
+    - can: kvaser_usb: kvaser_usb_leaf: fix bittiming limits
+    - xfs: remove incorrect ASSERT in xfs_rename
+    - ARM: meson: Fix refcount leak in meson_smp_prepare_cpus
+    - pinctrl: sunxi: a83t: Fix NAND function name for some pins
+    - pinctrl: sunxi: sunxi_pconf_set: use correct offset
+    - ARM: at91: pm: use proper compatible for sama5d2's rtc
+    - ARM: at91: pm: use proper compatibles for sam9x60's rtc and rtt
+    - ibmvnic: Properly dispose of all skbs during a failover.
+    - selftests: forwarding: fix flood_unicast_test when h2 supports
+      IFF_UNICAST_FLT
+    - selftests: forwarding: fix learning_test when h1 supports IFF_UNICAST_FLT
+    - selftests: forwarding: fix error message in learning_test
+    - i2c: cadence: Unregister the clk notifier in error path
+    - dmaengine: imx-sdma: Allow imx8m for imx7 FW revs
+    - misc: rtsx_usb: fix use of dma mapped buffer for usb bulk transfer
+    - misc: rtsx_usb: use separate command and response buffers
+    - misc: rtsx_usb: set return value in rsp_buf alloc err path
+    - dt-bindings: dma: allwinner,sun50i-a64-dma: Fix min/max typo
+    - ida: don't use BUG_ON() for debugging
+    - dmaengine: pl330: Fix lockdep warning about non-static key
+    - dmaengine: at_xdma: handle errors of at_xdmac_alloc_desc() correctly
+    - dmaengine: ti: Fix refcount leak in ti_dra7_xbar_route_allocate
+    - dmaengine: ti: Add missing put_device in ti_dra7_xbar_route_allocate
+    - Linux 5.4.205
+
+  * Focal update: v5.4.204 upstream stable release (LP: #1988212)
+    - ipv6: take care of disable_policy when restoring routes
+    - nvdimm: Fix badblocks clear off-by-one error
+    - powerpc/prom_init: Fix kernel config grep
+    - powerpc/bpf: Fix use of user_pt_regs in uapi
+    - dm raid: fix accesses beyond end of raid member array
+    - dm raid: fix KASAN warning in raid5_add_disks
+    - s390/archrandom: simplify back to earlier design and initialize earlier
+    - SUNRPC: Fix READ_PLUS crasher
+    - net: rose: fix UAF bugs caused by timer handler
+    - net: usb: ax88179_178a: Fix packet receiving
+    - virtio-net: fix race between ndo_open() and virtio_device_ready()
+    - selftests/net: pass ipv6_args to udpgso_bench's IPv6 TCP test
+    - net: tun: unlink NAPI from device on destruction
+    - net: tun: stop NAPI when detaching queues
+    - RDMA/qedr: Fix reporting QP timeout attribute
+    - linux/dim: Fix divide by 0 in RDMA DIM
+    - usbnet: fix memory allocation in helpers
+    - net: ipv6: unexport __init-annotated seg6_hmac_net_init()
+    - caif_virtio: fix race between virtio_device_ready() and ndo_open()
+    - PM / devfreq: exynos-ppmu: Fix refcount leak in of_get_devfreq_events
+    - s390: remove unneeded 'select BUILD_BIN2C'
+    - netfilter: nft_dynset: restore set element counter when failing to update
+    - net/sched: act_api: Notify user space if any actions were flushed before
+      error
+    - net: bonding: fix possible NULL deref in rlb code
+    - net: bonding: fix use-after-free after 802.3ad slave unbind
+    - nfc: nfcmrvl: Fix irq_of_parse_and_map() return value
+    - NFC: nxp-nci: Don't issue a zero length i2c_master_read()
+    - net: tun: avoid disabling NAPI twice
+    - xen/gntdev: Avoid blocking in unmap_grant_pages()
+    - hwmon: (ibmaem) don't call platform_device_del() if platform_device_add()
+      fails
+    - net: dsa: bcm_sf2: force pause link settings
+    - sit: use min
+    - ipv6/sit: fix ipip6_tunnel_get_prl return value
+    - rseq/selftests,x86_64: Add rseq_offset_deref_addv()
+    - selftests/rseq: remove ARRAY_SIZE define from individual tests
+    - selftests/rseq: introduce own copy of rseq uapi header
+    - selftests/rseq: Remove useless assignment to cpu variable
+    - selftests/rseq: Remove volatile from __rseq_abi
+    - selftests/rseq: Introduce rseq_get_abi() helper
+    - selftests/rseq: Introduce thread pointer getters
+    - selftests/rseq: Uplift rseq selftests for compatibility with glibc-2.35
+    - selftests/rseq: Fix ppc32: wrong rseq_cs 32-bit field pointer on big endian
+    - selftests/rseq: Fix ppc32 missing instruction selection "u" and "x" for
+      load/store
+    - selftests/rseq: Fix ppc32 offsets by using long rather than off_t
+    - selftests/rseq: Fix warnings about #if checks of undefined tokens
+    - selftests/rseq: Remove arm/mips asm goto compiler work-around
+    - selftests/rseq: Fix: work-around asm goto compiler bugs
+    - selftests/rseq: x86-64: use %fs segment selector for accessing rseq thread
+      area
+    - selftests/rseq: x86-32: use %gs segment selector for accessing rseq thread
+      area
+    - selftests/rseq: Change type of rseq_offset to ptrdiff_t
+    - xen/blkfront: fix leaking data in shared pages
+    - xen/netfront: fix leaking data in shared pages
+    - xen/netfront: force data bouncing when backend is untrusted
+    - xen/blkfront: force data bouncing when backend is untrusted
+    - xen/arm: Fix race in RB-tree based P2M accounting
+    - net: usb: qmi_wwan: add Telit 0x1060 composition
+    - net: usb: qmi_wwan: add Telit 0x1070 composition
+    - clocksource/drivers/ixp4xx: remove EXPORT_SYMBOL_GPL from
+      ixp4xx_timer_setup()
+    - Linux 5.4.204
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Fri, 16 Sep 2022 11:05:09 +0200
+
+linux (5.4.0-126.142) focal; urgency=medium
+
+  * focal/linux: 5.4.0-126.142 -proposed tracker (LP: #1987819)
+
+  * [SRU] fnic driver on needs to be updated to 1.6.0.53 on Focal (LP: #1984011)
+    - scsi: fnic: Change shost_printk() to FNIC_FCS_DBG()
+    - scsi: fnic: Avoid looping in TRANS ETH on unload
+    - scsi: fnic: Change shost_printk() to FNIC_MAIN_DBG()
+    - scsi: fnic: Set scsi_set_resid() only for underflow
+    - scsi: fnic: Validate io_req before others
+
+  * Focal update: v5.4.203 upstream stable release (LP: #1986999)
+    - drm: remove drm_fb_helper_modinit
+    - powerpc/ftrace: Remove ftrace init tramp once kernel init is complete
+    - kexec_file: drop weak attribute from arch_kexec_apply_relocations[_add]
+    - net: mscc: ocelot: allow unregistered IP multicast flooding
+    - ARM: 8989/1: use .fpu assembler directives instead of assembler arguments
+    - ARM: 8990/1: use VFP assembler mnemonics in register load/store macros
+    - ARM: 8971/1: replace the sole use of a symbol with its definition
+    - crypto: arm/sha256-neon - avoid ADRL pseudo instruction
+    - crypto: arm/sha512-neon - avoid ADRL pseudo instruction
+    - ARM: 8933/1: replace Sun/Solaris style flag on section directive
+    - ARM: 8929/1: use APSR_nzcv instead of r15 as mrc operand
+    - ARM: OMAP2+: drop unnecessary adrl
+    - ARM: 9029/1: Make iwmmxt.S support Clang's integrated assembler
+    - crypto: arm - use Kconfig based compiler checks for crypto opcodes
+    - crypto: arm/ghash-ce - define fpu before fpu registers are referenced
+    - Linux 5.4.203
+
+  * Focal update: v5.4.202 upstream stable release (LP: #1986995)
+    - random: schedule mix_interrupt_randomness() less often
+    - ALSA: hda/via: Fix missing beep setup
+    - ALSA: hda/conexant: Fix missing beep setup
+    - ALSA: hda/realtek - ALC897 headset MIC no sound
+    - ALSA: hda/realtek: Add quirk for Clevo PD70PNT
+    - net: openvswitch: fix parsing of nw_proto for IPv6 fragments
+    - mmc: sdhci-pci-o2micro: Fix card detect by dealing with debouncing
+    - ata: libata: add qc->flags in ata_qc_complete_template tracepoint
+    - dm era: commit metadata in postsuspend after worker stops
+    - dm mirror log: clear log bits up to BITS_PER_LONG boundary
+    - random: quiet urandom warning ratelimit suppression message
+    - USB: serial: option: add Telit LE910Cx 0x1250 composition
+    - USB: serial: option: add Quectel EM05-G modem
+    - USB: serial: option: add Quectel RM500K module support
+    - bpf: Fix request_sock leak in sk lookup helpers
+    - phy: aquantia: Fix AN when higher speeds than 1G are not advertised
+    - bonding: ARP monitor spams NETDEV_NOTIFY_PEERS notifiers
+    - net/sched: sch_netem: Fix arithmetic in netem_dump() for 32-bit platforms
+    - drm/msm/mdp4: Fix refcount leak in mdp4_modeset_init_intf
+    - erspan: do not assume transport header is always set
+    - net/tls: fix tls_sk_proto_close executed repeatedly
+    - udmabuf: add back sanity check
+    - x86/xen: Remove undefined behavior in setup_features()
+    - MIPS: Remove repetitive increase irq_err_count
+    - afs: Fix dynamic root getattr
+    - ice: ethtool: advertise 1000M speeds properly
+    - regmap-irq: Fix a bug in regmap_irq_enable() for type_in_mask chips
+    - igb: Make DMA faster when CPU is active on the PCIe link
+    - virtio_net: fix xdp_rxq_info bug after suspend/resume
+    - Revert "net/tls: fix tls_sk_proto_close executed repeatedly"
+    - gpio: winbond: Fix error code in winbond_gpio_get()
+    - s390/cpumf: Handle events cycles and instructions identical
+    - iio: adc: vf610: fix conversion mode sysfs node name
+    - xhci: turn off port power in shutdown
+    - usb: chipidea: udc: check request status before setting device address
+    - iio:chemical:ccs811: rearrange iio trigger get and register
+    - iio:accel:bma180: rearrange iio trigger get and register
+    - iio:accel:mxc4005: rearrange iio trigger get and register
+    - iio: accel: mma8452: ignore the return value of reset operation
+    - iio: gyro: mpu3050: Fix the error handling in mpu3050_power_up()
+    - iio: trigger: sysfs: fix use-after-free on remove
+    - iio: adc: stm32: fix maximum clock rate for stm32mp15x
+    - iio: adc: axp288: Override TS pin bias current for some models
+    - xtensa: xtfpga: Fix refcount leak bug in setup
+    - xtensa: Fix refcount leak bug in time.c
+    - parisc: Enable ARCH_HAS_STRICT_MODULE_RWX
+    - powerpc: Enable execve syscall exit tracepoint
+    - powerpc/rtas: Allow ibm,platform-dump RTAS call with null buffer address
+    - powerpc/powernv: wire up rng during setup_arch
+    - ARM: dts: imx6qdl: correct PU regulator ramp delay
+    - ARM: exynos: Fix refcount leak in exynos_map_pmu
+    - soc: bcm: brcmstb: pm: pm-arm: Fix refcount leak in brcmstb_pm_probe
+    - ARM: Fix refcount leak in axxia_boot_secondary
+    - ARM: cns3xxx: Fix refcount leak in cns3xxx_init
+    - modpost: fix section mismatch check for exported init/exit sections
+    - random: update comment from copy_to_user() -> copy_to_iter()
+    - kbuild: link vmlinux only once for CONFIG_TRIM_UNUSED_KSYMS (2nd attempt)
+    - powerpc/pseries: wire up rng during setup_arch()
+    - Linux 5.4.202
+
+  * Focal update: v5.4.201 upstream stable release (LP: #1986993)
+    - dm: remove special-casing of bio-based immutable singleton target on NVMe
+    - usb: gadget: u_ether: fix regression in setting fixed MAC address
+    - tcp: add some entropy in __inet_hash_connect()
+    - tcp: use different parts of the port_offset for index and offset
+    - tcp: add small random increments to the source port
+    - tcp: dynamically allocate the perturb table used by source ports
+    - tcp: increase source port perturb table to 2^16
+    - tcp: drop the hash_32() part from the index calculation
+    - arm64: mm: Don't invalidate FROM_DEVICE buffers at start of DMA transfer
+    - Linux 5.4.201
+
+  * Focal update: v5.4.200 upstream stable release (LP: #1983152)
+    - Revert "UBUNTU: SAUCE: random: Make getrandom() ready earlier"
+    - 9p: missing chunk of "fs/9p: Don't update file type when updating file
+      attributes"
+    - bpf: Fix incorrect memory charge cost calculation in stack_map_alloc()
+    - nfc: st21nfca: fix incorrect sizing calculations in EVT_TRANSACTION
+    - crypto: blake2s - generic C library implementation and selftest
+    - lib/crypto: blake2s: move hmac construction into wireguard
+    - lib/crypto: sha1: re-roll loops to reduce code size
+    - compat_ioctl: remove /dev/random commands
+    - random: don't forget compat_ioctl on urandom
+    - random: Don't wake crng_init_wait when crng_init == 1
+    - random: Add a urandom_read_nowait() for random APIs that don't warn
+    - random: add GRND_INSECURE to return best-effort non-cryptographic bytes
+    - random: ignore GRND_RANDOM in getentropy(2)
+    - random: make /dev/random be almost like /dev/urandom
+    - random: remove the blocking pool
+    - random: delete code to pull data into pools
+    - random: remove kernel.random.read_wakeup_threshold
+    - random: remove unnecessary unlikely()
+    - random: convert to ENTROPY_BITS for better code readability
+    - random: Add and use pr_fmt()
+    - random: fix typo in add_timer_randomness()
+    - random: remove some dead code of poolinfo
+    - random: split primary/secondary crng init paths
+    - random: avoid warnings for !CONFIG_NUMA builds
+    - x86: Remove arch_has_random, arch_has_random_seed
+    - powerpc: Remove arch_has_random, arch_has_random_seed
+    - s390: Remove arch_has_random, arch_has_random_seed
+    - linux/random.h: Remove arch_has_random, arch_has_random_seed
+    - linux/random.h: Use false with bool
+    - linux/random.h: Mark CONFIG_ARCH_RANDOM functions __must_check
+    - powerpc: Use bool in archrandom.h
+    - random: add arch_get_random_*long_early()
+    - random: avoid arch_get_random_seed_long() when collecting IRQ randomness
+    - random: remove dead code left over from blocking pool
+    - MAINTAINERS: co-maintain random.c
+    - crypto: blake2s - include <linux/bug.h> instead of <asm/bug.h>
+    - crypto: blake2s - adjust include guard naming
+    - random: document add_hwgenerator_randomness() with other input functions
+    - random: remove unused irq_flags argument from add_interrupt_randomness()
+    - random: use BLAKE2s instead of SHA1 in extraction
+    - random: do not sign extend bytes for rotation when mixing
+    - random: do not re-init if crng_reseed completes before primary init
+    - random: mix bootloader randomness into pool
+    - random: harmonize "crng init done" messages
+    - random: use IS_ENABLED(CONFIG_NUMA) instead of ifdefs
+    - random: initialize ChaCha20 constants with correct endianness
+    - random: early initialization of ChaCha constants
+    - random: avoid superfluous call to RDRAND in CRNG extraction
+    - random: don't reset crng_init_cnt on urandom_read()
+    - random: fix typo in comments
+    - random: cleanup poolinfo abstraction
+    - random: cleanup integer types
+    - random: remove incomplete last_data logic
+    - random: remove unused extract_entropy() reserved argument
+    - random: rather than entropy_store abstraction, use global
+    - random: remove unused OUTPUT_POOL constants
+    - random: de-duplicate INPUT_POOL constants
+    - random: prepend remaining pool constants with POOL_
+    - random: cleanup fractional entropy shift constants
+    - random: access input_pool_data directly rather than through pointer
+    - random: selectively clang-format where it makes sense
+    - random: simplify arithmetic function flow in account()
+    - random: continually use hwgenerator randomness
+    - random: access primary_pool directly rather than through pointer
+    - random: only call crng_finalize_init() for primary_crng
+    - random: use computational hash for entropy extraction
+    - random: simplify entropy debiting
+    - random: use linear min-entropy accumulation crediting
+    - random: always wake up entropy writers after extraction
+    - random: make credit_entropy_bits() always safe
+    - random: remove use_input_pool parameter from crng_reseed()
+    - random: remove batched entropy locking
+    - random: fix locking in crng_fast_load()
+    - random: use RDSEED instead of RDRAND in entropy extraction
+    - random: get rid of secondary crngs
+    - random: inline leaves of rand_initialize()
+    - random: ensure early RDSEED goes through mixer on init
+    - random: do not xor RDRAND when writing into /dev/random
+    - random: absorb fast pool into input pool after fast load
+    - random: use simpler fast key erasure flow on per-cpu keys
+    - random: use hash function for crng_slow_load()
+    - random: make more consistent use of integer types
+    - random: remove outdated INT_MAX >> 6 check in urandom_read()
+    - random: zero buffer after reading entropy from userspace
+    - random: fix locking for crng_init in crng_reseed()
+    - random: tie batched entropy generation to base_crng generation
+    - random: remove ifdef'd out interrupt bench
+    - random: remove unused tracepoints
+    - random: add proper SPDX header
+    - random: deobfuscate irq u32/u64 contributions
+    - random: introduce drain_entropy() helper to declutter crng_reseed()
+    - random: remove useless header comment
+    - random: remove whitespace and reorder includes
+    - random: group initialization wait functions
+    - random: group crng functions
+    - random: group entropy extraction functions
+    - random: group entropy collection functions
+    - random: group userspace read/write functions
+    - random: group sysctl functions
+    - random: rewrite header introductory comment
+    - random: defer fast pool mixing to worker
+    - random: do not take pool spinlock at boot
+    - random: unify early init crng load accounting
+    - random: check for crng_init == 0 in add_device_randomness()
+    - random: pull add_hwgenerator_randomness() declaration into random.h
+    - random: clear fast pool, crng, and batches in cpuhp bring up
+    - random: round-robin registers as ulong, not u32
+    - random: only wake up writers after zap if threshold was passed
+    - random: cleanup UUID handling
+    - random: unify cycles_t and jiffies usage and types
+    - random: do crng pre-init loading in worker rather than irq
+    - random: give sysctl_random_min_urandom_seed a more sensible value
+    - random: don't let 644 read-only sysctls be written to
+    - random: replace custom notifier chain with standard one
+    - random: use SipHash as interrupt entropy accumulator
+    - random: make consistent usage of crng_ready()
+    - random: reseed more often immediately after booting
+    - random: check for signal and try earlier when generating entropy
+    - random: skip fast_init if hwrng provides large chunk of entropy
+    - random: treat bootloader trust toggle the same way as cpu trust toggle
+    - random: re-add removed comment about get_random_{u32,u64} reseeding
+    - random: mix build-time latent entropy into pool at init
+    - random: do not split fast init input in add_hwgenerator_randomness()
+    - random: do not allow user to keep crng key around on stack
+    - random: check for signal_pending() outside of need_resched() check
+    - random: check for signals every PAGE_SIZE chunk of /dev/[u]random
+    - random: allow partial reads if later user copies fail
+    - random: make random_get_entropy() return an unsigned long
+    - random: document crng_fast_key_erasure() destination possibility
+    - random: fix sysctl documentation nits
+    - init: call time_init() before rand_initialize()
+    - ia64: define get_cycles macro for arch-override
+    - s390: define get_cycles macro for arch-override
+    - parisc: define get_cycles macro for arch-override
+    - alpha: define get_cycles macro for arch-override
+    - powerpc: define get_cycles macro for arch-override
+    - timekeeping: Add raw clock fallback for random_get_entropy()
+    - m68k: use fallback for random_get_entropy() instead of zero
+    - mips: use fallback for random_get_entropy() instead of just c0 random
+    - arm: use fallback for random_get_entropy() instead of zero
+    - nios2: use fallback for random_get_entropy() instead of zero
+    - x86/tsc: Use fallback for random_get_entropy() instead of zero
+    - um: use fallback for random_get_entropy() instead of zero
+    - sparc: use fallback for random_get_entropy() instead of zero
+    - xtensa: use fallback for random_get_entropy() instead of zero
+    - random: insist on random_get_entropy() existing in order to simplify
+    - random: do not use batches when !crng_ready()
+    - random: use first 128 bits of input as fast init
+    - random: do not pretend to handle premature next security model
+    - random: order timer entropy functions below interrupt functions
+    - random: do not use input pool from hard IRQs
+    - random: help compiler out with fast_mix() by using simpler arguments
+    - siphash: use one source of truth for siphash permutations
+    - random: use symbolic constants for crng_init states
+    - random: avoid initializing twice in credit race
+    - random: move initialization out of reseeding hot path
+    - random: remove ratelimiting for in-kernel unseeded randomness
+    - random: use proper jiffies comparison macro
+    - random: handle latent entropy and command line from random_init()
+    - random: credit architectural init the exact amount
+    - random: use static branch for crng_ready()
+    - random: remove extern from functions in header
+    - random: use proper return types on get_random_{int,long}_wait()
+    - random: make consistent use of buf and len
+    - random: move initialization functions out of hot pages
+    - random: move randomize_page() into mm where it belongs
+    - random: unify batched entropy implementations
+    - random: convert to using fops->read_iter()
+    - random: convert to using fops->write_iter()
+    - random: wire up fops->splice_{read,write}_iter()
+    - random: check for signals after page of pool writes
+    - Revert "random: use static branch for crng_ready()"
+    - crypto: drbg - always seeded with SP800-90B compliant noise source
+    - crypto: drbg - prepare for more fine-grained tracking of seeding state
+    - crypto: drbg - track whether DRBG was seeded with !rng_is_initialized()
+    - crypto: drbg - move dynamic ->reseed_threshold adjustments to __drbg_seed()
+    - crypto: drbg - always try to free Jitter RNG instance
+    - crypto: drbg - make reseeding from get_random_bytes() synchronous
+    - random: avoid checking crng_ready() twice in random_init()
+    - random: mark bootloader randomness code as __init
+    - random: account for arch randomness in bits
+    - powerpc/kasan: Silence KASAN warnings in __get_wchan()
+    - ASoC: nau8822: Add operation for internal PLL off and on
+    - dma-debug: make things less spammy under memory pressure
+    - ASoC: cs42l52: Fix TLV scales for mixer controls
+    - ASoC: cs35l36: Update digital volume TLV
+    - ASoC: cs53l30: Correct number of volume levels on SX controls
+    - ASoC: cs42l52: Correct TLV for Bypass Volume
+    - ASoC: cs42l56: Correct typo in minimum level for SX volume controls
+    - ata: libata-core: fix NULL pointer deref in ata_host_alloc_pinfo()
+    - ASoC: wm8962: Fix suspend while playing music
+    - ASoC: es8328: Fix event generation for deemphasis control
+    - ASoC: wm_adsp: Fix event generation for wm_adsp_fw_put()
+    - scsi: vmw_pvscsi: Expand vcpuHint to 16 bits
+    - scsi: lpfc: Fix port stuck in bypassed state after LIP in PT2PT topology
+    - scsi: lpfc: Allow reduced polling rate for nvme_admin_async_event cmd
+      completion
+    - scsi: ipr: Fix missing/incorrect resource cleanup in error case
+    - scsi: pmcraid: Fix missing resource cleanup in error case
+    - ALSA: hda/realtek - Add HW8326 support
+    - virtio-mmio: fix missing put_device() when vm_cmdline_parent registration
+      failed
+    - nfc: nfcmrvl: Fix memory leak in nfcmrvl_play_deferred
+    - ipv6: Fix signed integer overflow in l2tp_ip6_sendmsg
+    - net: ethernet: mtk_eth_soc: fix misuse of mem alloc interface
+      netdev[napi]_alloc_frag
+    - random: credit cpu and bootloader seeds by default
+    - pNFS: Don't keep retrying if the server replied NFS4ERR_LAYOUTUNAVAILABLE
+    - clocksource: hyper-v: unexport __init-annotated hv_init_clocksource()
+    - i40e: Fix adding ADQ filter to TC0
+    - i40e: Fix calculating the number of queue pairs
+    - i40e: Fix call trace in setup_tx_descriptors
+    - tty: goldfish: Fix free_irq() on remove
+    - misc: atmel-ssc: Fix IRQ check in ssc_probe
+    - mlxsw: spectrum_cnt: Reorder counter pools
+    - net: bgmac: Fix an erroneous kfree() in bgmac_remove()
+    - arm64: ftrace: fix branch range checks
+    - certs/blacklist_hashes.c: fix const confusion in certs blacklist
+    - faddr2line: Fix overlapping text section failures, the sequel
+    - irqchip/gic/realview: Fix refcount leak in realview_gic_of_init
+    - irqchip/gic-v3: Fix error handling in gic_populate_ppi_partitions
+    - irqchip/gic-v3: Fix refcount leak in gic_populate_ppi_partitions
+    - i2c: designware: Use standard optional ref clock implementation
+    - comedi: vmk80xx: fix expression for tx buffer size
+    - USB: serial: option: add support for Cinterion MV31 with new baseline
+    - USB: serial: io_ti: add Agilent E5805A support
+    - usb: dwc2: Fix memory leak in dwc2_hcd_init
+    - usb: gadget: lpc32xx_udc: Fix refcount leak in lpc32xx_udc_probe
+    - serial: 8250: Store to lsr_save_flags after lsr read
+    - dm mirror log: round up region bitmap size to BITS_PER_LONG
+    - ext4: fix bug_on ext4_mb_use_inode_pa
+    - ext4: make variable "count" signed
+    - ext4: add reserved GDT blocks check
+    - ALSA: hda/realtek: fix right sounds and mute/micmute LEDs for HP machine
+    - virtio-pci: Remove wrong address verification in vp_del_vqs()
+    - net/sched: act_police: more accurate MTU policing
+    - net: openvswitch: fix leak of nested actions
+    - arm64: kprobes: Use BRK instead of single-step when executing instructions
+      out-of-line
+    - RISC-V: fix barrier() use in <vdso/processor.h>
+    - riscv: Less inefficient gcc tishift helpers (and export their symbols)
+    - powerpc/mm: Switch obsolete dssall to .long
+    - Linux 5.4.200
+
+  * Focal update: v5.4.199 upstream stable release (LP: #1983150)
+    - Linux 5.4.199
+
+  * Focal update: v5.4.198 upstream stable release (LP: #1982409)
+    - binfmt_flat: do not stop relocating GOT entries prematurely on riscv
+    - ALSA: hda/realtek - Fix microphone noise on ASUS TUF B550M-PLUS
+    - USB: serial: option: add Quectel BG95 modem
+    - USB: new quirk for Dell Gen 2 devices
+    - perf/x86/intel: Fix event constraints for ICL
+    - ptrace/um: Replace PT_DTRACE with TIF_SINGLESTEP
+    - ptrace/xtensa: Replace PT_SINGLESTEP with TIF_SINGLESTEP
+    - ptrace: Reimplement PTRACE_KILL by always sending SIGKILL
+    - btrfs: add "0x" prefix for unsupported optional features
+    - btrfs: repair super block num_devices automatically
+    - drm/virtio: fix NULL pointer dereference in virtio_gpu_conn_get_modes
+    - mwifiex: add mutex lock for call in mwifiex_dfs_chan_sw_work_queue
+    - b43legacy: Fix assigning negative value to unsigned variable
+    - b43: Fix assigning negative value to unsigned variable
+    - ipw2x00: Fix potential NULL dereference in libipw_xmit()
+    - ipv6: fix locking issues with loops over idev->addr_list
+    - fbcon: Consistently protect deferred_takeover with console_lock()
+    - ACPICA: Avoid cache flush inside virtual machines
+    - drm/komeda: return early if drm_universal_plane_init() fails.
+    - ALSA: jack: Access input_dev under mutex
+    - spi: spi-rspi: Remove setting {src,dst}_{addr,addr_width} based on DMA
+      direction
+    - tools/power turbostat: fix ICX DRAM power numbers
+    - drm/amd/pm: fix double free in si_parse_power_table()
+    - ath9k: fix QCA9561 PA bias level
+    - media: venus: hfi: avoid null dereference in deinit
+    - media: pci: cx23885: Fix the error handling in cx23885_initdev()
+    - media: cx25821: Fix the warning when removing the module
+    - md/bitmap: don't set sb values if can't pass sanity check
+    - mmc: jz4740: Apply DMA engine limits to maximum segment size
+    - scsi: megaraid: Fix error check return value of register_chrdev()
+    - drm/plane: Move range check for format_count earlier
+    - drm/amd/pm: fix the compile warning
+    - arm64: compat: Do not treat syscall number as ESR_ELx for a bad syscall
+    - drm: msm: fix error check return value of irq_of_parse_and_map()
+    - ipv6: Don't send rs packets to the interface of ARPHRD_TUNNEL
+    - net/mlx5: fs, delete the FTE when there are no rules attached to it
+    - ASoC: dapm: Don't fold register value changes into notifications
+    - mlxsw: spectrum_dcb: Do not warn about priority changes
+    - drm/amdgpu/ucode: Remove firmware load type check in amdgpu_ucode_free_bo
+    - HID: bigben: fix slab-out-of-bounds Write in bigben_probe
+    - ASoC: tscs454: Add endianness flag in snd_soc_component_driver
+    - s390/preempt: disable __preempt_count_add() optimization for
+      PROFILE_ALL_BRANCHES
+    - spi: stm32-qspi: Fix wait_cmd timeout in APM mode
+    - dma-debug: change allocation mode from GFP_NOWAIT to GFP_ATIOMIC
+    - ACPI: PM: Block ASUS B1400CEAE from suspend to idle by default
+    - ipmi:ssif: Check for NULL msg when handling events and messages
+    - ipmi: Fix pr_fmt to avoid compilation issues
+    - rtlwifi: Use pr_warn instead of WARN_ONCE
+    - media: coda: limit frame interval enumeration to supported encoder frame
+      sizes
+    - media: cec-adap.c: fix is_configuring state
+    - openrisc: start CPU timer early in boot
+    - nvme-pci: fix a NULL pointer dereference in nvme_alloc_admin_tags
+    - ASoC: rt5645: Fix errorenous cleanup order
+    - nbd: Fix hung on disconnect request if socket is closed before
+    - net: phy: micrel: Allow probing without .driver_data
+    - media: exynos4-is: Fix compile warning
+    - ASoC: max98357a: remove dependency on GPIOLIB
+    - rxrpc: Return an error to sendmsg if call failed
+    - eth: tg3: silence the GCC 12 array-bounds warning
+    - selftests/bpf: fix btf_dump/btf_dump due to recent clang change
+    - IB/rdmavt: add missing locks in rvt_ruc_loopback
+    - ARM: dts: ox820: align interrupt controller node name with dtschema
+    - PM / devfreq: rk3399_dmc: Disable edev on remove()
+    - fs: jfs: fix possible NULL pointer dereference in dbFree()
+    - ARM: OMAP1: clock: Fix UART rate reporting algorithm
+    - powerpc/fadump: Fix fadump to work with a different endian capture kernel
+    - fat: add ratelimit to fat*_ent_bread()
+    - ARM: versatile: Add missing of_node_put in dcscb_init
+    - ARM: dts: exynos: add atmel,24c128 fallback to Samsung EEPROM
+    - ARM: hisi: Add missing of_node_put after of_find_compatible_node
+    - PCI: Avoid pci_dev_lock() AB/BA deadlock with sriov_numvfs_store()
+    - tracing: incorrect isolate_mote_t cast in mm_vmscan_lru_isolate
+    - powerpc/xics: fix refcount leak in icp_opal_init()
+    - powerpc/powernv: fix missing of_node_put in uv_init()
+    - macintosh/via-pmu: Fix build failure when CONFIG_INPUT is disabled
+    - powerpc/iommu: Add missing of_node_put in iommu_init_early_dart
+    - RDMA/hfi1: Prevent panic when SDMA is disabled
+    - drm: fix EDID struct for old ARM OABI format
+    - ath9k: fix ar9003_get_eepmisc
+    - drm/edid: fix invalid EDID extension block filtering
+    - drm/bridge: adv7511: clean up CEC adapter when probe fails
+    - ASoC: mediatek: Fix error handling in mt8173_max98090_dev_probe
+    - ASoC: mediatek: Fix missing of_node_put in mt2701_wm8960_machine_probe
+    - x86/delay: Fix the wrong asm constraint in delay_loop()
+    - drm/mediatek: Fix mtk_cec_mask()
+    - drm/vc4: txp: Don't set TXP_VSTART_AT_EOF
+    - drm/vc4: txp: Force alpha to be 0xff if it's disabled
+    - bpf: Fix excessive memory allocation in stack_map_alloc()
+    - nl80211: show SSID for P2P_GO interfaces
+    - drm/komeda: Fix an undefined behavior bug in komeda_plane_add()
+    - drm: mali-dp: potential dereference of null pointer
+    - spi: spi-ti-qspi: Fix return value handling of wait_for_completion_timeout
+    - NFC: NULL out the dev->rfkill to prevent UAF
+    - efi: Add missing prototype for efi_capsule_setup_info
+    - drbd: fix duplicate array initializer
+    - HID: hid-led: fix maximum brightness for Dream Cheeky
+    - HID: elan: Fix potential double free in elan_input_configured
+    - drm/bridge: Fix error handling in analogix_dp_probe
+    - sched/fair: Fix cfs_rq_clock_pelt() for throttled cfs_rq
+    - spi: img-spfi: Fix pm_runtime_get_sync() error checking
+    - cpufreq: Fix possible race in cpufreq online error path
+    - ath9k_htc: fix potential out of bounds access with invalid
+      rxstatus->rs_keyix
+    - inotify: show inotify mask flags in proc fdinfo
+    - fsnotify: fix wrong lockdep annotations
+    - of: overlay: do not break notify on NOTIFY_{OK|STOP}
+    - scsi: ufs: core: Exclude UECxx from SFR dump list
+    - x86/pm: Fix false positive kmemleak report in msr_build_context()
+    - x86/speculation: Add missing prototype for unpriv_ebpf_notify()
+    - ASoC: rk3328: fix disabling mclk on pclk probe failure
+    - perf tools: Add missing headers needed by util/data.h
+    - drm/msm/disp/dpu1: set vbif hw config to NULL to avoid use after memory free
+      during pm runtime resume
+    - drm/msm/dsi: fix error checks and return values for DSI xmit functions
+    - drm/msm/hdmi: check return value after calling
+      platform_get_resource_byname()
+    - drm/msm/hdmi: fix error check return value of irq_of_parse_and_map()
+    - drm/rockchip: vop: fix possible null-ptr-deref in vop_bind()
+    - virtio_blk: fix the discard_granularity and discard_alignment queue limits
+    - x86: Fix return value of __setup handlers
+    - irqchip/exiu: Fix acknowledgment of edge triggered interrupts
+    - irqchip/aspeed-i2c-ic: Fix irq_of_parse_and_map() return value
+    - x86/mm: Cleanup the control_va_addr_alignment() __setup handler
+    - regulator: core: Fix enable_count imbalance with EXCLUSIVE_GET
+    - drm/msm/mdp5: Return error code in mdp5_pipe_release when deadlock is
+      detected
+    - drm/msm/mdp5: Return error code in mdp5_mixer_release when deadlock is
+      detected
+    - drm/msm: return an error pointer in msm_gem_prime_get_sg_table()
+    - media: uvcvideo: Fix missing check to determine if element is found in list
+    - iomap: iomap_write_failed fix
+    - Revert "cpufreq: Fix possible race in cpufreq online error path"
+    - perf/amd/ibs: Use interrupt regs ip for stack unwinding
+    - ASoC: fsl: Fix refcount leak in imx_sgtl5000_probe
+    - ASoC: mxs-saif: Fix refcount leak in mxs_saif_probe
+    - regulator: pfuze100: Fix refcount leak in pfuze_parse_regulators_dt
+    - scripts/faddr2line: Fix overlapping text section failures
+    - media: aspeed: Fix an error handling path in aspeed_video_probe()
+    - media: st-delta: Fix PM disable depth imbalance in delta_probe
+    - media: exynos4-is: Change clk_disable to clk_disable_unprepare
+    - media: pvrusb2: fix array-index-out-of-bounds in pvr2_i2c_core_init
+    - media: vsp1: Fix offset calculation for plane cropping
+    - Bluetooth: fix dangling sco_conn and use-after-free in sco_sock_timeout
+    - m68k: math-emu: Fix dependencies of math emulation support
+    - sctp: read sk->sk_bound_dev_if once in sctp_rcv()
+    - media: ov7670: remove ov7670_power_off from ov7670_remove
+    - ext4: reject the 'commit' option on ext2 filesystems
+    - drm/msm/a6xx: Fix refcount leak in a6xx_gpu_init
+    - drm: msm: fix possible memory leak in mdp5_crtc_cursor_set()
+    - thermal/drivers/broadcom: Fix potential NULL dereference in sr_thermal_probe
+    - ASoC: wm2000: fix missing clk_disable_unprepare() on error in
+      wm2000_anc_transition()
+    - NFC: hci: fix sleep in atomic context bugs in nfc_hci_hcp_message_tx
+    - rxrpc: Fix listen() setting the bar too high for the prealloc rings
+    - rxrpc: Don't try to resend the request if we're receiving the reply
+    - rxrpc: Fix overlapping ACK accounting
+    - rxrpc: Don't let ack.previousPacket regress
+    - rxrpc: Fix decision on when to generate an IDLE ACK
+    - net/smc: postpone sk_refcnt increment in connect()
+    - arm64: dts: rockchip: Move drive-impedance-ohm to emmc phy on rk3399
+    - ARM: dts: suniv: F1C100: fix watchdog compatible
+    - soc: qcom: smp2p: Fix missing of_node_put() in smp2p_parse_ipc
+    - soc: qcom: smsm: Fix missing of_node_put() in smsm_parse_ipc
+    - PCI: cadence: Fix find_first_zero_bit() limit
+    - PCI: rockchip: Fix find_first_zero_bit() limit
+    - KVM: nVMX: Leave most VM-Exit info fields unmodified on failed VM-Entry
+    - can: xilinx_can: mark bit timing constants as const
+    - ARM: dts: bcm2835-rpi-zero-w: Fix GPIO line name for Wifi/BT
+    - ARM: dts: bcm2837-rpi-cm3-io3: Fix GPIO line names for SMPS I2C
+    - ARM: dts: bcm2837-rpi-3-b-plus: Fix GPIO line name of power LED
+    - ARM: dts: bcm2835-rpi-b: Fix GPIO line names
+    - misc: ocxl: fix possible double free in ocxl_file_register_afu
+    - crypto: marvell/cesa - ECB does not IV
+    - arm: mediatek: select arch timer for mt7629
+    - powerpc/fadump: fix PT_LOAD segment for boot memory area
+    - mfd: ipaq-micro: Fix error check return value of platform_get_irq()
+    - scsi: fcoe: Fix Wstringop-overflow warnings in fcoe_wwn_from_mac()
+    - firmware: arm_scmi: Fix list protocols enumeration in the base protocol
+    - nvdimm: Allow overwrite in the presence of disabled dimms
+    - pinctrl: mvebu: Fix irq_of_parse_and_map() return value
+    - drivers/base/node.c: fix compaction sysfs file leak
+    - dax: fix cache flush on PMD-mapped pages
+    - powerpc/8xx: export 'cpm_setbrg' for modules
+    - powerpc/idle: Fix return value of __setup() handler
+    - powerpc/4xx/cpm: Fix return value of __setup() handler
+    - proc: fix dentry/inode overinstantiating under /proc/${pid}/net
+    - ipc/mqueue: use get_tree_nodev() in mqueue_get_tree()
+    - PCI: imx6: Fix PERST# start-up sequence
+    - tty: fix deadlock caused by calling printk() under tty_port->lock
+    - crypto: cryptd - Protect per-CPU resource by disabling BH.
+    - Input: sparcspkr - fix refcount leak in bbc_beep_probe
+    - powerpc/64: Only WARN if __pa()/__va() called with bad addresses
+    - powerpc/perf: Fix the threshold compare group constraint for power9
+    - macintosh: via-pmu and via-cuda need RTC_LIB
+    - powerpc/fsl_rio: Fix refcount leak in fsl_rio_setup
+    - mfd: davinci_voicecodec: Fix possible null-ptr-deref davinci_vc_probe()
+    - mailbox: forward the hrtimer if not queued and under a lock
+    - RDMA/hfi1: Prevent use of lock before it is initialized
+    - Input: stmfts - do not leave device disabled in stmfts_input_open
+    - f2fs: fix dereference of stale list iterator after loop body
+    - iommu/mediatek: Add list_del in mtk_iommu_remove
+    - i2c: at91: use dma safe buffers
+    - i2c: at91: Initialize dma_buf in at91_twi_xfer()
+    - NFS: Do not report EINTR/ERESTARTSYS as mapping errors
+    - NFS: Do not report flush errors in nfs_write_end()
+    - NFS: Don't report errors from nfs_pageio_complete() more than once
+    - NFSv4/pNFS: Do not fail I/O when we fail to allocate the pNFS layout
+    - video: fbdev: clcdfb: Fix refcount leak in clcdfb_of_vram_setup
+    - dmaengine: stm32-mdma: remove GISR1 register
+    - iommu/amd: Increase timeout waiting for GA log enablement
+    - perf c2c: Use stdio interface if slang is not supported
+    - perf jevents: Fix event syntax error caused by ExtSel
+    - f2fs: fix to avoid f2fs_bug_on() in dec_valid_node_count()
+    - f2fs: fix to do sanity check on block address in f2fs_do_zero_range()
+    - f2fs: fix to clear dirty inode in f2fs_evict_inode()
+    - f2fs: fix deadloop in foreground GC
+    - f2fs: don't need inode lock for system hidden quota
+    - f2fs: fix fallocate to use file_modified to update permissions consistently
+    - wifi: mac80211: fix use-after-free in chanctx code
+    - iwlwifi: mvm: fix assert 1F04 upon reconfig
+    - fs-writeback: writeback_sb_inodes：Recalculate 'wrote' according skipped
+      pages
+    - efi: Do not import certificates from UEFI Secure Boot for T2 Macs
+    - bfq: Split shared queues on move between cgroups
+    - bfq: Update cgroup information before merging bio
+    - bfq: Track whether bfq_group is still online
+    - ext4: fix use-after-free in ext4_rename_dir_prepare
+    - ext4: fix warning in ext4_handle_inode_extension
+    - ext4: fix bug_on in ext4_writepages
+    - ext4: verify dir block before splitting it
+    - ext4: avoid cycles in directory h-tree
+    - ACPI: property: Release subnode properties with data nodes
+    - tracing: Fix potential double free in create_var_ref()
+    - PCI/PM: Fix bridge_d3_blacklist[] Elo i2 overwrite of Gigabyte X299
+    - PCI: qcom: Fix runtime PM imbalance on probe errors
+    - PCI: qcom: Fix unbalanced PHY init on probe errors
+    - mm, compaction: fast_find_migrateblock() should return pfn in the target
+      zone
+    - dlm: fix plock invalid read
+    - dlm: fix missing lkb refcount handling
+    - ocfs2: dlmfs: fix error handling of user_dlm_destroy_lock
+    - scsi: dc395x: Fix a missing check on list iterator
+    - scsi: ufs: qcom: Add a readl() to make sure ref_clk gets enabled
+    - drm/amdgpu/cs: make commands with 0 chunks illegal behaviour.
+    - drm/etnaviv: check for reaped mapping in etnaviv_iommu_unmap_gem
+    - drm/nouveau/clk: Fix an incorrect NULL check on list iterator
+    - drm/bridge: analogix_dp: Grab runtime PM reference for DP-AUX
+    - md: fix an incorrect NULL check in does_sb_need_changing
+    - md: fix an incorrect NULL check in md_reload_sb
+    - mtd: cfi_cmdset_0002: Move and rename
+      chip_check/chip_ready/chip_good_for_write
+    - media: coda: Fix reported H264 profile
+    - media: coda: Add more H264 levels for CODA960
+    - Kconfig: Add option for asm goto w/ tied outputs to workaround clang-13 bug
+    - RDMA/hfi1: Fix potential integer multiplication overflow errors
+    - irqchip/armada-370-xp: Do not touch Performance Counter Overflow on A375,
+      A38x, A39x
+    - irqchip: irq-xtensa-mx: fix initial IRQ affinity
+    - mac80211: upgrade passive scan to active scan on DFS channels after beacon
+      rx
+    - um: chan_user: Fix winch_tramp() return value
+    - um: Fix out-of-bounds read in LDT setup
+    - iommu/msm: Fix an incorrect NULL check on list iterator
+    - nodemask.h: fix compilation error with GCC12
+    - hugetlb: fix huge_pmd_unshare address update
+    - rtl818x: Prevent using not initialized queues
+    - ASoC: rt5514: Fix event generation for "DSP Voice Wake Up" control
+    - carl9170: tx: fix an incorrect use of list iterator
+    - serial: pch: don't overwrite xmit->buf[0] by x_char
+    - tilcdc: tilcdc_external: fix an incorrect NULL check on list iterator
+    - gma500: fix an incorrect NULL check on list iterator
+    - arm64: dts: qcom: ipq8074: fix the sleep clock frequency
+    - phy: qcom-qmp: fix struct clk leak on probe errors
+    - ARM: pxa: maybe fix gpio lookup tables
+    - docs/conf.py: Cope with removal of language=None in Sphinx 5.0.0
+    - dt-bindings: gpio: altera: correct interrupt-cells
+    - blk-iolatency: Fix inflight count imbalances and IO hangs on offline
+    - phy: qcom-qmp: fix reset-controller leak on probe errors
+    - Kconfig: add config option for asm goto w/ outputs
+    - RDMA/rxe: Generate a completion for unsupported/invalid opcode
+    - MIPS: IP27: Remove incorrect `cpu_has_fpu' override
+    - bfq: Avoid merging queues with different parents
+    - bfq: Drop pointless unlock-lock pair
+    - bfq: Remove pointless bfq_init_rq() calls
+    - bfq: Get rid of __bio_blkcg() usage
+    - bfq: Make sure bfqg for which we are queueing requests is online
+    - block: fix bio_clone_blkg_association() to associate with proper blkcg_gq
+    - md: bcache: check the return value of kzalloc() in detached_dev_do_request()
+    - pcmcia: db1xxx_ss: restrict to MIPS_DB1XXX boards
+    - staging: greybus: codecs: fix type confusion of list iterator variable
+    - iio: adc: ad7124: Remove shift from scan_type
+    - tty: goldfish: Use tty_port_destroy() to destroy port
+    - tty: serial: owl: Fix missing clk_disable_unprepare() in owl_uart_probe
+    - tty: serial: fsl_lpuart: fix potential bug when using both of_alias_get_id
+      and ida_simple_get
+    - usb: usbip: fix a refcount leak in stub_probe()
+    - usb: usbip: add missing device lock on tweak configuration cmd
+    - USB: storage: karma: fix rio_karma_init return
+    - usb: musb: Fix missing of_node_put() in omap2430_probe
+    - staging: fieldbus: Fix the error handling path in
+      anybuss_host_common_probe()
+    - pwm: lp3943: Fix duty calculation in case period was clamped
+    - rpmsg: qcom_smd: Fix irq_of_parse_and_map() return value
+    - usb: dwc3: pci: Fix pm_runtime_get_sync() error checking
+    - firmware: stratix10-svc: fix a missing check on list iterator
+    - iio: adc: stmpe-adc: Fix wait_for_completion_timeout return value check
+    - iio: adc: sc27xx: fix read big scale voltage not right
+    - iio: adc: sc27xx: Fine tune the scale calibration values
+    - rpmsg: qcom_smd: Fix returning 0 if irq_of_parse_and_map() fails
+    - phy: qcom-qmp: fix pipe-clock imbalance on power-on failure
+    - serial: sifive: Report actual baud base rather than fixed 115200
+    - coresight: cpu-debug: Replace mutex with mutex_trylock on panic notifier
+    - soc: rockchip: Fix refcount leak in rockchip_grf_init
+    - clocksource/drivers/riscv: Events are stopped during CPU suspend
+    - rtc: mt6397: check return value after calling platform_get_resource()
+    - serial: meson: acquire port->lock in startup()
+    - serial: 8250_fintek: Check SER_RS485_RTS_* only with RS485
+    - serial: digicolor-usart: Don't allow CS5-6
+    - serial: rda-uart: Don't allow CS5-6
+    - serial: txx9: Don't allow CS5-6
+    - serial: sh-sci: Don't allow CS5-6
+    - serial: sifive: Sanitize CSIZE and c_iflag
+    - serial: st-asc: Sanitize CSIZE and correct PARENB for CS7
+    - serial: stm32-usart: Correct CSIZE, bits, and parity
+    - firmware: dmi-sysfs: Fix memory leak in dmi_sysfs_register_handle
+    - bus: ti-sysc: Fix warnings for unbind for serial
+    - driver: base: fix UAF when driver_attach failed
+    - driver core: fix deadlock in __device_attach
+    - watchdog: ts4800_wdt: Fix refcount leak in ts4800_wdt_probe
+    - ASoC: fsl_sai: Fix FSL_SAI_xDR/xFR definition
+    - clocksource/drivers/oxnas-rps: Fix irq_of_parse_and_map() return value
+    - s390/crypto: fix scatterwalk_unmap() callers in AES-GCM
+    - net: sched: fixed barrier to prevent skbuff sticking in qdisc backlog
+    - net: ethernet: mtk_eth_soc: out of bounds read in mtk_hwlro_get_fdir_entry()
+    - net: dsa: mv88e6xxx: Fix refcount leak in mv88e6xxx_mdios_register
+    - modpost: fix removing numeric suffixes
+    - jffs2: fix memory leak in jffs2_do_fill_super
+    - ubi: ubi_create_volume: Fix use-after-free when volume creation failed
+    - nfp: only report pause frame configuration for physical device
+    - net/mlx5: Don't use already freed action pointer
+    - net/mlx5e: Update netdev features after changing XDP state
+    - net: sched: add barrier to fix packet stuck problem for lockless qdisc
+    - tcp: tcp_rtx_synack() can be called from process context
+    - afs: Fix infinite loop found by xfstest generic/676
+    - tipc: check attribute length for bearer name
+    - perf c2c: Fix sorting in percent_rmt_hitm_cmp()
+    - mips: cpc: Fix refcount leak in mips_cpc_default_phys_base
+    - tracing: Fix sleeping function called from invalid context on RT kernel
+    - tracing: Avoid adding tracer option before update_tracer_options
+    - f2fs: remove WARN_ON in f2fs_is_valid_blkaddr
+    - i2c: cadence: Increase timeout per message if necessary
+    - m68knommu: set ZERO_PAGE() to the allocated zeroed page
+    - m68knommu: fix undefined reference to `_init_sp'
+    - dmaengine: zynqmp_dma: In struct zynqmp_dma_chan fix desc_size data type
+    - NFSv4: Don't hold the layoutget locks across multiple RPC calls
+    - video: fbdev: pxa3xx-gcu: release the resources correctly in
+      pxa3xx_gcu_probe/remove()
+    - xprtrdma: treat all calls not a bcall when bc_serv is NULL
+    - netfilter: nat: really support inet nat without l3 address
+    - ata: pata_octeon_cf: Fix refcount leak in octeon_cf_probe
+    - netfilter: nf_tables: memleak flow rule from commit path
+    - xen: unexport __init-annotated xen_xlate_map_ballooned_pages()
+    - af_unix: Fix a data-race in unix_dgram_peer_wake_me().
+    - bpf, arm64: Clear prog->jited_len along prog->jited
+    - net: dsa: lantiq_gswip: Fix refcount leak in gswip_gphy_fw_list
+    - net/mlx4_en: Fix wrong return value on ioctl EEPROM query failure
+    - SUNRPC: Fix the calculation of xdr->end in xdr_get_next_encode_buffer()
+    - net: mdio: unexport __init-annotated mdio_bus_init()
+    - net: xfrm: unexport __init-annotated xfrm4_protocol_init()
+    - net: ipv6: unexport __init-annotated seg6_hmac_init()
+    - net/mlx5: Rearm the FW tracer after each tracer event
+    - net/mlx5: fs, fail conflicting actions
+    - ip_gre: test csum_start instead of transport header
+    - net: altera: Fix refcount leak in altera_tse_mdio_create
+    - drm: imx: fix compiler warning with gcc-12
+    - iio: dummy: iio_simple_dummy: check the return value of kstrdup()
+    - iio: st_sensors: Add a local lock for protecting odr
+    - lkdtm/usercopy: Expand size of "out of frame" object
+    - tty: synclink_gt: Fix null-pointer-dereference in slgt_clean()
+    - tty: Fix a possible resource leak in icom_probe
+    - drivers: staging: rtl8192u: Fix deadlock in ieee80211_beacons_stop()
+    - drivers: staging: rtl8192e: Fix deadlock in rtllib_beacons_stop()
+    - USB: host: isp116x: check return value after calling platform_get_resource()
+    - drivers: tty: serial: Fix deadlock in sa1100_set_termios()
+    - drivers: usb: host: Fix deadlock in oxu_bus_suspend()
+    - USB: hcd-pci: Fully suspend across freeze/thaw cycle
+    - usb: dwc2: gadget: don't reset gadget's driver->bus
+    - misc: rtsx: set NULL intfdata when probe fails
+    - extcon: Modify extcon device to be created after driver data is set
+    - clocksource/drivers/sp804: Avoid error on multiple instances
+    - staging: rtl8712: fix uninit-value in usb_read8() and friends
+    - staging: rtl8712: fix uninit-value in r871xu_drv_init()
+    - serial: msm_serial: disable interrupts in __msm_console_write()
+    - kernfs: Separate kernfs_pr_cont_buf and rename_lock.
+    - watchdog: wdat_wdt: Stop watchdog when rebooting the system
+    - md: protect md_unregister_thread from reentrancy
+    - scsi: myrb: Fix up null pointer access on myrb_cleanup()
+    - ceph: allow ceph.dir.rctime xattr to be updatable
+    - drm/radeon: fix a possible null pointer dereference
+    - modpost: fix undefined behavior of is_arm_mapping_symbol()
+    - x86/cpu: Elide KCSAN for cpu_has() and friends
+    - nbd: call genl_unregister_family() first in nbd_cleanup()
+    - nbd: fix race between nbd_alloc_config() and module removal
+    - cifs: version operations for smb20 unneeded when legacy support disabled
+    - nodemask: Fix return values to be unsigned
+    - vringh: Fix loop descriptors check in the indirect cases
+    - scripts/gdb: change kernel config dumping method
+    - ALSA: hda/conexant - Fix loopback issue with CX20632
+    - cifs: return errors during session setup during reconnects
+    - ata: libata-transport: fix {dma|pio|xfer}_mode sysfs files
+    - mmc: block: Fix CQE recovery reset success
+    - nfc: st21nfca: fix incorrect validating logic in EVT_TRANSACTION
+    - nfc: st21nfca: fix memory leaks in EVT_TRANSACTION handling
+    - ixgbe: fix bcast packets Rx on VF after promisc removal
+    - ixgbe: fix unexpected VLAN Rx in promisc mode on VF
+    - Input: bcm5974 - set missing URB_NO_TRANSFER_DMA_MAP urb flag
+    - powerpc/32: Fix overread/overwrite of thread_struct via ptrace
+    - md/raid0: Ignore RAID0 layout if the second zone has only one device
+    - mtd: cfi_cmdset_0002: Use chip_ready() for write on S29GL064N
+    - tcp: fix tcp_mtup_probe_success vs wrong snd_cwnd
+    - Linux 5.4.198
+
+  * Focal update: v5.4.197 upstream stable release (LP: #1981758)
+    - x86/pci/xen: Disable PCI/MSI[-X] masking for XEN_HVM guests
+    - staging: rtl8723bs: prevent ->Ssid overflow in rtw_wx_set_scan()
+    - Input: goodix - fix spurious key release events
+    - tcp: change source port randomizarion at connect() time
+    - secure_seq: use the 64 bits of the siphash for port offset calculation
+    - media: vim2m: Register video device after setting up internals
+    - media: vim2m: initialize the media device earlier
+    - ACPI: sysfs: Make sparse happy about address space in use
+    - ACPI: sysfs: Fix BERT error region memory mapping
+    - pinctrl: sunxi: fix f1c100s uart2 function
+    - net: af_key: check encryption module availability consistency
+    - net: ftgmac100: Disable hardware checksum on AST2600
+    - i2c: ismt: Provide a DMA buffer for Interrupt Cause Logging
+    - drivers: i2c: thunderx: Allow driver to work with ACPI defined TWSI
+      controllers
+    - assoc_array: Fix BUG_ON during garbage collect
+    - cfg80211: set custom regdomain after wiphy registration
+    - drm/i915: Fix -Wstringop-overflow warning in call to intel_read_wm_latency()
+    - exec: Force single empty string when argv is empty
+    - netfilter: conntrack: re-fetch conntrack after insertion
+    - crypto: ecrdsa - Fix incorrect use of vli_cmp
+    - zsmalloc: fix races between asynchronous zspage free and page migration
+    - dm integrity: fix error code in dm_integrity_ctr()
+    - dm crypt: make printing of the key constant-time
+    - dm stats: add cond_resched when looping over entries
+    - dm verity: set DM_TARGET_IMMUTABLE feature flag
+    - raid5: introduce MD_BROKEN
+    - HID: multitouch: Add support for Google Whiskers Touchpad
+    - tpm: Fix buffer access in tpm2_get_tpm_pt()
+    - tpm: ibmvtpm: Correct the return value in tpm_ibmvtpm_probe()
+    - docs: submitting-patches: Fix crossref to 'The canonical patch format'
+    - NFS: Memory allocation failures are not server fatal errors
+    - NFSD: Fix possible sleep during nfsd4_release_lockowner()
+    - bpf: Enlarge offset check value to INT_MAX in bpf_skb_{load,store}_bytes
+    - Linux 5.4.197
+
+  * Focal update: v5.4.196 upstream stable release (LP: #1981111)
+    - x86/xen: Make the boot CPU idle task reliable
+    - x86/xen: Make the secondary CPU idle tasks reliable
+    - rtc: fix use-after-free on device removal
+    - um: Cleanup syscall_handler_t definition/cast, fix warning
+    - Input: add bounds checking to input_set_capability()
+    - Input: stmfts - fix reference leak in stmfts_input_open
+    - crypto: stm32 - fix reference leak in stm32_crc_remove
+    - crypto: x86/chacha20 - Avoid spurious jumps to other functions
+    - ALSA: hda/realtek: Enable headset mic on Lenovo P360
+    - nvme-multipath: fix hang when disk goes live over reconnect
+    - rtc: mc146818-lib: Fix the AltCentury for AMD platforms
+    - MIPS: lantiq: check the return value of kzalloc()
+    - drbd: remove usage of list iterator variable after loop
+    - platform/chrome: cros_ec_debugfs: detach log reader wq from devm
+    - ARM: 9191/1: arm/stacktrace, kasan: Silence KASAN warnings in unwind_frame()
+    - nilfs2: fix lockdep warnings in page operations for btree nodes
+    - nilfs2: fix lockdep warnings during disk space reclamation
+    - mmc: core: Specify timeouts for BKOPS and CACHE_FLUSH for eMMC
+    - mmc: block: Use generic_cmd6_time when modifying INAND_CMD38_ARG_EXT_CSD
+    - mmc: core: Default to generic_cmd6_time as timeout in __mmc_switch()
+    - SUNRPC: Clean up scheduling of autoclose
+    - SUNRPC: Prevent immediate close+reconnect
+    - SUNRPC: Don't call connect() more than once on a TCP socket
+    - ALSA: wavefront: Proper check of get_user() error
+    - perf: Fix sys_perf_event_open() race against self
+    - Fix double fget() in vhost_net_set_backend()
+    - PCI/PM: Avoid putting Elo i2 PCIe Ports in D3cold
+    - KVM: x86/mmu: Update number of zapped pages even if page list is stable
+    - crypto: qcom-rng - fix infinite loop on requests not multiple of WORD_SZ
+    - drm/dp/mst: fix a possible memory leak in fetch_monitor_name()
+    - dma-buf: fix use of DMA_BUF_SET_NAME_{A,B} in userspace
+    - ARM: dts: aspeed-g6: remove FWQSPID group in pinctrl dtsi
+    - ARM: dts: aspeed-g6: fix SPI1/SPI2 quad pin group
+    - net: macb: Increment rx bd head after allocating skb and buffer
+    - net/sched: act_pedit: sanitize shift argument before usage
+    - net: vmxnet3: fix possible use-after-free bugs in vmxnet3_rq_alloc_rx_buf()
+    - net: vmxnet3: fix possible NULL pointer dereference in vmxnet3_rq_cleanup()
+    - ice: fix possible under reporting of ethtool Tx and Rx statistics
+    - clk: at91: generated: consider range when calculating best rate
+    - net/qla3xxx: Fix a test in ql_reset_work()
+    - NFC: nci: fix sleep in atomic context bugs caused by nci_skb_alloc
+    - net/mlx5e: Properly block LRO when XDP is enabled
+    - ARM: 9196/1: spectre-bhb: enable for Cortex-A15
+    - ARM: 9197/1: spectre-bhb: fix loop8 sequence for Thumb2
+    - igb: skip phy status check where unavailable
+    - net: bridge: Clear offload_fwd_mark when passing frame up bridge interface.
+    - gpio: gpio-vf610: do not touch other bits when set the target bit
+    - gpio: mvebu/pwm: Refuse requests with inverted polarity
+    - perf bench numa: Address compiler error on s390
+    - scsi: qla2xxx: Fix missed DMA unmap for aborted commands
+    - mac80211: fix rx reordering with non explicit / psmp ack policy
+    - selftests: add ping test with ping_group_range tuned
+    - ethernet: tulip: fix missing pci_disable_device() on error in
+      tulip_init_one()
+    - net: stmmac: fix missing pci_disable_device() on error in stmmac_pci_probe()
+    - net: atlantic: verify hw_head_ lies within TX buffer ring
+    - Input: ili210x - fix reset timing
+    - block: return ELEVATOR_DISCARD_MERGE if possible
+    - net: stmmac: disable Split Header (SPH) for Intel platforms
+    - firmware_loader: use kernel credentials when reading firmware
+    - ARM: dts: imx7: Use audio_mclk_post_div instead audio_mclk_root_clk
+    - Reinstate some of "swiotlb: rework "fix info leak with DMA_FROM_DEVICE""
+    - x86/xen: fix booting 32-bit pv guest
+    - x86/xen: Mark cpu_bringup_and_idle() as dead_end_function
+    - i2c: mt7621: fix missing clk_disable_unprepare() on error in mtk_i2c_probe()
+    - afs: Fix afs_getattr() to refetch file status if callback break occurred
+    - Linux 5.4.196
+
+  * CVE-2022-36946
+    - netfilter: nf_queue: do not allow packet truncation below transport header
+      offset
+
+  * CVE-2021-33655
+    - fbcon: Disallow setting font bigger than screen size
+    - fbcon: Prevent that screen size is smaller than font size
+    - fbmem: Check virtual screen sizes in fb_set_var()
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Fri, 26 Aug 2022 11:39:48 +0200
+
+linux (5.4.0-125.141) focal; urgency=medium
+
+  * focal/linux: 5.4.0-125.141 -proposed tracker (LP: #1983947)
+
+  * nbd: requests can become stuck when disconnecting from server with qemu-nbd
+    (LP: #1896350)
+    - blk-mq: blk-mq: provide forced completion method
+    - blk-mq: move failure injection out of blk_mq_complete_request
+    - nbd: don't handle response without a corresponding request message
+    - nbd: make sure request completion won't concurrent
+    - nbd: don't clear 'NBD_CMD_INFLIGHT' flag if request is not completed
+    - nbd: fix io hung while disconnecting device
+
+  * CVE-2021-33656
+    - vt: drop old FONT ioctls
+
+  * CVE-2021-33061
+    - ixgbe: add the ability for the PF to disable VF link state
+    - ixgbe: add improvement for MDD response functionality
+    - ixgbevf: add disable link state
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Wed, 10 Aug 2022 10:17:28 +0200
+
+linux (5.4.0-124.140) focal; urgency=medium
+
+  * CVE-2022-2586
+    - SAUCE: netfilter: nf_tables: do not allow SET_ID to refer to another table
+    - SAUCE: netfilter: nf_tables: do not allow RULE_ID to refer to another chain
+
+  * CVE-2022-2588
+    - SAUCE: net_sched: cls_route: remove from list when handle is 0
+
+  * CVE-2022-34918
+    - netfilter: nf_tables: stricter validation of element data
+
+ -- Thadeu Lima de Souza Cascardo <cascardo@canonical.com>  Wed, 03 Aug 2022 22:48:34 -0300
+
+linux (5.4.0-123.139) focal; urgency=medium
+
+  * focal/linux: 5.4.0-123.139 -proposed tracker (LP: #1981284)
+
+  * Packaging resync (LP: #1786013)
+    - debian/dkms-versions -- update from kernel-versions (main/2022.07.11)
+
+  * Hairpin traffic does not work with centralized NAT gw (LP: #1967856)
+    - net: openvswitch: fix misuse of the cached connection on tuple changes
+
+  * [UBUNTU 20.04] Include patches to avoid self-detected stall with Secure
+    Execution (LP: #1979296)
+    - KVM: s390: pv: add macros for UVC CC values
+    - KVM: s390: pv: avoid stalls when making pages secure
+    - KVM: s390: pv: avoid stalls for kvm_s390_pv_init_vm
+
+  * Focal update: v5.4.195 upstream stable release (LP: #1980407)
+    - batman-adv: Don't skb_split skbuffs with frag_list
+    - hwmon: (tmp401) Add OF device ID table
+    - mac80211: Reset MBSSID parameters upon connection
+    - net: Fix features skip in for_each_netdev_feature()
+    - ipv4: drop dst in multicast routing path
+    - drm/nouveau: Fix a potential theorical leak in nouveau_get_backlight_name()
+    - netlink: do not reset transport header in netlink_recvmsg()
+    - mac80211_hwsim: call ieee80211_tx_prepare_skb under RCU protection
+    - dim: initialize all struct fields
+    - hwmon: (ltq-cputemp) restrict it to SOC_XWAY
+    - s390/ctcm: fix variable dereferenced before check
+    - s390/ctcm: fix potential memory leak
+    - s390/lcs: fix variable dereferenced before check
+    - net/sched: act_pedit: really ensure the skb is writable
+    - net/smc: non blocking recvmsg() return -EAGAIN when no data and
+      signal_pending
+    - net: sfc: ef10: fix memory leak in efx_ef10_mtd_probe()
+    - gfs2: Fix filesystem block deallocation for short writes
+    - hwmon: (f71882fg) Fix negative temperature
+    - ASoC: max98090: Reject invalid values in custom control put()
+    - ASoC: max98090: Generate notifications on changes for custom control
+    - ASoC: ops: Validate input values in snd_soc_put_volsw_range()
+    - s390: disable -Warray-bounds
+    - net: emaclite: Don't advertise 1000BASE-T and do auto negotiation
+    - tcp: resalt the secret every 10 seconds
+    - tty: n_gsm: fix mux activation issues in gsm_config()
+    - usb: cdc-wdm: fix reading stuck on device close
+    - usb: typec: tcpci: Don't skip cleanup in .remove() on error
+    - USB: serial: pl2303: add device id for HP LM930 Display
+    - USB: serial: qcserial: add support for Sierra Wireless EM7590
+    - USB: serial: option: add Fibocom L610 modem
+    - USB: serial: option: add Fibocom MA510 modem
+    - slimbus: qcom: Fix IRQ check in qcom_slim_probe
+    - serial: 8250_mtk: Fix UART_EFR register address
+    - serial: 8250_mtk: Fix register address for XON/XOFF character
+    - drm/nouveau/tegra: Stop using iommu_present()
+    - i40e: i40e_main: fix a missing check on list iterator
+    - cgroup/cpuset: Remove cpus_allowed/mems_allowed setup in cpuset_init_smp()
+    - drm/vmwgfx: Initialize drm_mode_fb_cmd2
+    - MIPS: fix build with gcc-12
+    - net: phy: Fix race condition on link status change
+    - arm[64]/memremap: don't abuse pfn_valid() to ensure presence of linear map
+    - ping: fix address binding wrt vrf
+    - tty/serial: digicolor: fix possible null-ptr-deref in digicolor_uart_probe()
+    - Linux 5.4.195
+
+  * Focal update: v5.4.194 upstream stable release (LP: #1980399)
+    - MIPS: Use address-of operator on section symbols
+    - block: drbd: drbd_nl: Make conversion to 'enum drbd_ret_code' explicit
+    - drm/amd/display/dc/gpio/gpio_service: Pass around correct dce_{version,
+      environment} types
+    - drm/i915: Cast remain to unsigned long in eb_relocate_vma
+    - nfp: bpf: silence bitwise vs. logical OR warning
+    - can: grcan: grcan_probe(): fix broken system id check for errata workaround
+      needs
+    - can: grcan: only use the NAPI poll budget for RX
+    - arm: remove CONFIG_ARCH_HAS_HOLES_MEMORYMODEL
+    - [Config] updateconfigs for ARCH_HAS_HOLES_MEMORYMODEL
+    - KVM: x86/pmu: Refactoring find_arch_event() to pmc_perf_hw_id()
+    - x86/asm: Allow to pass macros to __ASM_FORM()
+    - x86: xen: kvm: Gather the definition of emulate prefixes
+    - x86: xen: insn: Decode Xen and KVM emulate-prefix signature
+    - x86: kprobes: Prohibit probing on instruction which has emulate prefix
+    - KVM: x86/svm: Account for family 17h event renumberings in
+      amd_pmc_perf_hw_id
+    - Bluetooth: Fix the creation of hdev->name
+    - mm: fix missing cache flush for all tail pages of compound page
+    - mm: hugetlb: fix missing cache flush in copy_huge_page_from_user()
+    - mm: userfaultfd: fix missing cache flush in mcopy_atomic_pte() and
+      __mcopy_atomic()
+    - Linux 5.4.194
+
+  * Focal update: v5.4.193 upstream stable release (LP: #1979566)
+    - MIPS: Fix CP0 counter erratum detection for R4k CPUs
+    - parisc: Merge model and model name into one line in /proc/cpuinfo
+    - ALSA: fireworks: fix wrong return count shorter than expected by 4 bytes
+    - gpiolib: of: fix bounds check for 'gpio-reserved-ranges'
+    - Revert "SUNRPC: attempt AF_LOCAL connect on setup"
+    - firewire: fix potential uaf in outbound_phy_packet_callback()
+    - firewire: remove check of list iterator against head past the loop body
+    - firewire: core: extend card->lock in fw_core_handle_bus_reset
+    - ACPICA: Always create namespace nodes using acpi_ns_create_node()
+    - genirq: Synchronize interrupt thread startup
+    - ASoC: da7219: Fix change notifications for tone generator frequency
+    - ASoC: wm8958: Fix change notifications for DSP controls
+    - ASoC: meson: Fix event generation for G12A tohdmi mux
+    - s390/dasd: fix data corruption for ESE devices
+    - s390/dasd: prevent double format of tracks for ESE devices
+    - s390/dasd: Fix read for ESE with blksize < 4k
+    - s390/dasd: Fix read inconsistency for ESE DASD devices
+    - can: grcan: grcan_close(): fix deadlock
+    - can: grcan: use ofdev->dev when allocating DMA memory
+    - nfc: replace improper check device_is_registered() in netlink related
+      functions
+    - NFC: netlink: fix sleep in atomic bug when firmware download timeout
+    - hwmon: (adt7470) Fix warning on module removal
+    - ASoC: dmaengine: Restore NULL prepare_slave_config() callback
+    - RDMA/siw: Fix a condition race issue in MPA request processing
+    - net: ethernet: mediatek: add missing of_node_put() in mtk_sgmii_init()
+    - net: stmmac: dwmac-sun8i: add missing of_node_put() in
+      sun8i_dwmac_register_mdio_mux()
+    - net: emaclite: Add error handling for of_address_to_resource()
+    - selftests: mirror_gre_bridge_1q: Avoid changing PVID while interface is
+      operational
+    - bnxt_en: Fix possible bnxt_open() failure caused by wrong RFS flag
+    - smsc911x: allow using IRQ0
+    - btrfs: always log symlinks in full mode
+    - net: igmp: respect RCU rules in ip_mc_source() and ip_mc_msfilter()
+    - drm/amdkfd: Use drm_priv to pass VM from KFD to amdgpu
+    - NFSv4: Don't invalidate inode attributes on delegation return
+    - kvm: x86/cpuid: Only provide CPUID leaf 0xA if host has architectural PMU
+    - x86/kvm: Preserve BSP MSR_KVM_POLL_CONTROL across suspend/resume
+    - KVM: LAPIC: Enable timer posted-interrupt only when mwait/hlt is advertised
+    - net: ipv6: ensure we call ipv6_mc_down() at most once
+    - block-map: add __GFP_ZERO flag for alloc_page in function bio_copy_kern
+    - mm: fix unexpected zeroed page mapping with zram swap
+    - ALSA: pcm: Fix races among concurrent hw_params and hw_free calls
+    - ALSA: pcm: Fix races among concurrent read/write and buffer changes
+    - ALSA: pcm: Fix races among concurrent prepare and hw_params/hw_free calls
+    - ALSA: pcm: Fix races among concurrent prealloc proc writes
+    - ALSA: pcm: Fix potential AB/BA lock with buffer_mutex and mmap_lock
+    - tcp: make sure treq->af_specific is initialized
+    - dm: fix mempool NULL pointer race when completing IO
+    - dm: interlock pending dm_io and dm_wait_for_bios_completion
+    - PCI: aardvark: Clear all MSIs at setup
+    - PCI: aardvark: Fix reading MSI interrupt number
+    - mmc: rtsx: add 74 Clocks in power on flow
+    - Linux 5.4.193
+
+  * CVE-2022-1679
+    - SAUCE: ath9k: fix use-after-free in ath9k_hif_usb_rx_cb
+
+  * CVE-2022-28893
+    - SUNRPC: Ensure we flush any closed sockets before xs_xprt_free()
+    - SUNRPC: Don't leak sockets in xs_local_connect()
+
+  * CVE-2022-1734
+    - nfc: nfcmrvl: main: reorder destructive operations in
+      nfcmrvl_nci_unregister_dev to avoid bugs
+
+  * CVE-2022-1652
+    - floppy: use a statically allocated error counter
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Mon, 11 Jul 2022 16:54:06 +0200
+
+linux (5.4.0-122.138) focal; urgency=medium
+
+  * focal/linux: 5.4.0-122.138 -proposed tracker (LP: #1979489)
+
+  * Remove SAUCE patches from test_vxlan_under_vrf.sh in net of
+    ubuntu_kernel_selftests (LP: #1975691)
+    - Revert "UBUNTU: SAUCE: selftests: net: Don't fail test_vxlan_under_vrf on
+      xfail"
+    - Revert "UBUNTU: SAUCE: selftests: net: Make test for VXLAN underlay in non-
+      default VRF an expected failure"
+
+  * Enable Asus USB-BT500 Bluetooth dongle(0b05:190e) (LP: #1976613)
+    - Bluetooth: btusb: Add flag to define wideband speech capability
+    - Bluetooth: btrtl: Add support for RTL8761B
+    - Bluetooth: btusb: Add 0x0b05:0x190e Realtek 8761BU (ASUS BT500) device.
+
+  * [UBUNTU 20.04] rcu stalls with many storage key guests (LP: #1975582)
+    - s390/gmap: voluntarily schedule during key setting
+    - s390/mm: use non-quiescing sske for KVM switch to keyed guest
+
+  * Ubuntu 5.4.0-117.132-generic 5.4.189 has BUG: kernel NULL pointer
+    dereference, address: 0000000000000034 (LP: #1978719)
+    - mm: rmap: explicitly reset vma->anon_vma in unlink_anon_vmas()
+
+  * Focal update: upstream stable patchset v5.4.192 (LP: #1979014)
+    - floppy: disable FDRAWCMD by default
+    - [Config] updateconfigs for BLK_DEV_FD_RAWCMD
+    - hamradio: defer 6pack kfree after unregister_netdev
+    - hamradio: remove needs_free_netdev to avoid UAF
+    - lightnvm: disable the subsystem
+    - [Config] updateconfigs for NVM, NVM_PBLK
+    - usb: mtu3: fix USB 3.0 dual-role-switch from device to host
+    - USB: quirks: add a Realtek card reader
+    - USB: quirks: add STRING quirk for VCOM device
+    - USB: serial: whiteheat: fix heap overflow in WHITEHEAT_GET_DTR_RTS
+    - USB: serial: cp210x: add PIDs for Kamstrup USB Meter Reader
+    - USB: serial: option: add support for Cinterion MV32-WA/MV32-WB
+    - USB: serial: option: add Telit 0x1057, 0x1058, 0x1075 compositions
+    - xhci: stop polling roothubs after shutdown
+    - xhci: increase usb U3 -> U0 link resume timeout from 100ms to 500ms
+    - iio: dac: ad5592r: Fix the missing return value.
+    - iio: dac: ad5446: Fix read_raw not returning set value
+    - iio: magnetometer: ak8975: Fix the error handling in ak8975_power_on()
+    - usb: misc: fix improper handling of refcount in uss720_probe()
+    - usb: typec: ucsi: Fix role swapping
+    - usb: gadget: uvc: Fix crash when encoding data for usb request
+    - usb: gadget: configfs: clear deactivation flag in
+      configfs_composite_unbind()
+    - usb: dwc3: core: Fix tx/rx threshold settings
+    - usb: dwc3: gadget: Return proper request status
+    - serial: imx: fix overrun interrupts in DMA mode
+    - serial: 8250: Also set sticky MCR bits in console restoration
+    - serial: 8250: Correct the clock for EndRun PTP/1588 PCIe device
+    - arch_topology: Do not set llc_sibling if llc_id is invalid
+    - hex2bin: make the function hex_to_bin constant-time
+    - hex2bin: fix access beyond string end
+    - video: fbdev: udlfb: properly check endpoint type
+    - arm64: dts: meson: remove CPU opps below 1GHz for G12B boards
+    - arm64: dts: meson: remove CPU opps below 1GHz for SM1 boards
+    - mtd: rawnand: fix ecc parameters for mt7622
+    - USB: Fix xhci event ring dequeue pointer ERDP update issue
+    - ARM: dts: imx6qdl-apalis: Fix sgtl5000 detection issue
+    - phy: samsung: Fix missing of_node_put() in exynos_sata_phy_probe
+    - phy: samsung: exynos5250-sata: fix missing device put in probe error paths
+    - ARM: OMAP2+: Fix refcount leak in omap_gic_of_init
+    - phy: ti: omap-usb2: Fix error handling in omap_usb2_enable_clocks
+    - ARM: dts: at91: Map MCLK for wm8731 on at91sam9g20ek
+    - phy: mapphone-mdm6600: Fix PM error handling in phy_mdm6600_probe
+    - phy: ti: Add missing pm_runtime_disable() in serdes_am654_probe
+    - ARM: dts: Fix mmc order for omap3-gta04
+    - ARM: dts: am3517-evm: Fix misc pinmuxing
+    - ARM: dts: logicpd-som-lv: Fix wrong pinmuxing on OMAP35
+    - ipvs: correctly print the memory size of ip_vs_conn_tab
+    - mtd: rawnand: Fix return value check of wait_for_completion_timeout
+    - bpf, lwt: Fix crash when using bpf_skb_set_tunnel_key() from bpf_xmit lwt
+      hook
+    - tcp: md5: incorrect tcp_header_len for incoming connections
+    - tcp: ensure to use the most recently sent skb when filling the rate sample
+    - sctp: check asoc strreset_chunk in sctp_generate_reconf_event
+    - ARM: dts: imx6ull-colibri: fix vqmmc regulator
+    - arm64: dts: imx8mn-ddr4-evk: Describe the 32.768 kHz PMIC clock
+    - pinctrl: pistachio: fix use of irq_of_parse_and_map()
+    - cpufreq: fix memory leak in sun50i_cpufreq_nvmem_probe
+    - net: hns3: add validity check for message data length
+    - net/smc: sync err code when tcp connection was refused
+    - ip_gre: Make o_seqno start from 0 in native mode
+    - tcp: fix potential xmit stalls caused by TCP_NOTSENT_LOWAT
+    - bus: sunxi-rsb: Fix the return value of sunxi_rsb_device_create()
+    - clk: sunxi: sun9i-mmc: check return value after calling
+      platform_get_resource()
+    - net: bcmgenet: hide status block before TX timestamping
+    - net: dsa: lantiq_gswip: Don't set GSWIP_MII_CFG_RMII_CLK
+    - drm/amd/display: Fix memory leak in dcn21_clock_source_create
+    - tls: Skip tls_append_frag on zero copy size
+    - bnx2x: fix napi API usage sequence
+    - ixgbe: ensure IPsec VF<->PF compatibility
+    - tcp: fix F-RTO may not work correctly when receiving DSACK
+    - ASoC: wm8731: Disable the regulator when probing fails
+    - ip6_gre: Avoid updating tunnel->tun_hlen in __gre6_xmit()
+    - x86: __memcpy_flushcache: fix wrong alignment if size > 2^32
+    - cifs: destage any unwritten data to the server before calling
+      copychunk_write
+    - drivers: net: hippi: Fix deadlock in rr_close()
+    - net: ethernet: stmmac: fix write to sgmii_adapter_base
+    - x86/cpu: Load microcode during restore_processor_state()
+    - tty: n_gsm: fix wrong signal octet encoding in convergence layer type 2
+    - tty: n_gsm: fix malformed counter for out of frame data
+    - netfilter: nft_socket: only do sk lookups when indev is available
+    - tty: n_gsm: fix insufficient txframe size
+    - tty: n_gsm: fix missing explicit ldisc flush
+    - tty: n_gsm: fix wrong command retry handling
+    - tty: n_gsm: fix wrong command frame length field encoding
+    - tty: n_gsm: fix incorrect UA handling
+    - hugetlbfs: get unmapped area below TASK_UNMAPPED_BASE for hugetlbfs
+    - mm, hugetlb: allow for "high" userspace addresses
+    - Linux 5.4.192
+
+  * CVE-2022-1789
+    - KVM: x86/mmu: fix NULL pointer dereference on guest INVPCID
+
+  * Focal update: v5.4.191 upstream stable release (LP: #1976116)
+    - etherdevice: Adjust ether_addr* prototypes to silence -Wstringop-overead
+    - mm: page_alloc: fix building error on -Werror=array-compare
+    - tracing: Dump stacktrace trigger to the corresponding instance
+    - gfs2: assign rgrp glock before compute_bitstructs
+    - tcp: fix race condition when creating child sockets from syncookies
+    - tcp: Fix potential use-after-free due to double kfree()
+    - ALSA: usb-audio: Clear MIDI port active flag after draining
+    - ASoC: atmel: Remove system clock tree configuration for at91sam9g20ek
+    - ASoC: msm8916-wcd-digital: Check failure for devm_snd_soc_register_component
+    - dmaengine: imx-sdma: Fix error checking in sdma_event_remap
+    - dmaengine: mediatek:Fix PM usage reference leak of
+      mtk_uart_apdma_alloc_chan_resources
+    - igc: Fix infinite loop in release_swfw_sync
+    - igc: Fix BUG: scheduling while atomic
+    - rxrpc: Restore removed timer deletion
+    - net/smc: Fix sock leak when release after smc_shutdown()
+    - net/packet: fix packet_sock xmit return value checking
+    - net/sched: cls_u32: fix possible leak in u32_init_knode()
+    - l3mdev: l3mdev_master_upper_ifindex_by_index_rcu should be using
+      netdev_master_upper_dev_get_rcu
+    - netlink: reset network and mac headers in netlink_dump()
+    - selftests: mlxsw: vxlan_flooding: Prevent flooding of unwanted packets
+    - ARM: vexpress/spc: Avoid negative array index when !SMP
+    - reset: tegra-bpmp: Restore Handle errors in BPMP response
+    - platform/x86: samsung-laptop: Fix an unsigned comparison which can never be
+      negative
+    - ALSA: usb-audio: Fix undefined behavior due to shift overflowing the
+      constant
+    - vxlan: fix error return code in vxlan_fdb_append
+    - cifs: Check the IOCB_DIRECT flag, not O_DIRECT
+    - mt76: Fix undefined behavior due to shift overflowing the constant
+    - brcmfmac: sdio: Fix undefined behavior due to shift overflowing the constant
+    - dpaa_eth: Fix missing of_node_put in dpaa_get_ts_info()
+    - drm/msm/mdp5: check the return of kzalloc()
+    - net: macb: Restart tx only if queue pointer is lagging
+    - scsi: qedi: Fix failed disconnect handling
+    - stat: fix inconsistency between struct stat and struct compat_stat
+    - EDAC/synopsys: Read the error count from the correct register
+    - oom_kill.c: futex: delay the OOM reaper to allow time for proper futex
+      cleanup
+    - ata: pata_marvell: Check the 'bmdma_addr' beforing reading
+    - dma: at_xdmac: fix a missing check on list iterator
+    - drm/panel/raspberrypi-touchscreen: Avoid NULL deref if not initialised
+    - drm/panel/raspberrypi-touchscreen: Initialise the bridge in prepare
+    - KVM: PPC: Fix TCE handling for VFIO
+    - drm/vc4: Use pm_runtime_resume_and_get to fix pm_runtime_get_sync() usage
+    - powerpc/perf: Fix power9 event alternatives
+    - xtensa: patch_text: Fixup last cpu should be master
+    - xtensa: fix a7 clobbering in coprocessor context load/store
+    - openvswitch: fix OOB access in reserve_sfa_size()
+    - ASoC: soc-dapm: fix two incorrect uses of list iterator
+    - e1000e: Fix possible overflow in LTR decoding
+    - ARC: entry: fix syscall_trace_exit argument
+    - arm_pmu: Validate single/group leader events
+    - ext4: fix symlink file size not match to file content
+    - ext4: fix use-after-free in ext4_search_dir
+    - ext4, doc: fix incorrect h_reserved size
+    - ext4: fix overhead calculation to account for the reserved gdt blocks
+    - ext4: force overhead calculation if the s_overhead_cluster makes no sense
+    - jbd2: fix a potential race while discarding reserved buffers after an abort
+    - spi: atmel-quadspi: Fix the buswidth adjustment between spi-mem and
+      controller
+    - staging: ion: Prevent incorrect reference counting behavour
+    - block/compat_ioctl: fix range check in BLKGETSIZE
+    - Linux 5.4.191
+
+  * Focal update: v5.4.190 upstream stable release (LP: #1973085)
+    - memory: atmel-ebi: Fix missing of_node_put in atmel_ebi_probe
+    - net/sched: flower: fix parsing of ethertype following VLAN header
+    - veth: Ensure eth header is in skb's linear part
+    - gpiolib: acpi: use correct format characters
+    - mlxsw: i2c: Fix initialization error flow
+    - net/sched: fix initialization order when updating chain 0 head
+    - net: ethernet: stmmac: fix altr_tse_pcs function when using a fixed-link
+    - net/sched: taprio: Check if socket flags are valid
+    - cfg80211: hold bss_lock while updating nontrans_list
+    - drm/msm/dsi: Use connector directly in msm_dsi_manager_connector_init()
+    - net/smc: Fix NULL pointer dereference in smc_pnet_find_ib()
+    - sctp: Initialize daddr on peeled off socket
+    - testing/selftests/mqueue: Fix mq_perf_tests to free the allocated cpu set
+    - nfc: nci: add flush_workqueue to prevent uaf
+    - cifs: potential buffer overflow in handling symlinks
+    - drm/amd: Add USBC connector ID
+    - drm/amd/display: fix audio format not updated after edid updated
+    - drm/amd/display: Update VTEM Infopacket definition
+    - drm/amdkfd: Fix Incorrect VMIDs passed to HWS
+    - drm/amdkfd: Check for potential null return of kmalloc_array()
+    - Drivers: hv: vmbus: Prevent load re-ordering when reading ring buffer
+    - scsi: target: tcmu: Fix possible page UAF
+    - scsi: ibmvscsis: Increase INITIAL_SRP_LIMIT to 1024
+    - ata: libata-core: Disable READ LOG DMA EXT for Samsung 840 EVOs
+    - gpu: ipu-v3: Fix dev_dbg frequency output
+    - regulator: wm8994: Add an off-on delay for WM8994 variant
+    - arm64: alternatives: mark patch_alternative() as `noinstr`
+    - tlb: hugetlb: Add more sizes to tlb_remove_huge_tlb_entry
+    - net: usb: aqc111: Fix out-of-bounds accesses in RX fixup
+    - drm/amd/display: Fix allocate_mst_payload assert on resume
+    - powerpc: Fix virt_addr_valid() for 64-bit Book3E & 32-bit
+    - scsi: mvsas: Add PCI ID of RocketRaid 2640
+    - scsi: megaraid_sas: Target with invalid LUN ID is deleted during scan
+    - drivers: net: slip: fix NPD bug in sl_tx_timeout()
+    - perf/imx_ddr: Fix undefined behavior due to shift overflowing the constant
+    - mm, page_alloc: fix build_zonerefs_node()
+    - mm: kmemleak: take a full lowmem check in kmemleak_*_phys()
+    - gcc-plugins: latent_entropy: use /dev/urandom
+    - ath9k: Properly clear TX status area before reporting to mac80211
+    - ath9k: Fix usage of driver-private space in tx_info
+    - btrfs: remove unused variable in btrfs_{start,write}_dirty_block_groups()
+    - btrfs: mark resumed async balance as writing
+    - ALSA: hda/realtek: Add quirk for Clevo PD50PNT
+    - ALSA: pcm: Test for "silence" field in struct "pcm_format_data"
+    - ipv6: fix panic when forwarding a pkt with no in6 dev
+    - drm/amd/display: don't ignore alpha property on pre-multiplied mode
+    - genirq/affinity: Consider that CPUs on nodes can be unbalanced
+    - tick/nohz: Use WARN_ON_ONCE() to prevent console saturation
+    - ARM: davinci: da850-evm: Avoid NULL pointer dereference
+    - dm integrity: fix memory corruption when tag_size is less than digest size
+    - smp: Fix offline cpu check in flush_smp_call_function_queue()
+    - i2c: pasemi: Wait for write xfers to finish
+    - dma-direct: avoid redundant memory sync for swiotlb
+    - ax25: add refcount in ax25_dev to avoid UAF bugs
+    - ax25: fix reference count leaks of ax25_dev
+    - ax25: fix UAF bugs of net_device caused by rebinding operation
+    - ax25: Fix refcount leaks caused by ax25_cb_del()
+    - ax25: fix UAF bug in ax25_send_control()
+    - ax25: fix NPD bug in ax25_disconnect
+    - ax25: Fix NULL pointer dereferences in ax25 timers
+    - ax25: Fix UAF bugs in ax25 timers
+    - Linux 5.4.190
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Wed, 22 Jun 2022 15:00:52 +0200
+
+linux (5.4.0-121.137) focal; urgency=medium
+
+  * focal/linux: 5.4.0-121.137 -proposed tracker (LP: #1978666)
+
+  * Packaging resync (LP: #1786013)
+    - debian/dkms-versions -- update from kernel-versions (main/2022.05.30)
+
+  * CVE-2022-28388
+    - can: usb_8dev: usb_8dev_start_xmit(): fix double dev_kfree_skb() in error
+      path
+
+  * test_vxlan_under_vrf.sh in net from ubuntu_kernel_selftests failed (Check VM
+    connectivity through VXLAN (underlay in the default VRF) [FAIL])
+    (LP: #1871015)
+    - selftests: net: test_vxlan_under_vrf: fix HV connectivity test
+
+  * [UBUNTU 20.04] CPU-MF: add extended counter set definitions for new IBM z16
+    (LP: #1974433)
+    - s390/cpumf: add new extended counter set for IBM z16
+
+  * [UBUNTU 20.04] KVM nesting support leaks too much memory, might result in
+    stalls during cleanup (LP: #1974017)
+    - KVM: s390: vsie/gmap: reduce gmap_rmap overhead
+
+  * [UBUNTU 20.04] Null Pointer issue in nfs code running Ubuntu on IBM Z
+    (LP: #1968096)
+    - NFS: Fix up nfs_ctx_key_to_expire()
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Wed, 15 Jun 2022 15:13:27 +0200
+
+linux (5.4.0-120.136) focal; urgency=medium
+
+  * CVE-2022-21123 // CVE-2022-21125 // CVE-2022-21166
+    - cpu/speculation: Add prototype for cpu_show_srbds()
+    - x86/cpu: Add Jasper Lake to Intel family
+    - x86/cpu: Add Lakefield, Alder Lake and Rocket Lake models to the to Intel
+      CPU family
+    - x86/cpu: Add another Alder Lake CPU to the Intel family
+    - Documentation: Add documentation for Processor MMIO Stale Data
+    - x86/speculation/mmio: Enumerate Processor MMIO Stale Data bug
+    - x86/speculation: Add a common function for MD_CLEAR mitigation update
+    - x86/speculation/mmio: Add mitigation for Processor MMIO Stale Data
+    - x86/bugs: Group MDS, TAA & Processor MMIO Stale Data mitigations
+    - x86/speculation/mmio: Enable CPU Fill buffer clearing on idle
+    - x86/speculation/mmio: Add sysfs reporting for Processor MMIO Stale Data
+    - x86/speculation/srbds: Update SRBDS mitigation selection
+    - x86/speculation/mmio: Reuse SRBDS mitigation for SBDS
+    - KVM: x86/speculation: Disable Fill buffer clear within guests
+    - x86/speculation/mmio: Print SMT warning
+
+ -- Thadeu Lima de Souza Cascardo <cascardo@canonical.com>  Fri, 10 Jun 2022 10:21:07 -0300
+
+linux (5.4.0-117.132) focal; urgency=medium
+
+  * CVE-2022-1966
+    - netfilter: nf_tables: add nft_set_elem_expr_alloc()
+    - netfilter: nf_tables: disallow non-stateful expression in sets earlier
+
+ -- Thadeu Lima de Souza Cascardo <cascardo@canonical.com>  Wed, 01 Jun 2022 20:07:42 -0300
+
+linux (5.4.0-115.129) focal; urgency=medium
+
+  * CVE-2022-21499
+    - SAUCE: debug: Lock down kgdb
+
+ -- Thadeu Lima de Souza Cascardo <cascardo@canonical.com>  Sat, 21 May 2022 12:07:10 -0300
+
+linux (5.4.0-114.128) focal; urgency=medium
+
+  * focal/linux: 5.4.0-114.128 -proposed tracker (LP: #1974391)
+
+  * 32 GT/s PCI link speeds reporting "Unknown speed" in sysfs (LP: #1970798)
+    - PCI: Add 32 GT/s decoding in some macros
+    - PCI: Add pci_speed_string()
+    - PCI: Use pci_speed_string() for all PCI/PCI-X/PCIe strings
+    - PCI: Add PCIE_LNKCAP2_SLS2SPEED() macro
+
+  * issuing invalid ioctl to /dev/vsock may spam dmesg (LP: #1971480)
+    - vsock: remove ratelimit unknown ioctl message
+
+  * config CONFIG_HISI_PMU for  kunpeng920 (LP: #1956086)
+    - drivers/perf: hisi: Permit modular builds of HiSilicon uncore drivers
+    - [Config] CONFIG_HISI_PMU=m
+
+  * Focal update: v5.4.189 upstream stable release (LP: #1971497)
+    - swiotlb: fix info leak with DMA_FROM_DEVICE
+    - USB: serial: pl2303: add IBM device IDs
+    - USB: serial: simple: add Nokia phone driver
+    - netdevice: add the case if dev is NULL
+    - HID: logitech-dj: add new lightspeed receiver id
+    - xfrm: fix tunnel model fragmentation behavior
+    - virtio_console: break out of buf poll on remove
+    - ethernet: sun: Free the coherent when failing in probing
+    - spi: Fix invalid sgs value
+    - net:mcf8390: Use platform_get_irq() to get the interrupt
+    - spi: Fix erroneous sgs value with min_t()
+    - af_key: add __GFP_ZERO flag for compose_sadb_supported in function
+      pfkey_register
+    - net: dsa: microchip: add spi_device_id tables
+    - iommu/iova: Improve 32-bit free space estimate
+    - tpm: fix reference counting for struct tpm_chip
+    - block: Add a helper to validate the block size
+    - virtio-blk: Use blk_validate_block_size() to validate block size
+    - USB: usb-storage: Fix use of bitfields for hardware data in ene_ub6250.c
+    - xhci: fix runtime PM imbalance in USB2 resume
+    - xhci: make xhci_handshake timeout for xhci_reset() adjustable
+    - xhci: fix uninitialized string returned by xhci_decode_ctrl_ctx()
+    - coresight: Fix TRCCONFIGR.QE sysfs interface
+    - iio: afe: rescale: use s64 for temporary scale calculations
+    - iio: inkern: apply consumer scale on IIO_VAL_INT cases
+    - iio: inkern: apply consumer scale when no channel scale is available
+    - iio: inkern: make a best effort on offset calculation
+    - greybus: svc: fix an error handling bug in gb_svc_hello()
+    - clk: uniphier: Fix fixed-rate initialization
+    - KEYS: fix length validation in keyctl_pkey_params_get_2()
+    - Documentation: add link to stable release candidate tree
+    - Documentation: update stable tree link
+    - HID: intel-ish-hid: Use dma_alloc_coherent for firmware update
+    - SUNRPC: avoid race between mod_timer() and del_timer_sync()
+    - NFSD: prevent underflow in nfssvc_decode_writeargs()
+    - NFSD: prevent integer overflow on 32 bit systems
+    - f2fs: fix to unlock page correctly in error path of is_alive()
+    - f2fs: quota: fix loop condition at f2fs_quota_sync()
+    - f2fs: fix to do sanity check on .cp_pack_total_block_count
+    - pinctrl: samsung: drop pin banks references on error paths
+    - spi: mxic: Fix the transmit path
+    - jffs2: fix use-after-free in jffs2_clear_xattr_subsystem
+    - jffs2: fix memory leak in jffs2_do_mount_fs
+    - jffs2: fix memory leak in jffs2_scan_medium
+    - mm/pages_alloc.c: don't create ZONE_MOVABLE beyond the end of a node
+    - mm: invalidate hwpoison page cache page in fault path
+    - mempolicy: mbind_range() set_policy() after vma_merge()
+    - scsi: libsas: Fix sas_ata_qc_issue() handling of NCQ NON DATA commands
+    - qed: display VF trust config
+    - qed: validate and restrict untrusted VFs vlan promisc mode
+    - riscv: Fix fill_callchain return value
+    - Revert "Input: clear BTN_RIGHT/MIDDLE on buttonpads"
+    - ALSA: cs4236: fix an incorrect NULL check on list iterator
+    - ALSA: hda/realtek: Fix audio regression on Mi Notebook Pro 2020
+    - mm,hwpoison: unmap poisoned page before invalidation
+    - mm/kmemleak: reset tag when compare object pointer
+    - drbd: fix potential silent data corruption
+    - powerpc/kvm: Fix kvm_use_magic_page
+    - udp: call udp_encap_enable for v6 sockets when enabling encap
+    - ACPI: properties: Consistently return -ENOENT if there are no more
+      references
+    - drivers: hamradio: 6pack: fix UAF bug caused by mod_timer()
+    - mailbox: tegra-hsp: Flush whole channel
+    - block: don't merge across cgroup boundaries if blkcg is enabled
+    - drm/edid: check basic audio support on CEA extension block
+    - video: fbdev: sm712fb: Fix crash in smtcfb_read()
+    - video: fbdev: atari: Atari 2 bpp (STe) palette bugfix
+    - ARM: dts: at91: sama5d2: Fix PMERRLOC resource size
+    - ARM: dts: exynos: fix UART3 pins configuration in Exynos5250
+    - ARM: dts: exynos: add missing HDMI supplies on SMDK5250
+    - ARM: dts: exynos: add missing HDMI supplies on SMDK5420
+    - carl9170: fix missing bit-wise or operator for tx_params
+    - thermal: int340x: Increase bitmap size
+    - lib/raid6/test: fix multiple definition linking error
+    - crypto: rsa-pkcs1pad - correctly get hash from source scatterlist
+    - crypto: rsa-pkcs1pad - restore signature length check
+    - crypto: rsa-pkcs1pad - fix buffer overread in pkcs1pad_verify_complete()
+    - DEC: Limit PMAX memory probing to R3k systems
+    - media: davinci: vpif: fix unbalanced runtime PM get
+    - xtensa: fix stop_machine_cpuslocked call in patch_text
+    - xtensa: fix xtensa_wsr always writing 0
+    - brcmfmac: firmware: Allocate space for default boardrev in nvram
+    - brcmfmac: pcie: Release firmwares in the brcmf_pcie_setup error path
+    - brcmfmac: pcie: Replace brcmf_pcie_copy_mem_todev with memcpy_toio
+    - brcmfmac: pcie: Fix crashes due to early IRQs
+    - PCI: pciehp: Clear cmd_busy bit in polling mode
+    - regulator: qcom_smd: fix for_each_child.cocci warnings
+    - crypto: authenc - Fix sleep in atomic context in decrypt_tail
+    - crypto: mxs-dcp - Fix scatterlist processing
+    - spi: tegra114: Add missing IRQ check in tegra_spi_probe
+    - selftests/x86: Add validity check and allow field splitting
+    - audit: log AUDIT_TIME_* records only from rules
+    - crypto: ccree - don't attempt 0 len DMA mappings
+    - spi: pxa2xx-pci: Balance reference count for PCI DMA device
+    - hwmon: (pmbus) Add mutex to regulator ops
+    - hwmon: (sch56xx-common) Replace WDOG_ACTIVE with WDOG_HW_RUNNING
+    - block: don't delete queue kobject before its children
+    - PM: hibernate: fix __setup handler error handling
+    - PM: suspend: fix return value of __setup handler
+    - hwrng: atmel - disable trng on failure path
+    - crypto: vmx - add missing dependencies
+    - clocksource/drivers/timer-of: Check return value of of_iomap in
+      timer_of_base_init()
+    - ACPI: APEI: fix return value of __setup handlers
+    - crypto: ccp - ccp_dmaengine_unregister release dma channels
+    - hwmon: (pmbus) Add Vin unit off handling
+    - clocksource: acpi_pm: fix return value of __setup handler
+    - sched/debug: Remove mpol_get/put and task_lock/unlock from sched_show_numa
+    - perf/core: Fix address filter parser for multiple filters
+    - perf/x86/intel/pt: Fix address filter config for 32-bit kernel
+    - f2fs: fix missing free nid in f2fs_handle_failed_inode
+    - f2fs: fix to avoid potential deadlock
+    - media: bttv: fix WARNING regression on tunerless devices
+    - media: coda: Fix missing put_device() call in coda_get_vdoa_data
+    - media: hantro: Fix overfill bottom register field name
+    - media: aspeed: Correct value for h-total-pixels
+    - video: fbdev: smscufx: Fix null-ptr-deref in ufx_usb_probe()
+    - video: fbdev: atmel_lcdfb: fix an error code in atmel_lcdfb_probe()
+    - video: fbdev: fbcvt.c: fix printing in fb_cvt_print_name()
+    - ARM: dts: qcom: ipq4019: fix sleep clock
+    - soc: qcom: rpmpd: Check for null return of devm_kcalloc
+    - soc: qcom: aoss: remove spurious IRQF_ONESHOT flags
+    - arm64: dts: qcom: sm8150: Correct TCS configuration for apps rsc
+    - soc: ti: wkup_m3_ipc: Fix IRQ check in wkup_m3_ipc_probe
+    - ARM: dts: imx: Add missing LVDS decoder on M53Menlo
+    - media: video/hdmi: handle short reads of hdmi info frame.
+    - media: em28xx: initialize refcount before kref_get
+    - media: usb: go7007: s2250-board: fix leak in probe()
+    - uaccess: fix nios2 and microblaze get_user_8()
+    - ASoC: rt5663: check the return value of devm_kzalloc() in rt5663_parse_dp()
+    - ASoC: ti: davinci-i2s: Add check for clk_enable()
+    - ALSA: spi: Add check for clk_enable()
+    - arm64: dts: ns2: Fix spi-cpol and spi-cpha property
+    - arm64: dts: broadcom: Fix sata nodename
+    - printk: fix return value of printk.devkmsg __setup handler
+    - ASoC: mxs-saif: Handle errors for clk_enable
+    - ASoC: atmel_ssc_dai: Handle errors for clk_enable
+    - ASoC: soc-compress: prevent the potentially use of null pointer
+    - memory: emif: Add check for setup_interrupts
+    - memory: emif: check the pointer temp in get_device_details()
+    - ALSA: firewire-lib: fix uninitialized flag for AV/C deferred transaction
+    - arm64: dts: rockchip: Fix SDIO regulator supply properties on rk3399-firefly
+    - media: stk1160: If start stream fails, return buffers with
+      VB2_BUF_STATE_QUEUED
+    - ASoC: atmel: Add missing of_node_put() in at91sam9g20ek_audio_probe
+    - ASoC: wm8350: Handle error for wm8350_register_irq
+    - ASoC: fsi: Add check for clk_enable
+    - video: fbdev: omapfb: Add missing of_node_put() in dvic_probe_of
+    - ivtv: fix incorrect device_caps for ivtvfb
+    - ASoC: dmaengine: do not use a NULL prepare_slave_config() callback
+    - ASoC: mxs: Fix error handling in mxs_sgtl5000_probe
+    - ASoC: imx-es8328: Fix error return code in imx_es8328_probe()
+    - ASoC: msm8916-wcd-digital: Fix missing clk_disable_unprepare() in
+      msm8916_wcd_digital_probe
+    - mmc: davinci_mmc: Handle error for clk_enable
+    - ASoC: msm8916-wcd-analog: Fix error handling in pm8916_wcd_analog_spmi_probe
+    - drm/bridge: Fix free wrong object in sii8620_init_rcp_input_dev
+    - drm/bridge: Add missing pm_runtime_disable() in __dw_mipi_dsi_probe
+    - ath10k: fix memory overwrite of the WoWLAN wakeup packet pattern
+    - udmabuf: validate ubuf->pagecount
+    - Bluetooth: hci_serdev: call init_rwsem() before p->open()
+    - mtd: onenand: Check for error irq
+    - mtd: rawnand: gpmi: fix controller timings setting
+    - drm/edid: Don't clear formats if using deep color
+    - drm/amd/display: Fix a NULL pointer dereference in
+      amdgpu_dm_connector_add_common_modes()
+    - ath9k_htc: fix uninit value bugs
+    - KVM: PPC: Fix vmx/vsx mixup in mmio emulation
+    - i40e: don't reserve excessive XDP_PACKET_HEADROOM on XSK Rx to skb
+    - power: reset: gemini-poweroff: Fix IRQ check in gemini_poweroff_probe
+    - ray_cs: Check ioremap return value
+    - powerpc/perf: Don't use perf_hw_context for trace IMC PMU
+    - mt76: mt7603: check sta_rates pointer in mt7603_sta_rate_tbl_update
+    - mt76: mt7615: check sta_rates pointer in mt7615_sta_rate_tbl_update
+    - net: dsa: mv88e6xxx: Enable port policy support on 6097
+    - PCI: aardvark: Fix reading PCI_EXP_RTSTA_PME bit on emulated bridge
+    - power: supply: ab8500: Fix memory leak in ab8500_fg_sysfs_init
+    - HID: i2c-hid: fix GET/SET_REPORT for unnumbered reports
+    - iommu/ipmmu-vmsa: Check for error num after setting mask
+    - drm/amd/display: Add affected crtcs to atomic state for dsc mst unplug
+    - IB/cma: Allow XRC INI QPs to set their local ACK timeout
+    - dax: make sure inodes are flushed before destroy cache
+    - iwlwifi: Fix -EIO error code that is never returned
+    - iwlwifi: mvm: Fix an error code in iwl_mvm_up()
+    - dm crypt: fix get_key_size compiler warning if !CONFIG_KEYS
+    - scsi: pm8001: Fix command initialization in pm80XX_send_read_log()
+    - scsi: pm8001: Fix command initialization in pm8001_chip_ssp_tm_req()
+    - scsi: pm8001: Fix payload initialization in pm80xx_set_thermal_config()
+    - scsi: pm8001: Fix abort all task initialization
+    - drm/amd/display: Remove vupdate_int_entry definition
+    - TOMOYO: fix __setup handlers return values
+    - ext2: correct max file size computing
+    - drm/tegra: Fix reference leak in tegra_dsi_ganged_probe
+    - power: supply: bq24190_charger: Fix bq24190_vbus_is_enabled() wrong false
+      return
+    - scsi: hisi_sas: Change permission of parameter prot_mask
+    - drm/bridge: cdns-dsi: Make sure to to create proper aliases for dt
+    - bpf, arm64: Call build_prologue() first in first JIT pass
+    - bpf, arm64: Feed byte-offset into bpf line info
+    - libbpf: Skip forward declaration when counting duplicated type names
+    - powerpc/Makefile: Don't pass -mcpu=powerpc64 when building 32-bit
+    - KVM: x86: Fix emulation in writing cr8
+    - KVM: x86/emulator: Defer not-present segment check in
+      __load_segment_descriptor()
+    - hv_balloon: rate-limit "Unhandled message" warning
+    - i2c: xiic: Make bus names unique
+    - power: supply: wm8350-power: Handle error for wm8350_register_irq
+    - power: supply: wm8350-power: Add missing free in free_charger_irq
+    - PCI: Reduce warnings on possible RW1C corruption
+    - mips: DEC: honor CONFIG_MIPS_FP_SUPPORT=n
+    - powerpc/sysdev: fix incorrect use to determine if list is empty
+    - mfd: mc13xxx: Add check for mc13xxx_irq_request
+    - selftests/bpf: Make test_lwt_ip_encap more stable and faster
+    - powerpc: 8xx: fix a return value error in mpc8xx_pic_init
+    - vxcan: enable local echo for sent CAN frames
+    - MIPS: RB532: fix return value of __setup handler
+    - mtd: rawnand: atmel: fix refcount issue in atmel_nand_controller_init
+    - RDMA/mlx5: Fix memory leak in error flow for subscribe event routine
+    - bpf, sockmap: Fix memleak in tcp_bpf_sendmsg while sk msg is full
+    - bpf, sockmap: Fix more uncharged while msg has more_data
+    - bpf, sockmap: Fix double uncharge the mem of sk_msg
+    - USB: storage: ums-realtek: fix error code in rts51x_read_mem()
+    - Bluetooth: btmtksdio: Fix kernel oops in btmtksdio_interrupt
+    - af_netlink: Fix shift out of bounds in group mask calculation
+    - i2c: mux: demux-pinctrl: do not deactivate a master that is not active
+    - selftests/bpf/test_lirc_mode2.sh: Exit with proper code
+    - tcp: ensure PMTU updates are processed during fastopen
+    - openvswitch: always update flow key after nat
+    - tipc: fix the timer expires after interval 100ms
+    - mfd: asic3: Add missing iounmap() on error asic3_mfd_probe
+    - mxser: fix xmit_buf leak in activate when LSR == 0xff
+    - pwm: lpc18xx-sct: Initialize driver data and hardware before pwmchip_add()
+    - misc: alcor_pci: Fix an error handling path
+    - staging:iio:adc:ad7280a: Fix handing of device address bit reversing.
+    - pinctrl: renesas: r8a77470: Reduce size for narrow VIN1 channel
+    - clk: qcom: ipq8074: Use floor ops for SDCC1 clock
+    - phy: dphy: Correct lpx parameter and its derivatives(ta_{get,go,sure})
+    - serial: 8250_mid: Balance reference count for PCI DMA device
+    - serial: 8250: Fix race condition in RTS-after-send handling
+    - iio: adc: Add check for devm_request_threaded_irq
+    - NFS: Return valid errors from nfs2/3_decode_dirent()
+    - dma-debug: fix return value of __setup handlers
+    - clk: imx7d: Remove audio_mclk_root_clk
+    - clk: qcom: clk-rcg2: Update logic to calculate D value for RCG
+    - clk: qcom: clk-rcg2: Update the frac table for pixel clock
+    - remoteproc: qcom: Fix missing of_node_put in adsp_alloc_memory_region
+    - remoteproc: qcom_wcnss: Add missing of_node_put() in
+      wcnss_alloc_memory_region
+    - clk: actions: Terminate clk_div_table with sentinel element
+    - clk: loongson1: Terminate clk_div_table with sentinel element
+    - clk: clps711x: Terminate clk_div_table with sentinel element
+    - clk: tegra: tegra124-emc: Fix missing put_device() call in
+      emc_ensure_emc_driver
+    - NFS: remove unneeded check in decode_devicenotify_args()
+    - staging: mt7621-dts: fix LEDs and pinctrl on GB-PC1 devicetree
+    - pinctrl: mediatek: Fix missing of_node_put() in mtk_pctrl_init
+    - pinctrl: mediatek: paris: Fix "argument" argument type for mtk_pinconf_get()
+    - pinctrl: mediatek: paris: Fix pingroup pin config state readback
+    - pinctrl: nomadik: Add missing of_node_put() in nmk_pinctrl_probe
+    - pinctrl/rockchip: Add missing of_node_put() in rockchip_pinctrl_probe
+    - tty: hvc: fix return value of __setup handler
+    - kgdboc: fix return value of __setup handler
+    - kgdbts: fix return value of __setup handler
+    - firmware: google: Properly state IOMEM dependency
+    - driver core: dd: fix return value of __setup handler
+    - jfs: fix divide error in dbNextAG
+    - netfilter: nf_conntrack_tcp: preserve liberal flag in tcp options
+    - NFSv4.1: don't retry BIND_CONN_TO_SESSION on session error
+    - clk: qcom: gcc-msm8994: Fix gpll4 width
+    - clk: Initialize orphan req_rate
+    - xen: fix is_xen_pmu()
+    - net: phy: broadcom: Fix brcm_fet_config_init()
+    - selftests: test_vxlan_under_vrf: Fix broken test case
+    - qlcnic: dcb: default to returning -EOPNOTSUPP
+    - net/x25: Fix null-ptr-deref caused by x25_disconnect
+    - NFSv4/pNFS: Fix another issue with a list iterator pointing to the head
+    - net: dsa: bcm_sf2_cfp: fix an incorrect NULL check on list iterator
+    - lib/test: use after free in register_test_dev_kmod()
+    - LSM: general protection fault in legacy_parse_param
+    - gcc-plugins/stackleak: Exactly match strings instead of prefixes
+    - pinctrl: npcm: Fix broken references to chip->parent_device
+    - block, bfq: don't move oom_bfqq
+    - selinux: use correct type for context length
+    - loop: use sysfs_emit() in the sysfs xxx show()
+    - Fix incorrect type in assignment of ipv6 port for audit
+    - irqchip/qcom-pdc: Fix broken locking
+    - irqchip/nvic: Release nvic_base upon failure
+    - bfq: fix use-after-free in bfq_dispatch_request
+    - ACPICA: Avoid walking the ACPI Namespace if it is not there
+    - lib/raid6/test/Makefile: Use $(pound) instead of \# for Make 4.3
+    - Revert "Revert "block, bfq: honor already-setup queue merges""
+    - ACPI/APEI: Limit printable size of BERT table data
+    - PM: core: keep irq flags in device_pm_check_callbacks()
+    - spi: tegra20: Use of_device_get_match_data()
+    - ext4: don't BUG if someone dirty pages without asking ext4 first
+    - ntfs: add sanity check on allocation size
+    - video: fbdev: nvidiafb: Use strscpy() to prevent buffer overflow
+    - video: fbdev: w100fb: Reset global state
+    - video: fbdev: cirrusfb: check pixclock to avoid divide by zero
+    - video: fbdev: omapfb: acx565akm: replace snprintf with sysfs_emit
+    - ARM: dts: qcom: fix gic_irq_domain_translate warnings for msm8960
+    - ARM: dts: bcm2837: Add the missing L1/L2 cache information
+    - ASoC: madera: Add dependencies on MFD
+    - video: fbdev: omapfb: panel-dsi-cm: Use sysfs_emit() instead of snprintf()
+    - video: fbdev: omapfb: panel-tpo-td043mtea1: Use sysfs_emit() instead of
+      snprintf()
+    - video: fbdev: udlfb: replace snprintf in show functions with sysfs_emit
+    - ASoC: soc-core: skip zero num_dai component in searching dai name
+    - media: cx88-mpeg: clear interrupt status register before streaming video
+    - ARM: tegra: tamonten: Fix I2C3 pad setting
+    - ARM: mmp: Fix failure to remove sram device
+    - video: fbdev: sm712fb: Fix crash in smtcfb_write()
+    - media: Revert "media: em28xx: add missing em28xx_close_extension"
+    - media: hdpvr: initialize dev->worker at hdpvr_register_videodev
+    - mmc: host: Return an error when ->enable_sdio_irq() ops is missing
+    - ALSA: hda/realtek: Add alc256-samsung-headphone fixup
+    - powerpc/lib/sstep: Fix 'sthcx' instruction
+    - powerpc/lib/sstep: Fix build errors with newer binutils
+    - powerpc: Fix build errors with newer binutils
+    - scsi: qla2xxx: Fix stuck session in gpdb
+    - scsi: qla2xxx: Fix wrong FDMI data for 64G adapter
+    - scsi: qla2xxx: Fix warning for missing error code
+    - scsi: qla2xxx: Fix device reconnect in loop topology
+    - scsi: qla2xxx: Add devids and conditionals for 28xx
+    - scsi: qla2xxx: Check for firmware dump already collected
+    - scsi: qla2xxx: Suppress a kernel complaint in qla_create_qpair()
+    - scsi: qla2xxx: Fix disk failure to rediscover
+    - scsi: qla2xxx: Fix incorrect reporting of task management failure
+    - scsi: qla2xxx: Fix hang due to session stuck
+    - scsi: qla2xxx: Fix missed DMA unmap for NVMe ls requests
+    - scsi: qla2xxx: Fix N2N inconsistent PLOGI
+    - scsi: qla2xxx: Reduce false trigger to login
+    - scsi: qla2xxx: Use correct feature type field during RFF_ID processing
+    - KVM: Prevent module exit until all VMs are freed
+    - KVM: x86: fix sending PV IPI
+    - ASoC: SOF: Intel: Fix NULL ptr dereference when ENOMEM
+    - ubifs: rename_whiteout: Fix double free for whiteout_ui->data
+    - ubifs: Fix deadlock in concurrent rename whiteout and inode writeback
+    - ubifs: Add missing iput if do_tmpfile() failed in rename whiteout
+    - ubifs: setflags: Make dirtied_ino_d 8 bytes aligned
+    - ubifs: Fix read out-of-bounds in ubifs_wbuf_write_nolock()
+    - ubifs: rename_whiteout: correct old_dir size computing
+    - XArray: Fix xas_create_range() when multi-order entry present
+    - can: mcba_usb: mcba_usb_start_xmit(): fix double dev_kfree_skb in error path
+    - can: mcba_usb: properly check endpoint type
+    - XArray: Update the LRU list in xas_split()
+    - rtc: check if __rtc_read_time was successful
+    - gfs2: Make sure FITRIM minlen is rounded up to fs block size
+    - net: hns3: fix software vlan talbe of vlan 0 inconsistent with hardware
+    - pinctrl: pinconf-generic: Print arguments for bias-pull-*
+    - pinctrl: nuvoton: npcm7xx: Rename DS() macro to DSTR()
+    - pinctrl: nuvoton: npcm7xx: Use %zu printk format for ARRAY_SIZE()
+    - ASoC: mediatek: mt6358: add missing EXPORT_SYMBOLs
+    - ubi: Fix race condition between ctrl_cdev_ioctl and ubi_cdev_ioctl
+    - ARM: iop32x: offset IRQ numbers by 1
+    - ACPI: CPPC: Avoid out of bounds access when parsing _CPC data
+    - powerpc/kasan: Fix early region not updated correctly
+    - ASoC: soc-compress: Change the check for codec_dai
+    - mm/mmap: return 1 from stack_guard_gap __setup() handler
+    - mm/memcontrol: return 1 from cgroup.memory __setup() handler
+    - mm/usercopy: return 1 from hardened_usercopy __setup() handler
+    - bpf: Fix comment for helper bpf_current_task_under_cgroup()
+    - dt-bindings: mtd: nand-controller: Fix the reg property description
+    - dt-bindings: mtd: nand-controller: Fix a comment in the examples
+    - dt-bindings: spi: mxic: The interrupt property is not mandatory
+    - ubi: fastmap: Return error code if memory allocation fails in add_aeb()
+    - ASoC: topology: Allow TLV control to be either read or write
+    - ARM: dts: spear1340: Update serial node properties
+    - ARM: dts: spear13xx: Update SPI dma properties
+    - um: Fix uml_mconsole stop/go
+    - openvswitch: Fixed nd target mask field in the flow dump.
+    - KVM: x86/mmu: do compare-and-exchange of gPTE via the user address
+    - KVM: x86: Forbid VMM to set SYNIC/STIMER MSRs when SynIC wasn't activated
+    - ubifs: Rectify space amount budget for mkdir/tmpfile operations
+    - rtc: wm8350: Handle error for wm8350_register_irq
+    - riscv module: remove (NOLOAD)
+    - ARM: 9187/1: JIVE: fix return value of __setup handler
+    - KVM: x86/svm: Clear reserved bits written to PerfEvtSeln MSRs
+    - drm: Add orientation quirk for GPD Win Max
+    - ath5k: fix OOB in ath5k_eeprom_read_pcal_info_5111
+    - drm/amd/amdgpu/amdgpu_cs: fix refcount leak of a dma_fence obj
+    - ptp: replace snprintf with sysfs_emit
+    - powerpc: dts: t104xrdb: fix phy type for FMAN 4/5
+    - bpf: Make dst_port field in struct bpf_sock 16-bit wide
+    - scsi: mvsas: Replace snprintf() with sysfs_emit()
+    - scsi: bfa: Replace snprintf() with sysfs_emit()
+    - power: supply: axp20x_battery: properly report current when discharging
+    - ipv6: make mc_forwarding atomic
+    - powerpc: Set crashkernel offset to mid of RMA region
+    - drm/amdgpu: Fix recursive locking warning
+    - PCI: aardvark: Fix support for MSI interrupts
+    - iommu/arm-smmu-v3: fix event handling soft lockup
+    - usb: ehci: add pci device support for Aspeed platforms
+    - PCI: pciehp: Add Qualcomm quirk for Command Completed erratum
+    - power: supply: axp288-charger: Set Vhold to 4.4V
+    - ipv4: Invalidate neighbour for broadcast address upon address addition
+    - dm ioctl: prevent potential spectre v1 gadget
+    - drm/amdkfd: make CRAT table missing message informational only
+    - scsi: pm8001: Fix pm8001_mpi_task_abort_resp()
+    - scsi: aha152x: Fix aha152x_setup() __setup handler return value
+    - net/smc: correct settings of RMB window update limit
+    - mips: ralink: fix a refcount leak in ill_acc_of_setup()
+    - macvtap: advertise link netns via netlink
+    - tuntap: add sanity checks about msg_controllen in sendmsg
+    - bnxt_en: Eliminate unintended link toggle during FW reset
+    - MIPS: fix fortify panic when copying asm exception handlers
+    - scsi: libfc: Fix use after free in fc_exch_abts_resp()
+    - usb: dwc3: omap: fix "unbalanced disables for smps10_out1" on omap5evm
+    - xtensa: fix DTC warning unit_address_format
+    - Bluetooth: Fix use after free in hci_send_acl
+    - netlabel: fix out-of-bounds memory accesses
+    - init/main.c: return 1 from handled __setup() functions
+    - minix: fix bug when opening a file with O_DIRECT
+    - clk: si5341: fix reported clk_rate when output divider is 2
+    - w1: w1_therm: fixes w1_seq for ds28ea00 sensors
+    - NFSv4: Protect the state recovery thread against direct reclaim
+    - xen: delay xen_hvm_init_time_ops() if kdump is boot on vcpu>=32
+    - clk: Enforce that disjoints limits are invalid
+    - SUNRPC/call_alloc: async tasks mustn't block waiting for memory
+    - NFS: swap IO handling is slightly different for O_DIRECT IO
+    - NFS: swap-out must always use STABLE writes.
+    - serial: samsung_tty: do not unlock port->lock for uart_write_wakeup()
+    - virtio_console: eliminate anonymous module_init & module_exit
+    - jfs: prevent NULL deref in diFree
+    - SUNRPC: Fix socket waits for write buffer space
+    - parisc: Fix CPU affinity for Lasi, WAX and Dino chips
+    - parisc: Fix patch code locking and flushing
+    - mm: fix race between MADV_FREE reclaim and blkdev direct IO read
+    - KVM: arm64: Check arm64_get_bp_hardening_data() didn't return NULL
+    - drm/amdgpu: fix off by one in amdgpu_gfx_kiq_acquire()
+    - Drivers: hv: vmbus: Fix potential crash on module unload
+    - scsi: zorro7xx: Fix a resource leak in zorro7xx_remove_one()
+    - net/tls: fix slab-out-of-bounds bug in decrypt_internal
+    - net: ipv4: fix route with nexthop object delete warning
+    - net: stmmac: Fix unset max_speed difference between DT and non-DT platforms
+    - drm/imx: Fix memory leak in imx_pd_connector_get_modes
+    - bnxt_en: reserve space inside receive page for skb_shared_info
+    - IB/rdmavt: add lock to call to rvt_error_qp to prevent a race condition
+    - dpaa2-ptp: Fix refcount leak in dpaa2_ptp_probe
+    - ipv6: Fix stats accounting in ip6_pkt_drop
+    - net: openvswitch: don't send internal clone attribute to the userspace.
+    - rxrpc: fix a race in rxrpc_exit_net()
+    - qede: confirm skb is allocated before using
+    - spi: bcm-qspi: fix MSPI only access with bcm_qspi_exec_mem_op()
+    - bpf: Support dual-stack sockets in bpf_tcp_check_syncookie
+    - drbd: Fix five use after free bugs in get_initial_state
+    - SUNRPC: Handle ENOMEM in call_transmit_status()
+    - SUNRPC: Handle low memory situations in call_status()
+    - perf tools: Fix perf's libperf_print callback
+    - perf session: Remap buf if there is no space for event
+    - Revert "mmc: sdhci-xenon: fix annoying 1.8V regulator warning"
+    - mmc: renesas_sdhi: don't overwrite TAP settings when HS400 tuning is
+      complete
+    - lz4: fix LZ4_decompress_safe_partial read out of bound
+    - mmmremap.c: avoid pointless invalidate_range_start/end on mremap(old_size=0)
+    - mm/mempolicy: fix mpol_new leak in shared_policy_replace
+    - x86/pm: Save the MSR validity status at context setup
+    - x86/speculation: Restore speculation related MSRs during S3 resume
+    - btrfs: fix qgroup reserve overflow the qgroup limit
+    - arm64: patch_text: Fixup last cpu should be master
+    - ata: sata_dwc_460ex: Fix crash due to OOB write
+    - perf: qcom_l2_pmu: fix an incorrect NULL check on list iterator
+    - irqchip/gic-v3: Fix GICR_CTLR.RWP polling
+    - tools build: Filter out options and warnings not supported by clang
+    - tools build: Use $(shell ) instead of `` to get embedded libperl's ccopts
+    - dmaengine: Revert "dmaengine: shdma: Fix runtime PM imbalance on error"
+    - mmc: mmci_sdmmc: Replace sg_dma_xxx macros
+    - mmc: mmci: stm32: correctly check all elements of sg list
+    - mm: don't skip swap entry even if zap_details specified
+    - arm64: module: remove (NOLOAD) from linker script
+    - mm/sparsemem: fix 'mem_section' will never be NULL gcc 12 warning
+    - drm/amdkfd: add missing void argument to function kgd2kfd_init
+    - drm/amdkfd: Fix -Wstrict-prototypes from
+      amdgpu_amdkfd_gfx_10_0_get_functions()
+    - cgroup: Use open-time credentials for process migraton perm checks
+    - cgroup: Allocate cgroup_file_ctx for kernfs_open_file->priv
+    - cgroup: Use open-time cgroup namespace for process migration perm checks
+    - selftests: cgroup: Make cg_create() use 0755 for permission instead of 0644
+    - selftests: cgroup: Test open-time credential usage for migration checks
+    - selftests: cgroup: Test open-time cgroup namespace usage for migration
+      checks
+    - cpuidle: PSCI: Move the `has_lpi` check to the beginning of the function
+    - ACPI: processor idle: Check for architectural support for LPI
+    - Linux 5.4.189
+
+  * Focal update: v5.4.188 upstream stable release (LP: #1971496)
+    - nfsd: cleanup nfsd_file_lru_dispose()
+    - nfsd: Containerise filecache laundrette
+    - net: ipv6: fix skb_over_panic in __ip6_append_data
+    - tpm: Fix error handling in async work
+    - staging: fbtft: fb_st7789v: reset display before initialization
+    - thermal: int340x: fix memory leak in int3400_notify()
+    - llc: fix netdevice reference leaks in llc_ui_bind()
+    - ALSA: pcm: Add stream lock during PCM reset ioctl operations
+    - ALSA: usb-audio: Add mute TLV for playback volumes on RODE NT-USB
+    - ALSA: cmipci: Restore aux vol on suspend/resume
+    - ALSA: pci: fix reading of swapped values from pcmreg in AC97 codec
+    - drivers: net: xgene: Fix regression in CRC stripping
+    - ASoC: sti: Fix deadlock via snd_pcm_stop_xrun() call
+    - ALSA: oss: Fix PCM OSS buffer allocation overflow
+    - ALSA: hda/realtek - Fix headset mic problem for a HP machine with alc671
+    - ALSA: hda/realtek: Add quirk for ASUS GA402
+    - ACPI / x86: Work around broken XSDT on Advantech DAC-BJ01 board
+    - ACPI: battery: Add device HID and quirk for Microsoft Surface Go 3
+    - ACPI: video: Force backlight native for Clevo NL5xRU and NL5xNU
+    - crypto: qat - disable registration of algorithms
+    - rcu: Don't deboost before reporting expedited quiescent state
+    - mac80211: fix potential double free on mesh join
+    - tpm: use try_get_ops() in tpm-space.c
+    - nds32: fix access_ok() checks in get/put_user
+    - llc: only change llc->dev when bind() succeeds
+    - Linux 5.4.188
+
+  * Focal update: v5.4.187 upstream stable release (LP: #1971493)
+    - crypto: qcom-rng - ensure buffer for generate is completely filled
+    - ocfs2: fix crash when initialize filecheck kobj fails
+    - efi: fix return value of __setup handlers
+    - net: phy: marvell: Fix invalid comparison in the resume and suspend
+      functions
+    - net/packet: fix slab-out-of-bounds access in packet_recvmsg()
+    - atm: eni: Add check for dma_map_single
+    - hv_netvsc: Add check for kvmalloc_array
+    - drm/panel: simple: Fix Innolux G070Y2-L01 BPP settings
+    - net: handle ARPHRD_PIMREG in dev_is_mac_header_xmit()
+    - net: dsa: Add missing of_node_put() in dsa_port_parse_of
+    - arm64: fix clang warning about TRAMP_VALIAS
+    - usb: gadget: rndis: prevent integer overflow in rndis_set_response()
+    - usb: gadget: Fix use-after-free bug by not setting udc->dev.driver
+    - usb: usbtmc: Fix bug in pipe direction for control transfers
+    - Input: aiptek - properly check endpoint type
+    - perf symbols: Fix symbol size calculation condition
+    - Linux 5.4.187
+
+  * Focal update: v5.4.186 upstream stable release (LP: #1969678)
+    - Revert "xfrm: state and policy should fail if XFRMA_IF_ID 0"
+    - sctp: fix the processing for INIT chunk
+    - xfrm: Check if_id in xfrm_migrate
+    - xfrm: Fix xfrm migrate issues when address family changes
+    - arm64: dts: rockchip: fix rk3399-puma eMMC HS400 signal integrity
+    - arm64: dts: rockchip: reorder rk3399 hdmi clocks
+    - arm64: dts: agilex: use the compatible "intel,socfpga-agilex-hsotg"
+    - ARM: dts: rockchip: reorder rk322x hmdi clocks
+    - ARM: dts: rockchip: fix a typo on rk3288 crypto-controller
+    - mac80211: refuse aggregations sessions before authorized
+    - MIPS: smp: fill in sibling and core maps earlier
+    - ARM: 9178/1: fix unmet dependency on BITREVERSE for HAVE_ARCH_BITREVERSE
+    - can: rcar_canfd: rcar_canfd_channel_probe(): register the CAN device when
+      fully ready
+    - atm: firestream: check the return value of ioremap() in fs_init()
+    - iwlwifi: don't advertise TWT support
+    - drm/vrr: Set VRR capable prop only if it is attached to connector
+    - nl80211: Update bss channel on channel switch for P2P_CLIENT
+    - tcp: make tcp_read_sock() more robust
+    - sfc: extend the locking on mcdi->seqno
+    - kselftest/vm: fix tests build with old libc
+    - fixup for "arm64 entry: Add macro for reading symbol address from the
+      trampoline"
+    - Linux 5.4.186
+
+  * Focal update: v5.4.185 upstream stable release (LP: #1969672)
+    - clk: qcom: gdsc: Add support to update GDSC transition delay
+    - arm64: dts: armada-3720-turris-mox: Add missing ethernet0 alias
+    - virtio-blk: Don't use MAX_DISCARD_SEGMENTS if max_discard_seg is zero
+    - net: qlogic: check the return value of dma_alloc_coherent() in
+      qed_vf_hw_prepare()
+    - qed: return status of qed_iov_get_link
+    - drm/sun4i: mixer: Fix P010 and P210 format numbers
+    - ARM: dts: aspeed: Fix AST2600 quad spi group
+    - ethernet: Fix error handling in xemaclite_of_probe
+    - net: ethernet: ti: cpts: Handle error for clk_enable
+    - net: ethernet: lpc_eth: Handle error for clk_enable
+    - ax25: Fix NULL pointer dereference in ax25_kill_by_device
+    - net/mlx5: Fix size field in bufferx_reg struct
+    - net/mlx5: Fix a race on command flush flow
+    - NFC: port100: fix use-after-free in port100_send_complete
+    - selftests: pmtu.sh: Kill tcpdump processes launched by subshell.
+    - gpio: ts4900: Do not set DAT and OE together
+    - gianfar: ethtool: Fix refcount leak in gfar_get_ts_info
+    - net: phy: DP83822: clear MISR2 register to disable interrupts
+    - sctp: fix kernel-infoleak for SCTP sockets
+    - net: bcmgenet: Don't claim WOL when its not available
+    - net-sysfs: add check for netdevice being present to speed_show
+    - Revert "xen-netback: remove 'hotplug-status' once it has served its purpose"
+    - Revert "xen-netback: Check for hotplug-status existence before watching"
+    - ipv6: prevent a possible race condition with lifetimes
+    - tracing: Ensure trace buffer is at least 4096 bytes large
+    - selftest/vm: fix map_fixed_noreplace test failure
+    - selftests/memfd: clean up mapping in mfd_fail_write
+    - ARM: Spectre-BHB: provide empty stub for non-config
+    - fuse: fix pipe buffer lifetime for direct_io
+    - staging: gdm724x: fix use after free in gdm_lte_rx()
+    - net: macb: Fix lost RX packet wakeup race in NAPI receive
+    - mmc: meson: Fix usage of meson_mmc_post_req()
+    - riscv: Fix auipc+jalr relocation range checks
+    - arm64: dts: marvell: armada-37xx: Remap IO space to bus address 0x0
+    - virtio: unexport virtio_finalize_features
+    - virtio: acknowledge all features before access
+    - ARM: fix Thumb2 regression with Spectre BHB
+    - ext4: add check to prevent attempting to resize an fs with sparse_super2
+    - x86/cpufeatures: Mark two free bits in word 3
+    - x86/cpu: Add hardware-enforced cache coherency as a CPUID feature
+    - x86/mm/pat: Don't flush cache if hardware enforces cache coherency across
+      encryption domnains
+    - KVM: SVM: Don't flush cache if hardware enforces cache coherency across
+      encryption domains
+    - Linux 5.4.185
+
+  * Focal update: v5.4.184 upstream stable release (LP: #1969242)
+    - arm/arm64: Provide a wrapper for SMCCC 1.1 calls
+    - arm/arm64: smccc/psci: add arm_smccc_1_1_get_conduit()
+    - ARM: report Spectre v2 status through sysfs
+    - ARM: early traps initialisation
+    - ARM: use LOADADDR() to get load address of sections
+    - [Config] updateconfigs for HARDEN_BRANCH_HISTORY
+    - ARM: Spectre-BHB workaround
+    - ARM: include unprivileged BPF status in Spectre V2 reporting
+    - ARM: fix build error when BPF_SYSCALL is disabled
+    - ARM: fix co-processor register typo
+    - ARM: Do not use NOCROSSREFS directive with ld.lld
+    - ARM: fix build warning in proc-v7-bugs.c
+    - xen/xenbus: don't let xenbus_grant_ring() remove grants in error case
+    - xen/grant-table: add gnttab_try_end_foreign_access()
+    - xen/blkfront: don't use gnttab_query_foreign_access() for mapped status
+    - xen/netfront: don't use gnttab_query_foreign_access() for mapped status
+    - xen/scsifront: don't use gnttab_query_foreign_access() for mapped status
+    - xen/gntalloc: don't use gnttab_query_foreign_access()
+    - xen: remove gnttab_query_foreign_access()
+    - xen/9p: use alloc/free_pages_exact()
+    - xen/pvcalls: use alloc/free_pages_exact()
+    - xen/gnttab: fix gnttab_end_foreign_access() without page specified
+    - xen/netfront: react properly to failing gnttab_end_foreign_access_ref()
+    - Linux 5.4.184
+
+  * Focal update: v5.4.183 upstream stable release (LP: #1969239)
+    - mac80211_hwsim: report NOACK frames in tx_status
+    - mac80211_hwsim: initialize ieee80211_tx_info at hw_scan_work
+    - i2c: bcm2835: Avoid clock stretching timeouts
+    - ASoC: rt5668: do not block workqueue if card is unbound
+    - ASoC: rt5682: do not block workqueue if card is unbound
+    - Input: clear BTN_RIGHT/MIDDLE on buttonpads
+    - cifs: fix double free race when mount fails in cifs_get_root()
+    - dmaengine: shdma: Fix runtime PM imbalance on error
+    - i2c: cadence: allow COMPILE_TEST
+    - i2c: qup: allow COMPILE_TEST
+    - net: usb: cdc_mbim: avoid altsetting toggling for Telit FN990
+    - usb: gadget: don't release an existing dev->buf
+    - usb: gadget: clear related members when goto fail
+    - ata: pata_hpt37x: fix PCI clock detection
+    - ALSA: intel_hdmi: Fix reference to PCM buffer address
+    - ASoC: ops: Shift tested values in snd_soc_put_volsw() by +min
+    - xfrm: fix MTU regression
+    - netfilter: fix use-after-free in __nf_register_net_hook()
+    - xfrm: enforce validity of offload input flags
+    - netfilter: nf_queue: don't assume sk is full socket
+    - netfilter: nf_queue: fix possible use-after-free
+    - batman-adv: Request iflink once in batadv-on-batadv check
+    - batman-adv: Request iflink once in batadv_get_real_netdevice
+    - batman-adv: Don't expect inter-netns unique iflink indices
+    - net: dcb: flush lingering app table entries for unregistered devices
+    - net/smc: fix unexpected SMC_CLC_DECL_ERR_REGRMB error generated by client
+    - net/smc: fix unexpected SMC_CLC_DECL_ERR_REGRMB error cause by server
+    - block: Fix fsync always failed if once failed
+    - xen/netfront: destroy queues before real_num_tx_queues is zeroed
+    - sched/topology: Make sched_init_numa() use a set for the deduplicating sort
+    - sched/topology: Fix sched_domain_topology_level alloc in sched_init_numa()
+    - ia64: ensure proper NUMA distance and possible map initialization
+    - mac80211: fix forwarded mesh frames AC & queue selection
+    - net: stmmac: fix return value of __setup handler
+    - iavf: Fix missing check for running netdev
+    - net: sxgbe: fix return value of __setup handler
+    - net: arcnet: com20020: Fix null-ptr-deref in com20020pci_probe()
+    - ixgbe: xsk: change !netif_carrier_ok() handling in ixgbe_xmit_zc()
+    - efivars: Respect "block" flag in efivar_entry_set_safe()
+    - firmware: arm_scmi: Remove space in MODULE_ALIAS name
+    - ASoC: cs4265: Fix the duplicated control name
+    - can: gs_usb: change active_channels's type from atomic_t to u8
+    - arm64: dts: rockchip: Switch RK3399-Gru DP to SPDIF output
+    - igc: igc_read_phy_reg_gpy: drop premature return
+    - ARM: Fix kgdb breakpoint for Thumb2
+    - ARM: 9182/1: mmu: fix returns from early_param() and __setup() functions
+    - igc: igc_write_phy_reg_gpy: drop premature return
+    - ibmvnic: free reset-work-item when flushing
+    - memfd: fix F_SEAL_WRITE after shmem huge page allocated
+    - soc: fsl: qe: Check of ioremap return value
+    - net: chelsio: cxgb3: check the return value of pci_find_capability()
+    - nl80211: Handle nla_memdup failures in handle_nan_filter
+    - Input: elan_i2c - move regulator_[en|dis]able() out of
+      elan_[en|dis]able_power()
+    - Input: elan_i2c - fix regulator enable count imbalance after suspend/resume
+    - HID: add mapping for KEY_DICTATE
+    - HID: add mapping for KEY_ALL_APPLICATIONS
+    - tracing/histogram: Fix sorting on old "cpu" value
+    - tracing: Fix return value of __setup handlers
+    - btrfs: fix lost prealloc extents beyond eof after full fsync
+    - btrfs: qgroup: fix deadlock between rescan worker and remove qgroup
+    - btrfs: add missing run of delayed items after unlink during log replay
+    - Revert "xfrm: xfrm_state_mtu should return at least 1280 for ipv6"
+    - net: dcb: disable softirqs in dcbnl_flush_dev()
+    - hamradio: fix macro redefine warning
+    - Linux 5.4.183
+
+  * Focal update: v5.4.182 upstream stable release (LP: #1969236)
+    - cgroup/cpuset: Fix a race between cpuset_attach() and cpu hotplug
+    - clk: jz4725b: fix mmc0 clock gating
+    - vhost/vsock: don't check owner in vhost_vsock_stop() while releasing
+    - parisc/unaligned: Fix fldd and fstd unaligned handlers on 32-bit kernel
+    - parisc/unaligned: Fix ldw() and stw() unalignment handlers
+    - drm/amdgpu: disable MMHUB PG for Picasso
+    - sr9700: sanity check for packet length
+    - USB: zaurus: support another broken Zaurus
+    - x86/fpu: Correct pkru/xstate inconsistency
+    - tee: export teedev_open() and teedev_close_context()
+    - optee: use driver internal tee_context for some rpc
+    - lan743x: fix deadlock in lan743x_phy_link_status_change()
+    - ping: remove pr_err from ping_lookup
+    - perf data: Fix double free in perf_session__delete()
+    - bpf: Do not try bpf_msg_push_data with len 0
+    - net: __pskb_pull_tail() & pskb_carve_frag_list() drop_monitor friends
+    - tipc: Fix end of loop tests for list_for_each_entry()
+    - gso: do not skip outer ip header in case of ipip and net_failover
+    - openvswitch: Fix setting ipv6 fields causing hw csum failure
+    - drm/edid: Always set RGB444
+    - net/mlx5e: Fix wrong return value on ioctl EEPROM query failure
+    - net: ll_temac: check the return value of devm_kmalloc()
+    - net: Force inlining of checksum functions in net/checksum.h
+    - nfp: flower: Fix a potential leak in nfp_tunnel_add_shared_mac()
+    - netfilter: nf_tables: fix memory leak during stateful obj update
+    - net/mlx5: Fix possible deadlock on rule deletion
+    - net/mlx5: Fix wrong limitation of metadata match on ecpf
+    - spi: spi-zynq-qspi: Fix a NULL pointer dereference in
+      zynq_qspi_exec_mem_op()
+    - configfs: fix a race in configfs_{,un}register_subsystem()
+    - RDMA/ib_srp: Fix a deadlock
+    - tracing: Have traceon and traceoff trigger honor the instance
+    - iio: adc: men_z188_adc: Fix a resource leak in an error handling path
+    - iio: adc: ad7124: fix mask used for setting AIN_BUFP & AIN_BUFM bits
+    - iio: Fix error handling for PM
+    - ata: pata_hpt37x: disable primary channel on HPT371
+    - Revert "USB: serial: ch341: add new Product ID for CH341A"
+    - usb: gadget: rndis: add spinlock for rndis response list
+    - tracefs: Set the group ownership in apply_options() not parse_options()
+    - USB: serial: option: add support for DW5829e
+    - USB: serial: option: add Telit LE910R1 compositions
+    - usb: dwc3: pci: Fix Bay Trail phy GPIO mappings
+    - usb: dwc3: gadget: Let the interrupt handler disable bottom halves.
+    - xhci: re-initialize the HC during resume if HCE was set
+    - xhci: Prevent futile URB re-submissions due to incorrect return value.
+    - tty: n_gsm: fix encoding of control signal octet bit DV
+    - tty: n_gsm: fix proper link termination after failed open
+    - tty: n_gsm: fix NULL pointer access due to DLCI release
+    - gpio: tegra186: Fix chip_data type confusion
+    - Revert "drm/nouveau/pmu/gm200-: avoid touching PMU outside of
+      DEVINIT/PREOS/ACR"
+    - memblock: use kfree() to release kmalloced memblock regions
+    - fget: clarify and improve __fget_files() implementation
+    - Linux 5.4.182
+
+  * CVE-2022-28390
+    - can: ems_usb: ems_usb_start_xmit(): fix double dev_kfree_skb() in error path
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Fri, 20 May 2022 15:31:22 +0200
+
+linux (5.4.0-113.127) focal; urgency=medium
+
+  * focal/linux: 5.4.0-113.127 -proposed tracker (LP: #1973980)
+
+  * CVE-2022-29581
+    - net/sched: cls_u32: fix netns refcount changes in u32_change()
+
+  * CVE-2022-1116
+    - io_uring: fix fs->users overflow
+
+  * ext4: limit length to bitmap_maxbytes (LP: #1972281)
+    - ext4: limit length to bitmap_maxbytes - blocksize in punch_hole
+
+  * Unprivileged users may use PTRACE_SEIZE to set PTRACE_O_SUSPEND_SECCOMP
+    option (LP: #1972740)
+    - ptrace: Check PTRACE_O_SUSPEND_SECCOMP permission on PTRACE_SEIZE
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Wed, 18 May 2022 16:07:54 +0200
+
+linux (5.4.0-110.124) focal; urgency=medium
+
+  * focal/linux: 5.4.0-110.124 -proposed tracker (LP: #1969053)
+
+  * net/mlx5e: Fix page DMA map/unmap attributes (LP: #1967292)
+    - net/mlx5e: Fix page DMA map/unmap attributes
+
+  * xfs: Fix deadlock between AGI and AGF when target_ip exists in xfs_rename()
+    (LP: #1966803)
+    - xfs: Fix deadlock between AGI and AGF when target_ip exists in xfs_rename()
+
+  * LRMv6: add multi-architecture support (LP: #1968774)
+    - [Packaging] resync dkms-build{,--nvidia-N}
+
+  * xfrm interface cannot be changed anymore (LP: #1968591)
+    - xfrm: fix the if_id check in changelink
+
+  * Use kernel-testing repo from launchpad for ADT tests (LP: #1968016)
+    - [Debian] Use kernel-testing repo from launchpad
+
+  * vmx_ldtr_test in ubuntu_kvm_unit_tests failed (FAIL: Expected 0 for L1 LDTR
+    selector (got 50)) (LP: #1956315)
+    - KVM: nVMX: Set LDTR to its architecturally defined value on nested VM-Exit
+
+  * [SRU][Regression] Revert "PM: ACPI: reboot: Use S5 for reboot" which causes
+    Bus Fatal Error when rebooting system with BCM5720 NIC (LP: #1917471)
+    - Revert "PM: ACPI: reboot: Use S5 for reboot"
+
+  * Focal update: v5.4.181 upstream stable release (LP: #1967582)
+    - Makefile.extrawarn: Move -Wunaligned-access to W=1
+    - HID:Add support for UGTABLET WP5540
+    - Revert "svm: Add warning message for AVIC IPI invalid target"
+    - serial: parisc: GSC: fix build when IOSAPIC is not set
+    - parisc: Drop __init from map_pages declaration
+    - parisc: Fix data TLB miss in sba_unmap_sg
+    - parisc: Fix sglist access in ccio-dma.c
+    - btrfs: send: in case of IO error log it
+    - platform/x86: ISST: Fix possible circular locking dependency detected
+    - selftests: rtc: Increase test timeout so that all tests run
+    - net: ieee802154: at86rf230: Stop leaking skb's
+    - selftests/zram: Skip max_comp_streams interface on newer kernel
+    - selftests/zram01.sh: Fix compression ratio calculation
+    - selftests/zram: Adapt the situation that /dev/zram0 is being used
+    - ax25: improve the incomplete fix to avoid UAF and NPD bugs
+    - vfs: make freeze_super abort when sync_filesystem returns error
+    - quota: make dquot_quota_sync return errors from ->sync_fs
+    - nvme: fix a possible use-after-free in controller reset during load
+    - nvme-tcp: fix possible use-after-free in transport error_recovery work
+    - nvme-rdma: fix possible use-after-free in transport error_recovery work
+    - drm/amdgpu: fix logic inversion in check
+    - Revert "module, async: async_synchronize_full() on module init iff async is
+      used"
+    - ftrace: add ftrace_init_nop()
+    - module/ftrace: handle patchable-function-entry
+    - arm64: module: rework special section handling
+    - arm64: module/ftrace: intialize PLT at load time
+    - iwlwifi: fix use-after-free
+    - drm/radeon: Fix backlight control on iMac 12,1
+    - ext4: check for out-of-order index extents in ext4_valid_extent_entries()
+    - ext4: check for inconsistent extents between index and leaf block
+    - ext4: prevent partial update of the extent blocks
+    - taskstats: Cleanup the use of task->exit_code
+    - dmaengine: at_xdmac: Start transfer for cyclic channels in issue_pending
+    - vsock: remove vsock from connected table when connect is interrupted by a
+      signal
+    - mmc: block: fix read single on recovery logic
+    - iwlwifi: pcie: fix locking when "HW not ready"
+    - iwlwifi: pcie: gen2: fix locking when "HW not ready"
+    - netfilter: nft_synproxy: unregister hooks on init error path
+    - net: dsa: lan9303: fix reset on probe
+    - net: ieee802154: ca8210: Fix lifs/sifs periods
+    - ping: fix the dif and sdif check in ping_lookup
+    - bonding: force carrier update when releasing slave
+    - drop_monitor: fix data-race in dropmon_net_event / trace_napi_poll_hit
+    - bonding: fix data-races around agg_select_timer
+    - libsubcmd: Fix use-after-free for realloc(..., 0)
+    - ALSA: hda: Fix regression on forced probe mask option
+    - ALSA: hda: Fix missing codec probe on Shenker Dock 15
+    - ASoC: ops: Fix stereo change notifications in snd_soc_put_volsw()
+    - ASoC: ops: Fix stereo change notifications in snd_soc_put_volsw_range()
+    - powerpc/lib/sstep: fix 'ptesync' build error
+    - mtd: rawnand: gpmi: don't leak PM reference in error path
+    - block/wbt: fix negative inflight counter when remove scsi device
+    - NFS: LOOKUP_DIRECTORY is also ok with symlinks
+    - NFS: Do not report writeback errors in nfs_getattr()
+    - mtd: rawnand: qcom: Fix clock sequencing in qcom_nandc_probe()
+    - mtd: rawnand: brcmnand: Fixed incorrect sub-page ECC status
+    - scsi: lpfc: Fix pt2pt NVMe PRLI reject LOGO loop
+    - EDAC: Fix calculation of returned address and next offset in
+      edac_align_ptr()
+    - net: sched: limit TC_ACT_REPEAT loops
+    - dmaengine: sh: rcar-dmac: Check for error num after setting mask
+    - copy_process(): Move fd_install() out of sighand->siglock critical section
+    - i2c: brcmstb: fix support for DSL and CM variants
+    - Drivers: hv: vmbus: Fix memory leak in vmbus_add_channel_kobj
+    - KVM: x86/pmu: Use AMD64_RAW_EVENT_MASK for PERF_TYPE_RAW
+    - ARM: OMAP2+: hwmod: Add of_node_put() before break
+    - ARM: OMAP2+: adjust the location of put_device() call in omapdss_init_of
+    - irqchip/sifive-plic: Add missing thead,c900-plic match string
+    - netfilter: conntrack: don't refresh sctp entries in closed state
+    - arm64: dts: meson-gx: add ATF BL32 reserved-memory region
+    - arm64: dts: meson-g12: add ATF BL32 reserved-memory region
+    - arm64: dts: meson-g12: drop BL32 region from SEI510/SEI610
+    - kconfig: let 'shell' return enough output for deep path names
+    - ata: libata-core: Disable TRIM on M88V29
+    - drm/rockchip: dw_hdmi: Do not leave clock enabled in error case
+    - tracing: Fix tp_printk option related with tp_printk_stop_on_boot
+    - net: usb: qmi_wwan: Add support for Dell DW5829e
+    - net: macb: Align the dma and coherent dma masks
+    - kconfig: fix failing to generate auto.conf
+    - Linux 5.4.181
+
+  * Focal update: v5.4.180 upstream stable release (LP: #1966118)
+    - integrity: check the return value of audit_log_start()
+    - ima: Remove ima_policy file before directory
+    - ima: Allow template selection with ima_template[_fmt]= after ima_hash=
+    - ima: Do not print policy rule with inactive LSM labels
+    - mmc: sdhci-of-esdhc: Check for error num after setting mask
+    - net: phy: marvell: Fix RGMII Tx/Rx delays setting in 88e1121-compatible PHYs
+    - net: phy: marvell: Fix MDI-x polarity setting in 88e1118-compatible PHYs
+    - NFS: Fix initialisation of nfs_client cl_flags field
+    - NFSD: Clamp WRITE offsets
+    - NFSD: Fix offset type in I/O trace points
+    - NFSv4 only print the label when its queried
+    - nfs: nfs4clinet: check the return value of kstrdup()
+    - NFSv4.1: Fix uninitialised variable in devicenotify
+    - NFSv4 remove zero number of fs_locations entries error check
+    - NFSv4 expose nfs_parse_server_name function
+    - drm: panel-orientation-quirks: Add quirk for the 1Netbook OneXPlayer
+    - net: sched: Clarify error message when qdisc kind is unknown
+    - scsi: target: iscsi: Make sure the np under each tpg is unique
+    - scsi: qedf: Fix refcount issue when LOGO is received during TMF
+    - scsi: myrs: Fix crash in error case
+    - PM: hibernate: Remove register_nosave_region_late()
+    - usb: dwc2: gadget: don't try to disable ep0 in dwc2_hsotg_suspend
+    - net: stmmac: dwmac-sun8i: use return val of readl_poll_timeout()
+    - KVM: nVMX: eVMCS: Filter out VM_EXIT_SAVE_VMX_PREEMPTION_TIMER
+    - riscv: fix build with binutils 2.38
+    - ARM: dts: imx23-evk: Remove MX23_PAD_SSP1_DETECT from hog group
+    - ARM: socfpga: fix missing RESET_CONTROLLER
+    - nvme-tcp: fix bogus request completion when failing to send AER
+    - ACPI/IORT: Check node revision for PMCG resources
+    - PM: s2idle: ACPI: Fix wakeup interrupts handling
+    - net: bridge: fix stale eth hdr pointer in br_dev_xmit
+    - perf probe: Fix ppc64 'perf probe add events failed' case
+    - ARM: dts: meson: Fix the UART compatible strings
+    - staging: fbtft: Fix error path in fbtft_driver_module_init()
+    - ARM: dts: imx6qdl-udoo: Properly describe the SD card detect
+    - usb: f_fs: Fix use-after-free for epfile
+    - misc: fastrpc: avoid double fput() on failed usercopy
+    - ixgbevf: Require large buffers for build_skb on 82599VF
+    - bonding: pair enable_port with slave_arr_updates
+    - ipmr,ip6mr: acquire RTNL before calling ip[6]mr_free_table() on failure path
+    - nfp: flower: fix ida_idx not being released
+    - net: do not keep the dst cache when uncloning an skb dst and its metadata
+    - net: fix a memleak when uncloning an skb dst and its metadata
+    - veth: fix races around rq->rx_notify_masked
+    - net: mdio: aspeed: Add missing MODULE_DEVICE_TABLE
+    - tipc: rate limit warning for received illegal binding update
+    - net: amd-xgbe: disable interrupts during pci removal
+    - vt_ioctl: fix array_index_nospec in vt_setactivate
+    - vt_ioctl: add array_index_nospec to VT_ACTIVATE
+    - n_tty: wake up poll(POLLRDNORM) on receiving data
+    - eeprom: ee1004: limit i2c reads to I2C_SMBUS_BLOCK_MAX
+    - net: usb: ax88179_178a: Fix out-of-bounds accesses in RX fixup
+    - usb: ulpi: Move of_node_put to ulpi_dev_release
+    - usb: ulpi: Call of_node_put correctly
+    - usb: dwc3: gadget: Prevent core from processing stale TRBs
+    - usb: gadget: udc: renesas_usb3: Fix host to USB_ROLE_NONE transition
+    - USB: gadget: validate interface OS descriptor requests
+    - usb: gadget: rndis: check size of RNDIS_MSG_SET command
+    - usb: gadget: f_uac2: Define specific wTerminalType
+    - USB: serial: ftdi_sio: add support for Brainboxes US-159/235/320
+    - USB: serial: option: add ZTE MF286D modem
+    - USB: serial: ch341: add support for GW Instek USB2.0-Serial devices
+    - USB: serial: cp210x: add NCR Retail IO box id
+    - USB: serial: cp210x: add CPI Bulk Coin Recycler id
+    - seccomp: Invalidate seccomp mode to catch death failures
+    - hwmon: (dell-smm) Speed up setting of fan speed
+    - scsi: lpfc: Remove NVMe support if kernel has NVME_FC disabled
+    - perf: Fix list corruption in perf_cgroup_switch()
+    - Linux 5.4.180
+
+  * Focal update: v5.4.179 upstream stable release (LP: #1965591)
+    - moxart: fix potential use-after-free on remove path
+    - Linux 5.4.179
+
+  * CVE-2020-27820
+    - drm/nouveau: Add a dedicated mutex for the clients list
+    - drm/nouveau: clean up all clients on device removal
+
+  * CVE-2022-1016
+    - netfilter: nf_tables: initialize registers in nft_do_chain()
+
+  * CVE-2022-27223
+    - USB: gadget: validate endpoint index for xilinx udc
+
+  * CVE-2022-26490
+    - nfc: st21nfca: Fix potential buffer overflows in EVT_TRANSACTION
+
+  * CVE-2021-26401
+    - x86/speculation: Use generic retpoline by default on AMD
+    - x86/speculation: Update link to AMD speculation whitepaper
+    - x86/speculation: Warn about Spectre v2 LFENCE mitigation
+    - x86/speculation: Warn about eIBRS + LFENCE + Unprivileged eBPF + SMT
+
+  * CVE-2022-0001
+    - x86/speculation: Include unprivileged eBPF status in Spectre v2 mitigation
+      reporting
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Thu, 14 Apr 2022 14:19:29 +0200
+
+linux (5.4.0-109.123) focal; urgency=medium
+
+  * focal/linux: 5.4.0-109.123 -proposed tracker (LP: #1968290)
+
+  * USB devices not detected during boot on USB 3.0 hubs (LP: #1968210)
+    - SAUCE: Revert "Revert "xhci: Set HCD flag to defer primary roothub
+      registration""
+    - SAUCE: Revert "Revert "usb: core: hcd: Add support for deferring roothub
+      registration""
+
+ -- Kleber Sacilotto de Souza <kleber.souza@canonical.com>  Fri, 08 Apr 2022 10:44:46 +0200
+
+linux (5.4.0-108.122) focal; urgency=medium
+
+  * focal/linux: 5.4.0-108.122 -proposed tracker (LP: #1966740)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync dkms-build{,--nvidia-N} from LRMv5
+    - debian/dkms-versions -- update from kernel-versions (main/2022.03.21)
+
+  * Low RX performance for 40G Solarflare NICs (LP: #1964512)
+    - SAUCE: sfc: The size of the RX recycle ring should be more flexible
+
+  * [UBUNTU 20.04] KVM: Enable storage key checking for intercepted instruction
+    (LP: #1962831)
+    - selftests: kvm: add _vm_ioctl
+    - selftests: kvm: Introduce the TEST_FAIL macro
+    - KVM: selftests: Add GUEST_ASSERT variants to pass values to host
+    - KVM: s390: gaccess: Refactor gpa and length calculation
+    - KVM: s390: gaccess: Refactor access address range check
+    - KVM: s390: gaccess: Cleanup access to guest pages
+    - s390/uaccess: introduce bit field for OAC specifier
+    - s390/uaccess: fix compile error
+    - s390/uaccess: Add copy_from/to_user_key functions
+    - KVM: s390: Honor storage keys when accessing guest memory
+    - KVM: s390: handle_tprot: Honor storage keys
+    - KVM: s390: selftests: Test TEST PROTECTION emulation
+    - KVM: s390: Add optional storage key checking to MEMOP IOCTL
+    - KVM: s390: Add vm IOCTL for key checked guest absolute memory access
+    - KVM: s390: Rename existing vcpu memop functions
+    - KVM: s390: Add capability for storage key extension of MEM_OP IOCTL
+    - KVM: s390: Update api documentation for memop ioctl
+    - KVM: s390: Clarify key argument for MEM_OP in api docs
+    - KVM: s390: Add missing vm MEM_OP size check
+
+  * 【sec-0911】 fail to reset sec module (LP: #1943301)
+    - crypto: hisilicon/sec2 - Add workqueue for SEC driver.
+    - crypto: hisilicon/sec2 - update SEC initialization and reset
+
+  * Lots of hisi_qm zombie task slow down system after stress test
+    (LP: #1932117)
+    - crypto: hisilicon - Use one workqueue per qm instead of per qp
+
+  * Lots of hisi_qm zombie task slow down system after stress test
+    (LP: #1932117) // 【sec-0911】 fail to reset sec module (LP: #1943301)
+    - crypto: hisilicon - Unify hardware error init/uninit into QM
+
+  * [UBUNTU 20.04] Fix SIGP processing on KVM/s390 (LP: #1962578)
+    - KVM: s390: Simplify SIGP Set Arch handling
+    - KVM: s390: Add a routine for setting userspace CPU state
+
+  * Move virtual graphics drivers from linux-modules-extra to linux-modules
+    (LP: #1960633)
+    - [Packaging] Move VM DRM drivers into modules
+
+  * Focal update: v5.4.178 upstream stable release (LP: #1964634)
+    - audit: improve audit queue handling when "audit=1" on cmdline
+    - ASoC: ops: Reject out of bounds values in snd_soc_put_volsw()
+    - ASoC: ops: Reject out of bounds values in snd_soc_put_volsw_sx()
+    - ASoC: ops: Reject out of bounds values in snd_soc_put_xr_sx()
+    - ALSA: usb-audio: Simplify quirk entries with a macro
+    - ALSA: hda/realtek: Add quirk for ASUS GU603
+    - ALSA: hda/realtek: Add missing fixup-model entry for Gigabyte X570 ALC1220
+      quirks
+    - ALSA: hda/realtek: Fix silent output on Gigabyte X570S Aorus Master (newer
+      chipset)
+    - ALSA: hda/realtek: Fix silent output on Gigabyte X570 Aorus Xtreme after
+      reboot from Windows
+    - btrfs: fix deadlock between quota disable and qgroup rescan worker
+    - drm/nouveau: fix off by one in BIOS boundary checking
+    - mm/kmemleak: avoid scanning potential huge holes
+    - block: bio-integrity: Advance seed correctly for larger interval sizes
+    - memcg: charge fs_context and legacy_fs_context
+    - IB/rdmavt: Validate remote_addr during loopback atomic tests
+    - RDMA/siw: Fix broken RDMA Read Fence/Resume logic.
+    - RDMA/mlx4: Don't continue event handler after memory allocation failure
+    - iommu/vt-d: Fix potential memory leak in intel_setup_irq_remapping()
+    - iommu/amd: Fix loop timeout issue in iommu_ga_log_enable()
+    - spi: bcm-qspi: check for valid cs before applying chip select
+    - spi: mediatek: Avoid NULL pointer crash in interrupt
+    - spi: meson-spicc: add IRQ check in meson_spicc_probe
+    - net: ieee802154: hwsim: Ensure proper channel selection at probe time
+    - net: ieee802154: mcr20a: Fix lifs/sifs periods
+    - net: ieee802154: ca8210: Stop leaking skb's
+    - net: ieee802154: Return meaningful error codes from the netlink helpers
+    - net: macsec: Verify that send_sci is on when setting Tx sci explicitly
+    - net: stmmac: dump gmac4 DMA registers correctly
+    - net: stmmac: ensure PTP time register reads are consistent
+    - drm/i915/overlay: Prevent divide by zero bugs in scaling
+    - ASoC: fsl: Add missing error handling in pcm030_fabric_probe
+    - ASoC: xilinx: xlnx_formatter_pcm: Make buffer bytes multiple of period bytes
+    - ASoC: cpcap: Check for NULL pointer after calling of_get_child_by_name
+    - ASoC: max9759: fix underflow in speaker_gain_control_put()
+    - pinctrl: bcm2835: Fix a few error paths
+    - scsi: bnx2fc: Make bnx2fc_recv_frame() mp safe
+    - nfsd: nfsd4_setclientid_confirm mistakenly expires confirmed client.
+    - selftests: futex: Use variable MAKE instead of make
+    - rtc: cmos: Evaluate century appropriate
+    - EDAC/altera: Fix deferred probing
+    - EDAC/xgene: Fix deferred probing
+    - ext4: fix error handling in ext4_restore_inline_data()
+    - cgroup/cpuset: Fix "suspicious RCU usage" lockdep warning
+    - Linux 5.4.178
+
+  * Focal update: v5.4.177 upstream stable release (LP: #1964628)
+    - PCI: pciehp: Fix infinite loop in IRQ handler upon power fault
+    - psi: Fix uaf issue when psi trigger is destroyed while being polled
+    - ipheth: fix EOVERFLOW in ipheth_rcvbulk_callback
+    - net: amd-xgbe: ensure to reset the tx_timer_active flag
+    - net: amd-xgbe: Fix skb data length underflow
+    - rtnetlink: make sure to refresh master_dev/m_ops in __rtnl_newlink()
+    - cpuset: Fix the bug that subpart_cpus updated wrongly in update_cpumask()
+    - af_packet: fix data-race in packet_setsockopt / packet_setsockopt
+    - Linux 5.4.177
+
+  * Focal update: v5.4.176 upstream stable release (LP: #1962345)
+    - s390/hypfs: include z/VM guests with access control group set
+    - scsi: zfcp: Fix failed recovery on gone remote port with non-NPIV FCP
+      devices
+    - udf: Restore i_lenAlloc when inode expansion fails
+    - udf: Fix NULL ptr deref when converting from inline format
+    - PM: wakeup: simplify the output logic of pm_show_wakelocks()
+    - tracing/histogram: Fix a potential memory leak for kstrdup()
+    - tracing: Don't inc err_log entry count if entry allocation fails
+    - fsnotify: fix fsnotify hooks in pseudo filesystems
+    - drm/etnaviv: relax submit size limits
+    - arm64: errata: Fix exec handling in erratum 1418040 workaround
+    - netfilter: nft_payload: do not update layer 4 checksum when mangling
+      fragments
+    - serial: 8250: of: Fix mapped region size when using reg-offset property
+    - serial: stm32: fix software flow control transfer
+    - tty: n_gsm: fix SW flow control encoding/handling
+    - tty: Add support for Brainboxes UC cards.
+    - usb-storage: Add unusual-devs entry for VL817 USB-SATA bridge
+    - usb: common: ulpi: Fix crash in ulpi_match()
+    - usb: gadget: f_sourcesink: Fix isoc transfer for USB_SPEED_SUPER_PLUS
+    - USB: core: Fix hang in usb_kill_urb by adding memory barriers
+    - usb: typec: tcpm: Do not disconnect while receiving VBUS off
+    - ucsi_ccg: Check DEV_INT bit only when starting CCG4
+    - net: sfp: ignore disabled SFP node
+    - powerpc/32: Fix boot failure with GCC latent entropy plugin
+    - i40e: Increase delay to 1 s after global EMP reset
+    - i40e: Fix issue when maximum queues is exceeded
+    - i40e: Fix queues reservation for XDP
+    - i40e: fix unsigned stat widths
+    - rpmsg: char: Fix race between the release of rpmsg_ctrldev and cdev
+    - rpmsg: char: Fix race between the release of rpmsg_eptdev and cdev
+    - scsi: bnx2fc: Flush destroy_work queue before calling bnx2fc_interface_put()
+    - ipv6_tunnel: Rate limit warning messages
+    - net: fix information leakage in /proc/net/ptype
+    - hwmon: (lm90) Mark alert as broken for MAX6646/6647/6649
+    - hwmon: (lm90) Mark alert as broken for MAX6680
+    - ping: fix the sk_bound_dev_if match in ping_lookup
+    - ipv4: avoid using shared IP generator for connected sockets
+    - hwmon: (lm90) Reduce maximum conversion rate for G781
+    - NFSv4: Handle case where the lookup of a directory fails
+    - NFSv4: nfs_atomic_open() can race when looking up a non-regular file
+    - net-procfs: show net devices bound packet types
+    - drm/msm: Fix wrong size calculation
+    - drm/msm/dsi: Fix missing put_device() call in dsi_get_phy
+    - drm/msm/dsi: invalid parameter check in msm_dsi_phy_enable
+    - ipv6: annotate accesses to fn->fn_sernum
+    - NFS: Ensure the server has an up to date ctime before hardlinking
+    - NFS: Ensure the server has an up to date ctime before renaming
+    - netfilter: conntrack: don't increment invalid counter on NF_REPEAT
+    - net: phy: broadcom: hook up soft_reset for BCM54616S
+    - phylib: fix potential use-after-free
+    - rxrpc: Adjust retransmission backoff
+    - hwmon: (lm90) Mark alert as broken for MAX6654
+    - ibmvnic: init ->running_cap_crqs early
+    - ibmvnic: don't spin in tasklet
+    - drm/msm/hdmi: Fix missing put_device() call in msm_hdmi_get_phy
+    - yam: fix a memory leak in yam_siocdevprivate()
+    - net: hns3: handle empty unknown interrupt for VF
+    - ipv4: raw: lock the socket in raw_bind()
+    - ipv4: tcp: send zero IPID in SYNACK messages
+    - ipv4: remove sparse error in ip_neigh_gw4()
+    - dt-bindings: can: tcan4x5x: fix mram-cfg RX FIFO config
+    - fsnotify: invalidate dcache before IN_DELETE event
+    - block: Fix wrong offset in bio_truncate()
+    - mtd: rawnand: mpc5121: Remove unused variable in ads5121_select_chip()
+    - Linux 5.4.176
+
+  * Focal update: v5.4.175 upstream stable release (LP: #1962330)
+    - rcu: Tighten rcu_advance_cbs_nowake() checks
+    - pinctrl: bcm2835: Drop unused define
+    - pinctrl: bcm2835: Refactor platform data
+    - pinctrl: bcm2835: Add support for all GPIOs on BCM2711
+    - pinctrl: bcm2835: Match BCM7211 compatible string
+    - pinctrl: bcm2835: Add support for wake-up interrupts
+    - pinctrl: bcm2835: Change init order for gpio hogs
+    - ARM: dts: gpio-ranges property is now required
+    - mmc: sdhci-esdhc-imx: disable CMDQ support
+    - select: Fix indefinitely sleeping task in poll_schedule_timeout()
+    - Linux 5.4.175
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Tue, 29 Mar 2022 09:18:40 +0200
+
+linux (5.4.0-107.121) focal; urgency=medium
+
+  * focal/linux: 5.4.0-107.121 -proposed tracker (LP: #1966275)
+
+  * CVE-2022-27666
+    - esp: Fix possible buffer overflow in ESP transformation
+
+  * CVE-2022-1055
+    - net: sched: fix use-after-free in tc_new_tfilter()
+
+  * Pick fixup from v5.4.176 upstream stable release to address cert
+    failure with clock jitter test in NUC7i3DNHE (LP: #1964204)
+    - Bluetooth: refactor malicious adv data check
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Thu, 24 Mar 2022 16:48:48 +0100
+
+linux (5.4.0-105.119) focal; urgency=medium
+
+  * CVE-2022-0847
+    - lib/iov_iter: initialize "flags" in new pipe_buffer
+
+  * Broken network on some AWS instances with focal/impish kernels
+    (LP: #1961968)
+    - SAUCE: Revert "PCI/MSI: Mask MSI-X vectors only on success"
+
+  * [UBUNTU 20.04] kernel: Add support for CPU-MF counter second version 7
+    (LP: #1960182)
+    - s390/cpumf: Support for CPU Measurement Facility CSVN 7
+    - s390/cpumf: Support for CPU Measurement Sampling Facility LS bit
+
+  * Hipersocket page allocation failure on Ubuntu 20.04 based SSC environments
+    (LP: #1959529)
+    - s390/qeth: use memory reserves to back RX buffers
+
+  * CVE-2022-0516
+    - KVM: s390: Return error on SIDA memop on normal guest
+
+  * CVE-2022-0435
+    - tipc: improve size validations for received domain records
+
+  * CVE-2022-0492
+    - cgroup-v1: Require capabilities to set release_agent
+
+  * Recalled NFSv4 files delegations overwhelm server (LP: #1957986)
+    - NFSv4: Fix delegation handling in update_open_stateid()
+    - NFSv4: nfs4_callback_getattr() should ignore revoked delegations
+    - NFSv4: Delegation recalls should not find revoked delegations
+    - NFSv4: fail nfs4_refresh_delegation_stateid() when the delegation was
+      revoked
+    - NFS: Rename nfs_inode_return_delegation_noreclaim()
+    - NFSv4: Don't remove the delegation from the super_list more than once
+    - NFSv4: Hold the delegation spinlock when updating the seqid
+    - NFSv4: Clear the NFS_DELEGATION_REVOKED flag in
+      nfs_update_inplace_delegation()
+    - NFSv4: Update the stateid seqid in nfs_revoke_delegation()
+    - NFSv4: Revoke the delegation on success in nfs4_delegreturn_done()
+    - NFSv4: Ignore requests to return the delegation if it was revoked
+    - NFSv4: Don't reclaim delegations that have been returned or revoked
+    - NFSv4: nfs4_return_incompatible_delegation() should check delegation
+      validity
+    - NFSv4: Fix nfs4_inode_make_writeable()
+    - NFS: nfs_inode_find_state_and_recover() fix stateid matching
+    - NFSv4: Fix races between open and delegreturn
+    - NFSv4: Handle NFS4ERR_OLD_STATEID in delegreturn
+    - NFSv4: Don't retry the GETATTR on old stateid in nfs4_delegreturn_done()
+    - NFSv4: nfs_inode_evict_delegation() should set NFS_DELEGATION_RETURNING
+    - NFS: Clear NFS_DELEGATION_RETURN_IF_CLOSED when the delegation is returned
+    - NFSv4: Try to return the delegation immediately when marked for return on
+      close
+    - NFSv4: Add accounting for the number of active delegations held
+    - NFSv4: Limit the total number of cached delegations
+    - NFSv4: Ensure the delegation is pinned in nfs_do_return_delegation()
+    - NFSv4: Ensure the delegation cred is pinned when we call delegreturn
+
+  * Focal update: v5.4.174 upstream stable release (LP: #1960566)
+    - HID: uhid: Fix worker destroying device without any protection
+    - HID: wacom: Reset expected and received contact counts at the same time
+    - HID: wacom: Ignore the confidence flag when a touch is removed
+    - HID: wacom: Avoid using stale array indicies to read contact count
+    - f2fs: fix to do sanity check in is_alive()
+    - nfc: llcp: fix NULL error pointer dereference on sendmsg() after failed
+      bind()
+    - mtd: rawnand: gpmi: Add ERR007117 protection for nfc_apply_timings
+    - mtd: rawnand: gpmi: Remove explicit default gpmi clock setting for i.MX6
+    - x86/gpu: Reserve stolen memory for first integrated Intel GPU
+    - tools/nolibc: x86-64: Fix startup code bug
+    - tools/nolibc: i386: fix initial stack alignment
+    - tools/nolibc: fix incorrect truncation of exit code
+    - rtc: cmos: take rtc_lock while reading from CMOS
+    - media: v4l2-ioctl.c: readbuffers depends on V4L2_CAP_READWRITE
+    - media: flexcop-usb: fix control-message timeouts
+    - media: mceusb: fix control-message timeouts
+    - media: em28xx: fix control-message timeouts
+    - media: cpia2: fix control-message timeouts
+    - media: s2255: fix control-message timeouts
+    - media: dib0700: fix undefined behavior in tuner shutdown
+    - media: redrat3: fix control-message timeouts
+    - media: pvrusb2: fix control-message timeouts
+    - media: stk1160: fix control-message timeouts
+    - can: softing_cs: softingcs_probe(): fix memleak on registration failure
+    - lkdtm: Fix content of section containing lkdtm_rodata_do_nothing()
+    - iommu/io-pgtable-arm-v7s: Add error handle for page table allocation failure
+    - dma_fence_array: Fix PENDING_ERROR leak in dma_fence_array_signaled()
+    - PCI: Add function 1 DMA alias quirk for Marvell 88SE9125 SATA controller
+    - mm_zone: add function to check if managed dma zone exists
+    - mm/page_alloc.c: do not warn allocation failure on zone DMA if no managed
+      pages
+    - shmem: fix a race between shmem_unused_huge_shrink and shmem_evict_inode
+    - drm/rockchip: dsi: Hold pm-runtime across bind/unbind
+    - drm/rockchip: dsi: Reconfigure hardware on resume()
+    - drm/panel: kingdisplay-kd097d04: Delete panel on attach() failure
+    - drm/panel: innolux-p079zca: Delete panel on attach() failure
+    - drm/rockchip: dsi: Fix unbalanced clock on probe error
+    - Bluetooth: cmtp: fix possible panic when cmtp_init_sockets() fails
+    - clk: bcm-2835: Pick the closest clock rate
+    - clk: bcm-2835: Remove rounding up the dividers
+    - wcn36xx: Indicate beacon not connection loss on MISSED_BEACON_IND
+    - wcn36xx: Release DMA channel descriptor allocations
+    - media: videobuf2: Fix the size printk format
+    - media: aspeed: fix mode-detect always time out at 2nd run
+    - media: em28xx: fix memory leak in em28xx_init_dev
+    - media: aspeed: Update signal status immediately to ensure sane hw state
+    - arm64: dts: meson-gxbb-wetek: fix HDMI in early boot
+    - arm64: dts: meson-gxbb-wetek: fix missing GPIO binding
+    - Bluetooth: stop proccessing malicious adv data
+    - tee: fix put order in teedev_close_context()
+    - media: dmxdev: fix UAF when dvb_register_device() fails
+    - crypto: qce - fix uaf on qce_ahash_register_one
+    - arm64: dts: ti: k3-j721e: correct cache-sets info
+    - tty: serial: atmel: Check return code of dmaengine_submit()
+    - tty: serial: atmel: Call dma_async_issue_pending()
+    - media: rcar-csi2: Correct the selection of hsfreqrange
+    - media: imx-pxp: Initialize the spinlock prior to using it
+    - media: si470x-i2c: fix possible memory leak in si470x_i2c_probe()
+    - media: mtk-vcodec: call v4l2_m2m_ctx_release first when file is released
+    - media: venus: core: Fix a resource leak in the error handling path of
+      'venus_probe()'
+    - netfilter: bridge: add support for pppoe filtering
+    - arm64: dts: qcom: msm8916: fix MMC controller aliases
+    - ACPI: EC: Rework flushing of EC work while suspended to idle
+    - drm/amdgpu: Fix a NULL pointer dereference in
+      amdgpu_connector_lcd_native_mode()
+    - drm/radeon/radeon_kms: Fix a NULL pointer dereference in
+      radeon_driver_open_kms()
+    - arm64: dts: ti: k3-j721e: Fix the L2 cache sets
+    - tty: serial: uartlite: allow 64 bit address
+    - serial: amba-pl011: do not request memory region twice
+    - floppy: Fix hang in watchdog when disk is ejected
+    - staging: rtl8192e: return error code from rtllib_softmac_init()
+    - staging: rtl8192e: rtllib_module: fix error handle case in alloc_rtllib()
+    - Bluetooth: btmtksdio: fix resume failure
+    - media: dib8000: Fix a memleak in dib8000_init()
+    - media: saa7146: mxb: Fix a NULL pointer dereference in mxb_attach()
+    - media: si2157: Fix "warm" tuner state detection
+    - sched/rt: Try to restart rt period timer when rt runtime exceeded
+    - rcu/exp: Mark current CPU as exp-QS in IPI loop second pass
+    - mwifiex: Fix possible ABBA deadlock
+    - xfrm: fix a small bug in xfrm_sa_len()
+    - crypto: stm32/cryp - fix xts and race condition in crypto_engine requests
+    - crypto: stm32/cryp - fix double pm exit
+    - crypto: stm32/cryp - fix lrw chaining mode
+    - ARM: dts: gemini: NAS4220-B: fis-index-block with 128 KiB sectors
+    - media: dw2102: Fix use after free
+    - media: msi001: fix possible null-ptr-deref in msi001_probe()
+    - media: coda/imx-vdoa: Handle dma_set_coherent_mask error codes
+    - drm/msm/dpu: fix safe status debugfs file
+    - drm/bridge: ti-sn65dsi86: Set max register for regmap
+    - media: hantro: Fix probe func error path
+    - xfrm: interface with if_id 0 should return error
+    - xfrm: state and policy should fail if XFRMA_IF_ID 0
+    - ARM: 9159/1: decompressor: Avoid UNPREDICTABLE NOP encoding
+    - usb: ftdi-elan: fix memory leak on device disconnect
+    - ARM: dts: armada-38x: Add generic compatible to UART nodes
+    - mmc: meson-mx-sdio: add IRQ check
+    - selinux: fix potential memleak in selinux_add_opt()
+    - bpftool: Enable line buffering for stdout
+    - x86/mce/inject: Avoid out-of-bounds write when setting flags
+    - ACPI: scan: Create platform device for BCM4752 and LNV4752 ACPI nodes
+    - pcmcia: rsrc_nonstatic: Fix a NULL pointer dereference in
+      __nonstatic_find_io_region()
+    - pcmcia: rsrc_nonstatic: Fix a NULL pointer dereference in
+      nonstatic_find_mem_region()
+    - netfilter: ipt_CLUSTERIP: fix refcount leak in clusterip_tg_check()
+    - bpf: Fix SO_RCVBUF/SO_SNDBUF handling in _bpf_setsockopt().
+    - ppp: ensure minimum packet size in ppp_write()
+    - rocker: fix a sleeping in atomic bug
+    - staging: greybus: audio: Check null pointer
+    - fsl/fman: Check for null pointer after calling devm_ioremap
+    - Bluetooth: hci_bcm: Check for error irq
+    - HID: hid-uclogic-params: Invalid parameter check in uclogic_params_init
+    - HID: hid-uclogic-params: Invalid parameter check in
+      uclogic_params_get_str_desc
+    - HID: hid-uclogic-params: Invalid parameter check in
+      uclogic_params_huion_init
+    - HID: hid-uclogic-params: Invalid parameter check in
+      uclogic_params_frame_init_v1_buttonpad
+    - debugfs: lockdown: Allow reading debugfs files that are not world readable
+    - net/mlx5e: Don't block routes with nexthop objects in SW
+    - Revert "net/mlx5e: Block offload of outer header csum for UDP tunnels"
+    - net/mlx5: Set command entry semaphore up once got index free
+    - spi: spi-meson-spifc: Add missing pm_runtime_disable() in meson_spifc_probe
+    - tpm: add request_locality before write TPM_INT_ENABLE
+    - can: softing: softing_startstop(): fix set but not used variable warning
+    - can: xilinx_can: xcan_probe(): check for error irq
+    - pcmcia: fix setting of kthread task states
+    - net: mcs7830: handle usb read errors properly
+    - ext4: avoid trim error on fs with small groups
+    - ALSA: jack: Add missing rwsem around snd_ctl_remove() calls
+    - ALSA: PCM: Add missing rwsem around snd_ctl_remove() calls
+    - ALSA: hda: Add missing rwsem around snd_ctl_remove() calls
+    - RDMA/hns: Validate the pkey index
+    - clk: imx8mn: Fix imx8mn_clko1_sels
+    - powerpc/prom_init: Fix improper check of prom_getprop()
+    - ASoC: uniphier: drop selecting non-existing SND_SOC_UNIPHIER_AIO_DMA
+    - ALSA: oss: fix compile error when OSS_DEBUG is enabled
+    - char/mwave: Adjust io port register size
+    - binder: fix handling of error during copy
+    - iommu/io-pgtable-arm: Fix table descriptor paddr formatting
+    - scsi: ufs: Fix race conditions related to driver data
+    - PCI/MSI: Fix pci_irq_vector()/pci_irq_get_affinity()
+    - powerpc/powermac: Add additional missing lockdep_register_key()
+    - RDMA/core: Let ib_find_gid() continue search even after empty entry
+    - RDMA/cma: Let cma_resolve_ib_dev() continue search even after empty entry
+    - ASoC: rt5663: Handle device_property_read_u32_array error codes
+    - clk: stm32: Fix ltdc's clock turn off by clk_disable_unused() after system
+      enter shell
+    - dmaengine: pxa/mmp: stop referencing config->slave_id
+    - iommu/iova: Fix race between FQ timeout and teardown
+    - phy: uniphier-usb3ss: fix unintended writing zeros to PHY register
+    - ASoC: samsung: idma: Check of ioremap return value
+    - misc: lattice-ecp3-config: Fix task hung when firmware load failed
+    - mips: lantiq: add support for clk_set_parent()
+    - mips: bcm63xx: add support for clk_set_parent()
+    - RDMA/cxgb4: Set queue pair state when being queried
+    - of: base: Fix phandle argument length mismatch error message
+    - Bluetooth: Fix debugfs entry leak in hci_register_dev()
+    - fs: dlm: filter user dlm messages for kernel locks
+    - drm/lima: fix warning when CONFIG_DEBUG_SG=y & CONFIG_DMA_API_DEBUG=y
+    - ar5523: Fix null-ptr-deref with unexpected WDCMSG_TARGET_START reply
+    - drm/nouveau/pmu/gm200-: avoid touching PMU outside of DEVINIT/PREOS/ACR
+    - ARM: shmobile: rcar-gen2: Add missing of_node_put()
+    - batman-adv: allow netlink usage in unprivileged containers
+    - usb: gadget: f_fs: Use stream_open() for endpoint files
+    - drm: panel-orientation-quirks: Add quirk for the Lenovo Yoga Book X91F/L
+    - HID: apple: Do not reset quirks when the Fn key is not found
+    - media: b2c2: Add missing check in flexcop_pci_isr:
+    - EDAC/synopsys: Use the quirk for version instead of ddr version
+    - mlxsw: pci: Add shutdown method in PCI driver
+    - drm/bridge: megachips: Ensure both bridges are probed before registration
+    - gpiolib: acpi: Do not set the IRQ type if the IRQ is already in use
+    - HSI: core: Fix return freed object in hsi_new_client
+    - mwifiex: Fix skb_over_panic in mwifiex_usb_recv()
+    - rsi: Fix use-after-free in rsi_rx_done_handler()
+    - rsi: Fix out-of-bounds read in rsi_read_pkt()
+    - usb: uhci: add aspeed ast2600 uhci support
+    - floppy: Add max size check for user space request
+    - x86/mm: Flush global TLB when switching to trampoline page-table
+    - media: uvcvideo: Increase UVC_CTRL_CONTROL_TIMEOUT to 5 seconds.
+    - media: saa7146: hexium_orion: Fix a NULL pointer dereference in
+      hexium_attach()
+    - media: m920x: don't use stack on USB reads
+    - iwlwifi: mvm: synchronize with FW after multicast commands
+    - ath10k: Fix tx hanging
+    - net-sysfs: update the queue counts in the unregistration path
+    - net: phy: prefer 1000baseT over 1000baseKX
+    - gpio: aspeed: Convert aspeed_gpio.lock to raw_spinlock
+    - x86/mce: Mark mce_panic() noinstr
+    - x86/mce: Mark mce_end() noinstr
+    - x86/mce: Mark mce_read_aux() noinstr
+    - net: bonding: debug: avoid printing debug logs when bond is not notifying
+      peers
+    - bpf: Do not WARN in bpf_warn_invalid_xdp_action()
+    - HID: quirks: Allow inverting the absolute X/Y values
+    - media: igorplugusb: receiver overflow should be reported
+    - media: saa7146: hexium_gemini: Fix a NULL pointer dereference in
+      hexium_attach()
+    - mmc: core: Fixup storing of OCR for MMC_QUIRK_NONSTD_SDIO
+    - audit: ensure userspace is penalized the same as the kernel when under
+      pressure
+    - arm64: dts: ls1028a-qds: move rtc node to the correct i2c bus
+    - arm64: tegra: Adjust length of CCPLEX cluster MMIO region
+    - cpufreq: Fix initialization of min and max frequency QoS requests
+    - usb: hub: Add delay for SuperSpeed hub resume to let links transit to U0
+    - ath9k: Fix out-of-bound memcpy in ath9k_hif_usb_rx_stream
+    - iwlwifi: fix leaks/bad data after failed firmware load
+    - iwlwifi: remove module loading failure message
+    - iwlwifi: mvm: Fix calculation of frame length
+    - um: registers: Rename function names to avoid conflicts and build problems
+    - jffs2: GC deadlock reading a page that is used in jffs2_write_begin()
+    - ACPICA: actypes.h: Expand the ACPI_ACCESS_ definitions
+    - ACPICA: Utilities: Avoid deleting the same object twice in a row
+    - ACPICA: Executer: Fix the REFCLASS_REFOF case in acpi_ex_opcode_1A_0T_1R()
+    - ACPICA: Fix wrong interpretation of PCC address
+    - ACPICA: Hardware: Do not flush CPU cache when entering S4 and S5
+    - drm/amdgpu: fixup bad vram size on gmc v8
+    - ACPI: battery: Add the ThinkPad "Not Charging" quirk
+    - btrfs: remove BUG_ON() in find_parent_nodes()
+    - btrfs: remove BUG_ON(!eie) in find_parent_nodes
+    - net: mdio: Demote probed message to debug print
+    - mac80211: allow non-standard VHT MCS-10/11
+    - dm btree: add a defensive bounds check to insert_at()
+    - dm space map common: add bounds check to sm_ll_lookup_bitmap()
+    - net: phy: marvell: configure RGMII delays for 88E1118
+    - net: gemini: allow any RGMII interface mode
+    - regulator: qcom_smd: Align probe function with rpmh-regulator
+    - serial: pl010: Drop CR register reset on set_termios
+    - serial: core: Keep mctrl register state and cached copy in sync
+    - random: do not throw away excess input to crng_fast_load
+    - parisc: Avoid calling faulthandler_disabled() twice
+    - powerpc/6xx: add missing of_node_put
+    - powerpc/powernv: add missing of_node_put
+    - powerpc/cell: add missing of_node_put
+    - powerpc/btext: add missing of_node_put
+    - powerpc/watchdog: Fix missed watchdog reset due to memory ordering race
+    - i2c: i801: Don't silently correct invalid transfer size
+    - powerpc/smp: Move setup_profiling_timer() under CONFIG_PROFILING
+    - i2c: mpc: Correct I2C reset procedure
+    - clk: meson: gxbb: Fix the SDM_EN bit for MPLL0 on GXBB
+    - powerpc/powermac: Add missing lockdep_register_key()
+    - KVM: PPC: Book3S: Suppress failed alloc warning in H_COPY_TOFROM_GUEST
+    - w1: Misuse of get_user()/put_user() reported by sparse
+    - scsi: lpfc: Trigger SLI4 firmware dump before doing driver cleanup
+    - ALSA: seq: Set upper limit of processed events
+    - powerpc: handle kdump appropriately with crash_kexec_post_notifiers option
+    - MIPS: OCTEON: add put_device() after of_find_device_by_node()
+    - i2c: designware-pci: Fix to change data types of hcnt and lcnt parameters
+    - MIPS: Octeon: Fix build errors using clang
+    - scsi: sr: Don't use GFP_DMA
+    - ASoC: mediatek: mt8173: fix device_node leak
+    - power: bq25890: Enable continuous conversion for ADC at charging
+    - rpmsg: core: Clean up resources on announce_create failure.
+    - crypto: omap-aes - Fix broken pm_runtime_and_get() usage
+    - crypto: stm32/crc32 - Fix kernel BUG triggered in probe()
+    - crypto: caam - replace this_cpu_ptr with raw_cpu_ptr
+    - ubifs: Error path in ubifs_remount_rw() seems to wrongly free write buffers
+    - fuse: Pass correct lend value to filemap_write_and_wait_range()
+    - serial: Fix incorrect rs485 polarity on uart open
+    - cputime, cpuacct: Include guest time in user time in cpuacct.stat
+    - tracing/kprobes: 'nmissed' not showed correctly for kretprobe
+    - iwlwifi: mvm: Increase the scan timeout guard to 30 seconds
+    - s390/mm: fix 2KB pgtable release race
+    - drm/etnaviv: limit submit sizes
+    - drm/nouveau/kms/nv04: use vzalloc for nv04_display
+    - drm/bridge: analogix_dp: Make PSR-exit block less
+    - PCI: pci-bridge-emul: Properly mark reserved PCIe bits in PCI config space
+    - PCI: pci-bridge-emul: Correctly set PCIe capabilities
+    - PCI: pci-bridge-emul: Set PCI_STATUS_CAP_LIST for PCIe device
+    - xfrm: fix policy lookup for ipv6 gre packets
+    - btrfs: fix deadlock between quota enable and other quota operations
+    - btrfs: check the root node for uptodate before returning it
+    - btrfs: respect the max size in the header when activating swap file
+    - ext4: make sure to reset inode lockdep class when quota enabling fails
+    - ext4: make sure quota gets properly shutdown on error
+    - ext4: set csum seed in tmp inode while migrating to extents
+    - ext4: Fix BUG_ON in ext4_bread when write quota data
+    - ext4: don't use the orphan list when migrating an inode
+    - drm/radeon: fix error handling in radeon_driver_open_kms
+    - of: base: Improve argument length mismatch error
+    - firmware: Update Kconfig help text for Google firmware
+    - media: rcar-csi2: Optimize the selection PHTW register
+    - Documentation: dmaengine: Correctly describe dmatest with channel unset
+    - Documentation: ACPI: Fix data node reference documentation
+    - Documentation: refer to config RANDOMIZE_BASE for kernel address-space
+      randomization
+    - Documentation: fix firewire.rst ABI file path error
+    - scsi: core: Show SCMD_LAST in text form
+    - RDMA/hns: Modify the mapping attribute of doorbell to device
+    - RDMA/rxe: Fix a typo in opcode name
+    - dmaengine: stm32-mdma: fix STM32_MDMA_CTBR_TSEL_MASK
+    - Revert "net/mlx5: Add retry mechanism to the command entry index allocation"
+    - powerpc/cell: Fix clang -Wimplicit-fallthrough warning
+    - powerpc/fsl/dts: Enable WA for erratum A-009885 on fman3l MDIO buses
+    - bpftool: Remove inclusion of utilities.mak from Makefiles
+    - ipv4: avoid quadratic behavior in netns dismantle
+    - net/fsl: xgmac_mdio: Fix incorrect iounmap when removing module
+    - parisc: pdc_stable: Fix memory leak in pdcs_register_pathentries
+    - f2fs: fix to reserve space for IO align feature
+    - af_unix: annote lockless accesses to unix_tot_inflight & gc_in_progress
+    - clk: si5341: Fix clock HW provider cleanup
+    - net: axienet: limit minimum TX ring size
+    - net: axienet: fix number of TX ring slots for available check
+    - net: axienet: increase default TX ring size to 128
+    - rtc: pxa: fix null pointer dereference
+    - inet: frags: annotate races around fqdir->dead and fqdir->high_thresh
+    - netns: add schedule point in ops_exit_list()
+    - xfrm: Don't accidentally set RTO_ONLINK in decode_session4()
+    - gre: Don't accidentally set RTO_ONLINK in gre_fill_metadata_dst()
+    - libcxgb: Don't accidentally set RTO_ONLINK in cxgb_find_route()
+    - perf script: Fix hex dump character output
+    - dmaengine: at_xdmac: Don't start transactions at tx_submit level
+    - dmaengine: at_xdmac: Print debug message after realeasing the lock
+    - dmaengine: at_xdmac: Fix concurrency over xfers_list
+    - dmaengine: at_xdmac: Fix lld view setting
+    - dmaengine: at_xdmac: Fix at_xdmac_lld struct definition
+    - arm64: dts: qcom: msm8996: drop not documented adreno properties
+    - net_sched: restore "mpu xxx" handling
+    - bcmgenet: add WOL IRQ check
+    - net: ethernet: mtk_eth_soc: fix error checking in mtk_mac_config()
+    - dt-bindings: display: meson-dw-hdmi: add missing sound-name-prefix property
+    - dt-bindings: display: meson-vpu: Add missing amlogic,canvas property
+    - scripts/dtc: dtx_diff: remove broken example from help text
+    - lib82596: Fix IRQ check in sni_82596_probe
+    - lib/test_meminit: destroy cache in kmem_cache_alloc_bulk() test
+    - mtd: nand: bbt: Fix corner case in bad block table handling
+    - Revert "ia64: kprobes: Use generic kretprobe trampoline handler"
+    - Linux 5.4.174
+
+  * Focal update: v5.4.173 upstream stable release (LP: #1959701)
+    - kbuild: Add $(KBUILD_HOSTLDFLAGS) to 'has_libelf' test
+    - devtmpfs regression fix: reconfigure on each mount
+    - orangefs: Fix the size of a memory allocation in orangefs_bufmap_alloc()
+    - perf: Protect perf_guest_cbs with RCU
+    - KVM: s390: Clarify SIGP orders versus STOP/RESTART
+    - media: uvcvideo: fix division by zero at stream start
+    - rtlwifi: rtl8192cu: Fix WARNING when calling local_irq_restore() with
+      interrupts enabled
+    - firmware: qemu_fw_cfg: fix sysfs information leak
+    - firmware: qemu_fw_cfg: fix NULL-pointer deref on duplicate entries
+    - firmware: qemu_fw_cfg: fix kobject leak in probe error path
+    - KVM: x86: remove PMU FIXED_CTR3 from msrs_to_save_all
+    - ALSA: hda/realtek - Fix silent output on Gigabyte X570 Aorus Master after
+      reboot from Windows
+    - mtd: fixup CFI on ixp4xx
+    - ARM: 9025/1: Kconfig: CPU_BIG_ENDIAN depends on !LD_IS_LLD
+    - Linux 5.4.173
+
+  * Focal update: v5.4.172 upstream stable release (LP: #1959698)
+    - workqueue: Fix unbind_workers() VS wq_worker_running() race
+    - Bluetooth: btusb: fix memory leak in btusb_mtk_submit_wmt_recv_urb()
+    - Bluetooth: bfusb: fix division by zero in send path
+    - USB: core: Fix bug in resuming hub's handling of wakeup requests
+    - USB: Fix "slab-out-of-bounds Write" bug in usb_hcd_poll_rh_status
+    - mmc: sdhci-pci: Add PCI ID for Intel ADL
+    - veth: Do not record rx queue hint in veth_xmit
+    - mfd: intel-lpss: Fix too early PM enablement in the ACPI ->probe()
+    - drivers core: Use sysfs_emit and sysfs_emit_at for show(device *...)
+      functions
+    - can: gs_usb: fix use of uninitialized variable, detach device on reception
+      of invalid USB data
+    - can: gs_usb: gs_can_start_xmit(): zero-initialize hf->{flags,reserved}
+    - random: fix data race on crng_node_pool
+    - random: fix data race on crng init time
+    - random: fix crash on multiple early calls to add_bootloader_randomness()
+    - media: Revert "media: uvcvideo: Set unique vdev name based in type"
+    - staging: wlan-ng: Avoid bitwise vs logical OR warning in
+      hfa384x_usb_throttlefn()
+    - drm/i915: Avoid bitwise vs logical OR warning in snb_wm_latency_quirk()
+    - staging: greybus: fix stack size warning with UBSAN
+    - Linux 5.4.172
+
+  * Focal update: v5.4.171 upstream stable release (LP: #1959437)
+    - f2fs: quota: fix potential deadlock
+    - Input: touchscreen - Fix backport of
+      a02dcde595f7cbd240ccd64de96034ad91cffc40
+    - selftests: x86: fix [-Wstringop-overread] warn in test_process_vm_readv()
+    - tracing: Fix check for trace_percpu_buffer validity in get_trace_buf()
+    - tracing: Tag trace_percpu_buffer as a percpu pointer
+    - ieee802154: atusb: fix uninit value in atusb_set_extended_addr
+    - iavf: Fix limit of total number of queues to active queues of VF
+    - RDMA/core: Don't infoleak GRH fields
+    - RDMA/uverbs: Check for null return of kmalloc_array
+    - mac80211: initialize variable have_higher_than_11mbit
+    - i40e: fix use-after-free in i40e_sync_filters_subtask()
+    - i40e: Fix for displaying message regarding NVM version
+    - i40e: Fix incorrect netdev's real number of RX/TX queues
+    - ipv4: Check attribute length for RTA_GATEWAY in multipath route
+    - ipv4: Check attribute length for RTA_FLOW in multipath route
+    - ipv6: Check attribute length for RTA_GATEWAY in multipath route
+    - ipv6: Check attribute length for RTA_GATEWAY when deleting multipath route
+    - lwtunnel: Validate RTA_ENCAP_TYPE attribute length
+    - batman-adv: mcast: don't send link-local multicast to mcast routers
+    - sch_qfq: prevent shift-out-of-bounds in qfq_init_qdisc
+    - net: phy: micrel: set soft_reset callback to genphy_soft_reset for KSZ8081
+    - power: supply: core: Break capacity loop
+    - power: reset: ltc2952: Fix use of floating point literals
+    - rndis_host: support Hytera digital radios
+    - phonet: refcount leak in pep_sock_accep
+    - ipv6: Continue processing multipath route even if gateway attribute is
+      invalid
+    - ipv6: Do cleanup if attribute validation fails in multipath route
+    - usb: mtu3: fix interval value for intr and isoc
+    - scsi: libiscsi: Fix UAF in iscsi_conn_get_param()/iscsi_conn_teardown()
+    - ip6_vti: initialize __ip6_tnl_parm struct in vti6_siocdevprivate
+    - net: udp: fix alignment problem in udp4_seq_show()
+    - atlantic: Fix buff_ring OOB in aq_ring_rx_clean
+    - mISDN: change function names to avoid conflicts
+    - Linux 5.4.171
+
+  * Focal update: v5.4.170 upstream stable release (LP: #1958898)
+    - tee: handle lookup of shm with reference count 0
+    - Input: i8042 - add deferred probe support
+    - Input: i8042 - enable deferred probe quirk for ASUS UM325UA
+    - tomoyo: Check exceeded quota early in tomoyo_domain_quota_is_ok().
+    - platform/x86: apple-gmux: use resource_size() with res
+    - memblock: fix memblock_phys_alloc() section mismatch error
+    - recordmcount.pl: fix typo in s390 mcount regex
+    - selinux: initialize proto variable in selinux_ip_postroute_compat()
+    - scsi: lpfc: Terminate string in lpfc_debugfs_nvmeio_trc_write()
+    - net/mlx5: DR, Fix NULL vs IS_ERR checking in dr_domain_init_resources
+    - sctp: use call_rcu to free endpoint
+    - net: usb: pegasus: Do not drop long Ethernet frames
+    - net: lantiq_xrx200: fix statistics of received bytes
+    - NFC: st21nfca: Fix memory leak in device probe and remove
+    - ionic: Initialize the 'lif->dbid_inuse' bitmap
+    - net/mlx5e: Fix wrong features assignment in case of error
+    - selftests/net: udpgso_bench_tx: fix dst ip argument
+    - net/ncsi: check for error return from call to nla_put_u32
+    - fsl/fman: Fix missing put_device() call in fman_port_probe
+    - i2c: validate user data in compat ioctl
+    - nfc: uapi: use kernel size_t to fix user-space builds
+    - uapi: fix linux/nfc.h userspace compilation errors
+    - xhci: Fresco FL1100 controller should not have BROKEN_MSI quirk set.
+    - usb: gadget: f_fs: Clear ffs_eventfd in ffs_data_clear.
+    - usb: mtu3: add memory barrier before set GPD's HWO
+    - usb: mtu3: fix list_head check warning
+    - usb: mtu3: set interval of FS intr and isoc endpoint
+    - binder: fix async_free_space accounting for empty parcels
+    - scsi: vmw_pvscsi: Set residual data length conditionally
+    - Input: appletouch - initialize work before device registration
+    - Input: spaceball - fix parsing of movement data packets
+    - net: fix use-after-free in tw_timer_handler
+    - perf script: Fix CPU filtering of a script's switch events
+    - Linux 5.4.170
+
+  * Focal update: v5.4.170 upstream stable release (LP: #1958898) // HID_ASUS
+    should depend on USB_HID in stable v4.15 backports (LP: #1959762)
+    - HID: asus: Add depends on USB_HID to HID_ASUS Kconfig option
+
+  * Focal update: v5.4.169 upstream stable release (LP: #1958557)
+    - net: usb: lan78xx: add Allied Telesis AT29M2-AF
+    - serial: 8250_fintek: Fix garbled text for console
+    - arm64: dts: allwinner: orangepi-zero-plus: fix PHY mode
+    - spi: change clk_disable_unprepare to clk_unprepare
+    - IB/qib: Fix memory leak in qib_user_sdma_queue_pkts()
+    - netfilter: fix regression in looped (broad|multi)cast's MAC handling
+    - qlcnic: potential dereference null pointer of rx_queue->page_ring
+    - net: accept UFOv6 packages in virtio_net_hdr_to_skb
+    - net: skip virtio_net_hdr_set_proto if protocol already set
+    - ipmi: Fix UAF when uninstall ipmi_si and ipmi_msghandler module
+    - bonding: fix ad_actor_system option setting to default
+    - fjes: Check for error irq
+    - drivers: net: smc911x: Check for error irq
+    - sfc: falcon: Check null pointer of rx_queue->page_ring
+    - Input: elantech - fix stack out of bound access in
+      elantech_change_report_id()
+    - hwmon: (lm90) Fix usage of CONFIG2 register in detect function
+    - hwmon: (lm90) Add max6654 support to lm90 driver
+    - hwmon: (lm90) Add basic support for TI TMP461
+    - hwmon: (lm90) Introduce flag indicating extended temperature support
+    - hwmon: (lm90) Drop critical attribute support for MAX6654
+    - ALSA: jack: Check the return value of kstrdup()
+    - ALSA: drivers: opl3: Fix incorrect use of vp->state
+    - ALSA: hda/realtek: Amp init fixup for HP ZBook 15 G6
+    - Input: atmel_mxt_ts - fix double free in mxt_read_info_block
+    - ipmi: bail out if init_srcu_struct fails
+    - ipmi: ssif: initialize ssif_info->client early
+    - ipmi: fix initialization when workqueue allocation fails
+    - parisc: Correct completer in lws start
+    - x86/pkey: Fix undefined behaviour with PKRU_WD_BIT
+    - pinctrl: stm32: consider the GPIO offset to expose all the GPIO lines
+    - mmc: sdhci-tegra: Fix switch to HS400ES mode
+    - mmc: core: Disable card detect during shutdown
+    - ARM: 9169/1: entry: fix Thumb2 bug in iWMMXt exception handling
+    - tee: optee: Fix incorrect page free bug
+    - f2fs: fix to do sanity check on last xattr entry in __f2fs_setxattr()
+    - usb: gadget: u_ether: fix race in setting MAC address in setup phase
+    - KVM: VMX: Fix stale docs for kvm-intel.emulate_invalid_guest_state
+    - mm: mempolicy: fix THP allocations escaping mempolicy restrictions
+    - pinctrl: mediatek: fix global-out-of-bounds issue
+    - hwmom: (lm90) Fix citical alarm status for MAX6680/MAX6681
+    - hwmon: (lm90) Do not report 'busy' status bit as alarm
+    - ax25: NPD bug when detaching AX25 device
+    - hamradio: defer ax25 kfree after unregister_netdev
+    - hamradio: improve the incomplete fix to avoid NPD
+    - phonet/pep: refuse to enable an unbound pipe
+    - Linux 5.4.169
+
+  * Focal update: v5.4.168 upstream stable release (LP: #1957991)
+    - KVM: selftests: Make sure kvm_create_max_vcpus test won't hit RLIMIT_NOFILE
+    - mac80211: mark TX-during-stop for TX in in_reconfig
+    - mac80211: send ADDBA requests using the tid/queue of the aggregation session
+    - firmware: arm_scpi: Fix string overflow in SCPI genpd driver
+    - virtio_ring: Fix querying of maximum DMA mapping size for virtio device
+    - recordmcount.pl: look for jgnop instruction as well as bcrl on s390
+    - dm btree remove: fix use after free in rebalance_children()
+    - audit: improve robustness of the audit queue handling
+    - iio: adc: stm32: fix a current leak by resetting pcsel before disabling vdda
+    - nfsd: fix use-after-free due to delegation race
+    - arm64: dts: rockchip: remove mmc-hs400-enhanced-strobe from rk3399-khadas-
+      edge
+    - arm64: dts: rockchip: fix rk3399-leez-p710 vcc3v3-lan supply
+    - arm64: dts: rockchip: fix audio-supply for Rock Pi 4
+    - mac80211: track only QoS data frames for admission control
+    - ARM: socfpga: dts: fix qspi node compatible
+    - clk: Don't parent clks until the parent is fully registered
+    - selftests: net: Correct ping6 expected rc from 2 to 1
+    - s390/kexec_file: fix error handling when applying relocations
+    - sch_cake: do not call cake_destroy() from cake_init()
+    - inet_diag: use jiffies_delta_to_msecs()
+    - inet_diag: fix kernel-infoleak for UDP sockets
+    - selftests: Fix raw socket bind tests with VRF
+    - selftests: Fix IPv6 address bind tests
+    - dmaengine: st_fdma: fix MODULE_ALIAS
+    - selftest/net/forwarding: declare NETIFS p9 p10
+    - mac80211: agg-tx: refactor sending addba
+    - mac80211: agg-tx: don't schedule_and_wake_txq() under sta->lock
+    - mac80211: accept aggregation sessions on 6 GHz
+    - mac80211: fix lookup when adding AddBA extension element
+    - net: sched: lock action when translating it to flow_action infra
+    - flow_offload: return EOPNOTSUPP for the unsupported mpls action type
+    - rds: memory leak in __rds_conn_create()
+    - soc/tegra: fuse: Fix bitwise vs. logical OR warning
+    - igb: Fix removal of unicast MAC filters of VFs
+    - igbvf: fix double free in `igbvf_probe`
+    - ixgbe: set X550 MDIO speed before talking to PHY
+    - netdevsim: Zero-initialize memory for new map's value in function
+      nsim_bpf_map_alloc
+    - net: Fix double 0x prefix print in SKB dump
+    - net/smc: Prevent smc_release() from long blocking
+    - net: systemport: Add global locking for descriptor lifecycle
+    - sit: do not call ipip6_dev_free() from sit_init_net()
+    - USB: NO_LPM quirk Lenovo USB-C to Ethernet Adapher(RTL8153-04)
+    - PCI/MSI: Clear PCI_MSIX_FLAGS_MASKALL on error
+    - PCI/MSI: Mask MSI-X vectors only on success
+    - usb: xhci: Extend support for runtime power management for AMD's Yellow
+      carp.
+    - USB: serial: cp210x: fix CP2105 GPIO registration
+    - USB: serial: option: add Telit FN990 compositions
+    - timekeeping: Really make sure wall_to_monotonic isn't positive
+    - libata: if T_LENGTH is zero, dma direction should be DMA_NONE
+    - drm/amdgpu: correct register access for RLC_JUMP_TABLE_RESTORE
+    - mac80211: validate extended element ID is present
+    - mwifiex: Remove unnecessary braces from HostCmd_SET_SEQ_NO_BSS_INFO
+    - Input: touchscreen - avoid bitwise vs logical OR warning
+    - ARM: dts: imx6ull-pinfunc: Fix CSI_DATA07__ESAI_TX0 pad name
+    - xsk: Do not sleep in poll() when need_wakeup set
+    - media: mxl111sf: change mutex_init() location
+    - fuse: annotate lock in fuse_reverse_inval_entry()
+    - ovl: fix warning in ovl_create_real()
+    - scsi: scsi_debug: Sanity check block descriptor length in resp_mode_select()
+    - rcu: Mark accesses to rcu_state.n_force_qs
+    - mac80211: fix regression in SSN handling of addba tx
+    - net: sched: Fix suspicious RCU usage while accessing tcf_tunnel_info
+    - Revert "xsk: Do not sleep in poll() when need_wakeup set"
+    - xen/blkfront: harden blkfront against event channel storms
+    - xen/netfront: harden netfront against event channel storms
+    - xen/console: harden hvc_xen against event channel storms
+    - xen/netback: fix rx queue stall detection
+    - xen/netback: don't queue unlimited number of packages
+    - Linux 5.4.168
+
+  * Focal update: v5.4.167 upstream stable release (LP: #1957987)
+    - nfc: fix segfault in nfc_genl_dump_devices_done
+    - drm/msm/dsi: set default num_data_lanes
+    - net/mlx4_en: Update reported link modes for 1/10G
+    - parisc/agp: Annotate parisc agp init functions with __init
+    - i2c: rk3x: Handle a spurious start completion interrupt flag
+    - net: netlink: af_netlink: Prevent empty skb by adding a check on len.
+    - drm/amd/display: Fix for the no Audio bug with Tiled Displays
+    - drm/amd/display: add connector type check for CRC source set
+    - tracing: Fix a kmemleak false positive in tracing_map
+    - KVM: x86: Ignore sparse banks size for an "all CPUs", non-sparse IPI req
+    - selinux: fix race condition when computing ocontext SIDs
+    - bpf: Fix integer overflow in argument calculation for bpf_map_area_alloc
+    - hwmon: (dell-smm) Fix warning on /proc/i8k creation error
+    - memblock: free_unused_memmap: use pageblock units instead of MAX_ORDER
+    - memblock: align freed memory map on pageblock boundaries with SPARSEMEM
+    - memblock: ensure there is no overflow in memblock_overlaps_region()
+    - arm: extend pfn_valid to take into account freed memory map alignment
+    - arm: ioremap: don't abuse pfn_valid() to check if pfn is in RAM
+    - Linux 5.4.167
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync getabis
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Mon, 07 Mar 2022 17:07:14 +0100
+
+linux (5.4.0-104.118) focal; urgency=medium
+
+  * CVE-2022-23960
+    - SAUCE: kvm: arm: fix build on 32-bit
+
+ -- Thadeu Lima de Souza Cascardo <cascardo@canonical.com>  Wed, 02 Mar 2022 14:10:18 -0300
+
+linux (5.4.0-103.117) focal; urgency=medium
+
+  * CVE-2022-23960
+    - arm64: Add part number for Arm Cortex-A77
+    - arm64: Add Neoverse-N2, Cortex-A710 CPU part definition
+    - arm64: Add Cortex-X2 CPU part definition
+    - arm64: add ID_AA64ISAR2_EL1 sys register
+    - SAUCE: arm64: entry.S: Add ventry overflow sanity checks
+    - SAUCE: arm64: entry: Make the trampoline cleanup optional
+    - SAUCE: arm64: entry: Free up another register on kpti's tramp_exit path
+    - SAUCE: arm64: entry: Move the trampoline data page before the text page
+    - SAUCE: arm64: entry: Allow tramp_alias to access symbols after the 4K
+      boundary
+    - SAUCE: arm64: entry: Don't assume tramp_vectors is the start of the vectors
+    - SAUCE: arm64: entry: Move trampoline macros out of ifdef'd section
+    - SAUCE: arm64: entry: Make the kpti trampoline's kpti sequence optional
+    - SAUCE: arm64: entry: Allow the trampoline text to occupy multiple pages
+    - SAUCE: arm64: entry: Add non-kpti __bp_harden_el1_vectors for mitigations
+    - SAUCE: arm64: entry: Add vectors that have the bhb mitigation sequences
+    - SAUCE: arm64: entry: Add macro for reading symbol addresses from the
+      trampoline
+    - SAUCE: arm64: Add percpu vectors for EL1
+    - SAUCE: arm64: proton-pack: Report Spectre-BHB vulnerabilities as part of
+      Spectre-v2
+    - SAUCE: KVM: arm64: Add templates for BHB mitigation sequences
+    - SAUCE: arm64: Mitigate spectre style branch history side channels
+    - SAUCE: KVM: arm64: Allow SMCCC_ARCH_WORKAROUND_3 to be discovered and
+      migrated
+    - SAUCE: arm64: Use the clearbhb instruction in mitigations
+    - [Config]: set CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY=y
+
+  * CVE-2022-25636
+    - netfilter: nf_tables_offload: incorrect flow offload action array size
+
+  * CVE-2022-0001
+    - x86/speculation: Merge one test in spectre_v2_user_select_mitigation()
+    - x86,bugs: Unconditionally allow spectre_v2=retpoline,amd
+    - SAUCE: x86/speculation: Rename RETPOLINE_AMD to RETPOLINE_LFENCE
+    - SAUCE: x86/speculation: Add eIBRS + Retpoline options
+    - SAUCE: Documentation/hw-vuln: Update spectre doc
+
+  * Disable unprivileged BPF by default (LP: #1961338)
+    - bpf: Add kconfig knob for disabling unpriv bpf by default
+    - [Config] set CONFIG_BPF_UNPRIV_DEFAULT_OFF=y
+
+ -- Thadeu Lima de Souza Cascardo <cascardo@canonical.com>  Wed, 02 Mar 2022 05:33:12 -0300
+
+linux (5.4.0-100.113) focal; urgency=medium
+
+  * focal/linux: 5.4.0-100.113 -proposed tracker (LP: #1959900)
+
+  * CVE-2022-22942
+    - SAUCE: drm/vmwgfx: Fix stale file descriptors on failed usercopy
+
+  * CVE-2022-0330
+    - drm/i915: Flush TLBs before releasing backing store
+
+  * Focal update: v5.4.166 upstream stable release (LP: #1957008)
+    - netfilter: selftest: conntrack_vrf.sh: fix file permission
+    - Linux 5.4.166
+    - net/packet: rx_owner_map depends on pg_vec
+    - USB: gadget: bRequestType is a bitfield, not a enum
+    - HID: holtek: fix mouse probing
+    - udp: using datalen to cap ipv6 udp max gso segments
+    - selftests: Calculate udpgso segment count without header adjustment
+
+  * Focal update: v5.4.165 upstream stable release (LP: #1957007)
+    - serial: tegra: Change lower tolerance baud rate limit for tegra20 and
+      tegra30
+    - ntfs: fix ntfs_test_inode and ntfs_init_locked_inode function type
+    - HID: quirks: Add quirk for the Microsoft Surface 3 type-cover
+    - HID: google: add eel USB id
+    - HID: add hid_is_usb() function to make it simpler for USB detection
+    - HID: add USB_HID dependancy to hid-prodikeys
+    - HID: add USB_HID dependancy to hid-chicony
+    - HID: add USB_HID dependancy on some USB HID drivers
+    - HID: bigbenff: prevent null pointer dereference
+    - HID: wacom: fix problems when device is not a valid USB device
+    - HID: check for valid USB device for many HID drivers
+    - can: kvaser_usb: get CAN clock frequency from device
+    - can: kvaser_pciefd: kvaser_pciefd_rx_error_frame(): increase correct
+      stats->{rx,tx}_errors counter
+    - can: sja1000: fix use after free in ems_pcmcia_add_card()
+    - nfc: fix potential NULL pointer deref in nfc_genl_dump_ses_done
+    - selftests: netfilter: add a vrf+conntrack testcase
+    - vrf: don't run conntrack on vrf with !dflt qdisc
+    - bpf: Fix the off-by-two error in range markings
+    - ice: ignore dropped packets during init
+    - bonding: make tx_rebalance_counter an atomic
+    - nfp: Fix memory leak in nfp_cpp_area_cache_add()
+    - seg6: fix the iif in the IPv6 socket control block
+    - udp: using datalen to cap max gso segments
+    - iavf: restore MSI state on reset
+    - iavf: Fix reporting when setting descriptor count
+    - IB/hfi1: Correct guard on eager buffer deallocation
+    - mm: bdi: initialize bdi_min_ratio when bdi is unregistered
+    - ALSA: ctl: Fix copy of updated id with element read/write
+    - ALSA: hda/realtek - Add headset Mic support for Lenovo ALC897 platform
+    - ALSA: pcm: oss: Fix negative period/buffer sizes
+    - ALSA: pcm: oss: Limit the period size to 16MB
+    - ALSA: pcm: oss: Handle missing errors in snd_pcm_oss_change_params*()
+    - btrfs: clear extent buffer uptodate when we fail to write it
+    - btrfs: replace the BUG_ON in btrfs_del_root_ref with proper error handling
+    - nfsd: Fix nsfd startup race (again)
+    - tracefs: Have new files inherit the ownership of their parent
+    - clk: qcom: regmap-mux: fix parent clock lookup
+    - drm/syncobj: Deal with signalled fences in drm_syncobj_find_fence.
+    - can: pch_can: pch_can_rx_normal: fix use after free
+    - can: m_can: Disable and ignore ELO interrupt
+    - x86/sme: Explicitly map new EFI memmap table as encrypted
+    - libata: add horkage for ASMedia 1092
+    - wait: add wake_up_pollfree()
+    - SAUCE: binder: export __wake_up_pollfree for binder module
+    - binder: use wake_up_pollfree()
+    - signalfd: use wake_up_pollfree()
+    - aio: keep poll requests on waitqueue until completed
+    - aio: fix use-after-free due to missing POLLFREE handling
+    - tracefs: Set all files to the same group ownership as the mount option
+    - block: fix ioprio_get(IOPRIO_WHO_PGRP) vs setuid(2)
+    - qede: validate non LSO skb length
+    - ASoC: qdsp6: q6routing: Fix return value from msm_routing_put_audio_mixer
+    - i40e: Fix failed opcode appearing if handling messages from VF
+    - i40e: Fix pre-set max number of queues for VF
+    - mtd: rawnand: fsmc: Take instruction delay into account
+    - mtd: rawnand: fsmc: Fix timing computation
+    - dt-bindings: net: Reintroduce PHY no lane swap binding
+    - tools build: Remove needless libpython-version feature check that breaks
+      test-all fast path
+    - net: cdc_ncm: Allow for dwNtbOutMaxSize to be unset or zero
+    - net: altera: set a couple error code in probe()
+    - net: fec: only clear interrupt of handling queue in fec_enet_rx_queue()
+    - net, neigh: clear whole pneigh_entry at alloc time
+    - net/qla3xxx: fix an error code in ql_adapter_up()
+    - Revert "UBUNTU: SAUCE: selftests: fib_tests: assign address to dummy1 for
+      rp_filter tests"
+    - selftests/fib_tests: Rework fib_rp_filter_test()
+    - USB: gadget: detect too-big endpoint 0 requests
+    - USB: gadget: zero allocate endpoint 0 buffers
+    - usb: core: config: fix validation of wMaxPacketValue entries
+    - xhci: Remove CONFIG_USB_DEFAULT_PERSIST to prevent xHCI from runtime
+      suspending
+    - usb: core: config: using bit mask instead of individual bits
+    - xhci: avoid race between disable slot command and host runtime suspend
+    - iio: trigger: Fix reference counting
+    - iio: trigger: stm32-timer: fix MODULE_ALIAS
+    - iio: stk3310: Don't return error code in interrupt handler
+    - iio: mma8452: Fix trigger reference couting
+    - iio: ltr501: Don't return error code in trigger handler
+    - iio: kxsd9: Don't return error code in trigger handler
+    - iio: itg3200: Call iio_trigger_notify_done() on error
+    - iio: dln2-adc: Fix lockdep complaint
+    - iio: dln2: Check return value of devm_iio_trigger_register()
+    - iio: at91-sama5d2: Fix incorrect sign extension
+    - iio: adc: axp20x_adc: fix charging current reporting on AXP22x
+    - iio: ad7768-1: Call iio_trigger_notify_done() on error
+    - iio: accel: kxcjk-1013: Fix possible memory leak in probe and remove
+    - irqchip/armada-370-xp: Fix return value of armada_370_xp_msi_alloc()
+    - irqchip/armada-370-xp: Fix support for Multi-MSI interrupts
+    - irqchip/irq-gic-v3-its.c: Force synchronisation when issuing INVALL
+    - irqchip: nvic: Fix offset for Interrupt Priority Offsets
+    - misc: fastrpc: fix improper packet size calculation
+    - bpf: Add selftests to cover packet access corner cases
+    - Linux 5.4.165
+
+  * Focal update: v5.4.164 upstream stable release (LP: #1956381)
+    - NFSv42: Fix pagecache invalidation after COPY/CLONE
+    - of: clk: Make <linux/of_clk.h> self-contained
+    - arm64: dts: mcbin: support 2W SFP modules
+    - can: j1939: j1939_tp_cmd_recv(): check the dst address of TP.CM_BAM
+    - gfs2: Fix length of holes reported at end-of-file
+    - drm/sun4i: fix unmet dependency on RESET_CONTROLLER for PHY_SUN6I_MIPI_DPHY
+    - mac80211: do not access the IV when it was stripped
+    - net/smc: Transfer remaining wait queue entries during fallback
+    - atlantic: Fix OOB read and write in hw_atl_utils_fw_rpc_wait
+    - net: return correct error code
+    - platform/x86: thinkpad_acpi: Fix WWAN device disabled issue after S3 deep
+    - s390/setup: avoid using memblock_enforce_memory_limit
+    - btrfs: check-integrity: fix a warning on write caching disabled disk
+    - thermal: core: Reset previous low and high trip during thermal zone init
+    - scsi: iscsi: Unblock session then wake up error handler
+    - ata: ahci: Add Green Sardine vendor ID as board_ahci_mobile
+    - ethernet: hisilicon: hns: hns_dsaf_misc: fix a possible array overflow in
+      hns_dsaf_ge_srst_by_port()
+    - net: tulip: de4x5: fix the problem that the array 'lp->phy[8]' may be out of
+      bound
+    - net: ethernet: dec: tulip: de4x5: fix possible array overflows in
+      type3_infoblock()
+    - perf hist: Fix memory leak of a perf_hpp_fmt
+    - perf report: Fix memory leaks around perf_tip()
+    - net/smc: Avoid warning of possible recursive locking
+    - vrf: Reset IPCB/IP6CB when processing outbound pkts in vrf dev xmit
+    - kprobes: Limit max data_size of the kretprobe instances
+    - rt2x00: do not mark device gone on EPROTO errors during start
+    - cpufreq: Fix get_cpu_device() failure in add_cpu_dev_symlink()
+    - s390/pci: move pseudo-MMIO to prevent MIO overlap
+    - sata_fsl: fix UAF in sata_fsl_port_stop when rmmod sata_fsl
+    - sata_fsl: fix warning in remove_proc_entry when rmmod sata_fsl
+    - i2c: stm32f7: flush TX FIFO upon transfer errors
+    - i2c: stm32f7: recover the bus on access timeout
+    - i2c: stm32f7: stop dma transfer in case of NACK
+    - i2c: cbus-gpio: set atomic transfer callback
+    - natsemi: xtensa: fix section mismatch warnings
+    - net: qlogic: qlcnic: Fix a NULL pointer dereference in
+      qlcnic_83xx_add_rings()
+    - net: mpls: Fix notifications when deleting a device
+    - siphash: use _unaligned version by default
+    - net/mlx4_en: Fix an use-after-free bug in mlx4_en_try_alloc_resources()
+    - selftests: net: Correct case name
+    - rxrpc: Fix rxrpc_local leak in rxrpc_lookup_peer()
+    - net: usb: lan78xx: lan78xx_phy_init(): use PHY_POLL instead of "0" if no IRQ
+      is available
+    - net: marvell: mvpp2: Fix the computation of shared CPUs
+    - net: annotate data-races on txq->xmit_lock_owner
+    - ipv4: convert fib_num_tclassid_users to atomic_t
+    - net/rds: correct socket tunable error in rds_tcp_tune()
+    - net/smc: Keep smc_close_final rc during active close
+    - drm/msm: Do hw_init() before capturing GPU state
+    - ipv6: fix memory leak in fib6_rule_suppress
+    - KVM: x86/pmu: Fix reserved bits for AMD PerfEvtSeln register
+    - sched/uclamp: Fix rq->uclamp_max not set on first enqueue
+    - parisc: Fix KBUILD_IMAGE for self-extracting kernel
+    - parisc: Fix "make install" on newer debian releases
+    - vgacon: Propagate console boot parameters before calling `vc_resize'
+    - xhci: Fix commad ring abort, write all 64 bits to CRCR register.
+    - USB: NO_LPM quirk Lenovo Powered USB-C Travel Hub
+    - usb: typec: tcpm: Wait in SNK_DEBOUNCED until disconnect
+    - x86/tsc: Add a timer to make sure TSC_adjust is always checked
+    - x86/tsc: Disable clocksource watchdog for TSC on qualified platorms
+    - x86/64/mm: Map all kernel memory into trampoline_pgd
+    - tty: serial: msm_serial: Deactivate RX DMA for polling support
+    - serial: pl011: Add ACPI SBSA UART match id
+    - serial: core: fix transmit-buffer reset and memleak
+    - serial: 8250_pci: Fix ACCES entries in pci_serial_quirks array
+    - serial: 8250_pci: rewrite pericom_do_set_divisor()
+    - iwlwifi: mvm: retry init flow if failed
+    - parisc: Mark cr16 CPU clocksource unstable on all SMP machines
+    - net/tls: Fix authentication failure in CCM mode
+    - Linux 5.4.164
+
+  * Focal update: v5.4.163 upstream stable release (LP: #1956380)
+    - USB: serial: option: add Telit LE910S1 0x9200 composition
+    - USB: serial: option: add Fibocom FM101-GL variants
+    - usb: dwc2: gadget: Fix ISOC flow for elapsed frames
+    - usb: dwc2: hcd_queue: Fix use of floating point literal
+    - net: nexthop: fix null pointer dereference when IPv6 is not enabled
+    - usb: typec: fusb302: Fix masking of comparator and bc_lvl interrupts
+    - usb: hub: Fix usb enumeration issue due to address0 race
+    - usb: hub: Fix locking issues with address0_mutex
+    - binder: fix test regression due to sender_euid change
+    - ALSA: ctxfi: Fix out-of-range access
+    - media: cec: copy sequence field for the reply
+    - HID: wacom: Use "Confidence" flag to prevent reporting invalid contacts
+    - staging/fbtft: Fix backlight
+    - staging: rtl8192e: Fix use after free in _rtl92e_pci_disconnect()
+    - xen: don't continue xenstore initialization in case of errors
+    - xen: detect uninitialized xenbus in xenbus_init
+    - KVM: PPC: Book3S HV: Prevent POWER7/8 TLB flush flushing SLB
+    - tracing/uprobe: Fix uprobe_perf_open probes iteration
+    - tracing: Fix pid filtering when triggers are attached
+    - mmc: sdhci: Fix ADMA for PAGE_SIZE >= 64KiB
+    - mdio: aspeed: Fix "Link is Down" issue
+    - PCI: aardvark: Deduplicate code in advk_pcie_rd_conf()
+    - PCI: aardvark: Wait for endpoint to be ready before training link
+    - PCI: aardvark: Fix big endian support
+    - PCI: aardvark: Train link immediately after enabling training
+    - PCI: aardvark: Improve link training
+    - PCI: aardvark: Issue PERST via GPIO
+    - PCI: aardvark: Replace custom macros by standard linux/pci_regs.h macros
+    - PCI: aardvark: Don't touch PCIe registers if no card connected
+    - PCI: aardvark: Fix compilation on s390
+    - PCI: aardvark: Move PCIe reset card code to advk_pcie_train_link()
+    - PCI: aardvark: Update comment about disabling link training
+    - PCI: pci-bridge-emul: Fix array overruns, improve safety
+    - PCI: aardvark: Configure PCIe resources from 'ranges' DT property
+    - PCI: aardvark: Fix PCIe Max Payload Size setting
+    - PCI: aardvark: Implement re-issuing config requests on CRS response
+    - PCI: aardvark: Simplify initialization of rootcap on virtual bridge
+    - PCI: aardvark: Fix link training
+    - PCI: aardvark: Fix support for bus mastering and PCI_COMMAND on emulated
+      bridge
+    - PCI: aardvark: Set PCI Bridge Class Code to PCI Bridge
+    - PCI: aardvark: Fix support for PCI_BRIDGE_CTL_BUS_RESET on emulated bridge
+    - pinctrl: armada-37xx: Correct PWM pins definitions
+    - arm64: dts: marvell: armada-37xx: Set pcie_reset_pin to gpio function
+    - proc/vmcore: fix clearing user buffer by properly using clear_user()
+    - netfilter: ipvs: Fix reuse connection if RS weight is 0
+    - ARM: dts: BCM5301X: Fix I2C controller interrupt
+    - ARM: dts: BCM5301X: Add interrupt properties to GPIO node
+    - ASoC: qdsp6: q6routing: Conditionally reset FrontEnd Mixer
+    - ASoC: topology: Add missing rwsem around snd_ctl_remove() calls
+    - net: ieee802154: handle iftypes as u32
+    - firmware: arm_scmi: pm: Propagate return value to caller
+    - NFSv42: Don't fail clone() unless the OP_CLONE operation failed
+    - ARM: socfpga: Fix crash with CONFIG_FORTIRY_SOURCE
+    - scsi: mpt3sas: Fix kernel panic during drive powercycle test
+    - drm/vc4: fix error code in vc4_create_object()
+    - iavf: Prevent changing static ITR values if adaptive moderation is on
+    - ipv6: fix typos in __ip6_finish_output()
+    - nfp: checking parameter process for rx-usecs/tx-usecs is invalid
+    - net: ipv6: add fib6_nh_release_dsts stub
+    - net: nexthop: release IPv6 per-cpu dsts when replacing a nexthop group
+    - scsi: core: sysfs: Fix setting device state to SDEV_RUNNING
+    - net/smc: Ensure the active closing peer first closes clcsock
+    - nvmet-tcp: fix incomplete data digest send
+    - net/ncsi : Add payload to be 32-bit aligned to fix dropped packets
+    - PM: hibernate: use correct mode for swsusp_close()
+    - tcp_cubic: fix spurious Hystart ACK train detections for not-cwnd-limited
+      flows
+    - nvmet: use IOCB_NOWAIT only if the filesystem supports it
+    - igb: fix netpoll exit with traffic
+    - MIPS: use 3-level pgtable for 64KB page size on MIPS_VA_BITS_48
+    - net: vlan: fix underflow for the real_dev refcnt
+    - net/smc: Don't call clcsock shutdown twice when smc shutdown
+    - net: hns3: fix VF RSS failed problem after PF enable multi-TCs
+    - net: mscc: ocelot: don't downgrade timestamping RX filters in SIOCSHWTSTAMP
+    - net: mscc: ocelot: correctly report the timestamping RX filters in ethtool
+    - f2fs: set SBI_NEED_FSCK flag when inconsistent node block found
+    - smb3: do not error on fsync when readonly
+    - vhost/vsock: fix incorrect used length reported to the guest
+    - tracing: Check pid filtering when creating events
+    - s390/mm: validate VMA in PGSTE manipulation functions
+    - shm: extend forced shm destroy to support objects from several IPC nses
+    - NFC: add NCI_UNREG flag to eliminate the race
+    - fuse: release pipe buf after last use
+    - xen: sync include/xen/interface/io/ring.h with Xen's newest version
+    - xen/blkfront: read response from backend only once
+    - xen/blkfront: don't take local copy of a request from the ring page
+    - xen/blkfront: don't trust the backend response data blindly
+    - xen/netfront: read response from backend only once
+    - xen/netfront: don't read data from request on the ring page
+    - xen/netfront: disentangle tx_skb_freelist
+    - xen/netfront: don't trust the backend response data blindly
+    - tty: hvc: replace BUG_ON() with negative return value
+    - Linux 5.4.163
+
+  * net/mlx5e: EPERM on vlan 0 programming (LP: #1957753)
+    - net/mlx5e: Unblock setting vid 0 for VF in case PF isn't eswitch manager
+
+  * CVE-2021-4083
+    - fget: check that the fd still exists after getting a ref to it
+
+  * CVE-2021-4155
+    - xfs: map unwritten blocks in XFS_IOC_{ALLOC, FREE}SP just like fallocate
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Thu, 03 Feb 2022 19:16:55 +0100
+
+linux (5.4.0-99.112) focal; urgency=medium
+
+  * focal/linux: 5.4.0-99.112 -proposed tracker (LP: #1959817)
+
+  * linux-image-5.4.0-97.110 freezes by accessing cifs shares (LP: #1959665)
+    - Revert "cifs: To match file servers, make sure the server hostname matches"
+    - Revert "cifs: set a minimum of 120s for next dns resolution"
+    - Revert "cifs: use the expiry output of dns_query to schedule next
+      resolution"
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Wed, 02 Feb 2022 17:21:18 +0100
+
+linux (5.4.0-97.110) focal; urgency=medium
+
+  * icmp_redirect from selftests fails on F/kvm (unary operator expected)
+    (LP: #1938964)
+    - selftests: icmp_redirect: pass xfail=0 to log_test()
+
+  * Focal: CIFS stable updates (LP: #1954926)
+    - cifs: use the expiry output of dns_query to schedule next resolution
+    - cifs: set a minimum of 120s for next dns resolution
+    - cifs: To match file servers, make sure the server hostname matches
+
+  * seccomp_bpf in seccomp from ubuntu_kernel_selftests failed to build on B-5.4
+    (LP: #1896420)
+    - SAUCE: selftests/seccomp: fix "storage size of 'md' isn't known" build issue
+    - SAUCE: selftests/seccomp: Fix s390x regs not defined issue
+
+  * system crash when removing ipmi_msghandler module (LP: #1950666)
+    - ipmi: Move remove_work to dedicated workqueue
+    - ipmi: msghandler: Make symbol 'remove_work_wq' static
+
+  * zcrypt DD: Toleration for new IBM Z Crypto Hardware - (Backport to Ubuntu
+    20.04) (LP: #1954680)
+    - s390/AP: support new dynamic AP bus size limit
+
+  * [UBUNTU 20.04] KVM hardware diagnose data improvements for guest kernel -
+    kernel part (LP: #1953334)
+    - s390/setup: diag 318: refactor struct
+    - s390/kvm: diagnose 0x318 sync and reset
+    - KVM: s390: remove diag318 reset code
+    - KVM: s390: add debug statement for diag 318 CPNC data
+
+  * Updates to ib_peer_memory requested by Nvidia (LP: #1947206)
+    - SAUCE: RDMA/core: Updated ib_peer_memory
+
+  * Include Infiniband Peer Memory interface (LP: #1923104)
+    - IB: Allow calls to ib_umem_get from kernel ULPs
+    - SAUCE: RDMA/core: Introduce peer memory interface
+
+  * Focal update: v5.4.162 upstream stable release (LP: #1954834)
+    - arm64: zynqmp: Do not duplicate flash partition label property
+    - arm64: zynqmp: Fix serial compatible string
+    - ARM: dts: NSP: Fix mpcore, mmc node names
+    - scsi: lpfc: Fix list_add() corruption in lpfc_drain_txq()
+    - arm64: dts: hisilicon: fix arm,sp805 compatible string
+    - RDMA/bnxt_re: Check if the vlan is valid before reporting
+    - usb: musb: tusb6010: check return value after calling
+      platform_get_resource()
+    - usb: typec: tipd: Remove WARN_ON in tps6598x_block_read
+    - arm64: dts: qcom: msm8998: Fix CPU/L2 idle state latency and residency
+    - arm64: dts: freescale: fix arm,sp805 compatible string
+    - ASoC: SOF: Intel: hda-dai: fix potential locking issue
+    - clk: imx: imx6ul: Move csi_sel mux to correct base register
+    - ASoC: nau8824: Add DMI quirk mechanism for active-high jack-detect
+    - scsi: advansys: Fix kernel pointer leak
+    - firmware_loader: fix pre-allocated buf built-in firmware use
+    - ARM: dts: omap: fix gpmc,mux-add-data type
+    - usb: host: ohci-tmio: check return value after calling
+      platform_get_resource()
+    - ARM: dts: ls1021a: move thermal-zones node out of soc/
+    - ARM: dts: ls1021a-tsn: use generic "jedec,spi-nor" compatible for flash
+    - ALSA: ISA: not for M68K
+    - tty: tty_buffer: Fix the softlockup issue in flush_to_ldisc
+    - MIPS: sni: Fix the build
+    - scsi: target: Fix ordered tag handling
+    - scsi: target: Fix alua_tg_pt_gps_count tracking
+    - iio: imu: st_lsm6dsx: Avoid potential array overflow in st_lsm6dsx_set_odr()
+    - powerpc/5200: dts: fix memory node unit name
+    - ALSA: gus: fix null pointer dereference on pointer block
+    - powerpc/dcr: Use cmplwi instead of 3-argument cmpli
+    - sh: check return code of request_irq
+    - maple: fix wrong return value of maple_bus_init().
+    - f2fs: fix up f2fs_lookup tracepoints
+    - sh: fix kconfig unmet dependency warning for FRAME_POINTER
+    - sh: math-emu: drop unused functions
+    - sh: define __BIG_ENDIAN for math-emu
+    - clk: ingenic: Fix bugs with divided dividers
+    - clk/ast2600: Fix soc revision for AHB
+    - clk: qcom: gcc-msm8996: Drop (again) gcc_aggre1_pnoc_ahb_clk
+    - mips: BCM63XX: ensure that CPU_SUPPORTS_32BIT_KERNEL is set
+    - sched/core: Mitigate race cpus_share_cache()/update_top_cache_domain()
+    - tracing: Save normal string variables
+    - tracing/histogram: Do not copy the fixed-size char array field over the
+      field size
+    - RDMA/netlink: Add __maybe_unused to static inline in C file
+    - perf bpf: Avoid memory leak from perf_env__insert_btf()
+    - perf bench futex: Fix memory leak of perf_cpu_map__new()
+    - perf tests: Remove bash construct from record+zstd_comp_decomp.sh
+    - net: bnx2x: fix variable dereferenced before check
+    - iavf: check for null in iavf_fix_features
+    - iavf: free q_vectors before queues in iavf_disable_vf
+    - iavf: Fix failure to exit out from last all-multicast mode
+    - iavf: prevent accidental free of filter structure
+    - iavf: validate pointers
+    - iavf: Fix for the false positive ASQ/ARQ errors while issuing VF reset
+    - MIPS: generic/yamon-dt: fix uninitialized variable error
+    - mips: bcm63xx: add support for clk_get_parent()
+    - mips: lantiq: add support for clk_get_parent()
+    - platform/x86: hp_accel: Fix an error handling path in 'lis3lv02d_probe()'
+    - scsi: core: sysfs: Fix hang when device state is set via sysfs
+    - net: sched: act_mirred: drop dst for the direction from egress to ingress
+    - net: dpaa2-eth: fix use-after-free in dpaa2_eth_remove
+    - net: virtio_net_hdr_to_skb: count transport header in UFO
+    - i40e: Fix correct max_pkt_size on VF RX queue
+    - i40e: Fix NULL ptr dereference on VSI filter sync
+    - i40e: Fix changing previously set num_queue_pairs for PFs
+    - i40e: Fix ping is lost after configuring ADq on VF
+    - i40e: Fix creation of first queue by omitting it if is not power of two
+    - i40e: Fix display error code in dmesg
+    - NFC: reorganize the functions in nci_request
+    - drm/nouveau: hdmigv100.c: fix corrupted HDMI Vendor InfoFrame
+    - NFC: reorder the logic in nfc_{un,}register_device
+    - KVM: PPC: Book3S HV: Use GLOBAL_TOC for kvmppc_h_set_dabr/xdabr()
+    - perf/x86/intel/uncore: Fix filter_tid mask for CHA events on Skylake Server
+    - perf/x86/intel/uncore: Fix IIO event constraints for Skylake Server
+    - s390/kexec: fix return code handling
+    - arm64: vdso32: suppress error message for 'make mrproper'
+    - tun: fix bonding active backup with arp monitoring
+    - hexagon: export raw I/O routines for modules
+    - ipc: WARN if trying to remove ipc object which is absent
+    - mm: kmemleak: slob: respect SLAB_NOLEAKTRACE flag
+    - x86/hyperv: Fix NULL deref in set_hv_tscchange_cb() if Hyper-V setup fails
+    - s390/kexec: fix memory leak of ipl report buffer
+    - udf: Fix crash after seekdir
+    - btrfs: fix memory ordering between normal and ordered work functions
+    - parisc/sticon: fix reverse colors
+    - cfg80211: call cfg80211_stop_ap when switch from P2P_GO type
+    - drm/udl: fix control-message timeout
+    - drm/nouveau: use drm_dev_unplug() during device removal
+    - drm/i915/dp: Ensure sink rate values are always valid
+    - drm/amdgpu: fix set scaling mode Full/Full aspect/Center not works on vga
+      and dvi connectors
+    - Revert "net: mvpp2: disable force link UP during port init procedure"
+    - perf/core: Avoid put_page() when GUP fails
+    - batman-adv: Consider fragmentation for needed_headroom
+    - batman-adv: Reserve needed_*room for fragments
+    - batman-adv: Don't always reallocate the fragmentation skb head
+    - ASoC: DAPM: Cover regression by kctl change notification fix
+    - usb: max-3421: Use driver data instead of maintaining a list of bound
+      devices
+    - ice: Delete always true check of PF pointer
+    - ALSA: hda: hdac_ext_stream: fix potential locking issues
+    - ALSA: hda: hdac_stream: fix potential locking issue in
+      snd_hdac_stream_assign()
+    - Linux 5.4.162
+
+  * Focal update: v5.4.161 upstream stable release (LP: #1954828)
+    - scsi: ufs: Fix interrupt error message for shared interrupts
+    - MIPS: Fix assembly error from MIPSr2 code used within MIPS_ISA_ARCH_LEVEL
+    - ext4: fix lazy initialization next schedule time computation in more
+      granular unit
+    - scsi: ufs: Fix tm request when non-fatal error happens
+    - fortify: Explicitly disable Clang support
+    - parisc/entry: fix trace test in syscall exit path
+    - PCI/MSI: Destroy sysfs before freeing entries
+    - PCI/MSI: Deal with devices lying about their MSI mask capability
+    - PCI: Add MSI masking quirk for Nvidia ION AHCI
+    - erofs: remove the occupied parameter from z_erofs_pagevec_enqueue()
+    - erofs: fix unsafe pagevec reuse of hooked pclusters
+    - Linux 5.4.161
+
+  * Focal update: v5.4.160 upstream stable release (LP: #1953387)
+    - xhci: Fix USB 3.1 enumeration issues by increasing roothub power-on-good
+      delay
+    - usb: xhci: Enable runtime-pm by default on AMD Yellow Carp platform
+    - binder: use euid from cred instead of using task
+    - binder: use cred instead of task for selinux checks
+    - binder: use cred instead of task for getsecid
+    - Input: iforce - fix control-message timeout
+    - Input: elantench - fix misreporting trackpoint coordinates
+    - Input: i8042 - Add quirk for Fujitsu Lifebook T725
+    - libata: fix read log timeout value
+    - ocfs2: fix data corruption on truncate
+    - scsi: qla2xxx: Fix kernel crash when accessing port_speed sysfs file
+    - scsi: qla2xxx: Fix use after free in eh_abort path
+    - mmc: dw_mmc: Dont wait for DRTO on Write RSP error
+    - parisc: Fix ptrace check on syscall return
+    - tpm: Check for integer overflow in tpm2_map_response_body()
+    - firmware/psci: fix application of sizeof to pointer
+    - crypto: s5p-sss - Add error handling in s5p_aes_probe()
+    - media: ite-cir: IR receiver stop working after receive overflow
+    - media: ir-kbd-i2c: improve responsiveness of hauppauge zilog receivers
+    - media: v4l2-ioctl: Fix check_ext_ctrls
+    - ALSA: hda/realtek: Add quirk for Clevo PC70HS
+    - ALSA: hda/realtek: Add a quirk for Acer Spin SP513-54N
+    - ALSA: hda/realtek: Add quirk for ASUS UX550VE
+    - ALSA: hda/realtek: Add quirk for HP EliteBook 840 G7 mute LED
+    - ALSA: ua101: fix division by zero at probe
+    - ALSA: 6fire: fix control and bulk message timeouts
+    - ALSA: line6: fix control and interrupt message timeouts
+    - ALSA: usb-audio: Add registration quirk for JBL Quantum 400
+    - ALSA: synth: missing check for possible NULL after the call to kstrdup
+    - ALSA: timer: Fix use-after-free problem
+    - ALSA: timer: Unconditionally unlink slave instances, too
+    - fuse: fix page stealing
+    - x86/sme: Use #define USE_EARLY_PGTABLE_L5 in mem_encrypt_identity.c
+    - x86/cpu: Fix migration safety with X86_BUG_NULL_SEL
+    - x86/irq: Ensure PI wakeup handler is unregistered before module unload
+    - cavium: Return negative value when pci_alloc_irq_vectors() fails
+    - scsi: qla2xxx: Return -ENOMEM if kzalloc() fails
+    - scsi: qla2xxx: Fix unmap of already freed sgl
+    - cavium: Fix return values of the probe function
+    - sfc: Don't use netif_info before net_device setup
+    - hyperv/vmbus: include linux/bitops.h
+    - ARM: dts: sun7i: A20-olinuxino-lime2: Fix ethernet phy-mode
+    - reset: socfpga: add empty driver allowing consumers to probe
+    - mmc: winbond: don't build on M68K
+    - drm: panel-orientation-quirks: Add quirk for Aya Neo 2021
+    - bpf: Define bpf_jit_alloc_exec_limit for arm64 JIT
+    - bpf: Prevent increasing bpf_jit_limit above max
+    - xen/netfront: stop tx queues during live migration
+    - nvmet-tcp: fix a memory leak when releasing a queue
+    - spi: spl022: fix Microwire full duplex mode
+    - net: multicast: calculate csum of looped-back and forwarded packets
+    - watchdog: Fix OMAP watchdog early handling
+    - drm: panel-orientation-quirks: Add quirk for GPD Win3
+    - nvmet-tcp: fix header digest verification
+    - r8169: Add device 10ec:8162 to driver r8169
+    - vmxnet3: do not stop tx queues after netif_device_detach()
+    - nfp: bpf: relax prog rejection for mtu check through max_pkt_offset
+    - net/smc: Correct spelling mistake to TCPF_SYN_RECV
+    - btrfs: clear MISSING device status bit in btrfs_close_one_device
+    - btrfs: fix lost error handling when replaying directory deletes
+    - btrfs: call btrfs_check_rw_degradable only if there is a missing device
+    - ia64: kprobes: Fix to pass correct trampoline address to the handler
+    - hwmon: (pmbus/lm25066) Add offset coefficients
+    - regulator: s5m8767: do not use reset value as DVS voltage if GPIO DVS is
+      disabled
+    - regulator: dt-bindings: samsung,s5m8767: correct s5m8767,pmic-buck-default-
+      dvs-idx property
+    - EDAC/sb_edac: Fix top-of-high-memory value for Broadwell/Haswell
+    - mwifiex: fix division by zero in fw download path
+    - ath6kl: fix division by zero in send path
+    - ath6kl: fix control-message timeout
+    - ath10k: fix control-message timeout
+    - ath10k: fix division by zero in send path
+    - PCI: Mark Atheros QCA6174 to avoid bus reset
+    - rtl8187: fix control-message timeouts
+    - evm: mark evm_fixmode as __ro_after_init
+    - wcn36xx: Fix HT40 capability for 2Ghz band
+    - mwifiex: Read a PCI register after writing the TX ring write pointer
+    - libata: fix checking of DMA state
+    - wcn36xx: handle connection loss indication
+    - rsi: fix occasional initialisation failure with BT coex
+    - rsi: fix key enabled check causing unwanted encryption for vap_id > 0
+    - rsi: fix rate mask set leading to P2P failure
+    - rsi: Fix module dev_oper_mode parameter description
+    - RDMA/qedr: Fix NULL deref for query_qp on the GSI QP
+    - signal: Remove the bogus sigkill_pending in ptrace_stop
+    - signal/mips: Update (_save|_restore)_fp_context to fail with -EFAULT
+    - power: supply: max17042_battery: Prevent int underflow in set_soc_threshold
+    - power: supply: max17042_battery: use VFSOC for capacity when no rsns
+    - KVM: nVMX: Query current VMCS when determining if MSR bitmaps are in use
+    - can: j1939: j1939_tp_cmd_recv(): ignore abort message in the BAM transport
+    - can: j1939: j1939_can_recv(): ignore messages with invalid source address
+    - powerpc/85xx: Fix oops when mpc85xx_smp_guts_ids node cannot be found
+    - serial: core: Fix initializing and restoring termios speed
+    - ALSA: mixer: oss: Fix racy access to slots
+    - ALSA: mixer: fix deadlock in snd_mixer_oss_set_volume
+    - xen/balloon: add late_initcall_sync() for initial ballooning done
+    - PCI: pci-bridge-emul: Fix emulation of W1C bits
+    - PCI: aardvark: Do not clear status bits of masked interrupts
+    - PCI: aardvark: Fix checking for link up via LTSSM state
+    - PCI: aardvark: Do not unmask unused interrupts
+    - PCI: aardvark: Fix reporting Data Link Layer Link Active
+    - PCI: aardvark: Fix return value of MSI domain .alloc() method
+    - PCI: aardvark: Read all 16-bits from PCIE_MSI_PAYLOAD_REG
+    - quota: check block number when reading the block in quota file
+    - quota: correct error number in free_dqentry()
+    - pinctrl: core: fix possible memory leak in pinctrl_enable()
+    - iio: dac: ad5446: Fix ad5622_write() return value
+    - USB: serial: keyspan: fix memleak on probe errors
+    - USB: iowarrior: fix control-message timeouts
+    - USB: chipidea: fix interrupt deadlock
+    - dma-buf: WARN on dmabuf release with pending attachments
+    - drm: panel-orientation-quirks: Update the Lenovo Ideapad D330 quirk (v2)
+    - drm: panel-orientation-quirks: Add quirk for KD Kurio Smart C15200 2-in-1
+    - drm: panel-orientation-quirks: Add quirk for the Samsung Galaxy Book 10.6
+    - Bluetooth: sco: Fix lock_sock() blockage by memcpy_from_msg()
+    - Bluetooth: fix use-after-free error in lock_sock_nested()
+    - drm/panel-orientation-quirks: add Valve Steam Deck
+    - platform/x86: wmi: do not fail if disabling fails
+    - MIPS: lantiq: dma: add small delay after reset
+    - MIPS: lantiq: dma: reset correct number of channel
+    - locking/lockdep: Avoid RCU-induced noinstr fail
+    - net: sched: update default qdisc visibility after Tx queue cnt changes
+    - smackfs: Fix use-after-free in netlbl_catmap_walk()
+    - x86: Increase exception stack sizes
+    - mwifiex: Run SET_BSS_MODE when changing from P2P to STATION vif-type
+    - mwifiex: Properly initialize private structure on interface type changes
+    - ath10k: high latency fixes for beacon buffer
+    - media: mt9p031: Fix corrupted frame after restarting stream
+    - media: netup_unidvb: handle interrupt properly according to the firmware
+    - media: stm32: Potential NULL pointer dereference in dcmi_irq_thread()
+    - media: uvcvideo: Set capability in s_param
+    - media: uvcvideo: Return -EIO for control errors
+    - media: uvcvideo: Set unique vdev name based in type
+    - media: s5p-mfc: fix possible null-pointer dereference in s5p_mfc_probe()
+    - media: s5p-mfc: Add checking to s5p_mfc_probe().
+    - media: imx: set a media_device bus_info string
+    - media: mceusb: return without resubmitting URB in case of -EPROTO error.
+    - ia64: don't do IA64_CMPXCHG_DEBUG without CONFIG_PRINTK
+    - brcmfmac: Add DMI nvram filename quirk for Cyberbook T116 tablet
+    - media: rcar-csi2: Add checking to rcsi2_start_receiver()
+    - ipmi: Disable some operations during a panic
+    - ACPICA: Avoid evaluating methods too early during system resume
+    - media: ipu3-imgu: imgu_fmt: Handle properly try
+    - media: ipu3-imgu: VIDIOC_QUERYCAP: Fix bus_info
+    - media: usb: dvd-usb: fix uninit-value bug in dibusb_read_eeprom_byte()
+    - net-sysfs: try not to restart the syscall if it will fail eventually
+    - tracefs: Have tracefs directories not set OTH permission bits by default
+    - ath: dfs_pattern_detector: Fix possible null-pointer dereference in
+      channel_detector_create()
+    - iov_iter: Fix iov_iter_get_pages{,_alloc} page fault return value
+    - ACPI: battery: Accept charges over the design capacity as full
+    - leaking_addresses: Always print a trailing newline
+    - memstick: r592: Fix a UAF bug when removing the driver
+    - lib/xz: Avoid overlapping memcpy() with invalid input with in-place
+      decompression
+    - lib/xz: Validate the value before assigning it to an enum variable
+    - workqueue: make sysfs of unbound kworker cpumask more clever
+    - tracing/cfi: Fix cmp_entries_* functions signature mismatch
+    - mwl8k: Fix use-after-free in mwl8k_fw_state_machine()
+    - block: remove inaccurate requeue check
+    - nvmet: fix use-after-free when a port is removed
+    - nvmet-tcp: fix use-after-free when a port is removed
+    - nvme: drop scan_lock and always kick requeue list when removing namespaces
+    - PM: hibernate: Get block device exclusively in swsusp_check()
+    - selftests: kvm: fix mismatched fclose() after popen()
+    - iwlwifi: mvm: disable RX-diversity in powersave
+    - smackfs: use __GFP_NOFAIL for smk_cipso_doi()
+    - ARM: clang: Do not rely on lr register for stacktrace
+    - gre/sit: Don't generate link-local addr if addr_gen_mode is
+      IN6_ADDR_GEN_MODE_NONE
+    - ARM: 9136/1: ARMv7-M uses BE-8, not BE-32
+    - vrf: run conntrack only in context of lower/physdev for locally generated
+      packets
+    - net: annotate data-race in neigh_output()
+    - btrfs: do not take the uuid_mutex in btrfs_rm_device
+    - spi: bcm-qspi: Fix missing clk_disable_unprepare() on error in
+      bcm_qspi_probe()
+    - x86/hyperv: Protect set_hv_tscchange_cb() against getting preempted
+    - parisc: fix warning in flush_tlb_all
+    - task_stack: Fix end_of_stack() for architectures with upwards-growing stack
+    - parisc/unwind: fix unwinder when CONFIG_64BIT is enabled
+    - parisc/kgdb: add kgdb_roundup() to make kgdb work with idle polling
+    - netfilter: conntrack: set on IPS_ASSURED if flows enters internal stream
+      state
+    - selftests/bpf: Fix strobemeta selftest regression
+    - Bluetooth: fix init and cleanup of sco_conn.timeout_work
+    - rcu: Fix existing exp request check in sync_sched_exp_online_cleanup()
+    - drm/v3d: fix wait for TMU write combiner flush
+    - virtio-gpu: fix possible memory allocation failure
+    - net: net_namespace: Fix undefined member in key_remove_domain()
+    - cgroup: Make rebind_subsystems() disable v2 controllers all at once
+    - wilc1000: fix possible memory leak in cfg_scan_result()
+    - Bluetooth: btmtkuart: fix a memleak in mtk_hci_wmt_sync
+    - crypto: caam - disable pkc for non-E SoCs
+    - rxrpc: Fix _usecs_to_jiffies() by using usecs_to_jiffies()
+    - net: dsa: rtl8366rb: Fix off-by-one bug
+    - ath10k: Fix missing frame timestamp for beacon/probe-resp
+    - drm/amdgpu: fix warning for overflow check
+    - media: em28xx: add missing em28xx_close_extension
+    - media: cxd2880-spi: Fix a null pointer dereference on error handling path
+    - media: dvb-usb: fix ununit-value in az6027_rc_query
+    - media: TDA1997x: handle short reads of hdmi info frame.
+    - media: mtk-vpu: Fix a resource leak in the error handling path of
+      'mtk_vpu_probe()'
+    - media: radio-wl1273: Avoid card name truncation
+    - media: si470x: Avoid card name truncation
+    - media: tm6000: Avoid card name truncation
+    - media: cx23885: Fix snd_card_free call on null card pointer
+    - kprobes: Do not use local variable when creating debugfs file
+    - crypto: ecc - fix CRYPTO_DEFAULT_RNG dependency
+    - cpuidle: Fix kobject memory leaks in error paths
+    - media: em28xx: Don't use ops->suspend if it is NULL
+    - ath9k: Fix potential interrupt storm on queue reset
+    - EDAC/amd64: Handle three rank interleaving mode
+    - netfilter: nft_dynset: relax superfluous check on set updates
+    - media: dvb-frontends: mn88443x: Handle errors of clk_prepare_enable()
+    - crypto: qat - detect PFVF collision after ACK
+    - crypto: qat - disregard spurious PFVF interrupts
+    - hwrng: mtk - Force runtime pm ops for sleep ops
+    - b43legacy: fix a lower bounds test
+    - b43: fix a lower bounds test
+    - mmc: sdhci-omap: Fix NULL pointer exception if regulator is not configured
+    - memstick: avoid out-of-range warning
+    - memstick: jmb38x_ms: use appropriate free function in jmb38x_ms_alloc_host()
+    - net, neigh: Fix NTF_EXT_LEARNED in combination with NTF_USE
+    - hwmon: Fix possible memleak in __hwmon_device_register()
+    - hwmon: (pmbus/lm25066) Let compiler determine outer dimension of
+      lm25066_coeff
+    - ath10k: fix max antenna gain unit
+    - drm/msm: uninitialized variable in msm_gem_import()
+    - net: stream: don't purge sk_error_queue in sk_stream_kill_queues()
+    - mmc: mxs-mmc: disable regulator on error and in the remove function
+    - block: ataflop: fix breakage introduced at blk-mq refactoring
+    - platform/x86: thinkpad_acpi: Fix bitwise vs. logical warning
+    - mt76: mt76x02: fix endianness warnings in mt76x02_mac.c
+    - rsi: stop thread firstly in rsi_91x_init() error handling
+    - mwifiex: Send DELBA requests according to spec
+    - phy: micrel: ksz8041nl: do not use power down mode
+    - nvme-rdma: fix error code in nvme_rdma_setup_ctrl
+    - PM: hibernate: fix sparse warnings
+    - clocksource/drivers/timer-ti-dm: Select TIMER_OF
+    - drm/msm: Fix potential NULL dereference in DPU SSPP
+    - smackfs: use netlbl_cfg_cipsov4_del() for deleting cipso_v4_doi
+    - libbpf: Fix BTF data layout checks and allow empty BTF
+    - s390/gmap: don't unconditionally call pte_unmap_unlock() in __gmap_zap()
+    - irq: mips: avoid nested irq_enter()
+    - tcp: don't free a FIN sk_buff in tcp_remove_empty_skb()
+    - samples/kretprobes: Fix return value if register_kretprobe() failed
+    - KVM: s390: Fix handle_sske page fault handling
+    - libertas_tf: Fix possible memory leak in probe and disconnect
+    - libertas: Fix possible memory leak in probe and disconnect
+    - wcn36xx: add proper DMA memory barriers in rx path
+    - drm/amdgpu/gmc6: fix DMA mask from 44 to 40 bits
+    - net: amd-xgbe: Toggle PLL settings during rate change
+    - net: phylink: avoid mvneta warning when setting pause parameters
+    - crypto: pcrypt - Delay write to padata->info
+    - selftests/bpf: Fix fclose/pclose mismatch in test_progs
+    - udp6: allow SO_MARK ctrl msg to affect routing
+    - ibmvnic: don't stop queue in xmit
+    - ibmvnic: Process crqs after enabling interrupts
+    - RDMA/rxe: Fix wrong port_cap_flags
+    - clk: mvebu: ap-cpu-clk: Fix a memory leak in error handling paths
+    - ARM: s3c: irq-s3c24xx: Fix return value check for s3c24xx_init_intc()
+    - arm64: dts: rockchip: Fix GPU register width for RK3328
+    - ARM: dts: qcom: msm8974: Add xo_board reference clock to DSI0 PHY
+    - RDMA/bnxt_re: Fix query SRQ failure
+    - arm64: dts: meson-g12a: Fix the pwm regulator supply properties
+    - ARM: dts: at91: tse850: the emac<->phy interface is rmii
+    - scsi: dc395: Fix error case unwinding
+    - MIPS: loongson64: make CPU_LOONGSON64 depends on MIPS_FP_SUPPORT
+    - JFS: fix memleak in jfs_mount
+    - ALSA: hda: Reduce udelay() at SKL+ position reporting
+    - arm: dts: omap3-gta04a4: accelerometer irq fix
+    - soc/tegra: Fix an error handling path in tegra_powergate_power_up()
+    - memory: fsl_ifc: fix leak of irq and nand_irq in fsl_ifc_ctrl_probe
+    - clk: at91: check pmc node status before registering syscore ops
+    - video: fbdev: chipsfb: use memset_io() instead of memset()
+    - serial: 8250_dw: Drop wrong use of ACPI_PTR()
+    - usb: gadget: hid: fix error code in do_config()
+    - power: supply: rt5033_battery: Change voltage values to µV
+    - scsi: csiostor: Uninitialized data in csio_ln_vnp_read_cbfn()
+    - RDMA/mlx4: Return missed an error if device doesn't support steering
+    - staging: ks7010: select CRYPTO_HASH/CRYPTO_MICHAEL_MIC
+    - ARM: dts: stm32: fix SAI sub nodes register range
+    - ASoC: cs42l42: Correct some register default values
+    - ASoC: cs42l42: Defer probe if request_threaded_irq() returns EPROBE_DEFER
+    - phy: qcom-qusb2: Fix a memory leak on probe
+    - serial: xilinx_uartps: Fix race condition causing stuck TX
+    - HID: u2fzero: clarify error check and length calculations
+    - HID: u2fzero: properly handle timeouts in usb_submit_urb
+    - powerpc/44x/fsp2: add missing of_node_put
+    - mips: cm: Convert to bitfield API to fix out-of-bounds access
+    - power: supply: bq27xxx: Fix kernel crash on IRQ handler register error
+    - apparmor: fix error check
+    - rpmsg: Fix rpmsg_create_ept return when RPMSG config is not defined
+    - pnfs/flexfiles: Fix misplaced barrier in nfs4_ff_layout_prepare_ds
+    - drm/plane-helper: fix uninitialized variable reference
+    - PCI: aardvark: Don't spam about PIO Response Status
+    - PCI: aardvark: Fix preserving PCI_EXP_RTCTL_CRSSVE flag on emulated bridge
+    - opp: Fix return in _opp_add_static_v2()
+    - NFS: Fix deadlocks in nfs_scan_commit_list()
+    - fs: orangefs: fix error return code of orangefs_revalidate_lookup()
+    - mtd: spi-nor: hisi-sfc: Remove excessive clk_disable_unprepare()
+    - mtd: core: don't remove debugfs directory if device is in use
+    - dmaengine: at_xdmac: fix AT_XDMAC_CC_PERID() macro
+    - auxdisplay: img-ascii-lcd: Fix lock-up when displaying empty string
+    - auxdisplay: ht16k33: Connect backlight to fbdev
+    - auxdisplay: ht16k33: Fix frame buffer device blanking
+    - soc: fsl: dpaa2-console: free buffer before returning from
+      dpaa2_console_read
+    - netfilter: nfnetlink_queue: fix OOB when mac header was cleared
+    - dmaengine: dmaengine_desc_callback_valid(): Check for `callback_result`
+    - signal/sh: Use force_sig(SIGKILL) instead of do_group_exit(SIGKILL)
+    - m68k: set a default value for MEMORY_RESERVE
+    - watchdog: f71808e_wdt: fix inaccurate report in WDIOC_GETTIMEOUT
+    - ar7: fix kernel builds for compiler test
+    - scsi: qla2xxx: Fix gnl list corruption
+    - scsi: qla2xxx: Turn off target reset during issue_lip
+    - NFSv4: Fix a regression in nfs_set_open_stateid_locked()
+    - i2c: xlr: Fix a resource leak in the error handling path of
+      'xlr_i2c_probe()'
+    - xen-pciback: Fix return in pm_ctrl_init()
+    - net: davinci_emac: Fix interrupt pacing disable
+    - net: vlan: fix a UAF in vlan_dev_real_dev()
+    - ACPI: PMIC: Fix intel_pmic_regs_handler() read accesses
+    - bonding: Fix a use-after-free problem when bond_sysfs_slave_add() failed
+    - mm/zsmalloc.c: close race window between zs_pool_dec_isolated() and
+      zs_unregister_migration()
+    - zram: off by one in read_block_state()
+    - perf bpf: Add missing free to bpf_event__print_bpf_prog_info()
+    - llc: fix out-of-bound array index in llc_sk_dev_hash()
+    - nfc: pn533: Fix double free when pn533_fill_fragment_skbs() fails
+    - arm64: pgtable: make __pte_to_phys/__phys_to_pte_val inline functions
+    - bpf: sockmap, strparser, and tls are reusing qdisc_skb_cb and colliding
+    - net/sched: sch_taprio: fix undefined behavior in ktime_mono_to_any
+    - net: hns3: allow configure ETS bandwidth of all TCs
+    - vsock: prevent unnecessary refcnt inc for nonblocking connect
+    - net/smc: fix sk_refcnt underflow on linkdown and fallback
+    - cxgb4: fix eeprom len when diagnostics not implemented
+    - selftests/net: udpgso_bench_rx: fix port argument
+    - ARM: 9155/1: fix early early_iounmap()
+    - ARM: 9156/1: drop cc-option fallbacks for architecture selection
+    - parisc: Fix set_fixmap() on PA1.x CPUs
+    - irqchip/sifive-plic: Fixup EOI failed when masked
+    - f2fs: should use GFP_NOFS for directory inodes
+    - net, neigh: Enable state migration between NUD_PERMANENT and NTF_USE
+    - 9p/net: fix missing error check in p9_check_errors
+    - ovl: fix deadlock in splice write
+    - powerpc/lib: Add helper to check if offset is within conditional branch
+      range
+    - powerpc/bpf: Validate branch ranges
+    - powerpc/bpf: Fix BPF_SUB when imm == 0x80000000
+    - powerpc/security: Add a helper to query stf_barrier type
+    - powerpc/bpf: Emit stf barrier instruction sequences for BPF_NOSPEC
+    - mm, oom: pagefault_out_of_memory: don't force global OOM for dying tasks
+    - mm, oom: do not trigger out_of_memory from the #PF
+    - video: backlight: Drop maximum brightness override for brightness zero
+    - s390/cio: check the subchannel validity for dev_busid
+    - s390/tape: fix timer initialization in tape_std_assign()
+    - s390/cio: make ccw_device_dma_* more robust
+    - powerpc/powernv/prd: Unregister OPAL_MSG_PRD2 notifier during module unload
+    - PCI: Add PCI_EXP_DEVCTL_PAYLOAD_* macros
+    - SUNRPC: Partial revert of commit 6f9f17287e78
+    - ath10k: fix invalid dma_addr_t token assignment
+    - selftests/bpf: Fix also no-alu32 strobemeta selftest
+    - Linux 5.4.160
+    - soc/tegra: pmc: Fix imbalanced clock disabling in error code path
+
+  * Focal update: v5.4.159 upstream stable release (LP: #1953071)
+    - Revert "x86/kvm: fix vcpu-id indexed array sizes"
+    - usb: ehci: handshake CMD_RUN instead of STS_HALT
+    - usb: gadget: Mark USB_FSL_QE broken on 64-bit
+    - usb: musb: Balance list entry in musb_gadget_queue
+    - usb-storage: Add compatibility quirk flags for iODD 2531/2541
+    - binder: don't detect sender/target during buffer cleanup
+    - printk/console: Allow to disable console output by using console="" or
+      console=null
+    - isofs: Fix out of bound access for corrupted isofs image
+    - comedi: dt9812: fix DMA buffers on stack
+    - comedi: ni_usb6501: fix NULL-deref in command paths
+    - comedi: vmk80xx: fix transfer-buffer overflows
+    - comedi: vmk80xx: fix bulk-buffer overflow
+    - comedi: vmk80xx: fix bulk and interrupt message timeouts
+    - staging: r8712u: fix control-message timeout
+    - staging: rtl8192u: fix control-message timeouts
+    - media: staging/intel-ipu3: css: Fix wrong size comparison imgu_css_fw_init
+    - rsi: fix control-message timeout
+    - Linux 5.4.159
+
+  * Focal update: v5.4.158 upstream stable release (LP: #1953066)
+    - scsi: core: Put LLD module refcnt after SCSI device is released
+    - vrf: Revert "Reset skb conntrack connection..."
+    - net: ethernet: microchip: lan743x: Fix skb allocation failure
+    - media: firewire: firedtv-avc: fix a buffer overflow in avc_ca_pmt()
+    - Revert "xhci: Set HCD flag to defer primary roothub registration"
+    - Revert "usb: core: hcd: Add support for deferring roothub registration"
+    - sfc: Fix reading non-legacy supported link modes
+    - ARM: 9120/1: Revert "amba: make use of -1 IRQs warn"
+    - Linux 5.4.158
+
+  * [Ubuntu 20.04] Problem leading IUCV service down (on s390x) (LP: #1913442)
+    - usercopy: mark dma-kmalloc caches as usercopy caches
+
+ -- Kleber Sacilotto de Souza <kleber.souza@canonical.com>  Thu, 13 Jan 2022 19:00:41 +0100
+
+linux (5.4.0-96.109) focal; urgency=medium
+
+  * Support builtin revoked certificates (LP: #1932029)
+    - [Config]: add i386 to CONFIG_SYSTEM_REVOCATION_KEYS annotation
+
+  * CVE-2022-0185
+    - SAUCE: vfs: Out-of-bounds write of heap buffer in fs_context.c
+    - SAUCE: vfs: test that one given mount param is not larger than PAGE_SIZE
+
+ -- Thadeu Lima de Souza Cascardo <cascardo@canonical.com>  Wed, 12 Jan 2022 12:16:43 -0300
+
+linux (5.4.0-94.106) focal; urgency=medium
+
+  * focal/linux: 5.4.0-94.106 -proposed tracker (LP: #1956628)
+
+  * [Regression] Focal kernel  5.4.0-92.103 fails to boot when Secure Encrypted
+    Virtualization(SEV) is enabled (LP: #1956575)
+    - x86/ioremap: Map EFI-reserved memory as encrypted for SEV
+
+ -- Khalid Elmously <khalid.elmously@canonical.com>  Thu, 06 Jan 2022 16:56:46 -0500
+
+linux (5.4.0-92.103) focal; urgency=medium
+
+  * focal/linux: 5.4.0-92.103 -proposed tracker (LP: #1952316)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync update-dkms-versions helper
+    - debian/dkms-versions -- update from kernel-versions (main/2021.11.29)
+
+  * CVE-2021-4002
+    - tlb: mmu_gather: add tlb_flush_*_range APIs
+    - hugetlbfs: flush TLBs correctly after huge_pmd_unshare
+
+  * Re-enable DEBUG_INFO_BTF where it was disabled (LP: #1945632)
+    - [Config] Enable CONFIG_DEBUG_INFO_BTF on all arches
+
+  * Focal linux-azure: Vm crash on Dv5/Ev5 (LP: #1950462)
+    - KVM: VMX: eVMCS: make evmcs_sanitize_exec_ctrls() work again
+    - jump_label: Fix usage in module __init
+
+  * Support builtin revoked certificates (LP: #1932029)
+    - Revert "UBUNTU: SAUCE: (lockdown) Make get_cert_list() not complain about
+      cert lists that aren't present."
+    - integrity: Move import of MokListRT certs to a separate routine
+    - integrity: Load certs from the EFI MOK config table
+    - certs: Add ability to preload revocation certs
+    - integrity: Load mokx variables into the blacklist keyring
+    - certs: add 'x509_revocation_list' to gitignore
+    - SAUCE: Dump stack when X.509 certificates cannot be loaded
+    - [Packaging] build canonical-revoked-certs.pem from branch/arch certs
+    - [Packaging] Revoke 2012 UEFI signing certificate as built-in
+    - [Config] Configure CONFIG_SYSTEM_REVOCATION_KEYS with revoked keys
+
+  * Support importing mokx keys into revocation list from the mok table
+    (LP: #1928679)
+    - efi: Support for MOK variable config table
+    - efi: mokvar-table: fix some issues in new code
+    - efi: mokvar: add missing include of asm/early_ioremap.h
+    - efi/mokvar: Reserve the table only if it is in boot services data
+    - SAUCE: integrity: add informational messages when revoking certs
+
+  * Support importing mokx keys into revocation list from the mok table
+    (LP: #1928679) // CVE-2020-26541 when certificates are revoked via
+    MokListXRT.
+    - SAUCE: integrity: Load mokx certs from the EFI MOK config table
+
+  * Focal update: v5.4.157 upstream stable release (LP: #1951883)
+    - ARM: 9133/1: mm: proc-macros: ensure *_tlb_fns are 4B aligned
+    - ARM: 9134/1: remove duplicate memcpy() definition
+    - ARM: 9139/1: kprobes: fix arch_init_kprobes() prototype
+    - ARM: 9141/1: only warn about XIP address when not compile testing
+    - ipv6: use siphash in rt6_exception_hash()
+    - ipv4: use siphash instead of Jenkins in fnhe_hashfun()
+    - usbnet: sanity check for maxpacket
+    - usbnet: fix error return code in usbnet_probe()
+    - Revert "pinctrl: bcm: ns: support updated DT binding as syscon subnode"
+    - ata: sata_mv: Fix the error handling of mv_chip_id()
+    - nfc: port100: fix using -ERRNO as command type mask
+    - net/tls: Fix flipped sign in tls_err_abort() calls
+    - mmc: vub300: fix control-message timeouts
+    - mmc: cqhci: clear HALT state after CQE enable
+    - mmc: dw_mmc: exynos: fix the finding clock sample value
+    - mmc: sdhci: Map more voltage level to SDHCI_POWER_330
+    - mmc: sdhci-esdhc-imx: clear the buffer_read_ready to reset standard tuning
+      circuit
+    - cfg80211: scan: fix RCU in cfg80211_add_nontrans_list()
+    - net: lan78xx: fix division by zero in send path
+    - tcp_bpf: Fix one concurrency problem in the tcp_bpf_send_verdict function
+    - IB/qib: Protect from buffer overflow in struct qib_user_sdma_pkt fields
+    - IB/hfi1: Fix abba locking issue with sc_disable()
+    - nvmet-tcp: fix data digest pointer calculation
+    - nvme-tcp: fix data digest pointer calculation
+    - RDMA/mlx5: Set user priority for DCT
+    - arm64: dts: allwinner: h5: NanoPI Neo 2: Fix ethernet node
+    - regmap: Fix possible double-free in regcache_rbtree_exit()
+    - net: batman-adv: fix error handling
+    - net: Prevent infinite while loop in skb_tx_hash()
+    - RDMA/sa_query: Use strscpy_pad instead of memcpy to copy a string
+    - nios2: Make NIOS2_DTB_SOURCE_BOOL depend on !COMPILE_TEST
+    - net: ethernet: microchip: lan743x: Fix driver crash when lan743x_pm_resume
+      fails
+    - net: ethernet: microchip: lan743x: Fix dma allocation failure by using
+      dma_set_mask_and_coherent
+    - net: nxp: lpc_eth.c: avoid hang when bringing interface down
+    - net/tls: Fix flipped sign in async_wait.err assignment
+    - phy: phy_ethtool_ksettings_get: Lock the phy for consistency
+    - phy: phy_start_aneg: Add an unlocked version
+    - sctp: use init_tag from inithdr for ABORT chunk
+    - sctp: fix the processing for INIT_ACK chunk
+    - sctp: fix the processing for COOKIE_ECHO chunk
+    - sctp: add vtag check in sctp_sf_violation
+    - sctp: add vtag check in sctp_sf_do_8_5_1_E_sa
+    - sctp: add vtag check in sctp_sf_ootb
+    - net: use netif_is_bridge_port() to check for IFF_BRIDGE_PORT
+    - cfg80211: correct bridge/4addr mode check
+    - KVM: s390: clear kicked_mask before sleeping again
+    - KVM: s390: preserve deliverable_mask in __airqs_kick_single_vcpu
+    - perf script: Check session->header.env.arch before using it
+    - Linux 5.4.157
+
+  * keyboard not working on Medion notebook s17 series (LP: #1950536)
+    - ACPI: resources: Add one more Medion model in IRQ override quirk
+
+  * creat09 from ubuntu_ltp_syscalls and cve-2018-13405 from ubuntu_ltp/cve
+    failed with XFS (LP: #1950239)
+    - xfs: ensure that the inode uid/gid match values match the icdinode ones
+    - xfs: merge the projid fields in struct xfs_icdinode
+    - xfs: remove the icdinode di_uid/di_gid members
+    - xfs: fix up non-directory creation in SGID directories
+
+  * reuseport_bpf_numa in net from ubuntu_kernel_selftests fails on ppc64le
+    (LP: #1867570)
+    - selftests/net: Fix reuseport_bpf_numa by skipping unavailable nodes
+
+  * Focal update: v5.4.156 upstream stable release (LP: #1951295)
+    - parisc: math-emu: Fix fall-through warnings
+    - net: switchdev: do not propagate bridge updates across bridges
+    - tee: optee: Fix missing devices unregister during optee_remove
+    - ARM: dts: at91: sama5d2_som1_ek: disable ISC node by default
+    - xtensa: xtfpga: use CONFIG_USE_OF instead of CONFIG_OF
+    - xtensa: xtfpga: Try software restart before simulating CPU reset
+    - NFSD: Keep existing listeners on portlist error
+    - dma-debug: fix sg checks in debug_dma_map_sg()
+    - ASoC: wm8960: Fix clock configuration on slave mode
+    - netfilter: ipvs: make global sysctl readonly in non-init netns
+    - lan78xx: select CRC32
+    - net: dsa: lantiq_gswip: fix register definition
+    - NIOS2: irqflags: rename a redefined register name
+    - net: hns3: reset DWRR of unused tc to zero
+    - net: hns3: add limit ets dwrr bandwidth cannot be 0
+    - net: hns3: disable sriov before unload hclge layer
+    - net: stmmac: Fix E2E delay mechanism
+    - net: enetc: fix ethtool counter name for PM0_TERR
+    - can: rcar_can: fix suspend/resume
+    - can: peak_usb: pcan_usb_fd_decode_status(): fix back to ERROR_ACTIVE state
+      notification
+    - can: peak_pci: peak_pci_remove(): fix UAF
+    - can: j1939: j1939_tp_rxtimer(): fix errant alert in j1939_tp_rxtimer
+    - can: j1939: j1939_netdev_start(): fix UAF for rx_kref of j1939_priv
+    - can: j1939: j1939_xtp_rx_dat_one(): cancel session if receive TP.DT with
+      error length
+    - can: j1939: j1939_xtp_rx_rts_session_new(): abort TP less than 9 bytes
+    - ceph: fix handling of "meta" errors
+    - ocfs2: fix data corruption after conversion from inline format
+    - ocfs2: mount fails with buffer overflow in strlen
+    - elfcore: correct reference to CONFIG_UML
+    - ALSA: usb-audio: Provide quirk for Sennheiser GSP670 Headset
+    - ALSA: hda/realtek: Add quirk for Clevo PC50HS
+    - ASoC: DAPM: Fix missing kctl change notifications
+    - audit: fix possible null-pointer dereference in audit_filter_rules
+    - powerpc64/idle: Fix SP offsets when saving GPRs
+    - KVM: PPC: Book3S HV: Fix stack handling in idle_kvm_start_guest()
+    - KVM: PPC: Book3S HV: Make idle_kvm_start_guest() return 0 if it went to
+      guest
+    - powerpc/idle: Don't corrupt back chain when going idle
+    - mm, slub: fix mismatch between reconstructed freelist depth and cnt
+    - mm, slub: fix potential memoryleak in kmem_cache_open()
+    - nfc: nci: fix the UAF of rf_conn_info object
+    - isdn: cpai: check ctr->cnr to avoid array index out of bound
+    - netfilter: Kconfig: use 'default y' instead of 'm' for bool config option
+    - selftests: netfilter: remove stray bash debug line
+    - gcc-plugins/structleak: add makefile var for disabling structleak
+    - btrfs: deal with errors when checking if a dir entry exists during log
+      replay
+    - net: stmmac: add support for dwmac 3.40a
+    - ARM: dts: spear3xx: Fix gmac node
+    - isdn: mISDN: Fix sleeping function called from invalid context
+    - platform/x86: intel_scu_ipc: Update timeout value in comment
+    - ALSA: hda: avoid write to STATESTS if controller is in reset
+    - Input: snvs_pwrkey - add clk handling
+    - scsi: core: Fix shost->cmd_per_lun calculation in scsi_add_host_with_dma()
+    - tracing: Have all levels of checks prevent recursion
+    - ARM: 9122/1: select HAVE_FUTEX_CMPXCHG
+    - pinctrl: stm32: use valid pin identifier in stm32_pinctrl_resume()
+    - Linux 5.4.156
+
+  * ubuntu_ltp / finit_module02 fails on v4.15 and other kernels
+    (LP: #1950644) // Focal update: v5.4.156 upstream stable release
+    (LP: #1951295)
+    - vfs: check fd has read access in kernel_read_file_from_fd()
+
+  * Focal update: v5.4.155 upstream stable release (LP: #1951291)
+    - ovl: simplify file splice
+    - ALSA: usb-audio: Add quirk for VF0770
+    - ALSA: seq: Fix a potential UAF by wrong private_free call order
+    - ALSA: hda/realtek: Complete partial device name to avoid ambiguity
+    - ALSA: hda/realtek: Add quirk for Clevo X170KM-G
+    - ALSA: hda/realtek - ALC236 headset MIC recording issue
+    - ALSA: hda/realtek: Fix the mic type detection issue for ASUS G551JW
+    - nds32/ftrace: Fix Error: invalid operands (*UND* and *UND* sections) for `^'
+    - s390: fix strrchr() implementation
+    - csky: don't let sigreturn play with priveleged bits of status register
+    - csky: Fixup regs.sr broken in ptrace
+    - btrfs: unlock newly allocated extent buffer after error
+    - btrfs: deal with errors when replaying dir entry during log replay
+    - btrfs: deal with errors when adding inode reference during log replay
+    - btrfs: check for error when looking up inode during dir entry replay
+    - watchdog: orion: use 0 for unset heartbeat
+    - x86/resctrl: Free the ctrlval arrays when domain_setup_mon_state() fails
+    - mei: me: add Ice Lake-N device id.
+    - xhci: guard accesses to ep_state in xhci_endpoint_reset()
+    - xhci: Fix command ring pointer corruption while aborting a command
+    - xhci: Enable trust tx length quirk for Fresco FL11 USB controller
+    - cb710: avoid NULL pointer subtraction
+    - efi/cper: use stack buffer for error record decoding
+    - efi: Change down_interruptible() in virt_efi_reset_system() to
+      down_trylock()
+    - usb: musb: dsps: Fix the probe error path
+    - Input: xpad - add support for another USB ID of Nacon GC-100
+    - USB: serial: qcserial: add EM9191 QDL support
+    - USB: serial: option: add Quectel EC200S-CN module support
+    - USB: serial: option: add Telit LE910Cx composition 0x1204
+    - USB: serial: option: add prod. id for Quectel EG91
+    - EDAC/armada-xp: Fix output of uncorrectable error counter
+    - nvmem: Fix shift-out-of-bound (UBSAN) with byte size cells
+    - x86/Kconfig: Do not enable AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT automatically
+    - powerpc/xive: Discard disabled interrupts in get_irqchip_state()
+    - iio: adc: aspeed: set driver data when adc probe.
+    - iio: adc128s052: Fix the error handling path of 'adc128_probe()'
+    - iio: mtk-auxadc: fix case IIO_CHAN_INFO_PROCESSED
+    - iio: light: opt3001: Fixed timeout error when 0 lux
+    - iio: ssp_sensors: add more range checking in ssp_parse_dataframe()
+    - iio: ssp_sensors: fix error code in ssp_print_mcu_debug()
+    - iio: dac: ti-dac5571: fix an error code in probe()
+    - sctp: account stream padding length for reconf chunk
+    - gpio: pca953x: Improve bias setting
+    - net: arc: select CRC32
+    - net: korina: select CRC32
+    - net/mlx5e: Mutually exclude RX-FCS and RX-port-timestamp
+    - net: stmmac: fix get_hw_feature() on old hardware
+    - net: encx24j600: check error in devm_regmap_init_encx24j600
+    - ethernet: s2io: fix setting mac address during resume
+    - nfc: fix error handling of nfc_proto_register()
+    - NFC: digital: fix possible memory leak in digital_tg_listen_mdaa()
+    - NFC: digital: fix possible memory leak in digital_in_send_sdd_req()
+    - pata_legacy: fix a couple uninitialized variable bugs
+    - ata: ahci_platform: fix null-ptr-deref in ahci_platform_enable_regulators()
+    - mlxsw: thermal: Fix out-of-bounds memory accesses
+    - platform/mellanox: mlxreg-io: Fix argument base in kstrtou32() call
+    - drm/panel: olimex-lcd-olinuxino: select CRC32
+    - drm/msm: Fix null pointer dereference on pointer edp
+    - drm/msm/dsi: Fix an error code in msm_dsi_modeset_init()
+    - drm/msm/dsi: fix off by one in dsi_bus_clk_enable error handling
+    - acpi/arm64: fix next_platform_timer() section mismatch error
+    - mqprio: Correct stats in mqprio_dump_class_stats().
+    - qed: Fix missing error code in qed_slowpath_start()
+    - r8152: select CRC32 and CRYPTO/CRYPTO_HASH/CRYPTO_SHA256
+    - ionic: don't remove netdev->dev_addr when syncing uc list
+    - Linux 5.4.155
+
+  * [UBUNTU 20.04] kernel:  unable to read partitions on virtio-block dasd (kvm)
+    (LP: #1950144) // Focal update: v5.4.155 upstream stable release
+    (LP: #1951291)
+    - virtio: write back F_VERSION_1 before validate
+
+  * Focal update: v5.4.154 upstream stable release (LP: #1951288)
+    - net: phy: bcm7xxx: Fixed indirect MMD operations
+    - ext4: correct the error path of ext4_write_inline_data_end()
+    - HID: apple: Fix logical maximum and usage maximum of Magic Keyboard JIS
+    - netfilter: ip6_tables: zero-initialize fragment offset
+    - HID: wacom: Add new Intuos BT (CTL-4100WL/CTL-6100WL) device IDs
+    - netfilter: nf_nat_masquerade: make async masq_inet6_event handling generic
+    - netfilter: nf_nat_masquerade: defer conntrack walk to work queue
+    - mac80211: Drop frames from invalid MAC address in ad-hoc mode
+    - m68k: Handle arrivals of multiple signals correctly
+    - net: prevent user from passing illegal stab size
+    - mac80211: check return value of rhashtable_init
+    - net: sun: SUNVNET_COMMON should depend on INET
+    - drm/amdgpu: fix gart.bo pin_count leak
+    - scsi: ses: Fix unsigned comparison with less than zero
+    - scsi: virtio_scsi: Fix spelling mistake "Unsupport" -> "Unsupported"
+    - sched: Always inline is_percpu_thread()
+    - Linux 5.4.154
+
+  * Focal update: v5.4.153 upstream stable release (LP: #1950014)
+    - Partially revert "usb: Kconfig: using select for USB_COMMON dependency"
+    - USB: cdc-acm: fix racy tty buffer accesses
+    - USB: cdc-acm: fix break reporting
+    - usb: typec: tcpm: handle SRC_STARTUP state if cc changes
+    - xen/privcmd: fix error handling in mmap-resource processing
+    - mmc: meson-gx: do not use memcpy_to/fromio for dram-access-quirk
+    - ovl: fix missing negative dentry check in ovl_rename()
+    - nfsd: fix error handling of register_pernet_subsys() in init_nfsd()
+    - nfsd4: Handle the NFSv4 READDIR 'dircount' hint being zero
+    - xen/balloon: fix cancelled balloon action
+    - ARM: dts: omap3430-sdp: Fix NAND device node
+    - ARM: dts: qcom: apq8064: use compatible which contains chipid
+    - MIPS: BPF: Restore MIPS32 cBPF JIT
+    - bpf, mips: Validate conditional branch offsets
+    - soc: qcom: socinfo: Fixed argument passed to platform_set_data()
+    - ARM: dts: qcom: apq8064: Use 27MHz PXO clock as DSI PLL reference
+    - soc: qcom: mdt_loader: Drop PT_LOAD check on hash segment
+    - ARM: dts: imx: Add missing pinctrl-names for panel on M53Menlo
+    - ARM: dts: imx: Fix USB host power regulator polarity on M53Menlo
+    - arm64: dts: qcom: pm8150: use qcom,pm8998-pon binding
+    - xtensa: move XCHAL_KIO_* definitions to kmem_layout.h
+    - xtensa: use CONFIG_USE_OF instead of CONFIG_OF
+    - xtensa: call irqchip_init only when CONFIG_USE_OF is selected
+    - bpf, arm: Fix register clobbering in div/mod implementation
+    - bpf: Fix integer overflow in prealloc_elems_and_freelist()
+    - phy: mdio: fix memory leak
+    - net_sched: fix NULL deref in fifo_set_limit()
+    - powerpc/fsl/dts: Fix phy-connection-type for fm1mac3
+    - ptp_pch: Load module automatically if ID matches
+    - arm64: dts: freescale: Fix SP805 clock-names
+    - arm64: dts: ls1028a: add missing CAN nodes
+    - ARM: imx6: disable the GIC CPU interface before calling stby-poweroff
+      sequence
+    - net: bridge: use nla_total_size_64bit() in br_get_linkxstats_size()
+    - net/sched: sch_taprio: properly cancel timer from taprio_destroy()
+    - net: sfp: Fix typo in state machine debug string
+    - netlink: annotate data races around nlk->bound
+    - bus: ti-sysc: Use CLKDM_NOAUTO for dra7 dcan1 for errata i893
+    - video: fbdev: gbefb: Only instantiate device when built for IP32
+    - drm/nouveau/debugfs: fix file release memory leak
+    - gve: Correct available tx qpl check
+    - rtnetlink: fix if_nlmsg_stats_size() under estimation
+    - gve: fix gve_get_stats()
+    - i40e: fix endless loop under rtnl
+    - i40e: Fix freeing of uninitialized misc IRQ vector
+    - net: prefer socket bound to interface when not in VRF
+    - i2c: acpi: fix resource leak in reconfiguration device addition
+    - bpf, s390: Fix potential memory leak about jit_data
+    - RISC-V: Include clone3() on rv32
+    - x86/platform/olpc: Correct ifdef symbol to intended CONFIG_OLPC_XO15_SCI
+    - x86/hpet: Use another crystalball to evaluate HPET usability
+    - x86/Kconfig: Correct reference to MWINCHIP3D
+    - Linux 5.4.153
+
+  * Focal update: v5.4.152 upstream stable release (LP: #1950009)
+    - net: mdio: introduce a shutdown method to mdio device drivers
+    - xen-netback: correct success/error reporting for the SKB-with-fraglist case
+    - sparc64: fix pci_iounmap() when CONFIG_PCI is not set
+    - ext2: fix sleeping in atomic bugs on error
+    - scsi: sd: Free scsi_disk device via put_device()
+    - usb: testusb: Fix for showing the connection speed
+    - usb: dwc2: check return value after calling platform_get_resource()
+    - selftests: be sure to make khdr before other targets
+    - selftests:kvm: fix get_warnings_count() ignoring fscanf() return warn
+    - scsi: ses: Retry failed Send/Receive Diagnostic commands
+    - tools/vm/page-types: remove dependency on opt_file for idle page tracking
+    - KVM: do not shrink halt_poll_ns below grow_start
+    - kvm: x86: Add AMD PMU MSRs to msrs_to_save_all[]
+    - perf/x86: Reset destroy callback on event init failure
+    - silence nfscache allocation warnings with kvzalloc
+    - libata: Add ATA_HORKAGE_NO_NCQ_ON_ATI for Samsung 860 and 870 SSD.
+    - Linux 5.4.152
+
+  * linux-aws: Fix backport of RDMA/efa: Expose maximum  TX doorbell batch
+    (LP: #1949882)
+    - SAUCE: aws: Fix backport of RDMA/efa: Expose maximum TX doorbell batch
+
+ -- Kleber Sacilotto de Souza <kleber.souza@canonical.com>  Fri, 26 Nov 2021 15:42:03 +0100
+
+linux (5.4.0-91.102) focal; urgency=medium
+
+  * focal/linux: 5.4.0-91.102 -proposed tracker (LP: #1949840)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update Ubuntu.md
+    - debian/dkms-versions -- update from kernel-versions (main/2021.11.08)
+
+  * KVM emulation failure when booting into  VM crash kernel with multiple CPUs
+    (LP: #1948862)
+    - KVM: x86: Properly reset MMU context at vCPU RESET/INIT
+
+  * aufs: kernel bug with apparmor and fuseblk (LP: #1948470)
+    - SAUCE: aufs: bugfix, stop omitting path->mnt
+
+  * ebpf:  bpf_redirect fails with ip6 gre interfaces (LP: #1947164)
+    - net: handle ARPHRD_IP6GRE in dev_is_mac_header_xmit()
+
+  * require CAP_NET_ADMIN to attach N_HCI ldisc (LP: #1949516)
+    - Bluetooth: hci_ldisc: require CAP_NET_ADMIN to attach N_HCI ldisc
+
+  * ACL updates on OCFS2 are not revalidated (LP: #1947161)
+    - ocfs2: fix remounting needed after setfacl command
+
+  * ppc64 BPF JIT mod by 1 will not return 0 (LP: #1948351)
+    - powerpc/bpf: Fix BPF_MOD when imm == 1
+
+  * Drop "UBUNTU: SAUCE: cachefiles: Page leaking in
+    cachefiles_read_backing_file while vmscan is active" (LP: #1947709)
+    - Revert "UBUNTU: SAUCE: cachefiles: Page leaking in
+      cachefiles_read_backing_file while vmscan is active"
+
+  * Reassign I/O Path of ConnectX-5 Port 1 before Port 2 causes NULL dereference
+    (LP: #1943464)
+    - s390/pci: fix leak of PCI device structure
+    - s390/pci: fix use after free of zpci_dev
+    - s390/pci: fix zpci_zdev_put() on reserve
+
+  * [SRU][F] USB: serial: pl2303: add support for PL2303HXN (LP: #1948377)
+    - USB: serial: pl2303: add support for PL2303HXN
+    - USB: serial: pl2303: fix line-speed handling on newer chips
+
+  * Focal update: v5.4.151 upstream stable release (LP: #1947888)
+    - tty: Fix out-of-bound vmalloc access in imageblit
+    - cpufreq: schedutil: Use kobject release() method to free sugov_tunables
+    - cpufreq: schedutil: Destroy mutex before kobject_put() frees the memory
+    - usb: cdns3: fix race condition before setting doorbell
+    - fs-verity: fix signed integer overflow with i_size near S64_MAX
+    - hwmon: (w83793) Fix NULL pointer dereference by removing unnecessary
+      structure field
+    - hwmon: (w83792d) Fix NULL pointer dereference by removing unnecessary
+      structure field
+    - hwmon: (w83791d) Fix NULL pointer dereference by removing unnecessary
+      structure field
+    - scsi: ufs: Fix illegal offset in UPIU event trace
+    - mac80211: fix use-after-free in CCMP/GCMP RX
+    - x86/kvmclock: Move this_cpu_pvti into kvmclock.h
+    - drm/amd/display: Pass PCI deviceid into DC
+    - ipvs: check that ip_vs_conn_tab_bits is between 8 and 20
+    - hwmon: (mlxreg-fan) Return non-zero value when fan current state is enforced
+      from sysfs
+    - mac80211: Fix ieee80211_amsdu_aggregate frag_tail bug
+    - mac80211: limit injected vht mcs/nss in ieee80211_parse_tx_radiotap
+    - mac80211: mesh: fix potentially unaligned access
+    - mac80211-hwsim: fix late beacon hrtimer handling
+    - sctp: break out if skb_header_pointer returns NULL in sctp_rcv_ootb
+    - hwmon: (tmp421) report /PVLD condition as fault
+    - hwmon: (tmp421) fix rounding for negative values
+    - net: ipv4: Fix rtnexthop len when RTA_FLOW is present
+    - e100: fix length calculation in e100_get_regs_len
+    - e100: fix buffer overrun in e100_get_regs
+    - selftests, bpf: test_lwt_ip_encap: Really disable rp_filter
+    - scsi: csiostor: Add module softdep on cxgb4
+    - net: hns3: do not allow call hns3_nic_net_open repeatedly
+    - net: sched: flower: protect fl_walk() with rcu
+    - af_unix: fix races in sk_peer_pid and sk_peer_cred accesses
+    - perf/x86/intel: Update event constraints for ICX
+    - elf: don't use MAP_FIXED_NOREPLACE for elf interpreter mappings
+    - debugfs: debugfs_create_file_size(): use IS_ERR to check for error
+    - ipack: ipoctal: fix stack information leak
+    - ipack: ipoctal: fix tty registration race
+    - ipack: ipoctal: fix tty-registration error handling
+    - ipack: ipoctal: fix missing allocation-failure check
+    - ipack: ipoctal: fix module reference leak
+    - ext4: fix loff_t overflow in ext4_max_bitmap_size()
+    - ext4: fix reserved space counter leakage
+    - ext4: fix potential infinite loop in ext4_dx_readdir()
+    - HID: u2fzero: ignore incomplete packets without data
+    - net: udp: annotate data race around udp_sk(sk)->corkflag
+    - net: stmmac: don't attach interface until resume finishes
+    - PCI: Fix pci_host_bridge struct device release/free handling
+    - libnvdimm/pmem: Fix crash triggered when I/O in-flight during unbind
+    - hso: fix bailout in error case of probe
+    - usb: hso: fix error handling code of hso_create_net_device
+    - usb: hso: remove the bailout parameter
+    - crypto: ccp - fix resource leaks in ccp_run_aes_gcm_cmd()
+    - HID: betop: fix slab-out-of-bounds Write in betop_probe
+    - netfilter: ipset: Fix oversized kvmalloc() calls
+    - HID: usbhid: free raw_report buffers in usbhid_stop
+    - Linux 5.4.151
+
+  * Focal update: v5.4.150 upstream stable release (LP: #1947886)
+    - usb: gadget: r8a66597: fix a loop in set_feature()
+    - usb: dwc2: gadget: Fix ISOC flow for BDMA and Slave
+    - usb: dwc2: gadget: Fix ISOC transfer complete handling for DDMA
+    - usb: musb: tusb6010: uninitialized data in tusb_fifo_write_unaligned()
+    - cifs: fix incorrect check for null pointer in header_assemble
+    - xen/x86: fix PV trap handling on secondary processors
+    - usb-storage: Add quirk for ScanLogic SL11R-IDE older than 2.6c
+    - USB: serial: cp210x: add ID for GW Instek GDM-834x Digital Multimeter
+    - USB: cdc-acm: fix minor-number release
+    - binder: make sure fd closes complete
+    - staging: greybus: uart: fix tty use after free
+    - Re-enable UAS for LaCie Rugged USB3-FW with fk quirk
+    - USB: serial: mos7840: remove duplicated 0xac24 device ID
+    - USB: serial: option: add Telit LN920 compositions
+    - USB: serial: option: remove duplicate USB device ID
+    - USB: serial: option: add device id for Foxconn T99W265
+    - mcb: fix error handling in mcb_alloc_bus()
+    - erofs: fix up erofs_lookup tracepoint
+    - btrfs: prevent __btrfs_dump_space_info() to underflow its free space
+    - serial: mvebu-uart: fix driver's tx_empty callback
+    - net: hso: fix muxed tty registration
+    - afs: Fix incorrect triggering of sillyrename on 3rd-party invalidation
+    - platform/x86/intel: punit_ipc: Drop wrong use of ACPI_PTR()
+    - enetc: Fix illegal access when reading affinity_hint
+    - bnxt_en: Fix TX timeout when TX ring size is set to the smallest
+    - net/smc: add missing error check in smc_clc_prfx_set()
+    - gpio: uniphier: Fix void functions to remove return value
+    - qed: rdma - don't wait for resources under hw error recovery flow
+    - net/mlx4_en: Don't allow aRFS for encapsulated packets
+    - scsi: iscsi: Adjust iface sysfs attr detection
+    - tty: synclink_gt, drop unneeded forward declarations
+    - tty: synclink_gt: rename a conflicting function name
+    - fpga: machxo2-spi: Return an error on failure
+    - fpga: machxo2-spi: Fix missing error code in machxo2_write_complete()
+    - thermal/core: Potential buffer overflow in thermal_build_list_of_policies()
+    - cifs: fix a sign extension bug
+    - scsi: qla2xxx: Restore initiator in dual mode
+    - scsi: lpfc: Use correct scnprintf() limit
+    - irqchip/goldfish-pic: Select GENERIC_IRQ_CHIP to fix build
+    - irqchip/gic-v3-its: Fix potential VPE leak on error
+    - md: fix a lock order reversal in md_alloc
+    - blktrace: Fix uaf in blk_trace access after removing by sysfs
+    - net: macb: fix use after free on rmmod
+    - net: stmmac: allow CSR clock of 300MHz
+    - m68k: Double cast io functions to unsigned long
+    - ipv6: delay fib6_sernum increase in fib6_add
+    - bpf: Add oversize check before call kvcalloc()
+    - xen/balloon: use a kernel thread instead a workqueue
+    - nvme-multipath: fix ANA state updates when a namespace is not present
+    - sparc32: page align size in arch_dma_alloc
+    - blk-cgroup: fix UAF by grabbing blkcg lock before destroying blkg pd
+    - compiler.h: Introduce absolute_pointer macro
+    - net: i825xx: Use absolute_pointer for memcpy from fixed memory location
+    - sparc: avoid stringop-overread errors
+    - qnx4: avoid stringop-overread errors
+    - parisc: Use absolute_pointer() to define PAGE0
+    - arm64: Mark __stack_chk_guard as __ro_after_init
+    - alpha: Declare virt_to_phys and virt_to_bus parameter as pointer to volatile
+    - net: 6pack: Fix tx timeout and slot time
+    - spi: Fix tegra20 build with CONFIG_PM=n
+    - EDAC/synopsys: Fix wrong value type assignment for edac_mode
+    - thermal/drivers/int340x: Do not set a wrong tcc offset on resume
+    - arm64: dts: marvell: armada-37xx: Extend PCIe MEM space
+    - xen/balloon: fix balloon kthread freezing
+    - qnx4: work around gcc false positive warning bug
+    - Linux 5.4.150
+
+  * ACL updates on OCFS2 are not revalidated (LP: #1947161) // Focal update:
+    v5.4.150 upstream stable release (LP: #1947886)
+    - ocfs2: drop acl cache for directories too
+
+  * Focal update: v5.4.149 upstream stable release (LP: #1947885)
+    - PCI: pci-bridge-emul: Fix big-endian support
+    - PCI: aardvark: Indicate error in 'val' when config read fails
+    - PCI: pci-bridge-emul: Add PCIe Root Capabilities Register
+    - PCI: aardvark: Fix reporting CRS value
+    - PCI/ACPI: Add Ampere Altra SOC MCFG quirk
+    - KVM: remember position in kvm->vcpus array
+    - console: consume APC, DM, DCS
+    - s390/pci_mmio: fully validate the VMA before calling follow_pte()
+    - ARM: Qualify enabling of swiotlb_init()
+    - apparmor: remove duplicate macro list_entry_is_head()
+    - ARM: 9077/1: PLT: Move struct plt_entries definition to header
+    - ARM: 9078/1: Add warn suppress parameter to arm_gen_branch_link()
+    - ARM: 9079/1: ftrace: Add MODULE_PLTS support
+    - ARM: 9098/1: ftrace: MODULE_PLT: Fix build problem without DYNAMIC_FTRACE
+    - sctp: validate chunk size in __rcv_asconf_lookup
+    - sctp: add param size validation for SCTP_PARAM_SET_PRIMARY
+    - staging: rtl8192u: Fix bitwise vs logical operator in
+      TranslateRxSignalStuff819xUsb()
+    - um: virtio_uml: fix memory leak on init failures
+    - dmaengine: acpi: Avoid comparison GSI with Linux vIRQ
+    - thermal/drivers/exynos: Fix an error code in exynos_tmu_probe()
+    - 9p/trans_virtio: Remove sysfs file on probe failure
+    - prctl: allow to setup brk for et_dyn executables
+    - nilfs2: use refcount_dec_and_lock() to fix potential UAF
+    - profiling: fix shift-out-of-bounds bugs
+    - pwm: lpc32xx: Don't modify HW state in .probe() after the PWM chip was
+      registered
+    - phy: avoid unnecessary link-up delay in polling mode
+    - net: stmmac: reset Tx desc base address before restarting Tx
+    - Kconfig.debug: drop selecting non-existing HARDLOCKUP_DETECTOR_ARCH
+    - thermal/core: Fix thermal_cooling_device_register() prototype
+    - drivers: base: cacheinfo: Get rid of DEFINE_SMP_CALL_CACHE_FUNCTION()
+    - parisc: Move pci_dev_is_behind_card_dino to where it is used
+    - dmaengine: sprd: Add missing MODULE_DEVICE_TABLE
+    - dmaengine: ioat: depends on !UML
+    - dmaengine: xilinx_dma: Set DMA mask for coherent APIs
+    - ceph: request Fw caps before updating the mtime in ceph_write_iter
+    - ceph: lockdep annotations for try_nonblocking_invalidate
+    - btrfs: fix lockdep warning while mounting sprout fs
+    - nilfs2: fix memory leak in nilfs_sysfs_create_device_group
+    - nilfs2: fix NULL pointer in nilfs_##name##_attr_release
+    - nilfs2: fix memory leak in nilfs_sysfs_create_##name##_group
+    - nilfs2: fix memory leak in nilfs_sysfs_delete_##name##_group
+    - nilfs2: fix memory leak in nilfs_sysfs_create_snapshot_group
+    - nilfs2: fix memory leak in nilfs_sysfs_delete_snapshot_group
+    - pwm: img: Don't modify HW state in .remove() callback
+    - pwm: rockchip: Don't modify HW state in .remove() callback
+    - pwm: stm32-lp: Don't modify HW state in .remove() callback
+    - blk-throttle: fix UAF by deleteing timer in blk_throtl_exit()
+    - rtc: rx8010: select REGMAP_I2C
+    - drm/nouveau/nvkm: Replace -ENOSYS with -ENODEV
+    - Linux 5.4.149
+
+ -- Kleber Sacilotto de Souza <kleber.souza@canonical.com>  Fri, 05 Nov 2021 17:02:56 +0100
+
+linux (5.4.0-90.101) focal; urgency=medium
+
+  * focal/linux: 5.4.0-90.101 -proposed tracker (LP: #1947260)
+
+  * Packaging resync (LP: #1786013)
+    - debian/dkms-versions -- update from kernel-versions (main/2021.10.18)
+
+  * Add final-checks to check certificates (LP: #1947174)
+    - [Packaging] Add system trusted and revocation keys final check
+
+  * No sound on Lenovo laptop models Legion 15IMHG05, Yoga 7 14ITL5, and 13s
+    Gen2 (LP: #1939052)
+    - ALSA: hda/realtek: Quirks to enable speaker output for Lenovo Legion 7i
+      15IMHG05, Yoga 7i 14ITL5/15ITL5, and 13s Gen2 laptops.
+    - ALSA: hda/realtek: Fix for quirk to enable speaker output on the Lenovo 13s
+      Gen2
+
+  * CVE-2020-36385
+    - RDMA/cma: Add missing locking to rdma_accept()
+    - RDMA/ucma: Fix the locking of ctx->file
+    - RDMA/ucma: Rework ucma_migrate_id() to avoid races with destroy
+
+  * Focal update: v5.4.148 upstream stable release (LP: #1946802)
+    - rtc: tps65910: Correct driver module alias
+    - btrfs: wake up async_delalloc_pages waiters after submit
+    - btrfs: reset replace target device to allocation state on close
+    - blk-zoned: allow zone management send operations without CAP_SYS_ADMIN
+    - blk-zoned: allow BLKREPORTZONE without CAP_SYS_ADMIN
+    - PCI/MSI: Skip masking MSI-X on Xen PV
+    - powerpc/perf/hv-gpci: Fix counter value parsing
+    - xen: fix setting of max_pfn in shared_info
+    - include/linux/list.h: add a macro to test if entry is pointing to the head
+    - 9p/xen: Fix end of loop tests for list_for_each_entry
+    - tools/thermal/tmon: Add cross compiling support
+    - pinctrl: stmfx: Fix hazardous u8[] to unsigned long cast
+    - pinctrl: ingenic: Fix incorrect pull up/down info
+    - soc: qcom: aoss: Fix the out of bound usage of cooling_devs
+    - soc: aspeed: lpc-ctrl: Fix boundary check for mmap
+    - soc: aspeed: p2a-ctrl: Fix boundary check for mmap
+    - arm64: head: avoid over-mapping in map_memory
+    - crypto: public_key: fix overflow during implicit conversion
+    - block: bfq: fix bfq_set_next_ioprio_data()
+    - power: supply: max17042: handle fails of reading status register
+    - dm crypt: Avoid percpu_counter spinlock contention in crypt_page_alloc()
+    - VMCI: fix NULL pointer dereference when unmapping queue pair
+    - media: uvc: don't do DMA on stack
+    - media: rc-loopback: return number of emitters rather than error
+    - Revert "dmaengine: imx-sdma: refine to load context only once"
+    - dmaengine: imx-sdma: remove duplicated sdma_load_context
+    - libata: add ATA_HORKAGE_NO_NCQ_TRIM for Samsung 860 and 870 SSDs
+    - ARM: 9105/1: atags_to_fdt: don't warn about stack size
+    - PCI/portdrv: Enable Bandwidth Notification only if port supports it
+    - PCI: Restrict ASMedia ASM1062 SATA Max Payload Size Supported
+    - PCI: Return ~0 data on pciconfig_read() CAP_SYS_ADMIN failure
+    - PCI: xilinx-nwl: Enable the clock through CCF
+    - PCI: aardvark: Fix checking for PIO status
+    - PCI: aardvark: Increase polling delay to 1.5s while waiting for PIO response
+    - PCI: aardvark: Fix masking and unmasking legacy INTx interrupts
+    - HID: input: do not report stylus battery state as "full"
+    - f2fs: quota: fix potential deadlock
+    - scsi: bsg: Remove support for SCSI_IOCTL_SEND_COMMAND
+    - IB/hfi1: Adjust pkey entry in index 0
+    - RDMA/iwcm: Release resources if iw_cm module initialization fails
+    - docs: Fix infiniband uverbs minor number
+    - pinctrl: samsung: Fix pinctrl bank pin count
+    - vfio: Use config not menuconfig for VFIO_NOIOMMU
+    - powerpc/stacktrace: Include linux/delay.h
+    - RDMA/efa: Remove double QP type assignment
+    - f2fs: show f2fs instance in printk_ratelimited
+    - f2fs: reduce the scope of setting fsck tag when de->name_len is zero
+    - openrisc: don't printk() unconditionally
+    - dma-debug: fix debugfs initialization order
+    - SUNRPC: Fix potential memory corruption
+    - scsi: fdomain: Fix error return code in fdomain_probe()
+    - pinctrl: single: Fix error return code in pcs_parse_bits_in_pinctrl_entry()
+    - scsi: smartpqi: Fix an error code in pqi_get_raid_map()
+    - scsi: qedi: Fix error codes in qedi_alloc_global_queues()
+    - scsi: qedf: Fix error codes in qedf_alloc_global_queues()
+    - powerpc/config: Renable MTD_PHYSMAP_OF
+    - scsi: target: avoid per-loop XCOPY buffer allocations
+    - HID: i2c-hid: Fix Elan touchpad regression
+    - KVM: PPC: Book3S HV Nested: Reflect guest PMU in-use to L0 when guest SPRs
+      are live
+    - platform/x86: dell-smbios-wmi: Add missing kfree in error-exit from
+      run_smbios_call
+    - fscache: Fix cookie key hashing
+    - clk: at91: sam9x60: Don't use audio PLL
+    - clk: at91: clk-generated: pass the id of changeable parent at registration
+    - clk: at91: clk-generated: Limit the requested rate to our range
+    - KVM: PPC: Fix clearing never mapped TCEs in realmode
+    - f2fs: fix to account missing .skipped_gc_rwsem
+    - f2fs: fix unexpected ENOENT comes from f2fs_map_blocks()
+    - f2fs: fix to unmap pages from userspace process in punch_hole()
+    - MIPS: Malta: fix alignment of the devicetree buffer
+    - kbuild: Fix 'no symbols' warning when CONFIG_TRIM_UNUSD_KSYMS=y
+    - userfaultfd: prevent concurrent API initialization
+    - drm/amdgpu: Fix amdgpu_ras_eeprom_init()
+    - ASoC: atmel: ATMEL drivers don't need HAS_DMA
+    - media: dib8000: rewrite the init prbs logic
+    - crypto: mxs-dcp - Use sg_mapping_iter to copy data
+    - PCI: Use pci_update_current_state() in pci_enable_device_flags()
+    - tipc: keep the skb in rcv queue until the whole data is read
+    - iio: dac: ad5624r: Fix incorrect handling of an optional regulator.
+    - iavf: do not override the adapter state in the watchdog task
+    - iavf: fix locking of critical sections
+    - ARM: dts: qcom: apq8064: correct clock names
+    - video: fbdev: kyro: fix a DoS bug by restricting user input
+    - netlink: Deal with ESRCH error in nlmsg_notify()
+    - Smack: Fix wrong semantics in smk_access_entry()
+    - drm: avoid blocking in drm_clients_info's rcu section
+    - igc: Check if num of q_vectors is smaller than max before array access
+    - usb: host: fotg210: fix the endpoint's transactional opportunities
+      calculation
+    - usb: host: fotg210: fix the actual_length of an iso packet
+    - usb: gadget: u_ether: fix a potential null pointer dereference
+    - USB: EHCI: ehci-mv: improve error handling in mv_ehci_enable()
+    - usb: gadget: composite: Allow bMaxPower=0 if self-powered
+    - staging: board: Fix uninitialized spinlock when attaching genpd
+    - tty: serial: jsm: hold port lock when reporting modem line changes
+    - drm/amd/display: Fix timer_per_pixel unit error
+    - drm/amd/amdgpu: Update debugfs link_settings output link_rate field in hex
+    - bpf/tests: Fix copy-and-paste error in double word test
+    - bpf/tests: Do not PASS tests without actually testing the result
+    - video: fbdev: asiliantfb: Error out if 'pixclock' equals zero
+    - video: fbdev: kyro: Error out if 'pixclock' equals zero
+    - video: fbdev: riva: Error out if 'pixclock' equals zero
+    - ipv4: ip_output.c: Fix out-of-bounds warning in ip_copy_addrs()
+    - flow_dissector: Fix out-of-bounds warnings
+    - s390/jump_label: print real address in a case of a jump label bug
+    - s390: make PCI mio support a machine flag
+    - serial: 8250: Define RX trigger levels for OxSemi 950 devices
+    - xtensa: ISS: don't panic in rs_init
+    - hvsi: don't panic on tty_register_driver failure
+    - serial: 8250_pci: make setup_port() parameters explicitly unsigned
+    - staging: ks7010: Fix the initialization of the 'sleep_status' structure
+    - samples: bpf: Fix tracex7 error raised on the missing argument
+    - ata: sata_dwc_460ex: No need to call phy_exit() befre phy_init()
+    - Bluetooth: skip invalid hci_sync_conn_complete_evt
+    - workqueue: Fix possible memory leaks in wq_numa_init()
+    - bonding: 3ad: fix the concurrency between __bond_release_one() and
+      bond_3ad_state_machine_handler()
+    - arm64: tegra: Fix Tegra194 PCIe EP compatible string
+    - ASoC: Intel: bytcr_rt5640: Move "Platform Clock" routes to the maps for the
+      matching in-/output
+    - media: imx258: Rectify mismatch of VTS value
+    - media: imx258: Limit the max analogue gain to 480
+    - media: v4l2-dv-timings.c: fix wrong condition in two for-loops
+    - media: TDA1997x: fix tda1997x_query_dv_timings() return value
+    - media: tegra-cec: Handle errors of clk_prepare_enable()
+    - ARM: dts: imx53-ppd: Fix ACHC entry
+    - arm64: dts: qcom: sdm660: use reg value for memory node
+    - net: ethernet: stmmac: Do not use unreachable() in ipq806x_gmac_probe()
+    - drm/msm: mdp4: drop vblank get/put from prepare/complete_commit
+    - selftests/bpf: Fix xdp_tx.c prog section name
+    - Bluetooth: schedule SCO timeouts with delayed_work
+    - Bluetooth: avoid circular locks in sco_sock_connect
+    - net/mlx5: Fix variable type to match 64bit
+    - gpu: drm: amd: amdgpu: amdgpu_i2c: fix possible uninitialized-variable
+      access in amdgpu_i2c_router_select_ddc_port()
+    - drm/display: fix possible null-pointer dereference in dcn10_set_clock()
+    - mac80211: Fix monitor MTU limit so that A-MSDUs get through
+    - ARM: tegra: tamonten: Fix UART pad setting
+    - arm64: tegra: Fix compatible string for Tegra132 CPUs
+    - arm64: dts: ls1046a: fix eeprom entries
+    - nvme-tcp: don't check blk_mq_tag_to_rq when receiving pdu data
+    - Bluetooth: Fix handling of LE Enhanced Connection Complete
+    - opp: Don't print an error if required-opps is missing
+    - serial: sh-sci: fix break handling for sysrq
+    - tcp: enable data-less, empty-cookie SYN with TFO_SERVER_COOKIE_NOT_REQD
+    - rpc: fix gss_svc_init cleanup on failure
+    - staging: rts5208: Fix get_ms_information() heap buffer size
+    - gfs2: Don't call dlm after protocol is unmounted
+    - usb: chipidea: host: fix port index underflow and UBSAN complains
+    - lockd: lockd server-side shouldn't set fl_ops
+    - drm/exynos: Always initialize mapping in exynos_drm_register_dma()
+    - m68knommu: only set CONFIG_ISA_DMA_API for ColdFire sub-arch
+    - btrfs: tree-log: check btrfs_lookup_data_extent return value
+    - ASoC: Intel: Skylake: Fix module configuration for KPB and MIXER
+    - ASoC: Intel: Skylake: Fix passing loadable flag for module
+    - of: Don't allow __of_attached_node_sysfs() without CONFIG_SYSFS
+    - mmc: sdhci-of-arasan: Check return value of non-void funtions
+    - mmc: rtsx_pci: Fix long reads when clock is prescaled
+    - selftests/bpf: Enlarge select() timeout for test_maps
+    - mmc: core: Return correct emmc response in case of ioctl error
+    - cifs: fix wrong release in sess_alloc_buffer() failed path
+    - Revert "USB: xhci: fix U1/U2 handling for hardware with XHCI_INTEL_HOST
+      quirk set"
+    - usb: musb: musb_dsps: request_irq() after initializing musb
+    - usbip: give back URBs for unsent unlink requests during cleanup
+    - usbip:vhci_hcd USB port can get stuck in the disabled state
+    - ASoC: rockchip: i2s: Fix regmap_ops hang
+    - ASoC: rockchip: i2s: Fixup config for DAIFMT_DSP_A/B
+    - drm/amdkfd: Account for SH/SE count when setting up cu masks.
+    - iwlwifi: mvm: fix a memory leak in iwl_mvm_mac_ctxt_beacon_changed
+    - iwlwifi: mvm: avoid static queue number aliasing
+    - iwlwifi: mvm: fix access to BSS elements
+    - net/mlx5: DR, Enable QP retransmission
+    - parport: remove non-zero check on count
+    - ath9k: fix OOB read ar9300_eeprom_restore_internal
+    - ath9k: fix sleeping in atomic context
+    - net: fix NULL pointer reference in cipso_v4_doi_free
+    - fix array-index-out-of-bounds in taprio_change
+    - net: w5100: check return value after calling platform_get_resource()
+    - parisc: fix crash with signals and alloca
+    - ovl: fix BUG_ON() in may_delete() when called from ovl_cleanup()
+    - scsi: BusLogic: Fix missing pr_cont() use
+    - scsi: qla2xxx: Changes to support kdump kernel
+    - scsi: qla2xxx: Sync queue idx with queue_pair_map idx
+    - cpufreq: powernv: Fix init_chip_info initialization in numa=off
+    - s390/pv: fix the forcing of the swiotlb
+    - mm/hugetlb: initialize hugetlb_usage in mm_init
+    - mm,vmscan: fix divide by zero in get_scan_count
+    - memcg: enable accounting for pids in nested pid namespaces
+    - platform/chrome: cros_ec_proto: Send command again when timeout occurs
+    - lib/test_stackinit: Fix static initializer test
+    - net: dsa: lantiq_gswip: fix maximum frame length
+    - drm/msi/mdp4: populate priv->kms in mdp4_kms_init
+    - drm/amdgpu: Fix BUG_ON assert
+    - drm/panfrost: Simplify lock_region calculation
+    - drm/panfrost: Use u64 for size in lock_region
+    - drm/panfrost: Clamp lock region to Bifrost minimum
+    - btrfs: fix upper limit for max_inline for page size 64K
+    - xen: reset legacy rtc flag for PV domU
+    - bnx2x: Fix enabling network interfaces without VFs
+    - arm64/sve: Use correct size when reinitialising SVE state
+    - PM: base: power: don't try to use non-existing RTC for storing data
+    - PCI: Add AMD GPU multi-function power dependencies
+    - drm/amd/amdgpu: Increase HWIP_MAX_INSTANCE to 10
+    - drm/etnaviv: return context from etnaviv_iommu_context_get
+    - drm/etnaviv: put submit prev MMU context when it exists
+    - drm/etnaviv: stop abusing mmu_context as FE running marker
+    - drm/etnaviv: keep MMU context across runtime suspend/resume
+    - drm/etnaviv: exec and MMU state is lost when resetting the GPU
+    - drm/etnaviv: fix MMU context leak on GPU reset
+    - drm/etnaviv: reference MMU context when setting up hardware state
+    - drm/etnaviv: add missing MMU context put when reaping MMU mapping
+    - s390/sclp: fix Secure-IPL facility detection
+    - x86/mm: Fix kern_addr_valid() to cope with existing but not present entries
+    - tipc: fix an use-after-free issue in tipc_recvmsg
+    - net-caif: avoid user-triggerable WARN_ON(1)
+    - ptp: dp83640: don't define PAGE0
+    - net/l2tp: Fix reference count leak in l2tp_udp_recv_core
+    - r6040: Restore MDIO clock frequency after MAC reset
+    - tipc: increase timeout in tipc_sk_enqueue()
+    - perf machine: Initialize srcline string member in add_location struct
+    - net/mlx5: FWTrace, cancel work on alloc pd error flow
+    - net/mlx5: Fix potential sleeping in atomic context
+    - events: Reuse value read using READ_ONCE instead of re-reading it
+    - vhost_net: fix OoB on sendmsg() failure.
+    - net/af_unix: fix a data-race in unix_dgram_poll
+    - net: dsa: destroy the phylink instance on any error in dsa_slave_phy_setup
+    - tcp: fix tp->undo_retrans accounting in tcp_sacktag_one()
+    - qed: Handle management FW error
+    - dt-bindings: arm: Fix Toradex compatible typo
+    - ibmvnic: check failover_pending in login response
+    - KVM: PPC: Book3S HV: Tolerate treclaim. in fake-suspend mode changing
+      registers
+    - net: hns3: pad the short tunnel frame before sending to hardware
+    - net: hns3: change affinity_mask to numa node range
+    - net: hns3: disable mac in flr process
+    - net: hns3: fix the timing issue of VF clearing interrupt sources
+    - mm/memory_hotplug: use "unsigned long" for PFN in zone_for_pfn_range()
+    - dt-bindings: mtd: gpmc: Fix the ECC bytes vs. OOB bytes equation
+    - mfd: db8500-prcmu: Adjust map to reality
+    - PCI: Add ACS quirks for NXP LX2xx0 and LX2xx2 platforms
+    - fuse: fix use after free in fuse_read_interrupt()
+    - mfd: Don't use irq_create_mapping() to resolve a mapping
+    - tracing/probes: Reject events which have the same name of existing one
+    - PCI: Add ACS quirks for Cavium multi-function devices
+    - Set fc_nlinfo in nh_create_ipv4, nh_create_ipv6
+    - net: usb: cdc_mbim: avoid altsetting toggling for Telit LN920
+    - PCI: ibmphp: Fix double unmap of io_mem
+    - ethtool: Fix an error code in cxgb2.c
+    - NTB: Fix an error code in ntb_msit_probe()
+    - NTB: perf: Fix an error code in perf_setup_inbuf()
+    - mfd: axp20x: Update AXP288 volatile ranges
+    - PCI: Fix pci_dev_str_match_path() alloc while atomic bug
+    - mfd: tqmx86: Clear GPIO IRQ resource when no IRQ is set
+    - KVM: arm64: Handle PSCI resets before userspace touches vCPU state
+    - PCI: Sync __pci_register_driver() stub for CONFIG_PCI=n
+    - mtd: rawnand: cafe: Fix a resource leak in the error handling path of
+      'cafe_nand_probe()'
+    - ARC: export clear_user_page() for modules
+    - perf unwind: Do not overwrite FEATURE_CHECK_LDFLAGS-libunwind-{x86,aarch64}
+    - net: dsa: b53: Fix calculating number of switch ports
+    - netfilter: socket: icmp6: fix use-after-scope
+    - fq_codel: reject silly quantum parameters
+    - qlcnic: Remove redundant unlock in qlcnic_pinit_from_rom
+    - ip_gre: validate csum_start only on pull
+    - net: renesas: sh_eth: Fix freeing wrong tx descriptor
+    - Linux 5.4.148
+
+  * Focal update: v5.4.147 upstream stable release (LP: #1946795)
+    - Linux 5.4.147
+    - upstream stable to v5.4.147
+
+  * CVE-2021-3428
+    - ext4: save the error code which triggered an ext4_error() in the superblock
+    - ext4: simulate various I/O and checksum errors when reading metadata
+    - ext4: save all error info in save_error_info() and drop ext4_set_errno()
+    - ext4: check journal inode extents more carefully
+
+  * ip6gretap / erspan / ip6erspan in rtnetlink.sh from net of
+    ubuntu_kernel_selftests failed on B-5.4-aws / B-5.4-gke / B-5.4-oracle /
+    B-5.4-azure / B-5.4 (LP: #1896448)
+    - SAUCE: selftests: rtnetlink: fixes for older iproute2
+
+  * CVE-2019-19449
+    - f2fs: fix wrong total_sections check and fsmeta check
+    - f2fs: fix to do sanity check on segment/section count
+
+  * kernel bug found when disconnecting one fiber channel interface on Cisco
+    Chassis with fnic DRV_VERSION "1.6.0.47" (LP: #1944586)
+    - scsi: fnic: Do not call 'scsi_done()' for unhandled commands
+
+  * memfd from ubuntu_kernel_selftests failed to build on B-5.4 (unknown type
+    name ‘__u64’) (LP: #1944613)
+    - SAUCE: selftests/memfd: fix __u64 not defined build issue
+
+  * Medion Notebook Keyboard not working (LP: #1909814)
+    - ACPI: resources: Add DMI-based legacy IRQ override quirk
+
+  * vrf: fix refcnt leak with vxlan slaves (LP: #1945180)
+    - ipv4: Fix device used for dst_alloc with local routes
+
+  * Check for changes relevant for security certifications (LP: #1945989)
+    - [Packaging] Add a new fips-checks script
+    - [Packaging] Add fips-checks as part of finalchecks
+
+  * Fix cold plugged USB device on certain PCIe USB cards (LP: #1945211)
+    - Revert "UBUNTU: SAUCE: Revert "usb: core: reduce power-on-good delay time of
+      root hub""
+    - usb: core: hcd: Add support for deferring roothub registration
+    - xhci: Set HCD flag to defer primary roothub registration
+    - usb: core: hcd: Modularize HCD stop configuration in usb_stop_hcd()
+
+  * CVE-2021-3759
+    - memcg: enable accounting of ipc resources
+
+  * Focal update: v5.4.146 upstream stable release (LP: #1946024)
+    - locking/mutex: Fix HANDOFF condition
+    - regmap: fix the offset of register error log
+    - crypto: mxs-dcp - Check for DMA mapping errors
+    - sched/deadline: Fix reset_on_fork reporting of DL tasks
+    - power: supply: axp288_fuel_gauge: Report register-address on readb / writeb
+      errors
+    - crypto: omap-sham - clear dma flags only after omap_sham_update_dma_stop()
+    - sched/deadline: Fix missing clock update in migrate_task_rq_dl()
+    - rcu/tree: Handle VM stoppage in stall detection
+    - hrtimer: Avoid double reprogramming in __hrtimer_start_range_ns()
+    - hrtimer: Ensure timerfd notification for HIGHRES=n
+    - udf: Check LVID earlier
+    - udf: Fix iocharset=utf8 mount option
+    - isofs: joliet: Fix iocharset=utf8 mount option
+    - bcache: add proper error unwinding in bcache_device_init
+    - nvme-tcp: don't update queue count when failing to set io queues
+    - nvme-rdma: don't update queue count when failing to set io queues
+    - nvmet: pass back cntlid on successful completion
+    - power: supply: max17042_battery: fix typo in MAx17042_TOFF
+    - s390/cio: add dev_busid sysfs entry for each subchannel
+    - libata: fix ata_host_start()
+    - crypto: qat - do not ignore errors from enable_vf2pf_comms()
+    - crypto: qat - handle both source of interrupt in VF ISR
+    - crypto: qat - fix reuse of completion variable
+    - crypto: qat - fix naming for init/shutdown VF to PF notifications
+    - crypto: qat - do not export adf_iov_putmsg()
+    - fcntl: fix potential deadlock for &fasync_struct.fa_lock
+    - udf_get_extendedattr() had no boundary checks.
+    - s390/kasan: fix large PMD pages address alignment check
+    - s390/debug: fix debug area life cycle
+    - m68k: emu: Fix invalid free in nfeth_cleanup()
+    - sched: Fix UCLAMP_FLAG_IDLE setting
+    - spi: spi-fsl-dspi: Fix issue with uninitialized dma_slave_config
+    - spi: spi-pic32: Fix issue with uninitialized dma_slave_config
+    - genirq/timings: Fix error return code in irq_timings_test_irqs()
+    - lib/mpi: use kcalloc in mpi_resize
+    - clocksource/drivers/sh_cmt: Fix wrong setting if don't request IRQ for clock
+      source channel
+    - crypto: qat - use proper type for vf_mask
+    - certs: Trigger creation of RSA module signing key if it's not an RSA key
+    - regulator: vctrl: Use locked regulator_get_voltage in probe path
+    - regulator: vctrl: Avoid lockdep warning in enable/disable ops
+    - spi: sprd: Fix the wrong WDG_LOAD_VAL
+    - spi: spi-zynq-qspi: use wait_for_completion_timeout to make
+      zynq_qspi_exec_mem_op not interruptible
+    - EDAC/i10nm: Fix NVDIMM detection
+    - drm/panfrost: Fix missing clk_disable_unprepare() on error in
+      panfrost_clk_init()
+    - media: TDA1997x: enable EDID support
+    - soc: rockchip: ROCKCHIP_GRF should not default to y, unconditionally
+    - media: cxd2880-spi: Fix an error handling path
+    - bpf: Fix a typo of reuseport map in bpf.h.
+    - bpf: Fix potential memleak and UAF in the verifier.
+    - ARM: dts: aspeed-g6: Fix HVI3C function-group in pinctrl dtsi
+    - arm64: dts: renesas: r8a77995: draak: Remove bogus adv7511w properties
+    - soc: qcom: rpmhpd: Use corner in power_off
+    - media: dvb-usb: fix uninit-value in dvb_usb_adapter_dvb_init
+    - media: dvb-usb: fix uninit-value in vp702x_read_mac_addr
+    - media: dvb-usb: Fix error handling in dvb_usb_i2c_init
+    - media: go7007: remove redundant initialization
+    - media: coda: fix frame_mem_ctrl for YUV420 and YVU420 formats
+    - Bluetooth: sco: prevent information leak in sco_conn_defer_accept()
+    - 6lowpan: iphc: Fix an off-by-one check of array index
+    - netns: protect netns ID lookups with RCU
+    - tcp: seq_file: Avoid skipping sk during tcp_seek_last_pos
+    - ARM: dts: meson8: Use a higher default GPU clock frequency
+    - ARM: dts: meson8b: odroidc1: Fix the pwm regulator supply properties
+    - ARM: dts: meson8b: mxq: Fix the pwm regulator supply properties
+    - ARM: dts: meson8b: ec100: Fix the pwm regulator supply properties
+    - net/mlx5e: Prohibit inner indir TIRs in IPoIB
+    - cgroup/cpuset: Fix a partition bug with hotplug
+    - net: cipso: fix warnings in netlbl_cipsov4_add_std
+    - i2c: highlander: add IRQ check
+    - leds: lt3593: Put fwnode in any case during ->probe()
+    - leds: trigger: audio: Add an activate callback to ensure the initial
+      brightness is set
+    - media: em28xx-input: fix refcount bug in em28xx_usb_disconnect
+    - media: venus: venc: Fix potential null pointer dereference on pointer fmt
+    - PCI: PM: Avoid forcing PCI_D0 for wakeup reasons inconsistently
+    - PCI: PM: Enable PME if it can be signaled from D3cold
+    - soc: qcom: smsm: Fix missed interrupts if state changes while masked
+    - debugfs: Return error during {full/open}_proxy_open() on rmmod
+    - Bluetooth: increase BTNAMSIZ to 21 chars to fix potential buffer overflow
+    - PM: EM: Increase energy calculation precision
+    - drm/msm/dpu: make dpu_hw_ctl_clear_all_blendstages clear necessary LMs
+    - arm64: dts: exynos: correct GIC CPU interfaces address range on Exynos7
+    - counter: 104-quad-8: Return error when invalid mode during ceiling_write
+    - Bluetooth: fix repeated calls to sco_sock_kill
+    - drm/msm/dsi: Fix some reference counted resource leaks
+    - usb: gadget: udc: at91: add IRQ check
+    - usb: phy: fsl-usb: add IRQ check
+    - usb: phy: twl6030: add IRQ checks
+    - usb: gadget: udc: renesas_usb3: Fix soc_device_match() abuse
+    - usb: host: ohci-tmio: add IRQ check
+    - usb: phy: tahvo: add IRQ check
+    - mac80211: Fix insufficient headroom issue for AMSDU
+    - lockd: Fix invalid lockowner cast after vfs_test_lock
+    - nfsd4: Fix forced-expiry locking
+    - usb: gadget: mv_u3d: request_irq() after initializing UDC
+    - mm/swap: consider max pages in iomap_swapfile_add_extent
+    - Bluetooth: add timeout sanity check to hci_inquiry
+    - i2c: iop3xx: fix deferred probing
+    - i2c: s3c2410: fix IRQ check
+    - rsi: fix error code in rsi_load_9116_firmware()
+    - rsi: fix an error code in rsi_probe()
+    - ASoC: Intel: Skylake: Leave data as is when invoking TLV IPCs
+    - ASoC: Intel: Skylake: Fix module resource and format selection
+    - mmc: dw_mmc: Fix issue with uninitialized dma_slave_config
+    - mmc: moxart: Fix issue with uninitialized dma_slave_config
+    - bpf: Fix possible out of bound write in narrow load handling
+    - CIFS: Fix a potencially linear read overflow
+    - i2c: mt65xx: fix IRQ check
+    - usb: ehci-orion: Handle errors of clk_prepare_enable() in probe
+    - usb: bdc: Fix an error handling path in 'bdc_probe()' when no suitable DMA
+      config is available
+    - tty: serial: fsl_lpuart: fix the wrong mapbase value
+    - ASoC: wcd9335: Fix a double irq free in the remove function
+    - ASoC: wcd9335: Fix a memory leak in the error handling path of the probe
+      function
+    - ASoC: wcd9335: Disable irq on slave ports in the remove function
+    - ath6kl: wmi: fix an error code in ath6kl_wmi_sync_point()
+    - bcma: Fix memory leak for internally-handled cores
+    - brcmfmac: pcie: fix oops on failure to resume and reprobe
+    - ipv6: make exception cache less predictible
+    - ipv4: make exception cache less predictible
+    - net: sched: Fix qdisc_rate_table refcount leak when get tcf_block failed
+    - net: qualcomm: fix QCA7000 checksum handling
+    - octeontx2-af: Fix loop in free and unmap counter
+    - ipv4: fix endianness issue in inet_rtm_getroute_build_skb()
+    - bpf: Introduce BPF nospec instruction for mitigating Spectre v4
+    - bpf: Fix leakage due to insufficient speculative store bypass mitigation
+    - bpf: verifier: Allocate idmap scratch in verifier env
+    - bpf: Fix pointer arithmetic mask tightening under state pruning
+    - tty: Fix data race between tiocsti() and flush_to_ldisc()
+    - perf/x86/amd/ibs: Extend PERF_PMU_CAP_NO_EXCLUDE to IBS Op
+    - x86/resctrl: Fix a maybe-uninitialized build warning treated as error
+    - KVM: s390: index kvm->arch.idle_mask by vcpu_idx
+    - KVM: x86: Update vCPU's hv_clock before back to guest when tsc_offset is
+      adjusted
+    - KVM: nVMX: Unconditionally clear nested.pi_pending on nested VM-Enter
+    - fuse: truncate pagecache on atomic_o_trunc
+    - fuse: flush extending writes
+    - IMA: remove -Wmissing-prototypes warning
+    - IMA: remove the dependency on CRYPTO_MD5
+    - fbmem: don't allow too huge resolutions
+    - backlight: pwm_bl: Improve bootloader/kernel device handover
+    - clk: kirkwood: Fix a clocking boot regression
+    - Linux 5.4.146
+
+  * AMD A8-7680 (amdgpu): broken Xorg acceleration and hibernation
+    (LP: #1920674) // Focal update: v5.4.146 upstream stable release
+    (LP: #1946024)
+    - drm/amdgpu/acp: Make PM domain really work
+
+  * Focal update: v5.4.145 upstream stable release (LP: #1945517)
+    - fscrypt: add fscrypt_symlink_getattr() for computing st_size
+    - ext4: report correct st_size for encrypted symlinks
+    - f2fs: report correct st_size for encrypted symlinks
+    - ubifs: report correct st_size for encrypted symlinks
+    - kthread: Fix PF_KTHREAD vs to_kthread() race
+    - xtensa: fix kconfig unmet dependency warning for HAVE_FUTEX_CMPXCHG
+    - gpu: ipu-v3: Fix i.MX IPU-v3 offset calculations for (semi)planar U/V
+      formats
+    - reset: reset-zynqmp: Fixed the argument data type
+    - qed: Fix the VF msix vectors flow
+    - net: macb: Add a NULL check on desc_ptp
+    - qede: Fix memset corruption
+    - perf/x86/intel/pt: Fix mask of num_address_ranges
+    - perf/x86/amd/ibs: Work around erratum #1197
+    - perf/x86/amd/power: Assign pmu.module
+    - cryptoloop: add a deprecation warning
+    - ARM: 8918/2: only build return_address() if needed
+    - ALSA: hda/realtek: Workaround for conflicting SSID on ASUS ROG Strix G17
+    - ALSA: pcm: fix divide error in snd_pcm_lib_ioctl
+    - ARC: wireup clone3 syscall
+    - media: stkwebcam: fix memory leak in stk_camera_probe
+    - igmp: Add ip_mc_list lock in ip_check_mc_rcu
+    - USB: serial: mos7720: improve OOM-handling in read_mos_reg()
+    - ipv4/icmp: l3mdev: Perform icmp error route lookup on source device routing
+      table (v2)
+    - powerpc/boot: Delete unneeded .globl _zimage_start
+    - net: ll_temac: Remove left-over debug message
+    - mm/page_alloc: speed up the iteration of max_order
+    - Revert "r8169: avoid link-up interrupt issue on RTL8106e if user enables
+      ASPM"
+    - x86/events/amd/iommu: Fix invalid Perf result due to IOMMU PMC power-gating
+    - Revert "btrfs: compression: don't try to compress if we don't have enough
+      pages"
+    - ALSA: usb-audio: Add registration quirk for JBL Quantum 800
+    - usb: host: xhci-rcar: Don't reload firmware after the completion
+    - usb: mtu3: use @mult for HS isoc or intr
+    - usb: mtu3: fix the wrong HS mult value
+    - xhci: fix unsafe memory usage in xhci tracing
+    - x86/reboot: Limit Dell Optiplex 990 quirk to early BIOS versions
+    - PCI: Call Max Payload Size-related fixup quirks early
+    - Linux 5.4.145
+
+  * Focal update: v5.4.144 upstream stable release (LP: #1944756)
+    - net: qrtr: fix another OOB Read in qrtr_endpoint_post
+    - ARC: Fix CONFIG_STACKDEPOT
+    - netfilter: conntrack: collect all entries in one cycle
+    - once: Fix panic when module unload
+    - ovl: fix uninitialized pointer read in ovl_lookup_real_one()
+    - mmc: sdhci-msm: Update the software timeout value for sdhc
+    - mm, oom: make the calculation of oom badness more accurate
+    - can: usb: esd_usb2: esd_usb2_rx_event(): fix the interchange of the CAN RX
+      and TX error counters
+    - Revert "USB: serial: ch341: fix character loss at high transfer rates"
+    - USB: serial: option: add new VID/PID to support Fibocom FG150
+    - usb: dwc3: gadget: Fix dwc3_calc_trbs_left()
+    - usb: dwc3: gadget: Stop EP0 transfers during pullup disable
+    - scsi: core: Fix hang of freezing queue between blocking and running device
+    - RDMA/bnxt_re: Add missing spin lock initialization
+    - IB/hfi1: Fix possible null-pointer dereference in _extend_sdma_tx_descs()
+    - e1000e: Fix the max snoop/no-snoop latency for 10M
+    - RDMA/efa: Free IRQ vectors on error flow
+    - ip_gre: add validation for csum_start
+    - xgene-v2: Fix a resource leak in the error handling path of 'xge_probe()'
+    - net: marvell: fix MVNETA_TX_IN_PRGRS bit number
+    - rtnetlink: Return correct error on changing device netns
+    - net: hns3: clear hardware resource when loading driver
+    - net: hns3: fix duplicate node in VLAN list
+    - net: hns3: fix get wrong pfc_en when query PFC configuration
+    - drm/i915: Fix syncmap memory leak
+    - usb: gadget: u_audio: fix race condition on endpoint stop
+    - perf/x86/intel/uncore: Fix integer overflow on 23 bit left shift of a u32
+    - opp: remove WARN when no valid OPPs remain
+    - virtio: Improve vq->broken access to avoid any compiler optimization
+    - virtio_pci: Support surprise removal of virtio pci device
+    - vringh: Use wiov->used to check for read/write desc order
+    - qed: qed ll2 race condition fixes
+    - qed: Fix null-pointer dereference in qed_rdma_create_qp()
+    - drm: Copy drm_wait_vblank to user before returning
+    - drm/nouveau/disp: power down unused DP links during init
+    - net/rds: dma_map_sg is entitled to merge entries
+    - btrfs: fix race between marking inode needs to be logged and log syncing
+    - vt_kdsetmode: extend console locking
+    - bpf: Track contents of read-only maps as scalars
+    - bpf: Fix cast to pointer from integer of different size warning
+    - net: dsa: mt7530: fix VLAN traffic leaks again
+    - KVM: x86/mmu: Treat NX as used (not reserved) for all !TDP shadow MMUs
+    - arm64: dts: qcom: msm8994-angler: Fix gpio-reserved-ranges 85-88
+    - btrfs: fix NULL pointer dereference when deleting device by invalid id
+    - Revert "floppy: reintroduce O_NDELAY fix"
+    - Revert "parisc: Add assembly implementations for memset, strlen, strcpy,
+      strncpy and strcat"
+    - net: don't unconditionally copy_from_user a struct ifreq for socket ioctls
+    - audit: move put_tree() to avoid trim_trees refcount underflow and UAF
+    - Linux 5.4.144
+
+ -- Kelsey Skunberg <kelsey.skunberg@canonical.com>  Fri, 15 Oct 2021 11:56:24 -0600
+
+linux (5.4.0-89.100) focal; urgency=medium
+
+  * focal/linux: 5.4.0-89.100 -proposed tracker (LP: #1944901)
+
+  * Packaging resync (LP: #1786013)
+    - debian/dkms-versions -- update from kernel-versions (main/2021.09.27)
+
+  * ext4 journal recovery fails w/ data=journal + mmap (LP: #1847340)
+    - jbd2: introduce/export functions
+      jbd2_journal_submit|finish_inode_data_buffers()
+    - jbd2, ext4, ocfs2: introduce/use journal callbacks
+      j_submit|finish_inode_data_buffers()
+    - ext4: data=journal: fixes for ext4_page_mkwrite()
+    - ext4: data=journal: write-protect pages on j_submit_inode_data_buffers()
+    - ext4: fix mmap write protection for data=journal mode
+
+  * CVE-2021-40490
+    - ext4: fix race writing to an inline_data file while its xattrs are changing
+
+  * Obsolete patch "UBUNTU: SAUCE: ext4: fix directory index node split
+    corruption" (LP: #1942902)
+    - Revert "UBUNTU: SAUCE: ext4: fix directory index node split corruption"
+
+  * psock_snd.sh in net from ubuntu_kernel_selftests ADT failure with
+    focal/groovy/hirsute/impish (LP: #1892213)
+    - selftests/net: remove min gso test in packet_snd
+
+  * Focal update: v5.4.143 upstream stable release (LP: #1944212)
+    - ext4: fix EXT4_MAX_LOGICAL_BLOCK macro
+    - x86/fpu: Make init_fpstate correct with optimized XSAVE
+    - ath: Use safer key clearing with key cache entries
+    - ath9k: Clear key cache explicitly on disabling hardware
+    - ath: Export ath_hw_keysetmac()
+    - ath: Modify ath_key_delete() to not need full key entry
+    - ath9k: Postpone key cache entry deletion for TXQ frames reference it
+    - mtd: cfi_cmdset_0002: fix crash when erasing/writing AMD cards
+    - media: zr364xx: propagate errors from zr364xx_start_readpipe()
+    - media: zr364xx: fix memory leaks in probe()
+    - media: drivers/media/usb: fix memory leak in zr364xx_probe
+    - USB: core: Avoid WARNings for 0-length descriptor requests
+    - dmaengine: xilinx_dma: Fix read-after-free bug when terminating transfers
+    - dmaengine: usb-dmac: Fix PM reference leak in usb_dmac_probe()
+    - ARM: dts: am43x-epos-evm: Reduce i2c0 bus speed for tps65218
+    - dmaengine: of-dma: router_xlate to return -EPROBE_DEFER if controller is not
+      yet available
+    - scsi: megaraid_mm: Fix end of loop tests for list_for_each_entry()
+    - scsi: scsi_dh_rdac: Avoid crash during rdac_bus_attach()
+    - scsi: core: Avoid printing an error if target_alloc() returns -ENXIO
+    - scsi: core: Fix capacity set to zero after offlinining device
+    - ARM: dts: nomadik: Fix up interrupt controller node names
+    - net: usb: lan78xx: don't modify phy_device state concurrently
+    - drm/amd/display: Fix Dynamic bpp issue with 8K30 with Navi 1X
+    - Bluetooth: hidp: use correct wait queue when removing ctrl_wait
+    - iommu: Check if group is NULL before remove device
+    - cpufreq: armada-37xx: forbid cpufreq for 1.2 GHz variant
+    - dccp: add do-while-0 stubs for dccp_pr_debug macros
+    - virtio: Protect vqs list access
+    - vhost: Fix the calculation in vhost_overflow()
+    - bpf: Clear zext_dst of dead insns
+    - bnxt: don't lock the tx queue from napi poll
+    - bnxt: disable napi before canceling DIM
+    - net: 6pack: fix slab-out-of-bounds in decode_data
+    - ptp_pch: Restore dependency on PCI
+    - bnxt_en: Add missing DMA memory barriers
+    - vrf: Reset skb conntrack connection on VRF rcv
+    - virtio-net: support XDP when not more queues
+    - virtio-net: use NETIF_F_GRO_HW instead of NETIF_F_LRO
+    - net: qlcnic: add missed unlock in qlcnic_83xx_flash_read32
+    - net: mdio-mux: Don't ignore memory allocation errors
+    - net: mdio-mux: Handle -EPROBE_DEFER correctly
+    - ovs: clear skb->tstamp in forwarding path
+    - i40e: Fix ATR queue selection
+    - iavf: Fix ping is lost after untrusted VF had tried to change MAC
+    - ovl: add splice file read write helper
+    - mmc: dw_mmc: Fix hang on data CRC error
+    - ALSA: hda - fix the 'Capture Switch' value change notifications
+    - tracing / histogram: Fix NULL pointer dereference on strcmp() on NULL event
+      name
+    - slimbus: messaging: start transaction ids from 1 instead of zero
+    - slimbus: messaging: check for valid transaction id
+    - slimbus: ngd: reset dma setup during runtime pm
+    - ipack: tpci200: fix many double free issues in tpci200_pci_probe
+    - ipack: tpci200: fix memory leak in the tpci200_register
+    - btrfs: prevent rename2 from exchanging a subvol with a directory from
+      different parents
+    - PCI: Increase D3 delay for AMD Renoir/Cezanne XHCI
+    - ASoC: intel: atom: Fix breakage for PCM buffer address setup
+    - mm, memcg: avoid stale protection values when cgroup is above protection
+    - mm: memcontrol: fix occasional OOMs due to proportional memory.low reclaim
+    - fs: warn about impending deprecation of mandatory locks
+    - netfilter: nft_exthdr: fix endianness of tcp option cast
+    - Linux 5.4.143
+
+  * Focal update: v5.4.142 upstream stable release (LP: #1944202)
+    - iio: adc: ti-ads7950: Ensure CS is deasserted after reading channels
+    - iio: humidity: hdc100x: Add margin to the conversion time
+    - iio: adc: Fix incorrect exit of for-loop
+    - ASoC: xilinx: Fix reference to PCM buffer address
+    - ASoC: intel: atom: Fix reference to PCM buffer address
+    - i2c: dev: zero out array used for i2c reads from userspace
+    - ceph: reduce contention in ceph_check_delayed_caps()
+    - ACPI: NFIT: Fix support for virtual SPA ranges
+    - libnvdimm/region: Fix label activation vs errors
+    - ieee802154: hwsim: fix GPF in hwsim_set_edge_lqi
+    - ieee802154: hwsim: fix GPF in hwsim_new_edge_nl
+    - ASoC: cs42l42: Correct definition of ADC Volume control
+    - ASoC: cs42l42: Don't allow SND_SOC_DAIFMT_LEFT_J
+    - ASoC: cs42l42: Fix inversion of ADC Notch Switch control
+    - ASoC: cs42l42: Remove duplicate control for WNF filter frequency
+    - netfilter: nf_conntrack_bridge: Fix memory leak when error
+    - ASoC: cs42l42: Fix LRCLK frame start edge
+    - net: dsa: mt7530: add the missing RxUnicast MIB counter
+    - platform/x86: pcengines-apuv2: revert wiring up simswitch GPIO as LED
+    - platform/x86: pcengines-apuv2: Add missing terminating entries to gpio-
+      lookup tables
+    - net: phy: micrel: Fix link detection on ksz87xx switch"
+    - ppp: Fix generating ifname when empty IFLA_IFNAME is specified
+    - net: sched: act_mirred: Reset ct info when mirror/redirect skb
+    - iavf: Set RSS LUT and key in reset handle path
+    - psample: Add a fwd declaration for skbuff
+    - net/mlx5: Fix return value from tracer initialization
+    - drm/meson: fix colour distortion from HDR set during vendor u-boot
+    - net: dsa: microchip: Fix ksz_read64()
+    - net: Fix memory leak in ieee802154_raw_deliver
+    - net: igmp: fix data-race in igmp_ifc_timer_expire()
+    - net: dsa: lan9303: fix broken backpressure in .port_fdb_dump
+    - net: dsa: lantiq: fix broken backpressure in .port_fdb_dump
+    - net: dsa: sja1105: fix broken backpressure in .port_fdb_dump
+    - net: bridge: fix memleak in br_add_if()
+    - net: linkwatch: fix failure to restore device state across suspend/resume
+    - tcp_bbr: fix u32 wrap bug in round logic if bbr_init() called after 2B
+      packets
+    - net: igmp: increase size of mr_ifc_count
+    - xen/events: Fix race in set_evtchn_to_irq
+    - vsock/virtio: avoid potential deadlock when vsock device remove
+    - nbd: Aovid double completion of a request
+    - powerpc/kprobes: Fix kprobe Oops happens in booke
+    - x86/tools: Fix objdump version check again
+    - genirq: Provide IRQCHIP_AFFINITY_PRE_STARTUP
+    - x86/msi: Force affinity setup before startup
+    - x86/ioapic: Force affinity setup before startup
+    - x86/resctrl: Fix default monitoring groups reporting
+    - genirq/msi: Ensure deactivation on teardown
+    - genirq/timings: Prevent potential array overflow in __irq_timings_store()
+    - PCI/MSI: Enable and mask MSI-X early
+    - PCI/MSI: Mask all unused MSI-X entries
+    - PCI/MSI: Enforce that MSI-X table entry is masked for update
+    - PCI/MSI: Enforce MSI[X] entry updates to be visible
+    - PCI/MSI: Do not set invalid bits in MSI mask
+    - PCI/MSI: Correct misleading comments
+    - PCI/MSI: Use msi_mask_irq() in pci_msi_shutdown()
+    - PCI/MSI: Protect msi_desc::masked for multi-MSI
+    - KVM: VMX: Use current VMCS to query WAITPKG support for MSR emulation
+    - ceph: add some lockdep assertions around snaprealm handling
+    - ceph: clean up locking annotation for ceph_get_snap_realm and
+      __lookup_snap_realm
+    - ceph: take snap_empty_lock atomically with snaprealm refcount change
+    - vmlinux.lds.h: Handle clang's module.{c,d}tor sections
+    - iommu/vt-d: Fix agaw for a supported 48 bit guest address width
+    - Linux 5.4.142
+
+  * Focal update: v5.4.141 upstream stable release (LP: #1943484)
+    - KVM: SVM: Fix off-by-one indexing when nullifying last used SEV VMCB
+    - tee: Correct inappropriate usage of TEE_SHM_DMA_BUF flag
+    - media: v4l2-mem2mem: always consider OUTPUT queue during poll
+    - tracing: Reject string operand in the histogram expression
+    - usb: dwc3: Stop active transfers before halting the controller
+    - usb: dwc3: gadget: Allow runtime suspend if UDC unbinded
+    - usb: dwc3: gadget: Restart DWC3 gadget when enabling pullup
+    - usb: dwc3: gadget: Prevent EP queuing while stopping transfers
+    - usb: dwc3: gadget: Clear DEP flags after stop transfers in ep disable
+    - usb: dwc3: gadget: Disable gadget IRQ during pullup disable
+    - usb: dwc3: gadget: Avoid runtime resume if disabling pullup
+    - KVM: X86: MMU: Use the correct inherited permissions to get shadow page
+    - USB:ehci:fix Kunpeng920 ehci hardware problem
+    - ALSA: hda: Add quirk for ASUS Flow x13
+    - ppp: Fix generating ppp unit id when ifname is not specified
+    - ovl: prevent private clone if bind mount is not allowed
+    - btrfs: make qgroup_free_reserved_data take btrfs_inode
+    - btrfs: make btrfs_qgroup_reserve_data take btrfs_inode
+    - btrfs: qgroup: allow to unreserve range without releasing other ranges
+    - btrfs: qgroup: try to flush qgroup space when we get -EDQUOT
+    - btrfs: transaction: Cleanup unused TRANS_STATE_BLOCKED
+    - btrfs: qgroup: remove ASYNC_COMMIT mechanism in favor of reserve retry-
+      after-EDQUOT
+    - btrfs: fix lockdep splat when enabling and disabling qgroups
+    - net: xilinx_emaclite: Do not print real IOMEM pointer
+    - btrfs: qgroup: don't commit transaction when we already hold the handle
+    - btrfs: export and rename qgroup_reserve_meta
+    - btrfs: don't flush from btrfs_delayed_inode_reserve_metadata
+    - Linux 5.4.141
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Fri, 24 Sep 2021 15:50:10 +0200
+
+linux (5.4.0-88.99) focal; urgency=medium
+
+  * focal/linux: 5.4.0-88.99 -proposed tracker (LP: #1944747)
+
+  * Packaging resync (LP: #1786013)
+    - debian/dkms-versions -- update from kernel-versions (main/2021.09.06)
+
+  * please drop virtualbox-guest-dkms virtualbox-guest-source (LP: #1933248)
+    - Revert "UBUNTU: [Config] Disable virtualbox dkms build"
+
+ -- Kelsey Skunberg <kelsey.skunberg@canonical.com>  Thu, 23 Sep 2021 10:40:49 -0600
+
+linux (5.4.0-87.98) focal; urgency=medium
+
+  * please drop virtualbox-guest-dkms virtualbox-guest-source (LP: #1933248)
+    - [Config] Disable virtualbox dkms build
+
+  * Packaging resync (LP: #1786013)
+    - debian/dkms-versions -- update from kernel-versions (main/2021.09.06)
+
+  *  LRMv5: switch primary version handling to kernel-versions data set
+    (LP: #1928921)
+    - [Packaging] switch to kernel-versions
+
+  * disable “CONFIG_HISI_DMA” config for ubuntu version (LP: #1936771)
+    - Disable CONFIG_HISI_DMA
+    - [Config] Record hisi_dma no longer built for arm64
+
+  * memory leaking when removing a profile (LP: #1939915)
+    - apparmor: Fix memory leak of profile proxy
+
+  * CryptoExpress EP11 cards are going offline (LP: #1939618)
+    - s390/zcrypt: Support for CCA protected key block version 2
+    - s390: Replace zero-length array with flexible-array member
+    - s390/zcrypt: Use scnprintf() for avoiding potential buffer overflow
+    - s390/zcrypt: replace snprintf/sprintf with scnprintf
+    - s390/ap: Remove ap device suspend and resume callbacks
+    - s390/zcrypt: use fallthrough;
+    - s390/zcrypt: use kvmalloc instead of kmalloc for 256k alloc
+    - s390/ap: remove power management code from ap bus and drivers
+    - s390/ap: introduce new ap function ap_get_qdev()
+    - s390/zcrypt: use kzalloc
+    - s390/zcrypt: fix smatch warnings
+    - s390/zcrypt: code beautification and struct field renames
+    - s390/zcrypt: split ioctl function into smaller code units
+    - s390/ap: rename and clarify ap state machine related stuff
+    - s390/zcrypt: provide cex4 cca sysfs attributes for cex3
+    - s390/ap: rework crypto config info and default domain code
+    - s390/zcrypt: simplify cca_findcard2 loop code
+    - s390/zcrypt: remove set_fs() invocation in zcrypt device driver
+    - s390/ap: remove unnecessary spin_lock_init()
+    - s390/zcrypt: Support for CCA APKA master keys
+    - s390/zcrypt: introduce msg tracking in zcrypt functions
+    - s390/ap: split ap queue state machine state from device state
+    - s390/ap: add error response code field for ap queue devices
+    - s390/ap: add card/queue deconfig state
+    - s390/sclp: Add support for SCLP AP adapter config/deconfig
+    - s390/ap: Support AP card SCLP config and deconfig operations
+    - s390/ap/zcrypt: revisit ap and zcrypt error handling
+    - s390/zcrypt: move ap_msg param one level up the call chain
+    - s390/zcrypt: Introduce Failure Injection feature
+    - s390/zcrypt: fix wrong format specifications
+    - s390/ap: fix ap devices reference counting
+    - s390/zcrypt: return EIO when msg retry limit reached
+    - s390/zcrypt: fix zcard and zqueue hot-unplug memleak
+    - s390/ap: Fix hanging ioctl caused by wrong msg counter
+
+  * memfd from ubuntu_kernel_selftests failed to build on B-5.4 (LP: #1926142)
+    - SAUCE: selftests/memfd: fix build when F_SEAL_FUTURE_WRITE is not defined
+
+  * [SRU] Ice driver causes the kernel to crash with Ubuntu 20.04.2 with ethtool
+    specific register commands (LP: #1939855)
+    - ice: Fix bad register reads
+
+  * ubunut_kernel_selftests: memory-hotplug: avoid spamming logs with
+    dump_page() (LP: #1941829)
+    - selftests: memory-hotplug: avoid spamming logs with dump_page(), ratio limit
+      hot-remove error test
+
+  * e1000e blocks the boot process when it tried to write checksum to its NVM
+    (LP: #1936998)
+    - e1000e: Do not take care about recovery NVM checksum
+
+  * Focal update: v5.4.140 upstream stable release (LP: #1941798)
+    - Revert "ACPICA: Fix memory leak caused by _CID repair function"
+    - ALSA: seq: Fix racy deletion of subscriber
+    - arm64: dts: ls1028a: fix node name for the sysclk
+    - ARM: imx: add missing iounmap()
+    - ARM: imx: add missing clk_disable_unprepare()
+    - ARM: dts: imx6qdl-sr-som: Increase the PHY reset duration to 10ms
+    - ARM: dts: colibri-imx6ull: limit SDIO clock to 25MHz
+    - ARM: imx: fix missing 3rd argument in macro imx_mmdc_perf_init
+    - ARM: dts: imx: Swap M53Menlo pinctrl_power_button/pinctrl_power_out pins
+    - arm64: dts: armada-3720-turris-mox: remove mrvl,i2c-fast-mode
+    - ALSA: usb-audio: fix incorrect clock source setting
+    - clk: stm32f4: fix post divisor setup for I2S/SAI PLLs
+    - ARM: dts: am437x-l4: fix typo in can@0 node
+    - omap5-board-common: remove not physically existing vdds_1v8_main fixed-
+      regulator
+    - spi: imx: mx51-ecspi: Reinstate low-speed CONFIGREG delay
+    - spi: imx: mx51-ecspi: Fix low-speed CONFIGREG delay calculation
+    - scsi: sr: Return correct event when media event code is 3
+    - media: videobuf2-core: dequeue if start_streaming fails
+    - dmaengine: imx-dma: configure the generic DMA type to make it work
+    - net, gro: Set inner transport header offset in tcp/udp GRO hook
+    - net: dsa: sja1105: overwrite dynamic FDB entries with static ones in
+      .port_fdb_add
+    - net: dsa: sja1105: invalidate dynamic FDB entries learned concurrently with
+      statically added ones
+    - net: phy: micrel: Fix detection of ksz87xx switch
+    - net: natsemi: Fix missing pci_disable_device() in probe and remove
+    - gpio: tqmx86: really make IRQ optional
+    - sctp: move the active_key update after sh_keys is added
+    - nfp: update ethtool reporting of pauseframe control
+    - net: ipv6: fix returned variable type in ip6_skb_dst_mtu
+    - mips: Fix non-POSIX regexp
+    - bnx2x: fix an error code in bnx2x_nic_load()
+    - net: pegasus: fix uninit-value in get_interrupt_interval
+    - net: fec: fix use-after-free in fec_drv_remove
+    - net: vxge: fix use-after-free in vxge_device_unregister
+    - blk-iolatency: error out if blk_get_queue() failed in iolatency_set_limit()
+    - Bluetooth: defer cleanup of resources in hci_unregister_dev()
+    - USB: usbtmc: Fix RCU stall warning
+    - USB: serial: option: add Telit FD980 composition 0x1056
+    - USB: serial: ch341: fix character loss at high transfer rates
+    - USB: serial: ftdi_sio: add device ID for Auto-M3 OP-COM v2
+    - firmware_loader: use -ETIMEDOUT instead of -EAGAIN in fw_load_sysfs_fallback
+    - firmware_loader: fix use-after-free in firmware_fallback_sysfs
+    - ALSA: hda/realtek: add mic quirk for Acer SF314-42
+    - ALSA: usb-audio: Add registration quirk for JBL Quantum 600
+    - usb: cdns3: Fixed incorrect gadget state
+    - usb: gadget: f_hid: added GET_IDLE and SET_IDLE handlers
+    - usb: gadget: f_hid: fixed NULL pointer dereference
+    - usb: gadget: f_hid: idle uses the highest byte for duration
+    - usb: otg-fsm: Fix hrtimer list corruption
+    - clk: fix leak on devm_clk_bulk_get_all() unwind
+    - scripts/tracing: fix the bug that can't parse raw_trace_func
+    - tracing / histogram: Give calculation hist_fields a size
+    - optee: Clear stale cache entries during initialization
+    - tee: add tee_shm_alloc_kernel_buf()
+    - optee: Fix memory leak when failing to register shm pages
+    - tpm_ftpm_tee: Free and unregister TEE shared memory during kexec
+    - staging: rtl8723bs: Fix a resource leak in sd_int_dpc
+    - staging: rtl8712: get rid of flush_scheduled_work
+    - media: rtl28xxu: fix zero-length control request
+    - pipe: increase minimum default pipe size to 2 pages
+    - ext4: fix potential htree corruption when growing large_dir directories
+    - serial: tegra: Only print FIFO error message when an error occurs
+    - serial: 8250_mtk: fix uart corruption issue when rx power off
+    - serial: 8250: Mask out floating 16/32-bit bus bits
+    - MIPS: Malta: Do not byte-swap accesses to the CBUS UART
+    - serial: 8250_pci: Enumerate Elkhart Lake UARTs via dedicated driver
+    - serial: 8250_pci: Avoid irq sharing for MSI(-X) interrupts.
+    - timers: Move clearing of base::timer_running under base:: Lock
+    - pcmcia: i82092: fix a null pointer dereference bug
+    - md/raid10: properly indicate failure when ending a failed write request
+    - KVM: x86: accept userspace interrupt only if no event is injected
+    - KVM: Do not leak memory for duplicate debugfs directories
+    - KVM: x86/mmu: Fix per-cpu counter corruption on 32-bit builds
+    - arm64: vdso: Avoid ISB after reading from cntvct_el0
+    - soc: ixp4xx: fix printing resources
+    - spi: meson-spicc: fix memory leak in meson_spicc_remove
+    - soc: ixp4xx/qmgr: fix invalid __iomem access
+    - perf/x86/amd: Don't touch the AMD64_EVENTSEL_HOSTONLY bit inside the guest
+    - bpf, selftests: Adjust few selftest result_unpriv outcomes
+    - libata: fix ata_pio_sector for CONFIG_HIGHMEM
+    - reiserfs: add check for root_inode in reiserfs_fill_super
+    - reiserfs: check directory items on read from disk
+    - virt_wifi: fix error on connect
+    - alpha: Send stop IPI to send to online CPUs
+    - net/qla3xxx: fix schedule while atomic in ql_wait_for_drvr_lock and
+      ql_adapter_reset
+    - arm64: fix compat syscall return truncation
+    - Linux 5.4.140
+
+  * Focal update: v5.4.139 upstream stable release (LP: #1941796)
+    - btrfs: delete duplicated words + other fixes in comments
+    - btrfs: do not commit logs and transactions during link and rename operations
+    - btrfs: fix race causing unnecessary inode logging during link and rename
+    - btrfs: fix lost inode on log replay after mix of fsync, rename and inode
+      eviction
+    - regulator: rt5033: Fix n_voltages settings for BUCK and LDO
+    - spi: stm32h7: fix full duplex irq handler handling
+    - ASoC: tlv320aic31xx: fix reversed bclk/wclk master bits
+    - r8152: Fix potential PM refcount imbalance
+    - qed: fix possible unpaired spin_{un}lock_bh in _qed_mcp_cmd_and_union()
+    - net: Fix zero-copy head len calculation.
+    - nvme: fix nvme_setup_command metadata trace event
+    - ACPI: fix NULL pointer dereference
+    - Revert "Bluetooth: Shutdown controller after workqueues are flushed or
+      cancelled"
+    - firmware: arm_scmi: Ensure drivers provide a probe function
+    - firmware: arm_scmi: Add delayed response status check
+    - bpf: Inherit expanded/patched seen count from old aux data
+    - bpf: Do not mark insn as seen under speculative path verification
+    - bpf: Fix leakage under speculation on mispredicted branches
+    - bpf: Test_verifier, add alu32 bounds tracking tests
+    - bpf, selftests: Add a verifier test for assigning 32bit reg states to 64bit
+      ones
+    - bpf, selftests: Adjust few selftest outcomes wrt unreachable code
+    - spi: mediatek: Fix fifo transfer
+    - Linux 5.4.139
+
+  * Focal update: v5.4.138 upstream stable release (LP: #1940559)
+    - net_sched: check error pointer in tcf_dump_walker()
+    - x86/asm: Ensure asm/proto.h can be included stand-alone
+    - btrfs: fix rw device counting in __btrfs_free_extra_devids
+    - btrfs: mark compressed range uptodate only if all bio succeed
+    - x86/kvm: fix vcpu-id indexed array sizes
+    - KVM: add missing compat KVM_CLEAR_DIRTY_LOG
+    - ocfs2: fix zero out valid data
+    - ocfs2: issue zeroout to EOF blocks
+    - can: j1939: j1939_xtp_rx_dat_one(): fix rxtimer value between consecutive
+      TP.DT to 750ms
+    - can: raw: raw_setsockopt(): fix raw_rcv panic for sock UAF
+    - can: mcba_usb_start(): add missing urb->transfer_dma initialization
+    - can: usb_8dev: fix memory leak
+    - can: ems_usb: fix memory leak
+    - can: esd_usb2: fix memory leak
+    - HID: wacom: Re-enable touch by default for Cintiq 24HDT / 27QHDT
+    - NIU: fix incorrect error return, missed in previous revert
+    - nfc: nfcsim: fix use after free during module unload
+    - cfg80211: Fix possible memory leak in function cfg80211_bss_update
+    - netfilter: conntrack: adjust stop timestamp to real expiry value
+    - netfilter: nft_nat: allow to specify layer 4 protocol NAT only
+    - i40e: Fix logic of disabling queues
+    - i40e: Fix firmware LLDP agent related warning
+    - i40e: Fix queue-to-TC mapping on Tx
+    - i40e: Fix log TC creation failure when max num of queues is exceeded
+    - tipc: fix sleeping in tipc accept routine
+    - net: Set true network header for ECN decapsulation
+    - mlx4: Fix missing error code in mlx4_load_one()
+    - net: llc: fix skb_over_panic
+    - net/mlx5: Fix flow table chaining
+    - net/mlx5e: Fix nullptr in mlx5e_hairpin_get_mdev()
+    - sctp: fix return value check in __sctp_rcv_asconf_lookup
+    - tulip: windbond-840: Fix missing pci_disable_device() in probe and remove
+    - sis900: Fix missing pci_disable_device() in probe and remove
+    - can: hi311x: fix a signedness bug in hi3110_cmd()
+    - PCI: mvebu: Setup BAR0 in order to fix MSI
+    - powerpc/pseries: Fix regression while building external modules
+    - i40e: Add additional info to PHY type error
+    - can: j1939: j1939_session_deactivate(): clarify lifetime of session object
+    - Linux 5.4.138
+
+  * Focal update: v5.4.137 upstream stable release (LP: #1940557)
+    - selftest: fix build error in tools/testing/selftests/vm/userfaultfd.c
+    - tools: Allow proper CC/CXX/... override with LLVM=1 in Makefile.include
+    - KVM: x86: determine if an exception has an error code only when injecting
+      it.
+    - af_unix: fix garbage collect vs MSG_PEEK
+    - workqueue: fix UAF in pwq_unbound_release_workfn()
+    - cgroup1: fix leaked context root causing sporadic NULL deref in LTP
+    - net/802/mrp: fix memleak in mrp_request_join()
+    - net/802/garp: fix memleak in garp_request_join()
+    - net: annotate data race around sk_ll_usec
+    - sctp: move 198 addresses from unusable to private scope
+    - ipv6: allocate enough headroom in ip6_finish_output2()
+    - hfs: add missing clean-up in hfs_fill_super
+    - hfs: fix high memory mapping in hfs_bnode_read
+    - hfs: add lock nesting notation to hfs_find_init
+    - firmware: arm_scmi: Fix possible scmi_linux_errmap buffer overflow
+    - firmware: arm_scmi: Fix range check for the maximum number of pending
+      messages
+    - cifs: fix the out of range assignment to bit fields in
+      parse_server_interfaces
+    - iomap: remove the length variable in iomap_seek_data
+    - iomap: remove the length variable in iomap_seek_hole
+    - ARM: dts: versatile: Fix up interrupt controller node names
+    - ipv6: ip6_finish_output2: set sk into newly allocated nskb
+    - Linux 5.4.137
+
+  * Focal update: v5.4.136 upstream stable release (LP: #1939899)
+    - igc: Fix use-after-free error during reset
+    - igb: Fix use-after-free error during reset
+    - igc: change default return of igc_read_phy_reg()
+    - ixgbe: Fix an error handling path in 'ixgbe_probe()'
+    - igc: Prefer to use the pci_release_mem_regions method
+    - igc: Fix an error handling path in 'igc_probe()'
+    - igb: Fix an error handling path in 'igb_probe()'
+    - fm10k: Fix an error handling path in 'fm10k_probe()'
+    - e1000e: Fix an error handling path in 'e1000_probe()'
+    - iavf: Fix an error handling path in 'iavf_probe()'
+    - igb: Check if num of q_vectors is smaller than max before array access
+    - igb: Fix position of assignment to *ring
+    - gve: Fix an error handling path in 'gve_probe()'
+    - ipv6: fix 'disable_policy' for fwd packets
+    - selftests: icmp_redirect: remove from checking for IPv6 route get
+    - selftests: icmp_redirect: IPv6 PMTU info should be cleared after redirect
+    - pwm: sprd: Ensure configuring period and duty_cycle isn't wrongly skipped
+    - cxgb4: fix IRQ free race during driver unload
+    - nvme-pci: do not call nvme_dev_remove_admin from nvme_remove
+    - perf probe: Fix dso->nsinfo refcounting
+    - perf env: Fix sibling_dies memory leak
+    - perf test session_topology: Delete session->evlist
+    - perf test event_update: Fix memory leak of evlist
+    - perf dso: Fix memory leak in dso__new_map()
+    - perf script: Fix memory 'threads' and 'cpus' leaks on exit
+    - perf lzma: Close lzma stream on exit
+    - perf probe-file: Delete namelist in del_events() on the error path
+    - perf data: Close all files in close_dir()
+    - spi: imx: add a check for speed_hz before calculating the clock
+    - spi: stm32: Use dma_request_chan() instead dma_request_slave_channel()
+    - spi: stm32: fixes pm_runtime calls in probe/remove
+    - regulator: hi6421: Use correct variable type for regmap api val argument
+    - regulator: hi6421: Fix getting wrong drvdata
+    - spi: mediatek: fix fifo rx mode
+    - ASoC: rt5631: Fix regcache sync errors on resume
+    - liquidio: Fix unintentional sign extension issue on left shift of u16
+    - s390/bpf: Perform r1 range checking before accessing jit->seen_reg[r1]
+    - bpf, sockmap, tcp: sk_prot needs inuse_idx set for proc stats
+    - bpftool: Check malloc return value in mount_bpffs_for_pin
+    - net: fix uninit-value in caif_seqpkt_sendmsg
+    - efi/tpm: Differentiate missing and invalid final event log table.
+    - net: decnet: Fix sleeping inside in af_decnet
+    - KVM: PPC: Book3S: Fix CONFIG_TRANSACTIONAL_MEM=n crash
+    - KVM: PPC: Fix kvm_arch_vcpu_ioctl vcpu_load leak
+    - net: sched: fix memory leak in tcindex_partial_destroy_work
+    - netrom: Decrease sock refcount when sock timers expire
+    - scsi: iscsi: Fix iface sysfs attr detection
+    - scsi: target: Fix protect handling in WRITE SAME(32)
+    - spi: cadence: Correct initialisation of runtime PM again
+    - bnxt_en: Improve bnxt_ulp_stop()/bnxt_ulp_start() call sequence.
+    - bnxt_en: Refresh RoCE capabilities in bnxt_ulp_probe()
+    - bnxt_en: Add missing check for BNXT_STATE_ABORT_ERR in bnxt_fw_rset_task()
+    - bnxt_en: Check abort error state in bnxt_half_open_nic()
+    - net: hisilicon: rename CACHE_LINE_MASK to avoid redefinition
+    - net/tcp_fastopen: fix data races around tfo_active_disable_stamp
+    - net: hns3: fix rx VLAN offload state inconsistent issue
+    - net/sched: act_skbmod: Skip non-Ethernet packets
+    - ipv6: fix another slab-out-of-bounds in fib6_nh_flush_exceptions
+    - nvme-pci: don't WARN_ON in nvme_reset_work if ctrl.state is not RESETTING
+    - Revert "USB: quirks: ignore remote wake-up on Fibocom L850-GL LTE modem"
+    - afs: Fix tracepoint string placement with built-in AFS
+    - r8169: Avoid duplicate sysfs entry creation error
+    - nvme: set the PRACT bit when using Write Zeroes with T10 PI
+    - sctp: update active_key for asoc when old key is being replaced
+    - net: sched: cls_api: Fix the the wrong parameter
+    - drm/panel: raspberrypi-touchscreen: Prevent double-free
+    - proc: Avoid mixing integer types in mem_rw()
+    - s390/ftrace: fix ftrace_update_ftrace_func implementation
+    - s390/boot: fix use of expolines in the DMA code
+    - ALSA: usb-audio: Add missing proc text entry for BESPOKEN type
+    - ALSA: usb-audio: Add registration quirk for JBL Quantum headsets
+    - ALSA: sb: Fix potential ABBA deadlock in CSP driver
+    - ALSA: hdmi: Expose all pins on MSI MS-7C94 board
+    - xhci: Fix lost USB 2 remote wake
+    - KVM: PPC: Book3S: Fix H_RTAS rets buffer overflow
+    - KVM: PPC: Book3S HV Nested: Sanitise H_ENTER_NESTED TM state
+    - usb: hub: Disable USB 3 device initiated lpm if exit latency is too high
+    - usb: hub: Fix link power management max exit latency (MEL) calculations
+    - USB: usb-storage: Add LaCie Rugged USB3-FW to IGNORE_UAS
+    - usb: max-3421: Prevent corruption of freed memory
+    - usb: renesas_usbhs: Fix superfluous irqs happen after usb_pkt_pop()
+    - USB: serial: option: add support for u-blox LARA-R6 family
+    - USB: serial: cp210x: fix comments for GE CS1000
+    - USB: serial: cp210x: add ID for CEL EM3588 USB ZigBee stick
+    - usb: dwc2: gadget: Fix sending zero length packet in DDMA mode.
+    - firmware/efi: Tell memblock about EFI iomem reservations
+    - tracing/histogram: Rename "cpu" to "common_cpu"
+    - tracing: Fix bug in rb_per_cpu_empty() that might cause deadloop.
+    - btrfs: check for missing device in btrfs_trim_fs
+    - media: ngene: Fix out-of-bounds bug in ngene_command_config_free_buf()
+    - ixgbe: Fix packet corruption due to missing DMA sync
+    - selftest: use mmap instead of posix_memalign to allocate memory
+    - userfaultfd: do not untag user pointers
+    - hugetlbfs: fix mount mode command line processing
+    - rbd: don't hold lock_rwsem while running_list is being drained
+    - rbd: always kick acquire on "acquired" and "released" notifications
+    - nds32: fix up stack guard gap
+    - drm: Return -ENOTTY for non-drm ioctls
+    - net: dsa: mv88e6xxx: use correct .stats_set_histogram() on Topaz
+    - net: bcmgenet: ensure EXT_ENERGY_DET_MASK is clear
+    - iio: accel: bma180: Use explicit member assignment
+    - iio: accel: bma180: Fix BMA25x bandwidth register values
+    - btrfs: compression: don't try to compress if we don't have enough pages
+    - PCI: Mark AMD Navi14 GPU ATS as broken
+    - perf inject: Close inject.output on exit
+    - xhci: add xhci_get_virt_ep() helper
+    - Linux 5.4.136
+
+  * Focal update: v5.4.135 upstream stable release (LP: #1939442)
+    - ARM: dts: gemini: rename mdio to the right name
+    - ARM: dts: gemini: add device_type on pci
+    - ARM: dts: rockchip: fix pinctrl sleep nodename for rk3036-kylin and rk3288
+    - arm64: dts: rockchip: fix pinctrl sleep nodename for rk3399.dtsi
+    - ARM: dts: rockchip: Fix the timer clocks order
+    - ARM: dts: rockchip: Fix IOMMU nodes properties on rk322x
+    - ARM: dts: rockchip: Fix power-controller node names for rk3066a
+    - ARM: dts: rockchip: Fix power-controller node names for rk3188
+    - ARM: dts: rockchip: Fix power-controller node names for rk3288
+    - arm64: dts: rockchip: Fix power-controller node names for px30
+    - arm64: dts: rockchip: Fix power-controller node names for rk3328
+    - reset: ti-syscon: fix to_ti_syscon_reset_data macro
+    - ARM: brcmstb: dts: fix NAND nodes names
+    - ARM: Cygnus: dts: fix NAND nodes names
+    - ARM: NSP: dts: fix NAND nodes names
+    - ARM: dts: BCM63xx: Fix NAND nodes names
+    - ARM: dts: Hurricane 2: Fix NAND nodes names
+    - ARM: dts: imx6: phyFLEX: Fix UART hardware flow control
+    - ARM: imx: pm-imx5: Fix references to imx5_cpu_suspend_info
+    - rtc: mxc_v2: add missing MODULE_DEVICE_TABLE
+    - kbuild: sink stdout from cmd for silent build
+    - ARM: dts: am57xx-cl-som-am57x: fix ti,no-reset-on-init flag for gpios
+    - ARM: dts: am437x-gp-evm: fix ti,no-reset-on-init flag for gpios
+    - ARM: dts: stm32: fix gpio-keys node on STM32 MCU boards
+    - ARM: dts: stm32: fix RCC node name on stm32f429 MCU
+    - ARM: dts: stm32: fix timer nodes on STM32 MCU to prevent warnings
+    - arm64: dts: juno: Update SCPI nodes as per the YAML schema
+    - ARM: dts: rockchip: fix supply properties in io-domains nodes
+    - ARM: dts: stm32: fix i2c node name on stm32f746 to prevent warnings
+    - ARM: dts: stm32: move stmmac axi config in ethernet node on stm32mp15
+    - soc/tegra: fuse: Fix Tegra234-only builds
+    - firmware: tegra: bpmp: Fix Tegra234-only builds
+    - arm64: dts: ls208xa: remove bus-num from dspi node
+    - arm64: dts: imx8mq: assign PCIe clocks
+    - thermal/core: Correct function name thermal_zone_device_unregister()
+    - kbuild: mkcompile_h: consider timestamp if KBUILD_BUILD_TIMESTAMP is set
+    - rtc: max77686: Do not enforce (incorrect) interrupt trigger type
+    - scsi: aic7xxx: Fix unintentional sign extension issue on left shift of u8
+    - scsi: libsas: Add LUN number check in .slave_alloc callback
+    - scsi: libfc: Fix array index out of bound exception
+    - scsi: qedf: Add check to synchronize abort and flush
+    - sched/fair: Fix CFS bandwidth hrtimer expiry type
+    - s390: introduce proper type handling call_on_stack() macro
+    - cifs: prevent NULL deref in cifs_compose_mount_options()
+    - arm64: dts: armada-3720-turris-mox: add firmware node
+    - firmware: turris-mox-rwtm: add marvell,armada-3700-rwtm-firmware compatible
+      string
+    - arm64: dts: marvell: armada-37xx: move firmware node to generic dtsi file
+    - f2fs: Show casefolding support only when supported
+    - usb: cdns3: Enable TDL_CHK only for OUT ep
+    - Revert "UBUNTU: SAUCE: Revert "mm: memcg/slab: fix memory leak at non-root
+      kmem_cache destroy""
+    - mm: slab: fix kmem_cache_create failed when sysfs node not destroyed
+    - dm writecache: return the exact table values that were set
+    - net: dsa: mv88e6xxx: enable .port_set_policy() on Topaz
+    - net: dsa: mv88e6xxx: enable .rmu_disable() on Topaz
+    - net: ipv6: fix return value of ip6_skb_dst_mtu
+    - netfilter: ctnetlink: suspicious RCU usage in ctnetlink_dump_helpinfo
+    - net/sched: act_ct: fix err check for nf_conntrack_confirm
+    - net: bridge: sync fdb to new unicast-filtering ports
+    - net: bcmgenet: Ensure all TX/RX queues DMAs are disabled
+    - net: ip_tunnel: fix mtu calculation for ETHER tunnel devices
+    - net: moxa: fix UAF in moxart_mac_probe
+    - net: qcom/emac: fix UAF in emac_remove
+    - net: ti: fix UAF in tlan_remove_one
+    - net: send SYNACK packet with accepted fwmark
+    - net: validate lwtstate->data before returning from skb_tunnel_info()
+    - net: fddi: fix UAF in fza_probe
+    - dma-buf/sync_file: Don't leak fences on merge failure
+    - tcp: annotate data races around tp->mtu_info
+    - ipv6: tcp: drop silly ICMPv6 packet too big messages
+    - bpftool: Properly close va_list 'ap' by va_end() on error
+    - perf test bpf: Free obj_buf
+    - udp: annotate data races around unix_sk(sk)->gso_size
+    - Linux 5.4.135
+
+  * Focal update: v5.4.134 upstream stable release (LP: #1939440)
+    - KVM: mmio: Fix use-after-free Read in kvm_vm_ioctl_unregister_coalesced_mmio
+    - KVM: x86: Use guest MAXPHYADDR from CPUID.0x8000_0008 iff TDP is enabled
+    - KVM: X86: Disable hardware breakpoints unconditionally before kvm_x86->run()
+    - scsi: core: Fix bad pointer dereference when ehandler kthread is invalid
+    - tracing: Do not reference char * as a string in histograms
+    - cgroup: verify that source is a string
+    - fbmem: Do not delete the mode that is still in use
+    - net: moxa: Use devm_platform_get_and_ioremap_resource()
+    - dmaengine: fsl-qdma: check dma_set_mask return value
+    - srcu: Fix broken node geometry after early ssp init
+    - tty: serial: fsl_lpuart: fix the potential risk of division or modulo by
+      zero
+    - misc/libmasm/module: Fix two use after free in ibmasm_init_one
+    - misc: alcor_pci: fix null-ptr-deref when there is no PCI bridge
+    - iio: gyro: fxa21002c: Balance runtime pm + use pm_runtime_resume_and_get().
+    - iio: magn: bmc150: Balance runtime pm + use pm_runtime_resume_and_get()
+    - ALSA: usx2y: Don't call free_pages_exact() with NULL address
+    - Revert "ALSA: bebob/oxfw: fix Kconfig entry for Mackie d.2 Pro"
+    - w1: ds2438: fixing bug that would always get page0
+    - scsi: hisi_sas: Propagate errors in interrupt_init_v1_hw()
+    - scsi: lpfc: Fix "Unexpected timeout" error in direct attach topology
+    - scsi: lpfc: Fix crash when lpfc_sli4_hba_setup() fails to initialize the
+      SGLs
+    - scsi: core: Cap scsi_host cmd_per_lun at can_queue
+    - ALSA: ac97: fix PM reference leak in ac97_bus_remove()
+    - tty: serial: 8250: serial_cs: Fix a memory leak in error handling path
+    - scsi: scsi_dh_alua: Check for negative result value
+    - fs/jfs: Fix missing error code in lmLogInit()
+    - scsi: megaraid_sas: Fix resource leak in case of probe failure
+    - scsi: megaraid_sas: Early detection of VD deletion through RaidMap update
+    - scsi: megaraid_sas: Handle missing interrupts while re-enabling IRQs
+    - scsi: iscsi: Add iscsi_cls_conn refcount helpers
+    - scsi: iscsi: Fix conn use after free during resets
+    - scsi: iscsi: Fix shost->max_id use
+    - scsi: qedi: Fix null ref during abort handling
+    - mfd: da9052/stmpe: Add and modify MODULE_DEVICE_TABLE
+    - mfd: cpcap: Fix cpcap dmamask not set warnings
+    - ASoC: img: Fix PM reference leak in img_i2s_in_probe()
+    - serial: tty: uartlite: fix console setup
+    - s390/sclp_vt220: fix console name to match device
+    - ALSA: sb: Fix potential double-free of CSP mixer elements
+    - powerpc/ps3: Add dma_mask to ps3_dma_region
+    - iommu/arm-smmu: Fix arm_smmu_device refcount leak when arm_smmu_rpm_get
+      fails
+    - iommu/arm-smmu: Fix arm_smmu_device refcount leak in address translation
+    - gpio: zynq: Check return value of pm_runtime_get_sync
+    - ALSA: ppc: fix error return code in snd_pmac_probe()
+    - selftests/powerpc: Fix "no_handler" EBB selftest
+    - gpio: pca953x: Add support for the On Semi pca9655
+    - ASoC: soc-core: Fix the error return code in
+      snd_soc_of_parse_audio_routing()
+    - s390/processor: always inline stap() and __load_psw_mask()
+    - s390/ipl_parm: fix program check new psw handling
+    - s390/mem_detect: fix diag260() program check new psw handling
+    - s390/mem_detect: fix tprot() program check new psw handling
+    - Input: hideep - fix the uninitialized use in hideep_nvm_unlock()
+    - ALSA: bebob: add support for ToneWeal FW66
+    - ALSA: usb-audio: scarlett2: Fix 18i8 Gen 2 PCM Input count
+    - ALSA: usb-audio: scarlett2: Fix data_mutex lock
+    - ALSA: usb-audio: scarlett2: Fix scarlett2_*_ctl_put() return values
+    - usb: gadget: f_hid: fix endianness issue with descriptors
+    - usb: gadget: hid: fix error return code in hid_bind()
+    - powerpc/boot: Fixup device-tree on little endian
+    - ASoC: Intel: kbl_da7219_max98357a: shrink platform_id below 20 characters
+    - backlight: lm3630a: Fix return code of .update_status() callback
+    - ALSA: hda: Add IRQ check for platform_get_irq()
+    - ALSA: usb-audio: scarlett2: Fix 6i6 Gen 2 line out descriptions
+    - staging: rtl8723bs: fix macro value for 2.4Ghz only device
+    - intel_th: Wait until port is in reset before programming it
+    - i2c: core: Disable client irq on reboot/shutdown
+    - power: supply: sc27xx: Add missing MODULE_DEVICE_TABLE
+    - power: supply: sc2731_charger: Add missing MODULE_DEVICE_TABLE
+    - pwm: spear: Don't modify HW state in .remove callback
+    - power: supply: ab8500: Avoid NULL pointers
+    - power: supply: max17042: Do not enforce (incorrect) interrupt trigger type
+    - power: reset: gpio-poweroff: add missing MODULE_DEVICE_TABLE
+    - ARM: 9087/1: kprobes: test-thumb: fix for LLVM_IAS=1
+    - PCI/P2PDMA: Avoid pci_get_slot(), which may sleep
+    - watchdog: Fix possible use-after-free in wdt_startup()
+    - watchdog: sc520_wdt: Fix possible use-after-free in wdt_turnoff()
+    - watchdog: Fix possible use-after-free by calling del_timer_sync()
+    - watchdog: imx_sc_wdt: fix pretimeout
+    - x86/fpu: Return proper error codes from user access functions
+    - PCI: tegra: Add missing MODULE_DEVICE_TABLE
+    - orangefs: fix orangefs df output.
+    - ceph: remove bogus checks and WARN_ONs from ceph_set_page_dirty
+    - NFS: nfs_find_open_context() may only select open files
+    - power: supply: charger-manager: add missing MODULE_DEVICE_TABLE
+    - power: supply: ab8500: add missing MODULE_DEVICE_TABLE
+    - pwm: img: Fix PM reference leak in img_pwm_enable()
+    - pwm: tegra: Don't modify HW state in .remove callback
+    - ACPI: AMBA: Fix resource name in /proc/iomem
+    - ACPI: video: Add quirk for the Dell Vostro 3350
+    - virtio-blk: Fix memory leak among suspend/resume procedure
+    - virtio_net: Fix error handling in virtnet_restore()
+    - virtio_console: Assure used length from device is limited
+    - x86/signal: Detect and prevent an alternate signal stack overflow
+    - f2fs: add MODULE_SOFTDEP to ensure crc32 is included in the initramfs
+    - PCI/sysfs: Fix dsm_label_utf16s_to_utf8s() buffer overrun
+    - power: supply: rt5033_battery: Fix device tree enumeration
+    - NFSv4: Initialise connection to the server in nfs4_alloc_client()
+    - um: fix error return code in slip_open()
+    - um: fix error return code in winch_tramp()
+    - watchdog: aspeed: fix hardware timeout calculation
+    - nfs: fix acl memory leak of posix_acl_create()
+    - ubifs: Set/Clear I_LINKABLE under i_lock for whiteout inode
+    - PCI: iproc: Fix multi-MSI base vector number allocation
+    - PCI: iproc: Support multi-MSI only on uniprocessor kernel
+    - x86/fpu: Limit xstate copy size in xstateregs_set()
+    - pwm: imx1: Don't disable clocks at device remove time
+    - virtio_net: move tx vq operation under tx queue lock
+    - nvme-tcp: can't set sk_user_data without write_lock
+    - ALSA: isa: Fix error return code in snd_cmi8330_probe()
+    - NFSv4/pNFS: Don't call _nfs4_pnfs_v3_ds_connect multiple times
+    - hexagon: use common DISCARDS macro
+    - ARM: dts: gemini-rut1xx: remove duplicate ethernet node
+    - reset: a10sr: add missing of_match_table reference
+    - ARM: exynos: add missing of_node_put for loop iteration
+    - ARM: dts: exynos: fix PWM LED max brightness on Odroid XU/XU3
+    - ARM: dts: exynos: fix PWM LED max brightness on Odroid HC1
+    - ARM: dts: exynos: fix PWM LED max brightness on Odroid XU4
+    - memory: atmel-ebi: add missing of_node_put for loop iteration
+    - reset: brcmstb: Add missing MODULE_DEVICE_TABLE
+    - memory: pl353: Fix error return code in pl353_smc_probe()
+    - rtc: fix snprintf() checking in is_rtc_hctosys()
+    - arm64: dts: renesas: v3msk: Fix memory size
+    - ARM: dts: r8a7779, marzen: Fix DU clock names
+    - firmware: tegra: Fix error return code in tegra210_bpmp_init()
+    - firmware: arm_scmi: Reset Rx buffer to max size during async commands
+    - ARM: dts: BCM5301X: Fixup SPI binding
+    - reset: bail if try_module_get() fails
+    - memory: fsl_ifc: fix leak of IO mapping on probe failure
+    - memory: fsl_ifc: fix leak of private memory on probe failure
+    - ARM: dts: am335x: align ti,pindir-d0-out-d1-in property with dt-shema
+    - ARM: dts: am437x: align ti,pindir-d0-out-d1-in property with dt-shema
+    - ARM: dts: imx6q-dhcom: Fix ethernet reset time properties
+    - ARM: dts: imx6q-dhcom: Fix ethernet plugin detection problems
+    - ARM: dts: imx6q-dhcom: Add gpios pinctrl for i2c bus recovery
+    - thermal/drivers/rcar_gen3_thermal: Fix coefficient calculations
+    - firmware: turris-mox-rwtm: fix reply status decoding function
+    - firmware: turris-mox-rwtm: report failures better
+    - firmware: turris-mox-rwtm: fail probing when firmware does not support hwrng
+    - scsi: be2iscsi: Fix an error handling path in beiscsi_dev_probe()
+    - mips: always link byteswap helpers into decompressor
+    - mips: disable branch profiling in boot/decompress.o
+    - MIPS: vdso: Invalid GIC access through VDSO
+    - scsi: scsi_dh_alua: Fix signedness bug in alua_rtpg()
+    - misc: alcor_pci: fix inverted branch condition
+    - Linux 5.4.134
+
+ -- Kleber Sacilotto de Souza <kleber.souza@canonical.com>  Mon, 20 Sep 2021 21:38:19 +0200
+
+linux (5.4.0-86.97) focal; urgency=medium
+
+  * s390x BPF JIT vulnerabilities (LP: #1943960)
+    - SAUCE: s390/bpf: Fix 64-bit subtraction of the -0x80000000 constant
+    - SAUCE: s390/bpf: Fix optimizing out zero-extensions
+
+ -- Thadeu Lima de Souza Cascardo <cascardo@canonical.com>  Fri, 17 Sep 2021 15:35:09 -0300
+
+linux (5.4.0-84.94) focal; urgency=medium
+
+  * focal/linux: 5.4.0-84.94 -proposed tracker (LP: #1941767)
+
+  * Server boot failure after adding checks for ACPI IRQ override (LP: #1941657)
+    - Revert "ACPI: resources: Add checks for ACPI IRQ override"
+
+ -- Kelsey Skunberg <kelsey.skunberg@canonical.com>  Thu, 26 Aug 2021 12:48:59 -0600
+
+linux (5.4.0-83.93) focal; urgency=medium
+
+  * focal/linux: 5.4.0-83.93 -proposed tracker (LP: #1940159)
+
+  * fails to launch linux L2 guests on AMD (LP: #1940134) // CVE-2021-3653
+    - KVM: nSVM: avoid picking up unsupported bits from L2 in int_ctl
+      (CVE-2021-3653)
+
+  * fails to launch linux L2 guests on AMD (LP: #1940134)
+    - SAUCE: Revert "UBUNTU: SAUCE: KVM: nSVM: avoid picking up unsupported bits
+      from L2 in int_ctl"
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Tue, 17 Aug 2021 11:37:56 +0200
+
+linux (5.4.0-82.92) focal; urgency=medium
+
+  * focal/linux: 5.4.0-82.92 -proposed tracker (LP: #1939799)
+
+  * Packaging resync (LP: #1786013)
+    - debian/dkms-versions -- update from kernel-versions (main/2021.08.16)
+
+  * CVE-2021-3656
+    - SAUCE: KVM: nSVM: always intercept VMLOAD/VMSAVE when nested
+
+  * CVE-2021-3653
+    - SAUCE: KVM: nSVM: avoid picking up unsupported bits from L2 in int_ctl
+
+  * [regression] USB device is not detected during boot (LP: #1939638)
+    - SAUCE: Revert "usb: core: reduce power-on-good delay time of root hub"
+
+  * dev_forward_skb: do not scrub skb mark within the same name space
+    (LP: #1935040)
+    - dev_forward_skb: do not scrub skb mark within the same name space
+
+  * XPS 9510 (TGL) Screen Brightness could not be changed (LP: #1933566)
+    - SAUCE: drm/i915: Force DPCD backlight mode for Dell XPS 9510(TGL)
+
+  * Acer Aspire 5 sound driver issues (LP: #1930188)
+    - ALSA: hda/realtek: headphone and mic don't work on an Acer laptop
+
+  * Sony Dualshock 4 usb dongle crashes the whole system (LP: #1935846)
+    - HID: sony: Workaround for DS4 dongle hotplug kernel crash.
+
+  * [21.10 FEAT] KVM: Provide a secure guest indication (LP: #1933173)
+    - s390/uv: add prot virt guest/host indication files
+    - s390/uv: fix prot virt host indication compilation
+
+  * Skip rtcpie test in kselftests/timers if the default RTC device does not
+    exist (LP: #1937991)
+    - selftests: timers: rtcpie: skip test if default RTC device does not exist
+
+  * Focal update: v5.4.133 upstream stable release (LP: #1938713)
+    - drm/mxsfb: Don't select DRM_KMS_FB_HELPER
+    - drm/zte: Don't select DRM_KMS_FB_HELPER
+    - drm/amd/amdgpu/sriov disable all ip hw status by default
+    - drm/vc4: fix argument ordering in vc4_crtc_get_margins()
+    - net: pch_gbe: Use proper accessors to BE data in pch_ptp_match()
+    - drm/amd/display: fix use_max_lb flag for 420 pixel formats
+    - hugetlb: clear huge pte during flush function on mips platform
+    - atm: iphase: fix possible use-after-free in ia_module_exit()
+    - mISDN: fix possible use-after-free in HFC_cleanup()
+    - atm: nicstar: Fix possible use-after-free in nicstar_cleanup()
+    - net: Treat __napi_schedule_irqoff() as __napi_schedule() on PREEMPT_RT
+    - drm/mediatek: Fix PM reference leak in mtk_crtc_ddp_hw_init()
+    - reiserfs: add check for invalid 1st journal block
+    - drm/virtio: Fix double free on probe failure
+    - drm/sched: Avoid data corruptions
+    - udf: Fix NULL pointer dereference in udf_symlink function
+    - e100: handle eeprom as little endian
+    - igb: handle vlan types with checker enabled
+    - drm/bridge: cdns: Fix PM reference leak in cdns_dsi_transfer()
+    - clk: renesas: r8a77995: Add ZA2 clock
+    - clk: tegra: Ensure that PLLU configuration is applied properly
+    - ipv6: use prandom_u32() for ID generation
+    - RDMA/cxgb4: Fix missing error code in create_qp()
+    - dm space maps: don't reset space map allocation cursor when committing
+    - pinctrl: mcp23s08: fix race condition in irq handler
+    - ice: set the value of global config lock timeout longer
+    - virtio_net: Remove BUG() to avoid machine dead
+    - net: bcmgenet: check return value after calling platform_get_resource()
+    - net: mvpp2: check return value after calling platform_get_resource()
+    - net: micrel: check return value after calling platform_get_resource()
+    - drm/amd/display: Update scaling settings on modeset
+    - drm/amd/display: Release MST resources on switch from MST to SST
+    - drm/amd/display: Set DISPCLK_MAX_ERRDET_CYCLES to 7
+    - drm/amdkfd: use allowed domain for vmbo validation
+    - fjes: check return value after calling platform_get_resource()
+    - selinux: use __GFP_NOWARN with GFP_NOWAIT in the AVC
+    - r8169: avoid link-up interrupt issue on RTL8106e if user enables ASPM
+    - drm/amd/display: Verify Gamma & Degamma LUT sizes in amdgpu_dm_atomic_check
+    - xfrm: Fix error reporting in xfrm_state_construct.
+    - wlcore/wl12xx: Fix wl12xx get_mac error if device is in ELP
+    - wl1251: Fix possible buffer overflow in wl1251_cmd_scan
+    - cw1200: add missing MODULE_DEVICE_TABLE
+    - bpf: Fix up register-based shifts in interpreter to silence KUBSAN
+    - mt76: mt7615: fix fixed-rate tx status reporting
+    - net: fix mistake path for netdev_features_strings
+    - net: sched: fix error return code in tcf_del_walker()
+    - drm/amdkfd: Walk through list with dqm lock hold
+    - rtl8xxxu: Fix device info for RTL8192EU devices
+    - atm: nicstar: use 'dma_free_coherent' instead of 'kfree'
+    - atm: nicstar: register the interrupt handler in the right place
+    - vsock: notify server to shutdown when client has pending signal
+    - RDMA/rxe: Don't overwrite errno from ib_umem_get()
+    - iwlwifi: mvm: don't change band on bound PHY contexts
+    - iwlwifi: pcie: free IML DMA memory allocation
+    - iwlwifi: pcie: fix context info freeing
+    - sfc: avoid double pci_remove of VFs
+    - sfc: error code if SRIOV cannot be disabled
+    - wireless: wext-spy: Fix out-of-bounds warning
+    - media, bpf: Do not copy more entries than user space requested
+    - net: ip: avoid OOM kills with large UDP sends over loopback
+    - RDMA/cma: Fix rdma_resolve_route() memory leak
+    - Bluetooth: btusb: Fixed too many in-token issue for Mediatek Chip.
+    - Bluetooth: Fix the HCI to MGMT status conversion table
+    - Bluetooth: Shutdown controller after workqueues are flushed or cancelled
+    - Bluetooth: btusb: fix bt fiwmare downloading failure issue for qca btsoc.
+    - sctp: validate from_addr_param return
+    - sctp: add size validation when walking chunks
+    - MIPS: loongsoon64: Reserve memory below starting pfn to prevent Oops
+    - MIPS: set mips32r5 for virt extensions
+    - fscrypt: don't ignore minor_hash when hash is 0
+    - crypto: ccp - Annotate SEV Firmware file names
+    - perf bench: Fix 2 memory sanitizer warnings
+    - powerpc/mm: Fix lockup on kernel exec fault
+    - powerpc/barrier: Avoid collision with clang's __lwsync macro
+    - drm/amdgpu: Update NV SIMD-per-CU to 2
+    - drm/radeon: Add the missed drm_gem_object_put() in
+      radeon_user_framebuffer_create()
+    - drm/rockchip: dsi: remove extra component_del() call
+    - drm/amd/display: fix incorrrect valid irq check
+    - pinctrl/amd: Add device HID for new AMD GPIO controller
+    - drm/tegra: Don't set allow_fb_modifiers explicitly
+    - drm/msm/mdp4: Fix modifier support enabling
+    - drm/arm/malidp: Always list modifiers
+    - mmc: sdhci: Fix warning message when accessing RPMB in HS400 mode
+    - mmc: core: clear flags before allowing to retune
+    - mmc: core: Allow UHS-I voltage switch for SDSC cards if supported
+    - ata: ahci_sunxi: Disable DIPM
+    - cpu/hotplug: Cure the cpusets trainwreck
+    - clocksource/arm_arch_timer: Improve Allwinner A64 timer workaround
+    - fpga: stratix10-soc: Add missing fpga_mgr_free() call
+    - MIPS: fix "mipsel-linux-ld: decompress.c:undefined reference to `memmove'"
+    - ASoC: tegra: Set driver_name=tegra for all machine drivers
+    - qemu_fw_cfg: Make fw_cfg_rev_attr a proper kobj_attribute
+    - ipmi/watchdog: Stop watchdog timer when the current action is 'none'
+    - thermal/drivers/int340x/processor_thermal: Fix tcc setting
+    - ubifs: Fix races between xattr_{set|get} and listxattr operations
+    - power: supply: ab8500: Fix an old bug
+    - nvmem: core: add a missing of_node_put
+    - extcon: intel-mrfld: Sync hardware and software state on init
+    - seq_buf: Fix overflow in seq_buf_putmem_hex()
+    - rq-qos: fix missed wake-ups in rq_qos_throttle try two
+    - tracing: Simplify & fix saved_tgids logic
+    - tracing: Resize tgid_map to pid_max, not PID_MAX_DEFAULT
+    - ipack/carriers/tpci200: Fix a double free in tpci200_pci_probe
+    - coresight: tmc-etf: Fix global-out-of-bounds in tmc_update_etf_buffer()
+    - dm btree remove: assign new_root only when removal succeeds
+    - PCI: Leave Apple Thunderbolt controllers on for s2idle or standby
+    - PCI: aardvark: Fix checking for PIO Non-posted Request
+    - PCI: aardvark: Implement workaround for the readback value of VEND_ID
+    - media: subdev: disallow ioctl for saa6588/davinci
+    - media: dtv5100: fix control-request directions
+    - media: zr364xx: fix memory leak in zr364xx_start_readpipe
+    - media: gspca/sq905: fix control-request direction
+    - media: gspca/sunplus: fix zero-length control requests
+    - pinctrl: mcp23s08: Fix missing unlock on error in mcp23s08_irq()
+    - jfs: fix GPF in diFree
+    - smackfs: restrict bytes count in smk_set_cipso()
+    - Linux 5.4.133
+
+  * Focal update: v5.4.132 upstream stable release (LP: #1938199)
+    - ALSA: usb-audio: fix rate on Ozone Z90 USB headset
+    - ALSA: usb-audio: Fix OOB access at proc output
+    - ALSA: usb-audio: scarlett2: Fix wrong resume call
+    - ALSA: intel8x0: Fix breakage at ac97 clock measurement
+    - ALSA: hda/realtek: Add another ALC236 variant support
+    - ALSA: hda/realtek: Improve fixup for HP Spectre x360 15-df0xxx
+    - ALSA: hda/realtek: Fix bass speaker DAC mapping for Asus UM431D
+    - ALSA: hda/realtek: Apply LED fixup for HP Dragonfly G1, too
+    - media: dvb-usb: fix wrong definition
+    - Input: usbtouchscreen - fix control-request directions
+    - net: can: ems_usb: fix use-after-free in ems_usb_disconnect()
+    - usb: gadget: eem: fix echo command packet response issue
+    - USB: cdc-acm: blacklist Heimann USB Appset device
+    - usb: dwc3: Fix debugfs creation flow
+    - usb: typec: Add the missed altmode_id_remove() in typec_register_altmode()
+    - xhci: solve a double free problem while doing s4
+    - ntfs: fix validity check for file name attribute
+    - copy_page_to_iter(): fix ITER_DISCARD case
+    - iov_iter_fault_in_readable() should do nothing in xarray case
+    - Input: joydev - prevent use of not validated data in JSIOCSBTNMAP ioctl
+    - arm_pmu: Fix write counter incorrect in ARMv7 big-endian mode
+    - ARM: dts: at91: sama5d4: fix pinctrl muxing
+    - btrfs: send: fix invalid path for unlink operations after parent
+      orphanization
+    - btrfs: clear defrag status of a root if starting transaction fails
+    - ext4: cleanup in-core orphan list if ext4_truncate() failed to get a
+      transaction handle
+    - ext4: fix kernel infoleak via ext4_extent_header
+    - ext4: return error code when ext4_fill_flex_info() fails
+    - ext4: correct the cache_nr in tracepoint ext4_es_shrink_exit
+    - ext4: remove check for zero nr_to_scan in ext4_es_scan()
+    - ext4: fix avefreec in find_group_orlov
+    - ext4: use ext4_grp_locked_error in mb_find_extent
+    - can: gw: synchronize rcu operations before removing gw job entry
+    - can: j1939: j1939_sk_init(): set SOCK_RCU_FREE to call sk_destruct() after
+      RCU is done
+    - can: peak_pciefd: pucan_handle_status(): fix a potential starvation issue in
+      TX path
+    - mac80211: remove iwlwifi specific workaround that broke sta NDP tx
+    - SUNRPC: Fix the batch tasks count wraparound.
+    - SUNRPC: Should wake up the privileged task firstly.
+    - perf/smmuv3: Don't trample existing events with global filter
+    - KVM: PPC: Book3S HV: Workaround high stack usage with clang
+    - s390/cio: dont call css_wait_for_slow_path() inside a lock
+    - rtc: stm32: Fix unbalanced clk_disable_unprepare() on probe error path
+    - iio: light: tcs3472: do not free unallocated IRQ
+    - iio: ltr501: mark register holding upper 8 bits of ALS_DATA{0,1} and PS_DATA
+      as volatile, too
+    - iio: ltr501: ltr559: fix initialization of LTR501_ALS_CONTR
+    - iio: ltr501: ltr501_read_ps(): add missing endianness conversion
+    - serial: mvebu-uart: fix calculation of clock divisor
+    - serial: sh-sci: Stop dmaengine transfer in sci_stop_tx()
+    - serial_cs: Add Option International GSM-Ready 56K/ISDN modem
+    - serial_cs: remove wrong GLOBETROTTER.cis entry
+    - ath9k: Fix kernel NULL pointer dereference during ath_reset_internal()
+    - ssb: sdio: Don't overwrite const buffer if block_write fails
+    - rsi: Assign beacon rate settings to the correct rate_info descriptor field
+    - rsi: fix AP mode with WPA failure due to encrypted EAPOL
+    - tracing/histograms: Fix parsing of "sym-offset" modifier
+    - tracepoint: Add tracepoint_probe_register_may_exist() for BPF tracing
+    - seq_buf: Make trace_seq_putmem_hex() support data longer than 8
+    - powerpc/stacktrace: Fix spurious "stale" traces in raise_backtrace_ipi()
+    - evm: Execute evm_inode_init_security() only when an HMAC key is loaded
+    - evm: Refuse EVM_ALLOW_METADATA_WRITES only if an HMAC key is loaded
+    - fuse: ignore PG_workingset after stealing
+    - fuse: check connected before queueing on fpq->io
+    - fuse: reject internal errno
+    - spi: Make of_register_spi_device also set the fwnode
+    - media: mdk-mdp: fix pm_runtime_get_sync() usage count
+    - media: s5p: fix pm_runtime_get_sync() usage count
+    - media: sh_vou: fix pm_runtime_get_sync() usage count
+    - media: mtk-vcodec: fix PM runtime get logic
+    - media: s5p-jpeg: fix pm_runtime_get_sync() usage count
+    - media: sti/bdisp: fix pm_runtime_get_sync() usage count
+    - media: exynos-gsc: fix pm_runtime_get_sync() usage count
+    - spi: spi-loopback-test: Fix 'tx_buf' might be 'rx_buf'
+    - spi: spi-topcliff-pch: Fix potential double free in
+      pch_spi_process_messages()
+    - spi: omap-100k: Fix the length judgment problem
+    - regulator: uniphier: Add missing MODULE_DEVICE_TABLE
+    - hwrng: exynos - Fix runtime PM imbalance on error
+    - crypto: nx - add missing MODULE_DEVICE_TABLE
+    - media: sti: fix obj-$(config) targets
+    - media: cpia2: fix memory leak in cpia2_usb_probe
+    - media: cobalt: fix race condition in setting HPD
+    - media: pvrusb2: fix warning in pvr2_i2c_core_done
+    - media: imx: imx7_mipi_csis: Fix logging of only error event counters
+    - crypto: qat - check return code of qat_hal_rd_rel_reg()
+    - crypto: qat - remove unused macro in FW loader
+    - sched/fair: Fix ascii art by relpacing tabs
+    - media: em28xx: Fix possible memory leak of em28xx struct
+    - media: v4l2-core: Avoid the dangling pointer in v4l2_fh_release
+    - media: bt8xx: Fix a missing check bug in bt878_probe
+    - media: st-hva: Fix potential NULL pointer dereferences
+    - Makefile: fix GDB warning with CONFIG_RELR
+    - media: dvd_usb: memory leak in cinergyt2_fe_attach
+    - memstick: rtsx_usb_ms: fix UAF
+    - mmc: sdhci-sprd: use sdhci_sprd_writew
+    - mmc: via-sdmmc: add a check against NULL pointer dereference
+    - crypto: shash - avoid comparing pointers to exported functions under CFI
+    - media: dvb_net: avoid speculation from net slot
+    - media: siano: fix device register error path
+    - media: imx-csi: Skip first few frames from a BT.656 source
+    - hwmon: (max31790) Report correct current pwm duty cycles
+    - hwmon: (max31790) Fix pwmX_enable attributes
+    - drivers/perf: fix the missed ida_simple_remove() in ddr_perf_probe()
+    - KVM: PPC: Book3S HV: Fix TLB management on SMT8 POWER9 and POWER10
+      processors
+    - btrfs: fix error handling in __btrfs_update_delayed_inode
+    - btrfs: abort transaction if we fail to update the delayed inode
+    - btrfs: disable build on platforms having page size 256K
+    - locking/lockdep: Fix the dep path printing for backwards BFS
+    - lockding/lockdep: Avoid to find wrong lock dep path in check_irq_usage()
+    - KVM: s390: get rid of register asm usage
+    - regulator: mt6358: Fix vdram2 .vsel_mask
+    - regulator: da9052: Ensure enough delay time for .set_voltage_time_sel
+    - media: Fix Media Controller API config checks
+    - HID: do not use down_interruptible() when unbinding devices
+    - EDAC/ti: Add missing MODULE_DEVICE_TABLE
+    - ACPI: processor idle: Fix up C-state latency if not ordered
+    - hv_utils: Fix passing zero to 'PTR_ERR' warning
+    - lib: vsprintf: Fix handling of number field widths in vsscanf
+    - ACPI: EC: Make more Asus laptops use ECDT _GPE
+    - block_dump: remove block_dump feature in mark_inode_dirty()
+    - fs: dlm: cancel work sync othercon
+    - random32: Fix implicit truncation warning in prandom_seed_state()
+    - fs: dlm: fix memory leak when fenced
+    - ACPICA: Fix memory leak caused by _CID repair function
+    - ACPI: bus: Call kobject_put() in acpi_init() error path
+    - block: fix race between adding/removing rq qos and normal IO
+    - platform/x86: toshiba_acpi: Fix missing error code in
+      toshiba_acpi_setup_keyboard()
+    - nvmet-fc: do not check for invalid target port in nvmet_fc_handle_fcp_rqst()
+    - EDAC/Intel: Do not load EDAC driver when running as a guest
+    - PCI: hv: Add check for hyperv_initialized in init_hv_pci_drv()
+    - clocksource: Retry clock read if long delays detected
+    - ACPI: tables: Add custom DSDT file as makefile prerequisite
+    - HID: wacom: Correct base usage for capacitive ExpressKey status bits
+    - cifs: fix missing spinlock around update to ses->status
+    - block: fix discard request merge
+    - kthread_worker: fix return value when kthread_mod_delayed_work() races with
+      kthread_cancel_delayed_work_sync()
+    - ia64: mca_drv: fix incorrect array size calculation
+    - writeback, cgroup: increment isw_nr_in_flight before grabbing an inode
+    - media: s5p_cec: decrement usage count if disabled
+    - crypto: ixp4xx - dma_unmap the correct address
+    - crypto: ux500 - Fix error return code in hash_hw_final()
+    - sata_highbank: fix deferred probing
+    - pata_rb532_cf: fix deferred probing
+    - media: I2C: change 'RST' to "RSET" to fix multiple build errors
+    - sched/uclamp: Fix wrong implementation of cpu.uclamp.min
+    - sched/uclamp: Fix locking around cpu_util_update_eff()
+    - kbuild: run the checker after the compiler
+    - kbuild: Fix objtool dependency for 'OBJECT_FILES_NON_STANDARD_<obj> := n'
+    - pata_octeon_cf: avoid WARN_ON() in ata_host_activate()
+    - evm: fix writing <securityfs>/evm overflow
+    - crypto: ccp - Fix a resource leak in an error handling path
+    - media: rc: i2c: Fix an error message
+    - pata_ep93xx: fix deferred probing
+    - media: exynos4-is: Fix a use after free in isp_video_release
+    - media: au0828: fix a NULL vs IS_ERR() check
+    - media: tc358743: Fix error return code in tc358743_probe_of()
+    - media: gspca/gl860: fix zero-length control requests
+    - m68k: atari: Fix ATARI_KBD_CORE kconfig unmet dependency warning
+    - media: siano: Fix out-of-bounds warnings in smscore_load_firmware_family2()
+    - crypto: nitrox - fix unchecked variable in nitrox_register_interrupts
+    - crypto: omap-sham - Fix PM reference leak in omap sham ops
+    - mmc: usdhi6rol0: fix error return code in usdhi6_probe()
+    - arm64: consistently use reserved_pg_dir
+    - arm64/mm: Fix ttbr0 values stored in struct thread_info for software-pan
+    - media: s5p-g2d: Fix a memory leak on ctx->fh.m2m_ctx
+    - hwmon: (max31722) Remove non-standard ACPI device IDs
+    - hwmon: (max31790) Fix fan speed reporting for fan7..12
+    - KVM: nVMX: Ensure 64-bit shift when checking VMFUNC bitmap
+    - regulator: hi655x: Fix pass wrong pointer to config.driver_data
+    - btrfs: clear log tree recovering status if starting transaction fails
+    - sched/rt: Fix RT utilization tracking during policy change
+    - sched/rt: Fix Deadline utilization tracking during policy change
+    - sched/uclamp: Fix uclamp_tg_restrict()
+    - spi: spi-sun6i: Fix chipselect/clock bug
+    - crypto: nx - Fix RCU warning in nx842_OF_upd_status
+    - ACPI: sysfs: Fix a buffer overrun problem with description_show()
+    - extcon: extcon-max8997: Fix IRQ freeing at error path
+    - blk-wbt: introduce a new disable state to prevent false positive by
+      rwb_enabled()
+    - blk-wbt: make sure throttle is enabled properly
+    - ACPI: Use DEVICE_ATTR_<RW|RO|WO> macros
+    - ACPI: bgrt: Fix CFI violation
+    - cpufreq: Make cpufreq_online() call driver->offline() on errors
+    - ocfs2: fix snprintf() checking
+    - dax: fix ENOMEM handling in grab_mapping_entry()
+    - xfrm: xfrm_state_mtu should return at least 1280 for ipv6
+    - video: fbdev: imxfb: Fix an error message
+    - net: mvpp2: Put fwnode in error case during ->probe()
+    - net: pch_gbe: Propagate error from devm_gpio_request_one()
+    - pinctrl: renesas: r8a7796: Add missing bias for PRESET# pin
+    - pinctrl: renesas: r8a77990: JTAG pins do not have pull-down capabilities
+    - clk: meson: g12a: fix gp0 and hifi ranges
+    - net: ftgmac100: add missing error return code in ftgmac100_probe()
+    - drm/rockchip: cdn-dp-core: add missing clk_disable_unprepare() on error in
+      cdn_dp_grf_write()
+    - drm/rockchip: dsi: move all lane config except LCDC mux to bind()
+    - ehea: fix error return code in ehea_restart_qps()
+    - net/sched: act_vlan: Fix modify to allow 0
+    - RDMA/core: Sanitize WQ state received from the userspace
+    - RDMA/rxe: Fix failure during driver load
+    - drm: qxl: ensure surf.data is ininitialized
+    - tools/bpftool: Fix error return code in do_batch()
+    - ath10k: go to path err_unsupported when chip id is not supported
+    - ath10k: add missing error return code in ath10k_pci_probe()
+    - wireless: carl9170: fix LEDS build errors & warnings
+    - ieee802154: hwsim: Fix possible memory leak in hwsim_subscribe_all_others
+    - wcn36xx: Move hal_buf allocation to devm_kmalloc in probe
+    - ssb: Fix error return code in ssb_bus_scan()
+    - brcmfmac: fix setting of station info chains bitmask
+    - brcmfmac: correctly report average RSSI in station info
+    - brcmsmac: mac80211_if: Fix a resource leak in an error handling path
+    - ath10k: Fix an error code in ath10k_add_interface()
+    - netlabel: Fix memory leak in netlbl_mgmt_add_common
+    - RDMA/mlx5: Don't add slave port to unaffiliated list
+    - netfilter: nft_exthdr: check for IPv6 packet before further processing
+    - netfilter: nft_osf: check for TCP packet before further processing
+    - netfilter: nft_tproxy: restrict support to TCP and UDP transport protocols
+    - RDMA/rxe: Fix qp reference counting for atomic ops
+    - samples/bpf: Fix the error return code of xdp_redirect's main()
+    - net: ethernet: aeroflex: fix UAF in greth_of_remove
+    - net: ethernet: ezchip: fix UAF in nps_enet_remove
+    - net: ethernet: ezchip: fix error handling
+    - vrf: do not push non-ND strict packets with a source LLA through packet taps
+      again
+    - net: sched: add barrier to ensure correct ordering for lockless qdisc
+    - tls: prevent oversized sendfile() hangs by ignoring MSG_MORE
+    - pkt_sched: sch_qfq: fix qfq_change_class() error path
+    - vxlan: add missing rcu_read_lock() in neigh_reduce()
+    - net/ipv4: swap flow ports when validating source
+    - tc-testing: fix list handling
+    - ieee802154: hwsim: Fix memory leak in hwsim_add_one
+    - ieee802154: hwsim: avoid possible crash in hwsim_del_edge_nl()
+    - mac80211: remove iwlwifi specific workaround NDPs of null_response
+    - net: bcmgenet: Fix attaching to PYH failed on RPi 4B
+    - ipv6: exthdrs: do not blindly use init_net
+    - bpf: Do not change gso_size during bpf_skb_change_proto()
+    - i40e: Fix error handling in i40e_vsi_open
+    - i40e: Fix autoneg disabling for non-10GBaseT links
+    - Revert "ibmvnic: remove duplicate napi_schedule call in open function"
+    - ibmvnic: free tx_pool if tso_pool alloc fails
+    - ipv6: fix out-of-bound access in ip6_parse_tlv()
+    - e1000e: Check the PCIm state
+    - bpfilter: Specify the log level for the kmsg message
+    - gve: Fix swapped vars when fetching max queues
+    - Revert "be2net: disable bh with spin_lock in be_process_mcc"
+    - Bluetooth: mgmt: Fix slab-out-of-bounds in tlv_data_is_valid
+    - Bluetooth: Fix handling of HCI_LE_Advertising_Set_Terminated event
+    - clk: actions: Fix UART clock dividers on Owl S500 SoC
+    - clk: actions: Fix SD clocks factor table on Owl S500 SoC
+    - clk: actions: Fix bisp_factor_table based clocks on Owl S500 SoC
+    - clk: si5341: Avoid divide errors due to bogus register contents
+    - clk: si5341: Update initialization magic
+    - writeback: fix obtain a reference to a freeing memcg css
+    - net: lwtunnel: handle MTU calculation in forwading
+    - net: sched: fix warning in tcindex_alloc_perfect_hash
+    - RDMA/mlx5: Don't access NULL-cleared mpi pointer
+    - MIPS: Fix PKMAP with 32-bit MIPS huge page support
+    - staging: fbtft: Rectify GPIO handling
+    - rcu: Invoke rcu_spawn_core_kthreads() from rcu_spawn_gp_kthread()
+    - tty: nozomi: Fix a resource leak in an error handling function
+    - mwifiex: re-fix for unaligned accesses
+    - iio: adis_buffer: do not return ints in irq handlers
+    - iio: adis16400: do not return ints in irq handlers
+    - iio: accel: bma180: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: accel: bma220: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: accel: hid: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: accel: kxcjk-1013: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio:accel:mxc4005: Drop unnecessary explicit casts in regmap_bulk_read calls
+    - iio: accel: mxc4005: Fix overread of data and alignment issue.
+    - iio: accel: stk8312: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: accel: stk8ba50: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: adc: ti-ads1015: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: adc: vf610: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: gyro: bmg160: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: humidity: am2315: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: prox: srf08: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: prox: pulsed-light: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: prox: as3935: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: magn: hmc5843: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: magn: bmc150: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: light: isl29125: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: light: tcs3414: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: light: tcs3472: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: cros_ec_sensors: Fix alignment of buffer in
+      iio_push_to_buffers_with_timestamp()
+    - iio: potentiostat: lmp91000: Fix alignment of buffer in
+      iio_push_to_buffers_with_timestamp()
+    - ASoC: rk3328: fix missing clk_disable_unprepare() on error in
+      rk3328_platform_probe()
+    - ASoC: hisilicon: fix missing clk_disable_unprepare() on error in
+      hi6210_i2s_startup()
+    - backlight: lm3630a_bl: Put fwnode in error case during ->probe()
+    - ASoC: rsnd: tidyup loop on rsnd_adg_clk_query()
+    - Input: hil_kbd - fix error return code in hil_dev_connect()
+    - mtd: partitions: redboot: seek fis-index-block in the right node
+    - char: pcmcia: error out if 'num_bytes_read' is greater than 4 in
+      set_protocol()
+    - firmware: stratix10-svc: Fix a resource leak in an error handling path
+    - tty: nozomi: Fix the error handling path of 'nozomi_card_init()'
+    - leds: lm3532: select regmap I2C API
+    - leds: lm36274: cosmetic: rename lm36274_data to chip
+    - leds: lm3692x: Put fwnode in any case during ->probe()
+    - scsi: FlashPoint: Rename si_flags field
+    - fsi: core: Fix return of error values on failures
+    - fsi: scom: Reset the FSI2PIB engine for any error
+    - fsi: occ: Don't accept response from un-initialized OCC
+    - fsi/sbefifo: Clean up correct FIFO when receiving reset request from SBE
+    - fsi/sbefifo: Fix reset timeout
+    - visorbus: fix error return code in visorchipset_init()
+    - s390: appldata depends on PROC_SYSCTL
+    - iommu/dma: Fix IOVA reserve dma ranges
+    - ASoC: mediatek: mtk-btcvsd: Fix an error handling path in
+      'mtk_btcvsd_snd_probe()'
+    - usb: gadget: f_fs: Fix setting of device and driver data cross-references
+    - usb: dwc2: Don't reset the core after setting turnaround time
+    - eeprom: idt_89hpesx: Put fwnode in matching case during ->probe()
+    - eeprom: idt_89hpesx: Restore printing the unsupported fwnode name
+    - iio: at91-sama5d2_adc: remove usage of iio_priv_to_dev() helper
+    - iio: adc: at91-sama5d2: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: adc: hx711: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: adc: mxs-lradc: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: adc: ti-ads8688: Fix alignment of buffer in
+      iio_push_to_buffers_with_timestamp()
+    - iio: magn: rm3100: Fix alignment of buffer in
+      iio_push_to_buffers_with_timestamp()
+    - staging: gdm724x: check for buffer overflow in gdm_lte_multi_sdu_pkt()
+    - staging: gdm724x: check for overflow in gdm_lte_netif_rx()
+    - staging: rtl8712: remove redundant check in r871xu_drv_init
+    - staging: rtl8712: fix memory leak in rtl871x_load_fw_cb
+    - staging: mt7621-dts: fix pci address for PCI memory range
+    - serial: 8250: Actually allow UPF_MAGIC_MULTIPLIER baud rates
+    - iio: light: vcnl4035: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: prox: isl29501: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - ASoC: cs42l42: Correct definition of CS42L42_ADC_PDN_MASK
+    - of: Fix truncation of memory sizes on 32-bit platforms
+    - mtd: rawnand: marvell: add missing clk_disable_unprepare() on error in
+      marvell_nfc_resume()
+    - scsi: mpt3sas: Fix error return value in _scsih_expander_add()
+    - soundwire: stream: Fix test for DP prepare complete
+    - phy: uniphier-pcie: Fix updating phy parameters
+    - phy: ti: dm816x: Fix the error handling path in 'dm816x_usb_phy_probe()
+    - extcon: sm5502: Drop invalid register write in sm5502_reg_data
+    - extcon: max8997: Add missing modalias string
+    - ASoC: atmel-i2s: Fix usage of capture and playback at the same time
+    - configfs: fix memleak in configfs_release_bin_file
+    - leds: as3645a: Fix error return code in as3645a_parse_node()
+    - leds: ktd2692: Fix an error handling path
+    - powerpc: Offline CPU in stop_this_cpu()
+    - serial: mvebu-uart: do not allow changing baudrate when uartclk is not
+      available
+    - serial: mvebu-uart: correctly calculate minimal possible baudrate
+    - arm64: dts: marvell: armada-37xx: Fix reg for standard variant of UART
+    - vfio/pci: Handle concurrent vma faults
+    - mm/huge_memory.c: don't discard hugepage if other processes are mapping it
+    - mm/z3fold: fix potential memory leak in z3fold_destroy_pool()
+    - selftests/vm/pkeys: fix alloc_random_pkey() to make it really, really random
+    - perf llvm: Return -ENOMEM when asprintf() fails
+    - scsi: target: cxgbit: Unmap DMA buffer before calling target_execute_cmd()
+    - mmc: block: Disable CMDQ on the ioctl path
+    - mmc: vub3000: fix control-request direction
+    - scsi: core: Retry I/O for Notify (Enable Spinup) Required error
+    - iommu/dma: Fix compile warning in 32-bit builds
+    - Linux 5.4.132
+
+  * Keyboard not working (LP: #1909814) // Focal update: v5.4.132 upstream
+    stable release (LP: #1938199)
+    - ACPI: resources: Add checks for ACPI IRQ override
+
+  * Focal update: v5.4.131 upstream stable release (LP: #1936245)
+    - KVM: SVM: Periodically schedule when unregistering regions on destroy
+    - s390/stack: fix possible register corruption with stack switch helper
+    - KVM: SVM: Call SEV Guest Decommission if ASID binding fails
+    - xen/events: reset active flag for lateeoi events later
+    - Linux 5.4.131
+
+  * Focal update: v5.4.130 upstream stable release (LP: #1936244)
+    - scsi: sr: Return appropriate error code when disk is ejected
+    - drm/nouveau: fix dma_address check for CPU/GPU sync
+    - gpio: AMD8111 and TQMX86 require HAS_IOPORT_MAP
+    - RDMA/mlx5: Block FDB rules when not in switchdev mode
+    - Linux 5.4.130
+
+  * Focal update: v5.4.129 upstream stable release (LP: #1936242)
+    - module: limit enabling module.sig_enforce
+    - drm/nouveau: wait for moving fence after pinning v2
+    - drm/radeon: wait for moving fence after pinning
+    - ARM: 9081/1: fix gcc-10 thumb2-kernel regression
+    - mmc: meson-gx: use memcpy_to/fromio for dram-access-quirk
+    - kbuild: add CONFIG_LD_IS_LLD
+    - arm64: link with -z norelro for LLD or aarch64-elf
+    - MIPS: generic: Update node names to avoid unit addresses
+    - spi: spi-nxp-fspi: move the register operation after the clock enable
+    - Revert "PCI: PM: Do not read power state in pci_enable_device_flags()"
+    - dmaengine: zynqmp_dma: Fix PM reference leak in
+      zynqmp_dma_alloc_chan_resourc()
+    - mac80211: remove warning in ieee80211_get_sband()
+    - mac80211_hwsim: drop pending frames on stop
+    - cfg80211: call cfg80211_leave_ocb when switching away from OCB
+    - dmaengine: rcar-dmac: Fix PM reference leak in rcar_dmac_probe()
+    - dmaengine: mediatek: free the proper desc in desc_free handler
+    - dmaengine: mediatek: do not issue a new desc if one is still current
+    - dmaengine: mediatek: use GFP_NOWAIT instead of GFP_ATOMIC in prep_dma
+    - net: ipv4: Remove unneed BUG() function
+    - mac80211: drop multicast fragments
+    - net: ethtool: clear heap allocations for ethtool function
+    - ping: Check return value of function 'ping_queue_rcv_skb'
+    - inet: annotate date races around sk->sk_txhash
+    - net: phy: dp83867: perform soft reset and retain established link
+    - net: caif: fix memory leak in ldisc_open
+    - net/packet: annotate accesses to po->bind
+    - net/packet: annotate accesses to po->ifindex
+    - r8152: Avoid memcpy() over-reading of ETH_SS_STATS
+    - sh_eth: Avoid memcpy() over-reading of ETH_SS_STATS
+    - r8169: Avoid memcpy() over-reading of ETH_SS_STATS
+    - KVM: selftests: Fix kvm_check_cap() assertion
+    - net: qed: Fix memcpy() overflow of qed_dcbx_params()
+    - recordmcount: Correct st_shndx handling
+    - PCI: Add AMD RS690 quirk to enable 64-bit DMA
+    - net: ll_temac: Add memory-barriers for TX BD access
+    - net: ll_temac: Avoid ndo_start_xmit returning NETDEV_TX_BUSY
+    - pinctrl: stm32: fix the reported number of GPIO lines per bank
+    - nilfs2: fix memory leak in nilfs_sysfs_delete_device_group
+    - KVM: do not allow mapping valid but non-reference-counted pages
+    - i2c: robotfuzz-osif: fix control-request directions
+    - kthread_worker: split code for canceling the delayed work timer
+    - kthread: prevent deadlock when kthread_mod_delayed_work() races with
+      kthread_cancel_delayed_work_sync()
+    - mm: add VM_WARN_ON_ONCE_PAGE() macro
+    - mm/rmap: remove unneeded semicolon in page_not_mapped()
+    - mm/rmap: use page_not_mapped in try_to_unmap()
+    - mm, thp: use head page in __migration_entry_wait()
+    - mm/thp: fix __split_huge_pmd_locked() on shmem migration entry
+    - mm/thp: make is_huge_zero_pmd() safe and quicker
+    - mm/thp: try_to_unmap() use TTU_SYNC for safe splitting
+    - mm/thp: fix vma_address() if virtual address below file offset
+    - mm/thp: fix page_address_in_vma() on file THP tails
+    - mm/thp: unmap_mapping_page() to fix THP truncate_cleanup_page()
+    - mm: thp: replace DEBUG_VM BUG with VM_WARN when unmap fails for split
+    - mm: page_vma_mapped_walk(): use page for pvmw->page
+    - mm: page_vma_mapped_walk(): settle PageHuge on entry
+    - mm: page_vma_mapped_walk(): use pmde for *pvmw->pmd
+    - mm: page_vma_mapped_walk(): prettify PVMW_MIGRATION block
+    - mm: page_vma_mapped_walk(): crossing page table boundary
+    - mm: page_vma_mapped_walk(): add a level of indentation
+    - mm: page_vma_mapped_walk(): use goto instead of while (1)
+    - mm: page_vma_mapped_walk(): get vma_address_end() earlier
+    - mm/thp: fix page_vma_mapped_walk() if THP mapped by ptes
+    - mm/thp: another PVMW_SYNC fix in page_vma_mapped_walk()
+    - mm, futex: fix shared futex pgoff on shmem huge page
+    - [Config] enable CONFIG_SYSTEM_REVOCATION_LIST
+    - certs: Add EFI_CERT_X509_GUID support for dbx entries
+    - certs: Move load_system_certificate_list to a common function
+    - Linux 5.4.129
+
+  * Patch To Fix Bug in the Linux Block Layer Responsible For  Merging BIOs
+    (LP: #1931497)
+    - block: return the correct bvec when checking for gaps
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Fri, 13 Aug 2021 11:58:48 +0200
+
+linux (5.4.0-81.91) focal; urgency=medium
+
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+
+  * large_dir in ext4 broken (LP: #1933074)
+    - SAUCE: ext4: fix directory index node split corruption
+
+  * Some test in kselftest/net on focal source tree were not tested at all
+    (LP: #1934282)
+    - selftests/net: add missing tests to Makefile
+
+  * curtin: install flash-kernel in arm64 UEFI unexpected (LP: #1918427)
+    - [Packaging] Allow grub-efi-arm* to satisfy recommends on ARM
+
+  * Add l2tp.sh in net from ubuntu_kernel_selftests back (LP: #1934293)
+    - Revert "UBUNTU: SAUCE: selftests/net -- disable l2tp.sh test"
+
+  * icmp_redirect.sh in net from ubuntu_kernel_selftests failed on F-OEM-5.6 /
+    F-OEM-5.10 / F-OEM-5.13 / F / G / H (LP: #1880645)
+    - selftests: icmp_redirect: support expected failures
+
+  * Focal update: v5.4.128 upstream stable release (LP: #1934179)
+    - dmaengine: ALTERA_MSGDMA depends on HAS_IOMEM
+    - dmaengine: QCOM_HIDMA_MGMT depends on HAS_IOMEM
+    - dmaengine: stedma40: add missing iounmap() on error in d40_probe()
+    - afs: Fix an IS_ERR() vs NULL check
+    - mm/memory-failure: make sure wait for page writeback in memory_failure
+    - kvm: LAPIC: Restore guard to prevent illegal APIC register access
+    - batman-adv: Avoid WARN_ON timing related checks
+    - net: ipv4: fix memory leak in netlbl_cipsov4_add_std
+    - vrf: fix maximum MTU
+    - net: rds: fix memory leak in rds_recvmsg
+    - net: lantiq: disable interrupt before sheduling NAPI
+    - udp: fix race between close() and udp_abort()
+    - rtnetlink: Fix regression in bridge VLAN configuration
+    - net/sched: act_ct: handle DNAT tuple collision
+    - net/mlx5e: Remove dependency in IPsec initialization flows
+    - net/mlx5e: Fix page reclaim for dead peer hairpin
+    - net/mlx5: Consider RoCE cap before init RDMA resources
+    - net/mlx5e: allow TSO on VXLAN over VLAN topologies
+    - net/mlx5e: Block offload of outer header csum for UDP tunnels
+    - netfilter: synproxy: Fix out of bounds when parsing TCP options
+    - sch_cake: Fix out of bounds when parsing TCP options and header
+    - alx: Fix an error handling path in 'alx_probe()'
+    - net: stmmac: dwmac1000: Fix extended MAC address registers definition
+    - net: make get_net_ns return error if NET_NS is disabled
+    - qlcnic: Fix an error handling path in 'qlcnic_probe()'
+    - netxen_nic: Fix an error handling path in 'netxen_nic_probe()'
+    - net: qrtr: fix OOB Read in qrtr_endpoint_post
+    - ptp: improve max_adj check against unreasonable values
+    - net: cdc_ncm: switch to eth%d interface naming
+    - lantiq: net: fix duplicated skb in rx descriptor ring
+    - net: usb: fix possible use-after-free in smsc75xx_bind
+    - net: fec_ptp: fix issue caused by refactor the fec_devtype
+    - net: ipv4: fix memory leak in ip_mc_add1_src
+    - net/af_unix: fix a data-race in unix_dgram_sendmsg / unix_release_sock
+    - be2net: Fix an error handling path in 'be_probe()'
+    - net: hamradio: fix memory leak in mkiss_close
+    - net: cdc_eem: fix tx fixup skb leak
+    - cxgb4: fix wrong shift.
+    - bnxt_en: Rediscover PHY capabilities after firmware reset
+    - bnxt_en: Call bnxt_ethtool_free() in bnxt_init_one() error path
+    - icmp: don't send out ICMP messages with a source address of 0.0.0.0
+    - net: ethernet: fix potential use-after-free in ec_bhf_remove
+    - regulator: bd70528: Fix off-by-one for buck123 .n_voltages setting
+    - ASoC: rt5659: Fix the lost powers for the HDA header
+    - spi: stm32-qspi: Always wait BUSY bit to be cleared in stm32_qspi_wait_cmd()
+    - pinctrl: ralink: rt2880: avoid to error in calls is pin is already enabled
+    - radeon: use memcpy_to/fromio for UVD fw upload
+    - hwmon: (scpi-hwmon) shows the negative temperature properly
+    - can: bcm: fix infoleak in struct bcm_msg_head
+    - can: bcm/raw/isotp: use per module netdevice notifier
+    - can: j1939: fix Use-after-Free, hold skb ref while in use
+    - can: mcba_usb: fix memory leak in mcba_usb
+    - usb: core: hub: Disable autosuspend for Cypress CY7C65632
+    - tracing: Do not stop recording cmdlines when tracing is off
+    - tracing: Do not stop recording comms if the trace file is being read
+    - tracing: Do no increment trace_clock_global() by one
+    - PCI: Mark TI C667X to avoid bus reset
+    - PCI: Mark some NVIDIA GPUs to avoid bus reset
+    - PCI: aardvark: Don't rely on jiffies while holding spinlock
+    - PCI: aardvark: Fix kernel panic during PIO transfer
+    - PCI: Add ACS quirk for Broadcom BCM57414 NIC
+    - PCI: Work around Huawei Intelligent NIC VF FLR erratum
+    - KVM: x86: Immediately reset the MMU context when the SMM flag is cleared
+    - ARCv2: save ABI registers across signal handling
+    - x86/process: Check PF_KTHREAD and not current->mm for kernel threads
+    - x86/pkru: Write hardware init value to PKRU when xstate is init
+    - x86/fpu: Reset state for all signal restore failures
+    - dmaengine: pl330: fix wrong usage of spinlock flags in dma_cyclc
+    - cfg80211: make certificate generation more robust
+    - cfg80211: avoid double free of PMSR request
+    - net: ll_temac: Make sure to free skb when it is completely used
+    - net: ll_temac: Fix TX BD buffer overwrite
+    - net: bridge: fix vlan tunnel dst null pointer dereference
+    - net: bridge: fix vlan tunnel dst refcnt when egressing
+    - mm/slub: clarify verification reporting
+    - mm/slub: fix redzoning for small allocations
+    - mm/slub.c: include swab.h
+    - net: stmmac: disable clocks in stmmac_remove_config_dt()
+    - net: fec_ptp: add clock rate zero check
+    - tools headers UAPI: Sync linux/in.h copy with the kernel sources
+    - KVM: arm/arm64: Fix KVM_VGIC_V3_ADDR_TYPE_REDIST read
+    - ARM: OMAP: replace setup_irq() by request_irq()
+    - clocksource/drivers/timer-ti-dm: Add clockevent and clocksource support
+    - clocksource/drivers/timer-ti-dm: Prepare to handle dra7 timer wrap issue
+    - clocksource/drivers/timer-ti-dm: Handle dra7 timer wrap errata i940
+    - usb: dwc3: debugfs: Add and remove endpoint dirs dynamically
+    - usb: dwc3: core: fix kernel panic when do reboot
+    - Linux 5.4.128
+
+  * linux-azure CIFS DFS oops (LP: #1935833)
+    - cifs: get rid of unused parameter in reconn_setup_dfs_targets()
+    - cifs: handle empty list of targets in cifs_reconnect()
+
+  * pmtu.sh from net in ubuntu_kernel_selftests failed with no error message
+    (LP: #1887661)
+    - selftests: pmtu.sh: improve the test result processing
+
+  * cifs: On cifs_reconnect, resolve the hostname again (LP: #1929831)
+    - cifs: rename reconn_inval_dfs_target()
+    - cifs: Simplify reconnect code when dfs upcall is enabled
+    - cifs: Avoid error pointer dereference
+    - cifs: On cifs_reconnect, resolve the hostname again.
+
+  * Pixel format change broken for Elgato Cam Link 4K (LP: #1932367)
+    - (upstream) media: uvcvideo: Fix pixel format change for Elgato Cam Link 4K
+
+  * Focal update: v5.4.127 upstream stable release (LP: #1933851)
+    - net: ieee802154: fix null deref in parse dev addr
+    - HID: quirks: Set INCREMENT_USAGE_ON_DUPLICATE for Saitek X65
+    - HID: hid-input: add mapping for emoji picker key
+    - HID: hid-sensor-hub: Return error for hid_set_field() failure
+    - HID: quirks: Add quirk for Lenovo optical mouse
+    - HID: multitouch: set Stylus suffix for Stylus-application devices, too
+    - HID: Add BUS_VIRTUAL to hid_connect logging
+    - HID: usbhid: fix info leak in hid_submit_ctrl
+    - drm/tegra: sor: Do not leak runtime PM reference
+    - ARM: OMAP2+: Fix build warning when mmc_omap is not built
+    - gfs2: Prevent direct-I/O write fallback errors from getting lost
+    - HID: gt683r: add missing MODULE_DEVICE_TABLE
+    - riscv: Use -mno-relax when using lld linker
+    - gfs2: Fix use-after-free in gfs2_glock_shrink_scan
+    - scsi: target: core: Fix warning on realtime kernels
+    - ethernet: myri10ge: Fix missing error code in myri10ge_probe()
+    - scsi: qedf: Do not put host in qedf_vport_create() unconditionally
+    - scsi: scsi_devinfo: Add blacklist entry for HPE OPEN-V
+    - nvme-loop: reset queue count to 1 in nvme_loop_destroy_io_queues()
+    - nvme-loop: clear NVME_LOOP_Q_LIVE when nvme_loop_configure_admin_queue()
+      fails
+    - nvme-loop: check for NVME_LOOP_Q_LIVE in nvme_loop_destroy_admin_queue()
+    - net: ipconfig: Don't override command-line hostnames or domains
+    - drm/amd/display: Allow bandwidth validation for 0 streams.
+    - rtnetlink: Fix missing error code in rtnl_bridge_notify()
+    - net/x25: Return the correct errno code
+    - net: Return the correct errno code
+    - fib: Return the correct errno code
+    - Linux 5.4.127
+
+  * Focal update: v5.4.126 upstream stable release (LP: #1933369)
+    - proc: Check /proc/$pid/attr/ writes against file opener
+    - proc: Track /proc/$pid/attr/ opener mm_struct
+    - ASoC: max98088: fix ni clock divider calculation
+    - spi: Fix spi device unregister flow
+    - net/nfc/rawsock.c: fix a permission check bug
+    - usb: cdns3: Fix runtime PM imbalance on error
+    - ASoC: Intel: bytcr_rt5640: Add quirk for the Glavey TM800A550L tablet
+    - ASoC: Intel: bytcr_rt5640: Add quirk for the Lenovo Miix 3-830 tablet
+    - vfio-ccw: Serialize FSM IDLE state with I/O completion
+    - ASoC: sti-sas: add missing MODULE_DEVICE_TABLE
+    - spi: sprd: Add missing MODULE_DEVICE_TABLE
+    - isdn: mISDN: netjet: Fix crash in nj_probe:
+    - bonding: init notify_work earlier to avoid uninitialized use
+    - netlink: disable IRQs for netlink_lock_table()
+    - net: mdiobus: get rid of a BUG_ON()
+    - cgroup: disable controllers at parse time
+    - wq: handle VM suspension in stall detection
+    - net/qla3xxx: fix schedule while atomic in ql_sem_spinlock
+    - RDS tcp loopback connection can hang
+    - scsi: bnx2fc: Return failure if io_req is already in ABTS processing
+    - scsi: vmw_pvscsi: Set correct residual data length
+    - scsi: hisi_sas: Drop free_irq() of devm_request_irq() allocated irq
+    - scsi: target: qla2xxx: Wait for stop_phase1 at WWN removal
+    - net: macb: ensure the device is available before accessing GEMGXL control
+      registers
+    - net: appletalk: cops: Fix data race in cops_probe1
+    - net: dsa: microchip: enable phy errata workaround on 9567
+    - nvme-fabrics: decode host pathing error for connect
+    - MIPS: Fix kernel hang under FUNCTION_GRAPH_TRACER and PREEMPT_TRACER
+    - dm verity: fix require_signatures module_param permissions
+    - bnx2x: Fix missing error code in bnx2x_iov_init_one()
+    - nvme-tcp: remove incorrect Kconfig dep in BLK_DEV_NVME
+    - powerpc/fsl: set fsl,i2c-erratum-a004447 flag for P2041 i2c controllers
+    - powerpc/fsl: set fsl,i2c-erratum-a004447 flag for P1010 i2c controllers
+    - spi: Don't have controller clean up spi device before driver unbind
+    - spi: Cleanup on failure of initial setup
+    - i2c: mpc: Make use of i2c_recover_bus()
+    - i2c: mpc: implement erratum A-004447 workaround
+    - x86/boot: Add .text.* to setup.ld
+    - spi: bcm2835: Fix out-of-bounds access with more than 4 slaves
+    - drm: Fix use-after-free read in drm_getunique()
+    - drm: Lock pointer access in drm_master_release()
+    - kvm: avoid speculation-based attacks from out-of-range memslot accesses
+    - staging: rtl8723bs: Fix uninitialized variables
+    - btrfs: return value from btrfs_mark_extent_written() in case of error
+    - btrfs: promote debugging asserts to full-fledged checks in validate_super
+    - cgroup1: don't allow '\n' in renaming
+    - USB: f_ncm: ncm_bitrate (speed) is unsigned
+    - usb: f_ncm: only first packet of aggregate needs to start timer
+    - usb: pd: Set PD_T_SINK_WAIT_CAP to 310ms
+    - usb: dwc3: ep0: fix NULL pointer exception
+    - usb: musb: fix MUSB_QUIRK_B_DISCONNECT_99 handling
+    - usb: typec: wcove: Use LE to CPU conversion when accessing msg->header
+    - usb: typec: ucsi: Clear PPM capability data in ucsi_init() error path
+    - usb: gadget: f_fs: Ensure io_completion_wq is idle during unbind
+    - USB: serial: ftdi_sio: add NovaTech OrionMX product ID
+    - USB: serial: omninet: add device id for Zyxel Omni 56K Plus
+    - USB: serial: quatech2: fix control-request directions
+    - USB: serial: cp210x: fix alternate function for CP2102N QFN20
+    - usb: gadget: eem: fix wrong eem header operation
+    - usb: fix various gadgets null ptr deref on 10gbps cabling.
+    - usb: fix various gadget panics on 10gbps cabling
+    - regulator: core: resolve supply for boot-on/always-on regulators
+    - regulator: max77620: Use device_set_of_node_from_dev()
+    - usb: typec: mux: Fix copy-paste mistake in typec_mux_match
+    - RDMA/ipoib: Fix warning caused by destroying non-initial netns
+    - RDMA/mlx4: Do not map the core_clock page to user space unless enabled
+    - vmlinux.lds.h: Avoid orphan section with !SMP
+    - perf: Fix data race between pin_count increment/decrement
+    - sched/fair: Make sure to update tg contrib for blocked load
+    - KVM: x86: Ensure liveliness of nested VM-Enter fail tracepoint message
+    - IB/mlx5: Fix initializing CQ fragments buffer
+    - NFS: Fix a potential NULL dereference in nfs_get_client()
+    - NFSv4: Fix deadlock between nfs4_evict_inode() and nfs4_opendata_get_inode()
+    - perf session: Correct buffer copying when peeking events
+    - kvm: fix previous commit for 32-bit builds
+    - NFS: Fix use-after-free in nfs4_init_client()
+    - NFSv4: Fix second deadlock in nfs4_evict_inode()
+    - NFSv4: nfs4_proc_set_acl needs to restore NFS_CAP_UIDGID_NOMAP on error.
+    - scsi: core: Fix error handling of scsi_host_alloc()
+    - scsi: core: Fix failure handling of scsi_add_host_with_dma()
+    - scsi: core: Put .shost_dev in failure path if host state changes to RUNNING
+    - scsi: core: Only put parent device if host state differs from SHOST_CREATED
+    - ftrace: Do not blindly read the ip address in ftrace_bug()
+    - tracing: Correct the length check which causes memory corruption
+    - proc: only require mm_struct for writing
+    - Linux 5.4.126
+
+  * Focal update: v5.4.125 upstream stable release (LP: #1932957)
+    - btrfs: tree-checker: do not error out if extent ref hash doesn't match
+    - net: usb: cdc_ncm: don't spew notifications
+    - ALSA: usb: update old-style static const declaration
+    - nl80211: validate key indexes for cfg80211_registered_device
+    - hwmon: (dell-smm-hwmon) Fix index values
+    - netfilter: conntrack: unregister ipv4 sockopts on error unwind
+    - efi: Allow EFI_MEMORY_XP and EFI_MEMORY_RO both to be cleared
+    - efi: cper: fix snprintf() use in cper_dimm_err_location()
+    - vfio/pci: Fix error return code in vfio_ecap_init()
+    - vfio/pci: zap_vma_ptes() needs MMU
+    - samples: vfio-mdev: fix error handing in mdpy_fb_probe()
+    - vfio/platform: fix module_put call in error flow
+    - ipvs: ignore IP_VS_SVC_F_HASHED flag when adding service
+    - HID: pidff: fix error return code in hid_pidff_init()
+    - HID: i2c-hid: fix format string mismatch
+    - net/sched: act_ct: Fix ct template allocation for zone 0
+    - ACPICA: Clean up context mutex during object deletion
+    - netfilter: nft_ct: skip expectations for confirmed conntrack
+    - netfilter: nfnetlink_cthelper: hit EBUSY on updates if size mismatches
+    - ieee802154: fix error return code in ieee802154_add_iface()
+    - ieee802154: fix error return code in ieee802154_llsec_getparams()
+    - ixgbevf: add correct exception tracing for XDP
+    - ipv6: Fix KASAN: slab-out-of-bounds Read in fib6_nh_flush_exceptions
+    - ice: write register with correct offset
+    - ice: Fix VFR issues for AVF drivers that expect ATQLEN cleared
+    - ice: Allow all LLDP packets from PF to Tx
+    - i2c: qcom-geni: Add shutdown callback for i2c
+    - i40e: optimize for XDP_REDIRECT in xsk path
+    - i40e: add correct exception tracing for XDP
+    - arm64: dts: ls1028a: fix memory node
+    - arm64: dts: zii-ultra: fix 12V_MAIN voltage
+    - ARM: dts: imx7d-meerkat96: Fix the 'tuning-step' property
+    - ARM: dts: imx7d-pico: Fix the 'tuning-step' property
+    - ARM: dts: imx: emcon-avari: Fix nxp,pca8574 #gpio-cells
+    - bus: ti-sysc: Fix flakey idling of uarts and stop using swsup_sidle_act
+    - tipc: add extack messages for bearer/media failure
+    - tipc: fix unique bearer names sanity check
+    - Bluetooth: fix the erroneous flush_work() order
+    - Bluetooth: use correct lock to prevent UAF of hdev object
+    - net: caif: added cfserl_release function
+    - net: caif: add proper error handling
+    - net: caif: fix memory leak in caif_device_notify
+    - net: caif: fix memory leak in cfusbl_device_notify
+    - HID: i2c-hid: Skip ELAN power-on command after reset
+    - HID: magicmouse: fix NULL-deref on disconnect
+    - HID: multitouch: require Finger field to mark Win8 reports as MT
+    - ALSA: timer: Fix master timer notification
+    - ALSA: hda: Fix for mute key LED for HP Pavilion 15-CK0xx
+    - ARM: dts: imx6dl-yapp4: Fix RGMII connection to QCA8334 switch
+    - ARM: dts: imx6q-dhcom: Add PU,VDD1P1,VDD2P5 regulators
+    - ext4: fix bug on in ext4_es_cache_extent as ext4_split_extent_at failed
+    - usb: dwc2: Fix build in periphal-only mode
+    - pid: take a reference when initializing `cad_pid`
+    - ocfs2: fix data corruption by fallocate
+    - nfc: fix NULL ptr dereference in llcp_sock_getname() after failed connect
+    - drm/amdgpu: Don't query CE and UE errors
+    - drm/amdgpu: make sure we unpin the UVD BO
+    - x86/apic: Mark _all_ legacy interrupts when IO/APIC is missing
+    - btrfs: mark ordered extent and inode with error if we fail to finish
+    - btrfs: fix error handling in btrfs_del_csums
+    - btrfs: return errors from btrfs_del_csums in cleanup_ref_head
+    - btrfs: fixup error handling in fixup_inode_link_counts
+    - mm, hugetlb: fix simple resv_huge_pages underflow on UFFDIO_COPY
+    - bnxt_en: Remove the setting of dev_port.
+    - mm: add thp_order
+    - XArray: add xa_get_order
+    - XArray: add xas_split
+    - mm/filemap: fix storing to a THP shadow entry
+    - btrfs: fix unmountable seed device after fstrim
+    - KVM: SVM: Truncate GPR value for DR and CR accesses in !64-bit mode
+    - KVM: arm64: Fix debug register indexing
+    - lib/lz4: explicitly support in-place decompression
+    - xen-pciback: redo VF placement in the virtual topology
+    - i2c: qcom-geni: Suspend and resume the bus during SYSTEM_SLEEP_PM ops
+    - neighbour: allow NUD_NOARP entries to be forced GCed
+    - Linux 5.4.125
+
+ -- Kleber Sacilotto de Souza <kleber.souza@canonical.com>  Thu, 15 Jul 2021 20:01:02 +0200
+
+linux (5.4.0-80.90) focal; urgency=medium
+
+  * CVE-2021-33909
+    - SAUCE: seq_file: Disallow extremely large seq buffer allocations
+
+ -- Thadeu Lima de Souza Cascardo <cascardo@canonical.com>  Fri, 09 Jul 2021 12:49:11 -0300
+
+linux (5.4.0-79.88) focal; urgency=medium
+
+  * focal/linux: 5.4.0-79.88 -proposed tracker (LP: #1934343)
+
+  * lxd exec fails (LP: #1934187)
+    - SAUCE: Revert "proc: Check /proc/$pid/attr/ writes against file opener"
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Fri, 02 Jul 2021 10:27:49 +0200
+
+linux (5.4.0-78.87) focal; urgency=medium
+
+  * focal/linux: 5.4.0-78.87 -proposed tracker (LP: #1932478)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync getabis
+    - [Packaging] update helper scripts
+    - update dkms package versions
+
+  * Disable hv-kvp-daemon.service on certain instance types (LP: #1932081)
+    - [Packaging]: Add kernel command line condition to hv-kvp-daemon service
+
+  * QLogic Direct-Connect host can't discover SCSI-FC or NVMe/FC devices
+    (LP: #1860724)
+    - scsi: qla2xxx: Serialize fc_port alloc in N2N
+    - scsi: qla2xxx: Set Nport ID for N2N
+    - scsi: qla2xxx: Fix point-to-point (N2N) device discovery issue
+    - scsi: qla2xxx: Fix N2N and NVMe connect retry failure
+
+  * [SRU] Add support for E810 NIC to Ice Driver in Focal (LP: #1912511)
+    - ice: add additional E810 device id
+
+  * Focal update: v5.4.124 upstream stable release (LP: #1931166)
+    - ALSA: hda/realtek: Headphone volume is controlled by Front mixer
+    - ALSA: usb-audio: scarlett2: Fix device hang with ehci-pci
+    - ALSA: usb-audio: scarlett2: Improve driver startup messages
+    - cifs: set server->cipher_type to AES-128-CCM for SMB3.0
+    - NFSv4: Fix a NULL pointer dereference in pnfs_mark_matching_lsegs_return()
+    - iommu/vt-d: Fix sysfs leak in alloc_iommu()
+    - perf intel-pt: Fix sample instruction bytes
+    - perf intel-pt: Fix transaction abort handling
+    - perf scripts python: exported-sql-viewer.py: Fix copy to clipboard from Top
+      Calls by elapsed Time report
+    - perf scripts python: exported-sql-viewer.py: Fix Array TypeError
+    - perf scripts python: exported-sql-viewer.py: Fix warning display
+    - proc: Check /proc/$pid/attr/ writes against file opener
+    - net: hso: fix control-request directions
+    - ath10k: Validate first subframe of A-MSDU before processing the list
+    - dm snapshot: properly fix a crash when an origin has no snapshots
+    - drm/amdgpu/vcn1: add cancel_delayed_work_sync before power gate
+    - drm/amdgpu/vcn2.0: add cancel_delayed_work_sync before power gate
+    - drm/amdgpu/vcn2.5: add cancel_delayed_work_sync before power gate
+    - selftests/gpio: Use TEST_GEN_PROGS_EXTENDED
+    - selftests/gpio: Move include of lib.mk up
+    - selftests/gpio: Fix build when source tree is read only
+    - kgdb: fix gcc-11 warnings harder
+    - Documentation: seccomp: Fix user notification documentation
+    - serial: core: fix suspicious security_locked_down() call
+    - misc/uss720: fix memory leak in uss720_probe
+    - thunderbolt: dma_port: Fix NVM read buffer bounds and offset issue
+    - mei: request autosuspend after sending rx flow control
+    - staging: iio: cdc: ad7746: avoid overwrite of num_channels
+    - iio: gyro: fxas21002c: balance runtime power in error path
+    - iio: adc: ad7768-1: Fix too small buffer passed to
+      iio_push_to_buffers_with_timestamp()
+    - iio: adc: ad7124: Fix missbalanced regulator enable / disable on error.
+    - iio: adc: ad7124: Fix potential overflow due to non sequential channel
+      numbers
+    - iio: adc: ad7793: Add missing error code in ad7793_setup()
+    - serial: 8250_pci: Add support for new HPE serial device
+    - serial: 8250_pci: handle FL_NOIRQ board flag
+    - USB: trancevibrator: fix control-request direction
+    - USB: usbfs: Don't WARN about excessively large memory allocations
+    - serial: tegra: Fix a mask operation that is always true
+    - serial: sh-sci: Fix off-by-one error in FIFO threshold register setting
+    - serial: rp2: use 'request_firmware' instead of 'request_firmware_nowait'
+    - USB: serial: ti_usb_3410_5052: add startech.com device id
+    - USB: serial: option: add Telit LE910-S1 compositions 0x7010, 0x7011
+    - USB: serial: ftdi_sio: add IDs for IDS GmbH Products
+    - USB: serial: pl2303: add device id for ADLINK ND-6530 GC
+    - thermal/drivers/intel: Initialize RW trip to THERMAL_TEMP_INVALID
+    - usb: dwc3: gadget: Properly track pending and queued SG
+    - usb: gadget: udc: renesas_usb3: Fix a race in usb3_start_pipen()
+    - net: usb: fix memory leak in smsc75xx_bind
+    - spi: spi-geni-qcom: Fix use-after-free on unbind
+    - Bluetooth: cmtp: fix file refcount when cmtp_attach_device fails
+    - fs/nfs: Use fatal_signal_pending instead of signal_pending
+    - NFS: fix an incorrect limit in filelayout_decode_layout()
+    - NFS: Fix an Oopsable condition in __nfs_pageio_add_request()
+    - NFS: Don't corrupt the value of pg_bytes_written in nfs_do_recoalesce()
+    - NFSv4: Fix v4.0/v4.1 SEEK_DATA return -ENOTSUPP when set NFS_V4_2 config
+    - drm/meson: fix shutdown crash when component not probed
+    - net/mlx5e: Fix multipath lag activation
+    - net/mlx5e: Fix nullptr in add_vlan_push_action()
+    - net/mlx4: Fix EEPROM dump support
+    - Revert "net:tipc: Fix a double free in tipc_sk_mcast_rcv"
+    - tipc: wait and exit until all work queues are done
+    - tipc: skb_linearize the head skb when reassembling msgs
+    - spi: spi-fsl-dspi: Fix a resource leak in an error handling path
+    - net: dsa: mt7530: fix VLAN traffic leaks
+    - net: dsa: fix a crash if ->get_sset_count() fails
+    - net: dsa: sja1105: error out on unsupported PHY mode
+    - i2c: s3c2410: fix possible NULL pointer deref on read message after write
+    - i2c: i801: Don't generate an interrupt on bus reset
+    - i2c: sh_mobile: Use new clock calculation formulas for RZ/G2E
+    - perf jevents: Fix getting maximum number of fds
+    - platform/x86: hp_accel: Avoid invoking _INI to speed up resume
+    - gpio: cadence: Add missing MODULE_DEVICE_TABLE
+    - Revert "media: usb: gspca: add a missed check for goto_low_power"
+    - Revert "ALSA: sb: fix a missing check of snd_ctl_add"
+    - Revert "serial: max310x: pass return value of spi_register_driver"
+    - serial: max310x: unregister uart driver in case of failure and abort
+    - Revert "net: fujitsu: fix a potential NULL pointer dereference"
+    - net: fujitsu: fix potential null-ptr-deref
+    - Revert "net/smc: fix a NULL pointer dereference"
+    - net: caif: remove BUG_ON(dev == NULL) in caif_xmit
+    - Revert "char: hpet: fix a missing check of ioremap"
+    - char: hpet: add checks after calling ioremap
+    - Revert "ALSA: gus: add a check of the status of snd_ctl_add"
+    - Revert "ALSA: usx2y: Fix potential NULL pointer dereference"
+    - Revert "isdn: mISDNinfineon: fix potential NULL pointer dereference"
+    - isdn: mISDNinfineon: check/cleanup ioremap failure correctly in setup_io
+    - Revert "ath6kl: return error code in ath6kl_wmi_set_roam_lrssi_cmd()"
+    - ath6kl: return error code in ath6kl_wmi_set_roam_lrssi_cmd()
+    - Revert "isdn: mISDN: Fix potential NULL pointer dereference of kzalloc"
+    - isdn: mISDN: correctly handle ph_info allocation failure in hfcsusb_ph_info
+    - Revert "dmaengine: qcom_hidma: Check for driver register failure"
+    - dmaengine: qcom_hidma: comment platform_driver_register call
+    - Revert "libertas: add checks for the return value of sysfs_create_group"
+    - libertas: register sysfs groups properly
+    - Revert "ASoC: cs43130: fix a NULL pointer dereference"
+    - ASoC: cs43130: handle errors in cs43130_probe() properly
+    - Revert "media: dvb: Add check on sp8870_readreg"
+    - media: dvb: Add check on sp8870_readreg return
+    - Revert "media: gspca: mt9m111: Check write_bridge for timeout"
+    - media: gspca: mt9m111: Check write_bridge for timeout
+    - Revert "media: gspca: Check the return value of write_bridge for timeout"
+    - media: gspca: properly check for errors in po1030_probe()
+    - Revert "net: liquidio: fix a NULL pointer dereference"
+    - net: liquidio: Add missing null pointer checks
+    - Revert "brcmfmac: add a check for the status of usb_register"
+    - brcmfmac: properly check for bus register errors
+    - btrfs: return whole extents in fiemap
+    - scsi: BusLogic: Fix 64-bit system enumeration error for Buslogic
+    - openrisc: Define memory barrier mb
+    - btrfs: do not BUG_ON in link_to_fixup_dir
+    - platform/x86: hp-wireless: add AMD's hardware id to the supported list
+    - platform/x86: intel_punit_ipc: Append MODULE_DEVICE_TABLE for ACPI
+    - platform/x86: touchscreen_dmi: Add info for the Mediacom Winpad 7.0 W700
+      tablet
+    - SMB3: incorrect file id in requests compounded with open
+    - drm/amd/display: Disconnect non-DP with no EDID
+    - drm/amd/amdgpu: fix refcount leak
+    - drm/amdgpu: Fix a use-after-free
+    - drm/amd/amdgpu: fix a potential deadlock in gpu reset
+    - net: netcp: Fix an error message
+    - net: dsa: fix error code getting shifted with 4 in dsa_slave_get_sset_count
+    - ASoC: cs42l42: Regmap must use_single_read/write
+    - vfio-ccw: Check initialized flag in cp_init()
+    - net: really orphan skbs tied to closing sk
+    - net: fec: fix the potential memory leak in fec_enet_init()
+    - net: mdio: thunder: Fix a double free issue in the .remove function
+    - net: mdio: octeon: Fix some double free issues
+    - openvswitch: meter: fix race when getting now_ms.
+    - tls splice: check SPLICE_F_NONBLOCK instead of MSG_DONTWAIT
+    - net: sched: fix packet stuck problem for lockless qdisc
+    - net: sched: fix tx action rescheduling issue during deactivation
+    - net: sched: fix tx action reschedule issue with stopped queue
+    - net: hso: check for allocation failure in hso_create_bulk_serial_device()
+    - net: bnx2: Fix error return code in bnx2_init_board()
+    - bnxt_en: Include new P5 HV definition in VF check.
+    - mld: fix panic in mld_newpack()
+    - gve: Check TX QPL was actually assigned
+    - gve: Update mgmt_msix_idx if num_ntfy changes
+    - gve: Add NULL pointer checks when freeing irqs.
+    - gve: Upgrade memory barrier in poll routine
+    - gve: Correct SKB queue index validation.
+    - cxgb4: avoid accessing registers when clearing filters
+    - staging: emxx_udc: fix loop in _nbu2ss_nuke()
+    - ASoC: cs35l33: fix an error code in probe()
+    - bpf: Set mac_len in bpf_skb_change_head
+    - ixgbe: fix large MTU request from VF
+    - scsi: libsas: Use _safe() loop in sas_resume_port()
+    - net: lantiq: fix memory corruption in RX ring
+    - ipv6: record frag_max_size in atomic fragments in input path
+    - ALSA: usb-audio: scarlett2: snd_scarlett_gen2_controls_create() can be
+      static
+    - net: ethernet: mtk_eth_soc: Fix packet statistics support for MT7628/88
+    - sch_dsmark: fix a NULL deref in qdisc_reset()
+    - MIPS: alchemy: xxs1500: add gpio-au1000.h header file
+    - MIPS: ralink: export rt_sysc_membase for rt2880_wdt.c
+    - drm/i915/display: fix compiler warning about array overrun
+    - i915: fix build warning in intel_dp_get_link_status()
+    - drivers/net/ethernet: clean up unused assignments
+    - net: hns3: check the return of skb_checksum_help()
+    - Revert "Revert "ALSA: usx2y: Fix potential NULL pointer dereference""
+    - net: hso: bail out on interrupt URB allocation failure
+    - neighbour: Prevent Race condition in neighbour subsytem
+    - usb: core: reduce power-on-good delay time of root hub
+    - Linux 5.4.124
+
+  * Focal update: v5.4.123 upstream stable release (LP: #1931160)
+    - usb: dwc3: gadget: Enable suspend events
+    - perf unwind: Fix separate debug info files when using elfutils' libdw's
+      unwinder
+    - perf unwind: Set userdata for all __report_module() paths
+    - NFC: nci: fix memory leak in nci_allocate_device
+    - Linux 5.4.123
+
+  * Focal update: v5.4.122 upstream stable release (LP: #1931159)
+    - firmware: arm_scpi: Prevent the ternary sign expansion bug
+    - openrisc: Fix a memory leak
+    - RDMA/siw: Properly check send and receive CQ pointers
+    - RDMA/siw: Release xarray entry
+    - RDMA/rxe: Clear all QP fields if creation failed
+    - scsi: ufs: core: Increase the usable queue depth
+    - scsi: qla2xxx: Fix error return code in qla82xx_write_flash_dword()
+    - RDMA/mlx5: Recover from fatal event in dual port mode
+    - RDMA/core: Don't access cm_id after its destruction
+    - platform/mellanox: mlxbf-tmfifo: Fix a memory barrier issue
+    - platform/x86: dell-smbios-wmi: Fix oops on rmmod dell_smbios
+    - RDMA/uverbs: Fix a NULL vs IS_ERR() bug
+    - ptrace: make ptrace() fail if the tracee changed its pid unexpectedly
+    - nvmet: seset ns->file when open fails
+    - locking/mutex: clear MUTEX_FLAGS if wait_list is empty due to signal
+    - btrfs: avoid RCU stalls while running delayed iputs
+    - cifs: fix memory leak in smb2_copychunk_range
+    - ALSA: dice: fix stream format for TC Electronic Konnekt Live at high
+      sampling transfer frequency
+    - ALSA: intel8x0: Don't update period unless prepared
+    - ALSA: line6: Fix racy initialization of LINE6 MIDI
+    - ALSA: dice: fix stream format at middle sampling rate for Alesis iO 26
+    - ALSA: firewire-lib: fix calculation for size of IR context payload
+    - ALSA: usb-audio: Validate MS endpoint descriptors
+    - ALSA: bebob/oxfw: fix Kconfig entry for Mackie d.2 Pro
+    - ALSA: hda: fixup headset for ASUS GU502 laptop
+    - Revert "ALSA: sb8: add a check for request_region"
+    - ALSA: firewire-lib: fix check for the size of isochronous packet payload
+    - ALSA: hda/realtek: reset eapd coeff to default value for alc287
+    - ALSA: hda/realtek: Add some CLOVE SSIDs of ALC293
+    - ALSA: hda/realtek: Fix silent headphone output on ASUS UX430UA
+    - ALSA: hda/realtek: Add fixup for HP OMEN laptop
+    - ALSA: hda/realtek: Add fixup for HP Spectre x360 15-df0xxx
+    - uio_hv_generic: Fix a memory leak in error handling paths
+    - Revert "rapidio: fix a NULL pointer dereference when create_workqueue()
+      fails"
+    - rapidio: handle create_workqueue() failure
+    - Revert "serial: mvebu-uart: Fix to avoid a potential NULL pointer
+      dereference"
+    - drm/amdgpu: disable 3DCGCG on picasso/raven1 to avoid compute hang
+    - drm/amdgpu: update gc golden setting for Navi12
+    - drm/amdgpu: update sdma golden setting for Navi12
+    - mmc: sdhci-pci-gli: increase 1.8V regulator wait
+    - xen-pciback: reconfigure also from backend watch handler
+    - dm snapshot: fix crash with transient storage and zero chunk size
+    - Revert "video: hgafb: fix potential NULL pointer dereference"
+    - Revert "net: stmicro: fix a missing check of clk_prepare"
+    - Revert "leds: lp5523: fix a missing check of return value of lp55xx_read"
+    - Revert "hwmon: (lm80) fix a missing check of bus read in lm80 probe"
+    - Revert "video: imsttfb: fix potential NULL pointer dereferences"
+    - Revert "ecryptfs: replace BUG_ON with error handling code"
+    - Revert "scsi: ufs: fix a missing check of devm_reset_control_get"
+    - Revert "gdrom: fix a memory leak bug"
+    - cdrom: gdrom: deallocate struct gdrom_unit fields in remove_gdrom
+    - cdrom: gdrom: initialize global variable at init time
+    - Revert "media: rcar_drif: fix a memory disclosure"
+    - Revert "rtlwifi: fix a potential NULL pointer dereference"
+    - Revert "qlcnic: Avoid potential NULL pointer dereference"
+    - Revert "niu: fix missing checks of niu_pci_eeprom_read"
+    - ethernet: sun: niu: fix missing checks of niu_pci_eeprom_read()
+    - net: stmicro: handle clk_prepare() failure during init
+    - scsi: ufs: handle cleanup correctly on devm_reset_control_get error
+    - net: rtlwifi: properly check for alloc_workqueue() failure
+    - ics932s401: fix broken handling of errors when word reading fails
+    - leds: lp5523: check return value of lp5xx_read and jump to cleanup code
+    - qlcnic: Add null check after calling netdev_alloc_skb
+    - video: hgafb: fix potential NULL pointer dereference
+    - vgacon: Record video mode changes with VT_RESIZEX
+    - vt: Fix character height handling with VT_RESIZEX
+    - tty: vt: always invoke vc->vc_sw->con_resize callback
+    - nvme-multipath: fix double initialization of ANA state
+    - ext4: fix error handling in ext4_end_enable_verity()
+    - Bluetooth: L2CAP: Fix handling LE modes by L2CAP_OPTIONS
+    - nvmet: use new ana_log_size instead the old one
+    - video: hgafb: correctly handle card detect failure during probe
+    - Bluetooth: SMP: Fail if remote and local public keys are identical
+    - Linux 5.4.122
+
+  * Focal update: v5.4.121 upstream stable release (LP: #1931158)
+    - x86/msr: Fix wr/rdmsr_safe_regs_on_cpu() prototypes
+    - kgdb: fix gcc-11 warning on indentation
+    - usb: sl811-hcd: improve misleading indentation
+    - cxgb4: Fix the -Wmisleading-indentation warning
+    - isdn: capi: fix mismatched prototypes
+    - pinctrl: ingenic: Improve unreachable code generation
+    - xsk: Simplify detection of empty and full rings
+    - virtio_net: Do not pull payload in skb->head
+    - PCI: thunder: Fix compile testing
+    - dmaengine: dw-edma: Fix crash on loading/unloading driver
+    - ARM: 9066/1: ftrace: pause/unpause function graph tracer in cpu_suspend()
+    - ACPI / hotplug / PCI: Fix reference count leak in enable_slot()
+    - Input: elants_i2c - do not bind to i2c-hid compatible ACPI instantiated
+      devices
+    - Input: silead - add workaround for x86 BIOS-es which bring the chip up in a
+      stuck state
+    - um: Mark all kernel symbols as local
+    - um: Disable CONFIG_GCOV with MODULES
+    - ARM: 9075/1: kernel: Fix interrupted SMC calls
+    - scripts/recordmcount.pl: Fix RISC-V regex for clang
+    - riscv: Workaround mcount name prior to clang-13
+    - scsi: lpfc: Fix illegal memory access on Abort IOCBs
+    - ceph: fix fscache invalidation
+    - scsi: target: tcmu: Return from tcmu_handle_completions() if cmd_id not
+      found
+    - bridge: Fix possible races between assigning rx_handler_data and setting
+      IFF_BRIDGE_PORT bit
+    - drm/amd/display: Fix two cursor duplication when using overlay
+    - gpiolib: acpi: Add quirk to ignore EC wakeups on Dell Venue 10 Pro 5055
+    - ALSA: hda: generic: change the DAC ctl name for LO+SPK or LO+HP
+    - block: reexpand iov_iter after read/write
+    - lib: stackdepot: turn depot_lock spinlock to raw_spinlock
+    - net: stmmac: Do not enable RX FIFO overflow interrupts
+    - ip6_gre: proper dev_{hold|put} in ndo_[un]init methods
+    - sit: proper dev_{hold|put} in ndo_[un]init methods
+    - ip6_tunnel: sit: proper dev_{hold|put} in ndo_[un]init methods
+    - ipv6: remove extra dev_hold() for fallback tunnels
+    - KVM: arm64: Initialize VCPU mdcr_el2 before loading it
+    - tweewide: Fix most Shebang lines
+    - scripts: switch explicitly to Python 3
+    - Linux 5.4.121
+
+  * Focal update: v5.4.120 upstream stable release (LP: #1930474)
+    - tpm: fix error return code in tpm2_get_cc_attrs_tbl()
+    - tpm, tpm_tis: Extend locality handling to TPM2 in tpm_tis_gen_interrupt()
+    - tpm, tpm_tis: Reserve locality in tpm_tis_resume()
+    - KVM: x86/mmu: Remove the defunct update_pte() paging hook
+    - PM: runtime: Fix unpaired parent child_count for force_resume
+    - fs: dlm: fix debugfs dump
+    - tipc: convert dest node's address to network order
+    - ASoC: Intel: bytcr_rt5640: Enable jack-detect support on Asus T100TAF
+    - net: stmmac: Set FIFO sizes for ipq806x
+    - ASoC: rsnd: core: Check convert rate in rsnd_hw_params
+    - i2c: bail out early when RDWR parameters are wrong
+    - ALSA: hdsp: don't disable if not enabled
+    - ALSA: hdspm: don't disable if not enabled
+    - ALSA: rme9652: don't disable if not enabled
+    - ALSA: bebob: enable to deliver MIDI messages for multiple ports
+    - Bluetooth: Set CONF_NOT_COMPLETE as l2cap_chan default
+    - Bluetooth: initialize skb_queue_head at l2cap_chan_create()
+    - net: bridge: when suppression is enabled exclude RARP packets
+    - Bluetooth: check for zapped sk before connecting
+    - ip6_vti: proper dev_{hold|put} in ndo_[un]init methods
+    - ASoC: Intel: bytcr_rt5640: Add quirk for the Chuwi Hi8 tablet
+    - i2c: Add I2C_AQ_NO_REP_START adapter quirk
+    - mac80211: clear the beacon's CRC after channel switch
+    - pinctrl: samsung: use 'int' for register masks in Exynos
+    - mt76: mt76x0: disable GTK offloading
+    - cuse: prevent clone
+    - ASoC: rsnd: call rsnd_ssi_master_clk_start() from rsnd_ssi_init()
+    - Revert "iommu/amd: Fix performance counter initialization"
+    - iommu/amd: Remove performance counter pre-initialization test
+    - drm/amd/display: Force vsync flip when reconfiguring MPCC
+    - selftests: Set CC to clang in lib.mk if LLVM is set
+    - kconfig: nconf: stop endless search loops
+    - ALSA: hda/hdmi: fix race in handling acomp ELD notification at resume
+    - sctp: Fix out-of-bounds warning in sctp_process_asconf_param()
+    - flow_dissector: Fix out-of-bounds warning in __skb_flow_bpf_to_target()
+    - powerpc/smp: Set numa node before updating mask
+    - ASoC: rt286: Generalize support for ALC3263 codec
+    - ethtool: ioctl: Fix out-of-bounds warning in store_link_ksettings_for_user()
+    - net: sched: tapr: prevent cycle_time == 0 in parse_taprio_schedule
+    - samples/bpf: Fix broken tracex1 due to kprobe argument change
+    - powerpc/pseries: Stop calling printk in rtas_stop_self()
+    - drm/amd/display: fixed divide by zero kernel crash during dsc enablement
+    - wl3501_cs: Fix out-of-bounds warnings in wl3501_send_pkt
+    - wl3501_cs: Fix out-of-bounds warnings in wl3501_mgmt_join
+    - qtnfmac: Fix possible buffer overflow in qtnf_event_handle_external_auth
+    - powerpc/iommu: Annotate nested lock for lockdep
+    - iavf: remove duplicate free resources calls
+    - net: ethernet: mtk_eth_soc: fix RX VLAN offload
+    - bnxt_en: Add PCI IDs for Hyper-V VF devices.
+    - ia64: module: fix symbolizer crash on fdescr
+    - ASoC: rt286: Make RT286_SET_GPIO_* readable and writable
+    - thermal: thermal_of: Fix error return code of
+      thermal_of_populate_bind_params()
+    - f2fs: fix a redundant call to f2fs_balance_fs if an error occurs
+    - PCI: iproc: Fix return value of iproc_msi_irq_domain_alloc()
+    - PCI: Release OF node in pci_scan_device()'s error path
+    - ARM: 9064/1: hw_breakpoint: Do not directly check the event's
+      overflow_handler hook
+    - rpmsg: qcom_glink_native: fix error return code of qcom_glink_rx_data()
+    - NFSv4.2: Always flush out writes in nfs42_proc_fallocate()
+    - NFS: Deal correctly with attribute generation counter overflow
+    - PCI: endpoint: Fix missing destroy_workqueue()
+    - pNFS/flexfiles: fix incorrect size check in decode_nfs_fh()
+    - NFSv4.2 fix handling of sr_eof in SEEK's reply
+    - rtc: fsl-ftm-alarm: add MODULE_TABLE()
+    - ceph: fix inode leak on getattr error in __fh_to_dentry
+    - rtc: ds1307: Fix wday settings for rx8130
+    - net: hns3: fix incorrect configuration for igu_egu_hw_err
+    - net: hns3: initialize the message content in hclge_get_link_mode()
+    - net: hns3: add check for HNS3_NIC_STATE_INITED in
+      hns3_reset_notify_up_enet()
+    - net: hns3: fix for vxlan gpe tx checksum bug
+    - net: hns3: use netif_tx_disable to stop the transmit queue
+    - net: hns3: disable phy loopback setting in hclge_mac_start_phy
+    - sctp: do asoc update earlier in sctp_sf_do_dupcook_a
+    - RISC-V: Fix error code returned by riscv_hartid_to_cpuid()
+    - sunrpc: Fix misplaced barrier in call_decode
+    - ethernet:enic: Fix a use after free bug in enic_hard_start_xmit
+    - sctp: fix a SCTP_MIB_CURRESTAB leak in sctp_sf_do_dupcook_b
+    - netfilter: xt_SECMARK: add new revision to fix structure layout
+    - drm/radeon: Fix off-by-one power_state index heap overwrite
+    - drm/radeon: Avoid power table parsing memory leaks
+    - khugepaged: fix wrong result value for trace_mm_collapse_huge_page_isolate()
+    - mm/hugeltb: handle the error case in hugetlb_fix_reserve_counts()
+    - mm/migrate.c: fix potential indeterminate pte entry in
+      migrate_vma_insert_page()
+    - ksm: fix potential missing rmap_item for stable_node
+    - net: fix nla_strcmp to handle more then one trailing null character
+    - smc: disallow TCP_ULP in smc_setsockopt()
+    - netfilter: nfnetlink_osf: Fix a missing skb_header_pointer() NULL check
+    - can: m_can: m_can_tx_work_queue(): fix tx_skb race condition
+    - sched: Fix out-of-bound access in uclamp
+    - sched/fair: Fix unfairness caused by missing load decay
+    - kernel: kexec_file: fix error return code of kexec_calculate_store_digests()
+    - netfilter: nftables: avoid overflows in nft_hash_buckets()
+    - i40e: Fix use-after-free in i40e_client_subtask()
+    - i40e: fix the restart auto-negotiation after FEC modified
+    - i40e: Fix PHY type identifiers for 2.5G and 5G adapters
+    - ARC: entry: fix off-by-one error in syscall number validation
+    - ARC: mm: PAE: use 40-bit physical page mask
+    - powerpc/64s: Fix crashes when toggling stf barrier
+    - powerpc/64s: Fix crashes when toggling entry flush barrier
+    - hfsplus: prevent corruption in shrinking truncate
+    - squashfs: fix divide error in calculate_skip()
+    - userfaultfd: release page in error path to avoid BUG_ON
+    - mm/hugetlb: fix F_SEAL_FUTURE_WRITE
+    - drm/radeon/dpm: Disable sclk switching on Oland when two 4K 60Hz monitors
+      are connected
+    - drm/i915: Avoid div-by-zero on gen2
+    - iio: proximity: pulsedlight: Fix rumtime PM imbalance on error
+    - usb: fotg210-hcd: Fix an error message
+    - hwmon: (occ) Fix poll rate limiting
+    - ACPI: scan: Fix a memory leak in an error handling path
+    - kyber: fix out of bounds access when preempted
+    - nbd: Fix NULL pointer in flush_workqueue
+    - blk-mq: Swap two calls in blk_mq_exit_queue()
+    - iomap: fix sub-page uptodate handling
+    - usb: dwc3: omap: improve extcon initialization
+    - usb: dwc3: pci: Enable usb2-gadget-lpm-disable for Intel Merrifield
+    - usb: xhci: Increase timeout for HC halt
+    - usb: dwc2: Fix gadget DMA unmap direction
+    - usb: core: hub: fix race condition about TRSMRCY of resume
+    - usb: dwc3: gadget: Return success always for kick transfer in ep queue
+    - xhci: Do not use GFP_KERNEL in (potentially) atomic context
+    - xhci: Add reset resume quirk for AMD xhci controller.
+    - iio: gyro: mpu3050: Fix reported temperature value
+    - iio: tsl2583: Fix division by a zero lux_val
+    - cdc-wdm: untangle a circular dependency between callback and softint
+    - KVM: x86: Cancel pvclock_gtod_work on module removal
+    - mm: fix struct page layout on 32-bit systems
+    - FDDI: defxx: Make MMIO the configuration default except for EISA
+    - MIPS: Reinstate platform `__div64_32' handler
+    - MIPS: Avoid DIVU in `__div64_32' is result would be zero
+    - MIPS: Avoid handcoded DIVU in `__div64_32' altogether
+    - thermal/core/fair share: Lock the thermal zone while looping over instances
+    - f2fs: fix error handling in f2fs_end_enable_verity()
+    - ARM: 9011/1: centralize phys-to-virt conversion of DT/ATAGS address
+    - ARM: 9012/1: move device tree mapping out of linear region
+    - ARM: 9020/1: mm: use correct section size macro to describe the FDT virtual
+      address
+    - ARM: 9027/1: head.S: explicitly map DT even if it lives in the first
+      physical section
+    - usb: typec: tcpm: Fix error while calculating PPS out values
+    - kobject_uevent: remove warning in init_uevent_argv()
+    - netfilter: conntrack: Make global sysctls readonly in non-init netns
+    - clk: exynos7: Mark aclk_fsys1_200 as critical
+    - nvme: do not try to reconfigure APST when the controller is not live
+    - ASoC: rsnd: check all BUSIF status when error
+    - Linux 5.4.120
+
+  * scsi: storvsc: Parameterize number hardware queues (LP: #1930626)
+    - scsi: storvsc: Parameterize number hardware queues
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Fri, 18 Jun 2021 16:07:34 +0200
+
+linux (5.4.0-77.86) focal; urgency=medium
+
+  * UAF on CAN J1939 j1939_can_recv (LP: #1932209)
+    - SAUCE: can: j1939: delay release of j1939_priv after synchronize_rcu
+
+  * UAF on CAN BCM bcm_rx_handler (LP: #1931855)
+    - SAUCE: can: bcm: delay release of struct bcm_op after synchronize_rcu
+
+ -- Thadeu Lima de Souza Cascardo <cascardo@canonical.com>  Wed, 16 Jun 2021 22:05:50 -0300
+
+linux (5.4.0-76.85) focal; urgency=medium
+
+  * focal/linux: 5.4.0-76.85 -proposed tracker (LP: #1932123)
+
+  * Upstream v5.9 introduced 'module' patches that removed exported symbols
+    (LP: #1932065)
+    - SAUCE: Revert "modules: inherit TAINT_PROPRIETARY_MODULE"
+    - SAUCE: Revert "modules: return licensing information from find_symbol"
+    - SAUCE: Revert "modules: rename the licence field in struct symsearch to
+      license"
+    - SAUCE: Revert "modules: unexport __module_address"
+    - SAUCE: Revert "modules: unexport __module_text_address"
+    - SAUCE: Revert "modules: mark each_symbol_section static"
+    - SAUCE: Revert "modules: mark find_symbol static"
+    - SAUCE: Revert "modules: mark ref_module static"
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Wed, 16 Jun 2021 10:37:49 +0200
+
+linux (5.4.0-75.84) focal; urgency=medium
+
+  * focal/linux: 5.4.0-75.84 -proposed tracker (LP: #1930032)
+
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+
+  * CVE-2021-33200
+    - bpf: Wrap aux data inside bpf_sanitize_info container
+    - bpf: Fix mask direction swap upon off reg sign change
+    - bpf: No need to simulate speculative domain for immediates
+
+  * Realtek USB hubs in Dell WD19SC/DC/TB fail to work after exiting s2idle
+    (LP: #1928242)
+    - USB: Verify the port status when timeout happens during port suspend
+
+  * CVE-2020-26145
+    - ath10k: drop fragments with multicast DA for SDIO
+    - ath10k: add CCMP PN replay protection for fragmented frames for PCIe
+    - ath10k: drop fragments with multicast DA for PCIe
+
+  * CVE-2020-26141
+    - ath10k: Fix TKIP Michael MIC verification for PCIe
+
+  * CVE-2020-24588
+    - mac80211: properly handle A-MSDUs that start with an RFC 1042 header
+    - cfg80211: mitigate A-MSDU aggregation attacks
+    - mac80211: drop A-MSDUs on old ciphers
+    - ath10k: drop MPDU which has discard flag set by firmware for SDIO
+
+  * CVE-2020-26139
+    - mac80211: do not accept/forward invalid EAPOL frames
+
+  * CVE-2020-24586 // CVE-2020-24587 // CVE-2020-24587 for such cases.
+    - mac80211: extend protection against mixed key and fragment cache attacks
+
+  * CVE-2020-24586 // CVE-2020-24587
+    - mac80211: prevent mixed key and fragment cache attacks
+    - mac80211: add fragment cache to sta_info
+    - mac80211: check defrag PN against current frame
+    - mac80211: prevent attacks on TKIP/WEP as well
+
+  * CVE-2020-26147
+    - mac80211: assure all fragments are encrypted
+
+  * raid10: Block discard is very slow, causing severe delays for mkfs and
+    fstrim operations (LP: #1896578)
+    - md: add md_submit_discard_bio() for submitting discard bio
+    - md/raid10: extend r10bio devs to raid disks
+    - md/raid10: pull the code that wait for blocked dev into one function
+    - md/raid10: improve raid10 discard request
+    - md/raid10: improve discard request for far layout
+    - dm raid: remove unnecessary discard limits for raid0 and raid10
+
+  * [SRU] mpt3sas: only one vSES is handy even IOC has multi vSES (LP: #1926517)
+    - scsi: mpt3sas: Only one vSES is present even when IOC has multi vSES
+
+  * kvm: properly tear down PV features on hibernate (LP: #1920944)
+    - x86/kvm: Fix pr_info() for async PF setup/teardown
+    - x86/kvm: Teardown PV features on boot CPU as well
+    - x86/kvm: Disable kvmclock on all CPUs on shutdown
+    - x86/kvm: Disable all PV features on crash
+    - x86/kvm: Unify kvm_pv_guest_cpu_reboot() with kvm_guest_cpu_offline()
+
+  * Focal update: v5.4.119 upstream stable release (LP: #1929615)
+    - Bluetooth: verify AMP hci_chan before amp_destroy
+    - hsr: use netdev_err() instead of WARN_ONCE()
+    - bluetooth: eliminate the potential race condition when removing the HCI
+      controller
+    - net/nfc: fix use-after-free llcp_sock_bind/connect
+    - Revert "USB: cdc-acm: fix rounding error in TIOCSSERIAL"
+    - tty: moxa: fix TIOCSSERIAL jiffies conversions
+    - tty: amiserial: fix TIOCSSERIAL permission check
+    - USB: serial: usb_wwan: fix TIOCSSERIAL jiffies conversions
+    - staging: greybus: uart: fix TIOCSSERIAL jiffies conversions
+    - USB: serial: ti_usb_3410_5052: fix TIOCSSERIAL permission check
+    - staging: fwserial: fix TIOCSSERIAL jiffies conversions
+    - tty: moxa: fix TIOCSSERIAL permission check
+    - staging: fwserial: fix TIOCSSERIAL permission check
+    - usb: typec: tcpm: Address incorrect values of tcpm psy for fixed supply
+    - usb: typec: tcpm: Address incorrect values of tcpm psy for pps supply
+    - usb: typec: tcpm: update power supply once partner accepts
+    - usb: xhci-mtk: remove or operator for setting schedule parameters
+    - usb: xhci-mtk: improve bandwidth scheduling with TT
+    - ASoC: samsung: tm2_wm5110: check of of_parse return value
+    - ASoC: Intel: kbl_da7219_max98927: Fix kabylake_ssp_fixup function
+    - MIPS: pci-mt7620: fix PLL lock check
+    - MIPS: pci-rt2880: fix slot 0 configuration
+    - FDDI: defxx: Bail out gracefully with unassigned PCI resource for CSR
+    - PCI: Allow VPD access for QLogic ISP2722
+    - iio:accel:adis16201: Fix wrong axis assignment that prevents loading
+    - misc: lis3lv02d: Fix false-positive WARN on various HP models
+    - misc: vmw_vmci: explicitly initialize vmci_notify_bm_set_msg struct
+    - misc: vmw_vmci: explicitly initialize vmci_datagram payload
+    - md/bitmap: wait for external bitmap writes to complete during tear down
+    - md-cluster: fix use-after-free issue when removing rdev
+    - md: split mddev_find
+    - md: factor out a mddev_find_locked helper from mddev_find
+    - md: md_open returns -EBUSY when entering racing area
+    - md: Fix missing unused status line of /proc/mdstat
+    - ipw2x00: potential buffer overflow in libipw_wx_set_encodeext()
+    - cfg80211: scan: drop entry from hidden_list on overflow
+    - rtw88: Fix array overrun in rtw_get_tx_power_params()
+    - drm/panfrost: Clear MMU irqs before handling the fault
+    - drm/panfrost: Don't try to map pages that are already mapped
+    - drm/radeon: fix copy of uninitialized variable back to userspace
+    - drm/amd/display: Reject non-zero src_y and src_x for video planes
+    - ALSA: hda/realtek: Re-order ALC882 Acer quirk table entries
+    - ALSA: hda/realtek: Re-order ALC882 Sony quirk table entries
+    - ALSA: hda/realtek: Re-order ALC882 Clevo quirk table entries
+    - ALSA: hda/realtek: Re-order ALC269 HP quirk table entries
+    - ALSA: hda/realtek: Re-order ALC269 Acer quirk table entries
+    - ALSA: hda/realtek: Re-order ALC269 Dell quirk table entries
+    - ALSA: hda/realtek: Re-order ALC269 ASUS quirk table entries
+    - ALSA: hda/realtek: Re-order ALC269 Sony quirk table entries
+    - ALSA: hda/realtek: Re-order ALC269 Lenovo quirk table entries
+    - ALSA: hda/realtek: Re-order remaining ALC269 quirk table entries
+    - ALSA: hda/realtek: Re-order ALC662 quirk table entries
+    - ALSA: hda/realtek: Remove redundant entry for ALC861 Haier/Uniwill devices
+    - ALSA: hda/realtek: ALC285 Thinkpad jack pin quirk is unreachable
+    - KVM: s390: split kvm_s390_logical_to_effective
+    - KVM: s390: fix guarded storage control register handling
+    - s390: fix detection of vector enhancements facility 1 vs. vector packed
+      decimal facility
+    - KVM: s390: split kvm_s390_real_to_abs
+    - KVM: nVMX: Truncate bits 63:32 of VMCS field on nested check in !64-bit
+    - KVM: Stop looking for coalesced MMIO zones if the bus is destroyed
+    - Revert "i3c master: fix missing destroy_workqueue() on error in
+      i3c_master_register"
+    - ovl: fix missing revert_creds() on error path
+    - usb: gadget: pch_udc: Revert d3cb25a12138 completely
+    - memory: gpmc: fix out of bounds read and dereference on gpmc_cs[]
+    - ARM: dts: exynos: correct fuel gauge interrupt trigger level on Midas family
+    - ARM: dts: exynos: correct MUIC interrupt trigger level on Midas family
+    - ARM: dts: exynos: correct PMIC interrupt trigger level on Midas family
+    - ARM: dts: exynos: correct PMIC interrupt trigger level on Odroid X/U3 family
+    - ARM: dts: exynos: correct PMIC interrupt trigger level on SMDK5250
+    - ARM: dts: exynos: correct PMIC interrupt trigger level on Snow
+    - serial: stm32: fix incorrect characters on console
+    - serial: stm32: fix tx_empty condition
+    - usb: typec: tcpci: Check ROLE_CONTROL while interpreting CC_STATUS
+    - regmap: set debugfs_name to NULL after it is freed
+    - mtd: rawnand: fsmc: Fix error code in fsmc_nand_probe()
+    - mtd: rawnand: brcmnand: fix OOB R/W with Hamming ECC
+    - mtd: Handle possible -EPROBE_DEFER from parse_mtd_partitions()
+    - mtd: rawnand: qcom: Return actual error code instead of -ENODEV
+    - arm64: dts: qcom: sm8150: fix number of pins in 'gpio-ranges'
+    - spi: stm32: drop devres version of spi_register_master
+    - arm64: dts: renesas: r8a77980: Fix vin4-7 endpoint binding
+    - x86/microcode: Check for offline CPUs before requesting new microcode
+    - usb: gadget: pch_udc: Replace cpu_to_le32() by lower_32_bits()
+    - usb: gadget: pch_udc: Check if driver is present before calling ->setup()
+    - usb: gadget: pch_udc: Check for DMA mapping error
+    - crypto: qat - don't release uninitialized resources
+    - crypto: qat - ADF_STATUS_PF_RUNNING should be set after adf_dev_init
+    - fotg210-udc: Fix DMA on EP0 for length > max packet size
+    - fotg210-udc: Fix EP0 IN requests bigger than two packets
+    - fotg210-udc: Remove a dubious condition leading to fotg210_done
+    - fotg210-udc: Mask GRP2 interrupts we don't handle
+    - fotg210-udc: Don't DMA more than the buffer can take
+    - fotg210-udc: Complete OUT requests on short packets
+    - mtd: require write permissions for locking and badblock ioctls
+    - bus: qcom: Put child node before return
+    - soundwire: bus: Fix device found flag correctly
+    - phy: marvell: ARMADA375_USBCLUSTER_PHY should not default to y,
+      unconditionally
+    - crypto: qat - fix error path in adf_isr_resource_alloc()
+    - usb: gadget: aspeed: fix dma map failure
+    - USB: gadget: udc: fix wrong pointer passed to IS_ERR() and PTR_ERR()
+    - memory: pl353: fix mask of ECC page_size config register
+    - soundwire: stream: fix memory leak in stream config error path
+    - m68k: mvme147,mvme16x: Don't wipe PCC timer config bits
+    - mtd: rawnand: gpmi: Fix a double free in gpmi_nand_init
+    - irqchip/gic-v3: Fix OF_BAD_ADDR error handling
+    - staging: rtl8192u: Fix potential infinite loop
+    - staging: greybus: uart: fix unprivileged TIOCCSERIAL
+    - PM / devfreq: Use more accurate returned new_freq as resume_freq
+    - spi: Fix use-after-free with devm_spi_alloc_*
+    - soc: qcom: mdt_loader: Validate that p_filesz < p_memsz
+    - soc: qcom: mdt_loader: Detect truncated read of segments
+    - ACPI: CPPC: Replace cppc_attr with kobj_attribute
+    - crypto: qat - Fix a double free in adf_create_ring
+    - cpufreq: armada-37xx: Fix setting TBG parent for load levels
+    - clk: mvebu: armada-37xx-periph: remove .set_parent method for CPU PM clock
+    - cpufreq: armada-37xx: Fix the AVS value for load L1
+    - clk: mvebu: armada-37xx-periph: Fix switching CPU freq from 250 Mhz to 1 GHz
+    - clk: mvebu: armada-37xx-periph: Fix workaround for switching from L1 to L0
+    - cpufreq: armada-37xx: Fix driver cleanup when registration failed
+    - cpufreq: armada-37xx: Fix determining base CPU frequency
+    - spi: fsl-lpspi: Fix PM reference leak in lpspi_prepare_xfer_hardware()
+    - usb: gadget: r8a66597: Add missing null check on return from
+      platform_get_resource
+    - USB: cdc-acm: fix unprivileged TIOCCSERIAL
+    - USB: cdc-acm: fix TIOCGSERIAL implementation
+    - tty: fix return value for unsupported ioctls
+    - serial: core: return early on unsupported ioctls
+    - firmware: qcom-scm: Fix QCOM_SCM configuration
+    - node: fix device cleanups in error handling code
+    - usbip: vudc: fix missing unlock on error in usbip_sockfd_store()
+    - platform/x86: pmc_atom: Match all Beckhoff Automation baytrail boards with
+      critclk_systems DMI table
+    - x86/platform/uv: Fix !KEXEC build failure
+    - usb: dwc2: Fix host mode hibernation exit with remote wakeup flow.
+    - usb: dwc2: Fix hibernation between host and device modes.
+    - ttyprintk: Add TTY hangup callback.
+    - xen-blkback: fix compatibility bug with single page rings
+    - soc: aspeed: fix a ternary sign expansion bug
+    - media: vivid: fix assignment of dev->fbuf_out_flags
+    - media: omap4iss: return error code when omap4iss_get() failed
+    - media: aspeed: fix clock handling logic
+    - media: platform: sunxi: sun6i-csi: fix error return code of
+      sun6i_video_start_streaming()
+    - media: m88rs6000t: avoid potential out-of-bounds reads on arrays
+    - drm/amdkfd: fix build error with AMD_IOMMU_V2=m
+    - x86/kprobes: Fix to check non boostable prefixes correctly
+    - pata_arasan_cf: fix IRQ check
+    - pata_ipx4xx_cf: fix IRQ check
+    - sata_mv: add IRQ checks
+    - ata: libahci_platform: fix IRQ check
+    - nvme-tcp: block BH in sk state_change sk callback
+    - nvmet-tcp: fix incorrect locking in state_change sk callback
+    - nvme: retrigger ANA log update if group descriptor isn't found
+    - media: v4l2-ctrls.c: fix race condition in hdl->requests list
+    - vfio/mdev: Do not allow a mdev_type to have a NULL parent pointer
+    - clk: zynqmp: move zynqmp_pll_set_mode out of round_rate callback
+    - clk: qcom: a53-pll: Add missing MODULE_DEVICE_TABLE
+    - clk: uniphier: Fix potential infinite loop
+    - scsi: hisi_sas: Fix IRQ checks
+    - scsi: jazz_esp: Add IRQ check
+    - scsi: sun3x_esp: Add IRQ check
+    - scsi: sni_53c710: Add IRQ check
+    - scsi: ibmvfc: Fix invalid state machine BUG_ON()
+    - mfd: stm32-timers: Avoid clearing auto reload register
+    - nvme-pci: don't simple map sgl when sgls are disabled
+    - HSI: core: fix resource leaks in hsi_add_client_from_dt()
+    - x86/events/amd/iommu: Fix sysfs type mismatch
+    - sched/debug: Fix cgroup_path[] serialization
+    - drivers/block/null_blk/main: Fix a double free in null_init.
+    - HID: plantronics: Workaround for double volume key presses
+    - perf symbols: Fix dso__fprintf_symbols_by_name() to return the number of
+      printed chars
+    - net: lapbether: Prevent racing when checking whether the netif is running
+    - powerpc/fadump: Mark fadump_calculate_reserve_size as __init
+    - powerpc/prom: Mark identical_pvr_fixup as __init
+    - inet: use bigger hash table for IP ID generation
+    - powerpc: Fix HAVE_HARDLOCKUP_DETECTOR_ARCH build configuration
+    - ALSA: core: remove redundant spin_lock pair in snd_card_disconnect
+    - bug: Remove redundant condition check in report_bug
+    - nfc: pn533: prevent potential memory corruption
+    - net: hns3: Limiting the scope of vector_ring_chain variable
+    - mips: bmips: fix syscon-reboot nodes
+    - ALSA: usb-audio: Add error checks for usb_driver_claim_interface() calls
+    - ASoC: simple-card: fix possible uninitialized single_cpu local variable
+    - liquidio: Fix unintented sign extension of a left shift of a u16
+    - powerpc/64s: Fix pte update for kernel memory on radix
+    - powerpc/perf: Fix PMU constraint check for EBB events
+    - powerpc: iommu: fix build when neither PCI or IBMVIO is set
+    - mac80211: bail out if cipher schemes are invalid
+    - mt7601u: fix always true expression
+    - KVM: PPC: Book3S HV P9: Restore host CTRL SPR after guest exit
+    - RDMA/qedr: Fix error return code in qedr_iw_connect()
+    - IB/hfi1: Fix error return code in parse_platform_config()
+    - cxgb4: Fix unintentional sign extension issues
+    - net: thunderx: Fix unintentional sign extension issue
+    - RDMA/srpt: Fix error return code in srpt_cm_req_recv()
+    - i2c: img-scb: fix reference leak when pm_runtime_get_sync fails
+    - i2c: imx-lpi2c: fix reference leak when pm_runtime_get_sync fails
+    - i2c: omap: fix reference leak when pm_runtime_get_sync fails
+    - i2c: sprd: fix reference leak when pm_runtime_get_sync fails
+    - i2c: cadence: add IRQ check
+    - i2c: emev2: add IRQ check
+    - i2c: jz4780: add IRQ check
+    - i2c: sh7760: add IRQ check
+    - powerpc/xive: Fix xmon command "dxi"
+    - ASoC: ak5558: correct reset polarity
+    - drm/i915/gvt: Fix error code in intel_gvt_init_device()
+    - perf beauty: Fix fsconfig generator
+    - MIPS: pci-legacy: stop using of_pci_range_to_resource
+    - powerpc/pseries: extract host bridge from pci_bus prior to bus removal
+    - rtlwifi: 8821ae: upgrade PHY and RF parameters
+    - i2c: sh7760: fix IRQ error path
+    - mwl8k: Fix a double Free in mwl8k_probe_hw
+    - vsock/vmci: log once the failed queue pair allocation
+    - gro: fix napi_gro_frags() Fast GRO breakage due to IP alignment check
+    - RDMA/cxgb4: add missing qpid increment
+    - RDMA/i40iw: Fix error unwinding when i40iw_hmc_sd_one fails
+    - ALSA: usb: midi: don't return -ENOMEM when usb_urb_ep_type_check fails
+    - net: davinci_emac: Fix incorrect masking of tx and rx error channel
+    - net: renesas: ravb: Fix a stuck issue when a lot of frames are received
+    - net: phy: intel-xway: enable integrated led functions
+    - ath9k: Fix error check in ath9k_hw_read_revisions() for PCI devices
+    - ath10k: Fix ath10k_wmi_tlv_op_pull_peer_stats_info() unlock without lock
+    - powerpc/52xx: Fix an invalid ASM expression ('addi' used instead of 'add')
+    - bnxt_en: fix ternary sign extension bug in bnxt_show_temp()
+    - ARM: dts: uniphier: Change phy-mode to RGMII-ID to enable delay pins for
+      RTL8211E
+    - arm64: dts: uniphier: Change phy-mode to RGMII-ID to enable delay pins for
+      RTL8211E
+    - net: geneve: modify IP header check in geneve6_xmit_skb and geneve_xmit_skb
+    - selftests: net: mirror_gre_vlan_bridge_1q: Make an FDB entry static
+    - bnxt_en: Fix RX consumer index logic in the error path.
+    - net:emac/emac-mac: Fix a use after free in emac_mac_tx_buf_send
+    - RDMA/siw: Fix a use after free in siw_alloc_mr
+    - RDMA/bnxt_re: Fix a double free in bnxt_qplib_alloc_res
+    - net: bridge: mcast: fix broken length + header check for MRDv6 Adv.
+    - net:nfc:digital: Fix a double free in digital_tg_recv_dep_req
+    - kfifo: fix ternary sign extension bugs
+    - mm/sparse: add the missing sparse_buffer_fini() in error branch
+    - mm/memory-failure: unnecessary amount of unmapping
+    - net: Only allow init netns to set default tcp cong to a restricted algo
+    - smp: Fix smp_call_function_single_async prototype
+    - Revert "net/sctp: fix race condition in sctp_destroy_sock"
+    - sctp: delay auto_asconf init until binding the first addr
+    - Revert "of/fdt: Make sure no-map does not remove already reserved regions"
+    - Revert "fdt: Properly handle "no-map" field in the memory region"
+    - Linux 5.4.119
+
+  * seccomp_bpf:syscall_faked from kselftests fail on s390x (LP: #1928522)
+    - selftests/seccomp: s390 shares the syscall and return value register
+
+  * Can't detect intel wifi 6235 (LP: #1920180)
+    - SAUCE: iwlwifi: add new pci id for 6235
+
+  * Mark kprobe_args_user.tc in kselftest/ftrace as unsupported (LP: #1929527)
+    - selftests/ftrace: Return unsupported for the unconfigured features
+
+  * pmtu.sh from net in ubuntu_kernel_selftests failed with no error message
+    (LP: #1887661)
+    - selftests: pmtu.sh: use $ksft_skip for skipped return code
+
+  * alsa/sof: make sof driver work in the case of without i915 (focal kernel)
+    (LP: #1927672)
+    - SAUCE: ASoC: SOF: Intel: hda: move the probe_bus ahead of creation of mach
+      device
+
+  * Fix kdump failures (LP: #1927518)
+    - video: hyperv_fb: Add ratelimit on error message
+    - Drivers: hv: vmbus: Increase wait time for VMbus unload
+    - Drivers: hv: vmbus: Initialize unload_event statically
+
+  * Ubuntu 20.04 - 'Support flow counters offset for bulk counters'
+    (LP: #1922494)
+    - IB/mlx5: Support flow counters offset for bulk counters
+
+  * Focal update: v5.4.118 upstream stable release (LP: #1928825)
+    - s390/disassembler: increase ebpf disasm buffer size
+    - ACPI: custom_method: fix potential use-after-free issue
+    - ACPI: custom_method: fix a possible memory leak
+    - ftrace: Handle commands when closing set_ftrace_filter file
+    - ARM: 9056/1: decompressor: fix BSS size calculation for LLVM ld.lld
+    - arm64: dts: marvell: armada-37xx: add syscon compatible to NB clk node
+    - arm64: dts: mt8173: fix property typo of 'phys' in dsi node
+    - ecryptfs: fix kernel panic with null dev_name
+    - mtd: spinand: core: add missing MODULE_DEVICE_TABLE()
+    - mtd: rawnand: atmel: Update ecc_stats.corrected counter
+    - erofs: add unsupported inode i_format check
+    - spi: spi-ti-qspi: Free DMA resources
+    - scsi: qla2xxx: Fix crash in qla2xxx_mqueuecommand()
+    - scsi: mpt3sas: Block PCI config access from userspace during reset
+    - mmc: uniphier-sd: Fix an error handling path in uniphier_sd_probe()
+    - mmc: uniphier-sd: Fix a resource leak in the remove function
+    - mmc: sdhci: Check for reset prior to DMA address unmap
+    - mmc: sdhci-pci: Fix initialization of some SD cards for Intel BYT-based
+      controllers
+    - mmc: block: Update ext_csd.cache_ctrl if it was written
+    - mmc: block: Issue a cache flush only when it's enabled
+    - mmc: core: Do a power cycle when the CMD11 fails
+    - mmc: core: Set read only for SD cards with permanent write protect bit
+    - mmc: core: Fix hanging on I/O during system suspend for removable cards
+    - modules: mark ref_module static
+    - modules: mark find_symbol static
+    - modules: mark each_symbol_section static
+    - modules: unexport __module_text_address
+    - modules: unexport __module_address
+    - modules: rename the licence field in struct symsearch to license
+    - modules: return licensing information from find_symbol
+    - modules: inherit TAINT_PROPRIETARY_MODULE
+    - irqchip/gic-v3: Do not enable irqs when handling spurious interrups
+    - cifs: Return correct error code from smb2_get_enc_key
+    - btrfs: fix metadata extent leak after failure to create subvolume
+    - intel_th: pci: Add Rocket Lake CPU support
+    - posix-timers: Preserve return value in clock_adjtime32()
+    - fbdev: zero-fill colormap in fbcmap.c
+    - bus: ti-sysc: Probe for l4_wkup and l4_cfg interconnect devices first
+    - staging: wimax/i2400m: fix byte-order issue
+    - spi: ath79: always call chipselect function
+    - spi: ath79: remove spi-master setup and cleanup assignment
+    - crypto: api - check for ERR pointers in crypto_destroy_tfm()
+    - crypto: qat - fix unmap invalid dma address
+    - usb: gadget: uvc: add bInterval checking for HS mode
+    - usb: webcam: Invalid size of Processing Unit Descriptor
+    - genirq/matrix: Prevent allocation counter corruption
+    - usb: gadget: f_uac2: validate input parameters
+    - usb: gadget: f_uac1: validate input parameters
+    - usb: dwc3: gadget: Ignore EP queue requests during bus reset
+    - usb: xhci: Fix port minor revision
+    - PCI: PM: Do not read power state in pci_enable_device_flags()
+    - x86/build: Propagate $(CLANG_FLAGS) to $(REALMODE_FLAGS)
+    - tee: optee: do not check memref size on return from Secure World
+    - perf/arm_pmu_platform: Fix error handling
+    - usb: xhci-mtk: support quirk to disable usb2 lpm
+    - xhci: check control context is valid before dereferencing it.
+    - xhci: fix potential array out of bounds with several interrupters
+    - spi: dln2: Fix reference leak to master
+    - spi: omap-100k: Fix reference leak to master
+    - spi: qup: fix PM reference leak in spi_qup_remove()
+    - usb: musb: fix PM reference leak in musb_irq_work()
+    - usb: core: hub: Fix PM reference leak in usb_port_resume()
+    - tty: n_gsm: check error while registering tty devices
+    - intel_th: Consistency and off-by-one fix
+    - phy: phy-twl4030-usb: Fix possible use-after-free in twl4030_usb_remove()
+    - crypto: stm32/hash - Fix PM reference leak on stm32-hash.c
+    - crypto: stm32/cryp - Fix PM reference leak on stm32-cryp.c
+    - crypto: omap-aes - Fix PM reference leak on omap-aes.c
+    - platform/x86: intel_pmc_core: Don't use global pmcdev in quirks
+    - btrfs: convert logic BUG_ON()'s in replace_path to ASSERT()'s
+    - drm: Added orientation quirk for OneGX1 Pro
+    - drm/qxl: release shadow on shutdown
+    - drm/amd/display: Check for DSC support instead of ASIC revision
+    - drm/amd/display: Don't optimize bandwidth before disabling planes
+    - scsi: lpfc: Fix incorrect dbde assignment when building target abts wqe
+    - scsi: lpfc: Fix pt2pt connection does not recover after LOGO
+    - scsi: target: pscsi: Fix warning in pscsi_complete_cmd()
+    - media: ite-cir: check for receive overflow
+    - media: drivers: media: pci: sta2x11: fix Kconfig dependency on GPIOLIB
+    - media: imx: capture: Return -EPIPE from __capture_legacy_try_fmt()
+    - power: supply: bq27xxx: fix power_avg for newer ICs
+    - extcon: arizona: Fix some issues when HPDET IRQ fires after the jack has
+      been unplugged
+    - extcon: arizona: Fix various races on driver unbind
+    - media: media/saa7164: fix saa7164_encoder_register() memory leak bugs
+    - media: gspca/sq905.c: fix uninitialized variable
+    - power: supply: Use IRQF_ONESHOT
+    - drm/amdgpu: mask the xgmi number of hops reported from psp to kfd
+    - drm/amdkfd: Fix UBSAN shift-out-of-bounds warning
+    - drm/amdgpu : Fix asic reset regression issue introduce by 8f211fe8ac7c4f
+    - drm/amd/display: Fix UBSAN warning for not a valid value for type '_Bool'
+    - drm/amd/display: fix dml prefetch validation
+    - scsi: qla2xxx: Always check the return value of qla24xx_get_isp_stats()
+    - drm/vkms: fix misuse of WARN_ON
+    - scsi: qla2xxx: Fix use after free in bsg
+    - mmc: sdhci-pci: Add PCI IDs for Intel LKF
+    - ata: ahci: Disable SXS for Hisilicon Kunpeng920
+    - scsi: smartpqi: Correct request leakage during reset operations
+    - scsi: smartpqi: Add new PCI IDs
+    - scsi: scsi_dh_alua: Remove check for ASC 24h in alua_rtpg()
+    - media: em28xx: fix memory leak
+    - media: vivid: update EDID
+    - clk: socfpga: arria10: Fix memory leak of socfpga_clk on error return
+    - power: supply: generic-adc-battery: fix possible use-after-free in
+      gab_remove()
+    - power: supply: s3c_adc_battery: fix possible use-after-free in
+      s3c_adc_bat_remove()
+    - media: tc358743: fix possible use-after-free in tc358743_remove()
+    - media: adv7604: fix possible use-after-free in adv76xx_remove()
+    - media: i2c: adv7511-v4l2: fix possible use-after-free in adv7511_remove()
+    - media: i2c: tda1997: Fix possible use-after-free in tda1997x_remove()
+    - media: i2c: adv7842: fix possible use-after-free in adv7842_remove()
+    - media: platform: sti: Fix runtime PM imbalance in regs_show
+    - media: dvb-usb: fix memory leak in dvb_usb_adapter_init
+    - media: gscpa/stv06xx: fix memory leak
+    - sched/fair: Ignore percpu threads for imbalance pulls
+    - drm/msm/mdp5: Configure PP_SYNC_HEIGHT to double the vtotal
+    - drm/msm/mdp5: Do not multiply vclk line count by 100
+    - drm/amdkfd: Fix cat debugfs hang_hws file causes system crash bug
+    - amdgpu: avoid incorrect %hu format string
+    - drm/amdgpu: fix NULL pointer dereference
+    - scsi: lpfc: Fix crash when a REG_RPI mailbox fails triggering a LOGO
+      response
+    - scsi: lpfc: Fix error handling for mailboxes completed in MBX_POLL mode
+    - scsi: lpfc: Remove unsupported mbox PORT_CAPABILITIES logic
+    - mfd: arizona: Fix rumtime PM imbalance on error
+    - scsi: libfc: Fix a format specifier
+    - s390/archrandom: add parameter check for s390_arch_random_generate
+    - ALSA: emu8000: Fix a use after free in snd_emu8000_create_mixer
+    - ALSA: hda/conexant: Re-order CX5066 quirk table entries
+    - ALSA: sb: Fix two use after free in snd_sb_qsound_build
+    - ALSA: usb-audio: Explicitly set up the clock selector
+    - ALSA: usb-audio: More constifications
+    - ALSA: usb-audio: Add dB range mapping for Sennheiser Communications Headset
+      PC 8
+    - ALSA: hda/realtek: GA503 use same quirks as GA401
+    - ALSA: hda/realtek: fix mic boost on Intel NUC 8
+    - ALSA: hda/realtek: fix static noise on ALC285 Lenovo laptops
+    - ALSA: hda/realtek: Add quirk for Intel Clevo PCx0Dx
+    - btrfs: fix race when picking most recent mod log operation for an old root
+    - arm64/vdso: Discard .note.gnu.property sections in vDSO
+    - Makefile: Move -Wno-unused-but-set-variable out of GCC only block
+    - virtiofs: fix memory leak in virtio_fs_probe()
+    - ubifs: Only check replay with inode type to judge if inode linked
+    - f2fs: fix to avoid out-of-bounds memory access
+    - mlxsw: spectrum_mr: Update egress RIF list before route's action
+    - openvswitch: fix stack OOB read while fragmenting IPv4 packets
+    - ACPI: GTDT: Don't corrupt interrupt mappings on watchdow probe failure
+    - NFS: Don't discard pNFS layout segments that are marked for return
+    - NFSv4: Don't discard segments marked for return in _pnfs_return_layout()
+    - Input: ili210x - add missing negation for touch indication on ili210x
+    - jffs2: Fix kasan slab-out-of-bounds problem
+    - powerpc/eeh: Fix EEH handling for hugepages in ioremap space.
+    - powerpc: fix EDEADLOCK redefinition error in uapi/asm/errno.h
+    - intel_th: pci: Add Alder Lake-M support
+    - tpm: efi: Use local variable for calculating final log size
+    - tpm: vtpm_proxy: Avoid reading host log when using a virtual device
+    - crypto: rng - fix crypto_rng_reset() refcounting when !CRYPTO_STATS
+    - md/raid1: properly indicate failure when ending a failed write request
+    - dm raid: fix inconclusive reshape layout on fast raid4/5/6 table reload
+      sequences
+    - fuse: fix write deadlock
+    - security: commoncap: fix -Wstringop-overread warning
+    - Fix misc new gcc warnings
+    - jffs2: check the validity of dstlen in jffs2_zlib_compress()
+    - Revert 337f13046ff0 ("futex: Allow FUTEX_CLOCK_REALTIME with FUTEX_WAIT op")
+    - x86/cpu: Initialize MSR_TSC_AUX if RDTSCP *or* RDPID is supported
+    - kbuild: update config_data.gz only when the content of .config is changed
+    - ext4: fix check to prevent false positive report of incorrect used inodes
+    - ext4: do not set SB_ACTIVE in ext4_orphan_cleanup()
+    - ext4: fix error code in ext4_commit_super
+    - media: dvbdev: Fix memory leak in dvb_media_device_free()
+    - media: dvb-usb: Fix use-after-free access
+    - media: dvb-usb: Fix memory leak at error in dvb_usb_device_init()
+    - media: staging/intel-ipu3: Fix memory leak in imu_fmt
+    - media: staging/intel-ipu3: Fix set_fmt error handling
+    - media: staging/intel-ipu3: Fix race condition during set_fmt
+    - usb: gadget: dummy_hcd: fix gpf in gadget_setup
+    - usb: gadget: Fix double free of device descriptor pointers
+    - usb: gadget/function/f_fs string table fix for multiple languages
+    - usb: dwc3: gadget: Fix START_TRANSFER link state check
+    - usb: dwc2: Fix session request interrupt handler
+    - tty: fix memory leak in vc_deallocate
+    - rsi: Use resume_noirq for SDIO
+    - tracing: Map all PIDs to command lines
+    - tracing: Restructure trace_clock_global() to never block
+    - dm persistent data: packed struct should have an aligned() attribute too
+    - dm space map common: fix division bug in sm_ll_find_free_block()
+    - dm integrity: fix missing goto in bitmap_flush_interval error handling
+    - dm rq: fix double free of blk_mq_tag_set in dev remove after table load
+      fails
+    - Linux 5.4.118
+
+  * Focal update: v5.4.117 upstream stable release (LP: #1928823)
+    - mips: Do not include hi and lo in clobber list for R6
+    - ACPI: tables: x86: Reserve memory occupied by ACPI tables
+    - ACPI: x86: Call acpi_boot_table_init() after acpi_table_upgrade()
+    - net: usb: ax88179_178a: initialize local variables before use
+    - igb: Enable RSS for Intel I211 Ethernet Controller
+    - iwlwifi: Fix softirq/hardirq disabling in iwl_pcie_enqueue_hcmd()
+    - bpf: Fix masking negation logic upon negative dst register
+    - bpf: Fix leakage of uninitialized bpf stack under speculation
+    - avoid __memcat_p link failure
+    - iwlwifi: Fix softirq/hardirq disabling in iwl_pcie_gen2_enqueue_hcmd()
+    - perf data: Fix error return code in perf_data__create_dir()
+    - perf ftrace: Fix access to pid in array when setting a pid filter
+    - ALSA: usb-audio: Add MIDI quirk for Vox ToneLab EX
+    - USB: Add reset-resume quirk for WD19's Realtek Hub
+    - platform/x86: thinkpad_acpi: Correct thermal sensor allocation
+    - scsi: ufs: Unlock on a couple error paths
+    - ovl: allow upperdir inside lowerdir
+    - perf/core: Fix unconditional security_locked_down() call
+    - vfio: Depend on MMU
+    - Linux 5.4.117
+
+  * r8152 tx status -71 (LP: #1922651) // Focal update: v5.4.117 upstream stable
+    release (LP: #1928823)
+    - USB: Add LPM quirk for Lenovo ThinkPad USB-C Dock Gen2 Ethernet
+
+  * Focal update: v5.4.116 upstream stable release (LP: #1928821)
+    - bpf: Move off_reg into sanitize_ptr_alu
+    - bpf: Ensure off_reg has no mixed signed bounds for all types
+    - bpf: Rework ptr_limit into alu_limit and add common error path
+    - bpf: Improve verifier error messages for users
+    - bpf: Refactor and streamline bounds check into helper
+    - bpf: Move sanitize_val_alu out of op switch
+    - bpf: Tighten speculative pointer arithmetic mask
+    - bpf: Update selftests to reflect new error states
+    - Linux 5.4.116
+
+  * Focal update: v5.4.115 upstream stable release (LP: #1927997)
+    - gpio: omap: Save and restore sysconfig
+    - pinctrl: lewisburg: Update number of pins in community
+    - arm64: dts: allwinner: Revert SD card CD GPIO for Pine64-LTS
+    - perf/x86/intel/uncore: Remove uncore extra PCI dev HSWEP_PCI_PCU_3
+    - perf/x86/kvm: Fix Broadwell Xeon stepping in isolation_ucodes[]
+    - perf auxtrace: Fix potential NULL pointer dereference
+    - HID: google: add don USB id
+    - HID: alps: fix error return code in alps_input_configured()
+    - HID: wacom: Assign boolean values to a bool variable
+    - ARM: dts: Fix swapped mmc order for omap3
+    - net: geneve: check skb is large enough for IPv4/IPv6 header
+    - s390/entry: save the caller of psw_idle
+    - xen-netback: Check for hotplug-status existence before watching
+    - cavium/liquidio: Fix duplicate argument
+    - csky: change a Kconfig symbol name to fix e1000 build error
+    - ia64: fix discontig.c section mismatches
+    - ia64: tools: remove duplicate definition of ia64_mf() on ia64
+    - x86/crash: Fix crash_setup_memmap_entries() out-of-bounds access
+    - net: hso: fix NULL-deref on disconnect regression
+    - USB: CDC-ACM: fix poison/unpoison imbalance
+    - Linux 5.4.115
+
+ -- Kleber Sacilotto de Souza <kleber.souza@canonical.com>  Fri, 28 May 2021 18:14:26 +0200
+
+linux (5.4.0-74.83) focal; urgency=medium
+
+  * focal/linux: 5.4.0-74.83 -proposed tracker (LP: #1927619)
+
+  * Introduce the 465 driver series, fabric-manager, and libnvidia-nscq
+    (LP: #1925522)
+    - debian/dkms-versions -- add NVIDIA 465 and migrate 450 to 460
+
+  * linux-image-5.0.0-35-generic breaks checkpointing of container
+    (LP: #1857257)
+    - SAUCE: overlayfs: fix incorrect mnt_id of files opened from map_files
+
+  * Enable CIFS GCM256 (LP: #1921916)
+    - smb3: add defines for new crypto algorithms
+    - smb3.1.1: add new module load parm require_gcm_256
+    - smb3.1.1: add new module load parm enable_gcm_256
+    - smb3.1.1: print warning if server does not support requested encryption type
+    - smb3.1.1: rename nonces used for GCM and CCM encryption
+    - smb3.1.1: set gcm256 when requested
+    - cifs: Adjust key sizes and key generation routines for AES256 encryption
+
+  * locking/qrwlock: Fix ordering in queued_write_lock_slowpath() (LP: #1926184)
+    - locking/qrwlock: Fix ordering in queued_write_lock_slowpath()
+
+  * [Ubuntu 21.04] net/mlx5: Fix HW spec violation configuring uplink
+    (LP: #1925452)
+    - net/mlx5: Fix HW spec violation configuring uplink
+
+  * Focal update: v5.4.114 upstream stable release (LP: #1926493)
+    - Revert "scsi: qla2xxx: Retry PLOGI on FC-NVMe PRLI failure"
+    - Revert "scsi: qla2xxx: Fix stuck login session using prli_pend_timer"
+    - scsi: qla2xxx: Dual FCP-NVMe target port support
+    - scsi: qla2xxx: Fix device connect issues in P2P configuration
+    - scsi: qla2xxx: Retry PLOGI on FC-NVMe PRLI failure
+    - scsi: qla2xxx: Add a shadow variable to hold disc_state history of fcport
+    - scsi: qla2xxx: Fix stuck login session using prli_pend_timer
+    - scsi: qla2xxx: Fix fabric scan hang
+    - net/sctp: fix race condition in sctp_destroy_sock
+    - Input: nspire-keypad - enable interrupts only when opened
+    - gpio: sysfs: Obey valid_mask
+    - dmaengine: dw: Make it dependent to HAS_IOMEM
+    - ARM: dts: Drop duplicate sha2md5_fck to fix clk_disable race
+    - ARM: dts: Fix moving mmc devices with aliases for omap4 & 5
+    - lockdep: Add a missing initialization hint to the "INFO: Trying to register
+      non-static key" message
+    - arc: kernel: Return -EFAULT if copy_to_user() fails
+    - ASoC: max98373: Added 30ms turn on/off time delay
+    - neighbour: Disregard DEAD dst in neigh_update
+    - ARM: keystone: fix integer overflow warning
+    - ARM: omap1: fix building with clang IAS
+    - drm/msm: Fix a5xx/a6xx timestamps
+    - ASoC: fsl_esai: Fix TDM slot setup for I2S mode
+    - scsi: scsi_transport_srp: Don't block target in SRP_PORT_LOST state
+    - net: ieee802154: stop dump llsec keys for monitors
+    - net: ieee802154: forbid monitor for add llsec key
+    - net: ieee802154: forbid monitor for del llsec key
+    - net: ieee802154: stop dump llsec devs for monitors
+    - net: ieee802154: forbid monitor for add llsec dev
+    - net: ieee802154: forbid monitor for del llsec dev
+    - net: ieee802154: stop dump llsec devkeys for monitors
+    - net: ieee802154: forbid monitor for add llsec devkey
+    - net: ieee802154: forbid monitor for del llsec devkey
+    - net: ieee802154: stop dump llsec seclevels for monitors
+    - net: ieee802154: forbid monitor for add llsec seclevel
+    - pcnet32: Use pci_resource_len to validate PCI resource
+    - mac80211: clear sta->fast_rx when STA removed from 4-addr VLAN
+    - virt_wifi: Return micros for BSS TSF values
+    - Input: s6sy761 - fix coordinate read bit shift
+    - Input: i8042 - fix Pegatron C15B ID entry
+    - HID: wacom: set EV_KEY and EV_ABS only for non-HID_GENERIC type of devices
+    - dm verity fec: fix misaligned RS roots IO
+    - readdir: make sure to verify directory entry for legacy interfaces too
+    - arm64: fix inline asm in load_unaligned_zeropad()
+    - arm64: alternatives: Move length validation in alternative_{insn, endif}
+    - vfio/pci: Add missing range check in vfio_pci_mmap
+    - riscv: Fix spelling mistake "SPARSEMEM" to "SPARSMEM"
+    - scsi: libsas: Reset num_scatter if libata marks qc as NODATA
+    - netfilter: conntrack: do not print icmpv6 as unknown via /proc
+    - libnvdimm/region: Fix nvdimm_has_flush() to handle ND_REGION_ASYNC
+    - netfilter: bridge: add pre_exit hooks for ebtable unregistration
+    - netfilter: arp_tables: add pre_exit hook for table unregister
+    - net: macb: fix the restore of cmp registers
+    - netfilter: nft_limit: avoid possible divide error in nft_limit_init
+    - net: davicom: Fix regulator not turned off on failed probe
+    - net: sit: Unregister catch-all devices
+    - net: ip6_tunnel: Unregister catch-all devices
+    - i40e: fix the panic when running bpf in xdpdrv mode
+    - ibmvnic: avoid calling napi_disable() twice
+    - ibmvnic: remove duplicate napi_schedule call in do_reset function
+    - ibmvnic: remove duplicate napi_schedule call in open function
+    - gro: ensure frag0 meets IP header alignment
+    - ARM: footbridge: fix PCI interrupt mapping
+    - arm64: dts: allwinner: Fix SD card CD GPIO for SOPine systems
+    - r8169: remove fiddling with the PCIe max read request size
+    - r8169: simplify setting PCI_EXP_DEVCTL_NOSNOOP_EN
+    - r8169: fix performance regression related to PCIe max read request size
+    - r8169: improve rtl_jumbo_config
+    - r8169: tweak max read request size for newer chips also in jumbo mtu mode
+    - r8169: don't advertise pause in jumbo mode
+    - ARM: 9071/1: uprobes: Don't hook on thumb instructions
+    - net: phy: marvell: fix detection of PHY on Topaz switches
+    - Linux 5.4.114
+
+  * Focal update: v5.4.113 upstream stable release (LP: #1926490)
+    - interconnect: core: fix error return code of icc_link_destroy()
+    - KVM: arm64: Hide system instruction access to Trace registers
+    - KVM: arm64: Disable guest access to trace filter controls
+    - drm/imx: imx-ldb: fix out of bounds array access warning
+    - gfs2: report "already frozen/thawed" errors
+    - drm/tegra: dc: Don't set PLL clock to 0Hz
+    - block: only update parent bi_status when bio fail
+    - radix tree test suite: Register the main thread with the RCU library
+    - idr test suite: Take RCU read lock in idr_find_test_1
+    - idr test suite: Create anchor before launching throbber
+    - riscv,entry: fix misaligned base for excp_vect_table
+    - block: don't ignore REQ_NOWAIT for direct IO
+    - netfilter: x_tables: fix compat match/target pad out-of-bound write
+    - driver core: Fix locking bug in deferred_probe_timeout_work_func()
+    - perf tools: Use %define api.pure full instead of %pure-parser
+    - perf tools: Use %zd for size_t printf formats on 32-bit
+    - perf map: Tighten snprintf() string precision to pass gcc check on some
+      32-bit arches
+    - xen/events: fix setting irq affinity
+    - Linux 5.4.113
+
+  * Focal update: v5.4.112 upstream stable release (LP: #1926489)
+    - counter: stm32-timer-cnt: fix ceiling miss-alignment with reload register
+    - ALSA: aloop: Fix initialization of controls
+    - ALSA: hda/realtek: Fix speaker amp setup on Acer Aspire E1
+    - ASoC: intel: atom: Stop advertising non working S24LE support
+    - nfc: fix refcount leak in llcp_sock_bind()
+    - nfc: fix refcount leak in llcp_sock_connect()
+    - nfc: fix memory leak in llcp_sock_connect()
+    - nfc: Avoid endless loops caused by repeated llcp_sock_connect()
+    - xen/evtchn: Change irq_info lock to raw_spinlock_t
+    - net: ipv6: check for validity before dereferencing cfg->fc_nlinfo.nlh
+    - net: dsa: lantiq_gswip: Let GSWIP automatically set the xMII clock
+    - drm/i915: Fix invalid access to ACPI _DSM objects
+    - gcov: re-fix clang-11+ support
+    - ia64: fix user_stack_pointer() for ptrace()
+    - nds32: flush_dcache_page: use page_mapping_file to avoid races with swapoff
+    - ocfs2: fix deadlock between setattr and dio_end_io_write
+    - fs: direct-io: fix missing sdio->boundary
+    - parisc: parisc-agp requires SBA IOMMU driver
+    - parisc: avoid a warning on u8 cast for cmpxchg on u8 pointers
+    - ARM: dts: turris-omnia: configure LED[2]/INTn pin as interrupt pin
+    - batman-adv: initialize "struct batadv_tvlv_tt_vlan_data"->reserved field
+    - ice: Increase control queue timeout
+    - ice: Fix for dereference of NULL pointer
+    - ice: Cleanup fltr list in case of allocation issues
+    - net: hso: fix null-ptr-deref during tty device unregistration
+    - ethernet/netronome/nfp: Fix a use after free in nfp_bpf_ctrl_msg_rx
+    - bpf, sockmap: Fix sk->prot unhash op reset
+    - net: ensure mac header is set in virtio_net_hdr_to_skb()
+    - i40e: Fix sparse warning: missing error code 'err'
+    - i40e: Fix sparse error: 'vsi->netdev' could be null
+    - net: sched: sch_teql: fix null-pointer dereference
+    - mac80211: fix TXQ AC confusion
+    - net: hsr: Reset MAC header for Tx path
+    - net-ipv6: bugfix - raw & sctp - switch to ipv6_can_nonlocal_bind()
+    - net: let skb_orphan_partial wake-up waiters.
+    - usbip: add sysfs_lock to synchronize sysfs code paths
+    - usbip: stub-dev synchronize sysfs code paths
+    - usbip: vudc synchronize sysfs code paths
+    - usbip: synchronize event handler with sysfs code paths
+    - i2c: turn recovery error on init to debug
+    - virtio_net: Add XDP meta data support
+    - net: dsa: lantiq_gswip: Don't use PHY auto polling
+    - net: dsa: lantiq_gswip: Configure all remaining GSWIP_MII_CFG bits
+    - xfrm: interface: fix ipv4 pmtu check to honor ip header df
+    - regulator: bd9571mwv: Fix AVS and DVFS voltage range
+    - net: xfrm: Localize sequence counter per network namespace
+    - esp: delete NETIF_F_SCTP_CRC bit from features for esp offload
+    - ASoC: SOF: Intel: hda: remove unnecessary parentheses
+    - ASoC: SOF: Intel: HDA: fix core status verification
+    - ASoC: wm8960: Fix wrong bclk and lrclk with pll enabled for some chips
+    - xfrm: Fix NULL pointer dereference on policy lookup
+    - i40e: Added Asym_Pause to supported link modes
+    - i40e: Fix kernel oops when i40e driver removes VF's
+    - hostfs: Use kasprintf() instead of fixed buffer formatting
+    - hostfs: fix memory handling in follow_link()
+    - amd-xgbe: Update DMA coherency values
+    - sch_red: fix off-by-one checks in red_check_params()
+    - arm64: dts: imx8mm/q: Fix pad control of SD1_DATA0
+    - can: bcm/raw: fix msg_namelen values depending on CAN_REQUIRED_SIZE
+    - gianfar: Handle error code at MAC address change
+    - cxgb4: avoid collecting SGE_QBASE regs during traffic
+    - net:tipc: Fix a double free in tipc_sk_mcast_rcv
+    - ARM: dts: imx6: pbab01: Set vmmc supply for both SD interfaces
+    - net/ncsi: Avoid channel_monitor hrtimer deadlock
+    - nfp: flower: ignore duplicate merge hints from FW
+    - net: phy: broadcom: Only advertise EEE for supported modes
+    - ASoC: sunxi: sun4i-codec: fill ASoC card owner
+    - net/mlx5e: Fix ethtool indication of connector type
+    - net/mlx5: Don't request more than supported EQs
+    - net/rds: Fix a use after free in rds_message_map_pages
+    - soc/fsl: qbman: fix conflicting alignment attributes
+    - i40e: Fix display statistics for veb_tc
+    - drm/msm: Set drvdata to NULL when msm_drm_init() fails
+    - net: udp: Add support for getsockopt(..., ..., UDP_GRO, ..., ...);
+    - scsi: ufs: Fix irq return code
+    - scsi: ufs: Avoid busy-waiting by eliminating tag conflicts
+    - scsi: ufs: Use blk_{get,put}_request() to allocate and free TMFs
+    - scsi: ufs: core: Fix task management request completion timeout
+    - scsi: ufs: core: Fix wrong Task Tag used in task management request UPIUs
+    - net: macb: restore cmp registers on resume path
+    - clk: fix invalid usage of list cursor in register
+    - clk: fix invalid usage of list cursor in unregister
+    - workqueue: Move the position of debug_work_activate() in __queue_work()
+    - s390/cpcmd: fix inline assembly register clobbering
+    - perf inject: Fix repipe usage
+    - net: openvswitch: conntrack: simplify the return expression of
+      ovs_ct_limit_get_default_limit()
+    - openvswitch: fix send of uninitialized stack memory in ct limit reply
+    - net: hns3: clear VF down state bit before request link status
+    - net/mlx5: Fix placement of log_max_flow_counter
+    - net/mlx5: Fix PBMC register mapping
+    - RDMA/cxgb4: check for ipv6 address properly while destroying listener
+    - RDMA/addr: Be strict with gid size
+    - RAS/CEC: Correct ce_add_elem()'s returned values
+    - clk: socfpga: fix iomem pointer cast on 64-bit
+    - dt-bindings: net: ethernet-controller: fix typo in NVMEM
+    - net: sched: bump refcount for new action in ACT replace mode
+    - cfg80211: remove WARN_ON() in cfg80211_sme_connect
+    - net: tun: set tun->dev->addr_len during TUNSETLINK processing
+    - drivers: net: fix memory leak in atusb_probe
+    - drivers: net: fix memory leak in peak_usb_create_dev
+    - net: mac802154: Fix general protection fault
+    - net: ieee802154: nl-mac: fix check on panid
+    - net: ieee802154: fix nl802154 del llsec key
+    - net: ieee802154: fix nl802154 del llsec dev
+    - net: ieee802154: fix nl802154 add llsec key
+    - net: ieee802154: fix nl802154 del llsec devkey
+    - net: ieee802154: forbid monitor for set llsec params
+    - net: ieee802154: forbid monitor for del llsec seclevel
+    - net: ieee802154: stop dump llsec params for monitors
+    - Linux 5.4.112
+
+  * crash utility fails on arm64 with  cannot determine VA_BITS_ACTUAL
+    (LP: #1919275)
+    - arm64/crash_core: Export TCR_EL1.T1SZ in vmcoreinfo
+
+  * Focal update: v5.4.111 upstream stable release (LP: #1923874)
+    - ARM: dts: am33xx: add aliases for mmc interfaces
+    - bus: ti-sysc: Fix warning on unbind if reset is not deasserted
+    - platform/x86: intel-hid: Support Lenovo ThinkPad X1 Tablet Gen 2
+    - bpf, x86: Use kvmalloc_array instead kmalloc_array in bpf_jit_comp
+    - net/mlx5e: Enforce minimum value check for ICOSQ size
+    - net: pxa168_eth: Fix a potential data race in pxa168_eth_remove
+    - mISDN: fix crash in fritzpci
+    - mac80211: choose first enabled channel for monitor
+    - drm/msm/adreno: a5xx_power: Don't apply A540 lm_setup to other GPUs
+    - drm/msm: Ratelimit invalid-fence message
+    - netfilter: conntrack: Fix gre tunneling over ipv6
+    - platform/x86: thinkpad_acpi: Allow the FnLock LED to change state
+    - x86/build: Turn off -fcf-protection for realmode targets
+    - scsi: target: pscsi: Clean up after failure in pscsi_map_sg()
+    - ia64: mca: allocate early mca with GFP_ATOMIC
+    - ia64: fix format strings for err_inject
+    - cifs: revalidate mapping when we open files for SMB1 POSIX
+    - cifs: Silently ignore unknown oplock break handle
+    - nvme-mpath: replace direct_make_request with generic_make_request
+    - init/Kconfig: make COMPILE_TEST depend on !S390
+    - init/Kconfig: make COMPILE_TEST depend on HAS_IOMEM
+    - Linux 5.4.111
+
+  * Focal update: v5.4.110 upstream stable release (LP: #1923869)
+    - selinux: vsock: Set SID for socket returned by accept()
+    - ipv6: weaken the v4mapped source check
+    - modsign: print module name along with error message
+    - module: merge repetitive strings in module_sig_check()
+    - module: avoid *goto*s in module_sig_check()
+    - module: harden ELF info handling
+    - ext4: shrink race window in ext4_should_retry_alloc()
+    - ext4: fix bh ref count on error paths
+    - fs: nfsd: fix kconfig dependency warning for NFSD_V4
+    - rpc: fix NULL dereference on kmalloc failure
+    - iomap: Fix negative assignment to unsigned sis->pages in
+      iomap_swapfile_activate
+    - ASoC: rt5640: Fix dac- and adc- vol-tlv values being off by a factor of 10
+    - ASoC: rt5651: Fix dac- and adc- vol-tlv values being off by a factor of 10
+    - ASoC: sgtl5000: set DAP_AVC_CTRL register to correct default value on probe
+    - ASoC: es8316: Simplify adc_pga_gain_tlv table
+    - ASoC: cs42l42: Fix Bitclock polarity inversion
+    - ASoC: cs42l42: Fix channel width support
+    - ASoC: cs42l42: Fix mixer volume control
+    - ASoC: cs42l42: Always wait at least 3ms after reset
+    - NFSD: fix error handling in NFSv4.0 callbacks
+    - powerpc: Force inlining of cpu_has_feature() to avoid build failure
+    - vhost: Fix vhost_vq_reset()
+    - scsi: st: Fix a use after free in st_open()
+    - scsi: qla2xxx: Fix broken #endif placement
+    - staging: comedi: cb_pcidas: fix request_irq() warn
+    - staging: comedi: cb_pcidas64: fix request_irq() warn
+    - ASoC: rt5659: Update MCLK rate in set_sysclk()
+    - thermal/core: Add NULL pointer check before using cooling device stats
+    - locking/ww_mutex: Simplify use_ww_ctx & ww_ctx handling
+    - ext4: do not iput inode under running transaction in ext4_rename()
+    - net: mvpp2: fix interrupt mask/unmask skip condition
+    - flow_dissector: fix TTL and TOS dissection on IPv4 fragments
+    - can: dev: move driver related infrastructure into separate subdir
+    - net: introduce CAN specific pointer in the struct net_device
+    - can: tcan4x5x: fix max register value
+    - brcmfmac: clear EAP/association status bits on linkdown events
+    - ath10k: hold RCU lock when calling ieee80211_find_sta_by_ifaddr()
+    - net: ethernet: aquantia: Handle error cleanup of start on open
+    - appletalk: Fix skb allocation size in loopback case
+    - net: wan/lmc: unregister device when no matching device is found
+    - bpf: Remove MTU check in __bpf_skb_max_len
+    - ALSA: usb-audio: Apply sample rate quirk to Logitech Connect
+    - ALSA: hda: Re-add dropped snd_poewr_change_state() calls
+    - ALSA: hda: Add missing sanity checks in PM prepare/complete callbacks
+    - ALSA: hda/realtek: fix a determine_headset_type issue for a Dell AIO
+    - ALSA: hda/realtek: call alc_update_headset_mode() in hp_automute_hook
+    - xtensa: move coprocessor_flush to the .text section
+    - PM: runtime: Fix race getting/putting suppliers at probe
+    - PM: runtime: Fix ordering in pm_runtime_get_suppliers()
+    - tracing: Fix stack trace event size
+    - mm: fix race by making init_zero_pfn() early_initcall
+    - drm/amdgpu: fix offset calculation in amdgpu_vm_bo_clear_mappings()
+    - drm/amdgpu: check alignment on CPU page for bo map
+    - reiserfs: update reiserfs_xattrs_initialized() condition
+    - vfio/nvlink: Add missing SPAPR_TCE_IOMMU depends
+    - pinctrl: rockchip: fix restore error in resume
+    - extcon: Add stubs for extcon_register_notifier_all() functions
+    - extcon: Fix error handling in extcon_dev_register
+    - firewire: nosy: Fix a use-after-free bug in nosy_ioctl()
+    - usbip: vhci_hcd fix shift out-of-bounds in vhci_hub_control()
+    - USB: quirks: ignore remote wake-up on Fibocom L850-GL LTE modem
+    - usb: musb: Fix suspend with devices connected for a64
+    - usb: xhci-mtk: fix broken streams issue on 0.96 xHCI
+    - cdc-acm: fix BREAK rx code path adding necessary calls
+    - USB: cdc-acm: untangle a circular dependency between callback and softint
+    - USB: cdc-acm: downgrade message to debug
+    - USB: cdc-acm: fix double free on probe failure
+    - USB: cdc-acm: fix use-after-free after probe failure
+    - usb: gadget: udc: amd5536udc_pci fix null-ptr-dereference
+    - usb: dwc2: Fix HPRT0.PrtSusp bit setting for HiKey 960 board.
+    - usb: dwc2: Prevent core suspend when port connection flag is 0
+    - staging: rtl8192e: Fix incorrect source in memcpy()
+    - staging: rtl8192e: Change state information from u16 to u8
+    - drivers: video: fbcon: fix NULL dereference in fbcon_cursor()
+    - Linux 5.4.110
+
+  * Focal update: v5.4.109 upstream stable release (LP: #1923220)
+    - hugetlbfs: hugetlb_fault_mutex_hash() cleanup
+    - net: fec: ptp: avoid register access when ipg clock is disabled
+    - powerpc/4xx: Fix build errors from mfdcr()
+    - atm: eni: dont release is never initialized
+    - atm: lanai: dont run lanai_dev_close if not open
+    - Revert "r8152: adjust the settings about MAC clock speed down for RTL8153"
+    - ALSA: hda: ignore invalid NHLT table
+    - ixgbe: Fix memleak in ixgbe_configure_clsu32
+    - net: tehuti: fix error return code in bdx_probe()
+    - net: intel: iavf: fix error return code of iavf_init_get_resources()
+    - sun/niu: fix wrong RXMAC_BC_FRM_CNT_COUNT count
+    - gianfar: fix jumbo packets+napi+rx overrun crash
+    - cifs: ask for more credit on async read/write code paths
+    - cpufreq: blacklist Arm Vexpress platforms in cpufreq-dt-platdev
+    - gpiolib: acpi: Add missing IRQF_ONESHOT
+    - nfs: fix PNFS_FLEXFILE_LAYOUT Kconfig default
+    - NFS: Correct size calculation for create reply length
+    - net: hisilicon: hns: fix error return code of hns_nic_clear_all_rx_fetch()
+    - net: wan: fix error return code of uhdlc_init()
+    - net: davicom: Use platform_get_irq_optional()
+    - atm: uPD98402: fix incorrect allocation
+    - atm: idt77252: fix null-ptr-dereference
+    - cifs: change noisy error message to FYI
+    - irqchip/ingenic: Add support for the JZ4760
+    - sparc64: Fix opcode filtering in handling of no fault loads
+    - habanalabs: Call put_pid() when releasing control device
+    - u64_stats,lockdep: Fix u64_stats_init() vs lockdep
+    - regulator: qcom-rpmh: Correct the pmic5_hfsmps515 buck
+    - drm/amd/display: Revert dram_clock_change_latency for DCN2.1
+    - drm/amdgpu: fb BO should be ttm_bo_type_device
+    - drm/radeon: fix AGP dependency
+    - nvme: add NVME_REQ_CANCELLED flag in nvme_cancel_request()
+    - nvme-fc: return NVME_SC_HOST_ABORTED_CMD when a command has been aborted
+    - nvme-pci: add the DISABLE_WRITE_ZEROES quirk for a Samsung PM1725a
+    - nfs: we don't support removing system.nfs4_acl
+    - block: Suppress uevent for hidden device when removed
+    - ia64: fix ia64_syscall_get_set_arguments() for break-based syscalls
+    - ia64: fix ptrace(PTRACE_SYSCALL_INFO_EXIT) sign
+    - netsec: restore phy power state after controller reset
+    - platform/x86: intel-vbtn: Stop reporting SW_DOCK events
+    - squashfs: fix inode lookup sanity checks
+    - squashfs: fix xattr id and id lookup sanity checks
+    - kasan: fix per-page tags for non-page_alloc pages
+    - gcov: fix clang-11+ support
+    - ACPI: video: Add missing callback back for Sony VPCEH3U1E
+    - arm64: dts: ls1046a: mark crypto engine dma coherent
+    - arm64: dts: ls1012a: mark crypto engine dma coherent
+    - arm64: dts: ls1043a: mark crypto engine dma coherent
+    - ARM: dts: at91-sama5d27_som1: fix phy address to 7
+    - integrity: double check iint_cache was initialized
+    - dm verity: fix DM_VERITY_OPTS_MAX value
+    - dm ioctl: fix out of bounds array access when no devices
+    - bus: omap_l3_noc: mark l3 irqs as IRQF_NO_THREAD
+    - veth: Store queue_mapping independently of XDP prog presence
+    - libbpf: Fix INSTALL flag order
+    - net/mlx5e: Don't match on Geneve options in case option masks are all zero
+    - ipv6: fix suspecious RCU usage warning
+    - macvlan: macvlan_count_rx() needs to be aware of preemption
+    - net: sched: validate stab values
+    - net: dsa: bcm_sf2: Qualify phydev->dev_flags based on port
+    - igc: Fix Pause Frame Advertising
+    - igc: Fix Supported Pause Frame Link Setting
+    - e1000e: add rtnl_lock() to e1000_reset_task
+    - e1000e: Fix error handling in e1000_set_d0_lplu_state_82571
+    - net/qlcnic: Fix a use after free in qlcnic_83xx_get_minidump_template
+    - ftgmac100: Restart MAC HW once
+    - selftests/bpf: Set gopt opt_class to 0 if get tunnel opt failed
+    - netfilter: ctnetlink: fix dump of the expect mask attribute
+    - tcp: relookup sock for RST+ACK packets handled by obsolete req sock
+    - can: peak_usb: add forgotten supported devices
+    - can: flexcan: flexcan_chip_freeze(): fix chip freeze for missing bitrate
+    - can: kvaser_pciefd: Always disable bus load reporting
+    - can: c_can_pci: c_can_pci_remove(): fix use-after-free
+    - can: c_can: move runtime PM enable/disable to c_can_platform
+    - can: m_can: m_can_do_rx_poll(): fix extraneous msg loss warning
+    - can: m_can: m_can_rx_peripheral(): fix RX being blocked by errors
+    - mac80211: fix rate mask reset
+    - nfp: flower: fix pre_tun mask id allocation
+    - libbpf: Use SOCK_CLOEXEC when opening the netlink socket
+    - octeontx2-af: Fix irq free in rvu teardown
+    - octeontx2-af: fix infinite loop in unmapping NPC counter
+    - net: cdc-phonet: fix data-interface release on probe failure
+    - r8152: limit the RX buffer size of RTL8153A for USB 2.0
+    - net: stmmac: dwmac-sun8i: Provide TX and RX fifo sizes
+    - selftests: forwarding: vxlan_bridge_1d: Fix vxlan ecn decapsulate value
+    - libbpf: Fix BTF dump of pointer-to-array-of-struct
+    - drm/msm: fix shutdown hook in case GPU components failed to bind
+    - arm64: kdump: update ppos when reading elfcorehdr
+    - PM: runtime: Defer suspending suppliers
+    - net/mlx5e: Fix error path for ethtool set-priv-flag
+    - PM: EM: postpone creating the debugfs dir till fs_initcall
+    - RDMA/cxgb4: Fix adapter LE hash errors while destroying ipv6 listening
+      server
+    - bpf: Don't do bpf_cgroup_storage_set() for kuprobe/tp programs
+    - ACPI: scan: Rearrange memory allocation in acpi_device_add()
+    - ACPI: scan: Use unique number for instance_no
+    - perf auxtrace: Fix auxtrace queue conflict
+    - block: recalculate segment count for multi-segment discards correctly
+    - scsi: Revert "qla2xxx: Make sure that aborted commands are freed"
+    - scsi: qedi: Fix error return code of qedi_alloc_global_queues()
+    - scsi: mpt3sas: Fix error return code of mpt3sas_base_attach()
+    - locking/mutex: Fix non debug version of mutex_lock_io_nested()
+    - x86/mem_encrypt: Correct physical address calculation in __set_clr_pte_enc()
+    - can: dev: Move device back to init netns on owning netns delete
+    - net: dsa: b53: VLAN filtering is global to all users
+    - net: qrtr: fix a kernel-infoleak in qrtr_recvmsg()
+    - mac80211: fix double free in ibss_leave
+    - ext4: add reclaim checks to xattr code
+    - can: peak_usb: Revert "can: peak_usb: add forgotten supported devices"
+    - xen-blkback: don't leak persistent grants from xen_blkbk_map()
+    - Linux 5.4.109
+
+  * Focal update: v5.4.108 upstream stable release (LP: #1923214)
+    - ASoC: ak4458: Add MODULE_DEVICE_TABLE
+    - ASoC: ak5558: Add MODULE_DEVICE_TABLE
+    - ALSA: dice: fix null pointer dereference when node is disconnected
+    - ALSA: hda/realtek: apply pin quirk for XiaomiNotebook Pro
+    - ALSA: hda: generic: Fix the micmute led init state
+    - ALSA: hda/realtek: Apply headset-mic quirks for Xiaomi Redmibook Air
+    - Revert "PM: runtime: Update device status before letting suppliers suspend"
+    - ARM: 9030/1: entry: omit FP emulation for UND exceptions taken in kernel
+      mode
+    - ARM: 9044/1: vfp: use undef hook for VFP support detection
+    - btrfs: fix race when cloning extent buffer during rewind of an old root
+    - btrfs: fix slab cache flags for free space tree bitmap
+    - ASoC: fsl_ssi: Fix TDM slot setup for I2S mode
+    - ASoC: SOF: Intel: unregister DMIC device on probe error
+    - ASoC: SOF: intel: fix wrong poll bits in dsp power down
+    - ASoC: simple-card-utils: Do not handle device clock
+    - afs: Stop listxattr() from listing "afs.*" attributes
+    - nvme: fix Write Zeroes limitations
+    - nvme-tcp: fix possible hang when failing to set io queues
+    - nvme-tcp: fix a NULL deref when receiving a 0-length r2t PDU
+    - nvmet: don't check iosqes,iocqes for discovery controllers
+    - nfsd: Don't keep looking up unhashed files in the nfsd file cache
+    - NFSD: Repair misuse of sv_lock in 5.10.16-rt30.
+    - svcrdma: disable timeouts on rdma backchannel
+    - vfio: IOMMU_API should be selected
+    - sunrpc: fix refcount leak for rpc auth modules
+    - net/qrtr: fix __netdev_alloc_skb call
+    - kbuild: Fix <linux/version.h> for empty SUBLEVEL or PATCHLEVEL again
+    - riscv: Correct SPARSEMEM configuration
+    - scsi: lpfc: Fix some error codes in debugfs
+    - scsi: myrs: Fix a double free in myrs_cleanup()
+    - counter: stm32-timer-cnt: Report count function when SLAVE_MODE_DISABLED
+    - nvme-rdma: fix possible hang when failing to set io queues
+    - usb-storage: Add quirk to defeat Kindle's automatic unload
+    - usbip: Fix incorrect double assignment to udc->ud.tcp_rx
+    - USB: replace hardcode maximum usb string length by definition
+    - usb: gadget: configfs: Fix KASAN use-after-free
+    - usb: typec: tcpm: Invoke power_supply_changed for tcpm-source-psy-
+    - iio:adc:stm32-adc: Add HAS_IOMEM dependency
+    - iio:adc:qcom-spmi-vadc: add default scale to LR_MUX2_BAT_ID channel
+    - iio: adis16400: Fix an error code in adis16400_initial_setup()
+    - iio: gyro: mpu3050: Fix error handling in mpu3050_trigger_handler
+    - iio: adc: ad7949: fix wrong ADC result due to incorrect bit mask
+    - iio: hid-sensor-humidity: Fix alignment issue of timestamp channel
+    - iio: hid-sensor-prox: Fix scale not correct issue
+    - iio: hid-sensor-temperature: Fix issues of timestamp channel
+    - counter: stm32-timer-cnt: fix ceiling write max value
+    - PCI: rpadlpar: Fix potential drc_name corruption in store functions
+    - perf/x86/intel: Fix a crash caused by zero PEBS status
+    - x86/ioapic: Ignore IRQ2 again
+    - kernel, fs: Introduce and use set_restart_fn() and arch_set_restart_data()
+    - x86: Move TS_COMPAT back to asm/thread_info.h
+    - x86: Introduce TS_COMPAT_RESTART to fix get_nr_restart_syscall()
+    - ext4: find old entry again if failed to rename whiteout
+    - ext4: do not try to set xattr into ea_inode if value is empty
+    - ext4: fix potential error in ext4_do_update_inode
+    - efi: use 32-bit alignment for efi_guid_t literals
+    - firmware/efi: Fix a use after bug in efi_mem_reserve_persistent
+    - genirq: Disable interrupts for force threaded handlers
+    - x86/apic/of: Fix CPU devicetree-node lookups
+    - cifs: Fix preauth hash corruption
+    - Linux 5.4.108
+
+  * Focal update: v5.4.107 upstream stable release (LP: #1923210)
+    - KVM: arm64: nvhe: Save the SPE context early
+    - btrfs: scrub: Don't check free space before marking a block group RO
+    - drm/i915/gvt: Set SNOOP for PAT3 on BXT/APL to workaround GPU BB hang
+    - drm/i915/gvt: Fix mmio handler break on BXT/APL.
+    - drm/i915/gvt: Fix virtual display setup for BXT/APL
+    - drm/i915/gvt: Fix port number for BDW on EDID region setup
+    - drm/i915/gvt: Fix vfio_edid issue for BXT/APL
+    - fuse: fix live lock in fuse_iget()
+    - crypto: x86 - Regularize glue function prototypes
+    - crypto: aesni - Use TEST %reg,%reg instead of CMP $0,%reg
+    - crypto: x86/aes-ni-xts - use direct calls to and 4-way stride
+    - net: dsa: tag_mtk: fix 802.1ad VLAN egress
+    - net: dsa: b53: Support setting learning on port
+    - Linux 5.4.107
+
+ -- Kelsey Skunberg <kelsey.skunberg@canonical.com>  Fri, 07 May 2021 18:45:05 -0600
+
+linux (5.4.0-73.82) focal; urgency=medium
+
+  * focal/linux: 5.4.0-73.82 -proposed tracker (LP: #1923781)
+
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+
+  * CIFS DFS entries not accessible with 5.4.0-71.74-generic (LP: #1923670)
+    - Revert "cifs: Set CIFS_MOUNT_USE_PREFIX_PATH flag on setting
+      cifs_sb->prepath."
+
+  * CVE-2021-29650
+    - Revert "netfilter: x_tables: Update remaining dereference to RCU"
+    - Revert "netfilter: x_tables: Switch synchronization to RCU"
+    - netfilter: x_tables: Use correct memory barriers.
+
+  * LRMv4: switch to signing nvidia modules via the Ubuntu Modules signing key
+    (LP: #1918134)
+    - [Packaging] dkms-build{,--nvidia-N} sync back from LRMv4
+
+  * 5.4 kernel: when iommu is on crashdump fails (LP: #1922738)
+    - iommu/vt-d: Refactor find_domain() helper
+    - iommu/vt-d: Add attach_deferred() helper
+    - iommu/vt-d: Move deferred device attachment into helper function
+    - iommu/vt-d: Do deferred attachment in iommu_need_mapping()
+    - iommu/vt-d: Remove deferred_attach_domain()
+    - iommu/vt-d: Simplify check in identity_mapping()
+
+  * Backport mlx5e fix for tunnel offload (LP: #1921769)
+    - net/mlx5e: Check tunnel offload is required before setting SWP
+
+  * Bcache bypasse writeback on caching device with fragmentation (LP: #1900438)
+    - bcache: consider the fragmentation when update the writeback rate
+
+  * Fix implicit declaration warnings for kselftests/memfd test on newer
+    releases (LP: #1910323)
+    - selftests/memfd: Fix implicit declaration warnings
+
+  * net/mlx5e: Add missing capability check for uplink follow (LP: #1921104)
+    - net/mlx5e: Add missing capability check for uplink follow
+
+  * [UBUNUT 21.04] s390/vtime: fix increased steal time accounting
+    (LP: #1921498)
+    - s390/vtime: fix increased steal time accounting
+
+  * Mute/Mic-mute LEDs are not work on HP 850/840/440 G8 Laptops (LP: #1920030)
+    - ALSA: hda/realtek: fix mute/micmute LEDs for HP 840 G8
+    - ALSA: hda/realtek: fix mute/micmute LEDs for HP 440 G8
+    - ALSA: hda/realtek: fix mute/micmute LEDs for HP 850 G8
+
+  * Focal update: v5.4.106 upstream stable release (LP: #1920246)
+    - uapi: nfnetlink_cthelper.h: fix userspace compilation error
+    - powerpc/pseries: Don't enforce MSI affinity with kdump
+    - ath9k: fix transmitting to stations in dynamic SMPS mode
+    - net: Fix gro aggregation for udp encaps with zero csum
+    - net: check if protocol extracted by virtio_net_hdr_set_proto is correct
+    - net: avoid infinite loop in mpls_gso_segment when mpls_hlen == 0
+    - sh_eth: fix TRSCER mask for SH771x
+    - can: skb: can_skb_set_owner(): fix ref counting if socket was closed before
+      setting skb ownership
+    - can: flexcan: assert FRZ bit in flexcan_chip_freeze()
+    - can: flexcan: enable RX FIFO after FRZ/HALT valid
+    - can: flexcan: invoke flexcan_chip_freeze() to enter freeze mode
+    - can: tcan4x5x: tcan4x5x_init(): fix initialization - clear MRAM before
+      entering Normal Mode
+    - tcp: add sanity tests to TCP_QUEUE_SEQ
+    - netfilter: nf_nat: undo erroneous tcp edemux lookup
+    - netfilter: x_tables: gpf inside xt_find_revision()
+    - selftests/bpf: No need to drop the packet when there is no geneve opt
+    - selftests/bpf: Mask bpf_csum_diff() return value to 16 bits in test_verifier
+    - samples, bpf: Add missing munmap in xdpsock
+    - ibmvnic: always store valid MAC address
+    - mt76: dma: do not report truncated frames to mac80211
+    - powerpc/603: Fix protection of user pages mapped with PROT_NONE
+    - mount: fix mounting of detached mounts onto targets that reside on shared
+      mounts
+    - cifs: return proper error code in statfs(2)
+    - Revert "mm, slub: consider rest of partial list if acquire_slab() fails"
+    - net: enetc: don't overwrite the RSS indirection table when initializing
+    - net/mlx4_en: update moderation when config reset
+    - net: stmmac: fix incorrect DMA channel intr enable setting of EQoS v4.10
+    - nexthop: Do not flush blackhole nexthops when loopback goes down
+    - net: sched: avoid duplicates in classes dump
+    - net: usb: qmi_wwan: allow qmimux add/del with master up
+    - netdevsim: init u64 stats for 32bit hardware
+    - cipso,calipso: resolve a number of problems with the DOI refcounts
+    - net: lapbether: Remove netif_start_queue / netif_stop_queue
+    - net: davicom: Fix regulator not turned off on failed probe
+    - net: davicom: Fix regulator not turned off on driver removal
+    - net: qrtr: fix error return code of qrtr_sendmsg()
+    - ixgbe: fail to create xfrm offload of IPsec tunnel mode SA
+    - net: stmmac: stop each tx channel independently
+    - net: stmmac: fix watchdog timeout during suspend/resume stress test
+    - selftests: forwarding: Fix race condition in mirror installation
+    - perf traceevent: Ensure read cmdlines are null terminated.
+    - net: hns3: fix query vlan mask value error for flow director
+    - net: hns3: fix bug when calculating the TCAM table info
+    - s390/cio: return -EFAULT if copy_to_user() fails again
+    - bnxt_en: reliably allocate IRQ table on reset to avoid crash
+    - drm/compat: Clear bounce structures
+    - drm/shmem-helper: Check for purged buffers in fault handler
+    - drm/shmem-helper: Don't remove the offset in vm_area_struct pgoff
+    - drm: meson_drv add shutdown function
+    - s390/cio: return -EFAULT if copy_to_user() fails
+    - s390/crypto: return -EFAULT if copy_to_user() fails
+    - qxl: Fix uninitialised struct field head.surface_id
+    - sh_eth: fix TRSCER mask for R7S9210
+    - media: usbtv: Fix deadlock on suspend
+    - media: v4l: vsp1: Fix uif null pointer access
+    - media: v4l: vsp1: Fix bru null pointer access
+    - media: rc: compile rc-cec.c into rc-core
+    - [Config] update abi for rc-cec
+    - net: hns3: fix error mask definition of flow director
+    - net: enetc: initialize RFS/RSS memories for unused ports too
+    - net: phy: fix save wrong speed and duplex problem if autoneg is on
+    - i2c: rcar: faster irq code to minimize HW race condition
+    - i2c: rcar: optimize cacheline to minimize HW race condition
+    - udf: fix silent AED tagLocation corruption
+    - mmc: mxs-mmc: Fix a resource leak in an error handling path in
+      'mxs_mmc_probe()'
+    - mmc: mediatek: fix race condition between msdc_request_timeout and irq
+    - Platform: OLPC: Fix probe error handling
+    - powerpc/pci: Add ppc_md.discover_phbs()
+    - spi: stm32: make spurious and overrun interrupts visible
+    - powerpc: improve handling of unrecoverable system reset
+    - powerpc/perf: Record counter overflow always if SAMPLE_IP is unset
+    - HID: logitech-dj: add support for the new lightspeed connection iteration
+    - powerpc/64: Fix stack trace not displaying final frame
+    - iommu/amd: Fix performance counter initialization
+    - sparc32: Limit memblock allocation to low memory
+    - sparc64: Use arch_validate_flags() to validate ADI flag
+    - Input: applespi - don't wait for responses to commands indefinitely.
+    - PCI: xgene-msi: Fix race in installing chained irq handler
+    - PCI: mediatek: Add missing of_node_put() to fix reference leak
+    - kbuild: clamp SUBLEVEL to 255
+    - PCI: Fix pci_register_io_range() memory leak
+    - i40e: Fix memory leak in i40e_probe
+    - s390/smp: __smp_rescan_cpus() - move cpumask away from stack
+    - sysctl.c: fix underflow value setting risk in vm_table
+    - scsi: libiscsi: Fix iscsi_prep_scsi_cmd_pdu() error handling
+    - scsi: target: core: Add cmd length set before cmd complete
+    - scsi: target: core: Prevent underflow for service actions
+    - ALSA: usb: Add Plantronics C320-M USB ctrl msg delay quirk
+    - ALSA: hda/hdmi: Cancel pending works before suspend
+    - ALSA: hda/ca0132: Add Sound BlasterX AE-5 Plus support
+    - ALSA: hda: Drop the BATCH workaround for AMD controllers
+    - ALSA: hda: Flush pending unsolicited events before suspend
+    - ALSA: hda: Avoid spurious unsol event handling during S3/S4
+    - ALSA: usb-audio: Fix "cannot get freq eq" errors on Dell AE515 sound bar
+    - ALSA: usb-audio: Apply the control quirk to Plantronics headsets
+    - Revert 95ebabde382c ("capabilities: Don't allow writing ambiguous v3 file
+      capabilities")
+    - arm64: kasan: fix page_alloc tagging with DEBUG_VIRTUAL
+    - s390/dasd: fix hanging DASD driver unbind
+    - s390/dasd: fix hanging IO request during DASD driver unbind
+    - software node: Fix node registration
+    - mmc: core: Fix partition switch time for eMMC
+    - mmc: cqhci: Fix random crash when remove mmc module/card
+    - Goodix Fingerprint device is not a modem
+    - USB: gadget: u_ether: Fix a configfs return code
+    - usb: gadget: f_uac2: always increase endpoint max_packet_size by one audio
+      slot
+    - usb: gadget: f_uac1: stop playback on function disable
+    - usb: dwc3: qcom: Add missing DWC3 OF node refcount decrement
+    - usb: dwc3: qcom: Honor wakeup enabled/disabled state
+    - USB: usblp: fix a hang in poll() if disconnected
+    - usb: renesas_usbhs: Clear PIPECFG for re-enabling pipe with other EPNUM
+    - usb: xhci: do not perform Soft Retry for some xHCI hosts
+    - xhci: Improve detection of device initiated wake signal.
+    - usb: xhci: Fix ASMedia ASM1042A and ASM3242 DMA addressing
+    - xhci: Fix repeated xhci wake after suspend due to uncleared internal wake
+      state
+    - USB: serial: io_edgeport: fix memory leak in edge_startup
+    - USB: serial: ch341: add new Product ID
+    - USB: serial: cp210x: add ID for Acuity Brands nLight Air Adapter
+    - USB: serial: cp210x: add some more GE USB IDs
+    - usbip: fix stub_dev to check for stream socket
+    - usbip: fix vhci_hcd to check for stream socket
+    - usbip: fix vudc to check for stream socket
+    - usbip: fix stub_dev usbip_sockfd_store() races leading to gpf
+    - usbip: fix vhci_hcd attach_store() races leading to gpf
+    - usbip: fix vudc usbip_sockfd_store races leading to gpf
+    - misc/pvpanic: Export module FDT device table
+    - misc: fastrpc: restrict user apps from sending kernel RPC messages
+    - staging: rtl8192u: fix ->ssid overflow in r8192_wx_set_scan()
+    - staging: rtl8188eu: prevent ->ssid overflow in rtw_wx_set_scan()
+    - staging: rtl8712: unterminated string leads to read overflow
+    - staging: rtl8188eu: fix potential memory corruption in
+      rtw_check_beacon_data()
+    - staging: ks7010: prevent buffer overflow in ks_wlan_set_scan()
+    - staging: rtl8712: Fix possible buffer overflow in r8712_sitesurvey_cmd
+    - staging: rtl8192e: Fix possible buffer overflow in _rtl92e_wx_set_scan
+    - staging: comedi: addi_apci_1032: Fix endian problem for COS sample
+    - staging: comedi: addi_apci_1500: Fix endian problem for command sample
+    - staging: comedi: adv_pci1710: Fix endian problem for AI command data
+    - staging: comedi: das6402: Fix endian problem for AI command data
+    - staging: comedi: das800: Fix endian problem for AI command data
+    - staging: comedi: dmm32at: Fix endian problem for AI command data
+    - staging: comedi: me4000: Fix endian problem for AI command data
+    - staging: comedi: pcl711: Fix endian problem for AI command data
+    - staging: comedi: pcl818: Fix endian problem for AI command data
+    - sh_eth: fix TRSCER mask for R7S72100
+    - arm64/mm: Fix pfn_valid() for ZONE_DEVICE based memory
+    - SUNRPC: Set memalloc_nofs_save() for sync tasks
+    - NFS: Don't revalidate the directory permissions on a lookup failure
+    - NFS: Don't gratuitously clear the inode cache when lookup failed
+    - NFSv4.2: fix return value of _nfs4_get_security_label()
+    - block: rsxx: fix error return code of rsxx_pci_probe()
+    - configfs: fix a use-after-free in __configfs_open_file
+    - arm64: mm: use a 48-bit ID map when possible on 52-bit VA builds
+    - hrtimer: Update softirq_expires_next correctly after
+      __hrtimer_get_next_event()
+    - stop_machine: mark helpers __always_inline
+    - include/linux/sched/mm.h: use rcu_dereference in in_vfork()
+    - zram: fix return value on writeback_store
+    - sched/membarrier: fix missing local execution of ipi_sync_rq_state()
+    - powerpc/64s: Fix instruction encoding for lis in ppc_function_entry()
+    - binfmt_misc: fix possible deadlock in bm_register_write
+    - x86/unwind/orc: Disable KASAN checking in the ORC unwinder, part 2
+    - KVM: arm64: Fix exclusive limit for IPA size
+    - nvme: unlink head after removing last namespace
+    - nvme: release namespace head reference on error
+    - KVM: arm64: Ensure I-cache isolation between vcpus of a same VM
+    - KVM: arm64: Reject VM creation when the default IPA size is unsupported
+    - xen/events: reset affinity of 2-level event when tearing it down
+    - xen/events: don't unmask an event channel when an eoi is pending
+    - xen/events: avoid handling the same event on two cpus at the same time
+    - Linux 5.4.106
+
+  * Focal update: v5.4.105 upstream stable release (LP: #1920244)
+    - net: dsa: add GRO support via gro_cells
+    - dm table: fix iterate_devices based device capability checks
+    - dm table: fix DAX iterate_devices based device capability checks
+    - dm table: fix zoned iterate_devices based device capability checks
+    - ACPICA: Fix race in generic_serial_bus (I2C) and GPIO op_region parameter
+      handling
+    - iommu/amd: Fix sleeping in atomic in increase_address_space()
+    - mwifiex: pcie: skip cancel_work_sync() on reset failure path
+    - platform/x86: acer-wmi: Cleanup ACER_CAP_FOO defines
+    - platform/x86: acer-wmi: Cleanup accelerometer device handling
+    - platform/x86: acer-wmi: Add new force_caps module parameter
+    - platform/x86: acer-wmi: Add ACER_CAP_SET_FUNCTION_MODE capability flag
+    - platform/x86: acer-wmi: Add support for SW_TABLET_MODE on Switch devices
+    - platform/x86: acer-wmi: Add ACER_CAP_KBD_DOCK quirk for the Aspire Switch
+      10E SW3-016
+    - HID: mf: add support for 0079:1846 Mayflash/Dragonrise USB Gamecube Adapter
+    - media: cx23885: add more quirks for reset DMA on some AMD IOMMU
+    - ACPI: video: Add DMI quirk for GIGABYTE GB-BXBT-2807
+    - ASoC: Intel: bytcr_rt5640: Add quirk for ARCHOS Cesium 140
+    - PCI: Add function 1 DMA alias quirk for Marvell 9215 SATA controller
+    - misc: eeprom_93xx46: Add quirk to support Microchip 93LC46B eeprom
+    - drm/msm/a5xx: Remove overwriting A5XX_PC_DBG_ECO_CNTL register
+    - mmc: sdhci-of-dwcmshc: set SDHCI_QUIRK2_PRESET_VALUE_BROKEN
+    - HID: i2c-hid: Add I2C_HID_QUIRK_NO_IRQ_AFTER_RESET for ITE8568 EC on Voyo
+      Winpad A15
+    - nvme-pci: mark Seagate Nytro XM1440 as QUIRK_NO_NS_DESC_LIST.
+    - nvme-pci: add quirks for Lexar 256GB SSD
+    - Linux 5.4.105
+
+  * Focal update: v5.4.104 upstream stable release (LP: #1920238)
+    - tpm, tpm_tis: Decorate tpm_tis_gen_interrupt() with request_locality()
+    - tpm, tpm_tis: Decorate tpm_get_timeouts() with request_locality()
+    - btrfs: raid56: simplify tracking of Q stripe presence
+    - btrfs: fix raid6 qstripe kmap
+    - btrfs: validate qgroup inherit for SNAP_CREATE_V2 ioctl
+    - btrfs: free correct amount of space in btrfs_delayed_inode_reserve_metadata
+    - btrfs: unlock extents in btrfs_zero_range in case of quota reservation
+      errors
+    - btrfs: fix warning when creating a directory with smack enabled
+    - PM: runtime: Update device status before letting suppliers suspend
+    - dm bufio: subtract the number of initial sectors in dm_bufio_get_device_size
+    - dm verity: fix FEC for RS roots unaligned to block size
+    - drm/amdgpu: fix parameter error of RREG32_PCIE() in amdgpu_regs_pcie
+    - arm64: ptrace: Fix seccomp of traced syscall -1 (NO_SYSCALL)
+    - crypto - shash: reduce minimum alignment of shash_desc structure
+    - usbip: tools: fix build error for multiple definition
+    - ALSA: ctxfi: cthw20k2: fix mask on conf to allow 4 bits
+    - RDMA/rxe: Fix missing kconfig dependency on CRYPTO
+    - IB/mlx5: Add missing error code
+    - ALSA: hda: intel-nhlt: verify config type
+    - ftrace: Have recordmcount use w8 to read relp->r_info in
+      arm64_is_fake_mcount
+    - rsxx: Return -EFAULT if copy_to_user() fails
+    - r8169: fix resuming from suspend on RTL8105e if machine runs on battery
+    - Linux 5.4.104
+
+  * Focal update: v5.4.103 upstream stable release (LP: #1920235)
+    - net: usb: qmi_wwan: support ZTE P685M modem
+    - nvme-pci: refactor nvme_unmap_data
+    - nvme-pci: fix error unwind in nvme_map_data
+    - arm64 module: set plt* section addresses to 0x0
+    - MIPS: VDSO: Use CLANG_FLAGS instead of filtering out '--target='
+    - JFS: more checks for invalid superblock
+    - udlfb: Fix memory leak in dlfb_usb_probe
+    - media: mceusb: sanity check for prescaler value
+    - erofs: fix shift-out-of-bounds of blkszbits
+    - media: v4l2-ctrls.c: fix shift-out-of-bounds in std_validate
+    - xfs: Fix assert failure in xfs_setattr_size()
+    - net/af_iucv: remove WARN_ONCE on malformed RX packets
+    - smackfs: restrict bytes count in smackfs write functions
+    - net: fix up truesize of cloned skb in skb_prepare_for_shift()
+    - nbd: handle device refs for DESTROY_ON_DISCONNECT properly
+    - mm/hugetlb.c: fix unnecessary address expansion of pmd sharing
+    - net: bridge: use switchdev for port flags set through sysfs too
+    - net: ag71xx: remove unnecessary MTU reservation
+    - net: fix dev_ifsioc_locked() race condition
+    - dt-bindings: ethernet-controller: fix fixed-link specification
+    - dt-bindings: net: btusb: DT fix s/interrupt-name/interrupt-names/
+    - MIPS: Drop 32-bit asm string functions
+    - drm/virtio: use kvmalloc for large allocations
+    - rsi: Fix TX EAPOL packet handling against iwlwifi AP
+    - rsi: Move card interrupt handling to RX thread
+    - staging: fwserial: Fix error handling in fwserial_create
+    - x86/reboot: Add Zotac ZBOX CI327 nano PCI reboot quirk
+    - vt/consolemap: do font sum unsigned
+    - wlcore: Fix command execute failure 19 for wl12xx
+    - Bluetooth: hci_h5: Set HCI_QUIRK_SIMULTANEOUS_DISCOVERY for btrtl
+    - pktgen: fix misuse of BUG_ON() in pktgen_thread_worker()
+    - ath10k: fix wmi mgmt tx queue full due to race condition
+    - x86/build: Treat R_386_PLT32 relocation as R_386_PC32
+    - Bluetooth: Fix null pointer dereference in amp_read_loc_assoc_final_data
+    - staging: most: sound: add sanity check for function argument
+    - staging: bcm2835-audio: Replace unsafe strcpy() with strscpy()
+    - brcmfmac: Add DMI nvram filename quirk for Predia Basic tablet
+    - brcmfmac: Add DMI nvram filename quirk for Voyo winpad A15 tablet
+    - drm/hisilicon: Fix use-after-free
+    - crypto: tcrypt - avoid signed overflow in byte count
+    - drm/amdgpu: Add check to prevent IH overflow
+    - PCI: Add a REBAR size quirk for Sapphire RX 5600 XT Pulse
+    - drm/amd/display: Guard against NULL pointer deref when get_i2c_info fails
+    - media: uvcvideo: Allow entities with no pads
+    - f2fs: handle unallocated section and zone on pinned/atgc
+    - f2fs: fix to set/clear I_LINKABLE under i_lock
+    - nvme-core: add cancel tagset helpers
+    - nvme-rdma: add clean action for failed reconnection
+    - nvme-tcp: add clean action for failed reconnection
+    - ASoC: Intel: Add DMI quirk table to soc_intel_is_byt_cr()
+    - btrfs: fix error handling in commit_fs_roots
+    - perf/x86/kvm: Add Cascade Lake Xeon steppings to isolation_ucodes[]
+    - parisc: Bump 64-bit IRQ stack size to 64 KB
+    - sched/features: Fix hrtick reprogramming
+    - ASoC: Intel: bytcr_rt5640: Add quirk for the Estar Beauty HD MID 7316R
+      tablet
+    - ASoC: Intel: bytcr_rt5640: Add quirk for the Voyo Winpad A15 tablet
+    - ASoC: Intel: bytcr_rt5651: Add quirk for the Jumper EZpad 7 tablet
+    - ASoC: Intel: bytcr_rt5640: Add quirk for the Acer One S1002 tablet
+    - Xen/gnttab: handle p2m update errors on a per-slot basis
+    - xen-netback: respect gnttab_map_refs()'s return value
+    - zsmalloc: account the number of compacted pages correctly
+    - swap: fix swapfile read/write offset
+    - media: v4l: ioctl: Fix memory leak in video_usercopy
+    - ALSA: hda/realtek: Add quirk for Clevo NH55RZQ
+    - ALSA: hda/realtek: Add quirk for Intel NUC 10
+    - ALSA: hda/realtek: Apply dual codec quirks for MSI Godlike X570 board
+    - Linux 5.4.103
+
+  * Focal update: v5.4.102 upstream stable release (LP: #1918974)
+    - vmlinux.lds.h: add DWARF v5 sections
+    - kvm: x86: replace kvm_spec_ctrl_test_value with runtime test on the host
+    - debugfs: be more robust at handling improper input in debugfs_lookup()
+    - debugfs: do not attempt to create a new file before the filesystem is
+      initalized
+    - kdb: Make memory allocations more robust
+    - PCI: qcom: Use PHY_REFCLK_USE_PAD only for ipq8064
+    - PCI: Decline to resize resources if boot config must be preserved
+    - virt: vbox: Do not use wait_event_interruptible when called from kernel
+      context
+    - bfq: Avoid false bfq queue merging
+    - ALSA: usb-audio: Fix PCM buffer allocation in non-vmalloc mode
+    - MIPS: vmlinux.lds.S: add missing PAGE_ALIGNED_DATA() section
+    - random: fix the RNDRESEEDCRNG ioctl
+    - ath10k: Fix error handling in case of CE pipe init failure
+    - Bluetooth: btqcomsmd: Fix a resource leak in error handling paths in the
+      probe function
+    - Bluetooth: hci_uart: Fix a race for write_work scheduling
+    - Bluetooth: Fix initializing response id after clearing struct
+    - ARM: dts: exynos: correct PMIC interrupt trigger level on Artik 5
+    - ARM: dts: exynos: correct PMIC interrupt trigger level on Monk
+    - ARM: dts: exynos: correct PMIC interrupt trigger level on Rinato
+    - ARM: dts: exynos: correct PMIC interrupt trigger level on Spring
+    - ARM: dts: exynos: correct PMIC interrupt trigger level on Arndale Octa
+    - ARM: dts: exynos: correct PMIC interrupt trigger level on Odroid XU3 family
+    - arm64: dts: exynos: correct PMIC interrupt trigger level on TM2
+    - arm64: dts: exynos: correct PMIC interrupt trigger level on Espresso
+    - memory: mtk-smi: Fix PM usage counter unbalance in mtk_smi ops
+    - bpf: Add bpf_patch_call_args prototype to include/linux/bpf.h
+    - bpf: Avoid warning when re-casting __bpf_call_base into __bpf_call_base_args
+    - arm64: dts: allwinner: A64: properly connect USB PHY to port 0
+    - arm64: dts: allwinner: H6: properly connect USB PHY to port 0
+    - arm64: dts: allwinner: Drop non-removable from SoPine/LTS SD card
+    - arm64: dts: allwinner: H6: Allow up to 150 MHz MMC bus frequency
+    - arm64: dts: allwinner: A64: Limit MMC2 bus frequency to 150 MHz
+    - cpufreq: brcmstb-avs-cpufreq: Free resources in error path
+    - cpufreq: brcmstb-avs-cpufreq: Fix resource leaks in ->remove()
+    - ACPICA: Fix exception code class checks
+    - usb: gadget: u_audio: Free requests only after callback
+    - Bluetooth: drop HCI device reference before return
+    - Bluetooth: Put HCI device if inquiry procedure interrupts
+    - memory: ti-aemif: Drop child node when jumping out loop
+    - ARM: dts: Configure missing thermal interrupt for 4430
+    - usb: dwc2: Do not update data length if it is 0 on inbound transfers
+    - usb: dwc2: Abort transaction after errors with unknown reason
+    - usb: dwc2: Make "trimming xfer length" a debug message
+    - staging: rtl8723bs: wifi_regd.c: Fix incorrect number of regulatory rules
+    - ARM: dts: armada388-helios4: assign pinctrl to LEDs
+    - ARM: dts: armada388-helios4: assign pinctrl to each fan
+    - arm64: dts: armada-3720-turris-mox: rename u-boot mtd partition to
+      a53-firmware
+    - Bluetooth: btusb: Fix memory leak in btusb_mtk_wmt_recv
+    - arm64: dts: msm8916: Fix reserved and rfsa nodes unit address
+    - ARM: s3c: fix fiq for clang IAS
+    - soc: aspeed: snoop: Add clock control logic
+    - bpf_lru_list: Read double-checked variable once without lock
+    - ath9k: fix data bus crash when setting nf_override via debugfs
+    - ibmvnic: Set to CLOSED state even on error
+    - bnxt_en: reverse order of TX disable and carrier off
+    - xen/netback: fix spurious event detection for common event case
+    - mac80211: fix potential overflow when multiplying to u32 integers
+    - bpf: Fix bpf_fib_lookup helper MTU check for SKB ctx
+    - tcp: fix SO_RCVLOWAT related hangs under mem pressure
+    - net: axienet: Handle deferred probe on clock properly
+    - cxgb4/chtls/cxgbit: Keeping the max ofld immediate data size same in cxgb4
+      and ulds
+    - b43: N-PHY: Fix the update of coef for the PHY revision >= 3case
+    - ibmvnic: add memory barrier to protect long term buffer
+    - ibmvnic: skip send_request_unmap for timeout reset
+    - net: amd-xgbe: Reset the PHY rx data path when mailbox command timeout
+    - net: amd-xgbe: Fix NETDEV WATCHDOG transmit queue timeout warning
+    - net: amd-xgbe: Reset link when the link never comes back
+    - net: amd-xgbe: Fix network fluctuations when using 1G BELFUSE SFP
+    - net: mvneta: Remove per-cpu queue mapping for Armada 3700
+    - fbdev: aty: SPARC64 requires FB_ATY_CT
+    - drm/gma500: Fix error return code in psb_driver_load()
+    - gma500: clean up error handling in init
+    - drm/fb-helper: Add missed unlocks in setcmap_legacy()
+    - crypto: sun4i-ss - linearize buffers content must be kept
+    - crypto: sun4i-ss - fix kmap usage
+    - crypto: arm64/aes-ce - really hide slower algos when faster ones are enabled
+    - drm/amdgpu: Fix macro name _AMDGPU_TRACE_H_ in preprocessor if condition
+    - MIPS: c-r4k: Fix section mismatch for loongson2_sc_init
+    - MIPS: lantiq: Explicitly compare LTQ_EBU_PCC_ISTAT against 0
+    - media: i2c: ov5670: Fix PIXEL_RATE minimum value
+    - media: imx: Unregister csc/scaler only if registered
+    - media: imx: Fix csc/scaler unregister
+    - media: camss: missing error code in msm_video_register()
+    - media: vsp1: Fix an error handling path in the probe function
+    - media: em28xx: Fix use-after-free in em28xx_alloc_urbs
+    - media: media/pci: Fix memleak in empress_init
+    - media: tm6000: Fix memleak in tm6000_start_stream
+    - media: aspeed: fix error return code in aspeed_video_setup_video()
+    - ASoC: cs42l56: fix up error handling in probe
+    - evm: Fix memleak in init_desc
+    - crypto: bcm - Rename struct device_private to bcm_device_private
+    - drm/sun4i: tcon: fix inverted DCLK polarity
+    - MIPS: properly stop .eh_frame generation
+    - bsg: free the request before return error code
+    - drm/amd/display: Fix 10/12 bpc setup in DCE output bit depth reduction.
+    - drm/amd/display: Fix HDMI deep color output for DCE 6-11.
+    - media: software_node: Fix refcounts in software_node_get_next_child()
+    - media: lmedm04: Fix misuse of comma
+    - media: qm1d1c0042: fix error return code in qm1d1c0042_init()
+    - media: cx25821: Fix a bug when reallocating some dma memory
+    - media: pxa_camera: declare variable when DEBUG is defined
+    - media: uvcvideo: Accept invalid bFormatIndex and bFrameIndex values
+    - sched/eas: Don't update misfit status if the task is pinned
+    - mtd: parser: imagetag: fix error codes in
+      bcm963xx_parse_imagetag_partitions()
+    - crypto: talitos - Work around SEC6 ERRATA (AES-CTR mode data size error)
+    - drm/nouveau: bail out of nouveau_channel_new if channel init fails
+    - ata: ahci_brcm: Add back regulators management
+    - ASoC: cpcap: fix microphone timeslot mask
+    - mtd: parsers: afs: Fix freeing the part name memory in failure
+    - f2fs: fix to avoid inconsistent quota data
+    - drm/amdgpu: Prevent shift wrapping in amdgpu_read_mask()
+    - f2fs: fix a wrong condition in __submit_bio
+    - Drivers: hv: vmbus: Avoid use-after-free in vmbus_onoffer_rescind()
+    - ASoC: SOF: debug: Fix a potential issue on string buffer termination
+    - btrfs: clarify error returns values in __load_free_space_cache
+    - hwrng: timeriomem - Fix cooldown period calculation
+    - crypto: ecdh_helper - Ensure 'len >= secret.len' in decode_key()
+    - ima: Free IMA measurement buffer on error
+    - ima: Free IMA measurement buffer after kexec syscall
+    - ASoC: simple-card-utils: Fix device module clock
+    - fs/jfs: fix potential integer overflow on shift of a int
+    - jffs2: fix use after free in jffs2_sum_write_data()
+    - ubifs: Fix memleak in ubifs_init_authentication
+    - ubifs: Fix error return code in alloc_wbufs()
+    - capabilities: Don't allow writing ambiguous v3 file capabilities
+    - HSI: Fix PM usage counter unbalance in ssi_hw_init
+    - clk: meson: clk-pll: fix initializing the old rate (fallback) for a PLL
+    - clk: meson: clk-pll: make "ret" a signed integer
+    - clk: meson: clk-pll: propagate the error from meson_clk_pll_set_rate()
+    - quota: Fix memory leak when handling corrupted quota file
+    - i2c: iproc: handle only slave interrupts which are enabled
+    - i2c: iproc: update slave isr mask (ISR_MASK_SLAVE)
+    - i2c: iproc: handle master read request
+    - spi: cadence-quadspi: Abort read if dummy cycles required are too many
+    - clk: sunxi-ng: h6: Fix CEC clock
+    - HID: core: detect and skip invalid inputs to snto32()
+    - RDMA/siw: Fix handling of zero-sized Read and Receive Queues.
+    - dmaengine: fsldma: Fix a resource leak in the remove function
+    - dmaengine: fsldma: Fix a resource leak in an error handling path of the
+      probe function
+    - dmaengine: owl-dma: Fix a resource leak in the remove function
+    - dmaengine: hsu: disable spurious interrupt
+    - mfd: bd9571mwv: Use devm_mfd_add_devices()
+    - fdt: Properly handle "no-map" field in the memory region
+    - of/fdt: Make sure no-map does not remove already reserved regions
+    - power: reset: at91-sama5d2_shdwc: fix wkupdbc mask
+    - rtc: s5m: select REGMAP_I2C
+    - clocksource/drivers/ixp4xx: Select TIMER_OF when needed
+    - clocksource/drivers/mxs_timer: Add missing semicolon when DEBUG is defined
+    - RDMA/mlx5: Use the correct obj_id upon DEVX TIR creation
+    - clk: sunxi-ng: h6: Fix clock divider range on some clocks
+    - regulator: axp20x: Fix reference cout leak
+    - certs: Fix blacklist flag type confusion
+    - regulator: s5m8767: Fix reference count leak
+    - spi: atmel: Put allocated master before return
+    - regulator: s5m8767: Drop regulators OF node reference
+    - regulator: core: Avoid debugfs: Directory ... already present! error
+    - isofs: release buffer head before return
+    - auxdisplay: ht16k33: Fix refresh rate handling
+    - objtool: Fix error handling for STD/CLD warnings
+    - objtool: Fix ".cold" section suffix check for newer versions of GCC
+    - IB/umad: Return EIO in case of when device disassociated
+    - IB/umad: Return EPOLLERR in case of when device disassociated
+    - KVM: PPC: Make the VMX instruction emulation routines static
+    - powerpc/47x: Disable 256k page size
+    - mmc: sdhci-sprd: Fix some resource leaks in the remove function
+    - mmc: usdhi6rol0: Fix a resource leak in the error handling path of the probe
+    - mmc: renesas_sdhi_internal_dmac: Fix DMA buffer alignment from 8 to
+      128-bytes
+    - ARM: 9046/1: decompressor: Do not clear SCTLR.nTLSMD for ARMv7+ cores
+    - i2c: qcom-geni: Store DMA mapping data in geni_i2c_dev struct
+    - amba: Fix resource leak for drivers without .remove
+    - IB/mlx5: Return appropriate error code instead of ENOMEM
+    - IB/cm: Avoid a loop when device has 255 ports
+    - tracepoint: Do not fail unregistering a probe due to memory failure
+    - perf tools: Fix DSO filtering when not finding a map for a sampled address
+    - perf vendor events arm64: Fix Ampere eMag event typo
+    - RDMA/rxe: Fix coding error in rxe_recv.c
+    - RDMA/rxe: Fix coding error in rxe_rcv_mcast_pkt
+    - RDMA/rxe: Correct skb on loopback path
+    - spi: stm32: properly handle 0 byte transfer
+    - mfd: wm831x-auxadc: Prevent use after free in wm831x_auxadc_read_irq()
+    - powerpc/pseries/dlpar: handle ibm, configure-connector delay status
+    - powerpc/8xx: Fix software emulation interrupt
+    - clk: qcom: gcc-msm8998: Fix Alpha PLL type for all GPLLs
+    - RDMA/hns: Fixed wrong judgments in the goto branch
+    - RDMA/siw: Fix calculation of tx_valid_cpus size
+    - RDMA/hns: Fix type of sq_signal_bits
+    - spi: pxa2xx: Fix the controller numbering for Wildcat Point
+    - regulator: qcom-rpmh: fix pm8009 ldo7
+    - clk: aspeed: Fix APLL calculate formula from ast2600-A2
+    - nfsd: register pernet ops last, unregister first
+    - RDMA/hns: Fixes missing error code of CMDQ
+    - Input: sur40 - fix an error code in sur40_probe()
+    - perf intel-pt: Fix missing CYC processing in PSB
+    - perf intel-pt: Fix premature IPC
+    - perf test: Fix unaligned access in sample parsing test
+    - Input: elo - fix an error code in elo_connect()
+    - sparc64: only select COMPAT_BINFMT_ELF if BINFMT_ELF is set
+    - misc: eeprom_93xx46: Fix module alias to enable module autoprobe
+    - phy: rockchip-emmc: emmc_phy_init() always return 0
+    - misc: eeprom_93xx46: Add module alias to avoid breaking support for non
+      device tree users
+    - soundwire: cadence: fix ACK/NAK handling
+    - pwm: rockchip: rockchip_pwm_probe(): Remove superfluous clk_unprepare()
+    - VMCI: Use set_page_dirty_lock() when unregistering guest memory
+    - PCI: Align checking of syscall user config accessors
+    - mei: hbm: call mei_set_devstate() on hbm stop response
+    - drm/msm/dsi: Correct io_start for MSM8994 (20nm PHY)
+    - drm/msm/mdp5: Fix wait-for-commit for cmd panels
+    - vfio/iommu_type1: Fix some sanity checks in detach group
+    - ext4: fix potential htree index checksum corruption
+    - nvmem: core: Fix a resource leak on error in nvmem_add_cells_from_of()
+    - nvmem: core: skip child nodes not matching binding
+    - regmap: sdw: use _no_pm functions in regmap_read/write
+    - i40e: Fix flow for IPv6 next header (extension header)
+    - i40e: Add zero-initialization of AQ command structures
+    - i40e: Fix overwriting flow control settings during driver loading
+    - i40e: Fix addition of RX filters after enabling FW LLDP agent
+    - i40e: Fix VFs not created
+    - i40e: Fix add TC filter for IPv6
+    - vfio/type1: Use follow_pte()
+    - net/mlx4_core: Add missed mlx4_free_cmd_mailbox()
+    - vxlan: move debug check after netdev unregister
+    - ocfs2: fix a use after free on error
+    - mm/memory.c: fix potential pte_unmap_unlock pte error
+    - mm/hugetlb: fix potential double free in hugetlb_register_node() error path
+    - mm/compaction: fix misbehaviors of fast_find_migrateblock()
+    - r8169: fix jumbo packet handling on RTL8168e
+    - arm64: Add missing ISB after invalidating TLB in __primary_switch
+    - i2c: brcmstb: Fix brcmstd_send_i2c_cmd condition
+    - mm/rmap: fix potential pte_unmap on an not mapped pte
+    - scsi: bnx2fc: Fix Kconfig warning & CNIC build errors
+    - blk-settings: align max_sectors on "logical_block_size" boundary
+    - ACPI: property: Fix fwnode string properties matching
+    - ACPI: configfs: add missing check after configfs_register_default_group()
+    - HID: logitech-dj: add support for keyboard events in eQUAD step 4 Gaming
+    - HID: wacom: Ignore attempts to overwrite the touch_max value from HID
+    - Input: raydium_ts_i2c - do not send zero length
+    - Input: xpad - add support for PowerA Enhanced Wired Controller for Xbox
+      Series X|S
+    - Input: joydev - prevent potential read overflow in ioctl
+    - Input: i8042 - add ASUS Zenbook Flip to noselftest list
+    - media: mceusb: Fix potential out-of-bounds shift
+    - USB: serial: option: update interface mapping for ZTE P685M
+    - usb: musb: Fix runtime PM race in musb_queue_resume_work
+    - usb: dwc3: gadget: Fix setting of DEPCFG.bInterval_m1
+    - usb: dwc3: gadget: Fix dep->interval for fullspeed interrupt
+    - USB: serial: ftdi_sio: fix FTX sub-integer prescaler
+    - USB: serial: mos7840: fix error code in mos7840_write()
+    - USB: serial: mos7720: fix error code in mos7720_write()
+    - ALSA: hda: Add another CometLake-H PCI ID
+    - ALSA: hda/realtek: modify EAPD in the ALC886
+    - Revert "bcache: Kill btree_io_wq"
+    - bcache: Give btree_io_wq correct semantics again
+    - bcache: Move journal work to new flush wq
+    - drm/amd/display: Add vupdate_no_lock interrupts for DCN2.1
+    - drm/amdgpu: Set reference clock to 100Mhz on Renoir (v2)
+    - drm/nouveau/kms: handle mDP connectors
+    - drm/sched: Cancel and flush all outstanding jobs before finish.
+    - erofs: initialized fields can only be observed after bit is set
+    - tpm_tis: Fix check_locality for correct locality acquisition
+    - tpm_tis: Clean up locality release
+    - KEYS: trusted: Fix migratable=1 failing
+    - btrfs: abort the transaction if we fail to inc ref in btrfs_copy_root
+    - btrfs: fix reloc root leak with 0 ref reloc roots on recovery
+    - btrfs: splice remaining dirty_bg's onto the transaction dirty bg list
+    - btrfs: fix extent buffer leak on failure to copy root
+    - crypto: arm64/sha - add missing module aliases
+    - crypto: aesni - prevent misaligned buffers on the stack
+    - crypto: sun4i-ss - checking sg length is not sufficient
+    - crypto: sun4i-ss - handle BigEndian for cipher
+    - crypto: sun4i-ss - initialize need_fallback
+    - seccomp: Add missing return in non-void function
+    - misc: rtsx: init of rts522a add OCP power off when no card is present
+    - drivers/misc/vmw_vmci: restrict too big queue size in qp_host_alloc_queue
+    - pstore: Fix typo in compression option name
+    - dts64: mt7622: fix slow sd card access
+    - staging/mt7621-dma: mtk-hsdma.c->hsdma-mt7621.c
+    - staging: gdm724x: Fix DMA from stack
+    - staging: rtl8188eu: Add Edimax EW-7811UN V2 to device table
+    - media: ipu3-cio2: Fix mbus_code processing in cio2_subdev_set_fmt()
+    - x86/virt: Eat faults on VMXOFF in reboot flows
+    - x86/reboot: Force all cpus to exit VMX root if VMX is supported
+    - powerpc/prom: Fix "ibm,arch-vec-5-platform-support" scan
+    - rcu: Pull deferred rcuog wake up to rcu_eqs_enter() callers
+    - rcu/nocb: Perform deferred wake up before last idle's need_resched() check
+    - floppy: reintroduce O_NDELAY fix
+    - arm64: kexec_file: fix memory leakage in create_dtb() when fdt_open_into()
+      fails
+    - arm64: uprobe: Return EOPNOTSUPP for AARCH32 instruction probing
+    - watchdog: qcom: Remove incorrect usage of QCOM_WDT_ENABLE_IRQ
+    - watchdog: mei_wdt: request stop on unregister
+    - mtd: spi-nor: sfdp: Fix last erase region marking
+    - mtd: spi-nor: sfdp: Fix wrong erase type bitmask for overlaid region
+    - mtd: spi-nor: core: Fix erase type discovery for overlaid region
+    - mtd: spi-nor: core: Add erase size check for erase command initialization
+    - mtd: spi-nor: hisi-sfc: Put child node np on error path
+    - fs/affs: release old buffer head on error path
+    - seq_file: document how per-entry resources are managed.
+    - x86: fix seq_file iteration for pat/memtype.c
+    - hugetlb: fix update_and_free_page contig page struct assumption
+    - hugetlb: fix copy_huge_page_from_user contig page struct assumption
+    - arm64: Extend workaround for erratum 1024718 to all versions of Cortex-A55
+    - media: smipcie: fix interrupt handling and IR timeout
+    - module: Ignore _GLOBAL_OFFSET_TABLE_ when warning for undefined symbols
+    - mmc: sdhci-esdhc-imx: fix kernel panic when remove module
+    - powerpc/32s: Add missing call to kuep_lock on syscall entry
+    - spmi: spmi-pmic-arb: Fix hw_irq overflow
+    - gpio: pcf857x: Fix missing first interrupt
+    - printk: fix deadlock when kernel panic
+    - cpufreq: intel_pstate: Get per-CPU max freq via MSR_HWP_CAPABILITIES if
+      available
+    - s390/vtime: fix inline assembly clobber list
+    - virtio/s390: implement virtio-ccw revision 2 correctly
+    - um: mm: check more comprehensively for stub changes
+    - f2fs: fix out-of-repair __setattr_copy()
+    - sparc32: fix a user-triggerable oops in clear_user()
+    - spi: spi-synquacer: fix set_cs handling
+    - gfs2: Don't skip dlm unlock if glock has an lvb
+    - gfs2: Recursive gfs2_quota_hold in gfs2_iomap_end
+    - dm: fix deadlock when swapping to encrypted device
+    - dm writecache: fix writing beyond end of underlying device when shrinking
+    - dm era: Recover committed writeset after crash
+    - dm era: Verify the data block size hasn't changed
+    - dm era: Fix bitset memory leaks
+    - dm era: Use correct value size in equality function of writeset tree
+    - dm era: Reinitialize bitset cache before digesting a new writeset
+    - dm era: only resize metadata in preresume
+    - drm/i915: Reject 446-480MHz HDMI clock on GLK
+    - icmp: introduce helper for nat'd source address in network device context
+    - icmp: allow icmpv6_ndo_send to work with CONFIG_IPV6=n
+    - gtp: use icmp_ndo_send helper
+    - sunvnet: use icmp_ndo_send helper
+    - xfrm: interface: use icmp_ndo_send helper
+    - ipv6: icmp6: avoid indirect call for icmpv6_send()
+    - ipv6: silence compilation warning for non-IPV6 builds
+    - net: icmp: pass zeroed opts from icmp{,v6}_ndo_send before sending
+    - net: sched: fix police ext initialization
+    - dm era: Update in-core bitset after committing the metadata
+    - net: qrtr: Fix memory leak in qrtr_tun_open
+    - ARM: dts: aspeed: Add LCLK to lpc-snoop
+    - Linux 5.4.102
+
+  * eeh-basic.sh from powerpc in ubuntu_kernel_selftests failed with unexpected
+    operator on F-5.8 (LP: #1909428)
+    - selftests/powerpc: Make the test check in eeh-basic.sh posix compliant
+
+ -- Kleber Sacilotto de Souza <kleber.souza@canonical.com>  Wed, 14 Apr 2021 18:35:30 +0200
+
+linux (5.4.0-72.80) focal; urgency=medium
+
+  * overlayfs calls vfs_setxattr without cap_convert_nscap
+    - vfs: move cap_convert_nscap() call into vfs_setxattr()
+
+  * CVE-2021-3492
+    - SAUCE: shiftfs: free allocated memory in shiftfs_btrfs_ioctl_fd_replace()
+      error paths
+    - SAUCE: shiftfs: handle copy_to_user() return values correctly
+
+  * CVE-2021-29154
+    - SAUCE: bpf, x86: Validate computation of branch displacements for x86-64
+    - SAUCE: bpf, x86: Validate computation of branch displacements for x86-32
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Mon, 12 Apr 2021 17:12:08 +0200
+
+linux (5.4.0-71.79) focal; urgency=medium
+
+  * focal/linux: 5.4.0-71.79 -proposed tracker (LP: #1921040)
+
+  * selftests: bpf verifier fails after sanitize_ptr_alu fixes (LP: #1920995)
+    - bpf: Simplify alu_limit masking for pointer arithmetic
+    - bpf: Add sanity check for upper ptr_limit
+    - bpf, selftests: Fix up some test_verifier cases for unprivileged
+
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+
+  * Fix missing HDMI/DP audio on NVidia card after S3 (LP: #1918228)
+    - ALSA: hda/hdmi: Reduce hda_jack_tbl lookup at unsol event handling
+    - ALSA: hda/hdmi: Don't use standard hda_jack for generic HDMI jacks
+    - ALSA: hda/hdmi: Move runtime PM resume into hdmi_present_sense_via_verbs()
+    - ALSA: hda/hdmi: Move ELD parse and jack reporting into update_eld()
+
+  * Focal update: v5.4.101 upstream stable release (LP: #1918170)
+    - HID: make arrays usage and value to be the same
+    - USB: quirks: sort quirk entries
+    - usb: quirks: add quirk to start video capture on ELMO L-12F document camera
+      reliable
+    - ntfs: check for valid standard information attribute
+    - arm64: tegra: Add power-domain for Tegra210 HDA
+    - scripts: use pkg-config to locate libcrypto
+    - scripts: set proper OpenSSL include dir also for sign-file
+    - mm: unexport follow_pte_pmd
+    - mm: simplify follow_pte{,pmd}
+    - KVM: do not assume PTE is writable after follow_pfn
+    - mm: provide a saner PTE walking API for modules
+    - KVM: Use kvm_pfn_t for local PFN variable in hva_to_pfn_remapped()
+    - NET: usb: qmi_wwan: Adding support for Cinterion MV31
+    - cxgb4: Add new T6 PCI device id 0x6092
+    - cifs: Set CIFS_MOUNT_USE_PREFIX_PATH flag on setting cifs_sb->prepath.
+    - scripts/recordmcount.pl: support big endian for ARCH sh
+    - Linux 5.4.101
+
+  * Focal update: v5.4.100 upstream stable release (LP: #1918168)
+    - KVM: SEV: fix double locking due to incorrect backport
+    - net: qrtr: Fix port ID for control messages
+    - net: bridge: Fix a warning when del bridge sysfs
+    - Xen/x86: don't bail early from clear_foreign_p2m_mapping()
+    - Xen/x86: also check kernel mapping in set_foreign_p2m_mapping()
+    - Xen/gntdev: correct dev_bus_addr handling in gntdev_map_grant_pages()
+    - Xen/gntdev: correct error checking in gntdev_map_grant_pages()
+    - xen/arm: don't ignore return errors from set_phys_to_machine
+    - xen-blkback: don't "handle" error by BUG()
+    - xen-netback: don't "handle" error by BUG()
+    - xen-scsiback: don't "handle" error by BUG()
+    - xen-blkback: fix error handling in xen_blkbk_map()
+    - media: pwc: Use correct device for DMA
+    - btrfs: fix backport of 2175bf57dc952 in 5.4.95
+    - Linux 5.4.100
+
+  * Focal update: v5.4.99 upstream stable release (LP: #1918167)
+    - gpio: ep93xx: fix BUG_ON port F usage
+    - gpio: ep93xx: Fix single irqchip with multi gpiochips
+    - tracing: Do not count ftrace events in top level enable output
+    - tracing: Check length before giving out the filter buffer
+    - arm/xen: Don't probe xenbus as part of an early initcall
+    - cgroup: fix psi monitor for root cgroup
+    - arm64: dts: rockchip: Fix PCIe DT properties on rk3399
+    - arm64: dts: qcom: sdm845: Reserve LPASS clocks in gcc
+    - ARM: OMAP2+: Fix suspcious RCU usage splats for omap_enter_idle_coupled
+    - platform/x86: hp-wmi: Disable tablet-mode reporting by default
+    - ovl: perform vfs_getxattr() with mounter creds
+    - cap: fix conversions on getxattr
+    - ovl: skip getxattr of security labels
+    - nvme-pci: ignore the subsysem NQN on Phison E16
+    - drm/amd/display: Add more Clock Sources to DCN2.1
+    - drm/amd/display: Fix dc_sink kref count in emulated_link_detect
+    - drm/amd/display: Free atomic state after drm_atomic_commit
+    - drm/amd/display: Decrement refcount of dc_sink before reassignment
+    - riscv: virt_addr_valid must check the address belongs to linear mapping
+    - bfq-iosched: Revert "bfq: Fix computation of shallow depth"
+    - ARM: dts: lpc32xx: Revert set default clock rate of HCLK PLL
+    - ARM: ensure the signal page contains defined contents
+    - ARM: kexec: fix oops after TLB are invalidated
+    - vmlinux.lds.h: Create section for protection against instrumentation
+    - lkdtm: don't move ctors to .rodata
+    - mt76: dma: fix a possible memory leak in mt76_add_fragment()
+    - drm/vc4: hvs: Fix buffer overflow with the dlist handling
+    - bpf: Check for integer overflow when using roundup_pow_of_two()
+    - netfilter: xt_recent: Fix attempt to update deleted entry
+    - netfilter: nftables: fix possible UAF over chains from packet path in netns
+    - netfilter: flowtable: fix tcp and udp header checksum update
+    - xen/netback: avoid race in xenvif_rx_ring_slots_available()
+    - net: enetc: initialize the RFS and RSS memories
+    - selftests: txtimestamp: fix compilation issue
+    - net: stmmac: set TxQ mode back to DCB after disabling CBS
+    - ibmvnic: Clear failover_pending if unable to schedule
+    - netfilter: conntrack: skip identical origin tuple in same zone only
+    - x86/build: Disable CET instrumentation in the kernel for 32-bit too
+    - net: hns3: add a check for queue_id in hclge_reset_vf_queue()
+    - firmware_loader: align .builtin_fw to 8
+    - drm/sun4i: tcon: set sync polarity for tcon1 channel
+    - drm/sun4i: Fix H6 HDMI PHY configuration
+    - drm/sun4i: dw-hdmi: Fix max. frequency for H6
+    - clk: sunxi-ng: mp: fix parent rate change flag check
+    - i2c: stm32f7: fix configuration of the digital filter
+    - h8300: fix PREEMPTION build, TI_PRE_COUNT undefined
+    - usb: dwc3: ulpi: fix checkpatch warning
+    - usb: dwc3: ulpi: Replace CPU-based busyloop with Protocol-based one
+    - rxrpc: Fix clearance of Tx/Rx ring when releasing a call
+    - udp: fix skb_copy_and_csum_datagram with odd segment sizes
+    - net: dsa: call teardown method on probe failure
+    - net: gro: do not keep too many GRO packets in napi->rx_list
+    - net: fix iteration for sctp transport seq_files
+    - net/vmw_vsock: improve locking in vsock_connect_timeout()
+    - net: watchdog: hold device global xmit lock during tx disable
+    - vsock/virtio: update credit only if socket is not closed
+    - vsock: fix locking in vsock_shutdown()
+    - net/rds: restrict iovecs length for RDS_CMSG_RDMA_ARGS
+    - net/qrtr: restrict user-controlled length in qrtr_tun_write_iter()
+    - ovl: expand warning in ovl_d_real()
+    - Linux 5.4.99
+
+  * Focal update: v5.4.98 upstream stable release (LP: #1918158)
+    - tracing/kprobe: Fix to support kretprobe events on unloaded modules
+    - af_key: relax availability checks for skb size calculation
+    - regulator: core: avoid regulator_resolve_supply() race condition
+    - mac80211: 160MHz with extended NSS BW in CSA
+    - ASoC: Intel: Skylake: Zero snd_ctl_elem_value
+    - chtls: Fix potential resource leak
+    - pNFS/NFSv4: Try to return invalid layout in pnfs_layout_process()
+    - ASoC: ak4458: correct reset polarity
+    - iwlwifi: mvm: skip power command when unbinding vif during CSA
+    - iwlwifi: mvm: take mutex for calling iwl_mvm_get_sync_time()
+    - iwlwifi: pcie: add a NULL check in iwl_pcie_txq_unmap
+    - iwlwifi: pcie: fix context info memory leak
+    - iwlwifi: mvm: invalidate IDs of internal stations at mvm start
+    - iwlwifi: mvm: guard against device removal in reprobe
+    - SUNRPC: Move simple_get_bytes and simple_get_netobj into private header
+    - SUNRPC: Handle 0 length opaque XDR object data properly
+    - i2c: mediatek: Move suspend and resume handling to NOIRQ phase
+    - blk-cgroup: Use cond_resched() when destroy blkgs
+    - regulator: Fix lockdep warning resolving supplies
+    - Fix unsynchronized access to sev members through svm_register_enc_region
+    - squashfs: add more sanity checks in id lookup
+    - squashfs: add more sanity checks in inode lookup
+    - squashfs: add more sanity checks in xattr id lookup
+    - Linux 5.4.98
+
+  * Enforce CONFIG_DRM_BOCHS=m (LP: #1916290)
+    - [Config] Enforce CONFIG_DRM_BOCHS=m
+
+  * powerpc/eeh-basic.sh in kselftest make P8 node stopped working
+    (LP: #1916468)
+    - selftests/eeh: Skip ahci adapters
+
+  * Focal update: v5.4.97 upstream stable release (LP: #1916066)
+    - USB: serial: cp210x: add pid/vid for WSDA-200-USB
+    - USB: serial: cp210x: add new VID/PID for supporting Teraoka AD2000
+    - USB: serial: option: Adding support for Cinterion MV31
+    - arm64: dts: qcom: c630: keep both touchpad devices enabled
+    - arm64: dts: amlogic: meson-g12: Set FL-adj property value
+    - arm64: dts: rockchip: fix vopl iommu irq on px30
+    - bpf, cgroup: Fix optlen WARN_ON_ONCE toctou
+    - bpf, cgroup: Fix problematic bounds check
+    - um: virtio: free vu_dev only with the contained struct device
+    - rxrpc: Fix deadlock around release of dst cached on udp tunnel
+    - arm64: dts: ls1046a: fix dcfg address range
+    - igc: set the default return value to -IGC_ERR_NVM in igc_write_nvm_srwr
+    - igc: check return value of ret_val in igc_config_fc_after_link_up
+    - i40e: Revert "i40e: don't report link up for a VF who hasn't enabled queues"
+    - net/mlx5: Fix leak upon failure of rule creation
+    - net: lapb: Copy the skb before sending a packet
+    - net: mvpp2: TCAM entry enable should be written after SRAM data
+    - r8169: fix WoL on shutdown if CONFIG_DEBUG_SHIRQ is set
+    - ARM: dts: sun7i: a20: bananapro: Fix ethernet phy-mode
+    - nvmet-tcp: fix out-of-bounds access when receiving multiple h2cdata PDUs
+    - memblock: do not start bottom-up allocations with kernel_end
+    - USB: gadget: legacy: fix an error code in eth_bind()
+    - USB: usblp: don't call usb_set_interface if there's a single alt
+    - usb: renesas_usbhs: Clear pipe running flag in usbhs_pkt_pop()
+    - usb: dwc2: Fix endpoint direction check in ep_from_windex
+    - usb: dwc3: fix clock issue during resume in OTG mode
+    - usb: xhci-mtk: fix unreleased bandwidth data
+    - usb: xhci-mtk: skip dropping bandwidth of unchecked endpoints
+    - usb: xhci-mtk: break loop when find the endpoint to drop
+    - usb: host: xhci-plat: add priv quirk for skip PHY initialization
+    - ovl: fix dentry leak in ovl_get_redirect
+    - mac80211: fix station rate table updates on assoc
+    - fgraph: Initialize tracing_graph_pause at task creation
+    - kretprobe: Avoid re-registration of the same kretprobe earlier
+    - libnvdimm/dimm: Avoid race between probe and available_slots_show()
+    - genirq/msi: Activate Multi-MSI early when MSI_FLAG_ACTIVATE_EARLY is set
+    - xhci: fix bounce buffer usage for non-sg list case
+    - cifs: report error instead of invalid when revalidating a dentry fails
+    - smb3: Fix out-of-bounds bug in SMB2_negotiate()
+    - smb3: fix crediting for compounding when only one request in flight
+    - mmc: core: Limit retries when analyse of SDIO tuples fails
+    - drm/amd/display: Revert "Fix EDID parsing after resume from suspend"
+    - nvme-pci: avoid the deepest sleep state on Kingston A2000 SSDs
+    - KVM: SVM: Treat SVM as unsupported when running as an SEV guest
+    - KVM: x86: Update emulator context mode if SYSENTER xfers to 64-bit mode
+    - ARM: footbridge: fix dc21285 PCI configuration accessors
+    - mm: hugetlbfs: fix cannot migrate the fallocated HugeTLB page
+    - mm: hugetlb: fix a race between freeing and dissolving the page
+    - mm: hugetlb: fix a race between isolating and freeing page
+    - mm: hugetlb: remove VM_BUG_ON_PAGE from page_huge_active
+    - mm, compaction: move high_pfn to the for loop scope
+    - mm: thp: fix MADV_REMOVE deadlock on shmem THP
+    - x86/build: Disable CET instrumentation in the kernel
+    - x86/apic: Add extra serialization for non-serializing MSRs
+    - iwlwifi: mvm: don't send RFH_QUEUE_CONFIG_CMD with no queues
+    - Input: xpad - sync supported devices with fork on GitHub
+    - iommu/vt-d: Do not use flush-queue when caching-mode is on
+    - md: Set prev_flush_start and flush_bio in an atomic way
+    - neighbour: Prevent a dead entry from updating gc_list
+    - net: ip_tunnel: fix mtu calculation
+    - net: dsa: mv88e6xxx: override existent unicast portvec in port_fdb_add
+    - net: sched: replaced invalid qdisc tree flush helper in qdisc_replace
+    - usb: host: xhci: mvebu: make USB 3.0 PHY optional for Armada 3720
+    - Linux 5.4.97
+
+  * Focal update: v5.4.96 upstream stable release (LP: #1916061)
+    - net: dsa: bcm_sf2: put device node before return
+    - net: switchdev: don't set port_obj_info->handled true when -EOPNOTSUPP
+    - ibmvnic: Ensure that CRQ entry read are correctly ordered
+    - Revert "Revert "block: end bio with BLK_STS_AGAIN in case of non-mq devs and
+      REQ_NOWAIT""
+    - ACPI: thermal: Do not call acpi_thermal_check() directly
+    - arm64: Fix kernel address detection of __is_lm_address()
+    - arm64: Do not pass tagged addresses to __is_lm_address()
+    - tcp: make TCP_USER_TIMEOUT accurate for zero window probes
+    - btrfs: backref, only collect file extent items matching backref offset
+    - btrfs: backref, don't add refs from shared block when resolving normal
+      backref
+    - btrfs: backref, only search backref entries from leaves of the same root
+    - btrfs: backref, use correct count to resolve normal data refs
+    - net_sched: gen_estimator: support large ewma log
+    - phy: cpcap-usb: Fix warning for missing regulator_disable
+    - platform/x86: touchscreen_dmi: Add swap-x-y quirk for Goodix touchscreen on
+      Estar Beauty HD tablet
+    - platform/x86: intel-vbtn: Support for tablet mode on Dell Inspiron 7352
+    - x86: __always_inline __{rd,wr}msr()
+    - scsi: scsi_transport_srp: Don't block target in failfast state
+    - scsi: libfc: Avoid invoking response handler twice if ep is already
+      completed
+    - scsi: fnic: Fix memleak in vnic_dev_init_devcmd2
+    - ASoC: SOF: Intel: hda: Resume codec to do jack detection
+    - mac80211: fix fast-rx encryption check
+    - scsi: ibmvfc: Set default timeout to avoid crash during migration
+    - udf: fix the problem that the disc content is not displayed
+    - nvme: check the PRINFO bit before deciding the host buffer length
+    - selftests/powerpc: Only test lwm/stmw on big endian
+    - drm/amd/display: Update dram_clock_change_latency for DCN2.1
+    - drm/amd/display: Change function decide_dp_link_settings to avoid infinite
+      looping
+    - objtool: Don't fail on missing symbol table
+    - kthread: Extract KTHREAD_IS_PER_CPU
+    - workqueue: Restrict affinity change to rescuer
+    - Linux 5.4.96
+
+  * Focal update: v5.4.95 upstream stable release (LP: #1916056)
+    - ICMPv6: Add ICMPv6 Parameter Problem, code 3 definition
+    - IPv6: reply ICMP error if the first fragment don't include all headers
+    - nbd: freeze the queue while we're adding connections
+    - ACPI: sysfs: Prefer "compatible" modalias
+    - kernel: kexec: remove the lock operation of system_transition_mutex
+    - ALSA: hda/realtek: Enable headset of ASUS B1400CEPE with ALC256
+    - ALSA: hda/via: Apply the workaround generically for Clevo machines
+    - media: rc: ensure that uevent can be read directly after rc device register
+    - ARM: dts: imx6qdl-gw52xx: fix duplicate regulator naming
+    - wext: fix NULL-ptr-dereference with cfg80211's lack of commit()
+    - net: usb: qmi_wwan: added support for Thales Cinterion PLSx3 modem family
+    - s390/vfio-ap: No need to disable IRQ after queue reset
+    - PM: hibernate: flush swap writer after marking
+    - drivers: soc: atmel: Avoid calling at91_soc_init on non AT91 SoCs
+    - drivers: soc: atmel: add null entry at the end of at91_soc_allowed_list[]
+    - btrfs: fix possible free space tree corruption with online conversion
+    - KVM: x86/pmu: Fix HW_REF_CPU_CYCLES event pseudo-encoding in
+      intel_arch_events[]
+    - KVM: x86/pmu: Fix UBSAN shift-out-of-bounds warning in intel_pmu_refresh()
+    - KVM: nVMX: Sync unsync'd vmcs02 state to vmcs12 on migration
+    - KVM: x86: get smi pending status correctly
+    - KVM: Forbid the use of tagged userspace addresses for memslots
+    - xen: Fix XenStore initialisation for XS_LOCAL
+    - leds: trigger: fix potential deadlock with libata
+    - arm64: dts: broadcom: Fix USB DMA address translation for Stingray
+    - mt7601u: fix kernel crash unplugging the device
+    - mt7601u: fix rx buffer refcounting
+    - drm/nouveau/svm: fail NOUVEAU_SVM_INIT ioctl on unsupported devices
+    - drm/i915: Check for all subplatform bits
+    - tee: optee: replace might_sleep with cond_resched
+    - xen-blkfront: allow discard-* nodes to be optional
+    - ARM: imx: build suspend-imx6.S with arm instruction set
+    - netfilter: nft_dynset: add timeout extension to template
+    - xfrm: Fix oops in xfrm_replay_advance_bmp
+    - xfrm: fix disable_xfrm sysctl when used on xfrm interfaces
+    - selftests: xfrm: fix test return value override issue in xfrm_policy.sh
+    - xfrm: Fix wraparound in xfrm_policy_addr_delta()
+    - arm64: dts: ls1028a: fix the offset of the reset register
+    - ARM: dts: imx6qdl-kontron-samx6i: fix i2c_lcd/cam default status
+    - firmware: imx: select SOC_BUS to fix firmware build
+    - RDMA/cxgb4: Fix the reported max_recv_sge value
+    - ASoC: Intel: Skylake: skl-topology: Fix OOPs ib skl_tplg_complete
+    - pNFS/NFSv4: Fix a layout segment leak in pnfs_layout_process()
+    - iwlwifi: pcie: use jiffies for memory read spin time limit
+    - iwlwifi: pcie: reschedule in long-running memory reads
+    - mac80211: pause TX while changing interface type
+    - i40e: acquire VSI pointer only after VF is initialized
+    - igc: fix link speed advertising
+    - net/mlx5: Fix memory leak on flow table creation error flow
+    - net/mlx5e: E-switch, Fix rate calculation for overflow
+    - net/mlx5e: Reduce tc unsupported key print level
+    - can: dev: prevent potential information leak in can_fill_info()
+    - nvme-multipath: Early exit if no path is available
+    - selftests: forwarding: Specify interface when invoking mausezahn
+    - iommu/vt-d: Gracefully handle DMAR units with no supported address widths
+    - iommu/vt-d: Don't dereference iommu_device if IOMMU_API is not built
+    - rxrpc: Fix memory leak in rxrpc_lookup_local
+    - NFC: fix resource leak when target index is invalid
+    - NFC: fix possible resource leak
+    - ASoC: topology: Fix memory corruption in soc_tplg_denum_create_values()
+    - team: protect features update by RCU to avoid deadlock
+    - tcp: fix TLP timer not set when CA_STATE changes from DISORDER to OPEN
+    - Linux 5.4.95
+
+ -- Kleber Sacilotto de Souza <kleber.souza@canonical.com>  Wed, 24 Mar 2021 11:25:50 +0100
+
+linux (5.4.0-70.78) focal; urgency=medium
+
+  * CVE-2020-27170
+    - bpf: Fix off-by-one for area size in creating mask to left
+
+  * CVE-2020-27171
+    - bpf: Prohibit alu ops for pointer types not defining ptr_limit
+
+  * binary assembly failures with CONFIG_MODVERSIONS present (LP: #1919315)
+    - [Packaging] quiet (nomially) benign errors in BUILD script
+
+ -- Kleber Sacilotto de Souza <kleber.souza@canonical.com>  Fri, 19 Mar 2021 12:57:03 +0100
+
+linux (5.4.0-69.77) focal; urgency=medium
+
+  * CVE-2021-3444
+    - bpf: Fix 32 bit src register truncation on div/mod
+    - bpf: Fix truncation handling for mod32 dst reg wrt zero
+
+  * CVE-2021-27365
+    - scsi: iscsi: Verify lengths on passthrough PDUs
+    - sysfs: Add sysfs_emit and sysfs_emit_at to format sysfs output
+    - scsi: iscsi: Ensure sysfs attributes are limited to PAGE_SIZE
+
+  * CVE-2021-27363 // CVE-2021-27364
+    - scsi: iscsi: Restrict sessions and handles to admin capabilities
+
+ -- Kleber Sacilotto de Souza <kleber.souza@canonical.com>  Tue, 16 Mar 2021 12:29:06 +0100
+
+linux (5.4.0-67.75) focal; urgency=medium
+
+  * focal/linux: 5.4.0-67.75 -proposed tracker (LP: #1916169)
+
+  * Please trust Canonical Livepatch Service kmod signing key (LP: #1898716)
+    - [Config] enable CONFIG_MODVERSIONS=y
+    - [Packaging] build canonical-certs.pem from branch/arch certs
+    - [Config] add Canonical Livepatch Service key to SYSTEM_TRUSTED_KEYS
+    - [Config] add ubuntu-drivers key to SYSTEM_TRUSTED_KEYS
+    - [Config] Allow ASM_MODVERSIONS and MODULE_REL_CRCS
+
+  * geneve overlay network on vlan interface broken with offload enabled
+    (LP: #1914447)
+    - net/mlx5e: Fix SWP offsets when vlan inserted by driver
+
+  * Add support for selective build of special drivers (LP: #1912789)
+    - [Packaging] Fix ODM support in actual build
+
+  * devlink: don't do reporter recovery if the state is healthy (LP: #1915403)
+    - devlink: don't do reporter recovery if the state is healthy
+
+  * Missing device id for Intel TGL-H ISH [8086:43fc] in intel-ish-hid driver
+    (LP: #1914543)
+    - HID: intel-ish-hid: ipc: Add Tiger Lake H PCI device ID
+
+  * Focal update: v5.4.94 upstream stable release (LP: #1915200)
+    - gpio: mvebu: fix pwm .get_state period calculation
+    - futex: Ensure the correct return value from futex_lock_pi()
+    - futex: Replace pointless printk in fixup_owner()
+    - futex: Provide and use pi_state_update_owner()
+    - rtmutex: Remove unused argument from rt_mutex_proxy_unlock()
+    - futex: Use pi_state_update_owner() in put_pi_state()
+    - futex: Simplify fixup_pi_state_owner()
+    - futex: Handle faults correctly for PI futexes
+    - HID: wacom: Correct NULL dereference on AES pen proximity
+    - io_uring: Fix current->fs handling in io_sq_wq_submit_work()
+    - tracing: Fix race in trace_open and buffer resize call
+    - arm64: mm: use single quantity to represent the PA to VA translation
+    - SMB3.1.1: do not log warning message if server doesn't populate salt
+    - tools: Factor HOSTCC, HOSTLD, HOSTAR definitions
+    - dm integrity: conditionally disable "recalculate" feature
+    - writeback: Drop I_DIRTY_TIME_EXPIRE
+    - fs: fix lazytime expiration handling in __writeback_single_inode()
+    - Linux 5.4.94
+
+  * Focal update: v5.4.93 upstream stable release (LP: #1915195)
+    - i2c: bpmp-tegra: Ignore unknown I2C_M flags
+    - platform/x86: ideapad-laptop: Disable touchpad_switch for ELAN0634
+    - ALSA: seq: oss: Fix missing error check in snd_seq_oss_synth_make_info()
+    - ALSA: hda/via: Add minimum mute flag
+    - ACPI: scan: Make acpi_bus_get_device() clear return pointer on error
+    - btrfs: don't get an EINTR during drop_snapshot for reloc
+    - btrfs: fix lockdep splat in btrfs_recover_relocation
+    - btrfs: don't clear ret in btrfs_start_dirty_block_groups
+    - btrfs: send: fix invalid clone operations when cloning from the same file
+      and root
+    - mmc: core: don't initialize block size from ext_csd if not present
+    - mmc: sdhci-xenon: fix 1.8v regulator stabilization
+    - dm: avoid filesystem lookup in dm_get_dev_t()
+    - dm integrity: fix a crash if "recalculate" used without "internal_hash"
+    - drm/atomic: put state on error path
+    - drm/syncobj: Fix use-after-free
+    - drm/i915/gt: Prevent use of engine->wa_ctx after error
+    - ASoC: Intel: haswell: Add missing pm_ops
+    - dm integrity: select CRYPTO_SKCIPHER
+    - scsi: ufs: Correct the LUN used in eh_device_reset_handler() callback
+    - scsi: qedi: Correct max length of CHAP secret
+    - scsi: sd: Suppress spurious errors when WRITE SAME is being disabled
+    - riscv: Fix kernel time_init()
+    - riscv: Fix sifive serial driver
+    - HID: logitech-dj: add the G602 receiver
+    - HID: Ignore battery for Elan touchscreen on ASUS UX550
+    - clk: tegra30: Add hda clock default rates to clock driver
+    - arm64: make atomic helpers __always_inline
+    - xen: Fix event channel callback via INTX/GSI
+    - x86/xen: Add xen_no_vector_callback option to test PCI INTX delivery
+    - dts: phy: fix missing mdio device and probe failure of vsc8541-01 device
+    - riscv: defconfig: enable gpio support for HiFive Unleashed
+    - drm/amdgpu/psp: fix psp gfx ctrl cmds
+    - drm/amd/display: Fix to be able to stop crc calculation
+    - drm/nouveau/bios: fix issue shadowing expansion ROMs
+    - drm/nouveau/privring: ack interrupts the same way as RM
+    - drm/nouveau/i2c/gm200: increase width of aux semaphore owner fields
+    - drm/nouveau/mmu: fix vram heap sizing
+    - drm/nouveau/kms/nv50-: fix case where notifier buffer is at offset 0
+    - powerpc: Use the common INIT_DATA_SECTION macro in vmlinux.lds.S
+    - pinctrl: aspeed: g6: Fix PWMG0 pinctrl setting
+    - scsi: megaraid_sas: Fix MEGASAS_IOC_FIRMWARE regression
+    - powerpc: Fix alignment bug within the init sections
+    - i2c: octeon: check correct size of maximum RECV_LEN packet
+    - platform/x86: intel-vbtn: Drop HP Stream x360 Convertible PC 11 from allow-
+      list
+    - selftests: net: fib_tests: remove duplicate log test
+    - can: dev: can_restart: fix use after free bug
+    - can: vxcan: vxcan_xmit: fix use after free bug
+    - can: peak_usb: fix use after free bugs
+    - iio: ad5504: Fix setting power-down state
+    - cifs: do not fail __smb_send_rqst if non-fatal signals are pending
+    - irqchip/mips-cpu: Set IPI domain parent chip
+    - x86/fpu: Add kernel_fpu_begin_mask() to selectively initialize state
+    - x86/topology: Make __max_die_per_package available unconditionally
+    - x86/mmx: Use KFPU_387 for MMX string operations
+    - intel_th: pci: Add Alder Lake-P support
+    - stm class: Fix module init return on allocation failure
+    - serial: mvebu-uart: fix tx lost characters at power off
+    - ehci: fix EHCI host controller initialization sequence
+    - USB: ehci: fix an interrupt calltrace error
+    - usb: gadget: aspeed: fix stop dma register setting.
+    - usb: udc: core: Use lock when write to soft_connect
+    - [Config] updateconfigs for USB_BDC_PCI
+    - usb: bdc: Make bdc pci driver depend on BROKEN
+    - xhci: make sure TRB is fully written before giving it to the controller
+    - xhci: tegra: Delay for disabling LFPS detector
+    - driver core: Extend device_is_dependent()
+    - pinctrl: ingenic: Fix JZ4760 support
+    - x86/cpu/amd: Set __max_die_per_package on AMD
+    - netfilter: rpfilter: mask ecn bits before fib lookup
+    - sh: dma: fix kconfig dependency for G2_DMA
+    - net: dsa: mv88e6xxx: also read STU state in mv88e6250_g1_vtu_getnext
+    - sh_eth: Fix power down vs. is_opened flag ordering
+    - lightnvm: fix memory leak when submit fails
+    - skbuff: back tiny skbs with kmalloc() in __netdev_alloc_skb() too
+    - kasan: fix unaligned address is unhandled in kasan_remove_zero_shadow
+    - kasan: fix incorrect arguments passing in kasan_add_zero_shadow
+    - udp: mask TOS bits in udp_v4_early_demux()
+    - ipv6: create multicast route with RTPROT_KERNEL
+    - net_sched: avoid shift-out-of-bounds in tcindex_set_parms()
+    - net_sched: reject silly cell_log in qdisc_get_rtab()
+    - ipv6: set multicast flag on the multicast route
+    - net: mscc: ocelot: allow offloading of bridge on top of LAG
+    - net: Disable NETIF_F_HW_TLS_RX when RXCSUM is disabled
+    - net: dsa: b53: fix an off by one in checking "vlan->vid"
+    - tcp: do not mess with cloned skbs in tcp_add_backlog()
+    - tcp: fix TCP_USER_TIMEOUT with zero window
+    - Linux 5.4.93
+
+  * High load from process irq/65-i2c-INT3  - kernel module tps6598x
+    (LP: #1883511) // Focal update: v5.4.93 upstream stable release
+    (LP: #1915195)
+    - platform/x86: i2c-multi-instantiate: Don't create platform device for
+      INT3515 ACPI nodes
+
+  * Focal update: v5.4.92 upstream stable release (LP: #1915186)
+    - usb: ohci: Make distrust_firmware param default to false
+    - compiler.h: Raise minimum version of GCC to 5.1 for arm64
+    - xen/privcmd: allow fetching resource sizes
+    - elfcore: fix building with clang
+    - scsi: lpfc: Make lpfc_defer_acc_rsp static
+    - spi: npcm-fiu: simplify the return expression of npcm_fiu_probe()
+    - spi: npcm-fiu: Disable clock in probe error path
+    - nfsd4: readdirplus shouldn't return parent of export
+    - bpf: Don't leak memory in bpf getsockopt when optlen == 0
+    - bpf: Fix helper bpf_map_peek_elem_proto pointing to wrong callback
+    - udp: Prevent reuseport_select_sock from reading uninitialized socks
+    - netxen_nic: fix MSI/MSI-x interrupts
+    - net: introduce skb_list_walk_safe for skb segment walking
+    - net: skbuff: disambiguate argument and member for skb_list_walk_safe helper
+    - net: ipv6: Validate GSO SKB before finish IPv6 processing
+    - mlxsw: core: Add validation of transceiver temperature thresholds
+    - mlxsw: core: Increase critical threshold for ASIC thermal zone
+    - net: mvpp2: Remove Pause and Asym_Pause support
+    - rndis_host: set proper input size for OID_GEN_PHYSICAL_MEDIUM request
+    - esp: avoid unneeded kmap_atomic call
+    - net: dcb: Validate netlink message in DCB handler
+    - net: dcb: Accept RTM_GETDCB messages carrying set-like DCB commands
+    - rxrpc: Call state should be read with READ_ONCE() under some circumstances
+    - net: stmmac: Fixed mtu channged by cache aligned
+    - net: sit: unregister_netdevice on newlink's error path
+    - net: avoid 32 x truesize under-estimation for tiny skbs
+    - rxrpc: Fix handling of an unsupported token type in rxrpc_read()
+    - net, sctp, filter: remap copy_from_user failure error
+    - tipc: fix NULL deref in tipc_link_xmit()
+    - mac80211: do not drop tx nulldata packets on encrypted links
+    - mac80211: check if atf has been disabled in __ieee80211_schedule_txq
+    - spi: cadence: cache reference clock rate during probe
+    - Linux 5.4.92
+
+  * intel-hid is not loaded on new Intel platform (LP: #1907160)
+    - platform/x86: intel-hid: Add Tiger Lake ACPI device ID
+    - platform/x86: intel-hid: fix: Update Tiger Lake ACPI device ID
+    - platform/x86: intel-hid: Move MODULE_DEVICE_TABLE() closer to the table
+    - platform/x86: intel-hid: add Rocket Lake ACPI device ID
+
+  * Support Advantech UNO-420 platform (LP: #1902672)
+    - ODM: MAINTAINERS: Add Advantech AHC1EC0 embedded controller entry
+    - ODM: mfd: ahc1ec0: Add Advantech EC include file used by dt-bindings
+    - ODM: dt-bindings: mfd: ahc1ec0.yaml: Add Advantech embedded controller -
+      AHC1EC0
+    - ODM: mfd: ahc1ec0: Add support for Advantech embedded controller
+    - ODM: hwmon: ahc1ec0-hwmon: Add sub-device hwmon for Advantech embedded
+      controller
+    - ODM: watchdog: ahc1ec0-wdt: Add sub-device watchdog for Advantech embedded
+      controller
+    - ODM: [Config] update config for Advantech devices
+
+  * Remove scary stack trace from Realtek WiFi driver (LP: #1913263)
+    - rtw88: reduce the log level for failure of tx report
+
+  * Focal update: v5.4.91 upstream stable release (LP: #1914654)
+    - kbuild: enforce -Werror=return-type
+    - btrfs: prevent NULL pointer dereference in extent_io_tree_panic
+    - ASoC: dapm: remove widget from dirty list on free
+    - x86/hyperv: check cpu mask after interrupt has been disabled
+    - tracing/kprobes: Do the notrace functions check without kprobes on ftrace
+    - [Config] update annotations for KPROBE_EVENTS_ON_NOTRACE
+    - mips: fix Section mismatch in reference
+    - mips: lib: uncached: fix non-standard usage of variable 'sp'
+    - MIPS: boot: Fix unaligned access with CONFIG_MIPS_RAW_APPENDED_DTB
+    - MIPS: relocatable: fix possible boot hangup with KASLR enabled
+    - RDMA/ocrdma: Fix use after free in ocrdma_dealloc_ucontext_pd()
+    - ACPI: scan: Harden acpi_device_add() against device ID overflows
+    - mm/hugetlb: fix potential missing huge page size info
+    - dm raid: fix discard limits for raid1
+    - dm snapshot: flush merged data before committing metadata
+    - dm integrity: fix the maximum number of arguments
+    - r8152: Add Lenovo Powered USB-C Travel Hub
+    - btrfs: tree-checker: check if chunk item end overflows
+    - drm/i915/backlight: fix CPU mode backlight takeover on LPT
+    - ext4: fix bug for rename with RENAME_WHITEOUT
+    - ext4: don't leak old mountpoint samples
+    - cifs: fix interrupted close commands
+    - dm integrity: fix flush with external metadata device
+    - ARC: build: remove non-existing bootpImage from KBUILD_IMAGE
+    - ARC: build: add uImage.lzma to the top-level target
+    - ARC: build: add boot_targets to PHONY
+    - ARC: build: move symlink creation to arch/arc/Makefile to avoid race
+    - netfilter: ipset: fixes possible oops in mtype_resize
+    - btrfs: fix transaction leak and crash after RO remount caused by qgroup
+      rescan
+    - regulator: bd718x7: Add enable times
+    - ethernet: ucc_geth: fix definition and size of ucc_geth_tx_global_pram
+    - habanalabs: register to pci shutdown callback
+    - habanalabs: Fix memleak in hl_device_reset
+    - hwmon: (pwm-fan) Ensure that calculation doesn't discard big period values
+    - lib/raid6: Let $(UNROLL) rules work with macOS userland
+    - bfq: Fix computation of shallow depth
+    - arch/arc: add copy_user_page() to <asm/page.h> to fix build error on ARC
+    - misdn: dsp: select CONFIG_BITREVERSE
+    - net: ethernet: fs_enet: Add missing MODULE_LICENSE
+    - nvme-pci: mark Samsung PM1725a as IGNORE_DEV_SUBNQN
+    - nvmet-rdma: Fix list_del corruption on queue establishment failure
+    - drm/amdgpu: fix a GPU hang issue when remove device
+    - usb: typec: Fix copy paste error for NVIDIA alt-mode description
+    - ACPI: scan: add stub acpi_create_platform_device() for !CONFIG_ACPI
+    - drm/msm: Call msm_init_vram before binding the gpu
+    - ARM: picoxcell: fix missing interrupt-parent properties
+    - perf intel-pt: Fix 'CPU too large' error
+    - dump_common_audit_data(): fix racy accesses to ->d_name
+    - ASoC: meson: axg-tdm-interface: fix loopback
+    - ASoC: meson: axg-tdmin: fix axg skew offset
+    - ASoC: Intel: fix error code cnl_set_dsp_D0()
+    - nvme-tcp: fix possible data corruption with bio merges
+    - NFS4: Fix use-after-free in trace_event_raw_event_nfs4_set_lock
+    - pNFS: We want return-on-close to complete when evicting the inode
+    - pNFS: Mark layout for return if return-on-close was not sent
+    - pNFS: Stricter ordering of layoutget and layoutreturn
+    - NFS/pNFS: Fix a leak of the layout 'plh_outstanding' counter
+    - NFS: nfs_igrab_and_active must first reference the superblock
+    - ext4: fix superblock checksum failure when setting password salt
+    - RDMA/restrack: Don't treat as an error allocation ID wrapping
+    - RDMA/usnic: Fix memleak in find_free_vf_and_create_qp_grp
+    - bnxt_en: Improve stats context resource accounting with RDMA driver loaded.
+    - RDMA/mlx5: Fix wrong free of blue flame register on error
+    - IB/mlx5: Fix error unwinding when set_has_smi_cap fails
+    - drm/i915/dsi: Use unconditional msleep for the panel_on_delay when there is
+      no reset-deassert MIPI-sequence
+    - mm, slub: consider rest of partial list if acquire_slab() fails
+    - iommu/vt-d: Fix unaligned addresses for intel_flush_svm_range_dev()
+    - net: sunrpc: interpret the return value of kstrtou32 correctly
+    - dm: eliminate potential source of excessive kernel log noise
+    - ALSA: fireface: Fix integer overflow in transmit_midi_msg()
+    - ALSA: firewire-tascam: Fix integer overflow in midi_port_work()
+    - netfilter: conntrack: fix reading nf_conntrack_buckets
+    - netfilter: nf_nat: Fix memleak in nf_nat_init
+    - netfilter: nft_compat: remove flush counter optimization
+    - Linux 5.4.91
+
+  * Focal update: v5.4.90 upstream stable release (LP: #1913487)
+    - x86/asm/32: Add ENDs to some functions and relabel with SYM_CODE_*
+    - vfio iommu: Add dma available capability
+    - net: cdc_ncm: correct overhead in delayed_ndp_size
+    - net: hns3: fix the number of queues actually used by ARQ
+    - net: hns3: fix a phy loopback fail issue
+    - net: stmmac: dwmac-sun8i: Balance internal PHY resource references
+    - net: stmmac: dwmac-sun8i: Balance internal PHY power
+    - net: vlan: avoid leaks on register_vlan_dev() failures
+    - net/sonic: Fix some resource leaks in error handling paths
+    - net: ipv6: fib: flush exceptions when purging route
+    - tools: selftests: add test for changing routes with PTMU exceptions
+    - net: fix pmtu check in nopmtudisc mode
+    - net: ip: always refragment ip defragmented packets
+    - octeontx2-af: fix memory leak of lmac and lmac->name
+    - nexthop: Fix off-by-one error in error path
+    - nexthop: Unlink nexthop group entry in error path
+    - s390/qeth: fix L2 header access in qeth_l3_osa_features_check()
+    - net: dsa: lantiq_gswip: Exclude RMII from modes that report 1 GbE
+    - net/mlx5: Use port_num 1 instead of 0 when delete a RoCE address
+    - net/mlx5e: ethtool, Fix restriction of autoneg with 56G
+    - chtls: Fix hardware tid leak
+    - chtls: Remove invalid set_tcb call
+    - chtls: Fix panic when route to peer not configured
+    - chtls: Replace skb_dequeue with skb_peek
+    - chtls: Added a check to avoid NULL pointer dereference
+    - chtls: Fix chtls resources release sequence
+    - x86/resctrl: Use an IPI instead of task_work_add() to update PQR_ASSOC MSR
+    - x86/resctrl: Don't move a task to the same resource group
+    - exfat: Month timestamp metadata accidentally incremented
+    - vmlinux.lds.h: Add PGO and AutoFDO input sections
+    - iio: imu: st_lsm6dsx: fix edge-trigger interrupts
+    - HID: wacom: Fix memory leakage caused by kfifo_alloc
+    - ARM: OMAP2+: omap_device: fix idling of devices during probe
+    - i2c: sprd: use a specific timeout to avoid system hang up issue
+    - dmaengine: dw-edma: Fix use after free in dw_edma_alloc_chunk()
+    - can: tcan4x5x: fix bittiming const, use common bittiming from m_can driver
+    - can: m_can: m_can_class_unregister(): remove erroneous m_can_clk_stop()
+    - can: kvaser_pciefd: select CONFIG_CRC32
+    - cpufreq: powernow-k8: pass policy rather than use cpufreq_cpu_get()
+    - spi: stm32: FIFO threshold level - fix align packet size
+    - i2c: i801: Fix the i2c-mux gpiod_lookup_table not being properly terminated
+    - dmaengine: mediatek: mtk-hsdma: Fix a resource leak in the error handling
+      path of the probe function
+    - dmaengine: xilinx_dma: check dma_async_device_register return value
+    - dmaengine: xilinx_dma: fix incompatible param warning in _child_probe()
+    - dmaengine: xilinx_dma: fix mixed_enum_type coverity warning
+    - qed: select CONFIG_CRC32
+    - wil6210: select CONFIG_CRC32
+    - block: rsxx: select CONFIG_CRC32
+    - lightnvm: select CONFIG_CRC32
+    - iommu/intel: Fix memleak in intel_irq_remapping_alloc
+    - bpftool: Fix compilation failure for net.o with older glibc
+    - net/mlx5e: Fix memleak in mlx5e_create_l2_table_groups
+    - net/mlx5e: Fix two double free cases
+    - regmap: debugfs: Fix a memory leak when calling regmap_attach_dev
+    - wan: ds26522: select CONFIG_BITREVERSE
+    - regulator: qcom-rpmh-regulator: correct hfsmps515 definition
+    - net: mvpp2: disable force link UP during port init procedure
+    - KVM: arm64: Don't access PMCR_EL0 when no PMU is available
+    - block: fix use-after-free in disk_part_iter_next
+    - net: drop bogus skb with CHECKSUM_PARTIAL and offset beyond end of trimmed
+      packet
+    - regmap: debugfs: Fix a reversed if statement in regmap_debugfs_init()
+    - Linux 5.4.90
+
+  * Focal update: v5.4.89 upstream stable release (LP: #1913486)
+    - workqueue: Kick a worker based on the actual activation of delayed works
+    - scsi: ufs: Fix wrong print message in dev_err()
+    - scsi: ufs-pci: Ensure UFS device is in PowerDown mode for suspend-to-disk
+      ->poweroff()
+    - scsi: ide: Do not set the RQF_PREEMPT flag for sense requests
+    - scsi: scsi_transport_spi: Set RQF_PM for domain validation commands
+    - lib/genalloc: fix the overflow when size is too big
+    - depmod: handle the case of /sbin/depmod without /sbin in PATH
+    - proc: change ->nlink under proc_subdir_lock
+    - proc: fix lookup in /proc/net subdirectories after setns(2)
+    - i40e: Fix Error I40E_AQ_RC_EINVAL when removing VFs
+    - iavf: fix double-release of rtnl_lock
+    - net: mvpp2: Add TCAM entry to drop flow control pause frames
+    - net: mvpp2: prs: fix PPPoE with ipv6 packet parse
+    - net: systemport: set dev->max_mtu to UMAC_MAX_MTU_SIZE
+    - ethernet: ucc_geth: fix use-after-free in ucc_geth_remove()
+    - ethernet: ucc_geth: set dev->max_mtu to 1518
+    - atm: idt77252: call pci_disable_device() on error path
+    - net: mvpp2: Fix GoP port 3 Networking Complex Control configurations
+    - ibmvnic: continue fatal error reset after passive init
+    - net: ethernet: mvneta: Fix error handling in mvneta_probe
+    - virtio_net: Fix recursive call to cpus_read_lock()
+    - net/ncsi: Use real net-device for response handler
+    - net: ethernet: Fix memleak in ethoc_probe
+    - net-sysfs: take the rtnl lock when storing xps_cpus
+    - net-sysfs: take the rtnl lock when accessing xps_cpus_map and num_tc
+    - net-sysfs: take the rtnl lock when storing xps_rxqs
+    - net-sysfs: take the rtnl lock when accessing xps_rxqs_map and num_tc
+    - net: ethernet: ti: cpts: fix ethtool output when no ptp_clock registered
+    - tun: fix return value when the number of iovs exceeds MAX_SKB_FRAGS
+    - net: mvpp2: fix pkt coalescing int-threshold configuration
+    - ipv4: Ignore ECN bits for fib lookups in fib_compute_spec_dst()
+    - net: sched: prevent invalid Scell_log shift count
+    - net: hns: fix return value check in __lb_other_process()
+    - erspan: fix version 1 check in gre_parse_header()
+    - net: hdlc_ppp: Fix issues when mod_timer is called while timer is running
+    - r8169: work around power-saving bug on some chip versions
+    - net: dsa: lantiq_gswip: Enable GSWIP_MII_CFG_EN also for internal PHYs
+    - net: dsa: lantiq_gswip: Fix GSWIP_MII_CFG(p) register access
+    - CDC-NCM: remove "connected" log message
+    - net: usb: qmi_wwan: add Quectel EM160R-GL
+    - vhost_net: fix ubuf refcount incorrectly when sendmsg fails
+    - ionic: account for vlan tag len in rx buffer len
+    - net/sched: sch_taprio: ensure to reset/destroy all child qdiscs
+    - kbuild: don't hardcode depmod path
+    - Bluetooth: revert: hci_h5: close serdev device and free hu in h5_close
+    - video: hyperv_fb: Fix the mmap() regression for v5.4.y and older
+    - crypto: ecdh - avoid buffer overflow in ecdh_set_secret()
+    - crypto: asym_tpm: correct zero out potential secrets
+    - powerpc: Handle .text.{hot,unlikely}.* in linker script
+    - staging: mt7621-dma: Fix a resource leak in an error handling path
+    - usb: gadget: enable super speed plus
+    - USB: cdc-acm: blacklist another IR Droid device
+    - USB: cdc-wdm: Fix use after free in service_outstanding_interrupt().
+    - usb: dwc3: ulpi: Use VStsDone to detect PHY regs access completion
+    - usb: chipidea: ci_hdrc_imx: add missing put_device() call in
+      usbmisc_get_init_data()
+    - USB: xhci: fix U1/U2 handling for hardware with XHCI_INTEL_HOST quirk set
+    - usb: usbip: vhci_hcd: protect shift size
+    - usb: uas: Add PNY USB Portable SSD to unusual_uas
+    - USB: serial: iuu_phoenix: fix DMA from stack
+    - USB: serial: option: add LongSung M5710 module support
+    - USB: serial: option: add Quectel EM160R-GL
+    - USB: yurex: fix control-URB timeout handling
+    - USB: usblp: fix DMA to stack
+    - ALSA: usb-audio: Fix UBSAN warnings for MIDI jacks
+    - usb: gadget: select CONFIG_CRC32
+    - usb: gadget: f_uac2: reset wMaxPacketSize
+    - usb: gadget: function: printer: Fix a memory leak for interface descriptor
+    - usb: gadget: u_ether: Fix MTU size mismatch with RX packet size
+    - USB: gadget: legacy: fix return error code in acm_ms_bind()
+    - usb: gadget: Fix spinlock lockup on usb_function_deactivate
+    - usb: gadget: configfs: Preserve function ordering after bind failure
+    - usb: gadget: configfs: Fix use-after-free issue with udc_name
+    - USB: serial: keyspan_pda: remove unused variable
+    - x86/mm: Fix leak of pmd ptlock
+    - kvm: check tlbs_dirty directly
+    - ALSA: hda/via: Fix runtime PM for Clevo W35xSS
+    - ALSA: hda/conexant: add a new hda codec CX11970
+    - ALSA: hda/realtek - Fix speaker volume control on Lenovo C940
+    - ALSA: hda/realtek: Add two "Intel Reference board" SSID in the ALC256.
+    - btrfs: send: fix wrong file path when there is an inode with a pending rmdir
+    - Revert "device property: Keep secondary firmware node secondary by type"
+    - dmabuf: fix use-after-free of dmabuf's file->f_inode
+    - drm/i915: clear the gpu reloc batch
+    - netfilter: x_tables: Update remaining dereference to RCU
+    - netfilter: ipset: fix shift-out-of-bounds in htable_bits()
+    - netfilter: xt_RATEEST: reject non-null terminated string from userspace
+    - netfilter: nft_dynset: report EOPNOTSUPP on missing set feature
+    - x86/mtrr: Correct the range check before performing MTRR type lookups
+    - KVM: x86: fix shift out of bounds reported by UBSAN
+    - Linux 5.4.89
+
+  * Focal update: v5.4.88 upstream stable release (LP: #1913223)
+    - Revert "drm/amd/display: Fix memory leaks in S3 resume"
+    - Revert "mtd: spinand: Fix OOB read"
+    - dmaengine: at_hdmac: Substitute kzalloc with kmalloc
+    - dmaengine: at_hdmac: add missing put_device() call in at_dma_xlate()
+    - dmaengine: at_hdmac: add missing kfree() call in at_dma_xlate()
+    - kdev_t: always inline major/minor helper functions
+    - iio:imu:bmi160: Fix alignment and data leak issues
+    - fuse: fix bad inode
+    - perf: Break deadlock involving exec_update_mutex
+    - rwsem: Implement down_read_killable_nested
+    - rwsem: Implement down_read_interruptible
+    - exec: Transform exec_update_mutex into a rw_semaphore
+    - mwifiex: Fix possible buffer overflows in mwifiex_cmd_802_11_ad_hoc_start
+    - Linux 5.4.88
+
+  * Focal update: v5.4.87 upstream stable release (LP: #1912681)
+    - net/sched: sch_taprio: reset child qdiscs before freeing them
+    - md/raid10: initialize r10_bio->read_slot before use.
+    - thermal/drivers/cpufreq_cooling: Update cpufreq_state only if state has
+      changed
+    - ext4: prevent creating duplicate encrypted filenames
+    - ubifs: prevent creating duplicate encrypted filenames
+    - f2fs: prevent creating duplicate encrypted filenames
+    - fscrypt: add fscrypt_is_nokey_name()
+    - fscrypt: remove kernel-internal constants from UAPI header
+    - vfio/pci: Move dummy_resources_list init in vfio_pci_probe()
+    - btrfs: fix race when defragmenting leads to unnecessary IO
+    - ext4: don't remount read-only with errors=continue on reboot
+    - KVM: x86: avoid incorrect writes to host MSR_IA32_SPEC_CTRL
+    - KVM: SVM: relax conditions for allowing MSR_IA32_SPEC_CTRL accesses
+    - KVM: x86: reinstate vendor-agnostic check on SPEC_CTRL cpuid bits
+    - powerpc/bitops: Fix possible undefined behaviour with fls() and fls64()
+    - jffs2: Allow setting rp_size to zero during remounting
+    - jffs2: Fix NULL pointer dereference in rp_size fs option parsing
+    - scsi: block: Fix a race in the runtime power management code
+    - uapi: move constants from <linux/kernel.h> to <linux/const.h>
+    - tools headers UAPI: Sync linux/const.h with the kernel headers
+    - null_blk: Fix zone size initialization
+    - of: fix linker-section match-table corruption
+    - cgroup: Fix memory leak when parsing multiple source parameters
+    - scsi: cxgb4i: Fix TLS dependency
+    - Bluetooth: hci_h5: close serdev device and free hu in h5_close
+    - reiserfs: add check for an invalid ih_entry_count
+    - misc: vmw_vmci: fix kernel info-leak by initializing dbells in
+      vmci_ctx_get_chkpt_doorbells()
+    - media: gp8psk: initialize stats at power control logic
+    - f2fs: fix shift-out-of-bounds in sanity_check_raw_super()
+    - ALSA: seq: Use bool for snd_seq_queue internal flags
+    - ALSA: rawmidi: Access runtime->avail always in spinlock
+    - bfs: don't use WARNING: string when it's just info.
+    - fcntl: Fix potential deadlock in send_sig{io, urg}()
+    - rtc: sun6i: Fix memleak in sun6i_rtc_clk_init
+    - module: set MODULE_STATE_GOING state when a module fails to load
+    - quota: Don't overflow quota file offsets
+    - rtc: pl031: fix resource leak in pl031_probe
+    - powerpc: sysdev: add missing iounmap() on error in mpic_msgr_probe()
+    - i3c master: fix missing destroy_workqueue() on error in i3c_master_register
+    - NFSv4: Fix a pNFS layout related use-after-free race when freeing the inode
+    - f2fs: avoid race condition for shrinker count
+    - module: delay kobject uevent until after module init call
+    - fs/namespace.c: WARN if mnt_count has become negative
+    - um: ubd: Submit all data segments atomically
+    - tick/sched: Remove bogus boot "safety" check
+    - ALSA: pcm: Clear the full allocated memory at hw_params
+    - dm verity: skip verity work if I/O error when system is shutting down
+    - Linux 5.4.87
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Fri, 19 Feb 2021 17:11:23 +0100
+
+linux (5.4.0-66.74) focal; urgency=medium
+
+  * focal/linux: 5.4.0-66.74 -proposed tracker (LP: #1913152)
+
+  * Add support for selective build of special drivers (LP: #1912789)
+    - [Packaging] Add support for ODM drivers
+    - [Packaging] Turn on ODM support for amd64
+
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+    - update dkms package versions
+
+  * Introduce the new NVIDIA 460-server series and update the 460 series
+    (LP: #1913200)
+    - [Config] dkms-versions -- drop NVIDIA 435 455 and 440-server
+    - [Config] dkms-versions -- add the 460-server nvidia driver
+
+  * Enable mute and micmute LED on HP EliteBook 850 G7 (LP: #1910102)
+    - ALSA: hda/realtek: Enable mute and micmute LED on HP EliteBook 850 G7
+
+  * SYNA30B4:00 06CB:CE09 Mouse  on HP EliteBook 850 G7 not working at all
+    (LP: #1908992)
+    - HID: multitouch: Enable multi-input for Synaptics pointstick/touchpad device
+
+  * HD Audio Device PCI ID for the Intel Cometlake-R platform (LP: #1912427)
+    - SAUCE: ALSA: hda: Add Cometlake-R PCI ID
+
+  * switch to an autogenerated nvidia series based core via dkms-versions
+    (LP: #1912803)
+    - [Packaging] nvidia -- use dkms-versions to define versions built
+    - [Packaging] update-version-dkms -- maintain flags fields
+    - [Config] dkms-versions -- add transitional/skip information for nvidia
+      packages
+
+  * udpgro.sh in net from ubuntu_kernel_selftests seems not reflecting sub-test
+    result (LP: #1908499)
+    - selftests: fix the return value for UDP GRO test
+
+  * qede: Kubernetes Internal DNS Failure due to QL41xxx NIC not supporting IPIP
+    tx csum offload (LP: #1909062)
+    - qede: fix offload for IPIP tunnel packets
+
+  * Use DCPD to control HP DreamColor panel (LP: #1911001)
+    - SAUCE: drm/dp: Another HP DreamColor panel brigntness fix
+
+  * kvm: Windows 2k19 with Hyper-v role gets stuck on pending hypervisor
+    requests on cascadelake based kvm hosts (LP: #1911848)
+    - KVM: x86: Set KVM_REQ_EVENT if run is canceled with req_immediate_exit set
+
+  * Ubuntu 20.10 four needed fixes to 'Add driver for Mellanox Connect-IB
+    adapters' (LP: #1905574)
+    - net/mlx5: Fix a race when moving command interface to polling mode
+
+  * Fix right sounds and mute/micmute LEDs for HP ZBook Fury 15/17 G7 Mobile
+    Workstation (LP: #1910561)
+    - ALSA: hda/realtek: fix right sounds and mute/micmute LEDs for HP machines
+
+  * Ubuntu 20.04 - multicast counter is not increased in ip -s (LP: #1901842)
+    - net/mlx5e: Fix multicast counter not up-to-date in "ip -s"
+
+  * eeh-basic.sh in powerpc from ubuntu_kernel_selftests timeout with 5.4 P8 /
+    P9 (LP: #1882503)
+    - selftests/powerpc/eeh: disable kselftest timeout setting for eeh-basic
+
+  * DMI entry syntax fix for Pegatron / ByteSpeed C15B (LP: #1910639)
+    - Input: i8042 - unbreak Pegatron C15B
+
+  * CVE-2020-29372
+    - mm: check that mm is still valid in madvise()
+
+  * update ENA driver, incl. new ethtool stats (LP: #1910291)
+    - net: ena: Change WARN_ON expression in ena_del_napi_in_range()
+    - net: ena: ethtool: convert stat_offset to 64 bit resolution
+    - net: ena: ethtool: Add new device statistics
+    - net: ena: ethtool: add stats printing to XDP queues
+    - net: ena: xdp: add queue counters for xdp actions
+    - net: ena: Change license into format to SPDX in all files
+    - net: ena: Change log message to netif/dev function
+    - net: ena: Capitalize all log strings and improve code readability
+    - net: ena: Remove redundant print of placement policy
+    - net: ena: Change RSS related macros and variables names
+    - net: ena: Fix all static chekers' warnings
+    - drivers/net/ethernet: remove incorrectly formatted doc
+    - net: ena: handle bad request id in ena_netdev
+    - net: ena: fix packet's addresses for rx_offset feature
+
+  * s390x broken with unknown syscall number on kernels < 5.8 (LP: #1895132)
+    - s390/ptrace: return -ENOSYS when invalid syscall is supplied
+
+  * Focal update: v5.4.86 upstream stable release (LP: #1910822)
+    - ARM: dts: sun7i: bananapi: Enable RGMII RX/TX delay on Ethernet PHY
+    - ARM: dts: sun8i: r40: bananapi-m2-berry: Fix dcdc1 regulator
+    - ARM: dts: sun8i: v40: bananapi-m2-berry: Fix ethernet node
+    - pinctrl: merrifield: Set default bias in case no particular value given
+    - pinctrl: baytrail: Avoid clearing debounce value when turning it off
+    - ARM: dts: sun8i: v3s: fix GIC node memory range
+    - ARM: dts: sun7i: pcduino3-nano: enable RGMII RX/TX delay on PHY
+    - ARM: dts: imx6qdl-wandboard-revd1: Remove PAD_GPIO_6 from enetgrp
+    - ARM: dts: imx6qdl-kontron-samx6i: fix I2C_PM scl pin
+    - PM: runtime: Add pm_runtime_resume_and_get to deal with usage counter
+    - gpio: zynq: fix reference leak in zynq_gpio functions
+    - gpio: mvebu: fix potential user-after-free on probe
+    - scsi: bnx2i: Requires MMU
+    - xsk: Fix xsk_poll()'s return type
+    - xsk: Replace datagram_poll by sock_poll_wait
+    - can: softing: softing_netdev_open(): fix error handling
+    - clk: renesas: r9a06g032: Drop __packed for portability
+    - block: Simplify REQ_OP_ZONE_RESET_ALL handling
+    - block: factor out requeue handling from dispatch code
+    - blk-mq: In blk_mq_dispatch_rq_list() "no budget" is a reason to kick
+    - pinctrl: aspeed: Fix GPIO requests on pass-through banks
+    - netfilter: x_tables: Switch synchronization to RCU
+    - netfilter: nft_compat: make sure xtables destructors have run
+    - netfilter: nft_dynset: fix timeouts later than 23 days
+    - afs: Fix memory leak when mounting with multiple source parameters
+    - Revert "gpio: eic-sprd: Use devm_platform_ioremap_resource()"
+    - gpio: eic-sprd: break loop when getting NULL device resource
+    - netfilter: nft_ct: Remove confirmation check for NFT_CT_ID
+    - selftests/bpf/test_offload.py: Reset ethtool features after failed setting
+    - RDMA/cm: Fix an attempt to use non-valid pointer when cleaning timewait
+    - i40e: Refactor rx_bi accesses
+    - i40e: optimise prefetch page refcount
+    - i40e: avoid premature Rx buffer reuse
+    - ixgbe: avoid premature Rx buffer reuse
+    - selftests: fix poll error in udpgro.sh
+    - net: mvpp2: add mvpp2_phylink_to_port() helper
+    - drm/tegra: replace idr_init() by idr_init_base()
+    - kernel/cpu: add arch override for clear_tasks_mm_cpumask() mm handling
+    - drm/tegra: sor: Disable clocks on error in tegra_sor_init()
+    - habanalabs: put devices before driver removal
+    - arm64: syscall: exit userspace before unmasking exceptions
+    - vxlan: Add needed_headroom for lower device
+    - vxlan: Copy needed_tailroom from lowerdev
+    - scsi: mpt3sas: Increase IOCInit request timeout to 30s
+    - dm table: Remove BUG_ON(in_interrupt())
+    - iwlwifi: pcie: add one missing entry for AX210
+    - drm/amd/display: Init clock value by current vbios CLKs
+    - perf/x86/intel: Check PEBS status correctly
+    - kbuild: avoid split lines in .mod files
+    - soc/tegra: fuse: Fix index bug in get_process_id
+    - usb: mtu3: fix memory corruption in mtu3_debugfs_regset()
+    - USB: serial: option: add interface-number sanity check to flag handling
+    - USB: gadget: f_acm: add support for SuperSpeed Plus
+    - USB: gadget: f_midi: setup SuperSpeed Plus descriptors
+    - usb: gadget: f_fs: Re-use SS descriptors for SuperSpeedPlus
+    - USB: gadget: f_rndis: fix bitrate for SuperSpeed and above
+    - usb: chipidea: ci_hdrc_imx: Pass DISABLE_DEVICE_STREAMING flag to imx6ul
+    - ARM: dts: exynos: fix roles of USB 3.0 ports on Odroid XU
+    - ARM: dts: exynos: fix USB 3.0 VBUS control and over-current pins on
+      Exynos5410
+    - ARM: dts: exynos: fix USB 3.0 pins supply being turned off on Odroid XU
+    - coresight: tmc-etf: Fix NULL ptr dereference in tmc_enable_etf_sink_perf()
+    - coresight: tmc-etr: Check if page is valid before dma_map_page()
+    - coresight: tmc-etr: Fix barrier packet insertion for perf buffer
+    - coresight: etb10: Fix possible NULL ptr dereference in etb_enable_perf()
+    - scsi: megaraid_sas: Check user-provided offsets
+    - HID: i2c-hid: add Vero K147 to descriptor override
+    - serial_core: Check for port state when tty is in error state
+    - Bluetooth: Fix slab-out-of-bounds read in hci_le_direct_adv_report_evt()
+    - quota: Sanity-check quota file headers on load
+    - media: msi2500: assign SPI bus number dynamically
+    - crypto: af_alg - avoid undefined behavior accessing salg_name
+    - md: fix a warning caused by a race between concurrent md_ioctl()s
+    - drm/gma500: fix double free of gma_connector
+    - drm/aspeed: Fix Kconfig warning & subsequent build errors
+    - drm/mcde: Fix handling of platform_get_irq() error
+    - drm/tve200: Fix handling of platform_get_irq() error
+    - arm64: dts: renesas: hihope-rzg2-ex: Drop rxc-skew-ps from ethernet-phy node
+    - arm64: dts: renesas: cat875: Remove rxc-skew-ps from ethernet-phy node
+    - soc: renesas: rmobile-sysc: Fix some leaks in rmobile_init_pm_domains()
+    - soc: mediatek: Check if power domains can be powered on at boot time
+    - soc: qcom: geni: More properly switch to DMA mode
+    - Revert "i2c: i2c-qcom-geni: Fix DMA transfer race"
+    - RDMA/bnxt_re: Set queue pair state when being queried
+    - rtc: pcf2127: fix pcf2127_nvmem_read/write() returns
+    - selinux: fix error initialization in inode_doinit_with_dentry()
+    - ARM: dts: aspeed: s2600wf: Fix VGA memory region location
+    - RDMA/rxe: Compute PSN windows correctly
+    - x86/mm/ident_map: Check for errors from ident_pud_init()
+    - ARM: p2v: fix handling of LPAE translation in BE mode
+    - x86/apic: Fix x2apic enablement without interrupt remapping
+    - sched/deadline: Fix sched_dl_global_validate()
+    - sched: Reenable interrupts in do_sched_yield()
+    - drm/amdgpu: fix incorrect enum type
+    - crypto: talitos - Endianess in current_desc_hdr()
+    - crypto: talitos - Fix return type of current_desc_hdr()
+    - crypto: inside-secure - Fix sizeof() mismatch
+    - ASoC: sun4i-i2s: Fix lrck_period computation for I2S justified mode
+    - ARM: dts: aspeed: tiogapass: Remove vuart
+    - drm/amdgpu: fix build_coefficients() argument
+    - powerpc/64: Set up a kernel stack for secondaries before cpu_restore()
+    - spi: img-spfi: fix reference leak in img_spfi_resume
+    - f2fs: call f2fs_get_meta_page_retry for nat page
+    - drm/msm/dsi_pll_10nm: restore VCO rate during restore_state
+    - spi: spi-mem: fix reference leak in spi_mem_access_start
+    - ASoC: pcm: DRAIN support reactivation
+    - selinux: fix inode_doinit_with_dentry() LABEL_INVALID error handling
+    - spi: stm32: fix reference leak in stm32_spi_resume
+    - brcmfmac: Fix memory leak for unpaired brcmf_{alloc/free}
+    - arm64: dts: exynos: Include common syscon restart/poweroff for Exynos7
+    - arm64: dts: exynos: Correct psci compatible used on Exynos7
+    - Bluetooth: Fix null pointer dereference in hci_event_packet()
+    - Bluetooth: hci_h5: fix memory leak in h5_close
+    - spi: spi-ti-qspi: fix reference leak in ti_qspi_setup
+    - spi: mt7621: fix missing clk_disable_unprepare() on error in
+      mt7621_spi_probe
+    - spi: tegra20-slink: fix reference leak in slink ops of tegra20
+    - spi: tegra20-sflash: fix reference leak in tegra_sflash_resume
+    - spi: tegra114: fix reference leak in tegra spi ops
+    - spi: bcm63xx-hsspi: fix missing clk_disable_unprepare() on error in
+      bcm63xx_hsspi_resume
+    - mwifiex: fix mwifiex_shutdown_sw() causing sw reset failure
+    - selftest/bpf: Add missed ip6ip6 test back
+    - ASoC: wm8998: Fix PM disable depth imbalance on error
+    - spi: sprd: fix reference leak in sprd_spi_remove
+    - ASoC: arizona: Fix a wrong free in wm8997_probe
+    - RDMa/mthca: Work around -Wenum-conversion warning
+    - MIPS: BCM47XX: fix kconfig dependency bug for BCM47XX_BCMA
+    - crypto: qat - fix status check in qat_hal_put_rel_rd_xfer()
+    - staging: greybus: codecs: Fix reference counter leak in error handling
+    - staging: gasket: interrupt: fix the missed eventfd_ctx_put() in
+      gasket_interrupt.c
+    - media: tm6000: Fix sizeof() mismatches
+    - media: mtk-vcodec: add missing put_device() call in mtk_vcodec_init_dec_pm()
+    - media: mtk-vcodec: add missing put_device() call in
+      mtk_vcodec_release_dec_pm()
+    - media: mtk-vcodec: add missing put_device() call in mtk_vcodec_init_enc_pm()
+    - media: v4l2-fwnode: Return -EINVAL for invalid bus-type
+    - ASoC: meson: fix COMPILE_TEST error
+    - scsi: core: Fix VPD LUN ID designator priorities
+    - media: solo6x10: fix missing snd_card_free in error handling case
+    - video: fbdev: atmel_lcdfb: fix return error code in atmel_lcdfb_of_init()
+    - drm/omap: dmm_tiler: fix return error code in omap_dmm_probe()
+    - Input: ads7846 - fix race that causes missing releases
+    - Input: ads7846 - fix integer overflow on Rt calculation
+    - Input: ads7846 - fix unaligned access on 7845
+    - usb/max3421: fix return error code in max3421_probe()
+    - spi: mxs: fix reference leak in mxs_spi_probe
+    - selftests/bpf: Fix broken riscv build
+    - powerpc: Avoid broken GCC __attribute__((optimize))
+    - powerpc/feature: Fix CPU_FTRS_ALWAYS by removing CPU_FTRS_GENERIC_32
+    - EDAC/mce_amd: Use struct cpuinfo_x86.cpu_die_id for AMD NodeId
+    - crypto: crypto4xx - Replace bitwise OR with logical OR in crypto4xx_build_pd
+    - crypto: omap-aes - Fix PM disable depth imbalance in omap_aes_probe
+    - spi: fix resource leak for drivers without .remove callback
+    - soc: ti: knav_qmss: fix reference leak in knav_queue_probe
+    - soc: ti: Fix reference imbalance in knav_dma_probe
+    - drivers: soc: ti: knav_qmss_queue: Fix error return code in knav_queue_probe
+    - Input: omap4-keypad - fix runtime PM error handling
+    - clk: meson: Kconfig: fix dependency for G12A
+    - RDMA/cxgb4: Validate the number of CQEs
+    - memstick: fix a double-free bug in memstick_check
+    - ARM: dts: at91: sama5d4_xplained: add pincontrol for USB Host
+    - ARM: dts: at91: sama5d3_xplained: add pincontrol for USB Host
+    - mmc: pxamci: Fix error return code in pxamci_probe
+    - orinoco: Move context allocation after processing the skb
+    - qtnfmac: fix error return code in qtnf_pcie_probe()
+    - rsi: fix error return code in rsi_reset_card()
+    - cw1200: fix missing destroy_workqueue() on error in cw1200_init_common
+    - dmaengine: mv_xor_v2: Fix error return code in mv_xor_v2_probe()
+    - arm64: tegra: Fix DT binding for IO High Voltage entry
+    - media: siano: fix memory leak of debugfs members in smsdvb_hotplug
+    - platform/x86: mlx-platform: Remove PSU EEPROM from default platform
+      configuration
+    - platform/x86: mlx-platform: Remove PSU EEPROM from MSN274x platform
+      configuration
+    - samples: bpf: Fix lwt_len_hist reusing previous BPF map
+    - media: imx214: Fix stop streaming
+    - mips: cdmm: fix use-after-free in mips_cdmm_bus_discover
+    - media: max2175: fix max2175_set_csm_mode() error code
+    - slimbus: qcom-ngd-ctrl: Avoid sending power requests without QMI
+    - HSI: omap_ssi: Don't jump to free ID in ssi_add_controller()
+    - ARM: dts: Remove non-existent i2c1 from 98dx3236
+    - arm64: dts: armada-3720-turris-mox: update ethernet-phy handle name
+    - arm64: dts: rockchip: Set dr_mode to "host" for OTG on rk3328-roc-cc
+    - power: supply: axp288_charger: Fix HP Pavilion x2 10 DMI matching
+    - power: supply: bq24190_charger: fix reference leak
+    - genirq/irqdomain: Don't try to free an interrupt that has no mapping
+    - arm64: dts: ls1028a: fix ENETC PTP clock input
+    - arm64: dts: qcom: c630: Polish i2c-hid devices
+    - PCI: Bounds-check command-line resource alignment requests
+    - PCI: Fix overflow in command-line resource alignment requests
+    - PCI: iproc: Fix out-of-bound array accesses
+    - arm64: dts: meson: fix spi-max-frequency on Khadas VIM2
+    - arm64: dts: meson-sm1: fix typo in opp table
+    - soc: amlogic: canvas: add missing put_device() call in meson_canvas_get()
+    - ARM: dts: at91: at91sam9rl: fix ADC triggers
+    - platform/x86: dell-smbios-base: Fix error return code in dell_smbios_init
+    - ath10k: Fix the parsing error in service available event
+    - ath10k: Fix an error handling path
+    - ath10k: Release some resources in an error handling path
+    - SUNRPC: rpc_wake_up() should wake up tasks in the correct order
+    - NFSv4.2: condition READDIR's mask for security label based on LSM state
+    - SUNRPC: xprt_load_transport() needs to support the netid "rdma6"
+    - NFSv4: Fix the alignment of page data in the getdeviceinfo reply
+    - net: sunrpc: Fix 'snprintf' return value check in 'do_xprt_debugfs'
+    - lockd: don't use interval-based rebinding over TCP
+    - NFS: switch nfsiod to be an UNBOUND workqueue.
+    - selftests/seccomp: Update kernel config
+    - vfio-pci: Use io_remap_pfn_range() for PCI IO memory
+    - hwmon: (ina3221) Fix PM usage counter unbalance in ina3221_write_enable
+    - media: saa7146: fix array overflow in vidioc_s_audio()
+    - powerpc/perf: Fix crash with is_sier_available when pmu is not set
+    - powerpc/64: Fix an EMIT_BUG_ENTRY in head_64.S
+    - clocksource/drivers/orion: Add missing clk_disable_unprepare() on error path
+    - clocksource/drivers/cadence_ttc: Fix memory leak in ttc_setup_clockevent()
+    - iio: hrtimer-trigger: Mark hrtimer to expire in hard interrupt context
+    - ARM: dts: at91: sama5d2: map securam as device
+    - bpf: Fix bpf_put_raw_tracepoint()'s use of __module_address()
+    - pinctrl: falcon: add missing put_device() call in pinctrl_falcon_probe()
+    - arm64: dts: rockchip: Fix UART pull-ups on rk3328
+    - memstick: r592: Fix error return in r592_probe()
+    - MIPS: Don't round up kernel sections size for memblock_add()
+    - net/mlx5: Properly convey driver version to firmware
+    - ASoC: jz4740-i2s: add missed checks for clk_get()
+    - dm ioctl: fix error return code in target_message
+    - phy: renesas: rcar-gen3-usb2: disable runtime pm in case of failure
+    - clocksource/drivers/arm_arch_timer: Use stable count reader in erratum sne
+    - clocksource/drivers/arm_arch_timer: Correct fault programming of
+      CNTKCTL_EL1.EVNTI
+    - cpufreq: ap806: Add missing MODULE_DEVICE_TABLE
+    - cpufreq: highbank: Add missing MODULE_DEVICE_TABLE
+    - cpufreq: mediatek: Add missing MODULE_DEVICE_TABLE
+    - cpufreq: qcom: Add missing MODULE_DEVICE_TABLE
+    - cpufreq: st: Add missing MODULE_DEVICE_TABLE
+    - cpufreq: sun50i: Add missing MODULE_DEVICE_TABLE
+    - cpufreq: loongson1: Add missing MODULE_ALIAS
+    - cpufreq: scpi: Add missing MODULE_ALIAS
+    - Bluetooth: btusb: Add the missed release_firmware() in
+      btusb_mtk_setup_firmware()
+    - Bluetooth: btmtksdio: Add the missed release_firmware() in
+      mtk_setup_firmware()
+    - arm64: dts: meson: fix PHY deassert timing requirements
+    - ARM: dts: meson: fix PHY deassert timing requirements
+    - arm64: dts: meson: g12a: x96-max: fix PHY deassert timing requirements
+    - scsi: qedi: Fix missing destroy_workqueue() on error in __qedi_probe
+    - scsi: pm80xx: Fix error return in pm8001_pci_probe()
+    - seq_buf: Avoid type mismatch for seq_buf_init
+    - scsi: fnic: Fix error return code in fnic_probe()
+    - platform/x86: mlx-platform: Fix item counter assignment for MSN2700, MSN24xx
+      systems
+    - powerpc/pseries/hibernation: drop pseries_suspend_begin() from suspend ops
+    - powerpc/pseries/hibernation: remove redundant cacheinfo update
+    - drm/mediatek: avoid dereferencing a null hdmi_phy on an error message
+    - ASoC: amd: change clk_get() to devm_clk_get() and add missed checks
+    - powerpc/mm: sanity_check_fault() should work for all, not only BOOK3S
+    - usb: ehci-omap: Fix PM disable depth umbalance in ehci_hcd_omap_probe
+    - usb: oxu210hp-hcd: Fix memory leak in oxu_create
+    - speakup: fix uninitialized flush_lock
+    - nfsd: Fix message level for normal termination
+    - nfs_common: need lock during iterate through the list
+    - x86/kprobes: Restore BTF if the single-stepping is cancelled
+    - platform/chrome: cros_ec_spi: Don't overwrite spi::mode
+    - bus: fsl-mc: fix error return code in fsl_mc_object_allocate()
+    - s390/cio: fix use-after-free in ccw_device_destroy_console
+    - iwlwifi: mvm: hook up missing RX handlers
+    - erofs: avoid using generic_block_bmap
+    - can: m_can: m_can_config_endisable(): remove double clearing of clock stop
+      request bit
+    - RDMA/core: Do not indicate device ready when device enablement fails
+    - remoteproc: q6v5-mss: fix error handling in q6v5_pds_enable
+    - remoteproc: qcom: fix reference leak in adsp_start
+    - remoteproc: qcom: Fix potential NULL dereference in adsp_init_mmio()
+    - clk: tegra: Fix duplicated SE clock entry
+    - mtd: rawnand: gpmi: fix reference count leak in gpmi ops
+    - mtd: rawnand: meson: Fix a resource leak in init
+    - mtd: rawnand: gpmi: Fix the random DMA timeout issue
+    - extcon: max77693: Fix modalias string
+    - crypto: atmel-i2c - select CONFIG_BITREVERSE
+    - mac80211: don't set set TDLS STA bandwidth wider than possible
+    - ASoC: wm_adsp: remove "ctl" from list on error in wm_adsp_create_control()
+    - irqchip/alpine-msi: Fix freeing of interrupts on allocation error path
+    - watchdog: armada_37xx: Add missing dependency on HAS_IOMEM
+    - watchdog: sirfsoc: Add missing dependency on HAS_IOMEM
+    - watchdog: sprd: remove watchdog disable from resume fail path
+    - watchdog: sprd: check busy bit before new loading rather than after that
+    - watchdog: Fix potential dereferencing of null pointer
+    - ubifs: Fix error return code in ubifs_init_authentication()
+    - um: Monitor error events in IRQ controller
+    - um: tty: Fix handling of close in tty lines
+    - um: chan_xterm: Fix fd leak
+    - sunrpc: fix xs_read_xdr_buf for partial pages receive
+    - RDMA/cma: Don't overwrite sgid_attr after device is released
+    - nfc: s3fwrn5: Release the nfc firmware
+    - powerpc/ps3: use dma_mapping_error()
+    - sparc: fix handling of page table constructor failure
+    - mm: don't wake kswapd prematurely when watermark boosting is disabled
+    - checkpatch: fix unescaped left brace
+    - lan743x: fix rx_napi_poll/interrupt ping-pong
+    - net: bcmgenet: Fix a resource leak in an error handling path in the probe
+      functin
+    - net: allwinner: Fix some resources leak in the error handling path of the
+      probe and in the remove function
+    - net: korina: fix return value
+    - libnvdimm/label: Return -ENXIO for no slot in __blk_label_update
+    - watchdog: qcom: Avoid context switch in restart handler
+    - watchdog: coh901327: add COMMON_CLK dependency
+    - clk: ti: Fix memleak in ti_fapll_synth_setup
+    - pwm: zx: Add missing cleanup in error path
+    - pwm: lp3943: Dynamically allocate PWM chip base
+    - perf record: Fix memory leak when using '--user-regs=?' to list registers
+    - qlcnic: Fix error code in probe
+    - virtio_ring: Cut and paste bugs in vring_create_virtqueue_packed()
+    - virtio_net: Fix error code in probe()
+    - virtio_ring: Fix two use after free bugs
+    - clk: at91: sam9x60: remove atmel,osc-bypass support
+    - clk: s2mps11: Fix a resource leak in error handling paths in the probe
+      function
+    - clk: sunxi-ng: Make sure divider tables have sentinel
+    - kconfig: fix return value of do_error_if()
+    - perf probe: Fix memory leak when synthesizing SDT probes
+    - ARM: sunxi: Add machine match for the Allwinner V3 SoC
+    - cfg80211: initialize rekey_data
+    - fix namespaced fscaps when !CONFIG_SECURITY
+    - lwt: Disable BH too in run_lwt_bpf()
+    - drm/amd/display: Prevent bandwidth overflow
+    - drm/amdkfd: Fix leak in dmabuf import
+    - Input: cros_ec_keyb - send 'scancodes' in addition to key events
+    - initramfs: fix clang build failure
+    - Input: goodix - add upside-down quirk for Teclast X98 Pro tablet
+    - vfio/pci/nvlink2: Do not attempt NPU2 setup on POWER8NVL NPU
+    - media: gspca: Fix memory leak in probe
+    - media: sunxi-cir: ensure IR is handled when it is continuous
+    - media: netup_unidvb: Don't leak SPI master in probe error path
+    - media: ipu3-cio2: Remove traces of returned buffers
+    - media: ipu3-cio2: Return actual subdev format
+    - media: ipu3-cio2: Serialise access to pad format
+    - media: ipu3-cio2: Validate mbus format in setting subdev format
+    - media: ipu3-cio2: Make the field on subdev format V4L2_FIELD_NONE
+    - Input: cyapa_gen6 - fix out-of-bounds stack access
+    - ALSA: hda/ca0132 - Change Input Source enum strings.
+    - Revert "ACPI / resources: Use AE_CTRL_TERMINATE to terminate resources
+      walks"
+    - ACPI: PNP: compare the string length in the matching_id()
+    - ALSA: hda: Fix regressions on clear and reconfig sysfs
+    - ALSA: hda/ca0132 - Fix AE-5 rear headphone pincfg.
+    - ALSA: hda/realtek: make bass spk volume adjustable on a yoga laptop
+    - ALSA: hda/realtek - Enable headset mic of ASUS X430UN with ALC256
+    - ALSA: hda/realtek - Enable headset mic of ASUS Q524UQK with ALC255
+    - ALSA: hda/realtek - Add supported for more Lenovo ALC285 Headset Button
+    - ALSA: pcm: oss: Fix a few more UBSAN fixes
+    - ALSA/hda: apply jack fixup for the Acer Veriton N4640G/N6640G/N2510G
+    - ALSA: hda/realtek: Add quirk for MSI-GP73
+    - ALSA: hda/realtek: Apply jack fixup for Quanta NL3
+    - ALSA: usb-audio: Add VID to support native DSD reproduction on FiiO devices
+    - ALSA: usb-audio: Disable sample read check if firmware doesn't give back
+    - ALSA: core: memalloc: add page alignment for iram
+    - s390/smp: perform initial CPU reset also for SMT siblings
+    - s390/kexec_file: fix diag308 subcode when loading crash kernel
+    - s390/dasd: fix hanging device offline processing
+    - s390/dasd: prevent inconsistent LCU device data
+    - s390/dasd: fix list corruption of pavgroup group list
+    - s390/dasd: fix list corruption of lcu list
+    - binder: add flag to clear buffer on txn complete
+    - ASoC: cx2072x: Fix doubly definitions of Playback and Capture streams
+    - staging: comedi: mf6x4: Fix AI end-of-conversion detection
+    - perf/x86/intel: Add event constraint for CYCLE_ACTIVITY.STALLS_MEM_ANY
+    - perf/x86/intel: Fix rtm_abort_event encoding on Ice Lake
+    - powerpc/perf: Exclude kernel samples while counting events in user space.
+    - crypto: ecdh - avoid unaligned accesses in ecdh_set_secret()
+    - crypto: arm/aes-ce - work around Cortex-A57/A72 silion errata
+    - EDAC/i10nm: Use readl() to access MMIO registers
+    - EDAC/amd64: Fix PCI component registration
+    - cpuset: fix race between hotplug work and later CPU offline
+    - USB: serial: mos7720: fix parallel-port state restore
+    - USB: serial: digi_acceleport: fix write-wakeup deadlocks
+    - USB: serial: keyspan_pda: fix dropped unthrottle interrupts
+    - USB: serial: keyspan_pda: fix write deadlock
+    - USB: serial: keyspan_pda: fix stalled writes
+    - USB: serial: keyspan_pda: fix write-wakeup use-after-free
+    - USB: serial: keyspan_pda: fix tx-unthrottle use-after-free
+    - USB: serial: keyspan_pda: fix write unthrottling
+    - btrfs: do not shorten unpin len for caching block groups
+    - ext4: fix a memory leak of ext4_free_data
+    - ext4: fix deadlock with fs freezing and EA inodes
+    - KVM: arm64: Introduce handling of AArch32 TTBCR2 traps
+    - ARM: dts: pandaboard: fix pinmux for gpio user button of Pandaboard ES
+    - ARM: dts: at91: sama5d2: fix CAN message ram offset and size
+    - xprtrdma: Fix XDRBUF_SPARSE_PAGES support
+    - powerpc: Fix incorrect stw{, ux, u, x} instructions in __set_pte_at
+    - powerpc/rtas: Fix typo of ibm,open-errinjct in RTAS filter
+    - powerpc/feature: Add CPU_FTR_NOEXECUTE to G2_LE
+    - powerpc/xmon: Change printk() to pr_cont()
+    - powerpc/8xx: Fix early debug when SMC1 is relocated
+    - powerpc/mm: Fix verification of MMU_FTR_TYPE_44x
+    - powerpc/powernv/npu: Do not attempt NPU2 setup on POWER8NVL NPU
+    - powerpc/powernv/memtrace: Don't leak kernel memory to user space
+    - powerpc/powernv/memtrace: Fix crashing the kernel when enabling concurrently
+    - ima: Don't modify file descriptor mode on the fly
+    - um: Remove use of asprinf in umid.c
+    - ceph: fix race in concurrent __ceph_remove_cap invocations
+    - SMB3: avoid confusing warning message on mount to Azure
+    - ubifs: wbuf: Don't leak kernel memory to flash
+    - jffs2: Fix GC exit abnormally
+    - jffs2: Fix ignoring mounting options problem during remounting
+    - jfs: Fix array index bounds check in dbAdjTree
+    - platform/x86: mlx-platform: remove an unused variable
+    - drm/amd/display: Fix memory leaks in S3 resume
+    - drm/dp_aux_dev: check aux_dev before use in drm_dp_aux_dev_get_by_minor()
+    - drm/i915: Fix mismatch between misplaced vma check and vma insert
+    - spi: pxa2xx: Fix use-after-free on unbind
+    - spi: spi-sh: Fix use-after-free on unbind
+    - spi: atmel-quadspi: Fix use-after-free on unbind
+    - spi: davinci: Fix use-after-free on unbind
+    - spi: fsl: fix use of spisel_boot signal on MPC8309
+    - spi: gpio: Don't leak SPI master in probe error path
+    - spi: mxic: Don't leak SPI master in probe error path
+    - spi: pic32: Don't leak DMA channels in probe error path
+    - spi: rb4xx: Don't leak SPI master in probe error path
+    - spi: sc18is602: Don't leak SPI master in probe error path
+    - spi: st-ssc4: Fix unbalanced pm_runtime_disable() in probe error path
+    - spi: synquacer: Disable clock in probe error path
+    - spi: mt7621: Disable clock in probe error path
+    - spi: mt7621: Don't leak SPI master in probe error path
+    - spi: atmel-quadspi: Disable clock in probe error path
+    - spi: atmel-quadspi: Fix AHB memory accesses
+    - soc: qcom: smp2p: Safely acquire spinlock without IRQs
+    - mtd: spinand: Fix OOB read
+    - mtd: parser: cmdline: Fix parsing of part-names with colons
+    - mtd: rawnand: qcom: Fix DMA sync on FLASH_STATUS register read
+    - mtd: rawnand: meson: fix meson_nfc_dma_buffer_release() arguments
+    - scsi: qla2xxx: Fix crash during driver load on big endian machines
+    - scsi: lpfc: Fix invalid sleeping context in lpfc_sli4_nvmet_alloc()
+    - scsi: lpfc: Re-fix use after free in lpfc_rq_buf_free()
+    - iio: buffer: Fix demux update
+    - iio: adc: rockchip_saradc: fix missing clk_disable_unprepare() on error in
+      rockchip_saradc_resume
+    - iio:light:rpr0521: Fix timestamp alignment and prevent data leak.
+    - iio:light:st_uvis25: Fix timestamp alignment and prevent data leak.
+    - iio:magnetometer:mag3110: Fix alignment and data leak issues.
+    - iio:pressure:mpl3115: Force alignment of buffer
+    - iio:imu:bmi160: Fix too large a buffer.
+    - iio:adc:ti-ads124s08: Fix buffer being too long.
+    - iio:adc:ti-ads124s08: Fix alignment and data leak issues.
+    - md/cluster: block reshape with remote resync job
+    - md/cluster: fix deadlock when node is doing resync job
+    - pinctrl: sunxi: Always call chained_irq_{enter, exit} in
+      sunxi_pinctrl_irq_handler
+    - clk: ingenic: Fix divider calculation with div tables
+    - clk: mvebu: a3700: fix the XTAL MODE pin to MPP1_9
+    - clk: tegra: Do not return 0 on failure
+    - device-dax/core: Fix memory leak when rmmod dax.ko
+    - dma-buf/dma-resv: Respect num_fences when initializing the shared fence
+      list.
+    - xen-blkback: set ring->xenblkd to NULL after kthread_stop()
+    - xen/xenbus: Allow watches discard events before queueing
+    - xen/xenbus: Add 'will_handle' callback support in xenbus_watch_path()
+    - xen/xenbus/xen_bus_type: Support will_handle watch callback
+    - xen/xenbus: Count pending messages for each watch
+    - xenbus/xenbus_backend: Disallow pending watch messages
+    - libnvdimm/namespace: Fix reaping of invalidated block-window-namespace
+      labels
+    - platform/x86: intel-vbtn: Allow switch events on Acer Switch Alpha 12
+    - PCI: Fix pci_slot_release() NULL pointer dereference
+    - regulator: axp20x: Fix DLDO2 voltage control register mask for AXP22x
+    - rtc: ep93xx: Fix NULL pointer dereference in ep93xx_rtc_read_time
+    - Revert: "ring-buffer: Remove HAVE_64BIT_ALIGNED_ACCESS"
+    - x86/CPU/AMD: Save AMD NodeId as cpu_die_id
+    - Linux 5.4.86
+
+  * Focal update: v5.4.85 upstream stable release (LP: #1910817)
+    - ptrace: Prevent kernel-infoleak in ptrace_get_syscall_info()
+    - ipv4: fix error return code in rtm_to_fib_config()
+    - mac80211: mesh: fix mesh_pathtbl_init() error path
+    - net: bridge: vlan: fix error return code in __vlan_add()
+    - vrf: packets with lladdr src needs dst at input with orig_iif when needs
+      strict
+    - net: hns3: remove a misused pragma packed
+    - udp: fix the proto value passed to ip_protocol_deliver_rcu for the segments
+    - enetc: Fix reporting of h/w packet counters
+    - bridge: Fix a deadlock when enabling multicast snooping
+    - net: stmmac: free tx skb buffer in stmmac_resume()
+    - tcp: select sane initial rcvq_space.space for big MSS
+    - tcp: fix cwnd-limited bug for TSO deferral where we send nothing
+    - net/mlx4_en: Avoid scheduling restart task if it is already running
+    - lan743x: fix for potential NULL pointer dereference with bare card
+    - net/mlx4_en: Handle TX error CQE
+    - net: ll_temac: Fix potential NULL dereference in temac_probe()
+    - net: stmmac: dwmac-meson8b: fix mask definition of the m250_sel mux
+    - net: stmmac: delete the eee_ctrl_timer after napi disabled
+    - ktest.pl: If size of log is too big to email, email error message
+    - USB: dummy-hcd: Fix uninitialized array use in init()
+    - USB: add RESET_RESUME quirk for Snapscan 1212
+    - ALSA: usb-audio: Fix potential out-of-bounds shift
+    - ALSA: usb-audio: Fix control 'access overflow' errors from chmap
+    - xhci: Give USB2 ports time to enter U3 in bus suspend
+    - xhci-pci: Allow host runtime PM as default for Intel Alpine Ridge LP
+    - USB: UAS: introduce a quirk to set no_write_same
+    - USB: sisusbvga: Make console support depend on BROKEN
+    - [Config] updateconfigs for USB_SISUSBVGA_CON
+    - ALSA: pcm: oss: Fix potential out-of-bounds shift
+    - serial: 8250_omap: Avoid FIFO corruption caused by MDR1 access
+    - KVM: mmu: Fix SPTE encoding of MMIO generation upper half
+    - membarrier: Explicitly sync remote cores when SYNC_CORE is requested
+    - x86/resctrl: Remove unused struct mbm_state::chunks_bw
+    - x86/resctrl: Fix incorrect local bandwidth when mba_sc is enabled
+    - Linux 5.4.85
+
+  * Focal update: v5.4.84 upstream stable release (LP: #1910816)
+    - Kbuild: do not emit debug info for assembly with LLVM_IAS=1
+    - x86/lib: Change .weak to SYM_FUNC_START_WEAK for arch/x86/lib/mem*_64.S
+    - iwlwifi: pcie: limit memory read spin time
+    - arm64: dts: rockchip: Assign a fixed index to mmc devices on rk3399 boards.
+    - iwlwifi: pcie: set LTR to avoid completion timeout
+    - iwlwifi: mvm: fix kernel panic in case of assert during CSA
+    - powerpc: Drop -me200 addition to build flags
+    - arm64: dts: broadcom: clear the warnings caused by empty dma-ranges
+    - ARC: stack unwinding: don't assume non-current task is sleeping
+    - scsi: ufs: Make sure clk scaling happens only when HBA is runtime ACTIVE
+    - interconnect: qcom: qcs404: Remove GPU and display RPM IDs
+    - ibmvnic: skip tx timeout reset while in resetting
+    - irqchip/gic-v3-its: Unconditionally save/restore the ITS state on suspend
+    - spi: spi-nxp-fspi: fix fspi panic by unexpected interrupts
+    - soc: fsl: dpio: Get the cpumask through cpumask_of(cpu)
+    - arm64: tegra: Disable the ACONNECT for Jetson TX2
+    - platform/x86: thinkpad_acpi: Do not report SW_TABLET_MODE on Yoga 11e
+    - platform/x86: thinkpad_acpi: Add BAT1 is primary battery quirk for Thinkpad
+      Yoga 11e 4th gen
+    - platform/x86: acer-wmi: add automatic keyboard background light toggle key
+      as KEY_LIGHTS_TOGGLE
+    - platform/x86: intel-vbtn: Support for tablet mode on HP Pavilion 13 x360 PC
+    - platform/x86: touchscreen_dmi: Add info for the Irbis TW118 tablet
+    - can: m_can: m_can_dev_setup(): add support for bosch mcan version 3.3.0
+    - ktest.pl: Fix incorrect reboot for grub2bls
+    - Input: cm109 - do not stomp on control URB
+    - Input: i8042 - add Acer laptops to the i8042 reset list
+    - mmc: block: Fixup condition for CMD13 polling for RPMB requests
+    - drm/i915/display/dp: Compute the correct slice count for VDSC on DP
+    - kbuild: avoid static_assert for genksyms
+    - proc: use untagged_addr() for pagemap_read addresses
+    - scsi: be2iscsi: Revert "Fix a theoretical leak in beiscsi_create_eqs()"
+    - x86/mm/mem_encrypt: Fix definition of PMD_FLAGS_DEC_WP
+    - x86/membarrier: Get rid of a dubious optimization
+    - x86/apic/vector: Fix ordering in vector assignment
+    - mm/zsmalloc.c: drop ZSMALLOC_PGTABLE_MAPPING
+    - [Config] updateconfigs for PGTABLE_MAPPING
+    - compiler.h: fix barrier_data() on clang
+    - Linux 5.4.84
+
+  * MSFT Touchpad not working on Lenovo Legion-5 15ARH05 (LP: #1887190) // Focal
+    update: v5.4.84 upstream stable release (LP: #1910816)
+    - pinctrl: amd: remove debounce filter setting in IRQ type setting
+
+  * Focal update: v5.4.83 upstream stable release (LP: #1910784)
+    - pinctrl: baytrail: Replace WARN with dev_info_once when setting direct-irq
+      pin to output
+    - pinctrl: baytrail: Fix pin being driven low for a while on gpiod_get(...,
+      GPIOD_OUT_HIGH)
+    - usb: gadget: f_fs: Use local copy of descriptors for userspace copy
+    - USB: serial: kl5kusb105: fix memleak on open
+    - USB: serial: ch341: add new Product ID for CH341A
+    - USB: serial: ch341: sort device-id entries
+    - USB: serial: option: add Fibocom NL668 variants
+    - USB: serial: option: add support for Thales Cinterion EXS82
+    - USB: serial: option: fix Quectel BG96 matching
+    - tty: Fix ->pgrp locking in tiocspgrp()
+    - tty: Fix ->session locking
+    - ALSA: hda/realtek: Fix bass speaker DAC assignment on Asus Zephyrus G14
+    - ALSA: hda/realtek: Add mute LED quirk to yet another HP x360 model
+    - ALSA: hda/realtek: Enable headset of ASUS UX482EG & B9400CEA with ALC294
+    - ALSA: hda/realtek - Add new codec supported for ALC897
+    - ALSA: hda/generic: Add option to enforce preferred_dacs pairs
+    - ftrace: Fix updating FTRACE_FL_TRAMP
+    - cifs: allow syscalls to be restarted in __smb_send_rqst()
+    - cifs: fix potential use-after-free in cifs_echo_request()
+    - i2c: imx: Don't generate STOP condition if arbitration has been lost
+    - thunderbolt: Fix use-after-free in remove_unplugged_switch()
+    - drm/i915/gt: Program mocs:63 for cache eviction on gen9
+    - scsi: mpt3sas: Fix ioctl timeout
+    - dm writecache: fix the maximum number of arguments
+    - powerpc/64s/powernv: Fix memory corruption when saving SLB entries on MCE
+    - genirq/irqdomain: Add an irq_create_mapping_affinity() function
+    - powerpc/pseries: Pass MSI affinity to irq_create_mapping()
+    - dm: fix bug with RCU locking in dm_blk_report_zones
+    - dm: remove invalid sparse __acquires and __releases annotations
+    - x86/uprobes: Do not use prefixes.nbytes when looping over prefixes.bytes
+    - coredump: fix core_pattern parse error
+    - mm: list_lru: set shrinker map bit when child nr_items is not zero
+    - mm/swapfile: do not sleep with a spin lock held
+    - speakup: Reject setting the speakup line discipline outside of speakup
+    - i2c: imx: Fix reset of I2SR_IAL flag
+    - i2c: imx: Check for I2SR_IAL after every byte
+    - spi: bcm2835: Release the DMA channel if probe fails after dma_init
+    - iommu/amd: Set DTE[IntTabLen] to represent 512 IRTEs
+    - tracing: Fix userstacktrace option for instances
+    - lib/syscall: fix syscall registers retrieval on 32-bit platforms
+    - can: af_can: can_rx_unregister(): remove WARN() statement from list
+      operation sanity check
+    - gfs2: check for empty rgrp tree in gfs2_ri_update
+    - netfilter: ipset: prevent uninit-value in hash_ip6_add
+    - tipc: fix a deadlock when flushing scheduled work
+    - ASoC: wm_adsp: fix error return code in wm_adsp_load()
+    - rtw88: debug: Fix uninitialized memory in debugfs code
+    - i2c: qup: Fix error return code in qup_i2c_bam_schedule_desc()
+    - dm writecache: remove BUG() and fail gracefully instead
+    - Input: i8042 - fix error return code in i8042_setup_aux()
+    - netfilter: nf_tables: avoid false-postive lockdep splat
+    - netfilter: nftables_offload: set address type in control dissector
+    - x86/insn-eval: Use new for_each_insn_prefix() macro to loop over prefixes
+      bytes
+    - Linux 5.4.83
+
+  * dep-8 ubuntu-regression-suite tests are not run for all linux-hwe-* kernels
+    (LP: #1908529)
+    - [dep-8] Allow all hwe kernels
+
+  * failing ftrace self tests from 5.7+ onwards (LP: #1893024)
+    - SAUCE: Revert "selftests/ftrace: check for do_sys_openat2 in user-memory
+      test"
+
+  * selftests: test_vxlan_under_vrf: mute unnecessary error message
+    (LP: #1908342)
+    - selftests: test_vxlan_under_vrf: mute unnecessary error message
+
+  * Focal update: v5.4.82 upstream stable release (LP: #1908564)
+    - devlink: Hold rtnl lock while reading netdev attributes
+    - ipv6: addrlabel: fix possible memory leak in ip6addrlbl_net_init
+    - net/af_iucv: set correct sk_protocol for child sockets
+    - net/tls: missing received data after fast remote close
+    - net/tls: Protect from calling tls_dev_del for TLS RX twice
+    - rose: Fix Null pointer dereference in rose_send_frame()
+    - sock: set sk_err to ee_errno on dequeue from errq
+    - tcp: Set INET_ECN_xmit configuration in tcp_reinit_congestion_control
+    - tun: honor IOCB_NOWAIT flag
+    - usbnet: ipheth: fix connectivity with iOS 14
+    - bonding: wait for sysfs kobject destruction before freeing struct slave
+    - staging/octeon: fix up merge error
+    - ima: extend boot_aggregate with kernel measurements
+    - sched/fair: Fix unthrottle_cfs_rq() for leaf_cfs_rq list
+    - netfilter: bridge: reset skb->pkt_type after NF_INET_POST_ROUTING traversal
+    - ipv4: Fix tos mask in inet_rtm_getroute()
+    - dt-bindings: net: correct interrupt flags in examples
+    - chelsio/chtls: fix panic during unload reload chtls
+    - ibmvnic: Ensure that SCRQ entry reads are correctly ordered
+    - ibmvnic: Fix TX completion error handling
+    - inet_ecn: Fix endianness of checksum update when setting ECT(1)
+    - net: ip6_gre: set dev->hard_header_len when using header_ops
+    - net/x25: prevent a couple of overflows
+    - cxgb3: fix error return code in t3_sge_alloc_qset()
+    - net: pasemi: fix error return code in pasemi_mac_open()
+    - vxlan: fix error return code in __vxlan_dev_create()
+    - chelsio/chtls: fix a double free in chtls_setkey()
+    - net: mvpp2: Fix error return code in mvpp2_open()
+    - net: skbuff: ensure LSE is pullable before decrementing the MPLS ttl
+    - net: openvswitch: ensure LSE is pullable before reading it
+    - net/sched: act_mpls: ensure LSE is pullable before reading it
+    - net/mlx5: DR, Proper handling of unsupported Connect-X6DX SW steering
+    - net/mlx5: Fix wrong address reclaim when command interface is down
+    - ALSA: usb-audio: US16x08: fix value count for level meters
+    - Input: xpad - support Ardwiino Controllers
+    - tracing: Remove WARN_ON in start_thread()
+    - RDMA/i40iw: Address an mmap handler exploit in i40iw
+    - Linux 5.4.82
+
+  * Focal update: v5.4.81 upstream stable release (LP: #1908562)
+    - spi: bcm-qspi: Fix use-after-free on unbind
+    - spi: bcm2835: Fix use-after-free on unbind
+    - ipv4: use IS_ENABLED instead of ifdef
+    - netfilter: clear skb->next in NF_HOOK_LIST()
+    - btrfs: tree-checker: add missing return after error in root_item
+    - btrfs: tree-checker: add missing returns after data_ref alignment checks
+    - btrfs: don't access possibly stale fs_info data for printing duplicate
+      device
+    - btrfs: fix lockdep splat when reading qgroup config on mount
+    - wireless: Use linux/stddef.h instead of stddef.h
+    - smb3: Call cifs reconnect from demultiplex thread
+    - smb3: Avoid Mid pending list corruption
+    - smb3: Handle error case during offload read path
+    - cifs: fix a memleak with modefromsid
+    - KVM: PPC: Book3S HV: XIVE: Fix possible oops when accessing ESB page
+    - KVM: arm64: vgic-v3: Drop the reporting of GICR_TYPER.Last for userspace
+    - KVM: x86: handle !lapic_in_kernel case in kvm_cpu_*_extint
+    - KVM: x86: Fix split-irqchip vs interrupt injection window request
+    - trace: fix potenial dangerous pointer
+    - arm64: pgtable: Fix pte_accessible()
+    - arm64: pgtable: Ensure dirty bit is preserved across pte_wrprotect()
+    - HID: uclogic: Add ID for Trust Flex Design Tablet
+    - HID: ite: Replace ABS_MISC 120/121 events with touchpad on/off keypresses
+    - HID: cypress: Support Varmilo Keyboards' media hotkeys
+    - HID: add support for Sega Saturn
+    - Input: i8042 - allow insmod to succeed on devices without an i8042
+      controller
+    - HID: hid-sensor-hub: Fix issue with devices with no report ID
+    - staging: ralink-gdma: fix kconfig dependency bug for DMA_RALINK
+    - HID: add HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE for Gamevice devices
+    - dmaengine: xilinx_dma: use readl_poll_timeout_atomic variant
+    - x86/xen: don't unbind uninitialized lock_kicker_irq
+    - HID: logitech-hidpp: Add HIDPP_CONSUMER_VENDOR_KEYS quirk for the Dinovo
+      Edge
+    - HID: Add Logitech Dinovo Edge battery quirk
+    - proc: don't allow async path resolution of /proc/self components
+    - nvme: free sq/cq dbbuf pointers when dbbuf set fails
+    - vhost scsi: fix cmd completion race
+    - dmaengine: pl330: _prep_dma_memcpy: Fix wrong burst size
+    - scsi: libiscsi: Fix NOP race condition
+    - scsi: target: iscsi: Fix cmd abort fabric stop race
+    - perf/x86: fix sysfs type mismatches
+    - xtensa: uaccess: Add missing __user to strncpy_from_user() prototype
+    - net: dsa: mv88e6xxx: Wait for EEPROM done after HW reset
+    - bus: ti-sysc: Fix bogus resetdone warning on enable for cpsw
+    - ARM: OMAP2+: Manage MPU state properly for omap_enter_idle_coupled()
+    - phy: tegra: xusb: Fix dangling pointer on probe failure
+    - iwlwifi: mvm: write queue_sync_state only for sync
+    - batman-adv: set .owner to THIS_MODULE
+    - arch: pgtable: define MAX_POSSIBLE_PHYSMEM_BITS where needed
+    - ARM: dts: dra76x: m_can: fix order of clocks
+    - scsi: ufs: Fix race between shutdown and runtime resume flow
+    - bnxt_en: fix error return code in bnxt_init_one()
+    - bnxt_en: fix error return code in bnxt_init_board()
+    - video: hyperv_fb: Fix the cache type when mapping the VRAM
+    - bnxt_en: Release PCI regions when DMA mask setup fails during probe.
+    - cxgb4: fix the panic caused by non smac rewrite
+    - s390/qeth: make af_iucv TX notification call more robust
+    - s390/qeth: fix af_iucv notification race
+    - s390/qeth: fix tear down of async TX buffers
+    - ibmvnic: fix call_netdevice_notifiers in do_reset
+    - ibmvnic: notify peers when failover and migration happen
+    - powerpc/64s: Fix allnoconfig build since uaccess flush
+    - IB/mthca: fix return value of error branch in mthca_init_cq()
+    - i40e: Fix removing driver while bare-metal VFs pass traffic
+    - nfc: s3fwrn5: use signed integer for parsing GPIO numbers
+    - net: ena: set initial DMA width to avoid intel iommu issue
+    - ibmvnic: fix NULL pointer dereference in reset_sub_crq_queues
+    - ibmvnic: fix NULL pointer dereference in ibmvic_reset_crq
+    - optee: add writeback to valid memory type
+    - arm64: tegra: Wrong AON HSP reg property size
+    - efivarfs: revert "fix memory leak in efivarfs_create()"
+    - efi: EFI_EARLYCON should depend on EFI
+    - can: gs_usb: fix endianess problem with candleLight firmware
+    - platform/x86: thinkpad_acpi: Send tablet mode switch at wakeup time
+    - platform/x86: toshiba_acpi: Fix the wrong variable assignment
+    - RDMA/hns: Fix retry_cnt and rnr_cnt when querying QP
+    - RDMA/hns: Bugfix for memory window mtpt configuration
+    - can: m_can: m_can_open(): remove IRQF_TRIGGER_FALLING from
+      request_threaded_irq()'s flags
+    - can: m_can: fix nominal bitiming tseg2 min for version >= 3.1
+    - perf stat: Use proper cpu for shadow stats
+    - perf probe: Fix to die_entrypc() returns error correctly
+    - spi: bcm2835aux: Restore err assignment in bcm2835aux_spi_probe
+    - USB: core: Change %pK for __user pointers to %px
+    - usb: gadget: f_midi: Fix memleak in f_midi_alloc
+    - USB: quirks: Add USB_QUIRK_DISCONNECT_SUSPEND quirk for Lenovo A630Z TIO
+      built-in usb-audio card
+    - usb: gadget: Fix memleak in gadgetfs_fill_super
+    - irqchip/exiu: Fix the index of fwspec for IRQ type
+    - x86/mce: Do not overwrite no_way_out if mce_end() fails
+    - x86/speculation: Fix prctl() when spectre_v2_user={seccomp,prctl},ibpb
+    - x86/resctrl: Remove superfluous kernfs_get() calls to prevent refcount leak
+    - x86/resctrl: Add necessary kernfs_put() calls to prevent refcount leak
+    - USB: core: Fix regression in Hercules audio card
+    - ASoC: Intel: Skylake: Remove superfluous chip initialization
+    - ASoC: Intel: Skylake: Select hda configuration permissively
+    - ASoC: Intel: Skylake: Enable codec wakeup during chip init
+    - ASoC: Intel: Skylake: Shield against no-NHLT configurations
+    - ASoC: Intel: Allow for ROM init retry on CNL platforms
+    - ASoC: Intel: Skylake: Await purge request ack on CNL
+    - ASoC: Intel: Multiple I/O PCM format support for pipe
+    - ASoC: Intel: Skylake: Automatic DMIC format configuration according to
+      information from NHLT
+    - Linux 5.4.81
+
+  * Focal update: v5.4.80 upstream stable release (LP: #1908561)
+    - ah6: fix error return code in ah6_input()
+    - atm: nicstar: Unmap DMA on send error
+    - bnxt_en: read EEPROM A2h address using page 0
+    - devlink: Add missing genlmsg_cancel() in devlink_nl_sb_port_pool_fill()
+    - Exempt multicast addresses from five-second neighbor lifetime
+    - inet_diag: Fix error path to cancel the meseage in inet_req_diag_fill()
+    - ipv6: Fix error path to cancel the meseage
+    - lan743x: fix issue causing intermittent kernel log warnings
+    - lan743x: prevent entire kernel HANG on open, for some platforms
+    - mlxsw: core: Use variable timeout for EMAD retries
+    - net: b44: fix error return code in b44_init_one()
+    - net: bridge: add missing counters to ndo_get_stats64 callback
+    - net: dsa: mv88e6xxx: Avoid VTU corruption on 6097
+    - net: ethernet: ti: cpsw: fix error return code in cpsw_probe()
+    - net: Have netpoll bring-up DSA management interface
+    - netlabel: fix our progress tracking in netlbl_unlabel_staticlist()
+    - netlabel: fix an uninitialized warning in netlbl_unlabel_staticlist()
+    - net: lantiq: Wait for the GPHY firmware to be ready
+    - net/mlx4_core: Fix init_hca fields offset
+    - net: qualcomm: rmnet: Fix incorrect receive packet handling during cleanup
+    - net/smc: fix direct access to ib_gid_addr->ndev in smc_ib_determine_gid()
+    - net/tls: fix corrupted data in recvmsg
+    - net: x25: Increase refcnt of "struct x25_neigh" in x25_rx_call_request
+    - page_frag: Recover from memory pressure
+    - qed: fix error return code in qed_iwarp_ll2_start()
+    - qlcnic: fix error return code in qlcnic_83xx_restart_hw()
+    - sctp: change to hold/put transport for proto_unreach_timer
+    - tcp: only postpone PROBE_RTT if RTT is < current min_rtt estimate
+    - net/mlx5: Add handling of port type in rule deletion
+    - net/mlx5: Disable QoS when min_rates on all VFs are zero
+    - net: usb: qmi_wwan: Set DTR quirk for MR400
+    - net/ncsi: Fix netlink registration
+    - net: ftgmac100: Fix crash when removing driver
+    - pinctrl: rockchip: enable gpio pclk for rockchip_gpio_to_irq
+    - scsi: ufs: Fix unbalanced scsi_block_reqs_cnt caused by ufshcd_hold()
+    - selftests: kvm: Fix the segment descriptor layout to match the actual layout
+    - ACPI: button: Add DMI quirk for Medion Akoya E2228T
+    - arm64: errata: Fix handling of 1418040 with late CPU onlining
+    - arm64: psci: Avoid printing in cpu_psci_cpu_die()
+    - arm64: smp: Tell RCU about CPUs that fail to come online
+    - vfs: remove lockdep bogosity in __sb_start_write
+    - gfs2: fix possible reference leak in gfs2_check_blk_type
+    - hwmon: (pwm-fan) Fix RPM calculation
+    - arm64: dts: allwinner: beelink-gs1: Enable both RGMII RX/TX delay
+    - arm64: dts: allwinner: Pine H64: Enable both RGMII RX/TX delay
+    - arm64: dts: allwinner: a64: OrangePi Win: Fix ethernet node
+    - arm64: dts: allwinner: a64: Pine64 Plus: Fix ethernet node
+    - arm64: dts: allwinner: h5: OrangePi PC2: Fix ethernet node
+    - ARM: dts: sun8i: r40: bananapi-m2-ultra: Fix ethernet node
+    - Revert "arm: sun8i: orangepi-pc-plus: Set EMAC activity LEDs to active high"
+    - ARM: dts: sun6i: a31-hummingbird: Enable RGMII RX/TX delay on Ethernet PHY
+    - ARM: dts: sun7i: cubietruck: Enable RGMII RX/TX delay on Ethernet PHY
+    - ARM: dts: sun7i: bananapi-m1-plus: Enable RGMII RX/TX delay on Ethernet PHY
+    - ARM: dts: sun8i: h3: orangepi-plus2e: Enable RGMII RX/TX delay on Ethernet
+      PHY
+    - ARM: dts: sun8i: a83t: Enable both RGMII RX/TX delay on Ethernet PHY
+    - ARM: dts: sun9i: Enable both RGMII RX/TX delay on Ethernet PHY
+    - ARM: dts: sunxi: bananapi-m2-plus: Enable RGMII RX/TX delay on Ethernet PHY
+    - arm64: dts: allwinner: a64: bananapi-m64: Enable RGMII RX/TX delay on PHY
+    - Input: adxl34x - clean up a data type in adxl34x_probe()
+    - MIPS: export has_transparent_hugepage() for modules
+    - arm64: dts: allwinner: h5: OrangePi Prime: Fix ethernet node
+    - arm64: dts imx8mn: Remove non-existent USB OTG2
+    - arm: dts: imx6qdl-udoo: fix rgmii phy-mode for ksz9031 phy
+    - swiotlb: using SIZE_MAX needs limits.h included
+    - arm64: dts: imx8mm: fix voltage for 1.6GHz CPU operating point
+    - ARM: dts: imx50-evk: Fix the chip select 1 IOMUX
+    - Input: resistive-adc-touch - fix kconfig dependency on IIO_BUFFER
+    - rfkill: Fix use-after-free in rfkill_resume()
+    - RDMA/pvrdma: Fix missing kfree() in pvrdma_register_device()
+    - [Config] updateconfigs for INFINIBAND_VIRT_DMA
+    - RMDA/sw: Don't allow drivers using dma_virt_ops on highmem configs
+    - perf lock: Don't free "lock_seq_stat" if read_count isn't zero
+    - tools, bpftool: Add missing close before bpftool net attach exit
+    - ip_tunnels: Set tunnel option flag when tunnel metadata is present
+    - can: af_can: prevent potential access of uninitialized member in can_rcv()
+    - can: af_can: prevent potential access of uninitialized member in canfd_rcv()
+    - can: dev: can_restart(): post buffer from the right context
+    - can: ti_hecc: Fix memleak in ti_hecc_probe
+    - can: mcba_usb: mcba_usb_start_xmit(): first fill skb, then pass to
+      can_put_echo_skb()
+    - can: peak_usb: fix potential integer overflow on shift of a int
+    - can: flexcan: fix failure handling of pm_runtime_get_sync()
+    - can: tcan4x5x: replace depends on REGMAP_SPI with depends on SPI
+    - can: tcan4x5x: tcan4x5x_can_probe(): add missing error checking for
+      devm_regmap_init()
+    - can: tcan4x5x: tcan4x5x_can_remove(): fix order of deregistration
+    - can: m_can: m_can_handle_state_change(): fix state change
+    - can: m_can: m_can_class_free_dev(): introduce new function
+    - can: m_can: m_can_stop(): set device to software init mode before closing
+    - ASoC: qcom: lpass-platform: Fix memory leak
+    - selftests/bpf: Fix error return code in run_getsockopt_test()
+    - MIPS: Alchemy: Fix memleak in alchemy_clk_setup_cpu
+    - drm/sun4i: dw-hdmi: fix error return code in sun8i_dw_hdmi_bind()
+    - net/mlx5: E-Switch, Fail mlx5_esw_modify_vport_rate if qos disabled
+    - bpf, sockmap: Fix partial copy_page_to_iter so progress can still be made
+    - bpf, sockmap: Ensure SO_RCVBUF memory is observed on ingress redirect
+    - can: kvaser_pciefd: Fix KCAN bittiming limits
+    - can: kvaser_usb: kvaser_usb_hydra: Fix KCAN bittiming limits
+    - iommu/vt-d: Move intel_iommu_gfx_mapped to Intel IOMMU header
+    - iommu/vt-d: Avoid panic if iommu init fails in tboot system
+    - can: flexcan: flexcan_chip_start(): fix erroneous
+      flexcan_transceiver_enable() during bus-off recovery
+    - can: m_can: process interrupt only when not runtime suspended
+    - xfs: fix the minrecs logic when dealing with inode root child blocks
+    - xfs: strengthen rmap record flags checking
+    - xfs: return corresponding errcode if xfs_initialize_perag() fail
+    - regulator: ti-abb: Fix array out of bound read access on the first
+      transition
+    - fail_function: Remove a redundant mutex unlock
+    - xfs: revert "xfs: fix rmap key and record comparison functions"
+    - bpf, sockmap: Skb verdict SK_PASS to self already checked rmem limits
+    - bpf, sockmap: On receive programs try to fast track SK_PASS ingress
+    - bpf, sockmap: Use truesize with sk_rmem_schedule()
+    - bpf, sockmap: Avoid returning unneeded EAGAIN when redirecting to self
+    - efi/x86: Free efi_pgd with free_pages()
+    - libfs: fix error cast of negative value in simple_attr_write()
+    - HID: logitech-hidpp: Add PID for MX Anywhere 2
+    - HID: logitech-dj: Handle quad/bluetooth keyboards with a builtin trackpad
+    - HID: logitech-dj: Fix Dinovo Mini when paired with a MX5x00 receiver
+    - speakup: Do not let the line discipline be used several times
+    - ALSA: firewire: Clean up a locking issue in copy_resp_to_buf()
+    - ALSA: usb-audio: Add delay quirk for all Logitech USB devices
+    - ALSA: ctl: fix error path at adding user-defined element set
+    - ALSA: mixart: Fix mutex deadlock
+    - ALSA: hda/realtek - Add supported for Lenovo ThinkPad Headset Button
+    - ALSA: hda/realtek: Add some Clove SSID in the ALC293(ALC1220)
+    - tty: serial: imx: fix potential deadlock
+    - tty: serial: imx: keep console clocks always on
+    - HID: logitech-dj: Fix an error in mse_bluetooth_descriptor
+    - efivarfs: fix memory leak in efivarfs_create()
+    - staging: rtl8723bs: Add 024c:0627 to the list of SDIO device-ids
+    - iio: light: fix kconfig dependency bug for VCNL4035
+    - ext4: fix bogus warning in ext4_update_dx_flag()
+    - iio: accel: kxcjk1013: Replace is_smo8500_device with an acpi_type enum
+    - iio: accel: kxcjk1013: Add support for KIOX010A ACPI DSM for setting tablet-
+      mode
+    - iio: adc: mediatek: fix unset field
+    - spi: lpspi: Fix use-after-free on unbind
+    - spi: Introduce device-managed SPI controller allocation
+    - spi: npcm-fiu: Don't leak SPI master in probe error path
+    - spi: bcm2835aux: Fix use-after-free on unbind
+    - regulator: pfuze100: limit pfuze-support-disable-sw to pfuze{100,200}
+    - regulator: fix memory leak with repeated set_machine_constraints()
+    - regulator: avoid resolve_supply() infinite recursion
+    - regulator: workaround self-referent regulators
+    - xtensa: fix TLBTEMP area placement
+    - xtensa: disable preemption around cache alias management calls
+    - mac80211: minstrel: remove deferred sampling code
+    - mac80211: minstrel: fix tx status processing corner case
+    - mac80211: free sta in sta_info_insert_finish() on errors
+    - s390/cpum_sf.c: fix file permission for cpum_sfb_size
+    - s390/dasd: fix null pointer dereference for ERP requests
+    - Drivers: hv: vmbus: Allow cleanup of VMBUS_CONNECT_CPU if disconnected
+    - drm/amd/display: Add missing pflip irq for dcn2.0
+    - drm/i915: Handle max_bpc==16
+    - mmc: sdhci-pci: Prefer SDR25 timing for High Speed mode for BYT-based Intel
+      controllers
+    - ptrace: Set PF_SUPERPRIV when checking capability
+    - seccomp: Set PF_SUPERPRIV when checking capability
+    - x86/microcode/intel: Check patch signature before saving microcode for early
+      loading
+    - mm: memcg/slab: fix root memcg vmstats
+    - mm/userfaultfd: do not access vma->vm_mm after calling handle_userfault()
+    - mm, page_alloc: skip ->waternark_boost for atomic order-0 allocations
+    - sched/fair: Fix overutilized update in enqueue_task_fair()
+    - Linux 5.4.80
+
+  * [SRU][F/G/H/U/OEM-5.6] Fix i2c report error on elan trackpoint
+    (LP: #1908335)
+    - Input: elan_i2c - add support for high resolution reports
+    - Input: elan_i2c - add new trackpoint report type 0x5F
+    - Input: elantech - fix protocol errors for some trackpoints in SMBus mode
+
+  * rtwpci driver blocks the system to enter PC10, stuck at PC3 (LP: #1907200)
+    - SAUCE: rtw88: 8723de: let cpu enter c10
+
+  * [UBUNTU 21.04] s390/pci: vfio-pci mmio being disabled erroneously
+    (LP: #1907265)
+    - s390/pci: Mark all VFs as not implementing PCI_COMMAND_MEMORY
+
+  * Touchpad not detected on ByteSpeed C15B laptop (LP: #1906128)
+    - Input: i8042 - add ByteSpeed touchpad to noloop table
+
+  * Fix reading speed and duplex sysfs on igc device (LP: #1906851)
+    - SAUCE: igc: Report speed and duplex as unknown when device is runtime
+      suspended
+
+  * stack trace in kernel (LP: #1903596)
+    - net: napi: remove useless stack trace
+
+  * Refresh ACPI wakeup power to make Thunderbolt hotplug detection work
+    (LP: #1906229)
+    - PM: ACPI: PCI: Drop acpi_pm_set_bridge_wakeup()
+    - PM: ACPI: Refresh wakeup device power configuration every time
+
+  * CVE-2020-27777
+    - [Config]: Set CONFIG_PPC_RTAS_FILTER
+
+  * Add dpcd backlight control for 0x4c83 0x4f41 (LP: #1905663)
+    - SAUCE: drm/dp: Add dpcd backlight control for 0x4c83 0x4f41
+
+  * Focal update: v5.4.79 upstream stable release (LP: #1907151)
+    - powerpc: Only include kup-radix.h for 64-bit Book3S
+    - MIPS: PCI: Fix MIPS build
+    - powerpc/8xx: Always fault when _PAGE_ACCESSED is not set
+    - net: lantiq: Add locking for TX DMA channel
+    - Input: sunkbd - avoid use-after-free in teardown paths
+    - mac80211: always wind down STA state
+    - can: proc: can_remove_proc(): silence remove_proc_entry warning
+    - KVM: x86: clflushopt should be treated as a no-op by emulation
+    - ACPI: GED: fix -Wformat
+    - Linux 5.4.79
+
+ -- Ian May <ian.may@canonical.com>  Wed, 27 Jan 2021 15:44:24 -0600
+
+linux (5.4.0-65.73) focal; urgency=medium
+
+  * focal/linux: 5.4.0-65.73 -proposed tracker (LP: #1912220)
+
+  * initramfs unpacking failed (LP: #1835660)
+    - SAUCE: lib/decompress_unlz4.c: correctly handle zero-padding around initrds.
+
+  * overlay: permission regression in 5.4.0-51.56 due to patches related to
+    CVE-2020-16120 (LP: #1900141)
+    - ovl: do not fail because of O_NOATIME
+
+  * Focal update: v5.4.79 upstream stable release (LP: #1907151)
+    - net/mlx5: Use async EQ setup cleanup helpers for multiple EQs
+    - net/mlx5: poll cmd EQ in case of command timeout
+    - net/mlx5: Fix a race when moving command interface to events mode
+    - net/mlx5: Add retry mechanism to the command entry index allocation
+
+  * Kernel 5.4.0-56 Wi-Fi does not connect (LP: #1906770)
+    - mt76: fix fix ampdu locking
+
+  * [Ubuntu 21.04 FEAT] mpt3sas: Request to include the patch set which supports
+    topology where zoning is enabled in expander (LP: #1899802)
+    - scsi: mpt3sas: Define hba_port structure
+    - scsi: mpt3sas: Allocate memory for hba_port objects
+    - scsi: mpt3sas: Rearrange _scsih_mark_responding_sas_device()
+    - scsi: mpt3sas: Update hba_port's sas_address & phy_mask
+    - scsi: mpt3sas: Get device objects using sas_address & portID
+    - scsi: mpt3sas: Rename transport_del_phy_from_an_existing_port()
+    - scsi: mpt3sas: Get sas_device objects using device's rphy
+    - scsi: mpt3sas: Update hba_port objects after host reset
+    - scsi: mpt3sas: Set valid PhysicalPort in SMPPassThrough
+    - scsi: mpt3sas: Handling HBA vSES device
+    - scsi: mpt3sas: Add bypass_dirty_port_flag parameter
+    - scsi: mpt3sas: Handle vSES vphy object during HBA reset
+    - scsi: mpt3sas: Add module parameter multipath_on_hba
+    - scsi: mpt3sas: Bump driver version to 35.101.00.00
+
+ -- Kleber Sacilotto de Souza <kleber.souza@canonical.com>  Mon, 18 Jan 2021 17:31:23 +0100
+
+linux (5.4.0-64.72) focal; urgency=medium
+
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Fri, 15 Jan 2021 10:50:30 +0100
+
+linux (5.4.0-62.70) focal; urgency=medium
+
+  * focal/linux: 5.4.0-62.70 -proposed tracker (LP: #1911144)
+
+  * CVE-2020-28374
+    - SAUCE: target: fix XCOPY NAA identifier lookup
+
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+
+ -- Kleber Sacilotto de Souza <kleber.souza@canonical.com>  Tue, 12 Jan 2021 13:00:40 +0100
+
+linux (5.4.0-60.67) focal; urgency=medium
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update variants
+    - update dkms package versions
+
+  * CVE-2021-1052 // CVE-2021-1053
+    - [Packaging] NVIDIA -- Add the NVIDIA 460 driver
+
+ -- Thadeu Lima de Souza Cascardo <cascardo@canonical.com>  Tue, 05 Jan 2021 13:51:33 -0300
+
+linux (5.4.0-59.65) focal; urgency=medium
+
+  * focal/linux: 5.4.0-59.65 -proposed tracker (LP: #1907604)
+
+  * focal: selftests/bpf build broken: test_map_init.skel.h: No such file or
+    directory (LP: #1906866)
+    - SAUCE: Revert selftests/ "bpf: Zero-fill re-used per-cpu map element"
+
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+
+  * memory is leaked when tasks are moved to net_prio (LP: #1886859)
+    - netprio_cgroup: Fix unlimited memory leak of v2 cgroups
+
+  * Focal update: v5.4.78 upstream stable release (LP: #1905618)
+    - drm/i915/gem: Flush coherency domains on first set-domain-ioctl
+    - time: Prevent undefined behaviour in timespec64_to_ns()
+    - nbd: don't update block size after device is started
+    - KVM: arm64: Force PTE mapping on fault resulting in a device mapping
+    - PCI: qcom: Make sure PCIe is reset before init for rev 2.1.0
+    - usb: dwc3: gadget: Continue to process pending requests
+    - usb: dwc3: gadget: Reclaim extra TRBs after request completion
+    - btrfs: tracepoints: output proper root owner for trace_find_free_extent()
+    - btrfs: sysfs: init devices outside of the chunk_mutex
+    - btrfs: reschedule when cloning lots of extents
+    - ASoC: Intel: kbl_rt5663_max98927: Fix kabylake_ssp_fixup function
+    - genirq: Let GENERIC_IRQ_IPI select IRQ_DOMAIN_HIERARCHY
+    - hv_balloon: disable warning when floor reached
+    - net: xfrm: fix a race condition during allocing spi
+    - ASoC: codecs: wcd9335: Set digital gain range correctly
+    - xfs: set xefi_discard when creating a deferred agfl free log intent item
+    - netfilter: use actual socket sk rather than skb sk when routing harder
+    - netfilter: nf_tables: missing validation from the abort path
+    - netfilter: ipset: Update byte and packet counters regardless of whether they
+      match
+    - powerpc/eeh_cache: Fix a possible debugfs deadlock
+    - perf trace: Fix segfault when trying to trace events by cgroup
+    - perf tools: Add missing swap for ino_generation
+    - ALSA: hda: prevent undefined shift in snd_hdac_ext_bus_get_link()
+    - iommu/vt-d: Fix a bug for PDP check in prq_event_thread
+    - afs: Fix warning due to unadvanced marshalling pointer
+    - can: rx-offload: don't call kfree_skb() from IRQ context
+    - can: dev: can_get_echo_skb(): prevent call to kfree_skb() in hard IRQ
+      context
+    - can: dev: __can_get_echo_skb(): fix real payload length return value for RTR
+      frames
+    - can: can_create_echo_skb(): fix echo skb generation: always use skb_clone()
+    - can: j1939: swap addr and pgn in the send example
+    - can: j1939: j1939_sk_bind(): return failure if netdev is down
+    - can: ti_hecc: ti_hecc_probe(): add missed clk_disable_unprepare() in error
+      path
+    - can: xilinx_can: handle failure cases of pm_runtime_get_sync
+    - can: peak_usb: add range checking in decode operations
+    - can: peak_usb: peak_usb_get_ts_time(): fix timestamp wrapping
+    - can: peak_canfd: pucan_handle_can_rx(): fix echo management when loopback is
+      on
+    - can: flexcan: remove FLEXCAN_QUIRK_DISABLE_MECR quirk for LS1021A
+    - can: flexcan: flexcan_remove(): disable wakeup completely
+    - xfs: flush new eof page on truncate to avoid post-eof corruption
+    - xfs: fix scrub flagging rtinherit even if there is no rt device
+    - tpm: efi: Don't create binary_bios_measurements file for an empty log
+    - random32: make prandom_u32() output unpredictable
+    - KVM: arm64: ARM_SMCCC_ARCH_WORKAROUND_1 doesn't return
+      SMCCC_RET_NOT_REQUIRED
+    - KVM: x86: don't expose MSR_IA32_UMWAIT_CONTROL unconditionally
+    - ath9k_htc: Use appropriate rs_datalen type
+    - ASoC: qcom: sdm845: set driver name correctly
+    - ASoC: cs42l51: manage mclk shutdown delay
+    - usb: dwc3: pci: add support for the Intel Alder Lake-S
+    - opp: Reduce the size of critical section in _opp_table_kref_release()
+    - usb: gadget: goku_udc: fix potential crashes in probe
+    - selftests/ftrace: check for do_sys_openat2 in user-memory test
+    - selftests: pidfd: fix compilation errors due to wait.h
+    - ALSA: hda: Separate runtime and system suspend
+    - ALSA: hda: Reinstate runtime_allow() for all hda controllers
+    - gfs2: Free rd_bits later in gfs2_clear_rgrpd to fix use-after-free
+    - gfs2: Add missing truncate_inode_pages_final for sd_aspace
+    - gfs2: check for live vs. read-only file system in gfs2_fitrim
+    - scsi: hpsa: Fix memory leak in hpsa_init_one()
+    - drm/amdgpu: perform srbm soft reset always on SDMA resume
+    - drm/amd/pm: perform SMC reset on suspend/hibernation
+    - drm/amd/pm: do not use ixFEATURE_STATUS for checking smc running
+    - mac80211: fix use of skb payload instead of header
+    - cfg80211: initialize wdev data earlier
+    - cfg80211: regulatory: Fix inconsistent format argument
+    - tracing: Fix the checking of stackidx in __ftrace_trace_stack
+    - scsi: scsi_dh_alua: Avoid crash during alua_bus_detach()
+    - scsi: mpt3sas: Fix timeouts observed while reenabling IRQ
+    - nvme: introduce nvme_sync_io_queues
+    - nvme-rdma: avoid race between time out and tear down
+    - nvme-tcp: avoid race between time out and tear down
+    - nvme-rdma: avoid repeated request completion
+    - nvme-tcp: avoid repeated request completion
+    - iommu/amd: Increase interrupt remapping table limit to 512 entries
+    - s390/smp: move rcu_cpu_starting() earlier
+    - vfio: platform: fix reference leak in vfio_platform_open
+    - vfio/pci: Bypass IGD init in case of -ENODEV
+    - i2c: mediatek: move dma reset before i2c reset
+    - amd/amdgpu: Disable VCN DPG mode for Picasso
+    - selftests: proc: fix warning: _GNU_SOURCE redefined
+    - riscv: Set text_offset correctly for M-Mode
+    - i2c: sh_mobile: implement atomic transfers
+    - tpm_tis: Disable interrupts on ThinkPad T490s
+    - spi: bcm2835: remove use of uninitialized gpio flags variable
+    - tick/common: Touch watchdog in tick_unfreeze() on all CPUs
+    - mfd: sprd: Add wakeup capability for PMIC IRQ
+    - pinctrl: intel: Set default bias in case no particular value given
+    - ARM: 9019/1: kprobes: Avoid fortify_panic() when copying optprobe template
+    - bpf: Don't rely on GCC __attribute__((optimize)) to disable GCSE
+    - pinctrl: aspeed: Fix GPI only function problem.
+    - net/mlx5: Fix deletion of duplicate rules
+    - SUNRPC: Fix general protection fault in trace_rpc_xdr_overflow()
+    - bpf: Zero-fill re-used per-cpu map element
+    - nbd: fix a block_device refcount leak in nbd_release
+    - igc: Fix returning wrong statistics
+    - xfs: fix flags argument to rmap lookup when converting shared file rmaps
+    - xfs: set the unwritten bit in rmap lookup flags in xchk_bmap_get_rmapextents
+    - xfs: fix rmap key and record comparison functions
+    - xfs: fix brainos in the refcount scrubber's rmap fragment processor
+    - lan743x: fix "BUG: invalid wait context" when setting rx mode
+    - xfs: fix a missing unlock on error in xfs_fs_map_blocks
+    - of/address: Fix of_node memory leak in of_dma_is_coherent
+    - cosa: Add missing kfree in error path of cosa_write
+    - vrf: Fix fast path output packet handling with async Netfilter rules
+    - perf: Fix get_recursion_context()
+    - erofs: derive atime instead of leaving it empty
+    - ext4: correctly report "not supported" for {usr,grp}jquota when
+      !CONFIG_QUOTA
+    - ext4: unlock xattr_sem properly in ext4_inline_data_truncate()
+    - btrfs: ref-verify: fix memory leak in btrfs_ref_tree_mod
+    - btrfs: fix min reserved size calculation in merge_reloc_root
+    - btrfs: dev-replace: fail mount if we don't have replace item with target
+      device
+    - KVM: arm64: Don't hide ID registers from userspace
+    - thunderbolt: Fix memory leak if ida_simple_get() fails in
+      enumerate_services()
+    - thunderbolt: Add the missed ida_simple_remove() in ring_request_msix()
+    - uio: Fix use-after-free in uio_unregister_device()
+    - usb: cdc-acm: Add DISABLE_ECHO for Renesas USB Download mode
+    - xhci: hisilicon: fix refercence leak in xhci_histb_probe
+    - virtio: virtio_console: fix DMA memory allocation for rproc serial
+    - mei: protect mei_cl_mtu from null dereference
+    - futex: Don't enable IRQs unconditionally in put_pi_state()
+    - jbd2: fix up sparse warnings in checkpoint code
+    - mm/slub: fix panic in slab_alloc_node()
+    - Revert "kernel/reboot.c: convert simple_strtoul to kstrtoint"
+    - reboot: fix overflow parsing reboot cpu number
+    - ocfs2: initialize ip_next_orphan
+    - btrfs: fix potential overflow in cluster_pages_for_defrag on 32bit arch
+    - selinux: Fix error return code in sel_ib_pkey_sid_slow()
+    - gpio: pcie-idio-24: Fix irq mask when masking
+    - gpio: pcie-idio-24: Fix IRQ Enable Register value
+    - gpio: pcie-idio-24: Enable PEX8311 interrupts
+    - mmc: sdhci-of-esdhc: Handle pulse width detection erratum for more SoCs
+    - mmc: renesas_sdhi_core: Add missing tmio_mmc_host_free() at remove
+    - don't dump the threads that had been already exiting when zapped.
+    - drm/gma500: Fix out-of-bounds access to struct drm_device.vblank[]
+    - pinctrl: amd: use higher precision for 512 RtcClk
+    - pinctrl: amd: fix incorrect way to disable debounce filter
+    - swiotlb: fix "x86: Don't panic if can not alloc buffer for swiotlb"
+    - IPv6: Set SIT tunnel hard_header_len to zero
+    - net/af_iucv: fix null pointer dereference on shutdown
+    - net: udp: fix UDP header access on Fast/frag0 UDP GRO
+    - net: Update window_clamp if SOCK_RCVBUF is set
+    - net/x25: Fix null-ptr-deref in x25_connect
+    - tipc: fix memory leak in tipc_topsrv_start()
+    - r8169: fix potential skb double free in an error path
+    - drm/i915: Correctly set SFC capability for video engines
+    - powerpc/603: Always fault when _PAGE_ACCESSED is not set
+    - x86/speculation: Allow IBPB to be conditionally enabled on CPUs with always-
+      on STIBP
+    - perf scripting python: Avoid declaring function pointers with a visibility
+      attribute
+    - net: sch_generic: fix the missing new qdisc assignment bug
+    - Convert trailing spaces and periods in path components
+    - Linux 5.4.78
+
+  * Focal update: v5.4.77 upstream stable release (LP: #1905614)
+    - Linux 5.4.77
+
+  * Focal update: v5.4.76 upstream stable release (LP: #1905612)
+    - drm/i915: Break up error capture compression loops with cond_resched()
+    - drm/i915/gt: Delay execlist processing for tgl
+    - drm/i915: Drop runtime-pm assert from vgpu io accessors
+    - ASoC: Intel: Skylake: Add alternative topology binary name
+    - update dkms package versions
+    - linkage: Introduce new macros for assembler symbols
+    - arm64: asm: Add new-style position independent function annotations
+    - arm64: lib: Use modern annotations for assembly functions
+    - arm64: Change .weak to SYM_FUNC_START_WEAK_PI for arch/arm64/lib/mem*.S
+    - tipc: fix use-after-free in tipc_bcast_get_mode
+    - ptrace: fix task_join_group_stop() for the case when current is traced
+    - cadence: force nonlinear buffers to be cloned
+    - chelsio/chtls: fix memory leaks caused by a race
+    - chelsio/chtls: fix always leaking ctrl_skb
+    - gianfar: Replace skb_realloc_headroom with skb_cow_head for PTP
+    - gianfar: Account for Tx PTP timestamp in the skb headroom
+    - ionic: check port ptr before use
+    - ip_tunnel: fix over-mtu packet send fail without TUNNEL_DONT_FRAGMENT flags
+    - net: usb: qmi_wwan: add Telit LE910Cx 0x1230 composition
+    - powerpc/vnic: Extend "failover pending" window
+    - sctp: Fix COMM_LOST/CANT_STR_ASSOC err reporting on big-endian platforms
+    - sfp: Fix error handing in sfp_probe()
+    - Fonts: Replace discarded const qualifier
+    - ALSA: hda/realtek - Fixed HP headset Mic can't be detected
+    - ALSA: hda/realtek - Enable headphone for ASUS TM420
+    - ALSA: usb-audio: Add implicit feedback quirk for Zoom UAC-2
+    - ALSA: usb-audio: add usb vendor id as DSD-capable for Khadas devices
+    - ALSA: usb-audio: Add implicit feedback quirk for Qu-16
+    - ALSA: usb-audio: Add implicit feedback quirk for MODX
+    - mm: mempolicy: fix potential pte_unmap_unlock pte error
+    - lib/crc32test: remove extra local_irq_disable/enable
+    - kthread_worker: prevent queuing delayed work from timer_fn when it is being
+      canceled
+    - mm: always have io_remap_pfn_range() set pgprot_decrypted()
+    - gfs2: Wake up when sd_glock_disposal becomes zero
+    - ring-buffer: Fix recursion protection transitions between interrupt context
+    - mtd: spi-nor: Don't copy self-pointing struct around
+    - ftrace: Fix recursion check for NMI test
+    - ftrace: Handle tracing when switching between context
+    - regulator: defer probe when trying to get voltage from unresolved supply
+    - spi: bcm2835: fix gpio cs level inversion
+    - tracing: Fix out of bounds write in get_trace_buf
+    - futex: Handle transient "ownerless" rtmutex state correctly
+    - ARM: dts: sun4i-a10: fix cpu_alert temperature
+    - arm64: dts: meson: add missing g12 rng clock
+    - x86/kexec: Use up-to-dated screen_info copy to fill boot params
+    - of: Fix reserved-memory overlap detection
+    - drm/sun4i: frontend: Rework a bit the phase data
+    - drm/sun4i: frontend: Reuse the ch0 phase for RGB formats
+    - drm/sun4i: frontend: Fix the scaler phase on A33
+    - blk-cgroup: Fix memleak on error path
+    - blk-cgroup: Pre-allocate tree node on blkg_conf_prep
+    - scsi: core: Don't start concurrent async scan on same host
+    - drm/amdgpu: add DID for navi10 blockchain SKU
+    - scsi: ibmvscsi: Fix potential race after loss of transport
+    - vsock: use ns_capable_noaudit() on socket create
+    - nvme-rdma: handle unexpected nvme completion data length
+    - nvmet: fix a NULL pointer dereference when tracing the flush command
+    - drm/vc4: drv: Add error handding for bind
+    - ACPI: NFIT: Fix comparison to '-ENXIO'
+    - usb: cdns3: gadget: suspicious implicit sign extension
+    - drm/nouveau/nouveau: fix the start/end range for migration
+    - drm/nouveau/gem: fix "refcount_t: underflow; use-after-free"
+    - arm64/smp: Move rcu_cpu_starting() earlier
+    - vt: Disable KD_FONT_OP_COPY
+    - fork: fix copy_process(CLONE_PARENT) race with the exiting ->real_parent
+    - s390/pkey: fix paes selftest failure with paes and pkey static build
+    - serial: 8250_mtk: Fix uart_get_baud_rate warning
+    - serial: txx9: add missing platform_driver_unregister() on error in
+      serial_txx9_init
+    - USB: serial: cyberjack: fix write-URB completion race
+    - USB: serial: option: add Quectel EC200T module support
+    - USB: serial: option: add LE910Cx compositions 0x1203, 0x1230, 0x1231
+    - USB: serial: option: add Telit FN980 composition 0x1055
+    - tty: serial: fsl_lpuart: add LS1028A support
+    - tty: serial: fsl_lpuart: LS1021A has a FIFO size of 16 words, like LS1028A
+    - usb: dwc3: ep0: Fix delay status handling
+    - USB: Add NO_LPM quirk for Kingston flash drive
+    - usb: mtu3: fix panic in mtu3_gadget_stop()
+    - drm/panfrost: Fix a deadlock between the shrinker and madvise path
+    - ARC: stack unwinding: avoid indefinite looping
+    - PM: runtime: Drop runtime PM references to supplier on link removal
+    - PM: runtime: Drop pm_runtime_clean_up_links()
+    - PM: runtime: Resume the device earlier in __device_release_driver()
+    - xfs: flush for older, xfs specific ioctls
+    - perf/core: Fix a memory leak in perf_event_parse_addr_filter()
+    - arm64: dts: marvell: espressobin: Add ethernet switch aliases
+    - Linux 5.4.76
+
+  * s390: dbginfo.sh triggers kernel panic, reading from
+    /sys/kernel/mm/page_idle/bitmap (LP: #1904884)
+    - mm/page_idle.c: skip offline pages
+
+  * Ask 8821C Bluetooth controller to drop old firmware (LP: #1904221)
+    - Bluetooth: btrtl: Ask 8821C to drop old firmware
+    - Bluetooth: btrtl: fix incorrect skb allocation failure check
+
+  * Use ACPI S5 for reboot (LP: #1904225)
+    - PM: ACPI: reboot: Use S5 for reboot
+
+  * Focal update: v5.4.75 upstream stable release (LP: #1904450)
+    - xen/events: avoid removing an event channel while handling it
+    - xen/events: add a proper barrier to 2-level uevent unmasking
+    - xen/events: fix race in evtchn_fifo_unmask()
+    - xen/events: add a new "late EOI" evtchn framework
+    - xen/blkback: use lateeoi irq binding
+    - xen/netback: use lateeoi irq binding
+    - xen/scsiback: use lateeoi irq binding
+    - xen/pvcallsback: use lateeoi irq binding
+    - xen/pciback: use lateeoi irq binding
+    - xen/events: switch user event channels to lateeoi model
+    - xen/events: use a common cpu hotplug hook for event channels
+    - xen/events: defer eoi in case of excessive number of events
+    - xen/events: block rogue events for some time
+    - firmware: arm_scmi: Fix ARCH_COLD_RESET
+    - firmware: arm_scmi: Add missing Rx size re-initialisation
+    - x86/unwind/orc: Fix inactive tasks with stack pointer in %sp on GCC 10
+      compiled kernels
+    - mlxsw: core: Fix use-after-free in mlxsw_emad_trans_finish()
+    - RDMA/qedr: Fix memory leak in iWARP CM
+    - ata: sata_nv: Fix retrieving of active qcs
+    - futex: Fix incorrect should_fail_futex() handling
+    - powerpc/powernv/smp: Fix spurious DBG() warning
+    - [Config] update config for ARCH_WANT_IRQS_OFF_ACTIVATE_MM
+    - mm: fix exec activate_mm vs TLB shootdown and lazy tlb switching race
+    - powerpc: select ARCH_WANT_IRQS_OFF_ACTIVATE_MM
+    - sparc64: remove mm_cpumask clearing to fix kthread_use_mm race
+    - f2fs: add trace exit in exception path
+    - f2fs: fix uninit-value in f2fs_lookup
+    - f2fs: fix to check segment boundary during SIT page readahead
+    - s390/startup: avoid save_area_sync overflow
+    - um: change sigio_spinlock to a mutex
+    - f2fs: handle errors of f2fs_get_meta_page_nofail
+    - ARM: 8997/2: hw_breakpoint: Handle inexact watchpoint addresses
+    - NFS4: Fix oops when copy_file_range is attempted with NFS4.0 source
+    - power: supply: bq27xxx: report "not charging" on all types
+    - xfs: fix realtime bitmap/summary file truncation when growing rt volume
+    - video: fbdev: pvr2fb: initialize variables
+    - ath10k: start recovery process when payload length exceeds max htc length
+      for sdio
+    - ath10k: fix VHT NSS calculation when STBC is enabled
+    - drm/brige/megachips: Add checking if ge_b850v3_lvds_init() is working
+      correctly
+    - selftests/x86/fsgsbase: Reap a forgotten child
+    - media: videodev2.h: RGB BT2020 and HSV are always full range
+    - media: platform: Improve queue set up flow for bug fixing
+    - usb: typec: tcpm: During PR_SWAP, source caps should be sent only after
+      tSwapSourceStart
+    - media: tw5864: check status of tw5864_frameinterval_get
+    - media: imx274: fix frame interval handling
+    - mmc: via-sdmmc: Fix data race bug
+    - drm/bridge/synopsys: dsi: add support for non-continuous HS clock
+    - arm64: topology: Stop using MPIDR for topology information
+    - printk: reduce LOG_BUF_SHIFT range for H8300
+    - ia64: kprobes: Use generic kretprobe trampoline handler
+    - kgdb: Make "kgdbcon" work properly with "kgdb_earlycon"
+    - bpf: Permit map_ptr arithmetic with opcode add and offset 0
+    - media: uvcvideo: Fix dereference of out-of-bound list iterator
+    - selftests/bpf: Define string const as global for test_sysctl_prog.c
+    - samples/bpf: Fix possible deadlock in xdpsock
+    - riscv: Define AT_VECTOR_SIZE_ARCH for ARCH_DLINFO
+    - cpufreq: sti-cpufreq: add stih418 support
+    - USB: adutux: fix debugging
+    - uio: free uio id after uio file node is freed
+    - usb: xhci: omit duplicate actions when suspending a runtime suspended host.
+    - SUNRPC: Mitigate cond_resched() in xprt_transmit()
+    - arm64/mm: return cpu_all_mask when node is NUMA_NO_NODE
+    - can: flexcan: disable clocks during stop mode
+    - xfs: don't free rt blocks when we're doing a REMAP bunmapi call
+    - ACPI: Add out of bounds and numa_off protections to pxm_to_node()
+    - brcmfmac: Fix warning message after dongle setup failed
+    - drivers/net/wan/hdlc_fr: Correctly handle special skb->protocol values
+    - bus/fsl_mc: Do not rely on caller to provide non NULL mc_io
+    - ACPI: HMAT: Fix handling of changes from ACPI 6.2 to ACPI 6.3
+    - power: supply: test_power: add missing newlines when printing parameters by
+      sysfs
+    - drm/amd/display: HDMI remote sink need mode validation for Linux
+    - ARC: [dts] fix the errors detected by dtbs_check
+    - btrfs: fix replace of seed device
+    - md/bitmap: md_bitmap_get_counter returns wrong blocks
+    - bnxt_en: Log unknown link speed appropriately.
+    - rpmsg: glink: Use complete_all for open states
+    - clk: ti: clockdomain: fix static checker warning
+    - net: 9p: initialize sun_server.sun_path to have addr's value only when addr
+      is valid
+    - drivers: watchdog: rdc321x_wdt: Fix race condition bugs
+    - ext4: Detect already used quota file early
+    - KVM: PPC: Book3S HV: Do not allocate HPT for a nested guest
+    - gfs2: use-after-free in sysfs deregistration
+    - gfs2: add validation checks for size of superblock
+    - cifs: handle -EINTR in cifs_setattr
+    - arm64: dts: renesas: ulcb: add full-pwr-cycle-in-suspend into eMMC nodes
+    - ARM: dts: omap4: Fix sgx clock rate for 4430
+    - memory: emif: Remove bogus debugfs error handling
+    - ARM: dts: s5pv210: remove DMA controller bus node name to fix dtschema
+      warnings
+    - ARM: dts: s5pv210: move fixed clocks under root node
+    - ARM: dts: s5pv210: move PMU node out of clock controller
+    - ARM: dts: s5pv210: remove dedicated 'audio-subsystem' node
+    - nbd: make the config put is called before the notifying the waiter
+    - sgl_alloc_order: fix memory leak
+    - nvme-rdma: fix crash when connect rejected
+    - md/raid5: fix oops during stripe resizing
+    - mmc: sdhci: Add LTR support for some Intel BYT based controllers
+    - mmc: sdhci-acpi: AMDI0040: Set SDHCI_QUIRK2_PRESET_VALUE_BROKEN
+    - seccomp: Make duplicate listener detection non-racy
+    - selftests/x86/fsgsbase: Test PTRACE_PEEKUSER for GSBASE with invalid LDT GS
+    - perf/x86/intel: Fix Ice Lake event constraint table
+    - perf/x86/amd/ibs: Don't include randomized bits in get_ibs_op_count()
+    - perf/x86/amd/ibs: Fix raw sample data accumulation
+    - spi: sprd: Release DMA channel also on probe deferral
+    - extcon: ptn5150: Fix usage of atomic GPIO with sleeping GPIO chips
+    - leds: bcm6328, bcm6358: use devres LED registering function
+    - media: uvcvideo: Fix uvc_ctrl_fixup_xu_info() not having any effect
+    - fs: Don't invalidate page buffers in block_write_full_page()
+    - NFS: fix nfs_path in case of a rename retry
+    - ACPI: button: fix handling lid state changes when input device closed
+    - ACPI / extlog: Check for RDMSR failure
+    - ACPI: debug: don't allow debugging when ACPI is disabled
+    - PCI/ACPI: Whitelist hotplug ports for D3 if power managed by ACPI
+    - ACPI: EC: PM: Flush EC work unconditionally after wakeup
+    - ACPI: EC: PM: Drop ec_no_wakeup check from acpi_ec_dispatch_gpe()
+    - acpi-cpufreq: Honor _PSD table setting on new AMD CPUs
+    - w1: mxc_w1: Fix timeout resolution problem leading to bus error
+    - scsi: mptfusion: Fix null pointer dereferences in mptscsih_remove()
+    - scsi: qla2xxx: Fix crash on session cleanup with unload
+    - PM: runtime: Remove link state checks in rpm_get/put_supplier()
+    - btrfs: qgroup: fix wrong qgroup metadata reserve for delayed inode
+    - btrfs: improve device scanning messages
+    - btrfs: reschedule if necessary when logging directory items
+    - btrfs: send, orphanize first all conflicting inodes when processing
+      references
+    - btrfs: send, recompute reference path after orphanization of a directory
+    - btrfs: use kvzalloc() to allocate clone_roots in btrfs_ioctl_send()
+    - btrfs: tree-checker: fix false alert caused by legacy btrfs root item
+    - btrfs: cleanup cow block on error
+    - btrfs: tree-checker: validate number of chunk stripes and parity
+    - btrfs: fix use-after-free on readahead extent after failure to create it
+    - btrfs: fix readahead hang and use-after-free after removing a device
+    - Revert "UBUNTU: SAUCE: xhci: workaround for S3 issue on AMD SNPS 3.0 xHC"
+    - usb: xhci: Workaround for S3 issue on AMD SNPS 3.0 xHC
+    - usb: dwc3: pci: Allow Elkhart Lake to utilize DSM method for PM
+      functionality
+    - usb: dwc3: ep0: Fix ZLP for OUT ep0 requests
+    - usb: dwc3: gadget: Check MPS of the request length
+    - usb: dwc3: core: add phy cleanup for probe error handling
+    - usb: dwc3: core: don't trigger runtime pm when remove driver
+    - usb: dwc3: gadget: Resume pending requests after CLEAR_STALL
+    - usb: dwc3: gadget: END_TRANSFER before CLEAR_STALL command
+    - usb: cdc-acm: fix cooldown mechanism
+    - usb: typec: tcpm: reset hard_reset_count for any disconnect
+    - usb: host: fsl-mph-dr-of: check return of dma_set_mask()
+    - drm/i915: Force VT'd workarounds when running as a guest OS
+    - vt: keyboard, simplify vt_kdgkbsent
+    - vt: keyboard, extend func_buf_lock to readers
+    - HID: wacom: Avoid entering wacom_wac_pen_report for pad / battery
+    - udf: Fix memory leak when mounting
+    - dmaengine: dma-jz4780: Fix race in jz4780_dma_tx_status
+    - iio:light:si1145: Fix timestamp alignment and prevent data leak.
+    - iio: adc: gyroadc: fix leak of device node iterator
+    - iio:adc:ti-adc0832 Fix alignment issue with timestamp
+    - iio:adc:ti-adc12138 Fix alignment issue with timestamp
+    - iio:gyro:itg3200: Fix timestamp alignment and prevent data leak.
+    - powerpc/drmem: Make lmb_size 64 bit
+    - MIPS: DEC: Restore bootmem reservation for firmware working memory area
+    - s390/stp: add locking to sysfs functions
+    - [Config] update config for PPC_RTAS_FILTER
+    - powerpc/rtas: Restrict RTAS requests from userspace
+    - powerpc: Warn about use of smt_snooze_delay
+    - powerpc/memhotplug: Make lmb size 64bit
+    - powerpc/powernv/elog: Fix race while processing OPAL error log event.
+    - powerpc/powermac: Fix low_sleep_handler with KUAP and KUEP
+    - NFSv4: Wait for stateid updates after CLOSE/OPEN_DOWNGRADE
+    - NFSv4.2: support EXCHGID4_FLAG_SUPP_FENCE_OPS 4.2 EXCHANGE_ID flag
+    - NFSD: Add missing NFSv2 .pc_func methods
+    - ubifs: dent: Fix some potential memory leaks while iterating entries
+    - ubifs: xattr: Fix some potential memory leaks while iterating entries
+    - ubifs: journal: Make sure to not dirty twice for auth nodes
+    - ubifs: Fix a memleak after dumping authentication mount options
+    - ubifs: Don't parse authentication mount options in remount process
+    - ubifs: mount_ubifs: Release authentication resource in error handling path
+    - perf python scripting: Fix printable strings in python3 scripts
+    - ARC: perf: redo the pct irq missing in device-tree handling
+    - ubi: check kthread_should_stop() after the setting of task state
+    - ia64: fix build error with !COREDUMP
+    - rtc: rx8010: don't modify the global rtc ops
+    - i2c: imx: Fix external abort on interrupt in exit paths
+    - drm/amdgpu: don't map BO in reserved region
+    - drm/amd/display: Increase timeout for DP Disable
+    - drm/amdgpu: correct the gpu reset handling for job != NULL case
+    - drm/amdkfd: Use same SQ prefetch setting as amdgpu
+    - drm/amd/display: Avoid MST manager resource leak.
+    - drm/amdgpu: increase the reserved VM size to 2MB
+    - drm/amd/display: Don't invoke kgdb_breakpoint() unconditionally
+    - drm/amd/display: Fix kernel panic by dal_gpio_open() error
+    - ceph: promote to unsigned long long before shifting
+    - libceph: clear con->out_msg on Policy::stateful_server faults
+    - 9P: Cast to loff_t before multiplying
+    - ring-buffer: Return 0 on success from ring_buffer_resize()
+    - vringh: fix __vringh_iov() when riov and wiov are different
+    - ext4: fix leaking sysfs kobject after failed mount
+    - ext4: fix error handling code in add_new_gdb
+    - ext4: fix invalid inode checksum
+    - drm/ttm: fix eviction valuable range check.
+    - mmc: sdhci-of-esdhc: set timeout to max before tuning
+    - mmc: sdhci: Use Auto CMD Auto Select only when v4_mode is true
+    - drm/amd/pm: increase mclk switch threshold to 200 us
+    - tty: make FONTX ioctl use the tty pointer they were actually passed
+    - arm64: berlin: Select DW_APB_TIMER_OF
+    - [Config] update annotations for DW_APB_TIMER
+    - cachefiles: Handle readpage error correctly
+    - hil/parisc: Disable HIL driver when it gets stuck
+    - arm: dts: mt7623: add missing pause for switchport
+    - ARM: samsung: fix PM debug build with DEBUG_LL but !MMU
+    - ARM: s3c24xx: fix missing system reset
+    - device property: Keep secondary firmware node secondary by type
+    - device property: Don't clear secondary pointer for shared primary firmware
+      node
+    - KVM: arm64: Fix AArch32 handling of DBGD{CCINT,SCRext} and DBGVCR
+    - staging: fieldbus: anybuss: jump to correct label in an error path
+    - staging: comedi: cb_pcidas: Allow 2-channel commands for AO subdevice
+    - staging: octeon: repair "fixed-link" support
+    - staging: octeon: Drop on uncorrectable alignment or FCS error
+    - Linux 5.4.75
+
+  * [HP 635] Radeon 6310 brightness control does not work (LP: #1894667) //
+    Focal update: v5.4.75 upstream stable release (LP: #1904450)
+    - ACPI: video: use ACPI backlight for HP 635 Notebook
+
+  * Focal update: v5.4.74 upstream stable release (LP: #1904445)
+    - netfilter: nftables_offload: KASAN slab-out-of-bounds Read in
+      nft_flow_rule_create
+    - socket: don't clear SOCK_TSTAMP_NEW when SO_TIMESTAMPNS is disabled
+    - objtool: Support Clang non-section symbols in ORC generation
+    - scripts/setlocalversion: make git describe output more reliable
+    - arm64: Run ARCH_WORKAROUND_1 enabling code on all CPUs
+    - arm64: Run ARCH_WORKAROUND_2 enabling code on all CPUs
+    - arm64: link with -z norelro regardless of CONFIG_RELOCATABLE
+    - x86/PCI: Fix intel_mid_pci.c build error when ACPI is not enabled
+    - bnxt_en: Check abort error state in bnxt_open_nic().
+    - bnxt_en: Send HWRM_FUNC_RESET fw command unconditionally.
+    - chelsio/chtls: fix deadlock issue
+    - chelsio/chtls: fix memory leaks in CPL handlers
+    - chelsio/chtls: fix tls record info to user
+    - cxgb4: set up filter action after rewrites
+    - gtp: fix an use-before-init in gtp_newlink()
+    - ibmvnic: fix ibmvnic_set_mac
+    - mlxsw: core: Fix memory leak on module removal
+    - netem: fix zero division in tabledist
+    - net/sched: act_mpls: Add softdep on mpls_gso.ko
+    - r8169: fix issue with forced threading in combination with shared interrupts
+    - ravb: Fix bit fields checking in ravb_hwtstamp_get()
+    - tcp: Prevent low rmem stalls with SO_RCVLOWAT.
+    - tipc: fix memory leak caused by tipc_buf_append()
+    - net: hns3: Clear the CMDQ registers before unmapping BAR region
+    - bnxt_en: Re-write PCI BARs after PCI fatal error.
+    - bnxt_en: Fix regression in workqueue cleanup logic in bnxt_remove_one().
+    - bnxt_en: Invoke cancel_delayed_work_sync() for PFs also.
+    - erofs: avoid duplicated permission check for "trusted." xattrs
+    - arch/x86/amd/ibs: Fix re-arming IBS Fetch
+    - x86/xen: disable Firmware First mode for correctable memory errors
+    - ata: ahci: mvebu: Make SATA PHY optional for Armada 3720
+    - fuse: fix page dereference after free
+    - bpf: Fix comment for helper bpf_current_task_under_cgroup()
+    - evm: Check size of security.evm before using it
+    - p54: avoid accessing the data mapped to streaming DMA
+    - cxl: Rework error message for incompatible slots
+    - RDMA/addr: Fix race with netevent_callback()/rdma_addr_cancel()
+    - mtd: lpddr: Fix bad logic in print_drs_error
+    - serial: qcom_geni_serial: To correct QUP Version detection logic
+    - serial: pl011: Fix lockdep splat when handling magic-sysrq interrupt
+    - PM: runtime: Fix timer_expires data type on 32-bit arches
+    - ata: sata_rcar: Fix DMA boundary mask
+    - xen/gntdev.c: Mark pages as dirty
+    - crypto: x86/crc32c - fix building with clang ias
+    - openrisc: Fix issue with get_user for 64-bit values
+    - misc: rtsx: do not setting OC_POWER_DOWN reg in rtsx_pci_init_ocp()
+    - phy: marvell: comphy: Convert internal SMCC firmware return codes to errno
+    - Linux 5.4.74
+
+  * Bionic: btrfs: kernel BUG at /build/linux-
+    eTBZpZ/linux-4.15.0/fs/btrfs/ctree.c:3233! (LP: #1902254)
+    - btrfs: tree-checker: fix incorrect printk format
+
+  * NULL pointer dereference when configuring multi-function with devfn != 0
+    before devfn == 0 (LP: #1903682)
+    - s390/pci: fix hot-plug of PCI function missing bus
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Thu, 10 Dec 2020 12:37:45 +0100
+
+linux (5.4.0-58.64) focal; urgency=medium
+
+  * focal/linux: 5.4.0-58.64 -proposed tracker (LP: #1907390)
+
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+
+  * raid10: discard leads to corrupted file system (LP: #1907262)
+    - Revert "dm raid: remove unnecessary discard limits for raid10"
+    - Revert "dm raid: fix discard limits for raid1 and raid10"
+    - Revert "md/raid10: improve discard request for far layout"
+    - Revert "md/raid10: improve raid10 discard request"
+    - Revert "md/raid10: pull codes that wait for blocked dev into one function"
+    - Revert "md/raid10: extend r10bio devs to raid disks"
+    - Revert "md: add md_submit_discard_bio() for submitting discard bio"
+
+ -- Khalid Elmously <khalid.elmously@canonical.com>  Wed, 09 Dec 2020 02:10:30 -0500
+
+linux (5.4.0-56.62) focal; urgency=medium
+
+  * focal/linux: 5.4.0-56.62 -proposed tracker (LP: #1905300)
+
+  * CVE-2020-4788
+    - selftests/powerpc: rfi_flush: disable entry flush if present
+    - powerpc/64s: flush L1D on kernel entry
+    - powerpc/64s: flush L1D after user accesses
+    - selftests/powerpc: entry flush test
+
+ -- Thadeu Lima de Souza Cascardo <cascardo@canonical.com>  Mon, 23 Nov 2020 15:06:56 -0300
+
+linux (5.4.0-55.61) focal; urgency=medium
+
+  * focal/linux: 5.4.0-55.61 -proposed tracker (LP: #1903175)
+
+  * Update kernel packaging to support forward porting kernels (LP: #1902957)
+    - [Debian] Update for leader included in BACKPORT_SUFFIX
+
+  * Avoid double newline when running insertchanges (LP: #1903293)
+    - [Packaging] insertchanges: avoid double newline
+
+  * EFI: Fails when BootCurrent entry does not exist (LP: #1899993)
+    - efivarfs: Replace invalid slashes with exclamation marks in dentries.
+
+  * CVE-2020-14351
+    - perf/core: Fix race in the perf_mmap_close() function
+
+  * raid10: Block discard is very slow, causing severe delays for mkfs and
+    fstrim operations (LP: #1896578)
+    - md: add md_submit_discard_bio() for submitting discard bio
+    - md/raid10: extend r10bio devs to raid disks
+    - md/raid10: pull codes that wait for blocked dev into one function
+    - md/raid10: improve raid10 discard request
+    - md/raid10: improve discard request for far layout
+    - dm raid: fix discard limits for raid1 and raid10
+    - dm raid: remove unnecessary discard limits for raid10
+
+  * Bionic: btrfs: kernel BUG at /build/linux-
+    eTBZpZ/linux-4.15.0/fs/btrfs/ctree.c:3233! (LP: #1902254)
+    - btrfs: drop unnecessary offset_in_page in extent buffer helpers
+    - btrfs: extent_io: do extra check for extent buffer read write functions
+    - btrfs: extent-tree: kill BUG_ON() in __btrfs_free_extent()
+    - btrfs: extent-tree: kill the BUG_ON() in insert_inline_extent_backref()
+    - btrfs: ctree: check key order before merging tree blocks
+
+  * Ethernet no link lights after reboot (Intel i225-v 2.5G) (LP: #1902578)
+    - igc: Add PHY power management control
+
+  * Undetected Data corruption in MPI workloads that use VSX for reductions on
+    POWER9 DD2.1 systems (LP: #1902694)
+    - powerpc: Fix undetected data corruption with P9N DD2.1 VSX CI load emulation
+    - selftests/powerpc: Make alignment handler test P9N DD2.1 vector CI load
+      workaround
+
+  * [20.04 FEAT] Support/enhancement of NVMe IPL (LP: #1902179)
+    - s390: nvme ipl
+    - s390: nvme reipl
+    - s390/ipl: support NVMe IPL kernel parameters
+
+  * uvcvideo: add mapping for HEVC payloads (LP: #1895803)
+    - media: uvcvideo: Add mapping for HEVC payloads
+
+  * Focal update: v5.4.73 upstream stable release (LP: #1902115)
+    - ibmveth: Switch order of ibmveth_helper calls.
+    - ibmveth: Identify ingress large send packets.
+    - ipv4: Restore flowi4_oif update before call to xfrm_lookup_route
+    - mlx4: handle non-napi callers to napi_poll
+    - net: fec: Fix phy_device lookup for phy_reset_after_clk_enable()
+    - net: fec: Fix PHY init after phy_reset_after_clk_enable()
+    - net: fix pos incrementment in ipv6_route_seq_next
+    - net/smc: fix valid DMBE buffer sizes
+    - net/tls: sendfile fails with ktls offload
+    - net: usb: qmi_wwan: add Cellient MPL200 card
+    - tipc: fix the skb_unshare() in tipc_buf_append()
+    - socket: fix option SO_TIMESTAMPING_NEW
+    - can: m_can_platform: don't call m_can_class_suspend in runtime suspend
+    - can: j1935: j1939_tp_tx_dat_new(): fix missing initialization of skbcnt
+    - net: j1939: j1939_session_fresh_new(): fix missing initialization of skbcnt
+    - net/ipv4: always honour route mtu during forwarding
+    - net_sched: remove a redundant goto chain check
+    - r8169: fix data corruption issue on RTL8402
+    - cxgb4: handle 4-tuple PEDIT to NAT mode translation
+    - binder: fix UAF when releasing todo list
+    - ALSA: bebob: potential info leak in hwdep_read()
+    - ALSA: hda/hdmi: fix incorrect locking in hdmi_pcm_close
+    - nvme-pci: disable the write zeros command for Intel 600P/P3100
+    - chelsio/chtls: fix socket lock
+    - chelsio/chtls: correct netdevice for vlan interface
+    - chelsio/chtls: correct function return and return type
+    - ibmvnic: save changed mac address to adapter->mac_addr
+    - net: ftgmac100: Fix Aspeed ast2600 TX hang issue
+    - net: hdlc: In hdlc_rcv, check to make sure dev is an HDLC device
+    - net: hdlc_raw_eth: Clear the IFF_TX_SKB_SHARING flag after calling
+      ether_setup
+    - net: Properly typecast int values to set sk_max_pacing_rate
+    - net/sched: act_tunnel_key: fix OOB write in case of IPv6 ERSPAN tunnels
+    - nexthop: Fix performance regression in nexthop deletion
+    - nfc: Ensure presence of NFC_ATTR_FIRMWARE_NAME attribute in
+      nfc_genl_fw_download()
+    - r8169: fix operation under forced interrupt threading
+    - selftests: forwarding: Add missing 'rp_filter' configuration
+    - tcp: fix to update snd_wl1 in bulk receiver fast path
+    - icmp: randomize the global rate limiter
+    - ALSA: hda/realtek - set mic to auto detect on a HP AIO machine
+    - ALSA: hda/realtek - Add mute Led support for HP Elitebook 845 G7
+    - ALSA: hda/realtek: Enable audio jacks of ASUS D700SA with ALC887
+    - cifs: remove bogus debug code
+    - cifs: Return the error from crypt_message when enc/dec key not found.
+    - SMB3: Resolve data corruption of TCP server info fields
+    - KVM: nVMX: Reset the segment cache when stuffing guest segs
+    - KVM: nVMX: Reload vmcs01 if getting vmcs12's pages fails
+    - KVM: x86/mmu: Commit zap of remaining invalid pages when recovering lpages
+    - KVM: SVM: Initialize prev_ga_tag before use
+    - ima: Don't ignore errors from crypto_shash_update()
+    - crypto: algif_aead - Do not set MAY_BACKLOG on the async path
+    - crypto: caam/qi - add fallback for XTS with more than 8B IV
+    - EDAC/i5100: Fix error handling order in i5100_init_one()
+    - EDAC/aspeed: Fix handling of platform_get_irq() error
+    - EDAC/ti: Fix handling of platform_get_irq() error
+    - perf/x86/intel/ds: Fix x86_pmu_stop warning for large PEBS
+    - x86/fpu: Allow multiple bits in clearcpuid= parameter
+    - drivers/perf: xgene_pmu: Fix uninitialized resource struct
+    - drivers/perf: thunderx2_pmu: Fix memory resource error handling
+    - sched/fair: Fix wrong cpu selecting from isolated domain
+    - perf/x86/intel/uncore: Update Ice Lake uncore units
+    - perf/x86/intel/uncore: Reduce the number of CBOX counters
+    - x86/nmi: Fix nmi_handle() duration miscalculation
+    - x86/events/amd/iommu: Fix sizeof mismatch
+    - crypto: algif_skcipher - EBUSY on aio should be an error
+    - crypto: mediatek - Fix wrong return value in mtk_desc_ring_alloc()
+    - crypto: ixp4xx - Fix the size used in a 'dma_free_coherent()' call
+    - crypto: picoxcell - Fix potential race condition bug
+    - media: tuner-simple: fix regression in simple_set_radio_freq
+    - media: Revert "media: exynos4-is: Add missed check for
+      pinctrl_lookup_state()"
+    - media: ov5640: Correct Bit Div register in clock tree diagram
+    - media: m5mols: Check function pointer in m5mols_sensor_power
+    - media: uvcvideo: Set media controller entity functions
+    - media: uvcvideo: Silence shift-out-of-bounds warning
+    - media: staging/intel-ipu3: css: Correctly reset some memory
+    - media: omap3isp: Fix memleak in isp_probe
+    - media: i2c: ov5640: Remain in power down for DVP mode unless streaming
+    - media: i2c: ov5640: Separate out mipi configuration from s_power
+    - media: i2c: ov5640: Enable data pins on poweron for DVP mode
+    - media: rcar_drif: Fix fwnode reference leak when parsing DT
+    - media: rcar_drif: Allocate v4l2_async_subdev dynamically
+    - media: rcar-csi2: Allocate v4l2_async_subdev dynamically
+    - crypto: omap-sham - fix digcnt register handling with export/import
+    - hwmon: (pmbus/max34440) Fix status register reads for MAX344{51,60,61}
+    - cypto: mediatek - fix leaks in mtk_desc_ring_alloc
+    - media: mx2_emmaprp: Fix memleak in emmaprp_probe
+    - media: tc358743: initialize variable
+    - media: tc358743: cleanup tc358743_cec_isr
+    - media: rcar-vin: Fix a reference count leak.
+    - media: rockchip/rga: Fix a reference count leak.
+    - media: platform: fcp: Fix a reference count leak.
+    - media: camss: Fix a reference count leak.
+    - media: s5p-mfc: Fix a reference count leak
+    - media: stm32-dcmi: Fix a reference count leak
+    - media: ti-vpe: Fix a missing check and reference count leak
+    - regulator: resolve supply after creating regulator
+    - pinctrl: bcm: fix kconfig dependency warning when !GPIOLIB
+    - spi: spi-s3c64xx: swap s3c64xx_spi_set_cs() and s3c64xx_enable_datapath()
+    - spi: spi-s3c64xx: Check return values
+    - blk-mq: move cancel of hctx->run_work to the front of blk_exit_queue
+    - ath10k: provide survey info as accumulated data
+    - drm/vkms: fix xrgb on compute crc
+    - Bluetooth: hci_uart: Cancel init work before unregistering
+    - drm/amd/display: Fix wrong return value in dm_update_plane_state()
+    - drm: panel: Fix bus format for OrtusTech COM43H4M85ULC panel
+    - ath6kl: prevent potential array overflow in ath6kl_add_new_sta()
+    - ath9k: Fix potential out of bounds in ath9k_htc_txcompletion_cb()
+    - ath10k: Fix the size used in a 'dma_free_coherent()' call in an error
+      handling path
+    - wcn36xx: Fix reported 802.11n rx_highest rate wcn3660/wcn3680
+    - ASoC: qcom: lpass-platform: fix memory leak
+    - ASoC: qcom: lpass-cpu: fix concurrency issue
+    - brcmfmac: check ndev pointer
+    - mwifiex: Do not use GFP_KERNEL in atomic context
+    - staging: rtl8192u: Do not use GFP_KERNEL in atomic context
+    - drm/gma500: fix error check
+    - scsi: qla4xxx: Fix an error handling path in 'qla4xxx_get_host_stats()'
+    - scsi: qla2xxx: Fix wrong return value in qlt_chk_unresolv_exchg()
+    - scsi: qla2xxx: Fix wrong return value in qla_nvme_register_hba()
+    - scsi: csiostor: Fix wrong return value in csio_hw_prep_fw()
+    - backlight: sky81452-backlight: Fix refcount imbalance on error
+    - staging: emxx_udc: Fix passing of NULL to dma_alloc_coherent()
+    - VMCI: check return value of get_user_pages_fast() for errors
+    - mm/error_inject: Fix allow_error_inject function signatures.
+    - drm: panel: Fix bpc for OrtusTech COM43H4M85ULC panel
+    - drm/crc-debugfs: Fix memleak in crc_control_write
+    - binder: Remove bogus warning on failed same-process transaction
+    - tty: serial: earlycon dependency
+    - pty: do tty_flip_buffer_push without port->lock in pty_write
+    - pwm: lpss: Fix off by one error in base_unit math in pwm_lpss_prepare()
+    - pwm: lpss: Add range limit check for the base_unit register value
+    - drivers/virt/fsl_hypervisor: Fix error handling path
+    - video: fbdev: vga16fb: fix setting of pixclock because a pass-by-value error
+    - video: fbdev: sis: fix null ptr dereference
+    - video: fbdev: radeon: Fix memleak in radeonfb_pci_register
+    - ASoC: fsl: imx-es8328: add missing put_device() call in imx_es8328_probe()
+    - HID: roccat: add bounds checking in kone_sysfs_write_settings()
+    - drm/msm: Avoid div-by-zero in dpu_crtc_atomic_check()
+    - drm/panfrost: Ensure GPU quirks are always initialised
+    - iomap: Clear page error before beginning a write
+    - pinctrl: mcp23s08: Fix mcp23x17_regmap initialiser
+    - pinctrl: mcp23s08: Fix mcp23x17 precious range
+    - net/mlx5: Don't call timecounter cyc2time directly from 1PPS flow
+    - scsi: mpt3sas: Fix sync irqs
+    - net: stmmac: use netif_tx_start|stop_all_queues() function
+    - cpufreq: armada-37xx: Add missing MODULE_DEVICE_TABLE
+    - drm: mxsfb: check framebuffer pitch
+    - coresight: etm4x: Handle unreachable sink in perf mode
+    - xhci: don't create endpoint debugfs entry before ring buffer is set.
+    - net: dsa: rtl8366: Check validity of passed VLANs
+    - net: dsa: rtl8366: Refactor VLAN/PVID init
+    - net: dsa: rtl8366: Skip PVID setting if not requested
+    - net: wilc1000: clean up resource in error path of init mon interface
+    - ASoC: tlv320aic32x4: Fix bdiv clock rate derivation
+    - net: dsa: rtl8366rb: Support all 4096 VLANs
+    - spi: omap2-mcspi: Improve performance waiting for CHSTAT
+    - ath6kl: wmi: prevent a shift wrapping bug in ath6kl_wmi_delete_pstream_cmd()
+    - dmaengine: dmatest: Check list for emptiness before access its last entry
+    - misc: mic: scif: Fix error handling path
+    - ALSA: seq: oss: Avoid mutex lock for a long-time ioctl
+    - usb: dwc2: Fix parameter type in function pointer prototype
+    - quota: clear padding in v2r1_mem2diskdqb()
+    - slimbus: core: check get_addr before removing laddr ida
+    - slimbus: core: do not enter to clock pause mode in core
+    - slimbus: qcom-ngd-ctrl: disable ngd in qmi server down callback
+    - ASoC: fsl_sai: Instantiate snd_soc_dai_driver
+    - HID: hid-input: fix stylus battery reporting
+    - nvmem: core: fix possibly memleak when use nvmem_cell_info_to_nvmem_cell()
+    - nl80211: fix OBSS PD min and max offset validation
+    - coresight: etm: perf: Fix warning caused by etm_setup_aux failure
+    - ibmvnic: set up 200GBPS speed
+    - qtnfmac: fix resource leaks on unsupported iftype error return path
+    - iio: adc: stm32-adc: fix runtime autosuspend delay when slow polling
+    - net: enic: Cure the enic api locking trainwreck
+    - mfd: sm501: Fix leaks in probe()
+    - iwlwifi: mvm: split a print to avoid a WARNING in ROC
+    - usb: gadget: f_ncm: fix ncm_bitrate for SuperSpeed and above.
+    - usb: gadget: u_ether: enable qmult on SuperSpeed Plus as well
+    - nl80211: fix non-split wiphy information
+    - usb: dwc2: Fix INTR OUT transfers in DDMA mode.
+    - scsi: target: tcmu: Fix warning: 'page' may be used uninitialized
+    - scsi: be2iscsi: Fix a theoretical leak in beiscsi_create_eqs()
+    - ipmi_si: Fix wrong return value in try_smi_init()
+    - platform/x86: mlx-platform: Remove PSU EEPROM configuration
+    - mwifiex: fix double free
+    - ipvs: clear skb->tstamp in forwarding path
+    - net: korina: fix kfree of rx/tx descriptor array
+    - netfilter: nf_log: missing vlan offload tag and proto
+    - mm/swapfile.c: fix potential memory leak in sys_swapon
+    - mm/memcg: fix device private memcg accounting
+    - mm, oom_adj: don't loop through tasks in __set_oom_adj when not necessary
+    - fs: fix NULL dereference due to data race in prepend_path()
+    - selftests/ftrace: Change synthetic event name for inter-event-combined test
+    - i3c: master add i3c_master_attach_boardinfo to preserve boardinfo
+    - IB/mlx4: Fix starvation in paravirt mux/demux
+    - IB/mlx4: Adjust delayed work when a dup is observed
+    - powerpc/pseries: Fix missing of_node_put() in rng_init()
+    - powerpc/icp-hv: Fix missing of_node_put() in success path
+    - RDMA/ucma: Fix locking for ctx->events_reported
+    - RDMA/ucma: Add missing locking around rdma_leave_multicast()
+    - mtd: lpddr: fix excessive stack usage with clang
+    - RDMA/hns: Add a check for current state before modifying QP
+    - RDMA/umem: Fix signature of stub ib_umem_find_best_pgsz()
+    - powerpc/pseries: explicitly reschedule during drmem_lmb list traversal
+    - pseries/drmem: don't cache node id in drmem_lmb struct
+    - RDMA/mlx5: Fix potential race between destroy and CQE poll
+    - mtd: mtdoops: Don't write panic data twice
+    - ARM: 9007/1: l2c: fix prefetch bits init in L2X0_AUX_CTRL using DT values
+    - arc: plat-hsdk: fix kconfig dependency warning when !RESET_CONTROLLER
+    - ida: Free allocated bitmap in error path
+    - xfs: limit entries returned when counting fsmap records
+    - xfs: fix deadlock and streamline xfs_getfsmap performance
+    - xfs: fix high key handling in the rt allocator's query_range function
+    - RDMA/umem: Fix ib_umem_find_best_pgsz() for mappings that cross a page
+      boundary
+    - RDMA/umem: Prevent small pages from being returned by
+      ib_umem_find_best_pgsz()
+    - RDMA/qedr: Fix qp structure memory leak
+    - RDMA/qedr: Fix use of uninitialized field
+    - RDMA/qedr: Fix return code if accept is called on a destroyed qp
+    - RDMA/qedr: Fix inline size returned for iWARP
+    - powerpc/book3s64/hash/4k: Support large linear mapping range with 4K
+    - powerpc/tau: Use appropriate temperature sample interval
+    - powerpc/tau: Convert from timer to workqueue
+    - powerpc/tau: Remove duplicated set_thresholds() call
+    - powerpc/tau: Check processor type before enabling TAU interrupt
+    - powerpc/tau: Disable TAU between measurements
+    - powerpc/64s/radix: Fix mm_cpumask trimming race vs kthread_use_mm
+    - RDMA/cma: Remove dead code for kernel rdmacm multicast
+    - RDMA/cma: Consolidate the destruction of a cma_multicast in one place
+    - perf intel-pt: Fix "context_switch event has no tid" error
+    - RDMA/hns: Set the unsupported wr opcode
+    - RDMA/mlx5: Disable IB_DEVICE_MEM_MGT_EXTENSIONS if IB_WR_REG_MR can't work
+    - i40iw: Add support to make destroy QP synchronous
+    - perf stat: Skip duration_time in setup_system_wide
+    - RDMA/hns: Fix the wrong value of rnr_retry when querying qp
+    - RDMA/hns: Fix missing sq_sig_type when querying QP
+    - mtd: rawnand: vf610: disable clk on error handling path in probe
+    - mtd: spinand: gigadevice: Only one dummy byte in QUADIO
+    - mtd: spinand: gigadevice: Add QE Bit
+    - kdb: Fix pager search for multi-line strings
+    - overflow: Include header file with SIZE_MAX declaration
+    - RDMA/ipoib: Set rtnl_link_ops for ipoib interfaces
+    - powerpc/perf: Exclude pmc5/6 from the irrelevant PMU group constraints
+    - powerpc/perf/hv-gpci: Fix starting index value
+    - i3c: master: Fix error return in cdns_i3c_master_probe()
+    - cpufreq: powernv: Fix frame-size-overflow in powernv_cpufreq_reboot_notifier
+    - IB/rdmavt: Fix sizeof mismatch
+    - RDMA/rxe: Fix skb lifetime in rxe_rcv_mcast_pkt()
+    - maiblox: mediatek: Fix handling of platform_get_irq() error
+    - selftests/powerpc: Fix eeh-basic.sh exit codes
+    - f2fs: wait for sysfs kobject removal before freeing f2fs_sb_info
+    - RDMA/rxe: Handle skb_clone() failure in rxe_recv.c
+    - mm/page_owner: change split_page_owner to take a count
+    - lib/crc32.c: fix trivial typo in preprocessor condition
+    - ramfs: fix nommu mmap with gaps in the page cache
+    - rapidio: fix error handling path
+    - rapidio: fix the missed put_device() for rio_mport_add_riodev
+    - mailbox: avoid timer start from callback
+    - i2c: rcar: Auto select RESET_CONTROLLER
+    - clk: meson: g12a: mark fclk_div2 as critical
+    - PCI: aardvark: Check for errors from pci_bridge_emul_init() call
+    - PCI: iproc: Set affinity mask on MSI interrupts
+    - rpmsg: smd: Fix a kobj leak in in qcom_smd_parse_edge()
+    - PCI/IOV: Mark VFs as not implementing PCI_COMMAND_MEMORY
+    - vfio/pci: Decouple PCI_COMMAND_MEMORY bit checks from is_virtfn
+    - clk: qcom: gcc-sdm660: Fix wrong parent_map
+    - clk: keystone: sci-clk: fix parsing assigned-clock data during probe
+    - pwm: img: Fix null pointer access in probe
+    - clk: rockchip: Initialize hw to error to avoid undefined behavior
+    - clk: mediatek: add UART0 clock support
+    - module: statically initialize init section freeing data
+    - clk: at91: clk-main: update key before writing AT91_CKGR_MOR
+    - clk: bcm2835: add missing release if devm_clk_hw_register fails
+    - watchdog: Fix memleak in watchdog_cdev_register
+    - watchdog: Use put_device on error
+    - watchdog: sp5100: Fix definition of EFCH_PM_DECODEEN3
+    - svcrdma: fix bounce buffers for unaligned offsets and multiple pages
+    - ext4: limit entries returned when counting fsmap records
+    - vfio/pci: Clear token on bypass registration failure
+    - vfio iommu type1: Fix memory leak in vfio_iommu_type1_pin_pages
+    - clk: imx8mq: Fix usdhc parents order
+    - SUNRPC: fix copying of multiple pages in gss_read_proxy_verf()
+    - Input: imx6ul_tsc - clean up some errors in imx6ul_tsc_resume()
+    - Input: stmfts - fix a & vs && typo
+    - Input: ep93xx_keypad - fix handling of platform_get_irq() error
+    - Input: omap4-keypad - fix handling of platform_get_irq() error
+    - Input: twl4030_keypad - fix handling of platform_get_irq() error
+    - Input: sun4i-ps2 - fix handling of platform_get_irq() error
+    - KVM: x86: emulating RDPID failure shall return #UD rather than #GP
+    - scsi: bfa: Fix error return in bfad_pci_init()
+    - netfilter: conntrack: connection timeout after re-register
+    - netfilter: ebtables: Fixes dropping of small packets in bridge nat
+    - netfilter: nf_fwd_netdev: clear timestamp in forwarding path
+    - arm64: dts: meson: vim3: correct led polarity
+    - ARM: dts: imx6sl: fix rng node
+    - ARM: at91: pm: of_node_put() after its usage
+    - ARM: s3c24xx: fix mmc gpio lookup tables
+    - ARM: dts: sun8i: r40: bananapi-m2-ultra: Fix dcdc1 regulator
+    - arm64: dts: allwinner: h5: remove Mali GPU PMU module
+    - memory: omap-gpmc: Fix a couple off by ones
+    - memory: omap-gpmc: Fix build error without CONFIG_OF
+    - memory: fsl-corenet-cf: Fix handling of platform_get_irq() error
+    - arm64: dts: imx8mq: Add missing interrupts to GPC
+    - arm64: dts: qcom: msm8916: Remove one more thermal trip point unit name
+    - arm64: dts: qcom: pm8916: Remove invalid reg size from wcd_codec
+    - arm64: dts: qcom: msm8916: Fix MDP/DSI interrupts
+    - arm64: dts: renesas: r8a77990: Fix MSIOF1 DMA channels
+    - arm64: dts: renesas: r8a774c0: Fix MSIOF1 DMA channels
+    - arm64: dts: actions: limit address range for pinctrl node
+    - ARM: dts: owl-s500: Fix incorrect PPI interrupt specifiers
+    - soc: fsl: qbman: Fix return value on success
+    - ARM: OMAP2+: Restore MPU power domain if cpu_cluster_pm_enter() fails
+    - arm64: dts: zynqmp: Remove additional compatible string for i2c IPs
+    - ARM: dts: meson8: remove two invalid interrupt lines from the GPU node
+    - lightnvm: fix out-of-bounds write to array devices->info[]
+    - powerpc/powernv/dump: Fix race while processing OPAL dump
+    - powerpc/pseries: Avoid using addr_to_pfn in real mode
+    - nvmet: fix uninitialized work for zero kato
+    - NTB: hw: amd: fix an issue about leak system resources
+    - sched/features: Fix !CONFIG_JUMP_LABEL case
+    - perf: correct SNOOPX field offset
+    - i2c: core: Restore acpi_walk_dep_device_list() getting called after
+      registering the ACPI i2c devs
+    - md/bitmap: fix memory leak of temporary bitmap
+    - block: ratelimit handle_bad_sector() message
+    - crypto: ccp - fix error handling
+    - x86/asm: Replace __force_order with a memory clobber
+    - x86/mce: Add Skylake quirk for patrol scrub reported errors
+    - media: firewire: fix memory leak
+    - media: ati_remote: sanity check for both endpoints
+    - media: st-delta: Fix reference count leak in delta_run_work
+    - media: sti: Fix reference count leaks
+    - media: exynos4-is: Fix several reference count leaks due to
+      pm_runtime_get_sync
+    - media: exynos4-is: Fix a reference count leak due to pm_runtime_get_sync
+    - media: exynos4-is: Fix a reference count leak
+    - media: vsp1: Fix runtime PM imbalance on error
+    - media: platform: s3c-camif: Fix runtime PM imbalance on error
+    - media: platform: sti: hva: Fix runtime PM imbalance on error
+    - media: bdisp: Fix runtime PM imbalance on error
+    - media: media/pci: prevent memory leak in bttv_probe
+    - x86/mce: Make mce_rdmsrl() panic on an inaccessible MSR
+    - media: uvcvideo: Ensure all probed info is returned to v4l2
+    - mmc: sdio: Check for CISTPL_VERS_1 buffer size
+    - media: saa7134: avoid a shift overflow
+    - media: venus: fixes for list corruption
+    - fs: dlm: fix configfs memory leak
+    - media: venus: core: Fix runtime PM imbalance in venus_probe
+    - ntfs: add check for mft record size in superblock
+    - ip_gre: set dev->hard_header_len and dev->needed_headroom properly
+    - mac80211: handle lack of sband->bitrates in rates
+    - PM: hibernate: remove the bogus call to get_gendisk() in software_resume()
+    - scsi: mvumi: Fix error return in mvumi_io_attach()
+    - scsi: target: core: Add CONTROL field for trace events
+    - mic: vop: copy data to kernel space then write to io memory
+    - misc: vop: add round_up(x,4) for vring_size to avoid kernel panic
+    - usb: dwc3: Add splitdisable quirk for Hisilicon Kirin Soc
+    - usb: gadget: function: printer: fix use-after-free in __lock_acquire
+    - udf: Limit sparing table size
+    - udf: Avoid accessing uninitialized data on failed inode read
+    - rtw88: increse the size of rx buffer size
+    - USB: cdc-acm: handle broken union descriptors
+    - usb: dwc3: simple: add support for Hikey 970
+    - can: flexcan: flexcan_chip_stop(): add error handling and propagate error
+      value
+    - ath9k: hif_usb: fix race condition between usb_get_urb() and
+      usb_kill_anchored_urbs()
+    - drm/panfrost: add amlogic reset quirk callback
+    - bpf: Limit caller's stack depth 256 for subprogs with tailcalls
+    - misc: rtsx: Fix memory leak in rtsx_pci_probe
+    - reiserfs: only call unlock_new_inode() if I_NEW
+    - opp: Prevent memory leak in dev_pm_opp_attach_genpd()
+    - xfs: make sure the rt allocator doesn't run off the end
+    - usb: ohci: Default to per-port over-current protection
+    - Bluetooth: Only mark socket zapped after unlocking
+    - drm/msm/a6xx: fix a potential overflow issue
+    - iomap: fix WARN_ON_ONCE() from unprivileged users
+    - scsi: ibmvfc: Fix error return in ibmvfc_probe()
+    - scsi: qla2xxx: Warn if done() or free() are called on an already freed srb
+    - selftests/bpf: Fix test_sysctl_loop{1, 2} failure due to clang change
+    - brcmsmac: fix memory leak in wlc_phy_attach_lcnphy
+    - rtl8xxxu: prevent potential memory leak
+    - Fix use after free in get_capset_info callback.
+    - HID: ite: Add USB id match for Acer One S1003 keyboard dock
+    - scsi: qedf: Return SUCCESS if stale rport is encountered
+    - scsi: qedi: Protect active command list to avoid list corruption
+    - scsi: qedi: Fix list_del corruption while removing active I/O
+    - fbmem: add margin check to fb_check_caps()
+    - tty: ipwireless: fix error handling
+    - Bluetooth: btusb: Fix memleak in btusb_mtk_submit_wmt_recv_urb
+    - ipvs: Fix uninit-value in do_ip_vs_set_ctl()
+    - reiserfs: Fix memory leak in reiserfs_parse_options()
+    - mwifiex: don't call del_timer_sync() on uninitialized timer
+    - ALSA: hda/ca0132 - Add AE-7 microphone selection commands.
+    - ALSA: hda/ca0132 - Add new quirk ID for SoundBlaster AE-7.
+    - scsi: smartpqi: Avoid crashing kernel for controller issues
+    - brcm80211: fix possible memleak in brcmf_proto_msgbuf_attach
+    - usb: core: Solve race condition in anchor cleanup functions
+    - scsi: ufs: ufs-qcom: Fix race conditions caused by ufs_qcom_testbus_config()
+    - dmaengine: dw: Add DMA-channels mask cell support
+    - dmaengine: dw: Activate FIFO-mode for memory peripherals only
+    - ath10k: check idx validity in __ath10k_htt_rx_ring_fill_n()
+    - net: korina: cast KSEG0 address to pointer in kfree
+    - s390/qeth: don't let HW override the configured port role
+    - tty: serial: lpuart: fix lpuart32_write usage
+    - tty: serial: fsl_lpuart: fix lpuart32_poll_get_char
+    - usb: cdc-acm: add quirk to blacklist ETAS ES58X devices
+    - USB: cdc-wdm: Make wdm_flush() interruptible and add wdm_fsync().
+    - usb: cdns3: gadget: free interrupt after gadget has deleted
+    - eeprom: at25: set minimum read/write access stride to 1
+    - usb: gadget: f_ncm: allow using NCM in SuperSpeed Plus gadgets.
+    - Linux 5.4.73
+
+  * Focal update: v5.4.72 upstream stable release (LP: #1902111)
+    - perf cs-etm: Move definition of 'traceid_list' global variable from header
+      file
+    - btrfs: don't pass system_chunk into can_overcommit
+    - btrfs: take overcommit into account in inc_block_group_ro
+    - ARM: 8939/1: kbuild: use correct nm executable
+    - ACPI: Always build evged in
+    - Bluetooth: Consolidate encryption handling in hci_encrypt_cfm
+    - Bluetooth: Fix update of connection state in `hci_encrypt_cfm`
+    - Bluetooth: Disconnect if E0 is used for Level 4
+    - media: usbtv: Fix refcounting mixup
+    - USB: serial: option: add Cellient MPL200 card
+    - USB: serial: option: Add Telit FT980-KS composition
+    - staging: comedi: check validity of wMaxPacketSize of usb endpoints found
+    - USB: serial: pl2303: add device-id for HP GC device
+    - USB: serial: ftdi_sio: add support for FreeCalypso JTAG+UART adapters
+    - reiserfs: Initialize inode keys properly
+    - reiserfs: Fix oops during mount
+    - xen/events: don't use chip_data for legacy IRQs
+    - crypto: bcm - Verify GCM/CCM key length in setkey
+    - crypto: qat - check cipher length for aead AES-CBC-HMAC-SHA
+    - Linux 5.4.72
+
+  * Focal update: v5.4.71 upstream stable release (LP: #1902110)
+    - fbdev, newport_con: Move FONT_EXTRA_WORDS macros into linux/font.h
+    - Fonts: Support FONT_EXTRA_WORDS macros for built-in fonts
+    - fbcon: Fix global-out-of-bounds read in fbcon_get_font()
+    - Revert "ravb: Fixed to be able to unload modules"
+    - io_uring: Fix resource leaking when kill the process
+    - io_uring: Fix missing smp_mb() in io_cancel_async_work()
+    - io_uring: Fix remove irrelevant req from the task_list
+    - io_uring: Fix double list add in io_queue_async_work()
+    - net: wireless: nl80211: fix out-of-bounds access in nl80211_del_key()
+    - drm/nouveau/mem: guard against NULL pointer access in mem_del
+    - vhost: Don't call access_ok() when using IOTLB
+    - vhost: Use vhost_get_used_size() in vhost_vring_set_addr()
+    - usermodehelper: reset umask to default before executing user process
+    - Platform: OLPC: Fix memleak in olpc_ec_probe
+    - platform/x86: intel-vbtn: Fix SW_TABLET_MODE always reporting 1 on the HP
+      Pavilion 11 x360
+    - platform/x86: thinkpad_acpi: initialize tp_nvram_state variable
+    - bpf: Fix sysfs export of empty BTF section
+    - bpf: Prevent .BTF section elimination
+    - platform/x86: intel-vbtn: Switch to an allow-list for SW_TABLET_MODE
+      reporting
+    - platform/x86: thinkpad_acpi: re-initialize ACPI buffer size when reuse
+    - driver core: Fix probe_count imbalance in really_probe()
+    - perf test session topology: Fix data path
+    - perf top: Fix stdio interface input handling with glibc 2.28+
+    - i2c: i801: Exclude device from suspend direct complete optimization
+    - arm64: dts: stratix10: add status to qspi dts node
+    - Btrfs: send, allow clone operations within the same file
+    - Btrfs: send, fix emission of invalid clone operations within the same file
+    - btrfs: volumes: Use more straightforward way to calculate map length
+    - btrfs: Ensure we trim ranges across block group boundary
+    - btrfs: fix RWF_NOWAIT write not failling when we need to cow
+    - btrfs: allow btrfs_truncate_block() to fallback to nocow for data space
+      reservation
+    - nvme-core: put ctrl ref when module ref get fail
+    - macsec: avoid use-after-free in macsec_handle_frame()
+    - mm/khugepaged: fix filemap page_to_pgoff(page) != offset
+    - net: introduce helper sendpage_ok() in include/linux/net.h
+    - tcp: use sendpage_ok() to detect misused .sendpage
+    - nvme-tcp: check page by sendpage_ok() before calling kernel_sendpage()
+    - xfrmi: drop ignore_df check before updating pmtu
+    - cifs: Fix incomplete memory allocation on setxattr path
+    - i2c: meson: fix clock setting overwrite
+    - i2c: meson: fixup rate calculation with filter delay
+    - i2c: owl: Clear NACK and BUS error bits
+    - sctp: fix sctp_auth_init_hmacs() error path
+    - team: set dev->needed_headroom in team_setup_by_port()
+    - net: team: fix memory leak in __team_options_register
+    - openvswitch: handle DNAT tuple collision
+    - drm/amdgpu: prevent double kfree ttm->sg
+    - iommu/vt-d: Fix lockdep splat in iommu_flush_dev_iotlb()
+    - xfrm: clone XFRMA_SET_MARK in xfrm_do_migrate
+    - xfrm: clone XFRMA_REPLAY_ESN_VAL in xfrm_do_migrate
+    - xfrm: clone XFRMA_SEC_CTX in xfrm_do_migrate
+    - xfrm: clone whole liftime_cur structure in xfrm_do_migrate
+    - net: stmmac: removed enabling eee in EEE set callback
+    - platform/x86: fix kconfig dependency warning for FUJITSU_LAPTOP
+    - xfrm: Use correct address family in xfrm_state_find
+    - iavf: use generic power management
+    - iavf: Fix incorrect adapter get in iavf_resume
+    - net: ethernet: cavium: octeon_mgmt: use phy_start and phy_stop
+    - bonding: set dev->needed_headroom in bond_setup_by_slave()
+    - mdio: fix mdio-thunder.c dependency & build error
+    - mlxsw: spectrum_acl: Fix mlxsw_sp_acl_tcam_group_add()'s error path
+    - r8169: fix RTL8168f/RTL8411 EPHY config
+    - net: usb: ax88179_178a: fix missing stop entry in driver_info
+    - virtio-net: don't disable guest csum when disable LRO
+    - net/mlx5: Avoid possible free of command entry while timeout comp handler
+    - net/mlx5: Fix request_irqs error flow
+    - net/mlx5e: Add resiliency in Striding RQ mode for packets larger than MTU
+    - net/mlx5e: Fix VLAN cleanup flow
+    - net/mlx5e: Fix VLAN create flow
+    - rxrpc: Fix rxkad token xdr encoding
+    - rxrpc: Downgrade the BUG() for unsupported token type in rxrpc_read()
+    - rxrpc: Fix some missing _bh annotations on locking conn->state_lock
+    - rxrpc: The server keyring isn't network-namespaced
+    - rxrpc: Fix server keyring leak
+    - perf: Fix task_function_call() error handling
+    - mmc: core: don't set limits.discard_granularity as 0
+    - mm: khugepaged: recalculate min_free_kbytes after memory hotplug as expected
+      by khugepaged
+    - tcp: fix receive window update in tcp_add_backlog()
+    - net/core: check length before updating Ethertype in skb_mpls_{push,pop}
+    - net/tls: race causes kernel panic
+    - net/mlx5e: Fix driver's declaration to support GRE offload
+    - Input: ati_remote2 - add missing newlines when printing module parameters
+    - net: usb: rtl8150: set random MAC address when set_ethernet_addr() fails
+    - net_sched: defer tcf_idr_insert() in tcf_action_init_1()
+    - net_sched: commit action insertions together
+    - Linux 5.4.71
+
+  * kci_test_encap_fou() in rtnetlink.sh from kselftests/net failed with "FAIL:
+    can't add fou port 7777, skipping test" (LP: #1891421)
+    - selftests: rtnetlink: load fou module for kci_test_encap_fou() test
+
+  * alsa/hda/realtek - The front Mic on a HP machine doesn't work (LP: #1899508)
+    - ALSA: hda/realtek - The front Mic on a HP machine doesn't work
+
+  * Enable brightness control on HP DreamColor panel (LP: #1898865)
+    - drm/i915/dpcd_bl: Unbreak enable_dpcd_backlight modparam
+    - SAUCE: drm/i915/dpcd_bl: Skip testing control capability with force DPCD
+      quirk
+    - SAUCE: drm/dp: HP DreamColor panel brigntness fix
+
+  * Fix non-working Intel NVMe after S3 (LP: #1900847)
+    - SAUCE: PCI: Enable ACS quirk on all CML root ports
+
+  * bcache: Issues with large IO wait in bch_mca_scan() when shrinker is enabled
+    (LP: #1898786)
+    - bcache: remove member accessed from struct btree
+    - bcache: reap c->btree_cache_freeable from the tail in bch_mca_scan()
+    - bcache: reap from tail of c->btree_cache in bch_mca_scan()
+
+  * Improve descriptions for XFAIL cases in kselftests/net/psock_snd
+    (LP: #1900088)
+    - selftests/net: improve descriptions for XFAIL cases in psock_snd.sh
+
+  * ceph: fix inode number handling on arches with 32-bit ino_t (LP: #1899582)
+    - ceph: fix inode number handling on arches with 32-bit ino_t
+
+  * Fix system reboot when disconnecting WiFi (LP: #1899726)
+    - iwlwifi: msix: limit max RX queues for 9000 family
+
+  * Fix broken MSI interrupt after HDA controller was suspended (LP: #1899586)
+    - ALSA: hda: fix jack detection with Realtek codecs when in D3
+
+  * Focal update: v5.4.70 upstream stable release (LP: #1900632)
+    - btrfs: fix filesystem corruption after a device replace
+    - mmc: sdhci: Workaround broken command queuing on Intel GLK based IRBIS
+      models
+    - USB: gadget: f_ncm: Fix NDP16 datagram validation
+    - gpio: siox: explicitly support only threaded irqs
+    - gpio: mockup: fix resource leak in error path
+    - gpio: tc35894: fix up tc35894 interrupt configuration
+    - clk: socfpga: stratix10: fix the divider for the emac_ptp_free_clk
+    - vsock/virtio: add transport parameter to the
+      virtio_transport_reset_no_sock()
+    - net: virtio_vsock: Enhance connection semantics
+    - xfs: trim IO to found COW extent limit
+    - Input: i8042 - add nopnp quirk for Acer Aspire 5 A515
+    - iio: adc: qcom-spmi-adc5: fix driver name
+    - ftrace: Move RCU is watching check after recursion check
+    - memstick: Skip allocating card when removing host
+    - drm/amdgpu: restore proper ref count in amdgpu_display_crtc_set_config
+    - clocksource/drivers/timer-gx6605s: Fixup counter reload
+    - libbpf: Remove arch-specific include path in Makefile
+    - drivers/net/wan/hdlc_fr: Add needed_headroom for PVC devices
+    - drm/sun4i: mixer: Extend regmap max_register
+    - net: dec: de2104x: Increase receive ring size for Tulip
+    - rndis_host: increase sleep time in the query-response loop
+    - nvme-core: get/put ctrl and transport module in nvme_dev_open/release()
+    - fuse: fix the ->direct_IO() treatment of iov_iter
+    - drivers/net/wan/lapbether: Make skb->protocol consistent with the header
+    - drivers/net/wan/hdlc: Set skb->protocol before transmitting
+    - mac80211: Fix radiotap header channel flag for 6GHz band
+    - mac80211: do not allow bigger VHT MPDUs than the hardware supports
+    - tracing: Make the space reserved for the pid wider
+    - tools/io_uring: fix compile breakage
+    - spi: fsl-espi: Only process interrupts for expected events
+    - nvme-pci: fix NULL req in completion handler
+    - nvme-fc: fail new connections to a deleted host or remote port
+    - gpio: sprd: Clear interrupt when setting the type as edge
+    - phy: ti: am654: Fix a leak in serdes_am654_probe()
+    - pinctrl: mvebu: Fix i2c sda definition for 98DX3236
+    - nfs: Fix security label length not being reset
+    - clk: tegra: Always program PLL_E when enabled
+    - clk: samsung: exynos4: mark 'chipid' clock as CLK_IGNORE_UNUSED
+    - iommu/exynos: add missing put_device() call in exynos_iommu_of_xlate()
+    - gpio/aspeed-sgpio: enable access to all 80 input & output sgpios
+    - gpio/aspeed-sgpio: don't enable all interrupts by default
+    - gpio: aspeed: fix ast2600 bank properties
+    - i2c: cpm: Fix i2c_ram structure
+    - Input: trackpoint - enable Synaptics trackpoints
+    - scripts/dtc: only append to HOST_EXTRACFLAGS instead of overwriting
+    - random32: Restore __latent_entropy attribute on net_rand_state
+    - block/diskstats: more accurate approximation of io_ticks for slow disks
+    - mm: replace memmap_context by meminit_context
+    - mm: don't rely on system state to detect hot-plug operations
+    - nvme: Cleanup and rename nvme_block_nr()
+    - nvme: Introduce nvme_lba_to_sect()
+    - nvme: consolidate chunk_sectors settings
+    - epoll: do not insert into poll queues until all sanity checks are done
+    - epoll: replace ->visited/visited_list with generation count
+    - epoll: EPOLL_CTL_ADD: close the race in decision to take fast path
+    - ep_create_wakeup_source(): dentry name can change under you...
+    - netfilter: ctnetlink: add a range check for l3/l4 protonum
+    - Linux 5.4.70
+
+  * Focal update: v5.4.69 upstream stable release (LP: #1900624)
+    - kernel/sysctl-test: Add null pointer test for sysctl.c:proc_dointvec()
+    - selinux: allow labeling before policy is loaded
+    - media: mc-device.c: fix memleak in media_device_register_entity
+    - drm/amd/display: Do not double-buffer DTO adjustments
+    - drm/amdkfd: Fix race in gfx10 context restore handler
+    - dma-fence: Serialise signal enabling (dma_fence_enable_sw_signaling)
+    - scsi: qla2xxx: Add error handling for PLOGI ELS passthrough
+    - ath10k: fix array out-of-bounds access
+    - ath10k: fix memory leak for tpc_stats_final
+    - PCI/IOV: Serialize sysfs sriov_numvfs reads vs writes
+    - mm: fix double page fault on arm64 if PTE_AF is cleared
+    - scsi: aacraid: fix illegal IO beyond last LBA
+    - m68k: q40: Fix info-leak in rtc_ioctl
+    - xfs: fix inode fork extent count overflow
+    - gma/gma500: fix a memory disclosure bug due to uninitialized bytes
+    - ASoC: kirkwood: fix IRQ error handling
+    - soundwire: intel/cadence: fix startup sequence
+    - media: smiapp: Fix error handling at NVM reading
+    - drm/amd/display: Free gamma after calculating legacy transfer function
+    - xfs: properly serialise fallocate against AIO+DIO
+    - leds: mlxreg: Fix possible buffer overflow
+    - dm table: do not allow request-based DM to stack on partitions
+    - PM / devfreq: tegra30: Fix integer overflow on CPU's freq max out
+    - scsi: fnic: fix use after free
+    - powerpc/64s: Always disable branch profiling for prom_init.o
+    - net: silence data-races on sk_backlog.tail
+    - dax: Fix alloc_dax_region() compile warning
+    - iomap: Fix overflow in iomap_page_mkwrite
+    - f2fs: avoid kernel panic on corruption test
+    - clk/ti/adpll: allocate room for terminating null
+    - drm/amdgpu/powerplay: fix AVFS handling with custom powerplay table
+    - ice: Fix to change Rx/Tx ring descriptor size via ethtool with DCBx
+    - mtd: cfi_cmdset_0002: don't free cfi->cfiq in error path of
+      cfi_amdstd_setup()
+    - mfd: mfd-core: Protect against NULL call-back function pointer
+    - drm/amdgpu/powerplay/smu7: fix AVFS handling with custom powerplay table
+    - tpm_crb: fix fTPM on AMD Zen+ CPUs
+    - tracing: Verify if trace array exists before destroying it.
+    - tracing: Adding NULL checks for trace_array descriptor pointer
+    - bcache: fix a lost wake-up problem caused by mca_cannibalize_lock
+    - dmaengine: mediatek: hsdma_probe: fixed a memory leak when devm_request_irq
+      fails
+    - x86/kdump: Always reserve the low 1M when the crashkernel option is
+      specified
+    - RDMA/qedr: Fix potential use after free
+    - RDMA/i40iw: Fix potential use after free
+    - PCI: Avoid double hpmemsize MMIO window assignment
+    - fix dget_parent() fastpath race
+    - xfs: fix attr leaf header freemap.size underflow
+    - RDMA/iw_cgxb4: Fix an error handling path in 'c4iw_connect()'
+    - ubi: Fix producing anchor PEBs
+    - mmc: core: Fix size overflow for mmc partitions
+    - gfs2: clean up iopen glock mess in gfs2_create_inode
+    - scsi: pm80xx: Cleanup command when a reset times out
+    - mt76: do not use devm API for led classdev
+    - mt76: add missing locking around ampdu action
+    - debugfs: Fix !DEBUG_FS debugfs_create_automount
+    - SUNRPC: Capture completion of all RPC tasks
+    - CIFS: Use common error handling code in smb2_ioctl_query_info()
+    - CIFS: Properly process SMB3 lease breaks
+    - f2fs: stop GC when the victim becomes fully valid
+    - ASoC: max98090: remove msleep in PLL unlocked workaround
+    - xtensa: fix system_call interaction with ptrace
+    - s390: avoid misusing CALL_ON_STACK for task stack setup
+    - xfs: fix realtime file data space leak
+    - drm/amdgpu: fix calltrace during kmd unload(v3)
+    - arm64: insn: consistently handle exit text
+    - selftests/bpf: De-flake test_tcpbpf
+    - kernel/notifier.c: intercept duplicate registrations to avoid infinite loops
+    - kernel/sys.c: avoid copying possible padding bytes in copy_to_user
+    - KVM: arm/arm64: vgic: Fix potential double free dist->spis in
+      __kvm_vgic_destroy()
+    - module: Remove accidental change of module_enable_x()
+    - xfs: fix log reservation overflows when allocating large rt extents
+    - ALSA: hda: enable regmap internal locking
+    - tipc: fix link overflow issue at socket shutdown
+    - vcc_seq_next should increase position index
+    - neigh_stat_seq_next() should increase position index
+    - rt_cpu_seq_next should increase position index
+    - ipv6_route_seq_next should increase position index
+    - drm/mcde: Handle pending vblank while disabling display
+    - seqlock: Require WRITE_ONCE surrounding raw_seqcount_barrier
+    - drm/scheduler: Avoid accessing freed bad job.
+    - media: ti-vpe: cal: Restrict DMA to avoid memory corruption
+    - opp: Replace list_kref with a local counter
+    - scsi: qla2xxx: Fix stuck session in GNL
+    - sctp: move trace_sctp_probe_path into sctp_outq_sack
+    - ACPI: EC: Reference count query handlers under lock
+    - scsi: ufs: Make ufshcd_add_command_trace() easier to read
+    - scsi: ufs: Fix a race condition in the tracing code
+    - drm/amd/display: Initialize DSC PPS variables to 0
+    - i2c: tegra: Prevent interrupt triggering after transfer timeout
+    - btrfs: tree-checker: Check leaf chunk item size
+    - dmaengine: zynqmp_dma: fix burst length configuration
+    - s390/cpum_sf: Use kzalloc and minor changes
+    - nfsd: Fix a soft lockup race in nfsd_file_mark_find_or_create()
+    - powerpc/eeh: Only dump stack once if an MMIO loop is detected
+    - Bluetooth: btrtl: Use kvmalloc for FW allocations
+    - tracing: Set kernel_stack's caller size properly
+    - ARM: 8948/1: Prevent OOB access in stacktrace
+    - ar5523: Add USB ID of SMCWUSBT-G2 wireless adapter
+    - ceph: ensure we have a new cap before continuing in fill_inode
+    - selftests/ftrace: fix glob selftest
+    - tools/power/x86/intel_pstate_tracer: changes for python 3 compatibility
+    - Bluetooth: Fix refcount use-after-free issue
+    - mm/swapfile.c: swap_next should increase position index
+    - mm: pagewalk: fix termination condition in walk_pte_range()
+    - Bluetooth: prefetch channel before killing sock
+    - ALSA: hda: Clear RIRB status before reading WP
+    - skbuff: fix a data race in skb_queue_len()
+    - nfsd: Fix a perf warning
+    - drm/amd/display: fix workaround for incorrect double buffer register for DLG
+      ADL and TTU
+    - audit: CONFIG_CHANGE don't log internal bookkeeping as an event
+    - selinux: sel_avc_get_stat_idx should increase position index
+    - drm/omap: fix possible object reference leak
+    - locking/lockdep: Decrement IRQ context counters when removing lock chain
+    - clk: stratix10: use do_div() for 64-bit calculation
+    - crypto: chelsio - This fixes the kernel panic which occurs during a libkcapi
+      test
+    - mt76: clear skb pointers from rx aggregation reorder buffer during cleanup
+    - mt76: fix handling full tx queues in mt76_dma_tx_queue_skb_raw
+    - ALSA: usb-audio: Don't create a mixer element with bogus volume range
+    - perf test: Fix test trace+probe_vfs_getname.sh on s390
+    - RDMA/rxe: Fix configuration of atomic queue pair attributes
+    - KVM: x86: fix incorrect comparison in trace event
+    - KVM: nVMX: Hold KVM's srcu lock when syncing vmcs12->shadow
+    - dmaengine: stm32-mdma: use vchan_terminate_vdesc() in .terminate_all
+    - media: staging/imx: Missing assignment in
+      imx_media_capture_device_register()
+    - x86/pkeys: Add check for pkey "overflow"
+    - bpf: Remove recursion prevention from rcu free callback
+    - dmaengine: stm32-dma: use vchan_terminate_vdesc() in .terminate_all
+    - dmaengine: tegra-apb: Prevent race conditions on channel's freeing
+    - soundwire: bus: disable pm_runtime in sdw_slave_delete
+    - drm/amd/display: dal_ddc_i2c_payloads_create can fail causing panic
+    - drm/omap: dss: Cleanup DSS ports on initialisation failure
+    - iavf: use tc_cls_can_offload_and_chain0() instead of chain check
+    - firmware: arm_sdei: Use cpus_read_lock() to avoid races with cpuhp
+    - random: fix data races at timer_rand_state
+    - bus: hisi_lpc: Fixup IO ports addresses to avoid use-after-free in host
+      removal
+    - ASoC: SOF: ipc: check ipc return value before data copy
+    - media: go7007: Fix URB type for interrupt handling
+    - Bluetooth: guard against controllers sending zero'd events
+    - timekeeping: Prevent 32bit truncation in scale64_check_overflow()
+    - powerpc/book3s64: Fix error handling in mm_iommu_do_alloc()
+    - drm/amd/display: fix image corruption with ODM 2:1 DSC 2 slice
+    - ext4: fix a data race at inode->i_disksize
+    - perf jevents: Fix leak of mapfile memory
+    - mm: avoid data corruption on CoW fault into PFN-mapped VMA
+    - drm/amdgpu: increase atombios cmd timeout
+    - ARM: OMAP2+: Handle errors for cpu_pm
+    - clk: imx: Fix division by zero warning on pfdv2
+    - cpu-topology: Fix the potential data corruption
+    - s390/irq: replace setup_irq() by request_irq()
+    - perf cs-etm: Swap packets for instruction samples
+    - perf cs-etm: Correct synthesizing instruction samples
+    - ath10k: use kzalloc to read for ath10k_sdio_hif_diag_read
+    - scsi: aacraid: Disabling TM path and only processing IOP reset
+    - Bluetooth: L2CAP: handle l2cap config request during open state
+    - media: tda10071: fix unsigned sign extension overflow
+    - tty: sifive: Finish transmission before changing the clock
+    - xfs: don't ever return a stale pointer from __xfs_dir3_free_read
+    - xfs: mark dir corrupt when lookup-by-hash fails
+    - ext4: mark block bitmap corrupted when found instead of BUGON
+    - tpm: ibmvtpm: Wait for buffer to be set before proceeding
+    - rtc: sa1100: fix possible race condition
+    - rtc: ds1374: fix possible race condition
+    - nfsd: Don't add locks to closed or closing open stateids
+    - RDMA/cm: Remove a race freeing timewait_info
+    - intel_th: Disallow multi mode on devices where it's broken
+    - KVM: PPC: Book3S HV: Treat TM-related invalid form instructions on P9 like
+      the valid ones
+    - drm/msm: fix leaks if initialization fails
+    - drm/msm/a5xx: Always set an OPP supported hardware value
+    - tracing: Use address-of operator on section symbols
+    - thermal: rcar_thermal: Handle probe error gracefully
+    - KVM: LAPIC: Mark hrtimer for period or oneshot mode to expire in hard
+      interrupt context
+    - perf parse-events: Fix 3 use after frees found with clang ASAN
+    - btrfs: do not init a reloc root if we aren't relocating
+    - btrfs: free the reloc_control in a consistent way
+    - r8169: improve RTL8168b FIFO overflow workaround
+    - serial: 8250_port: Don't service RX FIFO if throttled
+    - serial: 8250_omap: Fix sleeping function called from invalid context during
+      probe
+    - serial: 8250: 8250_omap: Terminate DMA before pushing data on RX timeout
+    - perf cpumap: Fix snprintf overflow check
+    - net: axienet: Convert DMA error handler to a work queue
+    - net: axienet: Propagate failure of DMA descriptor setup
+    - cpufreq: powernv: Fix frame-size-overflow in powernv_cpufreq_work_fn
+    - tools: gpio-hammer: Avoid potential overflow in main
+    - exec: Add exec_update_mutex to replace cred_guard_mutex
+    - exec: Fix a deadlock in strace
+    - selftests/ptrace: add test cases for dead-locks
+    - kernel/kcmp.c: Use new infrastructure to fix deadlocks in execve
+    - proc: Use new infrastructure to fix deadlocks in execve
+    - proc: io_accounting: Use new infrastructure to fix deadlocks in execve
+    - perf: Use new infrastructure to fix deadlocks in execve
+    - nvme-multipath: do not reset on unknown status
+    - nvme: Fix ctrl use-after-free during sysfs deletion
+    - nvme: Fix controller creation races with teardown flow
+    - brcmfmac: Fix double freeing in the fmac usb data path
+    - xfs: prohibit fs freezing when using empty transactions
+    - RDMA/rxe: Set sys_image_guid to be aligned with HW IB devices
+    - IB/iser: Always check sig MR before putting it to the free pool
+    - scsi: hpsa: correct race condition in offload enabled
+    - SUNRPC: Fix a potential buffer overflow in 'svc_print_xprts()'
+    - svcrdma: Fix leak of transport addresses
+    - netfilter: nf_tables: silence a RCU-list warning in nft_table_lookup()
+    - PCI: Use ioremap(), not phys_to_virt() for platform ROM
+    - ubifs: ubifs_jnl_write_inode: Fix a memory leak bug
+    - ubifs: ubifs_add_orphan: Fix a memory leak bug
+    - ubifs: Fix out-of-bounds memory access caused by abnormal value of node_len
+    - ALSA: usb-audio: Fix case when USB MIDI interface has more than one extra
+      endpoint descriptor
+    - PCI: pciehp: Fix MSI interrupt race
+    - NFS: Fix races nfs_page_group_destroy() vs
+      nfs_destroy_unlinked_subrequests()
+    - drm/amdgpu/vcn2.0: stall DPG when WPTR/RPTR reset
+    - powerpc/perf: Implement a global lock to avoid races between trace, core and
+      thread imc events.
+    - mm/kmemleak.c: use address-of operator on section symbols
+    - mm/filemap.c: clear page error before actual read
+    - mm/swapfile: fix data races in try_to_unuse()
+    - mm/vmscan.c: fix data races using kswapd_classzone_idx
+    - SUNRPC: Don't start a timer on an already queued rpc task
+    - nvmet-rdma: fix double free of rdma queue
+    - workqueue: Remove the warning in wq_worker_sleeping()
+    - drm/amdgpu/sriov add amdgpu_amdkfd_pre_reset in gpu reset
+    - mm/mmap.c: initialize align_offset explicitly for vm_unmapped_area
+    - ALSA: hda: Skip controller resume if not needed
+    - scsi: qedi: Fix termination timeouts in session logout
+    - serial: uartps: Wait for tx_empty in console setup
+    - btrfs: fix setting last_trans for reloc roots
+    - KVM: Remove CREATE_IRQCHIP/SET_PIT2 race
+    - perf stat: Force error in fallback on :k events
+    - bdev: Reduce time holding bd_mutex in sync in blkdev_close()
+    - drivers: char: tlclk.c: Avoid data race between init and interrupt handler
+    - KVM: arm64: vgic-v3: Retire all pending LPIs on vcpu destroy
+    - KVM: arm64: vgic-its: Fix memory leak on the error path of vgic_add_lpi()
+    - net: openvswitch: use u64 for meter bucket
+    - scsi: aacraid: Fix error handling paths in aac_probe_one()
+    - staging:r8188eu: avoid skb_clone for amsdu to msdu conversion
+    - sparc64: vcc: Fix error return code in vcc_probe()
+    - arm64: cpufeature: Relax checks for AArch32 support at EL[0-2]
+    - sched/fair: Eliminate bandwidth race between throttling and distribution
+    - dpaa2-eth: fix error return code in setup_dpni()
+    - dt-bindings: sound: wm8994: Correct required supplies based on actual
+      implementaion
+    - devlink: Fix reporter's recovery condition
+    - atm: fix a memory leak of vcc->user_back
+    - media: venus: vdec: Init registered list unconditionally
+    - perf mem2node: Avoid double free related to realloc
+    - mm/slub: fix incorrect interpretation of s->offset
+    - i2c: tegra: Restore pinmux on system resume
+    - power: supply: max17040: Correct voltage reading
+    - phy: samsung: s5pv210-usb2: Add delay after reset
+    - Bluetooth: Handle Inquiry Cancel error after Inquiry Complete
+    - USB: EHCI: ehci-mv: fix error handling in mv_ehci_probe()
+    - KVM: x86: handle wrap around 32-bit address space
+    - tipc: fix memory leak in service subscripting
+    - tty: serial: samsung: Correct clock selection logic
+    - ALSA: hda: Fix potential race in unsol event handler
+    - drm/exynos: dsi: Remove bridge node reference in error handling path in
+      probe function
+    - ipmi:bt-bmc: Fix error handling and status check
+    - powerpc/traps: Make unrecoverable NMIs die instead of panic
+    - svcrdma: Fix backchannel return code
+    - fuse: don't check refcount after stealing page
+    - fuse: update attr_version counter on fuse_notify_inval_inode()
+    - USB: EHCI: ehci-mv: fix less than zero comparison of an unsigned int
+    - coresight: etm4x: Fix use-after-free of per-cpu etm drvdata
+    - arm64: acpi: Make apei_claim_sea() synchronise with APEI's irq work
+    - scsi: cxlflash: Fix error return code in cxlflash_probe()
+    - arm64/cpufeature: Drop TraceFilt feature exposure from ID_DFR0 register
+    - drm/amdkfd: fix restore worker race condition
+    - e1000: Do not perform reset in reset_task if we are already down
+    - drm/nouveau/debugfs: fix runtime pm imbalance on error
+    - drm/nouveau: fix runtime pm imbalance on error
+    - drm/nouveau/dispnv50: fix runtime pm imbalance on error
+    - printk: handle blank console arguments passed in.
+    - usb: dwc3: Increase timeout for CmdAct cleared by device controller
+    - btrfs: don't force read-only after error in drop snapshot
+    - btrfs: fix double __endio_write_update_ordered in direct I/O
+    - gpio: rcar: Fix runtime PM imbalance on error
+    - vfio/pci: fix memory leaks of eventfd ctx
+    - KVM: PPC: Book3S HV: Close race with page faults around memslot flushes
+    - perf evsel: Fix 2 memory leaks
+    - perf trace: Fix the selection for architectures to generate the errno name
+      tables
+    - perf stat: Fix duration_time value for higher intervals
+    - perf util: Fix memory leak of prefix_if_not_in
+    - perf metricgroup: Free metric_events on error
+    - perf kcore_copy: Fix module map when there are no modules loaded
+    - PCI: tegra194: Fix runtime PM imbalance on error
+    - ASoC: img-i2s-out: Fix runtime PM imbalance on error
+    - wlcore: fix runtime pm imbalance in wl1271_tx_work
+    - wlcore: fix runtime pm imbalance in wlcore_regdomain_config
+    - mtd: rawnand: gpmi: Fix runtime PM imbalance on error
+    - mtd: rawnand: omap_elm: Fix runtime PM imbalance on error
+    - PCI: tegra: Fix runtime PM imbalance on error
+    - ceph: fix potential race in ceph_check_caps
+    - mm/swap_state: fix a data race in swapin_nr_pages
+    - mm: memcontrol: fix stat-corrupting race in charge moving
+    - rapidio: avoid data race between file operation callbacks and
+      mport_cdev_add().
+    - mtd: parser: cmdline: Support MTD names containing one or more colons
+    - x86/speculation/mds: Mark mds_user_clear_cpu_buffers() __always_inline
+    - NFS: nfs_xdr_status should record the procedure name
+    - vfio/pci: Clear error and request eventfd ctx after releasing
+    - cifs: Fix double add page to memcg when cifs_readpages
+    - nvme: fix possible deadlock when I/O is blocked
+    - mac80211: skip mpath lookup also for control port tx
+    - scsi: libfc: Handling of extra kref
+    - scsi: libfc: Skip additional kref updating work event
+    - selftests/x86/syscall_nt: Clear weird flags after each test
+    - vfio/pci: fix racy on error and request eventfd ctx
+    - btrfs: qgroup: fix data leak caused by race between writeback and truncate
+    - perf tests: Fix test 68 zstd compression for s390
+    - scsi: qla2xxx: Retry PLOGI on FC-NVMe PRLI failure
+    - ubi: fastmap: Free unused fastmap anchor peb during detach
+    - mt76: fix LED link time failure
+    - opp: Increase parsed_static_opps in _of_add_opp_table_v1()
+    - perf parse-events: Use strcmp() to compare the PMU name
+    - ALSA: hda: Always use jackpoll helper for jack update after resume
+    - ALSA: hda: Workaround for spurious wakeups on some Intel platforms
+    - net: openvswitch: use div_u64() for 64-by-32 divisions
+    - nvme: explicitly update mpath disk capacity on revalidation
+    - device_cgroup: Fix RCU list debugging warning
+    - ASoC: pcm3168a: ignore 0 Hz settings
+    - ASoC: wm8994: Skip setting of the WM8994_MICBIAS register for WM1811
+    - ASoC: wm8994: Ensure the device is resumed in wm89xx_mic_detect functions
+    - ASoC: Intel: bytcr_rt5640: Add quirk for MPMAN Converter9 2-in-1
+    - RISC-V: Take text_mutex in ftrace_init_nop()
+    - i2c: aspeed: Mask IRQ status to relevant bits
+    - s390/init: add missing __init annotations
+    - lockdep: fix order in trace_hardirqs_off_caller()
+    - EDAC/ghes: Check whether the driver is on the safe list correctly
+    - drm/amdkfd: fix a memory leak issue
+    - drm/amd/display: update nv1x stutter latencies
+    - drm/amdgpu/dc: Require primary plane to be enabled whenever the CRTC is
+    - objtool: Fix noreturn detection for ignored functions
+    - ieee802154: fix one possible memleak in ca8210_dev_com_init
+    - ieee802154/adf7242: check status of adf7242_read_reg
+    - clocksource/drivers/h8300_timer8: Fix wrong return value in
+      h8300_8timer_init()
+    - batman-adv: bla: fix type misuse for backbone_gw hash indexing
+    - atm: eni: fix the missed pci_disable_device() for eni_init_one()
+    - batman-adv: mcast/TT: fix wrongly dropped or rerouted packets
+    - netfilter: conntrack: nf_conncount_init is failing with IPv6 disabled
+    - mac802154: tx: fix use-after-free
+    - bpf: Fix clobbering of r2 in bpf_gen_ld_abs
+    - drm/vc4/vc4_hdmi: fill ASoC card owner
+    - net: qed: Disable aRFS for NPAR and 100G
+    - net: qede: Disable aRFS for NPAR and 100G
+    - net: qed: RDMA personality shouldn't fail VF load
+    - drm/sun4i: sun8i-csc: Secondary CSC register correction
+    - batman-adv: Add missing include for in_interrupt()
+    - nvme-tcp: fix kconfig dependency warning when !CRYPTO
+    - batman-adv: mcast: fix duplicate mcast packets in BLA backbone from LAN
+    - batman-adv: mcast: fix duplicate mcast packets in BLA backbone from mesh
+    - batman-adv: mcast: fix duplicate mcast packets from BLA backbone to mesh
+    - bpf: Fix a rcu warning for bpffs map pretty-print
+    - lib80211: fix unmet direct dependendices config warning when !CRYPTO
+    - ALSA: asihpi: fix iounmap in error handler
+    - regmap: fix page selection for noinc reads
+    - regmap: fix page selection for noinc writes
+    - MIPS: Add the missing 'CPU_1074K' into __get_cpu_type()
+    - regulator: axp20x: fix LDO2/4 description
+    - KVM: x86: Reset MMU context if guest toggles CR4.SMAP or CR4.PKE
+    - KVM: SVM: Add a dedicated INVD intercept routine
+    - mm: validate pmd after splitting
+    - arch/x86/lib/usercopy_64.c: fix __copy_user_flushcache() cache writeback
+    - x86/ioapic: Unbreak check_timer()
+    - scsi: lpfc: Fix initial FLOGI failure due to BBSCN not supported
+    - ALSA: usb-audio: Add delay quirk for H570e USB headsets
+    - ALSA: hda/realtek - Couldn't detect Mic if booting with headset plugged
+    - ALSA: hda/realtek: Enable front panel headset LED on Lenovo ThinkStation
+      P520
+    - lib/string.c: implement stpcpy
+    - tracing: fix double free
+    - s390/dasd: Fix zero write for FBA devices
+    - kprobes: Fix to check probe enabled before disarm_kprobe_ftrace()
+    - kprobes: tracing/kprobes: Fix to kill kprobes on initmem after boot
+    - btrfs: fix overflow when copying corrupt csums for a message
+    - dmabuf: fix NULL pointer dereference in dma_buf_release()
+    - mm, THP, swap: fix allocating cluster for swapfile by mistake
+    - mm/gup: fix gup_fast with dynamic page table folding
+    - s390/zcrypt: Fix ZCRYPT_PERDEV_REQCNT ioctl
+    - KVM: arm64: Assume write fault on S1PTW permission fault on instruction
+      fetch
+    - dm: fix bio splitting and its bio completion order for regular IO
+    - ata: define AC_ERR_OK
+    - ata: make qc_prep return ata_completion_errors
+    - ata: sata_mv, avoid trigerrable BUG_ON
+    - Linux 5.4.69
+
+  * Focal update: v5.4.68 upstream stable release (LP: #1899511)
+    - af_key: pfkey_dump needs parameter validation
+    - ibmvnic fix NULL tx_pools and rx_tools issue at do_reset
+    - ibmvnic: add missing parenthesis in do_reset()
+    - kprobes: fix kill kprobe which has been marked as gone
+    - mm/thp: fix __split_huge_pmd_locked() for migration PMD
+    - act_ife: load meta modules before tcf_idr_check_alloc()
+    - bnxt_en: Avoid sending firmware messages when AER error is detected.
+    - bnxt_en: Fix NULL ptr dereference crash in bnxt_fw_reset_task()
+    - cxgb4: fix memory leak during module unload
+    - cxgb4: Fix offset when clearing filter byte counters
+    - geneve: add transport ports in route lookup for geneve
+    - hdlc_ppp: add range checks in ppp_cp_parse_cr()
+    - ip: fix tos reflection in ack and reset packets
+    - ipv4: Initialize flowi4_multipath_hash in data path
+    - ipv4: Update exception handling for multipath routes via same device
+    - ipv6: avoid lockdep issue in fib6_del()
+    - net: bridge: br_vlan_get_pvid_rcu() should dereference the VLAN group under
+      RCU
+    - net: DCB: Validate DCB_ATTR_DCB_BUFFER argument
+    - net: dsa: rtl8366: Properly clear member config
+    - net: Fix bridge enslavement failure
+    - net: ipv6: fix kconfig dependency warning for IPV6_SEG6_HMAC
+    - net/mlx5: Fix FTE cleanup
+    - net: sch_generic: aviod concurrent reset and enqueue op for lockless qdisc
+    - net: sctp: Fix IPv6 ancestor_size calc in sctp_copy_descendant
+    - nfp: use correct define to return NONE fec
+    - taprio: Fix allowing too small intervals
+    - tipc: Fix memory leak in tipc_group_create_member()
+    - tipc: fix shutdown() of connection oriented socket
+    - tipc: use skb_unshare() instead in tipc_buf_append()
+    - net/mlx5e: Enable adding peer miss rules only if merged eswitch is supported
+    - net/mlx5e: TLS, Do not expose FPGA TLS counter if not supported
+    - bnxt_en: return proper error codes in bnxt_show_temp
+    - bnxt_en: Protect bnxt_set_eee() and bnxt_set_pauseparam() with mutex.
+    - net: lantiq: Wake TX queue again
+    - net: lantiq: use netif_tx_napi_add() for TX NAPI
+    - net: lantiq: Use napi_complete_done()
+    - net: lantiq: Disable IRQs only if NAPI gets scheduled
+    - net: phy: Avoid NPD upon phy_detach() when driver is unbound
+    - net: phy: Do not warn in phy_stop() on PHY_DOWN
+    - net: qrtr: check skb_put_padto() return value
+    - net: add __must_check to skb_put_padto()
+    - mm: memcg: fix memcg reclaim soft lockup
+    - iommu/amd: Use cmpxchg_double() when updating 128-bit IRTE
+    - Linux 5.4.68
+
+  * *-tools-common packages descriptions have typo "PGKVER" (LP: #1898903)
+    - [Packaging] Fix typo in -tools template s/PGKVER/PKGVER/
+
+  * tc/ebpf: unable to use BPF_FUNC_skb_change_head (LP: #1896504)
+    - net: bpf: Allow TC programs to call BPF_FUNC_skb_change_head
+
+  * HP Zbook Studio G7 boots into corrupted screen with PSR featured panel
+    (LP: #1897501)
+    - SAUCE: drm/i915/psr: allow overriding PSR disable param by quirk
+    - SAUCE: drm/dp: add DP_QUIRK_FORCE_PSR_CHIP_DEFAULT quirk to CMN prod-ID
+      19-15
+
+  * Fix broken e1000e device after S3 (LP: #1897755)
+    - SAUCE: e1000e: Increase polling timeout on MDIC ready bit
+
+  * debian/rules editconfigs does not work on s390x to change s390x only configs
+    (LP: #1863116)
+    - [Packaging] kernelconfig -- only update/edit configurations on architectures
+      we have compiler support
+
+  * acpi event detection crashes (LP: #1896482)
+    - ACPI: EC: tweak naming in preparation for GpioInt support
+    - ACPI: EC: add support for hardware-reduced systems
+    - ACPI: EC: Avoid passing redundant argument to functions
+    - ACPI: EC: Consolidate event handler installation code
+
+  * mwifiex stops working after kernel upgrade (LP: #1897299)
+    - mwifiex: Increase AES key storage size to 256 bits
+
+  * Remove NVMe suspend-to-idle workaround (LP: #1897227)
+    - Revert "UBUTU: SAUCE: pci: prevent Intel NVMe SSDPEKKF from entering D3"
+    - Revert "UBUNTU: SAUCE: pci: prevent sk hynix nvme from entering D3"
+
+  * Request for CIFS patches to be available in 5.4 kernel (LP: #1896642)
+    - smb3: remove unused flag passed into close functions
+    - smb3: query attributes on file close
+
+  * Lenovo ThinkBook 14-IML Touchpad not showing up in /proc/bus/input/devices
+    (LP: #1853277)
+    - i2c: core: Call i2c_acpi_install_space_handler() before
+      i2c_acpi_register_devices()
+
+  * [Ubuntu 20.10] zPCI DMA tables and bitmap leak on hard unplug (PCI Event
+    0x0304) (LP: #1896216)
+    - s390/pci: fix leak of DMA tables on hard unplug
+
+  * Thunderbolt3 daisy chain sometimes doesn't work (LP: #1895606)
+    - thunderbolt: Retry DROM read once if parsing fails
+
+  * btrfs: trimming a btrfs device which has been shrunk previously fails and
+    fills root disk with garbage data (LP: #1896154)
+    - btrfs: trim: fix underflow in trim length to prevent access beyond device
+      boundary
+
+  * EFA: add support for 0xefa1 devices (LP: #1896791)
+    - RDMA/efa: Expose maximum TX doorbell batch
+    - RDMA/efa: Expose minimum SQ size
+    - RDMA/efa: User/kernel compatibility handshake mechanism
+    - RDMA/efa: Add EFA 0xefa1 PCI ID
+
+  * Focal update: v5.4.67 upstream stable release (LP: #1896828)
+    - gfs2: initialize transaction tr_ailX_lists earlier
+    - RDMA/bnxt_re: Restrict the max_gids to 256
+    - dsa: Allow forwarding of redirected IGMP traffic
+    - net: handle the return value of pskb_carve_frag_list() correctly
+    - hv_netvsc: Remove "unlikely" from netvsc_select_queue
+    - firmware_loader: fix memory leak for paged buffer
+    - NFSv4.1 handle ERR_DELAY error reclaiming locking state on delegation recall
+    - scsi: pm8001: Fix memleak in pm8001_exec_internal_task_abort
+    - scsi: libfc: Fix for double free()
+    - scsi: lpfc: Fix FLOGI/PLOGI receive race condition in pt2pt discovery
+    - regulator: pwm: Fix machine constraints application
+    - spi: spi-loopback-test: Fix out-of-bounds read
+    - NFS: Zero-stateid SETATTR should first return delegation
+    - SUNRPC: stop printk reading past end of string
+    - rapidio: Replace 'select' DMAENGINES 'with depends on'
+    - cifs: fix DFS mount with cifsacl/modefromsid
+    - openrisc: Fix cache API compile issue when not inlining
+    - nvme-fc: cancel async events before freeing event struct
+    - nvme-rdma: cancel async events before freeing event struct
+    - nvme-tcp: cancel async events before freeing event struct
+    - block: only call sched requeue_request() for scheduled requests
+    - f2fs: fix indefinite loop scanning for free nid
+    - f2fs: Return EOF on unaligned end of file DIO read
+    - i2c: algo: pca: Reapply i2c bus settings after reset
+    - spi: Fix memory leak on splited transfers
+    - KVM: MIPS: Change the definition of kvm type
+    - clk: davinci: Use the correct size when allocating memory
+    - clk: rockchip: Fix initialization of mux_pll_src_4plls_p
+    - ASoC: qcom: Set card->owner to avoid warnings
+    - ASoC: qcom: common: Fix refcount imbalance on error
+    - powerpc/book3s64/radix: Fix boot failure with large amount of guest memory
+    - ASoC: meson: axg-toddr: fix channel order on g12 platforms
+    - Drivers: hv: vmbus: hibernation: do not hang forever in vmbus_bus_resume()
+    - scsi: libsas: Fix error path in sas_notify_lldd_dev_found()
+    - arm64: Allow CPUs unffected by ARM erratum 1418040 to come in late
+    - Drivers: hv: vmbus: Add timeout to vmbus_wait_for_unload
+    - perf test: Fix the "signal" test inline assembly
+    - MIPS: SNI: Fix MIPS_L1_CACHE_SHIFT
+    - perf evlist: Fix cpu/thread map leak
+    - perf parse-event: Fix memory leak in evsel->unit
+    - perf test: Free formats for perf pmu parse test
+    - fbcon: Fix user font detection test at fbcon_resize().
+    - MIPS: SNI: Fix spurious interrupts
+    - drm/mediatek: Add exception handing in mtk_drm_probe() if component init
+      fail
+    - drm/mediatek: Add missing put_device() call in mtk_hdmi_dt_parse_pdata()
+    - arm64: bpf: Fix branch offset in JIT
+    - iommu/amd: Fix potential @entry null deref
+    - i2c: mxs: use MXS_DMA_CTRL_WAIT4END instead of DMA_CTRL_ACK
+    - riscv: Add sfence.vma after early page table changes
+    - drm/i915: Filter wake_flags passed to default_wake_function
+    - USB: quirks: Add USB_QUIRK_IGNORE_REMOTE_WAKEUP quirk for BYD zhaoxin
+      notebook
+    - USB: UAS: fix disconnect by unplugging a hub
+    - usblp: fix race between disconnect() and read()
+    - i2c: i801: Fix resume bug
+    - Revert "ALSA: hda - Fix silent audio output and corrupted input on MSI
+      X570-A PRO"
+    - ALSA: hda: fixup headset for ASUS GX502 laptop
+    - ALSA: hda/realtek - The Mic on a RedmiBook doesn't work
+    - percpu: fix first chunk size calculation for populated bitmap
+    - Input: trackpoint - add new trackpoint variant IDs
+    - Input: i8042 - add Entroware Proteus EL07R4 to nomux and reset lists
+    - serial: 8250_pci: Add Realtek 816a and 816b
+    - x86/boot/compressed: Disable relocation relaxation
+    - s390/zcrypt: fix kmalloc 256k failure
+    - ehci-hcd: Move include to keep CRC stable
+    - powerpc/dma: Fix dma_map_ops::get_required_mask
+    - selftests/vm: fix display of page size in map_hugetlb
+    - dm/dax: Fix table reference counts
+    - mm/memory_hotplug: drain per-cpu pages again during memory offline
+    - dm: Call proper helper to determine dax support
+    - dax: Fix compilation for CONFIG_DAX && !CONFIG_FS_DAX
+    - Linux 5.4.67
+
+  * Focal update: v5.4.67 upstream stable release (LP: #1896828) // Cherry Pick
+    needed for Critical upstream patch for Kernel null pointer dereference -
+    usb-c altmode (LP: #1897963)
+    - usb: typec: ucsi: Prevent mode overrun
+
+  * Focal update: v5.4.66 upstream stable release (LP: #1896824)
+    - ARM: dts: logicpd-torpedo-baseboard: Fix broken audio
+    - ARM: dts: logicpd-som-lv-baseboard: Fix broken audio
+    - ARM: dts: logicpd-som-lv-baseboard: Fix missing video
+    - regulator: push allocation in regulator_ena_gpio_request() out of lock
+    - regulator: remove superfluous lock in regulator_resolve_coupling()
+    - ARM: dts: socfpga: fix register entry for timer3 on Arria10
+    - ARM: dts: ls1021a: fix QuadSPI-memory reg range
+    - ARM: dts: imx7ulp: Correct gpio ranges
+    - RDMA/rxe: Fix memleak in rxe_mem_init_user
+    - RDMA/rxe: Drop pointless checks in rxe_init_ports
+    - RDMA/rxe: Fix panic when calling kmem_cache_create()
+    - RDMA/bnxt_re: Do not report transparent vlan from QP1
+    - drm/sun4i: add missing put_device() call in sun8i_r40_tcon_tv_set_mux()
+    - arm64: dts: imx8mq: Fix TMU interrupt property
+    - drm/sun4i: Fix dsi dcs long write function
+    - iio: adc: mcp3422: fix locking on error path
+    - iio: adc: mcp3422: fix locking scope
+    - scsi: libsas: Set data_dir as DMA_NONE if libata marks qc as NODATA
+    - RDMA/core: Fix reported speed and width
+    - scsi: megaraid_sas: Don't call disable_irq from process IRQ poll
+    - scsi: mpt3sas: Don't call disable_irq from IRQ poll handler
+    - soundwire: fix double free of dangling pointer
+    - drm/sun4i: backend: Support alpha property on lowest plane
+    - drm/sun4i: backend: Disable alpha on the lowest plane on the A20
+    - mmc: sdhci-acpi: Clear amd_sdhci_host on reset
+    - mmc: sdhci-msm: Add retries when all tuning phases are found valid
+    - spi: stm32: Rate-limit the 'Communication suspended' message
+    - nvme-fabrics: allow to queue requests for live queues
+    - spi: stm32: fix pm_runtime_get_sync() error checking
+    - block: Set same_page to false in __bio_try_merge_page if ret is false
+    - IB/isert: Fix unaligned immediate-data handling
+    - ARM: dts: bcm: HR2: Fixed QSPI compatible string
+    - ARM: dts: NSP: Fixed QSPI compatible string
+    - ARM: dts: BCM5301X: Fixed QSPI compatible string
+    - arm64: dts: ns2: Fixed QSPI compatible string
+    - ARC: HSDK: wireup perf irq
+    - dmaengine: acpi: Put the CSRT table after using it
+    - netfilter: conntrack: allow sctp hearbeat after connection re-use
+    - drivers/net/wan/lapbether: Added needed_tailroom
+    - NFC: st95hf: Fix memleak in st95hf_in_send_cmd
+    - firestream: Fix memleak in fs_open
+    - ALSA: hda: Fix 2 channel swapping for Tegra
+    - ALSA: hda/tegra: Program WAKEEN register for Tegra
+    - drivers/dma/dma-jz4780: Fix race condition between probe and irq handler
+    - net: hns3: Fix for geneve tx checksum bug
+    - xfs: fix off-by-one in inode alloc block reservation calculation
+    - drivers/net/wan/lapbether: Set network_header before transmitting
+    - cfg80211: Adjust 6 GHz frequency to channel conversion
+    - xfs: initialize the shortform attr header padding entry
+    - irqchip/eznps: Fix build error for !ARC700 builds
+    - nvmet-tcp: Fix NULL dereference when a connect data comes in h2cdata pdu
+    - nvme-fabrics: don't check state NVME_CTRL_NEW for request acceptance
+    - nvme: have nvme_wait_freeze_timeout return if it timed out
+    - nvme-tcp: serialize controller teardown sequences
+    - nvme-tcp: fix timeout handler
+    - nvme-tcp: fix reset hang if controller died in the middle of a reset
+    - nvme-rdma: serialize controller teardown sequences
+    - nvme-rdma: fix timeout handler
+    - nvme-rdma: fix reset hang if controller died in the middle of a reset
+    - nvme-pci: cancel nvme device request before disabling
+    - HID: quirks: Set INCREMENT_USAGE_ON_DUPLICATE for all Saitek X52 devices
+    - HID: microsoft: Add rumble support for the 8bitdo SN30 Pro+ controller
+    - drivers/net/wan/hdlc_cisco: Add hard_header_len
+    - HID: elan: Fix memleak in elan_input_configured
+    - ARC: [plat-hsdk]: Switch ethernet phy-mode to rgmii-id
+    - cpufreq: intel_pstate: Refuse to turn off with HWP enabled
+    - cpufreq: intel_pstate: Fix intel_pstate_get_hwp_max() for turbo disabled
+    - arm64/module: set trampoline section flags regardless of
+      CONFIG_DYNAMIC_FTRACE
+    - ALSA: hda: hdmi - add Rocketlake support
+    - ALSA: hda: fix a runtime pm issue in SOF when integrated GPU is disabled
+    - drm/amdgpu: Fix bug in reporting voltage for CIK
+    - iommu/amd: Do not use IOMMUv2 functionality when SME is active
+    - gcov: Disable gcov build with GCC 10
+    - iio: adc: ti-ads1015: fix conversion when CONFIG_PM is not set
+    - iio: cros_ec: Set Gyroscope default frequency to 25Hz
+    - iio:light:ltr501 Fix timestamp alignment issue.
+    - iio:proximity:mb1232: Fix timestamp alignment and prevent data leak.
+    - iio:accel:bmc150-accel: Fix timestamp alignment and prevent data leak.
+    - iio:adc:ti-adc084s021 Fix alignment and data leak issues.
+    - iio:adc:ina2xx Fix timestamp alignment issue.
+    - iio:adc:max1118 Fix alignment of timestamp and data leak issues
+    - iio:adc:ti-adc081c Fix alignment and data leak issues
+    - iio:magnetometer:ak8975 Fix alignment and data leak issues.
+    - iio:light:max44000 Fix timestamp alignment and prevent data leak.
+    - iio:chemical:ccs811: Fix timestamp alignment and prevent data leak.
+    - iio: accel: kxsd9: Fix alignment of local buffer.
+    - iio:accel:mma7455: Fix timestamp alignment and prevent data leak.
+    - iio:accel:mma8452: Fix timestamp alignment and prevent data leak.
+    - staging: wlan-ng: fix out of bounds read in prism2sta_probe_usb()
+    - btrfs: require only sector size alignment for parent eb bytenr
+    - btrfs: fix lockdep splat in add_missing_dev
+    - btrfs: fix wrong address when faulting in pages in the search ioctl
+    - kobject: Restore old behaviour of kobject_del(NULL)
+    - regulator: push allocation in regulator_init_coupling() outside of lock
+    - regulator: push allocations in create_regulator() outside of lock
+    - regulator: push allocation in set_consumer_device_supply() out of lock
+    - regulator: plug of_node leak in regulator_register()'s error path
+    - regulator: core: Fix slab-out-of-bounds in regulator_unlock_recursive()
+    - scsi: target: iscsi: Fix data digest calculation
+    - scsi: target: iscsi: Fix hang in iscsit_access_np() when getting
+      tpg->np_login_sem
+    - drm/i915/gvt: do not check len & max_len for lri
+    - drm/tve200: Stabilize enable/disable
+    - drm/msm: Disable preemption on all 5xx targets
+    - mmc: sdio: Use mmc_pre_req() / mmc_post_req()
+    - mmc: sdhci-of-esdhc: Don't walk device-tree on every interrupt
+    - rbd: require global CAP_SYS_ADMIN for mapping and unmapping
+    - RDMA/rxe: Fix the parent sysfs read when the interface has 15 chars
+    - RDMA/mlx4: Read pkey table length instead of hardcoded value
+    - fbcon: remove soft scrollback code
+    - fbcon: remove now unusued 'softback_lines' cursor() argument
+    - vgacon: remove software scrollback support
+    - [Config] updateconfigs for VGACON_SOFT_SCROLLBACK
+    - KVM: VMX: Don't freeze guest when event delivery causes an APIC-access exit
+    - KVM: arm64: Do not try to map PUDs when they are folded into PMD
+    - KVM: fix memory leak in kvm_io_bus_unregister_dev()
+    - debugfs: Fix module state check condition
+    - ARM: dts: vfxxx: Add syscon compatible with OCOTP
+    - video: fbdev: fix OOB read in vga_8planes_imageblit()
+    - staging: greybus: audio: fix uninitialized value issue
+    - phy: qcom-qmp: Use correct values for ipq8074 PCIe Gen2 PHY init
+    - usb: core: fix slab-out-of-bounds Read in read_descriptors
+    - USB: serial: ftdi_sio: add IDs for Xsens Mti USB converter
+    - USB: serial: option: support dynamic Quectel USB compositions
+    - USB: serial: option: add support for SIM7070/SIM7080/SIM7090 modules
+    - usb: Fix out of sync data toggle if a configured device is reconfigured
+    - usb: typec: ucsi: acpi: Check the _DEP dependencies
+    - drm/msm/gpu: make ringbuffer readonly
+    - drm/msm: Disable the RPTR shadow
+    - gcov: add support for GCC 10.1
+    - Linux 5.4.66
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Mon, 09 Nov 2020 14:56:24 +0100
+
+linux (5.4.0-54.60) focal; urgency=medium
+
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+
+  * Introduce the new NVIDIA 455 series (LP: #1902093)
+    - [Packaging] NVIDIA -- Add the NVIDIA 455 driver
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Thu, 05 Nov 2020 18:03:49 +0100
+
+linux (5.4.0-53.59) focal; urgency=medium
+
+  * CVE-2020-8694
+    - powercap: make attributes only readable by root
+
+ -- Kleber Sacilotto de Souza <kleber.souza@canonical.com>  Wed, 21 Oct 2020 11:00:29 +0200
+
+linux (5.4.0-52.57) focal; urgency=medium
+
+  * focal/linux: 5.4.0-52.57 -proposed tracker (LP: #1899920)
+
+  * CVE-2020-12351 // CVE-2020-12352 // CVE-2020-24490
+    - Bluetooth: Disable High Speed by default
+    - Bluetooth: MGMT: Fix not checking if BT_HS is enabled
+    - [Config] Disable BlueZ highspeed support
+
+  * CVE-2020-12351
+    - Bluetooth: L2CAP: Fix calling sk_filter on non-socket based channel
+
+  * CVE-2020-12352
+    - Bluetooth: A2MP: Fix not initializing all members
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Thu, 15 Oct 2020 12:28:28 +0200
+
+linux (5.4.0-51.56) focal; urgency=medium
+
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+
+ -- Kleber Sacilotto de Souza <kleber.souza@canonical.com>  Mon, 05 Oct 2020 15:34:26 +0200
+
+linux (5.4.0-50.55) focal; urgency=medium
+
+  * CVE-2020-16119
+    - SAUCE: dccp: avoid double free of ccid on child socket
+
+  * CVE-2020-16120
+    - Revert "UBUNTU: SAUCE: overlayfs: ensure mounter privileges when reading
+      directories"
+    - ovl: pass correct flags for opening real directory
+    - ovl: switch to mounter creds in readdir
+    - ovl: verify permissions in ovl_path_open()
+    - ovl: call secutiry hook in ovl_real_ioctl()
+    - ovl: check permission to open real file
+
+ -- Thadeu Lima de Souza Cascardo <cascardo@canonical.com>  Wed, 30 Sep 2020 10:04:48 -0300
+
+linux (5.4.0-49.53) focal; urgency=medium
+
+  * focal/linux: 5.4.0-49.53 -proposed tracker (LP: #1896007)
+
+  * Comet Lake PCH-H RAID not support on Ubuntu20.04 (LP: #1892288)
+    - ahci: Add Intel Comet Lake PCH-H PCI ID
+
+  * Novalink (mkvterm command failure) (LP: #1892546)
+    - tty: hvcs: Don't NULL tty->driver_data until hvcs_cleanup()
+
+  * Oops and hang when starting LVM snapshots on 5.4.0-47 (LP: #1894780)
+    - SAUCE: Revert "mm: memcg/slab: fix memory leak at non-root kmem_cache
+      destroy"
+
+  * Intel x710 LOMs do not work on Focal (LP: #1893956)
+    - i40e: Fix LED blinking flow for X710T*L devices
+    - i40e: enable X710 support
+
+  * Add/Backport EPYC-v3 and EPYC-Rome CPU model (LP: #1887490)
+    - kvm: svm: Update svm_xsaves_supported
+
+  * Fix non-working NVMe after S3 (LP: #1895718)
+    - SAUCE: PCI: Enable ACS quirk on CML root port
+
+  * Focal update: v5.4.65 upstream stable release (LP: #1895881)
+    - ipv4: Silence suspicious RCU usage warning
+    - ipv6: Fix sysctl max for fib_multipath_hash_policy
+    - netlabel: fix problems with mapping removal
+    - net: usb: dm9601: Add USB ID of Keenetic Plus DSL
+    - sctp: not disable bh in the whole sctp_get_port_local()
+    - taprio: Fix using wrong queues in gate mask
+    - tipc: fix shutdown() of connectionless socket
+    - net: disable netpoll on fresh napis
+    - Linux 5.4.65
+
+  * Focal update: v5.4.64 upstream stable release (LP: #1895880)
+    - HID: quirks: Always poll three more Lenovo PixArt mice
+    - drm/msm/dpu: Fix scale params in plane validation
+    - tty: serial: qcom_geni_serial: Drop __init from qcom_geni_console_setup
+    - drm/msm: add shutdown support for display platform_driver
+    - hwmon: (applesmc) check status earlier.
+    - nvmet: Disable keep-alive timer when kato is cleared to 0h
+    - drm/msm: enable vblank during atomic commits
+    - habanalabs: validate FW file size
+    - habanalabs: check correct vmalloc return code
+    - drm/msm/a6xx: fix gmu start on newer firmware
+    - ceph: don't allow setlease on cephfs
+    - drm/omap: fix incorrect lock state
+    - cpuidle: Fixup IRQ state
+    - nbd: restore default timeout when setting it to zero
+    - s390: don't trace preemption in percpu macros
+    - drm/amd/display: Reject overlay plane configurations in multi-display
+      scenarios
+    - drivers: gpu: amd: Initialize amdgpu_dm_backlight_caps object to 0 in
+      amdgpu_dm_update_backlight_caps
+    - drm/amd/display: Retry AUX write when fail occurs
+    - drm/amd/display: Fix memleak in amdgpu_dm_mode_config_init
+    - xen/xenbus: Fix granting of vmalloc'd memory
+    - fsldma: fix very broken 32-bit ppc ioread64 functionality
+    - dmaengine: of-dma: Fix of_dma_router_xlate's of_dma_xlate handling
+    - batman-adv: Avoid uninitialized chaddr when handling DHCP
+    - batman-adv: Fix own OGM check in aggregated OGMs
+    - batman-adv: bla: use netif_rx_ni when not in interrupt context
+    - dmaengine: at_hdmac: check return value of of_find_device_by_node() in
+      at_dma_xlate()
+    - rxrpc: Keep the ACK serial in a var in rxrpc_input_ack()
+    - rxrpc: Make rxrpc_kernel_get_srtt() indicate validity
+    - MIPS: mm: BMIPS5000 has inclusive physical caches
+    - MIPS: BMIPS: Also call bmips_cpu_setup() for secondary cores
+    - mmc: sdhci-acpi: Fix HS400 tuning for AMDI0040
+    - netfilter: nf_tables: add NFTA_SET_USERDATA if not null
+    - netfilter: nf_tables: incorrect enum nft_list_attributes definition
+    - netfilter: nf_tables: fix destination register zeroing
+    - net: hns: Fix memleak in hns_nic_dev_probe
+    - net: systemport: Fix memleak in bcm_sysport_probe
+    - ravb: Fixed to be able to unload modules
+    - net: arc_emac: Fix memleak in arc_mdio_probe
+    - dmaengine: pl330: Fix burst length if burst size is smaller than bus width
+    - gtp: add GTPA_LINK info to msg sent to userspace
+    - net: ethernet: ti: cpsw: fix clean up of vlan mc entries for host port
+    - bnxt_en: Don't query FW when netif_running() is false.
+    - bnxt_en: Check for zero dir entries in NVRAM.
+    - bnxt_en: Fix PCI AER error recovery flow
+    - bnxt_en: Fix possible crash in bnxt_fw_reset_task().
+    - bnxt_en: fix HWRM error when querying VF temperature
+    - xfs: fix boundary test in xfs_attr_shortform_verify
+    - bnxt: don't enable NAPI until rings are ready
+    - media: vicodec: add missing v4l2_ctrl_request_hdl_put()
+    - media: cedrus: Add missing v4l2_ctrl_request_hdl_put()
+    - selftests/bpf: Fix massive output from test_maps
+    - net: dsa: mt7530: fix advertising unsupported 1000baseT_Half
+    - netfilter: nfnetlink: nfnetlink_unicast() reports EAGAIN instead of ENOBUFS
+    - nvmet-fc: Fix a missed _irqsave version of spin_lock in
+      'nvmet_fc_fod_op_done()'
+    - nvme: fix controller instance leak
+    - cxgb4: fix thermal zone device registration
+    - perf tools: Correct SNOOPX field offset
+    - net: ethernet: mlx4: Fix memory allocation in mlx4_buddy_init()
+    - fix regression in "epoll: Keep a reference on files added to the check list"
+    - net: gemini: Fix another missing clk_disable_unprepare() in probe
+    - MIPS: add missing MSACSR and upper MSA initialization
+    - xfs: fix xfs_bmap_validate_extent_raw when checking attr fork of rt files
+    - perf jevents: Fix suspicious code in fixregex()
+    - tg3: Fix soft lockup when tg3_reset_task() fails.
+    - x86, fakenuma: Fix invalid starting node ID
+    - iommu/vt-d: Serialize IOMMU GCMD register modifications
+    - thermal: ti-soc-thermal: Fix bogus thermal shutdowns for omap4430
+    - thermal: qcom-spmi-temp-alarm: Don't suppress negative temp
+    - iommu/amd: Restore IRTE.RemapEn bit after programming IRTE
+    - include/linux/log2.h: add missing () around n in roundup_pow_of_two()
+    - iommu/vt-d: Handle 36bit addressing for x86-32
+    - tracing/kprobes, x86/ptrace: Fix regs argument order for i386
+    - ext2: don't update mtime on COW faults
+    - xfs: don't update mtime on COW faults
+    - ARC: perf: don't bail setup if pct irq missing in device-tree
+    - btrfs: drop path before adding new uuid tree entry
+    - btrfs: allocate scrub workqueues outside of locks
+    - btrfs: set the correct lockdep class for new nodes
+    - btrfs: set the lockdep class for log tree extent buffers
+    - btrfs: tree-checker: fix the error message for transid error
+    - net: core: use listified Rx for GRO_NORMAL in napi_gro_receive()
+    - btrfs: fix potential deadlock in the search ioctl
+    - ALSA: ca0106: fix error code handling
+    - ALSA: usb-audio: Add implicit feedback quirk for UR22C
+    - ALSA: pcm: oss: Remove superfluous WARN_ON() for mulaw sanity check
+    - ALSA: hda/hdmi: always check pin power status in i915 pin fixup
+    - ALSA: firewire-digi00x: exclude Avid Adrenaline from detection
+    - ALSA: hda - Fix silent audio output and corrupted input on MSI X570-A PRO
+    - ALSA; firewire-tascam: exclude Tascam FE-8 from detection
+    - ALSA: hda/realtek: Add quirk for Samsung Galaxy Book Ion NT950XCJ-X716A
+    - ALSA: hda/realtek - Improved routing for Thinkpad X1 7th/8th Gen
+    - arm64: dts: mt7622: add reset node for mmc device
+    - mmc: mediatek: add optional module reset property
+    - mmc: dt-bindings: Add resets/reset-names for Mediatek MMC bindings
+    - mmc: cqhci: Add cqhci_deactivate()
+    - mmc: sdhci-pci: Fix SDHCI_RESET_ALL for CQHCI for Intel GLK-based
+      controllers
+    - media: rc: do not access device via sysfs after rc_unregister_device()
+    - media: rc: uevent sysfs file races with rc_unregister_device()
+    - affs: fix basic permission bits to actually work
+    - block: allow for_each_bvec to support zero len bvec
+    - block: ensure bdi->io_pages is always initialized
+    - libata: implement ATA_HORKAGE_MAX_TRIM_128M and apply to Sandisks
+    - blk-iocost: ioc_pd_free() shouldn't assume irq disabled
+    - dmaengine: dw-edma: Fix scatter-gather address calculation
+    - drm/amd/pm: avoid false alarm due to confusing softwareshutdowntemp setting
+    - dm writecache: handle DAX to partitions on persistent memory correctly
+    - dm mpath: fix racey management of PG initialization
+    - dm integrity: fix error reporting in bitmap mode after creation
+    - dm crypt: Initialize crypto wait structures
+    - dm cache metadata: Avoid returning cmd->bm wild pointer on error
+    - dm thin metadata: Avoid returning cmd->bm wild pointer on error
+    - dm thin metadata: Fix use-after-free in dm_bm_set_read_only
+    - mm: slub: fix conversion of freelist_corrupted()
+    - mm: madvise: fix vma user-after-free
+    - vfio/pci: Fix SR-IOV VF handling with MMIO blocking
+    - perf record: Correct the help info of option "--no-bpf-event"
+    - sdhci: tegra: Add missing TMCLK for data timeout
+    - checkpatch: fix the usage of capture group ( ... )
+    - mm/hugetlb: fix a race between hugetlb sysctl handlers
+    - mm/khugepaged.c: fix khugepaged's request size in collapse_file
+    - cfg80211: regulatory: reject invalid hints
+    - net: usb: Fix uninit-was-stored issue in asix_read_phy_addr()
+    - Linux 5.4.64
+
+  * Focal update: v5.4.63 upstream stable release (LP: #1895879)
+    - HID: core: Correctly handle ReportSize being zero
+    - HID: core: Sanitize event code and type when mapping input
+    - perf record/stat: Explicitly call out event modifiers in the documentation
+    - drm/sched: Fix passing zero to 'PTR_ERR' warning v2
+    - drm/etnaviv: fix TS cache flushing on GPUs with BLT engine
+    - KVM: arm64: Add kvm_extable for vaxorcism code
+    - KVM: arm64: Survive synchronous exceptions caused by AT instructions
+    - KVM: arm64: Set HCR_EL2.PTW to prevent AT taking synchronous exception
+    - dt-bindings: mmc: tegra: Add tmclk for Tegra210 and later
+    - arm64: tegra: Add missing timeout clock to Tegra194 SDMMC nodes
+    - arm64: tegra: Add missing timeout clock to Tegra186 SDMMC nodes
+    - arm64: tegra: Add missing timeout clock to Tegra210 SDMMC
+    - sdhci: tegra: Remove SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK for Tegra210
+    - sdhci: tegra: Remove SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK for Tegra186
+    - scsi: target: tcmu: Fix size in calls to tcmu_flush_dcache_range
+    - scsi: target: tcmu: Optimize use of flush_dcache_page
+    - Linux 5.4.63
+
+  * Focal update: v5.4.62 upstream stable release (LP: #1895174)
+    - binfmt_flat: revert "binfmt_flat: don't offset the data start"
+    - gre6: Fix reception with IP6_TNL_F_RCV_DSCP_COPY
+    - net: Fix potential wrong skb->protocol in skb_vlan_untag()
+    - net: nexthop: don't allow empty NHA_GROUP
+    - net: qrtr: fix usage of idr in port assignment to socket
+    - net: sctp: Fix negotiation of the number of data streams.
+    - net/smc: Prevent kernel-infoleak in __smc_diag_dump()
+    - tipc: fix uninit skb->data in tipc_nl_compat_dumpit()
+    - net: ena: Make missed_tx stat incremental
+    - net/sched: act_ct: Fix skb double-free in tcf_ct_handle_fragments() error
+      flow
+    - ipvlan: fix device features
+    - ALSA: pci: delete repeated words in comments
+    - ASoC: img: Fix a reference count leak in img_i2s_in_set_fmt
+    - ASoC: img-parallel-out: Fix a reference count leak
+    - ASoC: tegra: Fix reference count leaks.
+    - mfd: intel-lpss: Add Intel Emmitsburg PCH PCI IDs
+    - arm64: dts: qcom: msm8916: Pull down PDM GPIOs during sleep
+    - powerpc/xive: Ignore kmemleak false positives
+    - media: pci: ttpci: av7110: fix possible buffer overflow caused by bad DMA
+      value in debiirq()
+    - blktrace: ensure our debugfs dir exists
+    - scsi: target: tcmu: Fix crash on ARM during cmd completion
+    - mfd: intel-lpss: Add Intel Tiger Lake PCH-H PCI IDs
+    - iommu/iova: Don't BUG on invalid PFNs
+    - drm/amdkfd: Fix reference count leaks.
+    - drm/radeon: fix multiple reference count leak
+    - drm/amdgpu: fix ref count leak in amdgpu_driver_open_kms
+    - drm/amd/display: fix ref count leak in amdgpu_drm_ioctl
+    - drm/amdgpu: fix ref count leak in amdgpu_display_crtc_set_config
+    - drm/amdgpu/display: fix ref count leak when pm_runtime_get_sync fails
+    - scsi: lpfc: Fix shost refcount mismatch when deleting vport
+    - xfs: Don't allow logging of XFS_ISTALE inodes
+    - scsi: target: Fix xcopy sess release leak
+    - selftests/powerpc: Purge extra count_pmc() calls of ebb selftests
+    - f2fs: fix error path in do_recover_data()
+    - omapfb: fix multiple reference count leaks due to pm_runtime_get_sync
+    - PCI: Fix pci_create_slot() reference count leak
+    - ARM: dts: ls1021a: output PPS signal on FIPER2
+    - rtlwifi: rtl8192cu: Prevent leaking urb
+    - mips/vdso: Fix resource leaks in genvdso.c
+    - cec-api: prevent leaking memory through hole in structure
+    - HID: quirks: add NOGET quirk for Logitech GROUP
+    - f2fs: fix use-after-free issue
+    - drm/nouveau/drm/noveau: fix reference count leak in nouveau_fbcon_open
+    - drm/nouveau: fix reference count leak in nv50_disp_atomic_commit
+    - drm/nouveau: Fix reference count leak in nouveau_connector_detect
+    - locking/lockdep: Fix overflow in presentation of average lock-time
+    - btrfs: file: reserve qgroup space after the hole punch range is locked
+    - btrfs: make btrfs_qgroup_check_reserved_leak take btrfs_inode
+    - scsi: iscsi: Do not put host in iscsi_set_flashnode_param()
+    - ceph: fix potential mdsc use-after-free crash
+    - ceph: do not access the kiocb after aio requests
+    - scsi: fcoe: Memory leak fix in fcoe_sysfs_fcf_del()
+    - EDAC/ie31200: Fallback if host bridge device is already initialized
+    - hugetlbfs: prevent filesystem stacking of hugetlbfs
+    - media: davinci: vpif_capture: fix potential double free
+    - KVM: arm64: Fix symbol dependency in __hyp_call_panic_nvhe
+    - powerpc/spufs: add CONFIG_COREDUMP dependency
+    - USB: sisusbvga: Fix a potential UB casued by left shifting a negative value
+    - brcmfmac: Set timeout value when configuring power save
+    - efi: provide empty efi_enter_virtual_mode implementation
+    - arm64: Fix __cpu_logical_map undefined issue
+    - Revert "ath10k: fix DMA related firmware crashes on multiple devices"
+    - sched/uclamp: Protect uclamp fast path code with static key
+    - sched/uclamp: Fix a deadlock when enabling uclamp static key
+    - usb: cdns3: gadget: always zeroed TRB buffer when enable endpoint
+    - PM / devfreq: rk3399_dmc: Add missing of_node_put()
+    - PM / devfreq: rk3399_dmc: Disable devfreq-event device when fails
+    - PM / devfreq: rk3399_dmc: Fix kernel oops when rockchip,pmu is absent
+    - drm/xen: fix passing zero to 'PTR_ERR' warning
+    - drm/xen-front: Fix misused IS_ERR_OR_NULL checks
+    - s390/numa: set node distance to LOCAL_DISTANCE
+    - btrfs: factor out inode items copy loop from btrfs_log_inode()
+    - btrfs: only commit the delayed inode when doing a full fsync
+    - btrfs: only commit delayed items at fsync if we are logging a directory
+    - mm/shuffle: don't move pages between zones and don't read garbage memmaps
+    - mm: fix kthread_use_mm() vs TLB invalidate
+    - mm/cma.c: switch to bitmap_zalloc() for cma bitmap allocation
+    - cma: don't quit at first error when activating reserved areas
+    - gpu/drm: ingenic: Use the plane's src_[x,y] to configure DMA length
+    - drm/ingenic: Fix incorrect assumption about plane->index
+    - drm/amd/display: Trigger modesets on MST DSC connectors
+    - drm/amd/display: Add additional config guards for DCN
+    - drm/amd/display: Fix dmesg warning from setting abm level
+    - mm/vunmap: add cond_resched() in vunmap_pmd_range
+    - EDAC: sb_edac: get rid of unused vars
+    - EDAC: skx_common: get rid of unused type var
+    - EDAC/{i7core,sb,pnd2,skx}: Fix error event severity
+    - PCI: qcom: Add missing ipq806x clocks in PCIe driver
+    - PCI: qcom: Change duplicate PCI reset to phy reset
+    - PCI: qcom: Add missing reset for ipq806x
+    - cpufreq: intel_pstate: Fix EPP setting via sysfs in active mode
+    - ALSA: usb-audio: Add capture support for Saffire 6 (USB 1.1)
+    - media: gpio-ir-tx: improve precision of transmitted signal due to scheduling
+    - block: respect queue limit of max discard segment
+    - block: virtio_blk: fix handling single range discard request
+    - drm/msm/adreno: fix updating ring fence
+    - block: Fix page_is_mergeable() for compound pages
+    - bfq: fix blkio cgroup leakage v4
+    - hwmon: (nct7904) Correct divide by 0
+    - blk-mq: insert request not through ->queue_rq into sw/scheduler queue
+    - blkcg: fix memleak for iolatency
+    - nvme-fc: Fix wrong return value in __nvme_fc_init_request()
+    - nvme: multipath: round-robin: fix single non-optimized path case
+    - null_blk: fix passing of REQ_FUA flag in null_handle_rq
+    - i2c: core: Don't fail PRP0001 enumeration when no ID table exist
+    - i2c: rcar: in slave mode, clear NACK earlier
+    - usb: gadget: f_tcm: Fix some resource leaks in some error paths
+    - spi: stm32: clear only asserted irq flags on interrupt
+    - jbd2: make sure jh have b_transaction set in refile/unfile_buffer
+    - ext4: don't BUG on inconsistent journal feature
+    - ext4: handle read only external journal device
+    - jbd2: abort journal if free a async write error metadata buffer
+    - ext4: handle option set by mount flags correctly
+    - ext4: handle error of ext4_setup_system_zone() on remount
+    - ext4: correctly restore system zone info when remount fails
+    - fs: prevent BUG_ON in submit_bh_wbc()
+    - spi: stm32h7: fix race condition at end of transfer
+    - spi: stm32: fix fifo threshold level in case of short transfer
+    - spi: stm32: fix stm32_spi_prepare_mbr in case of odd clk_rate
+    - spi: stm32: always perform registers configuration prior to transfer
+    - drm/amd/powerplay: correct Vega20 cached smu feature state
+    - drm/amd/powerplay: correct UVD/VCE PG state on custom pptable uploading
+    - drm/amd/display: Switch to immediate mode for updating infopackets
+    - netfilter: avoid ipv6 -> nf_defrag_ipv6 module dependency
+    - can: j1939: transport: j1939_xtp_rx_dat_one(): compare own packets to detect
+      corruptions
+    - ALSA: hda/realtek: Add model alc298-samsung-headphone
+    - s390/cio: add cond_resched() in the slow_eval_known_fn() loop
+    - ASoC: wm8994: Avoid attempts to read unreadable registers
+    - selftests: disable rp_filter for icmp_redirect.sh
+    - scsi: fcoe: Fix I/O path allocation
+    - scsi: ufs: Fix possible infinite loop in ufshcd_hold
+    - scsi: ufs: Improve interrupt handling for shared interrupts
+    - scsi: ufs: Clean up completed request without interrupt notification
+    - scsi: qla2xxx: Fix login timeout
+    - scsi: qla2xxx: Check if FW supports MQ before enabling
+    - scsi: qla2xxx: Fix null pointer access during disconnect from subsystem
+    - Revert "scsi: qla2xxx: Fix crash on qla2x00_mailbox_command"
+    - macvlan: validate setting of multiple remote source MAC addresses
+    - net: gianfar: Add of_node_put() before goto statement
+    - powerpc/perf: Fix soft lockups due to missed interrupt accounting
+    - arm64: Move handling of erratum 1418040 into C code
+    - arm64: Allow booting of late CPUs affected by erratum 1418040
+    - block: fix get_max_io_size()
+    - block: loop: set discard granularity and alignment for block device backed
+      loop
+    - HID: i2c-hid: Always sleep 60ms after I2C_HID_PWR_ON commands
+    - blk-mq: order adding requests to hctx->dispatch and checking SCHED_RESTART
+    - btrfs: reset compression level for lzo on remount
+    - btrfs: check the right error variable in btrfs_del_dir_entries_in_log
+    - btrfs: fix space cache memory leak after transaction abort
+    - btrfs: detect nocow for swap after snapshot delete
+    - fbcon: prevent user font height or width change from causing potential out-
+      of-bounds access
+    - USB: lvtest: return proper error code in probe
+    - vt: defer kfree() of vc_screenbuf in vc_do_resize()
+    - vt_ioctl: change VT_RESIZEX ioctl to check for error return from vc_resize()
+    - serial: samsung: Removes the IRQ not found warning
+    - serial: pl011: Fix oops on -EPROBE_DEFER
+    - serial: pl011: Don't leak amba_ports entry on driver register error
+    - serial: stm32: avoid kernel warning on absence of optional IRQ
+    - serial: 8250_exar: Fix number of ports for Commtech PCIe cards
+    - serial: 8250: change lock order in serial8250_do_startup()
+    - writeback: Protect inode->i_io_list with inode->i_lock
+    - writeback: Avoid skipping inode writeback
+    - writeback: Fix sync livelock due to b_dirty_time processing
+    - XEN uses irqdesc::irq_data_common::handler_data to store a per interrupt XEN
+      data pointer which contains XEN specific information.
+    - usb: host: xhci: fix ep context print mismatch in debugfs
+    - xhci: Do warm-reset when both CAS and XDEV_RESUME are set
+    - xhci: Always restore EP_SOFT_CLEAR_TOGGLE even if ep reset failed
+    - ARM64: vdso32: Install vdso32 from vdso_install
+    - arm64: vdso32: make vdso32 install conditional
+    - PM: sleep: core: Fix the handling of pending runtime resume requests
+    - powerpc/perf: Fix crashes with generic_compat_pmu & BHRB
+    - device property: Fix the secondary firmware node handling in
+      set_primary_fwnode()
+    - crypto: af_alg - Work around empty control messages without MSG_MORE
+    - genirq/matrix: Deal with the sillyness of for_each_cpu() on UP
+    - irqchip/stm32-exti: Avoid losing interrupts due to clearing pending bits by
+      mistake
+    - x86/hotplug: Silence APIC only after all interrupts are migrated
+    - drm/amdgpu: Fix buffer overflow in INFO ioctl
+    - drm/amdgpu/gfx10: refine mgcg setting
+    - drm/amd/powerplay: Fix hardmins not being sent to SMU for RV
+    - drm/amd/pm: correct Vega10 swctf limit setting
+    - drm/amd/pm: correct Vega12 swctf limit setting
+    - drm/amd/pm: correct Vega20 swctf limit setting
+    - drm/amd/pm: correct the thermal alert temperature limit settings
+    - USB: yurex: Fix bad gfp argument
+    - usb: uas: Add quirk for PNY Pro Elite
+    - USB: quirks: Ignore duplicate endpoint on Sound Devices MixPre-D
+    - USB: Ignore UAS for JMicron JMS567 ATA/ATAPI Bridge
+    - usb: host: ohci-exynos: Fix error handling in exynos_ohci_probe()
+    - USB: gadget: u_f: add overflow checks to VLA macros
+    - USB: gadget: f_ncm: add bounds checks to ncm_unwrap_ntb()
+    - USB: gadget: u_f: Unbreak offset calculation in VLAs
+    - USB: cdc-acm: rework notification_buffer resizing
+    - usb: storage: Add unusual_uas entry for Sony PSZ drives
+    - drm/i915: Fix cmd parser desc matching with masks
+    - usb: dwc3: gadget: Don't setup more than requested
+    - usb: dwc3: gadget: Fix handling ZLP
+    - usb: dwc3: gadget: Handle ZLP for sg requests
+    - fbmem: pull fbcon_update_vcs() out of fb_set_var()
+    - kheaders: remove unneeded 'cat' command piped to 'head' / 'tail'
+    - kheaders: optimize md5sum calculation for in-tree builds
+    - kheaders: optimize header copy for in-tree builds
+    - kheaders: remove the last bashism to allow sh to run it
+    - kheaders: explain why include/config/autoconf.h is excluded from md5sum
+    - kbuild: add variables for compression tools
+    - kbuild: fix broken builds because of GZIP,BZIP2,LZOP variables
+    - HID: hiddev: Fix slab-out-of-bounds write in hiddev_ioctl_usage()
+    - ALSA: usb-audio: Update documentation comment for MS2109 quirk
+    - io_uring: Fix NULL pointer dereference in io_sq_wq_submit_work()
+    - Linux 5.4.62
+
+  * DELL LATITUDE 5491 touchscreen doesn't work (LP: #1889446) // Focal update:
+    v5.4.62 upstream stable release (LP: #1895174)
+    - USB: quirks: Add no-lpm quirk for another Raydium touchscreen
+
+  * [NUC8CCHK][HDA-Intel - HDA Intel PCH, playback] No sound at all
+    (LP: #1875199) // Focal update: v5.4.62 upstream stable release
+    (LP: #1895174)
+    - ALSA: hda/realtek: Fix pin default on Intel NUC 8 Rugged
+
+  * Focal update: v5.4.61 upstream stable release (LP: #1893115)
+    - Documentation/llvm: add documentation on building w/ Clang/LLVM
+    - Documentation/llvm: fix the name of llvm-size
+    - net: wan: wanxl: use allow to pass CROSS_COMPILE_M68k for rebuilding
+      firmware
+    - net: wan: wanxl: use $(M68KCC) instead of $(M68KAS) for rebuilding firmware
+    - x86/boot: kbuild: allow readelf executable to be specified
+    - kbuild: remove PYTHON2 variable
+    - kbuild: remove AS variable
+    - kbuild: replace AS=clang with LLVM_IAS=1
+    - kbuild: support LLVM=1 to switch the default tools to Clang/LLVM
+    - drm/vgem: Replace opencoded version of drm_gem_dumb_map_offset()
+    - gfs2: Improve mmap write vs. punch_hole consistency
+    - gfs2: Never call gfs2_block_zero_range with an open transaction
+    - perf probe: Fix memory leakage when the probe point is not found
+    - khugepaged: khugepaged_test_exit() check mmget_still_valid()
+    - khugepaged: adjust VM_BUG_ON_MM() in __khugepaged_enter()
+    - bcache: avoid nr_stripes overflow in bcache_device_init()
+    - btrfs: export helpers for subvolume name/id resolution
+    - btrfs: don't show full path of bind mounts in subvol=
+    - btrfs: return EROFS for BTRFS_FS_STATE_ERROR cases
+    - btrfs: add wrapper for transaction abort predicate
+    - ALSA: hda/realtek: Add quirk for Samsung Galaxy Flex Book
+    - ALSA: hda/realtek: Add quirk for Samsung Galaxy Book Ion
+    - can: j1939: transport: j1939_session_tx_dat(): fix use-after-free read in
+      j1939_tp_txtimer()
+    - can: j1939: socket: j1939_sk_bind(): make sure ml_priv is allocated
+    - [Config] update config for SPI_DYNAMIC
+    - spi: Prevent adding devices below an unregistering controller
+    - romfs: fix uninitialized memory leak in romfs_dev_read()
+    - kernel/relay.c: fix memleak on destroy relay channel
+    - uprobes: __replace_page() avoid BUG in munlock_vma_page()
+    - mm: include CMA pages in lowmem_reserve at boot
+    - mm, page_alloc: fix core hung in free_pcppages_bulk()
+    - RDMA/hfi1: Correct an interlock issue for TID RDMA WRITE request
+    - ext4: fix checking of directory entry validity for inline directories
+    - jbd2: add the missing unlock_buffer() in the error path of
+      jbd2_write_superblock()
+    - scsi: zfcp: Fix use-after-free in request timeout handlers
+    - drm/amdgpu/display: use GFP_ATOMIC in dcn20_validate_bandwidth_internal
+    - drm/amd/display: Fix EDID parsing after resume from suspend
+    - drm/amd/display: fix pow() crashing when given base 0
+    - kthread: Do not preempt current task if it is going to call schedule()
+    - opp: Enable resources again if they were disabled earlier
+    - scsi: ufs: Add DELAY_BEFORE_LPM quirk for Micron devices
+    - scsi: target: tcmu: Fix crash in tcmu_flush_dcache_range on ARM
+    - media: budget-core: Improve exception handling in budget_register()
+    - rtc: goldfish: Enable interrupt in set_alarm() when necessary
+    - media: vpss: clean up resources in init
+    - Input: psmouse - add a newline when printing 'proto' by sysfs
+    - MIPS: Fix unable to reserve memory for Crash kernel
+    - m68knommu: fix overwriting of bits in ColdFire V3 cache control
+    - svcrdma: Fix another Receive buffer leak
+    - xfs: fix inode quota reservation checks
+    - drm/ttm: fix offset in VMAs with a pg_offs in ttm_bo_vm_access
+    - jffs2: fix UAF problem
+    - ceph: fix use-after-free for fsc->mdsc
+    - swiotlb-xen: use vmalloc_to_page on vmalloc virt addresses
+    - cpufreq: intel_pstate: Fix cpuinfo_max_freq when MSR_TURBO_RATIO_LIMIT is 0
+    - scsi: libfc: Free skb in fc_disc_gpn_id_resp() for valid cases
+    - virtio_ring: Avoid loop when vq is broken in virtqueue_poll
+    - media: camss: fix memory leaks on error handling paths in probe
+    - tools/testing/selftests/cgroup/cgroup_util.c: cg_read_strcmp: fix null
+      pointer dereference
+    - xfs: Fix UBSAN null-ptr-deref in xfs_sysfs_init
+    - alpha: fix annotation of io{read,write}{16,32}be()
+    - fs/signalfd.c: fix inconsistent return codes for signalfd4
+    - ext4: fix potential negative array index in do_split()
+    - ext4: don't allow overlapping system zones
+    - netfilter: nf_tables: nft_exthdr: the presence return value should be
+      little-endian
+    - spi: stm32: fixes suspend/resume management
+    - ASoC: q6afe-dai: mark all widgets registers as SND_SOC_NOPM
+    - ASoC: q6routing: add dummy register read/write function
+    - bpf: sock_ops sk access may stomp registers when dst_reg = src_reg
+    - can: j1939: fix kernel-infoleak in j1939_sk_sock2sockaddr_can()
+    - can: j1939: transport: j1939_simple_recv(): ignore local J1939 messages send
+      not by J1939 stack
+    - can: j1939: transport: add j1939_session_skb_find_by_offset() function
+    - i40e: Set RX_ONLY mode for unicast promiscuous on VLAN
+    - i40e: Fix crash during removing i40e driver
+    - net: fec: correct the error path for regulator disable in probe
+    - bonding: show saner speed for broadcast mode
+    - can: j1939: fix support for multipacket broadcast message
+    - can: j1939: cancel rxtimer on multipacket broadcast session complete
+    - can: j1939: abort multipacket broadcast session when timeout occurs
+    - can: j1939: add rxtimer for multipacket broadcast session
+    - bonding: fix a potential double-unregister
+    - s390/runtime_instrumentation: fix storage key handling
+    - s390/ptrace: fix storage key handling
+    - ASoC: msm8916-wcd-analog: fix register Interrupt offset
+    - ASoC: intel: Fix memleak in sst_media_open
+    - vfio/type1: Add proper error unwind for vfio_iommu_replay()
+    - kvm: x86: Toggling CR4.SMAP does not load PDPTEs in PAE mode
+    - kvm: x86: Toggling CR4.PKE does not load PDPTEs in PAE mode
+    - Revert "scsi: qla2xxx: Disable T10-DIF feature with FC-NVMe during probe"
+    - kconfig: qconf: do not limit the pop-up menu to the first row
+    - kconfig: qconf: fix signal connection to invalid slots
+    - efi: avoid error message when booting under Xen
+    - Fix build error when CONFIG_ACPI is not set/enabled:
+    - RDMA/bnxt_re: Do not add user qps to flushlist
+    - afs: Fix NULL deref in afs_dynroot_depopulate()
+    - bonding: fix active-backup failover for current ARP slave
+    - net: ena: Prevent reset after device destruction
+    - net: gemini: Fix missing free_netdev() in error path of
+      gemini_ethernet_port_probe()
+    - hv_netvsc: Fix the queue_mapping in netvsc_vf_xmit()
+    - net: dsa: b53: check for timeout
+    - powerpc/pseries: Do not initiate shutdown when system is running on UPS
+    - efi: add missed destroy_workqueue when efisubsys_init fails
+    - epoll: Keep a reference on files added to the check list
+    - do_epoll_ctl(): clean the failure exits up a bit
+    - mm/hugetlb: fix calculation of adjust_range_if_pmd_sharing_possible
+    - xen: don't reschedule in preemption off sections
+    - KVM: Pass MMU notifier range flags to kvm_unmap_hva_range()
+    - KVM: arm64: Only reschedule if MMU_NOTIFIER_RANGE_BLOCKABLE is not set
+    - Linux 5.4.61
+
+  * [UBUNTU 20.04] zPCI device hot-plug during boot may result in unusable
+    device (LP: #1893778)
+    - s390/pci: ignore stale configuration request event
+
+  * [SRU] [Focal/OEM-5.6/Groovy]Fix AMD usb host controller lost after stress S3
+    (LP: #1893914)
+    - SAUCE: xhci: workaround for S3 issue on AMD SNPS 3.0 xHC
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Fri, 18 Sep 2020 10:17:00 +0200
+
+linux (5.4.0-48.52) focal; urgency=medium
+
+  * focal/linux: 5.4.0-48.52 -proposed tracker (LP: #1894654)
+
+  * mm/slub kernel oops on focal kernel 5.4.0-45 (LP: #1895109)
+    - SAUCE: Revert "mm/slub: fix a memory leak in sysfs_slab_add()"
+
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+    - update dkms package versions
+
+  * Introduce the new NVIDIA 450-server and the 450 UDA series (LP: #1887674)
+    - [packaging] add signed modules for nvidia 450 and 450-server
+
+  * [UBUNTU 20.04] zPCI attach/detach issues with PF/VF linking support
+    (LP: #1892849)
+    - s390/pci: fix zpci_bus_link_virtfn()
+    - s390/pci: re-introduce zpci_remove_device()
+    - s390/pci: fix PF/VF linking on hot plug
+
+  * [UBUNTU 20.04] kernel: s390/cpum_cf,perf: changeDFLT_CCERROR counter name
+    (LP: #1891454)
+    - s390/cpum_cf, perf: change DFLT_CCERROR counter name
+
+  * [UBUNTU 20.04] zPCI: Enabling of a reserved PCI function regression
+    introduced by multi-function support (LP: #1891437)
+    - s390/pci: fix enabling a reserved PCI function
+
+  * CVE-2020-12888
+    - vfio/type1: Support faulting PFNMAP vmas
+    - vfio-pci: Fault mmaps to enable vma tracking
+    - vfio-pci: Invalidate mmaps and block MMIO access on disabled memory
+
+  *  [Hyper-V] VSS and File Copy daemons intermittently fails to start
+    (LP: #1891224)
+    - [Packaging] Bind hv_vss_daemon startup to hv_vss device
+    - [Packaging] bind hv_fcopy_daemon startup to hv_fcopy device
+
+  * alsa/hdmi: support nvidia mst hdmi/dp audio (LP: #1867704)
+    - ALSA: hda - Rename snd_hda_pin_sense to snd_hda_jack_pin_sense
+    - ALSA: hda - Add DP-MST jack support
+    - ALSA: hda - Add DP-MST support for non-acomp codecs
+    - ALSA: hda - Add DP-MST support for NVIDIA codecs
+    - ALSA: hda: hdmi - fix regression in connect list handling
+    - ALSA: hda: hdmi - fix kernel oops caused by invalid PCM idx
+    - ALSA: hda: hdmi - preserve non-MST PCM routing for Intel platforms
+    - ALSA: hda: hdmi - Keep old slot assignment behavior for Intel platforms
+    - ALSA: hda - Fix DP-MST support for NVIDIA codecs
+
+  * Focal update: v5.4.60 upstream stable release (LP: #1892899)
+    - smb3: warn on confusing error scenario with sec=krb5
+    - genirq/affinity: Make affinity setting if activated opt-in
+    - genirq/PM: Always unlock IRQ descriptor in rearm_wake_irq()
+    - PCI: hotplug: ACPI: Fix context refcounting in acpiphp_grab_context()
+    - PCI: Add device even if driver attach failed
+    - PCI: qcom: Define some PARF params needed for ipq8064 SoC
+    - PCI: qcom: Add support for tx term offset for rev 2.1.0
+    - btrfs: allow use of global block reserve for balance item deletion
+    - btrfs: free anon block device right after subvolume deletion
+    - btrfs: don't allocate anonymous block device for user invisible roots
+    - btrfs: ref-verify: fix memory leak in add_block_entry
+    - btrfs: stop incremening log_batch for the log root tree when syncing log
+    - btrfs: remove no longer needed use of log_writers for the log root tree
+    - btrfs: don't traverse into the seed devices in show_devname
+    - btrfs: open device without device_list_mutex
+    - btrfs: move the chunk_mutex in btrfs_read_chunk_tree
+    - btrfs: relocation: review the call sites which can be interrupted by signal
+    - btrfs: add missing check for nocow and compression inode flags
+    - btrfs: avoid possible signal interruption of btrfs_drop_snapshot() on
+      relocation tree
+    - btrfs: sysfs: use NOFS for device creation
+    - btrfs: don't WARN if we abort a transaction with EROFS
+    - btrfs: fix race between page release and a fast fsync
+    - btrfs: fix messages after changing compression level by remount
+    - btrfs: only search for left_info if there is no right_info in
+      try_merge_free_space
+    - btrfs: inode: fix NULL pointer dereference if inode doesn't need compression
+    - btrfs: fix memory leaks after failure to lookup checksums during inode
+      logging
+    - btrfs: make sure SB_I_VERSION doesn't get unset by remount
+    - btrfs: fix return value mixup in btrfs_get_extent
+    - arm64: perf: Correct the event index in sysfs
+    - dt-bindings: iio: io-channel-mux: Fix compatible string in example code
+    - iio: dac: ad5592r: fix unbalanced mutex unlocks in ad5592r_read_raw()
+    - xtensa: add missing exclusive access state management
+    - xtensa: fix xtensa_pmu_setup prototype
+    - cifs: Fix leak when handling lease break for cached root fid
+    - powerpc/ptdump: Fix build failure in hashpagetable.c
+    - powerpc: Allow 4224 bytes of stack expansion for the signal frame
+    - powerpc: Fix circular dependency between percpu.h and mmu.h
+    - pinctrl: ingenic: Enhance support for IRQ_TYPE_EDGE_BOTH
+    - media: vsp1: dl: Fix NULL pointer dereference on unbind
+    - net: ethernet: stmmac: Disable hardware multicast filter
+    - net: stmmac: dwmac1000: provide multicast filter fallback
+    - net/compat: Add missing sock updates for SCM_RIGHTS
+    - md/raid5: Fix Force reconstruct-write io stuck in degraded raid5
+    - bcache: allocate meta data pages as compound pages
+    - bcache: fix overflow in offset_to_stripe()
+    - mac80211: fix misplaced while instead of if
+    - driver core: Avoid binding drivers to dead devices
+    - MIPS: CPU#0 is not hotpluggable
+    - MIPS: qi_lb60: Fix routing to audio amplifier
+    - ext2: fix missing percpu_counter_inc
+    - khugepaged: collapse_pte_mapped_thp() flush the right range
+    - khugepaged: collapse_pte_mapped_thp() protect the pmd lock
+    - ocfs2: change slot number type s16 to u16
+    - mm/page_counter.c: fix protection usage propagation
+    - mm/memory_hotplug: fix unpaired mem_hotplug_begin/done
+    - ftrace: Setup correct FTRACE_FL_REGS flags for module
+    - kprobes: Fix NULL pointer dereference at kprobe_ftrace_handler
+    - tracing/hwlat: Honor the tracing_cpumask
+    - tracing: Use trace_sched_process_free() instead of exit() for pid tracing
+    - tracing: Move pipe reference to trace array instead of current_tracer
+    - watchdog: f71808e_wdt: indicate WDIOF_CARDRESET support in
+      watchdog_info.options
+    - watchdog: f71808e_wdt: remove use of wrong watchdog_info option
+    - watchdog: f71808e_wdt: clear watchdog timeout occurred flag
+    - ceph: set sec_context xattr on symlink creation
+    - ceph: handle zero-length feature mask in session messages
+    - pseries: Fix 64 bit logical memory block panic
+    - module: Correctly truncate sysfs sections output
+    - perf intel-pt: Fix FUP packet state
+    - perf intel-pt: Fix duplicate branch after CBR
+    - remoteproc: qcom: q6v5: Update running state before requesting stop
+    - remoteproc: qcom_q6v5_mss: Validate MBA firmware size before load
+    - remoteproc: qcom_q6v5_mss: Validate modem blob firmware size before load
+    - drm/imx: imx-ldb: Disable both channels for split mode in enc->disable()
+    - orangefs: get rid of knob code...
+    - pinctrl: ingenic: Properly detect GPIO direction when configured for IRQ
+    - crypto: algif_aead - Only wake up when ctx->more is zero
+    - mfd: arizona: Ensure 32k clock is put on driver unbind and error
+    - octeontx2-af: change (struct qmem)->entry_sz from u8 to u16
+    - mtd: rawnand: fsl_upm: Remove unused mtd var
+    - platform/chrome: cros_ec_ishtp: Fix a double-unlock issue
+    - RDMA/ipoib: Return void from ipoib_ib_dev_stop()
+    - RDMA/ipoib: Fix ABBA deadlock with ipoib_reap_ah()
+    - media: rockchip: rga: Introduce color fmt macros and refactor CSC mode logic
+    - media: rockchip: rga: Only set output CSC mode for RGB input
+    - IB/uverbs: Set IOVA on IB MR in uverbs layer
+    - selftests/bpf: Test_progs indicate to shell on non-actions
+    - selftests/bpf: test_progs use another shell exit on non-actions
+    - USB: serial: ftdi_sio: make process-packet buffer unsigned
+    - USB: serial: ftdi_sio: clean up receive processing
+    - crypto: af_alg - Fix regression on empty requests
+    - devres: keep both device name and resource name in pretty name
+    - RDMA/counter: Only bind user QPs in auto mode
+    - RDMA/counter: Allow manually bind QPs with different pids to same counter
+    - mmc: renesas_sdhi_internal_dmac: clean up the code for dma complete
+    - crypto: caam - Remove broken arc4 support
+    - gpu: ipu-v3: image-convert: Combine rotate/no-rotate irq handlers
+    - gpu: ipu-v3: image-convert: Wait for all EOFs before completing a tile
+    - dm rq: don't call blk_mq_queue_stopped() in dm_stop_queue()
+    - clk: actions: Fix h_clk for Actions S500 SoC
+    - selftests/powerpc: ptrace-pkey: Rename variables to make it easier to follow
+      code
+    - selftests/powerpc: ptrace-pkey: Update the test to mark an invalid pkey
+      correctly
+    - selftests/powerpc: ptrace-pkey: Don't update expected UAMOR value
+    - iommu/omap: Check for failure of a call to omap_iommu_dump_ctx
+    - clk: qcom: gcc: fix sm8150 GPU and NPU clocks
+    - clk: qcom: clk-alpha-pll: remove unused/incorrect PLL_CAL_VAL
+    - iommu/vt-d: Enforce PASID devTLB field mask
+    - i2c: rcar: slave: only send STOP event when we have been addressed
+    - clk: qcom: gcc-sdm660: Fix up gcc_mss_mnoc_bimc_axi_clk
+    - clk: clk-atlas6: fix return value check in atlas6_clk_init()
+    - pwm: bcm-iproc: handle clk_get_rate() return
+    - tools build feature: Use CC and CXX from parent
+    - i2c: rcar: avoid race when unregistering slave
+    - nfs: ensure correct writeback errors are returned on close()
+    - ubifs: Fix wrong orphan node deletion in ubifs_jnl_update|rename
+    - clk: bcm2835: Do not use prediv with bcm2711's PLLs
+    - libnvdimm/security: fix a typo
+    - libnvdimm/security: ensure sysfs poll thread woke up and fetch updated attr
+    - openrisc: Fix oops caused when dumping stack
+    - scsi: lpfc: nvmet: Avoid hang / use-after-free again when destroying
+      targetport
+    - nfs: nfs_file_write() should check for writeback errors
+    - watchdog: initialize device before misc_register
+    - md-cluster: Fix potential error pointer dereference in resize_bitmaps()
+    - x86/tsr: Fix tsc frequency enumeration bug on Lightning Mountain SoC
+    - Input: sentelic - fix error return when fsp_reg_write fails
+    - recordmcount: Fix build failure on non arm64
+    - drm/vmwgfx: Use correct vmw_legacy_display_unit pointer
+    - drm/vmwgfx: Fix two list_for_each loop exit tests
+    - net: qcom/emac: add missed clk_disable_unprepare in error path of
+      emac_clks_phase1_init
+    - nfs: Fix getxattr kernel panic and memory overflow
+    - fs/minix: set s_maxbytes correctly
+    - fs/minix: fix block limit check for V1 filesystems
+    - fs/minix: remove expected error message in block_to_path()
+    - fs/ufs: avoid potential u32 multiplication overflow
+    - test_kmod: avoid potential double free in trigger_config_run_type()
+    - i2c: iproc: fix race between client unreg and isr
+    - mfd: dln2: Run event handler loop under spinlock
+    - crypto: algif_aead - fix uninitialized ctx->init
+    - ALSA: echoaudio: Fix potential Oops in snd_echo_resume()
+    - perf bench mem: Always memset source before memcpy
+    - tools build feature: Quote CC and CXX for their arguments
+    - perf/x86/rapl: Fix missing psys sysfs attributes
+    - sh: landisk: Add missing initialization of sh_io_port_base
+    - khugepaged: retract_page_tables() remember to test exit
+    - arm64: dts: marvell: espressobin: add ethernet alias
+    - drm/panfrost: Use kvfree() to free bo->sgts
+    - drm: Added orientation quirk for ASUS tablet model T103HAF
+    - drm: fix drm_dp_mst_port refcount leaks in drm_dp_mst_allocate_vcpi
+    - drm/amdgpu: Fix bug where DPM is not enabled after hibernate and resume
+    - drm/amd/display: dchubbub p-state warning during surface planes switch
+    - Linux 5.4.60
+    - kprobes: Fix compiler warning for !CONFIG_KPROBES_ON_FTRACE
+
+  * Focal update: v5.4.59 upstream stable release (LP: #1892417)
+    - tracepoint: Mark __tracepoint_string's __used
+    - HID: input: Fix devices that return multiple bytes in battery report
+    - nvme: add a Identify Namespace Identification Descriptor list quirk
+    - fs/io_uring.c: Fix uninitialized variable is referenced in io_submit_sqe
+    - clk: qcom: clk-rpmh: Wait for completion when enabling clocks
+    - x86/mce/inject: Fix a wrong assignment of i_mce.status
+    - sched/fair: Fix NOHZ next idle balance
+    - sched: correct SD_flags returned by tl->sd_flags()
+    - arm64: dts: rockchip: fix rk3368-lion gmac reset gpio
+    - arm64: dts: rockchip: fix rk3399-puma vcc5v0-host gpio
+    - arm64: dts: rockchip: fix rk3399-puma gmac reset gpio
+    - EDAC: Fix reference count leaks
+    - crc-t10dif: Fix potential crypto notify dead-lock
+    - arm64: dts: qcom: msm8916: Replace invalid bias-pull-none property
+    - crypto: ccree - fix resource leak on error path
+    - ARM: exynos: MCPM: Restore big.LITTLE cpuidle support
+    - firmware: arm_scmi: Fix SCMI genpd domain probing
+    - arm64: dts: exynos: Fix silent hang after boot on Espresso
+    - sched/uclamp: Fix initialization of struct uclamp_rq
+    - clk: scmi: Fix min and max rate when registering clocks with discrete rates
+    - m68k: mac: Don't send IOP message until channel is idle
+    - m68k: mac: Fix IOP status/control register writes
+    - platform/x86: intel-hid: Fix return value check in check_acpi_dev()
+    - platform/x86: intel-vbtn: Fix return value check in check_acpi_dev()
+    - ARM: dts: gose: Fix ports node name for adv7180
+    - ARM: dts: gose: Fix ports node name for adv7612
+    - ARM: at91: pm: add missing put_device() call in at91_pm_sram_init()
+    - ARM: dts: sunxi: bananapi-m2-plus-v1.2: Add regulator supply to all CPU
+      cores
+    - ARM: dts: sunxi: bananapi-m2-plus-v1.2: Fix CPU supply voltages
+    - spi: lantiq: fix: Rx overflow error in full duplex mode
+    - tpm: Require that all digests are present in TCG_PCR_EVENT2 structures
+    - recordmcount: only record relocation of type R_AARCH64_CALL26 on arm64.
+    - regulator: fix memory leak on error path of regulator_register()
+    - io_uring: fix sq array offset calculation
+    - spi: rockchip: Fix error in SPI slave pio read
+    - ARM: socfpga: PM: add missing put_device() call in
+      socfpga_setup_ocram_self_refresh()
+    - iocost: Fix check condition of iocg abs_vdebt
+    - irqchip/ti-sci-inta: Fix return value about devm_ioremap_resource()
+    - seccomp: Fix ioctl number for SECCOMP_IOCTL_NOTIF_ID_VALID
+    - md: raid0/linear: fix dereference before null check on pointer mddev
+    - nvme-tcp: fix controller reset hang during traffic
+    - nvme-rdma: fix controller reset hang during traffic
+    - nvme-multipath: fix logic for non-optimized paths
+    - nvme-multipath: do not fall back to __nvme_find_path() for non-optimized
+      paths
+    - drm/tilcdc: fix leak & null ref in panel_connector_get_modes
+    - soc: qcom: rpmh-rsc: Set suppress_bind_attrs flag
+    - Bluetooth: add a mutex lock to avoid UAF in do_enale_set
+    - loop: be paranoid on exit and prevent new additions / removals
+    - fs/btrfs: Add cond_resched() for try_release_extent_mapping() stalls
+    - drm/amdgpu: avoid dereferencing a NULL pointer
+    - drm/radeon: Fix reference count leaks caused by pm_runtime_get_sync
+    - crypto: aesni - Fix build with LLVM_IAS=1
+    - video: fbdev: savage: fix memory leak on error handling path in probe
+    - video: fbdev: neofb: fix memory leak in neo_scan_monitor()
+    - bus: ti-sysc: Add missing quirk flags for usb_host_hs
+    - md-cluster: fix wild pointer of unlock_all_bitmaps()
+    - drm/nouveau/kms/nv50-: Fix disabling dithering
+    - arm64: dts: hisilicon: hikey: fixes to comply with adi, adv7533 DT binding
+    - drm/etnaviv: fix ref count leak via pm_runtime_get_sync
+    - drm/nouveau: fix reference count leak in nouveau_debugfs_strap_peek
+    - drm/nouveau: fix multiple instances of reference count leaks
+    - mmc: sdhci-cadence: do not use hardware tuning for SD mode
+    - btrfs: fix lockdep splat from btrfs_dump_space_info
+    - usb: mtu3: clear dual mode of u3port when disable device
+    - drm: msm: a6xx: fix gpu failure after system resume
+    - drm/msm: Fix a null pointer access in msm_gem_shrinker_count()
+    - drm/debugfs: fix plain echo to connector "force" attribute
+    - drm/radeon: disable AGP by default
+    - irqchip/irq-mtk-sysirq: Replace spinlock with raw_spinlock
+    - mm/mmap.c: Add cond_resched() for exit_mmap() CPU stalls
+    - drm/amdgpu/display bail early in dm_pp_get_static_clocks
+    - drm/amd/powerplay: fix compile error with ARCH=arc
+    - bpf: Fix fds_example SIGSEGV error
+    - brcmfmac: keep SDIO watchdog running when console_interval is non-zero
+    - brcmfmac: To fix Bss Info flag definition Bug
+    - brcmfmac: set state of hanger slot to FREE when flushing PSQ
+    - platform/x86: asus-nb-wmi: add support for ASUS ROG Zephyrus G14 and G15
+    - iwlegacy: Check the return value of pcie_capability_read_*()
+    - gpu: host1x: debug: Fix multiple channels emitting messages simultaneously
+    - ionic: update eid test for overflow
+    - mmc: sdhci-pci-o2micro: Bug fix for O2 host controller Seabird1
+    - usb: gadget: net2280: fix memory leak on probe error handling paths
+    - bdc: Fix bug causing crash after multiple disconnects
+    - usb: bdc: Halt controller on suspend
+    - dyndbg: fix a BUG_ON in ddebug_describe_flags
+    - bcache: fix super block seq numbers comparision in register_cache_set()
+    - ACPICA: Do not increment operation_region reference counts for field units
+    - drm/msm: ratelimit crtc event overflow error
+    - drm/gem: Fix a leak in drm_gem_objects_lookup()
+    - drm/bridge: ti-sn65dsi86: Clear old error bits before AUX transfers
+    - agp/intel: Fix a memory leak on module initialisation failure
+    - mwifiex: Fix firmware filename for sd8977 chipset
+    - mwifiex: Fix firmware filename for sd8997 chipset
+    - btmrvl: Fix firmware filename for sd8977 chipset
+    - btmrvl: Fix firmware filename for sd8997 chipset
+    - video: fbdev: sm712fb: fix an issue about iounmap for a wrong address
+    - console: newport_con: fix an issue about leak related system resources
+    - video: pxafb: Fix the function used to balance a 'dma_alloc_coherent()' call
+    - ath10k: Acquire tx_lock in tx error paths
+    - iio: improve IIO_CONCENTRATION channel type description
+    - drm/etnaviv: Fix error path on failure to enable bus clk
+    - drm/arm: fix unintentional integer overflow on left shift
+    - clk: bcm63xx-gate: fix last clock availability
+    - leds: lm355x: avoid enum conversion warning
+    - Bluetooth: btusb: fix up firmware download sequence
+    - Bluetooth: btmtksdio: fix up firmware download sequence
+    - media: cxusb-analog: fix V4L2 dependency
+    - media: marvell-ccic: Add missed v4l2_async_notifier_cleanup()
+    - media: omap3isp: Add missed v4l2_ctrl_handler_free() for
+      preview_init_entities()
+    - ASoC: SOF: nocodec: add missing .owner field
+    - ASoC: Intel: bxt_rt298: add missing .owner field
+    - scsi: cumana_2: Fix different dev_id between request_irq() and free_irq()
+    - drm/mipi: use dcs write for mipi_dsi_dcs_set_tear_scanline
+    - cxl: Fix kobject memleak
+    - drm/radeon: fix array out-of-bounds read and write issues
+    - staging: vchiq_arm: Add a matching unregister call
+    - iavf: fix error return code in iavf_init_get_resources()
+    - iavf: Fix updating statistics
+    - RDMA/core: Fix bogus WARN_ON during ib_unregister_device_queued()
+    - scsi: powertec: Fix different dev_id between request_irq() and free_irq()
+    - scsi: eesox: Fix different dev_id between request_irq() and free_irq()
+    - ipvs: allow connection reuse for unconfirmed conntrack
+    - media: firewire: Using uninitialized values in node_probe()
+    - media: exynos4-is: Add missed check for pinctrl_lookup_state()
+    - media: cros-ec-cec: do not bail on device_init_wakeup failure
+    - xfs: don't eat an EIO/ENOSPC writeback error when scrubbing data fork
+    - xfs: fix reflink quota reservation accounting error
+    - RDMA/rxe: Skip dgid check in loopback mode
+    - PCI: Fix pci_cfg_wait queue locking problem
+    - drm/stm: repair runtime power management
+    - kobject: Avoid premature parent object freeing in kobject_cleanup()
+    - leds: core: Flush scheduled work for system suspend
+    - drm: panel: simple: Fix bpc for LG LB070WV8 panel
+    - phy: exynos5-usbdrd: Calibrating makes sense only for USB2.0 PHY
+    - drm/bridge: sil_sii8620: initialize return of sii8620_readb
+    - scsi: scsi_debug: Add check for sdebug_max_queue during module init
+    - mwifiex: Prevent memory corruption handling keys
+    - kernfs: do not call fsnotify() with name without a parent
+    - powerpc/rtas: don't online CPUs for partition suspend
+    - powerpc/vdso: Fix vdso cpu truncation
+    - RDMA/qedr: SRQ's bug fixes
+    - RDMA/rxe: Prevent access to wr->next ptr afrer wr is posted to send queue
+    - ima: Have the LSM free its audit rule
+    - staging: rtl8192u: fix a dubious looking mask before a shift
+    - ASoC: meson: fixes the missed kfree() for axg_card_add_tdm_loopback
+    - PCI/ASPM: Add missing newline in sysfs 'policy'
+    - phy: renesas: rcar-gen3-usb2: move irq registration to init
+    - powerpc/book3s64/pkeys: Use PVR check instead of cpu feature
+    - drm/imx: fix use after free
+    - drm/imx: tve: fix regulator_disable error path
+    - gpu: ipu-v3: Restore RGB32, BGR32
+    - spi: lantiq-ssc: Fix warning by using WQ_MEM_RECLAIM
+    - USB: serial: iuu_phoenix: fix led-activity helpers
+    - usb: core: fix quirks_param_set() writing to a const pointer
+    - thermal: ti-soc-thermal: Fix reversed condition in
+      ti_thermal_expose_sensor()
+    - coresight: tmc: Fix TMC mode read in tmc_read_unprepare_etb()
+    - powerpc/perf: Fix missing is_sier_aviable() during build
+    - mt76: mt7615: fix potential memory leak in mcu message handler
+    - phy: armada-38x: fix NETA lockup when repeatedly switching speeds
+    - MIPS: OCTEON: add missing put_device() call in dwc3_octeon_device_init()
+    - usb: dwc2: Fix error path in gadget registration
+    - usb: gadget: f_uac2: fix AC Interface Header Descriptor wTotalLength
+    - scsi: megaraid_sas: Clear affinity hint
+    - scsi: mesh: Fix panic after host or bus reset
+    - net: dsa: mv88e6xxx: MV88E6097 does not support jumbo configuration
+    - macintosh/via-macii: Access autopoll_devs when inside lock
+    - PCI: cadence: Fix updating Vendor ID and Subsystem Vendor ID register
+    - RDMA/core: Fix return error value in _ib_modify_qp() to negative
+    - Smack: fix another vsscanf out of bounds
+    - Smack: prevent underflow in smk_set_cipso()
+    - power: supply: check if calc_soc succeeded in pm860x_init_battery
+    - Bluetooth: hci_h5: Set HCI_UART_RESET_ON_INIT to correct flags
+    - Bluetooth: hci_serdev: Only unregister device if it was registered
+    - net: dsa: rtl8366: Fix VLAN semantics
+    - net: dsa: rtl8366: Fix VLAN set-up
+    - xfs: fix inode allocation block res calculation precedence
+    - selftests/powerpc: Squash spurious errors due to device removal
+    - powerpc/32s: Fix CONFIG_BOOK3S_601 uses
+    - powerpc/boot: Fix CONFIG_PPC_MPC52XX references
+    - selftests/powerpc: Fix CPU affinity for child process
+    - RDMA/netlink: Remove CAP_NET_RAW check when dump a raw QP
+    - PCI: Release IVRS table in AMD ACS quirk
+    - [Config] update config for ARMADA_AP_CPU_CLK
+    - cpufreq: ap806: fix cpufreq driver needs ap cpu clk
+    - selftests/powerpc: Fix online CPU selection
+    - ASoC: meson: axg-tdm-interface: fix link fmt setup
+    - ASoC: meson: axg-tdmin: fix g12a skew
+    - ASoC: meson: axg-tdm-formatters: fix sclk inversion
+    - ASoC: fsl_sai: Fix value of FSL_SAI_CR1_RFW_MASK
+    - s390/qeth: don't process empty bridge port events
+    - ice: Graceful error handling in HW table calloc failure
+    - rtw88: fix LDPC field for RA info
+    - rtw88: fix short GI capability based on current bandwidth
+    - rtw88: coex: only skip coex triggered by BT info
+    - wl1251: fix always return 0 error
+    - tools, build: Propagate build failures from tools/build/Makefile.build
+    - tools, bpftool: Fix wrong return value in do_dump()
+    - net/mlx5: DR, Change push vlan action sequence
+    - net/mlx5: Delete extra dump stack that gives nothing
+    - net: ethernet: aquantia: Fix wrong return value
+    - liquidio: Fix wrong return value in cn23xx_get_pf_num()
+    - net: spider_net: Fix the size used in a 'dma_free_coherent()' call
+    - fsl/fman: use 32-bit unsigned integer
+    - fsl/fman: fix dereference null return value
+    - fsl/fman: fix unreachable code
+    - fsl/fman: check dereferencing null pointer
+    - fsl/fman: fix eth hash table allocation
+    - net: thunderx: initialize VF's mailbox mutex before first usage
+    - dlm: Fix kobject memleak
+    - ocfs2: fix unbalanced locking
+    - pinctrl-single: fix pcs_parse_pinconf() return value
+    - svcrdma: Fix page leak in svc_rdma_recv_read_chunk()
+    - x86/fsgsbase/64: Fix NULL deref in 86_fsgsbase_read_task
+    - crypto: aesni - add compatibility with IAS
+    - af_packet: TPACKET_V3: fix fill status rwlock imbalance
+    - drivers/net/wan/lapbether: Added needed_headroom and a skb->len check
+    - net: Fix potential memory leak in proto_register()
+    - net/nfc/rawsock.c: add CAP_NET_RAW check.
+    - net: phy: fix memory leak in device-create error path
+    - net: Set fput_needed iff FDPUT_FPUT is set
+    - net/tls: Fix kmap usage
+    - vmxnet3: use correct tcp hdr length when packet is encapsulated
+    - net: refactor bind_bucket fastreuse into helper
+    - net: initialize fastreuse on inet_inherit_port
+    - USB: serial: cp210x: re-enable auto-RTS on open
+    - USB: serial: cp210x: enable usb generic throttle/unthrottle
+    - ALSA: hda - fix the micmute led status for Lenovo ThinkCentre AIO
+    - ALSA: usb-audio: Creative USB X-Fi Pro SB1095 volume knob support
+    - ALSA: usb-audio: fix overeager device match for MacroSilicon MS2109
+    - ALSA: usb-audio: work around streaming quirk for MacroSilicon MS2109
+    - 9p: Fix memory leak in v9fs_mount
+    - media: media-request: Fix crash if memory allocation fails
+    - drm/ttm/nouveau: don't call tt destroy callback on alloc failure.
+    - io_uring: set ctx sq/cq entry count earlier
+    - NFS: Don't move layouts to plh_return_segs list while in use
+    - NFS: Don't return layout segments that are in use
+    - cpufreq: Fix locking issues with governors
+    - cpufreq: dt: fix oops on armada37xx
+    - include/asm-generic/vmlinux.lds.h: align ro_after_init
+    - spi: spidev: Align buffers for DMA
+    - mtd: rawnand: qcom: avoid write to unavailable register
+    - erofs: fix extended inode could cross boundary
+    - Revert "parisc: Drop LDCW barrier in CAS code when running UP"
+    - Revert "parisc: Use ldcw instruction for SMP spinlock release barrier"
+    - Revert "parisc: Revert "Release spinlocks using ordered store""
+    - parisc: Do not use an ordered store in pa_tlb_lock()
+    - parisc: Implement __smp_store_release and __smp_load_acquire barriers
+    - parisc: mask out enable and reserved bits from sba imask
+    - ARM: 8992/1: Fix unwind_frame for clang-built kernels
+    - irqdomain/treewide: Free firmware node after domain removal
+    - ALSA: usb-audio: add quirk for Pioneer DDJ-RB
+    - tpm: Unify the mismatching TPM space buffer sizes
+    - pstore: Fix linking when crypto API disabled
+    - crypto: hisilicon - don't sleep of CRYPTO_TFM_REQ_MAY_SLEEP was not
+      specified
+    - crypto: qat - fix double free in qat_uclo_create_batch_init_list
+    - crypto: ccp - Fix use of merged scatterlists
+    - crypto: cpt - don't sleep of CRYPTO_TFM_REQ_MAY_SLEEP was not specified
+    - bitfield.h: don't compile-time validate _val in FIELD_FIT
+    - fs/minix: check return value of sb_getblk()
+    - fs/minix: don't allow getting deleted inodes
+    - fs/minix: reject too-large maximum file size
+    - xen/balloon: fix accounting in alloc_xenballooned_pages error path
+    - xen/balloon: make the balloon wait interruptible
+    - xen/gntdev: Fix dmabuf import with non-zero sgt offset
+    - s390/dasd: fix inability to use DASD with DIAG driver
+    - s390/gmap: improve THP splitting
+    - io_uring: Fix NULL pointer dereference in loop_rw_iter()
+    - Linux 5.4.59
+
+  * Regression on NFS: unable to handle page fault in mempool_alloc_slab
+    (LP: #1886277) // Focal update: v5.4.59 upstream stable release
+    (LP: #1892417)
+    - SUNRPC: Fix ("SUNRPC: Add "@len" parameter to gss_unwrap()")
+
+  * Focal update: v5.4.59 upstream stable release (LP: #1892417) //
+    CVE-2019-19770 which shows this issue is not a core debugfs issue, but
+    - blktrace: fix debugfs use after free
+
+  * update ENA driver for LLQ acceleration mode, new hw support (LP: #1890845)
+    - net: ena: change num_queues to num_io_queues for clarity and consistency
+    - net: ena: multiple queue creation related cleanups
+    - net: ena: ethtool: get_channels: use combined only
+    - net: ena: make ethtool -l show correct max number of queues
+    - net: ena: remove redundant print of number of queues
+    - net: ena: ethtool: support set_channels callback
+    - net: ena: implement XDP drop support
+    - net: ena: Implement XDP_TX action
+    - net: ena: Add first_interrupt field to napi struct
+    - net: ena: fix default tx interrupt moderation interval
+    - net: ena: remove set but not used variable 'rx_ring'
+    - net: ena: remove set but not used variable 'hash_key'
+    - net: ena: ethtool: remove redundant non-zero check on rc
+    - net/amazon: Ensure that driver version is aligned to the linux kernel
+    - net: ena: fix broken interface between ENA driver and FW
+    - net: ena: ethtool: clean up minor indentation issue
+    - net: ena: fix incorrect setting of the number of msix vectors
+    - net: ena: fix request of incorrect number of IRQ vectors
+    - net: ena: avoid memory access violation by validating req_id properly
+    - net: ena: fix continuous keep-alive resets
+    - net: ena: Make some functions static
+    - net: ena: avoid unnecessary admin command when RSS function set fails
+    - net: ena: allow setting the hash function without changing the key
+    - net: ena: change default RSS hash function to Toeplitz
+    - net: ena: changes to RSS hash key allocation
+    - net: ena: remove code that does nothing
+    - net: ena: add unmask interrupts statistics to ethtool
+    - net: ena: add support for reporting of packet drops
+    - net: ena: drop superfluous prototype
+    - net: ena: use SHUTDOWN as reset reason when closing interface
+    - net: ena: cosmetic: remove unnecessary spaces and tabs in ena_com.h macros
+    - net: ena: cosmetic: extract code to ena_indirection_table_set()
+    - net: ena: add support for the rx offset feature
+    - net: ena: rename ena_com_free_desc to make API more uniform
+    - net: ena: use explicit variable size for clarity
+    - net: ena: fix ena_com_comp_status_to_errno() return value
+    - net: ena: simplify ena_com_update_intr_delay_resolution()
+    - net: ena: cosmetic: set queue sizes to u32 for consistency
+    - net: ena: cosmetic: fix spelling and grammar mistakes in comments
+    - net: ena: cosmetic: fix line break issues
+    - net: ena: cosmetic: remove unnecessary code
+    - net: ena: cosmetic: code reorderings
+    - net: ena: cosmetic: fix spacing issues
+    - net: ena: cosmetic: minor code changes
+    - net: ena: reduce driver load time
+    - net: ena: xdp: XDP_TX: fix memory leak
+    - net: ena: xdp: update napi budget for DROP and ABORTED
+    - ena_netdev: use generic power management
+    - net: ena: Fix using plain integer as NULL pointer in ena_init_napi_in_range
+    - net: ena: avoid unnecessary rearming of interrupt vector when busy-polling
+    - net: ena: add reserved PCI device ID
+    - net: ena: cosmetic: satisfy gcc warning
+    - net: ena: cosmetic: change ena_com_stats_admin stats to u64
+    - net: ena: add support for traffic mirroring
+    - net: ena: enable support of rss hash key and function changes
+    - net: ena: move llq configuration from ena_probe to ena_device_init()
+    - net: ena: support new LLQ acceleration mode
+
+  * [SRU] Fix acpi backlight issue on some thinkpads (LP: #1892010)
+    - platform/x86: thinkpad_acpi: not loading brightness_init when _BCL invalid
+
+  * [SRU][F/OEM-5.6] add a new OLED panel support for brightness control
+    (LP: #1887909)
+    - drm/dp: Lenovo X13 Yoga OLED panel brightness fix
+
+  * Realtek [10ec:c82f] Subsystem [17aa:c02f] Wifi adapter not found
+    (LP: #1886247)
+    - SAUCE: rtw88: 8822ce: add support for device ID 0xc82f
+
+  * KVM: Fix zero_page reference counter overflow when using KSM on KVM compute
+    host (LP: #1837810)
+    - KVM: fix overflow of zero page refcount with ksm running
+
+  * Fix missing HDMI Audio on another HP Desktop (LP: #1891617)
+    - ALSA: hda/hdmi: Use force connectivity quirk on another HP desktop
+
+  * alsa/sof: support 1 and 3 dmics (LP: #1891585)
+    - SAUCE: ASoC: SOF: intel: hda: support also devices with 1 and 3 dmics
+
+  * tcp_fastopen_backup_key.sh from net in ubuntu_kernel_selftests failed on
+    Eoan LPAR (LP: #1869134)
+    - tcp: correct read of TFO keys on big endian systems
+
+  * Fix false-negative return value for rtnetlink.sh in kselftests/net
+    (LP: #1890136)
+    - selftests: rtnetlink: correct the final return value for the test
+    - selftests: rtnetlink: make kci_test_encap() return sub-test result
+
+  * Focal update: v5.4.58 upstream stable release (LP: #1891387)
+    - USB: serial: qcserial: add EM7305 QDL product ID
+    - perf/core: Fix endless multiplex timer
+    - USB: iowarrior: fix up report size handling for some devices
+    - usb: xhci: define IDs for various ASMedia host controllers
+    - usb: xhci: Fix ASMedia ASM1142 DMA addressing
+    - io_uring: prevent re-read of sqe->opcode
+    - io_uring: Fix use-after-free in io_sq_wq_submit_work()
+    - Revert "ALSA: hda: call runtime_allow() for all hda controllers"
+    - ALSA: hda/realtek: Add alc269/alc662 pin-tables for Loongson-3 laptops
+    - ALSA: hda/ca0132 - Add new quirk ID for Recon3D.
+    - ALSA: hda/ca0132 - Fix ZxR Headphone gain control get value.
+    - ALSA: hda/ca0132 - Fix AE-5 microphone selection commands.
+    - ALSA: seq: oss: Serialize ioctls
+    - staging: android: ashmem: Fix lockdep warning for write operation
+    - staging: rtl8712: handle firmware load failure
+    - Staging: rtl8188eu: rtw_mlme: Fix uninitialized variable authmode
+    - Bluetooth: Fix slab-out-of-bounds read in hci_extended_inquiry_result_evt()
+    - Bluetooth: Prevent out-of-bounds read in hci_inquiry_result_evt()
+    - Bluetooth: Prevent out-of-bounds read in hci_inquiry_result_with_rssi_evt()
+    - omapfb: dss: Fix max fclk divider for omap36xx
+    - binder: Prevent context manager from incrementing ref 0
+    - Smack: fix use-after-free in smk_write_relabel_self()
+    - scripts: add dummy report mode to add_namespace.cocci
+    - vgacon: Fix for missing check in scrollback handling
+    - mtd: properly check all write ioctls for permissions
+    - leds: wm831x-status: fix use-after-free on unbind
+    - leds: lm36274: fix use-after-free on unbind
+    - leds: da903x: fix use-after-free on unbind
+    - leds: lm3533: fix use-after-free on unbind
+    - leds: 88pm860x: fix use-after-free on unbind
+    - net/9p: validate fds in p9_fd_open
+    - drm/nouveau/fbcon: fix module unload when fbcon init has failed for some
+      reason
+    - drm/nouveau/fbcon: zero-initialise the mode_cmd2 structure
+    - drm/drm_fb_helper: fix fbdev with sparc64
+    - i2c: slave: improve sanity check when registering
+    - i2c: slave: add sanity check when unregistering
+    - usb: hso: check for return value in hso_serial_common_create()
+    - net: ethernet: mtk_eth_soc: Always call mtk_gmac0_rgmii_adjust() for mt7623
+    - ALSA: hda: fix NULL pointer dereference during suspend
+    - firmware: Fix a reference count leak.
+    - cfg80211: check vendor command doit pointer before use
+    - igb: reinit_locked() should be called with rtnl_lock
+    - atm: fix atm_dev refcnt leaks in atmtcp_remove_persistent
+    - tools lib traceevent: Fix memory leak in process_dynamic_array_len
+    - Drivers: hv: vmbus: Ignore CHANNELMSG_TL_CONNECT_RESULT(23)
+    - xattr: break delegations in {set,remove}xattr
+    - Revert "powerpc/kasan: Fix shadow pages allocation failure"
+    - PCI: tegra: Revert tegra124 raw_violation_fixup
+    - ipv4: Silence suspicious RCU usage warning
+    - ipv6: fix memory leaks on IPV6_ADDRFORM path
+    - ipv6: Fix nexthop refcnt leak when creating ipv6 route info
+    - net: ethernet: mtk_eth_soc: fix MTU warnings
+    - rxrpc: Fix race between recvmsg and sendmsg on immediate call failure
+    - vxlan: Ensure FDB dump is performed under RCU
+    - net: lan78xx: replace bogus endpoint lookup
+    - appletalk: Fix atalk_proc_init() return path
+    - dpaa2-eth: Fix passing zero to 'PTR_ERR' warning
+    - hv_netvsc: do not use VF device if link is down
+    - net: gre: recompute gre csum for sctp over gre tunnels
+    - net: thunderx: use spin_lock_bh in nicvf_set_rx_mode_task()
+    - openvswitch: Prevent kernel-infoleak in ovs_ct_put_key()
+    - Revert "vxlan: fix tos value before xmit"
+    - tcp: apply a floor of 1 for RTT samples from TCP timestamps
+    - ima: move APPRAISE_BOOTPARAM dependency on ARCH_POLICY to runtime
+    - [Config] update annotations for IMA_APPRAISE_BOOTPARAM
+    - nfsd: Fix NFSv4 READ on RDMA when using readv
+    - Linux 5.4.58
+
+  * Focal update: v5.4.57 upstream stable release (LP: #1891064)
+    - random32: update the net random state on interrupt and activity
+    - ARM: percpu.h: fix build error
+    - random: fix circular include dependency on arm64 after addition of percpu.h
+    - random32: remove net_rand_state from the latent entropy gcc plugin
+    - random32: move the pseudo-random 32-bit definitions to prandom.h
+    - arm64: Workaround circular dependency in pointer_auth.h
+    - ext4: fix direct I/O read error
+    - selftests: bpf: Fix detach from sockmap tests
+    - bpf: sockmap: Require attach_bpf_fd when detaching a program
+    - Linux 5.4.57
+
+  * Focal update: v5.4.56 upstream stable release (LP: #1891063)
+    - crypto: ccp - Release all allocated memory if sha type is invalid
+    - media: rc: prevent memory leak in cx23888_ir_probe
+    - sunrpc: check that domain table is empty at module unload.
+    - ath10k: enable transmit data ack RSSI for QCA9884
+    - PCI/ASPM: Disable ASPM on ASMedia ASM1083/1085 PCIe-to-PCI bridge
+    - mm/filemap.c: don't bother dropping mmap_sem for zero size readahead
+    - ALSA: usb-audio: Add implicit feedback quirk for SSL2
+    - ALSA: hda/realtek: enable headset mic of ASUS ROG Zephyrus G15(GA502) series
+      with ALC289
+    - ALSA: hda/realtek: typo_fix: enable headset mic of ASUS ROG Zephyrus
+      G14(GA401) series with ALC289
+    - ALSA: hda/realtek: Fix add a "ultra_low_power" function for intel reference
+      board (alc256)
+    - ALSA: hda/hdmi: Fix keep_power assignment for non-component devices
+    - IB/rdmavt: Fix RQ counting issues causing use of an invalid RWQE
+    - vhost/scsi: fix up req type endian-ness
+    - 9p/trans_fd: Fix concurrency del of req_list in p9_fd_cancelled/p9_read_work
+    - wireless: Use offsetof instead of custom macro.
+    - ARM: 8986/1: hw_breakpoint: Don't invoke overflow handler on uaccess
+      watchpoints
+    - ARM: dts: imx6sx-sabreauto: Fix the phy-mode on fec2
+    - ARM: dts: imx6sx-sdb: Fix the phy-mode on fec2
+    - ARM: dts: imx6qdl-icore: Fix OTG_ID pin and sdcard detect
+    - virtio_balloon: fix up endian-ness for free cmd id
+    - Revert "drm/amdgpu: Fix NULL dereference in dpm sysfs handlers"
+    - drm/amd/display: Clear dm_state for fast updates
+    - drm/amdgpu: Prevent kernel-infoleak in amdgpu_info_ioctl()
+    - drm/dbi: Fix SPI Type 1 (9-bit) transfer
+    - drm: hold gem reference until object is no longer accessed
+    - rds: Prevent kernel-infoleak in rds_notify_queue_get()
+    - libtraceevent: Fix build with binutils 2.35
+    - net/x25: Fix x25_neigh refcnt leak when x25 disconnect
+    - net/x25: Fix null-ptr-deref in x25_disconnect
+    - ARM: dts sunxi: Relax a bit the CMA pool allocation range
+    - xfrm: Fix crash when the hold queue is used.
+    - ARM: dts: armada-38x: fix NETA lockup when repeatedly switching speeds
+    - nvme-tcp: fix possible hang waiting for icresp response
+    - selftests/net: rxtimestamp: fix clang issues for target arch PowerPC
+    - selftests/net: psock_fanout: fix clang issues for target arch PowerPC
+    - selftests/net: so_txtime: fix clang issues for target arch PowerPC
+    - sh/tlb: Fix PGTABLE_LEVELS > 2
+    - sh: Fix validation of system call number
+    - net: hns3: fix a TX timeout issue
+    - net: hns3: fix aRFS FD rules leftover after add a user FD rule
+    - net/mlx5: E-switch, Destroy TSAR when fail to enable the mode
+    - net/mlx5e: Fix error path of device attach
+    - net/mlx5: Verify Hardware supports requested ptp function on a given pin
+    - net/mlx5e: Modify uplink state on interface up/down
+    - net/mlx5e: Fix kernel crash when setting vf VLANID on a VF dev
+    - net: lan78xx: add missing endpoint sanity check
+    - net: lan78xx: fix transfer-buffer memory leak
+    - rhashtable: Fix unprotected RCU dereference in __rht_ptr
+    - mlx4: disable device on shutdown
+    - mlxsw: core: Increase scope of RCU read-side critical section
+    - mlxsw: core: Free EMAD transactions using kfree_rcu()
+    - ibmvnic: Fix IRQ mapping disposal in error path
+    - bpf: Fix map leak in HASH_OF_MAPS map
+    - mac80211: mesh: Free ie data when leaving mesh
+    - mac80211: mesh: Free pending skb when destroying a mpath
+    - arm64/alternatives: move length validation inside the subsection
+    - arm64: csum: Fix handling of bad packets
+    - Bluetooth: fix kernel oops in store_pending_adv_report
+    - net: nixge: fix potential memory leak in nixge_probe()
+    - net: gemini: Fix missing clk_disable_unprepare() in error path of
+      gemini_ethernet_port_probe()
+    - net/mlx5e: fix bpf_prog reference count leaks in mlx5e_alloc_rq
+    - perf tools: Fix record failure when mixed with ARM SPE event
+    - vxlan: fix memleak of fdb
+    - usb: hso: Fix debug compile warning on sparc32
+    - selftests: fib_nexthop_multiprefix: fix cleanup() netns deletion
+    - qed: Disable "MFW indication via attention" SPAM every 5 minutes
+    - selftests: net: ip_defrag: modprobe missing nf_defrag_ipv6 support
+    - nfc: s3fwrn5: add missing release on skb in s3fwrn5_recv_frame
+    - scsi: core: Run queue in case of I/O resource contention failure
+    - parisc: add support for cmpxchg on u8 pointers
+    - net: ethernet: ravb: exit if re-initialization fails in tx timeout
+    - Revert "i2c: cadence: Fix the hold bit setting"
+    - x86/unwind/orc: Fix ORC for newly forked tasks
+    - x86/stacktrace: Fix reliable check for empty user task stacks
+    - cxgb4: add missing release on skb in uld_send()
+    - xen-netfront: fix potential deadlock in xennet_remove()
+    - RISC-V: Set maximum number of mapped pages correctly
+    - drivers/net/wan: lapb: Corrected the usage of skb_cow
+    - KVM: arm64: Don't inherit exec permission across page-table levels
+    - KVM: LAPIC: Prevent setting the tscdeadline timer if the lapic is hw
+      disabled
+    - x86/i8259: Use printk_deferred() to prevent deadlock
+    - perf tests bp_account: Make global variable static
+    - perf env: Do not return pointers to local variables
+    - perf bench: Share some global variables to fix build with gcc 10
+    - Linux 5.4.56
+
+ -- Kleber Sacilotto de Souza <kleber.souza@canonical.com>  Thu, 10 Sep 2020 12:12:09 +0200
+
+linux (5.4.0-47.51) focal; urgency=medium
+
+  * focal/linux: 5.4.0-47.51 -proposed tracker (LP: #1894315)
+
+  * CVE-2020-14386
+    - SAUCE: net/packet: fix overflow in tpacket_rcv
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update helper scripts
+
+ -- Thadeu Lima de Souza Cascardo <cascardo@canonical.com>  Fri, 04 Sep 2020 16:08:25 -0300
+
+linux (5.4.0-45.49) focal; urgency=medium
+
+  * focal/linux: 5.4.0-45.49 -proposed tracker (LP: #1893050)
+
+  * [Potential Regression] dscr_inherit_exec_test from powerpc in
+    ubuntu_kernel_selftests failed on B/E/F (LP: #1888332)
+    - powerpc/64s: Don't init FSCR_DSCR in __init_FSCR()
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Wed, 26 Aug 2020 15:15:45 +0200
+
+linux (5.4.0-44.48) focal; urgency=medium
+
+  * focal/linux: 5.4.0-44.48 -proposed tracker (LP: #1891049)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update helper scripts
+
+  * ipsec: policy priority management is broken (LP: #1890796)
+    - xfrm: policy: match with both mark and mask on user interfaces
+
+ -- Kelsey Skunberg <kelsey.skunberg@canonical.com>  Mon, 10 Aug 2020 14:57:15 -0600
+
+linux (5.4.0-43.47) focal; urgency=medium
+
+  * focal/linux: 5.4.0-43.47 -proposed tracker (LP: #1890746)
+
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+
+  * Devlink -  add RoCE disable kernel support  (LP: #1877270)
+    - devlink: Add new "enable_roce" generic device param
+    - net/mlx5: Document flow_steering_mode devlink param
+    - net/mlx5: Handle "enable_roce" devlink param
+    - IB/mlx5: Rename profile and init methods
+    - IB/mlx5: Load profile according to RoCE enablement state
+    - net/mlx5: Remove unneeded variable in mlx5_unload_one
+    - net/mlx5: Add devlink reload
+    - IB/mlx5: Do reverse sequence during device removal
+
+  * msg_zerocopy.sh in net from ubuntu_kernel_selftests failed (LP: #1812620)
+    - selftests/net: relax cpu affinity requirement in msg_zerocopy test
+
+  * Enlarge hisi_sec2 capability (LP: #1890222)
+    - Revert "UBUNTU: [Config] Disable hisi_sec2 temporarily"
+    - crypto: hisilicon - update SEC driver module parameter
+
+  * Fix missing HDMI/DP Audio on an HP Desktop (LP: #1890441)
+    - ALSA: hda/hdmi: Add quirk to force connectivity
+
+  * Fix IOMMU error on AMD Radeon Pro W5700 (LP: #1890306)
+    - PCI: Mark AMD Navi10 GPU rev 0x00 ATS as broken
+
+  * ASoC:amd:renoir:  the dmic can't record sound after suspend and resume
+    (LP: #1890220)
+    - SAUCE: ASoC: amd: renoir: restore two more registers during resume
+
+  * No sound, Dummy output on Acer Swift 3 SF314-57G with Ice Lake core-i7  CPU
+    (LP: #1877757)
+    - ASoC: SOF: Intel: hda: fix generic hda codec support
+
+  * Fix right speaker of HP laptop (LP: #1889375)
+    - SAUCE: hda/realtek: Fix right speaker of HP laptop
+
+  * blk_update_request error when mount nvme partition (LP: #1872383)
+    - SAUCE: nvme-pci: prevent SK hynix PC400 from using Write Zeroes command
+
+  * soc/amd/renoir: detect dmic from acpi table (LP: #1887734)
+    - ASoC: amd: add logic to check dmic hardware runtime
+    - ASoC: amd: add ACPI dependency check
+    - ASoC: amd: fixed kernel warnings
+
+  * soc/amd/renoir: change the module name to make it work with ucm3
+    (LP: #1888166)
+    - AsoC: amd: add missing snd- module prefix to the acp3x-rn driver kernel
+      module
+    - SAUCE: remove a kernel module since its name is changed
+
+  * Focal update: v5.4.55 upstream stable release (LP: #1890343)
+    - AX.25: Fix out-of-bounds read in ax25_connect()
+    - AX.25: Prevent out-of-bounds read in ax25_sendmsg()
+    - dev: Defer free of skbs in flush_backlog
+    - drivers/net/wan/x25_asy: Fix to make it work
+    - ip6_gre: fix null-ptr-deref in ip6gre_init_net()
+    - net-sysfs: add a newline when printing 'tx_timeout' by sysfs
+    - net: udp: Fix wrong clean up for IS_UDPLITE macro
+    - qrtr: orphan socket in qrtr_release()
+    - rtnetlink: Fix memory(net_device) leak when ->newlink fails
+    - rxrpc: Fix sendmsg() returning EPIPE due to recvmsg() returning ENODATA
+    - tcp: allow at most one TLP probe per flight
+    - AX.25: Prevent integer overflows in connect and sendmsg
+    - sctp: shrink stream outq only when new outcnt < old outcnt
+    - sctp: shrink stream outq when fails to do addstream reconf
+    - udp: Copy has_conns in reuseport_grow().
+    - udp: Improve load balancing for SO_REUSEPORT.
+    - regmap: debugfs: check count when read regmap file
+    - PM: wakeup: Show statistics for deleted wakeup sources again
+    - Revert "dpaa_eth: fix usage as DSA master, try 3"
+    - Linux 5.4.55
+
+  * Add support for Atlantic NIC firmware v4 (LP: #1886908)
+    - net: atlantic: simplify hw_get_fw_version() usage
+    - net: atlantic: align return value of ver_match function with function name
+    - net: atlantic: add support for FW 4.x
+
+  * perf vendor events s390: Add new deflate counters for IBM z15 (LP: #1888551)
+    - perf vendor events s390: Add new deflate counters for IBM z15
+
+  * Focal update: v5.4.54 upstream stable release (LP: #1889669)
+    - soc: qcom: rpmh: Dirt can only make you dirtier, not cleaner
+    - gpio: arizona: handle pm_runtime_get_sync failure case
+    - gpio: arizona: put pm_runtime in case of failure
+    - pinctrl: amd: fix npins for uart0 in kerncz_groups
+    - mac80211: allow rx of mesh eapol frames with default rx key
+    - scsi: scsi_transport_spi: Fix function pointer check
+    - xtensa: fix __sync_fetch_and_{and,or}_4 declarations
+    - xtensa: update *pos in cpuinfo_op.next
+    - scsi: mpt3sas: Fix unlock imbalance
+    - drivers/net/wan/lapbether: Fixed the value of hard_header_len
+    - ALSA: hda/hdmi: fix failures at PCM open on Intel ICL and later
+    - net: sky2: initialize return of gm_phy_read
+    - drm/nouveau/i2c/g94-: increase NV_PMGR_DP_AUXCTL_TRANSACTREQ timeout
+    - scsi: mpt3sas: Fix error returns in BRM_status_show
+    - scsi: dh: Add Fujitsu device to devinfo and dh lists
+    - dm: use bio_uninit instead of bio_disassociate_blkg
+    - drivers/firmware/psci: Fix memory leakage in alloc_init_cpu_groups()
+    - fuse: fix weird page warning
+    - irqdomain/treewide: Keep firmware node unconditionally allocated
+    - ARM: dts: imx6qdl-gw551x: Do not use 'simple-audio-card,dai-link'
+    - ARM: dts: imx6qdl-gw551x: fix audio SSI
+    - dmabuf: use spinlock to access dmabuf->name
+    - drm/amd/display: Check DMCU Exists Before Loading
+    - SUNRPC reverting d03727b248d0 ("NFSv4 fix CLOSE not waiting for direct IO
+      compeletion")
+    - btrfs: reloc: fix reloc root leak and NULL pointer dereference
+    - btrfs: reloc: clear DEAD_RELOC_TREE bit for orphan roots to prevent runaway
+      balance
+    - uprobes: Change handle_swbp() to send SIGTRAP with si_code=SI_KERNEL, to fix
+      GDB regression
+    - ALSA: hda/realtek: Fixed ALC298 sound bug by adding quirk for Samsung
+      Notebook Pen S
+    - ALSA: info: Drop WARN_ON() from buffer NULL sanity check
+    - ASoC: rt5670: Correct RT5670_LDO_SEL_MASK
+    - btrfs: fix double free on ulist after backref resolution failure
+    - btrfs: fix mount failure caused by race with umount
+    - btrfs: fix page leaks after failure to lock page for delalloc
+    - bnxt_en: Fix race when modifying pause settings.
+    - bnxt_en: Fix completion ring sizing with TPA enabled.
+    - fpga: dfl: pci: reduce the scope of variable 'ret'
+    - fpga: dfl: fix bug in port reset handshake
+    - hippi: Fix a size used in a 'pci_free_consistent()' in an error handling
+      path
+    - vsock/virtio: annotate 'the_virtio_vsock' RCU pointer
+    - ax88172a: fix ax88172a_unbind() failures
+    - RDMA/mlx5: Use xa_lock_irq when access to SRQ table
+    - ASoC: Intel: bytcht_es8316: Add missed put_device()
+    - net: dp83640: fix SIOCSHWTSTAMP to update the struct with actual
+      configuration
+    - ieee802154: fix one possible memleak in adf7242_probe
+    - drm: sun4i: hdmi: Fix inverted HPD result
+    - net: smc91x: Fix possible memory leak in smc_drv_probe()
+    - bonding: check error value of register_netdevice() immediately
+    - mlxsw: destroy workqueue when trap_register in mlxsw_emad_init
+    - ionic: use offset for ethtool regs data
+    - ionic: fix up filter locks and debug msgs
+    - net: ag71xx: add missed clk_disable_unprepare in error path of probe
+    - net: hns3: fix error handling for desc filling
+    - net: dsa: microchip: call phy_remove_link_mode during probe
+    - netdevsim: fix unbalaced locking in nsim_create()
+    - qed: suppress "don't support RoCE & iWARP" flooding on HW init
+    - qed: suppress false-positives interrupt error messages on HW init
+    - ipvs: fix the connection sync failed in some cases
+    - net: ethernet: ave: Fix error returns in ave_init
+    - Revert "PCI/PM: Assume ports without DLL Link Active train links in 100 ms"
+    - nfsd4: fix NULL dereference in nfsd/clients display code
+    - enetc: Remove the mdio bus on PF probe bailout
+    - i2c: rcar: always clear ICSAR to avoid side effects
+    - i2c: i2c-qcom-geni: Fix DMA transfer race
+    - bonding: check return value of register_netdevice() in bond_newlink()
+    - geneve: fix an uninitialized value in geneve_changelink()
+    - serial: exar: Fix GPIO configuration for Sealevel cards based on XR17V35X
+    - scripts/decode_stacktrace: strip basepath from all paths
+    - scripts/gdb: fix lx-symbols 'gdb.error' while loading modules
+    - HID: i2c-hid: add Mediacom FlexBook edge13 to descriptor override
+    - HID: alps: support devices with report id 2
+    - HID: steam: fixes race in handling device list.
+    - HID: apple: Disable Fn-key key-re-mapping on clone keyboards
+    - dmaengine: tegra210-adma: Fix runtime PM imbalance on error
+    - Input: add `SW_MACHINE_COVER`
+    - ARM: dts: n900: remove mmc1 card detect gpio
+    - spi: mediatek: use correct SPI_CFG2_REG MACRO
+    - regmap: dev_get_regmap_match(): fix string comparison
+    - hwmon: (aspeed-pwm-tacho) Avoid possible buffer overflow
+    - dmaengine: fsl-edma: fix wrong tcd endianness for big-endian cpu
+    - dmaengine: ioat setting ioat timeout as module parameter
+    - Input: synaptics - enable InterTouch for ThinkPad X1E 1st gen
+    - Input: elan_i2c - only increment wakeup count on touch
+    - usb: dwc3: pci: add support for the Intel Tiger Lake PCH -H variant
+    - usb: dwc3: pci: add support for the Intel Jasper Lake
+    - usb: gadget: udc: gr_udc: fix memleak on error handling path in gr_ep_init()
+    - usb: cdns3: ep0: fix some endian issues
+    - usb: cdns3: trace: fix some endian issues
+    - hwmon: (adm1275) Make sure we are reading enough data for different chips
+    - drm/amdgpu/gfx10: fix race condition for kiq
+    - drm/amdgpu: fix preemption unit test
+    - hwmon: (nct6775) Accept PECI Calibration as temperature source for NCT6798D
+    - platform/x86: ISST: Add new PCI device ids
+    - platform/x86: asus-wmi: allow BAT1 battery name
+    - hwmon: (scmi) Fix potential buffer overflow in scmi_hwmon_probe()
+    - ALSA: hda/realtek - fixup for yet another Intel reference board
+    - drivers/perf: Fix kernel panic when rmmod PMU modules during perf sampling
+    - arm64: Use test_tsk_thread_flag() for checking TIF_SINGLESTEP
+    - x86: math-emu: Fix up 'cmp' insn for clang ias
+    - asm-generic/mmiowb: Allow mmiowb_set_pending() when preemptible()
+    - drivers/perf: Prevent forced unbinding of PMU drivers
+    - RISC-V: Upgrade smp_mb__after_spinlock() to iorw,iorw
+    - binder: Don't use mmput() from shrinker function.
+    - usb: xhci-mtk: fix the failure of bandwidth allocation
+    - usb: xhci: Fix ASM2142/ASM3142 DMA addressing
+    - Revert "cifs: Fix the target file was deleted when rename failed."
+    - iwlwifi: mvm: don't call iwl_mvm_free_inactive_queue() under RCU
+    - tty: xilinx_uartps: Really fix id assignment
+    - staging: wlan-ng: properly check endpoint types
+    - staging: comedi: addi_apci_1032: check INSN_CONFIG_DIGITAL_TRIG shift
+    - staging: comedi: ni_6527: fix INSN_CONFIG_DIGITAL_TRIG support
+    - staging: comedi: addi_apci_1500: check INSN_CONFIG_DIGITAL_TRIG shift
+    - staging: comedi: addi_apci_1564: check INSN_CONFIG_DIGITAL_TRIG shift
+    - serial: tegra: fix CREAD handling for PIO
+    - serial: 8250: fix null-ptr-deref in serial8250_start_tx()
+    - serial: 8250_mtk: Fix high-speed baud rates clamping
+    - /dev/mem: Add missing memory barriers for devmem_inode
+    - fbdev: Detect integer underflow at "struct fbcon_ops"->clear_margins.
+    - vt: Reject zero-sized screen buffer size.
+    - Makefile: Fix GCC_TOOLCHAIN_DIR prefix for Clang cross compilation
+    - mm/mmap.c: close race between munmap() and expand_upwards()/downwards()
+    - mm/memcg: fix refcount error while moving and swapping
+    - mm: memcg/slab: fix memory leak at non-root kmem_cache destroy
+    - khugepaged: fix null-pointer dereference due to race
+    - io-mapping: indicate mapping failure
+    - mmc: sdhci-of-aspeed: Fix clock divider calculation
+    - drm/amdgpu: Fix NULL dereference in dpm sysfs handlers
+    - drm/amd/powerplay: fix a crash when overclocking Vega M
+    - parisc: Add atomic64_set_release() define to avoid CPU soft lockups
+    - x86, vmlinux.lds: Page-align end of ..page_aligned sections
+    - ASoC: rt5670: Add new gpio1_is_ext_spk_en quirk and enable it on the Lenovo
+      Miix 2 10
+    - ASoC: qcom: Drop HAS_DMA dependency to fix link failure
+    - ASoC: topology: fix kernel oops on route addition error
+    - ASoC: topology: fix tlvs in error handling for widget_dmixer
+    - dm integrity: fix integrity recalculation that is improperly skipped
+    - ath9k: Fix regression with Atheros 9271
+    - Linux 5.4.54
+
+  * Focal update: v5.4.53 upstream stable release (LP: #1888560)
+    - crypto: atmel - Fix selection of CRYPTO_AUTHENC
+    - crypto: atmel - Fix build error of CRYPTO_AUTHENC
+    - net: atlantic: fix ip dst and ipv6 address filters
+    - net: rmnet: fix lower interface leak
+    - bridge: mcast: Fix MLD2 Report IPv6 payload length check
+    - genetlink: remove genl_bind
+    - ipv4: fill fl4_icmp_{type,code} in ping_v4_sendmsg
+    - ipv6: fib6_select_path can not use out path for nexthop objects
+    - ipv6: Fix use of anycast address with loopback
+    - l2tp: remove skb_dst_set() from l2tp_xmit_skb()
+    - llc: make sure applications use ARPHRD_ETHER
+    - net: Added pointer check for dst->ops->neigh_lookup in dst_neigh_lookup_skb
+    - net_sched: fix a memory leak in atm_tc_init()
+    - sched: consistently handle layer3 header accesses in the presence of VLANs
+    - tcp: fix SO_RCVLOWAT possible hangs under high mem pressure
+    - tcp: make sure listeners don't initialize congestion-control state
+    - tcp: md5: add missing memory barriers in tcp_md5_do_add()/tcp_md5_hash_key()
+    - tcp: md5: do not send silly options in SYNCOOKIES
+    - vlan: consolidate VLAN parsing code and limit max parsing depth
+    - tcp: md5: refine tcp_md5_do_add()/tcp_md5_hash_key() barriers
+    - tcp: md5: allow changing MD5 keys in all socket states
+    - cgroup: fix cgroup_sk_alloc() for sk_clone_lock()
+    - cgroup: Fix sock_cgroup_data on big-endian.
+    - ip: Fix SO_MARK in RST, ACK and ICMP packets
+    - arm64: Introduce a way to disable the 32bit vdso
+    - arm64: arch_timer: Allow an workaround descriptor to disable compat vdso
+    - arm64: arch_timer: Disable the compat vdso for cores affected by
+      ARM64_WORKAROUND_1418040
+    - drm/msm: fix potential memleak in error branch
+    - drm/msm/dpu: allow initialization of encoder locks during encoder init
+    - drm/exynos: Properly propagate return value in drm_iommu_attach_device()
+    - drm/exynos: fix ref count leak in mic_pre_enable
+    - x86/fpu: Reset MXCSR to default in kernel_fpu_begin()
+    - thermal/drivers: imx: Fix missing of_node_put() at probe time
+    - blk-mq-debugfs: update blk_queue_flag_name[] accordingly for new flags
+    - m68k: nommu: register start of the memory with memblock
+    - m68k: mm: fix node memblock init
+    - dt-bindings: mailbox: zynqmp_ipi: fix unit address
+    - cifs: prevent truncation from long to int in wait_for_free_credits
+    - arm64/alternatives: use subsections for replacement sequences
+    - tpm_tis: extra chip->ops check on error path in tpm_tis_core_init
+    - gfs2: read-only mounts should grab the sd_freeze_gl glock
+    - i2c: eg20t: Load module automatically if ID matches
+    - arm64/alternatives: don't patch up internal branches
+    - iio:magnetometer:ak8974: Fix alignment and data leak issues
+    - iio:humidity:hdc100x Fix alignment and data leak issues
+    - iio: magnetometer: ak8974: Fix runtime PM imbalance on error
+    - iio: core: add missing IIO_MOD_H2/ETHANOL string identifiers
+    - iio: mma8452: Add missed iio_device_unregister() call in mma8452_probe()
+    - iio: pressure: zpa2326: handle pm_runtime_get_sync failure
+    - iio:humidity:hts221 Fix alignment and data leak issues
+    - iio:pressure:ms5611 Fix buffer element alignment
+    - iio:health:afe4403 Fix timestamp alignment and prevent data leak.
+    - spi: spi-fsl-dspi: Fix lockup if device is shutdown during SPI transfer
+    - net: dsa: bcm_sf2: Fix node reference count
+    - of: of_mdio: Correct loop scanning logic
+    - net: macb: call pm_runtime_put_sync on failure path
+    - net: ethernet: mvneta: Do not error out in non serdes modes
+    - net: ethernet: mvneta: Add back interface mode validation
+    - Revert "usb/ohci-platform: Fix a warning when hibernating"
+    - Revert "usb/ehci-platform: Set PM runtime as active on resume"
+    - Revert "usb/xhci-plat: Set PM runtime as active on resume"
+    - net: sfp: add support for module quirks
+    - net: sfp: add some quirks for GPON modules
+    - ARM: OMAP4+: remove pdata quirks for omap4+ iommus
+    - ARM: OMAP2+: Add workaround for DRA7 DSP MStandby errata i879
+    - ARM: OMAP2+: use separate IOMMU pdata to fix DRA7 IPU1 boot
+    - mmc: mmci: Support any block sizes for ux500v2 and qcom variant
+    - HID: quirks: Remove ITE 8595 entry from hid_have_special_driver
+    - ARM: at91: pm: add quirk for sam9x60's ulp1
+    - drm/sun4i: tcon: Separate quirks for tcon0 and tcon1 on A20
+    - scsi: sr: remove references to BLK_DEV_SR_VENDOR, leave it enabled
+    - [Config] updateconfigs for BLK_DEV_SR_VENDOR
+    - bus: ti-sysc: Rename clk related quirks to pre_reset and post_reset quirks
+    - bus: ti-sysc: Consider non-existing registers too when matching quirks
+    - bus: ti-sysc: Handle module unlock quirk needed for some RTC
+    - bus: ti-sysc: Detect display subsystem related devices
+    - arm64: dts: g12-common: add parkmode_disable_ss_quirk on DWC3 controller
+    - bus: ti-sysc: Detect EDMA and set quirk flags for tptc
+    - ALSA: usb-audio: Add support for MOTU MicroBook IIc
+    - Input: goodix - fix touch coordinates on Cube I15-TC
+    - ALSA: usb-audio: Create a registration quirk for Kingston HyperX Amp
+      (0951:16d8)
+    - doc: dt: bindings: usb: dwc3: Update entries for disabling SS instances in
+      park mode
+    - mmc: sdhci: do not enable card detect interrupt for gpio cd type
+    - ALSA: usb-audio: Rewrite registration quirk handling
+    - ACPI: video: Use native backlight on Acer Aspire 5783z
+    - ALSA: usb-audio: Add registration quirk for Kingston HyperX Cloud Alpha S
+    - ALSA: usb-audio: Add quirk for Focusrite Scarlett 2i2
+    - Input: mms114 - add extra compatible for mms345l
+    - ACPI: video: Use native backlight on Acer TravelMate 5735Z
+    - bus: ti-sysc: Use optional clocks on for enable and wait for softreset bit
+    - ALSA: usb-audio: Add registration quirk for Kingston HyperX Cloud Flight S
+    - iio:health:afe4404 Fix timestamp alignment and prevent data leak.
+    - soundwire: intel: fix memory leak with devm_kasprintf
+    - dmaengine: sh: usb-dmac: set tx_result parameters
+    - phy: sun4i-usb: fix dereference of pointer phy0 before it is null checked
+    - arm64: dts: meson: add missing gxl rng clock
+    - arm64: dts: meson-gxl-s805x: reduce initial Mali450 core frequency
+    - bus: ti-sysc: Fix wakeirq sleeping function called from invalid context
+    - bus: ti-sysc: Fix sleeping function called from invalid context for RTC
+      quirk
+    - bus: ti-sysc: Do not disable on suspend for no-idle
+    - iio: adc: ad7780: Fix a resource handling path in 'ad7780_probe()'
+    - dmaengine: dw: Initialize channel before each transfer
+    - dmaengine: dmatest: stop completed threads when running without set channel
+    - spi: spi-sun6i: sun6i_spi_transfer_one(): fix setting of clock rate
+    - usb: gadget: udc: atmel: fix uninitialized read in debug printk
+    - staging: comedi: verify array index is correct before using it
+    - clk: mvebu: ARMADA_AP_CPU_CLK needs to select ARMADA_AP_CP_HELPER
+    - clk: AST2600: Add mux for EMMC clock
+    - NFS: Fix interrupted slots by sending a solo SEQUENCE operation
+    - fuse: don't ignore errors from fuse_writepages_fill()
+    - ARM: dts: Fix dcan driver probe failed on am437x platform
+    - Revert "thermal: mediatek: fix register index error"
+    - xprtrdma: fix incorrect header size calculations
+    - ARM: dts: socfpga: Align L2 cache-controller nodename with dtschema
+    - arm64: dts: spcfpga: Align GIC, NAND and UART nodenames with dtschema
+    - keys: asymmetric: fix error return code in software_key_query()
+    - regmap: debugfs: Don't sleep while atomic for fast_io regmaps
+    - copy_xstate_to_kernel: Fix typo which caused GDB regression
+    - arm: dts: mt7623: add phy-mode property for gmac2
+    - soc: qcom: socinfo: add missing soc_id sysfs entry
+    - habanalabs: Align protection bits configuration of all TPCs
+    - PCI/PM: Call .bridge_d3() hook only if non-NULL
+    - perf stat: Zero all the 'ena' and 'run' array slot stats for interval mode
+    - soc: qcom: rpmh: Update dirty flag only when data changes
+    - soc: qcom: rpmh: Invalidate SLEEP and WAKE TCSes before flushing new data
+    - soc: qcom: rpmh-rsc: Clear active mode configuration for wake TCS
+    - soc: qcom: rpmh-rsc: Allow using free WAKE TCS for active request
+    - RDMA/mlx5: Verify that QP is created with RQ or SQ
+    - mtd: rawnand: marvell: Fix the condition on a return code
+    - mtd: rawnand: marvell: Use nand_cleanup() when the device is not yet
+      registered
+    - mtd: rawnand: marvell: Fix probe error path
+    - mtd: rawnand: timings: Fix default tR_max and tCCS_min timings
+    - mtd: rawnand: brcmnand: correctly verify erased pages
+    - mtd: rawnand: brcmnand: fix CS0 layout
+    - mtd: rawnand: oxnas: Keep track of registered devices
+    - mtd: rawnand: oxnas: Unregister all devices on error
+    - mtd: rawnand: oxnas: Release all devices in the _remove() path
+    - clk: qcom: gcc: Add GPU and NPU clocks for SM8150
+    - clk: qcom: gcc: Add missing UFS clocks for SM8150
+    - slimbus: core: Fix mismatch in of_node_get/put
+    - HID: logitech-hidpp: avoid repeated "multiplier = " log messages
+    - HID: magicmouse: do not set up autorepeat
+    - HID: quirks: Always poll Obins Anne Pro 2 keyboard
+    - HID: quirks: Ignore Simply Automated UPB PIM
+    - ALSA: line6: Perform sanity check for each URB creation
+    - ALSA: line6: Sync the pending work cancel at disconnection
+    - ALSA: usb-audio: Fix race against the error recovery URB submission
+    - ALSA: hda/realtek - change to suitable link model for ASUS platform
+    - ALSA: hda/realtek: enable headset mic of ASUS ROG Zephyrus G14(G401) series
+      with ALC289
+    - ALSA: hda/realtek: Enable headset mic of Acer TravelMate B311R-31 with
+      ALC256
+    - ALSA: hda/realtek - Enable Speaker for ASUS UX533 and UX534
+    - ALSA: hda/realtek - Enable Speaker for ASUS UX563
+    - USB: c67x00: fix use after free in c67x00_giveback_urb
+    - usb: dwc2: Fix shutdown callback in platform
+    - usb: chipidea: core: add wakeup support for extcon
+    - usb: gadget: function: fix missing spinlock in f_uac1_legacy
+    - USB: serial: iuu_phoenix: fix memory corruption
+    - USB: serial: cypress_m8: enable Simply Automated UPB PIM
+    - USB: serial: ch341: add new Product ID for CH340
+    - USB: serial: option: add GosunCn GM500 series
+    - virt: vbox: Fix VBGL_IOCTL_VMMDEV_REQUEST_BIG and _LOG req numbers to match
+      upstream
+    - virt: vbox: Fix guest capabilities mask check
+    - Revert "tty: xilinx_uartps: Fix missing id assignment to the console"
+    - virtio: virtio_console: add missing MODULE_DEVICE_TABLE() for rproc serial
+    - serial: mxs-auart: add missed iounmap() in probe failure and remove
+    - ovl: fix regression with re-formatted lower squashfs
+    - ovl: inode reference leak in ovl_is_inuse true case.
+    - ovl: relax WARN_ON() when decoding lower directory file handle
+    - ovl: fix unneeded call to ovl_change_flags()
+    - fuse: ignore 'data' argument of mount(..., MS_REMOUNT)
+    - fuse: use ->reconfigure() instead of ->remount_fs()
+    - fuse: Fix parameter for FS_IOC_{GET,SET}FLAGS
+    - Revert "zram: convert remaining CLASS_ATTR() to CLASS_ATTR_RO()"
+    - mei: bus: don't clean driver pointer
+    - Input: i8042 - add Lenovo XiaoXin Air 12 to i8042 nomux list
+    - uio_pdrv_genirq: Remove warning when irq is not specified
+    - uio_pdrv_genirq: fix use without device tree and no interrupt
+    - scsi: megaraid_sas: Remove undefined ENABLE_IRQ_POLL macro
+    - timer: Prevent base->clk from moving backward
+    - timer: Fix wheel index calculation on last level
+    - riscv: use 16KB kernel stack on 64-bit
+    - hwmon: (emc2103) fix unable to change fan pwm1_enable attribute
+    - powerpc/book3s64/pkeys: Fix pkey_access_permitted() for execute disable pkey
+    - powerpc/pseries/svm: Fix incorrect check for shared_lppaca_size
+    - intel_th: pci: Add Jasper Lake CPU support
+    - intel_th: pci: Add Tiger Lake PCH-H support
+    - intel_th: pci: Add Emmitsburg PCH support
+    - intel_th: Fix a NULL dereference when hub driver is not loaded
+    - dmaengine: fsl-edma: Fix NULL pointer exception in fsl_edma_tx_handler
+    - dmaengine: mcf-edma: Fix NULL pointer exception in mcf_edma_tx_handler
+    - dmaengine: fsl-edma-common: correct DSIZE_32BYTE
+    - misc: atmel-ssc: lock with mutex instead of spinlock
+    - thermal: int3403_thermal: Downgrade error message
+    - thermal/drivers/cpufreq_cooling: Fix wrong frequency converted from power
+    - arm64: ptrace: Override SPSR.SS when single-stepping is enabled
+    - arm64: ptrace: Consistently use pseudo-singlestep exceptions
+    - arm64: compat: Ensure upper 32 bits of x0 are zero on syscall return
+    - sched: Fix unreliable rseq cpu_id for new tasks
+    - sched/fair: handle case of task_h_load() returning 0
+    - genirq/affinity: Handle affinity setting on inactive interrupts correctly
+    - drm/amdgpu/sdma5: fix wptr overwritten in ->get_wptr()
+    - drm/i915/gt: Ignore irq enabling on the virtual engines
+    - block: fix splitting segments on boundary masks
+    - block: fix get_max_segment_size() overflow on 32bit arch
+    - libceph: don't omit recovery_deletes in target_copy()
+    - rxrpc: Fix trace string
+    - spi: sprd: switch the sequence of setting WDG_LOAD_LOW and _HIGH
+    - ionic: export features for vlans to use
+    - iommu/vt-d: Make Intel SVM code 64-bit only
+    - drm/i915/gvt: Fix two CFL MMIO handling caused by regression.
+    - gpio: pca953x: disable regmap locking for automatic address incrementing
+    - Linux 5.4.53
+
+  * linux-libc-dev broken for crossbuilding, Multi-Arch:same violation
+    (LP: #1886188)
+    - [Packaging] Produce linux-libc-dev package for riscv64
+    - [Debian] Disallow building linux-libc-dev from linux-riscv
+
+  * [UBUNTU 20.04] DIF and DIX support in zfcp (s390x) is broken and the kernel
+    crashes unconditionally (LP: #1887124)
+    - scsi: zfcp: signal incomplete or error for sync exchange config/port data
+    - scsi: zfcp: diagnostics buffer caching and use for exchange port data
+    - scsi: zfcp: add diagnostics buffer for exchange config data
+    - scsi: zfcp: support retrieval of SFP Data via Exchange Port Data
+    - scsi: zfcp: introduce sysfs interface for diagnostics of local SFP
+      transceiver
+    - scsi: zfcp: implicitly refresh port-data diagnostics when reading sysfs
+    - scsi: zfcp: introduce sysfs interface to read the local B2B-Credit
+    - scsi: zfcp: implicitly refresh config-data diagnostics when reading sysfs
+    - scsi: zfcp: move maximum age of diagnostic buffers into a per-adapter
+      variable
+    - scsi: zfcp: proper indentation to reduce confusion in zfcp_erp_required_act
+    - scsi: zfcp: fix wrong data and display format of SFP+ temperature
+    - scsi: zfcp: expose fabric name as common fc_host sysfs attribute
+    - scsi: zfcp: wire previously driver-specific sysfs attributes also to fc_host
+    - scsi: zfcp: fix fc_host attributes that should be unknown on local link down
+    - scsi: zfcp: auto variables for dereferenced structs in open port handler
+    - scsi: zfcp: report FC Endpoint Security in sysfs
+    - scsi: zfcp: log FC Endpoint Security of connections
+    - scsi: zfcp: trace FC Endpoint Security of FCP devices and connections
+    - scsi: zfcp: enhance handling of FC Endpoint Security errors
+    - scsi: zfcp: log FC Endpoint Security errors
+    - scsi: zfcp: use fallthrough;
+    - scsi: zfcp: Move shost modification after QDIO (re-)open into fenced
+      function
+    - scsi: zfcp: Move shost updates during xconfig data handling into fenced
+      function
+    - scsi: zfcp: Move fc_host updates during xport data handling into fenced
+      function
+    - scsi: zfcp: Fence fc_host updates during link-down handling
+    - scsi: zfcp: Move p-t-p port allocation to after xport data
+    - scsi: zfcp: Fence adapter status propagation for common statuses
+    - scsi: zfcp: Fence early sysfs interfaces for accesses of shost objects
+    - scsi: zfcp: Move allocation of the shost object to after xconf- and xport-
+      data
+
+  * Enable Quectel EG95 LTE modem [2c7c:0195]  (LP: #1886744)
+    - net: usb: qmi_wwan: add support for Quectel EG95 LTE modem
+    - USB: serial: option: add Quectel EG95 LTE modem
+
+  * Kernel Regression between 5.4.0-26 and 5.4.0-40 causes laptop internal audio
+    devices to fail to load w/o unacceptable workaround (Lenovo IdeaPad 5
+    15IIL05) (LP: #1886341)
+    - ASoC: SOF: intel: hda: Modify signature for hda_codec_probe_bus()
+    - ASoC: SOF: Intel: drop HDA codec upon probe failure
+    - ASoC: SOF: Intel: hda: move i915 init earlier
+
+  * [UBUNTU 20.04] smc: SMC connections hang with later-level implementations
+    (LP: #1882088)
+    - net/smc: tolerate future SMCD versions
+
+  * zfs: backport AES-GCM performance accelleration (LP: #1881107)
+    - debian/dkms-versions: update ZFS dkms package version (LP: #1881107)
+
+  * Regression in kernel 4.15.0-91 causes kernel panic with Bcache
+    (LP: #1867916)
+    - bcache: check and adjust logical block size for backing devices
+
+  * [SRU][OEM-5.6/U] Fix r8117 firmware base issue (LP: #1885072)
+    - r8169: add helper r8168g_phy_param
+    - r8169: add support for RTL8117
+    - r8169: load firmware for RTL8168fp/RTL8117
+    - r8169: fix OCP access on RTL8117
+    - r8169: fix firmware not resetting tp->ocp_base
+
+  * [UBUNTU 20.04] Deflate counters reported by lscpumf are not valid or
+    available with perf (LP: #1881096)
+    - s390/cpum_cf: Add new extended counters for IBM z15
+
+  * shiftfs: O_TMPFILE reports ESTALE (LP: #1872757)
+    - SAUCE: shiftfs: prevent ESTALE for LOOKUP_JUMP lookups
+
+  * shiftfs: fix btrfs regression (LP: #1884767)
+    - SAUCE: Revert "UBUNTU: SAUCE: shiftfs: fix dentry revalidation"
+
+  * Focal update: v5.4.52 upstream stable release (LP: #1887853)
+    - KVM: s390: reduce number of IO pins to 1
+    - spi: spi-fsl-dspi: Adding shutdown hook
+    - spi: spi-fsl-dspi: Fix lockup if device is removed during SPI transfer
+    - regmap: fix alignment issue
+    - perf/x86/rapl: Move RAPL support to common x86 code
+    - perf/x86/rapl: Fix RAPL config variable bug
+    - [Packaging] module intel-rapl-perf rename
+    - ARM: dts: omap4-droid4: Fix spi configuration and increase rate
+    - drm/ttm: Fix dma_fence refcnt leak when adding move fence
+    - drm/tegra: hub: Do not enable orphaned window group
+    - gpu: host1x: Detach driver on unregister
+    - drm: mcde: Fix display initialization problem
+    - ASoC: SOF: Intel: add PCI ID for CometLake-S
+    - ALSA: hda: Intel: add missing PCI IDs for ICL-H, TGL-H and EKL
+    - spi: spidev: fix a race between spidev_release and spidev_remove
+    - spi: spidev: fix a potential use-after-free in spidev_release()
+    - net: ethernet: mvneta: Fix Serdes configuration for SoCs without comphy
+    - net: ethernet: mvneta: Add 2500BaseX support for SoCs without comphy
+    - ixgbe: protect ring accesses with READ- and WRITE_ONCE
+    - i40e: protect ring accesses with READ- and WRITE_ONCE
+    - ibmvnic: continue to init in CRQ reset returns H_CLOSED
+    - powerpc/kvm/book3s64: Fix kernel crash with nested kvm & DEBUG_VIRTUAL
+    - iommu/vt-d: Don't apply gfx quirks to untrusted devices
+    - drm: panel-orientation-quirks: Add quirk for Asus T101HA panel
+    - drm: panel-orientation-quirks: Use generic orientation-data for Acer S1003
+    - s390/kasan: fix early pgm check handler execution
+    - cifs: update ctime and mtime during truncate
+    - ARM: imx6: add missing put_device() call in imx6q_suspend_init()
+    - scsi: mptscsih: Fix read sense data size
+    - usb: dwc3: pci: Fix reference count leak in dwc3_pci_resume_work
+    - block: release bip in a right way in error path
+    - nvme-rdma: assign completion vector correctly
+    - x86/entry: Increase entry_stack size to a full page
+    - sched/core: Check cpus_mask, not cpus_ptr in __set_cpus_allowed_ptr(), to
+      fix mask corruption
+    - net: qrtr: Fix an out of bounds read qrtr_endpoint_post()
+    - gpio: pca953x: Override IRQ for one of the expanders on Galileo Gen 2
+    - gpio: pca953x: Fix GPIO resource leak on Intel Galileo Gen 2
+    - nl80211: don't return err unconditionally in nl80211_start_ap()
+    - drm/mediatek: Check plane visibility in atomic_update
+    - bpf, sockmap: RCU splat with redirect and strparser error or TLS
+    - bpf, sockmap: RCU dereferenced psock may be used outside RCU block
+    - netfilter: ipset: call ip_set_free() instead of kfree()
+    - net: mvneta: fix use of state->speed
+    - net: cxgb4: fix return error value in t4_prep_fw
+    - IB/sa: Resolv use-after-free in ib_nl_make_request()
+    - net: dsa: microchip: set the correct number of ports
+    - netfilter: conntrack: refetch conntrack after nf_conntrack_update()
+    - perf report TUI: Fix segmentation fault in perf_evsel__hists_browse()
+    - perf intel-pt: Fix recording PEBS-via-PT with registers
+    - perf intel-pt: Fix PEBS sample for XMM registers
+    - smsc95xx: check return value of smsc95xx_reset
+    - smsc95xx: avoid memory leak in smsc95xx_bind
+    - net: hns3: add a missing uninit debugfs when unload driver
+    - net: hns3: fix use-after-free when doing self test
+    - ALSA: compress: fix partial_drain completion state
+    - RDMA/siw: Fix reporting vendor_part_id
+    - arm64: kgdb: Fix single-step exception handling oops
+    - nbd: Fix memory leak in nbd_add_socket
+    - cxgb4: fix all-mask IP address comparison
+    - IB/mlx5: Fix 50G per lane indication
+    - qed: Populate nvm-file attributes while reading nvm config partition.
+    - net/mlx5: Fix eeprom support for SFP module
+    - net/mlx5e: Fix 50G per lane indication
+    - bnxt_en: fix NULL dereference in case SR-IOV configuration fails
+    - net: macb: fix wakeup test in runtime suspend/resume routines
+    - net: macb: mark device wake capable when "magic-packet" property present
+    - net: macb: fix call to pm_runtime in the suspend/resume functions
+    - mlxsw: spectrum_router: Remove inappropriate usage of WARN_ON()
+    - mlxsw: pci: Fix use-after-free in case of failed devlink reload
+    - IB/hfi1: Do not destroy hfi1_wq when the device is shut down
+    - IB/hfi1: Do not destroy link_wq when the device is shut down
+    - ALSA: opl3: fix infoleak in opl3
+    - ALSA: hda - let hs_mic be picked ahead of hp_mic
+    - ALSA: usb-audio: add quirk for MacroSilicon MS2109
+    - ALSA: usb-audio: Add implicit feedback quirk for RTX6001
+    - ALSA: hda/realtek - Fix Lenovo Thinkpad X1 Carbon 7th quirk subdevice id
+    - ALSA: hda/realtek - Enable audio jacks of Acer vCopperbox with ALC269VC
+    - ALSA: hda/realtek: Enable headset mic of Acer C20-820 with ALC269VC
+    - ALSA: hda/realtek: Enable headset mic of Acer Veriton N4660G with ALC269VC
+    - KVM: arm64: Fix definition of PAGE_HYP_DEVICE
+    - KVM: arm64: Stop clobbering x0 for HVC_SOFT_RESTART
+    - KVM: arm64: Annotate hyp NMI-related functions as __always_inline
+    - KVM: x86: bit 8 of non-leaf PDPEs is not reserved
+    - KVM: x86: Inject #GP if guest attempts to toggle CR4.LA57 in 64-bit mode
+    - KVM: x86: Mark CR4.TSD as being possibly owned by the guest
+    - KVM: arm64: Fix kvm_reset_vcpu() return code being incorrect with SVE
+    - kallsyms: Refactor kallsyms_show_value() to take cred
+    - module: Refactor section attr into bin attribute
+    - module: Do not expose section addresses to non-CAP_SYSLOG
+    - kprobes: Do not expose probe addresses to non-CAP_SYSLOG
+    - bpf: Check correct cred for CAP_SYSLOG in bpf_dump_raw_ok()
+    - btrfs: fix fatal extent_buffer readahead vs releasepage race
+    - btrfs: fix double put of block group with nocow
+    - drm/radeon: fix double free
+    - drm/amdgpu: don't do soft recovery if gpu_recovery=0
+    - dm: use noio when sending kobject event
+    - mmc: meson-gx: limit segments to 1 when dram-access-quirk is needed
+    - ARC: entry: fix potential EFA clobber when TIF_SYSCALL_TRACE
+    - ARC: elf: use right ELF_ARCH
+    - s390/setup: init jump labels before command line parsing
+    - s390/mm: fix huge pte soft dirty copying
+    - blk-mq: consider non-idle request as "inflight" in blk_mq_rq_inflight()
+    - dm writecache: reject asynchronous pmem devices
+    - perf scripts python: export-to-postgresql.py: Fix struct.pack() int argument
+    - perf scripts python: exported-sql-viewer.py: Fix zero id in call graph
+      'Find' result
+    - perf scripts python: exported-sql-viewer.py: Fix zero id in call tree 'Find'
+      result
+    - perf scripts python: exported-sql-viewer.py: Fix unexpanded 'Find' result
+    - pwm: jz4740: Fix build failure
+    - s390: Change s390_kernel_write() return type to match memcpy()
+    - s390/maccess: add no DAT mode to kernel_write
+    - Linux 5.4.52
+
+  * Focal update: v5.4.45 upstream stable release (LP: #1882802) // Focal
+    update: v5.4.52 upstream stable release (LP: #1887853)
+    - Revert "cgroup: Add memory barriers to plug cgroup_rstat_updated() race
+      window"
+
+  * Focal update: v5.4.51 upstream stable release (LP: #1886995)
+    - io_uring: make sure async workqueue is canceled on exit
+    - mm: fix swap cache node allocation mask
+    - EDAC/amd64: Read back the scrub rate PCI register on F15h
+    - usbnet: smsc95xx: Fix use-after-free after removal
+    - sched/debug: Make sd->flags sysctl read-only
+    - mm/slub.c: fix corrupted freechain in deactivate_slab()
+    - mm/slub: fix stack overruns with SLUB_STATS
+    - rxrpc: Fix race between incoming ACK parser and retransmitter
+    - usb: usbtest: fix missing kfree(dev->buf) in usbtest_disconnect
+    - tools lib traceevent: Add append() function helper for appending strings
+    - tools lib traceevent: Handle __attribute__((user)) in field names
+    - s390/debug: avoid kernel warning on too large number of pages
+    - nvme-multipath: set bdi capabilities once
+    - nvme-multipath: fix deadlock between ana_work and scan_work
+    - nvme-multipath: fix deadlock due to head->lock
+    - nvme-multipath: fix bogus request queue reference put
+    - kgdb: Avoid suspicious RCU usage warning
+    - selftests: tpm: Use /bin/sh instead of /bin/bash
+    - crypto: af_alg - fix use-after-free in af_alg_accept() due to bh_lock_sock()
+    - drm/msm/dpu: fix error return code in dpu_encoder_init
+    - rxrpc: Fix afs large storage transmission performance drop
+    - RDMA/counter: Query a counter before release
+    - cxgb4: use unaligned conversion for fetching timestamp
+    - cxgb4: parse TC-U32 key values and masks natively
+    - cxgb4: fix endian conversions for L4 ports in filters
+    - cxgb4: use correct type for all-mask IP address comparison
+    - cxgb4: fix SGE queue dump destination buffer context
+    - hwmon: (max6697) Make sure the OVERT mask is set correctly
+    - hwmon: (acpi_power_meter) Fix potential memory leak in
+      acpi_power_meter_add()
+    - thermal/drivers/mediatek: Fix bank number settings on mt8183
+    - thermal/drivers/rcar_gen3: Fix undefined temperature if negative
+    - nfsd4: fix nfsdfs reference count loop
+    - nfsd: fix nfsdfs inode reference count leak
+    - drm: sun4i: hdmi: Remove extra HPD polling
+    - virtio-blk: free vblk-vqs in error path of virtblk_probe()
+    - SMB3: Honor 'posix' flag for multiuser mounts
+    - nvme: fix identify error status silent ignore
+    - nvme: fix a crash in nvme_mpath_add_disk
+    - samples/vfs: avoid warning in statx override
+    - i2c: algo-pca: Add 0x78 as SCL stuck low status for PCA9665
+    - i2c: mlxcpld: check correct size of maximum RECV_LEN packet
+    - spi: spi-fsl-dspi: Fix external abort on interrupt in resume or exit paths
+    - nfsd: apply umask on fs without ACL support
+    - Revert "ALSA: usb-audio: Improve frames size computation"
+    - SMB3: Honor 'seal' flag for multiuser mounts
+    - SMB3: Honor persistent/resilient handle flags for multiuser mounts
+    - SMB3: Honor lease disabling for multiuser mounts
+    - SMB3: Honor 'handletimeout' flag for multiuser mounts
+    - cifs: Fix the target file was deleted when rename failed.
+    - MIPS: lantiq: xway: sysctrl: fix the GPHY clock alias names
+    - MIPS: Add missing EHB in mtc0 -> mfc0 sequence for DSPen
+    - drm/amd/display: Only revalidate bandwidth on medium and fast updates
+    - drm/amdgpu: use %u rather than %d for sclk/mclk
+    - drm/amdgpu/atomfirmware: fix vram_info fetching for renoir
+    - dma-buf: Move dma_buf_release() from fops to dentry_ops
+    - irqchip/gic: Atomically update affinity
+    - mm, compaction: fully assume capture is not NULL in compact_zone_order()
+    - mm, compaction: make capture control handling safe wrt interrupts
+    - x86/resctrl: Fix memory bandwidth counter width for AMD
+    - dm zoned: assign max_io_len correctly
+    - [Config] updateconfigs for EFI_CUSTOM_SSDT_OVERLAYS
+    - efi: Make it possible to disable efivar_ssdt entirely
+    - Linux 5.4.51
+
+  * Focal update: v5.4.50 upstream stable release (LP: #1885942)
+    - block/bio-integrity: don't free 'buf' if bio_integrity_add_page() failed
+    - enetc: Fix tx rings bitmap iteration range, irq handling
+    - geneve: allow changing DF behavior after creation
+    - ibmveth: Fix max MTU limit
+    - mld: fix memory leak in ipv6_mc_destroy_dev()
+    - mvpp2: ethtool rxtx stats fix
+    - net: bridge: enfore alignment for ethernet address
+    - net: core: reduce recursion limit value
+    - net: Do not clear the sock TX queue in sk_set_socket()
+    - net: fix memleak in register_netdevice()
+    - net: Fix the arp error in some cases
+    - net: increment xmit_recursion level in dev_direct_xmit()
+    - net: usb: ax88179_178a: fix packet alignment padding
+    - openvswitch: take into account de-fragmentation/gso_size in
+      execute_check_pkt_len
+    - rocker: fix incorrect error handling in dma_rings_init
+    - rxrpc: Fix notification call on completion of discarded calls
+    - sctp: Don't advertise IPv4 addresses if ipv6only is set on the socket
+    - tcp: don't ignore ECN CWR on pure ACK
+    - tcp: grow window for OOO packets only for SACK flows
+    - tg3: driver sleeps indefinitely when EEH errors exceed eeh_max_freezes
+    - ip6_gre: fix use-after-free in ip6gre_tunnel_lookup()
+    - net: phy: Check harder for errors in get_phy_id()
+    - ip_tunnel: fix use-after-free in ip_tunnel_lookup()
+    - sch_cake: don't try to reallocate or unshare skb unconditionally
+    - sch_cake: don't call diffserv parsing code when it is not needed
+    - sch_cake: fix a few style nits
+    - tcp_cubic: fix spurious HYSTART_DELAY exit upon drop in min RTT
+    - Revert "i2c: tegra: Fix suspending in active runtime PM state"
+    - btrfs: fix a block group ref counter leak after failure to remove block
+      group
+    - net: sched: export __netdev_watchdog_up()
+    - fix a braino in "sparc32: fix register window handling in
+      genregs32_[gs]et()"
+    - ALSA: usb-audio: Fix potential use-after-free of streams
+    - binder: fix null deref of proc->context
+    - USB: ohci-sm501: Add missed iounmap() in remove
+    - usb: dwc2: Postponed gadget registration to the udc class driver
+    - usb: add USB_QUIRK_DELAY_INIT for Logitech C922
+    - USB: ehci: reopen solution for Synopsys HC bug
+    - usb: host: xhci-mtk: avoid runtime suspend when removing hcd
+    - xhci: Poll for U0 after disabling USB2 LPM
+    - usb: host: ehci-exynos: Fix error check in exynos_ehci_probe()
+    - usb: typec: tcpci_rt1711h: avoid screaming irq causing boot hangs
+    - ALSA: usb-audio: Add implicit feedback quirk for SSL2+.
+    - ALSA: usb-audio: add quirk for Denon DCD-1500RE
+    - ALSA: usb-audio: add quirk for Samsung USBC Headset (AKG)
+    - ALSA: usb-audio: Fix OOB access of mixer element list
+    - usb: cdns3: trace: using correct dir value
+    - usb: cdns3: ep0: fix the test mode set incorrectly
+    - usb: cdns3: ep0: add spinlock for cdns3_check_new_setup
+    - scsi: qla2xxx: Keep initiator ports after RSCN
+    - scsi: zfcp: Fix panic on ERP timeout for previously dismissed ERP action
+    - cifs: Fix cached_fid refcnt leak in open_shroot
+    - cifs/smb3: Fix data inconsistent when punch hole
+    - cifs/smb3: Fix data inconsistent when zero file range
+    - xhci: Fix incorrect EP_STATE_MASK
+    - xhci: Fix enumeration issue when setting max packet size for FS devices.
+    - xhci: Return if xHCI doesn't support LPM
+    - cdc-acm: Add DISABLE_ECHO quirk for Microchip/SMSC chip
+    - loop: replace kill_bdev with invalidate_bdev
+    - IB/mad: Fix use after free when destroying MAD agent
+    - IB/hfi1: Fix module use count flaw due to leftover module put calls
+    - bus: ti-sysc: Flush posted write on enable and disable
+    - bus: ti-sysc: Ignore clockactivity unless specified as a quirk
+    - ARM: OMAP2+: Fix legacy mode dss_reset
+    - xfrm: Fix double ESP trailer insertion in IPsec crypto offload.
+    - ASoC: q6asm: handle EOS correctly
+    - efi/tpm: Verify event log header before parsing
+    - efi/esrt: Fix reference count leak in esre_create_sysfs_entry.
+    - ASoc: q6afe: add support to get port direction
+    - ASoC: qcom: common: set correct directions for dailinks
+    - regualtor: pfuze100: correct sw1a/sw2 on pfuze3000
+    - RDMA/siw: Fix pointer-to-int-cast warning in siw_rx_pbl()
+    - ASoC: fsl_ssi: Fix bclk calculation for mono channel
+    - samples/bpf: xdp_redirect_cpu: Set MAX_CPUS according to NR_CPUS
+    - bpf, xdp, samples: Fix null pointer dereference in *_user code
+    - ARM: dts: am335x-pocketbeagle: Fix mmc0 Write Protect
+    - ARM: dts: Fix duovero smsc interrupt for suspend
+    - x86/resctrl: Fix a NULL vs IS_ERR() static checker warning in
+      rdt_cdp_peer_get()
+    - regmap: Fix memory leak from regmap_register_patch
+    - devmap: Use bpf_map_area_alloc() for allocating hash buckets
+    - bpf: Don't return EINVAL from {get,set}sockopt when optlen > PAGE_SIZE
+    - ARM: dts: NSP: Correct FA2 mailbox node
+    - rxrpc: Fix handling of rwind from an ACK packet
+    - RDMA/rvt: Fix potential memory leak caused by rvt_alloc_rq
+    - RDMA/qedr: Fix KASAN: use-after-free in ucma_event_handler+0x532
+    - RDMA/cma: Protect bind_list and listen_list while finding matching cm id
+    - ASoC: rockchip: Fix a reference count leak.
+    - s390/qeth: fix error handling for isolation mode cmds
+    - RDMA/mad: Fix possible memory leak in ib_mad_post_receive_mads()
+    - selftests/net: report etf errors correctly
+    - iommu/vt-d: Enable PCI ACS for platform opt in hint
+    - iommu/vt-d: Update scalable mode paging structure coherency
+    - net: qed: fix left elements count calculation
+    - net: qed: fix async event callbacks unregistering
+    - net: qede: stop adding events on an already destroyed workqueue
+    - net: qed: fix NVMe login fails over VFs
+    - net: qed: fix excessive QM ILT lines consumption
+    - net: qede: fix PTP initialization on recovery
+    - net: qede: fix use-after-free on recovery and AER handling
+    - cxgb4: move handling L2T ARP failures to caller
+    - ARM: imx5: add missing put_device() call in imx_suspend_alloc_ocram()
+    - scsi: lpfc: Avoid another null dereference in lpfc_sli4_hba_unset()
+    - usb: gadget: udc: Potential Oops in error handling code
+    - usb: renesas_usbhs: getting residue from callback_result
+    - nvme: don't protect ns mutation with ns->head->lock
+    - netfilter: ipset: fix unaligned atomic access
+    - net: bcmgenet: use hardware padding of runt frames
+    - clk: sifive: allocate sufficient memory for struct __prci_data
+    - i2c: fsi: Fix the port number field in status register
+    - i2c: core: check returned size of emulated smbus block read
+    - afs: Fix storage of cell names
+    - sched/deadline: Initialize ->dl_boosted
+    - sched/core: Fix PI boosting between RT and DEADLINE tasks
+    - sata_rcar: handle pm_runtime_get_sync failure cases
+    - ata/libata: Fix usage of page address by page_address in
+      ata_scsi_mode_select_xlat function
+    - drm/amd/display: Use kfree() to free rgb_user in
+      calculate_user_regamma_ramp()
+    - riscv/atomic: Fix sign extension for RV64I
+    - hwrng: ks-sa - Fix runtime PM imbalance on error
+    - ibmvnic: Harden device login requests
+    - net: alx: fix race condition in alx_remove
+    - test_objagg: Fix potential memory leak in error handling
+    - pinctrl: qcom: spmi-gpio: fix warning about irq chip reusage
+    - pinctrl: tegra: Use noirq suspend/resume callbacks
+    - s390/ptrace: pass invalid syscall numbers to tracing
+    - s390/ptrace: fix setting syscall number
+    - s390/vdso: Use $(LD) instead of $(CC) to link vDSO
+    - s390/vdso: fix vDSO clock_getres()
+    - arm64: sve: Fix build failure when ARM64_SVE=y and SYSCTL=n
+    - kbuild: improve cc-option to clean up all temporary files
+    - recordmcount: support >64k sections
+    - kprobes: Suppress the suspicious RCU warning on kprobes
+    - blktrace: break out of blktrace setup on concurrent calls
+    - block: update hctx map when use multiple maps
+    - RISC-V: Don't allow write+exec only page mapping request in mmap
+    - ALSA: hda: Add NVIDIA codec IDs 9a & 9d through a0 to patch table
+    - ALSA: hda/realtek - Add quirk for MSI GE63 laptop
+    - ACPI: sysfs: Fix pm_profile_attr type
+    - erofs: fix partially uninitialized misuse in z_erofs_onlinepage_fixup
+    - KVM: X86: Fix MSR range of APIC registers in X2APIC mode
+    - KVM: nVMX: Plumb L2 GPA through to PML emulation
+    - KVM: VMX: Stop context switching MSR_IA32_UMWAIT_CONTROL
+    - x86/cpu: Use pinning mask for CR4 bits needing to be 0
+    - x86/asm/64: Align start of __clear_user() loop to 16-bytes
+    - btrfs: fix bytes_may_use underflow when running balance and scrub in
+      parallel
+    - btrfs: fix data block group relocation failure due to concurrent scrub
+    - btrfs: check if a log root exists before locking the log_mutex on unlink
+    - btrfs: fix failure of RWF_NOWAIT write into prealloc extent beyond eof
+    - mm/slab: use memzero_explicit() in kzfree()
+    - ocfs2: avoid inode removal while nfsd is accessing it
+    - ocfs2: load global_inode_alloc
+    - ocfs2: fix value of OCFS2_INVALID_SLOT
+    - ocfs2: fix panic on nfs server over ocfs2
+    - mm/memcontrol.c: add missed css_put()
+    - arm64: perf: Report the PC value in REGS_ABI_32 mode
+    - arm64: dts: imx8mm-evk: correct ldo1/ldo2 voltage range
+    - arm64: dts: imx8mn-ddr4-evk: correct ldo1/ldo2 voltage range
+    - tracing: Fix event trigger to accept redundant spaces
+    - ring-buffer: Zero out time extend if it is nested and not absolute
+    - drm/amd: fix potential memleak in err branch
+    - drm: rcar-du: Fix build error
+    - drm/radeon: fix fb_div check in ni_init_smc_spll_table()
+    - drm/amdgpu: add fw release for sdma v5_0
+    - Staging: rtl8723bs: prevent buffer overflow in update_sta_support_rate()
+    - sunrpc: fixed rollback in rpc_gssd_dummy_populate()
+    - SUNRPC: Properly set the @subbuf parameter of xdr_buf_subsegment()
+    - pNFS/flexfiles: Fix list corruption if the mirror count changes
+    - NFSv4 fix CLOSE not waiting for direct IO compeletion
+    - xprtrdma: Fix handling of RDMA_ERROR replies
+    - dm writecache: correct uncommitted_block when discarding uncommitted entry
+    - dm writecache: add cond_resched to loop in persistent_memory_claim()
+    - xfs: add agf freeblocks verify in xfs_agf_verify
+    - Revert "tty: hvc: Fix data abort due to race in hvc_open"
+    - Linux 5.4.50
+
+  * Focal update: v5.4.49 upstream stable release (LP: #1885322)
+    - power: supply: bq24257_charger: Replace depends on REGMAP_I2C with select
+    - clk: sunxi: Fix incorrect usage of round_down()
+    - ASoC: tegra: tegra_wm8903: Support nvidia, headset property
+    - i2c: piix4: Detect secondary SMBus controller on AMD AM4 chipsets
+    - ASoC: SOF: imx8: Fix randbuild error
+    - iio: pressure: bmp280: Tolerate IRQ before registering
+    - remoteproc: Fix IDR initialisation in rproc_alloc()
+    - clk: qcom: msm8916: Fix the address location of pll->config_reg
+    - ASoC: fsl_esai: Disable exception interrupt before scheduling tasklet
+    - backlight: lp855x: Ensure regulators are disabled on probe failure
+    - ARM: dts: renesas: Fix IOMMU device node names
+    - ASoC: davinci-mcasp: Fix dma_chan refcnt leak when getting dma type
+    - ARM: integrator: Add some Kconfig selections
+    - ARM: dts: stm32: Add missing ethernet PHY reset on AV96
+    - scsi: core: free sgtables in case command setup fails
+    - scsi: qedi: Check for buffer overflow in qedi_set_path()
+    - arm64: dts: meson: fixup SCP sram nodes
+    - ALSA: isa/wavefront: prevent out of bounds write in ioctl
+    - PCI: Allow pci_resize_resource() for devices on root bus
+    - scsi: qla2xxx: Fix issue with adapter's stopping state
+    - Input: edt-ft5x06 - fix get_default register write access
+    - powerpc/kasan: Fix stack overflow by increasing THREAD_SHIFT
+    - rtc: mc13xxx: fix a double-unlock issue
+    - iio: bmp280: fix compensation of humidity
+    - f2fs: report delalloc reserve as non-free in statfs for project quota
+    - i2c: pxa: clear all master action bits in i2c_pxa_stop_message()
+    - remoteproc: qcom_q6v5_mss: map/unmap mpss segments before/after use
+    - clk: samsung: Mark top ISP and CAM clocks on Exynos542x as critical
+    - usblp: poison URBs upon disconnect
+    - serial: 8250: Fix max baud limit in generic 8250 port
+    - misc: fastrpc: Fix an incomplete memory release in fastrpc_rpmsg_probe()
+    - misc: fastrpc: fix potential fastrpc_invoke_ctx leak
+    - dm mpath: switch paths in dm_blk_ioctl() code path
+    - arm64: dts: armada-3720-turris-mox: forbid SDR104 on SDIO for FCC purposes
+    - arm64: dts: armada-3720-turris-mox: fix SFP binding
+    - arm64: dts: juno: Fix GIC child nodes
+    - pinctrl: ocelot: Fix GPIO interrupt decoding on Jaguar2
+    - clk: renesas: cpg-mssr: Fix STBCR suspend/resume handling
+    - ASoC: SOF: Do nothing when DSP PM callbacks are not set
+    - arm64: dts: fvp: Fix GIC child nodes
+    - PCI: aardvark: Don't blindly enable ASPM L0s and don't write to read-only
+      register
+    - ps3disk: use the default segment boundary
+    - arm64: dts: fvp/juno: Fix node address fields
+    - vfio/pci: fix memory leaks in alloc_perm_bits()
+    - coresight: tmc: Fix TMC mode read in tmc_read_prepare_etb()
+    - RDMA/mlx5: Add init2init as a modify command
+    - scsi: hisi_sas: Do not reset phy timer to wait for stray phy up
+    - PCI: pci-bridge-emul: Fix PCIe bit conflicts
+    - m68k/PCI: Fix a memory leak in an error handling path
+    - gpio: dwapb: Call acpi_gpiochip_free_interrupts() on GPIO chip de-
+      registration
+    - usb: gadget: core: sync interrupt before unbind the udc
+    - powerpc/ptdump: Add _PAGE_COHERENT flag
+    - mfd: wm8994: Fix driver operation if loaded as modules
+    - scsi: cxgb3i: Fix some leaks in init_act_open()
+    - clk: zynqmp: fix memory leak in zynqmp_register_clocks
+    - scsi: lpfc: Fix lpfc_nodelist leak when processing unsolicited event
+    - scsi: vhost: Notify TCM about the maximum sg entries supported per command
+    - clk: clk-flexgen: fix clock-critical handling
+    - IB/mlx5: Fix DEVX support for MLX5_CMD_OP_INIT2INIT_QP command
+    - powerpc/perf/hv-24x7: Fix inconsistent output values incase multiple hv-24x7
+      events run
+    - nfsd: Fix svc_xprt refcnt leak when setup callback client failed
+    - PCI: vmd: Filter resource type bits from shadow register
+    - RDMA/core: Fix several reference count leaks.
+    - cifs: set up next DFS target before generic_ip_connect()
+    - ASoC: qcom: q6asm-dai: kCFI fix
+    - powerpc/crashkernel: Take "mem=" option into account
+    - pwm: img: Call pm_runtime_put() in pm_runtime_get_sync() failed case
+    - sparc32: mm: Don't try to free page-table pages if ctor() fails
+    - yam: fix possible memory leak in yam_init_driver
+    - NTB: ntb_pingpong: Choose doorbells based on port number
+    - NTB: Fix the default port and peer numbers for legacy drivers
+    - mksysmap: Fix the mismatch of '.L' symbols in System.map
+    - apparmor: fix introspection of of task mode for unconfined tasks
+    - net: dsa: lantiq_gswip: fix and improve the unsupported interface error
+    - f2fs: handle readonly filesystem in f2fs_ioc_shutdown()
+    - ASoC: meson: add missing free_irq() in error path
+    - bpf, sockhash: Fix memory leak when unlinking sockets in sock_hash_free
+    - scsi: sr: Fix sr_probe() missing deallocate of device minor
+    - scsi: ibmvscsi: Don't send host info in adapter info MAD after LPM
+    - x86/purgatory: Disable various profiling and sanitizing options
+    - staging: greybus: fix a missing-check bug in gb_lights_light_config()
+    - arm64: dts: mt8173: fix unit name warnings
+    - scsi: qedi: Do not flush offload work if ARP not resolved
+    - arm64: dts: qcom: msm8916: remove unit name for thermal trip points
+    - ARM: dts: sun8i-h2-plus-bananapi-m2-zero: Fix led polarity
+    - RDMA/mlx5: Fix udata response upon SRQ creation
+    - gpio: dwapb: Append MODULE_ALIAS for platform driver
+    - scsi: qedf: Fix crash when MFW calls for protocol stats while function is
+      still probing
+    - pinctrl: rza1: Fix wrong array assignment of rza1l_swio_entries
+    - virtiofs: schedule blocking async replies in separate worker
+    - arm64: dts: qcom: fix pm8150 gpio interrupts
+    - firmware: qcom_scm: fix bogous abuse of dma-direct internals
+    - staging: gasket: Fix mapping refcnt leak when put attribute fails
+    - staging: gasket: Fix mapping refcnt leak when register/store fails
+    - ALSA: usb-audio: Improve frames size computation
+    - ALSA: usb-audio: Fix racy list management in output queue
+    - s390/qdio: put thinint indicator after early error
+    - tty: hvc: Fix data abort due to race in hvc_open
+    - slimbus: ngd: get drvdata from correct device
+    - clk: meson: meson8b: Fix the first parent of vid_pll_in_sel
+    - clk: meson: meson8b: Fix the polarity of the RESET_N lines
+    - clk: meson: meson8b: Fix the vclk_div{1, 2, 4, 6, 12}_en gate bits
+    - gpio: pca953x: fix handling of automatic address incrementing
+    - thermal/drivers/ti-soc-thermal: Avoid dereferencing ERR_PTR
+    - clk: meson: meson8b: Don't rely on u-boot to init all GP_PLL registers
+    - ASoC: max98373: reorder max98373_reset() in resume
+    - soundwire: slave: don't init debugfs on device registration error
+    - HID: intel-ish-hid: avoid bogus uninitialized-variable warning
+    - usb: dwc3: gadget: Properly handle ClearFeature(halt)
+    - usb: dwc3: gadget: Properly handle failed kick_transfer
+    - staging: wilc1000: Increase the size of wid_list array
+    - staging: sm750fb: add missing case while setting FB_VISUAL
+    - PCI: v3-semi: Fix a memory leak in v3_pci_probe() error handling paths
+    - i2c: pxa: fix i2c_pxa_scream_blue_murder() debug output
+    - serial: amba-pl011: Make sure we initialize the port.lock spinlock
+    - drivers: base: Fix NULL pointer exception in __platform_driver_probe() if a
+      driver developer is foolish
+    - PCI: rcar: Fix incorrect programming of OB windows
+    - PCI/ASPM: Allow ASPM on links to PCIe-to-PCI/PCI-X Bridges
+    - scsi: qla2xxx: Fix warning after FC target reset
+    - ALSA: firewire-lib: fix invalid assignment to union data for directional
+      parameter
+    - power: supply: lp8788: Fix an error handling path in
+      'lp8788_charger_probe()'
+    - power: supply: smb347-charger: IRQSTAT_D is volatile
+    - ASoC: SOF: core: fix error return code in sof_probe_continue()
+    - arm64: dts: msm8996: Fix CSI IRQ types
+    - scsi: target: loopback: Fix READ with data and sensebytes
+    - scsi: mpt3sas: Fix double free warnings
+    - SoC: rsnd: add interrupt support for SSI BUSIF buffer
+    - ASoC: ux500: mop500: Fix some refcounted resources issues
+    - ASoC: ti: omap-mcbsp: Fix an error handling path in 'asoc_mcbsp_probe()'
+    - pinctrl: rockchip: fix memleak in rockchip_dt_node_to_map
+    - dlm: remove BUG() before panic()
+    - USB: ohci-sm501: fix error return code in ohci_hcd_sm501_drv_probe()
+    - clk: ti: composite: fix memory leak
+    - PCI: Fix pci_register_host_bridge() device_register() error handling
+    - powerpc/64: Don't initialise init_task->thread.regs
+    - tty: n_gsm: Fix SOF skipping
+    - tty: n_gsm: Fix waking up upper tty layer when room available
+    - ALSA: usb-audio: Add duplex sound support for USB devices using implicit
+      feedback
+    - HID: Add quirks for Trust Panora Graphic Tablet
+    - PCI/PM: Assume ports without DLL Link Active train links in 100 ms
+    - habanalabs: increase timeout during reset
+    - ipmi: use vzalloc instead of kmalloc for user creation
+    - powerpc/64s/exception: Fix machine check no-loss idle wakeup
+    - powerpc/pseries/ras: Fix FWNMI_VALID off by one
+    - drivers: phy: sr-usb: do not use internal fsm for USB2 phy init
+    - powerpc/ps3: Fix kexec shutdown hang
+    - vfio-pci: Mask cap zero
+    - usb/ohci-platform: Fix a warning when hibernating
+    - drm/msm/mdp5: Fix mdp5_init error path for failed mdp5_kms allocation
+    - ASoC: Intel: bytcr_rt5640: Add quirk for Toshiba Encore WT8-A tablet
+    - USB: host: ehci-mxc: Add error handling in ehci_mxc_drv_probe()
+    - tty: n_gsm: Fix bogus i++ in gsm_data_kick
+    - fpga: dfl: afu: Corrected error handling levels
+    - clk: samsung: exynos5433: Add IGNORE_UNUSED flag to sclk_i2s1
+    - RDMA/hns: Bugfix for querying qkey
+    - RDMA/hns: Fix cmdq parameter of querying pf timer resource
+    - scsi: target: tcmu: Userspace must not complete queued commands
+    - firmware: imx: scu: Fix possible memory leak in imx_scu_probe()
+    - fuse: fix copy_file_range cache issues
+    - fuse: copy_file_range should truncate cache
+    - arm64: tegra: Fix ethernet phy-mode for Jetson Xavier
+    - arm64: tegra: Fix flag for 64-bit resources in 'ranges' property
+    - powerpc/64s/pgtable: fix an undefined behaviour
+    - dm zoned: return NULL if dmz_get_zone_for_reclaim() fails to find a zone
+    - PCI/PTM: Inherit Switch Downstream Port PTM settings from Upstream Port
+    - PCI: dwc: Fix inner MSI IRQ domain registration
+    - PCI: amlogic: meson: Don't use FAST_LINK_MODE to set up link
+    - IB/cma: Fix ports memory leak in cma_configfs
+    - watchdog: da9062: No need to ping manually before setting timeout
+    - usb: dwc2: gadget: move gadget resume after the core is in L0 state
+    - USB: gadget: udc: s3c2410_udc: Remove pointless NULL check in
+      s3c2410_udc_nuke
+    - usb: gadget: lpc32xx_udc: don't dereference ep pointer before null check
+    - usb: gadget: fix potential double-free in m66592_probe.
+    - usb: gadget: Fix issue with config_ep_by_speed function
+    - scripts: headers_install: Exit with error on config leak
+    - RDMA/iw_cxgb4: cleanup device debugfs entries on ULD remove
+    - x86/apic: Make TSC deadline timer detection message visible
+    - mfd: stmfx: Reset chip on resume as supply was disabled
+    - mfd: stmfx: Fix stmfx_irq_init error path
+    - mfd: stmfx: Disable IRQ in suspend to avoid spurious interrupt
+    - powerpc/32s: Don't warn when mapping RO data ROX.
+    - ASoC: fix incomplete error-handling in img_i2s_in_probe.
+    - scsi: target: tcmu: Fix a use after free in tcmu_check_expired_queue_cmd()
+    - clk: bcm2835: Fix return type of bcm2835_register_gate
+    - scsi: ufs-qcom: Fix scheduling while atomic issue
+    - KVM: PPC: Book3S HV: Ignore kmemleak false positives
+    - KVM: PPC: Book3S: Fix some RCU-list locks
+    - clk: sprd: return correct type of value for _sprd_pll_recalc_rate
+    - clk: ast2600: Fix AHB clock divider for A1
+    - misc: xilinx-sdfec: improve get_user_pages_fast() error handling
+    - /dev/mem: Revoke mappings when a driver claims the region
+    - net: sunrpc: Fix off-by-one issues in 'rpc_ntop6'
+    - NFSv4.1 fix rpc_call_done assignment for BIND_CONN_TO_SESSION
+    - of: Fix a refcounting bug in __of_attach_node_sysfs()
+    - input: i8042 - Remove special PowerPC handling
+    - powerpc/4xx: Don't unmap NULL mbase
+    - extcon: adc-jack: Fix an error handling path in 'adc_jack_probe()'
+    - ASoC: fsl_asrc_dma: Fix dma_chan leak when config DMA channel failed
+    - vfio/mdev: Fix reference count leak in add_mdev_supported_type
+    - rtc: rv3028: Add missed check for devm_regmap_init_i2c()
+    - mailbox: zynqmp-ipi: Fix NULL vs IS_ERR() check in zynqmp_ipi_mbox_probe()
+    - rxrpc: Adjust /proc/net/rxrpc/calls to display call->debug_id not user_ID
+    - openrisc: Fix issue with argument clobbering for clone/fork
+    - drm/nouveau/disp/gm200-: fix NV_PDISP_SOR_HDMI2_CTRL(n) selection
+    - ceph: don't return -ESTALE if there's still an open file
+    - nfsd4: make drc_slab global, not per-net
+    - gfs2: Allow lock_nolock mount to specify jid=X
+    - scsi: iscsi: Fix reference count leak in iscsi_boot_create_kobj
+    - scsi: ufs: Don't update urgent bkops level when toggling auto bkops
+    - pinctrl: imxl: Fix an error handling path in 'imx1_pinctrl_core_probe()'
+    - pinctrl: freescale: imx: Fix an error handling path in 'imx_pinctrl_probe()'
+    - nfsd: safer handling of corrupted c_type
+    - drm/amd/display: Revalidate bandwidth before commiting DC updates
+    - crypto: omap-sham - add proper load balancing support for multicore
+    - geneve: change from tx_error to tx_dropped on missing metadata
+    - lib/zlib: remove outdated and incorrect pre-increment optimization
+    - include/linux/bitops.h: avoid clang shift-count-overflow warnings
+    - selftests/vm/pkeys: fix alloc_random_pkey() to make it really random
+    - blktrace: use errno instead of bi_status
+    - blktrace: fix endianness in get_pdu_int()
+    - blktrace: fix endianness for blk_log_remap()
+    - gfs2: fix use-after-free on transaction ail lists
+    - net: marvell: Fix OF_MDIO config check
+    - ntb_perf: pass correct struct device to dma_alloc_coherent
+    - ntb_tool: pass correct struct device to dma_alloc_coherent
+    - NTB: ntb_tool: reading the link file should not end in a NULL byte
+    - NTB: Revert the change to use the NTB device dev for DMA allocations
+    - NTB: perf: Don't require one more memory window than number of peers
+    - NTB: perf: Fix support for hardware that doesn't have port numbers
+    - NTB: perf: Fix race condition when run with ntb_test
+    - NTB: ntb_test: Fix bug when counting remote files
+    - i2c: icy: Fix build with CONFIG_AMIGA_PCMCIA=n
+    - drivers/perf: hisi: Fix wrong value for all counters enable
+    - selftests/net: in timestamping, strncpy needs to preserve null byte
+    - f2fs: don't return vmalloc() memory from f2fs_kmalloc()
+    - afs: Fix memory leak in afs_put_sysnames()
+    - ASoC: core: only convert non DPCM link to DPCM link
+    - ASoC: SOF: nocodec: conditionally set dpcm_capture/dpcm_playback flags
+    - ASoC: Intel: bytcr_rt5640: Add quirk for Toshiba Encore WT10-A tablet
+    - ASoC: rt5645: Add platform-data for Asus T101HA
+    - bpf/sockmap: Fix kernel panic at __tcp_bpf_recvmsg
+    - bpf, sockhash: Synchronize delete from bucket list on map free
+    - tracing/probe: Fix bpf_task_fd_query() for kprobes and uprobes
+    - drm/sun4i: hdmi ddc clk: Fix size of m divider
+    - libbpf: Handle GCC noreturn-turned-volatile quirk
+    - scsi: acornscsi: Fix an error handling path in acornscsi_probe()
+    - x86/idt: Keep spurious entries unset in system_vectors
+    - net/filter: Permit reading NET in load_bytes_relative when MAC not set
+    - nvme-pci: use simple suspend when a HMB is enabled
+    - nfs: set invalid blocks after NFSv4 writes
+    - xdp: Fix xsk_generic_xmit errno
+    - iavf: fix speed reporting over virtchnl
+    - bpf: Fix memlock accounting for sock_hash
+    - usb/xhci-plat: Set PM runtime as active on resume
+    - usb: host: ehci-platform: add a quirk to avoid stuck
+    - usb/ehci-platform: Set PM runtime as active on resume
+    - perf report: Fix NULL pointer dereference in
+      hists__fprintf_nr_sample_events()
+    - perf stat: Fix NULL pointer dereference
+    - ext4: stop overwrite the errcode in ext4_setup_super
+    - bcache: fix potential deadlock problem in btree_gc_coalesce
+    - powerpc: Fix kernel crash in show_instructions() w/DEBUG_VIRTUAL
+    - afs: Fix non-setting of mtime when writing into mmap
+    - afs: afs_write_end() should change i_size under the right lock
+    - afs: Fix EOF corruption
+    - afs: Always include dir in bulk status fetch from afs_do_lookup()
+    - afs: Set error flag rather than return error from file status decode
+    - afs: Fix the mapping of the UAEOVERFLOW abort code
+    - bnxt_en: Return from timer if interface is not in open state.
+    - scsi: ufs-bsg: Fix runtime PM imbalance on error
+    - block: Fix use-after-free in blkdev_get()
+    - mvpp2: remove module bugfix
+    - arm64: hw_breakpoint: Don't invoke overflow handler on uaccess watchpoints
+    - drm: encoder_slave: fix refcouting error for modules
+    - ext4: fix partial cluster initialization when splitting extent
+    - ext4: avoid utf8_strncasecmp() with unstable name
+    - drm/dp_mst: Reformat drm_dp_check_act_status() a bit
+    - drm/qxl: Use correct notify port address when creating cursor ring
+    - drm/amdgpu: Replace invalid device ID with a valid device ID
+    - selinux: fix double free
+    - jbd2: clean __jbd2_journal_abort_hard() and __journal_abort_soft()
+    - ext4: avoid race conditions when remounting with options that change dax
+    - drm/dp_mst: Increase ACT retry timeout to 3s
+    - drm/amd/display: Use swap() where appropriate
+    - x86/boot/compressed: Relax sed symbol type regex for LLVM ld.lld
+    - block: nr_sects_write(): Disable preemption on seqcount write
+    - net/mlx5: DR, Fix freeing in dr_create_rc_qp()
+    - f2fs: split f2fs_d_compare() from f2fs_match_name()
+    - f2fs: avoid utf8_strncasecmp() with unstable name
+    - s390: fix syscall_get_error for compat processes
+    - drm/i915: Fix AUX power domain toggling across TypeC mode resets
+    - drm/msm: Check for powered down HW in the devfreq callbacks
+    - drm/i915/gem: Avoid iterating an empty list
+    - drm/i915: Whitelist context-local timestamp in the gen9 cmdparser
+    - drm/connector: notify userspace on hotplug after register complete
+    - drm/amd/display: Use kvfree() to free coeff in build_regamma()
+    - drm/i915/icl+: Fix hotplug interrupt disabling after storm detection
+    - Revert "drm/amd/display: disable dcn20 abm feature for bring up"
+    - crypto: algif_skcipher - Cap recv SG list at ctx->used
+    - crypto: algboss - don't wait during notifier callback
+    - tracing/probe: Fix memleak in fetch_op_data operations
+    - kprobes: Fix to protect kick_kprobe_optimizer() by kprobe_mutex
+    - kretprobe: Prevent triggering kretprobe from within kprobe_flush_task
+    - e1000e: Do not wake up the system via WOL if device wakeup is disabled
+    - net: octeon: mgmt: Repair filling of RX ring
+    - pwm: jz4740: Enhance precision in calculation of duty cycle
+    - sched/rt, net: Use CONFIG_PREEMPTION.patch
+    - net: core: device_rename: Use rwsem instead of a seqcount
+    - Linux 5.4.49
+
+  * Computer is frozen after suspend (LP: #1867983) // Focal update: v5.4.49
+    upstream stable release (LP: #1885322)
+    - libata: Use per port sync for detach
+
+  * Focal update: v5.4.48 upstream stable release (LP: #1885023)
+    - ACPI: GED: use correct trigger type field in _Exx / _Lxx handling
+    - drm/amdgpu: fix and cleanup amdgpu_gem_object_close v4
+    - ath10k: Fix the race condition in firmware dump work queue
+    - drm: bridge: adv7511: Extend list of audio sample rates
+    - media: staging: imgu: do not hold spinlock during freeing mmu page table
+    - media: imx: imx7-mipi-csis: Cleanup and fix subdev pad format handling
+    - crypto: ccp -- don't "select" CONFIG_DMADEVICES
+    - media: vicodec: Fix error codes in probe function
+    - media: si2157: Better check for running tuner in init
+    - objtool: Ignore empty alternatives
+    - spi: spi-mem: Fix Dual/Quad modes on Octal-capable devices
+    - drm/amdgpu: Init data to avoid oops while reading pp_num_states.
+    - arm64/kernel: Fix range on invalidating dcache for boot page tables
+    - libbpf: Fix memory leak and possible double-free in hashmap__clear
+    - spi: pxa2xx: Apply CS clk quirk to BXT
+    - x86,smap: Fix smap_{save,restore}() alternatives
+    - sched/fair: Refill bandwidth before scaling
+    - net: atlantic: make hw_get_regs optional
+    - net: ena: fix error returning in ena_com_get_hash_function()
+    - efi/libstub/x86: Work around LLVM ELF quirk build regression
+    - ath10k: remove the max_sched_scan_reqs value
+    - arm64: cacheflush: Fix KGDB trap detection
+    - media: staging: ipu3: Fix stale list entries on parameter queue failure
+    - rtw88: fix an issue about leak system resources
+    - spi: dw: Zero DMA Tx and Rx configurations on stack
+    - ACPICA: Dispatcher: add status checks
+    - block: alloc map and request for new hardware queue
+    - arm64: insn: Fix two bugs in encoding 32-bit logical immediates
+    - block: reset mapping if failed to update hardware queue count
+    - drm: rcar-du: Set primary plane zpos immutably at initializing
+    - lockdown: Allow unprivileged users to see lockdown status
+    - ixgbe: Fix XDP redirect on archs with PAGE_SIZE above 4K
+    - platform/x86: dell-laptop: don't register micmute LED if there is no token
+    - MIPS: Loongson: Build ATI Radeon GPU driver as module
+    - Bluetooth: Add SCO fallback for invalid LMP parameters error
+    - kgdb: Disable WARN_CONSOLE_UNLOCKED for all kgdb
+    - kgdb: Prevent infinite recursive entries to the debugger
+    - pmu/smmuv3: Clear IRQ affinity hint on device removal
+    - ACPI/IORT: Fix PMCG node single ID mapping handling
+    - mips: Fix cpu_has_mips64r1/2 activation for MIPS32 CPUs
+    - spi: dw: Enable interrupts in accordance with DMA xfer mode
+    - clocksource: dw_apb_timer: Make CPU-affiliation being optional
+    - clocksource: dw_apb_timer_of: Fix missing clockevent timers
+    - media: dvbdev: Fix tuner->demod media controller link
+    - btrfs: account for trans_block_rsv in may_commit_transaction
+    - btrfs: do not ignore error from btrfs_next_leaf() when inserting checksums
+    - ARM: 8978/1: mm: make act_mm() respect THREAD_SIZE
+    - batman-adv: Revert "disable ethtool link speed detection when auto
+      negotiation off"
+    - ice: Fix memory leak
+    - ice: Fix for memory leaks and modify ICE_FREE_CQ_BUFS
+    - mmc: meson-mx-sdio: trigger a soft reset after a timeout or CRC error
+    - Bluetooth: btmtkuart: Improve exception handling in btmtuart_probe()
+    - spi: dw: Fix Rx-only DMA transfers
+    - x86/kvm/hyper-v: Explicitly align hcall param for kvm_hyperv_exit
+    - net: vmxnet3: fix possible buffer overflow caused by bad DMA value in
+      vmxnet3_get_rss()
+    - x86: fix vmap arguments in map_irq_stack
+    - staging: android: ion: use vmap instead of vm_map_ram
+    - ath10k: fix kernel null pointer dereference
+    - media: staging/intel-ipu3: Implement lock for stream on/off operations
+    - spi: Respect DataBitLength field of SpiSerialBusV2() ACPI resource
+    - brcmfmac: fix wrong location to get firmware feature
+    - regulator: qcom-rpmh: Fix typos in pm8150 and pm8150l
+    - tools api fs: Make xxx__mountpoint() more scalable
+    - e1000: Distribute switch variables for initialization
+    - dt-bindings: display: mediatek: control dpi pins mode to avoid leakage
+    - drm/mediatek: set dpi pin mode to gpio low to avoid leakage current
+    - audit: fix a net reference leak in audit_send_reply()
+    - media: dvb: return -EREMOTEIO on i2c transfer failure.
+    - media: platform: fcp: Set appropriate DMA parameters
+    - MIPS: Make sparse_init() using top-down allocation
+    - ath10k: add flush tx packets for SDIO chip
+    - Bluetooth: btbcm: Add 2 missing models to subver tables
+    - audit: fix a net reference leak in audit_list_rules_send()
+    - Drivers: hv: vmbus: Always handle the VMBus messages on CPU0
+    - dpaa2-eth: fix return codes used in ndo_setup_tc
+    - netfilter: nft_nat: return EOPNOTSUPP if type or flags are not supported
+    - selftests/bpf: Fix memory leak in extract_build_id()
+    - net: bcmgenet: set Rx mode before starting netif
+    - net: bcmgenet: Fix WoL with password after deep sleep
+    - lib/mpi: Fix 64-bit MIPS build with Clang
+    - exit: Move preemption fixup up, move blocking operations down
+    - sched/core: Fix illegal RCU from offline CPUs
+    - drivers/perf: hisi: Fix typo in events attribute array
+    - iocost_monitor: drop string wrap around numbers when outputting json
+    - net: lpc-enet: fix error return code in lpc_mii_init()
+    - selinux: fix error return code in policydb_read()
+    - drivers: net: davinci_mdio: fix potential NULL dereference in
+      davinci_mdio_probe()
+    - media: cec: silence shift wrapping warning in __cec_s_log_addrs()
+    - net: allwinner: Fix use correct return type for ndo_start_xmit()
+    - powerpc/spufs: fix copy_to_user while atomic
+    - libertas_tf: avoid a null dereference in pointer priv
+    - xfs: clean up the error handling in xfs_swap_extents
+    - Crypto/chcr: fix for ccm(aes) failed test
+    - MIPS: Truncate link address into 32bit for 32bit kernel
+    - mips: cm: Fix an invalid error code of INTVN_*_ERR
+    - kgdb: Fix spurious true from in_dbg_master()
+    - xfs: reset buffer write failure state on successful completion
+    - xfs: fix duplicate verification from xfs_qm_dqflush()
+    - platform/x86: intel-vbtn: Use acpi_evaluate_integer()
+    - platform/x86: intel-vbtn: Split keymap into buttons and switches parts
+    - platform/x86: intel-vbtn: Do not advertise switches to userspace if they are
+      not there
+    - platform/x86: intel-vbtn: Also handle tablet-mode switch on "Detachable" and
+      "Portable" chassis-types
+    - iwlwifi: avoid debug max amsdu config overwriting itself
+    - nvme: refine the Qemu Identify CNS quirk
+    - nvme-pci: align io queue count with allocted nvme_queue in nvme_probe
+    - nvme-tcp: use bh_lock in data_ready
+    - ath10k: Remove msdu from idr when management pkt send fails
+    - wcn36xx: Fix error handling path in 'wcn36xx_probe()'
+    - net: qed*: Reduce RX and TX default ring count when running inside kdump
+      kernel
+    - drm/mcde: dsi: Fix return value check in mcde_dsi_bind()
+    - mt76: avoid rx reorder buffer overflow
+    - md: don't flush workqueue unconditionally in md_open
+    - raid5: remove gfp flags from scribble_alloc()
+    - iocost: don't let vrate run wild while there's no saturation signal
+    - veth: Adjust hard_start offset on redirect XDP frames
+    - net/mlx5e: IPoIB, Drop multicast packets that this interface sent
+    - rtlwifi: Fix a double free in _rtl_usb_tx_urb_setup()
+    - mwifiex: Fix memory corruption in dump_station
+    - kgdboc: Use a platform device to handle tty drivers showing up late
+    - x86/boot: Correct relocation destination on old linkers
+    - sched: Defend cfs and rt bandwidth quota against overflow
+    - mips: MAAR: Use more precise address mask
+    - mips: Add udelay lpj numbers adjustment
+    - crypto: stm32/crc32 - fix ext4 chksum BUG_ON()
+    - crypto: stm32/crc32 - fix run-time self test issue.
+    - crypto: stm32/crc32 - fix multi-instance
+    - drm/amd/powerpay: Disable gfxoff when setting manual mode on picasso and
+      raven
+    - drm/amdgpu: Sync with VM root BO when switching VM to CPU update mode
+    - selftests/bpf: CONFIG_IPV6_SEG6_BPF required for test_seg6_loop.o
+    - x86/mm: Stop printing BRK addresses
+    - MIPS: tools: Fix resource leak in elf-entry.c
+    - m68k: mac: Don't call via_flush_cache() on Mac IIfx
+    - btrfs: improve global reserve stealing logic
+    - btrfs: qgroup: mark qgroup inconsistent if we're inherting snapshot to a new
+      qgroup
+    - macvlan: Skip loopback packets in RX handler
+    - PCI: Don't disable decoding when mmio_always_on is set
+    - MIPS: Fix IRQ tracing when call handle_fpe() and handle_msa_fpe()
+    - bcache: fix refcount underflow in bcache_device_free()
+    - mmc: sdhci-msm: Set SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12 quirk
+    - staging: greybus: sdio: Respect the cmd->busy_timeout from the mmc core
+    - mmc: via-sdmmc: Respect the cmd->busy_timeout from the mmc core
+    - ice: fix potential double free in probe unrolling
+    - ixgbe: fix signed-integer-overflow warning
+    - iwlwifi: mvm: fix aux station leak
+    - mmc: sdhci-esdhc-imx: fix the mask for tuning start point
+    - spi: dw: Return any value retrieved from the dma_transfer callback
+    - cpuidle: Fix three reference count leaks
+    - platform/x86: hp-wmi: Convert simple_strtoul() to kstrtou32()
+    - platform/x86: intel-hid: Add a quirk to support HP Spectre X2 (2015)
+    - platform/x86: intel-vbtn: Only blacklist SW_TABLET_MODE on the 9 / "Laptop"
+      chasis-type
+    - platform/x86: asus_wmi: Reserve more space for struct bias_args
+    - libbpf: Fix perf_buffer__free() API for sparse allocs
+    - bpf: Fix map permissions check
+    - bpf: Refactor sockmap redirect code so its easy to reuse
+    - bpf: Fix running sk_skb program types with ktls
+    - selftests/bpf, flow_dissector: Close TAP device FD after the test
+    - kasan: stop tests being eliminated as dead code with FORTIFY_SOURCE
+    - string.h: fix incompatibility between FORTIFY_SOURCE and KASAN
+    - btrfs: free alien device after device add
+    - btrfs: include non-missing as a qualifier for the latest_bdev
+    - btrfs: send: emit file capabilities after chown
+    - btrfs: force chunk allocation if our global rsv is larger than metadata
+    - btrfs: fix error handling when submitting direct I/O bio
+    - btrfs: fix wrong file range cleanup after an error filling dealloc range
+    - btrfs: fix space_info bytes_may_use underflow after nocow buffered write
+    - btrfs: fix space_info bytes_may_use underflow during space cache writeout
+    - powerpc/mm: Fix conditions to perform MMU specific management by blocks on
+      PPC32.
+    - mm: thp: make the THP mapcount atomic against __split_huge_pmd_locked()
+    - mm: initialize deferred pages with interrupts enabled
+    - mm/pagealloc.c: call touch_nmi_watchdog() on max order boundaries in
+      deferred init
+    - mm: call cond_resched() from deferred_init_memmap()
+    - ima: Fix ima digest hash table key calculation
+    - ima: Switch to ima_hash_algo for boot aggregate
+    - ima: Evaluate error in init_ima()
+    - ima: Directly assign the ima_default_policy pointer to ima_rules
+    - ima: Call ima_calc_boot_aggregate() in ima_eventdigest_init()
+    - ima: Remove __init annotation from ima_pcrread()
+    - evm: Fix possible memory leak in evm_calc_hmac_or_hash()
+    - ext4: fix EXT_MAX_EXTENT/INDEX to check for zeroed eh_max
+    - ext4: fix error pointer dereference
+    - ext4: fix race between ext4_sync_parent() and rename()
+    - PCI: Add ACS quirk for Intel Root Complex Integrated Endpoints
+    - PCI: Add Loongson vendor ID
+    - x86/amd_nb: Add AMD family 17h model 60h PCI IDs
+    - ima: Remove redundant policy rule set in add_rules()
+    - ima: Set again build_ima_appraise variable
+    - PCI: Program MPS for RCiEP devices
+    - e1000e: Relax condition to trigger reset for ME workaround
+    - carl9170: remove P2P_GO support
+    - media: go7007: fix a miss of snd_card_free
+    - media: cedrus: Program output format during each run
+    - serial: 8250: Avoid error message on reprobe
+    - Bluetooth: hci_bcm: fix freeing not-requested IRQ
+    - b43legacy: Fix case where channel status is corrupted
+    - b43: Fix connection problem with WPA3
+    - b43_legacy: Fix connection problem with WPA3
+    - media: ov5640: fix use of destroyed mutex
+    - clk: mediatek: assign the initial value to clk_init_data of mtk_mux
+    - hwmon: (k10temp) Add AMD family 17h model 60h PCI match
+    - EDAC/amd64: Add AMD family 17h model 60h PCI IDs
+    - power: vexpress: add suppress_bind_attrs to true
+    - power: supply: core: fix HWMON temperature labels
+    - power: supply: core: fix memory leak in HWMON error path
+    - pinctrl: samsung: Correct setting of eint wakeup mask on s5pv210
+    - pinctrl: samsung: Save/restore eint_mask over suspend for EINT_TYPE GPIOs
+    - gnss: sirf: fix error return code in sirf_probe()
+    - sparc32: fix register window handling in genregs32_[gs]et()
+    - sparc64: fix misuses of access_process_vm() in genregs32_[sg]et()
+    - dm crypt: avoid truncating the logical block size
+    - alpha: fix memory barriers so that they conform to the specification
+    - powerpc/fadump: use static allocation for reserved memory ranges
+    - powerpc/fadump: consider reserved ranges while reserving memory
+    - powerpc/fadump: Account for memory_limit while reserving memory
+    - kernel/cpu_pm: Fix uninitted local in cpu_pm
+    - ARM: tegra: Correct PL310 Auxiliary Control Register initialization
+    - soc/tegra: pmc: Select GENERIC_PINCONF
+    - ARM: dts: exynos: Fix GPIO polarity for thr GalaxyS3 CM36651 sensor's bus
+    - ARM: dts: at91: sama5d2_ptc_ek: fix vbus pin
+    - ARM: dts: s5pv210: Set keep-power-in-suspend for SDHCI1 on Aries
+    - drivers/macintosh: Fix memleak in windfarm_pm112 driver
+    - powerpc/32s: Fix another build failure with CONFIG_PPC_KUAP_DEBUG
+    - powerpc/kasan: Fix issues by lowering KASAN_SHADOW_END
+    - powerpc/kasan: Fix shadow pages allocation failure
+    - powerpc/32: Disable KASAN with pages bigger than 16k
+    - powerpc/64s: Don't let DT CPU features set FSCR_DSCR
+    - powerpc/64s: Save FSCR to init_task.thread.fscr after feature init
+    - kbuild: force to build vmlinux if CONFIG_MODVERSION=y
+    - sunrpc: svcauth_gss_register_pseudoflavor must reject duplicate
+      registrations.
+    - sunrpc: clean up properly in gss_mech_unregister()
+    - mtd: rawnand: Fix nand_gpio_waitrdy()
+    - mtd: rawnand: onfi: Fix redundancy detection check
+    - mtd: rawnand: brcmnand: fix hamming oob layout
+    - mtd: rawnand: diskonchip: Fix the probe error path
+    - mtd: rawnand: sharpsl: Fix the probe error path
+    - mtd: rawnand: ingenic: Fix the probe error path
+    - mtd: rawnand: xway: Fix the probe error path
+    - mtd: rawnand: orion: Fix the probe error path
+    - mtd: rawnand: socrates: Fix the probe error path
+    - mtd: rawnand: oxnas: Fix the probe error path
+    - mtd: rawnand: sunxi: Fix the probe error path
+    - mtd: rawnand: plat_nand: Fix the probe error path
+    - mtd: rawnand: pasemi: Fix the probe error path
+    - mtd: rawnand: mtk: Fix the probe error path
+    - mtd: rawnand: tmio: Fix the probe error path
+    - w1: omap-hdq: cleanup to add missing newline for some dev_dbg
+    - f2fs: fix checkpoint=disable:%u%%
+    - perf probe: Do not show the skipped events
+    - perf probe: Fix to check blacklist address correctly
+    - perf probe: Check address correctness by map instead of _etext
+    - perf symbols: Fix debuginfo search for Ubuntu
+    - perf symbols: Fix kernel maps for kcore and eBPF
+    - Linux 5.4.48
+
+  * The thread level parallelism would be a bottleneck when searching for the
+    shared pmd by using hugetlbfs (LP: #1882039)
+    - hugetlbfs: take read_lock on i_mmap for PMD sharing
+
+  * Support Audio Mute LED for two new HP laptops (LP: #1884251)
+    - ALSA: hda/realtek: Add mute LED and micmute LED support for HP systems
+
+  * Focal update: v5.4.47 upstream stable release (LP: #1884089)
+    - ipv6: fix IPV6_ADDRFORM operation logic
+    - mlxsw: core: Use different get_trend() callbacks for different thermal zones
+    - net_failover: fixed rollback in net_failover_open()
+    - tun: correct header offsets in napi frags mode
+    - bridge: Avoid infinite loop when suppressing NS messages with invalid
+      options
+    - vxlan: Avoid infinite loop when suppressing NS messages with invalid options
+    - bpf: Support llvm-objcopy for vmlinux BTF
+    - elfnote: mark all .note sections SHF_ALLOC
+    - Input: mms114 - fix handling of mms345l
+    - ARM: 8977/1: ptrace: Fix mask for thumb breakpoint hook
+    - sched/fair: Don't NUMA balance for kthreads
+    - Input: synaptics - add a second working PNP_ID for Lenovo T470s
+    - csky: Fixup abiv2 syscall_trace break a4 & a5
+    - gfs2: Even more gfs2_find_jhead fixes
+    - drivers/net/ibmvnic: Update VNIC protocol version reporting
+    - powerpc/xive: Clear the page tables for the ESB IO mapping
+    - spi: dw: Fix native CS being unset
+    - ath9k_htc: Silence undersized packet warnings
+    - smack: avoid unused 'sip' variable warning
+    - RDMA/uverbs: Make the event_queue fds return POLLERR when disassociated
+    - padata: add separate cpuhp node for CPUHP_PADATA_DEAD
+    - s390/pci: Log new handle in clp_disable_fh()
+    - x86/cpu/amd: Make erratum #1054 a legacy erratum
+    - KVM: x86: only do L1TF workaround on affected processors
+    - PCI/PM: Adjust pcie_wait_for_link_delay() for caller delay
+    - perf probe: Accept the instance number of kretprobe event
+    - mm: add kvfree_sensitive() for freeing sensitive data objects
+    - selftests: fix flower parent qdisc
+    - fanotify: fix ignore mask logic for events on child and on dir
+    - aio: fix async fsync creds
+    - ipv4: fix a RCU-list lock in fib_triestat_seq_show
+    - iwlwifi: mvm: fix NVM check for 3168 devices
+    - sctp: fix possibly using a bad saddr with a given dst
+    - sctp: fix refcount bug in sctp_wfree
+    - x86_64: Fix jiffies ODR violation
+    - x86/PCI: Mark Intel C620 MROMs as having non-compliant BARs
+    - x86/speculation: Prevent rogue cross-process SSBD shutdown
+    - x86/speculation: Avoid force-disabling IBPB based on STIBP and enhanced
+      IBRS.
+    - x86/speculation: PR_SPEC_FORCE_DISABLE enforcement for indirect branches.
+    - x86/reboot/quirks: Add MacBook6,1 reboot quirk
+    - perf/x86/intel: Add more available bits for OFFCORE_RESPONSE of Intel
+      Tremont
+    - KVM: x86/mmu: Set mmio_value to '0' if reserved #PF can't be generated
+    - KVM: x86: respect singlestep when emulating instruction
+    - KVM: x86: Fix APIC page invalidation race
+    - powerpc/ptdump: Properly handle non standard page size
+    - ASoC: max9867: fix volume controls
+    - io_uring: use kvfree() in io_sqe_buffer_register()
+    - efi/efivars: Add missing kobject_put() in sysfs entry creation error path
+    - smb3: fix incorrect number of credits when ioctl MaxOutputResponse > 64K
+    - smb3: add indatalen that can be a non-zero value to calculation of credit
+      charge in smb2 ioctl
+    - watchdog: imx_sc_wdt: Fix reboot on crash
+    - ALSA: es1688: Add the missed snd_card_free()
+    - ALSA: fireface: fix configuration error for nominal sampling transfer
+      frequency
+    - ALSA: hda/realtek - add a pintbl quirk for several Lenovo machines
+    - ALSA: pcm: disallow linking stream to itself
+    - ALSA: pcm: fix snd_pcm_link() lockdep splat
+    - ALSA: usb-audio: Fix inconsistent card PM state after resume
+    - ALSA: usb-audio: Add vendor, product and profile name for HP Thunderbolt
+      Dock
+    - ACPI: sysfs: Fix reference count leak in acpi_sysfs_add_hotplug_profile()
+    - ACPI: CPPC: Fix reference count leak in acpi_cppc_processor_probe()
+    - ACPI: GED: add support for _Exx / _Lxx handler methods
+    - ACPI: PM: Avoid using power resources if there are none for D0
+    - arm64: acpi: fix UBSAN warning
+    - lib/lzo: fix ambiguous encoding bug in lzo-rle
+    - nilfs2: fix null pointer dereference at nilfs_segctor_do_construct()
+    - spi: dw: Fix controller unregister order
+    - spi: Fix controller unregister order
+    - spi: pxa2xx: Fix controller unregister order
+    - spi: pxa2xx: Fix runtime PM ref imbalance on probe error
+    - spi: bcm2835: Fix controller unregister order
+    - spi: bcm2835aux: Fix controller unregister order
+    - spi: bcm-qspi: Handle clock probe deferral
+    - spi: bcm-qspi: when tx/rx buffer is NULL set to 0
+    - PM: runtime: clk: Fix clk_pm_runtime_get() error path
+    - gup: document and work around "COW can break either way" issue
+    - crypto: cavium/nitrox - Fix 'nitrox_get_first_device()' when ndevlist is
+      fully iterated
+    - crypto: algapi - Avoid spurious modprobe on LOADED
+    - crypto: drbg - fix error return code in drbg_alloc_state()
+    - x86/{mce,mm}: Unmap the entire page if the whole page is affected and
+      poisoned
+    - firmware: imx: warn on unexpected RX
+    - firmware: imx-scu: Support one TX and one RX
+    - firmware: imx: scu: Fix corruption of header
+    - crypto: virtio: Fix use-after-free in virtio_crypto_skcipher_finalize_req()
+    - crypto: virtio: Fix src/dst scatterlist calculation in
+      __virtio_crypto_skcipher_do_req()
+    - crypto: virtio: Fix dest length calculation in
+      __virtio_crypto_skcipher_do_req()
+    - dccp: Fix possible memleak in dccp_init and dccp_fini
+    - selftests/net: in rxtimestamp getopt_long needs terminating null entry
+    - net/mlx5: drain health workqueue in case of driver load error
+    - net/mlx5: Fix fatal error handling during device load
+    - net/mlx5e: Fix repeated XSK usage on one channel
+    - ovl: initialize error in ovl_copy_xattr
+    - proc: Use new_inode not new_inode_pseudo
+    - remoteproc: Fall back to using parent memory pool if no dedicated available
+    - remoteproc: Fix and restore the parenting hierarchy for vdev
+    - cpufreq: Fix up cpufreq_boost_set_sw()
+    - EDAC/skx: Use the mcmtr register to retrieve close_pg/bank_xor_enable
+    - video: vt8500lcdfb: fix fallthrough warning
+    - video: fbdev: w100fb: Fix a potential double free.
+    - KVM: nVMX: Skip IBPB when switching between vmcs01 and vmcs02
+    - KVM: nSVM: fix condition for filtering async PF
+    - KVM: nSVM: leave ASID aside in copy_vmcb_control_area
+    - KVM: nVMX: Consult only the "basic" exit reason when routing nested exit
+    - KVM: MIPS: Define KVM_ENTRYHI_ASID to cpu_asid_mask(&boot_cpu_data)
+    - KVM: MIPS: Fix VPN2_MASK definition for variable cpu_vmbits
+    - KVM: arm64: Stop writing aarch32's CSSELR into ACTLR
+    - KVM: arm64: Make vcpu_cp1x() work on Big Endian hosts
+    - scsi: megaraid_sas: TM command refire leads to controller firmware crash
+    - scsi: lpfc: Fix negation of else clause in lpfc_prep_node_fc4type
+    - selftests/ftrace: Return unsupported if no error_log file
+    - ath9k: Fix use-after-free Read in htc_connect_service
+    - ath9k: Fix use-after-free Read in ath9k_wmi_ctrl_rx
+    - ath9k: Fix use-after-free Write in ath9k_htc_rx_msg
+    - ath9x: Fix stack-out-of-bounds Write in ath9k_hif_usb_rx_cb
+    - ath9k: Fix general protection fault in ath9k_hif_usb_rx_cb
+    - Smack: slab-out-of-bounds in vsscanf
+    - drm/vkms: Hold gem object while still in-use
+    - mm/slub: fix a memory leak in sysfs_slab_add()
+    - fat: don't allow to mount if the FAT length == 0
+    - perf: Add cond_resched() to task_function_call()
+    - agp/intel: Reinforce the barrier after GTT updates
+    - mmc: sdhci-msm: Clear tuning done flag while hs400 tuning
+    - mmc: mmci_sdmmc: fix DMA API warning overlapping mappings
+    - mmc: tmio: Further fixup runtime PM management at remove
+    - mmc: uniphier-sd: call devm_request_irq() after tmio_mmc_host_probe()
+    - ARM: dts: at91: sama5d2_ptc_ek: fix sdmmc0 node description
+    - mmc: sdio: Fix potential NULL pointer error in mmc_sdio_init_card()
+    - mmc: sdio: Fix several potential memory leaks in mmc_sdio_init_card()
+    - block/floppy: fix contended case in floppy_queue_rq()
+    - xen/pvcalls-back: test for errors when calling backend_connect()
+    - KVM: arm64: Synchronize sysreg state on injecting an AArch32 exception
+    - KVM: arm64: Save the host's PtrAuth keys in non-preemptible context
+    - Linux 5.4.47
+
+  * apparmor reference leak causes refcount_t overflow with af_alg_accept()
+    (LP: #1883962)
+    - apparmor: check/put label on apparmor_sk_clone_security()
+
+  * Focal update: v5.4.46 upstream stable release (LP: #1883184)
+    - devinet: fix memleak in inetdev_init()
+    - l2tp: add sk_family checks to l2tp_validate_socket
+    - l2tp: do not use inet_hash()/inet_unhash()
+    - net/mlx5: Fix crash upon suspend/resume
+    - net: stmmac: enable timestamp snapshot for required PTP packets in dwmac
+      v5.10a
+    - net: usb: qmi_wwan: add Telit LE910C1-EUX composition
+    - NFC: st21nfca: add missed kfree_skb() in an error path
+    - nfp: flower: fix used time of merge flow statistics
+    - vsock: fix timeout in vsock_accept()
+    - net: check untrusted gso_size at kernel entry
+    - net: be more gentle about silly gso requests coming from user
+    - USB: serial: qcserial: add DW5816e QDL support
+    - USB: serial: usb_wwan: do not resubmit rx urb on fatal errors
+    - USB: serial: option: add Telit LE910C1-EUX compositions
+    - USB: serial: ch341: add basis for quirk detection
+    - iio:chemical:sps30: Fix timestamp alignment
+    - iio: vcnl4000: Fix i2c swapped word reading.
+    - iio:chemical:pms7003: Fix timestamp alignment and prevent data leak.
+    - iio: adc: stm32-adc: fix a wrong error message when probing interrupts
+    - usb: musb: start session in resume for host port
+    - usb: musb: Fix runtime PM imbalance on error
+    - vt: keyboard: avoid signed integer overflow in k_ascii
+    - tty: hvc_console, fix crashes on parallel open/close
+    - staging: rtl8712: Fix IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK
+    - CDC-ACM: heed quirk also in error handling
+    - nvmem: qfprom: remove incorrect write support
+    - uprobes: ensure that uprobe->offset and ->ref_ctr_offset are properly
+      aligned
+    - Revert "net/mlx5: Annotate mutex destroy for root ns"
+    - Linux 5.4.46
+
+  * Focal update: v5.4.45 upstream stable release (LP: #1882802)
+    - mm: Fix mremap not considering huge pmd devmap
+    - HID: sony: Fix for broken buttons on DS3 USB dongles
+    - HID: multitouch: enable multi-input as a quirk for some devices
+    - HID: i2c-hid: add Schneider SCL142ALM to descriptor override
+    - p54usb: add AirVasT USB stick device-id
+    - mt76: mt76x02u: Add support for newer versions of the XBox One wifi adapter
+    - mmc: fix compilation of user API
+    - media: Revert "staging: imgu: Address a compiler warning on alignment"
+    - media: staging: ipu3-imgu: Move alignment attribute to field
+    - scsi: ufs: Release clock if DMA map fails
+    - net: dsa: mt7530: set CPU port to fallback mode
+    - airo: Fix read overflows sending packets
+    - RDMA/qedr: Fix qpids xarray api used
+    - RDMA/qedr: Fix synchronization methods and memory leaks in qedr
+    - ARC: Fix ICCM & DCCM runtime size checks
+    - ARC: [plat-eznps]: Restrict to CONFIG_ISA_ARCOMPACT
+    - evm: Fix RCU list related warnings
+    - scsi: pm: Balance pm_only counter of request queue during system resume
+    - i2c: altera: Fix race between xfer_msg and isr thread
+    - io_uring: initialize ctx->sqo_wait earlier
+    - x86/mmiotrace: Use cpumask_available() for cpumask_var_t variables
+    - net: bmac: Fix read of MAC address from ROM
+    - drm/edid: Add Oculus Rift S to non-desktop list
+    - s390/mm: fix set_huge_pte_at() for empty ptes
+    - null_blk: return error for invalid zone size
+    - net/ethernet/freescale: rework quiesce/activate for ucc_geth
+    - net: ethernet: stmmac: Enable interface clocks on probe for IPQ806x
+    - selftests: mlxsw: qos_mc_aware: Specify arping timeout as an integer
+    - net: smsc911x: Fix runtime PM imbalance on error
+    - Linux 5.4.45
+
+ -- Khalid Elmously <khalid.elmously@canonical.com>  Sat, 08 Aug 2020 02:05:56 -0400
+
+linux (5.4.0-42.46) focal; urgency=medium
+
+  * focal/linux: 5.4.0-42.46 -proposed tracker (LP: #1887069)
+
+  * linux 4.15.0-109-generic network DoS regression vs -108 (LP: #1886668)
+    - SAUCE: Revert "netprio_cgroup: Fix unlimited memory leak of v2 cgroups"
+
+ -- Khalid Elmously <khalid.elmously@canonical.com>  Thu, 09 Jul 2020 19:50:26 -0400
+
+linux (5.4.0-41.45) focal; urgency=medium
+
+  * focal/linux: 5.4.0-41.45 -proposed tracker (LP: #1885855)
+
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+
+  * CVE-2019-19642
+    - kernel/relay.c: handle alloc_percpu returning NULL in relay_open
+
+  * CVE-2019-16089
+    - SAUCE: nbd_genl_status: null check for nla_nest_start
+
+  * CVE-2020-11935
+    - aufs: do not call i_readcount_inc()
+
+  * ip_defrag.sh in net from ubuntu_kernel_selftests failed with 5.0 / 5.3 / 5.4
+    kernel (LP: #1826848)
+    - selftests: net: ip_defrag: ignore EPERM
+
+  * Update lockdown patches (LP: #1884159)
+    - SAUCE: acpi: disallow loading configfs acpi tables when locked down
+
+  * seccomp_bpf fails on powerpc (LP: #1885757)
+    - SAUCE: selftests/seccomp: fix ptrace tests on powerpc
+
+  * Introduce the new NVIDIA 418-server and 440-server series, and update the
+    current NVIDIA drivers (LP: #1881137)
+    - [packaging] add signed modules for the 418-server and the 440-server
+      flavours
+
+ -- Kleber Sacilotto de Souza <kleber.souza@canonical.com>  Fri, 03 Jul 2020 10:32:54 +0200
+
+linux (5.4.0-40.44) focal; urgency=medium
+
+  * linux-oem-5.6-tools-common and -tools-host should be dropped (LP: #1881120)
+    - [Packaging] Add Conflicts/Replaces to remove linux-oem-5.6-tools-common and
+      -tools-host
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update helper scripts
+
+  * Slow send speed with Intel I219-V on Ubuntu 18.04.1 (LP: #1802691)
+    - e1000e: Disable TSO for buffer overrun workaround
+
+  * CVE-2020-0543
+    - UBUNTU/SAUCE: x86/speculation/srbds: do not try to turn mitigation off when
+      not supported
+
+  * Realtek 8723DE [10ec:d723] subsystem [10ec:d738]  disconnects unsolicitedly
+    when Bluetooth is paired: Reason: 23=IEEE8021X_FAILED (LP: #1878147)
+    - SAUCE: Revert "UBUNTU: SAUCE: rtw88: Move driver IQK to set channel before
+      association for 11N chip"
+    - SAUCE: Revert "UBUNTU: SAUCE: rtw88: fix rate for a while after being
+      connected"
+    - SAUCE: Revert "UBUNTU: SAUCE: rtw88: No retry and report for auth and assoc"
+    - SAUCE: Revert "UBUNTU: SAUCE: rtw88: 8723d: Add coex support"
+    - rtw88: add a debugfs entry to dump coex's info
+    - rtw88: add a debugfs entry to enable/disable coex mechanism
+    - rtw88: 8723d: Add coex support
+    - SAUCE: rtw88: coex: 8723d: set antanna control owner
+    - SAUCE: rtw88: coex: 8723d: handle BT inquiry cases
+    - SAUCE: rtw88: fix EAPOL 4-way failure by finish IQK earlier
+
+  * CPU stress test fails with focal kernel (LP: #1867900)
+    - [Config] Disable hisi_sec2 temporarily
+
+  * Enforce all config annotations (LP: #1879327)
+    - [Config]: do not enforce CONFIG_VERSION_SIGNATURE
+    - [Config]: prepare to enforce all
+    - [Config]: enforce all config options
+
+  * Focal update: v5.4.44 upstream stable release (LP: #1881927)
+    - ax25: fix setsockopt(SO_BINDTODEVICE)
+    - dpaa_eth: fix usage as DSA master, try 3
+    - net: don't return invalid table id error when we fall back to PF_UNSPEC
+    - net: dsa: mt7530: fix roaming from DSA user ports
+    - net: ethernet: ti: cpsw: fix ASSERT_RTNL() warning during suspend
+    - __netif_receive_skb_core: pass skb by reference
+    - net: inet_csk: Fix so_reuseport bind-address cache in tb->fast*
+    - net: ipip: fix wrong address family in init error path
+    - net/mlx5: Add command entry handling completion
+    - net: mvpp2: fix RX hashing for non-10G ports
+    - net: nlmsg_cancel() if put fails for nhmsg
+    - net: qrtr: Fix passing invalid reference to qrtr_local_enqueue()
+    - net: revert "net: get rid of an signed integer overflow in
+      ip_idents_reserve()"
+    - net sched: fix reporting the first-time use timestamp
+    - net/tls: fix race condition causing kernel panic
+    - nexthop: Fix attribute checking for groups
+    - r8152: support additional Microsoft Surface Ethernet Adapter variant
+    - sctp: Don't add the shutdown timer if its already been added
+    - sctp: Start shutdown on association restart if in SHUTDOWN-SENT state and
+      socket is closed
+    - tipc: block BH before using dst_cache
+    - net/mlx5e: kTLS, Destroy key object after destroying the TIS
+    - net/mlx5e: Fix inner tirs handling
+    - net/mlx5: Fix memory leak in mlx5_events_init
+    - net/mlx5e: Update netdev txq on completions during closure
+    - net/mlx5: Fix error flow in case of function_setup failure
+    - net/mlx5: Annotate mutex destroy for root ns
+    - net/tls: fix encryption error checking
+    - net/tls: free record only on encryption error
+    - net: sun: fix missing release regions in cas_init_one().
+    - net/mlx4_core: fix a memory leak bug.
+    - mlxsw: spectrum: Fix use-after-free of split/unsplit/type_set in case reload
+      fails
+    - ARM: dts: rockchip: fix phy nodename for rk3228-evb
+    - ARM: dts: rockchip: fix phy nodename for rk3229-xms6
+    - arm64: dts: rockchip: fix status for &gmac2phy in rk3328-evb.dts
+    - arm64: dts: rockchip: swap interrupts interrupt-names rk3399 gpu node
+    - ARM: dts: rockchip: swap clock-names of gpu nodes
+    - ARM: dts: rockchip: fix pinctrl sub nodename for spi in rk322x.dtsi
+    - gpio: tegra: mask GPIO IRQs during IRQ shutdown
+    - ALSA: usb-audio: add mapping for ASRock TRX40 Creator
+    - net: microchip: encx24j600: add missed kthread_stop
+    - gfs2: move privileged user check to gfs2_quota_lock_check
+    - gfs2: Grab glock reference sooner in gfs2_add_revoke
+    - drm/amdgpu: drop unnecessary cancel_delayed_work_sync on PG ungate
+    - drm/amd/powerplay: perform PG ungate prior to CG ungate
+    - drm/amdgpu: Use GEM obj reference for KFD BOs
+    - cachefiles: Fix race between read_waiter and read_copier involving op->to_do
+    - usb: dwc3: pci: Enable extcon driver for Intel Merrifield
+    - usb: phy: twl6030-usb: Fix a resource leak in an error handling path in
+      'twl6030_usb_probe()'
+    - usb: gadget: legacy: fix redundant initialization warnings
+    - net: freescale: select CONFIG_FIXED_PHY where needed
+    - IB/i40iw: Remove bogus call to netdev_master_upper_dev_get()
+    - riscv: stacktrace: Fix undefined reference to `walk_stackframe'
+    - clk: ti: am33xx: fix RTC clock parent
+    - csky: Fixup msa highest 3 bits mask
+    - csky: Fixup perf callchain unwind
+    - csky: Fixup remove duplicate irq_disable
+    - hwmon: (nct7904) Fix incorrect range of temperature limit registers
+    - cifs: Fix null pointer check in cifs_read
+    - csky: Fixup raw_copy_from_user()
+    - samples: bpf: Fix build error
+    - drivers: net: hamradio: Fix suspicious RCU usage warning in bpqether.c
+    - Input: usbtouchscreen - add support for BonXeon TP
+    - Input: evdev - call input_flush_device() on release(), not flush()
+    - Input: xpad - add custom init packet for Xbox One S controllers
+    - Input: dlink-dir685-touchkeys - fix a typo in driver name
+    - Input: i8042 - add ThinkPad S230u to i8042 reset list
+    - Input: synaptics-rmi4 - really fix attn_data use-after-free
+    - Input: synaptics-rmi4 - fix error return code in rmi_driver_probe()
+    - ARM: 8970/1: decompressor: increase tag size
+    - ARM: uaccess: consolidate uaccess asm to asm/uaccess-asm.h
+    - ARM: uaccess: integrate uaccess_save and uaccess_restore
+    - ARM: uaccess: fix DACR mismatch with nested exceptions
+    - gpio: exar: Fix bad handling for ida_simple_get error path
+    - arm64: dts: mt8173: fix vcodec-enc clock
+    - soc: mediatek: cmdq: return send msg error code
+    - gpu/drm: Ingenic: Fix opaque pointer casted to wrong type
+    - IB/qib: Call kobject_put() when kobject_init_and_add() fails
+    - ARM: dts/imx6q-bx50v3: Set display interface clock parents
+    - ARM: dts: bcm2835-rpi-zero-w: Fix led polarity
+    - ARM: dts: bcm: HR2: Fix PPI interrupt types
+    - mmc: block: Fix use-after-free issue for rpmb
+    - gpio: pxa: Fix return value of pxa_gpio_probe()
+    - gpio: bcm-kona: Fix return value of bcm_kona_gpio_probe()
+    - RDMA/pvrdma: Fix missing pci disable in pvrdma_pci_probe()
+    - ALSA: hwdep: fix a left shifting 1 by 31 UB bug
+    - ALSA: hda/realtek - Add a model for Thinkpad T570 without DAC workaround
+    - ALSA: usb-audio: mixer: volume quirk for ESS Technology Asus USB DAC
+    - exec: Always set cap_ambient in cap_bprm_set_creds
+    - clk: qcom: gcc: Fix parent for gpll0_out_even
+    - ALSA: usb-audio: Quirks for Gigabyte TRX40 Aorus Master onboard audio
+    - ALSA: hda/realtek - Add new codec supported for ALC287
+    - libceph: ignore pool overlay and cache logic on redirects
+    - ceph: flush release queue when handling caps for unknown inode
+    - RDMA/core: Fix double destruction of uobject
+    - drm/amd/display: drop cursor position check in atomic test
+    - IB/ipoib: Fix double free of skb in case of multicast traffic in CM mode
+    - mm,thp: stop leaking unreleased file pages
+    - mm: remove VM_BUG_ON(PageSlab()) from page_mapcount()
+    - fs/binfmt_elf.c: allocate initialized memory in fill_thread_core_info()
+    - include/asm-generic/topology.h: guard cpumask_of_node() macro argument
+    - Revert "block: end bio with BLK_STS_AGAIN in case of non-mq devs and
+      REQ_NOWAIT"
+    - gpio: fix locking open drain IRQ lines
+    - iommu: Fix reference count leak in iommu_group_alloc.
+    - parisc: Fix kernel panic in mem_init()
+    - cfg80211: fix debugfs rename crash
+    - x86/syscalls: Revert "x86/syscalls: Make __X32_SYSCALL_BIT be unsigned long"
+    - mac80211: mesh: fix discovery timer re-arming issue / crash
+    - x86/dma: Fix max PFN arithmetic overflow on 32 bit systems
+    - copy_xstate_to_kernel(): don't leave parts of destination uninitialized
+    - xfrm: allow to accept packets with ipv6 NEXTHDR_HOP in xfrm_input
+    - xfrm: do pskb_pull properly in __xfrm_transport_prep
+    - xfrm: remove the xfrm_state_put call becofe going to out_reset
+    - xfrm: call xfrm_output_gso when inner_protocol is set in xfrm_output
+    - xfrm interface: fix oops when deleting a x-netns interface
+    - xfrm: fix a warning in xfrm_policy_insert_list
+    - xfrm: fix a NULL-ptr deref in xfrm_local_error
+    - xfrm: fix error in comment
+    - ip_vti: receive ipip packet by calling ip_tunnel_rcv
+    - netfilter: nft_reject_bridge: enable reject with bridge vlan
+    - netfilter: ipset: Fix subcounter update skip
+    - netfilter: conntrack: make conntrack userspace helpers work again
+    - netfilter: nfnetlink_cthelper: unbreak userspace helper support
+    - netfilter: nf_conntrack_pptp: prevent buffer overflows in debug code
+    - esp6: get the right proto for transport mode in esp6_gso_encap
+    - bnxt_en: Fix accumulation of bp->net_stats_prev.
+    - ieee80211: Fix incorrect mask for default PE duration
+    - xsk: Add overflow check for u64 division, stored into u32
+    - qlcnic: fix missing release in qlcnic_83xx_interrupt_test.
+    - crypto: chelsio/chtls: properly set tp->lsndtime
+    - nexthops: Move code from remove_nexthop_from_groups to remove_nh_grp_entry
+    - nexthops: don't modify published nexthop groups
+    - nexthop: Expand nexthop_is_multipath in a few places
+    - ipv4: nexthop version of fib_info_nh_uses_dev
+    - net: dsa: declare lockless TX feature for slave ports
+    - bonding: Fix reference count leak in bond_sysfs_slave_add.
+    - netfilter: conntrack: comparison of unsigned in cthelper confirmation
+    - netfilter: conntrack: Pass value of ctinfo to __nf_conntrack_update
+    - netfilter: nf_conntrack_pptp: fix compilation warning with W=1 build
+    - perf: Make perf able to build with latest libbfd
+    - Linux 5.4.44
+
+  * Focal update: v5.4.43 upstream stable release (LP: #1881178)
+    - i2c: dev: Fix the race between the release of i2c_dev and cdev
+    - KVM: SVM: Fix potential memory leak in svm_cpu_init()
+    - ima: Set file->f_mode instead of file->f_flags in ima_calc_file_hash()
+    - evm: Check also if *tfm is an error pointer in init_desc()
+    - ima: Fix return value of ima_write_policy()
+    - ubifs: fix wrong use of crypto_shash_descsize()
+    - ACPI: EC: PM: Avoid flushing EC work when EC GPE is inactive
+    - mtd: spinand: Propagate ECC information to the MTD structure
+    - fix multiplication overflow in copy_fdtable()
+    - ubifs: remove broken lazytime support
+    - i2c: fix missing pm_runtime_put_sync in i2c_device_probe
+    - iommu/amd: Fix over-read of ACPI UID from IVRS table
+    - evm: Fix a small race in init_desc()
+    - i2c: mux: demux-pinctrl: Fix an error handling path in
+      'i2c_demux_pinctrl_probe()'
+    - ubi: Fix seq_file usage in detailed_erase_block_info debugfs file
+    - afs: Don't unlock fetched data pages until the op completes successfully
+    - mtd: Fix mtd not registered due to nvmem name collision
+    - kbuild: avoid concurrency issue in parallel building dtbs and dtbs_check
+    - net: drop_monitor: use IS_REACHABLE() to guard net_dm_hw_report()
+    - gcc-common.h: Update for GCC 10
+    - HID: multitouch: add eGalaxTouch P80H84 support
+    - HID: alps: Add AUI1657 device ID
+    - HID: alps: ALPS_1657 is too specific; use U1_UNICORN_LEGACY instead
+    - scsi: qla2xxx: Fix hang when issuing nvme disconnect-all in NPIV
+    - scsi: qla2xxx: Delete all sessions before unregister local nvme port
+    - configfs: fix config_item refcnt leak in configfs_rmdir()
+    - vhost/vsock: fix packet delivery order to monitoring devices
+    - aquantia: Fix the media type of AQC100 ethernet controller in the driver
+    - component: Silence bind error on -EPROBE_DEFER
+    - net/ena: Fix build warning in ena_xdp_set()
+    - scsi: ibmvscsi: Fix WARN_ON during event pool release
+    - HID: i2c-hid: reset Synaptics SYNA2393 on resume
+    - x86/mm/cpa: Flush direct map alias during cpa
+    - ibmvnic: Skip fatal error reset after passive init
+    - x86/apic: Move TSC deadline timer debug printk
+    - gtp: set NLM_F_MULTI flag in gtp_genl_dump_pdp()
+    - HID: quirks: Add HID_QUIRK_NO_INIT_REPORTS quirk for Dell K12A keyboard-dock
+    - ceph: fix double unlock in handle_cap_export()
+    - stmmac: fix pointer check after utilization in stmmac_interrupt
+    - USB: core: Fix misleading driver bug report
+    - platform/x86: asus-nb-wmi: Do not load on Asus T100TA and T200TA
+    - iommu/amd: Call domain_flush_complete() in update_domain()
+    - drm/amd/display: Prevent dpcd reads with passive dongles
+    - KVM: selftests: Fix build for evmcs.h
+    - ARM: futex: Address build warning
+    - scripts/gdb: repair rb_first() and rb_last()
+    - ALSA: hda - constify and cleanup static NodeID tables
+    - ALSA: hda: patch_realtek: fix empty macro usage in if block
+    - ALSA: hda: Manage concurrent reg access more properly
+    - ALSA: hda/realtek - Add supported new mute Led for HP
+    - ALSA: hda/realtek - Add HP new mute led supported for ALC236
+    - ALSA: hda/realtek: Add quirk for Samsung Notebook
+    - ALSA: hda/realtek - Enable headset mic of ASUS GL503VM with ALC295
+    - ALSA: hda/realtek - Enable headset mic of ASUS UX550GE with ALC295
+    - ALSA: hda/realtek: Enable headset mic of ASUS UX581LV with ALC295
+    - KVM: x86: Fix pkru save/restore when guest CR4.PKE=0, move it to x86.c
+    - ALSA: iec1712: Initialize STDSP24 properly when using the model=staudio
+      option
+    - ALSA: pcm: fix incorrect hw_base increase
+    - ALSA: hda/realtek - Fix silent output on Gigabyte X570 Aorus Xtreme
+    - ALSA: hda/realtek - Add more fixup entries for Clevo machines
+    - scsi: qla2xxx: Do not log message when reading port speed via sysfs
+    - scsi: target: Put lun_ref at end of tmr processing
+    - arm64: Fix PTRACE_SYSEMU semantics
+    - drm/etnaviv: fix perfmon domain interation
+    - apparmor: Fix aa_label refcnt leak in policy_update
+    - dmaengine: tegra210-adma: Fix an error handling path in 'tegra_adma_probe()'
+    - drm/etnaviv: Fix a leak in submit_pin_objects()
+    - dmaengine: dmatest: Restore default for channel
+    - dmaengine: owl: Use correct lock in owl_dma_get_pchan()
+    - vsprintf: don't obfuscate NULL and error pointers
+    - drm/i915/gvt: Init DPLL/DDI vreg for virtual display instead of inheritance.
+    - drm/i915: Propagate error from completed fences
+    - powerpc: Remove STRICT_KERNEL_RWX incompatibility with RELOCATABLE
+    - powerpc/64s: Disable STRICT_KERNEL_RWX
+    - bpf: Avoid setting bpf insns pages read-only when prog is jited
+    - kbuild: Remove debug info from kallsyms linking
+    - Revert "gfs2: Don't demote a glock until its revokes are written"
+    - media: fdp1: Fix R-Car M3-N naming in debug message
+    - staging: iio: ad2s1210: Fix SPI reading
+    - staging: kpc2000: fix error return code in kp2000_pcie_probe()
+    - staging: greybus: Fix uninitialized scalar variable
+    - iio: sca3000: Remove an erroneous 'get_device()'
+    - iio: dac: vf610: Fix an error handling path in 'vf610_dac_probe()'
+    - iio: adc: ti-ads8344: Fix channel selection
+    - misc: rtsx: Add short delay after exit from ASPM
+    - tty: serial: add missing spin_lock_init for SiFive serial console
+    - mei: release me_cl object reference
+    - ipack: tpci200: fix error return code in tpci200_register()
+    - s390/kaslr: add support for R_390_JMP_SLOT relocation type
+    - device-dax: don't leak kernel memory to user space after unloading kmem
+    - rapidio: fix an error in get_user_pages_fast() error handling
+    - kasan: disable branch tracing for core runtime
+    - rxrpc: Fix the excessive initial retransmission timeout
+    - rxrpc: Fix a memory leak in rxkad_verify_response()
+    - s390/kexec_file: fix initrd location for kdump kernel
+    - flow_dissector: Drop BPF flow dissector prog ref on netns cleanup
+    - x86/unwind/orc: Fix unwind_get_return_address_ptr() for inactive tasks
+    - iio: adc: stm32-adc: Use dma_request_chan() instead
+      dma_request_slave_channel()
+    - iio: adc: stm32-adc: fix device used to request dma
+    - iio: adc: stm32-dfsdm: Use dma_request_chan() instead
+      dma_request_slave_channel()
+    - iio: adc: stm32-dfsdm: fix device used to request dma
+    - rxrpc: Trace discarded ACKs
+    - rxrpc: Fix ack discard
+    - tpm: check event log version before reading final events
+    - sched/fair: Reorder enqueue/dequeue_task_fair path
+    - sched/fair: Fix reordering of enqueue/dequeue_task_fair()
+    - sched/fair: Fix enqueue_task_fair() warning some more
+    - Linux 5.4.43
+
+  * Focal update: v5.4.42 upstream stable release (LP: #1879759)
+    - net: dsa: Do not make user port errors fatal
+    - shmem: fix possible deadlocks on shmlock_user_lock
+    - net: phy: microchip_t1: add lan87xx_phy_init to initialize the lan87xx phy.
+    - KVM: arm: vgic: Synchronize the whole guest on GIC{D,R}_I{S,C}ACTIVER read
+    - gpio: pca953x: Fix pca953x_gpio_set_config
+    - SUNRPC: Add "@len" parameter to gss_unwrap()
+    - SUNRPC: Fix GSS privacy computation of auth->au_ralign
+    - net/sonic: Fix a resource leak in an error handling path in
+      'jazz_sonic_probe()'
+    - net: moxa: Fix a potential double 'free_irq()'
+    - ftrace/selftests: workaround cgroup RT scheduling issues
+    - drop_monitor: work around gcc-10 stringop-overflow warning
+    - virtio-blk: handle block_device_operations callbacks after hot unplug
+    - sun6i: dsi: fix gcc-4.8
+    - net_sched: fix tcm_parent in tc filter dump
+    - scsi: sg: add sg_remove_request in sg_write
+    - mmc: sdhci-acpi: Add SDHCI_QUIRK2_BROKEN_64_BIT_DMA for AMDI0040
+    - dpaa2-eth: properly handle buffer size restrictions
+    - net: fix a potential recursive NETDEV_FEAT_CHANGE
+    - netlabel: cope with NULL catmap
+    - net: phy: fix aneg restart in phy_ethtool_set_eee
+    - net: stmmac: fix num_por initialization
+    - pppoe: only process PADT targeted at local interfaces
+    - Revert "ipv6: add mtu lock check in __ip6_rt_update_pmtu"
+    - tcp: fix error recovery in tcp_zerocopy_receive()
+    - tcp: fix SO_RCVLOWAT hangs with fat skbs
+    - virtio_net: fix lockdep warning on 32 bit
+    - dpaa2-eth: prevent array underflow in update_cls_rule()
+    - hinic: fix a bug of ndo_stop
+    - net: dsa: loop: Add module soft dependency
+    - net: ipv4: really enforce backoff for redirects
+    - netprio_cgroup: Fix unlimited memory leak of v2 cgroups
+    - net: tcp: fix rx timestamp behavior for tcp_recvmsg
+    - nfp: abm: fix error return code in nfp_abm_vnic_alloc()
+    - r8169: re-establish support for RTL8401 chip version
+    - umh: fix memory leak on execve failure
+    - riscv: fix vdso build with lld
+    - dmaengine: pch_dma.c: Avoid data race between probe and irq handler
+    - dmaengine: mmp_tdma: Do not ignore slave config validation errors
+    - dmaengine: mmp_tdma: Reset channel error on release
+    - selftests/ftrace: Check the first record for kprobe_args_type.tc
+    - cpufreq: intel_pstate: Only mention the BIOS disabling turbo mode once
+    - ALSA: hda/hdmi: fix race in monitor detection during probe
+    - drm/amd/powerplay: avoid using pm_en before it is initialized revised
+    - drm/amd/display: check if REFCLK_CNTL register is present
+    - drm/amd/display: Update downspread percent to match spreadsheet for DCN2.1
+    - drm/qxl: lost qxl_bo_kunmap_atomic_page in qxl_image_init_helper()
+    - drm/amdgpu: simplify padding calculations (v2)
+    - drm/amdgpu: invalidate L2 before SDMA IBs (v2)
+    - ipc/util.c: sysvipc_find_ipc() incorrectly updates position index
+    - gfs2: Another gfs2_walk_metadata fix
+    - mmc: sdhci-pci-gli: Fix no irq handler from suspend
+    - IB/hfi1: Fix another case where pq is left on waitlist
+    - ACPI: EC: PM: Avoid premature returns from acpi_s2idle_wake()
+    - pinctrl: sunrisepoint: Fix PAD lock register offset for SPT-H
+    - pinctrl: baytrail: Enable pin configuration setting for GPIO chip
+    - pinctrl: qcom: fix wrong write in update_dual_edge
+    - pinctrl: cherryview: Add missing spinlock usage in chv_gpio_irq_handler
+    - bpf: Fix error return code in map_lookup_and_delete_elem()
+    - ALSA: firewire-lib: fix 'function sizeof not defined' error of tracepoints
+      format
+    - i40iw: Fix error handling in i40iw_manage_arp_cache()
+    - drm/i915: Don't enable WaIncreaseLatencyIPCEnabled when IPC is disabled
+    - bpf, sockmap: msg_pop_data can incorrecty set an sge length
+    - bpf, sockmap: bpf_tcp_ingress needs to subtract bytes from sg.size
+    - mmc: alcor: Fix a resource leak in the error path for ->probe()
+    - mmc: sdhci-pci-gli: Fix can not access GL9750 after reboot from Windows 10
+    - mmc: core: Check request type before completing the request
+    - mmc: core: Fix recursive locking issue in CQE recovery path
+    - mmc: block: Fix request completion in the CQE timeout path
+    - gfs2: More gfs2_find_jhead fixes
+    - fork: prevent accidental access to clone3 features
+    - drm/amdgpu: force fbdev into vram
+    - NFS: Fix fscache super_cookie index_key from changing after umount
+    - nfs: fscache: use timespec64 in inode auxdata
+    - NFSv4: Fix fscache cookie aux_data to ensure change_attr is included
+    - netfilter: conntrack: avoid gcc-10 zero-length-bounds warning
+    - drm/i915/gvt: Fix kernel oops for 3-level ppgtt guest
+    - arm64: fix the flush_icache_range arguments in machine_kexec
+    - nfs: fix NULL deference in nfs4_get_valid_delegation
+    - SUNRPC: Signalled ASYNC tasks need to exit
+    - netfilter: nft_set_rbtree: Introduce and use nft_rbtree_interval_start()
+    - netfilter: nft_set_rbtree: Add missing expired checks
+    - RDMA/rxe: Always return ERR_PTR from rxe_create_mmap_info()
+    - IB/mlx4: Test return value of calls to ib_get_cached_pkey
+    - IB/core: Fix potential NULL pointer dereference in pkey cache
+    - RDMA/core: Fix double put of resource
+    - RDMA/iw_cxgb4: Fix incorrect function parameters
+    - hwmon: (da9052) Synchronize access with mfd
+    - s390/ism: fix error return code in ism_probe()
+    - mm, memcg: fix inconsistent oom event behavior
+    - NFSv3: fix rpc receive buffer size for MOUNT call
+    - pnp: Use list_for_each_entry() instead of open coding
+    - net/rds: Use ERR_PTR for rds_message_alloc_sgs()
+    - Stop the ad-hoc games with -Wno-maybe-initialized
+    - [Config] updateconfigs for CC_HAS_WARN_MAYBE_UNINITIALIZED
+    - gcc-10: disable 'zero-length-bounds' warning for now
+    - gcc-10: disable 'array-bounds' warning for now
+    - gcc-10: disable 'stringop-overflow' warning for now
+    - gcc-10: disable 'restrict' warning for now
+    - gcc-10 warnings: fix low-hanging fruit
+    - gcc-10: mark more functions __init to avoid section mismatch warnings
+    - gcc-10: avoid shadowing standard library 'free()' in crypto
+    - usb: usbfs: correct kernel->user page attribute mismatch
+    - USB: usbfs: fix mmap dma mismatch
+    - ALSA: hda/realtek - Limit int mic boost for Thinkpad T530
+    - ALSA: hda/realtek - Add COEF workaround for ASUS ZenBook UX431DA
+    - ALSA: rawmidi: Fix racy buffer resize under concurrent accesses
+    - ALSA: usb-audio: Add control message quirk delay for Kingston HyperX headset
+    - usb: core: hub: limit HUB_QUIRK_DISABLE_AUTOSUSPEND to USB5534B
+    - usb: host: xhci-plat: keep runtime active when removing host
+    - usb: cdns3: gadget: prev_req->trb is NULL for ep0
+    - usb: xhci: Fix NULL pointer dereference when enqueuing trbs from urb sg list
+    - Make the "Reducing compressed framebufer size" message be DRM_INFO_ONCE()
+    - ARM: dts: dra7: Fix bus_dma_limit for PCIe
+    - ARM: dts: imx27-phytec-phycard-s-rdk: Fix the I2C1 pinctrl entries
+    - ARM: dts: imx6dl-yapp4: Fix Ursa board Ethernet connection
+    - drm/amd/display: add basic atomic check for cursor plane
+    - powerpc/32s: Fix build failure with CONFIG_PPC_KUAP_DEBUG
+    - cifs: fix leaked reference on requeued write
+    - x86: Fix early boot crash on gcc-10, third try
+    - x86/unwind/orc: Fix error handling in __unwind_start()
+    - exec: Move would_dump into flush_old_exec
+    - clk: rockchip: fix incorrect configuration of rk3228 aclk_gpu* clocks
+    - dwc3: Remove check for HWO flag in dwc3_gadget_ep_reclaim_trb_sg()
+    - fanotify: fix merging marks masks with FAN_ONDIR
+    - usb: gadget: net2272: Fix a memory leak in an error handling path in
+      'net2272_plat_probe()'
+    - usb: gadget: audio: Fix a missing error return value in audio_bind()
+    - usb: gadget: legacy: fix error return code in gncm_bind()
+    - usb: gadget: legacy: fix error return code in cdc_bind()
+    - clk: Unlink clock if failed to prepare or enable
+    - arm64: dts: meson-g12b-khadas-vim3: add missing frddr_a status property
+    - arm64: dts: meson-g12-common: fix dwc2 clock names
+    - arm64: dts: rockchip: Replace RK805 PMIC node name with "pmic" on rk3328
+      boards
+    - arm64: dts: rockchip: Rename dwc3 device nodes on rk3399 to make dtc happy
+    - arm64: dts: imx8mn: Change SDMA1 ahb clock for imx8mn
+    - ARM: dts: r8a73a4: Add missing CMT1 interrupts
+    - arm64: dts: renesas: r8a77980: Fix IPMMU VIP[01] nodes
+    - ARM: dts: r8a7740: Add missing extal2 to CPG node
+    - SUNRPC: Revert 241b1f419f0e ("SUNRPC: Remove xdr_buf_trim()")
+    - bpf: Fix sk_psock refcnt leak when receiving message
+    - KVM: x86: Fix off-by-one error in kvm_vcpu_ioctl_x86_setup_mce
+    - Makefile: disallow data races on gcc-10 as well
+    - Linux 5.4.42
+
+  * upgrading to 4.15.0-99-generic breaks the sound and the trackpad
+    (LP: #1875916) // Focal update: v5.4.42 upstream stable release
+    (LP: #1879759)
+    - Revert "ALSA: hda/realtek: Fix pop noise on ALC225"
+
+  * Pop sound from build-in speaker during cold boot and resume from S3
+    (LP: #1866357) // Focal update: v5.4.42 upstream stable release
+    (LP: #1879759)
+    - ALSA: hda/realtek - Fix S3 pop noise on Dell Wyse
+
+  * tpm: fix TIS locality timeout problems (LP: #1881710)
+    - SAUCE: tpm: fix TIS locality timeout problems
+
+  * [UBUNTU 20.04] s390x/pci: fix linking between PF and VF for multifunction
+    devices (LP: #1879704)
+    - PCI/IOV: Introduce pci_iov_sysfs_link() function
+    - s390/pci: create links between PFs and VFs
+
+  * Performing function level reset of AMD onboard USB and audio devices causes
+    system lockup (LP: #1865988)
+    - SAUCE: PCI: Avoid FLR for AMD Matisse HD Audio & USB 3.0
+    - SAUCE: PCI: Avoid FLR for AMD Starship USB 3.0
+
+  * seccomp_benchmark times out on eoan (LP: #1881576)
+    - SAUCE: selftests/seccomp: use 90s as timeout
+
+  * ASoC/amd: add audio driver for amd renoir (LP: #1881046)
+    - ASoC: amd: add Renoir ACP3x IP register header
+    - ASoC: amd: add Renoir ACP PCI driver
+    - ASoC: amd: add acp init/de-init functions
+    - ASoC: amd: create acp3x pdm platform device
+    - ASoC: amd: add ACP3x PDM platform driver
+    - ASoC: amd: irq handler changes for ACP3x PDM dma driver
+    - ASoC: amd: add acp3x pdm driver dma ops
+    - ASoC: amd: add ACP PDM DMA driver dai ops
+    - ASoC: amd: add Renoir ACP PCI driver PM ops
+    - ASoC: amd: add ACP PDM DMA driver pm ops
+    - ASoC: amd: enable Renoir acp3x drivers build
+    - ASoC: amd: create platform devices for Renoir
+    - ASoC: amd: RN machine driver using dmic
+    - ASoC: amd: enable build for RN machine driver
+    - ASoC: amd: fix kernel warning
+    - ASoC: amd: refactoring dai_hw_params() callback
+    - ASoC: amd: return error when acp de-init fails
+    - [Config]: enable amd renoir ASoC audio
+
+  * Fix for secure boot rules in IMA arch policy on powerpc (LP: #1877955)
+    - powerpc/ima: Fix secure boot rules in ima arch policy
+
+  * [UBUNTU 20.04] s390x/pci: s390_pci_mmio_write/read fail when MIO
+    instructions are available (LP: #1874055)
+    - s390/pci: Fix s390_mmio_read/write with MIO
+
+  * security: lockdown: remove trailing semicolon before function body
+    (LP: #1880660)
+    - SAUCE: (lockdown) security: lockdown: remove trailing semicolon before
+      function body
+
+  * Fix incorrect speed/duplex when I210 device is runtime suspended
+    (LP: #1880656)
+    - igb: Report speed and duplex as unknown when device is runtime suspended
+
+  * [OMEN by HP Laptop 15-dh0xxx, Realtek ALC285, Black Mic, Left] Recording
+    problem (LP: #1874698)
+    - ASoC: SOF: Intel: hda: allow operation without i915 gfx
+    - ASoC: intel/skl/hda - add no-HDMI cases to generic HDA driver
+
+  * CVE-2020-13143
+    - USB: gadget: fix illegal array access in binding with UDC
+
+  * rtl8723bu wifi issue after being turned off (LP: #1878296)
+    - rtl8xxxu: Improve TX performance of RTL8723BU on rtl8xxxu driver
+    - rtl8xxxu: add bluetooth co-existence support for single antenna
+    - rtl8xxxu: remove set but not used variable 'rate_mask'
+    - rtl8xxxu: Remove set but not used variable 'vif', 'dev', 'len'
+
+  * Fix Pericom USB controller OHCI/EHCI PME# defect (LP: #1879321)
+    - serial: 8250_pci: Move Pericom IDs to pci_ids.h
+    - PCI: Avoid Pericom USB controller OHCI/EHCI PME# defect
+
+  * shiftfs: fix btrfs snapshot deletion (LP: #1879688)
+    - SAUCE: shiftfs: let userns root destroy subvolumes from other users
+
+  * [UBUNTU 20.04] s390x/pci: enumerate pci functions per physical adapter
+    (LP: #1874056)
+    - s390/pci: Improve handling of unset UID
+    - s390/pci: embedding hotplug_slot in zdev
+    - s390/pci: Expose new port attribute for PCIe functions
+    - s390/pci: adaptation of iommu to multifunction
+    - s390/pci: define kernel parameters for PCI multifunction
+    - s390/pci: define RID and RID available
+    - s390/pci: create zPCI bus
+    - s390/pci: adapt events for zbus
+    - s390/pci: Handling multifunctions
+    - s390/pci: Do not disable PF when VFs exist
+    - s390/pci: Documentation for zPCI
+    - s390/pci: removes wrong PCI multifunction assignment
+
+  * update-initramfs complains of missing amdgpu firmware files (LP: #1873325)
+    - SAUCE: drm/amdgpu: Remove unreleased arcturus and navi12 firmware from
+      modinfo
+
+ -- Marcelo Henrique Cerri <marcelo.cerri@canonical.com>  Mon, 22 Jun 2020 17:59:17 -0300
+
+linux (5.4.0-39.43) focal; urgency=medium
+
+  * dkms-build: downloads fail in private PPAs (LP: #1883874)
+    - dkms-build: apt-cache policy elides username:password information
+
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+
+ -- Kleber Sacilotto de Souza <kleber.souza@canonical.com>  Fri, 19 Jun 2020 11:56:47 +0200
+
+linux (5.4.0-37.41) focal; urgency=medium
+
+  * CVE-2020-0543
+    - SAUCE: x86/speculation/spectre_v2: Exclude Zhaoxin CPUs from SPECTRE_V2
+    - SAUCE: x86/cpu: Add a steppings field to struct x86_cpu_id
+    - SAUCE: x86/cpu: Add 'table' argument to cpu_matches()
+    - SAUCE: x86/speculation: Add Special Register Buffer Data Sampling (SRBDS)
+      mitigation
+    - SAUCE: x86/speculation: Add SRBDS vulnerability and mitigation documentation
+    - SAUCE: x86/speculation: Add Ivy Bridge to affected list
+
+ -- Marcelo Henrique Cerri <marcelo.cerri@canonical.com>  Wed, 03 Jun 2020 11:24:23 -0300
+
+linux (5.4.0-34.38) focal; urgency=medium
+
+  * focal/linux: 5.4.0-34.38 -proposed tracker (LP: #1880118)
+
+  * debian/scripts/file-downloader does not handle positive failures correctly
+    (LP: #1878897)
+    - [Packaging] file-downloader not handling positive failures correctly
+
+  * Focal update: v5.4.41 upstream stable release (LP: #1878649)
+    - USB: serial: qcserial: Add DW5816e support
+    - nvme: refactor nvme_identify_ns_descs error handling
+    - nvme: fix possible hang when ns scanning fails during error recovery
+    - tracing/kprobes: Fix a double initialization typo
+    - net: macb: Fix runtime PM refcounting
+    - drm/amdgpu: move kfd suspend after ip_suspend_phase1
+    - drm/amdgpu: drop redundant cg/pg ungate on runpm enter
+    - vt: fix unicode console freeing with a common interface
+    - tty: xilinx_uartps: Fix missing id assignment to the console
+    - devlink: fix return value after hitting end in region read
+    - dp83640: reverse arguments to list_add_tail
+    - fq_codel: fix TCA_FQ_CODEL_DROP_BATCH_SIZE sanity checks
+    - ipv6: Use global sernum for dst validation with nexthop objects
+    - mlxsw: spectrum_acl_tcam: Position vchunk in a vregion list properly
+    - neigh: send protocol value in neighbor create notification
+    - net: dsa: Do not leave DSA master with NULL netdev_ops
+    - net: macb: fix an issue about leak related system resources
+    - net: macsec: preserve ingress frame ordering
+    - net/mlx4_core: Fix use of ENOSPC around mlx4_counter_alloc()
+    - net_sched: sch_skbprio: add message validation to skbprio_change()
+    - net: stricter validation of untrusted gso packets
+    - net: tc35815: Fix phydev supported/advertising mask
+    - net/tls: Fix sk_psock refcnt leak in bpf_exec_tx_verdict()
+    - net/tls: Fix sk_psock refcnt leak when in tls_data_ready()
+    - net: usb: qmi_wwan: add support for DW5816e
+    - nfp: abm: fix a memory leak bug
+    - sch_choke: avoid potential panic in choke_reset()
+    - sch_sfq: validate silly quantum values
+    - tipc: fix partial topology connection closure
+    - tunnel: Propagate ECT(1) when decapsulating as recommended by RFC6040
+    - bnxt_en: Fix VF anti-spoof filter setup.
+    - bnxt_en: Reduce BNXT_MSIX_VEC_MAX value to supported CQs per PF.
+    - bnxt_en: Improve AER slot reset.
+    - bnxt_en: Return error when allocating zero size context memory.
+    - bnxt_en: Fix VLAN acceleration handling in bnxt_fix_features().
+    - net/mlx5: DR, On creation set CQ's arm_db member to right value
+    - net/mlx5: Fix forced completion access non initialized command entry
+    - net/mlx5: Fix command entry leak in Internal Error State
+    - net: mvpp2: prevent buffer overflow in mvpp22_rss_ctx()
+    - net: mvpp2: cls: Prevent buffer overflow in mvpp2_ethtool_cls_rule_del()
+    - HID: wacom: Read HID_DG_CONTACTMAX directly for non-generic devices
+    - sctp: Fix bundling of SHUTDOWN with COOKIE-ACK
+    - Revert "HID: wacom: generic: read the number of expected touches on a per
+      collection basis"
+    - HID: usbhid: Fix race between usbhid_close() and usbhid_stop()
+    - HID: wacom: Report 2nd-gen Intuos Pro S center button status over BT
+    - USB: uas: add quirk for LaCie 2Big Quadra
+    - usb: chipidea: msm: Ensure proper controller reset using role switch API
+    - USB: serial: garmin_gps: add sanity checking for data length
+    - tracing: Add a vmalloc_sync_mappings() for safe measure
+    - crypto: arch/nhpoly1305 - process in explicit 4k chunks
+    - KVM: s390: Remove false WARN_ON_ONCE for the PQAP instruction
+    - KVM: VMX: Explicitly clear RFLAGS.CF and RFLAGS.ZF in VM-Exit RSB path
+    - KVM: arm: vgic: Fix limit condition when writing to GICD_I[CS]ACTIVER
+    - KVM: arm64: Fix 32bit PC wrap-around
+    - arm64: hugetlb: avoid potential NULL dereference
+    - drm: ingenic-drm: add MODULE_DEVICE_TABLE
+    - ipc/mqueue.c: change __do_notify() to bypass check_kill_permission()
+    - epoll: atomically remove wait entry on wake up
+    - eventpoll: fix missing wakeup for ovflist in ep_poll_callback
+    - mm/page_alloc: fix watchdog soft lockups during set_zone_contiguous()
+    - mm: limit boost_watermark on small zones
+    - ceph: demote quotarealm lookup warning to a debug message
+    - staging: gasket: Check the return value of gasket_get_bar_index()
+    - coredump: fix crash when umh is disabled
+    - iocost: protect iocg->abs_vdebt with iocg->waitq.lock
+    - batman-adv: fix batadv_nc_random_weight_tq
+    - batman-adv: Fix refcnt leak in batadv_show_throughput_override
+    - batman-adv: Fix refcnt leak in batadv_store_throughput_override
+    - batman-adv: Fix refcnt leak in batadv_v_ogm_process
+    - x86/entry/64: Fix unwind hints in register clearing code
+    - x86/entry/64: Fix unwind hints in kernel exit path
+    - x86/entry/64: Fix unwind hints in rewind_stack_do_exit()
+    - x86/unwind/orc: Don't skip the first frame for inactive tasks
+    - x86/unwind/orc: Prevent unwinding before ORC initialization
+    - x86/unwind/orc: Fix error path for bad ORC entry type
+    - x86/unwind/orc: Fix premature unwind stoppage due to IRET frames
+    - KVM: x86: Fixes posted interrupt check for IRQs delivery modes
+    - arch/x86/kvm/svm/sev.c: change flag passed to GUP fast in sev_pin_memory()
+    - netfilter: nat: never update the UDP checksum when it's 0
+    - netfilter: nf_osf: avoid passing pointer to local var
+    - objtool: Fix stack offset tracking for indirect CFAs
+    - iommu/virtio: Reverse arguments to list_add
+    - scripts/decodecode: fix trapping instruction formatting
+    - mm, memcg: fix error return value of mem_cgroup_css_alloc()
+    - bdi: move bdi_dev_name out of line
+    - bdi: add a ->dev_name field to struct backing_dev_info
+    - fsnotify: replace inode pointer with an object id
+    - fanotify: merge duplicate events on parent and child
+    - Linux 5.4.41
+
+  * Intel GPU Hangs : random screen freezing w/ Ubuntu 20.04 (Linux 5.4)
+    i915_active_acquire (LP: #1868551)
+    - drm/i915: Hold reference to intel_frontbuffer as we track activity
+    - drm/i915: fix uninitialized pointer reads on pointers to and from
+
+  * Kernel panic due to NULL ringbuffer vaddr dereference in i915 (LP: #1877394)
+    - Revert "UBUNTU: SAUCE: drm/i915: Synchronize active and retire callbacks"
+    - drm/i915/gt: Make intel_ring_unpin() safe for concurrent pint
+
+  * add 16-bit width registers support for EEPROM at24 device (LP: #1876699)
+    - regmap-i2c: add 16-bit width registers support
+
+  * [UBUNTU 20.04] PSI generates overhead on s390x (LP: #1876044)
+    - Ubuntu: [Config] Set CONFIG_PSI_DEFAULT_DISABLED=y on s390x
+
+  * Focal update: v5.4.40 upstream stable release (LP: #1878040)
+    - vhost: vsock: kick send_pkt worker once device is started
+    - drm/bridge: analogix_dp: Split bind() into probe() and real bind()
+    - ASoC: topology: Check return value of soc_tplg_create_tlv
+    - ASoC: topology: Check return value of soc_tplg_*_create
+    - ASoC: topology: Check soc_tplg_add_route return value
+    - ASoC: topology: Check return value of pcm_new_ver
+    - ASoC: topology: Check return value of soc_tplg_dai_config
+    - selftests/ipc: Fix test failure seen after initial test run
+    - ASoC: sgtl5000: Fix VAG power-on handling
+    - ASoC: topology: Fix endianness issue
+    - usb: dwc3: gadget: Properly set maxpacket limit
+    - ASoC: rsnd: Fix parent SSI start/stop in multi-SSI mode
+    - ASoC: rsnd: Fix HDMI channel mapping for multi-SSI mode
+    - ASoC: codecs: hdac_hdmi: Fix incorrect use of list_for_each_entry
+    - remoteproc: qcom_q6v5_mss: fix a bug in q6v5_probe()
+    - drm/amdgpu: Correctly initialize thermal controller for GPUs with Powerplay
+      table v0 (e.g Hawaii)
+    - wimax/i2400m: Fix potential urb refcnt leak
+    - net: stmmac: fix enabling socfpga's ptp_ref_clock
+    - net: stmmac: Fix sub-second increment
+    - ASoC: rsnd: Don't treat master SSI in multi SSI setup as parent
+    - ASoC: rsnd: Fix "status check failed" spam for multi-SSI
+    - cifs: protect updating server->dstaddr with a spinlock
+    - scripts/config: allow colons in option strings for sed
+    - cifs: do not share tcons with DFS
+    - tracing: Fix memory leaks in trace_events_hist.c
+    - lib/mpi: Fix building for powerpc with clang
+    - mac80211: sta_info: Add lockdep condition for RCU list usage
+    - net: bcmgenet: suppress warnings on failed Rx SKB allocations
+    - net: systemport: suppress warnings on failed Rx SKB allocations
+    - drm/i915: Extend WaDisableDARBFClkGating to icl,ehl,tgl
+    - sctp: Fix SHUTDOWN CTSN Ack in the peer restart case
+    - Revert "software node: Simplify software_node_release() function"
+    - hexagon: clean up ioremap
+    - hexagon: define ioremap_uc
+    - ALSA: hda: Match both PCI ID and SSID for driver blacklist
+    - x86/kvm: fix a missing-prototypes "vmread_error"
+    - platform/x86: GPD pocket fan: Fix error message when temp-limits are out of
+      range
+    - ACPI: PM: s2idle: Fix comment in acpi_s2idle_prepare_late()
+    - mac80211: add ieee80211_is_any_nullfunc()
+    - cgroup, netclassid: remove double cond_resched
+    - libbpf: Fix readelf output parsing for Fedora
+    - mm/mremap: Add comment explaining the untagging behaviour of mremap()
+    - Revert "drm/amd/display: setting the DIG_MODE to the correct value."
+    - tools headers UAPI: Sync copy of arm64's asm/unistd.h with the kernel
+      sources
+    - udp: document udp_rcv_segment special case for looped packets
+    - PM / devfreq: Add missing locking while setting suspend_freq
+    - Linux 5.4.40
+
+  * Focal update: v5.4.39 upstream stable release (LP: #1877592)
+    - dma-buf: Fix SET_NAME ioctl uapi
+    - drm/edid: Fix off-by-one in DispID DTD pixel clock
+    - drm/amd/display: Fix green screen issue after suspend
+    - drm/qxl: qxl_release leak in qxl_draw_dirty_fb()
+    - drm/qxl: qxl_release leak in qxl_hw_surface_alloc()
+    - drm/qxl: qxl_release use after free
+    - NFSv4.1: fix handling of backchannel binding in BIND_CONN_TO_SESSION
+    - btrfs: fix transaction leak in btrfs_recover_relocation
+    - btrfs: fix block group leak when removing fails
+    - btrfs: fix partial loss of prealloc extent past i_size after fsync
+    - btrfs: transaction: Avoid deadlock due to bad initialization timing of
+      fs_info::journal_info
+    - mmc: cqhci: Avoid false "cqhci: CQE stuck on" by not open-coding timeout
+      loop
+    - mmc: sdhci-xenon: fix annoying 1.8V regulator warning
+    - mmc: sdhci-pci: Fix eMMC driver strength for BYT-based controllers
+    - mmc: sdhci-msm: Enable host capabilities pertains to R1b response
+    - mmc: meson-mx-sdio: Set MMC_CAP_WAIT_WHILE_BUSY
+    - mmc: meson-mx-sdio: remove the broken ->card_busy() op
+    - crypto: caam - fix the address of the last entry of S/G
+    - ALSA: hda/realtek - Two front mics on a Lenovo ThinkCenter
+    - ALSA: usb-audio: Correct a typo of NuPrime DAC-10 USB ID
+    - ALSA: hda/hdmi: fix without unlocked before return
+    - ALSA: line6: Fix POD HD500 audio playback
+    - ALSA: pcm: oss: Place the plugin buffer overflow checks correctly
+    - i2c: amd-mp2-pci: Fix Oops in amd_mp2_pci_init() error handling
+    - Drivers: hv: vmbus: Fix Suspend-to-Idle for Generation-2 VM
+    - dlmfs_file_write(): fix the bogosity in handling non-zero *ppos
+    - IB/rdmavt: Always return ERR_PTR from rvt_create_mmap_info()
+    - PM: ACPI: Output correct message on target power state
+    - PM: hibernate: Freeze kernel threads in software_resume()
+    - dm verity fec: fix hash block number in verity_fec_decode
+    - dm writecache: fix data corruption when reloading the target
+    - dm multipath: use updated MPATHF_QUEUE_IO on mapping for bio-based mpath
+    - ARM: dts: imx6qdl-sr-som-ti: indicate powering off wifi is safe
+    - scsi: qla2xxx: set UNLOADING before waiting for session deletion
+    - scsi: qla2xxx: check UNLOADING before posting async work
+    - RDMA/mlx5: Set GRH fields in query QP on RoCE
+    - RDMA/mlx4: Initialize ib_spec on the stack
+    - RDMA/siw: Fix potential siw_mem refcnt leak in siw_fastreg_mr()
+    - RDMA/core: Prevent mixed use of FDs between shared ufiles
+    - RDMA/core: Fix race between destroy and release FD object
+    - RDMA/cm: Fix ordering of xa_alloc_cyclic() in ib_create_cm_id()
+    - RDMA/cm: Fix an error check in cm_alloc_id_priv()
+    - i2c: iproc: generate stop event for slave writes
+    - vfio: avoid possible overflow in vfio_iommu_type1_pin_pages
+    - vfio/type1: Fix VA->PA translation for PFNMAP VMAs in vaddr_get_pfn()
+    - iommu/qcom: Fix local_base status check
+    - scsi: target/iblock: fix WRITE SAME zeroing
+    - iommu/amd: Fix legacy interrupt remapping for x2APIC-enabled system
+    - i2c: aspeed: Avoid i2c interrupt status clear race condition.
+    - ALSA: opti9xx: shut up gcc-10 range warning
+    - Fix use after free in get_tree_bdev()
+    - nvme: prevent double free in nvme_alloc_ns() error handling
+    - nfs: Fix potential posix_acl refcnt leak in nfs3_set_acl
+    - dmaengine: dmatest: Fix iteration non-stop logic
+    - dmaengine: dmatest: Fix process hang when reading 'wait' parameter
+    - arm64: vdso: Add -fasynchronous-unwind-tables to cflags
+    - selinux: properly handle multiple messages in selinux_netlink_send()
+    - Linux 5.4.39
+
+  * Focal update: v5.4.38 upstream stable release (LP: #1876767)
+    - Linux 5.4.38
+
+  * Focal update: v5.4.37 upstream stable release (LP: #1876765)
+    - remoteproc: Fix wrong rvring index computation
+    - ubifs: Fix ubifs_tnc_lookup() usage in do_kill_orphans()
+    - printk: queue wake_up_klogd irq_work only if per-CPU areas are ready
+    - ASoC: stm32: sai: fix sai probe
+    - usb: dwc3: gadget: Do link recovery for SS and SSP
+    - kbuild: fix DT binding schema rule again to avoid needless rebuilds
+    - usb: gadget: udc: bdc: Remove unnecessary NULL checks in bdc_req_complete
+    - usb: gadget: udc: atmel: Fix vbus disconnect handling
+    - afs: Make record checking use TASK_UNINTERRUPTIBLE when appropriate
+    - afs: Fix to actually set AFS_SERVER_FL_HAVE_EPOCH
+    - iio:ad7797: Use correct attribute_group
+    - propagate_one(): mnt_set_mountpoint() needs mount_lock
+    - counter: 104-quad-8: Add lock guards - generic interface
+    - s390/ftrace: fix potential crashes when switching tracers
+    - ASoC: q6dsp6: q6afe-dai: add missing channels to MI2S DAIs
+    - ASoC: tas571x: disable regulators on failed probe
+    - ASoC: wm8960: Fix wrong clock after suspend & resume
+    - drivers: soc: xilinx: fix firmware driver Kconfig dependency
+    - nfsd: memory corruption in nfsd4_lock()
+    - bpf: Forbid XADD on spilled pointers for unprivileged users
+    - i2c: altera: use proper variable to hold errno
+    - rxrpc: Fix DATA Tx to disable nofrag for UDP on AF_INET6 socket
+    - net/cxgb4: Check the return from t4_query_params properly
+    - xfs: acquire superblock freeze protection on eofblocks scans
+    - svcrdma: Fix trace point use-after-free race
+    - svcrdma: Fix leak of svc_rdma_recv_ctxt objects
+    - net/mlx5e: Don't trigger IRQ multiple times on XSK wakeup to avoid WQ
+      overruns
+    - net/mlx5e: Get the latest values from counters in switchdev mode
+    - PCI: Add ACS quirk for Zhaoxin multi-function devices
+    - PCI: Make ACS quirk implementations more uniform
+    - PCI: Unify ACS quirk desired vs provided checking
+    - PCI: Add Zhaoxin Vendor ID
+    - PCI: Add ACS quirk for Zhaoxin Root/Downstream Ports
+    - PCI: Move Apex Edge TPU class quirk to fix BAR assignment
+    - ARM: dts: bcm283x: Disable dsi0 node
+    - cpumap: Avoid warning when CONFIG_DEBUG_PER_CPU_MAPS is enabled
+    - s390/pci: do not set affinity for floating irqs
+    - net/mlx5: Fix failing fw tracer allocation on s390
+    - sched/core: Fix reset-on-fork from RT with uclamp
+    - perf/core: fix parent pid/tid in task exit events
+    - netfilter: nat: fix error handling upon registering inet hook
+    - PM: sleep: core: Switch back to async_schedule_dev()
+    - blk-iocost: Fix error on iocost_ioc_vrate_adj
+    - um: ensure `make ARCH=um mrproper` removes
+      arch/$(SUBARCH)/include/generated/
+    - bpf, x86_32: Fix incorrect encoding in BPF_LDX zero-extension
+    - bpf, x86_32: Fix clobbering of dst for BPF_JSET
+    - bpf, x86_32: Fix logic error in BPF_LDX zero-extension
+    - mm: shmem: disable interrupt when acquiring info->lock in userfaultfd_copy
+      path
+    - xfs: clear PF_MEMALLOC before exiting xfsaild thread
+    - bpf, x86: Fix encoding for lower 8-bit registers in BPF_STX BPF_B
+    - libbpf: Initialize *nl_pid so gcc 10 is happy
+    - net: fec: set GPR bit on suspend by DT configuration.
+    - x86: hyperv: report value of misc_features
+    - signal: check sig before setting info in kill_pid_usb_asyncio
+    - afs: Fix length of dump of bad YFSFetchStatus record
+    - xfs: fix partially uninitialized structure in xfs_reflink_remap_extent
+    - ALSA: hda: Release resources at error in delayed probe
+    - ALSA: hda: Keep the controller initialization even if no codecs found
+    - ALSA: hda: Explicitly permit using autosuspend if runtime PM is supported
+    - scsi: target: fix PR IN / READ FULL STATUS for FC
+    - scsi: target: tcmu: reset_ring should reset TCMU_DEV_BIT_BROKEN
+    - objtool: Fix CONFIG_UBSAN_TRAP unreachable warnings
+    - objtool: Support Clang non-section symbols in ORC dump
+    - xen/xenbus: ensure xenbus_map_ring_valloc() returns proper grant status
+    - ALSA: hda: call runtime_allow() for all hda controllers
+    - net: stmmac: socfpga: Allow all RGMII modes
+    - mac80211: fix channel switch trigger from unknown mesh peer
+    - arm64: Delete the space separator in __emit_inst
+    - ext4: use matching invalidatepage in ext4_writepage
+    - ext4: increase wait time needed before reuse of deleted inode numbers
+    - ext4: convert BUG_ON's to WARN_ON's in mballoc.c
+    - blk-mq: Put driver tag in blk_mq_dispatch_rq_list() when no budget
+    - hwmon: (jc42) Fix name to have no illegal characters
+    - taprio: do not use BIT() in TCA_TAPRIO_ATTR_FLAG_* definitions
+    - qed: Fix race condition between scheduling and destroying the slowpath
+      workqueue
+    - Crypto: chelsio - Fixes a hang issue during driver registration
+    - net: use indirect call wrappers for skb_copy_datagram_iter()
+    - qed: Fix use after free in qed_chain_free
+    - ext4: check for non-zero journal inum in ext4_calculate_overhead
+    - ASoC: soc-core: disable route checks for legacy devices
+    - ASoC: stm32: spdifrx: fix regmap status check
+    - Linux 5.4.37
+
+  * Focal update: v5.4.36 upstream stable release (LP: #1876361)
+    - ext4: fix extent_status fragmentation for plain files
+    - f2fs: fix to avoid memory leakage in f2fs_listxattr
+    - net, ip_tunnel: fix interface lookup with no key
+    - [Config] updateconfigs for ARM64_ERRATUM_1542419
+    - arm64: errata: Hide CTR_EL0.DIC on systems affected by Neoverse-N1 #1542419
+    - arm64: Fake the IminLine size on systems affected by Neoverse-N1 #1542419
+    - arm64: compat: Workaround Neoverse-N1 #1542419 for compat user-space
+    - arm64: Silence clang warning on mismatched value/register sizes
+    - tools/testing/nvdimm: Fix compilation failure without
+      CONFIG_DEV_DAX_PMEM_COMPAT
+    - watchdog: reset last_hw_keepalive time at start
+    - scsi: lpfc: Fix kasan slab-out-of-bounds error in lpfc_unreg_login
+    - scsi: lpfc: Fix crash after handling a pci error
+    - scsi: lpfc: Fix crash in target side cable pulls hitting WAIT_FOR_UNREG
+    - scsi: libfc: If PRLI rejected, move rport to PLOGI state
+    - ceph: return ceph_mdsc_do_request() errors from __get_parent()
+    - ceph: don't skip updating wanted caps when cap is stale
+    - pwm: rcar: Fix late Runtime PM enablement
+    - nvme-tcp: fix possible crash in write_zeroes processing
+    - scsi: iscsi: Report unbind session event when the target has been removed
+    - tools/test/nvdimm: Fix out of tree build
+    - ASoC: Intel: atom: Take the drv->lock mutex before calling
+      sst_send_slot_map()
+    - nvme: fix deadlock caused by ANA update wrong locking
+    - drm/amd/display: Update stream adjust in dc_stream_adjust_vmin_vmax
+    - dma-direct: fix data truncation in dma_direct_get_required_mask()
+    - kernel/gcov/fs.c: gcov_seq_next() should increase position index
+    - selftests: kmod: fix handling test numbers above 9
+    - ipc/util.c: sysvipc_find_ipc() should increase position index
+    - kconfig: qconf: Fix a few alignment issues
+    - lib/raid6/test: fix build on distros whose /bin/sh is not bash
+    - s390/cio: generate delayed uevent for vfio-ccw subchannels
+    - s390/cio: avoid duplicated 'ADD' uevents
+    - loop: Better discard support for block devices
+    - Revert "powerpc/64: irq_work avoid interrupt when called with hardware irqs
+      enabled"
+    - powerpc/pseries: Fix MCE handling on pseries
+    - nvme: fix compat address handling in several ioctls
+    - pwm: renesas-tpu: Fix late Runtime PM enablement
+    - pwm: bcm2835: Dynamically allocate base
+    - perf/core: Disable page faults when getting phys address
+    - drm/amd/display: Calculate scaling ratios on every medium/full update
+    - ASoC: Intel: bytcr_rt5640: Add quirk for MPMAN MPWIN895CL tablet
+    - ALSA: usb-audio: Add Pioneer DJ DJM-250MK2 quirk
+    - drm/amd/display: Not doing optimize bandwidth if flip pending.
+    - cxgb4: fix adapter crash due to wrong MC size
+    - cxgb4: fix large delays in PTP synchronization
+    - ipv4: Update fib_select_default to handle nexthop objects
+    - ipv6: fix restrict IPV6_ADDRFORM operation
+    - macsec: avoid to set wrong mtu
+    - macvlan: fix null dereference in macvlan_device_event()
+    - mlxsw: Fix some IS_ERR() vs NULL bugs
+    - net: bcmgenet: correct per TX/RX ring statistics
+    - net/mlx4_en: avoid indirect call in TX completion
+    - net: netrom: Fix potential nr_neigh refcnt leak in nr_add_node
+    - net: openvswitch: ovs_ct_exit to be done under ovs_lock
+    - net: stmmac: dwmac-meson8b: Add missing boundary to RGMII TX clock array
+    - net/x25: Fix x25_neigh refcnt leak when receiving frame
+    - sched: etf: do not assume all sockets are full blown
+    - selftests: Fix suppress test in fib_tests.sh
+    - tcp: cache line align MAX_TCP_HEADER
+    - team: fix hang in team_mode_get()
+    - vrf: Fix IPv6 with qdisc and xfrm
+    - net: dsa: b53: Lookup VID in ARL searches when VLAN is enabled
+    - net: dsa: b53: Fix valid setting for MDB entries
+    - net: dsa: b53: Fix ARL register definitions
+    - net: dsa: b53: Rework ARL bin logic
+    - net: dsa: b53: b53_arl_rw_op() needs to select IVL or SVL
+    - vxlan: use the correct nlattr array in NL_SET_ERR_MSG_ATTR
+    - geneve: use the correct nlattr array in NL_SET_ERR_MSG_ATTR
+    - xfrm: Always set XFRM_TRANSFORMED in xfrm{4,6}_output_finish
+    - vrf: Check skb for XFRM_TRANSFORMED flag
+    - KEYS: Avoid false positive ENOMEM error on key read
+    - ALSA: hda: Remove ASUS ROG Zenith from the blacklist
+    - ALSA: usb-audio: Add static mapping table for ALC1220-VB-based mobos
+    - ALSA: usb-audio: Add connector notifier delegation
+    - iio: core: remove extra semi-colon from devm_iio_device_register() macro
+    - iio: st_sensors: rely on odr mask to know if odr can be set
+    - iio: adc: stm32-adc: fix sleep in atomic context
+    - iio: adc: ti-ads8344: properly byte swap value
+    - iio: xilinx-xadc: Fix ADC-B powerdown
+    - iio: xilinx-xadc: Fix clearing interrupt when enabling trigger
+    - iio: xilinx-xadc: Fix sequencer configuration for aux channels in
+      simultaneous mode
+    - iio: xilinx-xadc: Make sure not exceed maximum samplerate
+    - USB: sisusbvga: Change port variable from signed to unsigned
+    - USB: Add USB_QUIRK_DELAY_CTRL_MSG and USB_QUIRK_DELAY_INIT for Corsair K70
+      RGB RAPIDFIRE
+    - USB: early: Handle AMD's spec-compliant identifiers, too
+    - USB: core: Fix free-while-in-use bug in the USB S-Glibrary
+    - USB: hub: Fix handling of connect changes during sleep
+    - USB: hub: Revert commit bd0e6c9614b9 ("usb: hub: try old enumeration scheme
+      first for high speed devices")
+    - tty: serial: owl: add "much needed" clk_prepare_enable()
+    - vmalloc: fix remap_vmalloc_range() bounds checks
+    - staging: gasket: Fix incongruency in handling of sysfs entries creation
+    - coredump: fix null pointer dereference on coredump
+    - mm/hugetlb: fix a addressing exception caused by huge_pte_offset
+    - mm/ksm: fix NULL pointer dereference when KSM zero page is enabled
+    - tools/vm: fix cross-compile build
+    - ALSA: usx2y: Fix potential NULL dereference
+    - ALSA: hda/realtek - Fix unexpected init_amp override
+    - ALSA: hda/realtek - Add new codec supported for ALC245
+    - ALSA: hda/hdmi: Add module option to disable audio component binding
+    - ALSA: usb-audio: Fix usb audio refcnt leak when getting spdif
+    - ALSA: usb-audio: Filter out unsupported sample rates on Focusrite devices
+    - tpm/tpm_tis: Free IRQ if probing fails
+    - tpm: fix wrong return value in tpm_pcr_extend
+    - tpm: ibmvtpm: retry on H_CLOSED in tpm_ibmvtpm_send()
+    - KVM: s390: Return last valid slot if approx index is out-of-bounds
+    - KVM: Check validity of resolved slot when searching memslots
+    - KVM: VMX: Enable machine check support for 32bit targets
+    - tty: hvc: fix buffer overflow during hvc_alloc().
+    - tty: rocket, avoid OOB access
+    - usb-storage: Add unusual_devs entry for JMicron JMS566
+    - signal: Avoid corrupting si_pid and si_uid in do_notify_parent
+    - audit: check the length of userspace generated audit records
+    - ASoC: dapm: fixup dapm kcontrol widget
+    - mac80211: populate debugfs only after cfg80211 init
+    - SUNRPC: Fix backchannel RPC soft lockups
+    - iwlwifi: pcie: actually release queue memory in TVQM
+    - iwlwifi: mvm: beacon statistics shouldn't go backwards
+    - iwlwifi: mvm: limit maximum queue appropriately
+    - iwlwifi: mvm: Do not declare support for ACK Enabled Aggregation
+    - iwlwifi: mvm: fix inactive TID removal return value usage
+    - cifs: fix uninitialised lease_key in open_shroot()
+    - ARM: imx: provide v7_cpu_resume() only on ARM_CPU_SUSPEND=y
+    - powerpc/setup_64: Set cache-line-size based on cache-block-size
+    - staging: comedi: dt2815: fix writing hi byte of analog output
+    - staging: comedi: Fix comedi_device refcnt leak in comedi_open
+    - vt: don't hardcode the mem allocation upper bound
+    - vt: don't use kmalloc() for the unicode screen buffer
+    - staging: vt6656: Don't set RCR_MULTICAST or RCR_BROADCAST by default.
+    - staging: vt6656: Fix calling conditions of vnt_set_bss_mode
+    - staging: vt6656: Fix drivers TBTT timing counter.
+    - staging: vt6656: Fix pairwise key entry save.
+    - staging: vt6656: Power save stop wake_up_count wrap around.
+    - cdc-acm: close race betrween suspend() and acm_softint
+    - cdc-acm: introduce a cool down
+    - UAS: no use logging any details in case of ENODEV
+    - UAS: fix deadlock in error handling and PM flushing work
+    - fpga: dfl: pci: fix return value of cci_pci_sriov_configure
+    - usb: dwc3: gadget: Fix request completion check
+    - usb: f_fs: Clear OS Extended descriptor counts to zero in ffs_data_reset()
+    - usb: typec: tcpm: Ignore CC and vbus changes in PORT_RESET change
+    - usb: typec: altmode: Fix typec_altmode_get_partner sometimes returning an
+      invalid pointer
+    - xhci: Fix handling halted endpoint even if endpoint ring appears empty
+    - xhci: prevent bus suspend if a roothub port detected a over-current
+      condition
+    - xhci: Don't clear hub TT buffer on ep0 protocol stall
+    - serial: sh-sci: Make sure status register SCxSR is read in correct sequence
+    - Revert "serial: uartps: Fix uartps_major handling"
+    - Revert "serial: uartps: Use the same dynamic major number for all ports"
+    - Revert "serial: uartps: Fix error path when alloc failed"
+    - Revert "serial: uartps: Do not allow use aliases >= MAX_UART_INSTANCES"
+    - Revert "serial: uartps: Change uart ID port allocation"
+    - Revert "serial: uartps: Move Port ID to device data structure"
+    - Revert "serial: uartps: Register own uart console and driver structures"
+    - powerpc/kuap: PPC_KUAP_DEBUG should depend on PPC_KUAP
+    - powerpc/mm: Fix CONFIG_PPC_KUAP_DEBUG on PPC32
+    - compat: ARM64: always include asm-generic/compat.h
+    - Linux 5.4.36
+
+  * Focal update: v5.4.35 upstream stable release (LP: #1875660)
+    - ext4: use non-movable memory for superblock readahead
+    - watchdog: sp805: fix restart handler
+    - xsk: Fix out of boundary write in __xsk_rcv_memcpy
+    - arm, bpf: Fix bugs with ALU64 {RSH, ARSH} BPF_K shift by 0
+    - arm, bpf: Fix offset overflow for BPF_MEM BPF_DW
+    - objtool: Fix switch table detection in .text.unlikely
+    - scsi: sg: add sg_remove_request in sg_common_write
+    - ALSA: hda: Honor PM disablement in PM freeze and thaw_noirq ops
+    - ARM: dts: imx6: Use gpc for FEC interrupt controller to fix wake on LAN.
+    - kbuild, btf: Fix dependencies for DEBUG_INFO_BTF
+    - netfilter: nf_tables: report EOPNOTSUPP on unsupported flags/object type
+    - irqchip/mbigen: Free msi_desc on device teardown
+    - ALSA: hda: Don't release card at firmware loading error
+    - xsk: Add missing check on user supplied headroom size
+    - of: unittest: kmemleak on changeset destroy
+    - of: unittest: kmemleak in of_unittest_platform_populate()
+    - of: unittest: kmemleak in of_unittest_overlay_high_level()
+    - of: overlay: kmemleak in dup_and_fixup_symbol_prop()
+    - x86/Hyper-V: Unload vmbus channel in hv panic callback
+    - x86/Hyper-V: Trigger crash enlightenment only once during system crash.
+    - x86/Hyper-V: Report crash register data or kmsg before running crash kernel
+    - x86/Hyper-V: Report crash register data when sysctl_record_panic_msg is not
+      set
+    - x86/Hyper-V: Report crash data in die() when panic_on_oops is set
+    - afs: Fix missing XDR advance in xdr_decode_{AFS,YFS}FSFetchStatus()
+    - afs: Fix decoding of inline abort codes from version 1 status records
+    - afs: Fix rename operation status delivery
+    - afs: Fix afs_d_validate() to set the right directory version
+    - afs: Fix race between post-modification dir edit and readdir/d_revalidate
+    - block, bfq: turn put_queue into release_process_ref in
+      __bfq_bic_change_cgroup
+    - block, bfq: make reparent_leaf_entity actually work only on leaf entities
+    - block, bfq: invoke flush_idle_tree after reparent_active_queues in
+      pd_offline
+    - rbd: avoid a deadlock on header_rwsem when flushing notifies
+    - rbd: call rbd_dev_unprobe() after unwatching and flushing notifies
+    - x86/Hyper-V: Free hv_panic_page when fail to register kmsg dump
+    - drm/ttm: flush the fence on the bo after we individualize the reservation
+      object
+    - clk: Don't cache errors from clk_ops::get_phase()
+    - clk: at91: usb: continue if clk_hw_round_rate() return zero
+    - net/mlx5e: Enforce setting of a single FEC mode
+    - f2fs: fix the panic in do_checkpoint()
+    - ARM: dts: rockchip: fix vqmmc-supply property name for rk3188-bqedison2qc
+    - arm64: dts: allwinner: a64: Fix display clock register range
+    - power: supply: bq27xxx_battery: Silence deferred-probe error
+    - clk: tegra: Fix Tegra PMC clock out parents
+    - arm64: tegra: Add PCIe endpoint controllers nodes for Tegra194
+    - arm64: tegra: Fix Tegra194 PCIe compatible string
+    - arm64: dts: clearfog-gt-8k: set gigabit PHY reset deassert delay
+    - soc: imx: gpc: fix power up sequencing
+    - dma-coherent: fix integer overflow in the reserved-memory dma allocation
+    - rtc: 88pm860x: fix possible race condition
+    - NFS: alloc_nfs_open_context() must use the file cred when available
+    - NFSv4/pnfs: Return valid stateids in nfs_layout_find_inode_by_stateid()
+    - NFSv4.2: error out when relink swapfile
+    - ARM: dts: rockchip: fix lvds-encoder ports subnode for rk3188-bqedison2qc
+    - KVM: PPC: Book3S HV: Fix H_CEDE return code for nested guests
+    - f2fs: fix to show norecovery mount option
+    - phy: uniphier-usb3ss: Add Pro5 support
+    - NFS: direct.c: Fix memory leak of dreq when nfs_get_lock_context fails
+    - f2fs: Fix mount failure due to SPO after a successful online resize FS
+    - f2fs: Add a new CP flag to help fsck fix resize SPO issues
+    - s390/cpuinfo: fix wrong output when CPU0 is offline
+    - hibernate: Allow uswsusp to write to swap
+    - btrfs: add RCU locks around block group initialization
+    - powerpc/prom_init: Pass the "os-term" message to hypervisor
+    - powerpc/maple: Fix declaration made after definition
+    - s390/cpum_sf: Fix wrong page count in error message
+    - ext4: do not commit super on read-only bdev
+    - um: ubd: Prevent buffer overrun on command completion
+    - cifs: Allocate encryption header through kmalloc
+    - mm/hugetlb: fix build failure with HUGETLB_PAGE but not HUGEBTLBFS
+    - drm/nouveau/svm: check for SVM initialized before migrating
+    - drm/nouveau/svm: fix vma range check for migration
+    - include/linux/swapops.h: correct guards for non_swap_entry()
+    - percpu_counter: fix a data race at vm_committed_as
+    - compiler.h: fix error in BUILD_BUG_ON() reporting
+    - KVM: s390: vsie: Fix possible race when shadowing region 3 tables
+    - drm/nouveau: workaround runpm fail by disabling PCI power management on
+      certain intel bridges
+    - leds: core: Fix warning message when init_data
+    - x86: ACPI: fix CPU hotplug deadlock
+    - csky: Fixup cpu speculative execution to IO area
+    - drm/amdkfd: kfree the wrong pointer
+    - NFS: Fix memory leaks in nfs_pageio_stop_mirroring()
+    - csky: Fixup get wrong psr value from phyical reg
+    - f2fs: fix NULL pointer dereference in f2fs_write_begin()
+    - ACPICA: Fixes for acpiExec namespace init file
+    - um: falloc.h needs to be directly included for older libc
+    - drm/vc4: Fix HDMI mode validation
+    - iommu/virtio: Fix freeing of incomplete domains
+    - iommu/vt-d: Fix mm reference leak
+    - ext2: fix empty body warnings when -Wextra is used
+    - iommu/vt-d: Silence RCU-list debugging warning in dmar_find_atsr()
+    - iommu/vt-d: Fix page request descriptor size
+    - ext2: fix debug reference to ext2_xattr_cache
+    - sunrpc: Fix gss_unwrap_resp_integ() again
+    - csky: Fixup init_fpu compile warning with __init
+    - power: supply: axp288_fuel_gauge: Broaden vendor check for Intel Compute
+      Sticks.
+    - libnvdimm: Out of bounds read in __nd_ioctl()
+    - iommu/amd: Fix the configuration of GCR3 table root pointer
+    - f2fs: fix to wait all node page writeback
+    - drm/nouveau/gr/gp107,gp108: implement workaround for HW hanging during init
+    - net: dsa: bcm_sf2: Fix overflow checks
+    - dma-debug: fix displaying of dma allocation type
+    - fbdev: potential information leak in do_fb_ioctl()
+    - ARM: dts: sunxi: Fix DE2 clocks register range
+    - iio: si1133: read 24-bit signed integer for measurement
+    - fbmem: Adjust indentation in fb_prepare_logo and fb_blank
+    - tty: evh_bytechan: Fix out of bounds accesses
+    - locktorture: Print ratio of acquisitions, not failures
+    - mtd: rawnand: free the nand_device object
+    - mtd: spinand: Explicitly use MTD_OPS_RAW to write the bad block marker to
+      OOB
+    - docs: Fix path to MTD command line partition parser
+    - mtd: lpddr: Fix a double free in probe()
+    - mtd: phram: fix a double free issue in error path
+    - KEYS: Don't write out to userspace while holding key semaphore
+    - bpf: fix buggy r0 retval refinement for tracing helpers
+    - bpf: Test_verifier, bpf_get_stack return value add <0
+    - bpf: Test_progs, add test to catch retval refine error handling
+    - SAUCE: bpf: Test_progs, fix test_get_stack_rawtp_err.c build
+    - bpf, test_verifier: switch bpf_get_stack's 0 s> r8 test
+    - Linux 5.4.35
+
+  * Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201NGW),
+    REV=0x354 [8086:a0f0] subsystem id [1a56:1651] wireless adapter not found
+    due to firmware crash (LP: #1874685)
+    - iwlwifi: pcie: handle QuZ configs with killer NICs as well
+
+  * Support DMIC micmute LED on HP platforms (LP: #1876859)
+    - ALSA: hda/realtek - Introduce polarity for micmute LED GPIO
+    - ALSA: hda/realtek - Enable micmute LED on and HP system
+    - ALSA: hda/realtek - Add LED class support for micmute LED
+    - ALSA: hda/realtek - Fix unused variable warning w/o
+      CONFIG_LEDS_TRIGGER_AUDIO
+    - ASoC: SOF: Update correct LED status at the first time usage of
+      update_mute_led()
+
+  * linux: riscv: set max_pfn to the PFN of the last page (LP: #1876885)
+    - riscv: set max_pfn to the PFN of the last page
+
+  * Dell XPS 13 9300 mirror mode doesn't work sometimes with WD19TB
+    (LP: #1877013)
+    - drm/i915/perf: Do not clear pollin for small user read buffers
+
+  * [UBUNTU 20.04] s390x/pci: do not allow to create more pci functions than
+    configured via CONFIG_PCI_NR_FUNCTIONS (LP: #1874057)
+    - s390/pci: Fix zpci_alloc_domain() over allocation
+
+  * [Ubuntu 20.04] net/mlx5e: Fix endianness handling in pedit mask
+    (LP: #1872726)
+    - net/mlx5e: Fix endianness handling in pedit mask
+
+  * rtkit-daemon[*]: Failed to make ourselves RT: Operation not permitted after
+    upgrade to 20.04 (LP: #1875665)
+    - [Config] Turn off CONFIG_RT_GROUP_SCHED everywhere
+
+  * ceph -- Unable to mount ceph volume on s390x (LP: #1875863)
+    - ceph: fix endianness bug when handling MDS session feature bits
+
+  * Do not treat unresolved test case in ftrace from ubuntu_kernel_selftests as
+    failure (LP: #1877958)
+    - ftrace/selftest: make unresolved cases cause failure if --fail-unresolved
+      set
+
+  * Add support for Ambiq micro AM1805 RTC chip (LP: #1876667)
+    - SAUCE: rtc: add am-1805 RTC driver
+
+  * alsa/sof: kernel oops on the machine without Intel hdmi audio codec (a
+    regression in the  asoc machine driver) (LP: #1874359)
+    - SAUCE: ASoC: intel/skl/hda - fix oops on systems without i915 audio codec
+
+  * 'Elan touchpad' not detected on 'Lenovo ThinkBook 15 IIL' (LP: #1861610)
+    - SAUCE: Input: elan_i2c - add more hardware ID for Lenovo laptop
+
+ -- Kleber Sacilotto de Souza <kleber.souza@canonical.com>  Mon, 25 May 2020 17:05:37 +0200
+
+linux (5.4.0-33.37) focal; urgency=medium
+
+  * focal/linux: 5.4.0-33.37 -proposed tracker (LP: #1879926)
+
+  * Docker registry doesn't stay up and keeps restarting (LP: #1879690)
+    - Revert "UBUNTU: SAUCE: overlayfs: fix shitfs special-casing"
+    - Revert "UBUNTU: SAUCE: overlayfs: use shiftfs hacks only with shiftfs as
+      underlay"
+
+ -- Kleber Sacilotto de Souza <kleber.souza@canonical.com>  Thu, 21 May 2020 14:34:26 +0200
+
+linux (5.4.0-31.35) focal; urgency=medium
+
+  * focal/linux: 5.4.0-31.35 -proposed tracker (LP: #1877253)
+
+  * Intermittent display blackouts on event (LP: #1875254)
+    - drm/i915: Limit audio CDCLK>=2*BCLK constraint back to GLK only
+
+  * Unable to handle kernel pointer dereference in virtual kernel address space
+    on Eoan (LP: #1876645)
+    - SAUCE: overlayfs: fix shitfs special-casing
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Thu, 07 May 2020 11:05:18 +0200
+
+linux (5.4.0-30.34) focal; urgency=medium
+
+  * focal/linux: 5.4.0-30.34 -proposed tracker (LP: #1875385)
+
+  * ubuntu/focal64 fails to mount Vagrant shared folders  (LP: #1873506)
+    - [Packaging] Move virtualbox modules to linux-modules
+    - [Packaging] Remove vbox and zfs modules from generic.inclusion-list
+
+  * linux-image-5.0.0-35-generic breaks checkpointing of container
+    (LP: #1857257)
+    - SAUCE: overlayfs: use shiftfs hacks only with shiftfs as underlay
+
+  * shiftfs: broken shiftfs nesting (LP: #1872094)
+    - SAUCE: shiftfs: record correct creator credentials
+
+  * Add debian/rules targets to compile/run kernel selftests (LP: #1874286)
+    - [Packaging] add support to compile/run selftests
+
+  * shiftfs: O_TMPFILE reports ESTALE (LP: #1872757)
+    - SAUCE: shiftfs: fix dentry revalidation
+
+  * LIO hanging in iscsit_free_session and iscsit_stop_session (LP: #1871688)
+    - scsi: target: iscsi: calling iscsit_stop_session() inside
+      iscsit_close_session() has no effect
+
+  * [ICL] TC port in legacy/static mode can't be detected due TCCOLD
+    (LP: #1868936)
+    - SAUCE: drm/i915: Align power domain names with port names
+    - SAUCE: drm/i915/display: Move out code to return the digital_port of the aux
+      ch
+    - SAUCE: drm/i915/display: Add intel_legacy_aux_to_power_domain()
+    - SAUCE: drm/i915/display: Split hsw_power_well_enable() into two
+    - SAUCE: drm/i915/tc/icl: Implement TC cold sequences
+    - SAUCE: drm/i915/tc: Skip ref held check for TC legacy aux power wells
+    - SAUCE: drm/i915/tc/tgl: Implement TC cold sequences
+    - SAUCE: drm/i915/tc: Catch TC users accessing FIA registers without enable
+      aux
+    - SAUCE: drm/i915/tc: Do not warn when aux power well of static TC ports
+      timeout
+
+  * alsa/sof: external mic can't be deteced on Lenovo and HP laptops
+    (LP: #1872569)
+    - SAUCE: ASoC: intel/skl/hda - set autosuspend timeout for hda codecs
+
+  * amdgpu kernel errors in Linux 5.4 (LP: #1871248)
+    - drm/amd/display: Stop if retimer is not available
+
+  * Focal update: v5.4.34 upstream stable release (LP: #1874111)
+    - amd-xgbe: Use __napi_schedule() in BH context
+    - hsr: check protocol version in hsr_newlink()
+    - l2tp: Allow management of tunnels and session in user namespace
+    - net: dsa: mt7530: fix tagged frames pass-through in VLAN-unaware mode
+    - net: ipv4: devinet: Fix crash when add/del multicast IP with autojoin
+    - net: ipv6: do not consider routes via gateways for anycast address check
+    - net: phy: micrel: use genphy_read_status for KSZ9131
+    - net: qrtr: send msgs from local of same id as broadcast
+    - net: revert default NAPI poll timeout to 2 jiffies
+    - net: tun: record RX queue in skb before do_xdp_generic()
+    - net: dsa: mt7530: move mt7623 settings out off the mt7530
+    - net: ethernet: mediatek: move mt7623 settings out off the mt7530
+    - net/mlx5: Fix frequent ioread PCI access during recovery
+    - net/mlx5e: Add missing release firmware call
+    - net/mlx5e: Fix nest_level for vlan pop action
+    - net/mlx5e: Fix pfnum in devlink port attribute
+    - net: stmmac: dwmac-sunxi: Provide TX and RX fifo sizes
+    - ovl: fix value of i_ino for lower hardlink corner case
+    - scsi: ufs: Fix ufshcd_hold() caused scheduling while atomic
+    - platform/chrome: cros_ec_rpmsg: Fix race with host event
+    - jbd2: improve comments about freeing data buffers whose page mapping is NULL
+    - acpi/nfit: improve bounds checking for 'func'
+    - perf report: Fix no branch type statistics report issue
+    - pwm: pca9685: Fix PWM/GPIO inter-operation
+    - ext4: fix incorrect group count in ext4_fill_super error message
+    - ext4: fix incorrect inodes per group in error message
+    - clk: at91: sam9x60: fix usb clock parents
+    - clk: at91: usb: use proper usbs_mask
+    - ARM: dts: imx7-colibri: fix muxing of usbc_det pin
+    - arm64: dts: librem5-devkit: add a vbus supply to usb0
+    - usb: dwc3: gadget: Don't clear flags before transfer ended
+    - ASoC: Intel: mrfld: fix incorrect check on p->sink
+    - ASoC: Intel: mrfld: return error codes when an error occurs
+    - ALSA: hda/realtek - Enable the headset mic on Asus FX505DT
+    - ALSA: usb-audio: Filter error from connector kctl ops, too
+    - ALSA: usb-audio: Don't override ignore_ctl_error value from the map
+    - ALSA: usb-audio: Don't create jack controls for PCM terminals
+    - ALSA: usb-audio: Check mapping at creating connector controls, too
+    - arm64: vdso: don't free unallocated pages
+    - keys: Fix proc_keys_next to increase position index
+    - tracing: Fix the race between registering 'snapshot' event trigger and
+      triggering 'snapshot' operation
+    - btrfs: check commit root generation in should_ignore_root
+    - nl80211: fix NL80211_ATTR_FTM_RESPONDER policy
+    - mac80211: fix race in ieee80211_register_hw()
+    - mac80211_hwsim: Use kstrndup() in place of kasprintf()
+    - net/mlx5e: Encapsulate updating netdev queues into a function
+    - net/mlx5e: Rename hw_modify to preactivate
+    - net/mlx5e: Use preactivate hook to set the indirection table
+    - drm/amd/powerplay: force the trim of the mclk dpm_levels if OD is enabled
+    - drm/amdgpu: fix the hw hang during perform system reboot and reset
+    - i2c: designware: platdrv: Remove DPM_FLAG_SMART_SUSPEND flag on BYT and CHT
+    - ext4: do not zeroout extents beyond i_disksize
+    - irqchip/ti-sci-inta: Fix processing of masked irqs
+    - x86/resctrl: Preserve CDP enable over CPU hotplug
+    - x86/resctrl: Fix invalid attempt at removing the default resource group
+    - scsi: target: remove boilerplate code
+    - scsi: target: fix hang when multiple threads try to destroy the same iscsi
+      session
+    - x86/microcode/AMD: Increase microcode PATCH_MAX_SIZE
+    - Linux 5.4.34
+
+  * Focal update: v5.4.33 upstream stable release (LP: #1873481)
+    - ARM: dts: sun8i-a83t-tbs-a711: HM5065 doesn't like such a high voltage
+    - bus: sunxi-rsb: Return correct data when mixing 16-bit and 8-bit reads
+    - ARM: dts: Fix dm814x Ethernet by changing to use rgmii-id mode
+    - bpf: Fix deadlock with rq_lock in bpf_send_signal()
+    - iwlwifi: mvm: Fix rate scale NSS configuration
+    - Input: tm2-touchkey - add support for Coreriver TC360 variant
+    - soc: fsl: dpio: register dpio irq handlers after dpio create
+    - rxrpc: Abstract out the calculation of whether there's Tx space
+    - rxrpc: Fix call interruptibility handling
+    - net: stmmac: platform: Fix misleading interrupt error msg
+    - net: vxge: fix wrong __VA_ARGS__ usage
+    - hinic: fix a bug of waitting for IO stopped
+    - hinic: fix the bug of clearing event queue
+    - hinic: fix out-of-order excution in arm cpu
+    - hinic: fix wrong para of wait_for_completion_timeout
+    - hinic: fix wrong value of MIN_SKB_LEN
+    - selftests/net: add definition for SOL_DCCP to fix compilation errors for old
+      libc
+    - cxgb4/ptp: pass the sign of offset delta in FW CMD
+    - drm/scheduler: fix rare NULL ptr race
+    - cfg80211: Do not warn on same channel at the end of CSA
+    - qlcnic: Fix bad kzalloc null test
+    - i2c: st: fix missing struct parameter description
+    - i2c: pca-platform: Use platform_irq_get_optional
+    - media: rc: add keymap for Videostrong KII Pro
+    - cpufreq: imx6q: Fixes unwanted cpu overclocking on i.MX6ULL
+    - staging: wilc1000: avoid double unlocking of 'wilc->hif_cs' mutex
+    - media: venus: hfi_parser: Ignore HEVC encoding for V1
+    - firmware: arm_sdei: fix double-lock on hibernate with shared events
+    - null_blk: Fix the null_add_dev() error path
+    - null_blk: Handle null_add_dev() failures properly
+    - null_blk: fix spurious IO errors after failed past-wp access
+    - media: imx: imx7_mipi_csis: Power off the source when stopping streaming
+    - media: imx: imx7-media-csi: Fix video field handling
+    - xhci: bail out early if driver can't accress host in resume
+    - x86: Don't let pgprot_modify() change the page encryption bit
+    - dma-mapping: Fix dma_pgprot() for unencrypted coherent pages
+    - block: keep bdi->io_pages in sync with max_sectors_kb for stacked devices
+    - debugfs: Check module state before warning in {full/open}_proxy_open()
+    - irqchip/versatile-fpga: Handle chained IRQs properly
+    - time/sched_clock: Expire timer in hardirq context
+    - media: allegro: fix type of gop_length in channel_create message
+    - sched: Avoid scale real weight down to zero
+    - selftests/x86/ptrace_syscall_32: Fix no-vDSO segfault
+    - PCI/switchtec: Fix init_completion race condition with poll_wait()
+    - block, bfq: move forward the getting of an extra ref in bfq_bfqq_move
+    - media: i2c: video-i2c: fix build errors due to 'imply hwmon'
+    - libata: Remove extra scsi_host_put() in ata_scsi_add_hosts()
+    - pstore/platform: fix potential mem leak if pstore_init_fs failed
+    - gfs2: Do log_flush in gfs2_ail_empty_gl even if ail list is empty
+    - gfs2: Don't demote a glock until its revokes are written
+    - cpufreq: imx6q: fix error handling
+    - x86/boot: Use unsigned comparison for addresses
+    - efi/x86: Ignore the memory attributes table on i386
+    - genirq/irqdomain: Check pointer in irq_domain_alloc_irqs_hierarchy()
+    - block: Fix use-after-free issue accessing struct io_cq
+    - media: i2c: ov5695: Fix power on and off sequences
+    - usb: dwc3: core: add support for disabling SS instances in park mode
+    - irqchip/gic-v4: Provide irq_retrigger to avoid circular locking dependency
+    - md: check arrays is suspended in mddev_detach before call quiesce operations
+    - firmware: fix a double abort case with fw_load_sysfs_fallback
+    - spi: spi-fsl-dspi: Replace interruptible wait queue with a simple completion
+    - locking/lockdep: Avoid recursion in lockdep_count_{for,back}ward_deps()
+    - block, bfq: fix use-after-free in bfq_idle_slice_timer_body
+    - btrfs: qgroup: ensure qgroup_rescan_running is only set when the worker is
+      at least queued
+    - btrfs: remove a BUG_ON() from merge_reloc_roots()
+    - btrfs: restart relocate_tree_blocks properly
+    - btrfs: track reloc roots based on their commit root bytenr
+    - ASoC: fix regwmask
+    - ASoC: dapm: connect virtual mux with default value
+    - ASoC: dpcm: allow start or stop during pause for backend
+    - ASoC: topology: use name_prefix for new kcontrol
+    - usb: gadget: f_fs: Fix use after free issue as part of queue failure
+    - usb: gadget: composite: Inform controller driver of self-powered
+    - ALSA: usb-audio: Add mixer workaround for TRX40 and co
+    - ALSA: hda: Add driver blacklist
+    - ALSA: hda: Fix potential access overflow in beep helper
+    - ALSA: ice1724: Fix invalid access for enumerated ctl items
+    - ALSA: pcm: oss: Fix regression by buffer overflow fix
+    - ALSA: hda/realtek - a fake key event is triggered by running shutup
+    - ALSA: doc: Document PC Beep Hidden Register on Realtek ALC256
+    - ALSA: hda/realtek - Set principled PC Beep configuration for ALC256
+    - ALSA: hda/realtek - Remove now-unnecessary XPS 13 headphone noise fixups
+    - ALSA: hda/realtek - Add quirk for Lenovo Carbon X1 8th gen
+    - ALSA: hda/realtek - Add quirk for MSI GL63
+    - media: venus: firmware: Ignore secure call error on first resume
+    - media: hantro: Read be32 words starting at every fourth byte
+    - media: ti-vpe: cal: fix disable_irqs to only the intended target
+    - media: ti-vpe: cal: fix a kernel oops when unloading module
+    - seccomp: Add missing compat_ioctl for notify
+    - acpi/x86: ignore unspecified bit positions in the ACPI global lock field
+    - ACPICA: Allow acpi_any_gpe_status_set() to skip one GPE
+    - ACPI: PM: s2idle: Refine active GPEs check
+    - thermal: devfreq_cooling: inline all stubs for CONFIG_DEVFREQ_THERMAL=n
+    - nvmet-tcp: fix maxh2cdata icresp parameter
+    - efi/x86: Add TPM related EFI tables to unencrypted mapping checks
+    - PCI: pciehp: Fix indefinite wait on sysfs requests
+    - PCI/ASPM: Clear the correct bits when enabling L1 substates
+    - PCI: Add boot interrupt quirk mechanism for Xeon chipsets
+    - PCI: qcom: Fix the fixup of PCI_VENDOR_ID_QCOM
+    - PCI: endpoint: Fix for concurrent memory allocation in OB address region
+    - sched/fair: Fix enqueue_task_fair warning
+    - tpm: Don't make log failures fatal
+    - tpm: tpm1_bios_measurements_next should increase position index
+    - tpm: tpm2_bios_measurements_next should increase position index
+    - cpu/hotplug: Ignore pm_wakeup_pending() for disable_nonboot_cpus()
+    - genirq/debugfs: Add missing sanity checks to interrupt injection
+    - irqchip/versatile-fpga: Apply clear-mask earlier
+    - io_uring: remove bogus RLIMIT_NOFILE check in file registration
+    - pstore: pstore_ftrace_seq_next should increase position index
+    - MIPS/tlbex: Fix LDDIR usage in setup_pw() for Loongson-3
+    - MIPS: OCTEON: irq: Fix potential NULL pointer dereference
+    - PM / Domains: Allow no domain-idle-states DT property in genpd when parsing
+    - PM: sleep: wakeup: Skip wakeup_source_sysfs_remove() if device is not there
+    - ath9k: Handle txpower changes even when TPC is disabled
+    - signal: Extend exec_id to 64bits
+    - x86/tsc_msr: Use named struct initializers
+    - x86/tsc_msr: Fix MSR_FSB_FREQ mask for Cherry Trail devices
+    - x86/tsc_msr: Make MSR derived TSC frequency more accurate
+    - x86/entry/32: Add missing ASM_CLAC to general_protection entry
+    - platform/x86: asus-wmi: Support laptops where the first battery is named
+      BATT
+    - KVM: nVMX: Properly handle userspace interrupt window request
+    - KVM: s390: vsie: Fix region 1 ASCE sanity shadow address checks
+    - KVM: s390: vsie: Fix delivery of addressing exceptions
+    - KVM: x86: Allocate new rmap and large page tracking when moving memslot
+    - KVM: VMX: Always VMCLEAR in-use VMCSes during crash with kexec support
+    - KVM: x86: Gracefully handle __vmalloc() failure during VM allocation
+    - KVM: VMX: Add a trampoline to fix VMREAD error handling
+    - KVM: VMX: fix crash cleanup when KVM wasn't used
+    - smb3: fix performance regression with setting mtime
+    - CIFS: Fix bug which the return value by asynchronous read is error
+    - mtd: spinand: Stop using spinand->oobbuf for buffering bad block markers
+    - mtd: spinand: Do not erase the block before writing a bad block marker
+    - btrfs: Don't submit any btree write bio if the fs has errors
+    - Btrfs: fix crash during unmount due to race with delayed inode workers
+    - btrfs: reloc: clean dirty subvols if we fail to start a transaction
+    - btrfs: set update the uuid generation as soon as possible
+    - btrfs: drop block from cache on error in relocation
+    - btrfs: fix missing file extent item for hole after ranged fsync
+    - btrfs: unset reloc control if we fail to recover
+    - btrfs: fix missing semaphore unlock in btrfs_sync_file
+    - btrfs: use nofs allocations for running delayed items
+    - remoteproc: qcom_q6v5_mss: Don't reassign mpss region on shutdown
+    - remoteproc: qcom_q6v5_mss: Reload the mba region on coredump
+    - remoteproc: Fix NULL pointer dereference in rproc_virtio_notify
+    - crypto: rng - Fix a refcounting bug in crypto_rng_reset()
+    - crypto: mxs-dcp - fix scatterlist linearization for hash
+    - erofs: correct the remaining shrink objects
+    - io_uring: honor original task RLIMIT_FSIZE
+    - mmc: sdhci-of-esdhc: fix esdhc_reset() for different controller versions
+    - powerpc/pseries: Drop pointless static qualifier in vpa_debugfs_init()
+    - tools: gpio: Fix out-of-tree build regression
+    - net: qualcomm: rmnet: Allow configuration updates to existing devices
+    - arm64: dts: allwinner: h6: Fix PMU compatible
+    - sched/core: Remove duplicate assignment in sched_tick_remote()
+    - arm64: dts: allwinner: h5: Fix PMU compatible
+    - mm, memcg: do not high throttle allocators based on wraparound
+    - dm writecache: add cond_resched to avoid CPU hangs
+    - dm integrity: fix a crash with unusually large tag size
+    - dm verity fec: fix memory leak in verity_fec_dtr
+    - dm clone: Add overflow check for number of regions
+    - dm clone metadata: Fix return type of dm_clone_nr_of_hydrated_regions()
+    - XArray: Fix xas_pause for large multi-index entries
+    - xarray: Fix early termination of xas_for_each_marked
+    - crypto: caam/qi2 - fix chacha20 data size error
+    - crypto: caam - update xts sector size for large input length
+    - crypto: ccree - protect against empty or NULL scatterlists
+    - crypto: ccree - only try to map auth tag if needed
+    - crypto: ccree - dec auth tag size from cryptlen map
+    - scsi: zfcp: fix missing erp_lock in port recovery trigger for point-to-point
+    - scsi: ufs: fix Auto-Hibern8 error detection
+    - ARM: dts: exynos: Fix polarity of the LCD SPI bus on UniversalC210 board
+    - arm64: dts: ti: k3-am65: Add clocks to dwc3 nodes
+    - arm64: armv8_deprecated: Fix undef_hook mask for thumb setend
+    - selftests: vm: drop dependencies on page flags from mlock2 tests
+    - selftests/vm: fix map_hugetlb length used for testing read and write
+    - selftests/powerpc: Add tlbie_test in .gitignore
+    - vfio: platform: Switch to platform_get_irq_optional()
+    - drm/i915/gem: Flush all the reloc_gpu batch
+    - drm/etnaviv: rework perfmon query infrastructure
+    - drm: Remove PageReserved manipulation from drm_pci_alloc
+    - drm/amdgpu/powerplay: using the FCLK DPM table to set the MCLK
+    - drm/amdgpu: unify fw_write_wait for new gfx9 asics
+    - powerpc/pseries: Avoid NULL pointer dereference when drmem is unavailable
+    - nfsd: fsnotify on rmdir under nfsd/clients/
+    - NFS: Fix use-after-free issues in nfs_pageio_add_request()
+    - NFS: Fix a page leak in nfs_destroy_unlinked_subrequests()
+    - ext4: fix a data race at inode->i_blocks
+    - fs/filesystems.c: downgrade user-reachable WARN_ONCE() to pr_warn_once()
+    - ocfs2: no need try to truncate file beyond i_size
+    - perf tools: Support Python 3.8+ in Makefile
+    - s390/diag: fix display of diagnose call statistics
+    - Input: i8042 - add Acer Aspire 5738z to nomux list
+    - ftrace/kprobe: Show the maxactive number on kprobe_events
+    - clk: ingenic/jz4770: Exit with error if CGU init failed
+    - clk: ingenic/TCU: Fix round_rate returning error
+    - kmod: make request_module() return an error when autoloading is disabled
+    - cpufreq: powernv: Fix use-after-free
+    - hfsplus: fix crash and filesystem corruption when deleting files
+    - ipmi: fix hung processes in __get_guid()
+    - xen/blkfront: fix memory allocation flags in blkfront_setup_indirect()
+    - powerpc/64/tm: Don't let userspace set regs->trap via sigreturn
+    - powerpc/fsl_booke: Avoid creating duplicate tlb1 entry
+    - powerpc/hash64/devmap: Use H_PAGE_THP_HUGE when setting up huge devmap PTE
+      entries
+    - powerpc/xive: Use XIVE_BAD_IRQ instead of zero to catch non configured IPIs
+    - powerpc/64: Setup a paca before parsing device tree etc.
+    - powerpc/xive: Fix xmon support on the PowerNV platform
+    - powerpc/kprobes: Ignore traps that happened in real mode
+    - powerpc/64: Prevent stack protection in early boot
+    - scsi: mpt3sas: Fix kernel panic observed on soft HBA unplug
+    - powerpc: Make setjmp/longjmp signature standard
+    - arm64: Always force a branch protection mode when the compiler has one
+    - dm zoned: remove duplicate nr_rnd_zones increase in dmz_init_zone()
+    - dm clone: replace spin_lock_irqsave with spin_lock_irq
+    - dm clone: Fix handling of partial region discards
+    - dm clone: Add missing casts to prevent overflows and data corruption
+    - Revert "drm/dp_mst: Remove VCPI while disabling topology mgr"
+    - drm/dp_mst: Fix clearing payload state on topology disable
+    - drm/amdgpu: fix gfx hang during suspend with video playback (v2)
+    - drm/i915/icl+: Don't enable DDI IO power on a TypeC port in TBT mode
+    - powerpc/kasan: Fix kasan_remap_early_shadow_ro()
+    - mmc: sdhci: Convert sdhci_set_timeout_irq() to non-static
+    - mmc: sdhci: Refactor sdhci_set_timeout()
+    - bpf: Fix tnum constraints for 32-bit comparisons
+    - mfd: dln2: Fix sanity checking for endpoints
+    - efi/x86: Fix the deletion of variables in mixed mode
+    - ASoC: stm32: sai: Add missing cleanup
+    - Linux 5.4.33
+    - SUNRPC: fix krb5p mount to provide large enough buffer in rq_rcvsize
+
+  * Panic on suspend/resume Kernel panic - not syncing: stack-protector: Kernel
+    stack is corrupted in: sata_pmp_eh_recover+0xa2b/0xa40 (LP: #1821434) //
+    Focal update: v5.4.33 upstream stable release (LP: #1873481)
+    - libata: Return correct status in sata_pmp_eh_recover_pm() when
+      ATA_DFLAG_DETACH is set
+
+  * Focal update: v5.4.32 upstream stable release (LP: #1873292)
+    - cxgb4: fix MPS index overwrite when setting MAC address
+    - ipv6: don't auto-add link-local address to lag ports
+    - net: dsa: bcm_sf2: Do not register slave MDIO bus with OF
+    - net: dsa: bcm_sf2: Ensure correct sub-node is parsed
+    - net: dsa: mt7530: fix null pointer dereferencing in port5 setup
+    - net: phy: micrel: kszphy_resume(): add delay after genphy_resume() before
+      accessing PHY registers
+    - net_sched: add a temporary refcnt for struct tcindex_data
+    - net_sched: fix a missing refcnt in tcindex_init()
+    - net: stmmac: dwmac1000: fix out-of-bounds mac address reg setting
+    - tun: Don't put_page() for all negative return values from XDP program
+    - mlxsw: spectrum_flower: Do not stop at FLOW_ACTION_VLAN_MANGLE
+    - r8169: change back SG and TSO to be disabled by default
+    - s390: prevent leaking kernel address in BEAR
+    - random: always use batched entropy for get_random_u{32,64}
+    - usb: dwc3: gadget: Wrap around when skip TRBs
+    - uapi: rename ext2_swab() to swab() and share globally in swab.h
+    - slub: improve bit diffusion for freelist ptr obfuscation
+    - tools/accounting/getdelays.c: fix netlink attribute length
+    - hwrng: imx-rngc - fix an error path
+    - ACPI: PM: Add acpi_[un]register_wakeup_handler()
+    - platform/x86: intel_int0002_vgpio: Use acpi_register_wakeup_handler()
+    - ASoC: jz4740-i2s: Fix divider written at incorrect offset in register
+    - IB/hfi1: Call kobject_put() when kobject_init_and_add() fails
+    - IB/hfi1: Fix memory leaks in sysfs registration and unregistration
+    - IB/mlx5: Replace tunnel mpls capability bits for tunnel_offloads
+    - ARM: imx: Enable ARM_ERRATA_814220 for i.MX6UL and i.MX7D
+    - ARM: imx: only select ARM_ERRATA_814220 for ARMv7-A
+    - ceph: remove the extra slashes in the server path
+    - ceph: canonicalize server path in place
+    - include/uapi/linux/swab.h: fix userspace breakage, use __BITS_PER_LONG for
+      swap
+    - RDMA/ucma: Put a lock around every call to the rdma_cm layer
+    - RDMA/cma: Teach lockdep about the order of rtnl and lock
+    - RDMA/siw: Fix passive connection establishment
+    - Bluetooth: RFCOMM: fix ODEBUG bug in rfcomm_dev_ioctl
+    - RDMA/cm: Update num_paths in cma_resolve_iboe_route error flow
+    - blk-mq: Keep set->nr_hw_queues and set->map[].nr_queues in sync
+    - fbcon: fix null-ptr-deref in fbcon_switch
+    - iommu/vt-d: Allow devices with RMRRs to use identity domain
+    - Linux 5.4.32
+
+  * Focal update: v5.4.31 upstream stable release (LP: #1871651)
+    - nvme-rdma: Avoid double freeing of async event data
+    - kconfig: introduce m32-flag and m64-flag
+    - drm/amd/display: Add link_rate quirk for Apple 15" MBP 2017
+    - drm/bochs: downgrade pci_request_region failure from error to warning
+    - initramfs: restore default compression behavior
+    - drm/amdgpu: fix typo for vcn1 idle check
+    - [Packaging] add libcap-dev dependency
+    - tools/power turbostat: Fix gcc build warnings
+    - tools/power turbostat: Fix missing SYS_LPI counter on some Chromebooks
+    - tools/power turbostat: Fix 32-bit capabilities warning
+    - net/mlx5e: kTLS, Fix TCP seq off-by-1 issue in TX resync flow
+    - XArray: Fix xa_find_next for large multi-index entries
+    - padata: fix uninitialized return value in padata_replace()
+    - brcmfmac: abort and release host after error
+    - misc: rtsx: set correct pcr_ops for rts522A
+    - misc: pci_endpoint_test: Fix to support > 10 pci-endpoint-test devices
+    - misc: pci_endpoint_test: Avoid using module parameter to determine irqtype
+    - PCI: sysfs: Revert "rescan" file renames
+    - coresight: do not use the BIT() macro in the UAPI header
+    - mei: me: add cedar fork device ids
+    - nvmem: check for NULL reg_read and reg_write before dereferencing
+    - extcon: axp288: Add wakeup support
+    - power: supply: axp288_charger: Add special handling for HP Pavilion x2 10
+    - Revert "dm: always call blk_queue_split() in dm_process_bio()"
+    - ALSA: hda/ca0132 - Add Recon3Di quirk to handle integrated sound on EVGA X99
+      Classified motherboard
+    - soc: mediatek: knows_txdone needs to be set in Mediatek CMDQ helper
+    - net/mlx5e: kTLS, Fix wrong value in record tracker enum
+    - iwlwifi: consider HE capability when setting LDPC
+    - iwlwifi: yoyo: don't add TLV offset when reading FIFOs
+    - iwlwifi: dbg: don't abort if sending DBGC_SUSPEND_RESUME fails
+    - rxrpc: Fix sendmsg(MSG_WAITALL) handling
+    - IB/hfi1: Ensure pq is not left on waitlist
+    - tcp: fix TFO SYNACK undo to avoid double-timestamp-undo
+    - watchdog: iTCO_wdt: Export vendorsupport
+    - watchdog: iTCO_wdt: Make ICH_RES_IO_SMI optional
+    - i2c: i801: Do not add ICH_RES_IO_SMI for the iTCO_wdt device
+    - net: Fix Tx hash bound checking
+    - padata: always acquire cpu_hotplug_lock before pinst->lock
+    - mm: mempolicy: require at least one nodeid for MPOL_PREFERRED
+    - Linux 5.4.31
+
+  * Add hw timestamps to received skbs in peak_canfd (LP: #1874124)
+    - can: peak_canfd: provide hw timestamps in rx skbs
+
+  * kselftest: seccomp kill_after_ptrace() timeout (LP: #1872047)
+    - SAUCE: kselftest/runner: allow to properly deliver signals to tests
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Tue, 05 May 2020 12:36:10 +0200
+
+linux (5.4.0-29.33) focal; urgency=medium
+
+  * focal/linux: 5.4.0-29.33 -proposed tracker (LP: #1875858)
+
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+
+  * Add signed modules for the 435 NVIDIA driver (LP: #1875888)
+    - [Packaging] NVIDIA -- add signed modules for the 435 NVIDIA driver
+
+  * built-using constraints preventing uploads (LP: #1875601)
+    - temporarily drop Built-Using data
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Wed, 29 Apr 2020 15:34:16 +0200
+
+linux (5.4.0-28.32) focal; urgency=medium
+
+  * CVE-2020-11884
+    - SAUCE: s390/mm: fix page table upgrade vs 2ndary address mode accesses
+
+ -- Thadeu Lima de Souza Cascardo <cascardo@canonical.com>  Wed, 22 Apr 2020 11:08:40 -0300
+
+linux (5.4.0-26.30) focal; urgency=medium
+
+  * focal/linux: 5.4.0-26.30 -proposed tracker (LP: #1873882)
+
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+
+  * swap storms kills interactive use (LP: #1861359)
+    - SAUCE: drm/i915: prevent direct writeback from the shrinker
+
+  * 5.4.0-24.28 does not seem to apply rtprio, whereas -21 does. (LP: #1873315)
+    - [Config] lowlatency: turn off RT_GROUP_SCHED
+
+  * [RTL810xE] No ethernet connection (LP: #1871182)
+    - net: phy: realtek: fix handling of RTL8105e-integrated PHY
+
+ -- Andrea Righi <andrea.righi@canonical.com>  Mon, 20 Apr 2020 18:33:49 +0200
+
+linux (5.4.0-25.29) focal; urgency=medium
+
+  * focal/linux: 5.4.0-25.29 -proposed tracker (LP: #1873459)
+
+  * [TGL] VMD support in TGL (LP: #1855954)
+    - PCI: vmd: Add bus 224-255 restriction decode
+    - PCI: vmd: Add device id for VMD device 8086:9A0B
+
+  * Can not see the storage with Intel RAID On mode enabled on Intel Comet Lake
+    (LP: #1871812)
+    - ahci: Add Intel Comet Lake PCH RAID PCI ID
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Fri, 17 Apr 2020 08:41:16 -0500
+
+linux (5.4.0-24.28) focal; urgency=medium
+
+  * focal/linux: 5.4.0-24.28 -proposed tracker (LP: #1871939)
+
+  * getitimer returns it_value=0 erroneously (LP: #1349028)
+    - [Config] CONTEXT_TRACKING_FORCE policy should be unset
+
+  * 12d1:1038 Dual-Role OTG device on non-HNP port - unable to enumerate USB
+    device on port 1 (LP: #1047527)
+    - [Config] USB_OTG_FSM policy not needed
+
+  * Add DCPD backlight support for HP CML system (LP: #1871589)
+    - SAUCE: drm/i915: Force DPCD backlight mode for HP CML 2020 system
+
+  * Backlight brightness cannot be adjusted using keys (LP: #1860303)
+    - SAUCE drm/i915: Force DPCD backlight mode for HP Spectre x360 Convertible
+      13t-aw100
+
+  * CVE-2020-11494
+    - slcan: Don't transmit uninitialized stack data in padding
+
+  * Ubuntu Kernel Support for OpenPOWER NV Secure & Trusted Boot (LP: #1866909)
+    - powerpc: Detect the secure boot mode of the system
+    - powerpc/ima: Add support to initialize ima policy rules
+    - powerpc: Detect the trusted boot state of the system
+    - powerpc/ima: Define trusted boot policy
+    - ima: Make process_buffer_measurement() generic
+    - certs: Add wrapper function to check blacklisted binary hash
+    - ima: Check against blacklisted hashes for files with modsig
+    - powerpc/ima: Update ima arch policy to check for blacklist
+    - powerpc/ima: Indicate kernel modules appended signatures are enforced
+    - powerpc/powernv: Add OPAL API interface to access secure variable
+    - powerpc: expose secure variables to userspace via sysfs
+    - x86/efi: move common keyring handler functions to new file
+    - powerpc: Load firmware trusted keys/hashes into kernel keyring
+    - x86/efi: remove unused variables
+
+  * [roce-0227]sync mainline kernel 5.6rc3  roce patchset into ubuntu HWE kernel
+    branch (LP: #1864950)
+    - RDMA/hns: Cleanups of magic numbers
+    - RDMA/hns: Optimize eqe buffer allocation flow
+    - RDMA/hns: Add the workqueue framework for flush cqe handler
+    - RDMA/hns: Delayed flush cqe process with workqueue
+    - RDMA/hns: fix spelling mistake: "attatch" -> "attach"
+    - RDMA/hns: Initialize all fields of doorbells to zero
+    - RDMA/hns: Treat revision HIP08_A as a special case
+    - RDMA/hns: Use flush framework for the case in aeq
+    - RDMA/hns: Stop doorbell update while qp state error
+    - RDMA/hns: Optimize qp destroy flow
+    - RDMA/hns: Optimize qp context create and destroy flow
+    - RDMA/hns: Optimize qp number assign flow
+    - RDMA/hns: Optimize qp buffer allocation flow
+    - RDMA/hns: Optimize qp param setup flow
+    - RDMA/hns: Optimize kernel qp wrid allocation flow
+    - RDMA/hns: Optimize qp doorbell allocation flow
+    - RDMA/hns: Check if depth of qp is 0 before configure
+
+  * [hns3-0316]sync mainline kernel 5.6rc4  hns3 patchset into ubuntu HWE kernel
+    branch (LP: #1867586)
+    - net: hns3: modify an unsuitable print when setting unknown duplex to fibre
+    - net: hns3: add enabled TC numbers and DWRR weight info in debugfs
+    - net: hns3: add support for dump MAC ID and loopback status in debugfs
+    - net: hns3: add missing help info for QS shaper in debugfs
+    - net: hns3: fix some mixed type assignment
+    - net: hns3: rename macro HCLGE_MAX_NCL_CONFIG_LENGTH
+    - net: hns3: remove an unnecessary resetting check in
+      hclge_handle_hw_ras_error()
+    - net: hns3: delete some reduandant code
+    - net: hns3: add a check before PF inform VF to reset
+    - net: hns3: print out status register when VF receives unknown source
+      interrupt
+    - net: hns3: print out command code when dump fails in debugfs
+    - net: hns3: synchronize some print relating to reset issue
+    - net: hns3: delete unnecessary logs after kzalloc fails
+
+  * [SRU][F/U/OEM-5.6] UBUNTU: SAUCE: Fix amdgpu hang during acpi event
+    (LP: #1871316)
+    - SAUCE: drm/amdgpu: Fix oops when pp_funcs is unset in ACPI event
+
+  * alsa: make the dmic detection align to the mainline kernel-5.6
+    (LP: #1871284)
+    - ALSA: hda: add Intel DSP configuration / probe code
+    - ALSA: hda: fix intel DSP config
+    - ALSA: hda: Allow non-Intel device probe gracefully
+    - ALSA: hda: More constifications
+    - ALSA: hda: Rename back to dmic_detect option
+    - [Config] SND_INTEL_DSP_CONFIG=m
+
+  * add_key05 from ubuntu_ltp_syscalls failed (LP: #1869644)
+    - KEYS: reaching the keys quotas correctly
+
+  * Fix authentication fail on Realtek WiFi 8723de (LP: #1871300)
+    - SAUCE: rtw88: No retry and report for auth and assoc
+    - SAUCE: rtw88: fix rate for a while after being connected
+    - SAUCE: rtw88: Move driver IQK to set channel before association for 11N chip
+
+  * Add Mute LED support for an HP laptop (LP: #1871090)
+    - ALSA: hda/realtek: Enable mute LED on an HP system
+
+  * dscr_sysfs_test / futex_bench / tm-unavailable  in powerpc from
+    ubuntu_kernel_selftests timeout on PowerPC nodes with B-5.3 (LP: #1864642)
+    - Revert "UBUNTU: SAUCE: selftests/powerpc -- Disable timeout for benchmark
+      and tm tests"
+    - selftests/powerpc: Turn off timeout setting for benchmarks, dscr, signal, tm
+
+  * Update 20.0.4 NVMe Core, NVMe FC Transport and nvme-cli for Broadcom Emulex
+    lpfc driver 12.6.0.x dependencies (LP: #1856340)
+    - nvme-fc: Sync nvme-fc header to FC-NVME-2
+    - nvme-fc and nvmet-fc: sync with FC-NVME-2 header changes
+    - nvme-fc: Set new cmd set indicator in nvme-fc cmnd iu
+    - nvme-fc: clarify error messages
+    - nvme-fc: ensure association_id is cleared regardless of a Disconnect LS
+    - nvme: resync include/linux/nvme.h with nvmecli
+    - nvme: Fix parsing of ANA log page
+
+  * Update Broadcom Emulex lpfc driver in 5.4 to 12.6.0.x from 5.5
+    (LP: #1855303)
+    - scsi: lpfc: Fix pt2pt discovery on SLI3 HBAs
+    - scsi: lpfc: Fix premature re-enabling of interrupts in lpfc_sli_host_down
+    - scsi: lpfc: Fix miss of register read failure check
+    - scsi: lpfc: Fix NVME io abort failures causing hangs
+    - scsi: lpfc: Fix device recovery errors after PLOGI failures
+    - scsi: lpfc: Fix GPF on scsi command completion
+    - scsi: lpfc: Fix NVMe ABTS in response to receiving an ABTS
+    - scsi: lpfc: Fix coverity errors on NULL pointer checks
+    - scsi: lpfc: Fix host hang at boot or slow boot
+    - scsi: lpfc: Update async event logging
+    - scsi: lpfc: Complete removal of FCoE T10 PI support on SLI-4 adapters
+    - scsi: lpfc: cleanup: remove unused fcp_txcmlpq_cnt
+    - scsi: lpfc: Update lpfc version to 12.4.0.1
+    - scsi: lpfc: Make function lpfc_defer_pt2pt_acc static
+    - scsi: lpfc: fix lpfc_nvmet_mrq to be bound by hdw queue count
+    - scsi: lpfc: Fix reporting of read-only fw error errors
+    - scsi: lpfc: Fix lockdep errors in sli_ringtx_put
+    - scsi: lpfc: fix coverity error of dereference after null check
+    - scsi: lpfc: Slight fast-path performance optimizations
+    - scsi: lpfc: Remove lock contention target write path
+    - scsi: lpfc: Revise interrupt coalescing for missing scenarios
+    - scsi: lpfc: Make FW logging dynamically configurable
+    - scsi: lpfc: Add log macros to allow print by serverity or verbosity setting
+    - scsi: lpfc: Add FA-WWN Async Event reporting
+    - scsi: lpfc: Add FC-AL support to lpe32000 models
+    - scsi: lpfc: Add additional discovery log messages
+    - scsi: lpfc: Update lpfc version to 12.6.0.0
+    - scsi: lpfc: lpfc_attr: Fix Use plain integer as NULL pointer
+    - scsi: lpfc: lpfc_nvmet: Fix Use plain integer as NULL pointer
+    - scsi: lpfc: fix build error of lpfc_debugfs.c for vfree/vmalloc
+    - scsi: lpfc: fix spelling error in MAGIC_NUMER_xxx
+    - scsi: lpfc: Fix NULL check before mempool_destroy is not needed
+    - scsi: lpfc: Make lpfc_debugfs_ras_log_data static
+    - scsi: lpfc: Fix configuration of BB credit recovery in service parameters
+    - scsi: lpfc: Fix kernel crash at lpfc_nvme_info_show during remote port
+      bounce
+    - scsi: lpfc: Fix dynamic fw log enablement check
+    - scsi: lpfc: Sync with FC-NVMe-2 SLER change to require Conf with SLER
+    - scsi: lpfc: Clarify FAWNN error message
+    - scsi: lpfc: Add registration for CPU Offline/Online events
+    - scsi: lpfc: Change default IRQ model on AMD architectures
+    - scsi: lpfc: Add enablement of multiple adapter dumps
+    - scsi: lpfc: Update lpfc version to 12.6.0.1
+    - scsi: lpfc: Fix a kernel warning triggered by lpfc_sli4_enable_intr()
+    - scsi: lpfc: Fix lpfc_cpumask_of_node_init()
+    - scsi: lpfc: fix inlining of lpfc_sli4_cleanup_poll_list()
+    - scsi: lpfc: Initialize cpu_map for not present cpus
+    - scsi: lpfc: revise nvme max queues to be hdwq count
+    - scsi: lpfc: Update lpfc version to 12.6.0.2
+    - scsi: lpfc: size cpu map by last cpu id set
+    - scsi: lpfc: Fix incomplete NVME discovery when target
+    - scsi: lpfc: Fix missing check for CSF in Write Object Mbox Rsp
+    - scsi: lpfc: Fix Fabric hostname registration if system hostname changes
+    - scsi: lpfc: Fix ras_log via debugfs
+    - scsi: lpfc: Fix disablement of FC-AL on lpe35000 models
+    - scsi: lpfc: Fix unmap of dpp bars affecting next driver load
+    - scsi: lpfc: Fix MDS Latency Diagnostics Err-drop rates
+    - scsi: lpfc: Fix improper flag check for IO type
+    - scsi: lpfc: Update lpfc version to 12.6.0.3
+    - scsi: lpfc: Fix RQ buffer leakage when no IOCBs available
+    - scsi: lpfc: Fix lpfc_io_buf resource leak in lpfc_get_scsi_buf_s4 error path
+    - scsi: lpfc: Fix broken Credit Recovery after driver load
+    - scsi: lpfc: Fix registration of ELS type support in fdmi
+    - scsi: lpfc: Fix release of hwq to clear the eq relationship
+    - scsi: lpfc: Fix compiler warning on frame size
+    - scsi: lpfc: Fix coverity errors in fmdi attribute handling
+    - scsi: lpfc: Remove handler for obsolete ELS - Read Port Status (RPS)
+    - scsi: lpfc: Clean up hba max_lun_queue_depth checks
+    - scsi: lpfc: Update lpfc version to 12.6.0.4
+    - scsi: lpfc: Copyright updates for 12.6.0.4 patches
+    - scsi: fc: Update Descriptor definition and add RDF and Link Integrity FPINs
+    - scsi: lpfc: add RDF registration and Link Integrity FPIN logging
+
+  * lockdown on power (LP: #1855668) // Ubuntu Kernel Support for OpenPOWER NV
+    Secure & Trusted Boot (LP: #1866909)
+    - [Config] Enable configs for OpenPOWER NV Secure & Trusted Boot
+
+  * lockdown on power (LP: #1855668)
+    - SAUCE: (lockdown) powerpc: lock down kernel in secure boot mode
+
+  * Focal update: v5.4.30 upstream stable release (LP: #1870571)
+    - mac80211: Check port authorization in the ieee80211_tx_dequeue() case
+    - mac80211: fix authentication with iwlwifi/mvm
+    - serial: sprd: Fix a dereference warning
+    - vt: selection, introduce vc_is_sel
+    - vt: ioctl, switch VT_IS_IN_USE and VT_BUSY to inlines
+    - vt: switch vt_dont_switch to bool
+    - vt: vt_ioctl: remove unnecessary console allocation checks
+    - vt: vt_ioctl: fix VT_DISALLOCATE freeing in-use virtual console
+    - vt: vt_ioctl: fix use-after-free in vt_in_use()
+    - platform/x86: pmc_atom: Add Lex 2I385SW to critclk_systems DMI table
+    - bpf: Explicitly memset the bpf_attr structure
+    - bpf: Explicitly memset some bpf info structures declared on the stack
+    - gpiolib: acpi: Add quirk to ignore EC wakeups on HP x2 10 CHT + AXP288 model
+    - net: ks8851-ml: Fix IO operations, again
+    - clk: imx: Align imx sc clock msg structs to 4
+    - clk: imx: Align imx sc clock parent msg structs to 4
+    - clk: ti: am43xx: Fix clock parent for RTC clock
+    - libceph: fix alloc_msg_with_page_vector() memory leaks
+    - arm64: alternative: fix build with clang integrated assembler
+    - perf map: Fix off by one in strncpy() size argument
+    - ARM: dts: oxnas: Fix clear-mask property
+    - ARM: bcm2835-rpi-zero-w: Add missing pinctrl name
+    - ARM: dts: imx6: phycore-som: fix arm and soc minimum voltage
+    - ARM: dts: N900: fix onenand timings
+    - ARM: dts: sun8i: r40: Move AHCI device node based on address order
+    - arm64: dts: ls1043a-rdb: correct RGMII delay mode to rgmii-id
+    - arm64: dts: ls1046ardb: set RGMII interfaces to RGMII_ID mode
+    - Linux 5.4.30
+
+  * Miscellaneous Ubuntu changes
+    - [Config] CONFIG_RT_GROUP_SCHED=y
+    - SAUCE: powerpc/ima: require IMA module signatures only if MODULE_SIG is not
+      enabled
+    - SAUCE: Update aufs to 5.4.3 20200302
+    - SAUCE: drm/amdgpu: Remove missing firmware files from modinfo
+    - SAUCE: drm/i915: Fix ref->mutex deadlock in i915_active_wait()
+    - SAUCE: drm/i915: Synchronize active and retire callbacks
+    - SAUCE: apparmor: add a valid state flags check
+    - SAUCE: aapparmor: add consistency check between state and dfa diff encode
+      flags
+    - SAUCE: aapparmor: remove useless aafs_create_symlink
+    - SAUCE: aapparmor: fail unpack if profile mode is unknown
+    - SAUCE: apparmor: ensure that dfa state tables have entries
+    - SAUCE: apparmor: fix potential label refcnt leak in aa_change_profile
+    - SAUCE: security/apparmor/label.c: Clean code by removing redundant
+      instructions
+    - [Config] Remove PCIEASPM_DEBUG from annotations
+    - [Config] Remove HEADER_TEST from annotations
+    - SAUCE: selftests/seccomp: allow clock_nanosleep instead of nanosleep
+    - [Debian] Allow building linux-libc-dev from linux-riscv
+    - [Packaging] Remove riscv64 packaging from master kernel
+    - [Config] Remove CONFIG_SND_HDA_INTEL_DETECT_DMIC from annotations
+
+  * Miscellaneous upstream changes
+    - net/bpfilter: remove superfluous testing message
+    - apparmor: increase left match history buffer size
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Thu, 09 Apr 2020 16:49:54 -0500
+
+linux (5.4.0-23.27) focal; urgency=medium
+
+  * Miscellaneous Ubuntu changes
+    - [Packaging] Enable riscv64 build
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Sat, 04 Apr 2020 14:03:47 -0500
+
+linux (5.4.0-22.26) focal; urgency=medium
+
+  * focal/linux: 5.4.0-22.26 -proposed tracker (LP: #1870502)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update variants
+    - [Packaging] update helper scripts
+    - update dkms package versions
+
+  * [SFC-0316]sync mainline kernel 5.7rc1 SFC patchset into ubuntu HWE kernel
+    branch (LP: #1867588)
+    - spi: Allow SPI controller override device buswidth
+    - spi: HiSilicon v3xx: Properly set CMD_CONFIG for Dual/Quad modes
+    - spi: HiSilicon v3xx: Use DMI quirk to set controller buswidth override bits
+
+  * [hns3-0316]sync mainline kernel 5.6rc4  hns3 patchset into ubuntu HWE kernel
+    branch (LP: #1867586)
+    - net: hns3: fix VF VLAN table entries inconsistent issue
+    - net: hns3: fix RMW issue for VLAN filter switch
+    - net: hns3: clear port base VLAN when unload PF
+
+  * [sas-0316]sync mainline kernel 5.6rc1 roce patchset into ubuntu HWE kernel
+    branch (LP: #1867587)
+    - scsi: hisi_sas: use threaded irq to process CQ interrupts
+    - scsi: hisi_sas: replace spin_lock_irqsave/spin_unlock_restore with
+      spin_lock/spin_unlock
+    - scsi: hisi_sas: Replace magic number when handle channel interrupt
+    - scsi: hisi_sas: Modify the file permissions of trigger_dump to write only
+    - scsi: hisi_sas: Add prints for v3 hw interrupt converge and automatic
+      affinity
+    - scsi: hisi_sas: Rename hisi_sas_cq.pci_irq_mask
+
+  * Revert "nvme_fc: add module to ops template to allow module references"
+    (LP: #1869947)
+    - SAUCE: Revert "nvme_fc: add module to ops template to allow module
+      references"
+
+  * suspend only works once on ThinkPad X1 Carbon gen 7 (LP: #1865570)
+    - Revert "UBUNTU: SAUCE: e1000e: Disable s0ix flow for X1 Carbon 7th"
+    - SAUCE: e1000e: bump up timeout to wait when ME un-configure ULP mode
+
+  * Focal update: v5.4.29 upstream stable release (LP: #1870142)
+    - mmc: core: Allow host controllers to require R1B for CMD6
+    - mmc: core: Respect MMC_CAP_NEED_RSP_BUSY for erase/trim/discard
+    - mmc: core: Respect MMC_CAP_NEED_RSP_BUSY for eMMC sleep command
+    - mmc: sdhci-omap: Fix busy detection by enabling MMC_CAP_NEED_RSP_BUSY
+    - mmc: sdhci-tegra: Fix busy detection by enabling MMC_CAP_NEED_RSP_BUSY
+    - ACPI: PM: s2idle: Rework ACPI events synchronization
+    - cxgb4: fix throughput drop during Tx backpressure
+    - cxgb4: fix Txq restart check during backpressure
+    - geneve: move debug check after netdev unregister
+    - hsr: fix general protection fault in hsr_addr_is_self()
+    - ipv4: fix a RCU-list lock in inet_dump_fib()
+    - macsec: restrict to ethernet devices
+    - mlxsw: pci: Only issue reset when system is ready
+    - mlxsw: spectrum_mr: Fix list iteration in error path
+    - net/bpfilter: fix dprintf usage for /dev/kmsg
+    - net: cbs: Fix software cbs to consider packet sending time
+    - net: dsa: Fix duplicate frames flooded by learning
+    - net: dsa: mt7530: Change the LINK bit to reflect the link status
+    - net: dsa: tag_8021q: replace dsa_8021q_remove_header with __skb_vlan_pop
+    - net: ena: Add PCI shutdown handler to allow safe kexec
+    - net: mvneta: Fix the case where the last poll did not process all rx
+    - net/packet: tpacket_rcv: avoid a producer race condition
+    - net: phy: dp83867: w/a for fld detect threshold bootstrapping issue
+    - net: phy: mdio-bcm-unimac: Fix clock handling
+    - net: phy: mdio-mux-bcm-iproc: check clk_prepare_enable() return value
+    - net: qmi_wwan: add support for ASKEY WWHC050
+    - net/sched: act_ct: Fix leak of ct zone template on replace
+    - net_sched: cls_route: remove the right filter from hashtable
+    - net_sched: hold rtnl lock in tcindex_partial_destroy_work()
+    - net_sched: keep alloc_hash updated after hash allocation
+    - net: stmmac: dwmac-rk: fix error path in rk_gmac_probe
+    - NFC: fdp: Fix a signedness bug in fdp_nci_send_patch()
+    - r8169: re-enable MSI on RTL8168c
+    - slcan: not call free_netdev before rtnl_unlock in slcan_open
+    - tcp: also NULL skb->dev when copy was needed
+    - tcp: ensure skb->dev is NULL before leaving TCP stack
+    - tcp: repair: fix TCP_QUEUE_SEQ implementation
+    - vxlan: check return value of gro_cells_init()
+    - bnxt_en: Fix Priority Bytes and Packets counters in ethtool -S.
+    - bnxt_en: fix memory leaks in bnxt_dcbnl_ieee_getets()
+    - bnxt_en: Return error if bnxt_alloc_ctx_mem() fails.
+    - bnxt_en: Free context memory after disabling PCI in probe error path.
+    - bnxt_en: Reset rings if ring reservation fails during open()
+    - net: ip_gre: Separate ERSPAN newlink / changelink callbacks
+    - net: ip_gre: Accept IFLA_INFO_DATA-less configuration
+    - hsr: use rcu_read_lock() in hsr_get_node_{list/status}()
+    - hsr: add restart routine into hsr_get_node_list()
+    - hsr: set .netnsok flag
+    - net/mlx5: DR, Fix postsend actions write length
+    - net/mlx5e: Enhance ICOSQ WQE info fields
+    - net/mlx5e: Fix missing reset of SW metadata in Striding RQ reset
+    - net/mlx5e: Fix ICOSQ recovery flow with Striding RQ
+    - net/mlx5e: Do not recover from a non-fatal syndrome
+    - cgroup-v1: cgroup_pidlist_next should update position index
+    - nfs: add minor version to nfs_server_key for fscache
+    - cpupower: avoid multiple definition with gcc -fno-common
+    - drivers/of/of_mdio.c:fix of_mdiobus_register()
+    - cgroup1: don't call release_agent when it is ""
+    - [Config] updateconfigs for DPAA_ERRATUM_A050385
+    - dt-bindings: net: FMan erratum A050385
+    - arm64: dts: ls1043a: FMan erratum A050385
+    - fsl/fman: detect FMan erratum A050385
+    - drm/amd/display: update soc bb for nv14
+    - drm/amdgpu: correct ROM_INDEX/DATA offset for VEGA20
+    - drm/exynos: Fix cleanup of IOMMU related objects
+    - iommu/vt-d: Silence RCU-list debugging warnings
+    - s390/qeth: don't reset default_out_queue
+    - s390/qeth: handle error when backing RX buffer
+    - scsi: ipr: Fix softlockup when rescanning devices in petitboot
+    - mac80211: Do not send mesh HWMP PREQ if HWMP is disabled
+    - dpaa_eth: Remove unnecessary boolean expression in dpaa_get_headroom
+    - sxgbe: Fix off by one in samsung driver strncpy size arg
+    - net: hns3: fix "tc qdisc del" failed issue
+    - iommu/vt-d: Fix debugfs register reads
+    - iommu/vt-d: Populate debugfs if IOMMUs are detected
+    - iwlwifi: mvm: fix non-ACPI function
+    - i2c: hix5hd2: add missed clk_disable_unprepare in remove
+    - Input: raydium_i2c_ts - fix error codes in raydium_i2c_boot_trigger()
+    - Input: fix stale timestamp on key autorepeat events
+    - Input: synaptics - enable RMI on HP Envy 13-ad105ng
+    - Input: avoid BIT() macro usage in the serio.h UAPI header
+    - IB/rdmavt: Free kernel completion queue when done
+    - RDMA/core: Fix missing error check on dev_set_name()
+    - gpiolib: Fix irq_disable() semantics
+    - RDMA/nl: Do not permit empty devices names during RDMA_NLDEV_CMD_NEWLINK/SET
+    - RDMA/mad: Do not crash if the rdma device does not have a umad interface
+    - ceph: check POOL_FLAG_FULL/NEARFULL in addition to OSDMAP_FULL/NEARFULL
+    - ceph: fix memory leak in ceph_cleanup_snapid_map()
+    - ARM: dts: dra7: Add bus_dma_limit for L3 bus
+    - ARM: dts: omap5: Add bus_dma_limit for L3 bus
+    - x86/ioremap: Fix CONFIG_EFI=n build
+    - perf probe: Fix to delete multiple probe event
+    - perf probe: Do not depend on dwfl_module_addrsym()
+    - rtlwifi: rtl8188ee: Fix regression due to commit d1d1a96bdb44
+    - tools: Let O= makes handle a relative path with -C option
+    - scripts/dtc: Remove redundant YYLOC global declaration
+    - scsi: sd: Fix optimal I/O size for devices that change reported values
+    - nl80211: fix NL80211_ATTR_CHANNEL_WIDTH attribute type
+    - mac80211: drop data frames without key on encrypted links
+    - mac80211: mark station unauthorized before key removal
+    - mm/swapfile.c: move inode_lock out of claim_swapfile
+    - drivers/base/memory.c: indicate all memory blocks as removable
+    - mm/sparse: fix kernel crash with pfn_section_valid check
+    - mm: fork: fix kernel_stack memcg stats for various stack implementations
+    - gpiolib: acpi: Correct comment for HP x2 10 honor_wakeup quirk
+    - gpiolib: acpi: Rework honor_wakeup option into an ignore_wake option
+    - gpiolib: acpi: Add quirk to ignore EC wakeups on HP x2 10 BYT + AXP288 model
+    - bpf: Fix cgroup ref leak in cgroup_bpf_inherit on out-of-memory
+    - RDMA/core: Ensure security pkey modify is not lost
+    - afs: Fix handling of an abort from a service handler
+    - genirq: Fix reference leaks on irq affinity notifiers
+    - xfrm: handle NETDEV_UNREGISTER for xfrm device
+    - vti[6]: fix packet tx through bpf_redirect() in XinY cases
+    - RDMA/mlx5: Fix the number of hwcounters of a dynamic counter
+    - RDMA/mlx5: Fix access to wrong pointer while performing flush due to error
+    - RDMA/mlx5: Block delay drop to unprivileged users
+    - xfrm: fix uctx len check in verify_sec_ctx_len
+    - xfrm: add the missing verify_sec_ctx_len check in xfrm_add_acquire
+    - xfrm: policy: Fix doulbe free in xfrm_policy_timer
+    - afs: Fix client call Rx-phase signal handling
+    - afs: Fix some tracing details
+    - afs: Fix unpinned address list during probing
+    - ieee80211: fix HE SPR size calculation
+    - mac80211: set IEEE80211_TX_CTRL_PORT_CTRL_PROTO for nl80211 TX
+    - netfilter: flowtable: reload ip{v6}h in nf_flow_tuple_ip{v6}
+    - netfilter: nft_fwd_netdev: validate family and chain type
+    - netfilter: nft_fwd_netdev: allow to redirect to ifb via ingress
+    - i2c: nvidia-gpu: Handle timeout correctly in gpu_i2c_check_status()
+    - bpf, x32: Fix bug with JMP32 JSET BPF_X checking upper bits
+    - bpf: Initialize storage pointers to NULL to prevent freeing garbage pointer
+    - bpf/btf: Fix BTF verification of enum members in struct/union
+    - bpf, sockmap: Remove bucket->lock from sock_{hash|map}_free
+    - ARM: dts: sun8i-a83t-tbs-a711: Fix USB OTG mode detection
+    - vti6: Fix memory leak of skb if input policy check fails
+    - r8169: fix PHY driver check on platforms w/o module softdeps
+    - clocksource/drivers/hyper-v: Untangle stimers and timesync from clocksources
+    - USB: serial: option: add support for ASKEY WWHC050
+    - USB: serial: option: add BroadMobi BM806U
+    - USB: serial: option: add Wistron Neweb D19Q1
+    - USB: cdc-acm: restore capability check order
+    - USB: serial: io_edgeport: fix slab-out-of-bounds read in
+      edge_interrupt_callback
+    - usb: musb: fix crash with highmen PIO and usbmon
+    - media: flexcop-usb: fix endpoint sanity check
+    - media: usbtv: fix control-message timeouts
+    - staging: kpc2000: prevent underflow in cpld_reconfigure()
+    - staging: rtl8188eu: Add ASUS USB-N10 Nano B1 to device table
+    - staging: wlan-ng: fix ODEBUG bug in prism2sta_disconnect_usb
+    - staging: wlan-ng: fix use-after-free Read in hfa384x_usbin_callback
+    - ahci: Add Intel Comet Lake H RAID PCI ID
+    - libfs: fix infoleak in simple_attr_read()
+    - media: ov519: add missing endpoint sanity checks
+    - media: dib0700: fix rc endpoint lookup
+    - media: stv06xx: add missing descriptor sanity checks
+    - media: xirlink_cit: add missing descriptor sanity checks
+    - media: v4l2-core: fix a use-after-free bug of sd->devnode
+    - update wireguard dkms package version
+    - [Config] updateconfigs for NET_REDIRECT
+    - net: Fix CONFIG_NET_CLS_ACT=n and CONFIG_NFT_FWD_NETDEV={y, m} build
+    - Linux 5.4.29
+
+  * Restore kernel control of PCIe DPC via option (LP: #1869423)
+    - PCI/DPC: Add "pcie_ports=dpc-native" to allow DPC without AER control
+
+  * swap storms kills interactive use (LP: #1861359)
+    - SAUCE: mm/page_alloc.c: disable memory reclaim watermark boosting by default
+
+  * sysfs: incorrect network device permissions on network namespace change
+    (LP: #1865359)
+    - sysfs: add sysfs_file_change_owner()
+    - sysfs: add sysfs_link_change_owner()
+    - sysfs: add sysfs_group{s}_change_owner()
+    - sysfs: add sysfs_change_owner()
+    - device: add device_change_owner()
+    - drivers/base/power: add dpm_sysfs_change_owner()
+    - net-sysfs: add netdev_change_owner()
+    - net-sysfs: add queue_change_owner()
+    - net: fix sysfs permssions when device changes network namespace
+    - sysfs: fix static inline declaration of sysfs_groups_change_owner()
+
+  * Kernel Oops - general protection fault: 0000 [#1] SMP PTI after
+    disconnecting thunderbolt docking station (LP: #1864754)
+    - SAUCE: ptp: free ptp clock properly
+
+  * [Selftests] Apply various fixes and improvements (LP: #1870543)
+    - SAUCE: selftests: net: ip_defrag: limit packet to 1000 fragments
+    - SAUCE: kselftest/runner: avoid using timeout if timeout is disabled
+    - SAUCE: selftests/seccomp -- Disable timeout for seccomp tests
+
+  * Focal update: v5.4.28 upstream stable release (LP: #1869061)
+    - locks: fix a potential use-after-free problem when wakeup a waiter
+    - locks: reinstate locks_delete_block optimization
+    - spi: spi-omap2-mcspi: Support probe deferral for DMA channels
+    - drm/mediatek: Find the cursor plane instead of hard coding it
+    - phy: ti: gmii-sel: fix set of copy-paste errors
+    - phy: ti: gmii-sel: do not fail in case of gmii
+    - ARM: dts: dra7-l4: mark timer13-16 as pwm capable
+    - spi: qup: call spi_qup_pm_resume_runtime before suspending
+    - powerpc: Include .BTF section
+    - cifs: fix potential mismatch of UNC paths
+    - cifs: add missing mount option to /proc/mounts
+    - ARM: dts: dra7: Add "dma-ranges" property to PCIe RC DT nodes
+    - spi: pxa2xx: Add CS control clock quirk
+    - spi/zynqmp: remove entry that causes a cs glitch
+    - drm/exynos: dsi: propagate error value and silence meaningless warning
+    - drm/exynos: dsi: fix workaround for the legacy clock name
+    - drm/exynos: hdmi: don't leak enable HDMI_EN regulator if probe fails
+    - drivers/perf: fsl_imx8_ddr: Correct the CLEAR bit definition
+    - drivers/perf: arm_pmu_acpi: Fix incorrect checking of gicc pointer
+    - altera-stapl: altera_get_note: prevent write beyond end of 'key'
+    - dm bio record: save/restore bi_end_io and bi_integrity
+    - dm integrity: use dm_bio_record and dm_bio_restore
+    - riscv: avoid the PIC offset of static percpu data in module beyond 2G limits
+    - ASoC: stm32: sai: manage rebind issue
+    - spi: spi_register_controller(): free bus id on error paths
+    - riscv: Force flat memory model with no-mmu
+    - riscv: Fix range looking for kernel image memblock
+    - drm/amdgpu: clean wptr on wb when gpu recovery
+    - drm/amd/display: Clear link settings on MST disable connector
+    - drm/amd/display: fix dcc swath size calculations on dcn1
+    - xenbus: req->body should be updated before req->state
+    - xenbus: req->err should be updated before req->state
+    - block, bfq: fix overwrite of bfq_group pointer in bfq_find_set_group()
+    - parse-maintainers: Mark as executable
+    - binderfs: use refcount for binder control devices too
+    - Revert "drm/fbdev: Fallback to non tiled mode if all tiles not present"
+    - usb: quirks: add NO_LPM quirk for RTL8153 based ethernet adapters
+    - USB: serial: option: add ME910G1 ECM composition 0x110b
+    - usb: host: xhci-plat: add a shutdown
+    - USB: serial: pl2303: add device-id for HP LD381
+    - usb: xhci: apply XHCI_SUSPEND_DELAY to AMD XHCI controller 1022:145c
+    - usb: typec: ucsi: displayport: Fix NULL pointer dereference
+    - usb: typec: ucsi: displayport: Fix a potential race during registration
+    - USB: cdc-acm: fix close_delay and closing_wait units in TIOCSSERIAL
+    - USB: cdc-acm: fix rounding error in TIOCSSERIAL
+    - ALSA: line6: Fix endless MIDI read loop
+    - ALSA: hda/realtek - Enable headset mic of Acer X2660G with ALC662
+    - ALSA: hda/realtek - Enable the headset of Acer N50-600 with ALC662
+    - ALSA: seq: virmidi: Fix running status after receiving sysex
+    - ALSA: seq: oss: Fix running status after receiving sysex
+    - ALSA: pcm: oss: Avoid plugin buffer overflow
+    - ALSA: pcm: oss: Remove WARNING from snd_pcm_plug_alloc() checks
+    - tty: fix compat TIOCGSERIAL leaking uninitialized memory
+    - tty: fix compat TIOCGSERIAL checking wrong function ptr
+    - iio: chemical: sps30: fix missing triggered buffer dependency
+    - iio: st_sensors: remap SMO8840 to LIS2DH12
+    - iio: trigger: stm32-timer: disable master mode when stopping
+    - iio: accel: adxl372: Set iio_chan BE
+    - iio: magnetometer: ak8974: Fix negative raw values in sysfs
+    - iio: adc: stm32-dfsdm: fix sleep in atomic context
+    - iio: adc: at91-sama5d2_adc: fix differential channels in triggered mode
+    - iio: light: vcnl4000: update sampling periods for vcnl4200
+    - iio: light: vcnl4000: update sampling periods for vcnl4040
+    - mmc: rtsx_pci: Fix support for speed-modes that relies on tuning
+    - mmc: sdhci-of-at91: fix cd-gpios for SAMA5D2
+    - mmc: sdhci-cadence: set SDHCI_QUIRK2_PRESET_VALUE_BROKEN for UniPhier
+    - CIFS: fiemap: do not return EINVAL if get nothing
+    - kbuild: Disable -Wpointer-to-enum-cast
+    - staging: rtl8188eu: Add device id for MERCUSYS MW150US v2
+    - staging: greybus: loopback_test: fix poll-mask build breakage
+    - staging/speakup: fix get_word non-space look-ahead
+    - intel_th: msu: Fix the unexpected state warning
+    - intel_th: Fix user-visible error codes
+    - intel_th: pci: Add Elkhart Lake CPU support
+    - modpost: move the namespace field in Module.symvers last
+    - rtc: max8907: add missing select REGMAP_IRQ
+    - arm64: compat: Fix syscall number of compat_clock_getres
+    - xhci: Do not open code __print_symbolic() in xhci trace events
+    - btrfs: fix log context list corruption after rename whiteout error
+    - drm/amd/amdgpu: Fix GPR read from debugfs (v2)
+    - drm/lease: fix WARNING in idr_destroy
+    - stm class: sys-t: Fix the use of time_after()
+    - memcg: fix NULL pointer dereference in __mem_cgroup_usage_unregister_event
+    - mm, memcg: fix corruption on 64-bit divisor in memory.high throttling
+    - mm, memcg: throttle allocators based on ancestral memory.high
+    - mm/hotplug: fix hot remove failure in SPARSEMEM|!VMEMMAP case
+    - mm: do not allow MADV_PAGEOUT for CoW pages
+    - epoll: fix possible lost wakeup on epoll_ctl() path
+    - mm: slub: be more careful about the double cmpxchg of freelist
+    - mm, slub: prevent kmalloc_node crashes and memory leaks
+    - page-flags: fix a crash at SetPageError(THP_SWAP)
+    - x86/mm: split vmalloc_sync_all()
+    - futex: Fix inode life-time issue
+    - futex: Unbreak futex hashing
+    - arm64: smp: fix smp_send_stop() behaviour
+    - arm64: smp: fix crash_smp_send_stop() behaviour
+    - nvmet-tcp: set MSG_MORE only if we actually have more to send
+    - drm/bridge: dw-hdmi: fix AVI frame colorimetry
+    - staging: greybus: loopback_test: fix potential path truncation
+    - staging: greybus: loopback_test: fix potential path truncations
+    - Linux 5.4.28
+
+  * Pop sound from build-in speaker during cold boot and resume from S3
+    (LP: #1866357) // Focal update: v5.4.28 upstream stable release
+    (LP: #1869061)
+    - ALSA: hda/realtek: Fix pop noise on ALC225
+
+  * Focal update: v5.4.28 upstream stable release (LP: #1869061)
+    - perf/x86/amd: Add support for Large Increment per Cycle Events
+    - EDAC/amd64: Add family ops for Family 19h Models 00h-0Fh
+    - x86/MCE/AMD, EDAC/mce_amd: Add new Load Store unit McaType
+    - EDAC/mce_amd: Always load on SMCA systems
+    - x86/amd_nb: Add Family 19h PCI IDs
+    - EDAC/amd64: Drop some family checks for newer systems
+
+  * Update mpt3sas Driver to 33.100.00.00 for Ubuntu 20.04 (LP: #1863574)
+    - scsi: mpt3sas: Register trace buffer based on NVDATA settings
+    - scsi: mpt3sas: Display message before releasing diag buffer
+    - scsi: mpt3sas: Free diag buffer without any status check
+    - scsi: mpt3sas: Maintain owner of buffer through UniqueID
+    - scsi: mpt3sas: clear release bit when buffer reregistered
+    - scsi: mpt3sas: Reuse diag buffer allocated at load time
+    - scsi: mpt3sas: Add app owned flag support for diag buffer
+    - scsi: mpt3sas: Fail release cmnd if diag buffer is released
+    - scsi: mpt3sas: Use Component img header to get Package ver
+    - scsi: mpt3sas: Fix module parameter max_msix_vectors
+    - scsi: mpt3sas: Bump mpt3sas driver version to 32.100.00.00
+    - scsi: mpt3sas: Clean up some indenting
+    - scsi: mpt3sas: change allocation option
+    - scsi: mpt3sas: Update MPI Headers to v02.00.57
+    - scsi: mpt3sas: Add support for NVMe shutdown
+    - scsi: mpt3sas: renamed _base_after_reset_handler function
+    - scsi: mpt3sas: Add support IOCs new state named COREDUMP
+    - scsi: mpt3sas: Handle CoreDump state from watchdog thread
+    - scsi: mpt3sas: print in which path firmware fault occurred
+    - scsi: mpt3sas: Optimize mpt3sas driver logging
+    - scsi: mpt3sas: Print function name in which cmd timed out
+    - scsi: mpt3sas: Remove usage of device_busy counter
+    - scsi: mpt3sas: Update drive version to 33.100.00.00
+
+  * Ubuntu 20.04: megaraid_sas driver update to version 07.713.01.00-rc1
+    (LP: #1863581)
+    - scsi: megaraid_sas: Unique names for MSI-X vectors
+    - scsi: megaraid_sas: remove unused variables 'debugBlk','fusion'
+    - compat_ioctl: use correct compat_ptr() translation in drivers
+    - scsi: megaraid_sas: Make poll_aen_lock static
+    - scsi: megaraid_sas: Reset adapter if FW is not in READY state after device
+      resume
+    - scsi: megaraid_sas: Set no_write_same only for Virtual Disk
+    - scsi: megaraid_sas: Update optimal queue depth for SAS and NVMe devices
+    - scsi: megaraid_sas: Do not kill host bus adapter, if adapter is already dead
+    - scsi: megaraid_sas: Do not kill HBA if JBOD Seqence map or RAID map is
+      disabled
+    - scsi: megaraid_sas: Do not set HBA Operational if FW is not in operational
+      state
+    - scsi: megaraid_sas: Re-Define enum DCMD_RETURN_STATUS
+    - scsi: megaraid_sas: Limit the number of retries for the IOCTLs causing
+      firmware fault
+    - scsi: megaraid_sas: Use Block layer API to check SCSI device in-flight IO
+      requests
+    - scsi: megaraid_sas: Update driver version to 07.713.01.00-rc1
+    - scsi: megaraid_sas: fixup MSIx interrupt setup during resume
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Fri, 03 Apr 2020 16:28:40 +0200
+
+linux (5.4.0-21.25) focal; urgency=medium
+
+  * CVE-2020-8835
+    - SAUCE: bpf: undo incorrect __reg_bound_offset32 handling
+
+ -- Thadeu Lima de Souza Cascardo <cascardo@canonical.com>  Thu, 26 Mar 2020 17:51:28 -0300
+
+linux (5.4.0-20.24) focal; urgency=medium
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: (lockdown) Reduce lockdown level to INTEGRITY for secure boot
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 23 Mar 2020 14:54:04 -0500
+
+linux (5.4.0-19.23) focal; urgency=medium
+
+  * focal/linux: 5.4.0-19.23 -proposed tracker (LP: #1868347)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update helper scripts
+    - update dkms package versions
+
+  * Focal update: v5.4.27 upstream stable release (LP: #1868538)
+    - netfilter: hashlimit: do not use indirect calls during gc
+    - netfilter: xt_hashlimit: unregister proc file before releasing mutex
+    - drm/amdgpu: Fix TLB invalidation request when using semaphore
+    - ACPI: watchdog: Allow disabling WDAT at boot
+    - HID: apple: Add support for recent firmware on Magic Keyboards
+    - ACPI: watchdog: Set default timeout in probe
+    - HID: hid-bigbenff: fix general protection fault caused by double kfree
+    - HID: hid-bigbenff: call hid_hw_stop() in case of error
+    - HID: hid-bigbenff: fix race condition for scheduled work during removal
+    - selftests/rseq: Fix out-of-tree compilation
+    - tracing: Fix number printing bug in print_synth_event()
+    - cfg80211: check reg_rule for NULL in handle_channel_custom()
+    - scsi: libfc: free response frame from GPN_ID
+    - net: usb: qmi_wwan: restore mtu min/max values after raw_ip switch
+    - net: ks8851-ml: Fix IRQ handling and locking
+    - mac80211: rx: avoid RCU list traversal under mutex
+    - net: ll_temac: Fix race condition causing TX hang
+    - net: ll_temac: Add more error handling of dma_map_single() calls
+    - net: ll_temac: Fix RX buffer descriptor handling on GFP_ATOMIC pressure
+    - net: ll_temac: Handle DMA halt condition caused by buffer underrun
+    - blk-mq: insert passthrough request into hctx->dispatch directly
+    - drm/amdgpu: fix memory leak during TDR test(v2)
+    - kbuild: add dtbs_check to PHONY
+    - kbuild: add dt_binding_check to PHONY in a correct place
+    - signal: avoid double atomic counter increments for user accounting
+    - slip: not call free_netdev before rtnl_unlock in slip_open
+    - net: phy: mscc: fix firmware paths
+    - hinic: fix a irq affinity bug
+    - hinic: fix a bug of setting hw_ioctxt
+    - hinic: fix a bug of rss configuration
+    - net: rmnet: fix NULL pointer dereference in rmnet_newlink()
+    - net: rmnet: fix NULL pointer dereference in rmnet_changelink()
+    - net: rmnet: fix suspicious RCU usage
+    - net: rmnet: remove rcu_read_lock in rmnet_force_unassociate_device()
+    - net: rmnet: do not allow to change mux id if mux id is duplicated
+    - net: rmnet: use upper/lower device infrastructure
+    - net: rmnet: fix bridge mode bugs
+    - net: rmnet: fix packet forwarding in rmnet bridge mode
+    - sfc: fix timestamp reconstruction at 16-bit rollover points
+    - jbd2: fix data races at struct journal_head
+    - blk-mq: insert flush request to the front of dispatch queue
+    - net: qrtr: fix len of skb_put_padto in qrtr_node_enqueue
+    - ARM: 8957/1: VDSO: Match ARMv8 timer in cntvct_functional()
+    - ARM: 8958/1: rename missed uaccess .fixup section
+    - mm: slub: add missing TID bump in kmem_cache_alloc_bulk()
+    - HID: google: add moonball USB id
+    - HID: add ALWAYS_POLL quirk to lenovo pixart mouse
+    - ARM: 8961/2: Fix Kbuild issue caused by per-task stack protector GCC plugin
+    - ipv4: ensure rcu_read_lock() in cipso_v4_error()
+    - Linux 5.4.27
+
+  * This laptop contains a touchpadwhich is not recognized. (LP: #1858299) //
+    Focal update: v5.4.27 upstream stable release (LP: #1868538)
+    - HID: i2c-hid: add Trekstor Surfbook E11B to descriptor override
+
+  * suspend only works once on ThinkPad X1 Carbon gen 7 (LP: #1865570)
+    - SAUCE: e1000e: Disable s0ix flow for X1 Carbon 7th
+
+  *  Make Dell WD19 dock more reliable after suspend (LP: #1868217)
+    - xhci: Ensure link state is U3 after setting USB_SS_PORT_LS_U3
+    - xhci: Wait until link state trainsits to U0 after setting USB_SS_PORT_LS_U0
+    - xhci: Finetune host initiated USB3 rootport link suspend and resume
+    - USB: Disable LPM on WD19's Realtek Hub
+
+  * update-version-dkms doesn't add a BugLink (LP: #1867790)
+    - [Packaging] Add BugLink to update-version-dkms commit
+
+  * enable realtek ethernet device ASPM function (LP: #1836030)
+    - PCI/ASPM: Add L1 PM substate support to pci_disable_link_state()
+    - PCI/ASPM: Allow re-enabling Clock PM
+    - PCI/ASPM: Remove pcie_aspm_enabled() unnecessary locking
+    - PCI/ASPM: Add pcie_aspm_get_link()
+    - PCI/ASPM: Add sysfs attributes for controlling ASPM link states
+
+  * Update SmartPQI driver in Focal to 1.2.10-025 (LP: #1864484)
+    - scsi: smartpqi: clean up indentation of a statement
+    - scsi: smartpqi: remove set but not used variable 'ctrl_info'
+    - scsi: smartpqi: clean up an indentation issue
+    - scsi: smartpqi: fix controller lockup observed during force reboot
+    - scsi: smartpqi: fix call trace in device discovery
+    - scsi: smartpqi: add inquiry timeouts
+    - scsi: smartpqi: fix LUN reset when fw bkgnd thread is hung
+    - scsi: smartpqi: change TMF timeout from 60 to 30 seconds
+    - scsi: smartpqi: correct syntax issue
+    - scsi: smartpqi: fix problem with unique ID for physical device
+    - scsi: smartpqi: remove unused manifest constants
+    - scsi: smartpqi: Align driver syntax with oob
+    - scsi: smartpqi: bump version
+
+  * [roce-0111]sync mainline kernel 5.5rc6 roce patchset into ubuntu HWE kernel
+    branch (LP: #1859269)
+    - RDMA/hns: Modify variable/field name from vlan to vlan_id
+    - RDMA/hns: Fix a spelling mistake in a macro
+    - RDMA/hns: Delete BITS_PER_BYTE redefinition
+    - RDMA/core: Move core content from ib_uverbs to ib_core
+    - RDMA/core: Create mmap database and cookie helper functions
+    - RDMA: Connect between the mmap entry and the umap_priv structure
+    - RDMA/hns: Remove unsupported modify_port callback
+    - RDMA/hns: Delete unnecessary variable max_post
+    - RDMA/hns: Remove unnecessary structure hns_roce_sqp
+    - RDMA/hns: Delete unnecessary uar from hns_roce_cq
+    - RDMA/hns: Modify fields of struct hns_roce_srq
+    - RDMA/hns: Replace not intuitive function/macro names
+    - RDMA/hns: Simplify doorbell initialization code
+    - RDMA/hns: Modify hns_roce_hw_v2_get_cfg to simplify the code
+    - RDMA/hns: Fix non-standard error codes
+    - RDMA/hns: Modify appropriate printings
+    - dma-mapping: remove the DMA_ATTR_WRITE_BARRIER flag
+    - IB/umem: remove the dmasync argument to ib_umem_get
+    - RDMA/hns: Redefine interfaces used in creating cq
+    - RDMA/hns: Redefine the member of hns_roce_cq struct
+    - RDMA/hns: Rename the functions used inside creating cq
+    - RDMA/hns: Delete unnecessary callback functions for cq
+    - RDMA/hns: Remove unused function hns_roce_init_eq_table()
+    - RDMA/hns: Update the value of qp type
+    - RDMA/hns: Delete unnessary parameters in hns_roce_v2_qp_modify()
+    - RDMA/hns: Remove redundant print information
+    - RDMA/hns: Replace custom macros HNS_ROCE_ALIGN_UP
+    - RDMA/hns: Fix coding style issues
+    - RDMA/hns: Add support for reporting wc as software mode
+    - RDMA/hns: Remove some redundant variables related to capabilities
+    - RDMA/hns: Add interfaces to get pf capabilities from firmware
+    - RDMA/hns: Get pf capabilities from firmware
+    - RDMA/hns: Add support for extended atomic in userspace
+
+  * dmaengine: hisilicon: Add Kunpeng DMA engine support (LP: #1864442)
+    - dmaengine: hisilicon: Add Kunpeng DMA engine support
+    - [Config] CONFIG_HISI_DMA=m
+
+  * Add support for Realtek 8723DE wireless adapter (LP: #1780590)
+    - rtw88: 8822c: fix boolreturn.cocci warnings
+    - rtw88: remove redundant flag check helper function
+    - rtw88: pci: reset H2C queue indexes in a single write
+    - rtw88: not to enter or leave PS under IRQ
+    - rtw88: not to control LPS by each vif
+    - rtw88: remove unused lps state check helper
+    - rtw88: LPS enter/leave should be protected by lock
+    - rtw88: leave PS state for dynamic mechanism
+    - rtw88: add deep power save support
+    - rtw88: not to enter LPS by coex strategy
+    - rtw88: select deep PS mode when module is inserted
+    - rtw88: add deep PS PG mode for 8822c
+    - rtw88: remove misleading module parameter rtw_fw_support_lps
+    - mac80211: simplify TX aggregation start
+    - rtw88: check firmware leave lps successfully
+    - rtw88: allows to set RTS in TX descriptor
+    - rtw88: add driver TX queue support
+    - rtw88: take over rate control from mac80211
+    - rtw88: report tx rate to mac80211 stack
+    - rtw88: add TX-AMSDU support
+    - rtw88: flush hardware tx queues
+    - rtw88: Don't set RX_FLAG_DECRYPTED if packet has no encryption
+    - rtw88: configure TX queue EDCA parameters
+    - rtw88: raise firmware version debug level
+    - rtw88: use struct rtw_fw_hdr to access firmware header
+    - rtw88: Fix an error message
+    - rtw88: config 8822c multicast address in MAC init flow
+    - rtw88: add NL80211_EXT_FEATURE_CAN_REPLACE_PTK0 support
+    - rtw88: Use rtw_write8_set to set SYS_FUNC
+    - rtw88: pci: config phy after chip info is setup
+    - rtw88: use a for loop in rtw_power_mode_change(), not goto
+    - rtw88: include interrupt.h for tasklet_struct
+    - rtw88: mark rtw_fw_hdr __packed
+    - rtw88: use macro to check the current band
+    - rtw88: add power tracking support
+    - rtw88: Enable 802.11ac beamformee support
+    - rtw88: add set_bitrate_mask support
+    - rtw88: add phy_info debugfs to show Tx/Rx physical status
+    - rtw88: fix GENMASK_ULL for u64
+    - rtw88: fix sparse warnings for DPK
+    - rtw88: fix sparse warnings for power tracking
+    - rtw88: 8822b: add RFE type 3 support
+    - rtw88: use rtw_phy_pg_cfg_pair struct, not arrays
+    - rtw88: rearrange if..else statements for rx rate indexes
+    - rtw88: avoid FW info flood
+    - rtw88: remove redundant null pointer check on arrays
+    - rtw88: raise LPS threshold to 50, for less power consumption
+    - rtw88: fix potential NULL pointer access for firmware
+    - rtw88: signal completion even on firmware-request failure
+    - rtw88: remove duplicated include from ps.c
+    - rtw88: pci: use macros to access PCI DBI/MDIO registers
+    - rtw88: pci: use for loop instead of while loop for DBI/MDIO
+    - rtw88: pci: enable CLKREQ function if host supports it
+    - rtw88: allows to enable/disable HCI link PS mechanism
+    - rtw88: pci: reset ring index when release skbs in tx ring
+    - rtw88: pci: reset dma when reset pci trx ring
+    - rtw88: add interface config for 8822c
+    - rtw88: load wowlan firmware if wowlan is supported
+    - rtw88: support wowlan feature for 8822c
+    - rtw88: Add wowlan pattern match support
+    - rtw88: Add wowlan net-detect support
+    - rtw88: fix TX secondary channel offset of 40M if current bw is 20M or 40M
+    - rtw88: 8822c: update power sequence to v15
+    - rtw88: remove unused spinlock
+    - rtw88: remove unused variable 'in_lps'
+    - rtw88: remove unused vif pointer in struct rtw_vif
+    - rtw88: use rtw_hci_stop() instead of rtwdev->hci.ops->stop()
+    - rtw88: assign NULL to skb after being kfree()'ed
+    - rtw88: change max_num_of_tx_queue() definition to inline in pci.h
+    - rtw88: use true,false for bool variable
+    - rtw88: use shorter delay time to poll PS state
+    - rtw88: Fix return value of rtw_wow_check_fw_status
+    - SAUCE: rtw88: add regulatory process strategy for different chipset
+    - SAUCE: rtw88: support dynamic user regulatory setting
+    - SAUCE: rtw88: Use secondary channel offset enumeration
+    - SAUCE: rtw88: 8822c: modify rf protection setting
+    - SAUCE: rtw88: disable TX-AMSDU on 2.4G band
+    - SAUCE: Revert "rtw88: disable TX-AMSDU on 2.4G band"
+    - SAUCE: rtw88: disable TX-AMSDU on 2.4G band
+    - SAUCE: rtw88: remove unused parameter vif in rtw_lps_pg_info_get()
+    - SAUCE: rtw88: add rtw_read8_mask and rtw_read16_mask
+    - SAUCE: rtw88: pci: 8822c should set clock delay to zero
+    - SAUCE: rtw88: move rtw_enter_ips() to the last when config
+    - SAUCE: rtw88: avoid holding mutex for cancel_delayed_work_sync()
+    - SAUCE: rtw88: add ciphers to suppress error message
+    - SAUCE: rtw88: 8822c: update power sequence to v16
+    - SAUCE: rtw88: Fix incorrect beamformee role setting
+    - SAUCE: rtw88: don't hold all IRQs disabled for PS operations
+    - SAUCE: rtw88: extract alloc rsvd_page and h2c skb routines
+    - SAUCE: rtw88: associate reserved pages with each vif
+    - SAUCE: rtw88: add adaptivity support for EU/JP regulatory
+    - SAUCE: rtw88: 8723d: Add basic chip capabilities
+    - SAUCE: rtw88: 8723d: add beamform wrapper functions
+    - SAUCE: rtw88: 8723d: Add power sequence
+    - SAUCE: rtw88: 8723d: Add RF read/write ops
+    - SAUCE: rtw88: 8723d: Add mac/bb/rf/agc/power_limit tables
+    - SAUCE: rtw88: 8723d: Add cfg_ldo25 to control LDO25
+    - SAUCE: rtw88: 8723d: Add new chip op efuse_grant() to control efuse access
+    - SAUCE: rtw88: 8723d: Add read_efuse to recognize efuse info from map
+    - SAUCE: rtw88: add legacy firmware download for 8723D devices
+    - SAUCE: rtw88: no need to send additional information to legacy firmware
+    - SAUCE: rtw88: 8723d: Add mac power-on/-off function
+    - SAUCE: rtw88: decompose while(1) loop of power sequence polling command
+    - SAUCE: rtw88: 8723d: 11N chips don't support H2C queue
+    - SAUCE: rtw88: 8723d: implement set_tx_power_index ops
+    - SAUCE: rtw88: 8723d: Organize chip TX/RX FIFO
+    - SAUCE: rtw88: 8723d: initialize mac/bb/rf basic functions
+    - SAUCE: rtw88: 8723d: Add DIG parameter
+    - SAUCE: rtw88: 8723d: Add query_rx_desc
+    - SAUCE: rtw88: 8723d: Add set_channel
+    - SAUCE: rtw88: handle C2H_CCX_TX_RPT to know if packet TX'ed successfully
+    - SAUCE: rtw88: 8723d: 11N chips don't support LDPC
+    - SAUCE: rtw88: set default port to firmware
+    - SAUCE: rtw88: update tx descriptor of mgmt and rsvd page packets
+    - SAUCE: rtw88: sar: add SAR of TX power limit
+    - SAUCE: rtw88: sar: Load static SAR table from ACPI WRDS method
+    - SAUCE: rtw88: sar: Load dynamic SAR table from ACPI methods
+    - SAUCE: rtw88: sar: apply dynamic SAR table to tx power limit
+    - SAUCE: rtw88: sar: add sar_work to poll if dynamic SAR table is changed
+    - SAUCE: rtw88: sar: dump sar information via debugfs
+    - SAUCE: rtw88: 8723d: Add chip_ops::false_alarm_statistics
+    - SAUCE: rtw88: 8723d: Set IG register for CCK rate
+    - SAUCE: rtw88: 8723d: add interface configurations table
+    - SAUCE: rtw88: 8723d: Add LC calibration
+    - SAUCE: rtw88: 8723d: add IQ calibration
+    - SAUCE: rtw88: 8723d: Add power tracking
+    - SAUCE: rtw88: 8723d: Add shutdown callback to disable BT USB suspend
+    - SAUCE: rtw88: 8723d: implement flush queue
+    - SAUCE: rtw88: 8723d: set ltecoex register address in chip_info
+    - SAUCE: rtw88: 8723d: Add coex support
+    - SAUCE: rtw88: fill zeros to words 0x06 and 0x07 of security cam entry
+    - SAUCE: rtw88: 8723d: Add 8723DE to Kconfig and Makefile
+    - [Config] CONFIG_RTW88_8723DE=y
+
+  * [Ubuntu 20.04] Unset HIBERNATION and PM kernel config options for focal
+    (LP: #1867753)
+    - [Config] CONFIG_HIBERNATION=n and CONFIG_PM=n for s390x
+
+  * [20.04 FEAT] Base KVM setup for secure guests - kernel part (LP: #1835531)
+    - KVM: s390: Cleanup kvm_arch_init error path
+    - KVM: s390: Cleanup initial cpu reset
+    - KVM: s390: Add new reset vcpu API
+    - s390/protvirt: introduce host side setup
+    - s390/protvirt: add ultravisor initialization
+    - s390/mm: provide memory management functions for protected KVM guests
+    - s390/mm: add (non)secure page access exceptions handlers
+    - s390/protvirt: Add sysfs firmware interface for Ultravisor information
+    - KVM: s390/interrupt: do not pin adapter interrupt pages
+    - KVM: s390: protvirt: Add UV debug trace
+    - KVM: s390: add new variants of UV CALL
+    - KVM: s390: protvirt: Add initial vm and cpu lifecycle handling
+    - KVM: s390: protvirt: Secure memory is not mergeable
+    - KVM: s390/mm: Make pages accessible before destroying the guest
+    - KVM: s390: protvirt: Handle SE notification interceptions
+    - KVM: s390: protvirt: Instruction emulation
+    - KVM: s390: protvirt: Implement interrupt injection
+    - KVM: s390: protvirt: Add SCLP interrupt handling
+    - KVM: s390: protvirt: Handle spec exception loops
+    - KVM: s390: protvirt: Add new gprs location handling
+    - KVM: S390: protvirt: Introduce instruction data area bounce buffer
+    - KVM: s390: protvirt: handle secure guest prefix pages
+    - KVM: s390/mm: handle guest unpin events
+    - KVM: s390: protvirt: Write sthyi data to instruction data area
+    - KVM: s390: protvirt: STSI handling
+    - KVM: s390: protvirt: disallow one_reg
+    - KVM: s390: protvirt: Do only reset registers that are accessible
+    - KVM: s390: protvirt: Only sync fmt4 registers
+    - KVM: s390: protvirt: Add program exception injection
+    - KVM: s390: protvirt: UV calls in support of diag308 0, 1
+    - KVM: s390: protvirt: Report CPU state to Ultravisor
+    - KVM: s390: protvirt: Support cmd 5 operation state
+    - KVM: s390: protvirt: Mask PSW interrupt bits for interception 104 and 112
+    - KVM: s390: protvirt: do not inject interrupts after start
+    - KVM: s390: protvirt: Add UV cpu reset calls
+    - DOCUMENTATION: Protected virtual machine introduction and IPL
+    - KVM: s390: protvirt: introduce and enable KVM_CAP_S390_PROTECTED
+    - KVM: s390: protvirt: Add KVM api documentation
+    - mm/gup/writeback: add callbacks for inaccessible pages
+
+  * Sys oopsed with sysfs test in ubuntu_stress_smoke_test on X-hwe ARM64
+    (LP: #1866772)
+    - ACPI: sysfs: copy ACPI data using io memory copying
+
+  * Focal update: v5.4.26 upstream stable release (LP: #1867903)
+    - virtio_balloon: Adjust label in virtballoon_probe
+    - ALSA: hda/realtek - More constifications
+    - cgroup, netclassid: periodically release file_lock on classid updating
+    - gre: fix uninit-value in __iptunnel_pull_header
+    - inet_diag: return classid for all socket types
+    - ipv6/addrconf: call ipv6_mc_up() for non-Ethernet interface
+    - ipvlan: add cond_resched_rcu() while processing muticast backlog
+    - ipvlan: do not add hardware address of master to its unicast filter list
+    - ipvlan: do not use cond_resched_rcu() in ipvlan_process_multicast()
+    - ipvlan: don't deref eth hdr before checking it's set
+    - macvlan: add cond_resched() during multicast processing
+    - net: dsa: fix phylink_start()/phylink_stop() calls
+    - net: dsa: mv88e6xxx: fix lockup on warm boot
+    - net: fec: validate the new settings in fec_enet_set_coalesce()
+    - net: hns3: fix a not link up issue when fibre port supports autoneg
+    - net/ipv6: use configured metric when add peer route
+    - netlink: Use netlink header as base to calculate bad attribute offset
+    - net: macsec: update SCI upon MAC address change.
+    - net: nfc: fix bounds checking bugs on "pipe"
+    - net/packet: tpacket_rcv: do not increment ring index on drop
+    - net: phy: bcm63xx: fix OOPS due to missing driver name
+    - net: stmmac: dwmac1000: Disable ACS if enhanced descs are not used
+    - net: systemport: fix index check to avoid an array out of bounds access
+    - sfc: detach from cb_page in efx_copy_channel()
+    - slip: make slhc_compress() more robust against malicious packets
+    - taprio: Fix sending packets without dequeueing them
+    - bonding/alb: make sure arp header is pulled before accessing it
+    - bnxt_en: reinitialize IRQs when MTU is modified
+    - bnxt_en: fix error handling when flashing from file
+    - cgroup: memcg: net: do not associate sock with unrelated cgroup
+    - net: memcg: late association of sock to memcg
+    - net: memcg: fix lockdep splat in inet_csk_accept()
+    - devlink: validate length of param values
+    - devlink: validate length of region addr/len
+    - fib: add missing attribute validation for tun_id
+    - nl802154: add missing attribute validation
+    - nl802154: add missing attribute validation for dev_type
+    - can: add missing attribute validation for termination
+    - macsec: add missing attribute validation for port
+    - net: fq: add missing attribute validation for orphan mask
+    - net: taprio: add missing attribute validation for txtime delay
+    - team: add missing attribute validation for port ifindex
+    - team: add missing attribute validation for array index
+    - tipc: add missing attribute validation for MTU property
+    - nfc: add missing attribute validation for SE API
+    - nfc: add missing attribute validation for deactivate target
+    - nfc: add missing attribute validation for vendor subcommand
+    - net: phy: avoid clearing PHY interrupts twice in irq handler
+    - net: phy: fix MDIO bus PM PHY resuming
+    - net/ipv6: need update peer route when modify metric
+    - net/ipv6: remove the old peer route if change it to a new one
+    - selftests/net/fib_tests: update addr_metric_test for peer route testing
+    - net: dsa: Don't instantiate phylink for CPU/DSA ports unless needed
+    - net: phy: Avoid multiple suspends
+    - cgroup: cgroup_procs_next should increase position index
+    - cgroup: Iterate tasks that did not finish do_exit()
+    - netfilter: nf_tables: fix infinite loop when expr is not available
+    - iwlwifi: mvm: Do not require PHY_SKU NVM section for 3168 devices
+    - iommu/vt-d: quirk_ioat_snb_local_iommu: replace WARN_TAINT with pr_warn +
+      add_taint
+    - netfilter: nf_conntrack: ct_cpu_seq_next should increase position index
+    - netfilter: synproxy: synproxy_cpu_seq_next should increase position index
+    - netfilter: xt_recent: recent_seq_next should increase position index
+    - netfilter: x_tables: xt_mttg_seq_next should increase position index
+    - workqueue: don't use wq_select_unbound_cpu() for bound works
+    - drm/amd/display: remove duplicated assignment to grph_obj_type
+    - drm/i915: be more solid in checking the alignment
+    - drm/i915: Defer semaphore priority bumping to a workqueue
+    - mmc: sdhci-pci-gli: Enable MSI interrupt for GL975x
+    - pinctrl: falcon: fix syntax error
+    - ktest: Add timeout for ssh sync testing
+    - cifs_atomic_open(): fix double-put on late allocation failure
+    - gfs2_atomic_open(): fix O_EXCL|O_CREAT handling on cold dcache
+    - KVM: x86: clear stale x86_emulate_ctxt->intercept value
+    - KVM: nVMX: avoid NULL pointer dereference with incorrect EVMCS GPAs
+    - ARC: define __ALIGN_STR and __ALIGN symbols for ARC
+    - fuse: fix stack use after return
+    - s390/dasd: fix data corruption for thin provisioned devices
+    - ipmi_si: Avoid spurious errors for optional IRQs
+    - blk-iocost: fix incorrect vtime comparison in iocg_is_idle()
+    - fscrypt: don't evict dirty inodes after removing key
+    - macintosh: windfarm: fix MODINFO regression
+    - x86/ioremap: Map EFI runtime services data as encrypted for SEV
+    - efi: Fix a race and a buffer overflow while reading efivars via sysfs
+    - efi: Add a sanity check to efivar_store_raw()
+    - i2c: designware-pci: Fix BUG_ON during device removal
+    - mt76: fix array overflow on receiving too many fragments for a packet
+    - perf/amd/uncore: Replace manual sampling check with CAP_NO_INTERRUPT flag
+    - x86/mce: Fix logic and comments around MSR_PPIN_CTL
+    - iommu/dma: Fix MSI reservation allocation
+    - iommu/vt-d: dmar: replace WARN_TAINT with pr_warn + add_taint
+    - iommu/vt-d: Fix RCU list debugging warnings
+    - iommu/vt-d: Fix a bug in intel_iommu_iova_to_phys() for huge page
+    - batman-adv: Don't schedule OGM for disabled interface
+    - clk: imx8mn: Fix incorrect clock defines
+    - pinctrl: meson-gxl: fix GPIOX sdio pins
+    - pinctrl: imx: scu: Align imx sc msg structs to 4
+    - virtio_ring: Fix mem leak with vring_new_virtqueue()
+    - drm/i915/gvt: Fix dma-buf display blur issue on CFL
+    - pinctrl: core: Remove extra kref_get which blocks hogs being freed
+    - drm/i915/gvt: Fix unnecessary schedule timer when no vGPU exits
+    - driver code: clarify and fix platform device DMA mask allocation
+    - iommu/vt-d: Fix RCU-list bugs in intel_iommu_init()
+    - i2c: gpio: suppress error on probe defer
+    - nl80211: add missing attribute validation for critical protocol indication
+    - nl80211: add missing attribute validation for beacon report scanning
+    - nl80211: add missing attribute validation for channel switch
+    - perf bench futex-wake: Restore thread count default to online CPU count
+    - netfilter: cthelper: add missing attribute validation for cthelper
+    - netfilter: nft_payload: add missing attribute validation for payload csum
+      flags
+    - netfilter: nft_tunnel: add missing attribute validation for tunnels
+    - netfilter: nf_tables: dump NFTA_CHAIN_FLAGS attribute
+    - netfilter: nft_chain_nat: inet family is missing module ownership
+    - iommu/vt-d: Fix the wrong printing in RHSA parsing
+    - iommu/vt-d: Ignore devices with out-of-spec domain number
+    - i2c: acpi: put device when verifying client fails
+    - iommu/amd: Fix IOMMU AVIC not properly update the is_run bit in IRTE
+    - ipv6: restrict IPV6_ADDRFORM operation
+    - net/smc: check for valid ib_client_data
+    - net/smc: cancel event worker during device removal
+    - Linux 5.4.26
+
+  * please help enable CONFIG_EROFS_FS_ZIP (LP: #1867099)
+    - [Config] CONFIG_EROFS_FS_ZIP=y
+    - [Config] CONFIG_EROFS_FS_CLUSTER_PAGE_LIMIT=1
+
+  * All PS/2 ports on PS/2 Serial add-in bracket are not working after S3
+    (LP: #1866734)
+    - SAUCE: Input: i8042 - fix the selftest retry logic
+
+  * [UBUNTU 20.04] virtio-blk disks can go dissfunctional when swiotlb fills up
+    (LP: #1867109)
+    - virtio-blk: fix hw_queue stopped on arbitrary error
+    - virtio-blk: improve virtqueue error to BLK_STS
+
+  * Focal update: v5.4.25 upstream stable release (LP: #1867178)
+    - block, bfq: get extra ref to prevent a queue from being freed during a group
+      move
+    - block, bfq: do not insert oom queue into position tree
+    - net: dsa: bcm_sf2: Forcibly configure IMP port for 1Gb/sec
+    - net: stmmac: fix notifier registration
+    - dm thin metadata: fix lockdep complaint
+    - RDMA/core: Fix pkey and port assignment in get_new_pps
+    - RDMA/core: Fix use of logical OR in get_new_pps
+    - kbuild: fix 'No such file or directory' warning when cleaning
+    - kprobes: Fix optimize_kprobe()/unoptimize_kprobe() cancellation logic
+    - blktrace: fix dereference after null check
+    - ALSA: hda: do not override bus codec_mask in link_get()
+    - serial: ar933x_uart: set UART_CS_{RX,TX}_READY_ORIDE
+    - selftests: fix too long argument
+    - usb: gadget: composite: Support more than 500mA MaxPower
+    - usb: gadget: ffs: ffs_aio_cancel(): Save/restore IRQ flags
+    - usb: gadget: serial: fix Tx stall after buffer overflow
+    - habanalabs: halt the engines before hard-reset
+    - habanalabs: do not halt CoreSight during hard reset
+    - habanalabs: patched cb equals user cb in device memset
+    - drm/msm/mdp5: rate limit pp done timeout warnings
+    - drm: msm: Fix return type of dsi_mgr_connector_mode_valid for kCFI
+    - drm/modes: Make sure to parse valid rotation value from cmdline
+    - drm/modes: Allow DRM_MODE_ROTATE_0 when applying video mode parameters
+    - scsi: megaraid_sas: silence a warning
+    - drm/msm/dsi: save pll state before dsi host is powered off
+    - drm/msm/dsi/pll: call vco set rate explicitly
+    - selftests: forwarding: use proto icmp for {gretap, ip6gretap}_mac testing
+    - selftests: forwarding: vxlan_bridge_1d: fix tos value
+    - net: atlantic: check rpc result and wait for rpc address
+    - net: ks8851-ml: Remove 8-bit bus accessors
+    - net: ks8851-ml: Fix 16-bit data access
+    - net: ks8851-ml: Fix 16-bit IO operation
+    - net: ethernet: dm9000: Handle -EPROBE_DEFER in dm9000_parse_dt()
+    - watchdog: da9062: do not ping the hw during stop()
+    - s390/cio: cio_ignore_proc_seq_next should increase position index
+    - s390: make 'install' not depend on vmlinux
+    - efi: Only print errors about failing to get certs if EFI vars are found
+    - net/mlx5: DR, Fix matching on vport gvmi
+    - nvme/pci: Add sleep quirk for Samsung and Toshiba drives
+    - nvme-pci: Use single IRQ vector for old Apple models
+    - x86/boot/compressed: Don't declare __force_order in kaslr_64.c
+    - s390/qdio: fill SL with absolute addresses
+    - nvme: Fix uninitialized-variable warning
+    - ice: Don't tell the OS that link is going down
+    - x86/xen: Distribute switch variables for initialization
+    - net: thunderx: workaround BGX TX Underflow issue
+    - csky/mm: Fixup export invalid_pte_table symbol
+    - csky: Set regs->usp to kernel sp, when the exception is from kernel
+    - csky/smp: Fixup boot failed when CONFIG_SMP
+    - csky: Fixup ftrace modify panic
+    - csky: Fixup compile warning for three unimplemented syscalls
+    - arch/csky: fix some Kconfig typos
+    - selftests: forwarding: vxlan_bridge_1d: use more proper tos value
+    - firmware: imx: scu: Ensure sequential TX
+    - binder: prevent UAF for binderfs devices
+    - binder: prevent UAF for binderfs devices II
+    - ALSA: hda/realtek - Add Headset Mic supported
+    - ALSA: hda/realtek - Add Headset Button supported for ThinkPad X1
+    - ALSA: hda/realtek - Fix silent output on Gigabyte X570 Aorus Master
+    - ALSA: hda/realtek - Enable the headset of ASUS B9450FA with ALC294
+    - cifs: don't leak -EAGAIN for stat() during reconnect
+    - cifs: fix rename() by ensuring source handle opened with DELETE bit
+    - usb: storage: Add quirk for Samsung Fit flash
+    - usb: quirks: add NO_LPM quirk for Logitech Screen Share
+    - usb: dwc3: gadget: Update chain bit correctly when using sg list
+    - usb: cdns3: gadget: link trb should point to next request
+    - usb: cdns3: gadget: toggle cycle bit before reset endpoint
+    - usb: core: hub: fix unhandled return by employing a void function
+    - usb: core: hub: do error out if usb_autopm_get_interface() fails
+    - usb: core: port: do error out if usb_autopm_get_interface() fails
+    - vgacon: Fix a UAF in vgacon_invert_region
+    - mm, numa: fix bad pmd by atomically check for pmd_trans_huge when marking
+      page tables prot_numa
+    - mm: fix possible PMD dirty bit lost in set_pmd_migration_entry()
+    - mm, hotplug: fix page online with DEBUG_PAGEALLOC compiled but not enabled
+    - fat: fix uninit-memory access for partial initialized inode
+    - btrfs: fix RAID direct I/O reads with alternate csums
+    - arm64: dts: socfpga: agilex: Fix gmac compatible
+    - arm: dts: dra76x: Fix mmc3 max-frequency
+    - tty:serial:mvebu-uart:fix a wrong return
+    - tty: serial: fsl_lpuart: free IDs allocated by IDA
+    - serial: 8250_exar: add support for ACCES cards
+    - vt: selection, close sel_buffer race
+    - vt: selection, push console lock down
+    - vt: selection, push sel_lock up
+    - media: hantro: Fix broken media controller links
+    - media: mc-entity.c: use & to check pad flags, not ==
+    - media: vicodec: process all 4 components for RGB32 formats
+    - media: v4l2-mem2mem.c: fix broken links
+    - perf intel-pt: Fix endless record after being terminated
+    - perf intel-bts: Fix endless record after being terminated
+    - perf cs-etm: Fix endless record after being terminated
+    - perf arm-spe: Fix endless record after being terminated
+    - spi: spidev: Fix CS polarity if GPIO descriptors are used
+    - x86/pkeys: Manually set X86_FEATURE_OSPKE to preserve existing changes
+    - s390/pci: Fix unexpected write combine on resource
+    - s390/mm: fix panic in gup_fast on large pud
+    - dmaengine: imx-sdma: fix context cache
+    - dmaengine: imx-sdma: Fix the event id check to include RX event for UART6
+    - dmaengine: tegra-apb: Fix use-after-free
+    - dmaengine: tegra-apb: Prevent race conditions of tasklet vs free list
+    - dm integrity: fix recalculation when moving from journal mode to bitmap mode
+    - dm integrity: fix a deadlock due to offloading to an incorrect workqueue
+    - dm integrity: fix invalid table returned due to argument count mismatch
+    - dm cache: fix a crash due to incorrect work item cancelling
+    - dm: report suspended device during destroy
+    - dm writecache: verify watermark during resume
+    - dm zoned: Fix reference counter initial value of chunk works
+    - dm: fix congested_fn for request-based device
+    - arm64: dts: meson-sm1-sei610: add missing interrupt-names
+    - ARM: dts: ls1021a: Restore MDIO compatible to gianfar
+    - spi: bcm63xx-hsspi: Really keep pll clk enabled
+    - drm/virtio: make resource id workaround runtime switchable.
+    - drm/virtio: fix resource id creation race
+    - ASoC: topology: Fix memleak in soc_tplg_link_elems_load()
+    - ASoC: topology: Fix memleak in soc_tplg_manifest_load()
+    - ASoC: SOF: Fix snd_sof_ipc_stream_posn()
+    - ASoC: intel: skl: Fix pin debug prints
+    - ASoC: intel: skl: Fix possible buffer overflow in debug outputs
+    - powerpc: define helpers to get L1 icache sizes
+    - powerpc: Convert flush_icache_range & friends to C
+    - powerpc/mm: Fix missing KUAP disable in flush_coherent_icache()
+    - ASoC: pcm: Fix possible buffer overflow in dpcm state sysfs output
+    - ASoC: pcm512x: Fix unbalanced regulator enable call in probe error path
+    - ASoC: Intel: Skylake: Fix available clock counter incrementation
+    - ASoC: dapm: Correct DAPM handling of active widgets during shutdown
+    - spi: atmel-quadspi: fix possible MMIO window size overrun
+    - drm/panfrost: Don't try to map on error faults
+    - drm: kirin: Revert "Fix for hikey620 display offset problem"
+    - drm/sun4i: Add separate DE3 VI layer formats
+    - drm/sun4i: Fix DE2 VI layer format support
+    - drm/sun4i: de2/de3: Remove unsupported VI layer formats
+    - drm/i915: Program MBUS with rmw during initialization
+    - drm/i915/selftests: Fix return in assert_mmap_offset()
+    - phy: mapphone-mdm6600: Fix timeouts by adding wake-up handling
+    - phy: mapphone-mdm6600: Fix write timeouts with shorter GPIO toggle interval
+    - ARM: dts: imx6: phycore-som: fix emmc supply
+    - arm64: dts: imx8qxp-mek: Remove unexisting Ethernet PHY
+    - firmware: imx: misc: Align imx sc msg structs to 4
+    - firmware: imx: scu-pd: Align imx sc msg structs to 4
+    - firmware: imx: Align imx_sc_msg_req_cpu_start to 4
+    - soc: imx-scu: Align imx sc msg structs to 4
+    - Revert "RDMA/cma: Simplify rdma_resolve_addr() error flow"
+    - RDMA/rw: Fix error flow during RDMA context initialization
+    - RDMA/nldev: Fix crash when set a QP to a new counter but QPN is missing
+    - RDMA/siw: Fix failure handling during device creation
+    - RDMA/iwcm: Fix iwcm work deallocation
+    - RDMA/core: Fix protection fault in ib_mr_pool_destroy
+    - regulator: stm32-vrefbuf: fix a possible overshoot when re-enabling
+    - RMDA/cm: Fix missing ib_cm_destroy_id() in ib_cm_insert_listen()
+    - IB/hfi1, qib: Ensure RCU is locked when accessing list
+    - ARM: imx: build v7_cpu_resume() unconditionally
+    - ARM: dts: am437x-idk-evm: Fix incorrect OPP node names
+    - ARM: dts: dra7xx-clocks: Fixup IPU1 mux clock parent source
+    - ARM: dts: imx7-colibri: Fix frequency for sd/mmc
+    - hwmon: (adt7462) Fix an error return in ADT7462_REG_VOLT()
+    - dma-buf: free dmabuf->name in dma_buf_release()
+    - dmaengine: coh901318: Fix a double lock bug in dma_tc_handle()
+    - arm64: dts: meson: fix gxm-khadas-vim2 wifi
+    - bus: ti-sysc: Fix 1-wire reset quirk
+    - EDAC/synopsys: Do not print an error with back-to-back snprintf() calls
+    - powerpc: fix hardware PMU exception bug on PowerVM compatibility mode
+      systems
+    - efi/x86: Align GUIDs to their size in the mixed mode runtime wrapper
+    - efi/x86: Handle by-ref arguments covering multiple pages in mixed mode
+    - efi: READ_ONCE rng seed size before munmap
+    - block, bfq: get a ref to a group when adding it to a service tree
+    - block, bfq: remove ifdefs from around gets/puts of bfq groups
+    - csky: Implement copy_thread_tls
+    - drm/virtio: module_param_named() requires linux/moduleparam.h
+    - Linux 5.4.25
+
+  * Miscellaneous Ubuntu changes
+    - hio -- remove duplicated MODULE_DEVICE_TABLE declaration
+    - [Config] Add initial riscv64 config
+    - [Config] Bring riscv64 in line with other arches
+    - [Packaging] Add riscv64 arch support
+    - [Packaging] Add initial riscv64 abi
+    - [Config] updateconfigs for riscv64
+    - [Config] Update annotations for riscv64
+    - SAUCE: r8169: disable ASPM L1.1
+    - update wireguard dkms package version
+    - [Config] garbage collect PCIEASPM_DEBUG
+    - [Config] gcc version updateconfigs
+
+  * Miscellaneous upstream changes
+    - Revert "UBUNTU: SAUCE: platform/x86: dell-uart-backlight: move retry block"
+    - RISC-V: Do not invoke SBI call if cpumask is empty
+    - RISC-V: Issue a local tlbflush if possible.
+    - RISC-V: Issue a tlb page flush if possible
+    - riscv: add support for SECCOMP and SECCOMP_FILTER
+    - riscv: reject invalid syscalls below -1
+    - mtd: spi-nor: Add support for is25wp256
+    - PCI/ASPM: Remove PCIEASPM_DEBUG Kconfig option and related code
+
+ -- Paolo Pisati <paolo.pisati@canonical.com>  Mon, 23 Mar 2020 13:03:48 +0100
+
+linux (5.4.0-18.22) focal; urgency=medium
+
+  * focal/linux: 5.4.0-18.22 -proposed tracker (LP: #1866488)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync getabis
+    - [Packaging] update helper scripts
+
+  * Add sysfs attribute to show remapped NVMe (LP: #1863621)
+    - SAUCE: ata: ahci: Add sysfs attribute to show remapped NVMe device count
+
+  * [20.04 FEAT] Compression improvements in Linux kernel (LP: #1830208)
+    - lib/zlib: add s390 hardware support for kernel zlib_deflate
+    - s390/boot: rename HEAP_SIZE due to name collision
+    - lib/zlib: add s390 hardware support for kernel zlib_inflate
+    - s390/boot: add dfltcc= kernel command line parameter
+    - lib/zlib: add zlib_deflate_dfltcc_enabled() function
+    - btrfs: use larger zlib buffer for s390 hardware compression
+    - [Config] Introducing s390x specific kernel config option CONFIG_ZLIB_DFLTCC
+
+  * [UBUNTU 20.04] s390x/pci: increase CONFIG_PCI_NR_FUNCTIONS to 512 in kernel
+    config (LP: #1866056)
+    - [Config] Increase CONFIG_PCI_NR_FUNCTIONS from 64 to 512 starting with focal
+      on s390x
+
+  * CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set (LP: #1865332)
+    - [Config] CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
+
+  * Dell XPS 13 9300 Intel 1650S wifi [34f0:1651] fails to load firmware
+    (LP: #1865962)
+    - iwlwifi: remove IWL_DEVICE_22560/IWL_DEVICE_FAMILY_22560
+    - iwlwifi: 22000: fix some indentation
+    - iwlwifi: pcie: rx: use rxq queue_size instead of constant
+    - iwlwifi: allocate more receive buffers for HE devices
+    - iwlwifi: remove some outdated iwl22000 configurations
+    - iwlwifi: assume the driver_data is a trans_cfg, but allow full cfg
+
+  * [FOCAL][REGRESSION] Intel Gen 9 brightness cannot be controlled
+    (LP: #1861521)
+    - Revert "USUNTU: SAUCE: drm/i915: Force DPCD backlight mode on Dell Precision
+      4K sku"
+    - Revert "UBUNTU: SAUCE: drm/i915: Force DPCD backlight mode on X1 Extreme 2nd
+      Gen 4K AMOLED panel"
+    - SAUCE: drm/dp: Introduce EDID-based quirks
+    - SAUCE: drm/i915: Force DPCD backlight mode on X1 Extreme 2nd Gen 4K AMOLED
+      panel
+    - SAUCE: drm/i915: Force DPCD backlight mode for some Dell CML 2020 panels
+
+  * [20.04 FEAT] Enable proper kprobes on ftrace support (LP: #1865858)
+    - s390/ftrace: save traced function caller
+    - s390: support KPROBES_ON_FTRACE
+
+  * alsa/sof: load different firmware on different platforms (LP: #1857409)
+    - ASoC: SOF: Intel: hda: use fallback for firmware name
+    - ASoC: Intel: acpi-match: split CNL tables in three
+    - ASoC: SOF: Intel: Fix CFL and CML FW nocodec binary names.
+
+  * [UBUNTU 20.04] Enable CONFIG_NET_SWITCHDEV in kernel config for s390x
+    starting with focal (LP: #1865452)
+    - [Config] Enable CONFIG_NET_SWITCHDEV in kernel config for s390x starting
+      with focal
+
+  * Focal update: v5.4.24 upstream stable release (LP: #1866333)
+    - io_uring: grab ->fs as part of async offload
+    - EDAC: skx_common: downgrade message importance on missing PCI device
+    - net: dsa: b53: Ensure the default VID is untagged
+    - net: fib_rules: Correctly set table field when table number exceeds 8 bits
+    - net: macb: ensure interface is not suspended on at91rm9200
+    - net: mscc: fix in frame extraction
+    - net: phy: restore mdio regs in the iproc mdio driver
+    - net: sched: correct flower port blocking
+    - net/tls: Fix to avoid gettig invalid tls record
+    - nfc: pn544: Fix occasional HW initialization failure
+    - qede: Fix race between rdma destroy workqueue and link change event
+    - Revert "net: dev: introduce support for sch BYPASS for lockless qdisc"
+    - udp: rehash on disconnect
+    - sctp: move the format error check out of __sctp_sf_do_9_1_abort
+    - bnxt_en: Improve device shutdown method.
+    - bnxt_en: Issue PCIe FLR in kdump kernel to cleanup pending DMAs.
+    - bonding: add missing netdev_update_lockdep_key()
+    - net: export netdev_next_lower_dev_rcu()
+    - bonding: fix lockdep warning in bond_get_stats()
+    - ipv6: Fix route replacement with dev-only route
+    - ipv6: Fix nlmsg_flags when splitting a multipath route
+    - ipmi:ssif: Handle a possible NULL pointer reference
+    - drm/msm: Set dma maximum segment size for mdss
+    - sched/core: Don't skip remote tick for idle CPUs
+    - timers/nohz: Update NOHZ load in remote tick
+    - sched/fair: Prevent unlimited runtime on throttled group
+    - dax: pass NOWAIT flag to iomap_apply
+    - mac80211: consider more elements in parsing CRC
+    - cfg80211: check wiphy driver existence for drvinfo report
+    - s390/zcrypt: fix card and queue total counter wrap
+    - qmi_wwan: re-add DW5821e pre-production variant
+    - qmi_wwan: unconditionally reject 2 ep interfaces
+    - NFSv4: Fix races between open and dentry revalidation
+    - perf/smmuv3: Use platform_get_irq_optional() for wired interrupt
+    - perf/x86/intel: Add Elkhart Lake support
+    - perf/x86/cstate: Add Tremont support
+    - perf/x86/msr: Add Tremont support
+    - ceph: do not execute direct write in parallel if O_APPEND is specified
+    - ARM: dts: sti: fixup sound frame-inversion for stihxxx-b2120.dtsi
+    - drm/amd/display: Do not set optimized_require to false after plane disable
+    - RDMA/siw: Remove unwanted WARN_ON in siw_cm_llp_data_ready()
+    - drm/amd/display: Check engine is not NULL before acquiring
+    - drm/amd/display: Limit minimum DPPCLK to 100MHz.
+    - drm/amd/display: Add initialitions for PLL2 clock source
+    - amdgpu: Prevent build errors regarding soft/hard-float FP ABI tags
+    - soc/tegra: fuse: Fix build with Tegra194 configuration
+    - i40e: Fix the conditional for i40e_vc_validate_vqs_bitmaps
+    - net: ena: fix potential crash when rxfh key is NULL
+    - net: ena: fix uses of round_jiffies()
+    - net: ena: add missing ethtool TX timestamping indication
+    - net: ena: fix incorrect default RSS key
+    - net: ena: rss: do not allocate key when not supported
+    - net: ena: rss: fix failure to get indirection table
+    - net: ena: rss: store hash function as values and not bits
+    - net: ena: fix incorrectly saving queue numbers when setting RSS indirection
+      table
+    - net: ena: fix corruption of dev_idx_to_host_tbl
+    - net: ena: ethtool: use correct value for crc32 hash
+    - net: ena: ena-com.c: prevent NULL pointer dereference
+    - ice: update Unit Load Status bitmask to check after reset
+    - cifs: Fix mode output in debugging statements
+    - cfg80211: add missing policy for NL80211_ATTR_STATUS_CODE
+    - mac80211: fix wrong 160/80+80 MHz setting
+    - nvme/tcp: fix bug on double requeue when send fails
+    - nvme: prevent warning triggered by nvme_stop_keep_alive
+    - nvme/pci: move cqe check after device shutdown
+    - ext4: potential crash on allocation error in ext4_alloc_flex_bg_array()
+    - audit: fix error handling in audit_data_to_entry()
+    - audit: always check the netlink payload length in audit_receive_msg()
+    - ACPICA: Introduce ACPI_ACCESS_BYTE_WIDTH() macro
+    - ACPI: watchdog: Fix gas->access_width usage
+    - KVM: VMX: check descriptor table exits on instruction emulation
+    - HID: ite: Only bind to keyboard USB interface on Acer SW5-012 keyboard dock
+    - HID: core: fix off-by-one memset in hid_report_raw_event()
+    - HID: core: increase HID report buffer size to 8KiB
+    - drm/amdgpu: Drop DRIVER_USE_AGP
+    - drm/radeon: Inline drm_get_pci_dev
+    - macintosh: therm_windtunnel: fix regression when instantiating devices
+    - tracing: Disable trace_printk() on post poned tests
+    - Revert "PM / devfreq: Modify the device name as devfreq(X) for sysfs"
+    - amdgpu/gmc_v9: save/restore sdpif regs during S3
+    - cpufreq: Fix policy initialization for internal governor drivers
+    - io_uring: fix 32-bit compatability with sendmsg/recvmsg
+    - netfilter: ipset: Fix "INFO: rcu detected stall in hash_xxx" reports
+    - net/smc: transfer fasync_list in case of fallback
+    - vhost: Check docket sk_family instead of call getname
+    - netfilter: ipset: Fix forceadd evaluation path
+    - netfilter: xt_hashlimit: reduce hashlimit_mutex scope for htable_put()
+    - HID: alps: Fix an error handling path in 'alps_input_configured()'
+    - HID: hiddev: Fix race in in hiddev_disconnect()
+    - MIPS: VPE: Fix a double free and a memory leak in 'release_vpe()'
+    - i2c: altera: Fix potential integer overflow
+    - i2c: jz4780: silence log flood on txabrt
+    - drm/i915/gvt: Fix orphan vgpu dmabuf_objs' lifetime
+    - drm/i915/gvt: Separate display reset from ALL_ENGINES reset
+    - nl80211: fix potential leak in AP start
+    - mac80211: Remove a redundant mutex unlock
+    - kbuild: fix DT binding schema rule to detect command line changes
+    - hv_netvsc: Fix unwanted wakeup in netvsc_attach()
+    - usb: charger: assign specific number for enum value
+    - nvme-pci: Hold cq_poll_lock while completing CQEs
+    - s390/qeth: vnicc Fix EOPNOTSUPP precedence
+    - net: netlink: cap max groups which will be considered in netlink_bind()
+    - net: atlantic: fix use after free kasan warn
+    - net: atlantic: fix potential error handling
+    - net: atlantic: fix out of range usage of active_vlans array
+    - net/smc: no peer ID in CLC decline for SMCD
+    - net: ena: make ena rxfh support ETH_RSS_HASH_NO_CHANGE
+    - selftests: Install settings files to fix TIMEOUT failures
+    - kbuild: remove header compile test
+    - kbuild: move headers_check rule to usr/include/Makefile
+    - kbuild: remove unneeded variable, single-all
+    - kbuild: make single target builds even faster
+    - namei: only return -ECHILD from follow_dotdot_rcu()
+    - mwifiex: drop most magic numbers from mwifiex_process_tdls_action_frame()
+    - mwifiex: delete unused mwifiex_get_intf_num()
+    - KVM: SVM: Override default MMIO mask if memory encryption is enabled
+    - KVM: Check for a bad hva before dropping into the ghc slow path
+    - sched/fair: Optimize select_idle_cpu
+    - f2fs: fix to add swap extent correctly
+    - RDMA/hns: Simplify the calculation and usage of wqe idx for post verbs
+    - RDMA/hns: Bugfix for posting a wqe with sge
+    - drivers: net: xgene: Fix the order of the arguments of
+      'alloc_etherdev_mqs()'
+    - ima: ima/lsm policy rule loading logic bug fixes
+    - kprobes: Set unoptimized flag after unoptimizing code
+    - lib/vdso: Make __arch_update_vdso_data() logic understandable
+    - lib/vdso: Update coarse timekeeper unconditionally
+    - pwm: omap-dmtimer: put_device() after of_find_device_by_node()
+    - perf hists browser: Restore ESC as "Zoom out" of DSO/thread/etc
+    - perf ui gtk: Add missing zalloc object
+    - x86/resctrl: Check monitoring static key in the MBM overflow handler
+    - KVM: x86: Remove spurious kvm_mmu_unload() from vcpu destruction path
+    - KVM: x86: Remove spurious clearing of async #PF MSR
+    - rcu: Allow only one expedited GP to run concurrently with wakeups
+    - ubifs: Fix ino_t format warnings in orphan_delete()
+    - thermal: db8500: Depromote debug print
+    - thermal: brcmstb_thermal: Do not use DT coefficients
+    - netfilter: nft_tunnel: no need to call htons() when dumping ports
+    - netfilter: nf_flowtable: fix documentation
+    - bus: tegra-aconnect: Remove PM_CLK dependency
+    - xfs: clear kernel only flags in XFS_IOC_ATTRMULTI_BY_HANDLE
+    - locking/lockdep: Fix lockdep_stats indentation problem
+    - mm/debug.c: always print flags in dump_page()
+    - mm/gup: allow FOLL_FORCE for get_user_pages_fast()
+    - mm/huge_memory.c: use head to check huge zero page
+    - mm, thp: fix defrag setting if newline is not used
+    - kvm: nVMX: VMWRITE checks VMCS-link pointer before VMCS field
+    - kvm: nVMX: VMWRITE checks unsupported field before read-only field
+    - blktrace: Protect q->blk_trace with RCU
+    - Linux 5.4.24
+
+  * Focal update: v5.4.23 upstream stable release (LP: #1866165)
+    - iommu/qcom: Fix bogus detach logic
+    - ALSA: hda: Use scnprintf() for printing texts for sysfs/procfs
+    - ALSA: hda/realtek - Apply quirk for MSI GP63, too
+    - ALSA: hda/realtek - Apply quirk for yet another MSI laptop
+    - ASoC: codec2codec: avoid invalid/double-free of pcm runtime
+    - ASoC: sun8i-codec: Fix setting DAI data format
+    - tpm: Initialize crypto_id of allocated_banks to HASH_ALGO__LAST
+    - ecryptfs: fix a memory leak bug in parse_tag_1_packet()
+    - ecryptfs: fix a memory leak bug in ecryptfs_init_messaging()
+    - btrfs: handle logged extent failure properly
+    - thunderbolt: Prevent crash if non-active NVMem file is read
+    - USB: misc: iowarrior: add support for 2 OEMed devices
+    - USB: misc: iowarrior: add support for the 28 and 28L devices
+    - USB: misc: iowarrior: add support for the 100 device
+    - e1000e: Use rtnl_lock to prevent race conditions between net and pci/pm
+    - floppy: check FDC index for errors before assigning it
+    - vt: fix scrollback flushing on background consoles
+    - vt: selection, handle pending signals in paste_selection
+    - vt: vt_ioctl: fix race in VT_RESIZEX
+    - staging: android: ashmem: Disallow ashmem memory from being remapped
+    - staging: vt6656: fix sign of rx_dbm to bb_pre_ed_rssi.
+    - xhci: Force Maximum Packet size for Full-speed bulk devices to valid range.
+    - xhci: fix runtime pm enabling for quirky Intel hosts
+    - xhci: apply XHCI_PME_STUCK_QUIRK to Intel Comet Lake platforms
+    - xhci: Fix memory leak when caching protocol extended capability PSI tables -
+      take 2
+    - usb: host: xhci: update event ring dequeue pointer on purpose
+    - USB: core: add endpoint-blacklist quirk
+    - USB: quirks: blacklist duplicate ep on Sound Devices USBPre2
+    - usb: uas: fix a plug & unplug racing
+    - USB: Fix novation SourceControl XL after suspend
+    - USB: hub: Don't record a connect-change event during reset-resume
+    - USB: hub: Fix the broken detection of USB3 device in SMSC hub
+    - usb: dwc2: Fix SET/CLEAR_FEATURE and GET_STATUS flows
+    - usb: dwc3: gadget: Check for IOC/LST bit in TRB->ctrl fields
+    - usb: dwc3: debug: fix string position formatting mixup with ret and len
+    - scsi: Revert "target/core: Inline transport_lun_remove_cmd()"
+    - staging: rtl8188eu: Fix potential security hole
+    - staging: rtl8188eu: Fix potential overuse of kernel memory
+    - staging: rtl8723bs: Fix potential security hole
+    - staging: rtl8723bs: Fix potential overuse of kernel memory
+    - drm/panfrost: perfcnt: Reserve/use the AS attached to the perfcnt MMU
+      context
+    - powerpc/8xx: Fix clearing of bits 20-23 in ITLB miss
+    - powerpc/eeh: Fix deadlock handling dead PHB
+    - powerpc/tm: Fix clearing MSR[TS] in current when reclaiming on signal
+      delivery
+    - powerpc/entry: Fix an #if which should be an #ifdef in entry_32.S
+    - powerpc/hugetlb: Fix 512k hugepages on 8xx with 16k page size
+    - powerpc/hugetlb: Fix 8M hugepages on 8xx
+    - arm64: memory: Add missing brackets to untagged_addr() macro
+    - jbd2: fix ocfs2 corrupt when clearing block group bits
+    - x86/ima: use correct identifier for SetupMode variable
+    - x86/mce/amd: Publish the bank pointer only after setup has succeeded
+    - x86/mce/amd: Fix kobject lifetime
+    - x86/cpu/amd: Enable the fixed Instructions Retired counter IRPERF
+    - serial: 8250: Check UPF_IRQ_SHARED in advance
+    - tty/serial: atmel: manage shutdown in case of RS485 or ISO7816 mode
+    - tty: serial: imx: setup the correct sg entry for tx dma
+    - tty: serial: qcom_geni_serial: Fix RX cancel command failure
+    - serdev: ttyport: restore client ops on deregistration
+    - MAINTAINERS: Update drm/i915 bug filing URL
+    - ACPI: PM: s2idle: Check fixed wakeup events in acpi_s2idle_wake()
+    - mm/memcontrol.c: lost css_put in memcg_expand_shrinker_maps()
+    - nvme-multipath: Fix memory leak with ana_log_buf
+    - genirq/irqdomain: Make sure all irq domain flags are distinct
+    - mm/vmscan.c: don't round up scan size for online memory cgroup
+    - mm/sparsemem: pfn_to_page is not valid yet on SPARSEMEM
+    - lib/stackdepot.c: fix global out-of-bounds in stack_slabs
+    - mm: Avoid creating virtual address aliases in brk()/mmap()/mremap()
+    - drm/amdgpu/soc15: fix xclk for raven
+    - drm/amdgpu/gfx9: disable gfxoff when reading rlc clock
+    - drm/amdgpu/gfx10: disable gfxoff when reading rlc clock
+    - drm/nouveau/kms/gv100-: Re-set LUT after clearing for modesets
+    - drm/i915: Wean off drm_pci_alloc/drm_pci_free
+    - drm/i915: Update drm/i915 bug filing URL
+    - sched/psi: Fix OOB write when writing 0 bytes to PSI files
+    - KVM: nVMX: Don't emulate instructions in guest mode
+    - KVM: x86: don't notify userspace IOAPIC on edge-triggered interrupt EOI
+    - ext4: fix a data race in EXT4_I(inode)->i_disksize
+    - ext4: add cond_resched() to __ext4_find_entry()
+    - ext4: fix potential race between online resizing and write operations
+    - ext4: fix potential race between s_group_info online resizing and access
+    - ext4: fix potential race between s_flex_groups online resizing and access
+    - ext4: fix mount failure with quota configured as module
+    - ext4: rename s_journal_flag_rwsem to s_writepages_rwsem
+    - ext4: fix race between writepages and enabling EXT4_EXTENTS_FL
+    - KVM: nVMX: Refactor IO bitmap checks into helper function
+    - KVM: nVMX: Check IO instruction VM-exit conditions
+    - KVM: nVMX: clear PIN_BASED_POSTED_INTR from nested pinbased_ctls only when
+      apicv is globally disabled
+    - KVM: nVMX: handle nested posted interrupts when apicv is disabled for L1
+    - KVM: apic: avoid calculating pending eoi from an uninitialized val
+    - btrfs: destroy qgroup extent records on transaction abort
+    - btrfs: fix bytes_may_use underflow in prealloc error condtition
+    - btrfs: reset fs_root to NULL on error in open_ctree
+    - btrfs: do not check delayed items are empty for single transaction cleanup
+    - Btrfs: fix btrfs_wait_ordered_range() so that it waits for all ordered
+      extents
+    - Btrfs: fix race between shrinking truncate and fiemap
+    - btrfs: don't set path->leave_spinning for truncate
+    - Btrfs: fix deadlock during fast fsync when logging prealloc extents beyond
+      eof
+    - Revert "dmaengine: imx-sdma: Fix memory leak"
+    - drm/i915/gvt: more locking for ppgtt mm LRU list
+    - drm/bridge: tc358767: fix poll timeouts
+    - drm/i915/gt: Protect defer_request() from new waiters
+    - drm/msm/dpu: fix BGR565 vs RGB565 confusion
+    - scsi: Revert "RDMA/isert: Fix a recently introduced regression related to
+      logout"
+    - scsi: Revert "target: iscsi: Wait for all commands to finish before freeing
+      a session"
+    - usb: gadget: composite: Fix bMaxPower for SuperSpeedPlus
+    - usb: dwc2: Fix in ISOC request length checking
+    - staging: rtl8723bs: fix copy of overlapping memory
+    - staging: greybus: use after free in gb_audio_manager_remove_all()
+    - ASoC: atmel: fix atmel_ssc_set_audio link failure
+    - ASoC: fsl_sai: Fix exiting path on probing failure
+    - ecryptfs: replace BUG_ON with error handling code
+    - iommu/vt-d: Fix compile warning from intel-svm.h
+    - crypto: rename sm3-256 to sm3 in hash_algo_name
+    - genirq/proc: Reject invalid affinity masks (again)
+    - bpf, offload: Replace bitwise AND by logical AND in
+      bpf_prog_offload_info_fill
+    - arm64: lse: Fix LSE atomics with LLVM
+    - io_uring: fix __io_iopoll_check deadlock in io_sq_thread
+    - ALSA: rawmidi: Avoid bit fields for state flags
+    - ALSA: seq: Avoid concurrent access to queue flags
+    - ALSA: seq: Fix concurrent access to queue current tick/time
+    - netfilter: xt_hashlimit: limit the max size of hashtable
+    - rxrpc: Fix call RCU cleanup using non-bh-safe locks
+    - io_uring: prevent sq_thread from spinning when it should stop
+    - ata: ahci: Add shutdown to freeze hardware resources of ahci
+    - xen: Enable interrupts when calling _cond_resched()
+    - net/mlx5e: Reset RQ doorbell counter before moving RQ state from RST to RDY
+    - net/mlx5: Fix sleep while atomic in mlx5_eswitch_get_vepa
+    - net/mlx5e: Fix crash in recovery flow without devlink reporter
+    - s390/kaslr: Fix casts in get_random
+    - s390/mm: Explicitly compare PAGE_DEFAULT_KEY against zero in
+      storage_key_init_range
+    - bpf: Selftests build error in sockmap_basic.c
+    - ASoC: SOF: Intel: hda: Add iDisp4 DAI
+    - Linux 5.4.23
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: selftests/net -- disable timeout
+    - SAUCE: selftests/net -- disable l2tp.sh test
+    - SAUCE: selftests/ftrace: Use printf instead of echo in kprobe syntax error
+      tests
+    - SAUCE: selftests/powerpc -- Disable timeout for benchmark and tm tests
+    - SAUCE: selftests/ftrace: Escape additional strings in kprobe syntax error
+      tests
+    - SAUCE: Revert "UBUNTU: SAUCE: blk/core: Gracefully handle unset
+      make_request_fn"
+    - [Packaging] prevent duplicated entries in modules.ignore
+    - update dkms package versions
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Sat, 07 Mar 2020 10:23:40 -0600
+
+linux (5.4.0-17.21) focal; urgency=medium
+
+  * focal/linux: 5.4.0-17.20 -proposed tracker (LP: #1865025)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update helper scripts
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: drm/i915/execlists: fix off by one in execlists_update_context()
+
+ -- Andrea Righi <andrea.righi@canonical.com>  Thu, 27 Feb 2020 14:29:02 +0100
+
+linux (5.4.0-16.19) focal; urgency=medium
+
+  * focal/linux: 5.4.0-16.19 -proposed tracker (LP: #1864889)
+
+  * system hang: i915 Resetting rcs0 for hang on rcs0 (LP: #1861395)
+    - drm/i915/execlists: Always force a context reload when rewinding RING_TAIL
+
+  * nsleep-lat / set-timer-lat / inconsistency-check / raw_skew from timer in
+    ubuntu_kernel_selftests timeout on 5.3 / 5.4 (LP: #1864626)
+    - selftests/timers: Turn off timeout setting
+
+  * [sfc-0121]enable the HiSilicon v3xx SFC driver (LP: #1860401)
+    - spi: Add HiSilicon v3xx SPI NOR flash controller driver
+    - MAINTAINERS: Add a maintainer for the HiSilicon v3xx SFC driver
+    - [Config] CONFIG_SPI_HISI_SFC_V3XX=m
+
+  * [hns3-0217]sync mainline kernel 5.6rc1 hns3 patchset into ubuntu HWE kernel
+    branch (LP: #1863575)
+    - net: hns3: add management table after IMP reset
+    - net: hns3: fix VF bandwidth does not take effect in some case
+    - net: hns3: fix a copying IPv6 address error in hclge_fd_get_flow_tuples()
+
+  * [hns3-0111]sync mainline kernel 5.5rc6 hns3 patchset into ubuntu HWE kernel
+    branch Edit (LP: #1859261)
+    - net: hns3: schedule hclgevf_service by using delayed workqueue
+    - net: hns3: remove mailbox and reset work in hclge_main
+    - net: hns3: remove unnecessary work in hclgevf_main
+    - net: hns3: allocate WQ with WQ_MEM_RECLAIM flag
+    - net: hns3: do not schedule the periodic task when reset fail
+    - net: hns3: check FE bit before calling hns3_add_frag()
+    - net: hns3: remove useless mutex vport_cfg_mutex in the struct hclge_dev
+    - net: hns3: optimization for CMDQ uninitialization
+    - net: hns3: get FD rules location before dump in debugfs
+    - net: hns3: implement ndo_features_check ops for hns3 driver
+    - net: hns3: add some VF VLAN information for command "ip link show"
+    - net: hns3: add a log for getting chain failure in
+      hns3_nic_uninit_vector_data()
+    - net: hns3: only print misc interrupt status when handling fails
+    - net: hns3: add trace event support for HNS3 driver
+    - net: hns3: re-organize vector handle
+    - net: hns3: modify the IRQ name of TQP vector
+    - net: hns3: modify an unsuitable log in hclge_map_ring_to_vector()
+    - net: hns3: modify the IRQ name of misc vectors
+    - net: hns3: add protection when get SFP speed as 0
+    - net: hns3: replace an unsuitable variable type in
+      hclge_inform_reset_assert_to_vf()
+    - net: hns3: modify an unsuitable reset level for hardware error
+    - net: hns3: split hclge_reset() into preparing and rebuilding part
+    - net: hns3: split hclgevf_reset() into preparing and rebuilding part
+    - net: hns3: refactor the precedure of PF FLR
+    - net: hns3: refactor the procedure of VF FLR
+    - net: hns3: enlarge HCLGE_RESET_WAIT_CNT
+    - net: hns3: modify hclge_func_reset_sync_vf()'s return type to void
+    - net: hns3: refactor the notification scheme of PF reset
+
+  * alsa/hda/realtek: fix a mute led regression on Lenovo X1 Carbon
+    (LP: #1864576)
+    - SAUCE: ALSA: hda/realtek - Fix a regression for mute led on Lenovo Carbon X1
+
+  * ipc/sem.c : process loops infinitely in exit_sem() (LP: #1858834)
+    - Revert "ipc, sem: remove uneeded sem_undo_list lock usage in exit_sem()"
+
+  * r8152 init may take up to 40 seconds at initialization with Dell WD19/WD19DC
+    during hotplug (LP: #1864284)
+    - UBUNTU SAUCE: r8151: check disconnect status after long sleep
+
+  * Update kernel options CONFIG_NR_CPUS and CONFIG_NUMA_EMU for focal
+    (LP: #1864198)
+    - Ubuntu: [Config] Update kernel options CONFIG_NR_CPUS and CONFIG_NUMA_EMU
+
+  * ftrace test in ubuntu_kernel_selftests will timeout randomly (LP: #1864172)
+    - tracing/selftests: Turn off timeout setting
+
+  * Another Dell AIO backlight issue (LP: #1863880)
+    - SAUCE: platform/x86: dell-uart-backlight: move retry block
+
+  * Backport GetFB2 ioctl (LP: #1863874)
+    - SAUCE: drm: Add getfb2 ioctl
+
+  * [20.04] Allow to reset an opencapi adapter (LP: #1862121)
+    - powerpc/powernv/ioda: Fix ref count for devices with their own PE
+    - powerpc/powernv/ioda: Protect PE list
+    - powerpc/powernv/ioda: set up PE on opencapi device when enabling
+    - powerpc/powernv/ioda: Release opencapi device
+    - powerpc/powernv/ioda: Find opencapi slot for a device node
+    - pci/hotplug/pnv-php: Remove erroneous warning
+    - pci/hotplug/pnv-php: Improve error msg on power state change failure
+    - pci/hotplug/pnv-php: Register opencapi slots
+    - pci/hotplug/pnv-php: Relax check when disabling slot
+    - pci/hotplug/pnv-php: Wrap warnings in macro
+    - ocxl: Add PCI hotplug dependency to Kconfig
+
+  * alsa/asoc: export the number of dmic to userspace to work with the latest
+    ucm2 (focal) (LP: #1864400)
+    - ASoC: add control components management
+    - ASoC: intel/skl/hda - export number of digital microphones via control
+      components
+
+  * alsa/sof: let sof driver work with topology with volume and led control
+    (focal) (LP: #1864398)
+    - ASoC: SOF: enable dual control for pga
+    - AsoC: SOF: refactor control load code
+    - ASoC: SOF: acpi led support for switch controls
+    - ASoC: SOF: topology: check errors when parsing LED tokens
+
+  * machine doesn't come up after suspend and re-opening the lid (LP: #1861837)
+    - ASoC: SOF: trace: fix unconditional free in trace release
+
+  * 5.3.0-23-generic causes fans to spin when idle (LP: #1853044)
+    - drm/i915/gt: Close race between engine_park and intel_gt_retire_requests
+    - drm/i915/gt: Adapt engine_park synchronisation rules for engine_retire
+    - drm/i915/gt: Schedule request retirement when timeline idles
+
+  * Focal update: 5.4.22 upstream stable release (LP: #1864488)
+    - core: Don't skip generic XDP program execution for cloned SKBs
+    - enic: prevent waking up stopped tx queues over watchdog reset
+    - net/smc: fix leak of kernel memory to user space
+    - net: dsa: tag_qca: Make sure there is headroom for tag
+    - net/sched: matchall: add missing validation of TCA_MATCHALL_FLAGS
+    - net/sched: flower: add missing validation of TCA_FLOWER_FLAGS
+    - drm/gma500: Fixup fbdev stolen size usage evaluation
+    - ath10k: Fix qmi init error handling
+    - wil6210: fix break that is never reached because of zero'ing of a retry
+      counter
+    - drm/qxl: Complete exception handling in qxl_device_init()
+    - rcu/nocb: Fix dump_tree hierarchy print always active
+    - rcu: Fix missed wakeup of exp_wq waiters
+    - rcu: Fix data-race due to atomic_t copy-by-value
+    - f2fs: preallocate DIO blocks when forcing buffered_io
+    - f2fs: call f2fs_balance_fs outside of locked page
+    - media: meson: add missing allocation failure check on new_buf
+    - clk: meson: pll: Fix by 0 division in __pll_params_to_rate()
+    - cpu/hotplug, stop_machine: Fix stop_machine vs hotplug order
+    - brcmfmac: Fix memory leak in brcmf_p2p_create_p2pdev()
+    - brcmfmac: Fix use after free in brcmf_sdio_readframes()
+    - PCI: Fix pci_add_dma_alias() bitmask size
+    - drm/amd/display: Map ODM memory correctly when doing ODM combine
+    - leds: pca963x: Fix open-drain initialization
+    - ext4: fix ext4_dax_read/write inode locking sequence for IOCB_NOWAIT
+    - ALSA: ctl: allow TLV read operation for callback type of element in locked
+      case
+    - gianfar: Fix TX timestamping with a stacked DSA driver
+    - pinctrl: sh-pfc: sh7264: Fix CAN function GPIOs
+    - printk: fix exclusive_console replaying
+    - drm/mipi_dbi: Fix off-by-one bugs in mipi_dbi_blank()
+    - drm/msm/adreno: fix zap vs no-zap handling
+    - pxa168fb: Fix the function used to release some memory in an error handling
+      path
+    - media: ov5640: Fix check for PLL1 exceeding max allowed rate
+    - media: i2c: mt9v032: fix enum mbus codes and frame sizes
+    - media: sun4i-csi: Deal with DRAM offset
+    - media: sun4i-csi: Fix data sampling polarity handling
+    - media: sun4i-csi: Fix [HV]sync polarity handling
+    - clk: at91: sam9x60: fix programmable clock prescaler
+    - powerpc/powernv/iov: Ensure the pdn for VFs always contains a valid PE
+      number
+    - clk: meson: meson8b: make the CCF use the glitch-free mali mux
+    - gpio: gpio-grgpio: fix possible sleep-in-atomic-context bugs in
+      grgpio_irq_map/unmap()
+    - iommu/vt-d: Fix off-by-one in PASID allocation
+    - x86/fpu: Deactivate FPU state after failure during state load
+    - char/random: silence a lockdep splat with printk()
+    - media: sti: bdisp: fix a possible sleep-in-atomic-context bug in
+      bdisp_device_run()
+    - kernel/module: Fix memleak in module_add_modinfo_attrs()
+    - IB/core: Let IB core distribute cache update events
+    - pinctrl: baytrail: Do not clear IRQ flags on direct-irq enabled pins
+    - efi/x86: Map the entire EFI vendor string before copying it
+    - MIPS: Loongson: Fix potential NULL dereference in loongson3_platform_init()
+    - sparc: Add .exit.data section.
+    - net: ethernet: ixp4xx: Standard module init
+    - raid6/test: fix a compilation error
+    - uio: fix a sleep-in-atomic-context bug in uio_dmem_genirq_irqcontrol()
+    - drm/amdgpu/sriov: workaround on rev_id for Navi12 under sriov
+    - spi: fsl-lpspi: fix only one cs-gpio working
+    - drm/nouveau/nouveau: fix incorrect sizeof on args.src an args.dst
+    - usb: gadget: udc: fix possible sleep-in-atomic-context bugs in gr_probe()
+    - usb: dwc2: Fix IN FIFO allocation
+    - clocksource/drivers/bcm2835_timer: Fix memory leak of timer
+    - drm/amd/display: Clear state after exiting fixed active VRR state
+    - kselftest: Minimise dependency of get_size on C library interfaces
+    - jbd2: clear JBD2_ABORT flag before journal_reset to update log tail info
+      when load journal
+    - ext4: fix deadlock allocating bio_post_read_ctx from mempool
+    - clk: ti: dra7: fix parent for gmac_clkctrl
+    - x86/sysfb: Fix check for bad VRAM size
+    - pwm: omap-dmtimer: Simplify error handling
+    - udf: Allow writing to 'Rewritable' partitions
+    - dmaengine: fsl-qdma: fix duplicated argument to &&
+    - wan/hdlc_x25: fix skb handling
+    - powerpc/iov: Move VF pdev fixup into pcibios_fixup_iov()
+    - tracing: Fix tracing_stat return values in error handling paths
+    - tracing: Fix very unlikely race of registering two stat tracers
+    - ARM: 8952/1: Disable kmemleak on XIP kernels
+    - ext4, jbd2: ensure panic when aborting with zero errno
+    - ath10k: Correct the DMA direction for management tx buffers
+    - rtw88: fix rate mask for 1SS chip
+    - brcmfmac: sdio: Fix OOB interrupt initialization on brcm43362
+    - selftests: settings: tests can be in subsubdirs
+    - rtc: i2c/spi: Avoid inclusion of REGMAP support when not needed
+    - drm/amd/display: Retrain dongles when SINK_COUNT becomes non-zero
+    - tracing: Simplify assignment parsing for hist triggers
+    - nbd: add a flush_workqueue in nbd_start_device
+    - KVM: s390: ENOTSUPP -> EOPNOTSUPP fixups
+    - Btrfs: keep pages dirty when using btrfs_writepage_fixup_worker
+    - drivers/block/zram/zram_drv.c: fix error return codes not being returned in
+      writeback_store
+    - block, bfq: do not plug I/O for bfq_queues with no proc refs
+    - kconfig: fix broken dependency in randconfig-generated .config
+    - clk: qcom: Don't overwrite 'cfg' in clk_rcg2_dfs_populate_freq()
+    - clk: qcom: rcg2: Don't crash if our parent can't be found; return an error
+    - drm/amdkfd: Fix a bug in SDMA RLC queue counting under HWS mode
+    - bpf, sockhash: Synchronize_rcu before free'ing map
+    - drm/amdgpu: remove 4 set but not used variable in
+      amdgpu_atombios_get_connector_info_from_object_table
+    - ath10k: correct the tlv len of ath10k_wmi_tlv_op_gen_config_pno_start
+    - drm/amdgpu: Ensure ret is always initialized when using SOC15_WAIT_ON_RREG
+    - drm/panel: simple: Add Logic PD Type 28 display support
+    - arm64: dts: rockchip: Fix NanoPC-T4 cooling maps
+    - modules: lockdep: Suppress suspicious RCU usage warning
+    - ASoC: intel: sof_rt5682: Add quirk for number of HDMI DAI's
+    - ASoC: intel: sof_rt5682: Add support for tgl-max98357a-rt5682
+    - regulator: rk808: Lower log level on optional GPIOs being not available
+    - net/wan/fsl_ucc_hdlc: reject muram offsets above 64K
+    - NFC: port100: Convert cpu_to_le16(le16_to_cpu(E1) + E2) to use
+      le16_add_cpu().
+    - arm64: dts: allwinner: H6: Add PMU mode
+    - arm64: dts: allwinner: H5: Add PMU node
+    - arm: dts: allwinner: H3: Add PMU node
+    - opp: Free static OPPs on errors while adding them
+    - selinux: ensure we cleanup the internal AVC counters on error in
+      avc_insert()
+    - arm64: dts: qcom: msm8996: Disable USB2 PHY suspend by core
+    - padata: validate cpumask without removed CPU during offline
+    - clk: imx: Add correct failure handling for clk based helpers
+    - ARM: exynos_defconfig: Bring back explicitly wanted options
+    - ARM: dts: imx6: rdu2: Disable WP for USDHC2 and USDHC3
+    - ARM: dts: imx6: rdu2: Limit USBH1 to Full Speed
+    - bus: ti-sysc: Implement quirk handling for CLKDM_NOAUTO
+    - PCI: iproc: Apply quirk_paxc_bridge() for module as well as built-in
+    - media: cx23885: Add support for AVerMedia CE310B
+    - PCI: Add generic quirk for increasing D3hot delay
+    - PCI: Increase D3 delay for AMD Ryzen5/7 XHCI controllers
+    - gpu/drm: ingenic: Avoid null pointer deference in plane atomic update
+    - selftests/net: make so_txtime more robust to timer variance
+    - media: v4l2-device.h: Explicitly compare grp{id,mask} to zero in v4l2_device
+      macros
+    - reiserfs: Fix spurious unlock in reiserfs_fill_super() error handling
+    - samples/bpf: Set -fno-stack-protector when building BPF programs
+    - r8169: check that Realtek PHY driver module is loaded
+    - fore200e: Fix incorrect checks of NULL pointer dereference
+    - netfilter: nft_tunnel: add the missing ERSPAN_VERSION nla_policy
+    - ALSA: usx2y: Adjust indentation in snd_usX2Y_hwdep_dsp_status
+    - PCI: Add nr_devfns parameter to pci_add_dma_alias()
+    - PCI: Add DMA alias quirk for PLX PEX NTB
+    - b43legacy: Fix -Wcast-function-type
+    - ipw2x00: Fix -Wcast-function-type
+    - iwlegacy: Fix -Wcast-function-type
+    - rtlwifi: rtl_pci: Fix -Wcast-function-type
+    - orinoco: avoid assertion in case of NULL pointer
+    - drm/amdgpu: fix KIQ ring test fail in TDR of SRIOV
+    - clk: qcom: smd: Add missing bimc clock
+    - ACPICA: Disassembler: create buffer fields in ACPI_PARSE_LOAD_PASS1
+    - nfsd: Clone should commit src file metadata too
+    - scsi: ufs: Complete pending requests in host reset and restore path
+    - scsi: aic7xxx: Adjust indentation in ahc_find_syncrate
+    - crypto: inside-secure - add unspecified HAS_IOMEM dependency
+    - drm/mediatek: handle events when enabling/disabling crtc
+    - clk: renesas: rcar-gen3: Allow changing the RPC[D2] clocks
+    - ARM: dts: r8a7779: Add device node for ARM global timer
+    - selinux: ensure we cleanup the internal AVC counters on error in
+      avc_update()
+    - scsi: lpfc: Fix: Rework setting of fdmi symbolic node name registration
+    - arm64: dts: qcom: db845c: Enable ath10k 8bit host-cap quirk
+    - iommu/amd: Check feature support bit before accessing MSI capability
+      registers
+    - iommu/amd: Only support x2APIC with IVHD type 11h/40h
+    - iommu/iova: Silence warnings under memory pressure
+    - clk: actually call the clock init before any other callback of the clock
+    - dmaengine: Store module owner in dma_device struct
+    - dmaengine: imx-sdma: Fix memory leak
+    - bpf: Print error message for bpftool cgroup show
+    - net: phy: realtek: add logging for the RGMII TX delay configuration
+    - crypto: chtls - Fixed memory leak
+    - x86/vdso: Provide missing include file
+    - PM / devfreq: exynos-ppmu: Fix excessive stack usage
+    - PM / devfreq: rk3399_dmc: Add COMPILE_TEST and HAVE_ARM_SMCCC dependency
+    - drm/fbdev: Fallback to non tiled mode if all tiles not present
+    - pinctrl: sh-pfc: sh7269: Fix CAN function GPIOs
+    - reset: uniphier: Add SCSSI reset control for each channel
+    - ASoC: soc-topology: fix endianness issues
+    - fbdev: fix numbering of fbcon options
+    - RDMA/rxe: Fix error type of mmap_offset
+    - clk: sunxi-ng: add mux and pll notifiers for A64 CPU clock
+    - ALSA: sh: Fix unused variable warnings
+    - clk: Use parent node pointer during registration if necessary
+    - clk: uniphier: Add SCSSI clock gate for each channel
+    - ALSA: hda/realtek - Apply mic mute LED quirk for Dell E7xx laptops, too
+    - ALSA: sh: Fix compile warning wrt const
+    - net: phy: fixed_phy: fix use-after-free when checking link GPIO
+    - tools lib api fs: Fix gcc9 stringop-truncation compilation error
+    - vfio/spapr/nvlink2: Skip unpinning pages on error exit
+    - ASoC: Intel: sof_rt5682: Ignore the speaker amp when there isn't one.
+    - ACPI: button: Add DMI quirk for Razer Blade Stealth 13 late 2019 lid switch
+    - iommu/vt-d: Match CPU and IOMMU paging mode
+    - iommu/vt-d: Avoid sending invalid page response
+    - drm/amdkfd: Fix permissions of hang_hws
+    - mlx5: work around high stack usage with gcc
+    - RDMA/hns: Avoid printing address of mtt page
+    - drm: remove the newline for CRC source name.
+    - usb: dwc3: use proper initializers for property entries
+    - ARM: dts: stm32: Add power-supply for DSI panel on stm32f469-disco
+    - usbip: Fix unsafe unaligned pointer usage
+    - udf: Fix free space reporting for metadata and virtual partitions
+    - drm/mediatek: Add gamma property according to hardware capability
+    - staging: rtl8188: avoid excessive stack usage
+    - IB/hfi1: Add software counter for ctxt0 seq drop
+    - IB/hfi1: Add RcvShortLengthErrCnt to hfi1stats
+    - soc/tegra: fuse: Correct straps' address for older Tegra124 device trees
+    - efi/x86: Don't panic or BUG() on non-critical error conditions
+    - rcu: Use WRITE_ONCE() for assignments to ->pprev for hlist_nulls
+    - Input: edt-ft5x06 - work around first register access error
+    - bnxt: Detach page from page pool before sending up the stack
+    - x86/nmi: Remove irq_work from the long duration NMI handler
+    - wan: ixp4xx_hss: fix compile-testing on 64-bit
+    - clocksource: davinci: only enable clockevents once tim34 is initialized
+    - arm64: dts: rockchip: fix dwmmc clock name for px30
+    - arm64: dts: rockchip: add reg property to brcmf sub-nodes
+    - ARM: dts: rockchip: add reg property to brcmf sub node for
+      rk3188-bqedison2qc
+    - ALSA: usb-audio: Add boot quirk for MOTU M Series
+    - ASoC: atmel: fix build error with CONFIG_SND_ATMEL_SOC_DMA=m
+    - raid6/test: fix a compilation warning
+    - tty: synclinkmp: Adjust indentation in several functions
+    - tty: synclink_gt: Adjust indentation in several functions
+    - misc: xilinx_sdfec: fix xsdfec_poll()'s return type
+    - visorbus: fix uninitialized variable access
+    - driver core: platform: Prevent resouce overflow from causing infinite loops
+    - driver core: Print device when resources present in really_probe()
+    - ASoC: SOF: Intel: hda-dai: fix compilation warning in pcm_prepare
+    - bpf: Return -EBADRQC for invalid map type in __bpf_tx_xdp_map
+    - vme: bridges: reduce stack usage
+    - drm/nouveau/secboot/gm20b: initialize pointer in gm20b_secboot_new()
+    - drm/nouveau/gr/gk20a,gm200-: add terminators to method lists read from fw
+    - drm/nouveau: Fix copy-paste error in nouveau_fence_wait_uevent_handler
+    - drm/nouveau/drm/ttm: Remove set but not used variable 'mem'
+    - drm/nouveau/fault/gv100-: fix memory leak on module unload
+    - dm thin: don't allow changing data device during thin-pool reload
+    - gpiolib: Set lockdep class for hierarchical irq domains
+    - drm/vmwgfx: prevent memory leak in vmw_cmdbuf_res_add
+    - perf/imx_ddr: Fix cpu hotplug state cleanup
+    - usb: musb: omap2430: Get rid of musb .set_vbus for omap2430 glue
+    - kbuild: remove *.tmp file when filechk fails
+    - iommu/arm-smmu-v3: Use WRITE_ONCE() when changing validity of an STE
+    - ALSA: usb-audio: unlock on error in probe
+    - f2fs: set I_LINKABLE early to avoid wrong access by vfs
+    - f2fs: free sysfs kobject
+    - scsi: ufs: pass device information to apply_dev_quirks
+    - scsi: ufs-mediatek: add apply_dev_quirks variant operation
+    - scsi: iscsi: Don't destroy session if there are outstanding connections
+    - crypto: essiv - fix AEAD capitalization and preposition use in help text
+    - ALSA: usb-audio: add implicit fb quirk for MOTU M Series
+    - RDMA/mlx5: Don't fake udata for kernel path
+    - arm64: lse: fix LSE atomics with LLVM's integrated assembler
+    - arm64: fix alternatives with LLVM's integrated assembler
+    - drm/amd/display: fixup DML dependencies
+    - EDAC/sifive: Fix return value check in ecc_register()
+    - KVM: PPC: Remove set but not used variable 'ra', 'rs', 'rt'
+    - arm64: dts: ti: k3-j721e-main: Add missing power-domains for smmu
+    - sched/core: Fix size of rq::uclamp initialization
+    - sched/topology: Assert non-NUMA topology masks don't (partially) overlap
+    - perf/x86/amd: Constrain Large Increment per Cycle events
+    - watchdog/softlockup: Enforce that timestamp is valid on boot
+    - debugobjects: Fix various data races
+    - ASoC: SOF: Intel: hda: Fix SKL dai count
+    - regulator: vctrl-regulator: Avoid deadlock getting and setting the voltage
+    - f2fs: fix memleak of kobject
+    - x86/mm: Fix NX bit clearing issue in kernel_map_pages_in_pgd
+    - pwm: omap-dmtimer: Remove PWM chip in .remove before making it unfunctional
+    - cmd64x: potential buffer overflow in cmd64x_program_timings()
+    - ide: serverworks: potential overflow in svwks_set_pio_mode()
+    - pwm: Remove set but not set variable 'pwm'
+    - btrfs: fix possible NULL-pointer dereference in integrity checks
+    - btrfs: safely advance counter when looking up bio csums
+    - btrfs: device stats, log when stats are zeroed
+    - module: avoid setting info->name early in case we can fall back to
+      info->mod->name
+    - remoteproc: Initialize rproc_class before use
+    - regulator: core: Fix exported symbols to the exported GPL version
+    - irqchip/mbigen: Set driver .suppress_bind_attrs to avoid remove problems
+    - ALSA: hda/hdmi - add retry logic to parse_intel_hdmi()
+    - spi: spi-fsl-qspi: Ensure width is respected in spi-mem operations
+    - kbuild: use -S instead of -E for precise cc-option test in Kconfig
+    - objtool: Fix ARCH=x86_64 build error
+    - x86/decoder: Add TEST opcode to Group3-2
+    - s390: adjust -mpacked-stack support check for clang 10
+    - s390/ftrace: generate traced function stack frame
+    - driver core: platform: fix u32 greater or equal to zero comparison
+    - bpf, btf: Always output invariant hit in pahole DWARF to BTF transform
+    - ALSA: hda - Add docking station support for Lenovo Thinkpad T420s
+    - sunrpc: Fix potential leaks in sunrpc_cache_unhash()
+    - drm/nouveau/mmu: fix comptag memory leak
+    - powerpc/sriov: Remove VF eeh_dev state when disabling SR-IOV
+    - media: uvcvideo: Add a quirk to force GEO GC6500 Camera bits-per-pixel value
+    - btrfs: separate definition of assertion failure handlers
+    - btrfs: Fix split-brain handling when changing FSID to metadata uuid
+    - bcache: cached_dev_free needs to put the sb page
+    - bcache: rework error unwinding in register_bcache
+    - bcache: fix use-after-free in register_bcache()
+    - iommu/vt-d: Remove unnecessary WARN_ON_ONCE()
+    - alarmtimer: Make alarmtimer platform device child of RTC device
+    - selftests: bpf: Reset global state between reuseport test runs
+    - jbd2: switch to use jbd2_journal_abort() when failed to submit the commit
+      record
+    - jbd2: make sure ESHUTDOWN to be recorded in the journal superblock
+    - powerpc/pseries/lparcfg: Fix display of Maximum Memory
+    - selftests/eeh: Bump EEH wait time to 60s
+    - ARM: 8951/1: Fix Kexec compilation issue.
+    - ALSA: usb-audio: add quirks for Line6 Helix devices fw>=2.82
+    - hostap: Adjust indentation in prism2_hostapd_add_sta
+    - rtw88: fix potential NULL skb access in TX ISR
+    - iwlegacy: ensure loop counter addr does not wrap and cause an infinite loop
+    - cifs: fix unitialized variable poential problem with network I/O cache lock
+      patch
+    - cifs: Fix mount options set in automount
+    - cifs: fix NULL dereference in match_prepath
+    - bpf: map_seq_next should always increase position index
+    - powerpc/mm: Don't log user reads to 0xffffffff
+    - ceph: check availability of mds cluster on mount after wait timeout
+    - rbd: work around -Wuninitialized warning
+    - drm/amd/display: do not allocate display_mode_lib unnecessarily
+    - irqchip/gic-v3: Only provision redistributors that are enabled in ACPI
+    - drm/nouveau/disp/nv50-: prevent oops when no channel method map provided
+    - char: hpet: Fix out-of-bounds read bug
+    - ftrace: fpid_next() should increase position index
+    - trigger_next should increase position index
+    - radeon: insert 10ms sleep in dce5_crtc_load_lut
+    - powerpc: Do not consider weak unresolved symbol relocations as bad
+    - btrfs: do not do delalloc reservation under page lock
+    - ocfs2: make local header paths relative to C files
+    - ocfs2: fix a NULL pointer dereference when call
+      ocfs2_update_inode_fsync_trans()
+    - lib/scatterlist.c: adjust indentation in __sg_alloc_table
+    - reiserfs: prevent NULL pointer dereference in reiserfs_insert_item()
+    - bcache: fix memory corruption in bch_cache_accounting_clear()
+    - bcache: explicity type cast in bset_bkey_last()
+    - bcache: fix incorrect data type usage in btree_flush_write()
+    - irqchip/gic-v3-its: Reference to its_invall_cmd descriptor when building
+      INVALL
+    - nvmet: Pass lockdep expression to RCU lists
+    - nvme-pci: remove nvmeq->tags
+    - iwlwifi: mvm: Fix thermal zone registration
+    - iwlwifi: mvm: Check the sta is not NULL in iwl_mvm_cfg_he_sta()
+    - asm-generic/tlb: add missing CONFIG symbol
+    - microblaze: Prevent the overflow of the start
+    - brd: check and limit max_part par
+    - drm/amdgpu/smu10: fix smu10_get_clock_by_type_with_latency
+    - drm/amdgpu/smu10: fix smu10_get_clock_by_type_with_voltage
+    - NFS: Fix memory leaks
+    - help_next should increase position index
+    - i40e: Relax i40e_xsk_wakeup's return value when PF is busy
+    - cifs: log warning message (once) if out of disk space
+    - virtio_balloon: prevent pfn array overflow
+    - fuse: don't overflow LLONG_MAX with end offset
+    - mlxsw: spectrum_dpipe: Add missing error path
+    - drm/amdgpu/display: handle multiple numbers of fclks in dcn_calcs.c (v2)
+    - bcache: properly initialize 'path' and 'err' in register_bcache()
+    - rtc: Kconfig: select REGMAP_I2C when necessary
+    - Linux 5.4.22
+
+  * Focal update: 5.4.22 upstream stable release (LP: #1864488) //
+    CVE-2019-19076.
+    - Revert "nfp: abm: fix memory leak in nfp_abm_u32_knode_replace"
+
+  * Miscellaneous Ubuntu changes
+    - [Debian] Revert "UBUNTU: [Debian] Update linux source package name in
+      debian/tests/*"
+    - SAUCE: selftests: fix undefined lable cleanup build error
+    - SAUCE: selftests: fix undefined macro RET_IF() build error
+    - [Packaging] Include modules.builtin.modinfo in linux-modules
+    - update dkms package versions
+    - Revert "UBUNTU: [Debian] Update package name in getabis repo list"
+
+  * Miscellaneous upstream changes
+    - libbpf: Extract and generalize CPU mask parsing logic
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Wed, 26 Feb 2020 12:22:51 -0600
+
+linux (5.4.0-15.18) focal; urgency=medium
+
+  * focal/linux: 5.4.0-15.18 -proposed tracker (LP: #1864085)
+
+  * Focal update: v5.4.21 upstream stable release (LP: #1864046)
+    - Input: synaptics - switch T470s to RMI4 by default
+    - Input: synaptics - enable SMBus on ThinkPad L470
+    - Input: synaptics - remove the LEN0049 dmi id from topbuttonpad list
+    - ALSA: usb-audio: Fix UAC2/3 effect unit parsing
+    - ALSA: hda/realtek - Add more codec supported Headset Button
+    - ALSA: hda/realtek - Fix silent output on MSI-GL73
+    - ALSA: usb-audio: Apply sample rate quirk for Audioengine D1
+    - ACPI: EC: Fix flushing of pending work
+    - ACPI: PM: s2idle: Avoid possible race related to the EC GPE
+    - ACPICA: Introduce acpi_any_gpe_status_set()
+    - ACPI: PM: s2idle: Prevent spurious SCIs from waking up the system
+    - ALSA: usb-audio: sound: usb: usb true/false for bool return type
+    - ALSA: usb-audio: Add clock validity quirk for Denon MC7000/MCX8000
+    - ext4: don't assume that mmp_nodename/bdevname have NUL
+    - ext4: fix support for inode sizes > 1024 bytes
+    - ext4: fix checksum errors with indexed dirs
+    - ext4: add cond_resched() to ext4_protect_reserved_inode
+    - ext4: improve explanation of a mount failure caused by a misconfigured
+      kernel
+    - Btrfs: fix race between using extent maps and merging them
+    - btrfs: ref-verify: fix memory leaks
+    - btrfs: print message when tree-log replay starts
+    - btrfs: log message when rw remount is attempted with unclean tree-log
+    - ARM: npcm: Bring back GPIOLIB support
+    - gpio: xilinx: Fix bug where the wrong GPIO register is written to
+    - arm64: ssbs: Fix context-switch when SSBS is present on all CPUs
+    - xprtrdma: Fix DMA scatter-gather list mapping imbalance
+    - cifs: make sure we do not overflow the max EA buffer size
+    - EDAC/sysfs: Remove csrow objects on errors
+    - EDAC/mc: Fix use-after-free and memleaks during device removal
+    - KVM: nVMX: Use correct root level for nested EPT shadow page tables
+    - perf/x86/amd: Add missing L2 misses event spec to AMD Family 17h's event map
+    - s390/pkey: fix missing length of protected key on return
+    - s390/uv: Fix handling of length extensions
+    - drm/vgem: Close use-after-free race in vgem_gem_create
+    - drm/panfrost: Make sure the shrinker does not reclaim referenced BOs
+    - bus: moxtet: fix potential stack buffer overflow
+    - nvme: fix the parameter order for nvme_get_log in nvme_get_fw_slot_info
+    - drivers: ipmi: fix off-by-one bounds check that leads to a out-of-bounds
+      write
+    - IB/mlx5: Return failure when rts2rts_qp_counters_set_id is not supported
+    - IB/hfi1: Acquire lock to release TID entries when user file is closed
+    - IB/hfi1: Close window for pq and request coliding
+    - IB/rdmavt: Reset all QPs when the device is shut down
+    - IB/umad: Fix kernel crash while unloading ib_umad
+    - RDMA/core: Fix invalid memory access in spec_filter_size
+    - RDMA/iw_cxgb4: initiate CLOSE when entering TERM
+    - RDMA/hfi1: Fix memory leak in _dev_comp_vect_mappings_create
+    - RDMA/rxe: Fix soft lockup problem due to using tasklets in softirq
+    - RDMA/core: Fix protection fault in get_pkey_idx_qp_list
+    - s390/time: Fix clk type in get_tod_clock
+    - sched/uclamp: Reject negative values in cpu_uclamp_write()
+    - spmi: pmic-arb: Set lockdep class for hierarchical irq domains
+    - perf/x86/intel: Fix inaccurate period in context switch for auto-reload
+    - hwmon: (pmbus/ltc2978) Fix PMBus polling of MFR_COMMON definitions.
+    - mac80211: fix quiet mode activation in action frames
+    - cifs: fix mount option display for sec=krb5i
+    - arm64: dts: fast models: Fix FVP PCI interrupt-map property
+    - KVM: x86: Mask off reserved bit from #DB exception payload
+    - perf stat: Don't report a null stalled cycles per insn metric
+    - NFSv4.1 make cachethis=no for writes
+    - Revert "drm/sun4i: drv: Allow framebuffer modifiers in mode config"
+    - jbd2: move the clearing of b_modified flag to the journal_unmap_buffer()
+    - jbd2: do not clear the BH_Mapped flag when forgetting a metadata buffer
+    - ext4: choose hardlimit when softlimit is larger than hardlimit in
+      ext4_statfs_project()
+    - KVM: x86/mmu: Fix struct guest_walker arrays for 5-level paging
+    - gpio: add gpiod_toggle_active_low()
+    - mmc: core: Rework wp-gpio handling
+    - Linux 5.4.21
+
+  * Fix AMD Stoney Ridge screen flickering under 4K resolution (LP: #1864005)
+    - iommu/amd: Disable IOMMU on Stoney Ridge systems
+
+  * Focal Fossa (20.04) feature request - Enable CONFIG_X86_UV (LP: #1863810)
+    - [Config] CONFIG_X86_UV=y
+
+  * [UBUNTU 20.04] Enable proper reset/recovery of s390x/pci functions in error
+    state (LP: #1863768)
+    - s390/pci: Recover handle in clp_set_pci_fn()
+    - s390/pci: Fix possible deadlock in recover_store()
+
+  * [20.04 FEAT] Enhanced handling of secure keys and protected keys
+    (LP: #1853303)
+    - s390/zcrypt: enable card/domain autoselect on ep11 cprbs
+    - s390/zcrypt: ep11 structs rework, export zcrypt_send_ep11_cprb
+    - s390/zcrypt: add new low level ep11 functions support file
+    - s390/zcrypt: extend EP11 card and queue sysfs attributes
+    - s390/pkey/zcrypt: Support EP11 AES secure keys
+
+  * [20.04 FEAT] paes self test (LP: #1854948)
+    - s390/pkey: use memdup_user() to simplify code
+    - s390/pkey: Add support for key blob with clear key value
+    - s390/crypto: Rework on paes implementation
+    - s390/crypto: enable clear key values for paes ciphers
+    - crypto/testmgr: enable selftests for paes-s390 ciphers
+
+  * Sometimes can't adjust brightness on Dell AIO (LP: #1862885)
+    - SAUCE: platform/x86: dell-uart-backlight: increase retry times
+
+  * change the ASoC card name and card longname to meet the requirement of alsa-
+    lib-1.2.1 (Focal) (LP: #1862712)
+    - ASoC: improve the DMI long card code in asoc-core
+    - ASoC: DMI long name - avoid to add board name if matches with product name
+    - ASoC: intel - fix the card names
+
+  * Support Headset Mic on HP cPC (LP: #1862313)
+    - ALSA: hda/realtek - Add Headset Mic supported for HP cPC
+    - ALSA: hda/realtek - Fixed one of HP ALC671 platform Headset Mic supported
+
+  * [hns3-0205]sync mainline kernel 5.5rc7 hns3 patchset into ubuntu HWE kernel
+    branch (LP: #1861972)
+    - net: hns3: replace snprintf with scnprintf in hns3_dbg_cmd_read
+    - net: hns3: replace snprintf with scnprintf in hns3_update_strings
+    - net: hns3: limit the error logging in the hns3_clean_tx_ring()
+    - net: hns3: do not reuse pfmemalloc pages
+    - net: hns3: set VF's default reset_type to HNAE3_NONE_RESET
+    - net: hns3: move duplicated macro definition into header
+    - net: hns3: refine the input parameter 'size' for snprintf()
+    - net: hns3: rewrite a log in hclge_put_vector()
+    - net: hns3: delete unnecessary blank line and space for cleanup
+    - net: hns3: remove redundant print on ENOMEM
+
+  * [acc-0205]sync mainline kernel 5.5rc6 acc patchset into ubuntu HWE kernel
+    branch (LP: #1861976)
+    - crypto: hisilicon/sec2 - Use atomics instead of __sync
+    - crypto: hisilicon - still no need to check return value of debugfs_create
+      functions
+    - crypto: hisilicon - Update debugfs usage of SEC V2
+    - crypto: hisilicon - fix print/comment of SEC V2
+    - crypto: hisilicon - Update some names on SEC V2
+    - crypto: hisilicon - Update QP resources of SEC V2
+    - crypto: hisilicon - Adjust some inner logic
+    - crypto: hisilicon - Add callback error check
+    - crypto: hisilicon - Add branch prediction macro
+    - crypto: hisilicon - redefine skcipher initiation
+    - crypto: hisilicon - Add aead support on SEC2
+    - crypto: hisilicon - Bugfixed tfm leak
+    - crypto: hisilicon - Fixed some tiny bugs of HPRE
+    - crypto: hisilicon - adjust hpre_crt_para_get
+    - crypto: hisilicon - add branch prediction macro
+    - crypto: hisilicon - fix spelling mistake "disgest" -> "digest"
+
+  * [spi-0115]spi: dw: use "smp_mb()" to avoid sending spi data error
+    (LP: #1859744)
+    - spi: dw: use "smp_mb()" to avoid sending spi data error
+
+  * [tpm-0115]EFI/stub: tpm: enable tpm eventlog function for ARM64 platform
+    (LP: #1859743)
+    - efi: libstub/tpm: enable tpm eventlog function for ARM platforms
+
+  * Restrict xmon to read-only-mode if kernel is locked down (LP: #1863562)
+    - powerpc/xmon: Restrict when kernel is locked down
+
+  * [CML-H] Add intel_thermal_pch driver support Comet Lake -H (LP: #1853219)
+    - thermal: intel: intel_pch_thermal: Add Comet Lake (CML) platform support
+
+  * Root can lift kernel lockdown via USB/IP (LP: #1861238)
+    - Revert "UBUNTU: SAUCE: (lockdown) Add a SysRq option to lift kernel
+      lockdown"
+
+  * Dell XPS 13 (7390) Display Flickering - 19.10  (LP: #1849947)
+    - SAUCE: drm/i915: Disable PSR by default on all platforms
+
+  * Focal update: v5.4.20 upstream stable release (LP: #1863589)
+    - ASoC: pcm: update FE/BE trigger order based on the command
+    - hv_sock: Remove the accept port restriction
+    - IB/mlx4: Fix memory leak in add_gid error flow
+    - IB/srp: Never use immediate data if it is disabled by a user
+    - IB/mlx4: Fix leak in id_map_find_del
+    - RDMA/netlink: Do not always generate an ACK for some netlink operations
+    - RDMA/i40iw: fix a potential NULL pointer dereference
+    - RDMA/core: Fix locking in ib_uverbs_event_read
+    - RDMA/uverbs: Verify MR access flags
+    - RDMA/cma: Fix unbalanced cm_id reference count during address resolve
+    - RDMA/umem: Fix ib_umem_find_best_pgsz()
+    - scsi: ufs: Fix ufshcd_probe_hba() reture value in case
+      ufshcd_scsi_add_wlus() fails
+    - PCI/IOV: Fix memory leak in pci_iov_add_virtfn()
+    - ath10k: pci: Only dump ATH10K_MEM_REGION_TYPE_IOREG when safe
+    - PCI/switchtec: Use dma_set_mask_and_coherent()
+    - PCI/switchtec: Fix vep_vector_number ioread width
+    - PCI: tegra: Fix afi_pex2_ctrl reg offset for Tegra30
+    - PCI: Don't disable bridge BARs when assigning bus resources
+    - PCI/AER: Initialize aer_fifo
+    - iwlwifi: mvm: avoid use after free for pmsr request
+    - bpftool: Don't crash on missing xlated program instructions
+    - bpf, sockmap: Don't sleep while holding RCU lock on tear-down
+    - bpf, sockhash: Synchronize_rcu before free'ing map
+    - selftests/bpf: Test freeing sockmap/sockhash with a socket in it
+    - bpf: Improve bucket_log calculation logic
+    - bpf, sockmap: Check update requirements after locking
+    - nfs: NFS_SWAP should depend on SWAP
+    - NFS: Revalidate the file size on a fatal write error
+    - NFS/pnfs: Fix pnfs_generic_prepare_to_resend_writes()
+    - NFS: Fix fix of show_nfs_errors
+    - NFSv4: pnfs_roc() must use cred_fscmp() to compare creds
+    - NFSv4: try lease recovery on NFS4ERR_EXPIRED
+    - NFSv4.0: nfs4_do_fsinfo() should not do implicit lease renewals
+    - x86/boot: Handle malformed SRAT tables during early ACPI parsing
+    - rtc: hym8563: Return -EINVAL if the time is known to be invalid
+    - rtc: cmos: Stop using shared IRQ
+    - watchdog: qcom: Use platform_get_irq_optional() for bark irq
+    - ARC: [plat-axs10x]: Add missing multicast filter number to GMAC node
+    - platform/x86: intel_mid_powerbtn: Take a copy of ddata
+    - arm64: dts: qcom: msm8998: Fix tcsr syscon size
+    - arm64: dts: uDPU: fix broken ethernet
+    - ARM: dts: at91: Reenable UART TX pull-ups
+    - ARM: dts: am43xx: add support for clkout1 clock
+    - arm64: dts: renesas: r8a77990: ebisu: Remove clkout-lr-synchronous from
+      sound
+    - arm64: dts: marvell: clearfog-gt-8k: fix switch cpu port node
+    - ARM: dts: meson8: use the actual frequency for the GPU's 182.1MHz OPP
+    - ARM: dts: meson8b: use the actual frequency for the GPU's 364MHz OPP
+    - ARM: dts: at91: sama5d3: fix maximum peripheral clock rates
+    - ARM: dts: at91: sama5d3: define clock rate range for tcb1
+    - tools/power/acpi: fix compilation error
+    - soc: qcom: rpmhpd: Set 'active_only' for active only power domains
+    - Revert "powerpc/pseries/iommu: Don't use dma_iommu_ops on secure guests"
+    - powerpc/ptdump: Fix W+X verification call in mark_rodata_ro()
+    - powerpc/ptdump: Only enable PPC_CHECK_WX with STRICT_KERNEL_RWX
+    - powerpc/papr_scm: Fix leaking 'bus_desc.provider_name' in some paths
+    - powerpc/pseries/vio: Fix iommu_table use-after-free refcount warning
+    - powerpc/pseries: Allow not having ibm, hypertas-functions::hcall-multi-tce
+      for DDW
+    - iommu/arm-smmu-v3: Populate VMID field for CMDQ_OP_TLBI_NH_VA
+    - ARM: at91: pm: use SAM9X60 PMC's compatible
+    - ARM: at91: pm: use of_device_id array to find the proper shdwc node
+    - KVM: arm/arm64: vgic-its: Fix restoration of unmapped collections
+    - ARM: 8949/1: mm: mark free_memmap as __init
+    - sched/uclamp: Fix a bug in propagating uclamp value in new cgroups
+    - arm64: cpufeature: Fix the type of no FP/SIMD capability
+    - arm64: cpufeature: Set the FP/SIMD compat HWCAP bits properly
+    - arm64: ptrace: nofpsimd: Fail FP/SIMD regset operations
+    - KVM: arm/arm64: Fix young bit from mmu notifier
+    - KVM: arm: Fix DFSR setting for non-LPAE aarch32 guests
+    - KVM: arm: Make inject_abt32() inject an external abort instead
+    - KVM: arm64: pmu: Don't increment SW_INCR if PMCR.E is unset
+    - KVM: arm64: pmu: Fix chained SW_INCR counters
+    - KVM: arm64: Treat emulated TVAL TimerValue as a signed 32-bit integer
+    - arm64: nofpsmid: Handle TIF_FOREIGN_FPSTATE flag cleanly
+    - mtd: onenand_base: Adjust indentation in onenand_read_ops_nolock
+    - mtd: sharpslpart: Fix unsigned comparison to zero
+    - crypto: testmgr - don't try to decrypt uninitialized buffers
+    - crypto: artpec6 - return correct error code for failed setkey()
+    - crypto: atmel-sha - fix error handling when setting hmac key
+    - crypto: caam/qi2 - fix typo in algorithm's driver name
+    - drivers: watchdog: stm32_iwdg: set WDOG_HW_RUNNING at probe
+    - media: i2c: adv748x: Fix unsafe macros
+    - dt-bindings: iio: adc: ad7606: Fix wrong maxItems value
+    - bcache: avoid unnecessary btree nodes flushing in btree_flush_write()
+    - selinux: revert "stop passing MAY_NOT_BLOCK to the AVC upon follow_link"
+    - selinux: fix regression introduced by move_mount(2) syscall
+    - pinctrl: sh-pfc: r8a77965: Fix DU_DOTCLKIN3 drive/bias control
+    - pinctrl: sh-pfc: r8a7778: Fix duplicate SDSELF_B and SD1_CLK_B
+    - regmap: fix writes to non incrementing registers
+    - mfd: max77650: Select REGMAP_IRQ in Kconfig
+    - clk: meson: g12a: fix missing uart2 in regmap table
+    - dmaengine: axi-dmac: add a check for devm_regmap_init_mmio
+    - mwifiex: Fix possible buffer overflows in mwifiex_ret_wmm_get_status()
+    - mwifiex: Fix possible buffer overflows in mwifiex_cmd_append_vsie_tlv()
+    - libertas: don't exit from lbs_ibss_join_existing() with RCU read lock held
+    - libertas: make lbs_ibss_join_existing() return error code on rates overflow
+    - selinux: fall back to ref-walk if audit is required
+    - Linux 5.4.20
+
+  * Focal update: v5.4.19 upstream stable release (LP: #1863588)
+    - sparc32: fix struct ipc64_perm type definition
+    - bnxt_en: Move devlink_register before registering netdev
+    - cls_rsvp: fix rsvp_policy
+    - gtp: use __GFP_NOWARN to avoid memalloc warning
+    - l2tp: Allow duplicate session creation with UDP
+    - net: hsr: fix possible NULL deref in hsr_handle_frame()
+    - net_sched: fix an OOB access in cls_tcindex
+    - net: stmmac: Delete txtimer in suspend()
+    - bnxt_en: Fix TC queue mapping.
+    - rxrpc: Fix use-after-free in rxrpc_put_local()
+    - rxrpc: Fix insufficient receive notification generation
+    - rxrpc: Fix missing active use pinning of rxrpc_local object
+    - rxrpc: Fix NULL pointer deref due to call->conn being cleared on disconnect
+    - tcp: clear tp->total_retrans in tcp_disconnect()
+    - tcp: clear tp->delivered in tcp_disconnect()
+    - tcp: clear tp->data_segs{in|out} in tcp_disconnect()
+    - tcp: clear tp->segs_{in|out} in tcp_disconnect()
+    - ionic: fix rxq comp packet type mask
+    - MAINTAINERS: correct entries for ISDN/mISDN section
+    - netdevsim: fix stack-out-of-bounds in nsim_dev_debugfs_init()
+    - bnxt_en: Fix logic that disables Bus Master during firmware reset.
+    - media: uvcvideo: Avoid cyclic entity chains due to malformed USB descriptors
+    - mfd: dln2: More sanity checking for endpoints
+    - netfilter: ipset: fix suspicious RCU usage in find_set_and_id
+    - ipc/msg.c: consolidate all xxxctl_down() functions
+    - tracing/kprobes: Have uname use __get_str() in print_fmt
+    - tracing: Fix sched switch start/stop refcount racy updates
+    - rcu: Use *_ONCE() to protect lockless ->expmask accesses
+    - rcu: Avoid data-race in rcu_gp_fqs_check_wake()
+    - srcu: Apply *_ONCE() to ->srcu_last_gp_end
+    - rcu: Use READ_ONCE() for ->expmask in rcu_read_unlock_special()
+    - nvmet: Fix error print message at nvmet_install_queue function
+    - nvmet: Fix controller use after free
+    - Bluetooth: btusb: fix memory leak on fw
+    - Bluetooth: btusb: Disable runtime suspend on Realtek devices
+    - brcmfmac: Fix memory leak in brcmf_usbdev_qinit
+    - usb: dwc3: gadget: Check END_TRANSFER completion
+    - usb: dwc3: gadget: Delay starting transfer
+    - usb: typec: tcpci: mask event interrupts when remove driver
+    - objtool: Silence build output
+    - usb: gadget: f_fs: set req->num_sgs as 0 for non-sg transfer
+    - usb: gadget: legacy: set max_speed to super-speed
+    - usb: gadget: f_ncm: Use atomic_t to track in-flight request
+    - usb: gadget: f_ecm: Use atomic_t to track in-flight request
+    - ALSA: usb-audio: Fix endianess in descriptor validation
+    - ALSA: usb-audio: Annotate endianess in Scarlett gen2 quirk
+    - ALSA: dummy: Fix PCM format loop in proc output
+    - memcg: fix a crash in wb_workfn when a device disappears
+    - mm/sparse.c: reset section's mem_map when fully deactivated
+    - mmc: sdhci-pci: Make function amd_sdhci_reset static
+    - utimes: Clamp the timestamps in notify_change()
+    - mm/memory_hotplug: fix remove_memory() lockdep splat
+    - mm: thp: don't need care deferred split queue in memcg charge move path
+    - mm: move_pages: report the number of non-attempted pages
+    - media/v4l2-core: set pages dirty upon releasing DMA buffers
+    - media: v4l2-core: compat: ignore native command codes
+    - media: v4l2-rect.h: fix v4l2_rect_map_inside() top/left adjustments
+    - lib/test_kasan.c: fix memory leak in kmalloc_oob_krealloc_more()
+    - irqdomain: Fix a memory leak in irq_domain_push_irq()
+    - x86/cpu: Update cached HLE state on write to TSX_CTRL_CPUID_CLEAR
+    - platform/x86: intel_scu_ipc: Fix interrupt support
+    - ALSA: hda: Apply aligned MMIO access only conditionally
+    - ALSA: hda: Add Clevo W65_67SB the power_save blacklist
+    - ALSA: hda: Add JasperLake PCI ID and codec vid
+    - arm64: acpi: fix DAIF manipulation with pNMI
+    - KVM: arm64: Correct PSTATE on exception entry
+    - KVM: arm/arm64: Correct CPSR on exception entry
+    - KVM: arm/arm64: Correct AArch32 SPSR on exception entry
+    - KVM: arm64: Only sign-extend MMIO up to register width
+    - MIPS: syscalls: fix indentation of the 'SYSNR' message
+    - MIPS: fix indentation of the 'RELOCS' message
+    - MIPS: boot: fix typo in 'vmlinux.lzma.its' target
+    - s390/mm: fix dynamic pagetable upgrade for hugetlbfs
+    - powerpc/mmu_gather: enable RCU_TABLE_FREE even for !SMP case
+    - powerpc/ptdump: Fix W+X verification
+    - powerpc/xmon: don't access ASDR in VMs
+    - powerpc/pseries: Advance pfn if section is not present in lmb_is_removable()
+    - powerpc/32s: Fix bad_kuap_fault()
+    - powerpc/32s: Fix CPU wake-up from sleep mode
+    - tracing: Fix now invalid var_ref_vals assumption in trace action
+    - PCI: tegra: Fix return value check of pm_runtime_get_sync()
+    - PCI: keystone: Fix outbound region mapping
+    - PCI: keystone: Fix link training retries initiation
+    - PCI: keystone: Fix error handling when "num-viewport" DT property is not
+      populated
+    - mmc: spi: Toggle SPI polarity, do not hardcode it
+    - ACPI: video: Do not export a non working backlight interface on MSI MS-7721
+      boards
+    - ACPI / battery: Deal with design or full capacity being reported as -1
+    - ACPI / battery: Use design-cap for capacity calculations if full-cap is not
+      available
+    - ACPI / battery: Deal better with neither design nor full capacity not being
+      reported
+    - alarmtimer: Unregister wakeup source when module get fails
+    - fscrypt: don't print name of busy file when removing key
+    - ubifs: don't trigger assertion on invalid no-key filename
+    - ubifs: Fix wrong memory allocation
+    - ubifs: Fix FS_IOC_SETFLAGS unexpectedly clearing encrypt flag
+    - ubifs: Fix deadlock in concurrent bulk-read and writepage
+    - mmc: sdhci-of-at91: fix memleak on clk_get failure
+    - ASoC: SOF: core: free trace on errors
+    - hv_balloon: Balloon up according to request page number
+    - mfd: axp20x: Mark AXP20X_VBUS_IPSOUT_MGMT as volatile
+    - nvmem: core: fix memory abort in cleanup path
+    - crypto: api - Check spawn->alg under lock in crypto_drop_spawn
+    - crypto: ccree - fix backlog memory leak
+    - crypto: ccree - fix AEAD decrypt auth fail
+    - crypto: ccree - fix pm wrongful error reporting
+    - crypto: ccree - fix FDE descriptor sequence
+    - crypto: ccree - fix PM race condition
+    - padata: Remove broken queue flushing
+    - fs: allow deduplication of eof block into the end of the destination file
+    - scripts/find-unused-docs: Fix massive false positives
+    - erofs: fix out-of-bound read for shifted uncompressed block
+    - scsi: megaraid_sas: Do not initiate OCR if controller is not in ready state
+    - scsi: qla2xxx: Fix mtcp dump collection failure
+    - cpupower: Revert library ABI changes from commit ae2917093fb60bdc1ed3e
+    - power: supply: axp20x_ac_power: Fix reporting online status
+    - power: supply: ltc2941-battery-gauge: fix use-after-free
+    - ovl: fix wrong WARN_ON() in ovl_cache_update_ino()
+    - ovl: fix lseek overflow on 32bit
+    - f2fs: choose hardlimit when softlimit is larger than hardlimit in
+      f2fs_statfs_project()
+    - f2fs: fix miscounted block limit in f2fs_statfs_project()
+    - f2fs: code cleanup for f2fs_statfs_project()
+    - f2fs: fix dcache lookup of !casefolded directories
+    - f2fs: fix race conditions in ->d_compare() and ->d_hash()
+    - PM: core: Fix handling of devices deleted during system-wide resume
+    - cpufreq: Avoid creating excessively large stack frames
+    - of: Add OF_DMA_DEFAULT_COHERENT & select it on powerpc
+    - ARM: dma-api: fix max_pfn off-by-one error in __dma_supported()
+    - dm zoned: support zone sizes smaller than 128MiB
+    - dm space map common: fix to ensure new block isn't already in use
+    - dm writecache: fix incorrect flush sequence when doing SSD mode commit
+    - dm crypt: fix GFP flags passed to skcipher_request_alloc()
+    - dm crypt: fix benbi IV constructor crash if used in authenticated mode
+    - dm thin metadata: use pool locking at end of dm_pool_metadata_close
+    - scsi: qla2xxx: Fix stuck login session using prli_pend_timer
+    - ASoC: SOF: Introduce state machine for FW boot
+    - ASoC: SOF: core: release resources on errors in probe_continue
+    - tracing: Annotate ftrace_graph_hash pointer with __rcu
+    - tracing: Annotate ftrace_graph_notrace_hash pointer with __rcu
+    - ftrace: Add comment to why rcu_dereference_sched() is open coded
+    - ftrace: Protect ftrace_graph_hash with ftrace_sync
+    - crypto: pcrypt - Avoid deadlock by using per-instance padata queues
+    - btrfs: fix improper setting of scanned for range cyclic write cache pages
+    - btrfs: Handle another split brain scenario with metadata uuid feature
+    - riscv, bpf: Fix broken BPF tail calls
+    - selftests/bpf: Fix perf_buffer test on systems w/ offline CPUs
+    - bpf, devmap: Pass lockdep expression to RCU lists
+    - libbpf: Fix realloc usage in bpf_core_find_cands
+    - tc-testing: fix eBPF tests failure on linux fresh clones
+    - samples/bpf: Don't try to remove user's homedir on clean
+    - samples/bpf: Xdp_redirect_cpu fix missing tracepoint attach
+    - selftests/bpf: Fix test_attach_probe
+    - selftests/bpf: Skip perf hw events test if the setup disabled it
+    - selftests: bpf: Use a temporary file in test_sockmap
+    - selftests: bpf: Ignore FIN packets for reuseport tests
+    - crypto: api - fix unexpectedly getting generic implementation
+    - crypto: hisilicon - Use the offset fields in sqe to avoid need to split
+      scatterlists
+    - crypto: ccp - set max RSA modulus size for v3 platform devices as well
+    - crypto: arm64/ghash-neon - bump priority to 150
+    - crypto: pcrypt - Do not clear MAY_SLEEP flag in original request
+    - crypto: atmel-aes - Fix counter overflow in CTR mode
+    - crypto: api - Fix race condition in crypto_spawn_alg
+    - crypto: picoxcell - adjust the position of tasklet_init and fix missed
+      tasklet_kill
+    - powerpc/futex: Fix incorrect user access blocking
+    - scsi: qla2xxx: Fix unbound NVME response length
+    - NFS: Fix memory leaks and corruption in readdir
+    - NFS: Directory page cache pages need to be locked when read
+    - nfsd: fix filecache lookup
+    - jbd2_seq_info_next should increase position index
+    - ext4: fix deadlock allocating crypto bounce page from mempool
+    - ext4: fix race conditions in ->d_compare() and ->d_hash()
+    - Btrfs: fix missing hole after hole punching and fsync when using NO_HOLES
+    - Btrfs: make deduplication with range including the last block work
+    - Btrfs: fix infinite loop during fsync after rename operations
+    - btrfs: set trans->drity in btrfs_commit_transaction
+    - btrfs: drop log root for dropped roots
+    - Btrfs: fix race between adding and putting tree mod seq elements and nodes
+    - btrfs: flush write bio if we loop in extent_write_cache_pages
+    - btrfs: Correctly handle empty trees in find_first_clear_extent_bit
+    - ARM: tegra: Enable PLLP bypass during Tegra124 LP1
+    - iwlwifi: don't throw error when trying to remove IGTK
+    - mwifiex: fix unbalanced locking in mwifiex_process_country_ie()
+    - sunrpc: expiry_time should be seconds not timeval
+    - gfs2: fix gfs2_find_jhead that returns uninitialized jhead with seq 0
+    - gfs2: move setting current->backing_dev_info
+    - gfs2: fix O_SYNC write handling
+    - drm: atmel-hlcdc: use double rate for pixel clock only if supported
+    - drm: atmel-hlcdc: enable clock before configuring timing engine
+    - drm: atmel-hlcdc: prefer a lower pixel-clock than requested
+    - drm/rect: Avoid division by zero
+    - media: iguanair: fix endpoint sanity check
+    - media: rc: ensure lirc is initialized before registering input device
+    - tools/kvm_stat: Fix kvm_exit filter name
+    - xen/balloon: Support xend-based toolstack take two
+    - watchdog: fix UAF in reboot notifier handling in watchdog core code
+    - bcache: add readahead cache policy options via sysfs interface
+    - eventfd: track eventfd_signal() recursion depth
+    - aio: prevent potential eventfd recursion on poll
+    - KVM: x86: Refactor picdev_write() to prevent Spectre-v1/L1TF attacks
+    - KVM: x86: Refactor prefix decoding to prevent Spectre-v1/L1TF attacks
+    - KVM: x86: Protect pmu_intel.c from Spectre-v1/L1TF attacks
+    - KVM: x86: Protect DR-based index computations from Spectre-v1/L1TF attacks
+    - KVM: x86: Protect kvm_lapic_reg_write() from Spectre-v1/L1TF attacks
+    - KVM: x86: Protect kvm_hv_msr_[get|set]_crash_data() from Spectre-v1/L1TF
+      attacks
+    - KVM: x86: Protect ioapic_write_indirect() from Spectre-v1/L1TF attacks
+    - KVM: x86: Protect MSR-based index computations in pmu.h from Spectre-v1/L1TF
+      attacks
+    - KVM: x86: Protect ioapic_read_indirect() from Spectre-v1/L1TF attacks
+    - KVM: x86: Protect MSR-based index computations from Spectre-v1/L1TF attacks
+      in x86.c
+    - KVM: x86: Protect x86_decode_insn from Spectre-v1/L1TF attacks
+    - KVM: x86: Protect MSR-based index computations in fixed_msr_to_seg_unit()
+      from Spectre-v1/L1TF attacks
+    - KVM: x86: Fix potential put_fpu() w/o load_fpu() on MPX platform
+    - KVM: PPC: Book3S HV: Uninit vCPU if vcore creation fails
+    - KVM: PPC: Book3S PR: Free shared page if mmu initialization fails
+    - kvm/svm: PKU not currently supported
+    - KVM: VMX: Add non-canonical check on writes to RTIT address MSRs
+    - KVM: x86: Don't let userspace set host-reserved cr4 bits
+    - KVM: x86: Free wbinvd_dirty_mask if vCPU creation fails
+    - KVM: x86: Handle TIF_NEED_FPU_LOAD in kvm_{load,put}_guest_fpu()
+    - KVM: x86: Ensure guest's FPU state is loaded when accessing for emulation
+    - KVM: x86: Revert "KVM: X86: Fix fpu state crash in kvm guest"
+    - KVM: s390: do not clobber registers during guest reset/store status
+    - ocfs2: fix oops when writing cloned file
+    - mm/page_alloc.c: fix uninitialized memmaps on a partially populated last
+      section
+    - arm64: dts: qcom: qcs404-evb: Set vdd_apc regulator in high power mode
+    - mm/mmu_gather: invalidate TLB correctly on batch allocation failure and
+      flush
+    - clk: tegra: Mark fuse clock as critical
+    - drm/amd/dm/mst: Ignore payload update failures
+    - virtio-balloon: initialize all vq callbacks
+    - virtio-pci: check name when counting MSI-X vectors
+    - fix up iter on short count in fuse_direct_io()
+    - broken ping to ipv6 linklocal addresses on debian buster
+    - percpu: Separate decrypted varaibles anytime encryption can be enabled
+    - ASoC: meson: axg-fifo: fix fifo threshold setup
+    - scsi: qla2xxx: Fix the endianness of the qla82xx_get_fw_size() return type
+    - scsi: csiostor: Adjust indentation in csio_device_reset
+    - scsi: qla4xxx: Adjust indentation in qla4xxx_mem_free
+    - scsi: ufs: Recheck bkops level if bkops is disabled
+    - mtd: spi-nor: Split mt25qu512a (n25q512a) entry into two
+    - phy: qualcomm: Adjust indentation in read_poll_timeout
+    - ext2: Adjust indentation in ext2_fill_super
+    - powerpc/44x: Adjust indentation in ibm4xx_denali_fixup_memsize
+    - drm: msm: mdp4: Adjust indentation in mdp4_dsi_encoder_enable
+    - NFC: pn544: Adjust indentation in pn544_hci_check_presence
+    - ppp: Adjust indentation into ppp_async_input
+    - net: smc911x: Adjust indentation in smc911x_phy_configure
+    - net: tulip: Adjust indentation in {dmfe, uli526x}_init_module
+    - IB/mlx5: Fix outstanding_pi index for GSI qps
+    - IB/core: Fix ODP get user pages flow
+    - nfsd: fix delay timer on 32-bit architectures
+    - nfsd: fix jiffies/time_t mixup in LRU list
+    - nfsd: Return the correct number of bytes written to the file
+    - virtio-balloon: Fix memory leak when unloading while hinting is in progress
+    - virtio_balloon: Fix memory leaks on errors in virtballoon_probe()
+    - ubi: fastmap: Fix inverted logic in seen selfcheck
+    - ubi: Fix an error pointer dereference in error handling code
+    - ubifs: Fix memory leak from c->sup_node
+    - regulator: core: Add regulator_is_equal() helper
+    - ASoC: sgtl5000: Fix VDDA and VDDIO comparison
+    - bonding/alb: properly access headers in bond_alb_xmit()
+    - devlink: report 0 after hitting end in region read
+    - dpaa_eth: support all modes with rate adapting PHYs
+    - net: dsa: b53: Always use dev->vlan_enabled in b53_configure_vlan()
+    - net: dsa: bcm_sf2: Only 7278 supports 2Gb/sec IMP port
+    - net: dsa: microchip: enable module autoprobe
+    - net: mvneta: move rx_dropped and rx_errors in per-cpu stats
+    - net_sched: fix a resource leak in tcindex_set_parms()
+    - net: stmmac: fix a possible endless loop
+    - net: systemport: Avoid RBUF stuck in Wake-on-LAN mode
+    - net/mlx5: IPsec, Fix esp modify function attribute
+    - net/mlx5: IPsec, fix memory leak at mlx5_fpga_ipsec_delete_sa_ctx
+    - net: macb: Remove unnecessary alignment check for TSO
+    - net: macb: Limit maximum GEM TX length in TSO
+    - taprio: Fix enabling offload with wrong number of traffic classes
+    - taprio: Fix still allowing changing the flags during runtime
+    - taprio: Add missing policy validation for flags
+    - taprio: Use taprio_reset_tc() to reset Traffic Classes configuration
+    - taprio: Fix dropping packets when using taprio + ETF offloading
+    - ipv6/addrconf: fix potential NULL deref in inet6_set_link_af()
+    - qed: Fix timestamping issue for L2 unicast ptp packets.
+    - drop_monitor: Do not cancel uninitialized work item
+    - net/mlx5: Fix deadlock in fs_core
+    - net/mlx5: Deprecate usage of generic TLS HW capability bit
+    - ASoC: Intel: skl_hda_dsp_common: Fix global-out-of-bounds bug
+    - mfd: da9062: Fix watchdog compatible string
+    - mfd: rn5t618: Mark ADC control register volatile
+    - mfd: bd70528: Fix hour register mask
+    - x86/timer: Don't skip PIT setup when APIC is disabled or in legacy mode
+    - btrfs: use bool argument in free_root_pointers()
+    - btrfs: free block groups after free'ing fs trees
+    - drm/dp_mst: Remove VCPI while disabling topology mgr
+    - KVM: x86/mmu: Apply max PA check for MMIO sptes to 32-bit KVM
+    - KVM: x86: use CPUID to locate host page table reserved bits
+    - KVM: x86: Use gpa_t for cr2/gpa to fix TDP support on 32-bit KVM
+    - KVM: x86: fix overlap between SPTE_MMIO_MASK and generation
+    - KVM: nVMX: vmread should not set rflags to specify success in case of #PF
+    - KVM: Use vcpu-specific gva->hva translation when querying host page size
+    - KVM: Play nice with read-only memslots when querying host page size
+    - cifs: fail i/o on soft mounts if sessionsetup errors out
+    - x86/apic/msi: Plug non-maskable MSI affinity race
+    - clocksource: Prevent double add_timer_on() for watchdog_timer
+    - perf/core: Fix mlock accounting in perf_mmap()
+    - rxrpc: Fix service call disconnection
+    - regulator fix for "regulator: core: Add regulator_is_equal() helper"
+    - powerpc/kuap: Fix set direction in allow/prevent_user_access()
+    - Linux 5.4.19
+    - [Config] updateconfigs following v5.4.19 stable update
+
+  * 5.4.0-11 crash on cryptsetup open (LP: #1860231) // Focal update: v5.4.19
+    upstream stable release (LP: #1863588)
+    - dm: fix potential for q->make_request_fn NULL pointer
+
+  * Miscellaneous Ubuntu changes
+    - update dkms package versions
+    - [debian] ignore missing wireguard module
+    - debian: remove snapdragon config, rules and flavour
+    - [Config] updateconfigs following snapdragon removal
+    - remove snapdragon abi files
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Thu, 20 Feb 2020 11:42:30 -0600
+
+linux (5.4.0-14.17) focal; urgency=medium
+
+  * Empty entry.
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Wed, 19 Feb 2020 11:46:35 -0600
+
+linux-5.4 (5.4.0-14.17) focal; urgency=medium
+
+  * focal/linux-5.4: 5.4.0-14.17 -proposed tracker (LP: #1862255)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update helper scripts
+
+  * Boot log is swamped with "debugfs: Directory 'imc' with parent 'powerpc'
+    already present" messages on kernel 5.4 (LP: #1861379)
+    - powerpc/powernv: Avoid re-registration of imc debugfs directory
+
+  * CVE-2019-3016
+    - SAUCE: x86/kvm: Be careful not to clear KVM_VCPU_FLUSH_TLB bit
+    - SAUCE: x86/kvm: Introduce kvm_(un)map_gfn()
+    - SAUCE: x86/kvm: Cache gfn to pfn translation
+    - SAUCE: x86/KVM: Make sure KVM_VCPU_FLUSH_TLB flag is not missed
+    - SAUCE: x86/KVM: Clean up host's steal time structure
+
+  * installing linux-modules-nvidia does not remove nvidia-dkms, and the kernel
+    prioritizes the wrong version of the module from disk (LP: #1856414)
+    - Revert "UBUNTU: [Packaging] dkms -- switch basic provides to *-modules"
+    - Revert "UBUNTU: [Packaging] dkms -- add Provides: specifiers for existing
+      zfs/nvidia/vbox"
+    - Revert "UBUNTU: [packaging] dkms-build -- include versioned provides"
+    - [Packaging] wireguard -- drop provides
+
+  * Focal update: v5.4.18 upstream stable release (LP: #1862203)
+    - vfs: fix do_last() regression
+    - cifs: fix soft mounts hanging in the reconnect code
+    - x86/resctrl: Fix a deadlock due to inaccurate reference
+    - x86/resctrl: Fix use-after-free when deleting resource groups
+    - x86/resctrl: Fix use-after-free due to inaccurate refcount of rdtgroup
+    - e1000e: Drop unnecessary __E1000_DOWN bit twiddling
+    - e1000e: Revert "e1000e: Make watchdog use delayed work"
+    - gfs2: Another gfs2_find_jhead fix
+    - perf c2c: Fix return type for histogram sorting comparision functions
+    - PM / devfreq: Add new name attribute for sysfs
+    - tools lib: Fix builds when glibc contains strlcpy()
+    - arm64: kbuild: remove compressed images on 'make ARCH=arm64 (dist)clean'
+    - mm/mempolicy.c: fix out of bounds write in mpol_parse_str()
+    - reiserfs: Fix memory leak of journal device string
+    - media: digitv: don't continue if remote control state can't be read
+    - media: af9005: uninitialized variable printked
+    - media: vp7045: do not read uninitialized values if usb transfer fails
+    - media: gspca: zero usb_buf
+    - media: dvb-usb/dvb-usb-urb.c: initialize actlen to 0
+    - tomoyo: Use atomic_t for statistics counter
+    - ttyprintk: fix a potential deadlock in interrupt context issue
+    - Bluetooth: Fix race condition in hci_release_sock()
+    - cgroup: Prevent double killing of css when enabling threaded cgroup
+    - clk: sunxi-ng: v3s: Fix incorrect number of hw_clks.
+    - arm64: dts: meson-sm1-sei610: add gpio bluetooth interrupt
+    - ARM: dts: sun8i: a83t: Correct USB3503 GPIOs polarity
+    - ARM: dts: am57xx-beagle-x15/am57xx-idk: Remove "gpios" for endpoint dt nodes
+    - ARM: dts: beagle-x15-common: Model 5V0 regulator
+    - soc: ti: wkup_m3_ipc: Fix race condition with rproc_boot
+    - tools lib traceevent: Fix memory leakage in filter_event
+    - rseq: Unregister rseq for clone CLONE_VM
+    - clk: sunxi-ng: sun8i-r: Fix divider on APB0 clock
+    - clk: sunxi-ng: h6-r: Fix AR100/R_APB2 parent order
+    - mac80211: mesh: restrict airtime metric to peered established plinks
+    - clk: mmp2: Fix the order of timer mux parents
+    - ASoC: rt5640: Fix NULL dereference on module unload
+    - s390/zcrypt: move ap device reset from bus to driver code
+    - i40e: Fix virtchnl_queue_select bitmap validation
+    - ixgbevf: Remove limit of 10 entries for unicast filter list
+    - ixgbe: Fix calculation of queue with VFs and flow director on interface flap
+    - igb: Fix SGMII SFP module discovery for 100FX/LX.
+    - iavf: remove current MAC address filter on VF reset
+    - platform/x86: GPD pocket fan: Allow somewhat lower/higher temperature limits
+    - platform/x86: intel_pmc_core: update Comet Lake platform driver
+    - ASoC: hdac_hda: Fix error in driver removal after failed probe
+    - ASoC: sti: fix possible sleep-in-atomic
+    - qmi_wwan: Add support for Quectel RM500Q
+    - parisc: Use proper printk format for resource_size_t
+    - lkdtm/bugs: fix build error in lkdtm_UNSET_SMEP
+    - wireless: fix enabling channel 12 for custom regulatory domain
+    - cfg80211: Fix radar event during another phy CAC
+    - mac80211: Fix TKIP replay protection immediately after key setup
+    - wireless: wext: avoid gcc -O3 warning
+    - perf/x86/intel/uncore: Add PCI ID of IMC for Xeon E3 V5 Family
+    - perf/x86/intel/uncore: Remove PCIe3 unit for SNR
+    - riscv: delete temporary files
+    - XArray: Fix xas_pause at ULONG_MAX
+    - iwlwifi: pcie: allocate smaller dev_cmd for TX headers
+    - iwlwifi: Don't ignore the cap field upon mcc update
+    - iwlwifi: dbg: force stop the debug monitor HW
+    - Input: evdev - convert kzalloc()/vzalloc() to kvzalloc()
+    - ARM: dts: am335x-boneblack-common: fix memory size
+    - xfrm: interface: do not confirm neighbor when do pmtu update
+    - Input: max77650-onkey - add of_match table
+    - scsi: fnic: do not queue commands during fwreset
+    - ARM: 8955/1: virt: Relax arch timer version check during early boot
+    - led: max77650: add of_match table
+    - tee: optee: Fix compilation issue with nommu
+    - r8152: get default setting of WOL before initializing
+    - r8152: disable U2P3 for RTL8153B
+    - r8152: Disable PLA MCU clock speed down
+    - r8152: disable test IO for RTL8153B
+    - r8152: avoid the MCU to clear the lanwake
+    - r8152: disable DelayPhyPwrChg
+    - ARM: dts: am43x-epos-evm: set data pin directions for spi0 and spi1
+    - qlcnic: Fix CPU soft lockup while collecting firmware dump
+    - powerpc/fsl/dts: add fsl,erratum-a011043
+    - net/fsl: treat fsl,erratum-a011043
+    - net: fsl/fman: rename IF_MODE_XGMII to IF_MODE_10G
+    - seq_tab_next() should increase position index
+    - l2t_seq_next should increase position index
+    - netfilter: conntrack: sctp: use distinct states for new SCTP connections
+    - netfilter: nf_tables_offload: fix check the chain offload flag
+    - net: Fix skb->csum update in inet_proto_csum_replace16().
+    - btrfs: do not zero f_bavail if we have available space
+    - cpuidle: teo: Avoid using "early hits" incorrectly
+    - flow_dissector: Fix to use new variables for port ranges in bpf hook
+    - dm thin: fix use-after-free in metadata_pre_commit_callback
+    - perf report: Fix no libunwind compiled warning break s390 issue
+    - mm/migrate.c: also overwrite error when it is bigger than zero
+    - ASoC: topology: fix soc_tplg_fe_link_create() - link->dobj initialization
+      order
+    - Revert "rsi: fix potential null dereference in rsi_probe()"
+    - tracing/uprobe: Fix to make trace_uprobe_filter alignment safe
+    - Linux 5.4.18
+
+  *  Integrate Intel SGX driver into linux-azure (LP: #1844245)
+    - [Packaging] Add systemd service to load intel_sgx
+
+  * Focal update: v5.4.17 upstream stable release (LP: #1861784)
+    - Bluetooth: btusb: fix non-atomic allocation in completion handler
+    - orinoco_usb: fix interface sanity check
+    - rsi_91x_usb: fix interface sanity check
+    - usb: dwc3: pci: add ID for the Intel Comet Lake -V variant
+    - usb: host: xhci-tegra: set MODULE_FIRMWARE for tegra186
+    - USB: serial: ir-usb: add missing endpoint sanity check
+    - USB: serial: ir-usb: fix link-speed handling
+    - USB: serial: ir-usb: fix IrLAP framing
+    - usb: dwc3: turn off VBUS when leaving host mode
+    - usb: typec: wcove: fix "op-sink-microwatt" default that was in mW
+    - usb: typec: fusb302: fix "op-sink-microwatt" default that was in mW
+    - staging: most: net: fix buffer overflow
+    - staging: wlan-ng: ensure error return is actually returned
+    - staging: vt6656: correct packet types for CTS protect, mode.
+    - staging: vt6656: use NULLFUCTION stack on mac80211
+    - staging: vt6656: Fix false Tx excessive retries reporting.
+    - serial: 8250_bcm2835aux: Fix line mismatch on driver unbind
+    - serial: imx: fix a race condition in receive path
+    - debugfs: Return -EPERM when locked down
+    - component: do not dereference opaque pointer in debugfs
+    - binder: fix log spam for existing debugfs file creation.
+    - mei: hdcp: bind only with i915 on the same PCH
+    - mei: me: add comet point (lake) H device ids
+    - iio: adc: stm32-dfsdm: fix single conversion
+    - iio: st_gyro: Correct data for LSM9DS0 gyro
+    - driver core: Fix test_async_driver_probe if NUMA is disabled
+    - crypto: chelsio - fix writing tfm flags to wrong place
+    - CIFS: Fix task struct use-after-free on reconnect
+    - cifs: set correct max-buffer-size for smb2_ioctl_init()
+    - cifs: Fix memory allocation in __smb2_handle_cancelled_cmd()
+    - ath9k: fix storage endpoint lookup
+    - brcmfmac: fix interface sanity check
+    - rtl8xxxu: fix interface sanity check
+    - zd1211rw: fix storage endpoint lookup
+    - net_sched: ematch: reject invalid TCF_EM_SIMPLE
+    - net_sched: fix ops->bind_class() implementations
+    - net_sched: walk through all child classes in tc_bind_tclass()
+    - net: socionext: fix possible user-after-free in netsec_process_rx
+    - net: socionext: fix xdp_result initialization in netsec_process_rx
+    - udp: segment looped gso packets correctly
+    - mlxsw: minimal: Fix an error handling path in 'mlxsw_m_port_create()'
+    - net: include struct nhmsg size in nh nlmsg size
+    - rxrpc: Fix use-after-free in rxrpc_receive_data()
+    - arc: eznps: fix allmodconfig kconfig warning
+    - HID: Add quirk for Xin-Mo Dual Controller
+    - HID: ite: Add USB id match for Acer SW5-012 keyboard dock
+    - HID: asus: Ignore Asus vendor-page usage-code 0xff events
+    - HID: Add quirk for incorrect input length on Lenovo Y720
+    - HID: intel-ish-hid: ipc: add CMP device id
+    - HID: wacom: Recognize new MobileStudio Pro PID
+    - ASoC: SOF: fix fault at driver unload after failed probe
+    - ASoC: SOF: Intel: hda: hda-dai: fix oops on hda_link .hw_free
+    - drivers/hid/hid-multitouch.c: fix a possible null pointer access.
+    - phy: qcom-qmp: Increase PHY ready timeout
+    - ASoC: fsl_audmix: add missed pm_runtime_disable
+    - ASoC: topology: Prevent use-after-free in snd_soc_get_pcm_runtime()
+    - phy: cpcap-usb: Prevent USB line glitches from waking up modem
+    - HID: intel-ish-hid: ipc: Add Tiger Lake PCI device ID
+    - watchdog: max77620_wdt: fix potential build errors
+    - watchdog: rn5t618_wdt: fix module aliases
+    - watchdog: orion: fix platform_get_irq() complaints
+    - usb: musb: jz4740: Silence error if code is -EPROBE_DEFER
+    - can: tcan4x5x: tcan4x5x_parse_config(): reset device before register access
+    - spi: spi-dw: Add lock protect dw_spi rx/tx to prevent concurrent calls
+    - net: Google gve: Remove dma_wmb() before ringing doorbell
+    - drivers/net/b44: Change to non-atomic bit operations on pwol_mask
+    - net: wan: sdla: Fix cast from pointer to integer of different size
+    - gpio: max77620: Add missing dependency on GPIOLIB_IRQCHIP
+    - iommu/dma: fix variable 'cookie' set but not used
+    - drm/amd/display: Reduce HDMI pixel encoding if max clock is exceeded
+    - stmmac: debugfs entry name is not be changed when udev rename device name.
+    - atm: eni: fix uninitialized variable warning
+    - HID: steam: Fix input device disappearing
+    - extcon-intel-cht-wc: Don't reset USB data connection at probe
+    - ASoC: Intel: cht_bsw_rt5645: Add quirk for boards using pmc_plt_clk_0
+    - drm/amdgpu/SRIOV: add navi12 pci id for SRIOV (v2)
+    - libbpf: Fix BTF-defined map's __type macro handling of arrays
+    - staging: mt7621-pci: add quirks for 'E2' revision using
+      'soc_device_attribute'
+    - platform/x86: dell-laptop: disable kbd backlight on Inspiron 10xx
+    - PCI: Add DMA alias quirk for Intel VCA NTB
+    - media: dvbsky: add support for eyeTV Geniatech T2 lite
+    - bus: ti-sysc: Handle mstandby quirk and use it for musb
+    - bus: ti-sysc: Use swsup quirks also for am335x musb
+    - spi: pxa2xx: Add support for Intel Comet Lake-H
+    - iommu/amd: Support multiple PCI DMA aliases in device table
+    - iommu/amd: Support multiple PCI DMA aliases in IRQ Remapping
+    - perf/imx_ddr: Add enhanced AXI ID filter support
+    - ARM: config: aspeed-g5: Enable 8250_DW quirks
+    - ARM: OMAP2+: SmartReflex: add omap_sr_pdata definition
+    - mmc: sdhci-pci: Quirk for AMD SDHC Device 0x7906
+    - mmc: sdhci-pci: Add support for Intel JSL
+    - bus: ti-sysc: Add module enable quirk for audio AESS
+    - usb-storage: Disable UAS on JMicron SATA enclosure
+    - ALSA: hda/realtek - Move some alc236 pintbls to fallback table
+    - Bluetooth: Allow combination of BDADDR_PROPERTY and INVALID_BDADDR quirks
+    - Bluetooth: btbcm: Use the BDADDR_PROPERTY quirk
+    - bus: ti-sysc: Fix missing force mstandby quirk handling
+    - rsi: fix use-after-free on failed probe and unbind
+    - rsi: fix use-after-free on probe errors
+    - rsi: fix memory leak on failed URB submission
+    - rsi: fix non-atomic allocation in completion handler
+    - crypto: af_alg - Use bh_lock_sock in sk_destruct
+    - crypto: vmx - reject xts inputs that are too short
+    - crypto: caam - do not reset pointer size from MCFGR register
+    - crypto: pcrypt - Fix user-after-free on module unload
+    - KVM: arm64: Write arch.mdcr_el2 changes since last vcpu_load on VHE
+    - Revert "um: Enable CONFIG_CONSTRUCTORS"
+    - power/supply: ingenic-battery: Don't change scale if there's only one
+    - Linux 5.4.17
+
+  * Miscellaneous Ubuntu changes
+    - [Packaging] dkms -- switch basic provides to *-modules
+    - update dkms package versions
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Thu, 06 Feb 2020 16:30:48 -0600
+
+linux-5.4 (5.4.0-13.16) focal; urgency=medium
+
+  * focal/linux-5.4: 5.4.0-13.16 -proposed tracker (LP: #1861352)
+
+  * system hang: i915 Resetting rcs0 for hang on rcs0 (LP: #1861395)
+    - drm/i915/gt: Detect if we miss WaIdleLiteRestore
+
+  * Focal update: v5.4.16 upstream stable release (LP: #1861385)
+    - can, slip: Protect tty->disc_data in write_wakeup and close with RCU
+    - firestream: fix memory leaks
+    - gtp: make sure only SOCK_DGRAM UDP sockets are accepted
+    - ipv6: sr: remove SKB_GSO_IPXIP6 on End.D* actions
+    - net: bcmgenet: Use netif_tx_napi_add() for TX NAPI
+    - net: cxgb3_main: Add CAP_NET_ADMIN check to CHELSIO_GET_MEM
+    - net: ip6_gre: fix moving ip6gre between namespaces
+    - net, ip6_tunnel: fix namespaces move
+    - net, ip_tunnel: fix namespaces move
+    - net: rtnetlink: validate IFLA_MTU attribute in rtnl_create_link()
+    - net_sched: fix datalen for ematch
+    - net_sched: use validated TCA_KIND attribute in tc_new_tfilter()
+    - net-sysfs: Fix reference count leak
+    - net: usb: lan78xx: Add .ndo_features_check
+    - Revert "udp: do rmem bulk free even if the rx sk queue is empty"
+    - tcp_bbr: improve arithmetic division in bbr_update_bw()
+    - tcp: do not leave dangling pointers in tp->highest_sack
+    - tun: add mutex_unlock() call and napi.skb clearing in tun_get_user()
+    - airo: Fix possible info leak in AIROOLDIOCTL/SIOCDEVPRIVATE
+    - airo: Add missing CAP_NET_ADMIN check in AIROOLDIOCTL/SIOCDEVPRIVATE
+    - mlxsw: spectrum_acl: Fix use-after-free during reload
+    - fou: Fix IPv6 netlink policy
+    - net: Fix packet reordering caused by GRO and listified RX cooperation
+    - net/mlx5: Fix lowest FDB pool size
+    - net/mlx5: Update the list of the PCI supported devices
+    - net/mlx5: DR, Enable counter on non-fwd-dest objects
+    - net/mlx5: E-Switch, Prevent ingress rate configuration of uplink rep
+    - net/mlx5: DR, use non preemptible call to get the current cpu number
+    - net/mlx5e: kTLS, Fix corner-case checks in TX resync flow
+    - net/mlx5e: kTLS, Remove redundant posts in TX resync flow
+    - net/mlx5e: kTLS, Do not send decrypted-marked SKBs via non-accel path
+    - ipv4: Detect rollover in specific fib table dump
+    - Revert "io_uring: only allow submit from owning task"
+    - afs: Fix characters allowed into cell names
+    - hwmon: (adt7475) Make volt2reg return same reg as reg2volt input
+    - hwmon: (core) Do not use device managed functions for memory allocations
+    - ceph: hold extra reference to r_parent over life of request
+    - PCI: Mark AMD Navi14 GPU rev 0xc5 ATS as broken
+    - drm/panfrost: Add the panfrost_gem_mapping concept
+    - drm/i915: Align engine->uabi_class/instance with i915_drm.h
+    - PM: hibernate: fix crashes with init_on_free=1
+    - tracing: trigger: Replace unneeded RCU-list traversals
+    - tracing/uprobe: Fix double perf_event linking on multiprobe uprobe
+    - tracing: Do not set trace clock if tracefs lockdown is in effect
+    - tracing: Fix histogram code when expression has same var as value
+    - powerpc/mm/hash: Fix sharing context ids between kernel & userspace
+    - powerpc/xive: Discard ESB load value when interrupt is invalid
+    - Revert "iwlwifi: mvm: fix scan config command size"
+    - iwlwifi: mvm: don't send the IWL_MVM_RXQ_NSSN_SYNC notif to Rx queues
+    - XArray: Fix infinite loop with entry at ULONG_MAX
+    - XArray: Fix xa_find_after with multi-index entries
+    - XArray: Fix xas_find returning too many entries
+    - pinctrl: sunrisepoint: Add missing Interrupt Status register offset
+    - iommu/vt-d: Call __dmar_remove_one_dev_info with valid pointer
+    - Input: keyspan-remote - fix control-message timeouts
+    - Revert "Input: synaptics-rmi4 - don't increment rmiaddr for SMBus transfers"
+    - ARM: 8950/1: ftrace/recordmcount: filter relocation types
+    - mmc: tegra: fix SDR50 tuning override
+    - mmc: sdhci: fix minimum clock rate for v3 controller
+    - mmc: sdhci_am654: Remove Inverted Write Protect flag
+    - mmc: sdhci_am654: Reset Command and Data line after tuning
+    - mlxsw: switchx2: Do not modify cloned SKBs during xmit
+    - net/tls: fix async operation
+    - Input: pm8xxx-vib - fix handling of separate enable register
+    - Input: sur40 - fix interface sanity checks
+    - Input: gtco - fix endpoint sanity check
+    - Input: aiptek - fix endpoint sanity check
+    - Input: pegasus_notetaker - fix endpoint sanity check
+    - Input: sun4i-ts - add a check for devm_thermal_zone_of_sensor_register
+    - netfilter: nft_osf: add missing check for DREG attribute
+    - lib: Reduce user_access_begin() boundaries in strncpy_from_user() and
+      strnlen_user()
+    - iommu/amd: Fix IOMMU perf counter clobbering during init
+    - readdir: make user_access_begin() use the real access range
+    - leds: gpio: Fix uninitialized gpio label for fwnode based probe
+    - hsr: Fix a compilation error
+    - hwmon: (nct7802) Fix voltage limits to wrong registers
+    - hwmon: (nct7802) Fix non-working alarm on voltages
+    - scsi: RDMA/isert: Fix a recently introduced regression related to logout
+    - tracing: xen: Ordered comparison of function pointers
+    - iwlwifi: mvm: fix SKB leak on invalid queue
+    - iwlwifi: mvm: fix potential SKB leak on TXQ TX
+    - drm/i915/userptr: fix size calculation
+    - xfrm: support output_mark for offload ESP packets
+    - net, sk_msg: Don't check if sock is locked when tearing down psock
+    - do_last(): fetch directory ->i_mode and ->i_uid before it's too late
+    - readdir: be more conservative with directory entry names
+    - net/sonic: Add mutual exclusion for accessing shared state
+    - net/sonic: Clear interrupt flags immediately
+    - net/sonic: Use MMIO accessors
+    - net/sonic: Fix interface error stats collection
+    - net/sonic: Fix receive buffer handling
+    - net/sonic: Avoid needless receive descriptor EOL flag updates
+    - net/sonic: Improve receive descriptor status flag check
+    - net/sonic: Fix receive buffer replenishment
+    - net/sonic: Quiesce SONIC before re-initializing descriptor memory
+    - net/sonic: Fix command register usage
+    - net/sonic: Fix CAM initialization
+    - net/sonic: Prevent tx watchdog timeout
+    - media: v4l2-ioctl.c: zero reserved fields for S/TRY_FMT
+    - netfilter: ipset: use bitmap infrastructure completely
+    - netfilter: nf_tables: add __nft_chain_type_get()
+    - netfilter: nf_tables: autoload modules from the abort path
+    - net/x25: fix nonblocking connect
+    - Linux 5.4.16
+
+  * Build and ship a signed wireguard.ko (LP: #1861284)
+    - [Packaging] wireguard -- add support for building signed .ko
+    - [Config] wireguard -- enable on all architectures
+
+  * installing linux-modules-nvidia does not remove nvidia-dkms, and the kernel
+    prioritizes the wrong version of the module from disk (LP: #1856414)
+    - [packaging] dkms-build -- include versioned provides
+    - [Packaging] dkms -- add Provides: specifiers for existing zfs/nvidia/vbox
+
+  * dkms artifacts may expire from the pool (LP: #1850958)
+    - [Packaging] autoreconstruct -- manage executable debian files
+    - [packaging] handle downloads from the librarian better
+
+  * QAT drivers for C3XXX and C62X not included as modules (LP: #1845959)
+    - [Config] CRYPTO_DEV_QAT_C3XXX=m, CRYPTO_DEV_QAT_C62X=m and
+      CRYPTO_DEV_QAT_DH895xCC=m
+
+  * 5.4.0-11 crash on cryptsetup open (LP: #1860231)
+    - SAUCE: blk/core: Gracefully handle unset make_request_fn
+
+  * multi-zone raid0 corruption (LP: #1850540)
+    - SAUCE: md/raid0: Use kernel specific layout
+
+  * ipsec interfaces: fix sending with bpf_redirect() / AF_PACKET sockets
+    (LP: #1860969)
+    - vti[6]: fix packet tx through bpf_redirect()
+    - xfrm interface: fix packet tx through bpf_redirect()
+
+  * Focal update: v5.4.15 upstream stable release (LP: #1861091)
+    - drm/i915: Fix pid leak with banned clients
+    - libbpf: Fix compatibility for kernels without need_wakeup
+    - libbpf: Fix memory leak/double free issue
+    - libbpf: Fix potential overflow issue
+    - libbpf: Fix another potential overflow issue in bpf_prog_linfo
+    - libbpf: Make btf__resolve_size logic always check size error condition
+    - bpf: Force .BTF section start to zero when dumping from vmlinux
+    - samples: bpf: update map definition to new syntax BTF-defined map
+    - samples/bpf: Fix broken xdp_rxq_info due to map order assumptions
+    - ARM: dts: logicpd-torpedo-37xx-devkit-28: Reference new DRM panel
+    - ARM: OMAP2+: Add missing put_device() call in omapdss_init_of()
+    - xfs: Sanity check flags of Q_XQUOTARM call
+    - i2c: stm32f7: rework slave_id allocation
+    - i2c: i2c-stm32f7: fix 10-bits check in slave free id search loop
+    - mfd: intel-lpss: Add default I2C device properties for Gemini Lake
+    - SUNRPC: Fix svcauth_gss_proxy_init()
+    - SUNRPC: Fix backchannel latency metrics
+    - powerpc/security: Fix debugfs data leak on 32-bit
+    - powerpc/pseries: Enable support for ibm,drc-info property
+    - powerpc/kasan: Fix boot failure with RELOCATABLE && FSL_BOOKE
+    - powerpc/archrandom: fix arch_get_random_seed_int()
+    - tipc: reduce sensitive to retransmit failures
+    - tipc: update mon's self addr when node addr generated
+    - tipc: fix potential memory leak in __tipc_sendmsg()
+    - tipc: fix wrong socket reference counter after tipc_sk_timeout() returns
+    - tipc: fix wrong timeout input for tipc_wait_for_cond()
+    - net/mlx5e: Fix free peer_flow when refcount is 0
+    - phy: lantiq: vrx200-pcie: fix error return code in
+      ltq_vrx200_pcie_phy_power_on()
+    - net: phy: broadcom: Fix RGMII delays configuration for BCM54210E
+    - phy: ti: gmii-sel: fix mac tx internal delay for rgmii-rxid
+    - mt76: mt76u: fix endpoint definition order
+    - mt7601u: fix bbp version check in mt7601u_wait_bbp_ready
+    - ice: fix stack leakage
+    - s390/pkey: fix memory leak within _copy_apqns_from_user()
+    - nfsd: depend on CRYPTO_MD5 for legacy client tracking
+    - crypto: amcc - restore CRYPTO_AES dependency
+    - crypto: sun4i-ss - fix big endian issues
+    - perf map: No need to adjust the long name of modules
+    - leds: tlc591xx: update the maximum brightness
+    - soc/tegra: pmc: Fix crashes for hierarchical interrupts
+    - soc: qcom: llcc: Name regmaps to avoid collisions
+    - soc: renesas: Add missing check for non-zero product register address
+    - soc: aspeed: Fix snoop_file_poll()'s return type
+    - watchdog: sprd: Fix the incorrect pointer getting from driver data
+    - ipmi: Fix memory leak in __ipmi_bmc_register
+    - sched/core: Further clarify sched_class::set_next_task()
+    - gpiolib: No need to call gpiochip_remove_pin_ranges() twice
+    - rtw88: fix beaconing mode rsvd_page memory violation issue
+    - rtw88: fix error handling when setup efuse info
+    - drm/panfrost: Add missing check for pfdev->regulator
+    - drm: panel-lvds: Potential Oops in probe error handling
+    - drm/amdgpu: remove excess function parameter description
+    - hwrng: omap3-rom - Fix missing clock by probing with device tree
+    - dpaa2-eth: Fix minor bug in ethtool stats reporting
+    - drm/rockchip: Round up _before_ giving to the clock framework
+    - software node: Get reference to parent swnode in get_parent op
+    - PCI: mobiveil: Fix csr_read()/write() build issue
+    - drm: rcar_lvds: Fix color mismatches on R-Car H2 ES2.0 and later
+    - net: netsec: Correct dma sync for XDP_TX frames
+    - ACPI: platform: Unregister stale platform devices
+    - pwm: sun4i: Fix incorrect calculation of duty_cycle/period
+    - regulator: bd70528: Add MODULE_ALIAS to allow module auto loading
+    - drm/amdgpu/vi: silence an uninitialized variable warning
+    - power: supply: bd70528: Add MODULE_ALIAS to allow module auto loading
+    - firmware: imx: Remove call to devm_of_platform_populate
+    - libbpf: Don't use kernel-side u32 type in xsk.c
+    - rcu: Fix uninitialized variable in nocb_gp_wait()
+    - dpaa_eth: perform DMA unmapping before read
+    - dpaa_eth: avoid timestamp read on error paths
+    - scsi: ufs: delete redundant function ufshcd_def_desc_sizes()
+    - net: openvswitch: don't unlock mutex when changing the user_features fails
+    - hv_netvsc: flag software created hash value
+    - rt2800: remove errornous duplicate condition
+    - net: neigh: use long type to store jiffies delta
+    - net: axienet: Fix error return code in axienet_probe()
+    - selftests: gen_kselftest_tar.sh: Do not clobber kselftest/
+    - rtc: bd70528: fix module alias to autoload module
+    - packet: fix data-race in fanout_flow_is_huge()
+    - i2c: stm32f7: report dma error during probe
+    - kselftests: cgroup: Avoid the reuse of fd after it is deallocated
+    - firmware: arm_scmi: Fix doorbell ring logic for !CONFIG_64BIT
+    - mmc: sdio: fix wl1251 vendor id
+    - mmc: core: fix wl1251 sdio quirks
+    - tee: optee: Fix dynamic shm pool allocations
+    - tee: optee: fix device enumeration error handling
+    - workqueue: Add RCU annotation for pwq list walk
+    - SUNRPC: Fix another issue with MIC buffer space
+    - sched/cpufreq: Move the cfs_rq_util_change() call to cpufreq_update_util()
+    - mt76: mt76u: rely on usb_interface instead of usb_dev
+    - dma-direct: don't check swiotlb=force in dma_direct_map_resource
+    - afs: Remove set but not used variables 'before', 'after'
+    - dmaengine: ti: edma: fix missed failure handling
+    - drm/radeon: fix bad DMA from INTERRUPT_CNTL2
+    - xdp: Fix cleanup on map free for devmap_hash map type
+    - platform/chrome: wilco_ec: fix use after free issue
+    - block: fix memleak of bio integrity data
+    - s390/qeth: fix dangling IO buffers after halt/clear
+    - net-sysfs: Call dev_hold always in netdev_queue_add_kobject
+    - gpio: aspeed: avoid return type warning
+    - phy/rockchip: inno-hdmi: round clock rate down to closest 1000 Hz
+    - optee: Fix multi page dynamic shm pool alloc
+    - Linux 5.4.15
+
+  * Focal update: v5.4.14 upstream stable release (LP: #1861090)
+    - ARM: dts: meson8: fix the size of the PMU registers
+    - clk: qcom: gcc-sdm845: Add missing flag to votable GDSCs
+    - soc: amlogic: meson-ee-pwrc: propagate PD provider registration errors
+    - soc: amlogic: meson-ee-pwrc: propagate errors from pm_genpd_init()
+    - dt-bindings: reset: meson8b: fix duplicate reset IDs
+    - ARM: dts: imx6q-dhcom: fix rtc compatible
+    - arm64: dts: ls1028a: fix endian setting for dcfg
+    - arm64: dts: imx8mm: Change SDMA1 ahb clock for imx8mm
+    - bus: ti-sysc: Fix iterating over clocks
+    - clk: Don't try to enable critical clocks if prepare failed
+    - Revert "gpio: thunderx: Switch to GPIOLIB_IRQCHIP"
+    - arm64: dts: imx8mq-librem5-devkit: use correct interrupt for the
+      magnetometer
+    - ASoC: msm8916-wcd-digital: Reset RX interpolation path after use
+    - ASoC: stm32: sai: fix possible circular locking
+    - ASoC: stm32: dfsdm: fix 16 bits record
+    - ASoC: msm8916-wcd-analog: Fix selected events for MIC BIAS External1
+    - ASoC: msm8916-wcd-analog: Fix MIC BIAS Internal1
+    - ARM: OMAP2+: Fix ti_sysc_find_one_clockdomain to check for to_clk_hw_omap
+    - ARM: dts: imx7ulp: fix reg of cpu node
+    - ARM: dts: imx6q-dhcom: Fix SGTL5000 VDDIO regulator connection
+    - ASoC: Intel: bytcht_es8316: Fix Irbis NB41 netbook quirk
+    - ALSA: dice: fix fallback from protocol extension into limited functionality
+    - ALSA: seq: Fix racy access for queue timer in proc read
+    - ALSA: firewire-tascam: fix corruption due to spin lock without restoration
+      in SoftIRQ context
+    - ALSA: usb-audio: fix sync-ep altsetting sanity check
+    - arm64: dts: allwinner: a64: olinuxino: Fix SDIO supply regulator
+    - arm64: dts: allwinner: a64: olinuxino: Fix eMMC supply regulator
+    - arm64: dts: agilex/stratix10: fix pmu interrupt numbers
+    - Fix built-in early-load Intel microcode alignment
+    - clk: sunxi-ng: r40: Allow setting parent rate for external clock outputs
+    - block: fix an integer overflow in logical block size
+    - fuse: fix fuse_send_readpages() in the syncronous read case
+    - io_uring: only allow submit from owning task
+    - cpuidle: teo: Fix intervals[] array indexing bug
+    - ARM: dts: am571x-idk: Fix gpios property to have the correct gpio number
+    - ARM: davinci: select CONFIG_RESET_CONTROLLER
+    - perf: Correctly handle failed perf_get_aux_event()
+    - iio: adc: ad7124: Fix DT channel configuration
+    - iio: imu: st_lsm6dsx: Fix selection of ST_LSM6DS3_ID
+    - iio: light: vcnl4000: Fix scale for vcnl4040
+    - iio: chemical: pms7003: fix unmet triggered buffer dependency
+    - iio: buffer: align the size of scan bytes to size of the largest element
+    - USB: serial: simple: Add Motorola Solutions TETRA MTP3xxx and MTP85xx
+    - USB: serial: option: Add support for Quectel RM500Q
+    - USB: serial: opticon: fix control-message timeouts
+    - USB: serial: option: add support for Quectel RM500Q in QDL mode
+    - USB: serial: suppress driver bind attributes
+    - USB: serial: ch341: handle unbound port at reset_resume
+    - USB: serial: io_edgeport: handle unbound ports on URB completion
+    - USB: serial: io_edgeport: add missing active-port sanity check
+    - USB: serial: keyspan: handle unbound ports
+    - USB: serial: quatech2: handle unbound ports
+    - staging: comedi: ni_routes: fix null dereference in ni_find_route_source()
+    - staging: comedi: ni_routes: allow partial routing information
+    - scsi: fnic: fix invalid stack access
+    - scsi: mptfusion: Fix double fetch bug in ioctl
+    - ptrace: reintroduce usage of subjective credentials in ptrace_has_cap()
+    - mtd: rawnand: gpmi: Fix suspend/resume problem
+    - mtd: rawnand: gpmi: Restore nfc timing setup after suspend/resume
+    - usb: core: hub: Improved device recognition on remote wakeup
+    - cpu/SMT: Fix x86 link error without CONFIG_SYSFS
+    - x86/resctrl: Fix an imbalance in domain_remove_cpu()
+    - x86/CPU/AMD: Ensure clearing of SME/SEV features is maintained
+    - locking/rwsem: Fix kernel crash when spinning on RWSEM_OWNER_UNKNOWN
+    - perf/x86/intel/uncore: Fix missing marker for
+      snr_uncore_imc_freerunning_events
+    - x86/efistub: Disable paging at mixed mode entry
+    - s390/zcrypt: Fix CCA cipher key gen with clear key value function
+    - scsi: storvsc: Correctly set number of hardware queues for IDE disk
+    - mtd: spi-nor: Fix selection of 4-byte addressing opcodes on Spansion
+    - drm/i915: Add missing include file <linux/math64.h>
+    - x86/resctrl: Fix potential memory leak
+    - efi/earlycon: Fix write-combine mapping on x86
+    - s390/setup: Fix secure ipl message
+    - clk: samsung: exynos5420: Keep top G3D clocks enabled
+    - perf hists: Fix variable name's inconsistency in hists__for_each() macro
+    - locking/lockdep: Fix buffer overrun problem in stack_trace[]
+    - perf report: Fix incorrectly added dimensions as switch perf data file
+    - mm/shmem.c: thp, shmem: fix conflict of above-47bit hint address and PMD
+      alignment
+    - mm/huge_memory.c: thp: fix conflict of above-47bit hint address and PMD
+      alignment
+    - mm: memcg/slab: fix percpu slab vmstats flushing
+    - mm: memcg/slab: call flush_memcg_workqueue() only if memcg workqueue is
+      valid
+    - mm, debug_pagealloc: don't rely on static keys too early
+    - btrfs: rework arguments of btrfs_unlink_subvol
+    - btrfs: fix invalid removal of root ref
+    - btrfs: do not delete mismatched root refs
+    - btrfs: relocation: fix reloc_root lifespan and access
+    - btrfs: fix memory leak in qgroup accounting
+    - btrfs: check rw_devices, not num_devices for balance
+    - Btrfs: always copy scrub arguments back to user space
+    - mm/memory_hotplug: don't free usage map when removing a re-added early
+      section
+    - mm/page-writeback.c: avoid potential division by zero in wb_min_max_ratio()
+    - mm: khugepaged: add trace status description for SCAN_PAGE_HAS_PRIVATE
+    - ARM: dts: imx6qdl-sabresd: Remove incorrect power supply assignment
+    - ARM: dts: imx6sx-sdb: Remove incorrect power supply assignment
+    - ARM: dts: imx6sl-evk: Remove incorrect power supply assignment
+    - ARM: dts: imx6sll-evk: Remove incorrect power supply assignment
+    - ARM: dts: imx6q-icore-mipi: Use 1.5 version of i.Core MX6DL
+    - ARM: dts: imx7: Fix Toradex Colibri iMX7S 256MB NAND flash support
+    - net: stmmac: 16KB buffer must be 16 byte aligned
+    - net: stmmac: Enable 16KB buffer size
+    - reset: Fix {of,devm}_reset_control_array_get kerneldoc return types
+    - tipc: fix potential hanging after b/rcast changing
+    - tipc: fix retrans failure due to wrong destination
+    - net: fix kernel-doc warning in <linux/netdevice.h>
+    - block: Fix the type of 'sts' in bsg_queue_rq()
+    - drm/amd/display: Reorder detect_edp_sink_caps before link settings read.
+    - bpf: Fix incorrect verifier simulation of ARSH under ALU32
+    - bpf: Sockmap/tls, during free we may call tcp_bpf_unhash() in loop
+    - bpf: Sockmap, ensure sock lock held during tear down
+    - bpf: Sockmap/tls, push write_space updates through ulp updates
+    - bpf: Sockmap, skmsg helper overestimates push, pull, and pop bounds
+    - bpf: Sockmap/tls, msg_push_data may leave end mark in place
+    - bpf: Sockmap/tls, tls_sw can create a plaintext buf > encrypt buf
+    - bpf: Sockmap/tls, skmsg can have wrapped skmsg that needs extra chaining
+    - bpf: Sockmap/tls, fix pop data with SK_DROP return code
+    - i2c: tegra: Fix suspending in active runtime PM state
+    - i2c: tegra: Properly disable runtime PM on driver's probe error
+    - cfg80211: fix deadlocks in autodisconnect work
+    - cfg80211: fix memory leak in nl80211_probe_mesh_link
+    - cfg80211: fix memory leak in cfg80211_cqm_rssi_update
+    - cfg80211: fix page refcount issue in A-MSDU decap
+    - bpf/sockmap: Read psock ingress_msg before sk_receive_queue
+    - i2c: iop3xx: Fix memory leak in probe error path
+    - netfilter: fix a use-after-free in mtype_destroy()
+    - netfilter: arp_tables: init netns pointer in xt_tgdtor_param struct
+    - netfilter: nat: fix ICMP header corruption on ICMP errors
+    - netfilter: nft_tunnel: fix null-attribute check
+    - netfilter: nft_tunnel: ERSPAN_VERSION must not be null
+    - netfilter: nf_tables: remove WARN and add NLA_STRING upper limits
+    - netfilter: nf_tables: store transaction list locally while requesting module
+    - netfilter: nf_tables: fix flowtable list del corruption
+    - NFC: pn533: fix bulk-message timeout
+    - net: bpf: Don't leak time wait and request sockets
+    - bpftool: Fix printing incorrect pointer in btf_dump_ptr
+    - batman-adv: Fix DAT candidate selection on little endian systems
+    - macvlan: use skb_reset_mac_header() in macvlan_queue_xmit()
+    - hv_netvsc: Fix memory leak when removing rndis device
+    - net: avoid updating qdisc_xmit_lock_key in netdev_update_lockdep_key()
+    - net: dsa: tag_qca: fix doubled Tx statistics
+    - net: hns3: pad the short frame before sending to the hardware
+    - net: hns: fix soft lockup when there is not enough memory
+    - net: phy: dp83867: Set FORCE_LINK_GOOD to default after reset
+    - net/sched: act_ife: initalize ife->metalist earlier
+    - net: usb: lan78xx: limit size of local TSO packets
+    - net/wan/fsl_ucc_hdlc: fix out of bounds write on array utdm_info
+    - ptp: free ptp device pin descriptors properly
+    - r8152: add missing endpoint sanity check
+    - tcp: fix marked lost packets not being retransmitted
+    - bnxt_en: Fix NTUPLE firmware command failures.
+    - bnxt_en: Fix ipv6 RFS filter matching logic.
+    - bnxt_en: Do not treat DSN (Digital Serial Number) read failure as fatal.
+    - net: ethernet: ave: Avoid lockdep warning
+    - net: systemport: Fixed queue mapping in internal ring map
+    - net: dsa: sja1105: Don't error out on disabled ports with no phy-mode
+    - net: dsa: tag_gswip: fix typo in tagger name
+    - net: sched: act_ctinfo: fix memory leak
+    - net: dsa: bcm_sf2: Configure IMP port for 2Gb/sec
+    - i40e: prevent memory leak in i40e_setup_macvlans
+    - drm/amdgpu: allow direct upload save restore list for raven2
+    - sh_eth: check sh_eth_cpu_data::dual_port when dumping registers
+    - mlxsw: spectrum: Do not modify cloned SKBs during xmit
+    - mlxsw: spectrum: Wipe xstats.backlog of down ports
+    - mlxsw: spectrum_qdisc: Include MC TCs in Qdisc counters
+    - net: stmmac: selftests: Make it work in Synopsys AXS101 boards
+    - net: stmmac: selftests: Mark as fail when received VLAN ID != expected
+    - selftests: mlxsw: qos_mc_aware: Fix mausezahn invocation
+    - net: stmmac: selftests: Update status when disabling RSS
+    - net: stmmac: tc: Do not setup flower filtering if RSS is enabled
+    - devlink: Wait longer before warning about unset port type
+    - xen/blkfront: Adjust indentation in xlvbd_alloc_gendisk
+    - dt-bindings: Add missing 'properties' keyword enclosing 'snps,tso'
+    - tcp: refine rule to allow EPOLLOUT generation under mem pressure
+    - irqchip: Place CONFIG_SIFIVE_PLIC into the menu
+    - arm64: dts: qcom: msm8998: Disable coresight by default
+    - cw1200: Fix a signedness bug in cw1200_load_firmware()
+    - arm64: dts: meson: axg: fix audio fifo reg size
+    - arm64: dts: meson: g12: fix audio fifo reg size
+    - arm64: dts: meson-gxl-s905x-khadas-vim: fix gpio-keys-polled node
+    - arm64: dts: renesas: r8a77970: Fix PWM3
+    - arm64: dts: marvell: Add AP806-dual missing CPU clocks
+    - cfg80211: check for set_wiphy_params
+    - tick/sched: Annotate lockless access to last_jiffies_update
+    - arm64: dts: marvell: Fix CP110 NAND controller node multi-line comment
+      alignment
+    - arm64: dts: renesas: r8a774a1: Remove audio port node
+    - arm64: dts: imx8mm-evk: Assigned clocks for audio plls
+    - arm64: dts: qcom: sdm845-cheza: delete zap-shader
+    - ARM: dts: imx6ul-kontron-n6310-s: Disable the snvs-poweroff driver
+    - arm64: dts: allwinner: a64: Re-add PMU node
+    - ARM: dts: dra7: fix cpsw mdio fck clock
+    - arm64: dts: juno: Fix UART frequency
+    - ARM: dts: Fix sgx sysconfig register for omap4
+    - Revert "arm64: dts: juno: add dma-ranges property"
+    - mtd: devices: fix mchp23k256 read and write
+    - mtd: cfi_cmdset_0002: only check errors when ready in cfi_check_err_status()
+    - mtd: cfi_cmdset_0002: fix delayed error detection on HyperFlash
+    - um: Don't trace irqflags during shutdown
+    - um: virtio_uml: Disallow modular build
+    - reiserfs: fix handling of -EOPNOTSUPP in reiserfs_for_each_xattr
+    - scsi: esas2r: unlock on error in esas2r_nvram_read_direct()
+    - scsi: qla4xxx: fix double free bug
+    - scsi: bnx2i: fix potential use after free
+    - scsi: target: core: Fix a pr_debug() argument
+    - scsi: lpfc: fix: Coverity: lpfc_get_scsi_buf_s3(): Null pointer dereferences
+    - scsi: qla2xxx: Fix qla2x00_request_irqs() for MSI
+    - scsi: qla2xxx: fix rports not being mark as lost in sync fabric scan
+    - scsi: core: scsi_trace: Use get_unaligned_be*()
+    - scsi: lpfc: Fix list corruption detected in lpfc_put_sgl_per_hdwq
+    - scsi: lpfc: Fix hdwq sgl locks and irq handling
+    - scsi: lpfc: Fix a kernel warning triggered by lpfc_get_sgl_per_hdwq()
+    - rtw88: fix potential read outside array boundary
+    - perf probe: Fix wrong address verification
+    - perf script: Allow --time with --reltime
+    - clk: sprd: Use IS_ERR() to validate the return value of
+      syscon_regmap_lookup_by_phandle()
+    - clk: imx7ulp: Correct system clock source option #7
+    - clk: imx7ulp: Correct DDR clock mux options
+    - regulator: ab8500: Remove SYSCLKREQ from enum ab8505_regulator_id
+    - hwmon: (pmbus/ibm-cffps) Switch LEDs to blocking brightness call
+    - hwmon: (pmbus/ibm-cffps) Fix LED blink behavior
+    - perf script: Fix --reltime with --time
+    - scsi: lpfc: use hdwq assigned cpu for allocation
+    - Linux 5.4.14
+
+  * Focal update: v5.4.13 upstream stable release (LP: #1861085)
+    - HID: hidraw, uhid: Always report EPOLLOUT
+    - rtc: mt6397: fix alarm register overwrite
+    - phy: mapphone-mdm6600: Fix uninitialized status value regression
+    - RDMA/bnxt_re: Avoid freeing MR resources if dereg fails
+    - RDMA/bnxt_re: Fix Send Work Entry state check while polling completions
+    - IB/hfi1: Don't cancel unused work item
+    - mtd: rawnand: stm32_fmc2: avoid to lock the CPU bus
+    - i2c: bcm2835: Store pointer to bus clock
+    - ASoC: SOF: imx8: fix memory allocation failure check on priv->pd_dev
+    - ASoC: soc-core: Set dpcm_playback / dpcm_capture
+    - ASoC: stm32: spdifrx: fix inconsistent lock state
+    - ASoC: stm32: spdifrx: fix race condition in irq handler
+    - ASoC: stm32: spdifrx: fix input pin state management
+    - pinctrl: lochnagar: select GPIOLIB
+    - netfilter: nft_flow_offload: fix underflow in flowtable reference counter
+    - ASoC: SOF: imx8: Fix dsp_box offset
+    - mtd: onenand: omap2: Pass correct flags for prep_dma_memcpy
+    - gpio: zynq: Fix for bug in zynq_gpio_restore_context API
+    - pinctrl: meson: Fix wrong shift value when get drive-strength
+    - selftests: loopback.sh: skip this test if the driver does not support
+    - iommu/vt-d: Unlink device if failed to add to group
+    - iommu: Remove device link to group on failure
+    - bpf: cgroup: prevent out-of-order release of cgroup bpf
+    - fs: move guard_bio_eod() after bio_set_op_attrs
+    - scsi: mpt3sas: Fix double free in attach error handling
+    - gpio: Fix error message on out-of-range GPIO in lookup table
+    - PM / devfreq: tegra: Add COMMON_CLK dependency
+    - PCI: amlogic: Fix probed clock names
+    - drm/tegra: Fix ordering of cleanup code
+    - hsr: add hsr root debugfs directory
+    - hsr: rename debugfs file when interface name is changed
+    - hsr: reset network header when supervision frame is created
+    - s390/qeth: fix qdio teardown after early init error
+    - s390/qeth: fix false reporting of VNIC CHAR config failure
+    - s390/qeth: Fix vnicc_is_in_use if rx_bcast not set
+    - s390/qeth: vnicc Fix init to default
+    - s390/qeth: fix initialization on old HW
+    - cifs: Adjust indentation in smb2_open_file
+    - scsi: smartpqi: Update attribute name to `driver_version`
+    - MAINTAINERS: Append missed file to the database
+    - ath9k: use iowrite32 over __raw_writel
+    - can: j1939: fix address claim code example
+    - dt-bindings: reset: Fix brcmstb-reset example
+    - reset: brcmstb: Remove resource checks
+    - afs: Fix missing cell comparison in afs_test_super()
+    - perf vendor events s390: Remove name from L1D_RO_EXCL_WRITES description
+    - syscalls/x86: Wire up COMPAT_SYSCALL_DEFINE0
+    - syscalls/x86: Use COMPAT_SYSCALL_DEFINE0 for IA32 (rt_)sigreturn
+    - syscalls/x86: Use the correct function type for sys_ni_syscall
+    - syscalls/x86: Fix function types in COND_SYSCALL
+    - hsr: fix slab-out-of-bounds Read in hsr_debugfs_rename()
+    - btrfs: simplify inode locking for RWF_NOWAIT
+    - netfilter: nf_tables_offload: release flow_rule on error from commit path
+    - netfilter: nft_meta: use 64-bit time arithmetic
+    - ASoC: dt-bindings: mt8183: add missing update
+    - ASoC: simple_card_utils.h: Add missing include
+    - ASoC: fsl_esai: Add spin lock to protect reset, stop and start
+    - ASoC: core: Fix compile warning with CONFIG_DEBUG_FS=n
+    - ASoC: rsnd: fix DALIGN register for SSIU
+    - RDMA/hns: Prevent undefined behavior in hns_roce_set_user_sq_size()
+    - RDMA/hns: remove a redundant le16_to_cpu
+    - RDMA/hns: Modify return value of restrack functions
+    - RDMA/counter: Prevent QP counter manual binding in auto mode
+    - RDMA/siw: Fix port number endianness in a debug message
+    - RDMA/hns: Fix build error again
+    - RDMA/hns: Release qp resources when failed to destroy qp
+    - xprtrdma: Add unique trace points for posting Local Invalidate WRs
+    - xprtrdma: Connection becomes unstable after a reconnect
+    - xprtrdma: Fix MR list handling
+    - xprtrdma: Close window between waking RPC senders and posting Receives
+    - RDMA/hns: Fix to support 64K page for srq
+    - RDMA/hns: Bugfix for qpc/cqc timer configuration
+    - rdma: Remove nes ABI header
+    - RDMA/mlx5: Return proper error value
+    - RDMA/srpt: Report the SCSI residual to the initiator
+    - uaccess: Add non-pagefault user-space write function
+    - bpf: Make use of probe_user_write in probe write helper
+    - bpf: skmsg, fix potential psock NULL pointer dereference
+    - bpf: Support pre-2.25-binutils objcopy for vmlinux BTF
+    - libbpf: Fix Makefile' libbpf symbol mismatch diagnostic
+    - afs: Fix use-after-loss-of-ref
+    - afs: Fix afs_lookup() to not clobber the version on a new dentry
+    - keys: Fix request_key() cache
+    - scsi: enclosure: Fix stale device oops with hot replug
+    - scsi: sd: Clear sdkp->protection_type if disk is reformatted without PI
+    - platform/mellanox: fix potential deadlock in the tmfifo driver
+    - platform/x86: asus-wmi: Fix keyboard brightness cannot be set to 0
+    - platform/x86: GPD pocket fan: Use default values when wrong modparams are
+      given
+    - asm-generic/nds32: don't redefine cacheflush primitives
+    - Documentation/ABI: Fix documentation inconsistency for mlxreg-io sysfs
+      interfaces
+    - Documentation/ABI: Add missed attribute for mlxreg-io sysfs interfaces
+    - xprtrdma: Fix create_qp crash on device unload
+    - xprtrdma: Fix completion wait during device removal
+    - xprtrdma: Fix oops in Receive handler after device removal
+    - dm: add dm-clone to the documentation index
+    - scsi: ufs: Give an unique ID to each ufs-bsg
+    - crypto: cavium/nitrox - fix firmware assignment to AE cores
+    - crypto: hisilicon - select NEED_SG_DMA_LENGTH in qm Kconfig
+    - crypto: arm64/aes-neonbs - add return value of skcipher_walk_done() in
+      __xts_crypt()
+    - crypto: virtio - implement missing support for output IVs
+    - crypto: algif_skcipher - Use chunksize instead of blocksize
+    - crypto: geode-aes - convert to skcipher API and make thread-safe
+    - NFSv2: Fix a typo in encode_sattr()
+    - nfsd: Fix cld_net->cn_tfm initialization
+    - nfsd: v4 support requires CRYPTO_SHA256
+    - NFSv4.x: Handle bad/dead sessions correctly in nfs41_sequence_process()
+    - NFSv4.x: Drop the slot if nfs4_delegreturn_prepare waits for layoutreturn
+    - iio: imu: st_lsm6dsx: fix gyro gain definitions for LSM9DS1
+    - iio: imu: adis16480: assign bias value only if operation succeeded
+    - mei: fix modalias documentation
+    - clk: meson: axg-audio: fix regmap last register
+    - clk: samsung: exynos5420: Preserve CPU clocks configuration during
+      suspend/resume
+    - clk: Fix memory leak in clk_unregister()
+    - dmaengine: dw: platform: Mark 'hclk' clock optional
+    - clk: imx: pll14xx: Fix quick switch of S/K parameter
+    - rsi: fix potential null dereference in rsi_probe()
+    - affs: fix a memory leak in affs_remount
+    - pinctl: ti: iodelay: fix error checking on pinctrl_count_index_with_args
+      call
+    - pinctrl: sh-pfc: Fix PINMUX_IPSR_PHYS() to set GPSR
+    - pinctrl: sh-pfc: Do not use platform_get_irq() to count interrupts
+    - pinctrl: lewisburg: Update pin list according to v1.1v6
+    - Revert "drm/virtio: switch virtio_gpu_wait_ioctl() to gem helper."
+    - drm/amdgpu: cleanup creating BOs at fixed location (v2)
+    - drm/amdgpu/discovery: reserve discovery data at the top of VRAM
+    - scsi: sd: enable compat ioctls for sed-opal
+    - arm64: dts: apq8096-db820c: Increase load on l21 for SDCARD
+    - af_unix: add compat_ioctl support
+    - compat_ioctl: handle SIOCOUTQNSD
+    - PCI: aardvark: Use LTSSM state to build link training flag
+    - PCI: aardvark: Fix PCI_EXP_RTCTL register configuration
+    - PCI: dwc: Fix find_next_bit() usage
+    - PCI: Fix missing bridge dma_ranges resource list cleanup
+    - PCI/PM: Clear PCIe PME Status even for legacy power management
+    - tools: PCI: Fix fd leakage
+    - PCI/PTM: Remove spurious "d" from granularity message
+    - powerpc/powernv: Disable native PCIe port management
+    - MIPS: PCI: remember nasid changed by set interrupt affinity
+    - MIPS: Loongson: Fix return value of loongson_hwmon_init
+    - MIPS: SGI-IP27: Fix crash, when CPUs are disabled via nr_cpus parameter
+    - tty: serial: imx: use the sg count from dma_map_sg
+    - tty: serial: pch_uart: correct usage of dma_unmap_sg
+    - ARM: 8943/1: Fix topology setup in case of CPU hotplug for CONFIG_SCHED_MC
+    - media: ov6650: Fix incorrect use of JPEG colorspace
+    - media: ov6650: Fix some format attributes not under control
+    - media: ov6650: Fix .get_fmt() V4L2_SUBDEV_FORMAT_TRY support
+    - media: ov6650: Fix default format not applied on device probe
+    - media: rcar-vin: Fix incorrect return statement in rvin_try_format()
+    - media: hantro: h264: Fix the frame_num wraparound case
+    - media: v4l: cadence: Fix how unsued lanes are handled in 'csi2rx_start()'
+    - media: exynos4-is: Fix recursive locking in isp_video_release()
+    - media: coda: fix deadlock between decoder picture run and start command
+    - media: cedrus: Use correct H264 8x8 scaling list
+    - media: hantro: Do not reorder H264 scaling list
+    - media: aspeed-video: Fix memory leaks in aspeed_video_probe
+    - media: hantro: Set H264 FIELDPIC_FLAG_E flag correctly
+    - iommu/mediatek: Correct the flush_iotlb_all callback
+    - iommu/mediatek: Add a new tlb_lock for tlb_flush
+    - memory: mtk-smi: Add PM suspend and resume ops
+    - Revert "ubifs: Fix memory leak bug in alloc_ubifs_info() error path"
+    - ubifs: Fixed missed le64_to_cpu() in journal
+    - ubifs: do_kill_orphans: Fix a memory leak bug
+    - spi: sprd: Fix the incorrect SPI register
+    - mtd: spi-nor: fix silent truncation in spi_nor_read()
+    - mtd: spi-nor: fix silent truncation in spi_nor_read_raw()
+    - spi: pxa2xx: Set controller->max_transfer_size in dma mode
+    - spi: atmel: fix handling of cs_change set on non-last xfer
+    - spi: rspi: Use platform_get_irq_byname_optional() for optional irqs
+    - spi: lpspi: fix memory leak in fsl_lpspi_probe
+    - iwlwifi: mvm: consider ieee80211 station max amsdu value
+    - rtlwifi: Remove unnecessary NULL check in rtl_regd_init
+    - iwlwifi: mvm: fix support for single antenna diversity
+    - sch_cake: Add missing NLA policy entry TCA_CAKE_SPLIT_GSO
+    - f2fs: fix potential overflow
+    - NFSD fixing possible null pointer derefering in copy offload
+    - rtc: msm6242: Fix reading of 10-hour digit
+    - rtc: brcmstb-waketimer: add missed clk_disable_unprepare
+    - rtc: bd70528: Add MODULE ALIAS to autoload module
+    - gpio: mpc8xxx: Add platform device to gpiochip->parent
+    - scsi: libcxgbi: fix NULL pointer dereference in cxgbi_device_destroy()
+    - scsi: target/iblock: Fix protection error with blocks greater than 512B
+    - selftests: firmware: Fix it to do root uid check and skip
+    - rseq/selftests: Turn off timeout setting
+    - riscv: export flush_icache_all to modules
+    - mips: cacheinfo: report shared CPU map
+    - mips: Fix gettimeofday() in the vdso library
+    - tomoyo: Suppress RCU warning at list_for_each_entry_rcu().
+    - MIPS: Prevent link failure with kcov instrumentation
+    - drm/arm/mali: make malidp_mw_connector_helper_funcs static
+    - rxrpc: Unlock new call in rxrpc_new_incoming_call() rather than the caller
+    - rxrpc: Don't take call->user_mutex in rxrpc_new_incoming_call()
+    - rxrpc: Fix missing security check on incoming calls
+    - dmaengine: k3dma: Avoid null pointer traversal
+    - s390/qeth: lock the card while changing its hsuid
+    - ioat: ioat_alloc_ring() failure handling.
+    - drm/amdgpu: enable gfxoff for raven1 refresh
+    - media: intel-ipu3: Align struct ipu3_uapi_awb_fr_config_s to 32 bytes
+    - kbuild/deb-pkg: annotate libelf-dev dependency as :native
+    - hexagon: parenthesize registers in asm predicates
+    - hexagon: work around compiler crash
+    - ocfs2: call journal flush to mark journal as empty after journal recovery
+      when mount
+    - Linux 5.4.13
+    - [Config] updateconfigs following v5.4.13 stable update
+
+  * [hns3-0111]sync mainline kernel 5.5rc6 hns3 patchset into ubuntu HWE kernel
+    branch Edit (LP: #1859261)
+    - net: hns3: make array tick_array static, makes object smaller
+    - net: hns3: add support for setting VF link status on the host
+    - net: hns3: add support for spoof check setting
+    - net: hns3: add support for setting VF trust
+    - net: hns3: add support for configuring bandwidth of VF on the host
+    - net: hns3: add support for configuring VF MAC from the host
+    - net: hns3: support tx-scatter-gather-fraglist feature
+    - net: hns3: remove struct hns3_nic_ring_data in hns3_enet module
+    - net: hns3: optimized MAC address in management table.
+    - net: hns3: minor optimization for barrier in IO path
+    - net: hns3: introduce ring_to_netdev() in enet module
+    - net: hns3: make struct hns3_enet_ring cacheline aligned
+    - net: hns3: minor cleanup for hns3_handle_rx_bd()
+    - net: hns3: do not allocate linear data for fraglist skb
+    - net: hns3: dump some debug information when reset fail
+    - net: hns3: cleanup some magic numbers
+    - net: hns3: cleanup some coding style issues
+    - net: hns3: cleanup a format-truncation warning
+    - net: hns3: optimize local variable initialization
+    - net: hns3: add or modify some comments
+    - net: hns3: cleanup some print format warning
+    - net: hns3: cleanup byte order issues when printed
+    - net: hns3: remove unused macros
+    - net: hns3: fix for TX queue not restarted problem
+    - net: hns3: fix a use after free problem in hns3_nic_maybe_stop_tx()
+    - net: hns3: fix VF ID issue for setting VF VLAN
+
+  * [Dell Vostro 5490] proposed linux-oem-osp1 suspend resume fails
+    (LP: #1860642)
+    - Revert "ASoC: SOF: Intel: Fix CFL and CML FW nocodec binary names."
+    - Revert "ASoC: Intel: acpi-match: split CNL tables in three"
+    - Revert "ASoC: SOF: Intel: hda: use fallback for firmware name"
+
+  * shiftfs: prevent lower dentries from going negative during unlink
+    (LP: #1860041)
+    - SAUCE: shiftfs: prevent lower dentries from going negative during unlink
+
+  * [SRU][B/OEM-B/OEM-OSP1/D/E/Unstable] UBUNTU: SAUCE: Use native backlight on
+    Lenovo E41-25/45 (LP: #1859561)
+    - SAUCE: ACPI: video: Use native backlight on Lenovo E41-25/45
+
+  * Dell AIO can't adjust brightness (LP: #1858761)
+    - SAUCE: platform/x86: dell-uart-backlight: add retry for get scalar status
+
+  * [20.04 FEAT] qeth: Support for HiperSockets Multi-Write (LP: #1853292)
+    - s390/qdio: implement IQD Multi-Write
+    - s390/qeth: use IQD Multi-Write
+
+  * debian/tests/corosync: gfs2_jadd fails with ENOTTY for i386 package on amd64
+    kernel (LP: #1859827)
+    - gfs2: add compat_ioctl support
+
+  * Reduce s2idle power consumption when ethernet cable is connected on e1000e
+    (LP: #1859126)
+    - e1000e: Add support for S0ix
+
+  * USB key cannot be detected by hotplug on Sunix USB Type-A 3.1 Gen 2 card
+    [1b21:2142]  (LP: #1858988)
+    - SAUCE: PCI: Avoid ASMedia XHCI USB PME# from D0 defect
+
+  * [scsi-1130]scsi: scsi_transport_sas: Fix memory leak when removing devices
+    (LP: #1854550)
+    - scsi: scsi_transport_sas: Fix memory leak when removing devices
+
+  * Focal update: v5.4.12 upstream stable release (LP: #1860131)
+    - chardev: Avoid potential use-after-free in 'chrdev_open()'
+    - i2c: fix bus recovery stop mode timing
+    - powercap: intel_rapl: add NULL pointer check to rapl_mmio_cpu_online()
+    - usb: chipidea: host: Disable port power only if previously enabled
+    - ALSA: usb-audio: Apply the sample rate quirk for Bose Companion 5
+    - ALSA: hda/realtek - Add new codec supported for ALCS1200A
+    - ALSA: hda/realtek - Set EAPD control to default for ALC222
+    - ALSA: hda/realtek - Add quirk for the bass speaker on Lenovo Yoga X1 7th gen
+    - tpm: Revert "tpm_tis: reserve chip for duration of tpm_tis_core_init"
+    - tpm: Revert "tpm_tis_core: Set TPM_CHIP_FLAG_IRQ before probing for
+      interrupts"
+    - tpm: Revert "tpm_tis_core: Turn on the TPM before probing IRQ's"
+    - tpm: Handle negative priv->response_len in tpm_common_read()
+    - rtc: sun6i: Add support for RTC clocks on R40
+    - kernel/trace: Fix do not unregister tracepoints when register
+      sched_migrate_task fail
+    - tracing: Have stack tracer compile when MCOUNT_INSN_SIZE is not defined
+    - tracing: Change offset type to s32 in preempt/irq tracepoints
+    - HID: Fix slab-out-of-bounds read in hid_field_extract
+    - HID: uhid: Fix returning EPOLLOUT from uhid_char_poll
+    - HID: hidraw: Fix returning EPOLLOUT from hidraw_poll
+    - HID: hid-input: clear unmapped usages
+    - Input: add safety guards to input_set_keycode()
+    - Input: input_event - fix struct padding on sparc64
+    - drm/i915: Add Wa_1408615072 and Wa_1407596294 to icl,ehl
+    - Revert "drm/amdgpu: Set no-retry as default."
+    - drm/sun4i: tcon: Set RGB DCLK min. divider based on hardware model
+    - drm/fb-helper: Round up bits_per_pixel if possible
+    - drm/dp_mst: correct the shifting in DP_REMOTE_I2C_READ
+    - drm/i915: Add Wa_1407352427:icl,ehl
+    - drm/i915/gt: Mark up virtual engine uabi_instance
+    - IB/hfi1: Adjust flow PSN with the correct resync_psn
+    - can: kvaser_usb: fix interface sanity check
+    - can: gs_usb: gs_usb_probe(): use descriptors of current altsetting
+    - can: tcan4x5x: tcan4x5x_can_probe(): get the device out of standby before
+      register access
+    - can: mscan: mscan_rx_poll(): fix rx path lockup when returning from polling
+      to irq mode
+    - can: can_dropped_invalid_skb(): ensure an initialized headroom in outgoing
+      CAN sk_buffs
+    - gpiolib: acpi: Turn dmi_system_id table into a generic quirk table
+    - gpiolib: acpi: Add honor_wakeup module-option + quirk mechanism
+    - pstore/ram: Regularize prz label allocation lifetime
+    - staging: vt6656: set usb_set_intfdata on driver fail.
+    - staging: vt6656: Fix non zero logical return of, usb_control_msg
+    - usb: cdns3: should not use the same dev_id for shared interrupt handler
+    - usb: ohci-da8xx: ensure error return on variable error is set
+    - USB-PD tcpm: bad warning+size, PPS adapters
+    - USB: serial: option: add ZLP support for 0x1bc7/0x9010
+    - usb: musb: fix idling for suspend after disconnect interrupt
+    - usb: musb: Disable pullup at init
+    - usb: musb: dma: Correct parameter passed to IRQ handler
+    - staging: comedi: adv_pci1710: fix AI channels 16-31 for PCI-1713
+    - staging: vt6656: correct return of vnt_init_registers.
+    - staging: vt6656: limit reg output to block size
+    - staging: rtl8188eu: Add device code for TP-Link TL-WN727N v5.21
+    - serdev: Don't claim unsupported ACPI serial devices
+    - iommu/vt-d: Fix adding non-PCI devices to Intel IOMMU
+    - tty: link tty and port before configuring it as console
+    - tty: always relink the port
+    - arm64: Move __ARCH_WANT_SYS_CLONE3 definition to uapi headers
+    - arm64: Implement copy_thread_tls
+    - arm: Implement copy_thread_tls
+    - parisc: Implement copy_thread_tls
+    - riscv: Implement copy_thread_tls
+    - xtensa: Implement copy_thread_tls
+    - clone3: ensure copy_thread_tls is implemented
+    - um: Implement copy_thread_tls
+    - staging: vt6656: remove bool from vnt_radio_power_on ret
+    - mwifiex: pcie: Fix memory leak in mwifiex_pcie_alloc_cmdrsp_buf
+    - rpmsg: char: release allocated memory
+    - scsi: bfa: release allocated memory in case of error
+    - rtl8xxxu: prevent leaking urb
+    - HID: hiddev: fix mess in hiddev_open()
+    - USB: Fix: Don't skip endpoint descriptors with maxpacket=0
+    - phy: cpcap-usb: Fix error path when no host driver is loaded
+    - phy: cpcap-usb: Fix flakey host idling and enumerating of devices
+    - netfilter: arp_tables: init netns pointer in xt_tgchk_param struct
+    - netfilter: conntrack: dccp, sctp: handle null timeout argument
+    - netfilter: ipset: avoid null deref when IPSET_ATTR_LINENO is present
+    - drm/i915/gen9: Clear residual context state on context switch
+    - Linux 5.4.12
+
+  * Focal update: v5.4.11 upstream stable release (LP: #1860130)
+    - USB: dummy-hcd: use usb_urb_dir_in instead of usb_pipein
+    - bpf: Fix passing modified ctx to ld/abs/ind instruction
+    - ASoC: rt5682: fix i2c arbitration lost issue
+    - spi: pxa2xx: Add support for Intel Jasper Lake
+    - regulator: fix use after free issue
+    - ASoC: max98090: fix possible race conditions
+    - spi: fsl: Fix GPIO descriptor support
+    - gpio: Handle counting of Freescale chipselects
+    - spi: fsl: Handle the single hardwired chipselect case
+    - locking/spinlock/debug: Fix various data races
+    - netfilter: ctnetlink: netns exit must wait for callbacks
+    - netfilter: nf_tables_offload: Check for the NETDEV_UNREGISTER event
+    - libtraceevent: Fix lib installation with O=
+    - libtraceevent: Copy pkg-config file to output folder when using O=
+    - regulator: core: fix regulator_register() error paths to properly release
+      rdev
+    - x86/efi: Update e820 with reserved EFI boot services data to fix kexec
+      breakage
+    - ASoC: Intel: bytcr_rt5640: Update quirk for Teclast X89
+    - selftests: netfilter: use randomized netns names
+    - efi/gop: Return EFI_NOT_FOUND if there are no usable GOPs
+    - efi/gop: Return EFI_SUCCESS if a usable GOP was found
+    - efi/gop: Fix memory leak in __gop_query32/64()
+    - efi/earlycon: Remap entire framebuffer after page initialization
+    - ARM: dts: imx6ul: imx6ul-14x14-evk.dtsi: Fix SPI NOR probing
+    - ARM: vexpress: Set-up shared OPP table instead of individual for each CPU
+    - netfilter: uapi: Avoid undefined left-shift in xt_sctp.h
+    - netfilter: nft_set_rbtree: bogus lookup/get on consecutive elements in named
+      sets
+    - netfilter: nf_tables: validate NFT_SET_ELEM_INTERVAL_END
+    - netfilter: nf_tables: validate NFT_DATA_VALUE after nft_data_init()
+    - netfilter: nf_tables: skip module reference count bump on object updates
+    - netfilter: nf_tables_offload: return EOPNOTSUPP if rule specifies no actions
+    - ARM: dts: BCM5301X: Fix MDIO node address/size cells
+    - selftests/ftrace: Fix to check the existence of set_ftrace_filter
+    - selftests/ftrace: Fix ftrace test cases to check unsupported
+    - selftests/ftrace: Do not to use absolute debugfs path
+    - selftests/ftrace: Fix multiple kprobe testcase
+    - selftests: safesetid: Move link library to LDLIBS
+    - selftests: safesetid: Check the return value of setuid/setgid
+    - selftests: safesetid: Fix Makefile to set correct test program
+    - ARM: exynos_defconfig: Restore debugfs support
+    - ARM: dts: Cygnus: Fix MDIO node address/size cells
+    - spi: spi-cavium-thunderx: Add missing pci_release_regions()
+    - reset: Do not register resource data for missing resets
+    - ASoC: topology: Check return value for snd_soc_add_dai_link()
+    - ASoC: topology: Check return value for soc_tplg_pcm_create()
+    - ASoC: SOF: loader: snd_sof_fw_parse_ext_data log warning on unknown header
+    - ASoC: SOF: Intel: split cht and byt debug window sizes
+    - ARM: dts: am335x-sancloud-bbe: fix phy mode
+    - ARM: omap2plus_defconfig: Add back DEBUG_FS
+    - ARM: dts: bcm283x: Fix critical trip point
+    - arm64: dts: ls1028a: fix typo in TMU calibration data
+    - bpf, riscv: Limit to 33 tail calls
+    - bpf, mips: Limit to 33 tail calls
+    - bpftool: Don't crash on missing jited insns or ksyms
+    - perf metricgroup: Fix printing event names of metric group with multiple
+      events
+    - perf header: Fix false warning when there are no duplicate cache entries
+    - spi: spi-ti-qspi: Fix a bug when accessing non default CS
+    - ARM: dts: am437x-gp/epos-evm: fix panel compatible
+    - kselftest/runner: Print new line in print of timeout log
+    - kselftest: Support old perl versions
+    - samples: bpf: Replace symbol compare of trace_event
+    - samples: bpf: fix syscall_tp due to unused syscall
+    - arm64: dts: ls1028a: fix reboot node
+    - ARM: imx_v6_v7_defconfig: Explicitly restore CONFIG_DEBUG_FS
+    - pinctrl: aspeed-g6: Fix LPC/eSPI mux configuration
+    - bus: ti-sysc: Fix missing reset delay handling
+    - clk: walk orphan list on clock provider registration
+    - mac80211: fix TID field in monitor mode transmit
+    - cfg80211: fix double-free after changing network namespace
+    - pinctrl: pinmux: fix a possible null pointer in pinmux_can_be_used_for_gpio
+    - powerpc: Ensure that swiotlb buffer is allocated from low memory
+    - btrfs: Fix error messages in qgroup_rescan_init
+    - Btrfs: fix cloning range with a hole when using the NO_HOLES feature
+    - powerpc/vcpu: Assume dedicated processors as non-preempt
+    - powerpc/spinlocks: Include correct header for static key
+    - btrfs: handle error in btrfs_cache_block_group
+    - Btrfs: fix hole extent items with a zero size after range cloning
+    - ocxl: Fix potential memory leak on context creation
+    - bpf: Clear skb->tstamp in bpf_redirect when necessary
+    - habanalabs: rate limit error msg on waiting for CS
+    - habanalabs: remove variable 'val' set but not used
+    - bnx2x: Do not handle requests from VFs after parity
+    - bnx2x: Fix logic to get total no. of PFs per engine
+    - cxgb4: Fix kernel panic while accessing sge_info
+    - net: usb: lan78xx: Fix error message format specifier
+    - parisc: fix compilation when KEXEC=n and KEXEC_FILE=y
+    - parisc: add missing __init annotation
+    - rfkill: Fix incorrect check to avoid NULL pointer dereference
+    - ASoC: wm8962: fix lambda value
+    - regulator: rn5t618: fix module aliases
+    - spi: nxp-fspi: Ensure width is respected in spi-mem operations
+    - clk: at91: fix possible deadlock
+    - staging: axis-fifo: add unspecified HAS_IOMEM dependency
+    - iommu/iova: Init the struct iova to fix the possible memleak
+    - kconfig: don't crash on NULL expressions in expr_eq()
+    - scripts: package: mkdebian: add missing rsync dependency
+    - perf/x86: Fix potential out-of-bounds access
+    - perf/x86/intel: Fix PT PMI handling
+    - sched/psi: Fix sampling error and rare div0 crashes with cgroups and high
+      uptime
+    - psi: Fix a division error in psi poll()
+    - usb: typec: fusb302: Fix an undefined reference to 'extcon_get_state'
+    - block: end bio with BLK_STS_AGAIN in case of non-mq devs and REQ_NOWAIT
+    - fs: avoid softlockups in s_inodes iterators
+    - fs: call fsnotify_sb_delete after evict_inodes
+    - perf/smmuv3: Remove the leftover put_cpu() in error path
+    - iommu/dma: Relax locking in iommu_dma_prepare_msi()
+    - io_uring: don't wait when under-submitting
+    - clk: Move clk_core_reparent_orphans() under CONFIG_OF
+    - net: stmmac: selftests: Needs to check the number of Multicast regs
+    - net: stmmac: Determine earlier the size of RX buffer
+    - net: stmmac: Do not accept invalid MTU values
+    - net: stmmac: xgmac: Clear previous RX buffer size
+    - net: stmmac: RX buffer size must be 16 byte aligned
+    - net: stmmac: Always arm TX Timer at end of transmission start
+    - s390/purgatory: do not build purgatory with kcov, kasan and friends
+    - drm/exynos: gsc: add missed component_del
+    - tpm/tpm_ftpm_tee: add shutdown call back
+    - xsk: Add rcu_read_lock around the XSK wakeup
+    - net/mlx5e: Fix concurrency issues between config flow and XSK
+    - net/i40e: Fix concurrency issues between config flow and XSK
+    - net/ixgbe: Fix concurrency issues between config flow and XSK
+    - platform/x86: pcengines-apuv2: fix simswap GPIO assignment
+    - arm64: cpu_errata: Add Hisilicon TSV110 to spectre-v2 safe list
+    - block: Fix a lockdep complaint triggered by request queue flushing
+    - s390/dasd/cio: Interpret ccw_device_get_mdc return value correctly
+    - s390/dasd: fix memleak in path handling error case
+    - block: fix memleak when __blk_rq_map_user_iov() is failed
+    - parisc: Fix compiler warnings in debug_core.c
+    - sbitmap: only queue kyber's wait callback if not already active
+    - s390/qeth: handle error due to unsupported transport mode
+    - s390/qeth: fix promiscuous mode after reset
+    - s390/qeth: don't return -ENOTSUPP to userspace
+    - llc2: Fix return statement of llc_stat_ev_rx_null_dsap_xid_c (and _test_c)
+    - hv_netvsc: Fix unwanted rx_table reset
+    - selftests: pmtu: fix init mtu value in description
+    - tracing: Do not create directories if lockdown is in affect
+    - gtp: fix bad unlock balance in gtp_encap_enable_socket
+    - macvlan: do not assume mac_header is set in macvlan_broadcast()
+    - net: dsa: mv88e6xxx: Preserve priority when setting CPU port.
+    - net: freescale: fec: Fix ethtool -d runtime PM
+    - net: stmmac: dwmac-sun8i: Allow all RGMII modes
+    - net: stmmac: dwmac-sunxi: Allow all RGMII modes
+    - net: stmmac: Fixed link does not need MDIO Bus
+    - net: usb: lan78xx: fix possible skb leak
+    - pkt_sched: fq: do not accept silly TCA_FQ_QUANTUM
+    - sch_cake: avoid possible divide by zero in cake_enqueue()
+    - sctp: free cmd->obj.chunk for the unprocessed SCTP_CMD_REPLY
+    - tcp: fix "old stuff" D-SACK causing SACK to be treated as D-SACK
+    - vxlan: fix tos value before xmit
+    - mlxsw: spectrum_qdisc: Ignore grafting of invisible FIFO
+    - net: sch_prio: When ungrafting, replace with FIFO
+    - vlan: fix memory leak in vlan_dev_set_egress_priority
+    - vlan: vlan_changelink() should propagate errors
+    - macb: Don't unregister clks unconditionally
+    - net/mlx5: Move devlink registration before interfaces load
+    - net: dsa: mv88e6xxx: force cmode write on 6141/6341
+    - net/mlx5e: Always print health reporter message to dmesg
+    - net/mlx5: DR, No need for atomic refcount for internal SW steering resources
+    - net/mlx5e: Fix hairpin RSS table size
+    - net/mlx5: DR, Init lists that are used in rule's member
+    - usb: dwc3: gadget: Fix request complete check
+    - USB: core: fix check for duplicate endpoints
+    - USB: serial: option: add Telit ME910G1 0x110a composition
+    - usb: missing parentheses in USE_NEW_SCHEME
+    - Linux 5.4.11
+
+  * Focal update: v5.4.10 upstream stable release (LP: #1860127)
+    - powerpc/pmem: Fix kernel crash due to wrong range value usage in
+      flush_dcache_range
+    - Linux 5.4.10
+
+  * Focal update: v5.4.9 upstream stable release (LP: #1860125)
+    - drm/mcde: dsi: Fix invalid pointer dereference if panel cannot be found
+    - nvme_fc: add module to ops template to allow module references
+    - nvme-fc: fix double-free scenarios on hw queues
+    - drm/amdgpu: add check before enabling/disabling broadcast mode
+    - drm/amdgpu: add header line for power profile on Arcturus
+    - drm/amdgpu: add cache flush workaround to gfx8 emit_fence
+    - drm/amd/display: Map DSC resources 1-to-1 if numbers of OPPs and DSCs are
+      equal
+    - drm/amd/display: Fixed kernel panic when booting with DP-to-HDMI dongle
+    - drm/amd/display: Change the delay time before enabling FEC
+    - drm/amd/display: Reset steer fifo before unblanking the stream
+    - drm/amd/display: update dispclk and dppclk vco frequency
+    - nvme/pci: Fix write and poll queue types
+    - nvme/pci: Fix read queue count
+    - iio: st_accel: Fix unused variable warning
+    - iio: adc: max9611: Fix too short conversion time delay
+    - PM / devfreq: Fix devfreq_notifier_call returning errno
+    - PM / devfreq: Set scaling_max_freq to max on OPP notifier error
+    - PM / devfreq: Don't fail devfreq_dev_release if not in list
+    - afs: Fix afs_find_server lookups for ipv4 peers
+    - afs: Fix SELinux setting security label on /afs
+    - RDMA/cma: add missed unregister_pernet_subsys in init failure
+    - rxe: correctly calculate iCRC for unaligned payloads
+    - scsi: lpfc: Fix memory leak on lpfc_bsg_write_ebuf_set func
+    - scsi: qla2xxx: Use explicit LOGO in target mode
+    - scsi: qla2xxx: Drop superfluous INIT_WORK of del_work
+    - scsi: qla2xxx: Don't call qlt_async_event twice
+    - scsi: qla2xxx: Fix PLOGI payload and ELS IOCB dump length
+    - scsi: qla2xxx: Configure local loop for N2N target
+    - scsi: qla2xxx: Send Notify ACK after N2N PLOGI
+    - scsi: qla2xxx: Don't defer relogin unconditonally
+    - scsi: qla2xxx: Ignore PORT UPDATE after N2N PLOGI
+    - scsi: iscsi: qla4xxx: fix double free in probe
+    - scsi: libsas: stop discovering if oob mode is disconnected
+    - scsi: iscsi: Avoid potential deadlock in iscsi_if_rx func
+    - staging/wlan-ng: add CRC32 dependency in Kconfig
+    - drm/nouveau: Move the declaration of struct nouveau_conn_atom up a bit
+    - drm/nouveau: Fix drm-core using atomic code-paths on pre-nv50 hardware
+    - drm/nouveau/kms/nv50-: fix panel scaling
+    - usb: gadget: fix wrong endpoint desc
+    - net: make socket read/write_iter() honor IOCB_NOWAIT
+    - afs: Fix mountpoint parsing
+    - afs: Fix creation calls in the dynamic root to fail with EOPNOTSUPP
+    - raid5: need to set STRIPE_HANDLE for batch head
+    - md: raid1: check rdev before reference in raid1_sync_request func
+    - s390/cpum_sf: Adjust sampling interval to avoid hitting sample limits
+    - s390/cpum_sf: Avoid SBD overflow condition in irq handler
+    - RDMA/counter: Prevent auto-binding a QP which are not tracked with res
+    - IB/mlx4: Follow mirror sequence of device add during device removal
+    - IB/mlx5: Fix steering rule of drop and count
+    - xen-blkback: prevent premature module unload
+    - xen/balloon: fix ballooned page accounting without hotplug enabled
+    - ALSA: hda/realtek - Add Bass Speaker and fixed dac for bass speaker
+    - ALSA: hda/realtek - Enable the bass speaker of ASUS UX431FLC
+    - ALSA: hda - fixup for the bass speaker on Lenovo Carbon X1 7th gen
+    - tcp: fix data-race in tcp_recvmsg()
+    - shmem: pin the file in shmem_fault() if mmap_sem is dropped
+    - taskstats: fix data-race
+    - ALSA: hda - Downgrade error message for single-cmd fallback
+    - netfilter: nft_tproxy: Fix port selector on Big Endian
+    - block: add bio_truncate to fix guard_bio_eod
+    - mm: drop mmap_sem before calling balance_dirty_pages() in write fault
+    - ALSA: ice1724: Fix sleep-in-atomic in Infrasonic Quartet support code
+    - ALSA: usb-audio: fix set_format altsetting sanity check
+    - ALSA: hda - Apply sync-write workaround to old Intel platforms, too
+    - ALSA: hda/realtek - Add headset Mic no shutup for ALC283
+    - drm/sun4i: hdmi: Remove duplicate cleanup calls
+    - drm/amdgpu/smu: add metrics table lock
+    - drm/amdgpu/smu: add metrics table lock for arcturus (v2)
+    - drm/amdgpu/smu: add metrics table lock for navi (v2)
+    - drm/amdgpu/smu: add metrics table lock for vega20 (v2)
+    - MIPS: BPF: Disable MIPS32 eBPF JIT
+    - MIPS: BPF: eBPF JIT: check for MIPS ISA compliance in Kconfig
+    - MIPS: Avoid VDSO ABI breakage due to global register variable
+    - media: pulse8-cec: fix lost cec_transmit_attempt_done() call
+    - media: cec: CEC 2.0-only bcast messages were ignored
+    - media: cec: avoid decrementing transmit_queue_sz if it is 0
+    - media: cec: check 'transmit_in_progress', not 'transmitting'
+    - mm/memory_hotplug: shrink zones when offlining memory
+    - mm/zsmalloc.c: fix the migrated zspage statistics.
+    - memcg: account security cred as well to kmemcg
+    - mm: move_pages: return valid node id in status if the page is already on the
+      target node
+    - mm/oom: fix pgtables units mismatch in Killed process message
+    - ocfs2: fix the crash due to call ocfs2_get_dlm_debug once less
+    - pstore/ram: Write new dumps to start of recycled zones
+    - pstore/ram: Fix error-path memory leak in persistent_ram_new() callers
+    - gcc-plugins: make it possible to disable CONFIG_GCC_PLUGINS again
+    - locks: print unsigned ino in /proc/locks
+    - selftests/seccomp: Zero out seccomp_notif
+    - seccomp: Check that seccomp_notif is zeroed out by the user
+    - samples/seccomp: Zero out members based on seccomp_notif_sizes
+    - selftests/seccomp: Catch garbage on SECCOMP_IOCTL_NOTIF_RECV
+    - dmaengine: Fix access to uninitialized dma_slave_caps
+    - dmaengine: dma-jz4780: Also break descriptor chains on JZ4725B
+    - Btrfs: fix infinite loop during nocow writeback due to race
+    - compat_ioctl: block: handle Persistent Reservations
+    - compat_ioctl: block: handle BLKREPORTZONE/BLKRESETZONE
+    - compat_ioctl: block: handle BLKGETZONESZ/BLKGETNRZONES
+    - bpf: Fix precision tracking for unbounded scalars
+    - ata: libahci_platform: Export again ahci_platform_<en/dis>able_phys()
+    - ata: ahci_brcm: Fix AHCI resources management
+    - ata: ahci_brcm: Add missing clock management during recovery
+    - ata: ahci_brcm: BCM7425 AHCI requires AHCI_HFLAG_DELAY_ENGINE
+    - libata: Fix retrieving of active qcs
+    - gpio: xtensa: fix driver build
+    - gpiolib: fix up emulated open drain outputs
+    - clocksource: riscv: add notrace to riscv_sched_clock
+    - riscv: ftrace: correct the condition logic in function graph tracer
+    - rseq/selftests: Fix: Namespace gettid() for compatibility with glibc 2.30
+    - tracing: Fix lock inversion in trace_event_enable_tgid_record()
+    - tracing: Avoid memory leak in process_system_preds()
+    - tracing: Have the histogram compare functions convert to u64 first
+    - tracing: Fix endianness bug in histogram trigger
+    - samples/trace_printk: Wait for IRQ work to finish
+    - io_uring: use current task creds instead of allocating a new one
+    - mm/gup: fix memory leak in __gup_benchmark_ioctl
+    - apparmor: fix aa_xattrs_match() may sleep while holding a RCU lock
+    - dmaengine: virt-dma: Fix access after free in vchan_complete()
+    - gen_initramfs_list.sh: fix 'bad variable name' error
+    - ALSA: cs4236: fix error return comparison of an unsigned integer
+    - ALSA: pcm: Yet another missing check of non-cached buffer type
+    - ALSA: firewire-motu: Correct a typo in the clock proc string
+    - scsi: lpfc: Fix rpi release when deleting vport
+    - exit: panic before exit_mm() on global init exit
+    - ftrace: Avoid potential division by zero in function profiler
+    - spi: spi-fsl-dspi: Fix 16-bit word order in 32-bit XSPI mode
+    - drm/msm: include linux/sched/task.h
+    - PM / devfreq: Check NULL governor in available_governors_show
+    - sunrpc: fix crash when cache_head become valid before update
+    - arm64: dts: qcom: msm8998-clamshell: Remove retention idle state
+    - nfsd4: fix up replay_matches_cache()
+    - powerpc: Chunk calls to flush_dcache_range in arch_*_memory
+    - HID: i2c-hid: Reset ALPS touchpads on resume
+    - net/sched: annotate lockless accesses to qdisc->empty
+    - kernel/module.c: wakeup processes in module_wq on module unload
+    - ACPI: sysfs: Change ACPI_MASKABLE_GPE_MAX to 0x100
+    - perf callchain: Fix segfault in thread__resolve_callchain_sample()
+    - iommu/vt-d: Remove incorrect PSI capability check
+    - of: overlay: add_changeset_property() memory leak
+    - cifs: Fix potential softlockups while refreshing DFS cache
+    - firmware: arm_scmi: Avoid double free in error flow
+    - xfs: don't check for AG deadlock for realtime files in bunmapi
+    - platform/x86: pmc_atom: Add Siemens CONNECT X300 to critclk_systems DMI
+      table
+    - netfilter: nf_queue: enqueue skbs with NULL dst
+    - net, sysctl: Fix compiler warning when only cBPF is present
+    - watchdog: tqmx86_wdt: Fix build error
+    - regulator: axp20x: Fix axp20x_set_ramp_delay
+    - regulator: bd70528: Remove .set_ramp_delay for bd70528_ldo_ops
+    - spi: uniphier: Fix FIFO threshold
+    - regulator: axp20x: Fix AXP22x ELDO2 regulator enable bitmask
+    - powerpc/mm: Mark get_slice_psize() & slice_addr_is_low() as notrace
+    - Bluetooth: btusb: fix PM leak in error case of setup
+    - Bluetooth: delete a stray unlock
+    - Bluetooth: Fix memory leak in hci_connect_le_scan
+    - arm64: dts: meson-gxl-s905x-khadas-vim: fix uart_A bluetooth node
+    - arm64: dts: meson-gxm-khadas-vim2: fix uart_A bluetooth node
+    - media: flexcop-usb: ensure -EIO is returned on error condition
+    - regulator: ab8500: Remove AB8505 USB regulator
+    - media: usb: fix memory leak in af9005_identify_state
+    - dt-bindings: clock: renesas: rcar-usb2-clock-sel: Fix typo in example
+    - arm64: dts: meson: odroid-c2: Disable usb_otg bus to avoid power failed
+      warning
+    - phy: renesas: rcar-gen3-usb2: Use platform_get_irq_optional() for optional
+      irq
+    - tty: serial: msm_serial: Fix lockup for sysrq and oops
+    - cifs: Fix lookup of root ses in DFS referral cache
+    - fs: cifs: Fix atime update check vs mtime
+    - fix compat handling of FICLONERANGE, FIDEDUPERANGE and FS_IOC_FIEMAP
+    - ath9k_htc: Modify byte order for an error message
+    - ath9k_htc: Discard undersized packets
+    - drm/i915/execlists: Fix annotation for decoupling virtual request
+    - xfs: periodically yield scrub threads to the scheduler
+    - net: add annotations on hh->hh_len lockless accesses
+    - ubifs: ubifs_tnc_start_commit: Fix OOB in layout_in_gaps
+    - btrfs: get rid of unique workqueue helper functions
+    - Btrfs: only associate the locked page with one async_chunk struct
+    - s390/smp: fix physical to logical CPU map for SMT
+    - mm/sparse.c: mark populate_section_memmap as __meminit
+    - xen/blkback: Avoid unmapping unmapped grant pages
+    - lib/ubsan: don't serialize UBSAN report
+    - efi: Don't attempt to map RCI2 config table if it doesn't exist
+    - perf/x86/intel/bts: Fix the use of page_private()
+    - net: annotate lockless accesses to sk->sk_pacing_shift
+    - hsr: avoid debugfs warning message when module is remove
+    - hsr: fix error handling routine in hsr_dev_finalize()
+    - hsr: fix a race condition in node list insertion and deletion
+    - mm/hugetlb: defer freeing of huge pages if in non-task context
+    - Linux 5.4.9
+
+  * Miscellaneous Ubuntu changes
+    - [Debian] Update package name in getabis repo list
+    - [Packaging] Fix ubuntu-regression-suite python dependency for hwe kernel
+    - [Config] Fix typo in annotations file
+    - [Packaging] move linux-doc and linux-libc-dev stubs to debian.master
+    - update dkms package versions
+
+  * Miscellaneous upstream changes
+    - ASoC: SOF: Intel: fix HDA codec driver probe with multiple controllers
+
+ -- Paolo Pisati <paolo.pisati@canonical.com>  Thu, 30 Jan 2020 16:34:17 +0100
+
+linux-5.4 (5.4.0-12.15) focal; urgency=medium
+
+  * No change, rebuild to use new binutils
+
+ -- Andrea Righi <andrea.righi@canonical.com>  Tue, 21 Jan 2020 14:43:14 +0100
+
+linux-5.4 (5.4.0-11.14) focal; urgency=medium
+
+  * Miscellaneous Ubuntu changes
+    - [Packaging] Update ubuntu-regression-suite dependency to python2
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Thu, 09 Jan 2020 09:35:50 -0600
+
+linux-5.4 (5.4.0-10.13) focal; urgency=medium
+
+  * focal/linux-5.4: 5.4.0-10.13 -proposed tracker (LP: #1858880)
+
+  * PAN is broken for execute-only user mappings on ARMv8 (LP: #1858815)
+    - arm64: Revert support for execute-only user mappings
+
+  * linux build and autopkg tests need to use python2 instead of python
+    (LP: #1858487)
+    - [Packaging] Remove python-dev build dependency
+
+  * Support ath10k hardware rfkill (LP: #1858166)
+    - ath10k: add support for hardware rfkill
+
+  * [SRU][B/OEM-B/OEM-OSP1/D/E/F] Add LG I2C touchscreen multitouch support
+    (LP: #1857541)
+    - SAUCE: HID: multitouch: Add LG MELF0410 I2C touchscreen support
+
+  * usb-audio: the mic can't record any sound after resume on Dell Dock WD19
+    (LP: #1857496)
+    - ALSA: usb-audio: set the interface format after resume on Dell WD19
+
+  * alsa/sof: load different firmware on different platforms (LP: #1857409)
+    - ASoC: SOF: Intel: hda: use fallback for firmware name
+    - ASoC: Intel: acpi-match: split CNL tables in three
+    - ASoC: SOF: Intel: Fix CFL and CML FW nocodec binary names.
+
+  * Make vfio-pci built-in or xhci_hcd optional (LP: #1770845)
+    - [Config]: built-in VFIO_PCI for amd64
+
+  * multi-zone raid0 corruption (LP: #1850540)
+    - SAUCE: md/raid0: Link to wiki with guidance on multi-zone RAID0 layout
+      migration
+
+  * [hpre-1017]sync mainline kernel 5.4rc3 hpre patchset into ubuntu HWE kernel
+    branch (LP: #1850117) // [acc-1130]sync mainline kernel 5.5rc1 acc  patchset
+    into ubuntu HWE kernel branch (LP: #1854549)
+    - [Config] Enable HISI crypto drivers and update previous module
+
+  * [hpre-1017]sync mainline kernel 5.4rc3 hpre patchset into ubuntu HWE kernel
+    branch (LP: #1850117)
+    - crypto: hisilicon - add HiSilicon HPRE accelerator
+    - crypto: hisilicon - add SRIOV support for HPRE
+    - crypto: hisilicon - Add debugfs for HPRE
+    - MAINTAINERS: Add maintainer for HiSilicon HPRE driver
+    - Documentation: Add debugfs doc for hisi_hpre
+
+  * [acc-1130]sync mainline kernel 5.5rc1 acc  patchset into ubuntu HWE kernel
+    branch (LP: #1854549)
+    - crypto: hisilicon - allow compile-testing on x86
+    - crypto: hisilicon - merge sgl support to hisi_qm module
+    - crypto: hisilicon - add sgl_sge_nr module param for zip
+    - crypto: hisilicon - fix large sgl memory allocation problem when disable
+      smmu
+    - crypto: hisilicon - misc fix about sgl
+    - crypto: hisilicon - select NEED_SG_DMA_LENGTH in qm Kconfig
+    - crypto: hisilicon: Fix misuse of GENMASK macro
+    - crypto: hisilicon - tiny fix about QM/ZIP error callback print
+    - crypto: hisilicon - Fix using plain integer as NULL pointer
+    - crypto: hisilicon - fix param should be static when not external.
+    - crypto: hisilicon - fix endianness verification problem of QM
+    - crypto: hisilicon - use sgl API to get sgl dma addr and len
+    - crypto: hisilicon - fix to return sub-optimal device when best device has no
+      qps
+    - crypto: hisilicon - replace #ifdef with IS_ENABLED for CONFIG_NUMA
+    - crypto: hisilicon - add vfs_num module param for zip
+    - crypto: hisilicon - no need to check return value of debugfs_create
+      functions
+    - crypto: hisilicon - add HiSilicon SEC V2 driver
+    - crypto: hisilicon - add SRIOV for HiSilicon SEC
+    - crypto: hisilicon - add DebugFS for HiSilicon SEC
+    - crypto: hisilicon - fix a NULL vs IS_ERR() bug in sec_create_qp_ctx()
+    - hwrng: hisi - add HiSilicon TRNG driver support
+    - MAINTAINERS: Add maintainer for HiSilicon TRNG V2 driver
+    - MAINTAINERS: Add maintainer for HiSilicon SEC V2 driver
+    - Documentation: add DebugFS doc for HiSilicon SEC
+
+  * [sas-1130]enable sas DFX Function for 1620 soc (LP: #1854548)
+    - scsi: hisi_sas: Don't create debugfs dump folder twice
+    - scsi: hisi_sas: Set the BIST init value before enabling BIST
+    - scsi: hisi_sas: Add timestamp for a debugfs dump
+    - scsi: hisi_sas: Add debugfs file structure for CQ
+    - scsi: hisi_sas: Add debugfs file structure for DQ
+    - scsi: hisi_sas: Add debugfs file structure for registers
+    - scsi: hisi_sas: Add debugfs file structure for port
+    - scsi: hisi_sas: Add debugfs file structure for IOST
+    - scsi: hisi_sas: Add debugfs file structure for ITCT
+    - scsi: hisi_sas: Add debugfs file structure for IOST cache
+    - scsi: hisi_sas: Add debugfs file structure for ITCT cache
+    - scsi: hisi_sas: Allocate memory for multiple dumps of debugfs
+    - scsi: hisi_sas: Add module parameter for debugfs dump count
+    - scsi: hisi_sas: Add ability to have multiple debugfs dumps
+    - scsi: hisi_sas: Record the phy down event in debugfs
+    - scsi: hisi_sas: Relocate call to hisi_sas_debugfs_exit()
+
+  * scsi: hisi_sas: Return directly if init hardware failed (LP: #1855958)
+    - scsi: hisi_sas: Return directly if init hardware failed
+
+  * [sas-1126]scsi: hisi_sas: use wait_for_completion_timeout() when clearing
+    ITCT (LP: #1853999)
+    - scsi: hisi_sas: use wait_for_completion_timeout() when clearing ITCT
+
+  * Focal update: v5.4.8 upstream stable release (LP: #1858429)
+    - Revert "MIPS: futex: Restore \n after sync instructions"
+    - Revert "MIPS: futex: Emit Loongson3 sync workarounds within asm"
+    - scsi: lpfc: Fix spinlock_irq issues in lpfc_els_flush_cmd()
+    - scsi: lpfc: Fix discovery failures when target device connectivity bounces
+    - scsi: mpt3sas: Fix clear pending bit in ioctl status
+    - scsi: lpfc: Fix locking on mailbox command completion
+    - scsi: mpt3sas: Reject NVMe Encap cmnds to unsupported HBA
+    - gpio: mxc: Only get the second IRQ when there is more than one IRQ
+    - scsi: lpfc: Fix list corruption in lpfc_sli_get_iocbq
+    - Input: atmel_mxt_ts - disable IRQ across suspend
+    - f2fs: fix to update time in lazytime mode
+    - powerpc/papr_scm: Fix an off-by-one check in papr_scm_meta_{get, set}
+    - tools/power/x86/intel-speed-select: Remove warning for unused result
+    - platform/x86: peaq-wmi: switch to using polled mode of input devices
+    - iommu: rockchip: Free domain on .domain_free
+    - iommu/tegra-smmu: Fix page tables in > 4 GiB memory
+    - dmaengine: xilinx_dma: Clear desc_pendingcount in xilinx_dma_reset
+    - scsi: target: compare full CHAP_A Algorithm strings
+    - scsi: lpfc: Fix hardlockup in lpfc_abort_handler
+    - scsi: lpfc: Fix SLI3 hba in loop mode not discovering devices
+    - scsi: csiostor: Don't enable IRQs too early
+    - scsi: hisi_sas: Replace in_softirq() check in hisi_sas_task_exec()
+    - scsi: hisi_sas: Delete the debugfs folder of hisi_sas when the probe fails
+    - powerpc/pseries: Mark accumulate_stolen_time() as notrace
+    - powerpc/pseries: Don't fail hash page table insert for bolted mapping
+    - Input: st1232 - do not reset the chip too early
+    - selftests/powerpc: Fixup clobbers for TM tests
+    - powerpc/tools: Don't quote $objdump in scripts
+    - dma-debug: add a schedule point in debug_dma_dump_mappings()
+    - dma-mapping: Add vmap checks to dma_map_single()
+    - dma-mapping: fix handling of dma-ranges for reserved memory (again)
+    - dmaengine: fsl-qdma: Handle invalid qdma-queue0 IRQ
+    - leds: lm3692x: Handle failure to probe the regulator
+    - leds: an30259a: add a check for devm_regmap_init_i2c
+    - leds: trigger: netdev: fix handling on interface rename
+    - clocksource/drivers/asm9260: Add a check for of_clk_get
+    - clocksource/drivers/timer-of: Use unique device name instead of timer
+    - dtc: Use pkg-config to locate libyaml
+    - selftests/powerpc: Skip tm-signal-sigreturn-nt if TM not available
+    - powerpc/security/book3s64: Report L1TF status in sysfs
+    - powerpc/book3s64/hash: Add cond_resched to avoid soft lockup warning
+    - ext4: update direct I/O read lock pattern for IOCB_NOWAIT
+    - ext4: iomap that extends beyond EOF should be marked dirty
+    - jbd2: Fix statistics for the number of logged blocks
+    - scsi: tracing: Fix handling of TRANSFER LENGTH == 0 for READ(6) and WRITE(6)
+    - scsi: lpfc: Fix unexpected error messages during RSCN handling
+    - scsi: lpfc: Fix duplicate unreg_rpi error in port offline flow
+    - f2fs: fix to update dir's i_pino during cross_rename
+    - clk: qcom: smd: Add missing pnoc clock
+    - clk: qcom: Allow constant ratio freq tables for rcg
+    - clk: clk-gpio: propagate rate change to parent
+    - irqchip/irq-bcm7038-l1: Enable parent IRQ if necessary
+    - irqchip: ingenic: Error out if IRQ domain creation failed
+    - dma-direct: check for overflows on 32 bit DMA addresses
+    - fs/quota: handle overflows of sysctl fs.quota.* and report as unsigned long
+    - iommu/arm-smmu-v3: Don't display an error when IRQ lines are missing
+    - i2c: stm32f7: fix & reorder remove & probe error handling
+    - iomap: fix return value of iomap_dio_bio_actor on 32bit systems
+    - Input: ili210x - handle errors from input_mt_init_slots()
+    - scsi: lpfc: fix: Coverity: lpfc_cmpl_els_rsp(): Null pointer dereferences
+    - scsi: zorro_esp: Limit DMA transfers to 65536 bytes (except on Fastlane)
+    - PCI: rpaphp: Fix up pointer to first drc-info entry
+    - scsi: ufs: fix potential bug which ends in system hang
+    - powerpc/pseries/cmm: Implement release() function for sysfs device
+    - PCI: rpaphp: Don't rely on firmware feature to imply drc-info support
+    - PCI: rpaphp: Annotate and correctly byte swap DRC properties
+    - PCI: rpaphp: Correctly match ibm, my-drc-index to drc-name when using drc-
+      info
+    - powerpc/security: Fix wrong message when RFI Flush is disable
+    - powerpc/eeh: differentiate duplicate detection message
+    - powerpc/book3s/mm: Update Oops message to print the correct translation in
+      use
+    - scsi: atari_scsi: sun3_scsi: Set sg_tablesize to 1 instead of SG_NONE
+    - clk: pxa: fix one of the pxa RTC clocks
+    - bcache: at least try to shrink 1 node in bch_mca_scan()
+    - HID: quirks: Add quirk for HP MSU1465 PIXART OEM mouse
+    - dt-bindings: Improve validation build error handling
+    - HID: logitech-hidpp: Silence intermittent get_battery_capacity errors
+    - ARM: 8937/1: spectre-v2: remove Brahma-B53 from hardening
+    - libnvdimm/btt: fix variable 'rc' set but not used
+    - HID: Improve Windows Precision Touchpad detection.
+    - HID: rmi: Check that the RMI_STARTED bit is set before unregistering the RMI
+      transport device
+    - watchdog: imx7ulp: Fix reboot hang
+    - watchdog: prevent deferral of watchdogd wakeup on RT
+    - watchdog: Fix the race between the release of watchdog_core_data and cdev
+    - powerpc/fixmap: Use __fix_to_virt() instead of fix_to_virt()
+    - scsi: pm80xx: Fix for SATA device discovery
+    - scsi: ufs: Fix error handing during hibern8 enter
+    - scsi: scsi_debug: num_tgts must be >= 0
+    - scsi: NCR5380: Add disconnect_mask module parameter
+    - scsi: target: core: Release SPC-2 reservations when closing a session
+    - scsi: ufs: Fix up auto hibern8 enablement
+    - scsi: iscsi: Don't send data to unbound connection
+    - scsi: target: iscsi: Wait for all commands to finish before freeing a
+      session
+    - f2fs: Fix deadlock in f2fs_gc() context during atomic files handling
+    - habanalabs: skip VA block list update in reset flow
+    - gpio/mpc8xxx: fix qoriq GPIO reading
+    - platform/x86: intel_pmc_core: Fix the SoC naming inconsistency
+    - gpio: mpc8xxx: Don't overwrite default irq_set_type callback
+    - gpio: lynxpoint: Setup correct IRQ handlers
+    - tools/power/x86/intel-speed-select: Ignore missing config level
+    - Drivers: hv: vmbus: Fix crash handler reset of Hyper-V synic
+    - apparmor: fix unsigned len comparison with less than zero
+    - drm/amdgpu: Call find_vma under mmap_sem
+    - scripts/kallsyms: fix definitely-lost memory leak
+    - powerpc: Don't add -mabi= flags when building with Clang
+    - cifs: Fix use-after-free bug in cifs_reconnect()
+    - um: virtio: Keep reading on -EAGAIN
+    - io_uring: io_allocate_scq_urings() should return a sane state
+    - of: unittest: fix memory leak in attach_node_and_children
+    - cdrom: respect device capabilities during opening action
+    - cifs: move cifsFileInfo_put logic into a work-queue
+    - perf script: Fix brstackinsn for AUXTRACE
+    - perf regs: Make perf_reg_name() return "unknown" instead of NULL
+    - s390/zcrypt: handle new reply code FILTERED_BY_HYPERVISOR
+    - mailbox: imx: Clear the right interrupts at shutdown
+    - libfdt: define INT32_MAX and UINT32_MAX in libfdt_env.h
+    - s390/unwind: filter out unreliable bogus %r14
+    - s390/cpum_sf: Check for SDBT and SDB consistency
+    - ocfs2: fix passing zero to 'PTR_ERR' warning
+    - mailbox: imx: Fix Tx doorbell shutdown path
+    - s390: disable preemption when switching to nodat stack with CALL_ON_STACK
+    - selftests: vm: add fragment CONFIG_TEST_VMALLOC
+    - mm/hugetlbfs: fix error handling when setting up mounts
+    - kernel: sysctl: make drop_caches write-only
+    - userfaultfd: require CAP_SYS_PTRACE for UFFD_FEATURE_EVENT_FORK
+    - Revert "powerpc/vcpu: Assume dedicated processors as non-preempt"
+    - sctp: fix err handling of stream initialization
+    - md: make sure desc_nr less than MD_SB_DISKS
+    - Revert "iwlwifi: assign directly to iwl_trans->cfg in QuZ detection"
+    - netfilter: ebtables: compat: reject all padding in matches/watchers
+    - 6pack,mkiss: fix possible deadlock
+    - powerpc: Fix __clear_user() with KUAP enabled
+    - net/smc: add fallback check to connect()
+    - netfilter: bridge: make sure to pull arp header in br_nf_forward_arp()
+    - inetpeer: fix data-race in inet_putpeer / inet_putpeer
+    - net: add a READ_ONCE() in skb_peek_tail()
+    - net: icmp: fix data-race in cmp_global_allow()
+    - hrtimer: Annotate lockless access to timer->state
+    - tomoyo: Don't use nifty names on sockets.
+    - uaccess: disallow > INT_MAX copy sizes
+    - drm: limit to INT_MAX in create_blob ioctl
+    - xfs: fix mount failure crash on invalid iclog memory access
+    - cxgb4/cxgb4vf: fix flow control display for auto negotiation
+    - net: dsa: bcm_sf2: Fix IP fragment location and behavior
+    - net/mlxfw: Fix out-of-memory error in mfa2 flash burning
+    - net: phy: aquantia: add suspend / resume ops for AQR105
+    - net/sched: act_mirred: Pull mac prior redir to non mac_header_xmit device
+    - net/sched: add delete_empty() to filters and use it in cls_flower
+    - net_sched: sch_fq: properly set sk->sk_pacing_status
+    - net: stmmac: dwmac-meson8b: Fix the RGMII TX delay on Meson8b/8m2 SoCs
+    - ptp: fix the race between the release of ptp_clock and cdev
+    - tcp: Fix highest_sack and highest_sack_seq
+    - udp: fix integer overflow while computing available space in sk_rcvbuf
+    - bnxt_en: Fix MSIX request logic for RDMA driver.
+    - bnxt_en: Free context memory in the open path if firmware has been reset.
+    - bnxt_en: Return error if FW returns more data than dump length
+    - bnxt_en: Fix bp->fw_health allocation and free logic.
+    - bnxt_en: Remove unnecessary NULL checks for fw_health
+    - bnxt_en: Fix the logic that creates the health reporters.
+    - bnxt_en: Add missing devlink health reporters for VFs.
+    - mlxsw: spectrum_router: Skip loopback RIFs during MAC validation
+    - mlxsw: spectrum: Use dedicated policer for VRRP packets
+    - net: add bool confirm_neigh parameter for dst_ops.update_pmtu
+    - ip6_gre: do not confirm neighbor when do pmtu update
+    - gtp: do not confirm neighbor when do pmtu update
+    - net/dst: add new function skb_dst_update_pmtu_no_confirm
+    - tunnel: do not confirm neighbor when do pmtu update
+    - vti: do not confirm neighbor when do pmtu update
+    - sit: do not confirm neighbor when do pmtu update
+    - net/dst: do not confirm neighbor for vxlan and geneve pmtu update
+    - net: dsa: sja1105: Reconcile the meaning of TPID and TPID2 for E/T and
+      P/Q/R/S
+    - net: marvell: mvpp2: phylink requires the link interrupt
+    - gtp: fix wrong condition in gtp_genl_dump_pdp()
+    - gtp: avoid zero size hashtable
+    - bonding: fix active-backup transition after link failure
+    - tcp: do not send empty skb from tcp_write_xmit()
+    - tcp/dccp: fix possible race __inet_lookup_established()
+    - hv_netvsc: Fix tx_table init in rndis_set_subchannel()
+    - gtp: fix an use-after-free in ipv4_pdp_find()
+    - gtp: do not allow adding duplicate tid and ms_addr pdp context
+    - bnxt: apply computed clamp value for coalece parameter
+    - ipv6/addrconf: only check invalid header values when NETLINK_F_STRICT_CHK is
+      set
+    - net: phylink: fix interface passed to mac_link_up
+    - net: ena: fix napi handler misbehavior when the napi budget is zero
+    - vhost/vsock: accept only packets with the right dst_cid
+    - mmc: sdhci-of-esdhc: fix up erratum A-008171 workaround
+    - mmc: sdhci-of-esdhc: re-implement erratum A-009204 workaround
+    - mm/hugetlbfs: fix for_each_hstate() loop in init_hugetlbfs_fs()
+    - Linux 5.4.8
+
+  * Focal update: v5.4.7 upstream stable release (LP: #1858428) // Focal update:
+    v5.4.8 upstream stable release (LP: #1858429)
+    - [Config] updateconfigs following v5.4.7 stable update
+
+  * Focal update: v5.4.7 upstream stable release (LP: #1858428)
+    - af_packet: set defaule value for tmo
+    - fjes: fix missed check in fjes_acpi_add
+    - mod_devicetable: fix PHY module format
+    - net: dst: Force 4-byte alignment of dst_metrics
+    - net: gemini: Fix memory leak in gmac_setup_txqs
+    - net: hisilicon: Fix a BUG trigered by wrong bytes_compl
+    - net: nfc: nci: fix a possible sleep-in-atomic-context bug in
+      nci_uart_tty_receive()
+    - net: phy: ensure that phy IDs are correctly typed
+    - net: qlogic: Fix error paths in ql_alloc_large_buffers()
+    - net-sysfs: Call dev_hold always in rx_queue_add_kobject
+    - net: usb: lan78xx: Fix suspend/resume PHY register access error
+    - nfp: flower: fix stats id allocation
+    - qede: Disable hardware gro when xdp prog is installed
+    - qede: Fix multicast mac configuration
+    - sctp: fix memleak on err handling of stream initialization
+    - sctp: fully initialize v4 addr in some functions
+    - selftests: forwarding: Delete IPv6 address at the end
+    - neighbour: remove neigh_cleanup() method
+    - bonding: fix bond_neigh_init()
+    - dpaa2-ptp: fix double free of the ptp_qoriq IRQ
+    - mlxsw: spectrum_router: Remove unlikely user-triggerable warning
+    - net: ethernet: ti: davinci_cpdma: fix warning "device driver frees DMA
+      memory with different size"
+    - net: stmmac: platform: Fix MDIO init for platforms without PHY
+    - net: dsa: b53: Fix egress flooding settings
+    - NFC: nxp-nci: Fix probing without ACPI
+    - btrfs: don't double lock the subvol_sem for rename exchange
+    - btrfs: do not call synchronize_srcu() in inode_tree_del
+    - Btrfs: make tree checker detect checksum items with overlapping ranges
+    - btrfs: return error pointer from alloc_test_extent_buffer
+    - Btrfs: fix missing data checksums after replaying a log tree
+    - btrfs: send: remove WARN_ON for readonly mount
+    - btrfs: abort transaction after failed inode updates in create_subvol
+    - btrfs: skip log replay on orphaned roots
+    - btrfs: do not leak reloc root if we fail to read the fs root
+    - btrfs: handle ENOENT in btrfs_uuid_tree_iterate
+    - Btrfs: fix removal logic of the tree mod log that leads to use-after-free
+      issues
+    - ALSA: pcm: Avoid possible info leaks from PCM stream buffers
+    - ALSA: hda/ca0132 - Keep power on during processing DSP response
+    - ALSA: hda/ca0132 - Avoid endless loop
+    - ALSA: hda/ca0132 - Fix work handling in delayed HP detection
+    - drm/vc4/vc4_hdmi: fill in connector info
+    - drm/virtio: switch virtio_gpu_wait_ioctl() to gem helper.
+    - drm: mst: Fix query_payload ack reply struct
+    - drm/mipi-dbi: fix a loop in debugfs code
+    - drm/panel: Add missing drm_panel_init() in panel drivers
+    - drm: exynos: exynos_hdmi: use cec_notifier_conn_(un)register
+    - drm: Use EOPNOTSUPP, not ENOTSUPP
+    - drm/amd/display: verify stream link before link test
+    - drm/bridge: analogix-anx78xx: silence -EPROBE_DEFER warnings
+    - drm/amd/display: OTC underflow fix
+    - iio: max31856: add missing of_node and parent references to iio_dev
+    - iio: light: bh1750: Resolve compiler warning and make code more readable
+    - drm/amdgpu/sriov: add ring_stop before ring_create in psp v11 code
+    - drm/amdgpu: grab the id mgr lock while accessing passid_mapping
+    - drm/ttm: return -EBUSY on pipelining with no_gpu_wait (v2)
+    - drm/amd/display: Rebuild mapped resources after pipe split
+    - ath10k: add cleanup in ath10k_sta_state()
+    - drm/amd/display: Handle virtual signal type in disable_link()
+    - ath10k: Check if station exists before forwarding tx airtime report
+    - spi: Add call to spi_slave_abort() function when spidev driver is released
+    - drm/meson: vclk: use the correct G12A frac max value
+    - staging: rtl8192u: fix multiple memory leaks on error path
+    - staging: rtl8188eu: fix possible null dereference
+    - rtlwifi: prevent memory leak in rtl_usb_probe
+    - libertas: fix a potential NULL pointer dereference
+    - Revert "pinctrl: sh-pfc: r8a77990: Fix MOD_SEL1 bit30 when using SSI_SCK2
+      and SSI_WS2"
+    - Revert "pinctrl: sh-pfc: r8a77990: Fix MOD_SEL1 bit31 when using SIM0_D"
+    - ath10k: fix backtrace on coredump
+    - IB/iser: bound protection_sg size by data_sg size
+    - drm/komeda: Workaround for broken FLIP_COMPLETE timestamps
+    - spi: gpio: prevent memory leak in spi_gpio_probe
+    - media: am437x-vpfe: Setting STD to current value is not an error
+    - media: cedrus: fill in bus_info for media device
+    - media: seco-cec: Add a missing 'release_region()' in an error handling path
+    - media: vim2m: Fix abort issue
+    - media: vim2m: Fix BUG_ON in vim2m_device_release()
+    - media: max2175: Fix build error without CONFIG_REGMAP_I2C
+    - media: ov6650: Fix control handler not freed on init error
+    - media: i2c: ov2659: fix s_stream return value
+    - media: ov6650: Fix crop rectangle alignment not passed back
+    - media: i2c: ov2659: Fix missing 720p register config
+    - media: ov6650: Fix stored frame format not in sync with hardware
+    - media: ov6650: Fix stored crop rectangle not in sync with hardware
+    - tools/power/cpupower: Fix initializer override in hsw_ext_cstates
+    - media: venus: core: Fix msm8996 frequency table
+    - ath10k: fix offchannel tx failure when no ath10k_mac_tx_frm_has_freq
+    - media: vimc: Fix gpf in rmmod path when stream is active
+    - drm/amd/display: Set number of pipes to 1 if the second pipe was disabled
+    - pinctrl: devicetree: Avoid taking direct reference to device name string
+    - drm/sun4i: dsi: Fix TCON DRQ set bits
+    - drm/amdkfd: fix a potential NULL pointer dereference (v2)
+    - x86/math-emu: Check __copy_from_user() result
+    - drm/amd/powerplay: A workaround to GPU RESET on APU
+    - selftests/bpf: Correct path to include msg + path
+    - drm/amd/display: set minimum abm backlight level
+    - media: venus: Fix occasionally failures to suspend
+    - rtw88: fix NSS of hw_cap
+    - drm/amd/display: fix struct init in update_bounding_box
+    - usb: renesas_usbhs: add suspend event support in gadget mode
+    - crypto: aegis128-neon - use Clang compatible cflags for ARM
+    - hwrng: omap3-rom - Call clk_disable_unprepare() on exit only if not idled
+    - regulator: max8907: Fix the usage of uninitialized variable in
+      max8907_regulator_probe()
+    - tools/memory-model: Fix data race detection for unordered store and load
+    - media: flexcop-usb: fix NULL-ptr deref in flexcop_usb_transfer_init()
+    - media: cec-funcs.h: add status_req checks
+    - media: meson/ao-cec: move cec_notifier_cec_adap_register after hw setup
+    - drm/bridge: dw-hdmi: Refuse DDC/CI transfers on the internal I2C controller
+    - samples: pktgen: fix proc_cmd command result check logic
+    - block: Fix writeback throttling W=1 compiler warnings
+    - drm/amdkfd: Fix MQD size calculation
+    - MIPS: futex: Emit Loongson3 sync workarounds within asm
+    - mwifiex: pcie: Fix memory leak in mwifiex_pcie_init_evt_ring
+    - drm/drm_vblank: Change EINVAL by the correct errno
+    - selftests/bpf: Fix btf_dump padding test case
+    - libbpf: Fix struct end padding in btf_dump
+    - libbpf: Fix passing uninitialized bytes to setsockopt
+    - net/smc: increase device refcount for added link group
+    - team: call RCU read lock when walking the port_list
+    - media: cx88: Fix some error handling path in 'cx8800_initdev()'
+    - crypto: inside-secure - Fix a maybe-uninitialized warning
+    - crypto: aegis128/simd - build 32-bit ARM for v8 architecture explicitly
+    - misc: fastrpc: fix memory leak from miscdev->name
+    - media: ti-vpe: vpe: Fix Motion Vector vpdma stride
+    - media: ti-vpe: vpe: fix a v4l2-compliance warning about invalid pixel format
+    - media: ti-vpe: vpe: fix a v4l2-compliance failure about frame sequence
+      number
+    - media: ti-vpe: vpe: Make sure YUYV is set as default format
+    - media: ti-vpe: vpe: fix a v4l2-compliance failure causing a kernel panic
+    - media: ti-vpe: vpe: ensure buffers are cleaned up properly in abort cases
+    - drm/amd/display: Properly round nominal frequency for SPD
+    - drm/amd/display: wait for set pipe mcp command completion
+    - media: ti-vpe: vpe: fix a v4l2-compliance failure about invalid sizeimage
+    - drm/amd/display: add new active dongle to existent w/a
+    - syscalls/x86: Use the correct function type in SYSCALL_DEFINE0
+    - drm/amd/display: Fix dongle_caps containing stale information.
+    - extcon: sm5502: Reset registers during initialization
+    - drm/amd/display: Program DWB watermarks from correct state
+    - x86/mm: Use the correct function type for native_set_fixmap()
+    - ath10k: Correct error handling of dma_map_single()
+    - rtw88: coex: Set 4 slot mode for A2DP
+    - drm/bridge: dw-hdmi: Restore audio when setting a mode
+    - perf test: Report failure for mmap events
+    - perf report: Add warning when libunwind not compiled in
+    - perf test: Avoid infinite loop for task exit case
+    - perf vendor events arm64: Fix Hisi hip08 DDRC PMU eventname
+    - usb: usbfs: Suppress problematic bind and unbind uevents.
+    - drm/amd/powerplay: avoid disabling ECC if RAS is enabled for VEGA20
+    - iio: adc: max1027: Reset the device at probe time
+    - Bluetooth: btusb: avoid unused function warning
+    - Bluetooth: missed cpu_to_le16 conversion in hci_init4_req
+    - Bluetooth: Workaround directed advertising bug in Broadcom controllers
+    - Bluetooth: hci_core: fix init for HCI_USER_CHANNEL
+    - bpf/stackmap: Fix deadlock with rq_lock in bpf_get_stack()
+    - x86/mce: Lower throttling MCE messages' priority to warning
+    - drm/amd/display: enable hostvm based on roimmu active for dcn2.1
+    - drm/amd/display: fix header for RN clk mgr
+    - drm/amdgpu: fix amdgpu trace event print string format error
+    - staging: iio: ad9834: add a check for devm_clk_get
+    - power: supply: cpcap-battery: Check voltage before orderly_poweroff
+    - perf tests: Disable bp_signal testing for arm64
+    - selftests/bpf: Make a copy of subtest name
+    - net: hns3: log and clear hardware error after reset complete
+    - RDMA/hns: Fix wrong parameters when initial mtt of srq->idx_que
+    - drm/gma500: fix memory disclosures due to uninitialized bytes
+    - ASoC: soc-pcm: fixup dpcm_prune_paths() loop continue
+    - rtl8xxxu: fix RTL8723BU connection failure issue after warm reboot
+    - RDMA/siw: Fix SQ/RQ drain logic
+    - ipmi: Don't allow device module unload when in use
+    - x86/ioapic: Prevent inconsistent state when moving an interrupt
+    - media: cedrus: Fix undefined shift with a SHIFT_AND_MASK_BITS macro
+    - media: aspeed: set hsync and vsync polarities to normal before starting mode
+      detection
+    - drm/nouveau: Don't grab runtime PM refs for HPD IRQs
+    - media: ov6650: Fix stored frame interval not in sync with hardware
+    - media: ad5820: Define entity function
+    - media: ov5640: Make 2592x1944 mode only available at 15 fps
+    - media: st-mipid02: add a check for devm_gpiod_get_optional
+    - media: imx7-mipi-csis: Add a check for devm_regulator_get
+    - media: aspeed: clear garbage interrupts
+    - media: smiapp: Register sensor after enabling runtime PM on the device
+    - md: no longer compare spare disk superblock events in super_load
+    - staging: wilc1000: potential corruption in wilc_parse_join_bss_param()
+    - md/bitmap: avoid race window between md_bitmap_resize and
+      bitmap_file_clear_bit
+    - drm: Don't free jobs in wait_event_interruptible()
+    - EDAC/amd64: Set grain per DIMM
+    - arm64: psci: Reduce the waiting time for cpu_psci_cpu_kill()
+    - drm/amd/display: setting the DIG_MODE to the correct value.
+    - i40e: initialize ITRN registers with correct values
+    - drm/amd/display: correctly populate dpp refclk in fpga
+    - i40e: Wrong 'Advertised FEC modes' after set FEC to AUTO
+    - net: phy: dp83867: enable robust auto-mdix
+    - drm/tegra: sor: Use correct SOR index on Tegra210
+    - regulator: core: Release coupled_rdevs on regulator_init_coupling() error
+    - ubsan, x86: Annotate and allow __ubsan_handle_shift_out_of_bounds() in
+      uaccess regions
+    - spi: sprd: adi: Add missing lock protection when rebooting
+    - ACPI: button: Add DMI quirk for Medion Akoya E2215T
+    - RDMA/qedr: Fix memory leak in user qp and mr
+    - RDMA/hns: Fix memory leak on 'context' on error return path
+    - RDMA/qedr: Fix srqs xarray initialization
+    - RDMA/core: Set DMA parameters correctly
+    - staging: wilc1000: check if device is initialzied before changing vif
+    - gpu: host1x: Allocate gather copy for host1x
+    - net: dsa: LAN9303: select REGMAP when LAN9303 enable
+    - phy: renesas: phy-rcar-gen2: Fix the array off by one warning
+    - phy: qcom-usb-hs: Fix extcon double register after power cycle
+    - s390/time: ensure get_clock_monotonic() returns monotonic values
+    - s390: add error handling to perf_callchain_kernel
+    - s390/mm: add mm_pxd_folded() checks to pxd_free()
+    - net: hns3: add struct netdev_queue debug info for TX timeout
+    - libata: Ensure ata_port probe has completed before detach
+    - loop: fix no-unmap write-zeroes request behavior
+    - net/mlx5e: Verify that rule has at least one fwd/drop action
+    - pinctrl: sh-pfc: sh7734: Fix duplicate TCLK1_B
+    - ALSA: bebob: expand sleep just after breaking connections for protocol
+      version 1
+    - iio: dln2-adc: fix iio_triggered_buffer_postenable() position
+    - libbpf: Fix error handling in bpf_map__reuse_fd()
+    - Bluetooth: Fix advertising duplicated flags
+    - ALSA: pcm: Fix missing check of the new non-cached buffer type
+    - spi: sifive: disable clk when probe fails and remove
+    - ASoC: SOF: imx: fix reverse CONFIG_SND_SOC_SOF_OF dependency
+    - pinctrl: qcom: sc7180: Add missing tile info in SDC_QDSD_PINGROUP/UFS_RESET
+    - pinctrl: amd: fix __iomem annotation in amd_gpio_irq_handler()
+    - ixgbe: protect TX timestamping from API misuse
+    - cpufreq: sun50i: Fix CPU speed bin detection
+    - media: rcar_drif: fix a memory disclosure
+    - media: v4l2-core: fix touch support in v4l_g_fmt
+    - nvme: introduce "Command Aborted By host" status code
+    - media: staging/imx: Use a shorter name for driver
+    - nvmem: imx-ocotp: reset error status on probe
+    - nvmem: core: fix nvmem_cell_write inline function
+    - ASoC: SOF: topology: set trigger order for FE DAI link
+    - media: vivid: media_device_cleanup was called too early
+    - spi: dw: Fix Designware SPI loopback
+    - bnx2x: Fix PF-VF communication over multi-cos queues.
+    - spi: img-spfi: fix potential double release
+    - ALSA: timer: Limit max amount of slave instances
+    - RDMA/core: Fix return code when modify_port isn't supported
+    - drm: msm: a6xx: fix debug bus register configuration
+    - rtlwifi: fix memory leak in rtl92c_set_fw_rsvdpagepkt()
+    - perf probe: Fix to find range-only function instance
+    - perf cs-etm: Fix definition of macro TO_CS_QUEUE_NR
+    - perf probe: Fix to list probe event with correct line number
+    - perf jevents: Fix resource leak in process_mapfile() and main()
+    - perf probe: Walk function lines in lexical blocks
+    - perf probe: Fix to probe an inline function which has no entry pc
+    - perf probe: Fix to show ranges of variables in functions without entry_pc
+    - perf probe: Fix to show inlined function callsite without entry_pc
+    - libsubcmd: Use -O0 with DEBUG=1
+    - perf probe: Fix to probe a function which has no entry pc
+    - perf tools: Fix cross compile for ARM64
+    - perf tools: Splice events onto evlist even on error
+    - drm/amdgpu: disallow direct upload save restore list from gfx driver
+    - drm/amd/powerplay: fix struct init in renoir_print_clk_levels
+    - drm/amdgpu: fix potential double drop fence reference
+    - ice: Check for null pointer dereference when setting rings
+    - xen/gntdev: Use select for DMA_SHARED_BUFFER
+    - perf parse: If pmu configuration fails free terms
+    - perf probe: Skip overlapped location on searching variables
+    - net: avoid potential false sharing in neighbor related code
+    - perf probe: Return a better scope DIE if there is no best scope
+    - perf probe: Fix to show calling lines of inlined functions
+    - perf probe: Skip end-of-sequence and non statement lines
+    - perf probe: Filter out instances except for inlined subroutine and
+      subprogram
+    - libbpf: Fix negative FD close() in xsk_setup_xdp_prog()
+    - s390/bpf: Use kvcalloc for addrs array
+    - cgroup: freezer: don't change task and cgroups status unnecessarily
+    - selftests: proc: Make va_max 1MB
+    - drm/amdgpu: Avoid accidental thread reactivation.
+    - media: exynos4-is: fix wrong mdev and v4l2 dev order in error path
+    - ath10k: fix get invalid tx rate for Mesh metric
+    - fsi: core: Fix small accesses and unaligned offsets via sysfs
+    - selftests: net: Fix printf format warnings on arm
+    - media: pvrusb2: Fix oops on tear-down when radio support is not present
+    - soundwire: intel: fix PDI/stream mapping for Bulk
+    - crypto: atmel - Fix authenc support when it is set to m
+    - ice: delay less
+    - media: si470x-i2c: add missed operations in remove
+    - media: cedrus: Use helpers to access capture queue
+    - media: v4l2-ctrl: Lock main_hdl on operations of requests_queued.
+    - iio: cros_ec_baro: set info_mask_shared_by_all_available field
+    - EDAC/ghes: Fix grain calculation
+    - media: vicodec: media_device_cleanup was called too early
+    - media: vim2m: media_device_cleanup was called too early
+    - spi: pxa2xx: Add missed security checks
+    - ASoC: rt5677: Mark reg RT5677_PWR_ANLG2 as volatile
+    - iio: dac: ad5446: Add support for new AD5600 DAC
+    - bpf, testing: Workaround a verifier failure for test_progs
+    - ASoC: Intel: kbl_rt5663_rt5514_max98927: Add dmic format constraint
+    - net: dsa: sja1105: Disallow management xmit during switch reset
+    - r8169: respect EEE user setting when restarting network
+    - s390/disassembler: don't hide instruction addresses
+    - net: ethernet: ti: Add dependency for TI_DAVINCI_EMAC
+    - nvme: Discard workaround for non-conformant devices
+    - parport: load lowlevel driver if ports not found
+    - bcache: fix static checker warning in bcache_device_free()
+    - cpufreq: Register drivers only after CPU devices have been registered
+    - qtnfmac: fix debugfs support for multiple cards
+    - qtnfmac: fix invalid channel information output
+    - x86/crash: Add a forward declaration of struct kimage
+    - qtnfmac: fix using skb after free
+    - RDMA/efa: Clear the admin command buffer prior to its submission
+    - tracing: use kvcalloc for tgid_map array allocation
+    - MIPS: ralink: enable PCI support only if driver for mt7621 SoC is selected
+    - tracing/kprobe: Check whether the non-suffixed symbol is notrace
+    - iwlwifi: mvm: fix unaligned read of rx_pkt_status
+    - ASoC: wm8904: fix regcache handling
+    - regulator: core: Let boot-on regulators be powered off
+    - spi: tegra20-slink: add missed clk_unprepare
+    - tun: fix data-race in gro_normal_list()
+    - xhci-pci: Allow host runtime PM as default also for Intel Ice Lake xHCI
+    - crypto: virtio - deal with unsupported input sizes
+    - mmc: tmio: Add MMC_CAP_ERASE to allow erase/discard/trim requests
+    - btrfs: don't prematurely free work in end_workqueue_fn()
+    - btrfs: don't prematurely free work in run_ordered_work()
+    - sched/uclamp: Fix overzealous type replacement
+    - ASoC: wm2200: add missed operations in remove and probe failure
+    - spi: st-ssc4: add missed pm_runtime_disable
+    - ASoC: wm5100: add missed pm_runtime_disable
+    - perf/core: Fix the mlock accounting, again
+    - selftests, bpf: Fix test_tc_tunnel hanging
+    - selftests, bpf: Workaround an alu32 sub-register spilling issue
+    - bnxt_en: Return proper error code for non-existent NVM variable
+    - net: phy: avoid matching all-ones clause 45 PHY IDs
+    - firmware_loader: Fix labels with comma for builtin firmware
+    - ASoC: Intel: bytcr_rt5640: Update quirk for Acer Switch 10 SW5-012 2-in-1
+    - x86/insn: Add some Intel instructions to the opcode map
+    - net-af_xdp: Use correct number of channels from ethtool
+    - brcmfmac: remove monitor interface when detaching
+    - perf session: Fix decompression of PERF_RECORD_COMPRESSED records
+    - perf probe: Fix to show function entry line as probe-able
+    - s390/crypto: Fix unsigned variable compared with zero
+    - s390/kasan: support memcpy_real with TRACE_IRQFLAGS
+    - bnxt_en: Improve RX buffer error handling.
+    - iwlwifi: check kasprintf() return value
+    - fbtft: Make sure string is NULL terminated
+    - ASoC: soc-pcm: check symmetry before hw_params
+    - net: ethernet: ti: ale: clean ale tbl on init and intf restart
+    - mt76: fix possible out-of-bound access in mt7615_fill_txs/mt7603_fill_txs
+    - s390/cpumf: Adjust registration of s390 PMU device drivers
+    - crypto: sun4i-ss - Fix 64-bit size_t warnings
+    - crypto: sun4i-ss - Fix 64-bit size_t warnings on sun4i-ss-hash.c
+    - mac80211: consider QoS Null frames for STA_NULLFUNC_ACKED
+    - crypto: vmx - Avoid weird build failures
+    - libtraceevent: Fix memory leakage in copy_filter_type
+    - mips: fix build when "48 bits virtual memory" is enabled
+    - drm/amdgpu: fix bad DMA from INTERRUPT_CNTL2
+    - ice: Only disable VF state when freeing each VF resources
+    - ice: Fix setting coalesce to handle DCB configuration
+    - net: phy: initialise phydev speed and duplex sanely
+    - tools, bpf: Fix build for 'make -s tools/bpf O=<dir>'
+    - RDMA/bnxt_re: Fix missing le16_to_cpu
+    - RDMA/bnxt_re: Fix stat push into dma buffer on gen p5 devices
+    - bpf: Provide better register bounds after jmp32 instructions
+    - RDMA/bnxt_re: Fix chip number validation Broadcom's Gen P5 series
+    - ibmvnic: Fix completion structure initialization
+    - net: wireless: intel: iwlwifi: fix GRO_NORMAL packet stalling
+    - MIPS: futex: Restore \n after sync instructions
+    - btrfs: don't prematurely free work in reada_start_machine_worker()
+    - btrfs: don't prematurely free work in scrub_missing_raid56_worker()
+    - Revert "mmc: sdhci: Fix incorrect switch to HS mode"
+    - mmc: mediatek: fix CMD_TA to 2 for MT8173 HS200/HS400 mode
+    - tpm_tis: reserve chip for duration of tpm_tis_core_init
+    - tpm: fix invalid locking in NONBLOCKING mode
+    - iommu: fix KASAN use-after-free in iommu_insert_resv_region
+    - iommu: set group default domain before creating direct mappings
+    - iommu/vt-d: Fix dmar pte read access not set error
+    - iommu/vt-d: Set ISA bridge reserved region as relaxable
+    - iommu/vt-d: Allocate reserved region for ISA with correct permission
+    - can: xilinx_can: Fix missing Rx can packets on CANFD2.0
+    - can: m_can: tcan4x5x: add required delay after reset
+    - can: j1939: j1939_sk_bind(): take priv after lock is held
+    - can: flexcan: fix possible deadlock and out-of-order reception after wakeup
+    - can: flexcan: poll MCR_LPM_ACK instead of GPR ACK for stop mode
+      acknowledgment
+    - can: kvaser_usb: kvaser_usb_leaf: Fix some info-leaks to USB devices
+    - spi: dw: Correct handling of native chipselect
+    - spi: cadence: Correct handling of native chipselect
+    - usb: xhci: Fix build warning seen with CONFIG_PM=n
+    - drm/amdgpu: fix uninitialized variable pasid_mapping_needed
+    - ath10k: Revert "ath10k: add cleanup in ath10k_sta_state()"
+    - RDMA/siw: Fix post_recv QP state locking
+    - md: avoid invalid memory access for array sb->dev_roles
+    - s390/ftrace: fix endless recursion in function_graph tracer
+    - ARM: dts: Fix vcsi regulator to be always-on for droid4 to prevent hangs
+    - can: flexcan: add low power enter/exit acknowledgment helper
+    - usbip: Fix receive error in vhci-hcd when using scatter-gather
+    - usbip: Fix error path of vhci_recv_ret_submit()
+    - spi: fsl: don't map irq during probe
+    - spi: fsl: use platform_get_irq() instead of of_irq_to_resource()
+    - efi/memreserve: Register reservations as 'reserved' in /proc/iomem
+    - cpufreq: Avoid leaving stale IRQ work items during CPU offline
+    - KEYS: asymmetric: return ENOMEM if akcipher_request_alloc() fails
+    - mm: vmscan: protect shrinker idr replace with CONFIG_MEMCG
+    - USB: EHCI: Do not return -EPIPE when hub is disconnected
+    - intel_th: pci: Add Comet Lake PCH-V support
+    - intel_th: pci: Add Elkhart Lake SOC support
+    - intel_th: Fix freeing IRQs
+    - intel_th: msu: Fix window switching without windows
+    - platform/x86: hp-wmi: Make buffer for HPWMI_FEATURE2_QUERY 128 bytes
+    - staging: comedi: gsc_hpdi: check dma_alloc_coherent() return value
+    - tty/serial: atmel: fix out of range clock divider handling
+    - serial: sprd: Add clearing break interrupt operation
+    - pinctrl: baytrail: Really serialize all register accesses
+    - clk: imx: clk-imx7ulp: Add missing sentinel of ulp_div_table
+    - clk: imx: clk-composite-8m: add lock to gate/mux
+    - clk: imx: pll14xx: fix clk_pll14xx_wait_lock
+    - ext4: fix ext4_empty_dir() for directories with holes
+    - ext4: check for directory entries too close to block end
+    - ext4: unlock on error in ext4_expand_extra_isize()
+    - ext4: validate the debug_want_extra_isize mount option at parse time
+    - iocost: over-budget forced IOs should schedule async delay
+    - KVM: PPC: Book3S HV: Fix regression on big endian hosts
+    - kvm: x86: Host feature SSBD doesn't imply guest feature SPEC_CTRL_SSBD
+    - kvm: x86: Host feature SSBD doesn't imply guest feature AMD_SSBD
+    - KVM: arm/arm64: Properly handle faulting of device mappings
+    - KVM: arm64: Ensure 'params' is initialised when looking up sys register
+    - x86/MCE/AMD: Do not use rdmsr_safe_on_cpu() in smca_configure()
+    - x86/MCE/AMD: Allow Reserved types to be overwritten in smca_banks[]
+    - x86/mce: Fix possibly incorrect severity calculation on AMD
+    - powerpc/vcpu: Assume dedicated processors as non-preempt
+    - powerpc/irq: fix stack overflow verification
+    - ocxl: Fix concurrent AFU open and device removal
+    - mmc: sdhci-msm: Correct the offset and value for DDR_CONFIG register
+    - mmc: sdhci-of-esdhc: Revert "mmc: sdhci-of-esdhc: add erratum A-009204
+      support"
+    - mmc: sdhci: Update the tuning failed messages to pr_debug level
+    - mmc: sdhci-of-esdhc: fix P2020 errata handling
+    - mmc: sdhci: Workaround broken command queuing on Intel GLK
+    - mmc: sdhci: Add a quirk for broken command queuing
+    - nbd: fix shutdown and recv work deadlock v2
+    - iwlwifi: pcie: move power gating workaround earlier in the flow
+    - Linux 5.4.7
+
+  * Focal update: v5.4.6 upstream stable release (LP: #1858427)
+    - Revert "UBUNTU: SAUCE: drm/i915/fbc: disable framebuffer compression on
+      IceLake"
+    - USB: Fix incorrect DMA allocations for local memory pool drivers
+    - mmc: block: Make card_busy_detect() a bit more generic
+    - mmc: block: Add CMD13 polling for MMC IOCTLS with R1B response
+    - mmc: core: Drop check for mmc_card_is_removable() in mmc_rescan()
+    - mmc: core: Re-work HW reset for SDIO cards
+    - PCI/switchtec: Read all 64 bits of part_event_bitmap
+    - PCI/PM: Always return devices to D0 when thawing
+    - PCI: pciehp: Avoid returning prematurely from sysfs requests
+    - PCI: Fix Intel ACS quirk UPDCR register address
+    - PCI/MSI: Fix incorrect MSI-X masking on resume
+    - PCI: Do not use bus number zero from EA capability
+    - PCI: rcar: Fix missing MACCTLR register setting in initialization sequence
+    - PCI: Apply Cavium ACS quirk to ThunderX2 and ThunderX3
+    - PM / QoS: Redefine FREQ_QOS_MAX_DEFAULT_VALUE to S32_MAX
+    - block: fix "check bi_size overflow before merge"
+    - xtensa: use MEMBLOCK_ALLOC_ANYWHERE for KASAN shadow map
+    - gfs2: Multi-block allocations in gfs2_page_mkwrite
+    - gfs2: fix glock reference problem in gfs2_trans_remove_revoke
+    - xtensa: fix TLB sanity checker
+    - xtensa: fix syscall_set_return_value
+    - rpmsg: glink: Set tail pointer to 0 at end of FIFO
+    - rpmsg: glink: Fix reuse intents memory leak issue
+    - rpmsg: glink: Fix use after free in open_ack TIMEOUT case
+    - rpmsg: glink: Put an extra reference during cleanup
+    - rpmsg: glink: Fix rpmsg_register_device err handling
+    - rpmsg: glink: Don't send pending rx_done during remove
+    - rpmsg: glink: Free pending deferred work on remove
+    - cifs: smbd: Return -EAGAIN when transport is reconnecting
+    - cifs: smbd: Only queue work for error recovery on memory registration
+    - cifs: smbd: Add messages on RDMA session destroy and reconnection
+    - cifs: smbd: Return -EINVAL when the number of iovs exceeds SMBDIRECT_MAX_SGE
+    - cifs: smbd: Return -ECONNABORTED when trasnport is not in connected state
+    - cifs: Don't display RDMA transport on reconnect
+    - CIFS: Respect O_SYNC and O_DIRECT flags during reconnect
+    - CIFS: Close open handle after interrupted close
+    - CIFS: Do not miss cancelled OPEN responses
+    - CIFS: Fix NULL pointer dereference in mid callback
+    - ARM: dts: s3c64xx: Fix init order of clock providers
+    - ARM: tegra: Fix FLOW_CTLR_HALT register clobbering by tegra_resume()
+    - vfio/pci: call irq_bypass_unregister_producer() before freeing irq
+    - dma-buf: Fix memory leak in sync_file_merge()
+    - drm/panfrost: Fix a race in panfrost_ioctl_madvise()
+    - drm/panfrost: Fix a BO leak in panfrost_ioctl_mmap_bo()
+    - drm/panfrost: Fix a race in panfrost_gem_free_object()
+    - drm/mgag200: Extract device type from flags
+    - drm/mgag200: Store flags from PCI driver data in device structure
+    - drm/mgag200: Add workaround for HW that does not support 'startadd'
+    - drm/mgag200: Flag all G200 SE A machines as broken wrt <startadd>
+    - drm: meson: venc: cvbs: fix CVBS mode matching
+    - dm mpath: remove harmful bio-based optimization
+    - dm btree: increase rebalance threshold in __rebalance2()
+    - dm clone metadata: Track exact changes per transaction
+    - dm clone metadata: Use a two phase commit
+    - dm clone: Flush destination device before committing metadata
+    - dm thin metadata: Add support for a pre-commit callback
+    - dm thin: Flush data device before committing metadata
+    - scsi: ufs: Disable autohibern8 feature in Cadence UFS
+    - scsi: iscsi: Fix a potential deadlock in the timeout handler
+    - scsi: qla2xxx: Ignore NULL pointer in tcm_qla2xxx_free_mcmd
+    - scsi: qla2xxx: Initialize free_work before flushing it
+    - scsi: qla2xxx: Added support for MPI and PEP regions for ISP28XX
+    - scsi: qla2xxx: Change discovery state before PLOGI
+    - scsi: qla2xxx: Correctly retrieve and interpret active flash region
+    - scsi: qla2xxx: Fix incorrect SFUB length used for Secure Flash Update MB Cmd
+    - drm/nouveau/kms/nv50-: Call outp_atomic_check_view() before handling PBN
+    - drm/nouveau/kms/nv50-: Store the bpc we're using in nv50_head_atom
+    - drm/nouveau/kms/nv50-: Limit MST BPC to 8
+    - drm/i915/fbc: Disable fbc by default on all glk+
+    - drm/radeon: fix r1xx/r2xx register checker for POT textures
+    - drm/dp_mst: Correct the bug in drm_dp_update_payload_part1()
+    - drm/amd/display: re-enable wait in pipelock, but add timeout
+    - drm/amd/display: add default clocks if not able to fetch them
+    - drm/amdgpu: initialize vm_inv_eng0_sem for gfxhub and mmhub
+    - drm/amdgpu: invalidate mmhub semaphore workaround in gmc9/gmc10
+    - drm/amdgpu/gfx10: explicitly wait for cp idle after halt/unhalt
+    - drm/amdgpu/gfx10: re-init clear state buffer after gpu reset
+    - drm/i915/gvt: Fix cmd length check for MI_ATOMIC
+    - drm/amdgpu: avoid using invalidate semaphore for picasso
+    - drm/amdgpu: add invalidate semaphore limit for SRIOV and picasso in gmc9
+    - ALSA: hda: Fix regression by strip mask fix
+    - Linux 5.4.6
+
+  * Focal update: v5.4.5 upstream stable release (LP: #1858426)
+    - inet: protect against too small mtu values.
+    - mqprio: Fix out-of-bounds access in mqprio_dump
+    - net: bridge: deny dev_set_mac_address() when unregistering
+    - net: dsa: fix flow dissection on Tx path
+    - net: ethernet: ti: cpsw: fix extra rx interrupt
+    - net: sched: fix dump qlen for sch_mq/sch_mqprio with NOLOCK subqueues
+    - net_sched: validate TCA_KIND attribute in tc_chain_tmplt_add()
+    - net: thunderx: start phy before starting autonegotiation
+    - net/tls: Fix return values to avoid ENOTSUPP
+    - openvswitch: support asymmetric conntrack
+    - tcp: md5: fix potential overestimation of TCP option space
+    - tipc: fix ordering of tipc module init and exit routine
+    - net/mlx5e: Query global pause state before setting prio2buffer
+    - net: ipv6: add net argument to ip6_dst_lookup_flow
+    - net: ipv6_stub: use ip6_dst_lookup_flow instead of ip6_dst_lookup
+    - tcp: fix rejected syncookies due to stale timestamps
+    - tcp: tighten acceptance of ACKs not matching a child socket
+    - tcp: Protect accesses to .ts_recent_stamp with {READ,WRITE}_ONCE()
+    - net: core: rename indirect block ingress cb function
+    - net: sched: allow indirect blocks to bind to clsact in TC
+    - cls_flower: Fix the behavior using port ranges with hw-offload
+    - gre: refetch erspan header from skb->data after pskb_may_pull()
+    - Fixed updating of ethertype in function skb_mpls_pop
+    - hsr: fix a NULL pointer dereference in hsr_dev_xmit()
+    - net: Fixed updating of ethertype in skb_mpls_push()
+    - net/mlx5e: Fix TXQ indices to be sequential
+    - act_ct: support asymmetric conntrack
+    - net/mlx5e: Fix SFF 8472 eeprom length
+    - net/mlx5e: Fix freeing flow with kfree() and not kvfree()
+    - net/mlx5e: Fix translation of link mode into speed
+    - net/mlx5e: ethtool, Fix analysis of speed setting
+    - page_pool: do not release pool until inflight == 0.
+    - xdp: obtain the mem_id mutex before trying to remove an entry.
+    - ionic: keep users rss hash across lif reset
+    - net: mscc: ocelot: unregister the PTP clock on deinit
+    - r8169: add missing RX enabling for WoL on RTL8125
+    - Linux 5.4.5
+
+  * Focal update: v5.4.4 upstream stable release (LP: #1858424)
+    - usb: gadget: configfs: Fix missing spin_lock_init()
+    - usb: gadget: pch_udc: fix use after free
+    - nvme: Namepace identification descriptor list is optional
+    - Revert "nvme: Add quirk for Kingston NVME SSD running FW E8FK11.T"
+    - scsi: lpfc: Fix bad ndlp ptr in xri aborted handling
+    - scsi: zfcp: trace channel log even for FCP command responses
+    - scsi: qla2xxx: Do command completion on abort timeout
+    - scsi: qla2xxx: Fix driver unload hang
+    - scsi: qla2xxx: Fix double scsi_done for abort path
+    - scsi: qla2xxx: Fix memory leak when sending I/O fails
+    - compat_ioctl: add compat_ptr_ioctl()
+    - ceph: fix compat_ioctl for ceph_dir_operations
+    - media: venus: remove invalid compat_ioctl32 handler
+    - USB: uas: honor flag to avoid CAPACITY16
+    - USB: uas: heed CAPACITY_HEURISTICS
+    - USB: documentation: flags on usb-storage versus UAS
+    - usb: Allow USB device to be warm reset in suspended state
+    - usb: host: xhci-tegra: Correct phy enable sequence
+    - binder: fix incorrect calculation for num_valid
+    - staging: exfat: fix multiple definition error of `rename_file'
+    - staging: rtl8188eu: fix interface sanity check
+    - staging: rtl8712: fix interface sanity check
+    - staging: vchiq: call unregister_chrdev_region() when driver registration
+      fails
+    - staging: gigaset: fix general protection fault on probe
+    - staging: gigaset: fix illegal free on probe errors
+    - staging: gigaset: add endpoint-type sanity check
+    - usb: xhci: only set D3hot for pci device
+    - xhci: Fix memory leak in xhci_add_in_port()
+    - xhci: fix USB3 device initiated resume race with roothub autosuspend
+    - xhci: Increase STS_HALT timeout in xhci_suspend()
+    - xhci: handle some XHCI_TRUST_TX_LENGTH quirks cases as default behaviour.
+    - xhci: make sure interrupts are restored to correct state
+    - interconnect: qcom: sdm845: Walk the list safely on node removal
+    - interconnect: qcom: qcs404: Walk the list safely on node removal
+    - usb: common: usb-conn-gpio: Don't log an error on probe deferral
+    - ARM: dts: pandora-common: define wl1251 as child node of mmc3
+    - iio: adis16480: Add debugfs_reg_access entry
+    - iio: imu: st_lsm6dsx: fix ODR check in st_lsm6dsx_write_raw
+    - iio: adis16480: Fix scales factors
+    - iio: humidity: hdc100x: fix IIO_HUMIDITYRELATIVE channel reporting
+    - iio: imu: inv_mpu6050: fix temperature reporting using bad unit
+    - iio: adc: ad7606: fix reading unnecessary data from device
+    - iio: adc: ad7124: Enable internal reference
+    - USB: atm: ueagle-atm: add missing endpoint check
+    - USB: idmouse: fix interface sanity checks
+    - USB: serial: io_edgeport: fix epic endpoint lookup
+    - usb: roles: fix a potential use after free
+    - USB: adutux: fix interface sanity check
+    - usb: core: urb: fix URB structure initialization function
+    - usb: mon: Fix a deadlock in usbmon between mmap and read
+    - tpm: add check after commands attribs tab allocation
+    - tpm: Switch to platform_get_irq_optional()
+    - EDAC/altera: Use fast register IO for S10 IRQs
+    - brcmfmac: disable PCIe interrupts before bus reset
+    - mtd: spear_smi: Fix Write Burst mode
+    - mtd: rawnand: Change calculating of position page containing BBM
+    - virt_wifi: fix use-after-free in virt_wifi_newlink()
+    - virtio-balloon: fix managed page counts when migrating pages between zones
+    - usb: dwc3: pci: add ID for the Intel Comet Lake -H variant
+    - usb: dwc3: gadget: Fix logical condition
+    - usb: dwc3: gadget: Clear started flag for non-IOC
+    - usb: dwc3: ep0: Clear started flag on completion
+    - phy: renesas: rcar-gen3-usb2: Fix sysfs interface of "role"
+    - usb: typec: fix use after free in typec_register_port()
+    - iwlwifi: pcie: fix support for transmitting SKBs with fraglist
+    - btrfs: check page->mapping when loading free space cache
+    - btrfs: use btrfs_block_group_cache_done in update_block_group
+    - btrfs: use refcount_inc_not_zero in kill_all_nodes
+    - Btrfs: fix metadata space leak on fixup worker failure to set range as
+      delalloc
+    - Btrfs: fix negative subv_writers counter and data space leak after buffered
+      write
+    - btrfs: Avoid getting stuck during cyclic writebacks
+    - btrfs: Remove btrfs_bio::flags member
+    - Btrfs: send, skip backreference walking for extents with many references
+    - btrfs: record all roots for rename exchange on a subvol
+    - rtlwifi: rtl8192de: Fix missing code to retrieve RX buffer address
+    - rtlwifi: rtl8192de: Fix missing callback that tests for hw release of buffer
+    - rtlwifi: rtl8192de: Fix missing enable interrupt flag
+    - lib: raid6: fix awk build warnings
+    - ovl: fix corner case of non-unique st_dev;st_ino
+    - ovl: relax WARN_ON() on rename to self
+    - hwrng: omap - Fix RNG wait loop timeout
+    - dm writecache: handle REQ_FUA
+    - dm zoned: reduce overhead of backing device checks
+    - workqueue: Fix spurious sanity check failures in destroy_workqueue()
+    - workqueue: Fix pwq ref leak in rescuer_thread()
+    - ASoC: rt5645: Fixed buddy jack support.
+    - ASoC: rt5645: Fixed typo for buddy jack support.
+    - ASoC: Jack: Fix NULL pointer dereference in snd_soc_jack_report
+    - ASoC: fsl_audmix: Add spin lock to protect tdms
+    - md: improve handling of bio with REQ_PREFLUSH in md_flush_request()
+    - blk-mq: avoid sysfs buffer overflow with too many CPU cores
+    - cgroup: pids: use atomic64_t for pids->limit
+    - wil6210: check len before memcpy() calls
+    - ar5523: check NULL before memcpy() in ar5523_cmd()
+    - s390/mm: properly clear _PAGE_NOEXEC bit when it is not supported
+    - media: hantro: Fix s_fmt for dynamic resolution changes
+    - media: hantro: Fix motion vectors usage condition
+    - media: hantro: Fix picture order count table enable
+    - media: vimc: sen: remove unused kthread_sen field
+    - media: bdisp: fix memleak on release
+    - media: radio: wl1273: fix interrupt masking on release
+    - media: cec.h: CEC_OP_REC_FLAG_ values were swapped
+    - cpuidle: Do not unset the driver if it is there already
+    - cpuidle: teo: Ignore disabled idle states that are too deep
+    - cpuidle: teo: Rename local variable in teo_select()
+    - cpuidle: teo: Consider hits and misses metrics of disabled states
+    - cpuidle: teo: Fix "early hits" handling for disabled idle states
+    - cpuidle: use first valid target residency as poll time
+    - erofs: zero out when listxattr is called with no xattr
+    - perf tests: Fix out of bounds memory access
+    - drm/panfrost: Open/close the perfcnt BO
+    - powerpc/perf: Disable trace_imc pmu
+    - intel_th: Fix a double put_device() in error path
+    - intel_th: pci: Add Ice Lake CPU support
+    - intel_th: pci: Add Tiger Lake CPU support
+    - PM / devfreq: Lock devfreq in trans_stat_show
+    - cpufreq: powernv: fix stack bloat and hard limit on number of CPUs
+    - ALSA: fireface: fix return value in error path of isochronous resources
+      reservation
+    - ALSA: oxfw: fix return value in error path of isochronous resources
+      reservation
+    - ACPI / utils: Move acpi_dev_get_first_match_dev() under CONFIG_ACPI
+    - ACPI: LPSS: Add LNXVIDEO -> BYT I2C7 to lpss_device_links
+    - ACPI: LPSS: Add LNXVIDEO -> BYT I2C1 to lpss_device_links
+    - ACPI: LPSS: Add dmi quirk for skipping _DEP check for some device-links
+    - ACPI / hotplug / PCI: Allocate resources directly under the non-hotplug
+      bridge
+    - ACPI: OSL: only free map once in osl.c
+    - ACPI: bus: Fix NULL pointer check in acpi_bus_get_private_data()
+    - ACPI: EC: Rework flushing of pending work
+    - ACPI: PM: Avoid attaching ACPI PM domain to certain devices
+    - pinctrl: rza2: Fix gpio name typos
+    - pinctrl: armada-37xx: Fix irq mask access in armada_37xx_irq_set_type()
+    - pinctrl: samsung: Add of_node_put() before return in error path
+    - pinctrl: samsung: Fix device node refcount leaks in Exynos wakeup controller
+      init
+    - pinctrl: samsung: Fix device node refcount leaks in S3C24xx wakeup
+      controller init
+    - pinctrl: samsung: Fix device node refcount leaks in init code
+    - pinctrl: samsung: Fix device node refcount leaks in S3C64xx wakeup
+      controller init
+    - mmc: host: omap_hsmmc: add code for special init of wl1251 to get rid of
+      pandora_wl1251_init_card
+    - ARM: dts: omap3-tao3530: Fix incorrect MMC card detection GPIO polarity
+    - RDMA/core: Fix ib_dma_max_seg_size()
+    - ppdev: fix PPGETTIME/PPSETTIME ioctls
+    - stm class: Lose the protocol driver when dropping its reference
+    - coresight: Serialize enabling/disabling a link device.
+    - powerpc: Allow 64bit VDSO __kernel_sync_dicache to work across ranges >4GB
+    - powerpc/xive: Prevent page fault issues in the machine crash handler
+    - powerpc: Allow flush_icache_range to work across ranges >4GB
+    - powerpc/xive: Skip ioremap() of ESB pages for LSI interrupts
+    - video/hdmi: Fix AVI bar unpack
+    - quota: Check that quota is not dirty before release
+    - ext2: check err when partial != NULL
+    - quota: fix livelock in dquot_writeback_dquots
+    - ext4: Fix credit estimate for final inode freeing
+    - reiserfs: fix extended attributes on the root directory
+    - scsi: qla2xxx: Fix SRB leak on switch command timeout
+    - scsi: qla2xxx: Fix a dma_pool_free() call
+    - Revert "scsi: qla2xxx: Fix memory leak when sending I/O fails"
+    - iio: ad7949: kill pointless "readback"-handling code
+    - iio: ad7949: fix channels mixups
+    - omap: pdata-quirks: revert pandora specific gpiod additions
+    - omap: pdata-quirks: remove openpandora quirks for mmc3 and wl1251
+    - powerpc: Avoid clang warnings around setjmp and longjmp
+    - powerpc: Fix vDSO clock_getres()
+    - mm, memfd: fix COW issue on MAP_PRIVATE and F_SEAL_FUTURE_WRITE mappings
+    - mm: memcg/slab: wait for !root kmem_cache refcnt killing on root kmem_cache
+      destruction
+    - ext4: work around deleting a file with i_nlink == 0 safely
+    - firmware: qcom: scm: Ensure 'a0' status code is treated as signed
+    - s390/smp,vdso: fix ASCE handling
+    - s390/kaslr: store KASLR offset for early dumps
+    - mm/shmem.c: cast the type of unmap_start to u64
+    - powerpc: Define arch_is_kernel_initmem_freed() for lockdep
+    - USB: dummy-hcd: increase max number of devices to 32
+    - rtc: disable uie before setting time and enable after
+    - splice: only read in as much information as there is pipe buffer space
+    - ext4: fix a bug in ext4_wait_for_tail_page_commit
+    - ext4: fix leak of quota reservations
+    - blk-mq: make sure that line break can be printed
+    - workqueue: Fix missing kfree(rescuer) in destroy_workqueue()
+    - r8169: fix rtl_hw_jumbo_disable for RTL8168evl
+    - EDAC/ghes: Do not warn when incrementing refcount on 0
+    - Linux 5.4.4
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update variants
+
+  * Miscellaneous Ubuntu changes
+    - [Packaging] Change source package to linux-5.4
+    - [Packaging] Don't use SRCPKGNAME for linux-libc-dev
+    - [Packaging] Remove linux-source-3 Provides: from linux-source
+    - [Packaging] Fix linux-doc in linux-image Suggests:
+    - [Debian] Read variants list into a variable
+    - [Packaging] Generate linux-libc-dev package only for primary variant
+    - [Packaging] Generate linux-doc for only the primary variant
+    - [Debian] Update linux source package name in debian/tests/*
+    - [Config] update annotations to match config changes
+    - [Config] disable PCI_MESON
+    - SAUCE: tools: hv: Update shebang to use python3 instead of python
+    - update dkms package versions
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Wed, 08 Jan 2020 15:00:54 -0600
+
+linux-5.4 (5.4.0-9.12) focal; urgency=medium
+
+  * Empty entry.
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Tue, 17 Dec 2019 07:09:13 -0600
+
+linux (5.4.0-9.12) focal; urgency=medium
+
+  * alsa/hda/realtek: the line-out jack doens't work on a dell AIO
+    (LP: #1855999)
+    - SAUCE: ALSA: hda/realtek - Line-out jack doesn't work on a Dell AIO
+
+  * scsi: hisi_sas: Check sas_port before using it (LP: #1855952)
+    - scsi: hisi_sas: Check sas_port before using it
+
+  * CVE-2019-19078
+    - ath10k: fix memory leak
+
+  * cifs: DFS Caching feature causing problems traversing multi-tier DFS setups
+    (LP: #1854887)
+    - cifs: Fix retrieval of DFS referrals in cifs_mount()
+
+  * Support DPCD aux brightness control (LP: #1856134)
+    - SAUCE: drm/i915: Fix eDP DPCD aux max backlight calculations
+    - SAUCE: drm/i915: Assume 100% brightness when not in DPCD control mode
+    - SAUCE: drm/i915: Fix DPCD register order in intel_dp_aux_enable_backlight()
+    - SAUCE: drm/i915: Auto detect DPCD backlight support by default
+    - SAUCE: drm/i915: Force DPCD backlight mode on X1 Extreme 2nd Gen 4K AMOLED
+      panel
+    - USUNTU: SAUCE: drm/i915: Force DPCD backlight mode on Dell Precision 4K sku
+
+  * The system cannot resume from S3 if user unplugs the TB16 during suspend
+    state (LP: #1849269)
+    - PCI: pciehp: Do not disable interrupt twice on suspend
+    - PCI: pciehp: Prevent deadlock on disconnect
+
+  * change kconfig of the soundwire bus driver from y to m (LP: #1855685)
+    - [Config]: SOUNDWIRE=m
+
+  * alsa/sof: change to use hda hdmi codec driver to make hdmi audio on the
+    docking station work (LP: #1855666)
+    - ALSA: hda/hdmi - implement mst_no_extra_pcms flag
+    - ASoC: hdac_hda: add support for HDMI/DP as a HDA codec
+    - ASoC: Intel: skl-hda-dsp-generic: use snd-hda-codec-hdmi
+    - ASoC: Intel: skl-hda-dsp-generic: fix include guard name
+    - ASoC: SOF: Intel: add support for snd-hda-codec-hdmi
+    - ASoC: Intel: bxt-da7219-max98357a: common hdmi codec support
+    - ASoC: Intel: glk_rt5682_max98357a: common hdmi codec support
+    - ASoC: intel: sof_rt5682: common hdmi codec support
+    - ASoC: Intel: bxt_rt298: common hdmi codec support
+    - ASoC: SOF: enable sync_write in hdac_bus
+    - [config]: SND_SOC_SOF_HDA_COMMON_HDMI_CODEC=y
+
+  * Fix unusable USB hub on Dell TB16 after S3 (LP: #1855312)
+    - SAUCE: USB: core: Make port power cycle a seperate helper function
+    - SAUCE: USB: core: Attempt power cycle port when it's in eSS.Disabled state
+
+  * Focal update: v5.4.3 upstream stable release (LP: #1856583)
+    - rsi: release skb if rsi_prepare_beacon fails
+    - arm64: tegra: Fix 'active-low' warning for Jetson TX1 regulator
+    - arm64: tegra: Fix 'active-low' warning for Jetson Xavier regulator
+    - perf scripts python: exported-sql-viewer.py: Fix use of TRUE with SQLite
+    - sparc64: implement ioremap_uc
+    - lp: fix sparc64 LPSETTIMEOUT ioctl
+    - time: Zero the upper 32-bits in __kernel_timespec on 32-bit
+    - mailbox: tegra: Fix superfluous IRQ error message
+    - staging/octeon: Use stubs for MIPS && !CAVIUM_OCTEON_SOC
+    - usb: gadget: u_serial: add missing port entry locking
+    - serial: 8250-mtk: Use platform_get_irq_optional() for optional irq
+    - tty: serial: fsl_lpuart: use the sg count from dma_map_sg
+    - tty: serial: msm_serial: Fix flow control
+    - serial: pl011: Fix DMA ->flush_buffer()
+    - serial: serial_core: Perform NULL checks for break_ctl ops
+    - serial: stm32: fix clearing interrupt error flags
+    - serial: 8250_dw: Avoid double error messaging when IRQ absent
+    - serial: ifx6x60: add missed pm_runtime_disable
+    - mwifiex: Re-work support for SDIO HW reset
+    - io_uring: fix dead-hung for non-iter fixed rw
+    - io_uring: transform send/recvmsg() -ERESTARTSYS to -EINTR
+    - fuse: fix leak of fuse_io_priv
+    - fuse: verify nlink
+    - fuse: verify write return
+    - fuse: verify attributes
+    - io_uring: fix missing kmap() declaration on powerpc
+    - io_uring: ensure req->submit is copied when req is deferred
+    - SUNRPC: Avoid RPC delays when exiting suspend
+    - ALSA: hda/realtek - Enable internal speaker of ASUS UX431FLC
+    - ALSA: hda/realtek - Fix inverted bass GPIO pin on Acer 8951G
+    - ALSA: pcm: oss: Avoid potential buffer overflows
+    - ALSA: hda - Add mute led support for HP ProBook 645 G4
+    - ALSA: hda: Modify stream stripe mask only when needed
+    - soc: mediatek: cmdq: fixup wrong input order of write api
+    - Input: synaptics - switch another X1 Carbon 6 to RMI/SMbus
+    - Input: synaptics-rmi4 - re-enable IRQs in f34v7_do_reflash
+    - Input: synaptics-rmi4 - don't increment rmiaddr for SMBus transfers
+    - Input: goodix - add upside-down quirk for Teclast X89 tablet
+    - coresight: etm4x: Fix input validation for sysfs.
+    - Input: Fix memory leak in psxpad_spi_probe
+    - media: rc: mark input device as pointing stick
+    - x86/mm/32: Sync only to VMALLOC_END in vmalloc_sync_all()
+    - CIFS: Fix NULL-pointer dereference in smb2_push_mandatory_locks
+    - CIFS: Fix SMB2 oplock break processing
+    - tty: vt: keyboard: reject invalid keycodes
+    - can: slcan: Fix use-after-free Read in slcan_open
+    - nfsd: Ensure CLONE persists data and metadata changes to the target file
+    - nfsd: restore NFSv3 ACL support
+    - kernfs: fix ino wrap-around detection
+    - jbd2: Fix possible overflow in jbd2_log_space_left()
+    - drm/msm: fix memleak on release
+    - drm: damage_helper: Fix race checking plane->state->fb
+    - drm/i810: Prevent underflow in ioctl
+    - arm64: Validate tagged addresses in access_ok() called from kernel threads
+    - arm64: dts: exynos: Revert "Remove unneeded address space mapping for soc
+      node"
+    - KVM: PPC: Book3S HV: XIVE: Free previous EQ page when setting up a new one
+    - KVM: PPC: Book3S HV: XIVE: Fix potential page leak on error path
+    - KVM: PPC: Book3S HV: XIVE: Set kvm->arch.xive when VPs are allocated
+    - KVM: nVMX: Always write vmcs02.GUEST_CR3 during nested VM-Enter
+    - KVM: arm/arm64: vgic: Don't rely on the wrong pending table
+    - KVM: x86: do not modify masked bits of shared MSRs
+    - KVM: x86: fix presentation of TSX feature in ARCH_CAPABILITIES
+    - KVM: x86: Remove a spurious export of a static function
+    - KVM: x86: Grab KVM's srcu lock when setting nested state
+    - crypto: crypto4xx - fix double-free in crypto4xx_destroy_sdr
+    - crypto: atmel-aes - Fix IV handling when req->nbytes < ivsize
+    - crypto: af_alg - cast ki_complete ternary op to int
+    - crypto: geode-aes - switch to skcipher for cbc(aes) fallback
+    - crypto: ccp - fix uninitialized list head
+    - crypto: ecdh - fix big endian bug in ECC library
+    - crypto: user - fix memory leak in crypto_report
+    - spi: spi-fsl-qspi: Clear TDH bits in FLSHCR register
+    - spi: stm32-qspi: Fix kernel oops when unbinding driver
+    - spi: atmel: Fix CS high support
+    - spi: Fix SPI_CS_HIGH setting when using native and GPIO CS
+    - spi: Fix NULL pointer when setting SPI_CS_HIGH for GPIO CS
+    - can: ucan: fix non-atomic allocation in completion handler
+    - RDMA/qib: Validate ->show()/store() callbacks before calling them
+    - rfkill: allocate static minor
+    - bdev: Factor out bdev revalidation into a common helper
+    - bdev: Refresh bdev size for disks without partitioning
+    - iomap: Fix pipe page leakage during splicing
+    - thermal: Fix deadlock in thermal thermal_zone_device_check
+    - vcs: prevent write access to vcsu devices
+    - Revert "serial/8250: Add support for NI-Serial PXI/PXIe+485 devices"
+    - binder: Fix race between mmap() and binder_alloc_print_pages()
+    - binder: Prevent repeated use of ->mmap() via NULL mapping
+    - binder: Handle start==NULL in binder_update_page_range()
+    - KVM: x86: fix out-of-bounds write in KVM_GET_EMULATED_CPUID (CVE-2019-19332)
+    - ALSA: hda - Fix pending unsol events at shutdown
+    - cpufreq: imx-cpufreq-dt: Correct i.MX8MN's default speed grade value
+    - md/raid0: Fix an error message in raid0_make_request()
+    - drm/mcde: Fix an error handling path in 'mcde_probe()'
+    - watchdog: aspeed: Fix clock behaviour for ast2600
+    - EDAC/ghes: Fix locking and memory barrier issues
+    - perf script: Fix invalid LBR/binary mismatch error
+    - kselftest: Fix NULL INSTALL_PATH for TARGETS runlist
+    - Linux 5.4.3
+
+  * Realtek ALC256M with DTS Audio Processing internal microphone doesn't work
+    on Redmi Book 14 2019 (LP: #1846148) // Focal update: v5.4.3 upstream stable
+    release (LP: #1856583)
+    - ALSA: hda/realtek - Enable the headset-mic on a Xiaomi's laptop
+
+  * Miscellaneous Ubuntu changes
+    - [Debian] add python depends to ubuntu-regression-suite
+    - SAUCE: selftests: net: tls: remove recv_rcvbuf test
+    - update dkms package versions
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 16 Dec 2019 14:54:19 -0600
+
+linux (5.4.0-8.11) focal; urgency=medium
+
+  * focal/linux: 5.4.0-8.9 -proposed tracker (LP: #1855448)
+
+  * update ENA driver for DIMLIB dynamic interrupt moderation (LP: #1853180)
+    - SAUCE: net: ena: fix issues in setting interrupt moderation params in
+      ethtool
+    - SAUCE: net: ena: fix too long default tx interrupt moderation interval
+
+  * Kernel build log filled with "/bin/bash: line 5: warning: command
+    substitution: ignored null byte in input" (LP: #1853843)
+    - [Debian] Fix warnings when checking for modules signatures
+
+  * hwe-edge kernel 5.3.0-23.25 kernel does not boot on Precision 5720 AIO
+    (LP: #1852581)
+    - [Packaging] Fix module signing with older modinfo
+
+  * Fix MST support on Ice Lake (LP: #1854432)
+    - drm/i915: fix port checks for MST support on gen >= 11
+
+  * headphone has noise as not mute on dell machines with alc236/256
+    (LP: #1854401)
+    - SAUCE: ALSA: hda/realtek - Dell headphone has noise on unmute for ALC236
+
+  * [CML-S62] Need enable intel_pmc_core driver patch for Comet lake- S 6+2
+    (LP: #1847450)
+    - SAUCE: platform/x86: intel_pmc_core: Add Comet Lake (CML) platform support
+      to intel_pmc_core driver
+
+  * CVE-2019-14901
+    - SAUCE: mwifiex: Fix heap overflow in mmwifiex_process_tdls_action_frame()
+
+  * CVE-2019-14896 // CVE-2019-14897
+    - SAUCE: libertas: Fix two buffer overflows at parsing bss descriptor
+
+  * CVE-2019-14895
+    - SAUCE: mwifiex: fix possible heap overflow in mwifiex_process_country_ie()
+
+  * [CML-S62] Need enable intel_rapl patch support for Comet lake- S 6+2
+    (LP: #1847454)
+    - powercap/intel_rapl: add support for CometLake Mobile
+    - powercap/intel_rapl: add support for Cometlake desktop
+
+  * External microphone can't work on some dell machines with the codec alc256
+    or alc236 (LP: #1853791)
+    - SAUCE: ALSA: hda/realtek - Move some alc256 pintbls to fallback table
+    - SAUCE: ALSA: hda/realtek - Move some alc236 pintbls to fallback table
+
+  * remount of multilower moved pivoted-root overlayfs root, results in I/O
+    errors on some modified files (LP: #1824407)
+    - SAUCE: ovl: fix lookup failure on multi lower squashfs
+
+  * [CML-S62] Need enable turbostat patch support for Comet lake- S 6+2
+    (LP: #1847451)
+    - SAUCE: tools/power turbostat: Add Cometlake support
+
+  * CONFIG_ARCH_ROCKCHIP is not set in ubuntu 18.04 aarch64,arm64 (LP: #1825222)
+    - [Config] Enable ROCKCHIP support for arm64
+
+  * [broadwell-rt286, playback] Since Linux 5.2rc2 audio playback no longer
+    works on Dell Venue 11 Pro 7140 (LP: #1846539)
+    - SAUCE: ASoC: SOF: Intel: Broadwell: clarify mutual exclusion with legacy
+      driver
+
+  * i40e: general protection fault in i40e_config_vf_promiscuous_mode
+    (LP: #1852663)
+    - SAUCE: i40e Fix GPF when deleting VMs
+
+  * libbpf check_abi fails on ppc64el (LP: #1854974)
+    - libbpf: Fix readelf output parsing on powerpc with recent binutils
+
+  * CVE-2019-19050
+    - crypto: user - fix memory leak in crypto_reportstat
+
+  * Make hotplugging docking station to Thunderbolt port more reliable
+    (LP: #1853991)
+    - PCI/PM: Add pcie_wait_for_link_delay()
+    - PCI/PM: Add missing link delays required by the PCIe spec
+
+  * i915: Display flickers (monitor loses signal briefly) during "flickerfree"
+    boot, while showing the BIOS logo on a black background (LP: #1836858)
+    - [Config] FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER=y
+
+  * [CML] New device id's for CMP-H (LP: #1846335)
+    - i2c: i801: Add support for Intel Comet Lake PCH-H
+    - mtd: spi-nor: intel-spi: Add support for Intel Comet Lake-H SPI serial flash
+    - mfd: intel-lpss: Add Intel Comet Lake PCH-H PCI IDs
+
+  * Focal update: v5.4.2 upstream stable release (LP: #1855326)
+    - io_uring: async workers should inherit the user creds
+    - net: separate out the msghdr copy from ___sys_{send,recv}msg()
+    - net: disallow ancillary data for __sys_{send,recv}msg_file()
+    - crypto: inside-secure - Fix stability issue with Macchiatobin
+    - driver core: platform: use the correct callback type for bus_find_device
+    - usb: dwc2: use a longer core rest timeout in dwc2_core_reset()
+    - staging: wilc1000: fix illegal memory access in wilc_parse_join_bss_param()
+    - staging: rtl8192e: fix potential use after free
+    - staging: rtl8723bs: Drop ACPI device ids
+    - staging: rtl8723bs: Add 024c:0525 to the list of SDIO device-ids
+    - USB: serial: ftdi_sio: add device IDs for U-Blox C099-F9P
+    - mei: bus: prefix device names on bus with the bus name
+    - mei: me: add comet point V device id
+    - thunderbolt: Power cycle the router if NVM authentication fails
+    - x86/fpu: Don't cache access to fpu_fpregs_owner_ctx
+    - gve: Fix the queue page list allocated pages count
+    - macvlan: schedule bc_work even if error
+    - mdio_bus: don't use managed reset-controller
+    - net: dsa: sja1105: fix sja1105_parse_rgmii_delays()
+    - net: macb: add missed tasklet_kill
+    - net: psample: fix skb_over_panic
+    - net: sched: fix `tc -s class show` no bstats on class with nolock subqueues
+    - openvswitch: fix flow command message size
+    - sctp: Fix memory leak in sctp_sf_do_5_2_4_dupcook
+    - slip: Fix use-after-free Read in slip_open
+    - sctp: cache netns in sctp_ep_common
+    - openvswitch: drop unneeded BUG_ON() in ovs_flow_cmd_build_info()
+    - openvswitch: remove another BUG_ON()
+    - net/tls: take into account that bpf_exec_tx_verdict() may free the record
+    - net/tls: free the record on encryption error
+    - net: skmsg: fix TLS 1.3 crash with full sk_msg
+    - selftests/tls: add a test for fragmented messages
+    - net/tls: remove the dead inplace_crypto code
+    - net/tls: use sg_next() to walk sg entries
+    - selftests: bpf: test_sockmap: handle file creation failures gracefully
+    - selftests: bpf: correct perror strings
+    - tipc: fix link name length check
+    - selftests: pmtu: use -oneline for ip route list cache
+    - r8169: fix jumbo configuration for RTL8168evl
+    - r8169: fix resume on cable plug-in
+    - ext4: add more paranoia checking in ext4_expand_extra_isize handling
+    - Revert "jffs2: Fix possible null-pointer dereferences in
+      jffs2_add_frag_to_fragtree()"
+    - crypto: talitos - Fix build error by selecting LIB_DES
+    - HID: core: check whether Usage Page item is after Usage ID items
+    - platform/x86: hp-wmi: Fix ACPI errors caused by too small buffer
+    - platform/x86: hp-wmi: Fix ACPI errors caused by passing 0 as input size
+    - Linux 5.4.2
+
+  * no HDMI video output since GDM greeter after linux-oem-osp1 version
+    5.0.0-1026 (LP: #1852386)
+    - drm/i915: Add new CNL PCH ID seen on a CML platform
+    - SAUCE: drm/i915: Fix detection for a CMP-V PCH
+
+  * Please add patch fixing RK818 ID detection (LP: #1853192)
+    - SAUCE: mfd: rk808: Fix RK818 ID template
+
+  * Raydium Touchscreen on ThinkPad L390 does not work (LP: #1849721)
+    - HID: i2c-hid: fix no irq after reset on raydium 3118
+
+  * Touchpad doesn't work on Dell Inspiron 7000 2-in-1 (LP: #1851901)
+    - Revert "UBUNTU: SAUCE: mfd: intel-lpss: add quirk for Dell XPS 13 7390
+      2-in-1"
+    - lib: devres: add a helper function for ioremap_uc
+    - mfd: intel-lpss: Use devm_ioremap_uc for MMIO
+
+  * Lenovo dock MAC Address pass through doesn't work in Ubuntu  (LP: #1827961)
+    - r8152: Add macpassthru support for ThinkPad Thunderbolt 3 Dock Gen 2
+
+  * Disable unreliable HPET on CFL-H system (LP: #1852216)
+    - SAUCE: x86/intel: Disable HPET on Intel Coffe Lake H platforms
+
+  * Miscellaneous Ubuntu changes
+    - update dkms package versions
+    - [Config] Enable virtualbox dkms build
+    - [Config] update annotations to match current configs
+    - SAUCE: Add exfat module to signature inclusion list
+
+  * Miscellaneous upstream changes
+    - Bluetooth: Fix invalid-free in bcsp_close()
+    - ath9k_hw: fix uninitialized variable data
+    - ath10k: Fix a NULL-ptr-deref bug in ath10k_usb_alloc_urb_from_pipe
+    - ath10k: Fix HOST capability QMI incompatibility
+    - ath10k: restore QCA9880-AR1A (v1) detection
+    - Revert "Bluetooth: hci_ll: set operational frequency earlier"
+    - Revert "dm crypt: use WQ_HIGHPRI for the IO and crypt workqueues"
+    - md/raid10: prevent access of uninitialized resync_pages offset
+    - x86/insn: Fix awk regexp warnings
+    - x86/speculation: Fix incorrect MDS/TAA mitigation status
+    - x86/speculation: Fix redundant MDS mitigation message
+    - nbd: prevent memory leak
+    - x86/stackframe/32: Repair 32-bit Xen PV
+    - x86/xen/32: Make xen_iret_crit_fixup() independent of frame layout
+    - x86/xen/32: Simplify ring check in xen_iret_crit_fixup()
+    - x86/doublefault/32: Fix stack canaries in the double fault handler
+    - x86/pti/32: Size initial_page_table correctly
+    - x86/cpu_entry_area: Add guard page for entry stack on 32bit
+    - x86/entry/32: Fix IRET exception
+    - x86/entry/32: Use %ss segment where required
+    - x86/entry/32: Move FIXUP_FRAME after pushing %fs in SAVE_ALL
+    - x86/entry/32: Unwind the ESPFIX stack earlier on exception entry
+    - x86/entry/32: Fix NMI vs ESPFIX
+    - selftests/x86/mov_ss_trap: Fix the SYSENTER test
+    - selftests/x86/sigreturn/32: Invalidate DS and ES when abusing the kernel
+    - x86/pti/32: Calculate the various PTI cpu_entry_area sizes correctly, make
+      the CPU_ENTRY_AREA_PAGES assert precise
+    - x86/entry/32: Fix FIXUP_ESPFIX_STACK with user CR3
+    - futex: Prevent robust futex exit race
+    - ALSA: usb-audio: Fix NULL dereference at parsing BADD
+    - ALSA: usb-audio: Fix Scarlett 6i6 Gen 2 port data
+    - media: vivid: Set vid_cap_streaming and vid_out_streaming to true
+    - media: vivid: Fix wrong locking that causes race conditions on streaming
+      stop
+    - media: usbvision: Fix invalid accesses after device disconnect
+    - media: usbvision: Fix races among open, close, and disconnect
+    - cpufreq: Add NULL checks to show() and store() methods of cpufreq
+    - futex: Move futex exit handling into futex code
+    - futex: Replace PF_EXITPIDONE with a state
+    - exit/exec: Seperate mm_release()
+    - futex: Split futex_mm_release() for exit/exec
+    - futex: Set task::futex_state to DEAD right after handling futex exit
+    - futex: Mark the begin of futex exit explicitly
+    - futex: Sanitize exit state handling
+    - futex: Provide state handling for exec() as well
+    - futex: Add mutex around futex exit
+    - futex: Provide distinct return value when owner is exiting
+    - futex: Prevent exit livelock
+    - media: uvcvideo: Fix error path in control parsing failure
+    - media: b2c2-flexcop-usb: add sanity checking
+    - media: cxusb: detect cxusb_ctrl_msg error in query
+    - media: imon: invalid dereference in imon_touch_event
+    - media: mceusb: fix out of bounds read in MCE receiver buffer
+    - ALSA: hda - Disable audio component for legacy Nvidia HDMI codecs
+    - USBIP: add config dependency for SGL_ALLOC
+    - usbip: tools: fix fd leakage in the function of read_attr_usbip_status
+    - usbip: Fix uninitialized symbol 'nents' in stub_recv_cmd_submit()
+    - usb-serial: cp201x: support Mark-10 digital force gauge
+    - USB: chaoskey: fix error case of a timeout
+    - appledisplay: fix error handling in the scheduled work
+    - USB: serial: mos7840: add USB ID to support Moxa UPort 2210
+    - USB: serial: mos7720: fix remote wakeup
+    - USB: serial: mos7840: fix remote wakeup
+    - USB: serial: option: add support for DW5821e with eSIM support
+    - USB: serial: option: add support for Foxconn T77W968 LTE modules
+    - staging: comedi: usbduxfast: usbduxfast_ai_cmdtest rounding error
+    - powerpc/book3s64: Fix link stack flush on context switch
+    - KVM: PPC: Book3S HV: Flush link stack on guest exit to host kernel
+    - Linux 5.4.1
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Fri, 06 Dec 2019 15:53:53 -0600
+
+linux (5.4.0-7.8) focal; urgency=medium
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: selftests/bpf: Comment out BPF_CORE_READ's which cause clang to
+      segfault
+    - Update nvidia-430 to nvidia-440
+    - [Config] Enable nvidia dkms build
+    - update dkms package versions
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v5.4
+
+ -- Andrea Righi <andrea.righi@canonical.com>  Mon, 25 Nov 2019 15:02:30 +0100
+
+linux (5.4.0-6.7) focal; urgency=medium
+
+  * Miscellaneous Ubuntu changes
+    - update dkms package versions
+    - [Config] updateconfigs after rebase to 5.4-rc8
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v5.4-rc7
+
+ -- Andrea Righi <andrea.righi@canonical.com>  Mon, 18 Nov 2019 12:08:01 +0100
+
+linux (5.4.0-5.6) focal; urgency=medium
+
+  * refcount underflow and type confusion in shiftfs (LP: #1850867) //
+    CVE-2019-15793
+    - SAUCE: shiftfs: Correct id translation for lower fs operations
+
+  * refcount underflow and type confusion in shiftfs (LP: #1850867) //
+    CVE-2019-15792
+    - SAUCE: shiftfs: prevent type confusion
+
+  * refcount underflow and type confusion in shiftfs (LP: #1850867) //
+    CVE-2019-15791
+    - SAUCE: shiftfs: Fix refcount underflow in btrfs ioctl handling
+
+  * Some EFI systems fail to boot in efi_init() when booted via maas
+    (LP: #1851810)
+    - SAUCE: efi: efi_get_memory_map -- increase map headroom
+
+  * seccomp: fix SECCOMP_USER_NOTIF_FLAG_CONTINUE test (LP: #1849281)
+    - SAUCE: seccomp: rework define for SECCOMP_USER_NOTIF_FLAG_CONTINUE
+    - SAUCE: seccomp: avoid overflow in implicit constant conversion
+
+  * dkms artifacts may expire from the pool (LP: #1850958)
+    - [Packaging] dkms -- try launchpad librarian for pool downloads
+    - [Packaging] dkms -- dkms-build quieten wget verbiage
+
+  * tsc marked unstable after entered PC10 on Intel CoffeeLake (LP: #1840239)
+    - SAUCE: x86/intel: Disable HPET on Intel Coffe Lake platforms
+    - SAUCE: x86/intel: Disable HPET on Intel Ice Lake platforms
+
+  * shiftfs: prevent exceeding project quotas (LP: #1849483)
+    - SAUCE: shiftfs: drop CAP_SYS_RESOURCE from effective capabilities
+
+  * shiftfs: fix fallocate() (LP: #1849482)
+    - SAUCE: shiftfs: setup correct s_maxbytes limit
+
+  * The alsa hda driver is not loaded due to the missing of PCIID for Comet
+    Lake-S [8086:a3f0] (LP: #1852070)
+    - SAUCE: ALSA: hda: Add Cometlake-S PCI ID
+
+  * Can't adjust brightness on DELL UHD dGPU AIO (LP: #1813877)
+    - SAUCE: platform/x86: dell-uart-backlight: add missing status command
+    - SAUCE: platform/x86: dell-uart-backlight: load driver by scalar status
+    - SAUCE: platform/x86: dell-uart-backlight: add force parameter
+    - SAUCE: platform/x86: dell-uart-backlight: add quirk for old platforms
+
+  * s_iflags overlap prevents unprivileged overlayfs mounts (LP: #1851677)
+    - SAUCE: fs: Move SB_I_NOSUID to the top of s_iflags
+
+  * ubuntu-aufs-modified mmap_region() breaks refcounting in overlayfs/shiftfs
+    error path (LP: #1850994) // CVE-2019-15794
+    - SAUCE: shiftfs: Restore vm_file value when lower fs mmap fails
+    - SAUCE: ovl: Restore vm_file value when lower fs mmap fails
+
+  * Miscellaneous Ubuntu changes
+    - [Debian] Convert update-aufs.sh to use aufs5
+    - SAUCE: import aufs driver
+    - update dkms package versions
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v5.4-rc7
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Wed, 13 Nov 2019 11:56:35 -0800
+
+linux (5.4.0-4.5) focal; urgency=medium
+
+  * High power consumption using 5.0.0-25-generic (LP: #1840835)
+    - PCI: Add a helper to check Power Resource Requirements _PR3 existence
+    - ALSA: hda: Allow HDA to be runtime suspended when dGPU is not bound to a
+      driver
+    - PCI: Fix missing inline for pci_pr3_present()
+
+  * Fix signing of staging modules in eoan (LP: #1850234)
+    - [Packaging] Leave unsigned modules unsigned after adding .gnu_debuglink
+
+  * [20.04 FEAT] Set Architecture Level (ALS) to z13 (LP: #1837525)
+    - [Config] s390x bump march to z13, with tune to z15
+
+  * Miscellaneous Ubuntu changes
+    - [Debian]: do not skip tests for linux-hwe-edge
+    - update dkms package versions
+    - [Config] re-enable zfs
+    - [Config] rename module virtio_fs to virtiofs
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v5.4-rc6
+
+ -- Andrea Righi <andrea.righi@canonical.com>  Mon, 04 Nov 2019 15:12:02 +0100
+
+linux (5.4.0-3.4) focal; urgency=medium
+
+  * seccomp: fix SECCOMP_USER_NOTIF_FLAG_CONTINUE test (LP: #1849281)
+    - SAUCE: seccomp: fix SECCOMP_USER_NOTIF_FLAG_CONTINUE test
+
+  * cloudimg: no iavf/i40evf module so no network available with SR-IOV enabled
+    cloud (LP: #1848481)
+    - [Packaging] include iavf/i40evf in generic
+
+  * CVE-2019-17666
+    - SAUCE: rtlwifi: Fix potential overflow on P2P code
+
+  * Change Config Option CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE for s390x from yes
+    to no (LP: #1848492)
+    - [Config] Change Config Option CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE for s390x
+      from yes to no
+
+  * Add Intel Comet Lake ethernet support (LP: #1848555)
+    - SAUCE: e1000e: Add support for Comet Lake
+
+  * seccomp: add SECCOMP_USER_NOTIF_FLAG_CONTINUE    (LP: #1847744)
+    - SAUCE: seccomp: add SECCOMP_USER_NOTIF_FLAG_CONTINUE
+    - SAUCE: seccomp: test SECCOMP_USER_NOTIF_FLAG_CONTINUE
+
+  * drm/i915: Fix the issue of "azx_get_response timeout" for hdmi audio on ICL
+    platforms (LP: #1847192)
+    - SAUCE: drm/i915: Fix audio power up sequence for gen10+ display
+    - SAUCE: drm/i915: extend audio CDCLK>=2*BCLK constraint to more platforms
+
+  * PM / hibernate: fix potential memory corruption (LP: #1847118)
+    - SAUCE: PM / hibernate: memory_bm_find_bit -- tighten node optimisation
+
+  * [regression] NoNewPrivileges incompatible with Apparmor (LP: #1844186)
+    - SAUCE: apparmor: fix nnp subset test for unconfined
+
+  * overlayfs: allow with shiftfs as underlay (LP: #1846272)
+    - SAUCE: overlayfs: allow with shiftfs as underlay
+
+  * eoan: alsa/sof: Enable SOF_HDA link and codec (LP: #1848490)
+    - [Config] Fix SOF Kconfig options
+
+  * linux won't build when new virtualbox version is present on the archive
+    (LP: #1848788)
+    - [Packaging]: download virtualbox from sources
+
+  * Miscellaneous Ubuntu changes
+    - [Config] update annotations from configs
+    - [Config] updateconfigs after rebase to 5.4-rc5
+    - update dkms package versions
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v5.4-rc5
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Tue, 29 Oct 2019 12:01:27 -0500
+
+linux (5.4.0-2.3) eoan; urgency=medium
+
+  * Add installer support for iwlmvm adapters (LP: #1848236)
+    - d-i: Add iwlmvm to nic-modules
+
+  * shiftfs: rework how shiftfs opens files (LP: #1846265)
+    - SAUCE: shiftfs: rework how shiftfs opens files
+
+  * Miscellaneous Ubuntu changes
+    - update dkms package versions
+    - [Config] updateconfigs after rebase to 5.4-rc4
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v5.4-rc4
+
+ -- Andrea Righi <andrea.righi@canonical.com>  Mon, 21 Oct 2019 17:31:26 +0200
+
+linux (5.4.0-1.2) eoan; urgency=medium
+
+  * Miscellaneous Ubuntu changes
+    - update dkms package versions
+    - [Config] updateconfigs after rebase to 5.4-rc3
+    - [Config] add flexfb, fbtft_device and rio500 to modules.ignore
+    - [Config] amd64: ignore fbtft and all dependent modules
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v5.4-rc3
+
+ -- Andrea Righi <andrea.righi@canonical.com>  Mon, 14 Oct 2019 19:48:52 +0200
+
+linux (5.4.0-0.1) eoan; urgency=medium
+
+  * Enable the Dragonboards out of Eoan/master arm64 kernel (LP: #1846704)
+    - [Packaging] arm64: snapdragon: introduce a snapdragon flavour
+    - [Packaging] arm64: snapdragon: switch kernel format to Image
+    - [Config] arm64: snapdragon: CONFIG_PINCTRL_MSM8916=y
+    - [Config] arm64: snapdragon: CONFIG_PINCTRL_MSM8994=y
+    - [Config] arm64: snapdragon: CONFIG_PINCTRL_MSM8996=y
+    - [Config] arm64: snapdragon: CONFIG_PINCTRL_MSM8998=y
+    - [Config] arm64: snapdragon: CONFIG_REGULATOR_QCOM_RPMH=y
+    - [Config] arm64: snapdragon: CONFIG_QCOM_BAM_DMA=y
+    - [Config] arm64: snapdragon: CONFIG_QCOM_HIDMA_MGMT=y
+    - [Config] arm64: snapdragon: CONFIG_QCOM_HIDMA=y
+    - [Config] arm64: snapdragon: CONFIG_COMMON_CLK_QCOM=y
+    - [Config] arm64: snapdragon: CONFIG_QCOM_CLK_RPMH=y
+    - [Config] arm64: snapdragon: CONFIG_MSM_GCC_8916=y
+    - [Config] arm64: snapdragon: CONFIG_MSM_GCC_8994=y
+    - [Config] arm64: snapdragon: CONFIG_MSM_MMCC_8996=y
+    - [Config] arm64: snapdragon: CONFIG_MSM_GCC_8998=y
+    - [Config] arm64: snapdragon: CONFIG_HWSPINLOCK_QCOM=y
+    - [Config] arm64: snapdragon: CONFIG_QCOM_APCS_IPC=y
+    - [Config] arm64: snapdragon: CONFIG_RPMSG_QCOM_GLINK_RPM=y
+    - [Config] arm64: snapdragon: CONFIG_QCOM_GENI_SE=y
+    - [Config] arm64: snapdragon: CONFIG_QCOM_SMEM=y
+    - [Config] arm64: snapdragon: CONFIG_QCOM_SMD_RPM=y
+    - [Config] arm64: snapdragon: CONFIG_QCOM_SMP2P=y
+    - [Config] arm64: snapdragon: CONFIG_QCOM_SMSM=y
+    - [Config] arm64: snapdragon: CONFIG_QCOM_QFPROM=y
+    - [Config] arm64: snapdragon: CONFIG_SERIAL_QCOM_GENI=y
+    - [Config] arm64: snapdragon: CONFIG_QCOM_TSENS=y
+    - [Config] arm64: snapdragon: CONFIG_REGULATOR_QCOM_SMD_RPM=y
+    - [Config] arm64: snapdragon: CONFIG_QCOM_CLK_SMD_RPM=y
+    - [Config] arm64: snapdragon: CONFIG_RPMSG_QCOM_SMD=y
+    - [Config] arm64: snapdragon: CONFIG_MFD_QCOM_RPM=y
+    - [Config] arm64: snapdragon: CONFIG_SCSI_UFSHCD=y
+    - [Config] arm64: snapdragon: CONFIG_SCSI_UFSHCD_PLATFORM=y
+    - [Config] arm64: snapdragon: CONFIG_SCSI_UFS_HISI=y
+    - [Config] arm64: snapdragon: CONFIG_MMC_SDHCI=y
+    - [Config] arm64: snapdragon: CONFIG_MMC_SDHCI_PLTFM=y
+    - [Config] arm64: snapdragon: CONFIG_MMC_SDHCI_MSM=y
+    - [Config] arm64: snapdragon: CONFIG_REGULATOR_QCOM_SPMI=y
+    - [Config] arm64: snapdragon: CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
+    - [Config] arm64: snapdragon: CONFIG_PHY_QCOM_USB_HS=y
+    - [Config] arm64: snapdragon: CONFIG_PHY_QCOM_QMP=y
+    - [Config] arm64: snapdragon: CONFIG_PHY_QCOM_UFS=y
+    - [Config] arm64: snapdragon: CONFIG_PHY_QCOM_USB_HSIC=y
+    - [Config] arm64: snapdragon: CONFIG_USB_CHIPIDEA_OF=y
+    - [Config] arm64: snapdragon: CONFIG_USB_EHCI_HCD_PLATFORM=y
+    - [Config] arm64: snapdragon: CONFIG_EXTCON_USB_GPIO=y
+    - [Config] arm64: snapdragon: CONFIG_REGULATOR_FIXED_VOLTAGE=y
+    - [Config] arm64: snapdragon: CONFIG_LEDS_GPIO=y
+    - [Config] arm64: snapdragon: CONFIG_USB_HSIC_USB3503=y
+    - [Config] arm64: snapdragon: CONFIG_USB_NET_DRIVERS=y
+    - [Config] arm64: snapdragon: CONFIG_USB_OTG=y
+    - [Config] arm64: snapdragon: CONFIG_USB_XHCI_PLATFORM=y
+    - [Config] arm64: snapdragon: CONFIG_USB_OHCI_HCD_PLATFORM=y
+    - [Config] arm64: snapdragon: CONFIG_USB_MUSB_HDRC=y
+    - [Config] arm64: snapdragon: CONFIG_USB_DWC3=y
+    - [Config] arm64: snapdragon: CONFIG_USB_DWC3_PCI=y
+    - [Config] arm64: snapdragon: CONFIG_USB_DWC3_OF_SIMPLE=y
+    - [Config] arm64: snapdragon: CONFIG_USB_DWC3_QCOM=y
+    - [Config] arm64: snapdragon: CONFIG_LEDS_PWM=y
+    - [Config] arm64: snapdragon: CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+    - [Config] arm64: snapdragon: CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+    - [Config] arm64: snapdragon: CONFIG_QCOM_A53PLL=y
+    - [Config] arm64: snapdragon: CONFIG_QCOM_CLK_APCS_MSM8916=y
+    - [Config] arm64: snapdragon: CONFIG_NLS_ISO8859_1=y
+    - [Config] arm64: snapdragon: CONFIG_USB_USBNET=y
+    - [Config] arm64: snapdragon: CONFIG_CRYPTO_DEV_QCOM_RNG=y
+    - [Config] arm64: snapdragon: CONFIG_POWER_RESET_QCOM_PON=y
+    - [Config] arm64: snapdragon: CONFIG_INPUT_PM8941_PWRKEY=y
+    - [Config] arm64: snapdragon: CONFIG_KEYBOARD_GPIO=y
+    - [Config] arm64: snapdragon: CONFIG_RTC_DRV_PM8XXX=y
+
+  * Miscellaneous Ubuntu changes
+    - [Config] updateconfigs after rebase to 5.4-rc2
+    - SAUCE: (lockdown) Make get_cert_list() not complain about cert lists that
+      aren't present.
+    - SAUCE: (lockdown) Add efi_status_to_str() and rework efi_status_to_err().
+    - SAUCE: (lockdown) Make get_cert_list() use efi_status_to_str() to print
+      error messages.
+    - SAUCE: (lockdown) security: lockdown: expose a hook to lock the kernel down
+    - SAUCE: (lockdown) efi: Add an EFI_SECURE_BOOT flag to indicate secure boot
+      mode
+    - SAUCE: (lockdown) efi: Lock down the kernel if booted in secure boot mode
+    - SAUCE: (lockdown) Add a SysRq option to lift kernel lockdown
+    - SAUCE: (lockdown) KEYS: Make use of platform keyring for module signature
+      verify
+    - SAUCE: (lockdown) arm64: Allow locking down the kernel under EFI secure boot
+    - SAUCE: (lockdown) security: lockdown: Make
+      CONFIG_LOCK_DOWN_IN_EFI_SECURE_BOOT more generic
+    - SAUCE: (lockdown) s390/ipl: lockdown kernel when booted secure
+    - [Config] Enable lockdown under secure boot
+    - SAUCE: import aufs driver
+    - SAUCE: aufs: rwsem owner changed to atmoic_long_t in 5.3
+    - SAUCE: aufs: add "WITH Linux-syscall-note" to SPDX tag of uapi headers
+    - [Config] enable aufs
+    - update dkms package versions
+    - [Config] disable zfs
+    - [Config] disable nvidia dkms build
+    - [Config] disable virtualbox dkms build
+    - [Debian] Generate stub reconstruct for -rc kernels
+    - Revert "UBUNTU: SAUCE: (namespace) block_dev: Forbid unprivileged mounting
+      when device is opened for writing"
+    - Revert "UBUNTU: SAUCE: (namespace) ext4: Add module parameter to enable user
+      namespace mounts"
+    - Revert "UBUNTU: SAUCE: (namespace) ext4: Add support for unprivileged mounts
+      from user namespaces"
+    - Revert "UBUNTU: SAUCE: (namespace) mtd: Check permissions towards mtd block
+      device inode when mounting"
+    - Revert "UBUNTU: SAUCE: (namespace) block_dev: Check permissions towards
+      block device inode when mounting"
+    - Revert "UBUNTU: SAUCE: (namespace) block_dev: Support checking inode
+      permissions in lookup_bdev()"
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v5.4-rc2
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Fri, 11 Oct 2019 16:42:41 -0500
+
+linux (5.4.0-0.0) eoan; urgency=medium
+
+  * Dummy entry.
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Tue, 08 Oct 2019 09:59:00 -0500
+
+linux (5.3.0-17.18) eoan; urgency=medium
+
+  * eoan/linux: 5.3.0-17.18 -proposed tracker (LP: #1846641)
+
+  * CVE-2019-17056
+    - nfc: enforce CAP_NET_RAW for raw sockets
+
+  * CVE-2019-17055
+    - mISDN: enforce CAP_NET_RAW for raw sockets
+
+  * CVE-2019-17054
+    - appletalk: enforce CAP_NET_RAW for raw sockets
+
+  * CVE-2019-17053
+    - ieee802154: enforce CAP_NET_RAW for raw sockets
+
+  * CVE-2019-17052
+    - ax25: enforce CAP_NET_RAW for raw sockets
+
+  * CVE-2019-15098
+    - ath6kl: fix a NULL-ptr-deref bug in ath6kl_usb_alloc_urb_from_pipe()
+
+  * xHCI on AMD Stoney Ridge cannot detect USB 2.0 or 1.1 devices.
+    (LP: #1846470)
+    - x86/PCI: Avoid AMD FCH XHCI USB PME# from D0 defect
+
+  * Re-enable linux-libc-dev build on i386 (LP: #1846508)
+    - [Packaging] Build only linux-libc-dev for i386
+    - [Debian] final-checks -- ignore archtictures with no binaries
+
+  * arm64: loop on boot after installing linux-generic-hwe-18.04-edge/bionic-
+    proposed (LP: #1845820)
+    - [Config] Disable CONFIG_ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT
+
+  * Revert ESE DASD discard support (LP: #1846219)
+    - SAUCE: Revert "s390/dasd: Add discard support for ESE volumes"
+
+  * Miscellaneous Ubuntu changes
+    - update dkms package versions
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Thu, 03 Oct 2019 16:57:05 -0500
+
+linux (5.3.0-16.17) eoan; urgency=medium
+
+  * eoan/linux: 5.3.0-16.17 -proposed tracker (LP: #1846204)
+
+  * zfs fails to build on s390x  with debug symbols enabled (LP: #1846143)
+    - SAUCE: s390: Mark atomic const ops always inline
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Tue, 01 Oct 2019 07:46:43 -0500
+
+linux (5.3.0-15.16) eoan; urgency=medium
+
+  * eoan/linux: 5.3.0-15.16 -proposed tracker (LP: #1845987)
+
+  * Drop i386 build for 19.10 (LP: #1845714)
+    - [Packaging] Remove x32 arch references from control files
+    - [Debian] final-checks -- Get arch list from debian/control
+
+  * ZFS kernel modules lack debug symbols (LP: #1840704)
+    - [Debian] Fix conditional for setting zfs debug package path
+
+  * Use pyhon3-sphinx instead of python-sphinx for building html docs
+    (LP: #1845808)
+    - [Packaging] Update sphinx build dependencies to python3 packages
+
+  * Kernel panic with 19.10 beta image (LP: #1845454)
+    - efi/tpm: Don't access event->count when it isn't mapped.
+    - efi/tpm: don't traverse an event log with no events
+    - efi/tpm: only set efi_tpm_final_log_size after successful event log parsing
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 30 Sep 2019 11:57:20 -0500
+
+linux (5.3.0-14.15) eoan; urgency=medium
+
+  * eoan/linux: 5.3.0-14.15 -proposed tracker (LP: #1845728)
+
+  * Drop i386 build for 19.10 (LP: #1845714)
+    - [Debian] Remove support for producing i386 kernels
+    - [Debian] Don't use CROSS_COMPILE for i386 configs
+
+  * udevadm trigger will fail when trying to add /sys/devices/vio/
+    (LP: #1845572)
+    - SAUCE: powerpc/vio: drop bus_type from parent device
+
+  * Trying to online dasd drive results in invalid input/output from the kernel
+    on z/VM (LP: #1845323)
+    - SAUCE: s390/dasd: Fix error handling during online processing
+
+  * intel-lpss driver conflicts with write-combining MTRR region (LP: #1845584)
+    - SAUCE: mfd: intel-lpss: add quirk for Dell XPS 13 7390 2-in-1
+
+  * Support Hi1620 zip hw accelerator (LP: #1845355)
+    - [Config] Enable HiSilicon QM/ZIP as modules
+    - crypto: hisilicon - add queue management driver for HiSilicon QM module
+    - crypto: hisilicon - add hardware SGL support
+    - crypto: hisilicon - add HiSilicon ZIP accelerator support
+    - crypto: hisilicon - add SRIOV support for ZIP
+    - Documentation: Add debugfs doc for hisi_zip
+    - crypto: hisilicon - add debugfs for ZIP and QM
+    - MAINTAINERS: add maintainer for HiSilicon QM and ZIP controller driver
+    - crypto: hisilicon - fix kbuild warnings
+    - crypto: hisilicon - add dependency for CRYPTO_DEV_HISI_ZIP
+    - crypto: hisilicon - init curr_sgl_dma to fix compile warning
+    - crypto: hisilicon - add missing single_release
+    - crypto: hisilicon - fix error handle in hisi_zip_create_req_q
+    - crypto: hisilicon - Fix warning on printing %p with dma_addr_t
+    - crypto: hisilicon - Fix return value check in hisi_zip_acompress()
+    - crypto: hisilicon - avoid unused function warning
+
+  * SafeSetID LSM should be built but disabled by default (LP: #1845391)
+    - LSM: SafeSetID: Stop releasing uninitialized ruleset
+    - [Config] Build SafeSetID LSM but don't enable it by default
+
+  * CONFIG_LSM should not specify loadpin since it is not built (LP: #1845383)
+    - [Config] loadpin shouldn't be in CONFIG_LSM
+
+  * Add new pci-id's for CML-S, ICL (LP: #1845317)
+    - drm/i915/icl: Add missing device ID
+    - drm/i915/cml: Add Missing PCI IDs
+
+  * Thunderbolt support for ICL (LP: #1844680)
+    - thunderbolt: Correct path indices for PCIe tunnel
+    - thunderbolt: Move NVM upgrade support flag to struct icm
+    - thunderbolt: Use 32-bit writes when writing ring producer/consumer
+    - thunderbolt: Do not fail adding switch if some port is not implemented
+    - thunderbolt: Hide switch attributes that are not set
+    - thunderbolt: Expose active parts of NVM even if upgrade is not supported
+    - thunderbolt: Add support for Intel Ice Lake
+    - ACPI / property: Add two new Thunderbolt property GUIDs to the list
+
+  * Ubuntu 19.10 -  Additional PCI patch and fix (LP: #1844668)
+    - s390/pci: fix MSI message data
+
+  * Enhanced Hardware Support - Finalize Naming (LP: #1842774)
+    - s390: add support for IBM z15 machines
+    - [Config] CONFIG_MARCH_Z15=n, CONFIG_TUNE_Z15=n
+
+  * Eoan update: v5.3.1 upstream stable release (LP: #1845642)
+    - USB: usbcore: Fix slab-out-of-bounds bug during device reset
+    - media: tm6000: double free if usb disconnect while streaming
+    - phy: renesas: rcar-gen3-usb2: Disable clearing VBUS in over-current
+    - ip6_gre: fix a dst leak in ip6erspan_tunnel_xmit
+    - net/sched: fix race between deactivation and dequeue for NOLOCK qdisc
+    - net_sched: let qdisc_put() accept NULL pointer
+    - udp: correct reuseport selection with connected sockets
+    - xen-netfront: do not assume sk_buff_head list is empty in error handling
+    - net: dsa: Fix load order between DSA drivers and taggers
+    - net: stmmac: Hold rtnl lock in suspend/resume callbacks
+    - KVM: coalesced_mmio: add bounds checking
+    - Documentation: sphinx: Add missing comma to list of strings
+    - firmware: google: check if size is valid when decoding VPD data
+    - serial: sprd: correct the wrong sequence of arguments
+    - tty/serial: atmel: reschedule TX after RX was started
+    - nl80211: Fix possible Spectre-v1 for CQM RSSI thresholds
+    - Revert "arm64: Remove unnecessary ISBs from set_{pte,pmd,pud}"
+    - ovl: fix regression caused by overlapping layers detection
+    - phy: qcom-qmp: Correct ready status, again
+    - floppy: fix usercopy direction
+    - media: technisat-usb2: break out of loop at end of buffer
+    - Linux 5.3.1
+
+  * ZFS kernel modules lack debug symbols (LP: #1840704)
+    - [Debian]: Remove hardcoded $(pkgdir) in debug symbols handling
+    - [Debian]: Handle debug symbols for modules in extras too
+    - [Debian]: Check/link modules with debug symbols after DKMS modules
+    - [Debian]: Warn about modules without debug symbols
+    - [Debian]: dkms-build: new parameter for debug package directory
+    - [Debian]: dkms-build: zfs: support for debug symbols
+    - [Debian]: dkms-build: Avoid executing post-processor scripts twice
+    - [Debian]: dkms-build: Move zfs special-casing into configure script
+
+  * /proc/self/maps paths missing on live session (was vlc won't start; eoan
+    19.10 & bionic 18.04 ubuntu/lubuntu/kubuntu/xubuntu/ubuntu-mate dailies)
+    (LP: #1842382)
+    - SAUCE: Revert "UBUNTU: SAUCE: shiftfs: enable overlayfs on shiftfs"
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Fri, 27 Sep 2019 16:08:06 -0500
+
+linux (5.3.0-13.14) eoan; urgency=medium
+
+  * eoan/linux: 5.3.0-13.14 -proposed tracker (LP: #1845105)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update helper scripts
+
+  * Miscellaneous Ubuntu changes
+    - [Debian] Remove binutils-dev build dependency
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 23 Sep 2019 19:26:43 -0500
+
+linux (5.3.0-12.13) eoan; urgency=medium
+
+  * Change kernel compression method to improve boot speed (LP: #1840934)
+    - [Packaging] Add lz4 build dependency for s390x
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: Remove spl and zfs source
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Tue, 17 Sep 2019 13:36:26 +0200
+
+linux (5.3.0-11.12) eoan; urgency=medium
+
+  * eoan/linux: 5.3.0-11.12 -proposed tracker (LP: #1844144)
+
+  *  Suspend to RAM(S3) does not wake up for latest megaraid and mpt3sas
+    adapters(SAS3.5 onwards) (LP: #1838751)
+    - PCI: Restore Resizable BAR size bits correctly for 1MB BARs
+
+  * s390/setup: Actually init kernel lock down (LP: #1843961)
+    - SAUCE: (lockdown) s390/setup: Actually init kernel lock down
+
+  * cherrypick has_sipl fix (LP: #1843960)
+    - SAUCE: s390/sclp: Fix bit checked for has_sipl
+
+  * Change kernel compression method to improve boot speed (LP: #1840934)
+    - [Config]: Switch kernel compression from LZO to LZ4 on s390x
+
+  * Installation fails on eoan/PowerVM : missing /dev/nvram (LP: #1837726)
+    - [Config] CONFIG_NVRAM=y for ppc64el
+
+  * Miscellaneous Ubuntu changes
+    - [Config]: remove nvram from ppc64el modules ABI
+    - [Config] Update annotations for recent config changes
+    - SAUCE: sched: Add __ASSEMBLY__ guards around struct clone_args
+    - SAUCE: i2c: qcom-geni: Disable DMA processing on the Lenovo Yoga C630
+    - SAUCE: arm64: dts: qcom: Add Lenovo Yoga C630
+    - update dkms package versions
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v5.3
+
+ -- Paolo Pisati <paolo.pisati@canonical.com>  Mon, 16 Sep 2019 16:18:27 +0200
+
+linux (5.3.0-10.11) eoan; urgency=medium
+
+  * eoan/linux: 5.3.0-10.11 -proposed tracker (LP: #1843232)
+
+  * No sound inputs from the external microphone and headset on a Dell machine
+    (LP: #1842265)
+    - SAUCE: ALSA: hda - Expand pin_match function to match upcoming new tbls
+    - SAUCE: ALSA: hda - Define a fallback_pin_fixup_tbl for alc269 family
+
+  * Horizontal corrupted line at top of screen caused by framebuffer compression
+    (LP: #1840236)
+    - SAUCE: drm/i915/fbc: disable framebuffer compression on IceLake
+
+  * Add bpftool to linux-tools-common (LP: #1774815)
+    - [Debian] package bpftool in linux-tools-common
+
+  * Miscellaneous Ubuntu changes
+    - update dkms package versions
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v5.3-rc8
+
+ -- Paolo Pisati <paolo.pisati@canonical.com>  Mon, 09 Sep 2019 10:00:41 +0200
+
+linux (5.3.0-9.10) eoan; urgency=medium
+
+  * eoan/linux: 5.3.0-9.10 -proposed tracker (LP: #1842393)
+
+  * shiftfs: mark kmem_cache as reclaimable (LP: #1842059)
+    - SAUCE: shiftfs: mark slab objects SLAB_RECLAIM_ACCOUNT
+
+  * shiftfs: drop entries from cache on unlink (LP: #1841977)
+    - SAUCE: shiftfs: fix buggy unlink logic
+
+  * Fix touchpad IRQ storm after S3 (LP: #1841396)
+    - pinctrl: intel: remap the pin number to gpio offset for irq enabled pin
+
+  * Please include DTBs for arm64 laptops (LP: #1842050)
+    - arm64: dts: qcom: Add Lenovo Miix 630
+    - arm64: dts: qcom: Add HP Envy x2
+    - arm64: dts: qcom: Add Asus NovaGo TP370QL
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: import aufs driver
+    - [Packaging]: ignore vbox modules when vbox is disabled
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v5.3-rc7
+
+ -- Paolo Pisati <paolo.pisati@canonical.com>  Tue, 03 Sep 2019 10:27:33 +0200
+
+linux (5.3.0-8.9) eoan; urgency=medium
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync getabis
+
+  * Change kernel compression method to improve boot speed (LP: #1840934)
+    - [Config] change kernel compression method to improve boot speed
+    - [Packaging] add build dependencies for compression algorithms
+
+  * realtek r8822be kernel module fails after update to linux kernel-headers
+    5.0.0-21 (LP: #1838133)
+    - rtw88: Fix misuse of GENMASK macro
+    - rtw88: pci: Rearrange the memory usage for skb in RX ISR
+    - rtw88: pci: Use DMA sync instead of remapping in RX ISR
+    - rtw88: debug: dump tx power indexes in use
+    - rtw88: use txpwr_lmt_cfg_pair struct, not arrays
+    - rtw88: pci: remove set but not used variable 'ip_sel'
+    - rtw88: allow c2h operation in irq context
+    - rtw88: enclose c2h cmd handle with mutex
+    - rtw88: add BT co-existence support
+    - SAUCE: rtw88: pci: enable MSI interrupt
+
+  * VIMC module not available (CONFIG_VIDEO_VIMC not set) (LP: #1831482)
+    - [Config] Enable VIMC module
+
+  * Goodix touchpad may drop first input event (LP: #1840075)
+    - Revert "UBUNTU: SAUCE: i2c: designware: add G3 3590 into i2c quirk"
+    - Revert "UBUNTU: SAUCE: i2c: designware: add Inpiron 7591 into i2c quirk"
+    - Revert "UBUNTU: SAUCE: i2c: designware: add Inpiron/Vostro 7590 into i2c
+      quirk"
+    - Revert "UBUNTU: SAUCE: i2c: designware: Add disable runtime pm quirk"
+    - mfd: intel-lpss: Remove D3cold delay
+
+  * Include Sunix serial/parallel driver (LP: #1826716)
+    - serial: 8250_pci: Add support for Sunix serial boards
+    - parport: parport_serial: Add support for Sunix Multi I/O boards
+
+  * enable lockdown on s390x when Secure IPL is performed (LP: #1839622)
+    - SAUCE: (lockdown) s390/ipl: lockdown kernel when booted secure
+    - Ubuntu: [Config] Enable CONFIG_LOCK_DOWN_KERNEL on s390x.
+
+  * UBUNTU: SAUCE: shiftfs: pass correct point down (LP: #1837231)
+    - SAUCE: shiftfs: pass correct point down
+
+  * shiftfs: add O_DIRECT support (LP: #1837223)
+    - SAUCE: shiftfs: add O_DIRECT support
+
+  * Miscellaneous Ubuntu changes
+    - [Config] enable secureboot signing on s390x
+    - [Config] CONFIG_TEST_BLACKHOLE_DEV=m
+    - SAUCE: selftests: fib_tests: assign address to dummy1 for rp_filter tests
+    - [Debian] disable dkms builds for autopktest rebuilds
+    - update dkms package versions
+    - [Config] updateconfigs after v5.3-rc6 rebase
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v5.3-rc5
+
+ -- Paolo Pisati <paolo.pisati@canonical.com>  Mon, 26 Aug 2019 10:09:42 +0200
+
+linux (5.3.0-7.8) eoan; urgency=medium
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync getabis
+
+  * Miscellaneous Ubuntu changes
+    - [Config] updateconfigs after v5.3-rc5 rebase
+    - remove missing module after updateconfigs
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v5.3-rc5
+
+ -- Paolo Pisati <paolo.pisati@canonical.com>  Mon, 19 Aug 2019 15:31:24 +0200
+
+linux (5.3.0-6.7) eoan; urgency=medium
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: selftests/bpf: prevent headers to be compiled as C code
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Wed, 14 Aug 2019 13:25:01 -0500
+
+linux (5.3.0-5.6) eoan; urgency=medium
+
+  * Miscellaneous Ubuntu changes
+    - update dkms package versions
+    - [Config] enable zfs build
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Tue, 13 Aug 2019 09:16:06 -0500
+
+linux (5.3.0-4.5) eoan; urgency=medium
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync getabis
+    - [Packaging] update helper scripts
+
+  * bcache: bch_allocator_thread(): hung task timeout (LP: #1784665) // Tight
+    timeout for bcache removal causes spurious failures (LP: #1796292)
+    - SAUCE: bcache: fix deadlock in bcache_allocator
+
+  * shiftfs: allow overlayfs (LP: #1838677)
+    - SAUCE: shiftfs: enable overlayfs on shiftfs
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: Revert "kbuild: modpost: do not parse unnecessary rules for vmlinux
+      modpost"
+    - update dkms package versions
+    - enable nvidia dkms build
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v5.3-rc4
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 12 Aug 2019 10:41:27 -0500
+
+linux (5.3.0-3.4) eoan; urgency=medium
+
+  * Miscellaneous Ubuntu changes
+    - update dkms package versions
+    - SAUCE: aufs: add "WITH Linux-syscall-note" to SPDX tag of uapi headers
+    - [Config] add mux-* to modules.ignore
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v5.3-rc3
+
+ -- Paolo Pisati <paolo.pisati@canonical.com>  Mon, 05 Aug 2019 18:17:09 +0200
+
+linux (5.3.0-2.3) eoan; urgency=medium
+
+  * Miscellaneous Ubuntu changes
+    - [Packaging] add build dependincy on fontconfig
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 29 Jul 2019 12:18:46 -0400
+
+linux (5.3.0-1.2) eoan; urgency=medium
+
+  * System does not auto detect disconnection of external monitor (LP: #1835001)
+    - SAUCE: drm/i915: Add support for retrying hotplug
+    - SAUCE: drm/i915: Enable hotplug retry
+
+  * Please enable CONFIG_SCSI_UFS_QCOM as a module on arm64 (LP: #1837332)
+    - [Config] Enable CONFIG_SCSI_UFS_QCOM as a module on arm64.
+
+  * Add arm64 CONFIG_ARCH_MESON=y and related configs Edit (LP: #1820530)
+    - [Config] enable ARCH_MESON
+    - remove missing module
+    - [Config] update annotations after enabling ARCH_MESON for arm64
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: KVM: PPC: comment implicit fallthrough
+    - update dkms package versions
+    - [Config] enable vbox dkms build
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v5.3-rc2
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Sun, 28 Jul 2019 23:10:16 -0400
+
+linux (5.3.0-0.1) eoan; urgency=medium
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync git-ubuntu-log
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: (efi-lockdown) Add the ability to lock down access to the running
+      kernel image
+    - SAUCE: (efi-lockdown) Enforce module signatures if the kernel is locked down
+    - SAUCE: (efi-lockdown) Restrict /dev/{mem,kmem,port} when the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) kexec_load: Disable at runtime if the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) Copy secure_boot flag in boot params across kexec
+      reboot
+    - SAUCE: (efi-lockdown) kexec_file: split KEXEC_VERIFY_SIG into KEXEC_SIG and
+      KEXEC_SIG_FORCE
+    - SAUCE: (efi-lockdown) kexec_file: Restrict at runtime if the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) hibernate: Disable when the kernel is locked down
+    - SAUCE: (efi-lockdown) uswsusp: Disable when the kernel is locked down
+    - SAUCE: (efi-lockdown) PCI: Lock down BAR access when the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) x86: Lock down IO port access when the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) x86/msr: Restrict MSR access when the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) ACPI: Limit access to custom_method when the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) acpi: Ignore acpi_rsdp kernel param when the kernel
+      has been locked down
+    - SAUCE: (efi-lockdown) acpi: Disable ACPI table override if the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) acpi: Disable APEI error injection if the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) Prohibit PCMCIA CIS storage when the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) Lock down TIOCSSERIAL
+    - SAUCE: (efi-lockdown) Lock down module params that specify hardware
+      parameters (eg. ioport)
+    - SAUCE: (efi-lockdown) x86/mmiotrace: Lock down the testmmiotrace module
+    - SAUCE: (efi-lockdown) Lock down /proc/kcore
+    - SAUCE: (efi-lockdown) Lock down kprobes
+    - SAUCE: (efi-lockdown) bpf: Restrict kernel image access functions when the
+      kernel is locked down
+    - SAUCE: (efi-lockdown) Lock down perf
+    - SAUCE: (efi-lockdown) debugfs: Restrict debugfs when the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) lockdown: Print current->comm in restriction messages
+    - SAUCE: (efi-lockdown) kexec: Allow kexec_file() with appropriate IMA policy
+      when locked down
+    - SAUCE: (efi-lockdown) Add a SysRq option to lift kernel lockdown
+    - SAUCE: (efi-lockdown) debugfs: avoid EPERM when no open file operation
+      defined
+    - SAUCE: (efi-lockdown) Make get_cert_list() not complain about cert lists
+      that aren't present.
+    - SAUCE: (efi-lockdown) Add efi_status_to_str() and rework
+      efi_status_to_err().
+    - SAUCE: (efi-lockdown) Make get_cert_list() use efi_status_to_str() to print
+      error messages.
+    - SAUCE: (efi-lockdown) efi: Add an EFI_SECURE_BOOT flag to indicate secure
+      boot mode
+    - SAUCE: (efi-lockdown) efi: Lock down the kernel if booted in secure boot
+      mode
+    - SAUCE: (efi-lockdown) KEYS: Make use of platform keyring for module
+      signature verify
+    - SAUCE: (efi-lockdown) efi: Sanitize boot_params in efi stub
+    - SAUCE: (efi-lockdown) furter KEXEC_VERIFY_SIG -> KEXEC_SIG updates
+    - SAUCE: (efi-lockdown) arm64: add kernel config option to lock down when in
+      Secure Boot mode
+    - SAUCE: import aufs driver
+    - SAUCE: aufs: rwsem owner changed to atmoic_long_t in 5.3
+    - [Config] disable zfs dkms build
+    - [Config] disable nvidia dkms build
+    - [Config] disable vbox dkms build
+    - SAUCE: perf diff: use llabs for s64 vaules
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v5.3-rc1
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Tue, 23 Jul 2019 21:45:44 -0500
+
+linux (5.3.0-0.0) eoan; urgency=medium
+
+  * Dummy entry.
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 22 Jul 2019 10:19:04 -0500
+
+linux (5.2.0-9.10) eoan; urgency=medium
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update helper scripts
+
+  * input/mouse: alps trackpoint-only device doesn't work (LP: #1836752)
+    - SAUCE: Input: alps - don't handle ALPS cs19 trackpoint-only device
+    - SAUCE: Input: alps - fix a mismatch between a condition check and its
+      comment
+
+  * System does not auto detect disconnection of external monitor (LP: #1835001)
+    - SAUCE: drm/i915: Add support for retrying hotplug
+    - SAUCE: drm/i915: Enable hotplug retry
+
+  * alsa/hdmi: add icelake hdmi audio support for a Dell machine (LP: #1836916)
+    - SAUCE: ALSA: hda/hdmi - Remove duplicated define
+    - SAUCE: ALSA: hda/hdmi - Fix i915 reverse port/pin mapping
+
+  * First click on Goodix touchpad doesn't be recognized after runtime suspended
+    (LP: #1836836)
+    - SAUCE: i2c: designware: add G3 3590 into i2c quirk
+
+  * ixgbe{vf} - Physical Function gets IRQ when VF checks link state
+    (LP: #1836760)
+    - ixgbevf: Use cached link state instead of re-reading the value for ethtool
+
+  * Doing multiple squashfs (and other loop?) mounts in parallel breaks
+    (LP: #1836914)
+    - SAUCE: Revert "loop: Don't change loop device under exclusive opener"
+
+  * hibmc-drm Causes Unreadable Display for Huawei amd64 Servers (LP: #1762940)
+    - SAUCE: Make CONFIG_DRM_HISI_HIBMC depend on ARM64
+    - [Config] Set CONFIG_DRM_HISI_HIBMC to arm64 only
+    - [Config] add hibmc-drm to modules.ignore
+
+  * hda/realtek: can't detect external mic on a Dell machine (LP: #1836755)
+    - ALSA: hda/realtek: apply ALC891 headset fixup to one Dell machine
+
+  * Enable Armada SOCs and MVPP2 NIC driver for disco/generic arm64
+    (LP: #1835054)
+    - [Config] Enable Armada SOCs and MVPP2 NIC driver for disco/generic arm64
+
+  * Unhide Nvidia HDA audio controller (LP: #1836308)
+    - PCI: Enable NVIDIA HDA controllers
+
+  * Intel ethernet I219 may wrongly detect connection speed as 10Mbps
+    (LP: #1836177)
+    - e1000e: Make watchdog use delayed work
+
+  * Sometimes touchpad(goodix) can't use tap function (LP: #1836020)
+    - SAUCE: i2c: designware: add Inpiron/Vostro 7590 into i2c quirk
+    - SAUCE: i2c: designware: add Inpiron 7591 into i2c quirk
+
+  * Intel ethernet I219 has slow RX speed (LP: #1836152)
+    - e1000e: add workaround for possible stalled packet
+    - e1000e: disable force K1-off feature
+
+  * bcache: risk of data loss on I/O errors in backing or caching devices
+    (LP: #1829563)
+    - Revert "bcache: set CACHE_SET_IO_DISABLE in bch_cached_dev_error()"
+
+  * bnx2x driver causes 100% CPU load (LP: #1832082)
+    - bnx2x: Prevent ptp_task to be rescheduled indefinitely
+
+  * fcf-protection=none patch with new version
+    - Revert "UBUNTU: SAUCE: kbuild: add -fcf-protection=none to retpoline flags"
+    - SAUCE: kbuild: add -fcf-protection=none when using retpoline flags
+
+  * CVE-2019-12614
+    - powerpc/pseries/dlpar: Fix a missing check in dlpar_parse_cc_property()
+
+  * Eoan update: v5.2.1 upstream stable release (LP: #1836622)
+    - crypto: lrw - use correct alignmask
+    - crypto: talitos - rename alternative AEAD algos.
+    - fscrypt: don't set policy for a dead directory
+    - udf: Fix incorrect final NOT_ALLOCATED (hole) extent length
+    - media: stv0297: fix frequency range limit
+    - ALSA: usb-audio: Fix parse of UAC2 Extension Units
+    - ALSA: hda/realtek - Headphone Mic can't record after S3
+    - tpm: Actually fail on TPM errors during "get random"
+    - tpm: Fix TPM 1.2 Shutdown sequence to prevent future TPM operations
+    - block: fix .bi_size overflow
+    - block, bfq: NULL out the bic when it's no longer valid
+    - perf intel-pt: Fix itrace defaults for perf script
+    - perf auxtrace: Fix itrace defaults for perf script
+    - perf intel-pt: Fix itrace defaults for perf script intel-pt documentation
+    - perf pmu: Fix uncore PMU alias list for ARM64
+    - perf thread-stack: Fix thread stack return from kernel for kernel-only case
+    - perf header: Assign proper ff->ph in perf_event__synthesize_features()
+    - x86/ptrace: Fix possible spectre-v1 in ptrace_get_debugreg()
+    - x86/tls: Fix possible spectre-v1 in do_get_thread_area()
+    - Documentation: Add section about CPU vulnerabilities for Spectre
+    - Documentation/admin: Remove the vsyscall=native documentation
+    - mwifiex: Don't abort on small, spec-compliant vendor IEs
+    - USB: serial: ftdi_sio: add ID for isodebug v1
+    - USB: serial: option: add support for GosunCn ME3630 RNDIS mode
+    - Revert "serial: 8250: Don't service RX FIFO if interrupts are disabled"
+    - p54usb: Fix race between disconnect and firmware loading
+    - usb: gadget: f_fs: data_len used before properly set
+    - usb: gadget: ether: Fix race between gether_disconnect and rx_submit
+    - usb: dwc2: use a longer AHB idle timeout in dwc2_core_reset()
+    - usb: renesas_usbhs: add a workaround for a race condition of workqueue
+    - drivers/usb/typec/tps6598x.c: fix portinfo width
+    - drivers/usb/typec/tps6598x.c: fix 4CC cmd write
+    - p54: fix crash during initialization
+    - staging: comedi: dt282x: fix a null pointer deref on interrupt
+    - staging: wilc1000: fix error path cleanup in wilc_wlan_initialize()
+    - staging: bcm2835-camera: Restore return behavior of ctrl_set_bitrate()
+    - staging: comedi: amplc_pci230: fix null pointer deref on interrupt
+    - staging: mt7621-pci: fix PCIE_FTS_NUM_LO macro
+    - HID: Add another Primax PIXART OEM mouse quirk
+    - lkdtm: support llvm-objcopy
+    - binder: fix memory leak in error path
+    - binder: return errors from buffer copy functions
+    - iio: adc: stm32-adc: add missing vdda-supply
+    - coresight: Potential uninitialized variable in probe()
+    - coresight: etb10: Do not call smp_processor_id from preemptible
+    - coresight: tmc-etr: Do not call smp_processor_id() from preemptible
+    - coresight: tmc-etr: alloc_perf_buf: Do not call smp_processor_id from
+      preemptible
+    - coresight: tmc-etf: Do not call smp_processor_id from preemptible
+    - carl9170: fix misuse of device driver API
+    - Revert "x86/build: Move _etext to actual end of .text"
+    - VMCI: Fix integer overflow in VMCI handle arrays
+    - staging: vchiq_2835_arm: revert "quit using custom down_interruptible()"
+    - staging: vchiq: make wait events interruptible
+    - staging: vchiq: revert "switch to wait_for_completion_killable"
+    - staging: fsl-dpaa2/ethsw: fix memory leak of switchdev_work
+    - staging: bcm2835-camera: Replace spinlock protecting context_map with mutex
+    - staging: bcm2835-camera: Ensure all buffers are returned on disable
+    - staging: bcm2835-camera: Remove check of the number of buffers supplied
+    - staging: bcm2835-camera: Handle empty EOS buffers whilst streaming
+    - staging: rtl8712: reduce stack usage, again
+    - Linux 5.2.1
+    - [Config] updateconfigs after v5.2.1 stable update
+
+  * fcf-protection=none patch with upstream version
+    - Revert "UBUNTU: SAUCE: add -fcf-protection=none to retpoline flags"
+    - SAUCE: kbuild: add -fcf-protection=none to retpoline flags
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: selftests/ftrace: avoid failure when trying to probe a notrace
+      function
+    - SAUCE: selftests/powerpc/ptrace: fix build failure
+    - update dkms package versions
+    - [Packaging] add zlua to zfs-modules.ignore
+    - update dkms package versions
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Fri, 19 Jul 2019 15:04:45 -0500
+
+linux (5.2.0-8.9) eoan; urgency=medium
+
+  * linux: 5.2.0-8.9 -proposed tracker (LP: #1835700)
+
+  * Miscellaneous Ubuntu changes
+    - [Packaging] replace zfs and spl build with zfs 0.8.1-1ubuntu1
+    - SAUCE: test_bpf: remove expected fail for Ctx heavy transformations test on
+      s390
+    - SAUCE: add -fcf-protection=none to retpoline flags
+    - SAUCE: usbip: ensure strings copied using strncpy are null-terminated
+    - SAUCE: usbip: add -Wno-address-of-packed-member to EXTRA_CFLAGS
+    - SAUCE: perf jvmti: ensure strncpy result is null-terminated
+    - update dkms package versions
+    - add removed zfs modules to modules.ignore
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v5.2
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 08 Jul 2019 07:13:41 -0500
+
+linux (5.2.0-7.8) eoan; urgency=medium
+
+  * Kernel panic upon resetting ixgbe SR-IOV VFIO virtual function using 5.0
+    kernel (LP: #1829652)
+    - SAUCE: ixgbe: Avoid NULL pointer dereference with VF on non-IPsec hw
+
+  * Hi1620 driver updates from upstream 5.2 merge window (LP: #1830815)
+    - net: hns3: initialize CPU reverse mapping
+    - net: hns3: refine the flow director handle
+    - net: hns3: add aRFS support for PF
+    - net: hns3: fix for FEC configuration
+    - RDMA/hns: Remove unnecessary print message in aeq
+    - RDMA/hns: Update CQE specifications
+    - RDMA/hns: Move spin_lock_irqsave to the correct place
+    - RDMA/hns: Remove jiffies operation in disable interrupt context
+    - RDMA/hns: Replace magic numbers with #defines
+    - net: hns3: fix compile warning without CONFIG_RFS_ACCEL
+    - net: hns3: fix for HNS3_RXD_GRO_SIZE_M macro
+    - net: hns3: add support for dump firmware statistics by debugfs
+    - net: hns3: use HCLGE_STATE_NIC_REGISTERED to indicate PF NIC client has
+      registered
+    - net: hns3: use HCLGE_STATE_ROCE_REGISTERED to indicate PF ROCE client has
+      registered
+    - net: hns3: use HCLGEVF_STATE_NIC_REGISTERED to indicate VF NIC client has
+      registered
+    - net: hns3: modify hclge_init_client_instance()
+    - net: hns3: modify hclgevf_init_client_instance()
+    - net: hns3: add handshake with hardware while doing reset
+    - net: hns3: stop schedule reset service while unloading driver
+    - net: hns3: adjust hns3_uninit_phy()'s location in the hns3_client_uninit()
+    - net: hns3: fix a memory leak issue for hclge_map_unmap_ring_to_vf_vector
+    - RDMA/hns: Bugfix for posting multiple srq work request
+    - net: hns3: remove redundant core reset
+    - net: hns3: don't configure new VLAN ID into VF VLAN table when it's full
+    - net: hns3: fix VLAN filter restore issue after reset
+    - net: hns3: set the port shaper according to MAC speed
+    - net: hns3: add a check to pointer in error_detected and slot_reset
+    - net: hns3: set ops to null when unregister ad_dev
+    - net: hns3: add handling of two bits in MAC tunnel interrupts
+    - net: hns3: remove setting bit of reset_requests when handling mac tunnel
+      interrupts
+    - net: hns3: add opcode about query and clear RAS & MSI-X to special opcode
+    - net: hns3: delay and separate enabling of NIC and ROCE HW errors
+    - RDMA/hns: fix inverted logic of readl read and shift
+    - RDMA/hns: Bugfix for filling the sge of srq
+    - net: hns3: log detail error info of ROCEE ECC and AXI errors
+    - net: hns3: fix wrong size of mailbox responding data
+    - net: hns3: make HW GRO handling compliant with SW GRO
+    - net: hns3: replace numa_node_id with numa_mem_id for buffer reusing
+    - net: hns3: refactor hns3_get_new_int_gl function
+    - net: hns3: trigger VF reset if a VF has an over_8bd_nfe_err
+    - net: hns3: delete the redundant user NIC codes
+    - net: hns3: small changes for magic numbers
+    - net: hns3: use macros instead of magic numbers
+    - net: hns3: refactor PF/VF RSS hash key configuration
+    - net: hns3: some modifications to simplify and optimize code
+    - net: hns3: fix some coding style issues
+    - net: hns3: delay setting of reset level for hw errors until slot_reset is
+      called
+    - net: hns3: fix avoid unnecessary resetting for the H/W errors which do not
+      require reset
+    - net: hns3: process H/W errors occurred before HNS dev initialization
+    - net: hns3: add recovery for the H/W errors occurred before the HNS dev
+      initialization
+    - net: hns3: some changes of MSI-X bits in PPU(RCB)
+    - net: hns3: extract handling of mpf/pf msi-x errors into functions
+    - net: hns3: clear restting state when initializing HW device
+    - net: hns3: free irq when exit from abnormal branch
+    - net: hns3: fix for dereferencing before null checking
+    - net: hns3: fix for skb leak when doing selftest
+    - net: hns3: delay ring buffer clearing during reset
+    - net: hns3: some variable modification
+    - net: hns3: fix dereference of ae_dev before it is null checked
+    - scsi: hisi_sas: Delete PHY timers when rmmod or probe failed
+    - scsi: hisi_sas: Fix the issue of argument mismatch of printing ecc errors
+    - scsi: hisi_sas: Reduce HISI_SAS_SGE_PAGE_CNT in size
+    - scsi: hisi_sas: Change the type of some numbers to unsigned
+    - scsi: hisi_sas: Ignore the error code between phy down to phy up
+    - scsi: hisi_sas: Disable stash for v3 hw
+    - net: hns3: Add missing newline at end of file
+    - RDMa/hns: Don't stuck in endless timeout loop
+
+  * Sometimes touchpad automatically trigger double click (LP: #1833484)
+    - SAUCE: i2c: designware: Add disable runtime pm quirk
+
+  * Add pointstick support on HP ZBook 17 G5 (LP: #1833387)
+    - Revert "HID: multitouch: Support ALPS PTP stick with pid 0x120A"
+
+  * depmod may prefer unsigned l-r-m nvidia modules to signed modules
+    (LP: #1834479)
+    - [Packaging] dkms-build--nvidia-N -- clean up unsigned ko files
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: selftests/powerpc: disable signal_fuzzer test
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v5.2-rc7
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 01 Jul 2019 07:22:18 -0500
+
+linux (5.2.0-6.7) eoan; urgency=medium
+
+  * hinic: fix oops due to race in set_rx_mode (LP: #1832048)
+    - hinic: fix a bug in set rx mode
+
+  * Miscellaneous Ubuntu changes
+    - rebase to v5.2-rc6
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v5.2-rc6
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Sun, 23 Jun 2019 23:36:11 -0500
+
+linux (5.2.0-5.6) eoan; urgency=medium
+
+  * QCA9377 isn't being recognized sometimes (LP: #1757218)
+    - SAUCE: USB: Disable USB2 LPM at shutdown
+
+  * shiftfs: allow changing ro/rw for subvolumes (LP: #1832316)
+    - SAUCE: shiftfs: allow changing ro/rw for subvolumes
+
+  * Miscellaneous Ubuntu changes
+    - update dkms package versions
+    - [Packaging] replace nvidia-418 dkms build with nvidia-430
+    - SAUCE: import aufs driver
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v5.2-rc5
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 17 Jun 2019 15:04:12 -0500
+
+linux (5.2.0-4.5) eoan; urgency=medium
+
+  * arm64: cma_alloc errors at boot (LP: #1823753)
+    - [Config] Bump CMA_SIZE_MBYTES to 32 on arm64
+    - dma-contiguous: add dma_{alloc,free}_contiguous() helpers
+    - dma-contiguous: use fallback alloc_pages for single pages
+    - dma-contiguous: fix !CONFIG_DMA_CMA version of dma_{alloc,
+      free}_contiguous()
+
+  * Miscellaneous Ubuntu changes
+    - [Config] CONFIG_MFD_TQMX86=n for s390x
+    - [Config] CONFIG_GPIO_AMD_FCH=n for s390x
+    - [Config] CONFIG_BACKLIGHT_CLASS_DEVICE=n on s390x
+    - [Config] CONFIG_LCD_CLASS_DEVICE=n for s390x
+    - [Config] CONFIG_DRM_ETNAVIV=m for armhf generic-lpae
+    - [Config] CONFIG_DRM_NOUVEAU_SVM=n
+    - [Config] CONFIG_HWMON=n for s390x
+    - [Config] CONFIG_NEW_LEDS=n for s390x
+    - [Config] CONFIG_MTD_NAND_OMAP2=y for armhf
+    - [Config] CONFIG_VOP_BUS=n for non-amd64 arches
+    - [Config] CONFIG_TI_CPSW_PHY_SEL=n
+    - [Config] CONFIG_INTERCONNECT=n for s390x
+    - [Config] CONFIG_SCSI_GDTH=n for s390x
+    - [Config] CONFIG_PACKING=n for s390x
+    - [Config] CONFIG_ARCH_MILBEAUT=y for armhf
+    - [Config] update annotations following config review
+    - update dkms package versions
+    - [Config] enable nvidia dkms build
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v5.2-rc4
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 10 Jun 2019 07:00:11 -0500
+
+linux (5.2.0-3.4) eoan; urgency=medium
+
+  * [18.04/18.10] File libperf-jvmti.so is missing in linux-tools-common deb on
+    Ubuntu (LP: #1761379)
+    - [Packaging] Support building libperf-jvmti.so
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: Revert "bpf, selftest: test global data/bss/rodata sections"
+    - update dkms package versions
+    - [Config] enable zfs
+    - rebase to v5.2-rc3
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v5.2-rc3
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Sun, 02 Jun 2019 21:48:50 -0500
+
+linux (5.2.0-2.3) eoan; urgency=medium
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: perf arm64: Fix mksyscalltbl when system kernel headers are ahead of
+      the kernel
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Tue, 28 May 2019 07:12:39 -0500
+
+linux (5.2.0-1.2) eoan; urgency=medium
+
+  * Miscellaneous Ubuntu changes
+    - [Config] CONFIG_INTEGRITY_PLATFORM_KEYRING=y
+    - update dkms package versions
+    - [Config] enable vbox dkms build
+    - update dkms package versions
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v5.2-rc2
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 27 May 2019 21:11:27 -0500
+
+linux (5.2.0-0.1) eoan; urgency=medium
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: import aufs driver
+    - [Packaging] disable ZFS
+    - [Packaging] disable nvidia
+    - [Packaging] dkms-build -- expand paths searched for make.log files
+    - add virtualbox-guest-dkms dkms package build
+    - enable vbox dkms build for amd64 and i386
+    - update dkms package versions
+    - SAUCE: (efi-lockdown) Add the ability to lock down access to the running
+      kernel image
+    - SAUCE: (efi-lockdown) Enforce module signatures if the kernel is locked down
+    - SAUCE: (efi-lockdown) Restrict /dev/{mem,kmem,port} when the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) kexec_load: Disable at runtime if the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) Copy secure_boot flag in boot params across kexec
+      reboot
+    - SAUCE: (efi-lockdown) kexec_file: split KEXEC_VERIFY_SIG into KEXEC_SIG and
+      KEXEC_SIG_FORCE
+    - SAUCE: (efi-lockdown) kexec_file: Restrict at runtime if the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) hibernate: Disable when the kernel is locked down
+    - SAUCE: (efi-lockdown) uswsusp: Disable when the kernel is locked down
+    - SAUCE: (efi-lockdown) PCI: Lock down BAR access when the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) x86: Lock down IO port access when the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) x86/msr: Restrict MSR access when the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) ACPI: Limit access to custom_method when the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) acpi: Ignore acpi_rsdp kernel param when the kernel
+      has been locked down
+    - SAUCE: (efi-lockdown) acpi: Disable ACPI table override if the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) acpi: Disable APEI error injection if the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) Prohibit PCMCIA CIS storage when the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) Lock down TIOCSSERIAL
+    - SAUCE: (efi-lockdown) Lock down module params that specify hardware
+      parameters (eg. ioport)
+    - SAUCE: (efi-lockdown) x86/mmiotrace: Lock down the testmmiotrace module
+    - SAUCE: (efi-lockdown) Lock down /proc/kcore
+    - SAUCE: (efi-lockdown) Lock down kprobes
+    - SAUCE: (efi-lockdown) bpf: Restrict kernel image access functions when the
+      kernel is locked down
+    - SAUCE: (efi-lockdown) Lock down perf
+    - SAUCE: (efi-lockdown) debugfs: Restrict debugfs when the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) lockdown: Print current->comm in restriction messages
+    - SAUCE: (efi-lockdown) kexec: Allow kexec_file() with appropriate IMA policy
+      when locked down
+    - SAUCE: (efi-lockdown) Make get_cert_list() not complain about cert lists
+      that aren't present.
+    - SAUCE: (efi-lockdown) Add efi_status_to_str() and rework
+      efi_status_to_err().
+    - SAUCE: (efi-lockdown) Make get_cert_list() use efi_status_to_str() to print
+      error messages.
+    - SAUCE: (efi-lockdown) efi: Add an EFI_SECURE_BOOT flag to indicate secure
+      boot mode
+    - SAUCE: (efi-lockdown) efi: Lock down the kernel if booted in secure boot
+      mode
+    - SAUCE: (efi-lockdown) KEYS: Make use of platform keyring for module
+      signature verify
+    - SAUCE: (efi-lockdown) debugfs: avoid EPERM when no open file operation
+      defined
+    - SAUCE: (efi-lockdown) efi: Sanitize boot_params in efi stub
+    - SAUCE: (efi-lockdown) furter KEXEC_VERIFY_SIG -> KEXEC_SIG updates
+    - SAUCE: (efi-lockdown) arm64: add kernel config option to lock down when in
+      Secure Boot mode
+    - update dkms package versions
+    - [Config] disable vbox build
+    - SAUCE: s390: mark __cpacf_check_opcode() and cpacf_query_func() as
+      __always_inline
+    - SAUCE: IB/mlx5: use size_t instead of u64 when dividing
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v5.2-rc1
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Tue, 21 May 2019 11:18:43 -0500
+
+linux (5.2.0-0.0) eoan; urgency=medium
+
+  * Dummy entry.
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Tue, 21 May 2019 07:34:43 -0500
+
+linux (5.1.0-2.2) eoan; urgency=medium
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync git-ubuntu-log
+
+  * Eoan update: v5.1.2 upstream stable release (LP: #1829050)
+    - x86/msr-index: Cleanup bit defines
+    - x86/speculation: Consolidate CPU whitelists
+    - x86/speculation/mds: Add basic bug infrastructure for MDS
+    - x86/speculation/mds: Add BUG_MSBDS_ONLY
+    - x86/kvm: Expose X86_FEATURE_MD_CLEAR to guests
+    - x86/speculation/mds: Add mds_clear_cpu_buffers()
+    - x86/speculation/mds: Clear CPU buffers on exit to user
+    - x86/kvm/vmx: Add MDS protection when L1D Flush is not active
+    - x86/speculation/mds: Conditionally clear CPU buffers on idle entry
+    - x86/speculation/mds: Add mitigation control for MDS
+    - x86/speculation/mds: Add sysfs reporting for MDS
+    - x86/speculation/mds: Add mitigation mode VMWERV
+    - Documentation: Move L1TF to separate directory
+    - Documentation: Add MDS vulnerability documentation
+    - x86/speculation/mds: Add mds=full,nosmt cmdline option
+    - x86/speculation: Move arch_smt_update() call to after mitigation decisions
+    - x86/speculation/mds: Add SMT warning message
+    - x86/speculation/mds: Fix comment
+    - x86/speculation/mds: Print SMT vulnerable on MSBDS with mitigations off
+    - cpu/speculation: Add 'mitigations=' cmdline option
+    - x86/speculation: Support 'mitigations=' cmdline option
+    - powerpc/speculation: Support 'mitigations=' cmdline option
+    - s390/speculation: Support 'mitigations=' cmdline option
+    - x86/speculation/mds: Add 'mitigations=' support for MDS
+    - x86/mds: Add MDSUM variant to the MDS documentation
+    - Documentation: Correct the possible MDS sysfs values
+    - x86/speculation/mds: Fix documentation typo
+    - Linux 5.1.2
+
+  * Eoan update: v5.1.1 upstream stable release (LP: #1829046)
+    - Drivers: hv: vmbus: Remove the undesired put_cpu_ptr() in hv_synic_cleanup()
+    - ubsan: Fix nasty -Wbuiltin-declaration-mismatch GCC-9 warnings
+    - staging: greybus: power_supply: fix prop-descriptor request size
+    - staging: wilc1000: Avoid GFP_KERNEL allocation from atomic context.
+    - staging: most: cdev: fix chrdev_region leak in mod_exit
+    - staging: most: sound: pass correct device when creating a sound card
+    - usb: dwc3: Allow building USB_DWC3_QCOM without EXTCON
+    - usb: dwc3: Fix default lpm_nyet_threshold value
+    - USB: serial: f81232: fix interrupt worker not stop
+    - USB: cdc-acm: fix unthrottle races
+    - usb-storage: Set virt_boundary_mask to avoid SG overflows
+    - genirq: Prevent use-after-free and work list corruption
+    - intel_th: pci: Add Comet Lake support
+    - iio: adc: qcom-spmi-adc5: Fix of-based module autoloading
+    - cpufreq: armada-37xx: fix frequency calculation for opp
+    - ACPI / LPSS: Use acpi_lpss_* instead of acpi_subsys_* functions for
+      hibernate
+    - soc: sunxi: Fix missing dependency on REGMAP_MMIO
+    - scsi: lpfc: change snprintf to scnprintf for possible overflow
+    - scsi: qla2xxx: Fix incorrect region-size setting in optrom SYSFS routines
+    - scsi: qla2xxx: Set remote port devloss timeout to 0
+    - scsi: qla2xxx: Fix device staying in blocked state
+    - Bluetooth: hidp: fix buffer overflow
+    - Bluetooth: Align minimum encryption key size for LE and BR/EDR connections
+    - Bluetooth: Fix not initializing L2CAP tx_credits
+    - Bluetooth: hci_bcm: Fix empty regulator supplies for Intel Macs
+    - UAS: fix alignment of scatter/gather segments
+    - ASoC: Intel: avoid Oops if DMA setup fails
+    - i3c: Fix a shift wrap bug in i3c_bus_set_addr_slot_status()
+    - locking/futex: Allow low-level atomic operations to return -EAGAIN
+    - arm64: futex: Bound number of LDXR/STXR loops in FUTEX_WAKE_OP
+    - Linux 5.1.1
+
+  * shiftfs: lock security sensitive superblock flags (LP: #1827122)
+    - SAUCE: shiftfs: lock down certain superblock flags
+
+  * Please package libbpf (which is done out of the kernel src) in Debian [for
+    19.10] (LP: #1826410)
+    - SAUCE: tools -- fix add ability to disable libbfd
+
+  * ratelimit cma_alloc messages (LP: #1828092)
+    - SAUCE: cma: ratelimit cma_alloc error messages
+
+  * Headphone jack switch sense is inverted: plugging in headphones disables
+    headphone output (LP: #1824259)
+    - ASoC: rt5645: Headphone Jack sense inverts on the LattePanda board
+
+  * There are 4 HDMI/Displayport audio output listed in sound setting without
+    attach any HDMI/DP monitor (LP: #1827967)
+    - ALSA: hda/hdmi - Read the pin sense from register when repolling
+    - ALSA: hda/hdmi - Consider eld_valid when reporting jack event
+
+  * CONFIG_LOG_BUF_SHIFT set to 14 is too low on arm64 (LP: #1824864)
+    - [Config] CONFIG_LOG_BUF_SHIFT=18 on all 64bit arches
+
+  * CTAUTO:DevOps:860.50:devops4fp1:Error occurred during LINUX Dmesg error
+    Checking for all LINUX clients for devops4p10 (LP: #1766201)
+    - SAUCE: integrity: downgrade error to warning
+
+  * linux-buildinfo: pull out ABI information into its own package
+    (LP: #1806380)
+    - [Packaging] autoreconstruct -- base tag is always primary mainline version
+
+  * [SRU] Please sync vbox modules from virtualbox 6.0.6 on next kernel update
+    (LP: #1825210)
+    - vbox-update: updates for renamed makefiles
+    - ubuntu: vbox -- update to 6.0.6-dfsg-1
+
+  * autofs kernel module missing (LP: #1824333)
+    - [Config] Update autofs4 path in inclusion list
+
+  * The Realtek card reader does not enter PCIe 1.1/1.2 (LP: #1825487)
+    - SAUCE: misc: rtsx: Fixed rts5260 power saving parameter and sd glitch
+
+  * CVE-2019-3874
+    - sctp: implement memory accounting on tx path
+    - sctp: implement memory accounting on rx path
+
+  * apparmor does not start in Disco LXD containers (LP: #1824812)
+    - SAUCE: shiftfs: use separate llseek method for directories
+
+  * Miscellaneous Ubuntu changes
+    - [Packaging] autoreconstruct -- remove for -rc kernels
+    - SAUCE: (efi-lockdown) debugfs: avoid EPERM when no open file operation
+      defined
+    - SAUCE: (efi-lockdown) efi: Sanitize boot_params in efi stub
+    - SAUCE: (efi-lockdown) furter KEXEC_VERIFY_SIG -> KEXEC_SIG updates
+    - [Config] (efi-lockdown): update configs after efi lockdown patch refresh
+    - [Packaging] don't delete efi_parser.c
+    - vbox-update -- do not fix up KERN_DIR or KBUILD_EXTMOD
+    - ubuntu: vbox -- update to 6.0.6-dfsg-2
+    - add nvidia-418 dkms build
+    - remove virtualbox guest drivers
+    - [Packaging] dkms-build -- expand paths searched for make.log files
+    - add virtualbox-guest-dkms dkms package build
+    - enable vbox dkms build for amd64 and i386
+    - [Config] update configs for v5.1(-rc7)? rebase
+    - update dkms package versions
+    - Add the ability to lock down access to the running kernel image
+    - Enforce module signatures if the kernel is locked down
+    - Restrict /dev/{mem,kmem,port} when the kernel is locked down
+    - kexec_load: Disable at runtime if the kernel is locked down
+    - Copy secure_boot flag in boot params across kexec reboot
+    - kexec_file: split KEXEC_VERIFY_SIG into KEXEC_SIG and KEXEC_SIG_FORCE
+    - kexec_file: Restrict at runtime if the kernel is locked down
+    - hibernate: Disable when the kernel is locked down
+    - uswsusp: Disable when the kernel is locked down
+    - PCI: Lock down BAR access when the kernel is locked down
+    - x86: Lock down IO port access when the kernel is locked down
+    - x86/msr: Restrict MSR access when the kernel is locked down
+    - ACPI: Limit access to custom_method when the kernel is locked down
+    - acpi: Ignore acpi_rsdp kernel param when the kernel has been locked down
+    - acpi: Disable ACPI table override if the kernel is locked down
+    - acpi: Disable APEI error injection if the kernel is locked down
+    - Prohibit PCMCIA CIS storage when the kernel is locked down
+    - Lock down TIOCSSERIAL
+    - Lock down module params that specify hardware parameters (eg. ioport)
+    - x86/mmiotrace: Lock down the testmmiotrace module
+    - Lock down /proc/kcore
+    - Lock down kprobes
+    - bpf: Restrict kernel image access functions when the kernel is locked down
+    - Lock down perf
+    - debugfs: Restrict debugfs when the kernel is locked down
+    - lockdown: Print current->comm in restriction messages
+    - kexec: Allow kexec_file() with appropriate IMA policy when locked down
+    - Make get_cert_list() not complain about cert lists that aren't present.
+    - Add efi_status_to_str() and rework efi_status_to_err().
+    - Make get_cert_list() use efi_status_to_str() to print error messages.
+    - efi: Add an EFI_SECURE_BOOT flag to indicate secure boot mode
+    - efi: Lock down the kernel if booted in secure boot mode
+    - KEYS: Make use of platform keyring for module signature verify
+
+  * Miscellaneous upstream changes
+    - ALSA: hdea/realtek - Headset fixup for System76 Gazelle (gaze14)
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Tue, 14 May 2019 12:32:56 -0500
+
+linux (5.1.0-1.1) eoan; urgency=medium
+
+  * bionic: fork out linux-snapdragon into its own topic kernel (LP: #1820868)
+    - [Packaging]: really drop snapdragon
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: fix vbox use of MAP_SHARED
+    - SAUCE: fix vbox use of vm_fault_t
+    - [Packaging] disable ZFS
+    - [Packaging] disable nvidia
+    - SAUCE: perf annotate: Fix build on 32 bit for BPF annotation
+    - [Config]: updateconfig after rebase to v5.1-rc
+    - [Config]: build ETNAVIV only on arm platforms
+    - [Config]: Disable CMA on non-arm platforms
+    - [Config]: MMC_CQHCI is needed by some built-in drivers
+    - [Config]: a.out support has been deprecated
+    - [Config]: R3964 was marked as BROKEN
+    - [Config]: Add SENSIRION_SGP30 module
+
+  * Miscellaneous upstream changes
+    - Revert "UBUNTU: SAUCE: tools: lib/bpf -- add generated headers to search
+      path"
+    - Revert "UBUNTU: SAUCE: btqcomsmd: introduce BT_QCOMSMD_HACK"
+
+ -- Thadeu Lima de Souza Cascardo <cascardo@canonical.com>  Thu, 25 Apr 2019 10:03:25 -0300
+
+linux (5.1.0-0.0) eoan; urgency=medium
+
+  * Dummy entry.
+
+ -- Thadeu Lima de Souza Cascardo <cascardo@canonical.com>  Thu, 25 Apr 2019 09:49:47 -0300
+
+linux (5.0.0-13.14) disco; urgency=medium
+
+  * linux: 5.0.0-13.14 -proposed tracker (LP: #1824819)
+
+  * Display only has 640x480 (LP: #1824677)
+    - Revert "UBUNTU: SAUCE: drm/nouveau: Disable nouveau driver by default"
+
+  * shiftfs: use after free when checking mount options (LP: #1824735)
+    - SAUCE: shiftfs: prevent use-after-free when verifying mount options
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 15 Apr 2019 09:11:23 -0500
+
+linux (5.0.0-12.13) disco; urgency=medium
+
+  * linux: 5.0.0-12.13 -proposed tracker (LP: #1824726)
+
+  * Linux 5.0 black screen on boot, display flickers (i915 regression with
+    certain laptop panels) (LP: #1824216)
+    - drm/i915/dp: revert back to max link rate and lane count on eDP
+
+  * kernel BUG at fs/attr.c:287 when using shiftfs (LP: #1824717)
+    - SAUCE: shiftfs: fix passing of attrs to underaly for setattr
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Sun, 14 Apr 2019 13:38:05 -0500
+
+linux (5.0.0-11.12) disco; urgency=medium
+
+  * linux: 5.0.0-11.12 -proposed tracker (LP: #1824383)
+
+  * hns3: PPU_PF_ABNORMAL_INT_ST over_8bd_no_fe found [error status=0x1]
+    (LP: #1824194)
+    - net: hns3: fix for not calculating tx bd num correctly
+
+  * disco: unable to use iptables/enable ufw under -virtual kernel
+    (LP: #1823862)
+    - [Packaging] add bpfilter to linux-modules
+
+  * Make shiftfs a module rather than built-in (LP: #1824354)
+    - [Config] CONFIG_SHIFT_FS=m
+
+  * shiftfs: chown sets untranslated ids in lower fs (LP: #1824350)
+    - SAUCE: shiftfs: use translated ids when chaning lower fs attrs
+
+  * [Hyper-V] KVP daemon fails to start on first boot of disco VM (LP: #1820063)
+    - [Packaging] bind hv_kvp_daemon startup to hv_kvp device
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Thu, 11 Apr 2019 10:17:19 -0500
+
+linux (5.0.0-10.11) disco; urgency=medium
+
+  * linux: 5.0.0-10.11 -proposed tracker (LP: #1823936)
+
+  * Apparmor enforcement failure in lxc selftests (LP: #1823379)
+    - SAUCE: apparmor: Restore Y/N in /sys for apparmor's "enabled"
+
+  * systemd cause kernel trace "BUG: unable to handle kernel paging request at
+    6db23a14" on Cosmic i386 (LP: #1813244)
+    - openvswitch: fix flow actions reallocation
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Tue, 09 Apr 2019 08:30:38 -0500
+
+linux (5.0.0-9.10) disco; urgency=medium
+
+  * linux: 5.0.0-9.10 -proposed tracker (LP: #1823228)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync git-ubuntu-log
+    - [Packaging] update helper scripts
+    - [Packaging] resync retpoline extraction
+
+  * Huawei Hi1822 NIC has poor performance (LP: #1820187)
+    - net-next/hinic: replace disable_irq_nosync/enable_irq
+
+  * Add uid shifting overlay filesystem (shiftfs) (LP: #1823186)
+    - shiftfs: uid/gid shifting bind mount
+    - shiftfs: rework and extend
+    - shiftfs: support some btrfs ioctls
+    - [Config] enable shiftfs
+
+  * Cannot boot or install - have to use nomodeset (LP: #1821820)
+    - Revert "drm/i915/fbdev: Actually configure untiled displays"
+
+  * Disco update: v5.0.6 upstream stable release (LP: #1823060)
+    - netfilter: nf_tables: fix set double-free in abort path
+    - dccp: do not use ipv6 header for ipv4 flow
+    - genetlink: Fix a memory leak on error path
+    - gtp: change NET_UDP_TUNNEL dependency to select
+    - ipv6: make ip6_create_rt_rcu return ip6_null_entry instead of NULL
+    - mac8390: Fix mmio access size probe
+    - mISDN: hfcpci: Test both vendor & device ID for Digium HFC4S
+    - net: aquantia: fix rx checksum offload for UDP/TCP over IPv6
+    - net: datagram: fix unbounded loop in __skb_try_recv_datagram()
+    - net/packet: Set __GFP_NOWARN upon allocation in alloc_pg_vec
+    - net: phy: meson-gxl: fix interrupt support
+    - net: rose: fix a possible stack overflow
+    - net: stmmac: fix memory corruption with large MTUs
+    - net-sysfs: call dev_hold if kobject_init_and_add success
+    - net: usb: aqc111: Extend HWID table by QNAP device
+    - packets: Always register packet sk in the same order
+    - rhashtable: Still do rehash when we get EEXIST
+    - sctp: get sctphdr by offset in sctp_compute_cksum
+    - sctp: use memdup_user instead of vmemdup_user
+    - tcp: do not use ipv6 header for ipv4 flow
+    - tipc: allow service ranges to be connect()'ed on RDM/DGRAM
+    - tipc: change to check tipc_own_id to return in tipc_net_stop
+    - tipc: fix cancellation of topology subscriptions
+    - tun: properly test for IFF_UP
+    - vrf: prevent adding upper devices
+    - vxlan: Don't call gro_cells_destroy() before device is unregistered
+    - thunderx: enable page recycling for non-XDP case
+    - thunderx: eliminate extra calls to put_page() for pages held for recycling
+    - net: dsa: mv88e6xxx: fix few issues in mv88e6390x_port_set_cmode
+    - net: mii: Fix PAUSE cap advertisement from linkmode_adv_to_lcl_adv_t()
+      helper
+    - net: phy: don't clear BMCR in genphy_soft_reset
+    - r8169: fix cable re-plugging issue
+    - ila: Fix rhashtable walker list corruption
+    - tun: add a missing rcu_read_unlock() in error path
+    - powerpc/fsl: Fix the flush of branch predictor.
+    - Btrfs: fix incorrect file size after shrinking truncate and fsync
+    - btrfs: remove WARN_ON in log_dir_items
+    - btrfs: don't report readahead errors and don't update statistics
+    - btrfs: Fix bound checking in qgroup_trace_new_subtree_blocks
+    - btrfs: Avoid possible qgroup_rsv_size overflow in
+      btrfs_calculate_inode_block_rsv_size
+    - Btrfs: fix assertion failure on fsync with NO_HOLES enabled
+    - locks: wake any locks blocked on request before deadlock check
+    - tracing: initialize variable in create_dyn_event()
+    - ARM: imx6q: cpuidle: fix bug that CPU might not wake up at expected time
+    - powerpc: bpf: Fix generation of load/store DW instructions
+    - vfio: ccw: only free cp on final interrupt
+    - NFS: Fix nfs4_lock_state refcounting in nfs4_alloc_{lock,unlock}data()
+    - NFS: fix mount/umount race in nlmclnt.
+    - NFSv4.1 don't free interrupted slot on open
+    - net: dsa: qca8k: remove leftover phy accessors
+    - ALSA: rawmidi: Fix potential Spectre v1 vulnerability
+    - ALSA: seq: oss: Fix Spectre v1 vulnerability
+    - ALSA: pcm: Fix possible OOB access in PCM oss plugins
+    - ALSA: pcm: Don't suspend stream in unrecoverable PCM state
+    - ALSA: hda/realtek - Fixed Headset Mic JD not stable
+    - ALSA: hda/realtek: merge alc_fixup_headset_jack to alc295_fixup_chromebook
+    - ALSA: hda/realtek - Add support headset mode for DELL WYSE AIO
+    - ALSA: hda/realtek - Add support headset mode for New DELL WYSE NB
+    - ALSA: hda/realtek: Enable headset MIC of Acer AIO with ALC286
+    - ALSA: hda/realtek: Enable headset MIC of Acer Aspire Z24-890 with ALC286
+    - ALSA: hda/realtek - Add support for Acer Aspire E5-523G/ES1-432 headset mic
+    - ALSA: hda/realtek: Enable ASUS X441MB and X705FD headset MIC with ALC256
+    - ALSA: hda/realtek: Enable headset mic of ASUS P5440FF with ALC256
+    - ALSA: hda/realtek: Enable headset MIC of ASUS X430UN and X512DK with ALC256
+    - ALSA: hda/realtek - Fix speakers on Acer Predator Helios 500 Ryzen laptops
+    - kbuild: modversions: Fix relative CRC byte order interpretation
+    - fs/open.c: allow opening only regular files during execve()
+    - ocfs2: fix inode bh swapping mixup in ocfs2_reflink_inodes_lock
+    - scsi: sd: Fix a race between closing an sd device and sd I/O
+    - scsi: sd: Quiesce warning if device does not report optimal I/O size
+    - scsi: zfcp: fix rport unblock if deleted SCSI devices on Scsi_Host
+    - scsi: zfcp: fix scsi_eh host reset with port_forced ERP for non-NPIV FCP
+      devices
+    - drm/rockchip: vop: reset scale mode when win is disabled
+    - tty/serial: atmel: Add is_half_duplex helper
+    - tty/serial: atmel: RS485 HD w/DMA: enable RX after TX is stopped
+    - tty: mxs-auart: fix a potential NULL pointer dereference
+    - tty: atmel_serial: fix a potential NULL pointer dereference
+    - tty: serial: qcom_geni_serial: Initialize baud in qcom_geni_console_setup
+    - staging: comedi: ni_mio_common: Fix divide-by-zero for DIO cmdtest
+    - staging: olpc_dcon_xo_1: add missing 'const' qualifier
+    - staging: speakup_soft: Fix alternate speech with other synths
+    - staging: vt6655: Remove vif check from vnt_interrupt
+    - staging: vt6655: Fix interrupt race condition on device start up.
+    - staging: erofs: fix to handle error path of erofs_vmap()
+    - staging: erofs: fix error handling when failed to read compresssed data
+    - staging: erofs: keep corrupted fs from crashing kernel in erofs_readdir()
+    - serial: max310x: Fix to avoid potential NULL pointer dereference
+    - serial: mvebu-uart: Fix to avoid a potential NULL pointer dereference
+    - serial: sh-sci: Fix setting SCSCR_TIE while transferring data
+    - USB: serial: cp210x: add new device id
+    - USB: serial: ftdi_sio: add additional NovaTech products
+    - USB: serial: mos7720: fix mos_parport refcount imbalance on error path
+    - USB: serial: option: set driver_info for SIM5218 and compatibles
+    - USB: serial: option: add support for Quectel EM12
+    - USB: serial: option: add Olicard 600
+    - ACPI / CPPC: Fix guaranteed performance handling
+    - Disable kgdboc failed by echo space to /sys/module/kgdboc/parameters/kgdboc
+    - fs/proc/proc_sysctl.c: fix NULL pointer dereference in put_links
+    - drivers/block/zram/zram_drv.c: fix idle/writeback string compare
+    - blk-mq: fix sbitmap ws_active for shared tags
+    - cpufreq: intel_pstate: Also use CPPC nominal_perf for base_frequency
+    - cpufreq: scpi: Fix use after free
+    - drm/vgem: fix use-after-free when drm_gem_handle_create() fails
+    - drm/vkms: fix use-after-free when drm_gem_handle_create() fails
+    - drm/i915: Mark AML 0x87CA as ULX
+    - drm/i915/gvt: Fix MI_FLUSH_DW parsing with correct index check
+    - drm/i915/icl: Fix the TRANS_DDI_FUNC_CTL2 bitfield macro
+    - gpio: exar: add a check for the return value of ida_simple_get fails
+    - gpio: adnp: Fix testing wrong value in adnp_gpio_direction_input
+    - phy: sun4i-usb: Support set_mode to USB_HOST for non-OTG PHYs
+    - usb: mtu3: fix EXTCON dependency
+    - USB: gadget: f_hid: fix deadlock in f_hidg_write()
+    - usb: common: Consider only available nodes for dr_mode
+    - mm/memory.c: fix modifying of page protection by insert_pfn()
+    - usb: host: xhci-rcar: Add XHCI_TRUST_TX_LENGTH quirk
+    - xhci: Fix port resume done detection for SS ports with LPM enabled
+    - usb: xhci: dbc: Don't free all memory with spinlock held
+    - xhci: Don't let USB3 ports stuck in polling state prevent suspend
+    - usb: cdc-acm: fix race during wakeup blocking TX traffic
+    - usb: typec: tcpm: Try PD-2.0 if sink does not respond to 3.0 source-caps
+    - usb: typec: Fix unchecked return value
+    - mm/hotplug: fix offline undo_isolate_page_range()
+    - mm: add support for kmem caches in DMA32 zone
+    - iommu/io-pgtable-arm-v7s: request DMA32 memory, and improve debugging
+    - mm: mempolicy: make mbind() return -EIO when MPOL_MF_STRICT is specified
+    - mm/debug.c: fix __dump_page when mapping->host is not set
+    - mm/memory_hotplug.c: fix notification in offline error path
+    - mm/page_isolation.c: fix a wrong flag in set_migratetype_isolate()
+    - mm/migrate.c: add missing flush_dcache_page for non-mapped page migrate
+    - perf pmu: Fix parser error for uncore event alias
+    - perf intel-pt: Fix TSC slip
+    - objtool: Query pkg-config for libelf location
+    - powerpc/pseries/energy: Use OF accessor functions to read ibm,drc-indexes
+    - powerpc/64: Fix memcmp reading past the end of src/dest
+    - powerpc/pseries/mce: Fix misleading print for TLB mutlihit
+    - watchdog: Respect watchdog cpumask on CPU hotplug
+    - cpu/hotplug: Prevent crash when CPU bringup fails on CONFIG_HOTPLUG_CPU=n
+    - x86/smp: Enforce CONFIG_HOTPLUG_CPU when SMP=y
+    - KVM: Reject device ioctls from processes other than the VM's creator
+    - KVM: x86: Emulate MSR_IA32_ARCH_CAPABILITIES on AMD hosts
+    - KVM: x86: update %rip after emulating IO
+    - bpf: do not restore dst_reg when cur_state is freed
+    - mt76x02u: use usb_bulk_msg to upload firmware
+    - Linux 5.0.6
+
+  * RDMA/hns updates for disco (LP: #1822897)
+    - RDMA/hns: Fix the bug with updating rq head pointer when flush cqe
+    - RDMA/hns: Bugfix for the scene without receiver queue
+    - RDMA/hns: Add constraint on the setting of local ACK timeout
+    - RDMA/hns: Modify the pbl ba page size for hip08
+    - RDMA/hns: RDMA/hns: Assign rq head pointer when enable rq record db
+    - RDMA/hns: Add the process of AEQ overflow for hip08
+    - RDMA/hns: Add SCC context allocation support for hip08
+    - RDMA/hns: Add SCC context clr support for hip08
+    - RDMA/hns: Add timer allocation support for hip08
+    - RDMA/hns: Remove set but not used variable 'rst'
+    - RDMA/hns: Make some function static
+    - RDMA/hns: Fix the Oops during rmmod or insmod ko when reset occurs
+    - RDMA/hns: Fix the chip hanging caused by sending mailbox&CMQ during reset
+    - RDMA/hns: Fix the chip hanging caused by sending doorbell during reset
+    - RDMA/hns: Limit minimum ROCE CQ depth to 64
+    - RDMA/hns: Fix the state of rereg mr
+    - RDMA/hns: Set allocated memory to zero for wrid
+    - RDMA/hns: Delete useful prints for aeq subtype event
+    - RDMA/hns: Configure capacity of hns device
+    - RDMA/hns: Modify qp&cq&pd specification according to UM
+    - RDMA/hns: Bugfix for set hem of SCC
+    - RDMA/hns: Use GFP_ATOMIC in hns_roce_v2_modify_qp
+
+  * autopkgtests run too often, too much and don't skip enough (LP: #1823056)
+    - Set +x on rebuild testcase.
+    - Skip rebuild test, for regression-suite deps.
+    - Make ubuntu-regression-suite skippable on unbootable kernels.
+    - make rebuild use skippable error codes when skipping.
+    - Only run regression-suite, if requested to.
+
+  * touchpad not working on lenovo yoga 530 (LP: #1787775)
+    - Revert "UBUNTU: SAUCE: i2c:amd Depends on ACPI"
+    - Revert "UBUNTU: SAUCE: i2c:amd move out pointer in union i2c_event_base"
+    - i2c: add extra check to safe DMA buffer helper
+    - i2c: Add drivers for the AMD PCIe MP2 I2C controller
+    - [Config] Update config for AMD MP2 I2C driver
+
+  * Detect SMP PHY control command errors (LP: #1822680)
+    - scsi: libsas: Check SMP PHY control function result
+
+  * disable a.out support (LP: #1818552)
+    - [Config] Disable a.out support
+    - [Config] remove binfmt_aout from abi for i386 lowlatency
+
+  * bionic: fork out linux-snapdragon into its own topic kernel (LP: #1820868)
+    - [Packaging] remove snapdragon flavour support
+    - Revert "UBUNTU: SAUCE: (snapdragon) drm/msm/adv7511: wrap hacks under
+      CONFIG_ADV7511_SNAPDRAGON_HACKS #ifdefs"
+    - Revert "UBUNTU: SAUCE: (snapdragon) media: ov5645: skip address change if dt
+      addr == default addr"
+    - Revert "UBUNTU: SAUCE: (snapdragon) DT: leds: Add Qualcomm Light Pulse
+      Generator binding"
+    - Revert "UBUNTU: SAUCE: (snapdragon) MAINTAINERS: Add Qualcomm Camera Control
+      Interface driver"
+    - Revert "UBUNTU: SAUCE: (snapdragon) dt-bindings: media: Binding document for
+      Qualcomm Camera Control Interface driver"
+    - Revert "UBUNTU: SAUCE: (snapdragon) leds: Add driver for Qualcomm LPG"
+    - Revert "UBUNTU: SAUCE: (snapdragon) HACK: drm/msm/adv7511: Don't rely on
+      interrupts for EDID parsing"
+    - Revert "UBUNTU: SAUCE: (snapdragon) drm/bridge/adv7511: Delay clearing of
+      HPD interrupt status"
+    - Revert "UBUNTU: SAUCE: (snapdragon) media: ov5645: Fix I2C address"
+    - Revert "UBUNTU: SAUCE: (snapdragon) i2c-qcom-cci: Fix I2C address bug"
+    - Revert "UBUNTU: SAUCE: (snapdragon) i2c-qcom-cci: Fix run queue completion
+      timeout"
+    - Revert "UBUNTU: SAUCE: (snapdragon) camss: Do not register if no cameras are
+      present"
+    - Revert "UBUNTU: SAUCE: (snapdragon) i2c: Add Qualcomm Camera Control
+      Interface driver"
+    - Revert "UBUNTU: SAUCE: (snapdragon) ov5645: I2C address change"
+    - Revert "UBUNTU: SAUCE: (snapdragon) regulator: smd: Allow
+      REGULATOR_QCOM_SMD_RPM=m"
+    - Revert "UBUNTU: SAUCE: (snapdragon) cpufreq: Add apq8016 to cpufreq-dt-
+      platdev blacklist"
+    - Revert "UBUNTU: SAUCE: (snapdragon) PM / OPP: Add a helper to get an opp
+      regulator for device"
+    - Revert "UBUNTU: SAUCE: (snapdragon) PM / OPP: HACK: Allow to set regulator
+      without opp_list"
+    - Revert "UBUNTU: SAUCE: (snapdragon) PM / OPP: Drop RCU usage in
+      dev_pm_opp_adjust_voltage()"
+    - Revert "UBUNTU: SAUCE: (snapdragon) PM / OPP: Support adjusting OPP voltages
+      at runtime"
+    - Revert "UBUNTU: SAUCE: (snapdragon) regulator: smd: Add floor and corner
+      operations"
+    - Revert "UBUNTU: SAUCE: (snapdragon) power: avs: cpr: Register with cpufreq-
+      dt"
+    - Revert "UBUNTU: SAUCE: (snapdragon) power: avs: cpr: fix with new
+      reg_sequence structures"
+    - Revert "UBUNTU: SAUCE: (snapdragon) power: avs: cpr: Use raw mem access for
+      qfprom"
+    - Revert "UBUNTU: SAUCE: (snapdragon) power: avs: Add support for CPR (Core
+      Power Reduction)"
+    - Revert "UBUNTU: SAUCE: (snapdragon) HACK: drm/msm/iommu: Remove runtime_put
+      calls in map/unmap"
+    - Revert "UBUNTU: SAUCE: (snapdragon) arm64: defconfig: enable LEDS_QCOM_LPG"
+    - Revert "UBUNTU: SAUCE: (snapdragon) kernel: distro.config: enable 'BBR' TCP
+      congestion algorithm"
+    - Revert "UBUNTU: SAUCE: (snapdragon) kernel: distro.config: enable 'fq' and
+      'fq_codel' qdiscs"
+    - Revert "UBUNTU: SAUCE: (snapdragon) kernel: distro.config: enable
+      'schedutil' CPUfreq governor"
+    - Revert "UBUNTU: SAUCE: (snapdragon) kernel: configs: set USB_CONFIG_F_FS in
+      distro.config"
+    - Revert "UBUNTU: SAUCE: (snapdragon) arm64: defconfig: enable
+      CONFIG_USB_CONFIGFS_F_FS by default"
+    - Revert "UBUNTU: SAUCE: (snapdragon) kernel: configs: add freq stat to sysfs"
+    - Revert "UBUNTU: SAUCE: (snapdragon) arm64: configs: Enable camera drivers"
+    - Revert "UBUNTU: SAUCE: (snapdragon) arm64: defconfig: disable ANALOG_TV and
+      DIGITAL_TV"
+    - Revert "UBUNTU: SAUCE: (snapdragon) kernel: configs: add more USB net
+      drivers"
+    - Revert "UBUNTU: SAUCE: (snapdragon) arm64: configs: enable BT_QCOMSMD"
+    - Revert "UBUNTU: SAUCE: (snapdragon) arm64: defconfig: enable
+      CFG80211_DEFAULT_PS by default"
+    - Revert "UBUNTU: SAUCE: (snapdragon) Force the SMD regulator driver to be
+      compiled-in"
+    - Revert "UBUNTU: SAUCE: (snapdragon) kernel: configs: enable dm_mod and
+      dm_crypt"
+    - Revert "UBUNTU: SAUCE: (snapdragon) arm64: defconfig: Enable a53/apcs and
+      avs"
+    - Revert "UBUNTU: SAUCE: (snapdragon) arm64: configs: enable QCOM Venus"
+    - Revert "UBUNTU: SAUCE: (snapdragon) kernel: distro.config: enable debug
+      friendly USB network adpater"
+    - Revert "UBUNTU: SAUCE: (snapdragon) arm64: configs: enable WCN36xx"
+    - Revert "UBUNTU: SAUCE: (snapdragon) kernel: configs; add distro.config"
+    - Revert "UBUNTU: SAUCE: (snapdragon) arm64: defconfig: enable QCOM audio
+      drivers for APQ8016 and DB410c"
+    - Revert "UBUNTU: SAUCE: (snapdragon) arm64: defconfig: enable REMOTEPROC"
+    - [Config] fix abi for remove i2c-qcom-cci module
+    - [Config] update annotations
+    - [Config] update configs following snapdragon removal
+
+  * Disco update: v5.0.5 upstream stable release (LP: #1822671)
+    - Revert "ALSA: hda - Enforces runtime_resume after S3 and S4 for each codec"
+    - ALSA: hda - add Lenovo IdeaCentre B550 to the power_save_blacklist
+    - ALSA: firewire-motu: use 'version' field of unit directory to identify model
+    - mmc: pxamci: fix enum type confusion
+    - mmc: alcor: fix DMA reads
+    - mmc: mxcmmc: "Revert mmc: mxcmmc: handle highmem pages"
+    - mmc: renesas_sdhi: limit block count to 16 bit for old revisions
+    - drm/amdgpu: fix invalid use of change_bit
+    - drm/vmwgfx: Don't double-free the mode stored in par->set_mode
+    - drm/vmwgfx: Return 0 when gmrid::get_node runs out of ID's
+    - iommu/amd: fix sg->dma_address for sg->offset bigger than PAGE_SIZE
+    - iommu/iova: Fix tracking of recently failed iova address
+    - libceph: wait for latest osdmap in ceph_monc_blacklist_add()
+    - udf: Fix crash on IO error during truncate
+    - mips: loongson64: lemote-2f: Add IRQF_NO_SUSPEND to "cascade" irqaction.
+    - MIPS: Ensure ELF appended dtb is relocated
+    - MIPS: Fix kernel crash for R6 in jump label branch function
+    - powerpc/vdso64: Fix CLOCK_MONOTONIC inconsistencies across Y2038
+    - powerpc/security: Fix spectre_v2 reporting
+    - net/mlx5: Fix DCT creation bad flow
+    - scsi: core: Avoid that a kernel warning appears during system resume
+    - scsi: qla2xxx: Fix FC-AL connection target discovery
+    - scsi: ibmvscsi: Protect ibmvscsi_head from concurrent modificaiton
+    - scsi: ibmvscsi: Fix empty event pool access during host removal
+    - futex: Ensure that futex address is aligned in handle_futex_death()
+    - perf probe: Fix getting the kernel map
+    - objtool: Move objtool_file struct off the stack
+    - irqchip/gic-v3-its: Fix comparison logic in lpi_range_cmp
+    - clocksource/drivers/riscv: Fix clocksource mask
+    - ALSA: ac97: Fix of-node refcount unbalance
+    - ext4: fix NULL pointer dereference while journal is aborted
+    - ext4: fix data corruption caused by unaligned direct AIO
+    - ext4: brelse all indirect buffer in ext4_ind_remove_space()
+    - media: v4l2-ctrls.c/uvc: zero v4l2_event
+    - Bluetooth: hci_uart: Check if socket buffer is ERR_PTR in h4_recv_buf()
+    - Bluetooth: Fix decrementing reference count twice in releasing socket
+    - Bluetooth: hci_ldisc: Initialize hci_dev before open()
+    - Bluetooth: hci_ldisc: Postpone HCI_UART_PROTO_READY bit set in
+      hci_uart_set_proto()
+    - drm/vkms: Fix flush_work() without INIT_WORK().
+    - RDMA/cma: Rollback source IP address if failing to acquire device
+    - f2fs: fix to avoid deadlock of atomic file operations
+    - aio: simplify - and fix - fget/fput for io_submit()
+    - netfilter: ebtables: remove BUGPRINT messages
+    - loop: access lo_backing_file only when the loop device is Lo_bound
+    - x86/unwind: Handle NULL pointer calls better in frame unwinder
+    - x86/unwind: Add hardcoded ORC entry for NULL
+    - locking/lockdep: Add debug_locks check in __lock_downgrade()
+    - ALSA: hda - Record the current power state before suspend/resume calls
+    - ALSA: hda - Enforces runtime_resume after S3 and S4 for each codec
+    - Linux 5.0.5
+
+  * hisi_sas updates for disco (LP: #1822385)
+    - scsi: hisi_sas: send primitive NOTIFY to SSP situation only
+    - scsi: hisi_sas: shutdown axi bus to avoid exception CQ returned
+    - scsi: hisi_sas: remove the check of sas_dev status in
+      hisi_sas_I_T_nexus_reset()
+    - scsi: hisi_sas: Remove unused parameter of function hisi_sas_alloc()
+    - scsi: hisi_sas: Reject setting programmed minimum linkrate > 1.5G
+    - scsi: hisi_sas: Fix losing directly attached disk when hot-plug
+    - scsi: hisi_sas: Correct memory allocation size for DQ debugfs
+    - scsi: hisi_sas: Some misc tidy-up
+    - scsi: hisi_sas: Fix to only call scsi_get_prot_op() for non-NULL scsi_cmnd
+    - scsi: hisi_sas: Add missing seq_printf() call in hisi_sas_show_row_32()
+    - scsi: hisi_sas: Add support for DIX feature for v3 hw
+    - scsi: hisi_sas: Add manual trigger for debugfs dump
+    - scsi: hisi_sas: change queue depth from 512 to 4096
+    - scsi: hisi_sas: Issue internal abort on all relevant queues
+    - scsi: hisi_sas: Use pci_irq_get_affinity() for v3 hw as experimental
+    - scsi: hisi_sas: Do some more tidy-up
+    - scsi: hisi_sas: Change return variable type in phy_up_v3_hw()
+    - scsi: hisi_sas: Fix a timeout race of driver internal and SMP IO
+    - scsi: hisi_sas: print PHY RX errors count for later revision of v3 hw
+    - scsi: hisi_sas: Set PHY linkrate when disconnected
+    - scsi: hisi_sas: Send HARD RESET to clear the previous affiliation of STP
+      target port
+    - scsi: hisi_sas: Change SERDES_CFG init value to increase reliability of
+      HiLink
+    - scsi: hisi_sas: Add softreset in hisi_sas_I_T_nexus_reset()
+
+  * [Patch][Raven 2] kernel 5.0.0 cannot boot because of psp response
+    (LP: #1822267)
+    - drm/amdgpu/psp: Fix can't detect psp INVOKE command failed
+    - drm/amdgpu/psp: ignore psp response status
+
+  * 3b080b2564287be91605bfd1d5ee985696e61d3c in ubuntu_btrfs_kernel_fixes
+    triggers system hang on i386 (LP: #1812845)
+    - btrfs: raid56: properly unmap parity page in finish_parity_scrub()
+
+  * enable CONFIG_DRM_BOCHS (LP: #1795857)
+    - [Config] Reenable DRM_BOCHS as module
+
+  * [Dell Precision 7530/5530 with Nvidia Quadro P1000] Live USB freezes or
+    cannot complete install when nouveau driver is loaded (crashing in GP100
+    code) (LP: #1822026)
+    - SAUCE: drm/nouveau: Disable nouveau driver by default
+
+  * Need to add Intel CML related pci-id's (LP: #1821863)
+    - drm/i915/cml: Add CML PCI IDS
+    - drm/i915/cml: Introduce Comet Lake PCH
+
+  * ARM: Add support for the SDEI interface (LP: #1822005)
+    - ACPI / APEI: Don't wait to serialise with oops messages when panic()ing
+    - ACPI / APEI: Remove silent flag from ghes_read_estatus()
+    - ACPI / APEI: Switch estatus pool to use vmalloc memory
+    - ACPI / APEI: Make hest.c manage the estatus memory pool
+    - ACPI / APEI: Make estatus pool allocation a static size
+    - ACPI / APEI: Don't store CPER records physical address in struct ghes
+    - ACPI / APEI: Remove spurious GHES_TO_CLEAR check
+    - ACPI / APEI: Don't update struct ghes' flags in read/clear estatus
+    - ACPI / APEI: Generalise the estatus queue's notify code
+    - ACPI / APEI: Don't allow ghes_ack_error() to mask earlier errors
+    - ACPI / APEI: Move NOTIFY_SEA between the estatus-queue and NOTIFY_NMI
+    - ACPI / APEI: Switch NOTIFY_SEA to use the estatus queue
+    - KVM: arm/arm64: Add kvm_ras.h to collect kvm specific RAS plumbing
+    - arm64: KVM/mm: Move SEA handling behind a single 'claim' interface
+    - ACPI / APEI: Move locking to the notification helper
+    - ACPI / APEI: Let the notification helper specify the fixmap slot
+    - ACPI / APEI: Pass ghes and estatus separately to avoid a later copy
+    - ACPI / APEI: Make GHES estatus header validation more user friendly
+    - ACPI / APEI: Split ghes_read_estatus() to allow a peek at the CPER length
+    - ACPI / APEI: Only use queued estatus entry during in_nmi_queue_one_entry()
+    - ACPI / APEI: Use separate fixmap pages for arm64 NMI-like notifications
+    - firmware: arm_sdei: Add ACPI GHES registration helper
+    - ACPI / APEI: Add support for the SDEI GHES Notification type
+
+  * CVE-2019-9857
+    - inotify: Fix fsnotify_mark refcount leak in inotify_update_existing_watch()
+
+  * scsi: libsas: Support SATA PHY connection rate unmatch fixing during
+    discovery (LP: #1821408)
+    - scsi: libsas: Support SATA PHY connection rate unmatch fixing during
+      discovery
+
+  * Qualcomm Atheros QCA9377 wireless does not work (LP: #1818204)
+    - platform/x86: ideapad-laptop: Add Ideapad 530S-14ARR to no_hw_rfkill list
+
+  * Lenovo ideapad 330-15ICH Wifi rfkill hard blocked (LP: #1811815)
+    - platform/x86: ideapad: Add ideapad 330-15ICH to no_hw_rfkill
+
+  * hid-sensor-hub spamming dmesg in 4.20 (LP: #1818547)
+    - HID: Increase maximum report size allowed by hid_field_extract()
+
+  * [disco] [5.0.0-7.8] can't mount guest cifs share (LP: #1821053)
+    - cifs: allow guest mounts to work for smb3.11
+    - SMB3: Fix SMB3.1.1 guest mounts to Samba
+
+  * Add HiSilicon SoC quirk for cpufreq (LP: #1821620)
+    - ACPI / CPPC: Add a helper to get desired performance
+    - cpufreq / cppc: Work around for Hisilicon CPPC cpufreq
+
+  * Disco update: v5.0.4 upstream stable release (LP: #1821607)
+    - 9p: use inode->i_lock to protect i_size_write() under 32-bit
+    - 9p/net: fix memory leak in p9_client_create
+    - ASoC: fsl_esai: fix register setting issue in RIGHT_J mode
+    - ASoC: codecs: pcm186x: fix wrong usage of DECLARE_TLV_DB_SCALE()
+    - ASoC: codecs: pcm186x: Fix energysense SLEEP bit
+    - iio: adc: exynos-adc: Fix NULL pointer exception on unbind
+    - iio: adc: exynos-adc: Use proper number of channels for Exynos4x12
+    - mei: hbm: clean the feature flags on link reset
+    - mei: bus: move hw module get/put to probe/release
+    - stm class: Prevent division by zero
+    - stm class: Fix an endless loop in channel allocation
+    - crypto: caam - fix hash context DMA unmap size
+    - crypto: ccree - fix missing break in switch statement
+    - crypto: caam - fixed handling of sg list
+    - crypto: caam - fix DMA mapping of stack memory
+    - crypto: ccree - fix free of unallocated mlli buffer
+    - crypto: ccree - unmap buffer before copying IV
+    - crypto: ccree - don't copy zero size ciphertext
+    - crypto: cfb - add missing 'chunksize' property
+    - crypto: cfb - remove bogus memcpy() with src == dest
+    - crypto: ofb - fix handling partial blocks and make thread-safe
+    - crypto: ahash - fix another early termination in hash walk
+    - crypto: rockchip - fix scatterlist nents error
+    - crypto: rockchip - update new iv to device in multiple operations
+    - dax: Flush partial PMDs correctly
+    - nfit: Fix nfit_intel_shutdown_status() command submission
+    - nfit: acpi_nfit_ctl(): Check out_obj->type in the right place
+    - acpi/nfit: Fix bus command validation
+    - nfit/ars: Attempt a short-ARS whenever the ARS state is idle at boot
+    - nfit/ars: Attempt short-ARS even in the no_init_ars case
+    - libnvdimm/label: Clear 'updating' flag after label-set update
+    - libnvdimm, pfn: Fix over-trim in trim_pfn_device()
+    - libnvdimm/pmem: Honor force_raw for legacy pmem regions
+    - libnvdimm: Fix altmap reservation size calculation
+    - fix cgroup_do_mount() handling of failure exits
+    - crypto: aead - set CRYPTO_TFM_NEED_KEY if ->setkey() fails
+    - crypto: aegis - fix handling chunked inputs
+    - crypto: arm/crct10dif - revert to C code for short inputs
+    - crypto: arm64/aes-neonbs - fix returning final keystream block
+    - crypto: arm64/crct10dif - revert to C code for short inputs
+    - crypto: hash - set CRYPTO_TFM_NEED_KEY if ->setkey() fails
+    - crypto: morus - fix handling chunked inputs
+    - crypto: pcbc - remove bogus memcpy()s with src == dest
+    - crypto: skcipher - set CRYPTO_TFM_NEED_KEY if ->setkey() fails
+    - crypto: testmgr - skip crc32c context test for ahash algorithms
+    - crypto: x86/aegis - fix handling chunked inputs and MAY_SLEEP
+    - crypto: x86/aesni-gcm - fix crash on empty plaintext
+    - crypto: x86/morus - fix handling chunked inputs and MAY_SLEEP
+    - crypto: arm64/aes-ccm - fix logical bug in AAD MAC handling
+    - crypto: arm64/aes-ccm - fix bugs in non-NEON fallback routine
+    - CIFS: Fix leaking locked VFS cache pages in writeback retry
+    - CIFS: Do not reset lease state to NONE on lease break
+    - CIFS: Do not skip SMB2 message IDs on send failures
+    - CIFS: Fix read after write for files with read caching
+    - smb3: make default i/o size for smb3 mounts larger
+    - tracing: Use strncpy instead of memcpy for string keys in hist triggers
+    - tracing: Do not free iter->trace in fail path of tracing_open_pipe()
+    - tracing/perf: Use strndup_user() instead of buggy open-coded version
+    - vmw_balloon: release lock on error in vmballoon_reset()
+    - xen: fix dom0 boot on huge systems
+    - ACPI / device_sysfs: Avoid OF modalias creation for removed device
+    - mmc: sdhci-esdhc-imx: fix HS400 timing issue
+    - mmc: renesas_sdhi: Fix card initialization failure in high speed mode
+    - mmc:fix a bug when max_discard is 0
+    - spi: ti-qspi: Fix mmap read when more than one CS in use
+    - spi: pxa2xx: Setup maximum supported DMA transfer length
+    - spi: omap2-mcspi: Fix DMA and FIFO event trigger size mismatch
+    - spi: spi-gpio: fix SPI_CS_HIGH capability
+    - regulator: s2mps11: Fix steps for buck7, buck8 and LDO35
+    - regulator: max77620: Initialize values for DT properties
+    - regulator: s2mpa01: Fix step values for some LDOs
+    - mt76: fix corrupted software generated tx CCMP PN
+    - clocksource/drivers/exynos_mct: Move one-shot check from tick clear to ISR
+    - clocksource/drivers/exynos_mct: Clear timer interrupt when shutdown
+    - clocksource/drivers/arch_timer: Workaround for Allwinner A64 timer
+      instability
+    - s390: vfio_ap: link the vfio_ap devices to the vfio_ap bus subsystem
+    - s390/setup: fix early warning messages
+    - s390/virtio: handle find on invalid queue gracefully
+    - scsi: virtio_scsi: don't send sc payload with tmfs
+    - scsi: aacraid: Fix performance issue on logical drives
+    - scsi: sd: Optimal I/O size should be a multiple of physical block size
+    - scsi: target/iscsi: Avoid iscsit_release_commands_from_conn() deadlock
+    - scsi: qla2xxx: Fix LUN discovery if loop id is not assigned yet by firmware
+    - scsi: qla2xxx: Avoid PCI IRQ affinity mapping when multiqueue is not
+      supported
+    - scsi: qla2xxx: Use complete switch scan for RSCN events
+    - fs/devpts: always delete dcache dentry-s in dput()
+    - splice: don't merge into linked buffers
+    - ovl: During copy up, first copy up data and then xattrs
+    - ovl: Do not lose security.capability xattr over metadata file copy-up
+    - m68k: Add -ffreestanding to CFLAGS
+    - Btrfs: setup a nofs context for memory allocation at btrfs_create_tree()
+    - Btrfs: setup a nofs context for memory allocation at __btrfs_set_acl
+    - btrfs: scrub: fix circular locking dependency warning
+    - btrfs: drop the lock on error in btrfs_dev_replace_cancel
+    - btrfs: ensure that a DUP or RAID1 block group has exactly two stripes
+    - btrfs: init csum_list before possible free
+    - Btrfs: fix corruption reading shared and compressed extents after hole
+      punching
+    - Btrfs: fix deadlock between clone/dedupe and rename
+    - soc: qcom: rpmh: Avoid accessing freed memory from batch API
+    - libertas_tf: don't set URB_ZERO_PACKET on IN USB transfer
+    - irqchip/gic-v3-its: Avoid parsing _indirect_ twice for Device table
+    - irqchip/brcmstb-l2: Use _irqsave locking variants in non-interrupt code
+    - x86/kprobes: Prohibit probing on optprobe template code
+    - cpufreq: kryo: Release OPP tables on module removal
+    - cpufreq: tegra124: add missing of_node_put()
+    - cpufreq: pxa2xx: remove incorrect __init annotation
+    - ext4: fix check of inode in swap_inode_boot_loader
+    - ext4: cleanup pagecache before swap i_data
+    - mm: hwpoison: fix thp split handing in soft_offline_in_use_page()
+    - mm/vmalloc: fix size check for remap_vmalloc_range_partial()
+    - mm/memory.c: do_fault: avoid usage of stale vm_area_struct
+    - kernel/sysctl.c: add missing range check in do_proc_dointvec_minmax_conv
+    - nvmem: core: don't check the return value of notifier chain call
+    - device property: Fix the length used in PROPERTY_ENTRY_STRING()
+    - intel_th: Don't reference unassigned outputs
+    - parport_pc: fix find_superio io compare code, should use equal test.
+    - i2c: tegra: fix maximum transfer size
+    - i2c: tegra: update maximum transfer size
+    - media: i2c: ov5640: Fix post-reset delay
+    - gpio: pca953x: Fix dereference of irq data in shutdown
+    - ext4: update quota information while swapping boot loader inode
+    - ext4: add mask of ext4 flags to swap
+    - ext4: fix crash during online resizing
+    - dma: Introduce dma_max_mapping_size()
+    - swiotlb: Introduce swiotlb_max_mapping_size()
+    - swiotlb: Add is_swiotlb_active() function
+    - PCI/ASPM: Use LTR if already enabled by platform
+    - PCI/DPC: Fix print AER status in DPC event handling
+    - PCI: qcom: Don't deassert reset GPIO during probe
+    - PCI: dwc: skip MSI init if MSIs have been explicitly disabled
+    - PCI: pci-bridge-emul: Create per-bridge copy of register behavior
+    - PCI: pci-bridge-emul: Extend pci_bridge_emul_init() with flags
+    - IB/hfi1: Close race condition on user context disable and close
+    - IB/rdmavt: Fix loopback send with invalidate ordering
+    - IB/rdmavt: Fix concurrency panics in QP post_send and modify to error
+    - cxl: Wrap iterations over afu slices inside 'afu_list_lock'
+    - ext2: Fix underflow in ext2_max_size()
+    - clk: uniphier: Fix update register for CPU-gear
+    - clk: clk-twl6040: Fix imprecise external abort for pdmclk
+    - clk: samsung: exynos5: Fix possible NULL pointer exception on
+      platform_device_alloc() failure
+    - clk: samsung: exynos5: Fix kfree() of const memory on setting
+      driver_override
+    - clk: ingenic: Fix round_rate misbehaving with non-integer dividers
+    - clk: ingenic: Fix doc of ingenic_cgu_div_info
+    - usb: chipidea: tegra: Fix missed ci_hdrc_remove_device()
+    - usb: typec: tps6598x: handle block writes separately with plain-I2C adapters
+    - dmaengine: usb-dmac: Make DMAC system sleep callbacks explicit
+    - serial: uartps: Fix stuck ISR if RX disabled with non-empty FIFO
+    - serial: 8250_of: assume reg-shift of 2 for mrvl,mmp-uart
+    - serial: 8250_pci: Fix number of ports for ACCES serial cards
+    - serial: 8250_pci: Have ACCES cards that use the four port Pericom PI7C9X7954
+      chip use the pci_pericom_setup()
+    - jbd2: clear dirty flag when revoking a buffer from an older transaction
+    - jbd2: fix compile warning when using JBUFFER_TRACE
+    - selinux: add the missing walk_size + len check in selinux_sctp_bind_connect
+    - security/selinux: fix SECURITY_LSM_NATIVE_LABELS on reused superblock
+    - powerpc/32: Clear on-stack exception marker upon exception return
+    - powerpc/wii: properly disable use of BATs when requested.
+    - powerpc/powernv: Make opal log only readable by root
+    - powerpc/83xx: Also save/restore SPRG4-7 during suspend
+    - powerpc/kvm: Save and restore host AMR/IAMR/UAMOR
+    - powerpc/powernv: Don't reprogram SLW image on every KVM guest entry/exit
+    - powerpc/64s/hash: Fix assert_slb_presence() use of the slbfee. instruction
+    - powerpc: Fix 32-bit KVM-PR lockup and host crash with MacOS guest
+    - powerpc/ptrace: Simplify vr_get/set() to avoid GCC warning
+    - powerpc/hugetlb: Don't do runtime allocation of 16G pages in LPAR
+      configuration
+    - powerpc/smp: Fix NMI IPI timeout
+    - powerpc/smp: Fix NMI IPI xmon timeout
+    - powerpc/traps: fix recoverability of machine check handling on book3s/32
+    - powerpc/traps: Fix the message printed when stack overflows
+    - ARM: s3c24xx: Fix boolean expressions in osiris_dvs_notify
+    - arm64: Fix HCR.TGE status for NMI contexts
+    - arm64: debug: Don't propagate UNKNOWN FAR into si_code for debug signals
+    - arm64: debug: Ensure debug handlers check triggering exception level
+    - arm64: KVM: Fix architecturally invalid reset value for FPEXC32_EL2
+    - Revert "KVM/MMU: Flush tlb directly in the kvm_zap_gfn_range()"
+    - ipmi_si: Fix crash when using hard-coded device
+    - ipmi_si: fix use-after-free of resource->name
+    - dm: fix to_sector() for 32bit
+    - dm integrity: limit the rate of error messages
+    - media: cx25840: mark pad sig_types to fix cx231xx init
+    - mfd: sm501: Fix potential NULL pointer dereference
+    - cpcap-charger: generate events for userspace
+    - cpuidle: governor: Add new governors to cpuidle_governors again
+    - NFS: Fix I/O request leakages
+    - NFS: Fix an I/O request leakage in nfs_do_recoalesce
+    - NFS: Don't recoalesce on error in nfs_pageio_complete_mirror()
+    - nfsd: fix performance-limiting session calculation
+    - nfsd: fix memory corruption caused by readdir
+    - nfsd: fix wrong check in write_v4_end_grace()
+    - NFSv4.1: Reinitialise sequence results before retransmitting a request
+    - svcrpc: fix UDP on servers with lots of threads
+    - PM / wakeup: Rework wakeup source timer cancellation
+    - PM / OPP: Update performance state when freq == old_freq
+    - bcache: treat stale && dirty keys as bad keys
+    - bcache: use (REQ_META|REQ_PRIO) to indicate bio for metadata
+    - stable-kernel-rules.rst: add link to networking patch queue
+    - vt: perform safe console erase in the right order
+    - x86/unwind/orc: Fix ORC unwind table alignment
+    - perf intel-pt: Fix CYC timestamp calculation after OVF
+    - perf tools: Fix split_kallsyms_for_kcore() for trampoline symbols
+    - perf auxtrace: Define auxtrace record alignment
+    - perf intel-pt: Fix overlap calculation for padding
+    - perf/x86/intel/uncore: Fix client IMC events return huge result
+    - perf intel-pt: Fix divide by zero when TSC is not available
+    - md: Fix failed allocation of md_register_thread
+    - x86/kvmclock: set offset for kvm unstable clock
+    - x86/ftrace: Fix warning and considate ftrace_jmp_replace() and
+      ftrace_call_replace()
+    - tpm/tpm_crb: Avoid unaligned reads in crb_recv()
+    - tpm: Unify the send callback behaviour
+    - rcu: Do RCU GP kthread self-wakeup from softirq and interrupt
+    - media: imx: prpencvf: Stop upstream before disabling IDMA channel
+    - media: lgdt330x: fix lock status reporting
+    - media: sun6i: Fix CSI regmap's max_register
+    - media: uvcvideo: Avoid NULL pointer dereference at the end of streaming
+    - media: vimc: Add vimc-streamer for stream control
+    - media: imx-csi: Input connections to CSI should be optional
+    - media: imx: csi: Disable CSI immediately after last EOF
+    - media: imx: csi: Stop upstream before disabling IDMA channel
+    - drm/fb-helper: generic: Fix drm_fbdev_client_restore()
+    - drm/radeon/evergreen_cs: fix missing break in switch statement
+    - drm/amd/powerplay: correct power reading on fiji
+    - drm/amd/display: don't call dm_pp_ function from an fpu block
+    - KVM: Call kvm_arch_memslots_updated() before updating memslots
+    - KVM: VMX: Compare only a single byte for VMCS' "launched" in vCPU-run
+    - KVM: VMX: Zero out *all* general purpose registers after VM-Exit
+    - KVM: x86/mmu: Detect MMIO generation wrap in any address space
+    - KVM: x86/mmu: Do not cache MMIO accesses while memslots are in flux
+    - KVM: nVMX: Sign extend displacements of VMX instr's mem operands
+    - KVM: nVMX: Apply addr size mask to effective address for VMX instructions
+    - KVM: nVMX: Ignore limit checks on VMX instructions using flat segments
+    - KVM: nVMX: Check a single byte for VMCS "launched" in nested early checks
+    - net: dsa: lantiq_gswip: fix use-after-free on failed probe
+    - net: dsa: lantiq_gswip: fix OF child-node lookups
+    - s390/setup: fix boot crash for machine without EDAT-1
+    - SUNRPC: Prevent thundering herd when the socket is not connected
+    - SUNRPC: Fix up RPC back channel transmission
+    - SUNRPC: Respect RPC call timeouts when retrying transmission
+    - Linux 5.0.4
+    - [Config] update configs for 5.0.4 stable update
+
+  * New Intel Wireless-AC 9260 [8086:2526] card not correctly probed in Ubuntu
+    system (LP: #1821271)
+    - iwlwifi: add new card for 9260 series
+
+  * [CONFIG] please enable highdpi font FONT_TER16x32 (LP: #1819881)
+    - [Config]: enable highdpi Terminus 16x32 font support
+
+  * [SRU][B/B-OEM/C/D] Fix AMD IOMMU NULL dereference (LP: #1820990)
+    - iommu/amd: Fix NULL dereference bug in match_hid_uid
+
+  * some codecs stop working after S3 (LP: #1820930)
+    - ALSA: hda - Enforces runtime_resume after S3 and S4 for each codec
+    - ALSA: hda - Don't trigger jackpoll_work in azx_resume
+
+  * tcm_loop.ko: move from modules-extra into main modules package
+    (LP: #1817786)
+    - [Packaging] move tcm_loop.lo to main linux-modules package
+
+  * C++ demangling support missing from perf (LP: #1396654)
+    - [Packaging] fix a mistype
+
+  * r8169 doesn't get woken up by ethernet cable plugging, no PME generated
+    (LP: #1817676)
+    - PCI: pciehp: Disable Data Link Layer State Changed event on suspend
+
+  * Disco update: v5.0.3 upstream stable release (LP: #1821074)
+    - connector: fix unsafe usage of ->real_parent
+    - fou, fou6: avoid uninit-value in gue_err() and gue6_err()
+    - gro_cells: make sure device is up in gro_cells_receive()
+    - ipv4/route: fail early when inet dev is missing
+    - l2tp: fix infoleak in l2tp_ip6_recvmsg()
+    - lan743x: Fix RX Kernel Panic
+    - lan743x: Fix TX Stall Issue
+    - net: hsr: fix memory leak in hsr_dev_finalize()
+    - net/hsr: fix possible crash in add_timer()
+    - net: sit: fix UBSAN Undefined behaviour in check_6rd
+    - net/x25: fix use-after-free in x25_device_event()
+    - net/x25: reset state in x25_connect()
+    - pptp: dst_release sk_dst_cache in pptp_sock_destruct
+    - ravb: Decrease TxFIFO depth of Q3 and Q2 to one
+    - route: set the deleted fnhe fnhe_daddr to 0 in ip_del_fnhe to fix a race
+    - rxrpc: Fix client call queueing, waiting for channel
+    - sctp: remove sched init from sctp_stream_init
+    - tcp: do not report TCP_CM_INQ of 0 for closed connections
+    - tcp: Don't access TCP_SKB_CB before initializing it
+    - tcp: handle inet_csk_reqsk_queue_add() failures
+    - vxlan: Fix GRO cells race condition between receive and link delete
+    - vxlan: test dev->flags & IFF_UP before calling gro_cells_receive()
+    - net/mlx4_core: Fix reset flow when in command polling mode
+    - net/mlx4_core: Fix locking in SRIOV mode when switching between events and
+      polling
+    - net/mlx4_core: Fix qp mtt size calculation
+    - net: dsa: mv88e6xxx: Set correct interface mode for CPU/DSA ports
+    - vsock/virtio: fix kernel panic from virtio_transport_reset_no_sock
+    - net: sched: flower: insert new filter to idr after setting its mask
+    - f2fs: wait on atomic writes to count F2FS_CP_WB_DATA
+    - perf/x86: Fixup typo in stub functions
+    - ALSA: bebob: use more identical mod_alias for Saffire Pro 10 I/O against
+      Liquid Saffire 56
+    - ALSA: firewire-motu: fix construction of PCM frame for capture direction
+    - ALSA: hda: Extend i915 component bind timeout
+    - ALSA: hda - add more quirks for HP Z2 G4 and HP Z240
+    - ALSA: hda/realtek: Enable audio jacks of ASUS UX362FA with ALC294
+    - ALSA: hda/realtek - Reduce click noise on Dell Precision 5820 headphone
+    - ALSA: hda/realtek: Enable headset MIC of Acer TravelMate X514-51T with
+      ALC255
+    - perf/x86/intel: Fix memory corruption
+    - perf/x86/intel: Make dev_attr_allow_tsx_force_abort static
+    - It's wrong to add len to sector_nr in raid10 reshape twice
+    - drm: Block fb changes for async plane updates
+    - Linux 5.0.3
+
+  * Disco update: v5.0.2 upstream stable release (LP: #1820318)
+    - media: uvcvideo: Fix 'type' check leading to overflow
+    - Input: wacom_serial4 - add support for Wacom ArtPad II tablet
+    - Input: elan_i2c - add id for touchpad found in Lenovo s21e-20
+    - iscsi_ibft: Fix missing break in switch statement
+    - scsi: aacraid: Fix missing break in switch statement
+    - x86/PCI: Fixup RTIT_BAR of Intel Denverton Trace Hub
+    - arm64: dts: zcu100-revC: Give wifi some time after power-on
+    - arm64: dts: hikey: Give wifi some time after power-on
+    - arm64: dts: hikey: Revert "Enable HS200 mode on eMMC"
+    - ARM: dts: exynos: Fix pinctrl definition for eMMC RTSN line on Odroid X2/U3
+    - ARM: dts: exynos: Add minimal clkout parameters to Exynos3250 PMU
+    - ARM: dts: exynos: Fix max voltage for buck8 regulator on Odroid XU3/XU4
+    - drm: disable uncached DMA optimization for ARM and arm64
+    - media: Revert "media: rc: some events are dropped by userspace"
+    - Revert "PCI/PME: Implement runtime PM callbacks"
+    - bpf: Stop the psock parser before canceling its work
+    - gfs2: Fix missed wakeups in find_insert_glock
+    - staging: erofs: keep corrupted fs from crashing kernel in erofs_namei()
+    - staging: erofs: compressed_pages should not be accessed again after freed
+    - scripts/gdb: replace flags (MS_xyz -> SB_xyz)
+    - ath9k: Avoid OF no-EEPROM quirks without qca,no-eeprom
+    - perf/x86/intel: Make cpuc allocations consistent
+    - perf/x86/intel: Generalize dynamic constraint creation
+    - x86: Add TSX Force Abort CPUID/MSR
+    - perf/x86/intel: Implement support for TSX Force Abort
+    - Linux 5.0.2
+
+  * Linux security module stacking support
+    - LSM: Introduce LSM_FLAG_LEGACY_MAJOR
+    - LSM: Provide separate ordered initialization
+    - LSM: Plumb visibility into optional "enabled" state
+    - LSM: Lift LSM selection out of individual LSMs
+    - LSM: Build ordered list of LSMs to initialize
+    - LSM: Introduce CONFIG_LSM
+    - LSM: Introduce "lsm=" for boottime LSM selection
+    - LSM: Tie enabling logic to presence in ordered list
+    - LSM: Prepare for reorganizing "security=" logic
+    - LSM: Refactor "security=" in terms of enable/disable
+    - LSM: Separate idea of "major" LSM from "exclusive" LSM
+    - apparmor: Remove SECURITY_APPARMOR_BOOTPARAM_VALUE
+    - selinux: Remove SECURITY_SELINUX_BOOTPARAM_VALUE
+    - LSM: Add all exclusive LSMs to ordered initialization
+    - LSM: Split LSM preparation from initialization
+    - LoadPin: Initialize as ordered LSM
+    - Yama: Initialize as ordered LSM
+    - LSM: Introduce enum lsm_order
+    - capability: Initialize as LSM_ORDER_FIRST
+    - procfs: add smack subdir to attrs
+    - Smack: Abstract use of cred security blob
+    - SELinux: Abstract use of cred security blob
+    - SELinux: Remove cred security blob poisoning
+    - SELinux: Remove unused selinux_is_enabled
+    - AppArmor: Abstract use of cred security blob
+    - TOMOYO: Abstract use of cred security blob
+    - Infrastructure management of the cred security blob
+    - SELinux: Abstract use of file security blob
+    - Smack: Abstract use of file security blob
+    - LSM: Infrastructure management of the file security
+    - SELinux: Abstract use of inode security blob
+    - Smack: Abstract use of inode security blob
+    - LSM: Infrastructure management of the inode security
+    - LSM: Infrastructure management of the task security
+    - SELinux: Abstract use of ipc security blobs
+    - Smack: Abstract use of ipc security blobs
+    - LSM: Infrastructure management of the ipc security blob
+    - TOMOYO: Update LSM flags to no longer be exclusive
+    - LSM: generalize flag passing to security_capable
+    - LSM: Make lsm_early_cred() and lsm_early_task() local functions.
+    - LSM: Make some functions static
+    - apparmor: Adjust offset when accessing task blob.
+    - LSM: Ignore "security=" when "lsm=" is specified
+    - LSM: Update list of SECURITYFS users in Kconfig
+    - apparmor: delete the dentry in aafs_remove() to avoid a leak
+    - apparmor: fix double free when unpack of secmark rules fails
+    - SAUCE: LSM: Infrastructure management of the sock security
+    - SAUCE: LSM: Limit calls to certain module hooks
+    - SAUCE: LSM: Special handling for secctx lsm hooks
+    - SAUCE: LSM: Specify which LSM to display with /proc/self/attr/display
+    - SAUCE: Fix-up af_unix mediation for sock infrastructure management
+    - SAUCE: Revert "apparmor: Fix warning about unused function
+      apparmor_ipv6_postroute"
+    - SAUCE: Revert "apparmor: fix checkpatch error in Parse secmark policy"
+    - SAUCE: Revert "apparmor: add #ifdef checks for secmark filtering"
+    - SAUCE: Revert "apparmor: Allow filtering based on secmark policy"
+    - SAUCE: Revert "apparmor: Parse secmark policy"
+    - SAUCE: Revert "apparmor: Add a wildcard secid"
+    - SAUCE: Revert "apparmor: fix bad debug check in apparmor_secid_to_secctx()"
+    - SAUCE: Revert "apparmor: fixup secid map conversion to using IDR"
+    - SAUCE: Revert "apparmor: Use an IDR to allocate apparmor secids"
+    - SAUCE: Revert "apparmor: Fix memory leak of rule on error exit path"
+    - SAUCE: Revert "apparmor: modify audit rule support to support profile
+      stacks"
+    - SAUCE: Revert "apparmor: Add support for audit rule filtering"
+    - SAUCE: Revert "apparmor: add the ability to get a task's secid"
+    - SAUCE: Revert "apparmor: add support for mapping secids and using secctxes"
+    - SAUCE: apparmor: add proc subdir to attrs
+    - SAUCE: apparmor: add an apparmorfs entry to access current attrs
+    - SAUCE: apparmor: update flags to no longer be exclusive
+    - SAUCE: update configs and annotations for LSM stacking
+
+  * Miscellaneous Ubuntu changes
+    - [Config] CONFIG_EARLY_PRINTK_USB_XDBC=y
+    - SAUCE: (efi-lockdown) bpf: Restrict kernel image access functions when the
+      kernel is locked down
+    - [Config] CONFIG_RANDOM_TRUST_CPU=y
+    - [Config] refresh annotations for recent config changes
+    - ubuntu: vbox -- update to 6.0.4-dfsg-7
+    - Revert "UBUNTU: SAUCE: i2c:amd I2C Driver based on PCI Interface for
+      upcoming platform"
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Thu, 04 Apr 2019 14:49:59 -0500
+
+linux (5.0.0-8.9) disco; urgency=medium
+
+  * linux: 5.0.0-8.9 -proposed tracker (LP: #1819759)
+
+  * hisi_sas: add debugfs support (LP: #1819500)
+    - scsi: hisi_sas: Create root and device debugfs directories
+    - scsi: hisi_sas: Alloc debugfs snapshot buffer memory for all registers
+    - scsi: hisi_sas: Take debugfs snapshot for all regs
+    - scsi: hisi_sas: Debugfs global register create file and add file operations
+    - scsi: hisi_sas: Add debugfs for port registers
+    - scsi: hisi_sas: Add debugfs CQ file and add file operations
+    - scsi: hisi_sas: Add debugfs DQ file and add file operations
+    - scsi: hisi_sas: Add debugfs IOST file and add file operations
+    - scsi: hisi_sas: No need to check return value of debugfs_create functions
+    - scsi: hisi_sas: Fix type casting and missing static qualifier in debugfs
+      code
+    - scsi: hisi_sas: Add debugfs ITCT file and add file operations
+
+  * [disco] hns driver updates from 5.1 merge window (LP: #1819535)
+    - net: hns: Use struct_size() in devm_kzalloc()
+    - net: hns3: modify enet reinitialization interface
+    - net: hns3: remove unused member in struct hns3_enet_ring
+    - net: hns3: remove unnecessary hns3_adjust_tqps_num
+    - net: hns3: reuse reinitialization interface in the hns3_set_channels
+    - net: hns3: add interface hclge_tm_bp_setup
+    - net: hns3: modify parameter checks in the hns3_set_channels
+    - net: hns3: remove redundant codes in hclge_knic_setup
+    - net: hns3: fix user configuration loss for ethtool -L
+    - net: hns3: adjust the use of alloc_tqps and num_tqps
+    - net: hns3: fix wrong combined count returned by ethtool -l
+    - net: hns3: do reinitialization while ETS configuration changed
+    - net: hns3: add HNAE3_RESTORE_CLIENT interface in enet module
+    - net: hns3: add calling roce callback function when link status change
+    - net: hns3: add rx multicast packets statistic
+    - net: hns3: refactor the statistics updating for netdev
+    - net: hns3: fix rss configuration lost problem when setting channel
+    - net: hns3: fix for shaper not setting when TC num changes
+    - net: hns3: fix bug of ethtool_ops.get_channels for VF
+    - net: hns3: clear param in ring when free ring
+    - net: hns3: Change fw error code NOT_EXEC to NOT_SUPPORTED
+    - net: hns3: do not return GE PFC setting err when initializing
+    - net: hns3: add ETS TC weight setting in SSU module
+    - net: hns3: add statistics for PFC frames and MAC control frames
+    - net: hns3: fix PFC not setting problem for DCB module
+    - net: hns3: don't update packet statistics for packets dropped by hardware
+    - net: hns3: clear pci private data when unload hns3 driver
+    - net: hns3: add error handling in hclge_ieee_setets
+    - net: hns3: fix return value handle issue for hclge_set_loopback()
+    - net: hns3: fix broadcast promisc issue for revision 0x20
+    - net: hns3: After setting the loopback, add the status of getting MAC
+    - net: hns3: do reinitialization while mqprio configuration changed
+    - net: hns3: remove dcb_ops->map_update in hclge_dcb
+    - net: hns3: call hns3_nic_set_real_num_queue with netdev down
+    - net: hns3: add 8 BD limit for tx flow
+    - net: hns3: add initialization for nic state
+    - net: hns3: don't allow vf to enable promisc mode
+    - net: hns3: reuse the definition of l3 and l4 header info union
+    - net: hns3: fix VF dump register issue
+    - net: hns3: use the correct interface to stop|open port
+    - net: hns3: change hnae3_register_ae_dev() to int
+    - net: hns3: only support tc 0 for VF
+    - net: hns3: Fix NULL deref when unloading driver
+    - net: hns3: fix netif_napi_del() not do problem when unloading
+    - net: hns3: fix for rss result nonuniform
+    - net: hns3: fix improper error handling in the hclge_init_ae_dev()
+    - net: hns3: fix an issue for hclgevf_ae_get_hdev
+    - net: hns3: stop sending keep alive msg to PF when VF is resetting
+    - net: hns3: keep flow director state unchanged when reset
+    - net: hns3: Check for allocation failure
+    - net: hns3: fix a code style issue for hns3_update_new_int_gl()
+    - net: hns3: fix an issue for hns3_update_new_int_gl
+    - net: hns3: Modify parameter type from int to bool in set_gro_en
+    - net: hns3: code optimization for hclge_rx_buffer_calc
+    - net: hns3: add hclge_cmd_check_retval() to parse comman's return value
+    - net: hns3: move some set_bit statement into hclge_prepare_mac_addr
+    - net: hns3: fix a wrong checking in the hclge_tx_buffer_calc()
+    - net: hns3: fix the problem that the supported port is empty
+    - net: hns3: optimize the maximum TC macro
+    - net: hns3: don't allow user to change vlan filter state
+    - net: hns3: modify the upper limit judgment condition
+    - net: hns3: MAC table entry count function increases operation 0 value
+      protection measures
+    - net: hns3: make function hclge_set_all_vf_rst() static
+    - net: hns3: add pointer checking at the beginning of the exported functions.
+    - net: hns3: Check variable is valid before assigning it to another
+    - net: hns3: convert mac advertize and supported from u32 to link mode
+    - net: hns3: fix port info query issue for copper port
+    - net: hns3: modify print message of ssu common ecc errors
+    - net: hns3: some bugfix of ppu(rcb) ras errors
+    - net: hns3: enable 8~11th bit of mac common msi-x error
+    - net: hns3: fix 6th bit of ppp mpf abnormal errors
+    - net: hns3: Record VF unicast and multicast tables
+    - net: hns3: Record VF vlan tables
+    - net: hns3: uninitialize command queue while unloading PF driver
+    - net: hns3: clear command queue's registers when unloading VF driver
+    - net: hns3: add xps setting support for hns3 driver
+    - net: hns3: avoid mult + div op in critical data path
+    - net: hns3: limit some variable scope in critical data path
+    - net: hns3: remove some ops in struct hns3_nic_ops
+    - net: hns3: add unlikely for error handling in data path
+    - net: hns3: replace hnae3_set_bit and hnae3_set_field in data path
+    - net: hns3: remove hnae3_get_bit in data path
+    - net: hns3: add support to config depth for tx|rx ring separately
+    - net: hns3: enable VF VLAN filter for each VF when initializing
+    - net: hns3: fix get VF RSS issue
+    - net: hns3: fix setting of the hns reset_type for rdma hw errors
+    - net: hns3: fix improper error handling for hns3_client_start
+    - net: hns: use struct_size() in devm_kzalloc()
+    - net: hns3: Fix a logical vs bitwise typo
+    - net: hns3: add dma_rmb() for rx description
+    - net: hns3: fix to stop multiple HNS reset due to the AER changes
+
+  * Build Nvidia drivers in conjunction with kernel (LP: #1764792)
+    - [Packaging] dkms-build -- support building against packages in PPAs
+    - [Packaging] dkms-build: do not redownload files on subsequent passes
+    - [Packaging] dkms-build -- elide partial Built-Using information
+    - [Packaging] dkms-build -- remove retpoline data from final binary packages
+    - [Packaging] dkms-build--nvidia* -- check gcc version against primary build
+    - [Packaging] dkms-build -- add support for unversioned overrides
+    - [Packaging] dkms-build--nvidia-* -- convert to generic -N form
+    - [Packaging] fix-filenames -- handle exact string removal
+    - [Packaging] dkms-build--nvidia-N -- remove GCC versions
+
+  * Disco update: v5.0.1 upstream stable release (LP: #1819515)
+    - cpufreq: Use struct kobj_attribute instead of struct global_attr
+    - staging: erofs: fix mis-acted TAIL merging behavior
+    - binder: create node flag to request sender's security context
+    - USB: serial: option: add Telit ME910 ECM composition
+    - USB: serial: cp210x: add ID for Ingenico 3070
+    - USB: serial: ftdi_sio: add ID for Hjelmslund Electronics USB485
+    - driver core: Postpone DMA tear-down until after devres release
+    - staging: erofs: fix fast symlink w/o xattr when fs xattr is on
+    - staging: erofs: fix memleak of inode's shared xattr array
+    - staging: erofs: fix race of initializing xattrs of a inode at the same time
+    - staging: erofs: fix illegal address access under memory pressure
+    - staging: comedi: ni_660x: fix missing break in switch statement
+    - staging: wilc1000: fix to set correct value for 'vif_num'
+    - staging: android: ion: fix sys heap pool's gfp_flags
+    - staging: android: ashmem: Don't call fallocate() with ashmem_mutex held.
+    - staging: android: ashmem: Avoid range_alloc() allocation with ashmem_mutex
+      held.
+    - ip6mr: Do not call __IP6_INC_STATS() from preemptible context
+    - net: dsa: mv88e6xxx: add call to mv88e6xxx_ports_cmode_init to probe for new
+      DSA framework
+    - net: dsa: mv88e6xxx: handle unknown duplex modes gracefully in
+      mv88e6xxx_port_set_duplex
+    - net: dsa: mv8e6xxx: fix number of internal PHYs for 88E6x90 family
+    - net: mscc: Enable all ports in QSGMII
+    - net: sched: put back q.qlen into a single location
+    - net-sysfs: Fix mem leak in netdev_register_kobject
+    - qmi_wwan: Add support for Quectel EG12/EM12
+    - sctp: call iov_iter_revert() after sending ABORT
+    - team: Free BPF filter when unregistering netdev
+    - tipc: fix RDM/DGRAM connect() regression
+    - x86/CPU/AMD: Set the CPB bit unconditionally on F17h
+    - x86/boot/compressed/64: Do not read legacy ROM on EFI system
+    - tracing: Fix event filters and triggers to handle negative numbers
+    - xhci: tegra: Prevent error pointer dereference
+    - usb: xhci: Fix for Enabling USB ROLE SWITCH QUIRK on
+      INTEL_SUNRISEPOINT_LP_XHCI
+    - applicom: Fix potential Spectre v1 vulnerabilities
+    - alpha: wire up io_pgetevents system call
+    - MIPS: irq: Allocate accurate order pages for irq stack
+    - aio: Fix locking in aio_poll()
+    - xtensa: fix get_wchan
+    - gnss: sirf: fix premature wakeup interrupt enable
+    - USB: serial: cp210x: fix GPIO in autosuspend
+    - Revert "selftests: firmware: add CONFIG_FW_LOADER_USER_HELPER_FALLBACK to
+      config"
+    - Revert "selftests: firmware: remove use of non-standard diff -Z option"
+    - selftests: firmware: fix verify_reqs() return value
+    - Bluetooth: btrtl: Restore old logic to assume firmware is already loaded
+    - Bluetooth: Fix locking in bt_accept_enqueue() for BH context
+    - Linux 5.0.1
+
+  * sky2 ethernet card doesn't work after returning from suspend
+    (LP: #1807259) // sky2 ethernet card link not up after suspend
+    (LP: #1809843) // Disco update: v5.0.1 upstream stable release
+    (LP: #1819515)
+    - sky2: Disable MSI on Dell Inspiron 1545 and Gateway P-79
+
+  * tls selftest failures/hangs on i386 (LP: #1813607)
+    - [Config] CONFIG_TLS=n for i386
+
+  * CVE-2019-8980
+    - exec: Fix mem leak in kernel_read_file
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: selftests: net: Use 'ipproto ipv6-icmp' to match ICMPv6 headers
+    - [Config] enable nvidia build
+    - [Config] update gcc version to 8.3
+
+  * Miscellaneous upstream changes
+    - Revert "UBUNTU: SAUCE: selftests: pmtu: disable accept_dad for tests"
+
+ -- Thadeu Lima de Souza Cascardo <cascardo@canonical.com>  Tue, 12 Mar 2019 16:15:44 -0300
+
+linux (5.0.0-7.8) disco; urgency=medium
+
+  * linux: 5.0.0-7.8 -proposed tracker (LP: #1818519)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update helper scripts
+
+  * unnecessary request_queue freeze (LP: #1815733)
+    - block: avoid setting nr_requests to current value
+    - block: avoid setting none scheduler if it's already none
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: selftests: net: Don't fail test_vxlan_under_vrf on xfail
+    - update dkms package versions
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v5.0
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 04 Mar 2019 08:46:10 -0600
+
+linux (5.0.0-6.7) disco; urgency=medium
+
+  * linux: 5.0.0-6.7 -proposed tracker (LP: #1817585)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update helper scripts
+    - [Packaging] resync getabis
+
+  * installer does not support iSCSI iBFT (LP: #1817321)
+    - d-i: add iscsi_ibft to scsi-modules
+
+  * Silent "Unknown key" message when pressing keyboard backlight hotkey
+    (LP: #1817063)
+    - platform/x86: dell-wmi: Ignore new keyboard backlight change event
+
+  * Fix I219 doesn't get woken up after plugging ethernet cable (LP: #1817058)
+    - e1000e: Disable runtime PM on CNP+
+
+  * efi/arm/arm64: Allow SetVirtualAddressMap() to be omitted (LP: #1814982)
+    - efi/arm/arm64: Allow SetVirtualAddressMap() to be omitted
+
+  * CVE-2019-3460
+    - Bluetooth: Check L2CAP option sizes returned from l2cap_get_conf_opt
+
+  * CVE-2019-3459
+    - Bluetooth: Verify that l2cap_get_conf_opt provides large enough buffer
+
+  * kernel net tls selftest fails on 5.0 (LP: #1816716)
+    - SAUCE: Revert "selftests/tls: Add test for recv(PEEK) spanning across
+      multiple records"
+
+  * Please enable CONFIG_DMA_CMA=y on arm64 (LP: #1803206)
+    - [Config] annotations -- enforce CONFIG_DMA_CMA and update notes
+
+  * [19.04 FEAT] [LS1801] PCI Virtual function enablement (LP: #1814684)
+    - s390/pci: map IOV resources
+    - s390/pci: improve bar check
+
+  * glibc 2.28-0ubuntu1 ADT test failure with linux 5.0.0-1.2 (LP: #1813060)
+    - SAUCE: prevent a glibc test failure when looking for obsolete types on
+      headers
+
+  * Miscellaneous Ubuntu changes
+    - [Config] Enforce CONFIG_ZCRYPT_MULTIDEVNODES in annotations
+    - SAUCE: selftests: pmtu: disable accept_dad for tests
+    - SAUCE: arm64: add kernel config option to lock down when in Secure Boot mode
+    - SAUCE: selftests: net: Make test for VXLAN underlay in non-default VRF an
+      expected failure
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v5.0-rc8
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 25 Feb 2019 09:37:36 -0600
+
+linux (5.0.0-5.6) disco; urgency=medium
+
+  * [ALSA] [PATCH] System76 darp5 and oryp5 fixups (LP: #1815831)
+    - ALSA: hda/realtek - Headset microphone and internal speaker support for
+      System76 oryp5
+
+  * Miscellaneous Ubuntu changes
+    - [Config] Fix aufs menus in annotations file
+    - [Config] CONFIG_SAMPLE_TRACE_PRINTK=m
+    - [Config] Update annotations based on configs
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v5.0-rc7
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 18 Feb 2019 10:04:11 +0100
+
+linux (5.0.0-4.5) disco; urgency=medium
+
+  * linux-buildinfo: pull out ABI information into its own package
+    (LP: #1806380)
+    - [Packaging] autoreconstruct -- base tag is always primary mainline version
+
+  * [Packaging] Allow overlay of config annotations (LP: #1752072)
+    - [Packaging] config-check: Add an include directive
+
+  * Miscellaneous Ubuntu changes
+    - hio -- stub out BIOVEC_PHYS_MERGEABLE for 4.20+
+    - hio -- replace use of do_gettimeofday()
+    - hio -- part_round_stats() removed in 5.0
+    - hio -- device_add_disk() grew a 'groups' argument in 4.20
+    - enable hio build
+    - Revert "UBUNTU: [Packaging] autoreconstruct -- base tag is always primary
+      mainline version"
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v5.0-rc6
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Tue, 12 Feb 2019 08:15:32 -0600
+
+linux (5.0.0-3.4) disco; urgency=medium
+
+  * CONFIG_TEST_BPF is disabled (LP: #1813955)
+    - [Config]: Reenable TEST_BPF
+
+  * Ignore "incomplete report" from Elan touchpanels (LP: #1813733)
+    - HID: i2c-hid: Ignore input report if there's no data present on Elan
+      touchpanels
+
+  * SecureBoot support for arm64 (LP: #1804481)
+    - Build signed kernels for arm64
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: selftests: net: fix "from" match test in fib_rule_tests.sh
+    - [Config] CONFIG_PCMCIA=n for arm64 and s390x
+    - [Config] CONFIG_SERIAL_SC16IS7XX=n for s390x
+    - [Config] disable I2C TPM drivers for s390x
+    - [Config] CONFIG_RAPIDIO=n for s390x
+    - [Config] CONFIG_DMADEVICES=n for s390x
+    - [Config] disable gpio drivers for s390x
+    - [Config] CONFIG_SENSORS_OCC_P8_I2C=m for ppc64el
+    - [Config] disable I2C hardware drivers for s390x
+    - [Config] CONFIG_I3C=n for s390x
+    - [Config] CONFIG_SERIO=n for s390x
+    - [Config] disable misc drivers for s390x
+    - [Config] disable EEPROM drivers for s390x
+    - [Config] disable MFD drivers for s390x
+    - [Config] CONFIG_NVMEM=n for s390x
+    - [Config] CONFIG_MLXSW_I2C=n for s390x
+    - [Config] CONFIG_NET_VENDOR_MICROCHIP=n for s390x
+    - [Config] CONFIG_PPP=n for s390x
+    - [Config] CONFIG_PCCARD=n for s390x
+    - [Config] CONFIG_PCI_MESON=y
+    - [Config] CONFIG_SCSI_MYRB=n for s390x
+    - [Config] CONFIG_REGULATOR=n for s390x
+    - [Config] CONFIG_ZIIRAVE_WATCHDOG=n for s390x
+    - [Config] CONFIG_NCSI_OEM_CMD_GET_MAC=y
+    - [Config] update annotations following config review
+    - [Packaging] remove handoff check for uefi signing
+    - [Packaging] decompress gzipped efi images in signing tarball
+    - vbox-update: allow leading whitespace when fixing up KERN_DIR
+    - ubuntu: vbox -- update to 6.0.4-dfsg-3
+    - vbox: remove remount check in sf_read_super_aux()
+    - enable vbox build
+    - [Config] CONFIG_ANDROID_BINDER_DEVICES=""
+    - SAUCE: import aufs driver
+    - [Config]: Enable aufs
+    - [Config] relocate aufs annotations to menu
+    - [Config] remove unmatched configs from annotations
+    - [Config] fix up abi for removed modules
+    - SAUCE: (efi-lockdown) Enforce module signatures if the kernel is locked down
+    - SAUCE: (efi-lockdown) module: remove support for having IMA validate modules
+    - SAUCE: (efi-lockdown) Move EFI signature blob parser to shared location
+    - SAUCE: (efi-lockdown) MODSIGN: Import certificates from UEFI Secure Boot
+    - SAUCE: (efi-lockdown) MODSIGN: Allow the "db" UEFI variable to be suppressed
+    - [Config] (efi-lockdown) enable importing of efi certificates for module sig
+      verification
+
+  * Miscellaneous upstream changes
+    - binder: fix CONFIG_ANDROID_BINDER_DEVICES
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v5.0-rc5
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Tue, 05 Feb 2019 14:26:12 -0600
+
+linux (5.0.0-2.3) disco; urgency=medium
+
+  * kernel oops in bcache module (LP: #1793901)
+    - SAUCE: bcache: never writeback a discard operation
+
+  * Enable sound card power saving by default (LP: #1804265)
+    - [Config] CONFIG_SND_HDA_POWER_SAVE_DEFAULT=1
+
+  * Miscellaneous Ubuntu changes
+    - Revert "UBUNTU: SAUCE: selftests: disable some failing networking tests"
+    - SAUCE: ashmem: turn into module
+    - SAUCE: binder: turn into module
+    - SAUCE: binder: give binder_alloc its own debug mask file
+    - [Config] enable binder and ashmem as modules
+    - SAUCE: selftests: net: replace AF_MAX with INT_MAX in socket.c
+    - SAUCE: selftests/ftrace: Fix tab expansion in trace_marker snapshot trigger
+      test
+    - update dkms package versions
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v5.0-rc4
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Tue, 29 Jan 2019 06:57:32 -0600
+
+linux (5.0.0-1.2) disco; urgency=medium
+
+  * Fix non-working QCA Rome Bluetooth after S3 (LP: #1812812)
+    - USB: Add new USB LPM helpers
+    - USB: Consolidate LPM checks to avoid enabling LPM twice
+
+  * bluetooth controller not detected with 4.15 kernel (LP: #1810797)
+    - SAUCE: btqcomsmd: introduce BT_QCOMSMD_HACK
+    - [Config] arm64: snapdragon: BT_QCOMSMD_HACK=y
+
+  * [19.04 FEAT| Enable virtio-gpu for s390x (LP: #1799467)
+    - [Config] enable virtio-gpu for s390x
+
+  * Crash on "ip link add foo type ipip" (LP: #1811803)
+    - SAUCE: fan: Fix NULL pointer dereference
+
+  * Fix not working Goodix touchpad (LP: #1811929)
+    - HID: i2c-hid: Disable runtime PM on Goodix touchpad
+
+  * Miscellaneous Ubuntu changes
+    - update dkms package versions
+    - enable zfs build
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v5.0-rc3
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Tue, 22 Jan 2019 13:56:17 -0600
+
+linux (5.0.0-0.1) disco; urgency=medium
+
+  * Build Nvidia drivers in conjunction with kernel (LP: #1764792)
+    - [Packaging] dkms -- add per package post-process step
+    - [Packaging] dkms -- switch to a consistent build prefix length and strip
+    - [Packaging] nvidia -- build and sign nvidia packages and ship signatures
+    - [Packaging] nvidia -- make nvidia package version explicit
+
+  * Add support for ALC3277 codec on new Dell edge gateways (LP: #1807334)
+    - [Config] CONFIG_SND_SOC_INTEL_KBL_RT5660_MACH=m
+
+  * RTL8822BE WiFi Disabled in Kernel 4.18.0-12 (LP: #1806472)
+    - [Config] CONFIG_RTLWIFI_DEBUG_ST=n
+
+  * Miscellaneous Ubuntu changes
+    - ubuntu -- disable vbox build
+    - ubuntu -- disable hio build
+    - Disable zfs build
+    - SAUCE: import aufs driver
+    - update dkms package versions
+    - [Config] disable aufs config options
+    - [Config] disable nvidia build
+    - update dropped.txt
+    - [Packaging] disable nvidia dkms builds for mainline
+    - SAUCE: (efi-lockdown) Add the ability to lock down access to the running
+      kernel image
+    - SAUCE: (efi-lockdown) Add a SysRq option to lift kernel lockdown
+    - SAUCE: (efi-lockdown) Restrict /dev/{mem,kmem,port} when the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) kexec_load: Disable at runtime if the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) hibernate: Disable when the kernel is locked down
+    - SAUCE: (efi-lockdown) uswsusp: Disable when the kernel is locked down
+    - SAUCE: (efi-lockdown) PCI: Lock down BAR access when the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) x86: Lock down IO port access when the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) x86/msr: Restrict MSR access when the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) ACPI: Limit access to custom_method when the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) acpi: Ignore acpi_rsdp kernel param when the kernel
+      has been locked down
+    - SAUCE: (efi-lockdown) acpi: Disable ACPI table override if the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) acpi: Disable APEI error injection if the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) Prohibit PCMCIA CIS storage when the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) Lock down TIOCSSERIAL
+    - SAUCE: (efi-lockdown) Lock down module params that specify hardware
+      parameters (eg. ioport)
+    - SAUCE: (efi-lockdown) x86/mmiotrace: Lock down the testmmiotrace module
+    - SAUCE: (efi-lockdown) Lock down /proc/kcore
+    - SAUCE: (efi-lockdown) Lock down kprobes
+    - SAUCE: (efi-lockdown) Lock down perf
+    - SAUCE: (efi-lockdown) debugfs: Restrict debugfs when the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) debugfs: avoid EPERM when no open file operation
+      defined
+    - SAUCE: (efi-lockdown) KEYS: Allow unrestricted boot-time addition of keys to
+      secondary keyring
+    - SAUCE: (efi-lockdown) Make get_cert_list() not complain about cert lists
+      that aren't present.
+    - SAUCE: (efi-lockdown) Add efi_status_to_str() and rework
+      efi_status_to_err().
+    - SAUCE: (efi-lockdown) Make get_cert_list() use efi_status_to_str() to print
+      error messages.
+    - SAUCE: (efi-lockdown) Copy secure_boot flag in boot params across kexec
+      reboot
+    - SAUCE: (efi-lockdown) efi: Add an EFI_SECURE_BOOT flag to indicate secure
+      boot mode
+    - SAUCE: (efi-lockdown) efi: Lock down the kernel if booted in secure boot
+      mode
+    - SAUCE: (efi-lockdown) efi: Sanitize boot_params in efi stub
+    - [Config] set config options for efi lockdown
+    - Revert "UBUNTU: SAUCE: import aufs driver"
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v5.0-rc2
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Thu, 17 Jan 2019 12:31:29 -0600
+
+linux (5.0.0-0.0) disco; urgency=medium
+
+  * Dummy entry.
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Wed, 16 Jan 2019 14:48:05 -0600
+
+linux (4.20.0-2.3) disco; urgency=medium
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.20
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Thu, 03 Jan 2019 12:11:43 -0600
+
+linux (4.20.0-1.2) disco; urgency=medium
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update helper scripts
+
+  * Power leakage at S5 with Qualcomm Atheros QCA9377 802.11ac Wireless Network
+    Adapter (LP: #1805607)
+    - SAUCE: ath10k: provide reset function for QCA9377 chip
+
+  * zfs/spl build in conjunction with the kernel from DKMS source (LP: #1807378)
+    - [Packaging] dkms -- dkms package build packaging support
+    - [Packaging] dkms -- save build objects artifacts for validation
+    - [Packaging] dkms -- add general Built-Using: support
+    - [Packaging] simplify Provides comma handling
+    - [Packaging] zfs/spl -- remove packaging support for incorporated source
+    - [Packaging] zfs/spl -- remove incorporated source
+    - [Packaging] zfs/spl -- build via dkms
+    - [Packaging] zfs/spl -- make zfs package version explicit
+    - [Packaging] update-version-dkms -- sync archive versions to package
+
+  * Miscellaneous Ubuntu changes
+    - [Packaging] update-version-dkms -- fix getting distrbution from changelog
+    - update dkms package versions
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.20-rc6
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Tue, 11 Dec 2018 11:33:08 -0600
+
+linux (4.20.0-0.1) disco; urgency=medium
+
+  * Overlayfs in user namespace leaks directory content of inaccessible
+    directories (LP: #1793458) // CVE-2018-6559
+    - Revert "ovl: relax permission checking on underlying layers"
+    - SAUCE: overlayfs: ensure mounter privileges when reading directories
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: (efi-lockdown) Add the ability to lock down access to the running
+      kernel image
+    - SAUCE: (efi-lockdown) Add a SysRq option to lift kernel lockdown
+    - SAUCE: (efi-lockdown) Enforce module signatures if the kernel is locked down
+    - SAUCE: (efi-lockdown) Restrict /dev/{mem,kmem,port} when the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) kexec_load: Disable at runtime if the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) hibernate: Disable when the kernel is locked down
+    - SAUCE: (efi-lockdown) uswsusp: Disable when the kernel is locked down
+    - SAUCE: (efi-lockdown) PCI: Lock down BAR access when the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) x86: Lock down IO port access when the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) x86/msr: Restrict MSR access when the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) ACPI: Limit access to custom_method when the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) acpi: Ignore acpi_rsdp kernel param when the kernel
+      has been locked down
+    - SAUCE: (efi-lockdown) acpi: Disable ACPI table override if the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) acpi: Disable APEI error injection if the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) Prohibit PCMCIA CIS storage when the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) Lock down TIOCSSERIAL
+    - SAUCE: (efi-lockdown) Lock down module params that specify hardware
+      parameters (eg. ioport)
+    - SAUCE: (efi-lockdown) x86/mmiotrace: Lock down the testmmiotrace module
+    - SAUCE: (efi-lockdown) Lock down /proc/kcore
+    - SAUCE: (efi-lockdown) Lock down kprobes
+    - SAUCE: (efi-lockdown) Lock down perf
+    - SAUCE: (efi-lockdown) debugfs: Restrict debugfs when the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) KEYS: Allow unrestricted boot-time addition of keys to
+      secondary keyring
+    - SAUCE: (efi-lockdown) efi: Add EFI signature data types
+    - SAUCE: (efi-lockdown) efi: Add an EFI signature blob parser
+    - SAUCE: (efi-lockdown) MODSIGN: Import certificates from UEFI Secure Boot
+    - SAUCE: (efi-lockdown) MODSIGN: Allow the "db" UEFI variable to be suppressed
+    - SAUCE: (efi-lockdown) Make get_cert_list() not complain about cert lists
+      that aren't present.
+    - SAUCE: (efi-lockdown) Add efi_status_to_str() and rework
+      efi_status_to_err().
+    - SAUCE: (efi-lockdown) Make get_cert_list() use efi_status_to_str() to print
+      error messages.
+    - SAUCE: (efi-lockdown) Copy secure_boot flag in boot params across kexec
+      reboot
+    - SAUCE: (efi-lockdown) efi: Add an EFI_SECURE_BOOT flag to indicate secure
+      boot mode
+    - SAUCE: (efi-lockdown) efi: Lock down the kernel if booted in secure boot
+      mode
+    - SAUCE: (efi-lockdown) Fix for module sig verification
+    - SAUCE: (efi-lockdown) efi: Sanitize boot_params in efi stub
+    - SAUCE: Import aufs driver
+    - ubuntu: vbox -- update to 5.2.22-dfsg-2
+    - ubuntu -- disable vbox build
+    - ubuntu -- disable hio build
+    - Disable zfs build
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.20-rc5
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Fri, 07 Dec 2018 07:13:42 -0600
+
+linux (4.20.0-0.0) disco; urgency=medium
+
+  * Dummy entry.
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Thu, 06 Dec 2018 10:20:19 -0600
+
+linux (4.19.0-8.9) disco; urgency=medium
+
+  * linux: 4.19.0-8.9 -proposed tracker (LP: #1806952)
+
+  * Workaround CSS timeout on AMD SNPS 3.0 xHC (LP: #1806838)
+    - xhci: workaround CSS timeout on AMD SNPS 3.0 xHC
+
+  * Fix Intel I210 doesn't work when ethernet cable gets plugged (LP: #1806818)
+    - igb: Fix an issue that PME is not enabled during runtime suspend
+
+  * The line-out on the Dell Dock station can't work (LP: #1806532)
+    - ALSA: usb-audio: Add vendor and product name for Dell WD19 Dock
+
+  * CVE-2018-19407
+    - KVM: X86: Fix scan ioapic use-before-initialization
+
+  * PC SN720 NVMe WDC 256GB consumes more power in S2Idle than during long idle
+    (LP: #1805775)
+    - SAUCE: pci/nvme: prevent WDC PC SN720 NVMe from entering D3 and being
+      disabled
+
+  * Disco update: 4.19.6 upstream stable release (LP: #1806909)
+    - HID: steam: remove input device when a hid client is running.
+    - efi/libstub: arm: support building with clang
+    - usb: core: Fix hub port connection events lost
+    - usb: dwc3: gadget: fix ISOC TRB type on unaligned transfers
+    - usb: dwc3: gadget: Properly check last unaligned/zero chain TRB
+    - usb: dwc3: core: Clean up ULPI device
+    - usb: dwc3: Fix NULL pointer exception in dwc3_pci_remove()
+    - xhci: Fix leaking USB3 shared_hcd at xhci removal
+    - xhci: handle port status events for removed USB3 hcd
+    - xhci: Add check for invalid byte size error when UAS devices are connected.
+    - usb: xhci: fix uninitialized completion when USB3 port got wrong status
+    - usb: xhci: fix timeout for transition from RExit to U0
+    - xhci: Add quirk to workaround the errata seen on Cavium Thunder-X2 Soc
+    - usb: xhci: Prevent bus suspend if a port connect change or polling state is
+      detected
+    - ALSA: oss: Use kvzalloc() for local buffer allocations
+    - MAINTAINERS: Add Sasha as a stable branch maintainer
+    - Documentation/security-bugs: Clarify treatment of embargoed information
+    - Documentation/security-bugs: Postpone fix publication in exceptional cases
+    - mmc: sdhci-pci: Try "cd" for card-detect lookup before using NULL
+    - mmc: sdhci-pci: Workaround GLK firmware failing to restore the tuning value
+    - gpio: don't free unallocated ida on gpiochip_add_data_with_key() error path
+    - iwlwifi: fix wrong WGDS_WIFI_DATA_SIZE
+    - iwlwifi: mvm: support sta_statistics() even on older firmware
+    - iwlwifi: mvm: fix regulatory domain update when the firmware starts
+    - iwlwifi: mvm: don't use SAR Geo if basic SAR is not used
+    - brcmfmac: fix reporting support for 160 MHz channels
+    - opp: ti-opp-supply: Dynamically update u_volt_min
+    - opp: ti-opp-supply: Correct the supply in _get_optimal_vdd_voltage call
+    - tools/power/cpupower: fix compilation with STATIC=true
+    - v9fs_dir_readdir: fix double-free on p9stat_read error
+    - selinux: Add __GFP_NOWARN to allocation at str_read()
+    - Input: synaptics - avoid using uninitialized variable when probing
+    - bfs: add sanity check at bfs_fill_super()
+    - sctp: clear the transport of some out_chunk_list chunks in
+      sctp_assoc_rm_peer
+    - gfs2: Don't leave s_fs_info pointing to freed memory in init_sbd
+    - llc: do not use sk_eat_skb()
+    - mm: don't warn about large allocations for slab
+    - mm/memory.c: recheck page table entry with page table lock held
+    - tcp: do not release socket ownership in tcp_close()
+    - drm/fb-helper: Blacklist writeback when adding connectors to fbdev
+    - drm/amdgpu: Add missing firmware entry for HAINAN
+    - drm/vc4: Set ->legacy_cursor_update to false when doing non-async updates
+    - drm/amdgpu: Fix oops when pp_funcs->switch_power_profile is unset
+    - drm/i915: Disable LP3 watermarks on all SNB machines
+    - drm/ast: change resolution may cause screen blurred
+    - drm/ast: fixed cursor may disappear sometimes
+    - drm/ast: Remove existing framebuffers before loading driver
+    - can: flexcan: Unlock the MB unconditionally
+    - can: dev: can_get_echo_skb(): factor out non sending code to
+      __can_get_echo_skb()
+    - can: dev: __can_get_echo_skb(): replace struct can_frame by canfd_frame to
+      access frame length
+    - can: dev: __can_get_echo_skb(): Don't crash the kernel if can_priv::echo_skb
+      is accessed out of bounds
+    - can: dev: __can_get_echo_skb(): print error message, if trying to echo non
+      existing skb
+    - can: rx-offload: introduce can_rx_offload_get_echo_skb() and
+      can_rx_offload_queue_sorted() functions
+    - can: rx-offload: rename can_rx_offload_irq_queue_err_skb() to
+      can_rx_offload_queue_tail()
+    - can: flexcan: use can_rx_offload_queue_sorted() for flexcan_irq_bus_*()
+    - can: flexcan: handle tx-complete CAN frames via rx-offload infrastructure
+    - can: raw: check for CAN FD capable netdev in raw_sendmsg()
+    - can: hi311x: Use level-triggered interrupt
+    - can: flexcan: Always use last mailbox for TX
+    - can: flexcan: remove not needed struct flexcan_priv::tx_mb and struct
+      flexcan_priv::tx_mb_idx
+    - ACPICA: AML interpreter: add region addresses in global list during
+      initialization
+    - IB/hfi1: Eliminate races in the SDMA send error path
+    - fsnotify: generalize handling of extra event flags
+    - fanotify: fix handling of events on child sub-directory
+    - pinctrl: meson: fix pinconf bias disable
+    - pinctrl: meson: fix gxbb ao pull register bits
+    - pinctrl: meson: fix gxl ao pull register bits
+    - pinctrl: meson: fix meson8 ao pull register bits
+    - pinctrl: meson: fix meson8b ao pull register bits
+    - tools/testing/nvdimm: Fix the array size for dimm devices.
+    - scsi: lpfc: fix remoteport access
+    - scsi: hisi_sas: Remove set but not used variable 'dq_list'
+    - KVM: PPC: Move and undef TRACE_INCLUDE_PATH/FILE
+    - cpufreq: imx6q: add return value check for voltage scale
+    - rtc: cmos: Do not export alarm rtc_ops when we do not support alarms
+    - rtc: pcf2127: fix a kmemleak caused in pcf2127_i2c_gather_write
+    - crypto: simd - correctly take reqsize of wrapped skcipher into account
+    - floppy: fix race condition in __floppy_read_block_0()
+    - powerpc/io: Fix the IO workarounds code to work with Radix
+    - sched/fair: Fix cpu_util_wake() for 'execl' type workloads
+    - perf/x86/intel/uncore: Add more IMC PCI IDs for KabyLake and CoffeeLake CPUs
+    - block: copy ioprio in __bio_clone_fast() and bounce
+    - SUNRPC: Fix a bogus get/put in generic_key_to_expire()
+    - riscv: add missing vdso_install target
+    - RISC-V: Silence some module warnings on 32-bit
+    - drm/amdgpu: fix bug with IH ring setup
+    - kdb: Use strscpy with destination buffer size
+    - NFSv4: Fix an Oops during delegation callbacks
+    - powerpc/numa: Suppress "VPHN is not supported" messages
+    - efi/arm: Revert deferred unmap of early memmap mapping
+    - z3fold: fix possible reclaim races
+    - mm, memory_hotplug: check zone_movable in has_unmovable_pages
+    - tmpfs: make lseek(SEEK_DATA/SEK_HOLE) return ENXIO with a negative offset
+    - mm, page_alloc: check for max order in hot path
+    - dax: Avoid losing wakeup in dax_lock_mapping_entry
+    - include/linux/pfn_t.h: force '~' to be parsed as an unary operator
+    - tty: wipe buffer.
+    - tty: wipe buffer if not echoing data
+    - gfs2: Fix iomap buffer head reference counting bug
+    - rcu: Make need_resched() respond to urgent RCU-QS needs
+    - media: ov5640: Re-work MIPI startup sequence
+    - media: ov5640: Fix timings setup code
+    - media: ov5640: fix exposure regression
+    - media: ov5640: fix auto gain & exposure when changing mode
+    - media: ov5640: fix wrong binning value in exposure calculation
+    - media: ov5640: fix auto controls values when switching to manual mode
+    - Linux 4.19.6
+
+  * linux-buildinfo: pull out ABI information into its own package
+    (LP: #1806380)
+    - [Packaging] limit preparation to linux-libc-dev in headers
+    - [Packaging] commonise debhelper invocation
+    - [Packaging] ABI -- accumulate abi information at the end of the build
+    - [Packaging] buildinfo -- add basic build information
+    - [Packaging] buildinfo -- add firmware information to the flavour ABI
+    - [Packaging] buildinfo -- add compiler information to the flavour ABI
+    - [Packaging] buildinfo -- add buildinfo support to getabis
+    - [Packaging] getabis -- handle all known package combinations
+    - [Packaging] getabis -- support parsing a simple version
+
+  * linux packages should own /usr/lib/linux/triggers (LP: #1770256)
+    - [Packaging] own /usr/lib/linux/triggers
+
+  * Miscellaneous upstream changes
+    - blk-mq: fix corruption with direct issue
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Wed, 05 Dec 2018 09:18:30 -0600
+
+linux (4.19.0-7.8) disco; urgency=medium
+
+  * linux: 4.19.0-7.8 -proposed tracker (LP: #1805465)
+
+  * Fix and issue that LG I2C touchscreen stops working after reboot
+    (LP: #1805085)
+    - HID: i2c-hid: Disable runtime PM for LG touchscreen
+
+  * click/pop noise in the headphone on several lenovo laptops (LP: #1805079) //
+    click/pop noise in the headphone on several lenovo laptops (LP: #1805079)
+    - ALSA: hda/realtek - fix the pop noise on headphone for lenovo laptops
+
+  * Regression: hinic performance degrades over time (LP: #1805248)
+    - Revert "net-next/hinic: add checksum offload and TSO support"
+
+  * Disco update: 4.19.5 upstream stable release (LP: #1805461)
+    - drm/i915: Replace some PAGE_SIZE with I915_GTT_PAGE_SIZE
+    - cifs: don't dereference smb_file_target before null check
+    - cifs: fix return value for cifs_listxattr
+    - arm64: kprobe: make page to RO mode when allocate it
+    - block: brd: associate with queue until adding disk
+    - net: hns3: bugfix for rtnl_lock's range in the hclgevf_reset()
+    - net: hns3: bugfix for rtnl_lock's range in the hclge_reset()
+    - net: hns3: bugfix for handling mailbox while the command queue reinitialized
+    - net: hns3: bugfix for the initialization of command queue's spin lock
+    - ixgbe: fix MAC anti-spoofing filter after VFLR
+    - reiserfs: propagate errors from fill_with_dentries() properly
+    - hfs: prevent btree data loss on root split
+    - hfsplus: prevent btree data loss on root split
+    - perf unwind: Take pgoff into account when reporting elf to libdwfl
+    - um: Give start_idle_thread() a return code
+    - drm/edid: Add 6 bpc quirk for BOE panel.
+    - afs: Handle EIO from delivery function
+    - platform/x86: intel_telemetry: report debugfs failure
+    - clk: fixed-rate: fix of_node_get-put imbalance
+    - perf symbols: Set PLT entry/header sizes properly on Sparc
+    - fs/exofs: fix potential memory leak in mount option parsing
+    - clk: samsung: exynos5420: Enable PERIS clocks for suspend
+    - apparmor: Fix uninitialized value in aa_split_fqname
+    - x86/earlyprintk: Add a force option for pciserial device
+    - platform/x86: acerhdf: Add BIOS entry for Gateway LT31 v1.3307
+    - clk: meson-axg: pcie: drop the mpll3 clock parent
+    - arm64: percpu: Initialize ret in the default case
+    - clk: meson: clk-pll: drop CLK_GET_RATE_NOCACHE where unnecessary
+    - clk: renesas: r9a06g032: Fix UART34567 clock rate
+    - clk: ti: fix OF child-node lookup
+    - serial: sh-sci: Fix receive on SCIFA/SCIFB variants with DMA
+    - netfilter: ipv6: fix oops when defragmenting locally generated fragments
+    - netfilter: bridge: define INT_MIN & INT_MAX in userspace
+    - s390/decompressor: add missing FORCE to build targets
+    - s390/vdso: add missing FORCE to build targets
+    - HID: i2c-hid: Add a small delay after sleep command for Raydium touchpanel
+    - Revert "HID: add NOGET quirk for Eaton Ellipse MAX UPS"
+    - HID: alps: allow incoming reports when only the trackstick is opened
+    - Revert "netfilter: nft_numgen: add map lookups for numgen random operations"
+    - netfilter: ipset: list:set: Decrease refcount synchronously on deletion and
+      replace
+    - netfilter: ipset: actually allow allowable CIDR 0 in hash:net,port,net
+    - netfilter: ipset: fix ip_set_list allocation failure
+    - s390/mm: fix mis-accounting of pgtable_bytes
+    - s390/mm: Fix ERROR: "__node_distance" undefined!
+    - bpf: fix bpf_prog_get_info_by_fd to return 0 func_lens for unpriv
+    - netfilter: ipset: Correct rcu_dereference() call in ip_set_put_comment()
+    - netfilter: xt_IDLETIMER: add sysfs filename checking routine
+    - netfilter: ipset: Fix calling ip_set() macro at dumping
+    - netfilter: nft_compat: ebtables 'nat' table is normal chain type
+    - s390/qeth: fix HiperSockets sniffer
+    - s390/qeth: unregister netdevice only when registered
+    - net: hns3: Fix for out-of-bounds access when setting pfc back pressure
+    - hwmon: (ibmpowernv) Remove bogus __init annotations
+    - ARM: dts: imx6sll: fix typo for fsl,imx6sll-i2c node
+    - ARM: dts: fsl: Fix improperly quoted stdout-path values
+    - Revert "drm/exynos/decon5433: implement frame counter"
+    - arm64: dts: renesas: r8a7795: add missing dma-names on hscif2
+    - arm64: dts: renesas: condor: switch from EtherAVB to GEther
+    - xen/grant-table: Fix incorrect gnttab_dma_free_pages() pr_debug message
+    - clk: fixed-factor: fix of_node_get-put imbalance
+    - mtd: nand: Fix nanddev_pos_next_page() kernel-doc header
+    - lib/raid6: Fix arm64 test build
+    - drm/amd/display: Stop leaking planes
+    - block: Clear kernel memory before copying to user
+    - drm/amd/display: Drop reusing drm connector for MST
+    - drm/amd/amdgpu/dm: Fix dm_dp_create_fake_mst_encoder()
+    - s390/perf: Change CPUM_CF return code in event init function
+    - ceph: quota: fix null pointer dereference in quota check
+    - of/device: Really only set bus DMA mask when appropriate
+    - nvme: make sure ns head inherits underlying device limits
+    - i2c: omap: Enable for ARCH_K3
+    - i2c: qcom-geni: Fix runtime PM mismatch with child devices
+    - sched/core: Take the hotplug lock in sched_init_smp()
+    - perf tools: Fix undefined symbol scnprintf in libperf-jvmti.so
+    - perf tools: Do not zero sample_id_all for group members
+    - ice: Fix dead device link issue with flow control
+    - ice: Fix the bytecount sent to netdev_tx_sent_queue
+    - ice: Change req_speeds to be u16
+    - i40e: restore NETIF_F_GSO_IPXIP[46] to netdev features
+    - qed: Fix memory/entry leak in qed_init_sp_request()
+    - qed: Fix blocking/unlimited SPQ entries leak
+    - qed: Fix SPQ entries not returned to pool in error flows
+    - qed: Fix potential memory corruption
+    - net: stmmac: Fix RX packet size > 8191
+    - net: aquantia: fix potential IOMMU fault after driver unbind
+    - net: aquantia: fixed enable unicast on 32 macvlan
+    - net: aquantia: invalid checksumm offload implementation
+    - kbuild: deb-pkg: fix too low build version number
+    - Revert "scripts/setlocalversion: git: Make -dirty check more robust"
+    - SUNRPC: drop pointless static qualifier in xdr_get_next_encode_buffer()
+    - x86/mm: Move LDT remap out of KASLR region on 5-level paging
+    - x86/ldt: Unmap PTEs for the slot before freeing LDT pages
+    - x86/ldt: Remove unused variable in map_ldt_struct()
+    - media: v4l: event: Add subscription to list before calling "add" operation
+    - MIPS: OCTEON: cavium_octeon_defconfig: re-enable OCTEON USB driver
+    - RISC-V: Fix raw_copy_{to,from}_user()
+    - uio: Fix an Oops on load
+    - ALSA: hda/realtek - Add quirk entry for HP Pavilion 15
+    - ALSA: hda/ca0132 - Call pci_iounmap() instead of iounmap()
+    - can: kvaser_usb: Fix accessing freed memory in kvaser_usb_start_xmit()
+    - can: kvaser_usb: Fix potential uninitialized variable use
+    - usb: cdc-acm: add entry for Hiro (Conexant) modem
+    - USB: Wait for extra delay time after USB_PORT_FEAT_RESET for quirky hub
+    - usb: quirks: Add delay-init quirk for Corsair K70 LUX RGB
+    - misc: atmel-ssc: Fix section annotation on atmel_ssc_get_driver_data
+    - USB: misc: appledisplay: add 20" Apple Cinema Display
+    - gnss: serial: fix synchronous write timeout
+    - gnss: sirf: fix synchronous write timeout
+    - mtd: rawnand: atmel: fix OF child-node lookup
+    - drivers/misc/sgi-gru: fix Spectre v1 vulnerability
+    - ACPI / platform: Add SMB0001 HID to forbidden_id_list
+    - HID: uhid: forbid UHID_CREATE under KERNEL_DS or elevated privileges
+    - HID: Add quirk for Primax PIXART OEM mice
+    - HID: Add quirk for Microsoft PIXART OEM mouse
+    - libceph: fall back to sendmsg for slab pages
+    - mt76x0: run vco calibration for each channel configuration
+    - Linux 4.19.5
+
+  * Miscellaneous Ubuntu changes
+    - Revert "UBUNTU: Build signed kernels for arm64"
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Tue, 27 Nov 2018 10:38:34 -0600
+
+linux (4.19.0-6.7) disco; urgency=medium
+
+  * linux: 4.19.0-6.7 -proposed tracker (LP: #1805195)
+
+  * SecureBoot support for arm64 (LP: #1804481)
+    - Build signed kernels for arm64
+
+  * Add pointstick support for Cirque Touchpad (LP: #1805081)
+    - HID: multitouch: Add pointstick support for Cirque Touchpad
+
+  * Power consumption during s2idle is higher than long idle (Intel SSDPEKKF)
+    (LP: #1804588)
+    - SAUCE: pci: prevent Intel NVMe SSDPEKKF from entering D3
+    - SAUCE: nvme: add quirk to not call disable function when suspending
+
+  * Disco update: 4.19.4 upstream stable release (LP: #1805159)
+    - flow_dissector: do not dissect l4 ports for fragments
+    - ibmvnic: fix accelerated VLAN handling
+    - ip_tunnel: don't force DF when MTU is locked
+    - ipv6: fix a dst leak when removing its exception
+    - ipv6: Fix PMTU updates for UDP/raw sockets in presence of VRF
+    - net: bcmgenet: protect stop from timeout
+    - net-gro: reset skb->pkt_type in napi_reuse_skb()
+    - sctp: not allow to set asoc prsctp_enable by sockopt
+    - tcp: Fix SOF_TIMESTAMPING_RX_HARDWARE to use the latest timestamp during TCP
+      coalescing
+    - tg3: Add PHY reset for 5717/5719/5720 in change ring and flow control paths
+    - tipc: don't assume linear buffer when reading ancillary data
+    - tipc: fix lockdep warning when reinitilaizing sockets
+    - tuntap: fix multiqueue rx
+    - net: systemport: Protect stop from timeout
+    - net/sched: act_pedit: fix memory leak when IDR allocation fails
+    - net: sched: cls_flower: validate nested enc_opts_policy to avoid warning
+    - tipc: fix link re-establish failure
+    - net/mlx5e: Don't match on vlan non-existence if ethertype is wildcarded
+    - net/mlx5e: Claim TC hw offloads support only under a proper build config
+    - net/mlx5e: Adjust to max number of channles when re-attaching
+    - net/mlx5e: RX, verify received packet size in Linear Striding RQ
+    - Revert "sctp: remove sctp_transport_pmtu_check"
+    - net/mlx5e: Always use the match level enum when parsing TC rule match
+    - net/mlx5e: Fix selftest for small MTUs
+    - net/mlx5e: Removed unnecessary warnings in FEC caps query
+    - inet: frags: better deal with smp races
+    - l2tp: fix a sock refcnt leak in l2tp_tunnel_register
+    - net/mlx5: IPSec, Fix the SA context hash key
+    - net/mlx5e: IPoIB, Reset QP after channels are closed
+    - net: dsa: mv88e6xxx: Fix clearing of stats counters
+    - net: phy: realtek: fix RTL8201F sysfs name
+    - sctp: define SCTP_SS_DEFAULT for Stream schedulers
+    - net: qualcomm: rmnet: Fix incorrect assignment of real_dev
+    - net: dsa: microchip: initialize mutex before use
+    - sctp: fix strchange_flags name for Stream Change Event
+    - net: phy: mdio-gpio: Fix working over slow can_sleep GPIOs
+    - sctp: not increase stream's incnt before sending addstrm_in request
+    - mlxsw: spectrum: Fix IP2ME CPU policer configuration
+    - net: smsc95xx: Fix MTU range
+    - rxrpc: Fix lockup due to no error backoff after ack transmit error
+    - usbnet: smsc95xx: disable carrier check while suspending
+    - Revert "x86/speculation: Enable cross-hyperthread spectre v2 STIBP
+      mitigation"
+    - Linux 4.19.4
+
+  * Disco update: 4.19.3 upstream stable release (LP: #1805158)
+    - powerpc/traps: restore recoverability of machine_check interrupts
+    - powerpc/64/module: REL32 relocation range check
+    - powerpc/mm: Fix page table dump to work on Radix
+    - powerpc/mm: fix always true/false warning in slice.c
+    - drm/amd/display: fix bug of accessing invalid memory
+    - Input: wm97xx-ts - fix exit path
+    - powerpc/Makefile: Fix PPC_BOOK3S_64 ASFLAGS
+    - powerpc/eeh: Fix possible null deref in eeh_dump_dev_log()
+    - tty: check name length in tty_find_polling_driver()
+    - tracing/kprobes: Check the probe on unloaded module correctly
+    - drm/nouveau/secboot/acr: fix memory leak
+    - drm/amdgpu/powerplay: fix missing break in switch statements
+    - ARM: imx_v6_v7_defconfig: Select CONFIG_TMPFS_POSIX_ACL
+    - powerpc/nohash: fix undefined behaviour when testing page size support
+    - drm/msm/gpu: fix parameters in function msm_gpu_crashstate_capture
+    - drm/msm/disp/dpu: Use proper define for drm_encoder_init() 'encoder_type'
+    - drm/msm: dpu: Allow planes to extend past active display
+    - powerpc/mm: Don't report hugepage tables as memory leaks when using kmemleak
+    - drm/omap: fix memory barrier bug in DMM driver
+    - drm/amd/display: Raise dispclk value for dce120 by 15%
+    - drm/amd/display: fix gamma not being applied
+    - drm/hisilicon: hibmc: Do not carry error code in HiBMC framebuffer pointer
+    - media: pci: cx23885: handle adding to list failure
+    - media: coda: don't overwrite h.264 profile_idc on decoder instance
+    - MIPS: kexec: Mark CPU offline before disabling local IRQ
+    - powerpc/boot: Ensure _zimage_start is a weak symbol
+    - powerpc/memtrace: Remove memory in chunks
+    - MIPS/PCI: Call pcie_bus_configure_settings() to set MPS/MRRS
+    - staging: erofs: fix a missing endian conversion
+    - serial: 8250_of: Fix for lack of interrupt support
+    - sc16is7xx: Fix for multi-channel stall
+    - media: tvp5150: fix width alignment during set_selection()
+    - powerpc/selftests: Wait all threads to join
+    - staging:iio:ad7606: fix voltage scales
+    - drm: rcar-du: Update Gen3 output limitations
+    - drm/amdgpu: Fix SDMA TO after GPU reset v3
+    - staging: most: video: fix registration of an empty comp core_component
+    - 9p locks: fix glock.client_id leak in do_lock
+    - udf: Prevent write-unsupported filesystem to be remounted read-write
+    - ARM: dts: imx6ull: keep IMX6UL_ prefix for signals on both i.MX6UL and
+      i.MX6ULL
+    - media: ov5640: fix mode change regression
+    - 9p: clear dangling pointers in p9stat_free
+    - drm/amdgpu: fix integer overflow test in amdgpu_bo_list_create()
+    - media: ov5640: fix restore of last mode set
+    - cdrom: fix improper type cast, which can leat to information leak.
+    - ovl: fix error handling in ovl_verify_set_fh()
+    - ovl: fix recursive oi->lock in ovl_link()
+    - ovl: check whiteout in ovl_create_over_whiteout()
+    - ovl: automatically enable redirect_dir on metacopy=on
+    - serial: sh-sci: Fix could not remove dev_attr_rx_fifo_timeout
+    - scsi: qla2xxx: Fix incorrect port speed being set for FC adapters
+    - scsi: qla2xxx: Fix process response queue for ISP26XX and above
+    - scsi: qla2xxx: Remove stale debug trace message from tcm_qla2xxx
+    - scsi: qla2xxx: Fix early srb free on abort
+    - scsi: qla2xxx: shutdown chip if reset fail
+    - scsi: qla2xxx: Reject bsg request if chip is down.
+    - scsi: qla2xxx: Fix re-using LoopID when handle is in use
+    - scsi: qla2xxx: Fix for double free of SRB structure
+    - scsi: qla2xxx: Fix NVMe session hang on unload
+    - scsi: qla2xxx: Fix NVMe Target discovery
+    - scsi: qla2xxx: Fix duplicate switch database entries
+    - scsi: qla2xxx: Fix driver hang when FC-NVMe LUNs are configured
+    - vfs: fix FIGETBSZ ioctl on an overlayfs file
+    - fuse: Fix use-after-free in fuse_dev_do_read()
+    - fuse: Fix use-after-free in fuse_dev_do_write()
+    - fuse: fix blocked_waitq wakeup
+    - fuse: set FR_SENT while locked
+    - drm/msm: fix OF child-node lookup
+    - arm64: dts: stratix10: Support Ethernet Jumbo frame
+    - arm64: dts: stratix10: fix multicast filtering
+    - clk: meson-gxbb: set fclk_div3 as CLK_IS_CRITICAL
+    - clk: meson: axg: mark fdiv2 and fdiv3 as critical
+    - zram: close udev startup race condition as default groups
+    - MIPS: Loongson-3: Fix CPU UART irq delivery problem
+    - MIPS: Loongson-3: Fix BRIDGE irq delivery problem
+    - xtensa: add NOTES section to the linker script
+    - xtensa: make sure bFLT stack is 16 byte aligned
+    - xtensa: fix boot parameters address translation
+    - um: Drop own definition of PTRACE_SYSEMU/_SINGLESTEP
+    - clk: s2mps11: Fix matching when built as module and DT node contains
+      compatible
+    - clk: at91: Fix division by zero in PLL recalc_rate()
+    - clk: sunxi-ng: h6: fix bus clocks' divider position
+    - clk: rockchip: fix wrong mmc sample phase shift for rk3328
+    - clk: rockchip: Fix static checker warning in rockchip_ddrclk_get_parent call
+    - libceph: bump CEPH_MSG_MAX_DATA_LEN
+    - Revert "ceph: fix dentry leak in splice_dentry()"
+    - thermal: core: Fix use-after-free in thermal_cooling_device_destroy_sysfs
+    - mach64: fix display corruption on big endian machines
+    - mach64: fix image corruption due to reading accelerator registers
+    - acpi/nfit, x86/mce: Handle only uncorrectable machine checks
+    - acpi/nfit, x86/mce: Validate a MCE's address before using it
+    - acpi, nfit: Fix ARS overflow continuation
+    - reset: hisilicon: fix potential NULL pointer dereference
+    - crypto: hisilicon - Fix NULL dereference for same dst and src
+    - crypto: hisilicon - Fix reference after free of memories on error path
+    - vhost/scsi: truncate T10 PI iov_iter to prot_bytes
+    - scsi: qla2xxx: Initialize port speed to avoid setting lower speed
+    - SCSI: fix queue cleanup race before queue initialization is done
+    - Revert "powerpc/8xx: Use L1 entry APG to handle _PAGE_ACCESSED for
+      CONFIG_SWAP"
+    - soc: ti: QMSS: Fix usage of irq_set_affinity_hint
+    - ocfs2: fix a misuse a of brelse after failing ocfs2_check_dir_entry
+    - ocfs2: free up write context when direct IO failed
+    - mm: thp: relax __GFP_THISNODE for MADV_HUGEPAGE mappings
+    - memory_hotplug: cond_resched in __remove_pages
+    - netfilter: conntrack: fix calculation of next bucket number in early_drop
+    - ARM: 8809/1: proc-v7: fix Thumb annotation of cpu_v7_hvc_switch_mm
+    - bonding/802.3ad: fix link_failure_count tracking
+    - mtd: spi-nor: cadence-quadspi: Return error code in
+      cqspi_direct_read_execute()
+    - mtd: nand: Fix nanddev_neraseblocks()
+    - mtd: docg3: don't set conflicting BCH_CONST_PARAMS option
+    - hwmon: (core) Fix double-free in __hwmon_device_register()
+    - perf cs-etm: Correct CPU mode for samples
+    - perf stat: Handle different PMU names with common prefix
+    - perf callchain: Honour the ordering of PERF_CONTEXT_{USER,KERNEL,etc}
+    - perf intel-pt/bts: Calculate cpumode for synthesized samples
+    - perf intel-pt: Insert callchain context into synthesized callchains
+    - of, numa: Validate some distance map rules
+    - x86/cpu/vmware: Do not trace vmware_sched_clock()
+    - x86/hyper-v: Enable PIT shutdown quirk
+    - termios, tty/tty_baudrate.c: fix buffer overrun
+    - arch/alpha, termios: implement BOTHER, IBSHIFT and termios2
+    - watchdog/core: Add missing prototypes for weak functions
+    - btrfs: fix pinned underflow after transaction aborted
+    - Btrfs: fix missing data checksums after a ranged fsync (msync)
+    - Btrfs: fix cur_offset in the error case for nocow
+    - Btrfs: fix infinite loop on inode eviction after deduplication of eof block
+    - Btrfs: fix data corruption due to cloning of eof block
+    - btrfs: tree-checker: Fix misleading group system information
+    - clockevents/drivers/i8253: Add support for PIT shutdown quirk
+    - ext4: add missing brelse() update_backups()'s error path
+    - ext4: add missing brelse() in set_flexbg_block_bitmap()'s error path
+    - ext4: add missing brelse() add_new_gdb_meta_bg()'s error path
+    - ext4: avoid potential extra brelse in setup_new_flex_group_blocks()
+    - ext4: missing !bh check in ext4_xattr_inode_write()
+    - ext4: fix possible inode leak in the retry loop of ext4_resize_fs()
+    - ext4: avoid buffer leak on shutdown in ext4_mark_iloc_dirty()
+    - ext4: avoid buffer leak in ext4_orphan_add() after prior errors
+    - ext4: fix missing cleanup if ext4_alloc_flex_bg_array() fails while resizing
+    - ext4: avoid possible double brelse() in add_new_gdb() on error path
+    - ext4: fix possible leak of sbi->s_group_desc_leak in error path
+    - ext4: fix possible leak of s_journal_flag_rwsem in error path
+    - ext4: fix buffer leak in ext4_xattr_get_block() on error path
+    - ext4: release bs.bh before re-using in ext4_xattr_block_find()
+    - ext4: fix buffer leak in ext4_xattr_move_to_block() on error path
+    - ext4: fix buffer leak in ext4_expand_extra_isize_ea() on error path
+    - ext4: fix buffer leak in __ext4_read_dirblock() on error path
+    - mount: Prevent MNT_DETACH from disconnecting locked mounts
+    - mnt: fix __detach_mounts infinite loop
+    - uapi: fix linux/kfd_ioctl.h userspace compilation errors
+    - ARM: cpuidle: Don't register the driver when back-end init returns -ENXIO
+    - kdb: use correct pointer when 'btc' calls 'btt'
+    - kdb: print real address of pointers instead of hashed addresses
+    - sunrpc: correct the computation for page_ptr when truncating
+    - NFSv4: Don't exit the state manager without clearing
+      NFS4CLNT_MANAGER_RUNNING
+    - nfsd: COPY and CLONE operations require the saved filehandle to be set
+    - rtc: hctosys: Add missing range error reporting
+    - fuse: fix use-after-free in fuse_direct_IO()
+    - fuse: fix leaked notify reply
+    - fuse: fix possibly missed wake-up after abort
+    - selinux: check length properly in SCTP bind hook
+    - gfs2: Put bitmap buffers in put_super
+    - gfs2: Fix metadata read-ahead during truncate (2)
+    - libata: blacklist SAMSUNG MZ7TD256HAFV-000L9 SSD
+    - crypto: user - fix leaking uninitialized memory to userspace
+    - lib/ubsan.c: don't mark __ubsan_handle_builtin_unreachable as noreturn
+    - hugetlbfs: fix kernel BUG at fs/hugetlbfs/inode.c:444!
+    - mm/swapfile.c: use kvzalloc for swap_info_struct allocation
+    - efi/arm/libstub: Pack FDT after populating it
+    - mm: don't reclaim inodes with many attached pages
+    - scripts/spdxcheck.py: make python3 compliant
+    - drm/rockchip: Allow driver to be shutdown on reboot/kexec
+    - drm/amdgpu: Fix typo in amdgpu_vmid_mgr_init
+    - drm/amdgpu: add missing CHIP_HAINAN in amdgpu_ucode_get_load_type
+    - drm/amdgpu: Suppress keypresses from ACPI_VIDEO events
+    - drm/nouveau: Check backlight IDs are >= 0, not > 0
+    - drm/nouveau: Fix nv50_mstc->best_encoder()
+    - drm/amd/powerplay: Enable/Disable NBPSTATE on On/OFF of UVD
+    - drm/etnaviv: fix bogus fence complete check in timeout handler
+    - drm/dp_mst: Check if primary mstb is null
+    - drm: panel-orientation-quirks: Add quirk for Acer One 10 (S1003)
+    - drm/i915/dp: Link train Fallback on eDP only if fallback link BW can fit
+      panel's native mode
+    - drm/i915: Use the correct crtc when sanitizing plane mapping
+    - drm/i915: Restore vblank interrupts earlier
+    - drm/i915: Don't unset intel_connector->mst_port
+    - drm/i915: Skip vcpi allocation for MSTB ports that are gone
+    - drm/i915: Large page offsets for pread/pwrite
+    - drm/i915/dp: Fix link retraining comment in intel_dp_long_pulse()
+    - drm/i915/dp: Restrict link retrain workaround to external monitors
+    - drm/i915/icl: Fix the macros for DFLEXDPMLE register bits
+    - drm/i915/hdmi: Add HDMI 2.0 audio clock recovery N values
+    - drm/i915: Mark up GTT sizes as u64
+    - drm/i915: Fix error handling for the NV12 fb dimensions check
+    - drm/i915: Fix ilk+ watermarks when disabling pipes
+    - drm/i915: Compare user's 64b GTT offset even on 32b
+    - drm/i915: Don't oops during modeset shutdown after lpe audio deinit
+    - drm/i915: Mark pin flags as u64
+    - drm/i915/ringbuffer: Delay after EMIT_INVALIDATE for gen4/gen5
+    - drm/i915/execlists: Force write serialisation into context image vs
+      execution
+    - drm/i915: Fix possible race in intel_dp_add_mst_connector()
+    - drm/i915: Fix NULL deref when re-enabling HPD IRQs on systems with MST
+    - drm/i915: Fix hpd handling for pins with two encoders
+    - CONFIG_XEN_PV breaks xen_create_contiguous_region on ARM
+    - Revert "ACPICA: AML interpreter: add region addresses in global list during
+      initialization"
+    - Linux 4.19.3
+
+  * glibc 2.28-0ubuntu1 ADT test failure with linux 4.19.0-5.6 (LP: #1805154)
+    - SAUCE: Revert "x86: vdso: Use $LD instead of $CC to link"
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: (noup) Update spl to 0.7.12-1ubuntu1, zfs to 0.7.12-1ubuntu1
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 26 Nov 2018 11:44:00 -0600
+
+linux (4.19.0-5.6) disco; urgency=medium
+
+  * crash in ENA driver on removing an interface (LP: #1802341)
+    - SAUCE: net: ena: fix crash during ena_remove()
+
+  * Ubuntu 18.04.1 - [s390x] Kernel panic while stressing network bonding
+    (LP: #1797367)
+    - s390/qeth: sanitize strings in debug messages
+
+  * Disco update: 4.19.2 upstream stable release (LP: #1803410)
+    - bpf: fix partial copy of map_ptr when dst is scalar
+    - MIPS: VDSO: Reduce VDSO_RANDOMIZE_SIZE to 64MB for 64bit
+    - gpio: mxs: Get rid of external API call
+    - mtd: rawnand: marvell: fix the IRQ handler complete() condition
+    - mtd: maps: gpio-addr-flash: Fix ioremapped size
+    - mtd: spi-nor: fsl-quadspi: fix read error for flash size larger than 16MB
+    - mtd: spi-nor: intel-spi: Add support for Intel Ice Lake SPI serial flash
+    - mtd: spi-nor: fsl-quadspi: Don't let -EINVAL on the bus
+    - spi: spi-mem: Adjust op len based on message/transfer size limitations
+    - spi: bcm-qspi: switch back to reading flash using smaller chunks
+    - spi: bcm-qspi: fix calculation of address length
+    - bcache: trace missed reading by cache_missed
+    - bcache: fix ioctl in flash device
+    - bcache: correct dirty data statistics
+    - bcache: fix miss key refill->end in writeback
+    - hwmon: (pmbus) Fix page count auto-detection.
+    - jffs2: free jffs2_sb_info through jffs2_kill_sb()
+    - block: setup bounce bio_sets properly
+    - block: make sure discard bio is aligned with logical block size
+    - block: make sure writesame bio is aligned with logical block size
+    - cpufreq: conservative: Take limits changes into account properly
+    - dma-mapping: fix panic caused by passing empty cma command line argument
+    - pcmcia: Implement CLKRUN protocol disabling for Ricoh bridges
+    - ACPI / OSL: Use 'jiffies' as the time bassis for acpi_os_get_timer()
+    - ACPICA: AML interpreter: add region addresses in global list during
+      initialization
+    - ACPICA: AML Parser: fix parse loop to correctly skip erroneous extended
+      opcodes
+    - acpi, nfit: Fix Address Range Scrub completion tracking
+    - kprobes/x86: Use preempt_enable() in optimized_callback()
+    - mailbox: PCC: handle parse error
+    - parisc: Fix address in HPMC IVA
+    - parisc: Fix map_pages() to not overwrite existing pte entries
+    - parisc: Fix exported address of os_hpmc handler
+    - ALSA: hda - Add quirk for ASUS G751 laptop
+    - ALSA: hda - Fix headphone pin config for ASUS G751
+    - ALSA: hda - Add mic quirk for the Lenovo G50-30 (17aa:3905)
+    - ALSA: hda: Add 2 more models to the power_save blacklist
+    - ALSA: ca0106: Disable IZD on SB0570 DAC to fix audio pops
+    - ALSA: hda - Fix incorrect clearance of thinkpad_acpi hooks
+    - x86/speculation: Enable cross-hyperthread spectre v2 STIBP mitigation
+    - x86/xen: Fix boot loader version reported for PVH guests
+    - x86/corruption-check: Fix panic in memory_corruption_check() when boot
+      option without value is provided
+    - x86/kvm/nVMX: allow bare VMXON state migration
+    - x86/mm/pat: Disable preemption around __flush_tlb_all()
+    - x86/numa_emulation: Fix uniform-split numa emulation
+    - ARM: dts: exynos: Disable pull control for MAX8997 interrupts on Origen
+    - net: socionext: Reset tx queue in ndo_stop
+    - net: loopback: clear skb->tstamp before netif_rx()
+    - locking/lockdep: Fix debug_locks off performance problem
+    - netfilter: xt_nat: fix DNAT target for shifted portmap ranges
+    - ataflop: fix error handling during setup
+    - swim: fix cleanup on setup error
+    - arm64: cpufeature: ctr: Fix cpu capability check for late CPUs
+    - hv_netvsc: fix vf serial matching with pci slot info
+    - nfp: devlink port split support for 1x100G CXP NIC
+    - tun: Consistently configure generic netdev params via rtnetlink
+    - s390/sthyi: Fix machine name validity indication
+    - hwmon: (pwm-fan) Set fan speed to 0 on suspend
+    - lightnvm: pblk: fix race on sysfs line state
+    - lightnvm: pblk: fix two sleep-in-atomic-context bugs
+    - lightnvm: pblk: fix race condition on metadata I/O
+    - spi: spi-ep93xx: Use dma_data_direction for ep93xx_spi_dma_{finish,prepare}
+    - perf tools: Free temporary 'sys' string in read_event_files()
+    - perf tools: Cleanup trace-event-info 'tdata' leak
+    - perf tools: Free 'printk' string in parse_ftrace_printk()
+    - perf strbuf: Match va_{add,copy} with va_end
+    - cpupower: Fix coredump on VMWare
+    - bcache: Populate writeback_rate_minimum attribute
+    - mmc: sdhci-pci-o2micro: Add quirk for O2 Micro dev 0x8620 rev 0x01
+    - sdhci: acpi: add free_slot callback
+    - mtd: rawnand: denali: set SPARE_AREA_SKIP_BYTES register to 8 if unset
+    - iwlwifi: pcie: avoid empty free RB queue
+    - iwlwifi: mvm: clear HW_RESTART_REQUESTED when stopping the interface
+    - iwlwifi: mvm: check for n_profiles validity in EWRD ACPI
+    - x86/olpc: Indicate that legacy PC XO-1 platform should not register RTC
+    - wlcore: Fix BUG with clear completion on timeout
+    - ACPI/PPTT: Handle architecturally unknown cache types
+    - ACPI / PM: LPIT: Register sysfs attributes based on FADT
+    - ACPI / processor: Fix the return value of acpi_processor_ids_walk()
+    - cpufreq: dt: Try freeing static OPPs only if we have added them
+    - x86/intel_rdt: Show missing resctrl mount options
+    - mtd: rawnand: atmel: Fix potential NULL pointer dereference
+    - nvme: call nvme_complete_rq when nvmf_check_ready fails for mpath I/O
+    - ath10k: fix tx status flag setting for management frames
+    - signal: Introduce COMPAT_SIGMINSTKSZ for use in compat_sys_sigaltstack
+    - ice: fix changing of ring descriptor size (ethtool -G)
+    - ice: update fw version check logic
+    - net: hns3: Fix for packet buffer setting bug
+    - Bluetooth: btbcm: Add entry for BCM4335C0 UART bluetooth
+    - Bluetooth: hci_qca: Remove hdev dereference in qca_close().
+    - x86: boot: Fix EFI stub alignment
+    - net: hns3: Add nic state check before calling netif_tx_wake_queue
+    - net: hns3: Fix ets validate issue
+    - pinctrl: sunxi: fix 'pctrl->functions' allocation in
+      sunxi_pinctrl_build_state
+    - pinctrl: qcom: spmi-mpp: Fix err handling of pmic_mpp_set_mux
+    - brcmfmac: fix for proper support of 160MHz bandwidth
+    - net: hns3: Check hdev state when getting link status
+    - net: hns3: Set STATE_DOWN bit of hdev state when stopping net
+    - net: phy: phylink: ensure the carrier is off when starting phylink
+    - block, bfq: correctly charge and reset entity service in all cases
+    - arm64: entry: Allow handling of undefined instructions from EL1
+    - kprobes: Return error if we fail to reuse kprobe instead of BUG_ON()
+    - spi: gpio: No MISO does not imply no RX
+    - ACPI / LPSS: Add alternative ACPI HIDs for Cherry Trail DMA controllers
+    - pinctrl: qcom: spmi-mpp: Fix drive strength setting
+    - bpf/verifier: fix verifier instability
+    - failover: Add missing check to validate 'slave_dev' in
+      net_failover_slave_unregister
+    - perf tests: Fix record+probe_libc_inet_pton.sh without ping's debuginfo
+    - pinctrl: spmi-mpp: Fix pmic_mpp_config_get() to be compliant
+    - pinctrl: ssbi-gpio: Fix pm8xxx_pin_config_get() to be compliant
+    - net: hns3: Preserve vlan 0 in hardware table
+    - net: hns3: Fix ping exited problem when doing lp selftest
+    - net: hns3: Fix for vf vlan delete failed problem
+    - net: dsa: mv88e6xxx: Fix writing to a PHY page.
+    - mt76x2u: run device cleanup routine if resume fails
+    - rsi: fix memory alignment issue in ARM32 platforms
+    - libertas_tf: prevent underflow in process_cmdrequest()
+    - iwlwifi: mvm: fix BAR seq ctrl reporting
+    - gpio: brcmstb: allow 0 width GPIO banks
+    - ixgbe: disallow IPsec Tx offload when in SR-IOV mode
+    - ixgbevf: VF2VF TCP RSS
+    - wil6210: fix RX buffers release and unmap
+    - ath10k: schedule hardware restart if WMI command times out
+    - libata: Apply NOLPM quirk for SAMSUNG MZ7TD256HAFV-000L9
+    - thermal: rcar_thermal: Prevent doing work after unbind
+    - thermal: da9062/61: Prevent hardware access during system suspend
+    - cifs: fix a credits leak for compund commands
+    - cgroup, netclassid: add a preemption point to write_classid
+    - net: stmmac: dwmac-sun8i: fix OF child-node lookup
+    - f2fs: fix to account IO correctly for cgroup writeback
+    - MD: Memory leak when flush bio size is zero
+    - md: fix memleak for mempool
+    - of: Add missing exports of node name compare functions
+    - scsi: esp_scsi: Track residual for PIO transfers
+    - scsi: ufs: Schedule clk gating work on correct queue
+    - UAPI: ndctl: Fix g++-unsupported initialisation in headers
+    - KVM: nVMX: Clear reserved bits of #DB exit qualification
+    - scsi: megaraid_sas: fix a missing-check bug
+    - RDMA/core: Do not expose unsupported counters
+    - RDMA/cm: Respect returned status of cm_init_av_by_path
+    - IB/ipoib: Clear IPCB before icmp_send
+    - RDMA/bnxt_re: Avoid accessing nq->bar_reg_iomem in failure case
+    - RDMA/bnxt_re: Fix recursive lock warning in debug kernel
+    - usb: host: ohci-at91: fix request of irq for optional gpio
+    - PCI: mediatek: Fix mtk_pcie_find_port() endpoint/port matching logic
+    - PCI: cadence: Use AXI region 0 to signal interrupts from EP
+    - usb: typec: tcpm: Report back negotiated PPS voltage and current
+    - tpm: suppress transmit cmd error logs when TPM 1.2 is disabled/deactivated
+    - f2fs: clear PageError on the read path
+    - Drivers: hv: vmbus: Use cpumask_var_t for on-stack cpu mask
+    - VMCI: Resource wildcard match fixed
+    - PCI / ACPI: Enable wake automatically for power managed bridges
+    - xprtrdma: Reset credit grant properly after a disconnect
+    - irqchip/pdc: Setup all edge interrupts as rising edge at GIC
+    - usb: dwc2: fix call to vbus supply exit routine, call it unlocked
+    - usb: dwc2: fix a race with external vbus supply
+    - usb: gadget: udc: atmel: handle at91sam9rl PMC
+    - ext4: fix argument checking in EXT4_IOC_MOVE_EXT
+    - MD: fix invalid stored role for a disk
+    - PCI: cadence: Correct probe behaviour when failing to get PHY
+    - nvmem: check the return value of nvmem_add_cells()
+    - xhci: Avoid USB autosuspend when resuming USB2 ports.
+    - scsi: qla2xxx: Fix recursive mailbox timeout
+    - f2fs: fix to recover inode's crtime during POR
+    - f2fs: fix to recover inode's i_flags during POR
+    - PCI/MSI: Warn and return error if driver enables MSI/MSI-X twice
+    - coresight: etb10: Fix handling of perf mode
+    - PCI: dwc: pci-dra7xx: Enable errata i870 for both EP and RC mode
+    - crypto: caam - fix implicit casts in endianness helpers
+    - usb: chipidea: Prevent unbalanced IRQ disable
+    - Smack: ptrace capability use fixes
+    - driver/dma/ioat: Call del_timer_sync() without holding prep_lock
+    - ASoC: AMD: Fix capture unstable in beginning for some runs
+    - firmware: coreboot: Unmap ioregion after device population
+    - IB/ipoib: Use dev_port to expose network interface port numbers
+    - IB/mlx5: Allow transition of DCI QP to reset
+    - uio: ensure class is registered before devices
+    - scsi: lpfc: Correct soft lockup when running mds diagnostics
+    - scsi: lpfc: Correct race with abort on completion path
+    - f2fs: avoid sleeping under spin_lock
+    - f2fs: report error if quota off error during umount
+    - signal: Always deliver the kernel's SIGKILL and SIGSTOP to a pid namespace
+      init
+    - f2fs: fix to flush all dirty inodes recovered in readonly fs
+    - mfd: menelaus: Fix possible race condition and leak
+    - dmaengine: dma-jz4780: Return error if not probed from DT
+    - IB/rxe: fix for duplicate request processing and ack psns
+    - ALSA: hda: Check the non-cached stream buffers more explicitly
+    - cpupower: Fix AMD Family 0x17 msr_pstate size
+    - Revert "f2fs: fix to clear PG_checked flag in set_page_dirty()"
+    - f2fs: fix missing up_read
+    - f2fs: fix to recover cold bit of inode block during POR
+    - f2fs: fix to account IO correctly
+    - OPP: Free OPP table properly on performance state irregularities
+    - ARM: dts: exynos: Convert exynos5250.dtsi to opp-v2 bindings
+    - ARM: dts: exynos: Mark 1 GHz CPU OPP as suspend OPP on Exynos5250
+    - xen-swiotlb: use actually allocated size on check physical continuous
+    - tpm: Restore functionality to xen vtpm driver.
+    - xen/blkfront: avoid NULL blkfront_info dereference on device removal
+    - xen/balloon: Support xend-based toolstack
+    - xen: fix race in xen_qlock_wait()
+    - xen: make xen_qlock_wait() nestable
+    - xen/pvh: increase early stack size
+    - xen/pvh: don't try to unplug emulated devices
+    - libertas: don't set URB_ZERO_PACKET on IN USB transfer
+    - usbip:vudc: BUG kmalloc-2048 (Not tainted): Poison overwritten
+    - usb: typec: tcpm: Fix APDO PPS order checking to be based on voltage
+    - usb: gadget: udc: renesas_usb3: Fix b-device mode for "workaround"
+    - mt76: mt76x2: fix multi-interface beacon configuration
+    - iwlwifi: mvm: check return value of rs_rate_from_ucode_rate()
+    - net/ipv4: defensive cipso option parsing
+    - dmaengine: ppc4xx: fix off-by-one build failure
+    - scsi: sched/wait: Add wait_event_lock_irq_timeout for TASK_UNINTERRUPTIBLE
+      usage
+    - scsi: target: Fix target_wait_for_sess_cmds breakage with active signals
+    - libnvdimm: Hold reference on parent while scheduling async init
+    - libnvdimm, region: Fail badblocks listing for inactive regions
+    - libnvdimm, pmem: Fix badblocks population for 'raw' namespaces
+    - ASoC: intel: skylake: Add missing break in skl_tplg_get_token()
+    - ASoC: sta32x: set ->component pointer in private struct
+    - IB/mlx5: Fix MR cache initialization
+    - IB/rxe: Revise the ib_wr_opcode enum
+    - jbd2: fix use after free in jbd2_log_do_checkpoint()
+    - gfs2_meta: ->mount() can get NULL dev_name
+    - ext4: fix EXT4_IOC_SWAP_BOOT
+    - ext4: initialize retries variable in ext4_da_write_inline_data_begin()
+    - ext4: fix setattr project check in fssetxattr ioctl
+    - ext4: propagate error from dquot_initialize() in EXT4_IOC_FSSETXATTR
+    - ext4: fix use-after-free race in ext4_remount()'s error path
+    - selinux: fix mounting of cgroup2 under older policies
+    - HID: wacom: Work around HID descriptor bug in DTK-2451 and DTH-2452
+    - HID: hiddev: fix potential Spectre v1
+    - EDAC, amd64: Add Family 17h, models 10h-2fh support
+    - EDAC, {i7core,sb,skx}_edac: Fix uncorrected error counting
+    - EDAC, skx_edac: Fix logical channel intermediate decoding
+    - ARM: dts: dra7: Fix up unaligned access setting for PCIe EP
+    - PCI/ASPM: Fix link_state teardown on device removal
+    - PCI: Add Device IDs for Intel GPU "spurious interrupt" quirk
+    - signal/GenWQE: Fix sending of SIGKILL
+    - signal: Guard against negative signal numbers in copy_siginfo_from_user32
+    - crypto: lrw - Fix out-of bounds access on counter overflow
+    - crypto: tcrypt - fix ghash-generic speed test
+    - crypto: aesni - don't use GFP_ATOMIC allocation if the request doesn't cross
+      a page in gcm
+    - crypto: morus/generic - fix for big endian systems
+    - crypto: aegis/generic - fix for big endian systems
+    - crypto: speck - remove Speck
+    - mm: /proc/pid/smaps_rollup: fix NULL pointer deref in smaps_pte_range()
+    - userfaultfd: disable irqs when taking the waitqueue lock
+    - ima: fix showing large 'violations' or 'runtime_measurements_count'
+    - ima: open a new file instance if no read permissions
+    - hugetlbfs: dirty pages as they are added to pagecache
+    - mm/rmap: map_pte() was not handling private ZONE_DEVICE page properly
+    - mm/hmm: fix race between hmm_mirror_unregister() and mmu_notifier callback
+    - KVM: arm/arm64: Ensure only THP is candidate for adjustment
+    - KVM: arm64: Fix caching of host MDCR_EL2 value
+    - kbuild: fix kernel/bounds.c 'W=1' warning
+    - iio: ad5064: Fix regulator handling
+    - iio: adc: imx25-gcq: Fix leak of device_node in mx25_gcq_setup_cfgs()
+    - iio: adc: at91: fix acking DRDY irq on simple conversions
+    - iio: adc: at91: fix wrong channel number in triggered buffer mode
+    - w1: omap-hdq: fix missing bus unregister at removal
+    - smb3: allow stats which track session and share reconnects to be reset
+    - smb3: do not attempt cifs operation in smb3 query info error path
+    - smb3: on kerberos mount if server doesn't specify auth type use krb5
+    - printk: Fix panic caused by passing log_buf_len to command line
+    - genirq: Fix race on spurious interrupt detection
+    - tpm: fix response size validation in tpm_get_random()
+    - NFC: nfcmrvl_uart: fix OF child-node lookup
+    - NFSv4.1: Fix the r/wsize checking
+    - nfs: Fix a missed page unlock after pg_doio()
+    - nfsd: correctly decrement odstate refcount in error path
+    - nfsd: Fix an Oops in free_session()
+    - lockd: fix access beyond unterminated strings in prints
+    - dm ioctl: harden copy_params()'s copy_from_user() from malicious users
+    - dm zoned: fix metadata block ref counting
+    - dm zoned: fix various dmz_get_mblock() issues
+    - media: ov7670: make "xclk" clock optional
+    - fsnotify: Fix busy inodes during unmount
+    - powerpc64/module elfv1: Set opd addresses after module relocation
+    - powerpc/msi: Fix compile error on mpc83xx
+    - powerpc/tm: Fix HFSCR bit for no suspend case
+    - powerpc/64s/hash: Do not use PPC_INVALIDATE_ERAT on CPUs before POWER9
+    - MIPS: OCTEON: fix out of bounds array access on CN68XX
+    - rtc: ds1307: fix ds1339 wakealarm support
+    - rtc: cmos: Fix non-ACPI undefined reference to `hpet_rtc_interrupt'
+    - rtc: cmos: Remove the `use_acpi_alarm' module parameter for !ACPI
+    - power: supply: twl4030-charger: fix OF sibling-node lookup
+    - ocxl: Fix access to the AFU Descriptor Data
+    - iommu/arm-smmu: Ensure that page-table updates are visible before TLBI
+    - TC: Set DMA masks for devices
+    - net: bcmgenet: fix OF child-node lookup
+    - media: v4l2-tpg: fix kernel oops when enabling HFLIP and OSD
+    - Revert "media: dvbsky: use just one mutex for serializing device R/W ops"
+    - kgdboc: Passing ekgdboc to command line causes panic
+    - remoteproc: qcom: q6v5: Propagate EPROBE_DEFER
+    - media: cec: make cec_get_edid_spa_location() an inline function
+    - media: cec: integrate cec_validate_phys_addr() in cec-api.c
+    - xen: fix xen_qlock_wait()
+    - xen: remove size limit of privcmd-buf mapping interface
+    - xen-blkfront: fix kernel panic with negotiate_mq error path
+    - media: cec: add new tx/rx status bits to detect aborts/timeouts
+    - media: cec: fix the Signal Free Time calculation
+    - media: cec: forgot to cancel delayed work
+    - media: em28xx: use a default format if TRY_FMT fails
+    - media: tvp5150: avoid going past array on v4l2_querymenu()
+    - media: em28xx: fix input name for Terratec AV 350
+    - media: em28xx: make v4l2-compliance happier by starting sequence on zero
+    - media: em28xx: fix handler for vidioc_s_input()
+    - media: adv7604: when the EDID is cleared, unconfigure CEC as well
+    - media: adv7842: when the EDID is cleared, unconfigure CEC as well
+    - drm/mediatek: fix OF sibling-node lookup
+    - media: media colorspaces*.rst: rename AdobeRGB to opRGB
+    - media: replace ADOBERGB by OPRGB
+    - media: hdmi.h: rename ADOBE_RGB to OPRGB and ADOBE_YCC to OPYCC
+    - arm64: lse: remove -fcall-used-x0 flag
+    - rpmsg: smd: fix memory leak on channel create
+    - Cramfs: fix abad comparison when wrap-arounds occur
+    - ARM: dts: socfpga: Fix SDRAM node address for Arria10
+    - arm64: dts: stratix10: Correct System Manager register size
+    - soc: qcom: rmtfs-mem: Validate that scm is available
+    - soc/tegra: pmc: Fix child-node lookup
+    - selftests/ftrace: Fix synthetic event test to delete event correctly
+    - selftests/powerpc: Fix ptrace tm failure
+    - tracing: Return -ENOENT if there is no target synthetic event
+    - btrfs: qgroup: Avoid calling qgroup functions if qgroup is not enabled
+    - btrfs: Handle owner mismatch gracefully when walking up tree
+    - btrfs: locking: Add extra check in btrfs_init_new_buffer() to avoid deadlock
+    - btrfs: fix error handling in free_log_tree
+    - btrfs: fix error handling in btrfs_dev_replace_start
+    - btrfs: Enhance btrfs_trim_fs function to handle error better
+    - btrfs: Ensure btrfs_trim_fs can trim the whole filesystem
+    - btrfs: iterate all devices during trim, instead of fs_devices::alloc_list
+    - btrfs: don't attempt to trim devices that don't support it
+    - btrfs: keep trim from interfering with transaction commits
+    - btrfs: wait on caching when putting the bg cache
+    - Btrfs: don't clean dirty pages during buffered writes
+    - btrfs: release metadata before running delayed refs
+    - btrfs: protect space cache inode alloc with GFP_NOFS
+    - btrfs: reset max_extent_size on clear in a bitmap
+    - btrfs: make sure we create all new block groups
+    - Btrfs: fix warning when replaying log after fsync of a tmpfile
+    - Btrfs: fix wrong dentries after fsync of file that got its parent replaced
+    - btrfs: qgroup: Dirty all qgroups before rescan
+    - Btrfs: fix null pointer dereference on compressed write path error
+    - Btrfs: fix assertion on fsync of regular file when using no-holes feature
+    - Btrfs: fix deadlock when writing out free space caches
+    - btrfs: reset max_extent_size properly
+    - btrfs: set max_extent_size properly
+    - btrfs: don't use ctl->free_space for max_extent_size
+    - btrfs: only free reserved extent if we didn't insert it
+    - btrfs: fix insert_reserved error handling
+    - btrfs: don't run delayed_iputs in commit
+    - btrfs: move the dio_sem higher up the callchain
+    - Btrfs: fix use-after-free during inode eviction
+    - Btrfs: fix use-after-free when dumping free space
+    - net: sched: Remove TCA_OPTIONS from policy
+    - vt: fix broken display when running aptitude
+    - bpf: wait for running BPF programs when updating map-in-map
+    - vga_switcheroo: Fix missing gpu_bound call at audio client registration
+    - MD: fix invalid stored role for a disk - try2
+    - Linux 4.19.2
+
+  * [FEAT] Guest-dedicated Crypto Adapters (LP: #1787405)
+    - KVM: s390: vsie: simulate VCPU SIE entry/exit
+    - KVM: s390: introduce and use KVM_REQ_VSIE_RESTART
+    - KVM: s390: refactor crypto initialization
+    - s390: vfio-ap: base implementation of VFIO AP device driver
+    - s390: vfio-ap: register matrix device with VFIO mdev framework
+    - s390: vfio-ap: sysfs interfaces to configure adapters
+    - s390: vfio-ap: sysfs interfaces to configure domains
+    - s390: vfio-ap: sysfs interfaces to configure control domains
+    - s390: vfio-ap: sysfs interface to view matrix mdev matrix
+    - KVM: s390: interface to clear CRYCB masks
+    - s390: vfio-ap: implement mediated device open callback
+    - s390: vfio-ap: implement VFIO_DEVICE_GET_INFO ioctl
+    - s390: vfio-ap: zeroize the AP queues
+    - s390: vfio-ap: implement VFIO_DEVICE_RESET ioctl
+    - KVM: s390: Clear Crypto Control Block when using vSIE
+    - KVM: s390: vsie: Do the CRYCB validation first
+    - KVM: s390: vsie: Make use of CRYCB FORMAT2 clear
+    - KVM: s390: vsie: Allow CRYCB FORMAT-2
+    - KVM: s390: vsie: allow CRYCB FORMAT-1
+    - KVM: s390: vsie: allow CRYCB FORMAT-0
+    - KVM: s390: vsie: allow guest FORMAT-0 CRYCB on host FORMAT-1
+    - KVM: s390: vsie: allow guest FORMAT-1 CRYCB on host FORMAT-2
+    - KVM: s390: vsie: allow guest FORMAT-0 CRYCB on host FORMAT-2
+    - KVM: s390: device attrs to enable/disable AP interpretation
+    - KVM: s390: CPU model support for AP virtualization
+    - s390: doc: detailed specifications for AP virtualization
+    - KVM: s390: fix locking for crypto setting error path
+    - KVM: s390: Tracing APCB changes
+    - s390: vfio-ap: setup APCB mask using KVM dedicated function
+    - [Config:] Enable CONFIG_S390_AP_IOMMU and set CONFIG_VFIO_AP to module.
+
+  * Bypass of mount visibility through userns + mount propagation (LP: #1789161)
+    - mount: Retest MNT_LOCKED in do_umount
+    - mount: Don't allow copying MNT_UNBINDABLE|MNT_LOCKED mounts
+
+  *  CVE-2018-18955: nested user namespaces with more than five extents
+    incorrectly grant privileges over inode (LP: #1801924) // CVE-2018-18955
+    - userns: also map extents in the reverse map to kernel IDs
+
+  * kdump fail due to an IRQ storm (LP: #1797990)
+    - SAUCE: x86/PCI: Export find_cap() to be used in early PCI code
+    - SAUCE: x86/quirks: Add parameter to clear MSIs early on boot
+    - SAUCE: x86/quirks: Scan all busses for early PCI quirks
+
+  * Disable LPM for Raydium Touchscreens (LP: #1802248)
+    - USB: quirks: Add no-lpm quirk for Raydium touchscreens
+
+  * Power consumption during s2idle is higher than long idle(sk hynix)
+    (LP: #1801875)
+    - SAUCE: pci: prevent sk hynix nvme from entering D3
+    - SAUCE: nvme: add quirk to not call disable function when suspending
+
+  * Disco update: v4.19.1 upstream stable release (LP: #1801739)
+    - bridge: do not add port to router list when receives query with source
+      0.0.0.0
+    - ipv6/ndisc: Preserve IPv6 control buffer if protocol error handlers are
+      called
+    - net/mlx5e: fix csum adjustments caused by RXFCS
+    - net: sched: gred: pass the right attribute to gred_change_table_def()
+    - net: stmmac: Fix stmmac_mdio_reset() when building stmmac as modules
+    - net: udp: fix handling of CHECKSUM_COMPLETE packets
+    - Revert "net: simplify sock_poll_wait"
+    - rtnetlink: Disallow FDB configuration for non-Ethernet device
+    - vhost: Fix Spectre V1 vulnerability
+    - bonding: fix length of actor system
+    - openvswitch: Fix push/pop ethernet validation
+    - net/ipv6: Allow onlink routes to have a device mismatch if it is the default
+      route
+    - net/smc: fix smc_buf_unuse to use the lgr pointer
+    - mlxsw: spectrum_switchdev: Don't ignore deletions of learned MACs
+    - mlxsw: core: Fix devlink unregister flow
+    - net: drop skb on failure in ip_check_defrag()
+    - net: Properly unlink GRO packets on overflow.
+    - r8169: fix broken Wake-on-LAN from S5 (poweroff)
+    - Revert "be2net: remove desc field from be_eq_obj"
+    - sctp: check policy more carefully when getting pr status
+    - sparc64: Export __node_distance.
+    - sparc64: Make corrupted user stacks more debuggable.
+    - sparc64: Wire up compat getpeername and getsockname.
+    - net: bridge: remove ipv6 zero address check in mcast queries
+    - Linux 4.19.1
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: (noup) Update spl to 0.7.11-1ubuntu1, zfs to 0.7.11-3ubuntu1
+    - [Config] updateconfigs after 4.19.2 stable update
+    - [Config] Disable unneded options for s390
+    - [Config] Update annotations for 4.19
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Thu, 15 Nov 2018 09:55:37 -0800
+
+linux (4.19.0-4.5) disco; urgency=medium
+
+  * Add checksum offload and TSO support for HiNIC adapters (LP: #1800664)
+    - net-next/hinic: add checksum offload and TSO support
+
+  * [Bionic][Cosmic] Fix to ipmi to support vendor specific messages greater
+    than 255 bytes (LP: #1799794)
+    - ipmi:ssif: Add support for multi-part transmit messages > 2 parts
+
+  * Packaging resync (LP: #1786013)
+    - [Package] add support for specifying the primary makefile
+
+  * Update ENA driver to version 2.0.1K (LP: #1798182)
+    - net: ena: minor performance improvement
+    - net: ena: complete host info to match latest ENA spec
+    - net: ena: introduce Low Latency Queues data structures according to ENA spec
+    - net: ena: add functions for handling Low Latency Queues in ena_com
+    - net: ena: add functions for handling Low Latency Queues in ena_netdev
+    - net: ena: use CSUM_CHECKED device indication to report skb's checksum status
+    - net: ena: explicit casting and initialization, and clearer error handling
+    - net: ena: limit refill Rx threshold to 256 to avoid latency issues
+    - net: ena: change rx copybreak default to reduce kernel memory pressure
+    - net: ena: remove redundant parameter in ena_com_admin_init()
+    - net: ena: update driver version to 2.0.1
+    - net: ena: fix indentations in ena_defs for better readability
+    - net: ena: Fix Kconfig dependency on X86
+    - net: ena: enable Low Latency Queues
+    - net: ena: fix compilation error in xtensa architecture
+
+  * [Bionic][Cosmic]  ipmi: Fix timer race with module unload (LP: #1799281)
+    - ipmi: Fix timer race with module unload
+
+  * Overlayfs in user namespace leaks directory content of inaccessible
+    directories (LP: #1793458) // CVE-2018-6559
+    - SAUCE: overlayfs: ensure mounter privileges when reading directories
+
+  * not able to unwind the stack from within __kernel_clock_gettime in the Linux
+    vDSO (LP: #1797963)
+    - powerpc/vdso: Correct call frame information
+
+  * Miscellaneous Ubuntu changes
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) efi: Don't print secure boot state
+      from the efi stub"
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) efi: Sanitize boot_params in efi stub"
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) Make get_cert_list() use
+      efi_status_to_str() to print error messages."
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) Add efi_status_to_str() and rework
+      efi_status_to_err()."
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) Make get_cert_list() not complain
+      about cert lists that aren't present."
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) MODSIGN: Allow the "db" UEFI variable
+      to be suppressed"
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) MODSIGN: Import certificates from UEFI
+      Secure Boot"
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) efi: Add an EFI signature blob parser"
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) efi: Add EFI signature data types"
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) KEYS: Allow unrestricted boot-time
+      addition of keys to secondary keyring"
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) efi: Lock down the kernel if booted in
+      secure boot mode"
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) efi: Add an EFI_SECURE_BOOT flag to
+      indicate secure boot mode"
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) Copy secure_boot flag in boot params
+      across kexec reboot"
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) debugfs: Restrict debugfs when the
+      kernel is locked down"
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) Lock down perf"
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) bpf: Restrict kernel image access
+      functions when the kernel is locked down"
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) Lock down kprobes"
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) Lock down /proc/kcore"
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) x86/mmiotrace: Lock down the
+      testmmiotrace module"
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) Lock down module params that specify
+      hardware parameters (eg. ioport)"
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) Lock down TIOCSSERIAL"
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) Prohibit PCMCIA CIS storage when the
+      kernel is locked down"
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) acpi: Disable APEI error injection if
+      the kernel is locked down"
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) acpi: Disable ACPI table override if
+      the kernel is locked down"
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) acpi: Ignore acpi_rsdp kernel param
+      when the kernel has been locked down"
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) ACPI: Limit access to custom_method
+      when the kernel is locked down"
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) x86/msr: Restrict MSR access when the
+      kernel is locked down"
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) x86: Lock down IO port access when the
+      kernel is locked down"
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) PCI: Lock down BAR access when the
+      kernel is locked down"
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) uswsusp: Disable when the kernel is
+      locked down"
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) hibernate: Disable when the kernel is
+      locked down"
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) kexec_load: Disable at runtime if the
+      kernel is locked down"
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) Restrict /dev/{mem,kmem,port} when the
+      kernel is locked down"
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) Enforce module signatures if the
+      kernel is locked down"
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) Add a SysRq option to lift kernel
+      lockdown"
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) Add the ability to lock down access to
+      the running kernel image"
+    - SAUCE: (efi-lockdown) Add the ability to lock down access to the running
+      kernel image
+    - SAUCE: (efi-lockdown) Add a SysRq option to lift kernel lockdown
+    - SAUCE: (efi-lockdown) Enforce module signatures if the kernel is locked down
+    - SAUCE: (efi-lockdown) Restrict /dev/{mem,kmem,port} when the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) kexec_load: Disable at runtime if the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) hibernate: Disable when the kernel is locked down
+    - SAUCE: (efi-lockdown) uswsusp: Disable when the kernel is locked down
+    - SAUCE: (efi-lockdown) PCI: Lock down BAR access when the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) x86: Lock down IO port access when the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) x86/msr: Restrict MSR access when the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) ACPI: Limit access to custom_method when the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) acpi: Ignore acpi_rsdp kernel param when the kernel
+      has been locked down
+    - SAUCE: (efi-lockdown) acpi: Disable ACPI table override if the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) acpi: Disable APEI error injection if the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) Prohibit PCMCIA CIS storage when the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) Lock down TIOCSSERIAL
+    - SAUCE: (efi-lockdown) Lock down module params that specify hardware
+      parameters (eg. ioport)
+    - SAUCE: (efi-lockdown) x86/mmiotrace: Lock down the testmmiotrace module
+    - SAUCE: (efi-lockdown) Lock down /proc/kcore
+    - SAUCE: (efi-lockdown) Lock down kprobes
+    - SAUCE: (efi-lockdown) Lock down perf
+    - SAUCE: (efi-lockdown) debugfs: Restrict debugfs when the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) KEYS: Allow unrestricted boot-time addition of keys to
+      secondary keyring
+    - SAUCE: (efi-lockdown) efi: Add EFI signature data types
+    - SAUCE: (efi-lockdown) efi: Add an EFI signature blob parser
+    - SAUCE: (efi-lockdown) MODSIGN: Import certificates from UEFI Secure Boot
+    - SAUCE: (efi-lockdown) MODSIGN: Allow the "db" UEFI variable to be suppressed
+    - SAUCE: (efi-lockdown) Make get_cert_list() not complain about cert lists
+      that aren't present.
+    - SAUCE: (efi-lockdown) Add efi_status_to_str() and rework
+      efi_status_to_err().
+    - SAUCE: (efi-lockdown) Make get_cert_list() use efi_status_to_str() to print
+      error messages.
+    - SAUCE: (efi-lockdown) Copy secure_boot flag in boot params across kexec
+      reboot
+    - SAUCE: (efi-lockdown) efi: Add an EFI_SECURE_BOOT flag to indicate secure
+      boot mode
+    - SAUCE: (efi-lockdown) efi: Lock down the kernel if booted in secure boot
+      mode
+    - SAUCE: (efi-lockdown) efi/x86: Call efi_parse_options() from efi_main()
+    - SAUCE: (efi-lockdown) Fix for module sig verification
+    - SAUCE: (efi-lockdown) efi: Sanitize boot_params in efi stub
+    - SAUCE: (efi-lockdown) module: remove support for having IMA validate modules
+    - [Packaging] generate Vcs-Git url from changelog
+    - [Config] CONFIG_SCSI_MQ_DEFAULT=y
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Fri, 02 Nov 2018 14:22:55 -0500
+
+linux (4.19.0-3.4) cosmic; urgency=medium
+
+  * Support Edge Gateway's Bluetooth LED (LP: #1798332)
+    - SAUCE: Bluetooth: Support for LED on Edge Gateways
+
+  * Support Edge Gateway's WIFI LED (LP: #1798330)
+    - SAUCE: mwifiex: Switch WiFi LED state according to the device status
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.19
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 22 Oct 2018 09:13:39 -0500
+
+linux (4.19.0-2.3) cosmic; urgency=medium
+
+  * fscache: bad refcounting in fscache_op_complete leads to OOPS (LP: #1797314)
+    - SAUCE: fscache: Fix race in decrementing refcount of op->npages
+
+  * Provide mode where all vCPUs on a core must be the same VM (LP: #1792957)
+    - KVM: PPC: Book3S HV: Provide mode where all vCPUs on a core must be the same
+      VM
+
+  * The front MIC can't work on the Lenovo M715 (LP: #1797292)
+    - ALSA: hda/realtek - Fix the problem of the front MIC on the Lenovo M715
+
+  * arm64: snapdragon: WARNING: CPU: 0 PID: 1 at drivers/irqchip/irq-gic.c:1016
+    gic_irq_domain_translate (LP: #1797143)
+    - SAUCE: arm64: dts: msm8916: camms: fix gic_irq_domain_translate warnings
+
+  * Dell new AIO requires a new uart backlight driver (LP: #1727235)
+    - SAUCE: platform/x86: dell-uart-backlight: new backlight driver for DELL AIO
+    - updateconfigs for Dell UART backlight driver
+
+  * Please make CONFIG_PWM_LPSS_PCI and CONFIG_PWM_LPSS_PLATFORM built in to
+    make brightness adjustment working on various BayTrail/CherryTrail-based
+    devices (LP: #1783964)
+    - [Config]: Make PWM_LPSS_* built-in
+
+  * check and fix zkey required kernel modules locations in debs, udebs, and
+    initramfs (LP: #1794346)
+    - [Config] add s390 crypto modules to crypt-modules udeb
+
+  * Miscellaneous Ubuntu changes
+    - [Config] CONFIG_VBOXGUEST=n
+    - ubuntu: vbox -- update to 5.2.18-dfsg-2
+    - ubuntu: enable vbox build
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.19-rc8
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 15 Oct 2018 10:52:04 -0500
+
+linux (4.19.0-1.2) cosmic; urgency=medium
+
+  * Page leaking in cachefiles_read_backing_file while vmscan is active
+    (LP: #1793430)
+    - SAUCE: cachefiles: Page leaking in cachefiles_read_backing_file while vmscan
+      is active
+
+  * SRU: Enable middle button of touchpad on ThinkPad P72 (LP: #1793463)
+    - Input: elantech - enable middle button of touchpad on ThinkPad P72
+
+  * Improvements to the kernel source package preparation (LP: #1793461)
+    - [Packaging] startnewrelease: add support for backport kernels
+
+  * Fix unusable NVIDIA GPU after S3 (LP: #1793338)
+    - SAUCE: PCI: Reprogram bridge prefetch registers on resume
+
+  * Error reported when creating ZFS pool with "-t" option, despite successful
+    pool creation (LP: #1769937)
+    - SAUCE: (noup) Update zfs to 0.7.9-3ubuntu6
+
+  * device hotplug of vfio devices can lead to deadlock in vfio_pci_release
+    (LP: #1792099)
+    - SAUCE: vfio -- release device lock before userspace requests
+
+  * Miscellaneous Ubuntu changes
+    - [Packaging] retpoline -- fix temporary filenaming
+    - CONFIG_BCH_CONST_PARAMS=n
+    - Packaging: final-checks: remove trailing backport suffix
+    - SAUCE: import aufs driver
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.19-rc5
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Tue, 25 Sep 2018 16:32:24 -0500
+
+linux (4.19.0-0.1) cosmic; urgency=medium
+
+  * Miscellaneous Ubuntu changes
+    - ubuntu -- disable vbox build
+    - Disable zfs build
+    - SAUCE: Import aufs driver
+    - Update dropped.txt
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.19-rc3
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Thu, 13 Sep 2018 07:54:47 -0500
+
+linux (4.19.0-0.0) cosmic; urgency=medium
+
+  * Dummy entry.
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Thu, 13 Sep 2018 06:44:09 -0500
+
+linux (4.18.0-8.9) cosmic; urgency=medium
+
+  * linux: 4.18.0-8.9 -proposed tracker (LP: #1791663)
+
+  * Cosmic update to v4.18.7 stable release (LP: #1791660)
+    - rcu: Make expedited GPs handle CPU 0 being offline
+    - net: 6lowpan: fix reserved space for single frames
+    - net: mac802154: tx: expand tailroom if necessary
+    - 9p/net: Fix zero-copy path in the 9p virtio transport
+    - spi: davinci: fix a NULL pointer dereference
+    - spi: pxa2xx: Add support for Intel Ice Lake
+    - spi: spi-fsl-dspi: Fix imprecise abort on VF500 during probe
+    - spi: cadence: Change usleep_range() to udelay(), for atomic context
+    - mmc: block: Fix unsupported parallel dispatch of requests
+    - mmc: renesas_sdhi_internal_dmac: mask DMAC interrupts
+    - mmc: renesas_sdhi_internal_dmac: fix #define RST_RESERVED_BITS
+    - readahead: stricter check for bdi io_pages
+    - block: fix infinite loop if the device loses discard capability
+    - block: blk_init_allocated_queue() set q->fq as NULL in the fail case
+    - block: really disable runtime-pm for blk-mq
+    - blkcg: Introduce blkg_root_lookup()
+    - block: Introduce blk_exit_queue()
+    - block: Ensure that a request queue is dissociated from the cgroup controller
+    - apparmor: fix bad debug check in apparmor_secid_to_secctx()
+    - dma-buf: Move BUG_ON from _add_shared_fence to _add_shared_inplace
+    - libertas: fix suspend and resume for SDIO connected cards
+    - media: Revert "[media] tvp5150: fix pad format frame height"
+    - mailbox: xgene-slimpro: Fix potential NULL pointer dereference
+    - Replace magic for trusting the secondary keyring with #define
+    - Fix kexec forbidding kernels signed with keys in the secondary keyring to
+      boot
+    - powerpc/fadump: handle crash memory ranges array index overflow
+    - powerpc/64s: Fix page table fragment refcount race vs speculative references
+    - powerpc/pseries: Fix endianness while restoring of r3 in MCE handler.
+    - powerpc/pkeys: Give all threads control of their key permissions
+    - powerpc/pkeys: Deny read/write/execute by default
+    - powerpc/pkeys: key allocation/deallocation must not change pkey registers
+    - powerpc/pkeys: Save the pkey registers before fork
+    - powerpc/pkeys: Fix calculation of total pkeys.
+    - powerpc/pkeys: Preallocate execute-only key
+    - powerpc/nohash: fix pte_access_permitted()
+    - powerpc64/ftrace: Include ftrace.h needed for enable/disable calls
+    - powerpc/powernv/pci: Work around races in PCI bridge enabling
+    - cxl: Fix wrong comparison in cxl_adapter_context_get()
+    - IB/mlx5: Honor cnt_set_id_valid flag instead of set_id
+    - IB/mlx5: Fix leaking stack memory to userspace
+    - IB/srpt: Fix srpt_cm_req_recv() error path (1/2)
+    - IB/srpt: Fix srpt_cm_req_recv() error path (2/2)
+    - IB/srpt: Support HCAs with more than two ports
+    - overflow.h: Add arithmetic shift helper
+    - RDMA/mlx5: Fix shift overflow in mlx5_ib_create_wq
+    - ib_srpt: Fix a use-after-free in srpt_close_ch()
+    - ib_srpt: Fix a use-after-free in __srpt_close_all_ch()
+    - RDMA/rxe: Set wqe->status correctly if an unexpected response is received
+    - 9p: fix multiple NULL-pointer-dereferences
+    - fs/9p/xattr.c: catch the error of p9_client_clunk when setting xattr failed
+    - 9p/virtio: fix off-by-one error in sg list bounds check
+    - net/9p/client.c: version pointer uninitialized
+    - net/9p/trans_fd.c: fix race-condition by flushing workqueue before the
+      kfree()
+    - dm integrity: change 'suspending' variable from bool to int
+    - dm thin: stop no_space_timeout worker when switching to write-mode
+    - dm cache metadata: save in-core policy_hint_size to on-disk superblock
+    - dm cache metadata: set dirty on all cache blocks after a crash
+    - dm crypt: don't decrease device limits
+    - dm writecache: fix a crash due to reading past end of dirty_bitmap
+    - uart: fix race between uart_put_char() and uart_shutdown()
+    - Drivers: hv: vmbus: Fix the offer_in_progress in vmbus_process_offer()
+    - Drivers: hv: vmbus: Reset the channel callback in vmbus_onoffer_rescind()
+    - iio: sca3000: Fix missing return in switch
+    - iio: ad9523: Fix displayed phase
+    - iio: ad9523: Fix return value for ad952x_store()
+    - extcon: Release locking when sending the notification of connector state
+    - eventpoll.h: wrap casts in () properly
+    - vmw_balloon: fix inflation of 64-bit GFNs
+    - vmw_balloon: do not use 2MB without batching
+    - vmw_balloon: VMCI_DOORBELL_SET does not check status
+    - vmw_balloon: fix VMCI use when balloon built into kernel
+    - rtc: omap: fix resource leak in registration error path
+    - rtc: omap: fix potential crash on power off
+    - tracing: Do not call start/stop() functions when tracing_on does not change
+    - tracing/blktrace: Fix to allow setting same value
+    - printk/tracing: Do not trace printk_nmi_enter()
+    - livepatch: Validate module/old func name length
+    - uprobes: Use synchronize_rcu() not synchronize_sched()
+    - mfd: hi655x: Fix regmap area declared size for hi655x
+    - ovl: fix wrong use of impure dir cache in ovl_iterate()
+    - ACPICA: AML Parser: skip opcodes that open a scope upon parse failure
+    - ACPICA: Clear status of all events when entering sleep states
+    - drivers/block/zram/zram_drv.c: fix bug storing backing_dev
+    - sched: idle: Avoid retaining the tick when it has been stopped
+    - cpuidle: menu: Handle stopped tick more aggressively
+    - cpufreq: governor: Avoid accessing invalid governor_data
+    - PM / sleep: wakeup: Fix build error caused by missing SRCU support
+    - ALSA: ac97: fix device initialization in the compat layer
+    - ALSA: ac97: fix check of pm_runtime_get_sync failure
+    - ALSA: ac97: fix unbalanced pm_runtime_enable
+    - i2c: designware: Re-init controllers with pm_disabled set on resume
+    - KVM: VMX: fixes for vmentry_l1d_flush module parameter
+    - KVM: PPC: Book3S: Fix guest DMA when guest partially backed by THP pages
+    - xtensa: limit offsets in __loop_cache_{all,page}
+    - xtensa: increase ranges in ___invalidate_{i,d}cache_all
+    - block, bfq: return nbytes and not zero from struct cftype .write() method
+    - pnfs/blocklayout: off by one in bl_map_stripe()
+    - nfsd: fix leaked file lock with nfs exported overlayfs
+    - NFSv4 client live hangs after live data migration recovery
+    - NFSv4: Fix locking in pnfs_generic_recover_commit_reqs
+    - NFSv4: Fix a sleep in atomic context in nfs4_callback_sequence()
+    - ARM: tegra: Fix Tegra30 Cardhu PCA954x reset
+    - ARM: dts: am57xx-idk: Enable dual role for USB2 port
+    - pwm: omap-dmtimer: Return -EPROBE_DEFER if no dmtimer platform data
+    - mm/tlb: Remove tlb_remove_table() non-concurrent condition
+    - iommu/ipmmu-vmsa: Don't register as BUS IOMMU if machine doesn't have IPMMU-
+      VMSA
+    - iommu/vt-d: Add definitions for PFSID
+    - iommu/vt-d: Fix dev iotlb pfsid use
+    - sys: don't hold uts_sem while accessing userspace memory
+    - userns: move user access out of the mutex
+    - ubifs: Fix memory leak in lprobs self-check
+    - Revert "UBIFS: Fix potential integer overflow in allocation"
+    - ubifs: Check data node size before truncate
+    - ubifs: xattr: Don't operate on deleted inodes
+    - ubifs: Fix directory size calculation for symlinks
+    - ubifs: Fix synced_i_size calculation for xattr inodes
+    - pwm: tiehrpwm: Don't use emulation mode bits to control PWM output
+    - pwm: tiehrpwm: Fix disabling of output of PWMs
+    - fb: fix lost console when the user unplugs a USB adapter
+    - udlfb: fix semaphore value leak
+    - udlfb: fix display corruption of the last line
+    - udlfb: don't switch if we are switching to the same videomode
+    - udlfb: set optimal write delay
+    - udlfb: make a local copy of fb_ops
+    - udlfb: handle allocation failure
+    - udlfb: set line_length in dlfb_ops_set_par
+    - getxattr: use correct xattr length
+    - libnvdimm: Use max contiguous area for namespace size
+    - libnvdimm: fix ars_status output length calculation
+    - bcache: release dc->writeback_lock properly in bch_writeback_thread()
+    - kconfig: fix "Can't open ..." in parallel build
+    - perf auxtrace: Fix queue resize
+    - crypto: vmx - Fix sleep-in-atomic bugs
+    - crypto: aesni - Use unaligned loads from gcm_context_data
+    - crypto: arm64/sm4-ce - check for the right CPU feature bit
+    - crypto: caam - fix DMA mapping direction for RSA forms 2 & 3
+    - crypto: caam/jr - fix descriptor DMA unmapping
+    - crypto: caam/qi - fix error path in xts setkey
+    - fs/quota: Fix spectre gadget in do_quotactl
+    - udf: Fix mounting of Win7 created UDF filesystems
+    - cpuidle: menu: Retain tick when shallow state is selected
+    - arm64: mm: always enable CONFIG_HOLES_IN_ZONE
+    - Linux 4.18.7
+
+  * CVE-2017-5715
+    - s390: detect etoken facility
+    - KVM: s390: add etoken support for guests
+
+  * Missing Intel GPU pci-id's (LP: #1789924)
+    - drm/i915/whl: Introducing Whiskey Lake platform
+    - drm/i915/aml: Introducing Amber Lake platform
+    - drm/i915/cfl: Add a new CFL PCI ID.
+
+  * [18.10 FEAT] Add kernel config options for SMC-R/D (LP: #1789934)
+    - s390/ism: add device driver for internal shared memory
+    - CONFIG_ISM=y for s390
+
+  * Cosmic update to v4.18.6 stable release (LP: #1791105)
+    - PATCH scripts/kernel-doc
+    - scripts/kernel-doc: Escape all literal braces in regexes
+    - scsi: libsas: dynamically allocate and free ata host
+    - xprtrdma: Fix disconnect regression
+    - mei: don't update offset in write
+    - cifs: add missing support for ACLs in SMB 3.11
+    - CIFS: fix uninitialized ptr deref in smb2 signing
+    - cifs: add missing debug entries for kconfig options
+    - cifs: use a refcount to protect open/closing the cached file handle
+    - cifs: check kmalloc before use
+    - smb3: enumerating snapshots was leaving part of the data off end
+    - smb3: Do not send SMB3 SET_INFO if nothing changed
+    - smb3: don't request leases in symlink creation and query
+    - smb3: fill in statfs fsid and correct namelen
+    - btrfs: use correct compare function of dirty_metadata_bytes
+    - btrfs: don't leak ret from do_chunk_alloc
+    - Btrfs: fix mount failure after fsync due to hard link recreation
+    - Btrfs: fix btrfs_write_inode vs delayed iput deadlock
+    - Btrfs: fix send failure when root has deleted files still open
+    - Btrfs: send, fix incorrect file layout after hole punching beyond eof
+    - hwmon: (k10temp) 27C Offset needed for Threadripper2
+    - bpf, arm32: fix stack var offset in jit
+    - regulator: arizona-ldo1: Use correct device to get enable GPIO
+    - iommu/arm-smmu: Error out only if not enough context interrupts
+    - printk: Split the code for storing a message into the log buffer
+    - printk: Create helper function to queue deferred console handling
+    - printk/nmi: Prevent deadlock when accessing the main log buffer in NMI
+    - kprobes/arm64: Fix %p uses in error messages
+    - arm64: Fix mismatched cache line size detection
+    - arm64: Handle mismatched cache type
+    - arm64: mm: check for upper PAGE_SHIFT bits in pfn_valid()
+    - arm64: dts: rockchip: corrected uart1 clock-names for rk3328
+    - KVM: arm/arm64: Fix potential loss of ptimer interrupts
+    - KVM: arm/arm64: Fix lost IRQs from emulated physcial timer when blocked
+    - KVM: arm/arm64: Skip updating PMD entry if no change
+    - KVM: arm/arm64: Skip updating PTE entry if no change
+    - s390/kvm: fix deadlock when killed by oom
+    - perf kvm: Fix subcommands on s390
+    - stop_machine: Reflow cpu_stop_queue_two_works()
+    - stop_machine: Atomically queue and wake stopper threads
+    - ext4: check for NUL characters in extended attribute's name
+    - ext4: use ext4_warning() for sb_getblk failure
+    - ext4: sysfs: print ext4_super_block fields as little-endian
+    - ext4: reset error code in ext4_find_entry in fallback
+    - ext4: fix race when setting the bitmap corrupted flag
+    - x86/gpu: reserve ICL's graphics stolen memory
+    - platform/x86: wmi: Do not mix pages and kmalloc
+    - platform/x86: ideapad-laptop: Apply no_hw_rfkill to Y20-15IKBM, too
+    - mm: move tlb_table_flush to tlb_flush_mmu_free
+    - mm/tlb, x86/mm: Support invalidating TLB caches for RCU_TABLE_FREE
+    - x86/speculation/l1tf: Fix overflow in l1tf_pfn_limit() on 32bit
+    - x86/speculation/l1tf: Fix off-by-one error when warning that system has too
+      much RAM
+    - x86/speculation/l1tf: Suggest what to do on systems with too much RAM
+    - x86/vdso: Fix vDSO build if a retpoline is emitted
+    - x86/process: Re-export start_thread()
+    - KVM: x86: ensure all MSRs can always be KVM_GET/SET_MSR'd
+    - KVM: x86: SVM: Call x86_spec_ctrl_set_guest/host() with interrupts disabled
+    - fuse: Don't access pipe->buffers without pipe_lock()
+    - fuse: fix initial parallel dirops
+    - fuse: fix double request_end()
+    - fuse: fix unlocked access to processing queue
+    - fuse: umount should wait for all requests
+    - fuse: Fix oops at process_init_reply()
+    - fuse: Add missed unlock_page() to fuse_readpages_fill()
+    - lib/vsprintf: Do not handle %pO[^F] as %px
+    - udl-kms: change down_interruptible to down
+    - udl-kms: handle allocation failure
+    - udl-kms: fix crash due to uninitialized memory
+    - udl-kms: avoid division
+    - b43legacy/leds: Ensure NUL-termination of LED name string
+    - b43/leds: Ensure NUL-termination of LED name string
+    - ASoC: dpcm: don't merge format from invalid codec dai
+    - ASoC: zte: Fix incorrect PCM format bit usages
+    - ASoC: sirf: Fix potential NULL pointer dereference
+    - ASoC: wm_adsp: Correct DSP pointer for preloader control
+    - soc: qcom: rmtfs-mem: fix memleak in probe error paths
+    - pinctrl: freescale: off by one in imx1_pinconf_group_dbg_show()
+    - scsi: qla2xxx: Fix stalled relogin
+    - x86/vdso: Fix lsl operand order
+    - x86/nmi: Fix NMI uaccess race against CR3 switching
+    - x86/irqflags: Mark native_restore_fl extern inline
+    - x86/spectre: Add missing family 6 check to microcode check
+    - x86/speculation/l1tf: Increase l1tf memory limit for Nehalem+
+    - hwmon: (nct6775) Fix potential Spectre v1
+    - x86/entry/64: Wipe KASAN stack shadow before rewind_stack_do_exit()
+    - x86: Allow generating user-space headers without a compiler
+    - s390/mm: fix addressing exception after suspend/resume
+    - s390/lib: use expoline for all bcr instructions
+    - s390: fix br_r1_trampoline for machines without exrl
+    - s390/qdio: reset old sbal_state flags
+    - s390/numa: move initial setup of node_to_cpumask_map
+    - s390/purgatory: Fix crash with expoline enabled
+    - s390/purgatory: Add missing FORCE to Makefile targets
+    - kprobes: Show blacklist addresses as same as kallsyms does
+    - kprobes: Replace %p with other pointer types
+    - kprobes/arm: Fix %p uses in error messages
+    - kprobes: Make list and blacklist root user read only
+    - MIPS: Correct the 64-bit DSP accumulator register size
+    - MIPS: memset.S: Fix byte_fixup for MIPSr6
+    - MIPS: Always use -march=<arch>, not -<arch> shortcuts
+    - MIPS: Change definition of cpu_relax() for Loongson-3
+    - MIPS: lib: Provide MIPS64r6 __multi3() for GCC < 7
+    - tpm: Return the actual size when receiving an unsupported command
+    - tpm: separate cmd_ready/go_idle from runtime_pm
+    - scsi: mpt3sas: Fix calltrace observed while running IO & reset
+    - scsi: mpt3sas: Fix _transport_smp_handler() error path
+    - scsi: sysfs: Introduce sysfs_{un,}break_active_protection()
+    - scsi: core: Avoid that SCSI device removal through sysfs triggers a deadlock
+    - iscsi target: fix session creation failure handling
+    - mtd: rawnand: hynix: Use ->exec_op() in hynix_nand_reg_write_op()
+    - mtd: rawnand: fsmc: Stop using chip->read_buf()
+    - mtd: rawnand: marvell: add suspend and resume hooks
+    - mtd: rawnand: qcom: wait for desc completion in all BAM channels
+    - clk: rockchip: fix clk_i2sout parent selection bits on rk3399
+    - clk: npcm7xx: fix memory allocation
+    - PM / clk: signedness bug in of_pm_clk_add_clks()
+    - power: generic-adc-battery: fix out-of-bounds write when copying channel
+      properties
+    - power: generic-adc-battery: check for duplicate properties copied from iio
+      channels
+    - watchdog: Mark watchdog touch functions as notrace
+    - cdrom: Fix info leak/OOB read in cdrom_ioctl_drive_status
+    - x86/dumpstack: Don't dump kernel memory based on usermode RIP
+    - Linux 4.18.6
+    - updateconfigs after v4.18.6 stable update
+
+  * random oopses on s390 systems using NVMe devices (LP: #1790480)
+    - s390/pci: fix out of bounds access during irq setup
+
+  * [18.10 FEAT] zcrypt DD: introduce APQN tags to support deterministic driver
+    binding (LP: #1784331)
+    - s390/zcrypt: code beautify
+    - s390/zcrypt: AP bus support for alternate driver(s)
+    - s390/zcrypt: hex string mask improvements for apmask and aqmask.
+
+  * performance drop with ATS enabled (LP: #1788097)
+    - powerpc/powernv: Fix concurrency issue with npu->mmio_atsd_usage
+
+  * Fix MCE handling for user access of poisoned device-dax mapping
+    (LP: #1774366)
+    - device-dax: Convert to vmf_insert_mixed and vm_fault_t
+    - device-dax: Enable page_mapping()
+    - device-dax: Set page->index
+    - filesystem-dax: Set page->index
+    - mm, madvise_inject_error: Disable MADV_SOFT_OFFLINE for ZONE_DEVICE pages
+    - mm, dev_pagemap: Do not clear ->mapping on final put
+    - mm, madvise_inject_error: Let memory_failure() optionally take a page
+      reference
+    - mm, memory_failure: Collect mapping size in collect_procs()
+    - filesystem-dax: Introduce dax_lock_mapping_entry()
+    - mm, memory_failure: Teach memory_failure() about dev_pagemap pages
+    - x86/mm/pat: Prepare {reserve, free}_memtype() for "decoy" addresses
+    - x86/memory_failure: Introduce {set, clear}_mce_nospec()
+    - libnvdimm, pmem: Restore page attributes when clearing errors
+
+  * Reconcile hns3 SAUCE patches with upstream (LP: #1787477)
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: fix comments for
+      hclge_get_ring_chain_from_mbx"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: fix for using wrong mask and
+      shift in hclge_get_ring_chain_from_mbx"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: fix for reset_level default
+      assignment probelm"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: remove unnecessary ring
+      configuration operation while resetting"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: fix return value error in
+      hns3_reset_notify_down_enet"
+    - Revert "UBUNTU: SAUCE: net: hns3: Fix for phy link issue when using marvell
+      phy driver"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: separate roce from nic when
+      resetting"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: correct reset event status
+      register"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: prevent to request reset
+      frequently"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: reset net device with rtnl_lock"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: modify the order of initializeing
+      command queue register"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: prevent sending command during
+      global or core reset"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: Use roce handle when calling roce
+      callback function"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: remove the warning when clear
+      reset cause"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: fix get_vector ops in
+      hclgevf_main module"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: fix warning bug when doing lp
+      selftest"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: Add configure for mac minimal
+      frame size"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: fix for mailbox message truncated
+      problem"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: fix for l4 checksum offload bug"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: fix for waterline not setting
+      correctly"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: fix for mac pause not disable in
+      pfc mode"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: fix tc setup when netdev is first
+      up"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: Add calling roce callback
+      function when link status change"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: optimize the process of notifying
+      roce client"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: Add pf reset for hip08 RoCE"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: Add SPDX tags to hns3 driver"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: remove unused struct member and
+      definition"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: fix mislead parameter name"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: modify inconsistent bit mask
+      macros"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: use decimal for bit offset
+      macros"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: fix unreasonable code comments"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: remove extra space and brackets"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: standardize the handle of return
+      value"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: remove some redundant
+      assignments"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: modify hnae_ to hnae3_"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: use dma_zalloc_coherent instead
+      of kzalloc/dma_map_single"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: give default option while
+      dependency HNS3 set"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: remove some unused members of
+      some structures"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: remove a redundant
+      hclge_cmd_csq_done"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: using modulo for cyclic counters
+      in hclge_cmd_send"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: simplify hclge_cmd_csq_clean"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: remove some redundant
+      assignments"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: remove useless code in
+      hclge_cmd_send"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: remove unused
+      hclge_ring_to_dma_dir"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: use lower_32_bits and
+      upper_32_bits"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: remove back in struct hclge_hw"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: add unlikely for error check"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: remove the Redundant put_vector
+      in hns3_client_uninit"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: print the ret value in error
+      information"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: extraction an interface for state
+      state init|uninit"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: remove unused head file in
+      hnae3.c"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: add l4_type check for both ipv4
+      and ipv6"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: add vector status check before
+      free vector"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: rename the interface for
+      init_client_instance and uninit_client_instance"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: remove hclge_get_vector_index
+      from hclge_bind_ring_with_vector"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: RX BD information valid only in
+      last BD except VLD bit and buffer size"
+    - Revert "UBUNTU: SAUCE: {topost} net: hns3: add support for serdes loopback
+      selftest"
+    - net: hns3: Updates RX packet info fetch in case of multi BD
+    - net: hns3: remove hclge_get_vector_index from hclge_bind_ring_with_vector
+    - net: hns3: rename the interface for init_client_instance and
+      uninit_client_instance
+    - net: hns3: add vector status check before free vector
+    - net: hns3: add l4_type check for both ipv4 and ipv6
+    - net: hns3: add unlikely for error check
+    - net: hns3: remove unused head file in hnae3.c
+    - net: hns3: extraction an interface for state init|uninit
+    - net: hns3: print the ret value in error information
+    - net: hns3: remove the Redundant put_vector in hns3_client_uninit
+    - net: hns3: remove back in struct hclge_hw
+    - net: hns3: use lower_32_bits and upper_32_bits
+    - net: hns3: remove unused hclge_ring_to_dma_dir
+    - net: hns3: remove useless code in hclge_cmd_send
+    - net: hns3: remove some redundant assignments
+    - net: hns3: simplify hclge_cmd_csq_clean
+    - net: hns3: remove a redundant hclge_cmd_csq_done
+    - net: hns3: remove some unused members of some structures
+    - net: hns3: give default option while dependency HNS3 set
+    - net: hns3: use dma_zalloc_coherent instead of kzalloc/dma_map_single
+    - net: hns3: modify hnae_ to hnae3_
+    - net: hns3: Fix tc setup when netdev is first up
+    - net: hns3: Fix for mac pause not disable in pfc mode
+    - net: hns3: Fix for waterline not setting correctly
+    - net: hns3: Fix for l4 checksum offload bug
+    - net: hns3: Fix for mailbox message truncated problem
+    - net: hns3: Add configure for mac minimal frame size
+    - net: hns3: Fix warning bug when doing lp selftest
+    - net: hns3: Fix get_vector ops in hclgevf_main module
+    - net: hns3: Remove the warning when clear reset cause
+    - net: hns3: Prevent sending command during global or core reset
+    - net: hns3: Modify the order of initializing command queue register
+    - net: hns3: Reset net device with rtnl_lock
+    - net: hns3: Prevent to request reset frequently
+    - net: hns3: Correct reset event status register
+    - net: hns3: Fix return value error in hns3_reset_notify_down_enet
+    - net: hns3: remove unnecessary ring configuration operation while resetting
+    - net: hns3: Fix for reset_level default assignment probelm
+    - net: hns3: Fix for using wrong mask and shift in
+      hclge_get_ring_chain_from_mbx
+    - net: hns3: Fix comments for hclge_get_ring_chain_from_mbx
+    - net: hns3: Remove some redundant assignments
+    - net: hns3: Standardize the handle of return value
+    - net: hns3: Remove extra space and brackets
+    - net: hns3: Correct unreasonable code comments
+    - net: hns3: Use decimal for bit offset macros
+    - net: hns3: Modify inconsistent bit mask macros
+    - net: hns3: Fix misleading parameter name
+    - net: hns3: Remove unused struct member and definition
+    - net: hns3: Add SPDX tags to HNS3 PF driver
+    - net: hns3: Add support for serdes loopback selftest
+    - net: hns3: Fix for phy link issue when using marvell phy driver
+
+  * [Regression] kernel crashdump fails on arm64 (LP: #1786878)
+    - arm64: export memblock_reserve()d regions via /proc/iomem
+    - drivers: acpi: add dependency of EFI for arm64
+    - efi/arm: preserve early mapping of UEFI memory map longer for BGRT
+    - efi/arm: map UEFI memory map even w/o runtime services enabled
+    - arm64: acpi: fix alignment fault in accessing ACPI
+    - [Config] CONFIG_ARCH_SUPPORTS_ACPI=y
+    - arm64: fix ACPI dependencies
+    - ACPI: fix menuconfig presentation of ACPI submenu
+
+  * TB 16 issue on Dell Lattitude 7490 with large amount of data (LP: #1785780)
+    - r8152: disable RX aggregation on new Dell TB16 dock
+
+  * Support Power Management for Thunderbolt Controller  (LP: #1789358)
+    - thunderbolt: Use 64-bit DMA mask if supported by the platform
+    - thunderbolt: Do not unnecessarily call ICM get route
+    - thunderbolt: No need to take tb->lock in domain suspend/complete
+    - thunderbolt: Use correct ICM commands in system suspend
+    - thunderbolt: Add support for runtime PM
+
+  * Enable AMD PCIe MP2 for AMDI0011 (LP: #1773940)
+    - SAUCE: i2c:amd I2C Driver based on PCI Interface for upcoming platform
+    - SAUCE: i2c:amd move out pointer in union i2c_event_base
+    - SAUCE: i2c:amd Depends on ACPI
+    - [Config] i2c: CONFIG_I2C_AMD_MP2=y on x86
+
+  * Microphone cannot be detected with front panel audio combo jack on HP Z8-G4
+    machine (LP: #1789145)
+    - ALSA: hda/realtek - Fix HP Headset Mic can't record
+
+  * Please enable CONFIG_PAGE_POISONING (LP: #1783651)
+    - [Config] Enable CONFIG_PAGE_POISONING configs
+
+  * Tango platform uses __initcall without further checks (LP: #1787945)
+    - [Config] disable ARCH_TANGO
+
+  * [18.10 FEAT] SMC-Direct (LP: #1786902)
+    - net/smc: determine port attributes independent from pnet table
+    - net/smc: add pnetid support
+    - net/smc: add base infrastructure for SMC-D and ISM
+    - net/smc: add pnetid support for SMC-D and ISM
+    - net/smc: add SMC-D support in CLC messages
+    - net/smc: add SMC-D support in data transfer
+    - net/smc: add SMC-D support in af_smc
+    - net/smc: add SMC-D diag support
+    - net/smc: provide smc mode in smc_diag.c
+    - net/smc: eliminate cursor read and write calls
+    - net/smc: add function to get link group from link
+    - net/smc: use DECLARE_BITMAP for rtokens_used_mask
+    - net/smc: remove local variable page in smc_rx_splice()
+    - net/smc: Remove a WARN_ON() statement
+    - net/smc: Simplify ib_post_(send|recv|srq_recv)() calls
+    - net/smc: fewer parameters for smc_llc_send_confirm_link()
+    - net/smc: use correct vlan gid of RoCE device
+    - net/smc: provide fallback reason code
+    - net/smc: improve delete link processing
+    - net: simplify sock_poll_wait
+    - net/smc: send response to test link signal
+
+  * Miscellaneous Ubuntu changes
+    - [Config] update annotations for CONFIG_CRYPTO_SPECK_NEON
+    - [Config] fix up annotatios for CONFIG_CRYPTO_SPECK
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 10 Sep 2018 07:08:38 -0500
+
+linux (4.18.0-7.8) cosmic; urgency=medium
+
+  * linux: 4.18.0-7.8 -proposed tracker (LP: #1789459)
+
+  * pmtu.sh fails on 4.18 kernel (LP: #1789436)
+    - SAUCE: Revert "vti6: fix PMTU caching and reporting on xmit"
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Tue, 28 Aug 2018 11:08:51 -0500
+
+linux (4.18.0-6.7) cosmic; urgency=medium
+
+  * linux: 4.18.0-6.7 -proposed tracker (LP: #1788881)
+
+  * systemd 237-3ubuntu10 ADT test failure with linux 4.18.0-5.6 (LP: #1787440)
+    - Config: Disable BPF_JIT_ALWAYS_ON on i386
+
+  * execveat03 in ubuntu_ltp_syscalls failed on X/B (LP: #1786729)
+    - cap_inode_getsecurity: use d_find_any_alias() instead of d_find_alias()
+
+  * Cosmic update to v4.18.5 stable release (LP: #1788874)
+    - EDAC: Add missing MEM_LRDDR4 entry in edac_mem_types[]
+    - pty: fix O_CLOEXEC for TIOCGPTPEER
+    - mm: Allow non-direct-map arguments to free_reserved_area()
+    - x86/mm/init: Pass unconverted symbol addresses to free_init_pages()
+    - x86/mm/init: Add helper for freeing kernel image pages
+    - x86/mm/init: Remove freed kernel image areas from alias mapping
+    - powerpc64s: Show ori31 availability in spectre_v1 sysfs file not v2
+    - ext4: fix spectre gadget in ext4_mb_regular_allocator()
+    - drm/i915/kvmgt: Fix potential Spectre v1
+    - drm/amdgpu/pm: Fix potential Spectre v1
+    - parisc: Remove unnecessary barriers from spinlock.h
+    - parisc: Remove ordered stores from syscall.S
+    - PCI: Restore resized BAR state on resume
+    - PCI / ACPI / PM: Resume all bridges on suspend-to-RAM
+    - PCI: hotplug: Don't leak pci_slot on registration failure
+    - PCI: aardvark: Size bridges before resources allocation
+    - PCI: Skip MPS logic for Virtual Functions (VFs)
+    - PCI: pciehp: Fix use-after-free on unplug
+    - PCI: pciehp: Fix unprotected list iteration in IRQ handler
+    - i2c: core: ACPI: Properly set status byte to 0 for multi-byte writes
+    - i2c: imx: Fix race condition in dma read
+    - reiserfs: fix broken xattr handling (heap corruption, bad retval)
+    - Linux 4.18.5
+
+  * [18.10 FEAT] Add kernel config option "CONFIG_SCLP_OFB" (LP: #1787898)
+    - [Config] CONFIG_SCLP_OFB=y for s390x
+
+  * errors when scanning partition table of corrupted AIX disk (LP: #1787281)
+    - partitions/aix: fix usage of uninitialized lv_info and lvname structures
+    - partitions/aix: append null character to print data from disk
+
+  * Apply NVMe bugfix from Google that bjf asked for (LP: #1787635)
+    - nvme-pci: add a memory barrier to nvme_dbbuf_update_and_check_event
+
+  * ThinkPad systems have no HDMI sound when using the nvidia GPU (LP: #1787058)
+    - ACPI / OSI: Add OEM _OSI string to enable NVidia HDMI audio
+
+  * Cosmic update to v4.18.4 stable release (LP: #1788454)
+    - l2tp: use sk_dst_check() to avoid race on sk->sk_dst_cache
+    - net_sched: fix NULL pointer dereference when delete tcindex filter
+    - net_sched: Fix missing res info when create new tc_index filter
+    - r8169: don't use MSI-X on RTL8168g
+    - ALSA: hda - Sleep for 10ms after entering D3 on Conexant codecs
+    - ALSA: hda - Turn CX8200 into D3 as well upon reboot
+    - ALSA: vx222: Fix invalid endian conversions
+    - ALSA: virmidi: Fix too long output trigger loop
+    - ALSA: cs5535audio: Fix invalid endian conversion
+    - ALSA: dice: fix wrong copy to rx parameters for Alesis iO26
+    - ALSA: hda: Correct Asrock B85M-ITX power_save blacklist entry
+    - ALSA: memalloc: Don't exceed over the requested size
+    - ALSA: vxpocket: Fix invalid endian conversions
+    - ALSA: seq: Fix poll() error return
+    - media: gl861: fix probe of dvb_usb_gl861
+    - USB: serial: sierra: fix potential deadlock at close
+    - USB: serial: pl2303: add a new device id for ATEN
+    - USB: option: add support for DW5821e
+    - ACPI / PM: save NVS memory for ASUS 1025C laptop
+    - tty: serial: 8250: Revert NXP SC16C2552 workaround
+    - serial: 8250_exar: Read INT0 from slave device, too
+    - serial: 8250_dw: always set baud rate in dw8250_set_termios
+    - serial: 8250_dw: Add ACPI support for uart on Broadcom SoC
+    - uio: fix wrong return value from uio_mmap()
+    - misc: sram: fix resource leaks in probe error path
+    - Revert "uio: use request_threaded_irq instead"
+    - Bluetooth: avoid killing an already killed socket
+    - isdn: Disable IIOCDBGVAR
+    - net: sock_diag: Fix spectre v1 gadget in __sock_diag_cmd()
+    - hv/netvsc: Fix NULL dereference at single queue mode fallback
+    - r8169: don't use MSI-X on RTL8106e
+    - ip_vti: fix a null pointer deferrence when create vti fallback tunnel
+    - net: ethernet: mvneta: Fix napi structure mixup on armada 3700
+    - net: mvneta: fix mvneta_config_rss on armada 3700
+    - cls_matchall: fix tcf_unbind_filter missing
+    - Linux 4.18.4
+
+  * Cosmic update to v4.18.3 stable release (LP: #1788453)
+    - x86/speculation/l1tf: Exempt zeroed PTEs from inversion
+    - Linux 4.18.3
+
+  * Cosmic update to v4.18.2 stable release (LP: #1788452)
+    - x86/l1tf: Fix build error seen if CONFIG_KVM_INTEL is disabled
+    - x86: i8259: Add missing include file
+    - x86/hyper-v: Check for VP_INVAL in hyperv_flush_tlb_others()
+    - x86/platform/UV: Mark memblock related init code and data correctly
+    - x86/mm/pti: Clear Global bit more aggressively
+    - xen/pv: Call get_cpu_address_sizes to set x86_virt/phys_bits
+    - x86/mm: Disable ioremap free page handling on x86-PAE
+    - kbuild: verify that $DEPMOD is installed
+    - crypto: ccree - fix finup
+    - crypto: ccree - fix iv handling
+    - crypto: ccp - Check for NULL PSP pointer at module unload
+    - crypto: ccp - Fix command completion detection race
+    - crypto: x86/sha256-mb - fix digest copy in sha256_mb_mgr_get_comp_job_avx2()
+    - crypto: vmac - require a block cipher with 128-bit block size
+    - crypto: vmac - separate tfm and request context
+    - crypto: blkcipher - fix crash flushing dcache in error path
+    - crypto: ablkcipher - fix crash flushing dcache in error path
+    - crypto: skcipher - fix aligning block size in skcipher_copy_iv()
+    - crypto: skcipher - fix crash flushing dcache in error path
+    - ioremap: Update pgtable free interfaces with addr
+    - x86/mm: Add TLB purge to free pmd/pte page interfaces
+    - Linux 4.18.2
+
+  * Cosmic update to v4.18.2 stable release (LP: #1788452) // CVE-2018-9363
+    - Bluetooth: hidp: buffer overflow in hidp_process_report
+
+  * linux-cloud-tools-common: Ensure hv-kvp-daemon.service starts before
+    walinuxagent.service (LP: #1739107)
+    - [Debian] hyper-v -- Ensure that hv-kvp-daemon.service starts before
+      walinuxagent.service
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: ipvs: remove nbsp characters from Kconfig
+    - [Config] CONFIG_MPROFILE_KERNEL=y for ppc64el
+    - [Config] CONFIG_DRM_RCAR_LVDS=m for snapdragon
+    - [Config] CONFIG_MDIO_MSCC_MIIM=n for s390x
+    - [Config] CONFIG_NET_VENDOR_MICROSEMI=n, CONFIG_NET_VENDOR_NI=n for s390x
+    - [Config] update annotations following config review
+    - [Debian] set CROSS_COMPILE when generating kernel configs
+    - [Config] Disable the Speck cipher
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Fri, 24 Aug 2018 14:18:15 -0500
+
+linux (4.18.0-5.6) cosmic; urgency=medium
+
+  * Cosmic update to v4.18.1 stable release (LP: #1787264)
+    - x86/paravirt: Fix spectre-v2 mitigations for paravirt guests
+    - x86/speculation: Protect against userspace-userspace spectreRSB
+    - kprobes/x86: Fix %p uses in error messages
+    - x86/irqflags: Provide a declaration for native_save_fl
+    - x86/speculation/l1tf: Increase 32bit PAE __PHYSICAL_PAGE_SHIFT
+    - x86/speculation/l1tf: Change order of offset/type in swap entry
+    - x86/speculation/l1tf: Protect swap entries against L1TF
+    - x86/speculation/l1tf: Protect PROT_NONE PTEs against speculation
+    - x86/speculation/l1tf: Make sure the first page is always reserved
+    - x86/speculation/l1tf: Add sysfs reporting for l1tf
+    - x86/speculation/l1tf: Disallow non privileged high MMIO PROT_NONE mappings
+    - x86/speculation/l1tf: Limit swap file size to MAX_PA/2
+    - x86/bugs: Move the l1tf function and define pr_fmt properly
+    - sched/smt: Update sched_smt_present at runtime
+    - x86/smp: Provide topology_is_primary_thread()
+    - x86/topology: Provide topology_smt_supported()
+    - cpu/hotplug: Make bringup/teardown of smp threads symmetric
+    - cpu/hotplug: Split do_cpu_down()
+    - cpu/hotplug: Provide knobs to control SMT
+    - x86/cpu: Remove the pointless CPU printout
+    - x86/cpu/AMD: Remove the pointless detect_ht() call
+    - x86/cpu/common: Provide detect_ht_early()
+    - x86/cpu/topology: Provide detect_extended_topology_early()
+    - x86/cpu/intel: Evaluate smp_num_siblings early
+    - x86/CPU/AMD: Do not check CPUID max ext level before parsing SMP info
+    - x86/cpu/AMD: Evaluate smp_num_siblings early
+    - x86/apic: Ignore secondary threads if nosmt=force
+    - x86/speculation/l1tf: Extend 64bit swap file size limit
+    - x86/cpufeatures: Add detection of L1D cache flush support.
+    - x86/CPU/AMD: Move TOPOEXT reenablement before reading smp_num_siblings
+    - x86/speculation/l1tf: Protect PAE swap entries against L1TF
+    - x86/speculation/l1tf: Fix up pte->pfn conversion for PAE
+    - Revert "x86/apic: Ignore secondary threads if nosmt=force"
+    - cpu/hotplug: Boot HT siblings at least once
+    - x86/KVM: Warn user if KVM is loaded SMT and L1TF CPU bug being present
+    - x86/KVM/VMX: Add module argument for L1TF mitigation
+    - x86/KVM/VMX: Add L1D flush algorithm
+    - x86/KVM/VMX: Add L1D MSR based flush
+    - x86/KVM/VMX: Add L1D flush logic
+    - x86/KVM/VMX: Split the VMX MSR LOAD structures to have an host/guest numbers
+    - x86/KVM/VMX: Add find_msr() helper function
+    - x86/KVM/VMX: Separate the VMX AUTOLOAD guest/host number accounting
+    - x86/KVM/VMX: Extend add_atomic_switch_msr() to allow VMENTER only MSRs
+    - x86/KVM/VMX: Use MSR save list for IA32_FLUSH_CMD if required
+    - cpu/hotplug: Online siblings when SMT control is turned on
+    - x86/litf: Introduce vmx status variable
+    - x86/kvm: Drop L1TF MSR list approach
+    - x86/l1tf: Handle EPT disabled state proper
+    - x86/kvm: Move l1tf setup function
+    - x86/kvm: Add static key for flush always
+    - x86/kvm: Serialize L1D flush parameter setter
+    - x86/kvm: Allow runtime control of L1D flush
+    - cpu/hotplug: Expose SMT control init function
+    - cpu/hotplug: Set CPU_SMT_NOT_SUPPORTED early
+    - x86/bugs, kvm: Introduce boot-time control of L1TF mitigations
+    - Documentation: Add section about CPU vulnerabilities
+    - x86/speculation/l1tf: Unbreak !__HAVE_ARCH_PFN_MODIFY_ALLOWED architectures
+    - x86/KVM/VMX: Initialize the vmx_l1d_flush_pages' content
+    - Documentation/l1tf: Fix typos
+    - cpu/hotplug: detect SMT disabled by BIOS
+    - x86/KVM/VMX: Don't set l1tf_flush_l1d to true from vmx_l1d_flush()
+    - x86/KVM/VMX: Replace 'vmx_l1d_flush_always' with 'vmx_l1d_flush_cond'
+    - x86/KVM/VMX: Move the l1tf_flush_l1d test to vmx_l1d_flush()
+    - x86/irq: Demote irq_cpustat_t::__softirq_pending to u16
+    - x86/KVM/VMX: Introduce per-host-cpu analogue of l1tf_flush_l1d
+    - x86: Don't include linux/irq.h from asm/hardirq.h
+    - x86/irq: Let interrupt handlers set kvm_cpu_l1tf_flush_l1d
+    - x86/KVM/VMX: Don't set l1tf_flush_l1d from vmx_handle_external_intr()
+    - Documentation/l1tf: Remove Yonah processors from not vulnerable list
+    - x86/speculation: Simplify sysfs report of VMX L1TF vulnerability
+    - x86/speculation: Use ARCH_CAPABILITIES to skip L1D flush on vmentry
+    - KVM: VMX: Tell the nested hypervisor to skip L1D flush on vmentry
+    - cpu/hotplug: Fix SMT supported evaluation
+    - x86/speculation/l1tf: Invert all not present mappings
+    - x86/speculation/l1tf: Make pmd/pud_mknotpresent() invert
+    - x86/mm/pat: Make set_memory_np() L1TF safe
+    - x86/mm/kmmio: Make the tracer robust against L1TF
+    - tools headers: Synchronise x86 cpufeatures.h for L1TF additions
+    - x86/microcode: Allow late microcode loading with SMT disabled
+    - x86/smp: fix non-SMP broken build due to redefinition of
+      apic_id_is_primary_thread
+    - cpu/hotplug: Non-SMP machines do not make use of booted_once
+    - x86/init: fix build with CONFIG_SWAP=n
+    - Linux 4.18.1
+    - [Config] updateconfigs after v4.18.1 stable update
+
+  * Consider enabling CONFIG_NETWORK_PHY_TIMESTAMPING (LP: #1785816)
+    - [Config] Enable timestamping in network PHY devices
+
+  * Miscellaneous Ubuntu changes
+    - [Config] CONFIG_SYSCTL_SYSCALL=n
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.18
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Wed, 15 Aug 2018 14:20:59 -0500
+
+linux (4.18.0-4.5) cosmic; urgency=medium
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.18-rc8
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 06 Aug 2018 13:54:02 -0500
+
+linux (4.18.0-3.4) cosmic; urgency=medium
+
+  * Suspend fails in Ubuntu and Kubuntu 18.04 but works fine in Ubuntu and
+    Kubuntu 17.10 (and on Kubuntu 18.04 using kernel 4.14.47) (LP: #1774950)
+    - ACPI / LPSS: Avoid PM quirks on suspend and resume from hibernation
+
+  * hinic interfaces aren't getting predictable names (LP: #1783138)
+    - hinic: Link the logical network device to the pci device in sysfs
+
+  * libvirtd is unable to configure bridge devices inside of LXD containers
+    (LP: #1784501)
+    - kernfs: allow creating kernfs objects with arbitrary uid/gid
+    - sysfs, kobject: allow creating kobject belonging to arbitrary users
+    - kobject: kset_create_and_add() - fetch ownership info from parent
+    - driver core: set up ownership of class devices in sysfs
+    - net-sysfs: require net admin in the init ns for setting tx_maxrate
+    - net-sysfs: make sure objects belong to container's owner
+    - net: create reusable function for getting ownership info of sysfs inodes
+    - bridge: make sure objects belong to container's owner
+    - sysfs: Fix regression when adding a file to an existing group
+
+  * locking sockets broken due to missing AppArmor socket mediation patches
+    (LP: #1780227)
+    - UBUNTU SAUCE: apparmor: fix apparmor mediating locking non-fs, unix sockets
+
+  * Update2 for ocxl driver (LP: #1781436)
+    - ocxl: Fix page fault handler in case of fault on dying process
+
+  * HDMI/DP audio can't work on the laptop of Dell Latitude 5495 (LP: #1782689)
+    - ALSA: hda: use PCI_BASE_CLASS_DISPLAY to replace PCI_CLASS_DISPLAY_VGA
+    - vga_switcheroo: set audio client id according to bound GPU id
+
+  * Allow Raven Ridge's audio controller to be runtime suspended (LP: #1782540)
+    - ALSA: hda: Add AZX_DCAPS_PM_RUNTIME for AMD Raven Ridge
+
+  * Invoking obsolete 'firmware_install' target breaks snap build (LP: #1782166)
+    - snapcraft.yaml: stop invoking the obsolete (and non-existing)
+      'firmware_install' target
+
+  * snapcraft.yaml: missing ubuntu-retpoline-extract-one script breaks the build
+    (LP: #1782116)
+    - snapcraft.yaml: copy retpoline-extract-one to scripts before build
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.18-rc7
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Wed, 01 Aug 2018 08:49:40 -0500
+
+linux (4.18.0-2.3) cosmic; urgency=medium
+
+  * Kernel error "task zfs:pid blocked for more than 120 seconds" (LP: #1781364)
+    - SAUCE: (noup) zfs to 0.7.9-3ubuntu4
+
+  * [Regression] EXT4-fs error (device sda1): ext4_validate_inode_bitmap:99:
+    comm stress-ng: Corrupt inode bitmap (LP: #1780137)
+    - SAUCE: ext4: fix ext4_validate_inode_bitmap: comm stress-ng: Corrupt inode
+      bitmap
+
+  * Cloud-init causes potentially huge boot delays with 4.15 kernels
+    (LP: #1780062)
+    - random: Make getrandom() ready earlier
+
+  * hisi_sas_v3_hw: internal task abort: timeout and not done. (LP: #1777736)
+    - scsi: hisi_sas: Update a couple of register settings for v3 hw
+
+  * hisi_sas: Add missing PHY spinlock init (LP: #1777734)
+    - scsi: hisi_sas: Add missing PHY spinlock init
+
+  * hisi_sas: improve read performance by pre-allocating slot DMA buffers
+    (LP: #1777727)
+    - scsi: hisi_sas: Use dmam_alloc_coherent()
+    - scsi: hisi_sas: Pre-allocate slot DMA buffers
+
+  * hisi_sas: Failures during host reset (LP: #1777696)
+    - scsi: hisi_sas: Only process broadcast change in phy_bcast_v3_hw()
+    - scsi: hisi_sas: Fix the conflict between dev gone and host reset
+    - scsi: hisi_sas: Adjust task reject period during host reset
+    - scsi: hisi_sas: Add a flag to filter PHY events during reset
+    - scsi: hisi_sas: Release all remaining resources in clear nexus ha
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: (noup) Update spl to 0.7.9-3ubuntu2, zfs to 0.7.9-3ubuntu3
+    - SAUCE: mm: Fix exports that inadvertently make put_page() EXPORT_SYMBOL_GPL
+    - Enable zfs build
+    - SAUCE: Import aufs driver
+    - Revert "UBUNTU: [Config]: set CONFIG_EDAC_DEBUG=y for ARM64"
+    - [Config] retpoline -- review and accept retpoline changes
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.18-rc5
+  * Rebase to v4.18-rc6
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Tue, 24 Jul 2018 08:41:22 -0500
+
+linux (4.18.0-1.2) cosmic; urgency=medium
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.18-rc4
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 09 Jul 2018 07:36:31 -0500
+
+linux (4.18.0-0.1) cosmic; urgency=medium
+
+  * Miscellaneous Ubuntu changes
+    - ubuntu -- disable vbox build
+    - Disable zfs build
+    - SAUCE: (efi-lockdown) Add the ability to lock down access to the running
+      kernel image
+    - SAUCE: (efi-lockdown) Add a SysRq option to lift kernel lockdown
+    - SAUCE: (efi-lockdown) ima: require secure_boot rules in lockdown mode
+    - SAUCE: (efi-lockdown) Enforce module signatures if the kernel is locked down
+    - SAUCE: (efi-lockdown) Restrict /dev/{mem,kmem,port} when the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) kexec_load: Disable at runtime if the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) hibernate: Disable when the kernel is locked down
+    - SAUCE: (efi-lockdown) uswsusp: Disable when the kernel is locked down
+    - SAUCE: (efi-lockdown) PCI: Lock down BAR access when the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) x86: Lock down IO port access when the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) x86/msr: Restrict MSR access when the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) ACPI: Limit access to custom_method when the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) acpi: Ignore acpi_rsdp kernel param when the kernel
+      has been locked down
+    - SAUCE: (efi-lockdown) acpi: Disable ACPI table override if the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) acpi: Disable APEI error injection if the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) Prohibit PCMCIA CIS storage when the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) Lock down TIOCSSERIAL
+    - SAUCE: (efi-lockdown) Lock down module params that specify hardware
+      parameters (eg. ioport)
+    - SAUCE: (efi-lockdown) x86/mmiotrace: Lock down the testmmiotrace module
+    - SAUCE: (efi-lockdown) Lock down /proc/kcore
+    - SAUCE: (efi-lockdown) Lock down kprobes
+    - SAUCE: (efi-lockdown) bpf: Restrict kernel image access functions when the
+      kernel is locked down
+    - SAUCE: (efi-lockdown) Lock down perf
+    - SAUCE: (efi-lockdown) debugfs: Restrict debugfs when the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) Copy secure_boot flag in boot params across kexec
+      reboot
+    - SAUCE: (efi-lockdown) efi: Add an EFI_SECURE_BOOT flag to indicate secure
+      boot mode
+    - SAUCE: (efi-lockdown) efi: Lock down the kernel if booted in secure boot
+      mode
+    - SAUCE: (efi-lockdown) KEYS: Allow unrestricted boot-time addition of keys to
+      secondary keyring
+    - SAUCE: (efi-lockdown) efi: Add EFI signature data types
+    - SAUCE: (efi-lockdown) efi: Add an EFI signature blob parser
+    - SAUCE: (efi-lockdown) MODSIGN: Import certificates from UEFI Secure Boot
+    - SAUCE: (efi-lockdown) MODSIGN: Allow the "db" UEFI variable to be suppressed
+    - SAUCE: (efi-lockdown) Make get_cert_list() not complain about cert lists
+      that aren't present.
+    - SAUCE: (efi-lockdown) Add efi_status_to_str() and rework
+      efi_status_to_err().
+    - SAUCE: (efi-lockdown) Make get_cert_list() use efi_status_to_str() to print
+      error messages.
+    - SAUCE: (efi-lockdown) lockdown: fix coordination of kernel module signature
+      verification
+    - SAUCE: (efi-lockdown) efi: Sanitize boot_params in efi stub
+    - SAUCE: (efi-lockdown) efi: Don't print secure boot state from the efi stub
+    - SAUCE: (namespace) block_dev: Support checking inode permissions in
+      lookup_bdev()
+    - SAUCE: (namespace) block_dev: Check permissions towards block device inode
+      when mounting
+    - SAUCE: (namespace) mtd: Check permissions towards mtd block device inode
+      when mounting
+    - SAUCE: (namespace) ext4: Add support for unprivileged mounts from user
+      namespaces
+    - SAUCE: (namespace) ext4: Add module parameter to enable user namespace
+      mounts
+    - SAUCE: (namespace) block_dev: Forbid unprivileged mounting when device is
+      opened for writing
+    - SAUCE: Import aufs driver
+    - Update dropped.txt
+    - [Config] updateconfigs after 4.18-rc3 rebase
+    - SAUCE: (no-up): ASoC: Intel: bytcr-rt5660: Remove snd_soc_codec use for 4.18
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.18-rc3
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Fri, 06 Jul 2018 10:46:37 -0500
+
+linux (4.18.0-0.0) cosmic; urgency=medium
+
+  * Dummy entry.
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Tue, 03 Jul 2018 11:10:33 -0500
+
+linux (4.17.0-4.5) cosmic; urgency=medium
+
+  * linux: 4.17.0-4.5 -proposed tracker (LP: #1779399)
+
+  * Update to ocxl driver for 18.04.1 (LP: #1775786)
+    - powerpc: Add TIDR CPU feature for POWER9
+    - powerpc: Use TIDR CPU feature to control TIDR allocation
+    - powerpc: use task_pid_nr() for TID allocation
+    - ocxl: Rename pnv_ocxl_spa_remove_pe to clarify it's action
+    - ocxl: Expose the thread_id needed for wait on POWER9
+    - ocxl: Add an IOCTL so userspace knows what OCXL features are available
+    - ocxl: Document new OCXL IOCTLs
+    - ocxl: Fix missing unlock on error in afu_ioctl_enable_p9_wait()
+
+  * Please include ax88179_178a and r8152 modules in d-i udeb (LP: #1771823)
+    - [Config:] d-i: Add ax88179_178a and r8152 to nic-modules
+
+  * glibc pkeys test fail on powerpc (LP: #1776967)
+    - [Config] Temporarily disable CONFIG_PPC_MEM_KEYS
+
+  * After update to 4.13-43 Intel Graphics are Laggy (LP: #1773520)
+    - Revert "drm/i915/edp: Allow alternate fixed mode for eDP if available."
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: (noup) Update spl to 0.7.9-3ubuntu1, zfs to 0.7.9-3ubuntu1
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Fri, 29 Jun 2018 13:37:52 -0500
+
+linux (4.17.0-3.4) cosmic; urgency=medium
+
+  * linux: 4.17.0-3.4 -proposed tracker (LP: #1779124)
+
+  * Cosmic update to v4.17.3 stable release (LP: #1778997)
+    - net: aquantia: fix unsigned numvecs comparison with less than zero
+    - bonding: re-evaluate force_primary when the primary slave name changes
+    - cdc_ncm: avoid padding beyond end of skb
+    - ipv6: allow PMTU exceptions to local routes
+    - net: dsa: add error handling for pskb_trim_rcsum
+    - net: phy: dp83822: use BMCR_ANENABLE instead of BMSR_ANEGCAPABLE for DP83620
+    - net/sched: act_simple: fix parsing of TCA_DEF_DATA
+    - tcp: verify the checksum of the first data segment in a new connection
+    - tls: fix use-after-free in tls_push_record
+    - tls: fix waitall behavior in tls_sw_recvmsg
+    - socket: close race condition between sock_close() and sockfs_setattr()
+    - udp: fix rx queue len reported by diag and proc interface
+    - net: in virtio_net_hdr only add VLAN_HLEN to csum_start if payload holds
+      vlan
+    - hv_netvsc: Fix a network regression after ifdown/ifup
+    - ACPICA: AML parser: attempt to continue loading table after error
+    - ext4: fix hole length detection in ext4_ind_map_blocks()
+    - ext4: update mtime in ext4_punch_hole even if no blocks are released
+    - ext4: do not allow external inodes for inline data
+    - ext4: bubble errors from ext4_find_inline_data_nolock() up to ext4_iget()
+    - ext4: correctly handle a zero-length xattr with a non-zero e_value_offs
+    - ext4: fix fencepost error in check for inode count overflow during resize
+    - driver core: Don't ignore class_dir_create_and_add() failure.
+    - Btrfs: allow empty subvol= again
+    - Btrfs: fix clone vs chattr NODATASUM race
+    - Btrfs: fix memory and mount leak in btrfs_ioctl_rm_dev_v2()
+    - btrfs: return error value if create_io_em failed in cow_file_range
+    - btrfs: scrub: Don't use inode pages for device replace
+    - ALSA: usb-audio: Disable the quirk for Nura headset
+    - ALSA: hda/conexant - Add fixup for HP Z2 G4 workstation
+    - ALSA: hda - Handle kzalloc() failure in snd_hda_attach_pcm_stream()
+    - ALSA: hda: add dock and led support for HP EliteBook 830 G5
+    - ALSA: hda: add dock and led support for HP ProBook 640 G4
+    - x86/MCE: Fix stack out-of-bounds write in mce-inject.c: Flags_read()
+    - smb3: fix various xid leaks
+    - smb3: on reconnect set PreviousSessionId field
+    - CIFS: 511c54a2f69195b28afb9dd119f03787b1625bb4 adds a check for session
+      expiry
+    - cifs: For SMB2 security informaion query, check for minimum sized security
+      descriptor instead of sizeof FileAllInformation class
+    - nbd: fix nbd device deletion
+    - nbd: update size when connected
+    - nbd: use bd_set_size when updating disk size
+    - blk-mq: reinit q->tag_set_list entry only after grace period
+    - bdi: Move cgroup bdi_writeback to a dedicated low concurrency workqueue
+    - cpufreq: Fix new policy initialization during limits updates via sysfs
+    - cpufreq: ti-cpufreq: Fix an incorrect error return value
+    - cpufreq: governors: Fix long idle detection logic in load calculation
+    - libata: zpodd: small read overflow in eject_tray()
+    - libata: Drop SanDisk SD7UB3Q*G1001 NOLPM quirk
+    - nvme/pci: Sync controller reset for AER slot_reset
+    - w1: mxc_w1: Enable clock before calling clk_get_rate() on it
+    - x86/vector: Fix the args of vector_alloc tracepoint
+    - x86/apic/vector: Prevent hlist corruption and leaks
+    - x86/apic: Provide apic_ack_irq()
+    - x86/ioapic: Use apic_ack_irq()
+    - x86/platform/uv: Use apic_ack_irq()
+    - irq_remapping: Use apic_ack_irq()
+    - genirq/generic_pending: Do not lose pending affinity update
+    - genirq/affinity: Defer affinity setting if irq chip is busy
+    - genirq/migration: Avoid out of line call if pending is not set
+    - x86/intel_rdt: Enable CMT and MBM on new Skylake stepping
+    - media: uvcvideo: Prevent setting unavailable flags
+    - media: rc: ensure input/lirc device can be opened after register
+    - iwlwifi: fw: harden page loading code
+    - orangefs: set i_size on new symlink
+    - orangefs: report attributes_mask and attributes for statx
+    - HID: intel_ish-hid: ipc: register more pm callbacks to support hibernation
+    - HID: wacom: Correct logical maximum Y for 2nd-gen Intuos Pro large
+    - vhost: fix info leak due to uninitialized memory
+    - mm, page_alloc: do not break __GFP_THISNODE by zonelist reset
+    - Linux 4.17.3
+
+  * Use-after-free in sk_peer_label (LP: #1778646)
+    - SAUCE: apparmor: fix use after free in sk_peer_label
+
+  * kernel: Fix memory leak on CCA and EP11 CPRB processing. (LP: #1775390)
+    - s390/zcrypt: Fix CCA and EP11 CPRB processing failure memory leak.
+
+  * Various fixes for CXL kernel module (LP: #1774471)
+    - cxl: Configure PSL to not use APC virtual machines
+    - cxl: Disable prefault_mode in Radix mode
+
+  * Bluetooth not working (LP: #1764645)
+    - Bluetooth: btusb: Apply QCA Rome patches for some ATH3012 models
+
+  * Fake SAS addresses for SATA disks on HiSilicon D05 are non-unique
+    (LP: #1776750)
+    - scsi: hisi_sas: make SAS address of SATA disks unique
+
+  * linux-snapdragon: wcn36xx: mac address generation on boot (LP: #1776491)
+    - [Config] arm64: snapdragon: WCN36XX_SNAPDRAGON_HACKS=y
+    - SAUCE: wcn36xx: read MAC from file or randomly generate one
+
+  * Lenovo V330 needs patch in ideapad_laptop module for rfkill (LP: #1774636)
+    - SAUCE: Add Lenovo V330 to the ideapad_laptop rfkill blacklist
+
+  * register on binfmt_misc may overflow and crash the system (LP: #1775856)
+    - fs/binfmt_misc.c: do not allow offset overflow
+
+  * Network installs fail on SocioNext board (LP: #1775884)
+    - net: socionext: reset hardware in ndo_stop
+    - net: netsec: enable tx-irq during open callback
+
+  * Fix several bugs in RDMA/hns driver (LP: #1770974)
+    - RDMA/hns: Drop local zgid in favor of core defined variable
+    - RDMA/hns: Add 64KB page size support for hip08
+    - RDMA/hns: Rename the idx field of db
+    - RDMA/hns: Modify uar allocation algorithm to avoid bitmap exhaust
+    - RDMA/hns: Increase checking CMQ status timeout value
+    - RDMA/hns: Add reset process for RoCE in hip08
+    - RDMA/hns: Fix the illegal memory operation when cross page
+    - RDMA/hns: Implement the disassociate_ucontext API
+
+  * powerpc/livepatch: Implement reliable stack tracing for the consistency
+    model (LP: #1771844)
+    - powerpc/livepatch: Implement reliable stack tracing for the consistency
+      model
+
+  * Adding back alx WoL feature (LP: #1772610)
+    - SAUCE: Revert "alx: remove WoL support"
+    - SAUCE: alx: add enable_wol paramenter
+
+  * Lancer A0 Asic HBA's won't boot with 18.04 (LP: #1768103)
+    - scsi: lpfc: Fix WQ/CQ creation for older asic's.
+    - scsi: lpfc: Fix 16gb hbas failing cq create.
+
+  * [LTCTest][OPAL][OP920] cpupower idle-info is not listing stop4 and stop5
+    idle states when all CORES are guarded (LP: #1771780)
+    - powerpc/powernv/cpuidle: Init all present cpus for deep states
+
+  * Huawei 25G/100G Network Adapters Unsupported (LP: #1770970)
+    - net-next/hinic: add pci device ids for 25ge and 100ge card
+
+  * Expose arm64 CPU topology to userspace (LP: #1770231)
+    - drivers: base: cacheinfo: move cache_setup_of_node()
+    - drivers: base: cacheinfo: setup DT cache properties early
+    - cacheinfo: rename of_node to fw_token
+    - arm64/acpi: Create arch specific cpu to acpi id helper
+    - ACPI/PPTT: Add Processor Properties Topology Table parsing
+    - [Config] CONFIG_ACPI_PPTT=y
+    - ACPI: Enable PPTT support on ARM64
+    - drivers: base cacheinfo: Add support for ACPI based firmware tables
+    - arm64: Add support for ACPI based firmware tables
+    - arm64: topology: rename cluster_id
+    - arm64: topology: enable ACPI/PPTT based CPU topology
+    - ACPI: Add PPTT to injectable table list
+    - arm64: topology: divorce MC scheduling domain from core_siblings
+
+  * Vcs-Git header on bionic linux source package points to zesty git tree
+    (LP: #1766055)
+    - [Packaging]: Update Vcs-Git
+
+  * Request to revert SAUCE patches in the 18.04 SRU and update with upstream
+    version (LP: #1768431)
+    - scsi: cxlflash: Handle spurious interrupts
+    - scsi: cxlflash: Remove commmands from pending list on timeout
+    - scsi: cxlflash: Synchronize reset and remove ops
+    - SAUCE: (no-up) cxlflash: OCXL diff between v2 and v3
+
+  * hisi_sas robustness fixes (LP: #1774466)
+    - scsi: hisi_sas: delete timer when removing hisi_sas driver
+    - scsi: hisi_sas: print device id for errors
+    - scsi: hisi_sas: Add some checks to avoid free'ing a sas_task twice
+    - scsi: hisi_sas: check host frozen before calling "done" function
+    - scsi: hisi_sas: check sas_dev gone earlier in hisi_sas_abort_task()
+    - scsi: hisi_sas: stop controller timer for reset
+    - scsi: hisi_sas: update PHY linkrate after a controller reset
+    - scsi: hisi_sas: change slot index allocation mode
+    - scsi: hisi_sas: Change common allocation mode of device id
+    - scsi: hisi_sas: Reset disks when discovered
+    - scsi: hisi_sas: Create a scsi_host_template per HW module
+    - scsi: hisi_sas: Init disks after controller reset
+    - scsi: hisi_sas: Try wait commands before before controller reset
+    - scsi: hisi_sas: Include TMF elements in struct hisi_sas_slot
+    - scsi: hisi_sas: Add v2 hw force PHY function for internal ATA command
+    - scsi: hisi_sas: Terminate STP reject quickly for v2 hw
+    - scsi: hisi_sas: Fix return value when get_free_slot() failed
+    - scsi: hisi_sas: Mark PHY as in reset for nexus reset
+
+  * hisi_sas: Support newer v3 hardware (LP: #1774467)
+    - scsi: hisi_sas: update RAS feature for later revision of v3 HW
+    - scsi: hisi_sas: check IPTT is valid before using it for v3 hw
+    - scsi: hisi_sas: fix PI memory size
+    - scsi: hisi_sas: config ATA de-reset as an constrained command for v3 hw
+    - scsi: hisi_sas: remove redundant handling to event95 for v3
+    - scsi: hisi_sas: add readl poll timeout helper wrappers
+    - scsi: hisi_sas: workaround a v3 hw hilink bug
+    - scsi: hisi_sas: Add LED feature for v3 hw
+
+  * hisi_sas: improve performance by optimizing DQ locking (LP: #1774472)
+    - scsi: hisi_sas: optimise the usage of DQ locking
+    - scsi: hisi_sas: relocate smp sg map
+    - scsi: hisi_sas: make return type of prep functions void
+    - scsi: hisi_sas: allocate slot buffer earlier
+    - scsi: hisi_sas: Don't lock DQ for complete task sending
+    - scsi: hisi_sas: Use device lock to protect slot alloc/free
+    - scsi: hisi_sas: add check of device in hisi_sas_task_exec()
+    - scsi: hisi_sas: fix a typo in hisi_sas_task_prep()
+
+  * FS-Cache: Assertion failed: FS-Cache: 6 == 5 is false (LP: #1774336)
+    - SAUCE: CacheFiles: fix a read_waiter/read_copier race
+
+  * enable mic-mute hotkey and led on Lenovo M820z and M920z (LP: #1774306)
+    - ALSA: hda/realtek - Enable mic-mute hotkey for several Lenovo AIOs
+
+  * hns3 driver updates (LP: #1768670)
+    - net: hns3: Remove error log when getting pfc stats fails
+    - net: hns3: fix to correctly fetch l4 protocol outer header
+    - net: hns3: Fixes the out of bounds access in hclge_map_tqp
+    - net: hns3: Fixes the error legs in hclge_init_ae_dev function
+    - net: hns3: fix for phy_addr error in hclge_mac_mdio_config
+    - net: hns3: Fix to support autoneg only for port attached with phy
+    - net: hns3: fix a dead loop in hclge_cmd_csq_clean
+    - net: hns3: Fix for packet loss due wrong filter config in VLAN tbls
+    - net: hns3: Remove packet statistics in the range of 8192~12287
+    - net: hns3: Add support of hardware rx-vlan-offload to HNS3 VF driver
+    - net: hns3: Fix for setting mac address when resetting
+    - net: hns3: remove add/del_tunnel_udp in hns3_enet module
+    - net: hns3: fix for cleaning ring problem
+    - net: hns3: refactor the loopback related function
+    - net: hns3: Fix for deadlock problem occurring when unregistering ae_algo
+    - net: hns3: Fix for the null pointer problem occurring when initializing
+      ae_dev failed
+    - net: hns3: Add a check for client instance init state
+    - net: hns3: Change return type of hnae3_register_ae_dev
+    - net: hns3: Change return type of hnae3_register_ae_algo
+    - net: hns3: Change return value in hnae3_register_client
+    - net: hns3: Fixes the back pressure setting when sriov is enabled
+    - net: hns3: Fix for fiber link up problem
+    - net: hns3: Add support of .sriov_configure in HNS3 driver
+    - net: hns3: Fixes the missing PCI iounmap for various legs
+    - net: hns3: Fixes error reported by Kbuild and internal review
+    - net: hns3: Fixes API to fetch ethernet header length with kernel default
+    - net: hns3: cleanup of return values in hclge_init_client_instance()
+    - net: hns3: Fix the missing client list node initialization
+    - net: hns3: Fix for hns3 module is loaded multiple times problem
+    - net: hns3: Use enums instead of magic number in hclge_is_special_opcode
+    - net: hns3: Fix for netdev not running problem after calling net_stop and
+      net_open
+    - net: hns3: Fixes kernel panic issue during rmmod hns3 driver
+    - net: hns3: Fix for CMDQ and Misc. interrupt init order problem
+    - net: hns3: Updates RX packet info fetch in case of multi BD
+    - net: hns3: Add support for tx_accept_tag2 and tx_accept_untag2 config
+    - net: hns3: Add STRP_TAGP field support for hardware revision 0x21
+    - net: hns3: Add support to enable TX/RX promisc mode for H/W rev(0x21)
+    - net: hns3: Fix for PF mailbox receving unknown message
+    - net: hns3: Fixes the state to indicate client-type initialization
+    - net: hns3: Fixes the init of the VALID BD info in the descriptor
+    - net: hns3: Removes unnecessary check when clearing TX/RX rings
+    - net: hns3: Clear TX/RX rings when stopping port & un-initializing client
+    - net: hns3: Remove unused led control code
+    - net: hns3: Adds support for led locate command for copper port
+    - net: hns3: Fixes initalization of RoCE handle and makes it conditional
+    - net: hns3: Disable vf vlan filter when vf vlan table is full
+    - net: hns3: Add support for IFF_ALLMULTI flag
+    - net: hns3: Add repeat address checking for setting mac address
+    - net: hns3: Fix setting mac address error
+    - net: hns3: Fix for service_task not running problem after resetting
+    - net: hns3: Fix for hclge_reset running repeatly problem
+    - net: hns3: Fix for phy not link up problem after resetting
+    - net: hns3: Add missing break in misc_irq_handle
+    - net: hns3: Fix for vxlan tx checksum bug
+    - net: hns3: Optimize the PF's process of updating multicast MAC
+    - net: hns3: Optimize the VF's process of updating multicast MAC
+    - SAUCE: {topost} net: hns3: add support for serdes loopback selftest
+    - SAUCE: {topost} net: hns3: RX BD information valid only in last BD except
+      VLD bit and buffer size
+    - SAUCE: {topost} net: hns3: remove hclge_get_vector_index from
+      hclge_bind_ring_with_vector
+    - SAUCE: {topost} net: hns3: rename the interface for init_client_instance and
+      uninit_client_instance
+    - SAUCE: {topost} net: hns3: add vector status check before free vector
+    - SAUCE: {topost} net: hns3: add l4_type check for both ipv4 and ipv6
+    - SAUCE: {topost} net: hns3: remove unused head file in hnae3.c
+    - SAUCE: {topost} net: hns3: extraction an interface for state state
+      init|uninit
+    - SAUCE: {topost} net: hns3: print the ret value in error information
+    - SAUCE: {topost} net: hns3: remove the Redundant put_vector in
+      hns3_client_uninit
+    - SAUCE: {topost} net: hns3: add unlikely for error check
+    - SAUCE: {topost} net: hns3: remove back in struct hclge_hw
+    - SAUCE: {topost} net: hns3: use lower_32_bits and upper_32_bits
+    - SAUCE: {topost} net: hns3: remove unused hclge_ring_to_dma_dir
+    - SAUCE: {topost} net: hns3: remove useless code in hclge_cmd_send
+    - SAUCE: {topost} net: hns3: remove some redundant assignments
+    - SAUCE: {topost} net: hns3: simplify hclge_cmd_csq_clean
+    - SAUCE: {topost} net: hns3: using modulo for cyclic counters in
+      hclge_cmd_send
+    - SAUCE: {topost} net: hns3: remove a redundant hclge_cmd_csq_done
+    - SAUCE: {topost} net: hns3: remove some unused members of some structures
+    - SAUCE: {topost} net: hns3: give default option while dependency HNS3 set
+    - SAUCE: {topost} net: hns3: use dma_zalloc_coherent instead of
+      kzalloc/dma_map_single
+    - SAUCE: {topost} net: hns3: modify hnae_ to hnae3_
+    - SAUCE: {topost} net: hns3: fix unused function warning in VF driver
+    - SAUCE: {topost} net: hns3: remove some redundant assignments
+    - SAUCE: {topost} net: hns3: standardize the handle of return value
+    - SAUCE: {topost} net: hns3: remove extra space and brackets
+    - SAUCE: {topost} net: hns3: fix unreasonable code comments
+    - SAUCE: {topost} net: hns3: use decimal for bit offset macros
+    - SAUCE: {topost} net: hns3: modify inconsistent bit mask macros
+    - SAUCE: {topost} net: hns3: fix mislead parameter name
+    - SAUCE: {topost} net: hns3: remove unused struct member and definition
+    - SAUCE: {topost} net: hns3: Add SPDX tags to hns3 driver
+    - SAUCE: {topost} net: hns3: Add pf reset for hip08 RoCE
+    - SAUCE: {topost} net: hns3: optimize the process of notifying roce client
+    - SAUCE: {topost} net: hns3: Add calling roce callback function when link
+      status change
+    - SAUCE: {topost} net: hns3: fix tc setup when netdev is first up
+    - SAUCE: {topost} net: hns3: fix for mac pause not disable in pfc mode
+    - SAUCE: {topost} net: hns3: fix for waterline not setting correctly
+    - SAUCE: {topost} net: hns3: fix for l4 checksum offload bug
+    - SAUCE: {topost} net: hns3: fix for mailbox message truncated problem
+    - SAUCE: {topost} net: hns3: Add configure for mac minimal frame size
+    - SAUCE: {topost} net: hns3: fix warning bug when doing lp selftest
+    - SAUCE: {topost} net: hns3: fix get_vector ops in hclgevf_main module
+    - SAUCE: {topost} net: hns3: remove the warning when clear reset cause
+    - SAUCE: {topost} net: hns3: Use roce handle when calling roce callback
+      function
+    - SAUCE: {topost} net: hns3: prevent sending command during global or core
+      reset
+    - SAUCE: {topost} net: hns3: modify the order of initializeing command queue
+      register
+    - SAUCE: {topost} net: hns3: reset net device with rtnl_lock
+    - SAUCE: {topost} net: hns3: prevent to request reset frequently
+    - SAUCE: {topost} net: hns3: correct reset event status register
+    - SAUCE: {topost} net: hns3: separate roce from nic when resetting
+    - SAUCE: net: hns3: Fix for phy link issue when using marvell phy driver
+    - SAUCE: {topost} net: hns3: fix return value error in
+      hns3_reset_notify_down_enet
+    - SAUCE: {topost} net: hns3: remove unnecessary ring configuration operation
+      while resetting
+    - SAUCE: {topost} net: hns3: fix for reset_level default assignment probelm
+    - SAUCE: {topost} net: hns3: fix for using wrong mask and shift in
+      hclge_get_ring_chain_from_mbx
+    - SAUCE: {topost} net: hns3: fix comments for hclge_get_ring_chain_from_mbx
+    - SAUCE: net: hns3: Fix for VF mailbox cannot receiving PF response
+    - SAUCE: net: hns3: Fix for VF mailbox receiving unknown message
+    - SAUCE: net: hns3: Optimize PF CMDQ interrupt switching process
+
+  * CVE-2018-7755
+    - SAUCE: floppy: Do not copy a kernel pointer to user memory in FDGETPRM ioctl
+
+  * Incorrect blacklist of bcm2835_wdt (LP: #1766052)
+    - [Packaging] Fix missing watchdog for Raspberry Pi
+
+  * kernel: Fix arch random implementation (LP: #1775391)
+    - s390/archrandom: Rework arch random implementation.
+
+  * [Ubuntu 1804][boston][ixgbe] EEH causes kernel BUG at /build/linux-
+    jWa1Fv/linux-4.15.0/drivers/pci/msi.c:352 (i2S) (LP: #1776389)
+    - ixgbe/ixgbevf: Free IRQ when PCI error recovery removes the device
+
+  * Cosmic update to v4.17.2 stable release (LP: #1779117)
+    - crypto: chelsio - request to HW should wrap
+    - blkdev_report_zones_ioctl(): Use vmalloc() to allocate large buffers
+    - KVM: X86: Fix reserved bits check for MOV to CR3
+    - KVM: x86: introduce linear_{read,write}_system
+    - kvm: fix typo in flag name
+    - kvm: nVMX: Enforce cpl=0 for VMX instructions
+    - KVM: x86: pass kvm_vcpu to kvm_read_guest_virt and
+      kvm_write_guest_virt_system
+    - kvm: x86: use correct privilege level for sgdt/sidt/fxsave/fxrstor access
+    - staging: android: ion: Switch to pr_warn_once in ion_buffer_destroy
+    - NFC: pn533: don't send USB data off of the stack
+    - usbip: vhci_sysfs: fix potential Spectre v1
+    - usb-storage: Add support for FL_ALWAYS_SYNC flag in the UAS driver
+    - usb-storage: Add compatibility quirk flags for G-Technologies G-Drive
+    - Input: xpad - add GPD Win 2 Controller USB IDs
+    - phy: qcom-qusb2: Fix crash if nvmem cell not specified
+    - usb: core: message: remove extra endianness conversion in
+      usb_set_isoch_delay
+    - usb: typec: wcove: Remove dependency on HW FSM
+    - usb: gadget: function: printer: avoid wrong list handling in printer_write()
+    - usb: gadget: udc: renesas_usb3: fix double phy_put()
+    - usb: gadget: udc: renesas_usb3: should remove debugfs
+    - usb: gadget: udc: renesas_usb3: should call pm_runtime_enable() before add
+      udc
+    - usb: gadget: udc: renesas_usb3: should call devm_phy_get() before add udc
+    - usb: gadget: udc: renesas_usb3: should fail if devm_phy_get() returns error
+    - usb: gadget: udc: renesas_usb3: disable the controller's irqs for
+      reconnecting
+    - serial: sh-sci: Stop using printk format %pCr
+    - tty/serial: atmel: use port->name as name in request_irq()
+    - serial: samsung: fix maxburst parameter for DMA transactions
+    - serial: 8250: omap: Fix idling of clocks for unused uarts
+    - vmw_balloon: fixing double free when batching mode is off
+    - doc: fix sysfs ABI documentation
+    - arm64: defconfig: Enable CONFIG_PINCTRL_MT7622 by default
+    - tty: pl011: Avoid spuriously stuck-off interrupts
+    - crypto: ccree - correct host regs offset
+    - Input: goodix - add new ACPI id for GPD Win 2 touch screen
+    - Input: elan_i2c - add ELAN0612 (Lenovo v330 14IKB) ACPI ID
+    - crypto: caam - strip input zeros from RSA input buffer
+    - crypto: caam - fix DMA mapping dir for generated IV
+    - crypto: caam - fix IV DMA mapping and updating
+    - crypto: caam/qi - fix IV DMA mapping and updating
+    - crypto: caam - fix size of RSA prime factor q
+    - crypto: cavium - Fix fallout from CONFIG_VMAP_STACK
+    - crypto: cavium - Limit result reading attempts
+    - crypto: vmx - Remove overly verbose printk from AES init routines
+    - crypto: vmx - Remove overly verbose printk from AES XTS init
+    - crypto: omap-sham - fix memleak
+    - Linux 4.17.2
+
+  * Cosmic update to v4.17.1 stable release (LP: #1779116)
+    - netfilter: nf_flow_table: attach dst to skbs
+    - bnx2x: use the right constant
+    - ip6mr: only set ip6mr_table from setsockopt when ip6mr_new_table succeeds
+    - ipv6: omit traffic class when calculating flow hash
+    - l2tp: fix refcount leakage on PPPoL2TP sockets
+    - netdev-FAQ: clarify DaveM's position for stable backports
+    - net: metrics: add proper netlink validation
+    - net/packet: refine check for priv area size
+    - rtnetlink: validate attributes in do_setlink()
+    - sctp: not allow transport timeout value less than HZ/5 for hb_timer
+    - team: use netdev_features_t instead of u32
+    - vrf: check the original netdevice for generating redirect
+    - net: dsa: b53: Fix for brcm tag issue in Cygnus SoC
+    - ipmr: fix error path when ipmr_new_table fails
+    - PCI: hv: Do not wait forever on a device that has disappeared
+    - Linux 4.17.1
+
+  * Miscellaneous Ubuntu changes
+    - Revert "UBUNTU: SAUCE: crypto: thunderx_zip: Fix fallout from
+      CONFIG_VMAP_STACK"
+    - Revert "UBUNTU: SAUCE: cred: Add clone_cred() interface"
+    - SAUCE: apparmor: userspace queries
+    - SAUCE: apparmor: patch to provide compatibility with v2.x net rules
+    - SAUCE: apparmor: af_unix mediation
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Thu, 28 Jun 2018 08:03:32 -0500
+
+linux (4.17.0-2.3) cosmic; urgency=medium
+
+  * linux: 4.17.0-2.3 -proposed tracker (LP: #1776276)
+
+  * Miscellaneous Ubuntu changes
+    - Config: remove IrDA from annotations
+    - Config: remove scsi drivers from annotations
+    - Config: remove BT_HCIBTUART from annotations
+    - Config: pstore zlib support was renamed
+    - Config: disable NVRAM for armhf on annotations
+    - Config: Disable VT on s390x
+    - Config: Update SSB and B43/B44 options
+    - Config: some options not supported on some arches anymore
+    - Config: renamed and removed options
+    - Config: TCG_CRB is required for IMA on ACPI systems
+    - Config: EXTCON_AXP288 depends on X86
+    - Config: CONFIG_FSI depends on OF
+    - Config: DRM_RCAR_LVDS now depends on DRM
+    - CONFIG: Allow CONFIG_LEDS_MLXCPLD for i386
+    - Config: Enable HINIC on arm64
+    - Config: Set PPS and PTP_1588_CLOCK as y
+    - Config: Some NF_TABLES options are built-in now
+    - Config: GENERIC_CPU for ppc64el
+    - Config: KEXEC_FILE=n for s390x
+    - Config: CRYPTO_DEFLATE is needed by PSTORE_DEFLATE_COMPRESS
+    - Config: Disable STM32 support
+    - Config: Enable FORTIFY_SOURCE for armhf
+    - Config: use STRONG instead of AUTO for CC_STACKPROTECTOR
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.17
+
+ -- Thadeu Lima de Souza Cascardo <cascardo@canonical.com>  Mon, 11 Jun 2018 15:22:10 -0300
+
+linux (4.17.0-1.2) cosmic; urgency=medium
+
+  [ Seth Forshee ]
+  * [Config] enable EDAC_DEBUG on ARM64 (LP: #1772516)
+    - [Config]: set CONFIG_EDAC_DEBUG=y for ARM64
+
+  * Ubuntu 18.04 kernel crashed while in degraded mode (LP: #1770849)
+    - SAUCE: powerpc/perf: Fix memory allocation for core-imc based on
+      num_possible_cpus()
+
+  * Integrated Webcam Realtek Integrated_Webcam_HD (0bda:58f4) not working in
+    DELL XPS 13 9370 with firmware 1.50 (LP: #1763748)
+    - SAUCE: media: uvcvideo: Support realtek's UVC 1.5 device
+
+  * Switch Build-Depends: transfig to fig2dev (LP: #1770770)
+    - [Config] update Build-Depends: transfig to fig2dev
+
+  * update-initramfs not adding i915 GuC firmware for Kaby Lake, firmware fails
+    to load (LP: #1728238)
+    - Revert "UBUNTU: SAUCE: (no-up) i915: Remove MODULE_FIRMWARE statements for
+      unreleased firmware"
+
+  * No driver for Huawei network adapters on arm64 (LP: #1769899)
+    - net-next/hinic: add arm64 support
+
+  * linux-snapdragon: reduce EPROBEDEFER noise during boot (LP: #1768761)
+    - [Config] snapdragon: DRM_I2C_ADV7511=y
+
+  * Add d-i support for Huawei NICs (LP: #1767490)
+    - d-i: add hinic to nic-modules udeb
+
+  * Acer Swift sf314-52 power button not managed  (LP: #1766054)
+    - SAUCE: platform/x86: acer-wmi: add another KEY_POWER keycode
+
+  * Include nfp driver in linux-modules (LP: #1768526)
+    - [Config] Add nfp.ko to generic inclusion list
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: Import aufs driver
+    - [Config] Enable AUFS config options
+    - SAUCE: (efi-lockdown) Fix for module sig verification
+    - SAUCE: (efi-lockdown) Copy secure_boot flag in boot params across kexec
+      reboot
+    - SAUCE: (efi-lockdown) efi: Add an EFI_SECURE_BOOT flag to indicate secure
+      boot mode
+    - SAUCE: (efi-lockdown) efi: Lock down the kernel if booted in secure boot
+      mode
+    - SAUCE: (efi-lockdown) efi: Sanitize boot_params in efi stub
+    - SAUCE: (efi-lockdown) efi: Don't print secure boot state from the efi stub
+    - [Config] CONFIG_LOCK_DOWN_IN_EFI_SECURE_BOOT=y
+    - SAUCE: (efi-lockdown) really lock down kernel under EFI secure boot
+    - SAUCE: (noup) Update spl to 0.7.5-1ubuntu3, zfs to 0.7.5-1ubuntu17
+    - enable zfs build
+
+  * Miscellaneous upstream changes
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) ima: require secure_boot rules in
+      lockdown mode"
+    - Rebased to v4.17-rc6
+
+ -- Thadeu Lima de Souza Cascardo <cascardo@canonical.com>  Tue, 22 May 2018 14:48:13 -0300
+
+linux (4.17.0-0.1) bionic; urgency=medium
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.17-rc4
+
+ -- Thadeu Lima de Souza Cascardo <cascardo@canonical.com>  Tue, 08 May 2018 16:38:51 -0300
+
+linux (4.17.0-0.0) bionic; urgency=medium
+
+  * Dummy entry.
+
+ -- Thadeu Lima de Souza Cascardo <cascardo@canonical.com>  Fri, 27 Apr 2018 11:01:13 -0300
+
+linux (4.16.0-4.5) bionic; urgency=medium
+
+  * [18.04 FEAT] Add kvm_stat from kernel tree (LP: #1734130)
+    - tools/kvm_stat: Fix python3 syntax
+    - tools/kvm_stat: Don't use deprecated file()
+    - tools/kvm_stat: Remove unused function
+    - [Packaging] Add linux-tools-host package for VM host tools
+    - [Config] do_tools_host=true for amd64
+
+  * [Featire] CNL: Enable RAPL support (LP: #1685712)
+    - powercap: RAPL: Add support for Cannon Lake
+
+  * Bionic update to v4.16.2 stable release (LP: #1763388)
+    - sparc64: Oracle DAX driver depends on SPARC64
+    - arp: fix arp_filter on l3slave devices
+    - net: dsa: Discard frames from unused ports
+    - net/ipv6: Increment OUTxxx counters after netfilter hook
+    - net/sched: fix NULL dereference in the error path of tcf_bpf_init()
+    - pptp: remove a buggy dst release in pptp_connect()
+    - sctp: do not leak kernel memory to user space
+    - sctp: sctp_sockaddr_af must check minimal addr length for AF_INET6
+    - vlan: also check phy_driver ts_info for vlan's real device
+    - net: fool proof dev_valid_name()
+    - ip_tunnel: better validate user provided tunnel names
+    - ipv6: sit: better validate user provided tunnel names
+    - ip6_gre: better validate user provided tunnel names
+    - ip6_tunnel: better validate user provided tunnel names
+    - vti6: better validate user provided tunnel names
+    - net_sched: fix a missing idr_remove() in u32_delete_key()
+    - nfp: use full 40 bits of the NSP buffer address
+    - Linux 4.16.2
+
+  * sky2 gigabit ethernet driver sometimes stops working after lid-open resume
+    from sleep (88E8055) (LP: #1758507) // Bionic update to v4.16.2 stable
+    release (LP: #1763388)
+    - sky2: Increase D3 delay to sky2 stops working after suspend
+
+  * Merge the linux-snapdragon kernel into bionic master/snapdragon
+    (LP: #1763040)
+    - arm64: defconfig: enable REMOTEPROC
+    - arm64: defconfig: enable QCOM audio drivers for APQ8016 and DB410c
+    - kernel: configs; add distro.config
+    - arm64: configs: enable WCN36xx
+    - kernel: distro.config: enable debug friendly USB network adpater
+    - arm64: configs: enable QCOM Venus
+    - arm64: defconfig: Enable a53/apcs and avs
+    - arm64: defconfig: enable ondemand governor as default
+    - arm64: defconfig: enable QCOM_TSENS
+    - kernel: configs: enable dm_mod and dm_crypt
+    - Force the SMD regulator driver to be compiled-in
+    - arm64: defconfig: enable CFG80211_DEFAULT_PS by default
+    - arm64: configs: enable BT_QCOMSMD
+    - kernel: configs: add more USB net drivers
+    - arm64: defconfig: disable ANALOG_TV and DIGITAL_TV
+    - arm64: configs: Enable camera drivers
+    - kernel: configs: add freq stat to sysfs
+    - arm64: defconfig: enable CONFIG_USB_CONFIGFS_F_FS by default
+    - arm64: defconfig: Enable QRTR features
+    - kernel: configs: set USB_CONFIG_F_FS in distro.config
+    - kernel: distro.config: enable 'schedutil' CPUfreq governor
+    - kernel: distro.config: enable 'fq' and 'fq_codel' qdiscs
+    - kernel: distro.config: enable 'BBR' TCP congestion algorithm
+    - arm64: defconfig: enable LEDS_QCOM_LPG
+    - HACK: drm/msm/iommu: Remove runtime_put calls in map/unmap
+    - power: avs: Add support for CPR (Core Power Reduction)
+    - power: avs: cpr: Use raw mem access for qfprom
+    - power: avs: cpr: fix with new reg_sequence structures
+    - power: avs: cpr: Register with cpufreq-dt
+    - regulator: smd: Add floor and corner operations
+    - PM / OPP: Support adjusting OPP voltages at runtime
+    - PM / OPP: Drop RCU usage in dev_pm_opp_adjust_voltage()
+    - PM / OPP: HACK: Allow to set regulator without opp_list
+    - PM / OPP: Add a helper to get an opp regulator for device
+    - cpufreq: Add apq8016 to cpufreq-dt-platdev blacklist
+    - regulator: smd: Allow REGULATOR_QCOM_SMD_RPM=m
+    - ov5645: I2C address change
+    - i2c: Add Qualcomm Camera Control Interface driver
+    - camss: vfe: Skip first four frames from sensor
+    - camss: Do not register if no cameras are present
+    - i2c-qcom-cci: Fix run queue completion timeout
+    - i2c-qcom-cci: Fix I2C address bug
+    - media: ov5645: Fix I2C address
+    - drm/bridge/adv7511: Delay clearing of HPD interrupt status
+    - HACK: drm/msm/adv7511: Don't rely on interrupts for EDID parsing
+    - leds: Add driver for Qualcomm LPG
+    - wcn36xx: Fix warning due to duplicate scan_completed notification
+    - arm64: dts: Add CPR DT node for msm8916
+    - arm64: dts: add spmi-regulator nodes
+    - arm64: dts: msm8916: Add cpufreq support
+    - arm64: dts: msm8916: Add a shared CPU opp table
+    - arm64: dts: msm8916: Add cpu cooling maps
+    - arm64: dts: pm8916: Mark the s2 regulator as always-on
+    - arm64: dts: qcom: msm8916: Add msm8916 A53 PLL DT node
+    - arm64: dts: qcom: msm8916: Use the new APCS mailbox driver
+    - arm64: dts: qcom: msm8916: Add clock properties to the APCS node
+    - dt-bindings: media: Binding document for Qualcomm Camera Control Interface
+      driver
+    - MAINTAINERS: Add Qualcomm Camera Control Interface driver
+    - DT: leds: Add Qualcomm Light Pulse Generator binding
+    - arm64: dts: qcom: msm8996: Add mpp and lpg blocks
+    - arm64: dts: qcom: Add pwm node for pm8916
+    - arm64: dts: qcom: Add user LEDs on db820c
+    - arm64: dts: qcom: Add WiFI/BT LEDs on db820c
+    - ARM: dts: qcom: Add LPG node to pm8941
+    - ARM: dts: qcom: honami: Add LPG node and RGB LED
+    - arm64: dts: qcom: Add Camera Control Interface support
+    - arm64: dts: qcom: Add apps_iommu vfe child node
+    - arm64: dts: qcom: Add camss device node
+    - arm64: dts: qcom: Add ov5645 device nodes
+    - arm64: dts: msm8916: Fix camera sensors I2C addresses
+    - arm: dts: qcom: db410c: Enable PWM signal on MPP4
+    - packaging: arm64: add a uboot flavour - part1
+    - packaging: arm64: add a uboot flavour - part2
+    - packaging: arm64: add a uboot flavour - part3
+    - packaging: arm64: add a uboot flavour - part4
+    - packaging: arm64: add a uboot flavour - part5
+    - packaging: arm64: rename uboot flavour to snapdragon
+    - [Config] updateconfigs after qcomlt import
+    - [Config] arm64: snapdragon: COMMON_CLK_QCOM=y
+    - [Config] arm64: snapdragon: MSM_GCC_8916=y
+    - [Config] arm64: snapdragon: REGULATOR_FIXED_VOLTAGE=y
+    - [Config] arm64: snapdragon: PINCTRL_MSM8916=y
+    - [Config] arm64: snapdragon: HWSPINLOCK_QCOM=y
+    - [Config] arm64: snapdragon: SPMI=y, SPMI_MSM_PMIC_ARB=y
+    - [Config] arm64: snapdragon: REGMAP_SPMI=y, PINCTRL_QCOM_SPMI_PMIC=y
+    - [Config] arm64: snapdragon: REGULATOR_QCOM_SPMI=y
+    - [Config] arm64: snapdragon: MFD_SPMI_PMIC=y
+    - [Config] arm64: snapdragon: QCOM_SMEM=y
+    - [Config] arm64: snapdragon: RPMSG=y, RPMSG_QCOM_SMD=y
+    - [Config] arm64: snapdragon: QCOM_SMD_RPM=y, REGULATOR_QCOM_SMD_RPM=y
+    - [Config] arm64: snapdragon: QCOM_CLK_SMD_RPM=y
+    - [Config] arm64: snapdragon: QCOM_BAM_DMA=y
+    - [Config] arm64: snapdragon: QCOM_HIDMA=y, QCOM_HIDMA_MGMT=y
+    - [Config] arm64: snapdragon: QCOM_CPR=y
+    - [Config] arm64: snapdragon: QCOM_QFPROM=y, QCOM_TSENS=y
+    - [Config] arm64: snapdragon: MMC_SDHCI=y, MMC_SDHCI_PLTFM=y, MMC_SDHCI_MSM=y
+    - [Config] turn off DRM_MSM_REGISTER_LOGGING
+    - [Config] arm64: snapdragon: I2C_QUP=y
+    - [Config] arm64: snapdragon: SPI_QUP=y
+    - [Config] arm64: snapdragon: USB_ULPI_BUS=y, PHY_QCOM_USB_HS=y
+    - [Config] arm64: snapdragon: QCOM_APCS_IPC=y
+    - [Config] arm64: snapdragon: QCOM_WCNSS_CTRL=y
+    - [Config] arm64: snapdragon: QCOM_SMSM=y
+    - [Config] arm64: snapdragon: QCOM_SMP2P=y
+    - [Config] arm64: snapdragon: DRM_MSM=y
+    - [Config] arm64: snapdragon: SND_SOC=y
+    - [Config] arm64: snapdragon: QCOM_WCNSS_PIL=m
+    - [Config] arm64: snapdragon: INPUT_PM8941_PWRKEY=y
+    - [Config] arm64: snapdragon: MEDIA_SUBDRV_AUTOSELECT=y, VIDEO_OV5645=m
+    - [Config] arm64: snapdragon: SND_SOC_APQ8016_SBC=y, SND_SOC_LPASS_APQ8016=y
+    - [Config] arm64: snapdragon: SND_SOC_MSM8916_WCD_ANALOG=y,
+      SND_SOC_MSM8916_WCD_DIGITAL=y
+    - SAUCE: media: ov5645: skip address change if dt addr == default addr
+    - SAUCE: drm/msm/adv7511: wrap hacks under CONFIG_ADV7511_SNAPDRAGON_HACKS
+      #ifdefs
+    - [Config] arm64: snapdragon: ADV7511_SNAPDRAGON_HACKS=y
+    - [Packaging] fix up snapdragon abi paths
+
+  * LSM stacking patches for bionic (LP: #1763062)
+    - SAUCE: LSM stacking: procfs: add smack subdir to attrs
+    - SAUCE: LSM stacking: LSM: Manage credential security blobs
+    - SAUCE: LSM stacking: LSM: Manage file security blobs
+    - SAUCE: LSM stacking: LSM: Manage task security blobs
+    - SAUCE: LSM stacking: LSM: Manage remaining security blobs
+    - SAUCE: LSM stacking: LSM: General stacking
+    - SAUCE: LSM stacking: fixup initialize task->security
+    - SAUCE: LSM stacking: fixup: alloc_task_ctx is dead code
+    - SAUCE: LSM stacking: add support for stacking getpeersec_stream
+    - SAUCE: LSM stacking: add stacking support to apparmor network hooks
+    - SAUCE: LSM stacking: fixup apparmor stacking enablement
+    - SAUCE: LSM stacking: fixup stacking kconfig
+    - SAUCE: LSM stacking: allow selecting multiple LSMs using kernel boot params
+    - SAUCE: LSM stacking: provide prctl interface for setting context
+    - SAUCE: LSM stacking: inherit current display LSM
+    - SAUCE: LSM stacking: keep an index for each registered LSM
+    - SAUCE: LSM stacking: verify display LSM
+    - SAUCE: LSM stacking: provide a way to specify the default display lsm
+    - SAUCE: LSM stacking: make sure LSM blob align on 64 bit boundaries
+    - SAUCE: LSM stacking: add /proc/<pid>/attr/display_lsm
+    - SAUCE: LSM stacking: add Kconfig to set default display LSM
+    - SAUCE: LSM stacking: add configs for LSM stacking
+    - SAUCE: LSM stacking: add apparmor and selinux proc dirs
+    - SAUCE: LSM stacking: remove procfs context interface
+
+  * linux 4.13.0-13.14 ADT test failure with linux 4.13.0-13.14
+    (LP: #1720779) // LSM stacking patches for bionic (LP: #1763062)
+    - SAUCE: LSM stacking: check for invalid zero sized writes
+
+  * Support cq/rq record doorbell for RDMA on HSilicon hip08 systems
+    (LP: #1762755)
+    - RDMA/hns: Support rq record doorbell for the user space
+    - RDMA/hns: Support cq record doorbell for the user space
+    - RDMA/hns: Support rq record doorbell for kernel space
+    - RDMA/hns: Support cq record doorbell for kernel space
+    - RDMA/hns: Fix cqn type and init resp
+    - RDMA/hns: Fix init resp when alloc ucontext
+    - RDMA/hns: Fix cq record doorbell enable in kernel
+
+  * Replace LPC patchset with upstream version (LP: #1762758)
+    - Revert "UBUNTU: SAUCE: MAINTAINERS: Add maintainer for HiSilicon LPC driver"
+    - Revert "UBUNTU: SAUCE: HISI LPC: Add ACPI support"
+    - Revert "UBUNTU: SAUCE: ACPI / scan: do not enumerate Indirect IO host
+      children"
+    - Revert "UBUNTU: SAUCE: HISI LPC: Support the LPC host on Hip06/Hip07 with DT
+      bindings"
+    - Revert "UBUNTU: SAUCE: OF: Add missing I/O range exception for indirect-IO
+      devices"
+    - Revert "UBUNTU: SAUCE: PCI: Apply the new generic I/O management on PCI IO
+      hosts"
+    - Revert "UBUNTU: SAUCE: PCI: Add fwnode handler as input param of
+      pci_register_io_range()"
+    - Revert "UBUNTU: SAUCE: PCI: Remove unused __weak attribute in
+      pci_register_io_range()"
+    - Revert "UBUNTU: SAUCE: LIB: Introduce a generic PIO mapping method"
+    - lib: Add generic PIO mapping method
+    - PCI: Remove __weak tag from pci_register_io_range()
+    - PCI: Add fwnode handler as input param of pci_register_io_range()
+    - PCI: Apply the new generic I/O management on PCI IO hosts
+    - of: Add missing I/O range exception for indirect-IO devices
+    - HISI LPC: Support the LPC host on Hip06/Hip07 with DT bindings
+    - ACPI / scan: Rename acpi_is_serial_bus_slave() for more general use
+    - ACPI / scan: Do not enumerate Indirect IO host children
+    - HISI LPC: Add ACPI support
+    - MAINTAINERS: Add John Garry as maintainer for HiSilicon LPC driver
+
+  * Enable Tunneled Operations on POWER9 (LP: #1762448)
+    - powerpc/powernv: Enable tunneled operations
+    - cxl: read PHB indications from the device tree
+
+  * PSL traces reset after PERST for debug AFU image (LP: #1762462)
+    - cxl: Enable NORST bit in PSL_DEBUG register for PSL9
+
+  * NFS + sec=krb5 is broken (LP: #1759791)
+    - sunrpc: remove incorrect HMAC request initialization
+
+  * Raspberry Pi 3 microSD support missing from the installer (LP: #1729128)
+    - d-i: add bcm2835 to block-modules
+
+  * Backport USB core quirks (LP: #1762695)
+    - usb: core: Add "quirks" parameter for usbcore
+    - usb: core: Copy parameter string correctly and remove superfluous null check
+    - usb: core: Add USB_QUIRK_DELAY_CTRL_MSG to usbcore quirks
+
+  * [Ubuntu 18.04] cryptsetup: 'device-mapper: reload ioctl on  failed' when
+    setting up a second end-to-end encrypted disk (LP: #1762353)
+    - SAUCE: s390/crypto: Adjust s390 aes and paes cipher
+
+  * System Z {kernel} UBUNTU18.04 wrong kernel config (LP: #1762719)
+    - s390: move nobp parameter functions to nospec-branch.c
+    - s390: add automatic detection of the spectre defense
+    - s390: report spectre mitigation via syslog
+    - s390: add sysfs attributes for spectre
+    - [Config] CONFIG_EXPOLINE_AUTO=y, CONFIG_KERNEL_NOBP=n for s390
+    - s390: correct nospec auto detection init order
+
+  * Additional spectre and meltdown patches (LP: #1760099) // CVE-2017-5715
+    - powerpc/64s: Wire up cpu_show_spectre_v2()
+
+  * Additional spectre and meltdown patches (LP: #1760099) // CVE-2017-5753
+    - powerpc/64s: Wire up cpu_show_spectre_v1()
+
+  * Additional spectre and meltdown patches (LP: #1760099) // CVE-2017-5754
+    - powerpc/rfi-flush: Move the logic to avoid a redo into the debugfs code
+    - powerpc/rfi-flush: Make it possible to call setup_rfi_flush() again
+    - powerpc/rfi-flush: Always enable fallback flush on pseries
+    - powerpc/rfi-flush: Differentiate enabled and patched flush types
+    - powerpc/rfi-flush: Call setup_rfi_flush() after LPM migration
+    - powerpc/64s: Move cpu_show_meltdown()
+    - powerpc/64s: Enhance the information in cpu_show_meltdown()
+    - powerpc/powernv: Use the security flags in pnv_setup_rfi_flush()
+    - powerpc/pseries: Use the security flags in pseries_setup_rfi_flush()
+
+  * Additional spectre and meltdown patches (LP: #1760099) // CVE-2017-5715 //
+    CVE-2017-5753 // CVE-2017-5754
+    - powerpc/pseries: Add new H_GET_CPU_CHARACTERISTICS flags
+    - powerpc: Add security feature flags for Spectre/Meltdown
+    - powerpc/pseries: Set or clear security feature flags
+    - powerpc/powernv: Set or clear security feature flags
+
+  * Hisilicon network subsystem 3 support (LP: #1761610)
+    - net: hns3: export pci table of hclge and hclgevf to userspace
+    - d-i: Add hns3 drivers to nic-modules
+
+  * "ip a" command on a guest VM shows UNKNOWN status (LP: #1761534)
+    - virtio-net: Fix operstate for virtio when no VIRTIO_NET_F_STATUS
+
+  * perf vendor events arm64: Enable JSON events for ThunderX2 B0 (LP: #1760712)
+    - perf vendor events: Drop incomplete multiple mapfile support
+    - perf vendor events: Fix error code in json_events()
+    - perf vendor events: Drop support for unused topic directories
+    - perf vendor events: Add support for pmu events vendor subdirectory
+    - perf vendor events arm64: Relocate ThunderX2 JSON to cavium subdirectory
+    - perf vendor events arm64: Relocate Cortex A53 JSONs to arm subdirectory
+    - perf vendor events: Add support for arch standard events
+    - perf vendor events arm64: Add armv8-recommended.json
+    - perf vendor events arm64: Fixup ThunderX2 to use recommended events
+    - perf vendor events arm64: fixup A53 to use recommended events
+    - perf vendor events arm64: add HiSilicon hip08 JSON file
+    - perf vendor events arm64: Enable JSON events for ThunderX2 B0
+
+  * Warning "cache flush timed out!" seen when unloading the cxl driver
+    (LP: #1762367)
+    - cxl: Check if PSL data-cache is available before issue flush request
+
+  * Bionic update to v4.16.1 stable release (LP: #1763170)
+    - bitmap: fix memset optimization on big-endian systems
+    - USB: serial: ftdi_sio: add RT Systems VX-8 cable
+    - USB: serial: ftdi_sio: add support for Harman FirmwareHubEmulator
+    - USB: serial: cp210x: add ELDAT Easywave RX09 id
+    - serial: 8250: Add Nuvoton NPCM UART
+    - mei: remove dev_err message on an unsupported ioctl
+    - /dev/mem: Avoid overwriting "err" in read_mem()
+    - media: usbtv: prevent double free in error case
+    - parport_pc: Add support for WCH CH382L PCI-E single parallel port card.
+    - crypto: lrw - Free rctx->ext with kzfree
+    - crypto: ccp - Fill the result buffer only on digest, finup, and final ops
+    - crypto: talitos - don't persistently map req_ctx->hw_context and
+      req_ctx->buf
+    - crypto: inside-secure - fix clock management
+    - crypto: testmgr - Fix incorrect values in PKCS#1 test vector
+    - crypto: talitos - fix IPsec cipher in length
+    - crypto: ahash - Fix early termination in hash walk
+    - crypto: caam - Fix null dereference at error path
+    - crypto: ccp - return an actual key size from RSA max_size callback
+    - crypto: arm,arm64 - Fix random regeneration of S_shipped
+    - crypto: x86/cast5-avx - fix ECB encryption when long sg follows short one
+    - Bluetooth: hci_bcm: Add 6 new ACPI HIDs
+    - Btrfs: fix unexpected cow in run_delalloc_nocow
+    - siox: fix possible buffer overflow in device_add_store
+    - staging: comedi: ni_mio_common: ack ai fifo error interrupts.
+    - Revert "base: arch_topology: fix section mismatch build warnings"
+    - Input: ALPS - fix TrackStick detection on Thinkpad L570 and Latitude 7370
+    - Input: i8042 - add Lenovo ThinkPad L460 to i8042 reset list
+    - Input: i8042 - enable MUX on Sony VAIO VGN-CS series to fix touchpad
+    - vt: change SGR 21 to follow the standards
+    - Fix slab name "biovec-(1<<(21-12))"
+    - signal: Correct the offset of si_pkey and si_lower in struct siginfo on m68k
+    - Linux 4.16.1
+
+  * [18.04][config] regression: nvme and nvme_core couldn't be built as modules
+    starting 4.15-rc2 (LP: #1759893)
+    - SAUCE: Revert "lightnvm: include NVM Express driver if OCSSD is selected for
+      build"
+    - [Config] CONFIG_BLK_DEV_NMVE=m
+
+  * FFe: Enable configuring resume offset via sysfs (LP: #1760106)
+    - PM / hibernate: Make passing hibernate offsets more friendly
+
+  * Ubuntu18.04:POWER9:DD2.2 - Unable to start a KVM guest with default machine
+    type(pseries-bionic) complaining "KVM implementation does not support
+    Transactional Memory, try cap-htm=off" (kvm) (LP: #1752026)
+    - powerpc: Use feature bit for RTC presence rather than timebase presence
+    - powerpc: Book E: Remove unused CPU_FTR_L2CSR bit
+    - powerpc: Free up CPU feature bits on 64-bit machines
+    - powerpc: Add CPU feature bits for TM bug workarounds on POWER9 v2.2
+    - powerpc/powernv: Provide a way to force a core into SMT4 mode
+    - KVM: PPC: Book3S HV: Work around transactional memory bugs in POWER9
+    - KVM: PPC: Book3S HV: Work around XER[SO] bug in fake suspend mode
+    - KVM: PPC: Book3S HV: Work around TEXASR bug in fake suspend state
+
+  * [Feature][CFL][ICL] [CNL]Thunderbolt support (Titan Ridge) (LP: #1730775)
+    - thunderbolt: Resume control channel after hibernation image is created
+    - thunderbolt: Serialize PCIe tunnel creation with PCI rescan
+    - thunderbolt: Handle connecting device in place of host properly
+    - thunderbolt: Do not overwrite error code when domain adding fails
+    - thunderbolt: Wait a bit longer for root switch config space
+    - thunderbolt: Wait a bit longer for ICM to authenticate the active NVM
+    - thunderbolt: Handle rejected Thunderbolt devices
+    - thunderbolt: Factor common ICM add and update operations out
+    - thunderbolt: Correct function name in kernel-doc comment
+    - thunderbolt: Add tb_switch_get()
+    - thunderbolt: Add tb_switch_find_by_route()
+    - thunderbolt: Add tb_xdomain_find_by_route()
+    - thunderbolt: Add constant for approval timeout
+    - thunderbolt: Move driver ready handling to struct icm
+    - thunderbolt: Add 'boot' attribute for devices
+    - thunderbolt: Add support for preboot ACL
+    - thunderbolt: Introduce USB only (SL4) security level
+    - thunderbolt: Add support for Intel Titan Ridge
+
+  * QCA9377 requires more IRAM banks for its new firmware (LP: #1748345)
+    - ath10k: update the IRAM bank number for QCA9377
+
+  * Fix an issue that when system in S3, USB keyboard can't wake up the system.
+    (LP: #1759511)
+    - ACPI / PM: Allow deeper wakeup power states with no _SxD nor _SxW
+
+  * cxl: Fix timebase synchronization status on POWER9 missing (CAPI)
+    (LP: #1757228)
+    - cxl: Fix timebase synchronization status on P9
+
+  * [Feature]Update Ubuntu 18.04 lpfc FC driver with 32/64GB HBA support and bug
+    fixes (LP: #1752182)
+    - scsi: lpfc: Fix frequency of Release WQE CQEs
+    - scsi: lpfc: Increase CQ and WQ sizes for SCSI
+    - scsi: lpfc: move placement of target destroy on driver detach
+    - scsi: lpfc: correct debug counters for abort
+    - scsi: lpfc: Add WQ Full Logic for NVME Target
+    - scsi: lpfc: Fix PRLI handling when topology type changes
+    - scsi: lpfc: Fix IO failure during hba reset testing with nvme io.
+    - scsi: lpfc: Fix RQ empty firmware trap
+    - scsi: lpfc: Allow set of maximum outstanding SCSI cmd limit for a target
+    - scsi: lpfc: Fix soft lockup in lpfc worker thread during LIP testing
+    - scsi: lpfc: Fix issue_lip if link is disabled
+    - scsi: lpfc: Indicate CONF support in NVMe PRLI
+    - scsi: lpfc: Fix SCSI io host reset causing kernel crash
+    - scsi: lpfc: Validate adapter support for SRIU option
+    - scsi: lpfc: Fix header inclusion in lpfc_nvmet
+    - scsi: lpfc: Treat SCSI Write operation Underruns as an error
+    - scsi: lpfc: Fix nonrecovery of NVME controller after cable swap.
+    - scsi: lpfc: update driver version to 11.4.0.7
+    - scsi: lpfc: Update 11.4.0.7 modified files for 2018 Copyright
+    - scsi: lpfc: Rework lpfc to allow different sli4 cq and eq handlers
+    - scsi: lpfc: Rework sli4 doorbell infrastructure
+    - scsi: lpfc: Add SLI-4 if_type=6 support to the code base
+    - scsi: lpfc: Add push-to-adapter support to sli4
+    - scsi: lpfc: Add PCI Ids for if_type=6 hardware
+    - scsi: lpfc: Add 64G link speed support
+    - scsi: lpfc: Add if_type=6 support for cycling valid bits
+    - scsi: lpfc: Enable fw download on if_type=6 devices
+    - scsi: lpfc: Add embedded data pointers for enhanced performance
+    - scsi: lpfc: Fix nvme embedded io length on new hardware
+    - scsi: lpfc: Work around NVME cmd iu SGL type
+    - scsi: lpfc: update driver version to 12.0.0.0
+    - scsi: lpfc: Change Copyright of 12.0.0.0 modified files to 2018
+    - scsi: lpfc: use __raw_writeX on DPP copies
+    - scsi: lpfc: Add missing unlock in WQ full logic
+
+  * /dev/bcache/by-uuid links not created after reboot (LP: #1729145)
+    - SAUCE: (no-up) bcache: decouple emitting a cached_dev CHANGE uevent
+
+  * DKMS driver builds fail with: Cannot use CONFIG_STACK_VALIDATION=y, please
+    install libelf-dev, libelf-devel or elfutils-libelf-devel (LP: #1760876)
+    - [Packaging] include the retpoline extractor in the headers
+
+  * Use med_with_dipm SATA LPM to save more power for mobile platforms
+    (LP: #1759547)
+    - [Config] CONFIG_SATA_MOBILE_LPM_POLICY=3
+
+  * Miscellaneous Ubuntu changes
+    - [Packaging] Only install cloud init files when do_tools_common=true
+    - SAUCE: Import aufs driver
+    - [Config] Enable AUFS config options
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Thu, 12 Apr 2018 09:30:56 -0500
+
+linux (4.16.0-3.4) bionic; urgency=medium
+
+  * Allow multiple mounts of zfs datasets (LP: #1759848)
+    - SAUCE: Allow mounting datasets more than once (LP: #1759848)
+
+  * zfs system process hung on container stop/delete (LP: #1754584)
+    - SAUCE: Fix non-prefaulted page deadlock (LP: #1754584)
+    - Revert "UBUNTU: SAUCE: Fix non-prefaulted page deadlock (LP: #1754584)"
+    - SAUCE: Fix non-prefaulted page deadlock (LP: #1754584)
+
+  * ubuntu_zram_smoke test will cause soft lockup on Artful ThunderX ARM64
+    (LP: #1755073)
+    - SAUCE: crypto: thunderx_zip: Fix fallout from CONFIG_VMAP_STACK
+
+  * CAPI Flash (cxlflash) update (LP: #1752672)
+    - SAUCE: cxlflash: Preserve number of interrupts for master contexts
+    - SAUCE: cxlflash: Avoid clobbering context control register value
+    - SAUCE: cxlflash: Add argument identifier names
+    - SAUCE: cxlflash: Introduce OCXL backend
+    - SAUCE: cxlflash: Hardware AFU for OCXL
+    - SAUCE: cxlflash: Read host function configuration
+    - SAUCE: cxlflash: Setup function acTag range
+    - SAUCE: cxlflash: Read host AFU configuration
+    - SAUCE: cxlflash: Setup AFU acTag range
+    - SAUCE: cxlflash: Setup AFU PASID
+    - SAUCE: cxlflash: Adapter context support for OCXL
+    - SAUCE: cxlflash: Use IDR to manage adapter contexts
+    - SAUCE: cxlflash: Support adapter file descriptors for OCXL
+    - SAUCE: cxlflash: Support adapter context discovery
+    - SAUCE: cxlflash: Support image reload policy modification
+    - SAUCE: cxlflash: MMIO map the AFU
+    - SAUCE: cxlflash: Support starting an adapter context
+    - SAUCE: cxlflash: Support process specific mappings
+    - SAUCE: cxlflash: Support AFU state toggling
+    - SAUCE: cxlflash: Support reading adapter VPD data
+    - SAUCE: cxlflash: Setup function OCXL link
+    - SAUCE: cxlflash: Setup OCXL transaction layer
+    - SAUCE: cxlflash: Support process element lifecycle
+    - SAUCE: cxlflash: Support AFU interrupt management
+    - SAUCE: cxlflash: Support AFU interrupt mapping and registration
+    - SAUCE: cxlflash: Support starting user contexts
+    - SAUCE: cxlflash: Support adapter context polling
+    - SAUCE: cxlflash: Support adapter context reading
+    - SAUCE: cxlflash: Support adapter context mmap and release
+    - SAUCE: cxlflash: Support file descriptor mapping
+    - SAUCE: cxlflash: Introduce object handle fop
+    - SAUCE: cxlflash: Setup LISNs for user contexts
+    - SAUCE: cxlflash: Setup LISNs for master contexts
+    - SAUCE: cxlflash: Update synchronous interrupt status bits
+    - SAUCE: cxlflash: Introduce OCXL context state machine
+    - SAUCE: cxlflash: Register for translation errors
+    - SAUCE: cxlflash: Support AFU reset
+    - SAUCE: cxlflash: Enable OCXL operations
+
+  * [Artful][Wyse 3040] System hang when trying to enable an offlined CPU core
+    (LP: #1736393)
+    - SAUCE: drm/i915:Don't set chip specific data
+    - SAUCE: drm/i915: make previous commit affects Wyse 3040 only
+
+  * zed process consuming 100% cpu (LP: #1751796)
+    - SAUCE: Fix ioctl loop-spin in zed (LP: #1751796)
+
+  * Ubuntu18.04:PowerPC - Set Transparent Huge Pages (THP) by default to
+    "always" (LP: #1753708)
+    - Config: Set TRANSPARENT_HUGEPAGE_ALWAYS=y on ppc64el
+
+  * retpoline hints: primary infrastructure and initial hints (LP: #1758856)
+    - [Packaging] retpoline -- add safe usage hint support
+    - [Packaging] retpoline-check -- only report additions
+    - [Packaging] retpoline -- widen indirect call/jmp detection
+    - [Packaging] retpoline -- elide %rip relative indirections
+    - [Packaging] retpoline -- clear hint information from packages
+    - SAUCE: apm -- annotate indirect calls within
+      firmware_restrict_branch_speculation_{start,end}
+    - SAUCE: EFI -- annotate indirect calls within
+      firmware_restrict_branch_speculation_{start,end}
+    - SAUCE: early/late -- annotate indirect calls in early/late initialisation
+      code
+    - SAUCE: vga_set_mode -- avoid jump tables
+    - [Config] retpoine -- switch to new format
+
+  * Miscellaneous Ubuntu changes
+    - [Packaging] final-checks -- remove check for empty retpoline files
+    - [Packaging] skip cloud tools packaging when not building package
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.16
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 02 Apr 2018 16:15:36 -0500
+
+linux (4.16.0-2.3) bionic; urgency=medium
+
+  * devpts: handle bind-mounts (LP: #1755857)
+    - SAUCE: devpts: hoist out check for DEVPTS_SUPER_MAGIC
+    - SAUCE: devpts: resolve devpts bind-mounts
+    - SAUCE: devpts: comment devpts_mntget()
+    - SAUCE: selftests: add devpts selftests
+
+  * [bionic][arm64] d-i: add hisi_sas_v3_hw to scsi-modules (LP: #1756103)
+    - d-i: add hisi_sas_v3_hw to scsi-modules
+
+  * [Bionic][ARM64] PCI and SAS driver patches for hip08 SoCs (LP: #1756094)
+    - SAUCE: scsi: hisi_sas: config for hip08 ES
+    - SAUCE: scsi: hisi_sas: export device table of v3 hw to userspace
+
+  * s390/crypto: Fix kernel crash on aes_s390 module remove (LP: #1753424)
+    - SAUCE: s390/crypto: Fix kernel crash on aes_s390 module remove.
+
+  * Fix ARC hit rate (LP: #1755158)
+    - SAUCE: Fix ARC hit rate (LP: #1755158)
+
+  * ZFS setgid broken on 0.7 (LP: #1753288)
+    - SAUCE: Fix ZFS setgid
+
+  * CONFIG_EFI=y on armhf (LP: #1726362)
+    - [Config] CONFIG_EFI=y on armhf, reconcile secureboot EFI settings
+
+  * [Feature] Add xHCI debug device support in the driver (LP: #1730832)
+    - [Config] CONFIG_USB_XHCI_DBGCAP=y
+
+  * retpoline: ignore %cs:0xNNN constant indirections (LP: #1752655)
+    - [Packaging] retpoline -- elide %cs:0xNNNN constants on i386
+    - [Config] retpoline -- clean up i386 retpoline files
+
+  * Miscellaneous Ubuntu changes
+    - [Packaging] retpoline-extract: flag *0xNNN(%reg) branches
+    - [Config] fix up retpoline abi files
+    - [Config] fix up retpoline abi files
+    - d-i: Add netsec to nic-modules
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.16-rc6
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 19 Mar 2018 14:09:49 -0500
+
+linux (4.16.0-1.2) bionic; urgency=medium
+
+  * Driver not found in Ubuntu kernel does not detect interface (LP: #1745927)
+    - d-i: add cxgb4 to nic-modules
+
+  * Support low-pin-count devices on Hisilicon SoCs (LP: #1677319)
+    - [Config] CONFIG_INDIRECT_PIO=y
+    - SAUCE: LIB: Introduce a generic PIO mapping method
+    - SAUCE: PCI: Remove unused __weak attribute in pci_register_io_range()
+    - SAUCE: PCI: Add fwnode handler as input param of pci_register_io_range()
+    - SAUCE: PCI: Apply the new generic I/O management on PCI IO hosts
+    - SAUCE: OF: Add missing I/O range exception for indirect-IO devices
+    - [Config] CONFIG_HISILICON_LPC=y
+    - SAUCE: HISI LPC: Support the LPC host on Hip06/Hip07 with DT bindings
+    - SAUCE: ACPI / scan: do not enumerate Indirect IO host children
+    - SAUCE: HISI LPC: Add ACPI support
+    - SAUCE: MAINTAINERS: Add maintainer for HiSilicon LPC driver
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: tools: use CC for linking acpi tools
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.16-rc3
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Wed, 28 Feb 2018 10:17:23 -0600
+
+linux (4.16.0-0.1) bionic; urgency=medium
+
+  * retpoline abi files are empty on i386 (LP: #1751021)
+    - [Packaging] retpoline-extract -- instantiate retpoline files for i386
+    - [Packaging] final-checks -- sanity checking ABI contents
+    - [Packaging] final-checks -- check for empty retpoline files
+
+  * Miscellaneous upstream changes
+    - disable vbox build
+    - Disable zfs build
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.16-rc2
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Thu, 22 Feb 2018 08:58:57 -0600
+
+linux (4.16.0-0.0) bionic; urgency=medium
+
+  * Dummy entry
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Wed, 21 Feb 2018 14:33:13 -0600
+
+linux (4.15.0-10.11) bionic; urgency=medium
+
+  * linux: 4.15.0-10.11 -proposed tracker (LP: #1749250)
+
+  * "swiotlb: coherent allocation failed" dmesg spam with linux 4.15.0-9.10
+    (LP: #1749202)
+    - swiotlb: suppress warning when __GFP_NOWARN is set
+    - drm/ttm: specify DMA_ATTR_NO_WARN for huge page pools
+
+  * linux-tools: perf incorrectly linking libbfd (LP: #1748922)
+    - SAUCE: tools -- add ability to disable libbfd
+    - [Packaging] correct disablement of libbfd
+
+  * [Artful] Realtek ALC225: 2 secs noise when a headset plugged in
+    (LP: #1744058)
+    - ALSA: hda/realtek - update ALC225 depop optimize
+
+  * [Artful] Support headset mode for DELL WYSE (LP: #1723913)
+    - SAUCE: ALSA: hda/realtek - Add support headset mode for DELL WYSE
+
+  * headset mic can't be detected on two Dell machines (LP: #1748807)
+    - ALSA: hda/realtek - Support headset mode for ALC215/ALC285/ALC289
+    - ALSA: hda - Fix headset mic detection problem for two Dell machines
+
+  * Bionic update to v4.15.3 stable release (LP: #1749191)
+    - ip6mr: fix stale iterator
+    - net: igmp: add a missing rcu locking section
+    - qlcnic: fix deadlock bug
+    - qmi_wwan: Add support for Quectel EP06
+    - r8169: fix RTL8168EP take too long to complete driver initialization.
+    - tcp: release sk_frag.page in tcp_disconnect
+    - vhost_net: stop device during reset owner
+    - ipv6: addrconf: break critical section in addrconf_verify_rtnl()
+    - ipv6: change route cache aging logic
+    - Revert "defer call to mem_cgroup_sk_alloc()"
+    - net: ipv6: send unsolicited NA after DAD
+    - rocker: fix possible null pointer dereference in
+      rocker_router_fib_event_work
+    - tcp_bbr: fix pacing_gain to always be unity when using lt_bw
+    - cls_u32: add missing RCU annotation.
+    - ipv6: Fix SO_REUSEPORT UDP socket with implicit sk_ipv6only
+    - soreuseport: fix mem leak in reuseport_add_sock()
+    - net_sched: get rid of rcu_barrier() in tcf_block_put_ext()
+    - net: sched: fix use-after-free in tcf_block_put_ext
+    - media: mtk-vcodec: add missing MODULE_LICENSE/DESCRIPTION
+    - media: soc_camera: soc_scale_crop: add missing
+      MODULE_DESCRIPTION/AUTHOR/LICENSE
+    - media: tegra-cec: add missing MODULE_DESCRIPTION/AUTHOR/LICENSE
+    - gpio: uniphier: fix mismatch between license text and MODULE_LICENSE
+    - crypto: tcrypt - fix S/G table for test_aead_speed()
+    - Linux 4.15.3
+
+  * bnx2x_attn_int_deasserted3:4323 MC assert! (LP: #1715519) //
+    CVE-2018-1000026
+    - net: create skb_gso_validate_mac_len()
+    - bnx2x: disable GSO where gso_size is too big for hardware
+
+  * ethtool -p fails to light NIC LED on HiSilicon D05 systems (LP: #1748567)
+    - net: hns: add ACPI mode support for ethtool -p
+
+  * CVE-2017-5715 (Spectre v2 Intel)
+    - [Packaging] retpoline files must be sorted
+    - [Packaging] pull in retpoline files
+
+  * [Feature] PXE boot with Intel Omni-Path (LP: #1712031)
+    - d-i: Add hfi1 to nic-modules
+
+  * CVE-2017-5715 (Spectre v2 retpoline)
+    - [Packaging] retpoline -- add call site validation
+    - [Config] disable retpoline checks for first upload
+
+  * Do not duplicate changelog entries assigned to more than one bug or CVE
+    (LP: #1743383)
+    - [Packaging] git-ubuntu-log -- handle multiple bugs/cves better
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Tue, 13 Feb 2018 11:33:58 -0600
+
+linux (4.15.0-9.10) bionic; urgency=medium
+
+  * linux: 4.15.0-9.10 -proposed tracker (LP: #1748244)
+
+  * Miscellaneous Ubuntu changes
+    - [Debian] tests -- remove gcc-multilib dependency for arm64
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Thu, 08 Feb 2018 11:25:04 -0600
+
+linux (4.15.0-8.9) bionic; urgency=medium
+
+  * linux: 4.15.0-8.9 -proposed tracker (LP: #1748075)
+
+  * Bionic update to v4.15.2 stable release (LP: #1748072)
+    - KVM: x86: Make indirect calls in emulator speculation safe
+    - KVM: VMX: Make indirect call speculation safe
+    - module/retpoline: Warn about missing retpoline in module
+    - x86/cpufeatures: Add CPUID_7_EDX CPUID leaf
+    - x86/cpufeatures: Add Intel feature bits for Speculation Control
+    - x86/cpufeatures: Add AMD feature bits for Speculation Control
+    - x86/msr: Add definitions for new speculation control MSRs
+    - x86/pti: Do not enable PTI on CPUs which are not vulnerable to Meltdown
+    - x86/cpufeature: Blacklist SPEC_CTRL/PRED_CMD on early Spectre v2 microcodes
+    - x86/speculation: Add basic IBPB (Indirect Branch Prediction Barrier) support
+    - x86/alternative: Print unadorned pointers
+    - x86/nospec: Fix header guards names
+    - x86/bugs: Drop one "mitigation" from dmesg
+    - x86/cpu/bugs: Make retpoline module warning conditional
+    - x86/cpufeatures: Clean up Spectre v2 related CPUID flags
+    - x86/retpoline: Simplify vmexit_fill_RSB()
+    - x86/speculation: Simplify indirect_branch_prediction_barrier()
+    - auxdisplay: img-ascii-lcd: add missing MODULE_DESCRIPTION/AUTHOR/LICENSE
+    - iio: adc/accel: Fix up module licenses
+    - pinctrl: pxa: pxa2xx: add missing MODULE_DESCRIPTION/AUTHOR/LICENSE
+    - ASoC: pcm512x: add missing MODULE_DESCRIPTION/AUTHOR/LICENSE
+    - KVM: nVMX: Eliminate vmcs02 pool
+    - KVM: VMX: introduce alloc_loaded_vmcs
+    - objtool: Improve retpoline alternative handling
+    - objtool: Add support for alternatives at the end of a section
+    - objtool: Warn on stripped section symbol
+    - x86/mm: Fix overlap of i386 CPU_ENTRY_AREA with FIX_BTMAP
+    - x86/spectre: Check CONFIG_RETPOLINE in command line parser
+    - x86/entry/64: Remove the SYSCALL64 fast path
+    - x86/entry/64: Push extra regs right away
+    - x86/asm: Move 'status' from thread_struct to thread_info
+    - Documentation: Document array_index_nospec
+    - array_index_nospec: Sanitize speculative array de-references
+    - x86: Implement array_index_mask_nospec
+    - x86: Introduce barrier_nospec
+    - x86: Introduce __uaccess_begin_nospec() and uaccess_try_nospec
+    - x86/usercopy: Replace open coded stac/clac with __uaccess_{begin, end}
+    - x86/uaccess: Use __uaccess_begin_nospec() and uaccess_try_nospec
+    - x86/get_user: Use pointer masking to limit speculation
+    - x86/syscall: Sanitize syscall table de-references under speculation
+    - vfs, fdtable: Prevent bounds-check bypass via speculative execution
+    - nl80211: Sanitize array index in parse_txq_params
+    - x86/spectre: Report get_user mitigation for spectre_v1
+    - x86/spectre: Fix spelling mistake: "vunerable"-> "vulnerable"
+    - x86/cpuid: Fix up "virtual" IBRS/IBPB/STIBP feature bits on Intel
+    - x86/speculation: Use Indirect Branch Prediction Barrier in context switch
+    - x86/paravirt: Remove 'noreplace-paravirt' cmdline option
+    - KVM: VMX: make MSR bitmaps per-VCPU
+    - x86/kvm: Update spectre-v1 mitigation
+    - x86/retpoline: Avoid retpolines for built-in __init functions
+    - x86/spectre: Simplify spectre_v2 command line parsing
+    - x86/pti: Mark constant arrays as __initconst
+    - x86/speculation: Fix typo IBRS_ATT, which should be IBRS_ALL
+    - KVM/x86: Update the reverse_cpuid list to include CPUID_7_EDX
+    - KVM/x86: Add IBPB support
+    - KVM/VMX: Emulate MSR_IA32_ARCH_CAPABILITIES
+    - KVM/VMX: Allow direct access to MSR_IA32_SPEC_CTRL
+    - KVM/SVM: Allow direct access to MSR_IA32_SPEC_CTRL
+    - serial: core: mark port as initialized after successful IRQ change
+    - fpga: region: release of_parse_phandle nodes after use
+    - Linux 4.15.2
+
+  * Add support for the NIC on SynQuacer E-Series boards (LP: #1747792)
+    - net: phy: core: remove now uneeded disabling of interrupts
+    - [Config] CONFIG_NET_VENDOR_SOCIONEXT=y & CONFIG_SNI_NETSEC=m
+    - net: socionext: Add Synquacer NetSec driver
+    - net: socionext: include linux/io.h to fix build
+    - net: socionext: Fix error return code in netsec_netdev_open()
+
+  * [Artful/Bionic] [Config] enable EDAC_GHES for ARM64 (LP: #1747746)
+    - [Config] CONFIG_EDAC_GHES=y
+
+  * support thunderx2 vendor pmu events (LP: #1747523)
+    - perf pmu: Pass pmu as a parameter to get_cpuid_str()
+    - perf tools arm64: Add support for get_cpuid_str function.
+    - perf pmu: Add helper function is_pmu_core to detect PMU CORE devices
+    - perf vendor events arm64: Add ThunderX2 implementation defined pmu core
+      events
+    - perf pmu: Add check for valid cpuid in perf_pmu__find_map()
+
+  * linux 4.14.0-7.9 ADT test failure with linux 4.14.0-7.9 (LP: #1732463)
+    - SAUCE: mm: disable vma based swap readahead by default
+    - SAUCE: mm: fix memory hotplug in ZONE_HIGHMEM
+
+  * Miscellaneous Ubuntu changes
+    - [Config] Fix CONFIG_PROFILE_ALL_BRANCHES annotations
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Wed, 07 Feb 2018 21:13:27 -0600
+
+linux (4.15.0-7.8) bionic; urgency=medium
+
+  * Bionic update to v4.15.1 stable release (LP: #1747169)
+    - Bluetooth: hci_serdev: Init hci_uart proto_lock to avoid oops
+    - tools/gpio: Fix build error with musl libc
+    - gpio: stmpe: i2c transfer are forbiden in atomic context
+    - gpio: Fix kernel stack leak to userspace
+    - ALSA: hda - Reduce the suspend time consumption for ALC256
+    - crypto: ecdh - fix typo in KPP dependency of CRYPTO_ECDH
+    - crypto: aesni - handle zero length dst buffer
+    - crypto: aesni - fix typo in generic_gcmaes_decrypt
+    - crypto: aesni - add wrapper for generic gcm(aes)
+    - crypto: aesni - Fix out-of-bounds access of the data buffer in generic-gcm-
+      aesni
+    - crypto: aesni - Fix out-of-bounds access of the AAD buffer in generic-gcm-
+      aesni
+    - crypto: inside-secure - fix hash when length is a multiple of a block
+    - crypto: inside-secure - avoid unmapping DMA memory that was not mapped
+    - crypto: sha3-generic - fixes for alignment and big endian operation
+    - crypto: af_alg - whitelist mask and type
+    - HID: wacom: EKR: ensure devres groups at higher indexes are released
+    - HID: wacom: Fix reporting of touch toggle (WACOM_HID_WD_MUTE_DEVICE) events
+    - power: reset: zx-reboot: add missing MODULE_DESCRIPTION/AUTHOR/LICENSE
+    - gpio: iop: add missing MODULE_DESCRIPTION/AUTHOR/LICENSE
+    - gpio: ath79: add missing MODULE_DESCRIPTION/LICENSE
+    - mtd: nand: denali_pci: add missing MODULE_DESCRIPTION/AUTHOR/LICENSE
+    - igb: Free IRQs when device is hotplugged
+    - ima/policy: fix parsing of fsuuid
+    - scsi: aacraid: Fix udev inquiry race condition
+    - scsi: aacraid: Fix hang in kdump
+    - scsi: storvsc: missing error code in storvsc_probe()
+    - staging: lustre: separate a connection destroy from free struct kib_conn
+    - staging: ccree: NULLify backup_info when unused
+    - staging: ccree: fix fips event irq handling build
+    - tty: fix data race between tty_init_dev and flush of buf
+    - usb: option: Add support for FS040U modem
+    - USB: serial: pl2303: new device id for Chilitag
+    - USB: cdc-acm: Do not log urb submission errors on disconnect
+    - CDC-ACM: apply quirk for card reader
+    - USB: serial: io_edgeport: fix possible sleep-in-atomic
+    - usbip: prevent bind loops on devices attached to vhci_hcd
+    - usbip: list: don't list devices attached to vhci_hcd
+    - USB: serial: simple: add Motorola Tetra driver
+    - usb: f_fs: Prevent gadget unbind if it is already unbound
+    - usb: uas: unconditionally bring back host after reset
+    - usb/gadget: Fix "high bandwidth" check in usb_gadget_ep_match_desc()
+    - ANDROID: binder: remove waitqueue when thread exits.
+    - android: binder: use VM_ALLOC to get vm area
+    - mei: me: allow runtime pm for platform with D0i3
+    - serial: 8250_of: fix return code when probe function fails to get reset
+    - serial: 8250_uniphier: fix error return code in uniphier_uart_probe()
+    - serial: 8250_dw: Revert "Improve clock rate setting"
+    - serial: imx: Only wakeup via RTSDEN bit if the system has RTS/CTS
+    - spi: imx: do not access registers while clocks disabled
+    - iio: adc: stm32: fix scan of multiple channels with DMA
+    - iio: chemical: ccs811: Fix output of IIO_CONCENTRATION channels
+    - test_firmware: fix missing unlock on error in config_num_requests_store()
+    - Input: synaptics-rmi4 - unmask F03 interrupts when port is opened
+    - Input: synaptics-rmi4 - do not delete interrupt memory too early
+    - x86/efi: Clarify that reset attack mitigation needs appropriate userspace
+    - Linux 4.15.1
+
+  * Dell XPS 13 9360 bluetooth (Atheros) won't connect after resume
+    (LP: #1744712)
+    - Revert "Bluetooth: btusb: fix QCA Rome suspend/resume"
+    - Bluetooth: btusb: Restore QCA Rome suspend/resume fix with a "rewritten"
+      version
+
+  * apparmor profile load in stacked policy container fails (LP: #1746463)
+    - SAUCE: apparmor: fix display of .ns_name for containers
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Sun, 04 Feb 2018 11:56:32 +0100
+
+linux (4.15.0-6.7) bionic; urgency=low
+
+  * upload urgency should be medium by default (LP: #1745338)
+    - [Packaging] update urgency to medium by default
+
+  * Shutdown hang on 16.04 with iscsi targets (LP: #1569925)
+    - scsi: libiscsi: Allow sd_shutdown on bad transport
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: (noup) Update spl to 0.7.5-1ubuntu1, zfs to 0.7.5-1ubuntu1
+    - Revert "UBUNTU: SAUCE: mm: fix memory hotplug in ZONE_HIGHMEM"
+    - Revert "UBUNTU: SAUCE: mm: disable vma based swap readahead by default"
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.15
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 29 Jan 2018 08:47:07 -0600
+
+linux (4.15.0-5.6) bionic; urgency=low
+
+  * $(LOCAL_ENV_CC) and $(LOCAL_ENV_DISTCC_HOSTS) should be properly quoted
+    (LP: #1744077)
+    - [Debian] pass LOCAL_ENV_CC and LOCAL_ENV_DISTCC_HOSTS properly
+
+  * Missing install-time driver for QLogic QED 25/40/100Gb Ethernet NIC
+    (LP: #1743638)
+    - [d-i] Add qede to nic-modules udeb
+
+  * boot failure on AMD Raven + WesternXT (LP: #1742759)
+    - SAUCE: drm/amdgpu: add atpx quirk handling (v2)
+
+  * Unable to handle kernel NULL pointer dereference at isci_task_abort_task
+    (LP: #1726519)
+    - SAUCE: Revert "scsi: libsas: allow async aborts"
+
+  * Update Ubuntu-4.15.0 config to support Intel Atom devices (LP: #1739939)
+    - [Config] CONFIG_SERIAL_DEV_BUS=y, CONFIG_SERIAL_DEV_CTRL_TTYPORT=y
+
+  * Miscellaneous Ubuntu changes
+    - Rebase to v4.15-rc7
+    - [Config] CONFIG_CPU_ISOLATION=y
+    - [Config] Update annotations following config review
+    - Revert "UBUNTU: SAUCE: Import aufs driver"
+    - SAUCE: Import aufs driver
+    - ubuntu: vbox -- update to 5.2.6-dfsg-1
+    - ubuntu: vbox: build fixes for 4.15
+    - ubuntu: vbox -- update to 5.2.6-dfsg-2
+    - hio: updates for timer api changes in 4.15
+    - enable hio build
+    - Rebase to v4.15-rc9
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.15-rc9
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 22 Jan 2018 10:16:05 -0600
+
+linux (4.15.0-4.5) bionic; urgency=low
+
+  * [0cf3:e010] QCA6174A XR failed to pair with bt 4.0 device  (LP: #1741166)
+    - SAUCE: Bluetooth: btusb: Add support for 0cf3:e010
+
+  * External HDMI monitor failed to show screen on Lenovo X1 series
+    (LP: #1738523)
+    - SAUCE: drm/i915: Disable writing of TMDS_OE on Lenovo ThinkPad X1 series
+
+  * Miscellaneous Ubuntu changes
+    - [Debian] autoreconstruct - add resoration of execute permissions
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.15-rc4
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Wed, 10 Jan 2018 10:24:22 -0600
+
+linux (4.15.0-3.4) bionic; urgency=low
+
+  * ubuntu/xr-usb-serial didn't get built in zesty and artful (LP: #1733281)
+    - SAUCE: make sure ubuntu/xr-usb-serial builds for x86
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.15-rc6
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Wed, 03 Jan 2018 20:20:43 -0600
+
+linux (4.15.0-2.3) bionic; urgency=low
+
+  * nvidia-graphics-drivers-384 384.90-0ubuntu6 ADT test failure with linux
+    4.15.0-1.2 (LP: #1737752)
+    - x86/mm: Unbreak modules that use the DMA API
+
+  * Ubuntu 17.10 corrupting BIOS - many LENOVO laptops models (LP: #1734147)
+    - [Config] CONFIG_SPI_INTEL_SPI_*=n
+
+  * power: commonise configs IBMVETH/IBMVSCSI and ensure both are in linux-image
+    and udebs (LP: #1521712)
+    - [Config] Include ibmvnic in nic-modules
+
+  * Enable arm64 emulation of removed ARMv7 instructions (LP: #1545542)
+    - [Config] Enable support for emulation of deprecated ARMv8 instructions
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: (noup) Update spl with 4.15 compat fix (LP:#1737761)
+    - Enable zfs build
+    - [Debian] add icp to zfs-modules.ignore
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.15-rc4
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 18 Dec 2017 09:27:13 -0600
+
+linux (4.15.0-1.2) bionic; urgency=low
+
+  * Disabling zfs does not always disable module checks for the zfs modules
+    (LP: #1737176)
+    - [Packaging] disable zfs module checks when zfs is disabled
+
+  * Miscellaneous Ubuntu changes
+    - [Config] CONFIG_UNWINDER_FRAME_POINTER=y for amd64
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.15-rc3
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Sun, 10 Dec 2017 22:07:19 -0600
+
+linux (4.15.0-0.1) bionic; urgency=low
+
+  * Miscellaneous Ubuntu changes
+    - ubuntu: vbox -- update to 5.2.2-dfsg-2
+    - ubuntu: vbox: build fixes for 4.15
+    - disable hio build
+    - [Config] Update kernel lockdown options to fix build errors
+    - Disable zfs build
+    - SAUCE: Import aufs driver
+    - [Config] Enable AUFS config options
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.15-rc2
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Fri, 08 Dec 2017 13:55:42 -0600
+
+linux (4.14.0-11.13) bionic; urgency=low
+
+  * linux: 4.14.0-11.13 -proposed tracker (LP: #1736168)
+
+  * CVE-2017-1000405
+    - mm, thp: Do not make page table dirty unconditionally in touch_p[mu]d()
+
+  * linux 4.14.0-7.9 ADT test failure with linux 4.14.0-7.9 (LP: #1732463)
+    - SAUCE: mm: disable vma based swap readahead by default
+    - SAUCE: mm: fix memory hotplug in ZONE_HIGHMEM
+
+  * Bionic update to v4.14.3 stable release (LP: #1735843)
+    - s390: fix transactional execution control register handling
+    - s390/noexec: execute kexec datamover without DAT
+    - s390/runtime instrumention: fix possible memory corruption
+    - s390/guarded storage: fix possible memory corruption
+    - s390/disassembler: add missing end marker for e7 table
+    - s390/disassembler: increase show_code buffer size
+    - ACPI / PM: Fix acpi_pm_notifier_lock vs flush_workqueue() deadlock
+    - ACPI / EC: Fix regression related to triggering source of EC event handling
+    - cpufreq: schedutil: Reset cached_raw_freq when not in sync with next_freq
+    - serdev: fix registration of second slave
+    - sched: Make resched_cpu() unconditional
+    - lib/mpi: call cond_resched() from mpi_powm() loop
+    - x86/boot: Fix boot failure when SMP MP-table is based at 0
+    - x86/decoder: Add new TEST instruction pattern
+    - x86/entry/64: Fix entry_SYSCALL_64_after_hwframe() IRQ tracing
+    - x86/entry/64: Add missing irqflags tracing to native_load_gs_index()
+    - perf/x86/intel: Hide TSX events when RTM is not supported
+    - arm64: Implement arch-specific pte_access_permitted()
+    - ARM: 8722/1: mm: make STRICT_KERNEL_RWX effective for LPAE
+    - ARM: 8721/1: mm: dump: check hardware RO bit for LPAE
+    - uapi: fix linux/tls.h userspace compilation error
+    - uapi: fix linux/rxrpc.h userspace compilation errors
+    - MIPS: cmpxchg64() and HAVE_VIRT_CPU_ACCOUNTING_GEN don't work for 32-bit SMP
+    - MIPS: ralink: Fix MT7628 pinmux
+    - MIPS: ralink: Fix typo in mt7628 pinmux function
+    - net: mvneta: fix handling of the Tx descriptor counter
+    - nbd: wait uninterruptible for the dead timeout
+    - nbd: don't start req until after the dead connection logic
+    - PM / OPP: Add missing of_node_put(np)
+    - PCI/ASPM: Account for downstream device's Port Common_Mode_Restore_Time
+    - PCI/ASPM: Use correct capability pointer to program LTR_L1.2_THRESHOLD
+    - PCI: hv: Use effective affinity mask
+    - PCI: Set Cavium ACS capability quirk flags to assert RR/CR/SV/UF
+    - PCI: Apply Cavium ThunderX ACS quirk to more Root Ports
+    - ALSA: hda: Add Raven PCI ID
+    - dm integrity: allow unaligned bv_offset
+    - dm cache: fix race condition in the writeback mode overwrite_bio
+      optimisation
+    - dm crypt: allow unaligned bv_offset
+    - dm zoned: ignore last smaller runt zone
+    - dm mpath: remove annoying message of 'blk_get_request() returned -11'
+    - dm bufio: fix integer overflow when limiting maximum cache size
+    - ovl: Put upperdentry if ovl_check_origin() fails
+    - dm: allocate struct mapped_device with kvzalloc
+    - sched/rt: Simplify the IPI based RT balancing logic
+    - MIPS: pci: Remove KERN_WARN instance inside the mt7620 driver
+    - dm: fix race between dm_get_from_kobject() and __dm_destroy()
+    - dm: discard support requires all targets in a table support discards
+    - MIPS: Fix odd fp register warnings with MIPS64r2
+    - MIPS: Fix MIPS64 FP save/restore on 32-bit kernels
+    - MIPS: dts: remove bogus bcm96358nb4ser.dtb from dtb-y entry
+    - MIPS: Fix an n32 core file generation regset support regression
+    - MIPS: BCM47XX: Fix LED inversion for WRT54GSv1
+    - MIPS: math-emu: Fix final emulation phase for certain instructions
+    - rt2x00usb: mark device removed when get ENOENT usb error
+    - mm/z3fold.c: use kref to prevent page free/compact race
+    - autofs: don't fail mount for transient error
+    - nilfs2: fix race condition that causes file system corruption
+    - fscrypt: lock mutex before checking for bounce page pool
+    - eCryptfs: use after free in ecryptfs_release_messaging()
+    - libceph: don't WARN() if user tries to add invalid key
+    - bcache: check ca->alloc_thread initialized before wake up it
+    - fs: guard_bio_eod() needs to consider partitions
+    - fanotify: fix fsnotify_prepare_user_wait() failure
+    - isofs: fix timestamps beyond 2027
+    - btrfs: change how we decide to commit transactions during flushing
+    - f2fs: expose some sectors to user in inline data or dentry case
+    - NFS: Fix typo in nomigration mount option
+    - NFS: Revert "NFS: Move the flock open mode check into nfs_flock()"
+    - nfs: Fix ugly referral attributes
+    - NFS: Avoid RCU usage in tracepoints
+    - NFS: revalidate "." etc correctly on "open".
+    - nfsd: deal with revoked delegations appropriately
+    - rtlwifi: rtl8192ee: Fix memory leak when loading firmware
+    - rtlwifi: fix uninitialized rtlhal->last_suspend_sec time
+    - iwlwifi: fix firmware names for 9000 and A000 series hw
+    - md: fix deadlock error in recent patch.
+    - md: don't check MD_SB_CHANGE_CLEAN in md_allow_write
+    - Bluetooth: btqcomsmd: Add support for BD address setup
+    - md/bitmap: revert a patch
+    - fsnotify: clean up fsnotify_prepare/finish_user_wait()
+    - fsnotify: pin both inode and vfsmount mark
+    - fsnotify: fix pinning group in fsnotify_prepare_user_wait()
+    - ata: fixes kernel crash while tracing ata_eh_link_autopsy event
+    - ext4: fix interaction between i_size, fallocate, and delalloc after a crash
+    - ext4: prevent data corruption with inline data + DAX
+    - ext4: prevent data corruption with journaling + DAX
+    - ALSA: pcm: update tstamp only if audio_tstamp changed
+    - ALSA: usb-audio: Add sanity checks to FE parser
+    - ALSA: usb-audio: Fix potential out-of-bound access at parsing SU
+    - ALSA: usb-audio: Add sanity checks in v2 clock parsers
+    - ALSA: timer: Remove kernel warning at compat ioctl error paths
+    - ALSA: hda/realtek - Fix ALC275 no sound issue
+    - ALSA: hda: Fix too short HDMI/DP chmap reporting
+    - ALSA: hda - Fix yet remaining issue with vmaster 0dB initialization
+    - ALSA: hda/realtek - Fix ALC700 family no sound issue
+    - ASoC: sun8i-codec: Invert Master / Slave condition
+    - ASoC: sun8i-codec: Fix left and right channels inversion
+    - ASoC: sun8i-codec: Set the BCLK divider
+    - mfd: lpc_ich: Avoton/Rangeley uses SPI_BYT method
+    - fix a page leak in vhost_scsi_iov_to_sgl() error recovery
+    - 9p: Fix missing commas in mount options
+    - fs/9p: Compare qid.path in v9fs_test_inode
+    - net/9p: Switch to wait_event_killable()
+    - scsi: qla2xxx: Suppress a kernel complaint in qla_init_base_qpair()
+    - scsi: sd_zbc: Fix sd_zbc_read_zoned_characteristics()
+    - scsi: lpfc: fix pci hot plug crash in timer management routines
+    - scsi: lpfc: fix pci hot plug crash in list_add call
+    - scsi: lpfc: Fix crash receiving ELS while detaching driver
+    - scsi: lpfc: Fix FCP hba_wqidx assignment
+    - scsi: lpfc: Fix oops if nvmet_fc_register_targetport fails
+    - iscsi-target: Make TASK_REASSIGN use proper se_cmd->cmd_kref
+    - iscsi-target: Fix non-immediate TMR reference leak
+    - target: fix null pointer regression in core_tmr_drain_tmr_list
+    - target: fix buffer offset in core_scsi3_pri_read_full_status
+    - target: Fix QUEUE_FULL + SCSI task attribute handling
+    - target: Fix caw_sem leak in transport_generic_request_failure
+    - target: Fix quiese during transport_write_pending_qf endless loop
+    - target: Avoid early CMD_T_PRE_EXECUTE failures during ABORT_TASK
+    - mtd: Avoid probe failures when mtd->dbg.dfs_dir is invalid
+    - mtd: nand: Export nand_reset() symbol
+    - mtd: nand: atmel: Actually use the PM ops
+    - mtd: nand: omap2: Fix subpage write
+    - mtd: nand: Fix writing mtdoops to nand flash.
+    - mtd: nand: mtk: fix infinite ECC decode IRQ issue
+    - mailbox: bcm-flexrm-mailbox: Fix FlexRM ring flush sequence
+    - p54: don't unregister leds when they are not initialized
+    - block: Fix a race between blk_cleanup_queue() and timeout handling
+    - raid1: prevent freeze_array/wait_all_barriers deadlock
+    - genirq: Track whether the trigger type has been set
+    - irqchip/gic-v3: Fix ppi-partitions lookup
+    - lockd: double unregister of inetaddr notifiers
+    - KVM: PPC: Book3S HV: Don't call real-mode XICS hypercall handlers if not
+      enabled
+    - KVM: nVMX: set IDTR and GDTR limits when loading L1 host state
+    - KVM: SVM: obey guest PAT
+    - kvm: vmx: Reinstate support for CPUs without virtual NMI
+    - dax: fix PMD faults on zero-length files
+    - dax: fix general protection fault in dax_alloc_inode
+    - SUNRPC: Fix tracepoint storage issues with svc_recv and svc_rqst_status
+    - clk: ti: dra7-atl-clock: fix child-node lookups
+    - libnvdimm, dimm: clear 'locked' status on successful DIMM enable
+    - libnvdimm, pfn: make 'resource' attribute only readable by root
+    - libnvdimm, namespace: fix label initialization to use valid seq numbers
+    - libnvdimm, region : make 'resource' attribute only readable by root
+    - libnvdimm, namespace: make 'resource' attribute only readable by root
+    - svcrdma: Preserve CB send buffer across retransmits
+    - IB/srpt: Do not accept invalid initiator port names
+    - IB/cm: Fix memory corruption in handling CM request
+    - IB/hfi1: Fix incorrect available receive user context count
+    - IB/srp: Avoid that a cable pull can trigger a kernel crash
+    - IB/core: Avoid crash on pkey enforcement failed in received MADs
+    - IB/core: Only maintain real QPs in the security lists
+    - NFC: fix device-allocation error return
+    - spi-nor: intel-spi: Fix broken software sequencing codes
+    - i40e: Use smp_rmb rather than read_barrier_depends
+    - igb: Use smp_rmb rather than read_barrier_depends
+    - igbvf: Use smp_rmb rather than read_barrier_depends
+    - ixgbevf: Use smp_rmb rather than read_barrier_depends
+    - i40evf: Use smp_rmb rather than read_barrier_depends
+    - fm10k: Use smp_rmb rather than read_barrier_depends
+    - ixgbe: Fix skb list corruption on Power systems
+    - parisc: Fix validity check of pointer size argument in new CAS
+      implementation
+    - powerpc: Fix boot on BOOK3S_32 with CONFIG_STRICT_KERNEL_RWX
+    - powerpc/mm/radix: Fix crashes on Power9 DD1 with radix MMU and STRICT_RWX
+    - powerpc/perf/imc: Use cpu_to_node() not topology_physical_package_id()
+    - powerpc/signal: Properly handle return value from uprobe_deny_signal()
+    - powerpc/64s: Fix masking of SRR1 bits on instruction fault
+    - powerpc/64s/radix: Fix 128TB-512TB virtual address boundary case allocation
+    - powerpc/64s/hash: Fix 512T hint detection to use >= 128T
+    - powerpc/64s/hash: Fix 128TB-512TB virtual address boundary case allocation
+    - powerpc/64s/hash: Fix fork() with 512TB process address space
+    - powerpc/64s/hash: Allow MAP_FIXED allocations to cross 128TB boundary
+    - media: Don't do DMA on stack for firmware upload in the AS102 driver
+    - media: rc: check for integer overflow
+    - media: rc: nec decoder should not send both repeat and keycode
+    - cx231xx-cards: fix NULL-deref on missing association descriptor
+    - media: v4l2-ctrl: Fix flags field on Control events
+    - media: venus: fix wrong size on dma_free
+    - media: venus: venc: fix bytesused v4l2_plane field
+    - media: venus: reimplement decoder stop command
+    - ARM64: dts: meson-gxl: Add alternate ARM Trusted Firmware reserved memory
+      zone
+    - iwlwifi: fix wrong struct for a000 device
+    - iwlwifi: add a new a000 device
+    - iwlwifi: pcie: sort IDs for the 9000 series for easier comparisons
+    - iwlwifi: add new cards for a000 series
+    - iwlwifi: add new cards for 8265 series
+    - iwlwifi: add new cards for 8260 series
+    - iwlwifi: fix PCI IDs and configuration mapping for 9000 series
+    - iwlwifi: mvm: support version 7 of the SCAN_REQ_UMAC FW command
+    - e1000e: Fix error path in link detection
+    - e1000e: Fix return value test
+    - e1000e: Separate signaling for link check/link up
+    - e1000e: Avoid receiver overrun interrupt bursts
+    - e1000e: fix buffer overrun while the I219 is processing DMA transactions
+    - Linux 4.14.3
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: s390/topology: don't inline cpu_to_node
+    - SAUCE: (noup) Update spl to 0.7.3-1ubuntu1, zfs to 0.7.3-1ubuntu1
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 04 Dec 2017 09:08:07 -0600
+
+linux (4.14.0-10.12) bionic; urgency=low
+
+  * linux: 4.14.0-10.12 -proposed tracker (LP: #1734901)
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: Enable the ACPI kernel debugger and acpidbg tool
+    - [Packaging] Include arch/arm64/kernel/ftrace-mod.o in headers package
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Tue, 28 Nov 2017 08:46:49 -0600
+
+linux (4.14.0-9.11) bionic; urgency=low
+
+  * linux: 4.14.0-9.11 -proposed tracker (LP: #1734728)
+
+  * Miscellaneous Ubuntu changes
+    - Revert "UBUNTU: SAUCE: (noup) Update spl to 0.7.3-1ubuntu1, zfs to
+      0.7.3-1ubuntu1"
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 27 Nov 2017 12:44:48 -0600
+
+linux (4.14.0-8.10) bionic; urgency=low
+
+  * linux: 4.14.0-8.10 -proposed tracker (LP: #1734695)
+
+  * Bionic update to v4.14.2 stable release (LP: #1734694)
+    - bio: ensure __bio_clone_fast copies bi_partno
+    - af_netlink: ensure that NLMSG_DONE never fails in dumps
+    - vxlan: fix the issue that neigh proxy blocks all icmpv6 packets
+    - net: cdc_ncm: GetNtbFormat endian fix
+    - fealnx: Fix building error on MIPS
+    - net/sctp: Always set scope_id in sctp_inet6_skb_msgname
+    - ima: do not update security.ima if appraisal status is not INTEGRITY_PASS
+    - serial: omap: Fix EFR write on RTS deassertion
+    - serial: 8250_fintek: Fix finding base_port with activated SuperIO
+    - tpm-dev-common: Reject too short writes
+    - rcu: Fix up pending cbs check in rcu_prepare_for_idle
+    - mm/pagewalk.c: report holes in hugetlb ranges
+    - ocfs2: fix cluster hang after a node dies
+    - ocfs2: should wait dio before inode lock in ocfs2_setattr()
+    - ipmi: fix unsigned long underflow
+    - mm/page_alloc.c: broken deferred calculation
+    - mm/page_ext.c: check if page_ext is not prepared
+    - coda: fix 'kernel memory exposure attempt' in fsync
+    - ipmi: Prefer ACPI system interfaces over SMBIOS ones
+    - Linux 4.14.2
+
+  * Bionic update to v4.14.1 stable release (LP: #1734693)
+    - EDAC, sb_edac: Don't create a second memory controller if HA1 is not present
+    - dmaengine: dmatest: warn user when dma test times out
+    - media: imon: Fix null-ptr-deref in imon_probe
+    - media: dib0700: fix invalid dvb_detach argument
+    - crypto: dh - Fix double free of ctx->p
+    - crypto: dh - Don't permit 'p' to be 0
+    - crypto: dh - Don't permit 'key' or 'g' size longer than 'p'
+    - crypto: brcm - Explicity ACK mailbox message
+    - USB: early: Use new USB product ID and strings for DbC device
+    - USB: usbfs: compute urb->actual_length for isochronous
+    - USB: Add delay-init quirk for Corsair K70 LUX keyboards
+    - usb: gadget: f_fs: Fix use-after-free in ffs_free_inst
+    - USB: serial: metro-usb: stop I/O after failed open
+    - USB: serial: Change DbC debug device binding ID
+    - USB: serial: qcserial: add pid/vid for Sierra Wireless EM7355 fw update
+    - USB: serial: garmin_gps: fix I/O after failed probe and remove
+    - USB: serial: garmin_gps: fix memory leak on probe errors
+    - selftests/x86/protection_keys: Fix syscall NR redefinition warnings
+    - x86/MCE/AMD: Always give panic severity for UC errors in kernel context
+    - platform/x86: peaq-wmi: Add DMI check before binding to the WMI interface
+    - platform/x86: peaq_wmi: Fix missing terminating entry for peaq_dmi_table
+    - HID: cp2112: add HIDRAW dependency
+    - HID: wacom: generic: Recognize WACOM_HID_WD_PEN as a type of pen collection
+    - rpmsg: glink: Add missing MODULE_LICENSE
+    - staging: wilc1000: Fix bssid buffer offset in Txq
+    - staging: sm750fb: Fix parameter mistake in poke32
+    - staging: ccree: fix 64 bit scatter/gather DMA ops
+    - staging: greybus: spilib: fix use-after-free after deregistration
+    - staging: rtl8188eu: Revert 4 commits breaking ARP
+    - spi: fix use-after-free at controller deregistration
+    - sparc32: Add cmpxchg64().
+    - sparc64: mmu_context: Add missing include files
+    - sparc64: Fix page table walk for PUD hugepages
+    - Linux 4.14.1
+
+  * Set PANIC_TIMEOUT=10 on Power Systems (LP: #1730660)
+    - [Config]: Set PANIC_TIMEOUT=10 on ppc64el
+
+  * enable CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH easily confuse users
+    (LP: #1732627)
+    - [Config] CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH=n
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: (noup) Update spl to 0.7.3-1ubuntu1, zfs to 0.7.3-1ubuntu1
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 27 Nov 2017 07:43:44 -0600
+
+linux (4.14.0-7.9) bionic; urgency=low
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: apparmor: add base infastructure for socket mediation
+    - SAUCE: apparmor: af_unix mediation
+    - SAUCE: LSM stacking: procfs: add smack subdir to attrs
+    - SAUCE: LSM stacking: LSM: manage credential security blobs
+    - SAUCE: LSM stacking: LSM: Manage file security blobs
+    - SAUCE: LSM stacking: LSM: manage task security blobs
+    - SAUCE: LSM stacking: LSM: Infrastructure management of the remaining blobs
+    - SAUCE: LSM stacking: LSM: general but not extreme module stacking
+    - SAUCE: LSM stacking: LSM: Complete task_alloc hook
+    - SAUCE: LSM stacking: fixup procsfs: add smack subdir to attrs
+    - SAUCE: LSM stacking: fixup initialize task->security
+    - SAUCE: LSM stacking: fixup: alloc_task_ctx is dead code
+    - SAUCE: LSM stacking: add support for stacking getpeersec_stream
+    - SAUCE: LSM stacking: add stacking support to apparmor network hooks
+    - SAUCE: LSM stacking: fixup apparmor stacking enablement
+    - SAUCE: LSM stacking: fixup stacking kconfig
+    - SAUCE: LSM stacking: allow selecting multiple LSMs using kernel boot params
+    - SAUCE: LSM stacking: provide prctl interface for setting context
+    - SAUCE: LSM stacking: inherit current display LSM
+    - SAUCE: LSM stacking: keep an index for each registered LSM
+    - SAUCE: LSM stacking: verify display LSM
+    - SAUCE: LSM stacking: provide a way to specify the default display lsm
+    - SAUCE: LSM stacking: make sure LSM blob align on 64 bit boundaries
+    - SAUCE: LSM stacking: add /proc/<pid>/attr/display_lsm
+    - SAUCE: LSM stacking: add Kconfig to set default display LSM
+    - SAUCE: LSM stacking: add configs for LSM stacking
+    - SAUCE: LSM stacking: check for invalid zero sized writes
+    - [Config] Run updateconfigs after merging LSM stacking
+    - [Config] CONFIG_AMD_MEM_ENCRYPT=y
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.14
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 13 Nov 2017 08:12:08 -0600
+
+linux (4.14.0-6.8) bionic; urgency=low
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: add workarounds to enable ZFS for 4.14
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.14-rc8
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 06 Nov 2017 11:39:00 -0600
+
+linux (4.14.0-5.7) bionic; urgency=low
+
+  * Miscellaneous Ubuntu changes
+    - [Debian] Fix invocation of dh_prep for dbgsym packages
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Tue, 31 Oct 2017 07:07:23 -0500
+
+linux (4.14.0-4.5) bionic; urgency=low
+
+  * Miscellaneous Ubuntu changes
+    - [Packaging] virtualbox -- reduce in kernel module versions
+    - vbox-update: Fix up KERN_DIR definitions
+    - ubuntu: vbox -- update to 5.2.0-dfsg-2
+    - [Config] CONFIG_AMD_MEM_ENCRYPT=n
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.14-rc7
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 30 Oct 2017 13:29:20 -0500
+
+linux (4.14.0-3.4) artful; urgency=low
+
+  * Touchpad and TrackPoint Dose Not Work on Lenovo X1C6 and X280 (LP: #1723986)
+    - SAUCE: Input: synaptics-rmi4 - RMI4 can also use SMBUS version 3
+    - SAUCE: Input: synaptics - Lenovo X1 Carbon 5 should use SMBUS/RMI
+    - SAUCE: Input: synaptics - add Intertouch support on X1 Carbon 6th and X280
+
+  * powerpc/64s: Add workaround for P9 vector CI load issuenext (LP: #1721070)
+    - powerpc/64s: Add workaround for P9 vector CI load issue
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: staging: vboxvideo: Fix reporting invalid suggested-offset-properties
+    - [Config] CONFIG_DRM_VBOXVIDEO=m
+    - SAUCE: Import aufs driver
+    - [Config] Enable aufs
+    - [Config] Reorder annotations file after enabling aufs
+    - vbox-update: Disable imported vboxvideo module
+    - ubuntu: vbox -- update to 5.1.30-dfsg-1
+    - Enable vbox
+    - hio: Use correct sizes when initializing ssd_index_bits* arrays
+    - hio: Update io stat accounting for 4.14
+    - Enable hio
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.14-rc5
+  * Rebase to v4.14-rc6
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 23 Oct 2017 13:53:52 -0500
+
+linux (4.14.0-2.3) artful; urgency=low
+
+  * [Bug] USB controller failed to respond on Denverton after loading
+    intel_th_pci module (LP: #1715833)
+    - SAUCE: PCI: Disable broken RTIT_BAR of Intel TH
+
+  * CONFIG_DEBUG_FS is not enabled by "make zfcpdump_defconfig" with Ubuntu
+    17.10 (kernel 4.13) (LP: #1719290)
+    - SAUCE: s390: update zfcpdump_defconfig
+
+  * Add installer support for Broadcom BCM573xx network drivers. (LP: #1720466)
+    - d-i: Add bnxt_en to nic-modules.
+
+  * Miscellaneous Ubuntu changes
+    - [Config] Update annotations for 4.14-rc2
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.14-rc3
+  * Rebase to v4.14-rc4
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Wed, 11 Oct 2017 16:04:27 -0500
+
+linux (4.14.0-1.2) artful; urgency=low
+
+  * [Bug] USB 3.1 Gen2 works as 5Gbps (LP: #1720045)
+    - xhci: set missing SuperSpeedPlus Link Protocol bit in roothub descriptor
+
+  * Please make linux-libc-dev Provide: aufs-dev (LP: #1716091)
+    - [Packaging] Add aufs-dev to the Provides: for linux-libc-dev
+
+  * Upgrade to 4.13.0-11.12 in artful amd64 VM breaks display on wayland
+    (LP: #1718679)
+    - [Config] CONFIG_DRM_VBOXVIDEO=n
+
+  * ipmmu-vmsa driver breaks arm64 boots (LP: #1718734)
+    - [Config] Disable CONFIG_IPMMU_VMSA on arm64
+
+  * autopkgtest profile fails to build on armhf (LP: #1717920)
+    - [Packaging] autopkgtest -- disable d-i when dropping flavours
+
+  * Miscellaneous Ubuntu changes
+    - [Config] CONFIG_I2C_XLP9XX=m
+    - [Packaging] Use SRCPKGNAME rather than hard-coding the source package name
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.14-rc2
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Fri, 29 Sep 2017 09:09:11 -0400
+
+linux (4.14.0-0.1) artful; urgency=low
+
+  * Miscellaneous Ubuntu changes
+    - Disable vbox build
+    - Disable hio build
+    - Disable zfs build
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.14-rc1
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Tue, 19 Sep 2017 20:22:29 -0500
+
+linux (4.13.0-11.12) artful; urgency=low
+
+  * linux: 4.13.0-11.12 -proposed tracker (LP: #1716699)
+
+  * kernel panic -not syncing: Fatal exception: panic_on_oops (LP: #1708399)
+    - s390/mm: fix local TLB flushing vs. detach of an mm address space
+    - s390/mm: fix race on mm->context.flush_mm
+
+  * CVE-2017-1000251
+    - Bluetooth: Properly check L2CAP config option output buffer length
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Tue, 12 Sep 2017 10:18:38 -0500
+
+linux (4.13.0-10.11) artful; urgency=low
+
+  * linux: 4.13.0-10.11 -proposed tracker (LP: #1716287)
+
+  * please add aufs-dkms to the Provides: for the kernel packages (LP: #1716093)
+    - [Packaging] Add aufs-dkms to the Provides: for kernel packages
+
+  * Artful update to v4.13.1 stable release (LP: #1716284)
+    - usb: quirks: add delay init quirk for Corsair Strafe RGB keyboard
+    - USB: serial: option: add support for D-Link DWM-157 C1
+    - usb: Add device quirk for Logitech HD Pro Webcam C920-C
+    - usb:xhci:Fix regression when ATI chipsets detected
+    - USB: musb: fix external abort on suspend
+    - ANDROID: binder: add padding to binder_fd_array_object.
+    - ANDROID: binder: add hwbinder,vndbinder to BINDER_DEVICES.
+    - USB: core: Avoid race of async_completed() w/ usbdev_release()
+    - staging/rts5208: fix incorrect shift to extract upper nybble
+    - staging: ccree: save ciphertext for CTS IV
+    - staging: fsl-dpaa2/eth: fix off-by-one FD ctrl bitmaks
+    - iio: adc: ti-ads1015: fix incorrect data rate setting update
+    - iio: adc: ti-ads1015: fix scale information for ADS1115
+    - iio: adc: ti-ads1015: enable conversion when CONFIG_PM is not set
+    - iio: adc: ti-ads1015: avoid getting stale result after runtime resume
+    - iio: adc: ti-ads1015: don't return invalid value from buffer setup callbacks
+    - iio: adc: ti-ads1015: add adequate wait time to get correct conversion
+    - driver core: bus: Fix a potential double free
+    - HID: wacom: Do not completely map WACOM_HID_WD_TOUCHRINGSTATUS usage
+    - binder: free memory on error
+    - crypto: caam/qi - fix compilation with CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y
+    - crypto: caam/qi - fix compilation with DEBUG enabled
+    - thunderbolt: Fix reset response_type
+    - fpga: altera-hps2fpga: fix multiple init of l3_remap_lock
+    - intel_th: pci: Add Cannon Lake PCH-H support
+    - intel_th: pci: Add Cannon Lake PCH-LP support
+    - ath10k: fix memory leak in rx ring buffer allocation
+    - drm/vgem: Pin our pages for dmabuf exports
+    - drm/ttm: Fix accounting error when fail to get pages for pool
+    - drm/dp/mst: Handle errors from drm_atomic_get_private_obj_state() correctly
+    - rtlwifi: rtl_pci_probe: Fix fail path of _rtl_pci_find_adapter
+    - Bluetooth: Add support of 13d3:3494 RTL8723BE device
+    - iwlwifi: pci: add new PCI ID for 7265D
+    - dlm: avoid double-free on error path in dlm_device_{register,unregister}
+    - mwifiex: correct channel stat buffer overflows
+    - MCB: add support for SC31 to mcb-lpc
+    - s390/mm: avoid empty zero pages for KVM guests to avoid postcopy hangs
+    - drm/nouveau/pci/msi: disable MSI on big-endian platforms by default
+    - drm/nouveau: Fix error handling in nv50_disp_atomic_commit
+    - workqueue: Fix flag collision
+    - ahci: don't use MSI for devices with the silly Intel NVMe remapping scheme
+    - cs5536: add support for IDE controller variant
+    - scsi: sg: protect against races between mmap() and SG_SET_RESERVED_SIZE
+    - scsi: sg: recheck MMAP_IO request length with lock held
+    - of/device: Prevent buffer overflow in of_device_modalias()
+    - rtlwifi: Fix memory leak when firmware request fails
+    - rtlwifi: Fix fallback firmware loading
+    - Linux 4.13.1
+
+  * Kernel has trouble recognizing Corsair Strafe RGB keyboard (LP: #1678477)
+    - usb: quirks: add delay init quirk for Corsair Strafe RGB keyboard
+
+  * SRIOV: warning if unload VFs (LP: #1715073)
+    - PCI: Disable VF decoding before pcibios_sriov_disable() updates resources
+
+  * [Patch] network-i40e:NVM bug fixes (cherrypick from 4.14) (LP: #1715578)
+    - i40e: avoid NVM acquire deadlock during NVM update
+    - i40e: point wb_desc at the nvm_wb_desc during i40e_read_nvm_aq
+
+  * [P9,POwer NV] Perf PMU event : pm_br_2path and pm_ld_miss_l1 is counted
+    twice when perf stat is done (perf:) (LP: #1714571)
+    - perf vendor events powerpc: Remove duplicate events
+
+  * Unable to install Ubuntu on the NVMe disk under VMD PCI domain
+    (LP: #1703339)
+    - [Config] Include vmd in storage-core-modules udeb
+
+  * 17.10 fails to boot on POWER9 DD2.0 with Deep stop states (LP: #1715064)
+    - powerpc/powernv: Save/Restore additional SPRs for stop4 cpuidle
+    - powerpc/powernv: Clear PECE1 in LPCR via stop-api only on Hotplug
+    - SAUCE: powerpc/powernv: Clear LPCR[PECE1] via stop-api only for deep state
+      offline
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: selftests/seccomp: Support glibc 2.26 siginfo_t.h
+    - Revert "UBUNTU: SAUCE: Import aufs driver"
+    - SAUCE: Import aufs driver
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Sun, 10 Sep 2017 17:48:59 -0500
+
+linux (4.13.0-9.10) artful; urgency=low
+
+  * linux: 4.13.0-9.10 -proposed tracker (LP: #1715145)
+
+  * EDAC sbridge: Failed to register device with error -22. (LP: #1714112)
+    - [Config] CONFIG_EDAC_GHES=n
+
+  * Miscellaneous Ubuntu changes
+    - ubuntu: vbox -- update to 5.1.26-dfsg-2
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.13
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Tue, 05 Sep 2017 07:51:19 -0500
+
+linux (4.13.0-8.9) artful; urgency=low
+
+  * snapd 2.27.3+17.10 ADT test failure with linux 4.13.0-6.7 (LP: #1713103)
+    - SAUCE: apparmor: fix apparmorfs DAC access, permissions
+
+  * enable ARCH_SUNXI (and friends) in arm64 kernel .config (LP: #1701137)
+    - [Config] Enable CONFIG_ARCH_SUNXI and related options for arm64
+
+  * [Bug] Harrisonville: pnd2_edac always fail to load on B1 stepping
+    Harrisonville SDP (LP: #1709257)
+    - EDAC, pnd2: Build in a minimal sideband driver for Apollo Lake
+    - EDAC, pnd2: Mask off the lower four bits of a BAR
+    - EDAC, pnd2: Conditionally unhide/hide the P2SB PCI device to read BAR
+    - EDAC, pnd2: Properly toggle hidden state for P2SB PCI device
+    - SAUCE: i2c: i801: Restore the presence state of P2SB PCI device after
+      reading BAR
+
+  * Miscellaneous Ubuntu changes
+    - Revert "UBUNTU: SAUCE: Import aufs driver"
+    - SAUCE: Import aufs driver
+    - SAUCE: selftests/powerpc: Disable some ptrace selftests
+    - [Config] CONFIG_CRYPTO_DEV_NITROX_CNN55XX=n for s390x
+    - [Config] CONFIG_I2C_SLAVE=n for amd64, i386, ppc64el
+    - [Config] Disable CONFIG_MDIO_* options for s390x
+    - [Config] CONFIG_SCSI_MQ_DEFAULT=n for s390x
+    - [Config] Update annotations for 4.13
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Thu, 31 Aug 2017 14:27:09 -0500
+
+linux (4.13.0-7.8) artful; urgency=low
+
+  * linux 4.12.0-11.12 ADT test failure with linux 4.12.0-11.12 (LP: #1710904)
+    - SAUCE: selftests/powerpc: Use snprintf to construct DSCR sysfs interface
+      paths
+
+  * Miscellaneous Ubuntu changes
+    - Revert "UBUNTU: SAUCE: seccomp: log actions even when audit is disabled"
+
+  * Miscellaneous upstream changes
+    - seccomp: Provide matching filter for introspection
+    - seccomp: Sysctl to display available actions
+    - seccomp: Operation for checking if an action is available
+    - seccomp: Sysctl to configure actions that are allowed to be logged
+    - seccomp: Selftest for detection of filter flag support
+    - seccomp: Filter flag to log all actions except SECCOMP_RET_ALLOW
+    - seccomp: Action to log before allowing
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.13-rc7
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 28 Aug 2017 08:12:24 -0500
+
+linux (4.13.0-6.7) artful; urgency=low
+
+  * HID: multitouch: Support ALPS PTP Stick and Touchpad devices (LP: #1712481)
+    - SAUCE: HID: multitouch: Support ALPS PTP stick with pid 0x120A
+
+  * sort ABI files with C.UTF-8 locale (LP: #1712345)
+    - [Packaging] sort ABI files with C.UTF-8 locale
+
+  * igb: Support using Broadcom 54616 as PHY (LP: #1712024)
+    - SAUCE: igb: add support for using Broadcom 54616 as PHY
+
+  * RPT related fixes missing in Ubuntu 16.04.3 (LP: #1709220)
+    - powerpc/mm/radix: Improve _tlbiel_pid to be usable for PWC flushes
+    - powerpc/mm/radix: Improve TLB/PWC flushes
+    - powerpc/mm/radix: Avoid flushing the PWC on every flush_tlb_range
+
+  * Linux 4.12 refuses to load self-signed modules under Secure Boot with
+    properly enrolled keys (LP: #1712168)
+    - SAUCE: (efi-lockdown) MODSIGN: Fix module signature verification
+
+  * [17.10 FEAT] Enable NVMe driver - kernel (LP: #1708432)
+    - [Config] CONFIG_BLK_DEV_NVME=m for s390
+
+  * Artful: 4.12.0-11.12: Boot panic in vlv2_plat_configure_clock+0x3b/0xa0
+    (LP: #1711298)
+    - [Config] CONFIG_INTEL_ATOMISP=n
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: apparmor: af_unix mediation
+
+  * Miscellaneous upstream changes
+    - apparmor: Fix shadowed local variable in unpack_trans_table()
+    - apparmor: Fix logical error in verify_header()
+    - apparmor: Fix an error code in aafs_create()
+    - apparmor: Redundant condition: prev_ns. in [label.c:1498]
+    - apparmor: add the ability to mediate signals
+    - apparmor: add mount mediation
+    - apparmor: cleanup conditional check for label in label_print
+    - apparmor: add support for absolute root view based labels
+    - apparmor: make policy_unpack able to audit different info messages
+    - apparmor: add more debug asserts to apparmorfs
+    - apparmor: add base infastructure for socket mediation
+    - apparmor: move new_null_profile to after profile lookup fns()
+    - apparmor: fix race condition in null profile creation
+    - apparmor: ensure unconfined profiles have dfas initialized
+    - apparmor: fix incorrect type assignment when freeing proxies
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.13-rc6
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Wed, 23 Aug 2017 08:10:38 -0500
+
+linux (4.13.0-5.6) artful; urgency=low
+
+  * Ubuntu17.10 - perf: Update Power9 PMU event JSON files (LP: #1708630)
+    - perf pmu-events: Support additional POWER8+ PVR in mapfile
+    - perf vendor events: Add POWER9 PMU events
+    - perf vendor events: Add POWER9 PVRs to mapfile
+    - SAUCE: perf vendor events powerpc: remove suffix in mapfile
+    - SAUCE: perf vendor events powerpc: Update POWER9 events
+
+  * Disable CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE (LP: #1709171)
+    - [Config] CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE=n for ppc64el
+
+  * Please only recommend or suggest initramfs-tools | linux-initramfs-tool for
+    kernels able to boot without initramfs (LP: #1700972)
+    - [Debian] Don't depend on initramfs-tools
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: Import aufs driver
+    - SAUCE: aufs -- Add missing argument to loop_switch() call
+    - [Config] Enable aufs
+    - SAUCE: (noup) Update spl to 0.6.5.11-ubuntu1, zfs to 0.6.5.11-1ubuntu3
+    - Enable zfs build
+    - SAUCE: powerpc: Always initialize input array when calling epapr_hypercall()
+    - [Packaging] switch up to debhelper 9
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.13-rc5
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Tue, 15 Aug 2017 09:24:16 -0500
+
+linux (4.13.0-4.5) artful; urgency=low
+
+  * Lenovo Yoga 910 Sensors (LP: #1708120)
+    - SAUCE: (no-up) HID: Add quirk for Lenovo Yoga 910 with ITE Chips
+
+  * Unable to install Ubuntu on the NVMe disk under VMD PCI domain
+    (LP: #1703339)
+    - [Config] Add vmd driver to generic inclusion list
+
+  * Set CONFIG_SATA_HIGHBANK=y on armhf (LP: #1703430)
+    - [Config] CONFIG_SATA_HIGHBANK=y
+
+  * Miscellaneous Ubuntu changes
+    - ubuntu: vbox -- update to 5.1.26-dfsg-1
+    - SAUCE: hio: Build fixes for 4.13
+    - Enable hio build
+    - SAUCE: (noup) Update spl to 0.6.5.11-1, zfs to 0.6.5.11-1ubuntu1
+    - [debian] use all rather than amd64 dkms debs for sync
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.13-rc4
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Tue, 08 Aug 2017 11:31:48 -0500
+
+linux (4.13.0-3.4) artful; urgency=low
+
+  * Adt tests of src:linux time out often on armhf lxc containers (LP: #1705495)
+    - [Packaging] tests -- reduce rebuild test to one flavour
+    - [Packaging] tests -- reduce rebuild test to one flavour -- use filter
+
+  * snapd 2.26.8+17.10 ADT test failure with linux 4.12.0-6.7 (LP: #1704158)
+    - SAUCE: virtio_net: Revert mergeable buffer handling rework
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.13-rc3
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 31 Jul 2017 10:08:16 -0500
+
+linux (4.13.0-2.3) artful; urgency=low
+
+  * Change CONFIG_IBMVETH to module (LP: #1704479)
+    - [Config] CONFIG_IBMVETH=m
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.13-rc2
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 24 Jul 2017 13:58:08 -0500
+
+linux (4.13.0-1.2) artful; urgency=low
+
+  * Miscellaneous Ubuntu changes
+    - [Debian] Support sphinx-based kernel documentation
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Thu, 20 Jul 2017 09:18:33 -0500
+
+linux (4.13.0-0.1) artful; urgency=low
+
+  * Miscellaneous Ubuntu changes
+    - Disable hio
+    - Disable zfs build
+    - ubuntu: vbox -- update to 5.1.24-dfsg-1
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.13-rc1
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Wed, 19 Jul 2017 15:09:31 -0500
+
+linux (4.12.0-7.8) artful; urgency=low
+
+  * ThunderX: soft lockup on 4.8+ kernels when running qemu-efi with vhost=on
+    (LP: #1673564)
+    - arm64: Add a facility to turn an ESR syndrome into a sysreg encoding
+    - KVM: arm/arm64: vgic-v3: Add accessors for the ICH_APxRn_EL2 registers
+    - KVM: arm64: Make kvm_condition_valid32() accessible from EL2
+    - KVM: arm64: vgic-v3: Add hook to handle guest GICv3 sysreg accesses at EL2
+    - KVM: arm64: vgic-v3: Add ICV_BPR1_EL1 handler
+    - KVM: arm64: vgic-v3: Add ICV_IGRPEN1_EL1 handler
+    - KVM: arm64: vgic-v3: Add ICV_IAR1_EL1 handler
+    - KVM: arm64: vgic-v3: Add ICV_EOIR1_EL1 handler
+    - KVM: arm64: vgic-v3: Add ICV_AP1Rn_EL1 handler
+    - KVM: arm64: vgic-v3: Add ICV_HPPIR1_EL1 handler
+    - KVM: arm64: vgic-v3: Enable trapping of Group-1 system registers
+    - KVM: arm64: Enable GICv3 Group-1 sysreg trapping via command-line
+    - KVM: arm64: vgic-v3: Add ICV_BPR0_EL1 handler
+    - KVM: arm64: vgic-v3: Add ICV_IGNREN0_EL1 handler
+    - KVM: arm64: vgic-v3: Add misc Group-0 handlers
+    - KVM: arm64: vgic-v3: Enable trapping of Group-0 system registers
+    - KVM: arm64: Enable GICv3 Group-0 sysreg trapping via command-line
+    - arm64: Add MIDR values for Cavium cn83XX SoCs
+    - arm64: Add workaround for Cavium Thunder erratum 30115
+    - KVM: arm64: vgic-v3: Add ICV_DIR_EL1 handler
+    - KVM: arm64: vgic-v3: Add ICV_RPR_EL1 handler
+    - KVM: arm64: vgic-v3: Add ICV_CTLR_EL1 handler
+    - KVM: arm64: vgic-v3: Add ICV_PMR_EL1 handler
+    - KVM: arm64: Enable GICv3 common sysreg trapping via command-line
+    - KVM: arm64: vgic-v3: Log which GICv3 system registers are trapped
+    - KVM: arm64: Log an error if trapping a read-from-write-only GICv3 access
+    - KVM: arm64: Log an error if trapping a write-to-read-only GICv3 access
+
+  * hns: under heavy load, NIC may fail and require reboot (LP: #1704146)
+    - net: hns: Bugfix for Tx timeout handling in hns driver
+
+  * New ACPI identifiers for ThunderX SMMU (LP: #1703437)
+    - iommu/arm-smmu: Plumb in new ACPI identifiers
+
+  * Transparent hugepages should default to enabled=madvise (LP: #1703742)
+    - SAUCE: use CONFIG_TRANSPARENT_HUGEPAGE_MADVISE=y as default
+
+  * Artful update to v4.12.1 stable release (LP: #1703858)
+    - driver core: platform: fix race condition with driver_override
+    - RDMA/uverbs: Check port number supplied by user verbs cmds
+    - usb: dwc3: replace %p with %pK
+    - USB: serial: cp210x: add ID for CEL EM3588 USB ZigBee stick
+    - usb: usbip: set buffer pointers to NULL after free
+    - Add USB quirk for HVR-950q to avoid intermittent device resets
+    - usb: Fix typo in the definition of Endpoint[out]Request
+    - USB: core: fix device node leak
+    - USB: serial: option: add two Longcheer device ids
+    - USB: serial: qcserial: new Sierra Wireless EM7305 device ID
+    - xhci: Limit USB2 port wake support for AMD Promontory hosts
+    - gfs2: Fix glock rhashtable rcu bug
+    - Add "shutdown" to "struct class".
+    - tpm: Issue a TPM2_Shutdown for TPM2 devices.
+    - tpm: fix a kernel memory leak in tpm-sysfs.c
+    - powerpc/powernv: Fix CPU_HOTPLUG=n idle.c compile error
+    - x86/uaccess: Optimize copy_user_enhanced_fast_string() for short strings
+    - sched/fair, cpumask: Export for_each_cpu_wrap()
+    - sched/core: Implement new approach to scale select_idle_cpu()
+    - sched/numa: Use down_read_trylock() for the mmap_sem
+    - sched/numa: Override part of migrate_degrades_locality() when idle balancing
+    - sched/fair: Simplify wake_affine() for the single socket case
+    - sched/numa: Implement NUMA node level wake_affine()
+    - sched/fair: Remove effective_load()
+    - sched/numa: Hide numa_wake_affine() from UP build
+    - xen: avoid deadlock in xenbus driver
+    - crypto: drbg - Fixes panic in wait_for_completion call
+    - Linux 4.12.1
+
+  * cxlflash update request in the Xenial SRU stream (LP: #1702521)
+    - scsi: cxlflash: Combine the send queue locks
+    - scsi: cxlflash: Update cxlflash_afu_sync() to return errno
+    - scsi: cxlflash: Reset hardware queue context via specified register
+    - scsi: cxlflash: Schedule asynchronous reset of the host
+    - scsi: cxlflash: Handle AFU sync failures
+    - scsi: cxlflash: Track pending scsi commands in each hardware queue
+    - scsi: cxlflash: Flush pending commands in cleanup path
+    - scsi: cxlflash: Add scsi command abort handler
+    - scsi: cxlflash: Create character device to provide host management interface
+    - scsi: cxlflash: Separate AFU internal command handling from AFU sync
+      specifics
+    - scsi: cxlflash: Introduce host ioctl support
+    - scsi: cxlflash: Refactor AFU capability checking
+    - scsi: cxlflash: Support LUN provisioning
+    - scsi: cxlflash: Support AFU debug
+    - scsi: cxlflash: Support WS16 unmap
+    - scsi: cxlflash: Remove zeroing of private command data
+    - scsi: cxlflash: Update TMF command processing
+    - scsi: cxlflash: Avoid double free of character device
+    - scsi: cxlflash: Update send_tmf() parameters
+    - scsi: cxlflash: Update debug prints in reset handlers
+
+  * make snap-pkg support (LP: #1700747)
+    - make snap-pkg support
+
+  * Quirk for non-compliant PCI bridge on HiSilicon D05 board (LP: #1698706)
+    - SAUCE: PCI: Support hibmc VGA cards behind a misbehaving HiSilicon bridge
+
+  * arm64: fix crash reading /proc/kcore (LP: #1702749)
+    - fs/proc: kcore: use kcore_list type to check for vmalloc/module address
+    - arm64: mm: select CONFIG_ARCH_PROC_KCORE_TEXT
+
+  * Opal and POWER9 DD2 (LP: #1702159)
+    - SAUCE: powerpc/powernv: Tell OPAL about our MMU mode on POWER9
+
+  * Data corruption with hio driver  (LP: #1701316)
+    - SAUCE: hio: Fix incorrect use of enum req_opf values
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: (noup) Update spl to 0.6.5.10-1, zfs to 0.6.5.10-1ubuntu2
+    - snapcraft.yaml: Sync with xenial
+    - [Config] CONFIG_CAVIUM_ERRATUM_30115=y
+
+  * Miscellaneous upstream changes
+    - Revert "UBUNTU: SAUCE: (efi-lockdown) efi: Add sysctls for secureboot and
+      MokSBState"
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Fri, 14 Jul 2017 15:25:41 -0500
+
+linux (4.12.0-6.7) artful; urgency=low
+
+  * update ENA driver to 1.2.0k from net-next (LP: #1701575)
+    - net: ena: change return value for unsupported features unsupported return
+      value
+    - net: ena: add hardware hints capability to the driver
+    - net: ena: change sizeof() argument to be the type pointer
+    - net: ena: add reset reason for each device FLR
+    - net: ena: add support for out of order rx buffers refill
+    - net: ena: allow the driver to work with small number of msix vectors
+    - net: ena: use napi_schedule_irqoff when possible
+    - net: ena: separate skb allocation to dedicated function
+    - net: ena: use lower_32_bits()/upper_32_bits() to split dma address
+    - net: ena: update driver's rx drop statistics
+    - net: ena: update ena driver to version 1.2.0
+
+  * APST gets enabled against explicit kernel option (LP: #1699004)
+    - nvme: explicitly disable APST on quirked devices
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: hio: Update to Huawei ES3000_V2 (2.1.0.40)
+    - SAUCE: hio updates for 4.12
+    - SAUCE: Enable hio build
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Wed, 05 Jul 2017 14:23:20 -0500
+
+linux (4.12.0-5.6) artful; urgency=low
+
+  * ERAT invalidate on context switch removal (LP: #1700819)
+    - powerpc: Only do ERAT invalidate on radix context switch on P9 DD1
+
+  * powerpc: Invalidate ERAT on powersave wakeup for POWER9 (LP: #1700521)
+    - SAUCE: powerpc: Invalidate ERAT on powersave wakeup for POWER9
+
+  * Miscellaneous Ubuntu changes
+    - d-i: Move qcom-emac from arm64 to shared nic-modules
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.12
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 03 Jul 2017 07:52:02 -0500
+
+linux (4.12.0-4.5) artful; urgency=low
+
+  * aacraid driver may return uninitialized stack data to userspace
+    (LP: #1700077)
+    - SAUCE: scsi: aacraid: Don't copy uninitialized stack memory to userspace
+
+  * KILLER1435-S[0489:e0a2] BT cannot search BT 4.0 device (LP: #1699651)
+    - Bluetooth: btusb: Add support for 0489:e0a2 QCA_ROME device
+
+  * AACRAID for power9 platform (LP: #1689980)
+    - scsi: aacraid: Remove __GFP_DMA for raw srb memory
+    - scsi: aacraid: Fix DMAR issues with iommu=pt
+    - scsi: aacraid: Added 32 and 64 queue depth for arc natives
+    - scsi: aacraid: Set correct Queue Depth for HBA1000 RAW disks
+    - scsi: aacraid: Remove reset support from check_health
+    - scsi: aacraid: Change wait time for fib completion
+    - scsi: aacraid: Log count info of scsi cmds before reset
+    - scsi: aacraid: Print ctrl status before eh reset
+    - scsi: aacraid: Using single reset mask for IOP reset
+    - scsi: aacraid: Rework IOP reset
+    - scsi: aacraid: Add periodic checks to see IOP reset status
+    - scsi: aacraid: Rework SOFT reset code
+    - scsi: aacraid: Rework aac_src_restart
+    - scsi: aacraid: Use correct function to get ctrl health
+    - scsi: aacraid: Make sure ioctl returns on controller reset
+    - scsi: aacraid: Enable ctrl reset for both hba and arc
+    - scsi: aacraid: Add reset debugging statements
+    - scsi: aacraid: Remove reference to Series-9
+    - scsi: aacraid: Update driver version to 50834
+
+  * hibmc driver does not include "pci:" prefix in bus ID (LP: #1698700)
+    - SAUCE: drm: hibmc: Use set_busid function from drm core
+
+  * HiSilicon D05: installer doesn't appear on VGA (LP: #1698954)
+    - d-i: Add hibmc-drm to kernel-image udeb
+
+  * Fix /proc/cpuinfo revision for POWER9 DD2 (LP: #1698844)
+    - SAUCE: powerpc: Fix /proc/cpuinfo revision for POWER9 DD2
+
+  * Miscellaneous Ubuntu changes
+    - [Config] CONFIG_SATA_MV=n and CONFIG_GENERIC_PHY=n for s390x
+    - [Config] CONFIG_ATA=n for s390x
+    - [Config] Update annotations for 4.12
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.12-rc7
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 26 Jun 2017 11:27:29 -0500
+
+linux (4.12.0-3.4) artful; urgency=low
+
+  * Miscellaneous upstream changes
+    - ufs: fix the logics for tail relocation
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.12-rc6
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 19 Jun 2017 14:50:39 -0500
+
+linux (4.12.0-2.3) artful; urgency=low
+
+  * CVE-2014-9900
+    - SAUCE: (no-up) net: Zeroing the structure ethtool_wolinfo in
+      ethtool_get_wol()
+
+  * System doesn't boot properly on Gigabyte AM4 motherboards (AMD Ryzen)
+    (LP: #1671360)
+    - pinctrl/amd: Use regular interrupt instead of chained
+
+  * extend-diff-ignore should use exact matches (LP: #1693504)
+    - [Packaging] exact extend-diff-ignore matches
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: efi: Don't print secure boot state from the efi stub
+    - ubuntu: vbox -- Update to 5.1.22-dfsg-1
+    - SAUCE: vbox fixes for 4.12
+    - Re-enable virtualbox build
+    - [Config] CONFIG_ORANGEFS_FS=m
+    - SAUCE: (noup) Update spl to 0.6.5.9-1ubuntu2, zfs to 0.6.5.9-5ubuntu7
+    - Enable zfs build
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.12-rc4
+  * Rebase to v4.12-rc5
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Sun, 11 Jun 2017 22:25:13 -0500
+
+linux (4.12.0-1.2) artful; urgency=low
+
+  * Enable Matrox driver for Ubuntu 16.04.3 (LP: #1693337)
+    - [Config] Enable CONFIG_DRM_MGAG200 as module
+
+  * Support low-pin-count devices on Hisilicon SoCs (LP: #1677319)
+    - [Config] CONFIG_LIBIO=y on arm64 only
+    - SAUCE: LIBIO: Introduce a generic PIO mapping method
+    - SAUCE: OF: Add missing I/O range exception for indirect-IO devices
+    - [Config] CONFIG_HISILICON_LPC=y
+    - SAUCE: LPC: Support the device-tree LPC host on Hip06/Hip07
+    - SAUCE: LIBIO: Support the dynamically logical PIO registration of ACPI host
+      I/O
+    - SAUCE: LPC: Add the ACPI LPC support
+    - SAUCE: PCI: Apply the new generic I/O management on PCI IO hosts
+    - SAUCE: PCI: Restore codepath for !CONFIG_LIBIO
+
+  * POWER9: Additional patches for TTY and CPU_IDLE (LP: #1674325)
+    - SAUCE: tty: Fix ldisc crash on reopened tty
+
+  * Miscellaneous Ubuntu changes
+    - [Debian] Add build-dep on libnuma-dev to enable 'perf bench numa'
+    - Rebase to v4.12-rc3
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.12-rc3
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Mon, 29 May 2017 20:56:29 -0500
+
+linux (4.12.0-0.1) artful; urgency=low
+
+  * please enable CONFIG_ARM64_LSE_ATOMICS (LP: #1691614)
+    - [Config] CONFIG_ARM64_LSE_ATOMICS=y
+
+  * [Regression] NUMA_BALANCING disabled on arm64 (LP: #1690914)
+    - [Config] CONFIG_NUMA_BALANCING{,_DEFAULT_ENABLED}=y on arm64
+
+  * exec'ing a setuid binary from a threaded program sometimes fails to setuid
+    (LP: #1672819)
+    - SAUCE: exec: ensure file system accounting in check_unsafe_exec is correct
+
+  * Miscellaneous Ubuntu changes
+    - Update find-missing-sauce.sh to compare to artful
+    - Update dropped.txt
+    - SAUCE: (efi-lockdown) efi: Add EFI_SECURE_BOOT bit
+    - SAUCE: (efi-lockdown) Add the ability to lock down access to the running
+      kernel image
+    - SAUCE: (efi-lockdown) efi: Lock down the kernel if booted in secure boot
+      mode
+    - SAUCE: (efi-lockdown) Enforce module signatures if the kernel is locked down
+    - SAUCE: (efi-lockdown) Restrict /dev/mem and /dev/kmem when the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) Add a sysrq option to exit secure boot mode
+    - SAUCE: (efi-lockdown) kexec: Disable at runtime if the kernel is locked down
+    - SAUCE: (efi-lockdown) Copy secure_boot flag in boot params across kexec
+      reboot
+    - SAUCE: (efi-lockdown) kexec_file: Disable at runtime if securelevel has been
+      set
+    - SAUCE: (efi-lockdown) hibernate: Disable when the kernel is locked down
+    - SAUCE: (efi-lockdown) uswsusp: Disable when the kernel is locked down
+    - SAUCE: (efi-lockdown) PCI: Lock down BAR access when the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) x86: Lock down IO port access when the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) x86: Restrict MSR access when the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) asus-wmi: Restrict debugfs interface when the kernel
+      is locked down
+    - SAUCE: (efi-lockdown) ACPI: Limit access to custom_method when the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) acpi: Ignore acpi_rsdp kernel param when the kernel
+      has been locked down
+    - SAUCE: (efi-lockdown) acpi: Disable ACPI table override if the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) acpi: Disable APEI error injection if the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) Enable cold boot attack mitigation
+    - SAUCE: (efi-lockdown) bpf: Restrict kernel image access functions when the
+      kernel is locked down
+    - SAUCE: (efi-lockdown) scsi: Lock down the eata driver
+    - SAUCE: (efi-lockdown) Prohibit PCMCIA CIS storage when the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) Lock down TIOCSSERIAL
+    - SAUCE: (efi-lockdown) KEYS: Allow unrestricted boot-time addition of keys to
+      secondary keyring
+    - SAUCE: (efi-lockdown) efi: Add EFI signature data types
+    - SAUCE: (efi-lockdown) efi: Add an EFI signature blob parser
+    - SAUCE: (efi-lockdown) MODSIGN: Import certificates from UEFI Secure Boot
+    - SAUCE: (efi-lockdown) MODSIGN: Allow the "db" UEFI variable to be suppressed
+    - SAUCE: (efi-lockdown) efi: Sanitize boot_params in efi stub
+    - SAUCE: (efi-lockdown) efi: Add secure_boot state and status bit for
+      MokSBState
+    - SAUCE: (efi-lockdown) efi: Add sysctls for secureboot and MokSBState
+    - [Config] Set values for UEFI secure boot lockdown options
+    - Disable virtualbox build
+    - Disable hio build
+    - SAUCE: securityfs: Replace CURRENT_TIME with current_time()
+    - Disable zfs build
+    - [Debian] Work out upstream tag for use with gen-auto-reconstruct
+    - SAUCE: Import aufs driver
+    - SAUCE: aufs -- Include linux/mm.h in fs/aufs/file.h
+    - [Config] Enable aufs
+    - SAUCE: perf callchain: Include errno.h on x86 unconditinally
+
+  [ Upstream Kernel Changes ]
+
+  * Rebase to v4.12-rc2
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Sun, 21 May 2017 23:44:44 -0500
+
+linux (4.11.0-3.8) artful; urgency=low
+
+  [ Seth Forshee ]
+
+  * Release Tracking Bug
+    - LP: #1690999
+
+  * apparmor_parser hangs indefinitely when called by multiple threads
+    (LP: #1645037)
+    - SAUCE: apparmor: fix lock ordering for mkdir
+
+  * apparmor leaking securityfs pin count (LP: #1660846)
+    - SAUCE: apparmor: fix leak on securityfs pin count
+
+  * apparmor reference count leak when securityfs_setup_d_inode\ () fails
+    (LP: #1660845)
+    - SAUCE: apparmor: fix reference count leak when securityfs_setup_d_inode()
+      fails
+
+  * apparmor not checking error if security_pin_fs() fails (LP: #1660842)
+    - SAUCE: apparmor: fix not handling error case when securityfs_pin_fs() fails
+
+  * libvirt profile is blocking global setrlimit despite having no rlimit rule
+    (LP: #1679704)
+    - SAUCE: apparmor: fix complain mode failure for rlimit mediation
+    - apparmor: update auditing of rlimit check to provide capability information
+
+  * apparmor: does not provide a way to detect policy updataes (LP: #1678032)
+    - SAUCE: apparmor: add policy revision file interface
+
+  * apparmor does not make support of query data visible (LP: #1678023)
+    - SAUCE: apparmor: add label data availability to the feature set
+
+  * apparmor query interface does not make supported query info available
+    (LP: #1678030)
+    - SAUCE: apparmor: add information about the query inteface to the feature set
+
+  * change_profile incorrect when using namespaces with a compound stack
+    (LP: #1677959)
+    - SAUCE: apparmor: fix label parse for stacked labels
+
+  * Regression in 4.4.0-65-generic causes very frequent system crashes
+    (LP: #1669611)
+    - apparmor: sync of apparmor 3.6+ (17.04)
+
+  * Artful update to 4.11.1 stable release (LP: #1690814)
+    - dm ioctl: prevent stack leak in dm ioctl call
+    - drm/sti: fix GDP size to support up to UHD resolution
+    - power: supply: lp8788: prevent out of bounds array access
+    - brcmfmac: Ensure pointer correctly set if skb data location changes
+    - brcmfmac: Make skb header writable before use
+    - sparc64: fix fault handling in NGbzero.S and GENbzero.S
+    - refcount: change EXPORT_SYMBOL markings
+    - net: macb: fix phy interrupt parsing
+    - tcp: fix access to sk->sk_state in tcp_poll()
+    - geneve: fix incorrect setting of UDP checksum flag
+    - bpf: enhance verifier to understand stack pointer arithmetic
+    - bpf, arm64: fix jit branch offset related to ldimm64
+    - tcp: fix wraparound issue in tcp_lp
+    - net: ipv6: Do not duplicate DAD on link up
+    - net: usb: qmi_wwan: add Telit ME910 support
+    - tcp: do not inherit fastopen_req from parent
+    - ipv4, ipv6: ensure raw socket message is big enough to hold an IP header
+    - rtnetlink: NUL-terminate IFLA_PHYS_PORT_NAME string
+    - ipv6: initialize route null entry in addrconf_init()
+    - ipv6: reorder ip6_route_dev_notifier after ipv6_dev_notf
+    - tcp: randomize timestamps on syncookies
+    - bnxt_en: allocate enough space for ->ntp_fltr_bmap
+    - bpf: don't let ldimm64 leak map addresses on unprivileged
+    - net: mdio-mux: bcm-iproc: call mdiobus_free() in error path
+    - f2fs: sanity check segment count
+    - xen/arm,arm64: fix xen_dma_ops after 815dd18 "Consolidate get_dma_ops..."
+    - xen: Revert commits da72ff5bfcb0 and 72a9b186292d
+    - block: get rid of blk_integrity_revalidate()
+    - Linux 4.11.1
+
+  * Module signing exclusion for staging drivers does not work properly
+    (LP: #1690908)
+    - SAUCE: Fix module signing exclusion in package builds
+
+  * perf: qcom: Add L3 cache PMU driver (LP: #1689856)
+    - [Config] CONFIG_QCOM_L3_PMU=y
+    - perf: qcom: Add L3 cache PMU driver
+
+  * No PMU support for ACPI-based arm64 systems (LP: #1689661)
+    - drivers/perf: arm_pmu: rework per-cpu allocation
+    - drivers/perf: arm_pmu: manage interrupts per-cpu
+    - drivers/perf: arm_pmu: split irq request from enable
+    - drivers/perf: arm_pmu: remove pointless PMU disabling
+    - drivers/perf: arm_pmu: define armpmu_init_fn
+    - drivers/perf: arm_pmu: fold init into alloc
+    - drivers/perf: arm_pmu: factor out pmu registration
+    - drivers/perf: arm_pmu: simplify cpu_pmu_request_irqs()
+    - drivers/perf: arm_pmu: handle no platform_device
+    - drivers/perf: arm_pmu: rename irq request/free functions
+    - drivers/perf: arm_pmu: split cpu-local irq request/free
+    - drivers/perf: arm_pmu: move irq request/free into probe
+    - drivers/perf: arm_pmu: split out platform device probe logic
+    - arm64: add function to get a cpu's MADT GICC table
+    - [Config] CONFIG_ARM_PMU_ACPI=y
+    - drivers/perf: arm_pmu: add ACPI framework
+    - arm64: pmuv3: handle !PMUv3 when probing
+    - arm64: pmuv3: use arm_pmu ACPI framework
+
+  * Fix NVLINK2 TCE route (LP: #1690155)
+    - powerpc/powernv: Fix TCE kill on NVLink2
+
+  * CVE-2017-0605
+    - tracing: Use strlcpy() instead of strcpy() in __trace_find_cmdline()
+
+  * Miscellaneous Ubuntu changes
+    - [Config] Restore powerpc arch to annotations file
+    - [Config] Disable runtime testing modules
+    - [Config] Disable drivers not needed on s390x
+    - [Config] Update annotations for 4.11
+    - [Config] updateconfigs after apparmor updates
+
+  * Miscellaneous upstream changes
+    - apparmor: use SHASH_DESC_ON_STACK
+    - apparmor: fix invalid reference to index variable of iterator line 836
+    - apparmor: fix parameters so that the permission test is bypassed at boot
+    - apparmor: Make path_max parameter readonly
+    - apparmorfs: Combine two function calls into one in aa_fs_seq_raw_abi_show()
+    - apparmorfs: Use seq_putc() in two functions
+    - apparmor: provide information about path buffer size at boot
+    - apparmor: add/use fns to print hash string hex value
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Tue, 16 May 2017 00:39:13 -0500
+
+linux (4.11.0-2.7) artful; urgency=low
+
+  * kernel-wedge fails in artful due to leftover squashfs-modules d-i files
+    (LP: #1688259)
+    - Remove squashfs-modules files from d-i
+    - [Config] as squashfs-modules is builtin kernel-image must Provides: it
+
+  * [Zesty] d-i: replace msm_emac with qcom_emac (LP: #1677297)
+    - Revert "UBUNTU: d-i: initrd needs msm_emac on amberwing platform."
+    - d-i: initrd needs qcom_emac on amberwing platform.
+
+  * update for V3 kernel bits and improved multiple fan slice support
+    (LP: #1470091)
+    - SAUCE: fan: tunnel multiple mapping mode (v3)
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: (noup) Update spl to 0.6.5.9-1ubuntu1, zfs to 0.6.5.9-5ubuntu5
+    - Enable zfs
+    - SAUCE: fan: add VXLAN implementation
+    - SAUCE: (efi-lockdown) efi: Add EFI_SECURE_BOOT bit
+    - SAUCE: (efi-lockdown) Add the ability to lock down access to the running
+      kernel image
+    - SAUCE: (efi-lockdown) efi: Lock down the kernel if booted in secure boot
+      mode
+    - SAUCE: (efi-lockdown) Enforce module signatures if the kernel is locked down
+    - SAUCE: (efi-lockdown) Restrict /dev/mem and /dev/kmem when the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) Add a sysrq option to exit secure boot mode
+    - SAUCE: (efi-lockdown) kexec: Disable at runtime if the kernel is locked down
+    - SAUCE: (efi-lockdown) Copy secure_boot flag in boot params across kexec
+      reboot
+    - SAUCE: (efi-lockdown) kexec_file: Disable at runtime if securelevel has been
+      set
+    - SAUCE: (efi-lockdown) hibernate: Disable when the kernel is locked down
+    - SAUCE: (efi-lockdown) uswsusp: Disable when the kernel is locked down
+    - SAUCE: (efi-lockdown) PCI: Lock down BAR access when the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) x86: Lock down IO port access when the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) x86: Restrict MSR access when the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) asus-wmi: Restrict debugfs interface when the kernel
+      is locked down
+    - SAUCE: (efi-lockdown) ACPI: Limit access to custom_method when the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) acpi: Ignore acpi_rsdp kernel param when the kernel
+      has been locked down
+    - SAUCE: (efi-lockdown) acpi: Disable ACPI table override if the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) acpi: Disable APEI error injection if the kernel is
+      locked down
+    - SAUCE: (efi-lockdown) Enable cold boot attack mitigation
+    - SAUCE: (efi-lockdown) bpf: Restrict kernel image access functions when the
+      kernel is locked down
+    - SAUCE: (efi-lockdown) scsi: Lock down the eata driver
+    - SAUCE: (efi-lockdown) Prohibit PCMCIA CIS storage when the kernel is locked
+      down
+    - SAUCE: (efi-lockdown) Lock down TIOCSSERIAL
+    - SAUCE: (efi-lockdown) Add EFI signature data types
+    - SAUCE: (efi-lockdown) Add an EFI signature blob parser and key loader.
+    - SAUCE: (efi-lockdown) KEYS: Add a system blacklist keyring
+    - SAUCE: (efi-lockdown) MODSIGN: Import certificates from UEFI Secure Boot
+    - SAUCE: (efi-lockdown) MODSIGN: Support not importing certs from db
+    - SAUCE: (efi-lockdown) MODSIGN: Don't try secure boot if EFI runtime is
+      disabled
+    - SAUCE: (efi-lockdown) efi: Sanitize boot_params in efi stub
+    - SAUCE: (efi-lockdown) efi: Add secure_boot state and status bit for
+      MokSBState
+    - SAUCE: (efi-lockdown) efi: Add sysctls for secureboot and MokSBState
+    - [Config] Set values for UEFI secure boot lockdown options
+    - Update dropped.txt
+
+  [ Upstream Kernel Changes ]
+
+  * rebase to v4.11
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Fri, 05 May 2017 07:43:14 -0500
+
+linux (4.11.0-1.6) artful; urgency=low
+
+  * Miscellaneous Ubuntu changes
+    - [Debian] Use default compression for all packages
+    - SAUCE: (namespace) block_dev: Support checking inode permissions in
+      lookup_bdev()
+    - SAUCE: (namespace) block_dev: Check permissions towards block device inode
+      when mounting
+    - SAUCE: (namespace) mtd: Check permissions towards mtd block device inode
+      when mounting
+    - SAUCE: (namespace) fs: Allow superblock owner to change ownership of inodes
+    - SAUCE: (namespace) fs: Don't remove suid for CAP_FSETID for userns root
+    - SAUCE: (namespace) fs: Allow superblock owner to access do_remount_sb()
+    - SAUCE: (namespace) capabilities: Allow privileged user in s_user_ns to set
+      security.* xattrs
+    - SAUCE: (namespace) fs: Allow CAP_SYS_ADMIN in s_user_ns to freeze and thaw
+      filesystems
+    - SAUCE: (namespace) fuse: Add support for pid namespaces
+    - SAUCE: (namespace) fuse: Support fuse filesystems outside of init_user_ns
+    - SAUCE: (namespace) fuse: Restrict allow_other to the superblock's namespace
+      or a descendant
+    - SAUCE: (namespace) fuse: Allow user namespace mounts
+    - SAUCE: (namespace) ext4: Add support for unprivileged mounts from user
+      namespaces
+    - SAUCE: (namespace) evm: Don't update hmacs in user ns mounts
+    - SAUCE: (namespace) ext4: Add module parameter to enable user namespace
+      mounts
+    - SAUCE: (namespace) block_dev: Forbid unprivileged mounting when device is
+      opened for writing
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Wed, 26 Apr 2017 10:08:29 -0500
+
+linux (4.11.0-0.5) artful; urgency=low
+
+  * [Hyper-V][SAUCE] pci-hyperv: Use only 16 bit integer for PCI domain
+    (LP: #1684971)
+    - SAUCE: pci-hyperv: Use only 16 bit integer for PCI domain
+
+  * [Hyper-V] Ubuntu 14.04.2 LTS Generation 2 SCSI Errors on VSS Based Backups
+    (LP: #1470250)
+    - SAUCE: Tools: hv: vss: Thaw the filesystem and continue after freeze fails
+
+  * Enable virtual scsi server driver for Power (LP: #1615665)
+    - SAUCE: Return TCMU-generated sense data to fabric module
+
+  * include/linux/security.h header syntax error with !CONFIG_SECURITYFS
+    (LP: #1630990)
+    - SAUCE: (no-up) include/linux/security.h -- fix syntax error with
+      CONFIG_SECURITYFS=n
+
+  * Miscellaneous Ubuntu changes
+    - SAUCE: Import aufs driver
+    - [Config] Enable aufs
+    - [Debian] Add script to update virtualbox
+    - ubuntu: vbox -- Update to 5.1.20-dfsg-2
+    - Enable vbox
+    - SAUCE: aufs -- Include linux/mm.h in fs/aufs/file.h
+
+  [ Upstream Kernel Changes ]
+
+  * rebase to v4.11-rc8
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Tue, 25 Apr 2017 13:42:54 -0500
+
+linux (4.11.0-0.4) zesty; urgency=low
+
+  * POWER9: Improve performance on memory management (LP: #1681429)
+    - SAUCE: powerpc/mm/radix: Don't do page walk cache flush when doing full mm
+      flush
+    - SAUCE: powerpc/mm/radix: Remove unnecessary ptesync
+
+  * Miscellaneous Ubuntu changes
+    - find-missing-sauce.sh
+
+  [ Upstream Kernel Changes ]
+
+  * rebase to v4.11-rc7
+
+ -- Seth Forshee <seth.forshee@canonical.com>  Tue, 18 Apr 2017 08:19:43 -0500
+
+linux (4.11.0-0.3) zesty; urgency=low
+
+  * Disable CONFIG_HVC_UDBG on ppc64el (LP: #1680888)
+    - [Config] Disable CONFIG_HVC_UDBG on ppc64el
+
+  * smartpqi driver needed in initram disk and installer (LP: #1680156)
+    - [Config] Add smartpqi to d-i
+
+  * Disable CONFIG_SECURITY_SELINUX_DISABLE (LP: #1680315)
+    - [Config] CONFIG_SECURITY_SELINUX_DISABLE=n
+
+  * Miscellaneous Ubuntu changes
+    - [Config] flash-kernel should be a Breaks
+    - [Config] drop the info directory
+    - [Config] drop NOTES as obsolete
+    - [Config] drop changelog.historical as obsolete
+    - rebase to v4.11-rc6
+
+  [ Upstream Kernel Changes ]
+
+  * rebase to v4.11-rc6
+
+ -- Tim Gardner <tim.gardner@canonical.com>  Tue, 11 Apr 2017 07:16:52 -0600
+
+linux (4.11.0-0.2) zesty; urgency=low
+
+  [ Upstream Kernel Changes ]
+
+  * rebase to v4.11-rc5
+
+ -- Tim Gardner <tim.gardner@canonical.com>  Mon, 03 Apr 2017 08:26:07 +0100
+
+linux (4.11.0-0.1) zesty; urgency=low
+
+  [ Upstream Kernel Changes ]
+
+  * rebase to v4.11-rc4
+    - LP: #1591053
+
+ -- Tim Gardner <tim.gardner@canonical.com>  Mon, 20 Mar 2017 05:15:32 -0600
+
+linux (4.11.0-0.0) zesty; urgency=low
+
+  * dummy entry
+
+ -- Tim Gardner <tim.gardner@canonical.com>  Mon, 20 Mar 2017 05:15:32 -0600
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/config/README.rst
+++ linux-xilinx-zynqmp-5.4.0/debian.master/config/README.rst
@@ -0,0 +1,185 @@
+==================
+Config Annotations
+==================
+
+:Author: Andrea Righi
+
+Overview
+========
+
+Each Ubuntu kernel needs to maintain its own .config for each supported
+architecture and each flavour.
+
+Every time a new patch is applied or a kernel is rebased on top of a new
+one, we need to update the .config's accordingly (config options can be
+added, removed and also renamed).
+
+So, we need to make sure that some critical config options are always
+matching the desired value in order to have a functional kernel.
+
+State of the art
+================
+
+At the moment configs are maintained as a set of Kconfig chunks (inside
+`debian.<kernel>/config/`): a global one, plus per-arch / per-flavour
+chunks.
+
+In addition to that, we need to maintain also a file called
+'annotations'; the purpose of this file is to make sure that some
+critical config options are not silently removed or changed when the
+real .config is re-generated (for example after a rebase or after
+applying a new set of patches).
+
+The main problem with this approach is that, often, we have duplicate
+information that is stored both in the Kconfig chunks *and* in the
+annotations files and, at the same time, the whole .config's information
+is distributed between Kconfig chunks and annotations, making it hard to
+maintain, review and manage in general.
+
+Proposed solution
+=================
+
+The proposed solution is to store all the config information into the
+"annotations" format and get rid of the config chunks (basically the
+real .config's can be produced "compiling" annotations).
+
+Implementation
+==============
+
+To help the management of the annotations an helper script is provided
+(`debian/scripts/misc/annotations`):
+
+```
+usage: annotations [-h] [--version] [--file FILE] [--arch ARCH] [--flavour FLAVOUR] [--config CONFIG]
+                   (--query | --export | --import FILE | --update FILE | --check FILE)
+
+Manage Ubuntu kernel .config and annotations
+
+options:
+  -h, --help            show this help message and exit
+  --version, -v         show program's version number and exit
+  --file FILE, -f FILE  Pass annotations or .config file to be parsed
+  --arch ARCH, -a ARCH  Select architecture
+  --flavour FLAVOUR, -l FLAVOUR
+                        Select flavour (default is "generic")
+  --config CONFIG, -c CONFIG
+                        Select a specific config option
+
+Action:
+  --query, -q           Query annotations
+  --export, -e          Convert annotations to .config format
+  --import FILE, -i FILE
+                        Import a full .config for a specific arch and flavour into annotations
+  --update FILE, -u FILE
+                        Import a partial .config into annotations (only resync configs specified in FILE)
+  --check FILE, -k FILE
+                        Validate kernel .config with annotations
+```
+
+This script allows to query config settings (per arch/flavour/config),
+export them into the Kconfig format (generating the real .config files)
+and check if the final .config matches the rules defined in the
+annotations.
+
+Examples (annotations is defined as an alias to `debian/scripts/annotations`):
+
+ - Show settings for `CONFIG_DEBUG_INFO_BTF` for master kernel across all the
+   supported architectures and flavours:
+
+```
+$ annotations --query --config CONFIG_DEBUG_INFO_BTF
+{
+    "policy": {
+        "amd64": "y",
+        "arm64": "y",
+        "armhf": "n",
+        "ppc64el": "y",
+        "riscv64": "y",
+        "s390x": "y"
+    },
+    "note": "'Needs newer pahole for armhf'"
+}
+```
+
+ - Dump kernel .config for arm64 and flavour generic-64k:
+
+```
+$ annotations --arch arm64 --flavour generic-64k --export
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_COMPAT=y
+...
+```
+
+ - Update annotations file with a new kernel .config for amd64 flavour
+   generic:
+
+```
+$ annotations --arch amd64 --flavour generic --import build/.config
+```
+
+Moreover, an additional kernelconfig commands are provided
+(via debian/rules targets):
+ - `migrateconfigs`: automatically merge all the previous configs into
+   annotations (local changes still need to be committed)
+
+Annotations headers
+===================
+
+The main annotations file should contain a header to define the architectures
+and flavours that are supported.
+
+Here is the format of the header for the generic kernel:
+```
+# Menu: HEADER
+# FORMAT: 4
+# ARCH: amd64 arm64 armhf ppc64el riscv64 s390x
+# FLAVOUR: amd64-generic arm64-generic arm64-generic-64k armhf-generic armhf-generic-lpae ppc64el-generic riscv64-generic s390x-generic
+
+```
+
+Example header of a derivative (linux-aws):
+```
+# Menu: HEADER
+# FORMAT: 4
+# ARCH: amd64 arm64
+# FLAVOUR: amd64-aws arm64-aws
+# FLAVOUR_DEP: {'amd64-aws': 'amd64-generic', 'arm64-aws': 'arm64-generic'}
+
+include "../../debian.master/config/annotations"
+
+# Below you can define only the specific linux-aws configs that differ from linux generic
+
+```
+
+Pros and Cons
+=============
+
+ Pros:
+  - avoid duplicate information in .config's and annotations
+  - allow to easily define groups of config settings (for a specific
+    environment or feature, such as annotations.clouds, annotations.ubuntu,
+    annotations.snapd, etc.)
+  - config options are more accessible, easy to change and review
+  - we can easily document how config options are managed (and external
+    contributors won't be discouraged anymore when they need to to change a
+    config option)
+
+ Cons:
+  - potential regressions: the new tool/scripts can have potential bugs,
+    so we could experience regressions due to some missed config changes
+  - kernel team need to understand the new process (even if everything
+    is transparent, kernel cranking process is the same, there might be
+    corner cases that need to be addressed and resolved manually)
+
+TODO
+====
+
+ - Migrate all flavour and arch definitions into annotations (rather
+   than having this information defined in multiple places inside
+   debian/scripts); right now this information is "partially" migrated,
+   meaning that we need to define arches and flavours in the headers
+   section of annotations (so that the annotations tool can figure out
+   the list of supported arches and flavours), but arches and flavours
+   are still defined elsewhere, ideally we would like to have arches and
+   flavours defined only in one place: annotations.
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/config/annotations
+++ linux-xilinx-zynqmp-5.4.0/debian.master/config/annotations
@@ -0,0 +1,12866 @@
+# Menu: HEADER
+# FORMAT: 4
+# ARCH: amd64 arm64 armhf i386 ppc64el s390x
+# FLAVOUR: amd64-generic amd64-lowlatency arm64-generic armhf-generic armhf-generic-lpae i386-generic i386-lowlatency ppc64el-generic s390x-generic
+
+CONFIG_ACPI_CUSTOM_DSDT_FILE                    policy<{'amd64': '""', 'i386': '""'}>
+CONFIG_ACPI_CUSTOM_DSDT_FILE                    note<'might allow hardware damage'>
+
+CONFIG_ACPI_CUSTOM_METHOD                       policy<{'amd64': 'n', 'arm64': 'n', 'i386': 'n'}>
+CONFIG_ACPI_CUSTOM_METHOD                       note<'SECURITY: allows arbitrary execution'>
+
+CONFIG_AGP                                      policy<{'amd64': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_AGP                                      note<'not autoloadable'>
+
+CONFIG_ARCH_ROCKCHIP                            policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARCH_ROCKCHIP                            note<'LP:1566283 / LP:1825222'>
+
+CONFIG_ARCH_TANGO                               policy<{'armhf': 'n'}>
+CONFIG_ARCH_TANGO                               note<'LP:1787945'>
+
+CONFIG_ARCH_ZX                                  policy<{'arm64': 'n', 'armhf': 'n'}>
+CONFIG_ARCH_ZX                                  note<'LP:1628503'>
+
+CONFIG_ARM64_ERRATUM_843419                     policy<{'arm64': 'y'}>
+CONFIG_ARM64_ERRATUM_843419                     note<'LP:1647793'>
+
+CONFIG_ARM64_ERRATUM_858921                     policy<{'arm64': 'y'}>
+CONFIG_ARM64_ERRATUM_858921                     note<'LP#1675509'>
+
+CONFIG_ARM64_LSE_ATOMICS                        policy<{'arm64': 'y'}>
+CONFIG_ARM64_LSE_ATOMICS                        note<'LP:1691614'>
+
+CONFIG_ARM64_VA_BITS_48                         policy<{'arm64': 'y'}>
+CONFIG_ARM64_VA_BITS_48                         note<'Cavium ThunderX 2-socket needs a minimum of 41 bits of VA'>
+
+CONFIG_ARMV8_DEPRECATED                         policy<{'arm64': 'y'}>
+CONFIG_ARMV8_DEPRECATED                         note<'LP:1545542'>
+
+CONFIG_ARM_HIGHBANK_CPUIDLE                     policy<{'armhf-generic': 'n', 'armhf-generic-lpae': 'y'}>
+CONFIG_ARM_HIGHBANK_CPUIDLE                     note<'broken on ecx-1000'>
+
+CONFIG_ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT       policy<{'arm64': 'n'}>
+CONFIG_ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT       note<'LP:1845820'>
+
+CONFIG_ASYMMETRIC_KEY_TYPE                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ASYMMETRIC_KEY_TYPE                      note<'module signing'>
+
+CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE            note<'module signing'>
+
+CONFIG_ATA_PIIX                                 policy<{'amd64': 'y', 'arm64': 'm', 'armhf': 'm', 'i386': 'y', 'ppc64el': 'm'}>
+CONFIG_ATA_PIIX                                 note<'LP:1627324'>
+
+CONFIG_AUFS_EXPORT                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_AUFS_EXPORT                              note<'LP:1121699'>
+
+CONFIG_BINFMT_SCRIPT                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BINFMT_SCRIPT                            note<'required if init is a shell script such as in initramfs-tools'>
+
+CONFIG_BLK_DEV_DM                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BLK_DEV_DM                               note<'LP:#560717'>
+
+CONFIG_BLK_DEV_NVME                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BLK_DEV_NVME                             note<'LP:#1759893'>
+
+CONFIG_BLK_DEV_RAM                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BLK_DEV_RAM                              note<'LP #1593293'>
+
+CONFIG_BLK_DEV_RAM_SIZE                         policy<{'amd64': '65536', 'arm64': '65536', 'armhf': '65536', 'i386': '65536', 'ppc64el': '65536', 's390x': '65536'}>
+CONFIG_BLK_DEV_RAM_SIZE                         note<'Ramdisk size should be a minimum of 64M'>
+
+CONFIG_BLK_DEV_SD                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BLK_DEV_SD                               note<'LP:1627330'>
+
+CONFIG_BLK_DEV_SR                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BLK_DEV_SR                               note<'LP:1627330'>
+
+CONFIG_BLK_DEV_THROTTLING                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BLK_DEV_THROTTLING                       note<'CGROUP disk consumption control'>
+
+CONFIG_BLK_DEV_UMEM                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_BLK_DEV_UMEM                             note<'experimental NVRAM disk driver -- opt-in'>
+
+CONFIG_BT_HS                                    policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_BT_HS                                    note<'https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00435.html'>
+
+CONFIG_CHR_DEV_SG                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CHR_DEV_SG                               note<'not autoloadable'>
+
+CONFIG_CMA_SIZE_MBYTES                          policy<{'arm64': '32', 'armhf': '32'}>
+CONFIG_CMA_SIZE_MBYTES                          note<'LP:1823753'>
+
+CONFIG_COMPAT_BRK                               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_COMPAT_BRK                               note<'disables brk ASLR'>
+
+CONFIG_CP15_BARRIER_EMULATION                   policy<{'arm64': 'y'}>
+CONFIG_CP15_BARRIER_EMULATION                   note<'LP:1545542'>
+
+CONFIG_CPUFREQ_DT                               policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_CPUFREQ_DT                               note<'not autoloadable'>
+
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE         note<'for bootspeed'>
+
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE                note<'not autoloadable'>
+
+CONFIG_CPU_FREQ_GOV_ONDEMAND                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CPU_FREQ_GOV_ONDEMAND                    note<'not autoloadable'>
+
+CONFIG_CPU_FREQ_GOV_PERFORMANCE                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CPU_FREQ_GOV_PERFORMANCE                 note<'not autoloadable'>
+
+CONFIG_CPU_FREQ_GOV_POWERSAVE                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CPU_FREQ_GOV_POWERSAVE                   note<'not autoloadable'>
+
+CONFIG_CPU_FREQ_GOV_USERSPACE                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CPU_FREQ_GOV_USERSPACE                   note<'not autoloadable'>
+
+CONFIG_CPU_FREQ_STAT                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CPU_FREQ_STAT                            note<'dependancy of boot essential'>
+
+CONFIG_CRASH_DUMP                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRASH_DUMP                               note<'LP:1363180'>
+
+CONFIG_CRYPTO_SHA512                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_SHA512                            note<'module signing'>
+
+CONFIG_CS5535_MFGPT                             policy<{'i386': 'n'}>
+CONFIG_CS5535_MFGPT                             note<'should be disabled by default'>
+
+CONFIG_DEBUG_FS                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DEBUG_FS                                 note<'required debug option'>
+
+CONFIG_DEBUG_INFO                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DEBUG_INFO                               note<'required for debug packages'>
+
+CONFIG_DEBUG_INFO_SPLIT                         policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_INFO_SPLIT                         note<'LP:1413646 and LP:1413664'>
+
+CONFIG_DEBUG_KERNEL                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DEBUG_KERNEL                             note<'required debug option'>
+
+CONFIG_DEFAULT_MMAP_MIN_ADDR                    policy<{'amd64': '65536', 'arm64': '32768', 'armhf': '32768', 'i386': '65536', 'ppc64el': '65536', 's390x': '65536'}>
+CONFIG_DEFAULT_MMAP_MIN_ADDR                    note<'LP:1418140 LP:1531327'>
+
+CONFIG_DEVKMEM                                  policy<{'amd64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEVKMEM                                  note<'/dev/kmem is a large attack vector'>
+
+CONFIG_DEVTMPFS                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DEVTMPFS                                 note<'upstart requirement'>
+
+CONFIG_DEVTMPFS_MOUNT                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DEVTMPFS_MOUNT                           note<'upstart requirement'>
+
+CONFIG_DMA_CMA                                  policy<{'amd64': 'n', 'arm64': 'y', 'armhf': 'y', 'i386': 'n', 's390x': 'n'}>
+CONFIG_DMA_CMA                                  note<'LP:1803206'>
+
+CONFIG_DRM_AMDGPU_CIK                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_DRM_AMDGPU_CIK                           note<'LP:1661887 for zesty'>
+
+CONFIG_DRM_BOCHS                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DRM_BOCHS                                note<'LP#1916290'>
+
+CONFIG_DRM_HISI_HIBMC                           policy<{'arm64': 'm'}>
+CONFIG_DRM_HISI_HIBMC                           note<'LP:1762940'>
+
+CONFIG_DRM_LEGACY                               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DRM_LEGACY                               note<'Consider re-enabling but not signing the modules'>
+
+CONFIG_DRM_MGAG200                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_DRM_MGAG200                              note<'LP#1693337'>
+
+CONFIG_DRM_STI                                  policy<{'armhf': 'n'}>
+CONFIG_DRM_STI                                  note<'LP#1398458'>
+
+CONFIG_DRM_VBOXVIDEO                            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_DRM_VBOXVIDEO                            note<'LP:1718679'>
+
+CONFIG_DVB_DUMMY_FE                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_DUMMY_FE                             note<'expert use only'>
+
+CONFIG_ECRYPT_FS                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ECRYPT_FS                                note<'not autoloadable'>
+
+CONFIG_EFIVAR_FS                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_EFIVAR_FS                                note<'needed for variable EFI update'>
+
+CONFIG_EFI_VARS                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_EFI_VARS                                 note<'EFI boot requirement (d-i) LP:#837332'>
+
+CONFIG_EVM                                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_EVM                                      note<'LP:1643652'>
+
+CONFIG_EVM_ATTR_FSUUID                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_EVM_ATTR_FSUUID                          note<'LP:1643652'>
+
+CONFIG_EVM_LOAD_X509                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_EVM_LOAD_X509                            note<'LP:1643652'>
+
+CONFIG_EVM_X509_PATH                            policy<{'ppc64el': '"/etc/keys/x509_evm.der"'}>
+CONFIG_EVM_X509_PATH                            note<'LP:1643652'>
+
+CONFIG_EXT2_FS                                  policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_EXT2_FS                                  note<'ext4 handling via EXT4_USE_FOR_EXT23'>
+
+CONFIG_EXT3_FS                                  policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_EXT3_FS                                  note<'ext4 handling via EXT4_USE_FOR_EXT23'>
+
+CONFIG_FA_DUMP                                  policy<{'ppc64el': 'y'}>
+CONFIG_FA_DUMP                                  note<'LP:1415562'>
+
+CONFIG_FHANDLE                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FHANDLE                                  note<'LP:1412543'>
+
+CONFIG_FUSE_FS                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FUSE_FS                                  note<'not autoloadable'>
+
+CONFIG_FW_LOADER_USER_HELPER_FALLBACK           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_FW_LOADER_USER_HELPER_FALLBACK           note<'LP#1398458'>
+
+CONFIG_GPIO_EM                                  policy<{'armhf': 'n'}>
+CONFIG_GPIO_EM                                  note<'h/w not encounted'>
+
+CONFIG_GPIO_TWL4030                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'y', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_TWL4030                             note<'LP:#921934'>
+
+CONFIG_HIBERNATION                              policy<{'amd64': 'y', 'arm64': 'n', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_HIBERNATION                              note<'LP:1867753'>
+
+CONFIG_HIO                                      policy<{'amd64': 'm', 'arm64': 'n', 'armhf': 'n', 'i386': 'm', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_HIO                                      note<'LP:1635594'>
+
+CONFIG_HIPPI                                    policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_HIPPI                                    note<'DEPRECATED'>
+
+CONFIG_HOTPLUG_PCI_PCIE                         policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_HOTPLUG_PCI_PCIE                         note<'LP#1374440'>
+
+CONFIG_HOTPLUG_PCI_SHPC                         policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_HOTPLUG_PCI_SHPC                         note<'LP#1374440'>
+
+CONFIG_HVC_UDBG                                 policy<{'ppc64el': 'n'}>
+CONFIG_HVC_UDBG                                 note<'LP#1680888'>
+
+CONFIG_I2C_CHARDEV                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'm'}>
+CONFIG_I2C_CHARDEV                              note<'LP:1417032'>
+
+CONFIG_IBMVNIC                                  policy<{'ppc64el': 'm'}>
+CONFIG_IBMVNIC                                  note<'LP:#1628187'>
+
+CONFIG_IDLE_PAGE_TRACKING                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IDLE_PAGE_TRACKING                       note<'is there a cost associated with this?'>
+
+CONFIG_IIO_SIMPLE_DUMMY_BUFFER                  policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_IIO_SIMPLE_DUMMY_BUFFER                  note<'dummy driver'>
+
+CONFIG_IIO_SIMPLE_DUMMY_EVENTS                  policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_IIO_SIMPLE_DUMMY_EVENTS                  note<'dummy driver'>
+
+CONFIG_IMA                                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IMA                                      note<'LP:1643652'>
+
+CONFIG_IMA_APPRAISE                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IMA_APPRAISE                             note<'LP:1643652'>
+
+CONFIG_IMA_ARCH_POLICY                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_IMA_ARCH_POLICY                          note<'LP:1866909'>
+
+CONFIG_IMA_DEFAULT_HASH_SHA256                  policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_IMA_DEFAULT_HASH_SHA256                  note<'LP:1643652'>
+
+CONFIG_IMA_KEXEC                                policy<{'ppc64el': 'y'}>
+CONFIG_IMA_KEXEC                                note<'LP:1643652'>
+
+CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY note<'LP:1667490'>
+
+CONFIG_IMA_READ_POLICY                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_IMA_READ_POLICY                          note<'LP:1866909'>
+
+CONFIG_IMA_SIG_TEMPLATE                         policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_IMA_SIG_TEMPLATE                         note<'LP:1643652'>
+
+CONFIG_IMA_WRITE_POLICY                         policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_IMA_WRITE_POLICY                         note<'LP:1667490'>
+
+CONFIG_INPUT_UINPUT                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_INPUT_UINPUT                             note<'LP:584812'>
+
+CONFIG_INTEGRITY_PLATFORM_KEYRING               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_INTEGRITY_PLATFORM_KEYRING               note<'Required for lockdown'>
+
+CONFIG_INTEL_IOMMU_DEFAULT_ON                   policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_INTEL_IOMMU_DEFAULT_ON                   note<'the IOMMU can trigger boot failures'>
+
+CONFIG_IOMMU_DEBUGFS                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_IOMMU_DEBUGFS                            note<'Should not be enabled in production, LP #1861057'>
+
+CONFIG_IPDDP                                    policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_IPDDP                                    note<'LP:1559772'>
+
+CONFIG_IPMMU_VMSA                               policy<{'arm64': 'n', 'armhf': 'y'}>
+CONFIG_IPMMU_VMSA                               note<'LP:1718734'>
+
+CONFIG_IPV6                                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IPV6                                     note<'if this is a module we get a module load for every ipv6 packet'>
+
+CONFIG_IP_PNP                                   policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_IP_PNP                                   note<'LP:1259861'>
+
+CONFIG_ISM                                      policy<{'s390x': 'm'}>
+CONFIG_ISM                                      note<'LP:1789934'>
+
+CONFIG_KEXEC_BZIMAGE_VERIFY_SIG                 policy<{'amd64': 'y'}>
+CONFIG_KEXEC_BZIMAGE_VERIFY_SIG                 note<'Q: check this is in sync with the kexec/kdump userspace'>
+
+CONFIG_KGDB_SERIAL_CONSOLE                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_KGDB_SERIAL_CONSOLE                      note<'early debugging support'>
+
+CONFIG_KVM                                      policy<{'amd64': 'm', 'arm64': 'y', 'armhf-generic-lpae': 'y', 'i386': 'm', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_KVM                                      note<'LP:1532886'>
+
+CONFIG_LATENCYTOP                               policy<{'amd64-generic': 'n', 'amd64-lowlatency': 'y', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_LATENCYTOP                               note<'https://lists.ubuntu.com/archives/kernel-team/2014-July/045006.html, LP#1655986'>
+
+CONFIG_LOAD_PPC_KEYS                            policy<{'ppc64el': 'y'}>
+CONFIG_LOAD_PPC_KEYS                            note<'LP:1866909'>
+
+CONFIG_LOCALVERSION_AUTO                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_LOCALVERSION_AUTO                        note<'triggers packaging failures'>
+
+CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE            policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE            note<'LP:1709171 LP:1848492'>
+
+CONFIG_MFD_SM501                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'y', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MFD_SM501                                note<'boot essential on OMAP4'>
+
+CONFIG_MFD_TPS65217                             policy<{'arm64': 'm', 'armhf': 'y', 'ppc64el': 'n'}>
+CONFIG_MFD_TPS65217                             note<'boot essential on AM335x'>
+
+CONFIG_MMC_BLOCK                                policy<{'amd64': 'm', 'arm64': 'y', 'armhf': 'y', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MMC_BLOCK                                note<'boot essential on armhf/arm64'>
+
+CONFIG_MMC_OMAP_HS                              policy<{'armhf': 'y'}>
+CONFIG_MMC_OMAP_HS                              note<'boot essential on arm'>
+
+CONFIG_MMC_SDHCI                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'y', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MMC_SDHCI                                note<'installation essential on omap/highbank'>
+
+CONFIG_MMC_SDHCI_PLTFM                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'y', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MMC_SDHCI_PLTFM                          note<'boot essential on highbank'>
+
+CONFIG_MODIFY_LDT_SYSCALL                       policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_MODIFY_LDT_SYSCALL                       note<'Q: check this with security'>
+
+CONFIG_MODVERSIONS                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MODVERSIONS                              note<'LP:1898716 -- required as we have a livepatch/drivers modules signing key'>
+
+CONFIG_MOUSE_INPORT                             policy<{'i386': 'n'}>
+CONFIG_MOUSE_INPORT                             note<'very old ISA based mouse support'>
+
+CONFIG_MTD                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'y', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MTD                                      note<'boot essential on arm'>
+
+CONFIG_MTD_BLOCK                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'y', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_BLOCK                                note<'boot essential on arm'>
+
+CONFIG_MTD_DOCG3                                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_MTD_DOCG3                                note<'LP:1792205'>
+
+CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE             note<'can be enabled at runtime'>
+
+CONFIG_MTD_NAND_OMAP2                           policy<{'armhf': 'y'}>
+CONFIG_MTD_NAND_OMAP2                           note<'boot essential on arm'>
+
+CONFIG_MTD_NAND_OMAP_BCH                        policy<{'armhf': 'y'}>
+CONFIG_MTD_NAND_OMAP_BCH                        note<'boot essential on arm'>
+
+CONFIG_MTD_OF_PARTS                             policy<{'arm64': 'm', 'armhf': 'y', 'ppc64el': 'm'}>
+CONFIG_MTD_OF_PARTS                             note<'boot essential on arm'>
+
+CONFIG_MTD_ONENAND_VERIFY_WRITE                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MTD_ONENAND_VERIFY_WRITE                 note<'writes here are not checked in full without'>
+
+CONFIG_MTD_RAW_NAND                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'y', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_RAW_NAND                             note<'boot essential on arm'>
+
+CONFIG_NETWORK_PHY_TIMESTAMPING                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NETWORK_PHY_TIMESTAMPING                 note<'LP:1785816'>
+
+CONFIG_NET_9P                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_9P                                   note<'LP:1557994'>
+
+CONFIG_NET_DROP_MONITOR                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_DROP_MONITOR                         note<'LP #1660634'>
+
+CONFIG_NET_SWITCHDEV                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_SWITCHDEV                            note<'LP: #1865452, updated to y for s390x starting with focal'>
+
+CONFIG_NET_VENDOR_EMULEX                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_EMULEX                        note<'LP:1543165'>
+
+CONFIG_NLS                                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NLS                                      note<'dependancy of boot essential'>
+
+CONFIG_NOP_USB_XCEIV                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'y', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NOP_USB_XCEIV                            note<'boot essential on omap/highbank'>
+
+CONFIG_NOUVEAU_LEGACY_CTX_SUPPORT               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_NOUVEAU_LEGACY_CTX_SUPPORT               note<'Selects CONFIG_DRM_LEGACY which is not wanted'>
+
+CONFIG_NO_HZ_IDLE                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NO_HZ_IDLE                               note<'LP:1413968'>
+
+CONFIG_NR_CPUS                                  policy<{'amd64': '8192', 'arm64': '256', 'armhf': '4', 'i386': '8', 'ppc64el': '2048', 's390x': '512'}>
+CONFIG_NR_CPUS                                  note<'LP:1864198'>
+
+CONFIG_NUMA                                     policy<{'amd64': 'y', 'arm64': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NUMA                                     note<'LP:1543165 LP:1557690'>
+
+CONFIG_NUMA_BALANCING_DEFAULT_ENABLED           policy<{'amd64': 'y', 'arm64': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NUMA_BALANCING_DEFAULT_ENABLED           note<'LP:1557690'>
+
+CONFIG_NUMA_EMU                                 policy<{'amd64': 'n', 's390x': 'n'}>
+CONFIG_NUMA_EMU                                 note<'LP:1864198'>
+
+CONFIG_NVMEM                                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NVMEM                                    note<'Q: is this appropriate for s390x LP:1543165'>
+
+CONFIG_NVRAM                                    policy<{'amd64': 'm', 'i386': 'm', 'ppc64el': 'y'}>
+CONFIG_NVRAM                                    note<'LP#1837726'>
+
+CONFIG_N_GSM                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_N_GSM                                    note<'LP#1404670'>
+
+CONFIG_PAGE_POISONING                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PAGE_POISONING                           note<'LP:1783651'>
+
+CONFIG_PAGE_POISONING_NO_SANITY                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PAGE_POISONING_NO_SANITY                 note<'LP:1783651'>
+
+CONFIG_PAGE_POISONING_ZERO                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PAGE_POISONING_ZERO                      note<'LP:1783651'>
+
+CONFIG_PANIC_ON_OOPS                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_PANIC_ON_OOPS                            note<'keep working if at all possible'>
+
+CONFIG_PATA_HPT3X3_DMA                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_PATA_HPT3X3_DMA                          note<'DMA mode is documented problematic'>
+
+CONFIG_PCIEASPM_DEFAULT                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_PCIEASPM_DEFAULT                         note<'LP#1398544'>
+
+CONFIG_PCIEPORTBUS                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'n', 's390x': 'y'}>
+CONFIG_PCIEPORTBUS                              note<'LP#1665404'>
+
+CONFIG_PCI_NR_FUNCTIONS                         policy<{'s390x': '512'}>
+CONFIG_PCI_NR_FUNCTIONS                         note<'LP:1866056'>
+
+CONFIG_PINCTRL_CHERRYVIEW                       policy<{'amd64': 'y', 'i386': 'm'}>
+CONFIG_PINCTRL_CHERRYVIEW                       note<'LP #1630238'>
+
+CONFIG_PM                                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_PM                                       note<'LP:1867753'>
+
+CONFIG_PPC_MEM_KEYS                             policy<{'ppc64el': 'n'}>
+CONFIG_PPC_MEM_KEYS                             note<'LP:1776967'>
+
+CONFIG_PPC_RTAS_FILTER                          policy<{'ppc64el': 'y'}>
+CONFIG_PPC_RTAS_FILTER                          note<'CVE-2020-27777'>
+
+CONFIG_PPC_SECURE_BOOT                          policy<{'ppc64el': 'y'}>
+CONFIG_PPC_SECURE_BOOT                          note<'LP:1855668'>
+
+CONFIG_PPC_SECVAR_SYSFS                         policy<{'ppc64el': 'y'}>
+CONFIG_PPC_SECVAR_SYSFS                         note<'LP:1866909'>
+
+CONFIG_PREEMPT_NONE                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'y'}>
+CONFIG_PREEMPT_NONE                             note<'LP:1543165'>
+
+CONFIG_PSI_DEFAULT_DISABLED                     policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'y'}>
+CONFIG_PSI_DEFAULT_DISABLED                     note<'LP: #1876044'>
+
+CONFIG_QCOM_QDF2400_ERRATUM_0065                policy<{'arm64': 'y'}>
+CONFIG_QCOM_QDF2400_ERRATUM_0065                note<'LP:1672486'>
+
+CONFIG_REGULATOR_FIXED_VOLTAGE                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'y', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_FIXED_VOLTAGE                  note<'boot essential on arm'>
+
+CONFIG_REGULATOR_TPS65217                       policy<{'arm64': 'm', 'armhf': 'y'}>
+CONFIG_REGULATOR_TPS65217                       note<'boot essential on AM335x'>
+
+CONFIG_REGULATOR_TWL4030                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf-generic': 'y', 'armhf-generic-lpae': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_TWL4030                        note<'boot requisite for omap4'>
+
+CONFIG_RTC_DRV_CMOS                             policy<{'amd64': 'y', 'armhf': 'm', 'i386': 'y', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_CMOS                             note<'boot essential on i386/amd64'>
+
+CONFIG_RTC_DRV_EFI                              policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_RTC_DRV_EFI                              note<'LP:#1583738'>
+
+CONFIG_RTC_DRV_TWL4030                          policy<{'arm64': 'm', 'armhf': 'y', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_TWL4030                          note<'boot essential on OMAP3/OMAP4'>
+
+CONFIG_RT_GROUP_SCHED                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_RT_GROUP_SCHED                           note<'LP#1875665'>
+
+CONFIG_SAMPLE_TRACE_PRINTK                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_SAMPLE_TRACE_PRINTK                      note<'Required for ftrace selftests'>
+
+CONFIG_SATA_AHCI_PLATFORM                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'y', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SATA_AHCI_PLATFORM                       note<'boot essential on highbank'>
+
+CONFIG_SATA_HIGHBANK                            policy<{'armhf': 'y'}>
+CONFIG_SATA_HIGHBANK                            note<'LP:1703430'>
+
+CONFIG_SCLP_OFB                                 policy<{'s390x': 'y'}>
+CONFIG_SCLP_OFB                                 note<'LP:1787898'>
+
+CONFIG_SCSI_IPR_DUMP                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SCSI_IPR_DUMP                            note<'LP:1343109'>
+
+CONFIG_SCSI_IPR_TRACE                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SCSI_IPR_TRACE                           note<'LP:1343109'>
+
+CONFIG_SCSI_VIRTIO                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_SCSI_VIRTIO                              note<'tech preview of new feature'>
+
+CONFIG_SECURITY_SAFESETID                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SECURITY_SAFESETID                       note<'LP:#1845391'>
+
+CONFIG_SECURITY_SELINUX_DISABLE                 policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_SECURITY_SELINUX_DISABLE                 note<'LP#1680315'>
+
+CONFIG_SERIAL_DEV_BUS                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SERIAL_DEV_BUS                           note<'LP:1739939'>
+
+CONFIG_SERIAL_DEV_CTRL_TTYPORT                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SERIAL_DEV_CTRL_TTYPORT                  note<'LP:1739939'>
+
+CONFIG_SERIAL_SH_SCI                            policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_SERIAL_SH_SCI                            note<'LP: #2022361'>
+
+CONFIG_SERIAL_SH_SCI_CONSOLE                    policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_SERIAL_SH_SCI_CONSOLE                    note<'LP: #2022361'>
+
+CONFIG_SERIAL_SH_SCI_EARLYCON                   policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_SERIAL_SH_SCI_EARLYCON                   note<'LP: #2022361'>
+
+CONFIG_SETEND_EMULATION                         policy<{'arm64': 'y'}>
+CONFIG_SETEND_EMULATION                         note<'LP:1545542'>
+
+CONFIG_SMC                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_SMC                                      note<'LP:1789934'>
+
+CONFIG_SMC_DIAG                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_SMC_DIAG                                 note<'LP:1789934'>
+
+CONFIG_SND                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'y', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND                                      note<'not autoloadable on omap'>
+
+CONFIG_SND_HDA_POWER_SAVE_DEFAULT               policy<{'amd64': '1', 'arm64': '1', 'armhf': '1', 'i386': '1', 'ppc64el': '1'}>
+CONFIG_SND_HDA_POWER_SAVE_DEFAULT               note<'LP:1804265'>
+
+CONFIG_SND_HDA_RECONFIG                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SND_HDA_RECONFIG                         note<'allows fixes to be tested live'>
+
+CONFIG_SND_PCM_OSS                              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_SND_PCM_OSS                              note<'deprecated in favour of pulseaudio emulation'>
+
+CONFIG_SND_SOC                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'y', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC                                  note<'not autoloadable on omap'>
+
+CONFIG_SND_SOC_AMD_RENOIR                       policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_AMD_RENOIR                       note<'LP:1881046'>
+
+CONFIG_SND_SOC_AMD_RENOIR_MACH                  policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_AMD_RENOIR_MACH                  note<'LP:1881046'>
+
+CONFIG_SND_SOC_INTEL_CFL                        policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_SND_SOC_INTEL_CFL                        note<'deprecated'>
+
+CONFIG_SND_SOC_INTEL_CML_H                      policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_SND_SOC_INTEL_CML_H                      note<'deprecated'>
+
+CONFIG_SND_SOC_INTEL_CML_LP                     policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_SND_SOC_INTEL_CML_LP                     note<'deprecated'>
+
+CONFIG_SND_SOC_INTEL_CNL                        policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_SND_SOC_INTEL_CNL                        note<'deprecated'>
+
+CONFIG_SND_SOC_INTEL_SKYLAKE                    policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_SND_SOC_INTEL_SKYLAKE                    note<'deprecated'>
+
+CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC      policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC      note<'deprecated'>
+
+CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC              policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC              note<'LP:1848490'>
+
+CONFIG_SND_SOC_SOF_HDA_COMMON_HDMI_CODEC        policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_SND_SOC_SOF_HDA_COMMON_HDMI_CODEC        note<'LP:#1855666'>
+
+CONFIG_SND_SOC_SOF_HDA_LINK                     policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_SND_SOC_SOF_HDA_LINK                     note<'LP:1848490'>
+
+CONFIG_SND_SOC_SOF_NOCODEC_SUPPORT              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_SND_SOC_SOF_NOCODEC_SUPPORT              note<'LP:1848490'>
+
+CONFIG_SOUND                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'y', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SOUND                                    note<'not autoloadable on omap'>
+
+CONFIG_SOUNDWIRE                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SOUNDWIRE                                note<'LP:1855685'>
+
+CONFIG_SOUND_OSS_CORE_PRECLAIM                  policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_SOUND_OSS_CORE_PRECLAIM                  note<'LP#1105230 LP#1385510'>
+
+CONFIG_SPI_INTEL_SPI_PCI                        policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_SPI_INTEL_SPI_PCI                        note<'LP:1734147'>
+
+CONFIG_SPI_INTEL_SPI_PLATFORM                   policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_SPI_INTEL_SPI_PLATFORM                   note<'LP:1734147'>
+
+CONFIG_SQUASHFS                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SQUASHFS                                 note<'LP#1593134'>
+
+CONFIG_SQUASHFS_4K_DEVBLK_SIZE                  policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_SQUASHFS_4K_DEVBLK_SIZE                  note<'non-default block size'>
+
+CONFIG_STACK_VALIDATION                         policy<{'amd64': 'y'}>
+CONFIG_STACK_VALIDATION                         note<'needed for livepatch'>
+
+CONFIG_SWP_EMULATION                            policy<{'arm64': 'y'}>
+CONFIG_SWP_EMULATION                            note<'LP:1545542'>
+
+CONFIG_SYSFS_DEPRECATED                         policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_SYSFS_DEPRECATED                         note<'ensure nothing is using these deprecated interfaces'>
+
+CONFIG_TCG_TIS_I2C_ATMEL                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_TCG_TIS_I2C_ATMEL                        note<'LP:1643652'>
+
+CONFIG_TCG_TIS_I2C_INFINEON                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_TCG_TIS_I2C_INFINEON                     note<'LP:1643652'>
+
+CONFIG_TCG_TIS_I2C_NUVOTON                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_TCG_TIS_I2C_NUVOTON                      note<'LP:1643652'>
+
+CONFIG_TCG_TPM                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_TCG_TPM                                  note<'needed for early validation'>
+
+CONFIG_TEST_BLACKHOLE_DEV                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_TEST_BLACKHOLE_DEV                       note<'Used by net selftests'>
+
+CONFIG_TMPFS_POSIX_ACL                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_TMPFS_POSIX_ACL                          note<'some /dev nodes require POSIX ACLs, like /dev/dsp'>
+
+CONFIG_TOUCHSCREEN_ELAN                         policy<{'amd64': 'y', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_ELAN                         note<'LP #1630238'>
+
+CONFIG_UNWINDER_FRAME_POINTER                   policy<{'amd64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_UNWINDER_FRAME_POINTER                   note<'needed for livepatch'>
+
+CONFIG_USB_EHCI_HCD                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_EHCI_HCD                             note<'ensures USB 2.0/1.1 probe ordering'>
+
+CONFIG_USB_EHCI_HCD_PLATFORM                    policy<{'amd64': 'y', 'arm64': 'm', 'armhf': 'n', 'i386': 'y', 'ppc64el': 'm'}>
+CONFIG_USB_EHCI_HCD_PLATFORM                    note<'Dont use the generic ehci/ohci code on omap, it doesnt work'>
+
+CONFIG_USB_HCD_BCMA                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'n', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_HCD_BCMA                             note<'USB_{O,E}HCI_HCD_PLATFORM must be off on omap'>
+
+CONFIG_USB_HCD_SSB                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'n', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_HCD_SSB                              note<'USB_{O,E}HCI_HCD_PLATFORM must be off on omap'>
+
+CONFIG_USB_M66592                               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_USB_M66592                               note<'gadget device'>
+
+CONFIG_USB_MUSB_HDRC                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'y', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_MUSB_HDRC                            note<'not autoloadable on omap'>
+
+CONFIG_USB_OHCI_HCD                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_OHCI_HCD                             note<'ensures USB 2.0/1.1 probe ordering'>
+
+CONFIG_USB_OTG                                  policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_USB_OTG                                  note<'triggers breakage on x86 LP:1047527, LP:1411295'>
+
+CONFIG_USB_OTG_BLACKLIST_HUB                    policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_USB_OTG_BLACKLIST_HUB                    note<'OTG white/blacklists are disabled'>
+
+CONFIG_USB_OTG_WHITELIST                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_USB_OTG_WHITELIST                        note<'OTG white/blacklists are disabled'>
+
+CONFIG_USB_SERIAL_DEBUG                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_DEBUG                         note<'not actually debug'>
+
+CONFIG_USB_UHCI_HCD                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_UHCI_HCD                             note<'ensures USB 2.0/1.1 probe ordering'>
+
+CONFIG_USB_XHCI_DBGCAP                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_XHCI_DBGCAP                          note<'LP:1730832'>
+
+CONFIG_USB_XHCI_HCD                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_XHCI_HCD                             note<'ensures USB 2.0/1.1 probe ordering'>
+
+CONFIG_VBOXGUEST                                policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_VBOXGUEST                                note<'LP:1796647'>
+
+CONFIG_VFAT_FS                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_VFAT_FS                                  note<'needed on arm to ensure we can write the kernel when replacing'>
+
+CONFIG_VFIO                                     policy<{'amd64': 'y', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'y', 's390x': 'm'}>
+CONFIG_VFIO                                     note<'LP#1636733'>
+
+CONFIG_VFIO_PCI                                 policy<{'amd64': 'y', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'y', 's390x': 'm'}>
+CONFIG_VFIO_PCI                                 note<'LP#1636733'>
+
+CONFIG_VIDEO_VIMC                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_VIMC                               note<'LP#1831482'>
+
+CONFIG_VIRTIO_BLK                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_VIRTIO_BLK                               note<'KVM paravirt support -- not autoloadable'>
+
+CONFIG_VIRTIO_MMIO                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_VIRTIO_MMIO                              note<'LP:1557689'>
+
+CONFIG_VIRTIO_NET                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_VIRTIO_NET                               note<'KVM paravirt support -- not autoloadable'>
+
+CONFIG_X509_CERTIFICATE_PARSER                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_X509_CERTIFICATE_PARSER                  note<'module signing'>
+
+CONFIG_X86_ACPI_CPUFREQ                         policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_ACPI_CPUFREQ                         note<'not autoloadable'>
+
+CONFIG_X86_CPUFREQ_NFORCE2                      policy<{'i386': 'y'}>
+CONFIG_X86_CPUFREQ_NFORCE2                      note<'not autoloadable'>
+
+CONFIG_X86_LEGACY_VM86                          policy<{'i386': 'y'}>
+CONFIG_X86_LEGACY_VM86                          note<'LP:1499089'>
+
+CONFIG_X86_PCC_CPUFREQ                          policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_PCC_CPUFREQ                          note<'not autoloadable'>
+
+CONFIG_X86_POWERNOW_K8                          policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_POWERNOW_K8                          note<'not autoloadable'>
+
+CONFIG_X86_SPEEDSTEP_CENTRINO                   policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_SPEEDSTEP_CENTRINO                   note<'not autoloadable'>
+
+CONFIG_X86_SPEEDSTEP_ICH                        policy<{'i386': 'y'}>
+CONFIG_X86_SPEEDSTEP_ICH                        note<'not autoloadable'>
+
+CONFIG_X86_SPEEDSTEP_SMI                        policy<{'i386': 'y'}>
+CONFIG_X86_SPEEDSTEP_SMI                        note<'not autoloadable'>
+
+CONFIG_X86_UV                                   policy<{'amd64': 'y'}>
+CONFIG_X86_UV                                   note<'LP:1863810'>
+
+CONFIG_XEN_512GB                                policy<{'amd64': 'y'}>
+CONFIG_XEN_512GB                                note<'Q: is this related to the utlemming questions on memory size?'>
+
+CONFIG_XEN_ACPI_PROCESSOR                       policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_XEN_ACPI_PROCESSOR                       note<'boot essential on XEN host'>
+
+CONFIG_XEN_BLKDEV_FRONTEND                      policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_XEN_BLKDEV_FRONTEND                      note<'not autoloadable -- XEN paravirt support'>
+
+CONFIG_XEN_NETDEV_FRONTEND                      policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_XEN_NETDEV_FRONTEND                      note<'not autoloadable -- XEN paravirt support'>
+
+CONFIG_XZ_DEC                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_XZ_DEC                                   note<'boot essential -- initramfs decompressor'>
+
+CONFIG_ZCRYPT_MULTIDEVNODES                     policy<{'s390x': 'y'}>
+CONFIG_ZCRYPT_MULTIDEVNODES                     note<'LP:1805429'>
+
+CONFIG_ZLIB_DFLTCC                              policy<{'s390x': 'y'}>
+CONFIG_ZLIB_DFLTCC                              note<'LP:1830208'>
+
+CONFIG_ZONE_DMA                                 policy<{'amd64': 'y', 'armhf-generic-lpae': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_ZONE_DMA                                 note<'LP:1628523'>
+
+
+# ---- Annotations without notes ----
+
+CONFIG_104_QUAD_8                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_3C515                                    policy<{'i386': 'm'}>
+CONFIG_60XX_WDT                                 policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_64BIT                                    policy<{'amd64': 'y', 'arm64': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_64BIT_TIME                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_6LOWPAN                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_6LOWPAN_DEBUGFS                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_6LOWPAN_GHC_EXT_HDR_DEST                 policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG                 policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_6LOWPAN_GHC_EXT_HDR_HOP                  policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_6LOWPAN_GHC_ICMPV6                       policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_6LOWPAN_GHC_UDP                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_6LOWPAN_NHC                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_6LOWPAN_NHC_DEST                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_6LOWPAN_NHC_FRAGMENT                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_6LOWPAN_NHC_HOP                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_6LOWPAN_NHC_IPV6                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_6LOWPAN_NHC_MOBILITY                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_6LOWPAN_NHC_ROUTING                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_6LOWPAN_NHC_UDP                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_6PACK                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_8139CP                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_8139TOO                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_8139TOO_8129                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_8139TOO_PIO                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_8139TOO_TUNE_TWISTER                     policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_8139_OLD_RX_RESET                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_842_COMPRESS                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_842_DECOMPRESS                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_88EU_AP_MODE                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_9P_FS                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_9P_FSCACHE                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_9P_FS_POSIX_ACL                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_9P_FS_SECURITY                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_AB3100_CORE                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_AB3100_OTP                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ABP060MG                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ABX500_CORE                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_AC97_BUS                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'y', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ACCESSIBILITY                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_ACENIC                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ACENIC_OMIT_TIGON_I                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_ACERHDF                                  policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_ACER_WIRELESS                            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_ACER_WMI                                 policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_ACORN_PARTITION                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_ACPI                                     policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_ACPI_AC                                  policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_ACPI_ADXL                                policy<{'amd64': 'y'}>
+CONFIG_ACPI_ALS                                 policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_ACPI_APEI                                policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_ACPI_APEI_EINJ                           policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_ACPI_APEI_ERST_DEBUG                     policy<{'amd64': 'n', 'arm64': 'n', 'i386': 'n'}>
+CONFIG_ACPI_APEI_GHES                           policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_ACPI_APEI_MEMORY_FAILURE                 policy<{'amd64': 'y', 'arm64': 'y'}>
+CONFIG_ACPI_APEI_PCIEAER                        policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_ACPI_APEI_SEA                            policy<{'arm64': 'y'}>
+CONFIG_ACPI_BATTERY                             policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_ACPI_BGRT                                policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_ACPI_BUTTON                              policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_ACPI_CCA_REQUIRED                        policy<{'arm64': 'y'}>
+CONFIG_ACPI_CMPC                                policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_ACPI_CONFIGFS                            policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_ACPI_CONTAINER                           policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_ACPI_CPPC_CPUFREQ                        policy<{'arm64': 'm'}>
+CONFIG_ACPI_CPPC_LIB                            policy<{'amd64': 'y', 'arm64': 'y'}>
+CONFIG_ACPI_CPU_FREQ_PSS                        policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_ACPI_DEBUG                               policy<{'amd64': 'y', 'arm64': 'n', 'i386': 'n'}>
+CONFIG_ACPI_DEBUGGER                            policy<{'amd64': 'y', 'arm64': 'n', 'i386': 'n'}>
+CONFIG_ACPI_DEBUGGER_USER                       policy<{'amd64': 'y'}>
+CONFIG_ACPI_DOCK                                policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_ACPI_EC_DEBUGFS                          policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_ACPI_EXTLOG                              policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_ACPI_FAN                                 policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_ACPI_GENERIC_GSI                         policy<{'arm64': 'y'}>
+CONFIG_ACPI_GTDT                                policy<{'arm64': 'y'}>
+CONFIG_ACPI_HED                                 policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_ACPI_HMAT                                policy<{'amd64': 'y', 'arm64': 'y'}>
+CONFIG_ACPI_HOTPLUG_CPU                         policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_ACPI_HOTPLUG_IOAPIC                      policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_ACPI_HOTPLUG_MEMORY                      policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_ACPI_I2C_OPREGION                        policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_ACPI_IORT                                policy<{'arm64': 'y'}>
+CONFIG_ACPI_IPMI                                policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_ACPI_LEGACY_TABLES_LOOKUP                policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_ACPI_LPIT                                policy<{'amd64': 'y'}>
+CONFIG_ACPI_MCFG                                policy<{'arm64': 'y'}>
+CONFIG_ACPI_NFIT                                policy<{'amd64': 'm', 'arm64': 'm'}>
+CONFIG_ACPI_NUMA                                policy<{'amd64': 'y', 'arm64': 'y'}>
+CONFIG_ACPI_PCI_SLOT                            policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_ACPI_PPTT                                policy<{'arm64': 'y'}>
+CONFIG_ACPI_PROCESSOR                           policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_ACPI_PROCESSOR_AGGREGATOR                policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_ACPI_PROCESSOR_CSTATE                    policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_ACPI_PROCESSOR_IDLE                      policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_ACPI_PROCFS_POWER                        policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_ACPI_REDUCED_HARDWARE_ONLY               policy<{'amd64': 'n', 'arm64': 'y', 'i386': 'n'}>
+CONFIG_ACPI_REV_OVERRIDE_POSSIBLE               policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_ACPI_SBS                                 policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_ACPI_SLEEP                               policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_ACPI_SPCR_TABLE                          policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT         policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_ACPI_TABLE_UPGRADE                       policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_ACPI_TAD                                 policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_ACPI_THERMAL                             policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_ACPI_THERMAL_REL                         policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_ACPI_TOSHIBA                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_ACPI_VIDEO                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_ACPI_WATCHDOG                            policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_ACPI_WMI                                 policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_ACQUIRE_WDT                              policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_ACRN_GUEST                               policy<{'amd64': 'y'}>
+CONFIG_AD2S1200                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD2S1210                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD2S90                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD5064                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD525X_DPOT                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_AD525X_DPOT_I2C                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD525X_DPOT_SPI                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD5272                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD5360                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD5380                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD5421                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD5446                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD5449                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD5504                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD5592R                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD5592R_BASE                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD5593R                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD5624R_SPI                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD5686                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD5686_SPI                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD5696_I2C                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD5755                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD5758                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD5761                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD5764                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD5791                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD5933                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD7124                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD7150                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD7192                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD7266                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD7280                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD7291                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD7298                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD7303                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD7476                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD7606                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD7606_IFACE_PARALLEL                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD7606_IFACE_SPI                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD7746                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD7766                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD7768_1                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD7780                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD7791                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD7793                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD7816                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD7887                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD7923                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD7949                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD799X                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD8366                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD8801                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD9523                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD9832                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD9834                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ADAPTEC_STARFIRE                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ADE7854                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ADE7854_I2C                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ADE7854_SPI                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ADF4350                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ADF4371                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ADFS_FS                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_ADFS_FS_RW                               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_ADIN_PHY                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_ADIS16080                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ADIS16130                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ADIS16136                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ADIS16201                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ADIS16203                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ADIS16209                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ADIS16240                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ADIS16260                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ADIS16400                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ADIS16460                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ADIS16480                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ADJD_S311                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ADM8211                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ADT7316                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ADT7316_I2C                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ADT7316_SPI                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ADVANTECH_WDT                            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_ADVISE_SYSCALLS                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ADXL372                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ADXL372_I2C                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ADXL372_SPI                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ADXRS450                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AD_SIGMA_DELTA                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AEABI                                    policy<{'armhf': 'y'}>
+CONFIG_AFE4403                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AFE4404                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AFFS_FS                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_AFIUCV                                   policy<{'s390x': 'm'}>
+CONFIG_AFS_DEBUG                                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_AFS_DEBUG_CURSOR                         policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_AFS_FS                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_AFS_FSCACHE                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_AF_KCM                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_AF_RXRPC                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_AF_RXRPC_DEBUG                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_AF_RXRPC_INJECT_LOSS                     policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_AF_RXRPC_IPV6                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_AGP_ALI                                  policy<{'i386': 'm'}>
+CONFIG_AGP_AMD                                  policy<{'i386': 'y'}>
+CONFIG_AGP_AMD64                                policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_AGP_ATI                                  policy<{'i386': 'm'}>
+CONFIG_AGP_EFFICEON                             policy<{'i386': 'm'}>
+CONFIG_AGP_INTEL                                policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_AGP_NVIDIA                               policy<{'i386': 'y'}>
+CONFIG_AGP_SIS                                  policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_AGP_SWORKS                               policy<{'i386': 'm'}>
+CONFIG_AGP_VIA                                  policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_AHC1EC0_WDT                              policy<{'amd64': 'm'}>
+CONFIG_AHCI_BRCM                                policy<{'arm64': 'm'}>
+CONFIG_AHCI_CEVA                                policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_AHCI_DM816                               policy<{'armhf': 'm'}>
+CONFIG_AHCI_IMX                                 policy<{'arm64': 'y', 'armhf-generic': 'y'}>
+CONFIG_AHCI_MTK                                 policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_AHCI_MVEBU                               policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_AHCI_QORIQ                               policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_AHCI_SUNXI                               policy<{'arm64': 'n'}>
+CONFIG_AHCI_TEGRA                               policy<{'armhf-generic': 'm'}>
+CONFIG_AHCI_XGENE                               policy<{'arm64': 'm'}>
+CONFIG_AIC79XX_CMDS_PER_DEVICE                  policy<{'amd64': '32', 'arm64': '32', 'armhf': '32', 'i386': '32', 'ppc64el': '32'}>
+CONFIG_AIC79XX_DEBUG_ENABLE                     policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_AIC79XX_DEBUG_MASK                       policy<{'amd64': '0', 'arm64': '0', 'armhf': '0', 'i386': '0', 'ppc64el': '0'}>
+CONFIG_AIC79XX_REG_PRETTY_PRINT                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_AIC79XX_RESET_DELAY_MS                   policy<{'amd64': '5000', 'arm64': '5000', 'armhf': '5000', 'i386': '5000', 'ppc64el': '5000'}>
+CONFIG_AIC7XXX_CMDS_PER_DEVICE                  policy<{'amd64': '8', 'arm64': '8', 'armhf': '8', 'i386': '8', 'ppc64el': '8'}>
+CONFIG_AIC7XXX_DEBUG_ENABLE                     policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_AIC7XXX_DEBUG_MASK                       policy<{'amd64': '0', 'arm64': '0', 'armhf': '0', 'i386': '0', 'ppc64el': '0'}>
+CONFIG_AIC7XXX_REG_PRETTY_PRINT                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_AIC7XXX_RESET_DELAY_MS                   policy<{'amd64': '5000', 'arm64': '5000', 'armhf': '5000', 'i386': '5000', 'ppc64el': '5000'}>
+CONFIG_AIC94XX_DEBUG                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_AIO                                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_AIRO                                     policy<{'amd64': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AIRO_CS                                  policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_AIX_PARTITION                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_AK09911                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AK8974                                   policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_AK8975                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AL3320A                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ALIENWARE_WMI                            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_ALIGNMENT_TRAP                           policy<{'armhf': 'y'}>
+CONFIG_ALIM1535_WDT                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_ALIM7101_WDT                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_ALIX                                     policy<{'i386': 'y'}>
+CONFIG_ALLOW_DEV_COREDUMP                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ALPINE_MSI                               policy<{'armhf': 'y'}>
+CONFIG_ALTERA_FREEZE_BRIDGE                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ALTERA_MBOX                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ALTERA_MSGDMA                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ALTERA_PR_IP_CORE                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_ALTERA_PR_IP_CORE_PLAT                   policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_ALTERA_STAPL                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_ALTERA_TSE                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_ALTIVEC                                  policy<{'ppc64el': 'y'}>
+CONFIG_ALX                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AL_FIC                                   policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_AM2315                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AM335X_CONTROL_USB                       policy<{'armhf': 'm'}>
+CONFIG_AM335X_PHY_USB                           policy<{'armhf': 'm'}>
+CONFIG_AMBA_PL08X                               policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_AMD8111_ETH                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AMD_IOMMU                                policy<{'amd64': 'y'}>
+CONFIG_AMD_IOMMU_V2                             policy<{'amd64': 'm'}>
+CONFIG_AMD_MEM_ENCRYPT                          policy<{'amd64': 'y'}>
+CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT        policy<{'amd64': 'n'}>
+CONFIG_AMD_NB                                   policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_AMD_NUMA                                 policy<{'amd64': 'y'}>
+CONFIG_AMD_PHY                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_AMD_XGBE                                 policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_AMD_XGBE_DCB                             policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_AMD_XGBE_HAVE_ECC                        policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_AMIGA_PARTITION                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_AMILO_RFKILL                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_ANDROID                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_ANDROID_BINDERFS                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ANDROID_BINDER_DEVICES                   policy<{'amd64': '""', 'arm64': '""', 'armhf': '""', 'i386': '""', 'ppc64el': '""'}>
+CONFIG_ANDROID_BINDER_IPC                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ANDROID_BINDER_IPC_SELFTEST              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_ANDROID_VSOC                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_APB_TIMER                                policy<{'i386': 'y'}>
+CONFIG_APDS9300                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_APDS9802ALS                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_APDS9960                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_APM                                      policy<{'i386': 'm'}>
+CONFIG_APM_ALLOW_INTS                           policy<{'i386': 'n'}>
+CONFIG_APM_CPU_IDLE                             policy<{'i386': 'n'}>
+CONFIG_APM_DISPLAY_BLANK                        policy<{'i386': 'n'}>
+CONFIG_APM_DO_ENABLE                            policy<{'i386': 'n'}>
+CONFIG_APM_EMULATION                            policy<{'armhf': 'n'}>
+CONFIG_APM_IGNORE_USER_SUSPEND                  policy<{'i386': 'n'}>
+CONFIG_APPLDATA_BASE                            policy<{'s390x': 'y'}>
+CONFIG_APPLDATA_MEM                             policy<{'s390x': 'm'}>
+CONFIG_APPLDATA_NET_SUM                         policy<{'s390x': 'm'}>
+CONFIG_APPLDATA_OS                              policy<{'s390x': 'm'}>
+CONFIG_APPLE_GMUX                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_APPLE_PROPERTIES                         policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_APPLICOM                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_APQ_GCC_8084                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_APQ_MMCC_8084                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_AQTION                                   policy<{'amd64': 'm', 'arm64': 'm'}>
+CONFIG_AQUANTIA_PHY                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_AR5523                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ARCH_32BIT_OFF_T                         policy<{'armhf': 'y', 'i386': 'y'}>
+CONFIG_ARCH_ACTIONS                             policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARCH_AGILEX                              policy<{'arm64': 'y'}>
+CONFIG_ARCH_ALPINE                              policy<{'arm64': 'n', 'armhf': 'y'}>
+CONFIG_ARCH_ARTPEC                              policy<{'armhf': 'y'}>
+CONFIG_ARCH_ASPEED                              policy<{'armhf': 'y'}>
+CONFIG_ARCH_AT91                                policy<{'armhf': 'n'}>
+CONFIG_ARCH_AXXIA                               policy<{'armhf-generic-lpae': 'y'}>
+CONFIG_ARCH_BCM                                 policy<{'armhf': 'n'}>
+CONFIG_ARCH_BCM2835                             policy<{'arm64': 'y'}>
+CONFIG_ARCH_BCM_IPROC                           policy<{'arm64': 'y'}>
+CONFIG_ARCH_BERLIN                              policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARCH_BINFMT_ELF_STATE                    policy<{'s390x': 'y'}>
+CONFIG_ARCH_BITMAIN                             policy<{'arm64': 'y'}>
+CONFIG_ARCH_BRCMSTB                             policy<{'arm64': 'y'}>
+CONFIG_ARCH_CLOCKSOURCE_DATA                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_ARCH_CLOCKSOURCE_INIT                    policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_ARCH_CPUIDLE_HALTPOLL                    policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_ARCH_CPU_PROBE_RELEASE                   policy<{'ppc64el': 'y'}>
+CONFIG_ARCH_DEFCONFIG                           policy<{'amd64': '"arch/x86/configs/x86_64_defconfig"', 'i386': '"arch/x86/configs/i386_defconfig"'}>
+CONFIG_ARCH_DIGICOLOR                           policy<{'armhf': 'n'}>
+CONFIG_ARCH_DMA_ADDR_T_64BIT                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf-generic-lpae': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ARCH_DOVE                                policy<{'armhf': 'n'}>
+CONFIG_ARCH_EBSA110                             policy<{'armhf': 'n'}>
+CONFIG_ARCH_EMEV2                               policy<{'armhf': 'y'}>
+CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION           policy<{'amd64': 'y', 'arm64': 'y', 'ppc64el': 'y'}>
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG               policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE             policy<{'amd64': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK             policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ARCH_ENABLE_THP_MIGRATION                policy<{'amd64': 'y', 'ppc64el': 'y'}>
+CONFIG_ARCH_EP93XX                              policy<{'armhf': 'n'}>
+CONFIG_ARCH_EXYNOS                              policy<{'arm64': 'n', 'armhf': 'y'}>
+CONFIG_ARCH_EXYNOS3                             policy<{'armhf': 'n'}>
+CONFIG_ARCH_EXYNOS4                             policy<{'armhf': 'n'}>
+CONFIG_ARCH_EXYNOS5                             policy<{'armhf': 'y'}>
+CONFIG_ARCH_FLATMEM_ENABLE                      policy<{'i386': 'y'}>
+CONFIG_ARCH_FOOTBRIDGE                          policy<{'armhf': 'n'}>
+CONFIG_ARCH_HAS_ACPI_TABLE_UPGRADE              policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_ARCH_HAS_ADD_PAGES                       policy<{'amd64': 'y'}>
+CONFIG_ARCH_HAS_BANDGAP                         policy<{'armhf': 'y'}>
+CONFIG_ARCH_HAS_BINFMT_FLAT                     policy<{'armhf': 'y'}>
+CONFIG_ARCH_HAS_CACHE_LINE_SIZE                 policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_ARCH_HAS_CPU_FINALIZE_INIT               policy<{'amd64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_ARCH_HAS_CPU_RELAX                       policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_ARCH_HAS_DEBUG_VIRTUAL                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ARCH_HAS_DMA_COHERENT_TO_PFN             policy<{'arm64': 'y', 'armhf-generic-lpae': 'y'}>
+CONFIG_ARCH_HAS_DMA_PREP_COHERENT               policy<{'arm64': 'y'}>
+CONFIG_ARCH_HAS_ELF_RANDOMIZE                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ARCH_HAS_FAST_MULTIPLIER                 policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ARCH_HAS_FILTER_PGPROT                   policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_ARCH_HAS_FORCE_DMA_UNENCRYPTED           policy<{'amd64': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ARCH_HAS_FORTIFY_SOURCE                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ARCH_HAS_GIGANTIC_PAGE                   policy<{'amd64': 'y', 'arm64': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ARCH_HAS_HUGEPD                          policy<{'ppc64el': 'y'}>
+CONFIG_ARCH_HAS_KCOV                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ARCH_HAS_KEEPINITRD                      policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARCH_HAS_KEXEC_PURGATORY                 policy<{'amd64': 'y', 'ppc64el': 'y'}>
+CONFIG_ARCH_HAS_MEMBARRIER_CALLBACKS            policy<{'ppc64el': 'y'}>
+CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_ARCH_HAS_MEM_ENCRYPT                     policy<{'amd64': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ARCH_HAS_MMIOWB                          policy<{'ppc64el': 'y'}>
+CONFIG_ARCH_HAS_PHYS_TO_DMA                     policy<{'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_ARCH_HAS_PKEYS                           policy<{'amd64': 'y'}>
+CONFIG_ARCH_HAS_PMEM_API                        policy<{'amd64': 'y', 'arm64': 'y', 'ppc64el': 'y'}>
+CONFIG_ARCH_HAS_PTE_DEVMAP                      policy<{'amd64': 'y', 'arm64': 'y', 'ppc64el': 'y'}>
+CONFIG_ARCH_HAS_PTE_SPECIAL                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf-generic-lpae': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ARCH_HAS_RELR                            policy<{'arm64': 'y'}>
+CONFIG_ARCH_HAS_RESET_CONTROLLER                policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARCH_HAS_SCALED_CPUTIME                  policy<{'s390x': 'y'}>
+CONFIG_ARCH_HAS_SETUP_DMA_OPS                   policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARCH_HAS_SET_DIRECT_MAP                  policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_ARCH_HAS_SET_MEMORY                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_ARCH_HAS_STRICT_KERNEL_RWX               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_ARCH_HAS_STRICT_MODULE_RWX               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_ARCH_HAS_SYNC_CORE_BEFORE_USERMODE       policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU                policy<{'arm64': 'y', 'armhf-generic-lpae': 'y'}>
+CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE             policy<{'arm64': 'y', 'armhf-generic-lpae': 'y'}>
+CONFIG_ARCH_HAS_SYSCALL_WRAPPER                 policy<{'amd64': 'y', 'arm64': 'y', 's390x': 'y'}>
+CONFIG_ARCH_HAS_TEARDOWN_DMA_OPS                policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARCH_HAS_TICK_BROADCAST                  policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE              policy<{'amd64': 'y', 'arm64': 'y', 'ppc64el': 'y'}>
+CONFIG_ARCH_HAS_UACCESS_MCSAFE                  policy<{'amd64': 'y', 'ppc64el': 'y'}>
+CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL              policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H                  policy<{'armhf': 'y'}>
+CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG               policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ARCH_HI3xxx                              policy<{'armhf': 'y'}>
+CONFIG_ARCH_HIBERNATION_HEADER                  policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_ARCH_HIBERNATION_POSSIBLE                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ARCH_HIGHBANK                            policy<{'armhf': 'y'}>
+CONFIG_ARCH_HIP01                               policy<{'armhf': 'n'}>
+CONFIG_ARCH_HIP04                               policy<{'armhf': 'y'}>
+CONFIG_ARCH_HISI                                policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARCH_HIX5HD2                             policy<{'armhf': 'y'}>
+CONFIG_ARCH_INLINE_READ_LOCK                    policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_ARCH_INLINE_READ_LOCK_BH                 policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_ARCH_INLINE_READ_LOCK_IRQ                policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_ARCH_INLINE_READ_LOCK_IRQSAVE            policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_ARCH_INLINE_READ_TRYLOCK                 policy<{'s390x': 'y'}>
+CONFIG_ARCH_INLINE_READ_UNLOCK                  policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_ARCH_INLINE_READ_UNLOCK_BH               policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_ARCH_INLINE_READ_UNLOCK_IRQ              policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_ARCH_INLINE_READ_UNLOCK_IRQRESTORE       policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_ARCH_INLINE_SPIN_LOCK                    policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_ARCH_INLINE_SPIN_LOCK_BH                 policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_ARCH_INLINE_SPIN_LOCK_IRQ                policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_ARCH_INLINE_SPIN_LOCK_IRQSAVE            policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_ARCH_INLINE_SPIN_TRYLOCK                 policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_ARCH_INLINE_SPIN_TRYLOCK_BH              policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_ARCH_INLINE_SPIN_UNLOCK                  policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_ARCH_INLINE_SPIN_UNLOCK_BH               policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_ARCH_INLINE_SPIN_UNLOCK_IRQ              policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_ARCH_INLINE_SPIN_UNLOCK_IRQRESTORE       policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_ARCH_INLINE_WRITE_LOCK                   policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_ARCH_INLINE_WRITE_LOCK_BH                policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_ARCH_INLINE_WRITE_LOCK_IRQ               policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_ARCH_INLINE_WRITE_LOCK_IRQSAVE           policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_ARCH_INLINE_WRITE_TRYLOCK                policy<{'s390x': 'y'}>
+CONFIG_ARCH_INLINE_WRITE_UNLOCK                 policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_ARCH_INLINE_WRITE_UNLOCK_BH              policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_ARCH_INLINE_WRITE_UNLOCK_IRQ             policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE      policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_ARCH_IOP32X                              policy<{'armhf': 'n'}>
+CONFIG_ARCH_IXP4XX                              policy<{'armhf': 'n'}>
+CONFIG_ARCH_K3                                  policy<{'arm64': 'y'}>
+CONFIG_ARCH_K3_AM6_SOC                          policy<{'arm64': 'y'}>
+CONFIG_ARCH_K3_J721E_SOC                        policy<{'arm64': 'y'}>
+CONFIG_ARCH_KEEP_MEMBLOCK                       policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ARCH_KEYSTONE                            policy<{'armhf': 'n'}>
+CONFIG_ARCH_LAYERSCAPE                          policy<{'arm64': 'y'}>
+CONFIG_ARCH_LG1K                                policy<{'arm64': 'y'}>
+CONFIG_ARCH_MAY_HAVE_PC_FDC                     policy<{'amd64': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ARCH_MDM9615                             policy<{'armhf': 'y'}>
+CONFIG_ARCH_MEDIATEK                            policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARCH_MEMORY_PROBE                        policy<{'amd64': 'y', 'ppc64el': 'y'}>
+CONFIG_ARCH_MESON                               policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC                 policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT               policy<{'amd64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ARCH_MIGHT_HAVE_PC_SERIO                 policy<{'amd64': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ARCH_MILBEAUT                            policy<{'armhf': 'y'}>
+CONFIG_ARCH_MILBEAUT_M10V                       policy<{'armhf': 'y'}>
+CONFIG_ARCH_MMAP_RND_BITS                       policy<{'amd64': '28', 'arm64': '18', 'armhf': '8', 'i386': '8', 'ppc64el': '28'}>
+CONFIG_ARCH_MMAP_RND_BITS_MAX                   policy<{'amd64': '32', 'arm64': '33', 'armhf': '16', 'i386': '16', 'ppc64el': '29'}>
+CONFIG_ARCH_MMAP_RND_BITS_MIN                   policy<{'amd64': '28', 'arm64': '18', 'armhf': '8', 'i386': '8', 'ppc64el': '14'}>
+CONFIG_ARCH_MMAP_RND_COMPAT_BITS                policy<{'amd64': '8', 'arm64': '11', 'ppc64el': '8'}>
+CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX            policy<{'amd64': '16', 'arm64': '16', 'i386': '16', 'ppc64el': '13'}>
+CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN            policy<{'amd64': '8', 'arm64': '11', 'i386': '8', 'ppc64el': '7'}>
+CONFIG_ARCH_MMP                                 policy<{'armhf': 'n'}>
+CONFIG_ARCH_MSM8960                             policy<{'armhf': 'y'}>
+CONFIG_ARCH_MSM8974                             policy<{'armhf': 'y'}>
+CONFIG_ARCH_MSM8X60                             policy<{'armhf': 'y'}>
+CONFIG_ARCH_MULTIPLATFORM                       policy<{'armhf': 'y'}>
+CONFIG_ARCH_MULTI_V6                            policy<{'armhf': 'n'}>
+CONFIG_ARCH_MULTI_V6_V7                         policy<{'armhf': 'y'}>
+CONFIG_ARCH_MULTI_V7                            policy<{'armhf': 'y'}>
+CONFIG_ARCH_MVEBU                               policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARCH_MXC                                 policy<{'arm64': 'y', 'armhf-generic': 'y', 'armhf-generic-lpae': 'n'}>
+CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED              policy<{'armhf': 'y'}>
+CONFIG_ARCH_NPCM                                policy<{'armhf': 'y'}>
+CONFIG_ARCH_NPCM7XX                             policy<{'armhf': 'y'}>
+CONFIG_ARCH_NR_GPIO                             policy<{'armhf': '1024'}>
+CONFIG_ARCH_OMAP                                policy<{'armhf': 'y'}>
+CONFIG_ARCH_OMAP1                               policy<{'armhf': 'n'}>
+CONFIG_ARCH_OMAP2PLUS                           policy<{'armhf': 'y'}>
+CONFIG_ARCH_OMAP2PLUS_TYPICAL                   policy<{'armhf': 'y'}>
+CONFIG_ARCH_OMAP3                               policy<{'armhf-generic': 'y', 'armhf-generic-lpae': 'n'}>
+CONFIG_ARCH_OMAP4                               policy<{'armhf-generic': 'y', 'armhf-generic-lpae': 'n'}>
+CONFIG_ARCH_OPTIONAL_KERNEL_RWX                 policy<{'armhf': 'y'}>
+CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT         policy<{'armhf': 'y'}>
+CONFIG_ARCH_PROC_KCORE_TEXT                     policy<{'amd64': 'y', 'arm64': 'y'}>
+CONFIG_ARCH_PXA                                 policy<{'armhf': 'n'}>
+CONFIG_ARCH_QCOM                                policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARCH_R7S72100                            policy<{'armhf': 'y'}>
+CONFIG_ARCH_R7S9210                             policy<{'armhf': 'y'}>
+CONFIG_ARCH_R8A73A4                             policy<{'armhf': 'n'}>
+CONFIG_ARCH_R8A7740                             policy<{'armhf': 'y'}>
+CONFIG_ARCH_R8A7743                             policy<{'armhf': 'y'}>
+CONFIG_ARCH_R8A7744                             policy<{'armhf': 'y'}>
+CONFIG_ARCH_R8A7745                             policy<{'armhf': 'y'}>
+CONFIG_ARCH_R8A77470                            policy<{'armhf': 'y'}>
+CONFIG_ARCH_R8A774A1                            policy<{'arm64': 'y'}>
+CONFIG_ARCH_R8A774C0                            policy<{'arm64': 'y'}>
+CONFIG_ARCH_R8A7778                             policy<{'armhf': 'y'}>
+CONFIG_ARCH_R8A7779                             policy<{'armhf': 'y'}>
+CONFIG_ARCH_R8A7790                             policy<{'armhf': 'y'}>
+CONFIG_ARCH_R8A7791                             policy<{'armhf': 'y'}>
+CONFIG_ARCH_R8A7792                             policy<{'armhf': 'y'}>
+CONFIG_ARCH_R8A7793                             policy<{'armhf': 'y'}>
+CONFIG_ARCH_R8A7794                             policy<{'armhf': 'y'}>
+CONFIG_ARCH_R8A7795                             policy<{'arm64': 'y'}>
+CONFIG_ARCH_R8A7796                             policy<{'arm64': 'y'}>
+CONFIG_ARCH_R8A77965                            policy<{'arm64': 'y'}>
+CONFIG_ARCH_R8A77970                            policy<{'arm64': 'y'}>
+CONFIG_ARCH_R8A77980                            policy<{'arm64': 'y'}>
+CONFIG_ARCH_R8A77990                            policy<{'arm64': 'y'}>
+CONFIG_ARCH_R8A77995                            policy<{'arm64': 'y'}>
+CONFIG_ARCH_R9A06G032                           policy<{'armhf': 'y'}>
+CONFIG_ARCH_RANDOM                              policy<{'amd64': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ARCH_RCAR_GEN1                           policy<{'armhf': 'y'}>
+CONFIG_ARCH_RCAR_GEN2                           policy<{'armhf': 'y'}>
+CONFIG_ARCH_RCAR_GEN3                           policy<{'arm64': 'y'}>
+CONFIG_ARCH_RDA                                 policy<{'armhf': 'y'}>
+CONFIG_ARCH_REALTEK                             policy<{'arm64': 'y'}>
+CONFIG_ARCH_REALVIEW                            policy<{'armhf': 'n'}>
+CONFIG_ARCH_RENESAS                             policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARCH_RMOBILE                             policy<{'armhf': 'y'}>
+CONFIG_ARCH_RPC                                 policy<{'armhf': 'n'}>
+CONFIG_ARCH_RZN1                                policy<{'armhf': 'y'}>
+CONFIG_ARCH_S3C24XX                             policy<{'armhf': 'n'}>
+CONFIG_ARCH_S5PV210                             policy<{'armhf': 'n'}>
+CONFIG_ARCH_SA1100                              policy<{'armhf': 'n'}>
+CONFIG_ARCH_SEATTLE                             policy<{'arm64': 'y'}>
+CONFIG_ARCH_SELECT_MEMORY_MODEL                 policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ARCH_SH73A0                              policy<{'armhf': 'y'}>
+CONFIG_ARCH_SIRF                                policy<{'armhf': 'n'}>
+CONFIG_ARCH_SOCFPGA                             policy<{'armhf': 'n'}>
+CONFIG_ARCH_SPARSEMEM_DEFAULT                   policy<{'amd64': 'y', 'arm64': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ARCH_SPARSEMEM_ENABLE                    policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ARCH_SPRD                                policy<{'arm64': 'y'}>
+CONFIG_ARCH_STACKWALK                           policy<{'amd64': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_ARCH_STI                                 policy<{'armhf': 'n'}>
+CONFIG_ARCH_STM32                               policy<{'armhf': 'n'}>
+CONFIG_ARCH_STRATIX10                           policy<{'arm64': 'y'}>
+CONFIG_ARCH_SUNXI                               policy<{'arm64': 'y', 'armhf': 'n'}>
+CONFIG_ARCH_SUPPORTS_ACPI                       policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ARCH_SUPPORTS_BIG_ENDIAN                 policy<{'armhf': 'y'}>
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC            policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ARCH_SUPPORTS_INT128                     policy<{'amd64': 'y', 'arm64': 'y'}>
+CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE             policy<{'amd64': 'y', 'arm64': 'y', 'ppc64el': 'y'}>
+CONFIG_ARCH_SUPPORTS_NUMA_BALANCING             policy<{'amd64': 'y', 'arm64': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ARCH_SUPPORTS_UPROBES                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ARCH_SUSPEND_NONZERO_CPU                 policy<{'ppc64el': 'y'}>
+CONFIG_ARCH_SUSPEND_POSSIBLE                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ARCH_SYNQUACER                           policy<{'arm64': 'y'}>
+CONFIG_ARCH_TEGRA                               policy<{'arm64': 'n', 'armhf-generic': 'y', 'armhf-generic-lpae': 'n'}>
+CONFIG_ARCH_TEGRA_114_SOC                       policy<{'armhf-generic': 'y'}>
+CONFIG_ARCH_TEGRA_124_SOC                       policy<{'armhf-generic': 'y'}>
+CONFIG_ARCH_TEGRA_2x_SOC                        policy<{'armhf-generic': 'y'}>
+CONFIG_ARCH_TEGRA_3x_SOC                        policy<{'armhf-generic': 'y'}>
+CONFIG_ARCH_THUNDER                             policy<{'arm64': 'y'}>
+CONFIG_ARCH_THUNDER2                            policy<{'arm64': 'y'}>
+CONFIG_ARCH_U8500                               policy<{'armhf': 'n'}>
+CONFIG_ARCH_UNIPHIER                            policy<{'arm64': 'n', 'armhf': 'y'}>
+CONFIG_ARCH_USES_HIGH_VMA_FLAGS                 policy<{'amd64': 'y'}>
+CONFIG_ARCH_USES_PG_UNCACHED                    policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_ARCH_USE_BUILTIN_BSWAP                   policy<{'amd64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ARCH_USE_MEMREMAP_PROT                   policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_ARCH_USE_QUEUED_RWLOCKS                  policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_ARCH_USE_QUEUED_SPINLOCKS                policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_ARCH_VEXPRESS                            policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA        policy<{'armhf': 'y'}>
+CONFIG_ARCH_VEXPRESS_DCSCB                      policy<{'armhf': 'y'}>
+CONFIG_ARCH_VEXPRESS_SPC                        policy<{'armhf': 'y'}>
+CONFIG_ARCH_VEXPRESS_TC2_PM                     policy<{'armhf': 'y'}>
+CONFIG_ARCH_VIRT                                policy<{'armhf': 'y'}>
+CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT           policy<{'amd64': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_ARCH_WANTS_THP_SWAP                      policy<{'amd64': 'y'}>
+CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH        policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION       policy<{'amd64': 'y', 'arm64': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT    policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARCH_WANT_FRAME_POINTERS                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_ARCH_WANT_GENERAL_HUGETLB                policy<{'amd64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_ARCH_WANT_HUGE_PMD_SHARE                 policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION              policy<{'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ARCH_WANT_IRQS_OFF_ACTIVATE_MM           policy<{'ppc64el': 'y'}>
+CONFIG_ARCH_WANT_OLD_COMPAT_IPC                 policy<{'amd64': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ARCH_WEAK_RELEASE_ACQUIRE                policy<{'ppc64el': 'y'}>
+CONFIG_ARCH_WM8850                              policy<{'armhf': 'n'}>
+CONFIG_ARCH_XGENE                               policy<{'arm64': 'y'}>
+CONFIG_ARCH_ZYNQ                                policy<{'armhf': 'n'}>
+CONFIG_ARCH_ZYNQMP                              policy<{'arm64': 'y'}>
+CONFIG_ARCNET                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_ARCNET_1051                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ARCNET_1201                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ARCNET_CAP                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ARCNET_COM20020                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ARCNET_COM20020_CS                       policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_ARCNET_COM20020_ISA                      policy<{'i386': 'm'}>
+CONFIG_ARCNET_COM20020_PCI                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ARCNET_COM90xx                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ARCNET_COM90xxIO                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ARCNET_RAW                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ARCNET_RIM_I                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ARCX_ANYBUS_CONTROLLER                   policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_ARC_EMAC_CORE                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_ARM                                      policy<{'armhf': 'y'}>
+CONFIG_ARM64                                    policy<{'arm64': 'y'}>
+CONFIG_ARM64_16K_PAGES                          policy<{'arm64': 'n'}>
+CONFIG_ARM64_4K_PAGES                           policy<{'arm64': 'y'}>
+CONFIG_ARM64_64K_PAGES                          policy<{'arm64': 'n'}>
+CONFIG_ARM64_ACPI_PARKING_PROTOCOL              policy<{'arm64': 'y'}>
+CONFIG_ARM64_CNP                                policy<{'arm64': 'y'}>
+CONFIG_ARM64_CONT_SHIFT                         policy<{'arm64': '4'}>
+CONFIG_ARM64_CRYPTO                             policy<{'arm64': 'y'}>
+CONFIG_ARM64_DEBUG_PRIORITY_MASKING             policy<{'arm64': 'n'}>
+CONFIG_ARM64_ERRATUM_1024718                    policy<{'arm64': 'y'}>
+CONFIG_ARM64_ERRATUM_1165522                    policy<{'arm64': 'y'}>
+CONFIG_ARM64_ERRATUM_1286807                    policy<{'arm64': 'y'}>
+CONFIG_ARM64_ERRATUM_1418040                    policy<{'arm64': 'y'}>
+CONFIG_ARM64_ERRATUM_1463225                    policy<{'arm64': 'y'}>
+CONFIG_ARM64_ERRATUM_1542419                    policy<{'arm64': 'y'}>
+CONFIG_ARM64_ERRATUM_1742098                    policy<{'arm64': 'y'}>
+CONFIG_ARM64_ERRATUM_3194386                    policy<{'arm64': 'y'}>
+CONFIG_ARM64_ERRATUM_819472                     policy<{'arm64': 'y'}>
+CONFIG_ARM64_ERRATUM_824069                     policy<{'arm64': 'y'}>
+CONFIG_ARM64_ERRATUM_826319                     policy<{'arm64': 'y'}>
+CONFIG_ARM64_ERRATUM_827319                     policy<{'arm64': 'y'}>
+CONFIG_ARM64_ERRATUM_832075                     policy<{'arm64': 'y'}>
+CONFIG_ARM64_ERRATUM_834220                     policy<{'arm64': 'y'}>
+CONFIG_ARM64_ERRATUM_845719                     policy<{'arm64': 'y'}>
+CONFIG_ARM64_HW_AFDBM                           policy<{'arm64': 'y'}>
+CONFIG_ARM64_MODULE_PLTS                        policy<{'arm64': 'y'}>
+CONFIG_ARM64_PAGE_SHIFT                         policy<{'arm64': '12'}>
+CONFIG_ARM64_PAN                                policy<{'arm64': 'y'}>
+CONFIG_ARM64_PA_BITS                            policy<{'arm64': '48'}>
+CONFIG_ARM64_PA_BITS_48                         policy<{'arm64': 'y'}>
+CONFIG_ARM64_PMEM                               policy<{'arm64': 'y'}>
+CONFIG_ARM64_PSEUDO_NMI                         policy<{'arm64': 'y'}>
+CONFIG_ARM64_PTDUMP_CORE                        policy<{'arm64': 'y'}>
+CONFIG_ARM64_PTDUMP_DEBUGFS                     policy<{'arm64': 'n'}>
+CONFIG_ARM64_PTR_AUTH                           policy<{'arm64': 'y'}>
+CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET              policy<{'arm64': 'n'}>
+CONFIG_ARM64_RAS_EXTN                           policy<{'arm64': 'y'}>
+CONFIG_ARM64_RELOC_TEST                         policy<{'arm64': 'n'}>
+CONFIG_ARM64_SSBD                               policy<{'arm64': 'y'}>
+CONFIG_ARM64_SVE                                policy<{'arm64': 'y'}>
+CONFIG_ARM64_SW_TTBR0_PAN                       policy<{'arm64': 'y'}>
+CONFIG_ARM64_TAGGED_ADDR_ABI                    policy<{'arm64': 'y'}>
+CONFIG_ARM64_UAO                                policy<{'arm64': 'y'}>
+CONFIG_ARM64_VA_BITS                            policy<{'arm64': '48'}>
+CONFIG_ARM64_VA_BITS_39                         policy<{'arm64': 'n'}>
+CONFIG_ARM64_VHE                                policy<{'arm64': 'y'}>
+CONFIG_ARM64_WORKAROUND_CLEAN_CACHE             policy<{'arm64': 'y'}>
+CONFIG_ARM64_WORKAROUND_REPEAT_TLBI             policy<{'arm64': 'y'}>
+CONFIG_ARMADA375_USBCLUSTER_PHY                 policy<{'armhf': 'y'}>
+CONFIG_ARMADA_370_CLK                           policy<{'armhf': 'y'}>
+CONFIG_ARMADA_370_XP_IRQ                        policy<{'armhf': 'y'}>
+CONFIG_ARMADA_370_XP_TIMER                      policy<{'armhf': 'y'}>
+CONFIG_ARMADA_375_CLK                           policy<{'armhf': 'y'}>
+CONFIG_ARMADA_37XX_CLK                          policy<{'arm64': 'y'}>
+CONFIG_ARMADA_37XX_RWTM_MBOX                    policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_ARMADA_37XX_WATCHDOG                     policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_ARMADA_38X_CLK                           policy<{'armhf': 'y'}>
+CONFIG_ARMADA_39X_CLK                           policy<{'armhf': 'y'}>
+CONFIG_ARMADA_AP806_SYSCON                      policy<{'arm64': 'y'}>
+CONFIG_ARMADA_AP_CPU_CLK                        policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARMADA_AP_CP_HELPER                      policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARMADA_CP110_SYSCON                      policy<{'arm64': 'y'}>
+CONFIG_ARMADA_THERMAL                           policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARMADA_XP_CLK                            policy<{'armhf': 'y'}>
+CONFIG_ARM_ALLWINNER_SUN50I_CPUFREQ_NVMEM       policy<{'arm64': 'm'}>
+CONFIG_ARM_AMBA                                 policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARM_APPENDED_DTB                         policy<{'armhf': 'y'}>
+CONFIG_ARM_ARCH_TIMER                           policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARM_ARCH_TIMER_EVTSTREAM                 policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND            policy<{'arm64': 'y'}>
+CONFIG_ARM_ARMADA_37XX_CPUFREQ                  policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_ARM_ARMADA_8K_CPUFREQ                    policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_ARM_ATAG_DTB_COMPAT                      policy<{'armhf-generic': 'y', 'armhf-generic-lpae': 'n'}>
+CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND       policy<{'armhf-generic': 'y'}>
+CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER policy<{'armhf-generic': 'n'}>
+CONFIG_ARM_BIG_LITTLE_CPUFREQ                   policy<{'armhf': 'm'}>
+CONFIG_ARM_BIG_LITTLE_CPUIDLE                   policy<{'armhf': 'y'}>
+CONFIG_ARM_BRCMSTB_AVS_CPUFREQ                  policy<{'arm64': 'm'}>
+CONFIG_ARM_CCI                                  policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARM_CCI400_COMMON                        policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARM_CCI400_PMU                           policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARM_CCI400_PORT_CTRL                     policy<{'armhf': 'y'}>
+CONFIG_ARM_CCI5xx_PMU                           policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARM_CCI_PMU                              policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARM_CCN                                  policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARM_CHARLCD                              policy<{'armhf': 'y'}>
+CONFIG_ARM_CPUIDLE                              policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARM_CPU_SUSPEND                          policy<{'armhf': 'y'}>
+CONFIG_ARM_CPU_TOPOLOGY                         policy<{'armhf': 'y'}>
+CONFIG_ARM_CRYPTO                               policy<{'armhf': 'y'}>
+CONFIG_ARM_DMA_IOMMU_ALIGNMENT                  policy<{'armhf': '8'}>
+CONFIG_ARM_DMA_MEM_BUFFERABLE                   policy<{'armhf': 'y'}>
+CONFIG_ARM_DMA_USE_IOMMU                        policy<{'armhf': 'y'}>
+CONFIG_ARM_DSU_PMU                              policy<{'arm64': 'm'}>
+CONFIG_ARM_ERRATA_430973                        policy<{'armhf': 'y'}>
+CONFIG_ARM_ERRATA_643719                        policy<{'armhf': 'y'}>
+CONFIG_ARM_ERRATA_720789                        policy<{'armhf': 'y'}>
+CONFIG_ARM_ERRATA_754322                        policy<{'armhf': 'y'}>
+CONFIG_ARM_ERRATA_754327                        policy<{'armhf': 'y'}>
+CONFIG_ARM_ERRATA_764369                        policy<{'armhf': 'y'}>
+CONFIG_ARM_ERRATA_773022                        policy<{'armhf': 'y'}>
+CONFIG_ARM_ERRATA_775420                        policy<{'armhf': 'y'}>
+CONFIG_ARM_ERRATA_798181                        policy<{'armhf': 'y'}>
+CONFIG_ARM_ERRATA_814220                        policy<{'armhf': 'y'}>
+CONFIG_ARM_ERRATA_818325_852422                 policy<{'armhf': 'y'}>
+CONFIG_ARM_ERRATA_821420                        policy<{'armhf': 'y'}>
+CONFIG_ARM_ERRATA_825619                        policy<{'armhf': 'y'}>
+CONFIG_ARM_ERRATA_852421                        policy<{'armhf': 'y'}>
+CONFIG_ARM_ERRATA_852423                        policy<{'armhf': 'y'}>
+CONFIG_ARM_ERRATA_857271                        policy<{'armhf': 'y'}>
+CONFIG_ARM_ERRATA_857272                        policy<{'armhf': 'y'}>
+CONFIG_ARM_EXYNOS_BUS_DEVFREQ                   policy<{'armhf': 'y'}>
+CONFIG_ARM_EXYNOS_CPUIDLE                       policy<{'armhf': 'y'}>
+CONFIG_ARM_GIC                                  policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARM_GIC_MAX_NR                           policy<{'arm64': '1', 'armhf': '1'}>
+CONFIG_ARM_GIC_V2M                              policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARM_GIC_V3                               policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARM_GIC_V3_ITS                           policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARM_GIC_V3_ITS_FSL_MC                    policy<{'arm64': 'y'}>
+CONFIG_ARM_GIC_V3_ITS_PCI                       policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARM_GLOBAL_TIMER                         policy<{'armhf': 'y'}>
+CONFIG_ARM_HAS_SG_CHAIN                         policy<{'armhf': 'y'}>
+CONFIG_ARM_HEAVY_MB                             policy<{'armhf': 'y'}>
+CONFIG_ARM_HIGHBANK_CPUFREQ                     policy<{'armhf': 'm'}>
+CONFIG_ARM_IMX6Q_CPUFREQ                        policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_ARM_IMX_CPUFREQ_DT                       policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_ARM_KPROBES_TEST                         policy<{'armhf': 'm'}>
+CONFIG_ARM_L1_CACHE_SHIFT                       policy<{'armhf': '7'}>
+CONFIG_ARM_L1_CACHE_SHIFT_6                     policy<{'armhf': 'y'}>
+CONFIG_ARM_L1_CACHE_SHIFT_7                     policy<{'armhf': 'y'}>
+CONFIG_ARM_LPAE                                 policy<{'armhf-generic': 'n', 'armhf-generic-lpae': 'y'}>
+CONFIG_ARM_MEDIATEK_CPUFREQ                     policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_ARM_MHU                                  policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_ARM_MODULE_PLTS                          policy<{'armhf': 'n'}>
+CONFIG_ARM_MVEBU_V7_CPUIDLE                     policy<{'armhf': 'y'}>
+CONFIG_ARM_OMAP2PLUS_CPUFREQ                    policy<{'armhf': 'y'}>
+CONFIG_ARM_PATCH_IDIV                           policy<{'armhf': 'y'}>
+CONFIG_ARM_PATCH_PHYS_VIRT                      policy<{'armhf': 'y'}>
+CONFIG_ARM_PL172_MPMC                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_ARM_PMU                                  policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARM_PMU_ACPI                             policy<{'arm64': 'y'}>
+CONFIG_ARM_PSCI                                 policy<{'armhf': 'y'}>
+CONFIG_ARM_PSCI_CHECKER                         policy<{'arm64': 'n', 'armhf': 'n'}>
+CONFIG_ARM_PSCI_CPUIDLE                         policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARM_PSCI_FW                              policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARM_PTDUMP_CORE                          policy<{'armhf': 'y'}>
+CONFIG_ARM_PTDUMP_DEBUGFS                       policy<{'armhf': 'n'}>
+CONFIG_ARM_QCOM_CPUFREQ_HW                      policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_ARM_QCOM_CPUFREQ_NVMEM                   policy<{'arm64': 'm'}>
+CONFIG_ARM_RASPBERRYPI_CPUFREQ                  policy<{'arm64': 'm'}>
+CONFIG_ARM_RK3399_DMC_DEVFREQ                   policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_ARM_SBSA_WATCHDOG                        policy<{'arm64': 'm'}>
+CONFIG_ARM_SCMI_CPUFREQ                         policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_ARM_SCMI_POWER_DOMAIN                    policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_ARM_SCMI_PROTOCOL                        policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARM_SCPI_CPUFREQ                         policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_ARM_SCPI_POWER_DOMAIN                    policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_ARM_SCPI_PROTOCOL                        policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_ARM_SDE_INTERFACE                        policy<{'arm64': 'y'}>
+CONFIG_ARM_SMMU                                 policy<{'arm64': 'y', 'armhf': 'n'}>
+CONFIG_ARM_SMMU_V3                              policy<{'arm64': 'y'}>
+CONFIG_ARM_SMMU_V3_PMU                          policy<{'arm64': 'm'}>
+CONFIG_ARM_SP805_WATCHDOG                       policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_ARM_SPE_PMU                              policy<{'arm64': 'm'}>
+CONFIG_ARM_TEGRA124_CPUFREQ                     policy<{'armhf-generic': 'y'}>
+CONFIG_ARM_TEGRA186_CPUFREQ                     policy<{'armhf-generic': 'm'}>
+CONFIG_ARM_TEGRA20_CPUFREQ                      policy<{'armhf-generic': 'y'}>
+CONFIG_ARM_TEGRA20_DEVFREQ                      policy<{'armhf-generic': 'm'}>
+CONFIG_ARM_TEGRA_DEVFREQ                        policy<{'armhf-generic': 'm'}>
+CONFIG_ARM_THUMB                                policy<{'armhf': 'y'}>
+CONFIG_ARM_THUMBEE                              policy<{'armhf': 'y'}>
+CONFIG_ARM_TIMER_SP804                          policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ARM_TI_CPUFREQ                           policy<{'armhf': 'y'}>
+CONFIG_ARM_VEXPRESS_SPC_CPUFREQ                 policy<{'armhf': 'm'}>
+CONFIG_ARM_VIRT_EXT                             policy<{'armhf': 'y'}>
+CONFIG_AS3935                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ASHMEM                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ASM_MODVERSIONS                          policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ASN1                                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ASPEED_ADC                               policy<{'armhf': 'm'}>
+CONFIG_ASPEED_BT_IPMI_BMC                       policy<{'armhf': 'm'}>
+CONFIG_ASPEED_KCS_IPMI_BMC                      policy<{'armhf': 'm'}>
+CONFIG_ASPEED_LPC_CTRL                          policy<{'armhf': 'm'}>
+CONFIG_ASPEED_LPC_SNOOP                         policy<{'armhf': 'm'}>
+CONFIG_ASPEED_P2A_CTRL                          policy<{'armhf': 'm'}>
+CONFIG_ASPEED_WATCHDOG                          policy<{'armhf': 'y'}>
+CONFIG_ASSOCIATIVE_ARRAY                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ASUS_LAPTOP                              policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_ASUS_NB_WMI                              policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_ASUS_WIRELESS                            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_ASUS_WMI                                 policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_ASYMMETRIC_TPM_KEY_SUBTYPE               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_ASYNC_CORE                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_ASYNC_MEMCPY                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_ASYNC_PQ                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_ASYNC_RAID6_RECOV                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_ASYNC_RAID6_TEST                         policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_ASYNC_TX_DISABLE_PQ_VAL_DMA              policy<{'arm64': 'y'}>
+CONFIG_ASYNC_TX_DISABLE_XOR_VAL_DMA             policy<{'arm64': 'y'}>
+CONFIG_ASYNC_TX_DMA                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH           policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ASYNC_XOR                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_AT76C50X_USB                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AT803X_PHY                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_ATA                                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_ATAGS                                    policy<{'armhf': 'y'}>
+CONFIG_ATAGS_PROC                               policy<{'armhf': 'y'}>
+CONFIG_ATALK                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_ATARI_PARTITION                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_ATA_ACPI                                 policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_ATA_BMDMA                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ATA_GENERIC                              policy<{'amd64': 'y', 'arm64': 'm', 'armhf': 'm', 'i386': 'y', 'ppc64el': 'm'}>
+CONFIG_ATA_OVER_ETH                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_ATA_SFF                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ATA_VERBOSE_ERROR                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ATH10K                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ATH10K_AHB                               policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_ATH10K_CE                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ATH10K_DEBUG                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_ATH10K_DEBUGFS                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ATH10K_PCI                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ATH10K_SDIO                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ATH10K_SNOC                              policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_ATH10K_SPECTRAL                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ATH10K_TRACING                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ATH10K_USB                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ATH5K                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ATH5K_DEBUG                              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_ATH5K_PCI                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ATH5K_TRACER                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_ATH6KL                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ATH6KL_DEBUG                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_ATH6KL_SDIO                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ATH6KL_TRACING                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_ATH6KL_USB                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ATH9K                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ATH9K_AHB                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ATH9K_BTCOEX_SUPPORT                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ATH9K_CHANNEL_CONTEXT                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ATH9K_COMMON                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ATH9K_COMMON_DEBUG                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ATH9K_COMMON_SPECTRAL                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ATH9K_DEBUGFS                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ATH9K_DYNACK                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_ATH9K_HTC                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ATH9K_HTC_DEBUGFS                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ATH9K_HW                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ATH9K_HWRNG                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ATH9K_PCI                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ATH9K_PCI_NO_EEPROM                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ATH9K_PCOEM                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ATH9K_RFKILL                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ATH9K_STATION_STATISTICS                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ATH9K_WOW                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ATH_COMMON                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ATH_DEBUG                                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_ATL1                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ATL1C                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ATL1E                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ATL2                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ATLAS_PH_SENSOR                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ATM                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_ATMEL                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ATM_AMBASSADOR                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_ATM_AMBASSADOR_DEBUG                     policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_ATM_BR2684                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ATM_BR2684_IPFILTER                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_ATM_CLIP                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ATM_CLIP_NO_ICMP                         policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_ATM_DRIVERS                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ATM_DUMMY                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ATM_ENI                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ATM_ENI_DEBUG                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_ATM_ENI_TUNE_BURST                       policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_ATM_FIRESTREAM                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_ATM_FORE200E                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ATM_FORE200E_DEBUG                       policy<{'amd64': '0', 'arm64': '0', 'armhf': '0', 'i386': '0', 'ppc64el': '0'}>
+CONFIG_ATM_FORE200E_TX_RETRY                    policy<{'amd64': '16', 'arm64': '16', 'armhf': '16', 'i386': '16', 'ppc64el': '16'}>
+CONFIG_ATM_FORE200E_USE_TASKLET                 policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_ATM_HE                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ATM_HE_USE_SUNI                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ATM_HORIZON                              policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_ATM_HORIZON_DEBUG                        policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_ATM_IA                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ATM_IA_DEBUG                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_ATM_IDT77252                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ATM_IDT77252_DEBUG                       policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_ATM_IDT77252_RCV_ALL                     policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_ATM_IDT77252_USE_SUNI                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ATM_LANAI                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ATM_LANE                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ATM_MPOA                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ATM_NICSTAR                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ATM_NICSTAR_USE_IDT77105                 policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_ATM_NICSTAR_USE_SUNI                     policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_ATM_SOLOS                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ATM_TCP                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ATM_ZATM                                 policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_ATM_ZATM_DEBUG                           policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_ATOMIC64_SELFTEST                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_ATP                                      policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_AUDIT                                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_AUDITSYSCALL                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_AUDIT_ARCH                               policy<{'amd64': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_AUDIT_ARCH_COMPAT_GENERIC                policy<{'arm64': 'y'}>
+CONFIG_AUDIT_COMPAT_GENERIC                     policy<{'arm64': 'y'}>
+CONFIG_AUDIT_GENERIC                            policy<{'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_AUFS_BDEV_LOOP                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_AUFS_BRANCH_MAX_1023                     policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_AUFS_BRANCH_MAX_127                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_AUFS_BRANCH_MAX_32767                    policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_AUFS_BRANCH_MAX_511                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_AUFS_BR_FUSE                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_AUFS_BR_HFSPLUS                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_AUFS_BR_RAMFS                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_AUFS_DEBUG                               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_AUFS_DIRREN                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_AUFS_FHSM                                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_AUFS_FS                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_AUFS_HNOTIFY                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_AUFS_INO_T_64                            policy<{'amd64': 'y', 'arm64': 'y', 'ppc64el': 'y'}>
+CONFIG_AUFS_RDU                                 policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_AUFS_SBILIST                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_AUFS_SHWH                                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_AUFS_XATTR                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_AURORA_NB8800                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_AUTOFS4_FS                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'y'}>
+CONFIG_AUTOFS_FS                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'y'}>
+CONFIG_AUTO_ZRELADDR                            policy<{'armhf': 'y'}>
+CONFIG_AUXDISPLAY                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_AX25                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AX25_DAMA_SLAVE                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_AX88796                                  policy<{'armhf': 'm'}>
+CONFIG_AX88796B_PHY                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_AX88796_93CX6                            policy<{'armhf': 'n'}>
+CONFIG_AXI_DMAC                                 policy<{'arm64': 'm'}>
+CONFIG_AXP20X_ADC                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AXP20X_POWER                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AXP288_ADC                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_AXP288_CHARGER                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_AXP288_FUEL_GAUGE                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_B43                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_B43LEGACY                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_B43LEGACY_DEBUG                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_B43LEGACY_DMA                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_B43LEGACY_DMA_AND_PIO_MODE               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_B43LEGACY_DMA_MODE                       policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_B43LEGACY_HWRNG                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_B43LEGACY_LEDS                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_B43LEGACY_PCICORE_AUTOSELECT             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_B43LEGACY_PCI_AUTOSELECT                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_B43LEGACY_PIO                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_B43LEGACY_PIO_MODE                       policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_B43_BCMA                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_B43_BCMA_PIO                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_B43_BUSES_BCMA                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_B43_BUSES_BCMA_AND_SSB                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_B43_BUSES_SSB                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_B43_DEBUG                                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_B43_HWRNG                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_B43_LEDS                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_B43_PCICORE_AUTOSELECT                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_B43_PCI_AUTOSELECT                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_B43_PHY_G                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_B43_PHY_HT                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_B43_PHY_LP                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_B43_PHY_N                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_B43_PIO                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_B43_SDIO                                 policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_B43_SSB                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_B44                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_B44_PCI                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_B44_PCICORE_AUTOSELECT                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_B44_PCI_AUTOSELECT                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_B53                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_B53_MDIO_DRIVER                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_B53_MMAP_DRIVER                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_B53_SERDES                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_B53_SPI_DRIVER                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_B53_SRAB_DRIVER                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BACKLIGHT_88PM860X                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BACKLIGHT_AAT2870                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BACKLIGHT_ADP5520                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BACKLIGHT_ADP8860                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BACKLIGHT_ADP8870                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BACKLIGHT_APPLE                          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_BACKLIGHT_ARCXCNN                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BACKLIGHT_AS3711                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BACKLIGHT_BD6107                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BACKLIGHT_CARILLO_RANCH                  policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_BACKLIGHT_CLASS_DEVICE                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_BACKLIGHT_DA903X                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BACKLIGHT_DA9052                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BACKLIGHT_GENERIC                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BACKLIGHT_GPIO                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BACKLIGHT_LM3533                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BACKLIGHT_LM3630A                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BACKLIGHT_LM3639                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BACKLIGHT_LP855X                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BACKLIGHT_LP8788                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BACKLIGHT_LV5207LP                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BACKLIGHT_MAX8925                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BACKLIGHT_PANDORA                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BACKLIGHT_PCF50633                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BACKLIGHT_PM8941_WLED                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BACKLIGHT_PWM                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BACKLIGHT_RAVE_SP                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BACKLIGHT_SAHARA                         policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_BACKLIGHT_SKY81452                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BACKLIGHT_TPS65217                       policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_BACKLIGHT_WM831X                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BACKTRACE_SELF_TEST                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_BALLOON_COMPACTION                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BASE_FULL                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BASE_SMALL                               policy<{'amd64': '0', 'arm64': '0', 'armhf': '0', 'i386': '0', 'ppc64el': '0', 's390x': '0'}>
+CONFIG_BATMAN_ADV                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_BATMAN_ADV_BATMAN_V                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_BATMAN_ADV_BLA                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BATMAN_ADV_DAT                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BATMAN_ADV_DEBUG                         policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_BATMAN_ADV_DEBUGFS                       policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_BATMAN_ADV_MCAST                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BATMAN_ADV_NC                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BATMAN_ADV_SYSFS                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BATMAN_ADV_TRACING                       policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_BATTERY_88PM860X                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BATTERY_ACT8945A                         policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_BATTERY_AXP20X                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BATTERY_BQ27XXX                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_BATTERY_BQ27XXX_HDQ                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BATTERY_BQ27XXX_I2C                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BATTERY_CPCAP                            policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_BATTERY_DA9030                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BATTERY_DA9052                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BATTERY_DA9150                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BATTERY_DS2760                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BATTERY_DS2780                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BATTERY_DS2781                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BATTERY_DS2782                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BATTERY_GAUGE_LTC2941                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BATTERY_LEGO_EV3                         policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_BATTERY_MAX17040                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BATTERY_MAX17042                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BATTERY_MAX1721X                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BATTERY_RT5033                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BATTERY_RX51                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BATTERY_SBS                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BATTERY_TWL4030_MADC                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BAYCOM_EPP                               policy<{'armhf': 'm', 'i386': 'm'}>
+CONFIG_BAYCOM_PAR                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BAYCOM_SER_FDX                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BAYCOM_SER_HDX                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BCACHE                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BCACHE_CLOSURES_DEBUG                    policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_BCACHE_DEBUG                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_BCH                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'y', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BCM2835_MBOX                             policy<{'arm64': 'y'}>
+CONFIG_BCM2835_POWER                            policy<{'arm64': 'y'}>
+CONFIG_BCM2835_THERMAL                          policy<{'arm64': 'm'}>
+CONFIG_BCM2835_VCHIQ                            policy<{'arm64': 'm'}>
+CONFIG_BCM2835_WDT                              policy<{'arm64': 'm'}>
+CONFIG_BCM7038_L1_IRQ                           policy<{'arm64': 'y'}>
+CONFIG_BCM7038_WDT                              policy<{'arm64': 'm'}>
+CONFIG_BCM7XXX_PHY                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BCM87XX_PHY                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BCMA                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_BCMA_BLOCKIO                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BCMA_DEBUG                               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_BCMA_DRIVER_GMAC_CMN                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BCMA_DRIVER_GPIO                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BCMA_DRIVER_PCI                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BCMA_HOST_PCI                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BCMA_HOST_PCI_POSSIBLE                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BCMA_HOST_SOC                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BCMA_POSSIBLE                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BCMA_SFLASH                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BCMGENET                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BCM_FLEXRM_MBOX                          policy<{'arm64': 'm'}>
+CONFIG_BCM_IPROC_ADC                            policy<{'arm64': 'm'}>
+CONFIG_BCM_KONA_USB2_PHY                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_BCM_NET_PHYLIB                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BCM_NS_THERMAL                           policy<{'arm64': 'm'}>
+CONFIG_BCM_PDC_MBOX                             policy<{'arm64': 'm'}>
+CONFIG_BCM_SBA_RAID                             policy<{'arm64': 'm'}>
+CONFIG_BCM_SR_THERMAL                           policy<{'arm64': 'm'}>
+CONFIG_BCM_VIDEOCORE                            policy<{'arm64': 'm'}>
+CONFIG_BD70528_WATCHDOG                         policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_BE2ISCSI                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_BE2NET                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BE2NET_BE2                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BE2NET_BE3                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BE2NET_HWMON                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BE2NET_LANCER                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BE2NET_SKYHAWK                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BEFS_DEBUG                               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_BEFS_FS                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_BERLIN2_ADC                              policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_BFQ_CGROUP_DEBUG                         policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_BFQ_GROUP_IOSCHED                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BFS_FS                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_BGMAC                                    policy<{'arm64': 'y'}>
+CONFIG_BGMAC_PLATFORM                           policy<{'arm64': 'y'}>
+CONFIG_BH1750                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BH1780                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BIG_KEYS                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BIG_LITTLE                               policy<{'armhf': 'y'}>
+CONFIG_BINARY_PRINTF                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BINFMT_ELF                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BINFMT_ELF_FDPIC                         policy<{'armhf': 'y'}>
+CONFIG_BINFMT_FLAT                              policy<{'armhf': 'y'}>
+CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK          policy<{'armhf': 'y'}>
+CONFIG_BINFMT_FLAT_OLD                          policy<{'armhf': 'y'}>
+CONFIG_BINFMT_MISC                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BINFMT_SHARED_FLAT                       policy<{'armhf': 'y'}>
+CONFIG_BINFMT_ZFLAT                             policy<{'armhf': 'y'}>
+CONFIG_BITREVERSE                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BLK_CGROUP                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BLK_CGROUP_IOCOST                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BLK_CGROUP_IOLATENCY                     policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_BLK_CMDLINE_PARSER                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BLK_DEBUG_FS                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BLK_DEBUG_FS_ZONED                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BLK_DEV                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BLK_DEV_3W_XXXX_RAID                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_BLK_DEV_BSG                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BLK_DEV_BSGLIB                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BLK_DEV_CRYPTOLOOP                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_BLK_DEV_DM_BUILTIN                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BLK_DEV_DRBD                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BLK_DEV_FD                               policy<{'amd64': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BLK_DEV_FD_RAWCMD                        policy<{'amd64': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_BLK_DEV_INITRD                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BLK_DEV_INTEGRITY                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BLK_DEV_IO_TRACE                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BLK_DEV_LOOP                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BLK_DEV_LOOP_MIN_COUNT                   policy<{'amd64': '8', 'arm64': '8', 'armhf': '8', 'i386': '8', 'ppc64el': '8', 's390x': '8'}>
+CONFIG_BLK_DEV_MD                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BLK_DEV_NBD                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BLK_DEV_NULL_BLK                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BLK_DEV_PCIESSD_MTIP32XX                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_BLK_DEV_PMEM                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf-generic-lpae': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BLK_DEV_RAM_COUNT                        policy<{'amd64': '16', 'arm64': '16', 'armhf': '16', 'i386': '16', 'ppc64el': '16', 's390x': '16'}>
+CONFIG_BLK_DEV_RBD                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BLK_DEV_RSXX                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_BLK_DEV_SKD                              policy<{'amd64': 'm', 'arm64': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_BLK_DEV_THROTTLING_LOW                   policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_BLK_DEV_XPRAM                            policy<{'s390x': 'n'}>
+CONFIG_BLK_DEV_ZONED                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BLK_MQ_PCI                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BLK_MQ_RDMA                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BLK_MQ_VIRTIO                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BLK_PM                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BLK_RQ_ALLOC_TIME                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BLK_SCSI_REQUEST                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BLK_SED_OPAL                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BLK_WBT                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BLK_WBT_MQ                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BLOCK                                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BLOCK_COMPAT                             policy<{'amd64': 'y', 'arm64': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BL_SWITCHER                              policy<{'armhf': 'y'}>
+CONFIG_BL_SWITCHER_DUMMY_IF                     policy<{'armhf': 'm'}>
+CONFIG_BMA180                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BMA220                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BMC150_ACCEL                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BMC150_ACCEL_I2C                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BMC150_ACCEL_SPI                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BMC150_MAGN                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BMC150_MAGN_I2C                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BMC150_MAGN_SPI                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BME680                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BME680_I2C                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BME680_SPI                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BMG160                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BMG160_I2C                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BMG160_SPI                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BMI160                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BMI160_I2C                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BMI160_SPI                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BMP280                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BMP280_I2C                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BMP280_SPI                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BNA                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BNX2                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BNX2X                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BNX2X_SRIOV                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BNXT                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BNXT_DCB                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BNXT_FLOWER_OFFLOAD                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BNXT_HWMON                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BNXT_SRIOV                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BOARD_TPCI200                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BONDING                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BOOTPARAM_HARDLOCKUP_PANIC               policy<{'amd64': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE         policy<{'amd64': '0', 'i386': '0', 'ppc64el': '0'}>
+CONFIG_BOOTPARAM_HOTPLUG_CPU0                   policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE          policy<{'amd64': '0', 'arm64': '0', 'armhf': '0', 'i386': '0', 'ppc64el': '0', 's390x': '0'}>
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE         policy<{'amd64': '0', 'arm64': '0', 'armhf': '0', 'i386': '0', 'ppc64el': '0'}>
+CONFIG_BOOTX_TEXT                               policy<{'ppc64el': 'n'}>
+CONFIG_BOOT_PRINTK_DELAY                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_BOUNCE                                   policy<{'amd64': 'y', 'armhf': 'y', 'i386': 'y', 's390x': 'n'}>
+CONFIG_BPF                                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BPFILTER                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BPFILTER_UMH                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BPF_EVENTS                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BPF_JIT                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BPF_JIT_ALWAYS_ON                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'n', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BPF_KPROBE_OVERRIDE                      policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BPF_STREAM_PARSER                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BPF_SYSCALL                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BPF_UNPRIV_DEFAULT_OFF                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BPQETHER                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BQL                                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BRANCH_PROFILE_NONE                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BRCMDBG                                  policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_BRCMFMAC                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BRCMFMAC_PCIE                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BRCMFMAC_PROTO_BCDC                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BRCMFMAC_PROTO_MSGBUF                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BRCMFMAC_SDIO                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BRCMFMAC_USB                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BRCMSMAC                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BRCMSTB_GISB_ARB                         policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_BRCMSTB_L2_IRQ                           policy<{'arm64': 'y'}>
+CONFIG_BRCMSTB_PM                               policy<{'arm64': 'y'}>
+CONFIG_BRCMSTB_THERMAL                          policy<{'arm64': 'm'}>
+CONFIG_BRCMUTIL                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BRCM_TRACING                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BRIDGE                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BRIDGE_EBT_802_3                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BRIDGE_EBT_AMONG                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BRIDGE_EBT_ARP                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BRIDGE_EBT_ARPREPLY                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BRIDGE_EBT_BROUTE                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BRIDGE_EBT_DNAT                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BRIDGE_EBT_IP                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BRIDGE_EBT_IP6                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BRIDGE_EBT_LIMIT                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BRIDGE_EBT_LOG                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BRIDGE_EBT_MARK                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BRIDGE_EBT_MARK_T                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BRIDGE_EBT_NFLOG                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BRIDGE_EBT_PKTTYPE                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BRIDGE_EBT_REDIRECT                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BRIDGE_EBT_SNAT                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BRIDGE_EBT_STP                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BRIDGE_EBT_T_FILTER                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BRIDGE_EBT_T_NAT                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BRIDGE_EBT_VLAN                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BRIDGE_IGMP_SNOOPING                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BRIDGE_NETFILTER                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BRIDGE_NF_EBTABLES                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BRIDGE_VLAN_FILTERING                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BROADCOM_PHY                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BSD_DISKLABEL                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_BSD_PROCESS_ACCT                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BSD_PROCESS_ACCT_V3                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BT                                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BTREE                                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BTRFS_ASSERT                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_BTRFS_DEBUG                              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_BTRFS_FS                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_BTRFS_FS_CHECK_INTEGRITY                 policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_BTRFS_FS_POSIX_ACL                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BTRFS_FS_REF_VERIFY                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_BTRFS_FS_RUN_SANITY_TESTS                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_BTT                                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf-generic-lpae': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BT_6LOWPAN                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BT_ATH3K                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BT_BCM                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BT_BNEP                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BT_BNEP_MC_FILTER                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BT_BNEP_PROTO_FILTER                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BT_BREDR                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BT_CMTP                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BT_DEBUGFS                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BT_HCIBCM203X                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BT_HCIBFUSB                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BT_HCIBLUECARD                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_BT_HCIBPA10X                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BT_HCIBT3C                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_BT_HCIBTSDIO                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BT_HCIBTUSB                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BT_HCIBTUSB_AUTOSUSPEND                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BT_HCIBTUSB_BCM                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BT_HCIBTUSB_MTK                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BT_HCIBTUSB_RTL                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BT_HCIDTL1                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_BT_HCIRSI                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BT_HCIUART                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BT_HCIUART_3WIRE                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BT_HCIUART_AG6XX                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BT_HCIUART_ATH3K                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BT_HCIUART_BCM                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BT_HCIUART_BCSP                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BT_HCIUART_H4                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BT_HCIUART_INTEL                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BT_HCIUART_LL                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BT_HCIUART_MRVL                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BT_HCIUART_NOKIA                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BT_HCIUART_QCA                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BT_HCIUART_RTL                           policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_BT_HCIUART_SERDEV                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BT_HCIVHCI                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BT_HIDP                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BT_INTEL                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BT_LE                                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BT_LEDS                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BT_MRVL                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BT_MRVL_SDIO                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BT_MTKSDIO                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BT_MTKUART                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BT_QCA                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BT_QCOMSMD                               policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_BT_RFCOMM                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BT_RFCOMM_TTY                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_BT_RTL                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BT_SELFTEST                              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_BT_WILINK                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_BUG                                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BUG_ON_DATA_CORRUPTION                   policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_BUILDTIME_EXTABLE_SORT                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BUILD_BIN2C                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_BUILD_SALT                               policy<{'amd64': '""', 'arm64': '""', 'armhf': '""', 'i386': '""', 'ppc64el': '""', 's390x': '""'}>
+CONFIG_C101                                     policy<{'i386': 'm'}>
+CONFIG_C2PORT                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_C2PORT_DURAMAR_2150                      policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_CACHEFILES                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CACHEFILES_DEBUG                         policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_CACHEFILES_HISTOGRAM                     policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_CACHE_FEROCEON_L2                        policy<{'armhf': 'y'}>
+CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH           policy<{'armhf': 'n'}>
+CONFIG_CACHE_L2X0                               policy<{'armhf': 'y'}>
+CONFIG_CACHE_L2X0_PMU                           policy<{'armhf': 'y'}>
+CONFIG_CACHE_TAUROS2                            policy<{'armhf': 'y'}>
+CONFIG_CACHE_UNIPHIER                           policy<{'armhf': 'y'}>
+CONFIG_CADENCE_WATCHDOG                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_CAIF                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_CAIF_DEBUG                               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_CAIF_HSI                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAIF_NETDEV                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAIF_SPI_SLAVE                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAIF_SPI_SYNC                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_CAIF_TTY                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAIF_USB                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAIF_VIRTIO                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CALGARY_IOMMU                            policy<{'amd64': 'y'}>
+CONFIG_CALGARY_IOMMU_ENABLED_BY_DEFAULT         policy<{'amd64': 'y'}>
+CONFIG_CAN                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_CAN_8DEV_USB                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_BCM                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_CALC_BITTIMING                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CAN_CC770                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_CC770_ISA                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_CC770_PLATFORM                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_C_CAN                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_C_CAN_PCI                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_C_CAN_PLATFORM                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_DEBUG_DEVICES                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_CAN_DEV                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_EMS_PCI                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_EMS_PCMCIA                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_CAN_EMS_USB                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_ESD_USB2                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_F81601                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_FLEXCAN                              policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_GRCAN                                policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_GS_USB                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_GW                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_HI311X                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_IFI_CANFD                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_J1939                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_JANZ_ICAN3                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_KVASER_PCI                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_KVASER_PCIEFD                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_KVASER_USB                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_MCBA_USB                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_MCP251X                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_MSCAN                                policy<{'ppc64el': 'm'}>
+CONFIG_CAN_M_CAN                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_M_CAN_PLATFORM                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_M_CAN_TCAN4X5X                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_PEAK_PCI                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_PEAK_PCIEC                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CAN_PEAK_PCIEFD                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_PEAK_PCMCIA                          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_CAN_PEAK_USB                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_PLX_PCI                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_RAW                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_RCAR                                 policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_CAN_RCAR_CANFD                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_CAN_SJA1000                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_SJA1000_ISA                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_SJA1000_PLATFORM                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_SLCAN                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_SOFTING                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_SOFTING_CS                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_CAN_TI_HECC                              policy<{'armhf': 'm'}>
+CONFIG_CAN_TSCAN1                               policy<{'i386': 'm'}>
+CONFIG_CAN_UCAN                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_VCAN                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_VXCAN                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAN_XILINXCAN                            policy<{'arm64': 'm'}>
+CONFIG_CAPI_AVM                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CAPI_TRACE                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CARDBUS                                  policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_CARDMAN_4000                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_CARDMAN_4040                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_CARL9170                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CARL9170_DEBUGFS                         policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_CARL9170_HWRNG                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CARL9170_LEDS                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CARL9170_WPC                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CARMINE_DRAM_CUSTOM                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_CASSINI                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CAVIUM_CPT                               policy<{'arm64': 'm'}>
+CONFIG_CAVIUM_ERRATUM_22375                     policy<{'arm64': 'y'}>
+CONFIG_CAVIUM_ERRATUM_23144                     policy<{'arm64': 'y'}>
+CONFIG_CAVIUM_ERRATUM_23154                     policy<{'arm64': 'y'}>
+CONFIG_CAVIUM_ERRATUM_27456                     policy<{'arm64': 'y'}>
+CONFIG_CAVIUM_ERRATUM_30115                     policy<{'arm64': 'y'}>
+CONFIG_CAVIUM_PTP                               policy<{'amd64': 'm', 'arm64': 'm', 'ppc64el': 'm'}>
+CONFIG_CAVIUM_TX2_ERRATUM_219                   policy<{'arm64': 'y'}>
+CONFIG_CB710_CORE                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_CB710_DEBUG                              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_CB710_DEBUG_ASSUMPTIONS                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CC10001_ADC                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_CCS811                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CCW                                      policy<{'s390x': 'y'}>
+CONFIG_CCWGROUP                                 policy<{'s390x': 'm'}>
+CONFIG_CCW_CONSOLE                              policy<{'s390x': 'y'}>
+CONFIG_CC_CAN_LINK                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CC_HAS_ASM_GOTO                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CC_HAS_ASM_INLINE                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CC_HAS_KASAN_GENERIC                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CC_HAS_SANCOV_TRACE_PC                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CC_HAS_SANE_STACKPROTECTOR               policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_CC_HAS_STACKPROTECTOR_NONE               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG            policy<{'arm64': 'y'}>
+CONFIG_CC_IS_GCC                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CC_OPTIMIZE_FOR_SIZE                     policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_CDNS_I3C_MASTER                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CDROM                                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CDROM_PKTCDVD                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_CDROM_PKTCDVD_BUFFERS                    policy<{'amd64': '8', 'arm64': '8', 'armhf': '8', 'i386': '8', 'ppc64el': '8'}>
+CONFIG_CDROM_PKTCDVD_WCACHE                     policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_CEC_CORE                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CEC_GPIO                                 policy<{'amd64-lowlatency': 'm', 'i386-lowlatency': 'm'}>
+CONFIG_CEC_NOTIFIER                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CEC_PIN                                  policy<{'amd64-lowlatency': 'y', 'arm64': 'y', 'i386-lowlatency': 'y'}>
+CONFIG_CEC_PIN_ERROR_INJ                        policy<{'amd64-lowlatency': 'n', 'arm64': 'n', 'i386-lowlatency': 'n'}>
+CONFIG_CEC_PLATFORM_DRIVERS                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CEPH_FS                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CEPH_FSCACHE                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CEPH_FS_POSIX_ACL                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CEPH_FS_SECURITY_LABEL                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CEPH_LIB                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CEPH_LIB_PRETTYDEBUG                     policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_CEPH_LIB_USE_DNS_RESOLVER                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CFAG12864B                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_CFAG12864B_RATE                          policy<{'amd64': '20', 'i386': '20'}>
+CONFIG_CFG80211                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CFG80211_CERTIFICATION_ONUS              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_CFG80211_CRDA_SUPPORT                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CFG80211_DEBUGFS                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CFG80211_DEFAULT_PS                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CFG80211_DEVELOPER_WARNINGS              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_CFG80211_REQUIRE_SIGNED_REGDB            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CFG80211_USE_KERNEL_REGDB_KEYS           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CFG80211_WEXT                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CFG80211_WEXT_EXPORT                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CFS_BANDWIDTH                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CGROUPS                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CGROUP_BPF                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CGROUP_CPUACCT                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CGROUP_DEBUG                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_CGROUP_DEVICE                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CGROUP_FREEZER                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CGROUP_HUGETLB                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf-generic-lpae': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CGROUP_NET_CLASSID                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CGROUP_NET_PRIO                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CGROUP_PERF                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CGROUP_PIDS                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CGROUP_RDMA                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CGROUP_SCHED                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CGROUP_WRITEBACK                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CHARGER_88PM860X                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CHARGER_ADP5061                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CHARGER_AXP20X                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CHARGER_BD70528                          policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_CHARGER_BQ2415X                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CHARGER_BQ24190                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CHARGER_BQ24257                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CHARGER_BQ24735                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CHARGER_BQ25890                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CHARGER_CPCAP                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_CHARGER_CROS_USBPD                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_CHARGER_DA9150                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CHARGER_DETECTOR_MAX14656                policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_CHARGER_GPIO                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CHARGER_ISP1704                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CHARGER_LP8727                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CHARGER_LP8788                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CHARGER_LT3651                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CHARGER_MANAGER                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CHARGER_MAX14577                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CHARGER_MAX77650                         policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_CHARGER_MAX77693                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CHARGER_MAX8903                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CHARGER_MAX8997                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CHARGER_MAX8998                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CHARGER_PCF50633                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CHARGER_QCOM_SMBB                        policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_CHARGER_RT9455                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CHARGER_SBS                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CHARGER_SC2731                           policy<{'arm64': 'm'}>
+CONFIG_CHARGER_SMB347                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CHARGER_TPS65090                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CHARGER_TPS65217                         policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_CHARGER_TWL4030                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CHARGER_UCS1002                          policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_CHARGER_WILCO                            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_CHARLCD                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CHARLCD_BL_FLASH                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CHARLCD_BL_OFF                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_CHARLCD_BL_ON                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_CHECKPOINT_RESTORE                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CHECK_SIGNATURE                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CHELSIO_IPSEC_INLINE                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CHELSIO_LIB                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CHELSIO_T1                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CHELSIO_T1_1G                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CHELSIO_T3                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CHELSIO_T4                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CHELSIO_T4VF                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CHELSIO_T4_DCB                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CHELSIO_T4_FCOE                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CHROMEOS_LAPTOP                          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_CHROMEOS_PSTORE                          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_CHROMEOS_TBMC                            policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_CHROME_PLATFORMS                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_CHR_DEV_SCH                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CHR_DEV_ST                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CHSC_SCH                                 policy<{'s390x': 'm'}>
+CONFIG_CICADA_PHY                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CIFS                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CIFS_ALLOW_INSECURE_LEGACY               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CIFS_DEBUG                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CIFS_DEBUG2                              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_CIFS_DEBUG_DUMP_KEYS                     policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_CIFS_DFS_UPCALL                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CIFS_FSCACHE                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CIFS_POSIX                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CIFS_SMB_DIRECT                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_CIFS_STATS2                              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_CIFS_UPCALL                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CIFS_WEAK_PW_HASH                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CIFS_XATTR                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CIO_DAC                                  policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_CLANG_VERSION                            policy<{'amd64': '0', 'arm64': '0', 'armhf': '0', 'i386': '0', 'ppc64el': '0', 's390x': '0'}>
+CONFIG_CLEANCACHE                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CLKBLD_I8253                             policy<{'amd64': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CLKDEV_LOOKUP                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_CLKEVT_I8253                             policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK      policy<{'armhf': 'y'}>
+CONFIG_CLKSRC_EXYNOS_MCT                        policy<{'armhf': 'y'}>
+CONFIG_CLKSRC_I8253                             policy<{'i386': 'y'}>
+CONFIG_CLKSRC_IMX_GPT                           policy<{'armhf-generic': 'y'}>
+CONFIG_CLKSRC_IMX_TPM                           policy<{'armhf-generic': 'y'}>
+CONFIG_CLKSRC_MMIO                              policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_CLKSRC_QCOM                              policy<{'armhf': 'y'}>
+CONFIG_CLKSRC_TI_32K                            policy<{'armhf': 'y'}>
+CONFIG_CLKSRC_VERSATILE                         policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_CLK_ACTIONS                              policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_CLK_BCM2835                              policy<{'arm64': 'y'}>
+CONFIG_CLK_BCM_NS2                              policy<{'arm64': 'y'}>
+CONFIG_CLK_BCM_SR                               policy<{'arm64': 'y'}>
+CONFIG_CLK_EMEV2                                policy<{'armhf': 'y'}>
+CONFIG_CLK_HSDK                                 policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_CLK_IMX8MM                               policy<{'arm64': 'y'}>
+CONFIG_CLK_IMX8MN                               policy<{'arm64': 'y'}>
+CONFIG_CLK_IMX8MQ                               policy<{'arm64': 'y'}>
+CONFIG_CLK_IMX8QXP                              policy<{'arm64': 'y'}>
+CONFIG_CLK_OWL_S500                             policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_CLK_OWL_S700                             policy<{'arm64': 'y'}>
+CONFIG_CLK_OWL_S900                             policy<{'arm64': 'y'}>
+CONFIG_CLK_QORIQ                                policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_CLK_R7S9210                              policy<{'armhf': 'y'}>
+CONFIG_CLK_R8A7740                              policy<{'armhf': 'y'}>
+CONFIG_CLK_R8A7743                              policy<{'armhf': 'y'}>
+CONFIG_CLK_R8A7745                              policy<{'armhf': 'y'}>
+CONFIG_CLK_R8A77470                             policy<{'armhf': 'y'}>
+CONFIG_CLK_R8A774A1                             policy<{'arm64': 'y'}>
+CONFIG_CLK_R8A774C0                             policy<{'arm64': 'y'}>
+CONFIG_CLK_R8A7778                              policy<{'armhf': 'y'}>
+CONFIG_CLK_R8A7779                              policy<{'armhf': 'y'}>
+CONFIG_CLK_R8A7790                              policy<{'armhf': 'y'}>
+CONFIG_CLK_R8A7791                              policy<{'armhf': 'y'}>
+CONFIG_CLK_R8A7792                              policy<{'armhf': 'y'}>
+CONFIG_CLK_R8A7794                              policy<{'armhf': 'y'}>
+CONFIG_CLK_R8A7795                              policy<{'arm64': 'y'}>
+CONFIG_CLK_R8A7796                              policy<{'arm64': 'y'}>
+CONFIG_CLK_R8A77965                             policy<{'arm64': 'y'}>
+CONFIG_CLK_R8A77970                             policy<{'arm64': 'y'}>
+CONFIG_CLK_R8A77980                             policy<{'arm64': 'y'}>
+CONFIG_CLK_R8A77990                             policy<{'arm64': 'y'}>
+CONFIG_CLK_R8A77995                             policy<{'arm64': 'y'}>
+CONFIG_CLK_R9A06G032                            policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_CLK_RASPBERRYPI                          policy<{'arm64': 'm'}>
+CONFIG_CLK_RCAR_GEN2                            policy<{'armhf': 'y'}>
+CONFIG_CLK_RCAR_GEN2_CPG                        policy<{'armhf': 'y'}>
+CONFIG_CLK_RCAR_GEN3_CPG                        policy<{'arm64': 'y'}>
+CONFIG_CLK_RCAR_USB2_CLOCK_SEL                  policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_CLK_RENESAS                              policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_CLK_RENESAS_CPG_MSSR                     policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_CLK_RENESAS_CPG_MSTP                     policy<{'armhf': 'y'}>
+CONFIG_CLK_RENESAS_DIV6                         policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_CLK_RENESAS_LEGACY                       policy<{'armhf': 'y'}>
+CONFIG_CLK_RZA1                                 policy<{'armhf': 'y'}>
+CONFIG_CLK_SH73A0                               policy<{'armhf': 'y'}>
+CONFIG_CLK_SP810                                policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_CLK_SUNXI                                policy<{'arm64': 'y'}>
+CONFIG_CLK_SUNXI_CLOCKS                         policy<{'arm64': 'y'}>
+CONFIG_CLK_SUNXI_PRCM_SUN6I                     policy<{'arm64': 'y'}>
+CONFIG_CLK_SUNXI_PRCM_SUN8I                     policy<{'arm64': 'y'}>
+CONFIG_CLK_SUNXI_PRCM_SUN9I                     policy<{'arm64': 'y'}>
+CONFIG_CLK_TEGRA_BPMP                           policy<{'armhf-generic': 'y'}>
+CONFIG_CLK_TWL6040                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_CLK_UNIPHIER                             policy<{'armhf': 'y'}>
+CONFIG_CLK_VEXPRESS_OSC                         policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_CLOCKSOURCE_VALIDATE_LAST_CYCLE          policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_CLOCKSOURCE_WATCHDOG                     policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_CLOCK_THERMAL                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n'}>
+CONFIG_CLONE_BACKWARDS                          policy<{'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CLONE_BACKWARDS2                         policy<{'s390x': 'y'}>
+CONFIG_CLS_U32_MARK                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CLS_U32_PERF                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_CLZ_TAB                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CM32181                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CM3232                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CM3323                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CM3605                                   policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_CM36651                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CMA                                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CMA_ALIGNMENT                            policy<{'arm64': '8', 'armhf': '8'}>
+CONFIG_CMA_AREAS                                policy<{'amd64': '7', 'arm64': '7', 'armhf': '7', 'i386': '7', 'ppc64el': '7', 's390x': '7'}>
+CONFIG_CMA_DEBUG                                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_CMA_DEBUGFS                              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_CMA_SIZE_SEL_MAX                         policy<{'arm64': 'n', 'armhf': 'n'}>
+CONFIG_CMA_SIZE_SEL_MBYTES                      policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_CMA_SIZE_SEL_MIN                         policy<{'arm64': 'n', 'armhf': 'n'}>
+CONFIG_CMA_SIZE_SEL_PERCENTAGE                  policy<{'arm64': 'n', 'armhf': 'n'}>
+CONFIG_CMDLINE                                  policy<{'arm64': '"console=ttyAMA0"', 'armhf': '""', 'ppc64el': '""'}>
+CONFIG_CMDLINE_BOOL                             policy<{'amd64': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_CMDLINE_FORCE                            policy<{'arm64': 'n'}>
+CONFIG_CMDLINE_PARTITION                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_CMM                                      policy<{'ppc64el': 'm', 's390x': 'y'}>
+CONFIG_CMM_IUCV                                 policy<{'s390x': 'y'}>
+CONFIG_CMT_SPEECH                               policy<{'armhf-generic': 'm'}>
+CONFIG_CNIC                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CODA_FS                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CODE_PATCHING_SELFTEST                   policy<{'ppc64el': 'n'}>
+CONFIG_COMEDI                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_8254                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_8255                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_8255_PCI                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_8255_SA                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_ADDI_APCI_1032                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_ADDI_APCI_1500                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_ADDI_APCI_1516                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_ADDI_APCI_1564                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_ADDI_APCI_16XX                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_ADDI_APCI_2032                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_ADDI_APCI_2200                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_ADDI_APCI_3120                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_ADDI_APCI_3501                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_ADDI_APCI_3XXX                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_ADDI_WATCHDOG                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_ADL_PCI6208                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_ADL_PCI7X3X                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_ADL_PCI8164                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_ADL_PCI9111                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_ADL_PCI9118                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_ADQ12B                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_ADV_PCI1710                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_ADV_PCI1720                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_ADV_PCI1723                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_ADV_PCI1724                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_ADV_PCI1760                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_ADV_PCI_DIO                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_AIO_AIO12_8                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_AIO_IIRO_16                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_AMPLC_DIO200                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_AMPLC_DIO200_ISA                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_AMPLC_DIO200_PCI                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_AMPLC_PC236                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_AMPLC_PC236_ISA                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_AMPLC_PC236_PCI                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_AMPLC_PC263_ISA                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_AMPLC_PC263_PCI                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_AMPLC_PCI224                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_AMPLC_PCI230                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_BOND                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_C6XDIGIO                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_CB_DAS16_CS                       policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_COMEDI_CB_PCIDAS                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_CB_PCIDAS64                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_CB_PCIDDA                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_CB_PCIMDAS                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_CB_PCIMDDA                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_CONTEC_PCI_DIO                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_DAC02                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_DAQBOARD2000                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_DAS08                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_DAS08_CS                          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_COMEDI_DAS08_ISA                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_DAS08_PCI                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_DAS16                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_DAS16M1                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_DAS1800                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_DAS6402                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_DAS800                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_DEBUG                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_COMEDI_DEFAULT_BUF_MAXSIZE_KB            policy<{'amd64': '20480', 'arm64': '20480', 'armhf': '20480', 'i386': '20480', 'ppc64el': '20480'}>
+CONFIG_COMEDI_DEFAULT_BUF_SIZE_KB               policy<{'amd64': '2048', 'arm64': '2048', 'armhf': '2048', 'i386': '2048', 'ppc64el': '2048'}>
+CONFIG_COMEDI_DMM32AT                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_DT2801                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_DT2811                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_DT2814                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_DT2815                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_DT2817                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_DT282X                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_DT3000                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_DT9812                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_DYNA_PCI10XX                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_FL512                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_GSC_HPDI                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_ICP_MULTI                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_II_PCI20KC                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_ISADMA                            policy<{'amd64': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_ISA_DRIVERS                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_COMEDI_JR3_PCI                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_KCOMEDILIB                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_KE_COUNTER                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_ME4000                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_ME_DAQ                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_MF6X4                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_MISC_DRIVERS                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_COMEDI_MITE                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_MPC624                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_MULTIQ3                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_NI_6527                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_NI_65XX                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_NI_660X                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_NI_670X                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_NI_ATMIO                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_NI_ATMIO16D                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_NI_AT_A2150                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_NI_AT_AO                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_NI_DAQ_700_CS                     policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_COMEDI_NI_DAQ_DIO24_CS                   policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_COMEDI_NI_LABPC                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_NI_LABPC_CS                       policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_COMEDI_NI_LABPC_ISA                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_NI_LABPC_ISADMA                   policy<{'amd64': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_NI_LABPC_PCI                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_NI_MIO_CS                         policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_COMEDI_NI_PCIDIO                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_NI_PCIMIO                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_NI_ROUTING                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_NI_TIO                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_NI_TIOCMD                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_NI_USB6501                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_PARPORT                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_PCI_DRIVERS                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_PCL711                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_PCL724                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_PCL726                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_PCL730                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_PCL812                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_PCL816                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_PCL818                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_PCM3724                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_PCMAD                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_PCMCIA_DRIVERS                    policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_COMEDI_PCMDA12                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_PCMMIO                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_PCMUIO                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_QUATECH_DAQP_CS                   policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_COMEDI_RTD520                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_RTI800                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_RTI802                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_S526                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_S626                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_SSV_DNP                           policy<{'i386': 'm'}>
+CONFIG_COMEDI_TEST                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_USBDUX                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_USBDUXFAST                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_USBDUXSIGMA                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_USB_DRIVERS                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMEDI_VMK80XX                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_COMMON_CLK                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_COMMON_CLK_ASPEED                        policy<{'armhf': 'y'}>
+CONFIG_COMMON_CLK_AXG                           policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_AXG_AUDIO                     policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_COMMON_CLK_BD718XX                       policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_COMMON_CLK_CDCE706                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_COMMON_CLK_CDCE925                       policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_COMMON_CLK_CS2000_CP                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_COMMON_CLK_FIXED_MMIO                    policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_COMMON_CLK_G12A                          policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_GXBB                          policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_HI3516CV300                   policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_COMMON_CLK_HI3519                        policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_COMMON_CLK_HI3660                        policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_COMMON_CLK_HI3670                        policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_COMMON_CLK_HI3798CV200                   policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_COMMON_CLK_HI6220                        policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_COMMON_CLK_HI655X                        policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_COMMON_CLK_IPROC                         policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_LOCHNAGAR                     policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_COMMON_CLK_MAX77686                      policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_COMMON_CLK_MAX9485                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_COMMON_CLK_MEDIATEK                      policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_COMMON_CLK_MESON8B                       policy<{'armhf': 'y'}>
+CONFIG_COMMON_CLK_MESON_AO_CLKC                 policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MESON_CPU_DYNDIV              policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MESON_DUALDIV                 policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MESON_EE_CLKC                 policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MESON_MPLL                    policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_COMMON_CLK_MESON_PHASE                   policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_COMMON_CLK_MESON_PLL                     policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_COMMON_CLK_MESON_REGMAP                  policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_COMMON_CLK_MESON_SCLK_DIV                policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_COMMON_CLK_MESON_VID_PLL_DIV             policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MT2701                        policy<{'armhf': 'n'}>
+CONFIG_COMMON_CLK_MT2712                        policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MT2712_BDPSYS                 policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MT2712_IMGSYS                 policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MT2712_JPGDECSYS              policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MT2712_MFGCFG                 policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MT2712_MMSYS                  policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MT2712_VDECSYS                policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MT2712_VENCSYS                policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MT6779                        policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MT6779_AUDSYS                 policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MT6779_CAMSYS                 policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MT6779_IMGSYS                 policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MT6779_IPESYS                 policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MT6779_MFGCFG                 policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MT6779_MMSYS                  policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MT6779_VDECSYS                policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MT6779_VENCSYS                policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MT6797                        policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MT6797_IMGSYS                 policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MT6797_MMSYS                  policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MT6797_VDECSYS                policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MT6797_VENCSYS                policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MT7622                        policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_COMMON_CLK_MT7622_AUDSYS                 policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_COMMON_CLK_MT7622_ETHSYS                 policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_COMMON_CLK_MT7622_HIFSYS                 policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_COMMON_CLK_MT7629                        policy<{'armhf': 'y'}>
+CONFIG_COMMON_CLK_MT7629_ETHSYS                 policy<{'armhf': 'y'}>
+CONFIG_COMMON_CLK_MT7629_HIFSYS                 policy<{'armhf': 'y'}>
+CONFIG_COMMON_CLK_MT8135                        policy<{'armhf': 'y'}>
+CONFIG_COMMON_CLK_MT8173                        policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_COMMON_CLK_MT8183                        policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MT8183_AUDIOSYS               policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MT8183_CAMSYS                 policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MT8183_IMGSYS                 policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MT8183_IPU_ADL                policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MT8183_IPU_CONN               policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MT8183_IPU_CORE0              policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MT8183_IPU_CORE1              policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MT8183_MFGCFG                 policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MT8183_MMSYS                  policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MT8183_VDECSYS                policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MT8183_VENCSYS                policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_MT8516                        policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_COMMON_CLK_MT8516_AUDSYS                 policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_COMMON_CLK_PALMAS                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_COMMON_CLK_PWM                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_COMMON_CLK_QCOM                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_COMMON_CLK_RK808                         policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_COMMON_CLK_S2MPS11                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_COMMON_CLK_SAMSUNG                       policy<{'armhf': 'y'}>
+CONFIG_COMMON_CLK_SCMI                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_COMMON_CLK_SCPI                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_COMMON_CLK_SI514                         policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_COMMON_CLK_SI5341                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_COMMON_CLK_SI5351                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_COMMON_CLK_SI544                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_COMMON_CLK_SI570                         policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_COMMON_CLK_TI_ADPLL                      policy<{'armhf': 'y'}>
+CONFIG_COMMON_CLK_VC5                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_COMMON_CLK_VERSATILE                     policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_COMMON_CLK_WM831X                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_COMMON_CLK_XGENE                         policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_XLNX_CLKWZRD                  policy<{'arm64': 'n', 'armhf': 'n'}>
+CONFIG_COMMON_CLK_ZYNQMP                        policy<{'arm64': 'y'}>
+CONFIG_COMMON_RESET_HI3660                      policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_COMMON_RESET_HI6220                      policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_COMPACTION                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_COMPAL_LAPTOP                            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_COMPAT                                   policy<{'amd64': 'y', 'arm64': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_COMPAT_32                                policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_COMPAT_32BIT_TIME                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_COMPAT_BINFMT_ELF                        policy<{'amd64': 'y', 'arm64': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_COMPAT_FOR_U64_ALIGNMENT                 policy<{'amd64': 'y'}>
+CONFIG_COMPAT_NETLINK_MESSAGES                  policy<{'amd64': 'y', 'arm64': 'y', 'ppc64el': 'y'}>
+CONFIG_COMPAT_OLD_SIGACTION                     policy<{'amd64': 'y', 'arm64': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_COMPAT_VDSO                              policy<{'amd64': 'n', 'i386': 'n', 's390x': 'y'}>
+CONFIG_COMPILE_TEST                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_CONFIGFS_FS                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CONNECTOR                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CONSOLE_LOGLEVEL_DEFAULT                 policy<{'amd64': '7', 'arm64': '7', 'armhf': '7', 'i386': '7', 'ppc64el': '7', 's390x': '7'}>
+CONFIG_CONSOLE_LOGLEVEL_QUIET                   policy<{'amd64': '4', 'arm64': '4', 'armhf': '4', 'i386': '4', 'ppc64el': '4', 's390x': '4'}>
+CONFIG_CONSOLE_POLL                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CONSOLE_TRANSLATIONS                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CONTEXT_SWITCH_TRACER                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CONTIG_ALLOC                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_COPS                                     policy<{'amd64': '-', 'i386': 'm'}>
+CONFIG_COPS_DAYNA                               policy<{'amd64': '-', 'i386': 'y'}>
+CONFIG_COPS_TANGENT                             policy<{'amd64': '-', 'i386': 'y'}>
+CONFIG_CORDIC                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_COREDUMP                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CORESIGHT                                policy<{'arm64': 'n', 'armhf': 'n'}>
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CORTINA_PHY                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_COSA                                     policy<{'i386': 'm'}>
+CONFIG_COUNTER                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_CPA_DEBUG                                policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_CPCAP_ADC                                policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_CPU5_WDT                                 policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_CPUFREQ_DT_PLATDEV                       policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_CPUMASK_OFFSTACK                         policy<{'amd64': 'y'}>
+CONFIG_CPUSETS                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CPU_32v6K                                policy<{'armhf': 'y'}>
+CONFIG_CPU_32v7                                 policy<{'armhf': 'y'}>
+CONFIG_CPU_ABRT_EV7                             policy<{'armhf': 'y'}>
+CONFIG_CPU_BIG_ENDIAN                           policy<{'arm64': 'n', 'armhf': 'n', 'ppc64el': 'n', 's390x': 'y'}>
+CONFIG_CPU_BPREDICT_DISABLE                     policy<{'armhf': 'n'}>
+CONFIG_CPU_CACHE_V7                             policy<{'armhf': 'y'}>
+CONFIG_CPU_CACHE_VIPT                           policy<{'armhf': 'y'}>
+CONFIG_CPU_COPY_V6                              policy<{'armhf': 'y'}>
+CONFIG_CPU_CP15                                 policy<{'armhf': 'y'}>
+CONFIG_CPU_CP15_MMU                             policy<{'armhf': 'y'}>
+CONFIG_CPU_FREQ                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_CPU_FREQ_GOV_ATTR_SET                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CPU_FREQ_GOV_COMMON                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CPU_FREQ_GOV_SCHEDUTIL                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CPU_HAS_ASID                             policy<{'armhf': 'y'}>
+CONFIG_CPU_HOTPLUG_STATE_CONTROL                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_CPU_ICACHE_DISABLE                       policy<{'armhf': 'n'}>
+CONFIG_CPU_ICACHE_MISMATCH_WORKAROUND           policy<{'armhf': 'y'}>
+CONFIG_CPU_IDLE                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CPU_IDLE_GOV_HALTPOLL                    policy<{'amd64': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CPU_IDLE_GOV_LADDER                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CPU_IDLE_GOV_MENU                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CPU_IDLE_GOV_TEO                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CPU_IDLE_MULTIPLE_DRIVERS                policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_CPU_ISOLATION                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CPU_LITTLE_ENDIAN                        policy<{'ppc64el': 'y'}>
+CONFIG_CPU_PABRT_V7                             policy<{'armhf': 'y'}>
+CONFIG_CPU_PJ4                                  policy<{'armhf': 'y'}>
+CONFIG_CPU_PJ4B                                 policy<{'armhf': 'y'}>
+CONFIG_CPU_PM                                   policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_CPU_RMAP                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CPU_SPECTRE                              policy<{'armhf': 'y'}>
+CONFIG_CPU_SUP_AMD                              policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_CPU_SUP_CENTAUR                          policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_CPU_SUP_CYRIX_32                         policy<{'i386': 'y'}>
+CONFIG_CPU_SUP_HYGON                            policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_CPU_SUP_INTEL                            policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_CPU_SUP_TRANSMETA_32                     policy<{'i386': 'y'}>
+CONFIG_CPU_SUP_UMC_32                           policy<{'i386': 'y'}>
+CONFIG_CPU_SUP_ZHAOXIN                          policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_CPU_SW_DOMAIN_PAN                        policy<{'armhf-generic': 'y'}>
+CONFIG_CPU_THERMAL                              policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_CPU_THUMB_CAPABLE                        policy<{'armhf': 'y'}>
+CONFIG_CPU_TLB_V7                               policy<{'armhf': 'y'}>
+CONFIG_CPU_V7                                   policy<{'armhf': 'y'}>
+CONFIG_CRAMFS                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_CRAMFS_BLOCKDEV                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CRAMFS_MTD                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_CRASH_CORE                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRC16                                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRC32                                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRC32_BIT                                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_CRC32_SARWATE                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_CRC32_SELFTEST                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_CRC32_SLICEBY4                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_CRC32_SLICEBY8                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRC4                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRC64                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRC7                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRC8                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRC_CCITT                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRC_ITU_T                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRC_T10DIF                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CROSS_MEMORY_ATTACH                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CROS_EC                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_CROS_EC_CHARDEV                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_CROS_EC_DEBUGFS                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_CROS_EC_I2C                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_CROS_EC_ISHTP                            policy<{'amd64': 'm'}>
+CONFIG_CROS_EC_LIGHTBAR                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_CROS_EC_LPC                              policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_CROS_EC_PROTO                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_CROS_EC_RPMSG                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_CROS_EC_SPI                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_CROS_EC_SYSFS                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_CROS_EC_VBC                              policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_CROS_KBD_LED_BACKLIGHT                   policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_CROS_USBPD_LOGGER                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_CRYPTO                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_842                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_ACOMP2                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_ADIANTUM                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_AEAD                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_AEAD2                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_AEGIS128                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_AEGIS128_AESNI_SSE2               policy<{'amd64': 'm'}>
+CONFIG_CRYPTO_AEGIS128_SIMD                     policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_CRYPTO_AES                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_AES_ARM                           policy<{'armhf': 'm'}>
+CONFIG_CRYPTO_AES_ARM64                         policy<{'arm64': 'm'}>
+CONFIG_CRYPTO_AES_ARM64_BS                      policy<{'arm64': 'm'}>
+CONFIG_CRYPTO_AES_ARM64_CE                      policy<{'arm64': 'm'}>
+CONFIG_CRYPTO_AES_ARM64_CE_BLK                  policy<{'arm64': 'm'}>
+CONFIG_CRYPTO_AES_ARM64_CE_CCM                  policy<{'arm64': 'm'}>
+CONFIG_CRYPTO_AES_ARM64_NEON_BLK                policy<{'arm64': 'm'}>
+CONFIG_CRYPTO_AES_ARM_BS                        policy<{'armhf': 'm'}>
+CONFIG_CRYPTO_AES_ARM_CE                        policy<{'armhf': 'm'}>
+CONFIG_CRYPTO_AES_NI_INTEL                      policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_CRYPTO_AES_S390                          policy<{'s390x': 'm'}>
+CONFIG_CRYPTO_AES_TI                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_AKCIPHER                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_AKCIPHER2                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_ALGAPI                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_ALGAPI2                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_ANSI_CPRNG                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_ANUBIS                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_ARC4                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_AUTHENC                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_BLKCIPHER                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_BLKCIPHER2                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_BLOWFISH                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_BLOWFISH_COMMON                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_BLOWFISH_X86_64                   policy<{'amd64': 'm'}>
+CONFIG_CRYPTO_CAMELLIA                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_CAMELLIA_AESNI_AVX2_X86_64        policy<{'amd64': 'm'}>
+CONFIG_CRYPTO_CAMELLIA_AESNI_AVX_X86_64         policy<{'amd64': 'm'}>
+CONFIG_CRYPTO_CAMELLIA_X86_64                   policy<{'amd64': 'm'}>
+CONFIG_CRYPTO_CAST5                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_CAST5_AVX_X86_64                  policy<{'amd64': 'm'}>
+CONFIG_CRYPTO_CAST6                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_CAST6_AVX_X86_64                  policy<{'amd64': 'm'}>
+CONFIG_CRYPTO_CAST_COMMON                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_CBC                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_CCM                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_CFB                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_CHACHA20                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_CHACHA20POLY1305                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_CHACHA20_NEON                     policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_CRYPTO_CHACHA20_X86_64                   policy<{'amd64': 'm'}>
+CONFIG_CRYPTO_CMAC                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_CRC32                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_CRC32C                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_CRC32C_INTEL                      policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_CRYPTO_CRC32C_VPMSUM                     policy<{'ppc64el': 'm'}>
+CONFIG_CRYPTO_CRC32_ARM_CE                      policy<{'armhf': 'm'}>
+CONFIG_CRYPTO_CRC32_PCLMUL                      policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_CRYPTO_CRC32_S390                        policy<{'s390x': 'm'}>
+CONFIG_CRYPTO_CRCT10DIF                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_CRCT10DIF_ARM64_CE                policy<{'arm64': 'm'}>
+CONFIG_CRYPTO_CRCT10DIF_ARM_CE                  policy<{'armhf': 'm'}>
+CONFIG_CRYPTO_CRCT10DIF_PCLMUL                  policy<{'amd64': 'm'}>
+CONFIG_CRYPTO_CRCT10DIF_VPMSUM                  policy<{'ppc64el': 'm'}>
+CONFIG_CRYPTO_CRYPTD                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_CTR                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_CTS                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_DEFLATE                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'm'}>
+CONFIG_CRYPTO_DES                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_DES3_EDE_X86_64                   policy<{'amd64': 'm'}>
+CONFIG_CRYPTO_DES_S390                          policy<{'s390x': 'm'}>
+CONFIG_CRYPTO_DEV_ARTPEC6                       policy<{'armhf': 'm'}>
+CONFIG_CRYPTO_DEV_ATMEL_ECC                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_CRYPTO_DEV_ATMEL_I2C                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CRYPTO_DEV_ATMEL_SHA204A                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_CRYPTO_DEV_BCM_SPU                       policy<{'arm64': 'm'}>
+CONFIG_CRYPTO_DEV_CAVIUM_ZIP                    policy<{'arm64': 'm'}>
+CONFIG_CRYPTO_DEV_CCP                           policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_CRYPTO_DEV_CCP_CRYPTO                    policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_CRYPTO_DEV_CCP_DD                        policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_CRYPTO_DEV_CCP_DEBUGFS                   policy<{'amd64': 'n', 'arm64': 'n', 'i386': 'n'}>
+CONFIG_CRYPTO_DEV_CCREE                         policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_CRYPTO_DEV_CHELSIO                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CRYPTO_DEV_CHELSIO_TLS                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_CRYPTO_DEV_CPT                           policy<{'arm64': 'm'}>
+CONFIG_CRYPTO_DEV_EXYNOS_RNG                    policy<{'armhf': 'm'}>
+CONFIG_CRYPTO_DEV_FSL_CAAM                      policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API            policy<{'arm64': 'y', 'armhf-generic': 'y'}>
+CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API_DESC       policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_CRYPTO_DEV_FSL_CAAM_COMMON               policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API           policy<{'arm64': 'y', 'armhf-generic': 'y'}>
+CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_DESC      policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI        policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_DEV_FSL_CAAM_DEBUG                policy<{'arm64': 'n', 'armhf-generic': 'n'}>
+CONFIG_CRYPTO_DEV_FSL_CAAM_INTC                 policy<{'arm64': 'y', 'armhf-generic': 'y'}>
+CONFIG_CRYPTO_DEV_FSL_CAAM_INTC_COUNT_THLD      policy<{'arm64': '255', 'armhf-generic': '255'}>
+CONFIG_CRYPTO_DEV_FSL_CAAM_INTC_TIME_THLD       policy<{'arm64': '2048', 'armhf-generic': '2048'}>
+CONFIG_CRYPTO_DEV_FSL_CAAM_JR                   policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_CRYPTO_DEV_FSL_CAAM_PKC_API              policy<{'arm64': 'y', 'armhf-generic': 'y'}>
+CONFIG_CRYPTO_DEV_FSL_CAAM_RINGSIZE             policy<{'arm64': '9', 'armhf-generic': '9'}>
+CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API              policy<{'arm64': 'y', 'armhf-generic': 'y'}>
+CONFIG_CRYPTO_DEV_FSL_DPAA2_CAAM                policy<{'arm64': 'm'}>
+CONFIG_CRYPTO_DEV_GEODE                         policy<{'i386': 'm'}>
+CONFIG_CRYPTO_DEV_HIFN_795X                     policy<{'armhf-generic': 'm'}>
+CONFIG_CRYPTO_DEV_HIFN_795X_RNG                 policy<{'armhf-generic': 'y'}>
+CONFIG_CRYPTO_DEV_HISI_HPRE                     policy<{'arm64': 'm'}>
+CONFIG_CRYPTO_DEV_HISI_QM                       policy<{'arm64': 'm'}>
+CONFIG_CRYPTO_DEV_HISI_SEC                      policy<{'arm64': 'm'}>
+CONFIG_CRYPTO_DEV_HISI_SEC2                     policy<{'arm64': 'm'}>
+CONFIG_CRYPTO_DEV_HISI_ZIP                      policy<{'arm64': 'm'}>
+CONFIG_CRYPTO_DEV_MARVELL_CESA                  policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_CRYPTO_DEV_MEDIATEK                      policy<{'armhf': 'm'}>
+CONFIG_CRYPTO_DEV_MXS_DCP                       policy<{'arm64': 'n', 'armhf-generic': 'n'}>
+CONFIG_CRYPTO_DEV_NITROX                        policy<{'amd64': 'm', 'arm64': 'm', 'ppc64el': 'm'}>
+CONFIG_CRYPTO_DEV_NITROX_CNN55XX                policy<{'amd64': 'm', 'arm64': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_CRYPTO_DEV_NX                            policy<{'ppc64el': 'y'}>
+CONFIG_CRYPTO_DEV_NX_COMPRESS                   policy<{'ppc64el': 'm'}>
+CONFIG_CRYPTO_DEV_NX_COMPRESS_POWERNV           policy<{'ppc64el': 'm'}>
+CONFIG_CRYPTO_DEV_NX_COMPRESS_PSERIES           policy<{'ppc64el': 'm'}>
+CONFIG_CRYPTO_DEV_OMAP                          policy<{'armhf': 'm'}>
+CONFIG_CRYPTO_DEV_OMAP_AES                      policy<{'armhf': 'm'}>
+CONFIG_CRYPTO_DEV_OMAP_DES                      policy<{'armhf': 'm'}>
+CONFIG_CRYPTO_DEV_OMAP_SHAM                     policy<{'armhf': 'm'}>
+CONFIG_CRYPTO_DEV_PADLOCK                       policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_CRYPTO_DEV_PADLOCK_AES                   policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_CRYPTO_DEV_PADLOCK_SHA                   policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_CRYPTO_DEV_QAT                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_CRYPTO_DEV_QAT_C3XXX                     policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_CRYPTO_DEV_QAT_C3XXXVF                   policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_CRYPTO_DEV_QAT_C62X                      policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_CRYPTO_DEV_QAT_C62XVF                    policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_CRYPTO_DEV_QAT_DH895xCC                  policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_CRYPTO_DEV_QAT_DH895xCCVF                policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_CRYPTO_DEV_QCE                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_CRYPTO_DEV_QCOM_RNG                      policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_CRYPTO_DEV_ROCKCHIP                      policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_CRYPTO_DEV_S5P                           policy<{'armhf': 'm'}>
+CONFIG_CRYPTO_DEV_SAFEXCEL                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_CRYPTO_DEV_SAHARA                        policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_CRYPTO_DEV_SP_CCP                        policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_CRYPTO_DEV_SP_PSP                        policy<{'amd64': 'y'}>
+CONFIG_CRYPTO_DEV_VIRTIO                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_DEV_VMX                           policy<{'ppc64el': 'y'}>
+CONFIG_CRYPTO_DEV_VMX_ENCRYPT                   policy<{'ppc64el': 'm'}>
+CONFIG_CRYPTO_DH                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_DRBG                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_DRBG_CTR                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_DRBG_HASH                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_DRBG_HMAC                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_DRBG_MENU                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_ECB                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_ECC                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_ECDH                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_ECHAINIV                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_ECRDSA                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_ENGINE                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_ESSIV                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_FCRYPT                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_GCM                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_GF128MUL                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_GHASH                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_GHASH_ARM64_CE                    policy<{'arm64': 'm'}>
+CONFIG_CRYPTO_GHASH_ARM_CE                      policy<{'armhf': 'm'}>
+CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL              policy<{'amd64': 'm'}>
+CONFIG_CRYPTO_GHASH_S390                        policy<{'s390x': 'm'}>
+CONFIG_CRYPTO_GLUE_HELPER_X86                   policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_CRYPTO_HASH                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_HASH2                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_HASH_INFO                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_HMAC                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_HW                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_JITTERENTROPY                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_KEYWRAP                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_KHAZAD                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_KPP                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_KPP2                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_LIB_AES                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_LIB_ARC4                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_LIB_DES                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_LIB_SHA256                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_LRW                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_LZ4                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_LZ4HC                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_LZO                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_MANAGER                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_MANAGER2                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_MD4                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_MD5                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_MD5_PPC                           policy<{'ppc64el': 'm'}>
+CONFIG_CRYPTO_MICHAEL_MIC                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_NHPOLY1305                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_NHPOLY1305_AVX2                   policy<{'amd64': 'm'}>
+CONFIG_CRYPTO_NHPOLY1305_NEON                   policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_CRYPTO_NHPOLY1305_SSE2                   policy<{'amd64': 'm'}>
+CONFIG_CRYPTO_NULL                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_NULL2                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_OFB                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_PAES_S390                         policy<{'s390x': 'm'}>
+CONFIG_CRYPTO_PCBC                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_PCRYPT                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_POLY1305                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_POLY1305_X86_64                   policy<{'amd64': 'm'}>
+CONFIG_CRYPTO_RMD128                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_RMD160                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_RMD256                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_RMD320                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_RNG                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_RNG2                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_RNG_DEFAULT                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_RSA                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_SALSA20                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_SEED                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_SEQIV                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_SERPENT                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_SERPENT_AVX2_X86_64               policy<{'amd64': 'm'}>
+CONFIG_CRYPTO_SERPENT_AVX_X86_64                policy<{'amd64': 'm'}>
+CONFIG_CRYPTO_SERPENT_SSE2_586                  policy<{'i386': 'm'}>
+CONFIG_CRYPTO_SERPENT_SSE2_X86_64               policy<{'amd64': 'm'}>
+CONFIG_CRYPTO_SHA1                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_SHA1_ARM                          policy<{'armhf': 'm'}>
+CONFIG_CRYPTO_SHA1_ARM64_CE                     policy<{'arm64': 'm'}>
+CONFIG_CRYPTO_SHA1_ARM_CE                       policy<{'armhf': 'm'}>
+CONFIG_CRYPTO_SHA1_ARM_NEON                     policy<{'armhf': 'm'}>
+CONFIG_CRYPTO_SHA1_PPC                          policy<{'ppc64el': 'm'}>
+CONFIG_CRYPTO_SHA1_S390                         policy<{'s390x': 'm'}>
+CONFIG_CRYPTO_SHA1_SSSE3                        policy<{'amd64': 'm'}>
+CONFIG_CRYPTO_SHA256                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_SHA256_ARM                        policy<{'armhf': 'm'}>
+CONFIG_CRYPTO_SHA256_ARM64                      policy<{'arm64': 'm'}>
+CONFIG_CRYPTO_SHA256_S390                       policy<{'s390x': 'm'}>
+CONFIG_CRYPTO_SHA256_SSSE3                      policy<{'amd64': 'm'}>
+CONFIG_CRYPTO_SHA2_ARM64_CE                     policy<{'arm64': 'm'}>
+CONFIG_CRYPTO_SHA2_ARM_CE                       policy<{'armhf': 'm'}>
+CONFIG_CRYPTO_SHA3                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_SHA3_256_S390                     policy<{'s390x': 'm'}>
+CONFIG_CRYPTO_SHA3_512_S390                     policy<{'s390x': 'm'}>
+CONFIG_CRYPTO_SHA3_ARM64                        policy<{'arm64': 'm'}>
+CONFIG_CRYPTO_SHA512_ARM                        policy<{'armhf': 'm'}>
+CONFIG_CRYPTO_SHA512_ARM64                      policy<{'arm64': 'm'}>
+CONFIG_CRYPTO_SHA512_ARM64_CE                   policy<{'arm64': 'm'}>
+CONFIG_CRYPTO_SHA512_S390                       policy<{'s390x': 'm'}>
+CONFIG_CRYPTO_SHA512_SSSE3                      policy<{'amd64': 'm'}>
+CONFIG_CRYPTO_SIMD                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_CRYPTO_SM3                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_SM3_ARM64_CE                      policy<{'arm64': 'm'}>
+CONFIG_CRYPTO_SM4                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_SM4_ARM64_CE                      policy<{'arm64': 'm'}>
+CONFIG_CRYPTO_STATS                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_STREEBOG                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_TEA                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_TEST                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_TGR192                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_TWOFISH                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_TWOFISH_586                       policy<{'i386': 'm'}>
+CONFIG_CRYPTO_TWOFISH_AVX_X86_64                policy<{'amd64': 'm'}>
+CONFIG_CRYPTO_TWOFISH_COMMON                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_TWOFISH_X86_64                    policy<{'amd64': 'm'}>
+CONFIG_CRYPTO_TWOFISH_X86_64_3WAY               policy<{'amd64': 'm'}>
+CONFIG_CRYPTO_USER                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_USER_API                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_USER_API_AEAD                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_USER_API_HASH                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_USER_API_RNG                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_USER_API_SKCIPHER                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_VMAC                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_VPMSUM_TESTER                     policy<{'ppc64el': 'm'}>
+CONFIG_CRYPTO_WP512                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_XCBC                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_XTS                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_CRYPTO_XXHASH                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CRYPTO_ZSTD                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CS89x0                                   policy<{'amd64': '-', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_CS89x0_PLATFORM                          policy<{'amd64': '-', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_CTCM                                     policy<{'s390x': 'm'}>
+CONFIG_CUSE                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_CW1200                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CW1200_WLAN_SDIO                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CW1200_WLAN_SPI                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CXD2880_SPI_DRV                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CXL                                      policy<{'ppc64el': 'm'}>
+CONFIG_CXLFLASH                                 policy<{'ppc64el': 'm'}>
+CONFIG_CXL_AFU_DRIVER_OPS                       policy<{'ppc64el': 'y'}>
+CONFIG_CXL_BASE                                 policy<{'ppc64el': 'y'}>
+CONFIG_CXL_LIB                                  policy<{'ppc64el': 'y'}>
+CONFIG_CX_ECAT                                  policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_CYCLADES                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CYPRESS_FIRMWARE                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_CYZ_INTR                                 policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_DA280                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DA311                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DA9052_WATCHDOG                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DA9055_WATCHDOG                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DA9062_THERMAL                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DA9062_WATCHDOG                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DA9063_WATCHDOG                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DA9150_GPADC                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DASD                                     policy<{'s390x': 'm'}>
+CONFIG_DASD_DIAG                                policy<{'s390x': 'm'}>
+CONFIG_DASD_ECKD                                policy<{'s390x': 'm'}>
+CONFIG_DASD_EER                                 policy<{'s390x': 'y'}>
+CONFIG_DASD_FBA                                 policy<{'s390x': 'm'}>
+CONFIG_DASD_PROFILE                             policy<{'s390x': 'y'}>
+CONFIG_DATA_SHIFT                               policy<{'ppc64el': '16'}>
+CONFIG_DAVICOM_PHY                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DAX                                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DAX_DRIVER                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf-generic-lpae': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DCA                                      policy<{'amd64': 'm'}>
+CONFIG_DCACHE_WORD_ACCESS                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_DCB                                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DCDBAS                                   policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_DCSSBLK                                  policy<{'s390x': 'm'}>
+CONFIG_DDR                                      policy<{'armhf': 'y'}>
+CONFIG_DE2104X                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DE2104X_DSL                              policy<{'amd64': '0', 'arm64': '0', 'armhf': '0', 'i386': '0', 'ppc64el': '0'}>
+CONFIG_DE4X5                                    policy<{'amd64': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DEBUGGER                                 policy<{'ppc64el': 'y'}>
+CONFIG_DEBUG_ALIGN_RODATA                       policy<{'arm64': 'n', 'armhf': 'y'}>
+CONFIG_DEBUG_ATOMIC_SLEEP                       policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_BLOCK_EXT_DEVT                     policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_BOOT_PARAMS                        policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_DEBUG_BUGVERBOSE                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DEBUG_CREDENTIALS                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_DEVRES                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_DRIVER                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_EFI                                policy<{'arm64': 'n'}>
+CONFIG_DEBUG_ENTRY                              policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_DEBUG_FORCE_WEAK_PER_CPU                 policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_GPIO                               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_HIGHMEM                            policy<{'armhf': 'n', 'i386': 'n'}>
+CONFIG_DEBUG_HOTPLUG_CPU0                       policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_DEBUG_INFO_BTF                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DEBUG_INFO_DWARF4                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DEBUG_INFO_REDUCED                       policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_KERNEL_DC                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_DEBUG_KMEMLEAK                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_KOBJECT                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_LIST                               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_LL                                 policy<{'armhf': 'n'}>
+CONFIG_DEBUG_LL_INCLUDE                         policy<{'armhf': '"mach/debug-macro.S"'}>
+CONFIG_DEBUG_LOCKING_API_SELFTESTS              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_LOCK_ALLOC                         policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_MEMORY_INIT                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_MISC                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DEBUG_MUTEXES                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_NMI_SELFTEST                       policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_DEBUG_NOTIFIERS                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_OBJECTS                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_PAGEALLOC                          policy<{'amd64': 'n', 'arm64': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_PAGE_REF                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_PERF_USE_VMALLOC                   policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_PER_CPU_MAPS                       policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_PINCTRL                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_DEBUG_PLIST                              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_PREEMPT                            policy<{'amd64-lowlatency': 'n', 'i386-lowlatency': 'n'}>
+CONFIG_DEBUG_RODATA_TEST                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_RSEQ                               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_RT_MUTEXES                         policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_RWSEMS                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_SECTION_MISMATCH                   policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_SG                                 policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_SHIRQ                              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_SPINLOCK                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_STACKOVERFLOW                      policy<{'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_DEBUG_STACK_USAGE                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_TEST_DRIVER_REMOVE                 policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_TIMEKEEPING                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_TLBFLUSH                           policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_DEBUG_USER                               policy<{'armhf': 'n'}>
+CONFIG_DEBUG_VF_UART_PORT                       policy<{'armhf-generic': '1'}>
+CONFIG_DEBUG_VIRTUAL                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_DEBUG_VM                                 policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_WQ_FORCE_RR_CPU                    policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_WW_MUTEX_SLOWPATH                  policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEBUG_WX                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_DECOMPRESS_BZIP2                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DECOMPRESS_GZIP                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DECOMPRESS_LZ4                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DECOMPRESS_LZMA                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DECOMPRESS_LZO                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DECOMPRESS_XZ                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DEFAULT_CUBIC                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DEFAULT_HOSTNAME                         policy<{'amd64': '"(none)"', 'arm64': '"(none)"', 'armhf': '"(none)"', 'i386': '"(none)"', 'ppc64el': '"(none)"', 's390x': '"(none)"'}>
+CONFIG_DEFAULT_HUNG_TASK_TIMEOUT                policy<{'amd64': '120', 'arm64': '120', 'armhf': '120', 'i386': '120', 'ppc64el': '120', 's390x': '120'}>
+CONFIG_DEFAULT_RENO                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEFAULT_SECURITY_APPARMOR                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DEFAULT_SECURITY_DAC                     policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEFAULT_SECURITY_SELINUX                 policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEFAULT_SECURITY_SMACK                   policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEFAULT_SECURITY_TOMOYO                  policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEFAULT_TCP_CONG                         policy<{'amd64': '"cubic"', 'arm64': '"cubic"', 'armhf': '"cubic"', 'i386': '"cubic"', 'ppc64el': '"cubic"', 's390x': '"cubic"'}>
+CONFIG_DEFERRED_STRUCT_PAGE_INIT                policy<{'amd64': 'n', 'arm64': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DEFXX                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DEFXX_MMIO                               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_DELL_LAPTOP                              policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_DELL_RBTN                                policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_DELL_RBU                                 policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_DELL_SMBIOS                              policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_DELL_SMBIOS_SMM                          policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_DELL_SMBIOS_WMI                          policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_DELL_SMO8800                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_DELL_UART_BACKLIGHT                      policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_DELL_WMI                                 policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_DELL_WMI_AIO                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_DELL_WMI_DESCRIPTOR                      policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_DELL_WMI_LED                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_DEPRECATED_PARAM_STRUCT                  policy<{'armhf': 'n'}>
+CONFIG_DETECT_HUNG_TASK                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DEVFREQ_EVENT_EXYNOS_NOCP                policy<{'armhf': 'y'}>
+CONFIG_DEVFREQ_EVENT_EXYNOS_PPMU                policy<{'armhf': 'y'}>
+CONFIG_DEVFREQ_EVENT_ROCKCHIP_DFI               policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_DEVFREQ_GOV_PASSIVE                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_DEVFREQ_GOV_PERFORMANCE                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_DEVFREQ_GOV_POWERSAVE                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_DEVFREQ_GOV_USERSPACE                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_DEVFREQ_THERMAL                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_DEVICE_PRIVATE                           policy<{'amd64': 'y', 'ppc64el': 'y'}>
+CONFIG_DEVMEM                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DEVPORT                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DEV_APPLETALK                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DEV_COREDUMP                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_DEV_DAX                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf-generic-lpae': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DEV_DAX_KMEM                             policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DEV_DAX_PMEM                             policy<{'amd64': 'm', 'ppc64el': 'm'}>
+CONFIG_DEV_DAX_PMEM_COMPAT                      policy<{'amd64': 'm', 'ppc64el': 'm'}>
+CONFIG_DEV_PAGEMAP_OPS                          policy<{'amd64': 'y', 'ppc64el': 'y'}>
+CONFIG_DHT11                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DIAG288_WATCHDOG                         policy<{'s390x': 'm'}>
+CONFIG_DIMLIB                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DL2K                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DLCI                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DLCI_MAX                                 policy<{'amd64': '8', 'arm64': '8', 'armhf': '8', 'i386': '8', 'ppc64el': '8'}>
+CONFIG_DLM                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DLM_DEBUG                                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DLN2_ADC                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DM9000                                   policy<{'armhf': 'm'}>
+CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL             policy<{'armhf': 'n'}>
+CONFIG_DM9102                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DMABUF_SELFTESTS                         policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DMADEVICES                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_DMADEVICES_DEBUG                         policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_DMARD06                                  policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DMARD09                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DMARD10                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DMAR_TABLE                               policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_DMATEST                                  policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_DMA_ACPI                                 policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_DMA_API_DEBUG                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DMA_BCM2835                              policy<{'arm64': 'y'}>
+CONFIG_DMA_DECLARE_COHERENT                     policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_DMA_DIRECT_REMAP                         policy<{'arm64': 'y'}>
+CONFIG_DMA_ENGINE                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_DMA_ENGINE_RAID                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y'}>
+CONFIG_DMA_FENCE_TRACE                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DMA_OF                                   policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_DMA_OMAP                                 policy<{'armhf': 'y'}>
+CONFIG_DMA_REMAP                                policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_DMA_SHARED_BUFFER                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DMA_SUN6I                                policy<{'arm64': 'm'}>
+CONFIG_DMA_VIRTUAL_CHANNELS                     policy<{'amd64': 'm', 'arm64': 'y', 'armhf': 'y', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DMA_VIRT_OPS                             policy<{'amd64': 'y', 'arm64': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DMI                                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_DMIID                                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_DMI_SCAN_MACHINE_NON_EFI_FALLBACK        policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_DMI_SYSFS                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_DM_BIO_PRISON                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DM_BUFIO                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DM_CACHE                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DM_CACHE_SMQ                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DM_CLONE                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DM_CRYPT                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DM_DEBUG                                 policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'y'}>
+CONFIG_DM_DEBUG_BLOCK_MANAGER_LOCKING           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DM_DELAY                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DM_DUST                                  policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DM_ERA                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DM_FLAKEY                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DM_INIT                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DM_INTEGRITY                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DM_LOG_USERSPACE                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DM_LOG_WRITES                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DM_MIRROR                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DM_MULTIPATH                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DM_MULTIPATH_QL                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DM_MULTIPATH_ST                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DM_PERSISTENT_DATA                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DM_RAID                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DM_SNAPSHOT                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DM_SWITCH                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DM_THIN_PROVISIONING                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DM_UEVENT                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DM_UNSTRIPED                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DM_VERITY                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DM_VERITY_FEC                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DM_WRITECACHE                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DM_ZERO                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DM_ZONED                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DNET                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_DNOTIFY                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DNS_RESOLVER                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DOUBLEFAULT                              policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_DOVE_CLK                                 policy<{'armhf': 'y'}>
+CONFIG_DOVE_THERMAL                             policy<{'armhf': 'm'}>
+CONFIG_DP83640_PHY                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DP83822_PHY                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DP83848_PHY                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DP83867_PHY                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DP83TC811_PHY                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DPAA2_CONSOLE                            policy<{'arm64': 'm'}>
+CONFIG_DPAA_ERRATUM_A050385                     policy<{'arm64': 'y'}>
+CONFIG_DPM_WATCHDOG                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_DPOT_DAC                                 policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DPS310                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DPTF_POWER                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_DQL                                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DRA752_THERMAL                           policy<{'armhf': 'y'}>
+CONFIG_DRAGONRISE_FF                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_DRBD_FAULT_INJECTION                     policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DRM                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DRM_AMDGPU                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_DRM_AMDGPU_GART_DEBUGFS                  policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_DRM_AMDGPU_SI                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_DRM_AMDGPU_USERPTR                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_DRM_AMD_ACP                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_DRM_AMD_DC                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_DRM_AMD_DC_DCN1_0                        policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_DRM_AMD_DC_DCN2_0                        policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_DRM_AMD_DC_DCN2_1                        policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_DRM_AMD_DC_DSC_SUPPORT                   policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_DRM_ANALOGIX_ANX78XX                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_DRM_ANALOGIX_DP                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_DRM_ARCPGU                               policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_ARMADA                               policy<{'armhf': 'm'}>
+CONFIG_DRM_ASPEED_GFX                           policy<{'armhf': 'm'}>
+CONFIG_DRM_AST                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_DRM_ATMEL_HLCDC                          policy<{'armhf': 'm'}>
+CONFIG_DRM_BRIDGE                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DRM_CDNS_DSI                             policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_CIRRUS_QEMU                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_DRM_DEBUG_SELFTEST                       policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DRM_DP_AUX_CHARDEV                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_DRM_DP_CEC                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_DRM_DUMB_VGA_DAC                         policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_DW_HDMI                              policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_DW_HDMI_AHB_AUDIO                    policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_DW_HDMI_CEC                          policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_DW_HDMI_I2S_AUDIO                    policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_DW_MIPI_DSI                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_DRM_ETNAVIV                              policy<{'amd64': 'n', 'arm64': 'm', 'armhf': 'm', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DRM_ETNAVIV_THERMAL                      policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_DRM_EXYNOS                               policy<{'armhf': 'm'}>
+CONFIG_DRM_EXYNOS5433_DECON                     policy<{'armhf': 'y'}>
+CONFIG_DRM_EXYNOS7_DECON                        policy<{'armhf': 'n'}>
+CONFIG_DRM_EXYNOS_DSI                           policy<{'armhf': 'y'}>
+CONFIG_DRM_EXYNOS_FIMC                          policy<{'armhf': 'y'}>
+CONFIG_DRM_EXYNOS_FIMD                          policy<{'armhf': 'n'}>
+CONFIG_DRM_EXYNOS_HDMI                          policy<{'armhf': 'y'}>
+CONFIG_DRM_EXYNOS_IPP                           policy<{'armhf': 'y'}>
+CONFIG_DRM_EXYNOS_MIC                           policy<{'armhf': 'y'}>
+CONFIG_DRM_EXYNOS_MIXER                         policy<{'armhf': 'y'}>
+CONFIG_DRM_EXYNOS_ROTATOR                       policy<{'armhf': 'y'}>
+CONFIG_DRM_EXYNOS_SCALER                        policy<{'armhf': 'y'}>
+CONFIG_DRM_EXYNOS_VIDI                          policy<{'armhf': 'n'}>
+CONFIG_DRM_FBDEV_EMULATION                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM                 policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_DRM_FBDEV_OVERALLOC                      policy<{'amd64': '100', 'arm64': '100', 'armhf': '100', 'i386': '100', 'ppc64el': '100', 's390x': '100'}>
+CONFIG_DRM_FSL_DCU                              policy<{'armhf': 'm'}>
+CONFIG_DRM_GEM_CMA_HELPER                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_DRM_GEM_SHMEM_HELPER                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_DRM_GM12U320                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_GMA3600                              policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_DRM_GMA500                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_DRM_GMA600                               policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_DRM_HDLCD                                policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_DRM_HDLCD_SHOW_UNDERRUN                  policy<{'arm64': 'n', 'armhf': 'n'}>
+CONFIG_DRM_HISI_KIRIN                           policy<{'arm64': 'm'}>
+CONFIG_DRM_I2C_ADV7511                          policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_I2C_ADV7511_AUDIO                    policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_DRM_I2C_ADV7511_CEC                      policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_DRM_I2C_ADV7533                          policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_DRM_I2C_CH7006                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_DRM_I2C_NXP_TDA9950                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_DRM_I2C_NXP_TDA998X                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_DRM_I2C_SIL164                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_DRM_I915                                 policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_DRM_I915_ALPHA_SUPPORT                   policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_DRM_I915_CAPTURE_ERROR                   policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_DRM_I915_COMPRESS_ERROR                  policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_DRM_I915_DEBUG                           policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_DRM_I915_DEBUG_GUC                       policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_DRM_I915_DEBUG_MMIO                      policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_DRM_I915_DEBUG_RUNTIME_PM                policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_DRM_I915_DEBUG_VBLANK_EVADE              policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_DRM_I915_FORCE_PROBE                     policy<{'amd64': '""', 'i386': '""'}>
+CONFIG_DRM_I915_GVT                             policy<{'amd64': 'y'}>
+CONFIG_DRM_I915_GVT_KVMGT                       policy<{'amd64': 'm'}>
+CONFIG_DRM_I915_LOW_LEVEL_TRACEPOINTS           policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_DRM_I915_SELFTEST                        policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_DRM_I915_SPIN_REQUEST                    policy<{'amd64': '5', 'i386': '5'}>
+CONFIG_DRM_I915_SW_FENCE_CHECK_DAG              policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_DRM_I915_SW_FENCE_DEBUG_OBJECTS          policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_DRM_I915_USERFAULT_AUTOSUSPEND           policy<{'amd64': '250', 'i386': '250'}>
+CONFIG_DRM_I915_USERPTR                         policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_DRM_I915_WERROR                          policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_DRM_IMX                                  policy<{'armhf': 'm'}>
+CONFIG_DRM_IMX_HDMI                             policy<{'armhf': 'm'}>
+CONFIG_DRM_IMX_LDB                              policy<{'armhf': 'm'}>
+CONFIG_DRM_IMX_PARALLEL_DISPLAY                 policy<{'armhf': 'm'}>
+CONFIG_DRM_IMX_TVE                              policy<{'armhf': 'm'}>
+CONFIG_DRM_KMS_CMA_HELPER                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_DRM_KMS_FB_HELPER                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DRM_KMS_HELPER                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DRM_KOMEDA                               policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_DRM_LIMA                                 policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_DRM_LOAD_EDID_FIRMWARE                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DRM_LVDS_ENCODER                         policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_MALI_DISPLAY                         policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_DRM_MCDE                                 policy<{'armhf': 'm'}>
+CONFIG_DRM_MEDFIELD                             policy<{'i386': 'y'}>
+CONFIG_DRM_MEDIATEK                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_DRM_MEDIATEK_HDMI                        policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW      policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_MESON                                policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_DRM_MESON_DW_HDMI                        policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_DRM_MIPI_DBI                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_MIPI_DSI                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_DRM_MSM                                  policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_DRM_MSM_DSI                              policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_DRM_MSM_DSI_10NM_PHY                     policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_DRM_MSM_DSI_14NM_PHY                     policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_DRM_MSM_DSI_20NM_PHY                     policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_DRM_MSM_DSI_28NM_8960_PHY                policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_DRM_MSM_DSI_28NM_PHY                     policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_DRM_MSM_DSI_PLL                          policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_DRM_MSM_GPU_STATE                        policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_DRM_MSM_GPU_SUDO                         policy<{'arm64': 'n', 'armhf': 'n'}>
+CONFIG_DRM_MSM_HDMI_HDCP                        policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_DRM_MSM_REGISTER_LOGGING                 policy<{'arm64': 'n', 'armhf': 'n'}>
+CONFIG_DRM_MXS                                  policy<{'arm64': 'y', 'armhf-generic': 'y'}>
+CONFIG_DRM_MXSFB                                policy<{'arm64': 'm', 'armhf-generic': 'm', 'armhf-generic-lpae': '-'}>
+CONFIG_DRM_NOUVEAU                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_DRM_NOUVEAU_BACKLIGHT                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_DRM_NOUVEAU_SVM                          policy<{'amd64': 'n', 'ppc64el': 'n'}>
+CONFIG_DRM_NXP_PTN3460                          policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_OMAP                                 policy<{'armhf': 'n'}>
+CONFIG_DRM_PANEL                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DRM_PANEL_ARM_VERSATILE                  policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_BRIDGE                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DRM_PANEL_FEIYANG_FY07024DI26A30D        policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_ILITEK_IL9322                  policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_ILITEK_ILI9881C                policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_INNOLUX_P079ZCA                policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_JDI_LT070ME05000               policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_KINGDISPLAY_KD097D04           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_LG_LB035Q02                    policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_LG_LG4573                      policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_LVDS                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_NEC_NL8048HL11                 policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_NOVATEK_NT39016                policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_OLIMEX_LCD_OLINUXINO           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_ORIENTATION_QUIRKS             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DRM_PANEL_ORISETECH_OTM8009A             policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_OSD_OSD101T2587_53TS           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00         policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_RAYDIUM_RM67191                policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_RAYDIUM_RM68200                policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_ROCKTECH_JH057N00900           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_RONBO_RB070D30                 policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_SAMSUNG_LD9040                 policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_SAMSUNG_S6D16D0                policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2                policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03             policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_SAMSUNG_S6E63M0                policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0                policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_SEIKO_43WVF1G                  policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_SHARP_LQ101R1SX01              policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_SHARP_LS037V7DW01              policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_SHARP_LS043T1LE01              policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_SIMPLE                         policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_SITRONIX_ST7701                policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_SITRONIX_ST7789V               policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_SONY_ACX565AKM                 policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_TPO_TD028TTEC1                 policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_TPO_TD043MTEA1                 policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_TPO_TPG110                     policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA            policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PANFROST                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_DRM_PARADE_PS8622                        policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_PL111                                policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_DRM_QXL                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_DRM_RADEON                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_DRM_RADEON_USERPTR                       policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_DRM_RCAR_DU                              policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_DRM_RCAR_DW_HDMI                         policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_RCAR_LVDS                            policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'n'}>
+CONFIG_DRM_RCAR_VSP                             policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_DRM_RCAR_WRITEBACK                       policy<{'arm64': 'y'}>
+CONFIG_DRM_ROCKCHIP                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_DRM_SCHED                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_SII902X                              policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_SII9234                              policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_SIL_SII8620                          policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_STM                                  policy<{'armhf': 'm'}>
+CONFIG_DRM_STM_DSI                              policy<{'armhf': 'm'}>
+CONFIG_DRM_SUN4I                                policy<{'arm64': 'm'}>
+CONFIG_DRM_SUN4I_BACKEND                        policy<{'arm64': 'm'}>
+CONFIG_DRM_SUN4I_HDMI                           policy<{'arm64': 'm'}>
+CONFIG_DRM_SUN4I_HDMI_CEC                       policy<{'arm64': 'y'}>
+CONFIG_DRM_SUN6I_DSI                            policy<{'arm64': 'm'}>
+CONFIG_DRM_SUN8I_DW_HDMI                        policy<{'arm64': 'm'}>
+CONFIG_DRM_SUN8I_MIXER                          policy<{'arm64': 'm'}>
+CONFIG_DRM_SUN8I_TCON_TOP                       policy<{'arm64': 'm'}>
+CONFIG_DRM_TEGRA                                policy<{'armhf-generic': 'm'}>
+CONFIG_DRM_TEGRA_DEBUG                          policy<{'armhf-generic': 'n'}>
+CONFIG_DRM_TEGRA_STAGING                        policy<{'armhf-generic': 'y'}>
+CONFIG_DRM_THINE_THC63LVD1024                   policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_TILCDC                               policy<{'armhf': 'm'}>
+CONFIG_DRM_TI_SN65DSI86                         policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_TI_TFP410                            policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_TOSHIBA_TC358764                     policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_TOSHIBA_TC358767                     policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_TTM                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DRM_TVE200                               policy<{'armhf': 'm'}>
+CONFIG_DRM_UDL                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DRM_VC4                                  policy<{'arm64': 'm'}>
+CONFIG_DRM_VC4_HDMI_CEC                         policy<{'arm64': 'y'}>
+CONFIG_DRM_VGEM                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_DRM_VIRTIO_GPU                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DRM_VKMS                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_DRM_VMWGFX                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_DRM_VMWGFX_FBCON                         policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_DRM_VRAM_HELPER                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DRM_XEN                                  policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_DRM_XEN_FRONTEND                         policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_DS1682                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_DS1803                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DS4424                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DST_CACHE                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DTC                                      policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_DTL                                      policy<{'ppc64el': 'y'}>
+CONFIG_DTLK                                     policy<{'i386': 'm'}>
+CONFIG_DT_IDLE_STATES                           policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_DUMMY                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DUMMY_CONSOLE                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DUMMY_CONSOLE_COLUMNS                    policy<{'amd64': '80', 'arm64': '80', 'i386': '80', 'ppc64el': '80', 's390x': '80'}>
+CONFIG_DUMMY_CONSOLE_ROWS                       policy<{'amd64': '25', 'arm64': '25', 'i386': '25', 'ppc64el': '25', 's390x': '25'}>
+CONFIG_DUMMY_IRQ                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_DVB_A8293                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_AF9013                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_AF9033                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_AS102                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_AS102_FE                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_ASCOT2E                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_ATBM8830                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_AU8522                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_AU8522_DTV                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_AU8522_V4L                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_AV7110                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_AV7110_IR                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_DVB_AV7110_OSD                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_DVB_B2C2_FLEXCOP                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_B2C2_FLEXCOP_PCI                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_B2C2_FLEXCOP_PCI_DEBUG               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_DVB_B2C2_FLEXCOP_USB                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_B2C2_FLEXCOP_USB_DEBUG               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_DVB_BCM3510                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_BT8XX                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_BUDGET                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_BUDGET_AV                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_BUDGET_CI                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_BUDGET_CORE                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_BUDGET_PATCH                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_C8SECTPFE                            policy<{'armhf': 'n'}>
+CONFIG_DVB_CORE                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_CX22700                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_CX22702                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_CX24110                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_CX24116                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_CX24117                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_CX24120                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_CX24123                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_CXD2099                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_CXD2820R                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_CXD2841ER                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_CXD2880                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_DDBRIDGE                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_DDBRIDGE_MSIENABLE                   policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_DVB_DEMUX_SECTION_LOSS_LOG               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_DVB_DIB3000MB                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_DIB3000MC                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_DIB7000M                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_DIB7000P                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_DIB8000                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_DIB9000                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_DM1105                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_DRX39XYJ                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_DRXD                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_DRXK                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_DS3000                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_DYNAMIC_MINORS                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_DVB_EC100                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_FIREDTV                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_FIREDTV_INPUT                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_DVB_GP8PSK_FE                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_HELENE                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_HOPPER                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_HORUS3A                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_ISL6405                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_ISL6421                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_ISL6423                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_IX2505V                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_L64781                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_LG2160                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_LGDT3305                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_LGDT3306A                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_LGDT330X                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_LGS8GL5                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_LGS8GXX                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_LNBH25                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_LNBH29                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_LNBP21                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_LNBP22                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_M88DS3103                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_M88RS2000                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_MANTIS                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_MAX_ADAPTERS                         policy<{'amd64': '8', 'arm64': '8', 'armhf': '8', 'i386': '8', 'ppc64el': '8'}>
+CONFIG_DVB_MB86A16                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_MB86A20S                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_MMAP                                 policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_DVB_MN88443X                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_MN88472                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_MN88473                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_MT312                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_MT352                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_MXL5XX                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_NET                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_DVB_NETUP_UNIDVB                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_NGENE                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_NXT200X                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_NXT6000                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_OR51132                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_OR51211                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_PLATFORM_DRIVERS                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_DVB_PLL                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_PLUTO2                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_PT1                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_PT3                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_RTL2830                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_RTL2832                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_RTL2832_SDR                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_S5H1409                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_S5H1411                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_S5H1420                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_S5H1432                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_S921                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_SI2165                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_SI2168                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_SI21XX                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_SMIPCIE                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_SP2                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_SP8870                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_SP887X                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_STB0899                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_STB6000                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_STB6100                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_STV0288                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_STV0297                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_STV0299                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_STV0367                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_STV0900                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_STV090x                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_STV0910                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_STV6110                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_STV6110x                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_STV6111                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_TC90522                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_TDA10021                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_TDA10023                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_TDA10048                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_TDA1004X                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_TDA10071                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_TDA10086                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_TDA18271C2DD                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_TDA665x                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_TDA8083                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_TDA8261                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_TDA826X                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_TS2020                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_TTUSB_BUDGET                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_TTUSB_DEC                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_TUA6100                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_TUNER_CX24113                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_TUNER_DIB0070                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_TUNER_DIB0090                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_TUNER_ITD1000                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_ULE_DEBUG                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_DVB_USB                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_A800                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_AF9005                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_AF9005_REMOTE                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_AF9015                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_AF9035                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_ANYSEE                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_AU6610                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_AZ6007                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_AZ6027                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_CE6230                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_CINERGY_T2                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_CXUSB                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_CXUSB_ANALOG                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_DVB_USB_DEBUG                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_DVB_USB_DIB0700                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_DIB3000MC                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_DIBUSB_MB                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_DIBUSB_MB_FAULTY                 policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_DVB_USB_DIBUSB_MC                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_DIGITV                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_DTT200U                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_DTV5100                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_DVBSKY                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_DW2102                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_EC168                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_GL861                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_GP8PSK                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_LME2510                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_M920X                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_MXL111SF                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_NOVA_T_USB2                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_OPERA1                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_PCTV452E                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_RTL28XXU                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_TECHNISAT_USB2                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_TTUSB2                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_UMT_010                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_V2                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_VP702X                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_VP7045                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_USB_ZD1301                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_VES1820                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_VES1X93                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_ZD1301_DEMOD                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_ZL10036                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_ZL10039                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DVB_ZL10353                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DWC_XLGMAC                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DWC_XLGMAC_PCI                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_DWMAC_DWC_QOS_ETH                        policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DWMAC_GENERIC                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DWMAC_IPQ806X                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_DWMAC_MEDIATEK                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_DWMAC_MESON                              policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_DWMAC_QCOM_ETHQOS                        policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_DWMAC_ROCKCHIP                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_DWMAC_SOCFPGA                            policy<{'arm64': 'm'}>
+CONFIG_DWMAC_SUN8I                              policy<{'arm64': 'm'}>
+CONFIG_DWMAC_SUNXI                              policy<{'arm64': 'n'}>
+CONFIG_DW_APB_ICTL                              policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_DW_APB_TIMER                             policy<{'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_DW_APB_TIMER_OF                          policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_DW_AXI_DMAC                              policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_DW_DMAC                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DW_DMAC_CORE                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DW_DMAC_PCI                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DW_EDMA                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DW_EDMA_PCIE                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DW_I3C_MASTER                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_DW_WATCHDOG                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_DYNAMIC_DEBUG                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DYNAMIC_EVENTS                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DYNAMIC_FTRACE                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DYNAMIC_FTRACE_WITH_REGS                 policy<{'amd64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_DYNAMIC_MEMORY_LAYOUT                    policy<{'amd64': 'y'}>
+CONFIG_DYNAMIC_PHYSICAL_MASK                    policy<{'amd64': 'y'}>
+CONFIG_E100                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_E1000                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_E1000E                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_E1000E_HWTS                              policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_EADM_SCH                                 policy<{'s390x': 'm'}>
+CONFIG_EARLY_PRINTK                             policy<{'amd64': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_EARLY_PRINTK_DBGP                        policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_EARLY_PRINTK_USB                         policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_EARLY_PRINTK_USB_XDBC                    policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_EBC_C384_WDT                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_ECHO                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_ECRYPT_FS_MESSAGING                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_EDAC                                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_EDAC_ALTERA                              policy<{'arm64': 'y'}>
+CONFIG_EDAC_ALTERA_ETHERNET                     policy<{'arm64': 'y'}>
+CONFIG_EDAC_ALTERA_NAND                         policy<{'arm64': 'y'}>
+CONFIG_EDAC_ALTERA_OCRAM                        policy<{'arm64': 'y'}>
+CONFIG_EDAC_ALTERA_QSPI                         policy<{'arm64': 'y'}>
+CONFIG_EDAC_ALTERA_SDMMC                        policy<{'arm64': 'y'}>
+CONFIG_EDAC_ALTERA_SDRAM                        policy<{'arm64': 'y'}>
+CONFIG_EDAC_ALTERA_USB                          policy<{'arm64': 'y'}>
+CONFIG_EDAC_AMD64                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_EDAC_AMD64_ERROR_INJECTION               policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_EDAC_AMD76X                              policy<{'i386': 'm'}>
+CONFIG_EDAC_ARMADA_XP                           policy<{'armhf': 'y'}>
+CONFIG_EDAC_ATOMIC_SCRUB                        policy<{'amd64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_EDAC_BLUEFIELD                           policy<{'arm64': 'm'}>
+CONFIG_EDAC_CPC925                              policy<{'ppc64el': 'm'}>
+CONFIG_EDAC_DEBUG                               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_EDAC_DECODE_MCE                          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_EDAC_E752X                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_EDAC_E7XXX                               policy<{'i386': 'm'}>
+CONFIG_EDAC_GHES                                policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_EDAC_HIGHBANK_L2                         policy<{'armhf': 'm'}>
+CONFIG_EDAC_HIGHBANK_MC                         policy<{'armhf': 'm'}>
+CONFIG_EDAC_I10NM                               policy<{'amd64': 'm'}>
+CONFIG_EDAC_I3000                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_EDAC_I3200                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_EDAC_I5000                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_EDAC_I5100                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_EDAC_I5400                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_EDAC_I7300                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_EDAC_I7CORE                              policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_EDAC_I82860                              policy<{'i386': 'm'}>
+CONFIG_EDAC_I82875P                             policy<{'i386': 'm'}>
+CONFIG_EDAC_I82975X                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_EDAC_IE31200                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_EDAC_LAYERSCAPE                          policy<{'arm64': 'm'}>
+CONFIG_EDAC_LEGACY_SYSFS                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_EDAC_PND2                                policy<{'amd64': 'm'}>
+CONFIG_EDAC_QCOM                                policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_EDAC_R82600                              policy<{'i386': 'm'}>
+CONFIG_EDAC_SBRIDGE                             policy<{'amd64': 'm'}>
+CONFIG_EDAC_SKX                                 policy<{'amd64': 'm'}>
+CONFIG_EDAC_SUPPORT                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_EDAC_SYNOPSYS                            policy<{'arm64': 'm'}>
+CONFIG_EDAC_THUNDERX                            policy<{'arm64': 'm'}>
+CONFIG_EDAC_TI                                  policy<{'armhf': 'm'}>
+CONFIG_EDAC_X38                                 policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_EDAC_XGENE                               policy<{'arm64': 'm'}>
+CONFIG_EDD                                      policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_EDD_OFF                                  policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_EEEPC_LAPTOP                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_EEEPC_WMI                                policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_EEH                                      policy<{'ppc64el': 'y'}>
+CONFIG_EEPROM_93CX6                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_EEPROM_93XX46                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_EEPROM_AT24                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_EEPROM_AT25                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_EEPROM_EE1004                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_EEPROM_IDT_89HPESX                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_EEPROM_LEGACY                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_EEPROM_MAX6875                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_EFI                                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_EFI_ARMSTUB                              policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_EFI_ARMSTUB_DTB_LOADER                   policy<{'arm64': 'n', 'armhf': 'n'}>
+CONFIG_EFI_BOOTLOADER_CONTROL                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_EFI_CAPSULE_LOADER                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'y'}>
+CONFIG_EFI_CAPSULE_QUIRK_QUARK_CSH              policy<{'i386': 'y'}>
+CONFIG_EFI_CUSTOM_SSDT_OVERLAYS                 policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_EFI_DEV_PATH_PARSER                      policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_EFI_EARLYCON                             policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_EFI_ESRT                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_EFI_FAKE_MEMMAP                          policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_EFI_MIXED                                policy<{'amd64': 'y'}>
+CONFIG_EFI_PARAMS_FROM_FDT                      policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_EFI_PARTITION                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_EFI_PGT_DUMP                             policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_EFI_RCI2_TABLE                           policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_EFI_RUNTIME_MAP                          policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_EFI_RUNTIME_WRAPPERS                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_EFI_STUB                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_EFI_TEST                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_EFI_VARS_PSTORE                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n'}>
+CONFIG_EFS_FS                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_EINT_MTK                                 policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_EISA                                     policy<{'amd64': '-', 'i386': 'y'}>
+CONFIG_EISA_NAMES                               policy<{'amd64': '-', 'i386': 'y'}>
+CONFIG_EISA_PCI_EISA                            policy<{'amd64': '-', 'i386': 'y'}>
+CONFIG_EISA_VIRTUAL_ROOT                        policy<{'amd64': '-', 'i386': 'y'}>
+CONFIG_EISA_VLB_PRIMING                         policy<{'amd64': '-', 'i386': 'y'}>
+CONFIG_EL3                                      policy<{'amd64': '-', 'i386': 'm'}>
+CONFIG_ELFCORE                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ELF_CORE                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_EMAC_ROCKCHIP                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_EMBEDDED                                 policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_EM_TIMER_STI                             policy<{'armhf': 'y'}>
+CONFIG_ENABLE_MUST_CHECK                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_ENA_ETHERNET                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ENC28J60                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ENC28J60_WRITEVERIFY                     policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_ENCLOSURE_SERVICES                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_ENCRYPTED_KEYS                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ENCX24J600                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ENERGY_MODEL                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_ENIC                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ENVELOPE_DETECTOR                        policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_EPAPR_BOOT                               policy<{'ppc64el': 'y'}>
+CONFIG_EPAPR_PARAVIRT                           policy<{'ppc64el': 'y'}>
+CONFIG_EPIC100                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_EPOLL                                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_EQUALIZER                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_EROFS_FS                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_EROFS_FS_CLUSTER_PAGE_LIMIT              policy<{'amd64': '1', 'arm64': '1', 'armhf': '1', 'i386': '1', 'ppc64el': '1', 's390x': '1'}>
+CONFIG_EROFS_FS_DEBUG                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_EROFS_FS_POSIX_ACL                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_EROFS_FS_SECURITY                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_EROFS_FS_XATTR                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_EROFS_FS_ZIP                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ET131X                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ETEXT_SHIFT                              policy<{'ppc64el': '16'}>
+CONFIG_ETHERNET                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ETHOC                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_EUROTECH_WDT                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_EVENTFD                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_EVENT_TRACING                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_EVM_ADD_XATTRS                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_EVM_EXTRA_SMACK_XATTRS                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_EXFAT_DEBUG_MSG                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_EXFAT_DEFAULT_CODEPAGE                   policy<{'amd64': '437', 'arm64': '437', 'armhf': '437', 'i386': '437', 'ppc64el': '437'}>
+CONFIG_EXFAT_DEFAULT_IOCHARSET                  policy<{'amd64': '"utf8"', 'arm64': '"utf8"', 'armhf': '"utf8"', 'i386': '"utf8"', 'ppc64el': '"utf8"'}>
+CONFIG_EXFAT_DELAYED_SYNC                       policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_EXFAT_DISCARD                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_EXFAT_DONT_MOUNT_VFAT                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_EXFAT_FS                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_EXFAT_KERNEL_DEBUG                       policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_EXPERT                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_EXPOLINE                                 policy<{'s390x': 'y'}>
+CONFIG_EXPOLINE_AUTO                            policy<{'s390x': 'y'}>
+CONFIG_EXPOLINE_FULL                            policy<{'s390x': 'n'}>
+CONFIG_EXPOLINE_OFF                             policy<{'s390x': 'n'}>
+CONFIG_EXPORTFS                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_EXPORTFS_BLOCK_OPS                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_EXT4_DEBUG                               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_EXT4_FS                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_EXT4_FS_POSIX_ACL                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_EXT4_FS_SECURITY                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_EXT4_USE_FOR_EXT2                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_EXTCON                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_EXTCON_ADC_JACK                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_EXTCON_ARIZONA                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_EXTCON_AXP288                            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_EXTCON_FSA9480                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_EXTCON_GPIO                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_EXTCON_INTEL_CHT_WC                      policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_EXTCON_INTEL_INT3496                     policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_EXTCON_INTEL_MRFLD                       policy<{'i386': 'm'}>
+CONFIG_EXTCON_MAX14577                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_EXTCON_MAX3355                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_EXTCON_MAX77693                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_EXTCON_MAX77843                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_EXTCON_MAX8997                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_EXTCON_PALMAS                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_EXTCON_PTN5150                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_EXTCON_QCOM_SPMI_MISC                    policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_EXTCON_RT8973A                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_EXTCON_SM5502                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_EXTCON_USBC_CROS_EC                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_EXTCON_USB_GPIO                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_EXTRA_FIRMWARE                           policy<{'amd64': '""', 'arm64': '""', 'armhf': '""', 'i386': '""', 'ppc64el': '""', 's390x': '""'}>
+CONFIG_EXTRA_TARGETS                            policy<{'ppc64el': '""'}>
+CONFIG_EXYNOS_ADC                               policy<{'armhf': 'm'}>
+CONFIG_EXYNOS_AUDSS_CLK_CON                     policy<{'armhf': 'm'}>
+CONFIG_EXYNOS_CHIPID                            policy<{'armhf': 'y'}>
+CONFIG_EXYNOS_CPU_SUSPEND                       policy<{'armhf': 'y'}>
+CONFIG_EXYNOS_IOMMU                             policy<{'armhf': 'y'}>
+CONFIG_EXYNOS_IOMMU_DEBUG                       policy<{'armhf': 'n'}>
+CONFIG_EXYNOS_MCPM                              policy<{'armhf': 'y'}>
+CONFIG_EXYNOS_PMU                               policy<{'armhf': 'y'}>
+CONFIG_EXYNOS_PMU_ARM_DRIVERS                   policy<{'armhf': 'y'}>
+CONFIG_EXYNOS_PM_DOMAINS                        policy<{'armhf': 'y'}>
+CONFIG_EXYNOS_SROM                              policy<{'armhf': 'y'}>
+CONFIG_EXYNOS_THERMAL                           policy<{'armhf': 'y'}>
+CONFIG_EZCHIP_NPS_MANAGEMENT_ENET               policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_EZX_PCAP                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_F2FS_CHECK_FS                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_F2FS_FAULT_INJECTION                     policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_F2FS_FS                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_F2FS_FS_POSIX_ACL                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_F2FS_FS_SECURITY                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_F2FS_FS_XATTR                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_F2FS_IO_TRACE                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_F2FS_STAT_FS                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_F71808E_WDT                              policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_FAILOVER                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_FAIR_GROUP_SCHED                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FANOTIFY                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FANOTIFY_ACCESS_PERMISSIONS              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FARSYNC                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FAT_DEFAULT_CODEPAGE                     policy<{'amd64': '437', 'arm64': '437', 'armhf': '437', 'i386': '437', 'ppc64el': '437', 's390x': '437'}>
+CONFIG_FAT_DEFAULT_IOCHARSET                    policy<{'amd64': '"iso8859-1"', 'arm64': '"iso8859-1"', 'armhf': '"iso8859-1"', 'i386': '"iso8859-1"', 'ppc64el': '"iso8859-1"', 's390x': '"iso8859-1"'}>
+CONFIG_FAT_DEFAULT_UTF8                         policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_FAT_FS                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FAULT_INJECTION                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_FB                                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FB_3DFX                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_FB_3DFX_ACCEL                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_FB_3DFX_I2C                              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_FB_ARC                                   policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_FB_ARK                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_FB_ARMCLCD                               policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_FB_ASILIANT                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_FB_ATY                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_FB_ATY128                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_FB_ATY128_BACKLIGHT                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_FB_ATY_BACKLIGHT                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_FB_ATY_CT                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_FB_ATY_GENERIC_LCD                       policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_FB_ATY_GX                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_FB_BACKLIGHT                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_BOOT_VESA_SUPPORT                     policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_FB_CARILLO_RANCH                         policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_FB_CARMINE                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_FB_CARMINE_DRAM_EVAL                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_FB_CFB_COPYAREA                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'm'}>
+CONFIG_FB_CFB_FILLRECT                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'm'}>
+CONFIG_FB_CFB_IMAGEBLIT                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'm'}>
+CONFIG_FB_CFB_REV_PIXELS_IN_BYTE                policy<{'armhf-generic': 'y'}>
+CONFIG_FB_CIRRUS                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_FB_CMDLINE                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FB_CYBER2000                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_FB_CYBER2000_DDC                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_FB_DA8XX                                 policy<{'armhf-generic': 'm'}>
+CONFIG_FB_DDC                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_DEFERRED_IO                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FB_EFI                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_FB_FOREIGN_ENDIAN                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_FB_GEODE                                 policy<{'i386': 'y'}>
+CONFIG_FB_GEODE_GX                              policy<{'i386': 'm'}>
+CONFIG_FB_GEODE_GX1                             policy<{'i386': 'm'}>
+CONFIG_FB_GEODE_LX                              policy<{'i386': 'm'}>
+CONFIG_FB_HECUBA                                policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_FB_HGA                                   policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_FB_HYPERV                                policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_FB_I740                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_FB_I810                                  policy<{'i386': 'm'}>
+CONFIG_FB_I810_GTF                              policy<{'i386': 'n'}>
+CONFIG_FB_IBM_GXT4500                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_FB_IMSTT                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_FB_IMX                                   policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_FB_INTEL                                 policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_FB_INTEL_DEBUG                           policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_FB_INTEL_I2C                             policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_FB_KYRO                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_FB_LE80578                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_FB_MACMODES                              policy<{'ppc64el': 'y'}>
+CONFIG_FB_MATROX                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_FB_MATROX_G                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_FB_MATROX_I2C                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_MATROX_MAVEN                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_MATROX_MILLENIUM                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_FB_MATROX_MYSTIQUE                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_FB_MB862XX                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_FB_MB862XX_I2C                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_FB_MB862XX_LIME                          policy<{'ppc64el': 'n'}>
+CONFIG_FB_MB862XX_PCI_GDC                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_FB_METRONOME                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_FB_MODE_HELPERS                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FB_MX3                                   policy<{'arm64': 'y', 'armhf-generic': 'y'}>
+CONFIG_FB_N411                                  policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_FB_NEOMAGIC                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_FB_NOTIFY                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FB_NVIDIA                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_FB_NVIDIA_BACKLIGHT                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_FB_NVIDIA_DEBUG                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_FB_NVIDIA_I2C                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_FB_OF                                    policy<{'ppc64el': 'y'}>
+CONFIG_FB_OMAP2                                 policy<{'armhf': 'm'}>
+CONFIG_FB_OMAP2_CONNECTOR_ANALOG_TV             policy<{'armhf': 'n'}>
+CONFIG_FB_OMAP2_CONNECTOR_DVI                   policy<{'armhf': 'n'}>
+CONFIG_FB_OMAP2_CONNECTOR_HDMI                  policy<{'armhf': 'n'}>
+CONFIG_FB_OMAP2_DEBUG_SUPPORT                   policy<{'armhf': 'n'}>
+CONFIG_FB_OMAP2_DSS                             policy<{'armhf': 'm'}>
+CONFIG_FB_OMAP2_DSS_DEBUG                       policy<{'armhf': 'n'}>
+CONFIG_FB_OMAP2_DSS_DEBUGFS                     policy<{'armhf': 'n'}>
+CONFIG_FB_OMAP2_DSS_DPI                         policy<{'armhf': 'y'}>
+CONFIG_FB_OMAP2_DSS_DSI                         policy<{'armhf': 'n'}>
+CONFIG_FB_OMAP2_DSS_HDMI_COMMON                 policy<{'armhf': 'y'}>
+CONFIG_FB_OMAP2_DSS_INIT                        policy<{'armhf': 'y'}>
+CONFIG_FB_OMAP2_DSS_MIN_FCK_PER_PCK             policy<{'armhf': '0'}>
+CONFIG_FB_OMAP2_DSS_SDI                         policy<{'armhf': 'n'}>
+CONFIG_FB_OMAP2_DSS_SLEEP_AFTER_VENC_RESET      policy<{'armhf': 'y'}>
+CONFIG_FB_OMAP2_DSS_VENC                        policy<{'armhf': 'y'}>
+CONFIG_FB_OMAP2_ENCODER_OPA362                  policy<{'armhf': 'n'}>
+CONFIG_FB_OMAP2_ENCODER_TFP410                  policy<{'armhf': 'n'}>
+CONFIG_FB_OMAP2_ENCODER_TPD12S015               policy<{'armhf': 'n'}>
+CONFIG_FB_OMAP2_NUM_FBS                         policy<{'armhf': '3'}>
+CONFIG_FB_OMAP2_PANEL_DPI                       policy<{'armhf': 'n'}>
+CONFIG_FB_OMAP2_PANEL_DSI_CM                    policy<{'armhf': 'n'}>
+CONFIG_FB_OMAP2_PANEL_LGPHILIPS_LB035Q02        policy<{'armhf': 'n'}>
+CONFIG_FB_OMAP4_DSS_HDMI                        policy<{'armhf': 'y'}>
+CONFIG_FB_OMAP5_DSS_HDMI                        policy<{'armhf': 'n'}>
+CONFIG_FB_OPENCORES                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_FB_PM2                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_FB_PM2_FIFO_DISCONNECT                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_FB_PM3                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_FB_PROVIDE_GET_FB_UNMAPPED_AREA          policy<{'armhf': 'y'}>
+CONFIG_FB_RADEON                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_FB_RADEON_BACKLIGHT                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_FB_RADEON_DEBUG                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_FB_RADEON_I2C                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_FB_RIVA                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_FB_RIVA_BACKLIGHT                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_FB_RIVA_DEBUG                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_FB_RIVA_I2C                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_FB_S1D13XXX                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_FB_S3                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_FB_S3_DDC                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_FB_SAVAGE                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_FB_SAVAGE_ACCEL                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_FB_SAVAGE_I2C                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_FB_SH_MOBILE_LCDC                        policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_FB_SIMPLE                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_FB_SIS                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_FB_SIS_300                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_FB_SIS_315                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_FB_SM501                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_SM712                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_FB_SM750                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_SMSCUFX                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_SSD1307                               policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_SVGALIB                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_SYS_COPYAREA                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_FB_SYS_FILLRECT                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_FB_SYS_FOPS                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_FB_SYS_IMAGEBLIT                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_FB_TFT                                   policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_TFT_AGM1264K_FL                       policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_TFT_BD663474                          policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_TFT_HX8340BN                          policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_TFT_HX8347D                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_TFT_HX8353D                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_TFT_HX8357D                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_TFT_ILI9163                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_TFT_ILI9320                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_TFT_ILI9325                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_TFT_ILI9340                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_TFT_ILI9341                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_TFT_ILI9481                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_TFT_ILI9486                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_TFT_PCD8544                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_TFT_RA8875                            policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_TFT_S6D02A1                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_TFT_S6D1121                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_TFT_SH1106                            policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_TFT_SSD1289                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_TFT_SSD1305                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_TFT_SSD1306                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_TFT_SSD1331                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_TFT_SSD1351                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_TFT_ST7735R                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_TFT_ST7789V                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_TFT_TINYLCD                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_TFT_TLS8204                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_TFT_UC1611                            policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_TFT_UC1701                            policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_TFT_UPD161704                         policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_TFT_WATTEROTT                         policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_TILEBLITTING                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_FB_TMIO                                  policy<{'armhf': 'm'}>
+CONFIG_FB_TMIO_ACCELL                           policy<{'armhf': 'y'}>
+CONFIG_FB_TRIDENT                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_FB_UDL                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_UVESA                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_FB_VESA                                  policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_FB_VGA16                                 policy<{'amd64': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FB_VIA                                   policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_FB_VIA_DIRECT_PROCFS                     policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_FB_VIA_X_COMPATIBILITY                   policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_FB_VIRTUAL                               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_FB_VOODOO1                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_FB_VT8623                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_FB_XILINX                                policy<{'arm64': 'm'}>
+CONFIG_FCOE                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_FCOE_FNIC                                policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_FDDI                                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_FEALNX                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_FEC                                      policy<{'arm64': 'y', 'armhf-generic': 'y'}>
+CONFIG_FIB_RULES                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FIELDBUS_DEV                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FILE_LOCKING                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FIND_BIT_BENCHMARK                       policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_FIQ                                      policy<{'armhf-generic': 'y'}>
+CONFIG_FIREWIRE                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_FIREWIRE_NET                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FIREWIRE_NOSY                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_FIREWIRE_OHCI                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FIREWIRE_SBP2                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FIREWIRE_SERIAL                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FIRMWARE_EDID                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FIRMWARE_MEMMAP                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_FIXED_PHY                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'm'}>
+CONFIG_FIX_EARLYCON_MEM                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_FLATMEM                                  policy<{'armhf': 'y'}>
+CONFIG_FLATMEM_MANUAL                           policy<{'i386': 'n'}>
+CONFIG_FLAT_NODE_MEM_MAP                        policy<{'armhf': 'y'}>
+CONFIG_FM10K                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FONTS                                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FONT_10x18                               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_FONT_6x10                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FONT_6x11                                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_FONT_7x14                                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_FONT_8x16                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FONT_8x8                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FONT_ACORN_8x8                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FONT_MINI_4x6                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_FONT_PEARL_8x8                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_FONT_SUN12x22                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_FONT_SUN8x16                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_FONT_SUPPORT                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FONT_TER16x32                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FORCEDETH                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FORCE_DYNAMIC_FTRACE                     policy<{'i386': 'y'}>
+CONFIG_FORCE_MAX_ZONEORDER                      policy<{'arm64': '13', 'armhf-generic': '12', 'armhf-generic-lpae': '11', 'ppc64el': '9', 's390x': '9'}>
+CONFIG_FORCE_PCI                                policy<{'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_FORCE_SMP                                policy<{'ppc64el': 'y'}>
+CONFIG_FORTIFY_SOURCE                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FPGA                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_FPGA_BRIDGE                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_FPGA_DFL                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_FPGA_DFL_AFU                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FPGA_DFL_FME                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FPGA_DFL_FME_BRIDGE                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FPGA_DFL_FME_MGR                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FPGA_DFL_FME_REGION                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FPGA_DFL_PCI                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FPGA_MGR_ALTERA_CVP                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_FPGA_MGR_ALTERA_PS_SPI                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FPGA_MGR_ICE40_SPI                       policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FPGA_MGR_MACHXO2_SPI                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FPGA_MGR_STRATIX10_SOC                   policy<{'arm64': 'm'}>
+CONFIG_FPGA_MGR_XILINX_SPI                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FPGA_MGR_ZYNQMP_FPGA                     policy<{'arm64': 'm'}>
+CONFIG_FPGA_REGION                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FRAMEBUFFER_CONSOLE                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FRAME_POINTER                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_FRAME_VECTOR                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_FRAME_WARN                               policy<{'amd64': '1024', 'arm64': '1024', 'armhf': '1024', 'i386': '1024', 'ppc64el': '2048', 's390x': '1024'}>
+CONFIG_FREEZER                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FRONTSWAP                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FSCACHE                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_FSCACHE_DEBUG                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_FSCACHE_HISTOGRAM                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_FSCACHE_OBJECT_LIST                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_FSCACHE_STATS                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FSI                                      policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FSI_MASTER_AST_CF                        policy<{'armhf': 'm'}>
+CONFIG_FSI_MASTER_GPIO                          policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FSI_MASTER_HUB                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FSI_NEW_DEV_NODE                         policy<{'arm64': 'n', 'armhf': 'n', 'ppc64el': 'n'}>
+CONFIG_FSI_OCC                                  policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FSI_SBEFIFO                              policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FSI_SCOM                                 policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FSL_BMAN_TEST                            policy<{'arm64': 'm'}>
+CONFIG_FSL_BMAN_TEST_API                        policy<{'arm64': 'n'}>
+CONFIG_FSL_DPAA                                 policy<{'arm64': 'y'}>
+CONFIG_FSL_DPAA2                                policy<{'arm64': 'y'}>
+CONFIG_FSL_DPAA2_ETH                            policy<{'arm64': 'm'}>
+CONFIG_FSL_DPAA2_ETHSW                          policy<{'arm64': 'm'}>
+CONFIG_FSL_DPAA2_PTP_CLOCK                      policy<{'arm64': 'm'}>
+CONFIG_FSL_DPAA_CHECKING                        policy<{'arm64': 'y'}>
+CONFIG_FSL_DPAA_ETH                             policy<{'arm64': 'm'}>
+CONFIG_FSL_EDMA                                 policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FSL_ENETC                                policy<{'arm64': 'm'}>
+CONFIG_FSL_ENETC_HW_TIMESTAMPING                policy<{'arm64': 'y'}>
+CONFIG_FSL_ENETC_MDIO                           policy<{'arm64': 'm'}>
+CONFIG_FSL_ENETC_PTP_CLOCK                      policy<{'arm64': 'm'}>
+CONFIG_FSL_ENETC_VF                             policy<{'arm64': 'm'}>
+CONFIG_FSL_ERRATUM_A008585                      policy<{'arm64': 'y'}>
+CONFIG_FSL_FMAN                                 policy<{'arm64': 'y'}>
+CONFIG_FSL_GUTS                                 policy<{'arm64': 'y', 'armhf-generic': 'y', 'ppc64el': 'y'}>
+CONFIG_FSL_IFC                                  policy<{'arm64': 'y'}>
+CONFIG_FSL_IMX8_DDR_PMU                         policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_FSL_LBC                                  policy<{'ppc64el': 'y'}>
+CONFIG_FSL_MC_BUS                               policy<{'arm64': 'y'}>
+CONFIG_FSL_MC_DPIO                              policy<{'arm64': 'm'}>
+CONFIG_FSL_PQ_MDIO                              policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_FSL_QDMA                                 policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_FSL_QMAN_TEST                            policy<{'arm64': 'n'}>
+CONFIG_FSL_XGMAC_MDIO                           policy<{'arm64': 'y', 'armhf-generic': 'y'}>
+CONFIG_FSNOTIFY                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FS_DAX                                   policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FS_DAX_LIMITED                           policy<{'s390x': 'y'}>
+CONFIG_FS_DAX_PMD                               policy<{'amd64': 'y', 'ppc64el': 'y'}>
+CONFIG_FS_ENCRYPTION                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FS_IOMAP                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FS_MBCACHE                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FS_POSIX_ACL                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FS_VERITY                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FS_VERITY_BUILTIN_SIGNATURES             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FS_VERITY_DEBUG                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_FTGMAC100                                policy<{'armhf': 'm'}>
+CONFIG_FTL                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FTMAC100                                 policy<{'armhf': 'm'}>
+CONFIG_FTM_QUADDEC                              policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_FTRACE                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FTRACE_MCOUNT_RECORD                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FTRACE_STARTUP_TEST                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_FTRACE_SYSCALLS                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FTR_FIXUP_SELFTEST                       policy<{'ppc64el': 'n'}>
+CONFIG_FTWDT010_WATCHDOG                        policy<{'armhf': 'm'}>
+CONFIG_FUEL_GAUGE_SC27XX                        policy<{'arm64': 'm'}>
+CONFIG_FUJITSU_ERRATUM_010001                   policy<{'arm64': 'y'}>
+CONFIG_FUJITSU_ES                               policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_FUJITSU_LAPTOP                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_FUJITSU_TABLET                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_FUNCTION_ERROR_INJECTION                 policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_FUNCTION_GRAPH_TRACER                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FUNCTION_PROFILER                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FUNCTION_TRACER                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FUSION                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_FUSION_CTL                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FUSION_FC                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FUSION_LAN                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FUSION_LOGGING                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_FUSION_MAX_SGE                           policy<{'amd64': '128', 'arm64': '128', 'armhf': '128', 'i386': '128', 'ppc64el': '128'}>
+CONFIG_FUSION_SAS                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FUSION_SPI                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FUTEX                                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FUTEX_PI                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FWTTY_MAX_CARD_PORTS                     policy<{'amd64': '32', 'arm64': '32', 'armhf': '32', 'i386': '32', 'ppc64el': '32'}>
+CONFIG_FWTTY_MAX_TOTAL_PORTS                    policy<{'amd64': '64', 'arm64': '64', 'armhf': '64', 'i386': '64', 'ppc64el': '64'}>
+CONFIG_FW_CFG_SYSFS                             policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_FW_CFG_SYSFS_CMDLINE                     policy<{'amd64': 'n', 'arm64': 'n', 'i386': 'n'}>
+CONFIG_FW_LOADER                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FW_LOADER_COMPRESS                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FW_LOADER_PAGED_BUF                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FW_LOADER_USER_HELPER                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_FXAS21002C                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FXAS21002C_I2C                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_FXAS21002C_SPI                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GACT_PROB                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_GADGET_UAC1                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_GADGET_UAC1_LEGACY                       policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_GAMEPORT                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_GAMEPORT_EMU10K1                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GAMEPORT_FM801                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GAMEPORT_L4                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GAMEPORT_NS558                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GARP                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_GART_IOMMU                               policy<{'amd64': 'y'}>
+CONFIG_GCC_VERSION                              policy<{'amd64': '90400', 'arm64': '90400', 'armhf': '90400', 'i386': '90400', 'ppc64el': '90400', 's390x': '90400'}>
+CONFIG_GCOV_KERNEL                              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_GDB_SCRIPTS                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_GDS_FORCE_MITIGATION                     policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_GEMINI_ETHERNET                          policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_GENERIC_ADC_BATTERY                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GENERIC_ADC_THERMAL                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GENERIC_ALLOCATOR                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_GENERIC_ARCH_TOPOLOGY                    policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_GENERIC_BUG                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_GENERIC_BUG_RELATIVE_POINTERS            policy<{'amd64': 'y', 'arm64': 'y', 's390x': 'y'}>
+CONFIG_GENERIC_CALIBRATE_DELAY                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_GENERIC_CLOCKEVENTS                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST           policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_GENERIC_CMOS_UPDATE                      policy<{'amd64': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_GENERIC_CPU                              policy<{'amd64': 'y', 'ppc64el': 'y'}>
+CONFIG_GENERIC_CPU_AUTOPROBE                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_GENERIC_CPU_VULNERABILITIES              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_GENERIC_CSUM                             policy<{'arm64': 'y'}>
+CONFIG_GENERIC_EARLY_IOREMAP                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_GENERIC_FIND_FIRST_BIT                   policy<{'amd64': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_GENERIC_GETTIMEOFDAY                     policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_GENERIC_HWEIGHT                          policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_GENERIC_IDLE_POLL_SETUP                  policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_GENERIC_IOMAP                            policy<{'amd64': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_GENERIC_IRQ_CHIP                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_GENERIC_IRQ_DEBUGFS                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_GENERIC_IRQ_MATRIX_ALLOCATOR             policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_GENERIC_IRQ_MIGRATION                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_GENERIC_IRQ_MULTI_HANDLER                policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_GENERIC_IRQ_PROBE                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_GENERIC_IRQ_RESERVATION_MODE             policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_GENERIC_IRQ_SHOW                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_GENERIC_IRQ_SHOW_LEVEL                   policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_GENERIC_ISA_DMA                          policy<{'amd64': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_GENERIC_MSI_IRQ                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_GENERIC_MSI_IRQ_DOMAIN                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_GENERIC_NET_UTILS                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_GENERIC_PCI_IOMAP                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_GENERIC_PENDING_IRQ                      policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_GENERIC_PHY                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_GENERIC_PHY_MIPI_DPHY                    policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_GENERIC_PINCONF                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_GENERIC_PINCTRL_GROUPS                   policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_GENERIC_PINMUX_FUNCTIONS                 policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_GENERIC_SCHED_CLOCK                      policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_GENERIC_SMP_IDLE_THREAD                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_GENERIC_STRNCPY_FROM_USER                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_GENERIC_STRNLEN_USER                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_GENERIC_TIME_VSYSCALL                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_GENERIC_TRACER                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_GENERIC_VDSO_32                          policy<{'i386': 'y'}>
+CONFIG_GENEVE                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_GENWQE                                   policy<{'amd64': 'm', 'arm64': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_GENWQE_PLATFORM_ERROR_RECOVERY           policy<{'amd64': '0', 'arm64': '0', 'ppc64el': '0', 's390x': '0'}>
+CONFIG_GEN_RTC                                  policy<{'ppc64el': 'y'}>
+CONFIG_GEOS                                     policy<{'i386': 'y'}>
+CONFIG_GFS2_FS                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_GFS2_FS_LOCKING_DLM                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_GIANFAR                                  policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_GIGASET_BASE                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GIGASET_CAPI                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_GIGASET_DEBUG                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_GIGASET_M101                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GIGASET_M105                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GLOB                                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_GLOB_SELFTEST                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_GNSS                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_GNSS_MTK_SERIAL                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GNSS_SERIAL                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GNSS_SIRF_SERIAL                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GNSS_UBX_SERIAL                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GOLDFISH                                 policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n'}>
+CONFIG_GOOGLE_FIRMWARE                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n'}>
+CONFIG_GP2AP020A00F                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GPD_POCKET_FAN                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_GPIOLIB                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_GPIOLIB_FASTPATH_LIMIT                   policy<{'amd64': '512', 'arm64': '512', 'armhf': '512', 'i386': '512', 'ppc64el': '512', 's390x': '512'}>
+CONFIG_GPIOLIB_IRQCHIP                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_GPIO_104_DIO_48E                         policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_GPIO_104_IDIO_16                         policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_GPIO_104_IDI_48                          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_GPIO_74X164                              policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_74XX_MMIO                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_ACPI                                policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_GPIO_ADNP                                policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_ADP5520                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_ADP5588                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_GPIO_ALTERA                              policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_AMD8111                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_GPIO_AMDPT                               policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_GPIO_AMD_FCH                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_GPIO_ARIZONA                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_ASPEED                              policy<{'armhf': 'm'}>
+CONFIG_GPIO_BD70528                             policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_BD9571MWV                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_BRCMSTB                             policy<{'arm64': 'm'}>
+CONFIG_GPIO_BT8XX                               policy<{'s390x': 'm'}>
+CONFIG_GPIO_CADENCE                             policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_CRYSTAL_COVE                        policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_GPIO_CS5535                              policy<{'i386': 'm'}>
+CONFIG_GPIO_DA9052                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_DA9055                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_DAVINCI                             policy<{'arm64': 'y'}>
+CONFIG_GPIO_DLN2                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_DWAPB                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_GPIO_EIC_SPRD                            policy<{'arm64': 'm'}>
+CONFIG_GPIO_EXAR                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_F7188X                              policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_GPIO_FTGPIO010                           policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_GPIO_GENERIC                             policy<{'amd64': 'm', 'arm64': 'y', 'armhf': 'y', 'i386': 'm', 'ppc64el': 'y', 's390x': 'm'}>
+CONFIG_GPIO_GENERIC_PLATFORM                    policy<{'amd64': 'm', 'arm64': 'y', 'armhf': 'y', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_GPIO_GPIO_MM                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_GPIO_GRGPIO                              policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_GW_PLD                              policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_HLWD                                policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_ICH                                 policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_GPIO_INTEL_MID                           policy<{'i386': 'y'}>
+CONFIG_GPIO_IT87                                policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_GPIO_JANZ_TTL                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_KEMPLD                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_LP3943                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_LP873X                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_LP87565                             policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_LYNXPOINT                           policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_GPIO_MADERA                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_MAX3191X                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_MAX7300                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_GPIO_MAX7301                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_MAX730X                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_MAX732X                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_GPIO_MAX77620                            policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_MAX77650                            policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_MB86S7X                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_GPIO_MC33880                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_MENZ127                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_MERRIFIELD                          policy<{'i386': 'n'}>
+CONFIG_GPIO_MLXBF                               policy<{'arm64': 'm'}>
+CONFIG_GPIO_ML_IOH                              policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_GPIO_MOCKUP                              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_GPIO_MOXTET                              policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_MPC8XXX                             policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_GPIO_MSIC                                policy<{'i386': 'y'}>
+CONFIG_GPIO_MVEBU                               policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_GPIO_MXC                                 policy<{'arm64': 'y', 'armhf-generic': 'y'}>
+CONFIG_GPIO_OMAP                                policy<{'armhf': 'y'}>
+CONFIG_GPIO_PALMAS                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_GPIO_PCA953X                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_GPIO_PCF857X                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_GPIO_PCH                                 policy<{'i386': 'm'}>
+CONFIG_GPIO_PCIE_IDIO_24                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_GPIO_PCI_IDIO_16                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_GPIO_PISOSR                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_PL061                               policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_GPIO_PMIC_EIC_SPRD                       policy<{'arm64': 'm'}>
+CONFIG_GPIO_RASPBERRYPI_EXP                     policy<{'arm64': 'm'}>
+CONFIG_GPIO_RC5T583                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_GPIO_RCAR                                policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_GPIO_RDC321X                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_GPIO_SAMA5D2_PIOBU                       policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_SCH                                 policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_GPIO_SCH311X                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_GPIO_SIOX                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_GPIO_SPRD                                policy<{'arm64': 'm'}>
+CONFIG_GPIO_STMPE                               policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_GPIO_SYSCON                              policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_SYSFS                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_GPIO_TC3589X                             policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_GPIO_TEGRA                               policy<{'armhf-generic': 'y'}>
+CONFIG_GPIO_THUNDERX                            policy<{'arm64': 'm'}>
+CONFIG_GPIO_TIMBERDALE                          policy<{'i386': 'y'}>
+CONFIG_GPIO_TPIC2810                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_GPIO_TPS65086                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_TPS65218                            policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_TPS6586X                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_GPIO_TPS65910                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_GPIO_TPS65912                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_TPS68470                            policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_GPIO_TQMX86                              policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_TS4800                              policy<{'armhf-generic': 'm'}>
+CONFIG_GPIO_TS4900                              policy<{'armhf-generic': 'm'}>
+CONFIG_GPIO_TWL6040                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'y', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_UCB1400                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_UNIPHIER                            policy<{'armhf': 'm'}>
+CONFIG_GPIO_VF610                               policy<{'armhf-generic': 'y'}>
+CONFIG_GPIO_VIPERBOARD                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_VX855                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_GPIO_WATCHDOG                            policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_WHISKEY_COVE                        policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_GPIO_WINBOND                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_GPIO_WM831X                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_WM8350                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_WM8994                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_WS16C48                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_GPIO_XGENE                               policy<{'arm64': 'y'}>
+CONFIG_GPIO_XGENE_SB                            policy<{'arm64': 'm'}>
+CONFIG_GPIO_XILINX                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_GPIO_XLP                                 policy<{'arm64': 'm'}>
+CONFIG_GPIO_XRA1403                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GPIO_ZEVIO                               policy<{'armhf': 'y'}>
+CONFIG_GPIO_ZYNQ                                policy<{'arm64': 'm'}>
+CONFIG_GRACE_PERIOD                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_GREENASIA_FF                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_GREYBUS                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_GREYBUS_AUDIO                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GREYBUS_BOOTROM                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GREYBUS_BRIDGED_PHY                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GREYBUS_ES2                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GREYBUS_FIRMWARE                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GREYBUS_GPIO                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GREYBUS_HID                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GREYBUS_I2C                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GREYBUS_LIGHT                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GREYBUS_LOG                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GREYBUS_LOOPBACK                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GREYBUS_POWER                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GREYBUS_PWM                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GREYBUS_RAW                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GREYBUS_SDIO                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GREYBUS_SPI                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GREYBUS_UART                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GREYBUS_USB                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GREYBUS_VIBRATOR                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GRO_CELLS                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_GS_FPGABOOT                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_GTP                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_GUP_BENCHMARK                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_GUP_GET_PTE_LOW_HIGH                     policy<{'i386': 'y'}>
+CONFIG_GVE                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HABANA_AI                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_HALTPOLL_CPUIDLE                         policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_HAMACHI                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_HAMRADIO                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HANDLE_DOMAIN_IRQ                        policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_HANGCHECK_TIMER                          policy<{'amd64': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_HAPPYMEAL                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HARDENED_USERCOPY                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HARDENED_USERCOPY_FALLBACK               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HARDENED_USERCOPY_PAGESPAN               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_HARDEN_BRANCH_HISTORY                    policy<{'armhf': 'y'}>
+CONFIG_HARDEN_BRANCH_PREDICTOR                  policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_HARDEN_EL2_VECTORS                       policy<{'arm64': 'y'}>
+CONFIG_HARDIRQS_SW_RESEND                       policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_HARDLOCKUP_CHECK_TIMESTAMP               policy<{'amd64': 'y'}>
+CONFIG_HARDLOCKUP_DETECTOR                      policy<{'amd64': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HARDLOCKUP_DETECTOR_PERF                 policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_HAS_DMA                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAS_IOMEM                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAS_IOPORT_MAP                           policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HAVE_ACPI_APEI                           policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_HAVE_ACPI_APEI_NMI                       policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_HAVE_ALIGNED_STRUCT_PAGE                 policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_HAVE_ARCH_AUDITSYSCALL                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_ARCH_BITREVERSE                     policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_HAVE_ARCH_COMPAT_MMAP_BASES              policy<{'amd64': 'y'}>
+CONFIG_HAVE_ARCH_HUGE_VMAP                      policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HAVE_ARCH_JUMP_LABEL                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_ARCH_JUMP_LABEL_RELATIVE            policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_HAVE_ARCH_KASAN                          policy<{'amd64': 'y', 'arm64': 'y', 's390x': 'y'}>
+CONFIG_HAVE_ARCH_KASAN_SW_TAGS                  policy<{'arm64': 'y'}>
+CONFIG_HAVE_ARCH_KGDB                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HAVE_ARCH_MMAP_RND_BITS                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS           policy<{'amd64': 'y', 'arm64': 'y', 'ppc64el': 'y'}>
+CONFIG_HAVE_ARCH_NVRAM_OPS                      policy<{'ppc64el': 'y'}>
+CONFIG_HAVE_ARCH_PFN_VALID                      policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_HAVE_ARCH_PREL32_RELOCATIONS             policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_HAVE_ARCH_SECCOMP_FILTER                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_ARCH_SOFT_DIRTY                     policy<{'amd64': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_ARCH_STACKLEAK                      policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_HAVE_ARCH_TRACEHOOK                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE           policy<{'amd64': 'y', 'arm64': 'y', 'armhf-generic-lpae': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD       policy<{'amd64': 'y'}>
+CONFIG_HAVE_ARCH_VMAP_STACK                     policy<{'amd64': 'y', 'arm64': 'y', 's390x': 'y'}>
+CONFIG_HAVE_ARCH_WITHIN_STACK_FRAMES            policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_HAVE_ARM_ARCH_TIMER                      policy<{'armhf': 'y'}>
+CONFIG_HAVE_ARM_SCU                             policy<{'armhf': 'y'}>
+CONFIG_HAVE_ARM_SMCCC                           policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_HAVE_ARM_TWD                             policy<{'armhf': 'y'}>
+CONFIG_HAVE_ASM_MODVERSIONS                     policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_ATOMIC_IOMAP                        policy<{'i386': 'y'}>
+CONFIG_HAVE_BOOTMEM_INFO_NODE                   policy<{'amd64': 'y', 'ppc64el': 'y'}>
+CONFIG_HAVE_CLK                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_HAVE_CLK_PREPARE                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_HAVE_CMPXCHG_DOUBLE                      policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_HAVE_CMPXCHG_LOCAL                       policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_HAVE_CONTEXT_TRACKING                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_HAVE_COPY_THREAD_TLS                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_C_RECORDMCOUNT                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HAVE_DEBUG_BUGVERBOSE                    policy<{'arm64': 'y'}>
+CONFIG_HAVE_DEBUG_KMEMLEAK                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_DEBUG_STACKOVERFLOW                 policy<{'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HAVE_DMA_CONTIGUOUS                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_HAVE_DYNAMIC_FTRACE                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS            policy<{'amd64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_EBPF_JIT                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_EISA                                policy<{'amd64': '-', 'i386': 'y'}>
+CONFIG_HAVE_EXIT_THREAD                         policy<{'amd64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_HAVE_FAST_GUP                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf-generic-lpae': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_FENTRY                              policy<{'amd64': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_FUNCTION_ARG_ACCESS_API             policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_HAVE_FUNCTION_ERROR_INJECTION            policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_FUNCTION_TRACER                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_FUTEX_CMPXCHG                       policy<{'armhf': 'y', 's390x': 'y'}>
+CONFIG_HAVE_GCC_PLUGINS                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_GENERIC_VDSO                        policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_HARDLOCKUP_DETECTOR_ARCH            policy<{'ppc64el': 'y'}>
+CONFIG_HAVE_HARDLOCKUP_DETECTOR_PERF            policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_HAVE_HW_BREAKPOINT                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HAVE_IDE                                 policy<{'amd64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HAVE_IMA_KEXEC                           policy<{'ppc64el': 'y'}>
+CONFIG_HAVE_IMX_ANATOP                          policy<{'armhf-generic': 'y'}>
+CONFIG_HAVE_IMX_GPC                             policy<{'armhf-generic': 'y'}>
+CONFIG_HAVE_IMX_MMDC                            policy<{'armhf-generic': 'y'}>
+CONFIG_HAVE_IMX_SRC                             policy<{'armhf-generic': 'y'}>
+CONFIG_HAVE_INTEL_TXT                           policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_HAVE_IOREMAP_PROT                        policy<{'amd64': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK               policy<{'amd64': 'y', 'ppc64el': 'y'}>
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HAVE_KERNEL_BZIP2                        policy<{'amd64': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_HAVE_KERNEL_GZIP                         policy<{'amd64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_KERNEL_LZ4                          policy<{'amd64': 'y', 'armhf': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_HAVE_KERNEL_LZMA                         policy<{'amd64': 'y', 'armhf': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_HAVE_KERNEL_LZO                          policy<{'amd64': 'y', 'armhf': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_HAVE_KERNEL_UNCOMPRESSED                 policy<{'s390x': 'y'}>
+CONFIG_HAVE_KERNEL_XZ                           policy<{'amd64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_KPROBES                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_KPROBES_ON_FTRACE                   policy<{'amd64': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_KRETPROBES                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_KVM                                 policy<{'amd64': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_HAVE_KVM_ARCH_TLB_FLUSH_ALL              policy<{'arm64': 'y', 'armhf-generic-lpae': 'y'}>
+CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT             policy<{'amd64': 'y', 'arm64': 'y', 'armhf-generic-lpae': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_HAVE_KVM_EVENTFD                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf-generic-lpae': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_KVM_INVALID_WAKEUPS                 policy<{'s390x': 'y'}>
+CONFIG_HAVE_KVM_IRQCHIP                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf-generic-lpae': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_KVM_IRQFD                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf-generic-lpae': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_KVM_IRQ_BYPASS                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf-generic-lpae': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HAVE_KVM_IRQ_ROUTING                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf-generic-lpae': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_HAVE_KVM_MSI                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf-generic-lpae': 'y', 'i386': 'y'}>
+CONFIG_HAVE_KVM_NO_POLL                         policy<{'amd64': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_HAVE_KVM_VCPU_ASYNC_IOCTL                policy<{'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_KVM_VCPU_RUN_PID_CHANGE             policy<{'arm64': 'y'}>
+CONFIG_HAVE_LD_DEAD_CODE_DATA_ELIMINATION       policy<{'ppc64el': 'y'}>
+CONFIG_HAVE_LIVEPATCH                           policy<{'amd64': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_MARCH_Z10_FEATURES                  policy<{'s390x': 'y'}>
+CONFIG_HAVE_MARCH_Z13_FEATURES                  policy<{'s390x': 'y'}>
+CONFIG_HAVE_MARCH_Z196_FEATURES                 policy<{'s390x': 'y'}>
+CONFIG_HAVE_MARCH_Z900_FEATURES                 policy<{'s390x': 'y'}>
+CONFIG_HAVE_MARCH_Z990_FEATURES                 policy<{'s390x': 'y'}>
+CONFIG_HAVE_MARCH_Z9_109_FEATURES               policy<{'s390x': 'y'}>
+CONFIG_HAVE_MARCH_ZEC12_FEATURES                policy<{'s390x': 'y'}>
+CONFIG_HAVE_MEMBLOCK_NODE_MAP                   policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_MEMBLOCK_PHYS_MAP                   policy<{'s390x': 'y'}>
+CONFIG_HAVE_MEMORYLESS_NODES                    policy<{'ppc64el': 'y'}>
+CONFIG_HAVE_MEMORY_PRESENT                      policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_MIXED_BREAKPOINTS_REGS              policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_HAVE_MMIOTRACE_SUPPORT                   policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_HAVE_MMU_GATHER_NO_GATHER                policy<{'s390x': 'y'}>
+CONFIG_HAVE_MMU_GATHER_PAGE_SIZE                policy<{'ppc64el': 'y'}>
+CONFIG_HAVE_MOD_ARCH_SPECIFIC                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_MOVE_PMD                            policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_HAVE_NET_DSA                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HAVE_NMI                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_NMI_WATCHDOG                        policy<{'ppc64el': 'y'}>
+CONFIG_HAVE_NOP_MCOUNT                          policy<{'s390x': 'y'}>
+CONFIG_HAVE_OPROFILE                            policy<{'amd64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_OPTPROBES                           policy<{'amd64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HAVE_PATA_PLATFORM                       policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_HAVE_PCI                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_PCSPKR_PLATFORM                     policy<{'amd64': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HAVE_PERF_EVENTS                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_PERF_EVENTS_NMI                     policy<{'amd64': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HAVE_PERF_REGS                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_PERF_USER_STACK_DUMP                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_PNETID                              policy<{'s390x': 'm'}>
+CONFIG_HAVE_PROC_CPU                            policy<{'armhf': 'y'}>
+CONFIG_HAVE_RCU_TABLE_FREE                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf-generic-lpae': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_RELIABLE_STACKTRACE                 policy<{'amd64': 'y', 'ppc64el': 'y'}>
+CONFIG_HAVE_RSEQ                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_S3C2410_I2C                         policy<{'armhf': 'y'}>
+CONFIG_HAVE_S3C2410_WATCHDOG                    policy<{'armhf': 'y'}>
+CONFIG_HAVE_S3C_RTC                             policy<{'armhf': 'y'}>
+CONFIG_HAVE_SETUP_PER_CPU_AREA                  policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HAVE_SMP                                 policy<{'armhf': 'y'}>
+CONFIG_HAVE_STACKPROTECTOR                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HAVE_STACK_VALIDATION                    policy<{'amd64': 'y'}>
+CONFIG_HAVE_SYSCALL_TRACEPOINTS                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_UID16                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_HAVE_UNSTABLE_SCHED_CLOCK                policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_HAVE_USER_RETURN_NOTIFIER                policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING                 policy<{'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HBMC_AM654                               policy<{'arm64': 'm'}>
+CONFIG_HCALL_STATS                              policy<{'ppc64el': 'n'}>
+CONFIG_HD44780                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HDC100X                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HDLC                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HDLC_CISCO                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HDLC_FR                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HDLC_PPP                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HDLC_RAW                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HDLC_RAW_ETH                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HDLC_X25                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HDMI                                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HDMI_LPE_AUDIO                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_HDQ_MASTER_OMAP                          policy<{'armhf': 'm'}>
+CONFIG_HEADERS_INSTALL                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_HERMES                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HERMES_CACHE_FW_ON_INIT                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HERMES_PRISM                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_HFI1_DEBUG_SDMA_ORDER                    policy<{'amd64': 'n'}>
+CONFIG_HFSPLUS_FS                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_HFS_FS                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_HI13X1_GMAC                              policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_HI3660_MBOX                              policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_HI6220_MBOX                              policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_HI8435                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HIBERNATE_CALLBACKS                      policy<{'amd64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_HID                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_HIDRAW                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HID_A4TECH                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_ACCUTOUCH                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_ACRUX                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_ACRUX_FF                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HID_ALPS                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_APPLE                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_APPLEIR                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_ASUS                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_AUREAL                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_BATTERY_STRENGTH                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HID_BELKIN                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_BETOP_FF                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_BIGBEN_FF                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_CHERRY                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_CHICONY                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_CMEDIA                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_CORSAIR                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_COUGAR                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_CP2112                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_CREATIVE_SB0540                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_CYPRESS                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_DRAGONRISE                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_ELAN                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_ELECOM                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_ELO                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_EMS_FF                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_EZKEY                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_GEMBIRD                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_GENERIC                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_GFRM                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_GOOGLE_HAMMER                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_HID_GREENASIA                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_GT683R                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_GYRATION                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_HOLTEK                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_HYPERV_MOUSE                         policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_HID_ICADE                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_ITE                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_JABRA                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_KENSINGTON                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_KEYTOUCH                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_KYE                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_LCPOWER                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_LED                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_LENOVO                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_LOGITECH                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_LOGITECH_DJ                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_LOGITECH_HIDPP                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_MACALLY                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_MAGICMOUSE                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_MALTRON                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_MAYFLASH                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_MICROSOFT                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_MONTEREY                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_MULTITOUCH                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_NTI                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_NTRIG                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_ORTEK                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_PANTHERLORD                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_PENMOUNT                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_PETALYNX                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_PICOLCD                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_PICOLCD_BACKLIGHT                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HID_PICOLCD_CIR                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HID_PICOLCD_FB                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HID_PICOLCD_LCD                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HID_PICOLCD_LEDS                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HID_PID                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HID_PLANTRONICS                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_PRIMAX                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_PRODIKEYS                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_REDRAGON                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_RETRODE                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_RMI                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_ROCCAT                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_SAITEK                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_SAMSUNG                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_SENSOR_ACCEL_3D                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_SENSOR_ALS                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_SENSOR_CUSTOM_SENSOR                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_SENSOR_DEVICE_ROTATION               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_SENSOR_GYRO_3D                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_SENSOR_HUB                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_SENSOR_HUMIDITY                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_SENSOR_IIO_COMMON                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_SENSOR_IIO_TRIGGER                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_SENSOR_INCLINOMETER_3D               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_SENSOR_MAGNETOMETER_3D               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_SENSOR_PRESS                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_SENSOR_PROX                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_SENSOR_TEMP                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_SMARTJOYPLUS                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_SONY                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_SPEEDLINK                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_STEAM                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_STEELSERIES                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_SUNPLUS                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_THINGM                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_THRUSTMASTER                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_TIVO                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_TOPSEED                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_TWINHAN                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_U2FZERO                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_UCLOGIC                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_UDRAW_PS3                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_VIEWSONIC                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_WACOM                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_WALTOP                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_WIIMOTE                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_XINMO                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_ZEROPLUS                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HID_ZYDACRON                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HIGHMEM                                  policy<{'armhf': 'y', 'i386': 'y'}>
+CONFIG_HIGHMEM4G                                policy<{'i386': 'n'}>
+CONFIG_HIGHMEM64G                               policy<{'i386': 'y'}>
+CONFIG_HIGHPTE                                  policy<{'armhf': 'y', 'i386': 'y'}>
+CONFIG_HIGH_RES_TIMERS                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HINIC                                    policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_HIP04_ETH                                policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_HISILICON_ERRATUM_161010101              policy<{'arm64': 'y'}>
+CONFIG_HISILICON_ERRATUM_161600802              policy<{'arm64': 'y'}>
+CONFIG_HISILICON_IRQ_MBIGEN                     policy<{'arm64': 'y'}>
+CONFIG_HISILICON_LPC                            policy<{'arm64': 'y'}>
+CONFIG_HISI_DMA                                 policy<{'arm64': 'n'}>
+CONFIG_HISI_FEMAC                               policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_HISI_PMU                                 policy<{'arm64': 'm'}>
+CONFIG_HISI_THERMAL                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_HIST_TRIGGERS                            policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HIX5HD2_GMAC                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_HMC6352                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_HMC_DRV                                  policy<{'s390x': 'm'}>
+CONFIG_HMEM_REPORTING                           policy<{'amd64': 'y', 'arm64': 'y'}>
+CONFIG_HMM_MIRROR                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HMS_ANYBUSS_BUS                          policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_HMS_PROFINET                             policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_HNS                                      policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_HNS3                                     policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_HNS3_DCB                                 policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_HNS3_ENET                                policy<{'arm64': 'm'}>
+CONFIG_HNS3_HCLGE                               policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_HNS3_HCLGEVF                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_HNS_DSAF                                 policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_HNS_ENET                                 policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_HNS_MDIO                                 policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_HOLES_IN_ZONE                            policy<{'arm64': 'y'}>
+CONFIG_HOLTEK_FF                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HOSTAP                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HOSTAP_CS                                policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_HOSTAP_FIRMWARE                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HOSTAP_FIRMWARE_NVRAM                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HOSTAP_PCI                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HOSTAP_PLX                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HOSTESS_SV11                             policy<{'i386': 'm'}>
+CONFIG_HOTPLUG_CPU                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HOTPLUG_PCI                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'n', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HOTPLUG_PCI_ACPI                         policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_HOTPLUG_PCI_ACPI_IBM                     policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_HOTPLUG_PCI_COMPAQ                       policy<{'i386': 'm'}>
+CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM                 policy<{'i386': 'y'}>
+CONFIG_HOTPLUG_PCI_CPCI                         policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HOTPLUG_PCI_CPCI_GENERIC                 policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_HOTPLUG_PCI_CPCI_ZT5550                  policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_HOTPLUG_PCI_IBM                          policy<{'i386': 'm'}>
+CONFIG_HOTPLUG_PCI_POWERNV                      policy<{'ppc64el': 'm'}>
+CONFIG_HOTPLUG_PCI_RPA                          policy<{'ppc64el': 'm'}>
+CONFIG_HOTPLUG_PCI_RPA_DLPAR                    policy<{'ppc64el': 'm'}>
+CONFIG_HOTPLUG_PCI_S390                         policy<{'s390x': 'y'}>
+CONFIG_HOTPLUG_SMT                              policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_HP03                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HP100                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HP206C                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HPET                                     policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_HPET_EMULATE_RTC                         policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_HPET_MMAP                                policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_HPET_MMAP_DEFAULT                        policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_HPET_TIMER                               policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_HPFS_FS                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_HPWDT_NMI_DECODING                       policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_HP_ACCEL                                 policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_HP_ILO                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_HP_WATCHDOG                              policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_HP_WIRELESS                              policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_HP_WMI                                   policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_HSA_AMD                                  policy<{'amd64': 'y', 'arm64': 'y'}>
+CONFIG_HSI                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_HSI_BOARDINFO                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HSI_CHAR                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HSR                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_HSU_DMA                                  policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_HSU_DMA_PCI                              policy<{'i386': 'm'}>
+CONFIG_HT16K33                                  policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_HTC_EGPIO                                policy<{'armhf': 'y'}>
+CONFIG_HTC_I2CPLD                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HTC_PASIC3                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_HTS221                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HTS221_I2C                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HTS221_SPI                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HTU21                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HUAWEI_WMI                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_HUGETLBFS                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf-generic-lpae': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HUGETLB_PAGE                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf-generic-lpae': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HUGETLB_PAGE_SIZE_VARIABLE               policy<{'ppc64el': 'y'}>
+CONFIG_HVCS                                     policy<{'ppc64el': 'm'}>
+CONFIG_HVC_CONSOLE                              policy<{'ppc64el': 'y'}>
+CONFIG_HVC_DCC                                  policy<{'arm64': 'n', 'armhf': 'n'}>
+CONFIG_HVC_DRIVER                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HVC_IRQ                                  policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HVC_IUCV                                 policy<{'s390x': 'y'}>
+CONFIG_HVC_OLD_HVSI                             policy<{'ppc64el': 'y'}>
+CONFIG_HVC_OPAL                                 policy<{'ppc64el': 'y'}>
+CONFIG_HVC_RTAS                                 policy<{'ppc64el': 'y'}>
+CONFIG_HVC_XEN                                  policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_HVC_XEN_FRONTEND                         policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_HV_PERF_CTRS                             policy<{'ppc64el': 'y'}>
+CONFIG_HWLAT_TRACER                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HWMON                                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_HWMON_DEBUG_CHIP                         policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_HWMON_VID                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HWPOISON_INJECT                          policy<{'amd64': 'm', 'arm64': 'm', 'ppc64el': 'm'}>
+CONFIG_HWSPINLOCK                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_HWSPINLOCK_OMAP                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_HWSPINLOCK_QCOM                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_HWSPINLOCK_SPRD                          policy<{'arm64': 'm'}>
+CONFIG_HW_CONSOLE                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HW_PERF_EVENTS                           policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_HW_RANDOM                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HW_RANDOM_AMD                            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_HW_RANDOM_BCM2835                        policy<{'arm64': 'm'}>
+CONFIG_HW_RANDOM_CAVIUM                         policy<{'arm64': 'm'}>
+CONFIG_HW_RANDOM_EXYNOS                         policy<{'armhf': 'm'}>
+CONFIG_HW_RANDOM_GEODE                          policy<{'i386': 'm'}>
+CONFIG_HW_RANDOM_HISI                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_HW_RANDOM_HISI_V2                        policy<{'arm64': 'm'}>
+CONFIG_HW_RANDOM_IMX_RNGC                       policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_HW_RANDOM_INTEL                          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_HW_RANDOM_IPROC_RNG200                   policy<{'arm64': 'm'}>
+CONFIG_HW_RANDOM_MESON                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_HW_RANDOM_MTK                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_HW_RANDOM_OMAP                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_HW_RANDOM_OMAP3_ROM                      policy<{'armhf-generic': 'm'}>
+CONFIG_HW_RANDOM_OPTEE                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_HW_RANDOM_POWERNV                        policy<{'ppc64el': 'm'}>
+CONFIG_HW_RANDOM_PSERIES                        policy<{'ppc64el': 'm'}>
+CONFIG_HW_RANDOM_S390                           policy<{'s390x': 'm'}>
+CONFIG_HW_RANDOM_TIMERIOMEM                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_HW_RANDOM_TPM                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_HW_RANDOM_VIA                            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_HW_RANDOM_VIRTIO                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_HW_RANDOM_XGENE                          policy<{'arm64': 'm'}>
+CONFIG_HX711                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HYPERV                                   policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_HYPERVISOR_GUEST                         policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_HYPERV_BALLOON                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_HYPERV_IOMMU                             policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_HYPERV_KEYBOARD                          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_HYPERV_NET                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_HYPERV_STORAGE                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_HYPERV_TIMER                             policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_HYPERV_UTILS                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_HYPERV_VSOCKETS                          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_HYSDN                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_HYSDN_CAPI                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_HZ                                       policy<{'amd64-generic': '250', 'amd64-lowlatency': '1000', 'arm64': '250', 'armhf': '250', 'i386-generic': '250', 'i386-lowlatency': '1000', 'ppc64el': '250', 's390x': '100'}>
+CONFIG_HZ_100                                   policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'y'}>
+CONFIG_HZ_1000                                  policy<{'amd64-generic': 'n', 'amd64-lowlatency': 'y', 'arm64': 'n', 'armhf': 'n', 'i386-generic': 'n', 'i386-lowlatency': 'y', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_HZ_200                                   policy<{'armhf': 'n'}>
+CONFIG_HZ_250                                   policy<{'amd64-generic': 'y', 'amd64-lowlatency': 'n', 'arm64': 'y', 'armhf': 'y', 'i386-generic': 'y', 'i386-lowlatency': 'n', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_HZ_300                                   policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_HZ_500                                   policy<{'armhf': 'n'}>
+CONFIG_HZ_FIXED                                 policy<{'armhf': '0'}>
+CONFIG_HZ_PERIODIC                              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_I2C                                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'm'}>
+CONFIG_I2C_ALGOBIT                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_I2C_ALGOPCA                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_I2C_ALI1535                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_I2C_ALI1563                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_I2C_ALI15X3                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_I2C_AMD756                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_I2C_AMD756_S4882                         policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_I2C_AMD8111                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_I2C_AMD_MP2                              policy<{'amd64': 'm', 'arm64': 'n', 'i386': 'n'}>
+CONFIG_I2C_ARB_GPIO_CHALLENGE                   policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_I2C_ASPEED                               policy<{'armhf': 'm'}>
+CONFIG_I2C_AXXIA                                policy<{'armhf-generic-lpae': 'm'}>
+CONFIG_I2C_BCM2835                              policy<{'arm64': 'm'}>
+CONFIG_I2C_BCM_IPROC                            policy<{'arm64': 'm'}>
+CONFIG_I2C_BOARDINFO                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_I2C_BRCMSTB                              policy<{'arm64': 'm'}>
+CONFIG_I2C_CADENCE                              policy<{'arm64': 'n'}>
+CONFIG_I2C_CBUS_GPIO                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_I2C_CHT_WC                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_I2C_COMPAT                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_I2C_CROS_EC_TUNNEL                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_I2C_DEBUG_ALGO                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_I2C_DEBUG_BUS                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_I2C_DEBUG_CORE                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_I2C_DEMUX_PINCTRL                        policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_I2C_DESIGNWARE_BAYTRAIL                  policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_I2C_DESIGNWARE_CORE                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_I2C_DESIGNWARE_PCI                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_I2C_DESIGNWARE_PLATFORM                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_I2C_DESIGNWARE_SLAVE                     policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_I2C_DIOLAN_U2C                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_I2C_DLN2                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_I2C_EG20T                                policy<{'i386': 'm'}>
+CONFIG_I2C_EMEV2                                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'm', 'i386': 'n'}>
+CONFIG_I2C_EXYNOS5                              policy<{'armhf': 'm'}>
+CONFIG_I2C_FSI                                  policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_I2C_GPIO                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_I2C_GPIO_FAULT_INJECTOR                  policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_I2C_HELPER_AUTO                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_I2C_HID                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_I2C_HIX5HD2                              policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_I2C_I801                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_I2C_IMX                                  policy<{'arm64': 'm', 'armhf-generic': 'y'}>
+CONFIG_I2C_IMX_LPI2C                            policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_I2C_ISCH                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_I2C_ISMT                                 policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_I2C_KEMPLD                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_I2C_MESON                                policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_I2C_MLXCPLD                              policy<{'amd64': 'm'}>
+CONFIG_I2C_MPC                                  policy<{'ppc64el': 'm'}>
+CONFIG_I2C_MT65XX                               policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_I2C_MULTI_INSTANTIATE                    policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_I2C_MUX                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_I2C_MUX_GPIO                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_I2C_MUX_GPMUX                            policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_I2C_MUX_LTC4306                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_I2C_MUX_MLXCPLD                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_I2C_MUX_PCA9541                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_I2C_MUX_PCA954x                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_I2C_MUX_PINCTRL                          policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_I2C_MUX_REG                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_I2C_MV64XXX                              policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_I2C_NFORCE2                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_I2C_NFORCE2_S4985                        policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_I2C_NOMADIK                              policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_I2C_NVIDIA_GPU                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_I2C_OCORES                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_I2C_OMAP                                 policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_I2C_OPAL                                 policy<{'ppc64el': 'y'}>
+CONFIG_I2C_OWL                                  policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_I2C_PARPORT                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_I2C_PARPORT_LIGHT                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_I2C_PCA_ISA                              policy<{'i386': 'm'}>
+CONFIG_I2C_PCA_PLATFORM                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_I2C_PIIX4                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_I2C_PXA                                  policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_I2C_PXA_SLAVE                            policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_I2C_QCOM_GENI                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_I2C_QUP                                  policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_I2C_RCAR                                 policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_I2C_RIIC                                 policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_I2C_RK3X                                 policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_I2C_ROBOTFUZZ_OSIF                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_I2C_S3C2410                              policy<{'armhf': 'y'}>
+CONFIG_I2C_SCMI                                 policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_I2C_SH_MOBILE                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_I2C_SI470X                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_I2C_SI4713                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_I2C_SIMTEC                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_I2C_SIS5595                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_I2C_SIS630                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_I2C_SIS96X                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_I2C_SLAVE                                policy<{'amd64': 'n', 'arm64': 'y', 'armhf': 'y', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_I2C_SLAVE_EEPROM                         policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_I2C_SMBUS                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_I2C_SPRD                                 policy<{'arm64': 'y'}>
+CONFIG_I2C_STUB                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_I2C_SYNQUACER                            policy<{'arm64': 'm'}>
+CONFIG_I2C_TAOS_EVM                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_I2C_TEGRA                                policy<{'armhf-generic': 'm'}>
+CONFIG_I2C_TEGRA_BPMP                           policy<{'armhf-generic': 'm'}>
+CONFIG_I2C_THUNDERX                             policy<{'arm64': 'm'}>
+CONFIG_I2C_TINY_USB                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_I2C_UNIPHIER                             policy<{'armhf': 'n'}>
+CONFIG_I2C_UNIPHIER_F                           policy<{'armhf': 'n'}>
+CONFIG_I2C_VERSATILE                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_I2C_VIA                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_I2C_VIAPRO                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_I2C_VIPERBOARD                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_I2C_XGENE_SLIMPRO                        policy<{'arm64': 'm'}>
+CONFIG_I2C_XILINX                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_I2C_XLP9XX                               policy<{'arm64': 'm'}>
+CONFIG_I3C                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_I40E                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_I40EVF                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_I40E_DCB                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_I6300ESB_WDT                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_I82092                                   policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_I82365                                   policy<{'i386': 'm'}>
+CONFIG_I8253_LOCK                               policy<{'amd64': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_I8K                                      policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_IA32_EMULATION                           policy<{'amd64': 'y'}>
+CONFIG_IAQCORE                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IAVF                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IB700_WDT                                policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_IBMASR                                   policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_IBMVETH                                  policy<{'ppc64el': 'm'}>
+CONFIG_IBMVIO                                   policy<{'ppc64el': 'y'}>
+CONFIG_IBMVMC                                   policy<{'ppc64el': 'm'}>
+CONFIG_IBM_ASM                                  policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_IBM_BSR                                  policy<{'ppc64el': 'm'}>
+CONFIG_IBM_PARTITION                            policy<{'s390x': 'y'}>
+CONFIG_IBM_RTL                                  policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_ICE                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ICPLUS_PHY                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_ICS932S401                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_ICST                                     policy<{'armhf': 'y'}>
+CONFIG_IDE                                      policy<{'amd64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_IDEAPAD_LAPTOP                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_IDLE_INJECT                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_IE6XX_WDT                                policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_IEEE802154                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_IEEE802154_6LOWPAN                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IEEE802154_ADF7242                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IEEE802154_AT86RF230                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IEEE802154_AT86RF230_DEBUGFS             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_IEEE802154_ATUSB                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IEEE802154_CA8210                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_IEEE802154_CA8210_DEBUGFS                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_IEEE802154_CC2520                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IEEE802154_DRIVERS                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IEEE802154_FAKELB                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IEEE802154_HWSIM                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IEEE802154_MCR20A                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IEEE802154_MRF24J40                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IEEE802154_NL802154_EXPERIMENTAL         policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_IEEE802154_SOCKET                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IFB                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IGB                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IGBVF                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IGB_DCA                                  policy<{'amd64': 'y'}>
+CONFIG_IGB_HWMON                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_IGC                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_IIO_ADIS_LIB                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_ADIS_LIB_BUFFER                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_IIO_BUFFER                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_IIO_BUFFER_CB                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_BUFFER_HW_CONSUMER                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_CONFIGFS                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_CONSUMERS_PER_TRIGGER                policy<{'amd64': '2', 'arm64': '2', 'armhf': '2', 'i386': '2', 'ppc64el': '2'}>
+CONFIG_IIO_CROS_EC_ACCEL_LEGACY                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_IIO_CROS_EC_BARO                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_IIO_CROS_EC_LIGHT_PROX                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_IIO_CROS_EC_SENSORS                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_IIO_CROS_EC_SENSORS_CORE                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_IIO_CROS_EC_SENSORS_LID_ANGLE            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_IIO_HRTIMER_TRIGGER                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_INTERRUPT_TRIGGER                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_KFIFO_BUF                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_MS_SENSORS_I2C                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_MUX                                  policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_RESCALE                              policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_SIMPLE_DUMMY                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_SSP_SENSORHUB                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_SSP_SENSORS_COMMONS                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_ST_ACCEL_3AXIS                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_ST_ACCEL_I2C_3AXIS                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_ST_ACCEL_SPI_3AXIS                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_ST_GYRO_3AXIS                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_ST_GYRO_I2C_3AXIS                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_ST_GYRO_SPI_3AXIS                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_ST_LSM6DSX                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_ST_LSM6DSX_I2C                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_ST_LSM6DSX_I3C                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_ST_LSM6DSX_SPI                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_ST_MAGN_3AXIS                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_ST_MAGN_I2C_3AXIS                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_ST_MAGN_SPI_3AXIS                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_ST_PRESS                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_ST_PRESS_I2C                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_ST_PRESS_SPI                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_ST_SENSORS_CORE                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_ST_SENSORS_I2C                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_ST_SENSORS_SPI                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_SW_DEVICE                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_SW_TRIGGER                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_SYSFS_TRIGGER                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_TIGHTLOOP_TRIGGER                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_TRIGGER                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_IIO_TRIGGERED_BUFFER                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IIO_TRIGGERED_EVENT                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IKCONFIG                                 policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_IKHEADERS                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_ILLEGAL_POINTER_VALUE                    policy<{'amd64': '0xdead000000000000', 'arm64': '0xdead000000000000', 'i386': '0', 'ppc64el': '0x5deadbeef0000000'}>
+CONFIG_IMA_APPRAISE_BOOTPARAM                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IMA_APPRAISE_BUILD_POLICY                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_IMA_APPRAISE_MODSIG                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IMA_BLACKLIST_KEYRING                    policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_IMA_DEFAULT_HASH                         policy<{'amd64': '"sha1"', 'arm64': '"sha1"', 'armhf': '"sha1"', 'i386': '"sha1"', 'ppc64el': '"sha256"', 's390x': '"sha1"'}>
+CONFIG_IMA_DEFAULT_HASH_SHA1                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'n', 's390x': 'y'}>
+CONFIG_IMA_DEFAULT_HASH_SHA512                  policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_IMA_DEFAULT_TEMPLATE                     policy<{'amd64': '"ima-ng"', 'arm64': '"ima-ng"', 'armhf': '"ima-ng"', 'i386': '"ima-ng"', 'ppc64el': '"ima-sig"', 's390x': '"ima-ng"'}>
+CONFIG_IMA_LOAD_X509                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_IMA_LSM_RULES                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IMA_MEASURE_PCR_IDX                      policy<{'amd64': '10', 'arm64': '10', 'armhf': '10', 'i386': '10', 'ppc64el': '10', 's390x': '10'}>
+CONFIG_IMA_NG_TEMPLATE                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'n', 's390x': 'y'}>
+CONFIG_IMG_ASCII_LCD                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IMX2_WDT                                 policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_IMX7D_ADC                                policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_IMX7ULP_WDT                              policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_IMX_DMA                                  policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_IMX_DSP                                  policy<{'arm64': 'y', 'armhf-generic': 'y'}>
+CONFIG_IMX_GPCV2                                policy<{'arm64': 'y', 'armhf-generic': 'y'}>
+CONFIG_IMX_GPCV2_PM_DOMAINS                     policy<{'arm64': 'y', 'armhf-generic': 'y'}>
+CONFIG_IMX_IPUV3_CORE                           policy<{'armhf': 'm'}>
+CONFIG_IMX_IRQSTEER                             policy<{'arm64': 'y', 'armhf-generic': 'y'}>
+CONFIG_IMX_MBOX                                 policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_IMX_REMOTEPROC                           policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_IMX_SCU                                  policy<{'arm64': 'y', 'armhf-generic': 'y'}>
+CONFIG_IMX_SCU_PD                               policy<{'arm64': 'y', 'armhf-generic': 'y'}>
+CONFIG_IMX_SCU_SOC                              policy<{'arm64': 'y', 'armhf-generic': 'y'}>
+CONFIG_IMX_SC_WDT                               policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_IMX_SDMA                                 policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_IMX_THERMAL                              policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_IMX_WEIM                                 policy<{'arm64': 'y', 'armhf-generic': 'y'}>
+CONFIG_INA2XX_ADC                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INDIRECT_PIO                             policy<{'arm64': 'y'}>
+CONFIG_INET                                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_INET6_AH                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_INET6_ESP                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_INET6_ESP_OFFLOAD                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_INET6_IPCOMP                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_INET6_TUNNEL                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_INET6_XFRM_TUNNEL                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_INET_AH                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_INET_DCCP_DIAG                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_INET_DIAG                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_INET_DIAG_DESTROY                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_INET_ESP                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_INET_ESP_OFFLOAD                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_INET_IPCOMP                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_INET_RAW_DIAG                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_INET_SCTP_DIAG                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_INET_TABLE_PERTURB_ORDER                 policy<{'amd64': '16', 'arm64': '16', 'armhf': '16', 'i386': '16', 'ppc64el': '16', 's390x': '16'}>
+CONFIG_INET_TCP_DIAG                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_INET_TUNNEL                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_INET_UDP_DIAG                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_INET_XFRM_TUNNEL                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_INFINIBAND                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_INFINIBAND_ADDR_TRANS                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_INFINIBAND_ADDR_TRANS_CONFIGFS           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_INFINIBAND_BNXT_RE                       policy<{'amd64': 'm', 'arm64': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_INFINIBAND_CXGB3                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INFINIBAND_CXGB4                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INFINIBAND_EFA                           policy<{'amd64': 'm', 'arm64': 'm', 'ppc64el': 'm'}>
+CONFIG_INFINIBAND_EXP_LEGACY_VERBS_NEW_UAPI     policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_INFINIBAND_HFI1                          policy<{'amd64': 'm'}>
+CONFIG_INFINIBAND_HNS                           policy<{'arm64': 'm'}>
+CONFIG_INFINIBAND_HNS_HIP06                     policy<{'arm64': 'y'}>
+CONFIG_INFINIBAND_HNS_HIP08                     policy<{'arm64': 'y'}>
+CONFIG_INFINIBAND_I40IW                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INFINIBAND_IPOIB                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_INFINIBAND_IPOIB_CM                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_INFINIBAND_IPOIB_DEBUG                   policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_INFINIBAND_ISER                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_INFINIBAND_ISERT                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_INFINIBAND_MTHCA                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_INFINIBAND_MTHCA_DEBUG                   policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_INFINIBAND_OCRDMA                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_INFINIBAND_ON_DEMAND_PAGING              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_INFINIBAND_OPA_VNIC                      policy<{'amd64': 'm'}>
+CONFIG_INFINIBAND_QEDR                          policy<{'amd64': 'm', 'arm64': 'm', 'ppc64el': 'm'}>
+CONFIG_INFINIBAND_QIB                           policy<{'amd64': 'm'}>
+CONFIG_INFINIBAND_QIB_DCA                       policy<{'amd64': 'y'}>
+CONFIG_INFINIBAND_RDMAVT                        policy<{'amd64': 'm'}>
+CONFIG_INFINIBAND_SRP                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_INFINIBAND_SRPT                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_INFINIBAND_USER_ACCESS                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_INFINIBAND_USER_MAD                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_INFINIBAND_USER_MEM                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_INFINIBAND_USNIC                         policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_INFINIBAND_VIRT_DMA                      policy<{'amd64': 'y', 'arm64': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_INFINIBAND_VMWARE_PVRDMA                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_INFTL                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INITRAMFS_SOURCE                         policy<{'amd64': '""', 'arm64': '""', 'armhf': '""', 'i386': '""', 'ppc64el': '""', 's390x': '""'}>
+CONFIG_INIT_ENV_ARG_LIMIT                       policy<{'amd64': '32', 'arm64': '32', 'armhf': '32', 'i386': '32', 'ppc64el': '32', 's390x': '32'}>
+CONFIG_INIT_ON_ALLOC_DEFAULT_ON                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_INIT_ON_FREE_DEFAULT_ON                  policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_INIT_STACK_NONE                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_INLINE_READ_LOCK                         policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_INLINE_READ_LOCK_BH                      policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_INLINE_READ_LOCK_IRQ                     policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_INLINE_READ_LOCK_IRQSAVE                 policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_INLINE_READ_TRYLOCK                      policy<{'s390x': 'y'}>
+CONFIG_INLINE_READ_UNLOCK                       policy<{'amd64-generic': 'y', 'arm64': 'y', 'armhf': 'y', 'i386-generic': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_INLINE_READ_UNLOCK_BH                    policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_INLINE_READ_UNLOCK_IRQ                   policy<{'amd64-generic': 'y', 'arm64': 'y', 'armhf': 'y', 'i386-generic': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_INLINE_READ_UNLOCK_IRQRESTORE            policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_INLINE_SPIN_LOCK                         policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_INLINE_SPIN_LOCK_BH                      policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_INLINE_SPIN_LOCK_IRQ                     policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_INLINE_SPIN_LOCK_IRQSAVE                 policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_INLINE_SPIN_TRYLOCK                      policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_INLINE_SPIN_TRYLOCK_BH                   policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_INLINE_SPIN_UNLOCK_BH                    policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_INLINE_SPIN_UNLOCK_IRQ                   policy<{'amd64-generic': 'y', 'arm64': 'y', 'armhf': 'y', 'i386-generic': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE            policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_INLINE_WRITE_LOCK                        policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_INLINE_WRITE_LOCK_BH                     policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_INLINE_WRITE_LOCK_IRQ                    policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_INLINE_WRITE_LOCK_IRQSAVE                policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_INLINE_WRITE_TRYLOCK                     policy<{'s390x': 'y'}>
+CONFIG_INLINE_WRITE_UNLOCK                      policy<{'amd64-generic': 'y', 'arm64': 'y', 'armhf': 'y', 'i386-generic': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_INLINE_WRITE_UNLOCK_BH                   policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_INLINE_WRITE_UNLOCK_IRQ                  policy<{'amd64-generic': 'y', 'arm64': 'y', 'armhf': 'y', 'i386-generic': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE           policy<{'arm64': 'y', 's390x': 'y'}>
+CONFIG_INOTIFY_USER                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_INPUT                                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_INPUT_88PM80X_ONKEY                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_88PM860X_ONKEY                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_AD714X                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_AD714X_I2C                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_AD714X_SPI                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_ADXL34X                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_ADXL34X_I2C                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_ADXL34X_SPI                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_APANEL                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_INPUT_ARIZONA_HAPTICS                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_ATI_REMOTE2                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_ATLAS_BTNS                         policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_INPUT_ATMEL_CAPTOUCH                     policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_AXP20X_PEK                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_BMA150                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_CM109                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_CMA3000                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_CMA3000_I2C                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_CPCAP_PWRBUTTON                    policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_DA9052_ONKEY                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_DA9055_ONKEY                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_DA9063_ONKEY                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_DRV260X_HAPTICS                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_DRV2665_HAPTICS                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_DRV2667_HAPTICS                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_E3X0_BUTTON                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_EVBUG                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_INPUT_EVDEV                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_INPUT_FF_MEMLESS                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_INPUT_GP2A                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_GPIO_BEEPER                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_GPIO_DECODER                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_GPIO_ROTARY_ENCODER                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_GPIO_VIBRA                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_HISI_POWERKEY                      policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_INPUT_IDEAPAD_SLIDEBAR                   policy<{'amd64': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_IMS_PCU                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_JOYDEV                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_INPUT_JOYSTICK                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_INPUT_KEYBOARD                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_INPUT_KEYSPAN_REMOTE                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_KXTJ9                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_KXTJ9_POLLED_MODE                  policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_INPUT_LEDS                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_MATRIXKMAP                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_INPUT_MAX77650_ONKEY                     policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_MAX77693_HAPTIC                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_MAX8925_ONKEY                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_MAX8997_HAPTIC                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_MC13783_PWRBUTTON                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_MISC                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_INPUT_MMA8450                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_MOUSE                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_INPUT_MOUSEDEV                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_INPUT_MOUSEDEV_PSAUX                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_INPUT_MOUSEDEV_SCREEN_X                  policy<{'amd64': '1024', 'arm64': '1024', 'armhf': '1024', 'i386': '1024', 'ppc64el': '1024'}>
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y                  policy<{'amd64': '768', 'arm64': '768', 'armhf': '768', 'i386': '768', 'ppc64el': '768'}>
+CONFIG_INPUT_MSM_VIBRATOR                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_PALMAS_PWRBUTTON                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_PCAP                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_PCF50633_PMU                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_PCF8574                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_PCSPKR                             policy<{'amd64': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_PM8941_PWRKEY                      policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_INPUT_PM8XXX_VIBRATOR                    policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_INPUT_PMIC8XXX_PWRKEY                    policy<{'armhf': 'm'}>
+CONFIG_INPUT_POLLDEV                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_INPUT_POWERMATE                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_PWM_BEEPER                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_PWM_VIBRA                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_RAVE_SP_PWRBUTTON                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_REGULATOR_HAPTIC                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_RETU_PWRBUTTON                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_RK805_PWRKEY                       policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_SC27XX_VIBRA                       policy<{'arm64': 'm'}>
+CONFIG_INPUT_SOC_BUTTON_ARRAY                   policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_INPUT_SPARSEKMAP                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_INPUT_STPMIC1_ONKEY                      policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_TABLET                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_INPUT_TOUCHSCREEN                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_INPUT_TPS65218_PWRBUTTON                 policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_TWL4030_PWRBUTTON                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_TWL4030_VIBRA                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_TWL6040_VIBRA                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_WISTRON_BTNS                       policy<{'i386': 'm'}>
+CONFIG_INPUT_WM831X_ON                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INPUT_XEN_KBDDEV_FRONTEND                policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_INPUT_YEALINK                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INSTRUCTION_DECODER                      policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_INT3406_THERMAL                          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_INT340X_THERMAL                          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_INTEGRITY                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_INTEGRITY_ASYMMETRIC_KEYS                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_INTEGRITY_AUDIT                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_INTEGRITY_SIGNATURE                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_INTEGRITY_TRUSTED_KEYRING                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_INTEL_ATOMISP2_PM                        policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_INTEL_BXTWC_PMIC_TMU                     policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_INTEL_BXT_PMIC_THERMAL                   policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_INTEL_CHTDC_TI_PWRBTN                    policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_INTEL_CHT_INT33FE                        policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_INTEL_GTT                                policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_INTEL_HID_EVENT                          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_INTEL_IDLE                               policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_INTEL_IDMA64                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INTEL_INT0002_VGPIO                      policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_INTEL_IOATDMA                            policy<{'amd64': 'm'}>
+CONFIG_INTEL_IOMMU                              policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_INTEL_IOMMU_FLOPPY_WA                    policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_INTEL_IOMMU_SVM                          policy<{'amd64': 'y', 'i386': '-'}>
+CONFIG_INTEL_IPS                                policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_INTEL_ISH_FIRMWARE_DOWNLOADER            policy<{'amd64': 'm'}>
+CONFIG_INTEL_ISH_HID                            policy<{'amd64': 'm'}>
+CONFIG_INTEL_MEI                                policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_INTEL_MEI_HDCP                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_INTEL_MEI_ME                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_INTEL_MEI_TXE                            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_INTEL_MEI_WDT                            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_INTEL_MENLOW                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_INTEL_MFLD_THERMAL                       policy<{'i386': 'm'}>
+CONFIG_INTEL_MIC_BUS                            policy<{'amd64': 'm'}>
+CONFIG_INTEL_MIC_CARD                           policy<{'amd64': 'm'}>
+CONFIG_INTEL_MIC_HOST                           policy<{'amd64': 'm'}>
+CONFIG_INTEL_MIC_X100_DMA                       policy<{'amd64': 'm'}>
+CONFIG_INTEL_MID_POWER_BUTTON                   policy<{'i386': 'm'}>
+CONFIG_INTEL_MID_PTI                            policy<{'i386': 'm'}>
+CONFIG_INTEL_MID_WATCHDOG                       policy<{'i386': 'm'}>
+CONFIG_INTEL_MRFLD_PWRBTN                       policy<{'i386': 'm'}>
+CONFIG_INTEL_OAKTRAIL                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_INTEL_PCH_THERMAL                        policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_INTEL_PMC_CORE                           policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_INTEL_PMC_IPC                            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_INTEL_POWERCLAMP                         policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_INTEL_PUNIT_IPC                          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_INTEL_RAPL                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_INTEL_RAPL_CORE                          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_INTEL_RST                                policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_INTEL_SCU_IPC                            policy<{'i386': 'y'}>
+CONFIG_INTEL_SCU_IPC_UTIL                       policy<{'i386': 'm'}>
+CONFIG_INTEL_SCU_WATCHDOG                       policy<{'i386': 'y'}>
+CONFIG_INTEL_SMARTCONNECT                       policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_INTEL_SOC_DTS_IOSF_CORE                  policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_INTEL_SOC_DTS_THERMAL                    policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_INTEL_SOC_PMIC                           policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_INTEL_SOC_PMIC_BXTWC                     policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_INTEL_SOC_PMIC_CHTDC_TI                  policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_INTEL_SOC_PMIC_CHTWC                     policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_INTEL_SOC_PMIC_MRFLD                     policy<{'i386': 'm'}>
+CONFIG_INTEL_SPEED_SELECT_INTERFACE             policy<{'amd64': 'm'}>
+CONFIG_INTEL_STRATIX10_RSU                      policy<{'arm64': 'm'}>
+CONFIG_INTEL_STRATIX10_SERVICE                  policy<{'arm64': 'm'}>
+CONFIG_INTEL_TELEMETRY                          policy<{'amd64': 'm'}>
+CONFIG_INTEL_TH                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_INTEL_TH_ACPI                            policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_INTEL_TH_DEBUG                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_INTEL_TH_GTH                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_INTEL_TH_MSU                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_INTEL_TH_PCI                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_INTEL_TH_PTI                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_INTEL_TH_STH                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_INTEL_TURBO_MAX_3                        policy<{'amd64': 'y'}>
+CONFIG_INTEL_TXT                                policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_INTEL_VBTN                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_INTEL_WMI_THUNDERBOLT                    policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_INTEL_XWAY_PHY                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_INTERCONNECT                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_INTERCONNECT_QCOM                        policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_INTERCONNECT_QCOM_QCS404                 policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_INTERCONNECT_QCOM_SDM845                 policy<{'arm64': 'm'}>
+CONFIG_INTERCONNECT_QCOM_SMD_RPM                policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_INTERVAL_TREE                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_INTERVAL_TREE_TEST                       policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_INV_MPU6050_I2C                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INV_MPU6050_IIO                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_INV_MPU6050_SPI                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IOMMU_API                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IOMMU_DEBUG                              policy<{'amd64': 'n'}>
+CONFIG_IOMMU_DEFAULT_PASSTHROUGH                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_IOMMU_DMA                                policy<{'arm64': 'y'}>
+CONFIG_IOMMU_HELPER                             policy<{'amd64': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IOMMU_IOVA                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf-generic': 'm', 'i386': 'y'}>
+CONFIG_IOMMU_IO_PGTABLE                         policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_IOMMU_IO_PGTABLE_ARMV7S                  policy<{'arm64': 'n', 'armhf': 'n'}>
+CONFIG_IOMMU_IO_PGTABLE_LPAE                    policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_IOMMU_IO_PGTABLE_LPAE_SELFTEST           policy<{'arm64': 'n', 'armhf': 'n'}>
+CONFIG_IOMMU_SUPPORT                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ION                                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_IONIC                                    policy<{'amd64': 'm', 'arm64': 'm', 'ppc64el': 'm'}>
+CONFIG_IOSCHED_BFQ                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IOSF_MBI                                 policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_IOSF_MBI_DEBUG                           policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_IO_DELAY_0X80                            policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_IO_DELAY_0XED                            policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_IO_DELAY_NONE                            policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_IO_DELAY_UDELAY                          policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_IO_EVENT_IRQ                             policy<{'ppc64el': 'y'}>
+CONFIG_IO_STRICT_DEVMEM                         policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_IO_URING                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IP6_NF_FILTER                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP6_NF_IPTABLES                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP6_NF_MANGLE                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP6_NF_MATCH_AH                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP6_NF_MATCH_EUI64                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP6_NF_MATCH_FRAG                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP6_NF_MATCH_HL                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP6_NF_MATCH_IPV6HEADER                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP6_NF_MATCH_MH                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP6_NF_MATCH_OPTS                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP6_NF_MATCH_RPFILTER                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP6_NF_MATCH_RT                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP6_NF_MATCH_SRH                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP6_NF_NAT                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP6_NF_RAW                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP6_NF_SECURITY                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP6_NF_TARGET_HL                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP6_NF_TARGET_MASQUERADE                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP6_NF_TARGET_NPT                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP6_NF_TARGET_REJECT                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP6_NF_TARGET_SYNPROXY                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IPACK_BUS                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_IPC_NS                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IPMB_DEVICE_INTERFACE                    policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_IPMI_DEVICE_INTERFACE                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IPMI_DMI_DECODE                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_IPMI_HANDLER                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_IPMI_KCS_BMC                             policy<{'armhf': 'm'}>
+CONFIG_IPMI_PANIC_EVENT                         policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_IPMI_PLAT_DATA                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_IPMI_POWERNV                             policy<{'ppc64el': 'm'}>
+CONFIG_IPMI_POWEROFF                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IPMI_SI                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IPMI_SSIF                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IPMI_WATCHDOG                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IPQ_GCC_4019                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_IPQ_GCC_806X                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_IPQ_GCC_8074                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_IPQ_LCC_806X                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_IPV6_FOU                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IPV6_FOU_TUNNEL                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IPV6_GRE                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IPV6_ILA                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IPV6_MIP6                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IPV6_MROUTE                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IPV6_MULTIPLE_TABLES                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IPV6_NDISC_NODETYPE                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IPV6_OPTIMISTIC_DAD                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_IPV6_PIMSM_V2                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IPV6_ROUTER_PREF                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IPV6_ROUTE_INFO                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IPV6_SEG6_BPF                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IPV6_SEG6_HMAC                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IPV6_SEG6_LWTUNNEL                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IPV6_SIT                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IPV6_SIT_6RD                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IPV6_SUBTREES                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IPV6_TUNNEL                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IPV6_VTI                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IPVLAN                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IPVLAN_L3S                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IPVTAP                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IPW2100                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IPW2100_DEBUG                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_IPW2100_MONITOR                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_IPW2200                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IPW2200_DEBUG                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_IPW2200_MONITOR                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_IPW2200_PROMISCUOUS                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_IPW2200_QOS                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_IPW2200_RADIOTAP                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_IPWIRELESS                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_IP_ADVANCED_ROUTER                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IP_DCCP                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_DCCP_CCID2_DEBUG                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_IP_DCCP_CCID3                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'y'}>
+CONFIG_IP_DCCP_CCID3_DEBUG                      policy<{'s390x': 'n'}>
+CONFIG_IP_DCCP_DEBUG                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_IP_DCCP_TFRC_LIB                         policy<{'s390x': 'y'}>
+CONFIG_IP_FIB_TRIE_STATS                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IP_MROUTE                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IP_MROUTE_COMMON                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IP_MROUTE_MULTIPLE_TABLES                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IP_MULTICAST                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IP_MULTIPLE_TABLES                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IP_NF_ARPFILTER                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_NF_ARPTABLES                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_NF_ARP_MANGLE                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_NF_FILTER                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_NF_IPTABLES                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_NF_MANGLE                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_NF_MATCH_AH                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_NF_MATCH_ECN                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_NF_MATCH_RPFILTER                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_NF_MATCH_TTL                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_NF_NAT                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_NF_RAW                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_NF_SECURITY                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_NF_TARGET_CLUSTERIP                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_NF_TARGET_ECN                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_NF_TARGET_MASQUERADE                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_NF_TARGET_NETMAP                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_NF_TARGET_REDIRECT                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_NF_TARGET_REJECT                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_NF_TARGET_SYNPROXY                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_NF_TARGET_TTL                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_PIMSM_V1                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IP_PIMSM_V2                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IP_ROUTE_CLASSID                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IP_ROUTE_MULTIPATH                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IP_ROUTE_VERBOSE                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IP_SCTP                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_SET                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_SET_BITMAP_IP                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_SET_BITMAP_IPMAC                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_SET_BITMAP_PORT                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_SET_HASH_IP                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_SET_HASH_IPMAC                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_SET_HASH_IPMARK                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_SET_HASH_IPPORT                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_SET_HASH_IPPORTIP                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_SET_HASH_IPPORTNET                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_SET_HASH_MAC                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_SET_HASH_NET                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_SET_HASH_NETIFACE                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_SET_HASH_NETNET                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_SET_HASH_NETPORT                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_SET_HASH_NETPORTNET                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_SET_LIST_SET                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_SET_MAX                               policy<{'amd64': '256', 'arm64': '256', 'armhf': '256', 'i386': '256', 'ppc64el': '256', 's390x': '256'}>
+CONFIG_IP_VS                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_VS_DEBUG                              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_IP_VS_DH                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_VS_FO                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_VS_FTP                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_VS_IPV6                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IP_VS_LBLC                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_VS_LBLCR                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_VS_LC                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_VS_MH                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_VS_MH_TAB_INDEX                       policy<{'amd64': '12', 'arm64': '12', 'armhf': '12', 'i386': '12', 'ppc64el': '12', 's390x': '12'}>
+CONFIG_IP_VS_NFCT                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IP_VS_NQ                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_VS_OVF                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_VS_PE_SIP                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_VS_PROTO_AH                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IP_VS_PROTO_AH_ESP                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IP_VS_PROTO_ESP                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IP_VS_PROTO_SCTP                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IP_VS_PROTO_TCP                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IP_VS_PROTO_UDP                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IP_VS_RR                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_VS_SED                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_VS_SH                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_VS_SH_TAB_BITS                        policy<{'amd64': '8', 'arm64': '8', 'armhf': '8', 'i386': '8', 'ppc64el': '8', 's390x': '8'}>
+CONFIG_IP_VS_TAB_BITS                           policy<{'amd64': '12', 'arm64': '12', 'armhf': '12', 'i386': '12', 'ppc64el': '12', 's390x': '12'}>
+CONFIG_IP_VS_WLC                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IP_VS_WRR                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IRQCHIP                                  policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_IRQSOFF_TRACER                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_IRQ_ALL_CPUS                             policy<{'ppc64el': 'y'}>
+CONFIG_IRQ_BYPASS_MANAGER                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf-generic': 'm', 'armhf-generic-lpae': 'y', 'i386': 'm', 'ppc64el': 'y', 's390x': 'm'}>
+CONFIG_IRQ_CROSSBAR                             policy<{'armhf': 'y'}>
+CONFIG_IRQ_DOMAIN                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IRQ_DOMAIN_HIERARCHY                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_IRQ_FASTEOI_HIERARCHY_HANDLERS           policy<{'arm64': 'y'}>
+CONFIG_IRQ_FORCED_THREADING                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_IRQ_FORCED_THREADING_DEFAULT             policy<{'amd64-generic': 'n', 'amd64-lowlatency': 'y', 'arm64': 'n', 'armhf': 'n', 'i386-generic': 'n', 'i386-lowlatency': 'y', 'ppc64el': 'n'}>
+CONFIG_IRQ_MSI_IOMMU                            policy<{'arm64': 'y'}>
+CONFIG_IRQ_POLL                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IRQ_REMAP                                policy<{'amd64': 'y'}>
+CONFIG_IRQ_TIME_ACCOUNTING                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_IRQ_UNIPHIER_AIDET                       policy<{'armhf': 'y'}>
+CONFIG_IRQ_WORK                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_IR_ENE                                   policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_IR_FINTEK                                policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_IR_GPIO_CIR                              policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_IR_GPIO_TX                               policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_IR_HIX5HD2                               policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_IR_IGORPLUGUSB                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IR_IGUANA                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IR_IMON                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IR_IMON_DECODER                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IR_IMON_RAW                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IR_ITE_CIR                               policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_IR_JVC_DECODER                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IR_MCEUSB                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IR_MCE_KBD_DECODER                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IR_MESON                                 policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_IR_MTK                                   policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_IR_NEC_DECODER                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IR_NUVOTON                               policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_IR_PWM_TX                                policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_IR_RC5_DECODER                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IR_RC6_DECODER                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IR_RCMM_DECODER                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IR_REDRAT3                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IR_RX51                                  policy<{'armhf': 'm'}>
+CONFIG_IR_SANYO_DECODER                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IR_SERIAL                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IR_SERIAL_TRANSMITTER                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_IR_SHARP_DECODER                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IR_SIR                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IR_SONY_DECODER                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IR_SPI                                   policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_IR_STREAMZAP                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IR_SUNXI                                 policy<{'arm64': 'm'}>
+CONFIG_IR_TTUSBIR                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IR_WINBOND_CIR                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_IR_XMP_DECODER                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ISA                                      policy<{'i386': 'y'}>
+CONFIG_ISAPNP                                   policy<{'i386': 'y'}>
+CONFIG_ISA_BUS                                  policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_ISA_BUS_API                              policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_ISA_DMA_API                              policy<{'amd64': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ISCSI_BOOT_SYSFS                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_ISCSI_IBFT                               policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_ISCSI_IBFT_FIND                          policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_ISCSI_TARGET                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_ISCSI_TARGET_CXGB4                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ISCSI_TCP                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_ISDN                                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ISDN_CAPI                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ISDN_CAPI_CAPI20                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ISDN_CAPI_MIDDLEWARE                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ISDN_DRV_AVMB1_AVM_CS                    policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_ISDN_DRV_AVMB1_B1ISA                     policy<{'i386': 'm'}>
+CONFIG_ISDN_DRV_AVMB1_B1PCI                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ISDN_DRV_AVMB1_B1PCIV4                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ISDN_DRV_AVMB1_B1PCMCIA                  policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_ISDN_DRV_AVMB1_C4                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ISDN_DRV_AVMB1_T1ISA                     policy<{'i386': 'm'}>
+CONFIG_ISDN_DRV_AVMB1_T1PCI                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ISDN_DRV_GIGASET                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ISI                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ISL29003                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_ISL29020                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_ISL29125                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ISL29501                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ISO9660_FS                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_IT8712F_WDT                              policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_IT87_WDT                                 policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_ITCO_VENDOR_SUPPORT                      policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_ITCO_WDT                                 policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_ITG3200                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IUCV                                     policy<{'s390x': 'y'}>
+CONFIG_IWL3945                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IWL4965                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IWLDVM                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IWLEGACY                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IWLEGACY_DEBUG                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_IWLEGACY_DEBUGFS                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_IWLMVM                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IWLWIFI                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IWLWIFI_BCAST_FILTERING                  policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_IWLWIFI_DEBUG                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_IWLWIFI_DEBUGFS                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_IWLWIFI_DEVICE_TRACING                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_IWLWIFI_LEDS                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_IWLWIFI_OPMODE_MODULAR                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_IWMMXT                                   policy<{'armhf': 'y'}>
+CONFIG_IXGB                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IXGBE                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IXGBEVF                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_IXGBEVF_IPSEC                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_IXGBE_DCA                                policy<{'amd64': 'y'}>
+CONFIG_IXGBE_DCB                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_IXGBE_HWMON                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_IXGBE_IPSEC                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_JAILHOUSE_GUEST                          policy<{'amd64': 'y'}>
+CONFIG_JBD2                                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_JBD2_DEBUG                               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_JFFS2_CMODE_FAVOURLZO                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_JFFS2_CMODE_NONE                         policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_JFFS2_CMODE_PRIORITY                     policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_JFFS2_CMODE_SIZE                         policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_JFFS2_COMPRESSION_OPTIONS                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_JFFS2_FS                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_JFFS2_FS_DEBUG                           policy<{'amd64': '0', 'arm64': '0', 'armhf': '0', 'i386': '0', 'ppc64el': '0'}>
+CONFIG_JFFS2_FS_POSIX_ACL                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_JFFS2_FS_SECURITY                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_JFFS2_FS_WBUF_VERIFY                     policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_JFFS2_FS_WRITEBUFFER                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_JFFS2_FS_XATTR                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_JFFS2_LZO                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_JFFS2_RTIME                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_JFFS2_RUBIN                              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_JFFS2_SUMMARY                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_JFFS2_ZLIB                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_JFS_DEBUG                                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_JFS_FS                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_JFS_POSIX_ACL                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_JFS_SECURITY                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_JFS_STATISTICS                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_JME                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_JOLIET                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_JOYSTICK_A3D                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_JOYSTICK_ADI                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_JOYSTICK_ANALOG                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_JOYSTICK_AS5011                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_JOYSTICK_COBRA                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_JOYSTICK_DB9                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_JOYSTICK_FSIA6B                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_JOYSTICK_GAMECON                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_JOYSTICK_GF2K                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_JOYSTICK_GRIP                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_JOYSTICK_GRIP_MP                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_JOYSTICK_GUILLEMOT                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_JOYSTICK_IFORCE                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_JOYSTICK_IFORCE_232                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_JOYSTICK_IFORCE_USB                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_JOYSTICK_INTERACT                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_JOYSTICK_JOYDUMP                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_JOYSTICK_MAGELLAN                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_JOYSTICK_PSXPAD_SPI                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_JOYSTICK_PSXPAD_SPI_FF                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_JOYSTICK_PXRC                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_JOYSTICK_SIDEWINDER                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_JOYSTICK_SPACEBALL                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_JOYSTICK_SPACEORB                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_JOYSTICK_STINGER                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_JOYSTICK_TMDC                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_JOYSTICK_TURBOGRAFX                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_JOYSTICK_TWIDJOY                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_JOYSTICK_WALKERA0701                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_JOYSTICK_WARRIOR                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_JOYSTICK_XPAD                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_JOYSTICK_XPAD_FF                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_JOYSTICK_XPAD_LEDS                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_JOYSTICK_ZHENHUA                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_JSA1212                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_JUMP_LABEL                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'n', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_JUMP_LABEL_FEATURE_CHECKS                policy<{'ppc64el': 'y'}>
+CONFIG_JUMP_LABEL_FEATURE_CHECK_DEBUG           policy<{'ppc64el': 'n'}>
+CONFIG_K3_DMA                                   policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_KALLSYMS                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_KALLSYMS_ABSOLUTE_PERCPU                 policy<{'amd64': 'y'}>
+CONFIG_KALLSYMS_ALL                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_KALLSYMS_BASE_RELATIVE                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_KARMA_PARTITION                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_KASAN                                    policy<{'amd64': 'n', 'arm64': 'n', 's390x': 'n'}>
+CONFIG_KASAN_STACK                              policy<{'amd64': '1', 'arm64': '1', 'armhf': '1', 'i386': '1', 'ppc64el': '1', 's390x': '1'}>
+CONFIG_KCOV                                     policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_KDB_CONTINUE_CATASTROPHIC                policy<{'amd64': '0', 'arm64': '0', 'armhf': '0', 'i386': '0', 'ppc64el': '0'}>
+CONFIG_KDB_DEFAULT_ENABLE                       policy<{'amd64': '0x1', 'arm64': '0x1', 'armhf': '0x1', 'i386': '0x1', 'ppc64el': '0x1'}>
+CONFIG_KDB_KEYBOARD                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_KEMPLD_WDT                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KERNEL_BZIP2                             policy<{'amd64': 'n', 'i386': 'n', 's390x': 'n'}>
+CONFIG_KERNEL_GZIP                              policy<{'amd64': 'n', 'armhf': 'y', 'i386': 'n', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_KERNEL_LZ4                               policy<{'amd64': 'y', 'armhf': 'n', 'i386': 'y', 's390x': 'y'}>
+CONFIG_KERNEL_LZMA                              policy<{'amd64': 'n', 'armhf': 'n', 'i386': 'n', 's390x': 'n'}>
+CONFIG_KERNEL_LZO                               policy<{'amd64': 'n', 'armhf': 'n', 'i386': 'n', 's390x': 'n'}>
+CONFIG_KERNEL_MODE_NEON                         policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_KERNEL_NOBP                              policy<{'s390x': 'n'}>
+CONFIG_KERNEL_START                             policy<{'ppc64el': '0xc000000000000000'}>
+CONFIG_KERNEL_UNCOMPRESSED                      policy<{'s390x': 'n'}>
+CONFIG_KERNEL_XZ                                policy<{'amd64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_KERNFS                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_KEXEC                                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_KEXEC_CORE                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_KEXEC_ELF                                policy<{'ppc64el': 'y'}>
+CONFIG_KEXEC_FILE                               policy<{'amd64': 'y', 'arm64': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_KEXEC_IMAGE_VERIFY_SIG                   policy<{'arm64': 'n'}>
+CONFIG_KEXEC_JUMP                               policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_KEXEC_SIG                                policy<{'amd64': 'y', 'arm64': 'y'}>
+CONFIG_KEXEC_SIG_FORCE                          policy<{'amd64': 'n'}>
+CONFIG_KEYBOARD_ADC                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KEYBOARD_ADP5520                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KEYBOARD_ADP5588                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KEYBOARD_ADP5589                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KEYBOARD_APPLESPI                        policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_KEYBOARD_ATKBD                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_KEYBOARD_BCM                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_KEYBOARD_CAP11XX                         policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_KEYBOARD_CROS_EC                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_KEYBOARD_DLINK_DIR685                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KEYBOARD_GPIO                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KEYBOARD_GPIO_POLLED                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KEYBOARD_IMX                             policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_KEYBOARD_LKKBD                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KEYBOARD_LM8323                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KEYBOARD_LM8333                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KEYBOARD_MATRIX                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KEYBOARD_MAX7359                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KEYBOARD_MCS                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KEYBOARD_MPR121                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KEYBOARD_MTK_PMIC                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KEYBOARD_NEWTON                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KEYBOARD_NVEC                            policy<{'armhf-generic': 'm'}>
+CONFIG_KEYBOARD_OMAP4                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_KEYBOARD_OPENCORES                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KEYBOARD_PMIC8XXX                        policy<{'armhf': 'm'}>
+CONFIG_KEYBOARD_QT1050                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KEYBOARD_QT1070                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KEYBOARD_QT2160                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KEYBOARD_SAMSUNG                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_KEYBOARD_SNVS_PWRKEY                     policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_KEYBOARD_STMPE                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_KEYBOARD_STOWAWAY                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KEYBOARD_SUN4I_LRADC                     policy<{'arm64': 'n'}>
+CONFIG_KEYBOARD_SUNKBD                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KEYBOARD_TC3589X                         policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_KEYBOARD_TCA6416                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KEYBOARD_TCA8418                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KEYBOARD_TEGRA                           policy<{'armhf-generic': 'm'}>
+CONFIG_KEYBOARD_TM2_TOUCHKEY                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KEYBOARD_TWL4030                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KEYBOARD_XTKBD                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KEYS                                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_KEYS_COMPAT                              policy<{'amd64': 'y', 'arm64': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_KEYS_REQUEST_CACHE                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_KEY_DH_OPERATIONS                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_KGDB                                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_KGDB_KDB                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_KGDB_LOW_LEVEL_TRAP                      policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_KGDB_TESTS                               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_KMSG_IDS                                 policy<{'s390x': 'y'}>
+CONFIG_KMX61                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KPC2000                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_KPC2000_CORE                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KPC2000_DMA                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KPC2000_I2C                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KPC2000_SPI                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KPROBES                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_KPROBES_ON_FTRACE                        policy<{'amd64': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_KPROBES_SANITY_TEST                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_KPROBE_EVENTS                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_KPROBE_EVENTS_ON_NOTRACE                 policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_KPSS_XCC                                 policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_KRAITCC                                  policy<{'armhf': 'm'}>
+CONFIG_KRAIT_CLOCKS                             policy<{'armhf': 'y'}>
+CONFIG_KRAIT_L2_ACCESSORS                       policy<{'armhf': 'y'}>
+CONFIG_KRETPROBES                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_KS0108                                   policy<{'amd64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KS0108_DELAY                             policy<{'amd64': '2', 'armhf': '2', 'i386': '2', 'ppc64el': '2'}>
+CONFIG_KS0108_PORT                              policy<{'amd64': '0x378', 'armhf': '0x378', 'i386': '0x378', 'ppc64el': '0x378'}>
+CONFIG_KS7010                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KS8842                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KS8851                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KS8851_MLL                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KSM                                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_KSZ884X_PCI                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KUSER_HELPERS                            policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_KVM_AMD                                  policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_KVM_AMD_SEV                              policy<{'amd64': 'y'}>
+CONFIG_KVM_ARM_HOST                             policy<{'arm64': 'y', 'armhf-generic-lpae': 'y'}>
+CONFIG_KVM_ARM_PMU                              policy<{'arm64': 'y'}>
+CONFIG_KVM_ASYNC_PF                             policy<{'amd64': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_KVM_ASYNC_PF_SYNC                        policy<{'s390x': 'y'}>
+CONFIG_KVM_BOOK3S_64                            policy<{'ppc64el': 'm'}>
+CONFIG_KVM_BOOK3S_64_HANDLER                    policy<{'ppc64el': 'y'}>
+CONFIG_KVM_BOOK3S_64_HV                         policy<{'ppc64el': 'm'}>
+CONFIG_KVM_BOOK3S_64_PR                         policy<{'ppc64el': 'm'}>
+CONFIG_KVM_BOOK3S_HANDLER                       policy<{'ppc64el': 'y'}>
+CONFIG_KVM_BOOK3S_HV_EXIT_TIMING                policy<{'ppc64el': 'n'}>
+CONFIG_KVM_BOOK3S_HV_POSSIBLE                   policy<{'ppc64el': 'y'}>
+CONFIG_KVM_BOOK3S_PR_POSSIBLE                   policy<{'ppc64el': 'y'}>
+CONFIG_KVM_COMPAT                               policy<{'amd64': 'y', 'ppc64el': 'y'}>
+CONFIG_KVM_DEBUG_FS                             policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT        policy<{'amd64': 'y', 'arm64': 'y', 'armhf-generic-lpae': 'y', 'i386': 'y'}>
+CONFIG_KVM_GUEST                                policy<{'amd64': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_KVM_INDIRECT_VECTORS                     policy<{'arm64': 'y'}>
+CONFIG_KVM_INTEL                                policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_KVM_MMIO                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf-generic-lpae': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_KVM_MMU_AUDIT                            policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_KVM_S390_UCONTROL                        policy<{'s390x': 'n'}>
+CONFIG_KVM_VFIO                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf-generic-lpae': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_KVM_XICS                                 policy<{'ppc64el': 'y'}>
+CONFIG_KVM_XIVE                                 policy<{'ppc64el': 'y'}>
+CONFIG_KXCJK1013                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KXSD9                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KXSD9_I2C                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_KXSD9_SPI                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_L2TP                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_L2TP_DEBUGFS                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_L2TP_ETH                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_L2TP_IP                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_L2TP_V3                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_LAN743X                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LANCE                                    policy<{'i386': 'm'}>
+CONFIG_LANMEDIA                                 policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_LAPB                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_LAPBETHER                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LATTICE_ECP3_CONFIG                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LCD_AMS369FG06                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LCD_CLASS_DEVICE                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_LCD_HX8357                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LCD_ILI922X                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LCD_ILI9320                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LCD_L4F00242T03                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LCD_LMS283GF05                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LCD_LMS501KF03                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LCD_LTV350QV                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LCD_OTM3225A                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LCD_PLATFORM                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LCD_TDO24M                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LCD_VGG2432A4                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LCS                                      policy<{'s390x': 'm'}>
+CONFIG_LDISC_AUTOLOAD                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_LDM_DEBUG                                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_LDM_PARTITION                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_LD_DEAD_CODE_DATA_ELIMINATION            policy<{'ppc64el': 'n'}>
+CONFIG_LD_HEAD_STUB_CATCH                       policy<{'ppc64el': 'n'}>
+CONFIG_LEDS_88PM860X                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_AAT1290                             policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_ADP5520                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_AN30259A                            policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_APU                                 policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_LEDS_AS3645A                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_ASIC3                               policy<{'armhf': 'y'}>
+CONFIG_LEDS_BCM6328                             policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_BCM6358                             policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_BD2802                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_BLINKM                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_BRIGHTNESS_HW_CHANGED               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_LEDS_CLASS                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_LEDS_CLASS_FLASH                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_CLEVO_MAIL                          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_LEDS_CPCAP                               policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_CR0014114                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_DA903X                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_DA9052                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_DAC124S085                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_GPIO                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_INTEL_SS4200                        policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_LEDS_IS31FL319X                          policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_IS31FL32XX                          policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_KTD2692                             policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_LM3530                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_LM3532                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_LM3533                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_LM355x                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_LM3601X                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_LM36274                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_LM3642                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_LM3692X                             policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_LM3697                              policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_LP3944                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_LP3952                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_LP5521                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_LP5523                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_LP5562                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_LP55XX_COMMON                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_LP8501                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_LP8788                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_LP8860                              policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_LT3593                              policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_MAX77650                            policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_MAX77693                            policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_MAX8997                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_MC13783                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_MENF21BMC                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_MLXCPLD                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_LEDS_MLXREG                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_MT6323                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_NET48XX                             policy<{'i386': 'm'}>
+CONFIG_LEDS_NIC78BX                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_LEDS_NS2                                 policy<{'armhf': 'm'}>
+CONFIG_LEDS_OT200                               policy<{'i386': 'm'}>
+CONFIG_LEDS_PCA9532                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_PCA9532_GPIO                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_LEDS_PCA955X                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_PCA955X_GPIO                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_LEDS_PCA963X                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_PM8058                              policy<{'armhf': 'm'}>
+CONFIG_LEDS_POWERNV                             policy<{'ppc64el': 'm'}>
+CONFIG_LEDS_PWM                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_REGULATOR                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_SC27XX_BLTC                         policy<{'arm64': 'm'}>
+CONFIG_LEDS_SPI_BYTE                            policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_SYSCON                              policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_LEDS_TCA6507                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_TI_LMU_COMMON                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_TLC591XX                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_TRIGGERS                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_LEDS_TRIGGER_ACTIVITY                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_TRIGGER_AUDIO                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_TRIGGER_BACKLIGHT                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_TRIGGER_CAMERA                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_TRIGGER_CPU                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_LEDS_TRIGGER_DEFAULT_ON                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_TRIGGER_DISK                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_LEDS_TRIGGER_GPIO                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_TRIGGER_HEARTBEAT                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_TRIGGER_MTD                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_LEDS_TRIGGER_NETDEV                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_TRIGGER_ONESHOT                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_TRIGGER_PANIC                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_LEDS_TRIGGER_PATTERN                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_TRIGGER_TIMER                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_TRIGGER_TRANSIENT                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_USER                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_WM831X_STATUS                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_WM8350                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LEDS_WRAP                                policy<{'i386': 'm'}>
+CONFIG_LED_TRIGGER_PHY                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_LEGACY_PTYS                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_LEGACY_PTY_COUNT                         policy<{'amd64': '0', 'arm64': '0', 'armhf': '0', 'i386': '0', 'ppc64el': '0', 's390x': '0'}>
+CONFIG_LEGACY_VSYSCALL_EMULATE                  policy<{'amd64': 'n'}>
+CONFIG_LEGACY_VSYSCALL_NONE                     policy<{'amd64': 'n'}>
+CONFIG_LEGACY_VSYSCALL_XONLY                    policy<{'amd64': 'y'}>
+CONFIG_LG_LAPTOP                                policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_LIB80211                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LIB80211_CRYPT_CCMP                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LIB80211_CRYPT_TKIP                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LIB80211_CRYPT_WEP                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LIB80211_DEBUG                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_LIBCRC32C                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_LIBERTAS                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LIBERTAS_CS                              policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_LIBERTAS_DEBUG                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_LIBERTAS_MESH                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_LIBERTAS_SDIO                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LIBERTAS_SPI                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LIBERTAS_THINFIRM                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LIBERTAS_THINFIRM_DEBUG                  policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_LIBERTAS_THINFIRM_USB                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LIBERTAS_USB                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LIBFC                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_LIBFCOE                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_LIBFDT                                   policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_LIBIPW                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LIBIPW_DEBUG                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_LIBNVDIMM                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf-generic-lpae': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_LIDAR_LITE_V2                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LIQUIDIO                                 policy<{'amd64': 'm', 'arm64': 'm', 'ppc64el': 'm'}>
+CONFIG_LIQUIDIO_VF                              policy<{'amd64': 'm', 'arm64': 'm', 'ppc64el': 'm'}>
+CONFIG_LIRC                                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_LIVEPATCH                                policy<{'amd64': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_LKDTM                                    policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_LLC                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_LLC2                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_LMP91000                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LOAD_IPL_KEYS                            policy<{'s390x': 'y'}>
+CONFIG_LOAD_UEFI_KEYS                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_LOCALVERSION                             policy<{'amd64': '""', 'arm64': '""', 'armhf': '""', 'i386': '""', 'ppc64el': '""', 's390x': '""'}>
+CONFIG_LOCKD                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_LOCKDEP_SUPPORT                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_LOCKD_V4                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_LOCKUP_DETECTOR                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_LOCK_DEBUGGING_SUPPORT                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_LOCK_DOWN_IN_SECURE_BOOT                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_LOCK_DOWN_KERNEL_FORCE_CONFIDENTIALITY   policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_LOCK_DOWN_KERNEL_FORCE_INTEGRITY         policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_LOCK_DOWN_KERNEL_FORCE_NONE              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_LOCK_EVENT_COUNTS                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_LOCK_SPIN_ON_OWNER                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_LOCK_STAT                                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_LOCK_TORTURE_TEST                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_LOGIG940_FF                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_LOGIRUMBLEPAD2_FF                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_LOGITECH_FF                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_LOGIWHEELS_FF                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_LOGO                                     policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_LOG_BUF_SHIFT                            policy<{'amd64': '18', 'arm64': '18', 'armhf': '17', 'i386': '17', 'ppc64el': '18', 's390x': '18'}>
+CONFIG_LOG_CPU_MAX_BUF_SHIFT                    policy<{'amd64': '12', 'arm64': '12', 'armhf': '12', 'i386': '12', 'ppc64el': '12', 's390x': '12'}>
+CONFIG_LOOPBACK_TARGET                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_LP8788_ADC                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LPARCFG                                  policy<{'ppc64el': 'y'}>
+CONFIG_LPC_ICH                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_LPC_SCH                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_LP_CONSOLE                               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_LRU_CACHE                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_LSI_ET1011C_PHY                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_LSM                                      policy<{'amd64': '"lockdown,yama,integrity,apparmor"', 'arm64': '"lockdown,yama,integrity,apparmor"', 'armhf': '"lockdown,yama,integrity,apparmor"', 'i386': '"lockdown,yama,integrity,apparmor"', 'ppc64el': '"lockdown,yama,integrity,apparmor"', 's390x': '"lockdown,yama,integrity,apparmor"'}>
+CONFIG_LSM_MMAP_MIN_ADDR                        policy<{'amd64': '0', 'arm64': '0', 'armhf': '0', 'i386': '0', 'ppc64el': '0', 's390x': '0'}>
+CONFIG_LS_SCFG_MSI                              policy<{'arm64': 'y'}>
+CONFIG_LTC1660                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LTC2471                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LTC2485                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LTC2497                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LTC2632                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LTE_GDM724X                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LTPC                                     policy<{'amd64': '-', 'i386': 'm'}>
+CONFIG_LTR501                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LV0104CS                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_LWTUNNEL                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_LWTUNNEL_BPF                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_LXT_PHY                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_LZ4HC_COMPRESS                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_LZ4_COMPRESS                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_LZ4_DECOMPRESS                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_LZO_COMPRESS                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_LZO_DECOMPRESS                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_M486                                     policy<{'i386': 'n'}>
+CONFIG_M586                                     policy<{'i386': 'n'}>
+CONFIG_M586MMX                                  policy<{'i386': 'n'}>
+CONFIG_M586TSC                                  policy<{'i386': 'n'}>
+CONFIG_M62332                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_M686                                     policy<{'i386': 'y'}>
+CONFIG_MAC80211                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MAC80211_DEBUGFS                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MAC80211_DEBUG_MENU                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_MAC80211_HAS_RC                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MAC80211_HWSIM                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MAC80211_LEDS                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MAC80211_MESH                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MAC80211_MESSAGE_TRACING                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MAC80211_RC_DEFAULT                      policy<{'amd64': '"minstrel_ht"', 'arm64': '"minstrel_ht"', 'armhf': '"minstrel_ht"', 'i386': '"minstrel_ht"', 'ppc64el': '"minstrel_ht"'}>
+CONFIG_MAC80211_RC_DEFAULT_MINSTREL             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MAC80211_RC_MINSTREL                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MAC80211_STA_HASH_MAX_SIZE               policy<{'amd64': '0', 'arm64': '0', 'armhf': '0', 'i386': '0', 'ppc64el': '0'}>
+CONFIG_MAC802154                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MACB                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_MACB_PCI                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_MACB_USE_HWSTAMP                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_MACHZ_WDT                                policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_MACH_ARMADA_370                          policy<{'armhf': 'y'}>
+CONFIG_MACH_ARMADA_375                          policy<{'armhf': 'y'}>
+CONFIG_MACH_ARMADA_38X                          policy<{'armhf': 'y'}>
+CONFIG_MACH_ARMADA_39X                          policy<{'armhf': 'y'}>
+CONFIG_MACH_ARMADA_XP                           policy<{'armhf': 'y'}>
+CONFIG_MACH_ARTPEC6                             policy<{'armhf': 'n'}>
+CONFIG_MACH_ASPEED_G6                           policy<{'armhf': 'y'}>
+CONFIG_MACH_BERLIN_BG2                          policy<{'armhf': 'y'}>
+CONFIG_MACH_BERLIN_BG2CD                        policy<{'armhf': 'y'}>
+CONFIG_MACH_BERLIN_BG2Q                         policy<{'armhf': 'y'}>
+CONFIG_MACH_DOVE                                policy<{'armhf': 'y'}>
+CONFIG_MACH_MESON6                              policy<{'armhf': 'y'}>
+CONFIG_MACH_MESON8                              policy<{'armhf': 'y'}>
+CONFIG_MACH_MT2701                              policy<{'armhf': 'y'}>
+CONFIG_MACH_MT6589                              policy<{'armhf': 'y'}>
+CONFIG_MACH_MT6592                              policy<{'armhf': 'y'}>
+CONFIG_MACH_MT7623                              policy<{'armhf': 'y'}>
+CONFIG_MACH_MT7629                              policy<{'armhf': 'y'}>
+CONFIG_MACH_MT8127                              policy<{'armhf': 'y'}>
+CONFIG_MACH_MT8135                              policy<{'armhf': 'y'}>
+CONFIG_MACH_MVEBU_ANY                           policy<{'armhf': 'y'}>
+CONFIG_MACH_MVEBU_V7                            policy<{'armhf': 'y'}>
+CONFIG_MACH_OMAP3517EVM                         policy<{'armhf-generic': 'n'}>
+CONFIG_MACH_OMAP3_PANDORA                       policy<{'armhf-generic': 'y'}>
+CONFIG_MACH_OMAP_GENERIC                        policy<{'armhf': 'y'}>
+CONFIG_MACINTOSH_DRIVERS                        policy<{'amd64': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MACSEC                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MACVLAN                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MACVTAP                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MAC_EMUMOUSEBTN                          policy<{'amd64': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MAC_PARTITION                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_MADERA_IRQ                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MAG3110                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MAGIC_SYSRQ                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE               policy<{'amd64': '0x01b6', 'arm64': '0x01b6', 'armhf': '0x01b6', 'i386': '0x01b6', 'ppc64el': '0x01b6', 's390x': '0x01b6'}>
+CONFIG_MAGIC_SYSRQ_SERIAL                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MAILBOX                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_MAILBOX_TEST                             policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_MANAGER_SBS                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MANDATORY_FILE_LOCKING                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MANTIS_CORE                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MARCH_Z10                                policy<{'s390x': 'n'}>
+CONFIG_MARCH_Z13                                policy<{'s390x': 'y'}>
+CONFIG_MARCH_Z14                                policy<{'s390x': 'n'}>
+CONFIG_MARCH_Z15                                policy<{'s390x': 'n'}>
+CONFIG_MARCH_Z15_TUNE                           policy<{'s390x': 'y'}>
+CONFIG_MARCH_Z196                               policy<{'s390x': 'n'}>
+CONFIG_MARCH_Z900                               policy<{'s390x': 'n'}>
+CONFIG_MARCH_Z990                               policy<{'s390x': 'n'}>
+CONFIG_MARCH_Z9_109                             policy<{'s390x': 'n'}>
+CONFIG_MARCH_ZEC12                              policy<{'s390x': 'n'}>
+CONFIG_MARVELL_10G_PHY                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MARVELL_PHY                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MATH_EMULATION                           policy<{'i386': 'n'}>
+CONFIG_MATOM                                    policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_MAX1027                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MAX11100                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MAX1118                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MAX1363                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MAX30100                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MAX30102                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MAX31856                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MAX44000                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MAX44009                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MAX517                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MAX5432                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MAX5481                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MAX5487                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MAX5821                                  policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_MAX63XX_WATCHDOG                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MAX77620_THERMAL                         policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_MAX77620_WATCHDOG                        policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_MAX8925_POWER                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MAX9611                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MAXIM_THERMOCOUPLE                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MAXSMP                                   policy<{'amd64': 'y'}>
+CONFIG_MAX_PHYSMEM_BITS                         policy<{'s390x': '46'}>
+CONFIG_MAX_RAW_DEVS                             policy<{'amd64': '256', 'arm64': '256', 'armhf': '256', 'i386': '256', 'ppc64el': '256'}>
+CONFIG_MB1232                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MC3230                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MCB                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MCB_LPC                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MCB_PCI                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MCORE2                                   policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_MCP320X                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MCP3422                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MCP3911                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MCP4018                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MCP41010                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MCP4131                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MCP4531                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MCP4725                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MCP4922                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MCPM                                     policy<{'armhf': 'y'}>
+CONFIG_MCPM_QUAD_CLUSTER                        policy<{'armhf': 'y'}>
+CONFIG_MCRUSOE                                  policy<{'i386': 'n'}>
+CONFIG_MCYRIXIII                                policy<{'i386': 'n'}>
+CONFIG_MD                                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MDA_CONSOLE                              policy<{'i386': 'm'}>
+CONFIG_MDIO                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MDIO_ASPEED                              policy<{'armhf': 'm'}>
+CONFIG_MDIO_BCM_IPROC                           policy<{'arm64': 'n'}>
+CONFIG_MDIO_BCM_UNIMAC                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MDIO_BITBANG                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MDIO_BUS                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'm'}>
+CONFIG_MDIO_BUS_MUX                             policy<{'arm64': 'y', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_MDIO_BUS_MUX_BCM_IPROC                   policy<{'arm64': 'y'}>
+CONFIG_MDIO_BUS_MUX_GPIO                        policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_MDIO_BUS_MUX_MESON_G12A                  policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MDIO_BUS_MUX_MMIOREG                     policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_MDIO_BUS_MUX_MULTIPLEXER                 policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_MDIO_CAVIUM                              policy<{'amd64': 'm', 'arm64': 'm', 'ppc64el': 'm'}>
+CONFIG_MDIO_DEVICE                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MDIO_GPIO                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MDIO_HISI_FEMAC                          policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_MDIO_I2C                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MDIO_MSCC_MIIM                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MDIO_OCTEON                              policy<{'arm64': 'm', 'ppc64el': 'm'}>
+CONFIG_MDIO_SUN4I                               policy<{'arm64': 'n'}>
+CONFIG_MDIO_THUNDER                             policy<{'amd64': 'm', 'arm64': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MDIO_XGENE                               policy<{'arm64': 'm'}>
+CONFIG_MDM_GCC_9615                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MDM_LCC_9615                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MD_AUTODETECT                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MD_CLUSTER                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MD_FAULTY                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MD_LINEAR                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MD_MULTIPATH                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'y'}>
+CONFIG_MD_RAID0                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MD_RAID1                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MD_RAID10                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MD_RAID456                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MEDIATEK_MT6577_AUXADC                   policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MEDIATEK_WATCHDOG                        policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MEDIA_ALTERA_CI                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_ANALOG_TV_SUPPORT                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MEDIA_ATTACH                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MEDIA_CAMERA_SUPPORT                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MEDIA_CEC_SUPPORT                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MEDIA_COMMON_OPTIONS                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MEDIA_CONTROLLER                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MEDIA_CONTROLLER_DVB                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MEDIA_CONTROLLER_REQUEST_API             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_MEDIA_DIGITAL_TV_SUPPORT                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MEDIA_PCI_SUPPORT                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MEDIA_RADIO_SUPPORT                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MEDIA_SDR_SUPPORT                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MEDIA_SUBDRV_AUTOSELECT                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MEDIA_SUPPORT                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MEDIA_TUNER                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_E4000                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_FC0011                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_FC0012                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_FC0013                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_FC2580                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_IT913X                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_M88RS6000T                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_MAX2165                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_MC44S803                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_MSI001                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_MT2060                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_MT2063                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_MT20XX                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_MT2131                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_MT2266                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_MXL301RF                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_MXL5005S                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_MXL5007T                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_QM1D1B0004                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_QM1D1C0042                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_QT1010                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_R820T                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_SI2157                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_SIMPLE                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_TDA18212                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_TDA18218                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_TDA18250                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_TDA18271                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_TDA827X                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_TDA8290                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_TDA9887                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_TEA5761                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_TEA5767                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_TUA9001                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_XC2028                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_XC4000                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_TUNER_XC5000                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEDIA_USB_SUPPORT                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MEFFICEON                                policy<{'i386': 'n'}>
+CONFIG_MEGARAID_LEGACY                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MEGARAID_MAILBOX                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEGARAID_MM                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEGARAID_NEWGEN                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_MEGARAID_SAS                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MELAN                                    policy<{'i386': 'n'}>
+CONFIG_MELLANOX_PLATFORM                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_MEMBARRIER                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MEMCG                                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MEMCG_KMEM                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MEMCG_SWAP                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MEMCG_SWAP_ENABLED                       policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_MEMFD_CREATE                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MEMORY                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_MEMORY_BALLOON                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MEMORY_FAILURE                           policy<{'amd64': 'y', 'arm64': 'y', 'ppc64el': 'y'}>
+CONFIG_MEMORY_HOTPLUG                           policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MEMORY_HOTPLUG_SPARSE                    policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MEMORY_HOTREMOVE                         policy<{'amd64': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MEMORY_ISOLATION                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MEMORY_NOTIFIER_ERROR_INJECT             policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MEMSTICK                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MEMSTICK_DEBUG                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_MEMSTICK_JMICRON_38X                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEMSTICK_R592                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEMSTICK_REALTEK_PCI                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEMSTICK_REALTEK_USB                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEMSTICK_TIFM_MS                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEMSTICK_UNSAFE_RESUME                   policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_MEMTEST                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MEM_SOFT_DIRTY                           policy<{'amd64': 'y', 'ppc64el': 'n', 's390x': 'y'}>
+CONFIG_MENF21BMC_WATCHDOG                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MENZ069_WATCHDOG                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MEN_A21_WDT                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MEN_Z188_ADC                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MESON6_TIMER                             policy<{'armhf': 'y'}>
+CONFIG_MESON_CANVAS                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MESON_CLK_MEASURE                        policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_MESON_EE_PM_DOMAINS                      policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_MESON_EFUSE                              policy<{'arm64': 'm'}>
+CONFIG_MESON_GXBB_WATCHDOG                      policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MESON_GXL_PHY                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MESON_GX_PM_DOMAINS                      policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_MESON_GX_SOCINFO                         policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_MESON_IRQ_GPIO                           policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_MESON_MX_EFUSE                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MESON_MX_SOCINFO                         policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_MESON_SARADC                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MESON_SM                                 policy<{'arm64': 'y'}>
+CONFIG_MESON_WATCHDOG                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT                 policy<{'amd64': '4', 'arm64': '4', 'armhf': '4', 'i386': '4', 'ppc64el': '4', 's390x': '4'}>
+CONFIG_MFD_88PM800                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MFD_88PM805                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MFD_88PM860X                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_AAT2870_CORE                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_AC100                                policy<{'arm64': 'n'}>
+CONFIG_MFD_ACT8945A                             policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_MFD_AHC1EC0                              policy<{'amd64': 'm'}>
+CONFIG_MFD_ALTERA_SYSMGR                        policy<{'arm64': 'y'}>
+CONFIG_MFD_ARIZONA                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_ARIZONA_I2C                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MFD_ARIZONA_SPI                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MFD_AS3711                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_AS3722                               policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_ASIC3                                policy<{'armhf': 'y'}>
+CONFIG_MFD_ATMEL_FLEXCOM                        policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_MFD_ATMEL_HLCDC                          policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_MFD_AXP20X                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MFD_AXP20X_I2C                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MFD_AXP20X_RSB                           policy<{'arm64': 'm'}>
+CONFIG_MFD_BCM590XX                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MFD_BD9571MWV                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MFD_CORE                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'm'}>
+CONFIG_MFD_CPCAP                                policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_MFD_CROS_EC                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_MFD_CROS_EC_DEV                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_MFD_CS47L15                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_CS47L24                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_CS47L35                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_CS47L85                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_CS47L90                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_CS47L92                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_CS5535                               policy<{'i386': 'm'}>
+CONFIG_MFD_DA9052_I2C                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_DA9052_SPI                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_DA9055                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_DA9062                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MFD_DA9063                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_MFD_DA9150                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MFD_DLN2                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MFD_EXYNOS_LPASS                         policy<{'armhf': 'm'}>
+CONFIG_MFD_HI6421_PMIC                          policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_MFD_HI655X_PMIC                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MFD_INTEL_LPSS                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_MFD_INTEL_LPSS_ACPI                      policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_MFD_INTEL_LPSS_PCI                       policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_MFD_INTEL_MSIC                           policy<{'i386': 'y'}>
+CONFIG_MFD_INTEL_QUARK_I2C_GPIO                 policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_MFD_JANZ_CMODIO                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MFD_KEMPLD                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MFD_LM3533                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MFD_LOCHNAGAR                            policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_LP3943                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MFD_LP8788                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_MADERA                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MFD_MADERA_I2C                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MFD_MADERA_SPI                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MFD_MAX14577                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_MFD_MAX77620                             policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_MAX77650                             policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_MFD_MAX77686                             policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_MAX77693                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_MFD_MAX77843                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_MAX8907                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MFD_MAX8925                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_MAX8997                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_MAX8998                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_MC13XXX                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MFD_MC13XXX_I2C                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MFD_MC13XXX_SPI                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MFD_MENF21BMC                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MFD_MT6397                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MFD_NVEC                                 policy<{'armhf-generic': 'm'}>
+CONFIG_MFD_OMAP_USB_HOST                        policy<{'armhf': 'y'}>
+CONFIG_MFD_PALMAS                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_PCF50633                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MFD_PM8XXX                               policy<{'armhf': 'm'}>
+CONFIG_MFD_QCOM_RPM                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MFD_RC5T583                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_RDC321X                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MFD_RETU                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MFD_RK808                                policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_MFD_RN5T618                              policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_MFD_ROHM_BD70528                         policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_MFD_ROHM_BD718XX                         policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_MFD_RT5033                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MFD_SC27XX_PMIC                          policy<{'arm64': 'm'}>
+CONFIG_MFD_SEC_CORE                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_SI476X_CORE                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MFD_SKY81452                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MFD_SM501_GPIO                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_SMSC                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_SPMI_PMIC                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MFD_STMFX                                policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_MFD_STMPE                                policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_STPMIC1                              policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_MFD_SUN4I_GPADC                          policy<{'arm64': 'm'}>
+CONFIG_MFD_SUN6I_PRCM                           policy<{'arm64': 'y'}>
+CONFIG_MFD_SYSCON                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_MFD_T7L66XB                              policy<{'armhf': 'y'}>
+CONFIG_MFD_TC3589X                              policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_TC6387XB                             policy<{'armhf': 'y'}>
+CONFIG_MFD_TC6393XB                             policy<{'armhf': 'y'}>
+CONFIG_MFD_TIMBERDALE                           policy<{'i386': 'm'}>
+CONFIG_MFD_TI_AM335X_TSCADC                     policy<{'amd64': '-', 'arm64': 'm', 'armhf': 'm', 'i386': '-', 'ppc64el': '-', 's390x': '-'}>
+CONFIG_MFD_TI_LMU                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MFD_TI_LP873X                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MFD_TI_LP87565                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_MFD_TMIO                                 policy<{'armhf': 'y'}>
+CONFIG_MFD_TPS65086                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MFD_TPS65090                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_TPS65218                             policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_MFD_TPS6586X                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_TPS65910                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_TPS65912                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_TPS65912_I2C                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_MFD_TPS65912_SPI                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_TPS68470                             policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_MFD_TPS80031                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_TQMX86                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MFD_TWL4030_AUDIO                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_VEXPRESS_SYSREG                      policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_MFD_VIPERBOARD                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MFD_VX855                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MFD_WL1273_CORE                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MFD_WM5102                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_WM5110                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_WM831X                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_WM831X_I2C                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_WM831X_SPI                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_WM8350                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_WM8350_I2C                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_WM8400                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_WM8994                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MFD_WM8997                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MFD_WM8998                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MGEODEGX1                                policy<{'i386': 'n'}>
+CONFIG_MGEODE_LX                                policy<{'i386': 'n'}>
+CONFIG_MICREL_KS8995MA                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MICREL_PHY                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MICROCHIP_PHY                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MICROCHIP_T1_PHY                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MICROCODE                                policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_MICROCODE_AMD                            policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_MICROCODE_INTEL                          policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_MICROCODE_OLD_INTERFACE                  policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_MICROSEMI_PHY                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MIC_COSM                                 policy<{'amd64': 'm'}>
+CONFIG_MIGHT_HAVE_CACHE_L2X0                    policy<{'armhf': 'y'}>
+CONFIG_MIGRATION                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MII                                      policy<{'amd64': 'm', 'arm64': 'y', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MILBEAUT_TIMER                           policy<{'armhf': 'y'}>
+CONFIG_MINIX_FS                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MINIX_SUBPARTITION                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_MISC_ALCOR_PCI                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MISC_FILESYSTEMS                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MISC_RTSX                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MISC_RTSX_PCI                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MISC_RTSX_USB                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MISDN                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MISDN_AVMFRITZ                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MISDN_DSP                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MISDN_HDLC                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MISDN_HFCMULTI                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MISDN_HFCPCI                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MISDN_HFCUSB                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MISDN_INFINEON                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MISDN_IPAC                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MISDN_ISAR                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MISDN_L1OIP                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MISDN_NETJET                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MISDN_SPEEDFAX                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MISDN_W6692                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY          policy<{'arm64': 'y'}>
+CONFIG_MITIGATION_VMSCAPE                       policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_MIXCOMWD                                 policy<{'i386': 'm'}>
+CONFIG_MK6                                      policy<{'i386': 'n'}>
+CONFIG_MK7                                      policy<{'i386': 'n'}>
+CONFIG_MK8                                      policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_MKISS                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MLX4_CORE                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MLX4_CORE_GEN2                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MLX4_DEBUG                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MLX4_EN                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MLX4_EN_DCB                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MLX4_INFINIBAND                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MLX5_ACCEL                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MLX5_CORE                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MLX5_CORE_EN                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MLX5_CORE_EN_DCB                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MLX5_CORE_IPOIB                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MLX5_EN_ARFS                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MLX5_EN_IPSEC                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MLX5_EN_RXNFC                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MLX5_EN_TLS                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MLX5_ESWITCH                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MLX5_FPGA                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MLX5_FPGA_IPSEC                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MLX5_FPGA_TLS                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MLX5_INFINIBAND                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MLX5_MPFS                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MLX5_SW_STEERING                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MLX5_TLS                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MLX90614                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MLX90632                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MLXBF_TMFIFO                             policy<{'arm64': 'm'}>
+CONFIG_MLXFW                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MLXREG_HOTPLUG                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_MLXREG_IO                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_MLXSW_CORE                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MLXSW_CORE_HWMON                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MLXSW_CORE_THERMAL                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MLXSW_I2C                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_MLXSW_MINIMAL                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MLXSW_PCI                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MLXSW_SPECTRUM                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MLXSW_SPECTRUM_DCB                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MLXSW_SWITCHIB                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MLXSW_SWITCHX2                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MLX_PLATFORM                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_MLX_WDT                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_MMA7455                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MMA7455_I2C                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MMA7455_SPI                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MMA7660                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MMA8452                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MMA9551                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MMA9551_CORE                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MMA9553                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MMC                                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_MMC35240                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MMCONF_FAM10H                            policy<{'amd64': 'y'}>
+CONFIG_MMC_ALCOR                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MMC_ARMMMCI                              policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_MMC_BCM2835                              policy<{'arm64': 'm'}>
+CONFIG_MMC_BLOCK_MINORS                         policy<{'amd64': '8', 'arm64': '8', 'armhf': '8', 'i386': '8', 'ppc64el': '8'}>
+CONFIG_MMC_CAVIUM_THUNDERX                      policy<{'arm64': 'm'}>
+CONFIG_MMC_CB710                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MMC_CQHCI                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf-generic': 'y', 'armhf-generic-lpae': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MMC_DEBUG                                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_MMC_DW                                   policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MMC_DW_BLUEFIELD                         policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MMC_DW_EXYNOS                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MMC_DW_HI3798CV200                       policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MMC_DW_K3                                policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MMC_DW_PCI                               policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MMC_DW_PLTFM                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MMC_DW_ROCKCHIP                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MMC_MESON_GX                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MMC_MESON_MX_SDIO                        policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MMC_MTK                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MMC_MVSDIO                               policy<{'armhf': 'm'}>
+CONFIG_MMC_MXC                                  policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_MMC_OMAP                                 policy<{'armhf': 'm'}>
+CONFIG_MMC_QCOM_DML                             policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_MMC_REALTEK_PCI                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MMC_REALTEK_USB                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MMC_RICOH_MMC                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MMC_SDHCI_ACPI                           policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_MMC_SDHCI_AM654                          policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER  policy<{'ppc64el': 'y'}>
+CONFIG_MMC_SDHCI_BRCMSTB                        policy<{'arm64': 'm'}>
+CONFIG_MMC_SDHCI_CADENCE                        policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_MMC_SDHCI_DOVE                           policy<{'armhf': 'm'}>
+CONFIG_MMC_SDHCI_ESDHC_IMX                      policy<{'arm64': 'm', 'armhf-generic': 'y'}>
+CONFIG_MMC_SDHCI_F_SDH30                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MMC_SDHCI_IO_ACCESSORS                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MMC_SDHCI_IPROC                          policy<{'arm64': 'm'}>
+CONFIG_MMC_SDHCI_MSM                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MMC_SDHCI_OF_ARASAN                      policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MMC_SDHCI_OF_ASPEED                      policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_MMC_SDHCI_OF_AT91                        policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_MMC_SDHCI_OF_DWCMSHC                     policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MMC_SDHCI_OF_ESDHC                       policy<{'arm64': 'm', 'armhf-generic': 'm', 'ppc64el': 'm'}>
+CONFIG_MMC_SDHCI_OF_HLWD                        policy<{'ppc64el': 'm'}>
+CONFIG_MMC_SDHCI_OMAP                           policy<{'arm64': '-', 'armhf': 'm', 'ppc64el': '-'}>
+CONFIG_MMC_SDHCI_PCI                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MMC_SDHCI_PXAV3                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MMC_SDHCI_S3C                            policy<{'armhf': 'm'}>
+CONFIG_MMC_SDHCI_S3C_DMA                        policy<{'armhf': 'y'}>
+CONFIG_MMC_SDHCI_SPRD                           policy<{'arm64': 'm'}>
+CONFIG_MMC_SDHCI_TEGRA                          policy<{'armhf-generic': 'm'}>
+CONFIG_MMC_SDHCI_XENON                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MMC_SDHI                                 policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MMC_SDHI_INTERNAL_DMAC                   policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MMC_SDHI_SYS_DMAC                        policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MMC_SDRICOH_CS                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_MMC_SH_MMCIF                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MMC_SPI                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MMC_STM32_SDMMC                          policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_MMC_SUNXI                                policy<{'arm64': 'm'}>
+CONFIG_MMC_TEST                                 policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_MMC_TIFM_SD                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MMC_TMIO                                 policy<{'armhf': 'm'}>
+CONFIG_MMC_TMIO_CORE                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MMC_TOSHIBA_PCI                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MMC_UNIPHIER                             policy<{'armhf': 'm'}>
+CONFIG_MMC_USDHI6ROL0                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MMC_USHC                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MMC_VIA_SDMMC                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MMC_VUB300                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MMC_WBSD                                 policy<{'amd64': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MMIOTRACE                                policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_MMIOTRACE_TEST                           policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_MMIOWB                                   policy<{'ppc64el': 'y'}>
+CONFIG_MMU                                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MMU_NOTIFIER                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MODULES                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MODULES_TREE_LOOKUP                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MODULES_USE_ELF_REL                      policy<{'armhf': 'y', 'i386': 'y'}>
+CONFIG_MODULES_USE_ELF_RELA                     policy<{'amd64': 'y', 'arm64': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS   policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_MODULE_COMPRESS                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_MODULE_FORCE_LOAD                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_MODULE_FORCE_UNLOAD                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_MODULE_REL_CRCS                          policy<{'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MODULE_SIG                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MODULE_SIG_ALL                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MODULE_SIG_FORCE                         policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_MODULE_SIG_FORMAT                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MODULE_SIG_HASH                          policy<{'amd64': '"sha512"', 'arm64': '"sha512"', 'armhf': '"sha512"', 'i386': '"sha512"', 'ppc64el': '"sha512"', 's390x': '"sha512"'}>
+CONFIG_MODULE_SIG_KEY                           policy<{'amd64': '"certs/signing_key.pem"', 'arm64': '"certs/signing_key.pem"', 'armhf': '"certs/signing_key.pem"', 'i386': '"certs/signing_key.pem"', 'ppc64el': '"certs/signing_key.pem"', 's390x': '"certs/signing_key.pem"'}>
+CONFIG_MODULE_SIG_SHA1                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_MODULE_SIG_SHA224                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_MODULE_SIG_SHA256                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_MODULE_SIG_SHA384                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_MODULE_SIG_SHA512                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MODULE_SRCVERSION_ALL                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MODULE_UNLOAD                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MONREADER                                policy<{'s390x': 'm'}>
+CONFIG_MONWRITER                                policy<{'s390x': 'm'}>
+CONFIG_MOST                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MOST_CDEV                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MOST_DIM2                                policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_MOST_I2C                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MOST_NET                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MOST_SOUND                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MOST_USB                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MOST_VIDEO                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MOUSE_APPLETOUCH                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MOUSE_BCM5974                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MOUSE_CYAPA                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MOUSE_ELAN_I2C                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MOUSE_ELAN_I2C_I2C                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MOUSE_ELAN_I2C_SMBUS                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MOUSE_GPIO                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MOUSE_LOGIBM                             policy<{'i386': 'm'}>
+CONFIG_MOUSE_PC110PAD                           policy<{'i386': 'm'}>
+CONFIG_MOUSE_PS2                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MOUSE_PS2_ALPS                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MOUSE_PS2_BYD                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MOUSE_PS2_CYPRESS                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MOUSE_PS2_ELANTECH                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MOUSE_PS2_ELANTECH_SMBUS                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MOUSE_PS2_FOCALTECH                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MOUSE_PS2_LIFEBOOK                       policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_MOUSE_PS2_LOGIPS2PP                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MOUSE_PS2_SENTELIC                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MOUSE_PS2_SMBUS                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MOUSE_PS2_SYNAPTICS                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MOUSE_PS2_SYNAPTICS_SMBUS                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MOUSE_PS2_TOUCHKIT                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MOUSE_PS2_TRACKPOINT                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MOUSE_PS2_VMMOUSE                        policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_MOUSE_SERIAL                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MOUSE_SYNAPTICS_I2C                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MOUSE_SYNAPTICS_USB                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MOUSE_VSXXXAA                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MOXA_INTELLIO                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MOXA_SMARTIO                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MOXTET                                   policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_MPENTIUM4                                policy<{'i386': 'n'}>
+CONFIG_MPENTIUMII                               policy<{'i386': 'n'}>
+CONFIG_MPENTIUMIII                              policy<{'i386': 'n'}>
+CONFIG_MPENTIUMM                                policy<{'i386': 'n'}>
+CONFIG_MPIC                                     policy<{'ppc64el': 'y'}>
+CONFIG_MPIC_MSGR                                policy<{'ppc64el': 'n'}>
+CONFIG_MPILIB                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MPL115                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MPL115_I2C                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MPL115_SPI                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MPL3115                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MPLS                                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MPLS_IPTUNNEL                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MPLS_ROUTING                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MPROFILE_KERNEL                          policy<{'ppc64el': 'y'}>
+CONFIG_MPSC                                     policy<{'amd64': 'n'}>
+CONFIG_MPU3050                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MPU3050_I2C                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MQ_IOSCHED_DEADLINE                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MQ_IOSCHED_KYBER                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MRP                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MS5611                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MS5611_I2C                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MS5611_SPI                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MS5637                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MSCC_OCELOT_SWITCH                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MSCC_OCELOT_SWITCH_OCELOT                policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_MSDOS_FS                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_MSDOS_PARTITION                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MSI_BITMAP_SELFTEST                      policy<{'ppc64el': 'n'}>
+CONFIG_MSI_LAPTOP                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_MSI_WMI                                  policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_MSM_GCC_8660                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MSM_GCC_8916                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MSM_GCC_8960                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MSM_GCC_8974                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MSM_GCC_8994                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MSM_GCC_8996                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MSM_GCC_8998                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MSM_IOMMU                                policy<{'armhf': 'n'}>
+CONFIG_MSM_LCC_8960                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MSM_MMCC_8960                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MSM_MMCC_8974                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MSM_MMCC_8996                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MSPRO_BLOCK                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MS_BLOCK                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MT7601U                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MT7603E                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MT7615E                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MT76_CORE                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MT76_LEDS                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MT76_USB                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MT76x02_LIB                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MT76x02_USB                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MT76x0E                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MT76x0U                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MT76x0_COMMON                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MT76x2E                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MT76x2U                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MT76x2_COMMON                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTDRAM_ERASE_SIZE                        policy<{'amd64': '128', 'arm64': '128', 'armhf': '128', 'i386': '128', 'ppc64el': '128'}>
+CONFIG_MTDRAM_TOTAL_SIZE                        policy<{'amd64': '4096', 'arm64': '4096', 'armhf': '4096', 'i386': '4096', 'ppc64el': '4096'}>
+CONFIG_MTD_ABSENT                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_AFS_PARTS                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MTD_AMD76XROM                            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_MTD_AR7_PARTS                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_BCM47XXSFLASH                        policy<{'armhf': 'm'}>
+CONFIG_MTD_BLKDEVS                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'y', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_BLOCK2MTD                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_BLOCK_RO                             policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_CFI                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_CFI_ADV_OPTIONS                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_MTD_CFI_AMDSTD                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_CFI_I1                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MTD_CFI_I2                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MTD_CFI_INTELEXT                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_CFI_STAA                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_CFI_UTIL                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_CK804XROM                            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_MTD_CMDLINE_PARTS                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'y', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_COMPLEX_MAPPINGS                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MTD_DATAFLASH                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_DATAFLASH_OTP                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MTD_DATAFLASH_WRITE_VERIFY               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_MTD_ESB2ROM                              policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_MTD_GEN_PROBE                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_HYPERBUS                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_ICHXROM                              policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_MTD_IMPA7                                policy<{'armhf': 'm'}>
+CONFIG_MTD_INTEL_VR_NOR                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_JEDECPROBE                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_L440GX                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_MTD_LPDDR                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_LPDDR2_NVM                           policy<{'armhf': 'm'}>
+CONFIG_MTD_MAP_BANK_WIDTH_1                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MTD_MAP_BANK_WIDTH_2                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MTD_MAP_BANK_WIDTH_4                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MTD_MCHP23K256                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_MTDRAM                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_NAND_BRCMNAND                        policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MTD_NAND_CAFE                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_NAND_CORE                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'y', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_NAND_CS553X                          policy<{'i386': 'm'}>
+CONFIG_MTD_NAND_DENALI                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_NAND_DENALI_DT                       policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MTD_NAND_DENALI_PCI                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_NAND_DISKONCHIP                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS        policy<{'amd64': '0', 'arm64': '0', 'armhf': '0', 'i386': '0', 'ppc64el': '0'}>
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED       policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_MTD_NAND_ECC_SW_BCH                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MTD_NAND_ECC_SW_HAMMING                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'y', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_MTD_NAND_FSL_IFC                         policy<{'arm64': 'm'}>
+CONFIG_MTD_NAND_GPIO                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_NAND_GPMI_NAND                       policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_MTD_NAND_HISI504                         policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MTD_NAND_MARVELL                         policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MTD_NAND_MESON                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MTD_NAND_MTK                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MTD_NAND_MXC                             policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_MTD_NAND_MXIC                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_NAND_NANDSIM                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_NAND_OMAP_BCH_BUILD                  policy<{'armhf': 'y'}>
+CONFIG_MTD_NAND_ORION                           policy<{'armhf': 'm'}>
+CONFIG_MTD_NAND_PLATFORM                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_NAND_QCOM                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MTD_NAND_RICOH                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_NAND_SUNXI                           policy<{'arm64': 'n'}>
+CONFIG_MTD_NAND_TEGRA                           policy<{'armhf-generic': 'm'}>
+CONFIG_MTD_NAND_TMIO                            policy<{'armhf': 'm'}>
+CONFIG_MTD_NAND_VF610_NFC                       policy<{'armhf-generic': 'n'}>
+CONFIG_MTD_NETtel                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_MTD_ONENAND                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_ONENAND_2X_PROGRAM                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MTD_ONENAND_GENERIC                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_ONENAND_OMAP2                        policy<{'armhf-generic': 'm'}>
+CONFIG_MTD_ONENAND_OTP                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_MTD_OOPS                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_PARTITIONED_MASTER                   policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_MTD_PCI                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_PCMCIA                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_MTD_PCMCIA_ANONYMOUS                     policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_MTD_PHRAM                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_PHYSMAP                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_PHYSMAP_COMPAT                       policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_MTD_PHYSMAP_GEMINI                       policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'n'}>
+CONFIG_MTD_PHYSMAP_GPIO_ADDR                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MTD_PHYSMAP_OF                           policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_MTD_PHYSMAP_VERSATILE                    policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'n'}>
+CONFIG_MTD_PLATRAM                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_PMC551                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_PMC551_BUGFIX                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_MTD_PMC551_DEBUG                         policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_MTD_POWERNV_FLASH                        policy<{'ppc64el': 'm'}>
+CONFIG_MTD_QINFO_PROBE                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_RAM                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK              policy<{'amd64': '-1', 'arm64': '-1', 'armhf': '-1', 'i386': '-1', 'ppc64el': '-1'}>
+CONFIG_MTD_REDBOOT_PARTS                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_REDBOOT_PARTS_READONLY               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_MTD_ROM                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_SBC_GXX                              policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_MTD_SCB2_FLASH                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_MTD_SCx200_DOCFLASH                      policy<{'i386': 'm'}>
+CONFIG_MTD_SHARPSL_PARTS                        policy<{'armhf': 'm'}>
+CONFIG_MTD_SLRAM                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_SM_COMMON                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_SPI_NAND                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_SPI_NOR                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_SPI_NOR_USE_4K_SECTORS               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MTD_SST25L                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_SWAP                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_TESTS                                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_MTD_UBI                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_UBI_BEB_LIMIT                        policy<{'amd64': '20', 'arm64': '20', 'armhf': '20', 'i386': '20', 'ppc64el': '20'}>
+CONFIG_MTD_UBI_BLOCK                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MTD_UBI_FASTMAP                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MTD_UBI_GLUEBI                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MTD_UBI_WL_THRESHOLD                     policy<{'amd64': '4096', 'arm64': '4096', 'armhf': '4096', 'i386': '4096', 'ppc64el': '4096'}>
+CONFIG_MTK_CMDQ                                 policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MTK_CMDQ_MBOX                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MTK_CQDMA                                policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MTK_EFUSE                                policy<{'arm64': 'n', 'armhf': 'n'}>
+CONFIG_MTK_HSDMA                                policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MTK_INFRACFG                             policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_MTK_IOMMU                                policy<{'arm64': 'n', 'armhf': 'n'}>
+CONFIG_MTK_IOMMU_V1                             policy<{'armhf': 'n'}>
+CONFIG_MTK_PMIC_WRAP                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MTK_SCPSYS                               policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_MTK_SMI                                  policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_MTK_THERMAL                              policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MTK_TIMER                                policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_MTK_UART_APDMA                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MTRR                                     policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_MTRR_SANITIZER                           policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT            policy<{'amd64': '1', 'i386': '1'}>
+CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT      policy<{'amd64': '1', 'i386': '1'}>
+CONFIG_MULTIPLEXER                              policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_MULTIUSER                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MUSB_PIO_ONLY                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_MUTEX_SPIN_ON_OWNER                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_MUX_ADG792A                              policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_MUX_ADGS1408                             policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_MUX_GPIO                                 policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_MUX_MMIO                                 policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_MV643XX_ETH                              policy<{'armhf': 'm'}>
+CONFIG_MVEBU_CLK_COMMON                         policy<{'armhf': 'y'}>
+CONFIG_MVEBU_CLK_COREDIV                        policy<{'armhf': 'y'}>
+CONFIG_MVEBU_CLK_CPU                            policy<{'armhf': 'y'}>
+CONFIG_MVEBU_DEVBUS                             policy<{'armhf': 'y'}>
+CONFIG_MVEBU_GICP                               policy<{'arm64': 'y'}>
+CONFIG_MVEBU_ICU                                policy<{'arm64': 'y'}>
+CONFIG_MVEBU_MBUS                               policy<{'armhf': 'y'}>
+CONFIG_MVEBU_ODMI                               policy<{'arm64': 'y'}>
+CONFIG_MVEBU_PIC                                policy<{'arm64': 'y'}>
+CONFIG_MVEBU_SEI                                policy<{'arm64': 'y'}>
+CONFIG_MVIAC3_2                                 policy<{'i386': 'n'}>
+CONFIG_MVIAC7                                   policy<{'i386': 'n'}>
+CONFIG_MVMDIO                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MVNETA                                   policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MVNETA_BM_ENABLE                         policy<{'armhf': 'n'}>
+CONFIG_MVPP2                                    policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_MV_XOR                                   policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_MV_XOR_V2                                policy<{'arm64': 'y'}>
+CONFIG_MWAVE                                    policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_MWIFIEX                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MWIFIEX_PCIE                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MWIFIEX_SDIO                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MWIFIEX_USB                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MWINCHIP3D                               policy<{'i386': 'n'}>
+CONFIG_MWINCHIPC6                               policy<{'i386': 'n'}>
+CONFIG_MWL8K                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MX3_IPU                                  policy<{'arm64': 'y', 'armhf-generic': 'y'}>
+CONFIG_MX3_IPU_IRQS                             policy<{'arm64': '4', 'armhf-generic': '4'}>
+CONFIG_MXC4005                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MXC6255                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MXC_CLK                                  policy<{'arm64': 'y', 'armhf-generic': 'y'}>
+CONFIG_MXC_CLK_SCU                              policy<{'arm64': 'y'}>
+CONFIG_MXC_TZIC                                 policy<{'armhf-generic': 'y'}>
+CONFIG_MXM_WMI                                  policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_MXS_DMA                                  policy<{'arm64': 'y', 'armhf-generic': 'y'}>
+CONFIG_MYRI10GE                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_MYRI10GE_DCA                             policy<{'amd64': 'y'}>
+CONFIG_N2                                       policy<{'i386': 'm'}>
+CONFIG_NAMESPACES                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NATIONAL_PHY                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NATSEMI                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NAU7802                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NBPFAXI_DMA                              policy<{'armhf': 'm'}>
+CONFIG_NCSI_OEM_CMD_GET_MAC                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ND_BLK                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf-generic-lpae': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ND_BTT                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf-generic-lpae': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ND_CLAIM                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf-generic-lpae': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ND_PFN                                   policy<{'amd64': 'm', 'ppc64el': 'm'}>
+CONFIG_NE2000                                   policy<{'i386': 'm'}>
+CONFIG_NE2K_PCI                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NEED_DMA_MAP_STATE                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NEED_MULTIPLE_NODES                      policy<{'amd64': 'y', 'arm64': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK           policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK            policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_NEED_SG_DMA_LENGTH                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NEON                                     policy<{'armhf': 'y'}>
+CONFIG_NET                                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET5501                                  policy<{'i386': 'y'}>
+CONFIG_NETCONSOLE                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETCONSOLE_DYNAMIC                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NETDEVICES                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NETDEVSIM                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETDEV_NOTIFIER_ERROR_INJECT             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_NETFILTER                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NETFILTER_ADVANCED                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NETFILTER_CONNCOUNT                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_FAMILY_ARP                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NETFILTER_FAMILY_BRIDGE                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NETFILTER_INGRESS                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NETFILTER_NETLINK                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_NETLINK_ACCT                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_NETLINK_GLUE_CT                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NETFILTER_NETLINK_LOG                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_NETLINK_OSF                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_NETLINK_QUEUE                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_SYNPROXY                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XTABLES                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_CONNMARK                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MARK                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_BPF                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_CGROUP                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_CLUSTER               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_COMMENT               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_CONNLABEL             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_CONNMARK              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_CPU                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_DCCP                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_DEVGROUP              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_DSCP                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_ECN                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_ESP                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_HELPER                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_HL                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_IPCOMP                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_IPRANGE               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_IPVS                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_L2TP                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_LENGTH                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_LIMIT                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_MAC                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_MARK                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_NFACCT                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_OSF                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_OWNER                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_POLICY                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_QUOTA                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_RATEEST               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_REALM                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_RECENT                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_SCTP                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_SOCKET                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_STATE                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_STATISTIC             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_STRING                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_TCPMSS                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_TIME                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_MATCH_U32                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_NAT                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_SET                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_TARGET_AUDIT                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_TARGET_CONNMARK             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_TARGET_CT                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_TARGET_DSCP                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_TARGET_HL                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_TARGET_HMARK                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_TARGET_LED                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NETFILTER_XT_TARGET_LOG                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_TARGET_MARK                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_TARGET_MASQUERADE           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_TARGET_NETMAP               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_TARGET_NFLOG                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_TARGET_NOTRACK              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_NETFILTER_XT_TARGET_RATEEST              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_TARGET_REDIRECT             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_TARGET_SECMARK              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_TARGET_TCPMSS               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_TARGET_TEE                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_TARGET_TPROXY               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETFILTER_XT_TARGET_TRACE                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETIUCV                                  policy<{'s390x': 'm'}>
+CONFIG_NETLABEL                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NETLINK_DIAG                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NETPOLL                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NETROM                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NETWORK_FILESYSTEMS                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NETWORK_SECMARK                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NETXEN_NIC                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_9P_DEBUG                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_NET_9P_RDMA                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_9P_VIRTIO                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_9P_XEN                               policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_NET_ACT_BPF                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_ACT_CONNMARK                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_ACT_CSUM                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_ACT_CT                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_ACT_CTINFO                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_ACT_GACT                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_ACT_IFE                              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_NET_ACT_IPT                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_ACT_MIRRED                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_ACT_MPLS                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_ACT_NAT                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_ACT_PEDIT                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_ACT_POLICE                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_ACT_SAMPLE                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_ACT_SIMP                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_ACT_SKBEDIT                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_ACT_SKBMOD                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_ACT_TUNNEL_KEY                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_ACT_VLAN                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_CALXEDA_XGMAC                        policy<{'armhf': 'm'}>
+CONFIG_NET_CLS                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_CLS_ACT                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_CLS_BASIC                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_CLS_BPF                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_CLS_CGROUP                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_CLS_FLOW                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_CLS_FLOWER                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_CLS_FW                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_CLS_MATCHALL                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_CLS_ROUTE4                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_CLS_U32                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_CORE                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_DEVLINK                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_DSA                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_DSA_BCM_SF2                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_DSA_LANTIQ_GSWIP                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_DSA_LOOP                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_NET_DSA_MICROCHIP_KSZ8795                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_DSA_MICROCHIP_KSZ8795_SPI            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_DSA_MICROCHIP_KSZ9477                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_DSA_MICROCHIP_KSZ9477_I2C            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_DSA_MICROCHIP_KSZ9477_SPI            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_DSA_MICROCHIP_KSZ_COMMON             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_DSA_MT7530                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_DSA_MV88E6060                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_DSA_MV88E6XXX                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_DSA_MV88E6XXX_GLOBAL2                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_NET_DSA_MV88E6XXX_PTP                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_NET_DSA_QCA8K                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_DSA_REALTEK_SMI                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_DSA_SJA1105                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_DSA_SJA1105_PTP                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_NET_DSA_SJA1105_TAS                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_NET_DSA_SMSC_LAN9303                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_DSA_SMSC_LAN9303_I2C                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_DSA_SMSC_LAN9303_MDIO                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_DSA_TAG_8021Q                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_DSA_TAG_BRCM                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_DSA_TAG_BRCM_COMMON                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_DSA_TAG_BRCM_PREPEND                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_DSA_TAG_DSA                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_DSA_TAG_EDSA                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_DSA_TAG_GSWIP                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_DSA_TAG_KSZ                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_DSA_TAG_LAN9303                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_DSA_TAG_MTK                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_DSA_TAG_QCA                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_DSA_TAG_SJA1105                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_DSA_TAG_TRAILER                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_DSA_VITESSE_VSC73XX                  policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_DSA_VITESSE_VSC73XX_PLATFORM         policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_DSA_VITESSE_VSC73XX_SPI              policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_EGRESS                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_EMATCH                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_EMATCH_CANID                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NET_EMATCH_CMP                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_EMATCH_IPSET                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_EMATCH_IPT                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_EMATCH_META                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_EMATCH_NBYTE                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_EMATCH_STACK                         policy<{'amd64': '32', 'arm64': '32', 'armhf': '32', 'i386': '32', 'ppc64el': '32', 's390x': '32'}>
+CONFIG_NET_EMATCH_TEXT                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_EMATCH_U32                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_FAILOVER                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_FC                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_FLOW_LIMIT                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_FOU                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_FOU_IP_TUNNELS                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_IFE                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_INGRESS                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_IPGRE                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_IPGRE_BROADCAST                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_IPGRE_DEMUX                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_IPIP                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_IPVTI                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_IP_TUNNEL                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_KEY                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_KEY_MIGRATE                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_NET_L3_MASTER_DEV                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_MPLS_GSO                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_NCSI                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_NS                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_NSH                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_PKTGEN                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_POLL_CONTROLLER                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_PTP_CLASSIFY                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_REDIRECT                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_RX_BUSY_POLL                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_SB1000                               policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_NET_SCHED                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_SCH_CAKE                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_SCH_CBS                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_SCH_CHOKE                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_SCH_CODEL                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_SCH_DEFAULT                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_NET_SCH_DRR                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_SCH_ETF                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_SCH_FIFO                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_SCH_FQ                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_SCH_FQ_CODEL                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_SCH_GRED                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_SCH_HFSC                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_SCH_HHF                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_SCH_HTB                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_SCH_INGRESS                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_SCH_MQPRIO                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_SCH_MULTIQ                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_SCH_NETEM                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_SCH_PIE                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_SCH_PLUG                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_SCH_PRIO                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_SCH_QFQ                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_SCH_RED                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_SCH_SFB                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_SCH_SFQ                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_SCH_SKBPRIO                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_SCH_TAPRIO                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_SCH_TBF                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_SCH_TEQL                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_SOCK_MSG                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_TC_SKB_EXT                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_TEAM                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_TEAM_MODE_ACTIVEBACKUP               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_TEAM_MODE_BROADCAST                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_TEAM_MODE_LOADBALANCE                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_TEAM_MODE_RANDOM                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_TEAM_MODE_ROUNDROBIN                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_TULIP                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_NET_UDP_TUNNEL                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_VENDOR_3COM                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_8390                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_NET_VENDOR_ADAPTEC                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_AGERE                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_ALACRITECH                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_VENDOR_ALLWINNER                     policy<{'arm64': 'y'}>
+CONFIG_NET_VENDOR_ALTEON                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_AMAZON                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_VENDOR_AMD                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_AQUANTIA                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_VENDOR_ARC                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_ATHEROS                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_AURORA                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_VENDOR_BROADCOM                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_BROCADE                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_CADENCE                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_VENDOR_CAVIUM                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_CHELSIO                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_CIRRUS                        policy<{'amd64': '-', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_NET_VENDOR_CISCO                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_CORTINA                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_VENDOR_DEC                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_DLINK                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_EZCHIP                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_FARADAY                       policy<{'armhf': 'y'}>
+CONFIG_NET_VENDOR_FREESCALE                     policy<{'arm64': 'y', 'armhf-generic': 'y'}>
+CONFIG_NET_VENDOR_FUJITSU                       policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_NET_VENDOR_GOOGLE                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_HISILICON                     policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_NET_VENDOR_HP                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_HUAWEI                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_I825XX                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_NET_VENDOR_IBM                           policy<{'ppc64el': 'y'}>
+CONFIG_NET_VENDOR_INTEL                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_MARVELL                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_MEDIATEK                      policy<{'arm64': 'n', 'armhf': 'n'}>
+CONFIG_NET_VENDOR_MELLANOX                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_VENDOR_MICREL                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_MICROCHIP                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_MICROSEMI                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_MYRI                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_NATSEMI                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_NETERION                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_VENDOR_NETRONOME                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_VENDOR_NI                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_NVIDIA                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_OKI                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_PACKET_ENGINES                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_VENDOR_PENSANDO                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_QLOGIC                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_QUALCOMM                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_RDC                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_REALTEK                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_RENESAS                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_ROCKER                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_SAMSUNG                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_SEEQ                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_SILAN                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_SIS                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_SMSC                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_SOCIONEXT                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_VENDOR_SOLARFLARE                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_VENDOR_STMICRO                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_SUN                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_SYNOPSYS                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NET_VENDOR_TEHUTI                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_TI                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_VIA                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_WIZNET                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NET_VENDOR_XILINX                        policy<{'amd64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_NET_VENDOR_XIRCOM                        policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_NET_VRF                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NET_XGENE                                policy<{'arm64': 'm'}>
+CONFIG_NET_XGENE_V2                             policy<{'arm64': 'm'}>
+CONFIG_NEW_LEDS                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_NFC                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_NFC_DIGITAL                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NFC_FDP                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NFC_FDP_I2C                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NFC_HCI                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NFC_MEI_PHY                              policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_NFC_MICROREAD                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NFC_MICROREAD_I2C                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NFC_MICROREAD_MEI                        policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_NFC_MRVL                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NFC_MRVL_I2C                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NFC_MRVL_SPI                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NFC_MRVL_UART                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NFC_MRVL_USB                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NFC_NCI                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NFC_NCI_SPI                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NFC_NCI_UART                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NFC_NXP_NCI                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NFC_NXP_NCI_I2C                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NFC_PN533                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NFC_PN533_I2C                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NFC_PN533_USB                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NFC_PN544                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NFC_PN544_I2C                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NFC_PN544_MEI                            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_NFC_PORT100                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NFC_S3FWRN5                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NFC_S3FWRN5_I2C                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NFC_SHDLC                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_NFC_SIM                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NFC_ST21NFCA                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NFC_ST21NFCA_I2C                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NFC_ST95HF                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NFC_ST_NCI                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NFC_ST_NCI_I2C                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NFC_ST_NCI_SPI                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NFC_TRF7970A                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NFIT_SECURITY_DEBUG                      policy<{'amd64': 'n', 'arm64': 'n'}>
+CONFIG_NFP                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_NFP_APP_ABM_NIC                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_NFP_APP_FLOWER                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_NFP_DEBUG                                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_NFSD                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFSD_BLOCKLAYOUT                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NFSD_FLEXFILELAYOUT                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NFSD_PNFS                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NFSD_SCSILAYOUT                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NFSD_V2_ACL                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NFSD_V3                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NFSD_V3_ACL                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NFSD_V4                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NFSD_V4_SECURITY_LABEL                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NFS_ACL_SUPPORT                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFS_COMMON                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NFS_DEBUG                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NFS_FS                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFS_FSCACHE                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NFS_SWAP                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NFS_USE_KERNEL_DNS                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NFS_USE_LEGACY_DNS                       policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_NFS_V2                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFS_V3                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFS_V3_ACL                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NFS_V4                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFS_V4_1                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN        policy<{'amd64': '"kernel.org"', 'arm64': '"kernel.org"', 'armhf': '"kernel.org"', 'i386': '"kernel.org"', 'ppc64el': '"kernel.org"', 's390x': '"kernel.org"'}>
+CONFIG_NFS_V4_1_MIGRATION                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NFS_V4_2                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NFS_V4_SECURITY_LABEL                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NFTL                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NFTL_RW                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_NFT_BRIDGE_META                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFT_BRIDGE_REJECT                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFT_COMPAT                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFT_CONNLIMIT                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFT_COUNTER                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFT_CT                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFT_DUP_IPV4                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFT_DUP_IPV6                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFT_DUP_NETDEV                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFT_FIB                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFT_FIB_INET                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFT_FIB_IPV4                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFT_FIB_IPV6                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFT_FIB_NETDEV                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFT_FLOW_OFFLOAD                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFT_FWD_NETDEV                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFT_HASH                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFT_LIMIT                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFT_LOG                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFT_MASQ                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFT_NAT                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFT_NUMGEN                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFT_OBJREF                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFT_OSF                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFT_QUEUE                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFT_QUOTA                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFT_REDIR                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFT_REJECT                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFT_REJECT_INET                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFT_REJECT_IPV4                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFT_REJECT_IPV6                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFT_SOCKET                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFT_SYNPROXY                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFT_TPROXY                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFT_TUNNEL                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NFT_XFRM                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_CONNTRACK                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_CONNTRACK_AMANDA                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_CONNTRACK_BRIDGE                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_CONNTRACK_BROADCAST                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_CONNTRACK_EVENTS                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NF_CONNTRACK_FTP                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_CONNTRACK_H323                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_CONNTRACK_IRC                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_CONNTRACK_LABELS                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NF_CONNTRACK_MARK                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NF_CONNTRACK_NETBIOS_NS                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_CONNTRACK_PPTP                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_CONNTRACK_PROCFS                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_NF_CONNTRACK_SANE                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_CONNTRACK_SECMARK                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NF_CONNTRACK_SIP                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_CONNTRACK_SNMP                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_CONNTRACK_TFTP                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_CONNTRACK_TIMEOUT                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NF_CONNTRACK_TIMESTAMP                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NF_CONNTRACK_ZONES                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NF_CT_NETLINK                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_CT_NETLINK_HELPER                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_CT_NETLINK_TIMEOUT                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_CT_PROTO_DCCP                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NF_CT_PROTO_GRE                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NF_CT_PROTO_SCTP                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NF_CT_PROTO_UDPLITE                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NF_DEFRAG_IPV4                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_DEFRAG_IPV6                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_DUP_IPV4                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_DUP_IPV6                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_DUP_NETDEV                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_FLOW_TABLE                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_FLOW_TABLE_INET                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_FLOW_TABLE_IPV4                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_FLOW_TABLE_IPV6                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_LOG_ARP                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_LOG_BRIDGE                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_LOG_COMMON                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_LOG_IPV4                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_LOG_IPV6                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_LOG_NETDEV                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_NAT                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_NAT_AMANDA                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_NAT_FTP                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_NAT_H323                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_NAT_IRC                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_NAT_MASQUERADE                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NF_NAT_PPTP                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_NAT_REDIRECT                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NF_NAT_SIP                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_NAT_SNMP_BASIC                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_NAT_TFTP                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_REJECT_IPV4                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_REJECT_IPV6                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_SOCKET_IPV4                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_SOCKET_IPV6                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_TABLES                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_TABLES_ARP                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NF_TABLES_BRIDGE                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_TABLES_INET                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NF_TABLES_IPV4                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NF_TABLES_IPV6                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NF_TABLES_NETDEV                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NF_TABLES_SET                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_TPROXY_IPV4                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NF_TPROXY_IPV6                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NI65                                     policy<{'i386': 'm'}>
+CONFIG_NI903X_WDT                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_NIC7018_WDT                              policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_NILFS2_FS                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NIU                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NI_XGE_MANAGEMENT_ENET                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NL80211_TESTMODE                         policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_NLATTR                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NLMON                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_ASCII                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_CODEPAGE_1250                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_CODEPAGE_1251                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_CODEPAGE_437                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NLS_CODEPAGE_737                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_CODEPAGE_775                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_CODEPAGE_850                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_CODEPAGE_852                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_CODEPAGE_855                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_CODEPAGE_857                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_CODEPAGE_860                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_CODEPAGE_861                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_CODEPAGE_862                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_CODEPAGE_863                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_CODEPAGE_864                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_CODEPAGE_865                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_CODEPAGE_866                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_CODEPAGE_869                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_CODEPAGE_874                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_CODEPAGE_932                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_CODEPAGE_936                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_CODEPAGE_949                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_CODEPAGE_950                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_DEFAULT                              policy<{'amd64': '"utf8"', 'arm64': '"utf8"', 'armhf': '"utf8"', 'i386': '"utf8"', 'ppc64el': '"utf8"', 's390x': '"utf8"'}>
+CONFIG_NLS_ISO8859_1                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_ISO8859_13                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_ISO8859_14                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_ISO8859_15                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_ISO8859_2                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_ISO8859_3                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_ISO8859_4                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_ISO8859_5                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_ISO8859_6                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_ISO8859_7                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_ISO8859_8                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_ISO8859_9                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_KOI8_R                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_KOI8_U                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_MAC_CELTIC                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_MAC_CENTEURO                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_MAC_CROATIAN                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_MAC_CYRILLIC                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_MAC_GAELIC                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_MAC_GREEK                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_MAC_ICELAND                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_MAC_INUIT                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_MAC_ROMAN                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_MAC_ROMANIAN                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_MAC_TURKISH                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NLS_UTF8                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NMI_IPI                                  policy<{'ppc64el': 'y'}>
+CONFIG_NOA1305                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NODES_SHIFT                              policy<{'amd64': '10', 'arm64': '6', 'ppc64el': '8', 's390x': '4'}>
+CONFIG_NODES_SPAN_OTHER_NODES                   policy<{'amd64': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NOHIGHMEM                                policy<{'i386': 'n'}>
+CONFIG_NOKIA_MODEM                              policy<{'armhf-generic': 'm'}>
+CONFIG_NONSTATIC_KERNEL                         policy<{'ppc64el': 'y'}>
+CONFIG_NOP_TRACER                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NORTEL_HERMES                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NOTIFIER_ERROR_INJECTION                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NOUVEAU_DEBUG                            policy<{'amd64': '5', 'arm64': '5', 'armhf': '5', 'i386': '5', 'ppc64el': '5'}>
+CONFIG_NOUVEAU_DEBUG_DEFAULT                    policy<{'amd64': '3', 'arm64': '3', 'armhf': '3', 'i386': '3', 'ppc64el': '3'}>
+CONFIG_NOUVEAU_DEBUG_MMU                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_NOUVEAU_PLATFORM_DRIVER                  policy<{'armhf-generic': 'y'}>
+CONFIG_NOZOMI                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_NO_HZ                                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NO_HZ_COMMON                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NO_HZ_FULL                               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'ppc64el': 'n'}>
+CONFIG_NO_IOPORT_MAP                            policy<{'armhf': 'y', 's390x': 'y'}>
+CONFIG_NPCM7XX_KCS_IPMI_BMC                     policy<{'armhf': 'm'}>
+CONFIG_NPCM7XX_TIMER                            policy<{'armhf': 'y'}>
+CONFIG_NPCM7XX_WATCHDOG                         policy<{'armhf': 'y'}>
+CONFIG_NPCM_ADC                                 policy<{'armhf': 'm'}>
+CONFIG_NR_CPUS_DEFAULT                          policy<{'amd64': '8192', 'i386': '8'}>
+CONFIG_NR_CPUS_RANGE_BEGIN                      policy<{'amd64': '8192', 'i386': '2'}>
+CONFIG_NR_CPUS_RANGE_END                        policy<{'amd64': '8192', 'i386': '8'}>
+CONFIG_NR_IRQS                                  policy<{'ppc64el': '512'}>
+CONFIG_NS83820                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NSC_GPIO                                 policy<{'i386': 'm'}>
+CONFIG_NTB                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_NTB_AMD                                  policy<{'amd64': 'n'}>
+CONFIG_NTB_IDT                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NTB_INTEL                                policy<{'amd64': 'm'}>
+CONFIG_NTB_MSI                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_NTB_MSI_TEST                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_NTB_NETDEV                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NTB_PERF                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NTB_PINGPONG                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NTB_SWITCHTEC                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NTB_TOOL                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NTB_TRANSPORT                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_NTFS_DEBUG                               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_NTFS_FS                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NTFS_RW                                  policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'y'}>
+CONFIG_NULL_TTY                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NUMA_BALANCING                           policy<{'amd64': 'y', 'arm64': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NVDIMM_DAX                               policy<{'amd64': 'y', 'ppc64el': 'y'}>
+CONFIG_NVDIMM_KEYS                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf-generic-lpae': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_NVDIMM_PFN                               policy<{'amd64': 'y', 'ppc64el': 'y'}>
+CONFIG_NVEC_PAZ00                               policy<{'armhf-generic': 'm'}>
+CONFIG_NVEC_POWER                               policy<{'armhf-generic': 'm'}>
+CONFIG_NVMEM_BCM_OCOTP                          policy<{'arm64': 'm'}>
+CONFIG_NVMEM_IMX_IIM                            policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_NVMEM_IMX_OCOTP                          policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_NVMEM_IMX_OCOTP_SCU                      policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_NVMEM_REBOOT_MODE                        policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_NVMEM_SNVS_LPGPR                         policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_NVMEM_SUNXI_SID                          policy<{'arm64': 'm'}>
+CONFIG_NVMEM_SYSFS                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_NVMEM_VF610_OCOTP                        policy<{'armhf-generic': 'n'}>
+CONFIG_NVMEM_ZYNQMP                             policy<{'arm64': 'y'}>
+CONFIG_NVME_CORE                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NVME_FABRICS                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NVME_FC                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NVME_MULTIPATH                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_NVME_RDMA                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NVME_TARGET                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NVME_TARGET_FC                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NVME_TARGET_FCLOOP                       policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_NVME_TARGET_LOOP                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NVME_TARGET_RDMA                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NVME_TARGET_TCP                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NVME_TCP                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_NV_TCO                                   policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_NXP_TJA11XX_PHY                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_N_HDLC                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_OABI_COMPAT                              policy<{'armhf': 'n'}>
+CONFIG_OBJAGG                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_OCFS2_DEBUG_FS                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_OCFS2_DEBUG_MASKLOG                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_OCFS2_FS                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_OCFS2_FS_O2CB                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_OCFS2_FS_STATS                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_OCFS2_FS_USERSPACE_CLUSTER               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_OCTEONTX2_AF                             policy<{'arm64': 'm'}>
+CONFIG_OCTEONTX2_MBOX                           policy<{'arm64': 'm'}>
+CONFIG_OCXL                                     policy<{'ppc64el': 'm'}>
+CONFIG_OCXL_BASE                                policy<{'ppc64el': 'y'}>
+CONFIG_OF                                       policy<{'amd64': 'n', 'arm64': 'y', 'armhf': 'y', 'i386': 'n', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_OF_ADDRESS                               policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_OF_DMA_DEFAULT_COHERENT                  policy<{'ppc64el': 'y'}>
+CONFIG_OF_DYNAMIC                               policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_OF_EARLY_FLATTREE                        policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_OF_FLATTREE                              policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_OF_FPGA_REGION                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_OF_GPIO                                  policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_OF_IOMMU                                 policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_OF_IRQ                                   policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_OF_KOBJ                                  policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_OF_MDIO                                  policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_OF_NET                                   policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_OF_NUMA                                  policy<{'arm64': 'y'}>
+CONFIG_OF_OVERLAY                               policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_OF_PMEM                                  policy<{'arm64': 'm', 'armhf-generic-lpae': 'm', 'ppc64el': 'm'}>
+CONFIG_OF_RECONFIG_NOTIFIER_ERROR_INJECT        policy<{'arm64': 'n', 'armhf': 'n', 'ppc64el': 'n'}>
+CONFIG_OF_RESERVED_MEM                          policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_OF_RESOLVE                               policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_OF_UNITTEST                              policy<{'arm64': 'n', 'armhf': 'n', 'ppc64el': 'n'}>
+CONFIG_OID_REGISTRY                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_OLD_SIGACTION                            policy<{'armhf': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_OLD_SIGSUSPEND                           policy<{'ppc64el': 'y'}>
+CONFIG_OLD_SIGSUSPEND3                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_OMAP2PLUS_MBOX                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_OMAP2_VRFB                               policy<{'armhf-generic': 'y'}>
+CONFIG_OMAP3_L2_AUX_SECURE_SAVE_RESTORE         policy<{'armhf-generic': 'n'}>
+CONFIG_OMAP3_SDRC_AC_TIMING                     policy<{'armhf-generic': 'n'}>
+CONFIG_OMAP3_THERMAL                            policy<{'armhf-generic': 'n'}>
+CONFIG_OMAP4_THERMAL                            policy<{'armhf-generic': 'y'}>
+CONFIG_OMAP5_ERRATA_801819                      policy<{'armhf': 'y'}>
+CONFIG_OMAP_32K_TIMER                           policy<{'armhf': 'y'}>
+CONFIG_OMAP_CONTROL_PHY                         policy<{'armhf': 'm'}>
+CONFIG_OMAP_DM_TIMER                            policy<{'armhf': 'y'}>
+CONFIG_OMAP_GPMC                                policy<{'armhf': 'y'}>
+CONFIG_OMAP_GPMC_DEBUG                          policy<{'armhf': 'n'}>
+CONFIG_OMAP_INTERCONNECT                        policy<{'armhf': 'y'}>
+CONFIG_OMAP_INTERCONNECT_BARRIER                policy<{'armhf': 'y'}>
+CONFIG_OMAP_IOMMU                               policy<{'armhf': 'y'}>
+CONFIG_OMAP_IOMMU_DEBUG                         policy<{'armhf': 'n'}>
+CONFIG_OMAP_IRQCHIP                             policy<{'armhf': 'y'}>
+CONFIG_OMAP_MBOX_KFIFO_SIZE                     policy<{'arm64': '256', 'armhf': '256'}>
+CONFIG_OMAP_OCP2SCP                             policy<{'armhf': 'm'}>
+CONFIG_OMAP_PACKAGE_CBB                         policy<{'armhf-generic': 'y'}>
+CONFIG_OMAP_REMOTEPROC                          policy<{'armhf-generic': 'm'}>
+CONFIG_OMAP_RESET_CLOCKS                        policy<{'armhf': 'y'}>
+CONFIG_OMAP_SSI                                 policy<{'armhf-generic': 'm'}>
+CONFIG_OMAP_USB2                                policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_OMAP_WATCHDOG                            policy<{'armhf': 'm'}>
+CONFIG_OMFS_FS                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_OPAL_CORE                                policy<{'ppc64el': 'n'}>
+CONFIG_OPAL_PRD                                 policy<{'ppc64el': 'm'}>
+CONFIG_OPENVSWITCH                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_OPENVSWITCH_GENEVE                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_OPENVSWITCH_GRE                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_OPENVSWITCH_VXLAN                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_OPROFILE                                 policy<{'amd64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_OPROFILE_EVENT_MULTIPLEX                 policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_OPROFILE_NMI_TIMER                       policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_OPT3001                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_OPTEE                                    policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_OPTEE_SHM_NUM_PRIV_PAGES                 policy<{'arm64': '1', 'armhf': '1'}>
+CONFIG_OPTIMIZE_INLINING                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_OPTPROBES                                policy<{'amd64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ORANGEFS_FS                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_ORINOCO_USB                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ORION_IRQCHIP                            policy<{'armhf': 'y'}>
+CONFIG_ORION_TIMER                              policy<{'armhf': 'y'}>
+CONFIG_ORION_WATCHDOG                           policy<{'armhf': 'm'}>
+CONFIG_OSF_PARTITION                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_OUTER_CACHE                              policy<{'armhf': 'y'}>
+CONFIG_OUTER_CACHE_SYNC                         policy<{'armhf': 'y'}>
+CONFIG_OUTPUT_FORMAT                            policy<{'amd64': '"elf64-x86-64"', 'i386': '"elf32-i386"'}>
+CONFIG_OVERLAY_FS                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_OVERLAY_FS_INDEX                         policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_OVERLAY_FS_METACOPY                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_OVERLAY_FS_REDIRECT_DIR                  policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_OVERLAY_FS_XINO_AUTO                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_OWL_DMA                                  policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_OWL_PM_DOMAINS                           policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_OWL_PM_DOMAINS_HELPER                    policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_OWL_TIMER                                policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_P54_COMMON                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_P54_LEDS                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_P54_PCI                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_P54_SPI                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_P54_SPI_DEFAULT_EEPROM                   policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_P54_USB                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PA12203001                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PACKET                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PACKET_DIAG                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_PACKING                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_PACK_STACK                               policy<{'s390x': 'y'}>
+CONFIG_PADATA                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PAGE_COUNTER                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PAGE_EXTENSION                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_PAGE_OFFSET                              policy<{'armhf': '0xC0000000', 'i386': '0xC0000000', 'ppc64el': '0xc000000000000000'}>
+CONFIG_PAGE_OWNER                               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_PAGE_POOL                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PAGE_TABLE_ISOLATION                     policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_PALMAS_GPADC                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PANASONIC_LAPTOP                         policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PANEL                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PANEL_CHANGE_MESSAGE                     policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_PANEL_PARPORT                            policy<{'amd64': '0', 'arm64': '0', 'armhf': '0', 'i386': '0', 'ppc64el': '0'}>
+CONFIG_PANEL_PROFILE                            policy<{'amd64': '5', 'arm64': '5', 'armhf': '5', 'i386': '5', 'ppc64el': '5'}>
+CONFIG_PANIC_ON_OOPS_VALUE                      policy<{'amd64': '0', 'arm64': '0', 'armhf': '0', 'i386': '0', 'ppc64el': '0', 's390x': '0'}>
+CONFIG_PANIC_TIMEOUT                            policy<{'amd64': '0', 'arm64': '0', 'armhf': '0', 'i386': '0', 'ppc64el': '10', 's390x': '0'}>
+CONFIG_PANTHERLORD_FF                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PAPR_SCM                                 policy<{'ppc64el': 'm'}>
+CONFIG_PARAVIRT                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'n', 'i386': 'y'}>
+CONFIG_PARAVIRT_CLOCK                           policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_PARAVIRT_DEBUG                           policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_PARAVIRT_SPINLOCKS                       policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_PARAVIRT_TIME_ACCOUNTING                 policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n'}>
+CONFIG_PARAVIRT_XXL                             policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_PARIDE                                   policy<{'amd64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PARIDE_ATEN                              policy<{'amd64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PARIDE_BPCK                              policy<{'amd64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PARIDE_BPCK6                             policy<{'armhf': 'm', 'i386': 'm'}>
+CONFIG_PARIDE_COMM                              policy<{'amd64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PARIDE_DSTR                              policy<{'amd64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PARIDE_EPAT                              policy<{'amd64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PARIDE_EPATC8                            policy<{'amd64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PARIDE_EPIA                              policy<{'amd64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PARIDE_FIT2                              policy<{'amd64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PARIDE_FIT3                              policy<{'amd64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PARIDE_FRIQ                              policy<{'amd64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PARIDE_FRPW                              policy<{'amd64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PARIDE_KBIC                              policy<{'amd64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PARIDE_KTTI                              policy<{'amd64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PARIDE_ON20                              policy<{'amd64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PARIDE_ON26                              policy<{'amd64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PARIDE_PCD                               policy<{'amd64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PARIDE_PD                                policy<{'amd64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PARIDE_PF                                policy<{'amd64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PARIDE_PG                                policy<{'amd64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PARIDE_PT                                policy<{'amd64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PARMAN                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_PARPORT                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_PARPORT_1284                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PARPORT_AX88796                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PARPORT_NOT_PC                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PARPORT_PANEL                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PARPORT_PC                               policy<{'amd64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PARPORT_PC_FIFO                          policy<{'amd64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PARPORT_PC_PCMCIA                        policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PARPORT_PC_SUPERIO                       policy<{'amd64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_PARPORT_SERIAL                           policy<{'amd64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PARTITION_ADVANCED                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PARTITION_PERCPU                         policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_PATA_ACPI                                policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_PATA_ALI                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_AMD                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_ARTOP                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_ATIIXP                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_ATP867X                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_CMD640_PCI                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_CMD64X                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_CS5520                              policy<{'i386': 'm'}>
+CONFIG_PATA_CS5530                              policy<{'i386': 'm'}>
+CONFIG_PATA_CS5535                              policy<{'i386': 'm'}>
+CONFIG_PATA_CS5536                              policy<{'i386': 'm'}>
+CONFIG_PATA_CYPRESS                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_EFAR                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_HPT366                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_HPT37X                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_HPT3X2N                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_HPT3X3                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_IMX                                 policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_PATA_ISAPNP                              policy<{'i386': 'm'}>
+CONFIG_PATA_IT8213                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_IT821X                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_JMICRON                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_LEGACY                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_MARVELL                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_MPIIX                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_NETCELL                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_NINJA32                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_NS87410                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_NS87415                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_OF_PLATFORM                         policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_OLDPIIX                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_OPTI                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_OPTIDMA                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_PCMCIA                              policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PATA_PDC2027X                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_PDC_OLD                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_PLATFORM                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_QDI                                 policy<{'i386': 'm'}>
+CONFIG_PATA_RADISYS                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_RDC                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_RZ1000                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_SC1200                              policy<{'i386': 'm'}>
+CONFIG_PATA_SCH                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_SERVERWORKS                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_SIL680                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_SIS                                 policy<{'amd64': 'y', 'arm64': 'm', 'armhf': 'm', 'i386': 'y', 'ppc64el': 'm'}>
+CONFIG_PATA_TOSHIBA                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_TRIFLEX                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_VIA                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_WINBOND                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PATA_WINBOND_VLB                         policy<{'i386': 'm'}>
+CONFIG_PC104                                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_PC300TOO                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PC8736x_GPIO                             policy<{'i386': 'm'}>
+CONFIG_PC87413_WDT                              policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PCC                                      policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_PCCARD                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'n', 'i386': 'm', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_PCCARD_NONSTATIC                         policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_PCENGINES_APU2                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PCF50633_ADC                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PCF50633_GPIO                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PCH_CAN                                  policy<{'i386': 'm'}>
+CONFIG_PCH_DMA                                  policy<{'i386': 'm'}>
+CONFIG_PCH_GBE                                  policy<{'i386': 'm'}>
+CONFIG_PCH_PHUB                                 policy<{'i386': 'm'}>
+CONFIG_PCI                                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PCI200SYN                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PCIEAER                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_PCIEAER_INJECT                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 's390x': 'n'}>
+CONFIG_PCIEASPM                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_PCIEASPM_PERFORMANCE                     policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 's390x': 'n'}>
+CONFIG_PCIEASPM_POWERSAVE                       policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 's390x': 'n'}>
+CONFIG_PCIEASPM_POWER_SUPERSAVE                 policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 's390x': 'n'}>
+CONFIG_PCIE_AL                                  policy<{'arm64': 'y'}>
+CONFIG_PCIE_ALTERA                              policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_PCIE_ALTERA_MSI                          policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_PCIE_ARMADA_8K                           policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_PCIE_BW                                  policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 's390x': 'n'}>
+CONFIG_PCIE_CADENCE                             policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_PCIE_CADENCE_EP                          policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_PCIE_CADENCE_HOST                        policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_PCIE_DPC                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_PCIE_DW                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_PCIE_DW_EP                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_PCIE_DW_HOST                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_PCIE_DW_PLAT                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_PCIE_DW_PLAT_EP                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_PCIE_DW_PLAT_HOST                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_PCIE_ECRC                                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 's390x': 'n'}>
+CONFIG_PCIE_HISI_STB                            policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_PCIE_IPROC                               policy<{'arm64': 'm'}>
+CONFIG_PCIE_IPROC_MSI                           policy<{'arm64': 'y'}>
+CONFIG_PCIE_IPROC_PLATFORM                      policy<{'arm64': 'm'}>
+CONFIG_PCIE_KIRIN                               policy<{'arm64': 'y'}>
+CONFIG_PCIE_MEDIATEK                            policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_PCIE_MOBIVEIL                            policy<{'arm64': 'y'}>
+CONFIG_PCIE_PME                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_PCIE_PTM                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_PCIE_QCOM                                policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_PCIE_RCAR                                policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_PCIE_ROCKCHIP                            policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_PCIE_ROCKCHIP_EP                         policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_PCIE_ROCKCHIP_HOST                       policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PCIE_UNIPHIER                            policy<{'armhf': 'y'}>
+CONFIG_PCIE_XILINX                              policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_PCIE_XILINX_NWL                          policy<{'arm64': 'y'}>
+CONFIG_PCIPCWATCHDOG                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_PCI_AARDVARK                             policy<{'arm64': 'y'}>
+CONFIG_PCI_ATMEL                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PCI_ATS                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PCI_BIOS                                 policy<{'i386': 'y'}>
+CONFIG_PCI_BRIDGE_EMUL                          policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_PCI_CNB20LE_QUIRK                        policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_PCI_DEBUG                                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_PCI_DIRECT                               policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_PCI_DOMAINS                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PCI_DOMAINS_GENERIC                      policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_PCI_DRA7XX                               policy<{'armhf': 'y'}>
+CONFIG_PCI_DRA7XX_EP                            policy<{'armhf': 'y'}>
+CONFIG_PCI_DRA7XX_HOST                          policy<{'armhf': 'y'}>
+CONFIG_PCI_ECAM                                 policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_PCI_ENDPOINT                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PCI_ENDPOINT_CONFIGFS                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PCI_ENDPOINT_TEST                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_PCI_EPF_TEST                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_PCI_FTPCI100                             policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_PCI_GOANY                                policy<{'i386': 'y'}>
+CONFIG_PCI_GOBIOS                               policy<{'i386': 'n'}>
+CONFIG_PCI_GODIRECT                             policy<{'i386': 'n'}>
+CONFIG_PCI_GOMMCONFIG                           policy<{'i386': 'n'}>
+CONFIG_PCI_HISI                                 policy<{'arm64': 'y'}>
+CONFIG_PCI_HOST_COMMON                          policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_PCI_HOST_GENERIC                         policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_PCI_HOST_THUNDER_ECAM                    policy<{'arm64': 'y'}>
+CONFIG_PCI_HOST_THUNDER_PEM                     policy<{'arm64': 'y'}>
+CONFIG_PCI_HYPERV                               policy<{'amd64': 'm'}>
+CONFIG_PCI_HYPERV_INTERFACE                     policy<{'amd64': 'm'}>
+CONFIG_PCI_IMX6                                 policy<{'arm64': 'y', 'armhf-generic': 'y'}>
+CONFIG_PCI_IOV                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PCI_KEYSTONE                             policy<{'arm64': 'y'}>
+CONFIG_PCI_KEYSTONE_EP                          policy<{'arm64': 'y'}>
+CONFIG_PCI_KEYSTONE_HOST                        policy<{'arm64': 'y'}>
+CONFIG_PCI_LABEL                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_PCI_LAYERSCAPE                           policy<{'arm64': 'y', 'armhf': 'n'}>
+CONFIG_PCI_LAYERSCAPE_EP                        policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_PCI_LOCKLESS_CONFIG                      policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_PCI_MESON                                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n'}>
+CONFIG_PCI_MMCONFIG                             policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_PCI_MSI                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PCI_MSI_IRQ_DOMAIN                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_PCI_MVEBU                                policy<{'armhf': 'y'}>
+CONFIG_PCI_P2PDMA                               policy<{'amd64': 'n', 'ppc64el': 'n'}>
+CONFIG_PCI_PASID                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_PCI_PF_STUB                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_PCI_PRI                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_PCI_QUIRKS                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_PCI_RCAR_GEN2                            policy<{'armhf': 'y'}>
+CONFIG_PCI_REALLOC_ENABLE_AUTO                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PCI_STUB                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_PCI_SW_SWITCHTEC                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_PCI_SYSCALL                              policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_PCI_TEGRA                                policy<{'armhf-generic': 'y'}>
+CONFIG_PCI_V3_SEMI                              policy<{'armhf': 'y'}>
+CONFIG_PCI_XEN                                  policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_PCI_XGENE                                policy<{'arm64': 'y'}>
+CONFIG_PCI_XGENE_MSI                            policy<{'arm64': 'y'}>
+CONFIG_PCMCIA                                   policy<{'amd64': 'm', 'arm64': 'n', 'i386': 'm'}>
+CONFIG_PCMCIA_3C574                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PCMCIA_3C589                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PCMCIA_AHA152X                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PCMCIA_ATMEL                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PCMCIA_AXNET                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PCMCIA_FDOMAIN                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PCMCIA_FMVJ18X                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PCMCIA_HERMES                            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PCMCIA_LOAD_CIS                          policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_PCMCIA_NINJA_SCSI                        policy<{'i386': 'm'}>
+CONFIG_PCMCIA_NMCLAN                            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PCMCIA_PCNET                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PCMCIA_PROBE                             policy<{'i386': 'y'}>
+CONFIG_PCMCIA_QLOGIC                            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PCMCIA_RAYCS                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PCMCIA_SMC91C92                          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PCMCIA_SPECTRUM                          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PCMCIA_SYM53C500                         policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PCMCIA_WL3501                            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PCMCIA_XIRC2PS                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PCMCIA_XIRCOM                            policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_PCNET32                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PCSPKR_PLATFORM                          policy<{'amd64': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PCWATCHDOG                               policy<{'i386': 'm'}>
+CONFIG_PD6729                                   policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PDA_POWER                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PDC_ADMA                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PEAQ_WMI                                 policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PERCPU_STATS                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_PERCPU_TEST                              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_PERF_EVENTS                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PERF_EVENTS_AMD_POWER                    policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_PERF_EVENTS_INTEL_CSTATE                 policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PERF_EVENTS_INTEL_RAPL                   policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PERF_EVENTS_INTEL_UNCORE                 policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_PERF_USE_VMALLOC                         policy<{'armhf': 'y'}>
+CONFIG_PERSISTENT_KEYRINGS                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PFAULT                                   policy<{'s390x': 'y'}>
+CONFIG_PGSTE                                    policy<{'s390x': 'y'}>
+CONFIG_PGTABLE_LEVELS                           policy<{'amd64': '4', 'arm64': '4', 'armhf-generic': '2', 'armhf-generic-lpae': '3', 'i386': '3', 'ppc64el': '4', 's390x': '5'}>
+CONFIG_PHANTOM                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_PHONET                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_PHYLIB                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'm'}>
+CONFIG_PHYLINK                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PHYSICAL_ALIGN                           policy<{'amd64': '0x200000', 'i386': '0x1000000'}>
+CONFIG_PHYSICAL_START                           policy<{'amd64': '0x1000000', 'i386': '0x1000000', 'ppc64el': '0x00000000'}>
+CONFIG_PHYS_ADDR_T_64BIT                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf-generic-lpae': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PHY_AM654_SERDES                         policy<{'arm64': 'm'}>
+CONFIG_PHY_BCM_NS_USB2                          policy<{'arm64': 'm'}>
+CONFIG_PHY_BCM_NS_USB3                          policy<{'arm64': 'm'}>
+CONFIG_PHY_BCM_SR_PCIE                          policy<{'arm64': 'm'}>
+CONFIG_PHY_BCM_SR_USB                           policy<{'arm64': 'm'}>
+CONFIG_PHY_BERLIN_SATA                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PHY_BERLIN_USB                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PHY_BRCM_SATA                            policy<{'arm64': 'y'}>
+CONFIG_PHY_BRCM_USB                             policy<{'arm64': 'm'}>
+CONFIG_PHY_CADENCE_DP                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_PHY_CADENCE_DPHY                         policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_PHY_CADENCE_SIERRA                       policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_PHY_CPCAP_USB                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PHY_DM816X_USB                           policy<{'armhf': 'm'}>
+CONFIG_PHY_EXYNOS5250_SATA                      policy<{'armhf': 'y'}>
+CONFIG_PHY_EXYNOS5250_USB2                      policy<{'armhf': 'y'}>
+CONFIG_PHY_EXYNOS5_USBDRD                       policy<{'armhf': 'm'}>
+CONFIG_PHY_EXYNOS_DP_VIDEO                      policy<{'armhf': 'y'}>
+CONFIG_PHY_EXYNOS_MIPI_VIDEO                    policy<{'armhf': 'y'}>
+CONFIG_PHY_EXYNOS_PCIE                          policy<{'armhf': 'y'}>
+CONFIG_PHY_FSL_IMX8MQ_USB                       policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_PHY_HI3660_USB                           policy<{'arm64': 'm'}>
+CONFIG_PHY_HI6220_USB                           policy<{'arm64': 'm'}>
+CONFIG_PHY_HISI_INNO_USB2                       policy<{'arm64': 'm'}>
+CONFIG_PHY_HISTB_COMBPHY                        policy<{'arm64': 'm'}>
+CONFIG_PHY_HIX5HD2_SATA                         policy<{'armhf': 'm'}>
+CONFIG_PHY_MAPPHONE_MDM6600                     policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_PHY_MESON8B_USB2                         policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PHY_MESON_G12A_USB2                      policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PHY_MESON_G12A_USB3_PCIE                 policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PHY_MESON_GXL_USB2                       policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PHY_MESON_GXL_USB3                       policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PHY_MIXEL_MIPI_DPHY                      policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_PHY_MTK_TPHY                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PHY_MTK_UFS                              policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PHY_MTK_XSPHY                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PHY_MVEBU_A3700_COMPHY                   policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PHY_MVEBU_A3700_UTMI                     policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PHY_MVEBU_A38X_COMPHY                    policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PHY_MVEBU_CP110_COMPHY                   policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PHY_MVEBU_SATA                           policy<{'armhf': 'y'}>
+CONFIG_PHY_NS2_PCIE                             policy<{'arm64': 'y'}>
+CONFIG_PHY_NS2_USB_DRD                          policy<{'arm64': 'm'}>
+CONFIG_PHY_OCELOT_SERDES                        policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_PHY_PXA_28NM_HSIC                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_PHY_PXA_28NM_USB2                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_PHY_QCOM_APQ8064_SATA                    policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PHY_QCOM_IPQ806X_SATA                    policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PHY_QCOM_PCIE2                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PHY_QCOM_QMP                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PHY_QCOM_QUSB2                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PHY_QCOM_UFS                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PHY_QCOM_UFS_14NM                        policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PHY_QCOM_USB_HS                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PHY_QCOM_USB_HSIC                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PHY_RCAR_GEN2                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PHY_RCAR_GEN3_PCIE                       policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PHY_RCAR_GEN3_USB2                       policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PHY_RCAR_GEN3_USB3                       policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PHY_ROCKCHIP_DP                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PHY_ROCKCHIP_EMMC                        policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PHY_ROCKCHIP_INNO_HDMI                   policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PHY_ROCKCHIP_INNO_USB2                   policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PHY_ROCKCHIP_PCIE                        policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PHY_ROCKCHIP_TYPEC                       policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PHY_ROCKCHIP_USB                         policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PHY_SAMSUNG_USB2                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PHY_SUN4I_USB                            policy<{'arm64': 'm'}>
+CONFIG_PHY_SUN6I_MIPI_DPHY                      policy<{'arm64': 'm'}>
+CONFIG_PHY_SUN9I_USB                            policy<{'arm64': 'n'}>
+CONFIG_PHY_TEGRA_XUSB                           policy<{'armhf-generic': 'm'}>
+CONFIG_PHY_TI_GMII_SEL                          policy<{'armhf': 'y'}>
+CONFIG_PHY_TUSB1210                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PHY_UNIPHIER_PCIE                        policy<{'armhf': 'm'}>
+CONFIG_PHY_UNIPHIER_USB2                        policy<{'armhf': 'm'}>
+CONFIG_PHY_UNIPHIER_USB3                        policy<{'armhf': 'm'}>
+CONFIG_PHY_XGENE                                policy<{'arm64': 'y'}>
+CONFIG_PI433                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PID_IN_CONTEXTIDR                        policy<{'arm64': 'n', 'armhf': 'n'}>
+CONFIG_PID_NS                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PINCONF                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PINCTRL                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_PINCTRL_AMD                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PINCTRL_APQ8064                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PINCTRL_APQ8084                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PINCTRL_ARMADA_370                       policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_ARMADA_375                       policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_ARMADA_37XX                      policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_ARMADA_38X                       policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_ARMADA_39X                       policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_ARMADA_AP806                     policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_ARMADA_CP110                     policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_ARMADA_XP                        policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_AS370                            policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_PINCTRL_AS3722                           policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_PINCTRL_ASPEED                           policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_ASPEED_G6                        policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_AXP209                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_PINCTRL_BAYTRAIL                         policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_PINCTRL_BCM2835                          policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_BERLIN                           policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_PINCTRL_BERLIN_BG2                       policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_BERLIN_BG2CD                     policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_BERLIN_BG2Q                      policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_BERLIN_BG4CT                     policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_PINCTRL_BM1880                           policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_BROXTON                          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PINCTRL_CANNONLAKE                       policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PINCTRL_CEDARFORK                        policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PINCTRL_CS47L15                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PINCTRL_CS47L35                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PINCTRL_CS47L85                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PINCTRL_CS47L90                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PINCTRL_CS47L92                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PINCTRL_DENVERTON                        policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PINCTRL_DOVE                             policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_EXYNOS                           policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_EXYNOS_ARM                       policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_GEMINILAKE                       policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PINCTRL_ICELAKE                          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PINCTRL_IMX                              policy<{'arm64': 'y', 'armhf-generic': 'y'}>
+CONFIG_PINCTRL_IMX50                            policy<{'armhf-generic': 'y'}>
+CONFIG_PINCTRL_IMX51                            policy<{'armhf-generic': 'y'}>
+CONFIG_PINCTRL_IMX6Q                            policy<{'armhf-generic': 'y'}>
+CONFIG_PINCTRL_IMX6SL                           policy<{'armhf-generic': 'y'}>
+CONFIG_PINCTRL_IMX6SLL                          policy<{'armhf-generic': 'y'}>
+CONFIG_PINCTRL_IMX6SX                           policy<{'armhf-generic': 'y'}>
+CONFIG_PINCTRL_IMX6UL                           policy<{'armhf-generic': 'y'}>
+CONFIG_PINCTRL_IMX7D                            policy<{'armhf-generic': 'y'}>
+CONFIG_PINCTRL_IMX7ULP                          policy<{'armhf-generic': 'y'}>
+CONFIG_PINCTRL_IMX8MM                           policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_IMX8MN                           policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_IMX8MQ                           policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_IMX8QM                           policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_IMX8QXP                          policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_IMX_SCU                          policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_INTEL                            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PINCTRL_IPQ4019                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PINCTRL_IPQ8064                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PINCTRL_IPQ8074                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PINCTRL_IPROC_GPIO                       policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_LEWISBURG                        policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PINCTRL_LOCHNAGAR                        policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_PINCTRL_MADERA                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PINCTRL_MAX77620                         policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_PINCTRL_MCP23S08                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PINCTRL_MDM9615                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PINCTRL_MERRIFIELD                       policy<{'i386': 'n'}>
+CONFIG_PINCTRL_MESON                            policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_PINCTRL_MESON8                           policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_MESON8B                          policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_MESON8_PMX                       policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_PINCTRL_MESON_AXG                        policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_MESON_AXG_PMX                    policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_MESON_G12A                       policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_MESON_GXBB                       policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_MESON_GXL                        policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_MSM                              policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_PINCTRL_MSM8660                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PINCTRL_MSM8916                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PINCTRL_MSM8960                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PINCTRL_MSM8994                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PINCTRL_MSM8996                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PINCTRL_MSM8998                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PINCTRL_MSM8X74                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PINCTRL_MT2701                           policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_MT2712                           policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_MT6397                           policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_PINCTRL_MT6765                           policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_MT6797                           policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_MT7622                           policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_MT7623                           policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_MT7629                           policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_MT8127                           policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_MT8135                           policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_MT8173                           policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_MT8183                           policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_MT8516                           policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_MTK                              policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_PINCTRL_MTK_MOORE                        policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_PINCTRL_MTK_PARIS                        policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_MVEBU                            policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_PINCTRL_NPCM7XX                          policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_NS2_MUX                          policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_OCELOT                           policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_PINCTRL_OWL                              policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_PINCTRL_PALMAS                           policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_PINCTRL_PFC_EMEV2                        policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_PFC_R8A7740                      policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_PFC_R8A7743                      policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_PFC_R8A7744                      policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_PFC_R8A7745                      policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_PFC_R8A77470                     policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_PFC_R8A774A1                     policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_PFC_R8A774C0                     policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_PFC_R8A7778                      policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_PFC_R8A7779                      policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_PFC_R8A7790                      policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_PFC_R8A7791                      policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_PFC_R8A7792                      policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_PFC_R8A7793                      policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_PFC_R8A7794                      policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_PFC_R8A7795                      policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_PFC_R8A7796                      policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_PFC_R8A77965                     policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_PFC_R8A77970                     policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_PFC_R8A77980                     policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_PFC_R8A77990                     policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_PFC_R8A77995                     policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_PFC_SH73A0                       policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_QCOM_SPMI_PMIC                   policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PINCTRL_QCOM_SSBI_PMIC                   policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PINCTRL_QCS404                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PINCTRL_QDF2XXX                          policy<{'arm64': 'm'}>
+CONFIG_PINCTRL_RK805                            policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_PINCTRL_ROCKCHIP                         policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_PINCTRL_RZA1                             policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_RZA2                             policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_RZN1                             policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_S700                             policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_PINCTRL_S900                             policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_PINCTRL_SAMSUNG                          policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_SC7180                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PINCTRL_SDM660                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PINCTRL_SDM845                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PINCTRL_SH_PFC                           policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_PINCTRL_SH_PFC_GPIO                      policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_SINGLE                           policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_PINCTRL_SM8150                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PINCTRL_SPRD                             policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_SPRD_SC9860                      policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_STMFX                            policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_PINCTRL_SUN4I_A10                        policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_SUN50I_A64                       policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_SUN50I_A64_R                     policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_SUN50I_H5                        policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_SUN50I_H6                        policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_SUN50I_H6_R                      policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_SUN5I                            policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_SUN6I_A31                        policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_SUN6I_A31_R                      policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_SUN8I_A23                        policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_SUN8I_A23_R                      policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_SUN8I_A33                        policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_SUN8I_A83T                       policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_SUN8I_A83T_R                     policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_SUN8I_H3                         policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_SUN8I_H3_R                       policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_SUN8I_V3S                        policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_SUN9I_A80                        policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_SUN9I_A80_R                      policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_SUNRISEPOINT                     policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PINCTRL_SUNXI                            policy<{'arm64': 'y'}>
+CONFIG_PINCTRL_SX150X                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PINCTRL_TEGRA                            policy<{'armhf-generic': 'y'}>
+CONFIG_PINCTRL_TEGRA114                         policy<{'armhf-generic': 'y'}>
+CONFIG_PINCTRL_TEGRA124                         policy<{'armhf-generic': 'y'}>
+CONFIG_PINCTRL_TEGRA20                          policy<{'armhf-generic': 'y'}>
+CONFIG_PINCTRL_TEGRA30                          policy<{'armhf-generic': 'y'}>
+CONFIG_PINCTRL_TEGRA_XUSB                       policy<{'armhf-generic': 'y'}>
+CONFIG_PINCTRL_TI_IODELAY                       policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_UNIPHIER                         policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_UNIPHIER_LD11                    policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_UNIPHIER_LD20                    policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_UNIPHIER_LD4                     policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_UNIPHIER_LD6B                    policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_UNIPHIER_PRO4                    policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_UNIPHIER_PRO5                    policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_UNIPHIER_PXS2                    policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_UNIPHIER_PXS3                    policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_UNIPHIER_SLD8                    policy<{'armhf': 'y'}>
+CONFIG_PINCTRL_VF610                            policy<{'armhf-generic': 'y'}>
+CONFIG_PINMUX                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PJ4B_ERRATA_4742                         policy<{'armhf': 'y'}>
+CONFIG_PKCS7_MESSAGE_PARSER                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PKCS7_TEST_KEY                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_PKCS8_PRIVATE_KEY_PARSER                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_PKEY                                     policy<{'s390x': 'm'}>
+CONFIG_PL310_ERRATA_588369                      policy<{'armhf': 'y'}>
+CONFIG_PL310_ERRATA_727915                      policy<{'armhf': 'y'}>
+CONFIG_PL310_ERRATA_753970                      policy<{'armhf': 'y'}>
+CONFIG_PL310_ERRATA_769419                      policy<{'armhf': 'y'}>
+CONFIG_PL320_MBOX                               policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_PL330_DMA                                policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PL353_SMC                                policy<{'armhf': 'm'}>
+CONFIG_PLATFORM_MHU                             policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_PLATFORM_SI4713                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PLAT_ORION                               policy<{'armhf': 'y'}>
+CONFIG_PLAT_SAMSUNG                             policy<{'armhf': 'y'}>
+CONFIG_PLAT_SPEAR                               policy<{'armhf': 'n'}>
+CONFIG_PLAT_VERSATILE                           policy<{'armhf': 'y'}>
+CONFIG_PLIP                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PLUGIN_HOSTCC                            policy<{'amd64': '""', 'arm64': '""', 'armhf': '""', 'i386': '""', 'ppc64el': '""', 's390x': '""'}>
+CONFIG_PLX_HERMES                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PM8916_WATCHDOG                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PMBUS                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PMC_ATOM                                 policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_PMIC_ADP5520                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PMIC_DA903X                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PMIC_DA9052                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PMIC_OPREGION                            policy<{'amd64': 'n', 'arm64': 'n', 'i386': 'n'}>
+CONFIG_PMS7003                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PM_ADVANCED_DEBUG                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PM_AUTOSLEEP                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_PM_CLK                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_PM_DEBUG                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PM_DEVFREQ                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_PM_DEVFREQ_EVENT                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PM_GENERIC_DOMAINS                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PM_GENERIC_DOMAINS_OF                    policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_PM_GENERIC_DOMAINS_SLEEP                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PM_NOTIFIER_ERROR_INJECT                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PM_OPP                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PM_SLEEP                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PM_SLEEP_DEBUG                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PM_SLEEP_SMP                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PM_SLEEP_SMP_NONZERO_CPU                 policy<{'ppc64el': 'y'}>
+CONFIG_PM_STD_PARTITION                         policy<{'amd64': '""', 'armhf': '""', 'i386': '""'}>
+CONFIG_PM_TEST_SUSPEND                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_PM_TRACE                                 policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_PM_TRACE_RTC                             policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_PM_WAKELOCKS                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PM_WAKELOCKS_GC                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PM_WAKELOCKS_LIMIT                       policy<{'amd64': '100', 'arm64': '100', 'armhf': '100', 'i386': '100', 'ppc64el': '100'}>
+CONFIG_PNFS_BLOCK                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_PNFS_FILE_LAYOUT                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_PNFS_FLEXFILE_LAYOUT                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_PNP                                      policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_PNPACPI                                  policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_PNPBIOS                                  policy<{'i386': 'y'}>
+CONFIG_PNPBIOS_PROC_FS                          policy<{'i386': 'y'}>
+CONFIG_PNP_DEBUG_MESSAGES                       policy<{'amd64': 'n', 'arm64': 'n', 'i386': 'n'}>
+CONFIG_POSIX_MQUEUE                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_POSIX_MQUEUE_SYSCTL                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_POSIX_TIMERS                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_POWER7_CPU                               policy<{'ppc64el': 'n'}>
+CONFIG_POWER8_CPU                               policy<{'ppc64el': 'n'}>
+CONFIG_POWER9_CPU                               policy<{'ppc64el': 'n'}>
+CONFIG_POWERCAP                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_POWERNV_CPUFREQ                          policy<{'ppc64el': 'y'}>
+CONFIG_POWERNV_CPUIDLE                          policy<{'ppc64el': 'y'}>
+CONFIG_POWERNV_OP_PANEL                         policy<{'ppc64el': 'm'}>
+CONFIG_POWER_AVS                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_POWER_AVS_OMAP                           policy<{'armhf-generic': 'y'}>
+CONFIG_POWER_AVS_OMAP_CLASS3                    policy<{'armhf-generic': 'y'}>
+CONFIG_POWER_RESET                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_POWER_RESET_AS3722                       policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_POWER_RESET_AXXIA                        policy<{'armhf-generic-lpae': 'y'}>
+CONFIG_POWER_RESET_BRCMKONA                     policy<{'armhf': 'y'}>
+CONFIG_POWER_RESET_BRCMSTB                      policy<{'arm64': 'n', 'armhf': 'n'}>
+CONFIG_POWER_RESET_GPIO                         policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_POWER_RESET_GPIO_RESTART                 policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_POWER_RESET_HISI                         policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_POWER_RESET_LTC2952                      policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_POWER_RESET_MSM                          policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_POWER_RESET_QCOM_PON                     policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_POWER_RESET_QNAP                         policy<{'armhf': 'n'}>
+CONFIG_POWER_RESET_RESTART                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_POWER_RESET_RMOBILE                      policy<{'armhf': 'm'}>
+CONFIG_POWER_RESET_SC27XX                       policy<{'arm64': 'y'}>
+CONFIG_POWER_RESET_SYSCON                       policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_POWER_RESET_SYSCON_POWEROFF              policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_POWER_RESET_VERSATILE                    policy<{'armhf': 'y'}>
+CONFIG_POWER_RESET_VEXPRESS                     policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_POWER_RESET_XGENE                        policy<{'arm64': 'n'}>
+CONFIG_POWER_SUPPLY                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_POWER_SUPPLY_DEBUG                       policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_POWER_SUPPLY_HWMON                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PPC                                      policy<{'ppc64el': 'y'}>
+CONFIG_PPC64                                    policy<{'ppc64el': 'y'}>
+CONFIG_PPC64_BOOT_WRAPPER                       policy<{'ppc64el': 'y'}>
+CONFIG_PPC64_SUPPORTS_MEMORY_FAILURE            policy<{'ppc64el': 'y'}>
+CONFIG_PPC_4K_PAGES                             policy<{'ppc64el': 'n'}>
+CONFIG_PPC_64K_PAGES                            policy<{'ppc64el': 'y'}>
+CONFIG_PPC_BARRIER_NOSPEC                       policy<{'ppc64el': 'y'}>
+CONFIG_PPC_BOOK3E_64                            policy<{'ppc64el': 'n'}>
+CONFIG_PPC_BOOK3S                               policy<{'ppc64el': 'y'}>
+CONFIG_PPC_BOOK3S_64                            policy<{'ppc64el': 'y'}>
+CONFIG_PPC_COPRO_BASE                           policy<{'ppc64el': 'y'}>
+CONFIG_PPC_DAWR                                 policy<{'ppc64el': 'y'}>
+CONFIG_PPC_DENORMALISATION                      policy<{'ppc64el': 'y'}>
+CONFIG_PPC_DISABLE_WERROR                       policy<{'ppc64el': 'n'}>
+CONFIG_PPC_DOORBELL                             policy<{'ppc64el': 'y'}>
+CONFIG_PPC_DT_CPU_FTRS                          policy<{'ppc64el': 'y'}>
+CONFIG_PPC_EARLY_DEBUG                          policy<{'ppc64el': 'n'}>
+CONFIG_PPC_EMULATED_STATS                       policy<{'ppc64el': 'n'}>
+CONFIG_PPC_EPAPR_HV_BYTECHAN                    policy<{'ppc64el': 'n'}>
+CONFIG_PPC_FAST_ENDIAN_SWITCH                   policy<{'ppc64el': 'n'}>
+CONFIG_PPC_FPU                                  policy<{'ppc64el': 'y'}>
+CONFIG_PPC_HAVE_KUAP                            policy<{'ppc64el': 'y'}>
+CONFIG_PPC_HAVE_KUEP                            policy<{'ppc64el': 'y'}>
+CONFIG_PPC_HAVE_PMU_SUPPORT                     policy<{'ppc64el': 'y'}>
+CONFIG_PPC_I8259                                policy<{'ppc64el': 'y'}>
+CONFIG_PPC_ICP_HV                               policy<{'ppc64el': 'y'}>
+CONFIG_PPC_ICP_NATIVE                           policy<{'ppc64el': 'y'}>
+CONFIG_PPC_ICS_RTAS                             policy<{'ppc64el': 'y'}>
+CONFIG_PPC_INDIRECT_PIO                         policy<{'ppc64el': 'y'}>
+CONFIG_PPC_IRQ_SOFT_MASK_DEBUG                  policy<{'ppc64el': 'n'}>
+CONFIG_PPC_KUAP                                 policy<{'ppc64el': 'y'}>
+CONFIG_PPC_KUAP_DEBUG                           policy<{'ppc64el': 'n'}>
+CONFIG_PPC_KUEP                                 policy<{'ppc64el': 'y'}>
+CONFIG_PPC_MEMTRACE                             policy<{'ppc64el': 'y'}>
+CONFIG_PPC_MM_SLICES                            policy<{'ppc64el': 'y'}>
+CONFIG_PPC_MSI_BITMAP                           policy<{'ppc64el': 'y'}>
+CONFIG_PPC_NATIVE                               policy<{'ppc64el': 'y'}>
+CONFIG_PPC_OF_BOOT_TRAMPOLINE                   policy<{'ppc64el': 'y'}>
+CONFIG_PPC_P7_NAP                               policy<{'ppc64el': 'y'}>
+CONFIG_PPC_PAGE_SHIFT                           policy<{'ppc64el': '16'}>
+CONFIG_PPC_PERF_CTRS                            policy<{'ppc64el': 'y'}>
+CONFIG_PPC_POWERNV                              policy<{'ppc64el': 'y'}>
+CONFIG_PPC_PSERIES                              policy<{'ppc64el': 'y'}>
+CONFIG_PPC_PTDUMP                               policy<{'ppc64el': 'n'}>
+CONFIG_PPC_RADIX_MMU                            policy<{'ppc64el': 'y'}>
+CONFIG_PPC_RADIX_MMU_DEFAULT                    policy<{'ppc64el': 'y'}>
+CONFIG_PPC_RTAS                                 policy<{'ppc64el': 'y'}>
+CONFIG_PPC_RTAS_DAEMON                          policy<{'ppc64el': 'y'}>
+CONFIG_PPC_SMLPAR                               policy<{'ppc64el': 'y'}>
+CONFIG_PPC_SMP_MUXED_IPI                        policy<{'ppc64el': 'y'}>
+CONFIG_PPC_SPLPAR                               policy<{'ppc64el': 'y'}>
+CONFIG_PPC_SUBPAGE_PROT                         policy<{'ppc64el': 'y'}>
+CONFIG_PPC_SVM                                  policy<{'ppc64el': 'y'}>
+CONFIG_PPC_TRANSACTIONAL_MEM                    policy<{'ppc64el': 'y'}>
+CONFIG_PPC_UDBG_16550                           policy<{'ppc64el': 'y'}>
+CONFIG_PPC_VAS                                  policy<{'ppc64el': 'y'}>
+CONFIG_PPC_WATCHDOG                             policy<{'ppc64el': 'y'}>
+CONFIG_PPC_WERROR                               policy<{'ppc64el': 'y'}>
+CONFIG_PPC_XICS                                 policy<{'ppc64el': 'y'}>
+CONFIG_PPC_XIVE                                 policy<{'ppc64el': 'y'}>
+CONFIG_PPC_XIVE_NATIVE                          policy<{'ppc64el': 'y'}>
+CONFIG_PPC_XIVE_SPAPR                           policy<{'ppc64el': 'y'}>
+CONFIG_PPDEV                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PPP                                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_PPPOATM                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PPPOE                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PPPOL2TP                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PPP_ASYNC                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PPP_BSDCOMP                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PPP_DEFLATE                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PPP_FILTER                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PPP_MPPE                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PPP_MULTILINK                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PPP_SYNC_TTY                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PPS                                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'm'}>
+CONFIG_PPS_CLIENT_GPIO                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_PPS_CLIENT_KTIMER                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_PPS_CLIENT_LDISC                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_PPS_CLIENT_PARPORT                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PPS_DEBUG                                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_PPTP                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PREEMPT                                  policy<{'amd64-generic': 'n', 'amd64-lowlatency': 'y', 'arm64': 'n', 'armhf': 'n', 'i386-generic': 'n', 'i386-lowlatency': 'y', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_PREEMPTION                               policy<{'amd64-lowlatency': 'y', 'i386-lowlatency': 'y'}>
+CONFIG_PREEMPTIRQ_DELAY_TEST                    policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_PREEMPTIRQ_EVENTS                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_PREEMPT_COUNT                            policy<{'amd64-lowlatency': 'y', 'i386-lowlatency': 'y'}>
+CONFIG_PREEMPT_NOTIFIERS                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf-generic-lpae': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PREEMPT_RCU                              policy<{'amd64-lowlatency': 'y', 'i386-lowlatency': 'y'}>
+CONFIG_PREEMPT_TRACER                           policy<{'amd64-lowlatency': 'n', 'i386-lowlatency': 'n'}>
+CONFIG_PREEMPT_VOLUNTARY                        policy<{'amd64-generic': 'y', 'amd64-lowlatency': 'n', 'arm64': 'y', 'armhf': 'y', 'i386-generic': 'y', 'i386-lowlatency': 'n', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_PREVENT_FIRMWARE_BUILD                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PRINTER                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PRINTK                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PRINTK_CALLER                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_PRINTK_NMI                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT                policy<{'amd64': '13', 'arm64': '13', 'armhf': '13', 'i386': '13', 'ppc64el': '13', 's390x': '13'}>
+CONFIG_PRINTK_TIME                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PRINT_QUOTA_WARNING                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_PRINT_STACK_DEPTH                        policy<{'ppc64el': '64'}>
+CONFIG_PRISM2_USB                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PRISM54                                  policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_PROBE_EVENTS                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PROCESSOR_SELECT                         policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_PROC_CHILDREN                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PROC_EVENTS                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PROC_FS                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PROC_KCORE                               policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PROC_MEM_ALWAYS_FORCE                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PROC_MEM_FORCE_PTRACE                    policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_PROC_MEM_NO_FORCE                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_PROC_PAGE_MONITOR                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PROC_PID_ARCH_STATUS                     policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_PROC_PID_CPUSET                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PROC_SYSCTL                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PROC_THERMAL_MMIO_RAPL                   policy<{'amd64': 'y'}>
+CONFIG_PROC_VMCORE                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PROC_VMCORE_DEVICE_DUMP                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PROFILE_ANNOTATED_BRANCHES               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_PROFILING                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PROTECTED_VIRTUALIZATION_GUEST           policy<{'s390x': 'y'}>
+CONFIG_PROVE_LOCKING                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_PROVIDE_OHCI1394_DMA_INIT                policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_PSAMPLE                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_PSERIES_CPUIDLE                          policy<{'ppc64el': 'y'}>
+CONFIG_PSERIES_ENERGY                           policy<{'ppc64el': 'm'}>
+CONFIG_PSI                                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_PSTORE                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_PSTORE_842_COMPRESS                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_PSTORE_COMPRESS                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PSTORE_COMPRESS_DEFAULT                  policy<{'amd64': '"deflate"', 'arm64': '"deflate"', 'armhf': '"deflate"', 'i386': '"deflate"', 'ppc64el': '"deflate"'}>
+CONFIG_PSTORE_CONSOLE                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'y', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_PSTORE_DEFLATE_COMPRESS                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PSTORE_DEFLATE_COMPRESS_DEFAULT          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PSTORE_FTRACE                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_PSTORE_LZ4HC_COMPRESS                    policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_PSTORE_LZ4_COMPRESS                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_PSTORE_LZO_COMPRESS                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_PSTORE_PMSG                              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_PSTORE_RAM                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'y', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PSTORE_ZSTD_COMPRESS                     policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_PTP_1588_CLOCK                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'm'}>
+CONFIG_PTP_1588_CLOCK_DTE                       policy<{'arm64': 'm'}>
+CONFIG_PTP_1588_CLOCK_KVM                       policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PTP_1588_CLOCK_PCH                       policy<{'i386': 'm'}>
+CONFIG_PTP_1588_CLOCK_QORIQ                     policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_PUNIT_ATOM_DEBUG                         policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_PVH                                      policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_PVPANIC                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PWM                                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_PWM_ATMEL_HLCDC_PWM                      policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PWM_BCM2835                              policy<{'arm64': 'm'}>
+CONFIG_PWM_BCM_IPROC                            policy<{'arm64': 'm'}>
+CONFIG_PWM_BERLIN                               policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PWM_BRCMSTB                              policy<{'arm64': 'm'}>
+CONFIG_PWM_CRC                                  policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_PWM_CROS_EC                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_PWM_FSL_FTM                              policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_PWM_HIBVT                                policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PWM_IMX1                                 policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_PWM_IMX27                                policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_PWM_IMX_TPM                              policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_PWM_LP3943                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PWM_LPSS                                 policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_PWM_LPSS_PCI                             policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_PWM_LPSS_PLATFORM                        policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_PWM_MEDIATEK                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PWM_MESON                                policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PWM_MTK_DISP                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PWM_OMAP_DMTIMER                         policy<{'armhf': 'm'}>
+CONFIG_PWM_PCA9685                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PWM_RCAR                                 policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PWM_RENESAS_TPU                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PWM_ROCKCHIP                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_PWM_SAMSUNG                              policy<{'armhf': 'm'}>
+CONFIG_PWM_SPRD                                 policy<{'arm64': 'm'}>
+CONFIG_PWM_STMPE                                policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_PWM_SUN4I                                policy<{'arm64': 'm'}>
+CONFIG_PWM_SYSFS                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_PWM_TEGRA                                policy<{'armhf-generic': 'm'}>
+CONFIG_PWM_TIECAP                               policy<{'arm64': 'm', 'armhf-generic': 'm', 'armhf-generic-lpae': 'n'}>
+CONFIG_PWM_TIEHRPWM                             policy<{'arm64': 'm', 'armhf-generic': 'm', 'armhf-generic-lpae': 'n'}>
+CONFIG_PWM_TIPWMSS                              policy<{'armhf-generic': 'y'}>
+CONFIG_PWM_TWL                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PWM_TWL_LED                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_PWRSEQ_EMMC                              policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_PWRSEQ_SD8787                            policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_PWRSEQ_SIMPLE                            policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_PXA168_ETH                               policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCA7000                                  policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_QCA7000_SPI                              policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_QCA7000_UART                             policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_QCOM_A53PLL                              policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCOM_AOSS_QMP                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCOM_APCS_IPC                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCOM_APR                                 policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCOM_BAM_DMA                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCOM_CLK_APCS_MSM8916                    policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCOM_CLK_RPM                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCOM_CLK_RPMH                            policy<{'arm64': 'm'}>
+CONFIG_QCOM_CLK_SMD_RPM                         policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCOM_COINCELL                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCOM_COMMAND_DB                          policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_QCOM_EBI2                                policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_QCOM_EMAC                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_QCOM_FALKOR_ERRATUM_1003                 policy<{'arm64': 'y'}>
+CONFIG_QCOM_FALKOR_ERRATUM_1009                 policy<{'arm64': 'y'}>
+CONFIG_QCOM_FALKOR_ERRATUM_E1041                policy<{'arm64': 'y'}>
+CONFIG_QCOM_FASTRPC                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCOM_GDSC                                policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_QCOM_GENI_SE                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCOM_GLINK_SSR                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCOM_GSBI                                policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCOM_HFPLL                               policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCOM_HIDMA                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_QCOM_HIDMA_MGMT                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_QCOM_IOMMU                               policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_QCOM_IRQ_COMBINER                        policy<{'arm64': 'y'}>
+CONFIG_QCOM_L2_PMU                              policy<{'arm64': 'y'}>
+CONFIG_QCOM_L3_PMU                              policy<{'arm64': 'y'}>
+CONFIG_QCOM_LLCC                                policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCOM_MDT_LOADER                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCOM_PDC                                 policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_QCOM_PM                                  policy<{'armhf': 'y'}>
+CONFIG_QCOM_PM8XXX_XOADC                        policy<{'armhf': 'm'}>
+CONFIG_QCOM_Q6V5_ADSP                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCOM_Q6V5_COMMON                         policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCOM_Q6V5_MSS                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCOM_Q6V5_PAS                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCOM_Q6V5_WCSS                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCOM_QFPROM                              policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCOM_QMI_HELPERS                         policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCOM_RMTFS_MEM                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCOM_RPMCC                               policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_QCOM_RPMH                                policy<{'arm64': 'y'}>
+CONFIG_QCOM_RPMHPD                              policy<{'arm64': 'y'}>
+CONFIG_QCOM_RPROC_COMMON                        policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCOM_SCM                                 policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_QCOM_SCM_32                              policy<{'armhf': 'y'}>
+CONFIG_QCOM_SCM_64                              policy<{'arm64': 'y'}>
+CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT           policy<{'arm64': 'n', 'armhf': 'n'}>
+CONFIG_QCOM_SMD_RPM                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCOM_SMEM                                policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCOM_SMEM_STATE                          policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_QCOM_SMP2P                               policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCOM_SMSM                                policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCOM_SOCINFO                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCOM_SPMI_ADC5                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_QCOM_SPMI_IADC                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_QCOM_SPMI_TEMP_ALARM                     policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCOM_SPMI_VADC                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_QCOM_SYSMON                              policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCOM_TSENS                               policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCOM_VADC_COMMON                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_QCOM_WCNSS_CTRL                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCOM_WCNSS_PIL                           policy<{'arm64': 'n', 'armhf': 'n'}>
+CONFIG_QCOM_WDT                                 policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCS_GCC_404                              policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QCS_TURING_404                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QDIO                                     policy<{'s390x': 'm'}>
+CONFIG_QED                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_QEDE                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_QEDF                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_QEDI                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_QED_FCOE                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_QED_ISCSI                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_QED_LL2                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_QED_OOO                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_QED_RDMA                                 policy<{'amd64': 'y', 'arm64': 'y', 'ppc64el': 'y'}>
+CONFIG_QED_SRIOV                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_QETH                                     policy<{'s390x': 'm'}>
+CONFIG_QETH_L2                                  policy<{'s390x': 'm'}>
+CONFIG_QETH_L3                                  policy<{'s390x': 'm'}>
+CONFIG_QFMT_V1                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_QFMT_V2                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_QLA3XXX                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_QLCNIC                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_QLCNIC_DCB                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_QLCNIC_HWMON                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_QLCNIC_SRIOV                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_QLGE                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_QNX4FS_FS                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_QNX6FS_DEBUG                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_QNX6FS_FS                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_QORIQ_CPUFREQ                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QORIQ_THERMAL                            policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_QRTR                                     policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QRTR_SMD                                 policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QRTR_TUN                                 policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_QSEMI_PHY                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_QTNFMAC                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_QTNFMAC_PCIE                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_QUEUED_RWLOCKS                           policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_QUEUED_SPINLOCKS                         policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_QUOTA                                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_QUOTACTL                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_QUOTACTL_COMPAT                          policy<{'amd64': 'y'}>
+CONFIG_QUOTA_DEBUG                              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_QUOTA_NETLINK_INTERFACE                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_QUOTA_TREE                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_R6040                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_R8169                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_R8188EU                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_R8712U                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RADIO_ADAPTERS                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RADIO_AZTECH                             policy<{'i386': 'm'}>
+CONFIG_RADIO_CADET                              policy<{'i386': 'm'}>
+CONFIG_RADIO_GEMTEK                             policy<{'i386': 'm'}>
+CONFIG_RADIO_ISA                                policy<{'i386': 'm'}>
+CONFIG_RADIO_MAXIRADIO                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RADIO_MIROPCM20                          policy<{'i386': 'm'}>
+CONFIG_RADIO_RTRACK                             policy<{'i386': 'm'}>
+CONFIG_RADIO_RTRACK2                            policy<{'i386': 'm'}>
+CONFIG_RADIO_SAA7706H                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RADIO_SF16FMI                            policy<{'i386': 'm'}>
+CONFIG_RADIO_SF16FMR2                           policy<{'i386': 'm'}>
+CONFIG_RADIO_SHARK                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RADIO_SHARK2                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RADIO_SI470X                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RADIO_SI4713                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RADIO_SI476X                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RADIO_TEA575X                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RADIO_TEA5764                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RADIO_TEF6862                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RADIO_TERRATEC                           policy<{'i386': 'm'}>
+CONFIG_RADIO_TIMBERDALE                         policy<{'i386': 'm'}>
+CONFIG_RADIO_TRUST                              policy<{'i386': 'm'}>
+CONFIG_RADIO_TYPHOON                            policy<{'i386': 'm'}>
+CONFIG_RADIO_WL1273                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RADIO_WL128X                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RADIO_ZOLTRIX                            policy<{'i386': 'm'}>
+CONFIG_RAID6_PQ                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_RAID6_PQ_BENCHMARK                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_RAID_ATTRS                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_RANDOM32_SELFTEST                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_RANDOMIZE_BASE                           policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_RANDOMIZE_MEMORY                         policy<{'amd64': 'y'}>
+CONFIG_RANDOMIZE_MEMORY_PHYSICAL_PADDING        policy<{'amd64': '0xa'}>
+CONFIG_RANDOMIZE_MODULE_REGION_FULL             policy<{'arm64': 'y'}>
+CONFIG_RANDOM_TRUST_BOOTLOADER                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_RANDOM_TRUST_CPU                         policy<{'amd64': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_RAPIDIO                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_RAPIDIO_CHMAN                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RAPIDIO_CPS_GEN2                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RAPIDIO_CPS_XX                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RAPIDIO_DEBUG                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_RAPIDIO_DISC_TIMEOUT                     policy<{'amd64': '30', 'arm64': '30', 'armhf': '30', 'i386': '30', 'ppc64el': '30'}>
+CONFIG_RAPIDIO_DMA_ENGINE                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RAPIDIO_ENABLE_RX_TX_PORTS               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_RAPIDIO_ENUM_BASIC                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RAPIDIO_MPORT_CDEV                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RAPIDIO_RXS_GEN3                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RAPIDIO_TSI568                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RAPIDIO_TSI57X                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RAPIDIO_TSI721                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_RAS                                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_RASPBERRYPI_FIRMWARE                     policy<{'arm64': 'y'}>
+CONFIG_RASPBERRYPI_POWER                        policy<{'arm64': 'y'}>
+CONFIG_RAS_CEC                                  policy<{'amd64': 'y'}>
+CONFIG_RAS_CEC_DEBUG                            policy<{'amd64': 'n'}>
+CONFIG_RATIONAL                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RAVB                                     policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_RAVE_SP_CORE                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_RAVE_SP_EEPROM                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RAVE_SP_WATCHDOG                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RAW_DRIVER                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_RBTREE_TEST                              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_RCAR_DMAC                                policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_RCAR_GEN3_THERMAL                        policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_RCAR_GYRO_ADC                            policy<{'armhf': 'm'}>
+CONFIG_RCAR_THERMAL                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_RCU_CPU_STALL_TIMEOUT                    policy<{'amd64': '60', 'arm64': '60', 'armhf': '60', 'i386': '60', 'ppc64el': '21', 's390x': '21'}>
+CONFIG_RCU_EQS_DEBUG                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_RCU_EXPERT                               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_RCU_NEED_SEGCBLIST                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_RCU_PERF_TEST                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_RCU_STALL_COMMON                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_RCU_TORTURE_TEST                         policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_RCU_TRACE                                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_RC_ATI_REMOTE                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RC_CORE                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_RC_DECODERS                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RC_DEVICES                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RC_LOOPBACK                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RC_MAP                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RC_XBOX_DVD                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RDA_INTC                                 policy<{'armhf': 'y'}>
+CONFIG_RDA_TIMER                                policy<{'armhf': 'y'}>
+CONFIG_RDMA_RXE                                 policy<{'amd64': 'm', 'arm64': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_RDMA_SIW                                 policy<{'amd64': 'm', 'arm64': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_RDS                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_RDS_DEBUG                                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_RDS_RDMA                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_RDS_TCP                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_RD_BZIP2                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_RD_GZIP                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_RD_LZ4                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_RD_LZMA                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_RD_LZO                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_RD_XZ                                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_READABLE_ASM                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_READ_ONLY_THP_FOR_FS                     policy<{'amd64': 'n', 'arm64': 'n', 'armhf-generic-lpae': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_REALTEK_AUTOPM                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_REALTEK_PHY                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_REBOOT_MODE                              policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_REED_SOLOMON                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'y', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REED_SOLOMON_DEC16                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_REED_SOLOMON_DEC8                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_REED_SOLOMON_ENC8                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_REED_SOLOMON_TEST                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_REGMAP                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_REGMAP_AC97                              policy<{'armhf-generic': 'm'}>
+CONFIG_REGMAP_I2C                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_REGMAP_I3C                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGMAP_IRQ                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_REGMAP_MMIO                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_REGMAP_SCCB                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGMAP_SLIMBUS                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGMAP_SPI                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_REGMAP_SPMI                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGMAP_W1                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_REGULATOR_88PG86X                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_88PM800                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_88PM8607                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_AAT2870                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_AB3100                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_ACT8865                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_ACT8945A                       policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_AD5398                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_ANATOP                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_ARIZONA_LDO1                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_ARIZONA_MICSUPP                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_AS3711                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_AS3722                         policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_AXP20X                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_BCM590XX                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_BD70528                        policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_BD718XX                        policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_BD9571MWV                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_CPCAP                          policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_DA903X                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_DA9052                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_DA9055                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_DA9062                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_DA9063                         policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_DA9210                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_DA9211                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_DEBUG                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_REGULATOR_FAN53555                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_GPIO                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_HI6421                         policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_HI6421V530                     policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_HI655X                         policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_REGULATOR_ISL6271A                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_ISL9305                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_LM363X                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_LOCHNAGAR                      policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_LP3971                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_LP3972                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_LP872X                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_LP873X                         policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_LP8755                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_LP87565                        policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_LP8788                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_LTC3589                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_LTC3676                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_MAX14577                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_MAX1586                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_MAX77620                       policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_MAX77650                       policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_MAX77686                       policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_MAX77693                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_MAX77802                       policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_MAX8649                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_MAX8660                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_MAX8907                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_MAX8925                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_MAX8952                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_MAX8973                        policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_MAX8997                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_MAX8998                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_MC13783                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_MC13892                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_MC13XXX_CORE                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_MCP16502                       policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_MT6311                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_MT6323                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_MT6380                         policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_REGULATOR_MT6397                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_PALMAS                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_PBIAS                          policy<{'armhf': 'm'}>
+CONFIG_REGULATOR_PCAP                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_PCF50633                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_PFUZE100                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_PV88060                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_PV88080                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_PV88090                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_PWM                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_QCOM_RPM                       policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_REGULATOR_QCOM_RPMH                      policy<{'arm64': 'm'}>
+CONFIG_REGULATOR_QCOM_SMD_RPM                   policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_REGULATOR_QCOM_SPMI                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_RC5T583                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_RK808                          policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_RN5T618                        policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_RT5033                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_S2MPA01                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_S2MPS11                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_S5M8767                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_SC2731                         policy<{'arm64': 'm'}>
+CONFIG_REGULATOR_SKY81452                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_SLG51000                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_STPMIC1                        policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_SY8106A                        policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_SY8824X                        policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_TI_ABB                         policy<{'armhf': 'y'}>
+CONFIG_REGULATOR_TPS51632                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_TPS6105X                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_TPS62360                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_TPS65023                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_TPS6507X                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_TPS65086                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_TPS65090                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_TPS65132                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_TPS65218                       policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_TPS6524X                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_TPS6586X                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_TPS65910                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_TPS65912                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_TPS80031                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_UNIPHIER                       policy<{'armhf': 'm'}>
+CONFIG_REGULATOR_USERSPACE_CONSUMER             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_VCTRL                          policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_VEXPRESS                       policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_REGULATOR_VIRTUAL_CONSUMER               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_WM831X                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_WM8350                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_WM8400                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REGULATOR_WM8994                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_REISERFS_CHECK                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_REISERFS_FS                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_REISERFS_FS_POSIX_ACL                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_REISERFS_FS_SECURITY                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_REISERFS_FS_XATTR                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_REISERFS_PROC_INFO                       policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_RELAY                                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_RELOCATABLE                              policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_RELOCATABLE_TEST                         policy<{'ppc64el': 'n'}>
+CONFIG_REMOTEPROC                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_RENESAS_DMA                              policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_RENESAS_INTC_IRQPIN                      policy<{'armhf': 'y'}>
+CONFIG_RENESAS_IRQC                             policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_RENESAS_OSTM                             policy<{'armhf': 'y'}>
+CONFIG_RENESAS_PHY                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_RENESAS_RZA1_IRQC                        policy<{'armhf': 'y'}>
+CONFIG_RENESAS_RZAWDT                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_RENESAS_USB_DMAC                         policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_RENESAS_WDT                              policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_RESET_ATTACK_MITIGATION                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_RESET_BERLIN                             policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_RESET_BRCMSTB                            policy<{'arm64': 'm'}>
+CONFIG_RESET_CONTROLLER                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_RESET_HISI                               policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_RESET_IMX7                               policy<{'arm64': 'y', 'armhf-generic': 'y'}>
+CONFIG_RESET_MESON                              policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_RESET_MESON_AUDIO_ARB                    policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_RESET_QCOM_AOSS                          policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_RESET_QCOM_PDC                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_RESET_SCMI                               policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_RESET_SIMPLE                             policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_RESET_SUNXI                              policy<{'arm64': 'y'}>
+CONFIG_RESET_TEGRA_BPMP                         policy<{'armhf-generic': 'y'}>
+CONFIG_RESET_TI_SCI                             policy<{'arm64': 'm'}>
+CONFIG_RESET_TI_SYSCON                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RESET_UNIPHIER                           policy<{'armhf': 'm'}>
+CONFIG_RESET_UNIPHIER_GLUE                      policy<{'armhf': 'm'}>
+CONFIG_RETPOLINE                                policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_RETU_WATCHDOG                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RFD77402                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RFD_FTL                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RFKILL                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_RFKILL_GPIO                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RFKILL_INPUT                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RFKILL_LEDS                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RFS_ACCEL                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_RING_BUFFER                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_RING_BUFFER_ALLOW_SWAP                   policy<{'amd64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_RING_BUFFER_BENCHMARK                    policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_RING_BUFFER_STARTUP_TEST                 policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_RIONET                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RIONET_RX_SIZE                           policy<{'amd64': '128', 'arm64': '128', 'armhf': '128', 'i386': '128', 'ppc64el': '128'}>
+CONFIG_RIONET_TX_SIZE                           policy<{'amd64': '128', 'arm64': '128', 'armhf': '128', 'i386': '128', 'ppc64el': '128'}>
+CONFIG_RMI4_2D_SENSOR                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RMI4_CORE                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_RMI4_F03                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RMI4_F03_SERIO                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RMI4_F11                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RMI4_F12                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RMI4_F30                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RMI4_F34                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RMI4_F54                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RMI4_F55                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RMI4_I2C                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RMI4_SMB                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RMI4_SPI                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RMNET                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RN5T618_WATCHDOG                         policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_ROCKCHIP_ANALOGIX_DP                     policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ROCKCHIP_CDN_DP                          policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ROCKCHIP_DW_HDMI                         policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ROCKCHIP_DW_MIPI_DSI                     policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ROCKCHIP_EFUSE                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_ROCKCHIP_GRF                             policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ROCKCHIP_INNO_HDMI                       policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ROCKCHIP_IODOMAIN                        policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_ROCKCHIP_IOMMU                           policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ROCKCHIP_LVDS                            policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ROCKCHIP_MBOX                            policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ROCKCHIP_PHY                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_ROCKCHIP_PM_DOMAINS                      policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ROCKCHIP_RGB                             policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ROCKCHIP_RK3066_HDMI                     policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ROCKCHIP_SARADC                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_ROCKCHIP_THERMAL                         policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_ROCKCHIP_TIMER                           policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_ROCKER                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ROCKETPORT                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RODATA_FULL_DEFAULT_ENABLED              policy<{'arm64': 'y'}>
+CONFIG_ROMFS_BACKED_BY_BLOCK                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ROMFS_BACKED_BY_BOTH                     policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_ROMFS_BACKED_BY_MTD                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_ROMFS_FS                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_ROMFS_ON_BLOCK                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ROSE                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RPCSEC_GSS_KRB5                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_RPMSG                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RPMSG_CHAR                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RPMSG_QCOM_GLINK_NATIVE                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RPMSG_QCOM_GLINK_RPM                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RPMSG_QCOM_GLINK_SMEM                    policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_RPMSG_QCOM_SMD                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_RPMSG_VIRTIO                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_RPR0521                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RPS                                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_RSEQ                                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_RSI_91X                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RSI_COEX                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RSI_DEBUGFS                              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_RSI_SDIO                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RSI_USB                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RST_RCAR                                 policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_RT2400PCI                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RT2500PCI                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RT2500USB                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RT2800PCI                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RT2800PCI_RT3290                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RT2800PCI_RT33XX                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RT2800PCI_RT35XX                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RT2800PCI_RT53XX                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RT2800USB                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RT2800USB_RT33XX                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RT2800USB_RT3573                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RT2800USB_RT35XX                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RT2800USB_RT53XX                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RT2800USB_RT55XX                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RT2800USB_UNKNOWN                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RT2800_LIB                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RT2800_LIB_MMIO                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RT2X00                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RT2X00_DEBUG                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_RT2X00_LIB                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RT2X00_LIB_CRYPTO                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RT2X00_LIB_DEBUGFS                       policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_RT2X00_LIB_FIRMWARE                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RT2X00_LIB_LEDS                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RT2X00_LIB_MMIO                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RT2X00_LIB_PCI                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RT2X00_LIB_USB                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RT61PCI                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RT73USB                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTAS_ERROR_LOGGING                       policy<{'ppc64el': 'y'}>
+CONFIG_RTAS_FLASH                               policy<{'ppc64el': 'm'}>
+CONFIG_RTAS_PROC                                policy<{'ppc64el': 'y'}>
+CONFIG_RTC_CLASS                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RTC_DEBUG                                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_RTC_DRV_88PM80X                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_88PM860X                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_AB3100                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_ABB5ZES3                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_ABEOZ9                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_ABX80X                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_AM1805                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_ARMADA38X                        policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_RTC_DRV_AS3722                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_ASPEED                           policy<{'armhf': 'm'}>
+CONFIG_RTC_DRV_BD70528                          policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_BQ32K                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_BQ4802                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_BRCMSTB                          policy<{'arm64': 'm'}>
+CONFIG_RTC_DRV_CADENCE                          policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_CPCAP                            policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_CROS_EC                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_RTC_DRV_DA9052                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_DA9055                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_DA9063                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_DS1286                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_DS1302                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_DS1305                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_DS1307                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_DS1307_CENTURY                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RTC_DRV_DS1343                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_DS1347                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_DS1374                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_DS1374_WDT                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RTC_DRV_DS1390                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_DS1511                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_DS1553                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_DS1672                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_DS1685                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RTC_DRV_DS1685_FAMILY                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_DS1689                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_RTC_DRV_DS17285                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_RTC_DRV_DS1742                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_DS17485                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_RTC_DRV_DS17885                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_RTC_DRV_DS2404                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_DS3232                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_DS3232_HWMON                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RTC_DRV_EM3027                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_FM3130                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_FSL_FTM_ALARM                    policy<{'arm64': 'm'}>
+CONFIG_RTC_DRV_FTRTC010                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_GENERIC                          policy<{'ppc64el': 'y'}>
+CONFIG_RTC_DRV_HID_SENSOR_TIME                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_HYM8563                          policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_IMXDI                            policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_RTC_DRV_IMX_SC                           policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_RTC_DRV_ISL12022                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_ISL12026                         policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_ISL1208                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_LP8788                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_M41T80                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_M41T80_WDT                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RTC_DRV_M41T93                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_M41T94                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_M48T35                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_M48T59                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_M48T86                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_MAX6900                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_MAX6902                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_MAX6916                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_MAX77686                         policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_MAX8907                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_MAX8925                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_MAX8997                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_MAX8998                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_MC13XXX                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_MCP795                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_MESON                            policy<{'armhf': 'm'}>
+CONFIG_RTC_DRV_MESON_VRTC                       policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_RTC_DRV_MSM6242                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_MT6397                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_MT7622                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_RTC_DRV_MV                               policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_RTC_DRV_MXC                              policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_RTC_DRV_MXC_V2                           policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_RTC_DRV_OMAP                             policy<{'armhf': 'y'}>
+CONFIG_RTC_DRV_OPAL                             policy<{'ppc64el': 'y'}>
+CONFIG_RTC_DRV_PALMAS                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_PCAP                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_PCF2123                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_PCF2127                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_PCF50633                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_PCF85063                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_PCF8523                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf-generic': 'y', 'armhf-generic-lpae': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_PCF85363                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_PCF8563                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_PCF8583                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_PL030                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_RTC_DRV_PL031                            policy<{'arm64': 'm', 'armhf': 'y'}>
+CONFIG_RTC_DRV_PM8XXX                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_RTC_DRV_R7301                            policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_R9701                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_RC5T583                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_RK808                            policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_RP5C01                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_RS5C348                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_RS5C372                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_RTD119X                          policy<{'arm64': 'y'}>
+CONFIG_RTC_DRV_RV3028                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_RV3029C2                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_RV3029_HWMON                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RTC_DRV_RV8803                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_RX4581                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_RX6110                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_RX8010                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_RX8025                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_RX8581                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_S35390A                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_S3C                              policy<{'armhf': 'y'}>
+CONFIG_RTC_DRV_S5M                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_SC27XX                           policy<{'arm64': 'm'}>
+CONFIG_RTC_DRV_SD3078                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_SH                               policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_RTC_DRV_SNVS                             policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_STK17TA8                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_SUN6I                            policy<{'arm64': 'y'}>
+CONFIG_RTC_DRV_TEGRA                            policy<{'armhf-generic': 'm'}>
+CONFIG_RTC_DRV_TEST                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_RTC_DRV_TPS6586X                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_TPS65910                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_TPS80031                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_V3020                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_VRTC                             policy<{'i386': 'm'}>
+CONFIG_RTC_DRV_WILCO_EC                         policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_RTC_DRV_WM831X                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_WM8350                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_X1205                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_DRV_XGENE                            policy<{'arm64': 'y'}>
+CONFIG_RTC_DRV_ZYNQMP                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_RTC_HCTOSYS                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RTC_HCTOSYS_DEVICE                       policy<{'amd64': '"rtc0"', 'arm64': '"rtc0"', 'armhf': '"rtc0"', 'i386': '"rtc0"', 'ppc64el': '"rtc0"'}>
+CONFIG_RTC_I2C_AND_SPI                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RTC_INTF_DEV                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RTC_INTF_DEV_UIE_EMUL                    policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_RTC_INTF_PROC                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RTC_INTF_SYSFS                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RTC_LIB                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RTC_MC146818_LIB                         policy<{'amd64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RTC_NVMEM                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RTC_SYSTOHC                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RTC_SYSTOHC_DEVICE                       policy<{'amd64': '"rtc0"', 'arm64': '"rtc0"', 'armhf': '"rtc0"', 'i386': '"rtc0"', 'ppc64el': '"rtc0"'}>
+CONFIG_RTD119X_WATCHDOG                         policy<{'arm64': 'y'}>
+CONFIG_RTL8180                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTL8187                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTL8187_LEDS                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RTL8188EE                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTL8192CE                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTL8192CU                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTL8192C_COMMON                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTL8192DE                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTL8192E                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTL8192EE                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTL8192SE                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTL8192U                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTL8723AE                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTL8723BE                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTL8723BS                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTL8723_COMMON                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTL8821AE                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTL8XXXU                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTL8XXXU_UNTESTED                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RTLBTCOEXIST                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTLLIB                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTLLIB_CRYPTO_CCMP                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTLLIB_CRYPTO_TKIP                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTLLIB_CRYPTO_WEP                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTLWIFI                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTLWIFI_DEBUG                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_RTLWIFI_PCI                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTLWIFI_USB                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTL_CARDS                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTS5208                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTW88                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTW88_8723DE                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RTW88_8822BE                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RTW88_8822CE                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RTW88_CORE                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTW88_DEBUG                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RTW88_DEBUGFS                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_RTW88_PCI                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_RTW88_REGD_USER_REG_HINTS                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_RT_MUTEXES                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_RUNTIME_TESTING_MENU                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_RWSEM_SPIN_ON_OWNER                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_RXKAD                                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_S2IO                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_S390                                     policy<{'s390x': 'y'}>
+CONFIG_S390_AP_IOMMU                            policy<{'s390x': 'y'}>
+CONFIG_S390_CCW_IOMMU                           policy<{'s390x': 'y'}>
+CONFIG_S390_GUEST                               policy<{'s390x': 'y'}>
+CONFIG_S390_HYPFS_FS                            policy<{'s390x': 'y'}>
+CONFIG_S390_IOMMU                               policy<{'s390x': 'y'}>
+CONFIG_S390_PRNG                                policy<{'s390x': 'm'}>
+CONFIG_S390_PTDUMP                              policy<{'s390x': 'y'}>
+CONFIG_S390_TAPE                                policy<{'s390x': 'm'}>
+CONFIG_S390_TAPE_34XX                           policy<{'s390x': 'm'}>
+CONFIG_S390_TAPE_3590                           policy<{'s390x': 'm'}>
+CONFIG_S390_VMUR                                policy<{'s390x': 'm'}>
+CONFIG_S3C2410_WATCHDOG                         policy<{'armhf': 'm'}>
+CONFIG_S5P_DEV_MFC                              policy<{'armhf': 'y'}>
+CONFIG_SAMPLES                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SAMPLE_CONFIGFS                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_SAMPLE_HW_BREAKPOINT                     policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_SAMPLE_KDB                               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_SAMPLE_KFIFO                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_SAMPLE_KOBJECT                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_SAMPLE_KPROBES                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_SAMPLE_LIVEPATCH                         policy<{'amd64': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_SAMPLE_QMI_CLIENT                        policy<{'arm64': 'n', 'armhf': 'n'}>
+CONFIG_SAMPLE_RPMSG_CLIENT                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_SAMPLE_TRACE_EVENTS                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_SAMPLE_VFIO_MDEV_MBOCHS                  policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_SAMPLE_VFIO_MDEV_MDPY                    policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_SAMPLE_VFIO_MDEV_MDPY_FB                 policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_SAMPLE_VFIO_MDEV_MTTY                    policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_SAMSUNG_LAPTOP                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SAMSUNG_MC                               policy<{'armhf': 'y'}>
+CONFIG_SAMSUNG_Q10                              policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SATA_ACARD_AHCI                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SATA_AHCI                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SATA_AHCI_SEATTLE                        policy<{'arm64': 'm'}>
+CONFIG_SATA_DWC                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SATA_DWC_DEBUG                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_SATA_DWC_OLD_DMA                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SATA_INIC162X                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SATA_MOBILE_LPM_POLICY                   policy<{'amd64': '3', 'arm64': '3', 'armhf': '3', 'i386': '3', 'ppc64el': '3'}>
+CONFIG_SATA_MV                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SATA_NV                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SATA_PMP                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SATA_PROMISE                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SATA_QSTOR                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SATA_RCAR                                policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SATA_SIL                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SATA_SIL24                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SATA_SIS                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SATA_SVW                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SATA_SX4                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SATA_ULI                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SATA_VIA                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SATA_VITESSE                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SATA_ZPODD                               policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_SBC7240_WDT                              policy<{'i386': 'm'}>
+CONFIG_SBC8360_WDT                              policy<{'i386': 'm'}>
+CONFIG_SBC_EPX_C3_WATCHDOG                      policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SBC_FITPC2_WATCHDOG                      policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SBITMAP                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SBNI                                     policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SBNI_MULTILINE                           policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_SBP_TARGET                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SC1200_WDT                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SC27XX_ADC                               policy<{'arm64': 'm'}>
+CONFIG_SC27XX_EFUSE                             policy<{'arm64': 'm'}>
+CONFIG_SC92031                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SCA3000                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SCANLOG                                  policy<{'ppc64el': 'm'}>
+CONFIG_SCC                                      policy<{'i386': 'm'}>
+CONFIG_SCC_DELAY                                policy<{'i386': 'n'}>
+CONFIG_SCC_TRXECHO                              policy<{'i386': 'n'}>
+CONFIG_SCHEDSTATS                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SCHED_AUTOGROUP                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SCHED_BOOK                               policy<{'s390x': 'y'}>
+CONFIG_SCHED_DEBUG                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SCHED_DRAWER                             policy<{'s390x': 'y'}>
+CONFIG_SCHED_HRTICK                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SCHED_INFO                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SCHED_MC                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_SCHED_MC_PRIO                            policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_SCHED_OMIT_FRAME_POINTER                 policy<{'amd64': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SCHED_SMT                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'n', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SCHED_STACK_END_CHECK                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SCHED_TOPOLOGY                           policy<{'s390x': 'y'}>
+CONFIG_SCHED_TRACER                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SCIF                                     policy<{'amd64': 'm'}>
+CONFIG_SCIF_BUS                                 policy<{'amd64': 'm'}>
+CONFIG_SCLP_CONSOLE                             policy<{'s390x': 'y'}>
+CONFIG_SCLP_TTY                                 policy<{'s390x': 'y'}>
+CONFIG_SCLP_VT220_CONSOLE                       policy<{'s390x': 'y'}>
+CONFIG_SCLP_VT220_TTY                           policy<{'s390x': 'y'}>
+CONFIG_SCM_BLOCK                                policy<{'s390x': 'm'}>
+CONFIG_SCM_BUS                                  policy<{'s390x': 'y'}>
+CONFIG_SCOM_DEBUGFS                             policy<{'ppc64el': 'y'}>
+CONFIG_SCR24X                                   policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SCSI                                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SCSI_3W_9XXX                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_3W_SAS                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_AACRAID                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_ACARD                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_ADVANSYS                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_AHA152X                             policy<{'i386': 'm'}>
+CONFIG_SCSI_AHA1542                             policy<{'i386': 'm'}>
+CONFIG_SCSI_AHA1740                             policy<{'amd64': '-', 'i386': 'm'}>
+CONFIG_SCSI_AIC79XX                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_AIC7XXX                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_AIC94XX                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_AM53C974                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_ARCMSR                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_BFA_FC                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_BNX2X_FCOE                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_BNX2_ISCSI                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_BUSLOGIC                            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SCSI_CHELSIO_FCOE                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_CONSTANTS                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SCSI_CXGB3_ISCSI                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_CXGB4_ISCSI                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_DC395x                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_DEBUG                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_SCSI_DH                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SCSI_DH_ALUA                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_SCSI_DH_EMC                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_SCSI_DH_HP_SW                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_SCSI_DH_RDAC                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_SCSI_DMA                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SCSI_DMX3191D                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_DPT_I2O                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_SCSI_ENCLOSURE                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SCSI_ESAS2R                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_FC_ATTRS                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_SCSI_FDOMAIN                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SCSI_FDOMAIN_ISA                         policy<{'i386': 'm'}>
+CONFIG_SCSI_FDOMAIN_PCI                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_FLASHPOINT                          policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_SCSI_GDTH                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_GENERIC_NCR5380                     policy<{'i386': 'm'}>
+CONFIG_SCSI_HISI_SAS                            policy<{'arm64': 'm'}>
+CONFIG_SCSI_HISI_SAS_PCI                        policy<{'arm64': 'm'}>
+CONFIG_SCSI_HPSA                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_HPTIOP                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_IBMVFC                              policy<{'ppc64el': 'm'}>
+CONFIG_SCSI_IBMVFC_TRACE                        policy<{'ppc64el': 'y'}>
+CONFIG_SCSI_IBMVSCSI                            policy<{'ppc64el': 'm'}>
+CONFIG_SCSI_IBMVSCSIS                           policy<{'ppc64el': 'm'}>
+CONFIG_SCSI_IMM                                 policy<{'amd64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SCSI_INIA100                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_INITIO                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_IPR                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SCSI_IPS                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_ISCI                                policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SCSI_ISCSI_ATTRS                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_SCSI_IZIP_EPP16                          policy<{'amd64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_SCSI_IZIP_SLOW_CTR                       policy<{'amd64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_SCSI_LOGGING                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SCSI_LOWLEVEL                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SCSI_LOWLEVEL_PCMCIA                     policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_SCSI_LPFC                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_LPFC_DEBUG_FS                       policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_SCSI_MOD                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SCSI_MPT2SAS                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_SCSI_MPT2SAS_MAX_SGE                     policy<{'amd64': '128', 'arm64': '128', 'armhf': '128', 'i386': '128', 'ppc64el': '128', 's390x': '128'}>
+CONFIG_SCSI_MPT3SAS                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_SCSI_MPT3SAS_MAX_SGE                     policy<{'amd64': '128', 'arm64': '128', 'armhf': '128', 'i386': '128', 'ppc64el': '128', 's390x': '128'}>
+CONFIG_SCSI_MVSAS                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_MVSAS_DEBUG                         policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_SCSI_MVSAS_TASKLET                       policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_SCSI_MVUMI                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_MYRB                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_MYRS                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SCSI_NETLINK                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SCSI_NSP32                               policy<{'armhf': 'm', 'i386': 'm'}>
+CONFIG_SCSI_PM8001                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_PMCRAID                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_PPA                                 policy<{'amd64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SCSI_PROC_FS                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SCSI_QLA_FC                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_QLA_ISCSI                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_QLOGIC_1280                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_QLOGIC_FAS                          policy<{'i386': 'm'}>
+CONFIG_SCSI_SAS_ATA                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SCSI_SAS_ATTRS                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_SCSI_SAS_HOST_SMP                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SCSI_SAS_LIBSAS                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_SCSI_SCAN_ASYNC                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SCSI_SIM710                              policy<{'amd64': '-', 'i386': 'm'}>
+CONFIG_SCSI_SMARTPQI                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SCSI_SNIC                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_SNIC_DEBUG_FS                       policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_SCSI_SPI_ATTRS                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_SCSI_SRP_ATTRS                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'y', 's390x': 'm'}>
+CONFIG_SCSI_STEX                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_SYM53C8XX_2                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS              policy<{'amd64': '16', 'arm64': '16', 'armhf': '16', 'i386': '16', 'ppc64el': '16'}>
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE       policy<{'amd64': '1', 'arm64': '1', 'armhf': '1', 'i386': '1', 'ppc64el': '1'}>
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS                  policy<{'amd64': '64', 'arm64': '64', 'armhf': '64', 'i386': '64', 'ppc64el': '64'}>
+CONFIG_SCSI_SYM53C8XX_MMIO                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SCSI_UFSHCD                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCSI_UFSHCD_PCI                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SCSI_UFSHCD_PLATFORM                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SCSI_UFS_BSG                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SCSI_UFS_CDNS_PLATFORM                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SCSI_UFS_DWC_TC_PCI                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SCSI_UFS_DWC_TC_PLATFORM                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SCSI_UFS_HISI                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SCSI_UFS_MEDIATEK                        policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SCSI_UFS_QCOM                            policy<{'arm64': 'm', 'armhf': 'n'}>
+CONFIG_SCSI_WD719X                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SCTP_COOKIE_HMAC_MD5                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SCTP_COOKIE_HMAC_SHA1                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SCTP_DBG_OBJCNT                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_SCTP_DEFAULT_COOKIE_HMAC_NONE            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SCx200                                   policy<{'i386': 'm'}>
+CONFIG_SCx200HR_TIMER                           policy<{'i386': 'm'}>
+CONFIG_SCx200_ACB                               policy<{'i386': 'm'}>
+CONFIG_SCx200_GPIO                              policy<{'i386': 'm'}>
+CONFIG_SCx200_WDT                               policy<{'i386': 'm'}>
+CONFIG_SDIO_UART                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SDLA                                     policy<{'i386': 'm'}>
+CONFIG_SDMA_VERBOSITY                           policy<{'amd64': 'n'}>
+CONFIG_SDM_CAMCC_845                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SDM_DISPCC_845                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SDM_GCC_660                              policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SDM_GCC_845                              policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SDM_GPUCC_845                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SDM_LPASSCC_845                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SDM_VIDEOCC_845                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SDR_MAX2175                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SDR_PLATFORM_DRIVERS                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SD_ADC_MODULATOR                         policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_SEALEVEL_4021                            policy<{'i386': 'm'}>
+CONFIG_SECCOMP                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SECCOMP_FILTER                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SECONDARY_TRUSTED_KEYRING                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SECTION_MISMATCH_WARN_ONLY               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SECURITY                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SECURITYFS                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SECURITY_APPARMOR                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SECURITY_APPARMOR_DEBUG                  policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_SECURITY_APPARMOR_HASH                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SECURITY_APPARMOR_HASH_DEFAULT           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SECURITY_DMESG_RESTRICT                  policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_SECURITY_INFINIBAND                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SECURITY_LOADPIN                         policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_SECURITY_LOCKDOWN_LSM                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SECURITY_LOCKDOWN_LSM_EARLY              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SECURITY_NETWORK                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SECURITY_NETWORK_XFRM                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SECURITY_PATH                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SECURITY_PERF_EVENTS_RESTRICT            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SECURITY_SELINUX                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SECURITY_SELINUX_AVC_STATS               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SECURITY_SELINUX_BOOTPARAM               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE      policy<{'amd64': '1', 'arm64': '1', 'armhf': '1', 'i386': '1', 'ppc64el': '1', 's390x': '1'}>
+CONFIG_SECURITY_SELINUX_DEVELOP                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SECURITY_SMACK                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SECURITY_SMACK_APPEND_SIGNALS            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SECURITY_SMACK_BRINGUP                   policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_SECURITY_SMACK_NETFILTER                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SECURITY_TOMOYO                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SECURITY_TOMOYO_ACTIVATION_TRIGGER       policy<{'amd64': '"/sbin/init"', 'arm64': '"/sbin/init"', 'armhf': '"/sbin/init"', 'i386': '"/sbin/init"', 'ppc64el': '"/sbin/init"', 's390x': '"/sbin/init"'}>
+CONFIG_SECURITY_TOMOYO_INSECURE_BUILTIN_SETTING policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_SECURITY_TOMOYO_MAX_ACCEPT_ENTRY         policy<{'amd64': '2048', 'arm64': '2048', 'armhf': '2048', 'i386': '2048', 'ppc64el': '2048', 's390x': '2048'}>
+CONFIG_SECURITY_TOMOYO_MAX_AUDIT_LOG            policy<{'amd64': '1024', 'arm64': '1024', 'armhf': '1024', 'i386': '1024', 'ppc64el': '1024', 's390x': '1024'}>
+CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER    policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_SECURITY_TOMOYO_POLICY_LOADER            policy<{'amd64': '"/sbin/tomoyo-init"', 'arm64': '"/sbin/tomoyo-init"', 'armhf': '"/sbin/tomoyo-init"', 'i386': '"/sbin/tomoyo-init"', 'ppc64el': '"/sbin/tomoyo-init"', 's390x': '"/sbin/tomoyo-init"'}>
+CONFIG_SECURITY_YAMA                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SELECT_MEMORY_MODEL                      policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SENSIRION_SGP30                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_ABITUGURU                        policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SENSORS_ABITUGURU3                       policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SENSORS_ACPI_POWER                       policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_SENSORS_AD7314                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_AD7414                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_AD7418                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_ADC128D818                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_ADCXX                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_ADM1021                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_ADM1025                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_ADM1026                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_ADM1029                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_ADM1031                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_ADM1275                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_ADM9240                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_ADS7828                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_ADS7871                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_ADT7310                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_ADT7410                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_ADT7411                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_ADT7462                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_ADT7470                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_ADT7475                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_ADT7X10                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_AHC1EC0_HWMON                    policy<{'amd64': 'm'}>
+CONFIG_SENSORS_AMC6821                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_APDS990X                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SENSORS_APPLESMC                         policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SENSORS_ARM_SCMI                         policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SENSORS_ARM_SCPI                         policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SENSORS_AS370                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_ASB100                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SENSORS_ASC7621                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_ASPEED                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_ATK0110                          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SENSORS_ATXP1                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_BH1770                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SENSORS_CORETEMP                         policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SENSORS_DA9052_ADC                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_DA9055                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_DELL_SMM                         policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SENSORS_DME1737                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_SENSORS_DS1621                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_DS620                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_EMC1403                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_EMC2103                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_EMC6W201                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_F71805F                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_SENSORS_F71882FG                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_SENSORS_F75375S                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_FAM15H_POWER                     policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SENSORS_FSCHMD                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SENSORS_FTSTEUTATES                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_G760A                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_G762                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_GL518SM                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_GL520SM                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_GPIO_FAN                         policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_HDAPS                            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SENSORS_HIH6130                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_HMC5843                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_HMC5843_I2C                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_HMC5843_SPI                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_I5500                            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SENSORS_I5K_AMB                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_IBMAEM                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_IBMPEX                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_IBMPOWERNV                       policy<{'ppc64el': 'm'}>
+CONFIG_SENSORS_IBM_CFFPS                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_IIO_HWMON                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_INA209                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_INA2XX                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_INA3221                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_INSPUR_IPSPS                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_IR35221                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_IR38064                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_IRPS5401                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_ISL29018                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_ISL29028                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_ISL68137                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_IT87                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_SENSORS_JC42                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_K10TEMP                          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SENSORS_K8TEMP                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SENSORS_LINEAGE                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_LIS3LV02D                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_LIS3_I2C                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SENSORS_LIS3_SPI                         policy<{'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_LM25066                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_LM3533                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_LM63                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_LM70                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_LM73                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_LM75                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_LM77                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_LM78                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_LM80                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_LM83                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_LM85                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_LM87                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_LM90                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_LM92                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_LM93                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_LM95234                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_LM95241                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_LM95245                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_LOCHNAGAR                        policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_LTC2945                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_LTC2978                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_LTC2978_REGULATOR                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SENSORS_LTC2990                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_LTC3815                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_LTC4151                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_LTC4215                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_LTC4222                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_LTC4245                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_LTC4260                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_LTC4261                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_MAX1111                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_MAX16064                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_MAX16065                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_MAX1619                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_MAX1668                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_MAX197                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_MAX20751                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_MAX31722                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_MAX31785                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_MAX31790                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_MAX34440                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_MAX6621                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_MAX6639                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_MAX6642                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_MAX6650                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_MAX6697                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_MAX8688                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_MC13783_ADC                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_MCP3021                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_MENF21BMC_HWMON                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_MLXREG_FAN                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_SENSORS_NCT6683                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_SENSORS_NCT6775                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_SENSORS_NCT7802                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_NCT7904                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_NPCM7XX                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_NTC_THERMISTOR                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_OCC_P8_I2C                       policy<{'arm64': 'n', 'armhf': 'n'}>
+CONFIG_SENSORS_OCC_P9_SBE                       policy<{'arm64': 'n', 'armhf': 'n'}>
+CONFIG_SENSORS_PC87360                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_SENSORS_PC87427                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_SENSORS_PCF8591                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_PMBUS                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_POWR1220                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_PWM_FAN                          policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_PXE1610                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_RASPBERRYPI_HWMON                policy<{'arm64': 'm'}>
+CONFIG_SENSORS_RM3100                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_RM3100_I2C                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_RM3100_SPI                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_SCH5627                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_SENSORS_SCH5636                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_SENSORS_SCH56XX_COMMON                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_SENSORS_SHT15                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_SHT21                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_SHT3x                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_SHTC1                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_SIS5595                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_SMM665                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_SMSC47B397                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_SENSORS_SMSC47M1                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_SENSORS_SMSC47M192                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_STTS751                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_TC654                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_TC74                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_THMC50                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_TMP102                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_TMP103                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_TMP108                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_TMP401                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_TMP421                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_TPS40422                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_TPS53679                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_TSL2550                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SENSORS_TSL2563                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_UCD9000                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_UCD9200                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_VEXPRESS                         policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SENSORS_VIA686A                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_VIA_CPUTEMP                      policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SENSORS_VT1211                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_SENSORS_VT8231                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_W83627EHF                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_SENSORS_W83627HF                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_SENSORS_W83773G                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_W83781D                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_W83791D                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_W83792D                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_W83793                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_W83795                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_W83795_FANCTRL                   policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_SENSORS_W83L785TS                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_W83L786NG                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_WM831X                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_WM8350                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SENSORS_XGENE                            policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_SENSORS_ZL6100                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SERIAL_8250                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SERIAL_8250_ACCENT                       policy<{'i386': 'm'}>
+CONFIG_SERIAL_8250_ASPEED_VUART                 policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_SERIAL_8250_BCM2835AUX                   policy<{'arm64': 'n'}>
+CONFIG_SERIAL_8250_BOCA                         policy<{'i386': 'm'}>
+CONFIG_SERIAL_8250_CONSOLE                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SERIAL_8250_CS                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SERIAL_8250_DEPRECATED_OPTIONS           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_SERIAL_8250_DETECT_IRQ                   policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_SERIAL_8250_DMA                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SERIAL_8250_DW                           policy<{'amd64': 'm', 'arm64': 'y', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SERIAL_8250_DWLIB                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SERIAL_8250_EM                           policy<{'armhf': 'n'}>
+CONFIG_SERIAL_8250_EXAR                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SERIAL_8250_EXAR_ST16C554                policy<{'i386': 'm'}>
+CONFIG_SERIAL_8250_EXTENDED                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SERIAL_8250_FINTEK                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'n', 'i386': 'y', 'ppc64el': 'n'}>
+CONFIG_SERIAL_8250_FOURPORT                     policy<{'i386': 'm'}>
+CONFIG_SERIAL_8250_FSL                          policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_SERIAL_8250_HUB6                         policy<{'i386': 'm'}>
+CONFIG_SERIAL_8250_LPSS                         policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SERIAL_8250_MANY_PORTS                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SERIAL_8250_MEN_MCB                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SERIAL_8250_MID                          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SERIAL_8250_MT6577                       policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_SERIAL_8250_NR_UARTS                     policy<{'amd64': '48', 'arm64': '48', 'armhf': '48', 'i386': '48', 'ppc64el': '48'}>
+CONFIG_SERIAL_8250_OMAP                         policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SERIAL_8250_PCI                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SERIAL_8250_PNP                          policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_SERIAL_8250_RSA                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SERIAL_8250_RT288X                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SERIAL_8250_RUNTIME_UARTS                policy<{'amd64': '32', 'arm64': '32', 'armhf': '32', 'i386': '32', 'ppc64el': '32'}>
+CONFIG_SERIAL_8250_SHARE_IRQ                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SERIAL_8250_UNIPHIER                     policy<{'armhf': 'm'}>
+CONFIG_SERIAL_ALTERA_JTAGUART                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SERIAL_ALTERA_UART                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SERIAL_ALTERA_UART_BAUDRATE              policy<{'amd64': '115200', 'arm64': '115200', 'armhf': '115200', 'i386': '115200', 'ppc64el': '115200'}>
+CONFIG_SERIAL_ALTERA_UART_MAXPORTS              policy<{'amd64': '4', 'arm64': '4', 'armhf': '4', 'i386': '4', 'ppc64el': '4'}>
+CONFIG_SERIAL_AMBA_PL010                        policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SERIAL_AMBA_PL011                        policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_SERIAL_AMBA_PL011_CONSOLE                policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_SERIAL_ARC                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SERIAL_ARC_NR_PORTS                      policy<{'amd64': '1', 'arm64': '1', 'armhf': '1', 'i386': '1', 'ppc64el': '1'}>
+CONFIG_SERIAL_BCM63XX                           policy<{'armhf': 'm'}>
+CONFIG_SERIAL_CONEXANT_DIGICOLOR                policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_SERIAL_CORE                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'm'}>
+CONFIG_SERIAL_CORE_CONSOLE                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SERIAL_EARLYCON                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST             policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_SERIAL_FSL_LINFLEXUART                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SERIAL_FSL_LPUART                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SERIAL_ICOM                              policy<{'ppc64el': 'm'}>
+CONFIG_SERIAL_IFX6X60                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_SERIAL_IMX                               policy<{'arm64': 'y', 'armhf-generic': 'y'}>
+CONFIG_SERIAL_IMX_CONSOLE                       policy<{'arm64': 'y', 'armhf-generic': 'y'}>
+CONFIG_SERIAL_IPOCTAL                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SERIAL_JSM                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SERIAL_KGDB_NMI                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SERIAL_MAX3100                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SERIAL_MAX310X                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SERIAL_MCTRL_GPIO                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SERIAL_MEN_Z135                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SERIAL_MESON                             policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_SERIAL_MESON_CONSOLE                     policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_SERIAL_MILBEAUT_USIO                     policy<{'armhf': 'm'}>
+CONFIG_SERIAL_MILBEAUT_USIO_PORTS               policy<{'armhf': '4'}>
+CONFIG_SERIAL_MSM                               policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_SERIAL_MSM_CONSOLE                       policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_SERIAL_MVEBU_CONSOLE                     policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_SERIAL_MVEBU_UART                        policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_SERIAL_NONSTANDARD                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_SERIAL_OF_PLATFORM                       policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_SERIAL_OMAP                              policy<{'armhf': 'y'}>
+CONFIG_SERIAL_OMAP_CONSOLE                      policy<{'armhf': 'y'}>
+CONFIG_SERIAL_OWL                               policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_SERIAL_OWL_CONSOLE                       policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_SERIAL_PCH_UART                          policy<{'i386': 'm'}>
+CONFIG_SERIAL_QCOM_GENI                         policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SERIAL_RDA                               policy<{'armhf': 'y'}>
+CONFIG_SERIAL_RDA_CONSOLE                       policy<{'armhf': 'y'}>
+CONFIG_SERIAL_RP2                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SERIAL_RP2_NR_UARTS                      policy<{'amd64': '32', 'arm64': '32', 'armhf': '32', 'i386': '32', 'ppc64el': '32'}>
+CONFIG_SERIAL_SAMSUNG                           policy<{'armhf': 'm'}>
+CONFIG_SERIAL_SAMSUNG_UARTS                     policy<{'armhf': '4'}>
+CONFIG_SERIAL_SAMSUNG_UARTS_4                   policy<{'armhf': 'y'}>
+CONFIG_SERIAL_SC16IS7XX                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SERIAL_SC16IS7XX_CORE                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SERIAL_SC16IS7XX_I2C                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SERIAL_SC16IS7XX_SPI                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SERIAL_SCCNXP                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_SERIAL_SCCNXP_CONSOLE                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SERIAL_SH_SCI_DMA                        policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_SERIAL_SH_SCI_NR_UARTS                   policy<{'arm64': '2', 'armhf': '2'}>
+CONFIG_SERIAL_SIFIVE                            policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_SERIAL_SPRD                              policy<{'arm64': 'm'}>
+CONFIG_SERIAL_ST_ASC                            policy<{'armhf': 'm'}>
+CONFIG_SERIAL_TEGRA                             policy<{'armhf-generic': 'm'}>
+CONFIG_SERIAL_TEGRA_TCU                         policy<{'armhf-generic': 'm'}>
+CONFIG_SERIAL_TIMBERDALE                        policy<{'i386': 'm'}>
+CONFIG_SERIAL_UARTLITE                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_SERIAL_UARTLITE_NR_UARTS                 policy<{'amd64': '1', 'arm64': '1', 'armhf': '1', 'i386': '1', 'ppc64el': '1', 's390x': '1'}>
+CONFIG_SERIAL_XILINX_PS_UART                    policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_SERIO                                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_SERIO_ALTERA_PS2                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SERIO_AMBAKMI                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SERIO_APBPS2                             policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_SERIO_ARC_PS2                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SERIO_CT82C710                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SERIO_GPIO_PS2                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SERIO_I8042                              policy<{'amd64': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SERIO_LIBPS2                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SERIO_NVEC_PS2                           policy<{'armhf-generic': 'm'}>
+CONFIG_SERIO_PARKBD                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SERIO_PCIPS2                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SERIO_PS2MULT                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SERIO_RAW                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SERIO_SERPORT                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SERIO_SUN4I_PS2                          policy<{'arm64': 'n'}>
+CONFIG_SERIO_XILINX_XPS_PS2                     policy<{'ppc64el': 'm'}>
+CONFIG_SFC                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SFC_FALCON                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SFC_FALCON_MTD                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SFC_MCDI_LOGGING                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SFC_MCDI_MON                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SFC_MTD                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SFC_SRIOV                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SFI                                      policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_SFP                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SGETMASK_SYSCALL                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SGI_GRU                                  policy<{'amd64': 'm'}>
+CONFIG_SGI_GRU_DEBUG                            policy<{'amd64': 'n'}>
+CONFIG_SGI_PARTITION                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_SGI_XP                                   policy<{'amd64': 'm'}>
+CONFIG_SGL_ALLOC                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SG_POOL                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SG_SPLIT                                 policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_SHIFT_FS                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_SHIFT_FS_POSIX_ACL                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SHMEM                                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SHUFFLE_PAGE_ALLOCATOR                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SH_ETH                                   policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SH_TIMER_CMT                             policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_SH_TIMER_MTU2                            policy<{'armhf': 'y'}>
+CONFIG_SH_TIMER_TMU                             policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_SI1133                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SI1145                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SI7005                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SI7020                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SIGNALFD                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SIGNATURE                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SIGNED_PE_FILE_VERIFICATION              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SIMPLE_GPIO                              policy<{'ppc64el': 'n'}>
+CONFIG_SIMPLE_PM_BUS                            policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_SIOX                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_SIOX_BUS_GPIO                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_SIS190                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SIS900                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SKB_EXTENSIONS                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SKFP                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SKGE                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SKGE_DEBUG                               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_SKGE_GENESIS                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SKY2                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SKY2_DEBUG                               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_SLAB                                     policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_SLAB_FREELIST_HARDENED                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SLAB_FREELIST_RANDOM                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SLAB_MERGE_DEFAULT                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SLHC                                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SLICOSS                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_SLIC_DS26522                             policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_SLIMBUS                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_SLIM_QCOM_CTRL                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_SLIM_QCOM_NGD_CTRL                       policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SLIP                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SLIP_COMPRESSED                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SLIP_MODE_SLIP6                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SLIP_SMART                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SLOB                                     policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_SLUB                                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SLUB_CPU_PARTIAL                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SLUB_DEBUG                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SLUB_DEBUG_ON                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_SLUB_MEMCG_SYSFS_ON                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SLUB_STATS                               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_SMARTJOYPLUS_FF                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SMC911X                                  policy<{'armhf': 'm'}>
+CONFIG_SMC9194                                  policy<{'i386': 'm'}>
+CONFIG_SMC91X                                   policy<{'arm64': 'y', 'armhf': 'm'}>
+CONFIG_SMP                                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SMP_ON_UP                                policy<{'armhf': 'y'}>
+CONFIG_SMSC37B787_WDT                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SMSC911X                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SMSC9420                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SMSC_PHY                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_SMSC_SCH311X_WDT                         policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SMSGIUCV                                 policy<{'s390x': 'y'}>
+CONFIG_SMSGIUCV_EVENT                           policy<{'s390x': 'm'}>
+CONFIG_SMS_SDIO_DRV                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SMS_SIANO_DEBUGFS                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SMS_SIANO_MDTV                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SMS_SIANO_RC                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SMS_USB_DRV                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SM_FTL                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SM_GCC_8150                              policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_AC97_CODEC                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_AC97_POWER_SAVE                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SND_AC97_POWER_SAVE_DEFAULT              policy<{'amd64': '0', 'arm64': '0', 'armhf': '0', 'i386': '0', 'ppc64el': '0'}>
+CONFIG_SND_AD1816A                              policy<{'i386': 'm'}>
+CONFIG_SND_AD1848                               policy<{'i386': 'm'}>
+CONFIG_SND_AD1889                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_ADLIB                                policy<{'i386': 'm'}>
+CONFIG_SND_ALI5451                              policy<{'amd64': 'm', 'armhf-generic-lpae': 'm', 'i386': 'm'}>
+CONFIG_SND_ALOOP                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_ALS100                               policy<{'i386': 'm'}>
+CONFIG_SND_ALS300                               policy<{'amd64': 'm', 'armhf-generic-lpae': 'm', 'i386': 'm'}>
+CONFIG_SND_ALS4000                              policy<{'amd64': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_ARM                                  policy<{'armhf': 'y'}>
+CONFIG_SND_ARMAACI                              policy<{'armhf': 'm'}>
+CONFIG_SND_ASIHPI                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_ATIIXP                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_ATIIXP_MODEM                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_ATMEL_SOC                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_AU8810                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_AU8820                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_AU8830                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_AUDIO_GRAPH_CARD                     policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_AW2                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_AZT1605                              policy<{'i386': 'm'}>
+CONFIG_SND_AZT2316                              policy<{'i386': 'm'}>
+CONFIG_SND_AZT2320                              policy<{'i386': 'm'}>
+CONFIG_SND_AZT3328                              policy<{'amd64': 'm', 'armhf-generic-lpae': 'm', 'i386': 'm'}>
+CONFIG_SND_BCD2000                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_BCM2835                              policy<{'arm64': 'm'}>
+CONFIG_SND_BCM2835_SOC_I2S                      policy<{'arm64': 'm'}>
+CONFIG_SND_BEBOB                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_BT87X                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_BT87X_OVERCLOCK                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_SND_CA0106                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_CMI8328                              policy<{'i386': 'm'}>
+CONFIG_SND_CMI8330                              policy<{'i386': 'm'}>
+CONFIG_SND_CMIPCI                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_COMPRESS_OFFLOAD                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'y', 'i386': 'm'}>
+CONFIG_SND_CS4231                               policy<{'i386': 'm'}>
+CONFIG_SND_CS4236                               policy<{'i386': 'm'}>
+CONFIG_SND_CS4281                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_CS46XX                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_CS46XX_NEW_DSP                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SND_CS5530                               policy<{'i386': 'm'}>
+CONFIG_SND_CS5535AUDIO                          policy<{'i386': 'm'}>
+CONFIG_SND_CTXFI                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_DARLA20                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_DARLA24                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_DEBUG                                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_SND_DESIGNWARE_I2S                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_SND_DESIGNWARE_PCM                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_SND_DICE                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_DMAENGINE_PCM                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'y', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_DMA_SGBUF                            policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_SND_DRIVERS                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SND_DUMMY                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_DYNAMIC_MINORS                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SND_ECHO3G                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_EMU10K1                              policy<{'amd64': 'm', 'armhf-generic-lpae': 'm', 'i386': 'm'}>
+CONFIG_SND_EMU10K1X                             policy<{'amd64': 'm', 'armhf-generic-lpae': 'm', 'i386': 'm'}>
+CONFIG_SND_EMU10K1_SEQ                          policy<{'amd64': 'm', 'armhf-generic-lpae': 'm', 'i386': 'm'}>
+CONFIG_SND_ENS1370                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_ENS1371                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_ES1688                               policy<{'i386': 'm'}>
+CONFIG_SND_ES18XX                               policy<{'i386': 'm'}>
+CONFIG_SND_ES1938                               policy<{'amd64': 'm', 'armhf-generic-lpae': 'm', 'i386': 'm'}>
+CONFIG_SND_ES1968                               policy<{'amd64': 'm', 'armhf-generic-lpae': 'm', 'i386': 'm'}>
+CONFIG_SND_ES1968_INPUT                         policy<{'amd64': 'y', 'armhf-generic-lpae': 'y', 'i386': 'y'}>
+CONFIG_SND_ES1968_RADIO                         policy<{'amd64': 'y', 'armhf-generic-lpae': 'y', 'i386': 'y'}>
+CONFIG_SND_FIREFACE                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_FIREWIRE                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SND_FIREWIRE_DIGI00X                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_FIREWIRE_LIB                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_FIREWIRE_MOTU                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_FIREWIRE_TASCAM                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_FIREWORKS                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_FM801                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_FM801_TEA575X_BOOL                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SND_GINA20                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_GINA24                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_GUSCLASSIC                           policy<{'i386': 'm'}>
+CONFIG_SND_GUSEXTREME                           policy<{'i386': 'm'}>
+CONFIG_SND_GUSMAX                               policy<{'i386': 'm'}>
+CONFIG_SND_HDA                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_HDA_ALIGNED_MMIO                     policy<{'armhf-generic': 'y'}>
+CONFIG_SND_HDA_CODEC_ANALOG                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_HDA_CODEC_CA0110                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_HDA_CODEC_CA0132                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_HDA_CODEC_CA0132_DSP                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SND_HDA_CODEC_CIRRUS                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_HDA_CODEC_CMEDIA                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_HDA_CODEC_CONEXANT                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_HDA_CODEC_HDMI                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_HDA_CODEC_REALTEK                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_HDA_CODEC_SI3054                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_HDA_CODEC_SIGMATEL                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_HDA_CODEC_VIA                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_HDA_COMPONENT                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SND_HDA_CORE                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_HDA_DSP_LOADER                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SND_HDA_EXT_CORE                         policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_HDA_GENERIC                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_HDA_HWDEP                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SND_HDA_I915                             policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_SND_HDA_INPUT_BEEP                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SND_HDA_INPUT_BEEP_MODE                  policy<{'amd64': '0', 'arm64': '0', 'armhf': '0', 'i386': '0', 'ppc64el': '0'}>
+CONFIG_SND_HDA_INTEL                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_HDA_PATCH_LOADER                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SND_HDA_PREALLOC_SIZE                    policy<{'amd64': '64', 'arm64': '64', 'armhf': '64', 'i386': '64', 'ppc64el': '64'}>
+CONFIG_SND_HDA_TEGRA                            policy<{'armhf-generic': 'm'}>
+CONFIG_SND_HDSP                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_HDSPM                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_HRTIMER                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_HWDEP                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_I2S_HI6210_I2S                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_ICE1712                              policy<{'amd64': 'm', 'armhf-generic-lpae': 'm', 'i386': 'm'}>
+CONFIG_SND_ICE1724                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_IMX_SOC                              policy<{'arm64': 'm', 'armhf-generic': 'y'}>
+CONFIG_SND_INDIGO                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_INDIGODJ                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_INDIGODJX                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_INDIGOIO                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_INDIGOIOX                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_INTEL8X0                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_INTEL8X0M                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_INTEL_DSP_CONFIG                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_INTEL_NHLT                           policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_SND_INTERWAVE                            policy<{'i386': 'm'}>
+CONFIG_SND_INTERWAVE_STB                        policy<{'i386': 'm'}>
+CONFIG_SND_ISA                                  policy<{'i386': 'y'}>
+CONFIG_SND_ISIGHT                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_JACK                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SND_JACK_INPUT_DEV                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SND_JAZZ16                               policy<{'i386': 'm'}>
+CONFIG_SND_KIRKWOOD_SOC                         policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_KIRKWOOD_SOC_ARMADA370_DB            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_KORG1212                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_LAYLA20                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_LAYLA24                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_LOLA                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_LX6464ES                             policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_MAESTRO3                             policy<{'amd64': 'm', 'armhf-generic-lpae': 'm', 'i386': 'm'}>
+CONFIG_SND_MAESTRO3_INPUT                       policy<{'amd64': 'y', 'armhf-generic-lpae': 'y', 'i386': 'y'}>
+CONFIG_SND_MAX_CARDS                            policy<{'amd64': '32', 'arm64': '32', 'armhf': '32', 'i386': '32', 'ppc64el': '32'}>
+CONFIG_SND_MESON_AXG_FIFO                       policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_MESON_AXG_FRDDR                      policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_MESON_AXG_PDM                        policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_MESON_AXG_SOUND_CARD                 policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_MESON_AXG_SPDIFIN                    policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_MESON_AXG_SPDIFOUT                   policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_MESON_AXG_TDMIN                      policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_MESON_AXG_TDMOUT                     policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_MESON_AXG_TDM_FORMATTER              policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_MESON_AXG_TDM_INTERFACE              policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_MESON_AXG_TODDR                      policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_MESON_CARD_UTILS                     policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_MESON_CODEC_GLUE                     policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_MESON_G12A_TOHDMITX                  policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_MIA                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_MIRO                                 policy<{'i386': 'm'}>
+CONFIG_SND_MIXART                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_MIXER_OSS                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_MONA                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_MPU401                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_MPU401_UART                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_MSND_CLASSIC                         policy<{'i386': 'm'}>
+CONFIG_SND_MSND_PINNACLE                        policy<{'i386': 'm'}>
+CONFIG_SND_MTPAV                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_MTS64                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_NM256                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_OPL3SA2                              policy<{'i386': 'm'}>
+CONFIG_SND_OPL3_LIB                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_OPL3_LIB_SEQ                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_OPL4_LIB                             policy<{'i386': 'm'}>
+CONFIG_SND_OPL4_LIB_SEQ                         policy<{'i386': 'm'}>
+CONFIG_SND_OPTI92X_AD1848                       policy<{'i386': 'm'}>
+CONFIG_SND_OPTI92X_CS4231                       policy<{'i386': 'm'}>
+CONFIG_SND_OPTI93X                              policy<{'i386': 'm'}>
+CONFIG_SND_OSSEMUL                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SND_OXFW                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_OXYGEN                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_OXYGEN_LIB                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_PCI                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SND_PCM                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'y', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_PCMCIA                               policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_SND_PCM_ELD                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SND_PCM_IEC958                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SND_PCM_TIMER                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SND_PCSP                                 policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_PCXHR                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_PDAUDIOCF                            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_PORTMAN2X4                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_PPC                                  policy<{'ppc64el': 'y'}>
+CONFIG_SND_PROC_FS                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SND_RAWMIDI                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_RIPTIDE                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_RME32                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_RME96                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_RME9652                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SAMSUNG_I2S                          policy<{'armhf': 'm'}>
+CONFIG_SND_SAMSUNG_PCM                          policy<{'armhf': 'm'}>
+CONFIG_SND_SAMSUNG_SPDIF                        policy<{'armhf': 'm'}>
+CONFIG_SND_SB16                                 policy<{'i386': 'm'}>
+CONFIG_SND_SB16_CSP                             policy<{'i386': 'y'}>
+CONFIG_SND_SB16_DSP                             policy<{'i386': 'm'}>
+CONFIG_SND_SB8                                  policy<{'i386': 'm'}>
+CONFIG_SND_SB8_DSP                              policy<{'i386': 'm'}>
+CONFIG_SND_SBAWE                                policy<{'i386': 'm'}>
+CONFIG_SND_SBAWE_SEQ                            policy<{'i386': 'm'}>
+CONFIG_SND_SB_COMMON                            policy<{'amd64': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SC6000                               policy<{'i386': 'm'}>
+CONFIG_SND_SEQUENCER                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SEQUENCER_OSS                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_SND_SEQ_DEVICE                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SEQ_DUMMY                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SEQ_HRTIMER_DEFAULT                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SND_SEQ_MIDI                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SEQ_MIDI_EMUL                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SEQ_MIDI_EVENT                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SEQ_VIRMIDI                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SERIAL_U16550                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SIMPLE_CARD                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SIMPLE_CARD_UTILS                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SIS7019                              policy<{'i386': 'm'}>
+CONFIG_SND_SOC_AC97_BUS                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SND_SOC_AC97_CODEC                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_ACPI                             policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_ACPI_INTEL_MATCH                 policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_ADAU1701                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_ADAU1761                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_ADAU1761_I2C                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_ADAU1761_SPI                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_ADAU17X1                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_ADAU7002                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_ADAU_UTILS                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_AK4104                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_AK4118                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_AK4458                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_AK4554                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_AK4613                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_AK4642                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_AK5386                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_AK5558                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_ALC5623                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_ALC5632                          policy<{'armhf-generic': 'm'}>
+CONFIG_SND_SOC_AMD_ACP                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_AMD_ACP3x                        policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_AMD_CZ_DA7219MX98357_MACH        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_AMD_CZ_RT5645_MACH               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_APQ8016_SBC                      policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_SOC_ARIZONA                          policy<{'armhf': 'm'}>
+CONFIG_SND_SOC_ARNDALE_RT5631_ALC5631           policy<{'armhf': 'm'}>
+CONFIG_SND_SOC_BD28623                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_BT_SCO                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_COMPRESS                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_SND_SOC_CPCAP                            policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_CROS_EC_CODEC                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_CS35L32                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_CS35L33                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_CS35L34                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_CS35L35                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_CS35L36                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_CS4265                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_CS4270                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_CS4271                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_CS4271_I2C                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_CS4271_SPI                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_CS42L42                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_CS42L51                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_CS42L51_I2C                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_CS42L52                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_CS42L56                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_CS42L73                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_CS42XX8                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_CS42XX8_I2C                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_CS43130                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_CS4341                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_CS4349                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_CS53L30                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_CX2072X                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_DA7213                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_DA7219                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_DAVINCI_MCASP                    policy<{'armhf': 'm'}>
+CONFIG_SND_SOC_DMIC                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_ES7134                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_ES7241                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_ES8316                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_ES8328                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_ES8328_I2C                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_ES8328_SPI                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_EUKREA_TLV320                    policy<{'armhf-generic': 'm'}>
+CONFIG_SND_SOC_FSL_ASOC_CARD                    policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_SND_SOC_FSL_ASRC                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_FSL_AUDMIX                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_FSL_ESAI                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_FSL_MICFIL                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_FSL_SAI                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_FSL_SPDIF                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_FSL_SSI                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf-generic': 'y', 'armhf-generic-lpae': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_FSL_UTILS                        policy<{'armhf-generic': 'm'}>
+CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SND_SOC_GTM601                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_HDAC_HDA                         policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_HDAC_HDMI                        policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_HDMI_CODEC                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_I2C_AND_SPI                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'y', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_IMG                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SND_SOC_IMG_I2S_IN                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_IMG_I2S_OUT                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_IMG_PARALLEL_OUT                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_IMG_PISTACHIO_INTERNAL_DAC       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_IMG_SPDIF_IN                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_IMG_SPDIF_OUT                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_IMX_AUDMIX                       policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_SND_SOC_IMX_AUDMUX                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf-generic': 'y', 'armhf-generic-lpae': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_IMX_ES8328                       policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_SND_SOC_IMX_MC13783                      policy<{'armhf-generic': 'm'}>
+CONFIG_SND_SOC_IMX_PCM_DMA                      policy<{'arm64': 'm', 'armhf-generic': 'y'}>
+CONFIG_SND_SOC_IMX_PCM_FIQ                      policy<{'armhf-generic': 'y'}>
+CONFIG_SND_SOC_IMX_SGTL5000                     policy<{'arm64': 'm', 'armhf-generic': 'y'}>
+CONFIG_SND_SOC_IMX_SPDIF                        policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_SND_SOC_IMX_SSI                          policy<{'armhf-generic': 'm'}>
+CONFIG_SND_SOC_INNO_RK3036                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_INTEL_APL                        policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_BDW_RT5677_MACH            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_BROADWELL_MACH             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH  policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_BXT_RT298_MACH             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_BYTCR_RT5640_MACH          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_BYTCR_RT5651_MACH          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_BYT_CHT_CX2072X_MACH       policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_BYT_CHT_DA7213_MACH        policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_BYT_CHT_ES8316_MACH        policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH       policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_SND_SOC_INTEL_CHT_BSW_MAX98090_TI_MACH   policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_CHT_BSW_NAU8824_MACH       policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_CHT_BSW_RT5645_MACH        policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_CHT_BSW_RT5672_MACH        policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_CML_LP_DA7219_MAX98357A_MACH policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_DA7219_MAX98357A_GENERIC   policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_GLK                        policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_GLK_RT5682_MAX98357A_MACH  policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_HASWELL                    policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_HASWELL_MACH               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_KBL                        policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_KBL_DA7219_MAX98357A_MACH  policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_KBL_DA7219_MAX98927_MACH   policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_KBL_RT5660_MACH            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH   policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_KBL_RT5663_RT5514_MAX98927_MACH policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_MACH                       policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_SND_SOC_INTEL_SKL                        policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_SKL_HDA_DSP_GENERIC_MACH   policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_SKL_NAU88L25_MAX98357A_MACH policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_SKL_NAU88L25_SSM4567_MACH  policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_SKL_RT286_MACH             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_SKYLAKE_COMMON             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_SKYLAKE_FAMILY             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_SKYLAKE_SSP_CLK            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_SOF_RT5682_MACH            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_SST                        policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_SST_ACPI                   policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_SST_FIRMWARE               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_INTEL_SST_TOPLEVEL               policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_SND_SOC_LOCHNAGAR_SC                     policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_LPASS_APQ8016                    policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_SOC_LPASS_CPU                        policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_SOC_LPASS_IPQ806X                    policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_SOC_LPASS_PLATFORM                   policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_SOC_MAX9759                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_MAX98088                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_MAX98090                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_MAX98095                         policy<{'armhf': 'm'}>
+CONFIG_SND_SOC_MAX98357A                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_MAX98373                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_MAX98504                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_MAX9860                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_MAX9867                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_MAX98927                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_MC13783                          policy<{'armhf-generic': 'm'}>
+CONFIG_SND_SOC_MEDIATEK                         policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_SOC_MIKROE_PROTO                     policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_MSM8916_WCD_ANALOG               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_MSM8916_WCD_DIGITAL              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_MSM8996                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_SOC_MT2701                           policy<{'arm64': 'n', 'armhf': 'n'}>
+CONFIG_SND_SOC_MT6351                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_MT6358                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_MT6797                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_SOC_MT6797_MT6351                    policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_SOC_MT8173                           policy<{'arm64': 'n', 'armhf': 'n'}>
+CONFIG_SND_SOC_MT8183                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_SOC_MT8183_DA7219_MAX98357A          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_SOC_MT8183_MT6358_TS3A227E_MAX98357A policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_SOC_MTK_BTCVSD                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_NAU8540                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_NAU8810                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_NAU8822                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_NAU8824                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_NAU8825                          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_NOKIA_RX51                       policy<{'armhf-generic': 'm'}>
+CONFIG_SND_SOC_ODROID                           policy<{'armhf': 'm'}>
+CONFIG_SND_SOC_OMAP3_PANDORA                    policy<{'armhf-generic': 'm'}>
+CONFIG_SND_SOC_OMAP3_TWL4030                    policy<{'armhf-generic': 'm'}>
+CONFIG_SND_SOC_OMAP_ABE_TWL6040                 policy<{'armhf-generic': 'm'}>
+CONFIG_SND_SOC_OMAP_DMIC                        policy<{'armhf-generic': 'm'}>
+CONFIG_SND_SOC_OMAP_MCBSP                       policy<{'armhf': 'm'}>
+CONFIG_SND_SOC_OMAP_MCPDM                       policy<{'armhf-generic': 'm'}>
+CONFIG_SND_SOC_PCM1681                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_PCM1789                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_PCM1789_I2C                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_PCM179X                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_PCM179X_I2C                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_PCM179X_SPI                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_PCM186X                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_PCM186X_I2C                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_PCM186X_SPI                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_PCM3060                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_PCM3060_I2C                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_PCM3060_SPI                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_PCM3168A                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_PCM3168A_I2C                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_PCM3168A_SPI                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_PCM512x                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_PCM512x_I2C                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_PCM512x_SPI                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_QCOM                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_SOC_QCOM_COMMON                      policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_SOC_QDSP6                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_SOC_QDSP6_ADM                        policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_SOC_QDSP6_AFE                        policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_SOC_QDSP6_AFE_DAI                    policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_SOC_QDSP6_ASM                        policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_SOC_QDSP6_ASM_DAI                    policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_SOC_QDSP6_COMMON                     policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_SOC_QDSP6_CORE                       policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_SOC_QDSP6_ROUTING                    policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_SOC_RCAR                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_SOC_RK3288_HDMI_ANALOG               policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_SOC_RK3328                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_RK3399_GRU_SOUND                 policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_SOC_RL6231                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_RL6347A                          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_ROCKCHIP                         policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_SOC_ROCKCHIP_I2S                     policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_SOC_ROCKCHIP_MAX98090                policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_SOC_ROCKCHIP_PDM                     policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_SOC_ROCKCHIP_RT5645                  policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_SOC_ROCKCHIP_SPDIF                   policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_SOC_RT286                            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_RT298                            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_RT5514                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_RT5514_SPI                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_RT5616                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_RT5631                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_RT5640                           policy<{'amd64': 'm', 'armhf-generic': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_RT5645                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_RT5651                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_RT5660                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_RT5663                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_RT5670                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_RT5677                           policy<{'amd64': 'm', 'armhf-generic': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_RT5677_SPI                       policy<{'amd64': 'm', 'armhf-generic': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_RT5682                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_SAMSUNG                          policy<{'armhf': 'm'}>
+CONFIG_SND_SOC_SAMSUNG_SMDK_SPDIF               policy<{'armhf': 'm'}>
+CONFIG_SND_SOC_SAMSUNG_SMDK_WM8994              policy<{'armhf': 'm'}>
+CONFIG_SND_SOC_SAMSUNG_TM2_WM5110               policy<{'armhf': 'm'}>
+CONFIG_SND_SOC_SDM845                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_SOC_SGTL5000                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf-generic': 'y', 'armhf-generic-lpae': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_SH4_FSI                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_SOC_SI476X                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_SIGMADSP                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_SIGMADSP_I2C                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_SIGMADSP_REGMAP                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_SIMPLE_AMPLIFIER                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_SIRF_AUDIO_CODEC                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_SMDK_WM8994_PCM                  policy<{'armhf': 'm'}>
+CONFIG_SND_SOC_SNOW                             policy<{'armhf': 'm'}>
+CONFIG_SND_SOC_SOF                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_SOF_ACPI                         policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_SOF_APOLLOLAKE                   policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_SOF_APOLLOLAKE_SUPPORT           policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_SND_SOC_SOF_BAYTRAIL                     policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_SOF_BAYTRAIL_SUPPORT             policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_SND_SOC_SOF_CANNONLAKE                   policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_SOF_CANNONLAKE_SUPPORT           policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_SND_SOC_SOF_COFFEELAKE                   policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_SOF_COFFEELAKE_SUPPORT           policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_SND_SOC_SOF_COMETLAKE_H                  policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_SOF_COMETLAKE_H_SUPPORT          policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_SND_SOC_SOF_COMETLAKE_LP                 policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_SOF_COMETLAKE_LP_SUPPORT         policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_SND_SOC_SOF_DEBUG                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_SND_SOC_SOF_ELKHARTLAKE                  policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_SOF_ELKHARTLAKE_SUPPORT          policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_SND_SOC_SOF_GEMINILAKE                   policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_SOF_GEMINILAKE_SUPPORT           policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_SND_SOC_SOF_HDA                          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_SOF_HDA_ALWAYS_ENABLE_DMI_L1     policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_SND_SOC_SOF_HDA_COMMON                   policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_SOF_HDA_LINK_BASELINE            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_SOF_ICELAKE                      policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_SOF_ICELAKE_SUPPORT              policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_SND_SOC_SOF_IMX8                         policy<{'arm64': 'm'}>
+CONFIG_SND_SOC_SOF_IMX8_SUPPORT                 policy<{'arm64': 'y'}>
+CONFIG_SND_SOC_SOF_IMX_TOPLEVEL                 policy<{'arm64': 'y'}>
+CONFIG_SND_SOC_SOF_INTEL_ACPI                   policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_SOF_INTEL_ATOM_HIFI_EP           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_SOF_INTEL_COMMON                 policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_SOF_INTEL_HIFI_EP_IPC            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_SOF_INTEL_PCI                    policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_SOF_INTEL_TOPLEVEL               policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_SND_SOC_SOF_MERRIFIELD                   policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_SOF_MERRIFIELD_SUPPORT           policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_SND_SOC_SOF_OF                           policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_SOF_OPTIONS                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_SOF_PCI                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE             policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_SND_SOC_SOF_STRICT_ABI_CHECKS            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_SND_SOC_SOF_TIGERLAKE                    policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_SOF_TIGERLAKE_SUPPORT            policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_SND_SOC_SOF_TOPLEVEL                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SND_SOC_SOF_XTENSA                       policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_SPDIF                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_SPRD                             policy<{'arm64': 'm'}>
+CONFIG_SND_SOC_SPRD_MCDT                        policy<{'arm64': 'y'}>
+CONFIG_SND_SOC_SSM2305                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_SSM2602                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_SSM2602_I2C                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_SSM2602_SPI                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_SSM4567                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_STA32X                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_STA350                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_STI_SAS                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_STORM                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SND_SOC_TAS2552                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_TAS5086                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_TAS571X                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_TAS5720                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_TAS6424                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_TDA7419                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_TEGRA                            policy<{'armhf-generic': 'm'}>
+CONFIG_SND_SOC_TEGRA20_AC97                     policy<{'armhf-generic': 'm'}>
+CONFIG_SND_SOC_TEGRA20_DAS                      policy<{'armhf-generic': 'm'}>
+CONFIG_SND_SOC_TEGRA20_I2S                      policy<{'armhf-generic': 'm'}>
+CONFIG_SND_SOC_TEGRA20_SPDIF                    policy<{'armhf-generic': 'm'}>
+CONFIG_SND_SOC_TEGRA30_AHUB                     policy<{'armhf-generic': 'm'}>
+CONFIG_SND_SOC_TEGRA30_I2S                      policy<{'armhf-generic': 'm'}>
+CONFIG_SND_SOC_TEGRA_ALC5632                    policy<{'armhf-generic': 'm'}>
+CONFIG_SND_SOC_TEGRA_MAX98090                   policy<{'armhf-generic': 'm'}>
+CONFIG_SND_SOC_TEGRA_RT5640                     policy<{'armhf-generic': 'm'}>
+CONFIG_SND_SOC_TEGRA_RT5677                     policy<{'armhf-generic': 'm'}>
+CONFIG_SND_SOC_TEGRA_SGTL5000                   policy<{'armhf-generic': 'm'}>
+CONFIG_SND_SOC_TEGRA_TRIMSLICE                  policy<{'armhf-generic': 'm'}>
+CONFIG_SND_SOC_TEGRA_WM8753                     policy<{'armhf-generic': 'm'}>
+CONFIG_SND_SOC_TEGRA_WM8903                     policy<{'armhf-generic': 'm'}>
+CONFIG_SND_SOC_TEGRA_WM9712                     policy<{'armhf-generic': 'm'}>
+CONFIG_SND_SOC_TFA9879                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_TI_EDMA_PCM                      policy<{'armhf': 'm'}>
+CONFIG_SND_SOC_TI_SDMA_PCM                      policy<{'armhf': 'm'}>
+CONFIG_SND_SOC_TLV320AIC23                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_TLV320AIC23_I2C                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_TLV320AIC23_SPI                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_TLV320AIC31XX                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_TLV320AIC32X4                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_TLV320AIC32X4_I2C                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_TLV320AIC32X4_SPI                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_SND_SOC_TLV320AIC3X                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_TOPOLOGY                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SND_SOC_TPA6130A2                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_TS3A227E                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_TSCS42XX                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_TSCS454                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_TWL4030                          policy<{'armhf-generic': 'm'}>
+CONFIG_SND_SOC_TWL6040                          policy<{'armhf-generic': 'm'}>
+CONFIG_SND_SOC_UDA1334                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_UNIPHIER                         policy<{'armhf': 'm'}>
+CONFIG_SND_SOC_UNIPHIER_AIO                     policy<{'armhf': 'm'}>
+CONFIG_SND_SOC_UNIPHIER_EVEA_CODEC              policy<{'armhf': 'm'}>
+CONFIG_SND_SOC_UNIPHIER_LD11                    policy<{'armhf': 'm'}>
+CONFIG_SND_SOC_UNIPHIER_PXS2                    policy<{'armhf': 'm'}>
+CONFIG_SND_SOC_WCD9335                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_WM5110                           policy<{'armhf': 'm'}>
+CONFIG_SND_SOC_WM8510                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_WM8523                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_WM8524                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_WM8580                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_WM8711                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_WM8728                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_WM8731                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_WM8737                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_WM8741                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_WM8750                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_WM8753                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_WM8770                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_WM8776                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_WM8782                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_WM8804                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_WM8804_I2C                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_WM8804_SPI                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_WM8903                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_WM8904                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_WM8960                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_WM8962                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_WM8974                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_WM8978                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_WM8985                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_WM8994                           policy<{'armhf': 'm'}>
+CONFIG_SND_SOC_WM9712                           policy<{'armhf-generic': 'm'}>
+CONFIG_SND_SOC_WM_ADSP                          policy<{'armhf': 'm'}>
+CONFIG_SND_SOC_WM_HUBS                          policy<{'armhf': 'm'}>
+CONFIG_SND_SOC_XILINX_AUDIO_FORMATTER           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_XILINX_I2S                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_XILINX_SPDIF                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_XTFPGA_I2S                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SOC_ZX_AUD96P22                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_SONICVIBES                           policy<{'amd64': 'm', 'armhf-generic-lpae': 'm', 'i386': 'm'}>
+CONFIG_SND_SPI                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SND_SSCAPE                               policy<{'i386': 'm'}>
+CONFIG_SND_SST_ATOM_HIFI2_PLATFORM              policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI         policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_PCI          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SST_IPC                              policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SST_IPC_ACPI                         policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SST_IPC_PCI                          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_SUN4I_CODEC                          policy<{'arm64': 'n'}>
+CONFIG_SND_SUN4I_I2S                            policy<{'arm64': 'n'}>
+CONFIG_SND_SUN4I_SPDIF                          policy<{'arm64': 'n'}>
+CONFIG_SND_SUN50I_CODEC_ANALOG                  policy<{'arm64': 'm'}>
+CONFIG_SND_SUN8I_ADDA_PR_REGMAP                 policy<{'arm64': 'm'}>
+CONFIG_SND_SUN8I_CODEC                          policy<{'arm64': 'm'}>
+CONFIG_SND_SUN8I_CODEC_ANALOG                   policy<{'arm64': 'm'}>
+CONFIG_SND_SUPPORT_OLD_API                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SND_SYNTH_EMUX                           policy<{'amd64': 'm', 'armhf-generic-lpae': 'm', 'i386': 'm'}>
+CONFIG_SND_TIMER                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'y', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_TRIDENT                              policy<{'amd64': 'm', 'armhf-generic-lpae': 'm', 'i386': 'm'}>
+CONFIG_SND_USB                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SND_USB_6FIRE                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_USB_AUDIO                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_USB_AUDIO_USE_MEDIA_CONTROLLER       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SND_USB_CAIAQ                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_USB_CAIAQ_INPUT                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SND_USB_HIFACE                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_USB_LINE6                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_USB_POD                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_USB_PODHD                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_USB_TONEPORT                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_USB_UA101                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_USB_US122L                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_USB_USX2Y                            policy<{'amd64': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_USB_VARIAX                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_VERBOSE_PRINTK                       policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_SND_VERBOSE_PROCFS                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SND_VIA82XX                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_VIA82XX_MODEM                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_VIRMIDI                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_VIRTUOSO                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_VMASTER                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SND_VX222                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_VXPOCKET                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SND_VX_LIB                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SND_WAVEFRONT                            policy<{'i386': 'm'}>
+CONFIG_SND_WSS_LIB                              policy<{'i386': 'm'}>
+CONFIG_SND_X86                                  policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_SND_XEN_FRONTEND                         policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_SND_YMFPCI                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SNI_AVE                                  policy<{'armhf': 'm'}>
+CONFIG_SNI_NETSEC                               policy<{'arm64': 'm'}>
+CONFIG_SOCIONEXT_SYNQUACER_PREITS               policy<{'arm64': 'y'}>
+CONFIG_SOCK_CGROUP_DATA                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SOCK_VALIDATE_XMIT                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SOC_AM33XX                               policy<{'armhf-generic': 'y', 'armhf-generic-lpae': 'n'}>
+CONFIG_SOC_AM43XX                               policy<{'armhf': 'n'}>
+CONFIG_SOC_ASPEED                               policy<{'armhf': 'y'}>
+CONFIG_SOC_BRCMSTB                              policy<{'arm64': 'y', 'armhf': 'n'}>
+CONFIG_SOC_BUS                                  policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_SOC_DRA7XX                               policy<{'armhf': 'y'}>
+CONFIG_SOC_EXYNOS5250                           policy<{'armhf': 'y'}>
+CONFIG_SOC_EXYNOS5260                           policy<{'armhf': 'y'}>
+CONFIG_SOC_EXYNOS5410                           policy<{'armhf': 'y'}>
+CONFIG_SOC_EXYNOS5420                           policy<{'armhf': 'y'}>
+CONFIG_SOC_EXYNOS5800                           policy<{'armhf': 'y'}>
+CONFIG_SOC_HAS_OMAP2_SDRC                       policy<{'armhf': 'y'}>
+CONFIG_SOC_HAS_REALTIME_COUNTER                 policy<{'armhf': 'y'}>
+CONFIG_SOC_IMX5                                 policy<{'armhf-generic': 'y'}>
+CONFIG_SOC_IMX50                                policy<{'armhf-generic': 'y'}>
+CONFIG_SOC_IMX51                                policy<{'armhf-generic': 'y'}>
+CONFIG_SOC_IMX53                                policy<{'armhf-generic': 'n'}>
+CONFIG_SOC_IMX6                                 policy<{'armhf-generic': 'y'}>
+CONFIG_SOC_IMX6Q                                policy<{'armhf-generic': 'y'}>
+CONFIG_SOC_IMX6SL                               policy<{'armhf-generic': 'y'}>
+CONFIG_SOC_IMX6SLL                              policy<{'armhf-generic': 'y'}>
+CONFIG_SOC_IMX6SX                               policy<{'armhf-generic': 'y'}>
+CONFIG_SOC_IMX6UL                               policy<{'armhf-generic': 'y'}>
+CONFIG_SOC_IMX7D                                policy<{'armhf-generic': 'y'}>
+CONFIG_SOC_IMX7D_CA7                            policy<{'armhf-generic': 'y'}>
+CONFIG_SOC_IMX7ULP                              policy<{'armhf-generic': 'y'}>
+CONFIG_SOC_LS1021A                              policy<{'armhf-generic': 'n'}>
+CONFIG_SOC_OMAP3430                             policy<{'armhf-generic': 'y'}>
+CONFIG_SOC_OMAP5                                policy<{'armhf': 'n'}>
+CONFIG_SOC_RENESAS                              policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_SOC_SAMSUNG                              policy<{'armhf': 'y'}>
+CONFIG_SOC_TEGRA_FLOWCTRL                       policy<{'armhf-generic': 'y'}>
+CONFIG_SOC_TEGRA_FUSE                           policy<{'armhf-generic': 'y'}>
+CONFIG_SOC_TEGRA_PMC                            policy<{'armhf-generic': 'y'}>
+CONFIG_SOC_TEGRA_POWERGATE_BPMP                 policy<{'armhf-generic': 'y'}>
+CONFIG_SOC_TI                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_SOC_TI81XX                               policy<{'armhf-generic': 'y'}>
+CONFIG_SOC_VF610                                policy<{'armhf-generic': 'y'}>
+CONFIG_SOFTLOCKUP_DETECTOR                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SOFT_WATCHDOG                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_SOFT_WATCHDOG_PRETIMEOUT                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SOLARIS_X86_PARTITION                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_SONYPI                                   policy<{'i386': 'm'}>
+CONFIG_SONYPI_COMPAT                            policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_SONY_FF                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SONY_LAPTOP                              policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SOUNDWIRE_CADENCE                        policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SOUNDWIRE_INTEL                          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SOUND_OSS_CORE                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SP5100_TCO                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SPAPR_TCE_IOMMU                          policy<{'ppc64el': 'y'}>
+CONFIG_SPARSEMEM                                policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SPARSEMEM_EXTREME                        policy<{'amd64': 'y', 'arm64': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SPARSEMEM_MANUAL                         policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SPARSEMEM_STATIC                         policy<{'i386': 'y'}>
+CONFIG_SPARSEMEM_VMEMMAP                        policy<{'amd64': 'y', 'arm64': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SPARSEMEM_VMEMMAP_ENABLE                 policy<{'amd64': 'y', 'arm64': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SPARSE_IRQ                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SPEAKUP                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPEAKUP_SYNTH_ACNTPC                     policy<{'i386': 'm'}>
+CONFIG_SPEAKUP_SYNTH_ACNTSA                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPEAKUP_SYNTH_APOLLO                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPEAKUP_SYNTH_AUDPTR                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPEAKUP_SYNTH_BNS                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPEAKUP_SYNTH_DECEXT                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPEAKUP_SYNTH_DECPC                      policy<{'i386': 'm'}>
+CONFIG_SPEAKUP_SYNTH_DECTLK                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPEAKUP_SYNTH_DTLK                       policy<{'i386': 'm'}>
+CONFIG_SPEAKUP_SYNTH_DUMMY                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPEAKUP_SYNTH_KEYPC                      policy<{'i386': 'm'}>
+CONFIG_SPEAKUP_SYNTH_LTLK                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPEAKUP_SYNTH_SOFT                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPEAKUP_SYNTH_SPKOUT                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPEAKUP_SYNTH_TXPRT                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPECTRE_BHI_AUTO                         policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_SPECTRE_BHI_OFF                          policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_SPECTRE_BHI_ON                           policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_SPI                                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_SPI_ALTERA                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPI_ARMADA_3700                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SPI_ASPEED_SMC                           policy<{'armhf': 'm'}>
+CONFIG_SPI_AXI_SPI_ENGINE                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPI_BCM2835                              policy<{'arm64': 'm'}>
+CONFIG_SPI_BCM2835AUX                           policy<{'arm64': 'm'}>
+CONFIG_SPI_BCM_QSPI                             policy<{'arm64': 'm'}>
+CONFIG_SPI_BITBANG                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPI_BUTTERFLY                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPI_CADENCE                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPI_CADENCE_QUADSPI                      policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SPI_DEBUG                                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_SPI_DESIGNWARE                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPI_DLN2                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPI_DW_MID_DMA                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SPI_DW_MMIO                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPI_DW_PCI                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPI_DYNAMIC                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SPI_FSL_DSPI                             policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_SPI_FSL_LIB                              policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_SPI_FSL_LPSPI                            policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_SPI_FSL_QUADSPI                          policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_SPI_FSL_SPI                              policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_SPI_GPIO                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPI_HISI_SFC                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SPI_HISI_SFC_V3XX                        policy<{'arm64': 'm'}>
+CONFIG_SPI_IMX                                  policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_SPI_LM70_LLP                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPI_LOOPBACK_TEST                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPI_MASTER                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SPI_MEM                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SPI_MESON_SPICC                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SPI_MESON_SPIFC                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SPI_MT65XX                               policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SPI_MTK_QUADSPI                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPI_MXIC                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPI_NPCM_FIU                             policy<{'armhf': 'm'}>
+CONFIG_SPI_NPCM_PSPI                            policy<{'armhf': 'm'}>
+CONFIG_SPI_NXP_FLEXSPI                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPI_OC_TINY                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPI_OMAP24XX                             policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_SPI_ORION                                policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SPI_PL022                                policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SPI_PXA2XX                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPI_PXA2XX_PCI                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_SPI_QCOM_GENI                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SPI_QCOM_QSPI                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SPI_QUP                                  policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SPI_ROCKCHIP                             policy<{'amd64': 'n', 'arm64': 'm', 'armhf': 'm', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_SPI_RSPI                                 policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SPI_S3C64XX                              policy<{'armhf': 'm'}>
+CONFIG_SPI_SC18IS602                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPI_SH_HSPI                              policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SPI_SH_MSIOF                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SPI_SIFIVE                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPI_SLAVE                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SPI_SLAVE_MT27XX                         policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SPI_SLAVE_SYSTEM_CONTROL                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPI_SLAVE_TIME                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPI_SPIDEV                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPI_SPRD                                 policy<{'arm64': 'm'}>
+CONFIG_SPI_SPRD_ADI                             policy<{'arm64': 'm'}>
+CONFIG_SPI_SUN4I                                policy<{'arm64': 'n'}>
+CONFIG_SPI_SUN6I                                policy<{'arm64': 'm'}>
+CONFIG_SPI_SYNQUACER                            policy<{'arm64': 'm'}>
+CONFIG_SPI_TEGRA114                             policy<{'armhf-generic': 'm'}>
+CONFIG_SPI_TEGRA20_SFLASH                       policy<{'armhf-generic': 'm'}>
+CONFIG_SPI_TEGRA20_SLINK                        policy<{'armhf-generic': 'm'}>
+CONFIG_SPI_THUNDERX                             policy<{'arm64': 'm'}>
+CONFIG_SPI_TI_QSPI                              policy<{'armhf': 'm'}>
+CONFIG_SPI_TLE62X0                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPI_TOPCLIFF_PCH                         policy<{'i386': 'm'}>
+CONFIG_SPI_UNIPHIER                             policy<{'armhf': 'm'}>
+CONFIG_SPI_XCOMM                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPI_XILINX                               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_SPI_XLP                                  policy<{'arm64': 'm'}>
+CONFIG_SPI_ZYNQMP_GQSPI                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SPLIT_PTLOCK_CPUS                        policy<{'amd64': '4', 'arm64': '4', 'armhf': '4', 'i386': '4', 'ppc64el': '4', 's390x': '4'}>
+CONFIG_SPMI                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SPMI_MSM_PMIC_ARB                        policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SPMI_PMIC_CLKDIV                         policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_SPRD_COMMON_CLK                          policy<{'arm64': 'm'}>
+CONFIG_SPRD_DMA                                 policy<{'arm64': 'm'}>
+CONFIG_SPRD_SC9860_CLK                          policy<{'arm64': 'm'}>
+CONFIG_SPRD_TIMER                               policy<{'arm64': 'y'}>
+CONFIG_SPRD_WATCHDOG                            policy<{'arm64': 'm'}>
+CONFIG_SPS30                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SQUASHFS_DECOMP_MULTI                    policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_SQUASHFS_DECOMP_SINGLE                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SQUASHFS_EMBEDDED                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_SQUASHFS_FILE_CACHE                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_SQUASHFS_FILE_DIRECT                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE             policy<{'amd64': '3', 'arm64': '3', 'armhf': '3', 'i386': '3', 'ppc64el': '3', 's390x': '3'}>
+CONFIG_SQUASHFS_LZ4                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SQUASHFS_LZO                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SQUASHFS_XATTR                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SQUASHFS_XZ                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SQUASHFS_ZLIB                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SQUASHFS_ZSTD                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SRAM                                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_SRAM_EXEC                                policy<{'armhf': 'y'}>
+CONFIG_SRCU                                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SRF04                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SRF08                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SSB                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SSB_B43_PCI_BRIDGE                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SSB_BLOCKIO                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SSB_DRIVER_GPIO                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SSB_DRIVER_PCICORE                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SSB_DRIVER_PCICORE_POSSIBLE              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SSB_PCIHOST                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SSB_PCIHOST_POSSIBLE                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SSB_PCMCIAHOST                           policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_SSB_PCMCIAHOST_POSSIBLE                  policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_SSB_POSSIBLE                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SSB_SDIOHOST                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SSB_SDIOHOST_POSSIBLE                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SSB_SPROM                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SSFDC                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SSI_PROTOCOL                             policy<{'armhf-generic': 'm'}>
+CONFIG_STACKPROTECTOR                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_STACKPROTECTOR_PER_TASK                  policy<{'arm64': 'y'}>
+CONFIG_STACKPROTECTOR_STRONG                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_STACKTRACE                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_STACKTRACE_SUPPORT                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_STACK_TRACER                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_STAGING                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_STAGING_APEX_DRIVER                      policy<{'amd64': 'm', 'arm64': 'm'}>
+CONFIG_STAGING_BOARD                            policy<{'arm64': 'n', 'armhf': 'n'}>
+CONFIG_STAGING_GASKET_FRAMEWORK                 policy<{'amd64': 'm', 'arm64': 'm'}>
+CONFIG_STAGING_MEDIA                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_STANDALONE                               policy<{'amd64': 'n', 'arm64': 'y', 'armhf': 'y', 'i386': 'n', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_STATIC_KEYS_SELFTEST                     policy<{'amd64': 'n', 'arm64': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_STATIC_USERMODEHELPER                    policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_STE10XP                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_STK3310                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_STK8312                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_STK8BA50                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_STM                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_STMMAC_ETH                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_STMMAC_PCI                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_STMMAC_PLATFORM                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_STMMAC_SELFTESTS                         policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_STMPE_ADC                                policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_STMPE_I2C                                policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_STMPE_SPI                                policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_STMP_DEVICE                              policy<{'arm64': 'y', 'armhf-generic': 'y'}>
+CONFIG_STM_DUMMY                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_STM_PROTO_BASIC                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_STM_PROTO_SYS_T                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_STM_SOURCE_CONSOLE                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_STM_SOURCE_FTRACE                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_STM_SOURCE_HEARTBEAT                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_STP                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_STPMIC1_WATCHDOG                         policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_STREAM_PARSER                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_STRICT_DEVMEM                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_STRICT_KERNEL_RWX                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_STRICT_MODULE_RWX                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_STRING_SELFTEST                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_STRIP_ASM_SYMS                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_STUB_CLK_HI3660                          policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_STUB_CLK_HI6220                          policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_STX104                                   policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_ST_UVIS25                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ST_UVIS25_I2C                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ST_UVIS25_SPI                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SUN4I_EMAC                               policy<{'arm64': 'n'}>
+CONFIG_SUN4I_GPADC                              policy<{'arm64': 'n'}>
+CONFIG_SUN50I_A64_CCU                           policy<{'arm64': 'y'}>
+CONFIG_SUN50I_DE2_BUS                           policy<{'arm64': 'y'}>
+CONFIG_SUN50I_ERRATUM_UNKNOWN1                  policy<{'arm64': 'y'}>
+CONFIG_SUN50I_H6_CCU                            policy<{'arm64': 'y'}>
+CONFIG_SUN50I_H6_R_CCU                          policy<{'arm64': 'y'}>
+CONFIG_SUN8I_A83T_CCU                           policy<{'arm64': 'y'}>
+CONFIG_SUN8I_DE2_CCU                            policy<{'arm64': 'y'}>
+CONFIG_SUN8I_H3_CCU                             policy<{'arm64': 'y'}>
+CONFIG_SUN8I_R_CCU                              policy<{'arm64': 'y'}>
+CONFIG_SUNDANCE                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SUNDANCE_MMIO                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_SUNGEM                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SUNGEM_PHY                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SUNRPC                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_SUNRPC_BACKCHANNEL                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SUNRPC_DEBUG                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES         policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_SUNRPC_GSS                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_SUNRPC_SWAP                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SUNRPC_XPRT_RDMA                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_SUNXI_CCU                                policy<{'arm64': 'y'}>
+CONFIG_SUNXI_RSB                                policy<{'arm64': 'm'}>
+CONFIG_SUNXI_SRAM                               policy<{'arm64': 'y'}>
+CONFIG_SUNXI_WATCHDOG                           policy<{'arm64': 'm'}>
+CONFIG_SUN_PARTITION                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_SURFACE3_WMI                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SURFACE_3_BUTTON                         policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SURFACE_PRO3_BUTTON                      policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SUSPEND                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SUSPEND_FREEZER                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_SUSPEND_SKIP_SYNC                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_SWAP                                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SWIOTLB                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf-generic-lpae': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SWIOTLB_XEN                              policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_SWPHY                                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SWP_EMULATE                              policy<{'armhf': 'y'}>
+CONFIG_SW_SYNC                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SX9500                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SXGBE_ETH                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SYNCLINK                                 policy<{'amd64': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SYNCLINKMP                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SYNCLINK_CS                              policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_SYNCLINK_GT                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SYNC_FILE                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SYN_COOKIES                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SYSCON_REBOOT_MODE                       policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_SYSCTL                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SYSCTL_EXCEPTION_TRACE                   policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SYSCTL_SYSCALL                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_SYSC_R8A7743                             policy<{'armhf': 'y'}>
+CONFIG_SYSC_R8A7745                             policy<{'armhf': 'y'}>
+CONFIG_SYSC_R8A77470                            policy<{'armhf': 'y'}>
+CONFIG_SYSC_R8A774A1                            policy<{'arm64': 'y'}>
+CONFIG_SYSC_R8A774C0                            policy<{'arm64': 'y'}>
+CONFIG_SYSC_R8A7779                             policy<{'armhf': 'y'}>
+CONFIG_SYSC_R8A7790                             policy<{'armhf': 'y'}>
+CONFIG_SYSC_R8A7791                             policy<{'armhf': 'y'}>
+CONFIG_SYSC_R8A7792                             policy<{'armhf': 'y'}>
+CONFIG_SYSC_R8A7794                             policy<{'armhf': 'y'}>
+CONFIG_SYSC_R8A7795                             policy<{'arm64': 'y'}>
+CONFIG_SYSC_R8A7796                             policy<{'arm64': 'y'}>
+CONFIG_SYSC_R8A77965                            policy<{'arm64': 'y'}>
+CONFIG_SYSC_R8A77970                            policy<{'arm64': 'y'}>
+CONFIG_SYSC_R8A77980                            policy<{'arm64': 'y'}>
+CONFIG_SYSC_R8A77990                            policy<{'arm64': 'y'}>
+CONFIG_SYSC_R8A77995                            policy<{'arm64': 'y'}>
+CONFIG_SYSC_RCAR                                policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_SYSC_RMOBILE                             policy<{'armhf': 'y'}>
+CONFIG_SYSFS                                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SYSFS_SYSCALL                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SYSTEMPORT                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_SYSTEM_BLACKLIST_HASH_LIST               policy<{'amd64': '""', 'arm64': '""', 'armhf': '""', 'i386': '""', 'ppc64el': '""', 's390x': '""'}>
+CONFIG_SYSTEM_BLACKLIST_KEYRING                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SYSTEM_DATA_VERIFICATION                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SYSTEM_EXTRA_CERTIFICATE                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SYSTEM_EXTRA_CERTIFICATE_SIZE            policy<{'amd64': '4096', 'arm64': '4096', 'armhf': '4096', 'i386': '4096', 'ppc64el': '4096', 's390x': '4096'}>
+CONFIG_SYSTEM_REVOCATION_KEYS                   policy<{'amd64': '"debian/canonical-revoked-certs.pem"', 'arm64': '"debian/canonical-revoked-certs.pem"', 'armhf': '"debian/canonical-revoked-certs.pem"', 'i386': '"debian/canonical-revoked-certs.pem"', 'ppc64el': '"debian/canonical-revoked-certs.pem"', 's390x': '"debian/canonical-revoked-certs.pem"'}>
+CONFIG_SYSTEM_REVOCATION_LIST                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SYSTEM_TRUSTED_KEYRING                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SYSTEM_TRUSTED_KEYS                      policy<{'amd64': '"debian/canonical-certs.pem"', 'arm64': '"debian/canonical-certs.pem"', 'armhf': '"debian/canonical-certs.pem"', 'i386': '"debian/canonical-certs.pem"', 'ppc64el': '"debian/canonical-certs.pem"', 's390x': '"debian/canonical-certs.pem"'}>
+CONFIG_SYSV68_PARTITION                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_SYSVIPC                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SYSVIPC_COMPAT                           policy<{'amd64': 'y', 'arm64': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SYSVIPC_SYSCTL                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_SYSV_FS                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_SYS_HYPERVISOR                           policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_SYS_SUPPORTS_APM_EMULATION               policy<{'armhf': 'y'}>
+CONFIG_SYS_SUPPORTS_EM_STI                      policy<{'armhf': 'y'}>
+CONFIG_SYS_SUPPORTS_HUGETLBFS                   policy<{'arm64': 'y', 'armhf-generic-lpae': 'y', 'ppc64el': 'y'}>
+CONFIG_SYS_SUPPORTS_SH_CMT                      policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_SYS_SUPPORTS_SH_MTU2                     policy<{'armhf': 'y'}>
+CONFIG_SYS_SUPPORTS_SH_TMU                      policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_T5403                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TABLET_SERIAL_WACOM4                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TABLET_USB_ACECAD                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TABLET_USB_AIPTEK                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TABLET_USB_GTCO                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TABLET_USB_HANWANG                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TABLET_USB_KBTAB                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TABLET_USB_PEGASUS                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TAHVO_USB                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TAHVO_USB_HOST_BY_DEFAULT                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_TAP                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_TARGET_CORE                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_TASKSTATS                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_TASKS_RCU                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_TASK_DELAY_ACCT                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_TASK_IO_ACCOUNTING                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_TASK_XACCT                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_TC1100_WMI                               policy<{'i386': 'm'}>
+CONFIG_TCG_ATMEL                                policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TCG_CRB                                  policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_TCG_FTPM_TEE                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_TCG_IBMVTPM                              policy<{'ppc64el': 'y'}>
+CONFIG_TCG_INFINEON                             policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_TCG_NSC                                  policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_TCG_TIS                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_TCG_TIS_CORE                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_TCG_TIS_SPI                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TCG_TIS_ST33ZP24                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TCG_TIS_ST33ZP24_I2C                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_TCG_TIS_ST33ZP24_SPI                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TCG_VTPM_PROXY                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_TCG_XEN                                  policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_TCIC                                     policy<{'i386': 'm'}>
+CONFIG_TCM_FC                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_TCM_FILEIO                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_TCM_IBLOCK                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_TCM_PSCSI                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_TCM_QLA2XXX                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TCM_QLA2XXX_DEBUG                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_TCM_USER2                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_TCP_CONG_ADVANCED                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_TCP_CONG_BBR                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_TCP_CONG_BIC                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_TCP_CONG_CDG                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_TCP_CONG_CUBIC                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_TCP_CONG_DCTCP                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_TCP_CONG_HSTCP                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_TCP_CONG_HTCP                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_TCP_CONG_HYBLA                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_TCP_CONG_ILLINOIS                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_TCP_CONG_LP                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_TCP_CONG_NV                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_TCP_CONG_SCALABLE                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_TCP_CONG_VEGAS                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_TCP_CONG_VENO                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_TCP_CONG_WESTWOOD                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_TCP_CONG_YEAH                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_TCP_MD5SIG                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_TCS3414                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TCS3472                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TEE                                      policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_TEGRA124_EMC                             policy<{'armhf-generic': 'y'}>
+CONFIG_TEGRA20_APB_DMA                          policy<{'armhf-generic': 'y'}>
+CONFIG_TEGRA20_EMC                              policy<{'armhf-generic': 'y'}>
+CONFIG_TEGRA210_ADMA                            policy<{'armhf-generic': 'm'}>
+CONFIG_TEGRA_ACONNECT                           policy<{'armhf-generic': 'm'}>
+CONFIG_TEGRA_AHB                                policy<{'armhf-generic': 'y'}>
+CONFIG_TEGRA_BPMP                               policy<{'armhf-generic': 'y'}>
+CONFIG_TEGRA_BPMP_THERMAL                       policy<{'armhf-generic': 'm'}>
+CONFIG_TEGRA_CLK_DFLL                           policy<{'armhf-generic': 'y'}>
+CONFIG_TEGRA_CLK_EMC                            policy<{'armhf-generic': 'y'}>
+CONFIG_TEGRA_GMI                                policy<{'armhf-generic': 'm'}>
+CONFIG_TEGRA_HOST1X                             policy<{'armhf-generic': 'm'}>
+CONFIG_TEGRA_HOST1X_FIREWALL                    policy<{'armhf-generic': 'y'}>
+CONFIG_TEGRA_HSP_MBOX                           policy<{'armhf-generic': 'y'}>
+CONFIG_TEGRA_IOMMU_GART                         policy<{'armhf-generic': 'y'}>
+CONFIG_TEGRA_IOMMU_SMMU                         policy<{'armhf-generic': 'y'}>
+CONFIG_TEGRA_IVC                                policy<{'armhf-generic': 'y'}>
+CONFIG_TEGRA_MC                                 policy<{'armhf-generic': 'y'}>
+CONFIG_TEGRA_SOCTHERM                           policy<{'armhf-generic': 'n'}>
+CONFIG_TEGRA_TIMER                              policy<{'armhf-generic': 'y'}>
+CONFIG_TEGRA_VDE                                policy<{'armhf-generic': 'm'}>
+CONFIG_TEGRA_WATCHDOG                           policy<{'armhf-generic': 'm'}>
+CONFIG_TEHUTI                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TELCLOCK                                 policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_TERANETICS_PHY                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_TEST_ASYNC_DRIVER_PROBE                  policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_TEST_BITFIELD                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_TEST_BITMAP                              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_TEST_BPF                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_TEST_FIRMWARE                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_TEST_HASH                                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_TEST_HEXDUMP                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_TEST_IDA                                 policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_TEST_KMOD                                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_TEST_KSTRTOX                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_TEST_LIST_SORT                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_TEST_LIVEPATCH                           policy<{'amd64': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_TEST_LKM                                 policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_TEST_MEMCAT_P                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_TEST_MEMINIT                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_TEST_OBJAGG                              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_TEST_OVERFLOW                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_TEST_PARMAN                              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_TEST_POWER                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TEST_PRINTF                              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_TEST_RHASHTABLE                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_TEST_SORT                                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_TEST_STACKINIT                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_TEST_STATIC_KEYS                         policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_TEST_STRING_HELPERS                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_TEST_STRSCPY                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_TEST_SYSCTL                              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_TEST_UDELAY                              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_TEST_USER_COPY                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_TEST_UUID                                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_TEST_VMALLOC                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_TEST_XARRAY                              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_TEXTSEARCH                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_TEXTSEARCH_BM                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_TEXTSEARCH_FSM                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_TEXTSEARCH_KMP                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_THERMAL                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS      policy<{'amd64': '0', 'arm64': '0', 'armhf': '0', 'i386': '0', 'ppc64el': '0'}>
+CONFIG_THERMAL_EMULATION                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_THERMAL_GOV_BANG_BANG                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_THERMAL_GOV_FAIR_SHARE                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_THERMAL_GOV_STEP_WISE                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_THERMAL_GOV_USER_SPACE                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_THERMAL_HWMON                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_THERMAL_MMIO                             policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_THERMAL_OF                               policy<{'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y'}>
+CONFIG_THERMAL_STATISTICS                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_THERMAL_WRITABLE_TRIPS                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_THINKPAD_ACPI                            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_THINKPAD_ACPI_ALSA_SUPPORT               policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_THINKPAD_ACPI_DEBUG                      policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_THINKPAD_ACPI_DEBUGFACILITIES            policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_THINKPAD_ACPI_HOTKEY_POLL                policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_THINKPAD_ACPI_UNSAFE_LEDS                policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_THINKPAD_ACPI_VIDEO                      policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_THP_SWAP                                 policy<{'amd64': 'y'}>
+CONFIG_THREAD_INFO_IN_TASK                      policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_THREAD_SHIFT                             policy<{'ppc64el': '14'}>
+CONFIG_THRUSTMASTER_FF                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_THUMB2_KERNEL                            policy<{'armhf': 'n'}>
+CONFIG_THUNDERBOLT                              policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_THUNDERBOLT_NET                          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_THUNDERX2_PMU                            policy<{'arm64': 'm'}>
+CONFIG_THUNDER_NIC_BGX                          policy<{'amd64': 'm', 'arm64': 'm', 'ppc64el': 'm'}>
+CONFIG_THUNDER_NIC_PF                           policy<{'amd64': 'm', 'arm64': 'm', 'ppc64el': 'm'}>
+CONFIG_THUNDER_NIC_RGX                          policy<{'amd64': 'm', 'arm64': 'm', 'ppc64el': 'm'}>
+CONFIG_THUNDER_NIC_VF                           policy<{'amd64': 'm', 'arm64': 'm', 'ppc64el': 'm'}>
+CONFIG_TICK_CPU_ACCOUNTING                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_TICK_ONESHOT                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_TIFM_7XX1                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TIFM_CORE                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_TIGON3                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TIGON3_HWMON                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_TIMB_DMA                                 policy<{'i386': 'm'}>
+CONFIG_TIMERFD                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_TIMER_ACPI                               policy<{'arm64': 'y'}>
+CONFIG_TIMER_IMX_SYS_CTR                        policy<{'arm64': 'y'}>
+CONFIG_TIMER_OF                                 policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_TIMER_PROBE                              policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_TINYDRM_HX8357D                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TINYDRM_ILI9225                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TINYDRM_ILI9341                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TINYDRM_MI0283QT                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TINYDRM_REPAPER                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TINYDRM_ST7586                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TINYDRM_ST7735R                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TIPC                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_TIPC_DIAG                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_TIPC_MEDIA_IB                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_TIPC_MEDIA_UDP                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_TI_ADC081C                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TI_ADC0832                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TI_ADC084S021                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TI_ADC108S102                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TI_ADC12138                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TI_ADC128S052                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TI_ADC161S626                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TI_ADS1015                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TI_ADS124S08                             policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_TI_ADS7950                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TI_ADS8344                               policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_TI_ADS8688                               policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_TI_AM335X_ADC                            policy<{'amd64': '-', 'arm64': 'm', 'armhf': 'm', 'i386': '-', 'ppc64el': '-'}>
+CONFIG_TI_CPPI41                                policy<{'armhf': 'm'}>
+CONFIG_TI_CPSW                                  policy<{'armhf': 'y'}>
+CONFIG_TI_CPSW_PHY_SEL                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_TI_CPTS                                  policy<{'armhf': 'y'}>
+CONFIG_TI_CPTS_MOD                              policy<{'armhf': 'y'}>
+CONFIG_TI_DAC082S085                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TI_DAC5571                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TI_DAC7311                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TI_DAC7612                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TI_DAVINCI_EMAC                          policy<{'armhf-generic': 'm'}>
+CONFIG_TI_DAVINCI_MDIO                          policy<{'armhf': 'y'}>
+CONFIG_TI_DMA_CROSSBAR                          policy<{'armhf': 'y'}>
+CONFIG_TI_EDMA                                  policy<{'armhf': 'y'}>
+CONFIG_TI_EMIF                                  policy<{'armhf': 'm'}>
+CONFIG_TI_EMIF_SRAM                             policy<{'armhf-generic': 'm'}>
+CONFIG_TI_MESSAGE_MANAGER                       policy<{'arm64': 'y'}>
+CONFIG_TI_PIPE3                                 policy<{'armhf': 'm'}>
+CONFIG_TI_SCI_CLK                               policy<{'arm64': 'm'}>
+CONFIG_TI_SCI_CLK_PROBE_FROM_FW                 policy<{'arm64': 'n'}>
+CONFIG_TI_SCI_INTA_IRQCHIP                      policy<{'arm64': 'y'}>
+CONFIG_TI_SCI_INTA_MSI_DOMAIN                   policy<{'arm64': 'y'}>
+CONFIG_TI_SCI_INTR_IRQCHIP                      policy<{'arm64': 'y'}>
+CONFIG_TI_SCI_PM_DOMAINS                        policy<{'arm64': 'm'}>
+CONFIG_TI_SCI_PROTOCOL                          policy<{'arm64': 'y'}>
+CONFIG_TI_SOC_THERMAL                           policy<{'armhf': 'm'}>
+CONFIG_TI_ST                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_TI_SYSC                                  policy<{'armhf': 'y'}>
+CONFIG_TI_THERMAL                               policy<{'armhf': 'y'}>
+CONFIG_TI_TLC4541                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TLAN                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TLS                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'n', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_TLS_DEVICE                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_TMD_HERMES                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TMP006                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TMP007                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TMPFS                                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_TMPFS_XATTR                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_TN3215                                   policy<{'s390x': 'y'}>
+CONFIG_TN3215_CONSOLE                           policy<{'s390x': 'y'}>
+CONFIG_TN3270                                   policy<{'s390x': 'y'}>
+CONFIG_TN3270_CONSOLE                           policy<{'s390x': 'y'}>
+CONFIG_TN3270_FS                                policy<{'s390x': 'm'}>
+CONFIG_TN3270_TTY                               policy<{'s390x': 'y'}>
+CONFIG_TOPSTAR_LAPTOP                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_TORTURE_TEST                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_TOSHIBA                                  policy<{'i386': 'n'}>
+CONFIG_TOSHIBA_BT_RFKILL                        policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_TOSHIBA_HAPS                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_TOSHIBA_WMI                              policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_TOUCHSCREEN_88PM860X                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_AD7877                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_AD7879                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_AD7879_I2C                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_AD7879_SPI                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_ADC                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_ADS7846                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_AR1021_I2C                   policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_ATMEL_MXT                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_ATMEL_MXT_T37                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_TOUCHSCREEN_AUO_PIXCIR                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_BU21013                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_BU21029                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_CHIPONE_ICN8318              policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_CHIPONE_ICN8505              policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_TOUCHSCREEN_COLIBRI_VF50                 policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_CY8CTMG110                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_CYTTSP4_CORE                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_CYTTSP4_I2C                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_CYTTSP4_SPI                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_CYTTSP_CORE                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_CYTTSP_I2C                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_CYTTSP_SPI                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_DA9034                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_DA9052                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_DMI                          policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_TOUCHSCREEN_DYNAPRO                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_EDT_FT5X06                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_EETI                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_EGALAX                       policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_EGALAX_SERIAL                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_EKTF2127                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_ELO                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_EXC3000                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_FUJITSU                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_GOODIX                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_GUNZE                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_HAMPSHIRE                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_HIDEEP                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_HTCPEN                       policy<{'i386': 'm'}>
+CONFIG_TOUCHSCREEN_ILI210X                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_IMX6UL_TSC                   policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_INEXIO                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_IPROC                        policy<{'arm64': 'm'}>
+CONFIG_TOUCHSCREEN_IQS5XX                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_MAX11801                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_MC13783                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_MCS5000                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_MELFAS_MIP4                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_MK712                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_MMS114                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_MTOUCH                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_PCAP                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_PENMOUNT                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_PIXCIR                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_PROPERTIES                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_TOUCHSCREEN_RASPBERRYPI_FW               policy<{'arm64': 'm'}>
+CONFIG_TOUCHSCREEN_RM_TS                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_ROHM_BU21023                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_S6SY761                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_SILEAD                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_SIS_I2C                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_ST1232                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_STMFTS                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_STMPE                        policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_SUN4I                        policy<{'arm64': 'n'}>
+CONFIG_TOUCHSCREEN_SUR40                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_SURFACE3_SPI                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_SX8654                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_TI_AM335X_TSC                policy<{'amd64': '-', 'arm64': 'm', 'armhf': 'm', 'i386': '-', 'ppc64el': '-'}>
+CONFIG_TOUCHSCREEN_TOUCHIT213                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_TOUCHRIGHT                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_TOUCHWIN                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_TPS6507X                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_TS4800                       policy<{'armhf-generic': 'm'}>
+CONFIG_TOUCHSCREEN_TSC2004                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_TSC2005                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_TSC2007                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_TSC2007_IIO                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_TOUCHSCREEN_TSC200X_CORE                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_TSC_SERIO                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_UCB1400                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_USB_3M                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_TOUCHSCREEN_USB_COMPOSITE                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_USB_DMC_TSC10                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_TOUCHSCREEN_USB_E2I                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_TOUCHSCREEN_USB_EASYTOUCH                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_TOUCHSCREEN_USB_EGALAX                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_TOUCHSCREEN_USB_ELO                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_TOUCHSCREEN_USB_ETT_TC45USB              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_TOUCHSCREEN_USB_ETURBO                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_TOUCHSCREEN_USB_GOTOP                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_TOUCHSCREEN_USB_GUNZE                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_TOUCHSCREEN_USB_IDEALTEK                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_TOUCHSCREEN_USB_IRTOUCH                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_TOUCHSCREEN_USB_ITM                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_TOUCHSCREEN_USB_JASTEC                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_TOUCHSCREEN_USB_NEXIO                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_TOUCHSCREEN_USB_PANJIT                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_TOUCHSCREEN_USB_ZYTRONIC                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_TOUCHSCREEN_WACOM_I2C                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_WACOM_W8001                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_WDT87XX_I2C                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_WM831X                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_WM9705                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_TOUCHSCREEN_WM9712                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_TOUCHSCREEN_WM9713                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_TOUCHSCREEN_WM97XX                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_ZET6223                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TOUCHSCREEN_ZFORCE                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TPL0102                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TPM_KEY_PARSER                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_TPS6105X                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_TPS65010                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_TPS6507X                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_TPS68470_PMIC_OPREGION                   policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_TQMX86_WDT                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_TRACEPOINTS                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_TRACEPOINT_BENCHMARK                     policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_TRACER_MAX_TRACE                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_TRACER_SNAPSHOT                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_TRACE_CLOCK                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_TRACE_EVAL_MAP_FILE                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_TRACE_IRQFLAGS_SUPPORT                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_TRACE_ROUTER                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TRACE_SINK                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_TRACING                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_TRACING_MAP                              policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_TRACING_SUPPORT                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_TRANSPARENT_HUGEPAGE                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf-generic-lpae': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS              policy<{'amd64': 'n', 'arm64': 'n', 'armhf-generic-lpae': 'n', 'i386': 'n', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_TRANSPARENT_HUGEPAGE_MADVISE             policy<{'amd64': 'y', 'arm64': 'y', 'armhf-generic-lpae': 'y', 'i386': 'y', 'ppc64el': 'n', 's390x': 'y'}>
+CONFIG_TRANSPARENT_HUGE_PAGECACHE               policy<{'amd64': 'y', 'arm64': 'y', 'armhf-generic-lpae': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_TREE_RCU                                 policy<{'amd64-generic': 'y', 'arm64': 'y', 'armhf': 'y', 'i386-generic': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_TREE_SRCU                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_TRUSTED_FOUNDATIONS                      policy<{'armhf': 'y'}>
+CONFIG_TRUSTED_KEYS                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_TS4800_IRQ                               policy<{'armhf-generic': 'm'}>
+CONFIG_TS4800_WATCHDOG                          policy<{'armhf-generic': 'm'}>
+CONFIG_TSL2583                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TSL2772                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TSL4531                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TSYS01                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TSYS02D                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TTPCI_EEPROM                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TTY                                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_TTY_PRINTK                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_TTY_PRINTK_LEVEL                         policy<{'amd64': '6', 'arm64': '6', 'armhf': '6', 'i386': '6', 'ppc64el': '6'}>
+CONFIG_TULIP                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TULIP_MMIO                               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_TULIP_MWI                                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_TULIP_NAPI                               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_TUN                                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_TUNE_DEFAULT                             policy<{'s390x': 'n'}>
+CONFIG_TUNE_Z10                                 policy<{'s390x': 'n'}>
+CONFIG_TUNE_Z13                                 policy<{'s390x': 'n'}>
+CONFIG_TUNE_Z14                                 policy<{'s390x': 'n'}>
+CONFIG_TUNE_Z15                                 policy<{'s390x': 'y'}>
+CONFIG_TUNE_Z196                                policy<{'s390x': 'n'}>
+CONFIG_TUNE_Z900                                policy<{'s390x': 'n'}>
+CONFIG_TUNE_Z990                                policy<{'s390x': 'n'}>
+CONFIG_TUNE_Z9_109                              policy<{'s390x': 'n'}>
+CONFIG_TUNE_ZEC12                               policy<{'s390x': 'n'}>
+CONFIG_TUN_VNET_CROSS_LE                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_TURRIS_MOX_RWTM                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_TWL4030_CORE                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_TWL4030_MADC                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TWL4030_POWER                            policy<{'armhf': 'y'}>
+CONFIG_TWL4030_USB                              policy<{'armhf': 'm'}>
+CONFIG_TWL4030_WATCHDOG                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TWL6030_GPADC                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TWL6030_USB                              policy<{'armhf': 'm'}>
+CONFIG_TWL6040_CORE                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_TYPEC                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TYPEC_DP_ALTMODE                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TYPEC_FUSB302                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TYPEC_MUX_PI3USB30532                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TYPEC_NVIDIA_ALTMODE                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TYPEC_RT1711H                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TYPEC_TCPCI                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TYPEC_TCPM                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TYPEC_TPS6598X                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TYPEC_UCSI                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_TYPHOON                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_UACCESS_WITH_MEMCPY                      policy<{'armhf': 'n'}>
+CONFIG_UBIFS_ATIME_SUPPORT                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_UBIFS_FS                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_UBIFS_FS_ADVANCED_COMPR                  policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_UBIFS_FS_AUTHENTICATION                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_UBIFS_FS_LZO                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_UBIFS_FS_SECURITY                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_UBIFS_FS_XATTR                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_UBIFS_FS_ZLIB                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_UBIFS_FS_ZSTD                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_UBSAN                                    policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_UBSAN_ALIGNMENT                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_UBUNTU_ODM_DRIVERS                       policy<{'amd64': 'y'}>
+CONFIG_UCB1400_CORE                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_UCLAMP_BUCKETS_COUNT                     policy<{'amd64': '5', 'arm64': '5', 'armhf': '5', 'i386': '5', 'ppc64el': '5'}>
+CONFIG_UCLAMP_TASK                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_UCLAMP_TASK_GROUP                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_UCS2_STRING                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y'}>
+CONFIG_UCSI_ACPI                                policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_UCSI_CCG                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_UDBG_RTAS_CONSOLE                        policy<{'ppc64el': 'n'}>
+CONFIG_UDF_FS                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_UDMABUF                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_UEFI_CPER                                policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_UEFI_CPER_ARM                            policy<{'arm64': 'y'}>
+CONFIG_UEFI_CPER_X86                            policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_UEVENT_HELPER                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_UEVENT_HELPER_PATH                       policy<{'amd64': '""', 'arm64': '""', 'armhf': '""', 'i386': '""', 'ppc64el': '""', 's390x': '""'}>
+CONFIG_UFS_DEBUG                                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_UFS_FS                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_UFS_FS_WRITE                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_UHID                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_UID16                                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 's390x': 'y'}>
+CONFIG_UIO                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_UIO_AEC                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_UIO_CIF                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_UIO_DMEM_GENIRQ                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_UIO_FSL_ELBC_GPCM                        policy<{'ppc64el': 'm'}>
+CONFIG_UIO_FSL_ELBC_GPCM_NETX5152               policy<{'ppc64el': 'n'}>
+CONFIG_UIO_HV_GENERIC                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_UIO_MF624                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_UIO_NETX                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_UIO_PCI_GENERIC                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_UIO_PDRV_GENIRQ                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_UIO_PRUSS                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_UIO_SERCOS3                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_ULI526X                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ULTRA                                    policy<{'i386': 'm'}>
+CONFIG_ULTRIX_PARTITION                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_UNCOMPRESS_INCLUDE                       policy<{'armhf': '"debug/uncompress.h"'}>
+CONFIG_UNICODE                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_UNICODE_NORMALIZATION_SELFTEST           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_UNINLINE_SPIN_UNLOCK                     policy<{'amd64-lowlatency': 'y', 'i386-lowlatency': 'y'}>
+CONFIG_UNIPHIER_EFUSE                           policy<{'armhf': 'm'}>
+CONFIG_UNIPHIER_MDMAC                           policy<{'armhf': 'm'}>
+CONFIG_UNIPHIER_SYSTEM_BUS                      policy<{'armhf': 'y'}>
+CONFIG_UNIPHIER_THERMAL                         policy<{'armhf': 'm'}>
+CONFIG_UNIPHIER_WATCHDOG                        policy<{'armhf': 'm'}>
+CONFIG_UNISYSSPAR                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_UNISYS_VISORBUS                          policy<{'amd64': 'm'}>
+CONFIG_UNISYS_VISORHBA                          policy<{'amd64': 'm'}>
+CONFIG_UNISYS_VISORINPUT                        policy<{'amd64': 'm'}>
+CONFIG_UNISYS_VISORNIC                          policy<{'amd64': 'm'}>
+CONFIG_UNIX                                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_UNIX98_PTYS                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_UNIXWARE_DISKLABEL                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_UNIX_DIAG                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_UNIX_SCM                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_UNMAP_KERNEL_AT_EL0                      policy<{'arm64': 'y'}>
+CONFIG_UNUSED_SYMBOLS                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_UNWINDER_GUESS                           policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_UNWINDER_ORC                             policy<{'amd64': 'n'}>
+CONFIG_UPROBES                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_UPROBE_EVENTS                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_US5182D                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB                                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USBIP_CORE                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USBIP_DEBUG                              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_USBIP_HOST                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USBIP_VHCI_HCD                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USBIP_VHCI_HC_PORTS                      policy<{'amd64': '8', 'arm64': '8', 'armhf': '8', 'i386': '8', 'ppc64el': '8'}>
+CONFIG_USBIP_VHCI_NR_HCS                        policy<{'amd64': '1', 'arm64': '1', 'armhf': '1', 'i386': '1', 'ppc64el': '1'}>
+CONFIG_USBIP_VUDC                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USBPCWATCHDOG                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_ACM                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_ADUTUX                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_AIRSPY                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_ALI_M5632                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_AMD5536UDC                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_AN2720                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_ANNOUNCE_NEW_DEVICES                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_APPLEDISPLAY                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_ARCH_HAS_HCD                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_ARMLINUX                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_ASPEED_VHUB                          policy<{'armhf': 'm'}>
+CONFIG_USB_ATM                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_AUDIO                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_AUTOSUSPEND_DELAY                    policy<{'amd64': '2', 'arm64': '2', 'armhf': '2', 'i386': '2', 'ppc64el': '2'}>
+CONFIG_USB_BDC_UDC                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_BELKIN                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_C67X00_HCD                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_CATC                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_CDC_COMPOSITE                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_CDC_PHONET                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_CDNS3                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_CDNS3_GADGET                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_CDNS3_HOST                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_CDNS3_PCI_WRAP                       policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_USB_CHAOSKEY                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_CHIPIDEA                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_CHIPIDEA_HOST                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_CHIPIDEA_OF                          policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_CHIPIDEA_PCI                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_CHIPIDEA_UDC                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_COMMON                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_CONFIGFS                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_CONFIGFS_ACM                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_CONFIGFS_ECM                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_CONFIGFS_ECM_SUBSET                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_CONFIGFS_EEM                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_CONFIGFS_F_FS                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_CONFIGFS_F_HID                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_CONFIGFS_F_LB_SS                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_CONFIGFS_F_MIDI                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_CONFIGFS_F_PRINTER                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_CONFIGFS_F_TCM                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_CONFIGFS_F_UAC1                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_CONFIGFS_F_UAC1_LEGACY               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_CONFIGFS_F_UAC2                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_CONFIGFS_F_UVC                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_CONFIGFS_MASS_STORAGE                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_CONFIGFS_NCM                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_CONFIGFS_OBEX                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_CONFIGFS_PHONET                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_CONFIGFS_RNDIS                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_CONFIGFS_SERIAL                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_CONN_GPIO                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_CXACRU                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_CYPRESS_CY7C63                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_CYTHERM                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_DEFAULT_PERSIST                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_DSBR                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_DUMMY_HCD                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_USB_DWC2                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_DWC2_DEBUG                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_USB_DWC2_DUAL_ROLE                       policy<{'armhf': 'n'}>
+CONFIG_USB_DWC2_HOST                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_DWC2_PCI                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'y', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_DWC2_PERIPHERAL                      policy<{'armhf': 'n'}>
+CONFIG_USB_DWC2_TRACK_MISSED_SOFS               policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_USB_DWC3                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_DWC3_DUAL_ROLE                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_DWC3_EXYNOS                          policy<{'armhf': 'm'}>
+CONFIG_USB_DWC3_GADGET                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_USB_DWC3_HAPS                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_DWC3_HOST                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_USB_DWC3_KEYSTONE                        policy<{'arm64': 'm'}>
+CONFIG_USB_DWC3_MESON_G12A                      policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_USB_DWC3_OF_SIMPLE                       policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_USB_DWC3_OMAP                            policy<{'armhf': 'm'}>
+CONFIG_USB_DWC3_PCI                             policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_USB_DWC3_QCOM                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_USB_DWC3_ULPI                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_DYNAMIC_MINORS                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_EG20T                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_EHCI_EXYNOS                          policy<{'armhf': 'y'}>
+CONFIG_USB_EHCI_FSL                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_EHCI_HCD_NPCM7XX                     policy<{'armhf': 'm'}>
+CONFIG_USB_EHCI_HCD_OMAP                        policy<{'armhf': 'm'}>
+CONFIG_USB_EHCI_HCD_ORION                       policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_USB_EHCI_HCD_PPC_OF                      policy<{'ppc64el': 'y'}>
+CONFIG_USB_EHCI_MXC                             policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_USB_EHCI_PCI                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_EHCI_ROOT_HUB_TT                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_EHCI_TEGRA                           policy<{'armhf-generic': 'm'}>
+CONFIG_USB_EHCI_TT_NEWSCHED                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_EHSET_TEST_FIXTURE                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_EMI26                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_EMI62                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_EMXX                                 policy<{'arm64': 'm', 'armhf': 'y'}>
+CONFIG_USB_EPSON2888                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_ETH                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_ETH_EEM                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_ETH_RNDIS                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_EZUSB_FX2                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_FOTG210_HCD                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_FOTG210_UDC                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_FSL_USB2                             policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_USB_FTDI_ELAN                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_FUNCTIONFS                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_FUNCTIONFS_ETH                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_FUNCTIONFS_GENERIC                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_FUNCTIONFS_RNDIS                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_FUSB300                              policy<{'armhf-generic': 'm'}>
+CONFIG_USB_F_ACM                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_F_ECM                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_F_EEM                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_F_FS                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_F_HID                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_F_MASS_STORAGE                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_F_MIDI                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_F_NCM                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_F_OBEX                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_F_PHONET                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_F_PRINTER                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_F_RNDIS                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_F_SERIAL                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_F_SS_LB                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_F_SUBSET                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_F_TCM                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_F_UAC1                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_F_UAC1_LEGACY                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_F_UAC2                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_F_UVC                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GADGET                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'y', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GADGETFS                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GADGET_DEBUG                         policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_USB_GADGET_DEBUG_FILES                   policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_USB_GADGET_DEBUG_FS                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS           policy<{'amd64': '2', 'arm64': '2', 'armhf': '2', 'i386': '2', 'ppc64el': '2'}>
+CONFIG_USB_GADGET_TARGET                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GADGET_VBUS_DRAW                     policy<{'amd64': '2', 'arm64': '2', 'armhf': '2', 'i386': '2', 'ppc64el': '2'}>
+CONFIG_USB_GADGET_XILINX                        policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GL860                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GOKU                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GPIO_VBUS                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GR_UDC                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_BENQ                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_CONEX                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_CPIA1                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_DTCS033                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_ETOMS                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_FINEPIX                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_JEILINJ                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_JL2005BCD                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_KINECT                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_KONICA                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_MARS                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_MR97310A                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_NW80X                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_OV519                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_OV534                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_OV534_9                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_PAC207                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_PAC7302                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_PAC7311                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_SE401                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_SN9C2028                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_SN9C20X                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_SONIXB                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_SONIXJ                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_SPCA1528                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_SPCA500                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_SPCA501                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_SPCA505                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_SPCA506                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_SPCA508                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_SPCA561                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_SQ905                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_SQ905C                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_SQ930X                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_STK014                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_STK1135                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_STV0680                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_SUNPLUS                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_T613                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_TOPRO                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_TOUPTEK                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_TV8532                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_VC032X                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_VICAM                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_XIRLINK_CIT                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_GSPCA_ZC3XX                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_G_ACM_MS                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_G_DBGP                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_G_DBGP_PRINTK                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_USB_G_DBGP_SERIAL                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_G_HID                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_G_MULTI                              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'm', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_USB_G_MULTI_CDC                          policy<{'armhf': 'y'}>
+CONFIG_USB_G_MULTI_RNDIS                        policy<{'armhf': 'y'}>
+CONFIG_USB_G_NCM                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_G_NOKIA                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_G_PRINTER                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_G_SERIAL                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_G_WEBCAM                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_HACKRF                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_HCD_TEST_MODE                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_USB_HID                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_HIDDEV                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_HSIC_USB3503                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_HSIC_USB4604                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_HSO                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_HUB_USB251XB                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_HWA_HCD                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_IDMOUSE                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_IMX21_HCD                            policy<{'armhf-generic': 'm'}>
+CONFIG_USB_IOWARRIOR                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_IPHETH                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_ISIGHTFW                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_ISP116X_HCD                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_ISP1301                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_ISP1760                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_ISP1760_DUAL_ROLE                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_ISP1760_GADGET_ROLE                  policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_USB_ISP1760_HCD                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_ISP1760_HOST_ROLE                    policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_USB_ISP1761_UDC                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_KAWETH                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_KBD                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_KC2190                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_KEENE                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_LAN78XX                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_LCD                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_LD                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_LEDS_TRIGGER_USBPORT                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_LED_TRIG                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_LEGOTOWER                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_LIBCOMPOSITE                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_LINK_LAYER_TEST                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_M5602                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_MA901                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_MASS_STORAGE                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_MAX3421_HCD                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_MDC800                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_MICROTEK                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_MIDI_GADGET                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_MON                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_MOUSE                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_MR800                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_MSI2500                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_MTU3                                 policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_USB_MTU3_DEBUG                           policy<{'arm64': 'n', 'armhf': 'n'}>
+CONFIG_USB_MTU3_DUAL_ROLE                       policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_USB_MTU3_GADGET                          policy<{'arm64': 'n', 'armhf': 'n'}>
+CONFIG_USB_MTU3_HOST                            policy<{'arm64': 'n', 'armhf': 'n'}>
+CONFIG_USB_MUSB_AM335X_CHILD                    policy<{'armhf': 'm'}>
+CONFIG_USB_MUSB_AM35X                           policy<{'armhf': 'm'}>
+CONFIG_USB_MUSB_DSPS                            policy<{'armhf': 'm'}>
+CONFIG_USB_MUSB_DUAL_ROLE                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_MUSB_GADGET                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_USB_MUSB_HOST                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_USB_MUSB_OMAP2PLUS                       policy<{'armhf': 'm'}>
+CONFIG_USB_MUSB_SUNXI                           policy<{'arm64': 'm'}>
+CONFIG_USB_MUSB_TUSB6010                        policy<{'armhf': 'm'}>
+CONFIG_USB_MV_U3D                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_MV_UDC                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_MXS_PHY                              policy<{'arm64': 'y', 'armhf-generic': 'y'}>
+CONFIG_USB_NET2272                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_NET2272_DMA                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_NET2280                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_NET_AQC111                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_NET_AX88179_178A                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_NET_AX8817X                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_NET_CDCETHER                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_NET_CDC_EEM                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_NET_CDC_MBIM                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_NET_CDC_NCM                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_NET_CDC_SUBSET                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_NET_CDC_SUBSET_ENABLE                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_NET_CH9200                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_NET_CX82310_ETH                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_NET_DM9601                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_NET_DRIVERS                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_NET_GL620A                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_NET_HUAWEI_CDC_NCM                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_NET_INT51X1                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_NET_KALMIA                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_NET_MCS7830                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_NET_NET1080                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_NET_PLUSB                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_NET_QMI_WWAN                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_NET_RNDIS_HOST                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_NET_RNDIS_WLAN                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_NET_SMSC75XX                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_NET_SMSC95XX                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_NET_SR9700                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_NET_SR9800                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_NET_ZAURUS                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_OHCI_EXYNOS                          policy<{'armhf': 'y'}>
+CONFIG_USB_OHCI_HCD_OMAP3                       policy<{'armhf-generic': 'm'}>
+CONFIG_USB_OHCI_HCD_PCI                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_OHCI_HCD_PLATFORM                    policy<{'amd64': 'y', 'arm64': 'm', 'armhf-generic': 'm', 'armhf-generic-lpae': 'n', 'i386': 'y', 'ppc64el': 'm'}>
+CONFIG_USB_OHCI_HCD_PPC_OF_BE                   policy<{'ppc64el': 'n'}>
+CONFIG_USB_OHCI_HCD_PPC_OF_LE                   policy<{'ppc64el': 'n'}>
+CONFIG_USB_OHCI_LITTLE_ENDIAN                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_USB_OXU210HP_HCD                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_PCI                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_PEGASUS                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_PHY                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_PRINTER                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_PULSE8_CEC                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_PWC                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_PWC_DEBUG                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_USB_PWC_INPUT_EVDEV                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_PXA27X                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_R8A66597                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_R8A66597_HCD                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_RAINSHADOW_CEC                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_RAREMONO                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_RENESAS_USB3                         policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_USB_RENESAS_USBHS                        policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_USB_RENESAS_USBHS_HCD                    policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_USB_RENESAS_USBHS_UDC                    policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_USB_ROLES_INTEL_XHCI                     policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_USB_ROLE_SWITCH                          policy<{'amd64': 'm', 'arm64': 'y', 'armhf': 'y', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_RTL8150                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_RTL8152                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_S2255                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_AIRCABLE                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_ARK3116                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_BELKIN                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_CH341                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_CP210X                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_CYBERJACK                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_CYPRESS_M8                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_EDGEPORT                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_EDGEPORT_TI                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_EMPEG                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_F81232                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_F8153X                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_FTDI_SIO                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_GARMIN                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_GENERIC                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_SERIAL_IPAQ                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_IPW                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_IR                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_IUU                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_KEYSPAN                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_KEYSPAN_PDA                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_KLSI                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_KOBIL_SCT                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_MCT_U232                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_METRO                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_MOS7715_PARPORT               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_SERIAL_MOS7720                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_MOS7840                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_MXUPORT                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_NAVMAN                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_OMNINET                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_OPTICON                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_OPTION                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_OTI6858                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_PL2303                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_QCAUX                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_QT2                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_QUALCOMM                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_SAFE                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_SAFE_PADDED                   policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_USB_SERIAL_SIERRAWIRELESS                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_SIMPLE                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_SPCP8X5                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_SSU100                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_SYMBOL                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_TI                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_UPD78F0730                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_VISOR                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_WHITEHEAT                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_WISHBONE                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_WWAN                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_XIRCOM                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SERIAL_XSENS_MT                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SEVSEG                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SI470X                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SI4713                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SIERRA_NET                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SISUSBVGA                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SL811_CS                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_USB_SL811_HCD                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SL811_HCD_ISO                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_SNP_CORE                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SNP_UDC_PLAT                         policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SPEEDTOUCH                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_STKWEBCAM                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_STORAGE                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_STORAGE_ALAUDA                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_STORAGE_CYPRESS_ATACB                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_STORAGE_DATAFAB                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_STORAGE_DEBUG                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_USB_STORAGE_ENE_UB6250                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_STORAGE_FREECOM                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_STORAGE_ISD200                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_STORAGE_JUMPSHOT                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_STORAGE_KARMA                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_STORAGE_ONETOUCH                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_STORAGE_REALTEK                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_STORAGE_SDDR09                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_STORAGE_SDDR55                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_STORAGE_USBAT                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_STV06XX                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_SUPPORT                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_USB_TEGRA_PHY                            policy<{'armhf-generic': 'm'}>
+CONFIG_USB_TEST                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_TMC                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_TRANCEVIBRATOR                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_U132_HCD                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_UAS                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_UEAGLEATM                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_UHCI_ASPEED                          policy<{'armhf': 'y'}>
+CONFIG_USB_UHCI_PLATFORM                        policy<{'armhf': 'y'}>
+CONFIG_USB_UHCI_SUPPORT_NON_PCI_HC              policy<{'armhf': 'y'}>
+CONFIG_USB_ULPI                                 policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_USB_ULPI_BUS                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_ULPI_VIEWPORT                        policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_USB_USBNET                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_USS720                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_U_AUDIO                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_U_ETHER                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_U_SERIAL                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_VIDEO_CLASS                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_VL600                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_WDM                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_WHCI_HCD                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_WUSB                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_WUSB_CBAF                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_WUSB_CBAF_DEBUG                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_USB_XHCI_HISTB                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_USB_XHCI_MTK                             policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_USB_XHCI_MVEBU                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_USB_XHCI_PCI                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_USB_XHCI_PLATFORM                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_XHCI_RCAR                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_USB_XHCI_TEGRA                           policy<{'armhf-generic': 'm'}>
+CONFIG_USB_XUSBATM                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_YUREX                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_ZD1201                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_ZERO                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USB_ZR364XX                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USELIB                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_USERFAULTFD                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_USERIO                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_USER_NS                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_USER_RETURN_NOTIFIER                     policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_USER_STACKTRACE_SUPPORT                  policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_USE_OF                                   policy<{'armhf': 'y'}>
+CONFIG_USE_PERCPU_NUMA_NODE_ID                  policy<{'amd64': 'y', 'arm64': 'y', 'ppc64el': 'y'}>
+CONFIG_UTS_NS                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_UV_MMTIMER                               policy<{'amd64': 'm'}>
+CONFIG_UWB                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_UWB_HWA                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_UWB_I1480U                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_UWB_WHCI                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_U_SERIAL_CONSOLE                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_V4L2_FLASH_LED_CLASS                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_V4L2_FWNODE                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_V4L2_MEM2MEM_DEV                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_V4L_MEM2MEM_DRIVERS                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_V4L_PLATFORM_DRIVERS                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_V4L_RADIO_ISA_DRIVERS                    policy<{'i386': 'y'}>
+CONFIG_V4L_TEST_DRIVERS                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_VALIDATE_FS_PARSER                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_VCNL4000                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VCNL4035                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VDSO                                     policy<{'armhf': 'y'}>
+CONFIG_VEML6070                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VERSION_SIGNATURE                        policy<{'amd64': '""', 'arm64': '""', 'armhf': '""', 'i386': '""', 'ppc64el': '""', 's390x': '""'}>
+CONFIG_VETH                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_VEXPRESS_CONFIG                          policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_VEXPRESS_SYSCFG                          policy<{'arm64': 'y', 'armhf': 'y'}>
+CONFIG_VF610_ADC                                policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_VF610_DAC                                policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_VFIO_AMBA                                policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_VFIO_AP                                  policy<{'s390x': 'm'}>
+CONFIG_VFIO_CCW                                 policy<{'s390x': 'm'}>
+CONFIG_VFIO_IOMMU_SPAPR_TCE                     policy<{'ppc64el': 'y'}>
+CONFIG_VFIO_IOMMU_TYPE1                         policy<{'amd64': 'y', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 's390x': 'm'}>
+CONFIG_VFIO_MDEV                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_VFIO_MDEV_DEVICE                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_VFIO_NOIOMMU                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_VFIO_PCI_IGD                             policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_VFIO_PCI_INTX                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_VFIO_PCI_MMAP                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_VFIO_PCI_NVLINK2                         policy<{'ppc64el': 'y'}>
+CONFIG_VFIO_PCI_VGA                             policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_VFIO_PLATFORM                            policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_VFIO_PLATFORM_AMDXGBE_RESET              policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_VFIO_PLATFORM_BCMFLEXRM_RESET            policy<{'arm64': 'm'}>
+CONFIG_VFIO_PLATFORM_CALXEDAXGMAC_RESET         policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_VFIO_SPAPR_EEH                           policy<{'ppc64el': 'y'}>
+CONFIG_VFIO_VIRQFD                              policy<{'amd64': 'y', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'y', 's390x': 'm'}>
+CONFIG_VFP                                      policy<{'armhf': 'y'}>
+CONFIG_VFPv3                                    policy<{'armhf': 'y'}>
+CONFIG_VF_USE_ARM_GLOBAL_TIMER                  policy<{'armhf-generic': 'y'}>
+CONFIG_VF_USE_PIT_TIMER                         policy<{'armhf-generic': 'n'}>
+CONFIG_VGASTATE                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VGA_ARB                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_VGA_ARB_MAX_GPUS                         policy<{'amd64': '16', 'arm64': '16', 'armhf': '16', 'i386': '16', 'ppc64el': '16'}>
+CONFIG_VGA_CONSOLE                              policy<{'amd64': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_VGA_SWITCHEROO                           policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_VHOST                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_VHOST_CROSS_ENDIAN_LEGACY                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_VHOST_NET                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_VHOST_RING                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VHOST_SCSI                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_VHOST_VSOCK                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_VIA_RHINE                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIA_RHINE_MMIO                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_VIA_VELOCITY                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIA_WDT                                  policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_VIDEOBUF2_CORE                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEOBUF2_DMA_CONTIG                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEOBUF2_DMA_SG                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEOBUF2_DVB                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEOBUF2_MEMOPS                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEOBUF2_V4L2                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEOBUF2_VMALLOC                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEOBUF_DMA_SG                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEOBUF_GEN                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEOBUF_VMALLOC                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEOMODE_HELPERS                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_VIDEO_AD5820                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_AD9389B                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_ADP1653                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_ADV7170                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_ADV7175                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_ADV7180                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_ADV7183                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_ADV7343                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_ADV7393                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_ADV748X                            policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_ADV7511                            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_VIDEO_ADV7511_CEC                        policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_VIDEO_ADV7604                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_ADV7604_CEC                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_VIDEO_ADV7842                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_ADV7842_CEC                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_VIDEO_ADV_DEBUG                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_VIDEO_AK7375                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_AK881X                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_ALLEGRO_DVT                        policy<{'arm64': 'm'}>
+CONFIG_VIDEO_APTINA_PLL                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_ASPEED                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_AU0828                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_AU0828_RC                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_VIDEO_AU0828_V4L2                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_VIDEO_BCM2835                            policy<{'arm64': 'm'}>
+CONFIG_VIDEO_BT819                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_BT848                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_BT856                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_BT866                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_CADENCE                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_VIDEO_CADENCE_CSI2RX                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_CADENCE_CSI2TX                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_CAFE_CCIC                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_VIDEO_COBALT                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_VIDEO_CODA                               policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_VIDEO_CPIA2                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_CROS_EC_CEC                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_VIDEO_CS3308                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_CS5345                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_CS53L32A                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_CX18                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_CX18_ALSA                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_CX231XX                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_CX231XX_ALSA                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_CX231XX_DVB                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_CX231XX_RC                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_VIDEO_CX2341X                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_CX23885                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_CX25821                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_CX25821_ALSA                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_CX25840                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_CX88                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_CX88_ALSA                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_CX88_BLACKBIRD                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_CX88_DVB                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_CX88_ENABLE_VP3054                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_VIDEO_CX88_MPEG                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_CX88_VP3054                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_DEV                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_DT3155                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_DW9714                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_DW9807_VCM                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_EM28XX                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_EM28XX_ALSA                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_EM28XX_DVB                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_EM28XX_RC                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_EM28XX_V4L2                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_ET8EK8                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_FB_IVTV                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_FB_IVTV_FORCE_PAT                  policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_VIDEO_FIXED_MINOR_RANGES                 policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_VIDEO_GO7007                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_GO7007_LOADER                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_GO7007_USB                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_GO7007_USB_S2250_BOARD             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_GS1662                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_HDPVR                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_HEXIUM_GEMINI                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_HEXIUM_ORION                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_I2C                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_IMX214                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_IMX258                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_IMX274                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_IMX319                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_IMX355                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_IMX7_CSI                           policy<{'armhf-generic': 'm'}>
+CONFIG_VIDEO_IMX_CSI                            policy<{'armhf-generic': 'm'}>
+CONFIG_VIDEO_IMX_MEDIA                          policy<{'armhf-generic': 'm'}>
+CONFIG_VIDEO_IMX_PXP                            policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_VIDEO_IMX_VDOA                           policy<{'armhf-generic': 'm'}>
+CONFIG_VIDEO_IPU3_CIO2                          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_VIDEO_IPU3_IMGU                          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_VIDEO_IR_I2C                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_IVTV                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_IVTV_ALSA                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_IVTV_DEPRECATED_IOCTLS             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_VIDEO_KS0127                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_LM3560                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_LM3646                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_M52790                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_M5MOLS                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_MEDIATEK_VPU                       policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_VIDEO_MEM2MEM_DEINTERLACE                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_MESON_AO_CEC                       policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_VIDEO_MESON_G12A_AO_CEC                  policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_VIDEO_MESON_VDEC                         policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_VIDEO_MEYE                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_VIDEO_ML86V7667                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_MSP3400                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_MT9M001                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_MT9M032                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_MT9M111                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_MT9P031                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_MT9T001                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_MT9T112                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_MT9V011                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_MT9V032                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_MT9V111                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_MUX                                policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_MXB                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_NOON010PC30                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_OMAP2_VOUT                         policy<{'armhf-generic': 'm'}>
+CONFIG_VIDEO_OMAP2_VOUT_VRFB                    policy<{'armhf-generic': 'y'}>
+CONFIG_VIDEO_OMAP3                              policy<{'armhf-generic': 'm'}>
+CONFIG_VIDEO_OMAP3_DEBUG                        policy<{'armhf-generic': 'n'}>
+CONFIG_VIDEO_OMAP4                              policy<{'armhf-generic': 'm'}>
+CONFIG_VIDEO_OV13858                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_OV2640                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_OV2659                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_OV2680                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_OV2685                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_OV5640                             policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_OV5645                             policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_OV5647                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_OV5670                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_OV5675                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_OV5695                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_OV6650                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_OV7251                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_OV7640                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_OV7670                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_OV772X                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_OV7740                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_OV8856                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_OV9640                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_OV9650                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_PCI_SKELETON                       policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_VIDEO_PVRUSB2                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_PVRUSB2_DEBUGIFC                   policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_VIDEO_PVRUSB2_DVB                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_VIDEO_PVRUSB2_SYSFS                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_VIDEO_QCOM_CAMSS                         policy<{'arm64': 'm'}>
+CONFIG_VIDEO_QCOM_VENUS                         policy<{'arm64': 'm'}>
+CONFIG_VIDEO_RCAR_CSI2                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_VIDEO_RCAR_DRIF                          policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_VIDEO_RCAR_VIN                           policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_VIDEO_RENESAS_CEU                        policy<{'armhf': 'm'}>
+CONFIG_VIDEO_RENESAS_FCP                        policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_VIDEO_RENESAS_FDP1                       policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_VIDEO_RENESAS_JPU                        policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_VIDEO_RENESAS_VSP1                       policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_VIDEO_RJ54N1                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_ROCKCHIP_RGA                       policy<{'arm64': 'm', 'armhf': 'm'}>
+CONFIG_VIDEO_S5C73M3                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_S5K4ECGX                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_S5K5BAF                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_S5K6A3                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_S5K6AA                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_SAA6588                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_SAA6752HS                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_SAA7110                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_SAA711X                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_SAA7127                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_SAA7134                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_SAA7134_ALSA                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_SAA7134_DVB                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_SAA7134_GO7007                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_SAA7134_RC                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_VIDEO_SAA7146                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_SAA7146_VV                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_SAA7164                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_SAA717X                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_SAA7185                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_SAMSUNG_EXYNOS4_IS                 policy<{'armhf': 'n'}>
+CONFIG_VIDEO_SAMSUNG_EXYNOS_GSC                 policy<{'armhf': 'm'}>
+CONFIG_VIDEO_SAMSUNG_S5P_CEC                    policy<{'armhf': 'm'}>
+CONFIG_VIDEO_SAMSUNG_S5P_G2D                    policy<{'armhf': 'm'}>
+CONFIG_VIDEO_SAMSUNG_S5P_JPEG                   policy<{'armhf': 'm'}>
+CONFIG_VIDEO_SAMSUNG_S5P_MFC                    policy<{'armhf': 'm'}>
+CONFIG_VIDEO_SECO_CEC                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_VIDEO_SECO_RC                            policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_VIDEO_SH_VEU                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_SMIAPP                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_VIDEO_SMIAPP_PLL                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_VIDEO_SOLO6X10                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_SONY_BTF_MPX                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_SR030PC30                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_STK1160                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_STK1160_COMMON                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_ST_MIPID02                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_SUN4I_CSI                          policy<{'arm64': 'm'}>
+CONFIG_VIDEO_SUN6I_CSI                          policy<{'arm64': 'm'}>
+CONFIG_VIDEO_SUNXI                              policy<{'arm64': 'y'}>
+CONFIG_VIDEO_TC358743                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_TC358743_CEC                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_VIDEO_TDA1997X                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_TDA7432                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_TDA9840                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_TEA6415C                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_TEA6420                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_TEGRA_HDMI_CEC                     policy<{'armhf-generic': 'm'}>
+CONFIG_VIDEO_THS7303                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_THS8200                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_TI_CAL                             policy<{'armhf': 'm'}>
+CONFIG_VIDEO_TI_CSC                             policy<{'armhf': 'm'}>
+CONFIG_VIDEO_TI_SC                              policy<{'armhf': 'm'}>
+CONFIG_VIDEO_TI_VPDMA                           policy<{'armhf': 'm'}>
+CONFIG_VIDEO_TI_VPE                             policy<{'armhf': 'm'}>
+CONFIG_VIDEO_TI_VPE_DEBUG                       policy<{'armhf': 'n'}>
+CONFIG_VIDEO_TLV320AIC23B                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_TM6000                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_TM6000_ALSA                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_TM6000_DVB                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_TUNER                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_TVAUDIO                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_TVEEPROM                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_TVP514X                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_TVP5150                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_TVP7002                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_TW2804                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_TW5864                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_TW68                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_TW686X                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_TW9903                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_TW9906                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_TW9910                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_UDA1342                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_UPD64031A                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_UPD64083                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_USBTV                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_USBVISION                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_V4L2                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_V4L2_I2C                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_VIDEO_V4L2_SUBDEV_API                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_VIDEO_V4L2_TPG                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_VIA_CAMERA                         policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_VIDEO_VICODEC                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_VIM2M                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_VIVID                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_VIVID_CEC                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_VIDEO_VIVID_MAX_DEVS                     policy<{'amd64': '64', 'arm64': '64', 'armhf': '64', 'i386': '64', 'ppc64el': '64'}>
+CONFIG_VIDEO_VP27SMPX                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_VPX3220                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_VS6624                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_WM8739                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_WM8775                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_XILINX                             policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_XILINX_TPG                         policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_VIDEO_XILINX_VTC                         policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_VIPERBOARD_ADC                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIRTIO                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_VIRTIO_BALLOON                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_VIRTIO_BLK_SCSI                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_VIRTIO_CONSOLE                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_VIRTIO_FS                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_VIRTIO_INPUT                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_VIRTIO_IOMMU                             policy<{'arm64': 'y'}>
+CONFIG_VIRTIO_MENU                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_VIRTIO_PCI                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_VIRTIO_PCI_LEGACY                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_VIRTIO_PMEM                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf-generic-lpae': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VIRTIO_VSOCKETS                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_VIRTIO_VSOCKETS_COMMON                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_VIRTUALIZATION                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_VIRT_CPU_ACCOUNTING                      policy<{'s390x': 'y'}>
+CONFIG_VIRT_CPU_ACCOUNTING_GEN                  policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'ppc64el': 'n'}>
+CONFIG_VIRT_CPU_ACCOUNTING_NATIVE               policy<{'ppc64el': 'n', 's390x': 'y'}>
+CONFIG_VIRT_DRIVERS                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_VIRT_TO_BUS                              policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_VIRT_WIFI                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VITESSE_PHY                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_VL53L0X_I2C                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VL6180                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VLAN_8021Q                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_VLAN_8021Q_GVRP                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_VLAN_8021Q_MVRP                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_VM86                                     policy<{'i386': 'y'}>
+CONFIG_VMAP_STACK                               policy<{'amd64': 'y', 'arm64': 'y', 's390x': 'y'}>
+CONFIG_VMCP                                     policy<{'s390x': 'y'}>
+CONFIG_VMCP_CMA_SIZE                            policy<{'s390x': '4'}>
+CONFIG_VMD                                      policy<{'amd64': 'm'}>
+CONFIG_VME_BUS                                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_VME_CA91CX42                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_VME_FAKE                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VME_TSI148                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VME_USER                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VMIVME_7805                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VMLOGRDR                                 policy<{'s390x': 'm'}>
+CONFIG_VMSPLIT_1G                               policy<{'armhf': 'n', 'i386': 'n'}>
+CONFIG_VMSPLIT_2G                               policy<{'armhf': 'n', 'i386': 'n'}>
+CONFIG_VMSPLIT_3G                               policy<{'armhf': 'y', 'i386': 'y'}>
+CONFIG_VMSPLIT_3G_OPT                           policy<{'armhf-generic': 'n'}>
+CONFIG_VMWARE_BALLOON                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_VMWARE_PVSCSI                            policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_VMWARE_VMCI                              policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_VMWARE_VMCI_VSOCKETS                     policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_VMXNET3                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 's390x': 'n'}>
+CONFIG_VM_EVENT_COUNTERS                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_VOP                                      policy<{'amd64': 'm'}>
+CONFIG_VOP_BUS                                  policy<{'amd64': 'm', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_VORTEX                                   policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VSOCKETS                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_VSOCKETS_DIAG                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_VSOCKMON                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_VSX                                      policy<{'ppc64el': 'y'}>
+CONFIG_VT                                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_VT6655                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VT6656                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_VT_CONSOLE                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_VT_CONSOLE_SLEEP                         policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_VT_HW_CONSOLE_BINDING                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_VXFS_FS                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_VXGE                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_VXGE_DEBUG_TRACE_ALL                     policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_VXLAN                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_VZ89X                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_W1                                       policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_W1_CON                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_W1_MASTER_DS1WM                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_W1_MASTER_DS2482                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_W1_MASTER_DS2490                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_W1_MASTER_GPIO                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_W1_MASTER_MATROX                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_W1_MASTER_MXC                            policy<{'arm64': 'm', 'armhf-generic': 'm'}>
+CONFIG_W1_MASTER_SGI                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_W1_SLAVE_DS2405                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_W1_SLAVE_DS2406                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_W1_SLAVE_DS2408                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_W1_SLAVE_DS2408_READBACK                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_W1_SLAVE_DS2413                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_W1_SLAVE_DS2423                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_W1_SLAVE_DS2431                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_W1_SLAVE_DS2433                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_W1_SLAVE_DS2433_CRC                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_W1_SLAVE_DS2438                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_W1_SLAVE_DS250X                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_W1_SLAVE_DS2780                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_W1_SLAVE_DS2781                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_W1_SLAVE_DS2805                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_W1_SLAVE_DS28E04                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_W1_SLAVE_DS28E17                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_W1_SLAVE_SMEM                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_W1_SLAVE_THERM                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_W83627HF_WDT                             policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_W83877F_WDT                              policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_W83977F_WDT                              policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_WAFER_WDT                                policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_WAN                                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_WANT_DEV_COREDUMP                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_WANXL                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_WARN_ALL_UNSEEDED_RANDOM                 policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_WARN_DYNAMIC_STACK                       policy<{'s390x': 'n'}>
+CONFIG_WATCHDOG                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_WATCHDOG_CORE                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_WATCHDOG_NOWAYOUT                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_WATCHDOG_OPEN_TIMEOUT                    policy<{'amd64': '0', 'arm64': '0', 'armhf': '0', 'i386': '0', 'ppc64el': '0', 's390x': '0'}>
+CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC    policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_WATCHDOG_PRETIMEOUT_GOV                  policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_WATCHDOG_PRETIMEOUT_GOV_SEL              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_WATCHDOG_RTAS                            policy<{'ppc64el': 'm'}>
+CONFIG_WATCHDOG_SYSFS                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_WCN36XX                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_WCN36XX_DEBUGFS                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_WCN36XX_SNAPDRAGON_HACKS                 policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_WD80x3                                   policy<{'i386': 'm'}>
+CONFIG_WDAT_WDT                                 policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_WDT                                      policy<{'i386': 'm'}>
+CONFIG_WDTPCI                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_WEXT_CORE                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_WEXT_PRIV                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_WEXT_PROC                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_WEXT_SPY                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_WIL6210                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_WIL6210_DEBUGFS                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_WIL6210_ISR_COR                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_WIL6210_TRACING                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_WILC1000                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_WILC1000_HW_OOB_INTR                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_WILC1000_SDIO                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_WILC1000_SPI                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_WILCO_EC                                 policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_WILCO_EC_DEBUGFS                         policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_WILCO_EC_EVENTS                          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_WILCO_EC_TELEMETRY                       policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_WILINK_PLATFORM_DATA                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_WIMAX                                    policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_WIMAX_DEBUG_LEVEL                        policy<{'amd64': '8', 'arm64': '8', 'armhf': '8', 'i386': '8', 'ppc64el': '8'}>
+CONFIG_WIMAX_I2400M                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_WIMAX_I2400M_DEBUG_LEVEL                 policy<{'amd64': '8', 'arm64': '8', 'armhf': '8', 'i386': '8', 'ppc64el': '8'}>
+CONFIG_WIMAX_I2400M_USB                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_WINBOND_840                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_WINDFARM                                 policy<{'ppc64el': 'm'}>
+CONFIG_WIRELESS                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_WIRELESS_EXT                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_WIRELESS_WDS                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_WIZNET_BUS_ANY                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_WIZNET_BUS_DIRECT                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_WIZNET_BUS_INDIRECT                      policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_WIZNET_W5100                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_WIZNET_W5100_SPI                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_WIZNET_W5300                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_WKUP_M3_IPC                              policy<{'armhf-generic': 'n'}>
+CONFIG_WKUP_M3_RPROC                            policy<{'armhf-generic': 'm'}>
+CONFIG_WL1251                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_WL1251_SDIO                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_WL1251_SPI                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_WL12XX                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_WL18XX                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_WLAN                                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_WLAN_VENDOR_ADMTEK                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_WLAN_VENDOR_ATH                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_WLAN_VENDOR_ATMEL                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_WLAN_VENDOR_BROADCOM                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_WLAN_VENDOR_CISCO                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_WLAN_VENDOR_INTEL                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_WLAN_VENDOR_INTERSIL                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_WLAN_VENDOR_MARVELL                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_WLAN_VENDOR_MEDIATEK                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_WLAN_VENDOR_QUANTENNA                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_WLAN_VENDOR_RALINK                       policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_WLAN_VENDOR_REALTEK                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_WLAN_VENDOR_RSI                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_WLAN_VENDOR_ST                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_WLAN_VENDOR_TI                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_WLAN_VENDOR_ZYDAS                        policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_WLCORE                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_WLCORE_SDIO                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_WLCORE_SPI                               policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_WM831X_BACKUP                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_WM831X_POWER                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_WM831X_WATCHDOG                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_WM8350_POWER                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_WM8350_WATCHDOG                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_WMI_BMOF                                 policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_WQ_WATCHDOG                              policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_WW_MUTEX_SELFTEST                        policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_X25                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_X25_ASY                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_X86                                      policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_16BIT                                policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_32                                   policy<{'i386': 'y'}>
+CONFIG_X86_32_IRIS                              policy<{'i386': 'm'}>
+CONFIG_X86_32_NON_STANDARD                      policy<{'i386': 'n'}>
+CONFIG_X86_32_SMP                               policy<{'i386': 'y'}>
+CONFIG_X86_5LEVEL                               policy<{'amd64': 'n'}>
+CONFIG_X86_64                                   policy<{'amd64': 'y'}>
+CONFIG_X86_64_ACPI_NUMA                         policy<{'amd64': 'y'}>
+CONFIG_X86_64_SMP                               policy<{'amd64': 'y'}>
+CONFIG_X86_ACPI_CPUFREQ_CPB                     policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_AMD_FREQ_SENSITIVITY                 policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_X86_AMD_PLATFORM_DEVICE                  policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_ANCIENT_MCE                          policy<{'i386': 'n'}>
+CONFIG_X86_APM_BOOT                             policy<{'i386': 'y'}>
+CONFIG_X86_BIGSMP                               policy<{'i386': 'n'}>
+CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK    policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_CHECK_BIOS_CORRUPTION                policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_CMOV                                 policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_CMPXCHG64                            policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_CPA_STATISTICS                       policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_X86_CPUID                                policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_X86_CPU_RESCTRL                          policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_DEBUGCTLMSR                          policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_DEBUG_FPU                            policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_DECODER_SELFTEST                     policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_X86_DEV_DMA_OPS                          policy<{'amd64': 'y'}>
+CONFIG_X86_DIRECT_GBPAGES                       policy<{'amd64': 'y'}>
+CONFIG_X86_ESPFIX32                             policy<{'i386': 'y'}>
+CONFIG_X86_ESPFIX64                             policy<{'amd64': 'y'}>
+CONFIG_X86_EXTENDED_PLATFORM                    policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_E_POWERSAVER                         policy<{'i386': 'n'}>
+CONFIG_X86_FEATURE_NAMES                        policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_GENERIC                              policy<{'i386': 'y'}>
+CONFIG_X86_GOLDFISH                             policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_X86_GX_SUSPMOD                           policy<{'i386': 'm'}>
+CONFIG_X86_HV_CALLBACK_VECTOR                   policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_INTEL_LPSS                           policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS         policy<{'amd64': 'y'}>
+CONFIG_X86_INTEL_MID                            policy<{'amd64': 'n', 'i386': 'y'}>
+CONFIG_X86_INTEL_MPX                            policy<{'amd64': 'y'}>
+CONFIG_X86_INTEL_PSTATE                         policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_INTEL_QUARK                          policy<{'i386': 'n'}>
+CONFIG_X86_INTEL_TSX_MODE_AUTO                  policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_X86_INTEL_TSX_MODE_OFF                   policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_INTEL_TSX_MODE_ON                    policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_X86_INTEL_UMIP                           policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_INTEL_USERCOPY                       policy<{'i386': 'y'}>
+CONFIG_X86_INTERNODE_CACHE_SHIFT                policy<{'amd64': '6', 'i386': '6'}>
+CONFIG_X86_IO_APIC                              policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_L1_CACHE_SHIFT                       policy<{'amd64': '6', 'i386': '6'}>
+CONFIG_X86_LOCAL_APIC                           policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_LONGHAUL                             policy<{'i386': 'm'}>
+CONFIG_X86_LONGRUN                              policy<{'i386': 'm'}>
+CONFIG_X86_MCE                                  policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_MCELOG_LEGACY                        policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_MCE_AMD                              policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_MCE_INJECT                           policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_X86_MCE_INTEL                            policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_MCE_THRESHOLD                        policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_MINIMUM_CPU_FAMILY                   policy<{'amd64': '64', 'i386': '6'}>
+CONFIG_X86_MPPARSE                              policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_MSR                                  policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_X86_NEED_RELOCS                          policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_NUMACHIP                             policy<{'amd64': 'y'}>
+CONFIG_X86_P4_CLOCKMOD                          policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_X86_PAE                                  policy<{'i386': 'y'}>
+CONFIG_X86_PAT                                  policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_PKG_TEMP_THERMAL                     policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_X86_PLATFORM_DEVICES                     policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_PMEM_LEGACY                          policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_PMEM_LEGACY_DEVICE                   policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_PM_TIMER                             policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_POWERNOW_K6                          policy<{'i386': 'm'}>
+CONFIG_X86_POWERNOW_K7                          policy<{'i386': 'm'}>
+CONFIG_X86_POWERNOW_K7_ACPI                     policy<{'i386': 'y'}>
+CONFIG_X86_PTDUMP                               policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_X86_PTDUMP_CORE                          policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_RDC321X                              policy<{'i386': 'n'}>
+CONFIG_X86_REBOOTFIXUPS                         policy<{'i386': 'y'}>
+CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS         policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_RESERVE_LOW                          policy<{'amd64': '64', 'i386': '64'}>
+CONFIG_X86_SFI_CPUFREQ                          policy<{'i386': 'm'}>
+CONFIG_X86_SMAP                                 policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE             policy<{'i386': 'y'}>
+CONFIG_X86_SPEEDSTEP_LIB                        policy<{'amd64': 'm', 'i386': 'y'}>
+CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK          policy<{'i386': 'y'}>
+CONFIG_X86_SUPPORTS_MEMORY_FAILURE              policy<{'amd64': 'y'}>
+CONFIG_X86_SYSFB                                policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_X86_THERMAL_VECTOR                       policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_TSC                                  policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_X86_USE_PPRO_CHECKSUM                    policy<{'i386': 'y'}>
+CONFIG_X86_VERBOSE_BOOTUP                       policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_X86_VSMP                                 policy<{'amd64': 'n'}>
+CONFIG_X86_VSYSCALL_EMULATION                   policy<{'amd64': 'y'}>
+CONFIG_X86_X2APIC                               policy<{'amd64': 'y'}>
+CONFIG_X86_X32                                  policy<{'amd64': 'y'}>
+CONFIG_XARRAY_MULTI                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf-generic-lpae': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_XDP_SOCKETS                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_XDP_SOCKETS_DIAG                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_XEN                                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'n', 'i386': 'y'}>
+CONFIG_XENFS                                    policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_XEN_ACPI                                 policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_XEN_AUTO_XLATE                           policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_XEN_BACKEND                              policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_XEN_BALLOON                              policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_XEN_BALLOON_MEMORY_HOTPLUG               policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_XEN_BALLOON_MEMORY_HOTPLUG_LIMIT         policy<{'amd64': '512', 'i386': '4'}>
+CONFIG_XEN_BLKDEV_BACKEND                       policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_XEN_COMPAT_XENFS                         policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_XEN_DEBUG_FS                             policy<{'amd64': 'n', 'i386': 'n'}>
+CONFIG_XEN_DEV_EVTCHN                           policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_XEN_DOM0                                 policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_XEN_EFI                                  policy<{'amd64': 'y', 'arm64': 'y'}>
+CONFIG_XEN_FBDEV_FRONTEND                       policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_XEN_FRONT_PGDIR_SHBUF                    policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_XEN_GNTDEV                               policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_XEN_GNTDEV_DMABUF                        policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_XEN_GRANT_DEV_ALLOC                      policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_XEN_GRANT_DMA_ALLOC                      policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_XEN_HAVE_PVMMU                           policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_XEN_HAVE_VPMU                            policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_XEN_MCE_LOG                              policy<{'amd64': 'y'}>
+CONFIG_XEN_NETDEV_BACKEND                       policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_XEN_PCIDEV_BACKEND                       policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_XEN_PCIDEV_FRONTEND                      policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_XEN_PRIVCMD                              policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_XEN_PV                                   policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_XEN_PVCALLS_BACKEND                      policy<{'amd64': 'n', 'arm64': 'n', 'i386': 'n'}>
+CONFIG_XEN_PVCALLS_FRONTEND                     policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_XEN_PVH                                  policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_XEN_PVHVM                                policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_XEN_PVHVM_SMP                            policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_XEN_PV_SMP                               policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_XEN_SAVE_RESTORE                         policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_XEN_SCRUB_PAGES_DEFAULT                  policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_XEN_SCSI_BACKEND                         policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_XEN_SCSI_FRONTEND                        policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_XEN_SYMS                                 policy<{'amd64': 'y', 'i386': 'y'}>
+CONFIG_XEN_SYS_HYPERVISOR                       policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_XEN_WDT                                  policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_XEN_XENBUS_FRONTEND                      policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_XFRM                                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_XFRM_ALGO                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_XFRM_INTERFACE                           policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_XFRM_IPCOMP                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_XFRM_MIGRATE                             policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_XFRM_OFFLOAD                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_XFRM_STATISTICS                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_XFRM_SUB_POLICY                          policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_XFRM_USER                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_XFS_DEBUG                                policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_XFS_FS                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_XFS_ONLINE_SCRUB                         policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_XFS_POSIX_ACL                            policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_XFS_QUOTA                                policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_XFS_RT                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_XFS_WARN                                 policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_XGENE_DMA                                policy<{'arm64': 'm'}>
+CONFIG_XGENE_PMU                                policy<{'arm64': 'y'}>
+CONFIG_XGENE_SLIMPRO_MBOX                       policy<{'arm64': 'm'}>
+CONFIG_XIAOMI_WMI                               policy<{'amd64': 'm', 'i386': 'm'}>
+CONFIG_XILINX_AXI_EMAC                          policy<{'amd64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_XILINX_DMA                               policy<{'arm64': 'm'}>
+CONFIG_XILINX_GMII2RGMII                        policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_XILINX_LL_TEMAC                          policy<{'amd64': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_XILINX_PR_DECOUPLER                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_XILINX_SDFEC                             policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_XILINX_VCU                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_XILINX_WATCHDOG                          policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_XILINX_XADC                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_XILINX_ZYNQMP_DMA                        policy<{'arm64': 'm'}>
+CONFIG_XILLYBUS                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_XILLYBUS_OF                              policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_XILLYBUS_PCIE                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_XIL_AXIS_FIFO                            policy<{'arm64': 'm', 'armhf': 'm', 'ppc64el': 'm'}>
+CONFIG_XMON                                     policy<{'ppc64el': 'y'}>
+CONFIG_XMON_DEFAULT                             policy<{'ppc64el': 'n'}>
+CONFIG_XMON_DEFAULT_RO_MODE                     policy<{'ppc64el': 'y'}>
+CONFIG_XMON_DISASSEMBLY                         policy<{'ppc64el': 'y'}>
+CONFIG_XOR_BLOCKS                               policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_XPS                                      policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_XXHASH                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_XZ_DEC_ARM                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_XZ_DEC_ARMTHUMB                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_XZ_DEC_BCJ                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_XZ_DEC_IA64                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_XZ_DEC_POWERPC                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_XZ_DEC_SPARC                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_XZ_DEC_TEST                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_XZ_DEC_X86                               policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'n'}>
+CONFIG_YAM                                      policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_YELLOWFIN                                policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_YENTA                                    policy<{'amd64': 'm', 'arm64': 'm', 'i386': 'm'}>
+CONFIG_YENTA_ENE_TUNE                           policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_YENTA_O2                                 policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_YENTA_RICOH                              policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_YENTA_TI                                 policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_YENTA_TOSHIBA                            policy<{'amd64': 'y', 'arm64': 'y', 'i386': 'y'}>
+CONFIG_Z3FOLD                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_ZBOOT_ROM_BSS                            policy<{'armhf': '0x0'}>
+CONFIG_ZBOOT_ROM_TEXT                           policy<{'armhf': '0x0'}>
+CONFIG_ZBUD                                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ZCRYPT                                   policy<{'s390x': 'm'}>
+CONFIG_ZD1211RW                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ZD1211RW_DEBUG                           policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n'}>
+CONFIG_ZEROPLUS_FF                              policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y'}>
+CONFIG_ZFCP                                     policy<{'s390x': 'm'}>
+CONFIG_ZIIRAVE_WATCHDOG                         policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'n'}>
+CONFIG_ZISOFS                                   policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ZLIB_DEFLATE                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'm'}>
+CONFIG_ZLIB_INFLATE                             policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ZONE_DEVICE                              policy<{'amd64': 'y', 'ppc64el': 'y'}>
+CONFIG_ZONE_DMA32                               policy<{'amd64': 'y', 'arm64': 'y'}>
+CONFIG_ZOPT2201                                 policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ZPA2326                                  policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ZPA2326_I2C                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ZPA2326_SPI                              policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm'}>
+CONFIG_ZPOOL                                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ZRAM                                     policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_ZRAM_MEMORY_TRACKING                     policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ZRAM_WRITEBACK                           policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ZSMALLOC                                 policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ZSMALLOC_STAT                            policy<{'amd64': 'n', 'arm64': 'n', 'armhf': 'n', 'i386': 'n', 'ppc64el': 'n', 's390x': 'n'}>
+CONFIG_ZSTD_COMPRESS                            policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm', 'ppc64el': 'm', 's390x': 'm'}>
+CONFIG_ZSTD_DECOMPRESS                          policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ZSWAP                                    policy<{'amd64': 'y', 'arm64': 'y', 'armhf': 'y', 'i386': 'y', 'ppc64el': 'y', 's390x': 'y'}>
+CONFIG_ZX_TDM                                   policy<{'amd64': 'm', 'arm64': 'm', 'armhf': 'm', 'i386': 'm'}>
+CONFIG_ZYNQMP_FIRMWARE                          policy<{'arm64': 'y'}>
+CONFIG_ZYNQMP_FIRMWARE_DEBUG                    policy<{'arm64': 'n'}>
+CONFIG_ZYNQMP_IPI_MBOX                          policy<{'arm64': 'y'}>
+CONFIG_ZYNQMP_PM_DOMAINS                        policy<{'arm64': 'y'}>
+CONFIG_ZYNQMP_POWER                             policy<{'arm64': 'y'}>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/control.d/flavour-control.stub
+++ linux-xilinx-zynqmp-5.4.0/debian.master/control.d/flavour-control.stub
@@ -0,0 +1,152 @@
+# Items that get replaced:
+# FLAVOUR
+# DESC
+# ARCH
+# SUPPORTED
+# TARGET
+# BOOTLOADER
+# =PROVIDES=
+#
+# Items marked with =FOO= are optional
+#
+# This file describes the template for packages that are created for each flavour
+# in debian/control.d/vars.*
+#
+# This file gets edited in a couple of places. See the debian/control.stub rule in
+# debian/rules. PGGVER, ABINUM, and SRCPKGNAME are all converted in the
+# process of creating debian/control.
+#
+# The flavour specific strings (ARCH, DESC, etc) are converted using values from the various
+# flavour files in debian/control.d/vars.*
+#
+# XXX: Leave the blank line before the first package!!
+
+Package: linux-image=SIGN-ME-PKG=-PKGVER-ABINUM-FLAVOUR
+Build-Profiles: <!stage1>
+Architecture: ARCH
+Section: kernel
+Priority: optional
+Provides: linux-image, fuse-module, aufs-dkms, =PROVIDES=${linux:rprovides}
+Depends: ${misc:Depends}, ${shlibs:Depends}, kmod, linux-base (>= 4.5ubuntu1~16.04.1), linux-modules-PKGVER-ABINUM-FLAVOUR
+Recommends: BOOTLOADER, initramfs-tools | linux-initramfs-tool
+Breaks: flash-kernel (<< 3.90ubuntu2) [arm64 armhf], s390-tools (<< 2.3.0-0ubuntu3) [s390x]
+Conflicts: linux-image=SIGN-PEER-PKG=-PKGVER-ABINUM-FLAVOUR
+Suggests: fdutils, linux-doc | SRCPKGNAME-source-PKGVER, SRCPKGNAME-tools, linux-headers-PKGVER-ABINUM-FLAVOUR
+Description: Linux kernel image for version PKGVER on DESC
+ This package contains the=SIGN-ME-TXT= Linux kernel image for version PKGVER on
+ DESC.
+ .
+ Supports SUPPORTED processors.
+ .
+ TARGET
+ .
+ You likely do not want to install this package directly. Instead, install
+ the linux-FLAVOUR meta-package, which will ensure that upgrades work
+ correctly, and that supporting packages are also installed.
+
+Package: linux-modules-PKGVER-ABINUM-FLAVOUR
+Build-Profiles: <!stage1>
+Architecture: ARCH
+Section: kernel
+Priority: optional
+Depends: ${misc:Depends}, ${shlibs:Depends}
+Built-Using: ${linux:BuiltUsing}
+Description: Linux kernel extra modules for version PKGVER on DESC
+ Contains the corresponding System.map file, the modules built by the
+ packager, and scripts that try to ensure that the system is not left in an
+ unbootable state after an update.
+ .
+ Supports SUPPORTED processors.
+ .
+ TARGET
+ .
+ You likely do not want to install this package directly. Instead, install
+ the linux-FLAVOUR meta-package, which will ensure that upgrades work
+ correctly, and that supporting packages are also installed.
+
+Package: linux-modules-extra-PKGVER-ABINUM-FLAVOUR
+Build-Profiles: <!stage1>
+Architecture: ARCH
+Section: kernel
+Priority: optional
+Depends: ${misc:Depends}, ${shlibs:Depends}, linux-image-PKGVER-ABINUM-FLAVOUR | linux-image-unsigned-PKGVER-ABINUM-FLAVOUR, crda | wireless-crda
+Description: Linux kernel extra modules for version PKGVER on DESC
+ This package contains the Linux kernel extra modules for version PKGVER on
+ DESC.
+ .
+ Also includes the corresponding System.map file, the modules built by the
+ packager, and scripts that try to ensure that the system is not left in an
+ unbootable state after an update.
+ .
+ Supports SUPPORTED processors.
+ .
+ TARGET
+ .
+ You likely do not want to install this package directly. Instead, install
+ the linux-FLAVOUR meta-package, which will ensure that upgrades work
+ correctly, and that supporting packages are also installed.
+
+Package: linux-headers-PKGVER-ABINUM-FLAVOUR
+Build-Profiles: <!stage1>
+Architecture: ARCH
+Section: devel
+Priority: optional
+Depends: ${misc:Depends}, SRCPKGNAME-headers-PKGVER-ABINUM, ${shlibs:Depends}
+Provides: linux-headers, linux-headers-3.0
+Description: Linux kernel headers for version PKGVER on DESC
+ This package provides kernel header files for version PKGVER on
+ DESC.
+ .
+ This is for sites that want the latest kernel headers.  Please read
+ /usr/share/doc/linux-headers-PKGVER-ABINUM/debian.README.gz for details.
+
+Package: linux-image=SIGN-ME-PKG=-PKGVER-ABINUM-FLAVOUR-dbgsym
+Build-Profiles: <!stage1>
+Architecture: ARCH
+Section: devel
+Priority: optional
+Depends: ${misc:Depends}
+Provides: linux-debug
+Description: Linux kernel debug image for version PKGVER on DESC
+ This package provides the=SIGN-ME-TXT= kernel debug image for version PKGVER on
+ DESC.
+ .
+ This is for sites that wish to debug the kernel.
+ .
+ The kernel image contained in this package is NOT meant to boot from. It
+ is uncompressed, and unstripped. This package also includes the
+ unstripped modules.
+
+Package: linux-tools-PKGVER-ABINUM-FLAVOUR
+Build-Profiles: <!stage1>
+Architecture: ARCH
+Section: devel
+Priority: optional
+Depends: ${misc:Depends}, SRCPKGNAME-tools-PKGVER-ABINUM
+Description: Linux kernel version specific tools for version PKGVER-ABINUM
+ This package provides the architecture dependant parts for kernel
+ version locked tools (such as perf and x86_energy_perf_policy) for
+ version PKGVER-ABINUM on
+ =HUMAN=.
+
+Package: linux-cloud-tools-PKGVER-ABINUM-FLAVOUR
+Build-Profiles: <!stage1>
+Architecture: ARCH
+Section: devel
+Priority: optional
+Depends: ${misc:Depends}, SRCPKGNAME-cloud-tools-PKGVER-ABINUM
+Description: Linux kernel version specific cloud tools for version PKGVER-ABINUM
+ This package provides the architecture dependant parts for kernel
+ version locked tools for cloud for version PKGVER-ABINUM on
+ =HUMAN=.
+
+Package: linux-udebs-FLAVOUR
+Build-Profiles: <!stage1>
+XC-Package-Type: udeb
+Section: debian-installer
+Architecture: ARCH
+Depends: ${udeb:Depends}
+Description: Metapackage depending on kernel udebs
+ This package depends on the all udebs that the kernel build generated,
+ for easier version and migration tracking.
+
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/control.d/generic.inclusion-list
+++ linux-xilinx-zynqmp-5.4.0/debian.master/control.d/generic.inclusion-list
@@ -0,0 +1,258 @@
+arch/*/{crypto,kernel,oprofile}
+arch/*/kvm/kvm.ko
+arch/powerpc/kvm/kvm-hv.ko
+arch/powerpc/kvm/kvm-pr.ko
+arch/powerpc/kvm/vfio.ko
+arch/powerpc/platforms/powernv/opal-prd.ko
+arch/s390/*
+arch/x86/kvm/kvm-amd.ko
+arch/x86/kvm/kvm-intel.ko
+crypto/*
+drivers/acpi/*
+drivers/ata/acard-ahci.ko
+drivers/ata/ahci.ko
+drivers/ata/ahci_platform.ko
+drivers/ata/ata_generic.ko
+drivers/ata/libahci.ko
+drivers/ata/libahci_platform.ko
+drivers/block/brd.ko
+drivers/block/cryptoloop.ko
+drivers/block/floppy.ko
+drivers/block/loop.ko
+drivers/block/nbd.ko
+drivers/block/rbd.ko
+drivers/block/virtio_blk.ko
+drivers/block/xen-blkfront.ko
+drivers/char/hangcheck-timer.ko
+drivers/char/hw_random/powernv-rng.ko
+drivers/char/hw_random/virtio-rng.ko
+drivers/char/ipmi/*
+drivers/char/ipmi/ipmi_msghandler.ko
+drivers/char/lp.ko
+drivers/char/nvram.ko
+drivers/char/ppdev.ko
+drivers/char/raw.ko
+drivers/char/virtio_console.ko
+drivers/crypto/nx/*
+drivers/crypto/vmx/vmx-crypto.ko
+drivers/firmware/efi/*
+drivers/firmware/iscsi_ibft.ko
+drivers/gpu/drm/ast/ast.ko
+drivers/gpu/drm/bochs/bochs-drm.ko
+drivers/gpu/drm/cirrus/cirrus.ko
+drivers/gpu/drm/drm_kms_helper.ko
+drivers/gpu/drm/drm.ko
+drivers/gpu/drm/ttm/ttm.ko
+drivers/gpu/drm/vboxvideo/vboxvideo.ko
+drivers/gpu/drm/virtio/virtio-gpu.ko
+drivers/gpu/drm/vmwgfx/vmwgfx.ko
+drivers/gpu/drm/xen/drm_xen_front.ko
+drivers/hid/hid-generic.ko
+drivers/hid/hid-hyperv.ko
+drivers/hid/hid.ko
+drivers/hid/usbhid/usbhid.ko
+drivers/hv/*
+drivers/hwmon/ibmpowernv.ko
+drivers/infiniband/core/ib_addr.ko
+drivers/infiniband/core/ib_cm.ko
+drivers/infiniband/core/ib_core.ko
+drivers/infiniband/core/ib_mad.ko
+drivers/infiniband/core/ib_sa.ko
+drivers/infiniband/core/iw_cm.ko
+drivers/infiniband/core/rdma_cm.ko
+drivers/infiniband/ulp/iser/ib_iser.ko
+drivers/infiniband/ulp/isert/ib_isert.ko
+drivers/input/evbug.ko
+drivers/input/gameport/gameport.ko
+drivers/input/input-leds.ko
+drivers/input/joydev.ko
+drivers/input/misc/xen-kbdfront.ko
+drivers/input/mouse/psmouse.ko
+drivers/input/serio/hyperv-keyboard.ko
+drivers/input/serio/serio_raw.ko
+drivers/input/serio/serport.ko
+drivers/input/touchscreen/usbtouchscreen.ko
+drivers/leds/leds-powernv.ko
+drivers/md/*
+drivers/message/fusion*
+drivers/misc/cxl/*
+drivers/misc/eeprom/at24.ko
+drivers/misc/vmw_balloon.ko
+drivers/misc/vmw_vmci/vmw_vmci.ko
+drivers/mtd/cmdlinepart.ko
+drivers/mtd/devices/powernv_flash.ko
+drivers/mtd/ofpart.ko
+drivers/net/appletalk/ipddp.ko
+drivers/net/bonding/bonding.ko
+drivers/net/caif/caif_virtio.ko
+drivers/net/dummy.ko
+drivers/net/eql.ko
+drivers/net/ethernet/8390/8390.ko
+drivers/net/ethernet/8390/ne2k-pci.ko
+drivers/net/ethernet/amazon/ena/ena.ko
+drivers/net/ethernet/amd/pcnet32.ko
+drivers/net/ethernet/broadcom/bnx2x/*
+drivers/net/ethernet/broadcom/tg3.ko
+drivers/net/ethernet/dec/tulip/*
+drivers/net/ethernet/emulex/benet/*
+drivers/net/ethernet/ibm/*
+drivers/net/ethernet/intel/e1000/e1000.ko
+drivers/net/ethernet/intel/e1000e/e1000e.ko
+drivers/net/ethernet/intel/i40e/*
+drivers/net/ethernet/intel/iavf/iavf.ko
+drivers/net/ethernet/intel/igb/*
+drivers/net/ethernet/intel/igbvf/igbvf.ko
+drivers/net/ethernet/intel/ixgbe/*
+drivers/net/ethernet/intel/ixgbevf/ixgbevf.ko
+drivers/net/ethernet/mellanox/*
+drivers/net/ethernet/netronome/nfp/nfp.ko
+drivers/net/ethernet/realtek/8139cp.ko
+drivers/net/ethernet/realtek/8139too.ko
+drivers/net/fddi/*
+drivers/net/geneve.ko
+drivers/net/hyperv/hv_netvsc.ko
+drivers/net/ifb.ko
+drivers/net/ipvlan/*
+drivers/net/macvlan.ko
+drivers/net/macvtap.ko
+drivers/net/mii.ko
+drivers/net/netconsole.ko
+drivers/net/ppp/*
+drivers/net/ppp/bsd_comp.ko
+drivers/net/slip/*
+drivers/net/veth.ko
+drivers/net/virtio_net.ko
+drivers/net/vmxnet3/vmxnet3.ko
+drivers/net/vxlan.ko
+drivers/net/xen-netback/*
+drivers/net/xen-netfront.ko
+drivers/nvme/host/nvme.ko
+drivers/nvmem/nvmem_core.ko
+drivers/parport/parport.ko
+drivers/parport/parport_pc.ko
+drivers/pci/host/vmd.ko
+drivers/platform/x86/pvpanic.ko
+drivers/pps/pps_core.ko
+drivers/ptp/ptp.ko
+drivers/s390/*
+drivers/s390/block/xpram.ko
+drivers/scsi/aacraid/*
+drivers/scsi/BusLogic.ko
+drivers/scsi/cxlflash/*
+drivers/scsi/device_handler/scsi_dh_alua.ko
+drivers/scsi/device_handler/scsi_dh_emc.ko
+drivers/scsi/device_handler/scsi_dh_hp_sw.ko
+drivers/scsi/device_handler/scsi_dh_rdac.ko
+drivers/scsi/hv_storvsc.ko
+drivers/scsi/ibmvscsi/*
+drivers/scsi/ipr.ko
+drivers/scsi/iscsi_boot_sysfs.ko
+drivers/scsi/iscsi_tcp.ko
+drivers/scsi/libiscsi.ko
+drivers/scsi/libiscsi_tcp.ko
+drivers/scsi/libsas/*
+drivers/scsi/lpfc/*
+drivers/scsi/megaraid/*
+drivers/scsi/mpt3sas/*
+drivers/scsi/osd/libosd.ko
+drivers/scsi/osd/osd.ko
+drivers/scsi/qla1280.ko
+drivers/scsi/qla2xxx/*
+drivers/scsi/raid_class.ko
+drivers/scsi/scsi_transport_fc.ko
+drivers/scsi/scsi_transport_iscsi.ko
+drivers/scsi/scsi_transport_sas.ko
+drivers/scsi/scsi_transport_spi.ko
+drivers/scsi/sd_mod.ko
+drivers/scsi/sr_mod.ko
+drivers/scsi/virtio_scsi.ko
+drivers/scsi/vmw_pvscsi.ko
+drivers/target/target_core*.ko
+drivers/target/loopback/tcm_loop.ko
+drivers/tty/serial/jsm/*
+drivers/uio/uio.ko
+drivers/uio/uio_pdrv_genirq.ko
+drivers/usb/host/*
+drivers/usb/storage/uas.ko
+drivers/usb/storage/usb-storage.ko
+drivers/vfio/*
+drivers/vhost/*
+drivers/video/fbdev/*
+drivers/video/vgastate.ko
+drivers/virtio/*
+drivers/watchdog/softdog.ko
+drivers/xen/*
+! find sound/core -name oss -prune -o -name *.ko -print
+fs/9p/*
+fs/aufs/aufs.ko
+fs/autofs/autofs4.ko
+fs/binfmt_misc.ko
+fs/btrfs/*
+fs/cachefiles/cachefiles.ko
+fs/ceph/*
+fs/cifs/*
+fs/configfs/*
+fs/dlm/dlm.ko
+fs/ecryptfs/*
+fs/efivarfs/*
+fs/exofs/libore.ko
+fs/ext4/*
+fs/fat/*
+fs/fscache/*
+fs/fuse/*
+fs/isofs/*
+fs/lockd/*
+fs/nfs/*
+fs/nfs_common/*
+fs/nfsd/*
+fs/nls/nls_cp437.ko
+fs/nls/nls_iso8859-1.ko
+fs/overlayfs/*
+fs/shiftfs.ko
+fs/squashfs/*
+fs/udf/*
+fs/ufs/*
+fs/xfs/*
+lib/*
+net/6lowpan/*
+net/802/*
+net/8021q/*
+net/9p/*
+net/appletalk/*
+net/atm/*
+net/ax25/*
+net/bpfilter/*
+net/bridge/*
+net/can/*
+net/ceph/libceph.ko
+net/core/*
+net/dccp/*
+net/decnet/*
+net/ieee802154/*
+net/ipv4/*
+net/ipv6/*
+net/ipx/*
+net/key/*
+net/lapb/*
+net/llc/*
+net/netfilter/*
+net/netlink/netlink_diag.ko
+net/netrom/*
+net/openvswitch/*
+net/packet/af_packet_diag.ko
+net/phonet/*
+net/rose/*
+net/rxrpc/*
+net/sched/*
+net/sctp/*
+net/sunrpc/auth_gss/auth_rpcgss.ko
+net/sunrpc/auth_gss/rpcsec_gss_krb5.ko
+net/sunrpc/sunrpc.ko
+net/tipc/*
+net/unix/unix_diag.ko
+net/vmw_vsock/*
+net/x25/*
+net/xfrm/*
+sound/drivers/pcsp/snd-pcsp.ko
+sound/pci/snd-ens1370.ko
+sound/soundcore.ko
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/control.d/linux-doc.stub
+++ linux-xilinx-zynqmp-5.4.0/debian.master/control.d/linux-doc.stub
@@ -0,0 +1,12 @@
+Package: linux-doc
+Build-Profiles: <!stage1>
+Architecture: all
+Section: doc
+Priority: optional
+Depends: ${misc:Depends}
+Description: Linux kernel specific documentation for version PKGVER
+ This package provides the various documents in the PKGVER kernel
+ Documentation/ subdirectory.  These document kernel subsystems, APIs, device
+ drivers, and so on.  See
+ /usr/share/doc/SRCPKGNAME-doc/00-INDEX for a list of what is
+ contained in each file.
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/control.d/linux-libc-dev.stub
+++ linux-xilinx-zynqmp-5.4.0/debian.master/control.d/linux-libc-dev.stub
@@ -0,0 +1,12 @@
+Package: linux-libc-dev
+Architecture: amd64 armhf arm64 i386 ppc64el riscv64 s390x
+Depends: ${misc:Depends}
+Conflicts: linux-kernel-headers
+Replaces: linux-kernel-headers
+Provides: linux-kernel-headers, aufs-dev
+Multi-Arch: same
+Description: Linux Kernel Headers for development
+ This package provides headers from the Linux kernel.  These headers
+ are used by the installed headers for GNU glibc and other system
+ libraries. They are NOT meant to be used to build third-party modules for
+ your kernel. Use SRCPKGNAME-headers-* packages for that.
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/control.d/vars.generic
+++ linux-xilinx-zynqmp-5.4.0/debian.master/control.d/vars.generic
@@ -0,0 +1,6 @@
+arch="amd64 armhf arm64 ppc64el s390x"
+supported="Generic"
+target="Geared toward desktop and server systems."
+desc="=HUMAN= SMP"
+bootloader="grub-pc [amd64] | grub-efi-amd64 [amd64] | grub-efi-ia32 [amd64] | grub [amd64] | lilo [amd64] | flash-kernel [armhf arm64] | grub-efi-arm64 [arm64] | grub-efi-arm [armhf] | grub-ieee1275 [ppc64el]"
+provides="kvm-api-4, redhat-cluster-modules, ivtv-modules, virtualbox-guest-modules [amd64]"
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/control.d/vars.generic-lpae
+++ linux-xilinx-zynqmp-5.4.0/debian.master/control.d/vars.generic-lpae
@@ -0,0 +1,6 @@
+arch="armhf"
+supported="Generic LPAE"
+target="Geared toward desktop and server systems."
+desc="=HUMAN= SMP"
+bootloader="flash-kernel [armhf] | grub-efi-arm [armhf]"
+provides="kvm-api-4, redhat-cluster-modules, ivtv-modules"
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/control.d/vars.lowlatency
+++ linux-xilinx-zynqmp-5.4.0/debian.master/control.d/vars.lowlatency
@@ -0,0 +1,6 @@
+arch="amd64"
+supported="Lowlatency"
+target="Geared toward desktop and server systems."
+desc="=HUMAN= SMP"
+bootloader="grub-pc [amd64] | grub-efi-amd64 [amd64] | grub-efi-ia32 [amd64] | grub [amd64] | lilo [amd64] | flash-kernel [armhf arm64] | grub-efi-arm64 [arm64] | grub-efi-arm [armhf]"
+provides="kvm-api-4, redhat-cluster-modules, ivtv-modules, virtualbox-guest-modules [amd64]"
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/control.stub.in
+++ linux-xilinx-zynqmp-5.4.0/debian.master/control.stub.in
@@ -0,0 +1,155 @@
+Source: SRCPKGNAME
+Section: devel
+Priority: optional
+Maintainer: Ubuntu Kernel Team <kernel-team@lists.ubuntu.com>
+Standards-Version: 3.9.4.0
+Build-Depends:
+ autoconf <!stage1>,
+ automake <!stage1>,
+ bc <!stage1>,
+ bison <!stage1>,
+ cpio,
+ curl <!stage1>,
+ debhelper (>= 9),
+ default-jdk-headless <!stage1>,
+ dh-systemd,
+ dkms <!stage1>,
+ dwarves [amd64 arm64 armhf ppc64el s390x] <!stage1>,
+ flex <!stage1>,
+ gawk <!stage1>,
+ java-common <!stage1>,
+ kernel-wedge,
+ kmod <!stage1>,
+ libaudit-dev <!stage1>,
+ libcap-dev <!stage1>,
+ libdw-dev <!stage1>,
+ libelf-dev <!stage1>,
+ libiberty-dev <!stage1>,
+ liblzma-dev <!stage1>,
+ libnewt-dev <!stage1>,
+ libnuma-dev [amd64 arm64 ppc64el s390x] <!stage1>,
+ libpci-dev <!stage1>,
+ libssl-dev <!stage1>,
+ libtool <!stage1>,
+ libudev-dev <!stage1>,
+ libunwind8-dev [amd64 arm64 armhf ppc64el] <!stage1>,
+ lz4 [amd64 s390x] <!stage1>,
+ makedumpfile [amd64] <!stage1>,
+ openssl <!stage1>,
+ pkg-config <!stage1>,
+ rsync <!stage1>,
+ uuid-dev <!stage1>,
+Build-Depends-Indep:
+ asciidoc <!stage1>,
+ bzip2 <!stage1>,
+ docbook-utils <!stage1>,
+ fig2dev <!stage1>,
+ fontconfig <!stage1>,
+ ghostscript <!stage1>,
+ python3-docutils <!stage1>,
+ python3-sphinx <!stage1>,
+ python3-sphinx-rtd-theme <!stage1>,
+ sharutils <!stage1>,
+ xmlto <!stage1>,
+Vcs-Git: git://git.launchpad.net/~ubuntu-kernel/ubuntu/+source/linux/+git/=SERIES=
+XS-Testsuite: autopkgtest
+#XS-Testsuite-Depends: gcc-4.7 binutils
+
+Package: linux-source-PKGVER
+Build-Profiles: <!stage1>
+Architecture: all
+Section: devel
+Priority: optional
+Provides: linux-source
+Depends: ${misc:Depends}, binutils, bzip2, coreutils
+Recommends: libc-dev, gcc, make
+Suggests: libncurses-dev | ncurses-dev, kernel-package, libqt3-dev
+Description: Linux kernel source for version PKGVER with Ubuntu patches
+ This package provides the source code for the Linux kernel version
+ PKGVER.
+ .
+ This package is mainly meant for other packages to use, in order to build
+ custom flavours.
+ .
+ If you wish to use this package to create a custom Linux kernel, then it
+ is suggested that you investigate the package kernel-package, which has
+ been designed to ease the task of creating kernel image packages.
+ .
+ If you are simply trying to build third-party modules for your kernel,
+ you do not want this package. Install the appropriate linux-headers
+ package instead.
+
+Package: SRCPKGNAME-headers-PKGVER-ABINUM
+Build-Profiles: <!stage1>
+Architecture: all
+Multi-Arch: foreign
+Section: devel
+Priority: optional
+Depends: ${misc:Depends}, coreutils
+Description: Header files related to Linux kernel version PKGVER
+ This package provides kernel header files for version PKGVER, for sites
+ that want the latest kernel headers. Please read
+ /usr/share/doc/SRCPKGNAME-headers-PKGVER-ABINUM/debian.README.gz for details
+
+Package: SRCPKGNAME-tools-common
+Build-Profiles: <!stage1>
+Architecture: all
+Multi-Arch: foreign
+Section: kernel
+Priority: optional
+Depends: ${misc:Depends}, lsb-release
+Conflicts: linux-oem-5.6-tools-common
+Replaces: linux-oem-5.6-tools-common
+Description: Linux kernel version specific tools for version PKGVER
+ This package provides the architecture independent parts for kernel
+ version locked tools (such as perf and x86_energy_perf_policy) for
+ version PKGVER.
+
+Package: SRCPKGNAME-tools-PKGVER-ABINUM
+Build-Profiles: <!stage1>
+Architecture: amd64 armhf arm64 ppc64el s390x
+Section: devel
+Priority: optional
+Depends: ${misc:Depends}, ${shlibs:Depends}, linux-tools-common
+Description: Linux kernel version specific tools for version PKGVER-ABINUM
+ This package provides the architecture dependant parts for kernel
+ version locked tools (such as perf and x86_energy_perf_policy) for
+ version PKGVER-ABINUM on
+ =HUMAN=.
+ You probably want to install linux-tools-PKGVER-ABINUM-<flavour>.
+
+Package: SRCPKGNAME-cloud-tools-common
+Build-Profiles: <!stage1>
+Architecture: all
+Multi-Arch: foreign
+Section: kernel
+Priority: optional
+Depends: ${misc:Depends}
+Description: Linux kernel version specific cloud tools for version PKGVER
+ This package provides the architecture independent parts for kernel
+ version locked tools for cloud tools for version PKGVER.
+
+Package: SRCPKGNAME-cloud-tools-PKGVER-ABINUM
+Build-Profiles: <!stage1>
+Architecture: amd64 armhf
+Section: devel
+Priority: optional
+Depends: ${misc:Depends}, ${shlibs:Depends}, linux-cloud-tools-common
+Description: Linux kernel version specific cloud tools for version PKGVER-ABINUM
+ This package provides the architecture dependant parts for kernel
+ version locked tools for cloud tools for version PKGVER-ABINUM on
+ =HUMAN=.
+ You probably want to install linux-cloud-tools-PKGVER-ABINUM-<flavour>.
+
+Package: SRCPKGNAME-tools-host
+Build-Profiles: <!stage1>
+Architecture: all
+Multi-Arch: foreign
+Section: kernel
+Priority: optional
+Depends: ${misc:Depends}, python3
+Conflicts: linux-oem-5.6-tools-host
+Replaces: linux-oem-5.6-tools-host
+Description: Linux kernel VM host tools
+ This package provides kernel tools useful for VM hosts.
+
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/copyright
+++ linux-xilinx-zynqmp-5.4.0/debian.master/copyright
@@ -0,0 +1,29 @@
+This is the Ubuntu prepackaged version of the Linux kernel.
+Linux was written by Linus Torvalds <Linus.Torvalds@cs.Helsinki.FI>
+and others.
+
+This package was put together by the Ubuntu Kernel Team, from
+sources retrieved from upstream linux git.
+The sources may be found at most Linux ftp sites, including 
+ftp://ftp.kernel.org/pub/linux/kernel/
+
+This package is currently maintained by the
+Ubuntu Kernel Team <ubuntu-kernel@lists.ubuntu.com>
+
+Linux is copyrighted by Linus Torvalds and others.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+On Ubuntu Linux systems, the complete text of the GNU General
+Public License v2 can be found in `/usr/share/common-licenses/GPL-2'.
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/firmware/README.txt
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/firmware/README.txt
@@ -0,0 +1,4 @@
+#
+# Place the names of udeb modules into this directory that require
+# runtime firmware.
+#
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/firmware/amd64/README.txt
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/firmware/amd64/README.txt
@@ -0,0 +1,4 @@
+#
+# Place the names of udeb modules into this directory that require
+# runtime firmware.
+#
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/firmware/amd64/nic-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/firmware/amd64/nic-modules
@@ -0,0 +1 @@
+#include <nic-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/firmware/amd64/scsi-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/firmware/amd64/scsi-modules
@@ -0,0 +1 @@
+#include <scsi-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/firmware/arm64/README.txt
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/firmware/arm64/README.txt
@@ -0,0 +1,4 @@
+#
+# Place the names of udeb modules into this directory that require
+# runtime firmware.
+#
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/firmware/arm64/nic-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/firmware/arm64/nic-modules
@@ -0,0 +1 @@
+#include <nic-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/firmware/arm64/scsi-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/firmware/arm64/scsi-modules
@@ -0,0 +1 @@
+#include <scsi-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/firmware/armhf/README.txt
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/firmware/armhf/README.txt
@@ -0,0 +1,4 @@
+#
+# Place the names of udeb modules into this directory that require
+# runtime firmware.
+#
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/firmware/i386/README.txt
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/firmware/i386/README.txt
@@ -0,0 +1,4 @@
+#
+# Place the names of udeb modules into this directory that require
+# runtime firmware.
+#
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/firmware/i386/nic-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/firmware/i386/nic-modules
@@ -0,0 +1 @@
+#include <nic-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/firmware/i386/scsi-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/firmware/i386/scsi-modules
@@ -0,0 +1 @@
+#include <scsi-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/firmware/nic-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/firmware/nic-modules
@@ -0,0 +1,14 @@
+e100/d101m_ucode.bin ?
+e100/d101s_ucode.bin ?
+e100/d102e_ucode.bin ?
+bnx2/bnx2-mips-09-6.2.1b.fw ?
+bnx2/bnx2-rv2p-06-6.0.15.fw ?
+bnx2/bnx2-mips-06-6.2.3.fw ?
+bnx2/bnx2-rv2p-09-6.0.17.fw ?
+bnx2/bnx2-rv2p-09ax-6.0.17.fw ?
+bnx2x/bnx2x-e1h-7.12.30.0.fw ?
+bnx2x/bnx2x-e1-7.12.30.0.fw ?
+bnx2x/bnx2x-e2-7.12.30.0.fw ?
+tigon/tg3_tso5.bin ?
+tigon/tg3_tso.bin ?
+tigon/tg3.bin ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/firmware/powerpc/README.txt
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/firmware/powerpc/README.txt
@@ -0,0 +1,4 @@
+#
+# Place the names of udeb modules into this directory that require
+# runtime firmware.
+#
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/firmware/powerpc/nic-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/firmware/powerpc/nic-modules
@@ -0,0 +1 @@
+#include <nic-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/firmware/powerpc/scsi-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/firmware/powerpc/scsi-modules
@@ -0,0 +1 @@
+#include <scsi-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/firmware/ppc64el/README.txt
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/firmware/ppc64el/README.txt
@@ -0,0 +1,4 @@
+#
+# Place the names of udeb modules into this directory that require
+# runtime firmware.
+#
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/firmware/ppc64el/nic-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/firmware/ppc64el/nic-modules
@@ -0,0 +1 @@
+#include <nic-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/firmware/ppc64el/scsi-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/firmware/ppc64el/scsi-modules
@@ -0,0 +1 @@
+#include <scsi-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/firmware/s390x/README.txt
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/firmware/s390x/README.txt
@@ -0,0 +1,4 @@
+#
+# Place the names of udeb modules into this directory that require
+# runtime firmware.
+#
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/firmware/s390x/nic-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/firmware/s390x/nic-modules
@@ -0,0 +1 @@
+#include <nic-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/firmware/s390x/scsi-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/firmware/s390x/scsi-modules
@@ -0,0 +1 @@
+#include <scsi-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/firmware/scsi-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/firmware/scsi-modules
@@ -0,0 +1,3 @@
+qlogic/1040.bin ?
+qlogic/12160.bin ?
+qlogic/1280.bin ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/kernel-versions
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/kernel-versions
@@ -0,0 +1,16 @@
+# arch	version		flavour		installedname			suffix	bdep
+amd64	-		generic		-				-	-
+
+i386	-		generic		-				-	-
+
+armhf	-		generic		-				-	-
+armhf	-		generic-lpae	-				-	-
+
+arm64	-		generic		-				-	-
+
+ppc64el	-		generic		-				-	-
+
+s390x	-		generic		-				-	-
+
+# Ports
+# arch	version		flavour		installedname			suffix	bdep
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64-virtual/block-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64-virtual/block-modules
@@ -0,0 +1 @@
+#include <block-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64-virtual/crypto-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64-virtual/crypto-modules
@@ -0,0 +1 @@
+#include <crypto-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64-virtual/fat-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64-virtual/fat-modules
@@ -0,0 +1 @@
+#include <fat-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64-virtual/fb-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64-virtual/fb-modules
@@ -0,0 +1 @@
+#include <fb-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64-virtual/floppy-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64-virtual/floppy-modules
@@ -0,0 +1 @@
+#include <floppy-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64-virtual/fs-core-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64-virtual/fs-core-modules
@@ -0,0 +1 @@
+#include <fs-core-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64-virtual/fs-secondary-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64-virtual/fs-secondary-modules
@@ -0,0 +1 @@
+#include <fs-secondary-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64-virtual/kernel-image
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64-virtual/kernel-image
@@ -0,0 +1 @@
+#include <kernel-image>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64-virtual/md-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64-virtual/md-modules
@@ -0,0 +1 @@
+#include <md-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64-virtual/message-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64-virtual/message-modules
@@ -0,0 +1 @@
+#include <message-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64-virtual/mouse-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64-virtual/mouse-modules
@@ -0,0 +1 @@
+#include <mouse-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64-virtual/multipath-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64-virtual/multipath-modules
@@ -0,0 +1 @@
+#include <multipath-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64-virtual/nic-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64-virtual/nic-modules
@@ -0,0 +1 @@
+#include <nic-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64-virtual/nic-shared-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64-virtual/nic-shared-modules
@@ -0,0 +1 @@
+#include <nic-shared-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64-virtual/parport-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64-virtual/parport-modules
@@ -0,0 +1 @@
+#include <parport-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64-virtual/scsi-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64-virtual/scsi-modules
@@ -0,0 +1,2 @@
+#include <scsi-modules>
+ipr ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64-virtual/serial-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64-virtual/serial-modules
@@ -0,0 +1 @@
+#include <serial-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64-virtual/storage-core-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64-virtual/storage-core-modules
@@ -0,0 +1 @@
+#include <storage-core-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64-virtual/virtio-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64-virtual/virtio-modules
@@ -0,0 +1 @@
+#include <virtio-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64-virtual/vlan-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64-virtual/vlan-modules
@@ -0,0 +1 @@
+#include <vlan-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64/block-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64/block-modules
@@ -0,0 +1 @@
+#include <block-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64/crypto-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64/crypto-modules
@@ -0,0 +1 @@
+#include <crypto-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64/fat-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64/fat-modules
@@ -0,0 +1 @@
+#include <fat-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64/fb-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64/fb-modules
@@ -0,0 +1 @@
+#include <fb-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64/firewire-core-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64/firewire-core-modules
@@ -0,0 +1 @@
+#include <firewire-core-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64/floppy-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64/floppy-modules
@@ -0,0 +1 @@
+#include <floppy-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64/fs-core-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64/fs-core-modules
@@ -0,0 +1 @@
+#include <fs-core-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64/fs-secondary-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64/fs-secondary-modules
@@ -0,0 +1 @@
+#include <fs-secondary-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64/input-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64/input-modules
@@ -0,0 +1 @@
+#include <input-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64/ipmi-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64/ipmi-modules
@@ -0,0 +1 @@
+#include <ipmi-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64/kernel-image
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64/kernel-image
@@ -0,0 +1 @@
+#include <kernel-image>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64/md-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64/md-modules
@@ -0,0 +1 @@
+#include <md-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64/message-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64/message-modules
@@ -0,0 +1 @@
+#include <message-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64/mouse-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64/mouse-modules
@@ -0,0 +1 @@
+#include <mouse-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64/multipath-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64/multipath-modules
@@ -0,0 +1 @@
+#include <multipath-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64/nfs-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64/nfs-modules
@@ -0,0 +1 @@
+#include <nfs-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64/nic-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64/nic-modules
@@ -0,0 +1 @@
+#include <nic-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64/nic-pcmcia-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64/nic-pcmcia-modules
@@ -0,0 +1 @@
+#include <nic-pcmcia-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64/nic-shared-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64/nic-shared-modules
@@ -0,0 +1 @@
+#include <nic-shared-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64/nic-usb-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64/nic-usb-modules
@@ -0,0 +1 @@
+#include <nic-usb-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64/parport-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64/parport-modules
@@ -0,0 +1 @@
+#include <parport-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64/pata-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64/pata-modules
@@ -0,0 +1 @@
+#include <pata-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64/pcmcia-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64/pcmcia-modules
@@ -0,0 +1 @@
+#include <pcmcia-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64/pcmcia-storage-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64/pcmcia-storage-modules
@@ -0,0 +1 @@
+#include <pcmcia-storage-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64/plip-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64/plip-modules
@@ -0,0 +1 @@
+#include <plip-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64/ppp-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64/ppp-modules
@@ -0,0 +1 @@
+#include <ppp-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64/sata-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64/sata-modules
@@ -0,0 +1 @@
+#include <sata-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64/scsi-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64/scsi-modules
@@ -0,0 +1,2 @@
+#include <scsi-modules>
+ipr ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64/serial-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64/serial-modules
@@ -0,0 +1 @@
+#include <serial-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64/speakup-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64/speakup-modules
@@ -0,0 +1 @@
+#include <speakup-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64/storage-core-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64/storage-core-modules
@@ -0,0 +1 @@
+#include <storage-core-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64/usb-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64/usb-modules
@@ -0,0 +1 @@
+#include <usb-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64/virtio-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64/virtio-modules
@@ -0,0 +1 @@
+#include <virtio-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/amd64/vlan-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/amd64/vlan-modules
@@ -0,0 +1 @@
+#include <vlan-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/arm64/block-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/arm64/block-modules
@@ -0,0 +1 @@
+#include <block-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/arm64/crypto-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/arm64/crypto-modules
@@ -0,0 +1 @@
+#include <crypto-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/arm64/fat-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/arm64/fat-modules
@@ -0,0 +1 @@
+#include <fat-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/arm64/fs-core-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/arm64/fs-core-modules
@@ -0,0 +1 @@
+#include <fs-core-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/arm64/fs-secondary-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/arm64/fs-secondary-modules
@@ -0,0 +1 @@
+#include <fs-secondary-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/arm64/input-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/arm64/input-modules
@@ -0,0 +1 @@
+#include <input-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/arm64/ipmi-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/arm64/ipmi-modules
@@ -0,0 +1 @@
+#include <ipmi-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/arm64/kernel-image
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/arm64/kernel-image
@@ -0,0 +1 @@
+#include <kernel-image>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/arm64/md-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/arm64/md-modules
@@ -0,0 +1 @@
+#include <md-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/arm64/message-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/arm64/message-modules
@@ -0,0 +1 @@
+#include <message-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/arm64/mouse-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/arm64/mouse-modules
@@ -0,0 +1 @@
+#include <mouse-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/arm64/multipath-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/arm64/multipath-modules
@@ -0,0 +1 @@
+#include <multipath-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/arm64/nfs-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/arm64/nfs-modules
@@ -0,0 +1 @@
+#include <nfs-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/arm64/nic-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/arm64/nic-modules
@@ -0,0 +1 @@
+#include <nic-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/arm64/nic-shared-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/arm64/nic-shared-modules
@@ -0,0 +1 @@
+#include <nic-shared-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/arm64/nic-usb-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/arm64/nic-usb-modules
@@ -0,0 +1 @@
+#include <nic-usb-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/arm64/parport-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/arm64/parport-modules
@@ -0,0 +1 @@
+#include <parport-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/arm64/plip-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/arm64/plip-modules
@@ -0,0 +1 @@
+#include <plip-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/arm64/ppp-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/arm64/ppp-modules
@@ -0,0 +1 @@
+#include <ppp-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/arm64/sata-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/arm64/sata-modules
@@ -0,0 +1 @@
+#include <sata-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/arm64/scsi-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/arm64/scsi-modules
@@ -0,0 +1,2 @@
+#include <scsi-modules>
+ipr ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/arm64/speakup-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/arm64/speakup-modules
@@ -0,0 +1 @@
+#include <speakup-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/arm64/storage-core-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/arm64/storage-core-modules
@@ -0,0 +1 @@
+#include <storage-core-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/arm64/usb-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/arm64/usb-modules
@@ -0,0 +1 @@
+#include <usb-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/arm64/virtio-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/arm64/virtio-modules
@@ -0,0 +1 @@
+#include <virtio-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/arm64/vlan-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/arm64/vlan-modules
@@ -0,0 +1 @@
+#include <vlan-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/armhf/block-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/armhf/block-modules
@@ -0,0 +1 @@
+#include <block-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/armhf/crypto-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/armhf/crypto-modules
@@ -0,0 +1 @@
+#include <crypto-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/armhf/fat-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/armhf/fat-modules
@@ -0,0 +1 @@
+#include <fat-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/armhf/fs-core-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/armhf/fs-core-modules
@@ -0,0 +1 @@
+#include <fs-core-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/armhf/fs-secondary-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/armhf/fs-secondary-modules
@@ -0,0 +1 @@
+#include <fs-secondary-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/armhf/input-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/armhf/input-modules
@@ -0,0 +1 @@
+#include <input-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/armhf/ipmi-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/armhf/ipmi-modules
@@ -0,0 +1 @@
+#include <ipmi-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/armhf/kernel-image
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/armhf/kernel-image
@@ -0,0 +1 @@
+#include <kernel-image>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/armhf/md-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/armhf/md-modules
@@ -0,0 +1 @@
+#include <md-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/armhf/mouse-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/armhf/mouse-modules
@@ -0,0 +1 @@
+#include <mouse-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/armhf/multipath-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/armhf/multipath-modules
@@ -0,0 +1 @@
+#include <multipath-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/armhf/nfs-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/armhf/nfs-modules
@@ -0,0 +1 @@
+#include <nfs-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/armhf/nic-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/armhf/nic-modules
@@ -0,0 +1 @@
+#include <nic-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/armhf/nic-shared-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/armhf/nic-shared-modules
@@ -0,0 +1 @@
+#include <nic-shared-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/armhf/nic-usb-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/armhf/nic-usb-modules
@@ -0,0 +1 @@
+#include <nic-usb-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/armhf/parport-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/armhf/parport-modules
@@ -0,0 +1 @@
+#include <parport-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/armhf/plip-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/armhf/plip-modules
@@ -0,0 +1 @@
+#include <plip-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/armhf/ppp-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/armhf/ppp-modules
@@ -0,0 +1 @@
+#include <ppp-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/armhf/sata-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/armhf/sata-modules
@@ -0,0 +1 @@
+#include <sata-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/armhf/scsi-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/armhf/scsi-modules
@@ -0,0 +1,2 @@
+#include <scsi-modules>
+ipr ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/armhf/speakup-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/armhf/speakup-modules
@@ -0,0 +1 @@
+#include <speakup-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/armhf/storage-core-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/armhf/storage-core-modules
@@ -0,0 +1 @@
+#include <storage-core-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/armhf/usb-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/armhf/usb-modules
@@ -0,0 +1 @@
+#include <usb-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/armhf/vlan-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/armhf/vlan-modules
@@ -0,0 +1 @@
+#include <vlan-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/block-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/block-modules
@@ -0,0 +1,43 @@
+aoe ?
+aten ?
+bcm2835 ?
+bpck ?
+bpck6 ?
+cciss ?
+comm ?
+cpqarray ?
+DAC960 ?
+dstr ?
+epat ?
+epia ?
+fit2 ?
+fit3 ?
+friq ?
+frpw ?
+hpsa ?
+hio ?
+kbic ?
+ktti ?
+nbd ?
+nvme ?
+on20 ?
+on26 ?
+paride ?
+pcd ?
+pd ?
+pf ?
+pg ?
+pt ?
+sdhci-tegra ?
+sx8 ?
+umem ?
+virtio_blk ?
+xen-blkfront ?
+mtip32xx ?
+mmc_block ?
+sdhci ?
+sdhci-pci ?
+sdhci-acpi ?
+tifm_sd ?
+dw_mmc ?
+dw_mmc_pltfm ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/block-modules.powerpc
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/block-modules.powerpc
@@ -0,0 +1,31 @@
+aoe ?
+aten ?
+bpck ?
+bpck6 ?
+cciss ?
+comm ?
+cpqarray ?
+DAC960 ?
+dstr ?
+epat ?
+epia ?
+fit2 ?
+fit3 ?
+friq ?
+frpw ?
+kbic ?
+ktti ?
+nbd ?
+on20 ?
+on26 ?
+paride ?
+pcd ?
+pd ?
+pf ?
+pg ?
+ps3disk ?
+ps3vram ?
+pt ?
+sx8 ?
+umem ?
+virtio_blk ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/crypto-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/crypto-modules
@@ -0,0 +1,78 @@
+aesni-intel ?
+aes-x86_64 ?
+af_alg ?
+algif_hash ?
+algif_skcipher ?
+ansi_cprng ?
+anubis ?
+arc4 ?
+async_memcpy ?
+async_pq ?
+async_raid6_recov ?
+async_tx ?
+async_xor ?
+authenc ?
+authencesn ?
+blowfish_common ?
+blowfish_generic ?
+blowfish-x86_64 ?
+camellia ?
+cast5 ?
+cast6 ?
+ccm ?
+crc32_generic ?
+crc32c_generic ?
+crc32-vx_s390 ?
+cryptd ?
+cryptoloop ?
+crypto_null ?
+crypto_user ?
+ctr ?
+cts ?
+des_generic ?
+fcrypt ?
+gcm ?
+gf128mul ?
+ghash-clmulni-intel ?
+ghash-generic ?
+khazad ?
+lrw ?
+lzo ?
+md4 ?
+michael_mic ?
+padlock-aes ?
+padlock-sha ?
+paes_s390 ?
+pcbc ?
+pcrypt ?
+pkey ?
+raid6test ?
+rmd128 ?
+rmd160 ?
+rmd256 ?
+rmd320 ?
+salsa20_generic ?
+salsa20-x86_64 ?
+seed ?
+seqiv ?
+serpent_generic ?
+serpent-sse2-x86_64 ?
+sha1-ssse3 ?
+sha512_generic ?
+tcrypt ?
+tea ?
+tgr192 ?
+twofish_common ?
+twofish_generic ?
+twofish-x86_64 ?
+twofish-x86_64-3way ?
+vmac ?
+wp512 ?
+xcbc ?
+xor ?
+xts ?
+zcrypt ?
+zcrypt_cex2a ?
+zcrypt_cex4 ?
+zcrypt_pcixcc ?
+zlib ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/dasd-extra-modules.s390x
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/dasd-extra-modules.s390x
@@ -0,0 +1 @@
+dasd_diag_mod ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/dasd-modules.s390x
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/dasd-modules.s390x
@@ -0,0 +1,3 @@
+dasd_mod ?
+dasd_fba_mod ?
+dasd_eckd_mod ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/fat-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/fat-modules
@@ -0,0 +1,7 @@
+fat ?
+vfat ?
+
+# Supporting modules ?
+nls_cp437 ?
+nls_iso8859-1 ?
+nls_utf8 ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/fb-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/fb-modules
@@ -0,0 +1,3 @@
+fbcon ?
+vesafb ?
+vga16fb ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/firewire-core-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/firewire-core-modules
@@ -0,0 +1,4 @@
+firewire-core ?
+firewire-ohci ?
+firewire-sbp2 ?
+firewire-net ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/floppy-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/floppy-modules
@@ -0,0 +1 @@
+floppy ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/fs-core-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/fs-core-modules
@@ -0,0 +1,6 @@
+ext2 ?
+ext4 ?
+jfs ?
+reiserfs ?
+xfs ?
+zfs ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/fs-secondary-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/fs-secondary-modules
@@ -0,0 +1,5 @@
+btrfs ?
+fuse ?
+ntfs ?
+hfs ?
+hfsplus ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386-virtual/block-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386-virtual/block-modules
@@ -0,0 +1 @@
+#include <block-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386-virtual/crypto-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386-virtual/crypto-modules
@@ -0,0 +1 @@
+#include <crypto-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386-virtual/fat-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386-virtual/fat-modules
@@ -0,0 +1 @@
+#include <fat-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386-virtual/fb-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386-virtual/fb-modules
@@ -0,0 +1 @@
+#include <fb-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386-virtual/floppy-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386-virtual/floppy-modules
@@ -0,0 +1 @@
+#include <floppy-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386-virtual/fs-core-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386-virtual/fs-core-modules
@@ -0,0 +1 @@
+#include <fs-core-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386-virtual/fs-secondary-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386-virtual/fs-secondary-modules
@@ -0,0 +1 @@
+#include <fs-secondary-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386-virtual/kernel-image
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386-virtual/kernel-image
@@ -0,0 +1 @@
+#include <kernel-image>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386-virtual/md-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386-virtual/md-modules
@@ -0,0 +1 @@
+#include <md-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386-virtual/message-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386-virtual/message-modules
@@ -0,0 +1 @@
+#include <message-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386-virtual/mouse-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386-virtual/mouse-modules
@@ -0,0 +1 @@
+#include <mouse-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386-virtual/multipath-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386-virtual/multipath-modules
@@ -0,0 +1 @@
+#include <multipath-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386-virtual/nic-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386-virtual/nic-modules
@@ -0,0 +1 @@
+#include <nic-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386-virtual/nic-shared-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386-virtual/nic-shared-modules
@@ -0,0 +1 @@
+#include <nic-shared-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386-virtual/parport-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386-virtual/parport-modules
@@ -0,0 +1 @@
+#include <parport-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386-virtual/scsi-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386-virtual/scsi-modules
@@ -0,0 +1,2 @@
+#include <scsi-modules>
+ipr ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386-virtual/serial-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386-virtual/serial-modules
@@ -0,0 +1 @@
+#include <serial-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386-virtual/storage-core-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386-virtual/storage-core-modules
@@ -0,0 +1 @@
+#include <storage-core-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386-virtual/virtio-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386-virtual/virtio-modules
@@ -0,0 +1 @@
+#include <virtio-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386-virtual/vlan-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386-virtual/vlan-modules
@@ -0,0 +1 @@
+#include <vlan-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386/block-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386/block-modules
@@ -0,0 +1 @@
+#include <block-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386/crypto-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386/crypto-modules
@@ -0,0 +1 @@
+#include <crypto-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386/fat-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386/fat-modules
@@ -0,0 +1 @@
+#include <fat-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386/fb-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386/fb-modules
@@ -0,0 +1 @@
+#include <fb-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386/firewire-core-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386/firewire-core-modules
@@ -0,0 +1 @@
+#include <firewire-core-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386/floppy-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386/floppy-modules
@@ -0,0 +1 @@
+#include <floppy-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386/fs-core-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386/fs-core-modules
@@ -0,0 +1 @@
+#include <fs-core-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386/fs-secondary-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386/fs-secondary-modules
@@ -0,0 +1 @@
+#include <fs-secondary-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386/input-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386/input-modules
@@ -0,0 +1 @@
+#include <input-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386/ipmi-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386/ipmi-modules
@@ -0,0 +1 @@
+#include <ipmi-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386/kernel-image
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386/kernel-image
@@ -0,0 +1 @@
+#include <kernel-image>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386/md-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386/md-modules
@@ -0,0 +1 @@
+#include <md-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386/message-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386/message-modules
@@ -0,0 +1 @@
+#include <message-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386/mouse-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386/mouse-modules
@@ -0,0 +1 @@
+#include <mouse-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386/multipath-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386/multipath-modules
@@ -0,0 +1 @@
+#include <multipath-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386/nfs-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386/nfs-modules
@@ -0,0 +1 @@
+#include <nfs-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386/nic-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386/nic-modules
@@ -0,0 +1 @@
+#include <nic-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386/nic-pcmcia-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386/nic-pcmcia-modules
@@ -0,0 +1 @@
+#include <nic-pcmcia-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386/nic-shared-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386/nic-shared-modules
@@ -0,0 +1 @@
+#include <nic-shared-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386/nic-usb-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386/nic-usb-modules
@@ -0,0 +1 @@
+#include <nic-usb-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386/parport-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386/parport-modules
@@ -0,0 +1 @@
+#include <parport-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386/pata-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386/pata-modules
@@ -0,0 +1 @@
+#include <pata-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386/pcmcia-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386/pcmcia-modules
@@ -0,0 +1 @@
+#include <pcmcia-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386/pcmcia-storage-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386/pcmcia-storage-modules
@@ -0,0 +1 @@
+#include <pcmcia-storage-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386/plip-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386/plip-modules
@@ -0,0 +1 @@
+#include <plip-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386/ppp-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386/ppp-modules
@@ -0,0 +1 @@
+#include <ppp-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386/sata-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386/sata-modules
@@ -0,0 +1 @@
+#include <sata-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386/scsi-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386/scsi-modules
@@ -0,0 +1,2 @@
+#include <scsi-modules>
+ipr ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386/serial-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386/serial-modules
@@ -0,0 +1 @@
+#include <serial-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386/speakup-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386/speakup-modules
@@ -0,0 +1 @@
+#include <speakup-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386/storage-core-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386/storage-core-modules
@@ -0,0 +1 @@
+#include <storage-core-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386/usb-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386/usb-modules
@@ -0,0 +1 @@
+#include <usb-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386/virtio-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386/virtio-modules
@@ -0,0 +1 @@
+#include <virtio-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/i386/vlan-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/i386/vlan-modules
@@ -0,0 +1 @@
+#include <vlan-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/input-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/input-modules
@@ -0,0 +1,71 @@
+hid ?
+hid-a4tech ?
+hid-apple ?
+hid-appleir ?
+hid-aureal ?
+hid-belkin ?
+hid-bright ?
+hid-cherry ?
+hid-chicony ?
+hid-corsair ?
+hid-cp2112 ?
+hid-cypress ?
+hid-dell ?
+hid-elecom ?
+hid-elo ?
+hid-ezkey ?
+hid-generic ?
+hid-gfrm ?
+hid-gt683r ?
+hid-gyration ?
+hid-holtek-kbd ?
+hid-holtek-mouse ?
+hid-hyperv ?
+hid-kensington ?
+hid-keytouch ?
+hid-kye ?
+hid-lcpower ?
+hid-lenovo ?
+hid-logitech ?
+hid-logitech-dj ?
+hid-logitech-hidpp ?
+hid-magicmouse ?
+hid-microsoft ?
+hid-monterey ?
+hid-multitouch ?
+hid-ntrig ?
+hid-ortek ?
+hid-penmount ?
+hid-petalynx ?
+hid-picolcd ?
+hid-pl ?
+hid-plantronics ?
+hid-primax ?
+hid-rmi ?
+hid-roccat ?
+hid-roccat-arvo ?
+hid-roccat-common ?
+hid-roccat-isku ?
+hid-roccat-kone ?
+hid-roccat-koneplus ?
+hid-roccat-konepure ?
+hid-roccat-kovaplus ?
+hid-roccat-lua ?
+hid-roccat-pyra ?
+hid-roccat-ryos ?
+hid-roccat-savu ?
+hid-samsung ?
+hid-sony ?
+hid-speedlink ?
+hid-sunplus ?
+hid-thingm ?
+hid-tivo ?
+hid-topseed ?
+hid-twinhan ?
+hid-uclogic ?
+hid-waltop ?
+hid-wiimote ?
+hid-xinmo ?
+hid-zydacron ?
+uhid ?
+usbhid ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/ipmi-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/ipmi-modules
@@ -0,0 +1,5 @@
+ipmi_devintf ?
+ipmi_msghandler ?
+ipmi_poweroff ?
+ipmi_si ?
+ipmi_watchdog ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/kernel-image
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/kernel-image
@@ -0,0 +1,31 @@
+ast ?
+gpio-pca953x ?
+gpio-regulator ?
+hibmc-drm ?
+i2c-mux ?
+i2c-mux-pinctrl ?
+i2c-tegra ?
+max8907 ?
+max8907-regulator ?
+nvec ?
+nvec_kbd ?
+nvec_paz00 ?
+nvec_power ?
+nvec_ps2 ?
+palmas-regulator ?
+rtc-em3027 ?
+rtc-max8907 ?
+rtc-palmas ?
+rtc-tps6586x ?
+rtc-tps65910 ?
+tps51632-regulator ?
+tps62360-regulator ?
+tps65090-charger ?
+tps65090-regulator ?
+tps6586x-regulator ?
+tps65910-regulator ?
+host1x ?
+tegra-drm ?
+pwm_bl ?
+pwm-tegra ?
+panel-simple ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/md-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/md-modules
@@ -0,0 +1,16 @@
+dm-crypt ?
+dm-mirror ?
+dm-raid ?
+dm-snapshot ?
+dm-zero ?
+faulty ?
+linear ?
+multipath ?
+raid0 ?
+raid1 ?
+raid10 ?
+raid456 ?
+
+# Extras
+dm-raid45 ?
+dm-loop ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/message-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/message-modules
@@ -0,0 +1,9 @@
+mptbase ?
+mptctl ?
+mptfc ?
+mptlan ?
+mptsas ?
+mpt2sas ?
+mpt3sas ?
+mptscsih ?
+mptspi ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/message-modules.powerpc
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/message-modules.powerpc
@@ -0,0 +1,7 @@
+mptbase
+mptctl
+mptfc
+mptlan
+mptsas
+mptscsih
+mptspi
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/mouse-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/mouse-modules
@@ -0,0 +1,2 @@
+psmouse ?
+usbmouse ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/multipath-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/multipath-modules
@@ -0,0 +1,4 @@
+dm-multipath ?
+dm-round-robin ?
+dm-service-time ?
+dm-queue-length ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/nfs-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/nfs-modules
@@ -0,0 +1,6 @@
+nfs ?
+nfs_acl ?
+nfsv3 ?
+lockd ?
+sunrpc ?
+cifs ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/nic-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/nic-modules
@@ -0,0 +1,209 @@
+3c359 ?
+3c501 ?
+3c503 ?
+3c505 ?
+3c507 ?
+3c509 ?
+3c515 ?
+3c523 ?
+3c527 ?
+3c59x ?
+8139cp ?
+8139too ?
+82596 ?
+abyss ?
+ac3200 ?
+adm8211 ?
+airo ?
+airport ?
+alx ?
+amd8111e ?
+amd-xgbe ?
+aquantia ?
+arcnet ?
+arc-rawmode ?
+arc-rimi ?
+arlan ?
+at1700 ?
+ath5k ?
+ath9k ?
+ath9k_htc ?
+atl1 ?
+atl1c ?
+atl1e ?
+atl2 ?
+atmel ?
+atmel_pci ?
+b44 ?
+bcm87xx ?
+be2net ?
+bmac ?
+bnx2 ?
+bnx2x ?
+bnxt_en ?
+bonding ?
+brcmfmac ?
+brcmsmac ?
+broadcom ?
+xgmac ?
+cassini ?
+ccwgroup ?
+com20020 ?
+com20020-pci ?
+com90io ?
+com90xx ?
+cs89x0 ?
+ctcm ?
+cxgb4 ?
+de2104x ?
+de4x5 ?
+de600 ?
+de620 ?
+defxx ?
+depca ?
+dl2k ?
+dmfe ?
+dummy ?
+e100 ?
+e1000 ?
+e1000e ?
+e2100 ?
+eepro ?
+eepro100 ?
+eexpress ?
+enic ?
+epic100 ?
+eql ?
+es3210 ?
+eth16i ?
+ewrk3 ?
+fealnx ?
+forcedeth ?
+fsm ?
+ibmveth ?
+ibmvnic ?
+igb ?
+ps3_gelic ?
+hamachi ?
+hclge ?
+hermes ?
+hfi1 ?
+hinic ?
+hns_dsaf ?
+hns_enet_drv ?
+hns_mdio ?
+hns3 ?
+hp ?
+hp100 ?
+hp-plus ?
+i40e ?
+i40evf ?
+ibmtr ?
+ipddp ?
+ipw2100 ?
+ipw2200 ?
+iwl3945 ?
+iwl4965 ?
+iwl-legacy ?
+iwldvm ?
+iwlmvm ?
+iwlwifi ?
+ixgb ?
+ixgbe ?
+lance ?
+lanstreamer ?
+lcs ?
+lasi_82596 ?
+lne390 ?
+lp486e ?
+mace ?
+marvell ?
+mdio-thunder ?
+mlx4_core ?
+mlx4_en ?
+mlx5_core ?
+mv643xx_eth ?
+myri_sbus ?
+natsemi ?
+ne ?
+ne2 ?
+ne2k-pci ?
+ne3210 ?
+netconsole ?
+netiucv ?
+netsec ?
+netxen_nic ?
+ni5010 ?
+ni52 ?
+ni65 ?
+nicpf ?
+nicvf ?
+niu ?
+ns83820 ?
+olympic ?
+orinoco ?
+orinoco_pci ?
+orinoco_plx ?
+orinoco_tmd ?
+pcnet32 ?
+qcom-emac ?
+qede ?
+qeth ?
+qeth_l2 ?
+qeth_l3 ?
+qlcnic ?
+r815x ?
+r8169 ?
+rate_control ?
+realtek ?
+rfc1051 ?
+rfc1201 ?
+rrunner ?
+rt2400 ?
+rt2400pci ?
+rt2500 ?
+rt2500pci ?
+rt2800pci ?
+rt61pci ?
+s2io ?
+sfc ?
+shaper ?
+sis190 ?
+sis900 ?
+spidernet ?
+skfp ?
+skge ?
+sk98lin ?
+sky2 ?
+smc9194 ?
+smc-ultra ?
+smc-ultra32 ?
+starfire ?
+strip ?
+sunbmac ?
+sundance ?
+sungem ?
+sungem_phy ?
+sunhme ?
+sunlance ?
+sunqe ?
+sunvnet ?
+tg3 ?
+tlan ?
+tms380tr ?
+tmspci ?
+tulip ?
+tun ?
+typhoon ?
+uli526x ?
+via-rhine ?
+via-velocity ?
+virtio_net ?
+wavelan ?
+wd ?
+winbond-840 ?
+yellowfin ?
+znet ?
+vmxnet3 ?
+xen-netfront ?
+xgene-enet ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/nic-modules.powerpc
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/nic-modules.powerpc
@@ -0,0 +1,152 @@
+3c359 ?
+3c501 ?
+3c503 ?
+3c505 ?
+3c507 ?
+3c509 ?
+3c515 ?
+3c523 ?
+3c527 ?
+3c59x ?
+8139cp ?
+8139too ?
+82596 ?
+abyss ?
+ac3200 ?
+adm8211 ?
+airo ?
+airport ?
+amd8111e ?
+arc4 ?
+arcnet ?
+arc-rawmode ?
+arc-rimi ?
+arlan ?
+at1700 ?
+atl1 ?
+atl1e ?
+atl2 ?
+atmel ?
+atmel_pci ?
+b44 ?
+bcm43xx ?
+bcm43xx-mac80211 ?
+bmac ?
+bnx2 ?
+bnx2x ?
+bonding ?
+cassini ?
+com20020 ?
+com20020-pci ?
+com90io ?
+com90xx ?
+cs89x0 ?
+de2104x ?
+de4x5 ?
+de600 ?
+de620 ?
+defxx ?
+depca ?
+dl2k ?
+dmfe ?
+dummy ?
+e100 ?
+e1000 ?
+e1000e ?
+e2100 ?
+eepro ?
+eepro100 ?
+eexpress ?
+epic100 ?
+eql ?
+es3210 ?
+eth16i ?
+ewrk3 ?
+fealnx ?
+forcedeth ?
+igb ?
+hamachi ?
+hermes ?
+hp ?
+hp100 ?
+hp-plus ?
+ibmtr ?
+ibmveth ?
+ipddp ?
+ipw2100 ?
+ipw2200 ?
+ipw3945 ?
+ixgb ?
+lance ?
+lanstreamer ?
+lasi_82596 ?
+lne390 ?
+lp486e ?
+mace ?
+mv643xx_eth ?
+myri_sbus ?
+natsemi ?
+ne ?
+ne2 ?
+ne2k-pci ?
+ne3210 ?
+netconsole ?
+netxen_nic ?
+ni5010 ?
+ni52 ?
+ni65 ?
+niu ?
+ns83820 ?
+olympic ?
+orinoco ?
+orinoco_pci ?
+orinoco_plx ?
+orinoco_tmd ?
+pcnet32 ?
+ps3_gelic ?
+r8169 ?
+rate_control ?
+rfc1051 ?
+rfc1201 ?
+rrunner ?
+rt2400 ?
+rt2500 ?
+rt61pci ?
+s2io ?
+shaper ?
+sis190 ?
+sis900 ?
+spidernet ?
+skfp ?
+skge ?
+sk98lin ?
+sky2 ?
+smc9194 ?
+smc-ultra ?
+smc-ultra32 ?
+starfire ?
+strip ?
+sunbmac ?
+sundance ?
+sungem ?
+sungem_phy ?
+sunhme ?
+sunlance ?
+sunqe ?
+sunvnet ?
+tg3 ?
+tlan ?
+tms380tr ?
+tmspci ?
+tulip ?
+tun ?
+typhoon ?
+uli526x ?
+via-rhine ?
+via-velocity ?
+virtio_net ?
+wavelan ?
+wd ?
+winbond-840 ?
+yellowfin ?
+znet ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/nic-pcmcia-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/nic-pcmcia-modules
@@ -0,0 +1,19 @@
+3c574_cs ?
+3c589_cs ?
+airo_cs ?
+atmel_cs ?
+axnet_cs ?
+com20020_cs ?
+fmvj18x_cs ?
+ibmtr_cs ?
+netwave_cs ?
+nmclan_cs ?
+orinoco_cs ?
+pcnet_cs ?
+ray_cs ?
+smc91c92_cs ?
+wavelan_cs ?
+wl3501_cs ?
+xirc2ps_cs ?
+xircom_cb ?
+xircom_tulip_cb ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/nic-shared-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/nic-shared-modules
@@ -0,0 +1,26 @@
+# PHY
+8390 ?
+mii ?
+
+# CRC modules
+crc-ccitt ?
+crc-itu-t ?
+libcrc32c ?
+
+# mac80211 stuff
+mac80211 ?
+cfg80211 ?
+
+# rt2x00 lib (since rt2x00 is split across usb/pci/cb
+rt2x00lib ?
+rt2800lib ?
+
+# Atheros library (since drivers are split across nic-modules/nic-usb-modules)
+ath ?
+
+# Wireless 802.11 modules
+lib80211 ?
+cfg80211 ?
+lib80211_crypt_ccmp ?
+lib80211_crypt_tkip ?
+lib80211_crypt_wep ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/nic-usb-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/nic-usb-modules
@@ -0,0 +1,34 @@
+ax88179_178a ?
+catc ?
+kaweth ?
+pegasus ?
+prism2_usb ?
+rtl8150 ?
+usbnet ?
+zd1211rw ?
+zd1201 ?
+rt2500usb ?
+rt73usb ?
+rt2570 ?
+rt2800usb ?
+rt2x00usb ?
+cdc_ether ?
+asix ?
+cdc_eem ?
+cdc_ether ?
+cdc-phonet ?
+cdc_subset ?
+dm9601 ?
+gl620a ?
+hso ?
+int51x1 ?
+mcs7830 ?
+net1080 ?
+plusb ?
+rndis_host ?
+r8152 ?
+smsc95xx ?
+zaurus ?
+carl9170 ?
+smsc75xx ?
+smsc95xx ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/parport-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/parport-modules
@@ -0,0 +1,2 @@
+parport ?
+parport_pc ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/pata-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/pata-modules
@@ -0,0 +1,47 @@
+pata_ali.ko ?
+pata_amd.ko ?
+pata_artop.ko ?
+pata_atiixp.ko ?
+pata_atp867x.ko ?
+pata_cmd640.ko ?
+pata_cmd64x.ko ?
+pata_cs5520.ko ?
+pata_cs5530.ko ?
+pata_cs5535.ko ?
+pata_cs5536.ko ?
+pata_cypress.ko ?
+pata_efar.ko ?
+pata_hpt366.ko ?
+pata_hpt37x.ko ?
+pata_hpt3x2n.ko ?
+pata_hpt3x3.ko ?
+pata_isapnp.ko ?
+pata_it8213.ko ?
+pata_it821x.ko ?
+pata_jmicron.ko ?
+pata_legacy.ko ?
+pata_macio.ko ?
+pata_marvell.ko ?
+pata_mpiix.ko ?
+pata_netcell.ko ?
+pata_ninja32.ko ?
+pata_ns87410.ko ?
+pata_ns87415.ko ?
+pata_oldpiix.ko ?
+pata_optidma.ko ?
+pata_opti.ko ?
+pata_pcmcia.ko ?
+pata_pdc2027x.ko ?
+pata_pdc202xx_old.ko ?
+pata_qdi.ko ?
+pata_radisys.ko ?
+pata_rdc.ko ?
+pata_rz1000.ko ?
+pata_sc1200.ko ?
+pata_sch.ko ?
+pata_serverworks.ko ?
+pata_sil680.ko ?
+pata_sl82c105.ko ?
+pata_triflex.ko ?
+pata_via.ko ?
+pata_winbond.ko ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/pcmcia-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/pcmcia-modules
@@ -0,0 +1,8 @@
+i82092 ?
+i82365 ?
+pcmcia ?
+pcmcia_core ?
+pd6729 ?
+rsrc_nonstatic ?
+tcic ?
+yenta_socket ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/pcmcia-storage-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/pcmcia-storage-modules
@@ -0,0 +1,6 @@
+pata_pcmcia ?
+qlogic_cs ?
+fdomain_cs ?
+aha152x_cs ?
+nsp_cs ?
+sym53c500_cs ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/plip-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/plip-modules
@@ -0,0 +1 @@
+plip ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/ppc64el/block-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/ppc64el/block-modules
@@ -0,0 +1 @@
+#include <block-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/ppc64el/crypto-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/ppc64el/crypto-modules
@@ -0,0 +1 @@
+#include <crypto-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/ppc64el/floppy-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/ppc64el/floppy-modules
@@ -0,0 +1 @@
+#include <floppy-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/ppc64el/fs-core-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/ppc64el/fs-core-modules
@@ -0,0 +1 @@
+#include <fs-core-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/ppc64el/fs-secondary-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/ppc64el/fs-secondary-modules
@@ -0,0 +1 @@
+#include <fs-secondary-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/ppc64el/input-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/ppc64el/input-modules
@@ -0,0 +1 @@
+#include <input-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/ppc64el/ipmi-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/ppc64el/ipmi-modules
@@ -0,0 +1 @@
+#include <ipmi-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/ppc64el/kernel-image
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/ppc64el/kernel-image
@@ -0,0 +1 @@
+#include <kernel-image>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/ppc64el/md-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/ppc64el/md-modules
@@ -0,0 +1 @@
+#include <md-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/ppc64el/message-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/ppc64el/message-modules
@@ -0,0 +1 @@
+#include <message-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/ppc64el/multipath-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/ppc64el/multipath-modules
@@ -0,0 +1 @@
+#include <multipath-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/ppc64el/nfs-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/ppc64el/nfs-modules
@@ -0,0 +1 @@
+#include <nfs-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/ppc64el/nic-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/ppc64el/nic-modules
@@ -0,0 +1 @@
+#include <nic-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/ppc64el/nic-shared-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/ppc64el/nic-shared-modules
@@ -0,0 +1 @@
+#include <nic-shared-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/ppc64el/nic-usb-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/ppc64el/nic-usb-modules
@@ -0,0 +1 @@
+#include <nic-usb-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/ppc64el/parport-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/ppc64el/parport-modules
@@ -0,0 +1 @@
+#include <parport-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/ppc64el/plip-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/ppc64el/plip-modules
@@ -0,0 +1 @@
+#include <plip-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/ppc64el/ppp-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/ppc64el/ppp-modules
@@ -0,0 +1 @@
+#include <ppp-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/ppc64el/sata-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/ppc64el/sata-modules
@@ -0,0 +1 @@
+#include <sata-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/ppc64el/scsi-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/ppc64el/scsi-modules
@@ -0,0 +1 @@
+#include <scsi-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/ppc64el/storage-core-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/ppc64el/storage-core-modules
@@ -0,0 +1,2 @@
+#include <storage-core-modules>
+ipr ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/ppc64el/virtio-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/ppc64el/virtio-modules
@@ -0,0 +1 @@
+#include <virtio-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/ppc64el/vlan-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/ppc64el/vlan-modules
@@ -0,0 +1 @@
+#include <vlan-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/ppp-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/ppp-modules
@@ -0,0 +1,6 @@
+ppp_async ?
+ppp_deflate ?
+ppp_mppe ?
+pppoe ?
+pppox ?
+ppp_synctty ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/s390x/block-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/s390x/block-modules
@@ -0,0 +1 @@
+#include <block-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/s390x/crypto-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/s390x/crypto-modules
@@ -0,0 +1,2 @@
+#include <crypto-modules>
+deflate ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/s390x/dasd-extra-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/s390x/dasd-extra-modules
@@ -0,0 +1 @@
+#include <dasd-extra-modules.s390x>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/s390x/dasd-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/s390x/dasd-modules
@@ -0,0 +1 @@
+#include <dasd-modules.s390x>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/s390x/fat-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/s390x/fat-modules
@@ -0,0 +1 @@
+#include <fat-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/s390x/fs-core-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/s390x/fs-core-modules
@@ -0,0 +1 @@
+#include <fs-core-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/s390x/fs-secondary-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/s390x/fs-secondary-modules
@@ -0,0 +1 @@
+#include <fs-secondary-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/s390x/kernel-image
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/s390x/kernel-image
@@ -0,0 +1 @@
+#include <kernel-image>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/s390x/md-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/s390x/md-modules
@@ -0,0 +1 @@
+#include <md-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/s390x/multipath-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/s390x/multipath-modules
@@ -0,0 +1 @@
+#include <multipath-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/s390x/nfs-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/s390x/nfs-modules
@@ -0,0 +1 @@
+#include <nfs-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/s390x/nic-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/s390x/nic-modules
@@ -0,0 +1 @@
+#include <nic-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/s390x/nic-shared-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/s390x/nic-shared-modules
@@ -0,0 +1 @@
+#include <nic-shared-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/s390x/scsi-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/s390x/scsi-modules
@@ -0,0 +1,2 @@
+#include <scsi-modules>
+ipr ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/s390x/storage-core-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/s390x/storage-core-modules
@@ -0,0 +1 @@
+#include <storage-core-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/s390x/virtio-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/s390x/virtio-modules
@@ -0,0 +1 @@
+#include <virtio-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/s390x/vlan-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/s390x/vlan-modules
@@ -0,0 +1 @@
+#include <vlan-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/sata-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/sata-modules
@@ -0,0 +1,18 @@
+sata_inic162x.ko ?
+sata_mv.ko ?
+sata_nv.ko ?
+sata_promise.ko ?
+sata_qstor.ko ?
+sata_sil24.ko ?
+sata_sil.ko ?
+sata_sis.ko ?
+sata_svw.ko ?
+sata_sx4.ko ?
+sata_uli.ko ?
+sata_via.ko ?
+sata_vsc.ko ?
+ahci_platform ?
+ahci ?
+acard-ahci ?
+libahci ?
+ahci_xgene ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/scsi-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/scsi-modules
@@ -0,0 +1,137 @@
+# SCSI
+raid_class ?
+scsi_transport_spi ?
+scsi_transport_fc ?
+scsi_transport_iscsi ?
+scsi_transport_sas ?
+sr_mod ?
+iscsi_tcp ?
+libiscsi ?
+amiga7xx ?
+a3000 ?
+a2091 ?
+gvp11 ?
+mvme147 ?
+sgiwd93 ?
+cyberstorm ?
+cyberstormII ?
+blz2060 ?
+blz1230 ?
+fastlane ?
+oktagon_esp_mod ?
+atari_scsi ?
+mac_scsi ?
+mac_esp ?
+sun3_scsi ?
+mvme16x ?
+bvme6000 ?
+sim710 ?
+advansys ?
+pm80xx ?
+psi240i ?
+BusLogic ?
+dpt_i2o ?
+u14-34f ?
+ultrastor ?
+aha152x ?
+aha1542 ?
+aha1740 ?
+aic7xxx_old ?
+ips ?
+fd_mcs ?
+fdomain ?
+fnic ?
+in2000 ?
+g_NCR5380 ?
+g_NCR5380_mmio ?
+NCR53c406a ?
+NCR_D700 ?
+NCR_Q720_mod ?
+sym53c416 ?
+qlogicfas408 ?
+qla1280 ?
+pas16 ?
+seagate ?
+seagate ?
+t128 ?
+dmx3191d ?
+dtc ?
+zalon7xx ?
+eata_pio ?
+wd7000 ?
+mca_53c9x ?
+ibmmca ?
+eata ?
+dc395x ?
+tmscsim ?
+megaraid ?
+atp870u ?
+esp ?
+gdth ?
+initio ?
+a100u2w ?
+qlogicpti ?
+ide-scsi ?
+mesh ?
+mac53c94 ?
+pluto ?
+dec_esp ?
+3w-xxxx ?
+3w-9xxx ?
+ppa ?
+imm ?
+jazz_esp ?
+sun3x_esp ?
+fcal ?
+lasi700 ?
+nsp32 ?
+hptiop ?
+stex ?
+osst ?
+sg ?
+ch ?
+scsi_debug ?
+aacraid ?
+aic7xxx ?
+aic79xx ?
+aic94xx ?
+arcmsr ?
+acornscsi_mod ?
+arxescsi ?
+cumana_1 ?
+cumana_2 ?
+ecoscsi ?
+oak ?
+powertec ?
+eesox ?
+ibmvscsi ?
+ibmvfc ?
+libsas ?
+lpfc ?
+megaraid_mm ?
+megaraid_mbox ?
+megaraid_sas ?
+qla2xxx ?
+sym53c8xx ?
+qla4xxx ?
+mvsas ?
+vmw_pvscsi ?
+ums-cypress ?
+be2iscsi ?
+3w-sas ?
+isci ?
+mlx4_ib ?
+mlx5_ib ?
+zfcp ?
+sd_mod ?
+hisi_sas_v2_hw ?
+hisi_sas_v3_hw ?
+iscsi_ibft ?
+
+# device handlers
+scsi_dh_alua ?
+scsi_dh_emc ?
+scsi_dh_rdac ?
+scsi_dh_hp_sw ?
+
+smartpqi ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/scsi-modules.powerpc
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/scsi-modules.powerpc
@@ -0,0 +1,118 @@
+# SCSI
+raid_class ?
+scsi_transport_spi ?
+scsi_transport_fc ?
+scsi_transport_iscsi ?
+scsi_transport_sas ?
+iscsi_tcp ?
+libiscsi ?
+amiga7xx ?
+a3000 ?
+a2091 ?
+gvp11 ?
+mvme147 ?
+sgiwd93 ?
+cyberstorm ?
+cyberstormII ?
+blz2060 ?
+blz1230 ?
+fastlane ?
+oktagon_esp_mod ?
+atari_scsi ?
+mac_scsi ?
+mac_esp ?
+sun3_scsi ?
+mvme16x ?
+bvme6000 ?
+sim710 ?
+advansys ?
+psi240i ?
+BusLogic ?
+dpt_i2o ?
+u14-34f ?
+ultrastor ?
+aha152x ?
+aha1542 ?
+aha1740 ?
+aic7xxx_old ?
+ips ?
+fd_mcs ?
+fdomain ?
+in2000 ?
+g_NCR5380 ?
+g_NCR5380_mmio ?
+NCR53c406a ?
+NCR_D700 ?
+NCR_Q720_mod ?
+sym53c416 ?
+qlogicfas408 ?
+qla1280 ?
+pas16 ?
+seagate ?
+seagate ?
+t128 ?
+dmx3191d ?
+dtc ?
+zalon7xx ?
+eata_pio ?
+wd7000 ?
+mca_53c9x ?
+ibmmca ?
+ibmvfc ?
+ibmvscsi ?
+eata ?
+dc395x ?
+tmscsim ?
+megaraid ?
+atp870u ?
+esp ?
+gdth ?
+initio ?
+a100u2w ?
+qlogicpti ?
+ide-scsi ?
+mesh ?
+mac53c94 ?
+pluto ?
+dec_esp ?
+3w-xxxx ?
+3w-9xxx ?
+ppa ?
+imm ?
+jazz_esp ?
+sun3x_esp ?
+fcal ?
+lasi700 ?
+nsp32 ?
+ipr ?
+hptiop ?
+stex ?
+osst ?
+sg ?
+ch ?
+scsi_debug ?
+aacraid ?
+aic7xxx ?
+aic79xx ?
+aic94xx ?
+arcmsr ?
+acornscsi_mod ?
+arxescsi ?
+cumana_1 ?
+cumana_2 ?
+ecoscsi ?
+oak ?
+powertec ?
+eesox ?
+ibmvscsic ?
+libsas ?
+lpfc ?
+megaraid_mm ?
+megaraid_mbox ?
+megaraid_sas ?
+qla2xxx ?
+sym53c8xx ?
+qla4xxx ?
+mvsas ?
+sr_mod ?
+sd_mod ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/serial-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/serial-modules
@@ -0,0 +1,4 @@
+generic_serial ?
+serial_cs ?
+synclink_cs ?
+hyperv-keyboard ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/speakup-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/speakup-modules
@@ -0,0 +1,16 @@
+speakup ?
+speakup_acntpc ?
+speakup_acntsa ?
+speakup_apollo ?
+speakup_audptr ?
+speakup_bns ?
+speakup_decext ?
+speakup_dectlk ?
+speakup_dtlk ?
+speakup_dummy ?
+speakup_keypc ?
+speakup_ltlk ?
+speakup_soft ?
+speakup_spkout ?
+speakup_txprt ?
+speakup_decpc ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/storage-core-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/storage-core-modules
@@ -0,0 +1,15 @@
+# Core stacks
+usb-storage ?
+
+# Block level
+ata_piix ?
+ata_generic ?
+
+# Loop modules
+cryptoloop ?
+
+# Needs to be here for better cdrom initrd layout
+isofs ?
+
+# Needed for NVMe disks under VMD PCIe domains
+vmd ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/storage-core-modules.powerpc
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/storage-core-modules.powerpc
@@ -0,0 +1,13 @@
+# Core stacks
+usb-storage ?
+
+# Block level
+
+# Loop modules
+cryptoloop
+
+# Needs to be here for better cdrom initrd layout
+isofs
+
+ps3stor_lib ?
+ps3rom ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/usb-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/usb-modules
@@ -0,0 +1,15 @@
+ehci-hcd ?
+isp116x-hcd ?
+isp1760 ?
+ohci-hcd ?
+r8a66597-hcd ?
+sl811_cs ?
+sl811-hcd ?
+u132-hcd ?
+uhci-hcd ?
+xhci-hcd ?
+xhci-plat-hcd ?
+ehci-tegra ?
+ehci-msm ?
+ehci-platform ?
+uas ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/virtio-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/virtio-modules
@@ -0,0 +1,11 @@
+virtio_balloon ?
+virtio_pci ?
+virtio_ring ?
+virtio-rng ?
+virtio_scsi ?
+hv_vmbus ?
+hv_utils ?
+hv_netvsc ?
+hv_mouse ?
+hv_storvsc ?
+hv_balloon ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/modules/vlan-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/modules/vlan-modules
@@ -0,0 +1,3 @@
+slp ?
+garp ?
+8021q ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/d-i/package-list
+++ linux-xilinx-zynqmp-5.4.0/debian.master/d-i/package-list
@@ -0,0 +1,203 @@
+Package: kernel-image
+Provides: ext3-modules, ext4-modules, squashfs-modules
+Provides_amd64: efi-modules, ext3-modules, ext4-modules, squashfs-modules
+Provides_i386: efi-modules, ext3-modules, ext4-modules, squashfs-modules
+Provides_ppc64el: ext3-modules, ext4-modules, fat-modules, squashfs-modules
+Provides_s390x: ext3-modules, ext4-modules, ppp-modules, squashfs-modules
+Description: kernel image and system map
+
+Package: dasd-modules
+Depends: kernel-image, storage-core-modules
+Priority: standard
+Description: DASD storage support
+
+Package: dasd-extra-modules
+Depends: dasd-modules
+Priority: extra
+Description: DASD storage support -- extras
+
+Package: fat-modules
+Depends: kernel-image
+Priority: standard
+Description: FAT filesystem support
+ This includes Windows FAT and VFAT support.
+
+Package: fb-modules
+Depends: kernel-image
+Priority: standard
+Description: Framebuffer modules
+
+Package: firewire-core-modules
+Depends: kernel-image, storage-core-modules
+Priority: standard
+Description: Firewire (IEEE-1394) Support
+
+Package: floppy-modules
+Depends: kernel-image
+Priority: standard
+Description: Floppy driver support
+
+Package: fs-core-modules
+Depends: kernel-image
+Priority: standard
+Provides: ext2-modules, jfs-modules, reiserfs-modules, xfs-modules
+Description: Base filesystem modules
+ This includes jfs, reiserfs and xfs.
+
+Package: fs-secondary-modules
+Depends: kernel-image, fat-modules
+Priority: standard
+Provides: btrfs-modules, ntfs-modules, hfs-modules
+Description: Extra filesystem modules
+ This includes support for Windows NTFS and MacOS HFS/HFSPlus
+
+Package: input-modules
+Depends: kernel-image, usb-modules
+Priority: standard
+Description: Support for various input methods
+
+Package: md-modules
+Depends: kernel-image
+Priority: standard
+Provides: crypto-dm-modules
+Description: Multi-device support (raid, device-mapper, lvm)
+
+Package: nic-modules
+Depends: kernel-image, nic-shared-modules, virtio-modules
+Priority: standard
+Description: Network interface support
+
+Package: nic-pcmcia-modules
+Depends: kernel-image, nic-shared-modules, nic-modules
+Priority: standard
+Description: PCMCIA network interface support
+
+Package: nic-usb-modules
+Depends: kernel-image, nic-shared-modules, usb-modules
+Priority: standard
+Description: USB network interface support
+
+Package: nic-shared-modules
+Depends: kernel-image, crypto-modules
+Priority: standard
+Description: nic shared modules
+  This package contains modules which support nic modules
+
+Package: parport-modules
+Depends: kernel-image
+Priority: standard
+Description: Parallel port support
+
+Package: pata-modules
+Depends: kernel-image, storage-core-modules
+Priority: standard
+Description: PATA support modules
+
+Package: pcmcia-modules
+Depends: kernel-image
+Priority: standard
+Description: PCMCIA Modules
+
+Package: pcmcia-storage-modules
+Depends: kernel-image, scsi-modules
+Priority: standard
+Description: PCMCIA storage support
+
+Package: plip-modules
+Depends: kernel-image, nic-shared-modules, parport-modules
+Priority: standard
+Description: PLIP (parallel port) networking support
+
+Package: ppp-modules
+Depends: kernel-image, nic-shared-modules, serial-modules
+Priority: standard
+Description: PPP (serial port) networking support
+
+Package: sata-modules
+Depends: kernel-image, storage-core-modules
+Priority: standard
+Description: SATA storage support
+
+Package: scsi-modules
+Depends: kernel-image, storage-core-modules
+Priority: standard
+Description: SCSI storage support
+
+Package: serial-modules
+Depends: kernel-image
+Priority: standard
+Description: Serial port support
+
+Package: storage-core-modules
+Depends: kernel-image
+Priority: standard
+Provides: loop-modules
+Description: Core storage support
+ Includes core SCSI, LibATA, USB-Storage. Also includes related block
+ devices for CD, Disk and Tape medium (and IDE Floppy).
+
+Package: usb-modules
+Depends: kernel-image, storage-core-modules
+Priority: standard
+Description: Core USB support
+
+Package: nfs-modules
+Priority: standard
+Depends: kernel-image
+Description: NFS filesystem drivers
+ Includes the NFS client driver, and supporting modules.
+
+Package: block-modules
+Priority: standard
+Provides: nbd-modules
+Depends: kernel-image, storage-core-modules, parport-modules, virtio-modules
+Description: Block storage devices
+ This package contains the block storage devices, including DAC960 and
+ paraide.
+
+Package: message-modules
+Priority: standard
+Depends: kernel-image, storage-core-modules, scsi-modules
+Description: Fusion and i2o storage modules
+ This package containes the fusion and i2o storage modules.
+
+Package: crypto-modules
+Priority: extra
+Depends: kernel-image
+Description: crypto modules
+ This package contains crypto modules.
+
+Package: virtio-modules
+Priority: standard
+Depends: kernel-image
+Description: VirtIO Modules
+ Includes modules for VirtIO (virtual machine, generally kvm guests)
+
+Package: socket-modules
+Depends: kernel-image
+Priority: standard
+Description: Unix socket support
+
+Package: mouse-modules
+Depends: kernel-image, input-modules, usb-modules
+Priority: extra
+Description: Mouse support
+ This package contains mouse drivers for the Linux kernel.
+
+Package: vlan-modules
+Depends: kernel-image
+Priority: extra
+Description: vlan modules
+ This package contains vlan (8021.Q) modules.
+
+Package: ipmi-modules
+Depends: kernel-image
+Priority: standard
+Description: ipmi modules
+
+Package: multipath-modules
+Depends: kernel-image
+Priority: extra
+Description: DM-Multipath support
+  This package contains modules for device-mapper multipath support.
+
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/dkms-versions
+++ linux-xilinx-zynqmp-5.4.0/debian.master/dkms-versions
@@ -0,0 +1,3 @@
+zfs-linux 0.8.3-1ubuntu12.18
+virtualbox 6.1.50-dfsg-1~ubuntu1.20.04.1
+wireguard-linux-compat 1.0.20201112-1~20.04.1
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/etc/kernelconfig
+++ linux-xilinx-zynqmp-5.4.0/debian.master/etc/kernelconfig
@@ -0,0 +1,7 @@
+if [ "$variant" = "ports" ]; then
+	archs=""
+	family='ports'
+else
+	archs="amd64 i386 armhf arm64 ppc64el s390x"
+	family='ubuntu'
+fi
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/modprobe.d/common.conf
+++ linux-xilinx-zynqmp-5.4.0/debian.master/modprobe.d/common.conf
@@ -0,0 +1,3 @@
+# LP:1434842 -- disable OSS drivers by default to allow pulseaudio to emulate
+blacklist snd-mixer-oss
+blacklist snd-pcm-oss
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/reconstruct
+++ linux-xilinx-zynqmp-5.4.0/debian.master/reconstruct
@@ -0,0 +1,125 @@
+# Recreate any symlinks created since the orig.
+chmod +x 'arch/mips/pci/pcie-octeon.c'
+chmod +x 'debian/cloud-tools/hv_get_dhcp_info'
+chmod +x 'debian/cloud-tools/hv_get_dns_info'
+chmod +x 'debian/cloud-tools/hv_set_ifconfig'
+chmod +x 'debian/rules'
+chmod +x 'debian/scripts/config-check'
+chmod +x 'debian/scripts/control-create'
+chmod +x 'debian/scripts/dkms-build'
+chmod +x 'debian/scripts/dkms-build--nvidia-N'
+chmod +x 'debian/scripts/dkms-build--virtualbox-guest'
+chmod +x 'debian/scripts/dkms-build-configure--zfs'
+chmod +x 'debian/scripts/file-downloader'
+chmod +x 'debian/scripts/link-headers'
+chmod +x 'debian/scripts/misc/annotations'
+chmod +x 'debian/scripts/misc/arch-has-odm-enabled.sh'
+chmod +x 'debian/scripts/misc/final-checks'
+chmod +x 'debian/scripts/misc/find-missing-sauce.sh'
+chmod +x 'debian/scripts/misc/find-obsolete-firmware'
+chmod +x 'debian/scripts/misc/fw-to-ihex.sh'
+chmod +x 'debian/scripts/misc/gen-auto-reconstruct'
+chmod +x 'debian/scripts/misc/get-firmware'
+chmod +x 'debian/scripts/misc/git-ubuntu-log'
+chmod +x 'debian/scripts/misc/insert-changes.pl'
+chmod +x 'debian/scripts/misc/insert-mainline-changes'
+chmod +x 'debian/scripts/misc/insert-ubuntu-changes'
+chmod +x 'debian/scripts/misc/kernel-wedge-arch.pl'
+chmod +x 'debian/scripts/misc/kernelconfig'
+chmod +x 'debian/scripts/misc/migrate-annotations'
+chmod +x 'debian/scripts/misc/retag'
+chmod +x 'debian/scripts/misc/splitconfig.pl'
+chmod +x 'debian/scripts/misc/tristate.sh'
+chmod +x 'debian/scripts/misc/update-aufs.sh'
+chmod +x 'debian/scripts/module-inclusion'
+chmod +x 'debian/scripts/retpoline-extract'
+chmod +x 'debian/scripts/retpoline-extract-one'
+chmod +x 'debian/templates/extra.postinst.in'
+chmod +x 'debian/templates/extra.postrm.in'
+chmod +x 'debian/templates/headers.postinst.in'
+chmod +x 'debian/templates/image.postinst.in'
+chmod +x 'debian/templates/image.postrm.in'
+chmod +x 'debian/templates/image.preinst.in'
+chmod +x 'debian/templates/image.prerm.in'
+chmod +x 'debian/tests-build/check-aliases'
+chmod +x 'debian/tests/rebuild'
+chmod +x 'debian/tests/ubuntu-regression-suite'
+chmod +x 'samples/bpf/lwt_len_hist.sh'
+chmod +x 'samples/bpf/test_lwt_bpf.sh'
+chmod +x 'scripts/kmsg-doc'
+chmod +x 'scripts/parse-maintainers.pl'
+chmod +x 'tools/testing/selftests/net/fib_nexthop_nongw.sh'
+chmod +x 'tools/testing/selftests/netfilter/conntrack_vrf.sh'
+# Remove any files deleted from the orig.
+rm -f 'Documentation/devicetree/bindings/clock/axi-clkgen.txt'
+rm -f 'Documentation/devicetree/bindings/gpu/samsung-rotator.txt'
+rm -f 'Documentation/devicetree/bindings/phy/amlogic,meson-g12a-usb3-pcie-phy.yaml'
+rm -f 'Documentation/networking/decnet.txt'
+rm -f 'arch/alpha/include/asm/bugs.h'
+rm -f 'arch/ia64/include/asm/bugs.h'
+rm -f 'arch/m68k/include/asm/bugs.h'
+rm -f 'arch/parisc/include/asm/bugs.h'
+rm -f 'arch/parisc/kernel/module.lds'
+rm -f 'arch/parisc/lib/string.S'
+rm -f 'arch/powerpc/include/asm/bugs.h'
+rm -f 'arch/powerpc/include/uapi/asm/bpf_perf_event.h'
+rm -f 'arch/sh/include/asm/bugs.h'
+rm -f 'arch/sparc/include/asm/bugs.h'
+rm -f 'arch/um/include/asm/bugs.h'
+rm -f 'arch/um/kernel/gmon_syms.c'
+rm -f 'arch/x86/events/intel/rapl.c'
+rm -f 'arch/x86/include/asm/refcount.h'
+rm -f 'arch/xtensa/include/asm/bugs.h'
+rm -f 'drivers/block/sx8.c'
+rm -f 'drivers/crypto/hisilicon/sgl.h'
+rm -f 'drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.h'
+rm -f 'drivers/iio/adc/stx104.c'
+rm -f 'drivers/input/serio/i8042-ppcio.h'
+rm -f 'drivers/net/can/dev.c'
+rm -f 'drivers/net/can/rx-offload.c'
+rm -f 'drivers/net/phy/mdio-i2c.h'
+rm -f 'drivers/net/phy/mdio-xgene.h'
+rm -f 'drivers/soc/qcom/llcc-sdm845.c'
+rm -f 'drivers/soc/qcom/llcc-slice.c'
+rm -f 'drivers/staging/mt7621-dma/mtk-hsdma.c'
+rm -f 'include/Kbuild'
+rm -f 'include/asm-generic/bugs.h'
+rm -f 'include/linux/kd.h'
+rm -f 'include/net/dn.h'
+rm -f 'include/net/dn_dev.h'
+rm -f 'include/net/dn_fib.h'
+rm -f 'include/net/dn_neigh.h'
+rm -f 'include/net/dn_nsp.h'
+rm -f 'include/net/dn_route.h'
+rm -f 'include/trace/events/random.h'
+rm -f 'include/uapi/linux/dn.h'
+rm -f 'include/uapi/linux/netfilter_decnet.h'
+rm -f 'include/uapi/rdma/nes-abi.h'
+rm -f 'kernel/elfcore.c'
+rm -f 'net/decnet/Kconfig'
+rm -f 'net/decnet/Makefile'
+rm -f 'net/decnet/README'
+rm -f 'net/decnet/af_decnet.c'
+rm -f 'net/decnet/dn_dev.c'
+rm -f 'net/decnet/dn_fib.c'
+rm -f 'net/decnet/dn_neigh.c'
+rm -f 'net/decnet/dn_nsp_in.c'
+rm -f 'net/decnet/dn_nsp_out.c'
+rm -f 'net/decnet/dn_route.c'
+rm -f 'net/decnet/dn_rules.c'
+rm -f 'net/decnet/dn_table.c'
+rm -f 'net/decnet/dn_timer.c'
+rm -f 'net/decnet/netfilter/Kconfig'
+rm -f 'net/decnet/netfilter/Makefile'
+rm -f 'net/decnet/netfilter/dn_rtmsg.c'
+rm -f 'net/decnet/sysctl_net_decnet.c'
+rm -f 'net/sched/cls_rsvp.c'
+rm -f 'net/sched/cls_rsvp.h'
+rm -f 'net/sched/cls_rsvp6.c'
+rm -f 'net/sched/cls_tcindex.c'
+rm -f 'net/sched/sch_atm.c'
+rm -f 'net/sched/sch_cbq.c'
+rm -f 'net/sched/sch_dsmark.c'
+rm -f 'net/xfrm/xfrm_interface.c'
+rm -f 'tools/build/feature/test-libpython-version.c'
+exit 0
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/rules.d/amd64.mk
+++ linux-xilinx-zynqmp-5.4.0/debian.master/rules.d/amd64.mk
@@ -0,0 +1,27 @@
+human_arch	= 64 bit x86
+build_arch	= x86
+header_arch	= $(build_arch)
+defconfig	= defconfig
+flavours	= generic lowlatency
+build_image	= bzImage
+kernel_file	= arch/$(build_arch)/boot/bzImage
+install_file	= vmlinuz
+loader		= grub
+vdso		= vdso_install
+no_dumpfile	= true
+uefi_signed     = true
+do_tools_usbip  = true
+do_tools_cpupower = true
+do_tools_perf   = true
+do_tools_perf_jvmti = true
+do_tools_bpftool = true
+do_tools_x86	= true
+do_tools_hyperv	= true
+do_tools_host = true
+do_extras_package = true
+do_tools_common = true
+do_tools_acpidbg = true
+do_zfs		= true
+do_dkms_vbox    = true
+do_dkms_wireguard = true
+do_odm_drivers    = true
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/rules.d/arm64.mk
+++ linux-xilinx-zynqmp-5.4.0/debian.master/rules.d/arm64.mk
@@ -0,0 +1,24 @@
+human_arch	= ARMv8
+build_arch	= arm64
+header_arch	= arm64
+defconfig	= defconfig
+flavours	= generic
+build_image_generic	= Image.gz
+kernel_file_generic	= arch/$(build_arch)/boot/Image.gz
+install_file	= vmlinuz
+no_dumpfile = true
+uefi_signed     = true
+
+loader		= grub
+vdso		= vdso_install
+
+do_extras_package = true
+do_tools_usbip  = true
+do_tools_cpupower = true
+do_tools_perf   = true
+do_tools_perf_jvmti = true
+do_tools_bpftool = true
+
+do_dtbs		= true
+do_zfs		= true
+do_dkms_wireguard = true
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/rules.d/armhf.mk
+++ linux-xilinx-zynqmp-5.4.0/debian.master/rules.d/armhf.mk
@@ -0,0 +1,21 @@
+human_arch	= ARM (hard float)
+build_arch	= arm
+header_arch	= arm
+defconfig	= defconfig
+flavours	= generic generic-lpae
+build_image	= zImage
+kernel_file	= arch/$(build_arch)/boot/zImage
+install_file	= vmlinuz
+no_dumpfile	= true
+
+loader		= grub
+
+do_tools_usbip  = true
+do_tools_cpupower = true
+do_tools_perf	= true
+do_tools_perf_jvmti = true
+do_tools_bpftool = true
+
+do_dtbs		= true
+
+do_dkms_wireguard = true
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/rules.d/hooks.mk
+++ linux-xilinx-zynqmp-5.4.0/debian.master/rules.d/hooks.mk
@@ -0,0 +1 @@
+do_enforce_all = true
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/rules.d/i386.mk
+++ linux-xilinx-zynqmp-5.4.0/debian.master/rules.d/i386.mk
@@ -0,0 +1,19 @@
+human_arch	= 32 bit x86
+build_arch	= i386
+header_arch	= $(build_arch)
+defconfig	= defconfig
+flavours        = generic lowlatency
+build_image	= bzImage
+kernel_file	= arch/$(build_arch)/boot/bzImage
+install_file	= vmlinuz
+loader		= grub
+vdso		= vdso_install
+no_dumpfile	= true
+do_flavour_image_package = false
+do_tools	= false
+do_tools_common	= false
+do_extras_package = false
+do_source_package = false
+do_doc_package	= false
+do_flavour_header_package = false
+do_common_headers_indep = false
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/rules.d/ppc64el.mk
+++ linux-xilinx-zynqmp-5.4.0/debian.master/rules.d/ppc64el.mk
@@ -0,0 +1,22 @@
+human_arch	= PowerPC 64el
+build_arch	= powerpc
+header_arch	= $(build_arch)
+defconfig	= pseries_le_defconfig
+flavours	= generic
+build_image	= vmlinux.strip
+kernel_file     = arch/powerpc/boot/vmlinux.strip
+install_file	= vmlinux
+no_dumpfile	= true
+vdso		= vdso_install
+loader		= grub
+do_extras_package = true
+opal_signed       = true
+do_tools_usbip    = true
+do_tools_cpupower = true
+do_tools_perf	  = true
+do_tools_perf_jvmti = true
+do_tools_bpftool  = true
+
+#do_flavour_image_package = false
+do_zfs		= true
+do_dkms_wireguard = true
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/rules.d/riscv64.mk
+++ linux-xilinx-zynqmp-5.4.0/debian.master/rules.d/riscv64.mk
@@ -0,0 +1,21 @@
+human_arch	= RISC-V
+build_arch	= riscv
+header_arch	= $(build_arch)
+defconfig	= defconfig
+flavours        = generic
+build_image	= Image
+kernel_file	= arch/$(build_arch)/boot/Image
+install_file	= vmlinuz
+
+loader		= grub
+vdso		= vdso_install
+no_dumpfile	= true
+
+do_flavour_image_package = false
+do_tools	= false
+do_tools_common	= false
+do_extras_package = false
+do_source_package = false
+do_doc_package	= false
+do_flavour_header_package = false
+do_common_headers_indep = false
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/rules.d/s390x.mk
+++ linux-xilinx-zynqmp-5.4.0/debian.master/rules.d/s390x.mk
@@ -0,0 +1,22 @@
+human_arch      = System 390x
+build_arch      = s390
+header_arch     = $(build_arch)
+defconfig       = defconfig
+flavours        = generic
+build_image	= bzImage
+kernel_file	= arch/$(build_arch)/boot/bzImage
+install_file	= vmlinuz
+
+vdso		= vdso_install
+no_dumpfile	= true
+
+do_extras_package = true
+sipl_signed       = true
+do_tools_usbip    = true
+do_tools_cpupower = true
+do_tools_perf     = true
+do_tools_perf_jvmti = true
+do_tools_bpftool  = true
+
+do_zfs		= true
+do_dkms_wireguard = true
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/rules.d/x32.mk
+++ linux-xilinx-zynqmp-5.4.0/debian.master/rules.d/x32.mk
@@ -0,0 +1,14 @@
+human_arch	= 64 bit x86 (32 bit userspace)
+build_arch	= x86
+header_arch	= $(build_arch)
+defconfig	= defconfig
+flavours	= 
+build_image	= bzImage
+kernel_file	= arch/$(build_arch)/boot/bzImage
+install_file	= vmlinuz
+loader		= grub
+vdso		= vdso_install
+no_dumpfile	= true
+uefi_signed     = true
+
+do_flavour_image_package = false
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/tracking-bug
+++ linux-xilinx-zynqmp-5.4.0/debian.master/tracking-bug
@@ -0,0 +1 @@
+2144157 s2026.02.09-1
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/upstream-stable
+++ linux-xilinx-zynqmp-5.4.0/debian.master/upstream-stable
@@ -0,0 +1,3 @@
+# The following upstream stable releases have been ported:
+[upstream-stable]
+    linux-5.4.y = v5.4.292
--- linux-xilinx-zynqmp-5.4.0.orig/debian.master/variants
+++ linux-xilinx-zynqmp-5.4.0/debian.master/variants
@@ -0,0 +1,2 @@
+-5.4
+--
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/changelog
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/changelog
@@ -0,0 +1,29327 @@
+linux-xilinx-zynqmp (5.4.0-1075.79) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1075.79 -proposed tracker (LP: #2144155)
+
+  [ Ubuntu: 5.4.0-228.248 ]
+
+  * focal/linux: 5.4.0-228.248 -proposed tracker (LP: #2144157)
+  * CVE-2024-46816
+    - drm/amd/display: Stop amdgpu_dm initialize when link nums greater than
+      max_links
+  * CVE-2022-49046
+    - i2c: dev: check return value when calling dev_set_name()
+  * CVE-2025-37849
+    - KVM: arm/arm64: vgic: Reset base address on kvm_vgic_dist_destroy()
+    - KVM: arm64: vgic: Add a non-locking primitive for
+      kvm_vgic_vcpu_destroy()
+    - KVM: arm64: vgic: Force vcpu vgic teardown on vcpu destroy
+    - KVM: arm64: Tear down vGIC on failed vCPU creation
+  * CVE-2026-23074
+    - net/sched: Enforce that teql can only be used as root qdisc
+  * CVE-2026-23060
+    - crypto: authencesn - reject too-short AAD (assoclen<8) to match ESP/ESN
+      spec
+
+ -- Changwei Zou <changwei.zou@canonical.com>  Thu, 19 Mar 2026 14:24:30 +1100
+
+linux-xilinx-zynqmp (5.4.0-1074.78) focal; urgency=medium
+
+  [ Ubuntu: 5.4.0-227.247 ]
+
+  * Miscellaneous upstream changes
+    - apparmor: validate DFA start states are in bounds in unpack_pdb
+    - apparmor: fix memory leak in verify_header
+    - apparmor: replace recursive profile removal with iterative approach
+    - apparmor: fix: limit the number of levels of policy namespaces
+    - apparmor: fix side-effect bug in match_char() macro usage
+    - apparmor: fix missing bounds check on DEFAULT table in verify_dfa()
+    - apparmor: fix unprivileged local user can do privileged policy
+      management
+    - apparmor: fix differential encoding verification
+    - apparmor: fix race on rawdata dereference
+    - apparmor: fix race between freeing data and fs accessing it
+
+ -- Mehmet Basaran <mehmet.basaran@canonical.com>  Tue, 10 Mar 2026 23:50:52 +0300
+
+linux-xilinx-zynqmp (5.4.0-1073.77) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1073.77 -proposed tracker (LP: #2140844)
+
+  [ Ubuntu: 5.4.0-226.246 ]
+
+  * focal/linux: 5.4.0-226.246 -proposed tracker (LP: #2140846)
+  * CVE-2022-49072
+    - gpio: Restrict usage of GPIO chip irq members before initialization
+    - gpio: Request interrupts after IRQ is initialized
+  * CVE-2021-47599
+    - btrfs: convert latest_bdev type to btrfs_device and rename
+    - btrfs: use latest_dev in btrfs_show_devname
+  * CVE-2022-48875
+    - wifi: mac80211: sdata can be NULL during AMPDU start
+  * ipsec_offload in rtnetlink.sh from kselftests.net fails on s390x
+    (LP: #1893921)
+    - SAUCE: Fix selftest/net/rtnetlink.sh for Big Endian
+    - SAUCE: Fix selftest/net/rtnetlink.sh for Big Endian (ip address)
+  * CVE-2024-56640
+    - net/smc: fix LGR and link use-after-free issue
+  * CVE-2025-21780
+    - drm/amdgpu: avoid buffer overflow attach in smu_sys_set_pp_table()
+  * CVE-2022-49267
+    - mmc: core: use sysfs_emit() instead of sprintf()
+  * CVE-2024-49927
+    - x86/ioapic: Handle allocation failures gracefully
+  * statx09 in ubuntu_ltp_syscalls failed on Focal 5.4 (LP: #1966620)
+    - docs: fs-verity: document first supported kernel version
+    - statx: define STATX_ATTR_VERITY
+    - ext4: support STATX_ATTR_VERITY
+    - f2fs: support STATX_ATTR_VERITY
+    - docs: fs-verity: mention statx() support
+  * CVE-2025-40215 // CVE-2025-40256
+    - xfrm: delete x->tunnel as we delete x
+    - xfrm: also call xfrm_state_delete_tunnel at destroy time for states that
+      were never added
+
+ -- Stewart Hore <stewart.hore@canonical.com>  Wed, 11 Feb 2026 16:44:55 +1100
+
+linux-xilinx-zynqmp (5.4.0-1072.76) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1072.76 -proposed tracker (LP: #2137981)
+
+  [ Ubuntu: 5.4.0-225.245 ]
+
+  * focal/linux: 5.4.0-225.245 -proposed tracker (LP: #2137983)
+  * CVE-2022-49698
+    - netfilter: use get_random_u32 instead of prandom
+  * CVE-2025-40019
+    - crypto: essiv - Check ssize for decryption and in-place encryption
+  * Focal generic kernel FTBFS when CONFIG_PROVE_LOCKING = y (LP: #2130776)
+    - SAUCE: Use current->hardirqs_enabled in lockdep preemption asserts
+  * CVE-2025-21726
+    - padata: add pd get/put refcnt helper
+    - padata: avoid UAF for reorder_work
+    - padata: do not leak refcount in reorder_work
+
+ -- Stewart Hore <stewart.hore@canonical.com>  Thu, 22 Jan 2026 11:18:44 +1100
+
+linux-xilinx-zynqmp (5.4.0-1071.75) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1071.75 -proposed tracker (LP: #2131366)
+
+  [ Ubuntu: 5.4.0-224.244 ]
+
+  * focal/linux: 5.4.0-224.244 -proposed tracker (LP: #2131368)
+  * CVE-2025-38666
+    - net: appletalk: fix kerneldoc warnings
+    - net: appletalk: Fix use-after-free in AARP proxy probe
+  * CVE-2024-50196
+    - pinctrl: ocelot: fix system hang on level based interrupts
+  * CVE-2024-49935
+    - ACPI: PAD: fix crash in exit_round_robin()
+  * CVE-2022-49390
+    - macsec: fix UAF bug for real_dev
+  * CVE-2025-37958
+    - mm/huge_memory: fix dereferencing invalid pmd migration entry
+  * CVE-2024-50095
+    - IB/mad: Issue complete whenever decrements agent refcount
+    - RDMA/mad: Improve handling of timed out WRs of mad agent
+  * CVE-2025-39964
+    - crypto: af_alg - Disallow concurrent writes in af_alg_sendmsg
+    - crypto: af_alg - Fix incorrect boolean values in af_alg_ctx
+  * CVE-2024-50067
+    - uprobes: encapsulate preparation of uprobe args buffer
+    - uprobe: avoid out-of-bounds memory access of fetching args
+  * CVE-2024-53090
+    - afs: Fix lock recursion
+  * CVE-2022-49026
+    - e100: Fix possible use after free in e100_xmit_prepare
+  * CVE-2025-21855
+    - ibmvnic: Don't reference skb after sending to VIOS
+  * CVE-2024-53218
+    - f2fs: fix race in concurrent f2fs_stop_gc_thread
+  * CVE-2024-47691
+    - f2fs: fix to avoid use-after-free in f2fs_stop_gc_thread()
+  * CVE-2025-40018
+    - ipvs: Defer ip_vs_ftp unregister during netns cleanup
+  * CVE-2025-39993
+    - media: imon: reorganize serialization
+    - media: rc: fix races with imon_disconnect()
+
+ -- Stewart Hore <stewart.hore@canonical.com>  Mon, 24 Nov 2025 14:06:32 +1100
+
+linux-xilinx-zynqmp (5.4.0-1070.74) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1070.74 -proposed tracker (LP: #2127327)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] zynqmp: Remove dwarfdump from Build-Depends
+
+  [ Ubuntu: 5.4.0-223.243 ]
+
+  * focal/linux: 5.4.0-223.243 -proposed tracker (LP: #2127329)
+  * VMSCAPE CVE-2025-40300 (LP: #2124105) // CVE-2025-40300
+    - Documentation/hw-vuln: Add VMSCAPE documentation
+    - x86/vmscape: Enumerate VMSCAPE bug
+    - x86/vmscape: Add conditional IBPB mitigation
+    - x86/vmscape: Enable the mitigation
+    - x86/bugs: Move cpu_bugs_smt_update() down
+    - x86/vmscape: Warn when STIBP is disabled with SMT
+    - x86/vmscape: Add old Intel CPUs to affected list
+  * VMSCAPE CVE-2025-40300 (LP: #2124105)
+    - [Config] Enable MITIGATION_VMSCAPE config
+  * CVE-2024-50061
+    - i3c: master: cdns: Fix use after free vulnerability in cdns_i3c_master
+      Driver Due to Race Condition
+  * CVE-2025-38352
+    - posix-cpu-timers: fix race between handle_posix_cpu_timers() and
+      posix_cpu_timer_del()
+  * CVE-2025-21727
+    - padata: fix UAF in padata_reorder
+  * CVE-2024-56664
+    - bpf, sockmap: Fix race between element replace and close()
+  * CVE-2023-52854
+    - padata: Fix refcnt handling in padata_free_shell()
+  * CVE-2025-37838
+    - HSI: ssi_protocol: Fix use after free vulnerability in ssi_protocol
+      Driver Due to Race Condition
+  * CVE-2024-35867
+    - smb: client: fix potential UAF in cifs_stats_proc_show()
+
+ -- Stewart Hore <stewart.hore@canonical.com>  Thu, 16 Oct 2025 15:48:15 +1100
+
+linux-xilinx-zynqmp (5.4.0-1069.73) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1069.73 -proposed tracker (LP: #2124153)
+
+  [ Ubuntu: 5.4.0-222.242 ]
+
+  * focal/linux: 5.4.0-222.242 -proposed tracker (LP: #2124155)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync git-ubuntu-log
+  * sources list generation using dwarfdump takes up to 0.5hr in build process
+    (LP: #2104911)
+    - [Packaging] Don't generate list of source files
+  * CVE-2025-37785
+    - ext4: optimize __ext4_check_dir_entry()
+    - ext4: fix OOB read when checking dotdot dir
+  * CVE-2025-21796
+    - nfsd: clear acl_access/acl_default after releasing them
+  * CVE-2025-38617
+    - net/packet: fix a race in packet_set_ring() and packet_notifier()
+  * CVE-2025-38618
+    - vsock: Do not allow binding to VMADDR_PORT_ANY
+  * CVE-2025-38477
+    - net/sched: sch_qfq: Fix race condition on qfq_aggregate
+    - net/sched: sch_qfq: Avoid triggering might_sleep in atomic context in
+      qfq_delete_class
+
+ -- Stewart Hore <stewart.hore@canonical.com>  Wed, 24 Sep 2025 15:11:43 +1000
+
+linux-xilinx-zynqmp (5.4.0-1068.72) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1068.72 -proposed tracker (LP: #2119816)
+
+  [ Ubuntu: 5.4.0-221.241 ]
+
+  * focal/linux: 5.4.0-221.241 -proposed tracker (LP: #2119818)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update annotations scripts
+  * CVE-2025-38350
+    - net/sched: Always pass notifications when child class becomes empty
+  * CVE-2024-57996 // CVE-2025-37752
+    - net_sched: sch_sfq: move the limit validation
+
+ -- Wei-Lin Chang <weilin.chang@canonical.com>  Tue, 19 Aug 2025 10:50:11 +0800
+
+linux-xilinx-zynqmp (5.4.0-1067.71) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1067.71 -proposed tracker (LP: #2116504)
+
+  [ Ubuntu: 5.4.0-220.240 ]
+
+  * focal/linux: 5.4.0-220.240 -proposed tracker (LP: #2116506)
+  * CVE-2023-52975
+    - scsi: iscsi: Move pool freeing
+    - scsi: iscsi_tcp: Fix UAF during logout when accessing the shost
+      ipaddress
+  * CVE-2023-52757
+    - smb: client: fix potential deadlock when releasing mids
+  * CVE-2025-38083
+    - net_sched: prio: fix a race in prio_tune()
+  * CVE-2024-49950
+    - Bluetooth: L2CAP: Fix uaf in l2cap_connect
+    - Bluetooth: hci_core: Fix calling mgmt_device_connected
+  * CVE-2024-50073
+    - tty: n_gsm: Fix use-after-free in gsm_cleanup_mux
+  * CVE-2025-37797
+    - net_sched: hfsc: Fix a UAF vulnerability in class handling
+  * CVE-2024-38541
+    - of: module: add buffer overflow check in of_modalias()
+
+ -- Wei-Lin Chang <weilin.chang@canonical.com>  Wed, 23 Jul 2025 16:16:30 +0800
+
+linux-xilinx-zynqmp (5.4.0-1066.70) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1066.70 -proposed tracker (LP: #2114446)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update variants
+
+  [ Ubuntu: 5.4.0-219.239 ]
+
+  * focal/linux: 5.4.0-219.239 -proposed tracker (LP: #2114448)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update variants
+    - [Packaging] update annotations scripts
+  * CVE-2025-37798
+    - sch_htb: make htb_qlen_notify() idempotent
+    - sch_htb: make htb_deactivate() idempotent
+    - sch_drr: make drr_qlen_notify() idempotent
+    - sch_hfsc: make hfsc_qlen_notify() idempotent
+    - sch_qfq: make qfq_qlen_notify() idempotent
+    - codel: remove sch->q.qlen check before qdisc_tree_reduce_backlog()
+  * CVE-2024-53051
+    - drm/i915/hdcp: Add encoder check in intel_hdcp_get_capability
+  * CVE-2025-37997
+    - netfilter: ipset: fix region locking in hash types
+  * CVE-2025-37890
+    - net_sched: hfsc: Fix a UAF vulnerability in class with netem as child
+      qdisc
+    - sch_hfsc: Fix qlen accounting bug when using peek in hfsc_enqueue()
+    - net_sched: hfsc: Address reentrant enqueue adding class to eltree twice
+  * CVE-2024-46787
+    - userfaultfd: fix checks for huge PMDs
+  * CVE-2025-37782
+    - Revert "UBUNTU: SAUCE: fs: hfs/hfsplus: add key_len boundary check to
+      hfs_bnode_read_key"
+    - hfs/hfsplus: fix slab-out-of-bounds in hfs_bnode_read_key
+  * CVE-2025-37750
+    - smb: client: fix UAF in decryption with multichannel
+  * CVE-2024-53185
+    - smb: client: fix NULL ptr deref in crypto_aead_setkey()
+  * CVE-2024-50047
+    - smb: client: fix UAF in async decryption
+  * CVE-2024-56662
+    - acpi: nfit: vmalloc-out-of-bounds Read in acpi_nfit_ctl
+
+ -- Abdur Rahman <abdur.rahman@canonical.com>  Tue, 17 Jun 2025 23:41:23 -0400
+
+linux-xilinx-zynqmp (5.4.0-1065.69) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1065.69 -proposed tracker (LP: #2110874)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update update.conf
+
+  [ Ubuntu: 5.4.0-218.238 ]
+
+  * focal/linux: 5.4.0-218.238 -proposed tracker (LP: #2110876)
+  * Rotate the Canonical Livepatch key (LP: #2111244)
+    - [Config] Prepare for Canonical Livepatch key rotation
+  * CVE-2025-2312 cifs.upcall could access incorrect kerberos credentials cache
+    (LP: #2099914) // CVE-2025-2312
+    - CIFS: New mount option for cifs.upcall namespace resolution
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357)
+    - vlan: fix memory leak in vlan_newlink()
+    - clockevents/drivers/i8253: Fix stop sequence for timer 0
+    - sched/isolation: Prevent boot crash when the boot CPU is nohz_full
+    - Revert "UBUNTU: SAUCE: sctp: sysctl: pass right argument to container_of"
+    - Revert "sctp: sysctl: cookie_hmac_alg: avoid using current->nsproxy"
+    - Revert "sctp: sysctl: auth_enable: avoid using current->nsproxy"
+    - sctp: sysctl: cookie_hmac_alg: avoid using current->nsproxy
+    - sctp: sysctl: auth_enable: avoid using current->nsproxy
+    - pinctrl: bcm281xx: Fix incorrect regmap max_registers value
+    - netpoll: Fix use correct return type for ndo_start_xmit()
+    - netpoll: remove dev argument from netpoll_send_skb_on_dev()
+    - netpoll: move netpoll_send_skb() out of line
+    - netpoll: netpoll_send_skb() returns transmit status
+    - netpoll: hold rcu read lock in __netpoll_send_skb()
+    - drivers/hv: Replace binary semaphore with mutex
+    - Drivers: hv: vmbus: Don't release fb_mmio resource in vmbus_free_mmio()
+    - ipvs: prevent integer overflow in do_ip_vs_get_ctl()
+    - netfilter: nft_exthdr: fix offset with ipv4_find_option()
+    - net/mlx5e: Prevent bridge link show failure for non-eswitch-allowed devices
+    - nvme-fc: go straight to connecting state when initializing
+    - hrtimers: Mark is_migration_base() with __always_inline
+    - powercap: call put_device() on an error path in
+      powercap_register_control_type()
+    - ACPI: resource: IRQ override for Eluktronics MECH-17
+    - HID: intel-ish-hid: fix the length of MNG_SYNC_FW_CLOCK in doorbell
+    - s390/cio: Fix CHPID "configure" attribute caching
+    - ASoC: rsnd: don't indicate warning on rsnd_kctrl_accept_runtime()
+    - nvmet-rdma: recheck queue state is LIVE in state lock in recv done
+    - sctp: Fix undefined behavior in left shift operation
+    - nvme: only allow entering LIVE from CONNECTING state
+    - fuse: don't truncate cached, mutated symlink
+    - x86/irq: Define trace events conditionally
+    - drm/nouveau: Do not override forced connector status
+    - block: fix 'kmem_cache of name 'bio-108' already exists'
+    - USB: serial: ftdi_sio: add support for Altera USB Blaster 3
+    - USB: serial: option: add Telit Cinterion FE990B compositions
+    - USB: serial: option: fix Telit Cinterion FE990A name
+    - USB: serial: option: match on interface class for Telit FN990B
+    - drm/atomic: Filter out redundant DPMS calls
+    - qlcnic: fix memory leak issues in qlcnic_sriov_common.c
+    - drm/gma500: Add NULL check for pci_gfx_root in mid_get_vbt_data()
+    - ASoC: codecs: wm0010: Fix error handling path in wm0010_spi_probe()
+    - i2c: ali1535: Fix an error handling path in ali1535_probe()
+    - i2c: ali15x3: Fix an error handling path in ali15x3_probe()
+    - i2c: sis630: Fix an error handling path in sis630_probe()
+    - firmware: imx-scu: fix OF node leak in .probe()
+    - xfrm_output: Force software GSO only in tunnel mode
+    - RDMA/bnxt_re: Avoid clearing VLAN_ID mask in modify qp path
+    - RDMA/hns: Fix wrong value of max_sge_rd
+    - ipv6: Set errno after ip_fib_metrics_init() in ip6_route_info_create().
+    - net/neighbor: add missing policy for NDTPA_QUEUE_LENBYTES
+    - i2c: omap: fix IRQ storms
+    - drm/v3d: Don't run jobs that have errors flagged in its fence
+    - mmc: atmel-mci: Add missing clk_disable_unprepare()
+    - ARM: shmobile: smp: Enforce shmobile_smp_* alignment
+    - batman-adv: Ignore own maximum aggregation size during RX
+    - ALSA: usb-audio: Add quirk for Plantronics headsets to fix control names
+    - HID: hid-plantronics: Add mic mute mapping and generalize quirks
+    - ARM: 9350/1: fault: Implement copy_from_kernel_nofault_allowed()
+    - ARM: 9351/1: fault: Add "cut here" line for prefetch aborts
+    - ARM: Remove address checking for MMUless devices
+    - counter: stm32-lptimer-cnt: fix error handling when enabling
+    - tty: serial: 8250: Add some more device IDs
+    - net: usb: qmi_wwan: add Telit Cinterion FN990B composition
+    - net: usb: qmi_wwan: add Telit Cinterion FE990B composition
+    - net: usb: usbnet: restore usb%d name exception for local mac addresses
+    - serial: 8250_dma: terminate correct DMA in tx_dma_flush()
+    - x86/mm/pat: cpa-test: fix length for CPA_ARRAY test
+    - cpufreq: governor: Fix negative 'idle_time' handling in dbs_update()
+    - x86/fpu: Avoid copying dynamic FP state from init_task in
+      arch_dup_task_struct()
+    - x86/platform: Only allow CONFIG_EISA for 32-bit
+    - [Config] updateconfigs for HAVE_EISA
+    - selinux: Chain up tool resolving errors in install_policy.sh
+    - EDAC/ie31200: Fix the size of EDAC_MC_LAYER_CHIP_SELECT layer
+    - EDAC/ie31200: Fix the DIMM size mask for several SoCs
+    - EDAC/ie31200: Fix the error path order of ie31200_init()
+    - PM: sleep: Fix handling devices with direct_complete set on errors
+    - lockdep: Don't disable interrupts on RT in disable_irq_nosync_lockdep.*()
+    - perf/ring_buffer: Allow the EPOLLRDNORM flag for poll
+    - ALSA: hda/realtek: Always honor no_shutup_pins
+    - drm/mediatek: mtk_hdmi: Fix typo for aud_sampe_size member
+    - PCI/portdrv: Only disable pciehp interrupts early when needed
+    - PCI: Remove stray put_device() in pci_register_host_bridge()
+    - PCI: pciehp: Don't enable HPIE when resuming in poll mode
+    - fbdev: au1100fb: Move a variable assignment behind a null pointer check
+    - mdacon: rework dependency list
+    - fbdev: sm501fb: Add some geometry checks.
+    - clk: amlogic: gxbb: drop incorrect flag on 32k clock
+    - bpf: Use preempt_count() directly in bpf_send_signal_common()
+    - lib: 842: Improve error handling in sw842_compress()
+    - pinctrl: renesas: rza2: Fix missing of_node_put() call
+    - clk: rockchip: rk3328: fix wrong clk_ref_usb3otg parent
+    - IB/mad: Check available slots before posting receive WRs
+    - clk: amlogic: g12b: fix cluster A parent data
+    - clk: amlogic: gxbb: drop non existing 32k clock parent
+    - clk: amlogic: g12a: fix mmc A peripheral clock
+    - x86/entry: Fix ORC unwinder for PUSH_REGS with save_ret=1
+    - power: supply: max77693: Fix wrong conversion of charge input threshold
+      value
+    - mfd: sm501: Switch to BIT() to mitigate integer overflows
+    - x86/dumpstack: Fix inaccurate unwinding from exception stacks due to
+      misplaced assignment
+    - isofs: fix KMSAN uninit-value bug in do_isofs_readdir()
+    - coresight: catu: Fix number of pages while using 64k pages
+    - iio: accel: mma8452: Ensure error return on failure to matching oversampling
+      ratio
+    - perf units: Fix insufficient array space
+    - kexec: initialize ELF lowest address to ULONG_MAX
+    - perf python: Fixup description of sample.id event member
+    - perf python: Decrement the refcount of just created event on failure
+    - perf python: Check if there is space to copy all the event
+    - fs/procfs: fix the comment above proc_pid_wchan()
+    - objtool, media: dib8000: Prevent divide-by-zero in dib8000_set_dds()
+    - ring-buffer: Fix bytes_dropped calculation issue
+    - octeontx2-af: Fix mbox INTR handler when num VFs > 64
+    - sched/smt: Always inline sched_smt_active()
+    - wifi: iwlwifi: fw: allocate chained SG tables for dump
+    - affs: generate OFS sequence numbers starting at 1
+    - affs: don't write overlarge OFS data block size fields
+    - sched/deadline: Use online cpus for validating runtime
+    - locking/semaphore: Use wake_q to wake up processes outside lock critical
+      section
+    - can: statistics: use atomic access in hot path
+    - hwmon: (nct6775-core) Fix out of bounds access for NCT679{8,9}
+    - ntb: intel: Fix using link status DB's
+    - vsock: avoid timeout during connect() if the socket is closing
+    - ipv6: fix omitted netlink attributes when using RTEXT_FILTER_SKIP_STATS
+    - net: dsa: mv88e6xxx: propperly shutdown PPU re-enable timer on destroy
+    - can: flexcan: only change CAN state when link up in system PM
+    - ntb_perf: Delete duplicate dmaengine_unmap_put() call in perf_copy_chunk()
+    - x86/tsc: Always save/restore TSC sched_clock() on suspend/resume
+    - ACPI: resource: Skip IRQ override on ASUS Vivobook 14 X1404VAP
+    - mmc: sdhci-pxav3: set NEED_RSP_BUSY capability
+    - jfs: add index corruption check to DT_GETPAGE()
+    - Linux 5.4.292
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-39735
+    - jfs: fix slab-out-of-bounds read in ea_get()
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22035
+    - tracing: Fix use-after-free in print_graph_function_flags during tracer
+      switching
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22045
+    - x86/mm: Fix flush_tlb_range() when used for zapping normal PMDs
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22054
+    - arcnet: Add NULL check in com20020pci_probe()
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-38637
+    - net_sched: skbprio: Remove overly strict queue assertions
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22063
+    - netlabel: Fix NULL pointer exception caused by CALIPSO on IPv4 sockets
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2023-53034
+    - ntb_hw_switchtec: Fix shift-out-of-bounds in switchtec_ntb_mw_set_trans
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22071
+    - spufs: fix a leak in spufs_create_context()
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22073
+    - spufs: fix a leak on spufs_new_file() failure
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22079
+    - ocfs2: validate l_tree_depth to avoid out-of-bounds access
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22086
+    - RDMA/mlx5: Fix mlx5_poll_one() cur_qp update flow
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2024-58093
+    - PCI/ASPM: Fix link state exit during switch upstream function removal
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-23136
+    - thermal: int340x: Add NULL check for adev
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22020
+    - memstick: rtsx_usb_ms: Fix slab-use-after-free in rtsx_usb_ms_drv_remove
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22021
+    - netfilter: socket: Lookup orig tuple for IPv6 SNAT
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22018
+    - atm: Fix NULL pointer dereference
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-21996
+    - drm/radeon: fix uninitialized size issue in radeon_vce_cs_parse()
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22004
+    - net: atm: fix use after free in lec_send()
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22005
+    - ipv6: Fix memleak of nhc_pcpu_rth_output in fib_check_nh_v6_gw().
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22007
+    - Bluetooth: Fix error code in chan_alloc_skb_cb()
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-21956
+    - drm/amd/display: Assign normalized_pix_clk when color depth = 14
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-21991
+    - x86/microcode/AMD: Fix out-of-bounds on systems with CPU-less NUMA nodes
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-21992
+    - HID: ignore non-functional sensor in HP 5MP Camera
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-21957
+    - scsi: qla1280: Fix kernel oops when debug level > 2
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-21993
+    - iscsi_ibft: Fix UBSAN shift-out-of-bounds warning in ibft_attr_show_nic()
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-21959
+    - netfilter: nf_conncount: Fully initialize struct nf_conncount_tuple in
+      insert_tree()
+  * CVE-2024-53168
+    - net: make sock_inuse_add() available
+    - sunrpc: fix one UAF issue caused by sunrpc kernel tcp socket
+  * CVE-2024-56551
+    - drm/amdgpu: fix usage slab after free
+  * CVE-2021-47211
+    - ALSA: usb-audio: fix null pointer dereference on pointer cs_desc
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update annotations scripts
+
+ -- Abdur Rahman <abdur.rahman@canonical.com>  Thu, 05 Jun 2025 17:09:47 -0400
+
+linux-xilinx-zynqmp (5.4.0-1064.68) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1064.68 -proposed tracker (LP: #2106867)
+
+  [ Ubuntu: 5.4.0-216.236 ]
+
+  * focal/linux: 5.4.0-216.236 -proposed tracker (LP: #2106869)
+  * CVE-2023-52741
+    - cifs: Fix use-after-free in rdata->read_into_pages()
+  * CVE-2021-47191
+    - scsi: scsi_debug: Fix out-of-bound read in resp_readcap16()
+  * iommu/arm-smmu-v3: Don't reserve implementation defined register space
+    (LP: #2067864)
+    - iommu/arm-smmu-v3: Don't reserve implementation defined register space
+  * CVE-2025-21971
+    - net_sched: Prevent creation of classes with TC_H_ROOT
+  * CVE-2024-56599
+    - wifi: ath10k: avoid NULL pointer error during sdio remove
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002)
+    - perf cs-etm: Add missing variable in cs_etm__process_queues()
+    - udf: Fix use of check_add_overflow() with mixed type arguments
+    - overflow: Add __must_check attribute to check_*() helpers
+    - overflow: Correct check_shl_overflow() comment
+    - overflow: Allow mixed type arguments
+    - afs: Fix directory format encoding struct
+    - partitions: ldm: remove the initial kernel-doc notation
+    - drm/etnaviv: Fix page property being used for non writecombine buffers
+    - wifi: rtlwifi: do not complete firmware loading needlessly
+    - rtlwifi: rtl8192se Rename RT_TRACE to rtl_dbg
+    - wifi: rtlwifi: rtl8192se: rise completion of firmware loading as last step
+    - wifi: rtlwifi: usb: fix workqueue leak when probe fails
+    - dt-bindings: mmc: controller: clarify the address-cells description
+    - rtlwifi: replace usage of found with dedicated list iterator variable
+    - wifi: rtlwifi: remove unused timer and related code
+    - wifi: rtlwifi: remove unused dualmac control leftovers
+    - wifi: rtlwifi: pci: wait for firmware loading before releasing memory
+    - cpupower: fix TSC MHz calculation
+    - regulator: of: Implement the unwind path of of_regulator_match()
+    - wifi: wlcore: fix unbalanced pm_runtime calls
+    - selftests/harness: Display signed values correctly
+    - selftests: harness: fix printing of mismatch values in __EXPECT()
+    - clk: analogbits: Fix incorrect calculation of vco rate delta
+    - net/mlxfw: Drop hard coded max FW flash image size
+    - tools/testing/selftests/bpf/test_tc_tunnel.sh: Fix wait for server bind
+    - ASoC: sun4i-spdif: Add clock multiplier settings
+    - perf header: Fix one memory leakage in process_bpf_btf()
+    - perf header: Fix one memory leakage in process_bpf_prog_info()
+    - ktest.pl: Remove unused declarations in run_bisect_test function
+    - padata: fix sysfs store callback check
+    - perf top: Don't complain about lack of vmlinux when not resolving some
+      kernel samples
+    - perf report: Fix misleading help message about --demangle
+    - RDMA/mlx4: Avoid false error about access to uninitialized gids array
+    - arm64: dts: mediatek: mt8173-evb: Drop regulator-compatible property
+    - arm64: dts: mediatek: mt8173-evb: Fix MT6397 PMIC sub-node names
+    - ARM: dts: mediatek: mt7623: fix IR nodename
+    - fbdev: omapfb: Fix an OF node leak in dss_of_port_get_parent_device()
+    - media: rc: iguanair: handle timeouts
+    - media: lmedm04: Use GFP_KERNEL for URB allocation/submission.
+    - media: lmedm04: Handle errors for lme2510_int_read
+    - PCI: endpoint: Destroy the EPC device in devm_pci_epc_destroy()
+    - media: mipi-csis: Add check for clk_enable()
+    - media: camif-core: Add check for clk_enable()
+    - media: uvcvideo: Propagate buf->error to userspace
+    - staging: media: imx: fix OF node leak in imx_media_add_of_subdevs()
+    - scsi: mpt3sas: Set ioc->manu_pg11.EEDPTagMode directly to 1
+    - scsi: ufs: bsg: Delete bsg_dev when setting up bsg fails
+    - ocfs2: mark dquot as inactive if failed to start trans while releasing dquot
+    - module: Extend the preempt disabled section in
+      dereference_symbol_descriptor().
+    - dmaengine: ti: edma: fix OF node reference leaks in edma_driver
+    - net: fec: implement TSO descriptor cleanup
+    - PM: hibernate: Add error handling for syscore_suspend()
+    - perf trace: Fix runtime error of index out of bounds
+    - vsock: Allow retrying on connect() failure
+    - net: sh_eth: Fix missing rtnl lock in suspend/resume path
+    - genksyms: fix memory leak when the same symbol is added from source
+    - genksyms: fix memory leak when the same symbol is read from *.symref file
+    - hexagon: fix using plain integer as NULL pointer warning in cmpxchg
+    - hexagon: Fix unbalanced spinlock in die()
+    - NFSD: Reset cb_seq_status after NFS4ERR_DELAY
+    - ktest.pl: Check kernelrelease return in get_version
+    - drivers/card_reader/rtsx_usb: Restore interrupt based detection
+    - usb: typec: tcpm: set SRC_SEND_CAPABILITIES timeout to PD_T_SENDER_RESPONSE
+    - btrfs: output the reason for open_ctree() failure
+    - btrfs: convert BUG_ON in btrfs_reloc_cow_block() to proper error handling
+    - sched: Don't try to catch up excess steal time.
+    - x86/amd_nb: Restrict init function to AMD-based systems
+    - tun: fix group permission check
+    - mmc: core: Respect quirk_max_rate for non-UHS SDIO card
+    - mfd: lpc_ich: Add another Gemini Lake ISA bridge PCI device-id
+    - HID: Wacom: Add PCI Wacom device support
+    - APEI: GHES: Have GHES honor the panic= setting
+    - x86/mm: Don't disable PCID when INVLPG has been fixed by microcode
+    - spi-mxs: Fix chipselect glitch
+    - nilfs2: move page release outside of nilfs_delete_entry and nilfs_set_link
+    - nilfs2: eliminate staggered calls to kunmap in nilfs_rename
+    - media: uvcvideo: Only save async fh if success
+    - kbuild: userprogs: use correct lld when linking through clang
+    - tasklet: Introduce new initialization API
+    - net: usb: rtl8150: use new tasklet API
+    - usb: xhci: Add timeout argument in address_device USB HCD callback
+    - nvme: handle connectivity loss in nvme_set_queue_count
+    - firmware: iscsi_ibft: fix ISCSI_IBFT Kconfig entry
+    - gpu: drm_dp_cec: fix broken CEC adapter properties check
+    - tg3: Disable tg3 PCIe AER on system reboot
+    - udp: gso: do not drop small packets when PMTU reduces
+    - tun: revert fix group permission check
+    - cpufreq: s3c64xx: Fix compilation warning
+    - leds: lp8860: Write full EEPROM, not only half of it
+    - s390/futex: Fix FUTEX_OP_ANDN implementation
+    - m68k: vga: Fix I/O defines
+    - arm64: dts: rockchip: increase gmac rx_delay on rk3399-puma
+    - KVM: s390: vsie: fix some corner-cases when grabbing vsie pages
+    - drm/komeda: Add check for komeda_get_layer_fourcc_list()
+    - clk: qcom: clk-alpha-pll: fix alpha mode configuration
+    - clk: qcom: clk-rpmh: prevent integer overflow in recalc_rate
+    - perf bench: Fix undefined behavior in cmpworker()
+    - of: Correct child specifier used as input of the 2nd nexus node
+    - of: Fix of_find_node_opts_by_path() handling of alias+path+options
+    - of: reserved-memory: Fix using wrong number of cells to get property
+      'alignment'
+    - HID: hid-sensor-hub: don't use stale platform-data on remove
+    - usb: gadget: f_tcm: Translate error to sense
+    - usb: gadget: f_tcm: Decrement command ref count on cleanup
+    - usb: gadget: f_tcm: ep_autoconfig with fullspeed endpoint
+    - usb: gadget: f_tcm: Don't prepare BOT write request twice
+    - serial: sh-sci: Drop __initdata macro for port_cfg
+    - serial: sh-sci: Do not probe the serial port if its slot in sci_ports[] is
+      in use
+    - powerpc/pseries/eeh: Fix get PE state translation
+    - kbuild: Move -Wenum-enum-conversion to W=2
+    - soc: qcom: smem_state: fix missing of_node_put in error path
+    - media: ov5640: fix get_light_freq on auto
+    - media: uvcvideo: Fix event flags in uvc_ctrl_send_events
+    - media: uvcvideo: Remove redundant NULL assignment
+    - crypto: qce - fix goto jump in error path
+    - crypto: qce - unregister previously registered algos in error path
+    - nvmem: core: improve range check for nvmem_cell_write()
+    - vfio/platform: check the bounds of read/write syscalls
+    - ocfs2: fix incorrect CPU endianness conversion causing mount failure
+    - mtd: onenand: Fix uninitialized retlen in do_otp_read()
+    - misc: fastrpc: Fix registered buffer page address
+    - net/ncsi: wait for the last response to Deselect Package before configuring
+      channel
+    - MIPS: ftrace: Declare ftrace_get_parent_ra_addr() as static
+    - ocfs2: check dir i_size in ocfs2_find_entry
+    - ndisc: ndisc_send_redirect() must use dev_get_by_index_rcu()
+    - gpio: bcm-kona: Fix GPIO lock/unlock for banks above bank 0
+    - gpio: bcm-kona: Make sure GPIO bits are unlocked when requesting IRQ
+    - gpio: bcm-kona: Add missing newline to dev_err format string
+    - xen: remove a confusing comment on auto-translated guest I/O
+    - x86/xen: allow larger contiguous memory regions in PV guests
+    - media: cxd2841er: fix 64-bit division on gcc-9
+    - vfio/pci: Enable iowrite64 and ioread64 for vfio pci
+    - Grab mm lock before grabbing pt lock
+    - ASoC: Intel: bytcr_rt5640: Add DMI quirk for Vexia Edu Atla 10 tablet 5V
+    - usb: roles: set switch registered flag early on
+    - usb: gadget: udc: renesas_usb3: Fix compiler warning
+    - usb: dwc2: gadget: remove of_node reference upon udc_stop
+    - USB: pci-quirks: Fix HCCPARAMS register error for LS7A EHCI
+    - USB: quirks: add USB_QUIRK_NO_LPM quirk for Teclast dist
+    - USB: Add USB_QUIRK_NO_LPM quirk for sony xperia xz1 smartphone
+    - USB: cdc-acm: Fill in Renesas R-Car D3 USB Download mode quirk
+    - usb: cdc-acm: Fix handling of oversized fragments
+    - USB: serial: option: add MeiG Smart SLM828
+    - USB: serial: option: add Telit Cinterion FN990B compositions
+    - USB: serial: option: fix Telit Cinterion FN990A name
+    - USB: serial: option: drop MeiG Smart defines
+    - can: c_can: fix unbalanced runtime PM disable in error path
+    - can: j1939: j1939_sk_send_loop(): fix unable to send messages with data
+      length zero
+    - alpha: make stack 16-byte aligned (most cases)
+    - serial: 8250: Fix fifo underflow on flush
+    - alpha: align stack for page fault and user unaligned trap handlers
+    - gpio: stmpe: Check return value of stmpe_reg_read in
+      stmpe_gpio_irq_sync_unlock
+    - regmap-irq: Add missing kfree()
+    - net: treat possible_net_t net pointer as an RCU one and add read_pnet_rcu()
+    - net: add dev_net_rcu() helper
+    - ipv4: use RCU protection in rt_is_expired()
+    - ipv4: use RCU protection in inet_select_addr()
+    - neighbour: delete redundant judgment statements
+    - alpha: replace hardcoded stack offsets with autogenerated ones
+    - nilfs2: do not output warnings when clearing dirty buffers
+    - can: ems_pci: move ASIX AX99100 ids to pci_ids.h
+    - serial: 8250_pci: add support for ASIX AX99100
+    - parport_pc: add support for ASIX AX99100
+    - x86/i8253: Disable PIT timer 0 when not in use
+    - Revert "btrfs: avoid monopolizing a core when activating a swap file"
+    - btrfs: avoid monopolizing a core when activating a swap file
+    - vlan: introduce vlan_dev_free_egress_priority
+    - vlan: move dev_put into vlan_dev_uninit
+    - scsi: storvsc: Set correct data length for sending SCSI command without
+      payload
+    - crypto: testmgr - fix wrong key length for pkcs1pad
+    - crypto: testmgr - Fix wrong test case of RSA
+    - crypto: testmgr - fix version number of RSA tests
+    - crypto: testmgr - populate RSA CRT parameters in RSA test vectors
+    - crypto: testmgr - some more fixes to RSA test vectors
+    - mm: update mark_victim tracepoints fields
+    - usb: dwc3: Increase DWC3 controller halt timeout
+    - usb: dwc3: Fix timeout issue during controller enter/exit from halt state
+    - usb/gadget: f_midi: convert tasklets to use new tasklet_setup() API
+    - usb/gadget: f_midi: Replace tasklet with work
+    - powerpc/64s/mm: Move __real_pte stubs into hash-4k.h
+    - powerpc/64s: Rewrite __real_pte() and __rpte_to_hidx() as static inline
+    - ALSA: hda/realtek - Add type for ALC287
+    - ALSA: hda/realtek: Fixup ALC225 depop procedure
+    - geneve: Suppress list corruption splat in geneve_destroy_tunnels().
+    - net: extract port range fields from fl_flow_key
+    - flow_dissector: Fix handling of mixed port and port-range keys
+    - flow_dissector: Fix port range key handling in BPF conversion
+    - power: supply: da9150-fg: fix potential overflow
+    - ALSA: hda/conexant: Add quirk for HP ProBook 450 G4 mute LED
+    - acct: block access to kernel internal filesystems
+    - batman-adv: Ignore neighbor throughput metrics in error case
+    - sunrpc: suppress warnings for unused procfs functions
+    - net: loopback: Avoid sending IP packets without an Ethernet header
+    - net: cadence: macb: Synchronize stats calculations
+    - ASoC: es8328: fix route from DAC to output
+    - ipvs: Always clear ipvs_property flag in skb_scrub_packet()
+    - net: mvpp2: cls: Fixed Non IP flow, with vlan tag flow defination.
+    - x86/CPU: Fix warm boot hang regression on AMD SC1100 SoC systems
+    - ftrace: Avoid potential division by zero in function_stat_show()
+    - perf/core: Fix low freq setting via IOC_PERIOD
+    - phy: tegra: xusb: reset VBUS & ID OVERRIDE
+    - phy: exynos5-usbdrd: fix MPLL_MULTIPLIER and SSC_REFCLKSEL masks in refclk
+    - kernel/acct.c: use #elif instead of #end and #elif
+    - kernel/acct.c: use dedicated helper to access rlimit values
+    - drm/amdgpu: skip BAR resizing if the bios already did it
+    - drm/amdgpu: Check extended configuration space register when system uses
+      large bar
+    - drm/amdgpu: disable BAR resize on Dell G5 SE
+    - Revert "of: reserved-memory: Fix using wrong number of cells to get property
+      'alignment'"
+    - HID: appleir: Fix potential NULL dereference at raw event handle
+    - ALSA: hda: intel: Add Dell ALC3271 to power_save denylist
+    - ALSA: hda/realtek: update ALC222 depop optimize
+    - drm/radeon: Fix rs400_gpu_init for ATI mobility radeon Xpress 200M
+    - platform/x86: thinkpad_acpi: Add battery quirk for ThinkPad X131e
+    - x86/cacheinfo: Validate CPUID leaf 0x2 EDX output
+    - x86/cpu: Validate CPUID leaf 0x2 EDX output
+    - x86/cpu: Properly parse CPUID leaf 0x2 TLB descriptor 0x63
+    - wifi: cfg80211: regulatory: improve invalid hints checking
+    - wifi: nl80211: reject cooked mode if it is set along with other flags
+    - rapidio: add check for rio_add_net() in rio_scan_alloc_net()
+    - rapidio: fix an API misues when rio_add_net() fails
+    - mm/page_alloc: fix uninitialized variable
+    - wifi: iwlwifi: limit printed string from FW file
+    - HID: google: fix unused variable warning under !CONFIG_ACPI
+    - HID: intel-ish-hid: Fix use-after-free issue in ishtp_hid_remove()
+    - net: gso: fix ownership in __udp_gso_segment
+    - caif_virtio: fix wrong pointer check in cfv_probe()
+    - hwmon: (pmbus) Initialise page count in pmbus_identify()
+    - hwmon: (ntc_thermistor) Fix the ncpXXxh103 sensor table
+    - hwmon: (ad7314) Validate leading zero bits and return error
+    - llc: do not use skb_get() before dev_queue_xmit()
+    - hwmon: fix a NULL vs IS_ERR_OR_NULL() check in xgene_hwmon_probe()
+    - drm/sched: Fix preprocessor guard
+    - be2net: fix sleeping while atomic bugs in be_ndo_bridge_getlink
+    - ppp: Fix KMSAN uninit-value warning with bpf
+    - vlan: enforce underlying device type
+    - net-timestamp: support TCP GSO case for a few missing flags
+    - net: ipv6: fix dst ref loop in ila lwtunnel
+    - net: ipv6: fix missing dst ref drop in ila lwtunnel
+    - gpio: rcar: Fix missing of_node_put() call
+    - Revert "drivers/card_reader/rtsx_usb: Restore interrupt based detection"
+    - usb: renesas_usbhs: Call clk_put()
+    - usb: renesas_usbhs: Use devm_usb_get_phy()
+    - usb: quirks: Add DELAY_INIT and NO_LPM for Prolific Mass Storage Card Reader
+    - usb: renesas_usbhs: Flush the notify_hotplug_work
+    - usb: atm: cxacru: fix a flaw in existing endpoint checks
+    - usb: typec: ucsi: increase timeout for PPM reset operations
+    - usb: typec: tcpci_rt1711h: Unmask alert interrupts to fix functionality
+    - usb: gadget: Set self-powered based on MaxPower and bmAttributes
+    - usb: gadget: Fix setting self-powered state on suspend
+    - usb: gadget: Check bmAttributes only if configuration is valid
+    - xhci: pci: Fix indentation in the PCI device ID definitions
+    - intel_th: pci: Add Arrow Lake support
+    - intel_th: pci: Add Panther Lake-H support
+    - intel_th: pci: Add Panther Lake-P/U support
+    - slimbus: messaging: Free transaction ID in delayed interrupt scenario
+    - eeprom: digsy_mtc: Make GPIO lookup table match the device
+    - Linux 5.4.291
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-26982
+    - Squashfs: check the inode number is not the invalid value of zero
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21846
+    - acct: perform last write from workqueue
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21862
+    - drop_monitor: fix incorrect initialization order
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58090
+    - sched/core: Prevent rescheduling when interrupts are disabled
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21877
+    - usbnet: gl620a: fix endpoint checking in genelink_bind()
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21823
+    - batman-adv: Drop unmanaged ELP metric worker
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21848
+    - nfp: bpf: Add check for nfp_app_ctrl_msg_alloc()
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21871
+    - tee: optee: Fix supplicant wait loop
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21865
+    - gtp: Suppress list corruption splat in gtp_net_exit_batch_rtnl().
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21858
+    - geneve: Fix use-after-free in geneve_find_dev().
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21866
+    - powerpc/code-patching: Fix KASAN hit by not flagging text patching area as
+      VM_ALLOC
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21859
+    - USB: gadget: f_midi: f_midi_complete to call queue_work
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-57977
+    - memcg: fix soft lockup in the OOM process
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-50055
+    - driver core: bus: Fix double free in driver API bus_register()
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-57979
+    - pps: Fix a use-after-free
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21811
+    - nilfs2: protect access to buffers with no active references
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21722
+    - nilfs2: do not force clear folio if buffer is referenced
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21760
+    - ndisc: extend RCU protection in ndisc_send_skb()
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21761
+    - openvswitch: use RCU protection in ovs_vport_cmd_fill_info()
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21762
+    - arp: use RCU protection in arp_xmit()
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21763
+    - neighbour: use RCU protection in __neigh_notify()
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21764
+    - ndisc: use RCU protection in ndisc_alloc_skb()
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21765
+    - ipv6: use RCU protection in ip6_default_advmss()
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21772
+    - partitions: mac: fix handling of bogus partition table
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21704
+    - usb: cdc-acm: Check control transfer buffer size before access
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21776
+    - USB: hub: Ignore non-compliant devices with too many configs or interfaces
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21835
+    - usb: gadget: f_midi: fix MIDI Streaming descriptor lengths
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21781
+    - batman-adv: fix panic during interface removal
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21782
+    - orangefs: fix a oob in orangefs_debug_write
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21785
+    - arm64: cacheinfo: Avoid out-of-bounds write to cacheinfo array
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21787
+    - team: better TEAM_OPTION_TYPE_STRING validation
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21791
+    - vrf: use RCU protection in l3mdev_l3_out()
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58020
+    - HID: multitouch: Add NULL check in mt_input_configured
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21814
+    - ptp: Ensure info->enable callback is always set
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21735
+    - NFC: nci: Add bounds checking in nci_hci_create_pipe()
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21736
+    - nilfs2: fix possible int overflows in nilfs_fiemap()
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58001
+    - ocfs2: handle a symlink read error correctly
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58007
+    - soc: qcom: socinfo: Avoid out of bounds read of serial number
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21744
+    - wifi: brcmfmac: fix NULL pointer dereference in brcmf_txfinalize()
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58009
+    - Bluetooth: L2CAP: handle NULL sock pointer in l2cap_sock_alloc
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58083
+    - KVM: Explicitly verify target vCPU is online in kvm_get_vcpu()
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58010
+    - binfmt_flat: Fix integer overflow bug on 32 bit systems
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21749
+    - net: rose: lock the socket in rose_bind()
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-57981
+    - usb: xhci: Fix NULL pointer dereference on certain command aborts
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21708
+    - net: usb: rtl8150: enable basic endpoint checking
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21647
+    - sched: sch_cake: add bounds checks to host bulk flow fairness counts
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58002
+    - media: uvcvideo: Remove dangling pointers
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21721
+    - nilfs2: handle errors that nilfs_prepare_chunk() may return
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58085
+    - tomoyo: don't emit warning in tomoyo_write_control()
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58014
+    - wifi: brcmsmac: add gain range check to wlc_phy_iqcal_gainparams_nphy()
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58017
+    - printk: Fix signed integer overflow when defining LOG_BUF_LEN_MAX
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21753
+    - btrfs: fix use-after-free when attempting to join an aborted transaction
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58055
+    - usb: gadget: f_tcm: Don't free command immediately
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-57980
+    - media: uvcvideo: Fix double free in error path
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-57986
+    - HID: core: Fix assumption that Resolution Multipliers must be in Logical
+      Collections
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21715
+    - net: davicom: fix UAF in dm9000_drv_remove
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21718
+    - net: rose: fix timer races against user threads
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21719
+    - ipmr: do not call mr_mfc_uses_dev() for unres entries
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58058
+    - ubifs: skip dumping tnc tree when zroot is null
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58069
+    - rtc: pcf85063: fix potential OOB write in PCF85063 NVMEM read
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-57973
+    - rdma/cxgb4: Prevent potential integer overflow on 32bit
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21728
+    - bpf: Send signals asynchronously if !preemptible
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21806
+    - net: let net.core.dev_weight always be non-zero
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58071
+    - team: prevent adding a device which is already a team device lower
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58063
+    - wifi: rtlwifi: fix memory leaks and invalid access at probe error path
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58072
+    - wifi: rtlwifi: remove unused check_buddy_priv
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58051
+    - ipmi: ipmb: Add check devm_kasprintf() returned value
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58052
+    - drm/amdgpu: Fix potential NULL pointer dereference in
+      atomctrl_get_smc_sclk_range_table
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21731
+    - nbd: don't allow reconnect after disconnect
+  * CVE-2024-26996
+    - usb: gadget: f_ncm: Fix UAF ncm object at re-bind after usb ep transport
+      error
+  * CVE-2023-52664
+    - net: atlantic: eliminate double free in error handling logic
+  * CVE-2024-26689
+    - ceph: prevent use-after-free in encode_cap_msg()
+  * CVE-2023-52927
+    - netfilter: allow exp not to be removed in nf_ct_find_expectation
+
+ -- Wei-Lin Chang <weilin.chang@canonical.com>  Wed, 23 Apr 2025 10:31:08 +0800
+
+linux-xilinx-zynqmp (5.4.0-1063.67) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1063.67 -proposed tracker (LP: #2106917)
+
+  [ Ubuntu: 5.4.0-215.235 ]
+
+  * focal/linux: 5.4.0-215.235 -proposed tracker (LP: #2106919)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update annotations scripts
+  * CVE-2023-52664
+    - net: atlantic: eliminate double free in error handling logic
+  * CVE-2024-26689
+    - ceph: prevent use-after-free in encode_cap_msg()
+  * CVE-2023-52927
+    - netfilter: allow exp not to be removed in nf_ct_find_expectation
+
+ -- Wei-Lin Chang <weilin.chang@canonical.com>  Tue, 22 Apr 2025 10:10:46 +0800
+
+linux-xilinx-zynqmp (5.4.0-1062.66) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1062.66 -proposed tracker (LP: #2102633)
+
+  [ Ubuntu: 5.4.0-214.234 ]
+
+  * focal/linux: 5.4.0-214.234 -proposed tracker (LP: #2102635)
+  * CVE-2024-50256
+    - netfilter: nf_reject_ipv6: fix potential crash in nf_send_reset6()
+  * CVE-2025-21702
+    - pfifo_tail_enqueue: Drop new packet when sch->limit == 0
+  * CVE-2025-21703
+    - netem: Update sch->q.qlen before qdisc_tree_reduce_backlog()
+  * CVE-2024-26915
+    - drm/amdgpu: Reset IH OVERFLOW_CLEAR bit
+  * CVE-2025-21700
+    - net: sched: Disallow replacing of child qdisc from one parent to another
+  * CVE-2024-46826
+    - ELF: fix kernel.randomize_va_space double read
+  * CVE-2024-56651
+    - can: hi311x: hi3110_can_ist(): fix potential use-after-free
+  * CVE-2024-53237
+    - driver core: Introduce device_find_any_child() helper
+    - Bluetooth: fix use-after-free in device_for_each_child()
+  * CVE-2024-35958
+    - net: ena: Fix incorrect descriptor free behavior
+  * CVE-2024-49974
+    - NFSD: Limit the number of concurrent async COPY operations
+  * CVE-2021-47119
+    - ext4: fix memory leak in ext4_fill_super
+  * CVE-2024-56658
+    - net: defer final 'struct net' free in netns dismantle
+  * CVE-2024-35864
+    - smb: client: fix potential UAF in smb2_is_valid_lease_break()
+  * CVE-2024-35864/CVE-2024-26928
+    - smb: client: fix potential UAF in cifs_debug_files_proc_show()
+
+ -- Wei-Lin Chang <weilin.chang@canonical.com>  Wed, 26 Mar 2025 11:49:30 +0800
+
+linux-xilinx-zynqmp (5.4.0-1061.65) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1061.65 -proposed tracker (LP: #2102365)
+
+  [ Ubuntu: 5.4.0-212.232 ]
+
+  * focal/linux: 5.4.0-212.232 -proposed tracker (LP: #2102367)
+  * CVE-2024-56658
+    - net: defer final 'struct net' free in netns dismantle
+  * CVE-2024-35864
+    - smb: client: fix potential UAF in smb2_is_valid_lease_break()
+  * CVE-2024-35864/CVE-2024-26928
+    - smb: client: fix potential UAF in cifs_debug_files_proc_show()
+
+ -- Koichiro Den <koichiro.den@canonical.com>  Fri, 21 Mar 2025 10:35:17 +0900
+
+linux-xilinx-zynqmp (5.4.0-1060.64) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1060.64 -proposed tracker (LP: #2101994)
+
+  [ Ubuntu: 5.4.0-211.231 ]
+
+  * focal/linux: 5.4.0-211.231 -proposed tracker (LP: #2101996)
+  * cve-2018-5803 kernel panic (LP: #2101091)
+    - SAUCE: sctp: sysctl: pass right argument to container_of
+
+ -- Koichiro Den <koichiro.den@canonical.com>  Thu, 13 Mar 2025 10:04:51 +0900
+
+linux-xilinx-zynqmp (5.4.0-1059.63) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1059.63 -proposed tracker (LP: #2098351)
+
+  [ Ubuntu: 5.4.0-210.230 ]
+
+  * focal/linux: 5.4.0-210.230 -proposed tracker (LP: #2098353)
+  * Focal update: v5.4.290 upstream stable release (LP: #2098439)
+    - jbd2: flush filesystem device before updating tail sequence
+    - dm array: fix releasing a faulty array block twice in dm_array_cursor_end
+    - dm array: fix unreleased btree blocks on closing a faulty array cursor
+    - dm array: fix cursor index when skipping across block boundaries
+    - ieee802154: ca8210: Add missing check for kfifo_alloc() in ca8210_probe()
+    - net: 802: LLC+SNAP OID:PID lookup on start of skb data
+    - tcp/dccp: complete lockless accesses to sk->sk_max_ack_backlog
+    - tcp/dccp: allow a connection when sk_max_ack_backlog is zero
+    - net_sched: cls_flow: validate TCA_FLOW_RSHIFT attribute
+    - tls: Fix tls_sw_sendmsg error handling
+    - dm thin: make get_first_thin use rcu-safe list first function
+    - sctp: sysctl: cookie_hmac_alg: avoid using current->nsproxy
+    - sctp: sysctl: auth_enable: avoid using current->nsproxy
+    - drm/amd/display: Add check for granularity in dml ceil/floor helpers
+    - ACPI: resource: Add TongFang GM5HG0A to irq1_edge_low_force_override[]
+    - ACPI: resource: Add Asus Vivobook X1504VAP to irq1_level_low_skip_override[]
+    - drm/amd/display: increase MAX_SURFACES to the value supported by hw
+    - USB: serial: option: add MeiG Smart SRM815
+    - USB: serial: option: add Neoway N723-EA support
+    - staging: iio: ad9834: Correct phase range check
+    - staging: iio: ad9832: Correct phase range check
+    - usb-storage: Add max sectors quirk for Nokia 208
+    - USB: serial: cp210x: add Phoenix Contact UPS Device
+    - usb: gadget: u_serial: Disable ep before setting port to null to fix the
+      crash caused by port being null
+    - USB: usblp: return error when setting unsupported protocol
+    - USB: core: Disable LPM only for non-suspended ports
+    - usb: fix reference leak in usb_new_device()
+    - usb: gadget: f_fs: Remove WARN_ON in functionfs_bind
+    - iio: pressure: zpa2326: fix information leak in triggered buffer
+    - iio: dummy: iio_simply_dummy_buffer: fix information leak in triggered
+      buffer
+    - iio: light: vcnl4035: fix information leak in triggered buffer
+    - iio: imu: kmx61: fix information leak in triggered buffer
+    - iio: adc: ti-ads8688: fix information leak in triggered buffer
+    - iio: gyro: fxas21002c: Fix missing data update in trigger handler
+    - iio: adc: ti-ads124s08: Use gpiod_set_value_cansleep()
+    - iio: adc: at91: call input_free_device() on allocated iio_dev
+    - iio: inkern: call iio_device_put() only on mapped devices
+    - arm64: dts: rockchip: fix defines in pd_vio node for rk3399
+    - arm64: dts: rockchip: fix pd_tcpc0 and pd_tcpc1 node position on rk3399
+    - arm64: dts: rockchip: add #power-domain-cells to power domain nodes
+    - arm64: dts: rockchip: add hevc power domain clock to rk3328
+    - phy: core: fix code style in devm_of_phy_provider_unregister
+    - phy: core: Fix that API devm_of_phy_provider_unregister() fails to
+      unregister the phy provider
+    - ocfs2: correct return value of ocfs2_local_free_info()
+    - ocfs2: fix slab-use-after-free due to dangling pointer dqi_priv
+    - sctp: sysctl: rto_min/max: avoid using current->nsproxy
+    - net: ethernet: ti: cpsw_ale: Fix cpsw_ale_get_field()
+    - net: net_namespace: Optimize the code
+    - net: add exit_batch_rtnl() method
+    - gtp: use exit_batch_rtnl() method
+    - gtp: Use for_each_netdev_rcu() in gtp_genl_dump_pdp().
+    - gtp: Destroy device along with udp socket's netns dismantle.
+    - nfp: bpf: prevent integer overflow in nfp_bpf_event_output()
+    - drm/v3d: Ensure job pointer is set to NULL after job completion
+    - i2c: mux: demux-pinctrl: check initial mux selection, too
+    - mac802154: check local interfaces before deleting sdata list
+    - hfs: Sanity check the root record
+    - kheaders: Ignore silly-rename files
+    - poll_wait: add mb() to fix theoretical race between waitqueue_active() and
+      .poll()
+    - nvmet: propagate npwg topology
+    - net: ethernet: xgbe: re-add aneg to supported features in PHY quirks
+    - fs/proc: fix softlockup in __read_vmcore (part 2)
+    - irqchip/gic-v3: Handle CPU_PM_ENTER_FAILED correctly
+    - hrtimers: Handle CPU state correctly on hotplug
+    - ipv6: avoid possible NULL deref in rt6_uncached_list_flush_dev()
+    - scsi: sg: Fix slab-use-after-free read in sg_release()
+    - net: fix data-races around sk->sk_forward_alloc
+    - ASoC: wm8994: Add depends on MFD core
+    - scsi: iscsi: Fix redundant response for ISCSI_UEVENT_GET_HOST_STATS request
+    - irqchip/sunxi-nmi: Add missing SKIP_WAKE flag
+    - gfs2: Truncate address space when flipping GFS2_DIF_JDATA flag
+    - m68k: Update ->thread.esp0 before calling syscall_trace() in ret_from_signal
+    - m68k: Add missing mmap_read_lock() to sys_cacheflush()
+    - signal/m68k: Use force_sigsegv(SIGSEGV) in fpsp040_die
+    - net: xen-netback: hash.c: Use built-in RCU list checking
+    - net/xen-netback: prevent UAF in xenvif_flush_hash()
+    - vfio/platform: check the bounds of read/write syscalls
+    - ext4: avoid ext4_error()'s caused by ENOMEM in the truncate path
+    - ext4: fix slab-use-after-free in ext4_split_extent_at()
+    - USB: serial: quatech2: fix null-ptr-deref in qt2_process_read_urb()
+    - Revert "usb: gadget: u_serial: Disable ep before setting port to null to fix
+      the crash caused by port being null"
+    - Input: atkbd - map F23 key to support default copilot shortcut
+    - Input: xpad - add unofficial Xbox 360 wireless receiver clone
+    - Input: xpad - add support for wooting two he (arm)
+    - drm/v3d: Assign job pointer to NULL before signaling the fence
+    - xhci: use pm_ptr() instead of #ifdef for CONFIG_PM conditionals
+    - Partial revert of xhci: use pm_ptr() instead #ifdef for CONFIG_PM
+      conditionals
+    - Linux 5.4.290
+  * CVE-2021-47219
+    - scsi: scsi_debug: Fix out-of-bound read in resp_report_tgtpgs()
+  * CVE-2024-49925
+    - fbdev: efifb: Register sysfs groups through driver core
+  * CVE-2024-56614
+    - xsk: fix OOB map writes when deleting elements
+  * net: stmmac: kernel continually prints wol unbalance irq warning
+    (LP: #2095376)
+    - net: stmmac: ethtool: Fixed calltrace caused by unbalanced disable_irq_wake
+      calls
+  * CVE-2024-44938
+    - jfs: Fix shift-out-of-bounds in dbDiscardAG
+  * CVE-2024-43900
+    - media: xc2028: avoid use-after-free in load_firmware_cb()
+  * Focal update: v5.4.289 upstream stable release (LP: #2095437)
+    - usb: dwc2: gadget: Don't write invalid mapped sg entries into dma_desc with
+      iommu enabled
+    - PCI/AER: Disable AER service on suspend
+    - ALSA: usb: Fix UBSAN warning in parse_audio_unit()
+    - PCI: Add ACS quirk for Broadcom BCM5760X NIC
+    - i2c: pnx: Fix timeout in wait functions
+    - drm/i915: Fix memory leak by correcting cache object name in error handler
+    - erofs: fix order >= MAX_ORDER warning due to crafted negative i_size
+    - erofs: fix incorrect symlink detection in fast symlink
+    - net/smc: check sndbuf_space again after NOSPACE flag is set in smc_poll
+    - ionic: use ee->offset when returning sprom data
+    - net: hinic: Fix cleanup in create_rxqs/txqs()
+    - net: ethernet: bgmac-platform: fix an OF node reference leak
+    - netfilter: ipset: Fix for recursive locking warning
+    - mmc: sdhci-tegra: Remove SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC quirk
+    - chelsio/chtls: prevent potential integer overflow on 32bit
+    - i2c: riic: Always round-up when calculating bus period
+    - efivarfs: Fix error on non-existent file
+    - USB: serial: option: add TCL IK512 MBIM & ECM
+    - USB: serial: option: add MeiG Smart SLM770A
+    - USB: serial: option: add Netprisma LCUK54 modules for WWAN Ready
+    - USB: serial: option: add MediaTek T7XX compositions
+    - USB: serial: option: add Telit FE910C04 rmnet compositions
+    - sh: clk: Fix clk_enable() to return 0 on NULL clk
+    - zram: refuse to use zero sized block device as backing device
+    - btrfs: tree-checker: reject inline extent items with 0 ref count
+    - NFS/pnfs: Fix a live lock between recalled layouts and layoutget
+    - of/irq: Fix using uninitialized variable @addr_len in API of_irq_parse_one()
+    - nilfs2: prevent use of deleted inode
+    - udmabuf: also check for F_SEAL_FUTURE_WRITE
+    - of: Fix error path in of_parse_phandle_with_args_map()
+    - of: Fix refcount leakage for OF node returned by __of_get_dma_parent()
+    - media: dvb-frontends: dib3000mb: fix uninit-value in dib3000_write_reg
+    - bpf: Check negative offsets in __bpf_skb_min_len()
+    - nfsd: restore callback functionality for NFSv4.0
+    - mtd: diskonchip: Cast an operand to prevent potential overflow
+    - phy: core: Fix an OF node refcount leakage in _of_phy_get()
+    - phy: core: Fix an OF node refcount leakage in of_phy_provider_lookup()
+    - phy: core: Fix that API devm_phy_put() fails to release the phy
+    - phy: core: Fix that API devm_phy_destroy() fails to destroy the phy
+    - dmaengine: mv_xor: fix child node refcount handling in early exit
+    - dmaengine: at_xdmac: avoid null_prt_deref in at_xdmac_prep_dma_memset
+    - mtd: rawnand: fix double free in atmel_pmecc_create_user()
+    - tracing/kprobe: Make trace_kprobe's module callback called after jump_label
+      update
+    - scsi: qla1280: Fix hw revision numbering for ISP1020/1040
+    - scsi: megaraid_sas: Fix for a potential deadlock
+    - regmap: Use correct format specifier for logging range errors
+    - platform/x86: asus-nb-wmi: Ignore unknown event 0xCF
+    - scsi: mpt3sas: Diag-Reset when Doorbell-In-Use bit is set during driver load
+      time
+    - virtio-blk: don't keep queue frozen during system suspend
+    - epoll: Add synchronous wakeup support for ep_poll_callback
+    - MIPS: Probe toolchain support of -msym32
+    - ipv6: use skb_expand_head in ip6_finish_output2
+    - ipv6: use skb_expand_head in ip6_xmit
+    - ipv6: fix possible UAF in ip6_finish_output2()
+    - bpf: fix recursive lock when verdict program return SK_PASS
+    - tracing: Constify string literal data member in struct trace_event_call
+    - btrfs: avoid monopolizing a core when activating a swap file
+    - ipv6: prevent possible UAF in ip6_xmit()
+    - selinux: ignore unknown extended permissions
+    - Drivers: hv: util: Avoid accessing a ringbuffer not initialized yet
+    - IB/mlx5: Introduce and use mlx5_core_is_vf()
+    - net/mlx5: Make API mlx5_core_is_ecpf accept const pointer
+    - RDMA/mlx5: Enforce same type port association for multiport RoCE
+    - RDMA/bnxt_re: Add check for path mtu in modify_qp
+    - RDMA/bnxt_re: Fix reporting hw_ver in query_device
+    - RDMA/bnxt_re: Fix max_qp_wrs reported
+    - drm: bridge: adv7511: Enable SPDIF DAI
+    - drm/bridge: adv7511_audio: Update Audio InfoFrame properly
+    - netrom: check buffer length before accessing it
+    - netfilter: Replace zero-length array with flexible-array member
+    - netfilter: nft_set_hash: unaligned atomic read on struct nft_set_ext
+    - net: llc: reset skb->transport_header
+    - ALSA: usb-audio: US16x08: Initialize array before use
+    - af_packet: fix vlan_get_tci() vs MSG_PEEK
+    - af_packet: fix vlan_get_protocol_dgram() vs MSG_PEEK
+    - ila: serialize calls to nf_register_net_hooks()
+    - wifi: mac80211: wake the queues in case of failure in resume
+    - sound: usb: format: don't warn that raw DSD is unsupported
+    - bpf: fix potential error return
+    - net: usb: qmi_wwan: add Telit FE910C04 compositions
+    - irqchip/gic: Correct declaration of *percpu_base pointer in union gic_base
+    - ARC: build: Try to guess GCC variant of cross compiler
+    - modpost: fix input MODULE_DEVICE_TABLE() built for 64-bit on 32-bit host
+    - modpost: fix the missed iteration for the max bit in do_input()
+    - RDMA/uverbs: Prevent integer overflow issue
+    - pinctrl: mcp23s08: Fix sleeping in atomic context due to regmap locking
+    - sky2: Add device ID 11ab:4373 for Marvell 88E8075
+    - net/sctp: Prevent autoclose integer overflow in sctp_association_init()
+    - drm: adv7511: Drop dsi single lane support
+    - mm: vmscan: account for free pages to prevent infinite Loop in
+      throttle_direct_reclaim()
+    - ftrace: use preempt_enable/disable notrace macros to avoid double fault
+    - Linux 5.4.289
+  * Focal update: v5.4.289 upstream stable release (LP: #2095437) //
+    CVE-2024-38588
+    - ftrace: Fix possible use-after-free issue in ftrace_location()
+  * Focal update: v5.4.288 upstream stable release (LP: #2095199)
+    - usb: host: max3421-hcd: Correctly abort a USB request.
+    - ata: sata_highbank: fix OF node reference leak in highbank_initialize_phys()
+    - usb: dwc2: hcd: Fix GetPortStatus & SetPortFeature
+    - usb: ehci-hcd: fix call balance of clocks handling routines
+    - usb: gadget: u_serial: Fix the issue that gs_start_io crashed due to
+      accessing null pointer
+    - xfs: don't drop errno values when we fail to ficlone the entire range
+    - bpf, sockmap: Fix update element with same
+    - batman-adv: Do not send uninitialized TT changes
+    - batman-adv: Remove uninitialized data in full table TT response
+    - batman-adv: Do not let TT changes list grows indefinitely
+    - tipc: fix NULL deref in cleanup_bearer()
+    - net: lapb: increase LAPB_HEADER_LEN
+    - ACPI: resource: Fix memory resource type union access
+    - qca_spi: Fix clock speed for multiple QCA7000
+    - qca_spi: Make driver probing reliable
+    - net/sched: netem: account for backlog updates from child qdisc
+    - ACPICA: events/evxfregn: don't release the ContextMutex that was never
+      acquired
+    - blk-iocost: clamp inuse and skip noops in __propagate_weights()
+    - blk-iocost: fix weight updates of inner active iocgs
+    - blk-iocost: Avoid using clamp() on inuse in __propagate_weights()
+    - KVM: arm64: Ignore PMCNTENSET_EL0 while checking for overflow status
+    - tracing/kprobes: Skip symbol counting logic for module symbols in
+      create_local_trace_kprobe()
+    - xen/netfront: fix crash when removing device
+    - ALSA: usb-audio: Fix a DMA to stack memory bug
+    - Linux 5.4.288
+  * Focal update: v5.4.287 upstream stable release (LP: #2095145)
+    - netlink: terminate outstanding dump on socket close
+    - net/mlx5: fs, lock FTE when checking if active
+    - net/mlx5e: kTLS, Fix incorrect page refcounting
+    - ocfs2: uncache inode which has failed entering the group
+    - KVM: VMX: Bury Intel PT virtualization (guest/host mode) behind
+      CONFIG_BROKEN
+    - nilfs2: fix null-ptr-deref in block_touch_buffer tracepoint
+    - ocfs2: fix UBSAN warning in ocfs2_verify_volume()
+    - nilfs2: fix null-ptr-deref in block_dirty_buffer tracepoint
+    - Revert "mmc: dw_mmc: Fix IDMAC operation with pages bigger than 4K"
+    - media: dvbdev: fix the logic when DVB_DYNAMIC_MINORS is not set
+    - kbuild: Use uname for LINUX_COMPILE_HOST detection
+    - mm: revert "mm: shmem: fix data-race in shmem_getattr()"
+    - ASoC: Intel: bytcr_rt5640: Add DMI quirk for Vexia Edu Atla 10 tablet
+    - mac80211: fix user-power when emulating chanctx
+    - selftests/watchdog-test: Fix system accidentally reset after watchdog-test
+    - ALSA: hda/realtek: Add subwoofer quirk for Infinix ZERO BOOK 13
+    - x86/amd_nb: Fix compile-testing without CONFIG_AMD_NB
+    - net: usb: qmi_wwan: add Quectel RG650V
+    - soc: qcom: Add check devm_kasprintf() returned value
+    - regulator: rk808: Add apply_bit for BUCK3 on RK809
+    - ASoC: stm: Prevent potential division by zero in stm32_sai_mclk_round_rate()
+    - ASoC: stm: Prevent potential division by zero in stm32_sai_get_clk_div()
+    - proc/softirqs: replace seq_printf with seq_put_decimal_ull_width
+    - ipmr: Fix access to mfc_cache_list without lock held
+    - cifs: Fix buffer overflow when parsing NFS reparse points
+    - NFSD: Force all NFSv4.2 COPY requests to be synchronous
+    - nvme: fix metadata handling in nvme-passthrough
+    - mips: asm: fix warning when disabling MIPS_FP_SUPPORT
+    - initramfs: avoid filename buffer overrun
+    - nvme-pci: fix freeing of the HMB descriptor table
+    - m68k: mvme147: Fix SCSI controller IRQ numbers
+    - m68k: mvme16x: Add and use "mvme16x.h"
+    - m68k: mvme147: Reinstate early console
+    - acpi/arm64: Adjust error handling procedure in gtdt_parse_timer_block()
+    - s390/syscalls: Avoid creation of arch/arch/ directory
+    - hfsplus: don't query the device logical block size multiple times
+    - firmware: google: Unregister driver_info on failure and exit in gsmi
+    - firmware: google: Unregister driver_info on failure
+    - EDAC/bluefield: Fix potential integer overflow
+    - EDAC/fsl_ddr: Fix bad bit shift operations
+    - crypto: pcrypt - Call crypto layer directly when padata_do_parallel() return
+      -EBUSY
+    - crypto: cavium - Fix the if condition to exit loop after timeout
+    - crypto: bcm - add error check in the ahash_hmac_init function
+    - crypto: cavium - Fix an error handling path in cpt_ucode_load_fw()
+    - time: Fix references to _msecs_to_jiffies() handling of values
+    - soc: ti: smartreflex: Use IRQF_NO_AUTOEN flag in request_irq()
+    - soc: qcom: geni-se: fix array underflow in geni_se_clk_tbl_get()
+    - mmc: mmc_spi: drop buggy snprintf()
+    - efi/tpm: Pass correct address to memblock_reserve
+    - tpm: fix signed/unsigned bug when checking event logs
+    - ARM: dts: cubieboard4: Fix DCDC5 regulator constraints
+    - regmap: irq: Set lockdep class for hierarchical IRQ domains
+    - firmware: arm_scpi: Check the DVFS OPP count returned by the firmware
+    - drm/mm: Mark drm_mm_interval_tree*() functions with __maybe_unused
+    - wifi: ath9k: add range check for conn_rsp_epid in htc_connect_service()
+    - drm/omap: Fix locking in omap_gem_new_dmabuf()
+    - wifi: p54: Use IRQF_NO_AUTOEN flag in request_irq()
+    - wifi: mwifiex: Use IRQF_NO_AUTOEN flag in request_irq()
+    - drm/imx/ipuv3: Use IRQF_NO_AUTOEN flag in request_irq()
+    - dt-bindings: vendor-prefixes: Add NeoFidelity, Inc
+    - ASoC: fsl_micfil: Drop unnecessary register read
+    - ASoC: fsl_micfil: do not define SHIFT/MASK for single bits
+    - ASoC: fsl_micfil: use GENMASK to define register bit fields
+    - ASoC: fsl_micfil: fix regmap_write_bits usage
+    - bpf: Fix the xdp_adjust_tail sample prog issue
+    - wifi: mwifiex: Fix memcpy() field-spanning write warning in
+      mwifiex_config_scan()
+    - drm/panfrost: Remove unused id_mask from struct panfrost_model
+    - drm/msm/adreno: Use IRQF_NO_AUTOEN flag in request_irq()
+    - drm/etnaviv: dump: fix sparse warnings
+    - drm/etnaviv: fix power register offset on GC300
+    - drm/etnaviv: hold GPU lock across perfmon sampling
+    - bpf, sockmap: Several fixes to bpf_msg_push_data
+    - bpf, sockmap: Several fixes to bpf_msg_pop_data
+    - bpf, sockmap: Fix sk_msg_reset_curr
+    - selftests: net: really check for bg process completion
+    - net: rfkill: gpio: Add check for clk_enable()
+    - ALSA: us122l: Use snd_card_free_when_closed() at disconnection
+    - ALSA: caiaq: Use snd_card_free_when_closed() at disconnection
+    - ALSA: 6fire: Release resources at card release
+    - netpoll: Use rcu_access_pointer() in netpoll_poll_lock
+    - trace/trace_event_perf: remove duplicate samples on the first tracepoint
+      event
+    - powerpc/vdso: Flag VDSO64 entry points as functions
+    - mfd: tps65010: Use IRQF_NO_AUTOEN flag in request_irq() to fix race
+    - mfd: da9052-spi: Change read-mask to write-mask
+    - mfd: intel_soc_pmic_bxtwc: Use dev_err_probe()
+    - mfd: intel_soc_pmic_bxtwc: Use IRQ domain for USB Type-C device
+    - mfd: intel_soc_pmic_bxtwc: Use IRQ domain for TMU device
+    - mfd: intel_soc_pmic_bxtwc: Use IRQ domain for PMIC devices
+    - cpufreq: loongson2: Unregister platform_driver on failure
+    - mtd: rawnand: atmel: Fix possible memory leak
+    - RDMA/bnxt_re: Check cqe flags to know imm_data vs inv_irkey
+    - mfd: rt5033: Fix missing regmap_del_irq_chip()
+    - scsi: bfa: Fix use-after-free in bfad_im_module_exit()
+    - scsi: fusion: Remove unused variable 'rc'
+    - scsi: qedf: Fix a possible memory leak in qedf_alloc_and_init_sb()
+    - scsi: qedi: Fix a possible memory leak in qedi_alloc_and_init_sb()
+    - ocfs2: fix uninitialized value in ocfs2_file_read_iter()
+    - powerpc/sstep: make emulate_vsx_load and emulate_vsx_store static
+    - fbdev/sh7760fb: Alloc DMA memory from hardware device
+    - fbdev: sh7760fb: Fix a possible memory leak in sh7760fb_alloc_mem()
+    - dt-bindings: clock: adi,axi-clkgen: convert old binding to yaml format
+    - dt-bindings: clock: axi-clkgen: include AXI clk
+    - clk: axi-clkgen: use devm_platform_ioremap_resource() short-hand
+    - clk: clk-axi-clkgen: make sure to enable the AXI bus clock
+    - perf cs-etm: Don't flush when packet_queue fills up
+    - perf probe: Correct demangled symbols in C++ program
+    - PCI: cpqphp: Use PCI_POSSIBLE_ERROR() to check config reads
+    - PCI: cpqphp: Fix PCIBIOS_* return value confusion
+    - m68k: mcfgpio: Fix incorrect register offset for CONFIG_M5441x
+    - m68k: coldfire/device.c: only build FEC when HW macros are defined
+    - perf trace: Do not lose last events in a race
+    - perf trace: Avoid garbage when not printing a syscall's arguments
+    - rpmsg: glink: Add TX_DATA_CONT command while sending
+    - rpmsg: glink: Send READ_NOTIFY command in FIFO full case
+    - rpmsg: glink: Fix GLINK command prefix
+    - rpmsg: glink: use only lower 16-bits of param2 for CMD_OPEN name length
+    - NFSD: Prevent NULL dereference in nfsd4_process_cb_update()
+    - NFSD: Cap the number of bytes copied by nfs4_reset_recoverydir()
+    - NFSD: Fix nfsd4_shutdown_copy()
+    - vfio/pci: Properly hide first-in-list PCIe extended capability
+    - power: supply: core: Remove might_sleep() from power_supply_put()
+    - net: usb: lan78xx: Fix memory leak on device unplug by freeing PHY device
+    - tg3: Set coherent DMA mask bits to 31 for BCM57766 chipsets
+    - net: usb: lan78xx: Fix refcounting and autosuspend on invalid WoL
+      configuration
+    - marvell: pxa168_eth: fix call balance of pep->clk handling routines
+    - net: stmmac: dwmac-socfpga: Set RX watchdog interrupt as broken
+    - ipmr: convert /proc handlers to rcu_read_lock()
+    - ipmr: fix tables suspicious RCU usage
+    - usb: using mutex lock and supporting O_NONBLOCK flag in iowarrior_read()
+    - usb: yurex: make waiting on yurex_write interruptible
+    - USB: chaoskey: fail open after removal
+    - USB: chaoskey: Fix possible deadlock chaoskey_list_lock
+    - misc: apds990x: Fix missing pm_runtime_disable()
+    - staging: greybus: uart: clean up TIOCGSERIAL
+    - apparmor: fix 'Do simple duplicate message elimination'
+    - usb: ehci-spear: fix call balance of sehci clk handling routines
+    - cgroup: Make operations on the cgroup root_list RCU safe
+    - cgroup: Move rcu_head up near the top of cgroup_root
+    - soc: qcom: socinfo: fix revision check in qcom_socinfo_probe()
+    - ALSA: usb-audio: Fix potential out-of-bound accesses for Extigy and Mbox
+      devices
+    - ext4: supress data-race warnings in ext4_free_inodes_{count,set}()
+    - ext4: fix FS_IOC_GETFSMAP handling
+    - jfs: xattr: check invalid xattr size more strictly
+    - ASoC: codecs: Fix atomicity violation in snd_soc_component_get_drvdata()
+    - PCI: Fix use-after-free of slot->bus on hot remove
+    - comedi: Flush partial mappings in error case
+    - tty: ldsic: fix tty_ldisc_autoload sysctl's proc_handler
+    - Bluetooth: Fix type of len in rfcomm_sock_getsockopt{,_old}()
+    - Revert "usb: gadget: composite: fix OS descriptors w_value logic"
+    - serial: sh-sci: Clean sci_ports[0] after at earlycon exit
+    - Revert "serial: sh-sci: Clean sci_ports[0] after at earlycon exit"
+    - spi: Fix acpi deferred irq probe
+    - ubi: wl: Put source PEB into correct list if trying locking LEB failed
+    - um: ubd: Do not use drvdata in release
+    - um: net: Do not use drvdata in release
+    - serial: 8250: omap: Move pm_runtime_get_sync
+    - um: vector: Do not use drvdata in release
+    - sh: cpuinfo: Fix a warning for CONFIG_CPUMASK_OFFSTACK
+    - arm64: tls: Fix context-switching of tpidrro_el0 when kpti is enabled
+    - block: fix ordering between checking BLK_MQ_S_STOPPED request adding
+    - HID: wacom: Interpret tilt data from Intuos Pro BT as signed values
+    - media: wl128x: Fix atomicity violation in fmc_send_cmd()
+    - ALSA: hda/realtek: Update ALC225 depop procedure
+    - ALSA: hda/realtek: Set PCBeep to default value for ALC274
+    - ALSA: hda/realtek: Fix Internal Speaker and Mic boost of Infinix Y4 Max
+    - ALSA: hda/realtek: Apply quirk for Medion E15433
+    - usb: dwc3: gadget: Fix checking for number of TRBs left
+    - lib: string_helpers: silence snprintf() output truncation warning
+    - NFSD: Prevent a potential integer overflow
+    - SUNRPC: make sure cache entry active before cache_show
+    - rpmsg: glink: Propagate TX failures in intentless mode as well
+    - um: Fix potential integer overflow during physmem setup
+    - um: Fix the return value of elf_core_copy_task_fpregs
+    - um/sysrq: remove needless variable sp
+    - um: add show_stack_loglvl()
+    - um: Clean up stacktrace dump
+    - um: Always dump trace for specified task in show_stack
+    - NFSv4.0: Fix a use-after-free problem in the asynchronous open()
+    - rtc: st-lpc: Use IRQF_NO_AUTOEN flag in request_irq()
+    - rtc: abx80x: Fix WDT bit position of the status register
+    - rtc: check if __rtc_read_time was successful in rtc_timer_do_work()
+    - ubifs: Correct the total block count by deducting journal reservation
+    - ubi: fastmap: Fix duplicate slab cache names while attaching
+    - ubifs: authentication: Fix use-after-free in ubifs_tnc_end_commit
+    - jffs2: fix use of uninitialized variable
+    - block: return unsigned int from bdev_io_min
+    - 9p/xen: fix init sequence
+    - 9p/xen: fix release of IRQ
+    - rtc: ab-eoz9: don't fail temperature reads on undervoltage notification
+    - modpost: remove incorrect code in do_eisa_entry()
+    - SUNRPC: correct error code comment in xs_tcp_setup_socket()
+    - SUNRPC: Replace internal use of SOCKWQ_ASYNC_NOSPACE
+    - sunrpc: clear XPRT_SOCK_UPD_TIMEOUT when reset transport
+    - sh: intc: Fix use-after-free bug in register_intc_controller()
+    - ASoC: fsl_micfil: fix the naming style for mask definition
+    - quota: flush quota_release_work upon quota writeback
+    - btrfs: ref-verify: fix use-after-free after invalid ref action
+    - media: i2c: tc358743: Fix crash in the probe error path when using polling
+    - media: ts2020: fix null-ptr-deref in ts2020_probe()
+    - media: venus: Fix pm_runtime_set_suspended() with runtime pm enabled
+    - media: gspca: ov534-ov772x: Fix off-by-one error in set_frame_rate()
+    - media: platform: allegro-dvt: Fix possible memory leak in
+      allocate_buffers_internal()
+    - ovl: Filter invalid inodes with missing lookup function
+    - ftrace: Fix regression with module command in stack_trace_filter
+    - clk: qcom: gcc-qcs404: fix initial rate of GPLL3
+    - ad7780: fix division by zero in ad7780_write_raw()
+    - util_macros.h: fix/rework find_closest() macros
+    - i3c: master: Fix miss free init_dyn_addr at i3c_master_put_i3c_addrs()
+    - dm thin: Add missing destroy_work_on_stack()
+    - nfsd: make sure exp active before svc_export_show
+    - nfsd: fix nfs4_openowner leak when concurrent nfsd4_open occur
+    - drm/etnaviv: flush shader L1 cache after user commandstream
+    - iTCO_wdt: mask NMI_NOW bit for update_no_reboot_bit() call
+    - watchdog: mediatek: Make sure system reset gets asserted in
+      mtk_wdt_restart()
+    - can: sun4i_can: sun4i_can_err(): call can_change_state() even if cf is NULL
+    - can: sun4i_can: sun4i_can_err(): fix {rx,tx}_errors statistics
+    - ipvs: fix UB due to uninitialized stack access in ip_vs_protocol_init()
+    - netfilter: x_tables: fix LED ID check in led_tg_check()
+    - net/sched: tbf: correct backlog statistic for GSO packets
+    - can: j1939: j1939_session_new(): fix skb reference counting
+    - net/ipv6: release expired exception dst cached in socket
+    - dccp: Fix memory leak in dccp_feat_change_recv
+    - tipc: add reference counter to bearer
+    - tipc: enable creating a "preliminary" node
+    - tipc: add new AEAD key structure for user API
+    - tipc: Fix use-after-free of kernel socket in cleanup_bearer().
+    - net/qed: allow old cards not supporting "num_images" to work
+    - igb: Fix potential invalid memory access in igb_init_module()
+    - netfilter: ipset: Hold module reference while requesting a module
+    - netfilter: nft_set_hash: skip duplicated elements pending gc run
+    - xen/xenbus: reference count registered modules
+    - xenbus/backend: Add memory pressure handler callback
+    - xenbus/backend: Protect xenbus callback with lock
+    - xen/xenbus: fix locking
+    - xen: Fix the issue of resource not being properly released in
+      xenbus_dev_probe()
+    - x86/asm: Reorder early variables
+    - crypto: x86/aegis128 - access 32-bit arguments as 32-bit
+    - gpio: grgpio: use a helper variable to store the address of ofdev->dev
+    - gpio: grgpio: Add NULL check in grgpio_probe
+    - drm/sti: Add __iomem for mixer_dbg_mxn's parameter
+    - tcp_bpf: Fix the sk_mem_uncharge logic in tcp_bpf_sendmsg
+    - spi: mpc52xx: Add cancel_work_sync before module remove
+    - ocfs2: free inode when ocfs2_get_init_inode() fails
+    - bpf: Handle BPF_EXIST and BPF_NOEXIST for LPM trie
+    - bpf: Fix exact match conditions in trie_get_next_key()
+    - HID: wacom: fix when get product name maybe null pointer
+    - tracing: Fix cmp_entries_dup() to respect sort() comparison rules
+    - ocfs2: update seq_file index in ocfs2_dlm_seq_next
+    - scsi: qla2xxx: Fix NVMe and NPIV connect issue
+    - scsi: qla2xxx: Supported speed displayed incorrectly for VPorts
+    - scsi: qla2xxx: Remove check req_sg_cnt should be equal to rsp_sg_cnt
+    - nilfs2: fix potential out-of-bounds memory access in nilfs_find_entry()
+    - bcache: revert replacing IS_ERR_OR_NULL with IS_ERR again
+    - dma-buf: fix dma_fence_array_signaled v4
+    - regmap: detach regmap from dev on regmap_exit
+    - mmc: core: Further prevent card detect during shutdown
+    - s390/cpum_sf: Handle CPU hotplug remove during sampling
+    - media: uvcvideo: Add a quirk for the Kaiweets KTI-W02 infrared camera
+    - media: cx231xx: Add support for Dexatek USB Video Grabber 1d19:6108
+    - drm: panel-orientation-quirks: Add quirk for AYA NEO 2 model
+    - drm/mcde: Enable module autoloading
+    - drm/radeon/r600_cs: Fix possible int overflow in r600_packet3_check()
+    - samples/bpf: Fix a resource leak
+    - net: fec_mpc52xx_phy: Use %pa to format resource_size_t
+    - net: ethernet: fs_enet: Use %pa to format resource_size_t
+    - net/sched: cbs: Fix integer overflow in cbs_set_port_rate()
+    - af_packet: avoid erroring out after sock_init_data() in packet_create()
+    - Bluetooth: L2CAP: do not leave dangling sk pointer on error in
+      l2cap_sock_create()
+    - net: af_can: do not leave a dangling sk pointer in can_create()
+    - net: ieee802154: do not leave a dangling sk pointer in ieee802154_create()
+    - net: inet: do not leave a dangling sk pointer in inet_create()
+    - net: inet6: do not leave a dangling sk pointer in inet6_create()
+    - wifi: ath5k: add PCI ID for SX76X
+    - wifi: ath5k: add PCI ID for Arcadyan devices
+    - jfs: array-index-out-of-bounds fix in dtReadFirst
+    - jfs: fix shift-out-of-bounds in dbSplit
+    - jfs: fix array-index-out-of-bounds in jfs_readdir
+    - jfs: add a check to prevent array-index-out-of-bounds in dbAdjTree
+    - drm/amdgpu: set the right AMDGPU sg segment limitation
+    - wifi: ipw2x00: libipw_rx_any(): fix bad alignment
+    - wifi: brcmfmac: Fix oops due to NULL pointer dereference in
+      brcmf_sdiod_sglist_rw()
+    - Bluetooth: btusb: Add RTL8852BE device 0489:e123 to device tables
+    - ASoC: hdmi-codec: reorder channel allocation list
+    - rocker: fix link status detection in rocker_carrier_init()
+    - net/neighbor: clear error in case strict check is not set
+    - netpoll: Use rcu_access_pointer() in __netpoll_setup
+    - tracing: Use atomic64_inc_return() in trace_clock_counter()
+    - leds: class: Protect brightness_show() with led_cdev->led_access mutex
+    - scsi: st: Don't modify unknown block number in MTIOCGET
+    - scsi: st: Add MTIOCGET and MTLOAD to ioctls allowed after device reset
+    - pinctrl: qcom-pmic-gpio: add support for PM8937
+    - nvdimm: rectify the illogical code within nd_dax_probe()
+    - f2fs: fix f2fs_bug_on when uninstalling filesystem call f2fs_evict_inode.
+    - PCI: Add 'reset_subordinate' to reset hierarchy below bridge
+    - PCI: Add ACS quirk for Wangxun FF5xxx NICs
+    - i3c: Use i3cdev->desc->info instead of calling i3c_device_get_info() to
+      avoid deadlock
+    - usb: chipidea: udc: handle USB Error Interrupt if IOC not set
+    - powerpc/prom_init: Fixup missing powermac #size-cells
+    - misc: eeprom: eeprom_93cx6: Add quirk for extra read clock cycle
+    - xdp: Simplify devmap cleanup
+    - bpf: fix OOB devmap writes when deleting elements
+    - Revert "unicode: Don't special case ignorable code points"
+    - perf/x86/intel/pt: Fix buffer full but size is 0 case
+    - KVM: arm64: vgic-its: Add a data length check in vgic_its_save_*
+    - KVM: arm64: vgic-its: Clear DTE when MAPD unmaps a device
+    - KVM: arm64: vgic-its: Clear ITE when DISCARD frees an ITE
+    - jffs2: Prevent rtime decompress memory corruption
+    - jffs2: Fix rtime decompressor
+    - ocfs2: Revert "ocfs2: fix the la space leak when unmounting an ocfs2 volume"
+    - modpost: Add .irqentry.text to OTHER_SECTIONS
+    - Revert "drm/amdgpu: add missing size check in amdgpu_debugfs_gprwave_read()"
+    - PCI: rockchip-ep: Fix address translation unit programming
+    - ALSA: usb-audio: Fix out of bounds reads when finding clock sources
+    - bpf, xdp: Update devmap comments to reflect napi/rcu usage
+    - Linux 5.4.287
+  * CVE-2024-23848
+    - media: cec: abort if the current transmit was canceled
+    - media: cec: core: avoid recursive cec_claim_log_addrs
+    - media: cec: core: avoid confusing "transmit timed out" message
+
+  [ Ubuntu: 5.4.0-208.228 ]
+
+  * CVE-2025-0927
+    - SAUCE: fs: hfs/hfsplus: add key_len boundary check to hfs_bnode_read_key
+
+ -- Koichiro Den <koichiro.den@canonical.com>  Thu, 20 Feb 2025 12:02:39 +0900
+
+linux-xilinx-zynqmp (5.4.0-1058.62) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1058.62 -proposed tracker (LP: #2093783)
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233)
+    - [Config] xilinx-zynqmp: updateconfigs for SND_MESON_CARD_UTILS
+
+  [ Ubuntu: 5.4.0-207.227 ]
+
+  * focal/linux: 5.4.0-207.227 -proposed tracker (LP: #2095347)
+  * Remove "ftrace: Fix possible use-after-free issue in ftrace_location()" bad
+    commit from focal (LP: #2095348)
+    - Revert "ftrace: Fix possible use-after-free issue in ftrace_location()"
+
+  [ Ubuntu: 5.4.0-206.226 ]
+
+  * focal/linux: 5.4.0-206.226 -proposed tracker (LP: #2093785)
+  * nouveau keeps showing `disp: ctrl 00000080` and crippling the system
+    (LP: #2078011)
+    - drm/nouveau/disp/gv100-: halt NV_PDISP_FE_RM_INTR_STAT_CTRL_DISP_ERROR
+      storms
+    - drm/nouveau/kms/gv100-: move window ownership setup into modesetting path
+    - drm/nouveau/kms/gv100-: avoid sending a core update until the first modeset
+  * CVE-2024-43863
+    - drm/vmwgfx: Fix a deadlock in dma buf fence polling
+  * CVE-2024-40911
+    - wifi: cfg80211: Lock wiphy in cfg80211_get_station
+  * CVE-2024-35896
+    - netfilter: validate user input for expected length
+    - netfilter: complete validation of user input
+  * CVE-2023-52458
+    - block: add check that partition length needs to be aligned with block size
+  * kernel:nft "Could not process rule: Device or resource busy" on unreferenced
+    chain (LP: #2089699)
+    - SAUCE: netfilter: nf_tables: Fix EBUSY on deleting unreferenced chain
+  * CVE-2024-35887
+    - lockdep: Add preemption enabled/disabled assertion APIs
+    - timers: Don't block on ->expiry_lock for TIMER_IRQSAFE timers
+    - Documentation: Remove bogus claim about del_timer_sync()
+    - ARM: spear: Do not use timer namespace for timer_shutdown() function
+    - clocksource/drivers/arm_arch_timer: Do not use timer namespace for
+      timer_shutdown() function
+    - clocksource/drivers/sp804: Do not use timer namespace for timer_shutdown()
+      function
+    - timers: Get rid of del_singleshot_timer_sync()
+    - timers: Replace BUG_ON()s
+    - timers: Rename del_timer() to timer_delete()
+    - Documentation: Replace del_timer/del_timer_sync()
+    - timers: Silently ignore timers with a NULL function
+    - timers: Split [try_to_]del_timer[_sync]() to prepare for shutdown mode
+    - timers: Add shutdown mechanism to the internal functions
+    - timers: Provide timer_shutdown[_sync]()
+    - timers: Update the documentation to reflect on the new timer_shutdown() API
+    - ax25: fix use-after-free bugs caused by ax25_ds_del_timer
+  * CVE-2024-40965
+    - clk: Add a devm variant of clk_rate_exclusive_get()
+    - clk: Provide !COMMON_CLK dummy for devm_clk_rate_exclusive_get()
+    - i2c: lpi2c: Avoid calling clk_get_rate during transfer
+  * CVE-2024-40982
+    - ssb: Fix potential NULL pointer dereference in ssb_device_uevent()
+  * CVE-2024-41066
+    - ibmvnic: Add tx check to prevent skb leak
+  * CVE-2024-42252
+    - closures: Change BUG_ON() to WARN_ON()
+  * CVE-2024-46731
+    - drm/amd/pm: fix the Out-of-bounds read warning
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558)
+    - arm64: dts: rockchip: Fix rt5651 compatible value on rk3399-sapphire-
+      excavator
+    - arm64: dts: rockchip: Remove hdmi's 2nd interrupt on rk3328
+    - arm64: dts: rockchip: Fix bluetooth properties on Rock960 boards
+    - arm64: dts: rockchip: Remove #cooling-cells from fan on Theobroma lion
+    - ARM: dts: rockchip: fix rk3036 acodec node
+    - ARM: dts: rockchip: drop grf reference from rk3036 hdmi
+    - ARM: dts: rockchip: Fix the spi controller on rk3036
+    - ARM: dts: rockchip: Fix the realtek audio codec on rk3036-kylin
+    - enetc: simplify the return expression of enetc_vf_set_mac_addr()
+    - net: enetc: set MAC address to the VF net_device
+    - can: c_can: fix {rx,tx}_errors statistics
+    - media: stb0899_algo: initialize cfr before using it
+    - media: dvb_frontend: don't play tricks with underflow values
+    - media: adv7604: prevent underflow condition when reporting colorspace
+    - ALSA: firewire-lib: fix return value on fail in amdtp_tscm_init()
+    - pwm: imx-tpm: Use correct MODULO value for EPWM mode
+    - drm/amdgpu: prevent NULL pointer dereference if ATIF is not supported
+    - dm cache: correct the number of origin blocks to match the target length
+    - dm cache: optimize dirty bit checking with find_next_bit when resizing
+    - dm-unstriped: cast an operand to sector_t to prevent potential uint32_t
+      overflow
+    - mtd: rawnand: protect access to rawnand devices while in suspend
+    - spi: fix use-after-free of the add_lock mutex
+    - media: uvcvideo: Skip parsing frames of type UVC_VS_UNDEFINED in
+      uvc_parse_format
+    - fs/proc: fix compile warning about variable 'vmcore_mmap_ops'
+    - USB: serial: qcserial: add support for Sierra Wireless EM86xx
+    - USB: serial: option: add Fibocom FG132 0x0112 composition
+    - USB: serial: option: add Quectel RG650V
+    - irqchip/gic-v3: Force propagation of the active state with a read-back
+    - ALSA: usb-audio: Support jack detection on Dell dock
+    - ALSA: usb-audio: Add quirks for Dell WD19 dock
+    - NFSD: Fix NFSv4's PUTPUBFH operation
+    - ALSA: usb-audio: Add endianness annotations
+    - 9p: Avoid creating multiple slab caches with the same name
+    - HID: multitouch: Add quirk for HONOR MagicBook Art 14 touchpad
+    - bpf: use kvzmalloc to allocate BPF verifier environment
+    - sound: Make CONFIG_SND depend on INDIRECT_IOMEM instead of UML
+    - powerpc/powernv: Free name on error in opal_event_init()
+    - fs: Fix uninitialized value issue in from_kuid and from_kgid
+    - net: usb: qmi_wwan: add Fibocom FG132 0x0112 composition
+    - md/raid10: improve code of mrdev in raid10_sync_request
+    - mm: clarify a confusing comment for remap_pfn_range()
+    - mm: fix ambiguous comments for better code readability
+    - mm/memory.c: make remap_pfn_range() reject unaligned addr
+    - mm: add remap_pfn_range_notrack
+    - 9p: fix slab cache name creation for real
+    - Linux 5.4.286
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-47674
+    - mm: avoid leaving partial pfn mappings around in error case
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-38588
+    - ftrace: Fix possible use-after-free issue in ftrace_location()
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50265
+    - ocfs2: remove entry once instead of null-ptr-dereference in
+      ocfs2_xa_remove()
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50267
+    - USB: serial: io_edgeport: fix use after free in debug printk
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50269
+    - usb: musb: sunxi: Fix accessing an released usb phy
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2021-47469
+    - spi: Fix deadlock when adding SPI controllers on SPI buses
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50273
+    - btrfs: reinitialize delayed ref list after deleting it from the list
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-53066
+    - nfs: Fix KMSAN warning in decode_getfattr_attrs()
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50278
+    - dm cache: fix potential out-of-bounds access on the first resume
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50279
+    - dm cache: fix out-of-bounds access to the dirty bitset when resizing
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50282
+    - drm/amdgpu: add missing size check in amdgpu_debugfs_gprwave_read()
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50287
+    - media: v4l2-tpg: prevent the risk of a division by zero
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50290
+    - media: cx24116: prevent overflows on SNR calculus
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-53061
+    - media: s5p-jpeg: prevent buffer overflows
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-53063
+    - media: dvbdev: prevent the risk of out of memory access
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50296
+    - net: hns3: fix kernel crash when uninstalling driver
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50299
+    - sctp: properly validate chunk size in sctp_sf_ootb()
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50301
+    - security/keys: fix slab-out-of-bounds in key_task_permission
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50302
+    - HID: core: zero-initialize the report buffer
+  * Add list of source files to linux-buildinfo (LP: #2086606)
+    - [Packaging] Sort build dependencies alphabetically
+    - [Packaging] Add list of used source files to buildinfo package
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233)
+    - usbnet: ipheth: fix carrier detection in modes 1 and 4
+    - net: ethernet: use ip_hdrlen() instead of bit shift
+    - net: phy: vitesse: repair vsc73xx autonegotiation
+    - scripts: kconfig: merge_config: config files: add a trailing newline
+    - arm64: dts: rockchip: override BIOS_DISABLE signal via GPIO hog on RK3399
+      Puma
+    - ice: fix accounting for filters shared by multiple VSIs
+    - net/mlx5e: Add missing link modes to ptys2ethtool_map
+    - net: ftgmac100: Enable TX interrupt to avoid TX timeout
+    - soundwire: stream: Revert "soundwire: stream: fix programming slave ports
+      for non-continous port maps"
+    - selftests: breakpoints: Fix a typo of function name
+    - ASoC: allow module autoloading for table db1200_pids
+    - ALSA: hda/realtek - Fixed ALC256 headphone no sound
+    - ALSA: hda/realtek - FIxed ALC285 headphone no sound
+    - pinctrl: at91: make it work with current gpiolib
+    - microblaze: don't treat zero reserved memory regions as error
+    - net: ftgmac100: Ensure tx descriptor updates are visible
+    - wifi: iwlwifi: mvm: fix iwl_mvm_max_scan_ie_fw_cmd_room()
+    - ASoC: tda7419: fix module autoloading
+    - drm: komeda: Fix an issue related to normalized zpos
+    - spi: bcm63xx: Enable module autoloading
+    - x86/hyperv: Set X86_FEATURE_TSC_KNOWN_FREQ when Hyper-V provides frequency
+    - USB: serial: pl2303: add device id for Macrosilicon MS3020
+    - ACPI: PMIC: Remove unneeded check in tps68470_pmic_opregion_probe()
+    - wifi: ath9k: fix parameter check in ath9k_init_debug()
+    - wifi: ath9k: Remove error checks when creating debugfs entries
+    - fs: explicitly unregister per-superblock BDIs
+    - mount: warn only once about timestamp range expiration
+    - fs/namespace: fnic: Switch to use %ptTd
+    - mount: handle OOM on mnt_warn_timestamp_expiry
+    - can: j1939: use correct function name in comment
+    - netfilter: nf_tables: elements with timeout below CONFIG_HZ never expire
+    - netfilter: nf_tables: reject element expiration with no timeout
+    - netfilter: nf_tables: reject expiration higher than timeout
+    - wifi: cfg80211: fix UBSAN noise in cfg80211_wext_siwscan()
+    - wifi: cfg80211: fix two more possible UBSAN-detected off-by-one errors
+    - mac80211: parse radiotap header when selecting Tx queue
+    - Bluetooth: btusb: Fix not handling ZPL/short-transfer
+    - net: tipc: avoid possible garbage value
+    - block, bfq: choose the last bfqq from merge chain in bfq_setup_cooperator()
+    - block, bfq: don't break merge chain in bfq_split_bfqq()
+    - spi: ppc4xx: handle irq_of_parse_and_map() errors
+    - spi: ppc4xx: Avoid returning 0 when failed to parse and map IRQ
+    - ARM: dts: imx7d-zii-rmu2: fix Ethernet PHY pinctrl property
+    - ARM: versatile: fix OF node leak in CPUs prepare
+    - reset: berlin: fix OF node leak in probe() error path
+    - clocksource/drivers/qcom: Add missing iounmap() on errors in
+      msm_dt_timer_init()
+    - hwmon: (max16065) Fix overflows seen when writing limits
+    - mtd: slram: insert break after errors in parsing the map
+    - hwmon: (ntc_thermistor) fix module autoloading
+    - power: supply: axp20x_battery: allow disabling battery charging
+    - power: supply: axp20x_battery: Remove design from min and max voltage
+    - power: supply: max17042_battery: Fix SOC threshold calc w/ no current sense
+    - fbdev: hpfb: Fix an error handling path in hpfb_dio_probe()
+    - mtd: powernv: Add check devm_kasprintf() returned value
+    - drm/stm: Fix an error handling path in stm_drm_platform_probe()
+    - drm/amdgpu: Replace one-element array with flexible-array member
+    - drm/amdgpu: properly handle vbios fake edid sizing
+    - drm/radeon: Replace one-element array with flexible-array member
+    - drm/radeon: properly handle vbios fake edid sizing
+    - drm/rockchip: vop: Allow 4096px width scaling
+    - drm/rockchip: dw_hdmi: Fix reading EDID when using a forced mode
+    - drm/radeon/evergreen_cs: fix int overflow errors in cs track offsets
+    - drm/msm: Fix incorrect file name output in adreno_request_fw()
+    - drm/msm/a5xx: disable preemption in submits by default
+    - drm/msm/a5xx: properly clear preemption records on resume
+    - drm/msm/a5xx: fix races in preemption evaluation stage
+    - ipmi: docs: don't advertise deprecated sysfs entries
+    - drm/msm: fix %s null argument error
+    - drivers:drm:exynos_drm_gsc:Fix wrong assignment in gsc_bind()
+    - xen: use correct end address of kernel for conflict checking
+    - xen/swiotlb: add alignment check for dma buffers
+    - selftests/bpf: Fix compile error from rlim_t in sk_storage_map.c
+    - selftests/bpf: Fix compiling flow_dissector.c with musl-libc
+    - selftests/bpf: Fix compiling tcp_rtt.c with musl-libc
+    - selftests/bpf: Fix error compiling test_lru_map.c
+    - xz: cleanup CRC32 edits from 2018
+    - kthread: add kthread_work tracepoints
+    - kthread: fix task state in kthread worker if being frozen
+    - ext4: clear EXT4_GROUP_INFO_WAS_TRIMMED_BIT even mount with discard
+    - smackfs: Use rcu_assign_pointer() to ensure safe assignment in smk_set_cipso
+    - ext4: avoid negative min_clusters in find_group_orlov()
+    - ext4: return error on ext4_find_inline_entry
+    - nilfs2: determine empty node blocks as corrupted
+    - bpf: Fix bpf_strtol and bpf_strtoul helpers for 32bit
+    - perf sched timehist: Fix missing free of session in perf_sched__timehist()
+    - perf sched timehist: Fixed timestamp error when unable to confirm event
+      sched_in time
+    - perf time-utils: Fix 32-bit nsec parsing
+    - clk: rockchip: Set parent rate for DCLK_VOP clock on RK3228
+    - PCI: xilinx-nwl: Fix register misspelling
+    - pinctrl: single: fix missing error code in pcs_probe()
+    - clk: ti: dra7-atl: Fix leak of of_nodes
+    - pinctrl: mvebu: Fix devinit_dove_pinctrl_probe function
+    - watchdog: imx_sc_wdt: Don't disable WDT in suspend
+    - RDMA/hns: Optimize hem allocation performance
+    - riscv: Fix fp alignment bug in perf_callchain_user()
+    - f2fs: enhance to update i_mode and acl atomically in f2fs_setattr()
+    - f2fs: fix typo
+    - f2fs: fix to update i_ctime in __f2fs_setxattr()
+    - f2fs: remove unneeded check condition in __f2fs_setxattr()
+    - f2fs: reduce expensive checkpoint trigger frequency
+    - iio: adc: ad7606: fix oversampling gpio array
+    - iio: adc: ad7606: fix standby gpio state to match the documentation
+    - coresight: tmc: sg: Do not leak sg_table
+    - net: qrtr: Update packets cloning when broadcasting
+    - netfilter: ctnetlink: compile ctnetlink_label_size with
+      CONFIG_NF_CONNTRACK_EVENTS
+    - Remove *.orig pattern from .gitignore
+    - soc: versatile: integrator: fix OF node leak in probe() error path
+    - drm/amd/display: Round calculated vtotal
+    - USB: appledisplay: close race between probe and completion handler
+    - USB: misc: cypress_cy7c63: check for short transfer
+    - USB: class: CDC-ACM: fix race between get_serial and set_serial
+    - tty: rp2: Fix reset with non forgiving PCIe host bridges
+    - drbd: Fix atomicity violation in drbd_uuid_set_bm()
+    - drbd: Add NULL check for net_conf to prevent dereference in state validation
+    - ACPI: resource: Add another DMI match for the TongFang GMxXGxx
+    - wifi: rtw88: 8822c: Fix reported RX band width
+    - debugobjects: Fix conditions in fill_pool()
+    - f2fs: prevent possible int overflow in dir_block_index()
+    - f2fs: avoid potential int overflow in sanity_check_area_boundary()
+    - hwrng: mtk - Use devm_pm_runtime_enable
+    - fs: Fix file_set_fowner LSM hook inconsistencies
+    - nfs: fix memory leak in error path of nfs4_do_reclaim
+    - ASoC: meson: axg: extract sound card utils
+    - [Config] updateconfigs for SND_MESON_CARD_UTILS
+    - PCI: xilinx-nwl: Use irq_data_get_irq_chip_data()
+    - PCI: xilinx-nwl: Fix off-by-one in INTx IRQ handler
+    - soc: versatile: realview: fix memory leak during device remove
+    - soc: versatile: realview: fix soc_dev leak during device remove
+    - usb: yurex: Replace snprintf() with the safer scnprintf() variant
+    - USB: misc: yurex: fix race between read and write
+    - pps: remove usage of the deprecated ida_simple_xx() API
+    - pps: add an error check in parport_attach
+    - mm: only enforce minimum stack gap size if it's sensible
+    - i2c: aspeed: Update the stop sw state when the bus recovery occurs
+    - i2c: isch: Add missed 'else'
+    - usb: yurex: Fix inconsistent locking bug in yurex_read()
+    - mailbox: rockchip: fix a typo in module autoloading
+    - Minor fixes to the CAIF Transport drivers Kconfig file
+    - drivers: net: Fix Kconfig indentation, continued
+    - ieee802154: Fix build error
+    - net/mlx5: Added cond_resched() to crdump collection
+    - netfilter: uapi: NFTA_FLOWTABLE_HOOK is NLA_NESTED
+    - net: ieee802154: mcr20a: Use IRQF_NO_AUTOEN flag in request_irq()
+    - Bluetooth: btmrvl_sdio: Refactor irq wakeup
+    - Bluetooth: btmrvl: Use IRQF_NO_AUTOEN flag in request_irq()
+    - ipv4: ip_gre: Fix drops of small packets in ipgre_xmit
+    - ALSA: hda/realtek: Fix the push button function for the ALC257
+    - ALSA: hda/generic: Unconditionally prefer preferred_dacs pairs
+    - ALSA: hda/conexant: Fix conflicting quirk for System76 Pangolin
+    - wifi: ath9k: fix possible integer overflow in ath9k_get_et_stats()
+    - ice: Adjust over allocation of memory in ice_sched_add_root_node() and
+      ice_sched_add_node()
+    - net: hisilicon: hip04: fix OF node leak in probe()
+    - net: hisilicon: hns_dsaf_mac: fix OF node leak in hns_mac_get_info()
+    - net: hisilicon: hns_mdio: fix OF node leak in probe()
+    - ACPICA: Fix memory leak if acpi_ps_get_next_namepath() fails
+    - ACPICA: Fix memory leak if acpi_ps_get_next_field() fails
+    - net: sched: consistently use rcu_replace_pointer() in taprio_change()
+    - wifi: rtw88: select WANT_DEV_COREDUMP
+    - ACPI: EC: Do not release locks during operation region accesses
+    - net: mvpp2: Increase size of queue_name buffer
+    - ipv4: Check !in_dev earlier for ioctl(SIOCSIFADDR).
+    - ipv4: Mask upper DSCP bits and ECN bits in NETLINK_FIB_LOOKUP family
+    - tcp: avoid reusing FIN_WAIT2 when trying to find port in connect() process
+    - ACPICA: iasl: handle empty connection_node
+    - proc: add config & param to block forcing mem writes
+    - [Config] updateconfigs to select PROC_MEM_ALWAYS_FORCE
+    - nfp: Use IRQF_NO_AUTOEN flag in request_irq()
+    - signal: Replace BUG_ON()s
+    - ALSA: hdsp: Break infinite MIDI input flush loop
+    - x86/syscall: Avoid memcpy() for ia32 syscall_get_arguments()
+    - power: reset: brcmstb: Do not go into infinite loop if reset fails
+    - ata: sata_sil: Rename sil_blacklist to sil_quirks
+    - jfs: UBSAN: shift-out-of-bounds in dbFindBits
+    - drm/printer: Allow NULL data in devcoredump printer
+    - scsi: aacraid: Rearrange order of struct aac_srb_unit
+    - drm/radeon/r100: Handle unknown family in r100_cp_init_microcode()
+    - of/irq: Refer to actual buffer size in of_irq_parse_one()
+    - ext4: ext4_search_dir should return a proper error
+    - spi: s3c64xx: fix timeout counters in flush_fifo
+    - selftests: breakpoints: use remaining time to check if suspend succeed
+    - selftests: vDSO: fix vDSO symbols lookup for powerpc64
+    - i2c: xiic: Wait for TX empty to avoid missed TX NAKs
+    - firmware: tegra: bpmp: Drop unused mbox_client_to_bpmp()
+    - spi: bcm63xx: Fix module autoloading
+    - perf/core: Fix small negative period being ignored
+    - parisc: Fix itlb miss handler for 64-bit programs
+    - drm: Consistently use struct drm_mode_rect for FB_DAMAGE_CLIPS
+    - ALSA: core: add isascii() check to card ID generator
+    - ext4: propagate errors from ext4_find_extent() in ext4_insert_range()
+    - ext4: fix incorrect tid assumption in __jbd2_log_wait_for_space()
+    - ext4: fix incorrect tid assumption in ext4_wait_for_tail_page_commit()
+    - parisc: Fix 64-bit userspace syscall path
+    - parisc: Fix stack start for ADDR_NO_RANDOMIZE personality
+    - of/irq: Support #msi-cells=<0> in of_msi_get_domain
+    - mm: krealloc: consider spare memory for __GFP_ZERO
+    - ocfs2: fix the la space leak when unmounting an ocfs2 volume
+    - ocfs2: fix uninit-value in ocfs2_get_block()
+    - riscv: define ILLEGAL_POINTER_VALUE for 64bit
+    - clk: rockchip: fix error for unknown clocks
+    - media: sun4i_csi: Implement link validate for sun4i_csi subdev
+    - media: uapi/linux/cec.h: cec_msg_set_reply_to: zero flags
+    - iio: magnetometer: ak8975: Fix reading for ak099xx sensors
+    - tomoyo: fallback to realpath if symlink's pathname does not exist
+    - rtc: at91sam9: fix OF node leak in probe() error path
+    - Input: adp5589-keys - fix adp5589_gpio_get_value()
+    - ACPI: resource: Add Asus Vivobook X1704VAP to irq1_level_low_skip_override[]
+    - ACPI: resource: Add Asus ExpertBook B2502CVA to
+      irq1_level_low_skip_override[]
+    - gpio: davinci: fix lazy disable
+    - i2c: qcom-geni: Let firmware specify irq trigger flags
+    - i2c: qcom-geni: Grow a dev pointer to simplify code
+    - i2c: qcom-geni: Use IRQF_NO_AUTOEN flag in request_irq()
+    - arm64: Add Cortex-715 CPU part definition
+    - arm64: cputype: Add Neoverse-N3 definitions
+    - arm64: errata: Expand speculative SSBS workaround once more
+    - nfsd: use ktime_get_seconds() for timestamps
+    - nfsd: fix delegation_blocked() to block correctly for at least 30 seconds
+    - clk: qcom: rpmh: Simplify clk_rpmh_bcm_send_cmd()
+    - clk: qcom: clk-rpmh: Fix overflow in BCM vote
+    - r8169: Fix spelling mistake: "tx_underun" -> "tx_underrun"
+    - ACPI: battery: Simplify battery hook locking
+    - ext4: fix inode tree inconsistency caused by ENOMEM
+    - net: ethernet: cortina: Drop TSO support
+    - tracing: Remove precision vsnprintf() check from print event
+    - drm/crtc: fix uninitialized variable use even harder
+    - tracing: Have saved_cmdlines arrays all in one allocation
+    - virtio_console: fix misc probe bugs
+    - Input: synaptics-rmi4 - fix UAF of IRQ domain on driver removal
+    - bpf: Check percpu map value size first
+    - s390/facility: Disable compile time optimization for decompressor code
+    - s390/mm: Add cond_resched() to cmm_alloc/free_pages()
+    - ext4: nested locking for xattr inode
+    - s390/cpum_sf: Remove WARN_ON_ONCE statements
+    - ktest.pl: Avoid false positives with grub2 skip regex
+    - clk: bcm: bcm53573: fix OF node leak in init
+    - PCI: Add ACS quirk for Qualcomm SA8775P
+    - i2c: i801: Use a different adapter-name for IDF adapters
+    - PCI: Mark Creative Labs EMU20k2 INTx masking as broken
+    - media: videobuf2-core: clear memory related fields in
+      __vb2_plane_dmabuf_put()
+    - usb: chipidea: udc: enable suspend interrupt after usb reset
+    - usb: dwc2: Adjust the timing of USB Driver Interrupt Registration in the
+      Crashkernel Scenario
+    - tools/iio: Add memory allocation failure check for trigger_name
+    - driver core: bus: Return -EIO instead of 0 when show/store invalid bus
+      attribute
+    - ice: fix VLAN replay after reset
+    - SUNRPC: Fix integer overflow in decode_rc_list()
+    - tcp: fix to allow timestamp undo if no retransmits were sent
+    - tcp: fix tcp_enter_recovery() to zero retrans_stamp when it's safe
+    - gpio: aspeed: Add the flush write to ensure the write complete.
+    - gpio: aspeed: Use devm_clk api to manage clock source
+    - net: ibm: emac: mal: fix wrong goto
+    - net: annotate lockless accesses to sk->sk_ack_backlog
+    - net: annotate lockless accesses to sk->sk_max_ack_backlog
+    - sctp: ensure sk_state is set to CLOSED if hashing fails in sctp_listen_start
+    - locking/lockdep: Fix bad recursion pattern
+    - locking/lockdep: Rework lockdep_lock
+    - locking/lockdep: Avoid potential access of invalid memory in lock_class
+    - lockdep: fix deadlock issue between lockdep and rcu
+    - HID: plantronics: Workaround for an unexcepted opposite volume key
+    - Revert "usb: yurex: Replace snprintf() with the safer scnprintf() variant"
+    - usb: dwc3: core: Stop processing of pending events if controller is halted
+    - usb: xhci: Fix problem with xhci resume from suspend
+    - usb: storage: ignore bogus device raised by JieLi BR21 USB sound chip
+    - hid: intel-ish-hid: Fix uninitialized variable 'rv' in
+      ish_fw_xfer_direct_dma
+    - arm64: probes: Fix simulate_ldr*_literal()
+    - tracing/kprobes: Return EADDRNOTAVAIL when func matches several symbols
+    - tracing/kprobes: Fix symbol counting logic by looking at modules as well
+    - PCI: Add function 0 DMA alias quirk for Glenfly Arise chip
+    - fat: fix uninitialized variable
+    - s390/sclp_vt220: Convert newlines to CRLF instead of LFCR
+    - KVM: s390: Change virtual to physical address access in diag 0x258 handler
+    - x86/cpufeatures: Define X86_FEATURE_AMD_IBPB_RET
+    - drm/vmwgfx: Handle surface check failure correctly
+    - iio: dac: ltc1660: add missing select REGMAP_SPI in Kconfig
+    - iio: dac: stm32-dac-core: add missing select REGMAP_MMIO in Kconfig
+    - iio: adc: ti-ads8688: add missing select IIO_(TRIGGERED_)BUFFER in Kconfig
+    - iio: hid-sensors: Fix an error handling path in
+      _hid_sensor_set_report_latency()
+    - iio: light: opt3001: add missing full-scale range value
+    - iio: proximity: mb1232: add missing select IIO_(TRIGGERED_)BUFFER in Kconfig
+    - iio: adc: ti-ads124s08: add missing select IIO_(TRIGGERED_)BUFFER in Kconfig
+    - Bluetooth: Remove debugfs directory on module init failure
+    - Bluetooth: btusb: Fix regression with fake CSR controllers 0a12:0001
+    - xhci: Fix incorrect stream context type macro
+    - USB: serial: option: add support for Quectel EG916Q-GL
+    - USB: serial: option: add Telit FN920C04 MBIM compositions
+    - x86/resctrl: Annotate get_mem_config() functions as __init
+    - x86/apic: Always explicitly disarm TSC-deadline timer
+    - mac80211: Fix NULL ptr deref for injected rate info
+    - RDMA/bnxt_re: Fix incorrect AVID type in WQE structure
+    - ARM: dts: bcm2837-rpi-cm3-io3: Fix HDMI hpd-gpio pin
+    - RDMA/cxgb4: Fix RDMA_CM_EVENT_UNREACHABLE error for iWARP
+    - ipv4: give an IPv4 dev to blackhole_netdev
+    - RDMA/bnxt_re: Return more meaningful error
+    - drm/msm/dsi: fix 32-bit signed integer extension in pclk_rate calculation
+    - macsec: don't increment counters for an unrelated SA
+    - net: ethernet: aeroflex: fix potential memory leak in
+      greth_start_xmit_gbit()
+    - genetlink: hold RCU in genlmsg_mcast()
+    - arm64:uprobe fix the uprobe SWBP_INSN in big-endian
+    - KVM: s390: gaccess: Check if guest address is in memslot
+    - jfs: Fix sanity check in dbMount
+    - net: usb: usbnet: fix name regression
+    - r8169: avoid unsolicited interrupts
+    - posix-clock: posix-clock: Fix unbalanced locking in pc_clock_settime()
+    - ALSA: hda/realtek: Update default depop procedure
+    - ACPI: resource: Add LG 16T90SP to irq1_level_low_skip_override[]
+    - ACPI: button: Add DMI quirk for Samsung Galaxy Book2 to fix initial lid
+      detection issue
+    - ALSA: hda/realtek: Add subwoofer quirk for Acer Predator G9-593
+    - hv_netvsc: Fix VF namespace also in synthetic NIC NETDEV_REGISTER event
+    - selinux: improve error checking in sel_write_load()
+    - arm64/uprobes: change the uprobe_opcode_t typedef to fix the sparse warning
+    - cgroup: Fix potential overflow issue when checking max_depth
+    - wifi: mac80211: skip non-uploaded keys in ieee80211_iter_keys
+    - mac80211: do drv_reconfig_complete() before restarting all
+    - mac80211: Add support to trigger sta disconnect on hardware restart
+    - wifi: iwlwifi: mvm: disconnect station vifs if recovery failed
+    - ASoC: cs42l51: Fix some error handling paths in cs42l51_probe()
+    - dt-bindings: gpu: Convert Samsung Image Rotator to dt-schema
+    - gtp: simplify error handling code in 'gtp_encap_enable()'
+    - gtp: allow -1 to be specified as file description from userspace
+    - net: support ip generic csum processing in skb_csum_hwoffload_help
+    - net: skip offload for NETIF_F_IPV6_CSUM if ipv6 header contains extension
+    - drivers/misc: ti-st: Remove unneeded variable in st_tty_open
+    - firmware: arm_sdei: Fix the input parameter of cpuhp_remove_state()
+    - net: amd: mvme147: Fix probe banner message
+    - misc: sgi-gru: Don't disable preemption in GRU driver
+    - usbip: tools: Fix detach_port() invalid port error path
+    - usb: phy: Fix API devm_usb_put_phy() can not release the phy
+    - xhci: Fix Link TRB DMA in command ring stopped completion event
+    - Revert "driver core: Fix uevent_show() vs driver detach race"
+    - riscv: Remove unused GENERATING_ASM_OFFSETS
+    - Revert "drm/mipi-dsi: Set the fwnode for mipi_dsi_device"
+    - vt: prevent kernel-infoleak in con_font_get()
+    - mac80211: always have ieee80211_sta_restart()
+    - mm: krealloc: Fix MTE false alarm in __do_krealloc
+    - Linux 5.4.285
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50228
+    - mm: shmem: fix data-race in shmem_getattr()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50230
+    - nilfs2: fix kernel bug due to missing clearing of checked flag
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50218
+    - ocfs2: pass u64 to ocfs2_truncate_inline maybe overflow
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50229
+    - nilfs2: fix potential deadlock with newly created symlinks
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50233
+    - staging: iio: frequency: ad9832: fix division by zero in
+      ad9832_calc_freqreg()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50234
+    - wifi: iwlegacy: Clear stale interrupts before resuming device
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50236
+    - wifi: ath10k: Fix memory leak in management tx
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50237
+    - wifi: mac80211: do not pass a stopped vif to the driver in .get_txpower
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50251
+    - netfilter: nft_payload: sanitize offset and length before calling
+      skb_checksum()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50262
+    - bpf: Fix out-of-bounds write in trie_get_next_key()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-53059
+    - wifi: iwlwifi: mvm: Fix response handling in iwl_mvm_send_recovery_cmd()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50142
+    - xfrm: validate new SA's prefixlen using SA family when sel.family is unset
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50116
+    - nilfs2: fix kernel bug due to missing clearing of buffer delay flag
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50117
+    - drm/amd: Guard against bad data for ATIF ACPI method
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50205
+    - ALSA: firewire-lib: Avoid division by zero in apply_constraint_to_size()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50127
+    - net: sched: fix use-after-free in taprio_change()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50167
+    - be2net: fix potential memory leak in be_xmit()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50168
+    - net/sun3_82586: fix potential memory leak in sun3_82586_send_packet()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50131
+    - tracing: Consider the NULL character when validating the event length
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50143
+    - udf: fix uninit-value use in udf_get_fileshortad
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50134
+    - drm/vboxvideo: Replace fake VLA at end of vbva_mouse_pointer_shape with real
+      VLA
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50194
+    - arm64: probes: Fix uprobes for big-endian kernels
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50148
+    - Bluetooth: bnep: fix wild-memory-access in proto_unregister
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50150
+    - usb: typec: altmode should keep reference to parent
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50151
+    - smb: client: fix OOBs when building SMB2_IOCTL request
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50171
+    - net: systemport: fix potential memory leak in bcm_sysport_xmit()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50202
+    - nilfs2: propagate directory read errors from nilfs_find_entry()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50074
+    - parport: Proper fix for array out-of-bounds access
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50082
+    - blk-rq-qos: fix crash on rq_qos_wait vs. rq_qos_wake_function race
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-40953
+    - KVM: Fix a data race on last_boosted_vcpu in kvm_vcpu_on_spin()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50199
+    - mm/swapfile: skip HugeTLB pages for unuse_vma
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50099
+    - arm64: probes: Remove broken LDR (literal) uprobe support
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50195
+    - posix-clock: Fix missing timespec64 check in pc_clock_settime()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50096
+    - nouveau/dmem: Fix vulnerability in migrate_to_ram upon copy error
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50024
+    - net: Fix an unsafe loop on the list
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49878
+    - resource: fix region_intersects() vs add_memory_driver_managed()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50033
+    - slip: make slhc_remember() more robust against malicious packets
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50035
+    - ppp: fix ppp_async_encode() illegal access
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50039
+    - net/sched: accept TCA_STAB only for root qdisc
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50040
+    - igb: Do not bring the device up after non-fatal error
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50044
+    - Bluetooth: RFCOMM: FIX possible deadlock in rfcomm_sk_state_change
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50045
+    - netfilter: br_netfilter: fix panic with metadata_dst skb
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-38544
+    - RDMA/rxe: Fix seg fault in rxe_comp_queue_pkt
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50180
+    - fbdev: sisfb: Fix strbuf array overflow
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50184
+    - virtio_pmem: Check device status before requesting flush
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50059
+    - ntb: ntb_hw_switchtec: Fix use after free vulnerability in
+      switchtec_ntb_remove due to race condition
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50089
+    - unicode: Don't special case ignorable code points
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49955
+    - ACPI: battery: Fix possible crash when unregistering a battery hook
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49973
+    - r8169: add tally counter fields added with RTL8125
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49975
+    - uprobes: fix kernel info leak via "[uprobes]" vma
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49867
+    - btrfs: wait for fixup workers before stopping cleaner kthread during umount
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49868
+    - btrfs: fix a NULL pointer dereference when failed to start a new trasacntion
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49981
+    - media: venus: fix use after free bug in venus_remove due to race condition
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49982
+    - aoe: fix the potential use-after-free problem in more places
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49877
+    - ocfs2: fix possible null-ptr-deref in ocfs2_set_buffer_uptodate
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49957
+    - ocfs2: fix null-ptr-deref when journal load failed.
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49965
+    - ocfs2: remove unreasonable unlock in ocfs2_read_blocks
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49966
+    - ocfs2: cancel dqi_sync_work before freeing oinfo
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49958
+    - ocfs2: reserve space for inline xattr before attaching reflink tree
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49959
+    - jbd2: stop waiting for space when jbd2_cleanup_journal_tail() returns error
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49879
+    - drm: omapdrm: Add missing check for alloc_ordered_workqueue
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49882
+    - ext4: fix double brelse() the buffer of the extents path
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49883
+    - ext4: aovid use-after-free in ext4_ext_insert_extent()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49985
+    - i2c: stm32f7: Do not prepare/unprepare clock during runtime suspend/resume
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50006
+    - ext4: fix i_data_sem unlock order in ext4_ind_migrate()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49892
+    - drm/amd/display: Initialize get_bytes_per_element's default to 1
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49894
+    - drm/amd/display: Fix index out of bounds in degamma hardware format
+      translation
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49896
+    - drm/amd/display: Check stream before comparing them
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49900
+    - jfs: Fix uninit-value access of new_ea in ea_buffer
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49902
+    - jfs: check if leafidx greater than num leaves per dmap tree
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49903
+    - jfs: Fix uaf in dbFreeBits
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49924
+    - fbdev: pxafb: Fix possible use after free in pxafb_task()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50007
+    - ALSA: asihpi: Fix potential OOB array access
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50008
+    - wifi: mwifiex: Fix memcpy() field-spanning write warning in
+      mwifiex_cmd_802_11_scan_ext()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49995
+    - tipc: guard against string buffer overrun
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49962
+    - ACPICA: check null return of ACPI_ALLOCATE_ZEROED() in
+      acpi_db_convert_to_package()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49938
+    - wifi: ath9k_htc: Use __skb_set_length() for resetting urb before resubmit
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47740
+    - f2fs: Require FMODE_WRITE for atomic write ioctls
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49944
+    - sctp: set sk_state back to CLOSED if autobind fails in sctp_listen_start
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49948
+    - net: add more sanity checks to qdisc_pkt_len_init()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49949
+    - net: avoid potential underflow in qdisc_pkt_len_init() with UFO
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49997
+    - net: ethernet: lantiq_etop: fix memory disclosure
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49952
+    - netfilter: nf_tables: prevent nf_skb_duplicated corruption
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50179
+    - ceph: remove the incorrect Fw reference check when dirtying pages
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49963
+    - mailbox: bcm2835: Fix timeout during suspend mode
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-46849
+    - ASoC: meson: axg-card: fix 'use-after-free'
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47679
+    - vfs: fix race between evice_inodes() and find_inode()&iput()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49860
+    - ACPI: sysfs: validate return type of _STR method
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47742
+    - firmware_loader: Block path traversal
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47684
+    - tcp: check skb is non-NULL in tcp_rto_delta_us()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47747
+    - net: seeq: Fix use after free vulnerability in ether3 Driver Due to Race
+      Condition
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47685
+    - netfilter: nf_reject_ipv6: fix nf_reject_ip6_tcphdr_put()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47692
+    - nfsd: return -EINVAL when namelen is 0
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47737
+    - nfsd: call cache_put if xdr_reserve_space returns NULL
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2023-52917
+    - ntb: intel: Fix the NULL vs IS_ERR() bug for debugfs_create_dir()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47749
+    - RDMA/cxgb4: Added NULL check for lookup_atid
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47696
+    - RDMA/iwcm: Fix WARNING:at_kernel/workqueue.c:#check_flush_dependency
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47756
+    - PCI: keystone: Fix if-statement expression in ks_pcie_quirk()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47697
+    - drivers: media: dvb-frontends/rtl2830: fix an out-of-bounds write error
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47698
+    - drivers: media: dvb-frontends/rtl2832: fix an out-of-bounds write error
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47757
+    - nilfs2: fix potential oob read in nilfs_btree_check_delete()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47699
+    - nilfs2: fix potential null-ptr-deref in nilfs_btree_insert()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47701
+    - ext4: avoid OOB when system.data xattr changes underneath the filesystem
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49851
+    - tpm: Clean up TPM space after command failure
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47723
+    - jfs: fix out-of-bounds in dbNextAG() and diAlloc()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47706
+    - block, bfq: fix possible UAF for bfqq->bic with merge chain
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47709
+    - can: bcm: Clear bo->bcm_proc_read after remove_proc_entry().
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47710
+    - sock_map: Add a cond_resched() in sock_hash_free()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47712
+    - wifi: wilc1000: fix potential RCU dereference issue in
+      wilc_parse_join_bss_param
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47713
+    - wifi: mac80211: use two-phase skb reclamation in ieee80211_do_stop()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47671
+    - USB: usbtmc: prevent kernel-usb-infoleak
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-44931
+    - gpio: prevent potential speculation leaks in gpio_device_get_desc()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-41016
+    - ocfs2: strict bound check before memcmp in ocfs2_xattr_find_entry()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47670
+    - ocfs2: add bounds checking to ocfs2_xattr_find_entry()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47672
+    - wifi: iwlwifi: mvm: don't wait for tx queues if firmware is dead
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-46853
+    - spi: nxp-fspi: fix the KASAN report out-of-bounds bug
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-46854
+    - net: dpaa: Pad packets to ETH_ZLEN
+
+ -- Benjamin Wheeler <benjamin.wheeler@canonical.com>  Fri, 31 Jan 2025 12:06:43 -0500
+
+linux-xilinx-zynqmp (5.4.0-1057.61) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1057.61 -proposed tracker (LP: #2093619)
+
+  * Add list of source files to linux-buildinfo (LP: #2086606)
+    - [Packaging] Add dwarfdump package in the Build-Depends
+
+  [ Ubuntu: 5.4.0-205.225 ]
+
+  * focal/linux: 5.4.0-205.225 -proposed tracker (LP: #2093621)
+  * Hold IOPOLL locks when triggering io_uring's deferred work (LP: #2078659) //
+    CVE-2023-21400
+    - io_uring: remove extra check in __io_commit_cqring
+    - io_uring: dont kill fasync under completion_lock
+    - io_uring: ensure IOPOLL locks around deferred work
+  * CVE-2024-40967
+    - iopoll: introduce read_poll_timeout macro
+    - iopoll: Introduce read_poll_timeout_atomic macro
+    - serial: imx: Introduce timeout when waiting on transmitter empty
+  * CVE-2024-53164
+    - net: sched: fix ordering of qlen adjustment
+  * CVE-2024-53141
+    - netfilter: ipset: add missing range check in bitmap_ip_uadt
+  * CVE-2024-53103
+    - hv_sock: Initializing vsk->trans to NULL to prevent a dangling pointer
+
+ -- Wei-Lin Chang <weilin.chang@canonical.com>  Fri, 24 Jan 2025 18:28:35 +0800
+
+linux-xilinx-zynqmp (5.4.0-1056.60) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1056.60 -proposed tracker (LP: #2090085)
+
+  [ Ubuntu: 5.4.0-204.224 ]
+
+  * focal/linux: 5.4.0-204.224 -proposed tracker (LP: #2091090)
+  * CVE-2024-50264
+    - vsock/virtio: Initialization of the dangling pointer occurring in vsk->trans
+  * CVE-2024-53057
+    - net/sched: stop qdisc_tree_reduce_backlog on TC_H_ROOT
+  * CVE-2024-49967
+    - ext4: no need to continue when the number of entries is 1
+  * CVE-2024-43892
+    - memcg: protect concurrent access to mem_cgroup_idr
+  * CVE-2024-38553
+    - net: fec: remove .ndo_poll_controller to avoid deadlocks
+  * CVE-2024-38597
+    - eth: sungem: remove .ndo_poll_controller to avoid deadlocks
+  * CVE-2023-52821
+    - drm/panel: fix a possible null pointer dereference
+  * CVE-2024-36952
+    - scsi: lpfc: Move NPIV's transport unregistration to after resource clean up
+  * CVE-2024-40910
+    - ax25: Fix refcount imbalance on inbound connections
+  * CVE-2024-35963
+    - Bluetooth: hci_sock: Fix not validating setsockopt user input
+  * CVE-2024-35965
+    - Bluetooth: L2CAP: uninitialized variables in l2cap_sock_setsockopt()
+    - Bluetooth: L2CAP: Fix not validating setsockopt user input
+  * CVE-2024-35966
+    - Bluetooth: RFCOMM: Fix not validating setsockopt user input
+  * CVE-2024-35967
+    - Bluetooth: SCO: Fix not validating setsockopt user input
+  * CVE-2021-47101
+    - net: asix: fix uninit value bugs
+    - asix: fix wrong return value in asix_check_host_enable()
+    - asix: fix uninit-value in asix_mdio_read()
+  * CVE-2022-38096
+    - drm/vmwgfx: Fix possible null pointer derefence with invalid contexts
+  * CVE-2021-47001
+    - xprtrdma: Fix cwnd update ordering
+
+ -- Wei-Lin Chang <weilin.chang@canonical.com>  Mon, 16 Dec 2024 14:34:51 +0800
+
+linux-xilinx-zynqmp (5.4.0-1055.59) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1055.59 -proposed tracker (LP: #2086449)
+
+  [ Ubuntu: 5.4.0-202.222 ]
+
+  * focal/linux: 5.4.0-202.222 -proposed tracker (LP: #2086451)
+    - [Packaging] resync git-ubuntu-log
+  * CVE-2021-47501
+    - i40e: Fix NULL pointer dereference in i40e_dbg_dump_desc
+  * CVE-2024-46724
+    - drm/amdgpu: Fix out-of-bounds read of df_v1_7_channel_number
+  * CVE-2024-42240
+    - x86/bhi: Avoid warning in #DB handler due to BHI mitigation
+  * CVE-2024-42077
+    - ocfs2: fix DIO failure due to insufficient transaction credits
+  * CVE-2024-42068
+    - bpf: Take return from set_memory_ro() into account with bpf_prog_lock_ro()
+  * CVE-2024-36968
+    - Bluetooth: L2CAP: Fix div-by-zero in l2cap_le_flowctl_init()
+  * CVE-2024-35904
+    - selinux: avoid dereference of garbage after mount failure
+  * CVE-2023-52498
+    - PM: sleep: Avoid calling put_device() under dpm_list_mtx
+    - PM: sleep: Fix error handling in dpm_prepare()
+    - async: Split async_schedule_node_domain()
+    - async: Introduce async_schedule_dev_nocall()
+    - PM: sleep: Fix possible deadlocks in core system-wide PM code
+  * CVE-2023-52488
+    - serial: sc16is7xx: convert from _raw_ to _noinc_ regmap functions for FIFO
+  * CVE-2022-48938
+    - CDC-NCM: avoid overflow in sanity checking
+  * CVE-2024-42156
+    - s390/pkey: Wipe copies of clear-key structures on failure
+  * CVE-2024-44942
+    - f2fs: fix to do sanity check on F2FS_INLINE_DATA flag in inode during GC
+  * CVE-2024-38538
+    - net: bridge: xmit: make sure we have at least eth header len bytes
+  * CVE-2021-47076
+    - RDMA/rxe: Return CQE error if invalid lkey was supplied
+  * CVE-2024-36938
+    - bpf, skmsg: Fix NULL pointer dereference in sk_psock_skb_ingress_enqueue
+  * CVE-2024-44940
+    - fou: remove warn in gue_gro_receive on unsupported protocol
+  * CVE-2024-35951
+    - drm/panfrost: Fix the error path in panfrost_mmu_map_fault_addr()
+  * CVE-2023-52497
+    - erofs: fix lz4 inplace decompression
+  * CVE-2024-36953
+    - KVM: arm64: vgic-v2: Check for non-NULL vCPU in vgic_v2_parse_attr()
+  * CVE-2022-48943
+    - KVM: x86/mmu: make apf token non-zero to fix bug
+  * CVE-2024-26947
+    - ARM: 9359/1: flush: check if the folio is reserved for no-mapping addresses
+  * CVE-2022-48733
+    - btrfs: fix use-after-free after failure to create a snapshot
+  * CVE-2023-52639
+    - KVM: s390: vsie: fix race during shadow creation
+
+ -- Hui Wang <hui.wang@canonical.com>  Fri, 15 Nov 2024 13:03:39 +0800
+
+linux-xilinx-zynqmp (5.4.0-1054.58) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1054.58 -proposed tracker (LP: #2082934)
+
+  [ Ubuntu: 5.4.0-200.220 ]
+
+  * focal/linux: 5.4.0-200.220 -proposed tracker (LP: #2082937)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] debian.master/dkms-versions -- update from kernel-versions
+      (main/2024.09.30)
+  * CVE-2024-26800
+    - tls: rx: coalesce exit paths in tls_decrypt_sg()
+    - tls: separate no-async decryption request handling from async
+    - tls: fix use-after-free on failed backlog decryption
+  * CVE-2024-26641
+    - ip6_tunnel: make sure to pull inner header in __ip6_tnl_rcv()
+  * CVE-2021-47212
+    - net/mlx5: Update error handler for UCTX and UMEM
+  * wbt:wbt_* trace event NULL pointer dereference with GENHD_FL_HIDDEN disks
+    (LP: #2081085)
+    - bdi: use bdi_dev_name() to get device name
+  * Focal update: v5.4.284 upstream stable release (LP: #2081278)
+    - drm: panel-orientation-quirks: Add quirk for OrangePi Neo
+    - i2c: Fix conditional for substituting empty ACPI functions
+    - net: usb: qmi_wwan: add MeiG Smart SRM825L
+    - drm/amdgpu: Fix uninitialized variable warning in amdgpu_afmt_acr
+    - drm/amdgpu: fix overflowed array index read warning
+    - drm/amd/display: Check gpio_id before used as array index
+    - drm/amd/display: Stop amdgpu_dm initialize when stream nums greater than 6
+    - drm/amd/display: Check num_valid_sets before accessing reader_wm_sets[]
+    - drm/amd/display: Fix Coverity INTEGER_OVERFLOW within
+      dal_gpio_service_create
+    - drm/amdgpu: fix ucode out-of-bounds read warning
+    - drm/amdgpu: fix mc_data out-of-bounds read warning
+    - drm/amdkfd: Reconcile the definition and use of oem_id in struct
+      kfd_topology_device
+    - apparmor: fix possible NULL pointer dereference
+    - ionic: fix potential irq name truncation
+    - usbip: Don't submit special requests twice
+    - usb: typec: ucsi: Fix null pointer dereference in trace
+    - smack: tcp: ipv4, fix incorrect labeling
+    - wifi: cfg80211: make hash table duplicates more survivable
+    - drm/amd/display: Skip wbscl_set_scaler_filter if filter is null
+    - media: uvcvideo: Enforce alignment of frame and interval
+    - block: initialize integrity buffer to zero before writing it to media
+    - net: set SOCK_RCU_FREE before inserting socket into hashtable
+    - virtio_net: Fix napi_skb_cache_put warning
+    - udf: Limit file size to 4TB
+    - i2c: Use IS_REACHABLE() for substituting empty ACPI functions
+    - sch/netem: fix use after free in netem_dequeue
+    - ASoC: dapm: Fix UAF for snd_soc_pcm_runtime object
+    - ALSA: hda/conexant: Add pincfg quirk to enable top speakers on Sirius
+      devices
+    - ata: libata: Fix memory leak for error path in ata_host_alloc()
+    - irqchip/gic-v2m: Fix refcount leak in gicv2m_of_init()
+    - mmc: dw_mmc: Fix IDMAC operation with pages bigger than 4K
+    - mmc: sdhci-of-aspeed: fix module autoloading
+    - fuse: update stats for pages in dropped aux writeback list
+    - fuse: use unsigned type for getxattr/listxattr size truncation
+    - reset: hi6220: Add support for AO reset controller
+    - clk: hi6220: use CLK_OF_DECLARE_DRIVER
+    - clk: qcom: clk-alpha-pll: Fix the pll post div mask
+    - clk: qcom: clk-alpha-pll: Fix the trion pll postdiv set rate API
+    - ila: call nf_unregister_net_hooks() sooner
+    - sched: sch_cake: fix bulk flow accounting logic for host fairness
+    - nilfs2: fix missing cleanup on rollforward recovery error
+    - nilfs2: fix state management in error path of log writing function
+    - ALSA: hda: Add input value sanity checks to HDMI channel map controls
+    - smack: unix sockets: fix accept()ed socket label
+    - irqchip/armada-370-xp: Do not allow mapping IRQ 0 and 1
+    - af_unix: Remove put_pid()/put_cred() in copy_peercred().
+    - netfilter: nf_conncount: fix wrong variable type
+    - udf: Avoid excessive partition lengths
+    - wifi: brcmsmac: advertise MFP_CAPABLE to enable WPA3
+    - usb: uas: set host status byte on data completion error
+    - PCI: keystone: Add workaround for Errata #i2037 (AM65x SR 1.0)
+    - media: qcom: camss: Add check for v4l2_fwnode_endpoint_parse
+    - pcmcia: Use resource_size function on resource object
+    - can: bcm: Remove proc entry when dev is unregistered.
+    - igb: Fix not clearing TimeSync interrupts for 82580
+    - platform/x86: dell-smbios: Fix error path in dell_smbios_init()
+    - tcp_bpf: fix return value of tcp_bpf_sendmsg()
+    - cx82310_eth: re-enable ethernet mode after router reboot
+    - drivers/net/usb: Remove all strcpy() uses
+    - net: usb: don't write directly to netdev->dev_addr
+    - usbnet: modern method to get random MAC
+    - net: bridge: fdb: convert is_local to bitops
+    - net: bridge: fdb: convert is_static to bitops
+    - net: bridge: fdb: convert is_sticky to bitops
+    - net: bridge: fdb: convert added_by_user to bitops
+    - net: bridge: fdb: convert added_by_external_learn to use bitops
+    - net: bridge: br_fdb_external_learn_add(): always set EXT_LEARN
+    - net: dsa: vsc73xx: fix possible subblocks range of CAPT block
+    - ASoC: topology: Properly initialize soc_enum values
+    - dm init: Handle minors larger than 255
+    - iommu/vt-d: Handle volatile descriptor status read
+    - cgroup: Protect css->cgroup write under css_set_lock
+    - um: line: always fill *error_out in setup_one_line()
+    - devres: Initialize an uninitialized struct member
+    - pci/hotplug/pnv_php: Fix hotplug driver crash on Powernv
+    - hwmon: (adc128d818) Fix underflows seen when writing limit attributes
+    - hwmon: (lm95234) Fix underflows seen when writing limit attributes
+    - hwmon: (nct6775-core) Fix underflows seen when writing limit attributes
+    - hwmon: (w83627ehf) Fix underflows seen when writing limit attributes
+    - libbpf: Add NULL checks to bpf_object__{prev_map,next_map}
+    - wifi: mwifiex: Do not return unused priv in mwifiex_get_priv_by_id()
+    - smp: Add missing destroy_work_on_stack() call in smp_call_on_cpu()
+    - btrfs: replace BUG_ON with ASSERT in walk_down_proc()
+    - btrfs: clean up our handling of refs == 0 in snapshot delete
+    - PCI: Add missing bridge lock to pci_bus_lock()
+    - btrfs: initialize location to fix -Wmaybe-uninitialized in
+      btrfs_lookup_dentry()
+    - HID: cougar: fix slab-out-of-bounds Read in cougar_report_fixup
+    - Input: uinput - reject requests with unreasonable number of slots
+    - usbnet: ipheth: race between ipheth_close and error handling
+    - Squashfs: sanity check symbolic link size
+    - of/irq: Prevent device address out-of-bounds read in interrupt map walk
+    - lib/generic-radix-tree.c: Fix rare race in __genradix_ptr_alloc()
+    - ata: pata_macio: Use WARN instead of BUG
+    - NFSv4: Add missing rescheduling points in
+      nfs_client_return_marked_delegations
+    - staging: iio: frequency: ad9834: Validate frequency parameter value
+    - iio: buffer-dmaengine: fix releasing dma channel on error
+    - iio: fix scale application in iio_convert_raw_to_processed_unlocked
+    - binder: fix UAF caused by offsets overwrite
+    - nvmem: Fix return type of devm_nvmem_device_get() in kerneldoc
+    - uio_hv_generic: Fix kernel NULL pointer dereference in hv_uio_rescind
+    - Drivers: hv: vmbus: Fix rescind handling in uio_hv_generic
+    - VMCI: Fix use-after-free when removing resource in vmci_resource_remove()
+    - clocksource/drivers/imx-tpm: Fix return -ETIME when delta exceeds INT_MAX
+    - clocksource/drivers/imx-tpm: Fix next event not taking effect sometime
+    - clocksource/drivers/timer-of: Remove percpu irq related code
+    - uprobes: Use kzalloc to allocate xol area
+    - ring-buffer: Rename ring_buffer_read() to read_buffer_iter_advance()
+    - tracing: Avoid possible softlockup in tracing_iter_reset()
+    - nilfs2: replace snprintf in show functions with sysfs_emit
+    - nilfs2: protect references to superblock parameters exposed in sysfs
+    - ACPI: processor: Return an error if acpi_processor_get_info() fails in
+      processor_add()
+    - ACPI: processor: Fix memory leaks in error paths of processor_add()
+    - arm64: acpi: Move get_cpu_for_acpi_id() to a header
+    - arm64: acpi: Harden get_cpu_for_acpi_id() against missing CPU entry
+    - nvmet-tcp: fix kernel crash if commands allocation fails
+    - drm/i915/fence: Mark debug_fence_init_onstack() with __maybe_unused
+    - drm/i915/fence: Mark debug_fence_free() with __maybe_unused
+    - rtmutex: Drop rt_mutex::wait_lock before scheduling
+    - net, sunrpc: Remap EPERM in case of connection failure in
+      xs_tcp_setup_socket
+    - cx82310_eth: fix error return code in cx82310_bind()
+    - Linux 5.4.284
+  * CVE-2024-42244
+    - USB: serial: mos7840: fix crash on resume
+  * CVE-2024-40929
+    - wifi: iwlwifi: mvm: check n_ssids before accessing the ssids
+  * CVE-2024-41073
+    - nvme: avoid double free special payload
+  * CVE-2024-41071
+    - wifi: mac80211: Avoid address calculations via out of bounds array indexing
+  * CVE-2024-42229
+    - crypto: aead, cipher - zeroize key buffer after use
+  * CVE-2024-38611
+    - media: i2c: et8ek8: Don't strip remove function when driver is builtin
+  * CVE-2024-38602
+    - ax25: Fix reference count leak issues of ax25_dev
+  * CVE-2024-35848
+    - misc: eeprom: at24: fix regulator underflow
+    - misc: eeprom: at24: register nvmem only after eeprom is ready to use
+    - eeprom: at24: fix memory corruption race condition
+  * CVE-2024-26669
+    - net/sched: flower: Fix chain template offload
+  * CVE-2024-26668
+    - netfilter: nft_limit: rename stateful structure
+    - netfilter: nft_limit: reject configurations that cause integer overflow
+  * CVE-2024-26640
+    - net-zerocopy: Refactor frag-is-remappable test.
+    - tcp: add sanity checks to rx zerocopy
+  * CVE-2024-26607
+    - drm/bridge: sii902x: Fix probing race issue
+  * CVE-2023-52614
+    - PM / devfreq: Fix buffer overflow in trans_stat_show
+  * CVE-2023-52531
+    - wifi: iwlwifi: mvm: Fix a memory corruption issue
+  * CVE-2022-36402
+    - drm/vmwgfx: Use enum to represent graphics context capabilities
+    - drm/vmwgfx: Fix shader stage validation
+  * Focal update: v5.4.283 upstream stable release (LP: #2080595)
+    - fuse: Initialize beyond-EOF page contents before setting uptodate
+    - ALSA: usb-audio: Support Yamaha P-125 quirk entry
+    - xhci: Fix Panther point NULL pointer deref at full-speed re-enumeration
+    - s390/dasd: fix error recovery leading to data corruption on ESE devices
+    - arm64: ACPI: NUMA: initialize all values of acpi_early_node_map to
+      NUMA_NO_NODE
+    - dm resume: don't return EINVAL when signalled
+    - dm persistent data: fix memory allocation failure
+    - vfs: Don't evict inode under the inode lru traversing context
+    - bitmap: introduce generic optimized bitmap_size()
+    - fix bitmap corruption on close_range() with CLOSE_RANGE_UNSHARE
+    - selinux: fix potential counting error in avc_add_xperms_decision()
+    - drm/amdgpu: Actually check flags for all context ops.
+    - memcg_write_event_control(): fix a user-triggerable oops
+    - overflow.h: Add flex_array_size() helper
+    - overflow: Implement size_t saturating arithmetic helpers
+    - s390/cio: rename bitmap_size() -> idset_bitmap_size()
+    - btrfs: rename bitmap_set_bits() -> btrfs_bitmap_set_bits()
+    - s390/uv: Panic for set and remove shared access UVC errors
+    - net/mlx5e: Correctly report errors for ethtool rx flows
+    - atm: idt77252: prevent use after free in dequeue_rx()
+    - net: axienet: Fix DMA descriptor cleanup path
+    - net: axienet: Improve DMA error handling
+    - net: axienet: Factor out TX descriptor chain cleanup
+    - net: axienet: Check for DMA mapping errors
+    - net: axienet: Drop MDIO interrupt registers from ethtools dump
+    - net: axienet: Wrap DMA pointer writes to prepare for 64 bit
+    - net: axienet: Upgrade descriptors to hold 64-bit addresses
+    - net: axienet: Autodetect 64-bit DMA capability
+    - net: axienet: Fix register defines comment description
+    - net: dsa: vsc73xx: pass value in phy_write operation
+    - net: hns3: fix a deadlock problem when config TC during resetting
+    - ALSA: hda/realtek: Fix noise from speakers on Lenovo IdeaPad 3 15IAU7
+    - ssb: Fix division by zero issue in ssb_calc_clock_rate
+    - wifi: cw1200: Avoid processing an invalid TIM IE
+    - i2c: riic: avoid potential division by zero
+    - media: radio-isa: use dev_name to fill in bus_info
+    - staging: ks7010: disable bh on tx_dev_lock
+    - binfmt_misc: cleanup on filesystem umount
+    - scsi: spi: Fix sshdr use
+    - gfs2: setattr_chown: Add missing initialization
+    - wifi: iwlwifi: abort scan when rfkill on but device enabled
+    - IB/hfi1: Fix potential deadlock on &irq_src_lock and &dd->uctxt_lock
+    - powerpc/xics: Check return value of kasprintf in icp_native_map_one_cpu
+    - nvmet-trace: avoid dereferencing pointer too early
+    - ext4: do not trim the group with corrupted block bitmap
+    - quota: Remove BUG_ON from dqget()
+    - media: pci: cx23885: check cx23885_vdev_init() return
+    - fs: binfmt_elf_efpic: don't use missing interpreter's properties
+    - scsi: lpfc: Initialize status local variable in lpfc_sli4_repost_sgl_list()
+    - net/sun3_82586: Avoid reading past buffer in debug output
+    - drm/lima: set gp bus_stop bit before hard reset
+    - virtiofs: forbid newlines in tags
+    - md: clean up invalid BUG_ON in md_ioctl
+    - x86: Increase brk randomness entropy for 64-bit systems
+    - powerpc/boot: Handle allocation failure in simple_realloc()
+    - powerpc/boot: Only free if realloc() succeeds
+    - btrfs: change BUG_ON to assertion when checking for delayed_node root
+    - btrfs: handle invalid root reference found in may_destroy_subvol()
+    - btrfs: send: handle unexpected data in header buffer in begin_cmd()
+    - btrfs: delete pointless BUG_ON check on quota root in
+      btrfs_qgroup_account_extent()
+    - f2fs: fix to do sanity check in update_sit_entry
+    - usb: gadget: fsl: Increase size of name buffer for endpoints
+    - nvme: clear caller pointer on identify failure
+    - Bluetooth: bnep: Fix out-of-bound access
+    - nvmet-tcp: do not continue for invalid icreq
+    - NFS: avoid infinite loop in pnfs_update_layout.
+    - openrisc: Call setup_memory() earlier in the init sequence
+    - s390/iucv: fix receive buffer virtual vs physical address confusion
+    - usb: dwc3: core: Skip setting event buffers for host only controllers
+    - irqchip/gic-v3-its: Remove BUG_ON in its_vpe_irq_domain_alloc
+    - ext4: set the type of max_zeroout to unsigned int to avoid overflow
+    - nvmet-rdma: fix possible bad dereference when freeing rsps
+    - hrtimer: Prevent queuing of hrtimer without a function callback
+    - gtp: pull network headers in gtp_dev_xmit()
+    - block: use "unsigned long" for blk_validate_block_size().
+    - media: solo6x10: replace max(a, min(b, c)) by clamp(b, a, c)
+    - dm mpath: pass IO start time to path selector
+    - dm: do not use waitqueue for request-based DM
+    - dm suspend: return -ERESTARTSYS instead of -EINTR
+    - Bluetooth: Make use of __check_timeout on hci_sched_le
+    - Bluetooth: hci_core: Fix not handling link timeouts propertly
+    - Bluetooth: hci_core: Fix LE quote calculation
+    - tc-testing: don't access non-existent variable on exception
+    - kcm: Serialise kcm_sendmsg() for the same socket.
+    - netfilter: nft_counter: Synchronize nft_counter_reset() against reader.
+    - net: dsa: mv88e6xxx: global2: Expose ATU stats register
+    - net: dsa: mv88e6xxx: global1_atu: Add helper for get next
+    - net: dsa: mv88e6xxx: read FID when handling ATU violations
+    - net: dsa: mv88e6xxx: replace ATU violation prints with trace points
+    - net: dsa: mv88e6xxx: Fix out-of-bound access
+    - ipv6: prevent UAF in ip6_send_skb()
+    - net: xilinx: axienet: Always disable promiscuous mode
+    - net: xilinx: axienet: Fix dangling multicast addresses
+    - drm/msm: use drm_debug_enabled() to check for debug categories
+    - drm/msm/dpu: don't play tricks with debug macros
+    - mmc: mmc_test: Fix NULL dereference on allocation failure
+    - Bluetooth: MGMT: Add error handling to pair_device()
+    - HID: wacom: Defer calculation of resolution until resolution_code is known
+    - HID: microsoft: Add rumble support to latest xbox controllers
+    - cxgb4: add forgotten u64 ivlan cast before shift
+    - mmc: dw_mmc: allow biu and ciu clocks to defer
+    - ALSA: timer: Relax start tick time check for slave timer elements
+    - Input: MT - limit max slots
+    - tools: move alignment-related macros to new <linux/align.h>
+    - pinctrl: single: fix potential NULL dereference in pcs_get_function()
+    - wifi: mwifiex: duplicate static structs used in driver instances
+    - drm/amdkfd: don't allow mapping the MMIO HDP page with large pages
+    - filelock: Correct the filelock owner in fcntl_setlk/fcntl_setlk64
+    - media: uvcvideo: Fix integer overflow calculating timestamp
+    - ata: libata-core: Fix null pointer dereference on error
+    - cgroup/cpuset: Prevent UAF in proc_cpuset_show()
+    - net:rds: Fix possible deadlock in rds_message_put
+    - soundwire: stream: fix programming slave ports for non-continous port maps
+    - r8152: Factor out OOB link list waits
+    - ethtool: check device is present when getting link settings
+    - gtp: fix a potential NULL pointer dereference
+    - net: busy-poll: use ktime_get_ns() instead of local_clock()
+    - nfc: pn533: Add dev_up/dev_down hooks to phy_ops
+    - nfc: pn533: Add autopoll capability
+    - nfc: pn533: Add poll mod list filling check
+    - soc: qcom: cmd-db: Map shared memory as WC, not WB
+    - cdc-acm: Add DISABLE_ECHO quirk for GE HealthCare UI Controller
+    - USB: serial: option: add MeiG Smart SRM825L
+    - usb: dwc3: omap: add missing depopulate in probe error path
+    - usb: dwc3: core: Prevent USB core invalid event buffer address access
+    - usb: dwc3: st: fix probed platform device ref count on probe error path
+    - usb: dwc3: st: add missing depopulate in probe error path
+    - usb: core: sysfs: Unmerge @usb3_hardware_lpm_attr_group in
+      remove_power_attributes()
+    - net: dsa: mv8e6xxx: Fix stub function parameters
+    - scsi: aacraid: Fix double-free on probe failure
+    - Linux 5.4.283
+  * CVE-2024-27051
+    - cpufreq: brcmstb-avs-cpufreq: add check for cpufreq_cpu_get's return value
+    - cpufreq: brcmstb-avs-cpufreq: ISO C90 forbids mixed declarations
+  * CVE-2024-26891
+    - PCI: Make pci_dev_is_disconnected() helper public for other drivers
+    - iommu/vt-d: Don't issue ATS Invalidation request when device is disconnected
+  * Focal update: v5.4.282 upstream stable release (LP: #2078388)
+    - EDAC, skx_common: Refactor so that we initialize "dev" in result of adxl
+      decode.
+    - EDAC, skx: Retrieve and print retry_rd_err_log registers
+    - EDAC/skx_common: Add new ADXL components for 2-level memory
+    - EDAC, i10nm: make skx_common.o a separate module
+    - platform/chrome: cros_ec_debugfs: fix wrong EC message version
+    - hfsplus: fix to avoid false alarm of circular locking
+    - x86/of: Return consistent error type from x86_of_pci_irq_enable()
+    - x86/pci/intel_mid_pci: Fix PCIBIOS_* return code handling
+    - x86/pci/xen: Fix PCIBIOS_* return code handling
+    - x86/platform/iosf_mbi: Convert PCIBIOS_* return codes to errnos
+    - hwmon: (adt7475) Fix default duty on fan is disabled
+    - pwm: stm32: Always do lazy disabling
+    - hwmon: (max6697) Fix underflow when writing limit attributes
+    - hwmon: (max6697) Fix swapped temp{1,8} critical alarms
+    - arm64: dts: qcom: sdm845: add power-domain to UFS PHY
+    - arm64: dts: qcom: msm8996: specify UFS core_clk frequencies
+    - arm64: dts: rockchip: Increase VOP clk rate on RK3328
+    - ARM: dts: imx6qdl-kontron-samx6i: move phy reset into phy-node
+    - ARM: dts: imx6qdl-kontron-samx6i: fix PHY reset
+    - ARM: dts: imx6qdl-kontron-samx6i: fix board reset
+    - ARM: dts: imx6qdl-kontron-samx6i: fix PCIe reset polarity
+    - arm64: dts: mediatek: mt7622: fix "emmc" pinctrl mux
+    - arm64: dts: amlogic: gx: correct hdmi clocks
+    - m68k: atari: Fix TT bootup freeze / unexpected (SCU) interrupt messages
+    - x86/xen: Convert comma to semicolon
+    - m68k: cmpxchg: Fix return value for default case in __arch_xchg()
+    - firmware: turris-mox-rwtm: Fix checking return value of
+      wait_for_completion_timeout()
+    - firmware: turris-mox-rwtm: Initialize completion before mailbox
+    - wifi: brcmsmac: LCN PHY code is used for BCM4313 2G-only device
+    - net/smc: Allow SMC-D 1MB DMB allocations
+    - net/smc: set rmb's SG_MAX_SINGLE_ALLOC limitation only when
+      CONFIG_ARCH_NO_SG_CHAIN is defined
+    - selftests/bpf: Check length of recv in test_sockmap
+    - lib: objagg: Fix general protection fault
+    - mlxsw: spectrum_acl_erp: Fix object nesting warning
+    - wifi: cfg80211: fix typo in cfg80211_calculate_bitrate_he()
+    - wifi: cfg80211: handle 2x996 RU allocation in
+      cfg80211_calculate_bitrate_he()
+    - net: fec: Refactor: #define magic constants
+    - net: fec: Fix FEC_ECR_EN1588 being cleared on link-down
+    - ipvs: Avoid unnecessary calls to skb_is_gso_sctp
+    - netfilter: nf_tables: rise cap on SELinux secmark context
+    - perf/x86/intel/pt: Fix pt_topa_entry_for_page() address calculation
+    - perf: Fix perf_aux_size() for greater-than 32-bit size
+    - perf: Prevent passing zero nr_pages to rb_alloc_aux()
+    - qed: Improve the stack space of filter_config()
+    - wifi: virt_wifi: avoid reporting connection success with wrong SSID
+    - gss_krb5: Fix the error handling path for crypto_sync_skcipher_setkey
+    - wifi: virt_wifi: don't use strlen() in const context
+    - bna: adjust 'name' buf size of bna_tcb and bna_ccb structures
+    - selftests: forwarding: devlink_lib: Wait for udev events after reloading
+    - media: dvb-usb: Fix unexpected infinite loop in
+      dvb_usb_read_remote_control()
+    - media: imon: Fix race getting ictx->lock
+    - saa7134: Unchecked i2c_transfer function result fixed
+    - media: uvcvideo: Allow entity-defined get_info and get_cur
+    - media: uvcvideo: Override default flags
+    - media: renesas: vsp1: Fix _irqsave and _irq mix
+    - media: renesas: vsp1: Store RPF partition configuration per RPF instance
+    - leds: trigger: Unregister sysfs attributes before calling deactivate()
+    - perf report: Fix condition in sort__sym_cmp()
+    - drm/etnaviv: fix DMA direction handling for cached RW buffers
+    - drm/qxl: Add check for drm_cvt_mode
+    - mfd: omap-usb-tll: Use struct_size to allocate tll
+    - SUNRPC: avoid soft lockup when transmitting UDP to reachable server.
+    - ext4: avoid writing unitialized memory to disk in EA inodes
+    - sparc64: Fix incorrect function signature and add prototype for
+      prom_cif_init
+    - SUNRPC: Fixup gss_status tracepoint error output
+    - PCI: Fix resource double counting on remove & rescan
+    - Input: qt1050 - handle CHIP_ID reading error
+    - RDMA/mlx4: Fix truncated output warning in mad.c
+    - RDMA/mlx4: Fix truncated output warning in alias_GUID.c
+    - RDMA/rxe: Don't set BTH_ACK_MASK for UC or UD QPs
+    - ASoC: max98088: Check for clk_prepare_enable() error
+    - mtd: make mtd_test.c a separate module
+    - RDMA/device: Return error earlier if port in not valid
+    - Input: elan_i2c - do not leave interrupt disabled on suspend failure
+    - MIPS: Octeron: remove source file executable bit
+    - powerpc/xmon: Fix disassembly CPU feature checks
+    - macintosh/therm_windtunnel: fix module unload.
+    - bnxt_re: Fix imm_data endianness
+    - netfilter: ctnetlink: use helper function to calculate expect ID
+    - pinctrl: core: fix possible memory leak when pinctrl_enable() fails
+    - pinctrl: single: fix possible memory leak when pinctrl_enable() fails
+    - pinctrl: ti: ti-iodelay: Drop if block with always false condition
+    - pinctrl: ti: ti-iodelay: fix possible memory leak when pinctrl_enable()
+      fails
+    - pinctrl: freescale: mxs: Fix refcount of child
+    - fs/nilfs2: remove some unused macros to tame gcc
+    - nilfs2: avoid undefined behavior in nilfs_cnt32_ge macro
+    - rtc: interface: Add RTC offset to alarm after fix-up
+    - tick/broadcast: Make takeover of broadcast hrtimer reliable
+    - net: netconsole: Disable target before netpoll cleanup
+    - af_packet: Handle outgoing VLAN packets without hardware offloading
+    - ipv6: take care of scope when choosing the src addr
+    - char: tpm: Fix possible memory leak in tpm_bios_measurements_open()
+    - media: venus: fix use after free in vdec_close
+    - hfs: fix to initialize fields of hfs_inode_info after hfs_alloc_inode()
+    - drm/gma500: fix null pointer dereference in cdv_intel_lvds_get_modes
+    - drm/gma500: fix null pointer dereference in psb_intel_lvds_get_modes
+    - drm/amd/display: Check for NULL pointer
+    - udf: Avoid using corrupted block bitmap buffer
+    - m68k: amiga: Turn off Warp1260 interrupts during boot
+    - ext4: check dot and dotdot of dx_root before making dir indexed
+    - ext4: make sure the first directory block is not a hole
+    - wifi: mwifiex: Fix interface type change
+    - leds: ss4200: Convert PCIBIOS_* return codes to errnos
+    - tools/memory-model: Fix bug in lock.cat
+    - hwrng: amd - Convert PCIBIOS_* return codes to errnos
+    - PCI: hv: Return zero, not garbage, when reading PCI_INTERRUPT_PIN
+    - binder: fix hang of unregistered readers
+    - scsi: qla2xxx: Return ENOBUFS if sg_cnt is more than one for ELS cmds
+    - f2fs: fix to don't dirty inode for readonly filesystem
+    - clk: davinci: da8xx-cfgchip: Initialize clk_init_data before use
+    - ubi: eba: properly rollback inside self_check_eba
+    - decompress_bunzip2: fix rare decompression failure
+    - kobject_uevent: Fix OOB access within zap_modalias_env()
+    - rtc: cmos: Fix return value of nvmem callbacks
+    - scsi: qla2xxx: During vport delete send async logout explicitly
+    - scsi: qla2xxx: Fix for possible memory corruption
+    - scsi: qla2xxx: Complete command early within lock
+    - scsi: qla2xxx: validate nvme_local_port correctly
+    - perf/x86/intel/pt: Fix topa_entry base length
+    - perf/x86/intel/pt: Fix a topa_entry base address calculation
+    - rtc: isl1208: Fix return value of nvmem callbacks
+    - watchdog/perf: properly initialize the turbo mode timestamp and rearm
+      counter
+    - platform: mips: cpu_hwmon: Disable driver on unsupported hardware
+    - RDMA/iwcm: Fix a use-after-free related to destroying CM IDs
+    - selftests/sigaltstack: Fix ppc64 GCC build
+    - rbd: don't assume rbd_is_lock_owner() for exclusive mappings
+    - drm/panfrost: Mark simple_ondemand governor as softdep
+    - rbd: rename RBD_LOCK_STATE_RELEASING and releasing_wait
+    - rbd: don't assume RBD_LOCK_STATE_LOCKED for exclusive mappings
+    - Bluetooth: btusb: Add RTL8852BE device 0489:e125 to device tables
+    - Bluetooth: btusb: Add Realtek RTL8852BE support ID 0x13d3:0x3591
+    - nilfs2: handle inconsistent state in nilfs_btnode_create_block()
+    - kdb: address -Wformat-security warnings
+    - kdb: Use the passed prompt in kdb_position_cursor()
+    - jfs: Fix array-index-out-of-bounds in diFree
+    - um: time-travel: fix time-travel-start option
+    - libbpf: Fix no-args func prototype BTF dumping syntax
+    - dma: fix call order in dmam_free_coherent
+    - MIPS: SMP-CPS: Fix address for GCR_ACCESS register for CM3 and later
+    - ipv4: Fix incorrect source address in Record Route option
+    - net: bonding: correctly annotate RCU in bond_should_notify_peers()
+    - tipc: Return non-zero value from tipc_udp_addr2str() on error
+    - net: nexthop: Initialize all fields in dumped nexthops
+    - bpf: Fix a segment issue when downgrading gso_size
+    - mISDN: Fix a use after free in hfcmulti_tx()
+    - powerpc: fix a file leak in kvm_vcpu_ioctl_enable_cap()
+    - ASoC: Intel: Convert to new X86 CPU match macros
+    - ASoC: Intel: Move soc_intel_is_foo() helpers to a generic header
+    - ASoC: Intel: use soc_intel_is_byt_cr() only when IOSF_MBI is reachable
+    - nvme-pci: add missing condition check for existence of mapped data
+    - mm: avoid overflows in dirty throttling logic
+    - PCI: rockchip: Make 'ep-gpios' DT property optional
+    - PCI: rockchip: Use GPIOD_OUT_LOW flag while requesting ep_gpio
+    - parport: Convert printk(KERN_<LEVEL> to pr_<level>(
+    - parport: Standardize use of printmode
+    - dev/parport: fix the array out-of-bounds risk
+    - driver core: Cast to (void *) with __force for __percpu pointer
+    - devres: Fix memory leakage caused by driver API devm_free_percpu()
+    - genirq: Allow the PM device to originate from irq domain
+    - irqchip/imx-irqsteer: Constify irq_chip struct
+    - irqchip/imx-irqsteer: Add runtime PM support
+    - irqchip/imx-irqsteer: Handle runtime power management correctly
+    - remoteproc: imx_rproc: ignore mapping vdev regions
+    - remoteproc: imx_rproc: Fix ignoring mapping vdev regions
+    - remoteproc: imx_rproc: Skip over memory region when node value is NULL
+    - drm/nouveau: prime: fix refcount underflow
+    - drm/vmwgfx: Fix overlay when using Screen Targets
+    - net/iucv: fix use after free in iucv_sock_close()
+    - net/mlx5e: Add a check for the return value from mlx5_port_set_eth_ptys
+    - ipv6: fix ndisc_is_useropt() handling for PIO
+    - HID: wacom: Modify pen IDs
+    - protect the fetch of ->fd[fd] in do_dup2() from mispredictions
+    - ALSA: usb-audio: Correct surround channels in UAC1 channel map
+    - net: usb: sr9700: fix uninitialized variable use in sr_mdio_read
+    - netfilter: ipset: Add list flush to cancel_gc
+    - genirq: Allow irq_chip registration functions to take a const irq_chip
+    - irqchip/mbigen: Fix mbigen node address layout
+    - x86/mm: Fix pti_clone_pgtable() alignment assumption
+    - sctp: move hlist_node and hashent out of sctp_ep_common
+    - sctp: Fix null-ptr-deref in reuseport_add_sock().
+    - net: usb: qmi_wwan: fix memory leak for not ip packets
+    - net: linkwatch: use system_unbound_wq
+    - Bluetooth: l2cap: always unlock channel in l2cap_conless_channel()
+    - net: fec: Stop PPS on driver remove
+    - md/raid5: avoid BUG_ON() while continue reshape after reassembling
+    - clocksource/drivers/sh_cmt: Address race condition for clock events
+    - ACPI: battery: create alarm sysfs attribute atomically
+    - ACPI: SBS: manage alarm sysfs attribute through psy core
+    - selftests/bpf: Fix send_signal test with nested CONFIG_PARAVIRT
+    - PCI: Add Edimax Vendor ID to pci_ids.h
+    - udf: prevent integer overflow in udf_bitmap_free_blocks()
+    - wifi: nl80211: don't give key data to userspace
+    - btrfs: fix bitmap leak when loading free space cache on duplicate entry
+    - drm/amdgpu: Fix the null pointer dereference to ras_manager
+    - media: uvcvideo: Ignore empty TS packets
+    - media: uvcvideo: Fix the bandwdith quirk on USB 3.x
+    - jbd2: avoid memleak in jbd2_journal_write_metadata_buffer
+    - s390/sclp: Prevent release of buffer in I/O
+    - SUNRPC: Fix a race to wake a sync task
+    - ext4: fix wrong unit use in ext4_mb_find_by_goal
+    - arm64: cpufeature: Force HWCAP to be based on the sysreg visible to user-
+      space
+    - arm64: Add Neoverse-V2 part
+    - arm64: cputype: Add Cortex-X4 definitions
+    - arm64: cputype: Add Neoverse-V3 definitions
+    - arm64: errata: Add workaround for Arm errata 3194386 and 3312417
+    - [Config] Set ARM64_ERRATUM_3194386=y
+    - arm64: cputype: Add Cortex-X3 definitions
+    - arm64: cputype: Add Cortex-A720 definitions
+    - arm64: cputype: Add Cortex-X925 definitions
+    - arm64: errata: Unify speculative SSBS errata logic
+    - arm64: errata: Expand speculative SSBS workaround
+    - arm64: cputype: Add Cortex-X1C definitions
+    - arm64: cputype: Add Cortex-A725 definitions
+    - arm64: errata: Expand speculative SSBS workaround (again)
+    - i2c: smbus: Don't filter out duplicate alerts
+    - i2c: smbus: Improve handling of stuck alerts
+    - i2c: smbus: Send alert notifications to all devices if source not found
+    - bpf: kprobe: remove unused declaring of bpf_kprobe_override
+    - spi: fsl-lpspi: remove unneeded array
+    - spi: spi-fsl-lpspi: Fix scldiv calculation
+    - drm/client: fix null pointer dereference in drm_client_modeset_probe
+    - ALSA: line6: Fix racy access to midibuf
+    - ALSA: hda: Add HP MP9 G4 Retail System AMS to force connect list
+    - ALSA: hda/hdmi: Yet more pin fix for HP EliteDesk 800 G4
+    - usb: vhci-hcd: Do not drop references before new references are gained
+    - USB: serial: debug: do not echo input by default
+    - usb: gadget: core: Check for unset descriptor
+    - scsi: ufs: core: Fix hba->last_dme_cmd_tstamp timestamp updating logic
+    - tick/broadcast: Move per CPU pointer access into the atomic section
+    - ntp: Clamp maxerror and esterror to operating range
+    - driver core: Fix uevent_show() vs driver detach race
+    - ntp: Safeguard against time_constant overflow
+    - scsi: mpt3sas: Remove scsi_dma_map() error messages
+    - scsi: mpt3sas: Avoid IOMMU page faults on REPORT ZONES
+    - serial: core: check uartclk for zero to avoid divide by zero
+    - genirq/irqdesc: Honor caller provided affinity in alloc_desc()
+    - power: supply: axp288_charger: Fix constant_charge_voltage writes
+    - power: supply: axp288_charger: Round constant_charge_voltage writes down
+    - tracing: Fix overflow in get_free_elt()
+    - x86/mtrr: Check if fixed MTRRs exist before saving them
+    - drm/bridge: analogix_dp: properly handle zero sized AUX transactions
+    - drm/mgag200: Set DDC timeout in milliseconds
+    - Fix gcc 4.9 build issue in 5.4.y
+    - kbuild: Fix '-S -c' in x86 stack protector scripts
+    - netfilter: nf_tables: set element extended ACK reporting support
+    - netfilter: nf_tables: prefer nft_chain_validate
+    - drm/i915/gem: Fix Virtual Memory mapping boundaries calculation
+    - arm64: cpufeature: Fix the visibility of compat hwcaps
+    - media: uvcvideo: Use entity get_cur in uvc_ctrl_set
+    - exec: Fix ToCToU between perm check and set-uid/gid usage
+    - nvme/pci: Add APST quirk for Lenovo N60z laptop
+    - ARM: dts: imx6qdl-kontron-samx6i: fix phy-mode
+    - media: Revert "media: dvb-usb: Fix unexpected infinite loop in
+      dvb_usb_read_remote_control()"
+    - Linux 5.4.282
+  * CVE-2024-26885
+    - bpf: Fix DEVMAP_HASH overflow check on 32-bit arches
+  * Focal update: v5.4.281 upstream stable release (LP: #2076097)
+    - gcc-plugins: Rename last_stmt() for GCC 14+
+    - filelock: Remove locks reliably when fcntl/close race is detected
+    - scsi: qedf: Set qed_slowpath_params to zero before use
+    - ACPI: EC: Abort address space access upon error
+    - ACPI: EC: Avoid returning AE_OK on errors in address space handler
+    - wifi: mac80211: mesh: init nonpeer_pm to active by default in mesh sdata
+    - wifi: mac80211: fix UBSAN noise in ieee80211_prep_hw_scan()
+    - Input: silead - Always support 10 fingers
+    - ila: block BH in ila_output()
+    - kconfig: gconf: give a proper initial state to the Save button
+    - kconfig: remove wrong expr_trans_bool()
+    - fs/file: fix the check in find_next_fd()
+    - mei: demote client disconnect warning on suspend to debug
+    - wifi: cfg80211: wext: add extra SIOCSIWSCAN data check
+    - KVM: PPC: Book3S HV: Prevent UAF in kvm_spapr_tce_attach_iommu_group()
+    - ALSA: hda/realtek: Add more codec ID to no shutup pins list
+    - mips: fix compat_sys_lseek syscall
+    - Input: elantech - fix touchpad state on resume for Lenovo N24
+    - bytcr_rt5640 : inverse jack detect for Archos 101 cesium
+    - ASoC: ti: davinci-mcasp: Set min period size using FIFO config
+    - ASoC: ti: omap-hdmi: Fix too long driver name
+    - can: kvaser_usb: fix return value for hif_usb_send_regout
+    - s390/sclp: Fix sclp_init() cleanup on failure
+    - ALSA: dmaengine_pcm: terminate dmaengine before synchronize
+    - net: usb: qmi_wwan: add Telit FN912 compositions
+    - net: mac802154: Fix racy device stats updates by DEV_STATS_INC() and
+      DEV_STATS_ADD()
+    - powerpc/pseries: Whitelist dtl slub object for copying to userspace
+    - powerpc/eeh: avoid possible crash when edev->pdev changes
+    - scsi: libsas: Fix exp-attached device scan after probe failure scanned in
+      again after probe failed
+    - Bluetooth: hci_core: cancel all works upon hci_unregister_dev()
+    - fs: better handle deep ancestor chains in is_subdir()
+    - spi: imx: Don't expect DMA for i.MX{25,35,50,51,53} cspi devices
+    - selftests/vDSO: fix clang build errors and warnings
+    - hfsplus: fix uninit-value in copy_name
+    - ARM: 9324/1: fix get_user() broken with veneer
+    - ACPI: processor_idle: Fix invalid comparison with insertion sort for latency
+    - drm/amdgpu: Fix signedness bug in sdma_v4_0_process_trap_irq()
+    - net: relax socket state check at accept time.
+    - ocfs2: add bounds checking to ocfs2_check_dir_entry()
+    - jfs: don't walk off the end of ealist
+    - ALSA: hda/realtek: Enable headset mic on Positivo SU C1400
+    - filelock: Fix fcntl/close race recovery compat path
+    - tun: add missing verification for short frame
+    - tap: add missing verification for short frame
+    - Linux 5.4.281
+  * Focal update: v5.4.283 upstream stable release (LP: #2080595) //
+    CVE-2024-45016
+    - netem: fix return value if duplicate enqueue fails
+  * CVE-2024-38630
+    - watchdog: cpu5wdt.c: Fix use-after-free bug caused by cpu5wdt_trigger
+  * CVE-2024-27397
+    - netfilter: nf_tables: use timestamp to check for set element timeout
+  * CVE-2024-26960
+    - mm: swap: fix race between free_swap_and_cache() and swapoff()
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Wed, 09 Oct 2024 15:45:46 +1000
+
+linux-xilinx-zynqmp (5.4.0-1053.57) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1053.57 -proposed tracker (LP: #2082230)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] debian.zynqmp/dkms-versions -- update from kernel-versions
+      (main/s2024.09.02)
+
+  [ Ubuntu: 5.4.0-198.218 ]
+
+  * focal/linux: 5.4.0-198.218 -proposed tracker (LP: #2082232)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] debian.master/dkms-versions -- update from kernel-versions
+      (main/s2024.09.02)
+  * CVE-2024-45016
+    - netem: fix return value if duplicate enqueue fails
+  * CVE-2024-38630
+    - watchdog: cpu5wdt.c: Fix use-after-free bug caused by cpu5wdt_trigger
+  * CVE-2024-27397
+    - netfilter: nf_tables: use timestamp to check for set element timeout
+  * CVE-2024-26960
+    - mm: swap: fix race between free_swap_and_cache() and swapoff()
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Fri, 04 Oct 2024 07:50:02 +1000
+
+linux-xilinx-zynqmp (5.4.0-1052.56) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1052.56 -proposed tracker (LP: #2078203)
+
+  [ Ubuntu: 5.4.0-196.216 ]
+
+  * focal/linux: 5.4.0-196.216 -proposed tracker (LP: #2078205)
+  * CVE-2024-39494
+    - ima: Fix use-after-free on a dentry's dname.name
+  * CVE-2024-42160
+    - f2fs: check validation of fault attrs in f2fs_build_fault_attr()
+    - f2fs: Add inline to f2fs_build_fault_attr() stub
+  * CVE-2024-38570
+    - gfs2: Rename sd_{ glock => kill }_wait
+    - gfs2: Fix potential glock use-after-free on unmount
+  * CVE-2024-42228
+    - drm/amdgpu: Using uninitialized value *size when calling amdgpu_vce_cs_reloc
+  * CVE-2022-48791
+    - scsi: pm80xx: Fix TMF task completion race condition
+    - scsi: pm8001: Fix use-after-free for aborted TMF sas_task
+  * CVE-2024-26787
+    - mmc: mmci_sdmmc: Rename sdmmc_priv struct to sdmmc_idma
+    - mmc: mmci: stm32: use a buffer for unaligned DMA requests
+    - mmc: mmci: stm32: fix DMA API overlapping mappings warning
+  * CVE-2024-27012
+    - netfilter: nf_tables: restore set elements when delete set fails
+  * CVE-2022-48863
+    - mISDN: Fix memory leak in dsp_pipeline_build()
+  * CVE-2021-47188
+    - scsi: ufs: core: Improve SCSI abort handling
+  * CVE-2024-26677
+    - rxrpc: Fix delayed ACKs to not set the reference serial number
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Wed, 04 Sep 2024 11:13:23 +0200
+
+linux-xilinx-zynqmp (5.4.0-1051.55) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1051.55 -proposed tracker (LP: #2075952)
+
+  [ Ubuntu: 5.4.0-195.215 ]
+
+  * focal/linux: 5.4.0-195.215 -proposed tracker (LP: #2075954)
+  * Focal update: v5.4.280 upstream stable release (LP: #2075175)
+    - Compiler Attributes: Add __uninitialized macro
+    - drm/lima: fix shared irq handling on driver remove
+    - media: dvb: as102-fe: Fix as10x_register_addr packing
+    - media: dvb-usb: dib0700_devices: Add missing release_firmware()
+    - IB/core: Implement a limit on UMAD receive List
+    - scsi: qedf: Make qedf_execute_tmf() non-preemptible
+    - drm/amdgpu: Initialize timestamp for some legacy SOCs
+    - drm/amd/display: Skip finding free audio for unknown engine_id
+    - media: dw2102: Don't translate i2c read into write
+    - sctp: prefer struct_size over open coded arithmetic
+    - firmware: dmi: Stop decoding on broken entry
+    - Input: ff-core - prefer struct_size over open coded arithmetic
+    - net: dsa: mv88e6xxx: Correct check for empty list
+    - media: dvb-frontends: tda18271c2dd: Remove casting during div
+    - media: s2255: Use refcount_t instead of atomic_t for num_channels
+    - media: dvb-frontends: tda10048: Fix integer overflow
+    - i2c: i801: Annotate apanel_addr as __ro_after_init
+    - powerpc/64: Set _IO_BASE to POISON_POINTER_DELTA not 0 for CONFIG_PCI=n
+    - orangefs: fix out-of-bounds fsid access
+    - powerpc/xmon: Check cpu id in commands "c#", "dp#" and "dx#"
+    - jffs2: Fix potential illegal address access in jffs2_free_inode
+    - s390/pkey: Wipe sensitive data on failure
+    - tcp: tcp_mark_head_lost is only valid for sack-tcp
+    - tcp: add ece_ack flag to reno sack functions
+    - net: tcp better handling of reordering then loss cases
+    - UPSTREAM: tcp: fix DSACK undo in fast recovery to call tcp_try_to_open()
+    - tcp_metrics: validate source addr length
+    - wifi: wilc1000: fix ies_len type in connect path
+    - bonding: Fix out-of-bounds read in bond_option_arp_ip_targets_set()
+    - selftests: fix OOM in msg_zerocopy selftest
+    - selftests: make order checking verbose in msg_zerocopy selftest
+    - inet_diag: Initialize pad field in struct inet_diag_req_v2
+    - nilfs2: fix inode number range checks
+    - nilfs2: add missing check for inode numbers on directory entries
+    - mm: optimize the redundant loop of mm_update_owner_next()
+    - can: kvaser_usb: Explicitly initialize family in leafimx driver_info struct
+    - fsnotify: Do not generate events for O_PATH file descriptors
+    - Revert "mm/writeback: fix possible divide-by-zero in wb_dirty_limits(),
+      again"
+    - drm/nouveau: fix null pointer dereference in nouveau_connector_get_modes
+    - drm/amdgpu/atomfirmware: silence UBSAN warning
+    - media: dw2102: fix a potential buffer overflow
+    - i2c: pnx: Fix potential deadlock warning from del_timer_sync() call in isr
+    - ALSA: hda/realtek: Enable headset mic of JP-IK LEAP W502 with ALC897
+    - nvme-multipath: find NUMA path only for online numa-node
+    - nilfs2: fix incorrect inode allocation from reserved inodes
+    - filelock: fix potential use-after-free in posix_lock_inode
+    - fs/dcache: Re-use value stored to dentry->d_flags instead of re-reading
+    - vfs: don't mod negative dentry count when on shrinker list
+    - tcp: add TCP_INFO status for failed client TFO
+    - tcp: fix incorrect undo caused by DSACK of TLP retransmit
+    - octeontx2-af: Fix incorrect value output on error path in
+      rvu_check_rsrc_availability()
+    - net: lantiq_etop: add blank line after declaration
+    - net: ethernet: lantiq_etop: fix double free in detach
+    - ppp: reject claimed-as-LCP but actually malformed packets
+    - udp: Set SOCK_RCU_FREE earlier in udp_lib_get_port().
+    - s390: Mark psw in __load_psw_mask() as __unitialized
+    - ARM: davinci: Convert comma to semicolon
+    - octeontx2-af: fix detection of IP layer
+    - USB: serial: option: add Telit generic core-dump composition
+    - USB: serial: option: add Telit FN912 rmnet compositions
+    - USB: serial: option: add Fibocom FM350-GL
+    - USB: serial: option: add support for Foxconn T99W651
+    - USB: serial: option: add Netprisma LCUK54 series modules
+    - USB: serial: option: add Rolling RW350-GL variants
+    - USB: Add USB_QUIRK_NO_SET_INTF quirk for START BP-850k
+    - usb: gadget: configfs: Prevent OOB read/write in usb_string_copy()
+    - USB: core: Fix duplicate endpoint bug by clearing reserved bits in the
+      descriptor
+    - hpet: Support 32-bit userspace
+    - nvmem: meson-efuse: Fix return value of nvmem callbacks
+    - ALSA: hda/realtek: Limit mic boost on VAIO PRO PX
+    - libceph: fix race between delayed_work() and ceph_monc_stop()
+    - SUNRPC: Fix RPC client cleaned up the freed pipefs dentries
+    - tcp: refactor tcp_retransmit_timer()
+    - net: tcp: fix unexcepted socket die when snd_wnd is 0
+    - tcp: use signed arithmetic in tcp_rtx_probe0_timed_out()
+    - tcp: avoid too many retransmit packets
+    - nilfs2: fix kernel bug on rename operation of broken directory
+    - i2c: rcar: bring hardware to known state when probing
+    - Linux 5.4.280
+  * [SRU] UBSAN warnings in bnx2x kernel driver (LP: #2074215) // Focal update:
+    v5.4.280 upstream stable release (LP: #2075175)
+    - bnx2x: Fix multiple UBSAN array-index-out-of-bounds
+  * Focal update: v5.4.279 upstream stable release (LP: #2073621)
+    - wifi: mac80211: mesh: Fix leak of mesh_preq_queue objects
+    - wifi: mac80211: Fix deadlock in ieee80211_sta_ps_deliver_wakeup()
+    - wifi: cfg80211: pmsr: use correct nla_get_uX functions
+    - wifi: iwlwifi: mvm: revert gen2 TX A-MPDU size to 64
+    - wifi: iwlwifi: dbg_ini: move iwl_dbg_tlv_free outside of debugfs ifdef
+    - wifi: iwlwifi: mvm: don't read past the mfuart notifcation
+    - ipv6: sr: block BH in seg6_output_core() and seg6_input_core()
+    - net: sched: sch_multiq: fix possible OOB write in multiq_tune()
+    - vxlan: Fix regression when dropping packets due to invalid src addresses
+    - tcp: count CLOSE-WAIT sockets for TCP_MIB_CURRESTAB
+    - net/mlx5: Stop waiting for PCI if pci channel is offline
+    - net/sched: taprio: always validate TCA_TAPRIO_ATTR_PRIOMAP
+    - ptp: Fix error message on failed pin verification
+    - af_unix: Annotate data-race of sk->sk_state in unix_inq_len().
+    - af_unix: Annotate data-races around sk->sk_state in unix_write_space() and
+      poll().
+    - af_unix: Annotate data-races around sk->sk_state in sendmsg() and recvmsg().
+    - af_unix: Annotate data-races around sk->sk_state in UNIX_DIAG.
+    - af_unix: Annotate data-race of net->unx.sysctl_max_dgram_qlen.
+    - af_unix: Use unix_recvq_full_lockless() in unix_stream_connect().
+    - af_unix: Use skb_queue_len_lockless() in sk_diag_show_rqlen().
+    - af_unix: Annotate data-race of sk->sk_shutdown in sk_diag_fill().
+    - ipv6: fix possible race in __fib6_drop_pcpu_from()
+    - usb: gadget: f_fs: Fix race between aio_cancel() and AIO request complete
+    - ASoC: ti: davinci-mcasp: remove redundant assignment to variable ret
+    - ASoC: ti: davinci-mcasp: remove always zero of davinci_mcasp_get_dt_params
+    - ASoC: ti: davinci-mcasp: Use platform_get_irq_byname_optional
+    - ASoC: ti: davinci-mcasp: Remove legacy dma_request parsing
+    - ASoC: ti: davinci-mcasp: Simplify the configuration parameter handling
+    - ASoC: ti: davinci-mcasp: Handle missing required DT properties
+    - ASoC: ti: davinci-mcasp: Fix race condition during probe
+    - drm/amd/display: Handle Y carry-over in VCP X.Y calculation
+    - serial: sc16is7xx: replace hardcoded divisor value with BIT() macro
+    - serial: sc16is7xx: fix bug in sc16is7xx_set_baud() when using prescaler
+    - selftests/mm: compaction_test: fix incorrect write of zero to nr_hugepages
+    - selftests/mm: conform test to TAP format output
+    - selftests/mm: compaction_test: fix bogus test success on Aarch64
+    - nilfs2: Remove check for PageError
+    - nilfs2: return the mapped address from nilfs_get_page()
+    - nilfs2: fix nilfs_empty_dir() misjudgment and long loop on I/O errors
+    - USB: class: cdc-wdm: Fix CPU lockup caused by excessive log messages
+    - mei: me: release irq in mei_me_pci_resume error path
+    - jfs: xattr: fix buffer overflow for invalid xattr
+    - xhci: Set correct transferred length for cancelled bulk transfers
+    - xhci: Apply reset resume quirk to Etron EJ188 xHCI host
+    - xhci: Apply broken streams quirk to Etron EJ188 xHCI host
+    - scsi: mpt3sas: Avoid test/set_bit() operating in non-allocated memory
+    - Input: try trimming too long modalias strings
+    - SUNRPC: return proper error from gss_wrap_req_priv
+    - gpio: tqmx86: fix typo in Kconfig label
+    - HID: core: remove unnecessary WARN_ON() in implement()
+    - iommu/amd: Fix sysfs leak in iommu init
+    - iommu: Return right value in iommu_sva_bind_device()
+    - HID: logitech-dj: Fix memory leak in logi_dj_recv_switch_to_dj_mode()
+    - liquidio: Adjust a NULL pointer handling path in lio_vf_rep_copy_packet
+    - drm/komeda: check for error-valued pointer
+    - drm/bridge/panel: Fix runtime warning on panel bridge release
+    - tcp: fix race in tcp_v6_syn_recv_sock()
+    - net/mlx5e: Fix features validation check for tunneled UDP (non-VXLAN)
+      packets
+    - Bluetooth: L2CAP: Fix rejecting L2CAP_CONN_PARAM_UPDATE_REQ
+    - netfilter: ipset: Fix race between namespace cleanup and gc in the list:set
+      type
+    - net/ipv6: Fix the RT cache flush via sysctl using a previous delay
+    - ionic: fix use after netif_napi_del()
+    - drivers: core: synchronize really_probe() and dev_uevent()
+    - drm/exynos/vidi: fix memory leak in .get_modes()
+    - drm/exynos: hdmi: report safe 640x480 mode as a fallback when no EDID found
+    - tracing/selftests: Fix kprobe event name test for .isra. functions
+    - vmci: prevent speculation leaks by sanitizing event in event_deliver()
+    - fs/proc: fix softlockup in __read_vmcore
+    - ocfs2: use coarse time for new created files
+    - ocfs2: fix races between hole punching and AIO+DIO
+    - PCI: rockchip-ep: Remove wrong mask on subsys_vendor_id
+    - dmaengine: axi-dmac: fix possible race in remove()
+    - intel_th: pci: Add Granite Rapids support
+    - intel_th: pci: Add Granite Rapids SOC support
+    - intel_th: pci: Add Sapphire Rapids SOC support
+    - intel_th: pci: Add Meteor Lake-S support
+    - intel_th: pci: Add Lunar Lake support
+    - nilfs2: fix potential kernel bug due to lack of writeback flag waiting
+    - tick/nohz_full: Don't abuse smp_call_function_single() in
+      tick_setup_device()
+    - hv_utils: drain the timesync packets on onchannelcallback
+    - hugetlb_encode.h: fix undefined behaviour (34 << 26)
+    - greybus: Fix use-after-free bug in gb_interface_release due to race
+      condition.
+    - usb-storage: alauda: Check whether the media is initialized
+    - i2c: at91: Fix the functionality flags of the slave-only interface
+    - rcutorture: Fix rcu_torture_one_read() pipe_count overflow comment
+    - selftests/bpf: Prevent client connect before server bind in
+      test_tc_tunnel.sh
+    - batman-adv: bypass empty buckets in batadv_purge_orig_ref()
+    - drop_monitor: replace spin_lock by raw_spin_lock
+    - scsi: qedi: Fix crash while reading debugfs attribute
+    - Bluetooth: ath3k: Fix multiple issues reported by checkpatch.pl
+    - powerpc/pseries: Enforce hcall result buffer validity and size
+    - powerpc/io: Avoid clang null pointer arithmetic warnings
+    - usb: misc: uss720: check for incompatible versions of the Belkin F5U002
+    - udf: udftime: prevent overflow in udf_disk_stamp_to_time()
+    - PCI/PM: Avoid D3cold for HP Pavilion 17 PC/1972 PCIe Ports
+    - MIPS: Octeon: Add PCIe link status check
+    - MIPS: Routerboard 532: Fix vendor retry check code
+    - mips: bmips: BCM6358: make sure CBR is correctly set
+    - cipso: fix total option length computation
+    - netrom: Fix a memory leak in nr_heartbeat_expiry()
+    - ipv6: prevent possible NULL deref in fib6_nh_init()
+    - ipv6: prevent possible NULL dereference in rt6_probe()
+    - xfrm6: check ip6_dst_idev() return value in xfrm6_get_saddr()
+    - netns: Make get_net_ns() handle zero refcount net
+    - net/sched: act_api: rely on rcu in tcf_idr_check_alloc
+    - net/sched: act_api: fix possible infinite loop in tcf_idr_check_alloc()
+    - virtio_net: checksum offloading handling fix
+    - netfilter: ipset: Fix suspicious rcu_dereference_protected()
+    - net: usb: rtl8150 fix unintiatilzed variables in rtl8150_get_link_ksettings
+    - regulator: core: Fix modpost error "regulator_get_regmap" undefined
+    - dmaengine: ioatdma: Fix missing kmem_cache_destroy()
+    - ACPICA: Revert "ACPICA: avoid Info: mapping multiple BARs. Your kernel is
+      fine."
+    - drm/radeon: fix UBSAN warning in kv_dpm.c
+    - gcov: add support for GCC 14
+    - i2c: ocores: set IACK bit after core is enabled
+    - ARM: dts: samsung: smdkv310: fix keypad no-autorepeat
+    - ARM: dts: samsung: exynos4412-origen: fix keypad no-autorepeat
+    - ARM: dts: samsung: smdk4412: fix keypad no-autorepeat
+    - arm64: dts: qcom: qcs404: fix bluetooth device address
+    - tracing: Add MODULE_DESCRIPTION() to preemptirq_delay_test
+    - Revert "kheaders: substituting --sort in archive creation"
+    - kheaders: explicitly define file modes for archived headers
+    - perf/core: Fix missing wakeup when waiting for context reference
+    - PCI: Add PCI_ERROR_RESPONSE and related definitions
+    - x86/amd_nb: Check for invalid SMN reads
+    - iio: dac: ad5592r-base: Replace indio_dev->mlock with own device lock
+    - iio: dac: ad5592r: un-indent code-block for scale read
+    - iio: dac: ad5592r: fix temperature channel scaling value
+    - pinctrl: fix deadlock in create_pinctrl() when handling -EPROBE_DEFER
+    - pinctrl: rockchip: fix pinmux bits for RK3328 GPIO2-B pins
+    - pinctrl: rockchip: fix pinmux bits for RK3328 GPIO3-B pins
+    - pinctrl: rockchip: fix pinmux reset in rockchip_pmx_set
+    - drm/amdgpu: fix UBSAN warning in kv_dpm.c
+    - netfilter: nf_tables: validate family when identifying table via handle
+    - ASoC: fsl-asoc-card: set priv->pdev before using it
+    - net: dsa: microchip: fix initial port flush problem
+    - net: phy: mchp: Add support for LAN8814 QUAD PHY
+    - net: phy: micrel: add Microchip KSZ 9477 to the device table
+    - sparc: fix old compat_sys_select()
+    - parisc: use correct compat recv/recvfrom syscalls
+    - netfilter: nf_tables: fully validate NFT_DATA_VALUE on store to data
+      registers
+    - drm/panel: ilitek-ili9881c: Fix warning with GPIO controllers that sleep
+    - mtd: partitions: redboot: Added conversion of operands to a larger type
+    - net/iucv: Avoid explicit cpumask var allocation on stack
+    - net/dpaa2: Avoid explicit cpumask var allocation on stack
+    - ALSA: emux: improve patch ioctl data validation
+    - media: dvbdev: Initialize sbuf
+    - soc: ti: wkup_m3_ipc: Send NULL dummy message instead of pointer message
+    - nvme: fixup comment for nvme RDMA Provider Type
+    - gpio: davinci: Validate the obtained number of IRQs
+    - x86: stop playing stack games in profile_pc()
+    - mmc: sdhci-pci: Convert PCIBIOS_* return codes to errnos
+    - mmc: sdhci: Do not invert write-protect twice
+    - mmc: sdhci: Do not lock spinlock around mmc_gpio_get_ro()
+    - iio: adc: ad7266: Fix variable checking bug
+    - iio: chemical: bme680: Fix pressure value output
+    - iio: chemical: bme680: Fix calibration data variable
+    - iio: chemical: bme680: Fix overflows in compensate() functions
+    - iio: chemical: bme680: Fix sensor data read operation
+    - net: usb: ax88179_178a: improve link status logs
+    - usb: gadget: printer: SS+ support
+    - usb: musb: da8xx: fix a resource leak in probe()
+    - usb: atm: cxacru: fix endpoint checking in cxacru_bind()
+    - tty: mcf: MCF54418 has 10 UARTS
+    - net: can: j1939: Initialize unused data in j1939_send_one()
+    - net: can: j1939: recover socket queue on CAN bus error during BAM
+      transmission
+    - net: can: j1939: enhanced error handling for tightly received RTS messages
+      in xtp_rx_rts_session_new
+    - csky, hexagon: fix broken sys_sync_file_range
+    - hexagon: fix fadvise64_64 calling conventions
+    - drm/nouveau/dispnv04: fix null pointer dereference in nv17_tv_get_ld_modes
+    - drm/nouveau/dispnv04: fix null pointer dereference in nv17_tv_get_hd_modes
+    - batman-adv: Don't accept TT entries for out-of-spec VIDs
+    - ata: libata-core: Fix double free on error
+    - ftruncate: pass a signed offset
+    - mtd: spinand: macronix: Add support for serial NAND flash
+    - pwm: stm32: Refuse too small period requests
+    - nfs: Leave pages in the pagecache if readpage failed
+    - ARM: dts: rockchip: rk3066a: add #sound-dai-cells to hdmi node
+    - arm64: dts: rockchip: Add sound-dai-cells for RK3368
+    - Linux 5.4.279
+  * CVE-2024-26921
+    - skbuff: introduce skb_expand_head()
+    - skb_expand_head() adjust skb->truesize incorrectly
+    - inet: inet_defrag: prevent sk release while still in use
+  * CVE-2024-26929
+    - scsi: qla2xxx: Fix double free of fcport
+  * CVE-2024-39484
+    - mmc: davinci: Don't strip remove function when driver is builtin
+  * CVE-2024-36901
+    - ipv6: prevent NULL dereference in ip6_output()
+  * CVE-2024-26830
+    - i40e: Refactoring VF MAC filters counting to make more reliable
+    - i40e: Fix MAC address setting for a VF via Host/VM
+    - i40e: Do not allow untrusted VF to remove administratively set MAC
+  * CVE-2024-24860
+    - Bluetooth: Fix atomicity violation in {min, max}_key_size_set
+  * CVE-2023-52760
+    - gfs2: Fix slab-use-after-free in gfs2_qd_dealloc
+  * CVE-2024-2201
+    - [Config] Set SPECTRE_BHI_ON=y
+  * CVE-2023-52629
+    - sh: push-switch: Reorder cleanup operations to avoid use-after-free bug
+  * CVE-2021-46926
+    - ALSA: hda: intel-sdw-acpi: harden detection of controller
+
+ -- Roger Knecht <roger.knecht@canonical.com>  Wed, 14 Aug 2024 14:48:45 +0200
+
+linux-xilinx-zynqmp (5.4.0-1050.54) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1050.54 -proposed tracker (LP: #2075802)
+
+  [ Ubuntu: 5.4.0-193.213 ]
+
+  * focal/linux: 5.4.0-193.213 -proposed tracker (LP: #2075804)
+  * CVE-2024-26921
+    - skbuff: introduce skb_expand_head()
+    - skb_expand_head() adjust skb->truesize incorrectly
+    - inet: inet_defrag: prevent sk release while still in use
+  * CVE-2024-26929
+    - scsi: qla2xxx: Fix double free of fcport
+  * CVE-2024-39484
+    - mmc: davinci: Don't strip remove function when driver is builtin
+  * CVE-2024-36901
+    - ipv6: prevent NULL dereference in ip6_output()
+  * CVE-2024-26830
+    - i40e: Refactoring VF MAC filters counting to make more reliable
+    - i40e: Fix MAC address setting for a VF via Host/VM
+    - i40e: Do not allow untrusted VF to remove administratively set MAC
+  * CVE-2024-24860
+    - Bluetooth: Fix atomicity violation in {min, max}_key_size_set
+  * CVE-2023-52760
+    - gfs2: Fix slab-use-after-free in gfs2_qd_dealloc
+  * CVE-2024-2201
+    - [Config] Set SPECTRE_BHI_ON=y
+  * CVE-2023-52629
+    - sh: push-switch: Reorder cleanup operations to avoid use-after-free bug
+  * CVE-2021-46926
+    - ALSA: hda: intel-sdw-acpi: harden detection of controller
+
+ -- Roger Knecht <roger.knecht@canonical.com>  Thu, 08 Aug 2024 13:10:06 +0200
+
+linux-xilinx-zynqmp (5.4.0-1049.53) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1049.53 -proposed tracker (LP: #2072303)
+
+  [ Ubuntu: 5.4.0-192.212 ]
+
+  * focal/linux: 5.4.0-192.212 -proposed tracker (LP: #2072305)
+  * Focal update: v5.4.278 upstream stable release (LP: #2071668)
+    - x86/tsc: Trust initial offset in architectural TSC-adjust MSRs
+    - speakup: Fix sizeof() vs ARRAY_SIZE() bug
+    - ring-buffer: Fix a race between readers and resize checks
+    - net: smc91x: Fix m68k kernel compilation for ColdFire CPU
+    - nilfs2: fix unexpected freezing of nilfs_segctor_sync()
+    - nilfs2: fix potential hang in nilfs_detach_log_writer()
+    - wifi: cfg80211: fix the order of arguments for trace events of the tx_rx_evt
+      class
+    - net: usb: qmi_wwan: add Telit FN920C04 compositions
+    - drm/amd/display: Set color_mgmt_changed to true on unsuspend
+    - ASoC: rt5645: Fix the electric noise due to the CBJ contacts floating
+    - ASoC: dt-bindings: rt5645: add cbj sleeve gpio property
+    - ASoC: da7219-aad: fix usage of device_get_named_child_node()
+    - drm/amdkfd: Flush the process wq before creating a kfd_process
+    - nvme: find numa distance only if controller has valid numa id
+    - openpromfs: finish conversion to the new mount API
+    - crypto: bcm - Fix pointer arithmetic
+    - firmware: raspberrypi: Use correct device for DMA mappings
+    - ecryptfs: Fix buffer size for tag 66 packet
+    - nilfs2: fix out-of-range warning
+    - parisc: add missing export of __cmpxchg_u8()
+    - crypto: ccp - drop platform ifdef checks
+    - s390/cio: fix tracepoint subchannel type field
+    - jffs2: prevent xattr node from overflowing the eraseblock
+    - null_blk: Fix missing mutex_destroy() at module removal
+    - md: fix resync softlockup when bitmap size is less than array size
+    - wifi: ath10k: poll service ready message before failing
+    - x86/boot: Ignore relocations in .notes sections in walk_relocs() too
+    - qed: avoid truncating work queue length
+    - scsi: ufs: qcom: Perform read back after writing reset bit
+    - scsi: ufs: cdns-pltfrm: Perform read back after writing HCLKDIV
+    - scsi: ufs: core: Perform read back after disabling interrupts
+    - scsi: ufs: core: Perform read back after disabling UIC_COMMAND_COMPL
+    - irqchip/alpine-msi: Fix off-by-one in allocation error path
+    - ACPI: disable -Wstringop-truncation
+    - cpufreq: Reorganize checks in cpufreq_offline()
+    - cpufreq: Split cpufreq_offline()
+    - cpufreq: Rearrange locking in cpufreq_remove_dev()
+    - cpufreq: exit() callback is optional
+    - scsi: libsas: Fix the failure of adding phy with zero-address to port
+    - scsi: hpsa: Fix allocation size for Scsi_Host private data
+    - x86/purgatory: Switch to the position-independent small code model
+    - wifi: ath10k: Fix an error code problem in
+      ath10k_dbg_sta_write_peer_debug_trigger()
+    - wifi: ath10k: populate board data for WCN3990
+    - tcp: minor optimization in tcp_add_backlog()
+    - tcp: fix a signed-integer-overflow bug in tcp_add_backlog()
+    - tcp: avoid premature drops in tcp_add_backlog()
+    - macintosh/via-macii: Fix "BUG: sleeping function called from invalid
+      context"
+    - wifi: carl9170: add a proper sanity check for endpoints
+    - wifi: ar5523: enable proper endpoint verification
+    - sh: kprobes: Merge arch_copy_kprobe() into arch_prepare_kprobe()
+    - Revert "sh: Handle calling csum_partial with misaligned data"
+    - HID: intel-ish-hid: ipc: Add check for pci_alloc_irq_vectors
+    - scsi: bfa: Ensure the copied buf is NUL terminated
+    - scsi: qedf: Ensure the copied buf is NUL terminated
+    - wifi: mwl8k: initialize cmd->addr[] properly
+    - usb: aqc111: stop lying about skb->truesize
+    - net: usb: sr9700: stop lying about skb->truesize
+    - m68k: Fix spinlock race in kernel thread creation
+    - m68k: mac: Fix reboot hang on Mac IIci
+    - net: ethernet: cortina: Locking fixes
+    - af_unix: Fix data races in unix_release_sock/unix_stream_sendmsg
+    - net: usb: smsc95xx: stop lying about skb->truesize
+    - net: openvswitch: fix overwriting ct original tuple for ICMPv6
+    - ipv6: sr: add missing seg6_local_exit
+    - ipv6: sr: fix incorrect unregister order
+    - ipv6: sr: fix invalid unregister error path
+    - drm/amd/display: Fix potential index out of bounds in color transformation
+      function
+    - mtd: rawnand: hynix: fixed typo
+    - fbdev: shmobile: fix snprintf truncation
+    - drm/mediatek: Add 0 size check to mtk_drm_gem_obj
+    - powerpc/fsl-soc: hide unused const variable
+    - fbdev: sisfb: hide unused variables
+    - media: ngene: Add dvb_ca_en50221_init return value check
+    - media: radio-shark2: Avoid led_names truncations
+    - platform/x86: wmi: Make two functions static
+    - fbdev: sh7760fb: allow modular build
+    - drm/arm/malidp: fix a possible null pointer dereference
+    - ASoC: tracing: Export SND_SOC_DAPM_DIR_OUT to its value
+    - drm/panel: simple: Add missing Innolux G121X1-L03 format, flags, connector
+    - RDMA/hns: Use complete parentheses in macros
+    - x86/insn: Fix PUSH instruction in x86 instruction decoder opcode map
+    - ext4: avoid excessive credit estimate in ext4_tmpfile()
+    - sunrpc: removed redundant procp check
+    - SUNRPC: Fix gss_free_in_token_pages()
+    - selftests/kcmp: Make the test output consistent and clear
+    - selftests/kcmp: remove unused open mode
+    - RDMA/IPoIB: Fix format truncation compilation errors
+    - netrom: fix possible dead-lock in nr_rt_ioctl()
+    - af_packet: do not call packet_read_pending() from tpacket_destruct_skb()
+    - sched/topology: Don't set SD_BALANCE_WAKE on cpuset domain relax
+    - sched/fair: Allow disabling sched_balance_newidle with
+      sched_relax_domain_level
+    - greybus: lights: check return of get_channel_from_mode
+    - soundwire: cadence/intel: simplify PDI/port mapping
+    - soundwire: intel: don't filter out PDI0/1
+    - soundwire: cadence_master: improve PDI allocation
+    - soundwire: cadence: fix invalid PDI offset
+    - dmaengine: idma64: Add check for dma_set_max_seg_size
+    - firmware: dmi-id: add a release callback function
+    - serial: max3100: Lock port->lock when calling uart_handle_cts_change()
+    - serial: max3100: Update uart_driver_registered on driver removal
+    - serial: max3100: Fix bitwise types
+    - greybus: arche-ctrl: move device table to its right location
+    - iio: pressure: dps310: support negative temperature values
+    - microblaze: Remove gcc flag for non existing early_printk.c file
+    - microblaze: Remove early printk call from cpuinfo-static.c
+    - usb: gadget: u_audio: Clear uac pointer when freed.
+    - stm class: Fix a double free in stm_register_device()
+    - ppdev: Remove usage of the deprecated ida_simple_xx() API
+    - ppdev: Add an error check in register_device
+    - extcon: max8997: select IRQ_DOMAIN instead of depending on it
+    - f2fs: fix to release node block count in error path of f2fs_new_node_page()
+    - serial: sh-sci: protect invalidating RXDMA on shutdown
+    - libsubcmd: Fix parse-options memory leak
+    - Input: ims-pcu - fix printf string overflow
+    - Input: pm8xxx-vibrator - correct VIB_MAX_LEVELS calculation
+    - drm/msm/dpu: Always flush the slave INTF on the CTL
+    - um: Fix return value in ubd_init()
+    - um: Add winch to winch_handlers before registering winch IRQ
+    - media: stk1160: fix bounds checking in stk1160_copy_video()
+    - scsi: qla2xxx: Replace all non-returning strlcpy() with strscpy()
+    - powerpc/pseries: Add failure related checks for h_get_mpp and h_get_ppp
+    - um: Fix the -Wmissing-prototypes warning for __switch_mm
+    - media: cec: cec-adap: always cancel work in cec_transmit_msg_fh
+    - media: cec: cec-api: add locking in cec_release()
+    - null_blk: Fix the WARNING: modpost: missing MODULE_DESCRIPTION()
+    - x86/kconfig: Select ARCH_WANT_FRAME_POINTERS again when
+      UNWINDER_FRAME_POINTER=y
+    - [Config] Update CONFIG_ARCH_WANT_FRAME_POINTERS
+    - nfc: nci: Fix uninit-value in nci_rx_work
+    - sunrpc: fix NFSACL RPC retry on soft mount
+    - ipv6: sr: fix memleak in seg6_hmac_init_algo
+    - params: lift param_set_uint_minmax to common code
+    - tcp: Fix shift-out-of-bounds in dctcp_update_alpha().
+    - openvswitch: Set the skbuff pkt_type for proper pmtud support.
+    - arm64: asm-bug: Add .align 2 to the end of __BUG_ENTRY
+    - virtio: delete vq in vp_find_vqs_msix() when request_irq() fails
+    - net: fec: avoid lock evasion when reading pps_enable
+    - nfc: nci: Fix kcov check in nci_rx_work()
+    - nfc: nci: Fix handling of zero-length payload packets in nci_rx_work()
+    - netfilter: nfnetlink_queue: acquire rcu_read_lock() in
+      instance_destroy_rcu()
+    - spi: Don't mark message DMA mapped when no transfer in it is
+    - nvmet: fix ns enable/disable possible hang
+    - net/mlx5e: Use rx_missed_errors instead of rx_dropped for reporting buffer
+      exhaustion
+    - dma-buf/sw-sync: don't enable IRQ from sync_print_obj()
+    - enic: Validate length of nl attributes in enic_set_vf_port
+    - smsc95xx: remove redundant function arguments
+    - smsc95xx: use usbnet->driver_priv
+    - net: usb: smsc95xx: fix changing LED_SEL bit value updated from EEPROM
+    - net:fec: Add fec_enet_deinit()
+    - netfilter: tproxy: bail out if IP has been disabled on the device
+    - kconfig: fix comparison to constant symbols, 'm', 'n'
+    - spi: stm32: Don't warn about spurious interrupts
+    - ipvlan: Dont Use skb->sk in ipvlan_process_v{4,6}_outbound
+    - ALSA: timer: Set lower bound of start tick time
+    - genirq/cpuhotplug, x86/vector: Prevent vector leak during CPU offline
+    - SUNRPC: Fix loop termination condition in gss_free_in_token_pages()
+    - binder: fix max_thread type inconsistency
+    - mmc: core: Do not force a retune before RPMB switch
+    - io_uring: fail NOP if non-zero op flags is passed in
+    - afs: Don't cross .backup mountpoint from backup volume
+    - nilfs2: fix use-after-free of timer for log writer thread
+    - vxlan: Fix regression when dropping packets due to invalid src addresses
+    - x86/mm: Remove broken vsyscall emulation code from the page fault code
+    - f2fs: fix to do sanity check on i_xattr_nid in sanity_check_inode()
+    - media: lgdt3306a: Add a check against null-pointer-def
+    - drm/amdgpu: add error handle to avoid out-of-bounds
+    - ata: pata_legacy: make legacy_exit() work again
+    - ACPI: resource: Do IRQ override on TongFang GXxHRXx and GMxHGxx
+    - arm64: tegra: Correct Tegra132 I2C alias
+    - md/raid5: fix deadlock that raid5d() wait for itself to clear
+      MD_SB_CHANGE_PENDING
+    - wifi: rtl8xxxu: Fix the TX power of RTL8192CU, RTL8723AU
+    - arm64: dts: hi3798cv200: fix the size of GICR
+    - media: mc: mark the media devnode as registered from the, start
+    - media: mxl5xx: Move xpt structures off stack
+    - media: v4l2-core: hold videodev_lock until dev reg, finishes
+    - fbdev: savage: Handle err return when savagefb_check_var failed
+    - KVM: arm64: Allow AArch32 PSTATE.M to be restored as System mode
+    - crypto: ecrdsa - Fix module auto-load on add_key
+    - crypto: qat - Fix ADF_DEV_RESET_SYNC memory leak
+    - net/ipv6: Fix route deleting failure when metric equals 0
+    - net/9p: fix uninit-value in p9_client_rpc()
+    - intel_th: pci: Add Meteor Lake-S CPU support
+    - sparc64: Fix number of online CPUs
+    - kdb: Fix buffer overflow during tab-complete
+    - kdb: Use format-strings rather than '\0' injection in kdb_read()
+    - kdb: Fix console handling when editing and tab-completing commands
+    - kdb: Merge identical case statements in kdb_read()
+    - kdb: Use format-specifiers rather than memset() for padding in kdb_read()
+    - net: fix __dst_negative_advice() race
+    - xsk: validate user input for XDP_{UMEM|COMPLETION}_FILL_RING
+    - sparc: move struct termio to asm/termios.h
+    - ext4: fix mb_cache_entry's e_refcnt leak in ext4_xattr_block_cache_find()
+    - s390/ap: Fix crash in AP internal function modify_bitmap()
+    - nfs: fix undefined behavior in nfs_block_bits()
+    - Linux 5.4.278
+  * CVE-2024-27019
+    - netfilter: nf_tables: restrict tunnel object to NFPROTO_NETDEV
+    - netfilter: nf_tables: Fix potential data-race in __nft_obj_type_get()
+  * CVE-2024-26886
+    - Bluetooth: af_bluetooth: Fix deadlock
+  * CVE-2023-52752
+    - smb: client: fix use-after-free bug in cifs_debug_data_proc_show()
+  * CVE-2022-48674
+    - erofs: fix pcluster use-after-free on UP platforms
+  * Focal update: v5.4.277 upstream stable release (LP: #2070179)
+    - pinctrl: core: handle radix_tree_insert() errors in
+      pinctrl_register_one_pin()
+    - ext4: fix bug_on in __es_tree_search
+    - Revert "selftests: mm: fix map_hugetlb failure on 64K page size systems"
+    - Revert "net: bcmgenet: use RGMII loopback for MAC reset"
+    - net: bcmgenet: keep MAC in reset until PHY is up
+    - net: bcmgenet: synchronize EXT_RGMII_OOB_CTRL access
+    - net: bcmgenet: synchronize use of bcmgenet_set_rx_mode()
+    - net: bcmgenet: synchronize UMAC_CMD access
+    - smb: client: fix potential OOBs in smb2_parse_contexts()
+    - arm64: dts: qcom: Fix 'interrupt-map' parent address cells
+    - btrfs: add missing mutex_unlock in btrfs_relocate_sys_chunks()
+    - drm/amdgpu: Fix possible NULL dereference in
+      amdgpu_ras_query_error_status_helper()
+    - usb: typec: ucsi: displayport: Fix potential deadlock
+    - serial: kgdboc: Fix NMI-safety problems from keyboard reset code
+    - docs: kernel_include.py: Cope with docutils 0.21
+    - Linux 5.4.277
+  * Focal update: v5.4.276 upstream stable release (LP: #2069758)
+    - dmaengine: pl330: issue_pending waits until WFP state
+    - dmaengine: Revert "dmaengine: pl330: issue_pending waits until WFP state"
+    - wifi: nl80211: don't free NULL coalescing rule
+    - pinctrl: core: delete incorrect free in pinctrl_enable()
+    - pinctrl: mediatek: Check gpio pin number and use binary search in
+      mtk_hw_pin_field_lookup()
+    - pinctrl: mediatek: Supporting driving setting without mapping current to
+      register value
+    - pinctrl: mediatek: Refine mtk_pinconf_get() and mtk_pinconf_set()
+    - pinctrl: mediatek: Refine mtk_pinconf_get()
+    - pinctrl: mediatek: Backward compatible to previous Mediatek's bias-pull
+      usage
+    - pinctrl: mediatek: remove shadow variable declaration
+    - pinctrl: mediatek: paris: Fix PIN_CONFIG_BIAS_* readback
+    - pinctrl: mediatek: paris: Rework mtk_pinconf_{get,set} switch/case logic
+    - pinctrl: mediatek: paris: Rework support for
+      PIN_CONFIG_{INPUT,OUTPUT}_ENABLE
+    - sunrpc: add a struct rpc_stats arg to rpc_create_args
+    - nfs: expose /proc/net/sunrpc/nfs in net namespaces
+    - nfs: make the rpc_stat per net namespace
+    - nfs: Handle error of rpc_proc_register() in nfs_net_init().
+    - power: rt9455: hide unused rt9455_boost_voltage_values
+    - pinctrl: devicetree: fix refcount leak in pinctrl_dt_to_map()
+    - s390/mm: Fix storage key clearing for guest huge pages
+    - s390/mm: Fix clearing storage keys for huge pages
+    - bna: ensure the copied buf is NUL terminated
+    - nsh: Restore skb->{protocol,data,mac_header} for outer header in
+      nsh_gso_segment().
+    - net l2tp: drop flow hash on forward
+    - net: qede: use return from qede_parse_flow_attr() for flow_spec
+    - net: dsa: mv88e6xxx: Add number of MACs in the ATU
+    - net: dsa: mv88e6xxx: Fix number of databases for 88E6141 / 88E6341
+    - net: bridge: fix multicast-to-unicast with fraglist GSO
+    - tipc: fix a possible memleak in tipc_buf_append
+    - clk: sunxi-ng: h6: Reparent CPUX during PLL CPUX rate change
+    - scsi: lpfc: Update lpfc_ramp_down_queue_handler() logic
+    - gfs2: Fix invalid metadata access in punch_hole
+    - wifi: mac80211: fix ieee80211_bss_*_flags kernel-doc
+    - wifi: cfg80211: fix rdev_dump_mpp() arguments order
+    - net: mark racy access on sk->sk_rcvbuf
+    - scsi: bnx2fc: Remove spin_lock_bh while releasing resources after upload
+    - ALSA: line6: Zero-initialize message buffers
+    - net: bcmgenet: Reset RBUF on first open
+    - ata: sata_gemini: Check clk_enable() result
+    - firewire: ohci: mask bus reset interrupts between ISR and bottom half
+    - tools/power turbostat: Fix added raw MSR output
+    - tools/power turbostat: Fix Bzy_MHz documentation typo
+    - btrfs: make btrfs_clear_delalloc_extent() free delalloc reserve
+    - btrfs: always clear PERTRANS metadata during commit
+    - scsi: target: Fix SELinux error when systemd-modules loads the target module
+    - gpu: host1x: Do not setup DMA for virtual devices
+    - MIPS: scall: Save thread_info.syscall unconditionally on entry
+    - selftests: timers: Fix valid-adjtimex signed left-shift undefined behavior
+    - fs/9p: only translate RWX permissions for plain 9P2000
+    - fs/9p: translate O_TRUNC into OTRUNC
+    - 9p: explicitly deny setlease attempts
+    - gpio: wcove: Use -ENOTSUPP consistently
+    - gpio: crystalcove: Use -ENOTSUPP consistently
+    - clk: Don't hold prepare_lock when calling kref_put()
+    - fs/9p: drop inodes immediately on non-.L too
+    - net:usb:qmi_wwan: support Rolling modules
+    - pinctrl: mediatek: Fix fallback call path
+    - xfrm: Preserve vlan tags for transport mode software GRO
+    - tcp: defer shutdown(SEND_SHUTDOWN) for TCP_SYN_RECV sockets
+    - tcp: Use refcount_inc_not_zero() in tcp_twsk_unique().
+    - Bluetooth: Fix use-after-free bugs caused by sco_sock_timeout
+    - Bluetooth: l2cap: fix null-ptr-deref in l2cap_chan_timeout
+    - rtnetlink: Correct nested IFLA_VF_VLAN_LIST attribute validation
+    - phonet: fix rtm_phonet_notify() skb allocation
+    - net: bridge: fix corrupted ethernet header on multicast-to-unicast
+    - ipv6: fib6_rules: avoid possible NULL dereference in fib6_rule_action()
+    - net: qede: sanitize 'rc' in qede_add_tc_flower_fltr()
+    - net: qede: use return from qede_parse_flow_attr() for flower
+    - firewire: nosy: ensure user_length is taken into account when fetching
+      packet contents
+    - usb: gadget: composite: fix OS descriptors w_value logic
+    - usb: gadget: f_fs: Fix a race condition when processing setup packets.
+    - tipc: fix UAF in error path
+    - dyndbg: fix old BUG_ON in >control parser
+    - drm/vmwgfx: Fix invalid reads in fence signaled events
+    - net: fix out-of-bounds access in ops_init
+    - regulator: core: fix debugfs creation regression
+    - pinctrl: mediatek: Fix fallback behavior for bias_set_combo
+    - pinctrl: mediatek: Fix some off by one bugs
+    - pinctrl: mediatek: remove set but not used variable 'e'
+    - pinctrl: mediatek: paris: Fix PIN_CONFIG_INPUT_SCHMITT_ENABLE readback
+    - Linux 5.4.276
+  * Freezing user space processes failed after 20.008 seconds (1 tasks refusing
+    to freeze, wq_busy=0) (LP: #2061091)
+    - ALSA: Fix deadlocks with kctl removals at disconnection
+  * CVE-2024-36016
+    - tty: n_gsm: fix possible out-of-bounds in gsm0_receive()
+  * CVE-2022-48655
+    - firmware: arm_scmi: Harden accesses to the reset domains
+  * CVE-2024-26907
+    - RDMA/mlx5: Fix fortify source warning while accessing Eth segment
+  * CVE-2024-26585
+    - tls: fix race between tx work scheduling and socket close
+  * CVE-2024-26584
+    - net: tls: handle backlogging of crypto requests
+  * CVE-2024-26583
+    - net/tls: Replace TLS_RX_SYNC_RUNNING with RCU
+    - net/tls: Fix use-after-free after the TLS device goes down and up
+    - tls: splice_read: fix record type check
+    - tls splice: remove inappropriate flags checking for MSG_PEEK
+    - tls: splice_read: fix accessing pre-processed records
+    - tls: Fix context leak on tls_device_down
+    - net/tls: Check for errors in tls_device_init
+    - net/tls: Remove the context from the list in tls_device_down
+    - net/tls: pass context to tls_device_decrypted()
+    - net/tls: Perform immediate device ctx cleanup when possible
+    - net/tls: Multi-threaded calls to TX tls_dev_del
+    - net: tls: avoid discarding data on record close
+    - tls: rx: don't store the record type in socket context
+    - tls: rx: don't store the decryption status in socket context
+    - tls: rx: don't issue wake ups when data is decrypted
+    - tls: rx: refactor decrypt_skb_update()
+    - tls: hw: rx: use return value of tls_device_decrypted() to carry status
+    - tls: rx: drop unnecessary arguments from tls_setup_from_iter()
+    - tls: rx: don't report text length from the bowels of decrypt
+    - tls: rx: wrap decryption arguments in a structure
+    - tls: rx: factor out writing ContentType to cmsg
+    - tls: rx: don't track the async count
+    - tls: rx: assume crypto always calls our callback
+    - tls: rx: use async as an in-out argument
+    - tls: decrement decrypt_pending if no async completion will be called
+    - net: tls: fix async vs NIC crypto offload
+    - tls: rx: simplify async wait
+    - tls: extract context alloc/initialization out of tls_set_sw_offload
+    - net: tls: factor out tls_*crypt_async_wait()
+    - tls: fix race between async notify and socket close
+
+ -- Guoqing Jiang <guoqing.jiang@canonical.com>  Fri, 19 Jul 2024 11:03:17 +0800
+
+linux-xilinx-zynqmp (5.4.0-1048.52) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1048.52 -proposed tracker (LP: #2072106)
+
+  [ Ubuntu: 5.4.0-190.210 ]
+
+  * focal/linux: 5.4.0-190.210 -proposed tracker (LP: #2072108)
+  * CVE-2024-36016
+    - tty: n_gsm: fix possible out-of-bounds in gsm0_receive()
+  * CVE-2022-48655
+    - firmware: arm_scmi: Harden accesses to the reset domains
+  * CVE-2024-26907
+    - RDMA/mlx5: Fix fortify source warning while accessing Eth segment
+  * CVE-2024-26585
+    - tls: fix race between tx work scheduling and socket close
+  * CVE-2024-26584
+    - net: tls: handle backlogging of crypto requests
+  * CVE-2024-26583
+    - net/tls: Replace TLS_RX_SYNC_RUNNING with RCU
+    - net/tls: Fix use-after-free after the TLS device goes down and up
+    - tls: splice_read: fix record type check
+    - tls splice: remove inappropriate flags checking for MSG_PEEK
+    - tls: splice_read: fix accessing pre-processed records
+    - tls: Fix context leak on tls_device_down
+    - net/tls: Check for errors in tls_device_init
+    - net/tls: Remove the context from the list in tls_device_down
+    - net/tls: pass context to tls_device_decrypted()
+    - net/tls: Perform immediate device ctx cleanup when possible
+    - net/tls: Multi-threaded calls to TX tls_dev_del
+    - net: tls: avoid discarding data on record close
+    - tls: rx: don't store the record type in socket context
+    - tls: rx: don't store the decryption status in socket context
+    - tls: rx: don't issue wake ups when data is decrypted
+    - tls: rx: refactor decrypt_skb_update()
+    - tls: hw: rx: use return value of tls_device_decrypted() to carry status
+    - tls: rx: drop unnecessary arguments from tls_setup_from_iter()
+    - tls: rx: don't report text length from the bowels of decrypt
+    - tls: rx: wrap decryption arguments in a structure
+    - tls: rx: factor out writing ContentType to cmsg
+    - tls: rx: don't track the async count
+    - tls: rx: assume crypto always calls our callback
+    - tls: rx: use async as an in-out argument
+    - tls: decrement decrypt_pending if no async completion will be called
+    - net: tls: fix async vs NIC crypto offload
+    - tls: rx: simplify async wait
+    - tls: extract context alloc/initialization out of tls_set_sw_offload
+    - net: tls: factor out tls_*crypt_async_wait()
+    - tls: fix race between async notify and socket close
+
+ -- Guoqing Jiang <guoqing.jiang@canonical.com>  Wed, 17 Jul 2024 12:30:26 +0800
+
+linux-xilinx-zynqmp (5.4.0-1047.51) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1047.51 -proposed tracker (LP: #2068452)
+
+  [ Ubuntu: 5.4.0-189.209 ]
+
+  * focal/linux: 5.4.0-189.209 -proposed tracker (LP: #2068454)
+  * Focal update: v5.4.275 upstream stable release (LP: #2067865)
+    - batman-adv: Avoid infinite loop trying to resize local TT
+    - Bluetooth: Fix memory leak in hci_req_sync_complete()
+    - nouveau: fix function cast warning
+    - net: openvswitch: fix unwanted error log on timeout policy probing
+    - u64_stats: fix u64_stats_init() for lockdep when used repeatedly in one file
+    - geneve: fix header validation in geneve[6]_xmit_skb
+    - ipv6: fib: hide unused 'pn' variable
+    - ipv4/route: avoid unused-but-set-variable warning
+    - ipv6: fix race condition between ipv6_get_ifaddr and ipv6_del_addr
+    - net/mlx5: Properly link new fs rules into the tree
+    - net: ena: Fix potential sign extension issue
+    - btrfs: qgroup: correctly model root qgroup rsv in convert
+    - drm/client: Fully protect modes[] with dev->mode_config.mutex
+    - vhost: Add smp_rmb() in vhost_vq_avail_empty()
+    - selftests: timers: Fix abs() warning in posix_timers test
+    - x86/apic: Force native_apic_mem_read() to use the MOV instruction
+    - btrfs: record delayed inode root in transaction
+    - selftests/ftrace: Limit length in subsystem-enable tests
+    - kprobes: Fix possible use-after-free issue on kprobe registration
+    - Revert "tracing/trigger: Fix to return error if failed to alloc snapshot"
+    - netfilter: nf_tables: Fix potential data-race in __nft_expr_type_get()
+    - tun: limit printing rate when illegal packet received by tun dev
+    - RDMA/rxe: Fix the problem "mutex_destroy missing"
+    - RDMA/mlx5: Fix port number for counter query in multi-port configuration
+    - drm: nv04: Fix out of bounds access
+    - clk: Remove prepare_lock hold assertion in __clk_release()
+    - clk: Mark 'all_lists' as const
+    - clk: remove extra empty line
+    - clk: Print an info line before disabling unused clocks
+    - clk: Initialize struct clk_core kref earlier
+    - clk: Get runtime PM before walking tree during disable_unused
+    - x86/cpufeatures: Fix dependencies for GFNI, VAES, and VPCLMULQDQ
+    - comedi: vmk80xx: fix incomplete endpoint checking
+    - serial/pmac_zilog: Remove flawed mitigation for rx irq flood
+    - USB: serial: option: add Fibocom FM135-GL variants
+    - USB: serial: option: add support for Fibocom FM650/FG650
+    - USB: serial: option: add Lonsung U8300/U9300 product
+    - USB: serial: option: support Quectel EM060K sub-models
+    - USB: serial: option: add Rolling RW101-GL and RW135-GL support
+    - USB: serial: option: add Telit FN920C04 rmnet compositions
+    - usb: dwc2: host: Fix dereference issue in DDMA completion flow.
+    - speakup: Avoid crash on very long word
+    - fs: sysfs: Fix reference leak in sysfs_break_active_protection()
+    - nouveau: fix instmem race condition around ptr stores
+    - nilfs2: fix OOB in nilfs_set_de_type
+    - KVM: async_pf: Cleanup kvm_setup_async_pf()
+    - arm64: dts: rockchip: fix alphabetical ordering RK3399 puma
+    - arm64: dts: rockchip: enable internal pull-up on PCIE_WAKE# for RK3399 Puma
+    - arm64: dts: mediatek: mt7622: fix IR nodename
+    - arm64: dts: mediatek: mt7622: fix ethernet controller "compatible"
+    - arm64: dts: mediatek: mt7622: drop "reset-names" from thermal block
+    - arm64: dts: mt2712: add ethernet device node
+    - arm64: dts: mediatek: mt2712: fix validation errors
+    - ARC: [plat-hsdk]: Remove misplaced interrupt-cells property
+    - vxlan: drop packets from invalid src-address
+    - mlxsw: core: Unregister EMAD trap using FORWARD action
+    - NFC: trf7970a: disable all regulators on removal
+    - net: usb: ax88179_178a: stop lying about skb->truesize
+    - net: gtp: Fix Use-After-Free in gtp_dellink
+    - ipvs: Fix checksumming on GSO of SCTP packets
+    - net: openvswitch: Fix Use-After-Free in ovs_ct_exit
+    - mlxsw: spectrum_acl_tcam: Fix race during rehash delayed work
+    - mlxsw: spectrum_acl_tcam: Fix possible use-after-free during activity update
+    - mlxsw: spectrum_acl_tcam: Fix possible use-after-free during rehash
+    - mlxsw: spectrum_acl_tcam: Rate limit error message
+    - mlxsw: spectrum_acl_tcam: Fix memory leak during rehash
+    - mlxsw: spectrum_acl_tcam: Fix warning during rehash
+    - mlxsw: spectrum_acl_tcam: Fix incorrect list API usage
+    - mlxsw: spectrum_acl_tcam: Fix memory leak when canceling rehash work
+    - i40e: Do not use WQ_MEM_RECLAIM flag for workqueue
+    - iavf: Fix TC config comparison with existing adapter TC config
+    - af_unix: Suppress false-positive lockdep splat for spin_lock() in
+      __unix_gc().
+    - serial: core: Provide port lock wrappers
+    - serial: mxs-auart: add spinlock around changing cts state
+    - Revert "crypto: api - Disallow identical driver names"
+    - net/mlx5e: Fix a race in command alloc flow
+    - tracing: Show size of requested perf buffer
+    - tracing: Increase PERF_MAX_TRACE_SIZE to handle Sentinel1 and docker
+      together
+    - Bluetooth: Fix type of len in {l2cap,sco}_sock_getsockopt_old()
+    - Bluetooth: btusb: Add Realtek RTL8852BE support ID 0x0bda:0x4853
+    - btrfs: fix information leak in btrfs_ioctl_logical_to_ino()
+    - arm64: dts: rockchip: enable internal pull-up for Q7_THRM# on RK3399 Puma
+    - drm/amdgpu: Fix leak when GPU memory allocation fails
+    - irqchip/gic-v3-its: Prevent double free on error
+    - ethernet: Add helper for assigning packet type when dest address does not
+      match device address
+    - net: b44: set pause params only when interface is up
+    - stackdepot: respect __GFP_NOLOCKDEP allocation flag
+    - mtd: diskonchip: work around ubsan link failure
+    - tcp: Clean up kernel listener's reqsk in inet_twsk_purge()
+    - tcp: Fix NEW_SYN_RECV handling in inet_twsk_purge()
+    - dmaengine: owl: fix register access functions
+    - idma64: Don't try to serve interrupts when device is powered off
+    - i2c: smbus: fix NULL function pointer dereference
+    - HID: i2c-hid: remove I2C_HID_READ_PENDING flag to prevent lock-up
+    - bounds: Use the right number of bits for power-of-two CONFIG_NR_CPUS
+    - udp: preserve the connected status if only UDP cmsg
+    - serial: core: fix kernel-doc for uart_port_unlock_irqrestore()
+    - Linux 5.4.275
+  * Focal update: v5.4.274 upstream stable release (LP: #2067857)
+    - amdkfd: use calloc instead of kzalloc to avoid integer overflow
+    - Documentation/hw-vuln: Update spectre doc
+    - x86/cpu: Support AMD Automatic IBRS
+    - x86/bugs: Use sysfs_emit()
+    - timers: Update kernel-doc for various functions
+    - timers: Use del_timer_sync() even on UP
+    - timers: Rename del_timer_sync() to timer_delete_sync()
+    - media: staging: ipu3-imgu: Set fields before media_entity_pads_init()
+    - clk: qcom: gcc-sdm845: Add soft dependency on rpmhpd
+    - smack: Set SMACK64TRANSMUTE only for dirs in smack_inode_setxattr()
+    - smack: Handle SMACK64TRANSMUTE in smack_inode_setsecurity()
+    - ARM: dts: mmp2-brownstone: Don't redeclare phandle references
+    - arm: dts: marvell: Fix maxium->maxim typo in brownstone dts
+    - serial: max310x: fix NULL pointer dereference in I2C instantiation
+    - KVM: Always flush async #PF workqueue when vCPU is being destroyed
+    - sparc64: NMI watchdog: fix return value of __setup handler
+    - sparc: vDSO: fix return value of __setup handler
+    - crypto: qat - fix double free during reset
+    - crypto: qat - resolve race condition during AER recovery
+    - selftests/mqueue: Set timeout to 180 seconds
+    - ext4: correct best extent lstart adjustment logic
+    - fat: fix uninitialized field in nostale filehandles
+    - ubifs: Set page uptodate in the correct place
+    - ubi: Check for too small LEB size in VTBL code
+    - ubi: correct the calculation of fastmap size
+    - mtd: rawnand: meson: fix scrambling mode value in command macro
+    - parisc: Do not hardcode registers in checksum functions
+    - parisc: Fix ip_fast_csum
+    - parisc: Fix csum_ipv6_magic on 32-bit systems
+    - parisc: Fix csum_ipv6_magic on 64-bit systems
+    - parisc: Strip upper 32 bit of sum in csum_ipv6_magic for 64-bit builds
+    - PM: suspend: Set mem_sleep_current during kernel command line setup
+    - clk: qcom: gcc-ipq8074: fix terminating of frequency table arrays
+    - clk: qcom: mmcc-apq8084: fix terminating of frequency table arrays
+    - clk: qcom: mmcc-msm8974: fix terminating of frequency table arrays
+    - powerpc/fsl: Fix mfpmr build errors with newer binutils
+    - USB: serial: ftdi_sio: add support for GMC Z216C Adapter IR-USB
+    - USB: serial: add device ID for VeriFone adapter
+    - USB: serial: cp210x: add ID for MGP Instruments PDS100
+    - USB: serial: option: add MeiG Smart SLM320 product
+    - USB: serial: cp210x: add pid/vid for TDK NC0110013M and MM0110113M
+    - PM: sleep: wakeirq: fix wake irq warning in system suspend
+    - mmc: tmio: avoid concurrent runs of mmc_request_done()
+    - fuse: don't unhash root
+    - btrfs: fix off-by-one chunk length calculation at contains_pending_extent()
+    - PCI: Drop pci_device_remove() test of pci_dev->driver
+    - PCI/PM: Drain runtime-idle callbacks before driver removal
+    - Revert "Revert "md/raid5: Wait for MD_SB_CHANGE_PENDING in raid5d""
+    - dm-raid: fix lockdep waring in "pers->hot_add_disk"
+    - mmc: core: Fix switch on gp3 partition
+    - hwmon: (amc6821) add of_match table
+    - ext4: fix corruption during on-line resize
+    - firmware: meson_sm: Rework driver as a proper platform driver
+    - nvmem: meson-efuse: fix function pointer type mismatch
+    - slimbus: core: Remove usage of the deprecated ida_simple_xx() API
+    - speakup: Fix 8bit characters from direct synth
+    - kbuild: Move -Wenum-{compare-conditional,enum-conversion} into W=1
+    - vfio/platform: Disable virqfds on cleanup
+    - ring-buffer: Fix resetting of shortest_full
+    - ring-buffer: Fix full_waiters_pending in poll
+    - soc: fsl: qbman: Always disable interrupts when taking cgr_lock
+    - soc: fsl: qbman: Add helper for sanity checking cgr ops
+    - soc: fsl: qbman: Add CGR update function
+    - soc: fsl: qbman: Use raw spinlock for cgr_lock
+    - s390/zcrypt: fix reference counting on zcrypt card objects
+    - drm/exynos: do not return negative values from .get_modes()
+    - drm/imx/ipuv3: do not return negative values from .get_modes()
+    - drm/vc4: hdmi: do not return negative values from .get_modes()
+    - memtest: use {READ,WRITE}_ONCE in memory scanning
+    - nilfs2: fix failure to detect DAT corruption in btree and direct mappings
+    - nilfs2: use a more common logging style
+    - nilfs2: prevent kernel bug at submit_bh_wbc()
+    - x86/CPU/AMD: Update the Zenbleed microcode revisions
+    - ahci: asm1064: correct count of reported ports
+    - ahci: asm1064: asm1166: don't limit reported ports
+    - dm snapshot: fix lockup in dm_exception_table_exit
+    - comedi: comedi_test: Prevent timers rescheduling during deletion
+    - netfilter: nf_tables: reject constant set with timeout
+    - xfrm: Avoid clang fortify warning in copy_to_user_tmpl()
+    - ALSA: hda/realtek - Fix headset Mic no show at resume back for Lenovo ALC897
+      platform
+    - USB: usb-storage: Prevent divide-by-0 error in isd200_ata_command
+    - usb: gadget: ncm: Fix handling of zero block length packets
+    - usb: port: Don't try to peer unused USB ports based on location
+    - tty: serial: fsl_lpuart: avoid idle preamble pending if CTS is enabled
+    - vt: fix unicode buffer corruption when deleting characters
+    - fs/aio: Check IOCB_AIO_RW before the struct aio_kiocb conversion
+    - objtool: is_fentry_call() crashes if call has no destination
+    - objtool: Add support for intra-function calls
+    - x86/speculation: Support intra-function call validation
+    - xen/events: close evtchn after mapping cleanup
+    - printk: Update @console_may_schedule in console_trylock_spinning()
+    - btrfs: allocate btrfs_ioctl_defrag_range_args on stack
+    - Revert "loop: Check for overflow while configuring loop"
+    - loop: Call loop_config_discard() only after new config is applied
+    - loop: Remove sector_t truncation checks
+    - loop: Factor out setting loop device size
+    - loop: Refactor loop_set_status() size calculation
+    - loop: Factor out configuring loop from status
+    - loop: Check for overflow while configuring loop
+    - loop: loop_set_status_from_info() check before assignment
+    - perf/core: Fix reentry problem in perf_output_read_group()
+    - efivarfs: Request at most 512 bytes for variable names
+    - powerpc: xor_vmx: Add '-mhard-float' to CFLAGS
+    - bounds: support non-power-of-two CONFIG_NR_CPUS
+    - vt: fix memory overlapping when deleting chars in the buffer
+    - mm/memory-failure: fix an incorrect use of tail pages
+    - mm/migrate: set swap entry values of THP tail pages properly.
+    - wifi: mac80211: check/clear fast rx for non-4addr sta VLAN changes
+    - exec: Fix NOMMU linux_binprm::exec in transfer_args_to_stack()
+    - mmc: core: Initialize mmc_blk_ioc_data
+    - mmc: core: Avoid negative index with array access
+    - ALSA: sh: aica: reorder cleanup operations to avoid UAF bugs
+    - scsi: core: Fix unremoved procfs host directory regression
+    - usb: dwc2: host: Fix remote wakeup from hibernation
+    - usb: dwc2: host: Fix hibernation flow
+    - usb: dwc2: host: Fix ISOC flow in DDMA mode
+    - usb: dwc2: gadget: LPM flow fix
+    - usb: udc: remove warning when queue disabled ep
+    - scsi: qla2xxx: Fix command flush on cable pull
+    - x86/cpu: Enable STIBP on AMD if Automatic IBRS is enabled
+    - scsi: lpfc: Correct size for wqe for memset()
+    - USB: core: Fix deadlock in usb_deauthorize_interface()
+    - nfc: nci: Fix uninit-value in nci_dev_up and nci_ntf_packet
+    - ixgbe: avoid sleeping allocation in ixgbe_ipsec_vf_add_sa()
+    - tcp: properly terminate timers for kernel sockets
+    - dm integrity: fix out-of-range warning
+    - r8169: fix issue caused by buggy BIOS on certain boards with RTL8168d
+    - Bluetooth: hci_event: set the conn encrypted before conn establishes
+    - Bluetooth: Fix TOCTOU in HCI debugfs implementation
+    - netfilter: nf_tables: disallow timeout for anonymous sets
+    - net/rds: fix possible cp null dereference
+    - vfio/pci: Disable auto-enable of exclusive INTx IRQ
+    - vfio/pci: Lock external INTx masking ops
+    - vfio: Introduce interface to flush virqfd inject workqueue
+    - vfio/pci: Create persistent INTx handler
+    - vfio/platform: Create persistent IRQ handlers
+    - Revert "x86/mm/ident_map: Use gbpages only where full GB page should be
+      mapped."
+    - mm, vmscan: prevent infinite loop for costly GFP_NOIO | __GFP_RETRY_MAYFAIL
+      allocations
+    - netfilter: nf_tables: flush pending destroy work before exit_net release
+    - netfilter: nf_tables: Fix potential data-race in __nft_flowtable_type_get()
+    - bpf, sockmap: Prevent lock inversion deadlock in map delete elem
+    - net/sched: act_skbmod: prevent kernel-infoleak
+    - net: stmmac: fix rx queue priority assignment
+    - selftests: reuseaddr_conflict: add missing new line at the end of the output
+    - ipv6: Fix infinite recursion in fib6_dump_done().
+    - i40e: fix vf may be used uninitialized in this function warning
+    - staging: mmal-vchiq: Allocate and free components as required
+    - staging: mmal-vchiq: Fix client_component for 64 bit kernel
+    - staging: vc04_services: changen strncpy() to strscpy_pad()
+    - staging: vc04_services: fix information leak in create_component()
+    - fs: add a vfs_fchown helper
+    - fs: add a vfs_fchmod helper
+    - initramfs: switch initramfs unpacking to struct file based APIs
+    - init: open /initrd.image with O_LARGEFILE
+    - erspan: Add type I version 0 support.
+    - erspan: make sure erspan_base_hdr is present in skb->head
+    - net: ravb: Always process TX descriptor ring
+    - ASoC: ops: Fix wraparound for mask in snd_soc_get_volsw
+    - ata: sata_sx4: fix pdc20621_get_from_dimm() on 64-bit
+    - scsi: mylex: Fix sysfs buffer lengths
+    - ata: sata_mv: Fix PCI device ID table declaration compilation warning
+    - ALSA: hda/realtek: Update Panasonic CF-SZ6 quirk to support headset with
+      microphone
+    - x86/mce: Make sure to grab mce_sysfs_mutex in set_bank()
+    - s390/entry: align system call table on 8 bytes
+    - wifi: ath9k: fix LNA selection in ath_ant_try_scan()
+    - VMCI: Fix memcpy() run-time warning in dg_dispatch_as_host()
+    - panic: Flush kernel log buffer at the end
+    - arm64: dts: rockchip: fix rk3328 hdmi ports node
+    - arm64: dts: rockchip: fix rk3399 hdmi ports node
+    - ionic: set adminq irq affinity
+    - tools/power x86_energy_perf_policy: Fix file leak in get_pkg_num()
+    - btrfs: handle chunk tree lookup error in btrfs_relocate_sys_chunks()
+    - btrfs: export: handle invalid inode or root reference in btrfs_get_parent()
+    - btrfs: send: handle path ref underflow in header iterate_inode_ref()
+    - Bluetooth: btintel: Fix null ptr deref in btintel_read_version
+    - Input: synaptics-rmi4 - fail probing if memory allocation for "phys" fails
+    - sysv: don't call sb_bread() with pointers_lock held
+    - scsi: lpfc: Fix possible memory leak in lpfc_rcv_padisc()
+    - isofs: handle CDs with bad root inode but good Joliet root directory
+    - media: sta2x11: fix irq handler cast
+    - drm/amd/display: Fix nanosec stat overflow
+    - SUNRPC: increase size of rpc_wait_queue.qlen from unsigned short to unsigned
+      int
+    - Revert "ACPI: PM: Block ASUS B1400CEAE from suspend to idle by default"
+    - block: prevent division by zero in blk_rq_stat_sum()
+    - Input: allocate keycode for Display refresh rate toggle
+    - ktest: force $buildonly = 1 for 'make_warnings_file' test type
+    - tools: iio: replace seekdir() in iio_generic_buffer
+    - usb: typec: tcpci: add generic tcpci fallback compatible
+    - usb: sl811-hcd: only defined function checkdone if QUIRK2 is defined
+    - fbdev: viafb: fix typo in hw_bitblt_1 and hw_bitblt_2
+    - fbmon: prevent division by zero in fb_videomode_from_videomode()
+    - netfilter: nf_tables: reject new basechain after table flag update
+    - netfilter: nf_tables: discard table flag update with pending basechain
+      deletion
+    - tty: n_gsm: require CAP_NET_ADMIN to attach N_GSM0710 ldisc
+    - drm/vkms: call drm_atomic_helper_shutdown before drm_dev_put()
+    - virtio: reenable config if freezing device failed
+    - x86/mm/pat: fix VM_PAT handling in COW mappings
+    - drm/i915/gt: Reset queue_priority_hint on parking
+    - x86/alternative: Don't call text_poke() in lazy TLB mode
+    - Bluetooth: btintel: Fixe build regression
+    - VMCI: Fix possible memcpy() run-time warning in
+      vmci_datagram_invoke_guest_handler()
+    - erspan: Check IFLA_GRE_ERSPAN_VER is set.
+    - ip_gre: do not report erspan version on GRE interface
+    - firmware: meson_sm: fix to avoid potential NULL pointer dereference
+    - Linux 5.4.274
+  * CVE-2024-26586
+    - mlxsw: spectrum_acl_tcam: Fix stack corruption
+  * CVE-2024-26923
+    - af_unix: Do not use atomic ops for unix_sk(sk)->inflight.
+    - af_unix: Fix garbage collector racing against connect()
+  * Focal update: v5.4.273 upstream stable release (LP: #2064561)
+    - io_uring/unix: drop usage of io_uring socket
+    - io_uring: drop any code related to SCM_RIGHTS
+    - selftests: tls: use exact comparison in recv_partial
+    - ASoC: rt5645: Make LattePanda board DMI match more precise
+    - x86/xen: Add some null pointer checking to smp.c
+    - MIPS: Clear Cause.BD in instruction_pointer_set
+    - HID: multitouch: Add required quirk for Synaptics 0xcddc device
+    - RDMA/mlx5: Relax DEVX access upon modify commands
+    - net/iucv: fix the allocation size of iucv_path_table array
+    - parisc/ftrace: add missing CONFIG_DYNAMIC_FTRACE check
+    - block: sed-opal: handle empty atoms when parsing response
+    - dm-verity, dm-crypt: align "struct bvec_iter" correctly
+    - btrfs: fix data race at btrfs_use_block_rsv() when accessing block reserve
+    - scsi: mpt3sas: Prevent sending diag_reset when the controller is ready
+    - Bluetooth: rfcomm: Fix null-ptr-deref in rfcomm_check_security
+    - firewire: core: use long bus reset on gap count error
+    - ASoC: Intel: bytcr_rt5640: Add an extra entry for the Chuwi Vi8 tablet
+    - Input: gpio_keys_polled - suppress deferred probe error for gpio
+    - ASoC: wm8962: Enable oscillator if selecting WM8962_FLL_OSC
+    - ASoC: wm8962: Enable both SPKOUTR_ENA and SPKOUTL_ENA in mono mode
+    - ASoC: wm8962: Fix up incorrect error message in wm8962_set_fll
+    - do_sys_name_to_handle(): use kzalloc() to fix kernel-infoleak
+    - fs/select: rework stack allocation hack for clang
+    - timekeeping: Fix cross-timestamp interpolation on counter wrap
+    - timekeeping: Fix cross-timestamp interpolation corner case decision
+    - timekeeping: Fix cross-timestamp interpolation for non-x86
+    - wifi: ath10k: fix NULL pointer dereference in
+      ath10k_wmi_tlv_op_pull_mgmt_tx_compl_ev()
+    - b43: dma: Fix use true/false for bool type variable
+    - wifi: b43: Stop/wake correct queue in DMA Tx path when QoS is disabled
+    - wifi: b43: Stop/wake correct queue in PIO Tx path when QoS is disabled
+    - b43: main: Fix use true/false for bool type
+    - wifi: b43: Stop correct queue in DMA worker when QoS is disabled
+    - wifi: b43: Disable QoS for bcm4331
+    - wifi: wilc1000: fix declarations ordering
+    - wifi: wilc1000: fix RCU usage in connect path
+    - wifi: mwifiex: debugfs: Drop unnecessary error check for
+      debugfs_create_dir()
+    - sock_diag: annotate data-races around sock_diag_handlers[family]
+    - af_unix: Annotate data-race of gc_in_progress in wait_for_unix_gc().
+    - net: blackhole_dev: fix build warning for ethh set but not used
+    - wifi: libertas: fix some memleaks in lbs_allocate_cmd_buffer()
+    - arm64: dts: mediatek: mt7622: add missing "device_type" to memory nodes
+    - bpf: Add typecast to bpf helpers to help BTF generation
+    - bpf: Factor out bpf_spin_lock into helpers.
+    - bpf: Mark bpf_spin_{lock,unlock}() helpers with notrace correctly
+    - arm64: dts: qcom: db820c: Move non-soc entries out of /soc
+    - arm64: dts: qcom: msm8996: Use node references in db820c
+    - arm64: dts: qcom: msm8996: Move regulator consumers to db820c
+    - arm64: dts: qcom: msm8996: Pad addresses
+    - ACPI: processor_idle: Fix memory leak in acpi_processor_power_exit()
+    - bus: tegra-aconnect: Update dependency to ARCH_TEGRA
+    - [Config]: Update tegra configs
+    - iommu/amd: Mark interrupt as managed
+    - wifi: brcmsmac: avoid function pointer casts
+    - net: ena: Remove ena_select_queue
+    - ARM: dts: arm: realview: Fix development chip ROM compatible value
+    - ARM: dts: imx6dl-yapp4: Move phy reset into switch node
+    - ARM: dts: imx6dl-yapp4: Fix typo in the QCA switch register address
+    - ARM: dts: imx6dl-yapp4: Move the internal switch PHYs under the switch node
+    - ACPI: scan: Fix device check notification handling
+    - x86, relocs: Ignore relocations in .notes section
+    - SUNRPC: fix some memleaks in gssx_dec_option_array
+    - mmc: wmt-sdmmc: remove an incorrect release_mem_region() call in the .remove
+      function
+    - igb: move PEROUT and EXTTS isr logic to separate functions
+    - igb: Fix missing time sync events
+    - Bluetooth: Remove superfluous call to hci_conn_check_pending()
+    - sr9800: Add check for usbnet_get_endpoints
+    - bpf: Fix hashtab overflow check on 32-bit arches
+    - bpf: Fix stackmap overflow check on 32-bit arches
+    - ipv6: fib6_rules: flush route cache when rule is changed
+    - net: ip_tunnel: make sure to pull inner header in ip_tunnel_rcv()
+    - net: hns3: fix port duplex configure error in IMP reset
+    - tcp: fix incorrect parameter validation in the do_tcp_getsockopt() function
+    - l2tp: fix incorrect parameter validation in the pppol2tp_getsockopt()
+      function
+    - udp: fix incorrect parameter validation in the udp_lib_getsockopt() function
+    - net: kcm: fix incorrect parameter validation in the kcm_getsockopt) function
+    - net/x25: fix incorrect parameter validation in the x25_getsockopt() function
+    - nfp: flower: handle acti_netdevs allocation failure
+    - dm raid: fix false positive for requeue needed during reshape
+    - dm: call the resume method on internal suspend
+    - drm/tegra: dsi: Add missing check for of_find_device_by_node
+    - gpu: host1x: mipi: Update tegra_mipi_request() to be node based
+    - drm/tegra: dsi: Make use of the helper function dev_err_probe()
+    - drm/tegra: dsi: Fix some error handling paths in tegra_dsi_probe()
+    - drm/tegra: dsi: Fix missing pm_runtime_disable() in the error handling path
+      of tegra_dsi_probe()
+    - drm/tegra: output: Fix missing i2c_put_adapter() in the error handling paths
+      of tegra_output_probe()
+    - drm/rockchip: inno_hdmi: Fix video timing
+    - drm: Don't treat 0 as -1 in drm_fixp2int_ceil
+    - drm/rockchip: lvds: do not overwrite error code
+    - dmaengine: tegra210-adma: Update dependency to ARCH_TEGRA
+    - media: tc358743: register v4l2 async device only after successful setup
+    - PCI/DPC: Print all TLP Prefixes, not just the first
+    - perf record: Fix possible incorrect free in record__switch_output()
+    - drm/amd/display: Fix potential NULL pointer dereferences in
+      'dcn10_set_output_transfer_func()'
+    - perf evsel: Fix duplicate initialization of data->id in
+      evsel__parse_sample()
+    - media: em28xx: annotate unchecked call to media_device_register()
+    - media: v4l2-tpg: fix some memleaks in tpg_alloc
+    - media: v4l2-mem2mem: fix a memleak in v4l2_m2m_register_entity
+    - media: edia: dvbdev: fix a use-after-free
+    - clk: qcom: reset: Allow specifying custom reset delay
+    - clk: qcom: reset: support resetting multiple bits
+    - clk: qcom: reset: Commonize the de/assert functions
+    - clk: qcom: reset: Ensure write completion on reset de/assertion
+    - quota: simplify drop_dquot_ref()
+    - quota: Fix potential NULL pointer dereference
+    - quota: Fix rcu annotations of inode dquot pointers
+    - PCI: switchtec: Fix an error handling path in switchtec_pci_probe()
+    - perf thread_map: Free strlist on normal path in thread_map__new_by_tid_str()
+    - drm/radeon/ni: Fix wrong firmware size logging in ni_init_microcode()
+    - ALSA: seq: fix function cast warnings
+    - perf stat: Avoid metric-only segv
+    - media: imx: csc/scaler: fix v4l2_ctrl_handler memory leak
+    - media: go7007: add check of return value of go7007_read_addr()
+    - media: pvrusb2: remove redundant NULL check
+    - media: pvrusb2: fix pvr2_stream_callback casts
+    - clk: qcom: dispcc-sdm845: Adjust internal GDSC wait times
+    - drm/mediatek: dsi: Fix DSI RGB666 formats and definitions
+    - PCI: Mark 3ware-9650SE Root Port Extended Tags as broken
+    - clk: hisilicon: hi3519: Release the correct number of gates in
+      hi3519_clk_unregister()
+    - drm/tegra: put drm_gem_object ref on error in tegra_fb_create
+    - mfd: syscon: Call of_node_put() only when of_parse_phandle() takes a ref
+    - mfd: altera-sysmgr: Call of_node_put() only when of_parse_phandle() takes a
+      ref
+    - crypto: arm/sha - fix function cast warnings
+    - mtd: maps: physmap-core: fix flash size larger than 32-bit
+    - mtd: rawnand: lpc32xx_mlc: fix irq handler prototype
+    - ASoC: meson: axg-tdm-interface: fix mclk setup without mclk-fs
+    - drm/amdgpu: Fix missing break in ATOM_ARG_IMM Case of atom_get_src_int()
+    - media: pvrusb2: fix uaf in pvr2_context_set_notify
+    - media: dvb-frontends: avoid stack overflow warnings with clang
+    - media: go7007: fix a memleak in go7007_load_encoder
+    - media: v4l2-core: correctly validate video and metadata ioctls
+    - media: rename VFL_TYPE_GRABBER to _VIDEO
+    - media: media/pci: rename VFL_TYPE_GRABBER to _VIDEO
+    - media: ttpci: fix two memleaks in budget_av_attach
+    - drm/mediatek: Fix a null pointer crash in mtk_drm_crtc_finish_page_flip
+    - powerpc/hv-gpci: Fix the H_GET_PERF_COUNTER_INFO hcall return value checks
+    - drm/msm/dpu: add division of drm_display_mode's hskew parameter
+    - powerpc/embedded6xx: Fix no previous prototype for avr_uart_send() etc.
+    - backlight: lm3630a: Initialize backlight_properties on init
+    - backlight: lm3630a: Don't set bl->props.brightness in get_brightness
+    - backlight: da9052: Fully initialize backlight_properties during probe
+    - backlight: lm3639: Fully initialize backlight_properties during probe
+    - backlight: lp8788: Fully initialize backlight_properties during probe
+    - sparc32: Fix section mismatch in leon_pci_grpci
+    - clk: Fix clk_core_get NULL dereference
+    - ALSA: usb-audio: Stop parsing channels bits when all channels are found.
+    - scsi: csiostor: Avoid function pointer casts
+    - RDMA/device: Fix a race between mad_client and cm_client init
+    - scsi: bfa: Fix function pointer type mismatch for hcb_qe->cbfn
+    - net: sunrpc: Fix an off by one in rpc_sockaddr2uaddr()
+    - watchdog: stm32_iwdg: initialize default timeout
+    - NFS: Fix an off by one in root_nfs_cat()
+    - afs: Revert "afs: Hide silly-rename files from userspace"
+    - tty: vt: fix 20 vs 0x20 typo in EScsiignore
+    - serial: max310x: fix syntax error in IRQ error message
+    - tty: serial: samsung: fix tx_empty() to return TIOCSER_TEMT
+    - kconfig: fix infinite loop when expanding a macro at the end of file
+    - rtc: mt6397: select IRQ_DOMAIN instead of depending on it
+    - serial: 8250_exar: Don't remove GPIO device on suspend
+    - staging: greybus: fix get_channel_from_mode() failure path
+    - usb: gadget: net2272: Use irqflags in the call to net2272_probe_fin
+    - octeontx2-af: Use matching wake_up API variant in CGX command interface
+    - s390/vtime: fix average steal time calculation
+    - hsr: Fix uninit-value access in hsr_get_node()
+    - packet: annotate data-races around ignore_outgoing
+    - rds: introduce acquire/release ordering in acquire/release_in_xmit()
+    - hsr: Handle failures in module init
+    - net/bnx2x: Prevent access to a freed page in page_pool
+    - octeontx2-af: Use separate handlers for interrupts
+    - ARM: dts: sun8i-h2-plus-bananapi-m2-zero: add regulator nodes vcc-dram and
+      vcc1v2
+    - netfilter: nf_tables: do not compare internal table flags on updates
+    - rcu: add a helper to report consolidated flavor QS
+    - bpf: report RCU QS in cpumap kthread
+    - spi: spi-mt65xx: Fix NULL pointer access in interrupt handler
+    - regmap: Add missing map->bus check
+    - Linux 5.4.273
+  * Focal update: v5.4.272 upstream stable release (LP: #2064555)
+    - lan78xx: Fix white space and style issues
+    - lan78xx: Add missing return code checks
+    - lan78xx: Fix partial packet errors on suspend/resume
+    - lan78xx: Fix race conditions in suspend/resume handling
+    - net: lan78xx: fix runtime PM count underflow on link stop
+    - ixgbe: {dis, en}able irqs in ixgbe_txrx_ring_{dis, en}able
+    - geneve: make sure to pull inner header in geneve_rx()
+    - net: ice: Fix potential NULL pointer dereference in ice_bridge_setlink()
+    - net/ipv6: avoid possible UAF in ip6_route_mpath_notify()
+    - net/rds: fix WARNING in rds_conn_connect_if_down
+    - netfilter: nft_ct: fix l3num expectations with inet pseudo family
+    - netfilter: nf_conntrack_h323: Add protection for bmp length out of range
+    - netrom: Fix a data-race around sysctl_netrom_default_path_quality
+    - netrom: Fix a data-race around sysctl_netrom_obsolescence_count_initialiser
+    - netrom: Fix data-races around sysctl_netrom_network_ttl_initialiser
+    - netrom: Fix a data-race around sysctl_netrom_transport_timeout
+    - netrom: Fix a data-race around sysctl_netrom_transport_maximum_tries
+    - netrom: Fix a data-race around sysctl_netrom_transport_acknowledge_delay
+    - netrom: Fix a data-race around sysctl_netrom_transport_busy_delay
+    - netrom: Fix a data-race around sysctl_netrom_transport_requested_window_size
+    - netrom: Fix a data-race around sysctl_netrom_transport_no_activity_timeout
+    - netrom: Fix a data-race around sysctl_netrom_routing_control
+    - netrom: Fix a data-race around sysctl_netrom_link_fails_count
+    - netrom: Fix data-races around sysctl_net_busy_read
+    - selftests: mm: fix map_hugetlb failure on 64K page size systems
+    - um: allow not setting extra rpaths in the linux binary
+    - serial: max310x: Use devm_clk_get_optional() to get the input clock
+    - serial: max310x: Try to get crystal clock rate from property
+    - serial: max310x: fail probe if clock crystal is unstable
+    - serial: max310x: Make use of device properties
+    - serial: max310x: use regmap methods for SPI batch operations
+    - serial: max310x: use a separate regmap for each port
+    - serial: max310x: prevent infinite while() loop in port startup
+    - Input: i8042 - fix strange behavior of touchpad on Clevo NS70PU
+    - hv_netvsc: Make netvsc/VF binding check both MAC and serial number
+    - hv_netvsc: use netif_is_bond_master() instead of open code
+    - hv_netvsc: Register VF in netvsc_probe if NET_DEVICE_REGISTER missed
+    - y2038: rusage: use __kernel_old_timeval
+    - getrusage: add the "signal_struct *sig" local variable
+    - getrusage: move thread_group_cputime_adjusted() outside of
+      lock_task_sighand()
+    - getrusage: use __for_each_thread()
+    - getrusage: use sig->stats_lock rather than lock_task_sighand()
+    - serial: max310x: Unprepare and disable clock in error path
+    - regmap: allow to define reg_update_bits for no bus configuration
+    - regmap: Add bulk read/write callbacks into regmap_config
+    - serial: max310x: make accessing revision id interface-agnostic
+    - serial: max310x: implement I2C support
+    - serial: max310x: fix IO data corruption in batched operations
+    - arm64: dts: qcom: add PDC interrupt controller for SDM845
+    - arm64: dts: qcom: sdm845: fix USB DP/DM HS PHY interrupts
+    - Linux 5.4.272
+  * CVE-2024-23307
+    - md/raid5: fix atomicity violation in raid5_cache_count
+  * CVE-2024-26889
+    - Bluetooth: hci_core: Fix possible buffer overflow
+  * CVE-2024-26828
+    - cifs: fix underflow in parse_server_interfaces()
+  * CVE-2024-24861
+    - media: xc4000: Fix atomicity violation in xc4000_get_frequency
+  * CVE-2023-6270
+    - aoe: fix the potential use-after-free problem in aoecmd_cfg_pkts
+  * CVE-2024-26642
+    - netfilter: nf_tables: disallow anonymous set with timeout flag
+  * CVE-2024-26926
+    - binder: check offset alignment in binder_get_object()
+  * CVE-2024-26922
+    - drm/amdgpu: validate the parameters of bo mapping operations more clearly
+  * CVE-2024-26925
+    - netfilter: Cleanup nft_net->module_list from nf_tables_exit_net()
+    - netfilter: nf_tables: release batch on table validation from abort path
+    - netfilter: nf_tables: release mutex after nft_gc_seq_end from abort path
+  * CVE-2024-26643
+    - netfilter: nf_tables: mark set as dead when unbinding anonymous set with
+      timeout
+  * CVE-2024-2201
+    - x86/cpufeatures: Add new word for scattered features
+    - x86/cpufeatures: Add CPUID_LNX_5 to track recently added Linux-defined word
+    - x86/bugs: Change commas to semicolons in 'spectre_v2' sysfs file
+    - x86/bhi: Add support for clearing branch history at syscall entry
+    - x86/bhi: Define SPEC_CTRL_BHI_DIS_S
+    - x86/bhi: Enumerate Branch History Injection (BHI) bug
+    - x86/bhi: Add BHI mitigation knob
+    - x86/bhi: Mitigate KVM by default
+    - [Config] updateconfigs for CONFIG_BHI_{AUTO|ON|OFF}
+    - x86/bugs: Fix BHI documentation
+    - x86/bugs: Cache the value of MSR_IA32_ARCH_CAPABILITIES
+    - x86/bugs: Rename various 'ia32_cap' variables to 'x86_arch_cap_msr'
+    - x86/bugs: Fix BHI handling of RRSBA
+    - x86/bugs: Clarify that syscall hardening isn't a BHI mitigation
+    - x86/bugs: Fix BHI retpoline check
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Tue, 18 Jun 2024 08:47:37 +1000
+
+linux-xilinx-zynqmp (5.4.0-1046.50) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1046.50 -proposed tracker (LP: #2068289)
+
+  [ Ubuntu: 5.4.0-187.207 ]
+
+  * focal/linux: 5.4.0-187.207 -proposed tracker (LP: #2068291)
+  * CVE-2024-26925
+    - netfilter: Cleanup nft_net->module_list from nf_tables_exit_net()
+    - netfilter: nf_tables: release batch on table validation from abort path
+    - netfilter: nf_tables: release mutex after nft_gc_seq_end from abort path
+  * CVE-2024-26643
+    - netfilter: nf_tables: mark set as dead when unbinding anonymous set with
+      timeout
+  * CVE-2024-2201
+    - x86/cpufeatures: Add new word for scattered features
+    - x86/cpufeatures: Add CPUID_LNX_5 to track recently added Linux-defined word
+    - x86/bugs: Change commas to semicolons in 'spectre_v2' sysfs file
+    - x86/bhi: Add support for clearing branch history at syscall entry
+    - x86/bhi: Define SPEC_CTRL_BHI_DIS_S
+    - x86/bhi: Enumerate Branch History Injection (BHI) bug
+    - x86/bhi: Add BHI mitigation knob
+    - x86/bhi: Mitigate KVM by default
+    - [Config] updateconfigs for CONFIG_BHI_{AUTO|ON|OFF}
+    - x86/bugs: Fix BHI documentation
+    - x86/bugs: Cache the value of MSR_IA32_ARCH_CAPABILITIES
+    - x86/bugs: Rename various 'ia32_cap' variables to 'x86_arch_cap_msr'
+    - x86/bugs: Fix BHI handling of RRSBA
+    - x86/bugs: Clarify that syscall hardening isn't a BHI mitigation
+    - x86/bugs: Fix BHI retpoline check
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Fri, 14 Jun 2024 08:41:35 +1000
+
+linux-xilinx-zynqmp (5.4.0-1045.49) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1045.49 -proposed tracker (LP: #2063809)
+
+  [ Ubuntu: 5.4.0-186.206 ]
+
+  * focal/linux: 5.4.0-186.206 -proposed tracker (LP: #2063812)
+  * Mount CIFS fails with Permission denied (LP: #2061986)
+    - cifs: fix ntlmssp auth when there is no key exchange
+  * USB stick can't be detected (LP: #2040948)
+    - usb: Disable USB3 LPM at shutdown
+  * CVE-2024-26733
+    - net: dev: Convert sa_data to flexible array in struct sockaddr
+    - arp: Prevent overflow in arp_req_get().
+    - stddef: Introduce DECLARE_FLEX_ARRAY() helper
+  * CVE-2024-26712
+    - powerpc/kasan: Fix addr error caused by page alignment
+  * CVE-2023-52530
+    - wifi: mac80211: fix potential key use-after-free
+  * CVE-2021-47063
+    - drm: bridge/panel: Cleanup connector on bridge detach
+  * [Ubuntu 22.04.4/linux-image-6.5.0-26-generic] Kernel output "UBSAN: array-
+    index-out-of-bounds in /build/linux-hwe-6.5-34pCLi/linux-
+    hwe-6.5-6.5.0/drivers/net/hyperv/netvsc.c:1445:41" multiple times,
+    especially during boot. (LP: #2058477)
+    - hv: hyperv.h: Replace one-element array with flexible-array member
+  * CVE-2024-26614
+    - tcp: make sure init the accept_queue's spinlocks once
+    - ipv6: init the accept_queue's spinlocks in inet6_create
+  * Focal update: v5.4.271 upstream stable release (LP: #2060216)
+    - netlink: Fix kernel-infoleak-after-free in __skb_datagram_iter
+    - net: ip_tunnel: prevent perpetual headroom growth
+    - tun: Fix xdp_rxq_info's queue_index when detaching
+    - ipv6: fix potential "struct net" leak in inet6_rtm_getaddr()
+    - lan78xx: enable auto speed configuration for LAN7850 if no EEPROM is
+      detected
+    - net: usb: dm9601: fix wrong return value in dm9601_mdio_read
+    - Bluetooth: Avoid potential use-after-free in hci_error_reset
+    - Bluetooth: hci_event: Fix handling of HCI_EV_IO_CAPA_REQUEST
+    - Bluetooth: Enforce validation on max value of connection interval
+    - netfilter: nf_tables: allow NFPROTO_INET in nft_(match/target)_validate()
+    - rtnetlink: fix error logic of IFLA_BRIDGE_FLAGS writing back
+    - efi/capsule-loader: fix incorrect allocation size
+    - power: supply: bq27xxx-i2c: Do not free non existing IRQ
+    - ALSA: Drop leftover snd-rtctimer stuff from Makefile
+    - afs: Fix endless loop in directory parsing
+    - gtp: fix use-after-free and null-ptr-deref in gtp_newlink()
+    - wifi: nl80211: reject iftype change with mesh ID change
+    - btrfs: dev-replace: properly validate device names
+    - dmaengine: fsl-qdma: fix SoC may hang on 16 byte unaligned read
+    - dmaengine: fsl-qdma: init irq after reg initialization
+    - mmc: core: Fix eMMC initialization with 1-bit bus connection
+    - x86/cpu/intel: Detect TME keyid bits before setting MTRR mask registers
+    - cachefiles: fix memory leak in cachefiles_add_cache()
+    - fs,hugetlb: fix NULL pointer dereference in hugetlbs_fill_super
+    - gpio: 74x164: Enable output pins after registers are reset
+    - Linux 5.4.271
+  * Focal update: v5.4.270 upstream stable release (LP: #2060019)
+    - KVM: arm64: vgic-its: Test for valid IRQ in its_sync_lpi_pending_table()
+    - KVM: arm64: vgic-its: Test for valid IRQ in MOVALL handler
+    - net/sched: Retire CBQ qdisc
+    - [Config] updateconfigs for NET_SCH_CBQ
+    - net/sched: Retire ATM qdisc
+    - [Config] updateconfigs for NET_SCH_ATM
+    - net/sched: Retire dsmark qdisc
+    - [Config] updateconfigs for NET_SCH_DSMARK
+    - sched/rt: sysctl_sched_rr_timeslice show default timeslice after reset
+    - memcg: add refcnt for pcpu stock to avoid UAF problem in drain_all_stock()
+    - nilfs2: replace WARN_ONs for invalid DAT metadata block requests
+    - userfaultfd: fix mmap_changing checking in mfill_atomic_hugetlb
+    - sched/rt: Fix sysctl_sched_rr_timeslice intial value
+    - sched/rt: Disallow writing invalid values to sched_rt_period_us
+    - scsi: target: core: Add TMF to tmr_list handling
+    - dmaengine: shdma: increase size of 'dev_id'
+    - dmaengine: fsl-qdma: increase size of 'irq_name'
+    - wifi: cfg80211: fix missing interfaces when dumping
+    - wifi: mac80211: fix race condition on enabling fast-xmit
+    - fbdev: savage: Error out if pixclock equals zero
+    - fbdev: sis: Error out if pixclock equals zero
+    - ahci: asm1166: correct count of reported ports
+    - ahci: add 43-bit DMA address quirk for ASMedia ASM1061 controllers
+    - ext4: avoid allocating blocks from corrupted group in
+      ext4_mb_try_best_found()
+    - ext4: avoid allocating blocks from corrupted group in ext4_mb_find_by_goal()
+    - regulator: pwm-regulator: Add validity checks in continuous .get_voltage
+    - nvmet-tcp: fix nvme tcp ida memory leak
+    - ASoC: sunxi: sun4i-spdif: Add support for Allwinner H616
+    - netfilter: conntrack: check SCTP_CID_SHUTDOWN_ACK for vtag setting in
+      sctp_new
+    - nvmet-fc: abort command when there is no binding
+    - hwmon: (coretemp) Enlarge per package core count limit
+    - scsi: lpfc: Use unsigned type for num_sge
+    - firewire: core: send bus reset promptly on gap count error
+    - virtio-blk: Ensure no requests in virtqueues before deleting vqs.
+    - s390/qeth: Fix potential loss of L3-IP@ in case of network issues
+    - pmdomain: renesas: r8a77980-sysc: CR7 must be always on
+    - tcp: factor out __tcp_close() helper
+    - tcp: return EPOLLOUT from tcp_poll only when notsent_bytes is half the limit
+    - tcp: add annotations around sk->sk_shutdown accesses
+    - pinctrl: pinctrl-rockchip: Fix a bunch of kerneldoc misdemeanours
+    - pinctrl: rockchip: Fix refcount leak in rockchip_pinctrl_parse_groups
+    - spi: mt7621: Fix an error message in mt7621_spi_probe()
+    - net: bridge: clear bridge's private skb space on xmit
+    - selftests/bpf: Avoid running unprivileged tests with alignment requirements
+    - Revert "drm/sun4i: dsi: Change the start delay calculation"
+    - drm/amdgpu: Check for valid number of registers to read
+    - x86/alternatives: Disable KASAN in apply_alternatives()
+    - dm-integrity: don't modify bio's immutable bio_vec in integrity_metadata()
+    - iomap: Set all uptodate bits for an Uptodate page
+    - drm/amdgpu: Fix type of second parameter in trans_msg() callback
+    - arm64: dts: qcom: msm8916: Fix typo in pronto remoteproc node
+    - PCI: tegra: Fix reporting GPIO error value
+    - PCI: tegra: Fix OF node reference leak
+    - IB/hfi1: Fix sdma.h tx->num_descs off-by-one error
+    - dm-crypt: don't modify the data when using authenticated encryption
+    - gtp: fix use-after-free and null-ptr-deref in gtp_genl_dump_pdp()
+    - PCI/MSI: Prevent MSI hardware interrupt number truncation
+    - l2tp: pass correct message length to ip6_append_data
+    - ARM: ep93xx: Add terminator to gpiod_lookup_table
+    - usb: cdns3: fixed memory use after free at cdns3_gadget_ep_disable()
+    - usb: cdns3: fix memory double free when handle zero packet
+    - usb: gadget: ncm: Avoid dropping datagrams of properly parsed NTBs
+    - usb: roles: don't get/set_role() when usb_role_switch is unregistered
+    - IB/hfi1: Fix a memleak in init_credit_return
+    - RDMA/bnxt_re: Return error for SRQ resize
+    - RDMA/srpt: Make debug output more detailed
+    - RDMA/srpt: fix function pointer cast warnings
+    - scripts/bpf: teach bpf_helpers_doc.py to dump BPF helper definitions
+    - bpf, scripts: Correct GPL license name
+    - scsi: jazz_esp: Only build if SCSI core is builtin
+    - nouveau: fix function cast warnings
+    - ipv4: properly combine dev_base_seq and ipv4.dev_addr_genid
+    - ipv6: properly combine dev_base_seq and ipv6.dev_addr_genid
+    - afs: Increase buffer size in afs_update_volume_status()
+    - ipv6: sr: fix possible use-after-free and null-ptr-deref
+    - packet: move from strlcpy with unused retval to strscpy
+    - s390: use the correct count for __iowrite64_copy()
+    - tls: rx: jump to a more appropriate label
+    - tls: rx: drop pointless else after goto
+    - tls: stop recv() if initial process_rx_list gave us non-DATA
+    - netfilter: nf_tables: set dormant flag on hook register failure
+    - drm/syncobj: make lockdep complain on WAIT_FOR_SUBMIT v3
+    - drm/syncobj: call drm_syncobj_fence_add_wait when WAIT_AVAILABLE flag is set
+    - fs/aio: Restrict kiocb_set_cancel_fn() to I/O submitted via libaio
+    - scripts/bpf: Fix xdp_md forward declaration typo
+    - Linux 5.4.270
+  * CVE-2023-47233
+    - wifi: brcmfmac: Fix use-after-free bug in brcmf_cfg80211_detach
+  * CVE-2021-47070
+    - uio: uio_hv_generic: use devm_kzalloc() for private data alloc
+    - uio_hv_generic: Fix another memory leak in error handling paths
+  * CVE-2024-26622
+    - tomoyo: fix UAF write bug in tomoyo_write_control()
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Tue, 21 May 2024 12:47:20 +1000
+
+linux-xilinx-zynqmp (5.4.0-1044.48) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1044.48 -proposed tracker (LP: #2063683)
+
+  [ Ubuntu: 5.4.0-182.202 ]
+
+  * focal/linux: 5.4.0-182.202 -proposed tracker (LP: #2063685)
+  * CVE-2023-52530
+    - wifi: mac80211: fix potential key use-after-free
+  * CVE-2024-26622
+    - tomoyo: fix UAF write bug in tomoyo_write_control()
+  * CVE-2024-26614
+    - tcp: make sure init the accept_queue's spinlocks once
+    - ipv6: init the accept_queue's spinlocks in inet6_create
+  * CVE-2023-47233
+    - wifi: brcmfmac: Fix use-after-free bug in brcmf_cfg80211_detach
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Tue, 07 May 2024 10:22:39 +1000
+
+linux-xilinx-zynqmp (5.4.0-1043.47) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1043.47 -proposed tracker (LP: #2059547)
+
+  * Focal update: v5.4.269 upstream stable release (LP: #2058948)
+    - [Config] updateconfigs for MFD_TI_AM335X_TSCADC
+
+  [ Ubuntu: 5.4.0-181.201 ]
+
+  * focal/linux: 5.4.0-181.201 -proposed tracker (LP: #2059549)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] drop getabis data
+  * Drop fips-checks script from trees (LP: #2055083)
+    - [Packaging] Remove fips-checks script
+  * Remove getabis scripts (LP: #2059143)
+    - [Packaging] Remove getabis
+  * Focal update: v5.4.269 upstream stable release (LP: #2058948)
+    - PCI: mediatek: Clear interrupt status before dispatching handler
+    - include/linux/units.h: add helpers for kelvin to/from Celsius conversion
+    - units: Add Watt units
+    - units: change from 'L' to 'UL'
+    - units: add the HZ macros
+    - serial: sc16is7xx: set safe default SPI clock frequency
+    - spi: introduce SPI_MODE_X_MASK macro
+    - serial: sc16is7xx: add check for unsupported SPI modes during probe
+    - ext4: allow for the last group to be marked as trimmed
+    - crypto: api - Disallow identical driver names
+    - PM: hibernate: Enforce ordering during image compression/decompression
+    - hwrng: core - Fix page fault dead lock on mmap-ed hwrng
+    - rpmsg: virtio: Free driver_override when rpmsg_remove()
+    - parisc/firmware: Fix F-extend for PDC addresses
+    - arm64: dts: qcom: sdm845: fix USB wakeup interrupt types
+    - mmc: core: Use mrq.sbc in close-ended ffu
+    - nouveau/vmm: don't set addr on the fail path to avoid warning
+    - ubifs: ubifs_symlink: Fix memleak of inode->i_link in error path
+    - rename(): fix the locking of subdirectories
+    - block: Remove special-casing of compound pages
+    - mtd: spinand: macronix: Fix MX35LFxGE4AD page size
+    - fs: add mode_strip_sgid() helper
+    - fs: move S_ISGID stripping into the vfs_*() helpers
+    - powerpc: Use always instead of always-y in for crtsavres.o
+    - x86/CPU/AMD: Fix disabling XSAVES on AMD family 0x17 due to erratum
+    - net/smc: fix illegal rmb_desc access in SMC-D connection dump
+    - vlan: skip nested type that is not IFLA_VLAN_QOS_MAPPING
+    - llc: make llc_ui_sendmsg() more robust against bonding changes
+    - llc: Drop support for ETH_P_TR_802_2.
+    - net/rds: Fix UBSAN: array-index-out-of-bounds in rds_cmsg_recv
+    - tracing: Ensure visibility when inserting an element into tracing_map
+    - afs: Hide silly-rename files from userspace
+    - tcp: Add memory barrier to tcp_push()
+    - netlink: fix potential sleeping issue in mqueue_flush_file
+    - net/mlx5: DR, Use the right GVMI number for drop action
+    - net/mlx5: Use kfree(ft->g) in arfs_create_groups()
+    - net/mlx5e: fix a double-free in arfs_create_groups
+    - netfilter: nf_tables: restrict anonymous set and map names to 16 bytes
+    - netfilter: nf_tables: validate NFPROTO_* family
+    - fjes: fix memleaks in fjes_hw_setup
+    - net: fec: fix the unhandled context fault from smmu
+    - btrfs: ref-verify: free ref cache before clearing mount opt
+    - btrfs: tree-checker: fix inline ref size in error messages
+    - btrfs: don't warn if discard range is not aligned to sector
+    - btrfs: defrag: reject unknown flags of btrfs_ioctl_defrag_range_args
+    - rbd: don't move requests to the running list on errors
+    - gpiolib: acpi: Ignore touchpad wakeup on GPD G1619-04
+    - drm: Don't unref the same fb many times by mistake due to deadlock handling
+    - drm/bridge: nxp-ptn3460: fix i2c_master_send() error checking
+    - drm/bridge: nxp-ptn3460: simplify some error checking
+    - drm/exynos: fix accidental on-stack copy of exynos_drm_plane
+    - drm/exynos: gsc: minor fix for loop iteration in gsc_runtime_resume
+    - gpio: eic-sprd: Clear interrupt after set the interrupt type
+    - spi: bcm-qspi: fix SFDP BFPT read by usig mspi read
+    - mips: Call lose_fpu(0) before initializing fcr31 in mips_set_personality_nan
+    - tick/sched: Preserve number of idle sleeps across CPU hotplug events
+    - x86/entry/ia32: Ensure s32 is sign extended to s64
+    - powerpc/mm: Fix null-pointer dereference in pgtable_cache_add
+    - powerpc: Fix build error due to is_valid_bugaddr()
+    - powerpc/mm: Fix build failures due to arch_reserved_kernel_pages()
+    - powerpc: pmd_move_must_withdraw() is only needed for
+      CONFIG_TRANSPARENT_HUGEPAGE
+    - powerpc/lib: Validate size for vector operations
+    - x86/mce: Mark fatal MCE's page as poison to avoid panic in the kdump kernel
+    - perf/core: Fix narrow startup race when creating the perf nr_addr_filters
+      sysfs file
+    - regulator: core: Only increment use_count when enable_count changes
+    - audit: Send netlink ACK before setting connection in auditd_set
+    - ACPI: video: Add quirk for the Colorful X15 AT 23 Laptop
+    - PNP: ACPI: fix fortify warning
+    - ACPI: extlog: fix NULL pointer dereference check
+    - FS:JFS:UBSAN:array-index-out-of-bounds in dbAdjTree
+    - jfs: fix slab-out-of-bounds Read in dtSearch
+    - jfs: fix array-index-out-of-bounds in dbAdjTree
+    - pstore/ram: Fix crash when setting number of cpus to an odd number
+    - crypto: stm32/crc32 - fix parsing list of devices
+    - afs: fix the usage of read_seqbegin_or_lock() in afs_find_server*()
+    - rxrpc_find_service_conn_rcu: fix the usage of read_seqbegin_or_lock()
+    - jfs: fix array-index-out-of-bounds in diNewExt
+    - s390/ptrace: handle setting of fpc register correctly
+    - KVM: s390: fix setting of fpc register
+    - SUNRPC: Fix a suspicious RCU usage warning
+    - ecryptfs: Reject casefold directory inodes
+    - ext4: fix inconsistent between segment fstrim and full fstrim
+    - ext4: unify the type of flexbg_size to unsigned int
+    - ext4: remove unnecessary check from alloc_flex_gd()
+    - ext4: avoid online resizing failures due to oversized flex bg
+    - wifi: rt2x00: restart beacon queue when hardware reset
+    - selftests/bpf: satisfy compiler by having explicit return in btf test
+    - selftests/bpf: Fix pyperf180 compilation failure with clang18
+    - scsi: lpfc: Fix possible file string name overflow when updating firmware
+    - PCI: Add no PM reset quirk for NVIDIA Spectrum devices
+    - bonding: return -ENOMEM instead of BUG in alb_upper_dev_walk
+    - ARM: dts: imx7d: Fix coresight funnel ports
+    - ARM: dts: imx7s: Fix lcdif compatible
+    - ARM: dts: imx7s: Fix nand-controller #size-cells
+    - wifi: ath9k: Fix potential array-index-out-of-bounds read in
+      ath9k_htc_txstatus()
+    - bpf: Add map and need_defer parameters to .map_fd_put_ptr()
+    - scsi: libfc: Don't schedule abort twice
+    - scsi: libfc: Fix up timeout error in fc_fcp_rec_error()
+    - ARM: dts: rockchip: fix rk3036 hdmi ports node
+    - ARM: dts: imx25/27-eukrea: Fix RTC node name
+    - ARM: dts: imx: Use flash@0,0 pattern
+    - ARM: dts: imx27: Fix sram node
+    - ARM: dts: imx1: Fix sram node
+    - ARM: dts: imx25/27: Pass timing0
+    - ARM: dts: imx27-apf27dev: Fix LED name
+    - ARM: dts: imx23-sansa: Use preferred i2c-gpios properties
+    - ARM: dts: imx23/28: Fix the DMA controller node name
+    - block: prevent an integer overflow in bvec_try_merge_hw_page
+    - md: Whenassemble the array, consult the superblock of the freshest device
+    - arm64: dts: qcom: msm8996: Fix 'in-ports' is a required property
+    - arm64: dts: qcom: msm8998: Fix 'out-ports' is a required property
+    - wifi: rtl8xxxu: Add additional USB IDs for RTL8192EU devices
+    - wifi: rtlwifi: rtl8723{be,ae}: using calculate_bit_shift()
+    - wifi: cfg80211: free beacon_ies when overridden from hidden BSS
+    - f2fs: fix to check return value of f2fs_reserve_new_block()
+    - ASoC: doc: Fix undefined SND_SOC_DAPM_NOPM argument
+    - fast_dput(): handle underflows gracefully
+    - RDMA/IPoIB: Fix error code return in ipoib_mcast_join
+    - drm/drm_file: fix use of uninitialized variable
+    - drm/framebuffer: Fix use of uninitialized variable
+    - drm/mipi-dsi: Fix detach call without attach
+    - media: stk1160: Fixed high volume of stk1160_dbg messages
+    - media: rockchip: rga: fix swizzling for RGB formats
+    - PCI: add INTEL_HDA_ARL to pci_ids.h
+    - ALSA: hda: Intel: add HDA_ARL PCI ID support
+    - drm/exynos: Call drm_atomic_helper_shutdown() at shutdown/unbind time
+    - IB/ipoib: Fix mcast list locking
+    - media: ddbridge: fix an error code problem in ddb_probe
+    - drm/msm/dpu: Ratelimit framedone timeout msgs
+    - clk: hi3620: Fix memory leak in hi3620_mmc_clk_init()
+    - clk: mmp: pxa168: Fix memory leak in pxa168_clk_init()
+    - drm/amdgpu: Let KFD sync with VM fences
+    - drm/amdgpu: Drop 'fence' check in 'to_amdgpu_amdkfd_fence()'
+    - leds: trigger: panic: Don't register panic notifier if creating the trigger
+      failed
+    - um: Fix naming clash between UML and scheduler
+    - um: Don't use vfprintf() for os_info()
+    - um: net: Fix return type of uml_net_start_xmit()
+    - i3c: master: cdns: Update maximum prescaler value for i2c clock
+    - mfd: ti_am335x_tscadc: Fix TI SoC dependencies
+    - [Config] updateconfigs for MFD_TI_AM335X_TSCADC
+    - PCI: Only override AMD USB controller if required
+    - PCI: switchtec: Fix stdev_release() crash after surprise hot remove
+    - usb: hub: Replace hardcoded quirk value with BIT() macro
+    - fs/kernfs/dir: obey S_ISGID
+    - PCI/AER: Decode Requester ID when no error info found
+    - libsubcmd: Fix memory leak in uniq()
+    - virtio_net: Fix "‘%d’ directive writing between 1 and 11 bytes into a region
+      of size 10" warnings
+    - blk-mq: fix IO hang from sbitmap wakeup race
+    - ceph: fix deadlock or deadcode of misusing dget()
+    - drm/amdgpu: Release 'adev->pm.fw' before return in
+      'amdgpu_device_need_post()'
+    - perf: Fix the nr_addr_filters fix
+    - wifi: cfg80211: fix RCU dereference in __cfg80211_bss_update
+    - scsi: isci: Fix an error code problem in isci_io_request_build()
+    - net: remove unneeded break
+    - ixgbe: Remove non-inclusive language
+    - ixgbe: Refactor returning internal error codes
+    - ixgbe: Refactor overtemp event handling
+    - ixgbe: Fix an error handling path in ixgbe_read_iosf_sb_reg_x550()
+    - ipv6: Ensure natural alignment of const ipv6 loopback and router addresses
+    - llc: call sock_orphan() at release time
+    - netfilter: nf_log: replace BUG_ON by WARN_ON_ONCE when putting logger
+    - netfilter: nft_ct: sanitize layer 3 and 4 protocol number in custom
+      expectations
+    - net: ipv4: fix a memleak in ip_setup_cork
+    - af_unix: fix lockdep positive in sk_diag_dump_icons()
+    - SAUCE: Sync apparmor copy of af_unix.c
+    - net: sysfs: Fix /sys/class/net/<iface> path
+    - HID: apple: Add support for the 2021 Magic Keyboard
+    - HID: apple: Swap the Fn and Left Control keys on Apple keyboards
+    - HID: apple: Add 2021 magic keyboard FN key mapping
+    - bonding: remove print in bond_verify_device_path
+    - dmaengine: fsl-qdma: Fix a memory leak related to the status queue DMA
+    - dmaengine: fsl-qdma: Fix a memory leak related to the queue command DMA
+    - phy: renesas: rcar-gen3-usb2: Fix returning wrong error code
+    - dmaengine: fix is_slave_direction() return false when DMA_DEV_TO_DEV
+    - phy: ti: phy-omap-usb2: Fix NULL pointer dereference for SRP
+    - net: stmmac: xgmac: fix handling of DPP safety error for DMA channels
+    - selftests: net: avoid just another constant wait
+    - atm: idt77252: fix a memleak in open_card_ubr0
+    - hwmon: (aspeed-pwm-tacho) mutex for tach reading
+    - hwmon: (coretemp) Fix out-of-bounds memory access
+    - hwmon: (coretemp) Fix bogus core_id to attr name mapping
+    - inet: read sk->sk_family once in inet_recv_error()
+    - rxrpc: Fix response to PING RESPONSE ACKs to a dead call
+    - tipc: Check the bearer type before calling tipc_udp_nl_bearer_add()
+    - ppp_async: limit MRU to 64K
+    - netfilter: nft_compat: reject unused compat flag
+    - netfilter: nft_compat: restrict match/target protocol to u16
+    - netfilter: nft_ct: reject direction for ct id
+    - net/af_iucv: clean up a try_then_request_module()
+    - USB: serial: qcserial: add new usb-id for Dell Wireless DW5826e
+    - USB: serial: option: add Fibocom FM101-GL variant
+    - USB: serial: cp210x: add ID for IMST iM871A-USB
+    - hrtimer: Report offline hrtimer enqueue
+    - Input: atkbd - skip ATKBD_CMD_SETLEDS when skipping ATKBD_CMD_GETID
+    - net: stmmac: xgmac: use #define for string constants
+    - net: stmmac: xgmac: fix a typo of register name in DPP safety handling
+    - btrfs: forbid creating subvol qgroups
+    - btrfs: forbid deleting live subvol qgroup
+    - btrfs: send: return EOPNOTSUPP on unknown flags
+    - of: unittest: add overlay gpio test to catch gpio hog problem
+    - of: unittest: Fix compile in the non-dynamic case
+    - spi: ppc4xx: Drop write-only variable
+    - ASoC: rt5645: Fix deadlock in rt5645_jack_detect_work()
+    - MIPS: Add 'memory' clobber to csum_ipv6_magic() inline assembler
+    - i40e: Fix waiting for queues of all VSIs to be disabled
+    - tracing/trigger: Fix to return error if failed to alloc snapshot
+    - mm/writeback: fix possible divide-by-zero in wb_dirty_limits(), again
+    - HID: wacom: generic: Avoid reporting a serial of '0' to userspace
+    - HID: wacom: Do not register input devices until after hid_hw_start
+    - USB: hub: check for alternate port before enabling A_ALT_HNP_SUPPORT
+    - usb: f_mass_storage: forbid async queue when shutdown happen
+    - i2c: i801: Remove i801_set_block_buffer_mode
+    - i2c: i801: Fix block process call transactions
+    - scsi: Revert "scsi: fcoe: Fix potential deadlock on &fip->ctlr_lock"
+    - firewire: core: correct documentation of fw_csr_string() kernel API
+    - kbuild: Fix changing ELF file type for output of gen_btf for big endian
+    - nfc: nci: free rx_data_reassembly skb on NCI device cleanup
+    - xen-netback: properly sync TX responses
+    - ALSA: hda/realtek: Enable headset mic on Vaio VJFE-ADL
+    - binder: signal epoll threads of self-work
+    - misc: fastrpc: Mark all sessions as invalid in cb_remove
+    - ext4: fix double-free of blocks due to wrong extents moved_len
+    - tracing: Fix wasted memory in saved_cmdlines logic
+    - staging: iio: ad5933: fix type mismatch regression
+    - iio: magnetometer: rm3100: add boundary check for the value read from
+      RM3100_REG_TMRC
+    - ring-buffer: Clean ring_buffer_poll_wait() error return
+    - serial: max310x: set default value when reading clock ready bit
+    - serial: max310x: improve crystal stable clock detection
+    - x86/Kconfig: Transmeta Crusoe is CPU family 5, not 6
+    - x86/mm/ident_map: Use gbpages only where full GB page should be mapped.
+    - mmc: slot-gpio: Allow non-sleeping GPIO ro
+    - ALSA: hda/conexant: Add quirk for SWS JS201D
+    - nilfs2: fix data corruption in dsync block recovery for small block sizes
+    - nilfs2: fix hang in nilfs_lookup_dirty_data_buffers()
+    - nfp: use correct macro for LengthSelect in BAR config
+    - nfp: flower: prevent re-adding mac index for bonded port
+    - irqchip/irq-brcmstb-l2: Add write memory barrier before exit
+    - can: j1939: Fix UAF in j1939_sk_match_filter during
+      setsockopt(SO_J1939_FILTER)
+    - pmdomain: core: Move the unused cleanup to a _sync initcall
+    - tracing: Inform kmemleak of saved_cmdlines allocation
+    - Revert "md/raid5: Wait for MD_SB_CHANGE_PENDING in raid5d"
+    - bus: moxtet: Add spi device table
+    - arch, mm: remove stale mentions of DISCONIGMEM
+    - mips: Fix max_mapnr being uninitialized on early stages
+    - KVM: arm64: vgic-its: Avoid potential UAF in LPI translation cache
+    - netfilter: ipset: fix performance regression in swap operation
+    - netfilter: ipset: Missing gc cancellations fixed
+    - net: prevent mss overflow in skb_segment()
+    - sched/membarrier: reduce the ability to hammer on sys_membarrier
+    - nilfs2: fix potential bug in end_buffer_async_write
+    - PM: runtime: add devm_pm_runtime_enable helper
+    - PM: runtime: Have devm_pm_runtime_enable() handle
+      pm_runtime_dont_use_autosuspend()
+    - drm/msm/dsi: Enable runtime PM
+    - lsm: new security_file_ioctl_compat() hook
+    - Revert "Revert "mtd: rawnand: gpmi: Fix setting busy timeout setting""
+    - net: bcmgenet: Fix EEE implementation
+    - of: unittest: fix EXPECT text for gpio hog errors
+    - of: gpio unittest kfree() wrong object
+    - Linux 5.4.269
+  * Focal update: v5.4.269 upstream stable release (LP: #2058948) //
+    CVE-2023-52603
+    - UBSAN: array-index-out-of-bounds in dtSplitRoot
+  * CVE-2023-52600
+    - jfs: fix uaf in jfs_evict_inode
+  * CVE-2023-24023
+    - Bluetooth: Add more enc key size check
+  * CVE-2024-26581
+    - netfilter: nf_tables: nft_set_rbtree: fix spurious insertion failure
+    - netfilter: nft_set_rbtree: skip end interval element from gc
+  * CVE-2024-26589
+    - bpf: Reject variable offset alu on PTR_TO_FLOW_KEYS
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Fri, 12 Apr 2024 13:50:59 +1000
+
+linux-xilinx-zynqmp (5.4.0-1042.46) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1042.46 -proposed tracker (LP: #2059631)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] drop getabis data
+
+  [ Ubuntu: 5.4.0-177.197 ]
+
+  * focal/linux: 5.4.0-177.197 -proposed tracker (LP: #2059633)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] drop getabis data
+  * Remove getabis scripts (LP: #2059143)
+    - [Packaging] Remove getabis
+  * CVE-2023-24023
+    - Bluetooth: Add more enc key size check
+  * CVE-2023-52600
+    - jfs: fix uaf in jfs_evict_inode
+  * Focal update: v5.4.269 upstream stable release (LP: #2058948) //
+    CVE-2023-52603
+    - UBSAN: array-index-out-of-bounds in dtSplitRoot
+  * CVE-2024-26581
+    - netfilter: nf_tables: nft_set_rbtree: fix spurious insertion failure
+    - netfilter: nft_set_rbtree: skip end interval element from gc
+  * CVE-2024-26589
+    - bpf: Reject variable offset alu on PTR_TO_FLOW_KEYS
+
+  [ Ubuntu: 5.4.0-176.196 ]
+
+  * focal/linux: 5.4.0-176.196 -proposed tracker (LP: #2058756)
+  * Problems with HVCS and hotplugging (LP: #2056373)
+    - powerpc/pseries: Fix bad drc_index_start value parsing of drc-info entry
+    - powerpc/pseries: Fix of_read_drc_info_cell() to point at next record
+    - hvcs: Fix hvcs port reference counting
+    - hvcs: Use dev_groups to manage hvcs device attributes
+    - hvcs: Use driver groups to manage driver attributes
+    - hvcs: Get reference to tty in remove
+    - hvcs: Use vhangup in hotplug remove
+    - hvcs: Synchronize hotplug remove with port free
+
+ -- Aaron Jauregui <aaron.jauregui@canonical.com>  Thu, 04 Apr 2024 16:22:56 +1100
+
+linux-xilinx-zynqmp (5.4.0-1041.45) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1041.45 -proposed tracker (LP: #2055682)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] drop ABI data
+    - debian.zynqmp/dkms-versions -- update from kernel-versions (main/2024.03.04)
+
+  * Focal update: v5.4.268 upstream stable release (LP: #2055075)
+    - [Config] update annotations for CONFIG_MMC_SDHCI_OMAP
+
+  * Focal update: v5.4.267 upstream stable release (LP: #2054406)
+    - [Config] Update annotations for CONFIG_SND_MESON_CODEC_GLUE
+
+  [ Ubuntu: 5.4.0-175.195 ]
+
+  * focal/linux: 5.4.0-175.195 -proposed tracker (LP: #2055684)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] drop ABI data
+    - [Packaging] update annotations scripts
+    - debian.master/dkms-versions -- update from kernel-versions (main/2024.03.04)
+  * Drop ABI checks from kernel build (LP: #2055686)
+    - [Packaging] Remove in-tree abi checks
+    - [Packaging] Bring back install-<flavour> prerequisite for checks-<flavour>
+    - [Packaging] Remove abi-check from final-checks
+  * Cranky update-dkms-versions rollout (LP: #2055685)
+    - [Packaging] remove update-dkms-versions
+    - Move debian/dkms-versions to debian.master/dkms-versions
+    - [Packaging] Replace debian/dkms-versions with $(DEBIAN)/dkms-versions
+    - [Packaging] remove update-version-dkms
+  * linux-tools-common: man page of usbip[d] is misplaced (LP: #2054094)
+    - [Packaging] rules: Put usbip manpages in the correct directory
+  * CVE-2024-23851
+    - dm ioctl: log an error if the ioctl structure is corrupted
+    - dm: limit the number of targets and parameter size area
+  * Focal update: v5.4.268 upstream stable release (LP: #2055075)
+    - f2fs: explicitly null-terminate the xattr list
+    - pinctrl: lochnagar: Don't build on MIPS
+    - ALSA: hda - Fix speaker and headset mic pin config for CHUWI CoreBook XPro
+    - ASoC: Intel: Skylake: Fix mem leak in few functions
+    - ASoC: nau8822: Fix incorrect type in assignment and cast to restricted
+      __be16
+    - ASoC: Intel: Skylake: mem leak in skl register function
+    - ASoC: cs43130: Fix the position of const qualifier
+    - ASoC: cs43130: Fix incorrect frame delay configuration
+    - ASoC: rt5650: add mutex to avoid the jack detection failure
+    - nouveau/tu102: flush all pdbs on vmm flush
+    - net/tg3: fix race condition in tg3_reset_task()
+    - ASoC: da7219: Support low DC impedance headset
+    - nvme: introduce helper function to get ctrl state
+    - drm/exynos: fix a potential error pointer dereference
+    - drm/exynos: fix a wrong error checking
+    - clk: rockchip: rk3128: Fix HCLK_OTG gate register
+    - jbd2: correct the printing of write_flags in jbd2_write_superblock()
+    - drm/crtc: Fix uninit-value bug in drm_mode_setcrtc
+    - neighbour: Don't let neigh_forced_gc() disable preemption for long
+    - tracing: Have large events show up as '[LINE TOO BIG]' instead of nothing
+    - tracing: Add size check when printing trace_marker output
+    - ring-buffer: Do not record in NMI if the arch does not support cmpxchg in
+      NMI
+    - reset: hisilicon: hi6220: fix Wvoid-pointer-to-enum-cast warning
+    - Input: atkbd - skip ATKBD_CMD_GETID in translated mode
+    - Input: i8042 - add nomux quirk for Acer P459-G2-M
+    - s390/scm: fix virtual vs physical address confusion
+    - ARC: fix spare error
+    - Input: xpad - add Razer Wolverine V2 support
+    - ARM: sun9i: smp: fix return code check of of_property_match_string
+    - drm/crtc: fix uninitialized variable use
+    - ACPI: resource: Add another DMI match for the TongFang GMxXGxx
+    - binder: use EPOLLERR from eventpoll.h
+    - binder: fix trivial typo of binder_free_buf_locked()
+    - binder: fix comment on binder_alloc_new_buf() return value
+    - uio: Fix use-after-free in uio_open
+    - parport: parport_serial: Add Brainboxes BAR details
+    - parport: parport_serial: Add Brainboxes device IDs and geometry
+    - coresight: etm4x: Fix width of CCITMIN field
+    - x86/lib: Fix overflow when counting digits
+    - EDAC/thunderx: Fix possible out-of-bounds string access
+    - powerpc: add crtsavres.o to always-y instead of extra-y
+    - powerpc/44x: select I2C for CURRITUCK
+    - powerpc/pseries/memhotplug: Quieten some DLPAR operations
+    - powerpc/pseries/memhp: Fix access beyond end of drmem array
+    - selftests/powerpc: Fix error handling in FPU/VMX preemption tests
+    - powerpc/powernv: Add a null pointer check to scom_debug_init_one()
+    - powerpc/powernv: Add a null pointer check in opal_event_init()
+    - powerpc/powernv: Add a null pointer check in opal_powercap_init()
+    - powerpc/imc-pmu: Add a null pointer check in update_events_in_group()
+    - mtd: rawnand: Increment IFC_TIMEOUT_MSECS for nand controller response
+    - ACPI: video: check for error while searching for backlight device parent
+    - ACPI: LPIT: Avoid u32 multiplication overflow
+    - net: netlabel: Fix kerneldoc warnings
+    - netlabel: remove unused parameter in netlbl_netlink_auditinfo()
+    - calipso: fix memory leak in netlbl_calipso_add_pass()
+    - spi: sh-msiof: Enforce fixed DTDL for R-Car H3
+    - mtd: Fix gluebi NULL pointer dereference caused by ftl notifier
+    - selinux: Fix error priority for bind with AF_UNSPEC on PF_INET6 socket
+    - crypto: virtio - Handle dataq logic with tasklet
+    - crypto: virtio - don't use 'default m'
+    - virtio_crypto: Introduce VIRTIO_CRYPTO_NOSPC
+    - crypto: ccp - fix memleak in ccp_init_dm_workarea
+    - crypto: af_alg - Disallow multiple in-flight AIO requests
+    - crypto: sahara - remove FLAGS_NEW_KEY logic
+    - crypto: sahara - fix ahash selftest failure
+    - crypto: sahara - fix processing requests with cryptlen < sg->length
+    - crypto: sahara - fix error handling in sahara_hw_descriptor_create()
+    - pstore: ram_core: fix possible overflow in persistent_ram_init_ecc()
+    - gfs2: Fix kernel NULL pointer dereference in gfs2_rgrp_dump
+    - crypto: virtio - Wait for tasklet to complete on device remove
+    - crypto: sahara - fix ahash reqsize
+    - crypto: sahara - fix wait_for_completion_timeout() error handling
+    - crypto: sahara - improve error handling in sahara_sha_process()
+    - crypto: sahara - fix processing hash requests with req->nbytes < sg->length
+    - crypto: sahara - do not resize req->src when doing hash operations
+    - crypto: scomp - fix req->dst buffer overflow
+    - blocklayoutdriver: Fix reference leak of pnfs_device_node
+    - NFSv4.1/pnfs: Ensure we handle the error NFS4ERR_RETURNCONFLICT
+    - wifi: rtw88: fix RX filter in FIF_ALLMULTI flag
+    - bpf, lpm: Fix check prefixlen before walking trie
+    - wifi: libertas: stop selecting wext
+    - ARM: dts: qcom: apq8064: correct XOADC register address
+    - ncsi: internal.h: Fix a spello
+    - net/ncsi: Fix netlink major/minor version numbers
+    - firmware: ti_sci: Fix an off-by-one in ti_sci_debugfs_create()
+    - rtlwifi: Use ffs in <foo>_phy_calculate_bit_shift
+    - wifi: rtlwifi: rtl8821ae: phy: fix an undefined bitwise shift behavior
+    - scsi: fnic: Return error if vmalloc() failed
+    - arm64: dts: qcom: sdm845-db845c: correct LED panic indicator
+    - scsi: hisi_sas: Replace with standard error code return value
+    - selftests/net: fix grep checking for fib_nexthop_multiprefix
+    - virtio/vsock: fix logic which reduces credit update messages
+    - dma-mapping: clear dev->dma_mem to NULL after freeing it
+    - wifi: rtlwifi: add calculate_bit_shift()
+    - wifi: rtlwifi: rtl8188ee: phy: using calculate_bit_shift()
+    - wifi: rtlwifi: rtl8192c: using calculate_bit_shift()
+    - wifi: rtlwifi: rtl8192cu: using calculate_bit_shift()
+    - wifi: rtlwifi: rtl8192ce: using calculate_bit_shift()
+    - rtlwifi: rtl8192de: make arrays static const, makes object smaller
+    - wifi: rtlwifi: rtl8192de: using calculate_bit_shift()
+    - wifi: rtlwifi: rtl8192ee: using calculate_bit_shift()
+    - wifi: rtlwifi: rtl8192se: using calculate_bit_shift()
+    - netfilter: nf_tables: mark newset as dead on transaction abort
+    - Bluetooth: Fix bogus check for re-auth no supported with non-ssp
+    - Bluetooth: btmtkuart: fix recv_buf() return value
+    - ip6_tunnel: fix NEXTHDR_FRAGMENT handling in ip6_tnl_parse_tlv_enc_lim()
+    - ARM: davinci: always select CONFIG_CPU_ARM926T
+    - RDMA/usnic: Silence uninitialized symbol smatch warnings
+    - media: pvrusb2: fix use after free on context disconnection
+    - drm/bridge: Fix typo in post_disable() description
+    - f2fs: fix to avoid dirent corruption
+    - drm/radeon/r600_cs: Fix possible int overflows in r600_cs_check_reg()
+    - drm/radeon/r100: Fix integer overflow issues in r100_cs_track_check()
+    - drm/radeon: check return value of radeon_ring_lock()
+    - ASoC: cs35l33: Fix GPIO name and drop legacy include
+    - ASoC: cs35l34: Fix GPIO name and drop legacy include
+    - drm/msm/mdp4: flush vblank event on disable
+    - drm/msm/dsi: Use pm_runtime_resume_and_get to prevent refcnt leaks
+    - drm/drv: propagate errors from drm_modeset_register_all()
+    - drm/radeon: check the alloc_workqueue return value in radeon_crtc_init()
+    - drm/radeon/dpm: fix a memleak in sumo_parse_power_table
+    - drm/radeon/trinity_dpm: fix a memleak in trinity_parse_power_table
+    - drm/bridge: tc358767: Fix return value on error case
+    - media: cx231xx: fix a memleak in cx231xx_init_isoc
+    - media: dvbdev: drop refcount on error path in dvb_device_open()
+    - drm/amdgpu/debugfs: fix error code when smc register accessors are NULL
+    - drm/amd/pm: fix a double-free in si_dpm_init
+    - drivers/amd/pm: fix a use-after-free in kv_parse_power_table
+    - gpu/drm/radeon: fix two memleaks in radeon_vm_init
+    - drivers: clk: zynqmp: calculate closest mux rate
+    - watchdog: set cdev owner before adding
+    - watchdog/hpwdt: Only claim UNKNOWN NMI if from iLO
+    - watchdog: bcm2835_wdt: Fix WDIOC_SETTIMEOUT handling
+    - clk: si5341: fix an error code problem in si5341_output_clk_set_rate
+    - mmc: sdhci_omap: Fix TI SoC dependencies
+    - [Config] update annotations for CONFIG_MMC_SDHCI_OMAP
+    - [Config] remove sdhci-omap module for arm64/ppc64el
+    - of: Fix double free in of_parse_phandle_with_args_map
+    - of: unittest: Fix of_count_phandle_with_args() expected value message
+    - binder: fix async space check for 0-sized buffers
+    - binder: fix use-after-free in shinker's callback
+    - Input: atkbd - use ab83 as id when skipping the getid command
+    - Revert "ASoC: atmel: Remove system clock tree configuration for
+      at91sam9g20ek"
+    - binder: fix race between mmput() and do_exit()
+    - binder: fix unused alloc->free_async_space
+    - tick-sched: Fix idle and iowait sleeptime accounting vs CPU hotplug
+    - usb: phy: mxs: remove CONFIG_USB_OTG condition for mxs_phy_is_otg_host()
+    - usb: dwc: ep0: Update request status in dwc3_ep0_stall_restart
+    - Revert "usb: dwc3: Soft reset phy on probe for host"
+    - Revert "usb: dwc3: don't reset device side if dwc3 was configured as host-
+      only"
+    - usb: chipidea: wait controller resume finished for wakeup irq
+    - Revert "usb: typec: class: fix typec_altmode_put_partner to put plugs"
+    - usb: typec: class: fix typec_altmode_put_partner to put plugs
+    - usb: mon: Fix atomicity violation in mon_bin_vma_fault
+    - ALSA: oxygen: Fix right channel of capture volume mixer
+    - fbdev: flush deferred work in fb_deferred_io_fsync()
+    - rootfs: Fix support for rootfstype= when root= is given
+    - wifi: rtlwifi: Remove bogus and dangerous ASPM disable/enable code
+    - wifi: rtlwifi: Convert LNKCTL change to PCIe cap RMW accessors
+    - wifi: mwifiex: configure BSSID consistently when starting AP
+    - x86/kvm: Do not try to disable kvmclock if it was not enabled
+    - HID: wacom: Correct behavior when processing some confidence == false
+      touches
+    - mips: Fix incorrect max_low_pfn adjustment
+    - MIPS: Alchemy: Fix an out-of-bound access in db1200_dev_setup()
+    - MIPS: Alchemy: Fix an out-of-bound access in db1550_dev_setup()
+    - serial: 8250: omap: Don't skip resource freeing if
+      pm_runtime_resume_and_get() failed
+    - acpi: property: Let args be NULL in __acpi_node_get_property_reference
+    - software node: Let args be NULL in software_node_get_reference_args
+    - perf genelf: Set ELF program header addresses properly
+    - nvmet-tcp: Fix a kernel panic when host sends an invalid H2C PDU length
+    - nvmet-tcp: fix a crash in nvmet_req_complete()
+    - perf env: Add perf_env__numa_node()
+    - perf record: Move sb_evlist to 'struct record'
+    - perf top: Move sb_evlist to 'struct perf_top'
+    - perf bpf: Decouple creating the evlist from adding the SB event
+    - perf env: Avoid recursively taking env->bpf_progs.lock
+    - apparmor: avoid crash when parsed profile name is empty
+    - serial: imx: Correct clock error message in function probe()
+    - nvmet-tcp: Fix the H2C expected PDU len calculation
+    - PCI: keystone: Fix race condition when initializing PHYs
+    - s390/pci: fix max size calculation in zpci_memcpy_toio()
+    - net: qualcomm: rmnet: fix global oob in rmnet_policy
+    - net: phy: micrel: populate .soft_reset for KSZ9131
+    - net: ravb: Fix dma_addr_t truncation in error case
+    - net: dsa: vsc73xx: Add null pointer check to vsc73xx_gpio_probe
+    - netfilter: nf_tables: skip dead set elements in netlink dump
+    - ipvs: avoid stat macros calls from preemptible context
+    - kdb: Censor attempts to set PROMPT without ENABLE_MEM_READ
+    - kdb: Fix a potential buffer overflow in kdb_local()
+    - mlxsw: spectrum_acl_erp: Fix error flow of pool allocation failure
+    - i2c: s3c24xx: fix read transfers in polling mode
+    - i2c: s3c24xx: fix transferring more than one message in polling mode
+    - perf top: Skip side-band event setup if HAVE_LIBBPF_SUPPORT is not set
+    - arm64: dts: armada-3720-turris-mox: set irq type for RTC
+    - Linux 5.4.268
+  * CVE-2024-24855
+    - scsi: lpfc: Fix a possible data race in lpfc_unregister_fcf_rescan()
+  * Focal update: v5.4.267 upstream stable release (LP: #2054406)
+    - nfc: llcp_core: Hold a ref to llcp_local->dev when holding a ref to
+      llcp_local
+    - i40e: Fix filter input checks to prevent config with invalid values
+    - net: sched: em_text: fix possible memory leak in em_text_destroy()
+    - can: raw: add support for SO_TXTIME/SCM_TXTIME
+    - can: raw: add support for SO_MARK
+    - net-timestamp: extend SOF_TIMESTAMPING_OPT_ID to HW timestamps
+    - ARM: sun9i: smp: Fix array-index-out-of-bounds read in sunxi_mc_smp_init
+    - net: bcmgenet: Fix FCS generation for fragmented skbuffs
+    - net: Save and restore msg_namelen in sock_sendmsg
+    - i40e: fix use-after-free in i40e_aqc_add_filters()
+    - ASoC: meson: g12a: extract codec-to-codec utils
+    - [Config] Update annotations for CONFIG_SND_MESON_CODEC_GLUE
+    - ASoC: meson: g12a-tohdmitx: Validate written enum values
+    - ASoC: meson: g12a-tohdmitx: Fix event generation for S/PDIF mux
+    - i40e: Restore VF MSI-X state during PCI reset
+    - net/qla3xxx: switch from 'pci_' to 'dma_' API
+    - net/qla3xxx: fix potential memleak in ql_alloc_buffer_queues
+    - asix: Add check for usbnet_get_endpoints
+    - bnxt_en: Remove mis-applied code from bnxt_cfg_ntp_filters()
+    - net: Implement missing SO_TIMESTAMPING_NEW cmsg support
+    - mm/memory-failure: check the mapcount of the precise page
+    - firewire: ohci: suppress unexpected system reboot in AMD Ryzen machines and
+      ASM108x/VT630x PCIe cards
+    - i2c: core: Fix atomic xfer check for non-preempt config
+    - mm: fix unmap_mapping_range high bits shift bug
+    - mmc: rpmb: fixes pause retune on all RPMB partitions.
+    - mmc: core: Cancel delayed work before releasing host
+    - mmc: sdhci-sprd: Fix eMMC init failure after hw reset
+    - ath10k: Wait until copy complete is actually done before completing
+    - ath10k: Add interrupt summary based CE processing
+    - ath10k: Keep track of which interrupts fired, don't poll them
+    - ath10k: Get rid of "per_ce_irq" hw param
+    - PCI: Extract ATS disabling to a helper function
+    - PCI: Disable ATS for specific Intel IPU E2000 devices
+    - net/dst: use a smaller percpu_counter batch for dst entries accounting
+    - ipv6: make ip6_rt_gc_expire an atomic_t
+    - ipv6: remove max_size check inline with ipv4
+    - ASoC: meson: codec-glue: fix pcm format cast warning
+    - Linux 5.4.267
+  * CVE-2023-23000
+    - phy: tegra: xusb: Fix return value of tegra_xusb_find_port_node function
+  * CVE-2023-23004
+    - malidp: Fix NULL vs IS_ERR() checking
+  * CVE-2023-46838
+    - xen-netback: don't produce zero-size SKB frags
+  * CVE-2024-1086
+    - netfilter: nf_tables: reject QUEUE/DROP verdict parameters
+  * Focal update: v5.4.266 upstream stable release (LP: #2051655)
+    - ALSA: hda/realtek: Enable headset on Lenovo M90 Gen5
+    - ksmbd: fix wrong name of SMB2_CREATE_ALLOCATION_SIZE
+    - ARM: OMAP2+: Fix null pointer dereference and memory leak in
+      omap_soc_device_init
+    - reset: Fix crash when freeing non-existent optional resets
+    - s390/vx: fix save/restore of fpu kernel context
+    - wifi: mac80211: mesh_plink: fix matches_local logic
+    - net/mlx5: improve some comments
+    - net/mlx5: Fix fw tracer first block check
+    - net/mlx5e: Correct snprintf truncation handling for fw_version buffer used
+      by representors
+    - net: sched: ife: fix potential use-after-free
+    - ethernet: atheros: fix a memleak in atl1e_setup_ring_resources
+    - net/rose: fix races in rose_kill_by_device()
+    - net: check vlan filter feature in vlan_vids_add_by_dev() and
+      vlan_vids_del_by_dev()
+    - afs: Fix the dynamic root's d_delete to always delete unused dentries
+    - afs: Fix dynamic root lookup DNS check
+    - net: warn if gso_type isn't set for a GSO SKB
+    - net: check dev->gso_max_size in gso_features_check()
+    - afs: Fix overwriting of result of DNS query
+    - i2c: aspeed: Handle the coalesced stop conditions with the start conditions.
+    - pinctrl: at91-pio4: use dedicated lock class for IRQ
+    - ALSA: hda/hdmi: Add quirk to force pin connectivity on NUC10
+    - ALSA: hda/hdmi: add force-connect quirk for NUC5CPYB
+    - smb: client: fix NULL deref in asn1_ber_decoder()
+    - btrfs: do not allow non subvolume root targets for snapshot
+    - interconnect: Treat xlate() returning NULL node as an error
+    - iio: imu: inv_mpu6050: fix an error code problem in inv_mpu6050_read_raw
+    - Input: ipaq-micro-keys - add error handling for devm_kmemdup
+    - scsi: bnx2fc: Fix skb double free in bnx2fc_rcv()
+    - iio: common: ms_sensors: ms_sensors_i2c: fix humidity conversion time table
+    - iio: adc: ti_am335x_adc: Fix return value check of tiadc_request_dma()
+    - wifi: cfg80211: Add my certificate
+    - wifi: cfg80211: fix certs build to not depend on file order
+    - USB: serial: ftdi_sio: update Actisense PIDs constant names
+    - USB: serial: option: add Quectel EG912Y module support
+    - USB: serial: option: add Foxconn T99W265 with new baseline
+    - USB: serial: option: add Quectel RM500Q R13 firmware support
+    - Bluetooth: hci_event: Fix not checking if HCI_OP_INQUIRY has been sent
+    - net: 9p: avoid freeing uninit memory in p9pdu_vreadf
+    - net: rfkill: gpio: set GPIO direction
+    - x86/alternatives: Sync core before enabling interrupts
+    - usb: fotg210-hcd: delete an incorrect bounds test
+    - ring-buffer: Fix wake ups when buffer_percent is set to 100
+    - block: Don't invalidate pagecache for invalid falloc modes
+    - Linux 5.4.266
+  * CVE-2024-0607
+    - netfilter: nf_tables: fix pointer math issue in nft_byteorder_eval()
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Fri, 22 Mar 2024 08:57:27 +1000
+
+linux-xilinx-zynqmp (5.4.0-1040.44) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1040.44 -proposed tracker (LP: #2055976)
+
+  [ Ubuntu: 5.4.0-174.193 ]
+
+  * focal/linux: 5.4.0-174.193 -proposed tracker (LP: #2055978)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update annotations scripts
+    - debian/dkms-versions -- update from kernel-versions (main/s2024.02.05)
+  * CVE-2024-24855
+    - scsi: lpfc: Fix a possible data race in lpfc_unregister_fcf_rescan()
+  * CVE-2024-1086
+    - netfilter: nf_tables: reject QUEUE/DROP verdict parameters
+  * CVE-2023-23004
+    - malidp: Fix NULL vs IS_ERR() checking
+  * CVE-2023-23000
+    - phy: tegra: xusb: Fix return value of tegra_xusb_find_port_node function
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Tue, 12 Mar 2024 14:20:43 +1000
+
+linux-xilinx-zynqmp (5.4.0-1039.43) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1039.43 -proposed tracker (LP: #2052133)
+
+  * Focal update: v5.4.261 upstream stable release (LP: #2049049)
+    - [Config] xilinx-zynqmp: remove CONFIG_QCOM_SDM845_LLCC
+
+  * Focal update: v5.4.260 upstream stable release (LP: #2049024)
+    - [Config] xilinx-zynqmp: remove CONFIG_BLK_DEV_SX8
+
+  [ Ubuntu: 5.4.0-173.191 ]
+
+  * focal/linux: 5.4.0-173.191 -proposed tracker (LP: #2052135)
+  * Packaging resync (LP: #1786013)
+    - debian/dkms-versions -- update from kernel-versions (main/2024.02.05)
+  * CVE-2023-0340
+    - vhost: use kzalloc() instead of kmalloc() followed by memset()
+  * CVE-2023-6915
+    - ida: Fix crash in ida_free when the bitmap is empty
+  * Focal update: v5.4.265 upstream stable release (LP: #2051644)
+    - afs: Fix refcount underflow from error handling race
+    - net: ipv6: support reporting otherwise unknown prefix flags in RTM_NEWPREFIX
+    - qca_debug: Prevent crash on TX ring changes
+    - qca_debug: Fix ethtool -G iface tx behavior
+    - qca_spi: Fix reset behavior
+    - atm: solos-pci: Fix potential deadlock on &cli_queue_lock
+    - atm: solos-pci: Fix potential deadlock on &tx_queue_lock
+    - atm: Fix Use-After-Free in do_vcc_ioctl
+    - qed: Fix a potential use-after-free in qed_cxt_tables_alloc
+    - net: Remove acked SYN flag from packet in the transmit queue correctly
+    - sign-file: Fix incorrect return values check
+    - vsock/virtio: Fix unsigned integer wrap around in
+      virtio_transport_has_space()
+    - net: stmmac: use dev_err_probe() for reporting mdio bus registration failure
+    - net: stmmac: Handle disabled MDIO busses from devicetree
+    - cred: switch to using atomic_long_t
+    - ALSA: hda/hdmi: add force-connect quirks for ASUSTeK Z170 variants
+    - usb: aqc111: check packet for fixup for true limit
+    - blk-throttle: fix lockdep warning of "cgroup_mutex or RCU read lock
+      required!"
+    - bcache: avoid oversize memory allocation by small stripe_size
+    - bcache: add code comments for bch_btree_node_get() and
+      __bch_btree_node_alloc()
+    - bcache: avoid NULL checking to c->root in run_cache_set()
+    - platform/x86: intel_telemetry: Fix kernel doc descriptions
+    - HID: add ALWAYS_POLL quirk for Apple kb
+    - HID: hid-asus: reset the backlight brightness level on resume
+    - HID: multitouch: Add quirk for HONOR GLO-GXXX touchpad
+    - asm-generic: qspinlock: fix queued_spin_value_unlocked() implementation
+    - net: usb: qmi_wwan: claim interface 4 for ZTE MF290
+    - HID: hid-asus: add const to read-only outgoing usb buffer
+    - soundwire: stream: fix NULL pointer dereference for multi_link
+    - ext4: prevent the normalized size from exceeding EXT_MAX_BLOCKS
+    - arm64: mm: Always make sw-dirty PTEs hw-dirty in pte_modify
+    - team: Fix use-after-free when an option instance allocation fails
+    - ring-buffer: Fix memory leak of free page
+    - mmc: block: Be sure to wait while busy in CQE error recovery
+    - powerpc/ftrace: Create a dummy stackframe to fix stack unwind
+    - powerpc/ftrace: Fix stack teardown in ftrace_no_trace
+    - Linux 5.4.265
+  * Focal update: v5.4.264 upstream stable release (LP: #2049935)
+    - hrtimers: Push pending hrtimers away from outgoing CPU earlier
+    - netfilter: ipset: fix race condition between swap/destroy and kernel side
+      add/del/test
+    - tg3: Move the [rt]x_dropped counters to tg3_napi
+    - tg3: Increment tx_dropped in tg3_tso_bug()
+    - kconfig: fix memory leak from range properties
+    - drm/amdgpu: correct chunk_ptr to a pointer to chunk.
+    - of: base: Add of_get_cpu_state_node() to get idle states for a CPU node
+    - ACPI/IORT: Make iort_get_device_domain IRQ domain agnostic
+    - ACPI/IORT: Make iort_msi_map_rid() PCI agnostic
+    - of/iommu: Make of_map_rid() PCI agnostic
+    - of/irq: make of_msi_map_get_device_domain() bus agnostic
+    - of/irq: Make of_msi_map_rid() PCI bus agnostic
+    - of: base: Fix some formatting issues and provide missing descriptions
+    - of: Fix kerneldoc output formatting
+    - of: Add missing 'Return' section in kerneldoc comments
+    - of: dynamic: Fix of_reconfig_get_state_change() return value documentation
+    - ipv6: fix potential NULL deref in fib6_add()
+    - hv_netvsc: rndis_filter needs to select NLS
+    - net: arcnet: Fix RESET flag handling
+    - net: arcnet: com20020 fix error handling
+    - arcnet: restoring support for multiple Sohard Arcnet cards
+    - ipv4: ip_gre: Avoid skb_pull() failure in ipgre_xmit()
+    - net: hns: fix fake link up on xge port
+    - netfilter: xt_owner: Fix for unsafe access of sk->sk_socket
+    - tcp: do not accept ACK of bytes we never sent
+    - bpf: sockmap, updating the sg structure should also update curr
+    - RDMA/bnxt_re: Correct module description string
+    - hwmon: (acpi_power_meter) Fix 4.29 MW bug
+    - ASoC: wm_adsp: fix memleak in wm_adsp_buffer_populate
+    - tracing: Fix a warning when allocating buffered events fails
+    - scsi: be2iscsi: Fix a memleak in beiscsi_init_wrb_handle()
+    - ARM: imx: Check return value of devm_kasprintf in imx_mmdc_perf_init
+    - ARM: dts: imx: make gpt node name generic
+    - ARM: dts: imx7: Declare timers compatible with fsl,imx6dl-gpt
+    - ALSA: pcm: fix out-of-bounds in snd_pcm_state_names
+    - nilfs2: prevent WARNING in nilfs_sufile_set_segment_usage()
+    - tracing: Always update snapshot buffer size
+    - tracing: Fix incomplete locking when disabling buffered events
+    - tracing: Fix a possible race when disabling buffered events
+    - packet: Move reference count in packet_sock to atomic_long_t
+    - arm64: dts: mediatek: mt7622: fix memory node warning check
+    - arm64: dts: mediatek: mt8173-evb: Fix regulator-fixed node names
+    - gpiolib: sysfs: Fix error handling on failed export
+    - mmc: core: add helpers mmc_regulator_enable/disable_vqmmc
+    - mmc: sdhci-sprd: Fix vqmmc not shutting down after the card was pulled
+    - usb: gadget: f_hid: fix report descriptor allocation
+    - parport: Add support for Brainboxes IX/UC/PX parallel cards
+    - usb: typec: class: fix typec_altmode_put_partner to put plugs
+    - ARM: PL011: Fix DMA support
+    - serial: sc16is7xx: address RX timeout interrupt errata
+    - serial: 8250_omap: Add earlycon support for the AM654 UART controller
+    - x86/CPU/AMD: Check vendor in the AMD microcode callback
+    - KVM: s390/mm: Properly reset no-dat
+    - nilfs2: fix missing error check for sb_set_blocksize call
+    - io_uring/af_unix: disable sending io_uring over sockets
+    - netlink: don't call ->netlink_bind with table lock held
+    - genetlink: add CAP_NET_ADMIN test for multicast bind
+    - psample: Require 'CAP_NET_ADMIN' when joining "packets" group
+    - drop_monitor: Require 'CAP_SYS_ADMIN' when joining "events" group
+    - tools headers UAPI: Sync linux/perf_event.h with the kernel sources
+    - cifs: Fix non-availability of dedup breaking generic/304
+    - smb: client: fix potential NULL deref in parse_dfs_referrals()
+    - devcoredump : Serialize devcd_del work
+    - devcoredump: Send uevent once devcd is ready
+    - Linux 5.4.264
+  * CVE-2024-0646
+    - net: tls, update curr on splice as well
+  * CVE-2024-0565
+    - smb: client: fix OOB in receive_encrypted_standard()
+  * CVE-2023-51781
+    - appletalk: Fix Use-After-Free in atalk_ioctl
+  * CVE-2023-51782
+    - net/rose: Fix Use-After-Free in rose_ioctl
+  * Focal update: v5.4.263 upstream stable release (LP: #2049084)
+    - driver core: Release all resources during unbind before updating device
+      links
+    - RDMA/irdma: Prevent zero-length STAG registration
+    - PCI: keystone: Drop __init from ks_pcie_add_pcie_{ep,port}()
+    - afs: Make error on cell lookup failure consistent with OpenAFS
+    - drm/panel: simple: Fix Innolux G101ICE-L01 bus flags
+    - drm/panel: simple: Fix Innolux G101ICE-L01 timings
+    - ata: pata_isapnp: Add missing error check for devm_ioport_map()
+    - drm/rockchip: vop: Fix color for RGB888/BGR888 format on VOP full
+    - HID: core: store the unique system identifier in hid_device
+    - HID: fix HID device resource race between HID core and debugging support
+    - ipv4: Correct/silence an endian warning in __ip_do_redirect
+    - net: usb: ax88179_178a: fix failed operations during ax88179_reset
+    - arm/xen: fix xen_vcpu_info allocation alignment
+    - amd-xgbe: handle corner-case during sfp hotplug
+    - amd-xgbe: handle the corner-case during tx completion
+    - amd-xgbe: propagate the correct speed and duplex status
+    - net: axienet: Fix check for partial TX checksum
+    - afs: Return ENOENT if no cell DNS record can be found
+    - afs: Fix file locking on R/O volumes to operate in local mode
+    - nvmet: remove unnecessary ctrl parameter
+    - nvmet: nul-terminate the NQNs passed in the connect command
+    - MIPS: KVM: Fix a build warning about variable set but not used
+    - ext4: add a new helper to check if es must be kept
+    - ext4: factor out __es_alloc_extent() and __es_free_extent()
+    - ext4: use pre-allocated es in __es_insert_extent()
+    - ext4: use pre-allocated es in __es_remove_extent()
+    - ext4: using nofail preallocation in ext4_es_remove_extent()
+    - ext4: using nofail preallocation in ext4_es_insert_delayed_block()
+    - ext4: using nofail preallocation in ext4_es_insert_extent()
+    - ext4: fix slab-use-after-free in ext4_es_insert_extent()
+    - ext4: make sure allocate pending entry not fail
+    - arm64: cpufeature: Extract capped perfmon fields
+    - KVM: arm64: limit PMU version to PMUv3 for ARMv8.1
+    - ACPI: resource: Skip IRQ override on ASUS ExpertBook B1402CVA
+    - bcache: replace a mistaken IS_ERR() by IS_ERR_OR_NULL() in
+      btree_gc_coalesce()
+    - s390/dasd: protect device queue against concurrent access
+    - USB: serial: option: add Luat Air72*U series products
+    - hv_netvsc: Fix race of register_netdevice_notifier and VF register
+    - hv_netvsc: Mark VF as slave before exposing it to user-mode
+    - dm-delay: fix a race between delay_presuspend and delay_bio
+    - bcache: check return value from btree_node_alloc_replacement()
+    - bcache: prevent potential division by zero error
+    - USB: serial: option: add Fibocom L7xx modules
+    - USB: serial: option: fix FM101R-GL defines
+    - USB: serial: option: don't claim interface 4 for ZTE MF290
+    - USB: dwc2: write HCINT with INTMASK applied
+    - usb: dwc3: set the dma max_seg_size
+    - USB: dwc3: qcom: fix resource leaks on probe deferral
+    - USB: dwc3: qcom: fix wakeup after probe deferral
+    - io_uring: fix off-by one bvec index
+    - pinctrl: avoid reload of p state in list iteration
+    - firewire: core: fix possible memory leak in create_units()
+    - mmc: block: Do not lose cache flush during CQE error recovery
+    - ALSA: hda: Disable power-save on KONTRON SinglePC
+    - ALSA: hda/realtek: Headset Mic VREF to 100%
+    - ALSA: hda/realtek: Add supported ALC257 for ChromeOS
+    - dm-verity: align struct dm_verity_fec_io properly
+    - dm verity: don't perform FEC for failed readahead IO
+    - bcache: revert replacing IS_ERR_OR_NULL with IS_ERR
+    - powerpc: Don't clobber f0/vs0 during fp|altivec register save
+    - btrfs: fix off-by-one when checking chunk map includes logical address
+    - btrfs: send: ensure send_fd is writable
+    - btrfs: make error messages more clear when getting a chunk map
+    - Input: xpad - add HyperX Clutch Gladiate Support
+    - net: stmmac: xgmac: Disable FPE MMC interrupts
+    - ravb: Fix races between ravb_tx_timeout_work() and net related ops
+    - net: ravb: Use pm_runtime_resume_and_get()
+    - net: ravb: Start TX queues after HW initialization succeeded
+    - smb3: fix touch -h of symlink
+    - s390/mm: fix phys vs virt confusion in mark_kernel_pXd() functions family
+    - s390/cmma: fix detection of DAT pages
+    - mtd: cfi_cmdset_0001: Support the absence of protection registers
+    - mtd: cfi_cmdset_0001: Byte swap OTP info
+    - fbdev: stifb: Make the STI next font pointer a 32-bit signed offset
+    - ima: annotate iint mutex to avoid lockdep false positive warnings
+    - ovl: skip overlayfs superblocks at global sync
+    - ima: detect changes to the backing overlay file
+    - scsi: qla2xxx: Simplify the code for aborting SCSI commands
+    - scsi: core: Introduce the scsi_cmd_to_rq() function
+    - scsi: qla2xxx: Use scsi_cmd_to_rq() instead of scsi_cmnd.request
+    - scsi: qla2xxx: Fix system crash due to bad pointer access
+    - cpufreq: imx6q: don't warn for disabling a non-existing frequency
+    - cpufreq: imx6q: Don't disable 792 Mhz OPP unnecessarily
+    - mmc: cqhci: Increase recovery halt timeout
+    - mmc: cqhci: Warn of halt or task clear failure
+    - mmc: cqhci: Fix task clearing in CQE error recovery
+    - mmc: core: convert comma to semicolon
+    - mmc: block: Retry commands in CQE error recovery
+    - Linux 5.4.263
+  * Focal update: v5.4.262 upstream stable release (LP: #2049069)
+    - locking/ww_mutex/test: Fix potential workqueue corruption
+    - perf/core: Bail out early if the request AUX area is out of bound
+    - clocksource/drivers/timer-imx-gpt: Fix potential memory leak
+    - clocksource/drivers/timer-atmel-tcb: Fix initialization on SAM9 hardware
+    - x86/mm: Drop the 4 MB restriction on minimal NUMA node memory size
+    - wifi: mac80211_hwsim: fix clang-specific fortify warning
+    - wifi: mac80211: don't return unset power in ieee80211_get_tx_power()
+    - wifi: ath9k: fix clang-specific fortify warnings
+    - wifi: ath10k: fix clang-specific fortify warning
+    - net: annotate data-races around sk->sk_tx_queue_mapping
+    - net: annotate data-races around sk->sk_dst_pending_confirm
+    - wifi: ath10k: Don't touch the CE interrupt registers after power up
+    - Bluetooth: Fix double free in hci_conn_cleanup
+    - platform/x86: thinkpad_acpi: Add battery quirk for Thinkpad X120e
+    - drm/komeda: drop all currently held locks if deadlock happens
+    - drm/amd: Fix UBSAN array-index-out-of-bounds for SMU7
+    - drm/amd: Fix UBSAN array-index-out-of-bounds for Polaris and Tonga
+    - drm/amdgpu: Fix a null pointer access when the smc_rreg pointer is NULL
+    - selftests/efivarfs: create-read: fix a resource leak
+    - crypto: pcrypt - Fix hungtask for PADATA_RESET
+    - RDMA/hfi1: Use FIELD_GET() to extract Link Width
+    - fs/jfs: Add check for negative db_l2nbperpage
+    - fs/jfs: Add validity check for db_maxag and db_agpref
+    - jfs: fix array-index-out-of-bounds in dbFindLeaf
+    - jfs: fix array-index-out-of-bounds in diAlloc
+    - ARM: 9320/1: fix stack depot IRQ stack filter
+    - ALSA: hda: Fix possible null-ptr-deref when assigning a stream
+    - PCI: tegra194: Use FIELD_GET()/FIELD_PREP() with Link Width fields
+    - atm: iphase: Do PCI error checks on own line
+    - scsi: libfc: Fix potential NULL pointer dereference in fc_lport_ptp_setup()
+    - HID: Add quirk for Dell Pro Wireless Keyboard and Mouse KM5221W
+    - tty: vcc: Add check for kstrdup() in vcc_probe()
+    - usb: gadget: f_ncm: Always set current gadget in ncm_bind()
+    - i2c: sun6i-p2wi: Prevent potential division by zero
+    - media: gspca: cpia1: shift-out-of-bounds in set_flicker
+    - media: vivid: avoid integer overflow
+    - gfs2: ignore negated quota changes
+    - media: cobalt: Use FIELD_GET() to extract Link Width
+    - drm/amd/display: Avoid NULL dereference of timing generator
+    - kgdb: Flush console before entering kgdb on panic
+    - ASoC: ti: omap-mcbsp: Fix runtime PM underflow warnings
+    - pwm: Fix double shift bug
+    - wifi: iwlwifi: Use FW rate for non-data frames
+    - NFSv4.1: fix SP4_MACH_CRED protection for pnfs IO
+    - ipvlan: add ipvlan_route_v6_outbound() helper
+    - tty: Fix uninit-value access in ppp_sync_receive()
+    - net: hns3: fix variable may not initialized problem in hns3_init_mac_addr()
+    - tipc: Fix kernel-infoleak due to uninitialized TLV value
+    - ppp: limit MRU to 64K
+    - xen/events: fix delayed eoi list handling
+    - ptp: annotate data-race around q->head and q->tail
+    - bonding: stop the device in bond_setup_by_slave()
+    - net: ethernet: cortina: Fix max RX frame define
+    - net: ethernet: cortina: Handle large frames
+    - net: ethernet: cortina: Fix MTU max setting
+    - netfilter: nf_conntrack_bridge: initialize err to 0
+    - net: stmmac: Rework stmmac_rx()
+    - net: stmmac: fix rx budget limit check
+    - net/mlx5_core: Clean driver version and name
+    - net/mlx5e: Check return value of snprintf writing to fw_version buffer for
+      representors
+    - macvlan: Don't propagate promisc change to lower dev in passthru
+    - tools/power/turbostat: Fix a knl bug
+    - cifs: spnego: add ';' in HOST_KEY_LEN
+    - media: venus: hfi: add checks to perform sanity on queue pointers
+    - randstruct: Fix gcc-plugin performance mode to stay in group
+    - bpf: Fix precision tracking for BPF_ALU | BPF_TO_BE | BPF_END
+    - scsi: megaraid_sas: Increase register read retry rount from 3 to 30 for
+      selected registers
+    - x86/cpu/hygon: Fix the CPU topology evaluation for real
+    - KVM: x86: hyper-v: Don't auto-enable stimer on write from user-space
+    - KVM: x86: Ignore MSR_AMD64_TW_CFG access
+    - audit: don't take task_lock() in audit_exe_compare() code path
+    - audit: don't WARN_ON_ONCE(!current->mm) in audit_exe_compare()
+    - hvc/xen: fix error path in xen_hvc_init() to always register frontend driver
+    - PCI/sysfs: Protect driver's D3cold preference from user space
+    - ACPI: resource: Do IRQ override on TongFang GMxXGxx
+    - mmc: meson-gx: Remove setting of CMD_CFG_ERROR
+    - genirq/generic_chip: Make irq_remove_generic_chip() irqdomain aware
+    - PCI: keystone: Don't discard .remove() callback
+    - PCI: keystone: Don't discard .probe() callback
+    - parisc/pdc: Add width field to struct pdc_model
+    - clk: qcom: ipq8074: drop the CLK_SET_RATE_PARENT flag from PLL clocks
+    - mmc: vub300: fix an error code
+    - PM: hibernate: Use __get_safe_page() rather than touching the list
+    - PM: hibernate: Clean up sync_read handling in snapshot_write_next()
+    - btrfs: don't arbitrarily slow down delalloc if we're committing
+    - jbd2: fix potential data lost in recovering journal raced with synchronizing
+      fs bdev
+    - quota: explicitly forbid quota files from being encrypted
+    - kernel/reboot: emergency_restart: Set correct system_state
+    - i2c: core: Run atomic i2c xfer when !preemptible
+    - mcb: fix error handling for different scenarios when parsing
+    - dmaengine: stm32-mdma: correct desc prep when channel running
+    - mm/cma: use nth_page() in place of direct struct page manipulation
+    - i3c: master: cdns: Fix reading status register
+    - parisc: Prevent booting 64-bit kernels on PA1.x machines
+    - parisc/pgtable: Do not drop upper 5 address bits of physical address
+    - ALSA: info: Fix potential deadlock at disconnection
+    - ALSA: hda/realtek - Enable internal speaker of ASUS K6500ZC
+    - serial: meson: remove redundant initialization of variable id
+    - tty: serial: meson: retrieve port FIFO size from DT
+    - serial: meson: Use platform_get_irq() to get the interrupt
+    - tty: serial: meson: fix hard LOCKUP on crtscts mode
+    - Bluetooth: btusb: add Realtek 8822CE to usb_device_id table
+    - Bluetooth: btusb: Add Realtek RTL8852BE support ID 0x0cb8:0xc559
+    - bluetooth: Add device 0bda:887b to device tables
+    - bluetooth: Add device 13d3:3571 to device tables
+    - Bluetooth: btusb: Add RTW8852BE device 13d3:3570 to device tables
+    - Bluetooth: btusb: Add 0bda:b85b for Fn-Link RTL8852BE
+    - Revert ncsi: Propagate carrier gain/loss events to the NCSI controller
+    - net: dsa: lan9303: consequently nested-lock physical MDIO
+    - i2c: i801: fix potential race in i801_block_transaction_byte_by_byte
+    - media: lirc: drop trailing space from scancode transmit
+    - media: sharp: fix sharp encoding
+    - media: venus: hfi_parser: Add check to keep the number of codecs within
+      range
+    - media: venus: hfi: fix the check to handle session buffer requirement
+    - media: venus: hfi: add checks to handle capabilities from firmware
+    - nfsd: fix file memleak on client_opens_release
+    - ext4: apply umask if ACL support is disabled
+    - ext4: correct offset of gdb backup in non meta_bg group to update_backups
+    - ext4: correct return value of ext4_convert_meta_bg
+    - ext4: correct the start block of counting reserved clusters
+    - ext4: remove gdb backup copy for meta bg in setup_new_flex_group_blocks
+    - drm/amdgpu: fix error handling in amdgpu_bo_list_get()
+    - tracing: Have trace_event_file have ref counters
+    - netfilter: nf_tables: pass context to nft_set_destroy()
+    - netfilter: nftables: rename set element data activation/deactivation
+      functions
+    - netfilter: nf_tables: drop map element references from preparation phase
+    - netfilter: nft_set_rbtree: Switch to node list walk for overlap detection
+    - netfilter: nft_set_rbtree: fix null deref on element insertion
+    - netfilter: nft_set_rbtree: fix overlap expiration walk
+    - netfilter: nf_tables: don't skip expired elements during walk
+    - netfilter: nf_tables: GC transaction API to avoid race with control plane
+    - netfilter: nf_tables: adapt set backend to use GC transaction API
+    - netfilter: nft_set_hash: mark set element as dead when deleting from packet
+      path
+    - netfilter: nf_tables: remove busy mark and gc batch API
+    - netfilter: nf_tables: fix GC transaction races with netns and netlink event
+      exit path
+    - netfilter: nf_tables: GC transaction race with netns dismantle
+    - netfilter: nf_tables: GC transaction race with abort path
+    - netfilter: nf_tables: use correct lock to protect gc_list
+    - netfilter: nf_tables: defer gc run if previous batch is still pending
+    - netfilter: nft_set_rbtree: skip sync GC for new elements in this transaction
+    - netfilter: nft_set_rbtree: use read spinlock to avoid datapath contention
+    - netfilter: nft_set_hash: try later when GC hits EAGAIN on iteration
+    - netfilter: nf_tables: fix memleak when more than 255 elements expired
+    - netfilter: nf_tables: unregister flowtable hooks on netns exit
+    - netfilter: nf_tables: double hook unregistration in netns path
+    - netfilter: nftables: update table flags from the commit phase
+    - netfilter: nf_tables: fix table flag updates
+    - netfilter: nf_tables: disable toggling dormant table state more than once
+    - netfilter: nf_tables: bogus EBUSY when deleting flowtable after flush (for
+      5.4)
+    - Linux 5.4.262
+  * Focal update: v5.4.261 upstream stable release (LP: #2049049)
+    - vfs: fix readahead(2) on block devices
+    - genirq/matrix: Exclude managed interrupts in irq_matrix_allocated()
+    - i40e: fix potential memory leaks in i40e_remove()
+    - tcp: call tcp_try_undo_recovery when an RTOd TFO SYNACK is ACKed
+    - wifi: rtw88: debug: Fix the NULL vs IS_ERR() bug for debugfs_create_file()
+    - wifi: mt76: mt7603: rework/fix rx pse hang check
+    - tcp_metrics: add missing barriers on delete
+    - tcp_metrics: properly set tp->snd_ssthresh in tcp_init_metrics()
+    - tcp_metrics: do not create an entry from tcp_init_metrics()
+    - wifi: rtlwifi: fix EDCA limit set by BT coexistence
+    - can: dev: can_restart(): don't crash kernel if carrier is OK
+    - can: dev: can_restart(): fix race condition between controller restart and
+      netif_carrier_on()
+    - thermal: core: prevent potential string overflow
+    - r8169: use tp_to_dev instead of open code
+    - r8169: fix rare issue with broken rx after link-down on RTL8125
+    - chtls: fix tp->rcv_tstamp initialization
+    - tcp: Remove one extra ktime_get_ns() from cookie_init_timestamp
+    - tcp: fix cookie_init_timestamp() overflows
+    - ACPI: sysfs: Fix create_pnp_modalias() and create_of_modalias()
+    - ipv6: avoid atomic fragment on GSO packets
+    - net: add DEV_STATS_READ() helper
+    - ipvlan: properly track tx_errors
+    - regmap: debugfs: Fix a erroneous check after snprintf()
+    - clk: qcom: clk-rcg2: Fix clock rate overflow for high parent frequencies
+    - clk: qcom: gcc-sm8150: use ARRAY_SIZE instead of specifying num_parents
+    - clk: qcom: gcc-sm8150: Fix gcc_sdcc2_apps_clk_src
+    - clk: imx: Select MXC_CLK for CLK_IMX8QXP
+    - clk: keystone: pll: fix a couple NULL vs IS_ERR() checks
+    - clk: npcm7xx: Fix incorrect kfree
+    - clk: mediatek: clk-mt6779: Add check for mtk_alloc_clk_data
+    - clk: mediatek: clk-mt6797: Add check for mtk_alloc_clk_data
+    - clk: mediatek: clk-mt7629-eth: Add check for mtk_alloc_clk_data
+    - clk: mediatek: clk-mt7629: Add check for mtk_alloc_clk_data
+    - clk: mediatek: clk-mt2701: Add check for mtk_alloc_clk_data
+    - platform/x86: wmi: Fix probe failure when failing to register WMI devices
+    - platform/x86: wmi: remove unnecessary initializations
+    - platform/x86: wmi: Fix opening of char device
+    - hwmon: (coretemp) Fix potentially truncated sysfs attribute name
+    - drm/rockchip: vop: Fix reset of state in duplicate state crtc funcs
+    - drm/rockchip: vop: Fix call to crtc reset helper
+    - drm/radeon: possible buffer overflow
+    - drm/rockchip: cdn-dp: Fix some error handling paths in cdn_dp_probe()
+    - arm64: dts: qcom: sdm845-mtp: fix WiFi configuration
+    - ARM: dts: qcom: mdm9615: populate vsdcc fixed regulator
+    - soc: qcom: llcc cleanup to get rid of sdm845 specific driver file
+    - [Config] remove CONFIG_QCOM_SDM845_LLCC
+    - soc: qcom: Rename llcc-slice to llcc-qcom
+    - [Config] remove llcc-slice module
+    - soc: qcom: llcc: Handle a second device without data corruption
+    - firmware: ti_sci: Replace HTTP links with HTTPS ones
+    - firmware: ti_sci: Mark driver as non removable
+    - clk: scmi: Free scmi_clk allocated when the clocks with invalid info are
+      skipped
+    - hwrng: geode - fix accessing registers
+    - libnvdimm/of_pmem: Use devm_kstrdup instead of kstrdup and check its return
+      value
+    - sched/rt: Provide migrate_disable/enable() inlines
+    - nd_btt: Make BTT lanes preemptible
+    - crypto: caam/qi2 - fix Chacha20 + Poly1305 self test failure
+    - crypto: caam/jr - fix Chacha20 + Poly1305 self test failure
+    - HID: cp2112: Use irqchip template
+    - hid: cp2112: Fix duplicate workqueue initialization
+    - ARM: 9321/1: memset: cast the constant byte to unsigned char
+    - ext4: move 'ix' sanity check to corrent position
+    - scsi: ufs: core: Leave space for '\0' in utf8 desc string
+    - RDMA/hfi1: Workaround truncation compilation error
+    - sh: bios: Revive earlyprintk support
+    - ASoC: Intel: Skylake: Fix mem leak when parsing UUIDs fails
+    - ASoC: ams-delta.c: use component after check
+    - mfd: dln2: Fix double put in dln2_probe
+    - leds: pwm: simplify if condition
+    - leds: pwm: convert to atomic PWM API
+    - leds: pwm: Don't disable the PWM when the LED should be off
+    - ledtrig-cpu: Limit to 8 CPUs
+    - leds: trigger: ledtrig-cpu:: Fix 'output may be truncated' issue for 'cpu'
+    - tty: tty_jobctrl: fix pid memleak in disassociate_ctty()
+    - usb: dwc2: fix possible NULL pointer dereference caused by driver
+      concurrency
+    - dmaengine: ti: edma: handle irq_of_parse_and_map() errors
+    - misc: st_core: Do not call kfree_skb() under spin_lock_irqsave()
+    - tools: iio: privatize globals and functions in iio_generic_buffer.c file
+    - tools: iio: iio_generic_buffer: Fix some integer type and calculation
+    - tools: iio: iio_generic_buffer ensure alignment
+    - USB: usbip: fix stub_dev hub disconnect
+    - dmaengine: pxa_dma: Remove an erroneous BUG_ON() in pxad_free_desc()
+    - f2fs: fix to initialize map.m_pblk in f2fs_precache_extents()
+    - modpost: fix tee MODULE_DEVICE_TABLE built on big-endian host
+    - powerpc/xive: Fix endian conversion size
+    - powerpc/imc-pmu: Use the correct spinlock initializer.
+    - powerpc/pseries: fix potential memory leak in init_cpu_associativity()
+    - i3c: Fix potential refcount leak in i3c_master_register_new_i3c_devs
+    - rtc: pcf85363: fix wrong mask/val parameters in regmap_update_bits call
+    - pcmcia: cs: fix possible hung task and memory leak pccardd()
+    - pcmcia: ds: fix refcount leak in pcmcia_device_add()
+    - pcmcia: ds: fix possible name leak in error path in pcmcia_device_add()
+    - media: bttv: fix use after free error due to btv->timeout timer
+    - media: s3c-camif: Avoid inappropriate kfree()
+    - media: dvb-usb-v2: af9035: fix missing unlock
+    - regmap: prevent noinc writes from clobbering cache
+    - pwm: sti: Avoid conditional gotos
+    - pwm: sti: Reduce number of allocations and drop usage of chip_data
+    - pwm: brcmstb: Utilize appropriate clock APIs in suspend/resume
+    - Input: synaptics-rmi4 - fix use after free in rmi_unregister_function()
+    - llc: verify mac len before reading mac header
+    - tipc: Change nla_policy for bearer-related names to NLA_NUL_STRING
+    - inet: shrink struct flowi_common
+    - dccp: Call security_inet_conn_request() after setting IPv4 addresses.
+    - dccp/tcp: Call security_inet_conn_request() after setting IPv6 addresses.
+    - Fix termination state for idr_for_each_entry_ul()
+    - net: stmmac: xgmac: Enable support for multiple Flexible PPS outputs
+    - net/smc: fix dangling sock under state SMC_APPFINCLOSEWAIT
+    - tg3: power down device only on SYSTEM_POWER_OFF
+    - r8169: respect userspace disabling IFF_MULTICAST
+    - netfilter: xt_recent: fix (increase) ipv6 literal buffer length
+    - netfilter: nft_redir: use `struct nf_nat_range2` throughout and deduplicate
+      eval call-backs
+    - netfilter: nat: fix ipv6 nat redirect with mapped and scoped addresses
+    - drm/syncobj: fix DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE
+    - spi: spi-zynq-qspi: add spi-mem to driver kconfig dependencies
+    - fbdev: imsttfb: Fix error path of imsttfb_probe()
+    - fbdev: imsttfb: fix a resource leak in probe
+    - fbdev: fsl-diu-fb: mark wr_reg_wa() static
+    - Revert "mmc: core: Capture correct oemid-bits for eMMC cards"
+    - btrfs: use u64 for buffer sizes in the tree search ioctls
+    - Linux 5.4.261
+  * Focal update: v5.4.260 upstream stable release (LP: #2049024)
+    - mtd: rawnand: marvell: Ensure program page operations are successful
+    - selftests/ftrace: Add new test case which checks non unique symbol
+    - mcb: Return actual parsed size when reading chameleon table
+    - mcb-lpc: Reallocate memory region to avoid memory overlapping
+    - virtio_balloon: Fix endless deflation and inflation on arm64
+    - virtio-mmio: fix memory leak of vm_dev
+    - r8169: fix the KCSAN reported data-race in rtl_tx while reading
+      TxDescArray[entry].opts1
+    - r8169: fix the KCSAN reported data race in rtl_rx while reading desc->opts1
+    - treewide: Spelling fix in comment
+    - igb: Fix potential memory leak in igb_add_ethtool_nfc_entry
+    - neighbour: fix various data-races
+    - igc: Fix ambiguity in the ethtool advertising
+    - net: ieee802154: adf7242: Fix some potential buffer overflow in
+      adf7242_stats_show()
+    - r8152: Increase USB control msg timeout to 5000ms as per spec
+    - r8152: Run the unload routine if we have errors during probe
+    - r8152: Cancel hw_phy_work if we have an error in probe
+    - tcp: fix wrong RTO timeout when received SACK reneging
+    - gtp: uapi: fix GTPA_MAX
+    - gtp: fix fragmentation needed check with gso
+    - iio: exynos-adc: request second interupt only when touchscreen mode is used
+    - i2c: muxes: i2c-mux-pinctrl: Use of_get_i2c_adapter_by_node()
+    - i2c: muxes: i2c-mux-gpmux: Use of_get_i2c_adapter_by_node()
+    - i2c: muxes: i2c-demux-pinctrl: Use of_get_i2c_adapter_by_node()
+    - i2c: stm32f7: Fix PEC handling in case of SMBUS transfers
+    - i2c: aspeed: Fix i2c bus hang in slave read
+    - nvmem: imx: correct nregs for i.MX6ULL
+    - nvmem: imx: correct nregs for i.MX6SLL
+    - nvmem: imx: correct nregs for i.MX6UL
+    - perf/core: Fix potential NULL deref
+    - clk: Sanitize possible_parent_show to Handle Return Value of
+      of_clk_get_parent_name
+    - i40e: Fix wrong check for I40E_TXR_FLAGS_WB_ON_ITR
+    - x86/i8259: Skip probing when ACPI/MADT advertises PCAT compatibility
+    - drm/dp_mst: Fix NULL deref in get_mst_branch_device_by_guid_helper()
+    - arm64: fix a concurrency issue in emulation_proc_handler()
+    - smbdirect: missing rc checks while waiting for rdma events
+    - f2fs: fix to do sanity check on inode type during garbage collection
+    - nfsd: lock_rename() needs both directories to live on the same fs
+    - x86/mm: Simplify RESERVE_BRK()
+    - x86/mm: Fix RESERVE_BRK() for older binutils
+    - ext4: add two helper functions extent_logical_end() and pa_logical_end()
+    - ext4: avoid overlapping preallocations due to overflow
+    - ext4: fix BUG in ext4_mb_new_inode_pa() due to overflow
+    - driver: platform: Add helper for safer setting of driver_override
+    - rpmsg: Constify local variable in field store macro
+    - rpmsg: Fix kfree() of static memory on setting driver_override
+    - rpmsg: Fix calling device_lock() on non-initialized device
+    - rpmsg: glink: Release driver_override
+    - rpmsg: Fix possible refcount leak in rpmsg_register_device_override()
+    - x86: Fix .brk attribute in linker script
+    - Input: i8042 - add Fujitsu Lifebook E5411 to i8042 quirk table
+    - irqchip/stm32-exti: add missing DT IRQ flag translation
+    - dmaengine: ste_dma40: Fix PM disable depth imbalance in d40_probe
+    - Input: synaptics-rmi4 - handle reset delay when using SMBus trsnsport
+    - fbdev: atyfb: only use ioremap_uc() on i386 and ia64
+    - spi: npcm-fiu: Fix UMA reads when dummy.nbytes == 0
+    - netfilter: nfnetlink_log: silence bogus compiler warning
+    - ASoC: rt5650: fix the wrong result of key button
+    - fbdev: uvesafb: Call cn_del_callback() at the end of uvesafb_exit()
+    - scsi: mpt3sas: Fix in error path
+    - platform/x86: asus-wmi: Change ASUS_WMI_BRN_DOWN code from 0x20 to 0x2e
+    - platform/mellanox: mlxbf-tmfifo: Fix a warning message
+    - net: chelsio: cxgb4: add an error code check in t4_load_phy_fw
+    - ata: ahci: fix enum constants for gcc-13
+    - remove the sx8 block driver
+    - [Config] remove CONFIG_BLK_DEV_SX8
+    - Revert "ARM: dts: Move am33xx and am43xx mmc nodes to sdhci-omap driver"
+    - PCI: Prevent xHCI driver from claiming AMD VanGogh USB3 DRD device
+    - usb: storage: set 1.50 as the lower bcdDevice for older "Super Top"
+      compatibility
+    - tty: 8250: Remove UC-257 and UC-431
+    - tty: 8250: Add support for additional Brainboxes UC cards
+    - tty: 8250: Add support for Brainboxes UP cards
+    - tty: 8250: Add support for Intashield IS-100
+    - Linux 5.4.260
+  * CVE-2023-51779
+    - Bluetooth: af_bluetooth: Fix Use-After-Free in bt_sock_recvmsg
+  * CVE-2023-22995
+    - usb: dwc3: dwc3-qcom: Add missing platform_device_put() in
+      dwc3_qcom_acpi_register_core
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Wed, 21 Feb 2024 11:24:08 +1000
+
+linux-xilinx-zynqmp (5.4.0-1038.42) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1038.42 -proposed tracker (LP: #2052218)
+
+  [ Ubuntu: 5.4.0-172.190 ]
+
+  * focal/linux: 5.4.0-172.190 -proposed tracker (LP: #2052220)
+  * CVE-2023-51781
+    - appletalk: Fix Use-After-Free in atalk_ioctl
+  * CVE-2023-6915
+    - ida: Fix crash in ida_free when the bitmap is empty
+  * CVE-2024-0565
+    - smb: client: fix OOB in receive_encrypted_standard()
+  * CVE-2024-0646
+    - net: tls, update curr on splice as well
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Wed, 14 Feb 2024 09:16:12 +1000
+
+linux-xilinx-zynqmp (5.4.0-1037.41) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1037.41 -proposed tracker (LP: #2048280)
+
+  * Focal update: v5.4.258 upstream stable release (LP: #2042107)
+    - [Config] Update IMA_BLACKLIST_KEYRING and IMA_LOAD_X509
+
+  [ Ubuntu: 5.4.0-171.189 ]
+
+  * focal/linux: 5.4.0-171.189 -proposed tracker (LP: #2048282)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] remove helper scripts
+    - [Packaging] update annotations scripts
+    - debian/dkms-versions -- update from kernel-versions (main/2024.01.08)
+  * Page fault in RDMA ODP triggers BUG_ON during MMU notifier registration
+    (LP: #2046534)
+    - RDMA/odp: Ensure the mm is still alive before creating an implicit child
+  * Hotplugging SCSI disk in QEMU VM fails (LP: #2047382)
+    - Revert "PCI: acpiphp: Reassign resources on bridge if necessary"
+  * CVE-2023-6040
+    - netfilter: nf_tables: Reject tables of unsupported family
+  * kernel_selftests failures on kernel-P10d-LPAR10.ppc64el.10
+    (LP: #2032641)
+    - selftests: Skip TM tests on synthetic TM implementations
+  * [Debian] autoreconstruct - Do not generate chmod -x for deleted  files
+    (LP: #2045562)
+    - [Debian] autoreconstruct - Do not generate chmod -x for deleted files
+  * CVE-2023-6931
+    - perf/core: Add a new read format to get a number of lost samples
+    - perf: Fix perf_event_validate_size()
+    - perf: Fix perf_event_validate_size() lockdep splat
+  * CVE-2023-6932
+    - ipv4: igmp: fix refcnt uaf issue when receiving igmp query packet
+  * CVE-2023-6606
+    - smb: client: fix OOB in smbCalcSize()
+  * CVE-2023-45863
+    - kobject: Fix slab-out-of-bounds in fill_kobj_path()
+  * Focal update: v5.4.259 upstream stable release (LP: #2043724)
+    - RDMA/cxgb4: Check skb value for failure to allocate
+    - lib/test_meminit: fix off-by-one error in test_pages()
+    - pwm: hibvt: Explicitly set .polarity in .get_state()
+    - HID: logitech-hidpp: Fix kernel crash on receiver USB disconnect
+    - quota: Fix slow quotaoff
+    - net: prevent address rewrite in kernel_bind()
+    - drm: etvnaviv: fix bad backport leading to warning
+    - drm/msm/dsi: skip the wait for video mode done if not applicable
+    - ravb: Fix up dma_free_coherent() call in ravb_remove()
+    - ieee802154: ca8210: Fix a potential UAF in ca8210_probe
+    - mlxsw: fix mlxsw_sp2_nve_vxlan_learning_set() return type
+    - xen-netback: use default TX queue size for vifs
+    - drm/vmwgfx: fix typo of sizeof argument
+    - ixgbe: fix crash with empty VF macvlan list
+    - net: nfc: fix races in nfc_llcp_sock_get() and nfc_llcp_sock_get_sn()
+    - nfc: nci: assert requested protocol is valid
+    - workqueue: Override implicit ordered attribute in
+      workqueue_apply_unbound_cpumask()
+    - dmaengine: stm32-mdma: abort resume if no ongoing transfer
+    - usb: xhci: xhci-ring: Use sysdev for mapping bounce buffer
+    - net: usb: dm9601: fix uninitialized variable use in dm9601_mdio_read
+    - usb: dwc3: Soft reset phy on probe for host
+    - usb: musb: Get the musb_qh poniter after musb_giveback
+    - usb: musb: Modify the "HWVers" register address
+    - iio: pressure: bmp280: Fix NULL pointer exception
+    - iio: pressure: dps310: Adjust Timeout Settings
+    - iio: pressure: ms5611: ms5611_prom_is_valid false negative bug
+    - mcb: remove is_added flag from mcb_device struct
+    - libceph: use kernel_connect()
+    - ceph: fix incorrect revoked caps assert in ceph_fill_file_size()
+    - Input: powermate - fix use-after-free in powermate_config_complete
+    - Input: psmouse - fix fast_reconnect function for PS/2 mode
+    - Input: xpad - add PXN V900 support
+    - cgroup: Remove duplicates in cgroup v1 tasks file
+    - pinctrl: avoid unsafe code pattern in find_pinctrl()
+    - usb: gadget: udc-xilinx: replace memcpy with memcpy_toio
+    - usb: gadget: ncm: Handle decoding of multiple NTB's in unwrap call
+    - x86/cpu: Fix AMD erratum #1485 on Zen4-based CPUs
+    - dmaengine: mediatek: Fix deadlock caused by synchronize_irq()
+    - powerpc/8xx: Fix pte_access_permitted() for PAGE_NONE
+    - powerpc/64e: Fix wrong test in __ptep_test_and_clear_young()
+    - ravb: Fix use-after-free issue in ravb_tx_timeout_work()
+    - Documentation: sysctl: align cells in second content column
+    - usb: hub: Guard against accesses to uninitialized BOS descriptors
+    - Bluetooth: hci_event: Ignore NULL link key
+    - Bluetooth: Reject connection with the device which has same BD_ADDR
+    - Bluetooth: Fix a refcnt underflow problem for hci_conn
+    - Bluetooth: vhci: Fix race when opening vhci device
+    - Bluetooth: hci_event: Fix coding style
+    - Bluetooth: avoid memcmp() out of bounds warning
+    - ice: fix over-shifted variable
+    - nfc: nci: fix possible NULL pointer dereference in send_acknowledge()
+    - regmap: fix NULL deref on lookup
+    - KVM: x86: Mask LVTPC when handling a PMI
+    - netfilter: nft_payload: fix wrong mac header matching
+    - qed: fix LL2 RX buffer allocation
+    - xfrm: fix a data-race in xfrm_gen_index()
+    - xfrm: interface: use DEV_STATS_INC()
+    - net: ipv4: fix return value check in esp_remove_trailer
+    - net: ipv6: fix return value check in esp_remove_trailer
+    - net: rfkill: gpio: prevent value glitch during probe
+    - tcp: fix excessive TLP and RACK timeouts from HZ rounding
+    - tcp: tsq: relax tcp_small_queue_check() when rtx queue contains a single skb
+    - tun: prevent negative ifindex
+    - ipv4: fib: annotate races around nh->nh_saddr_genid and nh->nh_saddr
+    - net: usb: smsc95xx: Fix an error code in smsc95xx_reset()
+    - i40e: prevent crash on probe if hw registers have invalid values
+    - net/sched: sch_hfsc: upgrade 'rt' to 'sc' when it becomes a inner curve
+    - neighbor: tracing: Move pin6 inside CONFIG_IPV6=y section
+    - netfilter: nft_set_rbtree: .deactivate fails if element has expired
+    - net: pktgen: Fix interface flags printing
+    - resource: Add irqresource_disabled()
+    - ACPI: Drop acpi_dev_irqresource_disabled()
+    - ACPI: resource: Skip IRQ override on Asus Vivobook S5602ZA
+    - ACPI: resource: Add Asus ExpertBook B2502 to Asus quirks
+    - ACPI: resource: Skip IRQ override on Asus Expertbook B2402CBA
+    - ACPI: resource: Skip IRQ override on ASUS ExpertBook B1502CBA
+    - ACPI: resource: Skip IRQ override on ASUS ExpertBook B1402CBA
+    - ARM: dts: ti: omap: Fix noisy serial with overrun-throttle-ms for mapphone
+    - btrfs: return -EUCLEAN for delayed tree ref with a ref count not equals to 1
+    - btrfs: initialize start_slot in btrfs_log_prealloc_extents
+    - i2c: mux: Avoid potential false error message in i2c_mux_add_adapter
+    - overlayfs: set ctime when setting mtime and atime
+    - gpio: timberdale: Fix potential deadlock on &tgpio->lock
+    - ata: libata-eh: Fix compilation warning in ata_eh_link_report()
+    - tracing: relax trace_event_eval_update() execution with cond_resched()
+    - HID: holtek: fix slab-out-of-bounds Write in holtek_kbd_input_event
+    - Bluetooth: Avoid redundant authentication
+    - Bluetooth: hci_core: Fix build warnings
+    - wifi: mac80211: allow transmitting EAPOL frames with tainted key
+    - wifi: cfg80211: avoid leaking stack data into trace
+    - regulator/core: Revert "fix kobject release warning and memory leak in
+      regulator_register()"
+    - sky2: Make sure there is at least one frag_addr available
+    - drm: panel-orientation-quirks: Add quirk for One Mix 2S
+    - btrfs: fix some -Wmaybe-uninitialized warnings in ioctl.c
+    - HID: multitouch: Add required quirk for Synaptics 0xcd7e device
+    - Bluetooth: hci_event: Fix using memcmp when comparing keys
+    - mtd: rawnand: qcom: Unmap the right resource upon probe failure
+    - mtd: spinand: micron: correct bitmask for ecc status
+    - mtd: physmap-core: Restore map_rom fallback
+    - mmc: core: sdio: hold retuning if sdio in 1-bit mode
+    - mmc: core: Capture correct oemid-bits for eMMC cards
+    - Revert "pinctrl: avoid unsafe code pattern in find_pinctrl()"
+    - ACPI: irq: Fix incorrect return value in acpi_register_gsi()
+    - USB: serial: option: add Telit LE910C4-WWX 0x1035 composition
+    - USB: serial: option: add entry for Sierra EM9191 with new firmware
+    - USB: serial: option: add Fibocom to DELL custom modem FM101R-GL
+    - s390/pci: fix iommu bitmap allocation
+    - gpio: vf610: set value before the direction to avoid a glitch
+    - ASoC: pxa: fix a memory leak in probe()
+    - phy: mapphone-mdm6600: Fix runtime disable on probe
+    - phy: mapphone-mdm6600: Fix runtime PM for remove
+    - phy: mapphone-mdm6600: Fix pinctrl_pm handling for sleep pins
+    - Bluetooth: hci_sock: fix slab oob read in create_monitor_event
+    - Bluetooth: hci_sock: Correctly bounds check and pad HCI_MON_NEW_INDEX name
+    - xfrm6: fix inet6_dev refcount underflow problem
+    - Linux 5.4.259
+  * Focal update: v5.4.258 upstream stable release (LP: #2042107)
+    - NFS/pNFS: Report EINVAL errors from connect() to the server
+    - SUNRPC: Mark the cred for revalidation if the server rejects it
+    - tracing: Increase trace array ref count on enable and filter files
+    - ata: libahci: clear pending interrupt status
+    - ext4: remove the 'group' parameter of ext4_trim_extent
+    - ext4: add new helper interface ext4_try_to_trim_range()
+    - ext4: scope ret locally in ext4_try_to_trim_range()
+    - ext4: change s_last_trim_minblks type to unsigned long
+    - ext4: mark group as trimmed only if it was fully scanned
+    - ext4: replace the traditional ternary conditional operator with with
+      max()/min()
+    - ext4: move setting of trimmed bit into ext4_try_to_trim_range()
+    - ext4: do not let fstrim block system suspend
+    - ASoC: meson: spdifin: start hw on dai probe
+    - netfilter: nf_tables: disallow element removal on anonymous sets
+    - bpf: Avoid deadlock when using queue and stack maps from NMI
+    - selftests/tls: Add {} to avoid static checker warning
+    - selftests: tls: swap the TX and RX sockets in some tests
+    - ASoC: imx-audmix: Fix return error with devm_clk_get()
+    - i40e: Fix for persistent lldp support
+    - SAUCE: Revert "UBUNTU: SAUCE: i40e Fix GPF when deleting VMs"
+    - i40e: Remove scheduling while atomic possibility
+    - i40e: Fix warning message and call stack during rmmod i40e driver
+    - i40e: Fix VF VLAN offloading when port VLAN is configured
+    - powerpc/perf/hv-24x7: Update domain value check
+    - dccp: fix dccp_v4_err()/dccp_v6_err() again
+    - net: hns3: add 5ms delay before clear firmware reset irq source
+    - net: bridge: use DEV_STATS_INC()
+    - team: fix null-ptr-deref when team device type is changed
+    - net: rds: Fix possible NULL-pointer dereference
+    - gpio: tb10x: Fix an error handling path in tb10x_gpio_probe()
+    - i2c: mux: demux-pinctrl: check the return value of devm_kstrdup()
+    - Input: i8042 - add quirk for TUXEDO Gemini 17 Gen1/Clevo PD70PN
+    - scsi: qla2xxx: Fix update_fcport for current_topology
+    - scsi: qla2xxx: Fix deletion race condition
+    - drm/amd/display: Reinstate LFC optimization
+    - drm/amd/display: Fix LFC multiplier changing erratically
+    - drm/amd/display: prevent potential division by zero errors
+    - ata: libata: disallow dev-initiated LPM transitions to unsupported states
+    - MIPS: Alchemy: only build mmc support helpers if au1xmmc is enabled
+    - clk: tegra: fix error return case for recalc_rate
+    - ARM: dts: ti: omap: motorola-mapphone: Fix abe_clkctrl warning on boot
+    - bus: ti-sysc: Fix SYSC_QUIRK_SWSUP_SIDLE_ACT handling for uart wake-up
+    - xtensa: add default definition for XCHAL_HAVE_DIV32
+    - xtensa: iss/network: make functions static
+    - xtensa: boot: don't add include-dirs
+    - xtensa: boot/lib: fix function prototypes
+    - gpio: pmic-eic-sprd: Add can_sleep flag for PMIC EIC chip
+    - parisc: sba: Fix compile warning wrt list of SBA devices
+    - parisc: iosapic.c: Fix sparse warnings
+    - parisc: drivers: Fix sparse warning
+    - parisc: irq: Make irq_stack_union static to avoid sparse warning
+    - selftests/ftrace: Correctly enable event in instance-event.tc
+    - ring-buffer: Avoid softlockup in ring_buffer_resize()
+    - ata: libata-eh: do not clear ATA_PFLAG_EH_PENDING in ata_eh_reset()
+    - spi: nxp-fspi: reset the FLSHxCR1 registers
+    - bpf: Clarify error expectations from bpf_clone_redirect
+    - powerpc/watchpoints: Annotate atomic context in more places
+    - ncsi: Propagate carrier gain/loss events to the NCSI controller
+    - fbdev/sh7760fb: Depend on FB=y
+    - nvme-pci: do not set the NUMA node of device if it has none
+    - watchdog: iTCO_wdt: No need to stop the timer in probe
+    - watchdog: iTCO_wdt: Set NO_REBOOT if the watchdog is not already running
+    - i40e: improve locking of mac_filter_hash
+    - i40e: always propagate error value in i40e_set_vsi_promisc()
+    - i40e: fix return of uninitialized aq_ret in i40e_set_vsi_promisc
+    - smack: Record transmuting in smk_transmuted
+    - smack: Retrieve transmuting information in smack_inode_getsecurity()
+    - Smack:- Use overlay inode label in smack_inode_copy_up()
+    - serial: 8250_port: Check IRQ data before use
+    - nilfs2: fix potential use after free in nilfs_gccache_submit_read_data()
+    - ALSA: hda: Disable power save for solving pop issue on Lenovo ThinkCentre
+      M70q
+    - ata: libata-scsi: ignore reserved bits for REPORT SUPPORTED OPERATION CODES
+    - i2c: i801: unregister tco_pdev in i801_probe() error path
+    - ring-buffer: Update "shortest_full" in polling
+    - btrfs: properly report 0 avail for very full file systems
+    - net: thunderbolt: Fix TCPv6 GSO checksum calculation
+    - ata: libata-core: Fix ata_port_request_pm() locking
+    - ata: libata-core: Fix port and device removal
+    - ata: libata-core: Do not register PM operations for SAS ports
+    - ata: libata-sata: increase PMP SRST timeout to 10s
+    - fs: binfmt_elf_efpic: fix personality for ELF-FDPIC
+    - rbd: move rbd_dev_refresh() definition
+    - rbd: decouple header read-in from updating rbd_dev->header
+    - rbd: decouple parent info read-in from updating rbd_dev
+    - rbd: take header_rwsem in rbd_dev_refresh() only when updating
+    - Revert "PCI: qcom: Disable write access to read only registers for IP
+      v2.3.3"
+    - scsi: zfcp: Fix a double put in zfcp_port_enqueue()
+    - qed/red_ll2: Fix undefined behavior bug in struct qed_ll2_info
+    - wifi: mwifiex: Fix tlv_buf_left calculation
+    - net: replace calls to sock->ops->connect() with kernel_connect()
+    - net: prevent rewrite of msg_name in sock_sendmsg()
+    - wifi: iwlwifi: dbg_ini: fix structure packing
+    - wifi: mwifiex: Fix oob check condition in mwifiex_process_rx_packet
+    - drivers/net: process the result of hdlc_open() and add call of hdlc_close()
+      in uhdlc_close()
+    - wifi: mt76: mt76x02: fix MT76x0 external LNA gain handling
+    - regmap: rbtree: Fix wrong register marked as in-cache when creating new node
+    - ima: Finish deprecation of IMA_TRUSTED_KEYRING Kconfig
+    - scsi: target: core: Fix deadlock due to recursive locking
+    - NFS4: Trace state recovery operation
+    - NFS: Add a helper nfs_client_for_each_server()
+    - NFSv4: Fix a nfs4_state_manager() race
+    - modpost: add missing else to the "of" check
+    - net: fix possible store tearing in neigh_periodic_work()
+    - ipv4, ipv6: Fix handling of transhdrlen in __ip{,6}_append_data()
+    - net: dsa: mv88e6xxx: Avoid EEPROM timeout when EEPROM is absent
+    - net: usb: smsc75xx: Fix uninit-value access in __smsc75xx_read_reg
+    - net: nfc: llcp: Add lock when modifying device list
+    - netfilter: handle the connecting collision properly in
+      nf_conntrack_proto_sctp
+    - net: stmmac: dwmac-stm32: fix resume on STM32 MCU
+    - tcp: fix quick-ack counting to count actual ACKs of new data
+    - tcp: fix delayed ACKs for MSS boundary condition
+    - sctp: update transport state when processing a dupcook packet
+    - sctp: update hb timer immediately after users change hb_interval
+    - cpupower: add Makefile dependencies for install targets
+    - RDMA/core: Require admin capabilities to set system parameters
+    - IB/mlx4: Fix the size of a buffer in add_port_entries()
+    - gpio: aspeed: fix the GPIO number passed to pinctrl_gpio_set_config()
+    - gpio: pxa: disable pinctrl calls for MMP_GPIO
+    - RDMA/cma: Fix truncation compilation warning in make_cma_ports
+    - RDMA/uverbs: Fix typo of sizeof argument
+    - RDMA/siw: Fix connection failure handling
+    - RDMA/mlx5: Fix NULL string error
+    - parisc: Restore __ldcw_align for PA-RISC 2.0 processors
+    - NFS: Fix a race in __nfs_list_for_each_server()
+    - ima: rework CONFIG_IMA dependency block
+    - [Config] Update IMA_BLACKLIST_KEYRING and IMA_LOAD_X509
+    - xen/events: replace evtchn_rwlock with RCU
+    - Linux 5.4.258
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Thu, 18 Jan 2024 14:59:22 +1000
+
+linux-xilinx-zynqmp (5.4.0-1036.40) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1036.40 -proposed tracker (LP: #2048652)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] remove helper scripts
+
+  [ Ubuntu: 5.4.0-170.188 ]
+
+  * focal/linux: 5.4.0-170.188 -proposed tracker (LP: #2048654)
+  * CVE-2023-6040
+    - netfilter: nf_tables: Reject tables of unsupported family
+  * CVE-2023-6606
+    - smb: client: fix OOB in smbCalcSize()
+  * CVE-2023-6932
+    - ipv4: igmp: fix refcnt uaf issue when receiving igmp query packet
+  * CVE-2023-6931
+    - perf/core: Add a new read format to get a number of lost samples
+    - perf: Fix perf_event_validate_size()
+    - perf: Fix perf_event_validate_size() lockdep splat
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Tue, 16 Jan 2024 16:16:33 +1000
+
+linux-xilinx-zynqmp (5.4.0-1035.39) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1035.39 -proposed tracker (LP: #2041649)
+
+  * Focal update: v5.4.257 upstream stable release (LP: #2040284)
+    - [Config] Update annotations after CONFIG_IMA_TRUSTED_KEYRING removal
+
+  [ Ubuntu: 5.4.0-169.187 ]
+
+  * focal/linux: 5.4.0-169.187 -proposed tracker (LP: #2044375)
+  * USB bus error after upgrading to proposed kernel on lunar, jammy and focal
+    (LP: #2043197)
+    - USB: core: Fix oversight in SuperSpeed initialization
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync git-ubuntu-log
+    - [Packaging] resync update-dkms-versions helper
+    - [Packaging] update annotations scripts
+
+  [ Ubuntu: 5.4.0-168.186 ]
+
+  * focal/linux: 5.4.0-168.186 -proposed tracker (LP: #2041652)
+  * Focal update: v5.4.257 upstream stable release (LP: #2040284)
+    - erofs: ensure that the post-EOF tails are all zeroed
+    - ARM: pxa: remove use of symbol_get()
+    - mmc: au1xmmc: force non-modular build and remove symbol_get usage
+    - net: enetc: use EXPORT_SYMBOL_GPL for enetc_phc_index
+    - rtc: ds1685: use EXPORT_SYMBOL_GPL for ds1685_rtc_poweroff
+    - modules: only allow symbol_get of EXPORT_SYMBOL_GPL modules
+    - USB: serial: option: add Quectel EM05G variant (0x030e)
+    - USB: serial: option: add FOXCONN T99W368/T99W373 product
+    - HID: wacom: remove the battery when the EKR is off
+    - staging: rtl8712: fix race condition
+    - Bluetooth: btsdio: fix use after free bug in btsdio_remove due to race
+      condition
+    - serial: sc16is7xx: fix bug when first setting GPIO direction
+    - firmware: stratix10-svc: Fix an NULL vs IS_ERR() bug in probe
+    - fsi: master-ast-cf: Add MODULE_FIRMWARE macro
+    - nilfs2: fix general protection fault in nilfs_lookup_dirty_data_buffers()
+    - nilfs2: fix WARNING in mark_buffer_dirty due to discarded buffer reuse
+    - pinctrl: amd: Don't show `Invalid config param` errors
+    - 9p: virtio: make sure 'offs' is initialized in zc_request
+    - ASoC: da7219: Flush pending AAD IRQ when suspending
+    - ASoC: da7219: Check for failure reading AAD IRQ events
+    - ethernet: atheros: fix return value check in atl1c_tso_csum()
+    - vxlan: generalize vxlan_parse_gpe_hdr and remove unused args
+    - m68k: Fix invalid .section syntax
+    - s390/dasd: use correct number of retries for ERP requests
+    - s390/dasd: fix hanging device after request requeue
+    - fs/nls: make load_nls() take a const parameter
+    - ASoc: codecs: ES8316: Fix DMIC config
+    - ASoC: atmel: Fix the 8K sample parameter in I2SC master
+    - platform/x86: intel: hid: Always call BTNL ACPI method
+    - platform/x86: huawei-wmi: Silence ambient light sensor
+    - security: keys: perform capable check only on privileged operations
+    - clk: fixed-mmio: make COMMON_CLK_FIXED_MMIO depend on HAS_IOMEM
+    - net: usb: qmi_wwan: add Quectel EM05GV2
+    - idmaengine: make FSL_EDMA and INTEL_IDMA64 depends on HAS_IOMEM
+    - scsi: qedi: Fix potential deadlock on &qedi_percpu->p_work_lock
+    - netlabel: fix shift wrapping bug in netlbl_catmap_setlong()
+    - bnx2x: fix page fault following EEH recovery
+    - sctp: handle invalid error codes without calling BUG()
+    - cifs: add a warning when the in-flight count goes negative
+    - scsi: storvsc: Always set no_report_opcodes
+    - ALSA: seq: oss: Fix racy open/close of MIDI devices
+    - platform/mellanox: Fix mlxbf-tmfifo not handling all virtio CONSOLE
+      notifications
+    - powerpc/32s: Fix assembler warning about r0
+    - udf: Check consistency of Space Bitmap Descriptor
+    - udf: Handle error when adding extent to a file
+    - Revert "net: macsec: preserve ingress frame ordering"
+    - reiserfs: Check the return value from __getblk()
+    - eventfd: Export eventfd_ctx_do_read()
+    - eventfd: prevent underflow for eventfd semaphores
+    - new helper: lookup_positive_unlocked()
+    - fs: Fix error checking for d_hash_and_lookup()
+    - tmpfs: verify {g,u}id mount options correctly
+    - OPP: Fix passing 0 to PTR_ERR in _opp_attach_genpd()
+    - x86/asm: Make more symbols local
+    - x86/boot: Annotate local functions
+    - x86/decompressor: Don't rely on upper 32 bits of GPRs being preserved
+    - perf/imx_ddr: don't enable counter0 if none of 4 counters are used
+    - cpufreq: powernow-k8: Use related_cpus instead of cpus in driver.exit()
+    - bpf: Clear the probe_addr for uprobe
+    - tcp: tcp_enter_quickack_mode() should be static
+    - regmap: rbtree: Use alloc_flags for memory allocations
+    - spi: tegra20-sflash: fix to check return value of platform_get_irq() in
+      tegra_sflash_probe()
+    - can: gs_usb: gs_usb_receive_bulk_callback(): count RX overflow errors also
+      in case of OOM
+    - wifi: mwifiex: Fix OOB and integer underflow when rx packets
+    - mwifiex: switch from 'pci_' to 'dma_' API
+    - wifi: mwifiex: fix error recovery in PCIE buffer descriptor management
+    - crypto: stm32 - Properly handle pm_runtime_get failing
+    - Bluetooth: nokia: fix value check in nokia_bluetooth_serdev_probe()
+    - crypto: caam - fix unchecked return value error
+    - hwrng: iproc-rng200 - use semicolons rather than commas to separate
+      statements
+    - hwrng: iproc-rng200 - Implement suspend and resume calls
+    - lwt: Fix return values of BPF xmit ops
+    - lwt: Check LWTUNNEL_XMIT_CONTINUE strictly
+    - fs: ocfs2: namei: check return value of ocfs2_add_entry()
+    - wifi: mwifiex: fix memory leak in mwifiex_histogram_read()
+    - wifi: mwifiex: Fix missed return in oob checks failed path
+    - wifi: ath9k: fix races between ath9k_wmi_cmd and ath9k_wmi_ctrl_rx
+    - wifi: ath9k: protect WMI command response buffer replacement with a lock
+    - wifi: mwifiex: avoid possible NULL skb pointer dereference
+    - wifi: ath9k: use IS_ERR() with debugfs_create_dir()
+    - net: arcnet: Do not call kfree_skb() under local_irq_disable()
+    - mlxsw: i2c: Fix chunk size setting in output mailbox buffer
+    - mlxsw: i2c: Limit single transaction buffer size
+    - netrom: Deny concurrent connect().
+    - drm/bridge: tc358764: Fix debug print parameter order
+    - quota: avoid increasing DQST_LOOKUPS when iterating over dirty/inuse list
+    - quota: factor out dquot_write_dquot()
+    - quota: rename dquot_active() to inode_quota_active()
+    - quota: add new helper dquot_active()
+    - quota: fix dqput() to follow the guarantees dquot_srcu should provide
+    - drm/amdgpu: avoid integer overflow warning in amdgpu_device_resize_fb_bar()
+    - ARM: dts: BCM53573: Drop nonexistent "default-off" LED trigger
+    - ARM: dts: BCM53573: Add cells sizes to PCIe node
+    - ARM: dts: BCM53573: Use updated "spi-gpio" binding properties
+    - drm/etnaviv: fix dumping of active MMU context
+    - ARM: dts: s3c6410: move fixed clocks under root node in Mini6410
+    - ARM: dts: s3c6410: align node SROM bus node name with dtschema in Mini6410
+    - ARM: dts: s3c64xx: align pinctrl with dtschema
+    - ARM: dts: samsung: s3c6410-mini6410: correct ethernet reg addresses (split)
+    - ARM: dts: s5pv210: add RTC 32 KHz clock in SMDKV210
+    - ARM: dts: s5pv210: use defines for IRQ flags in SMDKV210
+    - ARM: dts: s5pv210: correct ethernet unit address in SMDKV210
+    - ARM: dts: s5pv210: add dummy 5V regulator for backlight on SMDKv210
+    - ARM: dts: samsung: s5pv210-smdkv210: correct ethernet reg addresses (split)
+    - drm: adv7511: Fix low refresh rate register for ADV7533/5
+    - ARM: dts: BCM53573: Fix Ethernet info for Luxul devices
+    - arm64: dts: qcom: sdm845: Add missing RPMh power domain to GCC
+    - drm/amdgpu: Update min() to min_t() in 'amdgpu_info_ioctl'
+    - md/bitmap: don't set max_write_behind if there is no write mostly device
+    - md/md-bitmap: hold 'reconfig_mutex' in backlog_store()
+    - drm/tegra: Remove superfluous error messages around platform_get_irq()
+    - drm/tegra: dpaux: Fix incorrect return value of platform_get_irq
+    - of: unittest: fix null pointer dereferencing in
+      of_unittest_find_node_by_name()
+    - drm/armada: Fix off-by-one error in armada_overlay_get_property()
+    - drm/panel: simple: Add missing connector type and pixel format for AUO
+      T215HVN01
+    - ima: Remove deprecated IMA_TRUSTED_KEYRING Kconfig
+    - [Config] Update annotations after CONFIG_IMA_TRUSTED_KEYRING removal
+    - drm/msm/mdp5: Don't leak some plane state
+    - smackfs: Prevent underflow in smk_set_cipso()
+    - audit: fix possible soft lockup in __audit_inode_child()
+    - drm/mediatek: Fix potential memory leak if vmap() fail
+    - of: unittest: Fix overlay type in apply/revert check
+    - ALSA: ac97: Fix possible error value of *rac97
+    - ipmi:ssif: Add check for kstrdup
+    - ipmi:ssif: Fix a memory leak when scanning for an adapter
+    - drivers: clk: keystone: Fix parameter judgment in _of_pll_clk_init()
+    - clk: sunxi-ng: Modify mismatched function name
+    - PCI: Mark NVIDIA T4 GPUs to avoid bus reset
+    - PCI: pciehp: Use RMW accessors for changing LNKCTL
+    - PCI/ASPM: Use RMW accessors for changing LNKCTL
+    - clk: imx: composite-8m: fix clock pauses when set_rate would be a no-op
+    - powerpc/fadump: reset dump area size if fadump memory reserve fails
+    - PCI: Add #defines for Enter Compliance, Transmit Margin
+    - drm/amdgpu: Correct Transmit Margin masks
+    - drm/amdgpu: Replace numbers with PCI_EXP_LNKCTL2 definitions
+    - drm/amdgpu: Prefer pcie_capability_read_word()
+    - drm/amdgpu: Use RMW accessors for changing LNKCTL
+    - drm/radeon: Correct Transmit Margin masks
+    - drm/radeon: Replace numbers with PCI_EXP_LNKCTL2 definitions
+    - drm/radeon: Prefer pcie_capability_read_word()
+    - drm/radeon: Use RMW accessors for changing LNKCTL
+    - wifi: ath10k: Use RMW accessors for changing LNKCTL
+    - nfs/blocklayout: Use the passed in gfp flags
+    - powerpc/iommu: Fix notifiers being shared by PCI and VIO buses
+    - jfs: validate max amount of blocks before allocation.
+    - fs: lockd: avoid possible wrong NULL parameter
+    - NFSD: da_addr_body field missing in some GETDEVICEINFO replies
+    - NFS: Guard against READDIR loop when entry names exceed MAXNAMELEN
+    - media: v4l2-fwnode: fix v4l2_fwnode_parse_link handling
+    - media: v4l2-fwnode: simplify v4l2_fwnode_parse_link
+    - media: v4l2-core: Fix a potential resource leak in v4l2_fwnode_parse_link()
+    - drivers: usb: smsusb: fix error handling code in smsusb_init_device
+    - media: dib7000p: Fix potential division by zero
+    - media: dvb-usb: m920x: Fix a potential memory leak in m920x_i2c_xfer()
+    - media: cx24120: Add retval check for cx24120_message_send()
+    - media: mediatek: vcodec: Return NULL if no vdec_fb is found
+    - usb: phy: mxs: fix getting wrong state with mxs_phy_is_otg_host()
+    - scsi: iscsi: Add strlen() check in iscsi_if_set{_host}_param()
+    - scsi: be2iscsi: Add length check when parsing nlattrs
+    - scsi: qla4xxx: Add length check when parsing nlattrs
+    - serial: sprd: getting port index via serial aliases only
+    - serial: sprd: remove redundant sprd_port cleanup
+    - serial: sprd: Assign sprd_port after initialized to avoid wrong access
+    - serial: sprd: Fix DMA buffer leak issue
+    - x86/APM: drop the duplicate APM_MINOR_DEV macro
+    - scsi: qedf: Do not touch __user pointer in
+      qedf_dbg_stop_io_on_error_cmd_read() directly
+    - scsi: qedf: Do not touch __user pointer in qedf_dbg_debug_cmd_read()
+      directly
+    - scsi: qedf: Do not touch __user pointer in qedf_dbg_fp_int_cmd_read()
+      directly
+    - coresight: tmc: Explicit type conversions to prevent integer overflow
+    - dma-buf/sync_file: Fix docs syntax
+    - driver core: test_async: fix an error code
+    - IB/uverbs: Fix an potential error pointer dereference
+    - iommu/vt-d: Fix to flush cache of PASID directory table
+    - media: go7007: Remove redundant if statement
+    - USB: gadget: f_mass_storage: Fix unused variable warning
+    - media: i2c: ov5640: Configure HVP lines in s_power callback
+    - media: ov5640: Enable MIPI interface in ov5640_set_power_mipi()
+    - media: i2c: ov2680: Set V4L2_CTRL_FLAG_MODIFY_LAYOUT on flips
+    - media: ov2680: Remove auto-gain and auto-exposure controls
+    - media: ov2680: Fix ov2680_bayer_order()
+    - media: ov2680: Fix vflip / hflip set functions
+    - media: ov2680: Fix regulators being left enabled on ov2680_power_on() errors
+    - scsi: core: Use 32-bit hostnum in scsi_host_lookup()
+    - scsi: fcoe: Fix potential deadlock on &fip->ctlr_lock
+    - serial: tegra: handle clk prepare error in tegra_uart_hw_init()
+    - amba: bus: fix refcount leak
+    - Revert "IB/isert: Fix incorrect release of isert connection"
+    - RDMA/siw: Balance the reference of cep->kref in the error path
+    - RDMA/siw: Correct wrong debug message
+    - HID: logitech-dj: Fix error handling in logi_dj_recv_switch_to_dj_mode()
+    - HID: multitouch: Correct devm device reference for hidinput input_dev name
+    - x86/speculation: Mark all Skylake CPUs as vulnerable to GDS
+    - tracing: Fix race issue between cpu buffer write and swap
+    - phy/rockchip: inno-hdmi: use correct vco_div_5 macro on rk3328
+    - phy/rockchip: inno-hdmi: round fractal pixclock in rk3328 recalc_rate
+    - phy/rockchip: inno-hdmi: do not power on rk3328 post pll on reg write
+    - rpmsg: glink: Add check for kstrdup
+    - mtd: rawnand: fsmc: handle clk prepare error in fsmc_nand_resume()
+    - um: Fix hostaudio build errors
+    - dmaengine: ste_dma40: Add missing IRQ check in d40_probe
+    - cpufreq: Fix the race condition while updating the transition_task of policy
+    - virtio_ring: fix avail_wrap_counter in virtqueue_add_packed
+    - skbuff: skb_segment, Call zero copy functions before using skbuff frags
+    - PM / devfreq: Fix leak in devfreq_dev_release()
+    - ALSA: pcm: Fix missing fixup call in compat hw_refine ioctl
+    - ipmi_si: fix a memleak in try_smi_init()
+    - ARM: OMAP2+: Fix -Warray-bounds warning in _pwrdm_state_switch()
+    - backlight/gpio_backlight: Compare against struct fb_info.device
+    - backlight/bd6107: Compare against struct fb_info.device
+    - backlight/lv5207lp: Compare against struct fb_info.device
+    - xtensa: PMU: fix base address for the newer hardware
+    - media: dvb: symbol fixup for dvb_attach()
+    - ntb: Drop packets when qp link is down
+    - ntb: Clean up tx tail index on link down
+    - ntb: Fix calculation ntb_transport_tx_free_entry()
+    - Revert "PCI: Mark NVIDIA T4 GPUs to avoid bus reset"
+    - procfs: block chmod on /proc/thread-self/comm
+    - parisc: Fix /proc/cpuinfo output for lscpu
+    - dlm: fix plock lookup when using multiple lockspaces
+    - dccp: Fix out of bounds access in DCCP error handler
+    - X.509: if signature is unsupported skip validation
+    - net: handle ARPHRD_PPP in dev_is_mac_header_xmit()
+    - fsverity: skip PKCS#7 parser when keyring is empty
+    - pstore/ram: Check start of empty przs during init
+    - s390/ipl: add missing secure/has_secure file to ipl type 'unknown'
+    - crypto: stm32 - fix loop iterating through scatterlist for DMA
+    - cpufreq: brcmstb-avs-cpufreq: Fix -Warray-bounds bug
+    - sc16is7xx: Set iobase to device index
+    - serial: sc16is7xx: fix broken port 0 uart init
+    - usb: typec: tcpci: clear the fault status bit
+    - udf: initialize newblock to 0
+    - drm: fix double free for gbo in drm_gem_vram_init and drm_gem_vram_create
+    - net/ipv6: SKB symmetric hash should incorporate transport ports
+    - scsi: qla2xxx: fix inconsistent TMF timeout
+    - scsi: qla2xxx: Fix erroneous link up failure
+    - scsi: qla2xxx: Turn off noisy message log
+    - scsi: qla2xxx: Remove unsupported ql2xenabledif option
+    - fbdev/ep93xx-fb: Do not assign to struct fb_info.dev
+    - drm/ast: Fix DRAM init on AST2200
+    - lib/test_meminit: allocate pages up to order MAX_ORDER
+    - parisc: led: Fix LAN receive and transmit LEDs
+    - parisc: led: Reduce CPU overhead for disk & lan LED computation
+    - clk: qcom: gcc-mdm9615: use proper parent for pll0_vote clock
+    - soc: qcom: qmi_encdec: Restrict string length in decode
+    - NFSv4/pnfs: minor fix for cleanup path in nfs4_get_device_info
+    - kconfig: fix possible buffer overflow
+    - perf annotate bpf: Don't enclose non-debug code with an assert()
+    - x86/virt: Drop unnecessary check on extended CPUID level in cpu_has_svm()
+    - perf top: Don't pass an ERR_PTR() directly to perf_session__delete()
+    - watchdog: intel-mid_wdt: add MODULE_ALIAS() to allow auto-load
+    - pwm: lpc32xx: Remove handling of PWM channels
+    - sctp: annotate data-races around sk->sk_wmem_queued
+    - ipv4: annotate data-races around fi->fib_dead
+    - net: read sk->sk_family once in sk_mc_loop()
+    - igb: disable virtualization features on 82580
+    - veth: Fixing transmit return status for dropped packets
+    - net: ipv6/addrconf: avoid integer underflow in ipv6_create_tempaddr
+    - af_unix: Fix data-races around user->unix_inflight.
+    - af_unix: Fix data-race around unix_tot_inflight.
+    - af_unix: Fix data-races around sk->sk_shutdown.
+    - af_unix: Fix data race around sk->sk_err.
+    - kcm: Destroy mutex in kcm_exit_net()
+    - igc: Change IGC_MIN to allow set rx/tx value between 64 and 80
+    - igbvf: Change IGBVF_MIN to allow set rx/tx value between 64 and 80
+    - igb: Change IGB_MIN to allow set rx/tx value between 64 and 80
+    - s390/zcrypt: don't leak memory if dev_set_name() fails
+    - idr: fix param name in idr_alloc_cyclic() doc
+    - ip_tunnels: use DEV_STATS_INC()
+    - net: hns3: fix the port information display when sfp is absent
+    - sh: boards: Fix CEU buffer size passed to dma_declare_coherent_memory()
+    - ata: sata_gemini: Add missing MODULE_DESCRIPTION
+    - ata: pata_ftide010: Add missing MODULE_DESCRIPTION
+    - fuse: nlookup missing decrement in fuse_direntplus_link
+    - btrfs: don't start transaction when joining with TRANS_JOIN_NOSTART
+    - btrfs: use the correct superblock to compare fsid in btrfs_validate_super
+    - mtd: rawnand: brcmnand: Fix crash during the panic_write
+    - mtd: rawnand: brcmnand: Fix potential out-of-bounds access in oob write
+    - mtd: rawnand: brcmnand: Fix potential false time out warning
+    - perf hists browser: Fix hierarchy mode header
+    - perf tools: Handle old data in PERF_RECORD_ATTR
+    - usb: typec: tcpm: Refactor tcpm_handle_vdm_request payload handling
+    - usb: typec: tcpm: Refactor tcpm_handle_vdm_request
+    - usb: typec: bus: verify partner exists in typec_altmode_attention
+    - ARM: dts: BCM5301X: Extend RAM to full 256MB for Linksys EA6500 V2
+    - clk: imx8mm: Move 1443X/1416X PLL clock structure to common place
+    - net: ipv4: fix one memleak in __inet_del_ifa()
+    - net: ethernet: mvpp2_main: fix possible OOB write in
+      mvpp2_ethtool_get_rxnfc()
+    - net: ethernet: mtk_eth_soc: fix possible NULL pointer dereference in
+      mtk_hwlro_get_fdir_all()
+    - r8152: check budget for r8152_poll()
+    - kcm: Fix memory leak in error path of kcm_sendmsg()
+    - platform/mellanox: mlxbf-tmfifo: Drop the Rx packet if no more descriptors
+    - mlxbf-tmfifo: sparse tags for config access
+    - platform/mellanox: mlxbf-tmfifo: Drop jumbo frames
+    - net/tls: do not free tls_rec on async operation in bpf_exec_tx_verdict()
+    - ixgbe: fix timestamp configuration code
+    - kcm: Fix error handling for SOCK_DGRAM in kcm_sendmsg().
+    - drm/amd/display: Fix a bug when searching for insert_above_mpcc
+    - parisc: Drop loops_per_jiffy from per_cpu struct
+    - autofs: fix memory leak of waitqueues in autofs_catatonic_mode
+    - btrfs: output extra debug info if we failed to find an inline backref
+    - locks: fix KASAN: use-after-free in trace_event_raw_event_filelock_lock
+    - ACPICA: Add AML_NO_OPERAND_RESOLVE flag to Timer
+    - kernel/fork: beware of __put_task_struct() calling context
+    - ACPI: video: Add backlight=native DMI quirk for Lenovo Ideapad Z470
+    - perf/smmuv3: Enable HiSilicon Erratum 162001900 quirk for HIP08/09
+    - hw_breakpoint: fix single-stepping when using bpf_overflow_handler
+    - devlink: remove reload failed checks in params get/set callbacks
+    - wifi: ath9k: fix printk specifier
+    - wifi: mwifiex: fix fortify warning
+    - crypto: lib/mpi - avoid null pointer deref in mpi_cmp_ui()
+    - tpm_tis: Resend command to recover from data transfer errors
+    - mmc: sdhci-esdhc-imx: improve ESDHC_FLAG_ERR010450
+    - alx: fix OOB-read compiler warning
+    - wifi: mac80211_hwsim: drop short frames
+    - drm/exynos: fix a possible null-pointer dereference due to data race in
+      exynos_drm_crtc_atomic_disable()
+    - bus: ti-sysc: Configure uart quirks for k3 SoC
+    - md: raid1: fix potential OOB in raid1_remove_disk()
+    - ext2: fix datatype of block number in ext2_xattr_set2()
+    - fs/jfs: prevent double-free in dbUnmount() after failed jfs_remount()
+    - jfs: fix invalid free of JFS_IP(ipimap)->i_imap in diUnmount
+    - powerpc/pseries: fix possible memory leak in ibmebus_bus_init()
+    - media: dvb-usb-v2: af9035: Fix null-ptr-deref in af9035_i2c_master_xfer
+    - media: dw2102: Fix null-ptr-deref in dw2102_i2c_transfer()
+    - media: af9005: Fix null-ptr-deref in af9005_i2c_xfer
+    - media: anysee: fix null-ptr-deref in anysee_master_xfer
+    - media: az6007: Fix null-ptr-deref in az6007_i2c_xfer()
+    - media: tuners: qt1010: replace BUG_ON with a regular error
+    - media: pci: cx23885: replace BUG with error return
+    - usb: gadget: fsl_qe_udc: validate endpoint index for ch9 udc
+    - scsi: target: iscsi: Fix buffer overflow in lio_target_nacl_info_show()
+    - serial: cpm_uart: Avoid suspicious locking
+    - media: pci: ipu3-cio2: Initialise timing struct to avoid a compiler warning
+    - kobject: Add sanity check for kset->kobj.ktype in kset_register()
+    - tools features: Add feature test to check if libbfd has buildid support
+    - perf jevents: Make build dependency on test JSONs
+    - perf tools: Add an option to build without libbfd
+    - btrfs: move btrfs_pinned_by_swapfile prototype into volumes.h
+    - btrfs: add a helper to read the superblock metadata_uuid
+    - btrfs: compare the correct fsid/metadata_uuid in btrfs_validate_super
+    - selftests: tracing: Fix to unmount tracefs for recovering environment
+    - md/raid1: fix error: ISO C90 forbids mixed declarations
+    - attr: block mode changes of symlinks
+    - btrfs: fix lockdep splat and potential deadlock after failure running
+      delayed items
+    - tracing: Have current_trace inc the trace array ref count
+    - tracing: Have option files inc the trace array ref count
+    - nfsd: fix change_info in NFSv4 RENAME replies
+    - tracefs: Add missing lockdown check to tracefs_create_dir()
+    - i2c: aspeed: Reset the i2c controller when timeout occurs
+    - scsi: megaraid_sas: Fix deadlock on firmware crashdump
+    - ext4: fix rec_len verify error
+    - mtd: rawnand: brcmnand: Fix ECC level field setting for v7.2 controller
+    - drm/amdgpu: fix amdgpu_cs_p1_user_fence
+    - Linux 5.4.257
+  * Focal update: v5.4.257 upstream stable release (LP: #2040284) //
+    CVE-2023-39189
+    - netfilter: nfnetlink_osf: avoid OOB read
+  * CVE-2023-45871
+    - igb: set max size RX buffer when store bad packet is enabled
+  * CVE-2023-39193
+    - netfilter: xt_sctp: validate the flag_info count
+  * CVE-2023-39192
+    - netfilter: xt_u32: validate user space input
+  * CVE-2023-31085
+    - ubi: Refuse attaching if mtd's erasesize is 0
+  * CVE-2023-5717
+    - perf: Disallow mis-matched inherited group reads
+  * CVE-2023-5178
+    - nvmet-tcp: move send/recv error handling in the send/recv methods instead of
+      call-sites
+    - nvmet-tcp: Fix a possible UAF in queue intialization setup
+  * CVE-2023-42754
+    - ipv4: fix null-deref in ipv4_link_failure
+  * Focal update: v5.4.256 upstream stable release (LP: #2039446)
+    - powerpc/pmac/smp: Avoid unused-variable warnings
+    - powerpc/pmac/smp: Drop unnecessary volatile qualifier
+    - Revert "MIPS: Alchemy: fix dbdma2"
+    - Linux 5.4.256
+  * Focal update: v5.4.255 upstream stable release (LP: #2039440)
+    - mmc: sdhci_f_sdh30: convert to devm_platform_ioremap_resource
+    - mmc: sdhci-f-sdh30: Replace with sdhci_pltfm
+    - selftests: forwarding: tc_flower: Relax success criterion
+    - macsec: Fix traffic counters/statistics
+    - macsec: use DEV_STATS_INC()
+    - drm/radeon: Fix integer overflow in radeon_cs_parser_init
+    - ALSA: emu10k1: roll up loops in DSP setup code for Audigy
+    - quota: Properly disable quotas when add_dquot_ref() fails
+    - quota: fix warning in dqgrab()
+    - HID: add quirk for 03f0:464a HP Elite Presenter Mouse
+    - ovl: check type and offset of struct vfsmount in ovl_entry
+    - udf: Fix uninitialized array access for some pathnames
+    - fs: jfs: Fix UBSAN: array-index-out-of-bounds in dbAllocDmapLev
+    - MIPS: dec: prom: Address -Warray-bounds warning
+    - FS: JFS: Fix null-ptr-deref Read in txBegin
+    - FS: JFS: Check for read-only mounted filesystem in txBegin
+    - media: v4l2-mem2mem: add lock to protect parameter num_rdy
+    - media: platform: mediatek: vpu: fix NULL ptr dereference
+    - usb: chipidea: imx: don't request QoS for imx8ulp
+    - gfs2: Fix possible data races in gfs2_show_options()
+    - pcmcia: rsrc_nonstatic: Fix memory leak in nonstatic_release_resource_db()
+    - Bluetooth: L2CAP: Fix use-after-free
+    - drm/amdgpu: Fix potential fence use-after-free v2
+    - ALSA: hda/realtek: Add quirks for Unis H3C Desktop B760 & Q760
+    - ALSA: hda: fix a possible null-pointer dereference due to data race in
+      snd_hdac_regmap_sync()
+    - powerpc/kasan: Disable KCOV in KASAN code
+    - IMA: allow/fix UML builds
+    - iio: add addac subdirectory
+    - iio: adc: stx104: Utilize iomap interface
+    - iio: adc: stx104: Implement and utilize register structures
+    - iio: stx104: Move to addac subdirectory
+    - iio: addac: stx104: Fix race condition for stx104_write_raw()
+    - iio: addac: stx104: Fix race condition when converting analog-to-digital
+    - iommu/amd: Fix "Guest Virtual APIC Table Root Pointer" configuration in IRTE
+    - PM-runtime: add tracepoints for usage_count changes
+    - PM: runtime: Add pm_runtime_get_if_active()
+    - ALSA: hda: Fix unhandled register update during auto-suspend period
+    - irqchip/mips-gic: Get rid of the reliance on irq_cpu_online()
+    - irqchip/mips-gic: Use raw spinlock for gic_lock
+    - interconnect: Move internal structs into a separate file
+    - interconnect: Add helpers for enabling/disabling a path
+    - usb: dwc3: qcom: Add helper functions to enable,disable wake irqs
+    - USB: dwc3: qcom: fix NULL-deref on suspend
+    - mmc: bcm2835: fix deferred probing
+    - mmc: sunxi: fix deferred probing
+    - leds: trigger: netdev: Recheck NETDEV_LED_MODE_LINKUP on dev rename
+    - tracing/probes: Have process_fetch_insn() take a void * instead of pt_regs
+    - tracing/probes: Fix to update dynamic data counter if fetcharg uses it
+    - net/ncsi: Fix gma flag setting after response
+    - nfsd4: kill warnings on testing stateids with mismatched clientids
+    - nfsd: Remove incorrect check in nfsd4_validate_stateid
+    - virtio-mmio: convert to devm_platform_ioremap_resource
+    - virtio-mmio: Use to_virtio_mmio_device() to simply code
+    - virtio-mmio: don't break lifecycle of vm_dev
+    - i2c: bcm-iproc: Fix bcm_iproc_i2c_isr deadlock issue
+    - fbdev: mmp: fix value check in mmphw_probe()
+    - powerpc/rtas_flash: allow user copy to flash block cache objects
+    - tty: serial: fsl_lpuart: Clear the error flags by writing 1 for lpuart32
+      platforms
+    - btrfs: fix BUG_ON condition in btrfs_cancel_balance
+    - net: xfrm: Fix xfrm_address_filter OOB read
+    - net: af_key: fix sadb_x_filter validation
+    - xfrm: interface: rename xfrm_interface.c to xfrm_interface_core.c
+    - xfrm: fix slab-use-after-free in decode_session6
+    - ip6_vti: fix slab-use-after-free in decode_session6
+    - ip_vti: fix potential slab-use-after-free in decode_session6
+    - selftests: mirror_gre_changes: Tighten up the TTL test match
+    - ipvs: fix racy memcpy in proc_do_sync_threshold
+    - netfilter: nft_dynset: disallow object maps
+    - team: Fix incorrect deletion of ETH_P_8021AD protocol vid from slaves
+    - i40e: fix misleading debug logs
+    - net: dsa: mv88e6xxx: Wait for EEPROM done before HW reset
+    - sock: Fix misuse of sk_under_memory_pressure()
+    - net: do not allow gso_size to be set to GSO_BY_FRAGS
+    - bus: ti-sysc: Improve reset to work with modules with no sysconfig
+    - bus: ti-sysc: Flush posted write on enable before reset
+    - ARM: dts: imx7s: Drop dma-apb interrupt-names
+    - ARM: dts: imx: Adjust dma-apbh node name
+    - ARM: dts: imx: Set default tuning step for imx7d usdhc
+    - ARM: dts: imx: Set default tuning step for imx6sx usdhc
+    - ASoC: rt5665: add missed regulator_bulk_disable
+    - ASoC: meson: axg-tdm-formatter: fix channel slot allocation
+    - serial: 8250: Fix oops for port->pm on uart_change_pm()
+    - ALSA: usb-audio: Add support for Mythware XA001AU capture and playback
+      interfaces.
+    - cifs: Release folio lock on fscache read hit.
+    - mmc: wbsd: fix double mmc_free_host() in wbsd_init()
+    - mmc: block: Fix in_flight[issue_type] value error
+    - netfilter: set default timeout to 3 secs for sctp shutdown send and recv
+      state
+    - virtio-net: set queues after driver_ok
+    - net: fix the RTO timer retransmitting skb every 1ms if linear option is
+      enabled
+    - net: xfrm: Amend XFRMA_SEC_CTX nla_policy structure
+    - mmc: f-sdh30: fix order of function calls in sdhci_f_sdh30_remove
+    - net: phy: broadcom: stub c45 read/write for 54810
+    - PCI: acpiphp: Reassign resources on bridge if necessary
+    - dlm: improve plock logging if interrupted
+    - dlm: replace usage of found with dedicated list iterator variable
+    - fs: dlm: add pid to debug log
+    - fs: dlm: change plock interrupted message to debug again
+    - fs: dlm: use dlm_plock_info for do_unlock_close
+    - fs: dlm: fix mismatch of plock results from userspace
+    - MIPS: cpu-features: Enable octeon_cache by cpu_type
+    - MIPS: cpu-features: Use boot_cpu_type for CPU type based features
+    - fbdev: Improve performance of sys_imageblit()
+    - fbdev: Fix sys_imageblit() for arbitrary image widths
+    - fbdev: fix potential OOB read in fast_imageblit()
+    - dm integrity: increase RECALC_SECTORS to improve recalculate speed
+    - dm integrity: reduce vmalloc space footprint on 32-bit architectures
+    - ALSA: pcm: Set per-card upper limit of PCM buffer allocations
+    - ALSA: pcm: Use SG-buffer only when direct DMA is available
+    - ALSA: pcm: Fix potential data race at PCM memory allocation helpers
+    - regmap: Account for register length in SMBus I/O limits
+    - ASoC: fsl_sai: Refine enable/disable TE/RE sequence in trigger()
+    - ASoC: fsl_sai: Add new added registers and new bit definition
+    - ASoC: fsl_sai: Disable bit clock with transmitter
+    - drm/amd/display: do not wait for mpc idle if tg is disabled
+    - drm/amd/display: check TG is non-null before checking if enabled
+    - tracing: Fix memleak due to race between current_tracer and trace
+    - octeontx2-af: SDP: fix receive link config
+    - sock: annotate data-races around prot->memory_pressure
+    - dccp: annotate data-races in dccp_poll()
+    - ipvlan: Fix a reference count leak warning in ipvlan_ns_exit()
+    - net: bgmac: Fix return value check for fixed_phy_register()
+    - net: bcmgenet: Fix return value check for fixed_phy_register()
+    - net: validate veth and vxcan peer ifindexes
+    - igb: Avoid starting unnecessary workqueues
+    - net/sched: fix a qdisc modification with ambiguous command request
+    - net: remove bond_slave_has_mac_rcu()
+    - bonding: fix macvlan over alb bond support
+    - ibmveth: Use dcbf rather than dcbfl
+    - NFSv4: Fix dropped lock for racing OPEN and delegation return
+    - clk: Fix slab-out-of-bounds error in devm_clk_release()
+    - nfsd: Fix race to FREE_STATEID and cl_revoked
+    - batman-adv: Trigger events for auto adjusted MTU
+    - batman-adv: Don't increase MTU when set by user
+    - batman-adv: Do not get eth header before batadv_check_management_packet
+    - batman-adv: Fix TT global entry leak when client roamed back
+    - batman-adv: Fix batadv_v_ogm_aggr_send memory leak
+    - batman-adv: Hold rtnl lock during MTU update via netlink
+    - lib/clz_ctz.c: Fix __clzdi2() and __ctzdi2() for 32-bit kernels
+    - radix tree: remove unused variable
+    - media: vcodec: Fix potential array out-of-bounds in encoder queue_setup
+    - PCI: acpiphp: Use pci_assign_unassigned_bridge_resources() only for non-root
+      bus
+    - drm/display/dp: Fix the DP DSC Receiver cap size
+    - mm: allow a controlled amount of unfairness in the page lock
+    - rtnetlink: Reject negative ifindexes in RTM_NEWLINK
+    - ALSA: pcm: Fix build error on m68k and others
+    - Revert "ALSA: pcm: Use SG-buffer only when direct DMA is available"
+    - interconnect: Do not skip aggregation for disabled paths
+    - ALSA: pcm: Check for null pointer of pointer substream before dereferencing
+      it
+    - Documentation/sysctl: document page_lock_unfairness
+    - irqchip/mips-gic: Don't touch vl_map if a local interrupt is not routable
+    - scsi: snic: Fix double free in snic_tgt_create()
+    - scsi: core: raid_class: Remove raid_component_add()
+    - clk: Fix undefined reference to `clk_rate_exclusive_{get,put}'
+    - pinctrl: renesas: rza2: Add lock around
+      pinctrl_generic{{add,remove}_group,{add,remove}_function}
+    - dma-buf/sw_sync: Avoid recursive lock during fence signal
+    - Linux 5.4.255
+  * Focal update: v5.4.254 upstream stable release (LP: #2039291)
+    - mmc: moxart: read scr register without changing byte order
+    - ipv6: adjust ndisc_is_useropt() to also return true for PIO
+    - dmaengine: pl330: Return DMA_PAUSED when transaction is paused
+    - drm/nouveau/gr: enable memory loads on helper invocation on all channels
+    - radix tree test suite: fix incorrect allocation size for pthreads
+    - nilfs2: fix use-after-free of nilfs_root in dirtying inodes via iput
+    - iio: cros_ec: Fix the allocation size for cros_ec_command
+    - binder: fix memory leak in binder_init()
+    - usb-storage: alauda: Fix uninit-value in alauda_check_media()
+    - usb: dwc3: Properly handle processing of pending events
+    - usb: common: usb-conn-gpio: Prevent bailing out if initial role is none
+    - x86/cpu/amd: Enable Zenbleed fix for AMD Custom APU 0405
+    - x86/mm: Fix VDSO and VVAR placement on 5-level paging machines
+    - x86: Move gds_ucode_mitigated() declaration to header
+    - drm/nouveau/disp: Revert a NULL check inside nouveau_connector_get_modes
+    - selftests/rseq: Fix build with undefined __weak
+    - mISDN: Update parameter type of dsp_cmx_send()
+    - net/packet: annotate data-races around tp->status
+    - bonding: Fix incorrect deletion of ETH_P_8021AD protocol vid from slaves
+    - dccp: fix data-race around dp->dccps_mss_cache
+    - drivers: net: prevent tun_build_skb() to exceed the packet size limit
+    - IB/hfi1: Fix possible panic during hotplug remove
+    - wifi: cfg80211: fix sband iftype data lookup for AP_VLAN
+    - dmaengine: mcf-edma: Fix a potential un-allocated memory access
+    - net/mlx5: Allow 0 for total host VFs
+    - ibmvnic: Handle DMA unmapping of login buffs in release functions
+    - btrfs: don't stop integrity writeback too early
+    - btrfs: set cache_block_group_error if we find an error
+    - nvme-tcp: fix potential unbalanced freeze & unfreeze
+    - nvme-rdma: fix potential unbalanced freeze & unfreeze
+    - netfilter: nf_tables: report use refcount overflow
+    - scsi: core: Fix legacy /proc parsing buffer overflow
+    - scsi: storvsc: Fix handling of virtual Fibre Channel timeouts
+    - scsi: 53c700: Check that command slot is not NULL
+    - scsi: snic: Fix possible memory leak if device_add() fails
+    - scsi: core: Fix possible memory leak if device_add() fails
+    - alpha: remove __init annotation from exported page_is_ram()
+    - sch_netem: fix issues in netem_change() vs get_dist_table()
+    - Linux 5.4.254
+  * Focal update: v5.4.253 upstream stable release (LP: #2038652)
+    - jbd2: fix incorrect code style
+    - jbd2: fix kernel-doc markups
+    - jbd2: remove redundant buffer io error checks
+    - jbd2: recheck chechpointing non-dirty buffer
+    - jbd2: Fix wrongly judgement for buffer head removing while doing checkpoint
+    - gpio: tps68470: Make tps68470_gpio_output() always set the initial value
+    - bcache: remove 'int n' from parameter list of bch_bucket_alloc_set()
+    - bcache: Fix __bch_btree_node_alloc to make the failure behavior consistent
+    - btrfs: qgroup: catch reserved space leaks at unmount time
+    - btrfs: fix race between quota disable and relocation
+    - btrfs: fix extent buffer leak after tree mod log failure at split_node()
+    - ext4: rename journal_dev to s_journal_dev inside ext4_sb_info
+    - ext4: Fix reusing stale buffer heads from last failed mounting
+    - PCI/ASPM: Return 0 or -ETIMEDOUT from pcie_retrain_link()
+    - PCI/ASPM: Factor out pcie_wait_for_retrain()
+    - PCI/ASPM: Avoid link retraining race
+    - dlm: cleanup plock_op vs plock_xop
+    - dlm: rearrange async condition return
+    - fs: dlm: interrupt posix locks only when process is killed
+    - ftrace: Add information on number of page groups allocated
+    - ftrace: Check if pages were allocated before calling free_pages()
+    - ftrace: Store the order of pages allocated in ftrace_page
+    - ftrace: Fix possible warning on checking all pages used in
+      ftrace_process_locs()
+    - pwm: meson: Remove redundant assignment to variable fin_freq
+    - pwm: meson: Simplify duplicated per-channel tracking
+    - pwm: meson: fix handling of period/duty if greater than UINT_MAX
+    - scsi: qla2xxx: Fix inconsistent format argument type in qla_os.c
+    - scsi: qla2xxx: Array index may go out of bound
+    - uapi: General notification queue definitions
+    - keys: Fix linking a duplicate key to a keyring's assoc_array
+    - ext4: fix to check return value of freeze_bdev() in ext4_shutdown()
+    - i40e: Fix an NULL vs IS_ERR() bug for debugfs_create_dir()
+    - vxlan: calculate correct header length for GPE
+    - phy: hisilicon: Fix an out of bounds check in hisi_inno_phy_probe()
+    - ethernet: atheros: fix return value check in atl1e_tso_csum()
+    - ipv6 addrconf: fix bug where deleting a mngtmpaddr can create a new
+      temporary address
+    - bonding: reset bond's flags when down link is P2P device
+    - team: reset team's flags when down link is P2P device
+    - platform/x86: msi-laptop: Fix rfkill out-of-sync on MSI Wind U100
+    - net/sched: mqprio: refactor nlattr parsing to a separate function
+    - net/sched: mqprio: add extack to mqprio_parse_nlattr()
+    - net/sched: mqprio: Add length check for TCA_MQPRIO_{MAX/MIN}_RATE64
+    - benet: fix return value check in be_lancer_xmit_workarounds()
+    - RDMA/mlx4: Make check for invalid flags stricter
+    - drm/msm/dpu: drop enum dpu_core_perf_data_bus_id
+    - drm/msm/adreno: Fix snapshot BINDLESS_DATA size
+    - drm/msm: Fix IS_ERR_OR_NULL() vs NULL check in a5xx_submit_in_rb()
+    - ASoC: fsl_spdif: Silence output on stop
+    - block: Fix a source code comment in include/uapi/linux/blkzoned.h
+    - dm raid: fix missing reconfig_mutex unlock in raid_ctr() error paths
+    - ata: pata_ns87415: mark ns87560_tf_read static
+    - ring-buffer: Fix wrong stat of cpu_buffer->read
+    - tracing: Fix warning in trace_buffered_event_disable()
+    - serial: 8250_dw: Preserve original value of DLF register
+    - serial: sifive: Fix sifive_serial_console_setup() section
+    - USB: serial: option: support Quectel EM060K_128
+    - USB: serial: option: add Quectel EC200A module support
+    - USB: serial: simple: add Kaufmann RKS+CAN VCP
+    - USB: serial: simple: sort driver entries
+    - can: gs_usb: gs_can_close(): add missing set of CAN state to
+      CAN_STATE_STOPPED
+    - Revert "usb: dwc3: core: Enable AutoRetry feature in the controller"
+    - usb: dwc3: pci: skip BYT GPIO lookup table for hardwired phy
+    - usb: dwc3: don't reset device side if dwc3 was configured as host-only
+    - usb: ohci-at91: Fix the unhandle interrupt when resume
+    - USB: quirks: add quirk for Focusrite Scarlett
+    - usb: xhci-mtk: set the dma max_seg_size
+    - Revert "usb: xhci: tegra: Fix error check"
+    - Documentation: security-bugs.rst: update preferences when dealing with the
+      linux-distros group
+    - Documentation: security-bugs.rst: clarify CVE handling
+    - staging: ks7010: potential buffer overflow in ks_wlan_set_encode_ext()
+    - hwmon: (nct7802) Fix for temp6 (PECI1) processed even if PECI1 disabled
+    - btrfs: check for commit error at btrfs_attach_transaction_barrier()
+    - tpm_tis: Explicitly check for error code
+    - irq-bcm6345-l1: Do not assume a fixed block to cpu mapping
+    - btrfs: check if the transaction was aborted at btrfs_wait_for_commit()
+    - virtio-net: fix race between set queues and probe
+    - s390/dasd: fix hanging device after quiesce/resume
+    - ASoC: wm8904: Fill the cache for WM8904_ADC_TEST_0 register
+    - dm cache policy smq: ensure IO doesn't prevent cleaner policy progress
+    - ACPI: processor: perflib: Use the "no limit" frequency QoS
+    - ACPI: processor: perflib: Avoid updating frequency QoS unnecessarily
+    - cpufreq: intel_pstate: Drop ACPI _PSS states table patching
+    - btrfs: qgroup: remove one-time use variables for quota_root checks
+    - btrfs: qgroup: return ENOTCONN instead of EINVAL when quotas are not enabled
+    - ASoC: cs42l51: fix driver to properly autoload with automatic module loading
+    - arm64: Add AMPERE1 to the Spectre-BHB affected list
+    - arm64: Fix bit-shifting UB in the MIDR_CPU_MODEL() macro
+    - perf: Fix function pointer case
+    - loop: Select I/O scheduler 'none' from inside add_disk()
+    - word-at-a-time: use the same return type for has_zero regardless of
+      endianness
+    - KVM: s390: fix sthyi error handling
+    - net/mlx5: DR, fix memory leak in mlx5dr_cmd_create_reformat_ctx
+    - net/mlx5e: fix return value check in mlx5e_ipsec_remove_trailer()
+    - rtnetlink: let rtnl_bridge_setlink checks IFLA_BRIDGE_MODE length
+    - perf test uprobe_from_different_cu: Skip if there is no gcc
+    - net: sched: cls_u32: Fix match key mis-addressing
+    - mISDN: hfcpci: Fix potential deadlock on &hc->lock
+    - net: annotate data-races around sk->sk_max_pacing_rate
+    - net: add missing READ_ONCE(sk->sk_rcvlowat) annotation
+    - net: add missing READ_ONCE(sk->sk_sndbuf) annotation
+    - net: add missing READ_ONCE(sk->sk_rcvbuf) annotation
+    - net: add missing data-race annotations around sk->sk_peek_off
+    - net: add missing data-race annotation for sk_ll_usec
+    - bpf: sockmap: Remove preempt_disable in sock_map_sk_acquire
+    - driver core: add device probe log helper
+    - net: ll_temac: Switch to use dev_err_probe() helper
+    - net: ll_temac: fix error checking of irq_of_parse_and_map()
+    - net: dcb: choose correct policy to parse DCB_ATTR_BCN
+    - ip6mr: Fix skb_under_panic in ip6mr_cache_report()
+    - tcp_metrics: fix addr_same() helper
+    - tcp_metrics: annotate data-races around tm->tcpm_stamp
+    - tcp_metrics: annotate data-races around tm->tcpm_lock
+    - tcp_metrics: annotate data-races around tm->tcpm_vals[]
+    - tcp_metrics: annotate data-races around tm->tcpm_net
+    - tcp_metrics: fix data-race in tcpm_suck_dst() vs fastopen
+    - scsi: zfcp: Defer fc_rport blocking until after ADISC response
+    - libceph: fix potential hang in ceph_osdc_notify()
+    - USB: zaurus: Add ID for A-300/B-500/C-700
+    - mtd: spinand: toshiba: Fix ecc_get_status
+    - mtd: rawnand: meson: fix OOB available bytes for ECC
+    - fs/sysv: Null check to prevent null-ptr-deref bug
+    - net: usbnet: Fix WARNING in usbnet_start_xmit/usb_submit_urb
+    - fs: Protect reconfiguration of sb read-write from racing writes
+    - ext2: Drop fragment support
+    - test_firmware: prevent race conditions by a correct implementation of
+      locking
+    - test_firmware: return ENOMEM instead of ENOSPC on failed memory allocation
+    - mtd: rawnand: omap_elm: Fix incorrect type in assignment
+    - powerpc/mm/altmap: Fix altmap boundary check
+    - selftests/rseq: check if libc rseq support is registered
+    - selftests/rseq: Play nice with binaries statically linked against glibc
+      2.35+
+    - PM / wakeirq: support enabling wake-up irq after runtime_suspend called
+    - PM: sleep: wakeirq: fix wake irq arming
+    - ceph: show tasks waiting on caps in debugfs caps file
+    - ceph: use kill_anon_super helper
+    - ceph: defer stopping mdsc delayed_work
+    - arm64: dts: stratix10: fix incorrect I2C property for SCL signal
+    - ARM: dts: imx6sll: Make ssi node name same as other platforms
+    - ARM: dts: imx: Align L2 cache-controller nodename with dtschema
+    - ARM: dts: imx: add usb alias
+    - ARM: dts: imx6sll: fixup of operating points
+    - ARM: dts: nxp/imx6sll: fix wrong property name in usbphy node
+    - driver core: Annotate dev_err_probe() with __must_check
+    - driver code: print symbolic error code
+    - drivers: core: fix kernel-doc markup for dev_err_probe()
+    - Revert "driver core: Annotate dev_err_probe() with __must_check"
+    - Linux 5.4.253
+    - Upstream stable to v5.4.253
+  * CVE-2023-37453
+    - USB: hub: Clean up use of port initialization schemes and retries
+    - USB: hub: Add Kconfig option to reduce number of port initialization retries
+    - USB: core: Unite old scheme and new scheme descriptor reads
+    - usb: hub: Check device descriptor before resusciation
+    - USB: core: Change usb_get_device_descriptor() API
+    - USB: core: Fix race by not overwriting udev->descriptor in hub_port_init()
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update helper scripts
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Mon, 27 Nov 2023 10:09:20 +1000
+
+linux-xilinx-zynqmp (5.4.0-1034.38) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1034.38 -proposed tracker (LP: #2041986)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync git-ubuntu-log
+    - [Packaging] resync update-dkms-versions helper
+
+  [ Ubuntu: 5.4.0-167.184 ]
+
+  * focal/linux: 5.4.0-167.184 -proposed tracker (LP: #2041988)
+  * CVE-2023-45871
+    - igb: set max size RX buffer when store bad packet is enabled
+  * CVE-2023-31085
+    - ubi: Refuse attaching if mtd's erasesize is 0
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update helper scripts
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Fri, 10 Nov 2023 10:50:11 +1000
+
+linux-xilinx-zynqmp (5.4.0-1033.37) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1033.37 -proposed tracker (LP: #2038008)
+
+  * Use new annotations model (LP: #2019000)
+    - [Config] migrate all configs into annotations
+
+  [ Ubuntu: 5.4.0-166.183 ]
+
+  * focal/linux: 5.4.0-166.183 -proposed tracker (LP: #2038010)
+  * Use new annotations model (LP: #2019000)
+    - [Packaging] new annotations model infrastructure
+    - [Packaging] config-check: Handle new annotations format 4
+    - [Packaging] rules: Use old-kernelconfig for old configs
+    - [Config] sanitize annotations
+    - [Config] import generated configs into annotation file
+    - [Packaging] kernelconfig: add i386 as supported arch
+    - [Config] Remove all old configs files
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update helper scripts
+    - [Packaging] update annotations scripts
+  * fix typo in config-checks invocation (LP: #2020413)
+    - [Packaging] fix typo when calling the old config-check
+    - [Packaging] fix typo in 4-checks.mk
+  * support python < 3.9 with annotations (LP: #2020531)
+    - [Packaging] kconfig/annotations.py: support older way of merging dicts
+  * CVE-2023-42756
+    - netfilter: ipset: Fix race between IPSET_CMD_CREATE and IPSET_CMD_SWAP
+  * CVE-2023-4623
+    - net/sched: sch_hfsc: Ensure inner classes have fsc curve
+  * Focal update: v5.4.252 upstream stable release (LP: #2036240)
+    - ia64/cpu: Switch to arch_cpu_finalize_init()
+    - m68k/cpu: Switch to arch_cpu_finalize_init()
+    - mips/cpu: Switch to arch_cpu_finalize_init()
+    - sh/cpu: Switch to arch_cpu_finalize_init()
+    - x86/cpufeatures: Add SEV-ES CPU feature
+    - x86/cpu: Add VM page flush MSR availablility as a CPUID feature
+    - x86/cpufeatures: Assign dedicated feature word for CPUID_0x8000001F[EAX]
+    - tools headers cpufeatures: Sync with the kernel sources
+    - x86/cpu, kvm: Add support for CPUID_80000021_EAX
+    - Linux 5.4.252
+    - Upstream stable to v5.4.252
+  * CVE-2023-42755
+    - net/sched: Retire rsvp classifier
+    - [Config] remove NET_CLS_RSVP and NET_CLS_RSVP6
+  * CVE-2023-42753
+    - netfilter: ipset: add the missing IP_SET_HASH_WITH_NET0 macro for
+      ip_set_hash_netportnet.c
+  * CVE-2023-34319
+    - xen/netback: Fix buffer overrun triggered by unusual packet
+  * CVE-2023-4921
+    - net: sched: sch_qfq: Fix UAF in qfq_dequeue()
+  * CVE-2023-42752
+    - igmp: limit igmpv3_newpack() packet size to IP_MAX_MTU
+  * Avoid address overwrite in kernel_connect (LP: #2035163)
+    - net: Avoid address overwrite in kernel_connect
+  * [regression] Unable to initialize SGX enclaves with XFRM other than 3
+    (LP: #2034745)
+    - x86/fpu: Set X86_FEATURE_OSXSAVE feature after enabling OSXSAVE in CR4
+  * CVE-2023-4881
+    - netfilter: nftables: exthdr: fix 4-byte stack OOB write
+  * CVE-2023-4622
+    - af_unix: Fix null-ptr-deref in unix_stream_sendpage().
+  * Focal update: v5.4.251 upstream stable release (LP: #2034918)
+    - x86/smp: Use dedicated cache-line for mwait_play_dead()
+    - video: imsttfb: check for ioremap() failures
+    - fbdev: imsttfb: Fix use after free bug in imsttfb_probe
+    - HID: wacom: Use ktime_t rather than int when dealing with timestamps
+    - drm/i915: Initialise outparam for error return from wait_for_register
+    - scripts/tags.sh: Resolve gtags empty index generation
+    - drm/amdgpu: Validate VM ioctl flags.
+    - bgmac: fix *initial* chip reset to support BCM5358
+    - x86/resctrl: Use is_closid_match() in more places
+    - x86/resctrl: Only show tasks' pid in current pid namespace
+    - md/raid10: check slab-out-of-bounds in md_bitmap_get_counter
+    - md/raid10: fix overflow of md/safe_mode_delay
+    - md/raid10: fix wrong setting of max_corr_read_errors
+    - md/raid10: fix null-ptr-deref of mreplace in raid10_sync_request
+    - md/raid10: fix io loss while replacement replace rdev
+    - irqchip/jcore-aic: Kill use of irq_create_strict_mappings()
+    - irqchip/jcore-aic: Fix missing allocation of IRQ descriptors
+    - tracing/timer: Add missing hrtimer modes to decode_hrtimer_mode().
+    - clocksource/drivers/cadence-ttc: Use ttc driver as platform driver
+    - clocksource/drivers/cadence-ttc: Fix memory leak in ttc_timer_probe
+    - PM: domains: fix integer overflow issues in genpd_parse_state()
+    - powercap: RAPL: Fix CONFIG_IOSF_MBI dependency
+    - ARM: 9303/1: kprobes: avoid missing-declaration warnings
+    - evm: Complete description of evm_inode_setattr()
+    - pstore/ram: Add check for kstrdup
+    - ima: Fix build warnings
+    - wifi: ath9k: fix AR9003 mac hardware hang check register offset calculation
+    - wifi: ath9k: avoid referencing uninit memory in ath9k_wmi_ctrl_rx
+    - samples/bpf: Fix buffer overflow in tcp_basertt
+    - spi: spi-geni-qcom: Correct CS_TOGGLE bit in SPI_TRANS_CFG
+    - wifi: mwifiex: Fix the size of a memory allocation in
+      mwifiex_ret_802_11_scan()
+    - nfc: constify several pointers to u8, char and sk_buff
+    - nfc: llcp: fix possible use of uninitialized variable in
+      nfc_llcp_send_connect()
+    - regulator: core: Fix more error checking for debugfs_create_dir()
+    - regulator: core: Streamline debugfs operations
+    - wifi: orinoco: Fix an error handling path in spectrum_cs_probe()
+    - wifi: orinoco: Fix an error handling path in orinoco_cs_probe()
+    - wifi: atmel: Fix an error handling path in atmel_probe()
+    - wl3501_cs: Fix a bunch of formatting issues related to function docs
+    - wl3501_cs: Remove unnecessary NULL check
+    - wl3501_cs: Fix misspelling and provide missing documentation
+    - net: create netdev->dev_addr assignment helpers
+    - wl3501_cs: use eth_hw_addr_set()
+    - wifi: wl3501_cs: Fix an error handling path in wl3501_probe()
+    - wifi: ray_cs: Utilize strnlen() in parse_addr()
+    - wifi: ray_cs: Drop useless status variable in parse_addr()
+    - wifi: ray_cs: Fix an error handling path in ray_probe()
+    - wifi: ath9k: don't allow to overwrite ENDPOINT0 attributes
+    - wifi: rsi: Do not set MMC_PM_KEEP_POWER in shutdown
+    - watchdog/perf: define dummy watchdog_update_hrtimer_threshold() on correct
+      config
+    - watchdog/perf: more properly prevent false positives with turbo modes
+    - kexec: fix a memory leak in crash_shrink_memory()
+    - memstick r592: make memstick_debug_get_tpc_name() static
+    - wifi: ath9k: Fix possible stall on ath9k_txq_list_has_key()
+    - rtnetlink: extend RTEXT_FILTER_SKIP_STATS to IFLA_VF_INFO
+    - wifi: iwlwifi: pull from TXQs with softirqs disabled
+    - wifi: cfg80211: rewrite merging of inherited elements
+    - wifi: ath9k: convert msecs to jiffies where needed
+    - netlink: fix potential deadlock in netlink_set_err()
+    - netlink: do not hard code device address lenth in fdb dumps
+    - selftests: rtnetlink: remove netdevsim device after ipsec offload test
+    - gtp: Fix use-after-free in __gtp_encap_destroy().
+    - lib/ts_bm: reset initial match offset for every block of text
+    - netfilter: conntrack: dccp: copy entire header to stack buffer, not just
+      basic one
+    - netfilter: nf_conntrack_sip: fix the ct_sip_parse_numerical_param() return
+      value.
+    - ipvlan: Fix return value of ipvlan_queue_xmit()
+    - netlink: Add __sock_i_ino() for __netlink_diag_dump().
+    - radeon: avoid double free in ci_dpm_init()
+    - Input: drv260x - sleep between polling GO bit
+    - ARM: dts: BCM5301X: Drop "clock-names" from the SPI node
+    - Input: adxl34x - do not hardcode interrupt trigger type
+    - drm: sun4i_tcon: use devm_clk_get_enabled in `sun4i_tcon_init_clocks`
+    - RDMA/bnxt_re: Fix to remove an unnecessary log
+    - ARM: dts: gta04: Move model property out of pinctrl node
+    - arm64: dts: qcom: msm8916: correct camss unit address
+    - drm/panel: simple: fix active size for Ampire AM-480272H3TMQW-T01H
+    - ARM: ep93xx: fix missing-prototype warnings
+    - memory: brcmstb_dpfe: fix testing array offset after use
+    - ASoC: es8316: Increment max value for ALC Capture Target Volume control
+    - ASoC: es8316: Do not set rate constraints for unsupported MCLKs
+    - soc/fsl/qe: fix usb.c build errors
+    - IB/hfi1: Fix sdma.h tx->num_descs off-by-one errors
+    - arm64: dts: renesas: ulcb-kf: Remove flow control for SCIF1
+    - fbdev: omapfb: lcd_mipid: Fix an error handling path in mipid_spi_probe()
+    - drm/amdkfd: Fix potential deallocation of previously deallocated memory.
+    - drm/radeon: fix possible division-by-zero errors
+    - clk: tegra: tegra124-emc: Fix potential memory leak
+    - ALSA: ac97: Fix possible NULL dereference in snd_ac97_mixer
+    - clk: cdce925: check return value of kasprintf()
+    - clk: keystone: sci-clk: check return value of kasprintf()
+    - ASoC: imx-audmix: check return value of devm_kasprintf()
+    - scsi: qedf: Fix NULL dereference in error handling
+    - PCI/ASPM: Disable ASPM on MFD function removal to avoid use-after-free
+    - scsi: 3w-xxxx: Add error handling for initialization failure in tw_probe()
+    - PCI: pciehp: Cancel bringup sequence if card is not present
+    - PCI: ftpci100: Release the clock resources
+    - PCI: Add pci_clear_master() stub for non-CONFIG_PCI
+    - pinctrl: cherryview: Return correct value if pin in push-pull mode
+    - perf dwarf-aux: Fix off-by-one in die_get_varname()
+    - pinctrl: at91-pio4: check return value of devm_kasprintf()
+    - powerpc/mm/dax: Fix the condition when checking if altmap vmemap can cross-
+      boundary
+    - hwrng: virtio - add an internal buffer
+    - hwrng: virtio - don't wait on cleanup
+    - hwrng: virtio - don't waste entropy
+    - hwrng: virtio - always add a pending request
+    - hwrng: virtio - Fix race on data_avail and actual data
+    - crypto: nx - fix build warnings when DEBUG_FS is not enabled
+    - modpost: fix section mismatch message for R_ARM_ABS32
+    - modpost: fix section mismatch message for R_ARM_{PC24,CALL,JUMP24}
+    - crypto: marvell/cesa - Fix type mismatch warning
+    - modpost: fix off by one in is_executable_section()
+    - ARC: define ASM_NL and __ALIGN(_STR) outside #ifdef __ASSEMBLY__ guard
+    - NFSv4.1: freeze the session table upon receiving NFS4ERR_BADSESSION
+    - hwrng: st - Fix W=1 unused variable warning
+    - hwrng: st - keep clock enabled while hwrng is registered
+    - USB: serial: option: add LARA-R6 01B PIDs
+    - usb: dwc3: gadget: Propagate core init errors to UDC during pullup
+    - block: fix signed int overflow in Amiga partition support
+    - block: change all __u32 annotations to __be32 in affs_hardblocks.h
+    - w1: fix loop in w1_fini()
+    - sh: j2: Use ioremap() to translate device tree address into kernel memory
+    - media: usb: Check az6007_read() return value
+    - media: videodev2.h: Fix struct v4l2_input tuner index comment
+    - usb: dwc3: qcom: Fix potential memory leak
+    - extcon: Fix kernel doc of property fields to avoid warnings
+    - extcon: Fix kernel doc of property capability fields to avoid warnings
+    - usb: phy: phy-tahvo: fix memory leak in tahvo_usb_probe()
+    - usb: hide unused usbfs_notify_suspend/resume functions
+    - mfd: rt5033: Drop rt5033-battery sub-device
+    - KVM: s390: fix KVM_S390_GET_CMMA_BITS for GFNs in memslot holes
+    - usb: dwc3: qcom: Release the correct resources in dwc3_qcom_remove()
+    - mfd: intel-lpss: Add missing check for platform_get_resource
+    - serial: 8250_omap: Use force_suspend and resume for system suspend
+    - mfd: stmfx: Fix error path in stmfx_chip_init
+    - KVM: s390: vsie: fix the length of APCB bitmap
+    - mfd: stmpe: Only disable the regulators if they are enabled
+    - pwm: imx-tpm: force 'real_period' to be zero in suspend
+    - pwm: sysfs: Do not apply state to already disabled PWMs
+    - rtc: st-lpc: Release some resources in st_rtc_probe() in case of error
+    - sctp: fix potential deadlock on &net->sctp.addr_wq_lock
+    - Add MODULE_FIRMWARE() for FIRMWARE_TG357766.
+    - spi: bcm-qspi: return error if neither hif_mspi nor mspi is available
+    - mailbox: ti-msgmgr: Fill non-message tx data fields with 0x0
+    - f2fs: fix error path handling in truncate_dnode()
+    - powerpc: allow PPC_EARLY_DEBUG_CPM only when SERIAL_CPM=y
+    - net: bridge: keep ports without IFF_UNICAST_FLT in BR_PROMISC mode
+    - tcp: annotate data races in __tcp_oow_rate_limited()
+    - xsk: Improve documentation for AF_XDP
+    - xsk: Honor SO_BINDTODEVICE on bind
+    - net/sched: act_pedit: Add size check for TCA_PEDIT_PARMS_EX
+    - net: dsa: tag_sja1105: fix MAC DA patching from meta frames
+    - sh: dma: Fix DMA channel offset calculation
+    - i2c: xiic: Defer xiic_wakeup() and __xiic_start_xfer() in xiic_process()
+    - i2c: xiic: Don't try to handle more interrupt events after error
+    - ALSA: jack: Fix mutex call in snd_jack_report()
+    - NFSD: add encoding of op_recall flag for write delegation
+    - mmc: core: disable TRIM on Kingston EMMC04G-M627
+    - mmc: core: disable TRIM on Micron MTFC4GACAJCN-1M
+    - mmc: sdhci: fix DMA configure compatibility issue when 64bit DMA mode is
+      used.
+    - bcache: Remove unnecessary NULL point check in node allocations
+    - integrity: Fix possible multiple allocation in integrity_inode_get()
+    - jffs2: reduce stack usage in jffs2_build_xattr_subsystem()
+    - fs: avoid empty option when generating legacy mount string
+    - ext4: Remove ext4 locking of moved directory
+    - Revert "f2fs: fix potential corruption when moving a directory"
+    - fs: Establish locking order for unrelated directories
+    - fs: Lock moved directories
+    - btrfs: fix race when deleting quota root from the dirty cow roots list
+    - ARM: orion5x: fix d2net gpio initialization
+    - fs: no need to check source
+    - fanotify: disallow mount/sb marks on kernel internal pseudo fs
+    - block: add overflow checks for Amiga partition support
+    - netfilter: nf_tables: fix nat hook table deletion
+    - netfilter: nftables: add helper function to set the base sequence number
+    - netfilter: add helper function to set up the nfnetlink header and use it
+    - netfilter: nf_tables: use net_generic infra for transaction data
+    - netfilter: nf_tables: add rescheduling points during loop detection walks
+    - netfilter: nf_tables: add NFT_TRANS_PREPARE_ERROR to deal with bound
+      set/chain
+    - netfilter: nf_tables: reject unbound anonymous set before commit phase
+    - netfilter: nf_tables: unbind non-anonymous set if rule construction fails
+    - netfilter: nf_tables: fix scheduling-while-atomic splat
+    - netfilter: conntrack: Avoid nf_ct_helper_hash uses after free
+    - tty: serial: fsl_lpuart: add earlycon for imx8ulp platform
+    - block/partition: fix signedness issue for Amiga partitions
+    - net: lan743x: Don't sleep in atomic context
+    - workqueue: clean up WORK_* constant types, clarify masking
+    - drm/panel: Initialise panel dev and funcs through drm_panel_init()
+    - drm/panel: Add and fill drm_panel type field
+    - drm/panel: simple: Add connector_type for innolux_at043tn24
+    - igc: Remove delay during TX ring configuration
+    - igc: set TP bit in 'supported' and 'advertising' fields of
+      ethtool_link_ksettings
+    - scsi: qla2xxx: Fix error code in qla2x00_start_sp()
+    - net: mvneta: fix txq_map in case of txq_number==1
+    - ionic: improve irq numa locality
+    - ionic: clean irq affinity on queue deinit
+    - ionic: move irq request to qcq alloc
+    - ionic: ionic_intr_free parameter change
+    - ionic: remove WARN_ON to prevent panic_on_warn
+    - icmp6: Fix null-ptr-deref of ip6_null_entry->rt6i_idev in icmp6_dev().
+    - udp6: fix udp6_ehashfn() typo
+    - ntb: idt: Fix error handling in idt_pci_driver_init()
+    - NTB: amd: Fix error handling in amd_ntb_pci_driver_init()
+    - ntb: intel: Fix error handling in intel_ntb_pci_driver_init()
+    - NTB: ntb_transport: fix possible memory leak while device_register() fails
+    - NTB: ntb_tool: Add check for devm_kcalloc
+    - ipv6/addrconf: fix a potential refcount underflow for idev
+    - platform/x86: wmi: Replace UUID redefinitions by their originals
+    - platform/x86: wmi: Fix indentation in some cases
+    - platform/x86: wmi: remove unnecessary argument
+    - platform/x86: wmi: use guid_t and guid_equal()
+    - platform/x86: wmi: move variables
+    - platform/x86: wmi: Break possible infinite loop when parsing GUID
+    - erofs: avoid infinite loop in z_erofs_do_read_page() when reading beyond EOF
+    - wifi: airo: avoid uninitialized warning in airo_get_rate()
+    - cls_flower: Add extack support for src and dst port range options
+    - net/sched: flower: Ensure both minimum and maximum ports are specified
+    - net/sched: make psched_mtu() RTNL-less safe
+    - pinctrl: amd: Fix mistake in handling clearing pins at startup
+    - pinctrl: amd: Detect internal GPIO0 debounce handling
+    - pinctrl: amd: Only use special debounce behavior for GPIO 0
+    - tpm: tpm_vtpm_proxy: fix a race condition in /dev/vtpmx creation
+    - mtd: rawnand: meson: fix unaligned DMA buffers handling
+    - net: bcmgenet: Ensure MDIO unregistration has clocks enabled
+    - powerpc: Fail build if using recordmcount with binutils v2.37
+    - misc: fastrpc: Create fastrpc scalar with correct buffer count
+    - SUNRPC: Fix UAF in svc_tcp_listen_data_ready()
+    - erofs: fix compact 4B support for 16k block size
+    - ext4: fix wrong unit use in ext4_mb_clear_bb
+    - ext4: only update i_reserved_data_blocks on successful block allocation
+    - jfs: jfs_dmap: Validate db_l2nbperpage while mounting
+    - PCI/PM: Avoid putting EloPOS E2/S2/H2 PCIe Ports in D3cold
+    - PCI: Add function 1 DMA alias quirk for Marvell 88SE9235
+    - PCI: qcom: Disable write access to read only registers for IP v2.3.3
+    - PCI: rockchip: Assert PCI Configuration Enable bit after probe
+    - PCI: rockchip: Write PCI Device ID to correct register
+    - PCI: rockchip: Add poll and timeout to wait for PHY PLLs to be locked
+    - PCI: rockchip: Fix legacy IRQ generation for RK3399 PCIe endpoint core
+    - PCI: rockchip: Use u32 variable to access 32-bit registers
+    - PCI: rockchip: Set address alignment for endpoint mode
+    - misc: pci_endpoint_test: Free IRQs before removing the device
+    - misc: pci_endpoint_test: Re-init completion for every test
+    - md/raid0: add discard support for the 'original' layout
+    - fs: dlm: return positive pid value for F_GETLK
+    - drm/atomic: Allow vblank-enabled + self-refresh "disable"
+    - drm/rockchip: vop: Leave vblank enabled in self-refresh
+    - serial: atmel: don't enable IRQs prematurely
+    - firmware: stratix10-svc: Fix a potential resource leak in
+      svc_create_memory_pool()
+    - hwrng: imx-rngc - fix the timeout for init and self check
+    - ceph: don't let check_caps skip sending responses for revoke msgs
+    - meson saradc: fix clock divider mask length
+    - Revert "8250: add support for ASIX devices with a FIFO bug"
+    - tty: serial: samsung_tty: Fix a memory leak in s3c24xx_serial_getclk() in
+      case of error
+    - tty: serial: samsung_tty: Fix a memory leak in s3c24xx_serial_getclk() when
+      iterating clk
+    - tracing/histograms: Add histograms to hist_vars if they have referenced
+      variables
+    - ring-buffer: Fix deadloop issue on reading trace_pipe
+    - xtensa: ISS: fix call to split_if_spec
+    - tracing: Fix null pointer dereference in tracing_err_log_open()
+    - tracing/probes: Fix not to count error code to total length
+    - scsi: qla2xxx: Wait for io return on terminate rport
+    - scsi: qla2xxx: Fix potential NULL pointer dereference
+    - scsi: qla2xxx: Check valid rport returned by fc_bsg_to_rport()
+    - scsi: qla2xxx: Correct the index of array
+    - scsi: qla2xxx: Pointer may be dereferenced
+    - scsi: qla2xxx: Remove unused nvme_ls_waitq wait queue
+    - drm/atomic: Fix potential use-after-free in nonblocking commits
+    - perf probe: Add test for regression introduced by switch to
+      die_get_decl_file()
+    - btrfs: fix warning when putting transaction with qgroups enabled after abort
+    - fuse: revalidate: don't invalidate if interrupted
+    - selftests: tc: set timeout to 15 minutes
+    - can: bcm: Fix UAF in bcm_proc_show()
+    - drm/client: Fix memory leak in drm_client_target_cloned
+    - drm/client: Fix memory leak in drm_client_modeset_probe
+    - ext4: correct inline offset when handling xattrs in inode body
+    - debugobjects: Recheck debug_objects_enabled before reporting
+    - nbd: Add the maximum limit of allocated index in nbd_dev_add
+    - md: fix data corruption for raid456 when reshape restart while grow up
+    - md/raid10: prevent soft lockup while flush writes
+    - posix-timers: Ensure timer ID search-loop limit is valid
+    - arm64: mm: fix VA-range sanity check
+    - sched/fair: Don't balance task to its current running CPU
+    - bpf: Address KCSAN report on bpf_lru_list
+    - devlink: report devlink_port_type_warn source device
+    - wifi: wext-core: Fix -Wstringop-overflow warning in
+      ioctl_standard_iw_point()
+    - wifi: iwlwifi: mvm: avoid baid size integer overflow
+    - igb: Fix igb_down hung on surprise removal
+    - spi: bcm63xx: fix max prepend length
+    - fbdev: imxfb: warn about invalid left/right margin
+    - pinctrl: amd: Use amd_pinconf_set() for all config options
+    - net: ethernet: ti: cpsw_ale: Fix cpsw_ale_get_field()/cpsw_ale_set_field()
+    - iavf: Fix use-after-free in free_netdev
+    - net:ipv6: check return value of pskb_trim()
+    - Revert "tcp: avoid the lookup process failing to get sk in ehash table"
+    - fbdev: au1200fb: Fix missing IRQ check in au1200fb_drv_probe
+    - llc: Don't drop packet from non-root netns.
+    - netfilter: nf_tables: fix spurious set element insertion failure
+    - netfilter: nf_tables: can't schedule in nft_chain_validate
+    - tcp: annotate data-races around tp->tcp_tx_delay
+    - net: Replace the limit of TCP_LINGER2 with TCP_FIN_TIMEOUT_MAX
+    - tcp: annotate data-races around tp->linger2
+    - tcp: annotate data-races around rskq_defer_accept
+    - tcp: annotate data-races around tp->notsent_lowat
+    - tcp: annotate data-races around fastopenq.max_qlen
+    - tracing/histograms: Return an error if we fail to add histogram to hist_vars
+      list
+    - Linux 5.4.251
+  * Focal update: v5.4.250 upstream stable release (LP: #2033297)
+    - x86/microcode/AMD: Load late on both threads too
+    - Linux 5.4.250
+  * Focal update: v5.4.249 upstream stable release (LP: #2033278)
+    - nilfs2: reject devices with insufficient block count
+    - mm: rewrite wait_on_page_bit_common() logic
+    - list: add "list_del_init_careful()" to go with "list_empty_careful()"
+    - epoll: ep_autoremove_wake_function should use list_del_init_careful
+    - tracing: Add tracing_reset_all_online_cpus_unlocked() function
+    - x86/purgatory: remove PGO flags
+    - tick/common: Align tick period during sched_timer setup
+    - media: dvbdev: Fix memleak in dvb_register_device
+    - media: dvbdev: fix error logic at dvb_register_device()
+    - media: dvb-core: Fix use-after-free due to race at dvb_register_device()
+    - nilfs2: fix buffer corruption due to concurrent device reads
+    - Drivers: hv: vmbus: Fix vmbus_wait_for_unload() to scan present CPUs
+    - PCI: hv: Fix a race condition bug in hv_pci_query_relations()
+    - cgroup: Do not corrupt task iteration when rebinding subsystem
+    - mmc: meson-gx: remove redundant mmc_request_done() call from irq context
+    - ip_tunnels: allow VXLAN/GENEVE to inherit TOS/TTL from VLAN
+    - writeback: fix dereferencing NULL mapping->host on writeback_page_template
+    - nilfs2: prevent general protection fault in nilfs_clear_dirty_page()
+    - cifs: Clean up DFS referral cache
+    - cifs: Get rid of kstrdup_const()'d paths
+    - cifs: Introduce helpers for finding TCP connection
+    - cifs: Merge is_path_valid() into get_normalized_path()
+    - cifs: Fix potential deadlock when updating vol in cifs_reconnect()
+    - x86/mm: Avoid using set_pgd() outside of real PGD pages
+    - ieee802154: hwsim: Fix possible memory leaks
+    - xfrm: Linearize the skb after offloading if needed.
+    - net: qca_spi: Avoid high load if QCA7000 is not available
+    - mmc: mtk-sd: fix deferred probing
+    - mmc: mvsdio: convert to devm_platform_ioremap_resource
+    - mmc: mvsdio: fix deferred probing
+    - mmc: omap: fix deferred probing
+    - mmc: omap_hsmmc: fix deferred probing
+    - mmc: sdhci-acpi: fix deferred probing
+    - mmc: sh_mmcif: fix deferred probing
+    - mmc: usdhi60rol0: fix deferred probing
+    - ipvs: align inner_mac_header for encapsulation
+    - net: dsa: mt7530: fix trapping frames on non-MT7621 SoC MT7530 switch
+    - be2net: Extend xmit workaround to BE3 chip
+    - netfilter: nf_tables: disallow element updates of bound anonymous sets
+    - netfilter: nfnetlink_osf: fix module autoload
+    - Revert "net: phy: dp83867: perform soft reset and retain established link"
+    - sch_netem: acquire qdisc lock in netem_change()
+    - scsi: target: iscsi: Prevent login threads from racing between each other
+    - HID: wacom: Add error check to wacom_parse_and_register()
+    - arm64: Add missing Set/Way CMO encodings
+    - media: cec: core: don't set last_initiator if tx in progress
+    - nfcsim.c: Fix error checking for debugfs_create_dir
+    - usb: gadget: udc: fix NULL dereference in remove()
+    - s390/cio: unregister device when the only path is gone
+    - ASoC: nau8824: Add quirk to active-high jack-detect
+    - ARM: dts: Fix erroneous ADS touchscreen polarities
+    - drm/exynos: vidi: fix a wrong error return
+    - drm/exynos: fix race condition UAF in exynos_g2d_exec_ioctl
+    - drm/radeon: fix race condition UAF in radeon_gem_set_domain_ioctl
+    - x86/apic: Fix kernel panic when booting with intremap=off and x2apic_phys
+    - i2c: imx-lpi2c: fix type char overflow issue when calculating the clock
+      cycle
+    - mm: fix VM_BUG_ON(PageTail) and BUG_ON(PageWriteback)
+    - mm: make wait_on_page_writeback() wait for multiple pending writebacks
+    - Linux 5.4.249
+  * allow io_uring to be disabled in runtime (LP: #2035116)
+    - io_uring: add a sysctl to disable io_uring system-wide
+  * CVE-2023-31083
+    - Bluetooth: hci_ldisc: check HCI_UART_PROTO_READY flag in HCIUARTGETPROTO
+  * CVE-2023-4132
+    - media: usb: siano: Fix warning due to null work_func_t function pointer
+  * CVE-2023-3772
+    - xfrm: add NULL check in xfrm_update_ae_params
+  * CVE-2023-0597
+    - random32: add noise from network and scheduling activity
+    - x86/kasan: Map shadow for percpu pages on demand
+    - x86/mm: Randomize per-cpu entry area
+    - x86/mm: Recompute physical address for every page of per-CPU CEA mapping
+    - x86/mm: Populate KASAN shadow for entire per-CPU range of CPU entry area
+    - x86/mm: Do not shuffle CPU entry areas without KASLR
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Wed, 11 Oct 2023 15:25:26 +1000
+
+linux-xilinx-zynqmp (5.4.0-1031.35) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1031.35 -proposed tracker (LP: #2033865)
+
+  * Firefox doesn't export URL (LP: #203112)
+    - [Config] updateconfigs for DECNET
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update helper scripts
+
+  [ Ubuntu: 5.4.0-164.181 ]
+
+  * focal/linux: 5.4.0-164.181 -proposed tracker (LP: #2033867)
+  * Please enable Renesas RZ platform serial installer (LP: #2022361)
+    - [Config] enable hihope RZ/G2M serial console
+  * Azure: hv_netvsc: add support for vlans in AF_PACKET mode (LP: #2030872)
+    - hv_netvsc: add support for vlans in AF_PACKET mode
+  * systemd mount units fail during boot, while file system is correctly mounted
+    (LP: #1837227)
+    - list: introduce list_for_each_continue()
+    - proc/mounts: add cursor
+  * CVE-2023-40283
+    - Bluetooth: L2CAP: Fix use-after-free in l2cap_sock_ready_cb
+  * CVE-2023-20588
+    - x86/bugs: Increase the x86 bugs vector size to two u32s
+    - x86/CPU/AMD: Do not leak quotient data after a division by 0
+    - x86/CPU/AMD: Fix the DIV(0) initial fix attempt
+  * CVE-2023-4194
+    - net: tun_chr_open(): set sk_uid from current_fsuid()
+    - net: tap_open(): set sk_uid from current_fsuid()
+  * CVE-2023-1206
+    - tcp: Reduce chance of collisions in inet6_hashfn().
+  * CVE-2021-4001
+    - bpf: Fix toctou on read-only map's constant scalar tracking
+  * Focal update: v5.4.248 upstream stable release (LP: #2031121)
+    - test_firmware: fix a memory leak with reqs buffer
+    - KEYS: asymmetric: Copy sig and digest in public_key_verify_signature()
+    - dasd: refactor dasd_ioctl_information
+    - s390/dasd: Use correct lock while counting channel queue length
+    - power: supply: ab8500: Fix external_power_changed race
+    - power: supply: sc27xx: Fix external_power_changed race
+    - power: supply: bq27xxx: Use mod_delayed_work() instead of cancel() +
+      schedule()
+    - ARM: dts: vexpress: add missing cache properties
+    - power: supply: Ratelimit no data debug output
+    - platform/x86: asus-wmi: Ignore WMI events with codes 0x7B, 0xC0
+    - regulator: Fix error checking for debugfs_create_dir
+    - irqchip/meson-gpio: Mark OF related data as maybe unused
+    - power: supply: Fix logic checking if system is running from battery
+    - btrfs: handle memory allocation failure in btrfs_csum_one_bio
+    - parisc: Improve cache flushing for PCXL in arch_sync_dma_for_cpu()
+    - parisc: Flush gatt writes and adjust gatt mask in parisc_agp_mask_memory()
+    - MIPS: Alchemy: fix dbdma2
+    - mips: Move initrd_start check after initrd address sanitisation.
+    - xen/blkfront: Only check REQ_FUA for writes
+    - drm:amd:amdgpu: Fix missing buffer object unlock in failure path
+    - ocfs2: fix use-after-free when unmounting read-only filesystem
+    - ocfs2: check new file size on fallocate call
+    - nios2: dts: Fix tse_mac "max-frame-size" property
+    - nilfs2: fix incomplete buffer cleanup in nilfs_btnode_abort_change_key()
+    - nilfs2: fix possible out-of-bounds segment allocation in resize ioctl
+    - kexec: support purgatories with .text.hot sections
+    - powerpc/purgatory: remove PGO flags
+    - nouveau: fix client work fence deletion race
+    - RDMA/uverbs: Restrict usage of privileged QKEYs
+    - net: usb: qmi_wwan: add support for Compal RXM-G1
+    - ALSA: hda/realtek: Add a quirk for Compaq N14JP6
+    - Remove DECnet support from kernel
+    - [Config] updateconfigs for DECNET
+    - USB: serial: option: add Quectel EM061KGL series
+    - serial: lantiq: add missing interrupt ack
+    - usb: dwc3: gadget: Reset num TRBs before giving back the request
+    - spi: spi-fsl-dspi: Remove unused chip->void_write_data
+    - spi: fsl-dspi: avoid SCK glitches with continuous transfers
+    - netfilter: nfnetlink: skip error delivery on batch in case of ENOMEM
+    - ping6: Fix send to link-local addresses with VRF.
+    - RDMA/rxe: Remove the unused variable obj
+    - RDMA/rxe: Removed unused name from rxe_task struct
+    - RDMA/rxe: Fix the use-before-initialization error of resp_pkts
+    - iavf: remove mask from iavf_irq_enable_queues()
+    - IB/uverbs: Fix to consider event queue closing also upon non-blocking mode
+    - IB/isert: Fix dead lock in ib_isert
+    - IB/isert: Fix possible list corruption in CMA handler
+    - IB/isert: Fix incorrect release of isert connection
+    - ipvlan: fix bound dev checking for IPv6 l3s mode
+    - sctp: fix an error code in sctp_sf_eat_auth()
+    - igb: fix nvm.ops.read() error handling
+    - drm/nouveau/dp: check for NULL nv_connector->native_mode
+    - drm/nouveau/kms: Don't change EDID when it hasn't actually changed
+    - drm/nouveau: add nv_encoder pointer check for NULL
+    - net/sched: cls_api: Fix lockup on flushing explicitly created chain
+    - net: lapbether: only support ethernet devices
+    - net: tipc: resize nlattr array to correct size
+    - selftests/ptp: Fix timestamp printf format for PTP_SYS_OFFSET
+    - afs: Fix vlserver probe RTT handling
+    - neighbour: Remove unused inline function neigh_key_eq16()
+    - net: Remove unused inline function dst_hold_and_use()
+    - neighbour: delete neigh_lookup_nodev as not used
+    - drm/nouveau/kms: Fix NULL pointer dereference in
+      nouveau_connector_detect_depth
+    - mmc: block: ensure error propagation for non-blk
+    - Linux 5.4.248
+  * Focal update: v5.4.247 upstream stable release (LP: #2030818)
+    - blk-iocost: avoid 64-bit division in ioc_timer_fn
+    - block/blk-iocost (gcc13): keep large values in a new enum
+    - i40iw: fix build warning in i40iw_manage_apbvt()
+    - i40e: fix build warnings in i40e_alloc.h
+    - spi: qup: Request DMA before enabling clocks
+    - neighbour: Replace zero-length array with flexible-array member
+    - neighbour: fix unaligned access to pneigh_entry
+    - net: dsa: lan9303: allow vid != 0 in port_fdb_{add|del} methods
+    - Bluetooth: Fix l2cap_disconnect_req deadlock
+    - Bluetooth: L2CAP: Add missing checks for invalid DCID
+    - netfilter: conntrack: fix NULL pointer dereference in nf_confirm_cthelper
+    - netfilter: ipset: Add schedule point in call_ad().
+    - rfs: annotate lockless accesses to sk->sk_rxhash
+    - rfs: annotate lockless accesses to RFS sock flow table
+    - net: sched: move rtm_tca_policy declaration to include file
+    - net: sched: fix possible refcount leak in tc_chain_tmplt_add()
+    - lib: cpu_rmap: Fix potential use-after-free in irq_cpu_rmap_release()
+    - bnxt_en: Query default VLAN before VNIC setup on a VF
+    - batman-adv: Broken sync while rescheduling delayed work
+    - Input: xpad - delete a Razer DeathAdder mouse VID/PID entry
+    - Input: psmouse - fix OOB access in Elantech protocol
+    - ALSA: hda/realtek: Add a quirk for HP Slim Desktop S01
+    - ALSA: hda/realtek: Add Lenovo P3 Tower platform
+    - drm/amdgpu: fix xclk freq on CHIP_STONEY
+    - can: j1939: j1939_sk_send_loop_abort(): improved error queue handling in
+      J1939 Socket
+    - can: j1939: change j1939_netdev_lock type to mutex
+    - can: j1939: avoid possible use-after-free when j1939_can_rx_register fails
+    - ceph: fix use-after-free bug for inodes when flushing capsnaps
+    - Bluetooth: Fix use-after-free in hci_remove_ltk/hci_remove_irk
+    - rbd: move RBD_OBJ_FLAG_COPYUP_ENABLED flag setting
+    - pinctrl: meson-axg: add missing GPIOA_18 gpio group
+    - usb: usbfs: Enforce page requirements for mmap
+    - usb: usbfs: Use consistent mmap functions
+    - bonding (gcc13): synchronize bond_{a,t}lb_xmit() types
+    - i2c: sprd: Delete i2c adapter in .remove's error path
+    - eeprom: at24: also select REGMAP
+    - ext4: only check dquot_initialize_needed() when debugging
+    - drm/atomic: Don't pollute crtc_state->mode_blob with error pointers
+    - rbd: get snapshot context after exclusive lock is ensured to be held
+    - mtd: spinand: macronix: Add support for MX35LFxGE4AD
+    - Linux 5.4.247
+  * CVE-2023-4128
+    - net/sched: cls_u32: No longer copy tcf_result on update to avoid use-after-
+      free
+    - net/sched: cls_fw: No longer copy tcf_result on update to avoid use-after-
+      free
+    - net/sched: cls_route: No longer copy tcf_result on update to avoid use-
+      after-free
+  * CVE-2023-3863
+    - nfc: llcp: simplify llcp_sock_connect() error paths
+    - net: nfc: Fix use-after-free caused by nfc_llcp_find_local
+  * CVE-2023-3212
+    - gfs2: Don't deref jdesc in evict
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Thu, 14 Sep 2023 20:09:45 +1000
+
+linux-xilinx-zynqmp (5.4.0-1030.34) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1030.34 -proposed tracker (LP: #2034245)
+
+  [ Ubuntu: 5.4.0-163.180 ]
+
+  * focal/linux: 5.4.0-163.180 -proposed tracker (LP: #2034247)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update helper scripts
+  * CVE-2023-40283
+    - Bluetooth: L2CAP: Fix use-after-free in l2cap_sock_ready_cb
+  * CVE-2023-20588
+    - x86/bugs: Increase the x86 bugs vector size to two u32s
+    - x86/CPU/AMD: Do not leak quotient data after a division by 0
+    - x86/CPU/AMD: Fix the DIV(0) initial fix attempt
+  * CVE-2023-4128
+    - net/sched: cls_u32: No longer copy tcf_result on update to avoid use-after-
+      free
+    - net/sched: cls_fw: No longer copy tcf_result on update to avoid use-after-
+      free
+    - net/sched: cls_route: No longer copy tcf_result on update to avoid use-
+      after-free
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Fri, 08 Sep 2023 10:43:09 +1000
+
+linux-xilinx-zynqmp (5.4.0-1029.33) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1029.33 -proposed tracker (LP: #2031015)
+
+  * Focal update: v5.4.246 upstream stable release (LP: #2028981)
+    - [Config] updateconfigs for SCSI_DPT_I2O
+
+  [ Ubuntu: 5.4.0-162.179 ]
+
+  * focal/linux: 5.4.0-162.179 -proposed tracker (LP: #2031128)
+  * libgnutls report "trap invalid opcode" when trying to install packages over
+    https (LP: #2031093)
+    - [Config]: disable CONFIG_GDS_FORCE_MITIGATION
+
+  [ Ubuntu: 5.4.0-160.177 ]
+
+  * focal/linux: 5.4.0-160.177 -proposed tracker (LP: #2031017)
+  * Fix boot test warning for log_check "CPU: 0 PID: 0 at
+    arch/x86/kernel/fpu/xstate.c:878 get_xsave_addr+0x98/0xb0" (LP: #2031022)
+    - x86/pkeys: Revert a5eff7259790 ("x86/pkeys: Add PKRU value to init_fpstate")
+
+ -- Wen-chien Jesse Sung <jesse.sung@canonical.com>  Fri, 25 Aug 2023 19:46:01 +0800
+
+linux-xilinx-zynqmp (5.4.0-1028.32) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1028.32 -proposed tracker (LP: #2030630)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync update-dkms-versions helper
+
+  [ Ubuntu: 5.4.0-159.176 ]
+
+  * focal/linux: 5.4.0-159.176 -proposed tracker (LP: #2031149)
+  * libgnutls report "trap invalid opcode" when trying to install packages over
+    https (LP: #2031093)
+    - [Config]: disable CONFIG_GDS_FORCE_MITIGATION
+  * Fix boot test warning for log_check "CPU: 0 PID: 0 at
+    arch/x86/kernel/fpu/xstate.c:878 get_xsave_addr+0x98/0xb0" (LP: #2031022)
+    - x86/pkeys: Revert a5eff7259790 ("x86/pkeys: Add PKRU value to init_fpstate")
+
+  [ Ubuntu: 5.4.0-157.174 ]
+
+  * focal/linux: 5.4.0-157.174 -proposed tracker (LP: #2030632)
+  * CVE-2022-40982
+    - x86/mm: Initialize text poking earlier
+    - x86/mm: fix poking_init() for Xen PV guests
+    - x86/mm: Use mm_alloc() in poking_init()
+    - mm: Move mm_cachep initialization to mm_init()
+    - init: Provide arch_cpu_finalize_init()
+    - x86/cpu: Switch to arch_cpu_finalize_init()
+    - ARM: cpu: Switch to arch_cpu_finalize_init()
+    - sparc/cpu: Switch to arch_cpu_finalize_init()
+    - um/cpu: Switch to arch_cpu_finalize_init()
+    - init: Remove check_bugs() leftovers
+    - init: Invoke arch_cpu_finalize_init() earlier
+    - init, x86: Move mem_encrypt_init() into arch_cpu_finalize_init()
+    - x86/fpu: Remove cpuinfo argument from init functions
+    - x86/fpu: Mark init functions __init
+    - x86/fpu: Move FPU initialization into arch_cpu_finalize_init()
+    - x86/xen: Fix secondary processors' FPU initialization
+    - x86/speculation: Add Gather Data Sampling mitigation
+    - x86/speculation: Add force option to GDS mitigation
+    - x86/speculation: Add Kconfig option for GDS
+    - KVM: Add GDS_NO support to KVM
+    - Documentation/x86: Fix backwards on/off logic about YMM support
+    - [Config]: Enable CONFIG_ARCH_HAS_CPU_FINALIZE_INIT and
+      CONFIG_GDS_FORCE_MITIGATION
+  * CVE-2023-20593
+    - x86/cpu/amd: Move the errata checking functionality up
+    - x86/cpu/amd: Add a Zenbleed fix
+  * CVE-2023-3776
+    - net/sched: cls_fw: Fix improper refcount update leads to use-after-free
+  * CVE-2023-3611
+    - net/sched: sch_qfq: account for stab overhead in qfq_enqueue
+  * CVE-2023-3609
+    - net/sched: cls_u32: Fix reference counter leak leading to overflow
+
+ -- Wen-chien Jesse Sung <jesse.sung@canonical.com>  Thu, 17 Aug 2023 22:00:01 +0800
+
+linux-xilinx-zynqmp (5.4.0-1027.31) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1027.31 -proposed tracker (LP: #2026582)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync update-dkms-versions helper
+    - [Packaging] resync getabis
+
+  [ Ubuntu: 5.4.0-156.173 ]
+
+  * focal/linux: 5.4.0-156.173 -proposed tracker (LP: #2026585)
+  * CVE-2023-3390
+    - netfilter: nf_tables: incorrect error path handling with NFT_MSG_NEWRULE
+  * Focal update: v5.4.241 upstream stable release (LP: #2023930)
+    - scsi: ses: Handle enclosure with just a primary component gracefully
+    - x86/PCI: Add quirk for AMD XHCI controller that loses MSI-X state in D3hot
+    - cgroup/cpuset: Wake up cpuset_attach_wq tasks in cpuset_cancel_attach()
+    - treewide: Replace DECLARE_TASKLET() with DECLARE_TASKLET_OLD()
+    - smb3: fix problem with null cifs super block with previous patch
+    - pinctrl: amd: Use irqchip template
+    - pinctrl: amd: disable and mask interrupts on probe
+    - pinctrl: amd: Disable and mask interrupts on resume
+    - pwm: cros-ec: Explicitly set .polarity in .get_state()
+    - pwm: sprd: Explicitly set .polarity in .get_state()
+    - wifi: mac80211: fix invalid drv_sta_pre_rcu_remove calls for non-uploaded
+      sta
+    - icmp: guard against too small mtu
+    - net: don't let netpoll invoke NAPI if in xmit context
+    - sctp: check send stream number after wait_for_sndbuf
+    - ipv6: Fix an uninit variable access bug in __ip6_make_skb()
+    - gpio: davinci: Add irq chip flag to skip set wake
+    - sunrpc: only free unix grouplist after RCU settles
+    - NFSD: callback request does not use correct credential for AUTH_SYS
+    - xhci: also avoid the XHCI_ZERO_64B_REGS quirk with a passthrough iommu
+    - USB: serial: cp210x: add Silicon Labs IFS-USB-DATACABLE IDs
+    - usb: typec: altmodes/displayport: Fix configure initial pin assignment
+    - USB: serial: option: add Telit FE990 compositions
+    - USB: serial: option: add Quectel RM500U-CN modem
+    - iio: adc: ti-ads7950: Set `can_sleep` flag for GPIO chip
+    - iio: dac: cio-dac: Fix max DAC write value check for 12-bit
+    - tty: serial: sh-sci: Fix transmit end interrupt handler
+    - tty: serial: sh-sci: Fix Rx on RZ/G2L SCI
+    - tty: serial: fsl_lpuart: avoid checking for transfer complete when
+      UARTCTRL_SBK is asserted in lpuart32_tx_empty
+    - nilfs2: fix potential UAF of struct nilfs_sc_info in nilfs_segctor_thread()
+    - nilfs2: fix sysfs interface lifetime
+    - ALSA: hda/realtek: Add quirk for Clevo X370SNW
+    - perf/core: Fix the same task check in perf_event_set_output
+    - ftrace: Mark get_lock_parent_ip() __always_inline
+    - can: j1939: j1939_tp_tx_dat_new(): fix out-of-bounds memory access
+    - tracing: Free error logs of tracing instances
+    - net_sched: prevent NULL dereference if default qdisc setup failed
+    - drm/panfrost: Fix the panfrost_mmu_map_fault_addr() error path
+    - ring-buffer: Fix race while reader and writer are on the same page
+    - mm/swap: fix swap_info_struct race between swapoff and get_swap_pages()
+    - irqdomain: Look for existing mapping only once
+    - irqdomain: Refactor __irq_domain_alloc_irqs()
+    - irqdomain: Fix mapping-creation race
+    - Revert "pinctrl: amd: Disable and mask interrupts on resume"
+    - ALSA: emu10k1: fix capture interrupt handler unlinking
+    - ALSA: hda/sigmatel: add pin overrides for Intel DP45SG motherboard
+    - ALSA: i2c/cs8427: fix iec958 mixer control deactivation
+    - ALSA: firewire-tascam: add missing unwind goto in
+      snd_tscm_stream_start_duplex()
+    - ALSA: hda/sigmatel: fix S/PDIF out on Intel D*45* motherboards
+    - Bluetooth: L2CAP: Fix use-after-free in l2cap_disconnect_{req,rsp}
+    - Bluetooth: Fix race condition in hidp_session_thread
+    - btrfs: print checksum type and implementation at mount time
+    - btrfs: fix fast csum implementation detection
+    - mtdblock: tolerate corrected bit-flips
+    - mtd: rawnand: meson: fix bitmask for length in command word
+    - mtd: rawnand: stm32_fmc2: remove unsupported EDO mode
+    - niu: Fix missing unwind goto in niu_alloc_channels()
+    - qlcnic: check pci_reset_function result
+    - sctp: fix a potential overflow in sctp_ifwdtsn_skip
+    - RDMA/core: Fix GID entry ref leak when create_ah fails
+    - udp6: fix potential access to stale information
+    - net: macb: fix a memory corruption in extended buffer descriptor mode
+    - power: supply: cros_usbpd: reclassify "default case!" as debug
+    - i2c: imx-lpi2c: clean rx/tx buffers upon new message
+    - efi: sysfb_efi: Add quirk for Lenovo Yoga Book X91F/L
+    - drm: panel-orientation-quirks: Add quirk for Lenovo Yoga Book X90F
+    - verify_pefile: relax wrapper length check
+    - asymmetric_keys: log on fatal failures in PE/pkcs7
+    - ubi: Fix failure attaching when vid_hdr offset equals to (sub)page size
+    - mtd: ubi: wl: Fix a couple of kernel-doc issues
+    - ubi: Fix deadlock caused by recursively holding work_sem
+    - i2c: ocores: generate stop condition after timeout in polling mode
+    - watchdog: sbsa_wdog: Make sure the timeout programming is within the limits
+    - coresight-etm4: Fix for() loop drvdata->nr_addr_cmp range bug
+    - xfs: show the proper user quota options
+    - xfs: remove the kuid/kgid conversion wrappers
+    - xfs: add a new xfs_sb_version_has_v3inode helper
+    - xfs: only check the superblock version for dinode size calculation
+    - xfs: simplify di_flags2 inheritance in xfs_ialloc
+    - xfs: simplify a check in xfs_ioctl_setattr_check_cowextsize
+    - xfs: remove the di_version field from struct icdinode
+    - xfs: set inode size after creating symlink
+    - xfs: report corruption only as a regular error
+    - xfs: shut down the filesystem if we screw up quota reservation
+    - xfs: consider shutdown in bmapbt cursor delete assert
+    - xfs: don't reuse busy extents on extent trim
+    - xfs: force log and push AIL to clear pinned inodes when aborting mount
+    - Linux 5.4.241
+  * [UBUNTU 20.04] [HPS] Kernel panic with "refcount_t: underflow" in mlx5
+    driver (LP: #2019011)
+    - net/mlx5: cmdif, Avoid skipping reclaim pages if FW is not accessible
+    - net/mlx5: Fix handling of entry refcount when command is not issued to FW
+  * Disable hv-kvp-daemon if /dev/vmbus/hv_kvp is not present (LP: #2024900)
+    - [Packaging] disable hv-kvp-daemon if needed
+  * CVE-2023-35001
+    - netfilter: nf_tables: prevent OOB access in nft_byteorder_eval
+  * CVE-2023-32629
+    - ovl: adhere to the vfs_ vs. ovl_do_ conventions for xattrs
+  * CVE-2023-3141
+    - memstick: r592: Fix UAF bug in r592_remove due to race condition
+  * CVE-2023-3111
+    - btrfs: check return value of btrfs_commit_transaction in relocation
+    - btrfs: unset reloc control if transaction commit fails in
+      prepare_to_relocate()
+  * CVE-2023-3090
+    - ipvlan:Fix out-of-bounds caused by unclear skb->cb
+  * CVE-2023-1611
+    - btrfs: fix race between quota disable and quota assign ioctls
+  * CVE-2022-0168
+    - cifs: move some variables off the stack in smb2_ioctl_query_info
+    - cifs: prevent bad output lengths in smb2_ioctl_query_info()
+    - cifs: fix NULL ptr dereference in smb2_ioctl_query_info()
+  * CVE-2022-27672
+    - x86/speculation: Identify processors vulnerable to SMT RSB predictions
+    - KVM: x86: Mitigate the cross-thread return address predictions bug
+    - Documentation/hw-vuln: Add documentation for Cross-Thread Return Predictions
+  * Severe NFS performance degradation after LP #2003053 (LP: #2022098)
+    - SAUCE: Make NFS file-access stale cache behaviour opt-in
+  * Encountering an issue with memcpy_fromio causing failed boot of SEV-enabled
+    guest (LP: #2020319)
+    - x86/sev: Unroll string mmio with CC_ATTR_GUEST_UNROLL_STRING_IO
+  * Focal update: v5.4.240 upstream stable release (LP: #2023601)
+    - net: tls: fix possible race condition between do_tls_getsockopt_conf() and
+      do_tls_setsockopt_conf()
+    - power: supply: da9150: Fix use after free bug in da9150_charger_remove due
+      to race condition
+    - iavf: fix inverted Rx hash condition leading to disabled hash
+    - iavf: fix non-tunneled IPv6 UDP packet type and hashing
+    - intel/igbvf: free irq on the error path in igbvf_request_msix()
+    - igbvf: Regard vf reset nack as success
+    - i2c: imx-lpi2c: check only for enabled interrupt flags
+    - scsi: scsi_dh_alua: Fix memleak for 'qdata' in alua_activate()
+    - net: usb: smsc95xx: Limit packet length to skb->len
+    - qed/qed_sriov: guard against NULL derefs from qed_iov_get_vf_info
+    - net: qcom/emac: Fix use after free bug in emac_remove due to race condition
+    - net/ps3_gelic_net: Fix RX sk_buff length
+    - net/ps3_gelic_net: Use dma_mapping_error
+    - keys: Do not cache key in task struct if key is requested from kernel thread
+    - bpf: Adjust insufficient default bpf_jit_limit
+    - net/mlx5: Read the TC mapping of all priorities on ETS query
+    - atm: idt77252: fix kmemleak when rmmod idt77252
+    - erspan: do not use skb_mac_header() in ndo_start_xmit()
+    - net/sonic: use dma_mapping_error() for error check
+    - nvme-tcp: fix nvme_tcp_term_pdu to match spec
+    - hvc/xen: prevent concurrent accesses to the shared ring
+    - net: mdio: thunder: Add missing fwnode_handle_put()
+    - Bluetooth: btqcomsmd: Fix command timeout after setting BD address
+    - platform/chrome: cros_ec_chardev: fix kernel data leak from ioctl
+    - hwmon (it87): Fix voltage scaling for chips with 10.9mV ADCs
+    - scsi: qla2xxx: Perform lockless command completion in abort path
+    - uas: Add US_FL_NO_REPORT_OPCODES for JMicron JMS583Gen 2
+    - thunderbolt: Use const qualifier for `ring_interrupt_index`
+    - riscv: Bump COMMAND_LINE_SIZE value to 1024
+    - ca8210: fix mac_len negative array access
+    - m68k: Only force 030 bus error if PC not in exception table
+    - selftests/bpf: check that modifier resolves after pointer
+    - scsi: target: iscsi: Fix an error message in iscsi_check_key()
+    - scsi: ufs: core: Add soft dependency on governor_simpleondemand
+    - scsi: lpfc: Avoid usage of list iterator variable after loop
+    - net: usb: cdc_mbim: avoid altsetting toggling for Telit FE990
+    - net: usb: qmi_wwan: add Telit 0x1080 composition
+    - sh: sanitize the flags on sigreturn
+    - cifs: empty interface list when server doesn't support query interfaces
+    - scsi: core: Add BLIST_SKIP_VPD_PAGES for SKhynix H28U74301AMR
+    - usb: gadget: u_audio: don't let userspace block driver unbind
+    - fsverity: Remove WQ_UNBOUND from fsverity read workqueue
+    - igb: revert rtnl_lock() that causes deadlock
+    - dm thin: fix deadlock when swapping to thin device
+    - usb: cdns3: Fix issue with using incorrect PCI device function
+    - usb: chipdea: core: fix return -EINVAL if request role is the same with
+      current role
+    - usb: chipidea: core: fix possible concurrent when switch role
+    - wifi: mac80211: fix qos on mesh interfaces
+    - nilfs2: fix kernel-infoleak in nilfs_ioctl_wrap_copy()
+    - i2c: xgene-slimpro: Fix out-of-bounds bug in xgene_slimpro_i2c_xfer()
+    - dm stats: check for and propagate alloc_percpu failure
+    - dm crypt: add cond_resched() to dmcrypt_write()
+    - sched/fair: sanitize vruntime of entity being placed
+    - sched/fair: Sanitize vruntime of entity being migrated
+    - tun: avoid double free in tun_free_netdev
+    - ocfs2: fix data corruption after failed write
+    - fsverity: don't drop pagecache at end of FS_IOC_ENABLE_VERITY
+    - bus: imx-weim: fix branch condition evaluates to a garbage value
+    - md: avoid signed overflow in slot_store()
+    - ALSA: asihpi: check pao in control_message()
+    - ALSA: hda/ca0132: fixup buffer overrun at tuning_ctl_set()
+    - fbdev: tgafb: Fix potential divide by zero
+    - sched_getaffinity: don't assume 'cpumask_size()' is fully initialized
+    - fbdev: nvidia: Fix potential divide by zero
+    - fbdev: intelfb: Fix potential divide by zero
+    - fbdev: lxfb: Fix potential divide by zero
+    - fbdev: au1200fb: Fix potential divide by zero
+    - ca8210: Fix unsigned mac_len comparison with zero in ca8210_skb_tx()
+    - dma-mapping: drop the dev argument to arch_sync_dma_for_*
+    - mips: bmips: BCM6358: disable RAC flush for TP1
+    - mtd: rawnand: meson: invalidate cache on polling ECC bit
+    - scsi: megaraid_sas: Fix crash after a double completion
+    - ptp_qoriq: fix memory leak in probe()
+    - regulator: fix spelling mistake "Cant" -> "Can't"
+    - regulator: Handle deferred clk
+    - net/net_failover: fix txq exceeding warning
+    - can: bcm: bcm_tx_setup(): fix KMSAN uninit-value in vfs_write
+    - s390/vfio-ap: fix memory leak in vfio_ap device driver
+    - i40e: fix registers dump after run ethtool adapter self test
+    - bnxt_en: Fix typo in PCI id to device description string mapping
+    - net: dsa: mv88e6xxx: Enable IGMP snooping on user ports only
+    - net: mvneta: make tx buffer array agnostic
+    - pinctrl: ocelot: Fix alt mode for ocelot
+    - Input: alps - fix compatibility with -funsigned-char
+    - Input: focaltech - use explicitly signed char type
+    - cifs: prevent infinite recursion in CIFSGetDFSRefer()
+    - cifs: fix DFS traversal oops without CONFIG_CIFS_DFS_UPCALL
+    - Input: goodix - add Lenovo Yoga Book X90F to nine_bytes_report DMI table
+    - xen/netback: don't do grant copy across page boundary
+    - pinctrl: at91-pio4: fix domain name assignment
+    - NFSv4: Fix hangs when recovering open state after a server reboot
+    - ALSA: hda/conexant: Partial revert of a quirk for Lenovo
+    - ALSA: usb-audio: Fix regression on detection of Roland VS-100
+    - drm/etnaviv: fix reference leak when mmaping imported buffer
+    - btrfs: scan device in non-exclusive mode
+    - ext4: fix kernel BUG in 'ext4_write_inline_data_end()'
+    - net_sched: add __rcu annotation to netdev->qdisc
+    - net: sched: fix race condition in qdisc_graft()
+    - firmware: arm_scmi: Fix device node validation for mailbox transport
+    - gfs2: Always check inode size of inline inodes
+    - Linux 5.4.240
+  * Focal update: v5.4.239 upstream stable release (LP: #2023600)
+    - Linux 5.4.239
+  * CVE-2023-2124
+    - xfs: verify buffer contents when we skip log replay
+  * CVE-2020-36691
+    - netlink: limit recursion depth in policy validation
+  * CVE-2022-1184
+    - ext4: check if directory block is within i_size
+    - ext4: fix check for block being out of directory size
+  * CVE-2022-4269
+    - net: sched: extract qstats update code into functions
+    - net: sched: don't expose action qstats to skb_tc_reinsert()
+    - net/sched: act_mirred: refactor the handle of xmit
+    - net: sched: remove unused tcf_result extension
+    - net/sched: act_mirred: better wording on protection against excessive stack
+      growth
+    - act_mirred: use the backlog for nested calls to mirred ingress
+  * Focal update: v5.4.238 upstream stable release (LP: #2023427)
+    - ext4: fix cgroup writeback accounting with fs-layer encryption
+    - xfrm: Allow transport-mode states with AF_UNSPEC selector
+    - drm/panfrost: Don't sync rpm suspension after mmu flushing
+    - cifs: Move the in_send statistic to __smb_send_rqst()
+    - drm/meson: fix 1px pink line on GXM when scaling video overlay
+    - clk: HI655X: select REGMAP instead of depending on it
+    - docs: Correct missing "d_" prefix for dentry_operations member
+      d_weak_revalidate
+    - scsi: mpt3sas: Fix NULL pointer access in mpt3sas_transport_port_add()
+    - ALSA: hda - add Intel DG1 PCI and HDMI ids
+    - ALSA: hda - controller is in GPU on the DG1
+    - ALSA: hda: Add Alderlake-S PCI ID and HDMI codec vid
+    - ALSA: hda: Add Intel DG2 PCI ID and HDMI codec vid
+    - ALSA: hda: Match only Intel devices with CONTROLLER_IN_GPU()
+    - netfilter: nft_redir: correct value of inet type `.maxattrs`
+    - scsi: core: Fix a comment in function scsi_host_dev_release()
+    - scsi: core: Fix a procfs host directory removal regression
+    - tcp: tcp_make_synack() can be called from process context
+    - nfc: pn533: initialize struct pn533_out_arg properly
+    - ipvlan: Make skb->skb_iif track skb->dev for l3s mode
+    - i40e: Fix kernel crash during reboot when adapter is in recovery mode
+    - qed/qed_dev: guard against a possible division by zero
+    - net: tunnels: annotate lockless accesses to dev->needed_headroom
+    - net: phy: smsc: bail out in lan87xx_read_status if genphy_read_status fails
+    - nfc: st-nci: Fix use after free bug in ndlc_remove due to race condition
+    - net: usb: smsc75xx: Limit packet length to skb->len
+    - nvmet: avoid potential UAF in nvmet_req_complete()
+    - block: sunvdc: add check for mdesc_grab() returning NULL
+    - ipv4: Fix incorrect table ID in IOCTL path
+    - net: usb: smsc75xx: Move packet length check to prevent kernel panic in
+      skb_pull
+    - net/iucv: Fix size of interrupt data
+    - ethernet: sun: add check for the mdesc_grab()
+    - hwmon: (adt7475) Display smoothing attributes in correct order
+    - hwmon: (adt7475) Fix masking of hysteresis registers
+    - hwmon: (xgene) Fix use after free bug in xgene_hwmon_remove due to race
+      condition
+    - hwmon: (ina3221) return prober error code
+    - media: m5mols: fix off-by-one loop termination error
+    - mmc: atmel-mci: fix race between stop command and start of next command
+    - jffs2: correct logic when creating a hole in jffs2_write_begin
+    - ext4: fail ext4_iget if special inode unallocated
+    - ext4: fix task hung in ext4_xattr_delete_inode
+    - drm/amdkfd: Fix an illegal memory access
+    - sh: intc: Avoid spurious sizeof-pointer-div warning
+    - ext4: fix possible double unlock when moving a directory
+    - tty: serial: fsl_lpuart: skip waiting for transmission complete when
+      UARTCTRL_SBK is asserted
+    - interconnect: fix mem leak when freeing nodes
+    - tracing: Check field value in hist_field_name()
+    - tracing: Make tracepoint lockdep check actually test something
+    - ftrace: Fix invalid address access in lookup_rec() when index is 0
+    - fbdev: stifb: Provide valid pixelclock and add fb_check_var() checks
+    - x86/mm: Fix use of uninitialized buffer in sme_enable()
+    - drm/i915: Don't use stolen memory for ring buffers with LLC
+    - serial: 8250_em: Fix UART port type
+    - s390/ipl: add missing intersection check to ipl_report handling
+    - PCI: Unify delay handling for reset and resume
+    - HID: core: Provide new max_buffer_size attribute to over-ride the default
+    - HID: uhid: Over-ride the default maximum data buffer value with our own
+    - Linux 5.4.238
+  * Focal update: v5.4.237 upstream stable release (LP: #2023420)
+    - fs: prevent out-of-bounds array speculation when closing a file descriptor
+    - x86/CPU/AMD: Disable XSAVES on AMD family 0x17
+    - drm/connector: print max_requested_bpc in state debugfs
+    - ext4: fix RENAME_WHITEOUT handling for inline directories
+    - ext4: fix another off-by-one fsmap error on 1k block filesystems
+    - ext4: move where set the MAY_INLINE_DATA flag is set
+    - ext4: fix WARNING in ext4_update_inline_data
+    - ext4: zero i_disksize when initializing the bootloader inode
+    - nfc: change order inside nfc_se_io error path
+    - iommu/amd: Add PCI segment support for ivrs_[ioapic/hpet/acpihid] commands
+    - iommu/amd: Fix ill-formed ivrs_ioapic, ivrs_hpet and ivrs_acpihid options
+    - iommu/amd: Add a length limitation for the ivrs_acpihid command-line
+      parameter
+    - ipmi:ssif: make ssif_i2c_send() void
+    - ipmi:ssif: resend_msg() cannot fail
+    - ipmi:ssif: Remove rtc_us_timer
+    - ipmi:ssif: Increase the message retry time
+    - ipmi:ssif: Add a timer between request retries
+    - irqdomain: Change the type of 'size' in __irq_domain_add() to be consistent
+    - irqdomain: Fix domain registration race
+    - iommu/vt-d: Fix PASID directory pointer coherency
+    - SMB3: Backup intent flag missing from some more ops
+    - cifs: Fix uninitialized memory read in smb3_qfs_tcon()
+    - scsi: core: Remove the /proc/scsi/${proc_name} directory earlier
+    - ext4: Fix possible corruption when moving a directory
+    - drm/msm/a5xx: fix setting of the CP_PREEMPT_ENABLE_LOCAL register
+    - nfc: fdp: add null check of devm_kmalloc_array in
+      fdp_nci_i2c_read_device_properties
+    - ila: do not generate empty messages in ila_xlat_nl_cmd_get_mapping()
+    - selftests: nft_nat: ensuring the listening side is up before starting the
+      client
+    - net: usb: lan78xx: Remove lots of set but unused 'ret' variables
+    - net: lan78xx: fix accessing the LAN7800's internal phy specific registers
+      from the MAC driver
+    - net: caif: Fix use-after-free in cfusbl_device_notify()
+    - bnxt_en: Avoid order-5 memory allocation for TPA data
+    - netfilter: tproxy: fix deadlock due to missing BH disable
+    - btf: fix resolving BTF_KIND_VAR after ARRAY, STRUCT, UNION, PTR
+    - scsi: megaraid_sas: Update max supported LD IDs to 240
+    - net/smc: fix fallback failed while sendmsg with fastopen
+    - riscv: Use READ_ONCE_NOCHECK in imprecise unwinding stack mode
+    - ext4: Fix deadlock during directory rename
+    - MIPS: Fix a compilation issue
+    - alpha: fix R_ALPHA_LITERAL reloc for large modules
+    - macintosh: windfarm: Use unsigned type for 1-bit bitfields
+    - PCI: Add SolidRun vendor ID
+    - media: ov5640: Fix analogue gain control
+    - ipmi/watchdog: replace atomic_add() and atomic_sub()
+    - ipmi:watchdog: Set panic count to proper value on a panic
+    - drm/i915: Don't use BAR mappings for ring buffers with LLC
+    - x86, vmlinux.lds: Add RUNTIME_DISCARD_EXIT to generic DISCARDS
+    - arch: fix broken BuildID for arm64 and riscv
+    - powerpc/vmlinux.lds: Define RUNTIME_DISCARD_EXIT
+    - powerpc/vmlinux.lds: Don't discard .rela* for relocatable builds
+    - s390: define RUNTIME_DISCARD_EXIT to fix link error with GNU ld < 2.36
+    - sh: define RUNTIME_DISCARD_EXIT
+    - UML: define RUNTIME_DISCARD_EXIT
+    - s390/dasd: add missing discipline function
+    - Linux 5.4.237
+  * Focal update: v5.4.236 upstream stable release (LP: #2020390)
+    - staging: rtl8192e: Remove function ..dm_check_ac_dc_power calling a script
+    - staging: rtl8192e: Remove call_usermodehelper starting RadioPower.sh
+    - Linux 5.4.236
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync update-dkms-versions helper
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Fri, 28 Jul 2023 05:30:21 +1000
+
+linux-xilinx-zynqmp (5.4.0-1026.30) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1026.30 -proposed tracker (LP: #2026398)
+
+  [ Ubuntu: 5.4.0-155.172 ]
+
+  * focal/linux: 5.4.0-155.172 -proposed tracker (LP: #2026401)
+  * CVE-2023-3390
+    - netfilter: nf_tables: incorrect error path handling with NFT_MSG_NEWRULE
+  * CVE-2023-35001
+    - netfilter: nf_tables: prevent OOB access in nft_byteorder_eval
+  * CVE-2023-32629
+    - ovl: adhere to the vfs_ vs. ovl_do_ conventions for xattrs
+  * CVE-2023-3090
+    - ipvlan:Fix out-of-bounds caused by unclear skb->cb
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync update-dkms-versions helper
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Thu, 13 Jul 2023 10:31:41 +1000
+
+linux-xilinx-zynqmp (5.4.0-1025.29) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1025.29 -proposed tracker (LP: #2024105)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync update-dkms-versions helper
+
+  [ Ubuntu: 5.4.0-153.170 ]
+
+  * focal/linux: 5.4.0-153.170 -proposed tracker (LP: #2024108)
+  * cls_flower: off-by-one in fl_set_geneve_opt (LP: #2023577)
+    - net/sched: flower: fix possible OOB write in fl_set_geneve_opt()
+  * Some INVLPG implementations can leave Global translations unflushed when
+    PCIDs are enabled (LP: #2023220)
+    - x86/mm: Avoid incomplete Global INVLPG flushes
+
+  [ Ubuntu: 5.4.0-152.169 ]
+
+  * focal/linux: 5.4.0-152.169 -proposed tracker (LP: #2023070)
+  * Focal update: v5.4.236 upstream stable release (LP: #2020390)
+    - wifi: cfg80211: Partial revert "wifi: cfg80211: Fix use after free for wext"
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync git-ubuntu-log
+    - [Packaging] resync getabis
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Tue, 11 Jul 2023 08:48:45 +1000
+
+linux-xilinx-zynqmp (5.4.0-1024.28) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1024.28 -proposed tracker (LP: #2019372)
+
+  * Focal update: Focal update: v5.4.235 upstream stable release (LP: #2017706)
+    - [Config] update annotations for CONFIG_DRM_MXSFB
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync git-ubuntu-log
+    - [Packaging] resync getabis
+
+  [ Ubuntu: 5.4.0-151.168 ]
+
+  * focal/linux: 5.4.0-151.168 -proposed tracker (LP: #2019375)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update helper scripts
+    - debian/dkms-versions -- update from kernel-versions (main/2023.05.15)
+  * CVE-2023-32233
+    - netfilter: nf_tables: deactivate anonymous set from preparation phase
+  * CVE-2023-2612
+    - SAUCE: shiftfs: prevent lock unbalance in shiftfs_create_object()
+  * CVE-2023-31436
+    - net: sched: sch_qfq: prevent slab-out-of-bounds in qfq_activate_agg
+  * CVE-2023-1380
+    - wifi: brcmfmac: slab-out-of-bounds read in brcmf_get_assoc_ies()
+  * Focal update: Focal update: v5.4.235 upstream stable release (LP: #2017706)
+    - HID: asus: Remove check for same LED brightness on set
+    - HID: asus: use spinlock to protect concurrent accesses
+    - HID: asus: use spinlock to safely schedule workers
+    - ARM: OMAP2+: Fix memory leak in realtime_counter_init()
+    - arm64: dts: qcom: qcs404: use symbol names for PCIe resets
+    - ARM: zynq: Fix refcount leak in zynq_early_slcr_init
+    - arm64: dts: meson-gx: Fix Ethernet MAC address unit name
+    - arm64: dts: meson-g12a: Fix internal Ethernet PHY unit name
+    - arm64: dts: meson-gx: Fix the SCPI DVFS node name and unit address
+    - arm64: dts: meson: remove CPU opps below 1GHz for G12A boards
+    - ARM: OMAP1: call platform_device_put() in error case in
+      omap1_dm_timer_init()
+    - ARM: dts: exynos: correct wr-active property in Exynos3250 Rinato
+    - ARM: imx: Call ida_simple_remove() for ida_simple_get
+    - arm64: dts: amlogic: meson-gx: fix SCPI clock dvfs node name
+    - arm64: dts: amlogic: meson-axg: fix SCPI clock dvfs node name
+    - arm64: dts: amlogic: meson-gx: add missing SCPI sensors compatible
+    - arm64: dts: amlogic: meson-gx: add missing unit address to rng node name
+    - arm64: dts: amlogic: meson-gxl: add missing unit address to eth-phy-mux node
+      name
+    - arm64: dts: amlogic: meson-gxl-s905d-phicomm-n1: fix led node name
+    - ARM: dts: imx7s: correct iomuxc gpr mux controller cells
+    - arm64: dts: mediatek: mt7622: Add missing pwm-cells to pwm node
+    - Revert "scsi: core: run queue if SCSI device queue isn't ready and queue is
+      idle"
+    - block: Limit number of items taken from the I/O scheduler in one go
+    - blk-mq: remove stale comment for blk_mq_sched_mark_restart_hctx
+    - blk-mq: wait on correct sbitmap_queue in blk_mq_mark_tag_wait
+    - blk-mq: correct stale comment of .get_budget
+    - s390/dasd: Prepare for additional path event handling
+    - s390/dasd: Fix potential memleak in dasd_eckd_init()
+    - sched/deadline,rt: Remove unused parameter from pick_next_[rt|dl]_entity()
+    - sched/rt: pick_next_rt_entity(): check list_entry
+    - block: bio-integrity: Copy flags when bio_integrity_payload is cloned
+    - wifi: rsi: Fix memory leak in rsi_coex_attach()
+    - net/wireless: Delete unnecessary checks before the macro call
+      “dev_kfree_skb”
+    - wifi: iwlegacy: common: don't call dev_kfree_skb() under spin_lock_irqsave()
+    - wifi: libertas: fix memory leak in lbs_init_adapter()
+    - wifi: rtl8xxxu: don't call dev_kfree_skb() under spin_lock_irqsave()
+    - rtlwifi: fix -Wpointer-sign warning
+    - wifi: rtlwifi: Fix global-out-of-bounds bug in
+      _rtl8812ae_phy_set_txpower_limit()
+    - ipw2x00: switch from 'pci_' to 'dma_' API
+    - wifi: ipw2x00: don't call dev_kfree_skb() under spin_lock_irqsave()
+    - wifi: ipw2200: fix memory leak in ipw_wdev_init()
+    - wilc1000: let wilc_mac_xmit() return NETDEV_TX_OK
+    - wifi: wilc1000: fix potential memory leak in wilc_mac_xmit()
+    - wifi: brcmfmac: fix potential memory leak in brcmf_netdev_start_xmit()
+    - wifi: brcmfmac: unmap dma buffer in brcmf_msgbuf_alloc_pktid()
+    - wifi: libertas_tf: don't call kfree_skb() under spin_lock_irqsave()
+    - wifi: libertas: if_usb: don't call kfree_skb() under spin_lock_irqsave()
+    - wifi: libertas: main: don't call kfree_skb() under spin_lock_irqsave()
+    - wifi: libertas: cmdresp: don't call kfree_skb() under spin_lock_irqsave()
+    - wifi: wl3501_cs: don't call kfree_skb() under spin_lock_irqsave()
+    - crypto: x86/ghash - fix unaligned access in ghash_setkey()
+    - ACPICA: Drop port I/O validation for some regions
+    - genirq: Fix the return type of kstat_cpu_irqs_sum()
+    - lib/mpi: Fix buffer overrun when SG is too long
+    - ACPICA: nsrepair: handle cases without a return value correctly
+    - wifi: orinoco: check return value of hermes_write_wordrec()
+    - wifi: ath9k: htc_hst: free skb in ath9k_htc_rx_msg() if there is no callback
+      function
+    - ath9k: hif_usb: simplify if-if to if-else
+    - ath9k: htc: clean up statistics macros
+    - wifi: ath9k: hif_usb: clean up skbs if ath9k_hif_usb_rx_stream() fails
+    - wifi: ath9k: Fix potential stack-out-of-bounds write in
+      ath9k_wmi_rsp_callback()
+    - ACPI: battery: Fix missing NUL-termination with large strings
+    - crypto: ccp - Failure on re-initialization due to duplicate sysfs filename
+    - crypto: essiv - remove redundant null pointer check before kfree
+    - crypto: essiv - Handle EBUSY correctly
+    - crypto: seqiv - Handle EBUSY correctly
+    - powercap: fix possible name leak in powercap_register_zone()
+    - net/mlx5: Enhance debug print in page allocation failure
+    - irqchip/alpine-msi: Fix refcount leak in alpine_msix_init_domains
+    - irqchip/irq-mvebu-gicp: Fix refcount leak in mvebu_gicp_probe
+    - irqchip/ti-sci: Fix refcount leak in ti_sci_intr_irq_domain_probe
+    - mptcp: add sk_stop_timer_sync helper
+    - net: add sock_init_data_uid()
+    - tun: tun_chr_open(): correctly initialize socket uid
+    - tap: tap_open(): correctly initialize socket uid
+    - OPP: fix error checking in opp_migrate_dentry()
+    - Bluetooth: L2CAP: Fix potential user-after-free
+    - libbpf: Fix alen calculation in libbpf_nla_dump_errormsg()
+    - rds: rds_rm_zerocopy_callback() correct order for list_add_tail()
+    - crypto: rsa-pkcs1pad - Use akcipher_request_complete
+    - m68k: /proc/hardware should depend on PROC_FS
+    - RISC-V: time: initialize hrtimer based broadcast clock event device
+    - usb: gadget: udc: Avoid tasklet passing a global
+    - wifi: iwl3945: Add missing check for create_singlethread_workqueue
+    - wifi: iwl4965: Add missing check for create_singlethread_workqueue()
+    - wifi: mwifiex: fix loop iterator in mwifiex_update_ampdu_txwinsize()
+    - crypto: crypto4xx - Call dma_unmap_page when done
+    - wifi: mac80211: make rate u32 in sta_set_rate_info_rx()
+    - thermal/drivers/hisi: Drop second sensor hi3660
+    - can: esd_usb: Move mislocated storage of SJA1000_ECC_SEG bits in case of a
+      bus error
+    - irqchip/irq-brcmstb-l2: Set IRQ_LEVEL for level triggered interrupts
+    - irqchip/irq-bcm7120-l2: Set IRQ_LEVEL for level triggered interrupts
+    - selftests/net: Interpret UDP_GRO cmsg data as an int value
+    - drm/fourcc: Add missing big-endian XRGB1555 and RGB565 formats
+    - drm: mxsfb: DRM_MXSFB should depend on ARCH_MXS || ARCH_MXC
+    - drm/bridge: megachips: Fix error handling in i2c_register_driver()
+    - drm/vc4: dpi: Add option for inverting pixel clock and output enable
+    - drm/vc4: dpi: Fix format mapping for RGB565
+    - gpu: ipu-v3: common: Add of_node_put() for reference returned by
+      of_graph_get_port_by_id()
+    - drm/msm/hdmi: Add missing check for alloc_ordered_workqueue
+    - pinctrl: stm32: Fix refcount leak in stm32_pctrl_get_irq_domain
+    - ASoC: fsl_sai: initialize is_dsp_mode flag
+    - ALSA: hda/ca0132: minor fix for allocation size
+    - drm/mipi-dsi: Fix byte order of 16-bit DCS set/get brightness
+    - drm/msm: use strscpy instead of strncpy
+    - drm/msm/dpu: Add check for cstate
+    - drm/msm/dpu: Add check for pstates
+    - drm/exynos: Don't reset bridge->next
+    - drm/bridge: Rename bridge helpers targeting a bridge chain
+    - drm/bridge: Introduce drm_bridge_get_next_bridge()
+    - drm: Initialize struct drm_crtc_state.no_vblank from device settings
+    - drm/msm/mdp5: Add check for kzalloc
+    - gpu: host1x: Don't skip assigning syncpoints to channels
+    - drm/mediatek: remove cast to pointers passed to kfree
+    - drm/mediatek: Use NULL instead of 0 for NULL pointer
+    - drm/mediatek: Drop unbalanced obj unref
+    - drm/mediatek: Clean dangling pointer on bind error path
+    - ASoC: soc-compress.c: fixup private_data on snd_soc_new_compress()
+    - gpio: vf610: connect GPIO label to dev name
+    - hwmon: (ltc2945) Handle error case in ltc2945_value_store
+    - scsi: aic94xx: Add missing check for dma_map_single()
+    - spi: bcm63xx-hsspi: fix pm_runtime
+    - spi: bcm63xx-hsspi: Fix multi-bit mode setting
+    - hwmon: (mlxreg-fan) Return zero speed for broken fan
+    - dm: remove flush_scheduled_work() during local_exit()
+    - spi: synquacer: Fix timeout handling in synquacer_spi_transfer_one()
+    - ASoC: dapm: declare missing structure prototypes
+    - ASoC: soc-dapm.h: fixup warning struct snd_pcm_substream not declared
+    - HID: bigben: use spinlock to protect concurrent accesses
+    - HID: bigben_worker() remove unneeded check on report_field
+    - HID: bigben: use spinlock to safely schedule workers
+    - HID: asus: Only set EV_REP if we are adding a mapping
+    - HID: asus: Add report_size to struct asus_touchpad_info
+    - HID: asus: Add support for multi-touch touchpad on Medion Akoya E1239T
+    - HID: asus: Fix mute and touchpad-toggle keys on Medion Akoya E1239T
+    - hid: bigben_probe(): validate report count
+    - nfsd: fix race to check ls_layouts
+    - cifs: Fix lost destroy smbd connection when MR allocate failed
+    - cifs: Fix warning and UAF when destroy the MR list
+    - gfs2: jdata writepage fix
+    - perf llvm: Fix inadvertent file creation
+    - perf tools: Fix auto-complete on aarch64
+    - sparc: allow PM configs for sparc32 COMPILE_TEST
+    - mfd: pcf50633-adc: Fix potential memleak in pcf50633_adc_async_read()
+    - clk: qcom: gcc-qcs404: disable gpll[04]_out_aux parents
+    - clk: qcom: gcc-qcs404: fix names of the DSI clocks used as parents
+    - mtd: rawnand: sunxi: Fix the size of the last OOB region
+    - clk: renesas: cpg-mssr: Fix use after free if cpg_mssr_common_init() failed
+    - clk: renesas: cpg-mssr: Use enum clk_reg_layout instead of a boolean flag
+    - clk: renesas: cpg-mssr: Remove superfluous check in resume code
+    - Input: ads7846 - don't report pressure for ads7845
+    - Input: ads7846 - don't check penirq immediately for 7845
+    - clk: qcom: gpucc-sdm845: fix clk_dis_wait being programmed for CX GDSC
+    - powerpc/powernv/ioda: Skip unallocated resources when mapping to PE
+    - clk: Honor CLK_OPS_PARENT_ENABLE in clk_core_is_enabled()
+    - powerpc/pseries/lpar: add missing RTAS retry status handling
+    - powerpc/pseries/lparcfg: add missing RTAS retry status handling
+    - powerpc/rtas: make all exports GPL
+    - powerpc/rtas: ensure 4KB alignment for rtas_data_buf
+    - powerpc/eeh: Small refactor of eeh_handle_normal_event()
+    - powerpc/eeh: Set channel state after notifying the drivers
+    - MIPS: SMP-CPS: fix build error when HOTPLUG_CPU not set
+    - MIPS: vpe-mt: drop physical_memsize
+    - remoteproc: qcom_q6v5_mss: Use a carveout to authenticate modem headers
+    - media: platform: ti: Add missing check for devm_regulator_get
+    - powerpc: Remove linker flag from KBUILD_AFLAGS
+    - media: ov5675: Fix memleak in ov5675_init_controls()
+    - media: i2c: ov772x: Fix memleak in ov772x_probe()
+    - media: i2c: ov7670: 0 instead of -EINVAL was returned
+    - media: usb: siano: Fix use after free bugs caused by do_submit_urb
+    - rpmsg: glink: Avoid infinite loop on intent for missing channel
+    - udf: Define EFSCORRUPTED error code
+    - ARM: dts: exynos: Use Exynos5420 compatible for the MIPI video phy
+    - blk-iocost: fix divide by 0 error in calc_lcoefs()
+    - wifi: brcmfmac: Fix potential stack-out-of-bounds in brcmf_c_preinit_dcmds()
+    - rcu: Suppress smp_processor_id() complaint in
+      synchronize_rcu_expedited_wait()
+    - thermal: intel: Fix unsigned comparison with less than zero
+    - timers: Prevent union confusion from unexpected restart_syscall()
+    - x86/bugs: Reset speculation control settings on init
+    - wifi: brcmfmac: ensure CLM version is null-terminated to prevent stack-out-
+      of-bounds
+    - wifi: mt7601u: fix an integer underflow
+    - inet: fix fast path in __inet_hash_connect()
+    - ice: add missing checks for PF vsi type
+    - ACPI: Don't build ACPICA with '-Os'
+    - net: bcmgenet: Add a check for oversized packets
+    - m68k: Check syscall_trace_enter() return code
+    - wifi: mt76: dma: free rx_head in mt76_dma_rx_cleanup
+    - ACPI: video: Fix Lenovo Ideapad Z570 DMI match
+    - net/mlx5: fw_tracer: Fix debug print
+    - coda: Avoid partial allocation of sig_inputArgs
+    - uaccess: Add minimum bounds check on kernel buffer size
+    - drm/amd/display: Fix potential null-deref in dm_resume
+    - drm/omap: dsi: Fix excessive stack usage
+    - HID: Add Mapping for System Microphone Mute
+    - drm/radeon: free iio for atombios when driver shutdown
+    - drm/msm/dsi: Add missing check for alloc_ordered_workqueue
+    - docs/scripts/gdb: add necessary make scripts_gdb step
+    - ASoC: kirkwood: Iterate over array indexes instead of using pointer math
+    - regulator: max77802: Bounds check regulator id against opmode
+    - regulator: s5m8767: Bounds check id indexing into arrays
+    - hwmon: (coretemp) Simplify platform device handling
+    - pinctrl: at91: use devm_kasprintf() to avoid potential leaks
+    - drm: panel-orientation-quirks: Add quirk for Lenovo IdeaPad Duet 3 10IGL5
+    - dm thin: add cond_resched() to various workqueue loops
+    - dm cache: add cond_resched() to various workqueue loops
+    - nfsd: zero out pointers after putting nfsd_files on COPY setup error
+    - wifi: rtl8xxxu: fixing transmisison failure for rtl8192eu
+    - firmware: coreboot: framebuffer: Ignore reserved pixel color bits
+    - rtc: pm8xxx: fix set-alarm race
+    - ipmi_ssif: Rename idle state and check
+    - s390: discard .interp section
+    - s390/kprobes: fix irq mask clobbering on kprobe reenter from post_handler
+    - s390/kprobes: fix current_kprobe never cleared after kprobes reenter
+    - ARM: dts: exynos: correct HDMI phy compatible in Exynos4
+    - hfs: fix missing hfs_bnode_get() in __hfs_bnode_create
+    - fs: hfsplus: fix UAF issue in hfsplus_put_super
+    - f2fs: fix information leak in f2fs_move_inline_dirents()
+    - f2fs: fix cgroup writeback accounting with fs-layer encryption
+    - ocfs2: fix defrag path triggering jbd2 ASSERT
+    - ocfs2: fix non-auto defrag path not working issue
+    - udf: Truncate added extents on failed expansion
+    - udf: Do not bother merging very long extents
+    - udf: Do not update file length for failed writes to inline files
+    - udf: Preserve link count of system files
+    - udf: Detect system inodes linked into directory hierarchy
+    - udf: Fix file corruption when appending just after end of preallocated
+      extent
+    - KVM: Destroy target device if coalesced MMIO unregistration fails
+    - KVM: s390: disable migration mode when dirty tracking is disabled
+    - x86/virt: Force GIF=1 prior to disabling SVM (for reboot flows)
+    - x86/crash: Disable virt in core NMI crash handler to avoid double shootdown
+    - x86/reboot: Disable virtualization in an emergency if SVM is supported
+    - x86/reboot: Disable SVM, not just VMX, when stopping CPUs
+    - x86/kprobes: Fix __recover_optprobed_insn check optimizing logic
+    - x86/kprobes: Fix arch_check_optimized_kprobe check within optimized_kprobe
+      range
+    - x86/microcode/amd: Remove load_microcode_amd()'s bsp parameter
+    - x86/microcode/AMD: Add a @cpu parameter to the reloading functions
+    - x86/microcode/AMD: Fix mixed steppings support
+    - x86/speculation: Allow enabling STIBP with legacy IBRS
+    - Documentation/hw-vuln: Document the interaction between IBRS and STIBP
+    - ima: Align ima_file_mmap() parameters with mmap_file LSM hook
+    - irqdomain: Fix association race
+    - irqdomain: Fix disassociation race
+    - irqdomain: Drop bogus fwspec-mapping error handling
+    - ALSA: ice1712: Do not left ice->gpio_mutex locked in aureon_add_controls()
+    - ALSA: hda/realtek: Add quirk for HP EliteDesk 800 G6 Tower PC
+    - ext4: optimize ea_inode block expansion
+    - ext4: refuse to create ea block when umounted
+    - wifi: rtl8xxxu: Use a longer retry limit of 48
+    - wifi: cfg80211: Fix use after free for wext
+    - thermal: intel: powerclamp: Fix cur_state for multi package system
+    - dm flakey: fix logic when corrupting a bio
+    - dm flakey: don't corrupt the zero page
+    - ARM: dts: exynos: correct TMU phandle in Exynos4
+    - ARM: dts: exynos: correct TMU phandle in Odroid XU
+    - rbd: avoid use-after-free in do_rbd_add() when rbd_dev_create() fails
+    - alpha: fix FEN fault handling
+    - mips: fix syscall_get_nr
+    - media: ipu3-cio2: Fix PM runtime usage_count in driver unbind
+    - mm: memcontrol: deprecate charge moving
+    - mm/thp: check and bail out if page in deferred queue already
+    - ktest.pl: Give back console on Ctrt^C on monitor
+    - ktest.pl: Fix missing "end_monitor" when machine check fails
+    - ktest.pl: Add RUN_TIMEOUT option with default unlimited
+    - scsi: qla2xxx: Fix link failure in NPIV environment
+    - scsi: qla2xxx: Fix DMA-API call trace on NVMe LS requests
+    - scsi: qla2xxx: Fix erroneous link down
+    - scsi: ses: Don't attach if enclosure has no components
+    - scsi: ses: Fix slab-out-of-bounds in ses_enclosure_data_process()
+    - scsi: ses: Fix possible addl_desc_ptr out-of-bounds accesses
+    - scsi: ses: Fix possible desc_ptr out-of-bounds accesses
+    - scsi: ses: Fix slab-out-of-bounds in ses_intf_remove()
+    - PCI/PM: Observe reset delay irrespective of bridge_d3
+    - PCI: hotplug: Allow marking devices as disconnected during bind/unbind
+    - PCI: Avoid FLR for AMD FCH AHCI adapters
+    - drm/i915/quirks: Add inverted backlight quirk for HP 14-r206nv
+    - drm/radeon: Fix eDP for single-display iMac11,2
+    - wifi: ath9k: use proper statements in conditionals
+    - kbuild: Port silent mode detection to future gnu make.
+    - fs/jfs: fix shift exponent db_agl2size negative
+    - pwm: sifive: Reduce time the controller lock is held
+    - pwm: sifive: Always let the first pwm_apply_state succeed
+    - pwm: stm32-lp: fix the check on arr and cmp registers update
+    - f2fs: use memcpy_{to,from}_page() where possible
+    - fs: f2fs: initialize fsdata in pagecache_write()
+    - um: vector: Fix memory leak in vector_config
+    - ubi: ensure that VID header offset + VID header size <= alloc, size
+    - ubifs: Fix build errors as symbol undefined
+    - ubifs: Rectify space budget for ubifs_symlink() if symlink is encrypted
+    - ubifs: Rectify space budget for ubifs_xrename()
+    - ubifs: Fix wrong dirty space budget for dirty inode
+    - ubifs: do_rename: Fix wrong space budget when target inode's nlink > 1
+    - ubifs: Reserve one leb for each journal head while doing budget
+    - ubi: Fix use-after-free when volume resizing failed
+    - ubi: Fix unreferenced object reported by kmemleak in ubi_resize_volume()
+    - ubifs: Fix memory leak in alloc_wbufs()
+    - ubi: Fix possible null-ptr-deref in ubi_free_volume()
+    - ubifs: Re-statistic cleaned znode count if commit failed
+    - ubifs: dirty_cow_znode: Fix memleak in error handling path
+    - ubifs: ubifs_writepage: Mark page dirty after writing inode failed
+    - ubi: Fix UAF wear-leveling entry in eraseblk_count_seq_show()
+    - ubi: ubi_wl_put_peb: Fix infinite loop when wear-leveling work failed
+    - x86: um: vdso: Add '%rcx' and '%r11' to the syscall clobber list
+    - watchdog: at91sam9_wdt: use devm_request_irq to avoid missing free_irq() in
+      error path
+    - watchdog: Fix kmemleak in watchdog_cdev_register
+    - watchdog: pcwd_usb: Fix attempting to access uninitialized memory
+    - netfilter: ctnetlink: fix possible refcount leak in
+      ctnetlink_create_conntrack()
+    - ipv6: Add lwtunnel encap size of all siblings in nexthop calculation
+    - sctp: add a refcnt in sctp_stream_priorities to avoid a nested loop
+    - net: fix __dev_kfree_skb_any() vs drop monitor
+    - 9p/xen: fix version parsing
+    - 9p/xen: fix connection sequence
+    - 9p/rdma: unmap receive dma buffer in rdma_request()/post_recv()
+    - net/mlx5: Geneve, Fix handling of Geneve object id as error code
+    - nfc: fix memory leak of se_io context in nfc_genl_se_io
+    - net/sched: act_sample: fix action bind logic
+    - ARM: dts: spear320-hmi: correct STMPE GPIO compatible
+    - tcp: tcp_check_req() can be called from process context
+    - vc_screen: modify vcs_size() handling in vcs_read()
+    - rtc: sun6i: Make external 32k oscillator optional
+    - rtc: sun6i: Always export the internal oscillator
+    - scsi: ipr: Work around fortify-string warning
+    - thermal: intel: quark_dts: fix error pointer dereference
+    - thermal: intel: BXT_PMIC: select REGMAP instead of depending on it
+    - tracing: Add NULL checks for buffer in ring_buffer_free_read_page()
+    - firmware/efi sysfb_efi: Add quirk for Lenovo IdeaPad Duet 3
+    - mfd: arizona: Use pm_runtime_resume_and_get() to prevent refcnt leak
+    - media: uvcvideo: Handle cameras with invalid descriptors
+    - media: uvcvideo: Handle errors from calls to usb_string
+    - media: uvcvideo: Quirk for autosuspend in Logitech B910 and C910
+    - media: uvcvideo: Silence memcpy() run-time false positive warnings
+    - staging: emxx_udc: Add checks for dma_alloc_coherent()
+    - tty: fix out-of-bounds access in tty_driver_lookup_tty()
+    - tty: serial: fsl_lpuart: disable the CTS when send break signal
+    - mei: bus-fixup:upon error print return values of send and receive
+    - tools/iio/iio_utils:fix memory leak
+    - iio: accel: mma9551_core: Prevent uninitialized variable in
+      mma9551_read_status_word()
+    - iio: accel: mma9551_core: Prevent uninitialized variable in
+      mma9551_read_config_word()
+    - usb: host: xhci: mvebu: Iterate over array indexes instead of using pointer
+      math
+    - USB: ene_usb6250: Allocate enough memory for full object
+    - usb: uvc: Enumerate valid values for color matching
+    - kernel/fail_function: fix memory leak with using debugfs_lookup()
+    - PCI: Add ACS quirk for Wangxun NICs
+    - phy: rockchip-typec: Fix unsigned comparison with less than zero
+    - net: tls: avoid hanging tasks on the tx_lock
+    - x86/resctrl: Apply READ_ONCE/WRITE_ONCE to task_struct.{rmid,closid}
+    - x86/resctl: fix scheduler confusion with 'current'
+    - Bluetooth: hci_sock: purge socket queues in the destruct() callback
+    - SAUCE: Revert "UBUNTU: SAUCE: Fix inet_csk_listen_start after CVE-2023-0461"
+    - tcp: Fix listen() regression in 5.4.229.
+    - media: uvcvideo: Provide sync and async uvc_ctrl_status_event
+    - media: uvcvideo: Fix race condition with usb_kill_urb
+    - dt-bindings: rtc: sun6i-a31-rtc: Loosen the requirements on the clocks
+    - Linux 5.4.235
+    - [Config] Drop mxsfb for armhf:generic-lpae
+  * Focal update: v5.4.234 upstream stable release (LP: #2017691)
+    - arm64: dts: rockchip: drop unused LED mode property from rk3328-roc-cc
+    - ARM: dts: rockchip: add power-domains property to dp node on rk3288
+    - ACPI: NFIT: fix a potential deadlock during NFIT teardown
+    - btrfs: send: limit number of clones and allocated memory size
+    - IB/hfi1: Assign npages earlier
+    - neigh: make sure used and confirmed times are valid
+    - HID: core: Fix deadloop in hid_apply_multiplier.
+    - bpf: bpf_fib_lookup should not return neigh in NUD_FAILED state
+    - net: Remove WARN_ON_ONCE(sk->sk_forward_alloc) from sk_stream_kill_queues().
+    - vc_screen: don't clobber return value in vcs_read
+    - dmaengine: sh: rcar-dmac: Check for error num after dma_set_max_seg_size
+    - USB: serial: option: add support for VW/Skoda "Carstick LTE"
+    - USB: core: Don't hold device lock while reading the "descriptors" sysfs file
+    - Linux 5.4.234
+  * CVE-2023-30456
+    - KVM: nVMX: add missing consistency checks for CR0 and CR4
+  * CVE-2023-1859
+    - 9p/xen : Fix use after free bug in xen_9pfs_front_remove due to race
+      condition
+  * CVE-2023-1670
+    - xirc2ps_cs: Fix use after free bug in xirc2ps_detach
+
+  [ Ubuntu: 5.4.0-149.166 ]
+
+  * focal/linux: 5.4.0-149.166 -proposed tracker (LP: #2016591)
+  * Focal update: v5.4.233 upstream stable release (LP: #2015909)
+    - dma-mapping: add generic helpers for mapping sgtable objects
+    - scatterlist: add generic wrappers for iterating over sgtable objects
+    - drm: etnaviv: fix common struct sg_table related issues
+    - drm/etnaviv: don't truncate physical page address
+    - wifi: rtl8xxxu: gen2: Turn on the rate control
+    - powerpc: dts: t208x: Mark MAC1 and MAC2 as 10G
+    - random: always mix cycle counter in add_latent_entropy()
+    - KVM: x86: Fail emulation during EMULTYPE_SKIP on any exception
+    - can: kvaser_usb: hydra: help gcc-13 to figure out cmd_len
+    - powerpc: dts: t208x: Disable 10G on MAC1 and MAC2
+    - alarmtimer: Prevent starvation by small intervals and SIG_IGN
+    - drm/i915/gvt: fix double free bug in split_2MB_gtt_entry
+    - mac80211: mesh: embedd mesh_paths and mpp_paths into ieee80211_if_mesh
+    - uaccess: Add speculation barrier to copy_from_user()
+    - wifi: mwifiex: Add missing compatible string for SD8787
+    - ext4: Fix function prototype mismatch for ext4_feat_ktype
+    - Revert "net/sched: taprio: make qdisc_leaf() see the per-netdev-queue pfifo
+      child qdiscs"
+    - bpf: add missing header file include
+    - Linux 5.4.233
+  *  selftest: fib_tests: Always cleanup before exit  (LP: #2015956)
+    - selftest: fib_tests: Always cleanup before exit
+  * fib_tests.sh in ubuntu_kernel_selftests was skipped silently on Focal
+    (LP: #2015440)
+    - selftests: Fix the executable permissions for fib_tests.sh
+  * Debian autoreconstruct Fix restoration of execute permissions (LP: #2015498)
+    - [Debian] autoreconstruct - fix restoration of execute permissions
+  * kernel: fix __clear_user() inline assembly constraints (LP: #2013088)
+    - s390/uaccess: add missing earlyclobber annotations to __clear_user()
+  * i/o error if next unused loop device is queried (LP: #1856871)
+    - loop: fix I/O error on fsync() in detached loop devices
+  * CVE-2023-1075
+    - net/tls: tls_is_tx_ready() checked list_entry
+  * Focal update: v5.4.232 upstream stable release (LP: #2011625)
+    - firewire: fix memory leak for payload of request subaction to IEC 61883-1
+      FCP region
+    - bus: sunxi-rsb: Fix error handling in sunxi_rsb_init()
+    - ASoC: Intel: bytcr_rt5651: Drop reference count of ACPI device after use
+    - ALSA: hda/via: Avoid potential array out-of-bound in add_secret_dac_path()
+    - arm64: dts: imx8mm: Fix pad control for UART1_DTE_RX
+    - scsi: Revert "scsi: core: map PQ=1, PDT=other values to
+      SCSI_SCAN_TARGET_PRESENT"
+    - WRITE is "data source", not destination...
+    - fix iov_iter_bvec() "direction" argument
+    - fix "direction" argument of iov_iter_kvec()
+    - netrom: Fix use-after-free caused by accept on already connected socket
+    - netfilter: br_netfilter: disable sabotage_in hook after first suppression
+    - squashfs: harden sanity check in squashfs_read_xattr_id_table
+    - net: phy: meson-gxl: Add generic dummy stubs for MMD register access
+    - can: j1939: fix errant WARN_ON_ONCE in j1939_session_deactivate
+    - ata: libata: Fix sata_down_spd_limit() when no link speed is reported
+    - selftests: net: udpgso_bench_rx: Fix 'used uninitialized' compiler warning
+    - selftests: net: udpgso_bench_rx/tx: Stop when wrong CLI args are provided
+    - selftests: net: udpgso_bench_tx: Cater for pending datagrams zerocopy
+      benchmarking
+    - virtio-net: Keep stop() to follow mirror sequence of open()
+    - net: openvswitch: fix flow memory leak in ovs_flow_cmd_new
+    - efi: fix potential NULL deref in efi_mem_reserve_persistent
+    - scsi: target: core: Fix warning on RT kernels
+    - scsi: iscsi_tcp: Fix UAF during login when accessing the shost ipaddress
+    - i2c: rk3x: fix a bunch of kernel-doc warnings
+    - net/x25: Fix to not accept on connected socket
+    - iio: adc: stm32-dfsdm: fill module aliases
+    - usb: dwc3: dwc3-qcom: Fix typo in the dwc3 vbus override API
+    - usb: dwc3: qcom: enable vbus override when in OTG dr-mode
+    - usb: gadget: f_fs: Fix unbalanced spinlock in __ffs_ep0_queue_wait
+    - vc_screen: move load of struct vc_data pointer in vcs_read() to avoid UAF
+    - Input: i8042 - move __initconst to fix code styling warning
+    - Input: i8042 - merge quirk tables
+    - Input: i8042 - add TUXEDO devices to i8042 quirk tables
+    - Input: i8042 - add Clevo PCX0DX to i8042 quirk table
+    - fbcon: Check font dimension limits
+    - watchdog: diag288_wdt: do not use stack buffers for hardware data
+    - watchdog: diag288_wdt: fix __diag288() inline assembly
+    - efi: Accept version 2 of memory attributes table
+    - iio: hid: fix the retval in accel_3d_capture_sample
+    - iio: adc: berlin2-adc: Add missing of_node_put() in error path
+    - iio:adc:twl6030: Enable measurements of VUSB, VBAT and others
+    - parisc: Fix return code of pdc_iodc_print()
+    - parisc: Wire up PTRACE_GETREGS/PTRACE_SETREGS for compat case
+    - riscv: disable generation of unwind tables
+    - mm: hugetlb: proc: check for hugetlb shared PMD in /proc/PID/smaps
+    - fpga: stratix10-soc: Fix return value check in s10_ops_write_init()
+    - mm/swapfile: add cond_resched() in get_swap_pages()
+    - Squashfs: fix handling and sanity checking of xattr_ids count
+    - nvmem: core: fix cell removal on error
+    - mm: swap: properly update readahead statistics in unuse_pte_range()
+    - xprtrdma: Fix regbuf data not freed in rpcrdma_req_create()
+    - serial: 8250_dma: Fix DMA Rx completion race
+    - serial: 8250_dma: Fix DMA Rx rearm race
+    - powerpc/imc-pmu: Revert nest_init_lock to being a mutex
+    - fbdev: smscufx: fix error handling code in ufx_usb_probe
+    - f2fs: fix to do sanity check on i_extra_isize in is_alive()
+    - wifi: brcmfmac: Check the count value of channel spec to prevent out-of-
+      bounds reads
+    - iio:adc:twl6030: Enable measurement of VAC
+    - btrfs: limit device extents to the device size
+    - btrfs: zlib: zero-initialize zlib workspace
+    - ALSA: emux: Avoid potential array out-of-bound in snd_emux_xg_control()
+    - tracing: Fix poll() and select() do not work on per_cpu trace_pipe and
+      trace_pipe_raw
+    - can: j1939: do not wait 250 ms if the same addr was already claimed
+    - IB/hfi1: Restore allocated resources on failed copyout
+    - IB/IPoIB: Fix legacy IPoIB due to wrong number of queues
+    - iommu: Add gfp parameter to iommu_ops::map
+    - RDMA/usnic: use iommu_map_atomic() under spin_lock()
+    - xfrm: fix bug with DSCP copy to v6 from v4 tunnel
+    - bonding: fix error checking in bond_debug_reregister()
+    - net: phy: meson-gxl: use MMD access dummy stubs for GXL, internal PHY
+    - ionic: clean interrupt before enabling queue to avoid credit race
+    - ice: Do not use WQ_MEM_RECLAIM flag for workqueue
+    - rds: rds_rm_zerocopy_callback() use list_first_entry()
+    - selftests: forwarding: lib: quote the sysctl values
+    - ALSA: pci: lx6464es: fix a debug loop
+    - pinctrl: aspeed: Fix confusing types in return value
+    - pinctrl: single: fix potential NULL dereference
+    - pinctrl: intel: Restore the pins that used to be in Direct IRQ mode
+    - net: USB: Fix wrong-direction WARNING in plusb.c
+    - usb: core: add quirk for Alcor Link AK9563 smartcard reader
+    - usb: typec: altmodes/displayport: Fix probe pin assign check
+    - ceph: flush cap releases when the session is flushed
+    - riscv: Fixup race condition on PG_dcache_clean in flush_icache_pte
+    - arm64: dts: meson-gx: Make mmc host controller interrupts level-sensitive
+    - arm64: dts: meson-g12-common: Make mmc host controller interrupts level-
+      sensitive
+    - arm64: dts: meson-axg: Make mmc host controller interrupts level-sensitive
+    - nvme-pci: Move enumeration by class to be last in the table
+    - bpf: Always return target ifindex in bpf_fib_lookup
+    - migrate: hugetlb: check for hugetlb shared PMD in node migration
+    - selftests/bpf: Verify copy_register_state() preserves parent/live fields
+    - ASoC: cs42l56: fix DT probe
+    - tools/virtio: fix the vringh test for virtio ring changes
+    - net/rose: Fix to not accept on connected socket
+    - net: stmmac: do not stop RX_CLK in Rx LPI state for qcs404 SoC
+    - net: sched: sch: Bounds check priority
+    - s390/decompressor: specify __decompress() buf len to avoid overflow
+    - nvme-fc: fix a missing queue put in nvmet_fc_ls_create_association
+    - aio: fix mremap after fork null-deref
+    - btrfs: free device in btrfs_close_devices for a single device filesystem
+    - netfilter: nft_tproxy: restrict to prerouting hook
+    - xfs: remove the xfs_efi_log_item_t typedef
+    - xfs: remove the xfs_efd_log_item_t typedef
+    - xfs: remove the xfs_inode_log_item_t typedef
+    - xfs: factor out a xfs_defer_create_intent helper
+    - xfs: merge the ->log_item defer op into ->create_intent
+    - xfs: merge the ->diff_items defer op into ->create_intent
+    - xfs: turn dfp_intent into a xfs_log_item
+    - xfs: refactor xfs_defer_finish_noroll
+    - xfs: log new intent items created as part of finishing recovered intent
+      items
+    - xfs: fix finobt btree block recovery ordering
+    - xfs: proper replay of deferred ops queued during log recovery
+    - xfs: xfs_defer_capture should absorb remaining block reservations
+    - xfs: xfs_defer_capture should absorb remaining transaction reservation
+    - xfs: clean up bmap intent item recovery checking
+    - xfs: clean up xfs_bui_item_recover iget/trans_alloc/ilock ordering
+    - xfs: fix an incore inode UAF in xfs_bui_recover
+    - xfs: change the order in which child and parent defer ops are finished
+    - xfs: periodically relog deferred intent items
+    - xfs: expose the log push threshold
+    - xfs: only relog deferred intent items if free space in the log gets low
+    - xfs: fix missing CoW blocks writeback conversion retry
+    - xfs: ensure inobt record walks always make forward progress
+    - xfs: fix the forward progress assertion in xfs_iwalk_run_callbacks
+    - xfs: prevent UAF in xfs_log_item_in_current_chkpt
+    - xfs: sync lazy sb accounting on quiesce of read-only mounts
+    - Revert "ipv4: Fix incorrect route flushing when source address is deleted"
+    - ipv4: Fix incorrect route flushing when source address is deleted
+    - mmc: sdio: fix possible resource leaks in some error paths
+    - mmc: mmc_spi: fix error handling in mmc_spi_probe()
+    - ALSA: hda/conexant: add a new hda codec SN6180
+    - ALSA: hda/realtek - fixed wrong gpio assigned
+    - sched/psi: Fix use-after-free in ep_remove_wait_queue()
+    - hugetlb: check for undefined shift on 32 bit architectures
+    - Revert "mm: Always release pages to the buddy allocator in
+      memblock_free_late()."
+    - net: Fix unwanted sign extension in netdev_stats_to_stats64()
+    - revert "squashfs: harden sanity check in squashfs_read_xattr_id_table"
+    - ixgbe: allow to increase MTU to 3K with XDP enabled
+    - i40e: add double of VLAN header when computing the max MTU
+    - net: bgmac: fix BCM5358 support by setting correct flags
+    - sctp: sctp_sock_filter(): avoid list_entry() on possibly empty list
+    - dccp/tcp: Avoid negative sk_forward_alloc by ipv6_pinfo.pktoptions.
+    - net/usb: kalmia: Don't pass act_len in usb_bulk_msg error path
+    - net: stmmac: fix order of dwmac5 FlexPPS parametrization sequence
+    - bnxt_en: Fix mqprio and XDP ring checking logic
+    - net: stmmac: Restrict warning on disabling DMA store and fwd mode
+    - ixgbe: add double of VLAN header when computing the max MTU
+    - ipv6: Fix datagram socket connection with DSCP.
+    - ipv6: Fix tcp socket connection with DSCP.
+    - i40e: Add checking for null for nlmsg_find_attr()
+    - kvm: initialize all of the kvm_debugregs structure before sending it to
+      userspace
+    - nilfs2: fix underflow in second superblock position calculations
+    - ASoC: SOF: Intel: hda-dai: fix possible stream_tag leak
+    - net: sched: sch: Fix off by one in htb_activate_prios()
+    - iommu/amd: Pass gfp flags to iommu_map_page() in amd_iommu_map()
+    - Linux 5.4.232
+  * CVE-2023-1118
+    - media: rc: Fix use-after-free bugs caused by ene_tx_irqsim()
+
+  [ Ubuntu: 5.4.0-148.165 ]
+
+  * focal/linux: 5.4.0-148.165 -proposed tracker (LP: #2016777)
+  * CVE-2023-1829
+    - net/sched: Retire tcindex classifier
+    - [Config]: Make sure CONFIG_NET_CLS_TCINDEX is not available
+
+  [ Ubuntu: 5.4.0-147.164 ]
+
+  * focal/linux: 5.4.0-147.164 -proposed tracker (LP: #2011959)
+  * CVE-2023-26545
+    - net: mpls: fix stale pointer if allocation fails during device rename
+  * CVE-2023-1281
+    - rcu: Upgrade rcu_swap_protected() to rcu_replace_pointer()
+    - net/sched: tcindex: update imperfect hash filters respecting rcu
+  * Focal update: v5.4.231 upstream stable release (LP: #2011226)
+    - clk: generalize devm_clk_get() a bit
+    - clk: Provide new devm_clk helpers for prepared and enabled clocks
+    - memory: atmel-sdramc: Fix missing clk_disable_unprepare in
+      atmel_ramc_probe()
+    - memory: mvebu-devbus: Fix missing clk_disable_unprepare in
+      mvebu_devbus_probe()
+    - ARM: dts: imx6qdl-gw560x: Remove incorrect 'uart-has-rtscts'
+    - ARM: imx27: Retrieve the SYSCTRL base address from devicetree
+    - ARM: imx31: Retrieve the IIM base address from devicetree
+    - ARM: imx35: Retrieve the IIM base address from devicetree
+    - ARM: imx: add missing of_node_put()
+    - HID: intel_ish-hid: Add check for ishtp_dma_tx_map
+    - EDAC/highbank: Fix memory leak in highbank_mc_probe()
+    - tomoyo: fix broken dependency on *.conf.default
+    - RDMA/core: Fix ib block iterator counter overflow
+    - IB/hfi1: Reject a zero-length user expected buffer
+    - IB/hfi1: Reserve user expected TIDs
+    - IB/hfi1: Fix expected receive setup error exit issues
+    - affs: initialize fsdata in affs_truncate()
+    - amd-xgbe: TX Flow Ctrl Registers are h/w ver dependent
+    - amd-xgbe: Delay AN timeout during KR training
+    - bpf: Fix pointer-leak due to insufficient speculative store bypass
+      mitigation
+    - phy: rockchip-inno-usb2: Fix missing clk_disable_unprepare() in
+      rockchip_usb2phy_power_on()
+    - net: nfc: Fix use-after-free in local_cleanup()
+    - net: wan: Add checks for NULL for utdm in undo_uhdlc_init and unmap_si_regs
+    - gpio: mxc: Always set GPIOs used as interrupt source to INPUT mode
+    - net/sched: sch_taprio: fix possible use-after-free
+    - net: fix a concurrency bug in l2tp_tunnel_register()
+    - l2tp: Serialize access to sk_user_data with sk_callback_lock
+    - l2tp: Don't sleep and disable BH under writer-side sk_callback_lock
+    - net: usb: sr9700: Handle negative len
+    - net: mdio: validate parameter addr in mdiobus_get_phy()
+    - HID: check empty report_list in hid_validate_values()
+    - HID: check empty report_list in bigben_probe()
+    - net: stmmac: fix invalid call to mdiobus_get_phy()
+    - HID: revert CHERRY_MOUSE_000C quirk
+    - usb: gadget: f_fs: Prevent race during ffs_ep0_queue_wait
+    - usb: gadget: f_fs: Ensure ep0req is dequeued before free_request
+    - net: mlx5: eliminate anonymous module_init & module_exit
+    - drm/panfrost: fix GENERIC_ATOMIC64 dependency
+    - dmaengine: Fix double increment of client_count in dma_chan_get()
+    - net: macb: fix PTP TX timestamp failure due to packet padding
+    - HID: betop: check shape of output reports
+    - dmaengine: xilinx_dma: use devm_platform_ioremap_resource()
+    - dmaengine: xilinx_dma: Fix devm_platform_ioremap_resource error handling
+    - dmaengine: xilinx_dma: call of_node_put() when breaking out of
+      for_each_child_of_node()
+    - tcp: avoid the lookup process failing to get sk in ehash table
+    - w1: fix deadloop in __w1_remove_master_device()
+    - w1: fix WARNING after calling w1_process()
+    - driver core: Fix test_async_probe_init saves device in wrong array
+    - net: dsa: microchip: ksz9477: port map correction in ALU table entry
+      register
+    - tcp: fix rate_app_limited to default to 1
+    - cpufreq: Add Tegra234 to cpufreq-dt-platdev blocklist
+    - ASoC: fsl_micfil: Correct the number of steps on SX controls
+    - drm: Add orientation quirk for Lenovo ideapad D330-10IGL
+    - s390/debug: add _ASM_S390_ prefix to header guard
+    - cpufreq: armada-37xx: stop using 0 as NULL pointer
+    - ASoC: fsl_ssi: Rename AC'97 streams to avoid collisions with AC'97 CODEC
+    - ASoC: fsl-asoc-card: Fix naming of AC'97 CODEC widgets
+    - spi: spidev: remove debug messages that access spidev->spi without locking
+    - KVM: s390: interrupt: use READ_ONCE() before cmpxchg()
+    - scsi: hisi_sas: Set a port invalid only if there are no devices attached
+      when refreshing port id
+    - platform/x86: touchscreen_dmi: Add info for the CSL Panther Tab HD
+    - platform/x86: asus-nb-wmi: Add alternate mapping for KEY_SCREENLOCK
+    - lockref: stop doing cpu_relax in the cmpxchg loop
+    - mmc: sdhci-esdhc-imx: clear pending interrupt and halt cqhci
+    - mmc: sdhci-esdhc-imx: disable the CMD CRC check for standard tuning
+    - mmc: sdhci-esdhc-imx: correct the tuning start tap and step setting
+    - netfilter: conntrack: do not renew entry stuck in tcp SYN_SENT state
+    - fs: reiserfs: remove useless new_opts in reiserfs_remount
+    - Bluetooth: hci_sync: cancel cmd_timer if hci_open failed
+    - scsi: hpsa: Fix allocation size for scsi_host_alloc()
+    - module: Don't wait for GOING modules
+    - tracing: Make sure trace_printk() can output as soon as it can be used
+    - trace_events_hist: add check for return value of 'create_hist_field'
+    - ftrace/scripts: Update the instructions for ftrace-bisect.sh
+    - cifs: Fix oops due to uncleared server->smbd_conn in reconnect
+    - KVM: x86/vmx: Do not skip segment attributes if unusable bit is set
+    - thermal: intel: int340x: Protect trip temperature from concurrent updates
+    - ARM: 9280/1: mm: fix warning on phys_addr_t to void pointer assignment
+    - EDAC/device: Respect any driver-supplied workqueue polling value
+    - EDAC/qcom: Do not pass llcc_driv_data as edac_device_ctl_info's pvt_info
+    - netlink: prevent potential spectre v1 gadgets
+    - net: fix UaF in netns ops registration error path
+    - netfilter: nft_set_rbtree: skip elements in transaction from garbage
+      collection
+    - netlink: annotate data races around nlk->portid
+    - netlink: annotate data races around dst_portid and dst_group
+    - netlink: annotate data races around sk_state
+    - ipv4: prevent potential spectre v1 gadget in ip_metrics_convert()
+    - ipv4: prevent potential spectre v1 gadget in fib_metrics_match()
+    - netfilter: conntrack: fix vtag checks for ABORT/SHUTDOWN_COMPLETE
+    - netrom: Fix use-after-free of a listening socket.
+    - net/sched: sch_taprio: do not schedule in taprio_reset()
+    - sctp: fail if no bound addresses can be used for a given scope
+    - net: ravb: Fix possible hang if RIS2_QFF1 happen
+    - thermal: intel: int340x: Add locking to int340x_thermal_get_trip_type()
+    - net/tg3: resolve deadlock in tg3_reset_task() during EEH
+    - net/phy/mdio-i2c: Move header file to include/linux/mdio
+    - net: xgene: Move shared header file into include/linux
+    - net: mdio-mux-meson-g12a: force internal PHY off on mux switch
+    - Revert "Input: synaptics - switch touchpad on HP Laptop 15-da3001TU to RMI
+      mode"
+    - nfsd: Ensure knfsd shuts down when the "nfsd" pseudofs is unmounted
+    - block: fix and cleanup bio_check_ro
+    - x86/i8259: Mark legacy PIC interrupts with IRQ_LEVEL
+    - netfilter: conntrack: unify established states for SCTP paths
+    - perf/x86/amd: fix potential integer overflow on shift of a int
+    - clk: Fix pointer casting to prevent oops in devm_clk_release()
+    - x86/asm: Fix an assembler warning with current binutils
+    - ARM: dts: imx: Fix pca9547 i2c-mux node name
+    - bpf: Skip task with pid=1 in send_signal_common()
+    - blk-cgroup: fix missing pd_online_fn() while activating policy
+    - dmaengine: imx-sdma: Fix a possible memory leak in sdma_transfer_init
+    - sysctl: add a new register_sysctl_init() interface
+    - panic: unset panic_on_warn inside panic()
+    - mm: kasan: do not panic if both panic_on_warn and kasan_multishot set
+    - exit: Add and use make_task_dead.
+    - objtool: Add a missing comma to avoid string concatenation
+    - hexagon: Fix function name in die()
+    - h8300: Fix build errors from do_exit() to make_task_dead() transition
+    - csky: Fix function name in csky_alignment() and die()
+    - ia64: make IA64_MCA_RECOVERY bool instead of tristate
+    - exit: Put an upper limit on how often we can oops
+    - exit: Expose "oops_count" to sysfs
+    - exit: Allow oops_limit to be disabled
+    - panic: Consolidate open-coded panic_on_warn checks
+    - panic: Introduce warn_limit
+    - panic: Expose "warn_count" to sysfs
+    - docs: Fix path paste-o for /sys/kernel/warn_count
+    - exit: Use READ_ONCE() for all oops/warn limit reads
+    - ipv6: ensure sane device mtu in tunnels
+    - Bluetooth: fix null ptr deref on hci_sync_conn_complete_evt
+    - usb: host: xhci-plat: add wakeup entry at sysfs
+    - Revert "xprtrdma: Fix regbuf data not freed in rpcrdma_req_create()"
+    - Linux 5.4.231
+  * CVE-2022-3903
+    - USB: add usb_control_msg_send() and usb_control_msg_recv()
+    - USB: correct API of usb_control_msg_send/recv
+    - USB: move snd_usb_pipe_sanity_check into the USB core
+    - media: mceusb: Use new usb_control_msg_*() routines
+  * CVE-2022-3108
+    - drm/amdkfd: Check for null pointer after calling kmemdup
+  * Focal update: v5.4.230 upstream stable release (LP: #2008946)
+    - pNFS/filelayout: Fix coalescing test for single DS
+    - net/ethtool/ioctl: return -EOPNOTSUPP if we have no phy stats
+    - RDMA/srp: Move large values to a new enum for gcc13
+    - f2fs: let's avoid panic if extent_tree is not created
+    - wifi: brcmfmac: fix regression for Broadcom PCIe wifi devices
+    - Add exception protection processing for vd in axi_chan_handle_err function
+    - nilfs2: fix general protection fault in nilfs_btree_insert()
+    - efi: fix userspace infinite retry read efivars after EFI runtime services
+      page fault
+    - drm/i915/gt: Reset twice
+    - ALSA: hda/realtek - Turn on power early
+    - xhci-pci: set the dma max_seg_size
+    - usb: xhci: Check endpoint is valid before dereferencing it
+    - xhci: Fix null pointer dereference when host dies
+    - xhci: Add update_hub_device override for PCI xHCI hosts
+    - xhci: Add a flag to disable USB3 lpm on a xhci root port level.
+    - usb: acpi: add helper to check port lpm capability using acpi _DSM
+    - xhci: Detect lpm incapable xHC USB3 roothub ports from ACPI tables
+    - prlimit: do_prlimit needs to have a speculation check
+    - USB: serial: option: add Quectel EM05-G (GR) modem
+    - USB: serial: option: add Quectel EM05-G (CS) modem
+    - USB: serial: option: add Quectel EM05-G (RS) modem
+    - USB: serial: option: add Quectel EC200U modem
+    - USB: serial: option: add Quectel EM05CN (SG) modem
+    - USB: serial: option: add Quectel EM05CN modem
+    - USB: misc: iowarrior: fix up header size for USB_DEVICE_ID_CODEMERCS_IOW100
+    - misc: fastrpc: Don't remove map on creater_process and device_release
+    - misc: fastrpc: Fix use-after-free race condition for maps
+    - usb: core: hub: disable autosuspend for TI TUSB8041
+    - comedi: adv_pci1760: Fix PWM instruction handling
+    - mmc: sunxi-mmc: Fix clock refcount imbalance during unbind
+    - btrfs: fix race between quota rescan and disable leading to NULL pointer
+      deref
+    - cifs: do not include page data when checking signature
+    - USB: serial: cp210x: add SCALANCE LPE-9000 device id
+    - usb: host: ehci-fsl: Fix module alias
+    - usb: typec: altmodes/displayport: Add pin assignment helper
+    - usb: typec: altmodes/displayport: Fix pin assignment calculation
+    - usb: gadget: g_webcam: Send color matching descriptor per frame
+    - usb: gadget: f_ncm: fix potential NULL ptr deref in ncm_bitrate()
+    - usb-storage: apply IGNORE_UAS only for HIKSEMI MD202 on RTL9210
+    - dt-bindings: phy: g12a-usb3-pcie-phy: fix compatible string documentation
+    - serial: pch_uart: Pass correct sg to dma_unmap_sg()
+    - dmaengine: tegra210-adma: fix global intr clear
+    - serial: atmel: fix incorrect baudrate setup
+    - gsmi: fix null-deref in gsmi_get_variable
+    - drm/i915: re-disable RC6p on Sandy Bridge
+    - drm/amd/display: Fix set scaling doesn's work
+    - drm/amd/display: Fix COLOR_SPACE_YCBCR2020_TYPE matrix
+    - x86/fpu: Use _Alignof to avoid undefined behavior in TYPE_ALIGN
+    - mm/khugepaged: fix collapse_pte_mapped_thp() to allow anon_vma
+    - Linux 5.4.230
+
+  [ Ubuntu: 5.4.0-146.163 ]
+
+  * focal/linux: 5.4.0-146.163 -proposed tracker (LP: #2012094)
+  * NFS deathlock with last Kernel 5.4.0-144.161 and 5.15.0-67.74 (LP: #2009325)
+    - NFS: Correct timing for assigning access cache timestamp
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Mon, 19 Jun 2023 15:02:18 +1000
+
+linux-xilinx-zynqmp (5.4.0-1023.27) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1023.27 -proposed tracker (LP: #2008386)
+
+  [ Ubuntu: 5.4.0-145.162 ]
+
+  * focal/linux: 5.4.0-145.162 -proposed tracker (LP: #2008389)
+  * [SRU]Update ice driver to support E823 devices (LP: #1986717)
+    - ice: Add device ids for E822 devices
+    - ice: add support for E823 devices
+  * btrfs/154: rename fails with EOVERFLOW when calculating item size during
+    item key collision (LP: #2004132)
+    - btrfs: correctly calculate item size used when item key collision happens
+  * rtcpie in timers from ubuntu_kernel_selftests randomly failing
+    (LP: #1814234)
+    - SAUCE: selftest: rtcpie: Force passing unreliable subtest
+  * [UBUNTU 20.04] KVM: s390: pv: don't allow userspace to set the clock under
+    PV - kernel part (LP: #1999882)
+    - KVM: s390x: fix SCK locking
+    - KVM: s390: pv: don't allow userspace to set the clock under PV
+  * CVE-2021-3669
+    - ipc: replace costly bailout check in sysvipc_find_ipc()
+  * net:fcnal-test.sh 'nettest' command not found on F/K (LP: #2006391)
+    - selftests/net: Find nettest in current directory
+  * xfs: Preallocated ioend transactions cause deadlock due to log buffer
+    exhaustion (LP: #2007219)
+    - xfs: drop submit side trans alloc for append ioends
+  * CVE-2022-4382
+    - USB: gadgetfs: Fix race between mounting and unmounting
+  * CVE-2022-2196
+    - KVM: VMX: Execute IBPB on emulated VM-exit when guest has IBRS
+  * ubuntu_kernel_selftests: net:udpgso_bench.sh failed (LP: #1951447)
+    - selftests: net: udpgso_bench: Fix racing bug between the rx/tx programs
+  * net:fcnal-test.sh didn't return a non-zero value even with some sub-tests
+    failed (LP: #2006692)
+    - selftests: net/fcnal-test.sh: add exit code
+  * Fix selftests/ftracetests/Meta-selftests in Focal (LP: #2006453)
+    - SAUCE: Fix ftrace/Meta-selftests bashism check
+  * CVE-2023-23559
+    - wifi: rndis_wlan: Prevent buffer overflow in rndis_query_oid
+
+ -- Masahiro Yamada <masahiro.yamada@canonical.com>  Fri, 17 Mar 2023 14:40:43 +0900
+
+linux-xilinx-zynqmp (5.4.0-1022.26) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1022.26 -proposed tracker (LP: #2007326)
+
+  * Focal update: v5.4.226 upstream stable release (LP: #2003896)
+    - [Config] updateconfigs for INET_TABLE_PERTURB_ORDER
+
+  [ Ubuntu: 5.4.0-144.161 ]
+
+  * focal/linux: 5.4.0-144.161 -proposed tracker (LP: #2004653)
+  * CVE-2023-0461
+    - SAUCE: Fix inet_csk_listen_start after CVE-2023-0461
+
+  [ Ubuntu: 5.4.0-143.160 ]
+
+  * focal/linux: 5.4.0-143.160 -proposed tracker (LP: #2004385)
+  * NFS: client permission error after adding user to permissible group
+    (LP: #2003053)
+    - NFS: Clear the file access cache upon login
+    - NFS: Judge the file access cache's timestamp in rcu path
+    - NFS: Fix up a sparse warning
+  * Focal update: v5.4.229 upstream stable release (LP: #2003914)
+    - tracing/ring-buffer: Only do full wait when cpu != RING_BUFFER_ALL_CPUS
+    - udf: Discard preallocation before extending file with a hole
+    - udf: Fix preallocation discarding at indirect extent boundary
+    - udf: Do not bother looking for prealloc extents if i_lenExtents matches
+      i_size
+    - udf: Fix extending file within last block
+    - usb: gadget: uvc: Prevent buffer overflow in setup handler
+    - USB: serial: option: add Quectel EM05-G modem
+    - USB: serial: cp210x: add Kamstrup RF sniffer PIDs
+    - USB: serial: f81232: fix division by zero on line-speed change
+    - USB: serial: f81534: fix division by zero on line-speed change
+    - igb: Initialize mailbox message for VF reset
+    - xen-netback: move removal of "hotplug-status" to the right place
+    - HID: ite: Add support for Acer S1002 keyboard-dock
+    - HID: ite: Enable QUIRK_TOUCHPAD_ON_OFF_REPORT on Acer Aspire Switch 10E
+    - HID: ite: Enable QUIRK_TOUCHPAD_ON_OFF_REPORT on Acer Aspire Switch V 10
+    - HID: uclogic: Add HID_QUIRK_HIDINPUT_FORCE quirk
+    - net: loopback: use NET_NAME_PREDICTABLE for name_assign_type
+    - usb: musb: remove extra check in musb_gadget_vbus_draw
+    - ARM: dts: qcom: apq8064: fix coresight compatible
+    - arm64: dts: qcom: sdm845-cheza: fix AP suspend pin bias
+    - drivers: soc: ti: knav_qmss_queue: Mark knav_acc_firmwares as static
+    - arm: dts: spear600: Fix clcd interrupt
+    - soc: ti: knav_qmss_queue: Use pm_runtime_resume_and_get instead of
+      pm_runtime_get_sync
+    - soc: ti: knav_qmss_queue: Fix PM disable depth imbalance in knav_queue_probe
+    - soc: ti: smartreflex: Fix PM disable depth imbalance in omap_sr_probe
+    - perf: arm_dsu: Fix hotplug callback leak in dsu_pmu_init()
+    - perf/smmuv3: Fix hotplug callback leak in arm_smmu_pmu_init()
+    - arm64: dts: mt2712e: Fix unit_address_vs_reg warning for oscillators
+    - arm64: dts: mt2712e: Fix unit address for pinctrl node
+    - arm64: dts: mt2712-evb: Fix vproc fixed regulators unit names
+    - arm64: dts: mt2712-evb: Fix usb vbus regulators unit names
+    - arm64: dts: mediatek: mt6797: Fix 26M oscillator unit name
+    - ARM: dts: dove: Fix assigned-addresses for every PCIe Root Port
+    - ARM: dts: armada-370: Fix assigned-addresses for every PCIe Root Port
+    - ARM: dts: armada-xp: Fix assigned-addresses for every PCIe Root Port
+    - ARM: dts: armada-375: Fix assigned-addresses for every PCIe Root Port
+    - ARM: dts: armada-38x: Fix assigned-addresses for every PCIe Root Port
+    - ARM: dts: armada-39x: Fix assigned-addresses for every PCIe Root Port
+    - ARM: dts: turris-omnia: Add ethernet aliases
+    - ARM: dts: turris-omnia: Add switch port 6 node
+    - arm64: dts: armada-3720-turris-mox: Add missing interrupt for RTC
+    - pstore/ram: Fix error return code in ramoops_probe()
+    - ARM: mmp: fix timer_read delay
+    - pstore: Avoid kcore oops by vmap()ing with VM_IOREMAP
+    - tpm/tpm_crb: Fix error message in __crb_relinquish_locality()
+    - cpuidle: dt: Return the correct numbers of parsed idle states
+    - alpha: fix syscall entry in !AUDUT_SYSCALL case
+    - PM: hibernate: Fix mistake in kerneldoc comment
+    - fs: don't audit the capability check in simple_xattr_list()
+    - selftests/ftrace: event_triggers: wait longer for test_event_enable
+    - perf: Fix possible memleak in pmu_dev_alloc()
+    - timerqueue: Use rb_entry_safe() in timerqueue_getnext()
+    - proc: fixup uptime selftest
+    - lib/fonts: fix undefined behavior in bit shift for get_default_font
+    - ocfs2: fix memory leak in ocfs2_stack_glue_init()
+    - MIPS: vpe-mt: fix possible memory leak while module exiting
+    - MIPS: vpe-cmp: fix possible memory leak while module exiting
+    - selftests/efivarfs: Add checking of the test return value
+    - PNP: fix name memory leak in pnp_alloc_dev()
+    - perf/x86/intel/uncore: Fix reference count leak in hswep_has_limit_sbox()
+    - irqchip: gic-pm: Use pm_runtime_resume_and_get() in gic_probe()
+    - EDAC/i10nm: fix refcount leak in pci_get_dev_wrapper()
+    - nfsd: don't call nfsd_file_put from client states seqfile display
+    - genirq/irqdesc: Don't try to remove non-existing sysfs files
+    - cpufreq: amd_freq_sensitivity: Add missing pci_dev_put()
+    - libfs: add DEFINE_SIMPLE_ATTRIBUTE_SIGNED for signed value
+    - lib/notifier-error-inject: fix error when writing -errno to debugfs file
+    - docs: fault-injection: fix non-working usage of negative values
+    - debugfs: fix error when writing negative value to atomic_t debugfs file
+    - ocfs2: ocfs2_mount_volume does cleanup job before return error
+    - ocfs2: rewrite error handling of ocfs2_fill_super
+    - ocfs2: fix memory leak in ocfs2_mount_volume()
+    - rapidio: fix possible name leaks when rio_add_device() fails
+    - rapidio: rio: fix possible name leak in rio_register_mport()
+    - clocksource/drivers/sh_cmt: Make sure channel clock supply is enabled
+    - ACPICA: Fix use-after-free in acpi_ut_copy_ipackage_to_ipackage()
+    - uprobes/x86: Allow to probe a NOP instruction with 0x66 prefix
+    - xen/events: only register debug interrupt for 2-level events
+    - x86/xen: Fix memory leak in xen_smp_intr_init{_pv}()
+    - x86/xen: Fix memory leak in xen_init_lock_cpu()
+    - xen/privcmd: Fix a possible warning in privcmd_ioctl_mmap_resource()
+    - PM: runtime: Improve path in rpm_idle() when no callback
+    - PM: runtime: Do not call __rpm_callback() from rpm_idle()
+    - platform/x86: mxm-wmi: fix memleak in mxm_wmi_call_mx[ds|mx]()
+    - MIPS: BCM63xx: Add check for NULL for clk in clk_enable
+    - MIPS: OCTEON: warn only once if deprecated link status is being used
+    - fs: sysv: Fix sysv_nblocks() returns wrong value
+    - rapidio: fix possible UAF when kfifo_alloc() fails
+    - eventfd: change int to __u64 in eventfd_signal() ifndef CONFIG_EVENTFD
+    - relay: fix type mismatch when allocating memory in relay_create_buf()
+    - hfs: Fix OOB Write in hfs_asc2mac
+    - rapidio: devices: fix missing put_device in mport_cdev_open
+    - wifi: ath9k: hif_usb: fix memory leak of urbs in
+      ath9k_hif_usb_dealloc_tx_urbs()
+    - wifi: ath9k: hif_usb: Fix use-after-free in ath9k_hif_usb_reg_in_cb()
+    - wifi: rtl8xxxu: Fix reading the vendor of combo chips
+    - pata_ipx4xx_cf: Fix unsigned comparison with less than zero
+    - media: i2c: ad5820: Fix error path
+    - can: kvaser_usb: do not increase tx statistics when sending error message
+      frames
+    - can: kvaser_usb: kvaser_usb_leaf: Get capabilities from device
+    - can: kvaser_usb: kvaser_usb_leaf: Rename {leaf,usbcan}_cmd_error_event to
+      {leaf,usbcan}_cmd_can_error_event
+    - can: kvaser_usb: kvaser_usb_leaf: Handle CMD_ERROR_EVENT
+    - can: kvaser_usb_leaf: Set Warning state even without bus errors
+    - can: kvaser_usb_leaf: Fix improved state not being reported
+    - can: kvaser_usb_leaf: Fix wrong CAN state after stopping
+    - can: kvaser_usb_leaf: Fix bogus restart events
+    - can: kvaser_usb: Add struct kvaser_usb_busparams
+    - can: kvaser_usb: Compare requested bittiming parameters with actual
+      parameters in do_set_{,data}_bittiming
+    - clk: renesas: r9a06g032: Repair grave increment error
+    - spi: Update reference to struct spi_controller
+    - drm/panel/panel-sitronix-st7701: Remove panel on DSI attach failure
+    - ima: Rename internal filter rule functions
+    - ima: Fix fall-through warnings for Clang
+    - ima: Handle -ESTALE returned by ima_filter_rule_match()
+    - media: vivid: fix compose size exceed boundary
+    - bpf: propagate precision in ALU/ALU64 operations
+    - mtd: Fix device name leak when register device failed in add_mtd_device()
+    - wifi: rsi: Fix handling of 802.3 EAPOL frames sent via control port
+    - media: camss: Clean up received buffers on failed start of streaming
+    - net, proc: Provide PROC_FS=n fallback for proc_create_net_single_write()
+    - rxrpc: Fix ack.bufferSize to be 0 when generating an ack
+    - drm/radeon: Add the missed acpi_put_table() to fix memory leak
+    - drm/mediatek: Modify dpi power on/off sequence.
+    - ASoC: pxa: fix null-pointer dereference in filter()
+    - regulator: core: fix unbalanced of node refcount in regulator_dev_lookup()
+    - amdgpu/pm: prevent array underflow in vega20_odn_edit_dpm_table()
+    - integrity: Fix memory leakage in keyring allocation error path
+    - ima: Fix misuse of dereference of pointer in template_desc_init_fields()
+    - wifi: ath10k: Fix return value in ath10k_pci_init()
+    - mtd: lpddr2_nvm: Fix possible null-ptr-deref
+    - Input: elants_i2c - properly handle the reset GPIO when power is off
+    - media: solo6x10: fix possible memory leak in solo_sysfs_init()
+    - media: platform: exynos4-is: Fix error handling in fimc_md_init()
+    - media: videobuf-dma-contig: use dma_mmap_coherent
+    - bpf: Move skb->len == 0 checks into __bpf_redirect
+    - HID: hid-sensor-custom: set fixed size for custom attributes
+    - ALSA: pcm: fix undefined behavior in bit shift for SNDRV_PCM_RATE_KNOT
+    - ALSA: seq: fix undefined behavior in bit shift for
+      SNDRV_SEQ_FILTER_USE_EVENT
+    - regulator: core: use kfree_const() to free space conditionally
+    - clk: rockchip: Fix memory leak in rockchip_clk_register_pll()
+    - bonding: Export skip slave logic to function
+    - bonding: Rename slave_arr to usable_slaves
+    - bonding: fix link recovery in mode 2 when updelay is nonzero
+    - mtd: maps: pxa2xx-flash: fix memory leak in probe
+    - media: imon: fix a race condition in send_packet()
+    - clk: imx8mn: correct the usb1_ctrl parent to be usb_bus
+    - clk: imx: replace osc_hdmi with dummy
+    - pinctrl: pinconf-generic: add missing of_node_put()
+    - media: dvb-core: Fix ignored return value in dvb_register_frontend()
+    - media: dvb-usb: az6027: fix null-ptr-deref in az6027_i2c_xfer()
+    - media: s5p-mfc: Add variant data for MFC v7 hardware for Exynos 3250 SoC
+    - drm/tegra: Add missing clk_disable_unprepare() in tegra_dc_probe()
+    - ASoC: dt-bindings: wcd9335: fix reset line polarity in example
+    - ASoC: mediatek: mtk-btcvsd: Add checks for write and read of mtk_btcvsd_snd
+    - NFSv4.2: Clear FATTR4_WORD2_SECURITY_LABEL when done decoding
+    - NFSv4.2: Fix a memory stomp in decode_attr_security_label
+    - NFSv4.2: Fix initialisation of struct nfs4_label
+    - NFSv4: Fix a deadlock between nfs4_open_recover_helper() and delegreturn
+    - ALSA: asihpi: fix missing pci_disable_device()
+    - wifi: iwlwifi: mvm: fix double free on tx path.
+    - ASoC: mediatek: mt8173: Enable IRQ when pdata is ready
+    - drm/radeon: Fix PCI device refcount leak in radeon_atrm_get_bios()
+    - drm/amdgpu: Fix PCI device refcount leak in amdgpu_atrm_get_bios()
+    - ASoC: pcm512x: Fix PM disable depth imbalance in pcm512x_probe
+    - netfilter: conntrack: set icmpv6 redirects as RELATED
+    - bpf, sockmap: Fix repeated calls to sock_put() when msg has more_data
+    - bpf, sockmap: Fix data loss caused by using apply_bytes on ingress redirect
+    - bonding: uninitialized variable in bond_miimon_inspect()
+    - spi: spidev: mask SPI_CS_HIGH in SPI_IOC_RD_MODE
+    - wifi: cfg80211: Fix not unregister reg_pdev when load_builtin_regdb_keys()
+      fails
+    - regulator: core: fix module refcount leak in set_supply()
+    - clk: qcom: clk-krait: fix wrong div2 functions
+    - hsr: Avoid double remove of a node.
+    - configfs: fix possible memory leak in configfs_create_dir()
+    - regulator: core: fix resource leak in regulator_register()
+    - bpf, sockmap: fix race in sock_map_free()
+    - media: saa7164: fix missing pci_disable_device()
+    - ALSA: mts64: fix possible null-ptr-defer in snd_mts64_interrupt
+    - xprtrdma: Fix regbuf data not freed in rpcrdma_req_create()
+    - SUNRPC: Fix missing release socket in rpc_sockname()
+    - NFSv4.x: Fail client initialisation if state manager thread can't run
+    - mmc: alcor: fix return value check of mmc_add_host()
+    - mmc: moxart: fix return value check of mmc_add_host()
+    - mmc: mxcmmc: fix return value check of mmc_add_host()
+    - mmc: pxamci: fix return value check of mmc_add_host()
+    - mmc: rtsx_usb_sdmmc: fix return value check of mmc_add_host()
+    - mmc: toshsd: fix return value check of mmc_add_host()
+    - mmc: vub300: fix return value check of mmc_add_host()
+    - mmc: wmt-sdmmc: fix return value check of mmc_add_host()
+    - mmc: atmel-mci: fix return value check of mmc_add_host()
+    - mmc: omap_hsmmc: fix return value check of mmc_add_host()
+    - mmc: meson-gx: fix return value check of mmc_add_host()
+    - mmc: via-sdmmc: fix return value check of mmc_add_host()
+    - mmc: wbsd: fix return value check of mmc_add_host()
+    - mmc: mmci: fix return value check of mmc_add_host()
+    - media: c8sectpfe: Add of_node_put() when breaking out of loop
+    - media: coda: Add check for dcoda_iram_alloc
+    - media: coda: Add check for kmalloc
+    - clk: samsung: Fix memory leak in _samsung_clk_register_pll()
+    - spi: spi-gpio: Don't set MOSI as an input if not 3WIRE mode
+    - wifi: rtl8xxxu: Add __packed to struct rtl8723bu_c2h
+    - wifi: brcmfmac: Fix error return code in brcmf_sdio_download_firmware()
+    - blktrace: Fix output non-blktrace event when blk_classic option enabled
+    - clk: socfpga: clk-pll: Remove unused variable 'rc'
+    - clk: socfpga: use clk_hw_register for a5/c5
+    - clk: socfpga: Fix memory leak in socfpga_gate_init()
+    - net: vmw_vsock: vmci: Check memcpy_from_msg()
+    - net: defxx: Fix missing err handling in dfx_init()
+    - net: stmmac: selftests: fix potential memleak in stmmac_test_arpoffload()
+    - drivers: net: qlcnic: Fix potential memory leak in qlcnic_sriov_init()
+    - of: overlay: fix null pointer dereferencing in find_dup_cset_node_entry()
+      and find_dup_cset_prop()
+    - ethernet: s2io: don't call dev_kfree_skb() under spin_lock_irqsave()
+    - net: farsync: Fix kmemleak when rmmods farsync
+    - net/tunnel: wait until all sk_user_data reader finish before releasing the
+      sock
+    - net: apple: mace: don't call dev_kfree_skb() under spin_lock_irqsave()
+    - net: apple: bmac: don't call dev_kfree_skb() under spin_lock_irqsave()
+    - net: emaclite: don't call dev_kfree_skb() under spin_lock_irqsave()
+    - net: ethernet: dnet: don't call dev_kfree_skb() under spin_lock_irqsave()
+    - hamradio: don't call dev_kfree_skb() under spin_lock_irqsave()
+    - net: amd: lance: don't call dev_kfree_skb() under spin_lock_irqsave()
+    - net: amd-xgbe: Fix logic around active and passive cables
+    - net: amd-xgbe: Check only the minimum speed for active/passive cables
+    - can: tcan4x5x: Remove invalid write in clear_interrupts
+    - net: lan9303: Fix read error execution path
+    - ntb_netdev: Use dev_kfree_skb_any() in interrupt context
+    - Bluetooth: btusb: don't call kfree_skb() under spin_lock_irqsave()
+    - Bluetooth: hci_qca: don't call kfree_skb() under spin_lock_irqsave()
+    - Bluetooth: hci_ll: don't call kfree_skb() under spin_lock_irqsave()
+    - Bluetooth: hci_h5: don't call kfree_skb() under spin_lock_irqsave()
+    - Bluetooth: hci_bcsp: don't call kfree_skb() under spin_lock_irqsave()
+    - Bluetooth: hci_core: don't call kfree_skb() under spin_lock_irqsave()
+    - Bluetooth: RFCOMM: don't call kfree_skb() under spin_lock_irqsave()
+    - stmmac: fix potential division by 0
+    - apparmor: fix a memleak in multi_transaction_new()
+    - apparmor: fix lockdep warning when removing a namespace
+    - apparmor: Fix abi check to include v8 abi
+    - apparmor: Use pointer to struct aa_label for lbs_cred
+    - RDMA/core: Fix order of nldev_exit call
+    - f2fs: fix normal discard process
+    - RDMA/siw: Fix immediate work request flush to completion queue
+    - RDMA/nldev: Return "-EAGAIN" if the cm_id isn't from expected port
+    - RDMA/siw: Set defined status for work completion with undefined status
+    - scsi: scsi_debug: Fix a warning in resp_write_scat()
+    - crypto: ccree - swap SHA384 and SHA512 larval hashes at build time
+    - crypto: ccree - Remove debugfs when platform_driver_register failed
+    - PCI: Check for alloc failure in pci_request_irq()
+    - RDMA/hfi: Decrease PCI device reference count in error path
+    - crypto: ccree - Make cc_debugfs_global_fini() available for module init
+      function
+    - RDMA/rxe: Fix NULL-ptr-deref in rxe_qp_do_cleanup() when socket create
+      failed
+    - scsi: hpsa: Fix possible memory leak in hpsa_init_one()
+    - crypto: tcrypt - Fix multibuffer skcipher speed test mem leak
+    - scsi: mpt3sas: Fix possible resource leaks in mpt3sas_transport_port_add()
+    - scsi: hpsa: Fix error handling in hpsa_add_sas_host()
+    - scsi: hpsa: Fix possible memory leak in hpsa_add_sas_device()
+    - scsi: fcoe: Fix possible name leak when device_register() fails
+    - scsi: ipr: Fix WARNING in ipr_init()
+    - scsi: fcoe: Fix transport not deattached when fcoe_if_init() fails
+    - scsi: snic: Fix possible UAF in snic_tgt_create()
+    - RDMA/nldev: Add checks for nla_nest_start() in fill_stat_counter_qps()
+    - f2fs: avoid victim selection from previous victim section
+    - crypto: omap-sham - Use pm_runtime_resume_and_get() in omap_sham_probe()
+    - RDMA/hfi1: Fix error return code in parse_platform_config()
+    - orangefs: Fix sysfs not cleanup when dev init failed
+    - crypto: img-hash - Fix variable dereferenced before check 'hdev->req'
+    - hwrng: amd - Fix PCI device refcount leak
+    - hwrng: geode - Fix PCI device refcount leak
+    - IB/IPoIB: Fix queue count inconsistency for PKEY child interfaces
+    - drivers: dio: fix possible memory leak in dio_init()
+    - tty: serial: tegra: Activate RX DMA transfer by request
+    - serial: tegra: Read DMA status before terminating
+    - class: fix possible memory leak in __class_register()
+    - vfio: platform: Do not pass return buffer to ACPI _RST method
+    - uio: uio_dmem_genirq: Fix missing unlock in irq configuration
+    - uio: uio_dmem_genirq: Fix deadlock between irq config and handling
+    - usb: fotg210-udc: Fix ages old endianness issues
+    - staging: vme_user: Fix possible UAF in tsi148_dma_list_add
+    - usb: typec: Check for ops->exit instead of ops->enter in altmode_exit
+    - usb: typec: tcpci: fix of node refcount leak in tcpci_register_port()
+    - serial: amba-pl011: avoid SBSA UART accessing DMACR register
+    - serial: pl011: Do not clear RX FIFO & RX interrupt in unthrottle.
+    - serial: pch: Fix PCI device refcount leak in pch_request_dma()
+    - tty: serial: clean up stop-tx part in altera_uart_tx_chars()
+    - tty: serial: altera_uart_{r,t}x_chars() need only uart_port
+    - serial: altera_uart: fix locking in polling mode
+    - serial: sunsab: Fix error handling in sunsab_init()
+    - test_firmware: fix memory leak in test_firmware_init()
+    - misc: ocxl: fix possible name leak in ocxl_file_register_afu()
+    - misc: tifm: fix possible memory leak in tifm_7xx1_switch_media()
+    - misc: sgi-gru: fix use-after-free error in gru_set_context_option, gru_fault
+      and gru_handle_user_call_os
+    - cxl: fix possible null-ptr-deref in cxl_guest_init_afu|adapter()
+    - cxl: fix possible null-ptr-deref in cxl_pci_init_afu|adapter()
+    - counter: stm32-lptimer-cnt: fix the check on arr and cmp registers update
+    - usb: roles: fix of node refcount leak in usb_role_switch_is_parent()
+    - usb: gadget: f_hid: optional SETUP/SET_REPORT mode
+    - usb: gadget: f_hid: fix f_hidg lifetime vs cdev
+    - usb: gadget: f_hid: fix refcount leak on error path
+    - drivers: mcb: fix resource leak in mcb_probe()
+    - mcb: mcb-parse: fix error handing in chameleon_parse_gdd()
+    - chardev: fix error handling in cdev_device_add()
+    - i2c: pxa-pci: fix missing pci_disable_device() on error in ce4100_i2c_probe
+    - staging: rtl8192u: Fix use after free in ieee80211_rx()
+    - staging: rtl8192e: Fix potential use-after-free in rtllib_rx_Monitor()
+    - vme: Fix error not catched in fake_init()
+    - i2c: ismt: Fix an out-of-bounds bug in ismt_access()
+    - usb: storage: Add check for kcalloc
+    - tracing/hist: Fix issue of losting command info in error_log
+    - samples: vfio-mdev: Fix missing pci_disable_device() in mdpy_fb_probe()
+    - fbdev: ssd1307fb: Drop optional dependency
+    - fbdev: pm2fb: fix missing pci_disable_device()
+    - fbdev: via: Fix error in via_core_init()
+    - fbdev: vermilion: decrease reference count in error path
+    - fbdev: uvesafb: Fixes an error handling path in uvesafb_probe()
+    - HSI: omap_ssi_core: fix unbalanced pm_runtime_disable()
+    - HSI: omap_ssi_core: fix possible memory leak in ssi_probe()
+    - power: supply: fix residue sysfs file in error handle route of
+      __power_supply_register()
+    - perf trace: Return error if a system call doesn't exist
+    - perf trace: Separate 'struct syscall_fmt' definition from syscall_fmts
+      variable
+    - perf trace: Factor out the initialization of syscal_arg_fmt->scnprintf
+    - perf trace: Add the syscall_arg_fmt pointer to syscall_arg
+    - perf trace: Allow associating scnprintf routines with well known arg names
+    - perf trace: Add a strtoul() method to 'struct syscall_arg_fmt'
+    - perf trace: Use macro RAW_SYSCALL_ARGS_NUM to replace number
+    - perf trace: Handle failure when trace point folder is missed
+    - perf symbol: correction while adjusting symbol
+    - HSI: omap_ssi_core: Fix error handling in ssi_init()
+    - power: supply: fix null pointer dereferencing in
+      power_supply_get_battery_info
+    - RDMA/siw: Fix pointer cast warning
+    - include/uapi/linux/swab: Fix potentially missing __always_inline
+    - rtc: snvs: Allow a time difference on clock register read
+    - rtc: pcf85063: Fix reading alarm
+    - iommu/amd: Fix pci device refcount leak in ppr_notifier()
+    - iommu/fsl_pamu: Fix resource leak in fsl_pamu_probe()
+    - macintosh: fix possible memory leak in macio_add_one_device()
+    - macintosh/macio-adb: check the return value of ioremap()
+    - powerpc/52xx: Fix a resource leak in an error handling path
+    - cxl: Fix refcount leak in cxl_calc_capp_routing
+    - powerpc/xive: add missing iounmap() in error path in
+      xive_spapr_populate_irq_data()
+    - powerpc/perf: callchain validate kernel stack pointer bounds
+    - powerpc/83xx/mpc832x_rdb: call platform_device_put() in error case in
+      of_fsl_spi_probe()
+    - powerpc/hv-gpci: Fix hv_gpci event list
+    - selftests/powerpc: Fix resource leaks
+    - pwm: sifive: Call pwm_sifive_update_clock() while mutex is held
+    - remoteproc: sysmon: fix memory leak in qcom_add_sysmon_subdev()
+    - remoteproc: qcom_q6v5_pas: Fix missing of_node_put() in
+      adsp_alloc_memory_region()
+    - rtc: st-lpc: Add missing clk_disable_unprepare in st_rtc_probe()
+    - rtc: pic32: Move devm_rtc_allocate_device earlier in pic32_rtc_probe()
+    - nfsd: Define the file access mode enum for tracing
+    - NFSD: Add tracepoints to NFSD's duplicate reply cache
+    - nfsd: under NFSv4.1, fix double svc_xprt_put on rpc_create failure
+    - mISDN: hfcsusb: don't call dev_kfree_skb/kfree_skb() under
+      spin_lock_irqsave()
+    - mISDN: hfcpci: don't call dev_kfree_skb/kfree_skb() under
+      spin_lock_irqsave()
+    - mISDN: hfcmulti: don't call dev_kfree_skb/kfree_skb() under
+      spin_lock_irqsave()
+    - nfc: pn533: Clear nfc_target before being used
+    - r6040: Fix kmemleak in probe and remove
+    - rtc: mxc_v2: Add missing clk_disable_unprepare()
+    - openvswitch: Fix flow lookup to use unmasked key
+    - skbuff: Account for tail adjustment during pull operations
+    - mailbox: zynq-ipi: fix error handling while device_register() fails
+    - net_sched: reject TCF_EM_SIMPLE case for complex ematch module
+    - rxrpc: Fix missing unlock in rxrpc_do_sendmsg()
+    - myri10ge: Fix an error handling path in myri10ge_probe()
+    - net: stream: purge sk_error_queue in sk_stream_kill_queues()
+    - rcu: Fix __this_cpu_read() lockdep warning in rcu_force_quiescent_state()
+    - binfmt_misc: fix shift-out-of-bounds in check_special_flags
+    - fs: jfs: fix shift-out-of-bounds in dbAllocAG
+    - udf: Avoid double brelse() in udf_rename()
+    - fs: jfs: fix shift-out-of-bounds in dbDiscardAG
+    - ACPICA: Fix error code path in acpi_ds_call_control_method()
+    - nilfs2: fix shift-out-of-bounds/overflow in nilfs_sb2_bad_offset()
+    - acct: fix potential integer overflow in encode_comp_t()
+    - hfs: fix OOB Read in __hfs_brec_find
+    - drm/etnaviv: add missing quirks for GC300
+    - brcmfmac: return error when getting invalid max_flowrings from dongle
+    - wifi: ath9k: verify the expected usb_endpoints are present
+    - wifi: ar5523: Fix use-after-free on ar5523_cmd() timed out
+    - ASoC: codecs: rt298: Add quirk for KBL-R RVP platform
+    - ipmi: fix memleak when unload ipmi driver
+    - bpf: make sure skb->len != 0 when redirecting to a tunneling device
+    - net: ethernet: ti: Fix return type of netcp_ndo_start_xmit()
+    - hamradio: baycom_epp: Fix return type of baycom_send_packet()
+    - wifi: brcmfmac: Fix potential shift-out-of-bounds in
+      brcmf_fw_alloc_request()
+    - igb: Do not free q_vector unless new one was allocated
+    - s390/ctcm: Fix return type of ctc{mp,}m_tx()
+    - s390/netiucv: Fix return type of netiucv_tx()
+    - s390/lcs: Fix return type of lcs_start_xmit()
+    - drm/rockchip: Use drm_mode_copy()
+    - drm/sti: Use drm_mode_copy()
+    - drivers/md/md-bitmap: check the return value of md_bitmap_get_counter()
+    - md/raid1: stop mdx_raid1 thread when raid1 array run failed
+    - net: add atomic_long_t to net_device_stats fields
+    - mrp: introduce active flags to prevent UAF when applicant uninit
+    - ppp: associate skb with a device at tx
+    - bpf: Prevent decl_tag from being referenced in func_proto arg
+    - media: dvb-frontends: fix leak of memory fw
+    - media: dvbdev: adopts refcnt to avoid UAF
+    - media: dvb-usb: fix memory leak in dvb_usb_adapter_init()
+    - blk-mq: fix possible memleak when register 'hctx' failed
+    - regulator: core: fix use_count leakage when handling boot-on
+    - mmc: f-sdh30: Add quirks for broken timeout clock capability
+    - media: si470x: Fix use-after-free in si470x_int_in_callback()
+    - clk: st: Fix memory leak in st_of_quadfs_setup()
+    - hugetlbfs: fix null-ptr-deref in hugetlbfs_parse_param()
+    - drm/fsl-dcu: Fix return type of fsl_dcu_drm_connector_mode_valid()
+    - drm/sti: Fix return type of sti_{dvo,hda,hdmi}_connector_mode_valid()
+    - orangefs: Fix kmemleak in orangefs_prepare_debugfs_help_string()
+    - orangefs: Fix kmemleak in orangefs_{kernel,client}_debug_init()
+    - ALSA/ASoC: hda: move/rename snd_hdac_ext_stop_streams to hdac_stream.c
+    - ALSA: hda: add snd_hdac_stop_streams() helper
+    - ASoC: Intel: Skylake: Fix driver hang during shutdown
+    - ASoC: mediatek: mt8173-rt5650-rt5514: fix refcount leak in
+      mt8173_rt5650_rt5514_dev_probe()
+    - ASoC: audio-graph-card: fix refcount leak of cpu_ep in
+      __graph_for_each_link()
+    - ASoC: rockchip: pdm: Add missing clk_disable_unprepare() in
+      rockchip_pdm_runtime_resume()
+    - ASoC: wm8994: Fix potential deadlock
+    - ASoC: rockchip: spdif: Add missing clk_disable_unprepare() in
+      rk_spdif_runtime_resume()
+    - ASoC: rt5670: Remove unbalanced pm_runtime_put()
+    - pstore: Switch pmsg_lock to an rt_mutex to avoid priority inversion
+    - pstore: Make sure CONFIG_PSTORE_PMSG selects CONFIG_RT_MUTEXES
+    - ALSA: hda/realtek: Add quirk for Lenovo TianYi510Pro-14IOB
+    - ALSA: hda/hdmi: Add HP Device 0x8711 to force connect list
+    - usb: dwc3: core: defer probe on ulpi_read_id timeout
+    - HID: wacom: Ensure bootloader PID is usable in hidraw mode
+    - reiserfs: Add missing calls to reiserfs_security_free()
+    - iio: adc: ad_sigma_delta: do not use internal iio_dev lock
+    - iio: adc128s052: add proper .data members in adc128_of_match table
+    - regulator: core: fix deadlock on regulator enable
+    - gcov: add support for checksum field
+    - media: dvbdev: fix build warning due to comments
+    - media: dvbdev: fix refcnt bug
+    - cifs: fix oops during encryption
+    - nvme-pci: fix doorbell buffer value endianness
+    - ata: ahci: Fix PCS quirk application for suspend
+    - nvme: fix the NVME_CMD_EFFECTS_CSE_MASK definition
+    - objtool: Fix SEGFAULT
+    - powerpc/rtas: avoid device tree lookups in rtas_os_term()
+    - powerpc/rtas: avoid scheduling in rtas_os_term()
+    - HID: multitouch: fix Asus ExpertBook P2 P2451FA trackpoint
+    - HID: plantronics: Additional PIDs for double volume key presses quirk
+    - hfsplus: fix bug causing custom uid and gid being unable to be assigned with
+      mount
+    - ovl: Use ovl mounter's fsuid and fsgid in ovl_link()
+    - ALSA: line6: correct midi status byte when receiving data from podxt
+    - ALSA: line6: fix stack overflow in line6_midi_transmit
+    - pnode: terminate at peers of source
+    - md: fix a crash in mempool_free
+    - mm, compaction: fix fast_isolate_around() to stay within boundaries
+    - f2fs: should put a page when checking the summary info
+    - mmc: vub300: fix warning - do not call blocking ops when !TASK_RUNNING
+    - tpm: tpm_crb: Add the missed acpi_put_table() to fix memory leak
+    - tpm: tpm_tis: Add the missed acpi_put_table() to fix memory leak
+    - SUNRPC: Don't leak netobj memory when gss_read_proxy_verf() fails
+    - net/af_packet: add VLAN support for AF_PACKET SOCK_RAW GSO
+    - net/af_packet: make sure to pull mac header
+    - media: stv0288: use explicitly signed char
+    - soc: qcom: Select REMAP_MMIO for LLCC driver
+    - kest.pl: Fix grub2 menu handling for rebooting
+    - ktest.pl minconfig: Unset configs instead of just removing them
+    - mmc: sdhci-sprd: Disable CLK_AUTO when the clock is less than 400K
+    - btrfs: fix resolving backrefs for inline extent followed by prealloc
+    - ARM: ux500: do not directly dereference __iomem
+    - arm64: dts: qcom: sdm850-lenovo-yoga-c630: correct I2C12 pins drive strength
+    - selftests: Use optional USERCFLAGS and USERLDFLAGS
+    - cpufreq: Init completion before kobject_init_and_add()
+    - binfmt: Move install_exec_creds after setup_new_exec to match binfmt_elf
+    - binfmt: Fix error return code in load_elf_fdpic_binary()
+    - dm cache: Fix ABBA deadlock between shrink_slab and dm_cache_metadata_abort
+    - dm thin: Fix ABBA deadlock between shrink_slab and dm_pool_abort_metadata
+    - dm thin: Use last transaction's pmd->root when commit failed
+    - dm thin: Fix UAF in run_timer_softirq()
+    - dm integrity: Fix UAF in dm_integrity_dtr()
+    - dm clone: Fix UAF in clone_dtr()
+    - dm cache: Fix UAF in destroy()
+    - dm cache: set needs_check flag after aborting metadata
+    - tracing/hist: Fix out-of-bound write on 'action_data.var_ref_idx'
+    - x86/microcode/intel: Do not retry microcode reloading on the APs
+    - tracing/hist: Fix wrong return value in parse_action_params()
+    - tracing: Fix infinite loop in tracing_read_pipe on overflowed
+      print_trace_line
+    - ARM: 9256/1: NWFPE: avoid compiler-generated __aeabi_uldivmod
+    - media: dvb-core: Fix double free in dvb_register_device()
+    - cifs: fix confusing debug message
+    - cifs: fix missing display of three mount options
+    - md/bitmap: Fix bitmap chunk size overflow issues
+    - efi: Add iMac Pro 2017 to uefi skip cert quirk
+    - ipmi: fix long wait in unload when IPMI disconnect
+    - mtd: spi-nor: Check for zero erase size in spi_nor_find_best_erase_type()
+    - ima: Fix a potential NULL pointer access in ima_restore_measurement_list
+    - ipmi: fix use after free in _ipmi_destroy_user()
+    - PCI: Fix pci_device_is_present() for VFs by checking PF
+    - PCI/sysfs: Fix double free in error path
+    - crypto: n2 - add missing hash statesize
+    - iommu/amd: Fix ivrs_acpihid cmdline parsing code
+    - parisc: led: Fix potential null-ptr-deref in start_task()
+    - device_cgroup: Roll back to original exceptions after copy failure
+    - drm/connector: send hotplug uevent on connector cleanup
+    - drm/vmwgfx: Validate the box size for the snooped cursor
+    - ext4: add inode table check in __ext4_get_inode_loc to aovid possible
+      infinite loop
+    - ext4: fix undefined behavior in bit shift for ext4_check_flag_values
+    - ext4: add EXT4_IGET_BAD flag to prevent unexpected bad inode
+    - ext4: add helper to check quota inums
+    - ext4: fix reserved cluster accounting in __es_remove_extent()
+    - ext4: fix bug_on in __es_tree_search caused by bad boot loader inode
+    - ext4: init quota for 'old.inode' in 'ext4_rename'
+    - ext4: fix delayed allocation bug in ext4_clu_mapped for bigalloc + inline
+    - ext4: fix corruption when online resizing a 1K bigalloc fs
+    - ext4: fix error code return to user-space in ext4_get_branch()
+    - ext4: avoid BUG_ON when creating xattrs
+    - ext4: fix inode leak in ext4_xattr_inode_create() on an error path
+    - ext4: initialize quota before expanding inode in setproject ioctl
+    - ext4: avoid unaccounted block allocation when expanding inode
+    - ext4: allocate extended attribute value in vmalloc area
+    - btrfs: replace strncpy() with strscpy()
+    - PM/devfreq: governor: Add a private governor_data for governor
+    - media: s5p-mfc: Fix to handle reference queue during finishing
+    - media: s5p-mfc: Clear workbit to handle error condition
+    - media: s5p-mfc: Fix in register read and write for H264
+    - dm thin: resume even if in FAIL mode
+    - perf probe: Use dwarf_attr_integrate as generic DWARF attr accessor
+    - perf probe: Fix to get the DW_AT_decl_file and DW_AT_call_file as unsinged
+      data
+    - KVM: x86: optimize more exit handlers in vmx.c
+    - KVM: retpolines: x86: eliminate retpoline from vmx.c exit handlers
+    - KVM: VMX: Rename INTERRUPT_PENDING to INTERRUPT_WINDOW
+    - KVM: VMX: Rename NMI_PENDING to NMI_WINDOW
+    - KVM: VMX: Fix the spelling of CPU_BASED_USE_TSC_OFFSETTING
+    - KVM: nVMX: Properly expose ENABLE_USR_WAIT_PAUSE control to L1
+    - ravb: Fix "failed to switch device to config mode" message during unbind
+    - ext4: goto right label 'failed_mount3a'
+    - ext4: correct inconsistent error msg in nojournal mode
+    - mm/highmem: Lift memcpy_[to|from]_page to core
+    - ext4: use memcpy_to_page() in pagecache_write()
+    - fs: ext4: initialize fsdata in pagecache_write()
+    - ext4: use kmemdup() to replace kmalloc + memcpy
+    - mbcache: don't reclaim used entries
+    - mbcache: add functions to delete entry if unused
+    - ext4: remove EA inode entry from mbcache on inode eviction
+    - ext4: unindent codeblock in ext4_xattr_block_set()
+    - ext4: fix race when reusing xattr blocks
+    - mbcache: automatically delete entries from cache on freeing
+    - ext4: fix deadlock due to mbcache entry corruption
+    - SUNRPC: ensure the matching upcall is in-flight upon downcall
+    - bpf: pull before calling skb_postpull_rcsum()
+    - nfsd: shut down the NFSv4 state objects before the filecache
+    - net: hns3: add interrupts re-initialization while doing VF FLR
+    - net: sched: fix memory leak in tcindex_set_parms
+    - qlcnic: prevent ->dcb use-after-free on qlcnic_dcb_enable() failure
+    - nfc: Fix potential resource leaks
+    - vhost: fix range used in translate_desc()
+    - net: amd-xgbe: add missed tasklet_kill
+    - net: phy: xgmiitorgmii: Fix refcount leak in xgmiitorgmii_probe
+    - RDMA/uverbs: Silence shiftTooManyBitsSigned warning
+    - RDMA/mlx5: Fix validation of max_rd_atomic caps for DC
+    - net: sched: atm: dont intepret cls results when asked to drop
+    - net: sched: cbq: dont intepret cls results when asked to drop
+    - perf tools: Fix resources leak in perf_data__open_dir()
+    - drivers/net/bonding/bond_3ad: return when there's no aggregator
+    - usb: rndis_host: Secure rndis_query check against int overflow
+    - drm/i915: unpin on error in intel_vgpu_shadow_mm_pin()
+    - caif: fix memory leak in cfctrl_linkup_request()
+    - udf: Fix extension of the last extent in the file
+    - ASoC: Intel: bytcr_rt5640: Add quirk for the Advantech MICA-071 tablet
+    - x86/bugs: Flush IBP in ib_prctl_set()
+    - nfsd: fix handling of readdir in v4root vs. mount upcall timeout
+    - riscv: uaccess: fix type of 0 variable on error in get_user()
+    - ext4: don't allow journal inode to have encrypt flag
+    - hfs/hfsplus: use WARN_ON for sanity check
+    - hfs/hfsplus: avoid WARN_ON() for sanity check, use proper error handling
+    - mbcache: Avoid nesting of cache->c_list_lock under bit locks
+    - parisc: Align parisc MADV_XXX constants with all other architectures
+    - selftests: Fix kselftest O=objdir build from cluttering top level objdir
+    - selftests: set the BUILD variable to absolute path
+    - driver core: Fix bus_type.match() error handling in __driver_attach()
+    - net: sched: disallow noqueue for qdisc classes
+    - KVM: arm64: Fix S1PTW handling on RO memslots
+    - efi: tpm: Avoid READ_ONCE() for accessing the event log
+    - docs: Fix the docs build with Sphinx 6.0
+    - perf auxtrace: Fix address filter duplicate symbol selection
+    - s390/kexec: fix ipl report address for kdump
+    - s390/percpu: add READ_ONCE() to arch_this_cpu_to_op_simple()
+    - net/ulp: prevent ULP without clone op from entering the LISTEN status
+    - ALSA: hda/hdmi: Add a HP device 0x8715 to force connect list
+    - cifs: Fix uninitialized memory read for smb311 posix symlink create
+    - drm/msm/adreno: Make adreno quirks not overwrite each other
+    - platform/x86: sony-laptop: Don't turn off 0x153 keyboard backlight during
+      probe
+    - ixgbe: fix pci device refcount leak
+    - ipv6: raw: Deduct extension header length in rawv6_push_pending_frames
+    - wifi: wilc1000: sdio: fix module autoloading
+    - usb: ulpi: defer ulpi_register on ulpi_read_id timeout
+    - jbd2: use the correct print format
+    - quota: Factor out setup of quota inode
+    - ext4: fix bug_on in __es_tree_search caused by bad quota inode
+    - ext4: lost matching-pair of trace in ext4_truncate
+    - ext4: fix use-after-free in ext4_orphan_cleanup
+    - ext4: fix uninititialized value in 'ext4_evict_inode'
+    - netfilter: ipset: Fix overflow before widen in the bitmap_ip_create()
+      function.
+    - powerpc/imc-pmu: Fix use of mutex in IRQs disabled section
+    - x86/boot: Avoid using Intel mnemonics in AT&T syntax asm
+    - EDAC/device: Fix period calculation in edac_device_reset_delay_period()
+    - regulator: da9211: Use irq handler when ready
+    - tipc: improve throughput between nodes in netns
+    - tipc: eliminate checking netns if node established
+    - tipc: fix unexpected link reset due to discovery messages
+    - hvc/xen: lock console list traversal
+    - nfc: pn533: Wait for out_urb's completion in pn533_usb_send_frame()
+    - net/sched: act_mpls: Fix warning during failed attribute validation
+    - net/mlx5: Rename ptp clock info
+    - net/mlx5: Fix ptp max frequency adjustment range
+    - iommu/mediatek-v1: Add error handle for mtk_iommu_probe
+    - iommu/mediatek-v1: Fix an error handling path in mtk_iommu_v1_probe()
+    - x86/resctrl: Use task_curr() instead of task_struct->on_cpu to prevent
+      unnecessary IPI
+    - x86/resctrl: Fix task CLOSID/RMID update race
+    - drm/virtio: Fix GEM handle creation UAF
+    - arm64: atomics: format whitespace consistently
+    - arm64: atomics: remove LL/SC trampolines
+    - arm64: cmpxchg_double*: hazard against entire exchange variable
+    - efi: fix NULL-deref in init error path
+    - mm: Always release pages to the buddy allocator in memblock_free_late().
+    - Revert "usb: ulpi: defer ulpi_register on ulpi_read_id timeout"
+    - tipc: fix use-after-free in tipc_disc_rcv()
+    - tty: serial: tegra: Handle RX transfer in PIO mode if DMA wasn't started
+    - tipc: Add a missing case of TIPC_DIRECT_MSG type
+    - ocfs2: fix freeing uninitialized resource on ocfs2_dlm_shutdown
+    - tipc: call tipc_lxc_xmit without holding node_read_lock
+    - Linux 5.4.229
+  * Focal update: v5.4.229 upstream stable release (LP: #2003914) //
+    CVE-2023-0266 was assigned for this issue.
+    - ALSA: pcm: Move rwsem lock inside snd_ctl_elem_read to prevent UAF
+  * Focal update: v5.4.229 upstream stable release (LP: #2003914) //
+    CVE-2022-41218 is assigned to those bugs above.
+    - media: dvb-core: Fix UAF due to refcount races at releasing
+  * Focal update: v5.4.228 upstream stable release (LP: #2003904)
+    - x86/smpboot: Move rcu_cpu_starting() earlier
+    - mm/hugetlb: fix races when looking up a CONT-PTE/PMD size hugetlb page
+    - block: unhash blkdev part inode when the part is deleted
+    - ASoC: ops: Check bounds for second channel in snd_soc_put_volsw_sx()
+    - pinctrl: meditatek: Startup with the IRQs disabled
+    - can: sja1000: fix size of OCR_MODE_MASK define
+    - can: mcba_usb: Fix termination command argument
+    - ASoC: ops: Correct bounds check for second channel on SX controls
+    - Linux 5.4.228
+  * Focal update: v5.4.227 upstream stable release (LP: #2003901)
+    - arm64: dts: rockchip: keep I2S1 disabled for GPIO function on ROCK Pi 4
+      series
+    - arm: dts: rockchip: fix node name for hym8563 rtc
+    - ARM: dts: rockchip: fix ir-receiver node names
+    - ARM: dts: rockchip: rk3188: fix lcdc1-rgb24 node name
+    - ARM: 9251/1: perf: Fix stacktraces for tracepoint events in THUMB2 kernels
+    - ARM: 9266/1: mm: fix no-MMU ZERO_PAGE() implementation
+    - ARM: dts: rockchip: disable arm_global_timer on rk3066 and rk3188
+    - 9p/fd: Use P9_HDRSZ for header size
+    - regulator: slg51000: Wait after asserting CS pin
+    - ALSA: seq: Fix function prototype mismatch in snd_seq_expand_var_event
+    - btrfs: send: avoid unaligned encoded writes when attempting to clone range
+    - ASoC: soc-pcm: Add NULL check in BE reparenting
+    - regulator: twl6030: fix get status of twl6032 regulators
+    - fbcon: Use kzalloc() in fbcon_prepare_logo()
+    - 9p/xen: check logical size for buffer size
+    - net: usb: qmi_wwan: add u-blox 0x1342 composition
+    - mm/khugepaged: take the right locks for page table retraction
+    - mm/khugepaged: fix GUP-fast interaction by sending IPI
+    - mm/khugepaged: invoke MMU notifiers in shmem/file collapse paths
+    - xen/netback: do some code cleanup
+    - xen/netback: don't call kfree_skb() with interrupts disabled
+    - Revert "net: dsa: b53: Fix valid setting for MDB entries"
+    - media: v4l2-dv-timings.c: fix too strict blanking sanity checks
+    - memcg: fix possible use-after-free in memcg_write_event_control()
+    - mm/gup: fix gup_pud_range() for dax
+    - KVM: s390: vsie: Fix the initialization of the epoch extension (epdx) field
+    - drm/shmem-helper: Remove errant put in error path
+    - HID: usbhid: Add ALWAYS_POLL quirk for some mice
+    - HID: hid-lg4ff: Add check for empty lbuf
+    - HID: core: fix shift-out-of-bounds in hid_report_raw_event
+    - can: af_can: fix NULL pointer dereference in can_rcv_filter
+    - ieee802154: cc2520: Fix error return code in cc2520_hw_init()
+    - ca8210: Fix crash by zero initializing data
+    - drm/bridge: ti-sn65dsi86: Fix output polarity setting bug
+    - gpio: amd8111: Fix PCI device reference count leak
+    - e1000e: Fix TX dispatch condition
+    - igb: Allocate MSI-X vector when testing
+    - af_unix: Get user_ns from in_skb in unix_diag_get_exact().
+    - Bluetooth: 6LoWPAN: add missing hci_dev_put() in get_l2cap_conn()
+    - Bluetooth: Fix not cleanup led when bt_init fails
+    - net: dsa: ksz: Check return value
+    - selftests: rtnetlink: correct xfrm policy rule in kci_test_ipsec_offload
+    - mac802154: fix missing INIT_LIST_HEAD in ieee802154_if_add()
+    - net: encx24j600: Add parentheses to fix precedence
+    - net: encx24j600: Fix invalid logic in reading of MISTAT register
+    - xen-netfront: Fix NULL sring after live migration
+    - net: mvneta: Prevent out of bounds read in mvneta_config_rss()
+    - i40e: Fix not setting default xps_cpus after reset
+    - i40e: Fix for VF MAC address 0
+    - i40e: Disallow ip4 and ip6 l4_4_bytes
+    - NFC: nci: Bounds check struct nfc_target arrays
+    - nvme initialize core quirks before calling nvme_init_subsystem
+    - net: stmmac: fix "snps,axi-config" node property parsing
+    - net: thunderx: Fix missing destroy_workqueue of nicvf_rx_mode_wq
+    - net: hisilicon: Fix potential use-after-free in hisi_femac_rx()
+    - net: hisilicon: Fix potential use-after-free in hix5hd2_rx()
+    - tipc: Fix potential OOB in tipc_link_proto_rcv()
+    - ipv4: Fix incorrect route flushing when source address is deleted
+    - ipv4: Fix incorrect route flushing when table ID 0 is used
+    - ethernet: aeroflex: fix potential skb leak in greth_init_rings()
+    - net: plip: don't call kfree_skb/dev_kfree_skb() under spin_lock_irq()
+    - ipv6: avoid use-after-free in ip6_fragment()
+    - net: mvneta: Fix an out of bounds check
+    - can: esd_usb: Allow REC and TEC to return to zero
+    - Linux 5.4.227
+  * 5.15.0-58.64 breaks xen bridge networking (pvh domU) (LP: #2002889) // Focal
+    update: v5.4.227 upstream stable release (LP: #2003901)
+    - xen/netback: fix build warning
+  * Focal update: v5.4.226 upstream stable release (LP: #2003896)
+    - wifi: mac80211: fix memory free error when registering wiphy fail
+    - wifi: mac80211_hwsim: fix debugfs attribute ps with rc table support
+    - audit: fix undefined behavior in bit shift for AUDIT_BIT
+    - wifi: mac80211: Fix ack frame idr leak when mesh has no route
+    - spi: stm32: fix stm32_spi_prepare_mbr() that halves spi clk for every run
+    - drm: panel-orientation-quirks: Add quirk for Acer Switch V 10 (SW5-017)
+    - block, bfq: fix null pointer dereference in bfq_bio_bfqg()
+    - arm64/syscall: Include asm/ptrace.h in syscall_wrapper header.
+    - RISC-V: vdso: Do not add missing symbols to version section in linker script
+    - MIPS: pic32: treat port as signed integer
+    - af_key: Fix send_acquire race with pfkey_register
+    - ARM: dts: am335x-pcm-953: Define fixed regulators in root node
+    - ASoC: sgtl5000: Reset the CHIP_CLK_CTRL reg on remove
+    - regulator: core: fix kobject release warning and memory leak in
+      regulator_register()
+    - regulator: core: fix UAF in destroy_regulator()
+    - bus: sunxi-rsb: Support atomic transfers
+    - tee: optee: fix possible memory leak in optee_register_device()
+    - ARM: dts: at91: sam9g20ek: enable udc vbus gpio pinctrl
+    - net: liquidio: simplify if expression
+    - nfc/nci: fix race with opening and closing
+    - net: pch_gbe: fix potential memleak in pch_gbe_tx_queue()
+    - 9p/fd: fix issue of list_del corruption in p9_fd_cancel()
+    - ARM: mxs: fix memory leak in mxs_machine_init()
+    - net/mlx4: Check retval of mlx4_bitmap_init
+    - net/qla3xxx: fix potential memleak in ql3xxx_send()
+    - net: pch_gbe: fix pci device refcount leak while module exiting
+    - nfp: add port from netdev validation for EEPROM access
+    - Drivers: hv: vmbus: fix double free in the error path of
+      vmbus_add_channel_work()
+    - Drivers: hv: vmbus: fix possible memory leak in vmbus_device_register()
+    - net/mlx5: Fix FW tracer timestamp calculation
+    - tipc: set con sock in tipc_conn_alloc
+    - tipc: add an extra conn_get in tipc_conn_alloc
+    - tipc: check skb_linearize() return value in tipc_disc_rcv()
+    - xfrm: Fix ignored return value in xfrm6_init()
+    - NFC: nci: fix memory leak in nci_rx_data_packet()
+    - regulator: twl6030: re-add TWL6032_SUBCLASS
+    - bnx2x: fix pci device refcount leak in bnx2x_vf_is_pcie_pending()
+    - dccp/tcp: Reset saddr on failure after inet6?_hash_connect().
+    - s390/dasd: fix no record found for raw_track_access
+    - nfc: st-nci: fix incorrect validating logic in EVT_TRANSACTION
+    - nfc: st-nci: fix memory leaks in EVT_TRANSACTION
+    - net: thunderx: Fix the ACPI memory leak
+    - s390/crashdump: fix TOD programmable field size
+    - lib/vdso: use "grep -E" instead of "egrep"
+    - usb: dwc3: exynos: Fix remove() function
+    - arm64: dts: rockchip: lower rk3399-puma-haikou SD controller clock frequency
+    - iio: light: apds9960: fix wrong register for gesture gain
+    - iio: core: Fix entry not deleted when iio_register_sw_trigger_type() fails
+    - init/Kconfig: fix CC_HAS_ASM_GOTO_TIED_OUTPUT test with dash
+    - nios2: add FORCE for vmlinuz.gz
+    - iio: ms5611: Simplify IO callback parameters
+    - iio: pressure: ms5611: fixed value compensation bug
+    - ceph: do not update snapshot context when there is no new snapshot
+    - ceph: avoid putting the realm twice when decoding snaps fails
+    - firmware: google: Release devices before unregistering the bus
+    - firmware: coreboot: Register bus in module init
+    - nilfs2: fix nilfs_sufile_mark_dirty() not set segment usage as dirty
+    - gcov: clang: fix the buffer overflow issue
+    - Input: synaptics - switch touchpad on HP Laptop 15-da3001TU to RMI mode
+    - ASoC: Intel: bytcht_es8316: Add quirk for the Nanote UMPC-01
+    - serial: 8250: 8250_omap: Avoid RS485 RTS glitch on ->set_termios()
+    - xen/platform-pci: add missing free_irq() in error path
+    - platform/x86: asus-wmi: add missing pci_dev_put() in asus_wmi_set_xusb2pr()
+    - platform/x86: acer-wmi: Enable SW_TABLET_MODE on Switch V 10 (SW5-017)
+    - platform/x86: hp-wmi: Ignore Smart Experience App event
+    - [Config] updateconfigs for INET_TABLE_PERTURB_ORDER
+    - tcp: configurable source port perturb table size
+    - net: usb: qmi_wwan: add Telit 0x103a composition
+    - dm integrity: flush the journal on suspend
+    - binder: avoid potential data leakage when copying txn
+    - binder: read pre-translated fds from sender buffer
+    - binder: defer copies of pre-patched txn data
+    - binder: fix pointer cast warning
+    - binder: Address corner cases in deferred copy and fixup
+    - binder: Gracefully handle BINDER_TYPE_FDA objects with num_fds=0
+    - btrfs: free btrfs_path before copying root refs to userspace
+    - btrfs: free btrfs_path before copying fspath to userspace
+    - btrfs: free btrfs_path before copying subvol info to userspace
+    - btrfs: sysfs: normalize the error handling branch in btrfs_init_sysfs()
+    - drm/amd/dc/dce120: Fix audio register mapping, stop triggering KASAN
+    - drm/amdgpu: always register an MMU notifier for userptr
+    - fuse: lock inode unconditionally in fuse_fallocate()
+    - btrfs: free btrfs_path before copying inodes to userspace
+    - spi: spi-imx: Fix spi_bus_clk if requested clock is higher than input clock
+    - btrfs: move QUOTA_ENABLED check to rescan_should_stop from
+      btrfs_qgroup_rescan_worker
+    - drm/amdgpu: update drm_display_info correctly when the edid is read
+    - drm/amdgpu: Partially revert "drm/amdgpu: update drm_display_info correctly
+      when the edid is read"
+    - btrfs: qgroup: fix sleep from invalid context bug in btrfs_qgroup_inherit()
+    - iio: health: afe4403: Fix oob read in afe4403_read_raw
+    - iio: health: afe4404: Fix oob read in afe4404_[read|write]_raw
+    - iio: light: rpr0521: add missing Kconfig dependencies
+    - scripts/faddr2line: Fix regression in name resolution on ppc64le
+    - hwmon: (i5500_temp) fix missing pci_disable_device()
+    - hwmon: (ibmpex) Fix possible UAF when ibmpex_register_bmc() fails
+    - of: property: decrement node refcount in of_fwnode_get_reference_args()
+    - net/mlx5: Fix uninitialized variable bug in outlen_write()
+    - net/mlx5e: Fix use-after-free when reverting termination table
+    - can: sja1000_isa: sja1000_isa_probe(): add missing free_sja1000dev()
+    - can: cc770: cc770_isa_probe(): add missing free_cc770dev()
+    - qlcnic: fix sleep-in-atomic-context bugs caused by msleep
+    - wifi: cfg80211: fix buffer overflow in elem comparison
+    - net: phy: fix null-ptr-deref while probe() failed
+    - net: net_netdev: Fix error handling in ntb_netdev_init_module()
+    - net/9p: Fix a potential socket leak in p9_socket_open
+    - net: ethernet: nixge: fix NULL dereference
+    - dsa: lan9303: Correct stat name
+    - net: hsr: Fix potential use-after-free
+    - afs: Fix fileserver probe RTT handling
+    - net: tun: Fix use-after-free in tun_detach()
+    - packet: do not set TP_STATUS_CSUM_VALID on CHECKSUM_COMPLETE
+    - sctp: fix memory leak in sctp_stream_outq_migrate()
+    - net: ethernet: renesas: ravb: Fix promiscuous mode after system resumed
+    - hwmon: (coretemp) Check for null before removing sysfs attrs
+    - hwmon: (coretemp) fix pci device refcount leak in nv1a_ram_new()
+    - net/mlx5: DR, Fix uninitialized var warning
+    - error-injection: Add prompt for function error injection
+    - tools/vm/slabinfo-gnuplot: use "grep -E" instead of "egrep"
+    - nilfs2: fix NULL pointer dereference in nilfs_palloc_commit_free_entry()
+    - x86/bugs: Make sure MSR_SPEC_CTRL is updated properly upon resume from S3
+    - pinctrl: intel: Save and restore pins in "direct IRQ" mode
+    - mmc: mmc_test: Fix removal of debugfs file
+    - mmc: core: Fix ambiguous TRIM and DISCARD arg
+    - mmc: sdhci-esdhc-imx: correct CQHCI exit halt state check
+    - mmc: sdhci-sprd: Fix no reset data and command after voltage switch
+    - tracing: Free buffers when a used dynamic event is removed
+    - arm64: Fix panic() when Spectre-v2 causes Spectre-BHB to re-allocate KVM
+      vectors
+    - arm64: errata: Fix KVM Spectre-v2 mitigation selection for Cortex-A57/A72
+    - mm: Fix '.data.once' orphan section warning
+    - ASoC: ops: Fix bounds check for _sx controls
+    - pinctrl: single: Fix potential division by zero
+    - iommu/vt-d: Fix PCI device refcount leak in dmar_dev_scope_init()
+    - parisc: Increase size of gcc stack frame check
+    - xtensa: increase size of gcc stack frame check
+    - parisc: Increase FRAME_WARN to 2048 bytes on parisc
+    - Kconfig.debug: provide a little extra FRAME_WARN leeway when KASAN is
+      enabled
+    - selftests: net: add delete nexthop route warning test
+    - selftests: net: fix nexthop warning cleanup double ip typo
+    - ipv4: Handle attempt to delete multipath route when fib_info contains an nh
+      reference
+    - ipv4: Fix route deletion when nexthop info is not specified
+    - tracing/ring-buffer: Have polling block on watermark
+    - nvme: restrict management ioctls to admin
+    - nvme: ensure subsystem reset is single threaded
+    - x86/tsx: Add a feature bit for TSX control MSR support
+    - x86/pm: Add enumeration check before spec MSRs save/restore setup
+    - x86/ioremap: Fix page aligned size calculation in __ioremap_caller()
+    - Revert "clocksource/drivers/riscv: Events are stopped during CPU suspend"
+    - char: tpm: Protect tpm_pm_suspend with locks
+    - mmc: sdhci: use FIELD_GET for preset value bit masks
+    - mmc: sdhci: Fix voltage switch delay
+    - proc: avoid integer type confusion in get_proc_long
+    - proc: proc_skip_spaces() shouldn't think it is working on C strings
+    - v4l2: don't fall back to follow_pfn() if pin_user_pages_fast() fails
+    - ipc/sem: Fix dangling sem_array access in semtimedop race
+    - Linux 5.4.226
+  * CVE-2022-4139
+    - drm/i915: fix TLB invalidation for Gen12 video and compute engines
+  * Focal update: v5.4.225 upstream stable release (LP: #2002347)
+    - xfs: preserve rmapbt swapext block reservation from freed blocks
+    - xfs: rename xfs_bmap_is_real_extent to is_written_extent
+    - xfs: redesign the reflink remap loop to fix blkres depletion crash
+    - xfs: use MMAPLOCK around filemap_map_pages()
+    - xfs: preserve inode versioning across remounts
+    - xfs: drain the buf delwri queue before xfsaild idles
+    - phy: stm32: fix an error code in probe
+    - wifi: cfg80211: silence a sparse RCU warning
+    - wifi: cfg80211: fix memory leak in query_regdb_file()
+    - bpf, sockmap: Fix the sk->sk_forward_alloc warning of sk_stream_kill_queues
+    - HID: hyperv: fix possible memory leak in mousevsc_probe()
+    - net: gso: fix panic on frag_list with mixed head alloc types
+    - net: tun: Fix memory leaks of napi_get_frags
+    - bnxt_en: Fix possible crash in bnxt_hwrm_set_coal()
+    - bnxt_en: fix potentially incorrect return value for ndo_rx_flow_steer
+    - net: fman: Unregister ethernet device on removal
+    - capabilities: fix undefined behavior in bit shift for CAP_TO_MASK
+    - net: lapbether: fix issue of dev reference count leakage in
+      lapbeth_device_event()
+    - hamradio: fix issue of dev reference count leakage in bpq_device_event()
+    - drm/vc4: Fix missing platform_unregister_drivers() call in
+      vc4_drm_register()
+    - ipv6: addrlabel: fix infoleak when sending struct ifaddrlblmsg to network
+    - can: af_can: fix NULL pointer dereference in can_rx_register()
+    - tipc: fix the msg->req tlv len check in
+      tipc_nl_compat_name_table_dump_header
+    - dmaengine: pxa_dma: use platform_get_irq_optional
+    - dmaengine: mv_xor_v2: Fix a resource leak in mv_xor_v2_remove()
+    - drivers: net: xgene: disable napi when register irq failed in
+      xgene_enet_open()
+    - perf stat: Fix printing os->prefix in CSV metrics output
+    - net: nixge: disable napi when enable interrupts failed in nixge_open()
+    - net/mlx5: Allow async trigger completion execution on single CPU systems
+    - net: cpsw: disable napi in cpsw_ndo_open()
+    - net: cxgb3_main: disable napi when bind qsets failed in cxgb_up()
+    - cxgb4vf: shut down the adapter when t4vf_update_port_info() failed in
+      cxgb4vf_open()
+    - ethernet: s2io: disable napi when start nic failed in s2io_card_up()
+    - net: mv643xx_eth: disable napi when init rxq or txq failed in
+      mv643xx_eth_open()
+    - ethernet: tundra: free irq when alloc ring failed in tsi108_open()
+    - net: macvlan: fix memory leaks of macvlan_common_newlink
+    - riscv: process: fix kernel info leakage
+    - arm64: efi: Fix handling of misaligned runtime regions and drop warning
+    - MIPS: jump_label: Fix compat branch range check
+    - mmc: cqhci: Provide helper for resetting both SDHCI and CQHCI
+    - mmc: sdhci-of-arasan: Fix SDHCI_RESET_ALL for CQHCI
+    - mmc: sdhci-tegra: Fix SDHCI_RESET_ALL for CQHCI
+    - ALSA: hda/ca0132: add quirk for EVGA Z390 DARK
+    - ALSA: hda: fix potential memleak in 'add_widget_node'
+    - ALSA: usb-audio: Add quirk entry for M-Audio Micro
+    - ALSA: usb-audio: Add DSD support for Accuphase DAC-60
+    - vmlinux.lds.h: Fix placement of '.data..decrypted' section
+    - nilfs2: fix deadlock in nilfs_count_free_blocks()
+    - nilfs2: fix use-after-free bug of ns_writer on remount
+    - drm/i915/dmabuf: fix sg_table handling in map_dma_buf
+    - btrfs: selftests: fix wrong error check in btrfs_free_dummy_root()
+    - udf: Fix a slab-out-of-bounds write bug in udf_find_entry()
+    - can: j1939: j1939_send_one(): fix missing CAN header initialization
+    - cert host tools: Stop complaining about deprecated OpenSSL functions
+    - dmaengine: at_hdmac: Fix at_lli struct definition
+    - dmaengine: at_hdmac: Don't start transactions at tx_submit level
+    - dmaengine: at_hdmac: Fix completion of unissued descriptor in case of errors
+    - dmaengine: at_hdmac: Don't allow CPU to reorder channel enable
+    - dmaengine: at_hdmac: Fix impossible condition
+    - dmaengine: at_hdmac: Check return code of dma_async_device_register
+    - net: tun: call napi_schedule_prep() to ensure we own a napi
+    - x86/cpu: Restore AMD's DE_CFG MSR after resume
+    - ASoC: wm5102: Revert "ASoC: wm5102: Fix PM disable depth imbalance in
+      wm5102_probe"
+    - ASoC: wm5110: Revert "ASoC: wm5110: Fix PM disable depth imbalance in
+      wm5110_probe"
+    - ASoC: wm8997: Revert "ASoC: wm8997: Fix PM disable depth imbalance in
+      wm8997_probe"
+    - ASoC: wm8962: Add an event handler for TEMP_HP and TEMP_SPK
+    - spi: intel: Fix the offset to get the 64K erase opcode
+    - ASoC: codecs: jz4725b: add missed Line In power control bit
+    - ASoC: codecs: jz4725b: fix reported volume for Master ctl
+    - ASoC: codecs: jz4725b: use right control for Capture Volume
+    - ASoC: codecs: jz4725b: fix capture selector naming
+    - selftests/futex: fix build for clang
+    - selftests/intel_pstate: fix build for ARCH=x86_64
+    - NFSv4: Retry LOCK on OLD_STATEID during delegation return
+    - i2c: i801: add lis3lv02d's I2C address for Vostro 5568
+    - drm/imx: imx-tve: Fix return type of imx_tve_connector_mode_valid
+    - btrfs: remove pointless and double ulist frees in error paths of qgroup
+      tests
+    - ASoC: codecs: jz4725b: Fix spelling mistake "Sourc" -> "Source", "Routee" ->
+      "Route"
+    - spi: stm32: Print summary 'callbacks suppressed' message
+    - ASoC: core: Fix use-after-free in snd_soc_exit()
+    - serial: 8250_omap: remove wait loop from Errata i202 workaround
+    - serial: 8250: omap: Fix unpaired pm_runtime_put_sync() in omap8250_remove()
+    - serial: 8250: omap: Flush PM QOS work on remove
+    - serial: imx: Add missing .thaw_noirq hook
+    - tty: n_gsm: fix sleep-in-atomic-context bug in gsm_control_send
+    - ASoC: soc-utils: Remove __exit for snd_soc_util_exit()
+    - block: sed-opal: kmalloc the cmd/resp buffers
+    - siox: fix possible memory leak in siox_device_add()
+    - parport_pc: Avoid FIFO port location truncation
+    - pinctrl: devicetree: fix null pointer dereferencing in pinctrl_dt_to_map
+    - arm64: dts: imx8mm: Fix NAND controller size-cells
+    - arm64: dts: imx8mn: Fix NAND controller size-cells
+    - ata: libata-transport: fix double ata_host_put() in ata_tport_add()
+    - net: bgmac: Drop free_netdev() from bgmac_enet_remove()
+    - mISDN: fix possible memory leak in mISDN_dsp_element_register()
+    - net: liquidio: release resources when liquidio driver open failed
+    - mISDN: fix misuse of put_device() in mISDN_register_device()
+    - net: macvlan: Use built-in RCU list checking
+    - net: caif: fix double disconnect client in chnl_net_open()
+    - bnxt_en: Remove debugfs when pci_register_driver failed
+    - xen/pcpu: fix possible memory leak in register_pcpu()
+    - drbd: use after free in drbd_create_device()
+    - platform/x86/intel: pmc: Don't unconditionally attach Intel PMC when
+      virtualized
+    - net/x25: Fix skb leak in x25_lapb_receive_frame()
+    - cifs: Fix wrong return value checking when GETFLAGS
+    - net: thunderbolt: Fix error handling in tbnet_init()
+    - cifs: add check for returning value of SMB2_set_info_init
+    - ftrace: Fix the possible incorrect kernel message
+    - ftrace: Optimize the allocation for mcount entries
+    - ftrace: Fix null pointer dereference in ftrace_add_mod()
+    - ring_buffer: Do not deactivate non-existant pages
+    - ALSA: usb-audio: Drop snd_BUG_ON() from snd_usbmidi_output_open()
+    - Revert "usb: dwc3: disable USB core PHY management"
+    - slimbus: stream: correct presence rate frequencies
+    - speakup: fix a segfault caused by switching consoles
+    - USB: serial: option: add Sierra Wireless EM9191
+    - USB: serial: option: remove old LARA-R6 PID
+    - USB: serial: option: add u-blox LARA-R6 00B modem
+    - USB: serial: option: add u-blox LARA-L6 modem
+    - USB: serial: option: add Fibocom FM160 0x0111 composition
+    - usb: add NO_LPM quirk for Realforce 87U Keyboard
+    - usb: chipidea: fix deadlock in ci_otg_del_timer
+    - iio: adc: at91_adc: fix possible memory leak in at91_adc_allocate_trigger()
+    - iio: trigger: sysfs: fix possible memory leak in iio_sysfs_trig_init()
+    - iio: pressure: ms5611: changed hardcoded SPI speed to value limited
+    - dm ioctl: fix misbehavior if list_versions races with module loading
+    - serial: 8250: Fall back to non-DMA Rx if IIR_RDI occurs
+    - serial: 8250_lpss: Configure DMA also w/o DMA filter
+    - Input: iforce - invert valid length check when fetching device IDs
+    - scsi: zfcp: Fix double free of FSF request when qdio send fails
+    - mmc: core: properly select voltage range without power cycle
+    - mmc: sdhci-pci-o2micro: fix card detect fail issue caused by CD# debounce
+      timeout
+    - mmc: sdhci-pci: Fix possible memory leak caused by missing pci_dev_put()
+    - docs: update mediator contact information in CoC doc
+    - misc/vmw_vmci: fix an infoleak in vmci_host_do_receive_datagram()
+    - serial: 8250: Flush DMA Rx on RLSI
+    - ring-buffer: Include dropped pages in counting dirty patches
+    - scsi: target: tcm_loop: Fix possible name leak in tcm_loop_setup_hba_bus()
+    - kprobes: Skip clearing aggrprobe's post_handler in kprobe-on-ftrace case
+    - Input: i8042 - fix leaking of platform device on module removal
+    - macvlan: enforce a consistent minimal mtu
+    - tcp: cdg: allow tcp_cdg_release() to be called multiple times
+    - kcm: avoid potential race in kcm_tx_work
+    - bpf, test_run: Fix alignment problem in bpf_prog_test_run_skb()
+    - kcm: close race conditions on sk_receive_queue
+    - 9p: trans_fd/p9_conn_cancel: drop client lock earlier
+    - gfs2: Check sb_bsize_shift after reading superblock
+    - gfs2: Switch from strlcpy to strscpy
+    - 9p/trans_fd: always use O_NONBLOCK read/write
+    - mm: fs: initialize fsdata passed to write_begin/write_end interface
+    - ntfs: fix use-after-free in ntfs_attr_find()
+    - ntfs: fix out-of-bounds read in ntfs_attr_find()
+    - ntfs: check overflow when iterating ATTR_RECORDs
+    - Linux 5.4.225
+  * CVE-2022-47520
+    - wifi: wilc1000: validate pairwise and authentication suite offsets
+  * CVE-2022-3545
+    - nfp: fix use-after-free in area_cache_get()
+
+  [ Ubuntu: 5.4.0-139.156 ]
+
+  * focal/linux: 5.4.0-139.156 -proposed tracker (LP: #2003486)
+  * Revoke & rotate to new signing key (LP: #2002812)
+    - [Packaging] Revoke and rotate to new signing key
+
+ -- Masahiro Yamada <masahiro.yamada@canonical.com>  Wed, 15 Feb 2023 19:38:53 +0900
+
+linux-xilinx-zynqmp (5.4.0-1021.25) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1021.25 -proposed tracker (LP: #2003295)
+
+  * Focal update: v5.4.221 upstream stable release (LP: #1997993)
+    - [Config] updateconfigs for ARM64_ERRATUM_1742098
+
+  [ Ubuntu: 5.4.0-138.155 ]
+
+  * focal/linux: 5.4.0-138.155 -proposed tracker (LP: #2001845)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update helper scripts
+  * Focal update: v5.4.224 upstream stable release (LP: #1999273)
+    - RDMA/cma: Use output interface for net_dev check
+    - IB/hfi1: Correctly move list in sc_disable()
+    - NFSv4.1: Handle RECLAIM_COMPLETE trunking errors
+    - NFSv4.1: We must always send RECLAIM_COMPLETE after a reboot
+    - nfs4: Fix kmemleak when allocate slot failed
+    - net: dsa: Fix possible memory leaks in dsa_loop_init()
+    - RDMA/core: Fix null-ptr-deref in ib_core_cleanup()
+    - RDMA/qedr: clean up work queue on failure in qedr_alloc_resources()
+    - nfc: s3fwrn5: Fix potential memory leak in s3fwrn5_nci_send()
+    - nfc: nfcmrvl: Fix potential memory leak in nfcmrvl_i2c_nci_send()
+    - net: fec: fix improper use of NETDEV_TX_BUSY
+    - ata: pata_legacy: fix pdc20230_set_piomode()
+    - net: sched: Fix use after free in red_enqueue()
+    - net: tun: fix bugs for oversize packet when napi frags enabled
+    - netfilter: nf_tables: release flow rule object from commit path
+    - ipvs: use explicitly signed chars
+    - ipvs: fix WARNING in __ip_vs_cleanup_batch()
+    - ipvs: fix WARNING in ip_vs_app_net_cleanup()
+    - rose: Fix NULL pointer dereference in rose_send_frame()
+    - mISDN: fix possible memory leak in mISDN_register_device()
+    - isdn: mISDN: netjet: fix wrong check of device registration
+    - btrfs: fix inode list leak during backref walking at resolve_indirect_refs()
+    - btrfs: fix inode list leak during backref walking at find_parent_nodes()
+    - btrfs: fix ulist leaks in error paths of qgroup self tests
+    - Bluetooth: L2CAP: fix use-after-free in l2cap_conn_del()
+    - net: mdio: fix undefined behavior in bit shift for __mdiobus_register
+    - net, neigh: Fix null-ptr-deref in neigh_table_clear()
+    - ipv6: fix WARNING in ip6_route_net_exit_late()
+    - media: s5p_cec: limit msg.len to CEC_MAX_MSG_SIZE
+    - media: cros-ec-cec: limit msg.len to CEC_MAX_MSG_SIZE
+    - media: dvb-frontends/drxk: initialize err to 0
+    - media: meson: vdec: fix possible refcount leak in vdec_probe()
+    - scsi: core: Restrict legal sdev_state transitions via sysfs
+    - HID: saitek: add madcatz variant of MMO7 mouse device ID
+    - i2c: xiic: Add platform module alias
+    - xfs: don't fail verifier on empty attr3 leaf block
+    - xfs: use ordered buffers to initialize dquot buffers during quotacheck
+    - xfs: gut error handling in xfs_trans_unreserve_and_mod_sb()
+    - xfs: group quota should return EDQUOT when prj quota enabled
+    - xfs: don't fail unwritten extent conversion on writeback due to edquot
+    - xfs: Add the missed xfs_perag_put() for xfs_ifree_cluster()
+    - Bluetooth: L2CAP: Fix attempting to access uninitialized memory
+    - block, bfq: protect 'bfqd->queued' by 'bfqd->lock'
+    - binder: fix UAF of alloc->vma in race with munmap()
+    - btrfs: fix type of parameter generation in btrfs_get_dentry
+    - tcp/udp: Make early_demux back namespacified.
+    - kprobe: reverse kp->flags when arm_kprobe failed
+    - tools/nolibc/string: Fix memcmp() implementation
+    - tracing/histogram: Update document for KEYS_MAX size
+    - capabilities: fix potential memleak on error path from vfs_getxattr_alloc()
+    - fuse: add file_modified() to fallocate
+    - efi: random: reduce seed size to 32 bytes
+    - perf/x86/intel: Fix pebs event constraints for ICL
+    - perf/x86/intel: Add Cooper Lake stepping to isolation_ucodes[]
+    - ALSA: usb-audio: Add quirks for MacroSilicon MS2100/MS2106 devices
+    - parisc: Make 8250_gsc driver dependend on CONFIG_PARISC
+    - parisc: Export iosapic_serial_irq() symbol for serial port driver
+    - parisc: Avoid printing the hardware path twice
+    - ext4: fix warning in 'ext4_da_release_space'
+    - ext4: fix BUG_ON() when directory entry has invalid rec_len
+    - KVM: x86: Mask off reserved bits in CPUID.8000001AH
+    - KVM: x86: Mask off reserved bits in CPUID.80000008H
+    - KVM: x86: emulator: em_sysexit should update ctxt->mode
+    - KVM: x86: emulator: introduce emulator_recalc_and_set_mode
+    - KVM: x86: emulator: update the emulation mode after CR0 write
+    - mtd: rawnand: gpmi: Set WAIT_FOR_READY timeout based on program/erase times
+    - drm/rockchip: dsi: Force synchronous probe
+    - drm/i915/sdvo: Filter out invalid outputs more sensibly
+    - drm/i915/sdvo: Setup DDC fully before output init
+    - wifi: brcmfmac: Fix potential buffer overflow in brcmf_fweh_event_worker()
+    - ipc: remove memcg accounting for sops objects in do_semtimedop()
+    - Linux 5.4.224
+  * Focal update: v5.4.223 upstream stable release (LP: #1999179)
+    - can: j1939: transport: j1939_session_skb_drop_old():
+      spin_unlock_irqrestore() before kfree_skb()
+    - can: kvaser_usb: Fix possible completions during init_completion
+    - ALSA: Use del_timer_sync() before freeing timer
+    - ALSA: au88x0: use explicitly signed char
+    - USB: add RESET_RESUME quirk for NVIDIA Jetson devices in RCM
+    - usb: dwc3: gadget: Stop processing more requests on IMI
+    - usb: dwc3: gadget: Don't set IMI for no_interrupt
+    - usb: bdc: change state when port disconnected
+    - usb: xhci: add XHCI_SPURIOUS_SUCCESS to ASM1042 despite being a V0.96
+      controller
+    - mtd: rawnand: marvell: Use correct logic for nand-keep-config
+    - xhci: Remove device endpoints from bandwidth list when freeing the device
+    - tools: iio: iio_utils: fix digit calculation
+    - iio: light: tsl2583: Fix module unloading
+    - fbdev: smscufx: Fix several use-after-free bugs
+    - mac802154: Fix LQI recording
+    - drm/msm/dsi: fix memory corruption with too many bridges
+    - drm/msm/hdmi: fix memory corruption with too many bridges
+    - mmc: core: Fix kernel panic when remove non-standard SDIO card
+    - kernfs: fix use-after-free in __kernfs_remove
+    - perf auxtrace: Fix address filter symbol name match for modules
+    - s390/futex: add missing EX_TABLE entry to __futex_atomic_op()
+    - s390/pci: add missing EX_TABLE entries to
+      __pcistg_mio_inuser()/__pcilg_mio_inuser()
+    - xfs: finish dfops on every insert range shift iteration
+    - xfs: clear XFS_DQ_FREEING if we can't lock the dquot buffer to flush
+    - xfs: force the log after remapping a synchronous-writes file
+    - Xen/gntdev: don't ignore kernel unmapping error
+    - xen/gntdev: Prevent leaking grants
+    - mm,hugetlb: take hugetlb_lock before decrementing h->resv_huge_pages
+    - net: ieee802154: fix error return code in dgram_bind()
+    - media: v4l2: Fix v4l2_i2c_subdev_set_name function documentation
+    - drm/msm: Fix return type of mdp4_lvds_connector_mode_valid
+    - arc: iounmap() arg is volatile
+    - ALSA: ac97: fix possible memory leak in snd_ac97_dev_register()
+    - tipc: fix a null-ptr-deref in tipc_topsrv_accept
+    - net: netsec: fix error handling in netsec_register_mdio()
+    - x86/unwind/orc: Fix unreliable stack dump with gcov
+    - amd-xgbe: fix the SFP compliance codes check for DAC cables
+    - amd-xgbe: add the bit rate quirk for Molex cables
+    - kcm: annotate data-races around kcm->rx_psock
+    - kcm: annotate data-races around kcm->rx_wait
+    - net: fix UAF issue in nfqnl_nf_hook_drop() when ops_init() failed
+    - net: lantiq_etop: don't free skb when returning NETDEV_TX_BUSY
+    - tcp: fix indefinite deferral of RTO with SACK reneging
+    - can: mscan: mpc5xxx: mpc5xxx_can_probe(): add missing put_clock() in error
+      path
+    - PM: hibernate: Allow hybrid sleep to work with s2idle
+    - media: vivid: s_fbuf: add more sanity checks
+    - media: vivid: dev->bitmap_cap wasn't freed in all cases
+    - media: v4l2-dv-timings: add sanity checks for blanking values
+    - media: videodev2.h: V4L2_DV_BT_BLANKING_HEIGHT should check 'interlaced'
+    - i40e: Fix ethtool rx-flow-hash setting for X722
+    - i40e: Fix VF hang when reset is triggered on another VF
+    - i40e: Fix flow-type by setting GL_HASH_INSET registers
+    - net: ksz884x: fix missing pci_disable_device() on error in pcidev_init()
+    - PM: domains: Fix handling of unavailable/disabled idle states
+    - ALSA: aoa: i2sbus: fix possible memory leak in i2sbus_add_dev()
+    - ALSA: aoa: Fix I2S device accounting
+    - openvswitch: switch from WARN to pr_warn
+    - net: ehea: fix possible memory leak in ehea_register_port()
+    - nh: fix scope used to find saddr when adding non gw nh
+    - net/mlx5e: Do not increment ESN when updating IPsec ESN state
+    - net/mlx5: Fix possible use-after-free in async command interface
+    - net: enetc: survive memory pressure without crashing
+    - can: rcar_canfd: rcar_canfd_handle_global_receive(): fix IRQ storm on global
+      FIFO receive
+    - Linux 5.4.223
+  * Focal update: v5.4.222 upstream stable release (LP: #1997994)
+    - once: fix section mismatch on clang builds
+    - Linux 5.4.222
+  * Focal update: v5.4.221 upstream stable release (LP: #1997993)
+    - xfs: open code insert range extent split helper
+    - xfs: rework insert range into an atomic operation
+    - xfs: rework collapse range into an atomic operation
+    - xfs: add a function to deal with corrupt buffers post-verifiers
+    - xfs: xfs_buf_corruption_error should take __this_address
+    - xfs: fix buffer corruption reporting when xfs_dir3_free_header_check fails
+    - xfs: check owner of dir3 data blocks
+    - xfs: check owner of dir3 blocks
+    - xfs: Use scnprintf() for avoiding potential buffer overflow
+    - xfs: remove the xfs_disk_dquot_t and xfs_dquot_t
+    - xfs: remove the xfs_dq_logitem_t typedef
+    - xfs: remove the xfs_qoff_logitem_t typedef
+    - xfs: Replace function declaration by actual definition
+    - xfs: factor out quotaoff intent AIL removal and memory free
+    - xfs: fix unmount hang and memory leak on shutdown during quotaoff
+    - xfs: preserve default grace interval during quotacheck
+    - xfs: Lower CIL flush limit for large logs
+    - xfs: Throttle commits on delayed background CIL push
+    - xfs: factor common AIL item deletion code
+    - xfs: tail updates only need to occur when LSN changes
+    - xfs: don't write a corrupt unmount record to force summary counter recalc
+    - xfs: trylock underlying buffer on dquot flush
+    - xfs: factor out a new xfs_log_force_inode helper
+    - xfs: reflink should force the log out if mounted with wsync
+    - xfs: move inode flush to the sync workqueue
+    - xfs: fix use-after-free on CIL context on shutdown
+    - ocfs2: clear dinode links count in case of error
+    - ocfs2: fix BUG when iput after ocfs2_mknod fails
+    - x86/microcode/AMD: Apply the patch early on every logical thread
+    - hwmon/coretemp: Handle large core ID value
+    - ata: ahci-imx: Fix MODULE_ALIAS
+    - ata: ahci: Match EM_MAX_SLOTS with SATA_PMP_MAX_PORTS
+    - KVM: arm64: vgic: Fix exit condition in scan_its_table()
+    - media: venus: dec: Handle the case where find_format fails
+    - [Config] updateconfigs for ARM64_ERRATUM_1742098
+    - arm64: errata: Remove AES hwcap for COMPAT tasks
+    - r8152: add PID for the Lenovo OneLink+ Dock
+    - btrfs: fix processing of delayed data refs during backref walking
+    - btrfs: fix processing of delayed tree block refs during backref walking
+    - ACPI: extlog: Handle multiple records
+    - tipc: Fix recognition of trial period
+    - tipc: fix an information leak in tipc_topsrv_kern_subscr
+    - HID: magicmouse: Do not set BTN_MOUSE on double report
+    - net/atm: fix proc_mpc_write incorrect return value
+    - net: phy: dp83867: Extend RX strap quirk for SGMII mode
+    - net: sched: cake: fix null pointer access issue when cake_init() fails
+    - net: hns: fix possible memory leak in hnae_ae_register()
+    - iommu/vt-d: Clean up si_domain in the init_dmars() error path
+    - arm64: topology: move store_cpu_topology() to shared code
+    - riscv: topology: fix default topology reporting
+    - ACPI: video: Force backlight native for more TongFang devices
+    - Makefile.debug: re-enable debug info for .S files
+    - hv_netvsc: Fix race between VF offering and VF association message from host
+    - mm: /proc/pid/smaps_rollup: fix no vma's null-deref
+    - Linux 5.4.221
+  * Focal update: v5.4.220 upstream stable release (LP: #1996812)
+    - ALSA: oss: Fix potential deadlock at unregistration
+    - ALSA: rawmidi: Drop register_mutex in snd_rawmidi_free()
+    - ALSA: usb-audio: Fix potential memory leaks
+    - ALSA: usb-audio: Fix NULL dererence at error path
+    - ALSA: hda/realtek: remove ALC289_FIXUP_DUAL_SPK for Dell 5530
+    - ALSA: hda/realtek: Correct pin configs for ASUS G533Z
+    - ALSA: hda/realtek: Add quirk for ASUS GV601R laptop
+    - ALSA: hda/realtek: Add Intel Reference SSID to support headset keys
+    - mtd: rawnand: atmel: Unmap streaming DMA mappings
+    - cifs: destage dirty pages before re-reading them for cache=none
+    - cifs: Fix the error length of VALIDATE_NEGOTIATE_INFO message
+    - iio: dac: ad5593r: Fix i2c read protocol requirements
+    - iio: pressure: dps310: Refactor startup procedure
+    - iio: pressure: dps310: Reset chip after timeout
+    - usb: add quirks for Lenovo OneLink+ Dock
+    - can: kvaser_usb: Fix use of uninitialized completion
+    - can: kvaser_usb_leaf: Fix overread with an invalid command
+    - can: kvaser_usb_leaf: Fix TX queue out of sync after restart
+    - can: kvaser_usb_leaf: Fix CAN state after restart
+    - mmc: sdhci-sprd: Fix minimum clock limit
+    - fs: dlm: fix race between test_bit() and queue_work()
+    - fs: dlm: handle -EBUSY first in lock arg validation
+    - HID: multitouch: Add memory barriers
+    - quota: Check next/prev free block number after reading from quota file
+    - ASoC: wcd9335: fix order of Slimbus unprepare/disable
+    - regulator: qcom_rpm: Fix circular deferral regression
+    - RISC-V: Make port I/O string accessors actually work
+    - parisc: fbdev/stifb: Align graphics memory size to 4MB
+    - riscv: Allow PROT_WRITE-only mmap()
+    - riscv: Pass -mno-relax only on lld < 15.0.0
+    - UM: cpuinfo: Fix a warning for CONFIG_CPUMASK_OFFSTACK
+    - PCI: Sanitise firmware BAR assignments behind a PCI-PCI bridge
+    - powerpc/boot: Explicitly disable usage of SPE instructions
+    - fbdev: smscufx: Fix use-after-free in ufx_ops_open()
+    - btrfs: fix race between quota enable and quota rescan ioctl
+    - f2fs: increase the limit for reserve_root
+    - f2fs: fix to do sanity check on destination blkaddr during recovery
+    - f2fs: fix to do sanity check on summary info
+    - nilfs2: fix use-after-free bug of struct nilfs_root
+    - jbd2: wake up journal waiters in FIFO order, not LIFO
+    - ext4: avoid crash when inline data creation follows DIO write
+    - ext4: fix null-ptr-deref in ext4_write_info
+    - ext4: make ext4_lazyinit_thread freezable
+    - ext4: place buffer head allocation before handle start
+    - livepatch: fix race between fork and KLP transition
+    - ftrace: Properly unset FTRACE_HASH_FL_MOD
+    - ring-buffer: Allow splice to read previous partially read pages
+    - ring-buffer: Have the shortest_full queue be the shortest not longest
+    - ring-buffer: Check pending waiters when doing wake ups as well
+    - ring-buffer: Fix race between reset page and reading page
+    - media: cedrus: Set the platform driver data earlier
+    - KVM: x86/emulator: Fix handing of POP SS to correctly set interruptibility
+    - KVM: nVMX: Unconditionally purge queued/injected events on nested "exit"
+    - KVM: VMX: Drop bits 31:16 when shoving exception error code into VMCS
+    - gcov: support GCC 12.1 and newer compilers
+    - drm/nouveau: fix a use-after-free in nouveau_gem_prime_import_sg_table()
+    - selinux: use "grep -E" instead of "egrep"
+    - tracing: Disable interrupt or preemption before acquiring arch_spinlock_t
+    - userfaultfd: open userfaultfds with O_RDONLY
+    - sh: machvec: Use char[] for section boundaries
+    - ARM: 9247/1: mm: set readonly for MT_MEMORY_RO with ARM_LPAE
+    - nfsd: Fix a memory leak in an error handling path
+    - wifi: ath10k: add peer map clean up for peer delete in ath10k_sta_state()
+    - wifi: mac80211: allow bw change during channel switch in mesh
+    - bpftool: Fix a wrong type cast in btf_dumper_int
+    - x86/resctrl: Fix to restore to original value when re-enabling hardware
+      prefetch register
+    - wifi: rtl8xxxu: tighten bounds checking in rtl8xxxu_read_efuse()
+    - spi: qup: add missing clk_disable_unprepare on error in spi_qup_resume()
+    - spi: qup: add missing clk_disable_unprepare on error in
+      spi_qup_pm_resume_runtime()
+    - wifi: rtl8xxxu: Fix skb misuse in TX queue selection
+    - bpf: btf: fix truncated last_member_type_id in btf_struct_resolve
+    - wifi: rtl8xxxu: gen2: Fix mistake in path B IQ calibration
+    - net: fs_enet: Fix wrong check in do_pd_setup
+    - bpf: Ensure correct locking around vulnerable function find_vpid()
+    - x86/microcode/AMD: Track patch allocation size explicitly
+    - spi/omap100k:Fix PM disable depth imbalance in omap1_spi100k_probe
+    - netfilter: nft_fib: Fix for rpath check with VRF devices
+    - spi: s3c64xx: Fix large transfers with DMA
+    - vhost/vsock: Use kvmalloc/kvfree for larger packets.
+    - sctp: handle the error returned from sctp_auth_asoc_init_active_key
+    - tcp: fix tcp_cwnd_validate() to not forget is_cwnd_limited
+    - net: rds: don't hold sock lock when cancelling work from
+      rds_tcp_reset_callbacks()
+    - bnx2x: fix potential memory leak in bnx2x_tpa_stop()
+    - net/ieee802154: reject zero-sized raw_sendmsg()
+    - once: add DO_ONCE_SLOW() for sleepable contexts
+    - net: mvpp2: fix mvpp2 debugfs leak
+    - drm: bridge: adv7511: fix CEC power down control register offset
+    - drm/mipi-dsi: Detach devices when removing the host
+    - platform/chrome: fix double-free in chromeos_laptop_prepare()
+    - platform/chrome: fix memory corruption in ioctl
+    - platform/x86: msi-laptop: Fix old-ec check for backlight registering
+    - platform/x86: msi-laptop: Fix resource cleanup
+    - drm: fix drm_mipi_dbi build errors
+    - drm/bridge: megachips: Fix a null pointer dereference bug
+    - ASoC: rsnd: Add check for rsnd_mod_power_on
+    - ALSA: hda: beep: Simplify keep-power-at-enable behavior
+    - drm/omap: dss: Fix refcount leak bugs
+    - mmc: au1xmmc: Fix an error handling path in au1xmmc_probe()
+    - ASoC: eureka-tlv320: Hold reference returned from of_find_xxx API
+    - drm/msm/dpu: index dpu_kms->hw_vbif using vbif_idx
+    - ALSA: dmaengine: increment buffer pointer atomically
+    - mmc: wmt-sdmmc: Fix an error handling path in wmt_mci_probe()
+    - ASoC: wm8997: Fix PM disable depth imbalance in wm8997_probe
+    - ASoC: wm5110: Fix PM disable depth imbalance in wm5110_probe
+    - ASoC: wm5102: Fix PM disable depth imbalance in wm5102_probe
+    - ALSA: hda/hdmi: Don't skip notification handling during PM operation
+    - memory: pl353-smc: Fix refcount leak bug in pl353_smc_probe()
+    - memory: of: Fix refcount leak bug in of_get_ddr_timings()
+    - soc: qcom: smsm: Fix refcount leak bugs in qcom_smsm_probe()
+    - soc: qcom: smem_state: Add refcounting for the 'state->of_node'
+    - ARM: dts: turris-omnia: Fix mpp26 pin name and comment
+    - ARM: dts: kirkwood: lsxl: fix serial line
+    - ARM: dts: kirkwood: lsxl: remove first ethernet port
+    - ARM: dts: exynos: correct s5k6a3 reset polarity on Midas family
+    - ARM: Drop CMDLINE_* dependency on ATAGS
+    - ARM: dts: exynos: fix polarity of VBUS GPIO of Origen
+    - iio: adc: at91-sama5d2_adc: fix AT91_SAMA5D2_MR_TRACKTIM_MAX
+    - iio: adc: at91-sama5d2_adc: check return status for pressure and touch
+    - iio: adc: at91-sama5d2_adc: lock around oversampling and sample freq
+    - iio: inkern: only release the device node when done with it
+    - iio: ABI: Fix wrong format of differential capacitance channel ABI.
+    - clk: meson: Hold reference returned by of_get_parent()
+    - clk: oxnas: Hold reference returned by of_get_parent()
+    - clk: berlin: Add of_node_put() for of_get_parent()
+    - clk: tegra: Fix refcount leak in tegra210_clock_init
+    - clk: tegra: Fix refcount leak in tegra114_clock_init
+    - clk: tegra20: Fix refcount leak in tegra20_clock_init
+    - HSI: omap_ssi: Fix refcount leak in ssi_probe
+    - HSI: omap_ssi_port: Fix dma_map_sg error check
+    - media: exynos4-is: fimc-is: Add of_node_put() when breaking out of loop
+    - tty: xilinx_uartps: Fix the ignore_status
+    - media: xilinx: vipp: Fix refcount leak in xvip_graph_dma_init
+    - RDMA/rxe: Fix "kernel NULL pointer dereference" error
+    - RDMA/rxe: Fix the error caused by qp->sk
+    - misc: ocxl: fix possible refcount leak in afu_ioctl()
+    - dyndbg: fix module.dyndbg handling
+    - dyndbg: let query-modname override actual module name
+    - mtd: devices: docg3: check the return value of devm_ioremap() in the probe
+    - RDMA/siw: Always consume all skbuf data in sk_data_ready() upcall.
+    - ata: fix ata_id_sense_reporting_enabled() and ata_id_has_sense_reporting()
+    - ata: fix ata_id_has_devslp()
+    - ata: fix ata_id_has_ncq_autosense()
+    - ata: fix ata_id_has_dipm()
+    - mtd: rawnand: meson: fix bit map use in meson_nfc_ecc_correct()
+    - md/raid5: Ensure stripe_fill happens on non-read IO with journal
+    - xhci: Don't show warning for reinit on known broken suspend
+    - usb: gadget: function: fix dangling pnp_string in f_printer.c
+    - drivers: serial: jsm: fix some leaks in probe
+    - tty: serial: fsl_lpuart: disable dma rx/tx use flags in lpuart_dma_shutdown
+    - phy: qualcomm: call clk_disable_unprepare in the error handling
+    - staging: vt6655: fix some erroneous memory clean-up loops
+    - firmware: google: Test spinlock on panic path to avoid lockups
+    - serial: 8250: Fix restoring termios speed after suspend
+    - scsi: libsas: Fix use-after-free bug in smp_execute_task_sg()
+    - fsi: core: Check error number after calling ida_simple_get
+    - mfd: intel_soc_pmic: Fix an error handling path in
+      intel_soc_pmic_i2c_probe()
+    - mfd: fsl-imx25: Fix an error handling path in mx25_tsadc_setup_irq()
+    - mfd: lp8788: Fix an error handling path in lp8788_probe()
+    - mfd: lp8788: Fix an error handling path in lp8788_irq_init() and
+      lp8788_irq_init()
+    - mfd: fsl-imx25: Fix check for platform_get_irq() errors
+    - mfd: sm501: Add check for platform_driver_register()
+    - clk: mediatek: mt8183: mfgcfg: Propagate rate changes to parent
+    - dmaengine: ioat: stop mod_timer from resurrecting deleted timer in
+      __cleanup()
+    - spmi: pmic-arb: correct duplicate APID to PPID mapping logic
+    - clk: bcm2835: fix bcm2835_clock_rate_from_divisor declaration
+    - clk: ti: dra7-atl: Fix reference leak in of_dra7_atl_clk_probe
+    - clk: ast2600: BCLK comes from EPLL
+    - mailbox: bcm-ferxrm-mailbox: Fix error check for dma_map_sg
+    - powerpc/math_emu/efp: Include module.h
+    - powerpc/sysdev/fsl_msi: Add missing of_node_put()
+    - powerpc/pci_dn: Add missing of_node_put()
+    - powerpc/powernv: add missing of_node_put() in opal_export_attrs()
+    - x86/hyperv: Fix 'struct hv_enlightened_vmcs' definition
+    - powerpc/64s: Fix GENERIC_CPU build flags for PPC970 / G5
+    - powerpc: Fix SPE Power ISA properties for e500v1 platforms
+    - cgroup/cpuset: Enable update_tasks_cpumask() on top_cpuset
+    - iommu/omap: Fix buffer overflow in debugfs
+    - crypto: akcipher - default implementation for setting a private key
+    - crypto: ccp - Release dma channels before dmaengine unrgister
+    - iommu/iova: Fix module config properly
+    - kbuild: remove the target in signal traps when interrupted
+    - crypto: cavium - prevent integer overflow loading firmware
+    - f2fs: fix race condition on setting FI_NO_EXTENT flag
+    - ACPI: video: Add Toshiba Satellite/Portege Z830 quirk
+    - MIPS: BCM47XX: Cast memcmp() of function to (void *)
+    - powercap: intel_rapl: fix UBSAN shift-out-of-bounds issue
+    - thermal: intel_powerclamp: Use get_cpu() instead of smp_processor_id() to
+      avoid crash
+    - NFSD: Return nfserr_serverfault if splice_ok but buf->pages have data
+    - wifi: brcmfmac: fix invalid address access when enabling SCAN log level
+    - bpftool: Clear errno after libcap's checks
+    - openvswitch: Fix double reporting of drops in dropwatch
+    - openvswitch: Fix overreporting of drops in dropwatch
+    - tcp: annotate data-race around tcp_md5sig_pool_populated
+    - wifi: ath9k: avoid uninit memory read in ath9k_htc_rx_msg()
+    - xfrm: Update ipcomp_scratches with NULL when freed
+    - wifi: brcmfmac: fix use-after-free bug in brcmf_netdev_start_xmit()
+    - Bluetooth: L2CAP: initialize delayed works at l2cap_chan_create()
+    - Bluetooth: hci_sysfs: Fix attempting to call device_add multiple times
+    - can: bcm: check the result of can_send() in bcm_can_tx()
+    - wifi: rt2x00: don't run Rt5592 IQ calibration on MT7620
+    - wifi: rt2x00: set correct TX_SW_CFG1 MAC register for MT7620
+    - wifi: rt2x00: set VGC gain for both chains of MT7620
+    - wifi: rt2x00: set SoC wmac clock register
+    - wifi: rt2x00: correctly set BBP register 86 for MT7620
+    - net: If sock is dead don't access sock's sk_wq in sk_stream_wait_memory
+    - Bluetooth: L2CAP: Fix user-after-free
+    - drm/nouveau/nouveau_bo: fix potential memory leak in nouveau_bo_alloc()
+    - drm: Use size_t type for len variable in drm_copy_field()
+    - drm: Prevent drm_copy_field() to attempt copying a NULL pointer
+    - drm/amd/display: fix overflow on MIN_I64 definition
+    - drm/vc4: vec: Fix timings for VEC modes
+    - drm: panel-orientation-quirks: Add quirk for Anbernic Win600
+    - platform/x86: msi-laptop: Change DMI match / alias strings to fix module
+      autoloading
+    - drm/amdgpu: fix initial connector audio value
+    - mmc: sdhci-msm: add compatible string check for sdm670
+    - ARM: dts: imx7d-sdb: config the max pressure for tsc2046
+    - ARM: dts: imx6q: add missing properties for sram
+    - ARM: dts: imx6dl: add missing properties for sram
+    - ARM: dts: imx6qp: add missing properties for sram
+    - ARM: dts: imx6sl: add missing properties for sram
+    - ARM: dts: imx6sll: add missing properties for sram
+    - ARM: dts: imx6sx: add missing properties for sram
+    - btrfs: scrub: try to fix super block errors
+    - clk: zynqmp: Fix stack-out-of-bounds in strncpy`
+    - media: cx88: Fix a null-ptr-deref bug in buffer_prepare()
+    - clk: zynqmp: pll: rectify rate rounding in zynqmp_pll_round_rate
+    - scsi: 3w-9xxx: Avoid disabling device if failing to enable it
+    - nbd: Fix hung when signal interrupts nbd_start_device_ioctl()
+    - power: supply: adp5061: fix out-of-bounds read in adp5061_get_chg_type()
+    - staging: vt6655: fix potential memory leak
+    - ata: libahci_platform: Sanity check the DT child nodes number
+    - bcache: fix set_at_max_writeback_rate() for multiple attached devices
+    - HID: roccat: Fix use-after-free in roccat_read()
+    - md/raid5: Wait for MD_SB_CHANGE_PENDING in raid5d
+    - usb: host: xhci: Fix potential memory leak in xhci_alloc_stream_info()
+    - usb: musb: Fix musb_gadget.c rxstate overflow bug
+    - Revert "usb: storage: Add quirk for Samsung Fit flash"
+    - staging: rtl8723bs: fix a potential memory leak in rtw_init_cmd_priv()
+    - nvme: copy firmware_rev on each init
+    - nvmet-tcp: add bounds check on Transfer Tag
+    - usb: idmouse: fix an uninit-value in idmouse_open
+    - clk: bcm2835: Make peripheral PLLC critical
+    - perf intel-pt: Fix segfault in intel_pt_print_info() with uClibc
+    - net: ieee802154: return -EINVAL for unknown addr type
+    - Revert "net/ieee802154: reject zero-sized raw_sendmsg()"
+    - net/ieee802154: don't warn zero-sized raw_sendmsg()
+    - ext4: continue to expand file system when the target size doesn't reach
+    - efi: libstub: drop pointless get_memory_map() call
+    - inet: fully convert sk->sk_rx_dst to RCU rules
+    - thermal: intel_powerclamp: Use first online CPU as control_cpu
+    - Linux 5.4.220
+  * Focal update: v5.4.219 upstream stable release (LP: #1996804)
+    - Linux 5.4.219
+
+  [ Ubuntu: 5.4.0-137.154 ]
+
+  * focal/linux: 5.4.0-137.154 -proposed tracker (LP: #2001969)
+  * CVE-2022-3643
+    - xen/netback: Ensure protocol headers don't fall in the non-linear area
+  * CVE-2022-43945
+    - NFSD: Cap rsize_bop result based on send buffer size
+  * CVE-2022-45934
+    - Bluetooth: L2CAP: Fix u8 overflow
+  * CVE-2022-42896
+    - Bluetooth: L2CAP: Fix accepting connection request for invalid SPSM
+    - Bluetooth: L2CAP: Fix l2cap_global_chan_by_psm
+
+ -- Masahiro Yamada <masahiro.yamada@canonical.com>  Mon, 23 Jan 2023 15:25:45 +0900
+
+linux-xilinx-zynqmp (5.4.0-1020.24) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1020.24 -proposed tracker (LP: #1999000)
+
+  [ Ubuntu: 5.4.0-136.153 ]
+
+  * focal/linux: 5.4.0-136.153 -proposed tracker (LP: #1997835)
+  * Expose built-in trusted and revoked certificates (LP: #1996892)
+    - [Packaging] Expose built-in trusted and revoked certificates
+  * [UBUNTU 20.04] KVM: PV: ext call delivered twice when receiver in PSW wait
+    (LP: #1995941)
+    - KVM: s390: pv: don't present the ecall interrupt twice
+  * [UBUNTU 20.04] boot: Add s390x secure boot trailer (LP: #1996071)
+    - s390/boot: add secure boot trailer
+  * Fix rfkill causing soft blocked wifi (LP: #1996198)
+    - platform/x86: hp_wmi: Fix rfkill causing soft blocked wifi
+  * md: Replace snprintf with scnprintf (LP: #1993315)
+    - md: Replace snprintf with scnprintf
+  * input/keyboard: the keyboard on some Asus laptops can't work (LP: #1992266)
+    - ACPI: resource: Skip IRQ override on Asus Vivobook K3402ZA/K3502ZA
+    - ACPI: resource: Add ASUS model S5402ZA to quirks
+  * Focal update: v5.4.218 upstream stable release (LP: #1995530)
+    - mm: pagewalk: Fix race between unmap and page walker
+    - perf tools: Fixup get_current_dir_name() compilation
+    - firmware: arm_scmi: Add SCMI PM driver remove routine
+    - dmaengine: xilinx_dma: cleanup for fetching xlnx,num-fstores property
+    - dmaengine: xilinx_dma: Report error in case of dma_set_mask_and_coherent API
+      failure
+    - ARM: dts: fix Moxa SDIO 'compatible', remove 'sdhci' misnomer
+    - scsi: qedf: Fix a UAF bug in __qedf_probe()
+    - net/ieee802154: fix uninit value bug in dgram_sendmsg
+    - um: Cleanup syscall_handler_t cast in syscalls_32.h
+    - um: Cleanup compiler warning in arch/x86/um/tls_32.c
+    - arch: um: Mark the stack non-executable to fix a binutils warning
+    - usb: mon: make mmapped memory read only
+    - USB: serial: ftdi_sio: fix 300 bps rate for SIO
+    - mmc: core: Replace with already defined values for readability
+    - mmc: core: Terminate infinite loop in SD-UHS voltage switch
+    - rpmsg: qcom: glink: replace strncpy() with strscpy_pad()
+    - nilfs2: fix leak of nilfs_root in case of writer thread creation failure
+    - nilfs2: replace WARN_ONs by nilfs_error for checkpoint acquisition failure
+    - ceph: don't truncate file in atomic_open
+    - random: clamp credited irq bits to maximum mixed
+    - ALSA: hda: Fix position reporting on Poulsbo
+    - efi: Correct Macmini DMI match in uefi cert quirk
+    - USB: serial: qcserial: add new usb-id for Dell branded EM7455
+    - random: restore O_NONBLOCK support
+    - random: avoid reading two cache lines on irq randomness
+    - random: use expired timer rather than wq for mixing fast pool
+    - Input: xpad - add supported devices as contributed on github
+    - Input: xpad - fix wireless 360 controller breaking after suspend
+    - Linux 5.4.218
+  * Focal update: v5.4.217 upstream stable release (LP: #1995528)
+    - xfs: fix misuse of the XFS_ATTR_INCOMPLETE flag
+    - xfs: introduce XFS_MAX_FILEOFF
+    - xfs: truncate should remove all blocks, not just to the end of the page
+      cache
+    - xfs: fix s_maxbytes computation on 32-bit kernels
+    - xfs: fix IOCB_NOWAIT handling in xfs_file_dio_aio_read
+    - xfs: refactor remote attr value buffer invalidation
+    - xfs: fix memory corruption during remote attr value buffer invalidation
+    - xfs: move incore structures out of xfs_da_format.h
+    - xfs: streamline xfs_attr3_leaf_inactive
+    - xfs: fix uninitialized variable in xfs_attr3_leaf_inactive
+    - xfs: remove unused variable 'done'
+    - Makefile.extrawarn: Move -Wcast-function-type-strict to W=1
+    - docs: update mediator information in CoC docs
+    - Linux 5.4.217
+  * Focal update: v5.4.216 upstream stable release (LP: #1995526)
+    - uas: add no-uas quirk for Hiksemi usb_disk
+    - usb-storage: Add Hiksemi USB3-FW to IGNORE_UAS
+    - uas: ignore UAS for Thinkplus chips
+    - net: usb: qmi_wwan: Add new usb-id for Dell branded EM7455
+    - clk: ingenic-tcu: Properly enable registers before accessing timers
+    - ARM: dts: integrator: Tag PCI host with device_type
+    - ntfs: fix BUG_ON in ntfs_lookup_inode_by_name()
+    - libata: add ATA_HORKAGE_NOLPM for Pioneer BDR-207M and BDR-205
+    - mmc: moxart: fix 4-bit bus width and remove 8-bit bus width
+    - mm/page_alloc: fix race condition between build_all_zonelists and page
+      allocation
+    - mm: prevent page_frag_alloc() from corrupting the memory
+    - mm/migrate_device.c: flush TLB while holding PTL
+    - mm: fix madivse_pageout mishandling on non-LRU page
+    - media: dvb_vb2: fix possible out of bound access
+    - ARM: dts: Move am33xx and am43xx mmc nodes to sdhci-omap driver
+    - ARM: dts: am33xx: Fix MMCHS0 dma properties
+    - soc: sunxi: sram: Actually claim SRAM regions
+    - soc: sunxi: sram: Prevent the driver from being unbound
+    - soc: sunxi_sram: Make use of the helper function
+      devm_platform_ioremap_resource()
+    - soc: sunxi: sram: Fix probe function ordering issues
+    - soc: sunxi: sram: Fix debugfs info for A64 SRAM C
+    - Revert "drm: bridge: analogix/dp: add panel prepare/unprepare in
+      suspend/resume time"
+    - Input: melfas_mip4 - fix return value check in mip4_probe()
+    - usbnet: Fix memory leak in usbnet_disconnect()
+    - nvme: add new line after variable declatation
+    - nvme: Fix IOC_PR_CLEAR and IOC_PR_RELEASE ioctls for nvme devices
+    - selftests: Fix the if conditions of in test_extra_filter()
+    - clk: imx: imx6sx: remove the SET_RATE_PARENT flag for QSPI clocks
+    - clk: iproc: Do not rely on node name for correct PLL setup
+    - Linux 5.4.216
+  * Focal update: v5.4.215 upstream stable release (LP: #1993203)
+    - of: fdt: fix off-by-one error in unflatten_dt_nodes()
+    - NFSv4: Turn off open-by-filehandle and NFS re-export for NFSv4.0
+    - gpio: mpc8xxx: Fix support for IRQ_TYPE_LEVEL_LOW flow_type in mpc85xx
+    - drm/meson: Correct OSD1 global alpha value
+    - drm/meson: Fix OSD1 RGB to YCbCr coefficient
+    - parisc: ccio-dma: Add missing iounmap in error path in ccio_probe()
+    - ALSA: pcm: oss: Fix race at SNDCTL_DSP_SYNC
+    - task_stack, x86/cea: Force-inline stack helpers
+    - tracing: hold caller_addr to hardirq_{enable,disable}_ip
+    - cifs: revalidate mapping when doing direct writes
+    - cifs: don't send down the destination address to sendmsg for a SOCK_STREAM
+    - MAINTAINERS: add Chandan as xfs maintainer for 5.4.y
+    - iomap: iomap that extends beyond EOF should be marked dirty
+    - ASoC: nau8824: Fix semaphore unbalance at error paths
+    - regulator: pfuze100: Fix the global-out-of-bounds access in
+      pfuze100_regulator_probe()
+    - rxrpc: Fix local destruction being repeated
+    - rxrpc: Fix calc of resend age
+    - ALSA: hda/sigmatel: Keep power up while beep is enabled
+    - ALSA: hda/tegra: Align BDL entry to 4KB boundary
+    - net: usb: qmi_wwan: add Quectel RM520N
+    - afs: Return -EAGAIN, not -EREMOTEIO, when a file already locked
+    - MIPS: OCTEON: irq: Fix octeon_irq_force_ciu_mapping()
+    - mksysmap: Fix the mismatch of 'L0' symbols in System.map
+    - video: fbdev: pxa3xx-gcu: Fix integer overflow in pxa3xx_gcu_write
+    - cgroup: Add missing cpus_read_lock() to cgroup_attach_task_all()
+    - ALSA: hda/sigmatel: Fix unused variable warning for beep power change
+    - usb: dwc3: gadget: Avoid starting DWC3 gadget during UDC unbind
+    - usb: dwc3: Issue core soft reset before enabling run/stop
+    - usb: dwc3: gadget: Prevent repeat pullup()
+    - usb: dwc3: gadget: Refactor pullup()
+    - usb: dwc3: gadget: Don't modify GEVNTCOUNT in pullup()
+    - usb: dwc3: gadget: Avoid duplicate requests to enable Run/Stop
+    - usb: xhci-mtk: get the microframe boundary for ESIT
+    - usb: xhci-mtk: add only one extra CS for FS/LS INTR
+    - usb: xhci-mtk: use @sch_tt to check whether need do TT schedule
+    - usb: xhci-mtk: add a function to (un)load bandwidth info
+    - usb: xhci-mtk: add some schedule error number
+    - usb: xhci-mtk: allow multiple Start-Split in a microframe
+    - usb: xhci-mtk: relax TT periodic bandwidth allocation
+    - wifi: mac80211: Fix UAF in ieee80211_scan_rx()
+    - tty/serial: atmel: RS485 & ISO7816: wait for TXRDY before sending data
+    - serial: atmel: remove redundant assignment in rs485_config
+    - tty: serial: atmel: Preserve previous USART mode if RS485 disabled
+    - usb: add quirks for Lenovo OneLink+ Dock
+    - usb: gadget: udc-xilinx: replace memcpy with memcpy_toio
+    - usb: cdns3: fix issue with rearming ISO OUT endpoint
+    - Revert "usb: add quirks for Lenovo OneLink+ Dock"
+    - Revert "usb: gadget: udc-xilinx: replace memcpy with memcpy_toio"
+    - USB: core: Fix RST error in hub.c
+    - USB: serial: option: add Quectel BG95 0x0203 composition
+    - USB: serial: option: add Quectel RM520N
+    - ALSA: hda/tegra: set depop delay for tegra
+    - ALSA: hda: add Intel 5 Series / 3400 PCI DID
+    - ALSA: hda/realtek: Add quirk for Huawei WRT-WX9
+    - ALSA: hda/realtek: Re-arrange quirk table entries
+    - ALSA: hda/realtek: Add pincfg for ASUS G513 HP jack
+    - ALSA: hda/realtek: Add pincfg for ASUS G533Z HP jack
+    - ALSA: hda/realtek: Add quirk for ASUS GA503R laptop
+    - ALSA: hda/realtek: Enable 4-speaker output Dell Precision 5530 laptop
+    - efi: libstub: check Shim mode using MokSBStateRT
+    - mm/slub: fix to return errno if kmalloc() fails
+    - arm64: dts: rockchip: Pull up wlan wake# on Gru-Bob
+    - arm64: dts: rockchip: Set RK3399-Gru PCLK_EDP to 24 MHz
+    - arm64: dts: rockchip: Remove 'enable-active-low' from rk3399-puma
+    - netfilter: nf_conntrack_sip: fix ct_sip_walk_headers
+    - netfilter: nf_conntrack_irc: Tighten matching on DCC message
+    - netfilter: nfnetlink_osf: fix possible bogus match in nf_osf_find()
+    - iavf: Fix cached head and tail value for iavf_get_tx_pending
+    - ipvlan: Fix out-of-bound bugs caused by unset skb->mac_header
+    - net: team: Unsync device addresses on ndo_stop
+    - MIPS: lantiq: export clk_get_io() for lantiq_wdt.ko
+    - MIPS: Loongson32: Fix PHY-mode being left unspecified
+    - iavf: Fix bad page state
+    - i40e: Fix set max_tx_rate when it is lower than 1 Mbps
+    - of: mdio: Add of_node_put() when breaking out of for_each_xx
+    - net/sched: taprio: avoid disabling offload when it was never enabled
+    - net/sched: taprio: make qdisc_leaf() see the per-netdev-queue pfifo child
+      qdiscs
+    - netfilter: ebtables: fix memory leak when blob is malformed
+    - can: gs_usb: gs_can_open(): fix race dev->can.state condition
+    - perf jit: Include program header in ELF files
+    - perf kcore_copy: Do not check /proc/modules is unchanged
+    - net: sunhme: Fix packet reception for len < RX_COPY_THRESHOLD
+    - net: sched: fix possible refcount leak in tc_new_tfilter()
+    - serial: Create uart_xmit_advance()
+    - serial: tegra: Use uart_xmit_advance(), fixes icount.tx accounting
+    - serial: tegra-tcu: Use uart_xmit_advance(), fixes icount.tx accounting
+    - s390/dasd: fix Oops in dasd_alias_get_start_dev due to missing pavgroup
+    - usb: xhci-mtk: fix issue of out-of-bounds array access
+    - cifs: always initialize struct msghdr smb_msg completely
+    - Drivers: hv: Never allocate anything besides framebuffer from framebuffer
+      memory region
+    - drm/amd/display: Limit user regamma to a valid value
+    - drm/rockchip: Fix return type of cdn_dp_connector_mode_valid
+    - workqueue: don't skip lockdep work dependency in cancel_work_sync()
+    - ext4: fix bug in extents parsing when eh_entries == 0 and eh_depth > 0
+    - xfs: replace -EIO with -EFSCORRUPTED for corrupt metadata
+    - xfs: slightly tweak an assert in xfs_fs_map_blocks
+    - xfs: add missing assert in xfs_fsmap_owner_from_rmap
+    - xfs: range check ri_cnt when recovering log items
+    - xfs: attach dquots and reserve quota blocks during unwritten conversion
+    - xfs: convert EIO to EFSCORRUPTED when log contents are invalid
+    - xfs: constify the buffer pointer arguments to error functions
+    - xfs: always log corruption errors
+    - xfs: fix some memory leaks in log recovery
+    - xfs: stabilize insert range start boundary to avoid COW writeback race
+    - xfs: use bitops interface for buf log item AIL flag check
+    - xfs: refactor agfl length computation function
+    - xfs: split the sunit parameter update into two parts
+    - xfs: don't commit sunit/swidth updates to disk if that would cause repair
+      failures
+    - xfs: fix an ABBA deadlock in xfs_rename
+    - xfs: fix use-after-free when aborting corrupt attr inactivation
+    - ext4: make directory inode spreading reflect flexbg size
+    - Linux 5.4.215
+  * Focal update: v5.4.214 upstream stable release (LP: #1993196)
+    - drm/msm/rd: Fix FIFO-full deadlock
+    - HID: ishtp-hid-clientHID: ishtp-hid-client: Fix comment typo
+    - hid: intel-ish-hid: ishtp: Fix ishtp client sending disordered message
+    - tg3: Disable tg3 device on system reboot to avoid triggering AER
+    - ieee802154: cc2520: add rc code in cc2520_tx()
+    - Input: iforce - add support for Boeder Force Feedback Wheel
+    - nvmet-tcp: fix unhandled tcp states in nvmet_tcp_state_change()
+    - perf/arm_pmu_platform: fix tests for platform_get_irq() failure
+    - platform/x86: acer-wmi: Acer Aspire One AOD270/Packard Bell Dot keymap fixes
+    - usb: storage: Add ASUS <0x0b05:0x1932> to IGNORE_UAS
+    - mm: Fix TLB flush for not-first PFNMAP mappings in unmap_region()
+    - net: dp83822: disable rx error interrupt
+    - soc: fsl: select FSL_GUTS driver for DPIO
+    - tracefs: Only clobber mode/uid/gid on remount if asked
+    - Linux 5.4.214
+  * Focal update: v5.4.213 upstream stable release (LP: #1992211)
+    - efi: capsule-loader: Fix use-after-free in efi_capsule_write
+    - wifi: iwlegacy: 4965: corrected fix for potential off-by-one overflow in
+      il4965_rs_fill_link_cmd()
+    - fs: only do a memory barrier for the first set_buffer_uptodate()
+    - Revert "mm: kmemleak: take a full lowmem check in kmemleak_*_phys()"
+    - net: dp83822: disable false carrier interrupt
+    - drm/msm/dsi: fix the inconsistent indenting
+    - drm/msm/dsi: Fix number of regulators for msm8996_dsi_cfg
+    - platform/x86: pmc_atom: Fix SLP_TYPx bitfield mask
+    - iio: adc: mcp3911: make use of the sign bit
+    - ieee802154/adf7242: defer destroy_workqueue call
+    - wifi: cfg80211: debugfs: fix return type in ht40allow_map_read()
+    - Revert "xhci: turn off port power in shutdown"
+    - net: sched: tbf: don't call qdisc_put() while holding tree lock
+    - ethernet: rocker: fix sleep in atomic context bug in neigh_timer_handler
+    - kcm: fix strp_init() order and cleanup
+    - sch_cake: Return __NET_XMIT_STOLEN when consuming enqueued skb
+    - tcp: annotate data-race around challenge_timestamp
+    - Revert "sch_cake: Return __NET_XMIT_STOLEN when consuming enqueued skb"
+    - net/smc: Remove redundant refcount increase
+    - serial: fsl_lpuart: RS485 RTS polariy is inverse
+    - staging: rtl8712: fix use after free bugs
+    - powerpc: align syscall table for ppc32
+    - vt: Clear selection before changing the font
+    - tty: serial: lpuart: disable flow control while waiting for the transmit
+      engine to complete
+    - Input: iforce - wake up after clearing IFORCE_XMIT_RUNNING flag
+    - iio: adc: mcp3911: use correct formula for AD conversion
+    - misc: fastrpc: fix memory corruption on probe
+    - misc: fastrpc: fix memory corruption on open
+    - USB: serial: ftdi_sio: add Omron CS1W-CIF31 device id
+    - binder: fix UAF of ref->proc caused by race condition
+    - usb: dwc3: qcom: fix use-after-free on runtime-PM wakeup
+    - drm/i915/reg: Fix spelling mistake "Unsupport" -> "Unsupported"
+    - clk: core: Honor CLK_OPS_PARENT_ENABLE for clk gate ops
+    - Revert "clk: core: Honor CLK_OPS_PARENT_ENABLE for clk gate ops"
+    - clk: core: Fix runtime PM sequence in clk_core_unprepare()
+    - Input: rk805-pwrkey - fix module autoloading
+    - clk: bcm: rpi: Fix error handling of raspberrypi_fw_get_rate
+    - hwmon: (gpio-fan) Fix array out of bounds access
+    - gpio: pca953x: Add mutex_lock for regcache sync in PM
+    - thunderbolt: Use the actual buffer in tb_async_error()
+    - xhci: Add grace period after xHC start to prevent premature runtime suspend.
+    - USB: serial: cp210x: add Decagon UCA device id
+    - USB: serial: option: add support for OPPO R11 diag port
+    - USB: serial: option: add Quectel EM060K modem
+    - USB: serial: option: add support for Cinterion MV32-WA/WB RmNet mode
+    - usb: typec: altmodes/displayport: correct pin assignment for UFP receptacles
+    - usb: dwc2: fix wrong order of phy_power_on and phy_init
+    - USB: cdc-acm: Add Icom PMR F3400 support (0c26:0020)
+    - usb-storage: Add ignore-residue quirk for NXP PN7462AU
+    - s390/hugetlb: fix prepare_hugepage_range() check for 2 GB hugepages
+    - s390: fix nospec table alignments
+    - USB: core: Prevent nested device-reset calls
+    - usb: gadget: mass_storage: Fix cdrom data transfers on MAC-OS
+    - driver core: Don't probe devices after bus_type.match() probe deferral
+    - wifi: mac80211: Don't finalize CSA in IBSS mode if state is disconnected
+    - net: mac802154: Fix a condition in the receive path
+    - ALSA: seq: oss: Fix data-race for max_midi_devs access
+    - ALSA: seq: Fix data-race at module auto-loading
+    - drm/i915/glk: ECS Liva Q2 needs GLK HDMI port timing quirk
+    - btrfs: harden identification of a stale device
+    - usb: dwc3: fix PHY disable sequence
+    - usb: dwc3: disable USB core PHY management
+    - USB: serial: ch341: fix lost character on LCR updates
+    - USB: serial: ch341: fix disabled rx timer on older devices
+    - scsi: megaraid_sas: Fix double kfree()
+    - drm/gem: Fix GEM handle release errors
+    - drm/amdgpu: Check num_gfx_rings for gfx v9_0 rb setup.
+    - drm/radeon: add a force flush to delay work when radeon
+    - parisc: ccio-dma: Handle kmalloc failure in ccio_init_resources()
+    - parisc: Add runtime check to prevent PA2.0 kernels on PA1.x machines
+    - arm64: cacheinfo: Fix incorrect assignment of signed error value to unsigned
+      fw_level
+    - fbdev: chipsfb: Add missing pci_disable_device() in chipsfb_pci_init()
+    - drm/amdgpu: mmVM_L2_CNTL3 register not initialized correctly
+    - ALSA: emu10k1: Fix out of bounds access in snd_emu10k1_pcm_channel_alloc()
+    - ALSA: aloop: Fix random zeros in capture data when using jiffies timer
+    - ALSA: usb-audio: Fix an out-of-bounds bug in
+      __snd_usb_parse_audio_interface()
+    - kprobes: Prohibit probes in gate area
+    - debugfs: add debugfs_lookup_and_remove()
+    - nvmet: fix a use-after-free
+    - scsi: mpt3sas: Fix use-after-free warning
+    - scsi: lpfc: Add missing destroy_workqueue() in error path
+    - cgroup: Optimize single thread migration
+    - cgroup: Elide write-locking threadgroup_rwsem when updating csses on an
+      empty subtree
+    - cgroup: Fix threadgroup_rwsem <-> cpus_read_lock() deadlock
+    - smb3: missing inode locks in punch hole
+    - ARM: dts: imx6qdl-kontron-samx6i: remove duplicated node
+    - regulator: core: Clean up on enable failure
+    - RDMA/cma: Fix arguments order in net device validation
+    - soc: brcmstb: pm-arm: Fix refcount leak and __iomem leak bugs
+    - RDMA/hns: Fix supported page size
+    - netfilter: br_netfilter: Drop dst references before setting.
+    - rxrpc: Fix an insufficiently large sglist in rxkad_verify_packet_2()
+    - afs: Use the operation issue time instead of the reply time for callbacks
+    - sch_sfb: Don't assume the skb is still around after enqueueing to child
+    - tipc: fix shift wrapping bug in map_get()
+    - i40e: Fix kernel crash during module removal
+    - RDMA/siw: Pass a pointer to virt_to_page()
+    - ipv6: sr: fix out-of-bounds read when setting HMAC data.
+    - RDMA/mlx5: Set local port to one when accessing counters
+    - nvme-tcp: fix UAF when detecting digest errors
+    - tcp: fix early ETIMEDOUT after spurious non-SACK RTO
+    - sch_sfb: Also store skb len before calling child enqueue
+    - x86/nospec: Fix i386 RSB stuffing
+    - MIPS: loongson32: ls1c: Fix hang during startup
+    - Linux 5.4.213
+  * CVE-2022-2663
+    - netfilter: nf_conntrack_irc: Fix forged IP logic
+  * CVE-2022-3061
+    - video: fbdev: i740fb: Error out if 'pixclock' equals zero
+
+  [ Ubuntu: 5.4.0-135.152 ]
+
+  * focal/linux: 5.4.0-135.152 -proposed tracker (LP: #1997412)
+  * containerd sporadic timeouts (LP: #1996678)
+    - epoll: call final ep_events_available() check under the lock
+    - epoll: check for events when removing a timed out thread from the wait queue
+    - Revert "fs: check FMODE_LSEEK to control internal pipe splicing"
+  * CVE-2022-3621
+    - nilfs2: fix NULL pointer dereference at nilfs_bmap_lookup_at_level()
+  * CVE-2022-3565
+    - mISDN: fix use-after-free bugs in l1oip timer handlers
+  * CVE-2022-3566
+    - tcp: Fix data races around icsk->icsk_af_ops.
+  * CVE-2022-3567
+    - ipv6: annotate some data-races around sk->sk_prot
+    - ipv6: Fix data races around sk->sk_prot.
+  * CVE-2022-3564
+    - Bluetooth: L2CAP: Fix use-after-free caused by l2cap_reassemble_sdu
+  * CVE-2022-3524
+    - tcp/udp: Fix memory leak in ipv6_renew_options().
+  * CVE-2022-3594
+    - r8152: Rate limit overflow messages
+  * CVE-2022-42703
+    - mm/rmap.c: don't reuse anon_vma if we just want a copy
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Mon, 12 Dec 2022 14:14:24 +1000
+
+linux-xilinx-zynqmp (5.4.0-1019.22) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1019.22 -proposed tracker (LP: #1996060)
+
+  * linux-xilinx-zynqmp/focal fails ubuntu_qrt_kernel_security. (LP: #1995465)
+    - [Config] updateconfigs for ubuntu_qrt_kernel_security
+    - [Config] Update abi modules based off updated configs
+
+  * linux-xilinx-zynqmp/focal: main(): sched_setscheduler(): Operation not
+    permitted (LP: #1992912)
+    - [Config] updateconfigs to disable RT_GROUP_SCHED
+
+  [ Ubuntu: 5.4.0-133.149 ]
+
+  * focal/linux: 5.4.0-133.149 -proposed tracker (LP: #1996385)
+  * CVE-2022-42703
+    - mm/rmap.c: don't reuse anon_vma if we just want a copy
+  * [UBUNTU 20.04] KVM: PV: ext call delivered twice when receiver in PSW wait
+    (LP: #1995941)
+    - KVM: s390: pv: don't present the ecall interrupt twice
+  * [UBUNTU 20.04] boot: Add s390x secure boot trailer (LP: #1996071)
+    - s390/boot: add secure boot trailer
+  * Fix rfkill causing soft blocked wifi (LP: #1996198)
+    - platform/x86: hp_wmi: Fix rfkill causing soft blocked wifi
+  * md: Replace snprintf with scnprintf (LP: #1993315)
+    - md: Replace snprintf with scnprintf
+  * input/keyboard: the keyboard on some Asus laptops can't work (LP: #1992266)
+    - ACPI: resource: Skip IRQ override on Asus Vivobook K3402ZA/K3502ZA
+    - ACPI: resource: Add ASUS model S5402ZA to quirks
+  * Focal update: v5.4.218 upstream stable release (LP: #1995530)
+    - mm: pagewalk: Fix race between unmap and page walker
+    - perf tools: Fixup get_current_dir_name() compilation
+    - firmware: arm_scmi: Add SCMI PM driver remove routine
+    - dmaengine: xilinx_dma: cleanup for fetching xlnx,num-fstores property
+    - dmaengine: xilinx_dma: Report error in case of dma_set_mask_and_coherent API
+      failure
+    - ARM: dts: fix Moxa SDIO 'compatible', remove 'sdhci' misnomer
+    - scsi: qedf: Fix a UAF bug in __qedf_probe()
+    - net/ieee802154: fix uninit value bug in dgram_sendmsg
+    - um: Cleanup syscall_handler_t cast in syscalls_32.h
+    - um: Cleanup compiler warning in arch/x86/um/tls_32.c
+    - arch: um: Mark the stack non-executable to fix a binutils warning
+    - usb: mon: make mmapped memory read only
+    - USB: serial: ftdi_sio: fix 300 bps rate for SIO
+    - mmc: core: Replace with already defined values for readability
+    - mmc: core: Terminate infinite loop in SD-UHS voltage switch
+    - rpmsg: qcom: glink: replace strncpy() with strscpy_pad()
+    - nilfs2: fix NULL pointer dereference at nilfs_bmap_lookup_at_level()
+    - nilfs2: fix leak of nilfs_root in case of writer thread creation failure
+    - nilfs2: replace WARN_ONs by nilfs_error for checkpoint acquisition failure
+    - ceph: don't truncate file in atomic_open
+    - random: clamp credited irq bits to maximum mixed
+    - ALSA: hda: Fix position reporting on Poulsbo
+    - efi: Correct Macmini DMI match in uefi cert quirk
+    - USB: serial: qcserial: add new usb-id for Dell branded EM7455
+    - random: restore O_NONBLOCK support
+    - random: avoid reading two cache lines on irq randomness
+    - random: use expired timer rather than wq for mixing fast pool
+    - Input: xpad - add supported devices as contributed on github
+    - Input: xpad - fix wireless 360 controller breaking after suspend
+    - Linux 5.4.218
+  * Focal update: v5.4.217 upstream stable release (LP: #1995528)
+    - xfs: fix misuse of the XFS_ATTR_INCOMPLETE flag
+    - xfs: introduce XFS_MAX_FILEOFF
+    - xfs: truncate should remove all blocks, not just to the end of the page
+      cache
+    - xfs: fix s_maxbytes computation on 32-bit kernels
+    - xfs: fix IOCB_NOWAIT handling in xfs_file_dio_aio_read
+    - xfs: refactor remote attr value buffer invalidation
+    - xfs: fix memory corruption during remote attr value buffer invalidation
+    - xfs: move incore structures out of xfs_da_format.h
+    - xfs: streamline xfs_attr3_leaf_inactive
+    - xfs: fix uninitialized variable in xfs_attr3_leaf_inactive
+    - xfs: remove unused variable 'done'
+    - Makefile.extrawarn: Move -Wcast-function-type-strict to W=1
+    - docs: update mediator information in CoC docs
+    - Linux 5.4.217
+  * Focal update: v5.4.216 upstream stable release (LP: #1995526)
+    - uas: add no-uas quirk for Hiksemi usb_disk
+    - usb-storage: Add Hiksemi USB3-FW to IGNORE_UAS
+    - uas: ignore UAS for Thinkplus chips
+    - net: usb: qmi_wwan: Add new usb-id for Dell branded EM7455
+    - clk: ingenic-tcu: Properly enable registers before accessing timers
+    - ARM: dts: integrator: Tag PCI host with device_type
+    - ntfs: fix BUG_ON in ntfs_lookup_inode_by_name()
+    - libata: add ATA_HORKAGE_NOLPM for Pioneer BDR-207M and BDR-205
+    - mmc: moxart: fix 4-bit bus width and remove 8-bit bus width
+    - mm/page_alloc: fix race condition between build_all_zonelists and page
+      allocation
+    - mm: prevent page_frag_alloc() from corrupting the memory
+    - mm/migrate_device.c: flush TLB while holding PTL
+    - mm: fix madivse_pageout mishandling on non-LRU page
+    - media: dvb_vb2: fix possible out of bound access
+    - ARM: dts: Move am33xx and am43xx mmc nodes to sdhci-omap driver
+    - ARM: dts: am33xx: Fix MMCHS0 dma properties
+    - soc: sunxi: sram: Actually claim SRAM regions
+    - soc: sunxi: sram: Prevent the driver from being unbound
+    - soc: sunxi_sram: Make use of the helper function
+      devm_platform_ioremap_resource()
+    - soc: sunxi: sram: Fix probe function ordering issues
+    - soc: sunxi: sram: Fix debugfs info for A64 SRAM C
+    - Revert "drm: bridge: analogix/dp: add panel prepare/unprepare in
+      suspend/resume time"
+    - Input: melfas_mip4 - fix return value check in mip4_probe()
+    - usbnet: Fix memory leak in usbnet_disconnect()
+    - nvme: add new line after variable declatation
+    - nvme: Fix IOC_PR_CLEAR and IOC_PR_RELEASE ioctls for nvme devices
+    - selftests: Fix the if conditions of in test_extra_filter()
+    - clk: imx: imx6sx: remove the SET_RATE_PARENT flag for QSPI clocks
+    - clk: iproc: Do not rely on node name for correct PLL setup
+    - Linux 5.4.216
+  * Focal update: v5.4.215 upstream stable release (LP: #1993203)
+    - of: fdt: fix off-by-one error in unflatten_dt_nodes()
+    - NFSv4: Turn off open-by-filehandle and NFS re-export for NFSv4.0
+    - gpio: mpc8xxx: Fix support for IRQ_TYPE_LEVEL_LOW flow_type in mpc85xx
+    - drm/meson: Correct OSD1 global alpha value
+    - drm/meson: Fix OSD1 RGB to YCbCr coefficient
+    - parisc: ccio-dma: Add missing iounmap in error path in ccio_probe()
+    - ALSA: pcm: oss: Fix race at SNDCTL_DSP_SYNC
+    - task_stack, x86/cea: Force-inline stack helpers
+    - tracing: hold caller_addr to hardirq_{enable,disable}_ip
+    - cifs: revalidate mapping when doing direct writes
+    - cifs: don't send down the destination address to sendmsg for a SOCK_STREAM
+    - MAINTAINERS: add Chandan as xfs maintainer for 5.4.y
+    - iomap: iomap that extends beyond EOF should be marked dirty
+    - ASoC: nau8824: Fix semaphore unbalance at error paths
+    - regulator: pfuze100: Fix the global-out-of-bounds access in
+      pfuze100_regulator_probe()
+    - rxrpc: Fix local destruction being repeated
+    - rxrpc: Fix calc of resend age
+    - ALSA: hda/sigmatel: Keep power up while beep is enabled
+    - ALSA: hda/tegra: Align BDL entry to 4KB boundary
+    - net: usb: qmi_wwan: add Quectel RM520N
+    - afs: Return -EAGAIN, not -EREMOTEIO, when a file already locked
+    - MIPS: OCTEON: irq: Fix octeon_irq_force_ciu_mapping()
+    - mksysmap: Fix the mismatch of 'L0' symbols in System.map
+    - video: fbdev: pxa3xx-gcu: Fix integer overflow in pxa3xx_gcu_write
+    - cgroup: Add missing cpus_read_lock() to cgroup_attach_task_all()
+    - ALSA: hda/sigmatel: Fix unused variable warning for beep power change
+    - usb: dwc3: gadget: Avoid starting DWC3 gadget during UDC unbind
+    - usb: dwc3: Issue core soft reset before enabling run/stop
+    - usb: dwc3: gadget: Prevent repeat pullup()
+    - usb: dwc3: gadget: Refactor pullup()
+    - usb: dwc3: gadget: Don't modify GEVNTCOUNT in pullup()
+    - usb: dwc3: gadget: Avoid duplicate requests to enable Run/Stop
+    - usb: xhci-mtk: get the microframe boundary for ESIT
+    - usb: xhci-mtk: add only one extra CS for FS/LS INTR
+    - usb: xhci-mtk: use @sch_tt to check whether need do TT schedule
+    - usb: xhci-mtk: add a function to (un)load bandwidth info
+    - usb: xhci-mtk: add some schedule error number
+    - usb: xhci-mtk: allow multiple Start-Split in a microframe
+    - usb: xhci-mtk: relax TT periodic bandwidth allocation
+    - wifi: mac80211: Fix UAF in ieee80211_scan_rx()
+    - tty/serial: atmel: RS485 & ISO7816: wait for TXRDY before sending data
+    - serial: atmel: remove redundant assignment in rs485_config
+    - tty: serial: atmel: Preserve previous USART mode if RS485 disabled
+    - usb: add quirks for Lenovo OneLink+ Dock
+    - usb: gadget: udc-xilinx: replace memcpy with memcpy_toio
+    - usb: cdns3: fix issue with rearming ISO OUT endpoint
+    - Revert "usb: add quirks for Lenovo OneLink+ Dock"
+    - Revert "usb: gadget: udc-xilinx: replace memcpy with memcpy_toio"
+    - USB: core: Fix RST error in hub.c
+    - USB: serial: option: add Quectel BG95 0x0203 composition
+    - USB: serial: option: add Quectel RM520N
+    - ALSA: hda/tegra: set depop delay for tegra
+    - ALSA: hda: add Intel 5 Series / 3400 PCI DID
+    - ALSA: hda/realtek: Add quirk for Huawei WRT-WX9
+    - ALSA: hda/realtek: Re-arrange quirk table entries
+    - ALSA: hda/realtek: Add pincfg for ASUS G513 HP jack
+    - ALSA: hda/realtek: Add pincfg for ASUS G533Z HP jack
+    - ALSA: hda/realtek: Add quirk for ASUS GA503R laptop
+    - ALSA: hda/realtek: Enable 4-speaker output Dell Precision 5530 laptop
+    - efi: libstub: check Shim mode using MokSBStateRT
+    - mm/slub: fix to return errno if kmalloc() fails
+    - arm64: dts: rockchip: Pull up wlan wake# on Gru-Bob
+    - arm64: dts: rockchip: Set RK3399-Gru PCLK_EDP to 24 MHz
+    - arm64: dts: rockchip: Remove 'enable-active-low' from rk3399-puma
+    - netfilter: nf_conntrack_sip: fix ct_sip_walk_headers
+    - netfilter: nf_conntrack_irc: Tighten matching on DCC message
+    - netfilter: nfnetlink_osf: fix possible bogus match in nf_osf_find()
+    - iavf: Fix cached head and tail value for iavf_get_tx_pending
+    - ipvlan: Fix out-of-bound bugs caused by unset skb->mac_header
+    - net: team: Unsync device addresses on ndo_stop
+    - MIPS: lantiq: export clk_get_io() for lantiq_wdt.ko
+    - MIPS: Loongson32: Fix PHY-mode being left unspecified
+    - iavf: Fix bad page state
+    - i40e: Fix set max_tx_rate when it is lower than 1 Mbps
+    - of: mdio: Add of_node_put() when breaking out of for_each_xx
+    - net/sched: taprio: avoid disabling offload when it was never enabled
+    - net/sched: taprio: make qdisc_leaf() see the per-netdev-queue pfifo child
+      qdiscs
+    - netfilter: ebtables: fix memory leak when blob is malformed
+    - can: gs_usb: gs_can_open(): fix race dev->can.state condition
+    - perf jit: Include program header in ELF files
+    - perf kcore_copy: Do not check /proc/modules is unchanged
+    - net: sunhme: Fix packet reception for len < RX_COPY_THRESHOLD
+    - net: sched: fix possible refcount leak in tc_new_tfilter()
+    - serial: Create uart_xmit_advance()
+    - serial: tegra: Use uart_xmit_advance(), fixes icount.tx accounting
+    - serial: tegra-tcu: Use uart_xmit_advance(), fixes icount.tx accounting
+    - s390/dasd: fix Oops in dasd_alias_get_start_dev due to missing pavgroup
+    - usb: xhci-mtk: fix issue of out-of-bounds array access
+    - cifs: always initialize struct msghdr smb_msg completely
+    - Drivers: hv: Never allocate anything besides framebuffer from framebuffer
+      memory region
+    - drm/amd/display: Limit user regamma to a valid value
+    - drm/rockchip: Fix return type of cdn_dp_connector_mode_valid
+    - workqueue: don't skip lockdep work dependency in cancel_work_sync()
+    - ext4: fix bug in extents parsing when eh_entries == 0 and eh_depth > 0
+    - xfs: replace -EIO with -EFSCORRUPTED for corrupt metadata
+    - xfs: slightly tweak an assert in xfs_fs_map_blocks
+    - xfs: add missing assert in xfs_fsmap_owner_from_rmap
+    - xfs: range check ri_cnt when recovering log items
+    - xfs: attach dquots and reserve quota blocks during unwritten conversion
+    - xfs: convert EIO to EFSCORRUPTED when log contents are invalid
+    - xfs: constify the buffer pointer arguments to error functions
+    - xfs: always log corruption errors
+    - xfs: fix some memory leaks in log recovery
+    - xfs: stabilize insert range start boundary to avoid COW writeback race
+    - xfs: use bitops interface for buf log item AIL flag check
+    - xfs: refactor agfl length computation function
+    - xfs: split the sunit parameter update into two parts
+    - xfs: don't commit sunit/swidth updates to disk if that would cause repair
+      failures
+    - xfs: fix an ABBA deadlock in xfs_rename
+    - xfs: fix use-after-free when aborting corrupt attr inactivation
+    - ext4: make directory inode spreading reflect flexbg size
+    - Linux 5.4.215
+  * Focal update: v5.4.214 upstream stable release (LP: #1993196)
+    - drm/msm/rd: Fix FIFO-full deadlock
+    - HID: ishtp-hid-clientHID: ishtp-hid-client: Fix comment typo
+    - hid: intel-ish-hid: ishtp: Fix ishtp client sending disordered message
+    - tg3: Disable tg3 device on system reboot to avoid triggering AER
+    - ieee802154: cc2520: add rc code in cc2520_tx()
+    - Input: iforce - add support for Boeder Force Feedback Wheel
+    - nvmet-tcp: fix unhandled tcp states in nvmet_tcp_state_change()
+    - perf/arm_pmu_platform: fix tests for platform_get_irq() failure
+    - platform/x86: acer-wmi: Acer Aspire One AOD270/Packard Bell Dot keymap fixes
+    - usb: storage: Add ASUS <0x0b05:0x1932> to IGNORE_UAS
+    - mm: Fix TLB flush for not-first PFNMAP mappings in unmap_region()
+    - net: dp83822: disable rx error interrupt
+    - soc: fsl: select FSL_GUTS driver for DPIO
+    - tracefs: Only clobber mode/uid/gid on remount if asked
+    - Linux 5.4.214
+  * Focal update: v5.4.213 upstream stable release (LP: #1992211)
+    - efi: capsule-loader: Fix use-after-free in efi_capsule_write
+    - wifi: iwlegacy: 4965: corrected fix for potential off-by-one overflow in
+      il4965_rs_fill_link_cmd()
+    - fs: only do a memory barrier for the first set_buffer_uptodate()
+    - Revert "mm: kmemleak: take a full lowmem check in kmemleak_*_phys()"
+    - net: dp83822: disable false carrier interrupt
+    - drm/msm/dsi: fix the inconsistent indenting
+    - drm/msm/dsi: Fix number of regulators for msm8996_dsi_cfg
+    - platform/x86: pmc_atom: Fix SLP_TYPx bitfield mask
+    - iio: adc: mcp3911: make use of the sign bit
+    - ieee802154/adf7242: defer destroy_workqueue call
+    - wifi: cfg80211: debugfs: fix return type in ht40allow_map_read()
+    - Revert "xhci: turn off port power in shutdown"
+    - net: sched: tbf: don't call qdisc_put() while holding tree lock
+    - ethernet: rocker: fix sleep in atomic context bug in neigh_timer_handler
+    - kcm: fix strp_init() order and cleanup
+    - sch_cake: Return __NET_XMIT_STOLEN when consuming enqueued skb
+    - tcp: annotate data-race around challenge_timestamp
+    - Revert "sch_cake: Return __NET_XMIT_STOLEN when consuming enqueued skb"
+    - net/smc: Remove redundant refcount increase
+    - serial: fsl_lpuart: RS485 RTS polariy is inverse
+    - staging: rtl8712: fix use after free bugs
+    - powerpc: align syscall table for ppc32
+    - vt: Clear selection before changing the font
+    - tty: serial: lpuart: disable flow control while waiting for the transmit
+      engine to complete
+    - Input: iforce - wake up after clearing IFORCE_XMIT_RUNNING flag
+    - iio: adc: mcp3911: use correct formula for AD conversion
+    - misc: fastrpc: fix memory corruption on probe
+    - misc: fastrpc: fix memory corruption on open
+    - USB: serial: ftdi_sio: add Omron CS1W-CIF31 device id
+    - binder: fix UAF of ref->proc caused by race condition
+    - usb: dwc3: qcom: fix use-after-free on runtime-PM wakeup
+    - drm/i915/reg: Fix spelling mistake "Unsupport" -> "Unsupported"
+    - clk: core: Honor CLK_OPS_PARENT_ENABLE for clk gate ops
+    - Revert "clk: core: Honor CLK_OPS_PARENT_ENABLE for clk gate ops"
+    - clk: core: Fix runtime PM sequence in clk_core_unprepare()
+    - Input: rk805-pwrkey - fix module autoloading
+    - clk: bcm: rpi: Fix error handling of raspberrypi_fw_get_rate
+    - hwmon: (gpio-fan) Fix array out of bounds access
+    - gpio: pca953x: Add mutex_lock for regcache sync in PM
+    - thunderbolt: Use the actual buffer in tb_async_error()
+    - xhci: Add grace period after xHC start to prevent premature runtime suspend.
+    - USB: serial: cp210x: add Decagon UCA device id
+    - USB: serial: option: add support for OPPO R11 diag port
+    - USB: serial: option: add Quectel EM060K modem
+    - USB: serial: option: add support for Cinterion MV32-WA/WB RmNet mode
+    - usb: typec: altmodes/displayport: correct pin assignment for UFP receptacles
+    - usb: dwc2: fix wrong order of phy_power_on and phy_init
+    - USB: cdc-acm: Add Icom PMR F3400 support (0c26:0020)
+    - usb-storage: Add ignore-residue quirk for NXP PN7462AU
+    - s390/hugetlb: fix prepare_hugepage_range() check for 2 GB hugepages
+    - s390: fix nospec table alignments
+    - USB: core: Prevent nested device-reset calls
+    - usb: gadget: mass_storage: Fix cdrom data transfers on MAC-OS
+    - driver core: Don't probe devices after bus_type.match() probe deferral
+    - wifi: mac80211: Don't finalize CSA in IBSS mode if state is disconnected
+    - net: mac802154: Fix a condition in the receive path
+    - ALSA: seq: oss: Fix data-race for max_midi_devs access
+    - ALSA: seq: Fix data-race at module auto-loading
+    - drm/i915/glk: ECS Liva Q2 needs GLK HDMI port timing quirk
+    - btrfs: harden identification of a stale device
+    - usb: dwc3: fix PHY disable sequence
+    - usb: dwc3: disable USB core PHY management
+    - USB: serial: ch341: fix lost character on LCR updates
+    - USB: serial: ch341: fix disabled rx timer on older devices
+    - scsi: megaraid_sas: Fix double kfree()
+    - drm/gem: Fix GEM handle release errors
+    - drm/amdgpu: Check num_gfx_rings for gfx v9_0 rb setup.
+    - drm/radeon: add a force flush to delay work when radeon
+    - parisc: ccio-dma: Handle kmalloc failure in ccio_init_resources()
+    - parisc: Add runtime check to prevent PA2.0 kernels on PA1.x machines
+    - arm64: cacheinfo: Fix incorrect assignment of signed error value to unsigned
+      fw_level
+    - fbdev: chipsfb: Add missing pci_disable_device() in chipsfb_pci_init()
+    - drm/amdgpu: mmVM_L2_CNTL3 register not initialized correctly
+    - ALSA: emu10k1: Fix out of bounds access in snd_emu10k1_pcm_channel_alloc()
+    - ALSA: aloop: Fix random zeros in capture data when using jiffies timer
+    - ALSA: usb-audio: Fix an out-of-bounds bug in
+      __snd_usb_parse_audio_interface()
+    - kprobes: Prohibit probes in gate area
+    - debugfs: add debugfs_lookup_and_remove()
+    - nvmet: fix a use-after-free
+    - scsi: mpt3sas: Fix use-after-free warning
+    - scsi: lpfc: Add missing destroy_workqueue() in error path
+    - cgroup: Optimize single thread migration
+    - cgroup: Elide write-locking threadgroup_rwsem when updating csses on an
+      empty subtree
+    - cgroup: Fix threadgroup_rwsem <-> cpus_read_lock() deadlock
+    - smb3: missing inode locks in punch hole
+    - ARM: dts: imx6qdl-kontron-samx6i: remove duplicated node
+    - regulator: core: Clean up on enable failure
+    - RDMA/cma: Fix arguments order in net device validation
+    - soc: brcmstb: pm-arm: Fix refcount leak and __iomem leak bugs
+    - RDMA/hns: Fix supported page size
+    - netfilter: br_netfilter: Drop dst references before setting.
+    - rxrpc: Fix an insufficiently large sglist in rxkad_verify_packet_2()
+    - afs: Use the operation issue time instead of the reply time for callbacks
+    - sch_sfb: Don't assume the skb is still around after enqueueing to child
+    - tipc: fix shift wrapping bug in map_get()
+    - i40e: Fix kernel crash during module removal
+    - RDMA/siw: Pass a pointer to virt_to_page()
+    - ipv6: sr: fix out-of-bounds read when setting HMAC data.
+    - RDMA/mlx5: Set local port to one when accessing counters
+    - nvme-tcp: fix UAF when detecting digest errors
+    - tcp: fix early ETIMEDOUT after spurious non-SACK RTO
+    - sch_sfb: Also store skb len before calling child enqueue
+    - x86/nospec: Fix i386 RSB stuffing
+    - MIPS: loongson32: ls1c: Fix hang during startup
+    - Linux 5.4.213
+  * CVE-2022-2663
+    - netfilter: nf_conntrack_irc: Fix forged IP logic
+  * CVE-2022-3061
+    - video: fbdev: i740fb: Error out if 'pixclock' equals zero
+
+  [ Ubuntu: 5.4.0-132.148 ]
+
+  * CVE-2022-42719
+    - mac80211: mlme: find auth challenge directly
+    - wifi: mac80211: don't parse mbssid in assoc response
+    - wifi: mac80211: fix MBSSID parsing use-after-free
+  * iavf: SR-IOV VFs error with no traffic flow when MTU greater than 1500
+    (LP: #1983656)
+    - iavf: Fix set max MTU size with port VLAN and jumbo frames
+    - i40e: Fix VF set max MTU size
+  * fib_nexthop_nongw.sh from ubuntu_kernel_selftests failed on B-5.4
+    (LP: #1990800)
+    - SAUCE: selftests/net: skipping tests for older ip command releases
+  * CVE-2022-29901
+    - Revert "x86/speculation: Add RSB VM Exit protections"
+    - Revert "x86/cpu: Add a steppings field to struct x86_cpu_id"
+    - x86/devicetable: Move x86 specific macro out of generic code
+    - x86/cpu: Add consistent CPU match macros
+    - x86/cpu: Add a steppings field to struct x86_cpu_id
+    - x86/kvm/vmx: Make noinstr clean
+    - x86/cpufeatures: Move RETPOLINE flags to word 11
+    - x86/bugs: Report AMD retbleed vulnerability
+    - x86/bugs: Add AMD retbleed= boot parameter
+    - x86/bugs: Keep a per-CPU IA32_SPEC_CTRL value
+    - x86/entry: Remove skip_r11rcx
+    - x86/entry: Add kernel IBRS implementation
+    - x86/bugs: Optimize SPEC_CTRL MSR writes
+    - x86/speculation: Add spectre_v2=ibrs option to support Kernel IBRS
+    - x86/bugs: Split spectre_v2_select_mitigation() and
+      spectre_v2_user_select_mitigation()
+    - x86/bugs: Report Intel retbleed vulnerability
+    - intel_idle: Disable IBRS during long idle
+    - x86/speculation: Change FILL_RETURN_BUFFER to work with objtool
+    - x86/speculation: Fix RSB filling with CONFIG_RETPOLINE=n
+    - x86/speculation: Fix firmware entry SPEC_CTRL handling
+    - x86/speculation: Fix SPEC_CTRL write on SMT state change
+    - x86/speculation: Use cached host SPEC_CTRL value for guest entry/exit
+    - x86/speculation: Remove x86_spec_ctrl_mask
+    - KVM/VMX: Use TEST %REG,%REG instead of CMP $0,%REG in vmenter.S
+    - KVM/nVMX: Use __vmx_vcpu_run in nested_vmx_check_vmentry_hw
+    - KVM: VMX: Flatten __vmx_vcpu_run()
+    - KVM: VMX: Convert launched argument to flags
+    - KVM: VMX: Prevent guest RSB poisoning attacks with eIBRS
+    - KVM: VMX: Fix IBRS handling after vmexit
+    - x86/speculation: Fill RSB on vmexit for IBRS
+    - x86/common: Stamp out the stepping madness
+    - x86/cpu/amd: Enumerate BTC_NO
+    - x86/bugs: Add Cannon lake to RETBleed affected CPU list
+    - x86/speculation: Disable RRSBA behavior
+    - x86/speculation: Use DECLARE_PER_CPU for x86_spec_ctrl_current
+    - x86/bugs: Warn when "ibrs" mitigation is selected on Enhanced IBRS parts
+    - x86/speculation: Add RSB VM Exit protections
+  * ACPI: processor idle: Practically limit "Dummy wait" workaround to old Intel
+    systems (LP: #1990985)
+    - ACPI: processor_idle: Skip dummy wait if kernel is in guest
+    - ACPI: processor idle: Practically limit "Dummy wait" workaround to old Intel
+      systems
+  * cgroup: all controllers mounted when using 'cgroup_no_v1=' (LP: #1988584)
+    - cgroup-v1: add disabled controller check in cgroup1_parse_param()
+  * Focal update: v5.4.212 upstream stable release (LP: #1991156)
+    - audit: fix potential double free on error path from fsnotify_add_inode_mark
+    - parisc: Fix exception handler for fldw and fstw instructions
+    - kernel/sys_ni: add compat entry for fadvise64_64
+    - usb: cdns3: Fix issue for clear halt endpoint
+    - pinctrl: amd: Don't save/restore interrupt status and wake status bits
+    - sched/deadline: Unthrottle PI boosted threads while enqueuing
+    - sched/deadline: Fix stale throttling on de-/boosted tasks
+    - sched/deadline: Fix priority inheritance with multiple scheduling classes
+    - kernel/sched: Remove dl_boosted flag comment
+    - xfrm: fix refcount leak in __xfrm_policy_check()
+    - SUNRPC: RPC level errors should set task->tk_rpc_status
+    - rose: check NULL rose_loopback_neigh->loopback
+    - net/mlx5e: Properly disable vlan strip on non-UL reps
+    - net: moxa: get rid of asymmetry in DMA mapping/unmapping
+    - bonding: 802.3ad: fix no transmission of LACPDUs
+    - net: ipvtap - add __init/__exit annotations to module init/exit funcs
+    - netfilter: ebtables: reject blobs that don't provide all entry points
+    - bnxt_en: fix NQ resource accounting during vf creation on 57500 chips
+    - netfilter: nft_payload: report ERANGE for too long offset and length
+    - netfilter: nft_payload: do not truncate csum_offset and csum_type
+    - netfilter: nft_osf: restrict osf to ipv4, ipv6 and inet families
+    - netfilter: nft_tunnel: restrict it to netdev family
+    - net: Fix data-races around weight_p and dev_weight_[rt]x_bias.
+    - net: Fix data-races around netdev_tstamp_prequeue.
+    - ratelimit: Fix data-races in ___ratelimit().
+    - net: Fix a data-race around sysctl_tstamp_allow_data.
+    - net: Fix a data-race around sysctl_net_busy_poll.
+    - net: Fix a data-race around sysctl_net_busy_read.
+    - net: Fix a data-race around netdev_budget.
+    - net: Fix a data-race around netdev_budget_usecs.
+    - net: Fix a data-race around sysctl_somaxconn.
+    - ixgbe: stop resetting SYSTIME in ixgbe_ptp_start_cyclecounter
+    - btrfs: fix silent failure when deleting root reference
+    - btrfs: replace: drop assert for suspended replace
+    - btrfs: add info when mount fails due to stale replace target
+    - btrfs: check if root is readonly while setting security xattr
+    - x86/unwind/orc: Unwind ftrace trampolines with correct ORC entry
+    - loop: Check for overflow while configuring loop
+    - asm-generic: sections: refactor memory_intersects
+    - s390: fix double free of GS and RI CBs on fork() failure
+    - ACPI: processor: Remove freq Qos request for all CPUs
+    - mm/hugetlb: fix hugetlb not supporting softdirty tracking
+    - md: call __md_stop_writes in md_stop
+    - perf/x86/intel/uncore: Fix broken read_counter() for SNB IMC PMU
+    - scsi: storvsc: Remove WQ_MEM_RECLAIM from storvsc_error_wq
+    - mm: Force TLB flush for PFNMAP mappings before unlink_file_vma()
+    - s390/mm: do not trigger write fault when vma does not allow VM_WRITE
+    - x86/bugs: Add "unknown" reporting for MMIO Stale Data
+    - kbuild: Fix include path in scripts/Makefile.modpost
+    - Bluetooth: L2CAP: Fix build errors in some archs
+    - HID: steam: Prevent NULL pointer dereference in steam_{recv,send}_report
+    - udmabuf: Set the DMA mask for the udmabuf device (v2)
+    - media: pvrusb2: fix memory leak in pvr_probe
+    - HID: hidraw: fix memory leak in hidraw_release()
+    - fbdev: fb_pm2fb: Avoid potential divide by zero error
+    - ftrace: Fix NULL pointer dereference in is_ftrace_trampoline when ftrace is
+      dead
+    - bpf: Don't redirect packets with invalid pkt_len
+    - mm/rmap: Fix anon_vma->degree ambiguity leading to double-reuse
+    - btrfs: introduce btrfs_lookup_match_dir
+    - btrfs: do not pin logs too early during renames
+    - btrfs: unify lookup return value when dir entry is missing
+    - drm/amd/display: Avoid MPC infinite loop
+    - drm/amd/display: clear optc underflow before turn off odm clock
+    - neigh: fix possible DoS due to net iface start/stop loop
+    - s390/hypfs: avoid error message under KVM
+    - drm/amd/display: Fix pixel clock programming
+    - netfilter: conntrack: NF_CONNTRACK_PROCFS should no longer default to y
+    - btrfs: tree-checker: check for overlapping extent items
+    - lib/vdso: Let do_coarse() return 0 to simplify the callsite
+    - lib/vdso: Mark do_hres() and do_coarse() as __always_inline
+    - kprobes: don't call disarm_kprobe() for disabled kprobes
+    - net/af_packet: check len when min_header_len equals to 0
+    - net: neigh: don't call kfree_skb() under spin_lock_irqsave()
+    - Linux 5.4.212
+  * Focal update: v5.4.211 upstream stable release (LP: #1990190)
+    - Makefile: link with -z noexecstack --no-warn-rwx-segments
+    - x86: link vdso and boot with -z noexecstack --no-warn-rwx-segments
+    - scsi: Revert "scsi: qla2xxx: Fix disk failure to rediscover"
+    - ALSA: bcd2000: Fix a UAF bug on the error path of probing
+    - igc: Remove _I_PHY_ID checking
+    - wifi: mac80211_hwsim: fix race condition in pending packet
+    - wifi: mac80211_hwsim: add back erroneously removed cast
+    - wifi: mac80211_hwsim: use 32-bit skb cookie
+    - add barriers to buffer_uptodate and set_buffer_uptodate
+    - HID: wacom: Only report rotation for art pen
+    - HID: wacom: Don't register pad_input for touch switch
+    - KVM: nVMX: Snapshot pre-VM-Enter BNDCFGS for !nested_run_pending case
+    - KVM: nVMX: Snapshot pre-VM-Enter DEBUGCTL for !nested_run_pending case
+    - KVM: SVM: Don't BUG if userspace injects an interrupt with GIF=0
+    - KVM: nVMX: Let userspace set nVMX MSR to any _host_ supported value
+    - KVM: x86: Mark TSS busy during LTR emulation _after_ all fault checks
+    - KVM: x86: Set error code to segment selector on LLDT/LTR non-canonical #GP
+    - mm/mremap: hold the rmap lock in write mode when moving page table entries.
+    - ALSA: hda/conexant: Add quirk for LENOVO 20149 Notebook model
+    - ALSA: hda/cirrus - support for iMac 12,1 model
+    - ALSA: hda/realtek: Add quirk for another Asus K42JZ model
+    - tty: vt: initialize unicode screen buffer
+    - vfs: Check the truncate maximum size in inode_newsize_ok()
+    - fs: Add missing umask strip in vfs_tmpfile
+    - thermal: sysfs: Fix cooling_device_stats_setup() error code path
+    - fbcon: Fix boundary checks for fbcon=vc:n1-n2 parameters
+    - usbnet: Fix linkwatch use-after-free on disconnect
+    - ovl: drop WARN_ON() dentry is NULL in ovl_encode_fh()
+    - parisc: Fix device names in /proc/iomem
+    - parisc: io_pgetevents_time64() needs compat syscall in 32-bit compat mode
+    - drm/gem: Properly annotate WW context on drm_gem_lock_reservations() error
+    - drm/nouveau: fix another off-by-one in nvbios_addr
+    - drm/amdgpu: Check BO's requested pinning domains against its
+      preferred_domains
+    - iio: light: isl29028: Fix the warning in isl29028_remove()
+    - fuse: limit nsec
+    - serial: mvebu-uart: uart2 error bits clearing
+    - md-raid10: fix KASAN warning
+    - ia64, processor: fix -Wincompatible-pointer-types in ia64_get_irr()
+    - PCI: Add defines for normal and subtractive PCI bridges
+    - powerpc/fsl-pci: Fix Class Code of PCIe Root Port
+    - powerpc/ptdump: Fix display of RW pages on FSL_BOOK3E
+    - powerpc/powernv: Avoid crashing if rng is NULL
+    - MIPS: cpuinfo: Fix a warning for CONFIG_CPUMASK_OFFSTACK
+    - coresight: Clear the connection field properly
+    - USB: HCD: Fix URB giveback issue in tasklet function
+    - ARM: dts: uniphier: Fix USB interrupts for PXs2 SoC
+    - arm64: dts: uniphier: Fix USB interrupts for PXs3 SoC
+    - netfilter: nf_tables: fix null deref due to zeroed list head
+    - epoll: autoremove wakers even more aggressively
+    - x86: Handle idle=nomwait cmdline properly for x86_idle
+    - arm64: Do not forget syscall when starting a new thread.
+    - arm64: fix oops in concurrently setting insn_emulation sysctls
+    - ext2: Add more validity checks for inode counts
+    - genirq: Don't return error on missing optional irq_request_resources()
+    - wait: Fix __wait_event_hrtimeout for RT/DL tasks
+    - ARM: dts: imx6ul: add missing properties for sram
+    - ARM: dts: imx6ul: change operating-points to uint32-matrix
+    - ARM: dts: imx6ul: fix csi node compatible
+    - ARM: dts: imx6ul: fix lcdif node compatible
+    - ARM: dts: imx6ul: fix qspi node compatible
+    - spi: synquacer: Add missing clk_disable_unprepare()
+    - ARM: OMAP2+: display: Fix refcount leak bug
+    - ACPI: EC: Remove duplicate ThinkPad X1 Carbon 6th entry from DMI quirks
+    - ACPI: PM: save NVS memory for Lenovo G40-45
+    - ACPI: LPSS: Fix missing check in register_device_clock()
+    - arm64: dts: qcom: ipq8074: fix NAND node name
+    - arm64: dts: allwinner: a64: orangepi-win: Fix LED node name
+    - ARM: shmobile: rcar-gen2: Increase refcount for new reference
+    - PM: hibernate: defer device probing when resuming from hibernation
+    - selinux: Add boundary check in put_entry()
+    - spi: spi-rspi: Fix PIO fallback on RZ platforms
+    - ARM: findbit: fix overflowing offset
+    - meson-mx-socinfo: Fix refcount leak in meson_mx_socinfo_init
+    - ARM: bcm: Fix refcount leak in bcm_kona_smc_init
+    - x86/pmem: Fix platform-device leak in error path
+    - ARM: dts: ast2500-evb: fix board compatible
+    - ARM: dts: ast2600-evb: fix board compatible
+    - soc: fsl: guts: machine variable might be unset
+    - ARM: dts: qcom: mdm9615: add missing PMIC GPIO reg
+    - ARM: OMAP2+: Fix refcount leak in omapdss_init_of
+    - ARM: OMAP2+: Fix refcount leak in omap3xxx_prm_late_init
+    - cpufreq: zynq: Fix refcount leak in zynq_get_revision
+    - soc: qcom: aoss: Fix refcount leak in qmp_cooling_devices_register
+    - ARM: dts: qcom: pm8841: add required thermal-sensor-cells
+    - bus: hisi_lpc: fix missing platform_device_put() in hisi_lpc_acpi_probe()
+    - arm64: dts: mt7622: fix BPI-R64 WPS button
+    - erofs: avoid consecutive detection for Highmem memory
+    - blk-mq: don't create hctx debugfs dir until q->debugfs_dir is created
+    - regulator: of: Fix refcount leak bug in of_get_regulation_constraints()
+    - nohz/full, sched/rt: Fix missed tick-reenabling bug in dequeue_task_rt()
+    - thermal/tools/tmon: Include pthread and time headers in tmon.h
+    - dm: return early from dm_pr_call() if DM device is suspended
+    - ath10k: do not enforce interrupt trigger type
+    - wifi: rtlwifi: fix error codes in rtl_debugfs_set_write_h2c()
+    - drm/mipi-dbi: align max_chunk to 2 in spi_transfer
+    - drm/radeon: fix potential buffer overflow in ni_set_mc_special_registers()
+    - drm/mediatek: Add pull-down MIPI operation in mtk_dsi_poweroff function
+    - drm: adv7511: override i2c address of cec before accessing it
+    - i2c: Fix a potential use after free
+    - media: tw686x: Register the irq at the end of probe
+    - wifi: iwlegacy: 4965: fix potential off-by-one overflow in
+      il4965_rs_fill_link_cmd()
+    - drm: bridge: adv7511: Add check for mipi_dsi_driver_register
+    - drm/mcde: Fix refcount leak in mcde_dsi_bind
+    - media: hdpvr: fix error value returns in hdpvr_read
+    - drm/vc4: plane: Remove subpixel positioning check
+    - drm/vc4: plane: Fix margin calculations for the right/bottom edges
+    - drm/vc4: dsi: Correct DSI divider calculations
+    - crypto: arm64/gcm - Select AEAD for GHASH_ARM64_CE
+    - drm/rockchip: vop: Don't crash for invalid duplicate_state()
+    - drm/rockchip: Fix an error handling path rockchip_dp_probe()
+    - drm/mediatek: dpi: Remove output format of YUV
+    - drm/mediatek: dpi: Only enable dpi after the bridge is enabled
+    - drm: bridge: sii8620: fix possible off-by-one
+    - drm/msm/mdp5: Fix global state lock backoff
+    - crypto: hisilicon - Kunpeng916 crypto driver don't sleep when in softirq
+    - media: platform: mtk-mdp: Fix mdp_ipi_comm structure alignment
+    - mediatek: mt76: mac80211: Fix missing of_node_put() in mt76_led_init()
+    - drm/exynos/exynos7_drm_decon: free resources when clk_set_parent() failed.
+    - tcp: make retransmitted SKB fit into the send window
+    - libbpf: Fix the name of a reused map
+    - selftests: timers: valid-adjtimex: build fix for newer toolchains
+    - selftests: timers: clocksource-switch: fix passing errors from child
+    - fs: check FMODE_LSEEK to control internal pipe splicing
+    - wifi: wil6210: debugfs: fix info leak in wil_write_file_wmi()
+    - wifi: p54: Fix an error handling path in p54spi_probe()
+    - wifi: p54: add missing parentheses in p54_flush()
+    - selftests/bpf: fix a test for snprintf() overflow
+    - can: pch_can: do not report txerr and rxerr during bus-off
+    - can: rcar_can: do not report txerr and rxerr during bus-off
+    - can: sja1000: do not report txerr and rxerr during bus-off
+    - can: hi311x: do not report txerr and rxerr during bus-off
+    - can: sun4i_can: do not report txerr and rxerr during bus-off
+    - can: kvaser_usb_hydra: do not report txerr and rxerr during bus-off
+    - can: kvaser_usb_leaf: do not report txerr and rxerr during bus-off
+    - can: usb_8dev: do not report txerr and rxerr during bus-off
+    - can: error: specify the values of data[5..7] of CAN error frames
+    - can: pch_can: pch_can_error(): initialize errc before using it
+    - Bluetooth: hci_intel: Add check for platform_driver_register
+    - i2c: cadence: Support PEC for SMBus block read
+    - i2c: mux-gpmux: Add of_node_put() when breaking out of loop
+    - wifi: wil6210: debugfs: fix uninitialized variable use in
+      `wil_write_file_wmi()`
+    - wifi: iwlwifi: mvm: fix double list_add at iwl_mvm_mac_wake_tx_queue
+    - wifi: libertas: Fix possible refcount leak in if_usb_probe()
+    - net/mlx5e: Fix the value of MLX5E_MAX_RQ_NUM_MTTS
+    - crypto: inside-secure - Add missing MODULE_DEVICE_TABLE for of
+    - iavf: Fix max_rate limiting
+    - netdevsim: Avoid allocation warnings triggered from user space
+    - net: rose: fix netdev reference changes
+    - dccp: put dccp_qpolicy_full() and dccp_qpolicy_push() in the same lock
+    - clk: renesas: r9a06g032: Fix UART clkgrp bitsel
+    - mtd: maps: Fix refcount leak in of_flash_probe_versatile
+    - mtd: maps: Fix refcount leak in ap_flash_init
+    - mtd: rawnand: meson: Fix a potential double free issue
+    - HID: cp2112: prevent a buffer overflow in cp2112_xfer()
+    - mtd: sm_ftl: Fix deadlock caused by cancel_work_sync in sm_release
+    - mtd: partitions: Fix refcount leak in parse_redboot_of
+    - mtd: st_spi_fsm: Add a clk_disable_unprepare() in .probe()'s error path
+    - fpga: altera-pr-ip: fix unsigned comparison with less than zero
+    - usb: host: Fix refcount leak in ehci_hcd_ppc_of_probe
+    - usb: ohci-nxp: Fix refcount leak in ohci_hcd_nxp_probe
+    - usb: xhci: tegra: Fix error check
+    - clk: mediatek: reset: Fix written reset bit offset
+    - misc: rtsx: Fix an error handling path in rtsx_pci_probe()
+    - driver core: fix potential deadlock in __driver_attach
+    - clk: qcom: clk-krait: unlock spin after mux completion
+    - usb: host: xhci: use snprintf() in xhci_decode_trb()
+    - clk: qcom: ipq8074: fix NSS port frequency tables
+    - clk: qcom: ipq8074: set BRANCH_HALT_DELAY flag for UBI clocks
+    - clk: qcom: camcc-sdm845: Fix topology around titan_top power domain
+    - soundwire: bus_type: fix remove and shutdown support
+    - intel_th: Fix a resource leak in an error handling path
+    - intel_th: msu-sink: Potential dereference of null pointer
+    - intel_th: msu: Fix vmalloced buffers
+    - staging: rtl8192u: Fix sleep in atomic context bug in
+      dm_fsync_timer_callback
+    - mmc: sdhci-of-esdhc: Fix refcount leak in esdhc_signal_voltage_switch
+    - memstick/ms_block: Fix some incorrect memory allocation
+    - memstick/ms_block: Fix a memory leak
+    - mmc: sdhci-of-at91: fix set_uhs_signaling rewriting of MC1R
+    - scsi: smartpqi: Fix DMA direction for RAID requests
+    - usb: gadget: udc: amd5536 depends on HAS_DMA
+    - RDMA/hns: Fix incorrect clearing of interrupt status register
+    - RDMA/siw: Fix duplicated reported IW_CM_EVENT_CONNECT_REPLY event
+    - RDMA/hfi1: fix potential memory leak in setup_base_ctxt()
+    - gpio: gpiolib-of: Fix refcount bugs in of_mm_gpiochip_add_data()
+    - mmc: cavium-octeon: Add of_node_put() when breaking out of loop
+    - mmc: cavium-thunderx: Add of_node_put() when breaking out of loop
+    - HID: alps: Declare U1_UNICORN_LEGACY support
+    - PCI: tegra194: Fix Root Port interrupt handling
+    - PCI: tegra194: Fix link up retry sequence
+    - USB: serial: fix tty-port initialized comments
+    - platform/olpc: Fix uninitialized data in debugfs write
+    - mm/mmap.c: fix missing call to vm_unacct_memory in mmap_region
+    - RDMA/rxe: Fix error unwind in rxe_create_qp()
+    - null_blk: fix ida error handling in null_add_dev()
+    - jbd2: fix outstanding credits assert in jbd2_journal_commit_transaction()
+    - ext4: recover csum seed of tmp_inode after migrating to extents
+    - jbd2: fix assertion 'jh->b_frozen_data == NULL' failure when journal aborted
+    - opp: Fix error check in dev_pm_opp_attach_genpd()
+    - ASoC: mediatek: mt8173: Fix refcount leak in mt8173_rt5650_rt5676_dev_probe
+    - ASoC: mt6797-mt6351: Fix refcount leak in mt6797_mt6351_dev_probe
+    - ASoC: codecs: da7210: add check for i2c_add_driver
+    - ASoC: mediatek: mt8173-rt5650: Fix refcount leak in mt8173_rt5650_dev_probe
+    - serial: 8250_dw: Store LSR into lsr_saved_flags in dw8250_tx_wait_empty()
+    - ASoC: codecs: msm8916-wcd-digital: move gains from SX_TLV to S8_TLV
+    - ASoC: codecs: wcd9335: move gains from SX_TLV to S8_TLV
+    - profiling: fix shift too large makes kernel panic
+    - tty: n_gsm: fix non flow control frames during mux flow off
+    - tty: n_gsm: fix packet re-transmission without open control channel
+    - tty: n_gsm: fix race condition in gsmld_write()
+    - remoteproc: qcom: wcnss: Fix handling of IRQs
+    - vfio/ccw: Do not change FSM state in subchannel event
+    - tty: n_gsm: fix wrong T1 retry count handling
+    - tty: n_gsm: fix DM command
+    - tty: n_gsm: fix missing corner cases in gsmld_poll()
+    - iommu/exynos: Handle failed IOMMU device registration properly
+    - rpmsg: qcom_smd: Fix refcount leak in qcom_smd_parse_edge
+    - kfifo: fix kfifo_to_user() return type
+    - mfd: t7l66xb: Drop platform disable callback
+    - mfd: max77620: Fix refcount leak in max77620_initialise_fps
+    - iommu/arm-smmu: qcom_iommu: Add of_node_put() when breaking out of loop
+    - s390/zcore: fix race when reading from hardware system area
+    - ASoC: qcom: q6dsp: Fix an off-by-one in q6adm_alloc_copp()
+    - fuse: Remove the control interface for virtio-fs
+    - ASoC: audio-graph-card: Add of_node_put() in fail path
+    - watchdog: armada_37xx_wdt: check the return value of devm_ioremap() in
+      armada_37xx_wdt_probe()
+    - video: fbdev: amba-clcd: Fix refcount leak bugs
+    - video: fbdev: sis: fix typos in SiS_GetModeID()
+    - powerpc/32: Do not allow selection of e5500 or e6500 CPUs on PPC32
+    - powerpc/pci: Prefer PCI domain assignment via DT 'linux,pci-domain' and
+      alias
+    - powerpc/spufs: Fix refcount leak in spufs_init_isolated_loader
+    - powerpc/xive: Fix refcount leak in xive_get_max_prio
+    - powerpc/cell/axon_msi: Fix refcount leak in setup_msi_msg_address
+    - perf symbol: Fail to read phdr workaround
+    - kprobes: Forbid probing on trampoline and BPF code areas
+    - powerpc/pci: Fix PHB numbering when using opal-phbid
+    - genelf: Use HAVE_LIBCRYPTO_SUPPORT, not the never defined HAVE_LIBCRYPTO
+    - scripts/faddr2line: Fix vmlinux detection on arm64
+    - x86/numa: Use cpumask_available instead of hardcoded NULL check
+    - video: fbdev: arkfb: Fix a divide-by-zero bug in ark_set_pixclock()
+    - tools/thermal: Fix possible path truncations
+    - video: fbdev: vt8623fb: Check the size of screen before memset_io()
+    - video: fbdev: arkfb: Check the size of screen before memset_io()
+    - video: fbdev: s3fb: Check the size of screen before memset_io()
+    - scsi: zfcp: Fix missing auto port scan and thus missing target ports
+    - scsi: qla2xxx: Fix discovery issues in FC-AL topology
+    - scsi: qla2xxx: Turn off multi-queue for 8G adapters
+    - scsi: qla2xxx: Fix erroneous mailbox timeout after PCI error injection
+    - x86/olpc: fix 'logical not is only applied to the left hand side'
+    - spmi: trace: fix stack-out-of-bound access in SPMI tracing functions
+    - kexec, KEYS, s390: Make use of built-in and secondary keyring for signature
+      verification
+    - tpm: eventlog: Fix section mismatch for DEBUG_SECTION_MISMATCH
+    - btrfs: reset block group chunk force if we have to wait
+    - ext4: add EXT4_INODE_HAS_XATTR_SPACE macro in xattr.h
+    - ext4: make sure ext4_append() always allocates new block
+    - ext4: fix use-after-free in ext4_xattr_set_entry
+    - ext4: update s_overhead_clusters in the superblock during an on-line resize
+    - ext4: fix extent status tree race in writeback error recovery path
+    - ext4: correct max_inline_xattr_value_size computing
+    - ext4: correct the misjudgment in ext4_iget_extra_inode
+    - intel_th: pci: Add Raptor Lake-S CPU support
+    - intel_th: pci: Add Raptor Lake-S PCH support
+    - intel_th: pci: Add Meteor Lake-P support
+    - dm raid: fix address sanitizer warning in raid_resume
+    - dm raid: fix address sanitizer warning in raid_status
+    - dm thin: fix use-after-free crash in dm_sm_register_threshold_callback
+    - dm writecache: set a default MAX_WRITEBACK_JOBS
+    - ACPI: CPPC: Do not prevent CPPC from working in the future
+    - timekeeping: contribute wall clock to rng on time change
+    - firmware: arm_scpi: Ensure scpi_info is not assigned if the probe fails
+    - iommu/vt-d: avoid invalid memory access via node_online(NUMA_NO_NODE)
+    - btrfs: reject log replay if there is unsupported RO compat flag
+    - KVM: Add infrastructure and macro to mark VM as bugged
+    - KVM: x86: Check lapic_in_kernel() before attempting to set a SynIC irq
+    - KVM: x86: Avoid theoretical NULL pointer dereference in
+      kvm_irq_delivery_to_apic_fast()
+    - tcp: fix over estimation in sk_forced_mem_schedule()
+    - scsi: sg: Allow waiting for commands to complete on removed device
+    - Bluetooth: L2CAP: Fix l2cap_global_chan_by_psm regression
+    - net/9p: Initialize the iounit field during fid creation
+    - net_sched: cls_route: disallow handle of 0
+    - ALSA: info: Fix llseek return value when using callback
+    - rds: add missing barrier to release_refill
+    - ata: libata-eh: Add missing command name
+    - mmc: pxamci: Fix another error handling path in pxamci_probe()
+    - mmc: pxamci: Fix an error handling path in pxamci_probe()
+    - btrfs: fix lost error handling when looking up extended ref on log replay
+    - tracing: Have filter accept "common_cpu" to be consistent
+    - can: ems_usb: fix clang's -Wunaligned-access warning
+    - apparmor: fix quiet_denied for file rules
+    - apparmor: fix absroot causing audited secids to begin with =
+    - apparmor: Fix failed mount permission check error message
+    - apparmor: fix aa_label_asxprint return check
+    - apparmor: fix overlapping attachment computation
+    - apparmor: fix reference count leak in aa_pivotroot()
+    - apparmor: Fix memleak in aa_simple_write_to_buffer()
+    - Documentation: ACPI: EINJ: Fix obsolete example
+    - NFSv4.1: Don't decrease the value of seq_nr_highest_sent
+    - NFSv4.1: Handle NFS4ERR_DELAY replies to OP_SEQUENCE correctly
+    - NFSv4: Fix races in the legacy idmapper upcall
+    - NFSv4.1: RECLAIM_COMPLETE must handle EACCES
+    - NFSv4/pnfs: Fix a use-after-free bug in open
+    - can: mcp251x: Fix race condition on receive interrupt
+    - sunrpc: fix expiry of auth creds
+    - SUNRPC: Reinitialise the backchannel request buffers before reuse
+    - devlink: Fix use-after-free after a failed reload
+    - net: bgmac: Fix a BUG triggered by wrong bytes_compl
+    - pinctrl: nomadik: Fix refcount leak in nmk_pinctrl_dt_subnode_to_map
+    - pinctrl: qcom: msm8916: Allow CAMSS GP clocks to be muxed
+    - pinctrl: sunxi: Add I/O bias setting for H6 R-PIO
+    - ACPI: property: Return type of acpi_add_nondev_subnodes() should be bool
+    - geneve: do not use RT_TOS for IPv6 flowlabel
+    - plip: avoid rcu debug splat
+    - vsock: Fix memory leak in vsock_connect()
+    - vsock: Set socket state back to SS_UNCONNECTED in vsock_connect_timeout()
+    - dt-bindings: arm: qcom: fix MSM8916 MTP compatibles
+    - tools/vm/slabinfo: use alphabetic order when two values are equal
+    - tools build: Switch to new openssl API for test-libcrypto
+    - NTB: ntb_tool: uninitialized heap data in tool_fn_write()
+    - nfp: ethtool: fix the display error of `ethtool -m DEVNAME`
+    - xen/xenbus: fix return type in xenbus_file_read()
+    - atm: idt77252: fix use-after-free bugs caused by tst_timer
+    - dpaa2-eth: trace the allocated address instead of page struct
+    - tee: add overflow check in register_shm_helper()
+    - nios2: page fault et.al. are *not* restartable syscalls...
+    - nios2: don't leave NULLs in sys_call_table[]
+    - nios2: traced syscall does need to check the syscall number
+    - nios2: fix syscall restart checks
+    - nios2: restarts apply only to the first sigframe we build...
+    - nios2: add force_successful_syscall_return()
+    - iavf: Fix adminq error handling
+    - clk: rockchip: add sclk_mac_lbtest to rk3188_critical_clocks
+    - netfilter: nf_tables: really skip inactive sets when allocating name
+    - powerpc/pci: Fix get_phb_number() locking
+    - net: dsa: mv88e6060: prevent crash on an unused port
+    - net: moxa: pass pdev instead of ndev to DMA functions
+    - net: dsa: microchip: ksz9477: fix fdb_dump last invalid entry
+    - ice: Ignore EEXIST when setting promisc mode
+    - i40e: Fix to stop tx_timeout recovery if GLOBR fails
+    - fec: Fix timer capture timing in `fec_ptp_enable_pps()`
+    - igb: Add lock to avoid data race
+    - gcc-plugins: Undefine LATENT_ENTROPY_PLUGIN when plugin disabled for a file
+    - locking/atomic: Make test_and_*_bit() ordered on failure
+    - drm/meson: Fix refcount bugs in meson_vpu_has_available_connectors()
+    - PCI: Add ACS quirk for Broadcom BCM5750x NICs
+    - usb: cdns3 fix use-after-free at workaround 2
+    - usb: gadget: uvc: call uvc uvcg_warn on completed status instead of
+      uvcg_info
+    - irqchip/tegra: Fix overflow implicit truncation warnings
+    - drm/meson: Fix overflow implicit truncation warnings
+    - usb: host: ohci-ppc-of: Fix refcount leak bug
+    - usb: renesas: Fix refcount leak bug
+    - vboxguest: Do not use devm for irq
+    - clk: qcom: ipq8074: dont disable gcc_sleep_clk_src
+    - scsi: lpfc: Prevent buffer overflow crashes in debugfs with malformed user
+      input
+    - gadgetfs: ep_io - wait until IRQ finishes
+    - cxl: Fix a memory leak in an error handling path
+    - PCI/ACPI: Guard ARM64-specific mcfg_quirks
+    - um: add "noreboot" command line option for PANIC_TIMEOUT=-1 setups
+    - selftests/kprobe: Do not test for GRP/ without event failures
+    - dmaengine: sprd: Cleanup in .remove() after pm_runtime_get_sync() failed
+    - nvmet-tcp: fix lockdep complaint on nvmet_tcp_wq flush during queue teardown
+    - drivers:md:fix a potential use-after-free bug
+    - ext4: avoid remove directory when directory is corrupted
+    - ext4: avoid resizing to a partial cluster size
+    - lib/list_debug.c: Detect uninitialized lists
+    - tty: serial: Fix refcount leak bug in ucc_uart.c
+    - vfio: Clear the caps->buf to NULL after free
+    - mips: cavium-octeon: Fix missing of_node_put() in octeon2_usb_clocks_start
+    - riscv: mmap with PROT_WRITE but no PROT_READ is invalid
+    - RISC-V: Add fast call path of crash_kexec()
+    - watchdog: export lockup_detector_reconfigure
+    - powerpc/32: Don't always pass -mcpu=powerpc to the compiler
+    - ALSA: core: Add async signal helpers
+    - ALSA: timer: Use deferred fasync helper
+    - f2fs: fix to avoid use f2fs_bug_on() in f2fs_new_node_page()
+    - smb3: check xattr value length earlier
+    - powerpc/64: Init jump labels before parse_early_param()
+    - video: fbdev: i740fb: Check the argument of i740_calc_vclk()
+    - MIPS: tlbex: Explicitly compare _PAGE_NO_EXEC against 0
+    - tracing/probes: Have kprobes and uprobes use $COMM too
+    - can: j1939: j1939_sk_queue_activate_next_locked(): replace WARN_ON_ONCE with
+      netdev_warn_once()
+    - can: j1939: j1939_session_destroy(): fix memory leak of skbs
+    - btrfs: only write the sectors in the vertical stripe which has data stripes
+    - btrfs: raid56: don't trust any cached sector in __raid56_parity_recover()
+    - Linux 5.4.211
+  * CVE-2022-3028
+    - af_key: Do not call xfrm_probe_algs in parallel
+  * CVE-2022-2978
+    - fs: fix UAF/GPF bug in nilfs_mdt_destroy
+  * CVE-2022-40768
+    - scsi: stex: Properly zero out the passthrough command structure
+
+  [ Ubuntu: 5.4.0-131.147 ]
+
+  * CVE-2022-2602
+    - SAUCE: io_uring/af_unix: defer registered files gc to io_uring release
+    - SAUCE: io_uring/af_unix: fix memleak during unix GC
+  * CVE-2022-41674
+    - SAUCE: wifi: cfg80211: fix u8 overflow in
+      cfg80211_update_notlisted_nontrans()
+    - SAUCE: wifi: cfg80211/mac80211: reject bad MBSSID elements
+    - SAUCE: wifi: cfg80211: ensure length byte is present before access
+    - SAUCE: wifi: mac80211_hwsim: avoid mac80211 warning on bad rate
+    - SAUCE: wifi: cfg80211: update hidden BSSes to avoid WARN_ON
+  * CVE-2022-42721
+    - SAUCE: wifi: cfg80211: avoid nontransmitted BSS list corruption
+  * CVE-2022-42720
+    - SAUCE: wifi: cfg80211: fix BSS refcounting bugs
+
+  [ Ubuntu: 5.4.0-128.144 ]
+
+  * focal/linux: 5.4.0-128.144 -proposed tracker (LP: #1990152)
+  * CVE-2022-3176
+    - io_uring: disable polling pollfree files
+  * ip/nexthop: fix default address selection for connected nexthop
+    (LP: #1988809)
+    - selftests/net: test nexthop without gw
+  * ip/nexthop: fix default address selection for connected nexthop
+    (LP: #1988809) // icmp_redirect.sh in ubuntu_kernel_selftests failed on
+    Jammy 5.15.0-49.55 (LP: #1990124)
+    - ip: fix triggering of 'icmp redirect'
+
+  [ Ubuntu: 5.4.0-127.143 ]
+
+  * focal/linux: 5.4.0-127.143 -proposed tracker (LP: #1989892)
+  * Packaging resync (LP: #1786013)
+    - debian/dkms-versions -- update from kernel-versions (main/2022.09.19)
+  * [UBUNTU 20.04] mlx5 driver crashes on accessing device attributes during
+    recovery (LP: #1987287)
+    - net/mlx5: Avoid processing commands before cmdif is ready
+  * Focal update: v5.4.210 upstream stable release (LP: #1989230)
+    - thermal: Fix NULL pointer dereferences in of_thermal_ functions
+    - ACPI: video: Force backlight native for some TongFang devices
+    - ACPI: video: Shortening quirk list by identifying Clevo by board_name only
+    - ACPI: APEI: Better fix to avoid spamming the console with old error logs
+    - bpf: Verifer, adjust_scalar_min_max_vals to always call update_reg_bounds()
+    - selftests/bpf: Extend verifier and bpf_sock tests for dst_port loads
+    - bpf: Test_verifier, #70 error message updates for 32-bit right shift
+    - KVM: Don't null dereference ops->destroy
+    - selftests: KVM: Handle compiler optimizations in ucall
+    - media: v4l2-mem2mem: Apply DST_QUEUE_OFF_BASE on MMAP buffers across ioctls
+    - macintosh/adb: fix oob read in do_adb_query() function
+    - x86/speculation: Add RSB VM Exit protections
+    - x86/speculation: Add LFENCE to RSB fill sequence
+    - Linux 5.4.210
+  * Focal update: v5.4.209 upstream stable release (LP: #1989228)
+    - Bluetooth: L2CAP: Fix use-after-free caused by l2cap_chan_put
+    - ntfs: fix use-after-free in ntfs_ucsncmp()
+    - s390/archrandom: prevent CPACF trng invocations in interrupt context
+    - tcp: Fix data-races around sysctl_tcp_dsack.
+    - tcp: Fix a data-race around sysctl_tcp_app_win.
+    - tcp: Fix a data-race around sysctl_tcp_adv_win_scale.
+    - tcp: Fix a data-race around sysctl_tcp_frto.
+    - tcp: Fix a data-race around sysctl_tcp_nometrics_save.
+    - ice: check (DD | EOF) bits on Rx descriptor rather than (EOP | RS)
+    - ice: do not setup vlan for loopback VSI
+    - scsi: ufs: host: Hold reference returned by of_parse_phandle()
+    - tcp: Fix a data-race around sysctl_tcp_limit_output_bytes.
+    - tcp: Fix a data-race around sysctl_tcp_challenge_ack_limit.
+    - net: ping6: Fix memleak in ipv6_renew_options().
+    - ipv6/addrconf: fix a null-ptr-deref bug for ip6_ptr
+    - igmp: Fix data-races around sysctl_igmp_qrv.
+    - net: sungem_phy: Add of_node_put() for reference returned by of_get_parent()
+    - tcp: Fix a data-race around sysctl_tcp_min_tso_segs.
+    - tcp: Fix a data-race around sysctl_tcp_min_rtt_wlen.
+    - tcp: Fix a data-race around sysctl_tcp_autocorking.
+    - tcp: Fix a data-race around sysctl_tcp_invalid_ratelimit.
+    - Documentation: fix sctp_wmem in ip-sysctl.rst
+    - tcp: Fix a data-race around sysctl_tcp_comp_sack_delay_ns.
+    - tcp: Fix a data-race around sysctl_tcp_comp_sack_nr.
+    - i40e: Fix interface init with MSI interrupts (no MSI-X)
+    - sctp: fix sleep in atomic context bug in timer handlers
+    - virtio-net: fix the race between refill work and close
+    - perf symbol: Correct address for bss symbols
+    - sfc: disable softirqs for ptp TX
+    - sctp: leave the err path free in sctp_stream_init to sctp_stream_free
+    - ARM: crypto: comment out gcc warning that breaks clang builds
+    - mt7601u: add USB device ID for some versions of XiaoDu WiFi Dongle.
+    - scsi: core: Fix race between handling STS_RESOURCE and completion
+    - Linux 5.4.209
+  * Focal update: v5.4.208 upstream stable release (LP: #1988225)
+    - pinctrl: stm32: fix optional IRQ support to gpios
+    - riscv: add as-options for modules with assembly compontents
+    - mlxsw: spectrum_router: Fix IPv4 nexthop gateway indication
+    - lockdown: Fix kexec lockdown bypass with ima policy
+    - xen/gntdev: Ignore failure to unmap INVALID_GRANT_HANDLE
+    - PCI: hv: Fix multi-MSI to allow more than one MSI vector
+    - PCI: hv: Fix hv_arch_irq_unmask() for multi-MSI
+    - PCI: hv: Reuse existing IRTE allocation in compose_msi_msg()
+    - PCI: hv: Fix interrupt mapping for multi-MSI
+    - serial: mvebu-uart: correctly report configured baudrate value
+    - xfrm: xfrm_policy: fix a possible double xfrm_pols_put() in
+      xfrm_bundle_lookup()
+    - power/reset: arm-versatile: Fix refcount leak in versatile_reboot_probe
+    - pinctrl: ralink: Check for null return of devm_kcalloc
+    - perf/core: Fix data race between perf_event_set_output() and
+      perf_mmap_close()
+    - igc: Reinstate IGC_REMOVED logic and implement it properly
+    - ip: Fix data-races around sysctl_ip_no_pmtu_disc.
+    - ip: Fix data-races around sysctl_ip_fwd_use_pmtu.
+    - ip: Fix data-races around sysctl_ip_nonlocal_bind.
+    - ip: Fix a data-race around sysctl_fwmark_reflect.
+    - tcp/dccp: Fix a data-race around sysctl_tcp_fwmark_accept.
+    - tcp: Fix data-races around sysctl_tcp_mtu_probing.
+    - tcp: Fix data-races around sysctl_tcp_base_mss.
+    - tcp: Fix data-races around sysctl_tcp_min_snd_mss.
+    - tcp: Fix a data-race around sysctl_tcp_mtu_probe_floor.
+    - tcp: Fix a data-race around sysctl_tcp_probe_threshold.
+    - tcp: Fix a data-race around sysctl_tcp_probe_interval.
+    - i2c: cadence: Change large transfer count reset logic to be unconditional
+    - net: stmmac: fix dma queue left shift overflow issue
+    - net/tls: Fix race in TLS device down flow
+    - igmp: Fix data-races around sysctl_igmp_llm_reports.
+    - igmp: Fix a data-race around sysctl_igmp_max_memberships.
+    - tcp: Fix data-races around sysctl_tcp_syncookies.
+    - tcp: Fix data-races around sysctl_tcp_reordering.
+    - tcp: Fix data-races around some timeout sysctl knobs.
+    - tcp: Fix a data-race around sysctl_tcp_notsent_lowat.
+    - tcp: Fix a data-race around sysctl_tcp_tw_reuse.
+    - tcp: Fix data-races around sysctl_max_syn_backlog.
+    - tcp: Fix data-races around sysctl_tcp_fastopen.
+    - iavf: Fix handling of dummy receive descriptors
+    - i40e: Fix erroneous adapter reinitialization during recovery process
+    - ixgbe: Add locking to prevent panic when setting sriov_numvfs to zero
+    - gpio: pca953x: only use single read/write for No AI mode
+    - be2net: Fix buffer overflow in be_get_module_eeprom
+    - ipv4: Fix a data-race around sysctl_fib_multipath_use_neigh.
+    - udp: Fix a data-race around sysctl_udp_l3mdev_accept.
+    - tcp: Fix data-races around sysctl knobs related to SYN option.
+    - tcp: Fix a data-race around sysctl_tcp_early_retrans.
+    - tcp: Fix data-races around sysctl_tcp_recovery.
+    - tcp: Fix a data-race around sysctl_tcp_thin_linear_timeouts.
+    - tcp: Fix data-races around sysctl_tcp_slow_start_after_idle.
+    - tcp: Fix a data-race around sysctl_tcp_retrans_collapse.
+    - tcp: Fix a data-race around sysctl_tcp_stdurg.
+    - tcp: Fix a data-race around sysctl_tcp_rfc1337.
+    - tcp: Fix data-races around sysctl_tcp_max_reordering.
+    - spi: bcm2835: bcm2835_spi_handle_err(): fix NULL pointer deref for non DMA
+      transfers
+    - mm/mempolicy: fix uninit-value in mpol_rebind_policy()
+    - bpf: Make sure mac_header was set before using it
+    - dlm: fix pending remove if msg allocation fails
+    - ima: remove the IMA_TEMPLATE Kconfig option
+    - [Config] updateconfigs for IMA_TEMPLATE
+    - locking/refcount: Define constants for saturation and max refcount values
+    - locking/refcount: Ensure integer operands are treated as signed
+    - locking/refcount: Remove unused refcount_*_checked() variants
+    - locking/refcount: Move the bulk of the REFCOUNT_FULL implementation into the
+      <linux/refcount.h> header
+    - locking/refcount: Improve performance of generic REFCOUNT_FULL code
+    - locking/refcount: Move saturation warnings out of line
+    - locking/refcount: Consolidate REFCOUNT_{MAX,SATURATED} definitions
+    - locking/refcount: Consolidate implementations of refcount_t
+    - [Config] updateconfigs for REFCOUNT_FULL
+    - x86: get rid of small constant size cases in raw_copy_{to,from}_user()
+    - x86/uaccess: Implement macros for CMPXCHG on user addresses
+    - mmap locking API: initial implementation as rwsem wrappers
+    - x86/mce: Deduplicate exception handling
+    - bitfield.h: Fix "type of reg too small for mask" test
+    - ALSA: memalloc: Align buffer allocations in page size
+    - Bluetooth: Add bt_skb_sendmsg helper
+    - Bluetooth: Add bt_skb_sendmmsg helper
+    - Bluetooth: SCO: Replace use of memcpy_from_msg with bt_skb_sendmsg
+    - Bluetooth: RFCOMM: Replace use of memcpy_from_msg with bt_skb_sendmmsg
+    - Bluetooth: Fix passing NULL to PTR_ERR
+    - Bluetooth: SCO: Fix sco_send_frame returning skb->len
+    - Bluetooth: Fix bt_skb_sendmmsg not allocating partial chunks
+    - tty: drivers/tty/, stop using tty_schedule_flip()
+    - tty: the rest, stop using tty_schedule_flip()
+    - tty: drop tty_schedule_flip()
+    - tty: extract tty_flip_buffer_commit() from tty_flip_buffer_push()
+    - tty: use new tty_insert_flip_string_and_push_buffer() in pty_write()
+    - x86: drop bogus "cc" clobber from __try_cmpxchg_user_asm()
+    - Linux 5.4.208
+  * Focal update: v5.4.207 upstream stable release (LP: #1988219)
+    - ALSA: hda - Add fixup for Dell Latitidue E5430
+    - ALSA: hda/conexant: Apply quirk for another HP ProDesk 600 G3 model
+    - ALSA: hda/realtek - Fix headset mic problem for a HP machine with alc671
+    - ALSA: hda/realtek - Fix headset mic problem for a HP machine with alc221
+    - ALSA: hda/realtek - Enable the headset-mic on a Xiaomi's laptop
+    - xen/netback: avoid entering xenvif_rx_next_skb() with an empty rx queue
+    - tracing/histograms: Fix memory leak problem
+    - net: sock: tracing: Fix sock_exceed_buf_limit not to dereference stale
+      pointer
+    - ip: fix dflt addr selection for connected nexthop
+    - ARM: 9213/1: Print message about disabled Spectre workarounds only once
+    - ARM: 9214/1: alignment: advance IT state after emulating Thumb instruction
+    - wifi: mac80211: fix queue selection for mesh/OCB interfaces
+    - cgroup: Use separate src/dst nodes when preloading css_sets for migration
+    - drm/panfrost: Fix shrinker list corruption by madvise IOCTL
+    - nilfs2: fix incorrect masking of permission flags for symlinks
+    - Revert "evm: Fix memleak in init_desc"
+    - sched/rt: Disable RT_RUNTIME_SHARE by default
+    - ext4: fix race condition between ext4_write and ext4_convert_inline_data
+    - ARM: dts: imx6qdl-ts7970: Fix ngpio typo and count
+    - ARM: 9209/1: Spectre-BHB: avoid pr_info() every time a CPU comes out of idle
+    - ARM: 9210/1: Mark the FDT_FIXED sections as shareable
+    - drm/i915: fix a possible refcount leak in intel_dp_add_mst_connector()
+    - ima: Fix a potential integer overflow in ima_appraise_measurement
+    - ASoC: sgtl5000: Fix noise on shutdown/remove
+    - net: stmmac: dwc-qos: Disable split header for Tegra194
+    - inetpeer: Fix data-races around sysctl.
+    - net: Fix data-races around sysctl_mem.
+    - cipso: Fix data-races around sysctl.
+    - icmp: Fix data-races around sysctl.
+    - ipv4: Fix a data-race around sysctl_fib_sync_mem.
+    - ARM: dts: at91: sama5d2: Fix typo in i2s1 node
+    - ARM: dts: sunxi: Fix SPI NOR campatible on Orange Pi Zero
+    - drm/i915/gt: Serialize TLB invalidates with GT resets
+    - icmp: Fix a data-race around sysctl_icmp_ratelimit.
+    - icmp: Fix a data-race around sysctl_icmp_ratemask.
+    - raw: Fix a data-race around sysctl_raw_l3mdev_accept.
+    - ipv4: Fix data-races around sysctl_ip_dynaddr.
+    - net: ftgmac100: Hold reference returned by of_get_child_by_name()
+    - sfc: fix use after free when disabling sriov
+    - seg6: fix skb checksum evaluation in SRH encapsulation/insertion
+    - seg6: fix skb checksum in SRv6 End.B6 and End.B6.Encaps behaviors
+    - seg6: bpf: fix skb checksum in bpf_push_seg6_encap()
+    - sfc: fix kernel panic when creating VF
+    - mm: sysctl: fix missing numa_stat when !CONFIG_HUGETLB_PAGE
+    - virtio_mmio: Add missing PM calls to freeze/restore
+    - virtio_mmio: Restore guest page size on resume
+    - netfilter: br_netfilter: do not skip all hooks with 0 priority
+    - cpufreq: pmac32-cpufreq: Fix refcount leak bug
+    - platform/x86: hp-wmi: Ignore Sanitization Mode event
+    - net: tipc: fix possible refcount leak in tipc_sk_create()
+    - NFC: nxp-nci: don't print header length mismatch on i2c error
+    - nvme: fix regression when disconnect a recovering ctrl
+    - net: sfp: fix memory leak in sfp_probe()
+    - ASoC: ops: Fix off by one in range control validation
+    - ASoC: wm5110: Fix DRE control
+    - ASoC: cs47l15: Fix event generation for low power mux control
+    - ASoC: madera: Fix event generation for OUT1 demux
+    - ASoC: madera: Fix event generation for rate controls
+    - irqchip: or1k-pic: Undefine mask_ack for level triggered hardware
+    - x86: Clear .brk area at early boot
+    - soc: ixp4xx/npe: Fix unused match warning
+    - ARM: dts: stm32: use the correct clock source for CEC on stm32mp151
+    - signal handling: don't use BUG_ON() for debugging
+    - USB: serial: ftdi_sio: add Belimo device ids
+    - usb: typec: add missing uevent when partner support PD
+    - usb: dwc3: gadget: Fix event pending check
+    - tty: serial: samsung_tty: set dma burst_size to 1
+    - serial: 8250: fix return error code in serial8250_request_std_resource()
+    - serial: stm32: Clear prev values before setting RTS delays
+    - serial: pl011: UPSTAT_AUTORTS requires .throttle/unthrottle
+    - can: m_can: m_can_tx_handler(): fix use after free of skb
+    - Linux 5.4.207
+  * Focal update: v5.4.206 upstream stable release (LP: #1988215)
+    - Linux 5.4.206
+  * Focal update: v5.4.205 upstream stable release (LP: #1988214)
+    - esp: limit skb_page_frag_refill use to a single page
+    - mm/slub: add missing TID updates on slab deactivation
+    - can: bcm: use call_rcu() instead of costly synchronize_rcu()
+    - can: grcan: grcan_probe(): remove extra of_node_get()
+    - can: gs_usb: gs_usb_open/close(): fix memory leak
+    - usbnet: fix memory leak in error case
+    - net: rose: fix UAF bug caused by rose_t0timer_expiry
+    - iommu/vt-d: Fix PCI bus rescan device hot add
+    - fbdev: fbmem: Fix logo center image dx issue
+    - video: of_display_timing.h: include errno.h
+    - powerpc/powernv: delay rng platform device creation until later in boot
+    - can: kvaser_usb: replace run-time checks with struct kvaser_usb_driver_info
+    - can: kvaser_usb: kvaser_usb_leaf: fix CAN clock frequency regression
+    - can: kvaser_usb: kvaser_usb_leaf: fix bittiming limits
+    - xfs: remove incorrect ASSERT in xfs_rename
+    - ARM: meson: Fix refcount leak in meson_smp_prepare_cpus
+    - pinctrl: sunxi: a83t: Fix NAND function name for some pins
+    - pinctrl: sunxi: sunxi_pconf_set: use correct offset
+    - ARM: at91: pm: use proper compatible for sama5d2's rtc
+    - ARM: at91: pm: use proper compatibles for sam9x60's rtc and rtt
+    - ibmvnic: Properly dispose of all skbs during a failover.
+    - selftests: forwarding: fix flood_unicast_test when h2 supports
+      IFF_UNICAST_FLT
+    - selftests: forwarding: fix learning_test when h1 supports IFF_UNICAST_FLT
+    - selftests: forwarding: fix error message in learning_test
+    - i2c: cadence: Unregister the clk notifier in error path
+    - dmaengine: imx-sdma: Allow imx8m for imx7 FW revs
+    - misc: rtsx_usb: fix use of dma mapped buffer for usb bulk transfer
+    - misc: rtsx_usb: use separate command and response buffers
+    - misc: rtsx_usb: set return value in rsp_buf alloc err path
+    - dt-bindings: dma: allwinner,sun50i-a64-dma: Fix min/max typo
+    - ida: don't use BUG_ON() for debugging
+    - dmaengine: pl330: Fix lockdep warning about non-static key
+    - dmaengine: at_xdma: handle errors of at_xdmac_alloc_desc() correctly
+    - dmaengine: ti: Fix refcount leak in ti_dra7_xbar_route_allocate
+    - dmaengine: ti: Add missing put_device in ti_dra7_xbar_route_allocate
+    - Linux 5.4.205
+  * Focal update: v5.4.204 upstream stable release (LP: #1988212)
+    - ipv6: take care of disable_policy when restoring routes
+    - nvdimm: Fix badblocks clear off-by-one error
+    - powerpc/prom_init: Fix kernel config grep
+    - powerpc/bpf: Fix use of user_pt_regs in uapi
+    - dm raid: fix accesses beyond end of raid member array
+    - dm raid: fix KASAN warning in raid5_add_disks
+    - s390/archrandom: simplify back to earlier design and initialize earlier
+    - SUNRPC: Fix READ_PLUS crasher
+    - net: rose: fix UAF bugs caused by timer handler
+    - net: usb: ax88179_178a: Fix packet receiving
+    - virtio-net: fix race between ndo_open() and virtio_device_ready()
+    - selftests/net: pass ipv6_args to udpgso_bench's IPv6 TCP test
+    - net: tun: unlink NAPI from device on destruction
+    - net: tun: stop NAPI when detaching queues
+    - RDMA/qedr: Fix reporting QP timeout attribute
+    - linux/dim: Fix divide by 0 in RDMA DIM
+    - usbnet: fix memory allocation in helpers
+    - net: ipv6: unexport __init-annotated seg6_hmac_net_init()
+    - caif_virtio: fix race between virtio_device_ready() and ndo_open()
+    - PM / devfreq: exynos-ppmu: Fix refcount leak in of_get_devfreq_events
+    - s390: remove unneeded 'select BUILD_BIN2C'
+    - netfilter: nft_dynset: restore set element counter when failing to update
+    - net/sched: act_api: Notify user space if any actions were flushed before
+      error
+    - net: bonding: fix possible NULL deref in rlb code
+    - net: bonding: fix use-after-free after 802.3ad slave unbind
+    - nfc: nfcmrvl: Fix irq_of_parse_and_map() return value
+    - NFC: nxp-nci: Don't issue a zero length i2c_master_read()
+    - net: tun: avoid disabling NAPI twice
+    - xen/gntdev: Avoid blocking in unmap_grant_pages()
+    - hwmon: (ibmaem) don't call platform_device_del() if platform_device_add()
+      fails
+    - net: dsa: bcm_sf2: force pause link settings
+    - sit: use min
+    - ipv6/sit: fix ipip6_tunnel_get_prl return value
+    - rseq/selftests,x86_64: Add rseq_offset_deref_addv()
+    - selftests/rseq: remove ARRAY_SIZE define from individual tests
+    - selftests/rseq: introduce own copy of rseq uapi header
+    - selftests/rseq: Remove useless assignment to cpu variable
+    - selftests/rseq: Remove volatile from __rseq_abi
+    - selftests/rseq: Introduce rseq_get_abi() helper
+    - selftests/rseq: Introduce thread pointer getters
+    - selftests/rseq: Uplift rseq selftests for compatibility with glibc-2.35
+    - selftests/rseq: Fix ppc32: wrong rseq_cs 32-bit field pointer on big endian
+    - selftests/rseq: Fix ppc32 missing instruction selection "u" and "x" for
+      load/store
+    - selftests/rseq: Fix ppc32 offsets by using long rather than off_t
+    - selftests/rseq: Fix warnings about #if checks of undefined tokens
+    - selftests/rseq: Remove arm/mips asm goto compiler work-around
+    - selftests/rseq: Fix: work-around asm goto compiler bugs
+    - selftests/rseq: x86-64: use %fs segment selector for accessing rseq thread
+      area
+    - selftests/rseq: x86-32: use %gs segment selector for accessing rseq thread
+      area
+    - selftests/rseq: Change type of rseq_offset to ptrdiff_t
+    - xen/blkfront: fix leaking data in shared pages
+    - xen/netfront: fix leaking data in shared pages
+    - xen/netfront: force data bouncing when backend is untrusted
+    - xen/blkfront: force data bouncing when backend is untrusted
+    - xen/arm: Fix race in RB-tree based P2M accounting
+    - net: usb: qmi_wwan: add Telit 0x1060 composition
+    - net: usb: qmi_wwan: add Telit 0x1070 composition
+    - clocksource/drivers/ixp4xx: remove EXPORT_SYMBOL_GPL from
+      ixp4xx_timer_setup()
+    - Linux 5.4.204
+
+  [ Ubuntu: 5.4.0-126.142 ]
+
+  * focal/linux: 5.4.0-126.142 -proposed tracker (LP: #1987819)
+  * [SRU] fnic driver on needs to be updated to 1.6.0.53 on Focal (LP: #1984011)
+    - scsi: fnic: Change shost_printk() to FNIC_FCS_DBG()
+    - scsi: fnic: Avoid looping in TRANS ETH on unload
+    - scsi: fnic: Change shost_printk() to FNIC_MAIN_DBG()
+    - scsi: fnic: Set scsi_set_resid() only for underflow
+    - scsi: fnic: Validate io_req before others
+  * Focal update: v5.4.203 upstream stable release (LP: #1986999)
+    - drm: remove drm_fb_helper_modinit
+    - powerpc/ftrace: Remove ftrace init tramp once kernel init is complete
+    - kexec_file: drop weak attribute from arch_kexec_apply_relocations[_add]
+    - net: mscc: ocelot: allow unregistered IP multicast flooding
+    - ARM: 8989/1: use .fpu assembler directives instead of assembler arguments
+    - ARM: 8990/1: use VFP assembler mnemonics in register load/store macros
+    - ARM: 8971/1: replace the sole use of a symbol with its definition
+    - crypto: arm/sha256-neon - avoid ADRL pseudo instruction
+    - crypto: arm/sha512-neon - avoid ADRL pseudo instruction
+    - ARM: 8933/1: replace Sun/Solaris style flag on section directive
+    - ARM: 8929/1: use APSR_nzcv instead of r15 as mrc operand
+    - ARM: OMAP2+: drop unnecessary adrl
+    - ARM: 9029/1: Make iwmmxt.S support Clang's integrated assembler
+    - crypto: arm - use Kconfig based compiler checks for crypto opcodes
+    - crypto: arm/ghash-ce - define fpu before fpu registers are referenced
+    - Linux 5.4.203
+  * Focal update: v5.4.202 upstream stable release (LP: #1986995)
+    - random: schedule mix_interrupt_randomness() less often
+    - ALSA: hda/via: Fix missing beep setup
+    - ALSA: hda/conexant: Fix missing beep setup
+    - ALSA: hda/realtek - ALC897 headset MIC no sound
+    - ALSA: hda/realtek: Add quirk for Clevo PD70PNT
+    - net: openvswitch: fix parsing of nw_proto for IPv6 fragments
+    - mmc: sdhci-pci-o2micro: Fix card detect by dealing with debouncing
+    - ata: libata: add qc->flags in ata_qc_complete_template tracepoint
+    - dm era: commit metadata in postsuspend after worker stops
+    - dm mirror log: clear log bits up to BITS_PER_LONG boundary
+    - random: quiet urandom warning ratelimit suppression message
+    - USB: serial: option: add Telit LE910Cx 0x1250 composition
+    - USB: serial: option: add Quectel EM05-G modem
+    - USB: serial: option: add Quectel RM500K module support
+    - bpf: Fix request_sock leak in sk lookup helpers
+    - phy: aquantia: Fix AN when higher speeds than 1G are not advertised
+    - bonding: ARP monitor spams NETDEV_NOTIFY_PEERS notifiers
+    - net/sched: sch_netem: Fix arithmetic in netem_dump() for 32-bit platforms
+    - drm/msm/mdp4: Fix refcount leak in mdp4_modeset_init_intf
+    - erspan: do not assume transport header is always set
+    - net/tls: fix tls_sk_proto_close executed repeatedly
+    - udmabuf: add back sanity check
+    - x86/xen: Remove undefined behavior in setup_features()
+    - MIPS: Remove repetitive increase irq_err_count
+    - afs: Fix dynamic root getattr
+    - ice: ethtool: advertise 1000M speeds properly
+    - regmap-irq: Fix a bug in regmap_irq_enable() for type_in_mask chips
+    - igb: Make DMA faster when CPU is active on the PCIe link
+    - virtio_net: fix xdp_rxq_info bug after suspend/resume
+    - Revert "net/tls: fix tls_sk_proto_close executed repeatedly"
+    - gpio: winbond: Fix error code in winbond_gpio_get()
+    - s390/cpumf: Handle events cycles and instructions identical
+    - iio: adc: vf610: fix conversion mode sysfs node name
+    - xhci: turn off port power in shutdown
+    - usb: chipidea: udc: check request status before setting device address
+    - iio:chemical:ccs811: rearrange iio trigger get and register
+    - iio:accel:bma180: rearrange iio trigger get and register
+    - iio:accel:mxc4005: rearrange iio trigger get and register
+    - iio: accel: mma8452: ignore the return value of reset operation
+    - iio: gyro: mpu3050: Fix the error handling in mpu3050_power_up()
+    - iio: trigger: sysfs: fix use-after-free on remove
+    - iio: adc: stm32: fix maximum clock rate for stm32mp15x
+    - iio: adc: axp288: Override TS pin bias current for some models
+    - xtensa: xtfpga: Fix refcount leak bug in setup
+    - xtensa: Fix refcount leak bug in time.c
+    - parisc: Enable ARCH_HAS_STRICT_MODULE_RWX
+    - powerpc: Enable execve syscall exit tracepoint
+    - powerpc/rtas: Allow ibm,platform-dump RTAS call with null buffer address
+    - powerpc/powernv: wire up rng during setup_arch
+    - ARM: dts: imx6qdl: correct PU regulator ramp delay
+    - ARM: exynos: Fix refcount leak in exynos_map_pmu
+    - soc: bcm: brcmstb: pm: pm-arm: Fix refcount leak in brcmstb_pm_probe
+    - ARM: Fix refcount leak in axxia_boot_secondary
+    - ARM: cns3xxx: Fix refcount leak in cns3xxx_init
+    - modpost: fix section mismatch check for exported init/exit sections
+    - random: update comment from copy_to_user() -> copy_to_iter()
+    - kbuild: link vmlinux only once for CONFIG_TRIM_UNUSED_KSYMS (2nd attempt)
+    - powerpc/pseries: wire up rng during setup_arch()
+    - Linux 5.4.202
+  * Focal update: v5.4.201 upstream stable release (LP: #1986993)
+    - dm: remove special-casing of bio-based immutable singleton target on NVMe
+    - usb: gadget: u_ether: fix regression in setting fixed MAC address
+    - tcp: add some entropy in __inet_hash_connect()
+    - tcp: use different parts of the port_offset for index and offset
+    - tcp: add small random increments to the source port
+    - tcp: dynamically allocate the perturb table used by source ports
+    - tcp: increase source port perturb table to 2^16
+    - tcp: drop the hash_32() part from the index calculation
+    - arm64: mm: Don't invalidate FROM_DEVICE buffers at start of DMA transfer
+    - Linux 5.4.201
+  * Focal update: v5.4.200 upstream stable release (LP: #1983152)
+    - Revert "UBUNTU: SAUCE: random: Make getrandom() ready earlier"
+    - 9p: missing chunk of "fs/9p: Don't update file type when updating file
+      attributes"
+    - bpf: Fix incorrect memory charge cost calculation in stack_map_alloc()
+    - nfc: st21nfca: fix incorrect sizing calculations in EVT_TRANSACTION
+    - crypto: blake2s - generic C library implementation and selftest
+    - lib/crypto: blake2s: move hmac construction into wireguard
+    - lib/crypto: sha1: re-roll loops to reduce code size
+    - compat_ioctl: remove /dev/random commands
+    - random: don't forget compat_ioctl on urandom
+    - random: Don't wake crng_init_wait when crng_init == 1
+    - random: Add a urandom_read_nowait() for random APIs that don't warn
+    - random: add GRND_INSECURE to return best-effort non-cryptographic bytes
+    - random: ignore GRND_RANDOM in getentropy(2)
+    - random: make /dev/random be almost like /dev/urandom
+    - random: remove the blocking pool
+    - random: delete code to pull data into pools
+    - random: remove kernel.random.read_wakeup_threshold
+    - random: remove unnecessary unlikely()
+    - random: convert to ENTROPY_BITS for better code readability
+    - random: Add and use pr_fmt()
+    - random: fix typo in add_timer_randomness()
+    - random: remove some dead code of poolinfo
+    - random: split primary/secondary crng init paths
+    - random: avoid warnings for !CONFIG_NUMA builds
+    - x86: Remove arch_has_random, arch_has_random_seed
+    - powerpc: Remove arch_has_random, arch_has_random_seed
+    - s390: Remove arch_has_random, arch_has_random_seed
+    - linux/random.h: Remove arch_has_random, arch_has_random_seed
+    - linux/random.h: Use false with bool
+    - linux/random.h: Mark CONFIG_ARCH_RANDOM functions __must_check
+    - powerpc: Use bool in archrandom.h
+    - random: add arch_get_random_*long_early()
+    - random: avoid arch_get_random_seed_long() when collecting IRQ randomness
+    - random: remove dead code left over from blocking pool
+    - MAINTAINERS: co-maintain random.c
+    - crypto: blake2s - include <linux/bug.h> instead of <asm/bug.h>
+    - crypto: blake2s - adjust include guard naming
+    - random: document add_hwgenerator_randomness() with other input functions
+    - random: remove unused irq_flags argument from add_interrupt_randomness()
+    - random: use BLAKE2s instead of SHA1 in extraction
+    - random: do not sign extend bytes for rotation when mixing
+    - random: do not re-init if crng_reseed completes before primary init
+    - random: mix bootloader randomness into pool
+    - random: harmonize "crng init done" messages
+    - random: use IS_ENABLED(CONFIG_NUMA) instead of ifdefs
+    - random: initialize ChaCha20 constants with correct endianness
+    - random: early initialization of ChaCha constants
+    - random: avoid superfluous call to RDRAND in CRNG extraction
+    - random: don't reset crng_init_cnt on urandom_read()
+    - random: fix typo in comments
+    - random: cleanup poolinfo abstraction
+    - random: cleanup integer types
+    - random: remove incomplete last_data logic
+    - random: remove unused extract_entropy() reserved argument
+    - random: rather than entropy_store abstraction, use global
+    - random: remove unused OUTPUT_POOL constants
+    - random: de-duplicate INPUT_POOL constants
+    - random: prepend remaining pool constants with POOL_
+    - random: cleanup fractional entropy shift constants
+    - random: access input_pool_data directly rather than through pointer
+    - random: selectively clang-format where it makes sense
+    - random: simplify arithmetic function flow in account()
+    - random: continually use hwgenerator randomness
+    - random: access primary_pool directly rather than through pointer
+    - random: only call crng_finalize_init() for primary_crng
+    - random: use computational hash for entropy extraction
+    - random: simplify entropy debiting
+    - random: use linear min-entropy accumulation crediting
+    - random: always wake up entropy writers after extraction
+    - random: make credit_entropy_bits() always safe
+    - random: remove use_input_pool parameter from crng_reseed()
+    - random: remove batched entropy locking
+    - random: fix locking in crng_fast_load()
+    - random: use RDSEED instead of RDRAND in entropy extraction
+    - random: get rid of secondary crngs
+    - random: inline leaves of rand_initialize()
+    - random: ensure early RDSEED goes through mixer on init
+    - random: do not xor RDRAND when writing into /dev/random
+    - random: absorb fast pool into input pool after fast load
+    - random: use simpler fast key erasure flow on per-cpu keys
+    - random: use hash function for crng_slow_load()
+    - random: make more consistent use of integer types
+    - random: remove outdated INT_MAX >> 6 check in urandom_read()
+    - random: zero buffer after reading entropy from userspace
+    - random: fix locking for crng_init in crng_reseed()
+    - random: tie batched entropy generation to base_crng generation
+    - random: remove ifdef'd out interrupt bench
+    - random: remove unused tracepoints
+    - random: add proper SPDX header
+    - random: deobfuscate irq u32/u64 contributions
+    - random: introduce drain_entropy() helper to declutter crng_reseed()
+    - random: remove useless header comment
+    - random: remove whitespace and reorder includes
+    - random: group initialization wait functions
+    - random: group crng functions
+    - random: group entropy extraction functions
+    - random: group entropy collection functions
+    - random: group userspace read/write functions
+    - random: group sysctl functions
+    - random: rewrite header introductory comment
+    - random: defer fast pool mixing to worker
+    - random: do not take pool spinlock at boot
+    - random: unify early init crng load accounting
+    - random: check for crng_init == 0 in add_device_randomness()
+    - random: pull add_hwgenerator_randomness() declaration into random.h
+    - random: clear fast pool, crng, and batches in cpuhp bring up
+    - random: round-robin registers as ulong, not u32
+    - random: only wake up writers after zap if threshold was passed
+    - random: cleanup UUID handling
+    - random: unify cycles_t and jiffies usage and types
+    - random: do crng pre-init loading in worker rather than irq
+    - random: give sysctl_random_min_urandom_seed a more sensible value
+    - random: don't let 644 read-only sysctls be written to
+    - random: replace custom notifier chain with standard one
+    - random: use SipHash as interrupt entropy accumulator
+    - random: make consistent usage of crng_ready()
+    - random: reseed more often immediately after booting
+    - random: check for signal and try earlier when generating entropy
+    - random: skip fast_init if hwrng provides large chunk of entropy
+    - random: treat bootloader trust toggle the same way as cpu trust toggle
+    - random: re-add removed comment about get_random_{u32,u64} reseeding
+    - random: mix build-time latent entropy into pool at init
+    - random: do not split fast init input in add_hwgenerator_randomness()
+    - random: do not allow user to keep crng key around on stack
+    - random: check for signal_pending() outside of need_resched() check
+    - random: check for signals every PAGE_SIZE chunk of /dev/[u]random
+    - random: allow partial reads if later user copies fail
+    - random: make random_get_entropy() return an unsigned long
+    - random: document crng_fast_key_erasure() destination possibility
+    - random: fix sysctl documentation nits
+    - init: call time_init() before rand_initialize()
+    - ia64: define get_cycles macro for arch-override
+    - s390: define get_cycles macro for arch-override
+    - parisc: define get_cycles macro for arch-override
+    - alpha: define get_cycles macro for arch-override
+    - powerpc: define get_cycles macro for arch-override
+    - timekeeping: Add raw clock fallback for random_get_entropy()
+    - m68k: use fallback for random_get_entropy() instead of zero
+    - mips: use fallback for random_get_entropy() instead of just c0 random
+    - arm: use fallback for random_get_entropy() instead of zero
+    - nios2: use fallback for random_get_entropy() instead of zero
+    - x86/tsc: Use fallback for random_get_entropy() instead of zero
+    - um: use fallback for random_get_entropy() instead of zero
+    - sparc: use fallback for random_get_entropy() instead of zero
+    - xtensa: use fallback for random_get_entropy() instead of zero
+    - random: insist on random_get_entropy() existing in order to simplify
+    - random: do not use batches when !crng_ready()
+    - random: use first 128 bits of input as fast init
+    - random: do not pretend to handle premature next security model
+    - random: order timer entropy functions below interrupt functions
+    - random: do not use input pool from hard IRQs
+    - random: help compiler out with fast_mix() by using simpler arguments
+    - siphash: use one source of truth for siphash permutations
+    - random: use symbolic constants for crng_init states
+    - random: avoid initializing twice in credit race
+    - random: move initialization out of reseeding hot path
+    - random: remove ratelimiting for in-kernel unseeded randomness
+    - random: use proper jiffies comparison macro
+    - random: handle latent entropy and command line from random_init()
+    - random: credit architectural init the exact amount
+    - random: use static branch for crng_ready()
+    - random: remove extern from functions in header
+    - random: use proper return types on get_random_{int,long}_wait()
+    - random: make consistent use of buf and len
+    - random: move initialization functions out of hot pages
+    - random: move randomize_page() into mm where it belongs
+    - random: unify batched entropy implementations
+    - random: convert to using fops->read_iter()
+    - random: convert to using fops->write_iter()
+    - random: wire up fops->splice_{read,write}_iter()
+    - random: check for signals after page of pool writes
+    - Revert "random: use static branch for crng_ready()"
+    - crypto: drbg - always seeded with SP800-90B compliant noise source
+    - crypto: drbg - prepare for more fine-grained tracking of seeding state
+    - crypto: drbg - track whether DRBG was seeded with !rng_is_initialized()
+    - crypto: drbg - move dynamic ->reseed_threshold adjustments to __drbg_seed()
+    - crypto: drbg - always try to free Jitter RNG instance
+    - crypto: drbg - make reseeding from get_random_bytes() synchronous
+    - random: avoid checking crng_ready() twice in random_init()
+    - random: mark bootloader randomness code as __init
+    - random: account for arch randomness in bits
+    - powerpc/kasan: Silence KASAN warnings in __get_wchan()
+    - ASoC: nau8822: Add operation for internal PLL off and on
+    - dma-debug: make things less spammy under memory pressure
+    - ASoC: cs42l52: Fix TLV scales for mixer controls
+    - ASoC: cs35l36: Update digital volume TLV
+    - ASoC: cs53l30: Correct number of volume levels on SX controls
+    - ASoC: cs42l52: Correct TLV for Bypass Volume
+    - ASoC: cs42l56: Correct typo in minimum level for SX volume controls
+    - ata: libata-core: fix NULL pointer deref in ata_host_alloc_pinfo()
+    - ASoC: wm8962: Fix suspend while playing music
+    - ASoC: es8328: Fix event generation for deemphasis control
+    - ASoC: wm_adsp: Fix event generation for wm_adsp_fw_put()
+    - scsi: vmw_pvscsi: Expand vcpuHint to 16 bits
+    - scsi: lpfc: Fix port stuck in bypassed state after LIP in PT2PT topology
+    - scsi: lpfc: Allow reduced polling rate for nvme_admin_async_event cmd
+      completion
+    - scsi: ipr: Fix missing/incorrect resource cleanup in error case
+    - scsi: pmcraid: Fix missing resource cleanup in error case
+    - ALSA: hda/realtek - Add HW8326 support
+    - virtio-mmio: fix missing put_device() when vm_cmdline_parent registration
+      failed
+    - nfc: nfcmrvl: Fix memory leak in nfcmrvl_play_deferred
+    - ipv6: Fix signed integer overflow in l2tp_ip6_sendmsg
+    - net: ethernet: mtk_eth_soc: fix misuse of mem alloc interface
+      netdev[napi]_alloc_frag
+    - random: credit cpu and bootloader seeds by default
+    - pNFS: Don't keep retrying if the server replied NFS4ERR_LAYOUTUNAVAILABLE
+    - clocksource: hyper-v: unexport __init-annotated hv_init_clocksource()
+    - i40e: Fix adding ADQ filter to TC0
+    - i40e: Fix calculating the number of queue pairs
+    - i40e: Fix call trace in setup_tx_descriptors
+    - tty: goldfish: Fix free_irq() on remove
+    - misc: atmel-ssc: Fix IRQ check in ssc_probe
+    - mlxsw: spectrum_cnt: Reorder counter pools
+    - net: bgmac: Fix an erroneous kfree() in bgmac_remove()
+    - arm64: ftrace: fix branch range checks
+    - certs/blacklist_hashes.c: fix const confusion in certs blacklist
+    - faddr2line: Fix overlapping text section failures, the sequel
+    - irqchip/gic/realview: Fix refcount leak in realview_gic_of_init
+    - irqchip/gic-v3: Fix error handling in gic_populate_ppi_partitions
+    - irqchip/gic-v3: Fix refcount leak in gic_populate_ppi_partitions
+    - i2c: designware: Use standard optional ref clock implementation
+    - comedi: vmk80xx: fix expression for tx buffer size
+    - USB: serial: option: add support for Cinterion MV31 with new baseline
+    - USB: serial: io_ti: add Agilent E5805A support
+    - usb: dwc2: Fix memory leak in dwc2_hcd_init
+    - usb: gadget: lpc32xx_udc: Fix refcount leak in lpc32xx_udc_probe
+    - serial: 8250: Store to lsr_save_flags after lsr read
+    - dm mirror log: round up region bitmap size to BITS_PER_LONG
+    - ext4: fix bug_on ext4_mb_use_inode_pa
+    - ext4: make variable "count" signed
+    - ext4: add reserved GDT blocks check
+    - ALSA: hda/realtek: fix right sounds and mute/micmute LEDs for HP machine
+    - virtio-pci: Remove wrong address verification in vp_del_vqs()
+    - net/sched: act_police: more accurate MTU policing
+    - net: openvswitch: fix leak of nested actions
+    - arm64: kprobes: Use BRK instead of single-step when executing instructions
+      out-of-line
+    - RISC-V: fix barrier() use in <vdso/processor.h>
+    - riscv: Less inefficient gcc tishift helpers (and export their symbols)
+    - powerpc/mm: Switch obsolete dssall to .long
+    - Linux 5.4.200
+  * Focal update: v5.4.199 upstream stable release (LP: #1983150)
+    - Linux 5.4.199
+  * Focal update: v5.4.198 upstream stable release (LP: #1982409)
+    - binfmt_flat: do not stop relocating GOT entries prematurely on riscv
+    - ALSA: hda/realtek - Fix microphone noise on ASUS TUF B550M-PLUS
+    - USB: serial: option: add Quectel BG95 modem
+    - USB: new quirk for Dell Gen 2 devices
+    - perf/x86/intel: Fix event constraints for ICL
+    - ptrace/um: Replace PT_DTRACE with TIF_SINGLESTEP
+    - ptrace/xtensa: Replace PT_SINGLESTEP with TIF_SINGLESTEP
+    - ptrace: Reimplement PTRACE_KILL by always sending SIGKILL
+    - btrfs: add "0x" prefix for unsupported optional features
+    - btrfs: repair super block num_devices automatically
+    - drm/virtio: fix NULL pointer dereference in virtio_gpu_conn_get_modes
+    - mwifiex: add mutex lock for call in mwifiex_dfs_chan_sw_work_queue
+    - b43legacy: Fix assigning negative value to unsigned variable
+    - b43: Fix assigning negative value to unsigned variable
+    - ipw2x00: Fix potential NULL dereference in libipw_xmit()
+    - ipv6: fix locking issues with loops over idev->addr_list
+    - fbcon: Consistently protect deferred_takeover with console_lock()
+    - ACPICA: Avoid cache flush inside virtual machines
+    - drm/komeda: return early if drm_universal_plane_init() fails.
+    - ALSA: jack: Access input_dev under mutex
+    - spi: spi-rspi: Remove setting {src,dst}_{addr,addr_width} based on DMA
+      direction
+    - tools/power turbostat: fix ICX DRAM power numbers
+    - drm/amd/pm: fix double free in si_parse_power_table()
+    - ath9k: fix QCA9561 PA bias level
+    - media: venus: hfi: avoid null dereference in deinit
+    - media: pci: cx23885: Fix the error handling in cx23885_initdev()
+    - media: cx25821: Fix the warning when removing the module
+    - md/bitmap: don't set sb values if can't pass sanity check
+    - mmc: jz4740: Apply DMA engine limits to maximum segment size
+    - scsi: megaraid: Fix error check return value of register_chrdev()
+    - drm/plane: Move range check for format_count earlier
+    - drm/amd/pm: fix the compile warning
+    - arm64: compat: Do not treat syscall number as ESR_ELx for a bad syscall
+    - drm: msm: fix error check return value of irq_of_parse_and_map()
+    - ipv6: Don't send rs packets to the interface of ARPHRD_TUNNEL
+    - net/mlx5: fs, delete the FTE when there are no rules attached to it
+    - ASoC: dapm: Don't fold register value changes into notifications
+    - mlxsw: spectrum_dcb: Do not warn about priority changes
+    - drm/amdgpu/ucode: Remove firmware load type check in amdgpu_ucode_free_bo
+    - HID: bigben: fix slab-out-of-bounds Write in bigben_probe
+    - ASoC: tscs454: Add endianness flag in snd_soc_component_driver
+    - s390/preempt: disable __preempt_count_add() optimization for
+      PROFILE_ALL_BRANCHES
+    - spi: stm32-qspi: Fix wait_cmd timeout in APM mode
+    - dma-debug: change allocation mode from GFP_NOWAIT to GFP_ATIOMIC
+    - ACPI: PM: Block ASUS B1400CEAE from suspend to idle by default
+    - ipmi:ssif: Check for NULL msg when handling events and messages
+    - ipmi: Fix pr_fmt to avoid compilation issues
+    - rtlwifi: Use pr_warn instead of WARN_ONCE
+    - media: coda: limit frame interval enumeration to supported encoder frame
+      sizes
+    - media: cec-adap.c: fix is_configuring state
+    - openrisc: start CPU timer early in boot
+    - nvme-pci: fix a NULL pointer dereference in nvme_alloc_admin_tags
+    - ASoC: rt5645: Fix errorenous cleanup order
+    - nbd: Fix hung on disconnect request if socket is closed before
+    - net: phy: micrel: Allow probing without .driver_data
+    - media: exynos4-is: Fix compile warning
+    - ASoC: max98357a: remove dependency on GPIOLIB
+    - rxrpc: Return an error to sendmsg if call failed
+    - eth: tg3: silence the GCC 12 array-bounds warning
+    - selftests/bpf: fix btf_dump/btf_dump due to recent clang change
+    - IB/rdmavt: add missing locks in rvt_ruc_loopback
+    - ARM: dts: ox820: align interrupt controller node name with dtschema
+    - PM / devfreq: rk3399_dmc: Disable edev on remove()
+    - fs: jfs: fix possible NULL pointer dereference in dbFree()
+    - ARM: OMAP1: clock: Fix UART rate reporting algorithm
+    - powerpc/fadump: Fix fadump to work with a different endian capture kernel
+    - fat: add ratelimit to fat*_ent_bread()
+    - ARM: versatile: Add missing of_node_put in dcscb_init
+    - ARM: dts: exynos: add atmel,24c128 fallback to Samsung EEPROM
+    - ARM: hisi: Add missing of_node_put after of_find_compatible_node
+    - PCI: Avoid pci_dev_lock() AB/BA deadlock with sriov_numvfs_store()
+    - tracing: incorrect isolate_mote_t cast in mm_vmscan_lru_isolate
+    - powerpc/xics: fix refcount leak in icp_opal_init()
+    - powerpc/powernv: fix missing of_node_put in uv_init()
+    - macintosh/via-pmu: Fix build failure when CONFIG_INPUT is disabled
+    - powerpc/iommu: Add missing of_node_put in iommu_init_early_dart
+    - RDMA/hfi1: Prevent panic when SDMA is disabled
+    - drm: fix EDID struct for old ARM OABI format
+    - ath9k: fix ar9003_get_eepmisc
+    - drm/edid: fix invalid EDID extension block filtering
+    - drm/bridge: adv7511: clean up CEC adapter when probe fails
+    - ASoC: mediatek: Fix error handling in mt8173_max98090_dev_probe
+    - ASoC: mediatek: Fix missing of_node_put in mt2701_wm8960_machine_probe
+    - x86/delay: Fix the wrong asm constraint in delay_loop()
+    - drm/mediatek: Fix mtk_cec_mask()
+    - drm/vc4: txp: Don't set TXP_VSTART_AT_EOF
+    - drm/vc4: txp: Force alpha to be 0xff if it's disabled
+    - bpf: Fix excessive memory allocation in stack_map_alloc()
+    - nl80211: show SSID for P2P_GO interfaces
+    - drm/komeda: Fix an undefined behavior bug in komeda_plane_add()
+    - drm: mali-dp: potential dereference of null pointer
+    - spi: spi-ti-qspi: Fix return value handling of wait_for_completion_timeout
+    - NFC: NULL out the dev->rfkill to prevent UAF
+    - efi: Add missing prototype for efi_capsule_setup_info
+    - drbd: fix duplicate array initializer
+    - HID: hid-led: fix maximum brightness for Dream Cheeky
+    - HID: elan: Fix potential double free in elan_input_configured
+    - drm/bridge: Fix error handling in analogix_dp_probe
+    - sched/fair: Fix cfs_rq_clock_pelt() for throttled cfs_rq
+    - spi: img-spfi: Fix pm_runtime_get_sync() error checking
+    - cpufreq: Fix possible race in cpufreq online error path
+    - ath9k_htc: fix potential out of bounds access with invalid
+      rxstatus->rs_keyix
+    - inotify: show inotify mask flags in proc fdinfo
+    - fsnotify: fix wrong lockdep annotations
+    - of: overlay: do not break notify on NOTIFY_{OK|STOP}
+    - scsi: ufs: core: Exclude UECxx from SFR dump list
+    - x86/pm: Fix false positive kmemleak report in msr_build_context()
+    - x86/speculation: Add missing prototype for unpriv_ebpf_notify()
+    - ASoC: rk3328: fix disabling mclk on pclk probe failure
+    - perf tools: Add missing headers needed by util/data.h
+    - drm/msm/disp/dpu1: set vbif hw config to NULL to avoid use after memory free
+      during pm runtime resume
+    - drm/msm/dsi: fix error checks and return values for DSI xmit functions
+    - drm/msm/hdmi: check return value after calling
+      platform_get_resource_byname()
+    - drm/msm/hdmi: fix error check return value of irq_of_parse_and_map()
+    - drm/rockchip: vop: fix possible null-ptr-deref in vop_bind()
+    - virtio_blk: fix the discard_granularity and discard_alignment queue limits
+    - x86: Fix return value of __setup handlers
+    - irqchip/exiu: Fix acknowledgment of edge triggered interrupts
+    - irqchip/aspeed-i2c-ic: Fix irq_of_parse_and_map() return value
+    - x86/mm: Cleanup the control_va_addr_alignment() __setup handler
+    - regulator: core: Fix enable_count imbalance with EXCLUSIVE_GET
+    - drm/msm/mdp5: Return error code in mdp5_pipe_release when deadlock is
+      detected
+    - drm/msm/mdp5: Return error code in mdp5_mixer_release when deadlock is
+      detected
+    - drm/msm: return an error pointer in msm_gem_prime_get_sg_table()
+    - media: uvcvideo: Fix missing check to determine if element is found in list
+    - iomap: iomap_write_failed fix
+    - Revert "cpufreq: Fix possible race in cpufreq online error path"
+    - perf/amd/ibs: Use interrupt regs ip for stack unwinding
+    - ASoC: fsl: Fix refcount leak in imx_sgtl5000_probe
+    - ASoC: mxs-saif: Fix refcount leak in mxs_saif_probe
+    - regulator: pfuze100: Fix refcount leak in pfuze_parse_regulators_dt
+    - scripts/faddr2line: Fix overlapping text section failures
+    - media: aspeed: Fix an error handling path in aspeed_video_probe()
+    - media: st-delta: Fix PM disable depth imbalance in delta_probe
+    - media: exynos4-is: Change clk_disable to clk_disable_unprepare
+    - media: pvrusb2: fix array-index-out-of-bounds in pvr2_i2c_core_init
+    - media: vsp1: Fix offset calculation for plane cropping
+    - Bluetooth: fix dangling sco_conn and use-after-free in sco_sock_timeout
+    - m68k: math-emu: Fix dependencies of math emulation support
+    - sctp: read sk->sk_bound_dev_if once in sctp_rcv()
+    - media: ov7670: remove ov7670_power_off from ov7670_remove
+    - ext4: reject the 'commit' option on ext2 filesystems
+    - drm/msm/a6xx: Fix refcount leak in a6xx_gpu_init
+    - drm: msm: fix possible memory leak in mdp5_crtc_cursor_set()
+    - thermal/drivers/broadcom: Fix potential NULL dereference in sr_thermal_probe
+    - ASoC: wm2000: fix missing clk_disable_unprepare() on error in
+      wm2000_anc_transition()
+    - NFC: hci: fix sleep in atomic context bugs in nfc_hci_hcp_message_tx
+    - rxrpc: Fix listen() setting the bar too high for the prealloc rings
+    - rxrpc: Don't try to resend the request if we're receiving the reply
+    - rxrpc: Fix overlapping ACK accounting
+    - rxrpc: Don't let ack.previousPacket regress
+    - rxrpc: Fix decision on when to generate an IDLE ACK
+    - net/smc: postpone sk_refcnt increment in connect()
+    - arm64: dts: rockchip: Move drive-impedance-ohm to emmc phy on rk3399
+    - ARM: dts: suniv: F1C100: fix watchdog compatible
+    - soc: qcom: smp2p: Fix missing of_node_put() in smp2p_parse_ipc
+    - soc: qcom: smsm: Fix missing of_node_put() in smsm_parse_ipc
+    - PCI: cadence: Fix find_first_zero_bit() limit
+    - PCI: rockchip: Fix find_first_zero_bit() limit
+    - KVM: nVMX: Leave most VM-Exit info fields unmodified on failed VM-Entry
+    - can: xilinx_can: mark bit timing constants as const
+    - ARM: dts: bcm2835-rpi-zero-w: Fix GPIO line name for Wifi/BT
+    - ARM: dts: bcm2837-rpi-cm3-io3: Fix GPIO line names for SMPS I2C
+    - ARM: dts: bcm2837-rpi-3-b-plus: Fix GPIO line name of power LED
+    - ARM: dts: bcm2835-rpi-b: Fix GPIO line names
+    - misc: ocxl: fix possible double free in ocxl_file_register_afu
+    - crypto: marvell/cesa - ECB does not IV
+    - arm: mediatek: select arch timer for mt7629
+    - powerpc/fadump: fix PT_LOAD segment for boot memory area
+    - mfd: ipaq-micro: Fix error check return value of platform_get_irq()
+    - scsi: fcoe: Fix Wstringop-overflow warnings in fcoe_wwn_from_mac()
+    - firmware: arm_scmi: Fix list protocols enumeration in the base protocol
+    - nvdimm: Allow overwrite in the presence of disabled dimms
+    - pinctrl: mvebu: Fix irq_of_parse_and_map() return value
+    - drivers/base/node.c: fix compaction sysfs file leak
+    - dax: fix cache flush on PMD-mapped pages
+    - powerpc/8xx: export 'cpm_setbrg' for modules
+    - powerpc/idle: Fix return value of __setup() handler
+    - powerpc/4xx/cpm: Fix return value of __setup() handler
+    - proc: fix dentry/inode overinstantiating under /proc/${pid}/net
+    - ipc/mqueue: use get_tree_nodev() in mqueue_get_tree()
+    - PCI: imx6: Fix PERST# start-up sequence
+    - tty: fix deadlock caused by calling printk() under tty_port->lock
+    - crypto: cryptd - Protect per-CPU resource by disabling BH.
+    - Input: sparcspkr - fix refcount leak in bbc_beep_probe
+    - powerpc/64: Only WARN if __pa()/__va() called with bad addresses
+    - powerpc/perf: Fix the threshold compare group constraint for power9
+    - macintosh: via-pmu and via-cuda need RTC_LIB
+    - powerpc/fsl_rio: Fix refcount leak in fsl_rio_setup
+    - mfd: davinci_voicecodec: Fix possible null-ptr-deref davinci_vc_probe()
+    - mailbox: forward the hrtimer if not queued and under a lock
+    - RDMA/hfi1: Prevent use of lock before it is initialized
+    - Input: stmfts - do not leave device disabled in stmfts_input_open
+    - f2fs: fix dereference of stale list iterator after loop body
+    - iommu/mediatek: Add list_del in mtk_iommu_remove
+    - i2c: at91: use dma safe buffers
+    - i2c: at91: Initialize dma_buf in at91_twi_xfer()
+    - NFS: Do not report EINTR/ERESTARTSYS as mapping errors
+    - NFS: Do not report flush errors in nfs_write_end()
+    - NFS: Don't report errors from nfs_pageio_complete() more than once
+    - NFSv4/pNFS: Do not fail I/O when we fail to allocate the pNFS layout
+    - video: fbdev: clcdfb: Fix refcount leak in clcdfb_of_vram_setup
+    - dmaengine: stm32-mdma: remove GISR1 register
+    - iommu/amd: Increase timeout waiting for GA log enablement
+    - perf c2c: Use stdio interface if slang is not supported
+    - perf jevents: Fix event syntax error caused by ExtSel
+    - f2fs: fix to avoid f2fs_bug_on() in dec_valid_node_count()
+    - f2fs: fix to do sanity check on block address in f2fs_do_zero_range()
+    - f2fs: fix to clear dirty inode in f2fs_evict_inode()
+    - f2fs: fix deadloop in foreground GC
+    - f2fs: don't need inode lock for system hidden quota
+    - f2fs: fix fallocate to use file_modified to update permissions consistently
+    - wifi: mac80211: fix use-after-free in chanctx code
+    - iwlwifi: mvm: fix assert 1F04 upon reconfig
+    - fs-writeback: writeback_sb_inodes：Recalculate 'wrote' according skipped
+      pages
+    - efi: Do not import certificates from UEFI Secure Boot for T2 Macs
+    - bfq: Split shared queues on move between cgroups
+    - bfq: Update cgroup information before merging bio
+    - bfq: Track whether bfq_group is still online
+    - ext4: fix use-after-free in ext4_rename_dir_prepare
+    - ext4: fix warning in ext4_handle_inode_extension
+    - ext4: fix bug_on in ext4_writepages
+    - ext4: verify dir block before splitting it
+    - ext4: avoid cycles in directory h-tree
+    - ACPI: property: Release subnode properties with data nodes
+    - tracing: Fix potential double free in create_var_ref()
+    - PCI/PM: Fix bridge_d3_blacklist[] Elo i2 overwrite of Gigabyte X299
+    - PCI: qcom: Fix runtime PM imbalance on probe errors
+    - PCI: qcom: Fix unbalanced PHY init on probe errors
+    - mm, compaction: fast_find_migrateblock() should return pfn in the target
+      zone
+    - dlm: fix plock invalid read
+    - dlm: fix missing lkb refcount handling
+    - ocfs2: dlmfs: fix error handling of user_dlm_destroy_lock
+    - scsi: dc395x: Fix a missing check on list iterator
+    - scsi: ufs: qcom: Add a readl() to make sure ref_clk gets enabled
+    - drm/amdgpu/cs: make commands with 0 chunks illegal behaviour.
+    - drm/etnaviv: check for reaped mapping in etnaviv_iommu_unmap_gem
+    - drm/nouveau/clk: Fix an incorrect NULL check on list iterator
+    - drm/bridge: analogix_dp: Grab runtime PM reference for DP-AUX
+    - md: fix an incorrect NULL check in does_sb_need_changing
+    - md: fix an incorrect NULL check in md_reload_sb
+    - mtd: cfi_cmdset_0002: Move and rename
+      chip_check/chip_ready/chip_good_for_write
+    - media: coda: Fix reported H264 profile
+    - media: coda: Add more H264 levels for CODA960
+    - Kconfig: Add option for asm goto w/ tied outputs to workaround clang-13 bug
+    - RDMA/hfi1: Fix potential integer multiplication overflow errors
+    - irqchip/armada-370-xp: Do not touch Performance Counter Overflow on A375,
+      A38x, A39x
+    - irqchip: irq-xtensa-mx: fix initial IRQ affinity
+    - mac80211: upgrade passive scan to active scan on DFS channels after beacon
+      rx
+    - um: chan_user: Fix winch_tramp() return value
+    - um: Fix out-of-bounds read in LDT setup
+    - iommu/msm: Fix an incorrect NULL check on list iterator
+    - nodemask.h: fix compilation error with GCC12
+    - hugetlb: fix huge_pmd_unshare address update
+    - rtl818x: Prevent using not initialized queues
+    - ASoC: rt5514: Fix event generation for "DSP Voice Wake Up" control
+    - carl9170: tx: fix an incorrect use of list iterator
+    - serial: pch: don't overwrite xmit->buf[0] by x_char
+    - tilcdc: tilcdc_external: fix an incorrect NULL check on list iterator
+    - gma500: fix an incorrect NULL check on list iterator
+    - arm64: dts: qcom: ipq8074: fix the sleep clock frequency
+    - phy: qcom-qmp: fix struct clk leak on probe errors
+    - ARM: pxa: maybe fix gpio lookup tables
+    - docs/conf.py: Cope with removal of language=None in Sphinx 5.0.0
+    - dt-bindings: gpio: altera: correct interrupt-cells
+    - blk-iolatency: Fix inflight count imbalances and IO hangs on offline
+    - phy: qcom-qmp: fix reset-controller leak on probe errors
+    - Kconfig: add config option for asm goto w/ outputs
+    - RDMA/rxe: Generate a completion for unsupported/invalid opcode
+    - MIPS: IP27: Remove incorrect `cpu_has_fpu' override
+    - bfq: Avoid merging queues with different parents
+    - bfq: Drop pointless unlock-lock pair
+    - bfq: Remove pointless bfq_init_rq() calls
+    - bfq: Get rid of __bio_blkcg() usage
+    - bfq: Make sure bfqg for which we are queueing requests is online
+    - block: fix bio_clone_blkg_association() to associate with proper blkcg_gq
+    - md: bcache: check the return value of kzalloc() in detached_dev_do_request()
+    - pcmcia: db1xxx_ss: restrict to MIPS_DB1XXX boards
+    - staging: greybus: codecs: fix type confusion of list iterator variable
+    - iio: adc: ad7124: Remove shift from scan_type
+    - tty: goldfish: Use tty_port_destroy() to destroy port
+    - tty: serial: owl: Fix missing clk_disable_unprepare() in owl_uart_probe
+    - tty: serial: fsl_lpuart: fix potential bug when using both of_alias_get_id
+      and ida_simple_get
+    - usb: usbip: fix a refcount leak in stub_probe()
+    - usb: usbip: add missing device lock on tweak configuration cmd
+    - USB: storage: karma: fix rio_karma_init return
+    - usb: musb: Fix missing of_node_put() in omap2430_probe
+    - staging: fieldbus: Fix the error handling path in
+      anybuss_host_common_probe()
+    - pwm: lp3943: Fix duty calculation in case period was clamped
+    - rpmsg: qcom_smd: Fix irq_of_parse_and_map() return value
+    - usb: dwc3: pci: Fix pm_runtime_get_sync() error checking
+    - firmware: stratix10-svc: fix a missing check on list iterator
+    - iio: adc: stmpe-adc: Fix wait_for_completion_timeout return value check
+    - iio: adc: sc27xx: fix read big scale voltage not right
+    - iio: adc: sc27xx: Fine tune the scale calibration values
+    - rpmsg: qcom_smd: Fix returning 0 if irq_of_parse_and_map() fails
+    - phy: qcom-qmp: fix pipe-clock imbalance on power-on failure
+    - serial: sifive: Report actual baud base rather than fixed 115200
+    - coresight: cpu-debug: Replace mutex with mutex_trylock on panic notifier
+    - soc: rockchip: Fix refcount leak in rockchip_grf_init
+    - clocksource/drivers/riscv: Events are stopped during CPU suspend
+    - rtc: mt6397: check return value after calling platform_get_resource()
+    - serial: meson: acquire port->lock in startup()
+    - serial: 8250_fintek: Check SER_RS485_RTS_* only with RS485
+    - serial: digicolor-usart: Don't allow CS5-6
+    - serial: rda-uart: Don't allow CS5-6
+    - serial: txx9: Don't allow CS5-6
+    - serial: sh-sci: Don't allow CS5-6
+    - serial: sifive: Sanitize CSIZE and c_iflag
+    - serial: st-asc: Sanitize CSIZE and correct PARENB for CS7
+    - serial: stm32-usart: Correct CSIZE, bits, and parity
+    - firmware: dmi-sysfs: Fix memory leak in dmi_sysfs_register_handle
+    - bus: ti-sysc: Fix warnings for unbind for serial
+    - driver: base: fix UAF when driver_attach failed
+    - driver core: fix deadlock in __device_attach
+    - watchdog: ts4800_wdt: Fix refcount leak in ts4800_wdt_probe
+    - ASoC: fsl_sai: Fix FSL_SAI_xDR/xFR definition
+    - clocksource/drivers/oxnas-rps: Fix irq_of_parse_and_map() return value
+    - s390/crypto: fix scatterwalk_unmap() callers in AES-GCM
+    - net: sched: fixed barrier to prevent skbuff sticking in qdisc backlog
+    - net: ethernet: mtk_eth_soc: out of bounds read in mtk_hwlro_get_fdir_entry()
+    - net: dsa: mv88e6xxx: Fix refcount leak in mv88e6xxx_mdios_register
+    - modpost: fix removing numeric suffixes
+    - jffs2: fix memory leak in jffs2_do_fill_super
+    - ubi: ubi_create_volume: Fix use-after-free when volume creation failed
+    - nfp: only report pause frame configuration for physical device
+    - net/mlx5: Don't use already freed action pointer
+    - net/mlx5e: Update netdev features after changing XDP state
+    - net: sched: add barrier to fix packet stuck problem for lockless qdisc
+    - tcp: tcp_rtx_synack() can be called from process context
+    - afs: Fix infinite loop found by xfstest generic/676
+    - tipc: check attribute length for bearer name
+    - perf c2c: Fix sorting in percent_rmt_hitm_cmp()
+    - mips: cpc: Fix refcount leak in mips_cpc_default_phys_base
+    - tracing: Fix sleeping function called from invalid context on RT kernel
+    - tracing: Avoid adding tracer option before update_tracer_options
+    - f2fs: remove WARN_ON in f2fs_is_valid_blkaddr
+    - i2c: cadence: Increase timeout per message if necessary
+    - m68knommu: set ZERO_PAGE() to the allocated zeroed page
+    - m68knommu: fix undefined reference to `_init_sp'
+    - dmaengine: zynqmp_dma: In struct zynqmp_dma_chan fix desc_size data type
+    - NFSv4: Don't hold the layoutget locks across multiple RPC calls
+    - video: fbdev: pxa3xx-gcu: release the resources correctly in
+      pxa3xx_gcu_probe/remove()
+    - xprtrdma: treat all calls not a bcall when bc_serv is NULL
+    - netfilter: nat: really support inet nat without l3 address
+    - ata: pata_octeon_cf: Fix refcount leak in octeon_cf_probe
+    - netfilter: nf_tables: memleak flow rule from commit path
+    - xen: unexport __init-annotated xen_xlate_map_ballooned_pages()
+    - af_unix: Fix a data-race in unix_dgram_peer_wake_me().
+    - bpf, arm64: Clear prog->jited_len along prog->jited
+    - net: dsa: lantiq_gswip: Fix refcount leak in gswip_gphy_fw_list
+    - net/mlx4_en: Fix wrong return value on ioctl EEPROM query failure
+    - SUNRPC: Fix the calculation of xdr->end in xdr_get_next_encode_buffer()
+    - net: mdio: unexport __init-annotated mdio_bus_init()
+    - net: xfrm: unexport __init-annotated xfrm4_protocol_init()
+    - net: ipv6: unexport __init-annotated seg6_hmac_init()
+    - net/mlx5: Rearm the FW tracer after each tracer event
+    - net/mlx5: fs, fail conflicting actions
+    - ip_gre: test csum_start instead of transport header
+    - net: altera: Fix refcount leak in altera_tse_mdio_create
+    - drm: imx: fix compiler warning with gcc-12
+    - iio: dummy: iio_simple_dummy: check the return value of kstrdup()
+    - iio: st_sensors: Add a local lock for protecting odr
+    - lkdtm/usercopy: Expand size of "out of frame" object
+    - tty: synclink_gt: Fix null-pointer-dereference in slgt_clean()
+    - tty: Fix a possible resource leak in icom_probe
+    - drivers: staging: rtl8192u: Fix deadlock in ieee80211_beacons_stop()
+    - drivers: staging: rtl8192e: Fix deadlock in rtllib_beacons_stop()
+    - USB: host: isp116x: check return value after calling platform_get_resource()
+    - drivers: tty: serial: Fix deadlock in sa1100_set_termios()
+    - drivers: usb: host: Fix deadlock in oxu_bus_suspend()
+    - USB: hcd-pci: Fully suspend across freeze/thaw cycle
+    - usb: dwc2: gadget: don't reset gadget's driver->bus
+    - misc: rtsx: set NULL intfdata when probe fails
+    - extcon: Modify extcon device to be created after driver data is set
+    - clocksource/drivers/sp804: Avoid error on multiple instances
+    - staging: rtl8712: fix uninit-value in usb_read8() and friends
+    - staging: rtl8712: fix uninit-value in r871xu_drv_init()
+    - serial: msm_serial: disable interrupts in __msm_console_write()
+    - kernfs: Separate kernfs_pr_cont_buf and rename_lock.
+    - watchdog: wdat_wdt: Stop watchdog when rebooting the system
+    - md: protect md_unregister_thread from reentrancy
+    - scsi: myrb: Fix up null pointer access on myrb_cleanup()
+    - ceph: allow ceph.dir.rctime xattr to be updatable
+    - drm/radeon: fix a possible null pointer dereference
+    - modpost: fix undefined behavior of is_arm_mapping_symbol()
+    - x86/cpu: Elide KCSAN for cpu_has() and friends
+    - nbd: call genl_unregister_family() first in nbd_cleanup()
+    - nbd: fix race between nbd_alloc_config() and module removal
+    - cifs: version operations for smb20 unneeded when legacy support disabled
+    - nodemask: Fix return values to be unsigned
+    - vringh: Fix loop descriptors check in the indirect cases
+    - scripts/gdb: change kernel config dumping method
+    - ALSA: hda/conexant - Fix loopback issue with CX20632
+    - cifs: return errors during session setup during reconnects
+    - ata: libata-transport: fix {dma|pio|xfer}_mode sysfs files
+    - mmc: block: Fix CQE recovery reset success
+    - nfc: st21nfca: fix incorrect validating logic in EVT_TRANSACTION
+    - nfc: st21nfca: fix memory leaks in EVT_TRANSACTION handling
+    - ixgbe: fix bcast packets Rx on VF after promisc removal
+    - ixgbe: fix unexpected VLAN Rx in promisc mode on VF
+    - Input: bcm5974 - set missing URB_NO_TRANSFER_DMA_MAP urb flag
+    - powerpc/32: Fix overread/overwrite of thread_struct via ptrace
+    - md/raid0: Ignore RAID0 layout if the second zone has only one device
+    - mtd: cfi_cmdset_0002: Use chip_ready() for write on S29GL064N
+    - tcp: fix tcp_mtup_probe_success vs wrong snd_cwnd
+    - Linux 5.4.198
+  * Focal update: v5.4.197 upstream stable release (LP: #1981758)
+    - x86/pci/xen: Disable PCI/MSI[-X] masking for XEN_HVM guests
+    - staging: rtl8723bs: prevent ->Ssid overflow in rtw_wx_set_scan()
+    - Input: goodix - fix spurious key release events
+    - tcp: change source port randomizarion at connect() time
+    - secure_seq: use the 64 bits of the siphash for port offset calculation
+    - media: vim2m: Register video device after setting up internals
+    - media: vim2m: initialize the media device earlier
+    - ACPI: sysfs: Make sparse happy about address space in use
+    - ACPI: sysfs: Fix BERT error region memory mapping
+    - pinctrl: sunxi: fix f1c100s uart2 function
+    - net: af_key: check encryption module availability consistency
+    - net: ftgmac100: Disable hardware checksum on AST2600
+    - i2c: ismt: Provide a DMA buffer for Interrupt Cause Logging
+    - drivers: i2c: thunderx: Allow driver to work with ACPI defined TWSI
+      controllers
+    - assoc_array: Fix BUG_ON during garbage collect
+    - cfg80211: set custom regdomain after wiphy registration
+    - drm/i915: Fix -Wstringop-overflow warning in call to intel_read_wm_latency()
+    - exec: Force single empty string when argv is empty
+    - netfilter: conntrack: re-fetch conntrack after insertion
+    - crypto: ecrdsa - Fix incorrect use of vli_cmp
+    - zsmalloc: fix races between asynchronous zspage free and page migration
+    - dm integrity: fix error code in dm_integrity_ctr()
+    - dm crypt: make printing of the key constant-time
+    - dm stats: add cond_resched when looping over entries
+    - dm verity: set DM_TARGET_IMMUTABLE feature flag
+    - raid5: introduce MD_BROKEN
+    - HID: multitouch: Add support for Google Whiskers Touchpad
+    - tpm: Fix buffer access in tpm2_get_tpm_pt()
+    - tpm: ibmvtpm: Correct the return value in tpm_ibmvtpm_probe()
+    - docs: submitting-patches: Fix crossref to 'The canonical patch format'
+    - NFS: Memory allocation failures are not server fatal errors
+    - NFSD: Fix possible sleep during nfsd4_release_lockowner()
+    - bpf: Enlarge offset check value to INT_MAX in bpf_skb_{load,store}_bytes
+    - Linux 5.4.197
+  * Focal update: v5.4.196 upstream stable release (LP: #1981111)
+    - x86/xen: Make the boot CPU idle task reliable
+    - x86/xen: Make the secondary CPU idle tasks reliable
+    - rtc: fix use-after-free on device removal
+    - um: Cleanup syscall_handler_t definition/cast, fix warning
+    - Input: add bounds checking to input_set_capability()
+    - Input: stmfts - fix reference leak in stmfts_input_open
+    - crypto: stm32 - fix reference leak in stm32_crc_remove
+    - crypto: x86/chacha20 - Avoid spurious jumps to other functions
+    - ALSA: hda/realtek: Enable headset mic on Lenovo P360
+    - nvme-multipath: fix hang when disk goes live over reconnect
+    - rtc: mc146818-lib: Fix the AltCentury for AMD platforms
+    - MIPS: lantiq: check the return value of kzalloc()
+    - drbd: remove usage of list iterator variable after loop
+    - platform/chrome: cros_ec_debugfs: detach log reader wq from devm
+    - ARM: 9191/1: arm/stacktrace, kasan: Silence KASAN warnings in unwind_frame()
+    - nilfs2: fix lockdep warnings in page operations for btree nodes
+    - nilfs2: fix lockdep warnings during disk space reclamation
+    - mmc: core: Specify timeouts for BKOPS and CACHE_FLUSH for eMMC
+    - mmc: block: Use generic_cmd6_time when modifying INAND_CMD38_ARG_EXT_CSD
+    - mmc: core: Default to generic_cmd6_time as timeout in __mmc_switch()
+    - SUNRPC: Clean up scheduling of autoclose
+    - SUNRPC: Prevent immediate close+reconnect
+    - SUNRPC: Don't call connect() more than once on a TCP socket
+    - ALSA: wavefront: Proper check of get_user() error
+    - perf: Fix sys_perf_event_open() race against self
+    - Fix double fget() in vhost_net_set_backend()
+    - PCI/PM: Avoid putting Elo i2 PCIe Ports in D3cold
+    - KVM: x86/mmu: Update number of zapped pages even if page list is stable
+    - crypto: qcom-rng - fix infinite loop on requests not multiple of WORD_SZ
+    - drm/dp/mst: fix a possible memory leak in fetch_monitor_name()
+    - dma-buf: fix use of DMA_BUF_SET_NAME_{A,B} in userspace
+    - ARM: dts: aspeed-g6: remove FWQSPID group in pinctrl dtsi
+    - ARM: dts: aspeed-g6: fix SPI1/SPI2 quad pin group
+    - net: macb: Increment rx bd head after allocating skb and buffer
+    - net/sched: act_pedit: sanitize shift argument before usage
+    - net: vmxnet3: fix possible use-after-free bugs in vmxnet3_rq_alloc_rx_buf()
+    - net: vmxnet3: fix possible NULL pointer dereference in vmxnet3_rq_cleanup()
+    - ice: fix possible under reporting of ethtool Tx and Rx statistics
+    - clk: at91: generated: consider range when calculating best rate
+    - net/qla3xxx: Fix a test in ql_reset_work()
+    - NFC: nci: fix sleep in atomic context bugs caused by nci_skb_alloc
+    - net/mlx5e: Properly block LRO when XDP is enabled
+    - ARM: 9196/1: spectre-bhb: enable for Cortex-A15
+    - ARM: 9197/1: spectre-bhb: fix loop8 sequence for Thumb2
+    - igb: skip phy status check where unavailable
+    - net: bridge: Clear offload_fwd_mark when passing frame up bridge interface.
+    - gpio: gpio-vf610: do not touch other bits when set the target bit
+    - gpio: mvebu/pwm: Refuse requests with inverted polarity
+    - perf bench numa: Address compiler error on s390
+    - scsi: qla2xxx: Fix missed DMA unmap for aborted commands
+    - mac80211: fix rx reordering with non explicit / psmp ack policy
+    - selftests: add ping test with ping_group_range tuned
+    - ethernet: tulip: fix missing pci_disable_device() on error in
+      tulip_init_one()
+    - net: stmmac: fix missing pci_disable_device() on error in stmmac_pci_probe()
+    - net: atlantic: verify hw_head_ lies within TX buffer ring
+    - Input: ili210x - fix reset timing
+    - block: return ELEVATOR_DISCARD_MERGE if possible
+    - net: stmmac: disable Split Header (SPH) for Intel platforms
+    - firmware_loader: use kernel credentials when reading firmware
+    - ARM: dts: imx7: Use audio_mclk_post_div instead audio_mclk_root_clk
+    - Reinstate some of "swiotlb: rework "fix info leak with DMA_FROM_DEVICE""
+    - x86/xen: fix booting 32-bit pv guest
+    - x86/xen: Mark cpu_bringup_and_idle() as dead_end_function
+    - i2c: mt7621: fix missing clk_disable_unprepare() on error in mtk_i2c_probe()
+    - afs: Fix afs_getattr() to refetch file status if callback break occurred
+    - Linux 5.4.196
+  * CVE-2022-36946
+    - netfilter: nf_queue: do not allow packet truncation below transport header
+      offset
+  * CVE-2021-33655
+    - fbcon: Disallow setting font bigger than screen size
+    - fbcon: Prevent that screen size is smaller than font size
+    - fbmem: Check virtual screen sizes in fb_set_var()
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Wed, 16 Nov 2022 15:21:39 +1000
+
+linux-xilinx-zynqmp (5.4.0-1018.21) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1018.21 -proposed tracker (LP: #1987968)
+
+  * Support builtin revoked certificates (LP: #1932029)
+    - [Config] Configure CONFIG_SYSTEM_REVOCATION_KEYS with revoked keys
+
+  * Please trust Canonical Livepatch Service kmod signing key (LP: #1898716)
+    - [Config] Add canonical-certs.pem
+
+  * CVE-2022-23960
+    - [Config] updateconfigs for CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY
+
+  * Focal update: upstream stable patchset v5.4.192 (LP: #1979014)
+    - [Config] updateconfigs for NVM
+
+  * Focal update: v5.4.141 upstream stable release (LP: #1943484)
+    - SAUCE: usb: dwc3: Fix dwc3_gadget_disable_irq declaration
+
+  * Focal update: v5.4.174 upstream stable release (LP: #1960566)
+    - SAUCE: tty: pl011: Remove release and request port callback in
+      xlnx_sbsa_uart_pops
+
+  * Focal update: v5.4.178 upstream stable release (LP: #1964634)
+    - ASoC: xilinx: xlnx_formatter_pcm: Make buffer bytes multiple of period bytes
+
+  * Focal update: v5.4.142 upstream stable release (LP: #1944202)
+    - ASoC: xilinx: Fix reference to PCM buffer address
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update Ubuntu.md
+
+  * Unable to handle kernel NULL pointer dereference on reboot (LP: #1950962)
+    - drm: xlnx: drv: unbind all components before framebuffer cleanup
+
+  [ Ubuntu: 5.4.0-125.141 ]
+
+  * focal/linux: 5.4.0-125.141 -proposed tracker (LP: #1983947)
+  * nbd: requests can become stuck when disconnecting from server with qemu-nbd
+    (LP: #1896350)
+    - blk-mq: blk-mq: provide forced completion method
+    - blk-mq: move failure injection out of blk_mq_complete_request
+    - nbd: don't handle response without a corresponding request message
+    - nbd: make sure request completion won't concurrent
+    - nbd: don't clear 'NBD_CMD_INFLIGHT' flag if request is not completed
+    - nbd: fix io hung while disconnecting device
+  * CVE-2021-33656
+    - vt: drop old FONT ioctls
+  * CVE-2021-33061
+    - ixgbe: add the ability for the PF to disable VF link state
+    - ixgbe: add improvement for MDD response functionality
+    - ixgbevf: add disable link state
+
+  [ Ubuntu: 5.4.0-124.140 ]
+
+  * CVE-2022-2586
+    - SAUCE: netfilter: nf_tables: do not allow SET_ID to refer to another table
+    - SAUCE: netfilter: nf_tables: do not allow RULE_ID to refer to another chain
+  * CVE-2022-2588
+    - SAUCE: net_sched: cls_route: remove from list when handle is 0
+  * CVE-2022-34918
+    - netfilter: nf_tables: stricter validation of element data
+
+  [ Ubuntu: 5.4.0-123.139 ]
+
+  * focal/linux: 5.4.0-123.139 -proposed tracker (LP: #1981284)
+  * Packaging resync (LP: #1786013)
+    - debian/dkms-versions -- update from kernel-versions (main/2022.07.11)
+  * Hairpin traffic does not work with centralized NAT gw (LP: #1967856)
+    - net: openvswitch: fix misuse of the cached connection on tuple changes
+  * [UBUNTU 20.04] Include patches to avoid self-detected stall with Secure
+    Execution (LP: #1979296)
+    - KVM: s390: pv: add macros for UVC CC values
+    - KVM: s390: pv: avoid stalls when making pages secure
+    - KVM: s390: pv: avoid stalls for kvm_s390_pv_init_vm
+  * Focal update: v5.4.195 upstream stable release (LP: #1980407)
+    - batman-adv: Don't skb_split skbuffs with frag_list
+    - hwmon: (tmp401) Add OF device ID table
+    - mac80211: Reset MBSSID parameters upon connection
+    - net: Fix features skip in for_each_netdev_feature()
+    - ipv4: drop dst in multicast routing path
+    - drm/nouveau: Fix a potential theorical leak in nouveau_get_backlight_name()
+    - netlink: do not reset transport header in netlink_recvmsg()
+    - mac80211_hwsim: call ieee80211_tx_prepare_skb under RCU protection
+    - dim: initialize all struct fields
+    - hwmon: (ltq-cputemp) restrict it to SOC_XWAY
+    - s390/ctcm: fix variable dereferenced before check
+    - s390/ctcm: fix potential memory leak
+    - s390/lcs: fix variable dereferenced before check
+    - net/sched: act_pedit: really ensure the skb is writable
+    - net/smc: non blocking recvmsg() return -EAGAIN when no data and
+      signal_pending
+    - net: sfc: ef10: fix memory leak in efx_ef10_mtd_probe()
+    - gfs2: Fix filesystem block deallocation for short writes
+    - hwmon: (f71882fg) Fix negative temperature
+    - ASoC: max98090: Reject invalid values in custom control put()
+    - ASoC: max98090: Generate notifications on changes for custom control
+    - ASoC: ops: Validate input values in snd_soc_put_volsw_range()
+    - s390: disable -Warray-bounds
+    - net: emaclite: Don't advertise 1000BASE-T and do auto negotiation
+    - tcp: resalt the secret every 10 seconds
+    - tty: n_gsm: fix mux activation issues in gsm_config()
+    - usb: cdc-wdm: fix reading stuck on device close
+    - usb: typec: tcpci: Don't skip cleanup in .remove() on error
+    - USB: serial: pl2303: add device id for HP LM930 Display
+    - USB: serial: qcserial: add support for Sierra Wireless EM7590
+    - USB: serial: option: add Fibocom L610 modem
+    - USB: serial: option: add Fibocom MA510 modem
+    - slimbus: qcom: Fix IRQ check in qcom_slim_probe
+    - serial: 8250_mtk: Fix UART_EFR register address
+    - serial: 8250_mtk: Fix register address for XON/XOFF character
+    - drm/nouveau/tegra: Stop using iommu_present()
+    - i40e: i40e_main: fix a missing check on list iterator
+    - cgroup/cpuset: Remove cpus_allowed/mems_allowed setup in cpuset_init_smp()
+    - drm/vmwgfx: Initialize drm_mode_fb_cmd2
+    - MIPS: fix build with gcc-12
+    - net: phy: Fix race condition on link status change
+    - arm[64]/memremap: don't abuse pfn_valid() to ensure presence of linear map
+    - ping: fix address binding wrt vrf
+    - tty/serial: digicolor: fix possible null-ptr-deref in digicolor_uart_probe()
+    - Linux 5.4.195
+  * Focal update: v5.4.194 upstream stable release (LP: #1980399)
+    - MIPS: Use address-of operator on section symbols
+    - block: drbd: drbd_nl: Make conversion to 'enum drbd_ret_code' explicit
+    - drm/amd/display/dc/gpio/gpio_service: Pass around correct dce_{version,
+      environment} types
+    - drm/i915: Cast remain to unsigned long in eb_relocate_vma
+    - nfp: bpf: silence bitwise vs. logical OR warning
+    - can: grcan: grcan_probe(): fix broken system id check for errata workaround
+      needs
+    - can: grcan: only use the NAPI poll budget for RX
+    - arm: remove CONFIG_ARCH_HAS_HOLES_MEMORYMODEL
+    - [Config] updateconfigs for ARCH_HAS_HOLES_MEMORYMODEL
+    - KVM: x86/pmu: Refactoring find_arch_event() to pmc_perf_hw_id()
+    - x86/asm: Allow to pass macros to __ASM_FORM()
+    - x86: xen: kvm: Gather the definition of emulate prefixes
+    - x86: xen: insn: Decode Xen and KVM emulate-prefix signature
+    - x86: kprobes: Prohibit probing on instruction which has emulate prefix
+    - KVM: x86/svm: Account for family 17h event renumberings in
+      amd_pmc_perf_hw_id
+    - Bluetooth: Fix the creation of hdev->name
+    - mm: fix missing cache flush for all tail pages of compound page
+    - mm: hugetlb: fix missing cache flush in copy_huge_page_from_user()
+    - mm: userfaultfd: fix missing cache flush in mcopy_atomic_pte() and
+      __mcopy_atomic()
+    - Linux 5.4.194
+  * Focal update: v5.4.193 upstream stable release (LP: #1979566)
+    - MIPS: Fix CP0 counter erratum detection for R4k CPUs
+    - parisc: Merge model and model name into one line in /proc/cpuinfo
+    - ALSA: fireworks: fix wrong return count shorter than expected by 4 bytes
+    - gpiolib: of: fix bounds check for 'gpio-reserved-ranges'
+    - Revert "SUNRPC: attempt AF_LOCAL connect on setup"
+    - firewire: fix potential uaf in outbound_phy_packet_callback()
+    - firewire: remove check of list iterator against head past the loop body
+    - firewire: core: extend card->lock in fw_core_handle_bus_reset
+    - ACPICA: Always create namespace nodes using acpi_ns_create_node()
+    - genirq: Synchronize interrupt thread startup
+    - ASoC: da7219: Fix change notifications for tone generator frequency
+    - ASoC: wm8958: Fix change notifications for DSP controls
+    - ASoC: meson: Fix event generation for G12A tohdmi mux
+    - s390/dasd: fix data corruption for ESE devices
+    - s390/dasd: prevent double format of tracks for ESE devices
+    - s390/dasd: Fix read for ESE with blksize < 4k
+    - s390/dasd: Fix read inconsistency for ESE DASD devices
+    - can: grcan: grcan_close(): fix deadlock
+    - can: grcan: use ofdev->dev when allocating DMA memory
+    - nfc: replace improper check device_is_registered() in netlink related
+      functions
+    - NFC: netlink: fix sleep in atomic bug when firmware download timeout
+    - hwmon: (adt7470) Fix warning on module removal
+    - ASoC: dmaengine: Restore NULL prepare_slave_config() callback
+    - RDMA/siw: Fix a condition race issue in MPA request processing
+    - net: ethernet: mediatek: add missing of_node_put() in mtk_sgmii_init()
+    - net: stmmac: dwmac-sun8i: add missing of_node_put() in
+      sun8i_dwmac_register_mdio_mux()
+    - net: emaclite: Add error handling for of_address_to_resource()
+    - selftests: mirror_gre_bridge_1q: Avoid changing PVID while interface is
+      operational
+    - bnxt_en: Fix possible bnxt_open() failure caused by wrong RFS flag
+    - smsc911x: allow using IRQ0
+    - btrfs: always log symlinks in full mode
+    - net: igmp: respect RCU rules in ip_mc_source() and ip_mc_msfilter()
+    - drm/amdkfd: Use drm_priv to pass VM from KFD to amdgpu
+    - NFSv4: Don't invalidate inode attributes on delegation return
+    - kvm: x86/cpuid: Only provide CPUID leaf 0xA if host has architectural PMU
+    - x86/kvm: Preserve BSP MSR_KVM_POLL_CONTROL across suspend/resume
+    - KVM: LAPIC: Enable timer posted-interrupt only when mwait/hlt is advertised
+    - net: ipv6: ensure we call ipv6_mc_down() at most once
+    - block-map: add __GFP_ZERO flag for alloc_page in function bio_copy_kern
+    - mm: fix unexpected zeroed page mapping with zram swap
+    - ALSA: pcm: Fix races among concurrent hw_params and hw_free calls
+    - ALSA: pcm: Fix races among concurrent read/write and buffer changes
+    - ALSA: pcm: Fix races among concurrent prepare and hw_params/hw_free calls
+    - ALSA: pcm: Fix races among concurrent prealloc proc writes
+    - ALSA: pcm: Fix potential AB/BA lock with buffer_mutex and mmap_lock
+    - tcp: make sure treq->af_specific is initialized
+    - dm: fix mempool NULL pointer race when completing IO
+    - dm: interlock pending dm_io and dm_wait_for_bios_completion
+    - PCI: aardvark: Clear all MSIs at setup
+    - PCI: aardvark: Fix reading MSI interrupt number
+    - mmc: rtsx: add 74 Clocks in power on flow
+    - Linux 5.4.193
+  * CVE-2022-1679
+    - SAUCE: ath9k: fix use-after-free in ath9k_hif_usb_rx_cb
+  * CVE-2022-28893
+    - SUNRPC: Ensure we flush any closed sockets before xs_xprt_free()
+    - SUNRPC: Don't leak sockets in xs_local_connect()
+  * CVE-2022-1734
+    - nfc: nfcmrvl: main: reorder destructive operations in
+      nfcmrvl_nci_unregister_dev to avoid bugs
+  * CVE-2022-1652
+    - floppy: use a statically allocated error counter
+
+  [ Ubuntu: 5.4.0-122.138 ]
+
+  * focal/linux: 5.4.0-122.138 -proposed tracker (LP: #1979489)
+  * Remove SAUCE patches from test_vxlan_under_vrf.sh in net of
+    ubuntu_kernel_selftests (LP: #1975691)
+    - Revert "UBUNTU: SAUCE: selftests: net: Don't fail test_vxlan_under_vrf on
+      xfail"
+    - Revert "UBUNTU: SAUCE: selftests: net: Make test for VXLAN underlay in non-
+      default VRF an expected failure"
+  * Enable Asus USB-BT500 Bluetooth dongle(0b05:190e) (LP: #1976613)
+    - Bluetooth: btusb: Add flag to define wideband speech capability
+    - Bluetooth: btrtl: Add support for RTL8761B
+    - Bluetooth: btusb: Add 0x0b05:0x190e Realtek 8761BU (ASUS BT500) device.
+  * [UBUNTU 20.04] rcu stalls with many storage key guests (LP: #1975582)
+    - s390/gmap: voluntarily schedule during key setting
+    - s390/mm: use non-quiescing sske for KVM switch to keyed guest
+  * Ubuntu 5.4.0-117.132-generic 5.4.189 has BUG: kernel NULL pointer
+    dereference, address: 0000000000000034 (LP: #1978719)
+    - mm: rmap: explicitly reset vma->anon_vma in unlink_anon_vmas()
+  * Focal update: upstream stable patchset v5.4.192 (LP: #1979014)
+    - floppy: disable FDRAWCMD by default
+    - [Config] updateconfigs for BLK_DEV_FD_RAWCMD
+    - hamradio: defer 6pack kfree after unregister_netdev
+    - hamradio: remove needs_free_netdev to avoid UAF
+    - lightnvm: disable the subsystem
+    - [Config] updateconfigs for NVM, NVM_PBLK
+    - usb: mtu3: fix USB 3.0 dual-role-switch from device to host
+    - USB: quirks: add a Realtek card reader
+    - USB: quirks: add STRING quirk for VCOM device
+    - USB: serial: whiteheat: fix heap overflow in WHITEHEAT_GET_DTR_RTS
+    - USB: serial: cp210x: add PIDs for Kamstrup USB Meter Reader
+    - USB: serial: option: add support for Cinterion MV32-WA/MV32-WB
+    - USB: serial: option: add Telit 0x1057, 0x1058, 0x1075 compositions
+    - xhci: stop polling roothubs after shutdown
+    - xhci: increase usb U3 -> U0 link resume timeout from 100ms to 500ms
+    - iio: dac: ad5592r: Fix the missing return value.
+    - iio: dac: ad5446: Fix read_raw not returning set value
+    - iio: magnetometer: ak8975: Fix the error handling in ak8975_power_on()
+    - usb: misc: fix improper handling of refcount in uss720_probe()
+    - usb: typec: ucsi: Fix role swapping
+    - usb: gadget: uvc: Fix crash when encoding data for usb request
+    - usb: gadget: configfs: clear deactivation flag in
+      configfs_composite_unbind()
+    - usb: dwc3: core: Fix tx/rx threshold settings
+    - usb: dwc3: gadget: Return proper request status
+    - serial: imx: fix overrun interrupts in DMA mode
+    - serial: 8250: Also set sticky MCR bits in console restoration
+    - serial: 8250: Correct the clock for EndRun PTP/1588 PCIe device
+    - arch_topology: Do not set llc_sibling if llc_id is invalid
+    - hex2bin: make the function hex_to_bin constant-time
+    - hex2bin: fix access beyond string end
+    - video: fbdev: udlfb: properly check endpoint type
+    - arm64: dts: meson: remove CPU opps below 1GHz for G12B boards
+    - arm64: dts: meson: remove CPU opps below 1GHz for SM1 boards
+    - mtd: rawnand: fix ecc parameters for mt7622
+    - USB: Fix xhci event ring dequeue pointer ERDP update issue
+    - ARM: dts: imx6qdl-apalis: Fix sgtl5000 detection issue
+    - phy: samsung: Fix missing of_node_put() in exynos_sata_phy_probe
+    - phy: samsung: exynos5250-sata: fix missing device put in probe error paths
+    - ARM: OMAP2+: Fix refcount leak in omap_gic_of_init
+    - phy: ti: omap-usb2: Fix error handling in omap_usb2_enable_clocks
+    - ARM: dts: at91: Map MCLK for wm8731 on at91sam9g20ek
+    - phy: mapphone-mdm6600: Fix PM error handling in phy_mdm6600_probe
+    - phy: ti: Add missing pm_runtime_disable() in serdes_am654_probe
+    - ARM: dts: Fix mmc order for omap3-gta04
+    - ARM: dts: am3517-evm: Fix misc pinmuxing
+    - ARM: dts: logicpd-som-lv: Fix wrong pinmuxing on OMAP35
+    - ipvs: correctly print the memory size of ip_vs_conn_tab
+    - mtd: rawnand: Fix return value check of wait_for_completion_timeout
+    - bpf, lwt: Fix crash when using bpf_skb_set_tunnel_key() from bpf_xmit lwt
+      hook
+    - tcp: md5: incorrect tcp_header_len for incoming connections
+    - tcp: ensure to use the most recently sent skb when filling the rate sample
+    - sctp: check asoc strreset_chunk in sctp_generate_reconf_event
+    - ARM: dts: imx6ull-colibri: fix vqmmc regulator
+    - arm64: dts: imx8mn-ddr4-evk: Describe the 32.768 kHz PMIC clock
+    - pinctrl: pistachio: fix use of irq_of_parse_and_map()
+    - cpufreq: fix memory leak in sun50i_cpufreq_nvmem_probe
+    - net: hns3: add validity check for message data length
+    - net/smc: sync err code when tcp connection was refused
+    - ip_gre: Make o_seqno start from 0 in native mode
+    - tcp: fix potential xmit stalls caused by TCP_NOTSENT_LOWAT
+    - bus: sunxi-rsb: Fix the return value of sunxi_rsb_device_create()
+    - clk: sunxi: sun9i-mmc: check return value after calling
+      platform_get_resource()
+    - net: bcmgenet: hide status block before TX timestamping
+    - net: dsa: lantiq_gswip: Don't set GSWIP_MII_CFG_RMII_CLK
+    - drm/amd/display: Fix memory leak in dcn21_clock_source_create
+    - tls: Skip tls_append_frag on zero copy size
+    - bnx2x: fix napi API usage sequence
+    - ixgbe: ensure IPsec VF<->PF compatibility
+    - tcp: fix F-RTO may not work correctly when receiving DSACK
+    - ASoC: wm8731: Disable the regulator when probing fails
+    - ip6_gre: Avoid updating tunnel->tun_hlen in __gre6_xmit()
+    - x86: __memcpy_flushcache: fix wrong alignment if size > 2^32
+    - cifs: destage any unwritten data to the server before calling
+      copychunk_write
+    - drivers: net: hippi: Fix deadlock in rr_close()
+    - net: ethernet: stmmac: fix write to sgmii_adapter_base
+    - x86/cpu: Load microcode during restore_processor_state()
+    - tty: n_gsm: fix wrong signal octet encoding in convergence layer type 2
+    - tty: n_gsm: fix malformed counter for out of frame data
+    - netfilter: nft_socket: only do sk lookups when indev is available
+    - tty: n_gsm: fix insufficient txframe size
+    - tty: n_gsm: fix missing explicit ldisc flush
+    - tty: n_gsm: fix wrong command retry handling
+    - tty: n_gsm: fix wrong command frame length field encoding
+    - tty: n_gsm: fix incorrect UA handling
+    - hugetlbfs: get unmapped area below TASK_UNMAPPED_BASE for hugetlbfs
+    - mm, hugetlb: allow for "high" userspace addresses
+    - Linux 5.4.192
+  * CVE-2022-1789
+    - KVM: x86/mmu: fix NULL pointer dereference on guest INVPCID
+  * Focal update: v5.4.191 upstream stable release (LP: #1976116)
+    - etherdevice: Adjust ether_addr* prototypes to silence -Wstringop-overead
+    - mm: page_alloc: fix building error on -Werror=array-compare
+    - tracing: Dump stacktrace trigger to the corresponding instance
+    - gfs2: assign rgrp glock before compute_bitstructs
+    - tcp: fix race condition when creating child sockets from syncookies
+    - tcp: Fix potential use-after-free due to double kfree()
+    - ALSA: usb-audio: Clear MIDI port active flag after draining
+    - ASoC: atmel: Remove system clock tree configuration for at91sam9g20ek
+    - ASoC: msm8916-wcd-digital: Check failure for devm_snd_soc_register_component
+    - dmaengine: imx-sdma: Fix error checking in sdma_event_remap
+    - dmaengine: mediatek:Fix PM usage reference leak of
+      mtk_uart_apdma_alloc_chan_resources
+    - igc: Fix infinite loop in release_swfw_sync
+    - igc: Fix BUG: scheduling while atomic
+    - rxrpc: Restore removed timer deletion
+    - net/smc: Fix sock leak when release after smc_shutdown()
+    - net/packet: fix packet_sock xmit return value checking
+    - net/sched: cls_u32: fix possible leak in u32_init_knode()
+    - l3mdev: l3mdev_master_upper_ifindex_by_index_rcu should be using
+      netdev_master_upper_dev_get_rcu
+    - netlink: reset network and mac headers in netlink_dump()
+    - selftests: mlxsw: vxlan_flooding: Prevent flooding of unwanted packets
+    - ARM: vexpress/spc: Avoid negative array index when !SMP
+    - reset: tegra-bpmp: Restore Handle errors in BPMP response
+    - platform/x86: samsung-laptop: Fix an unsigned comparison which can never be
+      negative
+    - ALSA: usb-audio: Fix undefined behavior due to shift overflowing the
+      constant
+    - vxlan: fix error return code in vxlan_fdb_append
+    - cifs: Check the IOCB_DIRECT flag, not O_DIRECT
+    - mt76: Fix undefined behavior due to shift overflowing the constant
+    - brcmfmac: sdio: Fix undefined behavior due to shift overflowing the constant
+    - dpaa_eth: Fix missing of_node_put in dpaa_get_ts_info()
+    - drm/msm/mdp5: check the return of kzalloc()
+    - net: macb: Restart tx only if queue pointer is lagging
+    - scsi: qedi: Fix failed disconnect handling
+    - stat: fix inconsistency between struct stat and struct compat_stat
+    - EDAC/synopsys: Read the error count from the correct register
+    - oom_kill.c: futex: delay the OOM reaper to allow time for proper futex
+      cleanup
+    - ata: pata_marvell: Check the 'bmdma_addr' beforing reading
+    - dma: at_xdmac: fix a missing check on list iterator
+    - drm/panel/raspberrypi-touchscreen: Avoid NULL deref if not initialised
+    - drm/panel/raspberrypi-touchscreen: Initialise the bridge in prepare
+    - KVM: PPC: Fix TCE handling for VFIO
+    - drm/vc4: Use pm_runtime_resume_and_get to fix pm_runtime_get_sync() usage
+    - powerpc/perf: Fix power9 event alternatives
+    - xtensa: patch_text: Fixup last cpu should be master
+    - xtensa: fix a7 clobbering in coprocessor context load/store
+    - openvswitch: fix OOB access in reserve_sfa_size()
+    - ASoC: soc-dapm: fix two incorrect uses of list iterator
+    - e1000e: Fix possible overflow in LTR decoding
+    - ARC: entry: fix syscall_trace_exit argument
+    - arm_pmu: Validate single/group leader events
+    - ext4: fix symlink file size not match to file content
+    - ext4: fix use-after-free in ext4_search_dir
+    - ext4, doc: fix incorrect h_reserved size
+    - ext4: fix overhead calculation to account for the reserved gdt blocks
+    - ext4: force overhead calculation if the s_overhead_cluster makes no sense
+    - jbd2: fix a potential race while discarding reserved buffers after an abort
+    - spi: atmel-quadspi: Fix the buswidth adjustment between spi-mem and
+      controller
+    - staging: ion: Prevent incorrect reference counting behavour
+    - block/compat_ioctl: fix range check in BLKGETSIZE
+    - Linux 5.4.191
+  * Focal update: v5.4.190 upstream stable release (LP: #1973085)
+    - memory: atmel-ebi: Fix missing of_node_put in atmel_ebi_probe
+    - net/sched: flower: fix parsing of ethertype following VLAN header
+    - veth: Ensure eth header is in skb's linear part
+    - gpiolib: acpi: use correct format characters
+    - mlxsw: i2c: Fix initialization error flow
+    - net/sched: fix initialization order when updating chain 0 head
+    - net: ethernet: stmmac: fix altr_tse_pcs function when using a fixed-link
+    - net/sched: taprio: Check if socket flags are valid
+    - cfg80211: hold bss_lock while updating nontrans_list
+    - drm/msm/dsi: Use connector directly in msm_dsi_manager_connector_init()
+    - net/smc: Fix NULL pointer dereference in smc_pnet_find_ib()
+    - sctp: Initialize daddr on peeled off socket
+    - testing/selftests/mqueue: Fix mq_perf_tests to free the allocated cpu set
+    - nfc: nci: add flush_workqueue to prevent uaf
+    - cifs: potential buffer overflow in handling symlinks
+    - drm/amd: Add USBC connector ID
+    - drm/amd/display: fix audio format not updated after edid updated
+    - drm/amd/display: Update VTEM Infopacket definition
+    - drm/amdkfd: Fix Incorrect VMIDs passed to HWS
+    - drm/amdkfd: Check for potential null return of kmalloc_array()
+    - Drivers: hv: vmbus: Prevent load re-ordering when reading ring buffer
+    - scsi: target: tcmu: Fix possible page UAF
+    - scsi: ibmvscsis: Increase INITIAL_SRP_LIMIT to 1024
+    - ata: libata-core: Disable READ LOG DMA EXT for Samsung 840 EVOs
+    - gpu: ipu-v3: Fix dev_dbg frequency output
+    - regulator: wm8994: Add an off-on delay for WM8994 variant
+    - arm64: alternatives: mark patch_alternative() as `noinstr`
+    - tlb: hugetlb: Add more sizes to tlb_remove_huge_tlb_entry
+    - net: usb: aqc111: Fix out-of-bounds accesses in RX fixup
+    - drm/amd/display: Fix allocate_mst_payload assert on resume
+    - powerpc: Fix virt_addr_valid() for 64-bit Book3E & 32-bit
+    - scsi: mvsas: Add PCI ID of RocketRaid 2640
+    - scsi: megaraid_sas: Target with invalid LUN ID is deleted during scan
+    - drivers: net: slip: fix NPD bug in sl_tx_timeout()
+    - perf/imx_ddr: Fix undefined behavior due to shift overflowing the constant
+    - mm, page_alloc: fix build_zonerefs_node()
+    - mm: kmemleak: take a full lowmem check in kmemleak_*_phys()
+    - gcc-plugins: latent_entropy: use /dev/urandom
+    - ath9k: Properly clear TX status area before reporting to mac80211
+    - ath9k: Fix usage of driver-private space in tx_info
+    - btrfs: remove unused variable in btrfs_{start,write}_dirty_block_groups()
+    - btrfs: mark resumed async balance as writing
+    - ALSA: hda/realtek: Add quirk for Clevo PD50PNT
+    - ALSA: pcm: Test for "silence" field in struct "pcm_format_data"
+    - ipv6: fix panic when forwarding a pkt with no in6 dev
+    - drm/amd/display: don't ignore alpha property on pre-multiplied mode
+    - genirq/affinity: Consider that CPUs on nodes can be unbalanced
+    - tick/nohz: Use WARN_ON_ONCE() to prevent console saturation
+    - ARM: davinci: da850-evm: Avoid NULL pointer dereference
+    - dm integrity: fix memory corruption when tag_size is less than digest size
+    - smp: Fix offline cpu check in flush_smp_call_function_queue()
+    - i2c: pasemi: Wait for write xfers to finish
+    - dma-direct: avoid redundant memory sync for swiotlb
+    - ax25: add refcount in ax25_dev to avoid UAF bugs
+    - ax25: fix reference count leaks of ax25_dev
+    - ax25: fix UAF bugs of net_device caused by rebinding operation
+    - ax25: Fix refcount leaks caused by ax25_cb_del()
+    - ax25: fix UAF bug in ax25_send_control()
+    - ax25: fix NPD bug in ax25_disconnect
+    - ax25: Fix NULL pointer dereferences in ax25 timers
+    - ax25: Fix UAF bugs in ax25 timers
+    - Linux 5.4.190
+
+  [ Ubuntu: 5.4.0-121.137 ]
+
+  * focal/linux: 5.4.0-121.137 -proposed tracker (LP: #1978666)
+  * Packaging resync (LP: #1786013)
+    - debian/dkms-versions -- update from kernel-versions (main/2022.05.30)
+  * CVE-2022-28388
+    - can: usb_8dev: usb_8dev_start_xmit(): fix double dev_kfree_skb() in error
+      path
+  * test_vxlan_under_vrf.sh in net from ubuntu_kernel_selftests failed (Check VM
+    connectivity through VXLAN (underlay in the default VRF) [FAIL])
+    (LP: #1871015)
+    - selftests: net: test_vxlan_under_vrf: fix HV connectivity test
+  * [UBUNTU 20.04] CPU-MF: add extended counter set definitions for new IBM z16
+    (LP: #1974433)
+    - s390/cpumf: add new extended counter set for IBM z16
+  * [UBUNTU 20.04] KVM nesting support leaks too much memory, might result in
+    stalls during cleanup (LP: #1974017)
+    - KVM: s390: vsie/gmap: reduce gmap_rmap overhead
+  * [UBUNTU 20.04] Null Pointer issue in nfs code running Ubuntu on IBM Z
+    (LP: #1968096)
+    - NFS: Fix up nfs_ctx_key_to_expire()
+
+  [ Ubuntu: 5.4.0-120.136 ]
+
+  * CVE-2022-21123 // CVE-2022-21125 // CVE-2022-21166
+    - cpu/speculation: Add prototype for cpu_show_srbds()
+    - x86/cpu: Add Jasper Lake to Intel family
+    - x86/cpu: Add Lakefield, Alder Lake and Rocket Lake models to the to Intel
+      CPU family
+    - x86/cpu: Add another Alder Lake CPU to the Intel family
+    - Documentation: Add documentation for Processor MMIO Stale Data
+    - x86/speculation/mmio: Enumerate Processor MMIO Stale Data bug
+    - x86/speculation: Add a common function for MD_CLEAR mitigation update
+    - x86/speculation/mmio: Add mitigation for Processor MMIO Stale Data
+    - x86/bugs: Group MDS, TAA & Processor MMIO Stale Data mitigations
+    - x86/speculation/mmio: Enable CPU Fill buffer clearing on idle
+    - x86/speculation/mmio: Add sysfs reporting for Processor MMIO Stale Data
+    - x86/speculation/srbds: Update SRBDS mitigation selection
+    - x86/speculation/mmio: Reuse SRBDS mitigation for SBDS
+    - KVM: x86/speculation: Disable Fill buffer clear within guests
+    - x86/speculation/mmio: Print SMT warning
+
+  [ Ubuntu: 5.4.0-117.132 ]
+
+  * CVE-2022-1966
+    - netfilter: nf_tables: add nft_set_elem_expr_alloc()
+    - netfilter: nf_tables: disallow non-stateful expression in sets earlier
+
+  [ Ubuntu: 5.4.0-115.129 ]
+
+  * CVE-2022-21499
+    - SAUCE: debug: Lock down kgdb
+
+  [ Ubuntu: 5.4.0-114.128 ]
+
+  * focal/linux: 5.4.0-114.128 -proposed tracker (LP: #1974391)
+  * 32 GT/s PCI link speeds reporting "Unknown speed" in sysfs (LP: #1970798)
+    - PCI: Add 32 GT/s decoding in some macros
+    - PCI: Add pci_speed_string()
+    - PCI: Use pci_speed_string() for all PCI/PCI-X/PCIe strings
+    - PCI: Add PCIE_LNKCAP2_SLS2SPEED() macro
+  * issuing invalid ioctl to /dev/vsock may spam dmesg (LP: #1971480)
+    - vsock: remove ratelimit unknown ioctl message
+  * config CONFIG_HISI_PMU for  kunpeng920 (LP: #1956086)
+    - drivers/perf: hisi: Permit modular builds of HiSilicon uncore drivers
+    - [Config] CONFIG_HISI_PMU=m
+  * Focal update: v5.4.189 upstream stable release (LP: #1971497)
+    - swiotlb: fix info leak with DMA_FROM_DEVICE
+    - USB: serial: pl2303: add IBM device IDs
+    - USB: serial: simple: add Nokia phone driver
+    - netdevice: add the case if dev is NULL
+    - HID: logitech-dj: add new lightspeed receiver id
+    - xfrm: fix tunnel model fragmentation behavior
+    - virtio_console: break out of buf poll on remove
+    - ethernet: sun: Free the coherent when failing in probing
+    - spi: Fix invalid sgs value
+    - net:mcf8390: Use platform_get_irq() to get the interrupt
+    - spi: Fix erroneous sgs value with min_t()
+    - af_key: add __GFP_ZERO flag for compose_sadb_supported in function
+      pfkey_register
+    - net: dsa: microchip: add spi_device_id tables
+    - iommu/iova: Improve 32-bit free space estimate
+    - tpm: fix reference counting for struct tpm_chip
+    - block: Add a helper to validate the block size
+    - virtio-blk: Use blk_validate_block_size() to validate block size
+    - USB: usb-storage: Fix use of bitfields for hardware data in ene_ub6250.c
+    - xhci: fix runtime PM imbalance in USB2 resume
+    - xhci: make xhci_handshake timeout for xhci_reset() adjustable
+    - xhci: fix uninitialized string returned by xhci_decode_ctrl_ctx()
+    - coresight: Fix TRCCONFIGR.QE sysfs interface
+    - iio: afe: rescale: use s64 for temporary scale calculations
+    - iio: inkern: apply consumer scale on IIO_VAL_INT cases
+    - iio: inkern: apply consumer scale when no channel scale is available
+    - iio: inkern: make a best effort on offset calculation
+    - greybus: svc: fix an error handling bug in gb_svc_hello()
+    - clk: uniphier: Fix fixed-rate initialization
+    - KEYS: fix length validation in keyctl_pkey_params_get_2()
+    - Documentation: add link to stable release candidate tree
+    - Documentation: update stable tree link
+    - HID: intel-ish-hid: Use dma_alloc_coherent for firmware update
+    - SUNRPC: avoid race between mod_timer() and del_timer_sync()
+    - NFSD: prevent underflow in nfssvc_decode_writeargs()
+    - NFSD: prevent integer overflow on 32 bit systems
+    - f2fs: fix to unlock page correctly in error path of is_alive()
+    - f2fs: quota: fix loop condition at f2fs_quota_sync()
+    - f2fs: fix to do sanity check on .cp_pack_total_block_count
+    - pinctrl: samsung: drop pin banks references on error paths
+    - spi: mxic: Fix the transmit path
+    - jffs2: fix use-after-free in jffs2_clear_xattr_subsystem
+    - jffs2: fix memory leak in jffs2_do_mount_fs
+    - jffs2: fix memory leak in jffs2_scan_medium
+    - mm/pages_alloc.c: don't create ZONE_MOVABLE beyond the end of a node
+    - mm: invalidate hwpoison page cache page in fault path
+    - mempolicy: mbind_range() set_policy() after vma_merge()
+    - scsi: libsas: Fix sas_ata_qc_issue() handling of NCQ NON DATA commands
+    - qed: display VF trust config
+    - qed: validate and restrict untrusted VFs vlan promisc mode
+    - riscv: Fix fill_callchain return value
+    - Revert "Input: clear BTN_RIGHT/MIDDLE on buttonpads"
+    - ALSA: cs4236: fix an incorrect NULL check on list iterator
+    - ALSA: hda/realtek: Fix audio regression on Mi Notebook Pro 2020
+    - mm,hwpoison: unmap poisoned page before invalidation
+    - mm/kmemleak: reset tag when compare object pointer
+    - drbd: fix potential silent data corruption
+    - powerpc/kvm: Fix kvm_use_magic_page
+    - udp: call udp_encap_enable for v6 sockets when enabling encap
+    - ACPI: properties: Consistently return -ENOENT if there are no more
+      references
+    - drivers: hamradio: 6pack: fix UAF bug caused by mod_timer()
+    - mailbox: tegra-hsp: Flush whole channel
+    - block: don't merge across cgroup boundaries if blkcg is enabled
+    - drm/edid: check basic audio support on CEA extension block
+    - video: fbdev: sm712fb: Fix crash in smtcfb_read()
+    - video: fbdev: atari: Atari 2 bpp (STe) palette bugfix
+    - ARM: dts: at91: sama5d2: Fix PMERRLOC resource size
+    - ARM: dts: exynos: fix UART3 pins configuration in Exynos5250
+    - ARM: dts: exynos: add missing HDMI supplies on SMDK5250
+    - ARM: dts: exynos: add missing HDMI supplies on SMDK5420
+    - carl9170: fix missing bit-wise or operator for tx_params
+    - thermal: int340x: Increase bitmap size
+    - lib/raid6/test: fix multiple definition linking error
+    - crypto: rsa-pkcs1pad - correctly get hash from source scatterlist
+    - crypto: rsa-pkcs1pad - restore signature length check
+    - crypto: rsa-pkcs1pad - fix buffer overread in pkcs1pad_verify_complete()
+    - DEC: Limit PMAX memory probing to R3k systems
+    - media: davinci: vpif: fix unbalanced runtime PM get
+    - xtensa: fix stop_machine_cpuslocked call in patch_text
+    - xtensa: fix xtensa_wsr always writing 0
+    - brcmfmac: firmware: Allocate space for default boardrev in nvram
+    - brcmfmac: pcie: Release firmwares in the brcmf_pcie_setup error path
+    - brcmfmac: pcie: Replace brcmf_pcie_copy_mem_todev with memcpy_toio
+    - brcmfmac: pcie: Fix crashes due to early IRQs
+    - PCI: pciehp: Clear cmd_busy bit in polling mode
+    - regulator: qcom_smd: fix for_each_child.cocci warnings
+    - crypto: authenc - Fix sleep in atomic context in decrypt_tail
+    - crypto: mxs-dcp - Fix scatterlist processing
+    - spi: tegra114: Add missing IRQ check in tegra_spi_probe
+    - selftests/x86: Add validity check and allow field splitting
+    - audit: log AUDIT_TIME_* records only from rules
+    - crypto: ccree - don't attempt 0 len DMA mappings
+    - spi: pxa2xx-pci: Balance reference count for PCI DMA device
+    - hwmon: (pmbus) Add mutex to regulator ops
+    - hwmon: (sch56xx-common) Replace WDOG_ACTIVE with WDOG_HW_RUNNING
+    - block: don't delete queue kobject before its children
+    - PM: hibernate: fix __setup handler error handling
+    - PM: suspend: fix return value of __setup handler
+    - hwrng: atmel - disable trng on failure path
+    - crypto: vmx - add missing dependencies
+    - clocksource/drivers/timer-of: Check return value of of_iomap in
+      timer_of_base_init()
+    - ACPI: APEI: fix return value of __setup handlers
+    - crypto: ccp - ccp_dmaengine_unregister release dma channels
+    - hwmon: (pmbus) Add Vin unit off handling
+    - clocksource: acpi_pm: fix return value of __setup handler
+    - sched/debug: Remove mpol_get/put and task_lock/unlock from sched_show_numa
+    - perf/core: Fix address filter parser for multiple filters
+    - perf/x86/intel/pt: Fix address filter config for 32-bit kernel
+    - f2fs: fix missing free nid in f2fs_handle_failed_inode
+    - f2fs: fix to avoid potential deadlock
+    - media: bttv: fix WARNING regression on tunerless devices
+    - media: coda: Fix missing put_device() call in coda_get_vdoa_data
+    - media: hantro: Fix overfill bottom register field name
+    - media: aspeed: Correct value for h-total-pixels
+    - video: fbdev: smscufx: Fix null-ptr-deref in ufx_usb_probe()
+    - video: fbdev: atmel_lcdfb: fix an error code in atmel_lcdfb_probe()
+    - video: fbdev: fbcvt.c: fix printing in fb_cvt_print_name()
+    - ARM: dts: qcom: ipq4019: fix sleep clock
+    - soc: qcom: rpmpd: Check for null return of devm_kcalloc
+    - soc: qcom: aoss: remove spurious IRQF_ONESHOT flags
+    - arm64: dts: qcom: sm8150: Correct TCS configuration for apps rsc
+    - soc: ti: wkup_m3_ipc: Fix IRQ check in wkup_m3_ipc_probe
+    - ARM: dts: imx: Add missing LVDS decoder on M53Menlo
+    - media: video/hdmi: handle short reads of hdmi info frame.
+    - media: em28xx: initialize refcount before kref_get
+    - media: usb: go7007: s2250-board: fix leak in probe()
+    - uaccess: fix nios2 and microblaze get_user_8()
+    - ASoC: rt5663: check the return value of devm_kzalloc() in rt5663_parse_dp()
+    - ASoC: ti: davinci-i2s: Add check for clk_enable()
+    - ALSA: spi: Add check for clk_enable()
+    - arm64: dts: ns2: Fix spi-cpol and spi-cpha property
+    - arm64: dts: broadcom: Fix sata nodename
+    - printk: fix return value of printk.devkmsg __setup handler
+    - ASoC: mxs-saif: Handle errors for clk_enable
+    - ASoC: atmel_ssc_dai: Handle errors for clk_enable
+    - ASoC: soc-compress: prevent the potentially use of null pointer
+    - memory: emif: Add check for setup_interrupts
+    - memory: emif: check the pointer temp in get_device_details()
+    - ALSA: firewire-lib: fix uninitialized flag for AV/C deferred transaction
+    - arm64: dts: rockchip: Fix SDIO regulator supply properties on rk3399-firefly
+    - media: stk1160: If start stream fails, return buffers with
+      VB2_BUF_STATE_QUEUED
+    - ASoC: atmel: Add missing of_node_put() in at91sam9g20ek_audio_probe
+    - ASoC: wm8350: Handle error for wm8350_register_irq
+    - ASoC: fsi: Add check for clk_enable
+    - video: fbdev: omapfb: Add missing of_node_put() in dvic_probe_of
+    - ivtv: fix incorrect device_caps for ivtvfb
+    - ASoC: dmaengine: do not use a NULL prepare_slave_config() callback
+    - ASoC: mxs: Fix error handling in mxs_sgtl5000_probe
+    - ASoC: imx-es8328: Fix error return code in imx_es8328_probe()
+    - ASoC: msm8916-wcd-digital: Fix missing clk_disable_unprepare() in
+      msm8916_wcd_digital_probe
+    - mmc: davinci_mmc: Handle error for clk_enable
+    - ASoC: msm8916-wcd-analog: Fix error handling in pm8916_wcd_analog_spmi_probe
+    - drm/bridge: Fix free wrong object in sii8620_init_rcp_input_dev
+    - drm/bridge: Add missing pm_runtime_disable() in __dw_mipi_dsi_probe
+    - ath10k: fix memory overwrite of the WoWLAN wakeup packet pattern
+    - udmabuf: validate ubuf->pagecount
+    - Bluetooth: hci_serdev: call init_rwsem() before p->open()
+    - mtd: onenand: Check for error irq
+    - mtd: rawnand: gpmi: fix controller timings setting
+    - drm/edid: Don't clear formats if using deep color
+    - drm/amd/display: Fix a NULL pointer dereference in
+      amdgpu_dm_connector_add_common_modes()
+    - ath9k_htc: fix uninit value bugs
+    - KVM: PPC: Fix vmx/vsx mixup in mmio emulation
+    - i40e: don't reserve excessive XDP_PACKET_HEADROOM on XSK Rx to skb
+    - power: reset: gemini-poweroff: Fix IRQ check in gemini_poweroff_probe
+    - ray_cs: Check ioremap return value
+    - powerpc/perf: Don't use perf_hw_context for trace IMC PMU
+    - mt76: mt7603: check sta_rates pointer in mt7603_sta_rate_tbl_update
+    - mt76: mt7615: check sta_rates pointer in mt7615_sta_rate_tbl_update
+    - net: dsa: mv88e6xxx: Enable port policy support on 6097
+    - PCI: aardvark: Fix reading PCI_EXP_RTSTA_PME bit on emulated bridge
+    - power: supply: ab8500: Fix memory leak in ab8500_fg_sysfs_init
+    - HID: i2c-hid: fix GET/SET_REPORT for unnumbered reports
+    - iommu/ipmmu-vmsa: Check for error num after setting mask
+    - drm/amd/display: Add affected crtcs to atomic state for dsc mst unplug
+    - IB/cma: Allow XRC INI QPs to set their local ACK timeout
+    - dax: make sure inodes are flushed before destroy cache
+    - iwlwifi: Fix -EIO error code that is never returned
+    - iwlwifi: mvm: Fix an error code in iwl_mvm_up()
+    - dm crypt: fix get_key_size compiler warning if !CONFIG_KEYS
+    - scsi: pm8001: Fix command initialization in pm80XX_send_read_log()
+    - scsi: pm8001: Fix command initialization in pm8001_chip_ssp_tm_req()
+    - scsi: pm8001: Fix payload initialization in pm80xx_set_thermal_config()
+    - scsi: pm8001: Fix abort all task initialization
+    - drm/amd/display: Remove vupdate_int_entry definition
+    - TOMOYO: fix __setup handlers return values
+    - ext2: correct max file size computing
+    - drm/tegra: Fix reference leak in tegra_dsi_ganged_probe
+    - power: supply: bq24190_charger: Fix bq24190_vbus_is_enabled() wrong false
+      return
+    - scsi: hisi_sas: Change permission of parameter prot_mask
+    - drm/bridge: cdns-dsi: Make sure to to create proper aliases for dt
+    - bpf, arm64: Call build_prologue() first in first JIT pass
+    - bpf, arm64: Feed byte-offset into bpf line info
+    - libbpf: Skip forward declaration when counting duplicated type names
+    - powerpc/Makefile: Don't pass -mcpu=powerpc64 when building 32-bit
+    - KVM: x86: Fix emulation in writing cr8
+    - KVM: x86/emulator: Defer not-present segment check in
+      __load_segment_descriptor()
+    - hv_balloon: rate-limit "Unhandled message" warning
+    - i2c: xiic: Make bus names unique
+    - power: supply: wm8350-power: Handle error for wm8350_register_irq
+    - power: supply: wm8350-power: Add missing free in free_charger_irq
+    - PCI: Reduce warnings on possible RW1C corruption
+    - mips: DEC: honor CONFIG_MIPS_FP_SUPPORT=n
+    - powerpc/sysdev: fix incorrect use to determine if list is empty
+    - mfd: mc13xxx: Add check for mc13xxx_irq_request
+    - selftests/bpf: Make test_lwt_ip_encap more stable and faster
+    - powerpc: 8xx: fix a return value error in mpc8xx_pic_init
+    - vxcan: enable local echo for sent CAN frames
+    - MIPS: RB532: fix return value of __setup handler
+    - mtd: rawnand: atmel: fix refcount issue in atmel_nand_controller_init
+    - RDMA/mlx5: Fix memory leak in error flow for subscribe event routine
+    - bpf, sockmap: Fix memleak in tcp_bpf_sendmsg while sk msg is full
+    - bpf, sockmap: Fix more uncharged while msg has more_data
+    - bpf, sockmap: Fix double uncharge the mem of sk_msg
+    - USB: storage: ums-realtek: fix error code in rts51x_read_mem()
+    - Bluetooth: btmtksdio: Fix kernel oops in btmtksdio_interrupt
+    - af_netlink: Fix shift out of bounds in group mask calculation
+    - i2c: mux: demux-pinctrl: do not deactivate a master that is not active
+    - selftests/bpf/test_lirc_mode2.sh: Exit with proper code
+    - tcp: ensure PMTU updates are processed during fastopen
+    - openvswitch: always update flow key after nat
+    - tipc: fix the timer expires after interval 100ms
+    - mfd: asic3: Add missing iounmap() on error asic3_mfd_probe
+    - mxser: fix xmit_buf leak in activate when LSR == 0xff
+    - pwm: lpc18xx-sct: Initialize driver data and hardware before pwmchip_add()
+    - misc: alcor_pci: Fix an error handling path
+    - staging:iio:adc:ad7280a: Fix handing of device address bit reversing.
+    - pinctrl: renesas: r8a77470: Reduce size for narrow VIN1 channel
+    - clk: qcom: ipq8074: Use floor ops for SDCC1 clock
+    - phy: dphy: Correct lpx parameter and its derivatives(ta_{get,go,sure})
+    - serial: 8250_mid: Balance reference count for PCI DMA device
+    - serial: 8250: Fix race condition in RTS-after-send handling
+    - iio: adc: Add check for devm_request_threaded_irq
+    - NFS: Return valid errors from nfs2/3_decode_dirent()
+    - dma-debug: fix return value of __setup handlers
+    - clk: imx7d: Remove audio_mclk_root_clk
+    - clk: qcom: clk-rcg2: Update logic to calculate D value for RCG
+    - clk: qcom: clk-rcg2: Update the frac table for pixel clock
+    - remoteproc: qcom: Fix missing of_node_put in adsp_alloc_memory_region
+    - remoteproc: qcom_wcnss: Add missing of_node_put() in
+      wcnss_alloc_memory_region
+    - clk: actions: Terminate clk_div_table with sentinel element
+    - clk: loongson1: Terminate clk_div_table with sentinel element
+    - clk: clps711x: Terminate clk_div_table with sentinel element
+    - clk: tegra: tegra124-emc: Fix missing put_device() call in
+      emc_ensure_emc_driver
+    - NFS: remove unneeded check in decode_devicenotify_args()
+    - staging: mt7621-dts: fix LEDs and pinctrl on GB-PC1 devicetree
+    - pinctrl: mediatek: Fix missing of_node_put() in mtk_pctrl_init
+    - pinctrl: mediatek: paris: Fix "argument" argument type for mtk_pinconf_get()
+    - pinctrl: mediatek: paris: Fix pingroup pin config state readback
+    - pinctrl: nomadik: Add missing of_node_put() in nmk_pinctrl_probe
+    - pinctrl/rockchip: Add missing of_node_put() in rockchip_pinctrl_probe
+    - tty: hvc: fix return value of __setup handler
+    - kgdboc: fix return value of __setup handler
+    - kgdbts: fix return value of __setup handler
+    - firmware: google: Properly state IOMEM dependency
+    - driver core: dd: fix return value of __setup handler
+    - jfs: fix divide error in dbNextAG
+    - netfilter: nf_conntrack_tcp: preserve liberal flag in tcp options
+    - NFSv4.1: don't retry BIND_CONN_TO_SESSION on session error
+    - clk: qcom: gcc-msm8994: Fix gpll4 width
+    - clk: Initialize orphan req_rate
+    - xen: fix is_xen_pmu()
+    - net: phy: broadcom: Fix brcm_fet_config_init()
+    - selftests: test_vxlan_under_vrf: Fix broken test case
+    - qlcnic: dcb: default to returning -EOPNOTSUPP
+    - net/x25: Fix null-ptr-deref caused by x25_disconnect
+    - NFSv4/pNFS: Fix another issue with a list iterator pointing to the head
+    - net: dsa: bcm_sf2_cfp: fix an incorrect NULL check on list iterator
+    - lib/test: use after free in register_test_dev_kmod()
+    - LSM: general protection fault in legacy_parse_param
+    - gcc-plugins/stackleak: Exactly match strings instead of prefixes
+    - pinctrl: npcm: Fix broken references to chip->parent_device
+    - block, bfq: don't move oom_bfqq
+    - selinux: use correct type for context length
+    - loop: use sysfs_emit() in the sysfs xxx show()
+    - Fix incorrect type in assignment of ipv6 port for audit
+    - irqchip/qcom-pdc: Fix broken locking
+    - irqchip/nvic: Release nvic_base upon failure
+    - bfq: fix use-after-free in bfq_dispatch_request
+    - ACPICA: Avoid walking the ACPI Namespace if it is not there
+    - lib/raid6/test/Makefile: Use $(pound) instead of \# for Make 4.3
+    - Revert "Revert "block, bfq: honor already-setup queue merges""
+    - ACPI/APEI: Limit printable size of BERT table data
+    - PM: core: keep irq flags in device_pm_check_callbacks()
+    - spi: tegra20: Use of_device_get_match_data()
+    - ext4: don't BUG if someone dirty pages without asking ext4 first
+    - ntfs: add sanity check on allocation size
+    - video: fbdev: nvidiafb: Use strscpy() to prevent buffer overflow
+    - video: fbdev: w100fb: Reset global state
+    - video: fbdev: cirrusfb: check pixclock to avoid divide by zero
+    - video: fbdev: omapfb: acx565akm: replace snprintf with sysfs_emit
+    - ARM: dts: qcom: fix gic_irq_domain_translate warnings for msm8960
+    - ARM: dts: bcm2837: Add the missing L1/L2 cache information
+    - ASoC: madera: Add dependencies on MFD
+    - video: fbdev: omapfb: panel-dsi-cm: Use sysfs_emit() instead of snprintf()
+    - video: fbdev: omapfb: panel-tpo-td043mtea1: Use sysfs_emit() instead of
+      snprintf()
+    - video: fbdev: udlfb: replace snprintf in show functions with sysfs_emit
+    - ASoC: soc-core: skip zero num_dai component in searching dai name
+    - media: cx88-mpeg: clear interrupt status register before streaming video
+    - ARM: tegra: tamonten: Fix I2C3 pad setting
+    - ARM: mmp: Fix failure to remove sram device
+    - video: fbdev: sm712fb: Fix crash in smtcfb_write()
+    - media: Revert "media: em28xx: add missing em28xx_close_extension"
+    - media: hdpvr: initialize dev->worker at hdpvr_register_videodev
+    - mmc: host: Return an error when ->enable_sdio_irq() ops is missing
+    - ALSA: hda/realtek: Add alc256-samsung-headphone fixup
+    - powerpc/lib/sstep: Fix 'sthcx' instruction
+    - powerpc/lib/sstep: Fix build errors with newer binutils
+    - powerpc: Fix build errors with newer binutils
+    - scsi: qla2xxx: Fix stuck session in gpdb
+    - scsi: qla2xxx: Fix wrong FDMI data for 64G adapter
+    - scsi: qla2xxx: Fix warning for missing error code
+    - scsi: qla2xxx: Fix device reconnect in loop topology
+    - scsi: qla2xxx: Add devids and conditionals for 28xx
+    - scsi: qla2xxx: Check for firmware dump already collected
+    - scsi: qla2xxx: Suppress a kernel complaint in qla_create_qpair()
+    - scsi: qla2xxx: Fix disk failure to rediscover
+    - scsi: qla2xxx: Fix incorrect reporting of task management failure
+    - scsi: qla2xxx: Fix hang due to session stuck
+    - scsi: qla2xxx: Fix missed DMA unmap for NVMe ls requests
+    - scsi: qla2xxx: Fix N2N inconsistent PLOGI
+    - scsi: qla2xxx: Reduce false trigger to login
+    - scsi: qla2xxx: Use correct feature type field during RFF_ID processing
+    - KVM: Prevent module exit until all VMs are freed
+    - KVM: x86: fix sending PV IPI
+    - ASoC: SOF: Intel: Fix NULL ptr dereference when ENOMEM
+    - ubifs: rename_whiteout: Fix double free for whiteout_ui->data
+    - ubifs: Fix deadlock in concurrent rename whiteout and inode writeback
+    - ubifs: Add missing iput if do_tmpfile() failed in rename whiteout
+    - ubifs: setflags: Make dirtied_ino_d 8 bytes aligned
+    - ubifs: Fix read out-of-bounds in ubifs_wbuf_write_nolock()
+    - ubifs: rename_whiteout: correct old_dir size computing
+    - XArray: Fix xas_create_range() when multi-order entry present
+    - can: mcba_usb: mcba_usb_start_xmit(): fix double dev_kfree_skb in error path
+    - can: mcba_usb: properly check endpoint type
+    - XArray: Update the LRU list in xas_split()
+    - rtc: check if __rtc_read_time was successful
+    - gfs2: Make sure FITRIM minlen is rounded up to fs block size
+    - net: hns3: fix software vlan talbe of vlan 0 inconsistent with hardware
+    - pinctrl: pinconf-generic: Print arguments for bias-pull-*
+    - pinctrl: nuvoton: npcm7xx: Rename DS() macro to DSTR()
+    - pinctrl: nuvoton: npcm7xx: Use %zu printk format for ARRAY_SIZE()
+    - ASoC: mediatek: mt6358: add missing EXPORT_SYMBOLs
+    - ubi: Fix race condition between ctrl_cdev_ioctl and ubi_cdev_ioctl
+    - ARM: iop32x: offset IRQ numbers by 1
+    - ACPI: CPPC: Avoid out of bounds access when parsing _CPC data
+    - powerpc/kasan: Fix early region not updated correctly
+    - ASoC: soc-compress: Change the check for codec_dai
+    - mm/mmap: return 1 from stack_guard_gap __setup() handler
+    - mm/memcontrol: return 1 from cgroup.memory __setup() handler
+    - mm/usercopy: return 1 from hardened_usercopy __setup() handler
+    - bpf: Fix comment for helper bpf_current_task_under_cgroup()
+    - dt-bindings: mtd: nand-controller: Fix the reg property description
+    - dt-bindings: mtd: nand-controller: Fix a comment in the examples
+    - dt-bindings: spi: mxic: The interrupt property is not mandatory
+    - ubi: fastmap: Return error code if memory allocation fails in add_aeb()
+    - ASoC: topology: Allow TLV control to be either read or write
+    - ARM: dts: spear1340: Update serial node properties
+    - ARM: dts: spear13xx: Update SPI dma properties
+    - um: Fix uml_mconsole stop/go
+    - openvswitch: Fixed nd target mask field in the flow dump.
+    - KVM: x86/mmu: do compare-and-exchange of gPTE via the user address
+    - KVM: x86: Forbid VMM to set SYNIC/STIMER MSRs when SynIC wasn't activated
+    - ubifs: Rectify space amount budget for mkdir/tmpfile operations
+    - rtc: wm8350: Handle error for wm8350_register_irq
+    - riscv module: remove (NOLOAD)
+    - ARM: 9187/1: JIVE: fix return value of __setup handler
+    - KVM: x86/svm: Clear reserved bits written to PerfEvtSeln MSRs
+    - drm: Add orientation quirk for GPD Win Max
+    - ath5k: fix OOB in ath5k_eeprom_read_pcal_info_5111
+    - drm/amd/amdgpu/amdgpu_cs: fix refcount leak of a dma_fence obj
+    - ptp: replace snprintf with sysfs_emit
+    - powerpc: dts: t104xrdb: fix phy type for FMAN 4/5
+    - bpf: Make dst_port field in struct bpf_sock 16-bit wide
+    - scsi: mvsas: Replace snprintf() with sysfs_emit()
+    - scsi: bfa: Replace snprintf() with sysfs_emit()
+    - power: supply: axp20x_battery: properly report current when discharging
+    - ipv6: make mc_forwarding atomic
+    - powerpc: Set crashkernel offset to mid of RMA region
+    - drm/amdgpu: Fix recursive locking warning
+    - PCI: aardvark: Fix support for MSI interrupts
+    - iommu/arm-smmu-v3: fix event handling soft lockup
+    - usb: ehci: add pci device support for Aspeed platforms
+    - PCI: pciehp: Add Qualcomm quirk for Command Completed erratum
+    - power: supply: axp288-charger: Set Vhold to 4.4V
+    - ipv4: Invalidate neighbour for broadcast address upon address addition
+    - dm ioctl: prevent potential spectre v1 gadget
+    - drm/amdkfd: make CRAT table missing message informational only
+    - scsi: pm8001: Fix pm8001_mpi_task_abort_resp()
+    - scsi: aha152x: Fix aha152x_setup() __setup handler return value
+    - net/smc: correct settings of RMB window update limit
+    - mips: ralink: fix a refcount leak in ill_acc_of_setup()
+    - macvtap: advertise link netns via netlink
+    - tuntap: add sanity checks about msg_controllen in sendmsg
+    - bnxt_en: Eliminate unintended link toggle during FW reset
+    - MIPS: fix fortify panic when copying asm exception handlers
+    - scsi: libfc: Fix use after free in fc_exch_abts_resp()
+    - usb: dwc3: omap: fix "unbalanced disables for smps10_out1" on omap5evm
+    - xtensa: fix DTC warning unit_address_format
+    - Bluetooth: Fix use after free in hci_send_acl
+    - netlabel: fix out-of-bounds memory accesses
+    - init/main.c: return 1 from handled __setup() functions
+    - minix: fix bug when opening a file with O_DIRECT
+    - clk: si5341: fix reported clk_rate when output divider is 2
+    - w1: w1_therm: fixes w1_seq for ds28ea00 sensors
+    - NFSv4: Protect the state recovery thread against direct reclaim
+    - xen: delay xen_hvm_init_time_ops() if kdump is boot on vcpu>=32
+    - clk: Enforce that disjoints limits are invalid
+    - SUNRPC/call_alloc: async tasks mustn't block waiting for memory
+    - NFS: swap IO handling is slightly different for O_DIRECT IO
+    - NFS: swap-out must always use STABLE writes.
+    - serial: samsung_tty: do not unlock port->lock for uart_write_wakeup()
+    - virtio_console: eliminate anonymous module_init & module_exit
+    - jfs: prevent NULL deref in diFree
+    - SUNRPC: Fix socket waits for write buffer space
+    - parisc: Fix CPU affinity for Lasi, WAX and Dino chips
+    - parisc: Fix patch code locking and flushing
+    - mm: fix race between MADV_FREE reclaim and blkdev direct IO read
+    - KVM: arm64: Check arm64_get_bp_hardening_data() didn't return NULL
+    - drm/amdgpu: fix off by one in amdgpu_gfx_kiq_acquire()
+    - Drivers: hv: vmbus: Fix potential crash on module unload
+    - scsi: zorro7xx: Fix a resource leak in zorro7xx_remove_one()
+    - net/tls: fix slab-out-of-bounds bug in decrypt_internal
+    - net: ipv4: fix route with nexthop object delete warning
+    - net: stmmac: Fix unset max_speed difference between DT and non-DT platforms
+    - drm/imx: Fix memory leak in imx_pd_connector_get_modes
+    - bnxt_en: reserve space inside receive page for skb_shared_info
+    - IB/rdmavt: add lock to call to rvt_error_qp to prevent a race condition
+    - dpaa2-ptp: Fix refcount leak in dpaa2_ptp_probe
+    - ipv6: Fix stats accounting in ip6_pkt_drop
+    - net: openvswitch: don't send internal clone attribute to the userspace.
+    - rxrpc: fix a race in rxrpc_exit_net()
+    - qede: confirm skb is allocated before using
+    - spi: bcm-qspi: fix MSPI only access with bcm_qspi_exec_mem_op()
+    - bpf: Support dual-stack sockets in bpf_tcp_check_syncookie
+    - drbd: Fix five use after free bugs in get_initial_state
+    - SUNRPC: Handle ENOMEM in call_transmit_status()
+    - SUNRPC: Handle low memory situations in call_status()
+    - perf tools: Fix perf's libperf_print callback
+    - perf session: Remap buf if there is no space for event
+    - Revert "mmc: sdhci-xenon: fix annoying 1.8V regulator warning"
+    - mmc: renesas_sdhi: don't overwrite TAP settings when HS400 tuning is
+      complete
+    - lz4: fix LZ4_decompress_safe_partial read out of bound
+    - mmmremap.c: avoid pointless invalidate_range_start/end on mremap(old_size=0)
+    - mm/mempolicy: fix mpol_new leak in shared_policy_replace
+    - x86/pm: Save the MSR validity status at context setup
+    - x86/speculation: Restore speculation related MSRs during S3 resume
+    - btrfs: fix qgroup reserve overflow the qgroup limit
+    - arm64: patch_text: Fixup last cpu should be master
+    - ata: sata_dwc_460ex: Fix crash due to OOB write
+    - perf: qcom_l2_pmu: fix an incorrect NULL check on list iterator
+    - irqchip/gic-v3: Fix GICR_CTLR.RWP polling
+    - tools build: Filter out options and warnings not supported by clang
+    - tools build: Use $(shell ) instead of `` to get embedded libperl's ccopts
+    - dmaengine: Revert "dmaengine: shdma: Fix runtime PM imbalance on error"
+    - mmc: mmci_sdmmc: Replace sg_dma_xxx macros
+    - mmc: mmci: stm32: correctly check all elements of sg list
+    - mm: don't skip swap entry even if zap_details specified
+    - arm64: module: remove (NOLOAD) from linker script
+    - mm/sparsemem: fix 'mem_section' will never be NULL gcc 12 warning
+    - drm/amdkfd: add missing void argument to function kgd2kfd_init
+    - drm/amdkfd: Fix -Wstrict-prototypes from
+      amdgpu_amdkfd_gfx_10_0_get_functions()
+    - cgroup: Use open-time credentials for process migraton perm checks
+    - cgroup: Allocate cgroup_file_ctx for kernfs_open_file->priv
+    - cgroup: Use open-time cgroup namespace for process migration perm checks
+    - selftests: cgroup: Make cg_create() use 0755 for permission instead of 0644
+    - selftests: cgroup: Test open-time credential usage for migration checks
+    - selftests: cgroup: Test open-time cgroup namespace usage for migration
+      checks
+    - cpuidle: PSCI: Move the `has_lpi` check to the beginning of the function
+    - ACPI: processor idle: Check for architectural support for LPI
+    - Linux 5.4.189
+  * Focal update: v5.4.188 upstream stable release (LP: #1971496)
+    - nfsd: cleanup nfsd_file_lru_dispose()
+    - nfsd: Containerise filecache laundrette
+    - net: ipv6: fix skb_over_panic in __ip6_append_data
+    - tpm: Fix error handling in async work
+    - staging: fbtft: fb_st7789v: reset display before initialization
+    - thermal: int340x: fix memory leak in int3400_notify()
+    - llc: fix netdevice reference leaks in llc_ui_bind()
+    - ALSA: pcm: Add stream lock during PCM reset ioctl operations
+    - ALSA: usb-audio: Add mute TLV for playback volumes on RODE NT-USB
+    - ALSA: cmipci: Restore aux vol on suspend/resume
+    - ALSA: pci: fix reading of swapped values from pcmreg in AC97 codec
+    - drivers: net: xgene: Fix regression in CRC stripping
+    - ASoC: sti: Fix deadlock via snd_pcm_stop_xrun() call
+    - ALSA: oss: Fix PCM OSS buffer allocation overflow
+    - ALSA: hda/realtek - Fix headset mic problem for a HP machine with alc671
+    - ALSA: hda/realtek: Add quirk for ASUS GA402
+    - ACPI / x86: Work around broken XSDT on Advantech DAC-BJ01 board
+    - ACPI: battery: Add device HID and quirk for Microsoft Surface Go 3
+    - ACPI: video: Force backlight native for Clevo NL5xRU and NL5xNU
+    - crypto: qat - disable registration of algorithms
+    - rcu: Don't deboost before reporting expedited quiescent state
+    - mac80211: fix potential double free on mesh join
+    - tpm: use try_get_ops() in tpm-space.c
+    - nds32: fix access_ok() checks in get/put_user
+    - llc: only change llc->dev when bind() succeeds
+    - Linux 5.4.188
+  * Focal update: v5.4.187 upstream stable release (LP: #1971493)
+    - crypto: qcom-rng - ensure buffer for generate is completely filled
+    - ocfs2: fix crash when initialize filecheck kobj fails
+    - efi: fix return value of __setup handlers
+    - net: phy: marvell: Fix invalid comparison in the resume and suspend
+      functions
+    - net/packet: fix slab-out-of-bounds access in packet_recvmsg()
+    - atm: eni: Add check for dma_map_single
+    - hv_netvsc: Add check for kvmalloc_array
+    - drm/panel: simple: Fix Innolux G070Y2-L01 BPP settings
+    - net: handle ARPHRD_PIMREG in dev_is_mac_header_xmit()
+    - net: dsa: Add missing of_node_put() in dsa_port_parse_of
+    - arm64: fix clang warning about TRAMP_VALIAS
+    - usb: gadget: rndis: prevent integer overflow in rndis_set_response()
+    - usb: gadget: Fix use-after-free bug by not setting udc->dev.driver
+    - usb: usbtmc: Fix bug in pipe direction for control transfers
+    - Input: aiptek - properly check endpoint type
+    - perf symbols: Fix symbol size calculation condition
+    - Linux 5.4.187
+  * Focal update: v5.4.186 upstream stable release (LP: #1969678)
+    - Revert "xfrm: state and policy should fail if XFRMA_IF_ID 0"
+    - sctp: fix the processing for INIT chunk
+    - xfrm: Check if_id in xfrm_migrate
+    - xfrm: Fix xfrm migrate issues when address family changes
+    - arm64: dts: rockchip: fix rk3399-puma eMMC HS400 signal integrity
+    - arm64: dts: rockchip: reorder rk3399 hdmi clocks
+    - arm64: dts: agilex: use the compatible "intel,socfpga-agilex-hsotg"
+    - ARM: dts: rockchip: reorder rk322x hmdi clocks
+    - ARM: dts: rockchip: fix a typo on rk3288 crypto-controller
+    - mac80211: refuse aggregations sessions before authorized
+    - MIPS: smp: fill in sibling and core maps earlier
+    - ARM: 9178/1: fix unmet dependency on BITREVERSE for HAVE_ARCH_BITREVERSE
+    - can: rcar_canfd: rcar_canfd_channel_probe(): register the CAN device when
+      fully ready
+    - atm: firestream: check the return value of ioremap() in fs_init()
+    - iwlwifi: don't advertise TWT support
+    - drm/vrr: Set VRR capable prop only if it is attached to connector
+    - nl80211: Update bss channel on channel switch for P2P_CLIENT
+    - tcp: make tcp_read_sock() more robust
+    - sfc: extend the locking on mcdi->seqno
+    - kselftest/vm: fix tests build with old libc
+    - fixup for "arm64 entry: Add macro for reading symbol address from the
+      trampoline"
+    - Linux 5.4.186
+  * Focal update: v5.4.185 upstream stable release (LP: #1969672)
+    - clk: qcom: gdsc: Add support to update GDSC transition delay
+    - arm64: dts: armada-3720-turris-mox: Add missing ethernet0 alias
+    - virtio-blk: Don't use MAX_DISCARD_SEGMENTS if max_discard_seg is zero
+    - net: qlogic: check the return value of dma_alloc_coherent() in
+      qed_vf_hw_prepare()
+    - qed: return status of qed_iov_get_link
+    - drm/sun4i: mixer: Fix P010 and P210 format numbers
+    - ARM: dts: aspeed: Fix AST2600 quad spi group
+    - ethernet: Fix error handling in xemaclite_of_probe
+    - net: ethernet: ti: cpts: Handle error for clk_enable
+    - net: ethernet: lpc_eth: Handle error for clk_enable
+    - ax25: Fix NULL pointer dereference in ax25_kill_by_device
+    - net/mlx5: Fix size field in bufferx_reg struct
+    - net/mlx5: Fix a race on command flush flow
+    - NFC: port100: fix use-after-free in port100_send_complete
+    - selftests: pmtu.sh: Kill tcpdump processes launched by subshell.
+    - gpio: ts4900: Do not set DAT and OE together
+    - gianfar: ethtool: Fix refcount leak in gfar_get_ts_info
+    - net: phy: DP83822: clear MISR2 register to disable interrupts
+    - sctp: fix kernel-infoleak for SCTP sockets
+    - net: bcmgenet: Don't claim WOL when its not available
+    - net-sysfs: add check for netdevice being present to speed_show
+    - Revert "xen-netback: remove 'hotplug-status' once it has served its purpose"
+    - Revert "xen-netback: Check for hotplug-status existence before watching"
+    - ipv6: prevent a possible race condition with lifetimes
+    - tracing: Ensure trace buffer is at least 4096 bytes large
+    - selftest/vm: fix map_fixed_noreplace test failure
+    - selftests/memfd: clean up mapping in mfd_fail_write
+    - ARM: Spectre-BHB: provide empty stub for non-config
+    - fuse: fix pipe buffer lifetime for direct_io
+    - staging: gdm724x: fix use after free in gdm_lte_rx()
+    - net: macb: Fix lost RX packet wakeup race in NAPI receive
+    - mmc: meson: Fix usage of meson_mmc_post_req()
+    - riscv: Fix auipc+jalr relocation range checks
+    - arm64: dts: marvell: armada-37xx: Remap IO space to bus address 0x0
+    - virtio: unexport virtio_finalize_features
+    - virtio: acknowledge all features before access
+    - ARM: fix Thumb2 regression with Spectre BHB
+    - ext4: add check to prevent attempting to resize an fs with sparse_super2
+    - x86/cpufeatures: Mark two free bits in word 3
+    - x86/cpu: Add hardware-enforced cache coherency as a CPUID feature
+    - x86/mm/pat: Don't flush cache if hardware enforces cache coherency across
+      encryption domnains
+    - KVM: SVM: Don't flush cache if hardware enforces cache coherency across
+      encryption domains
+    - Linux 5.4.185
+  * Focal update: v5.4.184 upstream stable release (LP: #1969242)
+    - arm/arm64: Provide a wrapper for SMCCC 1.1 calls
+    - arm/arm64: smccc/psci: add arm_smccc_1_1_get_conduit()
+    - ARM: report Spectre v2 status through sysfs
+    - ARM: early traps initialisation
+    - ARM: use LOADADDR() to get load address of sections
+    - [Config] updateconfigs for HARDEN_BRANCH_HISTORY
+    - ARM: Spectre-BHB workaround
+    - ARM: include unprivileged BPF status in Spectre V2 reporting
+    - ARM: fix build error when BPF_SYSCALL is disabled
+    - ARM: fix co-processor register typo
+    - ARM: Do not use NOCROSSREFS directive with ld.lld
+    - ARM: fix build warning in proc-v7-bugs.c
+    - xen/xenbus: don't let xenbus_grant_ring() remove grants in error case
+    - xen/grant-table: add gnttab_try_end_foreign_access()
+    - xen/blkfront: don't use gnttab_query_foreign_access() for mapped status
+    - xen/netfront: don't use gnttab_query_foreign_access() for mapped status
+    - xen/scsifront: don't use gnttab_query_foreign_access() for mapped status
+    - xen/gntalloc: don't use gnttab_query_foreign_access()
+    - xen: remove gnttab_query_foreign_access()
+    - xen/9p: use alloc/free_pages_exact()
+    - xen/pvcalls: use alloc/free_pages_exact()
+    - xen/gnttab: fix gnttab_end_foreign_access() without page specified
+    - xen/netfront: react properly to failing gnttab_end_foreign_access_ref()
+    - Linux 5.4.184
+  * Focal update: v5.4.183 upstream stable release (LP: #1969239)
+    - mac80211_hwsim: report NOACK frames in tx_status
+    - mac80211_hwsim: initialize ieee80211_tx_info at hw_scan_work
+    - i2c: bcm2835: Avoid clock stretching timeouts
+    - ASoC: rt5668: do not block workqueue if card is unbound
+    - ASoC: rt5682: do not block workqueue if card is unbound
+    - Input: clear BTN_RIGHT/MIDDLE on buttonpads
+    - cifs: fix double free race when mount fails in cifs_get_root()
+    - dmaengine: shdma: Fix runtime PM imbalance on error
+    - i2c: cadence: allow COMPILE_TEST
+    - i2c: qup: allow COMPILE_TEST
+    - net: usb: cdc_mbim: avoid altsetting toggling for Telit FN990
+    - usb: gadget: don't release an existing dev->buf
+    - usb: gadget: clear related members when goto fail
+    - ata: pata_hpt37x: fix PCI clock detection
+    - ALSA: intel_hdmi: Fix reference to PCM buffer address
+    - ASoC: ops: Shift tested values in snd_soc_put_volsw() by +min
+    - xfrm: fix MTU regression
+    - netfilter: fix use-after-free in __nf_register_net_hook()
+    - xfrm: enforce validity of offload input flags
+    - netfilter: nf_queue: don't assume sk is full socket
+    - netfilter: nf_queue: fix possible use-after-free
+    - batman-adv: Request iflink once in batadv-on-batadv check
+    - batman-adv: Request iflink once in batadv_get_real_netdevice
+    - batman-adv: Don't expect inter-netns unique iflink indices
+    - net: dcb: flush lingering app table entries for unregistered devices
+    - net/smc: fix unexpected SMC_CLC_DECL_ERR_REGRMB error generated by client
+    - net/smc: fix unexpected SMC_CLC_DECL_ERR_REGRMB error cause by server
+    - block: Fix fsync always failed if once failed
+    - xen/netfront: destroy queues before real_num_tx_queues is zeroed
+    - sched/topology: Make sched_init_numa() use a set for the deduplicating sort
+    - sched/topology: Fix sched_domain_topology_level alloc in sched_init_numa()
+    - ia64: ensure proper NUMA distance and possible map initialization
+    - mac80211: fix forwarded mesh frames AC & queue selection
+    - net: stmmac: fix return value of __setup handler
+    - iavf: Fix missing check for running netdev
+    - net: sxgbe: fix return value of __setup handler
+    - net: arcnet: com20020: Fix null-ptr-deref in com20020pci_probe()
+    - ixgbe: xsk: change !netif_carrier_ok() handling in ixgbe_xmit_zc()
+    - efivars: Respect "block" flag in efivar_entry_set_safe()
+    - firmware: arm_scmi: Remove space in MODULE_ALIAS name
+    - ASoC: cs4265: Fix the duplicated control name
+    - can: gs_usb: change active_channels's type from atomic_t to u8
+    - arm64: dts: rockchip: Switch RK3399-Gru DP to SPDIF output
+    - igc: igc_read_phy_reg_gpy: drop premature return
+    - ARM: Fix kgdb breakpoint for Thumb2
+    - ARM: 9182/1: mmu: fix returns from early_param() and __setup() functions
+    - igc: igc_write_phy_reg_gpy: drop premature return
+    - ibmvnic: free reset-work-item when flushing
+    - memfd: fix F_SEAL_WRITE after shmem huge page allocated
+    - soc: fsl: qe: Check of ioremap return value
+    - net: chelsio: cxgb3: check the return value of pci_find_capability()
+    - nl80211: Handle nla_memdup failures in handle_nan_filter
+    - Input: elan_i2c - move regulator_[en|dis]able() out of
+      elan_[en|dis]able_power()
+    - Input: elan_i2c - fix regulator enable count imbalance after suspend/resume
+    - HID: add mapping for KEY_DICTATE
+    - HID: add mapping for KEY_ALL_APPLICATIONS
+    - tracing/histogram: Fix sorting on old "cpu" value
+    - tracing: Fix return value of __setup handlers
+    - btrfs: fix lost prealloc extents beyond eof after full fsync
+    - btrfs: qgroup: fix deadlock between rescan worker and remove qgroup
+    - btrfs: add missing run of delayed items after unlink during log replay
+    - Revert "xfrm: xfrm_state_mtu should return at least 1280 for ipv6"
+    - net: dcb: disable softirqs in dcbnl_flush_dev()
+    - hamradio: fix macro redefine warning
+    - Linux 5.4.183
+  * Focal update: v5.4.182 upstream stable release (LP: #1969236)
+    - cgroup/cpuset: Fix a race between cpuset_attach() and cpu hotplug
+    - clk: jz4725b: fix mmc0 clock gating
+    - vhost/vsock: don't check owner in vhost_vsock_stop() while releasing
+    - parisc/unaligned: Fix fldd and fstd unaligned handlers on 32-bit kernel
+    - parisc/unaligned: Fix ldw() and stw() unalignment handlers
+    - drm/amdgpu: disable MMHUB PG for Picasso
+    - sr9700: sanity check for packet length
+    - USB: zaurus: support another broken Zaurus
+    - x86/fpu: Correct pkru/xstate inconsistency
+    - tee: export teedev_open() and teedev_close_context()
+    - optee: use driver internal tee_context for some rpc
+    - lan743x: fix deadlock in lan743x_phy_link_status_change()
+    - ping: remove pr_err from ping_lookup
+    - perf data: Fix double free in perf_session__delete()
+    - bpf: Do not try bpf_msg_push_data with len 0
+    - net: __pskb_pull_tail() & pskb_carve_frag_list() drop_monitor friends
+    - tipc: Fix end of loop tests for list_for_each_entry()
+    - gso: do not skip outer ip header in case of ipip and net_failover
+    - openvswitch: Fix setting ipv6 fields causing hw csum failure
+    - drm/edid: Always set RGB444
+    - net/mlx5e: Fix wrong return value on ioctl EEPROM query failure
+    - net: ll_temac: check the return value of devm_kmalloc()
+    - net: Force inlining of checksum functions in net/checksum.h
+    - nfp: flower: Fix a potential leak in nfp_tunnel_add_shared_mac()
+    - netfilter: nf_tables: fix memory leak during stateful obj update
+    - net/mlx5: Fix possible deadlock on rule deletion
+    - net/mlx5: Fix wrong limitation of metadata match on ecpf
+    - spi: spi-zynq-qspi: Fix a NULL pointer dereference in
+      zynq_qspi_exec_mem_op()
+    - configfs: fix a race in configfs_{,un}register_subsystem()
+    - RDMA/ib_srp: Fix a deadlock
+    - tracing: Have traceon and traceoff trigger honor the instance
+    - iio: adc: men_z188_adc: Fix a resource leak in an error handling path
+    - iio: adc: ad7124: fix mask used for setting AIN_BUFP & AIN_BUFM bits
+    - iio: Fix error handling for PM
+    - ata: pata_hpt37x: disable primary channel on HPT371
+    - Revert "USB: serial: ch341: add new Product ID for CH341A"
+    - usb: gadget: rndis: add spinlock for rndis response list
+    - tracefs: Set the group ownership in apply_options() not parse_options()
+    - USB: serial: option: add support for DW5829e
+    - USB: serial: option: add Telit LE910R1 compositions
+    - usb: dwc3: pci: Fix Bay Trail phy GPIO mappings
+    - usb: dwc3: gadget: Let the interrupt handler disable bottom halves.
+    - xhci: re-initialize the HC during resume if HCE was set
+    - xhci: Prevent futile URB re-submissions due to incorrect return value.
+    - tty: n_gsm: fix encoding of control signal octet bit DV
+    - tty: n_gsm: fix proper link termination after failed open
+    - tty: n_gsm: fix NULL pointer access due to DLCI release
+    - gpio: tegra186: Fix chip_data type confusion
+    - Revert "drm/nouveau/pmu/gm200-: avoid touching PMU outside of
+      DEVINIT/PREOS/ACR"
+    - memblock: use kfree() to release kmalloced memblock regions
+    - fget: clarify and improve __fget_files() implementation
+    - Linux 5.4.182
+  * CVE-2022-28390
+    - can: ems_usb: ems_usb_start_xmit(): fix double dev_kfree_skb() in error path
+
+  [ Ubuntu: 5.4.0-113.127 ]
+
+  * focal/linux: 5.4.0-113.127 -proposed tracker (LP: #1973980)
+  * CVE-2022-29581
+    - net/sched: cls_u32: fix netns refcount changes in u32_change()
+  * CVE-2022-1116
+    - io_uring: fix fs->users overflow
+  * ext4: limit length to bitmap_maxbytes (LP: #1972281)
+    - ext4: limit length to bitmap_maxbytes - blocksize in punch_hole
+  * Unprivileged users may use PTRACE_SEIZE to set PTRACE_O_SUSPEND_SECCOMP
+    option (LP: #1972740)
+    - ptrace: Check PTRACE_O_SUSPEND_SECCOMP permission on PTRACE_SEIZE
+
+  [ Ubuntu: 5.4.0-110.124 ]
+
+  * focal/linux: 5.4.0-110.124 -proposed tracker (LP: #1969053)
+  * net/mlx5e: Fix page DMA map/unmap attributes (LP: #1967292)
+    - net/mlx5e: Fix page DMA map/unmap attributes
+  * xfs: Fix deadlock between AGI and AGF when target_ip exists in xfs_rename()
+    (LP: #1966803)
+    - xfs: Fix deadlock between AGI and AGF when target_ip exists in xfs_rename()
+  * LRMv6: add multi-architecture support (LP: #1968774)
+    - [Packaging] resync dkms-build{,--nvidia-N}
+  * xfrm interface cannot be changed anymore (LP: #1968591)
+    - xfrm: fix the if_id check in changelink
+  * Use kernel-testing repo from launchpad for ADT tests (LP: #1968016)
+    - [Debian] Use kernel-testing repo from launchpad
+  * vmx_ldtr_test in ubuntu_kvm_unit_tests failed (FAIL: Expected 0 for L1 LDTR
+    selector (got 50)) (LP: #1956315)
+    - KVM: nVMX: Set LDTR to its architecturally defined value on nested VM-Exit
+  * [SRU][Regression] Revert "PM: ACPI: reboot: Use S5 for reboot" which causes
+    Bus Fatal Error when rebooting system with BCM5720 NIC (LP: #1917471)
+    - Revert "PM: ACPI: reboot: Use S5 for reboot"
+  * Focal update: v5.4.181 upstream stable release (LP: #1967582)
+    - Makefile.extrawarn: Move -Wunaligned-access to W=1
+    - HID:Add support for UGTABLET WP5540
+    - Revert "svm: Add warning message for AVIC IPI invalid target"
+    - serial: parisc: GSC: fix build when IOSAPIC is not set
+    - parisc: Drop __init from map_pages declaration
+    - parisc: Fix data TLB miss in sba_unmap_sg
+    - parisc: Fix sglist access in ccio-dma.c
+    - btrfs: send: in case of IO error log it
+    - platform/x86: ISST: Fix possible circular locking dependency detected
+    - selftests: rtc: Increase test timeout so that all tests run
+    - net: ieee802154: at86rf230: Stop leaking skb's
+    - selftests/zram: Skip max_comp_streams interface on newer kernel
+    - selftests/zram01.sh: Fix compression ratio calculation
+    - selftests/zram: Adapt the situation that /dev/zram0 is being used
+    - ax25: improve the incomplete fix to avoid UAF and NPD bugs
+    - vfs: make freeze_super abort when sync_filesystem returns error
+    - quota: make dquot_quota_sync return errors from ->sync_fs
+    - nvme: fix a possible use-after-free in controller reset during load
+    - nvme-tcp: fix possible use-after-free in transport error_recovery work
+    - nvme-rdma: fix possible use-after-free in transport error_recovery work
+    - drm/amdgpu: fix logic inversion in check
+    - Revert "module, async: async_synchronize_full() on module init iff async is
+      used"
+    - ftrace: add ftrace_init_nop()
+    - module/ftrace: handle patchable-function-entry
+    - arm64: module: rework special section handling
+    - arm64: module/ftrace: intialize PLT at load time
+    - iwlwifi: fix use-after-free
+    - drm/radeon: Fix backlight control on iMac 12,1
+    - ext4: check for out-of-order index extents in ext4_valid_extent_entries()
+    - ext4: check for inconsistent extents between index and leaf block
+    - ext4: prevent partial update of the extent blocks
+    - taskstats: Cleanup the use of task->exit_code
+    - dmaengine: at_xdmac: Start transfer for cyclic channels in issue_pending
+    - vsock: remove vsock from connected table when connect is interrupted by a
+      signal
+    - mmc: block: fix read single on recovery logic
+    - iwlwifi: pcie: fix locking when "HW not ready"
+    - iwlwifi: pcie: gen2: fix locking when "HW not ready"
+    - netfilter: nft_synproxy: unregister hooks on init error path
+    - net: dsa: lan9303: fix reset on probe
+    - net: ieee802154: ca8210: Fix lifs/sifs periods
+    - ping: fix the dif and sdif check in ping_lookup
+    - bonding: force carrier update when releasing slave
+    - drop_monitor: fix data-race in dropmon_net_event / trace_napi_poll_hit
+    - bonding: fix data-races around agg_select_timer
+    - libsubcmd: Fix use-after-free for realloc(..., 0)
+    - ALSA: hda: Fix regression on forced probe mask option
+    - ALSA: hda: Fix missing codec probe on Shenker Dock 15
+    - ASoC: ops: Fix stereo change notifications in snd_soc_put_volsw()
+    - ASoC: ops: Fix stereo change notifications in snd_soc_put_volsw_range()
+    - powerpc/lib/sstep: fix 'ptesync' build error
+    - mtd: rawnand: gpmi: don't leak PM reference in error path
+    - block/wbt: fix negative inflight counter when remove scsi device
+    - NFS: LOOKUP_DIRECTORY is also ok with symlinks
+    - NFS: Do not report writeback errors in nfs_getattr()
+    - mtd: rawnand: qcom: Fix clock sequencing in qcom_nandc_probe()
+    - mtd: rawnand: brcmnand: Fixed incorrect sub-page ECC status
+    - scsi: lpfc: Fix pt2pt NVMe PRLI reject LOGO loop
+    - EDAC: Fix calculation of returned address and next offset in
+      edac_align_ptr()
+    - net: sched: limit TC_ACT_REPEAT loops
+    - dmaengine: sh: rcar-dmac: Check for error num after setting mask
+    - copy_process(): Move fd_install() out of sighand->siglock critical section
+    - i2c: brcmstb: fix support for DSL and CM variants
+    - Drivers: hv: vmbus: Fix memory leak in vmbus_add_channel_kobj
+    - KVM: x86/pmu: Use AMD64_RAW_EVENT_MASK for PERF_TYPE_RAW
+    - ARM: OMAP2+: hwmod: Add of_node_put() before break
+    - ARM: OMAP2+: adjust the location of put_device() call in omapdss_init_of
+    - irqchip/sifive-plic: Add missing thead,c900-plic match string
+    - netfilter: conntrack: don't refresh sctp entries in closed state
+    - arm64: dts: meson-gx: add ATF BL32 reserved-memory region
+    - arm64: dts: meson-g12: add ATF BL32 reserved-memory region
+    - arm64: dts: meson-g12: drop BL32 region from SEI510/SEI610
+    - kconfig: let 'shell' return enough output for deep path names
+    - ata: libata-core: Disable TRIM on M88V29
+    - drm/rockchip: dw_hdmi: Do not leave clock enabled in error case
+    - tracing: Fix tp_printk option related with tp_printk_stop_on_boot
+    - net: usb: qmi_wwan: Add support for Dell DW5829e
+    - net: macb: Align the dma and coherent dma masks
+    - kconfig: fix failing to generate auto.conf
+    - Linux 5.4.181
+  * Focal update: v5.4.180 upstream stable release (LP: #1966118)
+    - integrity: check the return value of audit_log_start()
+    - ima: Remove ima_policy file before directory
+    - ima: Allow template selection with ima_template[_fmt]= after ima_hash=
+    - ima: Do not print policy rule with inactive LSM labels
+    - mmc: sdhci-of-esdhc: Check for error num after setting mask
+    - net: phy: marvell: Fix RGMII Tx/Rx delays setting in 88e1121-compatible PHYs
+    - net: phy: marvell: Fix MDI-x polarity setting in 88e1118-compatible PHYs
+    - NFS: Fix initialisation of nfs_client cl_flags field
+    - NFSD: Clamp WRITE offsets
+    - NFSD: Fix offset type in I/O trace points
+    - NFSv4 only print the label when its queried
+    - nfs: nfs4clinet: check the return value of kstrdup()
+    - NFSv4.1: Fix uninitialised variable in devicenotify
+    - NFSv4 remove zero number of fs_locations entries error check
+    - NFSv4 expose nfs_parse_server_name function
+    - drm: panel-orientation-quirks: Add quirk for the 1Netbook OneXPlayer
+    - net: sched: Clarify error message when qdisc kind is unknown
+    - scsi: target: iscsi: Make sure the np under each tpg is unique
+    - scsi: qedf: Fix refcount issue when LOGO is received during TMF
+    - scsi: myrs: Fix crash in error case
+    - PM: hibernate: Remove register_nosave_region_late()
+    - usb: dwc2: gadget: don't try to disable ep0 in dwc2_hsotg_suspend
+    - net: stmmac: dwmac-sun8i: use return val of readl_poll_timeout()
+    - KVM: nVMX: eVMCS: Filter out VM_EXIT_SAVE_VMX_PREEMPTION_TIMER
+    - riscv: fix build with binutils 2.38
+    - ARM: dts: imx23-evk: Remove MX23_PAD_SSP1_DETECT from hog group
+    - ARM: socfpga: fix missing RESET_CONTROLLER
+    - nvme-tcp: fix bogus request completion when failing to send AER
+    - ACPI/IORT: Check node revision for PMCG resources
+    - PM: s2idle: ACPI: Fix wakeup interrupts handling
+    - net: bridge: fix stale eth hdr pointer in br_dev_xmit
+    - perf probe: Fix ppc64 'perf probe add events failed' case
+    - ARM: dts: meson: Fix the UART compatible strings
+    - staging: fbtft: Fix error path in fbtft_driver_module_init()
+    - ARM: dts: imx6qdl-udoo: Properly describe the SD card detect
+    - usb: f_fs: Fix use-after-free for epfile
+    - misc: fastrpc: avoid double fput() on failed usercopy
+    - ixgbevf: Require large buffers for build_skb on 82599VF
+    - bonding: pair enable_port with slave_arr_updates
+    - ipmr,ip6mr: acquire RTNL before calling ip[6]mr_free_table() on failure path
+    - nfp: flower: fix ida_idx not being released
+    - net: do not keep the dst cache when uncloning an skb dst and its metadata
+    - net: fix a memleak when uncloning an skb dst and its metadata
+    - veth: fix races around rq->rx_notify_masked
+    - net: mdio: aspeed: Add missing MODULE_DEVICE_TABLE
+    - tipc: rate limit warning for received illegal binding update
+    - net: amd-xgbe: disable interrupts during pci removal
+    - vt_ioctl: fix array_index_nospec in vt_setactivate
+    - vt_ioctl: add array_index_nospec to VT_ACTIVATE
+    - n_tty: wake up poll(POLLRDNORM) on receiving data
+    - eeprom: ee1004: limit i2c reads to I2C_SMBUS_BLOCK_MAX
+    - net: usb: ax88179_178a: Fix out-of-bounds accesses in RX fixup
+    - usb: ulpi: Move of_node_put to ulpi_dev_release
+    - usb: ulpi: Call of_node_put correctly
+    - usb: dwc3: gadget: Prevent core from processing stale TRBs
+    - usb: gadget: udc: renesas_usb3: Fix host to USB_ROLE_NONE transition
+    - USB: gadget: validate interface OS descriptor requests
+    - usb: gadget: rndis: check size of RNDIS_MSG_SET command
+    - usb: gadget: f_uac2: Define specific wTerminalType
+    - USB: serial: ftdi_sio: add support for Brainboxes US-159/235/320
+    - USB: serial: option: add ZTE MF286D modem
+    - USB: serial: ch341: add support for GW Instek USB2.0-Serial devices
+    - USB: serial: cp210x: add NCR Retail IO box id
+    - USB: serial: cp210x: add CPI Bulk Coin Recycler id
+    - seccomp: Invalidate seccomp mode to catch death failures
+    - hwmon: (dell-smm) Speed up setting of fan speed
+    - scsi: lpfc: Remove NVMe support if kernel has NVME_FC disabled
+    - perf: Fix list corruption in perf_cgroup_switch()
+    - Linux 5.4.180
+  * Focal update: v5.4.179 upstream stable release (LP: #1965591)
+    - moxart: fix potential use-after-free on remove path
+    - Linux 5.4.179
+  * CVE-2020-27820
+    - drm/nouveau: Add a dedicated mutex for the clients list
+    - drm/nouveau: clean up all clients on device removal
+  * CVE-2022-1016
+    - netfilter: nf_tables: initialize registers in nft_do_chain()
+  * CVE-2022-27223
+    - USB: gadget: validate endpoint index for xilinx udc
+  * CVE-2022-26490
+    - nfc: st21nfca: Fix potential buffer overflows in EVT_TRANSACTION
+  * CVE-2021-26401
+    - x86/speculation: Use generic retpoline by default on AMD
+    - x86/speculation: Update link to AMD speculation whitepaper
+    - x86/speculation: Warn about Spectre v2 LFENCE mitigation
+    - x86/speculation: Warn about eIBRS + LFENCE + Unprivileged eBPF + SMT
+  * CVE-2022-0001
+    - x86/speculation: Include unprivileged eBPF status in Spectre v2 mitigation
+      reporting
+
+  [ Ubuntu: 5.4.0-109.123 ]
+
+  * focal/linux: 5.4.0-109.123 -proposed tracker (LP: #1968290)
+  * USB devices not detected during boot on USB 3.0 hubs (LP: #1968210)
+    - SAUCE: Revert "Revert "xhci: Set HCD flag to defer primary roothub
+      registration""
+    - SAUCE: Revert "Revert "usb: core: hcd: Add support for deferring roothub
+      registration""
+
+  [ Ubuntu: 5.4.0-108.122 ]
+
+  * focal/linux: 5.4.0-108.122 -proposed tracker (LP: #1966740)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync dkms-build{,--nvidia-N} from LRMv5
+    - debian/dkms-versions -- update from kernel-versions (main/2022.03.21)
+  * Low RX performance for 40G Solarflare NICs (LP: #1964512)
+    - SAUCE: sfc: The size of the RX recycle ring should be more flexible
+  * [UBUNTU 20.04] KVM: Enable storage key checking for intercepted instruction
+    (LP: #1962831)
+    - selftests: kvm: add _vm_ioctl
+    - selftests: kvm: Introduce the TEST_FAIL macro
+    - KVM: selftests: Add GUEST_ASSERT variants to pass values to host
+    - KVM: s390: gaccess: Refactor gpa and length calculation
+    - KVM: s390: gaccess: Refactor access address range check
+    - KVM: s390: gaccess: Cleanup access to guest pages
+    - s390/uaccess: introduce bit field for OAC specifier
+    - s390/uaccess: fix compile error
+    - s390/uaccess: Add copy_from/to_user_key functions
+    - KVM: s390: Honor storage keys when accessing guest memory
+    - KVM: s390: handle_tprot: Honor storage keys
+    - KVM: s390: selftests: Test TEST PROTECTION emulation
+    - KVM: s390: Add optional storage key checking to MEMOP IOCTL
+    - KVM: s390: Add vm IOCTL for key checked guest absolute memory access
+    - KVM: s390: Rename existing vcpu memop functions
+    - KVM: s390: Add capability for storage key extension of MEM_OP IOCTL
+    - KVM: s390: Update api documentation for memop ioctl
+    - KVM: s390: Clarify key argument for MEM_OP in api docs
+    - KVM: s390: Add missing vm MEM_OP size check
+  * 【sec-0911】 fail to reset sec module (LP: #1943301)
+    - crypto: hisilicon/sec2 - Add workqueue for SEC driver.
+    - crypto: hisilicon/sec2 - update SEC initialization and reset
+  * Lots of hisi_qm zombie task slow down system after stress test
+    (LP: #1932117)
+    - crypto: hisilicon - Use one workqueue per qm instead of per qp
+  * Lots of hisi_qm zombie task slow down system after stress test
+    (LP: #1932117) // 【sec-0911】 fail to reset sec module (LP: #1943301)
+    - crypto: hisilicon - Unify hardware error init/uninit into QM
+  * [UBUNTU 20.04] Fix SIGP processing on KVM/s390 (LP: #1962578)
+    - KVM: s390: Simplify SIGP Set Arch handling
+    - KVM: s390: Add a routine for setting userspace CPU state
+  * Move virtual graphics drivers from linux-modules-extra to linux-modules
+    (LP: #1960633)
+    - [Packaging] Move VM DRM drivers into modules
+  * Focal update: v5.4.178 upstream stable release (LP: #1964634)
+    - audit: improve audit queue handling when "audit=1" on cmdline
+    - ASoC: ops: Reject out of bounds values in snd_soc_put_volsw()
+    - ASoC: ops: Reject out of bounds values in snd_soc_put_volsw_sx()
+    - ASoC: ops: Reject out of bounds values in snd_soc_put_xr_sx()
+    - ALSA: usb-audio: Simplify quirk entries with a macro
+    - ALSA: hda/realtek: Add quirk for ASUS GU603
+    - ALSA: hda/realtek: Add missing fixup-model entry for Gigabyte X570 ALC1220
+      quirks
+    - ALSA: hda/realtek: Fix silent output on Gigabyte X570S Aorus Master (newer
+      chipset)
+    - ALSA: hda/realtek: Fix silent output on Gigabyte X570 Aorus Xtreme after
+      reboot from Windows
+    - btrfs: fix deadlock between quota disable and qgroup rescan worker
+    - drm/nouveau: fix off by one in BIOS boundary checking
+    - mm/kmemleak: avoid scanning potential huge holes
+    - block: bio-integrity: Advance seed correctly for larger interval sizes
+    - memcg: charge fs_context and legacy_fs_context
+    - IB/rdmavt: Validate remote_addr during loopback atomic tests
+    - RDMA/siw: Fix broken RDMA Read Fence/Resume logic.
+    - RDMA/mlx4: Don't continue event handler after memory allocation failure
+    - iommu/vt-d: Fix potential memory leak in intel_setup_irq_remapping()
+    - iommu/amd: Fix loop timeout issue in iommu_ga_log_enable()
+    - spi: bcm-qspi: check for valid cs before applying chip select
+    - spi: mediatek: Avoid NULL pointer crash in interrupt
+    - spi: meson-spicc: add IRQ check in meson_spicc_probe
+    - net: ieee802154: hwsim: Ensure proper channel selection at probe time
+    - net: ieee802154: mcr20a: Fix lifs/sifs periods
+    - net: ieee802154: ca8210: Stop leaking skb's
+    - net: ieee802154: Return meaningful error codes from the netlink helpers
+    - net: macsec: Verify that send_sci is on when setting Tx sci explicitly
+    - net: stmmac: dump gmac4 DMA registers correctly
+    - net: stmmac: ensure PTP time register reads are consistent
+    - drm/i915/overlay: Prevent divide by zero bugs in scaling
+    - ASoC: fsl: Add missing error handling in pcm030_fabric_probe
+    - ASoC: xilinx: xlnx_formatter_pcm: Make buffer bytes multiple of period bytes
+    - ASoC: cpcap: Check for NULL pointer after calling of_get_child_by_name
+    - ASoC: max9759: fix underflow in speaker_gain_control_put()
+    - pinctrl: bcm2835: Fix a few error paths
+    - scsi: bnx2fc: Make bnx2fc_recv_frame() mp safe
+    - nfsd: nfsd4_setclientid_confirm mistakenly expires confirmed client.
+    - selftests: futex: Use variable MAKE instead of make
+    - rtc: cmos: Evaluate century appropriate
+    - EDAC/altera: Fix deferred probing
+    - EDAC/xgene: Fix deferred probing
+    - ext4: fix error handling in ext4_restore_inline_data()
+    - cgroup/cpuset: Fix "suspicious RCU usage" lockdep warning
+    - Linux 5.4.178
+  * Focal update: v5.4.177 upstream stable release (LP: #1964628)
+    - PCI: pciehp: Fix infinite loop in IRQ handler upon power fault
+    - psi: Fix uaf issue when psi trigger is destroyed while being polled
+    - ipheth: fix EOVERFLOW in ipheth_rcvbulk_callback
+    - net: amd-xgbe: ensure to reset the tx_timer_active flag
+    - net: amd-xgbe: Fix skb data length underflow
+    - rtnetlink: make sure to refresh master_dev/m_ops in __rtnl_newlink()
+    - cpuset: Fix the bug that subpart_cpus updated wrongly in update_cpumask()
+    - af_packet: fix data-race in packet_setsockopt / packet_setsockopt
+    - Linux 5.4.177
+  * Focal update: v5.4.176 upstream stable release (LP: #1962345)
+    - s390/hypfs: include z/VM guests with access control group set
+    - scsi: zfcp: Fix failed recovery on gone remote port with non-NPIV FCP
+      devices
+    - udf: Restore i_lenAlloc when inode expansion fails
+    - udf: Fix NULL ptr deref when converting from inline format
+    - PM: wakeup: simplify the output logic of pm_show_wakelocks()
+    - tracing/histogram: Fix a potential memory leak for kstrdup()
+    - tracing: Don't inc err_log entry count if entry allocation fails
+    - fsnotify: fix fsnotify hooks in pseudo filesystems
+    - drm/etnaviv: relax submit size limits
+    - arm64: errata: Fix exec handling in erratum 1418040 workaround
+    - netfilter: nft_payload: do not update layer 4 checksum when mangling
+      fragments
+    - serial: 8250: of: Fix mapped region size when using reg-offset property
+    - serial: stm32: fix software flow control transfer
+    - tty: n_gsm: fix SW flow control encoding/handling
+    - tty: Add support for Brainboxes UC cards.
+    - usb-storage: Add unusual-devs entry for VL817 USB-SATA bridge
+    - usb: common: ulpi: Fix crash in ulpi_match()
+    - usb: gadget: f_sourcesink: Fix isoc transfer for USB_SPEED_SUPER_PLUS
+    - USB: core: Fix hang in usb_kill_urb by adding memory barriers
+    - usb: typec: tcpm: Do not disconnect while receiving VBUS off
+    - ucsi_ccg: Check DEV_INT bit only when starting CCG4
+    - net: sfp: ignore disabled SFP node
+    - powerpc/32: Fix boot failure with GCC latent entropy plugin
+    - i40e: Increase delay to 1 s after global EMP reset
+    - i40e: Fix issue when maximum queues is exceeded
+    - i40e: Fix queues reservation for XDP
+    - i40e: fix unsigned stat widths
+    - rpmsg: char: Fix race between the release of rpmsg_ctrldev and cdev
+    - rpmsg: char: Fix race between the release of rpmsg_eptdev and cdev
+    - scsi: bnx2fc: Flush destroy_work queue before calling bnx2fc_interface_put()
+    - ipv6_tunnel: Rate limit warning messages
+    - net: fix information leakage in /proc/net/ptype
+    - hwmon: (lm90) Mark alert as broken for MAX6646/6647/6649
+    - hwmon: (lm90) Mark alert as broken for MAX6680
+    - ping: fix the sk_bound_dev_if match in ping_lookup
+    - ipv4: avoid using shared IP generator for connected sockets
+    - hwmon: (lm90) Reduce maximum conversion rate for G781
+    - NFSv4: Handle case where the lookup of a directory fails
+    - NFSv4: nfs_atomic_open() can race when looking up a non-regular file
+    - net-procfs: show net devices bound packet types
+    - drm/msm: Fix wrong size calculation
+    - drm/msm/dsi: Fix missing put_device() call in dsi_get_phy
+    - drm/msm/dsi: invalid parameter check in msm_dsi_phy_enable
+    - ipv6: annotate accesses to fn->fn_sernum
+    - NFS: Ensure the server has an up to date ctime before hardlinking
+    - NFS: Ensure the server has an up to date ctime before renaming
+    - netfilter: conntrack: don't increment invalid counter on NF_REPEAT
+    - net: phy: broadcom: hook up soft_reset for BCM54616S
+    - phylib: fix potential use-after-free
+    - rxrpc: Adjust retransmission backoff
+    - hwmon: (lm90) Mark alert as broken for MAX6654
+    - ibmvnic: init ->running_cap_crqs early
+    - ibmvnic: don't spin in tasklet
+    - drm/msm/hdmi: Fix missing put_device() call in msm_hdmi_get_phy
+    - yam: fix a memory leak in yam_siocdevprivate()
+    - net: hns3: handle empty unknown interrupt for VF
+    - ipv4: raw: lock the socket in raw_bind()
+    - ipv4: tcp: send zero IPID in SYNACK messages
+    - ipv4: remove sparse error in ip_neigh_gw4()
+    - dt-bindings: can: tcan4x5x: fix mram-cfg RX FIFO config
+    - fsnotify: invalidate dcache before IN_DELETE event
+    - block: Fix wrong offset in bio_truncate()
+    - mtd: rawnand: mpc5121: Remove unused variable in ads5121_select_chip()
+    - Linux 5.4.176
+  * Focal update: v5.4.175 upstream stable release (LP: #1962330)
+    - rcu: Tighten rcu_advance_cbs_nowake() checks
+    - pinctrl: bcm2835: Drop unused define
+    - pinctrl: bcm2835: Refactor platform data
+    - pinctrl: bcm2835: Add support for all GPIOs on BCM2711
+    - pinctrl: bcm2835: Match BCM7211 compatible string
+    - pinctrl: bcm2835: Add support for wake-up interrupts
+    - pinctrl: bcm2835: Change init order for gpio hogs
+    - ARM: dts: gpio-ranges property is now required
+    - mmc: sdhci-esdhc-imx: disable CMDQ support
+    - select: Fix indefinitely sleeping task in poll_schedule_timeout()
+    - Linux 5.4.175
+
+  [ Ubuntu: 5.4.0-107.121 ]
+
+  * focal/linux: 5.4.0-107.121 -proposed tracker (LP: #1966275)
+  * CVE-2022-27666
+    - esp: Fix possible buffer overflow in ESP transformation
+  * CVE-2022-1055
+    - net: sched: fix use-after-free in tc_new_tfilter()
+  * Pick fixup from v5.4.176 upstream stable release to address cert
+    failure with clock jitter test in NUC7i3DNHE (LP: #1964204)
+    - Bluetooth: refactor malicious adv data check
+
+  [ Ubuntu: 5.4.0-105.119 ]
+
+  * CVE-2022-0847
+    - lib/iov_iter: initialize "flags" in new pipe_buffer
+  * Broken network on some AWS instances with focal/impish kernels
+    (LP: #1961968)
+    - SAUCE: Revert "PCI/MSI: Mask MSI-X vectors only on success"
+  * [UBUNTU 20.04] kernel: Add support for CPU-MF counter second version 7
+    (LP: #1960182)
+    - s390/cpumf: Support for CPU Measurement Facility CSVN 7
+    - s390/cpumf: Support for CPU Measurement Sampling Facility LS bit
+  * Hipersocket page allocation failure on Ubuntu 20.04 based SSC environments
+    (LP: #1959529)
+    - s390/qeth: use memory reserves to back RX buffers
+  * CVE-2022-0516
+    - KVM: s390: Return error on SIDA memop on normal guest
+  * CVE-2022-0435
+    - tipc: improve size validations for received domain records
+  * CVE-2022-0492
+    - cgroup-v1: Require capabilities to set release_agent
+  * Recalled NFSv4 files delegations overwhelm server (LP: #1957986)
+    - NFSv4: Fix delegation handling in update_open_stateid()
+    - NFSv4: nfs4_callback_getattr() should ignore revoked delegations
+    - NFSv4: Delegation recalls should not find revoked delegations
+    - NFSv4: fail nfs4_refresh_delegation_stateid() when the delegation was
+      revoked
+    - NFS: Rename nfs_inode_return_delegation_noreclaim()
+    - NFSv4: Don't remove the delegation from the super_list more than once
+    - NFSv4: Hold the delegation spinlock when updating the seqid
+    - NFSv4: Clear the NFS_DELEGATION_REVOKED flag in
+      nfs_update_inplace_delegation()
+    - NFSv4: Update the stateid seqid in nfs_revoke_delegation()
+    - NFSv4: Revoke the delegation on success in nfs4_delegreturn_done()
+    - NFSv4: Ignore requests to return the delegation if it was revoked
+    - NFSv4: Don't reclaim delegations that have been returned or revoked
+    - NFSv4: nfs4_return_incompatible_delegation() should check delegation
+      validity
+    - NFSv4: Fix nfs4_inode_make_writeable()
+    - NFS: nfs_inode_find_state_and_recover() fix stateid matching
+    - NFSv4: Fix races between open and delegreturn
+    - NFSv4: Handle NFS4ERR_OLD_STATEID in delegreturn
+    - NFSv4: Don't retry the GETATTR on old stateid in nfs4_delegreturn_done()
+    - NFSv4: nfs_inode_evict_delegation() should set NFS_DELEGATION_RETURNING
+    - NFS: Clear NFS_DELEGATION_RETURN_IF_CLOSED when the delegation is returned
+    - NFSv4: Try to return the delegation immediately when marked for return on
+      close
+    - NFSv4: Add accounting for the number of active delegations held
+    - NFSv4: Limit the total number of cached delegations
+    - NFSv4: Ensure the delegation is pinned in nfs_do_return_delegation()
+    - NFSv4: Ensure the delegation cred is pinned when we call delegreturn
+  * Focal update: v5.4.174 upstream stable release (LP: #1960566)
+    - HID: uhid: Fix worker destroying device without any protection
+    - HID: wacom: Reset expected and received contact counts at the same time
+    - HID: wacom: Ignore the confidence flag when a touch is removed
+    - HID: wacom: Avoid using stale array indicies to read contact count
+    - f2fs: fix to do sanity check in is_alive()
+    - nfc: llcp: fix NULL error pointer dereference on sendmsg() after failed
+      bind()
+    - mtd: rawnand: gpmi: Add ERR007117 protection for nfc_apply_timings
+    - mtd: rawnand: gpmi: Remove explicit default gpmi clock setting for i.MX6
+    - x86/gpu: Reserve stolen memory for first integrated Intel GPU
+    - tools/nolibc: x86-64: Fix startup code bug
+    - tools/nolibc: i386: fix initial stack alignment
+    - tools/nolibc: fix incorrect truncation of exit code
+    - rtc: cmos: take rtc_lock while reading from CMOS
+    - media: v4l2-ioctl.c: readbuffers depends on V4L2_CAP_READWRITE
+    - media: flexcop-usb: fix control-message timeouts
+    - media: mceusb: fix control-message timeouts
+    - media: em28xx: fix control-message timeouts
+    - media: cpia2: fix control-message timeouts
+    - media: s2255: fix control-message timeouts
+    - media: dib0700: fix undefined behavior in tuner shutdown
+    - media: redrat3: fix control-message timeouts
+    - media: pvrusb2: fix control-message timeouts
+    - media: stk1160: fix control-message timeouts
+    - can: softing_cs: softingcs_probe(): fix memleak on registration failure
+    - lkdtm: Fix content of section containing lkdtm_rodata_do_nothing()
+    - iommu/io-pgtable-arm-v7s: Add error handle for page table allocation failure
+    - dma_fence_array: Fix PENDING_ERROR leak in dma_fence_array_signaled()
+    - PCI: Add function 1 DMA alias quirk for Marvell 88SE9125 SATA controller
+    - mm_zone: add function to check if managed dma zone exists
+    - mm/page_alloc.c: do not warn allocation failure on zone DMA if no managed
+      pages
+    - shmem: fix a race between shmem_unused_huge_shrink and shmem_evict_inode
+    - drm/rockchip: dsi: Hold pm-runtime across bind/unbind
+    - drm/rockchip: dsi: Reconfigure hardware on resume()
+    - drm/panel: kingdisplay-kd097d04: Delete panel on attach() failure
+    - drm/panel: innolux-p079zca: Delete panel on attach() failure
+    - drm/rockchip: dsi: Fix unbalanced clock on probe error
+    - Bluetooth: cmtp: fix possible panic when cmtp_init_sockets() fails
+    - clk: bcm-2835: Pick the closest clock rate
+    - clk: bcm-2835: Remove rounding up the dividers
+    - wcn36xx: Indicate beacon not connection loss on MISSED_BEACON_IND
+    - wcn36xx: Release DMA channel descriptor allocations
+    - media: videobuf2: Fix the size printk format
+    - media: aspeed: fix mode-detect always time out at 2nd run
+    - media: em28xx: fix memory leak in em28xx_init_dev
+    - media: aspeed: Update signal status immediately to ensure sane hw state
+    - arm64: dts: meson-gxbb-wetek: fix HDMI in early boot
+    - arm64: dts: meson-gxbb-wetek: fix missing GPIO binding
+    - Bluetooth: stop proccessing malicious adv data
+    - tee: fix put order in teedev_close_context()
+    - media: dmxdev: fix UAF when dvb_register_device() fails
+    - crypto: qce - fix uaf on qce_ahash_register_one
+    - arm64: dts: ti: k3-j721e: correct cache-sets info
+    - tty: serial: atmel: Check return code of dmaengine_submit()
+    - tty: serial: atmel: Call dma_async_issue_pending()
+    - media: rcar-csi2: Correct the selection of hsfreqrange
+    - media: imx-pxp: Initialize the spinlock prior to using it
+    - media: si470x-i2c: fix possible memory leak in si470x_i2c_probe()
+    - media: mtk-vcodec: call v4l2_m2m_ctx_release first when file is released
+    - media: venus: core: Fix a resource leak in the error handling path of
+      'venus_probe()'
+    - netfilter: bridge: add support for pppoe filtering
+    - arm64: dts: qcom: msm8916: fix MMC controller aliases
+    - ACPI: EC: Rework flushing of EC work while suspended to idle
+    - drm/amdgpu: Fix a NULL pointer dereference in
+      amdgpu_connector_lcd_native_mode()
+    - drm/radeon/radeon_kms: Fix a NULL pointer dereference in
+      radeon_driver_open_kms()
+    - arm64: dts: ti: k3-j721e: Fix the L2 cache sets
+    - tty: serial: uartlite: allow 64 bit address
+    - serial: amba-pl011: do not request memory region twice
+    - floppy: Fix hang in watchdog when disk is ejected
+    - staging: rtl8192e: return error code from rtllib_softmac_init()
+    - staging: rtl8192e: rtllib_module: fix error handle case in alloc_rtllib()
+    - Bluetooth: btmtksdio: fix resume failure
+    - media: dib8000: Fix a memleak in dib8000_init()
+    - media: saa7146: mxb: Fix a NULL pointer dereference in mxb_attach()
+    - media: si2157: Fix "warm" tuner state detection
+    - sched/rt: Try to restart rt period timer when rt runtime exceeded
+    - rcu/exp: Mark current CPU as exp-QS in IPI loop second pass
+    - mwifiex: Fix possible ABBA deadlock
+    - xfrm: fix a small bug in xfrm_sa_len()
+    - crypto: stm32/cryp - fix xts and race condition in crypto_engine requests
+    - crypto: stm32/cryp - fix double pm exit
+    - crypto: stm32/cryp - fix lrw chaining mode
+    - ARM: dts: gemini: NAS4220-B: fis-index-block with 128 KiB sectors
+    - media: dw2102: Fix use after free
+    - media: msi001: fix possible null-ptr-deref in msi001_probe()
+    - media: coda/imx-vdoa: Handle dma_set_coherent_mask error codes
+    - drm/msm/dpu: fix safe status debugfs file
+    - drm/bridge: ti-sn65dsi86: Set max register for regmap
+    - media: hantro: Fix probe func error path
+    - xfrm: interface with if_id 0 should return error
+    - xfrm: state and policy should fail if XFRMA_IF_ID 0
+    - ARM: 9159/1: decompressor: Avoid UNPREDICTABLE NOP encoding
+    - usb: ftdi-elan: fix memory leak on device disconnect
+    - ARM: dts: armada-38x: Add generic compatible to UART nodes
+    - mmc: meson-mx-sdio: add IRQ check
+    - selinux: fix potential memleak in selinux_add_opt()
+    - bpftool: Enable line buffering for stdout
+    - x86/mce/inject: Avoid out-of-bounds write when setting flags
+    - ACPI: scan: Create platform device for BCM4752 and LNV4752 ACPI nodes
+    - pcmcia: rsrc_nonstatic: Fix a NULL pointer dereference in
+      __nonstatic_find_io_region()
+    - pcmcia: rsrc_nonstatic: Fix a NULL pointer dereference in
+      nonstatic_find_mem_region()
+    - netfilter: ipt_CLUSTERIP: fix refcount leak in clusterip_tg_check()
+    - bpf: Fix SO_RCVBUF/SO_SNDBUF handling in _bpf_setsockopt().
+    - ppp: ensure minimum packet size in ppp_write()
+    - rocker: fix a sleeping in atomic bug
+    - staging: greybus: audio: Check null pointer
+    - fsl/fman: Check for null pointer after calling devm_ioremap
+    - Bluetooth: hci_bcm: Check for error irq
+    - HID: hid-uclogic-params: Invalid parameter check in uclogic_params_init
+    - HID: hid-uclogic-params: Invalid parameter check in
+      uclogic_params_get_str_desc
+    - HID: hid-uclogic-params: Invalid parameter check in
+      uclogic_params_huion_init
+    - HID: hid-uclogic-params: Invalid parameter check in
+      uclogic_params_frame_init_v1_buttonpad
+    - debugfs: lockdown: Allow reading debugfs files that are not world readable
+    - net/mlx5e: Don't block routes with nexthop objects in SW
+    - Revert "net/mlx5e: Block offload of outer header csum for UDP tunnels"
+    - net/mlx5: Set command entry semaphore up once got index free
+    - spi: spi-meson-spifc: Add missing pm_runtime_disable() in meson_spifc_probe
+    - tpm: add request_locality before write TPM_INT_ENABLE
+    - can: softing: softing_startstop(): fix set but not used variable warning
+    - can: xilinx_can: xcan_probe(): check for error irq
+    - pcmcia: fix setting of kthread task states
+    - net: mcs7830: handle usb read errors properly
+    - ext4: avoid trim error on fs with small groups
+    - ALSA: jack: Add missing rwsem around snd_ctl_remove() calls
+    - ALSA: PCM: Add missing rwsem around snd_ctl_remove() calls
+    - ALSA: hda: Add missing rwsem around snd_ctl_remove() calls
+    - RDMA/hns: Validate the pkey index
+    - clk: imx8mn: Fix imx8mn_clko1_sels
+    - powerpc/prom_init: Fix improper check of prom_getprop()
+    - ASoC: uniphier: drop selecting non-existing SND_SOC_UNIPHIER_AIO_DMA
+    - ALSA: oss: fix compile error when OSS_DEBUG is enabled
+    - char/mwave: Adjust io port register size
+    - binder: fix handling of error during copy
+    - iommu/io-pgtable-arm: Fix table descriptor paddr formatting
+    - scsi: ufs: Fix race conditions related to driver data
+    - PCI/MSI: Fix pci_irq_vector()/pci_irq_get_affinity()
+    - powerpc/powermac: Add additional missing lockdep_register_key()
+    - RDMA/core: Let ib_find_gid() continue search even after empty entry
+    - RDMA/cma: Let cma_resolve_ib_dev() continue search even after empty entry
+    - ASoC: rt5663: Handle device_property_read_u32_array error codes
+    - clk: stm32: Fix ltdc's clock turn off by clk_disable_unused() after system
+      enter shell
+    - dmaengine: pxa/mmp: stop referencing config->slave_id
+    - iommu/iova: Fix race between FQ timeout and teardown
+    - phy: uniphier-usb3ss: fix unintended writing zeros to PHY register
+    - ASoC: samsung: idma: Check of ioremap return value
+    - misc: lattice-ecp3-config: Fix task hung when firmware load failed
+    - mips: lantiq: add support for clk_set_parent()
+    - mips: bcm63xx: add support for clk_set_parent()
+    - RDMA/cxgb4: Set queue pair state when being queried
+    - of: base: Fix phandle argument length mismatch error message
+    - Bluetooth: Fix debugfs entry leak in hci_register_dev()
+    - fs: dlm: filter user dlm messages for kernel locks
+    - drm/lima: fix warning when CONFIG_DEBUG_SG=y & CONFIG_DMA_API_DEBUG=y
+    - ar5523: Fix null-ptr-deref with unexpected WDCMSG_TARGET_START reply
+    - drm/nouveau/pmu/gm200-: avoid touching PMU outside of DEVINIT/PREOS/ACR
+    - ARM: shmobile: rcar-gen2: Add missing of_node_put()
+    - batman-adv: allow netlink usage in unprivileged containers
+    - usb: gadget: f_fs: Use stream_open() for endpoint files
+    - drm: panel-orientation-quirks: Add quirk for the Lenovo Yoga Book X91F/L
+    - HID: apple: Do not reset quirks when the Fn key is not found
+    - media: b2c2: Add missing check in flexcop_pci_isr:
+    - EDAC/synopsys: Use the quirk for version instead of ddr version
+    - mlxsw: pci: Add shutdown method in PCI driver
+    - drm/bridge: megachips: Ensure both bridges are probed before registration
+    - gpiolib: acpi: Do not set the IRQ type if the IRQ is already in use
+    - HSI: core: Fix return freed object in hsi_new_client
+    - mwifiex: Fix skb_over_panic in mwifiex_usb_recv()
+    - rsi: Fix use-after-free in rsi_rx_done_handler()
+    - rsi: Fix out-of-bounds read in rsi_read_pkt()
+    - usb: uhci: add aspeed ast2600 uhci support
+    - floppy: Add max size check for user space request
+    - x86/mm: Flush global TLB when switching to trampoline page-table
+    - media: uvcvideo: Increase UVC_CTRL_CONTROL_TIMEOUT to 5 seconds.
+    - media: saa7146: hexium_orion: Fix a NULL pointer dereference in
+      hexium_attach()
+    - media: m920x: don't use stack on USB reads
+    - iwlwifi: mvm: synchronize with FW after multicast commands
+    - ath10k: Fix tx hanging
+    - net-sysfs: update the queue counts in the unregistration path
+    - net: phy: prefer 1000baseT over 1000baseKX
+    - gpio: aspeed: Convert aspeed_gpio.lock to raw_spinlock
+    - x86/mce: Mark mce_panic() noinstr
+    - x86/mce: Mark mce_end() noinstr
+    - x86/mce: Mark mce_read_aux() noinstr
+    - net: bonding: debug: avoid printing debug logs when bond is not notifying
+      peers
+    - bpf: Do not WARN in bpf_warn_invalid_xdp_action()
+    - HID: quirks: Allow inverting the absolute X/Y values
+    - media: igorplugusb: receiver overflow should be reported
+    - media: saa7146: hexium_gemini: Fix a NULL pointer dereference in
+      hexium_attach()
+    - mmc: core: Fixup storing of OCR for MMC_QUIRK_NONSTD_SDIO
+    - audit: ensure userspace is penalized the same as the kernel when under
+      pressure
+    - arm64: dts: ls1028a-qds: move rtc node to the correct i2c bus
+    - arm64: tegra: Adjust length of CCPLEX cluster MMIO region
+    - cpufreq: Fix initialization of min and max frequency QoS requests
+    - usb: hub: Add delay for SuperSpeed hub resume to let links transit to U0
+    - ath9k: Fix out-of-bound memcpy in ath9k_hif_usb_rx_stream
+    - iwlwifi: fix leaks/bad data after failed firmware load
+    - iwlwifi: remove module loading failure message
+    - iwlwifi: mvm: Fix calculation of frame length
+    - um: registers: Rename function names to avoid conflicts and build problems
+    - jffs2: GC deadlock reading a page that is used in jffs2_write_begin()
+    - ACPICA: actypes.h: Expand the ACPI_ACCESS_ definitions
+    - ACPICA: Utilities: Avoid deleting the same object twice in a row
+    - ACPICA: Executer: Fix the REFCLASS_REFOF case in acpi_ex_opcode_1A_0T_1R()
+    - ACPICA: Fix wrong interpretation of PCC address
+    - ACPICA: Hardware: Do not flush CPU cache when entering S4 and S5
+    - drm/amdgpu: fixup bad vram size on gmc v8
+    - ACPI: battery: Add the ThinkPad "Not Charging" quirk
+    - btrfs: remove BUG_ON() in find_parent_nodes()
+    - btrfs: remove BUG_ON(!eie) in find_parent_nodes
+    - net: mdio: Demote probed message to debug print
+    - mac80211: allow non-standard VHT MCS-10/11
+    - dm btree: add a defensive bounds check to insert_at()
+    - dm space map common: add bounds check to sm_ll_lookup_bitmap()
+    - net: phy: marvell: configure RGMII delays for 88E1118
+    - net: gemini: allow any RGMII interface mode
+    - regulator: qcom_smd: Align probe function with rpmh-regulator
+    - serial: pl010: Drop CR register reset on set_termios
+    - serial: core: Keep mctrl register state and cached copy in sync
+    - random: do not throw away excess input to crng_fast_load
+    - parisc: Avoid calling faulthandler_disabled() twice
+    - powerpc/6xx: add missing of_node_put
+    - powerpc/powernv: add missing of_node_put
+    - powerpc/cell: add missing of_node_put
+    - powerpc/btext: add missing of_node_put
+    - powerpc/watchdog: Fix missed watchdog reset due to memory ordering race
+    - i2c: i801: Don't silently correct invalid transfer size
+    - powerpc/smp: Move setup_profiling_timer() under CONFIG_PROFILING
+    - i2c: mpc: Correct I2C reset procedure
+    - clk: meson: gxbb: Fix the SDM_EN bit for MPLL0 on GXBB
+    - powerpc/powermac: Add missing lockdep_register_key()
+    - KVM: PPC: Book3S: Suppress failed alloc warning in H_COPY_TOFROM_GUEST
+    - w1: Misuse of get_user()/put_user() reported by sparse
+    - scsi: lpfc: Trigger SLI4 firmware dump before doing driver cleanup
+    - ALSA: seq: Set upper limit of processed events
+    - powerpc: handle kdump appropriately with crash_kexec_post_notifiers option
+    - MIPS: OCTEON: add put_device() after of_find_device_by_node()
+    - i2c: designware-pci: Fix to change data types of hcnt and lcnt parameters
+    - MIPS: Octeon: Fix build errors using clang
+    - scsi: sr: Don't use GFP_DMA
+    - ASoC: mediatek: mt8173: fix device_node leak
+    - power: bq25890: Enable continuous conversion for ADC at charging
+    - rpmsg: core: Clean up resources on announce_create failure.
+    - crypto: omap-aes - Fix broken pm_runtime_and_get() usage
+    - crypto: stm32/crc32 - Fix kernel BUG triggered in probe()
+    - crypto: caam - replace this_cpu_ptr with raw_cpu_ptr
+    - ubifs: Error path in ubifs_remount_rw() seems to wrongly free write buffers
+    - fuse: Pass correct lend value to filemap_write_and_wait_range()
+    - serial: Fix incorrect rs485 polarity on uart open
+    - cputime, cpuacct: Include guest time in user time in cpuacct.stat
+    - tracing/kprobes: 'nmissed' not showed correctly for kretprobe
+    - iwlwifi: mvm: Increase the scan timeout guard to 30 seconds
+    - s390/mm: fix 2KB pgtable release race
+    - drm/etnaviv: limit submit sizes
+    - drm/nouveau/kms/nv04: use vzalloc for nv04_display
+    - drm/bridge: analogix_dp: Make PSR-exit block less
+    - PCI: pci-bridge-emul: Properly mark reserved PCIe bits in PCI config space
+    - PCI: pci-bridge-emul: Correctly set PCIe capabilities
+    - PCI: pci-bridge-emul: Set PCI_STATUS_CAP_LIST for PCIe device
+    - xfrm: fix policy lookup for ipv6 gre packets
+    - btrfs: fix deadlock between quota enable and other quota operations
+    - btrfs: check the root node for uptodate before returning it
+    - btrfs: respect the max size in the header when activating swap file
+    - ext4: make sure to reset inode lockdep class when quota enabling fails
+    - ext4: make sure quota gets properly shutdown on error
+    - ext4: set csum seed in tmp inode while migrating to extents
+    - ext4: Fix BUG_ON in ext4_bread when write quota data
+    - ext4: don't use the orphan list when migrating an inode
+    - drm/radeon: fix error handling in radeon_driver_open_kms
+    - of: base: Improve argument length mismatch error
+    - firmware: Update Kconfig help text for Google firmware
+    - media: rcar-csi2: Optimize the selection PHTW register
+    - Documentation: dmaengine: Correctly describe dmatest with channel unset
+    - Documentation: ACPI: Fix data node reference documentation
+    - Documentation: refer to config RANDOMIZE_BASE for kernel address-space
+      randomization
+    - Documentation: fix firewire.rst ABI file path error
+    - scsi: core: Show SCMD_LAST in text form
+    - RDMA/hns: Modify the mapping attribute of doorbell to device
+    - RDMA/rxe: Fix a typo in opcode name
+    - dmaengine: stm32-mdma: fix STM32_MDMA_CTBR_TSEL_MASK
+    - Revert "net/mlx5: Add retry mechanism to the command entry index allocation"
+    - powerpc/cell: Fix clang -Wimplicit-fallthrough warning
+    - powerpc/fsl/dts: Enable WA for erratum A-009885 on fman3l MDIO buses
+    - bpftool: Remove inclusion of utilities.mak from Makefiles
+    - ipv4: avoid quadratic behavior in netns dismantle
+    - net/fsl: xgmac_mdio: Fix incorrect iounmap when removing module
+    - parisc: pdc_stable: Fix memory leak in pdcs_register_pathentries
+    - f2fs: fix to reserve space for IO align feature
+    - af_unix: annote lockless accesses to unix_tot_inflight & gc_in_progress
+    - clk: si5341: Fix clock HW provider cleanup
+    - net: axienet: limit minimum TX ring size
+    - net: axienet: fix number of TX ring slots for available check
+    - net: axienet: increase default TX ring size to 128
+    - rtc: pxa: fix null pointer dereference
+    - inet: frags: annotate races around fqdir->dead and fqdir->high_thresh
+    - netns: add schedule point in ops_exit_list()
+    - xfrm: Don't accidentally set RTO_ONLINK in decode_session4()
+    - gre: Don't accidentally set RTO_ONLINK in gre_fill_metadata_dst()
+    - libcxgb: Don't accidentally set RTO_ONLINK in cxgb_find_route()
+    - perf script: Fix hex dump character output
+    - dmaengine: at_xdmac: Don't start transactions at tx_submit level
+    - dmaengine: at_xdmac: Print debug message after realeasing the lock
+    - dmaengine: at_xdmac: Fix concurrency over xfers_list
+    - dmaengine: at_xdmac: Fix lld view setting
+    - dmaengine: at_xdmac: Fix at_xdmac_lld struct definition
+    - arm64: dts: qcom: msm8996: drop not documented adreno properties
+    - net_sched: restore "mpu xxx" handling
+    - bcmgenet: add WOL IRQ check
+    - net: ethernet: mtk_eth_soc: fix error checking in mtk_mac_config()
+    - dt-bindings: display: meson-dw-hdmi: add missing sound-name-prefix property
+    - dt-bindings: display: meson-vpu: Add missing amlogic,canvas property
+    - scripts/dtc: dtx_diff: remove broken example from help text
+    - lib82596: Fix IRQ check in sni_82596_probe
+    - lib/test_meminit: destroy cache in kmem_cache_alloc_bulk() test
+    - mtd: nand: bbt: Fix corner case in bad block table handling
+    - Revert "ia64: kprobes: Use generic kretprobe trampoline handler"
+    - Linux 5.4.174
+  * Focal update: v5.4.173 upstream stable release (LP: #1959701)
+    - kbuild: Add $(KBUILD_HOSTLDFLAGS) to 'has_libelf' test
+    - devtmpfs regression fix: reconfigure on each mount
+    - orangefs: Fix the size of a memory allocation in orangefs_bufmap_alloc()
+    - perf: Protect perf_guest_cbs with RCU
+    - KVM: s390: Clarify SIGP orders versus STOP/RESTART
+    - media: uvcvideo: fix division by zero at stream start
+    - rtlwifi: rtl8192cu: Fix WARNING when calling local_irq_restore() with
+      interrupts enabled
+    - firmware: qemu_fw_cfg: fix sysfs information leak
+    - firmware: qemu_fw_cfg: fix NULL-pointer deref on duplicate entries
+    - firmware: qemu_fw_cfg: fix kobject leak in probe error path
+    - KVM: x86: remove PMU FIXED_CTR3 from msrs_to_save_all
+    - ALSA: hda/realtek - Fix silent output on Gigabyte X570 Aorus Master after
+      reboot from Windows
+    - mtd: fixup CFI on ixp4xx
+    - ARM: 9025/1: Kconfig: CPU_BIG_ENDIAN depends on !LD_IS_LLD
+    - Linux 5.4.173
+  * Focal update: v5.4.172 upstream stable release (LP: #1959698)
+    - workqueue: Fix unbind_workers() VS wq_worker_running() race
+    - Bluetooth: btusb: fix memory leak in btusb_mtk_submit_wmt_recv_urb()
+    - Bluetooth: bfusb: fix division by zero in send path
+    - USB: core: Fix bug in resuming hub's handling of wakeup requests
+    - USB: Fix "slab-out-of-bounds Write" bug in usb_hcd_poll_rh_status
+    - mmc: sdhci-pci: Add PCI ID for Intel ADL
+    - veth: Do not record rx queue hint in veth_xmit
+    - mfd: intel-lpss: Fix too early PM enablement in the ACPI ->probe()
+    - drivers core: Use sysfs_emit and sysfs_emit_at for show(device *...)
+      functions
+    - can: gs_usb: fix use of uninitialized variable, detach device on reception
+      of invalid USB data
+    - can: gs_usb: gs_can_start_xmit(): zero-initialize hf->{flags,reserved}
+    - random: fix data race on crng_node_pool
+    - random: fix data race on crng init time
+    - random: fix crash on multiple early calls to add_bootloader_randomness()
+    - media: Revert "media: uvcvideo: Set unique vdev name based in type"
+    - staging: wlan-ng: Avoid bitwise vs logical OR warning in
+      hfa384x_usb_throttlefn()
+    - drm/i915: Avoid bitwise vs logical OR warning in snb_wm_latency_quirk()
+    - staging: greybus: fix stack size warning with UBSAN
+    - Linux 5.4.172
+  * Focal update: v5.4.171 upstream stable release (LP: #1959437)
+    - f2fs: quota: fix potential deadlock
+    - Input: touchscreen - Fix backport of
+      a02dcde595f7cbd240ccd64de96034ad91cffc40
+    - selftests: x86: fix [-Wstringop-overread] warn in test_process_vm_readv()
+    - tracing: Fix check for trace_percpu_buffer validity in get_trace_buf()
+    - tracing: Tag trace_percpu_buffer as a percpu pointer
+    - ieee802154: atusb: fix uninit value in atusb_set_extended_addr
+    - iavf: Fix limit of total number of queues to active queues of VF
+    - RDMA/core: Don't infoleak GRH fields
+    - RDMA/uverbs: Check for null return of kmalloc_array
+    - mac80211: initialize variable have_higher_than_11mbit
+    - i40e: fix use-after-free in i40e_sync_filters_subtask()
+    - i40e: Fix for displaying message regarding NVM version
+    - i40e: Fix incorrect netdev's real number of RX/TX queues
+    - ipv4: Check attribute length for RTA_GATEWAY in multipath route
+    - ipv4: Check attribute length for RTA_FLOW in multipath route
+    - ipv6: Check attribute length for RTA_GATEWAY in multipath route
+    - ipv6: Check attribute length for RTA_GATEWAY when deleting multipath route
+    - lwtunnel: Validate RTA_ENCAP_TYPE attribute length
+    - batman-adv: mcast: don't send link-local multicast to mcast routers
+    - sch_qfq: prevent shift-out-of-bounds in qfq_init_qdisc
+    - net: phy: micrel: set soft_reset callback to genphy_soft_reset for KSZ8081
+    - power: supply: core: Break capacity loop
+    - power: reset: ltc2952: Fix use of floating point literals
+    - rndis_host: support Hytera digital radios
+    - phonet: refcount leak in pep_sock_accep
+    - ipv6: Continue processing multipath route even if gateway attribute is
+      invalid
+    - ipv6: Do cleanup if attribute validation fails in multipath route
+    - usb: mtu3: fix interval value for intr and isoc
+    - scsi: libiscsi: Fix UAF in iscsi_conn_get_param()/iscsi_conn_teardown()
+    - ip6_vti: initialize __ip6_tnl_parm struct in vti6_siocdevprivate
+    - net: udp: fix alignment problem in udp4_seq_show()
+    - atlantic: Fix buff_ring OOB in aq_ring_rx_clean
+    - mISDN: change function names to avoid conflicts
+    - Linux 5.4.171
+  * Focal update: v5.4.170 upstream stable release (LP: #1958898)
+    - tee: handle lookup of shm with reference count 0
+    - Input: i8042 - add deferred probe support
+    - Input: i8042 - enable deferred probe quirk for ASUS UM325UA
+    - tomoyo: Check exceeded quota early in tomoyo_domain_quota_is_ok().
+    - platform/x86: apple-gmux: use resource_size() with res
+    - memblock: fix memblock_phys_alloc() section mismatch error
+    - recordmcount.pl: fix typo in s390 mcount regex
+    - selinux: initialize proto variable in selinux_ip_postroute_compat()
+    - scsi: lpfc: Terminate string in lpfc_debugfs_nvmeio_trc_write()
+    - net/mlx5: DR, Fix NULL vs IS_ERR checking in dr_domain_init_resources
+    - sctp: use call_rcu to free endpoint
+    - net: usb: pegasus: Do not drop long Ethernet frames
+    - net: lantiq_xrx200: fix statistics of received bytes
+    - NFC: st21nfca: Fix memory leak in device probe and remove
+    - ionic: Initialize the 'lif->dbid_inuse' bitmap
+    - net/mlx5e: Fix wrong features assignment in case of error
+    - selftests/net: udpgso_bench_tx: fix dst ip argument
+    - net/ncsi: check for error return from call to nla_put_u32
+    - fsl/fman: Fix missing put_device() call in fman_port_probe
+    - i2c: validate user data in compat ioctl
+    - nfc: uapi: use kernel size_t to fix user-space builds
+    - uapi: fix linux/nfc.h userspace compilation errors
+    - xhci: Fresco FL1100 controller should not have BROKEN_MSI quirk set.
+    - usb: gadget: f_fs: Clear ffs_eventfd in ffs_data_clear.
+    - usb: mtu3: add memory barrier before set GPD's HWO
+    - usb: mtu3: fix list_head check warning
+    - usb: mtu3: set interval of FS intr and isoc endpoint
+    - binder: fix async_free_space accounting for empty parcels
+    - scsi: vmw_pvscsi: Set residual data length conditionally
+    - Input: appletouch - initialize work before device registration
+    - Input: spaceball - fix parsing of movement data packets
+    - net: fix use-after-free in tw_timer_handler
+    - perf script: Fix CPU filtering of a script's switch events
+    - Linux 5.4.170
+  * Focal update: v5.4.170 upstream stable release (LP: #1958898) // HID_ASUS
+    should depend on USB_HID in stable v4.15 backports (LP: #1959762)
+    - HID: asus: Add depends on USB_HID to HID_ASUS Kconfig option
+  * Focal update: v5.4.169 upstream stable release (LP: #1958557)
+    - net: usb: lan78xx: add Allied Telesis AT29M2-AF
+    - serial: 8250_fintek: Fix garbled text for console
+    - arm64: dts: allwinner: orangepi-zero-plus: fix PHY mode
+    - spi: change clk_disable_unprepare to clk_unprepare
+    - IB/qib: Fix memory leak in qib_user_sdma_queue_pkts()
+    - netfilter: fix regression in looped (broad|multi)cast's MAC handling
+    - qlcnic: potential dereference null pointer of rx_queue->page_ring
+    - net: accept UFOv6 packages in virtio_net_hdr_to_skb
+    - net: skip virtio_net_hdr_set_proto if protocol already set
+    - ipmi: Fix UAF when uninstall ipmi_si and ipmi_msghandler module
+    - bonding: fix ad_actor_system option setting to default
+    - fjes: Check for error irq
+    - drivers: net: smc911x: Check for error irq
+    - sfc: falcon: Check null pointer of rx_queue->page_ring
+    - Input: elantech - fix stack out of bound access in
+      elantech_change_report_id()
+    - hwmon: (lm90) Fix usage of CONFIG2 register in detect function
+    - hwmon: (lm90) Add max6654 support to lm90 driver
+    - hwmon: (lm90) Add basic support for TI TMP461
+    - hwmon: (lm90) Introduce flag indicating extended temperature support
+    - hwmon: (lm90) Drop critical attribute support for MAX6654
+    - ALSA: jack: Check the return value of kstrdup()
+    - ALSA: drivers: opl3: Fix incorrect use of vp->state
+    - ALSA: hda/realtek: Amp init fixup for HP ZBook 15 G6
+    - Input: atmel_mxt_ts - fix double free in mxt_read_info_block
+    - ipmi: bail out if init_srcu_struct fails
+    - ipmi: ssif: initialize ssif_info->client early
+    - ipmi: fix initialization when workqueue allocation fails
+    - parisc: Correct completer in lws start
+    - x86/pkey: Fix undefined behaviour with PKRU_WD_BIT
+    - pinctrl: stm32: consider the GPIO offset to expose all the GPIO lines
+    - mmc: sdhci-tegra: Fix switch to HS400ES mode
+    - mmc: core: Disable card detect during shutdown
+    - ARM: 9169/1: entry: fix Thumb2 bug in iWMMXt exception handling
+    - tee: optee: Fix incorrect page free bug
+    - f2fs: fix to do sanity check on last xattr entry in __f2fs_setxattr()
+    - usb: gadget: u_ether: fix race in setting MAC address in setup phase
+    - KVM: VMX: Fix stale docs for kvm-intel.emulate_invalid_guest_state
+    - mm: mempolicy: fix THP allocations escaping mempolicy restrictions
+    - pinctrl: mediatek: fix global-out-of-bounds issue
+    - hwmom: (lm90) Fix citical alarm status for MAX6680/MAX6681
+    - hwmon: (lm90) Do not report 'busy' status bit as alarm
+    - ax25: NPD bug when detaching AX25 device
+    - hamradio: defer ax25 kfree after unregister_netdev
+    - hamradio: improve the incomplete fix to avoid NPD
+    - phonet/pep: refuse to enable an unbound pipe
+    - Linux 5.4.169
+  * Focal update: v5.4.168 upstream stable release (LP: #1957991)
+    - KVM: selftests: Make sure kvm_create_max_vcpus test won't hit RLIMIT_NOFILE
+    - mac80211: mark TX-during-stop for TX in in_reconfig
+    - mac80211: send ADDBA requests using the tid/queue of the aggregation session
+    - firmware: arm_scpi: Fix string overflow in SCPI genpd driver
+    - virtio_ring: Fix querying of maximum DMA mapping size for virtio device
+    - recordmcount.pl: look for jgnop instruction as well as bcrl on s390
+    - dm btree remove: fix use after free in rebalance_children()
+    - audit: improve robustness of the audit queue handling
+    - iio: adc: stm32: fix a current leak by resetting pcsel before disabling vdda
+    - nfsd: fix use-after-free due to delegation race
+    - arm64: dts: rockchip: remove mmc-hs400-enhanced-strobe from rk3399-khadas-
+      edge
+    - arm64: dts: rockchip: fix rk3399-leez-p710 vcc3v3-lan supply
+    - arm64: dts: rockchip: fix audio-supply for Rock Pi 4
+    - mac80211: track only QoS data frames for admission control
+    - ARM: socfpga: dts: fix qspi node compatible
+    - clk: Don't parent clks until the parent is fully registered
+    - selftests: net: Correct ping6 expected rc from 2 to 1
+    - s390/kexec_file: fix error handling when applying relocations
+    - sch_cake: do not call cake_destroy() from cake_init()
+    - inet_diag: use jiffies_delta_to_msecs()
+    - inet_diag: fix kernel-infoleak for UDP sockets
+    - selftests: Fix raw socket bind tests with VRF
+    - selftests: Fix IPv6 address bind tests
+    - dmaengine: st_fdma: fix MODULE_ALIAS
+    - selftest/net/forwarding: declare NETIFS p9 p10
+    - mac80211: agg-tx: refactor sending addba
+    - mac80211: agg-tx: don't schedule_and_wake_txq() under sta->lock
+    - mac80211: accept aggregation sessions on 6 GHz
+    - mac80211: fix lookup when adding AddBA extension element
+    - net: sched: lock action when translating it to flow_action infra
+    - flow_offload: return EOPNOTSUPP for the unsupported mpls action type
+    - rds: memory leak in __rds_conn_create()
+    - soc/tegra: fuse: Fix bitwise vs. logical OR warning
+    - igb: Fix removal of unicast MAC filters of VFs
+    - igbvf: fix double free in `igbvf_probe`
+    - ixgbe: set X550 MDIO speed before talking to PHY
+    - netdevsim: Zero-initialize memory for new map's value in function
+      nsim_bpf_map_alloc
+    - net: Fix double 0x prefix print in SKB dump
+    - net/smc: Prevent smc_release() from long blocking
+    - net: systemport: Add global locking for descriptor lifecycle
+    - sit: do not call ipip6_dev_free() from sit_init_net()
+    - USB: NO_LPM quirk Lenovo USB-C to Ethernet Adapher(RTL8153-04)
+    - PCI/MSI: Clear PCI_MSIX_FLAGS_MASKALL on error
+    - PCI/MSI: Mask MSI-X vectors only on success
+    - usb: xhci: Extend support for runtime power management for AMD's Yellow
+      carp.
+    - USB: serial: cp210x: fix CP2105 GPIO registration
+    - USB: serial: option: add Telit FN990 compositions
+    - timekeeping: Really make sure wall_to_monotonic isn't positive
+    - libata: if T_LENGTH is zero, dma direction should be DMA_NONE
+    - drm/amdgpu: correct register access for RLC_JUMP_TABLE_RESTORE
+    - mac80211: validate extended element ID is present
+    - mwifiex: Remove unnecessary braces from HostCmd_SET_SEQ_NO_BSS_INFO
+    - Input: touchscreen - avoid bitwise vs logical OR warning
+    - ARM: dts: imx6ull-pinfunc: Fix CSI_DATA07__ESAI_TX0 pad name
+    - xsk: Do not sleep in poll() when need_wakeup set
+    - media: mxl111sf: change mutex_init() location
+    - fuse: annotate lock in fuse_reverse_inval_entry()
+    - ovl: fix warning in ovl_create_real()
+    - scsi: scsi_debug: Sanity check block descriptor length in resp_mode_select()
+    - rcu: Mark accesses to rcu_state.n_force_qs
+    - mac80211: fix regression in SSN handling of addba tx
+    - net: sched: Fix suspicious RCU usage while accessing tcf_tunnel_info
+    - Revert "xsk: Do not sleep in poll() when need_wakeup set"
+    - xen/blkfront: harden blkfront against event channel storms
+    - xen/netfront: harden netfront against event channel storms
+    - xen/console: harden hvc_xen against event channel storms
+    - xen/netback: fix rx queue stall detection
+    - xen/netback: don't queue unlimited number of packages
+    - Linux 5.4.168
+  * Focal update: v5.4.167 upstream stable release (LP: #1957987)
+    - nfc: fix segfault in nfc_genl_dump_devices_done
+    - drm/msm/dsi: set default num_data_lanes
+    - net/mlx4_en: Update reported link modes for 1/10G
+    - parisc/agp: Annotate parisc agp init functions with __init
+    - i2c: rk3x: Handle a spurious start completion interrupt flag
+    - net: netlink: af_netlink: Prevent empty skb by adding a check on len.
+    - drm/amd/display: Fix for the no Audio bug with Tiled Displays
+    - drm/amd/display: add connector type check for CRC source set
+    - tracing: Fix a kmemleak false positive in tracing_map
+    - KVM: x86: Ignore sparse banks size for an "all CPUs", non-sparse IPI req
+    - selinux: fix race condition when computing ocontext SIDs
+    - bpf: Fix integer overflow in argument calculation for bpf_map_area_alloc
+    - hwmon: (dell-smm) Fix warning on /proc/i8k creation error
+    - memblock: free_unused_memmap: use pageblock units instead of MAX_ORDER
+    - memblock: align freed memory map on pageblock boundaries with SPARSEMEM
+    - memblock: ensure there is no overflow in memblock_overlaps_region()
+    - arm: extend pfn_valid to take into account freed memory map alignment
+    - arm: ioremap: don't abuse pfn_valid() to check if pfn is in RAM
+    - Linux 5.4.167
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync getabis
+
+  [ Ubuntu: 5.4.0-104.118 ]
+
+  * CVE-2022-23960
+    - SAUCE: kvm: arm: fix build on 32-bit
+
+  [ Ubuntu: 5.4.0-103.117 ]
+
+  * CVE-2022-23960
+    - arm64: Add part number for Arm Cortex-A77
+    - arm64: Add Neoverse-N2, Cortex-A710 CPU part definition
+    - arm64: Add Cortex-X2 CPU part definition
+    - arm64: add ID_AA64ISAR2_EL1 sys register
+    - SAUCE: arm64: entry.S: Add ventry overflow sanity checks
+    - SAUCE: arm64: entry: Make the trampoline cleanup optional
+    - SAUCE: arm64: entry: Free up another register on kpti's tramp_exit path
+    - SAUCE: arm64: entry: Move the trampoline data page before the text page
+    - SAUCE: arm64: entry: Allow tramp_alias to access symbols after the 4K
+      boundary
+    - SAUCE: arm64: entry: Don't assume tramp_vectors is the start of the vectors
+    - SAUCE: arm64: entry: Move trampoline macros out of ifdef'd section
+    - SAUCE: arm64: entry: Make the kpti trampoline's kpti sequence optional
+    - SAUCE: arm64: entry: Allow the trampoline text to occupy multiple pages
+    - SAUCE: arm64: entry: Add non-kpti __bp_harden_el1_vectors for mitigations
+    - SAUCE: arm64: entry: Add vectors that have the bhb mitigation sequences
+    - SAUCE: arm64: entry: Add macro for reading symbol addresses from the
+      trampoline
+    - SAUCE: arm64: Add percpu vectors for EL1
+    - SAUCE: arm64: proton-pack: Report Spectre-BHB vulnerabilities as part of
+      Spectre-v2
+    - SAUCE: KVM: arm64: Add templates for BHB mitigation sequences
+    - SAUCE: arm64: Mitigate spectre style branch history side channels
+    - SAUCE: KVM: arm64: Allow SMCCC_ARCH_WORKAROUND_3 to be discovered and
+      migrated
+    - SAUCE: arm64: Use the clearbhb instruction in mitigations
+    - [Config]: set CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY=y
+  * CVE-2022-25636
+    - netfilter: nf_tables_offload: incorrect flow offload action array size
+  * CVE-2022-0001
+    - x86/speculation: Merge one test in spectre_v2_user_select_mitigation()
+    - x86,bugs: Unconditionally allow spectre_v2=retpoline,amd
+    - SAUCE: x86/speculation: Rename RETPOLINE_AMD to RETPOLINE_LFENCE
+    - SAUCE: x86/speculation: Add eIBRS + Retpoline options
+    - SAUCE: Documentation/hw-vuln: Update spectre doc
+  * Disable unprivileged BPF by default (LP: #1961338)
+    - bpf: Add kconfig knob for disabling unpriv bpf by default
+    - [Config] set CONFIG_BPF_UNPRIV_DEFAULT_OFF=y
+
+  [ Ubuntu: 5.4.0-100.113 ]
+
+  * focal/linux: 5.4.0-100.113 -proposed tracker (LP: #1959900)
+  * CVE-2022-22942
+    - SAUCE: drm/vmwgfx: Fix stale file descriptors on failed usercopy
+  * CVE-2022-0330
+    - drm/i915: Flush TLBs before releasing backing store
+  * Focal update: v5.4.166 upstream stable release (LP: #1957008)
+    - netfilter: selftest: conntrack_vrf.sh: fix file permission
+    - Linux 5.4.166
+    - net/packet: rx_owner_map depends on pg_vec
+    - USB: gadget: bRequestType is a bitfield, not a enum
+    - HID: holtek: fix mouse probing
+    - udp: using datalen to cap ipv6 udp max gso segments
+    - selftests: Calculate udpgso segment count without header adjustment
+  * Focal update: v5.4.165 upstream stable release (LP: #1957007)
+    - serial: tegra: Change lower tolerance baud rate limit for tegra20 and
+      tegra30
+    - ntfs: fix ntfs_test_inode and ntfs_init_locked_inode function type
+    - HID: quirks: Add quirk for the Microsoft Surface 3 type-cover
+    - HID: google: add eel USB id
+    - HID: add hid_is_usb() function to make it simpler for USB detection
+    - HID: add USB_HID dependancy to hid-prodikeys
+    - HID: add USB_HID dependancy to hid-chicony
+    - HID: add USB_HID dependancy on some USB HID drivers
+    - HID: bigbenff: prevent null pointer dereference
+    - HID: wacom: fix problems when device is not a valid USB device
+    - HID: check for valid USB device for many HID drivers
+    - can: kvaser_usb: get CAN clock frequency from device
+    - can: kvaser_pciefd: kvaser_pciefd_rx_error_frame(): increase correct
+      stats->{rx,tx}_errors counter
+    - can: sja1000: fix use after free in ems_pcmcia_add_card()
+    - nfc: fix potential NULL pointer deref in nfc_genl_dump_ses_done
+    - selftests: netfilter: add a vrf+conntrack testcase
+    - vrf: don't run conntrack on vrf with !dflt qdisc
+    - bpf: Fix the off-by-two error in range markings
+    - ice: ignore dropped packets during init
+    - bonding: make tx_rebalance_counter an atomic
+    - nfp: Fix memory leak in nfp_cpp_area_cache_add()
+    - seg6: fix the iif in the IPv6 socket control block
+    - udp: using datalen to cap max gso segments
+    - iavf: restore MSI state on reset
+    - iavf: Fix reporting when setting descriptor count
+    - IB/hfi1: Correct guard on eager buffer deallocation
+    - mm: bdi: initialize bdi_min_ratio when bdi is unregistered
+    - ALSA: ctl: Fix copy of updated id with element read/write
+    - ALSA: hda/realtek - Add headset Mic support for Lenovo ALC897 platform
+    - ALSA: pcm: oss: Fix negative period/buffer sizes
+    - ALSA: pcm: oss: Limit the period size to 16MB
+    - ALSA: pcm: oss: Handle missing errors in snd_pcm_oss_change_params*()
+    - btrfs: clear extent buffer uptodate when we fail to write it
+    - btrfs: replace the BUG_ON in btrfs_del_root_ref with proper error handling
+    - nfsd: Fix nsfd startup race (again)
+    - tracefs: Have new files inherit the ownership of their parent
+    - clk: qcom: regmap-mux: fix parent clock lookup
+    - drm/syncobj: Deal with signalled fences in drm_syncobj_find_fence.
+    - can: pch_can: pch_can_rx_normal: fix use after free
+    - can: m_can: Disable and ignore ELO interrupt
+    - x86/sme: Explicitly map new EFI memmap table as encrypted
+    - libata: add horkage for ASMedia 1092
+    - wait: add wake_up_pollfree()
+    - SAUCE: binder: export __wake_up_pollfree for binder module
+    - binder: use wake_up_pollfree()
+    - signalfd: use wake_up_pollfree()
+    - aio: keep poll requests on waitqueue until completed
+    - aio: fix use-after-free due to missing POLLFREE handling
+    - tracefs: Set all files to the same group ownership as the mount option
+    - block: fix ioprio_get(IOPRIO_WHO_PGRP) vs setuid(2)
+    - qede: validate non LSO skb length
+    - ASoC: qdsp6: q6routing: Fix return value from msm_routing_put_audio_mixer
+    - i40e: Fix failed opcode appearing if handling messages from VF
+    - i40e: Fix pre-set max number of queues for VF
+    - mtd: rawnand: fsmc: Take instruction delay into account
+    - mtd: rawnand: fsmc: Fix timing computation
+    - dt-bindings: net: Reintroduce PHY no lane swap binding
+    - tools build: Remove needless libpython-version feature check that breaks
+      test-all fast path
+    - net: cdc_ncm: Allow for dwNtbOutMaxSize to be unset or zero
+    - net: altera: set a couple error code in probe()
+    - net: fec: only clear interrupt of handling queue in fec_enet_rx_queue()
+    - net, neigh: clear whole pneigh_entry at alloc time
+    - net/qla3xxx: fix an error code in ql_adapter_up()
+    - Revert "UBUNTU: SAUCE: selftests: fib_tests: assign address to dummy1 for
+      rp_filter tests"
+    - selftests/fib_tests: Rework fib_rp_filter_test()
+    - USB: gadget: detect too-big endpoint 0 requests
+    - USB: gadget: zero allocate endpoint 0 buffers
+    - usb: core: config: fix validation of wMaxPacketValue entries
+    - xhci: Remove CONFIG_USB_DEFAULT_PERSIST to prevent xHCI from runtime
+      suspending
+    - usb: core: config: using bit mask instead of individual bits
+    - xhci: avoid race between disable slot command and host runtime suspend
+    - iio: trigger: Fix reference counting
+    - iio: trigger: stm32-timer: fix MODULE_ALIAS
+    - iio: stk3310: Don't return error code in interrupt handler
+    - iio: mma8452: Fix trigger reference couting
+    - iio: ltr501: Don't return error code in trigger handler
+    - iio: kxsd9: Don't return error code in trigger handler
+    - iio: itg3200: Call iio_trigger_notify_done() on error
+    - iio: dln2-adc: Fix lockdep complaint
+    - iio: dln2: Check return value of devm_iio_trigger_register()
+    - iio: at91-sama5d2: Fix incorrect sign extension
+    - iio: adc: axp20x_adc: fix charging current reporting on AXP22x
+    - iio: ad7768-1: Call iio_trigger_notify_done() on error
+    - iio: accel: kxcjk-1013: Fix possible memory leak in probe and remove
+    - irqchip/armada-370-xp: Fix return value of armada_370_xp_msi_alloc()
+    - irqchip/armada-370-xp: Fix support for Multi-MSI interrupts
+    - irqchip/irq-gic-v3-its.c: Force synchronisation when issuing INVALL
+    - irqchip: nvic: Fix offset for Interrupt Priority Offsets
+    - misc: fastrpc: fix improper packet size calculation
+    - bpf: Add selftests to cover packet access corner cases
+    - Linux 5.4.165
+  * Focal update: v5.4.164 upstream stable release (LP: #1956381)
+    - NFSv42: Fix pagecache invalidation after COPY/CLONE
+    - of: clk: Make <linux/of_clk.h> self-contained
+    - arm64: dts: mcbin: support 2W SFP modules
+    - can: j1939: j1939_tp_cmd_recv(): check the dst address of TP.CM_BAM
+    - gfs2: Fix length of holes reported at end-of-file
+    - drm/sun4i: fix unmet dependency on RESET_CONTROLLER for PHY_SUN6I_MIPI_DPHY
+    - mac80211: do not access the IV when it was stripped
+    - net/smc: Transfer remaining wait queue entries during fallback
+    - atlantic: Fix OOB read and write in hw_atl_utils_fw_rpc_wait
+    - net: return correct error code
+    - platform/x86: thinkpad_acpi: Fix WWAN device disabled issue after S3 deep
+    - s390/setup: avoid using memblock_enforce_memory_limit
+    - btrfs: check-integrity: fix a warning on write caching disabled disk
+    - thermal: core: Reset previous low and high trip during thermal zone init
+    - scsi: iscsi: Unblock session then wake up error handler
+    - ata: ahci: Add Green Sardine vendor ID as board_ahci_mobile
+    - ethernet: hisilicon: hns: hns_dsaf_misc: fix a possible array overflow in
+      hns_dsaf_ge_srst_by_port()
+    - net: tulip: de4x5: fix the problem that the array 'lp->phy[8]' may be out of
+      bound
+    - net: ethernet: dec: tulip: de4x5: fix possible array overflows in
+      type3_infoblock()
+    - perf hist: Fix memory leak of a perf_hpp_fmt
+    - perf report: Fix memory leaks around perf_tip()
+    - net/smc: Avoid warning of possible recursive locking
+    - vrf: Reset IPCB/IP6CB when processing outbound pkts in vrf dev xmit
+    - kprobes: Limit max data_size of the kretprobe instances
+    - rt2x00: do not mark device gone on EPROTO errors during start
+    - cpufreq: Fix get_cpu_device() failure in add_cpu_dev_symlink()
+    - s390/pci: move pseudo-MMIO to prevent MIO overlap
+    - sata_fsl: fix UAF in sata_fsl_port_stop when rmmod sata_fsl
+    - sata_fsl: fix warning in remove_proc_entry when rmmod sata_fsl
+    - i2c: stm32f7: flush TX FIFO upon transfer errors
+    - i2c: stm32f7: recover the bus on access timeout
+    - i2c: stm32f7: stop dma transfer in case of NACK
+    - i2c: cbus-gpio: set atomic transfer callback
+    - natsemi: xtensa: fix section mismatch warnings
+    - net: qlogic: qlcnic: Fix a NULL pointer dereference in
+      qlcnic_83xx_add_rings()
+    - net: mpls: Fix notifications when deleting a device
+    - siphash: use _unaligned version by default
+    - net/mlx4_en: Fix an use-after-free bug in mlx4_en_try_alloc_resources()
+    - selftests: net: Correct case name
+    - rxrpc: Fix rxrpc_local leak in rxrpc_lookup_peer()
+    - net: usb: lan78xx: lan78xx_phy_init(): use PHY_POLL instead of "0" if no IRQ
+      is available
+    - net: marvell: mvpp2: Fix the computation of shared CPUs
+    - net: annotate data-races on txq->xmit_lock_owner
+    - ipv4: convert fib_num_tclassid_users to atomic_t
+    - net/rds: correct socket tunable error in rds_tcp_tune()
+    - net/smc: Keep smc_close_final rc during active close
+    - drm/msm: Do hw_init() before capturing GPU state
+    - ipv6: fix memory leak in fib6_rule_suppress
+    - KVM: x86/pmu: Fix reserved bits for AMD PerfEvtSeln register
+    - sched/uclamp: Fix rq->uclamp_max not set on first enqueue
+    - parisc: Fix KBUILD_IMAGE for self-extracting kernel
+    - parisc: Fix "make install" on newer debian releases
+    - vgacon: Propagate console boot parameters before calling `vc_resize'
+    - xhci: Fix commad ring abort, write all 64 bits to CRCR register.
+    - USB: NO_LPM quirk Lenovo Powered USB-C Travel Hub
+    - usb: typec: tcpm: Wait in SNK_DEBOUNCED until disconnect
+    - x86/tsc: Add a timer to make sure TSC_adjust is always checked
+    - x86/tsc: Disable clocksource watchdog for TSC on qualified platorms
+    - x86/64/mm: Map all kernel memory into trampoline_pgd
+    - tty: serial: msm_serial: Deactivate RX DMA for polling support
+    - serial: pl011: Add ACPI SBSA UART match id
+    - serial: core: fix transmit-buffer reset and memleak
+    - serial: 8250_pci: Fix ACCES entries in pci_serial_quirks array
+    - serial: 8250_pci: rewrite pericom_do_set_divisor()
+    - iwlwifi: mvm: retry init flow if failed
+    - parisc: Mark cr16 CPU clocksource unstable on all SMP machines
+    - net/tls: Fix authentication failure in CCM mode
+    - Linux 5.4.164
+  * Focal update: v5.4.163 upstream stable release (LP: #1956380)
+    - USB: serial: option: add Telit LE910S1 0x9200 composition
+    - USB: serial: option: add Fibocom FM101-GL variants
+    - usb: dwc2: gadget: Fix ISOC flow for elapsed frames
+    - usb: dwc2: hcd_queue: Fix use of floating point literal
+    - net: nexthop: fix null pointer dereference when IPv6 is not enabled
+    - usb: typec: fusb302: Fix masking of comparator and bc_lvl interrupts
+    - usb: hub: Fix usb enumeration issue due to address0 race
+    - usb: hub: Fix locking issues with address0_mutex
+    - binder: fix test regression due to sender_euid change
+    - ALSA: ctxfi: Fix out-of-range access
+    - media: cec: copy sequence field for the reply
+    - HID: wacom: Use "Confidence" flag to prevent reporting invalid contacts
+    - staging/fbtft: Fix backlight
+    - staging: rtl8192e: Fix use after free in _rtl92e_pci_disconnect()
+    - xen: don't continue xenstore initialization in case of errors
+    - xen: detect uninitialized xenbus in xenbus_init
+    - KVM: PPC: Book3S HV: Prevent POWER7/8 TLB flush flushing SLB
+    - tracing/uprobe: Fix uprobe_perf_open probes iteration
+    - tracing: Fix pid filtering when triggers are attached
+    - mmc: sdhci: Fix ADMA for PAGE_SIZE >= 64KiB
+    - mdio: aspeed: Fix "Link is Down" issue
+    - PCI: aardvark: Deduplicate code in advk_pcie_rd_conf()
+    - PCI: aardvark: Wait for endpoint to be ready before training link
+    - PCI: aardvark: Fix big endian support
+    - PCI: aardvark: Train link immediately after enabling training
+    - PCI: aardvark: Improve link training
+    - PCI: aardvark: Issue PERST via GPIO
+    - PCI: aardvark: Replace custom macros by standard linux/pci_regs.h macros
+    - PCI: aardvark: Don't touch PCIe registers if no card connected
+    - PCI: aardvark: Fix compilation on s390
+    - PCI: aardvark: Move PCIe reset card code to advk_pcie_train_link()
+    - PCI: aardvark: Update comment about disabling link training
+    - PCI: pci-bridge-emul: Fix array overruns, improve safety
+    - PCI: aardvark: Configure PCIe resources from 'ranges' DT property
+    - PCI: aardvark: Fix PCIe Max Payload Size setting
+    - PCI: aardvark: Implement re-issuing config requests on CRS response
+    - PCI: aardvark: Simplify initialization of rootcap on virtual bridge
+    - PCI: aardvark: Fix link training
+    - PCI: aardvark: Fix support for bus mastering and PCI_COMMAND on emulated
+      bridge
+    - PCI: aardvark: Set PCI Bridge Class Code to PCI Bridge
+    - PCI: aardvark: Fix support for PCI_BRIDGE_CTL_BUS_RESET on emulated bridge
+    - pinctrl: armada-37xx: Correct PWM pins definitions
+    - arm64: dts: marvell: armada-37xx: Set pcie_reset_pin to gpio function
+    - proc/vmcore: fix clearing user buffer by properly using clear_user()
+    - netfilter: ipvs: Fix reuse connection if RS weight is 0
+    - ARM: dts: BCM5301X: Fix I2C controller interrupt
+    - ARM: dts: BCM5301X: Add interrupt properties to GPIO node
+    - ASoC: qdsp6: q6routing: Conditionally reset FrontEnd Mixer
+    - ASoC: topology: Add missing rwsem around snd_ctl_remove() calls
+    - net: ieee802154: handle iftypes as u32
+    - firmware: arm_scmi: pm: Propagate return value to caller
+    - NFSv42: Don't fail clone() unless the OP_CLONE operation failed
+    - ARM: socfpga: Fix crash with CONFIG_FORTIRY_SOURCE
+    - scsi: mpt3sas: Fix kernel panic during drive powercycle test
+    - drm/vc4: fix error code in vc4_create_object()
+    - iavf: Prevent changing static ITR values if adaptive moderation is on
+    - ipv6: fix typos in __ip6_finish_output()
+    - nfp: checking parameter process for rx-usecs/tx-usecs is invalid
+    - net: ipv6: add fib6_nh_release_dsts stub
+    - net: nexthop: release IPv6 per-cpu dsts when replacing a nexthop group
+    - scsi: core: sysfs: Fix setting device state to SDEV_RUNNING
+    - net/smc: Ensure the active closing peer first closes clcsock
+    - nvmet-tcp: fix incomplete data digest send
+    - net/ncsi : Add payload to be 32-bit aligned to fix dropped packets
+    - PM: hibernate: use correct mode for swsusp_close()
+    - tcp_cubic: fix spurious Hystart ACK train detections for not-cwnd-limited
+      flows
+    - nvmet: use IOCB_NOWAIT only if the filesystem supports it
+    - igb: fix netpoll exit with traffic
+    - MIPS: use 3-level pgtable for 64KB page size on MIPS_VA_BITS_48
+    - net: vlan: fix underflow for the real_dev refcnt
+    - net/smc: Don't call clcsock shutdown twice when smc shutdown
+    - net: hns3: fix VF RSS failed problem after PF enable multi-TCs
+    - net: mscc: ocelot: don't downgrade timestamping RX filters in SIOCSHWTSTAMP
+    - net: mscc: ocelot: correctly report the timestamping RX filters in ethtool
+    - f2fs: set SBI_NEED_FSCK flag when inconsistent node block found
+    - smb3: do not error on fsync when readonly
+    - vhost/vsock: fix incorrect used length reported to the guest
+    - tracing: Check pid filtering when creating events
+    - s390/mm: validate VMA in PGSTE manipulation functions
+    - shm: extend forced shm destroy to support objects from several IPC nses
+    - NFC: add NCI_UNREG flag to eliminate the race
+    - fuse: release pipe buf after last use
+    - xen: sync include/xen/interface/io/ring.h with Xen's newest version
+    - xen/blkfront: read response from backend only once
+    - xen/blkfront: don't take local copy of a request from the ring page
+    - xen/blkfront: don't trust the backend response data blindly
+    - xen/netfront: read response from backend only once
+    - xen/netfront: don't read data from request on the ring page
+    - xen/netfront: disentangle tx_skb_freelist
+    - xen/netfront: don't trust the backend response data blindly
+    - tty: hvc: replace BUG_ON() with negative return value
+    - Linux 5.4.163
+  * net/mlx5e: EPERM on vlan 0 programming (LP: #1957753)
+    - net/mlx5e: Unblock setting vid 0 for VF in case PF isn't eswitch manager
+  * CVE-2021-4083
+    - fget: check that the fd still exists after getting a ref to it
+  * CVE-2021-4155
+    - xfs: map unwritten blocks in XFS_IOC_{ALLOC, FREE}SP just like fallocate
+
+  [ Ubuntu: 5.4.0-99.112 ]
+
+  * focal/linux: 5.4.0-99.112 -proposed tracker (LP: #1959817)
+  * linux-image-5.4.0-97.110 freezes by accessing cifs shares (LP: #1959665)
+    - Revert "cifs: To match file servers, make sure the server hostname matches"
+    - Revert "cifs: set a minimum of 120s for next dns resolution"
+    - Revert "cifs: use the expiry output of dns_query to schedule next
+      resolution"
+
+  [ Ubuntu: 5.4.0-97.110 ]
+
+  * icmp_redirect from selftests fails on F/kvm (unary operator expected)
+    (LP: #1938964)
+    - selftests: icmp_redirect: pass xfail=0 to log_test()
+  * Focal: CIFS stable updates (LP: #1954926)
+    - cifs: use the expiry output of dns_query to schedule next resolution
+    - cifs: set a minimum of 120s for next dns resolution
+    - cifs: To match file servers, make sure the server hostname matches
+  * seccomp_bpf in seccomp from ubuntu_kernel_selftests failed to build on B-5.4
+    (LP: #1896420)
+    - SAUCE: selftests/seccomp: fix "storage size of 'md' isn't known" build issue
+    - SAUCE: selftests/seccomp: Fix s390x regs not defined issue
+  * system crash when removing ipmi_msghandler module (LP: #1950666)
+    - ipmi: Move remove_work to dedicated workqueue
+    - ipmi: msghandler: Make symbol 'remove_work_wq' static
+  * zcrypt DD: Toleration for new IBM Z Crypto Hardware - (Backport to Ubuntu
+    20.04) (LP: #1954680)
+    - s390/AP: support new dynamic AP bus size limit
+  * [UBUNTU 20.04] KVM hardware diagnose data improvements for guest kernel -
+    kernel part (LP: #1953334)
+    - s390/setup: diag 318: refactor struct
+    - s390/kvm: diagnose 0x318 sync and reset
+    - KVM: s390: remove diag318 reset code
+    - KVM: s390: add debug statement for diag 318 CPNC data
+  * Updates to ib_peer_memory requested by Nvidia (LP: #1947206)
+    - SAUCE: RDMA/core: Updated ib_peer_memory
+  * Include Infiniband Peer Memory interface (LP: #1923104)
+    - IB: Allow calls to ib_umem_get from kernel ULPs
+    - SAUCE: RDMA/core: Introduce peer memory interface
+  * Focal update: v5.4.162 upstream stable release (LP: #1954834)
+    - arm64: zynqmp: Do not duplicate flash partition label property
+    - arm64: zynqmp: Fix serial compatible string
+    - ARM: dts: NSP: Fix mpcore, mmc node names
+    - scsi: lpfc: Fix list_add() corruption in lpfc_drain_txq()
+    - arm64: dts: hisilicon: fix arm,sp805 compatible string
+    - RDMA/bnxt_re: Check if the vlan is valid before reporting
+    - usb: musb: tusb6010: check return value after calling
+      platform_get_resource()
+    - usb: typec: tipd: Remove WARN_ON in tps6598x_block_read
+    - arm64: dts: qcom: msm8998: Fix CPU/L2 idle state latency and residency
+    - arm64: dts: freescale: fix arm,sp805 compatible string
+    - ASoC: SOF: Intel: hda-dai: fix potential locking issue
+    - clk: imx: imx6ul: Move csi_sel mux to correct base register
+    - ASoC: nau8824: Add DMI quirk mechanism for active-high jack-detect
+    - scsi: advansys: Fix kernel pointer leak
+    - firmware_loader: fix pre-allocated buf built-in firmware use
+    - ARM: dts: omap: fix gpmc,mux-add-data type
+    - usb: host: ohci-tmio: check return value after calling
+      platform_get_resource()
+    - ARM: dts: ls1021a: move thermal-zones node out of soc/
+    - ARM: dts: ls1021a-tsn: use generic "jedec,spi-nor" compatible for flash
+    - ALSA: ISA: not for M68K
+    - tty: tty_buffer: Fix the softlockup issue in flush_to_ldisc
+    - MIPS: sni: Fix the build
+    - scsi: target: Fix ordered tag handling
+    - scsi: target: Fix alua_tg_pt_gps_count tracking
+    - iio: imu: st_lsm6dsx: Avoid potential array overflow in st_lsm6dsx_set_odr()
+    - powerpc/5200: dts: fix memory node unit name
+    - ALSA: gus: fix null pointer dereference on pointer block
+    - powerpc/dcr: Use cmplwi instead of 3-argument cmpli
+    - sh: check return code of request_irq
+    - maple: fix wrong return value of maple_bus_init().
+    - f2fs: fix up f2fs_lookup tracepoints
+    - sh: fix kconfig unmet dependency warning for FRAME_POINTER
+    - sh: math-emu: drop unused functions
+    - sh: define __BIG_ENDIAN for math-emu
+    - clk: ingenic: Fix bugs with divided dividers
+    - clk/ast2600: Fix soc revision for AHB
+    - clk: qcom: gcc-msm8996: Drop (again) gcc_aggre1_pnoc_ahb_clk
+    - mips: BCM63XX: ensure that CPU_SUPPORTS_32BIT_KERNEL is set
+    - sched/core: Mitigate race cpus_share_cache()/update_top_cache_domain()
+    - tracing: Save normal string variables
+    - tracing/histogram: Do not copy the fixed-size char array field over the
+      field size
+    - RDMA/netlink: Add __maybe_unused to static inline in C file
+    - perf bpf: Avoid memory leak from perf_env__insert_btf()
+    - perf bench futex: Fix memory leak of perf_cpu_map__new()
+    - perf tests: Remove bash construct from record+zstd_comp_decomp.sh
+    - net: bnx2x: fix variable dereferenced before check
+    - iavf: check for null in iavf_fix_features
+    - iavf: free q_vectors before queues in iavf_disable_vf
+    - iavf: Fix failure to exit out from last all-multicast mode
+    - iavf: prevent accidental free of filter structure
+    - iavf: validate pointers
+    - iavf: Fix for the false positive ASQ/ARQ errors while issuing VF reset
+    - MIPS: generic/yamon-dt: fix uninitialized variable error
+    - mips: bcm63xx: add support for clk_get_parent()
+    - mips: lantiq: add support for clk_get_parent()
+    - platform/x86: hp_accel: Fix an error handling path in 'lis3lv02d_probe()'
+    - scsi: core: sysfs: Fix hang when device state is set via sysfs
+    - net: sched: act_mirred: drop dst for the direction from egress to ingress
+    - net: dpaa2-eth: fix use-after-free in dpaa2_eth_remove
+    - net: virtio_net_hdr_to_skb: count transport header in UFO
+    - i40e: Fix correct max_pkt_size on VF RX queue
+    - i40e: Fix NULL ptr dereference on VSI filter sync
+    - i40e: Fix changing previously set num_queue_pairs for PFs
+    - i40e: Fix ping is lost after configuring ADq on VF
+    - i40e: Fix creation of first queue by omitting it if is not power of two
+    - i40e: Fix display error code in dmesg
+    - NFC: reorganize the functions in nci_request
+    - drm/nouveau: hdmigv100.c: fix corrupted HDMI Vendor InfoFrame
+    - NFC: reorder the logic in nfc_{un,}register_device
+    - KVM: PPC: Book3S HV: Use GLOBAL_TOC for kvmppc_h_set_dabr/xdabr()
+    - perf/x86/intel/uncore: Fix filter_tid mask for CHA events on Skylake Server
+    - perf/x86/intel/uncore: Fix IIO event constraints for Skylake Server
+    - s390/kexec: fix return code handling
+    - arm64: vdso32: suppress error message for 'make mrproper'
+    - tun: fix bonding active backup with arp monitoring
+    - hexagon: export raw I/O routines for modules
+    - ipc: WARN if trying to remove ipc object which is absent
+    - mm: kmemleak: slob: respect SLAB_NOLEAKTRACE flag
+    - x86/hyperv: Fix NULL deref in set_hv_tscchange_cb() if Hyper-V setup fails
+    - s390/kexec: fix memory leak of ipl report buffer
+    - udf: Fix crash after seekdir
+    - btrfs: fix memory ordering between normal and ordered work functions
+    - parisc/sticon: fix reverse colors
+    - cfg80211: call cfg80211_stop_ap when switch from P2P_GO type
+    - drm/udl: fix control-message timeout
+    - drm/nouveau: use drm_dev_unplug() during device removal
+    - drm/i915/dp: Ensure sink rate values are always valid
+    - drm/amdgpu: fix set scaling mode Full/Full aspect/Center not works on vga
+      and dvi connectors
+    - Revert "net: mvpp2: disable force link UP during port init procedure"
+    - perf/core: Avoid put_page() when GUP fails
+    - batman-adv: Consider fragmentation for needed_headroom
+    - batman-adv: Reserve needed_*room for fragments
+    - batman-adv: Don't always reallocate the fragmentation skb head
+    - ASoC: DAPM: Cover regression by kctl change notification fix
+    - usb: max-3421: Use driver data instead of maintaining a list of bound
+      devices
+    - ice: Delete always true check of PF pointer
+    - ALSA: hda: hdac_ext_stream: fix potential locking issues
+    - ALSA: hda: hdac_stream: fix potential locking issue in
+      snd_hdac_stream_assign()
+    - Linux 5.4.162
+  * Focal update: v5.4.161 upstream stable release (LP: #1954828)
+    - scsi: ufs: Fix interrupt error message for shared interrupts
+    - MIPS: Fix assembly error from MIPSr2 code used within MIPS_ISA_ARCH_LEVEL
+    - ext4: fix lazy initialization next schedule time computation in more
+      granular unit
+    - scsi: ufs: Fix tm request when non-fatal error happens
+    - fortify: Explicitly disable Clang support
+    - parisc/entry: fix trace test in syscall exit path
+    - PCI/MSI: Destroy sysfs before freeing entries
+    - PCI/MSI: Deal with devices lying about their MSI mask capability
+    - PCI: Add MSI masking quirk for Nvidia ION AHCI
+    - erofs: remove the occupied parameter from z_erofs_pagevec_enqueue()
+    - erofs: fix unsafe pagevec reuse of hooked pclusters
+    - Linux 5.4.161
+  * Focal update: v5.4.160 upstream stable release (LP: #1953387)
+    - xhci: Fix USB 3.1 enumeration issues by increasing roothub power-on-good
+      delay
+    - usb: xhci: Enable runtime-pm by default on AMD Yellow Carp platform
+    - binder: use euid from cred instead of using task
+    - binder: use cred instead of task for selinux checks
+    - binder: use cred instead of task for getsecid
+    - Input: iforce - fix control-message timeout
+    - Input: elantench - fix misreporting trackpoint coordinates
+    - Input: i8042 - Add quirk for Fujitsu Lifebook T725
+    - libata: fix read log timeout value
+    - ocfs2: fix data corruption on truncate
+    - scsi: qla2xxx: Fix kernel crash when accessing port_speed sysfs file
+    - scsi: qla2xxx: Fix use after free in eh_abort path
+    - mmc: dw_mmc: Dont wait for DRTO on Write RSP error
+    - parisc: Fix ptrace check on syscall return
+    - tpm: Check for integer overflow in tpm2_map_response_body()
+    - firmware/psci: fix application of sizeof to pointer
+    - crypto: s5p-sss - Add error handling in s5p_aes_probe()
+    - media: ite-cir: IR receiver stop working after receive overflow
+    - media: ir-kbd-i2c: improve responsiveness of hauppauge zilog receivers
+    - media: v4l2-ioctl: Fix check_ext_ctrls
+    - ALSA: hda/realtek: Add quirk for Clevo PC70HS
+    - ALSA: hda/realtek: Add a quirk for Acer Spin SP513-54N
+    - ALSA: hda/realtek: Add quirk for ASUS UX550VE
+    - ALSA: hda/realtek: Add quirk for HP EliteBook 840 G7 mute LED
+    - ALSA: ua101: fix division by zero at probe
+    - ALSA: 6fire: fix control and bulk message timeouts
+    - ALSA: line6: fix control and interrupt message timeouts
+    - ALSA: usb-audio: Add registration quirk for JBL Quantum 400
+    - ALSA: synth: missing check for possible NULL after the call to kstrdup
+    - ALSA: timer: Fix use-after-free problem
+    - ALSA: timer: Unconditionally unlink slave instances, too
+    - fuse: fix page stealing
+    - x86/sme: Use #define USE_EARLY_PGTABLE_L5 in mem_encrypt_identity.c
+    - x86/cpu: Fix migration safety with X86_BUG_NULL_SEL
+    - x86/irq: Ensure PI wakeup handler is unregistered before module unload
+    - cavium: Return negative value when pci_alloc_irq_vectors() fails
+    - scsi: qla2xxx: Return -ENOMEM if kzalloc() fails
+    - scsi: qla2xxx: Fix unmap of already freed sgl
+    - cavium: Fix return values of the probe function
+    - sfc: Don't use netif_info before net_device setup
+    - hyperv/vmbus: include linux/bitops.h
+    - ARM: dts: sun7i: A20-olinuxino-lime2: Fix ethernet phy-mode
+    - reset: socfpga: add empty driver allowing consumers to probe
+    - mmc: winbond: don't build on M68K
+    - drm: panel-orientation-quirks: Add quirk for Aya Neo 2021
+    - bpf: Define bpf_jit_alloc_exec_limit for arm64 JIT
+    - bpf: Prevent increasing bpf_jit_limit above max
+    - xen/netfront: stop tx queues during live migration
+    - nvmet-tcp: fix a memory leak when releasing a queue
+    - spi: spl022: fix Microwire full duplex mode
+    - net: multicast: calculate csum of looped-back and forwarded packets
+    - watchdog: Fix OMAP watchdog early handling
+    - drm: panel-orientation-quirks: Add quirk for GPD Win3
+    - nvmet-tcp: fix header digest verification
+    - r8169: Add device 10ec:8162 to driver r8169
+    - vmxnet3: do not stop tx queues after netif_device_detach()
+    - nfp: bpf: relax prog rejection for mtu check through max_pkt_offset
+    - net/smc: Correct spelling mistake to TCPF_SYN_RECV
+    - btrfs: clear MISSING device status bit in btrfs_close_one_device
+    - btrfs: fix lost error handling when replaying directory deletes
+    - btrfs: call btrfs_check_rw_degradable only if there is a missing device
+    - ia64: kprobes: Fix to pass correct trampoline address to the handler
+    - hwmon: (pmbus/lm25066) Add offset coefficients
+    - regulator: s5m8767: do not use reset value as DVS voltage if GPIO DVS is
+      disabled
+    - regulator: dt-bindings: samsung,s5m8767: correct s5m8767,pmic-buck-default-
+      dvs-idx property
+    - EDAC/sb_edac: Fix top-of-high-memory value for Broadwell/Haswell
+    - mwifiex: fix division by zero in fw download path
+    - ath6kl: fix division by zero in send path
+    - ath6kl: fix control-message timeout
+    - ath10k: fix control-message timeout
+    - ath10k: fix division by zero in send path
+    - PCI: Mark Atheros QCA6174 to avoid bus reset
+    - rtl8187: fix control-message timeouts
+    - evm: mark evm_fixmode as __ro_after_init
+    - wcn36xx: Fix HT40 capability for 2Ghz band
+    - mwifiex: Read a PCI register after writing the TX ring write pointer
+    - libata: fix checking of DMA state
+    - wcn36xx: handle connection loss indication
+    - rsi: fix occasional initialisation failure with BT coex
+    - rsi: fix key enabled check causing unwanted encryption for vap_id > 0
+    - rsi: fix rate mask set leading to P2P failure
+    - rsi: Fix module dev_oper_mode parameter description
+    - RDMA/qedr: Fix NULL deref for query_qp on the GSI QP
+    - signal: Remove the bogus sigkill_pending in ptrace_stop
+    - signal/mips: Update (_save|_restore)_fp_context to fail with -EFAULT
+    - power: supply: max17042_battery: Prevent int underflow in set_soc_threshold
+    - power: supply: max17042_battery: use VFSOC for capacity when no rsns
+    - KVM: nVMX: Query current VMCS when determining if MSR bitmaps are in use
+    - can: j1939: j1939_tp_cmd_recv(): ignore abort message in the BAM transport
+    - can: j1939: j1939_can_recv(): ignore messages with invalid source address
+    - powerpc/85xx: Fix oops when mpc85xx_smp_guts_ids node cannot be found
+    - serial: core: Fix initializing and restoring termios speed
+    - ALSA: mixer: oss: Fix racy access to slots
+    - ALSA: mixer: fix deadlock in snd_mixer_oss_set_volume
+    - xen/balloon: add late_initcall_sync() for initial ballooning done
+    - PCI: pci-bridge-emul: Fix emulation of W1C bits
+    - PCI: aardvark: Do not clear status bits of masked interrupts
+    - PCI: aardvark: Fix checking for link up via LTSSM state
+    - PCI: aardvark: Do not unmask unused interrupts
+    - PCI: aardvark: Fix reporting Data Link Layer Link Active
+    - PCI: aardvark: Fix return value of MSI domain .alloc() method
+    - PCI: aardvark: Read all 16-bits from PCIE_MSI_PAYLOAD_REG
+    - quota: check block number when reading the block in quota file
+    - quota: correct error number in free_dqentry()
+    - pinctrl: core: fix possible memory leak in pinctrl_enable()
+    - iio: dac: ad5446: Fix ad5622_write() return value
+    - USB: serial: keyspan: fix memleak on probe errors
+    - USB: iowarrior: fix control-message timeouts
+    - USB: chipidea: fix interrupt deadlock
+    - dma-buf: WARN on dmabuf release with pending attachments
+    - drm: panel-orientation-quirks: Update the Lenovo Ideapad D330 quirk (v2)
+    - drm: panel-orientation-quirks: Add quirk for KD Kurio Smart C15200 2-in-1
+    - drm: panel-orientation-quirks: Add quirk for the Samsung Galaxy Book 10.6
+    - Bluetooth: sco: Fix lock_sock() blockage by memcpy_from_msg()
+    - Bluetooth: fix use-after-free error in lock_sock_nested()
+    - drm/panel-orientation-quirks: add Valve Steam Deck
+    - platform/x86: wmi: do not fail if disabling fails
+    - MIPS: lantiq: dma: add small delay after reset
+    - MIPS: lantiq: dma: reset correct number of channel
+    - locking/lockdep: Avoid RCU-induced noinstr fail
+    - net: sched: update default qdisc visibility after Tx queue cnt changes
+    - smackfs: Fix use-after-free in netlbl_catmap_walk()
+    - x86: Increase exception stack sizes
+    - mwifiex: Run SET_BSS_MODE when changing from P2P to STATION vif-type
+    - mwifiex: Properly initialize private structure on interface type changes
+    - ath10k: high latency fixes for beacon buffer
+    - media: mt9p031: Fix corrupted frame after restarting stream
+    - media: netup_unidvb: handle interrupt properly according to the firmware
+    - media: stm32: Potential NULL pointer dereference in dcmi_irq_thread()
+    - media: uvcvideo: Set capability in s_param
+    - media: uvcvideo: Return -EIO for control errors
+    - media: uvcvideo: Set unique vdev name based in type
+    - media: s5p-mfc: fix possible null-pointer dereference in s5p_mfc_probe()
+    - media: s5p-mfc: Add checking to s5p_mfc_probe().
+    - media: imx: set a media_device bus_info string
+    - media: mceusb: return without resubmitting URB in case of -EPROTO error.
+    - ia64: don't do IA64_CMPXCHG_DEBUG without CONFIG_PRINTK
+    - brcmfmac: Add DMI nvram filename quirk for Cyberbook T116 tablet
+    - media: rcar-csi2: Add checking to rcsi2_start_receiver()
+    - ipmi: Disable some operations during a panic
+    - ACPICA: Avoid evaluating methods too early during system resume
+    - media: ipu3-imgu: imgu_fmt: Handle properly try
+    - media: ipu3-imgu: VIDIOC_QUERYCAP: Fix bus_info
+    - media: usb: dvd-usb: fix uninit-value bug in dibusb_read_eeprom_byte()
+    - net-sysfs: try not to restart the syscall if it will fail eventually
+    - tracefs: Have tracefs directories not set OTH permission bits by default
+    - ath: dfs_pattern_detector: Fix possible null-pointer dereference in
+      channel_detector_create()
+    - iov_iter: Fix iov_iter_get_pages{,_alloc} page fault return value
+    - ACPI: battery: Accept charges over the design capacity as full
+    - leaking_addresses: Always print a trailing newline
+    - memstick: r592: Fix a UAF bug when removing the driver
+    - lib/xz: Avoid overlapping memcpy() with invalid input with in-place
+      decompression
+    - lib/xz: Validate the value before assigning it to an enum variable
+    - workqueue: make sysfs of unbound kworker cpumask more clever
+    - tracing/cfi: Fix cmp_entries_* functions signature mismatch
+    - mwl8k: Fix use-after-free in mwl8k_fw_state_machine()
+    - block: remove inaccurate requeue check
+    - nvmet: fix use-after-free when a port is removed
+    - nvmet-tcp: fix use-after-free when a port is removed
+    - nvme: drop scan_lock and always kick requeue list when removing namespaces
+    - PM: hibernate: Get block device exclusively in swsusp_check()
+    - selftests: kvm: fix mismatched fclose() after popen()
+    - iwlwifi: mvm: disable RX-diversity in powersave
+    - smackfs: use __GFP_NOFAIL for smk_cipso_doi()
+    - ARM: clang: Do not rely on lr register for stacktrace
+    - gre/sit: Don't generate link-local addr if addr_gen_mode is
+      IN6_ADDR_GEN_MODE_NONE
+    - ARM: 9136/1: ARMv7-M uses BE-8, not BE-32
+    - vrf: run conntrack only in context of lower/physdev for locally generated
+      packets
+    - net: annotate data-race in neigh_output()
+    - btrfs: do not take the uuid_mutex in btrfs_rm_device
+    - spi: bcm-qspi: Fix missing clk_disable_unprepare() on error in
+      bcm_qspi_probe()
+    - x86/hyperv: Protect set_hv_tscchange_cb() against getting preempted
+    - parisc: fix warning in flush_tlb_all
+    - task_stack: Fix end_of_stack() for architectures with upwards-growing stack
+    - parisc/unwind: fix unwinder when CONFIG_64BIT is enabled
+    - parisc/kgdb: add kgdb_roundup() to make kgdb work with idle polling
+    - netfilter: conntrack: set on IPS_ASSURED if flows enters internal stream
+      state
+    - selftests/bpf: Fix strobemeta selftest regression
+    - Bluetooth: fix init and cleanup of sco_conn.timeout_work
+    - rcu: Fix existing exp request check in sync_sched_exp_online_cleanup()
+    - drm/v3d: fix wait for TMU write combiner flush
+    - virtio-gpu: fix possible memory allocation failure
+    - net: net_namespace: Fix undefined member in key_remove_domain()
+    - cgroup: Make rebind_subsystems() disable v2 controllers all at once
+    - wilc1000: fix possible memory leak in cfg_scan_result()
+    - Bluetooth: btmtkuart: fix a memleak in mtk_hci_wmt_sync
+    - crypto: caam - disable pkc for non-E SoCs
+    - rxrpc: Fix _usecs_to_jiffies() by using usecs_to_jiffies()
+    - net: dsa: rtl8366rb: Fix off-by-one bug
+    - ath10k: Fix missing frame timestamp for beacon/probe-resp
+    - drm/amdgpu: fix warning for overflow check
+    - media: em28xx: add missing em28xx_close_extension
+    - media: cxd2880-spi: Fix a null pointer dereference on error handling path
+    - media: dvb-usb: fix ununit-value in az6027_rc_query
+    - media: TDA1997x: handle short reads of hdmi info frame.
+    - media: mtk-vpu: Fix a resource leak in the error handling path of
+      'mtk_vpu_probe()'
+    - media: radio-wl1273: Avoid card name truncation
+    - media: si470x: Avoid card name truncation
+    - media: tm6000: Avoid card name truncation
+    - media: cx23885: Fix snd_card_free call on null card pointer
+    - kprobes: Do not use local variable when creating debugfs file
+    - crypto: ecc - fix CRYPTO_DEFAULT_RNG dependency
+    - cpuidle: Fix kobject memory leaks in error paths
+    - media: em28xx: Don't use ops->suspend if it is NULL
+    - ath9k: Fix potential interrupt storm on queue reset
+    - EDAC/amd64: Handle three rank interleaving mode
+    - netfilter: nft_dynset: relax superfluous check on set updates
+    - media: dvb-frontends: mn88443x: Handle errors of clk_prepare_enable()
+    - crypto: qat - detect PFVF collision after ACK
+    - crypto: qat - disregard spurious PFVF interrupts
+    - hwrng: mtk - Force runtime pm ops for sleep ops
+    - b43legacy: fix a lower bounds test
+    - b43: fix a lower bounds test
+    - mmc: sdhci-omap: Fix NULL pointer exception if regulator is not configured
+    - memstick: avoid out-of-range warning
+    - memstick: jmb38x_ms: use appropriate free function in jmb38x_ms_alloc_host()
+    - net, neigh: Fix NTF_EXT_LEARNED in combination with NTF_USE
+    - hwmon: Fix possible memleak in __hwmon_device_register()
+    - hwmon: (pmbus/lm25066) Let compiler determine outer dimension of
+      lm25066_coeff
+    - ath10k: fix max antenna gain unit
+    - drm/msm: uninitialized variable in msm_gem_import()
+    - net: stream: don't purge sk_error_queue in sk_stream_kill_queues()
+    - mmc: mxs-mmc: disable regulator on error and in the remove function
+    - block: ataflop: fix breakage introduced at blk-mq refactoring
+    - platform/x86: thinkpad_acpi: Fix bitwise vs. logical warning
+    - mt76: mt76x02: fix endianness warnings in mt76x02_mac.c
+    - rsi: stop thread firstly in rsi_91x_init() error handling
+    - mwifiex: Send DELBA requests according to spec
+    - phy: micrel: ksz8041nl: do not use power down mode
+    - nvme-rdma: fix error code in nvme_rdma_setup_ctrl
+    - PM: hibernate: fix sparse warnings
+    - clocksource/drivers/timer-ti-dm: Select TIMER_OF
+    - drm/msm: Fix potential NULL dereference in DPU SSPP
+    - smackfs: use netlbl_cfg_cipsov4_del() for deleting cipso_v4_doi
+    - libbpf: Fix BTF data layout checks and allow empty BTF
+    - s390/gmap: don't unconditionally call pte_unmap_unlock() in __gmap_zap()
+    - irq: mips: avoid nested irq_enter()
+    - tcp: don't free a FIN sk_buff in tcp_remove_empty_skb()
+    - samples/kretprobes: Fix return value if register_kretprobe() failed
+    - KVM: s390: Fix handle_sske page fault handling
+    - libertas_tf: Fix possible memory leak in probe and disconnect
+    - libertas: Fix possible memory leak in probe and disconnect
+    - wcn36xx: add proper DMA memory barriers in rx path
+    - drm/amdgpu/gmc6: fix DMA mask from 44 to 40 bits
+    - net: amd-xgbe: Toggle PLL settings during rate change
+    - net: phylink: avoid mvneta warning when setting pause parameters
+    - crypto: pcrypt - Delay write to padata->info
+    - selftests/bpf: Fix fclose/pclose mismatch in test_progs
+    - udp6: allow SO_MARK ctrl msg to affect routing
+    - ibmvnic: don't stop queue in xmit
+    - ibmvnic: Process crqs after enabling interrupts
+    - RDMA/rxe: Fix wrong port_cap_flags
+    - clk: mvebu: ap-cpu-clk: Fix a memory leak in error handling paths
+    - ARM: s3c: irq-s3c24xx: Fix return value check for s3c24xx_init_intc()
+    - arm64: dts: rockchip: Fix GPU register width for RK3328
+    - ARM: dts: qcom: msm8974: Add xo_board reference clock to DSI0 PHY
+    - RDMA/bnxt_re: Fix query SRQ failure
+    - arm64: dts: meson-g12a: Fix the pwm regulator supply properties
+    - ARM: dts: at91: tse850: the emac<->phy interface is rmii
+    - scsi: dc395: Fix error case unwinding
+    - MIPS: loongson64: make CPU_LOONGSON64 depends on MIPS_FP_SUPPORT
+    - JFS: fix memleak in jfs_mount
+    - ALSA: hda: Reduce udelay() at SKL+ position reporting
+    - arm: dts: omap3-gta04a4: accelerometer irq fix
+    - soc/tegra: Fix an error handling path in tegra_powergate_power_up()
+    - memory: fsl_ifc: fix leak of irq and nand_irq in fsl_ifc_ctrl_probe
+    - clk: at91: check pmc node status before registering syscore ops
+    - video: fbdev: chipsfb: use memset_io() instead of memset()
+    - serial: 8250_dw: Drop wrong use of ACPI_PTR()
+    - usb: gadget: hid: fix error code in do_config()
+    - power: supply: rt5033_battery: Change voltage values to µV
+    - scsi: csiostor: Uninitialized data in csio_ln_vnp_read_cbfn()
+    - RDMA/mlx4: Return missed an error if device doesn't support steering
+    - staging: ks7010: select CRYPTO_HASH/CRYPTO_MICHAEL_MIC
+    - ARM: dts: stm32: fix SAI sub nodes register range
+    - ASoC: cs42l42: Correct some register default values
+    - ASoC: cs42l42: Defer probe if request_threaded_irq() returns EPROBE_DEFER
+    - phy: qcom-qusb2: Fix a memory leak on probe
+    - serial: xilinx_uartps: Fix race condition causing stuck TX
+    - HID: u2fzero: clarify error check and length calculations
+    - HID: u2fzero: properly handle timeouts in usb_submit_urb
+    - powerpc/44x/fsp2: add missing of_node_put
+    - mips: cm: Convert to bitfield API to fix out-of-bounds access
+    - power: supply: bq27xxx: Fix kernel crash on IRQ handler register error
+    - apparmor: fix error check
+    - rpmsg: Fix rpmsg_create_ept return when RPMSG config is not defined
+    - pnfs/flexfiles: Fix misplaced barrier in nfs4_ff_layout_prepare_ds
+    - drm/plane-helper: fix uninitialized variable reference
+    - PCI: aardvark: Don't spam about PIO Response Status
+    - PCI: aardvark: Fix preserving PCI_EXP_RTCTL_CRSSVE flag on emulated bridge
+    - opp: Fix return in _opp_add_static_v2()
+    - NFS: Fix deadlocks in nfs_scan_commit_list()
+    - fs: orangefs: fix error return code of orangefs_revalidate_lookup()
+    - mtd: spi-nor: hisi-sfc: Remove excessive clk_disable_unprepare()
+    - mtd: core: don't remove debugfs directory if device is in use
+    - dmaengine: at_xdmac: fix AT_XDMAC_CC_PERID() macro
+    - auxdisplay: img-ascii-lcd: Fix lock-up when displaying empty string
+    - auxdisplay: ht16k33: Connect backlight to fbdev
+    - auxdisplay: ht16k33: Fix frame buffer device blanking
+    - soc: fsl: dpaa2-console: free buffer before returning from
+      dpaa2_console_read
+    - netfilter: nfnetlink_queue: fix OOB when mac header was cleared
+    - dmaengine: dmaengine_desc_callback_valid(): Check for `callback_result`
+    - signal/sh: Use force_sig(SIGKILL) instead of do_group_exit(SIGKILL)
+    - m68k: set a default value for MEMORY_RESERVE
+    - watchdog: f71808e_wdt: fix inaccurate report in WDIOC_GETTIMEOUT
+    - ar7: fix kernel builds for compiler test
+    - scsi: qla2xxx: Fix gnl list corruption
+    - scsi: qla2xxx: Turn off target reset during issue_lip
+    - NFSv4: Fix a regression in nfs_set_open_stateid_locked()
+    - i2c: xlr: Fix a resource leak in the error handling path of
+      'xlr_i2c_probe()'
+    - xen-pciback: Fix return in pm_ctrl_init()
+    - net: davinci_emac: Fix interrupt pacing disable
+    - net: vlan: fix a UAF in vlan_dev_real_dev()
+    - ACPI: PMIC: Fix intel_pmic_regs_handler() read accesses
+    - bonding: Fix a use-after-free problem when bond_sysfs_slave_add() failed
+    - mm/zsmalloc.c: close race window between zs_pool_dec_isolated() and
+      zs_unregister_migration()
+    - zram: off by one in read_block_state()
+    - perf bpf: Add missing free to bpf_event__print_bpf_prog_info()
+    - llc: fix out-of-bound array index in llc_sk_dev_hash()
+    - nfc: pn533: Fix double free when pn533_fill_fragment_skbs() fails
+    - arm64: pgtable: make __pte_to_phys/__phys_to_pte_val inline functions
+    - bpf: sockmap, strparser, and tls are reusing qdisc_skb_cb and colliding
+    - net/sched: sch_taprio: fix undefined behavior in ktime_mono_to_any
+    - net: hns3: allow configure ETS bandwidth of all TCs
+    - vsock: prevent unnecessary refcnt inc for nonblocking connect
+    - net/smc: fix sk_refcnt underflow on linkdown and fallback
+    - cxgb4: fix eeprom len when diagnostics not implemented
+    - selftests/net: udpgso_bench_rx: fix port argument
+    - ARM: 9155/1: fix early early_iounmap()
+    - ARM: 9156/1: drop cc-option fallbacks for architecture selection
+    - parisc: Fix set_fixmap() on PA1.x CPUs
+    - irqchip/sifive-plic: Fixup EOI failed when masked
+    - f2fs: should use GFP_NOFS for directory inodes
+    - net, neigh: Enable state migration between NUD_PERMANENT and NTF_USE
+    - 9p/net: fix missing error check in p9_check_errors
+    - ovl: fix deadlock in splice write
+    - powerpc/lib: Add helper to check if offset is within conditional branch
+      range
+    - powerpc/bpf: Validate branch ranges
+    - powerpc/bpf: Fix BPF_SUB when imm == 0x80000000
+    - powerpc/security: Add a helper to query stf_barrier type
+    - powerpc/bpf: Emit stf barrier instruction sequences for BPF_NOSPEC
+    - mm, oom: pagefault_out_of_memory: don't force global OOM for dying tasks
+    - mm, oom: do not trigger out_of_memory from the #PF
+    - video: backlight: Drop maximum brightness override for brightness zero
+    - s390/cio: check the subchannel validity for dev_busid
+    - s390/tape: fix timer initialization in tape_std_assign()
+    - s390/cio: make ccw_device_dma_* more robust
+    - powerpc/powernv/prd: Unregister OPAL_MSG_PRD2 notifier during module unload
+    - PCI: Add PCI_EXP_DEVCTL_PAYLOAD_* macros
+    - SUNRPC: Partial revert of commit 6f9f17287e78
+    - ath10k: fix invalid dma_addr_t token assignment
+    - selftests/bpf: Fix also no-alu32 strobemeta selftest
+    - Linux 5.4.160
+    - soc/tegra: pmc: Fix imbalanced clock disabling in error code path
+  * Focal update: v5.4.159 upstream stable release (LP: #1953071)
+    - Revert "x86/kvm: fix vcpu-id indexed array sizes"
+    - usb: ehci: handshake CMD_RUN instead of STS_HALT
+    - usb: gadget: Mark USB_FSL_QE broken on 64-bit
+    - usb: musb: Balance list entry in musb_gadget_queue
+    - usb-storage: Add compatibility quirk flags for iODD 2531/2541
+    - binder: don't detect sender/target during buffer cleanup
+    - printk/console: Allow to disable console output by using console="" or
+      console=null
+    - isofs: Fix out of bound access for corrupted isofs image
+    - comedi: dt9812: fix DMA buffers on stack
+    - comedi: ni_usb6501: fix NULL-deref in command paths
+    - comedi: vmk80xx: fix transfer-buffer overflows
+    - comedi: vmk80xx: fix bulk-buffer overflow
+    - comedi: vmk80xx: fix bulk and interrupt message timeouts
+    - staging: r8712u: fix control-message timeout
+    - staging: rtl8192u: fix control-message timeouts
+    - media: staging/intel-ipu3: css: Fix wrong size comparison imgu_css_fw_init
+    - rsi: fix control-message timeout
+    - Linux 5.4.159
+  * Focal update: v5.4.158 upstream stable release (LP: #1953066)
+    - scsi: core: Put LLD module refcnt after SCSI device is released
+    - vrf: Revert "Reset skb conntrack connection..."
+    - net: ethernet: microchip: lan743x: Fix skb allocation failure
+    - media: firewire: firedtv-avc: fix a buffer overflow in avc_ca_pmt()
+    - Revert "xhci: Set HCD flag to defer primary roothub registration"
+    - Revert "usb: core: hcd: Add support for deferring roothub registration"
+    - sfc: Fix reading non-legacy supported link modes
+    - ARM: 9120/1: Revert "amba: make use of -1 IRQs warn"
+    - Linux 5.4.158
+  * [Ubuntu 20.04] Problem leading IUCV service down (on s390x) (LP: #1913442)
+    - usercopy: mark dma-kmalloc caches as usercopy caches
+
+  [ Ubuntu: 5.4.0-96.109 ]
+
+  * Support builtin revoked certificates (LP: #1932029)
+    - [Config]: add i386 to CONFIG_SYSTEM_REVOCATION_KEYS annotation
+  * CVE-2022-0185
+    - SAUCE: vfs: Out-of-bounds write of heap buffer in fs_context.c
+    - SAUCE: vfs: test that one given mount param is not larger than PAGE_SIZE
+
+  [ Ubuntu: 5.4.0-94.106 ]
+
+  * focal/linux: 5.4.0-94.106 -proposed tracker (LP: #1956628)
+  * [Regression] Focal kernel  5.4.0-92.103 fails to boot when Secure Encrypted
+    Virtualization(SEV) is enabled (LP: #1956575)
+    - x86/ioremap: Map EFI-reserved memory as encrypted for SEV
+
+  [ Ubuntu: 5.4.0-92.103 ]
+
+  * focal/linux: 5.4.0-92.103 -proposed tracker (LP: #1952316)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync update-dkms-versions helper
+    - debian/dkms-versions -- update from kernel-versions (main/2021.11.29)
+  * CVE-2021-4002
+    - tlb: mmu_gather: add tlb_flush_*_range APIs
+    - hugetlbfs: flush TLBs correctly after huge_pmd_unshare
+  * Re-enable DEBUG_INFO_BTF where it was disabled (LP: #1945632)
+    - [Config] Enable CONFIG_DEBUG_INFO_BTF on all arches
+  * Focal linux-azure: Vm crash on Dv5/Ev5 (LP: #1950462)
+    - KVM: VMX: eVMCS: make evmcs_sanitize_exec_ctrls() work again
+    - jump_label: Fix usage in module __init
+  * Support builtin revoked certificates (LP: #1932029)
+    - Revert "UBUNTU: SAUCE: (lockdown) Make get_cert_list() not complain about
+      cert lists that aren't present."
+    - integrity: Move import of MokListRT certs to a separate routine
+    - integrity: Load certs from the EFI MOK config table
+    - certs: Add ability to preload revocation certs
+    - integrity: Load mokx variables into the blacklist keyring
+    - certs: add 'x509_revocation_list' to gitignore
+    - SAUCE: Dump stack when X.509 certificates cannot be loaded
+    - [Packaging] build canonical-revoked-certs.pem from branch/arch certs
+    - [Packaging] Revoke 2012 UEFI signing certificate as built-in
+    - [Config] Configure CONFIG_SYSTEM_REVOCATION_KEYS with revoked keys
+  * Support importing mokx keys into revocation list from the mok table
+    (LP: #1928679)
+    - efi: Support for MOK variable config table
+    - efi: mokvar-table: fix some issues in new code
+    - efi: mokvar: add missing include of asm/early_ioremap.h
+    - efi/mokvar: Reserve the table only if it is in boot services data
+    - SAUCE: integrity: add informational messages when revoking certs
+  * Support importing mokx keys into revocation list from the mok table
+    (LP: #1928679) // CVE-2020-26541 when certificates are revoked via
+    MokListXRT.
+    - SAUCE: integrity: Load mokx certs from the EFI MOK config table
+  * Focal update: v5.4.157 upstream stable release (LP: #1951883)
+    - ARM: 9133/1: mm: proc-macros: ensure *_tlb_fns are 4B aligned
+    - ARM: 9134/1: remove duplicate memcpy() definition
+    - ARM: 9139/1: kprobes: fix arch_init_kprobes() prototype
+    - ARM: 9141/1: only warn about XIP address when not compile testing
+    - ipv6: use siphash in rt6_exception_hash()
+    - ipv4: use siphash instead of Jenkins in fnhe_hashfun()
+    - usbnet: sanity check for maxpacket
+    - usbnet: fix error return code in usbnet_probe()
+    - Revert "pinctrl: bcm: ns: support updated DT binding as syscon subnode"
+    - ata: sata_mv: Fix the error handling of mv_chip_id()
+    - nfc: port100: fix using -ERRNO as command type mask
+    - net/tls: Fix flipped sign in tls_err_abort() calls
+    - mmc: vub300: fix control-message timeouts
+    - mmc: cqhci: clear HALT state after CQE enable
+    - mmc: dw_mmc: exynos: fix the finding clock sample value
+    - mmc: sdhci: Map more voltage level to SDHCI_POWER_330
+    - mmc: sdhci-esdhc-imx: clear the buffer_read_ready to reset standard tuning
+      circuit
+    - cfg80211: scan: fix RCU in cfg80211_add_nontrans_list()
+    - net: lan78xx: fix division by zero in send path
+    - tcp_bpf: Fix one concurrency problem in the tcp_bpf_send_verdict function
+    - IB/qib: Protect from buffer overflow in struct qib_user_sdma_pkt fields
+    - IB/hfi1: Fix abba locking issue with sc_disable()
+    - nvmet-tcp: fix data digest pointer calculation
+    - nvme-tcp: fix data digest pointer calculation
+    - RDMA/mlx5: Set user priority for DCT
+    - arm64: dts: allwinner: h5: NanoPI Neo 2: Fix ethernet node
+    - regmap: Fix possible double-free in regcache_rbtree_exit()
+    - net: batman-adv: fix error handling
+    - net: Prevent infinite while loop in skb_tx_hash()
+    - RDMA/sa_query: Use strscpy_pad instead of memcpy to copy a string
+    - nios2: Make NIOS2_DTB_SOURCE_BOOL depend on !COMPILE_TEST
+    - net: ethernet: microchip: lan743x: Fix driver crash when lan743x_pm_resume
+      fails
+    - net: ethernet: microchip: lan743x: Fix dma allocation failure by using
+      dma_set_mask_and_coherent
+    - net: nxp: lpc_eth.c: avoid hang when bringing interface down
+    - net/tls: Fix flipped sign in async_wait.err assignment
+    - phy: phy_ethtool_ksettings_get: Lock the phy for consistency
+    - phy: phy_start_aneg: Add an unlocked version
+    - sctp: use init_tag from inithdr for ABORT chunk
+    - sctp: fix the processing for INIT_ACK chunk
+    - sctp: fix the processing for COOKIE_ECHO chunk
+    - sctp: add vtag check in sctp_sf_violation
+    - sctp: add vtag check in sctp_sf_do_8_5_1_E_sa
+    - sctp: add vtag check in sctp_sf_ootb
+    - net: use netif_is_bridge_port() to check for IFF_BRIDGE_PORT
+    - cfg80211: correct bridge/4addr mode check
+    - KVM: s390: clear kicked_mask before sleeping again
+    - KVM: s390: preserve deliverable_mask in __airqs_kick_single_vcpu
+    - perf script: Check session->header.env.arch before using it
+    - Linux 5.4.157
+  * keyboard not working on Medion notebook s17 series (LP: #1950536)
+    - ACPI: resources: Add one more Medion model in IRQ override quirk
+  * creat09 from ubuntu_ltp_syscalls and cve-2018-13405 from ubuntu_ltp/cve
+    failed with XFS (LP: #1950239)
+    - xfs: ensure that the inode uid/gid match values match the icdinode ones
+    - xfs: merge the projid fields in struct xfs_icdinode
+    - xfs: remove the icdinode di_uid/di_gid members
+    - xfs: fix up non-directory creation in SGID directories
+  * reuseport_bpf_numa in net from ubuntu_kernel_selftests fails on ppc64le
+    (LP: #1867570)
+    - selftests/net: Fix reuseport_bpf_numa by skipping unavailable nodes
+  * Focal update: v5.4.156 upstream stable release (LP: #1951295)
+    - parisc: math-emu: Fix fall-through warnings
+    - net: switchdev: do not propagate bridge updates across bridges
+    - tee: optee: Fix missing devices unregister during optee_remove
+    - ARM: dts: at91: sama5d2_som1_ek: disable ISC node by default
+    - xtensa: xtfpga: use CONFIG_USE_OF instead of CONFIG_OF
+    - xtensa: xtfpga: Try software restart before simulating CPU reset
+    - NFSD: Keep existing listeners on portlist error
+    - dma-debug: fix sg checks in debug_dma_map_sg()
+    - ASoC: wm8960: Fix clock configuration on slave mode
+    - netfilter: ipvs: make global sysctl readonly in non-init netns
+    - lan78xx: select CRC32
+    - net: dsa: lantiq_gswip: fix register definition
+    - NIOS2: irqflags: rename a redefined register name
+    - net: hns3: reset DWRR of unused tc to zero
+    - net: hns3: add limit ets dwrr bandwidth cannot be 0
+    - net: hns3: disable sriov before unload hclge layer
+    - net: stmmac: Fix E2E delay mechanism
+    - net: enetc: fix ethtool counter name for PM0_TERR
+    - can: rcar_can: fix suspend/resume
+    - can: peak_usb: pcan_usb_fd_decode_status(): fix back to ERROR_ACTIVE state
+      notification
+    - can: peak_pci: peak_pci_remove(): fix UAF
+    - can: j1939: j1939_tp_rxtimer(): fix errant alert in j1939_tp_rxtimer
+    - can: j1939: j1939_netdev_start(): fix UAF for rx_kref of j1939_priv
+    - can: j1939: j1939_xtp_rx_dat_one(): cancel session if receive TP.DT with
+      error length
+    - can: j1939: j1939_xtp_rx_rts_session_new(): abort TP less than 9 bytes
+    - ceph: fix handling of "meta" errors
+    - ocfs2: fix data corruption after conversion from inline format
+    - ocfs2: mount fails with buffer overflow in strlen
+    - elfcore: correct reference to CONFIG_UML
+    - ALSA: usb-audio: Provide quirk for Sennheiser GSP670 Headset
+    - ALSA: hda/realtek: Add quirk for Clevo PC50HS
+    - ASoC: DAPM: Fix missing kctl change notifications
+    - audit: fix possible null-pointer dereference in audit_filter_rules
+    - powerpc64/idle: Fix SP offsets when saving GPRs
+    - KVM: PPC: Book3S HV: Fix stack handling in idle_kvm_start_guest()
+    - KVM: PPC: Book3S HV: Make idle_kvm_start_guest() return 0 if it went to
+      guest
+    - powerpc/idle: Don't corrupt back chain when going idle
+    - mm, slub: fix mismatch between reconstructed freelist depth and cnt
+    - mm, slub: fix potential memoryleak in kmem_cache_open()
+    - nfc: nci: fix the UAF of rf_conn_info object
+    - isdn: cpai: check ctr->cnr to avoid array index out of bound
+    - netfilter: Kconfig: use 'default y' instead of 'm' for bool config option
+    - selftests: netfilter: remove stray bash debug line
+    - gcc-plugins/structleak: add makefile var for disabling structleak
+    - btrfs: deal with errors when checking if a dir entry exists during log
+      replay
+    - net: stmmac: add support for dwmac 3.40a
+    - ARM: dts: spear3xx: Fix gmac node
+    - isdn: mISDN: Fix sleeping function called from invalid context
+    - platform/x86: intel_scu_ipc: Update timeout value in comment
+    - ALSA: hda: avoid write to STATESTS if controller is in reset
+    - Input: snvs_pwrkey - add clk handling
+    - scsi: core: Fix shost->cmd_per_lun calculation in scsi_add_host_with_dma()
+    - tracing: Have all levels of checks prevent recursion
+    - ARM: 9122/1: select HAVE_FUTEX_CMPXCHG
+    - pinctrl: stm32: use valid pin identifier in stm32_pinctrl_resume()
+    - Linux 5.4.156
+  * ubuntu_ltp / finit_module02 fails on v4.15 and other kernels
+    (LP: #1950644) // Focal update: v5.4.156 upstream stable release
+    (LP: #1951295)
+    - vfs: check fd has read access in kernel_read_file_from_fd()
+  * Focal update: v5.4.155 upstream stable release (LP: #1951291)
+    - ovl: simplify file splice
+    - ALSA: usb-audio: Add quirk for VF0770
+    - ALSA: seq: Fix a potential UAF by wrong private_free call order
+    - ALSA: hda/realtek: Complete partial device name to avoid ambiguity
+    - ALSA: hda/realtek: Add quirk for Clevo X170KM-G
+    - ALSA: hda/realtek - ALC236 headset MIC recording issue
+    - ALSA: hda/realtek: Fix the mic type detection issue for ASUS G551JW
+    - nds32/ftrace: Fix Error: invalid operands (*UND* and *UND* sections) for `^'
+    - s390: fix strrchr() implementation
+    - csky: don't let sigreturn play with priveleged bits of status register
+    - csky: Fixup regs.sr broken in ptrace
+    - btrfs: unlock newly allocated extent buffer after error
+    - btrfs: deal with errors when replaying dir entry during log replay
+    - btrfs: deal with errors when adding inode reference during log replay
+    - btrfs: check for error when looking up inode during dir entry replay
+    - watchdog: orion: use 0 for unset heartbeat
+    - x86/resctrl: Free the ctrlval arrays when domain_setup_mon_state() fails
+    - mei: me: add Ice Lake-N device id.
+    - xhci: guard accesses to ep_state in xhci_endpoint_reset()
+    - xhci: Fix command ring pointer corruption while aborting a command
+    - xhci: Enable trust tx length quirk for Fresco FL11 USB controller
+    - cb710: avoid NULL pointer subtraction
+    - efi/cper: use stack buffer for error record decoding
+    - efi: Change down_interruptible() in virt_efi_reset_system() to
+      down_trylock()
+    - usb: musb: dsps: Fix the probe error path
+    - Input: xpad - add support for another USB ID of Nacon GC-100
+    - USB: serial: qcserial: add EM9191 QDL support
+    - USB: serial: option: add Quectel EC200S-CN module support
+    - USB: serial: option: add Telit LE910Cx composition 0x1204
+    - USB: serial: option: add prod. id for Quectel EG91
+    - EDAC/armada-xp: Fix output of uncorrectable error counter
+    - nvmem: Fix shift-out-of-bound (UBSAN) with byte size cells
+    - x86/Kconfig: Do not enable AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT automatically
+    - powerpc/xive: Discard disabled interrupts in get_irqchip_state()
+    - iio: adc: aspeed: set driver data when adc probe.
+    - iio: adc128s052: Fix the error handling path of 'adc128_probe()'
+    - iio: mtk-auxadc: fix case IIO_CHAN_INFO_PROCESSED
+    - iio: light: opt3001: Fixed timeout error when 0 lux
+    - iio: ssp_sensors: add more range checking in ssp_parse_dataframe()
+    - iio: ssp_sensors: fix error code in ssp_print_mcu_debug()
+    - iio: dac: ti-dac5571: fix an error code in probe()
+    - sctp: account stream padding length for reconf chunk
+    - gpio: pca953x: Improve bias setting
+    - net: arc: select CRC32
+    - net: korina: select CRC32
+    - net/mlx5e: Mutually exclude RX-FCS and RX-port-timestamp
+    - net: stmmac: fix get_hw_feature() on old hardware
+    - net: encx24j600: check error in devm_regmap_init_encx24j600
+    - ethernet: s2io: fix setting mac address during resume
+    - nfc: fix error handling of nfc_proto_register()
+    - NFC: digital: fix possible memory leak in digital_tg_listen_mdaa()
+    - NFC: digital: fix possible memory leak in digital_in_send_sdd_req()
+    - pata_legacy: fix a couple uninitialized variable bugs
+    - ata: ahci_platform: fix null-ptr-deref in ahci_platform_enable_regulators()
+    - mlxsw: thermal: Fix out-of-bounds memory accesses
+    - platform/mellanox: mlxreg-io: Fix argument base in kstrtou32() call
+    - drm/panel: olimex-lcd-olinuxino: select CRC32
+    - drm/msm: Fix null pointer dereference on pointer edp
+    - drm/msm/dsi: Fix an error code in msm_dsi_modeset_init()
+    - drm/msm/dsi: fix off by one in dsi_bus_clk_enable error handling
+    - acpi/arm64: fix next_platform_timer() section mismatch error
+    - mqprio: Correct stats in mqprio_dump_class_stats().
+    - qed: Fix missing error code in qed_slowpath_start()
+    - r8152: select CRC32 and CRYPTO/CRYPTO_HASH/CRYPTO_SHA256
+    - ionic: don't remove netdev->dev_addr when syncing uc list
+    - Linux 5.4.155
+  * [UBUNTU 20.04] kernel:  unable to read partitions on virtio-block dasd (kvm)
+    (LP: #1950144) // Focal update: v5.4.155 upstream stable release
+    (LP: #1951291)
+    - virtio: write back F_VERSION_1 before validate
+  * Focal update: v5.4.154 upstream stable release (LP: #1951288)
+    - net: phy: bcm7xxx: Fixed indirect MMD operations
+    - ext4: correct the error path of ext4_write_inline_data_end()
+    - HID: apple: Fix logical maximum and usage maximum of Magic Keyboard JIS
+    - netfilter: ip6_tables: zero-initialize fragment offset
+    - HID: wacom: Add new Intuos BT (CTL-4100WL/CTL-6100WL) device IDs
+    - netfilter: nf_nat_masquerade: make async masq_inet6_event handling generic
+    - netfilter: nf_nat_masquerade: defer conntrack walk to work queue
+    - mac80211: Drop frames from invalid MAC address in ad-hoc mode
+    - m68k: Handle arrivals of multiple signals correctly
+    - net: prevent user from passing illegal stab size
+    - mac80211: check return value of rhashtable_init
+    - net: sun: SUNVNET_COMMON should depend on INET
+    - drm/amdgpu: fix gart.bo pin_count leak
+    - scsi: ses: Fix unsigned comparison with less than zero
+    - scsi: virtio_scsi: Fix spelling mistake "Unsupport" -> "Unsupported"
+    - sched: Always inline is_percpu_thread()
+    - Linux 5.4.154
+  * Focal update: v5.4.153 upstream stable release (LP: #1950014)
+    - Partially revert "usb: Kconfig: using select for USB_COMMON dependency"
+    - USB: cdc-acm: fix racy tty buffer accesses
+    - USB: cdc-acm: fix break reporting
+    - usb: typec: tcpm: handle SRC_STARTUP state if cc changes
+    - xen/privcmd: fix error handling in mmap-resource processing
+    - mmc: meson-gx: do not use memcpy_to/fromio for dram-access-quirk
+    - ovl: fix missing negative dentry check in ovl_rename()
+    - nfsd: fix error handling of register_pernet_subsys() in init_nfsd()
+    - nfsd4: Handle the NFSv4 READDIR 'dircount' hint being zero
+    - xen/balloon: fix cancelled balloon action
+    - ARM: dts: omap3430-sdp: Fix NAND device node
+    - ARM: dts: qcom: apq8064: use compatible which contains chipid
+    - MIPS: BPF: Restore MIPS32 cBPF JIT
+    - bpf, mips: Validate conditional branch offsets
+    - soc: qcom: socinfo: Fixed argument passed to platform_set_data()
+    - ARM: dts: qcom: apq8064: Use 27MHz PXO clock as DSI PLL reference
+    - soc: qcom: mdt_loader: Drop PT_LOAD check on hash segment
+    - ARM: dts: imx: Add missing pinctrl-names for panel on M53Menlo
+    - ARM: dts: imx: Fix USB host power regulator polarity on M53Menlo
+    - arm64: dts: qcom: pm8150: use qcom,pm8998-pon binding
+    - xtensa: move XCHAL_KIO_* definitions to kmem_layout.h
+    - xtensa: use CONFIG_USE_OF instead of CONFIG_OF
+    - xtensa: call irqchip_init only when CONFIG_USE_OF is selected
+    - bpf, arm: Fix register clobbering in div/mod implementation
+    - bpf: Fix integer overflow in prealloc_elems_and_freelist()
+    - phy: mdio: fix memory leak
+    - net_sched: fix NULL deref in fifo_set_limit()
+    - powerpc/fsl/dts: Fix phy-connection-type for fm1mac3
+    - ptp_pch: Load module automatically if ID matches
+    - arm64: dts: freescale: Fix SP805 clock-names
+    - arm64: dts: ls1028a: add missing CAN nodes
+    - ARM: imx6: disable the GIC CPU interface before calling stby-poweroff
+      sequence
+    - net: bridge: use nla_total_size_64bit() in br_get_linkxstats_size()
+    - net/sched: sch_taprio: properly cancel timer from taprio_destroy()
+    - net: sfp: Fix typo in state machine debug string
+    - netlink: annotate data races around nlk->bound
+    - bus: ti-sysc: Use CLKDM_NOAUTO for dra7 dcan1 for errata i893
+    - video: fbdev: gbefb: Only instantiate device when built for IP32
+    - drm/nouveau/debugfs: fix file release memory leak
+    - gve: Correct available tx qpl check
+    - rtnetlink: fix if_nlmsg_stats_size() under estimation
+    - gve: fix gve_get_stats()
+    - i40e: fix endless loop under rtnl
+    - i40e: Fix freeing of uninitialized misc IRQ vector
+    - net: prefer socket bound to interface when not in VRF
+    - i2c: acpi: fix resource leak in reconfiguration device addition
+    - bpf, s390: Fix potential memory leak about jit_data
+    - RISC-V: Include clone3() on rv32
+    - x86/platform/olpc: Correct ifdef symbol to intended CONFIG_OLPC_XO15_SCI
+    - x86/hpet: Use another crystalball to evaluate HPET usability
+    - x86/Kconfig: Correct reference to MWINCHIP3D
+    - Linux 5.4.153
+  * Focal update: v5.4.152 upstream stable release (LP: #1950009)
+    - net: mdio: introduce a shutdown method to mdio device drivers
+    - xen-netback: correct success/error reporting for the SKB-with-fraglist case
+    - sparc64: fix pci_iounmap() when CONFIG_PCI is not set
+    - ext2: fix sleeping in atomic bugs on error
+    - scsi: sd: Free scsi_disk device via put_device()
+    - usb: testusb: Fix for showing the connection speed
+    - usb: dwc2: check return value after calling platform_get_resource()
+    - selftests: be sure to make khdr before other targets
+    - selftests:kvm: fix get_warnings_count() ignoring fscanf() return warn
+    - scsi: ses: Retry failed Send/Receive Diagnostic commands
+    - tools/vm/page-types: remove dependency on opt_file for idle page tracking
+    - KVM: do not shrink halt_poll_ns below grow_start
+    - kvm: x86: Add AMD PMU MSRs to msrs_to_save_all[]
+    - perf/x86: Reset destroy callback on event init failure
+    - silence nfscache allocation warnings with kvzalloc
+    - libata: Add ATA_HORKAGE_NO_NCQ_ON_ATI for Samsung 860 and 870 SSD.
+    - Linux 5.4.152
+  * linux-aws: Fix backport of RDMA/efa: Expose maximum  TX doorbell batch
+    (LP: #1949882)
+    - SAUCE: aws: Fix backport of RDMA/efa: Expose maximum TX doorbell batch
+
+  [ Ubuntu: 5.4.0-91.102 ]
+
+  * focal/linux: 5.4.0-91.102 -proposed tracker (LP: #1949840)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update Ubuntu.md
+    - debian/dkms-versions -- update from kernel-versions (main/2021.11.08)
+  * KVM emulation failure when booting into  VM crash kernel with multiple CPUs
+    (LP: #1948862)
+    - KVM: x86: Properly reset MMU context at vCPU RESET/INIT
+  * aufs: kernel bug with apparmor and fuseblk (LP: #1948470)
+    - SAUCE: aufs: bugfix, stop omitting path->mnt
+  * ebpf:  bpf_redirect fails with ip6 gre interfaces (LP: #1947164)
+    - net: handle ARPHRD_IP6GRE in dev_is_mac_header_xmit()
+  * require CAP_NET_ADMIN to attach N_HCI ldisc (LP: #1949516)
+    - Bluetooth: hci_ldisc: require CAP_NET_ADMIN to attach N_HCI ldisc
+  * ACL updates on OCFS2 are not revalidated (LP: #1947161)
+    - ocfs2: fix remounting needed after setfacl command
+  * ppc64 BPF JIT mod by 1 will not return 0 (LP: #1948351)
+    - powerpc/bpf: Fix BPF_MOD when imm == 1
+  * Drop "UBUNTU: SAUCE: cachefiles: Page leaking in
+    cachefiles_read_backing_file while vmscan is active" (LP: #1947709)
+    - Revert "UBUNTU: SAUCE: cachefiles: Page leaking in
+      cachefiles_read_backing_file while vmscan is active"
+  * Reassign I/O Path of ConnectX-5 Port 1 before Port 2 causes NULL dereference
+    (LP: #1943464)
+    - s390/pci: fix leak of PCI device structure
+    - s390/pci: fix use after free of zpci_dev
+    - s390/pci: fix zpci_zdev_put() on reserve
+  * [SRU][F] USB: serial: pl2303: add support for PL2303HXN (LP: #1948377)
+    - USB: serial: pl2303: add support for PL2303HXN
+    - USB: serial: pl2303: fix line-speed handling on newer chips
+  * Focal update: v5.4.151 upstream stable release (LP: #1947888)
+    - tty: Fix out-of-bound vmalloc access in imageblit
+    - cpufreq: schedutil: Use kobject release() method to free sugov_tunables
+    - cpufreq: schedutil: Destroy mutex before kobject_put() frees the memory
+    - usb: cdns3: fix race condition before setting doorbell
+    - fs-verity: fix signed integer overflow with i_size near S64_MAX
+    - hwmon: (w83793) Fix NULL pointer dereference by removing unnecessary
+      structure field
+    - hwmon: (w83792d) Fix NULL pointer dereference by removing unnecessary
+      structure field
+    - hwmon: (w83791d) Fix NULL pointer dereference by removing unnecessary
+      structure field
+    - scsi: ufs: Fix illegal offset in UPIU event trace
+    - mac80211: fix use-after-free in CCMP/GCMP RX
+    - x86/kvmclock: Move this_cpu_pvti into kvmclock.h
+    - drm/amd/display: Pass PCI deviceid into DC
+    - ipvs: check that ip_vs_conn_tab_bits is between 8 and 20
+    - hwmon: (mlxreg-fan) Return non-zero value when fan current state is enforced
+      from sysfs
+    - mac80211: Fix ieee80211_amsdu_aggregate frag_tail bug
+    - mac80211: limit injected vht mcs/nss in ieee80211_parse_tx_radiotap
+    - mac80211: mesh: fix potentially unaligned access
+    - mac80211-hwsim: fix late beacon hrtimer handling
+    - sctp: break out if skb_header_pointer returns NULL in sctp_rcv_ootb
+    - hwmon: (tmp421) report /PVLD condition as fault
+    - hwmon: (tmp421) fix rounding for negative values
+    - net: ipv4: Fix rtnexthop len when RTA_FLOW is present
+    - e100: fix length calculation in e100_get_regs_len
+    - e100: fix buffer overrun in e100_get_regs
+    - selftests, bpf: test_lwt_ip_encap: Really disable rp_filter
+    - scsi: csiostor: Add module softdep on cxgb4
+    - net: hns3: do not allow call hns3_nic_net_open repeatedly
+    - net: sched: flower: protect fl_walk() with rcu
+    - af_unix: fix races in sk_peer_pid and sk_peer_cred accesses
+    - perf/x86/intel: Update event constraints for ICX
+    - elf: don't use MAP_FIXED_NOREPLACE for elf interpreter mappings
+    - debugfs: debugfs_create_file_size(): use IS_ERR to check for error
+    - ipack: ipoctal: fix stack information leak
+    - ipack: ipoctal: fix tty registration race
+    - ipack: ipoctal: fix tty-registration error handling
+    - ipack: ipoctal: fix missing allocation-failure check
+    - ipack: ipoctal: fix module reference leak
+    - ext4: fix loff_t overflow in ext4_max_bitmap_size()
+    - ext4: fix reserved space counter leakage
+    - ext4: fix potential infinite loop in ext4_dx_readdir()
+    - HID: u2fzero: ignore incomplete packets without data
+    - net: udp: annotate data race around udp_sk(sk)->corkflag
+    - net: stmmac: don't attach interface until resume finishes
+    - PCI: Fix pci_host_bridge struct device release/free handling
+    - libnvdimm/pmem: Fix crash triggered when I/O in-flight during unbind
+    - hso: fix bailout in error case of probe
+    - usb: hso: fix error handling code of hso_create_net_device
+    - usb: hso: remove the bailout parameter
+    - crypto: ccp - fix resource leaks in ccp_run_aes_gcm_cmd()
+    - HID: betop: fix slab-out-of-bounds Write in betop_probe
+    - netfilter: ipset: Fix oversized kvmalloc() calls
+    - HID: usbhid: free raw_report buffers in usbhid_stop
+    - Linux 5.4.151
+  * Focal update: v5.4.150 upstream stable release (LP: #1947886)
+    - usb: gadget: r8a66597: fix a loop in set_feature()
+    - usb: dwc2: gadget: Fix ISOC flow for BDMA and Slave
+    - usb: dwc2: gadget: Fix ISOC transfer complete handling for DDMA
+    - usb: musb: tusb6010: uninitialized data in tusb_fifo_write_unaligned()
+    - cifs: fix incorrect check for null pointer in header_assemble
+    - xen/x86: fix PV trap handling on secondary processors
+    - usb-storage: Add quirk for ScanLogic SL11R-IDE older than 2.6c
+    - USB: serial: cp210x: add ID for GW Instek GDM-834x Digital Multimeter
+    - USB: cdc-acm: fix minor-number release
+    - binder: make sure fd closes complete
+    - staging: greybus: uart: fix tty use after free
+    - Re-enable UAS for LaCie Rugged USB3-FW with fk quirk
+    - USB: serial: mos7840: remove duplicated 0xac24 device ID
+    - USB: serial: option: add Telit LN920 compositions
+    - USB: serial: option: remove duplicate USB device ID
+    - USB: serial: option: add device id for Foxconn T99W265
+    - mcb: fix error handling in mcb_alloc_bus()
+    - erofs: fix up erofs_lookup tracepoint
+    - btrfs: prevent __btrfs_dump_space_info() to underflow its free space
+    - serial: mvebu-uart: fix driver's tx_empty callback
+    - net: hso: fix muxed tty registration
+    - afs: Fix incorrect triggering of sillyrename on 3rd-party invalidation
+    - platform/x86/intel: punit_ipc: Drop wrong use of ACPI_PTR()
+    - enetc: Fix illegal access when reading affinity_hint
+    - bnxt_en: Fix TX timeout when TX ring size is set to the smallest
+    - net/smc: add missing error check in smc_clc_prfx_set()
+    - gpio: uniphier: Fix void functions to remove return value
+    - qed: rdma - don't wait for resources under hw error recovery flow
+    - net/mlx4_en: Don't allow aRFS for encapsulated packets
+    - scsi: iscsi: Adjust iface sysfs attr detection
+    - tty: synclink_gt, drop unneeded forward declarations
+    - tty: synclink_gt: rename a conflicting function name
+    - fpga: machxo2-spi: Return an error on failure
+    - fpga: machxo2-spi: Fix missing error code in machxo2_write_complete()
+    - thermal/core: Potential buffer overflow in thermal_build_list_of_policies()
+    - cifs: fix a sign extension bug
+    - scsi: qla2xxx: Restore initiator in dual mode
+    - scsi: lpfc: Use correct scnprintf() limit
+    - irqchip/goldfish-pic: Select GENERIC_IRQ_CHIP to fix build
+    - irqchip/gic-v3-its: Fix potential VPE leak on error
+    - md: fix a lock order reversal in md_alloc
+    - blktrace: Fix uaf in blk_trace access after removing by sysfs
+    - net: macb: fix use after free on rmmod
+    - net: stmmac: allow CSR clock of 300MHz
+    - m68k: Double cast io functions to unsigned long
+    - ipv6: delay fib6_sernum increase in fib6_add
+    - bpf: Add oversize check before call kvcalloc()
+    - xen/balloon: use a kernel thread instead a workqueue
+    - nvme-multipath: fix ANA state updates when a namespace is not present
+    - sparc32: page align size in arch_dma_alloc
+    - blk-cgroup: fix UAF by grabbing blkcg lock before destroying blkg pd
+    - compiler.h: Introduce absolute_pointer macro
+    - net: i825xx: Use absolute_pointer for memcpy from fixed memory location
+    - sparc: avoid stringop-overread errors
+    - qnx4: avoid stringop-overread errors
+    - parisc: Use absolute_pointer() to define PAGE0
+    - arm64: Mark __stack_chk_guard as __ro_after_init
+    - alpha: Declare virt_to_phys and virt_to_bus parameter as pointer to volatile
+    - net: 6pack: Fix tx timeout and slot time
+    - spi: Fix tegra20 build with CONFIG_PM=n
+    - EDAC/synopsys: Fix wrong value type assignment for edac_mode
+    - thermal/drivers/int340x: Do not set a wrong tcc offset on resume
+    - arm64: dts: marvell: armada-37xx: Extend PCIe MEM space
+    - xen/balloon: fix balloon kthread freezing
+    - qnx4: work around gcc false positive warning bug
+    - Linux 5.4.150
+  * ACL updates on OCFS2 are not revalidated (LP: #1947161) // Focal update:
+    v5.4.150 upstream stable release (LP: #1947886)
+    - ocfs2: drop acl cache for directories too
+  * Focal update: v5.4.149 upstream stable release (LP: #1947885)
+    - PCI: pci-bridge-emul: Fix big-endian support
+    - PCI: aardvark: Indicate error in 'val' when config read fails
+    - PCI: pci-bridge-emul: Add PCIe Root Capabilities Register
+    - PCI: aardvark: Fix reporting CRS value
+    - PCI/ACPI: Add Ampere Altra SOC MCFG quirk
+    - KVM: remember position in kvm->vcpus array
+    - console: consume APC, DM, DCS
+    - s390/pci_mmio: fully validate the VMA before calling follow_pte()
+    - ARM: Qualify enabling of swiotlb_init()
+    - apparmor: remove duplicate macro list_entry_is_head()
+    - ARM: 9077/1: PLT: Move struct plt_entries definition to header
+    - ARM: 9078/1: Add warn suppress parameter to arm_gen_branch_link()
+    - ARM: 9079/1: ftrace: Add MODULE_PLTS support
+    - ARM: 9098/1: ftrace: MODULE_PLT: Fix build problem without DYNAMIC_FTRACE
+    - sctp: validate chunk size in __rcv_asconf_lookup
+    - sctp: add param size validation for SCTP_PARAM_SET_PRIMARY
+    - staging: rtl8192u: Fix bitwise vs logical operator in
+      TranslateRxSignalStuff819xUsb()
+    - um: virtio_uml: fix memory leak on init failures
+    - dmaengine: acpi: Avoid comparison GSI with Linux vIRQ
+    - thermal/drivers/exynos: Fix an error code in exynos_tmu_probe()
+    - 9p/trans_virtio: Remove sysfs file on probe failure
+    - prctl: allow to setup brk for et_dyn executables
+    - nilfs2: use refcount_dec_and_lock() to fix potential UAF
+    - profiling: fix shift-out-of-bounds bugs
+    - pwm: lpc32xx: Don't modify HW state in .probe() after the PWM chip was
+      registered
+    - phy: avoid unnecessary link-up delay in polling mode
+    - net: stmmac: reset Tx desc base address before restarting Tx
+    - Kconfig.debug: drop selecting non-existing HARDLOCKUP_DETECTOR_ARCH
+    - thermal/core: Fix thermal_cooling_device_register() prototype
+    - drivers: base: cacheinfo: Get rid of DEFINE_SMP_CALL_CACHE_FUNCTION()
+    - parisc: Move pci_dev_is_behind_card_dino to where it is used
+    - dmaengine: sprd: Add missing MODULE_DEVICE_TABLE
+    - dmaengine: ioat: depends on !UML
+    - dmaengine: xilinx_dma: Set DMA mask for coherent APIs
+    - ceph: request Fw caps before updating the mtime in ceph_write_iter
+    - ceph: lockdep annotations for try_nonblocking_invalidate
+    - btrfs: fix lockdep warning while mounting sprout fs
+    - nilfs2: fix memory leak in nilfs_sysfs_create_device_group
+    - nilfs2: fix NULL pointer in nilfs_##name##_attr_release
+    - nilfs2: fix memory leak in nilfs_sysfs_create_##name##_group
+    - nilfs2: fix memory leak in nilfs_sysfs_delete_##name##_group
+    - nilfs2: fix memory leak in nilfs_sysfs_create_snapshot_group
+    - nilfs2: fix memory leak in nilfs_sysfs_delete_snapshot_group
+    - pwm: img: Don't modify HW state in .remove() callback
+    - pwm: rockchip: Don't modify HW state in .remove() callback
+    - pwm: stm32-lp: Don't modify HW state in .remove() callback
+    - blk-throttle: fix UAF by deleteing timer in blk_throtl_exit()
+    - rtc: rx8010: select REGMAP_I2C
+    - drm/nouveau/nvkm: Replace -ENOSYS with -ENODEV
+    - Linux 5.4.149
+
+  [ Ubuntu: 5.4.0-90.101 ]
+
+  * focal/linux: 5.4.0-90.101 -proposed tracker (LP: #1947260)
+  * Packaging resync (LP: #1786013)
+    - debian/dkms-versions -- update from kernel-versions (main/2021.10.18)
+  * Add final-checks to check certificates (LP: #1947174)
+    - [Packaging] Add system trusted and revocation keys final check
+  * No sound on Lenovo laptop models Legion 15IMHG05, Yoga 7 14ITL5, and 13s
+    Gen2 (LP: #1939052)
+    - ALSA: hda/realtek: Quirks to enable speaker output for Lenovo Legion 7i
+      15IMHG05, Yoga 7i 14ITL5/15ITL5, and 13s Gen2 laptops.
+    - ALSA: hda/realtek: Fix for quirk to enable speaker output on the Lenovo 13s
+      Gen2
+  * CVE-2020-36385
+    - RDMA/cma: Add missing locking to rdma_accept()
+    - RDMA/ucma: Fix the locking of ctx->file
+    - RDMA/ucma: Rework ucma_migrate_id() to avoid races with destroy
+  * Focal update: v5.4.148 upstream stable release (LP: #1946802)
+    - rtc: tps65910: Correct driver module alias
+    - btrfs: wake up async_delalloc_pages waiters after submit
+    - btrfs: reset replace target device to allocation state on close
+    - blk-zoned: allow zone management send operations without CAP_SYS_ADMIN
+    - blk-zoned: allow BLKREPORTZONE without CAP_SYS_ADMIN
+    - PCI/MSI: Skip masking MSI-X on Xen PV
+    - powerpc/perf/hv-gpci: Fix counter value parsing
+    - xen: fix setting of max_pfn in shared_info
+    - include/linux/list.h: add a macro to test if entry is pointing to the head
+    - 9p/xen: Fix end of loop tests for list_for_each_entry
+    - tools/thermal/tmon: Add cross compiling support
+    - pinctrl: stmfx: Fix hazardous u8[] to unsigned long cast
+    - pinctrl: ingenic: Fix incorrect pull up/down info
+    - soc: qcom: aoss: Fix the out of bound usage of cooling_devs
+    - soc: aspeed: lpc-ctrl: Fix boundary check for mmap
+    - soc: aspeed: p2a-ctrl: Fix boundary check for mmap
+    - arm64: head: avoid over-mapping in map_memory
+    - crypto: public_key: fix overflow during implicit conversion
+    - block: bfq: fix bfq_set_next_ioprio_data()
+    - power: supply: max17042: handle fails of reading status register
+    - dm crypt: Avoid percpu_counter spinlock contention in crypt_page_alloc()
+    - VMCI: fix NULL pointer dereference when unmapping queue pair
+    - media: uvc: don't do DMA on stack
+    - media: rc-loopback: return number of emitters rather than error
+    - Revert "dmaengine: imx-sdma: refine to load context only once"
+    - dmaengine: imx-sdma: remove duplicated sdma_load_context
+    - libata: add ATA_HORKAGE_NO_NCQ_TRIM for Samsung 860 and 870 SSDs
+    - ARM: 9105/1: atags_to_fdt: don't warn about stack size
+    - PCI/portdrv: Enable Bandwidth Notification only if port supports it
+    - PCI: Restrict ASMedia ASM1062 SATA Max Payload Size Supported
+    - PCI: Return ~0 data on pciconfig_read() CAP_SYS_ADMIN failure
+    - PCI: xilinx-nwl: Enable the clock through CCF
+    - PCI: aardvark: Fix checking for PIO status
+    - PCI: aardvark: Increase polling delay to 1.5s while waiting for PIO response
+    - PCI: aardvark: Fix masking and unmasking legacy INTx interrupts
+    - HID: input: do not report stylus battery state as "full"
+    - f2fs: quota: fix potential deadlock
+    - scsi: bsg: Remove support for SCSI_IOCTL_SEND_COMMAND
+    - IB/hfi1: Adjust pkey entry in index 0
+    - RDMA/iwcm: Release resources if iw_cm module initialization fails
+    - docs: Fix infiniband uverbs minor number
+    - pinctrl: samsung: Fix pinctrl bank pin count
+    - vfio: Use config not menuconfig for VFIO_NOIOMMU
+    - powerpc/stacktrace: Include linux/delay.h
+    - RDMA/efa: Remove double QP type assignment
+    - f2fs: show f2fs instance in printk_ratelimited
+    - f2fs: reduce the scope of setting fsck tag when de->name_len is zero
+    - openrisc: don't printk() unconditionally
+    - dma-debug: fix debugfs initialization order
+    - SUNRPC: Fix potential memory corruption
+    - scsi: fdomain: Fix error return code in fdomain_probe()
+    - pinctrl: single: Fix error return code in pcs_parse_bits_in_pinctrl_entry()
+    - scsi: smartpqi: Fix an error code in pqi_get_raid_map()
+    - scsi: qedi: Fix error codes in qedi_alloc_global_queues()
+    - scsi: qedf: Fix error codes in qedf_alloc_global_queues()
+    - powerpc/config: Renable MTD_PHYSMAP_OF
+    - scsi: target: avoid per-loop XCOPY buffer allocations
+    - HID: i2c-hid: Fix Elan touchpad regression
+    - KVM: PPC: Book3S HV Nested: Reflect guest PMU in-use to L0 when guest SPRs
+      are live
+    - platform/x86: dell-smbios-wmi: Add missing kfree in error-exit from
+      run_smbios_call
+    - fscache: Fix cookie key hashing
+    - clk: at91: sam9x60: Don't use audio PLL
+    - clk: at91: clk-generated: pass the id of changeable parent at registration
+    - clk: at91: clk-generated: Limit the requested rate to our range
+    - KVM: PPC: Fix clearing never mapped TCEs in realmode
+    - f2fs: fix to account missing .skipped_gc_rwsem
+    - f2fs: fix unexpected ENOENT comes from f2fs_map_blocks()
+    - f2fs: fix to unmap pages from userspace process in punch_hole()
+    - MIPS: Malta: fix alignment of the devicetree buffer
+    - kbuild: Fix 'no symbols' warning when CONFIG_TRIM_UNUSD_KSYMS=y
+    - userfaultfd: prevent concurrent API initialization
+    - drm/amdgpu: Fix amdgpu_ras_eeprom_init()
+    - ASoC: atmel: ATMEL drivers don't need HAS_DMA
+    - media: dib8000: rewrite the init prbs logic
+    - crypto: mxs-dcp - Use sg_mapping_iter to copy data
+    - PCI: Use pci_update_current_state() in pci_enable_device_flags()
+    - tipc: keep the skb in rcv queue until the whole data is read
+    - iio: dac: ad5624r: Fix incorrect handling of an optional regulator.
+    - iavf: do not override the adapter state in the watchdog task
+    - iavf: fix locking of critical sections
+    - ARM: dts: qcom: apq8064: correct clock names
+    - video: fbdev: kyro: fix a DoS bug by restricting user input
+    - netlink: Deal with ESRCH error in nlmsg_notify()
+    - Smack: Fix wrong semantics in smk_access_entry()
+    - drm: avoid blocking in drm_clients_info's rcu section
+    - igc: Check if num of q_vectors is smaller than max before array access
+    - usb: host: fotg210: fix the endpoint's transactional opportunities
+      calculation
+    - usb: host: fotg210: fix the actual_length of an iso packet
+    - usb: gadget: u_ether: fix a potential null pointer dereference
+    - USB: EHCI: ehci-mv: improve error handling in mv_ehci_enable()
+    - usb: gadget: composite: Allow bMaxPower=0 if self-powered
+    - staging: board: Fix uninitialized spinlock when attaching genpd
+    - tty: serial: jsm: hold port lock when reporting modem line changes
+    - drm/amd/display: Fix timer_per_pixel unit error
+    - drm/amd/amdgpu: Update debugfs link_settings output link_rate field in hex
+    - bpf/tests: Fix copy-and-paste error in double word test
+    - bpf/tests: Do not PASS tests without actually testing the result
+    - video: fbdev: asiliantfb: Error out if 'pixclock' equals zero
+    - video: fbdev: kyro: Error out if 'pixclock' equals zero
+    - video: fbdev: riva: Error out if 'pixclock' equals zero
+    - ipv4: ip_output.c: Fix out-of-bounds warning in ip_copy_addrs()
+    - flow_dissector: Fix out-of-bounds warnings
+    - s390/jump_label: print real address in a case of a jump label bug
+    - s390: make PCI mio support a machine flag
+    - serial: 8250: Define RX trigger levels for OxSemi 950 devices
+    - xtensa: ISS: don't panic in rs_init
+    - hvsi: don't panic on tty_register_driver failure
+    - serial: 8250_pci: make setup_port() parameters explicitly unsigned
+    - staging: ks7010: Fix the initialization of the 'sleep_status' structure
+    - samples: bpf: Fix tracex7 error raised on the missing argument
+    - ata: sata_dwc_460ex: No need to call phy_exit() befre phy_init()
+    - Bluetooth: skip invalid hci_sync_conn_complete_evt
+    - workqueue: Fix possible memory leaks in wq_numa_init()
+    - bonding: 3ad: fix the concurrency between __bond_release_one() and
+      bond_3ad_state_machine_handler()
+    - arm64: tegra: Fix Tegra194 PCIe EP compatible string
+    - ASoC: Intel: bytcr_rt5640: Move "Platform Clock" routes to the maps for the
+      matching in-/output
+    - media: imx258: Rectify mismatch of VTS value
+    - media: imx258: Limit the max analogue gain to 480
+    - media: v4l2-dv-timings.c: fix wrong condition in two for-loops
+    - media: TDA1997x: fix tda1997x_query_dv_timings() return value
+    - media: tegra-cec: Handle errors of clk_prepare_enable()
+    - ARM: dts: imx53-ppd: Fix ACHC entry
+    - arm64: dts: qcom: sdm660: use reg value for memory node
+    - net: ethernet: stmmac: Do not use unreachable() in ipq806x_gmac_probe()
+    - drm/msm: mdp4: drop vblank get/put from prepare/complete_commit
+    - selftests/bpf: Fix xdp_tx.c prog section name
+    - Bluetooth: schedule SCO timeouts with delayed_work
+    - Bluetooth: avoid circular locks in sco_sock_connect
+    - net/mlx5: Fix variable type to match 64bit
+    - gpu: drm: amd: amdgpu: amdgpu_i2c: fix possible uninitialized-variable
+      access in amdgpu_i2c_router_select_ddc_port()
+    - drm/display: fix possible null-pointer dereference in dcn10_set_clock()
+    - mac80211: Fix monitor MTU limit so that A-MSDUs get through
+    - ARM: tegra: tamonten: Fix UART pad setting
+    - arm64: tegra: Fix compatible string for Tegra132 CPUs
+    - arm64: dts: ls1046a: fix eeprom entries
+    - nvme-tcp: don't check blk_mq_tag_to_rq when receiving pdu data
+    - Bluetooth: Fix handling of LE Enhanced Connection Complete
+    - opp: Don't print an error if required-opps is missing
+    - serial: sh-sci: fix break handling for sysrq
+    - tcp: enable data-less, empty-cookie SYN with TFO_SERVER_COOKIE_NOT_REQD
+    - rpc: fix gss_svc_init cleanup on failure
+    - staging: rts5208: Fix get_ms_information() heap buffer size
+    - gfs2: Don't call dlm after protocol is unmounted
+    - usb: chipidea: host: fix port index underflow and UBSAN complains
+    - lockd: lockd server-side shouldn't set fl_ops
+    - drm/exynos: Always initialize mapping in exynos_drm_register_dma()
+    - m68knommu: only set CONFIG_ISA_DMA_API for ColdFire sub-arch
+    - btrfs: tree-log: check btrfs_lookup_data_extent return value
+    - ASoC: Intel: Skylake: Fix module configuration for KPB and MIXER
+    - ASoC: Intel: Skylake: Fix passing loadable flag for module
+    - of: Don't allow __of_attached_node_sysfs() without CONFIG_SYSFS
+    - mmc: sdhci-of-arasan: Check return value of non-void funtions
+    - mmc: rtsx_pci: Fix long reads when clock is prescaled
+    - selftests/bpf: Enlarge select() timeout for test_maps
+    - mmc: core: Return correct emmc response in case of ioctl error
+    - cifs: fix wrong release in sess_alloc_buffer() failed path
+    - Revert "USB: xhci: fix U1/U2 handling for hardware with XHCI_INTEL_HOST
+      quirk set"
+    - usb: musb: musb_dsps: request_irq() after initializing musb
+    - usbip: give back URBs for unsent unlink requests during cleanup
+    - usbip:vhci_hcd USB port can get stuck in the disabled state
+    - ASoC: rockchip: i2s: Fix regmap_ops hang
+    - ASoC: rockchip: i2s: Fixup config for DAIFMT_DSP_A/B
+    - drm/amdkfd: Account for SH/SE count when setting up cu masks.
+    - iwlwifi: mvm: fix a memory leak in iwl_mvm_mac_ctxt_beacon_changed
+    - iwlwifi: mvm: avoid static queue number aliasing
+    - iwlwifi: mvm: fix access to BSS elements
+    - net/mlx5: DR, Enable QP retransmission
+    - parport: remove non-zero check on count
+    - ath9k: fix OOB read ar9300_eeprom_restore_internal
+    - ath9k: fix sleeping in atomic context
+    - net: fix NULL pointer reference in cipso_v4_doi_free
+    - fix array-index-out-of-bounds in taprio_change
+    - net: w5100: check return value after calling platform_get_resource()
+    - parisc: fix crash with signals and alloca
+    - ovl: fix BUG_ON() in may_delete() when called from ovl_cleanup()
+    - scsi: BusLogic: Fix missing pr_cont() use
+    - scsi: qla2xxx: Changes to support kdump kernel
+    - scsi: qla2xxx: Sync queue idx with queue_pair_map idx
+    - cpufreq: powernv: Fix init_chip_info initialization in numa=off
+    - s390/pv: fix the forcing of the swiotlb
+    - mm/hugetlb: initialize hugetlb_usage in mm_init
+    - mm,vmscan: fix divide by zero in get_scan_count
+    - memcg: enable accounting for pids in nested pid namespaces
+    - platform/chrome: cros_ec_proto: Send command again when timeout occurs
+    - lib/test_stackinit: Fix static initializer test
+    - net: dsa: lantiq_gswip: fix maximum frame length
+    - drm/msi/mdp4: populate priv->kms in mdp4_kms_init
+    - drm/amdgpu: Fix BUG_ON assert
+    - drm/panfrost: Simplify lock_region calculation
+    - drm/panfrost: Use u64 for size in lock_region
+    - drm/panfrost: Clamp lock region to Bifrost minimum
+    - btrfs: fix upper limit for max_inline for page size 64K
+    - xen: reset legacy rtc flag for PV domU
+    - bnx2x: Fix enabling network interfaces without VFs
+    - arm64/sve: Use correct size when reinitialising SVE state
+    - PM: base: power: don't try to use non-existing RTC for storing data
+    - PCI: Add AMD GPU multi-function power dependencies
+    - drm/amd/amdgpu: Increase HWIP_MAX_INSTANCE to 10
+    - drm/etnaviv: return context from etnaviv_iommu_context_get
+    - drm/etnaviv: put submit prev MMU context when it exists
+    - drm/etnaviv: stop abusing mmu_context as FE running marker
+    - drm/etnaviv: keep MMU context across runtime suspend/resume
+    - drm/etnaviv: exec and MMU state is lost when resetting the GPU
+    - drm/etnaviv: fix MMU context leak on GPU reset
+    - drm/etnaviv: reference MMU context when setting up hardware state
+    - drm/etnaviv: add missing MMU context put when reaping MMU mapping
+    - s390/sclp: fix Secure-IPL facility detection
+    - x86/mm: Fix kern_addr_valid() to cope with existing but not present entries
+    - tipc: fix an use-after-free issue in tipc_recvmsg
+    - net-caif: avoid user-triggerable WARN_ON(1)
+    - ptp: dp83640: don't define PAGE0
+    - net/l2tp: Fix reference count leak in l2tp_udp_recv_core
+    - r6040: Restore MDIO clock frequency after MAC reset
+    - tipc: increase timeout in tipc_sk_enqueue()
+    - perf machine: Initialize srcline string member in add_location struct
+    - net/mlx5: FWTrace, cancel work on alloc pd error flow
+    - net/mlx5: Fix potential sleeping in atomic context
+    - events: Reuse value read using READ_ONCE instead of re-reading it
+    - vhost_net: fix OoB on sendmsg() failure.
+    - net/af_unix: fix a data-race in unix_dgram_poll
+    - net: dsa: destroy the phylink instance on any error in dsa_slave_phy_setup
+    - tcp: fix tp->undo_retrans accounting in tcp_sacktag_one()
+    - qed: Handle management FW error
+    - dt-bindings: arm: Fix Toradex compatible typo
+    - ibmvnic: check failover_pending in login response
+    - KVM: PPC: Book3S HV: Tolerate treclaim. in fake-suspend mode changing
+      registers
+    - net: hns3: pad the short tunnel frame before sending to hardware
+    - net: hns3: change affinity_mask to numa node range
+    - net: hns3: disable mac in flr process
+    - net: hns3: fix the timing issue of VF clearing interrupt sources
+    - mm/memory_hotplug: use "unsigned long" for PFN in zone_for_pfn_range()
+    - dt-bindings: mtd: gpmc: Fix the ECC bytes vs. OOB bytes equation
+    - mfd: db8500-prcmu: Adjust map to reality
+    - PCI: Add ACS quirks for NXP LX2xx0 and LX2xx2 platforms
+    - fuse: fix use after free in fuse_read_interrupt()
+    - mfd: Don't use irq_create_mapping() to resolve a mapping
+    - tracing/probes: Reject events which have the same name of existing one
+    - PCI: Add ACS quirks for Cavium multi-function devices
+    - Set fc_nlinfo in nh_create_ipv4, nh_create_ipv6
+    - net: usb: cdc_mbim: avoid altsetting toggling for Telit LN920
+    - PCI: ibmphp: Fix double unmap of io_mem
+    - ethtool: Fix an error code in cxgb2.c
+    - NTB: Fix an error code in ntb_msit_probe()
+    - NTB: perf: Fix an error code in perf_setup_inbuf()
+    - mfd: axp20x: Update AXP288 volatile ranges
+    - PCI: Fix pci_dev_str_match_path() alloc while atomic bug
+    - mfd: tqmx86: Clear GPIO IRQ resource when no IRQ is set
+    - KVM: arm64: Handle PSCI resets before userspace touches vCPU state
+    - PCI: Sync __pci_register_driver() stub for CONFIG_PCI=n
+    - mtd: rawnand: cafe: Fix a resource leak in the error handling path of
+      'cafe_nand_probe()'
+    - ARC: export clear_user_page() for modules
+    - perf unwind: Do not overwrite FEATURE_CHECK_LDFLAGS-libunwind-{x86,aarch64}
+    - net: dsa: b53: Fix calculating number of switch ports
+    - netfilter: socket: icmp6: fix use-after-scope
+    - fq_codel: reject silly quantum parameters
+    - qlcnic: Remove redundant unlock in qlcnic_pinit_from_rom
+    - ip_gre: validate csum_start only on pull
+    - net: renesas: sh_eth: Fix freeing wrong tx descriptor
+    - Linux 5.4.148
+  * Focal update: v5.4.147 upstream stable release (LP: #1946795)
+    - Linux 5.4.147
+    - upstream stable to v5.4.147
+  * CVE-2021-3428
+    - ext4: save the error code which triggered an ext4_error() in the superblock
+    - ext4: simulate various I/O and checksum errors when reading metadata
+    - ext4: save all error info in save_error_info() and drop ext4_set_errno()
+    - ext4: check journal inode extents more carefully
+  * ip6gretap / erspan / ip6erspan in rtnetlink.sh from net of
+    ubuntu_kernel_selftests failed on B-5.4-aws / B-5.4-gke / B-5.4-oracle /
+    B-5.4-azure / B-5.4 (LP: #1896448)
+    - SAUCE: selftests: rtnetlink: fixes for older iproute2
+  * CVE-2019-19449
+    - f2fs: fix wrong total_sections check and fsmeta check
+    - f2fs: fix to do sanity check on segment/section count
+  * kernel bug found when disconnecting one fiber channel interface on Cisco
+    Chassis with fnic DRV_VERSION "1.6.0.47" (LP: #1944586)
+    - scsi: fnic: Do not call 'scsi_done()' for unhandled commands
+  * memfd from ubuntu_kernel_selftests failed to build on B-5.4 (unknown type
+    name ‘__u64’) (LP: #1944613)
+    - SAUCE: selftests/memfd: fix __u64 not defined build issue
+  * Medion Notebook Keyboard not working (LP: #1909814)
+    - ACPI: resources: Add DMI-based legacy IRQ override quirk
+  * vrf: fix refcnt leak with vxlan slaves (LP: #1945180)
+    - ipv4: Fix device used for dst_alloc with local routes
+  * Check for changes relevant for security certifications (LP: #1945989)
+    - [Packaging] Add a new fips-checks script
+    - [Packaging] Add fips-checks as part of finalchecks
+  * Fix cold plugged USB device on certain PCIe USB cards (LP: #1945211)
+    - Revert "UBUNTU: SAUCE: Revert "usb: core: reduce power-on-good delay time of
+      root hub""
+    - usb: core: hcd: Add support for deferring roothub registration
+    - xhci: Set HCD flag to defer primary roothub registration
+    - usb: core: hcd: Modularize HCD stop configuration in usb_stop_hcd()
+  * CVE-2021-3759
+    - memcg: enable accounting of ipc resources
+  * Focal update: v5.4.146 upstream stable release (LP: #1946024)
+    - locking/mutex: Fix HANDOFF condition
+    - regmap: fix the offset of register error log
+    - crypto: mxs-dcp - Check for DMA mapping errors
+    - sched/deadline: Fix reset_on_fork reporting of DL tasks
+    - power: supply: axp288_fuel_gauge: Report register-address on readb / writeb
+      errors
+    - crypto: omap-sham - clear dma flags only after omap_sham_update_dma_stop()
+    - sched/deadline: Fix missing clock update in migrate_task_rq_dl()
+    - rcu/tree: Handle VM stoppage in stall detection
+    - hrtimer: Avoid double reprogramming in __hrtimer_start_range_ns()
+    - hrtimer: Ensure timerfd notification for HIGHRES=n
+    - udf: Check LVID earlier
+    - udf: Fix iocharset=utf8 mount option
+    - isofs: joliet: Fix iocharset=utf8 mount option
+    - bcache: add proper error unwinding in bcache_device_init
+    - nvme-tcp: don't update queue count when failing to set io queues
+    - nvme-rdma: don't update queue count when failing to set io queues
+    - nvmet: pass back cntlid on successful completion
+    - power: supply: max17042_battery: fix typo in MAx17042_TOFF
+    - s390/cio: add dev_busid sysfs entry for each subchannel
+    - libata: fix ata_host_start()
+    - crypto: qat - do not ignore errors from enable_vf2pf_comms()
+    - crypto: qat - handle both source of interrupt in VF ISR
+    - crypto: qat - fix reuse of completion variable
+    - crypto: qat - fix naming for init/shutdown VF to PF notifications
+    - crypto: qat - do not export adf_iov_putmsg()
+    - fcntl: fix potential deadlock for &fasync_struct.fa_lock
+    - udf_get_extendedattr() had no boundary checks.
+    - s390/kasan: fix large PMD pages address alignment check
+    - s390/debug: fix debug area life cycle
+    - m68k: emu: Fix invalid free in nfeth_cleanup()
+    - sched: Fix UCLAMP_FLAG_IDLE setting
+    - spi: spi-fsl-dspi: Fix issue with uninitialized dma_slave_config
+    - spi: spi-pic32: Fix issue with uninitialized dma_slave_config
+    - genirq/timings: Fix error return code in irq_timings_test_irqs()
+    - lib/mpi: use kcalloc in mpi_resize
+    - clocksource/drivers/sh_cmt: Fix wrong setting if don't request IRQ for clock
+      source channel
+    - crypto: qat - use proper type for vf_mask
+    - certs: Trigger creation of RSA module signing key if it's not an RSA key
+    - regulator: vctrl: Use locked regulator_get_voltage in probe path
+    - regulator: vctrl: Avoid lockdep warning in enable/disable ops
+    - spi: sprd: Fix the wrong WDG_LOAD_VAL
+    - spi: spi-zynq-qspi: use wait_for_completion_timeout to make
+      zynq_qspi_exec_mem_op not interruptible
+    - EDAC/i10nm: Fix NVDIMM detection
+    - drm/panfrost: Fix missing clk_disable_unprepare() on error in
+      panfrost_clk_init()
+    - media: TDA1997x: enable EDID support
+    - soc: rockchip: ROCKCHIP_GRF should not default to y, unconditionally
+    - media: cxd2880-spi: Fix an error handling path
+    - bpf: Fix a typo of reuseport map in bpf.h.
+    - bpf: Fix potential memleak and UAF in the verifier.
+    - ARM: dts: aspeed-g6: Fix HVI3C function-group in pinctrl dtsi
+    - arm64: dts: renesas: r8a77995: draak: Remove bogus adv7511w properties
+    - soc: qcom: rpmhpd: Use corner in power_off
+    - media: dvb-usb: fix uninit-value in dvb_usb_adapter_dvb_init
+    - media: dvb-usb: fix uninit-value in vp702x_read_mac_addr
+    - media: dvb-usb: Fix error handling in dvb_usb_i2c_init
+    - media: go7007: remove redundant initialization
+    - media: coda: fix frame_mem_ctrl for YUV420 and YVU420 formats
+    - Bluetooth: sco: prevent information leak in sco_conn_defer_accept()
+    - 6lowpan: iphc: Fix an off-by-one check of array index
+    - netns: protect netns ID lookups with RCU
+    - tcp: seq_file: Avoid skipping sk during tcp_seek_last_pos
+    - ARM: dts: meson8: Use a higher default GPU clock frequency
+    - ARM: dts: meson8b: odroidc1: Fix the pwm regulator supply properties
+    - ARM: dts: meson8b: mxq: Fix the pwm regulator supply properties
+    - ARM: dts: meson8b: ec100: Fix the pwm regulator supply properties
+    - net/mlx5e: Prohibit inner indir TIRs in IPoIB
+    - cgroup/cpuset: Fix a partition bug with hotplug
+    - net: cipso: fix warnings in netlbl_cipsov4_add_std
+    - i2c: highlander: add IRQ check
+    - leds: lt3593: Put fwnode in any case during ->probe()
+    - leds: trigger: audio: Add an activate callback to ensure the initial
+      brightness is set
+    - media: em28xx-input: fix refcount bug in em28xx_usb_disconnect
+    - media: venus: venc: Fix potential null pointer dereference on pointer fmt
+    - PCI: PM: Avoid forcing PCI_D0 for wakeup reasons inconsistently
+    - PCI: PM: Enable PME if it can be signaled from D3cold
+    - soc: qcom: smsm: Fix missed interrupts if state changes while masked
+    - debugfs: Return error during {full/open}_proxy_open() on rmmod
+    - Bluetooth: increase BTNAMSIZ to 21 chars to fix potential buffer overflow
+    - PM: EM: Increase energy calculation precision
+    - drm/msm/dpu: make dpu_hw_ctl_clear_all_blendstages clear necessary LMs
+    - arm64: dts: exynos: correct GIC CPU interfaces address range on Exynos7
+    - counter: 104-quad-8: Return error when invalid mode during ceiling_write
+    - Bluetooth: fix repeated calls to sco_sock_kill
+    - drm/msm/dsi: Fix some reference counted resource leaks
+    - usb: gadget: udc: at91: add IRQ check
+    - usb: phy: fsl-usb: add IRQ check
+    - usb: phy: twl6030: add IRQ checks
+    - usb: gadget: udc: renesas_usb3: Fix soc_device_match() abuse
+    - usb: host: ohci-tmio: add IRQ check
+    - usb: phy: tahvo: add IRQ check
+    - mac80211: Fix insufficient headroom issue for AMSDU
+    - lockd: Fix invalid lockowner cast after vfs_test_lock
+    - nfsd4: Fix forced-expiry locking
+    - usb: gadget: mv_u3d: request_irq() after initializing UDC
+    - mm/swap: consider max pages in iomap_swapfile_add_extent
+    - Bluetooth: add timeout sanity check to hci_inquiry
+    - i2c: iop3xx: fix deferred probing
+    - i2c: s3c2410: fix IRQ check
+    - rsi: fix error code in rsi_load_9116_firmware()
+    - rsi: fix an error code in rsi_probe()
+    - ASoC: Intel: Skylake: Leave data as is when invoking TLV IPCs
+    - ASoC: Intel: Skylake: Fix module resource and format selection
+    - mmc: dw_mmc: Fix issue with uninitialized dma_slave_config
+    - mmc: moxart: Fix issue with uninitialized dma_slave_config
+    - bpf: Fix possible out of bound write in narrow load handling
+    - CIFS: Fix a potencially linear read overflow
+    - i2c: mt65xx: fix IRQ check
+    - usb: ehci-orion: Handle errors of clk_prepare_enable() in probe
+    - usb: bdc: Fix an error handling path in 'bdc_probe()' when no suitable DMA
+      config is available
+    - tty: serial: fsl_lpuart: fix the wrong mapbase value
+    - ASoC: wcd9335: Fix a double irq free in the remove function
+    - ASoC: wcd9335: Fix a memory leak in the error handling path of the probe
+      function
+    - ASoC: wcd9335: Disable irq on slave ports in the remove function
+    - ath6kl: wmi: fix an error code in ath6kl_wmi_sync_point()
+    - bcma: Fix memory leak for internally-handled cores
+    - brcmfmac: pcie: fix oops on failure to resume and reprobe
+    - ipv6: make exception cache less predictible
+    - ipv4: make exception cache less predictible
+    - net: sched: Fix qdisc_rate_table refcount leak when get tcf_block failed
+    - net: qualcomm: fix QCA7000 checksum handling
+    - octeontx2-af: Fix loop in free and unmap counter
+    - ipv4: fix endianness issue in inet_rtm_getroute_build_skb()
+    - bpf: Introduce BPF nospec instruction for mitigating Spectre v4
+    - bpf: Fix leakage due to insufficient speculative store bypass mitigation
+    - bpf: verifier: Allocate idmap scratch in verifier env
+    - bpf: Fix pointer arithmetic mask tightening under state pruning
+    - tty: Fix data race between tiocsti() and flush_to_ldisc()
+    - perf/x86/amd/ibs: Extend PERF_PMU_CAP_NO_EXCLUDE to IBS Op
+    - x86/resctrl: Fix a maybe-uninitialized build warning treated as error
+    - KVM: s390: index kvm->arch.idle_mask by vcpu_idx
+    - KVM: x86: Update vCPU's hv_clock before back to guest when tsc_offset is
+      adjusted
+    - KVM: nVMX: Unconditionally clear nested.pi_pending on nested VM-Enter
+    - fuse: truncate pagecache on atomic_o_trunc
+    - fuse: flush extending writes
+    - IMA: remove -Wmissing-prototypes warning
+    - IMA: remove the dependency on CRYPTO_MD5
+    - fbmem: don't allow too huge resolutions
+    - backlight: pwm_bl: Improve bootloader/kernel device handover
+    - clk: kirkwood: Fix a clocking boot regression
+    - Linux 5.4.146
+  * AMD A8-7680 (amdgpu): broken Xorg acceleration and hibernation
+    (LP: #1920674) // Focal update: v5.4.146 upstream stable release
+    (LP: #1946024)
+    - drm/amdgpu/acp: Make PM domain really work
+  * Focal update: v5.4.145 upstream stable release (LP: #1945517)
+    - fscrypt: add fscrypt_symlink_getattr() for computing st_size
+    - ext4: report correct st_size for encrypted symlinks
+    - f2fs: report correct st_size for encrypted symlinks
+    - ubifs: report correct st_size for encrypted symlinks
+    - kthread: Fix PF_KTHREAD vs to_kthread() race
+    - xtensa: fix kconfig unmet dependency warning for HAVE_FUTEX_CMPXCHG
+    - gpu: ipu-v3: Fix i.MX IPU-v3 offset calculations for (semi)planar U/V
+      formats
+    - reset: reset-zynqmp: Fixed the argument data type
+    - qed: Fix the VF msix vectors flow
+    - net: macb: Add a NULL check on desc_ptp
+    - qede: Fix memset corruption
+    - perf/x86/intel/pt: Fix mask of num_address_ranges
+    - perf/x86/amd/ibs: Work around erratum #1197
+    - perf/x86/amd/power: Assign pmu.module
+    - cryptoloop: add a deprecation warning
+    - ARM: 8918/2: only build return_address() if needed
+    - ALSA: hda/realtek: Workaround for conflicting SSID on ASUS ROG Strix G17
+    - ALSA: pcm: fix divide error in snd_pcm_lib_ioctl
+    - ARC: wireup clone3 syscall
+    - media: stkwebcam: fix memory leak in stk_camera_probe
+    - igmp: Add ip_mc_list lock in ip_check_mc_rcu
+    - USB: serial: mos7720: improve OOM-handling in read_mos_reg()
+    - ipv4/icmp: l3mdev: Perform icmp error route lookup on source device routing
+      table (v2)
+    - powerpc/boot: Delete unneeded .globl _zimage_start
+    - net: ll_temac: Remove left-over debug message
+    - mm/page_alloc: speed up the iteration of max_order
+    - Revert "r8169: avoid link-up interrupt issue on RTL8106e if user enables
+      ASPM"
+    - x86/events/amd/iommu: Fix invalid Perf result due to IOMMU PMC power-gating
+    - Revert "btrfs: compression: don't try to compress if we don't have enough
+      pages"
+    - ALSA: usb-audio: Add registration quirk for JBL Quantum 800
+    - usb: host: xhci-rcar: Don't reload firmware after the completion
+    - usb: mtu3: use @mult for HS isoc or intr
+    - usb: mtu3: fix the wrong HS mult value
+    - xhci: fix unsafe memory usage in xhci tracing
+    - x86/reboot: Limit Dell Optiplex 990 quirk to early BIOS versions
+    - PCI: Call Max Payload Size-related fixup quirks early
+    - Linux 5.4.145
+  * Focal update: v5.4.144 upstream stable release (LP: #1944756)
+    - net: qrtr: fix another OOB Read in qrtr_endpoint_post
+    - ARC: Fix CONFIG_STACKDEPOT
+    - netfilter: conntrack: collect all entries in one cycle
+    - once: Fix panic when module unload
+    - ovl: fix uninitialized pointer read in ovl_lookup_real_one()
+    - mmc: sdhci-msm: Update the software timeout value for sdhc
+    - mm, oom: make the calculation of oom badness more accurate
+    - can: usb: esd_usb2: esd_usb2_rx_event(): fix the interchange of the CAN RX
+      and TX error counters
+    - Revert "USB: serial: ch341: fix character loss at high transfer rates"
+    - USB: serial: option: add new VID/PID to support Fibocom FG150
+    - usb: dwc3: gadget: Fix dwc3_calc_trbs_left()
+    - usb: dwc3: gadget: Stop EP0 transfers during pullup disable
+    - scsi: core: Fix hang of freezing queue between blocking and running device
+    - RDMA/bnxt_re: Add missing spin lock initialization
+    - IB/hfi1: Fix possible null-pointer dereference in _extend_sdma_tx_descs()
+    - e1000e: Fix the max snoop/no-snoop latency for 10M
+    - RDMA/efa: Free IRQ vectors on error flow
+    - ip_gre: add validation for csum_start
+    - xgene-v2: Fix a resource leak in the error handling path of 'xge_probe()'
+    - net: marvell: fix MVNETA_TX_IN_PRGRS bit number
+    - rtnetlink: Return correct error on changing device netns
+    - net: hns3: clear hardware resource when loading driver
+    - net: hns3: fix duplicate node in VLAN list
+    - net: hns3: fix get wrong pfc_en when query PFC configuration
+    - drm/i915: Fix syncmap memory leak
+    - usb: gadget: u_audio: fix race condition on endpoint stop
+    - perf/x86/intel/uncore: Fix integer overflow on 23 bit left shift of a u32
+    - opp: remove WARN when no valid OPPs remain
+    - virtio: Improve vq->broken access to avoid any compiler optimization
+    - virtio_pci: Support surprise removal of virtio pci device
+    - vringh: Use wiov->used to check for read/write desc order
+    - qed: qed ll2 race condition fixes
+    - qed: Fix null-pointer dereference in qed_rdma_create_qp()
+    - drm: Copy drm_wait_vblank to user before returning
+    - drm/nouveau/disp: power down unused DP links during init
+    - net/rds: dma_map_sg is entitled to merge entries
+    - btrfs: fix race between marking inode needs to be logged and log syncing
+    - vt_kdsetmode: extend console locking
+    - bpf: Track contents of read-only maps as scalars
+    - bpf: Fix cast to pointer from integer of different size warning
+    - net: dsa: mt7530: fix VLAN traffic leaks again
+    - KVM: x86/mmu: Treat NX as used (not reserved) for all !TDP shadow MMUs
+    - arm64: dts: qcom: msm8994-angler: Fix gpio-reserved-ranges 85-88
+    - btrfs: fix NULL pointer dereference when deleting device by invalid id
+    - Revert "floppy: reintroduce O_NDELAY fix"
+    - Revert "parisc: Add assembly implementations for memset, strlen, strcpy,
+      strncpy and strcat"
+    - net: don't unconditionally copy_from_user a struct ifreq for socket ioctls
+    - audit: move put_tree() to avoid trim_trees refcount underflow and UAF
+    - Linux 5.4.144
+
+  [ Ubuntu: 5.4.0-89.100 ]
+
+  * focal/linux: 5.4.0-89.100 -proposed tracker (LP: #1944901)
+  * Packaging resync (LP: #1786013)
+    - debian/dkms-versions -- update from kernel-versions (main/2021.09.27)
+  * ext4 journal recovery fails w/ data=journal + mmap (LP: #1847340)
+    - jbd2: introduce/export functions
+      jbd2_journal_submit|finish_inode_data_buffers()
+    - jbd2, ext4, ocfs2: introduce/use journal callbacks
+      j_submit|finish_inode_data_buffers()
+    - ext4: data=journal: fixes for ext4_page_mkwrite()
+    - ext4: data=journal: write-protect pages on j_submit_inode_data_buffers()
+    - ext4: fix mmap write protection for data=journal mode
+  * CVE-2021-40490
+    - ext4: fix race writing to an inline_data file while its xattrs are changing
+  * Obsolete patch "UBUNTU: SAUCE: ext4: fix directory index node split
+    corruption" (LP: #1942902)
+    - Revert "UBUNTU: SAUCE: ext4: fix directory index node split corruption"
+  * psock_snd.sh in net from ubuntu_kernel_selftests ADT failure with
+    focal/groovy/hirsute/impish (LP: #1892213)
+    - selftests/net: remove min gso test in packet_snd
+  * Focal update: v5.4.143 upstream stable release (LP: #1944212)
+    - ext4: fix EXT4_MAX_LOGICAL_BLOCK macro
+    - x86/fpu: Make init_fpstate correct with optimized XSAVE
+    - ath: Use safer key clearing with key cache entries
+    - ath9k: Clear key cache explicitly on disabling hardware
+    - ath: Export ath_hw_keysetmac()
+    - ath: Modify ath_key_delete() to not need full key entry
+    - ath9k: Postpone key cache entry deletion for TXQ frames reference it
+    - mtd: cfi_cmdset_0002: fix crash when erasing/writing AMD cards
+    - media: zr364xx: propagate errors from zr364xx_start_readpipe()
+    - media: zr364xx: fix memory leaks in probe()
+    - media: drivers/media/usb: fix memory leak in zr364xx_probe
+    - USB: core: Avoid WARNings for 0-length descriptor requests
+    - dmaengine: xilinx_dma: Fix read-after-free bug when terminating transfers
+    - dmaengine: usb-dmac: Fix PM reference leak in usb_dmac_probe()
+    - ARM: dts: am43x-epos-evm: Reduce i2c0 bus speed for tps65218
+    - dmaengine: of-dma: router_xlate to return -EPROBE_DEFER if controller is not
+      yet available
+    - scsi: megaraid_mm: Fix end of loop tests for list_for_each_entry()
+    - scsi: scsi_dh_rdac: Avoid crash during rdac_bus_attach()
+    - scsi: core: Avoid printing an error if target_alloc() returns -ENXIO
+    - scsi: core: Fix capacity set to zero after offlinining device
+    - ARM: dts: nomadik: Fix up interrupt controller node names
+    - net: usb: lan78xx: don't modify phy_device state concurrently
+    - drm/amd/display: Fix Dynamic bpp issue with 8K30 with Navi 1X
+    - Bluetooth: hidp: use correct wait queue when removing ctrl_wait
+    - iommu: Check if group is NULL before remove device
+    - cpufreq: armada-37xx: forbid cpufreq for 1.2 GHz variant
+    - dccp: add do-while-0 stubs for dccp_pr_debug macros
+    - virtio: Protect vqs list access
+    - vhost: Fix the calculation in vhost_overflow()
+    - bpf: Clear zext_dst of dead insns
+    - bnxt: don't lock the tx queue from napi poll
+    - bnxt: disable napi before canceling DIM
+    - net: 6pack: fix slab-out-of-bounds in decode_data
+    - ptp_pch: Restore dependency on PCI
+    - bnxt_en: Add missing DMA memory barriers
+    - vrf: Reset skb conntrack connection on VRF rcv
+    - virtio-net: support XDP when not more queues
+    - virtio-net: use NETIF_F_GRO_HW instead of NETIF_F_LRO
+    - net: qlcnic: add missed unlock in qlcnic_83xx_flash_read32
+    - net: mdio-mux: Don't ignore memory allocation errors
+    - net: mdio-mux: Handle -EPROBE_DEFER correctly
+    - ovs: clear skb->tstamp in forwarding path
+    - i40e: Fix ATR queue selection
+    - iavf: Fix ping is lost after untrusted VF had tried to change MAC
+    - ovl: add splice file read write helper
+    - mmc: dw_mmc: Fix hang on data CRC error
+    - ALSA: hda - fix the 'Capture Switch' value change notifications
+    - tracing / histogram: Fix NULL pointer dereference on strcmp() on NULL event
+      name
+    - slimbus: messaging: start transaction ids from 1 instead of zero
+    - slimbus: messaging: check for valid transaction id
+    - slimbus: ngd: reset dma setup during runtime pm
+    - ipack: tpci200: fix many double free issues in tpci200_pci_probe
+    - ipack: tpci200: fix memory leak in the tpci200_register
+    - btrfs: prevent rename2 from exchanging a subvol with a directory from
+      different parents
+    - PCI: Increase D3 delay for AMD Renoir/Cezanne XHCI
+    - ASoC: intel: atom: Fix breakage for PCM buffer address setup
+    - mm, memcg: avoid stale protection values when cgroup is above protection
+    - mm: memcontrol: fix occasional OOMs due to proportional memory.low reclaim
+    - fs: warn about impending deprecation of mandatory locks
+    - netfilter: nft_exthdr: fix endianness of tcp option cast
+    - Linux 5.4.143
+  * Focal update: v5.4.142 upstream stable release (LP: #1944202)
+    - iio: adc: ti-ads7950: Ensure CS is deasserted after reading channels
+    - iio: humidity: hdc100x: Add margin to the conversion time
+    - iio: adc: Fix incorrect exit of for-loop
+    - ASoC: xilinx: Fix reference to PCM buffer address
+    - ASoC: intel: atom: Fix reference to PCM buffer address
+    - i2c: dev: zero out array used for i2c reads from userspace
+    - ceph: reduce contention in ceph_check_delayed_caps()
+    - ACPI: NFIT: Fix support for virtual SPA ranges
+    - libnvdimm/region: Fix label activation vs errors
+    - ieee802154: hwsim: fix GPF in hwsim_set_edge_lqi
+    - ieee802154: hwsim: fix GPF in hwsim_new_edge_nl
+    - ASoC: cs42l42: Correct definition of ADC Volume control
+    - ASoC: cs42l42: Don't allow SND_SOC_DAIFMT_LEFT_J
+    - ASoC: cs42l42: Fix inversion of ADC Notch Switch control
+    - ASoC: cs42l42: Remove duplicate control for WNF filter frequency
+    - netfilter: nf_conntrack_bridge: Fix memory leak when error
+    - ASoC: cs42l42: Fix LRCLK frame start edge
+    - net: dsa: mt7530: add the missing RxUnicast MIB counter
+    - platform/x86: pcengines-apuv2: revert wiring up simswitch GPIO as LED
+    - platform/x86: pcengines-apuv2: Add missing terminating entries to gpio-
+      lookup tables
+    - net: phy: micrel: Fix link detection on ksz87xx switch"
+    - ppp: Fix generating ifname when empty IFLA_IFNAME is specified
+    - net: sched: act_mirred: Reset ct info when mirror/redirect skb
+    - iavf: Set RSS LUT and key in reset handle path
+    - psample: Add a fwd declaration for skbuff
+    - net/mlx5: Fix return value from tracer initialization
+    - drm/meson: fix colour distortion from HDR set during vendor u-boot
+    - net: dsa: microchip: Fix ksz_read64()
+    - net: Fix memory leak in ieee802154_raw_deliver
+    - net: igmp: fix data-race in igmp_ifc_timer_expire()
+    - net: dsa: lan9303: fix broken backpressure in .port_fdb_dump
+    - net: dsa: lantiq: fix broken backpressure in .port_fdb_dump
+    - net: dsa: sja1105: fix broken backpressure in .port_fdb_dump
+    - net: bridge: fix memleak in br_add_if()
+    - net: linkwatch: fix failure to restore device state across suspend/resume
+    - tcp_bbr: fix u32 wrap bug in round logic if bbr_init() called after 2B
+      packets
+    - net: igmp: increase size of mr_ifc_count
+    - xen/events: Fix race in set_evtchn_to_irq
+    - vsock/virtio: avoid potential deadlock when vsock device remove
+    - nbd: Aovid double completion of a request
+    - powerpc/kprobes: Fix kprobe Oops happens in booke
+    - x86/tools: Fix objdump version check again
+    - genirq: Provide IRQCHIP_AFFINITY_PRE_STARTUP
+    - x86/msi: Force affinity setup before startup
+    - x86/ioapic: Force affinity setup before startup
+    - x86/resctrl: Fix default monitoring groups reporting
+    - genirq/msi: Ensure deactivation on teardown
+    - genirq/timings: Prevent potential array overflow in __irq_timings_store()
+    - PCI/MSI: Enable and mask MSI-X early
+    - PCI/MSI: Mask all unused MSI-X entries
+    - PCI/MSI: Enforce that MSI-X table entry is masked for update
+    - PCI/MSI: Enforce MSI[X] entry updates to be visible
+    - PCI/MSI: Do not set invalid bits in MSI mask
+    - PCI/MSI: Correct misleading comments
+    - PCI/MSI: Use msi_mask_irq() in pci_msi_shutdown()
+    - PCI/MSI: Protect msi_desc::masked for multi-MSI
+    - KVM: VMX: Use current VMCS to query WAITPKG support for MSR emulation
+    - ceph: add some lockdep assertions around snaprealm handling
+    - ceph: clean up locking annotation for ceph_get_snap_realm and
+      __lookup_snap_realm
+    - ceph: take snap_empty_lock atomically with snaprealm refcount change
+    - vmlinux.lds.h: Handle clang's module.{c,d}tor sections
+    - iommu/vt-d: Fix agaw for a supported 48 bit guest address width
+    - Linux 5.4.142
+  * Focal update: v5.4.141 upstream stable release (LP: #1943484)
+    - KVM: SVM: Fix off-by-one indexing when nullifying last used SEV VMCB
+    - tee: Correct inappropriate usage of TEE_SHM_DMA_BUF flag
+    - media: v4l2-mem2mem: always consider OUTPUT queue during poll
+    - tracing: Reject string operand in the histogram expression
+    - usb: dwc3: Stop active transfers before halting the controller
+    - usb: dwc3: gadget: Allow runtime suspend if UDC unbinded
+    - usb: dwc3: gadget: Restart DWC3 gadget when enabling pullup
+    - usb: dwc3: gadget: Prevent EP queuing while stopping transfers
+    - usb: dwc3: gadget: Clear DEP flags after stop transfers in ep disable
+    - usb: dwc3: gadget: Disable gadget IRQ during pullup disable
+    - usb: dwc3: gadget: Avoid runtime resume if disabling pullup
+    - KVM: X86: MMU: Use the correct inherited permissions to get shadow page
+    - USB:ehci:fix Kunpeng920 ehci hardware problem
+    - ALSA: hda: Add quirk for ASUS Flow x13
+    - ppp: Fix generating ppp unit id when ifname is not specified
+    - ovl: prevent private clone if bind mount is not allowed
+    - btrfs: make qgroup_free_reserved_data take btrfs_inode
+    - btrfs: make btrfs_qgroup_reserve_data take btrfs_inode
+    - btrfs: qgroup: allow to unreserve range without releasing other ranges
+    - btrfs: qgroup: try to flush qgroup space when we get -EDQUOT
+    - btrfs: transaction: Cleanup unused TRANS_STATE_BLOCKED
+    - btrfs: qgroup: remove ASYNC_COMMIT mechanism in favor of reserve retry-
+      after-EDQUOT
+    - btrfs: fix lockdep splat when enabling and disabling qgroups
+    - net: xilinx_emaclite: Do not print real IOMEM pointer
+    - btrfs: qgroup: don't commit transaction when we already hold the handle
+    - btrfs: export and rename qgroup_reserve_meta
+    - btrfs: don't flush from btrfs_delayed_inode_reserve_metadata
+    - Linux 5.4.141
+
+ -- Wen-chien Jesse Sung <jesse.sung@canonical.com>  Mon, 12 Sep 2022 20:10:56 +0800
+
+linux-xilinx-zynqmp (5.4.0-1017.20) focal; urgency=medium
+
+  * INVALID or PRIVATE BUG (LP: #1949221)
+    - [Config] Enable NFS Server configs
+
+  * Miscellaneous upstream changes
+    - usb: dwc3: gadget: Don't send unintended link state change
+    - usb: dwc3: gadget: Set link state to RX_Detect on disconnect
+    - usb: dwc3: gadget: Clear DCTL.ULSTCHNGREQ before set
+    - spi: spi-zynqmp-gqspi: Set tapdelay as per spi-max-frequency
+    - spi: spi-cadence: Fix SPI CS gets toggling sporadically
+
+  [ Ubuntu: 5.4.0-88.99 ]
+
+  * focal/linux: 5.4.0-88.99 -proposed tracker (LP: #1944747)
+  * Packaging resync (LP: #1786013)
+    - debian/dkms-versions -- update from kernel-versions (main/2021.09.06)
+  * please drop virtualbox-guest-dkms virtualbox-guest-source (LP: #1933248)
+    - Revert "UBUNTU: [Config] Disable virtualbox dkms build"
+
+  [ Ubuntu: 5.4.0-87.98 ]
+
+  * please drop virtualbox-guest-dkms virtualbox-guest-source (LP: #1933248)
+    - [Config] Disable virtualbox dkms build
+  * Packaging resync (LP: #1786013)
+    - debian/dkms-versions -- update from kernel-versions (main/2021.09.06)
+  *  LRMv5: switch primary version handling to kernel-versions data set
+    (LP: #1928921)
+    - [Packaging] switch to kernel-versions
+  * disable “CONFIG_HISI_DMA” config for ubuntu version (LP: #1936771)
+    - Disable CONFIG_HISI_DMA
+    - [Config] Record hisi_dma no longer built for arm64
+  * memory leaking when removing a profile (LP: #1939915)
+    - apparmor: Fix memory leak of profile proxy
+  * CryptoExpress EP11 cards are going offline (LP: #1939618)
+    - s390/zcrypt: Support for CCA protected key block version 2
+    - s390: Replace zero-length array with flexible-array member
+    - s390/zcrypt: Use scnprintf() for avoiding potential buffer overflow
+    - s390/zcrypt: replace snprintf/sprintf with scnprintf
+    - s390/ap: Remove ap device suspend and resume callbacks
+    - s390/zcrypt: use fallthrough;
+    - s390/zcrypt: use kvmalloc instead of kmalloc for 256k alloc
+    - s390/ap: remove power management code from ap bus and drivers
+    - s390/ap: introduce new ap function ap_get_qdev()
+    - s390/zcrypt: use kzalloc
+    - s390/zcrypt: fix smatch warnings
+    - s390/zcrypt: code beautification and struct field renames
+    - s390/zcrypt: split ioctl function into smaller code units
+    - s390/ap: rename and clarify ap state machine related stuff
+    - s390/zcrypt: provide cex4 cca sysfs attributes for cex3
+    - s390/ap: rework crypto config info and default domain code
+    - s390/zcrypt: simplify cca_findcard2 loop code
+    - s390/zcrypt: remove set_fs() invocation in zcrypt device driver
+    - s390/ap: remove unnecessary spin_lock_init()
+    - s390/zcrypt: Support for CCA APKA master keys
+    - s390/zcrypt: introduce msg tracking in zcrypt functions
+    - s390/ap: split ap queue state machine state from device state
+    - s390/ap: add error response code field for ap queue devices
+    - s390/ap: add card/queue deconfig state
+    - s390/sclp: Add support for SCLP AP adapter config/deconfig
+    - s390/ap: Support AP card SCLP config and deconfig operations
+    - s390/ap/zcrypt: revisit ap and zcrypt error handling
+    - s390/zcrypt: move ap_msg param one level up the call chain
+    - s390/zcrypt: Introduce Failure Injection feature
+    - s390/zcrypt: fix wrong format specifications
+    - s390/ap: fix ap devices reference counting
+    - s390/zcrypt: return EIO when msg retry limit reached
+    - s390/zcrypt: fix zcard and zqueue hot-unplug memleak
+    - s390/ap: Fix hanging ioctl caused by wrong msg counter
+  * memfd from ubuntu_kernel_selftests failed to build on B-5.4 (LP: #1926142)
+    - SAUCE: selftests/memfd: fix build when F_SEAL_FUTURE_WRITE is not defined
+  * [SRU] Ice driver causes the kernel to crash with Ubuntu 20.04.2 with ethtool
+    specific register commands (LP: #1939855)
+    - ice: Fix bad register reads
+  * ubunut_kernel_selftests: memory-hotplug: avoid spamming logs with
+    dump_page() (LP: #1941829)
+    - selftests: memory-hotplug: avoid spamming logs with dump_page(), ratio limit
+      hot-remove error test
+  * e1000e blocks the boot process when it tried to write checksum to its NVM
+    (LP: #1936998)
+    - e1000e: Do not take care about recovery NVM checksum
+  * Focal update: v5.4.140 upstream stable release (LP: #1941798)
+    - Revert "ACPICA: Fix memory leak caused by _CID repair function"
+    - ALSA: seq: Fix racy deletion of subscriber
+    - arm64: dts: ls1028a: fix node name for the sysclk
+    - ARM: imx: add missing iounmap()
+    - ARM: imx: add missing clk_disable_unprepare()
+    - ARM: dts: imx6qdl-sr-som: Increase the PHY reset duration to 10ms
+    - ARM: dts: colibri-imx6ull: limit SDIO clock to 25MHz
+    - ARM: imx: fix missing 3rd argument in macro imx_mmdc_perf_init
+    - ARM: dts: imx: Swap M53Menlo pinctrl_power_button/pinctrl_power_out pins
+    - arm64: dts: armada-3720-turris-mox: remove mrvl,i2c-fast-mode
+    - ALSA: usb-audio: fix incorrect clock source setting
+    - clk: stm32f4: fix post divisor setup for I2S/SAI PLLs
+    - ARM: dts: am437x-l4: fix typo in can@0 node
+    - omap5-board-common: remove not physically existing vdds_1v8_main fixed-
+      regulator
+    - spi: imx: mx51-ecspi: Reinstate low-speed CONFIGREG delay
+    - spi: imx: mx51-ecspi: Fix low-speed CONFIGREG delay calculation
+    - scsi: sr: Return correct event when media event code is 3
+    - media: videobuf2-core: dequeue if start_streaming fails
+    - dmaengine: imx-dma: configure the generic DMA type to make it work
+    - net, gro: Set inner transport header offset in tcp/udp GRO hook
+    - net: dsa: sja1105: overwrite dynamic FDB entries with static ones in
+      .port_fdb_add
+    - net: dsa: sja1105: invalidate dynamic FDB entries learned concurrently with
+      statically added ones
+    - net: phy: micrel: Fix detection of ksz87xx switch
+    - net: natsemi: Fix missing pci_disable_device() in probe and remove
+    - gpio: tqmx86: really make IRQ optional
+    - sctp: move the active_key update after sh_keys is added
+    - nfp: update ethtool reporting of pauseframe control
+    - net: ipv6: fix returned variable type in ip6_skb_dst_mtu
+    - mips: Fix non-POSIX regexp
+    - bnx2x: fix an error code in bnx2x_nic_load()
+    - net: pegasus: fix uninit-value in get_interrupt_interval
+    - net: fec: fix use-after-free in fec_drv_remove
+    - net: vxge: fix use-after-free in vxge_device_unregister
+    - blk-iolatency: error out if blk_get_queue() failed in iolatency_set_limit()
+    - Bluetooth: defer cleanup of resources in hci_unregister_dev()
+    - USB: usbtmc: Fix RCU stall warning
+    - USB: serial: option: add Telit FD980 composition 0x1056
+    - USB: serial: ch341: fix character loss at high transfer rates
+    - USB: serial: ftdi_sio: add device ID for Auto-M3 OP-COM v2
+    - firmware_loader: use -ETIMEDOUT instead of -EAGAIN in fw_load_sysfs_fallback
+    - firmware_loader: fix use-after-free in firmware_fallback_sysfs
+    - ALSA: hda/realtek: add mic quirk for Acer SF314-42
+    - ALSA: usb-audio: Add registration quirk for JBL Quantum 600
+    - usb: cdns3: Fixed incorrect gadget state
+    - usb: gadget: f_hid: added GET_IDLE and SET_IDLE handlers
+    - usb: gadget: f_hid: fixed NULL pointer dereference
+    - usb: gadget: f_hid: idle uses the highest byte for duration
+    - usb: otg-fsm: Fix hrtimer list corruption
+    - clk: fix leak on devm_clk_bulk_get_all() unwind
+    - scripts/tracing: fix the bug that can't parse raw_trace_func
+    - tracing / histogram: Give calculation hist_fields a size
+    - optee: Clear stale cache entries during initialization
+    - tee: add tee_shm_alloc_kernel_buf()
+    - optee: Fix memory leak when failing to register shm pages
+    - tpm_ftpm_tee: Free and unregister TEE shared memory during kexec
+    - staging: rtl8723bs: Fix a resource leak in sd_int_dpc
+    - staging: rtl8712: get rid of flush_scheduled_work
+    - media: rtl28xxu: fix zero-length control request
+    - pipe: increase minimum default pipe size to 2 pages
+    - ext4: fix potential htree corruption when growing large_dir directories
+    - serial: tegra: Only print FIFO error message when an error occurs
+    - serial: 8250_mtk: fix uart corruption issue when rx power off
+    - serial: 8250: Mask out floating 16/32-bit bus bits
+    - MIPS: Malta: Do not byte-swap accesses to the CBUS UART
+    - serial: 8250_pci: Enumerate Elkhart Lake UARTs via dedicated driver
+    - serial: 8250_pci: Avoid irq sharing for MSI(-X) interrupts.
+    - timers: Move clearing of base::timer_running under base:: Lock
+    - pcmcia: i82092: fix a null pointer dereference bug
+    - md/raid10: properly indicate failure when ending a failed write request
+    - KVM: x86: accept userspace interrupt only if no event is injected
+    - KVM: Do not leak memory for duplicate debugfs directories
+    - KVM: x86/mmu: Fix per-cpu counter corruption on 32-bit builds
+    - arm64: vdso: Avoid ISB after reading from cntvct_el0
+    - soc: ixp4xx: fix printing resources
+    - spi: meson-spicc: fix memory leak in meson_spicc_remove
+    - soc: ixp4xx/qmgr: fix invalid __iomem access
+    - perf/x86/amd: Don't touch the AMD64_EVENTSEL_HOSTONLY bit inside the guest
+    - bpf, selftests: Adjust few selftest result_unpriv outcomes
+    - libata: fix ata_pio_sector for CONFIG_HIGHMEM
+    - reiserfs: add check for root_inode in reiserfs_fill_super
+    - reiserfs: check directory items on read from disk
+    - virt_wifi: fix error on connect
+    - alpha: Send stop IPI to send to online CPUs
+    - net/qla3xxx: fix schedule while atomic in ql_wait_for_drvr_lock and
+      ql_adapter_reset
+    - arm64: fix compat syscall return truncation
+    - Linux 5.4.140
+  * Focal update: v5.4.139 upstream stable release (LP: #1941796)
+    - btrfs: delete duplicated words + other fixes in comments
+    - btrfs: do not commit logs and transactions during link and rename operations
+    - btrfs: fix race causing unnecessary inode logging during link and rename
+    - btrfs: fix lost inode on log replay after mix of fsync, rename and inode
+      eviction
+    - regulator: rt5033: Fix n_voltages settings for BUCK and LDO
+    - spi: stm32h7: fix full duplex irq handler handling
+    - ASoC: tlv320aic31xx: fix reversed bclk/wclk master bits
+    - r8152: Fix potential PM refcount imbalance
+    - qed: fix possible unpaired spin_{un}lock_bh in _qed_mcp_cmd_and_union()
+    - net: Fix zero-copy head len calculation.
+    - nvme: fix nvme_setup_command metadata trace event
+    - ACPI: fix NULL pointer dereference
+    - Revert "Bluetooth: Shutdown controller after workqueues are flushed or
+      cancelled"
+    - firmware: arm_scmi: Ensure drivers provide a probe function
+    - firmware: arm_scmi: Add delayed response status check
+    - bpf: Inherit expanded/patched seen count from old aux data
+    - bpf: Do not mark insn as seen under speculative path verification
+    - bpf: Fix leakage under speculation on mispredicted branches
+    - bpf: Test_verifier, add alu32 bounds tracking tests
+    - bpf, selftests: Add a verifier test for assigning 32bit reg states to 64bit
+      ones
+    - bpf, selftests: Adjust few selftest outcomes wrt unreachable code
+    - spi: mediatek: Fix fifo transfer
+    - Linux 5.4.139
+  * Focal update: v5.4.138 upstream stable release (LP: #1940559)
+    - net_sched: check error pointer in tcf_dump_walker()
+    - x86/asm: Ensure asm/proto.h can be included stand-alone
+    - btrfs: fix rw device counting in __btrfs_free_extra_devids
+    - btrfs: mark compressed range uptodate only if all bio succeed
+    - x86/kvm: fix vcpu-id indexed array sizes
+    - KVM: add missing compat KVM_CLEAR_DIRTY_LOG
+    - ocfs2: fix zero out valid data
+    - ocfs2: issue zeroout to EOF blocks
+    - can: j1939: j1939_xtp_rx_dat_one(): fix rxtimer value between consecutive
+      TP.DT to 750ms
+    - can: raw: raw_setsockopt(): fix raw_rcv panic for sock UAF
+    - can: mcba_usb_start(): add missing urb->transfer_dma initialization
+    - can: usb_8dev: fix memory leak
+    - can: ems_usb: fix memory leak
+    - can: esd_usb2: fix memory leak
+    - HID: wacom: Re-enable touch by default for Cintiq 24HDT / 27QHDT
+    - NIU: fix incorrect error return, missed in previous revert
+    - nfc: nfcsim: fix use after free during module unload
+    - cfg80211: Fix possible memory leak in function cfg80211_bss_update
+    - netfilter: conntrack: adjust stop timestamp to real expiry value
+    - netfilter: nft_nat: allow to specify layer 4 protocol NAT only
+    - i40e: Fix logic of disabling queues
+    - i40e: Fix firmware LLDP agent related warning
+    - i40e: Fix queue-to-TC mapping on Tx
+    - i40e: Fix log TC creation failure when max num of queues is exceeded
+    - tipc: fix sleeping in tipc accept routine
+    - net: Set true network header for ECN decapsulation
+    - mlx4: Fix missing error code in mlx4_load_one()
+    - net: llc: fix skb_over_panic
+    - net/mlx5: Fix flow table chaining
+    - net/mlx5e: Fix nullptr in mlx5e_hairpin_get_mdev()
+    - sctp: fix return value check in __sctp_rcv_asconf_lookup
+    - tulip: windbond-840: Fix missing pci_disable_device() in probe and remove
+    - sis900: Fix missing pci_disable_device() in probe and remove
+    - can: hi311x: fix a signedness bug in hi3110_cmd()
+    - PCI: mvebu: Setup BAR0 in order to fix MSI
+    - powerpc/pseries: Fix regression while building external modules
+    - i40e: Add additional info to PHY type error
+    - can: j1939: j1939_session_deactivate(): clarify lifetime of session object
+    - Linux 5.4.138
+  * Focal update: v5.4.137 upstream stable release (LP: #1940557)
+    - selftest: fix build error in tools/testing/selftests/vm/userfaultfd.c
+    - tools: Allow proper CC/CXX/... override with LLVM=1 in Makefile.include
+    - KVM: x86: determine if an exception has an error code only when injecting
+      it.
+    - af_unix: fix garbage collect vs MSG_PEEK
+    - workqueue: fix UAF in pwq_unbound_release_workfn()
+    - cgroup1: fix leaked context root causing sporadic NULL deref in LTP
+    - net/802/mrp: fix memleak in mrp_request_join()
+    - net/802/garp: fix memleak in garp_request_join()
+    - net: annotate data race around sk_ll_usec
+    - sctp: move 198 addresses from unusable to private scope
+    - ipv6: allocate enough headroom in ip6_finish_output2()
+    - hfs: add missing clean-up in hfs_fill_super
+    - hfs: fix high memory mapping in hfs_bnode_read
+    - hfs: add lock nesting notation to hfs_find_init
+    - firmware: arm_scmi: Fix possible scmi_linux_errmap buffer overflow
+    - firmware: arm_scmi: Fix range check for the maximum number of pending
+      messages
+    - cifs: fix the out of range assignment to bit fields in
+      parse_server_interfaces
+    - iomap: remove the length variable in iomap_seek_data
+    - iomap: remove the length variable in iomap_seek_hole
+    - ARM: dts: versatile: Fix up interrupt controller node names
+    - ipv6: ip6_finish_output2: set sk into newly allocated nskb
+    - Linux 5.4.137
+  * Focal update: v5.4.136 upstream stable release (LP: #1939899)
+    - igc: Fix use-after-free error during reset
+    - igb: Fix use-after-free error during reset
+    - igc: change default return of igc_read_phy_reg()
+    - ixgbe: Fix an error handling path in 'ixgbe_probe()'
+    - igc: Prefer to use the pci_release_mem_regions method
+    - igc: Fix an error handling path in 'igc_probe()'
+    - igb: Fix an error handling path in 'igb_probe()'
+    - fm10k: Fix an error handling path in 'fm10k_probe()'
+    - e1000e: Fix an error handling path in 'e1000_probe()'
+    - iavf: Fix an error handling path in 'iavf_probe()'
+    - igb: Check if num of q_vectors is smaller than max before array access
+    - igb: Fix position of assignment to *ring
+    - gve: Fix an error handling path in 'gve_probe()'
+    - ipv6: fix 'disable_policy' for fwd packets
+    - selftests: icmp_redirect: remove from checking for IPv6 route get
+    - selftests: icmp_redirect: IPv6 PMTU info should be cleared after redirect
+    - pwm: sprd: Ensure configuring period and duty_cycle isn't wrongly skipped
+    - cxgb4: fix IRQ free race during driver unload
+    - nvme-pci: do not call nvme_dev_remove_admin from nvme_remove
+    - perf probe: Fix dso->nsinfo refcounting
+    - perf env: Fix sibling_dies memory leak
+    - perf test session_topology: Delete session->evlist
+    - perf test event_update: Fix memory leak of evlist
+    - perf dso: Fix memory leak in dso__new_map()
+    - perf script: Fix memory 'threads' and 'cpus' leaks on exit
+    - perf lzma: Close lzma stream on exit
+    - perf probe-file: Delete namelist in del_events() on the error path
+    - perf data: Close all files in close_dir()
+    - spi: imx: add a check for speed_hz before calculating the clock
+    - spi: stm32: Use dma_request_chan() instead dma_request_slave_channel()
+    - spi: stm32: fixes pm_runtime calls in probe/remove
+    - regulator: hi6421: Use correct variable type for regmap api val argument
+    - regulator: hi6421: Fix getting wrong drvdata
+    - spi: mediatek: fix fifo rx mode
+    - ASoC: rt5631: Fix regcache sync errors on resume
+    - liquidio: Fix unintentional sign extension issue on left shift of u16
+    - s390/bpf: Perform r1 range checking before accessing jit->seen_reg[r1]
+    - bpf, sockmap, tcp: sk_prot needs inuse_idx set for proc stats
+    - bpftool: Check malloc return value in mount_bpffs_for_pin
+    - net: fix uninit-value in caif_seqpkt_sendmsg
+    - efi/tpm: Differentiate missing and invalid final event log table.
+    - net: decnet: Fix sleeping inside in af_decnet
+    - KVM: PPC: Book3S: Fix CONFIG_TRANSACTIONAL_MEM=n crash
+    - KVM: PPC: Fix kvm_arch_vcpu_ioctl vcpu_load leak
+    - net: sched: fix memory leak in tcindex_partial_destroy_work
+    - netrom: Decrease sock refcount when sock timers expire
+    - scsi: iscsi: Fix iface sysfs attr detection
+    - scsi: target: Fix protect handling in WRITE SAME(32)
+    - spi: cadence: Correct initialisation of runtime PM again
+    - bnxt_en: Improve bnxt_ulp_stop()/bnxt_ulp_start() call sequence.
+    - bnxt_en: Refresh RoCE capabilities in bnxt_ulp_probe()
+    - bnxt_en: Add missing check for BNXT_STATE_ABORT_ERR in bnxt_fw_rset_task()
+    - bnxt_en: Check abort error state in bnxt_half_open_nic()
+    - net: hisilicon: rename CACHE_LINE_MASK to avoid redefinition
+    - net/tcp_fastopen: fix data races around tfo_active_disable_stamp
+    - net: hns3: fix rx VLAN offload state inconsistent issue
+    - net/sched: act_skbmod: Skip non-Ethernet packets
+    - ipv6: fix another slab-out-of-bounds in fib6_nh_flush_exceptions
+    - nvme-pci: don't WARN_ON in nvme_reset_work if ctrl.state is not RESETTING
+    - Revert "USB: quirks: ignore remote wake-up on Fibocom L850-GL LTE modem"
+    - afs: Fix tracepoint string placement with built-in AFS
+    - r8169: Avoid duplicate sysfs entry creation error
+    - nvme: set the PRACT bit when using Write Zeroes with T10 PI
+    - sctp: update active_key for asoc when old key is being replaced
+    - net: sched: cls_api: Fix the the wrong parameter
+    - drm/panel: raspberrypi-touchscreen: Prevent double-free
+    - proc: Avoid mixing integer types in mem_rw()
+    - s390/ftrace: fix ftrace_update_ftrace_func implementation
+    - s390/boot: fix use of expolines in the DMA code
+    - ALSA: usb-audio: Add missing proc text entry for BESPOKEN type
+    - ALSA: usb-audio: Add registration quirk for JBL Quantum headsets
+    - ALSA: sb: Fix potential ABBA deadlock in CSP driver
+    - ALSA: hdmi: Expose all pins on MSI MS-7C94 board
+    - xhci: Fix lost USB 2 remote wake
+    - KVM: PPC: Book3S: Fix H_RTAS rets buffer overflow
+    - KVM: PPC: Book3S HV Nested: Sanitise H_ENTER_NESTED TM state
+    - usb: hub: Disable USB 3 device initiated lpm if exit latency is too high
+    - usb: hub: Fix link power management max exit latency (MEL) calculations
+    - USB: usb-storage: Add LaCie Rugged USB3-FW to IGNORE_UAS
+    - usb: max-3421: Prevent corruption of freed memory
+    - usb: renesas_usbhs: Fix superfluous irqs happen after usb_pkt_pop()
+    - USB: serial: option: add support for u-blox LARA-R6 family
+    - USB: serial: cp210x: fix comments for GE CS1000
+    - USB: serial: cp210x: add ID for CEL EM3588 USB ZigBee stick
+    - usb: dwc2: gadget: Fix sending zero length packet in DDMA mode.
+    - firmware/efi: Tell memblock about EFI iomem reservations
+    - tracing/histogram: Rename "cpu" to "common_cpu"
+    - tracing: Fix bug in rb_per_cpu_empty() that might cause deadloop.
+    - btrfs: check for missing device in btrfs_trim_fs
+    - media: ngene: Fix out-of-bounds bug in ngene_command_config_free_buf()
+    - ixgbe: Fix packet corruption due to missing DMA sync
+    - selftest: use mmap instead of posix_memalign to allocate memory
+    - userfaultfd: do not untag user pointers
+    - hugetlbfs: fix mount mode command line processing
+    - rbd: don't hold lock_rwsem while running_list is being drained
+    - rbd: always kick acquire on "acquired" and "released" notifications
+    - nds32: fix up stack guard gap
+    - drm: Return -ENOTTY for non-drm ioctls
+    - net: dsa: mv88e6xxx: use correct .stats_set_histogram() on Topaz
+    - net: bcmgenet: ensure EXT_ENERGY_DET_MASK is clear
+    - iio: accel: bma180: Use explicit member assignment
+    - iio: accel: bma180: Fix BMA25x bandwidth register values
+    - btrfs: compression: don't try to compress if we don't have enough pages
+    - PCI: Mark AMD Navi14 GPU ATS as broken
+    - perf inject: Close inject.output on exit
+    - xhci: add xhci_get_virt_ep() helper
+    - Linux 5.4.136
+  * Focal update: v5.4.135 upstream stable release (LP: #1939442)
+    - ARM: dts: gemini: rename mdio to the right name
+    - ARM: dts: gemini: add device_type on pci
+    - ARM: dts: rockchip: fix pinctrl sleep nodename for rk3036-kylin and rk3288
+    - arm64: dts: rockchip: fix pinctrl sleep nodename for rk3399.dtsi
+    - ARM: dts: rockchip: Fix the timer clocks order
+    - ARM: dts: rockchip: Fix IOMMU nodes properties on rk322x
+    - ARM: dts: rockchip: Fix power-controller node names for rk3066a
+    - ARM: dts: rockchip: Fix power-controller node names for rk3188
+    - ARM: dts: rockchip: Fix power-controller node names for rk3288
+    - arm64: dts: rockchip: Fix power-controller node names for px30
+    - arm64: dts: rockchip: Fix power-controller node names for rk3328
+    - reset: ti-syscon: fix to_ti_syscon_reset_data macro
+    - ARM: brcmstb: dts: fix NAND nodes names
+    - ARM: Cygnus: dts: fix NAND nodes names
+    - ARM: NSP: dts: fix NAND nodes names
+    - ARM: dts: BCM63xx: Fix NAND nodes names
+    - ARM: dts: Hurricane 2: Fix NAND nodes names
+    - ARM: dts: imx6: phyFLEX: Fix UART hardware flow control
+    - ARM: imx: pm-imx5: Fix references to imx5_cpu_suspend_info
+    - rtc: mxc_v2: add missing MODULE_DEVICE_TABLE
+    - kbuild: sink stdout from cmd for silent build
+    - ARM: dts: am57xx-cl-som-am57x: fix ti,no-reset-on-init flag for gpios
+    - ARM: dts: am437x-gp-evm: fix ti,no-reset-on-init flag for gpios
+    - ARM: dts: stm32: fix gpio-keys node on STM32 MCU boards
+    - ARM: dts: stm32: fix RCC node name on stm32f429 MCU
+    - ARM: dts: stm32: fix timer nodes on STM32 MCU to prevent warnings
+    - arm64: dts: juno: Update SCPI nodes as per the YAML schema
+    - ARM: dts: rockchip: fix supply properties in io-domains nodes
+    - ARM: dts: stm32: fix i2c node name on stm32f746 to prevent warnings
+    - ARM: dts: stm32: move stmmac axi config in ethernet node on stm32mp15
+    - soc/tegra: fuse: Fix Tegra234-only builds
+    - firmware: tegra: bpmp: Fix Tegra234-only builds
+    - arm64: dts: ls208xa: remove bus-num from dspi node
+    - arm64: dts: imx8mq: assign PCIe clocks
+    - thermal/core: Correct function name thermal_zone_device_unregister()
+    - kbuild: mkcompile_h: consider timestamp if KBUILD_BUILD_TIMESTAMP is set
+    - rtc: max77686: Do not enforce (incorrect) interrupt trigger type
+    - scsi: aic7xxx: Fix unintentional sign extension issue on left shift of u8
+    - scsi: libsas: Add LUN number check in .slave_alloc callback
+    - scsi: libfc: Fix array index out of bound exception
+    - scsi: qedf: Add check to synchronize abort and flush
+    - sched/fair: Fix CFS bandwidth hrtimer expiry type
+    - s390: introduce proper type handling call_on_stack() macro
+    - cifs: prevent NULL deref in cifs_compose_mount_options()
+    - arm64: dts: armada-3720-turris-mox: add firmware node
+    - firmware: turris-mox-rwtm: add marvell,armada-3700-rwtm-firmware compatible
+      string
+    - arm64: dts: marvell: armada-37xx: move firmware node to generic dtsi file
+    - f2fs: Show casefolding support only when supported
+    - usb: cdns3: Enable TDL_CHK only for OUT ep
+    - Revert "UBUNTU: SAUCE: Revert "mm: memcg/slab: fix memory leak at non-root
+      kmem_cache destroy""
+    - mm: slab: fix kmem_cache_create failed when sysfs node not destroyed
+    - dm writecache: return the exact table values that were set
+    - net: dsa: mv88e6xxx: enable .port_set_policy() on Topaz
+    - net: dsa: mv88e6xxx: enable .rmu_disable() on Topaz
+    - net: ipv6: fix return value of ip6_skb_dst_mtu
+    - netfilter: ctnetlink: suspicious RCU usage in ctnetlink_dump_helpinfo
+    - net/sched: act_ct: fix err check for nf_conntrack_confirm
+    - net: bridge: sync fdb to new unicast-filtering ports
+    - net: bcmgenet: Ensure all TX/RX queues DMAs are disabled
+    - net: ip_tunnel: fix mtu calculation for ETHER tunnel devices
+    - net: moxa: fix UAF in moxart_mac_probe
+    - net: qcom/emac: fix UAF in emac_remove
+    - net: ti: fix UAF in tlan_remove_one
+    - net: send SYNACK packet with accepted fwmark
+    - net: validate lwtstate->data before returning from skb_tunnel_info()
+    - net: fddi: fix UAF in fza_probe
+    - dma-buf/sync_file: Don't leak fences on merge failure
+    - tcp: annotate data races around tp->mtu_info
+    - ipv6: tcp: drop silly ICMPv6 packet too big messages
+    - bpftool: Properly close va_list 'ap' by va_end() on error
+    - perf test bpf: Free obj_buf
+    - udp: annotate data races around unix_sk(sk)->gso_size
+    - Linux 5.4.135
+  * Focal update: v5.4.134 upstream stable release (LP: #1939440)
+    - KVM: mmio: Fix use-after-free Read in kvm_vm_ioctl_unregister_coalesced_mmio
+    - KVM: x86: Use guest MAXPHYADDR from CPUID.0x8000_0008 iff TDP is enabled
+    - KVM: X86: Disable hardware breakpoints unconditionally before kvm_x86->run()
+    - scsi: core: Fix bad pointer dereference when ehandler kthread is invalid
+    - tracing: Do not reference char * as a string in histograms
+    - cgroup: verify that source is a string
+    - fbmem: Do not delete the mode that is still in use
+    - net: moxa: Use devm_platform_get_and_ioremap_resource()
+    - dmaengine: fsl-qdma: check dma_set_mask return value
+    - srcu: Fix broken node geometry after early ssp init
+    - tty: serial: fsl_lpuart: fix the potential risk of division or modulo by
+      zero
+    - misc/libmasm/module: Fix two use after free in ibmasm_init_one
+    - misc: alcor_pci: fix null-ptr-deref when there is no PCI bridge
+    - iio: gyro: fxa21002c: Balance runtime pm + use pm_runtime_resume_and_get().
+    - iio: magn: bmc150: Balance runtime pm + use pm_runtime_resume_and_get()
+    - ALSA: usx2y: Don't call free_pages_exact() with NULL address
+    - Revert "ALSA: bebob/oxfw: fix Kconfig entry for Mackie d.2 Pro"
+    - w1: ds2438: fixing bug that would always get page0
+    - scsi: hisi_sas: Propagate errors in interrupt_init_v1_hw()
+    - scsi: lpfc: Fix "Unexpected timeout" error in direct attach topology
+    - scsi: lpfc: Fix crash when lpfc_sli4_hba_setup() fails to initialize the
+      SGLs
+    - scsi: core: Cap scsi_host cmd_per_lun at can_queue
+    - ALSA: ac97: fix PM reference leak in ac97_bus_remove()
+    - tty: serial: 8250: serial_cs: Fix a memory leak in error handling path
+    - scsi: scsi_dh_alua: Check for negative result value
+    - fs/jfs: Fix missing error code in lmLogInit()
+    - scsi: megaraid_sas: Fix resource leak in case of probe failure
+    - scsi: megaraid_sas: Early detection of VD deletion through RaidMap update
+    - scsi: megaraid_sas: Handle missing interrupts while re-enabling IRQs
+    - scsi: iscsi: Add iscsi_cls_conn refcount helpers
+    - scsi: iscsi: Fix conn use after free during resets
+    - scsi: iscsi: Fix shost->max_id use
+    - scsi: qedi: Fix null ref during abort handling
+    - mfd: da9052/stmpe: Add and modify MODULE_DEVICE_TABLE
+    - mfd: cpcap: Fix cpcap dmamask not set warnings
+    - ASoC: img: Fix PM reference leak in img_i2s_in_probe()
+    - serial: tty: uartlite: fix console setup
+    - s390/sclp_vt220: fix console name to match device
+    - ALSA: sb: Fix potential double-free of CSP mixer elements
+    - powerpc/ps3: Add dma_mask to ps3_dma_region
+    - iommu/arm-smmu: Fix arm_smmu_device refcount leak when arm_smmu_rpm_get
+      fails
+    - iommu/arm-smmu: Fix arm_smmu_device refcount leak in address translation
+    - gpio: zynq: Check return value of pm_runtime_get_sync
+    - ALSA: ppc: fix error return code in snd_pmac_probe()
+    - selftests/powerpc: Fix "no_handler" EBB selftest
+    - gpio: pca953x: Add support for the On Semi pca9655
+    - ASoC: soc-core: Fix the error return code in
+      snd_soc_of_parse_audio_routing()
+    - s390/processor: always inline stap() and __load_psw_mask()
+    - s390/ipl_parm: fix program check new psw handling
+    - s390/mem_detect: fix diag260() program check new psw handling
+    - s390/mem_detect: fix tprot() program check new psw handling
+    - Input: hideep - fix the uninitialized use in hideep_nvm_unlock()
+    - ALSA: bebob: add support for ToneWeal FW66
+    - ALSA: usb-audio: scarlett2: Fix 18i8 Gen 2 PCM Input count
+    - ALSA: usb-audio: scarlett2: Fix data_mutex lock
+    - ALSA: usb-audio: scarlett2: Fix scarlett2_*_ctl_put() return values
+    - usb: gadget: f_hid: fix endianness issue with descriptors
+    - usb: gadget: hid: fix error return code in hid_bind()
+    - powerpc/boot: Fixup device-tree on little endian
+    - ASoC: Intel: kbl_da7219_max98357a: shrink platform_id below 20 characters
+    - backlight: lm3630a: Fix return code of .update_status() callback
+    - ALSA: hda: Add IRQ check for platform_get_irq()
+    - ALSA: usb-audio: scarlett2: Fix 6i6 Gen 2 line out descriptions
+    - staging: rtl8723bs: fix macro value for 2.4Ghz only device
+    - intel_th: Wait until port is in reset before programming it
+    - i2c: core: Disable client irq on reboot/shutdown
+    - power: supply: sc27xx: Add missing MODULE_DEVICE_TABLE
+    - power: supply: sc2731_charger: Add missing MODULE_DEVICE_TABLE
+    - pwm: spear: Don't modify HW state in .remove callback
+    - power: supply: ab8500: Avoid NULL pointers
+    - power: supply: max17042: Do not enforce (incorrect) interrupt trigger type
+    - power: reset: gpio-poweroff: add missing MODULE_DEVICE_TABLE
+    - ARM: 9087/1: kprobes: test-thumb: fix for LLVM_IAS=1
+    - PCI/P2PDMA: Avoid pci_get_slot(), which may sleep
+    - watchdog: Fix possible use-after-free in wdt_startup()
+    - watchdog: sc520_wdt: Fix possible use-after-free in wdt_turnoff()
+    - watchdog: Fix possible use-after-free by calling del_timer_sync()
+    - watchdog: imx_sc_wdt: fix pretimeout
+    - x86/fpu: Return proper error codes from user access functions
+    - PCI: tegra: Add missing MODULE_DEVICE_TABLE
+    - orangefs: fix orangefs df output.
+    - ceph: remove bogus checks and WARN_ONs from ceph_set_page_dirty
+    - NFS: nfs_find_open_context() may only select open files
+    - power: supply: charger-manager: add missing MODULE_DEVICE_TABLE
+    - power: supply: ab8500: add missing MODULE_DEVICE_TABLE
+    - pwm: img: Fix PM reference leak in img_pwm_enable()
+    - pwm: tegra: Don't modify HW state in .remove callback
+    - ACPI: AMBA: Fix resource name in /proc/iomem
+    - ACPI: video: Add quirk for the Dell Vostro 3350
+    - virtio-blk: Fix memory leak among suspend/resume procedure
+    - virtio_net: Fix error handling in virtnet_restore()
+    - virtio_console: Assure used length from device is limited
+    - x86/signal: Detect and prevent an alternate signal stack overflow
+    - f2fs: add MODULE_SOFTDEP to ensure crc32 is included in the initramfs
+    - PCI/sysfs: Fix dsm_label_utf16s_to_utf8s() buffer overrun
+    - power: supply: rt5033_battery: Fix device tree enumeration
+    - NFSv4: Initialise connection to the server in nfs4_alloc_client()
+    - um: fix error return code in slip_open()
+    - um: fix error return code in winch_tramp()
+    - watchdog: aspeed: fix hardware timeout calculation
+    - nfs: fix acl memory leak of posix_acl_create()
+    - ubifs: Set/Clear I_LINKABLE under i_lock for whiteout inode
+    - PCI: iproc: Fix multi-MSI base vector number allocation
+    - PCI: iproc: Support multi-MSI only on uniprocessor kernel
+    - x86/fpu: Limit xstate copy size in xstateregs_set()
+    - pwm: imx1: Don't disable clocks at device remove time
+    - virtio_net: move tx vq operation under tx queue lock
+    - nvme-tcp: can't set sk_user_data without write_lock
+    - ALSA: isa: Fix error return code in snd_cmi8330_probe()
+    - NFSv4/pNFS: Don't call _nfs4_pnfs_v3_ds_connect multiple times
+    - hexagon: use common DISCARDS macro
+    - ARM: dts: gemini-rut1xx: remove duplicate ethernet node
+    - reset: a10sr: add missing of_match_table reference
+    - ARM: exynos: add missing of_node_put for loop iteration
+    - ARM: dts: exynos: fix PWM LED max brightness on Odroid XU/XU3
+    - ARM: dts: exynos: fix PWM LED max brightness on Odroid HC1
+    - ARM: dts: exynos: fix PWM LED max brightness on Odroid XU4
+    - memory: atmel-ebi: add missing of_node_put for loop iteration
+    - reset: brcmstb: Add missing MODULE_DEVICE_TABLE
+    - memory: pl353: Fix error return code in pl353_smc_probe()
+    - rtc: fix snprintf() checking in is_rtc_hctosys()
+    - arm64: dts: renesas: v3msk: Fix memory size
+    - ARM: dts: r8a7779, marzen: Fix DU clock names
+    - firmware: tegra: Fix error return code in tegra210_bpmp_init()
+    - firmware: arm_scmi: Reset Rx buffer to max size during async commands
+    - ARM: dts: BCM5301X: Fixup SPI binding
+    - reset: bail if try_module_get() fails
+    - memory: fsl_ifc: fix leak of IO mapping on probe failure
+    - memory: fsl_ifc: fix leak of private memory on probe failure
+    - ARM: dts: am335x: align ti,pindir-d0-out-d1-in property with dt-shema
+    - ARM: dts: am437x: align ti,pindir-d0-out-d1-in property with dt-shema
+    - ARM: dts: imx6q-dhcom: Fix ethernet reset time properties
+    - ARM: dts: imx6q-dhcom: Fix ethernet plugin detection problems
+    - ARM: dts: imx6q-dhcom: Add gpios pinctrl for i2c bus recovery
+    - thermal/drivers/rcar_gen3_thermal: Fix coefficient calculations
+    - firmware: turris-mox-rwtm: fix reply status decoding function
+    - firmware: turris-mox-rwtm: report failures better
+    - firmware: turris-mox-rwtm: fail probing when firmware does not support hwrng
+    - scsi: be2iscsi: Fix an error handling path in beiscsi_dev_probe()
+    - mips: always link byteswap helpers into decompressor
+    - mips: disable branch profiling in boot/decompress.o
+    - MIPS: vdso: Invalid GIC access through VDSO
+    - scsi: scsi_dh_alua: Fix signedness bug in alua_rtpg()
+    - misc: alcor_pci: fix inverted branch condition
+    - Linux 5.4.134
+
+  [ Ubuntu: 5.4.0-86.97 ]
+
+  * s390x BPF JIT vulnerabilities (LP: #1943960)
+    - SAUCE: s390/bpf: Fix 64-bit subtraction of the -0x80000000 constant
+    - SAUCE: s390/bpf: Fix optimizing out zero-extensions
+
+ -- Hsuan-Yu Lin <shane.lin@canonical.com>  Wed, 03 Nov 2021 16:44:30 +0800
+
+linux-xilinx-zynqmp (5.4.0-1016.19) focal; urgency=medium
+
+  * Miscellaneous Ubuntu changes
+    - [Config] Update configs for built-in nfs_layout_flexfiles
+
+  [ Ubuntu: 5.4.0-84.94 ]
+
+  * focal/linux: 5.4.0-84.94 -proposed tracker (LP: #1941767)
+  * Server boot failure after adding checks for ACPI IRQ override (LP: #1941657)
+    - Revert "ACPI: resources: Add checks for ACPI IRQ override"
+
+  [ Ubuntu: 5.4.0-83.93 ]
+
+  * focal/linux: 5.4.0-83.93 -proposed tracker (LP: #1940159)
+  * fails to launch linux L2 guests on AMD (LP: #1940134) // CVE-2021-3653
+    - KVM: nSVM: avoid picking up unsupported bits from L2 in int_ctl
+      (CVE-2021-3653)
+  * fails to launch linux L2 guests on AMD (LP: #1940134)
+    - SAUCE: Revert "UBUNTU: SAUCE: KVM: nSVM: avoid picking up unsupported bits
+      from L2 in int_ctl"
+
+  [ Ubuntu: 5.4.0-82.92 ]
+
+  * focal/linux: 5.4.0-82.92 -proposed tracker (LP: #1939799)
+  * Packaging resync (LP: #1786013)
+    - debian/dkms-versions -- update from kernel-versions (main/2021.08.16)
+  * CVE-2021-3656
+    - SAUCE: KVM: nSVM: always intercept VMLOAD/VMSAVE when nested
+  * CVE-2021-3653
+    - SAUCE: KVM: nSVM: avoid picking up unsupported bits from L2 in int_ctl
+  * [regression] USB device is not detected during boot (LP: #1939638)
+    - SAUCE: Revert "usb: core: reduce power-on-good delay time of root hub"
+  * dev_forward_skb: do not scrub skb mark within the same name space
+    (LP: #1935040)
+    - dev_forward_skb: do not scrub skb mark within the same name space
+  * XPS 9510 (TGL) Screen Brightness could not be changed (LP: #1933566)
+    - SAUCE: drm/i915: Force DPCD backlight mode for Dell XPS 9510(TGL)
+  * Acer Aspire 5 sound driver issues (LP: #1930188)
+    - ALSA: hda/realtek: headphone and mic don't work on an Acer laptop
+  * Sony Dualshock 4 usb dongle crashes the whole system (LP: #1935846)
+    - HID: sony: Workaround for DS4 dongle hotplug kernel crash.
+  * [21.10 FEAT] KVM: Provide a secure guest indication (LP: #1933173)
+    - s390/uv: add prot virt guest/host indication files
+    - s390/uv: fix prot virt host indication compilation
+  * Skip rtcpie test in kselftests/timers if the default RTC device does not
+    exist (LP: #1937991)
+    - selftests: timers: rtcpie: skip test if default RTC device does not exist
+  * Focal update: v5.4.133 upstream stable release (LP: #1938713)
+    - drm/mxsfb: Don't select DRM_KMS_FB_HELPER
+    - drm/zte: Don't select DRM_KMS_FB_HELPER
+    - drm/amd/amdgpu/sriov disable all ip hw status by default
+    - drm/vc4: fix argument ordering in vc4_crtc_get_margins()
+    - net: pch_gbe: Use proper accessors to BE data in pch_ptp_match()
+    - drm/amd/display: fix use_max_lb flag for 420 pixel formats
+    - hugetlb: clear huge pte during flush function on mips platform
+    - atm: iphase: fix possible use-after-free in ia_module_exit()
+    - mISDN: fix possible use-after-free in HFC_cleanup()
+    - atm: nicstar: Fix possible use-after-free in nicstar_cleanup()
+    - net: Treat __napi_schedule_irqoff() as __napi_schedule() on PREEMPT_RT
+    - drm/mediatek: Fix PM reference leak in mtk_crtc_ddp_hw_init()
+    - reiserfs: add check for invalid 1st journal block
+    - drm/virtio: Fix double free on probe failure
+    - drm/sched: Avoid data corruptions
+    - udf: Fix NULL pointer dereference in udf_symlink function
+    - e100: handle eeprom as little endian
+    - igb: handle vlan types with checker enabled
+    - drm/bridge: cdns: Fix PM reference leak in cdns_dsi_transfer()
+    - clk: renesas: r8a77995: Add ZA2 clock
+    - clk: tegra: Ensure that PLLU configuration is applied properly
+    - ipv6: use prandom_u32() for ID generation
+    - RDMA/cxgb4: Fix missing error code in create_qp()
+    - dm space maps: don't reset space map allocation cursor when committing
+    - pinctrl: mcp23s08: fix race condition in irq handler
+    - ice: set the value of global config lock timeout longer
+    - virtio_net: Remove BUG() to avoid machine dead
+    - net: bcmgenet: check return value after calling platform_get_resource()
+    - net: mvpp2: check return value after calling platform_get_resource()
+    - net: micrel: check return value after calling platform_get_resource()
+    - drm/amd/display: Update scaling settings on modeset
+    - drm/amd/display: Release MST resources on switch from MST to SST
+    - drm/amd/display: Set DISPCLK_MAX_ERRDET_CYCLES to 7
+    - drm/amdkfd: use allowed domain for vmbo validation
+    - fjes: check return value after calling platform_get_resource()
+    - selinux: use __GFP_NOWARN with GFP_NOWAIT in the AVC
+    - r8169: avoid link-up interrupt issue on RTL8106e if user enables ASPM
+    - drm/amd/display: Verify Gamma & Degamma LUT sizes in amdgpu_dm_atomic_check
+    - xfrm: Fix error reporting in xfrm_state_construct.
+    - wlcore/wl12xx: Fix wl12xx get_mac error if device is in ELP
+    - wl1251: Fix possible buffer overflow in wl1251_cmd_scan
+    - cw1200: add missing MODULE_DEVICE_TABLE
+    - bpf: Fix up register-based shifts in interpreter to silence KUBSAN
+    - mt76: mt7615: fix fixed-rate tx status reporting
+    - net: fix mistake path for netdev_features_strings
+    - net: sched: fix error return code in tcf_del_walker()
+    - drm/amdkfd: Walk through list with dqm lock hold
+    - rtl8xxxu: Fix device info for RTL8192EU devices
+    - atm: nicstar: use 'dma_free_coherent' instead of 'kfree'
+    - atm: nicstar: register the interrupt handler in the right place
+    - vsock: notify server to shutdown when client has pending signal
+    - RDMA/rxe: Don't overwrite errno from ib_umem_get()
+    - iwlwifi: mvm: don't change band on bound PHY contexts
+    - iwlwifi: pcie: free IML DMA memory allocation
+    - iwlwifi: pcie: fix context info freeing
+    - sfc: avoid double pci_remove of VFs
+    - sfc: error code if SRIOV cannot be disabled
+    - wireless: wext-spy: Fix out-of-bounds warning
+    - media, bpf: Do not copy more entries than user space requested
+    - net: ip: avoid OOM kills with large UDP sends over loopback
+    - RDMA/cma: Fix rdma_resolve_route() memory leak
+    - Bluetooth: btusb: Fixed too many in-token issue for Mediatek Chip.
+    - Bluetooth: Fix the HCI to MGMT status conversion table
+    - Bluetooth: Shutdown controller after workqueues are flushed or cancelled
+    - Bluetooth: btusb: fix bt fiwmare downloading failure issue for qca btsoc.
+    - sctp: validate from_addr_param return
+    - sctp: add size validation when walking chunks
+    - MIPS: loongsoon64: Reserve memory below starting pfn to prevent Oops
+    - MIPS: set mips32r5 for virt extensions
+    - fscrypt: don't ignore minor_hash when hash is 0
+    - crypto: ccp - Annotate SEV Firmware file names
+    - perf bench: Fix 2 memory sanitizer warnings
+    - powerpc/mm: Fix lockup on kernel exec fault
+    - powerpc/barrier: Avoid collision with clang's __lwsync macro
+    - drm/amdgpu: Update NV SIMD-per-CU to 2
+    - drm/radeon: Add the missed drm_gem_object_put() in
+      radeon_user_framebuffer_create()
+    - drm/rockchip: dsi: remove extra component_del() call
+    - drm/amd/display: fix incorrrect valid irq check
+    - pinctrl/amd: Add device HID for new AMD GPIO controller
+    - drm/tegra: Don't set allow_fb_modifiers explicitly
+    - drm/msm/mdp4: Fix modifier support enabling
+    - drm/arm/malidp: Always list modifiers
+    - mmc: sdhci: Fix warning message when accessing RPMB in HS400 mode
+    - mmc: core: clear flags before allowing to retune
+    - mmc: core: Allow UHS-I voltage switch for SDSC cards if supported
+    - ata: ahci_sunxi: Disable DIPM
+    - cpu/hotplug: Cure the cpusets trainwreck
+    - clocksource/arm_arch_timer: Improve Allwinner A64 timer workaround
+    - fpga: stratix10-soc: Add missing fpga_mgr_free() call
+    - MIPS: fix "mipsel-linux-ld: decompress.c:undefined reference to `memmove'"
+    - ASoC: tegra: Set driver_name=tegra for all machine drivers
+    - qemu_fw_cfg: Make fw_cfg_rev_attr a proper kobj_attribute
+    - ipmi/watchdog: Stop watchdog timer when the current action is 'none'
+    - thermal/drivers/int340x/processor_thermal: Fix tcc setting
+    - ubifs: Fix races between xattr_{set|get} and listxattr operations
+    - power: supply: ab8500: Fix an old bug
+    - nvmem: core: add a missing of_node_put
+    - extcon: intel-mrfld: Sync hardware and software state on init
+    - seq_buf: Fix overflow in seq_buf_putmem_hex()
+    - rq-qos: fix missed wake-ups in rq_qos_throttle try two
+    - tracing: Simplify & fix saved_tgids logic
+    - tracing: Resize tgid_map to pid_max, not PID_MAX_DEFAULT
+    - ipack/carriers/tpci200: Fix a double free in tpci200_pci_probe
+    - coresight: tmc-etf: Fix global-out-of-bounds in tmc_update_etf_buffer()
+    - dm btree remove: assign new_root only when removal succeeds
+    - PCI: Leave Apple Thunderbolt controllers on for s2idle or standby
+    - PCI: aardvark: Fix checking for PIO Non-posted Request
+    - PCI: aardvark: Implement workaround for the readback value of VEND_ID
+    - media: subdev: disallow ioctl for saa6588/davinci
+    - media: dtv5100: fix control-request directions
+    - media: zr364xx: fix memory leak in zr364xx_start_readpipe
+    - media: gspca/sq905: fix control-request direction
+    - media: gspca/sunplus: fix zero-length control requests
+    - pinctrl: mcp23s08: Fix missing unlock on error in mcp23s08_irq()
+    - jfs: fix GPF in diFree
+    - smackfs: restrict bytes count in smk_set_cipso()
+    - Linux 5.4.133
+  * Focal update: v5.4.132 upstream stable release (LP: #1938199)
+    - ALSA: usb-audio: fix rate on Ozone Z90 USB headset
+    - ALSA: usb-audio: Fix OOB access at proc output
+    - ALSA: usb-audio: scarlett2: Fix wrong resume call
+    - ALSA: intel8x0: Fix breakage at ac97 clock measurement
+    - ALSA: hda/realtek: Add another ALC236 variant support
+    - ALSA: hda/realtek: Improve fixup for HP Spectre x360 15-df0xxx
+    - ALSA: hda/realtek: Fix bass speaker DAC mapping for Asus UM431D
+    - ALSA: hda/realtek: Apply LED fixup for HP Dragonfly G1, too
+    - media: dvb-usb: fix wrong definition
+    - Input: usbtouchscreen - fix control-request directions
+    - net: can: ems_usb: fix use-after-free in ems_usb_disconnect()
+    - usb: gadget: eem: fix echo command packet response issue
+    - USB: cdc-acm: blacklist Heimann USB Appset device
+    - usb: dwc3: Fix debugfs creation flow
+    - usb: typec: Add the missed altmode_id_remove() in typec_register_altmode()
+    - xhci: solve a double free problem while doing s4
+    - ntfs: fix validity check for file name attribute
+    - copy_page_to_iter(): fix ITER_DISCARD case
+    - iov_iter_fault_in_readable() should do nothing in xarray case
+    - Input: joydev - prevent use of not validated data in JSIOCSBTNMAP ioctl
+    - arm_pmu: Fix write counter incorrect in ARMv7 big-endian mode
+    - ARM: dts: at91: sama5d4: fix pinctrl muxing
+    - btrfs: send: fix invalid path for unlink operations after parent
+      orphanization
+    - btrfs: clear defrag status of a root if starting transaction fails
+    - ext4: cleanup in-core orphan list if ext4_truncate() failed to get a
+      transaction handle
+    - ext4: fix kernel infoleak via ext4_extent_header
+    - ext4: return error code when ext4_fill_flex_info() fails
+    - ext4: correct the cache_nr in tracepoint ext4_es_shrink_exit
+    - ext4: remove check for zero nr_to_scan in ext4_es_scan()
+    - ext4: fix avefreec in find_group_orlov
+    - ext4: use ext4_grp_locked_error in mb_find_extent
+    - can: gw: synchronize rcu operations before removing gw job entry
+    - can: j1939: j1939_sk_init(): set SOCK_RCU_FREE to call sk_destruct() after
+      RCU is done
+    - can: peak_pciefd: pucan_handle_status(): fix a potential starvation issue in
+      TX path
+    - mac80211: remove iwlwifi specific workaround that broke sta NDP tx
+    - SUNRPC: Fix the batch tasks count wraparound.
+    - SUNRPC: Should wake up the privileged task firstly.
+    - perf/smmuv3: Don't trample existing events with global filter
+    - KVM: PPC: Book3S HV: Workaround high stack usage with clang
+    - s390/cio: dont call css_wait_for_slow_path() inside a lock
+    - rtc: stm32: Fix unbalanced clk_disable_unprepare() on probe error path
+    - iio: light: tcs3472: do not free unallocated IRQ
+    - iio: ltr501: mark register holding upper 8 bits of ALS_DATA{0,1} and PS_DATA
+      as volatile, too
+    - iio: ltr501: ltr559: fix initialization of LTR501_ALS_CONTR
+    - iio: ltr501: ltr501_read_ps(): add missing endianness conversion
+    - serial: mvebu-uart: fix calculation of clock divisor
+    - serial: sh-sci: Stop dmaengine transfer in sci_stop_tx()
+    - serial_cs: Add Option International GSM-Ready 56K/ISDN modem
+    - serial_cs: remove wrong GLOBETROTTER.cis entry
+    - ath9k: Fix kernel NULL pointer dereference during ath_reset_internal()
+    - ssb: sdio: Don't overwrite const buffer if block_write fails
+    - rsi: Assign beacon rate settings to the correct rate_info descriptor field
+    - rsi: fix AP mode with WPA failure due to encrypted EAPOL
+    - tracing/histograms: Fix parsing of "sym-offset" modifier
+    - tracepoint: Add tracepoint_probe_register_may_exist() for BPF tracing
+    - seq_buf: Make trace_seq_putmem_hex() support data longer than 8
+    - powerpc/stacktrace: Fix spurious "stale" traces in raise_backtrace_ipi()
+    - evm: Execute evm_inode_init_security() only when an HMAC key is loaded
+    - evm: Refuse EVM_ALLOW_METADATA_WRITES only if an HMAC key is loaded
+    - fuse: ignore PG_workingset after stealing
+    - fuse: check connected before queueing on fpq->io
+    - fuse: reject internal errno
+    - spi: Make of_register_spi_device also set the fwnode
+    - media: mdk-mdp: fix pm_runtime_get_sync() usage count
+    - media: s5p: fix pm_runtime_get_sync() usage count
+    - media: sh_vou: fix pm_runtime_get_sync() usage count
+    - media: mtk-vcodec: fix PM runtime get logic
+    - media: s5p-jpeg: fix pm_runtime_get_sync() usage count
+    - media: sti/bdisp: fix pm_runtime_get_sync() usage count
+    - media: exynos-gsc: fix pm_runtime_get_sync() usage count
+    - spi: spi-loopback-test: Fix 'tx_buf' might be 'rx_buf'
+    - spi: spi-topcliff-pch: Fix potential double free in
+      pch_spi_process_messages()
+    - spi: omap-100k: Fix the length judgment problem
+    - regulator: uniphier: Add missing MODULE_DEVICE_TABLE
+    - hwrng: exynos - Fix runtime PM imbalance on error
+    - crypto: nx - add missing MODULE_DEVICE_TABLE
+    - media: sti: fix obj-$(config) targets
+    - media: cpia2: fix memory leak in cpia2_usb_probe
+    - media: cobalt: fix race condition in setting HPD
+    - media: pvrusb2: fix warning in pvr2_i2c_core_done
+    - media: imx: imx7_mipi_csis: Fix logging of only error event counters
+    - crypto: qat - check return code of qat_hal_rd_rel_reg()
+    - crypto: qat - remove unused macro in FW loader
+    - sched/fair: Fix ascii art by relpacing tabs
+    - media: em28xx: Fix possible memory leak of em28xx struct
+    - media: v4l2-core: Avoid the dangling pointer in v4l2_fh_release
+    - media: bt8xx: Fix a missing check bug in bt878_probe
+    - media: st-hva: Fix potential NULL pointer dereferences
+    - Makefile: fix GDB warning with CONFIG_RELR
+    - media: dvd_usb: memory leak in cinergyt2_fe_attach
+    - memstick: rtsx_usb_ms: fix UAF
+    - mmc: sdhci-sprd: use sdhci_sprd_writew
+    - mmc: via-sdmmc: add a check against NULL pointer dereference
+    - crypto: shash - avoid comparing pointers to exported functions under CFI
+    - media: dvb_net: avoid speculation from net slot
+    - media: siano: fix device register error path
+    - media: imx-csi: Skip first few frames from a BT.656 source
+    - hwmon: (max31790) Report correct current pwm duty cycles
+    - hwmon: (max31790) Fix pwmX_enable attributes
+    - drivers/perf: fix the missed ida_simple_remove() in ddr_perf_probe()
+    - KVM: PPC: Book3S HV: Fix TLB management on SMT8 POWER9 and POWER10
+      processors
+    - btrfs: fix error handling in __btrfs_update_delayed_inode
+    - btrfs: abort transaction if we fail to update the delayed inode
+    - btrfs: disable build on platforms having page size 256K
+    - locking/lockdep: Fix the dep path printing for backwards BFS
+    - lockding/lockdep: Avoid to find wrong lock dep path in check_irq_usage()
+    - KVM: s390: get rid of register asm usage
+    - regulator: mt6358: Fix vdram2 .vsel_mask
+    - regulator: da9052: Ensure enough delay time for .set_voltage_time_sel
+    - media: Fix Media Controller API config checks
+    - HID: do not use down_interruptible() when unbinding devices
+    - EDAC/ti: Add missing MODULE_DEVICE_TABLE
+    - ACPI: processor idle: Fix up C-state latency if not ordered
+    - hv_utils: Fix passing zero to 'PTR_ERR' warning
+    - lib: vsprintf: Fix handling of number field widths in vsscanf
+    - ACPI: EC: Make more Asus laptops use ECDT _GPE
+    - block_dump: remove block_dump feature in mark_inode_dirty()
+    - fs: dlm: cancel work sync othercon
+    - random32: Fix implicit truncation warning in prandom_seed_state()
+    - fs: dlm: fix memory leak when fenced
+    - ACPICA: Fix memory leak caused by _CID repair function
+    - ACPI: bus: Call kobject_put() in acpi_init() error path
+    - block: fix race between adding/removing rq qos and normal IO
+    - platform/x86: toshiba_acpi: Fix missing error code in
+      toshiba_acpi_setup_keyboard()
+    - nvmet-fc: do not check for invalid target port in nvmet_fc_handle_fcp_rqst()
+    - EDAC/Intel: Do not load EDAC driver when running as a guest
+    - PCI: hv: Add check for hyperv_initialized in init_hv_pci_drv()
+    - clocksource: Retry clock read if long delays detected
+    - ACPI: tables: Add custom DSDT file as makefile prerequisite
+    - HID: wacom: Correct base usage for capacitive ExpressKey status bits
+    - cifs: fix missing spinlock around update to ses->status
+    - block: fix discard request merge
+    - kthread_worker: fix return value when kthread_mod_delayed_work() races with
+      kthread_cancel_delayed_work_sync()
+    - ia64: mca_drv: fix incorrect array size calculation
+    - writeback, cgroup: increment isw_nr_in_flight before grabbing an inode
+    - media: s5p_cec: decrement usage count if disabled
+    - crypto: ixp4xx - dma_unmap the correct address
+    - crypto: ux500 - Fix error return code in hash_hw_final()
+    - sata_highbank: fix deferred probing
+    - pata_rb532_cf: fix deferred probing
+    - media: I2C: change 'RST' to "RSET" to fix multiple build errors
+    - sched/uclamp: Fix wrong implementation of cpu.uclamp.min
+    - sched/uclamp: Fix locking around cpu_util_update_eff()
+    - kbuild: run the checker after the compiler
+    - kbuild: Fix objtool dependency for 'OBJECT_FILES_NON_STANDARD_<obj> := n'
+    - pata_octeon_cf: avoid WARN_ON() in ata_host_activate()
+    - evm: fix writing <securityfs>/evm overflow
+    - crypto: ccp - Fix a resource leak in an error handling path
+    - media: rc: i2c: Fix an error message
+    - pata_ep93xx: fix deferred probing
+    - media: exynos4-is: Fix a use after free in isp_video_release
+    - media: au0828: fix a NULL vs IS_ERR() check
+    - media: tc358743: Fix error return code in tc358743_probe_of()
+    - media: gspca/gl860: fix zero-length control requests
+    - m68k: atari: Fix ATARI_KBD_CORE kconfig unmet dependency warning
+    - media: siano: Fix out-of-bounds warnings in smscore_load_firmware_family2()
+    - crypto: nitrox - fix unchecked variable in nitrox_register_interrupts
+    - crypto: omap-sham - Fix PM reference leak in omap sham ops
+    - mmc: usdhi6rol0: fix error return code in usdhi6_probe()
+    - arm64: consistently use reserved_pg_dir
+    - arm64/mm: Fix ttbr0 values stored in struct thread_info for software-pan
+    - media: s5p-g2d: Fix a memory leak on ctx->fh.m2m_ctx
+    - hwmon: (max31722) Remove non-standard ACPI device IDs
+    - hwmon: (max31790) Fix fan speed reporting for fan7..12
+    - KVM: nVMX: Ensure 64-bit shift when checking VMFUNC bitmap
+    - regulator: hi655x: Fix pass wrong pointer to config.driver_data
+    - btrfs: clear log tree recovering status if starting transaction fails
+    - sched/rt: Fix RT utilization tracking during policy change
+    - sched/rt: Fix Deadline utilization tracking during policy change
+    - sched/uclamp: Fix uclamp_tg_restrict()
+    - spi: spi-sun6i: Fix chipselect/clock bug
+    - crypto: nx - Fix RCU warning in nx842_OF_upd_status
+    - ACPI: sysfs: Fix a buffer overrun problem with description_show()
+    - extcon: extcon-max8997: Fix IRQ freeing at error path
+    - blk-wbt: introduce a new disable state to prevent false positive by
+      rwb_enabled()
+    - blk-wbt: make sure throttle is enabled properly
+    - ACPI: Use DEVICE_ATTR_<RW|RO|WO> macros
+    - ACPI: bgrt: Fix CFI violation
+    - cpufreq: Make cpufreq_online() call driver->offline() on errors
+    - ocfs2: fix snprintf() checking
+    - dax: fix ENOMEM handling in grab_mapping_entry()
+    - xfrm: xfrm_state_mtu should return at least 1280 for ipv6
+    - video: fbdev: imxfb: Fix an error message
+    - net: mvpp2: Put fwnode in error case during ->probe()
+    - net: pch_gbe: Propagate error from devm_gpio_request_one()
+    - pinctrl: renesas: r8a7796: Add missing bias for PRESET# pin
+    - pinctrl: renesas: r8a77990: JTAG pins do not have pull-down capabilities
+    - clk: meson: g12a: fix gp0 and hifi ranges
+    - net: ftgmac100: add missing error return code in ftgmac100_probe()
+    - drm/rockchip: cdn-dp-core: add missing clk_disable_unprepare() on error in
+      cdn_dp_grf_write()
+    - drm/rockchip: dsi: move all lane config except LCDC mux to bind()
+    - ehea: fix error return code in ehea_restart_qps()
+    - net/sched: act_vlan: Fix modify to allow 0
+    - RDMA/core: Sanitize WQ state received from the userspace
+    - RDMA/rxe: Fix failure during driver load
+    - drm: qxl: ensure surf.data is ininitialized
+    - tools/bpftool: Fix error return code in do_batch()
+    - ath10k: go to path err_unsupported when chip id is not supported
+    - ath10k: add missing error return code in ath10k_pci_probe()
+    - wireless: carl9170: fix LEDS build errors & warnings
+    - ieee802154: hwsim: Fix possible memory leak in hwsim_subscribe_all_others
+    - wcn36xx: Move hal_buf allocation to devm_kmalloc in probe
+    - ssb: Fix error return code in ssb_bus_scan()
+    - brcmfmac: fix setting of station info chains bitmask
+    - brcmfmac: correctly report average RSSI in station info
+    - brcmsmac: mac80211_if: Fix a resource leak in an error handling path
+    - ath10k: Fix an error code in ath10k_add_interface()
+    - netlabel: Fix memory leak in netlbl_mgmt_add_common
+    - RDMA/mlx5: Don't add slave port to unaffiliated list
+    - netfilter: nft_exthdr: check for IPv6 packet before further processing
+    - netfilter: nft_osf: check for TCP packet before further processing
+    - netfilter: nft_tproxy: restrict support to TCP and UDP transport protocols
+    - RDMA/rxe: Fix qp reference counting for atomic ops
+    - samples/bpf: Fix the error return code of xdp_redirect's main()
+    - net: ethernet: aeroflex: fix UAF in greth_of_remove
+    - net: ethernet: ezchip: fix UAF in nps_enet_remove
+    - net: ethernet: ezchip: fix error handling
+    - vrf: do not push non-ND strict packets with a source LLA through packet taps
+      again
+    - net: sched: add barrier to ensure correct ordering for lockless qdisc
+    - tls: prevent oversized sendfile() hangs by ignoring MSG_MORE
+    - pkt_sched: sch_qfq: fix qfq_change_class() error path
+    - vxlan: add missing rcu_read_lock() in neigh_reduce()
+    - net/ipv4: swap flow ports when validating source
+    - tc-testing: fix list handling
+    - ieee802154: hwsim: Fix memory leak in hwsim_add_one
+    - ieee802154: hwsim: avoid possible crash in hwsim_del_edge_nl()
+    - mac80211: remove iwlwifi specific workaround NDPs of null_response
+    - net: bcmgenet: Fix attaching to PYH failed on RPi 4B
+    - ipv6: exthdrs: do not blindly use init_net
+    - bpf: Do not change gso_size during bpf_skb_change_proto()
+    - i40e: Fix error handling in i40e_vsi_open
+    - i40e: Fix autoneg disabling for non-10GBaseT links
+    - Revert "ibmvnic: remove duplicate napi_schedule call in open function"
+    - ibmvnic: free tx_pool if tso_pool alloc fails
+    - ipv6: fix out-of-bound access in ip6_parse_tlv()
+    - e1000e: Check the PCIm state
+    - bpfilter: Specify the log level for the kmsg message
+    - gve: Fix swapped vars when fetching max queues
+    - Revert "be2net: disable bh with spin_lock in be_process_mcc"
+    - Bluetooth: mgmt: Fix slab-out-of-bounds in tlv_data_is_valid
+    - Bluetooth: Fix handling of HCI_LE_Advertising_Set_Terminated event
+    - clk: actions: Fix UART clock dividers on Owl S500 SoC
+    - clk: actions: Fix SD clocks factor table on Owl S500 SoC
+    - clk: actions: Fix bisp_factor_table based clocks on Owl S500 SoC
+    - clk: si5341: Avoid divide errors due to bogus register contents
+    - clk: si5341: Update initialization magic
+    - writeback: fix obtain a reference to a freeing memcg css
+    - net: lwtunnel: handle MTU calculation in forwading
+    - net: sched: fix warning in tcindex_alloc_perfect_hash
+    - RDMA/mlx5: Don't access NULL-cleared mpi pointer
+    - MIPS: Fix PKMAP with 32-bit MIPS huge page support
+    - staging: fbtft: Rectify GPIO handling
+    - rcu: Invoke rcu_spawn_core_kthreads() from rcu_spawn_gp_kthread()
+    - tty: nozomi: Fix a resource leak in an error handling function
+    - mwifiex: re-fix for unaligned accesses
+    - iio: adis_buffer: do not return ints in irq handlers
+    - iio: adis16400: do not return ints in irq handlers
+    - iio: accel: bma180: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: accel: bma220: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: accel: hid: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: accel: kxcjk-1013: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio:accel:mxc4005: Drop unnecessary explicit casts in regmap_bulk_read calls
+    - iio: accel: mxc4005: Fix overread of data and alignment issue.
+    - iio: accel: stk8312: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: accel: stk8ba50: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: adc: ti-ads1015: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: adc: vf610: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: gyro: bmg160: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: humidity: am2315: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: prox: srf08: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: prox: pulsed-light: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: prox: as3935: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: magn: hmc5843: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: magn: bmc150: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: light: isl29125: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: light: tcs3414: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: light: tcs3472: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: cros_ec_sensors: Fix alignment of buffer in
+      iio_push_to_buffers_with_timestamp()
+    - iio: potentiostat: lmp91000: Fix alignment of buffer in
+      iio_push_to_buffers_with_timestamp()
+    - ASoC: rk3328: fix missing clk_disable_unprepare() on error in
+      rk3328_platform_probe()
+    - ASoC: hisilicon: fix missing clk_disable_unprepare() on error in
+      hi6210_i2s_startup()
+    - backlight: lm3630a_bl: Put fwnode in error case during ->probe()
+    - ASoC: rsnd: tidyup loop on rsnd_adg_clk_query()
+    - Input: hil_kbd - fix error return code in hil_dev_connect()
+    - mtd: partitions: redboot: seek fis-index-block in the right node
+    - char: pcmcia: error out if 'num_bytes_read' is greater than 4 in
+      set_protocol()
+    - firmware: stratix10-svc: Fix a resource leak in an error handling path
+    - tty: nozomi: Fix the error handling path of 'nozomi_card_init()'
+    - leds: lm3532: select regmap I2C API
+    - leds: lm36274: cosmetic: rename lm36274_data to chip
+    - leds: lm3692x: Put fwnode in any case during ->probe()
+    - scsi: FlashPoint: Rename si_flags field
+    - fsi: core: Fix return of error values on failures
+    - fsi: scom: Reset the FSI2PIB engine for any error
+    - fsi: occ: Don't accept response from un-initialized OCC
+    - fsi/sbefifo: Clean up correct FIFO when receiving reset request from SBE
+    - fsi/sbefifo: Fix reset timeout
+    - visorbus: fix error return code in visorchipset_init()
+    - s390: appldata depends on PROC_SYSCTL
+    - iommu/dma: Fix IOVA reserve dma ranges
+    - ASoC: mediatek: mtk-btcvsd: Fix an error handling path in
+      'mtk_btcvsd_snd_probe()'
+    - usb: gadget: f_fs: Fix setting of device and driver data cross-references
+    - usb: dwc2: Don't reset the core after setting turnaround time
+    - eeprom: idt_89hpesx: Put fwnode in matching case during ->probe()
+    - eeprom: idt_89hpesx: Restore printing the unsupported fwnode name
+    - iio: at91-sama5d2_adc: remove usage of iio_priv_to_dev() helper
+    - iio: adc: at91-sama5d2: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: adc: hx711: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: adc: mxs-lradc: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: adc: ti-ads8688: Fix alignment of buffer in
+      iio_push_to_buffers_with_timestamp()
+    - iio: magn: rm3100: Fix alignment of buffer in
+      iio_push_to_buffers_with_timestamp()
+    - staging: gdm724x: check for buffer overflow in gdm_lte_multi_sdu_pkt()
+    - staging: gdm724x: check for overflow in gdm_lte_netif_rx()
+    - staging: rtl8712: remove redundant check in r871xu_drv_init
+    - staging: rtl8712: fix memory leak in rtl871x_load_fw_cb
+    - staging: mt7621-dts: fix pci address for PCI memory range
+    - serial: 8250: Actually allow UPF_MAGIC_MULTIPLIER baud rates
+    - iio: light: vcnl4035: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: prox: isl29501: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - ASoC: cs42l42: Correct definition of CS42L42_ADC_PDN_MASK
+    - of: Fix truncation of memory sizes on 32-bit platforms
+    - mtd: rawnand: marvell: add missing clk_disable_unprepare() on error in
+      marvell_nfc_resume()
+    - scsi: mpt3sas: Fix error return value in _scsih_expander_add()
+    - soundwire: stream: Fix test for DP prepare complete
+    - phy: uniphier-pcie: Fix updating phy parameters
+    - phy: ti: dm816x: Fix the error handling path in 'dm816x_usb_phy_probe()
+    - extcon: sm5502: Drop invalid register write in sm5502_reg_data
+    - extcon: max8997: Add missing modalias string
+    - ASoC: atmel-i2s: Fix usage of capture and playback at the same time
+    - configfs: fix memleak in configfs_release_bin_file
+    - leds: as3645a: Fix error return code in as3645a_parse_node()
+    - leds: ktd2692: Fix an error handling path
+    - powerpc: Offline CPU in stop_this_cpu()
+    - serial: mvebu-uart: do not allow changing baudrate when uartclk is not
+      available
+    - serial: mvebu-uart: correctly calculate minimal possible baudrate
+    - arm64: dts: marvell: armada-37xx: Fix reg for standard variant of UART
+    - vfio/pci: Handle concurrent vma faults
+    - mm/huge_memory.c: don't discard hugepage if other processes are mapping it
+    - mm/z3fold: fix potential memory leak in z3fold_destroy_pool()
+    - selftests/vm/pkeys: fix alloc_random_pkey() to make it really, really random
+    - perf llvm: Return -ENOMEM when asprintf() fails
+    - scsi: target: cxgbit: Unmap DMA buffer before calling target_execute_cmd()
+    - mmc: block: Disable CMDQ on the ioctl path
+    - mmc: vub3000: fix control-request direction
+    - scsi: core: Retry I/O for Notify (Enable Spinup) Required error
+    - iommu/dma: Fix compile warning in 32-bit builds
+    - Linux 5.4.132
+  * Keyboard not working (LP: #1909814) // Focal update: v5.4.132 upstream
+    stable release (LP: #1938199)
+    - ACPI: resources: Add checks for ACPI IRQ override
+  * Focal update: v5.4.131 upstream stable release (LP: #1936245)
+    - KVM: SVM: Periodically schedule when unregistering regions on destroy
+    - s390/stack: fix possible register corruption with stack switch helper
+    - KVM: SVM: Call SEV Guest Decommission if ASID binding fails
+    - xen/events: reset active flag for lateeoi events later
+    - Linux 5.4.131
+  * Focal update: v5.4.130 upstream stable release (LP: #1936244)
+    - scsi: sr: Return appropriate error code when disk is ejected
+    - drm/nouveau: fix dma_address check for CPU/GPU sync
+    - gpio: AMD8111 and TQMX86 require HAS_IOPORT_MAP
+    - RDMA/mlx5: Block FDB rules when not in switchdev mode
+    - Linux 5.4.130
+  * Focal update: v5.4.129 upstream stable release (LP: #1936242)
+    - module: limit enabling module.sig_enforce
+    - drm/nouveau: wait for moving fence after pinning v2
+    - drm/radeon: wait for moving fence after pinning
+    - ARM: 9081/1: fix gcc-10 thumb2-kernel regression
+    - mmc: meson-gx: use memcpy_to/fromio for dram-access-quirk
+    - kbuild: add CONFIG_LD_IS_LLD
+    - arm64: link with -z norelro for LLD or aarch64-elf
+    - MIPS: generic: Update node names to avoid unit addresses
+    - spi: spi-nxp-fspi: move the register operation after the clock enable
+    - Revert "PCI: PM: Do not read power state in pci_enable_device_flags()"
+    - dmaengine: zynqmp_dma: Fix PM reference leak in
+      zynqmp_dma_alloc_chan_resourc()
+    - mac80211: remove warning in ieee80211_get_sband()
+    - mac80211_hwsim: drop pending frames on stop
+    - cfg80211: call cfg80211_leave_ocb when switching away from OCB
+    - dmaengine: rcar-dmac: Fix PM reference leak in rcar_dmac_probe()
+    - dmaengine: mediatek: free the proper desc in desc_free handler
+    - dmaengine: mediatek: do not issue a new desc if one is still current
+    - dmaengine: mediatek: use GFP_NOWAIT instead of GFP_ATOMIC in prep_dma
+    - net: ipv4: Remove unneed BUG() function
+    - mac80211: drop multicast fragments
+    - net: ethtool: clear heap allocations for ethtool function
+    - ping: Check return value of function 'ping_queue_rcv_skb'
+    - inet: annotate date races around sk->sk_txhash
+    - net: phy: dp83867: perform soft reset and retain established link
+    - net: caif: fix memory leak in ldisc_open
+    - net/packet: annotate accesses to po->bind
+    - net/packet: annotate accesses to po->ifindex
+    - r8152: Avoid memcpy() over-reading of ETH_SS_STATS
+    - sh_eth: Avoid memcpy() over-reading of ETH_SS_STATS
+    - r8169: Avoid memcpy() over-reading of ETH_SS_STATS
+    - KVM: selftests: Fix kvm_check_cap() assertion
+    - net: qed: Fix memcpy() overflow of qed_dcbx_params()
+    - recordmcount: Correct st_shndx handling
+    - PCI: Add AMD RS690 quirk to enable 64-bit DMA
+    - net: ll_temac: Add memory-barriers for TX BD access
+    - net: ll_temac: Avoid ndo_start_xmit returning NETDEV_TX_BUSY
+    - pinctrl: stm32: fix the reported number of GPIO lines per bank
+    - nilfs2: fix memory leak in nilfs_sysfs_delete_device_group
+    - KVM: do not allow mapping valid but non-reference-counted pages
+    - i2c: robotfuzz-osif: fix control-request directions
+    - kthread_worker: split code for canceling the delayed work timer
+    - kthread: prevent deadlock when kthread_mod_delayed_work() races with
+      kthread_cancel_delayed_work_sync()
+    - mm: add VM_WARN_ON_ONCE_PAGE() macro
+    - mm/rmap: remove unneeded semicolon in page_not_mapped()
+    - mm/rmap: use page_not_mapped in try_to_unmap()
+    - mm, thp: use head page in __migration_entry_wait()
+    - mm/thp: fix __split_huge_pmd_locked() on shmem migration entry
+    - mm/thp: make is_huge_zero_pmd() safe and quicker
+    - mm/thp: try_to_unmap() use TTU_SYNC for safe splitting
+    - mm/thp: fix vma_address() if virtual address below file offset
+    - mm/thp: fix page_address_in_vma() on file THP tails
+    - mm/thp: unmap_mapping_page() to fix THP truncate_cleanup_page()
+    - mm: thp: replace DEBUG_VM BUG with VM_WARN when unmap fails for split
+    - mm: page_vma_mapped_walk(): use page for pvmw->page
+    - mm: page_vma_mapped_walk(): settle PageHuge on entry
+    - mm: page_vma_mapped_walk(): use pmde for *pvmw->pmd
+    - mm: page_vma_mapped_walk(): prettify PVMW_MIGRATION block
+    - mm: page_vma_mapped_walk(): crossing page table boundary
+    - mm: page_vma_mapped_walk(): add a level of indentation
+    - mm: page_vma_mapped_walk(): use goto instead of while (1)
+    - mm: page_vma_mapped_walk(): get vma_address_end() earlier
+    - mm/thp: fix page_vma_mapped_walk() if THP mapped by ptes
+    - mm/thp: another PVMW_SYNC fix in page_vma_mapped_walk()
+    - mm, futex: fix shared futex pgoff on shmem huge page
+    - [Config] enable CONFIG_SYSTEM_REVOCATION_LIST
+    - certs: Add EFI_CERT_X509_GUID support for dbx entries
+    - certs: Move load_system_certificate_list to a common function
+    - Linux 5.4.129
+  * Patch To Fix Bug in the Linux Block Layer Responsible For  Merging BIOs
+    (LP: #1931497)
+    - block: return the correct bvec when checking for gaps
+
+  [ Ubuntu: 5.4.0-81.91 ]
+
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+  * large_dir in ext4 broken (LP: #1933074)
+    - SAUCE: ext4: fix directory index node split corruption
+  * Some test in kselftest/net on focal source tree were not tested at all
+    (LP: #1934282)
+    - selftests/net: add missing tests to Makefile
+  * curtin: install flash-kernel in arm64 UEFI unexpected (LP: #1918427)
+    - [Packaging] Allow grub-efi-arm* to satisfy recommends on ARM
+  * Add l2tp.sh in net from ubuntu_kernel_selftests back (LP: #1934293)
+    - Revert "UBUNTU: SAUCE: selftests/net -- disable l2tp.sh test"
+  * icmp_redirect.sh in net from ubuntu_kernel_selftests failed on F-OEM-5.6 /
+    F-OEM-5.10 / F-OEM-5.13 / F / G / H (LP: #1880645)
+    - selftests: icmp_redirect: support expected failures
+  * Focal update: v5.4.128 upstream stable release (LP: #1934179)
+    - dmaengine: ALTERA_MSGDMA depends on HAS_IOMEM
+    - dmaengine: QCOM_HIDMA_MGMT depends on HAS_IOMEM
+    - dmaengine: stedma40: add missing iounmap() on error in d40_probe()
+    - afs: Fix an IS_ERR() vs NULL check
+    - mm/memory-failure: make sure wait for page writeback in memory_failure
+    - kvm: LAPIC: Restore guard to prevent illegal APIC register access
+    - batman-adv: Avoid WARN_ON timing related checks
+    - net: ipv4: fix memory leak in netlbl_cipsov4_add_std
+    - vrf: fix maximum MTU
+    - net: rds: fix memory leak in rds_recvmsg
+    - net: lantiq: disable interrupt before sheduling NAPI
+    - udp: fix race between close() and udp_abort()
+    - rtnetlink: Fix regression in bridge VLAN configuration
+    - net/sched: act_ct: handle DNAT tuple collision
+    - net/mlx5e: Remove dependency in IPsec initialization flows
+    - net/mlx5e: Fix page reclaim for dead peer hairpin
+    - net/mlx5: Consider RoCE cap before init RDMA resources
+    - net/mlx5e: allow TSO on VXLAN over VLAN topologies
+    - net/mlx5e: Block offload of outer header csum for UDP tunnels
+    - netfilter: synproxy: Fix out of bounds when parsing TCP options
+    - sch_cake: Fix out of bounds when parsing TCP options and header
+    - alx: Fix an error handling path in 'alx_probe()'
+    - net: stmmac: dwmac1000: Fix extended MAC address registers definition
+    - net: make get_net_ns return error if NET_NS is disabled
+    - qlcnic: Fix an error handling path in 'qlcnic_probe()'
+    - netxen_nic: Fix an error handling path in 'netxen_nic_probe()'
+    - net: qrtr: fix OOB Read in qrtr_endpoint_post
+    - ptp: improve max_adj check against unreasonable values
+    - net: cdc_ncm: switch to eth%d interface naming
+    - lantiq: net: fix duplicated skb in rx descriptor ring
+    - net: usb: fix possible use-after-free in smsc75xx_bind
+    - net: fec_ptp: fix issue caused by refactor the fec_devtype
+    - net: ipv4: fix memory leak in ip_mc_add1_src
+    - net/af_unix: fix a data-race in unix_dgram_sendmsg / unix_release_sock
+    - be2net: Fix an error handling path in 'be_probe()'
+    - net: hamradio: fix memory leak in mkiss_close
+    - net: cdc_eem: fix tx fixup skb leak
+    - cxgb4: fix wrong shift.
+    - bnxt_en: Rediscover PHY capabilities after firmware reset
+    - bnxt_en: Call bnxt_ethtool_free() in bnxt_init_one() error path
+    - icmp: don't send out ICMP messages with a source address of 0.0.0.0
+    - net: ethernet: fix potential use-after-free in ec_bhf_remove
+    - regulator: bd70528: Fix off-by-one for buck123 .n_voltages setting
+    - ASoC: rt5659: Fix the lost powers for the HDA header
+    - spi: stm32-qspi: Always wait BUSY bit to be cleared in stm32_qspi_wait_cmd()
+    - pinctrl: ralink: rt2880: avoid to error in calls is pin is already enabled
+    - radeon: use memcpy_to/fromio for UVD fw upload
+    - hwmon: (scpi-hwmon) shows the negative temperature properly
+    - can: bcm: fix infoleak in struct bcm_msg_head
+    - can: bcm/raw/isotp: use per module netdevice notifier
+    - can: j1939: fix Use-after-Free, hold skb ref while in use
+    - can: mcba_usb: fix memory leak in mcba_usb
+    - usb: core: hub: Disable autosuspend for Cypress CY7C65632
+    - tracing: Do not stop recording cmdlines when tracing is off
+    - tracing: Do not stop recording comms if the trace file is being read
+    - tracing: Do no increment trace_clock_global() by one
+    - PCI: Mark TI C667X to avoid bus reset
+    - PCI: Mark some NVIDIA GPUs to avoid bus reset
+    - PCI: aardvark: Don't rely on jiffies while holding spinlock
+    - PCI: aardvark: Fix kernel panic during PIO transfer
+    - PCI: Add ACS quirk for Broadcom BCM57414 NIC
+    - PCI: Work around Huawei Intelligent NIC VF FLR erratum
+    - KVM: x86: Immediately reset the MMU context when the SMM flag is cleared
+    - ARCv2: save ABI registers across signal handling
+    - x86/process: Check PF_KTHREAD and not current->mm for kernel threads
+    - x86/pkru: Write hardware init value to PKRU when xstate is init
+    - x86/fpu: Reset state for all signal restore failures
+    - dmaengine: pl330: fix wrong usage of spinlock flags in dma_cyclc
+    - cfg80211: make certificate generation more robust
+    - cfg80211: avoid double free of PMSR request
+    - net: ll_temac: Make sure to free skb when it is completely used
+    - net: ll_temac: Fix TX BD buffer overwrite
+    - net: bridge: fix vlan tunnel dst null pointer dereference
+    - net: bridge: fix vlan tunnel dst refcnt when egressing
+    - mm/slub: clarify verification reporting
+    - mm/slub: fix redzoning for small allocations
+    - mm/slub.c: include swab.h
+    - net: stmmac: disable clocks in stmmac_remove_config_dt()
+    - net: fec_ptp: add clock rate zero check
+    - tools headers UAPI: Sync linux/in.h copy with the kernel sources
+    - KVM: arm/arm64: Fix KVM_VGIC_V3_ADDR_TYPE_REDIST read
+    - ARM: OMAP: replace setup_irq() by request_irq()
+    - clocksource/drivers/timer-ti-dm: Add clockevent and clocksource support
+    - clocksource/drivers/timer-ti-dm: Prepare to handle dra7 timer wrap issue
+    - clocksource/drivers/timer-ti-dm: Handle dra7 timer wrap errata i940
+    - usb: dwc3: debugfs: Add and remove endpoint dirs dynamically
+    - usb: dwc3: core: fix kernel panic when do reboot
+    - Linux 5.4.128
+  * linux-azure CIFS DFS oops (LP: #1935833)
+    - cifs: get rid of unused parameter in reconn_setup_dfs_targets()
+    - cifs: handle empty list of targets in cifs_reconnect()
+  * pmtu.sh from net in ubuntu_kernel_selftests failed with no error message
+    (LP: #1887661)
+    - selftests: pmtu.sh: improve the test result processing
+  * cifs: On cifs_reconnect, resolve the hostname again (LP: #1929831)
+    - cifs: rename reconn_inval_dfs_target()
+    - cifs: Simplify reconnect code when dfs upcall is enabled
+    - cifs: Avoid error pointer dereference
+    - cifs: On cifs_reconnect, resolve the hostname again.
+  * Pixel format change broken for Elgato Cam Link 4K (LP: #1932367)
+    - (upstream) media: uvcvideo: Fix pixel format change for Elgato Cam Link 4K
+  * Focal update: v5.4.127 upstream stable release (LP: #1933851)
+    - net: ieee802154: fix null deref in parse dev addr
+    - HID: quirks: Set INCREMENT_USAGE_ON_DUPLICATE for Saitek X65
+    - HID: hid-input: add mapping for emoji picker key
+    - HID: hid-sensor-hub: Return error for hid_set_field() failure
+    - HID: quirks: Add quirk for Lenovo optical mouse
+    - HID: multitouch: set Stylus suffix for Stylus-application devices, too
+    - HID: Add BUS_VIRTUAL to hid_connect logging
+    - HID: usbhid: fix info leak in hid_submit_ctrl
+    - drm/tegra: sor: Do not leak runtime PM reference
+    - ARM: OMAP2+: Fix build warning when mmc_omap is not built
+    - gfs2: Prevent direct-I/O write fallback errors from getting lost
+    - HID: gt683r: add missing MODULE_DEVICE_TABLE
+    - riscv: Use -mno-relax when using lld linker
+    - gfs2: Fix use-after-free in gfs2_glock_shrink_scan
+    - scsi: target: core: Fix warning on realtime kernels
+    - ethernet: myri10ge: Fix missing error code in myri10ge_probe()
+    - scsi: qedf: Do not put host in qedf_vport_create() unconditionally
+    - scsi: scsi_devinfo: Add blacklist entry for HPE OPEN-V
+    - nvme-loop: reset queue count to 1 in nvme_loop_destroy_io_queues()
+    - nvme-loop: clear NVME_LOOP_Q_LIVE when nvme_loop_configure_admin_queue()
+      fails
+    - nvme-loop: check for NVME_LOOP_Q_LIVE in nvme_loop_destroy_admin_queue()
+    - net: ipconfig: Don't override command-line hostnames or domains
+    - drm/amd/display: Allow bandwidth validation for 0 streams.
+    - rtnetlink: Fix missing error code in rtnl_bridge_notify()
+    - net/x25: Return the correct errno code
+    - net: Return the correct errno code
+    - fib: Return the correct errno code
+    - Linux 5.4.127
+  * Focal update: v5.4.126 upstream stable release (LP: #1933369)
+    - proc: Check /proc/$pid/attr/ writes against file opener
+    - proc: Track /proc/$pid/attr/ opener mm_struct
+    - ASoC: max98088: fix ni clock divider calculation
+    - spi: Fix spi device unregister flow
+    - net/nfc/rawsock.c: fix a permission check bug
+    - usb: cdns3: Fix runtime PM imbalance on error
+    - ASoC: Intel: bytcr_rt5640: Add quirk for the Glavey TM800A550L tablet
+    - ASoC: Intel: bytcr_rt5640: Add quirk for the Lenovo Miix 3-830 tablet
+    - vfio-ccw: Serialize FSM IDLE state with I/O completion
+    - ASoC: sti-sas: add missing MODULE_DEVICE_TABLE
+    - spi: sprd: Add missing MODULE_DEVICE_TABLE
+    - isdn: mISDN: netjet: Fix crash in nj_probe:
+    - bonding: init notify_work earlier to avoid uninitialized use
+    - netlink: disable IRQs for netlink_lock_table()
+    - net: mdiobus: get rid of a BUG_ON()
+    - cgroup: disable controllers at parse time
+    - wq: handle VM suspension in stall detection
+    - net/qla3xxx: fix schedule while atomic in ql_sem_spinlock
+    - RDS tcp loopback connection can hang
+    - scsi: bnx2fc: Return failure if io_req is already in ABTS processing
+    - scsi: vmw_pvscsi: Set correct residual data length
+    - scsi: hisi_sas: Drop free_irq() of devm_request_irq() allocated irq
+    - scsi: target: qla2xxx: Wait for stop_phase1 at WWN removal
+    - net: macb: ensure the device is available before accessing GEMGXL control
+      registers
+    - net: appletalk: cops: Fix data race in cops_probe1
+    - net: dsa: microchip: enable phy errata workaround on 9567
+    - nvme-fabrics: decode host pathing error for connect
+    - MIPS: Fix kernel hang under FUNCTION_GRAPH_TRACER and PREEMPT_TRACER
+    - dm verity: fix require_signatures module_param permissions
+    - bnx2x: Fix missing error code in bnx2x_iov_init_one()
+    - nvme-tcp: remove incorrect Kconfig dep in BLK_DEV_NVME
+    - powerpc/fsl: set fsl,i2c-erratum-a004447 flag for P2041 i2c controllers
+    - powerpc/fsl: set fsl,i2c-erratum-a004447 flag for P1010 i2c controllers
+    - spi: Don't have controller clean up spi device before driver unbind
+    - spi: Cleanup on failure of initial setup
+    - i2c: mpc: Make use of i2c_recover_bus()
+    - i2c: mpc: implement erratum A-004447 workaround
+    - x86/boot: Add .text.* to setup.ld
+    - spi: bcm2835: Fix out-of-bounds access with more than 4 slaves
+    - drm: Fix use-after-free read in drm_getunique()
+    - drm: Lock pointer access in drm_master_release()
+    - kvm: avoid speculation-based attacks from out-of-range memslot accesses
+    - staging: rtl8723bs: Fix uninitialized variables
+    - btrfs: return value from btrfs_mark_extent_written() in case of error
+    - btrfs: promote debugging asserts to full-fledged checks in validate_super
+    - cgroup1: don't allow '\n' in renaming
+    - USB: f_ncm: ncm_bitrate (speed) is unsigned
+    - usb: f_ncm: only first packet of aggregate needs to start timer
+    - usb: pd: Set PD_T_SINK_WAIT_CAP to 310ms
+    - usb: dwc3: ep0: fix NULL pointer exception
+    - usb: musb: fix MUSB_QUIRK_B_DISCONNECT_99 handling
+    - usb: typec: wcove: Use LE to CPU conversion when accessing msg->header
+    - usb: typec: ucsi: Clear PPM capability data in ucsi_init() error path
+    - usb: gadget: f_fs: Ensure io_completion_wq is idle during unbind
+    - USB: serial: ftdi_sio: add NovaTech OrionMX product ID
+    - USB: serial: omninet: add device id for Zyxel Omni 56K Plus
+    - USB: serial: quatech2: fix control-request directions
+    - USB: serial: cp210x: fix alternate function for CP2102N QFN20
+    - usb: gadget: eem: fix wrong eem header operation
+    - usb: fix various gadgets null ptr deref on 10gbps cabling.
+    - usb: fix various gadget panics on 10gbps cabling
+    - regulator: core: resolve supply for boot-on/always-on regulators
+    - regulator: max77620: Use device_set_of_node_from_dev()
+    - usb: typec: mux: Fix copy-paste mistake in typec_mux_match
+    - RDMA/ipoib: Fix warning caused by destroying non-initial netns
+    - RDMA/mlx4: Do not map the core_clock page to user space unless enabled
+    - vmlinux.lds.h: Avoid orphan section with !SMP
+    - perf: Fix data race between pin_count increment/decrement
+    - sched/fair: Make sure to update tg contrib for blocked load
+    - KVM: x86: Ensure liveliness of nested VM-Enter fail tracepoint message
+    - IB/mlx5: Fix initializing CQ fragments buffer
+    - NFS: Fix a potential NULL dereference in nfs_get_client()
+    - NFSv4: Fix deadlock between nfs4_evict_inode() and nfs4_opendata_get_inode()
+    - perf session: Correct buffer copying when peeking events
+    - kvm: fix previous commit for 32-bit builds
+    - NFS: Fix use-after-free in nfs4_init_client()
+    - NFSv4: Fix second deadlock in nfs4_evict_inode()
+    - NFSv4: nfs4_proc_set_acl needs to restore NFS_CAP_UIDGID_NOMAP on error.
+    - scsi: core: Fix error handling of scsi_host_alloc()
+    - scsi: core: Fix failure handling of scsi_add_host_with_dma()
+    - scsi: core: Put .shost_dev in failure path if host state changes to RUNNING
+    - scsi: core: Only put parent device if host state differs from SHOST_CREATED
+    - ftrace: Do not blindly read the ip address in ftrace_bug()
+    - tracing: Correct the length check which causes memory corruption
+    - proc: only require mm_struct for writing
+    - Linux 5.4.126
+  * Focal update: v5.4.125 upstream stable release (LP: #1932957)
+    - btrfs: tree-checker: do not error out if extent ref hash doesn't match
+    - net: usb: cdc_ncm: don't spew notifications
+    - ALSA: usb: update old-style static const declaration
+    - nl80211: validate key indexes for cfg80211_registered_device
+    - hwmon: (dell-smm-hwmon) Fix index values
+    - netfilter: conntrack: unregister ipv4 sockopts on error unwind
+    - efi: Allow EFI_MEMORY_XP and EFI_MEMORY_RO both to be cleared
+    - efi: cper: fix snprintf() use in cper_dimm_err_location()
+    - vfio/pci: Fix error return code in vfio_ecap_init()
+    - vfio/pci: zap_vma_ptes() needs MMU
+    - samples: vfio-mdev: fix error handing in mdpy_fb_probe()
+    - vfio/platform: fix module_put call in error flow
+    - ipvs: ignore IP_VS_SVC_F_HASHED flag when adding service
+    - HID: pidff: fix error return code in hid_pidff_init()
+    - HID: i2c-hid: fix format string mismatch
+    - net/sched: act_ct: Fix ct template allocation for zone 0
+    - ACPICA: Clean up context mutex during object deletion
+    - netfilter: nft_ct: skip expectations for confirmed conntrack
+    - netfilter: nfnetlink_cthelper: hit EBUSY on updates if size mismatches
+    - ieee802154: fix error return code in ieee802154_add_iface()
+    - ieee802154: fix error return code in ieee802154_llsec_getparams()
+    - ixgbevf: add correct exception tracing for XDP
+    - ipv6: Fix KASAN: slab-out-of-bounds Read in fib6_nh_flush_exceptions
+    - ice: write register with correct offset
+    - ice: Fix VFR issues for AVF drivers that expect ATQLEN cleared
+    - ice: Allow all LLDP packets from PF to Tx
+    - i2c: qcom-geni: Add shutdown callback for i2c
+    - i40e: optimize for XDP_REDIRECT in xsk path
+    - i40e: add correct exception tracing for XDP
+    - arm64: dts: ls1028a: fix memory node
+    - arm64: dts: zii-ultra: fix 12V_MAIN voltage
+    - ARM: dts: imx7d-meerkat96: Fix the 'tuning-step' property
+    - ARM: dts: imx7d-pico: Fix the 'tuning-step' property
+    - ARM: dts: imx: emcon-avari: Fix nxp,pca8574 #gpio-cells
+    - bus: ti-sysc: Fix flakey idling of uarts and stop using swsup_sidle_act
+    - tipc: add extack messages for bearer/media failure
+    - tipc: fix unique bearer names sanity check
+    - Bluetooth: fix the erroneous flush_work() order
+    - Bluetooth: use correct lock to prevent UAF of hdev object
+    - net: caif: added cfserl_release function
+    - net: caif: add proper error handling
+    - net: caif: fix memory leak in caif_device_notify
+    - net: caif: fix memory leak in cfusbl_device_notify
+    - HID: i2c-hid: Skip ELAN power-on command after reset
+    - HID: magicmouse: fix NULL-deref on disconnect
+    - HID: multitouch: require Finger field to mark Win8 reports as MT
+    - ALSA: timer: Fix master timer notification
+    - ALSA: hda: Fix for mute key LED for HP Pavilion 15-CK0xx
+    - ARM: dts: imx6dl-yapp4: Fix RGMII connection to QCA8334 switch
+    - ARM: dts: imx6q-dhcom: Add PU,VDD1P1,VDD2P5 regulators
+    - ext4: fix bug on in ext4_es_cache_extent as ext4_split_extent_at failed
+    - usb: dwc2: Fix build in periphal-only mode
+    - pid: take a reference when initializing `cad_pid`
+    - ocfs2: fix data corruption by fallocate
+    - nfc: fix NULL ptr dereference in llcp_sock_getname() after failed connect
+    - drm/amdgpu: Don't query CE and UE errors
+    - drm/amdgpu: make sure we unpin the UVD BO
+    - x86/apic: Mark _all_ legacy interrupts when IO/APIC is missing
+    - btrfs: mark ordered extent and inode with error if we fail to finish
+    - btrfs: fix error handling in btrfs_del_csums
+    - btrfs: return errors from btrfs_del_csums in cleanup_ref_head
+    - btrfs: fixup error handling in fixup_inode_link_counts
+    - mm, hugetlb: fix simple resv_huge_pages underflow on UFFDIO_COPY
+    - bnxt_en: Remove the setting of dev_port.
+    - mm: add thp_order
+    - XArray: add xa_get_order
+    - XArray: add xas_split
+    - mm/filemap: fix storing to a THP shadow entry
+    - btrfs: fix unmountable seed device after fstrim
+    - KVM: SVM: Truncate GPR value for DR and CR accesses in !64-bit mode
+    - KVM: arm64: Fix debug register indexing
+    - lib/lz4: explicitly support in-place decompression
+    - xen-pciback: redo VF placement in the virtual topology
+    - i2c: qcom-geni: Suspend and resume the bus during SYSTEM_SLEEP_PM ops
+    - neighbour: allow NUD_NOARP entries to be forced GCed
+    - Linux 5.4.125
+
+  [ Ubuntu: 5.4.0-80.90 ]
+
+  * CVE-2021-33909
+    - SAUCE: seq_file: Disallow extremely large seq buffer allocations
+
+  [ Ubuntu: 5.4.0-79.88 ]
+
+  * focal/linux: 5.4.0-79.88 -proposed tracker (LP: #1934343)
+  * lxd exec fails (LP: #1934187)
+    - SAUCE: Revert "proc: Check /proc/$pid/attr/ writes against file opener"
+
+  [ Ubuntu: 5.4.0-78.87 ]
+
+  * focal/linux: 5.4.0-78.87 -proposed tracker (LP: #1932478)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync getabis
+    - [Packaging] update helper scripts
+    - update dkms package versions
+  * Disable hv-kvp-daemon.service on certain instance types (LP: #1932081)
+    - [Packaging]: Add kernel command line condition to hv-kvp-daemon service
+  * QLogic Direct-Connect host can't discover SCSI-FC or NVMe/FC devices
+    (LP: #1860724)
+    - scsi: qla2xxx: Serialize fc_port alloc in N2N
+    - scsi: qla2xxx: Set Nport ID for N2N
+    - scsi: qla2xxx: Fix point-to-point (N2N) device discovery issue
+    - scsi: qla2xxx: Fix N2N and NVMe connect retry failure
+  * [SRU] Add support for E810 NIC to Ice Driver in Focal (LP: #1912511)
+    - ice: add additional E810 device id
+  * Focal update: v5.4.124 upstream stable release (LP: #1931166)
+    - ALSA: hda/realtek: Headphone volume is controlled by Front mixer
+    - ALSA: usb-audio: scarlett2: Fix device hang with ehci-pci
+    - ALSA: usb-audio: scarlett2: Improve driver startup messages
+    - cifs: set server->cipher_type to AES-128-CCM for SMB3.0
+    - NFSv4: Fix a NULL pointer dereference in pnfs_mark_matching_lsegs_return()
+    - iommu/vt-d: Fix sysfs leak in alloc_iommu()
+    - perf intel-pt: Fix sample instruction bytes
+    - perf intel-pt: Fix transaction abort handling
+    - perf scripts python: exported-sql-viewer.py: Fix copy to clipboard from Top
+      Calls by elapsed Time report
+    - perf scripts python: exported-sql-viewer.py: Fix Array TypeError
+    - perf scripts python: exported-sql-viewer.py: Fix warning display
+    - proc: Check /proc/$pid/attr/ writes against file opener
+    - net: hso: fix control-request directions
+    - ath10k: Validate first subframe of A-MSDU before processing the list
+    - dm snapshot: properly fix a crash when an origin has no snapshots
+    - drm/amdgpu/vcn1: add cancel_delayed_work_sync before power gate
+    - drm/amdgpu/vcn2.0: add cancel_delayed_work_sync before power gate
+    - drm/amdgpu/vcn2.5: add cancel_delayed_work_sync before power gate
+    - selftests/gpio: Use TEST_GEN_PROGS_EXTENDED
+    - selftests/gpio: Move include of lib.mk up
+    - selftests/gpio: Fix build when source tree is read only
+    - kgdb: fix gcc-11 warnings harder
+    - Documentation: seccomp: Fix user notification documentation
+    - serial: core: fix suspicious security_locked_down() call
+    - misc/uss720: fix memory leak in uss720_probe
+    - thunderbolt: dma_port: Fix NVM read buffer bounds and offset issue
+    - mei: request autosuspend after sending rx flow control
+    - staging: iio: cdc: ad7746: avoid overwrite of num_channels
+    - iio: gyro: fxas21002c: balance runtime power in error path
+    - iio: adc: ad7768-1: Fix too small buffer passed to
+      iio_push_to_buffers_with_timestamp()
+    - iio: adc: ad7124: Fix missbalanced regulator enable / disable on error.
+    - iio: adc: ad7124: Fix potential overflow due to non sequential channel
+      numbers
+    - iio: adc: ad7793: Add missing error code in ad7793_setup()
+    - serial: 8250_pci: Add support for new HPE serial device
+    - serial: 8250_pci: handle FL_NOIRQ board flag
+    - USB: trancevibrator: fix control-request direction
+    - USB: usbfs: Don't WARN about excessively large memory allocations
+    - serial: tegra: Fix a mask operation that is always true
+    - serial: sh-sci: Fix off-by-one error in FIFO threshold register setting
+    - serial: rp2: use 'request_firmware' instead of 'request_firmware_nowait'
+    - USB: serial: ti_usb_3410_5052: add startech.com device id
+    - USB: serial: option: add Telit LE910-S1 compositions 0x7010, 0x7011
+    - USB: serial: ftdi_sio: add IDs for IDS GmbH Products
+    - USB: serial: pl2303: add device id for ADLINK ND-6530 GC
+    - thermal/drivers/intel: Initialize RW trip to THERMAL_TEMP_INVALID
+    - usb: dwc3: gadget: Properly track pending and queued SG
+    - usb: gadget: udc: renesas_usb3: Fix a race in usb3_start_pipen()
+    - net: usb: fix memory leak in smsc75xx_bind
+    - spi: spi-geni-qcom: Fix use-after-free on unbind
+    - Bluetooth: cmtp: fix file refcount when cmtp_attach_device fails
+    - fs/nfs: Use fatal_signal_pending instead of signal_pending
+    - NFS: fix an incorrect limit in filelayout_decode_layout()
+    - NFS: Fix an Oopsable condition in __nfs_pageio_add_request()
+    - NFS: Don't corrupt the value of pg_bytes_written in nfs_do_recoalesce()
+    - NFSv4: Fix v4.0/v4.1 SEEK_DATA return -ENOTSUPP when set NFS_V4_2 config
+    - drm/meson: fix shutdown crash when component not probed
+    - net/mlx5e: Fix multipath lag activation
+    - net/mlx5e: Fix nullptr in add_vlan_push_action()
+    - net/mlx4: Fix EEPROM dump support
+    - Revert "net:tipc: Fix a double free in tipc_sk_mcast_rcv"
+    - tipc: wait and exit until all work queues are done
+    - tipc: skb_linearize the head skb when reassembling msgs
+    - spi: spi-fsl-dspi: Fix a resource leak in an error handling path
+    - net: dsa: mt7530: fix VLAN traffic leaks
+    - net: dsa: fix a crash if ->get_sset_count() fails
+    - net: dsa: sja1105: error out on unsupported PHY mode
+    - i2c: s3c2410: fix possible NULL pointer deref on read message after write
+    - i2c: i801: Don't generate an interrupt on bus reset
+    - i2c: sh_mobile: Use new clock calculation formulas for RZ/G2E
+    - perf jevents: Fix getting maximum number of fds
+    - platform/x86: hp_accel: Avoid invoking _INI to speed up resume
+    - gpio: cadence: Add missing MODULE_DEVICE_TABLE
+    - Revert "media: usb: gspca: add a missed check for goto_low_power"
+    - Revert "ALSA: sb: fix a missing check of snd_ctl_add"
+    - Revert "serial: max310x: pass return value of spi_register_driver"
+    - serial: max310x: unregister uart driver in case of failure and abort
+    - Revert "net: fujitsu: fix a potential NULL pointer dereference"
+    - net: fujitsu: fix potential null-ptr-deref
+    - Revert "net/smc: fix a NULL pointer dereference"
+    - net: caif: remove BUG_ON(dev == NULL) in caif_xmit
+    - Revert "char: hpet: fix a missing check of ioremap"
+    - char: hpet: add checks after calling ioremap
+    - Revert "ALSA: gus: add a check of the status of snd_ctl_add"
+    - Revert "ALSA: usx2y: Fix potential NULL pointer dereference"
+    - Revert "isdn: mISDNinfineon: fix potential NULL pointer dereference"
+    - isdn: mISDNinfineon: check/cleanup ioremap failure correctly in setup_io
+    - Revert "ath6kl: return error code in ath6kl_wmi_set_roam_lrssi_cmd()"
+    - ath6kl: return error code in ath6kl_wmi_set_roam_lrssi_cmd()
+    - Revert "isdn: mISDN: Fix potential NULL pointer dereference of kzalloc"
+    - isdn: mISDN: correctly handle ph_info allocation failure in hfcsusb_ph_info
+    - Revert "dmaengine: qcom_hidma: Check for driver register failure"
+    - dmaengine: qcom_hidma: comment platform_driver_register call
+    - Revert "libertas: add checks for the return value of sysfs_create_group"
+    - libertas: register sysfs groups properly
+    - Revert "ASoC: cs43130: fix a NULL pointer dereference"
+    - ASoC: cs43130: handle errors in cs43130_probe() properly
+    - Revert "media: dvb: Add check on sp8870_readreg"
+    - media: dvb: Add check on sp8870_readreg return
+    - Revert "media: gspca: mt9m111: Check write_bridge for timeout"
+    - media: gspca: mt9m111: Check write_bridge for timeout
+    - Revert "media: gspca: Check the return value of write_bridge for timeout"
+    - media: gspca: properly check for errors in po1030_probe()
+    - Revert "net: liquidio: fix a NULL pointer dereference"
+    - net: liquidio: Add missing null pointer checks
+    - Revert "brcmfmac: add a check for the status of usb_register"
+    - brcmfmac: properly check for bus register errors
+    - btrfs: return whole extents in fiemap
+    - scsi: BusLogic: Fix 64-bit system enumeration error for Buslogic
+    - openrisc: Define memory barrier mb
+    - btrfs: do not BUG_ON in link_to_fixup_dir
+    - platform/x86: hp-wireless: add AMD's hardware id to the supported list
+    - platform/x86: intel_punit_ipc: Append MODULE_DEVICE_TABLE for ACPI
+    - platform/x86: touchscreen_dmi: Add info for the Mediacom Winpad 7.0 W700
+      tablet
+    - SMB3: incorrect file id in requests compounded with open
+    - drm/amd/display: Disconnect non-DP with no EDID
+    - drm/amd/amdgpu: fix refcount leak
+    - drm/amdgpu: Fix a use-after-free
+    - drm/amd/amdgpu: fix a potential deadlock in gpu reset
+    - net: netcp: Fix an error message
+    - net: dsa: fix error code getting shifted with 4 in dsa_slave_get_sset_count
+    - ASoC: cs42l42: Regmap must use_single_read/write
+    - vfio-ccw: Check initialized flag in cp_init()
+    - net: really orphan skbs tied to closing sk
+    - net: fec: fix the potential memory leak in fec_enet_init()
+    - net: mdio: thunder: Fix a double free issue in the .remove function
+    - net: mdio: octeon: Fix some double free issues
+    - openvswitch: meter: fix race when getting now_ms.
+    - tls splice: check SPLICE_F_NONBLOCK instead of MSG_DONTWAIT
+    - net: sched: fix packet stuck problem for lockless qdisc
+    - net: sched: fix tx action rescheduling issue during deactivation
+    - net: sched: fix tx action reschedule issue with stopped queue
+    - net: hso: check for allocation failure in hso_create_bulk_serial_device()
+    - net: bnx2: Fix error return code in bnx2_init_board()
+    - bnxt_en: Include new P5 HV definition in VF check.
+    - mld: fix panic in mld_newpack()
+    - gve: Check TX QPL was actually assigned
+    - gve: Update mgmt_msix_idx if num_ntfy changes
+    - gve: Add NULL pointer checks when freeing irqs.
+    - gve: Upgrade memory barrier in poll routine
+    - gve: Correct SKB queue index validation.
+    - cxgb4: avoid accessing registers when clearing filters
+    - staging: emxx_udc: fix loop in _nbu2ss_nuke()
+    - ASoC: cs35l33: fix an error code in probe()
+    - bpf: Set mac_len in bpf_skb_change_head
+    - ixgbe: fix large MTU request from VF
+    - scsi: libsas: Use _safe() loop in sas_resume_port()
+    - net: lantiq: fix memory corruption in RX ring
+    - ipv6: record frag_max_size in atomic fragments in input path
+    - ALSA: usb-audio: scarlett2: snd_scarlett_gen2_controls_create() can be
+      static
+    - net: ethernet: mtk_eth_soc: Fix packet statistics support for MT7628/88
+    - sch_dsmark: fix a NULL deref in qdisc_reset()
+    - MIPS: alchemy: xxs1500: add gpio-au1000.h header file
+    - MIPS: ralink: export rt_sysc_membase for rt2880_wdt.c
+    - drm/i915/display: fix compiler warning about array overrun
+    - i915: fix build warning in intel_dp_get_link_status()
+    - drivers/net/ethernet: clean up unused assignments
+    - net: hns3: check the return of skb_checksum_help()
+    - Revert "Revert "ALSA: usx2y: Fix potential NULL pointer dereference""
+    - net: hso: bail out on interrupt URB allocation failure
+    - neighbour: Prevent Race condition in neighbour subsytem
+    - usb: core: reduce power-on-good delay time of root hub
+    - Linux 5.4.124
+  * Focal update: v5.4.123 upstream stable release (LP: #1931160)
+    - usb: dwc3: gadget: Enable suspend events
+    - perf unwind: Fix separate debug info files when using elfutils' libdw's
+      unwinder
+    - perf unwind: Set userdata for all __report_module() paths
+    - NFC: nci: fix memory leak in nci_allocate_device
+    - Linux 5.4.123
+  * Focal update: v5.4.122 upstream stable release (LP: #1931159)
+    - firmware: arm_scpi: Prevent the ternary sign expansion bug
+    - openrisc: Fix a memory leak
+    - RDMA/siw: Properly check send and receive CQ pointers
+    - RDMA/siw: Release xarray entry
+    - RDMA/rxe: Clear all QP fields if creation failed
+    - scsi: ufs: core: Increase the usable queue depth
+    - scsi: qla2xxx: Fix error return code in qla82xx_write_flash_dword()
+    - RDMA/mlx5: Recover from fatal event in dual port mode
+    - RDMA/core: Don't access cm_id after its destruction
+    - platform/mellanox: mlxbf-tmfifo: Fix a memory barrier issue
+    - platform/x86: dell-smbios-wmi: Fix oops on rmmod dell_smbios
+    - RDMA/uverbs: Fix a NULL vs IS_ERR() bug
+    - ptrace: make ptrace() fail if the tracee changed its pid unexpectedly
+    - nvmet: seset ns->file when open fails
+    - locking/mutex: clear MUTEX_FLAGS if wait_list is empty due to signal
+    - btrfs: avoid RCU stalls while running delayed iputs
+    - cifs: fix memory leak in smb2_copychunk_range
+    - ALSA: dice: fix stream format for TC Electronic Konnekt Live at high
+      sampling transfer frequency
+    - ALSA: intel8x0: Don't update period unless prepared
+    - ALSA: line6: Fix racy initialization of LINE6 MIDI
+    - ALSA: dice: fix stream format at middle sampling rate for Alesis iO 26
+    - ALSA: firewire-lib: fix calculation for size of IR context payload
+    - ALSA: usb-audio: Validate MS endpoint descriptors
+    - ALSA: bebob/oxfw: fix Kconfig entry for Mackie d.2 Pro
+    - ALSA: hda: fixup headset for ASUS GU502 laptop
+    - Revert "ALSA: sb8: add a check for request_region"
+    - ALSA: firewire-lib: fix check for the size of isochronous packet payload
+    - ALSA: hda/realtek: reset eapd coeff to default value for alc287
+    - ALSA: hda/realtek: Add some CLOVE SSIDs of ALC293
+    - ALSA: hda/realtek: Fix silent headphone output on ASUS UX430UA
+    - ALSA: hda/realtek: Add fixup for HP OMEN laptop
+    - ALSA: hda/realtek: Add fixup for HP Spectre x360 15-df0xxx
+    - uio_hv_generic: Fix a memory leak in error handling paths
+    - Revert "rapidio: fix a NULL pointer dereference when create_workqueue()
+      fails"
+    - rapidio: handle create_workqueue() failure
+    - Revert "serial: mvebu-uart: Fix to avoid a potential NULL pointer
+      dereference"
+    - drm/amdgpu: disable 3DCGCG on picasso/raven1 to avoid compute hang
+    - drm/amdgpu: update gc golden setting for Navi12
+    - drm/amdgpu: update sdma golden setting for Navi12
+    - mmc: sdhci-pci-gli: increase 1.8V regulator wait
+    - xen-pciback: reconfigure also from backend watch handler
+    - dm snapshot: fix crash with transient storage and zero chunk size
+    - Revert "video: hgafb: fix potential NULL pointer dereference"
+    - Revert "net: stmicro: fix a missing check of clk_prepare"
+    - Revert "leds: lp5523: fix a missing check of return value of lp55xx_read"
+    - Revert "hwmon: (lm80) fix a missing check of bus read in lm80 probe"
+    - Revert "video: imsttfb: fix potential NULL pointer dereferences"
+    - Revert "ecryptfs: replace BUG_ON with error handling code"
+    - Revert "scsi: ufs: fix a missing check of devm_reset_control_get"
+    - Revert "gdrom: fix a memory leak bug"
+    - cdrom: gdrom: deallocate struct gdrom_unit fields in remove_gdrom
+    - cdrom: gdrom: initialize global variable at init time
+    - Revert "media: rcar_drif: fix a memory disclosure"
+    - Revert "rtlwifi: fix a potential NULL pointer dereference"
+    - Revert "qlcnic: Avoid potential NULL pointer dereference"
+    - Revert "niu: fix missing checks of niu_pci_eeprom_read"
+    - ethernet: sun: niu: fix missing checks of niu_pci_eeprom_read()
+    - net: stmicro: handle clk_prepare() failure during init
+    - scsi: ufs: handle cleanup correctly on devm_reset_control_get error
+    - net: rtlwifi: properly check for alloc_workqueue() failure
+    - ics932s401: fix broken handling of errors when word reading fails
+    - leds: lp5523: check return value of lp5xx_read and jump to cleanup code
+    - qlcnic: Add null check after calling netdev_alloc_skb
+    - video: hgafb: fix potential NULL pointer dereference
+    - vgacon: Record video mode changes with VT_RESIZEX
+    - vt: Fix character height handling with VT_RESIZEX
+    - tty: vt: always invoke vc->vc_sw->con_resize callback
+    - nvme-multipath: fix double initialization of ANA state
+    - ext4: fix error handling in ext4_end_enable_verity()
+    - Bluetooth: L2CAP: Fix handling LE modes by L2CAP_OPTIONS
+    - nvmet: use new ana_log_size instead the old one
+    - video: hgafb: correctly handle card detect failure during probe
+    - Bluetooth: SMP: Fail if remote and local public keys are identical
+    - Linux 5.4.122
+  * Focal update: v5.4.121 upstream stable release (LP: #1931158)
+    - x86/msr: Fix wr/rdmsr_safe_regs_on_cpu() prototypes
+    - kgdb: fix gcc-11 warning on indentation
+    - usb: sl811-hcd: improve misleading indentation
+    - cxgb4: Fix the -Wmisleading-indentation warning
+    - isdn: capi: fix mismatched prototypes
+    - pinctrl: ingenic: Improve unreachable code generation
+    - xsk: Simplify detection of empty and full rings
+    - virtio_net: Do not pull payload in skb->head
+    - PCI: thunder: Fix compile testing
+    - dmaengine: dw-edma: Fix crash on loading/unloading driver
+    - ARM: 9066/1: ftrace: pause/unpause function graph tracer in cpu_suspend()
+    - ACPI / hotplug / PCI: Fix reference count leak in enable_slot()
+    - Input: elants_i2c - do not bind to i2c-hid compatible ACPI instantiated
+      devices
+    - Input: silead - add workaround for x86 BIOS-es which bring the chip up in a
+      stuck state
+    - um: Mark all kernel symbols as local
+    - um: Disable CONFIG_GCOV with MODULES
+    - ARM: 9075/1: kernel: Fix interrupted SMC calls
+    - scripts/recordmcount.pl: Fix RISC-V regex for clang
+    - riscv: Workaround mcount name prior to clang-13
+    - scsi: lpfc: Fix illegal memory access on Abort IOCBs
+    - ceph: fix fscache invalidation
+    - scsi: target: tcmu: Return from tcmu_handle_completions() if cmd_id not
+      found
+    - bridge: Fix possible races between assigning rx_handler_data and setting
+      IFF_BRIDGE_PORT bit
+    - drm/amd/display: Fix two cursor duplication when using overlay
+    - gpiolib: acpi: Add quirk to ignore EC wakeups on Dell Venue 10 Pro 5055
+    - ALSA: hda: generic: change the DAC ctl name for LO+SPK or LO+HP
+    - block: reexpand iov_iter after read/write
+    - lib: stackdepot: turn depot_lock spinlock to raw_spinlock
+    - net: stmmac: Do not enable RX FIFO overflow interrupts
+    - ip6_gre: proper dev_{hold|put} in ndo_[un]init methods
+    - sit: proper dev_{hold|put} in ndo_[un]init methods
+    - ip6_tunnel: sit: proper dev_{hold|put} in ndo_[un]init methods
+    - ipv6: remove extra dev_hold() for fallback tunnels
+    - KVM: arm64: Initialize VCPU mdcr_el2 before loading it
+    - tweewide: Fix most Shebang lines
+    - scripts: switch explicitly to Python 3
+    - Linux 5.4.121
+  * Focal update: v5.4.120 upstream stable release (LP: #1930474)
+    - tpm: fix error return code in tpm2_get_cc_attrs_tbl()
+    - tpm, tpm_tis: Extend locality handling to TPM2 in tpm_tis_gen_interrupt()
+    - tpm, tpm_tis: Reserve locality in tpm_tis_resume()
+    - KVM: x86/mmu: Remove the defunct update_pte() paging hook
+    - PM: runtime: Fix unpaired parent child_count for force_resume
+    - fs: dlm: fix debugfs dump
+    - tipc: convert dest node's address to network order
+    - ASoC: Intel: bytcr_rt5640: Enable jack-detect support on Asus T100TAF
+    - net: stmmac: Set FIFO sizes for ipq806x
+    - ASoC: rsnd: core: Check convert rate in rsnd_hw_params
+    - i2c: bail out early when RDWR parameters are wrong
+    - ALSA: hdsp: don't disable if not enabled
+    - ALSA: hdspm: don't disable if not enabled
+    - ALSA: rme9652: don't disable if not enabled
+    - ALSA: bebob: enable to deliver MIDI messages for multiple ports
+    - Bluetooth: Set CONF_NOT_COMPLETE as l2cap_chan default
+    - Bluetooth: initialize skb_queue_head at l2cap_chan_create()
+    - net: bridge: when suppression is enabled exclude RARP packets
+    - Bluetooth: check for zapped sk before connecting
+    - ip6_vti: proper dev_{hold|put} in ndo_[un]init methods
+    - ASoC: Intel: bytcr_rt5640: Add quirk for the Chuwi Hi8 tablet
+    - i2c: Add I2C_AQ_NO_REP_START adapter quirk
+    - mac80211: clear the beacon's CRC after channel switch
+    - pinctrl: samsung: use 'int' for register masks in Exynos
+    - mt76: mt76x0: disable GTK offloading
+    - cuse: prevent clone
+    - ASoC: rsnd: call rsnd_ssi_master_clk_start() from rsnd_ssi_init()
+    - Revert "iommu/amd: Fix performance counter initialization"
+    - iommu/amd: Remove performance counter pre-initialization test
+    - drm/amd/display: Force vsync flip when reconfiguring MPCC
+    - selftests: Set CC to clang in lib.mk if LLVM is set
+    - kconfig: nconf: stop endless search loops
+    - ALSA: hda/hdmi: fix race in handling acomp ELD notification at resume
+    - sctp: Fix out-of-bounds warning in sctp_process_asconf_param()
+    - flow_dissector: Fix out-of-bounds warning in __skb_flow_bpf_to_target()
+    - powerpc/smp: Set numa node before updating mask
+    - ASoC: rt286: Generalize support for ALC3263 codec
+    - ethtool: ioctl: Fix out-of-bounds warning in store_link_ksettings_for_user()
+    - net: sched: tapr: prevent cycle_time == 0 in parse_taprio_schedule
+    - samples/bpf: Fix broken tracex1 due to kprobe argument change
+    - powerpc/pseries: Stop calling printk in rtas_stop_self()
+    - drm/amd/display: fixed divide by zero kernel crash during dsc enablement
+    - wl3501_cs: Fix out-of-bounds warnings in wl3501_send_pkt
+    - wl3501_cs: Fix out-of-bounds warnings in wl3501_mgmt_join
+    - qtnfmac: Fix possible buffer overflow in qtnf_event_handle_external_auth
+    - powerpc/iommu: Annotate nested lock for lockdep
+    - iavf: remove duplicate free resources calls
+    - net: ethernet: mtk_eth_soc: fix RX VLAN offload
+    - bnxt_en: Add PCI IDs for Hyper-V VF devices.
+    - ia64: module: fix symbolizer crash on fdescr
+    - ASoC: rt286: Make RT286_SET_GPIO_* readable and writable
+    - thermal: thermal_of: Fix error return code of
+      thermal_of_populate_bind_params()
+    - f2fs: fix a redundant call to f2fs_balance_fs if an error occurs
+    - PCI: iproc: Fix return value of iproc_msi_irq_domain_alloc()
+    - PCI: Release OF node in pci_scan_device()'s error path
+    - ARM: 9064/1: hw_breakpoint: Do not directly check the event's
+      overflow_handler hook
+    - rpmsg: qcom_glink_native: fix error return code of qcom_glink_rx_data()
+    - NFSv4.2: Always flush out writes in nfs42_proc_fallocate()
+    - NFS: Deal correctly with attribute generation counter overflow
+    - PCI: endpoint: Fix missing destroy_workqueue()
+    - pNFS/flexfiles: fix incorrect size check in decode_nfs_fh()
+    - NFSv4.2 fix handling of sr_eof in SEEK's reply
+    - rtc: fsl-ftm-alarm: add MODULE_TABLE()
+    - ceph: fix inode leak on getattr error in __fh_to_dentry
+    - rtc: ds1307: Fix wday settings for rx8130
+    - net: hns3: fix incorrect configuration for igu_egu_hw_err
+    - net: hns3: initialize the message content in hclge_get_link_mode()
+    - net: hns3: add check for HNS3_NIC_STATE_INITED in
+      hns3_reset_notify_up_enet()
+    - net: hns3: fix for vxlan gpe tx checksum bug
+    - net: hns3: use netif_tx_disable to stop the transmit queue
+    - net: hns3: disable phy loopback setting in hclge_mac_start_phy
+    - sctp: do asoc update earlier in sctp_sf_do_dupcook_a
+    - RISC-V: Fix error code returned by riscv_hartid_to_cpuid()
+    - sunrpc: Fix misplaced barrier in call_decode
+    - ethernet:enic: Fix a use after free bug in enic_hard_start_xmit
+    - sctp: fix a SCTP_MIB_CURRESTAB leak in sctp_sf_do_dupcook_b
+    - netfilter: xt_SECMARK: add new revision to fix structure layout
+    - drm/radeon: Fix off-by-one power_state index heap overwrite
+    - drm/radeon: Avoid power table parsing memory leaks
+    - khugepaged: fix wrong result value for trace_mm_collapse_huge_page_isolate()
+    - mm/hugeltb: handle the error case in hugetlb_fix_reserve_counts()
+    - mm/migrate.c: fix potential indeterminate pte entry in
+      migrate_vma_insert_page()
+    - ksm: fix potential missing rmap_item for stable_node
+    - net: fix nla_strcmp to handle more then one trailing null character
+    - smc: disallow TCP_ULP in smc_setsockopt()
+    - netfilter: nfnetlink_osf: Fix a missing skb_header_pointer() NULL check
+    - can: m_can: m_can_tx_work_queue(): fix tx_skb race condition
+    - sched: Fix out-of-bound access in uclamp
+    - sched/fair: Fix unfairness caused by missing load decay
+    - kernel: kexec_file: fix error return code of kexec_calculate_store_digests()
+    - netfilter: nftables: avoid overflows in nft_hash_buckets()
+    - i40e: Fix use-after-free in i40e_client_subtask()
+    - i40e: fix the restart auto-negotiation after FEC modified
+    - i40e: Fix PHY type identifiers for 2.5G and 5G adapters
+    - ARC: entry: fix off-by-one error in syscall number validation
+    - ARC: mm: PAE: use 40-bit physical page mask
+    - powerpc/64s: Fix crashes when toggling stf barrier
+    - powerpc/64s: Fix crashes when toggling entry flush barrier
+    - hfsplus: prevent corruption in shrinking truncate
+    - squashfs: fix divide error in calculate_skip()
+    - userfaultfd: release page in error path to avoid BUG_ON
+    - mm/hugetlb: fix F_SEAL_FUTURE_WRITE
+    - drm/radeon/dpm: Disable sclk switching on Oland when two 4K 60Hz monitors
+      are connected
+    - drm/i915: Avoid div-by-zero on gen2
+    - iio: proximity: pulsedlight: Fix rumtime PM imbalance on error
+    - usb: fotg210-hcd: Fix an error message
+    - hwmon: (occ) Fix poll rate limiting
+    - ACPI: scan: Fix a memory leak in an error handling path
+    - kyber: fix out of bounds access when preempted
+    - nbd: Fix NULL pointer in flush_workqueue
+    - blk-mq: Swap two calls in blk_mq_exit_queue()
+    - iomap: fix sub-page uptodate handling
+    - usb: dwc3: omap: improve extcon initialization
+    - usb: dwc3: pci: Enable usb2-gadget-lpm-disable for Intel Merrifield
+    - usb: xhci: Increase timeout for HC halt
+    - usb: dwc2: Fix gadget DMA unmap direction
+    - usb: core: hub: fix race condition about TRSMRCY of resume
+    - usb: dwc3: gadget: Return success always for kick transfer in ep queue
+    - xhci: Do not use GFP_KERNEL in (potentially) atomic context
+    - xhci: Add reset resume quirk for AMD xhci controller.
+    - iio: gyro: mpu3050: Fix reported temperature value
+    - iio: tsl2583: Fix division by a zero lux_val
+    - cdc-wdm: untangle a circular dependency between callback and softint
+    - KVM: x86: Cancel pvclock_gtod_work on module removal
+    - mm: fix struct page layout on 32-bit systems
+    - FDDI: defxx: Make MMIO the configuration default except for EISA
+    - MIPS: Reinstate platform `__div64_32' handler
+    - MIPS: Avoid DIVU in `__div64_32' is result would be zero
+    - MIPS: Avoid handcoded DIVU in `__div64_32' altogether
+    - thermal/core/fair share: Lock the thermal zone while looping over instances
+    - f2fs: fix error handling in f2fs_end_enable_verity()
+    - ARM: 9011/1: centralize phys-to-virt conversion of DT/ATAGS address
+    - ARM: 9012/1: move device tree mapping out of linear region
+    - ARM: 9020/1: mm: use correct section size macro to describe the FDT virtual
+      address
+    - ARM: 9027/1: head.S: explicitly map DT even if it lives in the first
+      physical section
+    - usb: typec: tcpm: Fix error while calculating PPS out values
+    - kobject_uevent: remove warning in init_uevent_argv()
+    - netfilter: conntrack: Make global sysctls readonly in non-init netns
+    - clk: exynos7: Mark aclk_fsys1_200 as critical
+    - nvme: do not try to reconfigure APST when the controller is not live
+    - ASoC: rsnd: check all BUSIF status when error
+    - Linux 5.4.120
+  * scsi: storvsc: Parameterize number hardware queues (LP: #1930626)
+    - scsi: storvsc: Parameterize number hardware queues
+
+  [ Ubuntu: 5.4.0-77.86 ]
+
+  * UAF on CAN J1939 j1939_can_recv (LP: #1932209)
+    - SAUCE: can: j1939: delay release of j1939_priv after synchronize_rcu
+  * UAF on CAN BCM bcm_rx_handler (LP: #1931855)
+    - SAUCE: can: bcm: delay release of struct bcm_op after synchronize_rcu
+
+  [ Ubuntu: 5.4.0-76.85 ]
+
+  * focal/linux: 5.4.0-76.85 -proposed tracker (LP: #1932123)
+  * Upstream v5.9 introduced 'module' patches that removed exported symbols
+    (LP: #1932065)
+    - SAUCE: Revert "modules: inherit TAINT_PROPRIETARY_MODULE"
+    - SAUCE: Revert "modules: return licensing information from find_symbol"
+    - SAUCE: Revert "modules: rename the licence field in struct symsearch to
+      license"
+    - SAUCE: Revert "modules: unexport __module_address"
+    - SAUCE: Revert "modules: unexport __module_text_address"
+    - SAUCE: Revert "modules: mark each_symbol_section static"
+    - SAUCE: Revert "modules: mark find_symbol static"
+    - SAUCE: Revert "modules: mark ref_module static"
+
+  [ Ubuntu: 5.4.0-75.84 ]
+
+  * focal/linux: 5.4.0-75.84 -proposed tracker (LP: #1930032)
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+  * CVE-2021-33200
+    - bpf: Wrap aux data inside bpf_sanitize_info container
+    - bpf: Fix mask direction swap upon off reg sign change
+    - bpf: No need to simulate speculative domain for immediates
+  * Realtek USB hubs in Dell WD19SC/DC/TB fail to work after exiting s2idle
+    (LP: #1928242)
+    - USB: Verify the port status when timeout happens during port suspend
+  * CVE-2020-26145
+    - ath10k: drop fragments with multicast DA for SDIO
+    - ath10k: add CCMP PN replay protection for fragmented frames for PCIe
+    - ath10k: drop fragments with multicast DA for PCIe
+  * CVE-2020-26141
+    - ath10k: Fix TKIP Michael MIC verification for PCIe
+  * CVE-2020-24588
+    - mac80211: properly handle A-MSDUs that start with an RFC 1042 header
+    - cfg80211: mitigate A-MSDU aggregation attacks
+    - mac80211: drop A-MSDUs on old ciphers
+    - ath10k: drop MPDU which has discard flag set by firmware for SDIO
+  * CVE-2020-26139
+    - mac80211: do not accept/forward invalid EAPOL frames
+  * CVE-2020-24586 // CVE-2020-24587 // CVE-2020-24587 for such cases.
+    - mac80211: extend protection against mixed key and fragment cache attacks
+  * CVE-2020-24586 // CVE-2020-24587
+    - mac80211: prevent mixed key and fragment cache attacks
+    - mac80211: add fragment cache to sta_info
+    - mac80211: check defrag PN against current frame
+    - mac80211: prevent attacks on TKIP/WEP as well
+  * CVE-2020-26147
+    - mac80211: assure all fragments are encrypted
+  * raid10: Block discard is very slow, causing severe delays for mkfs and
+    fstrim operations (LP: #1896578)
+    - md: add md_submit_discard_bio() for submitting discard bio
+    - md/raid10: extend r10bio devs to raid disks
+    - md/raid10: pull the code that wait for blocked dev into one function
+    - md/raid10: improve raid10 discard request
+    - md/raid10: improve discard request for far layout
+    - dm raid: remove unnecessary discard limits for raid0 and raid10
+  * [SRU] mpt3sas: only one vSES is handy even IOC has multi vSES (LP: #1926517)
+    - scsi: mpt3sas: Only one vSES is present even when IOC has multi vSES
+  * kvm: properly tear down PV features on hibernate (LP: #1920944)
+    - x86/kvm: Fix pr_info() for async PF setup/teardown
+    - x86/kvm: Teardown PV features on boot CPU as well
+    - x86/kvm: Disable kvmclock on all CPUs on shutdown
+    - x86/kvm: Disable all PV features on crash
+    - x86/kvm: Unify kvm_pv_guest_cpu_reboot() with kvm_guest_cpu_offline()
+  * Focal update: v5.4.119 upstream stable release (LP: #1929615)
+    - Bluetooth: verify AMP hci_chan before amp_destroy
+    - hsr: use netdev_err() instead of WARN_ONCE()
+    - bluetooth: eliminate the potential race condition when removing the HCI
+      controller
+    - net/nfc: fix use-after-free llcp_sock_bind/connect
+    - Revert "USB: cdc-acm: fix rounding error in TIOCSSERIAL"
+    - tty: moxa: fix TIOCSSERIAL jiffies conversions
+    - tty: amiserial: fix TIOCSSERIAL permission check
+    - USB: serial: usb_wwan: fix TIOCSSERIAL jiffies conversions
+    - staging: greybus: uart: fix TIOCSSERIAL jiffies conversions
+    - USB: serial: ti_usb_3410_5052: fix TIOCSSERIAL permission check
+    - staging: fwserial: fix TIOCSSERIAL jiffies conversions
+    - tty: moxa: fix TIOCSSERIAL permission check
+    - staging: fwserial: fix TIOCSSERIAL permission check
+    - usb: typec: tcpm: Address incorrect values of tcpm psy for fixed supply
+    - usb: typec: tcpm: Address incorrect values of tcpm psy for pps supply
+    - usb: typec: tcpm: update power supply once partner accepts
+    - usb: xhci-mtk: remove or operator for setting schedule parameters
+    - usb: xhci-mtk: improve bandwidth scheduling with TT
+    - ASoC: samsung: tm2_wm5110: check of of_parse return value
+    - ASoC: Intel: kbl_da7219_max98927: Fix kabylake_ssp_fixup function
+    - MIPS: pci-mt7620: fix PLL lock check
+    - MIPS: pci-rt2880: fix slot 0 configuration
+    - FDDI: defxx: Bail out gracefully with unassigned PCI resource for CSR
+    - PCI: Allow VPD access for QLogic ISP2722
+    - iio:accel:adis16201: Fix wrong axis assignment that prevents loading
+    - misc: lis3lv02d: Fix false-positive WARN on various HP models
+    - misc: vmw_vmci: explicitly initialize vmci_notify_bm_set_msg struct
+    - misc: vmw_vmci: explicitly initialize vmci_datagram payload
+    - md/bitmap: wait for external bitmap writes to complete during tear down
+    - md-cluster: fix use-after-free issue when removing rdev
+    - md: split mddev_find
+    - md: factor out a mddev_find_locked helper from mddev_find
+    - md: md_open returns -EBUSY when entering racing area
+    - md: Fix missing unused status line of /proc/mdstat
+    - ipw2x00: potential buffer overflow in libipw_wx_set_encodeext()
+    - cfg80211: scan: drop entry from hidden_list on overflow
+    - rtw88: Fix array overrun in rtw_get_tx_power_params()
+    - drm/panfrost: Clear MMU irqs before handling the fault
+    - drm/panfrost: Don't try to map pages that are already mapped
+    - drm/radeon: fix copy of uninitialized variable back to userspace
+    - drm/amd/display: Reject non-zero src_y and src_x for video planes
+    - ALSA: hda/realtek: Re-order ALC882 Acer quirk table entries
+    - ALSA: hda/realtek: Re-order ALC882 Sony quirk table entries
+    - ALSA: hda/realtek: Re-order ALC882 Clevo quirk table entries
+    - ALSA: hda/realtek: Re-order ALC269 HP quirk table entries
+    - ALSA: hda/realtek: Re-order ALC269 Acer quirk table entries
+    - ALSA: hda/realtek: Re-order ALC269 Dell quirk table entries
+    - ALSA: hda/realtek: Re-order ALC269 ASUS quirk table entries
+    - ALSA: hda/realtek: Re-order ALC269 Sony quirk table entries
+    - ALSA: hda/realtek: Re-order ALC269 Lenovo quirk table entries
+    - ALSA: hda/realtek: Re-order remaining ALC269 quirk table entries
+    - ALSA: hda/realtek: Re-order ALC662 quirk table entries
+    - ALSA: hda/realtek: Remove redundant entry for ALC861 Haier/Uniwill devices
+    - ALSA: hda/realtek: ALC285 Thinkpad jack pin quirk is unreachable
+    - KVM: s390: split kvm_s390_logical_to_effective
+    - KVM: s390: fix guarded storage control register handling
+    - s390: fix detection of vector enhancements facility 1 vs. vector packed
+      decimal facility
+    - KVM: s390: split kvm_s390_real_to_abs
+    - KVM: nVMX: Truncate bits 63:32 of VMCS field on nested check in !64-bit
+    - KVM: Stop looking for coalesced MMIO zones if the bus is destroyed
+    - Revert "i3c master: fix missing destroy_workqueue() on error in
+      i3c_master_register"
+    - ovl: fix missing revert_creds() on error path
+    - usb: gadget: pch_udc: Revert d3cb25a12138 completely
+    - memory: gpmc: fix out of bounds read and dereference on gpmc_cs[]
+    - ARM: dts: exynos: correct fuel gauge interrupt trigger level on Midas family
+    - ARM: dts: exynos: correct MUIC interrupt trigger level on Midas family
+    - ARM: dts: exynos: correct PMIC interrupt trigger level on Midas family
+    - ARM: dts: exynos: correct PMIC interrupt trigger level on Odroid X/U3 family
+    - ARM: dts: exynos: correct PMIC interrupt trigger level on SMDK5250
+    - ARM: dts: exynos: correct PMIC interrupt trigger level on Snow
+    - serial: stm32: fix incorrect characters on console
+    - serial: stm32: fix tx_empty condition
+    - usb: typec: tcpci: Check ROLE_CONTROL while interpreting CC_STATUS
+    - regmap: set debugfs_name to NULL after it is freed
+    - mtd: rawnand: fsmc: Fix error code in fsmc_nand_probe()
+    - mtd: rawnand: brcmnand: fix OOB R/W with Hamming ECC
+    - mtd: Handle possible -EPROBE_DEFER from parse_mtd_partitions()
+    - mtd: rawnand: qcom: Return actual error code instead of -ENODEV
+    - arm64: dts: qcom: sm8150: fix number of pins in 'gpio-ranges'
+    - spi: stm32: drop devres version of spi_register_master
+    - arm64: dts: renesas: r8a77980: Fix vin4-7 endpoint binding
+    - x86/microcode: Check for offline CPUs before requesting new microcode
+    - usb: gadget: pch_udc: Replace cpu_to_le32() by lower_32_bits()
+    - usb: gadget: pch_udc: Check if driver is present before calling ->setup()
+    - usb: gadget: pch_udc: Check for DMA mapping error
+    - crypto: qat - don't release uninitialized resources
+    - crypto: qat - ADF_STATUS_PF_RUNNING should be set after adf_dev_init
+    - fotg210-udc: Fix DMA on EP0 for length > max packet size
+    - fotg210-udc: Fix EP0 IN requests bigger than two packets
+    - fotg210-udc: Remove a dubious condition leading to fotg210_done
+    - fotg210-udc: Mask GRP2 interrupts we don't handle
+    - fotg210-udc: Don't DMA more than the buffer can take
+    - fotg210-udc: Complete OUT requests on short packets
+    - mtd: require write permissions for locking and badblock ioctls
+    - bus: qcom: Put child node before return
+    - soundwire: bus: Fix device found flag correctly
+    - phy: marvell: ARMADA375_USBCLUSTER_PHY should not default to y,
+      unconditionally
+    - crypto: qat - fix error path in adf_isr_resource_alloc()
+    - usb: gadget: aspeed: fix dma map failure
+    - USB: gadget: udc: fix wrong pointer passed to IS_ERR() and PTR_ERR()
+    - memory: pl353: fix mask of ECC page_size config register
+    - soundwire: stream: fix memory leak in stream config error path
+    - m68k: mvme147,mvme16x: Don't wipe PCC timer config bits
+    - mtd: rawnand: gpmi: Fix a double free in gpmi_nand_init
+    - irqchip/gic-v3: Fix OF_BAD_ADDR error handling
+    - staging: rtl8192u: Fix potential infinite loop
+    - staging: greybus: uart: fix unprivileged TIOCCSERIAL
+    - PM / devfreq: Use more accurate returned new_freq as resume_freq
+    - spi: Fix use-after-free with devm_spi_alloc_*
+    - soc: qcom: mdt_loader: Validate that p_filesz < p_memsz
+    - soc: qcom: mdt_loader: Detect truncated read of segments
+    - ACPI: CPPC: Replace cppc_attr with kobj_attribute
+    - crypto: qat - Fix a double free in adf_create_ring
+    - cpufreq: armada-37xx: Fix setting TBG parent for load levels
+    - clk: mvebu: armada-37xx-periph: remove .set_parent method for CPU PM clock
+    - cpufreq: armada-37xx: Fix the AVS value for load L1
+    - clk: mvebu: armada-37xx-periph: Fix switching CPU freq from 250 Mhz to 1 GHz
+    - clk: mvebu: armada-37xx-periph: Fix workaround for switching from L1 to L0
+    - cpufreq: armada-37xx: Fix driver cleanup when registration failed
+    - cpufreq: armada-37xx: Fix determining base CPU frequency
+    - spi: fsl-lpspi: Fix PM reference leak in lpspi_prepare_xfer_hardware()
+    - usb: gadget: r8a66597: Add missing null check on return from
+      platform_get_resource
+    - USB: cdc-acm: fix unprivileged TIOCCSERIAL
+    - USB: cdc-acm: fix TIOCGSERIAL implementation
+    - tty: fix return value for unsupported ioctls
+    - serial: core: return early on unsupported ioctls
+    - firmware: qcom-scm: Fix QCOM_SCM configuration
+    - node: fix device cleanups in error handling code
+    - usbip: vudc: fix missing unlock on error in usbip_sockfd_store()
+    - platform/x86: pmc_atom: Match all Beckhoff Automation baytrail boards with
+      critclk_systems DMI table
+    - x86/platform/uv: Fix !KEXEC build failure
+    - usb: dwc2: Fix host mode hibernation exit with remote wakeup flow.
+    - usb: dwc2: Fix hibernation between host and device modes.
+    - ttyprintk: Add TTY hangup callback.
+    - xen-blkback: fix compatibility bug with single page rings
+    - soc: aspeed: fix a ternary sign expansion bug
+    - media: vivid: fix assignment of dev->fbuf_out_flags
+    - media: omap4iss: return error code when omap4iss_get() failed
+    - media: aspeed: fix clock handling logic
+    - media: platform: sunxi: sun6i-csi: fix error return code of
+      sun6i_video_start_streaming()
+    - media: m88rs6000t: avoid potential out-of-bounds reads on arrays
+    - drm/amdkfd: fix build error with AMD_IOMMU_V2=m
+    - x86/kprobes: Fix to check non boostable prefixes correctly
+    - pata_arasan_cf: fix IRQ check
+    - pata_ipx4xx_cf: fix IRQ check
+    - sata_mv: add IRQ checks
+    - ata: libahci_platform: fix IRQ check
+    - nvme-tcp: block BH in sk state_change sk callback
+    - nvmet-tcp: fix incorrect locking in state_change sk callback
+    - nvme: retrigger ANA log update if group descriptor isn't found
+    - media: v4l2-ctrls.c: fix race condition in hdl->requests list
+    - vfio/mdev: Do not allow a mdev_type to have a NULL parent pointer
+    - clk: zynqmp: move zynqmp_pll_set_mode out of round_rate callback
+    - clk: qcom: a53-pll: Add missing MODULE_DEVICE_TABLE
+    - clk: uniphier: Fix potential infinite loop
+    - scsi: hisi_sas: Fix IRQ checks
+    - scsi: jazz_esp: Add IRQ check
+    - scsi: sun3x_esp: Add IRQ check
+    - scsi: sni_53c710: Add IRQ check
+    - scsi: ibmvfc: Fix invalid state machine BUG_ON()
+    - mfd: stm32-timers: Avoid clearing auto reload register
+    - nvme-pci: don't simple map sgl when sgls are disabled
+    - HSI: core: fix resource leaks in hsi_add_client_from_dt()
+    - x86/events/amd/iommu: Fix sysfs type mismatch
+    - sched/debug: Fix cgroup_path[] serialization
+    - drivers/block/null_blk/main: Fix a double free in null_init.
+    - HID: plantronics: Workaround for double volume key presses
+    - perf symbols: Fix dso__fprintf_symbols_by_name() to return the number of
+      printed chars
+    - net: lapbether: Prevent racing when checking whether the netif is running
+    - powerpc/fadump: Mark fadump_calculate_reserve_size as __init
+    - powerpc/prom: Mark identical_pvr_fixup as __init
+    - inet: use bigger hash table for IP ID generation
+    - powerpc: Fix HAVE_HARDLOCKUP_DETECTOR_ARCH build configuration
+    - ALSA: core: remove redundant spin_lock pair in snd_card_disconnect
+    - bug: Remove redundant condition check in report_bug
+    - nfc: pn533: prevent potential memory corruption
+    - net: hns3: Limiting the scope of vector_ring_chain variable
+    - mips: bmips: fix syscon-reboot nodes
+    - ALSA: usb-audio: Add error checks for usb_driver_claim_interface() calls
+    - ASoC: simple-card: fix possible uninitialized single_cpu local variable
+    - liquidio: Fix unintented sign extension of a left shift of a u16
+    - powerpc/64s: Fix pte update for kernel memory on radix
+    - powerpc/perf: Fix PMU constraint check for EBB events
+    - powerpc: iommu: fix build when neither PCI or IBMVIO is set
+    - mac80211: bail out if cipher schemes are invalid
+    - mt7601u: fix always true expression
+    - KVM: PPC: Book3S HV P9: Restore host CTRL SPR after guest exit
+    - RDMA/qedr: Fix error return code in qedr_iw_connect()
+    - IB/hfi1: Fix error return code in parse_platform_config()
+    - cxgb4: Fix unintentional sign extension issues
+    - net: thunderx: Fix unintentional sign extension issue
+    - RDMA/srpt: Fix error return code in srpt_cm_req_recv()
+    - i2c: img-scb: fix reference leak when pm_runtime_get_sync fails
+    - i2c: imx-lpi2c: fix reference leak when pm_runtime_get_sync fails
+    - i2c: omap: fix reference leak when pm_runtime_get_sync fails
+    - i2c: sprd: fix reference leak when pm_runtime_get_sync fails
+    - i2c: cadence: add IRQ check
+    - i2c: emev2: add IRQ check
+    - i2c: jz4780: add IRQ check
+    - i2c: sh7760: add IRQ check
+    - powerpc/xive: Fix xmon command "dxi"
+    - ASoC: ak5558: correct reset polarity
+    - drm/i915/gvt: Fix error code in intel_gvt_init_device()
+    - perf beauty: Fix fsconfig generator
+    - MIPS: pci-legacy: stop using of_pci_range_to_resource
+    - powerpc/pseries: extract host bridge from pci_bus prior to bus removal
+    - rtlwifi: 8821ae: upgrade PHY and RF parameters
+    - i2c: sh7760: fix IRQ error path
+    - mwl8k: Fix a double Free in mwl8k_probe_hw
+    - vsock/vmci: log once the failed queue pair allocation
+    - gro: fix napi_gro_frags() Fast GRO breakage due to IP alignment check
+    - RDMA/cxgb4: add missing qpid increment
+    - RDMA/i40iw: Fix error unwinding when i40iw_hmc_sd_one fails
+    - ALSA: usb: midi: don't return -ENOMEM when usb_urb_ep_type_check fails
+    - net: davinci_emac: Fix incorrect masking of tx and rx error channel
+    - net: renesas: ravb: Fix a stuck issue when a lot of frames are received
+    - net: phy: intel-xway: enable integrated led functions
+    - ath9k: Fix error check in ath9k_hw_read_revisions() for PCI devices
+    - ath10k: Fix ath10k_wmi_tlv_op_pull_peer_stats_info() unlock without lock
+    - powerpc/52xx: Fix an invalid ASM expression ('addi' used instead of 'add')
+    - bnxt_en: fix ternary sign extension bug in bnxt_show_temp()
+    - ARM: dts: uniphier: Change phy-mode to RGMII-ID to enable delay pins for
+      RTL8211E
+    - arm64: dts: uniphier: Change phy-mode to RGMII-ID to enable delay pins for
+      RTL8211E
+    - net: geneve: modify IP header check in geneve6_xmit_skb and geneve_xmit_skb
+    - selftests: net: mirror_gre_vlan_bridge_1q: Make an FDB entry static
+    - bnxt_en: Fix RX consumer index logic in the error path.
+    - net:emac/emac-mac: Fix a use after free in emac_mac_tx_buf_send
+    - RDMA/siw: Fix a use after free in siw_alloc_mr
+    - RDMA/bnxt_re: Fix a double free in bnxt_qplib_alloc_res
+    - net: bridge: mcast: fix broken length + header check for MRDv6 Adv.
+    - net:nfc:digital: Fix a double free in digital_tg_recv_dep_req
+    - kfifo: fix ternary sign extension bugs
+    - mm/sparse: add the missing sparse_buffer_fini() in error branch
+    - mm/memory-failure: unnecessary amount of unmapping
+    - net: Only allow init netns to set default tcp cong to a restricted algo
+    - smp: Fix smp_call_function_single_async prototype
+    - Revert "net/sctp: fix race condition in sctp_destroy_sock"
+    - sctp: delay auto_asconf init until binding the first addr
+    - Revert "of/fdt: Make sure no-map does not remove already reserved regions"
+    - Revert "fdt: Properly handle "no-map" field in the memory region"
+    - Linux 5.4.119
+  * seccomp_bpf:syscall_faked from kselftests fail on s390x (LP: #1928522)
+    - selftests/seccomp: s390 shares the syscall and return value register
+  * Can't detect intel wifi 6235 (LP: #1920180)
+    - SAUCE: iwlwifi: add new pci id for 6235
+  * Mark kprobe_args_user.tc in kselftest/ftrace as unsupported (LP: #1929527)
+    - selftests/ftrace: Return unsupported for the unconfigured features
+  * pmtu.sh from net in ubuntu_kernel_selftests failed with no error message
+    (LP: #1887661)
+    - selftests: pmtu.sh: use $ksft_skip for skipped return code
+  * alsa/sof: make sof driver work in the case of without i915 (focal kernel)
+    (LP: #1927672)
+    - SAUCE: ASoC: SOF: Intel: hda: move the probe_bus ahead of creation of mach
+      device
+  * Fix kdump failures (LP: #1927518)
+    - video: hyperv_fb: Add ratelimit on error message
+    - Drivers: hv: vmbus: Increase wait time for VMbus unload
+    - Drivers: hv: vmbus: Initialize unload_event statically
+  * Ubuntu 20.04 - 'Support flow counters offset for bulk counters'
+    (LP: #1922494)
+    - IB/mlx5: Support flow counters offset for bulk counters
+  * Focal update: v5.4.118 upstream stable release (LP: #1928825)
+    - s390/disassembler: increase ebpf disasm buffer size
+    - ACPI: custom_method: fix potential use-after-free issue
+    - ACPI: custom_method: fix a possible memory leak
+    - ftrace: Handle commands when closing set_ftrace_filter file
+    - ARM: 9056/1: decompressor: fix BSS size calculation for LLVM ld.lld
+    - arm64: dts: marvell: armada-37xx: add syscon compatible to NB clk node
+    - arm64: dts: mt8173: fix property typo of 'phys' in dsi node
+    - ecryptfs: fix kernel panic with null dev_name
+    - mtd: spinand: core: add missing MODULE_DEVICE_TABLE()
+    - mtd: rawnand: atmel: Update ecc_stats.corrected counter
+    - erofs: add unsupported inode i_format check
+    - spi: spi-ti-qspi: Free DMA resources
+    - scsi: qla2xxx: Fix crash in qla2xxx_mqueuecommand()
+    - scsi: mpt3sas: Block PCI config access from userspace during reset
+    - mmc: uniphier-sd: Fix an error handling path in uniphier_sd_probe()
+    - mmc: uniphier-sd: Fix a resource leak in the remove function
+    - mmc: sdhci: Check for reset prior to DMA address unmap
+    - mmc: sdhci-pci: Fix initialization of some SD cards for Intel BYT-based
+      controllers
+    - mmc: block: Update ext_csd.cache_ctrl if it was written
+    - mmc: block: Issue a cache flush only when it's enabled
+    - mmc: core: Do a power cycle when the CMD11 fails
+    - mmc: core: Set read only for SD cards with permanent write protect bit
+    - mmc: core: Fix hanging on I/O during system suspend for removable cards
+    - modules: mark ref_module static
+    - modules: mark find_symbol static
+    - modules: mark each_symbol_section static
+    - modules: unexport __module_text_address
+    - modules: unexport __module_address
+    - modules: rename the licence field in struct symsearch to license
+    - modules: return licensing information from find_symbol
+    - modules: inherit TAINT_PROPRIETARY_MODULE
+    - irqchip/gic-v3: Do not enable irqs when handling spurious interrups
+    - cifs: Return correct error code from smb2_get_enc_key
+    - btrfs: fix metadata extent leak after failure to create subvolume
+    - intel_th: pci: Add Rocket Lake CPU support
+    - posix-timers: Preserve return value in clock_adjtime32()
+    - fbdev: zero-fill colormap in fbcmap.c
+    - bus: ti-sysc: Probe for l4_wkup and l4_cfg interconnect devices first
+    - staging: wimax/i2400m: fix byte-order issue
+    - spi: ath79: always call chipselect function
+    - spi: ath79: remove spi-master setup and cleanup assignment
+    - crypto: api - check for ERR pointers in crypto_destroy_tfm()
+    - crypto: qat - fix unmap invalid dma address
+    - usb: gadget: uvc: add bInterval checking for HS mode
+    - usb: webcam: Invalid size of Processing Unit Descriptor
+    - genirq/matrix: Prevent allocation counter corruption
+    - usb: gadget: f_uac2: validate input parameters
+    - usb: gadget: f_uac1: validate input parameters
+    - usb: dwc3: gadget: Ignore EP queue requests during bus reset
+    - usb: xhci: Fix port minor revision
+    - PCI: PM: Do not read power state in pci_enable_device_flags()
+    - x86/build: Propagate $(CLANG_FLAGS) to $(REALMODE_FLAGS)
+    - tee: optee: do not check memref size on return from Secure World
+    - perf/arm_pmu_platform: Fix error handling
+    - usb: xhci-mtk: support quirk to disable usb2 lpm
+    - xhci: check control context is valid before dereferencing it.
+    - xhci: fix potential array out of bounds with several interrupters
+    - spi: dln2: Fix reference leak to master
+    - spi: omap-100k: Fix reference leak to master
+    - spi: qup: fix PM reference leak in spi_qup_remove()
+    - usb: musb: fix PM reference leak in musb_irq_work()
+    - usb: core: hub: Fix PM reference leak in usb_port_resume()
+    - tty: n_gsm: check error while registering tty devices
+    - intel_th: Consistency and off-by-one fix
+    - phy: phy-twl4030-usb: Fix possible use-after-free in twl4030_usb_remove()
+    - crypto: stm32/hash - Fix PM reference leak on stm32-hash.c
+    - crypto: stm32/cryp - Fix PM reference leak on stm32-cryp.c
+    - crypto: omap-aes - Fix PM reference leak on omap-aes.c
+    - platform/x86: intel_pmc_core: Don't use global pmcdev in quirks
+    - btrfs: convert logic BUG_ON()'s in replace_path to ASSERT()'s
+    - drm: Added orientation quirk for OneGX1 Pro
+    - drm/qxl: release shadow on shutdown
+    - drm/amd/display: Check for DSC support instead of ASIC revision
+    - drm/amd/display: Don't optimize bandwidth before disabling planes
+    - scsi: lpfc: Fix incorrect dbde assignment when building target abts wqe
+    - scsi: lpfc: Fix pt2pt connection does not recover after LOGO
+    - scsi: target: pscsi: Fix warning in pscsi_complete_cmd()
+    - media: ite-cir: check for receive overflow
+    - media: drivers: media: pci: sta2x11: fix Kconfig dependency on GPIOLIB
+    - media: imx: capture: Return -EPIPE from __capture_legacy_try_fmt()
+    - power: supply: bq27xxx: fix power_avg for newer ICs
+    - extcon: arizona: Fix some issues when HPDET IRQ fires after the jack has
+      been unplugged
+    - extcon: arizona: Fix various races on driver unbind
+    - media: media/saa7164: fix saa7164_encoder_register() memory leak bugs
+    - media: gspca/sq905.c: fix uninitialized variable
+    - power: supply: Use IRQF_ONESHOT
+    - drm/amdgpu: mask the xgmi number of hops reported from psp to kfd
+    - drm/amdkfd: Fix UBSAN shift-out-of-bounds warning
+    - drm/amdgpu : Fix asic reset regression issue introduce by 8f211fe8ac7c4f
+    - drm/amd/display: Fix UBSAN warning for not a valid value for type '_Bool'
+    - drm/amd/display: fix dml prefetch validation
+    - scsi: qla2xxx: Always check the return value of qla24xx_get_isp_stats()
+    - drm/vkms: fix misuse of WARN_ON
+    - scsi: qla2xxx: Fix use after free in bsg
+    - mmc: sdhci-pci: Add PCI IDs for Intel LKF
+    - ata: ahci: Disable SXS for Hisilicon Kunpeng920
+    - scsi: smartpqi: Correct request leakage during reset operations
+    - scsi: smartpqi: Add new PCI IDs
+    - scsi: scsi_dh_alua: Remove check for ASC 24h in alua_rtpg()
+    - media: em28xx: fix memory leak
+    - media: vivid: update EDID
+    - clk: socfpga: arria10: Fix memory leak of socfpga_clk on error return
+    - power: supply: generic-adc-battery: fix possible use-after-free in
+      gab_remove()
+    - power: supply: s3c_adc_battery: fix possible use-after-free in
+      s3c_adc_bat_remove()
+    - media: tc358743: fix possible use-after-free in tc358743_remove()
+    - media: adv7604: fix possible use-after-free in adv76xx_remove()
+    - media: i2c: adv7511-v4l2: fix possible use-after-free in adv7511_remove()
+    - media: i2c: tda1997: Fix possible use-after-free in tda1997x_remove()
+    - media: i2c: adv7842: fix possible use-after-free in adv7842_remove()
+    - media: platform: sti: Fix runtime PM imbalance in regs_show
+    - media: dvb-usb: fix memory leak in dvb_usb_adapter_init
+    - media: gscpa/stv06xx: fix memory leak
+    - sched/fair: Ignore percpu threads for imbalance pulls
+    - drm/msm/mdp5: Configure PP_SYNC_HEIGHT to double the vtotal
+    - drm/msm/mdp5: Do not multiply vclk line count by 100
+    - drm/amdkfd: Fix cat debugfs hang_hws file causes system crash bug
+    - amdgpu: avoid incorrect %hu format string
+    - drm/amdgpu: fix NULL pointer dereference
+    - scsi: lpfc: Fix crash when a REG_RPI mailbox fails triggering a LOGO
+      response
+    - scsi: lpfc: Fix error handling for mailboxes completed in MBX_POLL mode
+    - scsi: lpfc: Remove unsupported mbox PORT_CAPABILITIES logic
+    - mfd: arizona: Fix rumtime PM imbalance on error
+    - scsi: libfc: Fix a format specifier
+    - s390/archrandom: add parameter check for s390_arch_random_generate
+    - ALSA: emu8000: Fix a use after free in snd_emu8000_create_mixer
+    - ALSA: hda/conexant: Re-order CX5066 quirk table entries
+    - ALSA: sb: Fix two use after free in snd_sb_qsound_build
+    - ALSA: usb-audio: Explicitly set up the clock selector
+    - ALSA: usb-audio: More constifications
+    - ALSA: usb-audio: Add dB range mapping for Sennheiser Communications Headset
+      PC 8
+    - ALSA: hda/realtek: GA503 use same quirks as GA401
+    - ALSA: hda/realtek: fix mic boost on Intel NUC 8
+    - ALSA: hda/realtek: fix static noise on ALC285 Lenovo laptops
+    - ALSA: hda/realtek: Add quirk for Intel Clevo PCx0Dx
+    - btrfs: fix race when picking most recent mod log operation for an old root
+    - arm64/vdso: Discard .note.gnu.property sections in vDSO
+    - Makefile: Move -Wno-unused-but-set-variable out of GCC only block
+    - virtiofs: fix memory leak in virtio_fs_probe()
+    - ubifs: Only check replay with inode type to judge if inode linked
+    - f2fs: fix to avoid out-of-bounds memory access
+    - mlxsw: spectrum_mr: Update egress RIF list before route's action
+    - openvswitch: fix stack OOB read while fragmenting IPv4 packets
+    - ACPI: GTDT: Don't corrupt interrupt mappings on watchdow probe failure
+    - NFS: Don't discard pNFS layout segments that are marked for return
+    - NFSv4: Don't discard segments marked for return in _pnfs_return_layout()
+    - Input: ili210x - add missing negation for touch indication on ili210x
+    - jffs2: Fix kasan slab-out-of-bounds problem
+    - powerpc/eeh: Fix EEH handling for hugepages in ioremap space.
+    - powerpc: fix EDEADLOCK redefinition error in uapi/asm/errno.h
+    - intel_th: pci: Add Alder Lake-M support
+    - tpm: efi: Use local variable for calculating final log size
+    - tpm: vtpm_proxy: Avoid reading host log when using a virtual device
+    - crypto: rng - fix crypto_rng_reset() refcounting when !CRYPTO_STATS
+    - md/raid1: properly indicate failure when ending a failed write request
+    - dm raid: fix inconclusive reshape layout on fast raid4/5/6 table reload
+      sequences
+    - fuse: fix write deadlock
+    - security: commoncap: fix -Wstringop-overread warning
+    - Fix misc new gcc warnings
+    - jffs2: check the validity of dstlen in jffs2_zlib_compress()
+    - Revert 337f13046ff0 ("futex: Allow FUTEX_CLOCK_REALTIME with FUTEX_WAIT op")
+    - x86/cpu: Initialize MSR_TSC_AUX if RDTSCP *or* RDPID is supported
+    - kbuild: update config_data.gz only when the content of .config is changed
+    - ext4: fix check to prevent false positive report of incorrect used inodes
+    - ext4: do not set SB_ACTIVE in ext4_orphan_cleanup()
+    - ext4: fix error code in ext4_commit_super
+    - media: dvbdev: Fix memory leak in dvb_media_device_free()
+    - media: dvb-usb: Fix use-after-free access
+    - media: dvb-usb: Fix memory leak at error in dvb_usb_device_init()
+    - media: staging/intel-ipu3: Fix memory leak in imu_fmt
+    - media: staging/intel-ipu3: Fix set_fmt error handling
+    - media: staging/intel-ipu3: Fix race condition during set_fmt
+    - usb: gadget: dummy_hcd: fix gpf in gadget_setup
+    - usb: gadget: Fix double free of device descriptor pointers
+    - usb: gadget/function/f_fs string table fix for multiple languages
+    - usb: dwc3: gadget: Fix START_TRANSFER link state check
+    - usb: dwc2: Fix session request interrupt handler
+    - tty: fix memory leak in vc_deallocate
+    - rsi: Use resume_noirq for SDIO
+    - tracing: Map all PIDs to command lines
+    - tracing: Restructure trace_clock_global() to never block
+    - dm persistent data: packed struct should have an aligned() attribute too
+    - dm space map common: fix division bug in sm_ll_find_free_block()
+    - dm integrity: fix missing goto in bitmap_flush_interval error handling
+    - dm rq: fix double free of blk_mq_tag_set in dev remove after table load
+      fails
+    - Linux 5.4.118
+  * Focal update: v5.4.117 upstream stable release (LP: #1928823)
+    - mips: Do not include hi and lo in clobber list for R6
+    - ACPI: tables: x86: Reserve memory occupied by ACPI tables
+    - ACPI: x86: Call acpi_boot_table_init() after acpi_table_upgrade()
+    - net: usb: ax88179_178a: initialize local variables before use
+    - igb: Enable RSS for Intel I211 Ethernet Controller
+    - iwlwifi: Fix softirq/hardirq disabling in iwl_pcie_enqueue_hcmd()
+    - bpf: Fix masking negation logic upon negative dst register
+    - bpf: Fix leakage of uninitialized bpf stack under speculation
+    - avoid __memcat_p link failure
+    - iwlwifi: Fix softirq/hardirq disabling in iwl_pcie_gen2_enqueue_hcmd()
+    - perf data: Fix error return code in perf_data__create_dir()
+    - perf ftrace: Fix access to pid in array when setting a pid filter
+    - ALSA: usb-audio: Add MIDI quirk for Vox ToneLab EX
+    - USB: Add reset-resume quirk for WD19's Realtek Hub
+    - platform/x86: thinkpad_acpi: Correct thermal sensor allocation
+    - scsi: ufs: Unlock on a couple error paths
+    - ovl: allow upperdir inside lowerdir
+    - perf/core: Fix unconditional security_locked_down() call
+    - vfio: Depend on MMU
+    - Linux 5.4.117
+  * r8152 tx status -71 (LP: #1922651) // Focal update: v5.4.117 upstream stable
+    release (LP: #1928823)
+    - USB: Add LPM quirk for Lenovo ThinkPad USB-C Dock Gen2 Ethernet
+  * Focal update: v5.4.116 upstream stable release (LP: #1928821)
+    - bpf: Move off_reg into sanitize_ptr_alu
+    - bpf: Ensure off_reg has no mixed signed bounds for all types
+    - bpf: Rework ptr_limit into alu_limit and add common error path
+    - bpf: Improve verifier error messages for users
+    - bpf: Refactor and streamline bounds check into helper
+    - bpf: Move sanitize_val_alu out of op switch
+    - bpf: Tighten speculative pointer arithmetic mask
+    - bpf: Update selftests to reflect new error states
+    - Linux 5.4.116
+  * Focal update: v5.4.115 upstream stable release (LP: #1927997)
+    - gpio: omap: Save and restore sysconfig
+    - pinctrl: lewisburg: Update number of pins in community
+    - arm64: dts: allwinner: Revert SD card CD GPIO for Pine64-LTS
+    - perf/x86/intel/uncore: Remove uncore extra PCI dev HSWEP_PCI_PCU_3
+    - perf/x86/kvm: Fix Broadwell Xeon stepping in isolation_ucodes[]
+    - perf auxtrace: Fix potential NULL pointer dereference
+    - HID: google: add don USB id
+    - HID: alps: fix error return code in alps_input_configured()
+    - HID: wacom: Assign boolean values to a bool variable
+    - ARM: dts: Fix swapped mmc order for omap3
+    - net: geneve: check skb is large enough for IPv4/IPv6 header
+    - s390/entry: save the caller of psw_idle
+    - xen-netback: Check for hotplug-status existence before watching
+    - cavium/liquidio: Fix duplicate argument
+    - csky: change a Kconfig symbol name to fix e1000 build error
+    - ia64: fix discontig.c section mismatches
+    - ia64: tools: remove duplicate definition of ia64_mf() on ia64
+    - x86/crash: Fix crash_setup_memmap_entries() out-of-bounds access
+    - net: hso: fix NULL-deref on disconnect regression
+    - USB: CDC-ACM: fix poison/unpoison imbalance
+    - Linux 5.4.115
+
+  [ Ubuntu: 5.4.0-74.83 ]
+
+  * focal/linux: 5.4.0-74.83 -proposed tracker (LP: #1927619)
+  * Introduce the 465 driver series, fabric-manager, and libnvidia-nscq
+    (LP: #1925522)
+    - debian/dkms-versions -- add NVIDIA 465 and migrate 450 to 460
+  * linux-image-5.0.0-35-generic breaks checkpointing of container
+    (LP: #1857257)
+    - SAUCE: overlayfs: fix incorrect mnt_id of files opened from map_files
+  * Enable CIFS GCM256 (LP: #1921916)
+    - smb3: add defines for new crypto algorithms
+    - smb3.1.1: add new module load parm require_gcm_256
+    - smb3.1.1: add new module load parm enable_gcm_256
+    - smb3.1.1: print warning if server does not support requested encryption type
+    - smb3.1.1: rename nonces used for GCM and CCM encryption
+    - smb3.1.1: set gcm256 when requested
+    - cifs: Adjust key sizes and key generation routines for AES256 encryption
+  * locking/qrwlock: Fix ordering in queued_write_lock_slowpath() (LP: #1926184)
+    - locking/qrwlock: Fix ordering in queued_write_lock_slowpath()
+  * [Ubuntu 21.04] net/mlx5: Fix HW spec violation configuring uplink
+    (LP: #1925452)
+    - net/mlx5: Fix HW spec violation configuring uplink
+  * Focal update: v5.4.114 upstream stable release (LP: #1926493)
+    - Revert "scsi: qla2xxx: Retry PLOGI on FC-NVMe PRLI failure"
+    - Revert "scsi: qla2xxx: Fix stuck login session using prli_pend_timer"
+    - scsi: qla2xxx: Dual FCP-NVMe target port support
+    - scsi: qla2xxx: Fix device connect issues in P2P configuration
+    - scsi: qla2xxx: Retry PLOGI on FC-NVMe PRLI failure
+    - scsi: qla2xxx: Add a shadow variable to hold disc_state history of fcport
+    - scsi: qla2xxx: Fix stuck login session using prli_pend_timer
+    - scsi: qla2xxx: Fix fabric scan hang
+    - net/sctp: fix race condition in sctp_destroy_sock
+    - Input: nspire-keypad - enable interrupts only when opened
+    - gpio: sysfs: Obey valid_mask
+    - dmaengine: dw: Make it dependent to HAS_IOMEM
+    - ARM: dts: Drop duplicate sha2md5_fck to fix clk_disable race
+    - ARM: dts: Fix moving mmc devices with aliases for omap4 & 5
+    - lockdep: Add a missing initialization hint to the "INFO: Trying to register
+      non-static key" message
+    - arc: kernel: Return -EFAULT if copy_to_user() fails
+    - ASoC: max98373: Added 30ms turn on/off time delay
+    - neighbour: Disregard DEAD dst in neigh_update
+    - ARM: keystone: fix integer overflow warning
+    - ARM: omap1: fix building with clang IAS
+    - drm/msm: Fix a5xx/a6xx timestamps
+    - ASoC: fsl_esai: Fix TDM slot setup for I2S mode
+    - scsi: scsi_transport_srp: Don't block target in SRP_PORT_LOST state
+    - net: ieee802154: stop dump llsec keys for monitors
+    - net: ieee802154: forbid monitor for add llsec key
+    - net: ieee802154: forbid monitor for del llsec key
+    - net: ieee802154: stop dump llsec devs for monitors
+    - net: ieee802154: forbid monitor for add llsec dev
+    - net: ieee802154: forbid monitor for del llsec dev
+    - net: ieee802154: stop dump llsec devkeys for monitors
+    - net: ieee802154: forbid monitor for add llsec devkey
+    - net: ieee802154: forbid monitor for del llsec devkey
+    - net: ieee802154: stop dump llsec seclevels for monitors
+    - net: ieee802154: forbid monitor for add llsec seclevel
+    - pcnet32: Use pci_resource_len to validate PCI resource
+    - mac80211: clear sta->fast_rx when STA removed from 4-addr VLAN
+    - virt_wifi: Return micros for BSS TSF values
+    - Input: s6sy761 - fix coordinate read bit shift
+    - Input: i8042 - fix Pegatron C15B ID entry
+    - HID: wacom: set EV_KEY and EV_ABS only for non-HID_GENERIC type of devices
+    - dm verity fec: fix misaligned RS roots IO
+    - readdir: make sure to verify directory entry for legacy interfaces too
+    - arm64: fix inline asm in load_unaligned_zeropad()
+    - arm64: alternatives: Move length validation in alternative_{insn, endif}
+    - vfio/pci: Add missing range check in vfio_pci_mmap
+    - riscv: Fix spelling mistake "SPARSEMEM" to "SPARSMEM"
+    - scsi: libsas: Reset num_scatter if libata marks qc as NODATA
+    - netfilter: conntrack: do not print icmpv6 as unknown via /proc
+    - libnvdimm/region: Fix nvdimm_has_flush() to handle ND_REGION_ASYNC
+    - netfilter: bridge: add pre_exit hooks for ebtable unregistration
+    - netfilter: arp_tables: add pre_exit hook for table unregister
+    - net: macb: fix the restore of cmp registers
+    - netfilter: nft_limit: avoid possible divide error in nft_limit_init
+    - net: davicom: Fix regulator not turned off on failed probe
+    - net: sit: Unregister catch-all devices
+    - net: ip6_tunnel: Unregister catch-all devices
+    - i40e: fix the panic when running bpf in xdpdrv mode
+    - ibmvnic: avoid calling napi_disable() twice
+    - ibmvnic: remove duplicate napi_schedule call in do_reset function
+    - ibmvnic: remove duplicate napi_schedule call in open function
+    - gro: ensure frag0 meets IP header alignment
+    - ARM: footbridge: fix PCI interrupt mapping
+    - arm64: dts: allwinner: Fix SD card CD GPIO for SOPine systems
+    - r8169: remove fiddling with the PCIe max read request size
+    - r8169: simplify setting PCI_EXP_DEVCTL_NOSNOOP_EN
+    - r8169: fix performance regression related to PCIe max read request size
+    - r8169: improve rtl_jumbo_config
+    - r8169: tweak max read request size for newer chips also in jumbo mtu mode
+    - r8169: don't advertise pause in jumbo mode
+    - ARM: 9071/1: uprobes: Don't hook on thumb instructions
+    - net: phy: marvell: fix detection of PHY on Topaz switches
+    - Linux 5.4.114
+  * Focal update: v5.4.113 upstream stable release (LP: #1926490)
+    - interconnect: core: fix error return code of icc_link_destroy()
+    - KVM: arm64: Hide system instruction access to Trace registers
+    - KVM: arm64: Disable guest access to trace filter controls
+    - drm/imx: imx-ldb: fix out of bounds array access warning
+    - gfs2: report "already frozen/thawed" errors
+    - drm/tegra: dc: Don't set PLL clock to 0Hz
+    - block: only update parent bi_status when bio fail
+    - radix tree test suite: Register the main thread with the RCU library
+    - idr test suite: Take RCU read lock in idr_find_test_1
+    - idr test suite: Create anchor before launching throbber
+    - riscv,entry: fix misaligned base for excp_vect_table
+    - block: don't ignore REQ_NOWAIT for direct IO
+    - netfilter: x_tables: fix compat match/target pad out-of-bound write
+    - driver core: Fix locking bug in deferred_probe_timeout_work_func()
+    - perf tools: Use %define api.pure full instead of %pure-parser
+    - perf tools: Use %zd for size_t printf formats on 32-bit
+    - perf map: Tighten snprintf() string precision to pass gcc check on some
+      32-bit arches
+    - xen/events: fix setting irq affinity
+    - Linux 5.4.113
+  * Focal update: v5.4.112 upstream stable release (LP: #1926489)
+    - counter: stm32-timer-cnt: fix ceiling miss-alignment with reload register
+    - ALSA: aloop: Fix initialization of controls
+    - ALSA: hda/realtek: Fix speaker amp setup on Acer Aspire E1
+    - ASoC: intel: atom: Stop advertising non working S24LE support
+    - nfc: fix refcount leak in llcp_sock_bind()
+    - nfc: fix refcount leak in llcp_sock_connect()
+    - nfc: fix memory leak in llcp_sock_connect()
+    - nfc: Avoid endless loops caused by repeated llcp_sock_connect()
+    - xen/evtchn: Change irq_info lock to raw_spinlock_t
+    - net: ipv6: check for validity before dereferencing cfg->fc_nlinfo.nlh
+    - net: dsa: lantiq_gswip: Let GSWIP automatically set the xMII clock
+    - drm/i915: Fix invalid access to ACPI _DSM objects
+    - gcov: re-fix clang-11+ support
+    - ia64: fix user_stack_pointer() for ptrace()
+    - nds32: flush_dcache_page: use page_mapping_file to avoid races with swapoff
+    - ocfs2: fix deadlock between setattr and dio_end_io_write
+    - fs: direct-io: fix missing sdio->boundary
+    - parisc: parisc-agp requires SBA IOMMU driver
+    - parisc: avoid a warning on u8 cast for cmpxchg on u8 pointers
+    - ARM: dts: turris-omnia: configure LED[2]/INTn pin as interrupt pin
+    - batman-adv: initialize "struct batadv_tvlv_tt_vlan_data"->reserved field
+    - ice: Increase control queue timeout
+    - ice: Fix for dereference of NULL pointer
+    - ice: Cleanup fltr list in case of allocation issues
+    - net: hso: fix null-ptr-deref during tty device unregistration
+    - ethernet/netronome/nfp: Fix a use after free in nfp_bpf_ctrl_msg_rx
+    - bpf, sockmap: Fix sk->prot unhash op reset
+    - net: ensure mac header is set in virtio_net_hdr_to_skb()
+    - i40e: Fix sparse warning: missing error code 'err'
+    - i40e: Fix sparse error: 'vsi->netdev' could be null
+    - net: sched: sch_teql: fix null-pointer dereference
+    - mac80211: fix TXQ AC confusion
+    - net: hsr: Reset MAC header for Tx path
+    - net-ipv6: bugfix - raw & sctp - switch to ipv6_can_nonlocal_bind()
+    - net: let skb_orphan_partial wake-up waiters.
+    - usbip: add sysfs_lock to synchronize sysfs code paths
+    - usbip: stub-dev synchronize sysfs code paths
+    - usbip: vudc synchronize sysfs code paths
+    - usbip: synchronize event handler with sysfs code paths
+    - i2c: turn recovery error on init to debug
+    - virtio_net: Add XDP meta data support
+    - net: dsa: lantiq_gswip: Don't use PHY auto polling
+    - net: dsa: lantiq_gswip: Configure all remaining GSWIP_MII_CFG bits
+    - xfrm: interface: fix ipv4 pmtu check to honor ip header df
+    - regulator: bd9571mwv: Fix AVS and DVFS voltage range
+    - net: xfrm: Localize sequence counter per network namespace
+    - esp: delete NETIF_F_SCTP_CRC bit from features for esp offload
+    - ASoC: SOF: Intel: hda: remove unnecessary parentheses
+    - ASoC: SOF: Intel: HDA: fix core status verification
+    - ASoC: wm8960: Fix wrong bclk and lrclk with pll enabled for some chips
+    - xfrm: Fix NULL pointer dereference on policy lookup
+    - i40e: Added Asym_Pause to supported link modes
+    - i40e: Fix kernel oops when i40e driver removes VF's
+    - hostfs: Use kasprintf() instead of fixed buffer formatting
+    - hostfs: fix memory handling in follow_link()
+    - amd-xgbe: Update DMA coherency values
+    - sch_red: fix off-by-one checks in red_check_params()
+    - arm64: dts: imx8mm/q: Fix pad control of SD1_DATA0
+    - can: bcm/raw: fix msg_namelen values depending on CAN_REQUIRED_SIZE
+    - gianfar: Handle error code at MAC address change
+    - cxgb4: avoid collecting SGE_QBASE regs during traffic
+    - net:tipc: Fix a double free in tipc_sk_mcast_rcv
+    - ARM: dts: imx6: pbab01: Set vmmc supply for both SD interfaces
+    - net/ncsi: Avoid channel_monitor hrtimer deadlock
+    - nfp: flower: ignore duplicate merge hints from FW
+    - net: phy: broadcom: Only advertise EEE for supported modes
+    - ASoC: sunxi: sun4i-codec: fill ASoC card owner
+    - net/mlx5e: Fix ethtool indication of connector type
+    - net/mlx5: Don't request more than supported EQs
+    - net/rds: Fix a use after free in rds_message_map_pages
+    - soc/fsl: qbman: fix conflicting alignment attributes
+    - i40e: Fix display statistics for veb_tc
+    - drm/msm: Set drvdata to NULL when msm_drm_init() fails
+    - net: udp: Add support for getsockopt(..., ..., UDP_GRO, ..., ...);
+    - scsi: ufs: Fix irq return code
+    - scsi: ufs: Avoid busy-waiting by eliminating tag conflicts
+    - scsi: ufs: Use blk_{get,put}_request() to allocate and free TMFs
+    - scsi: ufs: core: Fix task management request completion timeout
+    - scsi: ufs: core: Fix wrong Task Tag used in task management request UPIUs
+    - net: macb: restore cmp registers on resume path
+    - clk: fix invalid usage of list cursor in register
+    - clk: fix invalid usage of list cursor in unregister
+    - workqueue: Move the position of debug_work_activate() in __queue_work()
+    - s390/cpcmd: fix inline assembly register clobbering
+    - perf inject: Fix repipe usage
+    - net: openvswitch: conntrack: simplify the return expression of
+      ovs_ct_limit_get_default_limit()
+    - openvswitch: fix send of uninitialized stack memory in ct limit reply
+    - net: hns3: clear VF down state bit before request link status
+    - net/mlx5: Fix placement of log_max_flow_counter
+    - net/mlx5: Fix PBMC register mapping
+    - RDMA/cxgb4: check for ipv6 address properly while destroying listener
+    - RDMA/addr: Be strict with gid size
+    - RAS/CEC: Correct ce_add_elem()'s returned values
+    - clk: socfpga: fix iomem pointer cast on 64-bit
+    - dt-bindings: net: ethernet-controller: fix typo in NVMEM
+    - net: sched: bump refcount for new action in ACT replace mode
+    - cfg80211: remove WARN_ON() in cfg80211_sme_connect
+    - net: tun: set tun->dev->addr_len during TUNSETLINK processing
+    - drivers: net: fix memory leak in atusb_probe
+    - drivers: net: fix memory leak in peak_usb_create_dev
+    - net: mac802154: Fix general protection fault
+    - net: ieee802154: nl-mac: fix check on panid
+    - net: ieee802154: fix nl802154 del llsec key
+    - net: ieee802154: fix nl802154 del llsec dev
+    - net: ieee802154: fix nl802154 add llsec key
+    - net: ieee802154: fix nl802154 del llsec devkey
+    - net: ieee802154: forbid monitor for set llsec params
+    - net: ieee802154: forbid monitor for del llsec seclevel
+    - net: ieee802154: stop dump llsec params for monitors
+    - Linux 5.4.112
+  * crash utility fails on arm64 with  cannot determine VA_BITS_ACTUAL
+    (LP: #1919275)
+    - arm64/crash_core: Export TCR_EL1.T1SZ in vmcoreinfo
+  * Focal update: v5.4.111 upstream stable release (LP: #1923874)
+    - ARM: dts: am33xx: add aliases for mmc interfaces
+    - bus: ti-sysc: Fix warning on unbind if reset is not deasserted
+    - platform/x86: intel-hid: Support Lenovo ThinkPad X1 Tablet Gen 2
+    - bpf, x86: Use kvmalloc_array instead kmalloc_array in bpf_jit_comp
+    - net/mlx5e: Enforce minimum value check for ICOSQ size
+    - net: pxa168_eth: Fix a potential data race in pxa168_eth_remove
+    - mISDN: fix crash in fritzpci
+    - mac80211: choose first enabled channel for monitor
+    - drm/msm/adreno: a5xx_power: Don't apply A540 lm_setup to other GPUs
+    - drm/msm: Ratelimit invalid-fence message
+    - netfilter: conntrack: Fix gre tunneling over ipv6
+    - platform/x86: thinkpad_acpi: Allow the FnLock LED to change state
+    - x86/build: Turn off -fcf-protection for realmode targets
+    - scsi: target: pscsi: Clean up after failure in pscsi_map_sg()
+    - ia64: mca: allocate early mca with GFP_ATOMIC
+    - ia64: fix format strings for err_inject
+    - cifs: revalidate mapping when we open files for SMB1 POSIX
+    - cifs: Silently ignore unknown oplock break handle
+    - nvme-mpath: replace direct_make_request with generic_make_request
+    - init/Kconfig: make COMPILE_TEST depend on !S390
+    - init/Kconfig: make COMPILE_TEST depend on HAS_IOMEM
+    - Linux 5.4.111
+  * Focal update: v5.4.110 upstream stable release (LP: #1923869)
+    - selinux: vsock: Set SID for socket returned by accept()
+    - ipv6: weaken the v4mapped source check
+    - modsign: print module name along with error message
+    - module: merge repetitive strings in module_sig_check()
+    - module: avoid *goto*s in module_sig_check()
+    - module: harden ELF info handling
+    - ext4: shrink race window in ext4_should_retry_alloc()
+    - ext4: fix bh ref count on error paths
+    - fs: nfsd: fix kconfig dependency warning for NFSD_V4
+    - rpc: fix NULL dereference on kmalloc failure
+    - iomap: Fix negative assignment to unsigned sis->pages in
+      iomap_swapfile_activate
+    - ASoC: rt5640: Fix dac- and adc- vol-tlv values being off by a factor of 10
+    - ASoC: rt5651: Fix dac- and adc- vol-tlv values being off by a factor of 10
+    - ASoC: sgtl5000: set DAP_AVC_CTRL register to correct default value on probe
+    - ASoC: es8316: Simplify adc_pga_gain_tlv table
+    - ASoC: cs42l42: Fix Bitclock polarity inversion
+    - ASoC: cs42l42: Fix channel width support
+    - ASoC: cs42l42: Fix mixer volume control
+    - ASoC: cs42l42: Always wait at least 3ms after reset
+    - NFSD: fix error handling in NFSv4.0 callbacks
+    - powerpc: Force inlining of cpu_has_feature() to avoid build failure
+    - vhost: Fix vhost_vq_reset()
+    - scsi: st: Fix a use after free in st_open()
+    - scsi: qla2xxx: Fix broken #endif placement
+    - staging: comedi: cb_pcidas: fix request_irq() warn
+    - staging: comedi: cb_pcidas64: fix request_irq() warn
+    - ASoC: rt5659: Update MCLK rate in set_sysclk()
+    - thermal/core: Add NULL pointer check before using cooling device stats
+    - locking/ww_mutex: Simplify use_ww_ctx & ww_ctx handling
+    - ext4: do not iput inode under running transaction in ext4_rename()
+    - net: mvpp2: fix interrupt mask/unmask skip condition
+    - flow_dissector: fix TTL and TOS dissection on IPv4 fragments
+    - can: dev: move driver related infrastructure into separate subdir
+    - net: introduce CAN specific pointer in the struct net_device
+    - can: tcan4x5x: fix max register value
+    - brcmfmac: clear EAP/association status bits on linkdown events
+    - ath10k: hold RCU lock when calling ieee80211_find_sta_by_ifaddr()
+    - net: ethernet: aquantia: Handle error cleanup of start on open
+    - appletalk: Fix skb allocation size in loopback case
+    - net: wan/lmc: unregister device when no matching device is found
+    - bpf: Remove MTU check in __bpf_skb_max_len
+    - ALSA: usb-audio: Apply sample rate quirk to Logitech Connect
+    - ALSA: hda: Re-add dropped snd_poewr_change_state() calls
+    - ALSA: hda: Add missing sanity checks in PM prepare/complete callbacks
+    - ALSA: hda/realtek: fix a determine_headset_type issue for a Dell AIO
+    - ALSA: hda/realtek: call alc_update_headset_mode() in hp_automute_hook
+    - xtensa: move coprocessor_flush to the .text section
+    - PM: runtime: Fix race getting/putting suppliers at probe
+    - PM: runtime: Fix ordering in pm_runtime_get_suppliers()
+    - tracing: Fix stack trace event size
+    - mm: fix race by making init_zero_pfn() early_initcall
+    - drm/amdgpu: fix offset calculation in amdgpu_vm_bo_clear_mappings()
+    - drm/amdgpu: check alignment on CPU page for bo map
+    - reiserfs: update reiserfs_xattrs_initialized() condition
+    - vfio/nvlink: Add missing SPAPR_TCE_IOMMU depends
+    - pinctrl: rockchip: fix restore error in resume
+    - extcon: Add stubs for extcon_register_notifier_all() functions
+    - extcon: Fix error handling in extcon_dev_register
+    - firewire: nosy: Fix a use-after-free bug in nosy_ioctl()
+    - usbip: vhci_hcd fix shift out-of-bounds in vhci_hub_control()
+    - USB: quirks: ignore remote wake-up on Fibocom L850-GL LTE modem
+    - usb: musb: Fix suspend with devices connected for a64
+    - usb: xhci-mtk: fix broken streams issue on 0.96 xHCI
+    - cdc-acm: fix BREAK rx code path adding necessary calls
+    - USB: cdc-acm: untangle a circular dependency between callback and softint
+    - USB: cdc-acm: downgrade message to debug
+    - USB: cdc-acm: fix double free on probe failure
+    - USB: cdc-acm: fix use-after-free after probe failure
+    - usb: gadget: udc: amd5536udc_pci fix null-ptr-dereference
+    - usb: dwc2: Fix HPRT0.PrtSusp bit setting for HiKey 960 board.
+    - usb: dwc2: Prevent core suspend when port connection flag is 0
+    - staging: rtl8192e: Fix incorrect source in memcpy()
+    - staging: rtl8192e: Change state information from u16 to u8
+    - drivers: video: fbcon: fix NULL dereference in fbcon_cursor()
+    - Linux 5.4.110
+  * Focal update: v5.4.109 upstream stable release (LP: #1923220)
+    - hugetlbfs: hugetlb_fault_mutex_hash() cleanup
+    - net: fec: ptp: avoid register access when ipg clock is disabled
+    - powerpc/4xx: Fix build errors from mfdcr()
+    - atm: eni: dont release is never initialized
+    - atm: lanai: dont run lanai_dev_close if not open
+    - Revert "r8152: adjust the settings about MAC clock speed down for RTL8153"
+    - ALSA: hda: ignore invalid NHLT table
+    - ixgbe: Fix memleak in ixgbe_configure_clsu32
+    - net: tehuti: fix error return code in bdx_probe()
+    - net: intel: iavf: fix error return code of iavf_init_get_resources()
+    - sun/niu: fix wrong RXMAC_BC_FRM_CNT_COUNT count
+    - gianfar: fix jumbo packets+napi+rx overrun crash
+    - cifs: ask for more credit on async read/write code paths
+    - cpufreq: blacklist Arm Vexpress platforms in cpufreq-dt-platdev
+    - gpiolib: acpi: Add missing IRQF_ONESHOT
+    - nfs: fix PNFS_FLEXFILE_LAYOUT Kconfig default
+    - NFS: Correct size calculation for create reply length
+    - net: hisilicon: hns: fix error return code of hns_nic_clear_all_rx_fetch()
+    - net: wan: fix error return code of uhdlc_init()
+    - net: davicom: Use platform_get_irq_optional()
+    - atm: uPD98402: fix incorrect allocation
+    - atm: idt77252: fix null-ptr-dereference
+    - cifs: change noisy error message to FYI
+    - irqchip/ingenic: Add support for the JZ4760
+    - sparc64: Fix opcode filtering in handling of no fault loads
+    - habanalabs: Call put_pid() when releasing control device
+    - u64_stats,lockdep: Fix u64_stats_init() vs lockdep
+    - regulator: qcom-rpmh: Correct the pmic5_hfsmps515 buck
+    - drm/amd/display: Revert dram_clock_change_latency for DCN2.1
+    - drm/amdgpu: fb BO should be ttm_bo_type_device
+    - drm/radeon: fix AGP dependency
+    - nvme: add NVME_REQ_CANCELLED flag in nvme_cancel_request()
+    - nvme-fc: return NVME_SC_HOST_ABORTED_CMD when a command has been aborted
+    - nvme-pci: add the DISABLE_WRITE_ZEROES quirk for a Samsung PM1725a
+    - nfs: we don't support removing system.nfs4_acl
+    - block: Suppress uevent for hidden device when removed
+    - ia64: fix ia64_syscall_get_set_arguments() for break-based syscalls
+    - ia64: fix ptrace(PTRACE_SYSCALL_INFO_EXIT) sign
+    - netsec: restore phy power state after controller reset
+    - platform/x86: intel-vbtn: Stop reporting SW_DOCK events
+    - squashfs: fix inode lookup sanity checks
+    - squashfs: fix xattr id and id lookup sanity checks
+    - kasan: fix per-page tags for non-page_alloc pages
+    - gcov: fix clang-11+ support
+    - ACPI: video: Add missing callback back for Sony VPCEH3U1E
+    - arm64: dts: ls1046a: mark crypto engine dma coherent
+    - arm64: dts: ls1012a: mark crypto engine dma coherent
+    - arm64: dts: ls1043a: mark crypto engine dma coherent
+    - ARM: dts: at91-sama5d27_som1: fix phy address to 7
+    - integrity: double check iint_cache was initialized
+    - dm verity: fix DM_VERITY_OPTS_MAX value
+    - dm ioctl: fix out of bounds array access when no devices
+    - bus: omap_l3_noc: mark l3 irqs as IRQF_NO_THREAD
+    - veth: Store queue_mapping independently of XDP prog presence
+    - libbpf: Fix INSTALL flag order
+    - net/mlx5e: Don't match on Geneve options in case option masks are all zero
+    - ipv6: fix suspecious RCU usage warning
+    - macvlan: macvlan_count_rx() needs to be aware of preemption
+    - net: sched: validate stab values
+    - net: dsa: bcm_sf2: Qualify phydev->dev_flags based on port
+    - igc: Fix Pause Frame Advertising
+    - igc: Fix Supported Pause Frame Link Setting
+    - e1000e: add rtnl_lock() to e1000_reset_task
+    - e1000e: Fix error handling in e1000_set_d0_lplu_state_82571
+    - net/qlcnic: Fix a use after free in qlcnic_83xx_get_minidump_template
+    - ftgmac100: Restart MAC HW once
+    - selftests/bpf: Set gopt opt_class to 0 if get tunnel opt failed
+    - netfilter: ctnetlink: fix dump of the expect mask attribute
+    - tcp: relookup sock for RST+ACK packets handled by obsolete req sock
+    - can: peak_usb: add forgotten supported devices
+    - can: flexcan: flexcan_chip_freeze(): fix chip freeze for missing bitrate
+    - can: kvaser_pciefd: Always disable bus load reporting
+    - can: c_can_pci: c_can_pci_remove(): fix use-after-free
+    - can: c_can: move runtime PM enable/disable to c_can_platform
+    - can: m_can: m_can_do_rx_poll(): fix extraneous msg loss warning
+    - can: m_can: m_can_rx_peripheral(): fix RX being blocked by errors
+    - mac80211: fix rate mask reset
+    - nfp: flower: fix pre_tun mask id allocation
+    - libbpf: Use SOCK_CLOEXEC when opening the netlink socket
+    - octeontx2-af: Fix irq free in rvu teardown
+    - octeontx2-af: fix infinite loop in unmapping NPC counter
+    - net: cdc-phonet: fix data-interface release on probe failure
+    - r8152: limit the RX buffer size of RTL8153A for USB 2.0
+    - net: stmmac: dwmac-sun8i: Provide TX and RX fifo sizes
+    - selftests: forwarding: vxlan_bridge_1d: Fix vxlan ecn decapsulate value
+    - libbpf: Fix BTF dump of pointer-to-array-of-struct
+    - drm/msm: fix shutdown hook in case GPU components failed to bind
+    - arm64: kdump: update ppos when reading elfcorehdr
+    - PM: runtime: Defer suspending suppliers
+    - net/mlx5e: Fix error path for ethtool set-priv-flag
+    - PM: EM: postpone creating the debugfs dir till fs_initcall
+    - RDMA/cxgb4: Fix adapter LE hash errors while destroying ipv6 listening
+      server
+    - bpf: Don't do bpf_cgroup_storage_set() for kuprobe/tp programs
+    - ACPI: scan: Rearrange memory allocation in acpi_device_add()
+    - ACPI: scan: Use unique number for instance_no
+    - perf auxtrace: Fix auxtrace queue conflict
+    - block: recalculate segment count for multi-segment discards correctly
+    - scsi: Revert "qla2xxx: Make sure that aborted commands are freed"
+    - scsi: qedi: Fix error return code of qedi_alloc_global_queues()
+    - scsi: mpt3sas: Fix error return code of mpt3sas_base_attach()
+    - locking/mutex: Fix non debug version of mutex_lock_io_nested()
+    - x86/mem_encrypt: Correct physical address calculation in __set_clr_pte_enc()
+    - can: dev: Move device back to init netns on owning netns delete
+    - net: dsa: b53: VLAN filtering is global to all users
+    - net: qrtr: fix a kernel-infoleak in qrtr_recvmsg()
+    - mac80211: fix double free in ibss_leave
+    - ext4: add reclaim checks to xattr code
+    - can: peak_usb: Revert "can: peak_usb: add forgotten supported devices"
+    - xen-blkback: don't leak persistent grants from xen_blkbk_map()
+    - Linux 5.4.109
+  * Focal update: v5.4.108 upstream stable release (LP: #1923214)
+    - ASoC: ak4458: Add MODULE_DEVICE_TABLE
+    - ASoC: ak5558: Add MODULE_DEVICE_TABLE
+    - ALSA: dice: fix null pointer dereference when node is disconnected
+    - ALSA: hda/realtek: apply pin quirk for XiaomiNotebook Pro
+    - ALSA: hda: generic: Fix the micmute led init state
+    - ALSA: hda/realtek: Apply headset-mic quirks for Xiaomi Redmibook Air
+    - Revert "PM: runtime: Update device status before letting suppliers suspend"
+    - ARM: 9030/1: entry: omit FP emulation for UND exceptions taken in kernel
+      mode
+    - ARM: 9044/1: vfp: use undef hook for VFP support detection
+    - btrfs: fix race when cloning extent buffer during rewind of an old root
+    - btrfs: fix slab cache flags for free space tree bitmap
+    - ASoC: fsl_ssi: Fix TDM slot setup for I2S mode
+    - ASoC: SOF: Intel: unregister DMIC device on probe error
+    - ASoC: SOF: intel: fix wrong poll bits in dsp power down
+    - ASoC: simple-card-utils: Do not handle device clock
+    - afs: Stop listxattr() from listing "afs.*" attributes
+    - nvme: fix Write Zeroes limitations
+    - nvme-tcp: fix possible hang when failing to set io queues
+    - nvme-tcp: fix a NULL deref when receiving a 0-length r2t PDU
+    - nvmet: don't check iosqes,iocqes for discovery controllers
+    - nfsd: Don't keep looking up unhashed files in the nfsd file cache
+    - NFSD: Repair misuse of sv_lock in 5.10.16-rt30.
+    - svcrdma: disable timeouts on rdma backchannel
+    - vfio: IOMMU_API should be selected
+    - sunrpc: fix refcount leak for rpc auth modules
+    - net/qrtr: fix __netdev_alloc_skb call
+    - kbuild: Fix <linux/version.h> for empty SUBLEVEL or PATCHLEVEL again
+    - riscv: Correct SPARSEMEM configuration
+    - scsi: lpfc: Fix some error codes in debugfs
+    - scsi: myrs: Fix a double free in myrs_cleanup()
+    - counter: stm32-timer-cnt: Report count function when SLAVE_MODE_DISABLED
+    - nvme-rdma: fix possible hang when failing to set io queues
+    - usb-storage: Add quirk to defeat Kindle's automatic unload
+    - usbip: Fix incorrect double assignment to udc->ud.tcp_rx
+    - USB: replace hardcode maximum usb string length by definition
+    - usb: gadget: configfs: Fix KASAN use-after-free
+    - usb: typec: tcpm: Invoke power_supply_changed for tcpm-source-psy-
+    - iio:adc:stm32-adc: Add HAS_IOMEM dependency
+    - iio:adc:qcom-spmi-vadc: add default scale to LR_MUX2_BAT_ID channel
+    - iio: adis16400: Fix an error code in adis16400_initial_setup()
+    - iio: gyro: mpu3050: Fix error handling in mpu3050_trigger_handler
+    - iio: adc: ad7949: fix wrong ADC result due to incorrect bit mask
+    - iio: hid-sensor-humidity: Fix alignment issue of timestamp channel
+    - iio: hid-sensor-prox: Fix scale not correct issue
+    - iio: hid-sensor-temperature: Fix issues of timestamp channel
+    - counter: stm32-timer-cnt: fix ceiling write max value
+    - PCI: rpadlpar: Fix potential drc_name corruption in store functions
+    - perf/x86/intel: Fix a crash caused by zero PEBS status
+    - x86/ioapic: Ignore IRQ2 again
+    - kernel, fs: Introduce and use set_restart_fn() and arch_set_restart_data()
+    - x86: Move TS_COMPAT back to asm/thread_info.h
+    - x86: Introduce TS_COMPAT_RESTART to fix get_nr_restart_syscall()
+    - ext4: find old entry again if failed to rename whiteout
+    - ext4: do not try to set xattr into ea_inode if value is empty
+    - ext4: fix potential error in ext4_do_update_inode
+    - efi: use 32-bit alignment for efi_guid_t literals
+    - firmware/efi: Fix a use after bug in efi_mem_reserve_persistent
+    - genirq: Disable interrupts for force threaded handlers
+    - x86/apic/of: Fix CPU devicetree-node lookups
+    - cifs: Fix preauth hash corruption
+    - Linux 5.4.108
+  * Focal update: v5.4.107 upstream stable release (LP: #1923210)
+    - KVM: arm64: nvhe: Save the SPE context early
+    - btrfs: scrub: Don't check free space before marking a block group RO
+    - drm/i915/gvt: Set SNOOP for PAT3 on BXT/APL to workaround GPU BB hang
+    - drm/i915/gvt: Fix mmio handler break on BXT/APL.
+    - drm/i915/gvt: Fix virtual display setup for BXT/APL
+    - drm/i915/gvt: Fix port number for BDW on EDID region setup
+    - drm/i915/gvt: Fix vfio_edid issue for BXT/APL
+    - fuse: fix live lock in fuse_iget()
+    - crypto: x86 - Regularize glue function prototypes
+    - crypto: aesni - Use TEST %reg,%reg instead of CMP $0,%reg
+    - crypto: x86/aes-ni-xts - use direct calls to and 4-way stride
+    - net: dsa: tag_mtk: fix 802.1ad VLAN egress
+    - net: dsa: b53: Support setting learning on port
+    - Linux 5.4.107
+
+  [ Ubuntu: 5.4.0-73.82 ]
+
+  * focal/linux: 5.4.0-73.82 -proposed tracker (LP: #1923781)
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+  * CIFS DFS entries not accessible with 5.4.0-71.74-generic (LP: #1923670)
+    - Revert "cifs: Set CIFS_MOUNT_USE_PREFIX_PATH flag on setting
+      cifs_sb->prepath."
+  * CVE-2021-29650
+    - Revert "netfilter: x_tables: Update remaining dereference to RCU"
+    - Revert "netfilter: x_tables: Switch synchronization to RCU"
+    - netfilter: x_tables: Use correct memory barriers.
+  * LRMv4: switch to signing nvidia modules via the Ubuntu Modules signing key
+    (LP: #1918134)
+    - [Packaging] dkms-build{,--nvidia-N} sync back from LRMv4
+  * 5.4 kernel: when iommu is on crashdump fails (LP: #1922738)
+    - iommu/vt-d: Refactor find_domain() helper
+    - iommu/vt-d: Add attach_deferred() helper
+    - iommu/vt-d: Move deferred device attachment into helper function
+    - iommu/vt-d: Do deferred attachment in iommu_need_mapping()
+    - iommu/vt-d: Remove deferred_attach_domain()
+    - iommu/vt-d: Simplify check in identity_mapping()
+  * Backport mlx5e fix for tunnel offload (LP: #1921769)
+    - net/mlx5e: Check tunnel offload is required before setting SWP
+  * Bcache bypasse writeback on caching device with fragmentation (LP: #1900438)
+    - bcache: consider the fragmentation when update the writeback rate
+  * Fix implicit declaration warnings for kselftests/memfd test on newer
+    releases (LP: #1910323)
+    - selftests/memfd: Fix implicit declaration warnings
+  * net/mlx5e: Add missing capability check for uplink follow (LP: #1921104)
+    - net/mlx5e: Add missing capability check for uplink follow
+  * [UBUNUT 21.04] s390/vtime: fix increased steal time accounting
+    (LP: #1921498)
+    - s390/vtime: fix increased steal time accounting
+  * Mute/Mic-mute LEDs are not work on HP 850/840/440 G8 Laptops (LP: #1920030)
+    - ALSA: hda/realtek: fix mute/micmute LEDs for HP 840 G8
+    - ALSA: hda/realtek: fix mute/micmute LEDs for HP 440 G8
+    - ALSA: hda/realtek: fix mute/micmute LEDs for HP 850 G8
+  * Focal update: v5.4.106 upstream stable release (LP: #1920246)
+    - uapi: nfnetlink_cthelper.h: fix userspace compilation error
+    - powerpc/pseries: Don't enforce MSI affinity with kdump
+    - ath9k: fix transmitting to stations in dynamic SMPS mode
+    - net: Fix gro aggregation for udp encaps with zero csum
+    - net: check if protocol extracted by virtio_net_hdr_set_proto is correct
+    - net: avoid infinite loop in mpls_gso_segment when mpls_hlen == 0
+    - sh_eth: fix TRSCER mask for SH771x
+    - can: skb: can_skb_set_owner(): fix ref counting if socket was closed before
+      setting skb ownership
+    - can: flexcan: assert FRZ bit in flexcan_chip_freeze()
+    - can: flexcan: enable RX FIFO after FRZ/HALT valid
+    - can: flexcan: invoke flexcan_chip_freeze() to enter freeze mode
+    - can: tcan4x5x: tcan4x5x_init(): fix initialization - clear MRAM before
+      entering Normal Mode
+    - tcp: add sanity tests to TCP_QUEUE_SEQ
+    - netfilter: nf_nat: undo erroneous tcp edemux lookup
+    - netfilter: x_tables: gpf inside xt_find_revision()
+    - selftests/bpf: No need to drop the packet when there is no geneve opt
+    - selftests/bpf: Mask bpf_csum_diff() return value to 16 bits in test_verifier
+    - samples, bpf: Add missing munmap in xdpsock
+    - ibmvnic: always store valid MAC address
+    - mt76: dma: do not report truncated frames to mac80211
+    - powerpc/603: Fix protection of user pages mapped with PROT_NONE
+    - mount: fix mounting of detached mounts onto targets that reside on shared
+      mounts
+    - cifs: return proper error code in statfs(2)
+    - Revert "mm, slub: consider rest of partial list if acquire_slab() fails"
+    - net: enetc: don't overwrite the RSS indirection table when initializing
+    - net/mlx4_en: update moderation when config reset
+    - net: stmmac: fix incorrect DMA channel intr enable setting of EQoS v4.10
+    - nexthop: Do not flush blackhole nexthops when loopback goes down
+    - net: sched: avoid duplicates in classes dump
+    - net: usb: qmi_wwan: allow qmimux add/del with master up
+    - netdevsim: init u64 stats for 32bit hardware
+    - cipso,calipso: resolve a number of problems with the DOI refcounts
+    - net: lapbether: Remove netif_start_queue / netif_stop_queue
+    - net: davicom: Fix regulator not turned off on failed probe
+    - net: davicom: Fix regulator not turned off on driver removal
+    - net: qrtr: fix error return code of qrtr_sendmsg()
+    - ixgbe: fail to create xfrm offload of IPsec tunnel mode SA
+    - net: stmmac: stop each tx channel independently
+    - net: stmmac: fix watchdog timeout during suspend/resume stress test
+    - selftests: forwarding: Fix race condition in mirror installation
+    - perf traceevent: Ensure read cmdlines are null terminated.
+    - net: hns3: fix query vlan mask value error for flow director
+    - net: hns3: fix bug when calculating the TCAM table info
+    - s390/cio: return -EFAULT if copy_to_user() fails again
+    - bnxt_en: reliably allocate IRQ table on reset to avoid crash
+    - drm/compat: Clear bounce structures
+    - drm/shmem-helper: Check for purged buffers in fault handler
+    - drm/shmem-helper: Don't remove the offset in vm_area_struct pgoff
+    - drm: meson_drv add shutdown function
+    - s390/cio: return -EFAULT if copy_to_user() fails
+    - s390/crypto: return -EFAULT if copy_to_user() fails
+    - qxl: Fix uninitialised struct field head.surface_id
+    - sh_eth: fix TRSCER mask for R7S9210
+    - media: usbtv: Fix deadlock on suspend
+    - media: v4l: vsp1: Fix uif null pointer access
+    - media: v4l: vsp1: Fix bru null pointer access
+    - media: rc: compile rc-cec.c into rc-core
+    - [Config] update abi for rc-cec
+    - net: hns3: fix error mask definition of flow director
+    - net: enetc: initialize RFS/RSS memories for unused ports too
+    - net: phy: fix save wrong speed and duplex problem if autoneg is on
+    - i2c: rcar: faster irq code to minimize HW race condition
+    - i2c: rcar: optimize cacheline to minimize HW race condition
+    - udf: fix silent AED tagLocation corruption
+    - mmc: mxs-mmc: Fix a resource leak in an error handling path in
+      'mxs_mmc_probe()'
+    - mmc: mediatek: fix race condition between msdc_request_timeout and irq
+    - Platform: OLPC: Fix probe error handling
+    - powerpc/pci: Add ppc_md.discover_phbs()
+    - spi: stm32: make spurious and overrun interrupts visible
+    - powerpc: improve handling of unrecoverable system reset
+    - powerpc/perf: Record counter overflow always if SAMPLE_IP is unset
+    - HID: logitech-dj: add support for the new lightspeed connection iteration
+    - powerpc/64: Fix stack trace not displaying final frame
+    - iommu/amd: Fix performance counter initialization
+    - sparc32: Limit memblock allocation to low memory
+    - sparc64: Use arch_validate_flags() to validate ADI flag
+    - Input: applespi - don't wait for responses to commands indefinitely.
+    - PCI: xgene-msi: Fix race in installing chained irq handler
+    - PCI: mediatek: Add missing of_node_put() to fix reference leak
+    - kbuild: clamp SUBLEVEL to 255
+    - PCI: Fix pci_register_io_range() memory leak
+    - i40e: Fix memory leak in i40e_probe
+    - s390/smp: __smp_rescan_cpus() - move cpumask away from stack
+    - sysctl.c: fix underflow value setting risk in vm_table
+    - scsi: libiscsi: Fix iscsi_prep_scsi_cmd_pdu() error handling
+    - scsi: target: core: Add cmd length set before cmd complete
+    - scsi: target: core: Prevent underflow for service actions
+    - ALSA: usb: Add Plantronics C320-M USB ctrl msg delay quirk
+    - ALSA: hda/hdmi: Cancel pending works before suspend
+    - ALSA: hda/ca0132: Add Sound BlasterX AE-5 Plus support
+    - ALSA: hda: Drop the BATCH workaround for AMD controllers
+    - ALSA: hda: Flush pending unsolicited events before suspend
+    - ALSA: hda: Avoid spurious unsol event handling during S3/S4
+    - ALSA: usb-audio: Fix "cannot get freq eq" errors on Dell AE515 sound bar
+    - ALSA: usb-audio: Apply the control quirk to Plantronics headsets
+    - Revert 95ebabde382c ("capabilities: Don't allow writing ambiguous v3 file
+      capabilities")
+    - arm64: kasan: fix page_alloc tagging with DEBUG_VIRTUAL
+    - s390/dasd: fix hanging DASD driver unbind
+    - s390/dasd: fix hanging IO request during DASD driver unbind
+    - software node: Fix node registration
+    - mmc: core: Fix partition switch time for eMMC
+    - mmc: cqhci: Fix random crash when remove mmc module/card
+    - Goodix Fingerprint device is not a modem
+    - USB: gadget: u_ether: Fix a configfs return code
+    - usb: gadget: f_uac2: always increase endpoint max_packet_size by one audio
+      slot
+    - usb: gadget: f_uac1: stop playback on function disable
+    - usb: dwc3: qcom: Add missing DWC3 OF node refcount decrement
+    - usb: dwc3: qcom: Honor wakeup enabled/disabled state
+    - USB: usblp: fix a hang in poll() if disconnected
+    - usb: renesas_usbhs: Clear PIPECFG for re-enabling pipe with other EPNUM
+    - usb: xhci: do not perform Soft Retry for some xHCI hosts
+    - xhci: Improve detection of device initiated wake signal.
+    - usb: xhci: Fix ASMedia ASM1042A and ASM3242 DMA addressing
+    - xhci: Fix repeated xhci wake after suspend due to uncleared internal wake
+      state
+    - USB: serial: io_edgeport: fix memory leak in edge_startup
+    - USB: serial: ch341: add new Product ID
+    - USB: serial: cp210x: add ID for Acuity Brands nLight Air Adapter
+    - USB: serial: cp210x: add some more GE USB IDs
+    - usbip: fix stub_dev to check for stream socket
+    - usbip: fix vhci_hcd to check for stream socket
+    - usbip: fix vudc to check for stream socket
+    - usbip: fix stub_dev usbip_sockfd_store() races leading to gpf
+    - usbip: fix vhci_hcd attach_store() races leading to gpf
+    - usbip: fix vudc usbip_sockfd_store races leading to gpf
+    - misc/pvpanic: Export module FDT device table
+    - misc: fastrpc: restrict user apps from sending kernel RPC messages
+    - staging: rtl8192u: fix ->ssid overflow in r8192_wx_set_scan()
+    - staging: rtl8188eu: prevent ->ssid overflow in rtw_wx_set_scan()
+    - staging: rtl8712: unterminated string leads to read overflow
+    - staging: rtl8188eu: fix potential memory corruption in
+      rtw_check_beacon_data()
+    - staging: ks7010: prevent buffer overflow in ks_wlan_set_scan()
+    - staging: rtl8712: Fix possible buffer overflow in r8712_sitesurvey_cmd
+    - staging: rtl8192e: Fix possible buffer overflow in _rtl92e_wx_set_scan
+    - staging: comedi: addi_apci_1032: Fix endian problem for COS sample
+    - staging: comedi: addi_apci_1500: Fix endian problem for command sample
+    - staging: comedi: adv_pci1710: Fix endian problem for AI command data
+    - staging: comedi: das6402: Fix endian problem for AI command data
+    - staging: comedi: das800: Fix endian problem for AI command data
+    - staging: comedi: dmm32at: Fix endian problem for AI command data
+    - staging: comedi: me4000: Fix endian problem for AI command data
+    - staging: comedi: pcl711: Fix endian problem for AI command data
+    - staging: comedi: pcl818: Fix endian problem for AI command data
+    - sh_eth: fix TRSCER mask for R7S72100
+    - arm64/mm: Fix pfn_valid() for ZONE_DEVICE based memory
+    - SUNRPC: Set memalloc_nofs_save() for sync tasks
+    - NFS: Don't revalidate the directory permissions on a lookup failure
+    - NFS: Don't gratuitously clear the inode cache when lookup failed
+    - NFSv4.2: fix return value of _nfs4_get_security_label()
+    - block: rsxx: fix error return code of rsxx_pci_probe()
+    - configfs: fix a use-after-free in __configfs_open_file
+    - arm64: mm: use a 48-bit ID map when possible on 52-bit VA builds
+    - hrtimer: Update softirq_expires_next correctly after
+      __hrtimer_get_next_event()
+    - stop_machine: mark helpers __always_inline
+    - include/linux/sched/mm.h: use rcu_dereference in in_vfork()
+    - zram: fix return value on writeback_store
+    - sched/membarrier: fix missing local execution of ipi_sync_rq_state()
+    - powerpc/64s: Fix instruction encoding for lis in ppc_function_entry()
+    - binfmt_misc: fix possible deadlock in bm_register_write
+    - x86/unwind/orc: Disable KASAN checking in the ORC unwinder, part 2
+    - KVM: arm64: Fix exclusive limit for IPA size
+    - nvme: unlink head after removing last namespace
+    - nvme: release namespace head reference on error
+    - KVM: arm64: Ensure I-cache isolation between vcpus of a same VM
+    - KVM: arm64: Reject VM creation when the default IPA size is unsupported
+    - xen/events: reset affinity of 2-level event when tearing it down
+    - xen/events: don't unmask an event channel when an eoi is pending
+    - xen/events: avoid handling the same event on two cpus at the same time
+    - Linux 5.4.106
+  * Focal update: v5.4.105 upstream stable release (LP: #1920244)
+    - net: dsa: add GRO support via gro_cells
+    - dm table: fix iterate_devices based device capability checks
+    - dm table: fix DAX iterate_devices based device capability checks
+    - dm table: fix zoned iterate_devices based device capability checks
+    - ACPICA: Fix race in generic_serial_bus (I2C) and GPIO op_region parameter
+      handling
+    - iommu/amd: Fix sleeping in atomic in increase_address_space()
+    - mwifiex: pcie: skip cancel_work_sync() on reset failure path
+    - platform/x86: acer-wmi: Cleanup ACER_CAP_FOO defines
+    - platform/x86: acer-wmi: Cleanup accelerometer device handling
+    - platform/x86: acer-wmi: Add new force_caps module parameter
+    - platform/x86: acer-wmi: Add ACER_CAP_SET_FUNCTION_MODE capability flag
+    - platform/x86: acer-wmi: Add support for SW_TABLET_MODE on Switch devices
+    - platform/x86: acer-wmi: Add ACER_CAP_KBD_DOCK quirk for the Aspire Switch
+      10E SW3-016
+    - HID: mf: add support for 0079:1846 Mayflash/Dragonrise USB Gamecube Adapter
+    - media: cx23885: add more quirks for reset DMA on some AMD IOMMU
+    - ACPI: video: Add DMI quirk for GIGABYTE GB-BXBT-2807
+    - ASoC: Intel: bytcr_rt5640: Add quirk for ARCHOS Cesium 140
+    - PCI: Add function 1 DMA alias quirk for Marvell 9215 SATA controller
+    - misc: eeprom_93xx46: Add quirk to support Microchip 93LC46B eeprom
+    - drm/msm/a5xx: Remove overwriting A5XX_PC_DBG_ECO_CNTL register
+    - mmc: sdhci-of-dwcmshc: set SDHCI_QUIRK2_PRESET_VALUE_BROKEN
+    - HID: i2c-hid: Add I2C_HID_QUIRK_NO_IRQ_AFTER_RESET for ITE8568 EC on Voyo
+      Winpad A15
+    - nvme-pci: mark Seagate Nytro XM1440 as QUIRK_NO_NS_DESC_LIST.
+    - nvme-pci: add quirks for Lexar 256GB SSD
+    - Linux 5.4.105
+  * Focal update: v5.4.104 upstream stable release (LP: #1920238)
+    - tpm, tpm_tis: Decorate tpm_tis_gen_interrupt() with request_locality()
+    - tpm, tpm_tis: Decorate tpm_get_timeouts() with request_locality()
+    - btrfs: raid56: simplify tracking of Q stripe presence
+    - btrfs: fix raid6 qstripe kmap
+    - btrfs: validate qgroup inherit for SNAP_CREATE_V2 ioctl
+    - btrfs: free correct amount of space in btrfs_delayed_inode_reserve_metadata
+    - btrfs: unlock extents in btrfs_zero_range in case of quota reservation
+      errors
+    - btrfs: fix warning when creating a directory with smack enabled
+    - PM: runtime: Update device status before letting suppliers suspend
+    - dm bufio: subtract the number of initial sectors in dm_bufio_get_device_size
+    - dm verity: fix FEC for RS roots unaligned to block size
+    - drm/amdgpu: fix parameter error of RREG32_PCIE() in amdgpu_regs_pcie
+    - arm64: ptrace: Fix seccomp of traced syscall -1 (NO_SYSCALL)
+    - crypto - shash: reduce minimum alignment of shash_desc structure
+    - usbip: tools: fix build error for multiple definition
+    - ALSA: ctxfi: cthw20k2: fix mask on conf to allow 4 bits
+    - RDMA/rxe: Fix missing kconfig dependency on CRYPTO
+    - IB/mlx5: Add missing error code
+    - ALSA: hda: intel-nhlt: verify config type
+    - ftrace: Have recordmcount use w8 to read relp->r_info in
+      arm64_is_fake_mcount
+    - rsxx: Return -EFAULT if copy_to_user() fails
+    - r8169: fix resuming from suspend on RTL8105e if machine runs on battery
+    - Linux 5.4.104
+  * Focal update: v5.4.103 upstream stable release (LP: #1920235)
+    - net: usb: qmi_wwan: support ZTE P685M modem
+    - nvme-pci: refactor nvme_unmap_data
+    - nvme-pci: fix error unwind in nvme_map_data
+    - arm64 module: set plt* section addresses to 0x0
+    - MIPS: VDSO: Use CLANG_FLAGS instead of filtering out '--target='
+    - JFS: more checks for invalid superblock
+    - udlfb: Fix memory leak in dlfb_usb_probe
+    - media: mceusb: sanity check for prescaler value
+    - erofs: fix shift-out-of-bounds of blkszbits
+    - media: v4l2-ctrls.c: fix shift-out-of-bounds in std_validate
+    - xfs: Fix assert failure in xfs_setattr_size()
+    - net/af_iucv: remove WARN_ONCE on malformed RX packets
+    - smackfs: restrict bytes count in smackfs write functions
+    - net: fix up truesize of cloned skb in skb_prepare_for_shift()
+    - nbd: handle device refs for DESTROY_ON_DISCONNECT properly
+    - mm/hugetlb.c: fix unnecessary address expansion of pmd sharing
+    - net: bridge: use switchdev for port flags set through sysfs too
+    - net: ag71xx: remove unnecessary MTU reservation
+    - net: fix dev_ifsioc_locked() race condition
+    - dt-bindings: ethernet-controller: fix fixed-link specification
+    - dt-bindings: net: btusb: DT fix s/interrupt-name/interrupt-names/
+    - MIPS: Drop 32-bit asm string functions
+    - drm/virtio: use kvmalloc for large allocations
+    - rsi: Fix TX EAPOL packet handling against iwlwifi AP
+    - rsi: Move card interrupt handling to RX thread
+    - staging: fwserial: Fix error handling in fwserial_create
+    - x86/reboot: Add Zotac ZBOX CI327 nano PCI reboot quirk
+    - vt/consolemap: do font sum unsigned
+    - wlcore: Fix command execute failure 19 for wl12xx
+    - Bluetooth: hci_h5: Set HCI_QUIRK_SIMULTANEOUS_DISCOVERY for btrtl
+    - pktgen: fix misuse of BUG_ON() in pktgen_thread_worker()
+    - ath10k: fix wmi mgmt tx queue full due to race condition
+    - x86/build: Treat R_386_PLT32 relocation as R_386_PC32
+    - Bluetooth: Fix null pointer dereference in amp_read_loc_assoc_final_data
+    - staging: most: sound: add sanity check for function argument
+    - staging: bcm2835-audio: Replace unsafe strcpy() with strscpy()
+    - brcmfmac: Add DMI nvram filename quirk for Predia Basic tablet
+    - brcmfmac: Add DMI nvram filename quirk for Voyo winpad A15 tablet
+    - drm/hisilicon: Fix use-after-free
+    - crypto: tcrypt - avoid signed overflow in byte count
+    - drm/amdgpu: Add check to prevent IH overflow
+    - PCI: Add a REBAR size quirk for Sapphire RX 5600 XT Pulse
+    - drm/amd/display: Guard against NULL pointer deref when get_i2c_info fails
+    - media: uvcvideo: Allow entities with no pads
+    - f2fs: handle unallocated section and zone on pinned/atgc
+    - f2fs: fix to set/clear I_LINKABLE under i_lock
+    - nvme-core: add cancel tagset helpers
+    - nvme-rdma: add clean action for failed reconnection
+    - nvme-tcp: add clean action for failed reconnection
+    - ASoC: Intel: Add DMI quirk table to soc_intel_is_byt_cr()
+    - btrfs: fix error handling in commit_fs_roots
+    - perf/x86/kvm: Add Cascade Lake Xeon steppings to isolation_ucodes[]
+    - parisc: Bump 64-bit IRQ stack size to 64 KB
+    - sched/features: Fix hrtick reprogramming
+    - ASoC: Intel: bytcr_rt5640: Add quirk for the Estar Beauty HD MID 7316R
+      tablet
+    - ASoC: Intel: bytcr_rt5640: Add quirk for the Voyo Winpad A15 tablet
+    - ASoC: Intel: bytcr_rt5651: Add quirk for the Jumper EZpad 7 tablet
+    - ASoC: Intel: bytcr_rt5640: Add quirk for the Acer One S1002 tablet
+    - Xen/gnttab: handle p2m update errors on a per-slot basis
+    - xen-netback: respect gnttab_map_refs()'s return value
+    - zsmalloc: account the number of compacted pages correctly
+    - swap: fix swapfile read/write offset
+    - media: v4l: ioctl: Fix memory leak in video_usercopy
+    - ALSA: hda/realtek: Add quirk for Clevo NH55RZQ
+    - ALSA: hda/realtek: Add quirk for Intel NUC 10
+    - ALSA: hda/realtek: Apply dual codec quirks for MSI Godlike X570 board
+    - Linux 5.4.103
+  * Focal update: v5.4.102 upstream stable release (LP: #1918974)
+    - vmlinux.lds.h: add DWARF v5 sections
+    - kvm: x86: replace kvm_spec_ctrl_test_value with runtime test on the host
+    - debugfs: be more robust at handling improper input in debugfs_lookup()
+    - debugfs: do not attempt to create a new file before the filesystem is
+      initalized
+    - kdb: Make memory allocations more robust
+    - PCI: qcom: Use PHY_REFCLK_USE_PAD only for ipq8064
+    - PCI: Decline to resize resources if boot config must be preserved
+    - virt: vbox: Do not use wait_event_interruptible when called from kernel
+      context
+    - bfq: Avoid false bfq queue merging
+    - ALSA: usb-audio: Fix PCM buffer allocation in non-vmalloc mode
+    - MIPS: vmlinux.lds.S: add missing PAGE_ALIGNED_DATA() section
+    - random: fix the RNDRESEEDCRNG ioctl
+    - ath10k: Fix error handling in case of CE pipe init failure
+    - Bluetooth: btqcomsmd: Fix a resource leak in error handling paths in the
+      probe function
+    - Bluetooth: hci_uart: Fix a race for write_work scheduling
+    - Bluetooth: Fix initializing response id after clearing struct
+    - ARM: dts: exynos: correct PMIC interrupt trigger level on Artik 5
+    - ARM: dts: exynos: correct PMIC interrupt trigger level on Monk
+    - ARM: dts: exynos: correct PMIC interrupt trigger level on Rinato
+    - ARM: dts: exynos: correct PMIC interrupt trigger level on Spring
+    - ARM: dts: exynos: correct PMIC interrupt trigger level on Arndale Octa
+    - ARM: dts: exynos: correct PMIC interrupt trigger level on Odroid XU3 family
+    - arm64: dts: exynos: correct PMIC interrupt trigger level on TM2
+    - arm64: dts: exynos: correct PMIC interrupt trigger level on Espresso
+    - memory: mtk-smi: Fix PM usage counter unbalance in mtk_smi ops
+    - bpf: Add bpf_patch_call_args prototype to include/linux/bpf.h
+    - bpf: Avoid warning when re-casting __bpf_call_base into __bpf_call_base_args
+    - arm64: dts: allwinner: A64: properly connect USB PHY to port 0
+    - arm64: dts: allwinner: H6: properly connect USB PHY to port 0
+    - arm64: dts: allwinner: Drop non-removable from SoPine/LTS SD card
+    - arm64: dts: allwinner: H6: Allow up to 150 MHz MMC bus frequency
+    - arm64: dts: allwinner: A64: Limit MMC2 bus frequency to 150 MHz
+    - cpufreq: brcmstb-avs-cpufreq: Free resources in error path
+    - cpufreq: brcmstb-avs-cpufreq: Fix resource leaks in ->remove()
+    - ACPICA: Fix exception code class checks
+    - usb: gadget: u_audio: Free requests only after callback
+    - Bluetooth: drop HCI device reference before return
+    - Bluetooth: Put HCI device if inquiry procedure interrupts
+    - memory: ti-aemif: Drop child node when jumping out loop
+    - ARM: dts: Configure missing thermal interrupt for 4430
+    - usb: dwc2: Do not update data length if it is 0 on inbound transfers
+    - usb: dwc2: Abort transaction after errors with unknown reason
+    - usb: dwc2: Make "trimming xfer length" a debug message
+    - staging: rtl8723bs: wifi_regd.c: Fix incorrect number of regulatory rules
+    - ARM: dts: armada388-helios4: assign pinctrl to LEDs
+    - ARM: dts: armada388-helios4: assign pinctrl to each fan
+    - arm64: dts: armada-3720-turris-mox: rename u-boot mtd partition to
+      a53-firmware
+    - Bluetooth: btusb: Fix memory leak in btusb_mtk_wmt_recv
+    - arm64: dts: msm8916: Fix reserved and rfsa nodes unit address
+    - ARM: s3c: fix fiq for clang IAS
+    - soc: aspeed: snoop: Add clock control logic
+    - bpf_lru_list: Read double-checked variable once without lock
+    - ath9k: fix data bus crash when setting nf_override via debugfs
+    - ibmvnic: Set to CLOSED state even on error
+    - bnxt_en: reverse order of TX disable and carrier off
+    - xen/netback: fix spurious event detection for common event case
+    - mac80211: fix potential overflow when multiplying to u32 integers
+    - bpf: Fix bpf_fib_lookup helper MTU check for SKB ctx
+    - tcp: fix SO_RCVLOWAT related hangs under mem pressure
+    - net: axienet: Handle deferred probe on clock properly
+    - cxgb4/chtls/cxgbit: Keeping the max ofld immediate data size same in cxgb4
+      and ulds
+    - b43: N-PHY: Fix the update of coef for the PHY revision >= 3case
+    - ibmvnic: add memory barrier to protect long term buffer
+    - ibmvnic: skip send_request_unmap for timeout reset
+    - net: amd-xgbe: Reset the PHY rx data path when mailbox command timeout
+    - net: amd-xgbe: Fix NETDEV WATCHDOG transmit queue timeout warning
+    - net: amd-xgbe: Reset link when the link never comes back
+    - net: amd-xgbe: Fix network fluctuations when using 1G BELFUSE SFP
+    - net: mvneta: Remove per-cpu queue mapping for Armada 3700
+    - fbdev: aty: SPARC64 requires FB_ATY_CT
+    - drm/gma500: Fix error return code in psb_driver_load()
+    - gma500: clean up error handling in init
+    - drm/fb-helper: Add missed unlocks in setcmap_legacy()
+    - crypto: sun4i-ss - linearize buffers content must be kept
+    - crypto: sun4i-ss - fix kmap usage
+    - crypto: arm64/aes-ce - really hide slower algos when faster ones are enabled
+    - drm/amdgpu: Fix macro name _AMDGPU_TRACE_H_ in preprocessor if condition
+    - MIPS: c-r4k: Fix section mismatch for loongson2_sc_init
+    - MIPS: lantiq: Explicitly compare LTQ_EBU_PCC_ISTAT against 0
+    - media: i2c: ov5670: Fix PIXEL_RATE minimum value
+    - media: imx: Unregister csc/scaler only if registered
+    - media: imx: Fix csc/scaler unregister
+    - media: camss: missing error code in msm_video_register()
+    - media: vsp1: Fix an error handling path in the probe function
+    - media: em28xx: Fix use-after-free in em28xx_alloc_urbs
+    - media: media/pci: Fix memleak in empress_init
+    - media: tm6000: Fix memleak in tm6000_start_stream
+    - media: aspeed: fix error return code in aspeed_video_setup_video()
+    - ASoC: cs42l56: fix up error handling in probe
+    - evm: Fix memleak in init_desc
+    - crypto: bcm - Rename struct device_private to bcm_device_private
+    - drm/sun4i: tcon: fix inverted DCLK polarity
+    - MIPS: properly stop .eh_frame generation
+    - bsg: free the request before return error code
+    - drm/amd/display: Fix 10/12 bpc setup in DCE output bit depth reduction.
+    - drm/amd/display: Fix HDMI deep color output for DCE 6-11.
+    - media: software_node: Fix refcounts in software_node_get_next_child()
+    - media: lmedm04: Fix misuse of comma
+    - media: qm1d1c0042: fix error return code in qm1d1c0042_init()
+    - media: cx25821: Fix a bug when reallocating some dma memory
+    - media: pxa_camera: declare variable when DEBUG is defined
+    - media: uvcvideo: Accept invalid bFormatIndex and bFrameIndex values
+    - sched/eas: Don't update misfit status if the task is pinned
+    - mtd: parser: imagetag: fix error codes in
+      bcm963xx_parse_imagetag_partitions()
+    - crypto: talitos - Work around SEC6 ERRATA (AES-CTR mode data size error)
+    - drm/nouveau: bail out of nouveau_channel_new if channel init fails
+    - ata: ahci_brcm: Add back regulators management
+    - ASoC: cpcap: fix microphone timeslot mask
+    - mtd: parsers: afs: Fix freeing the part name memory in failure
+    - f2fs: fix to avoid inconsistent quota data
+    - drm/amdgpu: Prevent shift wrapping in amdgpu_read_mask()
+    - f2fs: fix a wrong condition in __submit_bio
+    - Drivers: hv: vmbus: Avoid use-after-free in vmbus_onoffer_rescind()
+    - ASoC: SOF: debug: Fix a potential issue on string buffer termination
+    - btrfs: clarify error returns values in __load_free_space_cache
+    - hwrng: timeriomem - Fix cooldown period calculation
+    - crypto: ecdh_helper - Ensure 'len >= secret.len' in decode_key()
+    - ima: Free IMA measurement buffer on error
+    - ima: Free IMA measurement buffer after kexec syscall
+    - ASoC: simple-card-utils: Fix device module clock
+    - fs/jfs: fix potential integer overflow on shift of a int
+    - jffs2: fix use after free in jffs2_sum_write_data()
+    - ubifs: Fix memleak in ubifs_init_authentication
+    - ubifs: Fix error return code in alloc_wbufs()
+    - capabilities: Don't allow writing ambiguous v3 file capabilities
+    - HSI: Fix PM usage counter unbalance in ssi_hw_init
+    - clk: meson: clk-pll: fix initializing the old rate (fallback) for a PLL
+    - clk: meson: clk-pll: make "ret" a signed integer
+    - clk: meson: clk-pll: propagate the error from meson_clk_pll_set_rate()
+    - quota: Fix memory leak when handling corrupted quota file
+    - i2c: iproc: handle only slave interrupts which are enabled
+    - i2c: iproc: update slave isr mask (ISR_MASK_SLAVE)
+    - i2c: iproc: handle master read request
+    - spi: cadence-quadspi: Abort read if dummy cycles required are too many
+    - clk: sunxi-ng: h6: Fix CEC clock
+    - HID: core: detect and skip invalid inputs to snto32()
+    - RDMA/siw: Fix handling of zero-sized Read and Receive Queues.
+    - dmaengine: fsldma: Fix a resource leak in the remove function
+    - dmaengine: fsldma: Fix a resource leak in an error handling path of the
+      probe function
+    - dmaengine: owl-dma: Fix a resource leak in the remove function
+    - dmaengine: hsu: disable spurious interrupt
+    - mfd: bd9571mwv: Use devm_mfd_add_devices()
+    - fdt: Properly handle "no-map" field in the memory region
+    - of/fdt: Make sure no-map does not remove already reserved regions
+    - power: reset: at91-sama5d2_shdwc: fix wkupdbc mask
+    - rtc: s5m: select REGMAP_I2C
+    - clocksource/drivers/ixp4xx: Select TIMER_OF when needed
+    - clocksource/drivers/mxs_timer: Add missing semicolon when DEBUG is defined
+    - RDMA/mlx5: Use the correct obj_id upon DEVX TIR creation
+    - clk: sunxi-ng: h6: Fix clock divider range on some clocks
+    - regulator: axp20x: Fix reference cout leak
+    - certs: Fix blacklist flag type confusion
+    - regulator: s5m8767: Fix reference count leak
+    - spi: atmel: Put allocated master before return
+    - regulator: s5m8767: Drop regulators OF node reference
+    - regulator: core: Avoid debugfs: Directory ... already present! error
+    - isofs: release buffer head before return
+    - auxdisplay: ht16k33: Fix refresh rate handling
+    - objtool: Fix error handling for STD/CLD warnings
+    - objtool: Fix ".cold" section suffix check for newer versions of GCC
+    - IB/umad: Return EIO in case of when device disassociated
+    - IB/umad: Return EPOLLERR in case of when device disassociated
+    - KVM: PPC: Make the VMX instruction emulation routines static
+    - powerpc/47x: Disable 256k page size
+    - mmc: sdhci-sprd: Fix some resource leaks in the remove function
+    - mmc: usdhi6rol0: Fix a resource leak in the error handling path of the probe
+    - mmc: renesas_sdhi_internal_dmac: Fix DMA buffer alignment from 8 to
+      128-bytes
+    - ARM: 9046/1: decompressor: Do not clear SCTLR.nTLSMD for ARMv7+ cores
+    - i2c: qcom-geni: Store DMA mapping data in geni_i2c_dev struct
+    - amba: Fix resource leak for drivers without .remove
+    - IB/mlx5: Return appropriate error code instead of ENOMEM
+    - IB/cm: Avoid a loop when device has 255 ports
+    - tracepoint: Do not fail unregistering a probe due to memory failure
+    - perf tools: Fix DSO filtering when not finding a map for a sampled address
+    - perf vendor events arm64: Fix Ampere eMag event typo
+    - RDMA/rxe: Fix coding error in rxe_recv.c
+    - RDMA/rxe: Fix coding error in rxe_rcv_mcast_pkt
+    - RDMA/rxe: Correct skb on loopback path
+    - spi: stm32: properly handle 0 byte transfer
+    - mfd: wm831x-auxadc: Prevent use after free in wm831x_auxadc_read_irq()
+    - powerpc/pseries/dlpar: handle ibm, configure-connector delay status
+    - powerpc/8xx: Fix software emulation interrupt
+    - clk: qcom: gcc-msm8998: Fix Alpha PLL type for all GPLLs
+    - RDMA/hns: Fixed wrong judgments in the goto branch
+    - RDMA/siw: Fix calculation of tx_valid_cpus size
+    - RDMA/hns: Fix type of sq_signal_bits
+    - spi: pxa2xx: Fix the controller numbering for Wildcat Point
+    - regulator: qcom-rpmh: fix pm8009 ldo7
+    - clk: aspeed: Fix APLL calculate formula from ast2600-A2
+    - nfsd: register pernet ops last, unregister first
+    - RDMA/hns: Fixes missing error code of CMDQ
+    - Input: sur40 - fix an error code in sur40_probe()
+    - perf intel-pt: Fix missing CYC processing in PSB
+    - perf intel-pt: Fix premature IPC
+    - perf test: Fix unaligned access in sample parsing test
+    - Input: elo - fix an error code in elo_connect()
+    - sparc64: only select COMPAT_BINFMT_ELF if BINFMT_ELF is set
+    - misc: eeprom_93xx46: Fix module alias to enable module autoprobe
+    - phy: rockchip-emmc: emmc_phy_init() always return 0
+    - misc: eeprom_93xx46: Add module alias to avoid breaking support for non
+      device tree users
+    - soundwire: cadence: fix ACK/NAK handling
+    - pwm: rockchip: rockchip_pwm_probe(): Remove superfluous clk_unprepare()
+    - VMCI: Use set_page_dirty_lock() when unregistering guest memory
+    - PCI: Align checking of syscall user config accessors
+    - mei: hbm: call mei_set_devstate() on hbm stop response
+    - drm/msm/dsi: Correct io_start for MSM8994 (20nm PHY)
+    - drm/msm/mdp5: Fix wait-for-commit for cmd panels
+    - vfio/iommu_type1: Fix some sanity checks in detach group
+    - ext4: fix potential htree index checksum corruption
+    - nvmem: core: Fix a resource leak on error in nvmem_add_cells_from_of()
+    - nvmem: core: skip child nodes not matching binding
+    - regmap: sdw: use _no_pm functions in regmap_read/write
+    - i40e: Fix flow for IPv6 next header (extension header)
+    - i40e: Add zero-initialization of AQ command structures
+    - i40e: Fix overwriting flow control settings during driver loading
+    - i40e: Fix addition of RX filters after enabling FW LLDP agent
+    - i40e: Fix VFs not created
+    - i40e: Fix add TC filter for IPv6
+    - vfio/type1: Use follow_pte()
+    - net/mlx4_core: Add missed mlx4_free_cmd_mailbox()
+    - vxlan: move debug check after netdev unregister
+    - ocfs2: fix a use after free on error
+    - mm/memory.c: fix potential pte_unmap_unlock pte error
+    - mm/hugetlb: fix potential double free in hugetlb_register_node() error path
+    - mm/compaction: fix misbehaviors of fast_find_migrateblock()
+    - r8169: fix jumbo packet handling on RTL8168e
+    - arm64: Add missing ISB after invalidating TLB in __primary_switch
+    - i2c: brcmstb: Fix brcmstd_send_i2c_cmd condition
+    - mm/rmap: fix potential pte_unmap on an not mapped pte
+    - scsi: bnx2fc: Fix Kconfig warning & CNIC build errors
+    - blk-settings: align max_sectors on "logical_block_size" boundary
+    - ACPI: property: Fix fwnode string properties matching
+    - ACPI: configfs: add missing check after configfs_register_default_group()
+    - HID: logitech-dj: add support for keyboard events in eQUAD step 4 Gaming
+    - HID: wacom: Ignore attempts to overwrite the touch_max value from HID
+    - Input: raydium_ts_i2c - do not send zero length
+    - Input: xpad - add support for PowerA Enhanced Wired Controller for Xbox
+      Series X|S
+    - Input: joydev - prevent potential read overflow in ioctl
+    - Input: i8042 - add ASUS Zenbook Flip to noselftest list
+    - media: mceusb: Fix potential out-of-bounds shift
+    - USB: serial: option: update interface mapping for ZTE P685M
+    - usb: musb: Fix runtime PM race in musb_queue_resume_work
+    - usb: dwc3: gadget: Fix setting of DEPCFG.bInterval_m1
+    - usb: dwc3: gadget: Fix dep->interval for fullspeed interrupt
+    - USB: serial: ftdi_sio: fix FTX sub-integer prescaler
+    - USB: serial: mos7840: fix error code in mos7840_write()
+    - USB: serial: mos7720: fix error code in mos7720_write()
+    - ALSA: hda: Add another CometLake-H PCI ID
+    - ALSA: hda/realtek: modify EAPD in the ALC886
+    - Revert "bcache: Kill btree_io_wq"
+    - bcache: Give btree_io_wq correct semantics again
+    - bcache: Move journal work to new flush wq
+    - drm/amd/display: Add vupdate_no_lock interrupts for DCN2.1
+    - drm/amdgpu: Set reference clock to 100Mhz on Renoir (v2)
+    - drm/nouveau/kms: handle mDP connectors
+    - drm/sched: Cancel and flush all outstanding jobs before finish.
+    - erofs: initialized fields can only be observed after bit is set
+    - tpm_tis: Fix check_locality for correct locality acquisition
+    - tpm_tis: Clean up locality release
+    - KEYS: trusted: Fix migratable=1 failing
+    - btrfs: abort the transaction if we fail to inc ref in btrfs_copy_root
+    - btrfs: fix reloc root leak with 0 ref reloc roots on recovery
+    - btrfs: splice remaining dirty_bg's onto the transaction dirty bg list
+    - btrfs: fix extent buffer leak on failure to copy root
+    - crypto: arm64/sha - add missing module aliases
+    - crypto: aesni - prevent misaligned buffers on the stack
+    - crypto: sun4i-ss - checking sg length is not sufficient
+    - crypto: sun4i-ss - handle BigEndian for cipher
+    - crypto: sun4i-ss - initialize need_fallback
+    - seccomp: Add missing return in non-void function
+    - misc: rtsx: init of rts522a add OCP power off when no card is present
+    - drivers/misc/vmw_vmci: restrict too big queue size in qp_host_alloc_queue
+    - pstore: Fix typo in compression option name
+    - dts64: mt7622: fix slow sd card access
+    - staging/mt7621-dma: mtk-hsdma.c->hsdma-mt7621.c
+    - staging: gdm724x: Fix DMA from stack
+    - staging: rtl8188eu: Add Edimax EW-7811UN V2 to device table
+    - media: ipu3-cio2: Fix mbus_code processing in cio2_subdev_set_fmt()
+    - x86/virt: Eat faults on VMXOFF in reboot flows
+    - x86/reboot: Force all cpus to exit VMX root if VMX is supported
+    - powerpc/prom: Fix "ibm,arch-vec-5-platform-support" scan
+    - rcu: Pull deferred rcuog wake up to rcu_eqs_enter() callers
+    - rcu/nocb: Perform deferred wake up before last idle's need_resched() check
+    - floppy: reintroduce O_NDELAY fix
+    - arm64: kexec_file: fix memory leakage in create_dtb() when fdt_open_into()
+      fails
+    - arm64: uprobe: Return EOPNOTSUPP for AARCH32 instruction probing
+    - watchdog: qcom: Remove incorrect usage of QCOM_WDT_ENABLE_IRQ
+    - watchdog: mei_wdt: request stop on unregister
+    - mtd: spi-nor: sfdp: Fix last erase region marking
+    - mtd: spi-nor: sfdp: Fix wrong erase type bitmask for overlaid region
+    - mtd: spi-nor: core: Fix erase type discovery for overlaid region
+    - mtd: spi-nor: core: Add erase size check for erase command initialization
+    - mtd: spi-nor: hisi-sfc: Put child node np on error path
+    - fs/affs: release old buffer head on error path
+    - seq_file: document how per-entry resources are managed.
+    - x86: fix seq_file iteration for pat/memtype.c
+    - hugetlb: fix update_and_free_page contig page struct assumption
+    - hugetlb: fix copy_huge_page_from_user contig page struct assumption
+    - arm64: Extend workaround for erratum 1024718 to all versions of Cortex-A55
+    - media: smipcie: fix interrupt handling and IR timeout
+    - module: Ignore _GLOBAL_OFFSET_TABLE_ when warning for undefined symbols
+    - mmc: sdhci-esdhc-imx: fix kernel panic when remove module
+    - powerpc/32s: Add missing call to kuep_lock on syscall entry
+    - spmi: spmi-pmic-arb: Fix hw_irq overflow
+    - gpio: pcf857x: Fix missing first interrupt
+    - printk: fix deadlock when kernel panic
+    - cpufreq: intel_pstate: Get per-CPU max freq via MSR_HWP_CAPABILITIES if
+      available
+    - s390/vtime: fix inline assembly clobber list
+    - virtio/s390: implement virtio-ccw revision 2 correctly
+    - um: mm: check more comprehensively for stub changes
+    - f2fs: fix out-of-repair __setattr_copy()
+    - sparc32: fix a user-triggerable oops in clear_user()
+    - spi: spi-synquacer: fix set_cs handling
+    - gfs2: Don't skip dlm unlock if glock has an lvb
+    - gfs2: Recursive gfs2_quota_hold in gfs2_iomap_end
+    - dm: fix deadlock when swapping to encrypted device
+    - dm writecache: fix writing beyond end of underlying device when shrinking
+    - dm era: Recover committed writeset after crash
+    - dm era: Verify the data block size hasn't changed
+    - dm era: Fix bitset memory leaks
+    - dm era: Use correct value size in equality function of writeset tree
+    - dm era: Reinitialize bitset cache before digesting a new writeset
+    - dm era: only resize metadata in preresume
+    - drm/i915: Reject 446-480MHz HDMI clock on GLK
+    - icmp: introduce helper for nat'd source address in network device context
+    - icmp: allow icmpv6_ndo_send to work with CONFIG_IPV6=n
+    - gtp: use icmp_ndo_send helper
+    - sunvnet: use icmp_ndo_send helper
+    - xfrm: interface: use icmp_ndo_send helper
+    - ipv6: icmp6: avoid indirect call for icmpv6_send()
+    - ipv6: silence compilation warning for non-IPV6 builds
+    - net: icmp: pass zeroed opts from icmp{,v6}_ndo_send before sending
+    - net: sched: fix police ext initialization
+    - dm era: Update in-core bitset after committing the metadata
+    - net: qrtr: Fix memory leak in qrtr_tun_open
+    - ARM: dts: aspeed: Add LCLK to lpc-snoop
+    - Linux 5.4.102
+  * eeh-basic.sh from powerpc in ubuntu_kernel_selftests failed with unexpected
+    operator on F-5.8 (LP: #1909428)
+    - selftests/powerpc: Make the test check in eeh-basic.sh posix compliant
+
+  [ Ubuntu: 5.4.0-72.80 ]
+
+  * overlayfs calls vfs_setxattr without cap_convert_nscap
+    - vfs: move cap_convert_nscap() call into vfs_setxattr()
+  * CVE-2021-3492
+    - SAUCE: shiftfs: free allocated memory in shiftfs_btrfs_ioctl_fd_replace()
+      error paths
+    - SAUCE: shiftfs: handle copy_to_user() return values correctly
+  * CVE-2021-29154
+    - SAUCE: bpf, x86: Validate computation of branch displacements for x86-64
+    - SAUCE: bpf, x86: Validate computation of branch displacements for x86-32
+
+  [ Ubuntu: 5.4.0-71.79 ]
+
+  * focal/linux: 5.4.0-71.79 -proposed tracker (LP: #1921040)
+  * selftests: bpf verifier fails after sanitize_ptr_alu fixes (LP: #1920995)
+    - bpf: Simplify alu_limit masking for pointer arithmetic
+    - bpf: Add sanity check for upper ptr_limit
+    - bpf, selftests: Fix up some test_verifier cases for unprivileged
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+  * Fix missing HDMI/DP audio on NVidia card after S3 (LP: #1918228)
+    - ALSA: hda/hdmi: Reduce hda_jack_tbl lookup at unsol event handling
+    - ALSA: hda/hdmi: Don't use standard hda_jack for generic HDMI jacks
+    - ALSA: hda/hdmi: Move runtime PM resume into hdmi_present_sense_via_verbs()
+    - ALSA: hda/hdmi: Move ELD parse and jack reporting into update_eld()
+  * Focal update: v5.4.101 upstream stable release (LP: #1918170)
+    - HID: make arrays usage and value to be the same
+    - USB: quirks: sort quirk entries
+    - usb: quirks: add quirk to start video capture on ELMO L-12F document camera
+      reliable
+    - ntfs: check for valid standard information attribute
+    - arm64: tegra: Add power-domain for Tegra210 HDA
+    - scripts: use pkg-config to locate libcrypto
+    - scripts: set proper OpenSSL include dir also for sign-file
+    - mm: unexport follow_pte_pmd
+    - mm: simplify follow_pte{,pmd}
+    - KVM: do not assume PTE is writable after follow_pfn
+    - mm: provide a saner PTE walking API for modules
+    - KVM: Use kvm_pfn_t for local PFN variable in hva_to_pfn_remapped()
+    - NET: usb: qmi_wwan: Adding support for Cinterion MV31
+    - cxgb4: Add new T6 PCI device id 0x6092
+    - cifs: Set CIFS_MOUNT_USE_PREFIX_PATH flag on setting cifs_sb->prepath.
+    - scripts/recordmcount.pl: support big endian for ARCH sh
+    - Linux 5.4.101
+  * Focal update: v5.4.100 upstream stable release (LP: #1918168)
+    - KVM: SEV: fix double locking due to incorrect backport
+    - net: qrtr: Fix port ID for control messages
+    - net: bridge: Fix a warning when del bridge sysfs
+    - Xen/x86: don't bail early from clear_foreign_p2m_mapping()
+    - Xen/x86: also check kernel mapping in set_foreign_p2m_mapping()
+    - Xen/gntdev: correct dev_bus_addr handling in gntdev_map_grant_pages()
+    - Xen/gntdev: correct error checking in gntdev_map_grant_pages()
+    - xen/arm: don't ignore return errors from set_phys_to_machine
+    - xen-blkback: don't "handle" error by BUG()
+    - xen-netback: don't "handle" error by BUG()
+    - xen-scsiback: don't "handle" error by BUG()
+    - xen-blkback: fix error handling in xen_blkbk_map()
+    - media: pwc: Use correct device for DMA
+    - btrfs: fix backport of 2175bf57dc952 in 5.4.95
+    - Linux 5.4.100
+  * Focal update: v5.4.99 upstream stable release (LP: #1918167)
+    - gpio: ep93xx: fix BUG_ON port F usage
+    - gpio: ep93xx: Fix single irqchip with multi gpiochips
+    - tracing: Do not count ftrace events in top level enable output
+    - tracing: Check length before giving out the filter buffer
+    - arm/xen: Don't probe xenbus as part of an early initcall
+    - cgroup: fix psi monitor for root cgroup
+    - arm64: dts: rockchip: Fix PCIe DT properties on rk3399
+    - arm64: dts: qcom: sdm845: Reserve LPASS clocks in gcc
+    - ARM: OMAP2+: Fix suspcious RCU usage splats for omap_enter_idle_coupled
+    - platform/x86: hp-wmi: Disable tablet-mode reporting by default
+    - ovl: perform vfs_getxattr() with mounter creds
+    - cap: fix conversions on getxattr
+    - ovl: skip getxattr of security labels
+    - nvme-pci: ignore the subsysem NQN on Phison E16
+    - drm/amd/display: Add more Clock Sources to DCN2.1
+    - drm/amd/display: Fix dc_sink kref count in emulated_link_detect
+    - drm/amd/display: Free atomic state after drm_atomic_commit
+    - drm/amd/display: Decrement refcount of dc_sink before reassignment
+    - riscv: virt_addr_valid must check the address belongs to linear mapping
+    - bfq-iosched: Revert "bfq: Fix computation of shallow depth"
+    - ARM: dts: lpc32xx: Revert set default clock rate of HCLK PLL
+    - ARM: ensure the signal page contains defined contents
+    - ARM: kexec: fix oops after TLB are invalidated
+    - vmlinux.lds.h: Create section for protection against instrumentation
+    - lkdtm: don't move ctors to .rodata
+    - mt76: dma: fix a possible memory leak in mt76_add_fragment()
+    - drm/vc4: hvs: Fix buffer overflow with the dlist handling
+    - bpf: Check for integer overflow when using roundup_pow_of_two()
+    - netfilter: xt_recent: Fix attempt to update deleted entry
+    - netfilter: nftables: fix possible UAF over chains from packet path in netns
+    - netfilter: flowtable: fix tcp and udp header checksum update
+    - xen/netback: avoid race in xenvif_rx_ring_slots_available()
+    - net: enetc: initialize the RFS and RSS memories
+    - selftests: txtimestamp: fix compilation issue
+    - net: stmmac: set TxQ mode back to DCB after disabling CBS
+    - ibmvnic: Clear failover_pending if unable to schedule
+    - netfilter: conntrack: skip identical origin tuple in same zone only
+    - x86/build: Disable CET instrumentation in the kernel for 32-bit too
+    - net: hns3: add a check for queue_id in hclge_reset_vf_queue()
+    - firmware_loader: align .builtin_fw to 8
+    - drm/sun4i: tcon: set sync polarity for tcon1 channel
+    - drm/sun4i: Fix H6 HDMI PHY configuration
+    - drm/sun4i: dw-hdmi: Fix max. frequency for H6
+    - clk: sunxi-ng: mp: fix parent rate change flag check
+    - i2c: stm32f7: fix configuration of the digital filter
+    - h8300: fix PREEMPTION build, TI_PRE_COUNT undefined
+    - usb: dwc3: ulpi: fix checkpatch warning
+    - usb: dwc3: ulpi: Replace CPU-based busyloop with Protocol-based one
+    - rxrpc: Fix clearance of Tx/Rx ring when releasing a call
+    - udp: fix skb_copy_and_csum_datagram with odd segment sizes
+    - net: dsa: call teardown method on probe failure
+    - net: gro: do not keep too many GRO packets in napi->rx_list
+    - net: fix iteration for sctp transport seq_files
+    - net/vmw_vsock: improve locking in vsock_connect_timeout()
+    - net: watchdog: hold device global xmit lock during tx disable
+    - vsock/virtio: update credit only if socket is not closed
+    - vsock: fix locking in vsock_shutdown()
+    - net/rds: restrict iovecs length for RDS_CMSG_RDMA_ARGS
+    - net/qrtr: restrict user-controlled length in qrtr_tun_write_iter()
+    - ovl: expand warning in ovl_d_real()
+    - Linux 5.4.99
+  * Focal update: v5.4.98 upstream stable release (LP: #1918158)
+    - tracing/kprobe: Fix to support kretprobe events on unloaded modules
+    - af_key: relax availability checks for skb size calculation
+    - regulator: core: avoid regulator_resolve_supply() race condition
+    - mac80211: 160MHz with extended NSS BW in CSA
+    - ASoC: Intel: Skylake: Zero snd_ctl_elem_value
+    - chtls: Fix potential resource leak
+    - pNFS/NFSv4: Try to return invalid layout in pnfs_layout_process()
+    - ASoC: ak4458: correct reset polarity
+    - iwlwifi: mvm: skip power command when unbinding vif during CSA
+    - iwlwifi: mvm: take mutex for calling iwl_mvm_get_sync_time()
+    - iwlwifi: pcie: add a NULL check in iwl_pcie_txq_unmap
+    - iwlwifi: pcie: fix context info memory leak
+    - iwlwifi: mvm: invalidate IDs of internal stations at mvm start
+    - iwlwifi: mvm: guard against device removal in reprobe
+    - SUNRPC: Move simple_get_bytes and simple_get_netobj into private header
+    - SUNRPC: Handle 0 length opaque XDR object data properly
+    - i2c: mediatek: Move suspend and resume handling to NOIRQ phase
+    - blk-cgroup: Use cond_resched() when destroy blkgs
+    - regulator: Fix lockdep warning resolving supplies
+    - Fix unsynchronized access to sev members through svm_register_enc_region
+    - squashfs: add more sanity checks in id lookup
+    - squashfs: add more sanity checks in inode lookup
+    - squashfs: add more sanity checks in xattr id lookup
+    - Linux 5.4.98
+  * Enforce CONFIG_DRM_BOCHS=m (LP: #1916290)
+    - [Config] Enforce CONFIG_DRM_BOCHS=m
+  * powerpc/eeh-basic.sh in kselftest make P8 node stopped working
+    (LP: #1916468)
+    - selftests/eeh: Skip ahci adapters
+  * Focal update: v5.4.97 upstream stable release (LP: #1916066)
+    - USB: serial: cp210x: add pid/vid for WSDA-200-USB
+    - USB: serial: cp210x: add new VID/PID for supporting Teraoka AD2000
+    - USB: serial: option: Adding support for Cinterion MV31
+    - arm64: dts: qcom: c630: keep both touchpad devices enabled
+    - arm64: dts: amlogic: meson-g12: Set FL-adj property value
+    - arm64: dts: rockchip: fix vopl iommu irq on px30
+    - bpf, cgroup: Fix optlen WARN_ON_ONCE toctou
+    - bpf, cgroup: Fix problematic bounds check
+    - um: virtio: free vu_dev only with the contained struct device
+    - rxrpc: Fix deadlock around release of dst cached on udp tunnel
+    - arm64: dts: ls1046a: fix dcfg address range
+    - igc: set the default return value to -IGC_ERR_NVM in igc_write_nvm_srwr
+    - igc: check return value of ret_val in igc_config_fc_after_link_up
+    - i40e: Revert "i40e: don't report link up for a VF who hasn't enabled queues"
+    - net/mlx5: Fix leak upon failure of rule creation
+    - net: lapb: Copy the skb before sending a packet
+    - net: mvpp2: TCAM entry enable should be written after SRAM data
+    - r8169: fix WoL on shutdown if CONFIG_DEBUG_SHIRQ is set
+    - ARM: dts: sun7i: a20: bananapro: Fix ethernet phy-mode
+    - nvmet-tcp: fix out-of-bounds access when receiving multiple h2cdata PDUs
+    - memblock: do not start bottom-up allocations with kernel_end
+    - USB: gadget: legacy: fix an error code in eth_bind()
+    - USB: usblp: don't call usb_set_interface if there's a single alt
+    - usb: renesas_usbhs: Clear pipe running flag in usbhs_pkt_pop()
+    - usb: dwc2: Fix endpoint direction check in ep_from_windex
+    - usb: dwc3: fix clock issue during resume in OTG mode
+    - usb: xhci-mtk: fix unreleased bandwidth data
+    - usb: xhci-mtk: skip dropping bandwidth of unchecked endpoints
+    - usb: xhci-mtk: break loop when find the endpoint to drop
+    - usb: host: xhci-plat: add priv quirk for skip PHY initialization
+    - ovl: fix dentry leak in ovl_get_redirect
+    - mac80211: fix station rate table updates on assoc
+    - fgraph: Initialize tracing_graph_pause at task creation
+    - kretprobe: Avoid re-registration of the same kretprobe earlier
+    - libnvdimm/dimm: Avoid race between probe and available_slots_show()
+    - genirq/msi: Activate Multi-MSI early when MSI_FLAG_ACTIVATE_EARLY is set
+    - xhci: fix bounce buffer usage for non-sg list case
+    - cifs: report error instead of invalid when revalidating a dentry fails
+    - smb3: Fix out-of-bounds bug in SMB2_negotiate()
+    - smb3: fix crediting for compounding when only one request in flight
+    - mmc: core: Limit retries when analyse of SDIO tuples fails
+    - drm/amd/display: Revert "Fix EDID parsing after resume from suspend"
+    - nvme-pci: avoid the deepest sleep state on Kingston A2000 SSDs
+    - KVM: SVM: Treat SVM as unsupported when running as an SEV guest
+    - KVM: x86: Update emulator context mode if SYSENTER xfers to 64-bit mode
+    - ARM: footbridge: fix dc21285 PCI configuration accessors
+    - mm: hugetlbfs: fix cannot migrate the fallocated HugeTLB page
+    - mm: hugetlb: fix a race between freeing and dissolving the page
+    - mm: hugetlb: fix a race between isolating and freeing page
+    - mm: hugetlb: remove VM_BUG_ON_PAGE from page_huge_active
+    - mm, compaction: move high_pfn to the for loop scope
+    - mm: thp: fix MADV_REMOVE deadlock on shmem THP
+    - x86/build: Disable CET instrumentation in the kernel
+    - x86/apic: Add extra serialization for non-serializing MSRs
+    - iwlwifi: mvm: don't send RFH_QUEUE_CONFIG_CMD with no queues
+    - Input: xpad - sync supported devices with fork on GitHub
+    - iommu/vt-d: Do not use flush-queue when caching-mode is on
+    - md: Set prev_flush_start and flush_bio in an atomic way
+    - neighbour: Prevent a dead entry from updating gc_list
+    - net: ip_tunnel: fix mtu calculation
+    - net: dsa: mv88e6xxx: override existent unicast portvec in port_fdb_add
+    - net: sched: replaced invalid qdisc tree flush helper in qdisc_replace
+    - usb: host: xhci: mvebu: make USB 3.0 PHY optional for Armada 3720
+    - Linux 5.4.97
+  * Focal update: v5.4.96 upstream stable release (LP: #1916061)
+    - net: dsa: bcm_sf2: put device node before return
+    - net: switchdev: don't set port_obj_info->handled true when -EOPNOTSUPP
+    - ibmvnic: Ensure that CRQ entry read are correctly ordered
+    - Revert "Revert "block: end bio with BLK_STS_AGAIN in case of non-mq devs and
+      REQ_NOWAIT""
+    - ACPI: thermal: Do not call acpi_thermal_check() directly
+    - arm64: Fix kernel address detection of __is_lm_address()
+    - arm64: Do not pass tagged addresses to __is_lm_address()
+    - tcp: make TCP_USER_TIMEOUT accurate for zero window probes
+    - btrfs: backref, only collect file extent items matching backref offset
+    - btrfs: backref, don't add refs from shared block when resolving normal
+      backref
+    - btrfs: backref, only search backref entries from leaves of the same root
+    - btrfs: backref, use correct count to resolve normal data refs
+    - net_sched: gen_estimator: support large ewma log
+    - phy: cpcap-usb: Fix warning for missing regulator_disable
+    - platform/x86: touchscreen_dmi: Add swap-x-y quirk for Goodix touchscreen on
+      Estar Beauty HD tablet
+    - platform/x86: intel-vbtn: Support for tablet mode on Dell Inspiron 7352
+    - x86: __always_inline __{rd,wr}msr()
+    - scsi: scsi_transport_srp: Don't block target in failfast state
+    - scsi: libfc: Avoid invoking response handler twice if ep is already
+      completed
+    - scsi: fnic: Fix memleak in vnic_dev_init_devcmd2
+    - ASoC: SOF: Intel: hda: Resume codec to do jack detection
+    - mac80211: fix fast-rx encryption check
+    - scsi: ibmvfc: Set default timeout to avoid crash during migration
+    - udf: fix the problem that the disc content is not displayed
+    - nvme: check the PRINFO bit before deciding the host buffer length
+    - selftests/powerpc: Only test lwm/stmw on big endian
+    - drm/amd/display: Update dram_clock_change_latency for DCN2.1
+    - drm/amd/display: Change function decide_dp_link_settings to avoid infinite
+      looping
+    - objtool: Don't fail on missing symbol table
+    - kthread: Extract KTHREAD_IS_PER_CPU
+    - workqueue: Restrict affinity change to rescuer
+    - Linux 5.4.96
+  * Focal update: v5.4.95 upstream stable release (LP: #1916056)
+    - ICMPv6: Add ICMPv6 Parameter Problem, code 3 definition
+    - IPv6: reply ICMP error if the first fragment don't include all headers
+    - nbd: freeze the queue while we're adding connections
+    - ACPI: sysfs: Prefer "compatible" modalias
+    - kernel: kexec: remove the lock operation of system_transition_mutex
+    - ALSA: hda/realtek: Enable headset of ASUS B1400CEPE with ALC256
+    - ALSA: hda/via: Apply the workaround generically for Clevo machines
+    - media: rc: ensure that uevent can be read directly after rc device register
+    - ARM: dts: imx6qdl-gw52xx: fix duplicate regulator naming
+    - wext: fix NULL-ptr-dereference with cfg80211's lack of commit()
+    - net: usb: qmi_wwan: added support for Thales Cinterion PLSx3 modem family
+    - s390/vfio-ap: No need to disable IRQ after queue reset
+    - PM: hibernate: flush swap writer after marking
+    - drivers: soc: atmel: Avoid calling at91_soc_init on non AT91 SoCs
+    - drivers: soc: atmel: add null entry at the end of at91_soc_allowed_list[]
+    - btrfs: fix possible free space tree corruption with online conversion
+    - KVM: x86/pmu: Fix HW_REF_CPU_CYCLES event pseudo-encoding in
+      intel_arch_events[]
+    - KVM: x86/pmu: Fix UBSAN shift-out-of-bounds warning in intel_pmu_refresh()
+    - KVM: nVMX: Sync unsync'd vmcs02 state to vmcs12 on migration
+    - KVM: x86: get smi pending status correctly
+    - KVM: Forbid the use of tagged userspace addresses for memslots
+    - xen: Fix XenStore initialisation for XS_LOCAL
+    - leds: trigger: fix potential deadlock with libata
+    - arm64: dts: broadcom: Fix USB DMA address translation for Stingray
+    - mt7601u: fix kernel crash unplugging the device
+    - mt7601u: fix rx buffer refcounting
+    - drm/nouveau/svm: fail NOUVEAU_SVM_INIT ioctl on unsupported devices
+    - drm/i915: Check for all subplatform bits
+    - tee: optee: replace might_sleep with cond_resched
+    - xen-blkfront: allow discard-* nodes to be optional
+    - ARM: imx: build suspend-imx6.S with arm instruction set
+    - netfilter: nft_dynset: add timeout extension to template
+    - xfrm: Fix oops in xfrm_replay_advance_bmp
+    - xfrm: fix disable_xfrm sysctl when used on xfrm interfaces
+    - selftests: xfrm: fix test return value override issue in xfrm_policy.sh
+    - xfrm: Fix wraparound in xfrm_policy_addr_delta()
+    - arm64: dts: ls1028a: fix the offset of the reset register
+    - ARM: dts: imx6qdl-kontron-samx6i: fix i2c_lcd/cam default status
+    - firmware: imx: select SOC_BUS to fix firmware build
+    - RDMA/cxgb4: Fix the reported max_recv_sge value
+    - ASoC: Intel: Skylake: skl-topology: Fix OOPs ib skl_tplg_complete
+    - pNFS/NFSv4: Fix a layout segment leak in pnfs_layout_process()
+    - iwlwifi: pcie: use jiffies for memory read spin time limit
+    - iwlwifi: pcie: reschedule in long-running memory reads
+    - mac80211: pause TX while changing interface type
+    - i40e: acquire VSI pointer only after VF is initialized
+    - igc: fix link speed advertising
+    - net/mlx5: Fix memory leak on flow table creation error flow
+    - net/mlx5e: E-switch, Fix rate calculation for overflow
+    - net/mlx5e: Reduce tc unsupported key print level
+    - can: dev: prevent potential information leak in can_fill_info()
+    - nvme-multipath: Early exit if no path is available
+    - selftests: forwarding: Specify interface when invoking mausezahn
+    - iommu/vt-d: Gracefully handle DMAR units with no supported address widths
+    - iommu/vt-d: Don't dereference iommu_device if IOMMU_API is not built
+    - rxrpc: Fix memory leak in rxrpc_lookup_local
+    - NFC: fix resource leak when target index is invalid
+    - NFC: fix possible resource leak
+    - ASoC: topology: Fix memory corruption in soc_tplg_denum_create_values()
+    - team: protect features update by RCU to avoid deadlock
+    - tcp: fix TLP timer not set when CA_STATE changes from DISORDER to OPEN
+    - Linux 5.4.95
+
+  [ Ubuntu: 5.4.0-70.78 ]
+
+  * CVE-2020-27170
+    - bpf: Fix off-by-one for area size in creating mask to left
+  * CVE-2020-27171
+    - bpf: Prohibit alu ops for pointer types not defining ptr_limit
+  * binary assembly failures with CONFIG_MODVERSIONS present (LP: #1919315)
+    - [Packaging] quiet (nomially) benign errors in BUILD script
+
+  [ Ubuntu: 5.4.0-69.77 ]
+
+  * CVE-2021-3444
+    - bpf: Fix 32 bit src register truncation on div/mod
+    - bpf: Fix truncation handling for mod32 dst reg wrt zero
+  * CVE-2021-27365
+    - scsi: iscsi: Verify lengths on passthrough PDUs
+    - sysfs: Add sysfs_emit and sysfs_emit_at to format sysfs output
+    - scsi: iscsi: Ensure sysfs attributes are limited to PAGE_SIZE
+  * CVE-2021-27363 // CVE-2021-27364
+    - scsi: iscsi: Restrict sessions and handles to admin capabilities
+
+  [ Ubuntu: 5.4.0-67.75 ]
+
+  * focal/linux: 5.4.0-67.75 -proposed tracker (LP: #1916169)
+  * Please trust Canonical Livepatch Service kmod signing key (LP: #1898716)
+    - [Config] enable CONFIG_MODVERSIONS=y
+    - [Packaging] build canonical-certs.pem from branch/arch certs
+    - [Config] add Canonical Livepatch Service key to SYSTEM_TRUSTED_KEYS
+    - [Config] add ubuntu-drivers key to SYSTEM_TRUSTED_KEYS
+    - [Config] Allow ASM_MODVERSIONS and MODULE_REL_CRCS
+  * geneve overlay network on vlan interface broken with offload enabled
+    (LP: #1914447)
+    - net/mlx5e: Fix SWP offsets when vlan inserted by driver
+  * Add support for selective build of special drivers (LP: #1912789)
+    - [Packaging] Fix ODM support in actual build
+  * devlink: don't do reporter recovery if the state is healthy (LP: #1915403)
+    - devlink: don't do reporter recovery if the state is healthy
+  * Missing device id for Intel TGL-H ISH [8086:43fc] in intel-ish-hid driver
+    (LP: #1914543)
+    - HID: intel-ish-hid: ipc: Add Tiger Lake H PCI device ID
+  * Focal update: v5.4.94 upstream stable release (LP: #1915200)
+    - gpio: mvebu: fix pwm .get_state period calculation
+    - futex: Ensure the correct return value from futex_lock_pi()
+    - futex: Replace pointless printk in fixup_owner()
+    - futex: Provide and use pi_state_update_owner()
+    - rtmutex: Remove unused argument from rt_mutex_proxy_unlock()
+    - futex: Use pi_state_update_owner() in put_pi_state()
+    - futex: Simplify fixup_pi_state_owner()
+    - futex: Handle faults correctly for PI futexes
+    - HID: wacom: Correct NULL dereference on AES pen proximity
+    - io_uring: Fix current->fs handling in io_sq_wq_submit_work()
+    - tracing: Fix race in trace_open and buffer resize call
+    - arm64: mm: use single quantity to represent the PA to VA translation
+    - SMB3.1.1: do not log warning message if server doesn't populate salt
+    - tools: Factor HOSTCC, HOSTLD, HOSTAR definitions
+    - dm integrity: conditionally disable "recalculate" feature
+    - writeback: Drop I_DIRTY_TIME_EXPIRE
+    - fs: fix lazytime expiration handling in __writeback_single_inode()
+    - Linux 5.4.94
+  * Focal update: v5.4.93 upstream stable release (LP: #1915195)
+    - i2c: bpmp-tegra: Ignore unknown I2C_M flags
+    - platform/x86: ideapad-laptop: Disable touchpad_switch for ELAN0634
+    - ALSA: seq: oss: Fix missing error check in snd_seq_oss_synth_make_info()
+    - ALSA: hda/via: Add minimum mute flag
+    - ACPI: scan: Make acpi_bus_get_device() clear return pointer on error
+    - btrfs: don't get an EINTR during drop_snapshot for reloc
+    - btrfs: fix lockdep splat in btrfs_recover_relocation
+    - btrfs: don't clear ret in btrfs_start_dirty_block_groups
+    - btrfs: send: fix invalid clone operations when cloning from the same file
+      and root
+    - mmc: core: don't initialize block size from ext_csd if not present
+    - mmc: sdhci-xenon: fix 1.8v regulator stabilization
+    - dm: avoid filesystem lookup in dm_get_dev_t()
+    - dm integrity: fix a crash if "recalculate" used without "internal_hash"
+    - drm/atomic: put state on error path
+    - drm/syncobj: Fix use-after-free
+    - drm/i915/gt: Prevent use of engine->wa_ctx after error
+    - ASoC: Intel: haswell: Add missing pm_ops
+    - dm integrity: select CRYPTO_SKCIPHER
+    - scsi: ufs: Correct the LUN used in eh_device_reset_handler() callback
+    - scsi: qedi: Correct max length of CHAP secret
+    - scsi: sd: Suppress spurious errors when WRITE SAME is being disabled
+    - riscv: Fix kernel time_init()
+    - riscv: Fix sifive serial driver
+    - HID: logitech-dj: add the G602 receiver
+    - HID: Ignore battery for Elan touchscreen on ASUS UX550
+    - clk: tegra30: Add hda clock default rates to clock driver
+    - arm64: make atomic helpers __always_inline
+    - xen: Fix event channel callback via INTX/GSI
+    - x86/xen: Add xen_no_vector_callback option to test PCI INTX delivery
+    - dts: phy: fix missing mdio device and probe failure of vsc8541-01 device
+    - riscv: defconfig: enable gpio support for HiFive Unleashed
+    - drm/amdgpu/psp: fix psp gfx ctrl cmds
+    - drm/amd/display: Fix to be able to stop crc calculation
+    - drm/nouveau/bios: fix issue shadowing expansion ROMs
+    - drm/nouveau/privring: ack interrupts the same way as RM
+    - drm/nouveau/i2c/gm200: increase width of aux semaphore owner fields
+    - drm/nouveau/mmu: fix vram heap sizing
+    - drm/nouveau/kms/nv50-: fix case where notifier buffer is at offset 0
+    - powerpc: Use the common INIT_DATA_SECTION macro in vmlinux.lds.S
+    - pinctrl: aspeed: g6: Fix PWMG0 pinctrl setting
+    - scsi: megaraid_sas: Fix MEGASAS_IOC_FIRMWARE regression
+    - powerpc: Fix alignment bug within the init sections
+    - i2c: octeon: check correct size of maximum RECV_LEN packet
+    - platform/x86: intel-vbtn: Drop HP Stream x360 Convertible PC 11 from allow-
+      list
+    - selftests: net: fib_tests: remove duplicate log test
+    - can: dev: can_restart: fix use after free bug
+    - can: vxcan: vxcan_xmit: fix use after free bug
+    - can: peak_usb: fix use after free bugs
+    - iio: ad5504: Fix setting power-down state
+    - cifs: do not fail __smb_send_rqst if non-fatal signals are pending
+    - irqchip/mips-cpu: Set IPI domain parent chip
+    - x86/fpu: Add kernel_fpu_begin_mask() to selectively initialize state
+    - x86/topology: Make __max_die_per_package available unconditionally
+    - x86/mmx: Use KFPU_387 for MMX string operations
+    - intel_th: pci: Add Alder Lake-P support
+    - stm class: Fix module init return on allocation failure
+    - serial: mvebu-uart: fix tx lost characters at power off
+    - ehci: fix EHCI host controller initialization sequence
+    - USB: ehci: fix an interrupt calltrace error
+    - usb: gadget: aspeed: fix stop dma register setting.
+    - usb: udc: core: Use lock when write to soft_connect
+    - [Config] updateconfigs for USB_BDC_PCI
+    - usb: bdc: Make bdc pci driver depend on BROKEN
+    - xhci: make sure TRB is fully written before giving it to the controller
+    - xhci: tegra: Delay for disabling LFPS detector
+    - driver core: Extend device_is_dependent()
+    - pinctrl: ingenic: Fix JZ4760 support
+    - x86/cpu/amd: Set __max_die_per_package on AMD
+    - netfilter: rpfilter: mask ecn bits before fib lookup
+    - sh: dma: fix kconfig dependency for G2_DMA
+    - net: dsa: mv88e6xxx: also read STU state in mv88e6250_g1_vtu_getnext
+    - sh_eth: Fix power down vs. is_opened flag ordering
+    - lightnvm: fix memory leak when submit fails
+    - skbuff: back tiny skbs with kmalloc() in __netdev_alloc_skb() too
+    - kasan: fix unaligned address is unhandled in kasan_remove_zero_shadow
+    - kasan: fix incorrect arguments passing in kasan_add_zero_shadow
+    - udp: mask TOS bits in udp_v4_early_demux()
+    - ipv6: create multicast route with RTPROT_KERNEL
+    - net_sched: avoid shift-out-of-bounds in tcindex_set_parms()
+    - net_sched: reject silly cell_log in qdisc_get_rtab()
+    - ipv6: set multicast flag on the multicast route
+    - net: mscc: ocelot: allow offloading of bridge on top of LAG
+    - net: Disable NETIF_F_HW_TLS_RX when RXCSUM is disabled
+    - net: dsa: b53: fix an off by one in checking "vlan->vid"
+    - tcp: do not mess with cloned skbs in tcp_add_backlog()
+    - tcp: fix TCP_USER_TIMEOUT with zero window
+    - Linux 5.4.93
+  * High load from process irq/65-i2c-INT3  - kernel module tps6598x
+    (LP: #1883511) // Focal update: v5.4.93 upstream stable release
+    (LP: #1915195)
+    - platform/x86: i2c-multi-instantiate: Don't create platform device for
+      INT3515 ACPI nodes
+  * Focal update: v5.4.92 upstream stable release (LP: #1915186)
+    - usb: ohci: Make distrust_firmware param default to false
+    - compiler.h: Raise minimum version of GCC to 5.1 for arm64
+    - xen/privcmd: allow fetching resource sizes
+    - elfcore: fix building with clang
+    - scsi: lpfc: Make lpfc_defer_acc_rsp static
+    - spi: npcm-fiu: simplify the return expression of npcm_fiu_probe()
+    - spi: npcm-fiu: Disable clock in probe error path
+    - nfsd4: readdirplus shouldn't return parent of export
+    - bpf: Don't leak memory in bpf getsockopt when optlen == 0
+    - bpf: Fix helper bpf_map_peek_elem_proto pointing to wrong callback
+    - udp: Prevent reuseport_select_sock from reading uninitialized socks
+    - netxen_nic: fix MSI/MSI-x interrupts
+    - net: introduce skb_list_walk_safe for skb segment walking
+    - net: skbuff: disambiguate argument and member for skb_list_walk_safe helper
+    - net: ipv6: Validate GSO SKB before finish IPv6 processing
+    - mlxsw: core: Add validation of transceiver temperature thresholds
+    - mlxsw: core: Increase critical threshold for ASIC thermal zone
+    - net: mvpp2: Remove Pause and Asym_Pause support
+    - rndis_host: set proper input size for OID_GEN_PHYSICAL_MEDIUM request
+    - esp: avoid unneeded kmap_atomic call
+    - net: dcb: Validate netlink message in DCB handler
+    - net: dcb: Accept RTM_GETDCB messages carrying set-like DCB commands
+    - rxrpc: Call state should be read with READ_ONCE() under some circumstances
+    - net: stmmac: Fixed mtu channged by cache aligned
+    - net: sit: unregister_netdevice on newlink's error path
+    - net: avoid 32 x truesize under-estimation for tiny skbs
+    - rxrpc: Fix handling of an unsupported token type in rxrpc_read()
+    - net, sctp, filter: remap copy_from_user failure error
+    - tipc: fix NULL deref in tipc_link_xmit()
+    - mac80211: do not drop tx nulldata packets on encrypted links
+    - mac80211: check if atf has been disabled in __ieee80211_schedule_txq
+    - spi: cadence: cache reference clock rate during probe
+    - Linux 5.4.92
+  * intel-hid is not loaded on new Intel platform (LP: #1907160)
+    - platform/x86: intel-hid: Add Tiger Lake ACPI device ID
+    - platform/x86: intel-hid: fix: Update Tiger Lake ACPI device ID
+    - platform/x86: intel-hid: Move MODULE_DEVICE_TABLE() closer to the table
+    - platform/x86: intel-hid: add Rocket Lake ACPI device ID
+  * Support Advantech UNO-420 platform (LP: #1902672)
+    - ODM: MAINTAINERS: Add Advantech AHC1EC0 embedded controller entry
+    - ODM: mfd: ahc1ec0: Add Advantech EC include file used by dt-bindings
+    - ODM: dt-bindings: mfd: ahc1ec0.yaml: Add Advantech embedded controller -
+      AHC1EC0
+    - ODM: mfd: ahc1ec0: Add support for Advantech embedded controller
+    - ODM: hwmon: ahc1ec0-hwmon: Add sub-device hwmon for Advantech embedded
+      controller
+    - ODM: watchdog: ahc1ec0-wdt: Add sub-device watchdog for Advantech embedded
+      controller
+    - ODM: [Config] update config for Advantech devices
+  * Remove scary stack trace from Realtek WiFi driver (LP: #1913263)
+    - rtw88: reduce the log level for failure of tx report
+  * Focal update: v5.4.91 upstream stable release (LP: #1914654)
+    - kbuild: enforce -Werror=return-type
+    - btrfs: prevent NULL pointer dereference in extent_io_tree_panic
+    - ASoC: dapm: remove widget from dirty list on free
+    - x86/hyperv: check cpu mask after interrupt has been disabled
+    - tracing/kprobes: Do the notrace functions check without kprobes on ftrace
+    - [Config] update annotations for KPROBE_EVENTS_ON_NOTRACE
+    - mips: fix Section mismatch in reference
+    - mips: lib: uncached: fix non-standard usage of variable 'sp'
+    - MIPS: boot: Fix unaligned access with CONFIG_MIPS_RAW_APPENDED_DTB
+    - MIPS: relocatable: fix possible boot hangup with KASLR enabled
+    - RDMA/ocrdma: Fix use after free in ocrdma_dealloc_ucontext_pd()
+    - ACPI: scan: Harden acpi_device_add() against device ID overflows
+    - mm/hugetlb: fix potential missing huge page size info
+    - dm raid: fix discard limits for raid1
+    - dm snapshot: flush merged data before committing metadata
+    - dm integrity: fix the maximum number of arguments
+    - r8152: Add Lenovo Powered USB-C Travel Hub
+    - btrfs: tree-checker: check if chunk item end overflows
+    - drm/i915/backlight: fix CPU mode backlight takeover on LPT
+    - ext4: fix bug for rename with RENAME_WHITEOUT
+    - ext4: don't leak old mountpoint samples
+    - cifs: fix interrupted close commands
+    - dm integrity: fix flush with external metadata device
+    - ARC: build: remove non-existing bootpImage from KBUILD_IMAGE
+    - ARC: build: add uImage.lzma to the top-level target
+    - ARC: build: add boot_targets to PHONY
+    - ARC: build: move symlink creation to arch/arc/Makefile to avoid race
+    - netfilter: ipset: fixes possible oops in mtype_resize
+    - btrfs: fix transaction leak and crash after RO remount caused by qgroup
+      rescan
+    - regulator: bd718x7: Add enable times
+    - ethernet: ucc_geth: fix definition and size of ucc_geth_tx_global_pram
+    - habanalabs: register to pci shutdown callback
+    - habanalabs: Fix memleak in hl_device_reset
+    - hwmon: (pwm-fan) Ensure that calculation doesn't discard big period values
+    - lib/raid6: Let $(UNROLL) rules work with macOS userland
+    - bfq: Fix computation of shallow depth
+    - arch/arc: add copy_user_page() to <asm/page.h> to fix build error on ARC
+    - misdn: dsp: select CONFIG_BITREVERSE
+    - net: ethernet: fs_enet: Add missing MODULE_LICENSE
+    - nvme-pci: mark Samsung PM1725a as IGNORE_DEV_SUBNQN
+    - nvmet-rdma: Fix list_del corruption on queue establishment failure
+    - drm/amdgpu: fix a GPU hang issue when remove device
+    - usb: typec: Fix copy paste error for NVIDIA alt-mode description
+    - ACPI: scan: add stub acpi_create_platform_device() for !CONFIG_ACPI
+    - drm/msm: Call msm_init_vram before binding the gpu
+    - ARM: picoxcell: fix missing interrupt-parent properties
+    - perf intel-pt: Fix 'CPU too large' error
+    - dump_common_audit_data(): fix racy accesses to ->d_name
+    - ASoC: meson: axg-tdm-interface: fix loopback
+    - ASoC: meson: axg-tdmin: fix axg skew offset
+    - ASoC: Intel: fix error code cnl_set_dsp_D0()
+    - nvme-tcp: fix possible data corruption with bio merges
+    - NFS4: Fix use-after-free in trace_event_raw_event_nfs4_set_lock
+    - pNFS: We want return-on-close to complete when evicting the inode
+    - pNFS: Mark layout for return if return-on-close was not sent
+    - pNFS: Stricter ordering of layoutget and layoutreturn
+    - NFS/pNFS: Fix a leak of the layout 'plh_outstanding' counter
+    - NFS: nfs_igrab_and_active must first reference the superblock
+    - ext4: fix superblock checksum failure when setting password salt
+    - RDMA/restrack: Don't treat as an error allocation ID wrapping
+    - RDMA/usnic: Fix memleak in find_free_vf_and_create_qp_grp
+    - bnxt_en: Improve stats context resource accounting with RDMA driver loaded.
+    - RDMA/mlx5: Fix wrong free of blue flame register on error
+    - IB/mlx5: Fix error unwinding when set_has_smi_cap fails
+    - drm/i915/dsi: Use unconditional msleep for the panel_on_delay when there is
+      no reset-deassert MIPI-sequence
+    - mm, slub: consider rest of partial list if acquire_slab() fails
+    - iommu/vt-d: Fix unaligned addresses for intel_flush_svm_range_dev()
+    - net: sunrpc: interpret the return value of kstrtou32 correctly
+    - dm: eliminate potential source of excessive kernel log noise
+    - ALSA: fireface: Fix integer overflow in transmit_midi_msg()
+    - ALSA: firewire-tascam: Fix integer overflow in midi_port_work()
+    - netfilter: conntrack: fix reading nf_conntrack_buckets
+    - netfilter: nf_nat: Fix memleak in nf_nat_init
+    - netfilter: nft_compat: remove flush counter optimization
+    - Linux 5.4.91
+  * Focal update: v5.4.90 upstream stable release (LP: #1913487)
+    - x86/asm/32: Add ENDs to some functions and relabel with SYM_CODE_*
+    - vfio iommu: Add dma available capability
+    - net: cdc_ncm: correct overhead in delayed_ndp_size
+    - net: hns3: fix the number of queues actually used by ARQ
+    - net: hns3: fix a phy loopback fail issue
+    - net: stmmac: dwmac-sun8i: Balance internal PHY resource references
+    - net: stmmac: dwmac-sun8i: Balance internal PHY power
+    - net: vlan: avoid leaks on register_vlan_dev() failures
+    - net/sonic: Fix some resource leaks in error handling paths
+    - net: ipv6: fib: flush exceptions when purging route
+    - tools: selftests: add test for changing routes with PTMU exceptions
+    - net: fix pmtu check in nopmtudisc mode
+    - net: ip: always refragment ip defragmented packets
+    - octeontx2-af: fix memory leak of lmac and lmac->name
+    - nexthop: Fix off-by-one error in error path
+    - nexthop: Unlink nexthop group entry in error path
+    - s390/qeth: fix L2 header access in qeth_l3_osa_features_check()
+    - net: dsa: lantiq_gswip: Exclude RMII from modes that report 1 GbE
+    - net/mlx5: Use port_num 1 instead of 0 when delete a RoCE address
+    - net/mlx5e: ethtool, Fix restriction of autoneg with 56G
+    - chtls: Fix hardware tid leak
+    - chtls: Remove invalid set_tcb call
+    - chtls: Fix panic when route to peer not configured
+    - chtls: Replace skb_dequeue with skb_peek
+    - chtls: Added a check to avoid NULL pointer dereference
+    - chtls: Fix chtls resources release sequence
+    - x86/resctrl: Use an IPI instead of task_work_add() to update PQR_ASSOC MSR
+    - x86/resctrl: Don't move a task to the same resource group
+    - exfat: Month timestamp metadata accidentally incremented
+    - vmlinux.lds.h: Add PGO and AutoFDO input sections
+    - iio: imu: st_lsm6dsx: fix edge-trigger interrupts
+    - HID: wacom: Fix memory leakage caused by kfifo_alloc
+    - ARM: OMAP2+: omap_device: fix idling of devices during probe
+    - i2c: sprd: use a specific timeout to avoid system hang up issue
+    - dmaengine: dw-edma: Fix use after free in dw_edma_alloc_chunk()
+    - can: tcan4x5x: fix bittiming const, use common bittiming from m_can driver
+    - can: m_can: m_can_class_unregister(): remove erroneous m_can_clk_stop()
+    - can: kvaser_pciefd: select CONFIG_CRC32
+    - cpufreq: powernow-k8: pass policy rather than use cpufreq_cpu_get()
+    - spi: stm32: FIFO threshold level - fix align packet size
+    - i2c: i801: Fix the i2c-mux gpiod_lookup_table not being properly terminated
+    - dmaengine: mediatek: mtk-hsdma: Fix a resource leak in the error handling
+      path of the probe function
+    - dmaengine: xilinx_dma: check dma_async_device_register return value
+    - dmaengine: xilinx_dma: fix incompatible param warning in _child_probe()
+    - dmaengine: xilinx_dma: fix mixed_enum_type coverity warning
+    - qed: select CONFIG_CRC32
+    - wil6210: select CONFIG_CRC32
+    - block: rsxx: select CONFIG_CRC32
+    - lightnvm: select CONFIG_CRC32
+    - iommu/intel: Fix memleak in intel_irq_remapping_alloc
+    - bpftool: Fix compilation failure for net.o with older glibc
+    - net/mlx5e: Fix memleak in mlx5e_create_l2_table_groups
+    - net/mlx5e: Fix two double free cases
+    - regmap: debugfs: Fix a memory leak when calling regmap_attach_dev
+    - wan: ds26522: select CONFIG_BITREVERSE
+    - regulator: qcom-rpmh-regulator: correct hfsmps515 definition
+    - net: mvpp2: disable force link UP during port init procedure
+    - KVM: arm64: Don't access PMCR_EL0 when no PMU is available
+    - block: fix use-after-free in disk_part_iter_next
+    - net: drop bogus skb with CHECKSUM_PARTIAL and offset beyond end of trimmed
+      packet
+    - regmap: debugfs: Fix a reversed if statement in regmap_debugfs_init()
+    - Linux 5.4.90
+  * Focal update: v5.4.89 upstream stable release (LP: #1913486)
+    - workqueue: Kick a worker based on the actual activation of delayed works
+    - scsi: ufs: Fix wrong print message in dev_err()
+    - scsi: ufs-pci: Ensure UFS device is in PowerDown mode for suspend-to-disk
+      ->poweroff()
+    - scsi: ide: Do not set the RQF_PREEMPT flag for sense requests
+    - scsi: scsi_transport_spi: Set RQF_PM for domain validation commands
+    - lib/genalloc: fix the overflow when size is too big
+    - depmod: handle the case of /sbin/depmod without /sbin in PATH
+    - proc: change ->nlink under proc_subdir_lock
+    - proc: fix lookup in /proc/net subdirectories after setns(2)
+    - i40e: Fix Error I40E_AQ_RC_EINVAL when removing VFs
+    - iavf: fix double-release of rtnl_lock
+    - net: mvpp2: Add TCAM entry to drop flow control pause frames
+    - net: mvpp2: prs: fix PPPoE with ipv6 packet parse
+    - net: systemport: set dev->max_mtu to UMAC_MAX_MTU_SIZE
+    - ethernet: ucc_geth: fix use-after-free in ucc_geth_remove()
+    - ethernet: ucc_geth: set dev->max_mtu to 1518
+    - atm: idt77252: call pci_disable_device() on error path
+    - net: mvpp2: Fix GoP port 3 Networking Complex Control configurations
+    - ibmvnic: continue fatal error reset after passive init
+    - net: ethernet: mvneta: Fix error handling in mvneta_probe
+    - virtio_net: Fix recursive call to cpus_read_lock()
+    - net/ncsi: Use real net-device for response handler
+    - net: ethernet: Fix memleak in ethoc_probe
+    - net-sysfs: take the rtnl lock when storing xps_cpus
+    - net-sysfs: take the rtnl lock when accessing xps_cpus_map and num_tc
+    - net-sysfs: take the rtnl lock when storing xps_rxqs
+    - net-sysfs: take the rtnl lock when accessing xps_rxqs_map and num_tc
+    - net: ethernet: ti: cpts: fix ethtool output when no ptp_clock registered
+    - tun: fix return value when the number of iovs exceeds MAX_SKB_FRAGS
+    - net: mvpp2: fix pkt coalescing int-threshold configuration
+    - ipv4: Ignore ECN bits for fib lookups in fib_compute_spec_dst()
+    - net: sched: prevent invalid Scell_log shift count
+    - net: hns: fix return value check in __lb_other_process()
+    - erspan: fix version 1 check in gre_parse_header()
+    - net: hdlc_ppp: Fix issues when mod_timer is called while timer is running
+    - r8169: work around power-saving bug on some chip versions
+    - net: dsa: lantiq_gswip: Enable GSWIP_MII_CFG_EN also for internal PHYs
+    - net: dsa: lantiq_gswip: Fix GSWIP_MII_CFG(p) register access
+    - CDC-NCM: remove "connected" log message
+    - net: usb: qmi_wwan: add Quectel EM160R-GL
+    - vhost_net: fix ubuf refcount incorrectly when sendmsg fails
+    - ionic: account for vlan tag len in rx buffer len
+    - net/sched: sch_taprio: ensure to reset/destroy all child qdiscs
+    - kbuild: don't hardcode depmod path
+    - Bluetooth: revert: hci_h5: close serdev device and free hu in h5_close
+    - video: hyperv_fb: Fix the mmap() regression for v5.4.y and older
+    - crypto: ecdh - avoid buffer overflow in ecdh_set_secret()
+    - crypto: asym_tpm: correct zero out potential secrets
+    - powerpc: Handle .text.{hot,unlikely}.* in linker script
+    - staging: mt7621-dma: Fix a resource leak in an error handling path
+    - usb: gadget: enable super speed plus
+    - USB: cdc-acm: blacklist another IR Droid device
+    - USB: cdc-wdm: Fix use after free in service_outstanding_interrupt().
+    - usb: dwc3: ulpi: Use VStsDone to detect PHY regs access completion
+    - usb: chipidea: ci_hdrc_imx: add missing put_device() call in
+      usbmisc_get_init_data()
+    - USB: xhci: fix U1/U2 handling for hardware with XHCI_INTEL_HOST quirk set
+    - usb: usbip: vhci_hcd: protect shift size
+    - usb: uas: Add PNY USB Portable SSD to unusual_uas
+    - USB: serial: iuu_phoenix: fix DMA from stack
+    - USB: serial: option: add LongSung M5710 module support
+    - USB: serial: option: add Quectel EM160R-GL
+    - USB: yurex: fix control-URB timeout handling
+    - USB: usblp: fix DMA to stack
+    - ALSA: usb-audio: Fix UBSAN warnings for MIDI jacks
+    - usb: gadget: select CONFIG_CRC32
+    - usb: gadget: f_uac2: reset wMaxPacketSize
+    - usb: gadget: function: printer: Fix a memory leak for interface descriptor
+    - usb: gadget: u_ether: Fix MTU size mismatch with RX packet size
+    - USB: gadget: legacy: fix return error code in acm_ms_bind()
+    - usb: gadget: Fix spinlock lockup on usb_function_deactivate
+    - usb: gadget: configfs: Preserve function ordering after bind failure
+    - usb: gadget: configfs: Fix use-after-free issue with udc_name
+    - USB: serial: keyspan_pda: remove unused variable
+    - x86/mm: Fix leak of pmd ptlock
+    - kvm: check tlbs_dirty directly
+    - ALSA: hda/via: Fix runtime PM for Clevo W35xSS
+    - ALSA: hda/conexant: add a new hda codec CX11970
+    - ALSA: hda/realtek - Fix speaker volume control on Lenovo C940
+    - ALSA: hda/realtek: Add two "Intel Reference board" SSID in the ALC256.
+    - btrfs: send: fix wrong file path when there is an inode with a pending rmdir
+    - Revert "device property: Keep secondary firmware node secondary by type"
+    - dmabuf: fix use-after-free of dmabuf's file->f_inode
+    - drm/i915: clear the gpu reloc batch
+    - netfilter: x_tables: Update remaining dereference to RCU
+    - netfilter: ipset: fix shift-out-of-bounds in htable_bits()
+    - netfilter: xt_RATEEST: reject non-null terminated string from userspace
+    - netfilter: nft_dynset: report EOPNOTSUPP on missing set feature
+    - x86/mtrr: Correct the range check before performing MTRR type lookups
+    - KVM: x86: fix shift out of bounds reported by UBSAN
+    - Linux 5.4.89
+  * Focal update: v5.4.88 upstream stable release (LP: #1913223)
+    - Revert "drm/amd/display: Fix memory leaks in S3 resume"
+    - Revert "mtd: spinand: Fix OOB read"
+    - dmaengine: at_hdmac: Substitute kzalloc with kmalloc
+    - dmaengine: at_hdmac: add missing put_device() call in at_dma_xlate()
+    - dmaengine: at_hdmac: add missing kfree() call in at_dma_xlate()
+    - kdev_t: always inline major/minor helper functions
+    - iio:imu:bmi160: Fix alignment and data leak issues
+    - fuse: fix bad inode
+    - perf: Break deadlock involving exec_update_mutex
+    - rwsem: Implement down_read_killable_nested
+    - rwsem: Implement down_read_interruptible
+    - exec: Transform exec_update_mutex into a rw_semaphore
+    - mwifiex: Fix possible buffer overflows in mwifiex_cmd_802_11_ad_hoc_start
+    - Linux 5.4.88
+  * Focal update: v5.4.87 upstream stable release (LP: #1912681)
+    - net/sched: sch_taprio: reset child qdiscs before freeing them
+    - md/raid10: initialize r10_bio->read_slot before use.
+    - thermal/drivers/cpufreq_cooling: Update cpufreq_state only if state has
+      changed
+    - ext4: prevent creating duplicate encrypted filenames
+    - ubifs: prevent creating duplicate encrypted filenames
+    - f2fs: prevent creating duplicate encrypted filenames
+    - fscrypt: add fscrypt_is_nokey_name()
+    - fscrypt: remove kernel-internal constants from UAPI header
+    - vfio/pci: Move dummy_resources_list init in vfio_pci_probe()
+    - btrfs: fix race when defragmenting leads to unnecessary IO
+    - ext4: don't remount read-only with errors=continue on reboot
+    - KVM: x86: avoid incorrect writes to host MSR_IA32_SPEC_CTRL
+    - KVM: SVM: relax conditions for allowing MSR_IA32_SPEC_CTRL accesses
+    - KVM: x86: reinstate vendor-agnostic check on SPEC_CTRL cpuid bits
+    - powerpc/bitops: Fix possible undefined behaviour with fls() and fls64()
+    - jffs2: Allow setting rp_size to zero during remounting
+    - jffs2: Fix NULL pointer dereference in rp_size fs option parsing
+    - scsi: block: Fix a race in the runtime power management code
+    - uapi: move constants from <linux/kernel.h> to <linux/const.h>
+    - tools headers UAPI: Sync linux/const.h with the kernel headers
+    - null_blk: Fix zone size initialization
+    - of: fix linker-section match-table corruption
+    - cgroup: Fix memory leak when parsing multiple source parameters
+    - scsi: cxgb4i: Fix TLS dependency
+    - Bluetooth: hci_h5: close serdev device and free hu in h5_close
+    - reiserfs: add check for an invalid ih_entry_count
+    - misc: vmw_vmci: fix kernel info-leak by initializing dbells in
+      vmci_ctx_get_chkpt_doorbells()
+    - media: gp8psk: initialize stats at power control logic
+    - f2fs: fix shift-out-of-bounds in sanity_check_raw_super()
+    - ALSA: seq: Use bool for snd_seq_queue internal flags
+    - ALSA: rawmidi: Access runtime->avail always in spinlock
+    - bfs: don't use WARNING: string when it's just info.
+    - fcntl: Fix potential deadlock in send_sig{io, urg}()
+    - rtc: sun6i: Fix memleak in sun6i_rtc_clk_init
+    - module: set MODULE_STATE_GOING state when a module fails to load
+    - quota: Don't overflow quota file offsets
+    - rtc: pl031: fix resource leak in pl031_probe
+    - powerpc: sysdev: add missing iounmap() on error in mpic_msgr_probe()
+    - i3c master: fix missing destroy_workqueue() on error in i3c_master_register
+    - NFSv4: Fix a pNFS layout related use-after-free race when freeing the inode
+    - f2fs: avoid race condition for shrinker count
+    - module: delay kobject uevent until after module init call
+    - fs/namespace.c: WARN if mnt_count has become negative
+    - um: ubd: Submit all data segments atomically
+    - tick/sched: Remove bogus boot "safety" check
+    - ALSA: pcm: Clear the full allocated memory at hw_params
+    - dm verity: skip verity work if I/O error when system is shutting down
+    - Linux 5.4.87
+
+  [ Ubuntu: 5.4.0-66.74 ]
+
+  * focal/linux: 5.4.0-66.74 -proposed tracker (LP: #1913152)
+  * Add support for selective build of special drivers (LP: #1912789)
+    - [Packaging] Add support for ODM drivers
+    - [Packaging] Turn on ODM support for amd64
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+    - update dkms package versions
+  * Introduce the new NVIDIA 460-server series and update the 460 series
+    (LP: #1913200)
+    - [Config] dkms-versions -- drop NVIDIA 435 455 and 440-server
+    - [Config] dkms-versions -- add the 460-server nvidia driver
+  * Enable mute and micmute LED on HP EliteBook 850 G7 (LP: #1910102)
+    - ALSA: hda/realtek: Enable mute and micmute LED on HP EliteBook 850 G7
+  * SYNA30B4:00 06CB:CE09 Mouse  on HP EliteBook 850 G7 not working at all
+    (LP: #1908992)
+    - HID: multitouch: Enable multi-input for Synaptics pointstick/touchpad device
+  * HD Audio Device PCI ID for the Intel Cometlake-R platform (LP: #1912427)
+    - SAUCE: ALSA: hda: Add Cometlake-R PCI ID
+  * switch to an autogenerated nvidia series based core via dkms-versions
+    (LP: #1912803)
+    - [Packaging] nvidia -- use dkms-versions to define versions built
+    - [Packaging] update-version-dkms -- maintain flags fields
+    - [Config] dkms-versions -- add transitional/skip information for nvidia
+      packages
+  * udpgro.sh in net from ubuntu_kernel_selftests seems not reflecting sub-test
+    result (LP: #1908499)
+    - selftests: fix the return value for UDP GRO test
+  * qede: Kubernetes Internal DNS Failure due to QL41xxx NIC not supporting IPIP
+    tx csum offload (LP: #1909062)
+    - qede: fix offload for IPIP tunnel packets
+  * Use DCPD to control HP DreamColor panel (LP: #1911001)
+    - SAUCE: drm/dp: Another HP DreamColor panel brigntness fix
+  * kvm: Windows 2k19 with Hyper-v role gets stuck on pending hypervisor
+    requests on cascadelake based kvm hosts (LP: #1911848)
+    - KVM: x86: Set KVM_REQ_EVENT if run is canceled with req_immediate_exit set
+  * Ubuntu 20.10 four needed fixes to 'Add driver for Mellanox Connect-IB
+    adapters' (LP: #1905574)
+    - net/mlx5: Fix a race when moving command interface to polling mode
+  * Fix right sounds and mute/micmute LEDs for HP ZBook Fury 15/17 G7 Mobile
+    Workstation (LP: #1910561)
+    - ALSA: hda/realtek: fix right sounds and mute/micmute LEDs for HP machines
+  * Ubuntu 20.04 - multicast counter is not increased in ip -s (LP: #1901842)
+    - net/mlx5e: Fix multicast counter not up-to-date in "ip -s"
+  * eeh-basic.sh in powerpc from ubuntu_kernel_selftests timeout with 5.4 P8 /
+    P9 (LP: #1882503)
+    - selftests/powerpc/eeh: disable kselftest timeout setting for eeh-basic
+  * DMI entry syntax fix for Pegatron / ByteSpeed C15B (LP: #1910639)
+    - Input: i8042 - unbreak Pegatron C15B
+  * CVE-2020-29372
+    - mm: check that mm is still valid in madvise()
+  * update ENA driver, incl. new ethtool stats (LP: #1910291)
+    - net: ena: Change WARN_ON expression in ena_del_napi_in_range()
+    - net: ena: ethtool: convert stat_offset to 64 bit resolution
+    - net: ena: ethtool: Add new device statistics
+    - net: ena: ethtool: add stats printing to XDP queues
+    - net: ena: xdp: add queue counters for xdp actions
+    - net: ena: Change license into format to SPDX in all files
+    - net: ena: Change log message to netif/dev function
+    - net: ena: Capitalize all log strings and improve code readability
+    - net: ena: Remove redundant print of placement policy
+    - net: ena: Change RSS related macros and variables names
+    - net: ena: Fix all static chekers' warnings
+    - drivers/net/ethernet: remove incorrectly formatted doc
+    - net: ena: handle bad request id in ena_netdev
+    - net: ena: fix packet's addresses for rx_offset feature
+  * s390x broken with unknown syscall number on kernels < 5.8 (LP: #1895132)
+    - s390/ptrace: return -ENOSYS when invalid syscall is supplied
+  * Focal update: v5.4.86 upstream stable release (LP: #1910822)
+    - ARM: dts: sun7i: bananapi: Enable RGMII RX/TX delay on Ethernet PHY
+    - ARM: dts: sun8i: r40: bananapi-m2-berry: Fix dcdc1 regulator
+    - ARM: dts: sun8i: v40: bananapi-m2-berry: Fix ethernet node
+    - pinctrl: merrifield: Set default bias in case no particular value given
+    - pinctrl: baytrail: Avoid clearing debounce value when turning it off
+    - ARM: dts: sun8i: v3s: fix GIC node memory range
+    - ARM: dts: sun7i: pcduino3-nano: enable RGMII RX/TX delay on PHY
+    - ARM: dts: imx6qdl-wandboard-revd1: Remove PAD_GPIO_6 from enetgrp
+    - ARM: dts: imx6qdl-kontron-samx6i: fix I2C_PM scl pin
+    - PM: runtime: Add pm_runtime_resume_and_get to deal with usage counter
+    - gpio: zynq: fix reference leak in zynq_gpio functions
+    - gpio: mvebu: fix potential user-after-free on probe
+    - scsi: bnx2i: Requires MMU
+    - xsk: Fix xsk_poll()'s return type
+    - xsk: Replace datagram_poll by sock_poll_wait
+    - can: softing: softing_netdev_open(): fix error handling
+    - clk: renesas: r9a06g032: Drop __packed for portability
+    - block: Simplify REQ_OP_ZONE_RESET_ALL handling
+    - block: factor out requeue handling from dispatch code
+    - blk-mq: In blk_mq_dispatch_rq_list() "no budget" is a reason to kick
+    - pinctrl: aspeed: Fix GPIO requests on pass-through banks
+    - netfilter: x_tables: Switch synchronization to RCU
+    - netfilter: nft_compat: make sure xtables destructors have run
+    - netfilter: nft_dynset: fix timeouts later than 23 days
+    - afs: Fix memory leak when mounting with multiple source parameters
+    - Revert "gpio: eic-sprd: Use devm_platform_ioremap_resource()"
+    - gpio: eic-sprd: break loop when getting NULL device resource
+    - netfilter: nft_ct: Remove confirmation check for NFT_CT_ID
+    - selftests/bpf/test_offload.py: Reset ethtool features after failed setting
+    - RDMA/cm: Fix an attempt to use non-valid pointer when cleaning timewait
+    - i40e: Refactor rx_bi accesses
+    - i40e: optimise prefetch page refcount
+    - i40e: avoid premature Rx buffer reuse
+    - ixgbe: avoid premature Rx buffer reuse
+    - selftests: fix poll error in udpgro.sh
+    - net: mvpp2: add mvpp2_phylink_to_port() helper
+    - drm/tegra: replace idr_init() by idr_init_base()
+    - kernel/cpu: add arch override for clear_tasks_mm_cpumask() mm handling
+    - drm/tegra: sor: Disable clocks on error in tegra_sor_init()
+    - habanalabs: put devices before driver removal
+    - arm64: syscall: exit userspace before unmasking exceptions
+    - vxlan: Add needed_headroom for lower device
+    - vxlan: Copy needed_tailroom from lowerdev
+    - scsi: mpt3sas: Increase IOCInit request timeout to 30s
+    - dm table: Remove BUG_ON(in_interrupt())
+    - iwlwifi: pcie: add one missing entry for AX210
+    - drm/amd/display: Init clock value by current vbios CLKs
+    - perf/x86/intel: Check PEBS status correctly
+    - kbuild: avoid split lines in .mod files
+    - soc/tegra: fuse: Fix index bug in get_process_id
+    - usb: mtu3: fix memory corruption in mtu3_debugfs_regset()
+    - USB: serial: option: add interface-number sanity check to flag handling
+    - USB: gadget: f_acm: add support for SuperSpeed Plus
+    - USB: gadget: f_midi: setup SuperSpeed Plus descriptors
+    - usb: gadget: f_fs: Re-use SS descriptors for SuperSpeedPlus
+    - USB: gadget: f_rndis: fix bitrate for SuperSpeed and above
+    - usb: chipidea: ci_hdrc_imx: Pass DISABLE_DEVICE_STREAMING flag to imx6ul
+    - ARM: dts: exynos: fix roles of USB 3.0 ports on Odroid XU
+    - ARM: dts: exynos: fix USB 3.0 VBUS control and over-current pins on
+      Exynos5410
+    - ARM: dts: exynos: fix USB 3.0 pins supply being turned off on Odroid XU
+    - coresight: tmc-etf: Fix NULL ptr dereference in tmc_enable_etf_sink_perf()
+    - coresight: tmc-etr: Check if page is valid before dma_map_page()
+    - coresight: tmc-etr: Fix barrier packet insertion for perf buffer
+    - coresight: etb10: Fix possible NULL ptr dereference in etb_enable_perf()
+    - scsi: megaraid_sas: Check user-provided offsets
+    - HID: i2c-hid: add Vero K147 to descriptor override
+    - serial_core: Check for port state when tty is in error state
+    - Bluetooth: Fix slab-out-of-bounds read in hci_le_direct_adv_report_evt()
+    - quota: Sanity-check quota file headers on load
+    - media: msi2500: assign SPI bus number dynamically
+    - crypto: af_alg - avoid undefined behavior accessing salg_name
+    - md: fix a warning caused by a race between concurrent md_ioctl()s
+    - drm/gma500: fix double free of gma_connector
+    - drm/aspeed: Fix Kconfig warning & subsequent build errors
+    - drm/mcde: Fix handling of platform_get_irq() error
+    - drm/tve200: Fix handling of platform_get_irq() error
+    - arm64: dts: renesas: hihope-rzg2-ex: Drop rxc-skew-ps from ethernet-phy node
+    - arm64: dts: renesas: cat875: Remove rxc-skew-ps from ethernet-phy node
+    - soc: renesas: rmobile-sysc: Fix some leaks in rmobile_init_pm_domains()
+    - soc: mediatek: Check if power domains can be powered on at boot time
+    - soc: qcom: geni: More properly switch to DMA mode
+    - Revert "i2c: i2c-qcom-geni: Fix DMA transfer race"
+    - RDMA/bnxt_re: Set queue pair state when being queried
+    - rtc: pcf2127: fix pcf2127_nvmem_read/write() returns
+    - selinux: fix error initialization in inode_doinit_with_dentry()
+    - ARM: dts: aspeed: s2600wf: Fix VGA memory region location
+    - RDMA/rxe: Compute PSN windows correctly
+    - x86/mm/ident_map: Check for errors from ident_pud_init()
+    - ARM: p2v: fix handling of LPAE translation in BE mode
+    - x86/apic: Fix x2apic enablement without interrupt remapping
+    - sched/deadline: Fix sched_dl_global_validate()
+    - sched: Reenable interrupts in do_sched_yield()
+    - drm/amdgpu: fix incorrect enum type
+    - crypto: talitos - Endianess in current_desc_hdr()
+    - crypto: talitos - Fix return type of current_desc_hdr()
+    - crypto: inside-secure - Fix sizeof() mismatch
+    - ASoC: sun4i-i2s: Fix lrck_period computation for I2S justified mode
+    - ARM: dts: aspeed: tiogapass: Remove vuart
+    - drm/amdgpu: fix build_coefficients() argument
+    - powerpc/64: Set up a kernel stack for secondaries before cpu_restore()
+    - spi: img-spfi: fix reference leak in img_spfi_resume
+    - f2fs: call f2fs_get_meta_page_retry for nat page
+    - drm/msm/dsi_pll_10nm: restore VCO rate during restore_state
+    - spi: spi-mem: fix reference leak in spi_mem_access_start
+    - ASoC: pcm: DRAIN support reactivation
+    - selinux: fix inode_doinit_with_dentry() LABEL_INVALID error handling
+    - spi: stm32: fix reference leak in stm32_spi_resume
+    - brcmfmac: Fix memory leak for unpaired brcmf_{alloc/free}
+    - arm64: dts: exynos: Include common syscon restart/poweroff for Exynos7
+    - arm64: dts: exynos: Correct psci compatible used on Exynos7
+    - Bluetooth: Fix null pointer dereference in hci_event_packet()
+    - Bluetooth: hci_h5: fix memory leak in h5_close
+    - spi: spi-ti-qspi: fix reference leak in ti_qspi_setup
+    - spi: mt7621: fix missing clk_disable_unprepare() on error in
+      mt7621_spi_probe
+    - spi: tegra20-slink: fix reference leak in slink ops of tegra20
+    - spi: tegra20-sflash: fix reference leak in tegra_sflash_resume
+    - spi: tegra114: fix reference leak in tegra spi ops
+    - spi: bcm63xx-hsspi: fix missing clk_disable_unprepare() on error in
+      bcm63xx_hsspi_resume
+    - mwifiex: fix mwifiex_shutdown_sw() causing sw reset failure
+    - selftest/bpf: Add missed ip6ip6 test back
+    - ASoC: wm8998: Fix PM disable depth imbalance on error
+    - spi: sprd: fix reference leak in sprd_spi_remove
+    - ASoC: arizona: Fix a wrong free in wm8997_probe
+    - RDMa/mthca: Work around -Wenum-conversion warning
+    - MIPS: BCM47XX: fix kconfig dependency bug for BCM47XX_BCMA
+    - crypto: qat - fix status check in qat_hal_put_rel_rd_xfer()
+    - staging: greybus: codecs: Fix reference counter leak in error handling
+    - staging: gasket: interrupt: fix the missed eventfd_ctx_put() in
+      gasket_interrupt.c
+    - media: tm6000: Fix sizeof() mismatches
+    - media: mtk-vcodec: add missing put_device() call in mtk_vcodec_init_dec_pm()
+    - media: mtk-vcodec: add missing put_device() call in
+      mtk_vcodec_release_dec_pm()
+    - media: mtk-vcodec: add missing put_device() call in mtk_vcodec_init_enc_pm()
+    - media: v4l2-fwnode: Return -EINVAL for invalid bus-type
+    - ASoC: meson: fix COMPILE_TEST error
+    - scsi: core: Fix VPD LUN ID designator priorities
+    - media: solo6x10: fix missing snd_card_free in error handling case
+    - video: fbdev: atmel_lcdfb: fix return error code in atmel_lcdfb_of_init()
+    - drm/omap: dmm_tiler: fix return error code in omap_dmm_probe()
+    - Input: ads7846 - fix race that causes missing releases
+    - Input: ads7846 - fix integer overflow on Rt calculation
+    - Input: ads7846 - fix unaligned access on 7845
+    - usb/max3421: fix return error code in max3421_probe()
+    - spi: mxs: fix reference leak in mxs_spi_probe
+    - selftests/bpf: Fix broken riscv build
+    - powerpc: Avoid broken GCC __attribute__((optimize))
+    - powerpc/feature: Fix CPU_FTRS_ALWAYS by removing CPU_FTRS_GENERIC_32
+    - EDAC/mce_amd: Use struct cpuinfo_x86.cpu_die_id for AMD NodeId
+    - crypto: crypto4xx - Replace bitwise OR with logical OR in crypto4xx_build_pd
+    - crypto: omap-aes - Fix PM disable depth imbalance in omap_aes_probe
+    - spi: fix resource leak for drivers without .remove callback
+    - soc: ti: knav_qmss: fix reference leak in knav_queue_probe
+    - soc: ti: Fix reference imbalance in knav_dma_probe
+    - drivers: soc: ti: knav_qmss_queue: Fix error return code in knav_queue_probe
+    - Input: omap4-keypad - fix runtime PM error handling
+    - clk: meson: Kconfig: fix dependency for G12A
+    - RDMA/cxgb4: Validate the number of CQEs
+    - memstick: fix a double-free bug in memstick_check
+    - ARM: dts: at91: sama5d4_xplained: add pincontrol for USB Host
+    - ARM: dts: at91: sama5d3_xplained: add pincontrol for USB Host
+    - mmc: pxamci: Fix error return code in pxamci_probe
+    - orinoco: Move context allocation after processing the skb
+    - qtnfmac: fix error return code in qtnf_pcie_probe()
+    - rsi: fix error return code in rsi_reset_card()
+    - cw1200: fix missing destroy_workqueue() on error in cw1200_init_common
+    - dmaengine: mv_xor_v2: Fix error return code in mv_xor_v2_probe()
+    - arm64: tegra: Fix DT binding for IO High Voltage entry
+    - media: siano: fix memory leak of debugfs members in smsdvb_hotplug
+    - platform/x86: mlx-platform: Remove PSU EEPROM from default platform
+      configuration
+    - platform/x86: mlx-platform: Remove PSU EEPROM from MSN274x platform
+      configuration
+    - samples: bpf: Fix lwt_len_hist reusing previous BPF map
+    - media: imx214: Fix stop streaming
+    - mips: cdmm: fix use-after-free in mips_cdmm_bus_discover
+    - media: max2175: fix max2175_set_csm_mode() error code
+    - slimbus: qcom-ngd-ctrl: Avoid sending power requests without QMI
+    - HSI: omap_ssi: Don't jump to free ID in ssi_add_controller()
+    - ARM: dts: Remove non-existent i2c1 from 98dx3236
+    - arm64: dts: armada-3720-turris-mox: update ethernet-phy handle name
+    - arm64: dts: rockchip: Set dr_mode to "host" for OTG on rk3328-roc-cc
+    - power: supply: axp288_charger: Fix HP Pavilion x2 10 DMI matching
+    - power: supply: bq24190_charger: fix reference leak
+    - genirq/irqdomain: Don't try to free an interrupt that has no mapping
+    - arm64: dts: ls1028a: fix ENETC PTP clock input
+    - arm64: dts: qcom: c630: Polish i2c-hid devices
+    - PCI: Bounds-check command-line resource alignment requests
+    - PCI: Fix overflow in command-line resource alignment requests
+    - PCI: iproc: Fix out-of-bound array accesses
+    - arm64: dts: meson: fix spi-max-frequency on Khadas VIM2
+    - arm64: dts: meson-sm1: fix typo in opp table
+    - soc: amlogic: canvas: add missing put_device() call in meson_canvas_get()
+    - ARM: dts: at91: at91sam9rl: fix ADC triggers
+    - platform/x86: dell-smbios-base: Fix error return code in dell_smbios_init
+    - ath10k: Fix the parsing error in service available event
+    - ath10k: Fix an error handling path
+    - ath10k: Release some resources in an error handling path
+    - SUNRPC: rpc_wake_up() should wake up tasks in the correct order
+    - NFSv4.2: condition READDIR's mask for security label based on LSM state
+    - SUNRPC: xprt_load_transport() needs to support the netid "rdma6"
+    - NFSv4: Fix the alignment of page data in the getdeviceinfo reply
+    - net: sunrpc: Fix 'snprintf' return value check in 'do_xprt_debugfs'
+    - lockd: don't use interval-based rebinding over TCP
+    - NFS: switch nfsiod to be an UNBOUND workqueue.
+    - selftests/seccomp: Update kernel config
+    - vfio-pci: Use io_remap_pfn_range() for PCI IO memory
+    - hwmon: (ina3221) Fix PM usage counter unbalance in ina3221_write_enable
+    - media: saa7146: fix array overflow in vidioc_s_audio()
+    - powerpc/perf: Fix crash with is_sier_available when pmu is not set
+    - powerpc/64: Fix an EMIT_BUG_ENTRY in head_64.S
+    - clocksource/drivers/orion: Add missing clk_disable_unprepare() on error path
+    - clocksource/drivers/cadence_ttc: Fix memory leak in ttc_setup_clockevent()
+    - iio: hrtimer-trigger: Mark hrtimer to expire in hard interrupt context
+    - ARM: dts: at91: sama5d2: map securam as device
+    - bpf: Fix bpf_put_raw_tracepoint()'s use of __module_address()
+    - pinctrl: falcon: add missing put_device() call in pinctrl_falcon_probe()
+    - arm64: dts: rockchip: Fix UART pull-ups on rk3328
+    - memstick: r592: Fix error return in r592_probe()
+    - MIPS: Don't round up kernel sections size for memblock_add()
+    - net/mlx5: Properly convey driver version to firmware
+    - ASoC: jz4740-i2s: add missed checks for clk_get()
+    - dm ioctl: fix error return code in target_message
+    - phy: renesas: rcar-gen3-usb2: disable runtime pm in case of failure
+    - clocksource/drivers/arm_arch_timer: Use stable count reader in erratum sne
+    - clocksource/drivers/arm_arch_timer: Correct fault programming of
+      CNTKCTL_EL1.EVNTI
+    - cpufreq: ap806: Add missing MODULE_DEVICE_TABLE
+    - cpufreq: highbank: Add missing MODULE_DEVICE_TABLE
+    - cpufreq: mediatek: Add missing MODULE_DEVICE_TABLE
+    - cpufreq: qcom: Add missing MODULE_DEVICE_TABLE
+    - cpufreq: st: Add missing MODULE_DEVICE_TABLE
+    - cpufreq: sun50i: Add missing MODULE_DEVICE_TABLE
+    - cpufreq: loongson1: Add missing MODULE_ALIAS
+    - cpufreq: scpi: Add missing MODULE_ALIAS
+    - Bluetooth: btusb: Add the missed release_firmware() in
+      btusb_mtk_setup_firmware()
+    - Bluetooth: btmtksdio: Add the missed release_firmware() in
+      mtk_setup_firmware()
+    - arm64: dts: meson: fix PHY deassert timing requirements
+    - ARM: dts: meson: fix PHY deassert timing requirements
+    - arm64: dts: meson: g12a: x96-max: fix PHY deassert timing requirements
+    - scsi: qedi: Fix missing destroy_workqueue() on error in __qedi_probe
+    - scsi: pm80xx: Fix error return in pm8001_pci_probe()
+    - seq_buf: Avoid type mismatch for seq_buf_init
+    - scsi: fnic: Fix error return code in fnic_probe()
+    - platform/x86: mlx-platform: Fix item counter assignment for MSN2700, MSN24xx
+      systems
+    - powerpc/pseries/hibernation: drop pseries_suspend_begin() from suspend ops
+    - powerpc/pseries/hibernation: remove redundant cacheinfo update
+    - drm/mediatek: avoid dereferencing a null hdmi_phy on an error message
+    - ASoC: amd: change clk_get() to devm_clk_get() and add missed checks
+    - powerpc/mm: sanity_check_fault() should work for all, not only BOOK3S
+    - usb: ehci-omap: Fix PM disable depth umbalance in ehci_hcd_omap_probe
+    - usb: oxu210hp-hcd: Fix memory leak in oxu_create
+    - speakup: fix uninitialized flush_lock
+    - nfsd: Fix message level for normal termination
+    - nfs_common: need lock during iterate through the list
+    - x86/kprobes: Restore BTF if the single-stepping is cancelled
+    - platform/chrome: cros_ec_spi: Don't overwrite spi::mode
+    - bus: fsl-mc: fix error return code in fsl_mc_object_allocate()
+    - s390/cio: fix use-after-free in ccw_device_destroy_console
+    - iwlwifi: mvm: hook up missing RX handlers
+    - erofs: avoid using generic_block_bmap
+    - can: m_can: m_can_config_endisable(): remove double clearing of clock stop
+      request bit
+    - RDMA/core: Do not indicate device ready when device enablement fails
+    - remoteproc: q6v5-mss: fix error handling in q6v5_pds_enable
+    - remoteproc: qcom: fix reference leak in adsp_start
+    - remoteproc: qcom: Fix potential NULL dereference in adsp_init_mmio()
+    - clk: tegra: Fix duplicated SE clock entry
+    - mtd: rawnand: gpmi: fix reference count leak in gpmi ops
+    - mtd: rawnand: meson: Fix a resource leak in init
+    - mtd: rawnand: gpmi: Fix the random DMA timeout issue
+    - extcon: max77693: Fix modalias string
+    - crypto: atmel-i2c - select CONFIG_BITREVERSE
+    - mac80211: don't set set TDLS STA bandwidth wider than possible
+    - ASoC: wm_adsp: remove "ctl" from list on error in wm_adsp_create_control()
+    - irqchip/alpine-msi: Fix freeing of interrupts on allocation error path
+    - watchdog: armada_37xx: Add missing dependency on HAS_IOMEM
+    - watchdog: sirfsoc: Add missing dependency on HAS_IOMEM
+    - watchdog: sprd: remove watchdog disable from resume fail path
+    - watchdog: sprd: check busy bit before new loading rather than after that
+    - watchdog: Fix potential dereferencing of null pointer
+    - ubifs: Fix error return code in ubifs_init_authentication()
+    - um: Monitor error events in IRQ controller
+    - um: tty: Fix handling of close in tty lines
+    - um: chan_xterm: Fix fd leak
+    - sunrpc: fix xs_read_xdr_buf for partial pages receive
+    - RDMA/cma: Don't overwrite sgid_attr after device is released
+    - nfc: s3fwrn5: Release the nfc firmware
+    - powerpc/ps3: use dma_mapping_error()
+    - sparc: fix handling of page table constructor failure
+    - mm: don't wake kswapd prematurely when watermark boosting is disabled
+    - checkpatch: fix unescaped left brace
+    - lan743x: fix rx_napi_poll/interrupt ping-pong
+    - net: bcmgenet: Fix a resource leak in an error handling path in the probe
+      functin
+    - net: allwinner: Fix some resources leak in the error handling path of the
+      probe and in the remove function
+    - net: korina: fix return value
+    - libnvdimm/label: Return -ENXIO for no slot in __blk_label_update
+    - watchdog: qcom: Avoid context switch in restart handler
+    - watchdog: coh901327: add COMMON_CLK dependency
+    - clk: ti: Fix memleak in ti_fapll_synth_setup
+    - pwm: zx: Add missing cleanup in error path
+    - pwm: lp3943: Dynamically allocate PWM chip base
+    - perf record: Fix memory leak when using '--user-regs=?' to list registers
+    - qlcnic: Fix error code in probe
+    - virtio_ring: Cut and paste bugs in vring_create_virtqueue_packed()
+    - virtio_net: Fix error code in probe()
+    - virtio_ring: Fix two use after free bugs
+    - clk: at91: sam9x60: remove atmel,osc-bypass support
+    - clk: s2mps11: Fix a resource leak in error handling paths in the probe
+      function
+    - clk: sunxi-ng: Make sure divider tables have sentinel
+    - kconfig: fix return value of do_error_if()
+    - perf probe: Fix memory leak when synthesizing SDT probes
+    - ARM: sunxi: Add machine match for the Allwinner V3 SoC
+    - cfg80211: initialize rekey_data
+    - fix namespaced fscaps when !CONFIG_SECURITY
+    - lwt: Disable BH too in run_lwt_bpf()
+    - drm/amd/display: Prevent bandwidth overflow
+    - drm/amdkfd: Fix leak in dmabuf import
+    - Input: cros_ec_keyb - send 'scancodes' in addition to key events
+    - initramfs: fix clang build failure
+    - Input: goodix - add upside-down quirk for Teclast X98 Pro tablet
+    - vfio/pci/nvlink2: Do not attempt NPU2 setup on POWER8NVL NPU
+    - media: gspca: Fix memory leak in probe
+    - media: sunxi-cir: ensure IR is handled when it is continuous
+    - media: netup_unidvb: Don't leak SPI master in probe error path
+    - media: ipu3-cio2: Remove traces of returned buffers
+    - media: ipu3-cio2: Return actual subdev format
+    - media: ipu3-cio2: Serialise access to pad format
+    - media: ipu3-cio2: Validate mbus format in setting subdev format
+    - media: ipu3-cio2: Make the field on subdev format V4L2_FIELD_NONE
+    - Input: cyapa_gen6 - fix out-of-bounds stack access
+    - ALSA: hda/ca0132 - Change Input Source enum strings.
+    - Revert "ACPI / resources: Use AE_CTRL_TERMINATE to terminate resources
+      walks"
+    - ACPI: PNP: compare the string length in the matching_id()
+    - ALSA: hda: Fix regressions on clear and reconfig sysfs
+    - ALSA: hda/ca0132 - Fix AE-5 rear headphone pincfg.
+    - ALSA: hda/realtek: make bass spk volume adjustable on a yoga laptop
+    - ALSA: hda/realtek - Enable headset mic of ASUS X430UN with ALC256
+    - ALSA: hda/realtek - Enable headset mic of ASUS Q524UQK with ALC255
+    - ALSA: hda/realtek - Add supported for more Lenovo ALC285 Headset Button
+    - ALSA: pcm: oss: Fix a few more UBSAN fixes
+    - ALSA/hda: apply jack fixup for the Acer Veriton N4640G/N6640G/N2510G
+    - ALSA: hda/realtek: Add quirk for MSI-GP73
+    - ALSA: hda/realtek: Apply jack fixup for Quanta NL3
+    - ALSA: usb-audio: Add VID to support native DSD reproduction on FiiO devices
+    - ALSA: usb-audio: Disable sample read check if firmware doesn't give back
+    - ALSA: core: memalloc: add page alignment for iram
+    - s390/smp: perform initial CPU reset also for SMT siblings
+    - s390/kexec_file: fix diag308 subcode when loading crash kernel
+    - s390/dasd: fix hanging device offline processing
+    - s390/dasd: prevent inconsistent LCU device data
+    - s390/dasd: fix list corruption of pavgroup group list
+    - s390/dasd: fix list corruption of lcu list
+    - binder: add flag to clear buffer on txn complete
+    - ASoC: cx2072x: Fix doubly definitions of Playback and Capture streams
+    - staging: comedi: mf6x4: Fix AI end-of-conversion detection
+    - perf/x86/intel: Add event constraint for CYCLE_ACTIVITY.STALLS_MEM_ANY
+    - perf/x86/intel: Fix rtm_abort_event encoding on Ice Lake
+    - powerpc/perf: Exclude kernel samples while counting events in user space.
+    - crypto: ecdh - avoid unaligned accesses in ecdh_set_secret()
+    - crypto: arm/aes-ce - work around Cortex-A57/A72 silion errata
+    - EDAC/i10nm: Use readl() to access MMIO registers
+    - EDAC/amd64: Fix PCI component registration
+    - cpuset: fix race between hotplug work and later CPU offline
+    - USB: serial: mos7720: fix parallel-port state restore
+    - USB: serial: digi_acceleport: fix write-wakeup deadlocks
+    - USB: serial: keyspan_pda: fix dropped unthrottle interrupts
+    - USB: serial: keyspan_pda: fix write deadlock
+    - USB: serial: keyspan_pda: fix stalled writes
+    - USB: serial: keyspan_pda: fix write-wakeup use-after-free
+    - USB: serial: keyspan_pda: fix tx-unthrottle use-after-free
+    - USB: serial: keyspan_pda: fix write unthrottling
+    - btrfs: do not shorten unpin len for caching block groups
+    - ext4: fix a memory leak of ext4_free_data
+    - ext4: fix deadlock with fs freezing and EA inodes
+    - KVM: arm64: Introduce handling of AArch32 TTBCR2 traps
+    - ARM: dts: pandaboard: fix pinmux for gpio user button of Pandaboard ES
+    - ARM: dts: at91: sama5d2: fix CAN message ram offset and size
+    - xprtrdma: Fix XDRBUF_SPARSE_PAGES support
+    - powerpc: Fix incorrect stw{, ux, u, x} instructions in __set_pte_at
+    - powerpc/rtas: Fix typo of ibm,open-errinjct in RTAS filter
+    - powerpc/feature: Add CPU_FTR_NOEXECUTE to G2_LE
+    - powerpc/xmon: Change printk() to pr_cont()
+    - powerpc/8xx: Fix early debug when SMC1 is relocated
+    - powerpc/mm: Fix verification of MMU_FTR_TYPE_44x
+    - powerpc/powernv/npu: Do not attempt NPU2 setup on POWER8NVL NPU
+    - powerpc/powernv/memtrace: Don't leak kernel memory to user space
+    - powerpc/powernv/memtrace: Fix crashing the kernel when enabling concurrently
+    - ima: Don't modify file descriptor mode on the fly
+    - um: Remove use of asprinf in umid.c
+    - ceph: fix race in concurrent __ceph_remove_cap invocations
+    - SMB3: avoid confusing warning message on mount to Azure
+    - ubifs: wbuf: Don't leak kernel memory to flash
+    - jffs2: Fix GC exit abnormally
+    - jffs2: Fix ignoring mounting options problem during remounting
+    - jfs: Fix array index bounds check in dbAdjTree
+    - platform/x86: mlx-platform: remove an unused variable
+    - drm/amd/display: Fix memory leaks in S3 resume
+    - drm/dp_aux_dev: check aux_dev before use in drm_dp_aux_dev_get_by_minor()
+    - drm/i915: Fix mismatch between misplaced vma check and vma insert
+    - spi: pxa2xx: Fix use-after-free on unbind
+    - spi: spi-sh: Fix use-after-free on unbind
+    - spi: atmel-quadspi: Fix use-after-free on unbind
+    - spi: davinci: Fix use-after-free on unbind
+    - spi: fsl: fix use of spisel_boot signal on MPC8309
+    - spi: gpio: Don't leak SPI master in probe error path
+    - spi: mxic: Don't leak SPI master in probe error path
+    - spi: pic32: Don't leak DMA channels in probe error path
+    - spi: rb4xx: Don't leak SPI master in probe error path
+    - spi: sc18is602: Don't leak SPI master in probe error path
+    - spi: st-ssc4: Fix unbalanced pm_runtime_disable() in probe error path
+    - spi: synquacer: Disable clock in probe error path
+    - spi: mt7621: Disable clock in probe error path
+    - spi: mt7621: Don't leak SPI master in probe error path
+    - spi: atmel-quadspi: Disable clock in probe error path
+    - spi: atmel-quadspi: Fix AHB memory accesses
+    - soc: qcom: smp2p: Safely acquire spinlock without IRQs
+    - mtd: spinand: Fix OOB read
+    - mtd: parser: cmdline: Fix parsing of part-names with colons
+    - mtd: rawnand: qcom: Fix DMA sync on FLASH_STATUS register read
+    - mtd: rawnand: meson: fix meson_nfc_dma_buffer_release() arguments
+    - scsi: qla2xxx: Fix crash during driver load on big endian machines
+    - scsi: lpfc: Fix invalid sleeping context in lpfc_sli4_nvmet_alloc()
+    - scsi: lpfc: Re-fix use after free in lpfc_rq_buf_free()
+    - iio: buffer: Fix demux update
+    - iio: adc: rockchip_saradc: fix missing clk_disable_unprepare() on error in
+      rockchip_saradc_resume
+    - iio:light:rpr0521: Fix timestamp alignment and prevent data leak.
+    - iio:light:st_uvis25: Fix timestamp alignment and prevent data leak.
+    - iio:magnetometer:mag3110: Fix alignment and data leak issues.
+    - iio:pressure:mpl3115: Force alignment of buffer
+    - iio:imu:bmi160: Fix too large a buffer.
+    - iio:adc:ti-ads124s08: Fix buffer being too long.
+    - iio:adc:ti-ads124s08: Fix alignment and data leak issues.
+    - md/cluster: block reshape with remote resync job
+    - md/cluster: fix deadlock when node is doing resync job
+    - pinctrl: sunxi: Always call chained_irq_{enter, exit} in
+      sunxi_pinctrl_irq_handler
+    - clk: ingenic: Fix divider calculation with div tables
+    - clk: mvebu: a3700: fix the XTAL MODE pin to MPP1_9
+    - clk: tegra: Do not return 0 on failure
+    - device-dax/core: Fix memory leak when rmmod dax.ko
+    - dma-buf/dma-resv: Respect num_fences when initializing the shared fence
+      list.
+    - xen-blkback: set ring->xenblkd to NULL after kthread_stop()
+    - xen/xenbus: Allow watches discard events before queueing
+    - xen/xenbus: Add 'will_handle' callback support in xenbus_watch_path()
+    - xen/xenbus/xen_bus_type: Support will_handle watch callback
+    - xen/xenbus: Count pending messages for each watch
+    - xenbus/xenbus_backend: Disallow pending watch messages
+    - libnvdimm/namespace: Fix reaping of invalidated block-window-namespace
+      labels
+    - platform/x86: intel-vbtn: Allow switch events on Acer Switch Alpha 12
+    - PCI: Fix pci_slot_release() NULL pointer dereference
+    - regulator: axp20x: Fix DLDO2 voltage control register mask for AXP22x
+    - rtc: ep93xx: Fix NULL pointer dereference in ep93xx_rtc_read_time
+    - Revert: "ring-buffer: Remove HAVE_64BIT_ALIGNED_ACCESS"
+    - x86/CPU/AMD: Save AMD NodeId as cpu_die_id
+    - Linux 5.4.86
+  * Focal update: v5.4.85 upstream stable release (LP: #1910817)
+    - ptrace: Prevent kernel-infoleak in ptrace_get_syscall_info()
+    - ipv4: fix error return code in rtm_to_fib_config()
+    - mac80211: mesh: fix mesh_pathtbl_init() error path
+    - net: bridge: vlan: fix error return code in __vlan_add()
+    - vrf: packets with lladdr src needs dst at input with orig_iif when needs
+      strict
+    - net: hns3: remove a misused pragma packed
+    - udp: fix the proto value passed to ip_protocol_deliver_rcu for the segments
+    - enetc: Fix reporting of h/w packet counters
+    - bridge: Fix a deadlock when enabling multicast snooping
+    - net: stmmac: free tx skb buffer in stmmac_resume()
+    - tcp: select sane initial rcvq_space.space for big MSS
+    - tcp: fix cwnd-limited bug for TSO deferral where we send nothing
+    - net/mlx4_en: Avoid scheduling restart task if it is already running
+    - lan743x: fix for potential NULL pointer dereference with bare card
+    - net/mlx4_en: Handle TX error CQE
+    - net: ll_temac: Fix potential NULL dereference in temac_probe()
+    - net: stmmac: dwmac-meson8b: fix mask definition of the m250_sel mux
+    - net: stmmac: delete the eee_ctrl_timer after napi disabled
+    - ktest.pl: If size of log is too big to email, email error message
+    - USB: dummy-hcd: Fix uninitialized array use in init()
+    - USB: add RESET_RESUME quirk for Snapscan 1212
+    - ALSA: usb-audio: Fix potential out-of-bounds shift
+    - ALSA: usb-audio: Fix control 'access overflow' errors from chmap
+    - xhci: Give USB2 ports time to enter U3 in bus suspend
+    - xhci-pci: Allow host runtime PM as default for Intel Alpine Ridge LP
+    - USB: UAS: introduce a quirk to set no_write_same
+    - USB: sisusbvga: Make console support depend on BROKEN
+    - [Config] updateconfigs for USB_SISUSBVGA_CON
+    - ALSA: pcm: oss: Fix potential out-of-bounds shift
+    - serial: 8250_omap: Avoid FIFO corruption caused by MDR1 access
+    - KVM: mmu: Fix SPTE encoding of MMIO generation upper half
+    - membarrier: Explicitly sync remote cores when SYNC_CORE is requested
+    - x86/resctrl: Remove unused struct mbm_state::chunks_bw
+    - x86/resctrl: Fix incorrect local bandwidth when mba_sc is enabled
+    - Linux 5.4.85
+  * Focal update: v5.4.84 upstream stable release (LP: #1910816)
+    - Kbuild: do not emit debug info for assembly with LLVM_IAS=1
+    - x86/lib: Change .weak to SYM_FUNC_START_WEAK for arch/x86/lib/mem*_64.S
+    - iwlwifi: pcie: limit memory read spin time
+    - arm64: dts: rockchip: Assign a fixed index to mmc devices on rk3399 boards.
+    - iwlwifi: pcie: set LTR to avoid completion timeout
+    - iwlwifi: mvm: fix kernel panic in case of assert during CSA
+    - powerpc: Drop -me200 addition to build flags
+    - arm64: dts: broadcom: clear the warnings caused by empty dma-ranges
+    - ARC: stack unwinding: don't assume non-current task is sleeping
+    - scsi: ufs: Make sure clk scaling happens only when HBA is runtime ACTIVE
+    - interconnect: qcom: qcs404: Remove GPU and display RPM IDs
+    - ibmvnic: skip tx timeout reset while in resetting
+    - irqchip/gic-v3-its: Unconditionally save/restore the ITS state on suspend
+    - spi: spi-nxp-fspi: fix fspi panic by unexpected interrupts
+    - soc: fsl: dpio: Get the cpumask through cpumask_of(cpu)
+    - arm64: tegra: Disable the ACONNECT for Jetson TX2
+    - platform/x86: thinkpad_acpi: Do not report SW_TABLET_MODE on Yoga 11e
+    - platform/x86: thinkpad_acpi: Add BAT1 is primary battery quirk for Thinkpad
+      Yoga 11e 4th gen
+    - platform/x86: acer-wmi: add automatic keyboard background light toggle key
+      as KEY_LIGHTS_TOGGLE
+    - platform/x86: intel-vbtn: Support for tablet mode on HP Pavilion 13 x360 PC
+    - platform/x86: touchscreen_dmi: Add info for the Irbis TW118 tablet
+    - can: m_can: m_can_dev_setup(): add support for bosch mcan version 3.3.0
+    - ktest.pl: Fix incorrect reboot for grub2bls
+    - Input: cm109 - do not stomp on control URB
+    - Input: i8042 - add Acer laptops to the i8042 reset list
+    - mmc: block: Fixup condition for CMD13 polling for RPMB requests
+    - drm/i915/display/dp: Compute the correct slice count for VDSC on DP
+    - kbuild: avoid static_assert for genksyms
+    - proc: use untagged_addr() for pagemap_read addresses
+    - scsi: be2iscsi: Revert "Fix a theoretical leak in beiscsi_create_eqs()"
+    - x86/mm/mem_encrypt: Fix definition of PMD_FLAGS_DEC_WP
+    - x86/membarrier: Get rid of a dubious optimization
+    - x86/apic/vector: Fix ordering in vector assignment
+    - mm/zsmalloc.c: drop ZSMALLOC_PGTABLE_MAPPING
+    - [Config] updateconfigs for PGTABLE_MAPPING
+    - compiler.h: fix barrier_data() on clang
+    - Linux 5.4.84
+  * MSFT Touchpad not working on Lenovo Legion-5 15ARH05 (LP: #1887190) // Focal
+    update: v5.4.84 upstream stable release (LP: #1910816)
+    - pinctrl: amd: remove debounce filter setting in IRQ type setting
+  * Focal update: v5.4.83 upstream stable release (LP: #1910784)
+    - pinctrl: baytrail: Replace WARN with dev_info_once when setting direct-irq
+      pin to output
+    - pinctrl: baytrail: Fix pin being driven low for a while on gpiod_get(...,
+      GPIOD_OUT_HIGH)
+    - usb: gadget: f_fs: Use local copy of descriptors for userspace copy
+    - USB: serial: kl5kusb105: fix memleak on open
+    - USB: serial: ch341: add new Product ID for CH341A
+    - USB: serial: ch341: sort device-id entries
+    - USB: serial: option: add Fibocom NL668 variants
+    - USB: serial: option: add support for Thales Cinterion EXS82
+    - USB: serial: option: fix Quectel BG96 matching
+    - tty: Fix ->pgrp locking in tiocspgrp()
+    - tty: Fix ->session locking
+    - ALSA: hda/realtek: Fix bass speaker DAC assignment on Asus Zephyrus G14
+    - ALSA: hda/realtek: Add mute LED quirk to yet another HP x360 model
+    - ALSA: hda/realtek: Enable headset of ASUS UX482EG & B9400CEA with ALC294
+    - ALSA: hda/realtek - Add new codec supported for ALC897
+    - ALSA: hda/generic: Add option to enforce preferred_dacs pairs
+    - ftrace: Fix updating FTRACE_FL_TRAMP
+    - cifs: allow syscalls to be restarted in __smb_send_rqst()
+    - cifs: fix potential use-after-free in cifs_echo_request()
+    - i2c: imx: Don't generate STOP condition if arbitration has been lost
+    - thunderbolt: Fix use-after-free in remove_unplugged_switch()
+    - drm/i915/gt: Program mocs:63 for cache eviction on gen9
+    - scsi: mpt3sas: Fix ioctl timeout
+    - dm writecache: fix the maximum number of arguments
+    - powerpc/64s/powernv: Fix memory corruption when saving SLB entries on MCE
+    - genirq/irqdomain: Add an irq_create_mapping_affinity() function
+    - powerpc/pseries: Pass MSI affinity to irq_create_mapping()
+    - dm: fix bug with RCU locking in dm_blk_report_zones
+    - dm: remove invalid sparse __acquires and __releases annotations
+    - x86/uprobes: Do not use prefixes.nbytes when looping over prefixes.bytes
+    - coredump: fix core_pattern parse error
+    - mm: list_lru: set shrinker map bit when child nr_items is not zero
+    - mm/swapfile: do not sleep with a spin lock held
+    - speakup: Reject setting the speakup line discipline outside of speakup
+    - i2c: imx: Fix reset of I2SR_IAL flag
+    - i2c: imx: Check for I2SR_IAL after every byte
+    - spi: bcm2835: Release the DMA channel if probe fails after dma_init
+    - iommu/amd: Set DTE[IntTabLen] to represent 512 IRTEs
+    - tracing: Fix userstacktrace option for instances
+    - lib/syscall: fix syscall registers retrieval on 32-bit platforms
+    - can: af_can: can_rx_unregister(): remove WARN() statement from list
+      operation sanity check
+    - gfs2: check for empty rgrp tree in gfs2_ri_update
+    - netfilter: ipset: prevent uninit-value in hash_ip6_add
+    - tipc: fix a deadlock when flushing scheduled work
+    - ASoC: wm_adsp: fix error return code in wm_adsp_load()
+    - rtw88: debug: Fix uninitialized memory in debugfs code
+    - i2c: qup: Fix error return code in qup_i2c_bam_schedule_desc()
+    - dm writecache: remove BUG() and fail gracefully instead
+    - Input: i8042 - fix error return code in i8042_setup_aux()
+    - netfilter: nf_tables: avoid false-postive lockdep splat
+    - netfilter: nftables_offload: set address type in control dissector
+    - x86/insn-eval: Use new for_each_insn_prefix() macro to loop over prefixes
+      bytes
+    - Linux 5.4.83
+  * dep-8 ubuntu-regression-suite tests are not run for all linux-hwe-* kernels
+    (LP: #1908529)
+    - [dep-8] Allow all hwe kernels
+  * failing ftrace self tests from 5.7+ onwards (LP: #1893024)
+    - SAUCE: Revert "selftests/ftrace: check for do_sys_openat2 in user-memory
+      test"
+  * selftests: test_vxlan_under_vrf: mute unnecessary error message
+    (LP: #1908342)
+    - selftests: test_vxlan_under_vrf: mute unnecessary error message
+  * Focal update: v5.4.82 upstream stable release (LP: #1908564)
+    - devlink: Hold rtnl lock while reading netdev attributes
+    - ipv6: addrlabel: fix possible memory leak in ip6addrlbl_net_init
+    - net/af_iucv: set correct sk_protocol for child sockets
+    - net/tls: missing received data after fast remote close
+    - net/tls: Protect from calling tls_dev_del for TLS RX twice
+    - rose: Fix Null pointer dereference in rose_send_frame()
+    - sock: set sk_err to ee_errno on dequeue from errq
+    - tcp: Set INET_ECN_xmit configuration in tcp_reinit_congestion_control
+    - tun: honor IOCB_NOWAIT flag
+    - usbnet: ipheth: fix connectivity with iOS 14
+    - bonding: wait for sysfs kobject destruction before freeing struct slave
+    - staging/octeon: fix up merge error
+    - ima: extend boot_aggregate with kernel measurements
+    - sched/fair: Fix unthrottle_cfs_rq() for leaf_cfs_rq list
+    - netfilter: bridge: reset skb->pkt_type after NF_INET_POST_ROUTING traversal
+    - ipv4: Fix tos mask in inet_rtm_getroute()
+    - dt-bindings: net: correct interrupt flags in examples
+    - chelsio/chtls: fix panic during unload reload chtls
+    - ibmvnic: Ensure that SCRQ entry reads are correctly ordered
+    - ibmvnic: Fix TX completion error handling
+    - inet_ecn: Fix endianness of checksum update when setting ECT(1)
+    - net: ip6_gre: set dev->hard_header_len when using header_ops
+    - net/x25: prevent a couple of overflows
+    - cxgb3: fix error return code in t3_sge_alloc_qset()
+    - net: pasemi: fix error return code in pasemi_mac_open()
+    - vxlan: fix error return code in __vxlan_dev_create()
+    - chelsio/chtls: fix a double free in chtls_setkey()
+    - net: mvpp2: Fix error return code in mvpp2_open()
+    - net: skbuff: ensure LSE is pullable before decrementing the MPLS ttl
+    - net: openvswitch: ensure LSE is pullable before reading it
+    - net/sched: act_mpls: ensure LSE is pullable before reading it
+    - net/mlx5: DR, Proper handling of unsupported Connect-X6DX SW steering
+    - net/mlx5: Fix wrong address reclaim when command interface is down
+    - ALSA: usb-audio: US16x08: fix value count for level meters
+    - Input: xpad - support Ardwiino Controllers
+    - tracing: Remove WARN_ON in start_thread()
+    - RDMA/i40iw: Address an mmap handler exploit in i40iw
+    - Linux 5.4.82
+  * Focal update: v5.4.81 upstream stable release (LP: #1908562)
+    - spi: bcm-qspi: Fix use-after-free on unbind
+    - spi: bcm2835: Fix use-after-free on unbind
+    - ipv4: use IS_ENABLED instead of ifdef
+    - netfilter: clear skb->next in NF_HOOK_LIST()
+    - btrfs: tree-checker: add missing return after error in root_item
+    - btrfs: tree-checker: add missing returns after data_ref alignment checks
+    - btrfs: don't access possibly stale fs_info data for printing duplicate
+      device
+    - btrfs: fix lockdep splat when reading qgroup config on mount
+    - wireless: Use linux/stddef.h instead of stddef.h
+    - smb3: Call cifs reconnect from demultiplex thread
+    - smb3: Avoid Mid pending list corruption
+    - smb3: Handle error case during offload read path
+    - cifs: fix a memleak with modefromsid
+    - KVM: PPC: Book3S HV: XIVE: Fix possible oops when accessing ESB page
+    - KVM: arm64: vgic-v3: Drop the reporting of GICR_TYPER.Last for userspace
+    - KVM: x86: handle !lapic_in_kernel case in kvm_cpu_*_extint
+    - KVM: x86: Fix split-irqchip vs interrupt injection window request
+    - trace: fix potenial dangerous pointer
+    - arm64: pgtable: Fix pte_accessible()
+    - arm64: pgtable: Ensure dirty bit is preserved across pte_wrprotect()
+    - HID: uclogic: Add ID for Trust Flex Design Tablet
+    - HID: ite: Replace ABS_MISC 120/121 events with touchpad on/off keypresses
+    - HID: cypress: Support Varmilo Keyboards' media hotkeys
+    - HID: add support for Sega Saturn
+    - Input: i8042 - allow insmod to succeed on devices without an i8042
+      controller
+    - HID: hid-sensor-hub: Fix issue with devices with no report ID
+    - staging: ralink-gdma: fix kconfig dependency bug for DMA_RALINK
+    - HID: add HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE for Gamevice devices
+    - dmaengine: xilinx_dma: use readl_poll_timeout_atomic variant
+    - x86/xen: don't unbind uninitialized lock_kicker_irq
+    - HID: logitech-hidpp: Add HIDPP_CONSUMER_VENDOR_KEYS quirk for the Dinovo
+      Edge
+    - HID: Add Logitech Dinovo Edge battery quirk
+    - proc: don't allow async path resolution of /proc/self components
+    - nvme: free sq/cq dbbuf pointers when dbbuf set fails
+    - vhost scsi: fix cmd completion race
+    - dmaengine: pl330: _prep_dma_memcpy: Fix wrong burst size
+    - scsi: libiscsi: Fix NOP race condition
+    - scsi: target: iscsi: Fix cmd abort fabric stop race
+    - perf/x86: fix sysfs type mismatches
+    - xtensa: uaccess: Add missing __user to strncpy_from_user() prototype
+    - net: dsa: mv88e6xxx: Wait for EEPROM done after HW reset
+    - bus: ti-sysc: Fix bogus resetdone warning on enable for cpsw
+    - ARM: OMAP2+: Manage MPU state properly for omap_enter_idle_coupled()
+    - phy: tegra: xusb: Fix dangling pointer on probe failure
+    - iwlwifi: mvm: write queue_sync_state only for sync
+    - batman-adv: set .owner to THIS_MODULE
+    - arch: pgtable: define MAX_POSSIBLE_PHYSMEM_BITS where needed
+    - ARM: dts: dra76x: m_can: fix order of clocks
+    - scsi: ufs: Fix race between shutdown and runtime resume flow
+    - bnxt_en: fix error return code in bnxt_init_one()
+    - bnxt_en: fix error return code in bnxt_init_board()
+    - video: hyperv_fb: Fix the cache type when mapping the VRAM
+    - bnxt_en: Release PCI regions when DMA mask setup fails during probe.
+    - cxgb4: fix the panic caused by non smac rewrite
+    - s390/qeth: make af_iucv TX notification call more robust
+    - s390/qeth: fix af_iucv notification race
+    - s390/qeth: fix tear down of async TX buffers
+    - ibmvnic: fix call_netdevice_notifiers in do_reset
+    - ibmvnic: notify peers when failover and migration happen
+    - powerpc/64s: Fix allnoconfig build since uaccess flush
+    - IB/mthca: fix return value of error branch in mthca_init_cq()
+    - i40e: Fix removing driver while bare-metal VFs pass traffic
+    - nfc: s3fwrn5: use signed integer for parsing GPIO numbers
+    - net: ena: set initial DMA width to avoid intel iommu issue
+    - ibmvnic: fix NULL pointer dereference in reset_sub_crq_queues
+    - ibmvnic: fix NULL pointer dereference in ibmvic_reset_crq
+    - optee: add writeback to valid memory type
+    - arm64: tegra: Wrong AON HSP reg property size
+    - efivarfs: revert "fix memory leak in efivarfs_create()"
+    - efi: EFI_EARLYCON should depend on EFI
+    - can: gs_usb: fix endianess problem with candleLight firmware
+    - platform/x86: thinkpad_acpi: Send tablet mode switch at wakeup time
+    - platform/x86: toshiba_acpi: Fix the wrong variable assignment
+    - RDMA/hns: Fix retry_cnt and rnr_cnt when querying QP
+    - RDMA/hns: Bugfix for memory window mtpt configuration
+    - can: m_can: m_can_open(): remove IRQF_TRIGGER_FALLING from
+      request_threaded_irq()'s flags
+    - can: m_can: fix nominal bitiming tseg2 min for version >= 3.1
+    - perf stat: Use proper cpu for shadow stats
+    - perf probe: Fix to die_entrypc() returns error correctly
+    - spi: bcm2835aux: Restore err assignment in bcm2835aux_spi_probe
+    - USB: core: Change %pK for __user pointers to %px
+    - usb: gadget: f_midi: Fix memleak in f_midi_alloc
+    - USB: quirks: Add USB_QUIRK_DISCONNECT_SUSPEND quirk for Lenovo A630Z TIO
+      built-in usb-audio card
+    - usb: gadget: Fix memleak in gadgetfs_fill_super
+    - irqchip/exiu: Fix the index of fwspec for IRQ type
+    - x86/mce: Do not overwrite no_way_out if mce_end() fails
+    - x86/speculation: Fix prctl() when spectre_v2_user={seccomp,prctl},ibpb
+    - x86/resctrl: Remove superfluous kernfs_get() calls to prevent refcount leak
+    - x86/resctrl: Add necessary kernfs_put() calls to prevent refcount leak
+    - USB: core: Fix regression in Hercules audio card
+    - ASoC: Intel: Skylake: Remove superfluous chip initialization
+    - ASoC: Intel: Skylake: Select hda configuration permissively
+    - ASoC: Intel: Skylake: Enable codec wakeup during chip init
+    - ASoC: Intel: Skylake: Shield against no-NHLT configurations
+    - ASoC: Intel: Allow for ROM init retry on CNL platforms
+    - ASoC: Intel: Skylake: Await purge request ack on CNL
+    - ASoC: Intel: Multiple I/O PCM format support for pipe
+    - ASoC: Intel: Skylake: Automatic DMIC format configuration according to
+      information from NHLT
+    - Linux 5.4.81
+  * Focal update: v5.4.80 upstream stable release (LP: #1908561)
+    - ah6: fix error return code in ah6_input()
+    - atm: nicstar: Unmap DMA on send error
+    - bnxt_en: read EEPROM A2h address using page 0
+    - devlink: Add missing genlmsg_cancel() in devlink_nl_sb_port_pool_fill()
+    - Exempt multicast addresses from five-second neighbor lifetime
+    - inet_diag: Fix error path to cancel the meseage in inet_req_diag_fill()
+    - ipv6: Fix error path to cancel the meseage
+    - lan743x: fix issue causing intermittent kernel log warnings
+    - lan743x: prevent entire kernel HANG on open, for some platforms
+    - mlxsw: core: Use variable timeout for EMAD retries
+    - net: b44: fix error return code in b44_init_one()
+    - net: bridge: add missing counters to ndo_get_stats64 callback
+    - net: dsa: mv88e6xxx: Avoid VTU corruption on 6097
+    - net: ethernet: ti: cpsw: fix error return code in cpsw_probe()
+    - net: Have netpoll bring-up DSA management interface
+    - netlabel: fix our progress tracking in netlbl_unlabel_staticlist()
+    - netlabel: fix an uninitialized warning in netlbl_unlabel_staticlist()
+    - net: lantiq: Wait for the GPHY firmware to be ready
+    - net/mlx4_core: Fix init_hca fields offset
+    - net: qualcomm: rmnet: Fix incorrect receive packet handling during cleanup
+    - net/smc: fix direct access to ib_gid_addr->ndev in smc_ib_determine_gid()
+    - net/tls: fix corrupted data in recvmsg
+    - net: x25: Increase refcnt of "struct x25_neigh" in x25_rx_call_request
+    - page_frag: Recover from memory pressure
+    - qed: fix error return code in qed_iwarp_ll2_start()
+    - qlcnic: fix error return code in qlcnic_83xx_restart_hw()
+    - sctp: change to hold/put transport for proto_unreach_timer
+    - tcp: only postpone PROBE_RTT if RTT is < current min_rtt estimate
+    - net/mlx5: Add handling of port type in rule deletion
+    - net/mlx5: Disable QoS when min_rates on all VFs are zero
+    - net: usb: qmi_wwan: Set DTR quirk for MR400
+    - net/ncsi: Fix netlink registration
+    - net: ftgmac100: Fix crash when removing driver
+    - pinctrl: rockchip: enable gpio pclk for rockchip_gpio_to_irq
+    - scsi: ufs: Fix unbalanced scsi_block_reqs_cnt caused by ufshcd_hold()
+    - selftests: kvm: Fix the segment descriptor layout to match the actual layout
+    - ACPI: button: Add DMI quirk for Medion Akoya E2228T
+    - arm64: errata: Fix handling of 1418040 with late CPU onlining
+    - arm64: psci: Avoid printing in cpu_psci_cpu_die()
+    - arm64: smp: Tell RCU about CPUs that fail to come online
+    - vfs: remove lockdep bogosity in __sb_start_write
+    - gfs2: fix possible reference leak in gfs2_check_blk_type
+    - hwmon: (pwm-fan) Fix RPM calculation
+    - arm64: dts: allwinner: beelink-gs1: Enable both RGMII RX/TX delay
+    - arm64: dts: allwinner: Pine H64: Enable both RGMII RX/TX delay
+    - arm64: dts: allwinner: a64: OrangePi Win: Fix ethernet node
+    - arm64: dts: allwinner: a64: Pine64 Plus: Fix ethernet node
+    - arm64: dts: allwinner: h5: OrangePi PC2: Fix ethernet node
+    - ARM: dts: sun8i: r40: bananapi-m2-ultra: Fix ethernet node
+    - Revert "arm: sun8i: orangepi-pc-plus: Set EMAC activity LEDs to active high"
+    - ARM: dts: sun6i: a31-hummingbird: Enable RGMII RX/TX delay on Ethernet PHY
+    - ARM: dts: sun7i: cubietruck: Enable RGMII RX/TX delay on Ethernet PHY
+    - ARM: dts: sun7i: bananapi-m1-plus: Enable RGMII RX/TX delay on Ethernet PHY
+    - ARM: dts: sun8i: h3: orangepi-plus2e: Enable RGMII RX/TX delay on Ethernet
+      PHY
+    - ARM: dts: sun8i: a83t: Enable both RGMII RX/TX delay on Ethernet PHY
+    - ARM: dts: sun9i: Enable both RGMII RX/TX delay on Ethernet PHY
+    - ARM: dts: sunxi: bananapi-m2-plus: Enable RGMII RX/TX delay on Ethernet PHY
+    - arm64: dts: allwinner: a64: bananapi-m64: Enable RGMII RX/TX delay on PHY
+    - Input: adxl34x - clean up a data type in adxl34x_probe()
+    - MIPS: export has_transparent_hugepage() for modules
+    - arm64: dts: allwinner: h5: OrangePi Prime: Fix ethernet node
+    - arm64: dts imx8mn: Remove non-existent USB OTG2
+    - arm: dts: imx6qdl-udoo: fix rgmii phy-mode for ksz9031 phy
+    - swiotlb: using SIZE_MAX needs limits.h included
+    - arm64: dts: imx8mm: fix voltage for 1.6GHz CPU operating point
+    - ARM: dts: imx50-evk: Fix the chip select 1 IOMUX
+    - Input: resistive-adc-touch - fix kconfig dependency on IIO_BUFFER
+    - rfkill: Fix use-after-free in rfkill_resume()
+    - RDMA/pvrdma: Fix missing kfree() in pvrdma_register_device()
+    - [Config] updateconfigs for INFINIBAND_VIRT_DMA
+    - RMDA/sw: Don't allow drivers using dma_virt_ops on highmem configs
+    - perf lock: Don't free "lock_seq_stat" if read_count isn't zero
+    - tools, bpftool: Add missing close before bpftool net attach exit
+    - ip_tunnels: Set tunnel option flag when tunnel metadata is present
+    - can: af_can: prevent potential access of uninitialized member in can_rcv()
+    - can: af_can: prevent potential access of uninitialized member in canfd_rcv()
+    - can: dev: can_restart(): post buffer from the right context
+    - can: ti_hecc: Fix memleak in ti_hecc_probe
+    - can: mcba_usb: mcba_usb_start_xmit(): first fill skb, then pass to
+      can_put_echo_skb()
+    - can: peak_usb: fix potential integer overflow on shift of a int
+    - can: flexcan: fix failure handling of pm_runtime_get_sync()
+    - can: tcan4x5x: replace depends on REGMAP_SPI with depends on SPI
+    - can: tcan4x5x: tcan4x5x_can_probe(): add missing error checking for
+      devm_regmap_init()
+    - can: tcan4x5x: tcan4x5x_can_remove(): fix order of deregistration
+    - can: m_can: m_can_handle_state_change(): fix state change
+    - can: m_can: m_can_class_free_dev(): introduce new function
+    - can: m_can: m_can_stop(): set device to software init mode before closing
+    - ASoC: qcom: lpass-platform: Fix memory leak
+    - selftests/bpf: Fix error return code in run_getsockopt_test()
+    - MIPS: Alchemy: Fix memleak in alchemy_clk_setup_cpu
+    - drm/sun4i: dw-hdmi: fix error return code in sun8i_dw_hdmi_bind()
+    - net/mlx5: E-Switch, Fail mlx5_esw_modify_vport_rate if qos disabled
+    - bpf, sockmap: Fix partial copy_page_to_iter so progress can still be made
+    - bpf, sockmap: Ensure SO_RCVBUF memory is observed on ingress redirect
+    - can: kvaser_pciefd: Fix KCAN bittiming limits
+    - can: kvaser_usb: kvaser_usb_hydra: Fix KCAN bittiming limits
+    - iommu/vt-d: Move intel_iommu_gfx_mapped to Intel IOMMU header
+    - iommu/vt-d: Avoid panic if iommu init fails in tboot system
+    - can: flexcan: flexcan_chip_start(): fix erroneous
+      flexcan_transceiver_enable() during bus-off recovery
+    - can: m_can: process interrupt only when not runtime suspended
+    - xfs: fix the minrecs logic when dealing with inode root child blocks
+    - xfs: strengthen rmap record flags checking
+    - xfs: return corresponding errcode if xfs_initialize_perag() fail
+    - regulator: ti-abb: Fix array out of bound read access on the first
+      transition
+    - fail_function: Remove a redundant mutex unlock
+    - xfs: revert "xfs: fix rmap key and record comparison functions"
+    - bpf, sockmap: Skb verdict SK_PASS to self already checked rmem limits
+    - bpf, sockmap: On receive programs try to fast track SK_PASS ingress
+    - bpf, sockmap: Use truesize with sk_rmem_schedule()
+    - bpf, sockmap: Avoid returning unneeded EAGAIN when redirecting to self
+    - efi/x86: Free efi_pgd with free_pages()
+    - libfs: fix error cast of negative value in simple_attr_write()
+    - HID: logitech-hidpp: Add PID for MX Anywhere 2
+    - HID: logitech-dj: Handle quad/bluetooth keyboards with a builtin trackpad
+    - HID: logitech-dj: Fix Dinovo Mini when paired with a MX5x00 receiver
+    - speakup: Do not let the line discipline be used several times
+    - ALSA: firewire: Clean up a locking issue in copy_resp_to_buf()
+    - ALSA: usb-audio: Add delay quirk for all Logitech USB devices
+    - ALSA: ctl: fix error path at adding user-defined element set
+    - ALSA: mixart: Fix mutex deadlock
+    - ALSA: hda/realtek - Add supported for Lenovo ThinkPad Headset Button
+    - ALSA: hda/realtek: Add some Clove SSID in the ALC293(ALC1220)
+    - tty: serial: imx: fix potential deadlock
+    - tty: serial: imx: keep console clocks always on
+    - HID: logitech-dj: Fix an error in mse_bluetooth_descriptor
+    - efivarfs: fix memory leak in efivarfs_create()
+    - staging: rtl8723bs: Add 024c:0627 to the list of SDIO device-ids
+    - iio: light: fix kconfig dependency bug for VCNL4035
+    - ext4: fix bogus warning in ext4_update_dx_flag()
+    - iio: accel: kxcjk1013: Replace is_smo8500_device with an acpi_type enum
+    - iio: accel: kxcjk1013: Add support for KIOX010A ACPI DSM for setting tablet-
+      mode
+    - iio: adc: mediatek: fix unset field
+    - spi: lpspi: Fix use-after-free on unbind
+    - spi: Introduce device-managed SPI controller allocation
+    - spi: npcm-fiu: Don't leak SPI master in probe error path
+    - spi: bcm2835aux: Fix use-after-free on unbind
+    - regulator: pfuze100: limit pfuze-support-disable-sw to pfuze{100,200}
+    - regulator: fix memory leak with repeated set_machine_constraints()
+    - regulator: avoid resolve_supply() infinite recursion
+    - regulator: workaround self-referent regulators
+    - xtensa: fix TLBTEMP area placement
+    - xtensa: disable preemption around cache alias management calls
+    - mac80211: minstrel: remove deferred sampling code
+    - mac80211: minstrel: fix tx status processing corner case
+    - mac80211: free sta in sta_info_insert_finish() on errors
+    - s390/cpum_sf.c: fix file permission for cpum_sfb_size
+    - s390/dasd: fix null pointer dereference for ERP requests
+    - Drivers: hv: vmbus: Allow cleanup of VMBUS_CONNECT_CPU if disconnected
+    - drm/amd/display: Add missing pflip irq for dcn2.0
+    - drm/i915: Handle max_bpc==16
+    - mmc: sdhci-pci: Prefer SDR25 timing for High Speed mode for BYT-based Intel
+      controllers
+    - ptrace: Set PF_SUPERPRIV when checking capability
+    - seccomp: Set PF_SUPERPRIV when checking capability
+    - x86/microcode/intel: Check patch signature before saving microcode for early
+      loading
+    - mm: memcg/slab: fix root memcg vmstats
+    - mm/userfaultfd: do not access vma->vm_mm after calling handle_userfault()
+    - mm, page_alloc: skip ->waternark_boost for atomic order-0 allocations
+    - sched/fair: Fix overutilized update in enqueue_task_fair()
+    - Linux 5.4.80
+  * [SRU][F/G/H/U/OEM-5.6] Fix i2c report error on elan trackpoint
+    (LP: #1908335)
+    - Input: elan_i2c - add support for high resolution reports
+    - Input: elan_i2c - add new trackpoint report type 0x5F
+    - Input: elantech - fix protocol errors for some trackpoints in SMBus mode
+  * rtwpci driver blocks the system to enter PC10, stuck at PC3 (LP: #1907200)
+    - SAUCE: rtw88: 8723de: let cpu enter c10
+  * [UBUNTU 21.04] s390/pci: vfio-pci mmio being disabled erroneously
+    (LP: #1907265)
+    - s390/pci: Mark all VFs as not implementing PCI_COMMAND_MEMORY
+  * Touchpad not detected on ByteSpeed C15B laptop (LP: #1906128)
+    - Input: i8042 - add ByteSpeed touchpad to noloop table
+  * Fix reading speed and duplex sysfs on igc device (LP: #1906851)
+    - SAUCE: igc: Report speed and duplex as unknown when device is runtime
+      suspended
+  * stack trace in kernel (LP: #1903596)
+    - net: napi: remove useless stack trace
+  * Refresh ACPI wakeup power to make Thunderbolt hotplug detection work
+    (LP: #1906229)
+    - PM: ACPI: PCI: Drop acpi_pm_set_bridge_wakeup()
+    - PM: ACPI: Refresh wakeup device power configuration every time
+  * CVE-2020-27777
+    - [Config]: Set CONFIG_PPC_RTAS_FILTER
+  * Add dpcd backlight control for 0x4c83 0x4f41 (LP: #1905663)
+    - SAUCE: drm/dp: Add dpcd backlight control for 0x4c83 0x4f41
+  * Focal update: v5.4.79 upstream stable release (LP: #1907151)
+    - powerpc: Only include kup-radix.h for 64-bit Book3S
+    - MIPS: PCI: Fix MIPS build
+    - powerpc/8xx: Always fault when _PAGE_ACCESSED is not set
+    - net: lantiq: Add locking for TX DMA channel
+    - Input: sunkbd - avoid use-after-free in teardown paths
+    - mac80211: always wind down STA state
+    - can: proc: can_remove_proc(): silence remove_proc_entry warning
+    - KVM: x86: clflushopt should be treated as a no-op by emulation
+    - ACPI: GED: fix -Wformat
+    - Linux 5.4.79
+
+  [ Ubuntu: 5.4.0-65.73 ]
+
+  * focal/linux: 5.4.0-65.73 -proposed tracker (LP: #1912220)
+  * initramfs unpacking failed (LP: #1835660)
+    - SAUCE: lib/decompress_unlz4.c: correctly handle zero-padding around initrds.
+  * overlay: permission regression in 5.4.0-51.56 due to patches related to
+    CVE-2020-16120 (LP: #1900141)
+    - ovl: do not fail because of O_NOATIME
+  * Focal update: v5.4.79 upstream stable release (LP: #1907151)
+    - net/mlx5: Use async EQ setup cleanup helpers for multiple EQs
+    - net/mlx5: poll cmd EQ in case of command timeout
+    - net/mlx5: Fix a race when moving command interface to events mode
+    - net/mlx5: Add retry mechanism to the command entry index allocation
+  * Kernel 5.4.0-56 Wi-Fi does not connect (LP: #1906770)
+    - mt76: fix fix ampdu locking
+  * [Ubuntu 21.04 FEAT] mpt3sas: Request to include the patch set which supports
+    topology where zoning is enabled in expander (LP: #1899802)
+    - scsi: mpt3sas: Define hba_port structure
+    - scsi: mpt3sas: Allocate memory for hba_port objects
+    - scsi: mpt3sas: Rearrange _scsih_mark_responding_sas_device()
+    - scsi: mpt3sas: Update hba_port's sas_address & phy_mask
+    - scsi: mpt3sas: Get device objects using sas_address & portID
+    - scsi: mpt3sas: Rename transport_del_phy_from_an_existing_port()
+    - scsi: mpt3sas: Get sas_device objects using device's rphy
+    - scsi: mpt3sas: Update hba_port objects after host reset
+    - scsi: mpt3sas: Set valid PhysicalPort in SMPPassThrough
+    - scsi: mpt3sas: Handling HBA vSES device
+    - scsi: mpt3sas: Add bypass_dirty_port_flag parameter
+    - scsi: mpt3sas: Handle vSES vphy object during HBA reset
+    - scsi: mpt3sas: Add module parameter multipath_on_hba
+    - scsi: mpt3sas: Bump driver version to 35.101.00.00
+
+  [ Ubuntu: 5.4.0-64.72 ]
+
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+
+  [ Ubuntu: 5.4.0-62.70 ]
+
+  * focal/linux: 5.4.0-62.70 -proposed tracker (LP: #1911144)
+  * CVE-2020-28374
+    - SAUCE: target: fix XCOPY NAA identifier lookup
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+
+  [ Ubuntu: 5.4.0-60.67 ]
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update variants
+    - update dkms package versions
+  * CVE-2021-1052 // CVE-2021-1053
+    - [Packaging] NVIDIA -- Add the NVIDIA 460 driver
+
+  [ Ubuntu: 5.4.0-59.65 ]
+
+  * focal/linux: 5.4.0-59.65 -proposed tracker (LP: #1907604)
+  * focal: selftests/bpf build broken: test_map_init.skel.h: No such file or
+    directory (LP: #1906866)
+    - SAUCE: Revert selftests/ "bpf: Zero-fill re-used per-cpu map element"
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+  * memory is leaked when tasks are moved to net_prio (LP: #1886859)
+    - netprio_cgroup: Fix unlimited memory leak of v2 cgroups
+  * Focal update: v5.4.78 upstream stable release (LP: #1905618)
+    - drm/i915/gem: Flush coherency domains on first set-domain-ioctl
+    - time: Prevent undefined behaviour in timespec64_to_ns()
+    - nbd: don't update block size after device is started
+    - KVM: arm64: Force PTE mapping on fault resulting in a device mapping
+    - PCI: qcom: Make sure PCIe is reset before init for rev 2.1.0
+    - usb: dwc3: gadget: Continue to process pending requests
+    - usb: dwc3: gadget: Reclaim extra TRBs after request completion
+    - btrfs: tracepoints: output proper root owner for trace_find_free_extent()
+    - btrfs: sysfs: init devices outside of the chunk_mutex
+    - btrfs: reschedule when cloning lots of extents
+    - ASoC: Intel: kbl_rt5663_max98927: Fix kabylake_ssp_fixup function
+    - genirq: Let GENERIC_IRQ_IPI select IRQ_DOMAIN_HIERARCHY
+    - hv_balloon: disable warning when floor reached
+    - net: xfrm: fix a race condition during allocing spi
+    - ASoC: codecs: wcd9335: Set digital gain range correctly
+    - xfs: set xefi_discard when creating a deferred agfl free log intent item
+    - netfilter: use actual socket sk rather than skb sk when routing harder
+    - netfilter: nf_tables: missing validation from the abort path
+    - netfilter: ipset: Update byte and packet counters regardless of whether they
+      match
+    - powerpc/eeh_cache: Fix a possible debugfs deadlock
+    - perf trace: Fix segfault when trying to trace events by cgroup
+    - perf tools: Add missing swap for ino_generation
+    - ALSA: hda: prevent undefined shift in snd_hdac_ext_bus_get_link()
+    - iommu/vt-d: Fix a bug for PDP check in prq_event_thread
+    - afs: Fix warning due to unadvanced marshalling pointer
+    - can: rx-offload: don't call kfree_skb() from IRQ context
+    - can: dev: can_get_echo_skb(): prevent call to kfree_skb() in hard IRQ
+      context
+    - can: dev: __can_get_echo_skb(): fix real payload length return value for RTR
+      frames
+    - can: can_create_echo_skb(): fix echo skb generation: always use skb_clone()
+    - can: j1939: swap addr and pgn in the send example
+    - can: j1939: j1939_sk_bind(): return failure if netdev is down
+    - can: ti_hecc: ti_hecc_probe(): add missed clk_disable_unprepare() in error
+      path
+    - can: xilinx_can: handle failure cases of pm_runtime_get_sync
+    - can: peak_usb: add range checking in decode operations
+    - can: peak_usb: peak_usb_get_ts_time(): fix timestamp wrapping
+    - can: peak_canfd: pucan_handle_can_rx(): fix echo management when loopback is
+      on
+    - can: flexcan: remove FLEXCAN_QUIRK_DISABLE_MECR quirk for LS1021A
+    - can: flexcan: flexcan_remove(): disable wakeup completely
+    - xfs: flush new eof page on truncate to avoid post-eof corruption
+    - xfs: fix scrub flagging rtinherit even if there is no rt device
+    - tpm: efi: Don't create binary_bios_measurements file for an empty log
+    - random32: make prandom_u32() output unpredictable
+    - KVM: arm64: ARM_SMCCC_ARCH_WORKAROUND_1 doesn't return
+      SMCCC_RET_NOT_REQUIRED
+    - KVM: x86: don't expose MSR_IA32_UMWAIT_CONTROL unconditionally
+    - ath9k_htc: Use appropriate rs_datalen type
+    - ASoC: qcom: sdm845: set driver name correctly
+    - ASoC: cs42l51: manage mclk shutdown delay
+    - usb: dwc3: pci: add support for the Intel Alder Lake-S
+    - opp: Reduce the size of critical section in _opp_table_kref_release()
+    - usb: gadget: goku_udc: fix potential crashes in probe
+    - selftests/ftrace: check for do_sys_openat2 in user-memory test
+    - selftests: pidfd: fix compilation errors due to wait.h
+    - ALSA: hda: Separate runtime and system suspend
+    - ALSA: hda: Reinstate runtime_allow() for all hda controllers
+    - gfs2: Free rd_bits later in gfs2_clear_rgrpd to fix use-after-free
+    - gfs2: Add missing truncate_inode_pages_final for sd_aspace
+    - gfs2: check for live vs. read-only file system in gfs2_fitrim
+    - scsi: hpsa: Fix memory leak in hpsa_init_one()
+    - drm/amdgpu: perform srbm soft reset always on SDMA resume
+    - drm/amd/pm: perform SMC reset on suspend/hibernation
+    - drm/amd/pm: do not use ixFEATURE_STATUS for checking smc running
+    - mac80211: fix use of skb payload instead of header
+    - cfg80211: initialize wdev data earlier
+    - cfg80211: regulatory: Fix inconsistent format argument
+    - tracing: Fix the checking of stackidx in __ftrace_trace_stack
+    - scsi: scsi_dh_alua: Avoid crash during alua_bus_detach()
+    - scsi: mpt3sas: Fix timeouts observed while reenabling IRQ
+    - nvme: introduce nvme_sync_io_queues
+    - nvme-rdma: avoid race between time out and tear down
+    - nvme-tcp: avoid race between time out and tear down
+    - nvme-rdma: avoid repeated request completion
+    - nvme-tcp: avoid repeated request completion
+    - iommu/amd: Increase interrupt remapping table limit to 512 entries
+    - s390/smp: move rcu_cpu_starting() earlier
+    - vfio: platform: fix reference leak in vfio_platform_open
+    - vfio/pci: Bypass IGD init in case of -ENODEV
+    - i2c: mediatek: move dma reset before i2c reset
+    - amd/amdgpu: Disable VCN DPG mode for Picasso
+    - selftests: proc: fix warning: _GNU_SOURCE redefined
+    - riscv: Set text_offset correctly for M-Mode
+    - i2c: sh_mobile: implement atomic transfers
+    - tpm_tis: Disable interrupts on ThinkPad T490s
+    - spi: bcm2835: remove use of uninitialized gpio flags variable
+    - tick/common: Touch watchdog in tick_unfreeze() on all CPUs
+    - mfd: sprd: Add wakeup capability for PMIC IRQ
+    - pinctrl: intel: Set default bias in case no particular value given
+    - ARM: 9019/1: kprobes: Avoid fortify_panic() when copying optprobe template
+    - bpf: Don't rely on GCC __attribute__((optimize)) to disable GCSE
+    - pinctrl: aspeed: Fix GPI only function problem.
+    - net/mlx5: Fix deletion of duplicate rules
+    - SUNRPC: Fix general protection fault in trace_rpc_xdr_overflow()
+    - bpf: Zero-fill re-used per-cpu map element
+    - nbd: fix a block_device refcount leak in nbd_release
+    - igc: Fix returning wrong statistics
+    - xfs: fix flags argument to rmap lookup when converting shared file rmaps
+    - xfs: set the unwritten bit in rmap lookup flags in xchk_bmap_get_rmapextents
+    - xfs: fix rmap key and record comparison functions
+    - xfs: fix brainos in the refcount scrubber's rmap fragment processor
+    - lan743x: fix "BUG: invalid wait context" when setting rx mode
+    - xfs: fix a missing unlock on error in xfs_fs_map_blocks
+    - of/address: Fix of_node memory leak in of_dma_is_coherent
+    - cosa: Add missing kfree in error path of cosa_write
+    - vrf: Fix fast path output packet handling with async Netfilter rules
+    - perf: Fix get_recursion_context()
+    - erofs: derive atime instead of leaving it empty
+    - ext4: correctly report "not supported" for {usr,grp}jquota when
+      !CONFIG_QUOTA
+    - ext4: unlock xattr_sem properly in ext4_inline_data_truncate()
+    - btrfs: ref-verify: fix memory leak in btrfs_ref_tree_mod
+    - btrfs: fix min reserved size calculation in merge_reloc_root
+    - btrfs: dev-replace: fail mount if we don't have replace item with target
+      device
+    - KVM: arm64: Don't hide ID registers from userspace
+    - thunderbolt: Fix memory leak if ida_simple_get() fails in
+      enumerate_services()
+    - thunderbolt: Add the missed ida_simple_remove() in ring_request_msix()
+    - uio: Fix use-after-free in uio_unregister_device()
+    - usb: cdc-acm: Add DISABLE_ECHO for Renesas USB Download mode
+    - xhci: hisilicon: fix refercence leak in xhci_histb_probe
+    - virtio: virtio_console: fix DMA memory allocation for rproc serial
+    - mei: protect mei_cl_mtu from null dereference
+    - futex: Don't enable IRQs unconditionally in put_pi_state()
+    - jbd2: fix up sparse warnings in checkpoint code
+    - mm/slub: fix panic in slab_alloc_node()
+    - Revert "kernel/reboot.c: convert simple_strtoul to kstrtoint"
+    - reboot: fix overflow parsing reboot cpu number
+    - ocfs2: initialize ip_next_orphan
+    - btrfs: fix potential overflow in cluster_pages_for_defrag on 32bit arch
+    - selinux: Fix error return code in sel_ib_pkey_sid_slow()
+    - gpio: pcie-idio-24: Fix irq mask when masking
+    - gpio: pcie-idio-24: Fix IRQ Enable Register value
+    - gpio: pcie-idio-24: Enable PEX8311 interrupts
+    - mmc: sdhci-of-esdhc: Handle pulse width detection erratum for more SoCs
+    - mmc: renesas_sdhi_core: Add missing tmio_mmc_host_free() at remove
+    - don't dump the threads that had been already exiting when zapped.
+    - drm/gma500: Fix out-of-bounds access to struct drm_device.vblank[]
+    - pinctrl: amd: use higher precision for 512 RtcClk
+    - pinctrl: amd: fix incorrect way to disable debounce filter
+    - swiotlb: fix "x86: Don't panic if can not alloc buffer for swiotlb"
+    - IPv6: Set SIT tunnel hard_header_len to zero
+    - net/af_iucv: fix null pointer dereference on shutdown
+    - net: udp: fix UDP header access on Fast/frag0 UDP GRO
+    - net: Update window_clamp if SOCK_RCVBUF is set
+    - net/x25: Fix null-ptr-deref in x25_connect
+    - tipc: fix memory leak in tipc_topsrv_start()
+    - r8169: fix potential skb double free in an error path
+    - drm/i915: Correctly set SFC capability for video engines
+    - powerpc/603: Always fault when _PAGE_ACCESSED is not set
+    - x86/speculation: Allow IBPB to be conditionally enabled on CPUs with always-
+      on STIBP
+    - perf scripting python: Avoid declaring function pointers with a visibility
+      attribute
+    - net: sch_generic: fix the missing new qdisc assignment bug
+    - Convert trailing spaces and periods in path components
+    - Linux 5.4.78
+  * Focal update: v5.4.77 upstream stable release (LP: #1905614)
+    - Linux 5.4.77
+  * Focal update: v5.4.76 upstream stable release (LP: #1905612)
+    - drm/i915: Break up error capture compression loops with cond_resched()
+    - drm/i915/gt: Delay execlist processing for tgl
+    - drm/i915: Drop runtime-pm assert from vgpu io accessors
+    - ASoC: Intel: Skylake: Add alternative topology binary name
+    - update dkms package versions
+    - linkage: Introduce new macros for assembler symbols
+    - arm64: asm: Add new-style position independent function annotations
+    - arm64: lib: Use modern annotations for assembly functions
+    - arm64: Change .weak to SYM_FUNC_START_WEAK_PI for arch/arm64/lib/mem*.S
+    - tipc: fix use-after-free in tipc_bcast_get_mode
+    - ptrace: fix task_join_group_stop() for the case when current is traced
+    - cadence: force nonlinear buffers to be cloned
+    - chelsio/chtls: fix memory leaks caused by a race
+    - chelsio/chtls: fix always leaking ctrl_skb
+    - gianfar: Replace skb_realloc_headroom with skb_cow_head for PTP
+    - gianfar: Account for Tx PTP timestamp in the skb headroom
+    - ionic: check port ptr before use
+    - ip_tunnel: fix over-mtu packet send fail without TUNNEL_DONT_FRAGMENT flags
+    - net: usb: qmi_wwan: add Telit LE910Cx 0x1230 composition
+    - powerpc/vnic: Extend "failover pending" window
+    - sctp: Fix COMM_LOST/CANT_STR_ASSOC err reporting on big-endian platforms
+    - sfp: Fix error handing in sfp_probe()
+    - Fonts: Replace discarded const qualifier
+    - ALSA: hda/realtek - Fixed HP headset Mic can't be detected
+    - ALSA: hda/realtek - Enable headphone for ASUS TM420
+    - ALSA: usb-audio: Add implicit feedback quirk for Zoom UAC-2
+    - ALSA: usb-audio: add usb vendor id as DSD-capable for Khadas devices
+    - ALSA: usb-audio: Add implicit feedback quirk for Qu-16
+    - ALSA: usb-audio: Add implicit feedback quirk for MODX
+    - mm: mempolicy: fix potential pte_unmap_unlock pte error
+    - lib/crc32test: remove extra local_irq_disable/enable
+    - kthread_worker: prevent queuing delayed work from timer_fn when it is being
+      canceled
+    - mm: always have io_remap_pfn_range() set pgprot_decrypted()
+    - gfs2: Wake up when sd_glock_disposal becomes zero
+    - ring-buffer: Fix recursion protection transitions between interrupt context
+    - mtd: spi-nor: Don't copy self-pointing struct around
+    - ftrace: Fix recursion check for NMI test
+    - ftrace: Handle tracing when switching between context
+    - regulator: defer probe when trying to get voltage from unresolved supply
+    - spi: bcm2835: fix gpio cs level inversion
+    - tracing: Fix out of bounds write in get_trace_buf
+    - futex: Handle transient "ownerless" rtmutex state correctly
+    - ARM: dts: sun4i-a10: fix cpu_alert temperature
+    - arm64: dts: meson: add missing g12 rng clock
+    - x86/kexec: Use up-to-dated screen_info copy to fill boot params
+    - of: Fix reserved-memory overlap detection
+    - drm/sun4i: frontend: Rework a bit the phase data
+    - drm/sun4i: frontend: Reuse the ch0 phase for RGB formats
+    - drm/sun4i: frontend: Fix the scaler phase on A33
+    - blk-cgroup: Fix memleak on error path
+    - blk-cgroup: Pre-allocate tree node on blkg_conf_prep
+    - scsi: core: Don't start concurrent async scan on same host
+    - drm/amdgpu: add DID for navi10 blockchain SKU
+    - scsi: ibmvscsi: Fix potential race after loss of transport
+    - vsock: use ns_capable_noaudit() on socket create
+    - nvme-rdma: handle unexpected nvme completion data length
+    - nvmet: fix a NULL pointer dereference when tracing the flush command
+    - drm/vc4: drv: Add error handding for bind
+    - ACPI: NFIT: Fix comparison to '-ENXIO'
+    - usb: cdns3: gadget: suspicious implicit sign extension
+    - drm/nouveau/nouveau: fix the start/end range for migration
+    - drm/nouveau/gem: fix "refcount_t: underflow; use-after-free"
+    - arm64/smp: Move rcu_cpu_starting() earlier
+    - vt: Disable KD_FONT_OP_COPY
+    - fork: fix copy_process(CLONE_PARENT) race with the exiting ->real_parent
+    - s390/pkey: fix paes selftest failure with paes and pkey static build
+    - serial: 8250_mtk: Fix uart_get_baud_rate warning
+    - serial: txx9: add missing platform_driver_unregister() on error in
+      serial_txx9_init
+    - USB: serial: cyberjack: fix write-URB completion race
+    - USB: serial: option: add Quectel EC200T module support
+    - USB: serial: option: add LE910Cx compositions 0x1203, 0x1230, 0x1231
+    - USB: serial: option: add Telit FN980 composition 0x1055
+    - tty: serial: fsl_lpuart: add LS1028A support
+    - tty: serial: fsl_lpuart: LS1021A has a FIFO size of 16 words, like LS1028A
+    - usb: dwc3: ep0: Fix delay status handling
+    - USB: Add NO_LPM quirk for Kingston flash drive
+    - usb: mtu3: fix panic in mtu3_gadget_stop()
+    - drm/panfrost: Fix a deadlock between the shrinker and madvise path
+    - ARC: stack unwinding: avoid indefinite looping
+    - PM: runtime: Drop runtime PM references to supplier on link removal
+    - PM: runtime: Drop pm_runtime_clean_up_links()
+    - PM: runtime: Resume the device earlier in __device_release_driver()
+    - xfs: flush for older, xfs specific ioctls
+    - perf/core: Fix a memory leak in perf_event_parse_addr_filter()
+    - arm64: dts: marvell: espressobin: Add ethernet switch aliases
+    - Linux 5.4.76
+  * s390: dbginfo.sh triggers kernel panic, reading from
+    /sys/kernel/mm/page_idle/bitmap (LP: #1904884)
+    - mm/page_idle.c: skip offline pages
+  * Ask 8821C Bluetooth controller to drop old firmware (LP: #1904221)
+    - Bluetooth: btrtl: Ask 8821C to drop old firmware
+    - Bluetooth: btrtl: fix incorrect skb allocation failure check
+  * Use ACPI S5 for reboot (LP: #1904225)
+    - PM: ACPI: reboot: Use S5 for reboot
+  * Focal update: v5.4.75 upstream stable release (LP: #1904450)
+    - xen/events: avoid removing an event channel while handling it
+    - xen/events: add a proper barrier to 2-level uevent unmasking
+    - xen/events: fix race in evtchn_fifo_unmask()
+    - xen/events: add a new "late EOI" evtchn framework
+    - xen/blkback: use lateeoi irq binding
+    - xen/netback: use lateeoi irq binding
+    - xen/scsiback: use lateeoi irq binding
+    - xen/pvcallsback: use lateeoi irq binding
+    - xen/pciback: use lateeoi irq binding
+    - xen/events: switch user event channels to lateeoi model
+    - xen/events: use a common cpu hotplug hook for event channels
+    - xen/events: defer eoi in case of excessive number of events
+    - xen/events: block rogue events for some time
+    - firmware: arm_scmi: Fix ARCH_COLD_RESET
+    - firmware: arm_scmi: Add missing Rx size re-initialisation
+    - x86/unwind/orc: Fix inactive tasks with stack pointer in %sp on GCC 10
+      compiled kernels
+    - mlxsw: core: Fix use-after-free in mlxsw_emad_trans_finish()
+    - RDMA/qedr: Fix memory leak in iWARP CM
+    - ata: sata_nv: Fix retrieving of active qcs
+    - futex: Fix incorrect should_fail_futex() handling
+    - powerpc/powernv/smp: Fix spurious DBG() warning
+    - [Config] update config for ARCH_WANT_IRQS_OFF_ACTIVATE_MM
+    - mm: fix exec activate_mm vs TLB shootdown and lazy tlb switching race
+    - powerpc: select ARCH_WANT_IRQS_OFF_ACTIVATE_MM
+    - sparc64: remove mm_cpumask clearing to fix kthread_use_mm race
+    - f2fs: add trace exit in exception path
+    - f2fs: fix uninit-value in f2fs_lookup
+    - f2fs: fix to check segment boundary during SIT page readahead
+    - s390/startup: avoid save_area_sync overflow
+    - um: change sigio_spinlock to a mutex
+    - f2fs: handle errors of f2fs_get_meta_page_nofail
+    - ARM: 8997/2: hw_breakpoint: Handle inexact watchpoint addresses
+    - NFS4: Fix oops when copy_file_range is attempted with NFS4.0 source
+    - power: supply: bq27xxx: report "not charging" on all types
+    - xfs: fix realtime bitmap/summary file truncation when growing rt volume
+    - video: fbdev: pvr2fb: initialize variables
+    - ath10k: start recovery process when payload length exceeds max htc length
+      for sdio
+    - ath10k: fix VHT NSS calculation when STBC is enabled
+    - drm/brige/megachips: Add checking if ge_b850v3_lvds_init() is working
+      correctly
+    - selftests/x86/fsgsbase: Reap a forgotten child
+    - media: videodev2.h: RGB BT2020 and HSV are always full range
+    - media: platform: Improve queue set up flow for bug fixing
+    - usb: typec: tcpm: During PR_SWAP, source caps should be sent only after
+      tSwapSourceStart
+    - media: tw5864: check status of tw5864_frameinterval_get
+    - media: imx274: fix frame interval handling
+    - mmc: via-sdmmc: Fix data race bug
+    - drm/bridge/synopsys: dsi: add support for non-continuous HS clock
+    - arm64: topology: Stop using MPIDR for topology information
+    - printk: reduce LOG_BUF_SHIFT range for H8300
+    - ia64: kprobes: Use generic kretprobe trampoline handler
+    - kgdb: Make "kgdbcon" work properly with "kgdb_earlycon"
+    - bpf: Permit map_ptr arithmetic with opcode add and offset 0
+    - media: uvcvideo: Fix dereference of out-of-bound list iterator
+    - selftests/bpf: Define string const as global for test_sysctl_prog.c
+    - samples/bpf: Fix possible deadlock in xdpsock
+    - riscv: Define AT_VECTOR_SIZE_ARCH for ARCH_DLINFO
+    - cpufreq: sti-cpufreq: add stih418 support
+    - USB: adutux: fix debugging
+    - uio: free uio id after uio file node is freed
+    - usb: xhci: omit duplicate actions when suspending a runtime suspended host.
+    - SUNRPC: Mitigate cond_resched() in xprt_transmit()
+    - arm64/mm: return cpu_all_mask when node is NUMA_NO_NODE
+    - can: flexcan: disable clocks during stop mode
+    - xfs: don't free rt blocks when we're doing a REMAP bunmapi call
+    - ACPI: Add out of bounds and numa_off protections to pxm_to_node()
+    - brcmfmac: Fix warning message after dongle setup failed
+    - drivers/net/wan/hdlc_fr: Correctly handle special skb->protocol values
+    - bus/fsl_mc: Do not rely on caller to provide non NULL mc_io
+    - ACPI: HMAT: Fix handling of changes from ACPI 6.2 to ACPI 6.3
+    - power: supply: test_power: add missing newlines when printing parameters by
+      sysfs
+    - drm/amd/display: HDMI remote sink need mode validation for Linux
+    - ARC: [dts] fix the errors detected by dtbs_check
+    - btrfs: fix replace of seed device
+    - md/bitmap: md_bitmap_get_counter returns wrong blocks
+    - bnxt_en: Log unknown link speed appropriately.
+    - rpmsg: glink: Use complete_all for open states
+    - clk: ti: clockdomain: fix static checker warning
+    - net: 9p: initialize sun_server.sun_path to have addr's value only when addr
+      is valid
+    - drivers: watchdog: rdc321x_wdt: Fix race condition bugs
+    - ext4: Detect already used quota file early
+    - KVM: PPC: Book3S HV: Do not allocate HPT for a nested guest
+    - gfs2: use-after-free in sysfs deregistration
+    - gfs2: add validation checks for size of superblock
+    - cifs: handle -EINTR in cifs_setattr
+    - arm64: dts: renesas: ulcb: add full-pwr-cycle-in-suspend into eMMC nodes
+    - ARM: dts: omap4: Fix sgx clock rate for 4430
+    - memory: emif: Remove bogus debugfs error handling
+    - ARM: dts: s5pv210: remove DMA controller bus node name to fix dtschema
+      warnings
+    - ARM: dts: s5pv210: move fixed clocks under root node
+    - ARM: dts: s5pv210: move PMU node out of clock controller
+    - ARM: dts: s5pv210: remove dedicated 'audio-subsystem' node
+    - nbd: make the config put is called before the notifying the waiter
+    - sgl_alloc_order: fix memory leak
+    - nvme-rdma: fix crash when connect rejected
+    - md/raid5: fix oops during stripe resizing
+    - mmc: sdhci: Add LTR support for some Intel BYT based controllers
+    - mmc: sdhci-acpi: AMDI0040: Set SDHCI_QUIRK2_PRESET_VALUE_BROKEN
+    - seccomp: Make duplicate listener detection non-racy
+    - selftests/x86/fsgsbase: Test PTRACE_PEEKUSER for GSBASE with invalid LDT GS
+    - perf/x86/intel: Fix Ice Lake event constraint table
+    - perf/x86/amd/ibs: Don't include randomized bits in get_ibs_op_count()
+    - perf/x86/amd/ibs: Fix raw sample data accumulation
+    - spi: sprd: Release DMA channel also on probe deferral
+    - extcon: ptn5150: Fix usage of atomic GPIO with sleeping GPIO chips
+    - leds: bcm6328, bcm6358: use devres LED registering function
+    - media: uvcvideo: Fix uvc_ctrl_fixup_xu_info() not having any effect
+    - fs: Don't invalidate page buffers in block_write_full_page()
+    - NFS: fix nfs_path in case of a rename retry
+    - ACPI: button: fix handling lid state changes when input device closed
+    - ACPI / extlog: Check for RDMSR failure
+    - ACPI: debug: don't allow debugging when ACPI is disabled
+    - PCI/ACPI: Whitelist hotplug ports for D3 if power managed by ACPI
+    - ACPI: EC: PM: Flush EC work unconditionally after wakeup
+    - ACPI: EC: PM: Drop ec_no_wakeup check from acpi_ec_dispatch_gpe()
+    - acpi-cpufreq: Honor _PSD table setting on new AMD CPUs
+    - w1: mxc_w1: Fix timeout resolution problem leading to bus error
+    - scsi: mptfusion: Fix null pointer dereferences in mptscsih_remove()
+    - scsi: qla2xxx: Fix crash on session cleanup with unload
+    - PM: runtime: Remove link state checks in rpm_get/put_supplier()
+    - btrfs: qgroup: fix wrong qgroup metadata reserve for delayed inode
+    - btrfs: improve device scanning messages
+    - btrfs: reschedule if necessary when logging directory items
+    - btrfs: send, orphanize first all conflicting inodes when processing
+      references
+    - btrfs: send, recompute reference path after orphanization of a directory
+    - btrfs: use kvzalloc() to allocate clone_roots in btrfs_ioctl_send()
+    - btrfs: tree-checker: fix false alert caused by legacy btrfs root item
+    - btrfs: cleanup cow block on error
+    - btrfs: tree-checker: validate number of chunk stripes and parity
+    - btrfs: fix use-after-free on readahead extent after failure to create it
+    - btrfs: fix readahead hang and use-after-free after removing a device
+    - Revert "UBUNTU: SAUCE: xhci: workaround for S3 issue on AMD SNPS 3.0 xHC"
+    - usb: xhci: Workaround for S3 issue on AMD SNPS 3.0 xHC
+    - usb: dwc3: pci: Allow Elkhart Lake to utilize DSM method for PM
+      functionality
+    - usb: dwc3: ep0: Fix ZLP for OUT ep0 requests
+    - usb: dwc3: gadget: Check MPS of the request length
+    - usb: dwc3: core: add phy cleanup for probe error handling
+    - usb: dwc3: core: don't trigger runtime pm when remove driver
+    - usb: dwc3: gadget: Resume pending requests after CLEAR_STALL
+    - usb: dwc3: gadget: END_TRANSFER before CLEAR_STALL command
+    - usb: cdc-acm: fix cooldown mechanism
+    - usb: typec: tcpm: reset hard_reset_count for any disconnect
+    - usb: host: fsl-mph-dr-of: check return of dma_set_mask()
+    - drm/i915: Force VT'd workarounds when running as a guest OS
+    - vt: keyboard, simplify vt_kdgkbsent
+    - vt: keyboard, extend func_buf_lock to readers
+    - HID: wacom: Avoid entering wacom_wac_pen_report for pad / battery
+    - udf: Fix memory leak when mounting
+    - dmaengine: dma-jz4780: Fix race in jz4780_dma_tx_status
+    - iio:light:si1145: Fix timestamp alignment and prevent data leak.
+    - iio: adc: gyroadc: fix leak of device node iterator
+    - iio:adc:ti-adc0832 Fix alignment issue with timestamp
+    - iio:adc:ti-adc12138 Fix alignment issue with timestamp
+    - iio:gyro:itg3200: Fix timestamp alignment and prevent data leak.
+    - powerpc/drmem: Make lmb_size 64 bit
+    - MIPS: DEC: Restore bootmem reservation for firmware working memory area
+    - s390/stp: add locking to sysfs functions
+    - [Config] update config for PPC_RTAS_FILTER
+    - powerpc/rtas: Restrict RTAS requests from userspace
+    - powerpc: Warn about use of smt_snooze_delay
+    - powerpc/memhotplug: Make lmb size 64bit
+    - powerpc/powernv/elog: Fix race while processing OPAL error log event.
+    - powerpc/powermac: Fix low_sleep_handler with KUAP and KUEP
+    - NFSv4: Wait for stateid updates after CLOSE/OPEN_DOWNGRADE
+    - NFSv4.2: support EXCHGID4_FLAG_SUPP_FENCE_OPS 4.2 EXCHANGE_ID flag
+    - NFSD: Add missing NFSv2 .pc_func methods
+    - ubifs: dent: Fix some potential memory leaks while iterating entries
+    - ubifs: xattr: Fix some potential memory leaks while iterating entries
+    - ubifs: journal: Make sure to not dirty twice for auth nodes
+    - ubifs: Fix a memleak after dumping authentication mount options
+    - ubifs: Don't parse authentication mount options in remount process
+    - ubifs: mount_ubifs: Release authentication resource in error handling path
+    - perf python scripting: Fix printable strings in python3 scripts
+    - ARC: perf: redo the pct irq missing in device-tree handling
+    - ubi: check kthread_should_stop() after the setting of task state
+    - ia64: fix build error with !COREDUMP
+    - rtc: rx8010: don't modify the global rtc ops
+    - i2c: imx: Fix external abort on interrupt in exit paths
+    - drm/amdgpu: don't map BO in reserved region
+    - drm/amd/display: Increase timeout for DP Disable
+    - drm/amdgpu: correct the gpu reset handling for job != NULL case
+    - drm/amdkfd: Use same SQ prefetch setting as amdgpu
+    - drm/amd/display: Avoid MST manager resource leak.
+    - drm/amdgpu: increase the reserved VM size to 2MB
+    - drm/amd/display: Don't invoke kgdb_breakpoint() unconditionally
+    - drm/amd/display: Fix kernel panic by dal_gpio_open() error
+    - ceph: promote to unsigned long long before shifting
+    - libceph: clear con->out_msg on Policy::stateful_server faults
+    - 9P: Cast to loff_t before multiplying
+    - ring-buffer: Return 0 on success from ring_buffer_resize()
+    - vringh: fix __vringh_iov() when riov and wiov are different
+    - ext4: fix leaking sysfs kobject after failed mount
+    - ext4: fix error handling code in add_new_gdb
+    - ext4: fix invalid inode checksum
+    - drm/ttm: fix eviction valuable range check.
+    - mmc: sdhci-of-esdhc: set timeout to max before tuning
+    - mmc: sdhci: Use Auto CMD Auto Select only when v4_mode is true
+    - drm/amd/pm: increase mclk switch threshold to 200 us
+    - tty: make FONTX ioctl use the tty pointer they were actually passed
+    - arm64: berlin: Select DW_APB_TIMER_OF
+    - [Config] update annotations for DW_APB_TIMER
+    - cachefiles: Handle readpage error correctly
+    - hil/parisc: Disable HIL driver when it gets stuck
+    - arm: dts: mt7623: add missing pause for switchport
+    - ARM: samsung: fix PM debug build with DEBUG_LL but !MMU
+    - ARM: s3c24xx: fix missing system reset
+    - device property: Keep secondary firmware node secondary by type
+    - device property: Don't clear secondary pointer for shared primary firmware
+      node
+    - KVM: arm64: Fix AArch32 handling of DBGD{CCINT,SCRext} and DBGVCR
+    - staging: fieldbus: anybuss: jump to correct label in an error path
+    - staging: comedi: cb_pcidas: Allow 2-channel commands for AO subdevice
+    - staging: octeon: repair "fixed-link" support
+    - staging: octeon: Drop on uncorrectable alignment or FCS error
+    - Linux 5.4.75
+  * [HP 635] Radeon 6310 brightness control does not work (LP: #1894667) //
+    Focal update: v5.4.75 upstream stable release (LP: #1904450)
+    - ACPI: video: use ACPI backlight for HP 635 Notebook
+  * Focal update: v5.4.74 upstream stable release (LP: #1904445)
+    - netfilter: nftables_offload: KASAN slab-out-of-bounds Read in
+      nft_flow_rule_create
+    - socket: don't clear SOCK_TSTAMP_NEW when SO_TIMESTAMPNS is disabled
+    - objtool: Support Clang non-section symbols in ORC generation
+    - scripts/setlocalversion: make git describe output more reliable
+    - arm64: Run ARCH_WORKAROUND_1 enabling code on all CPUs
+    - arm64: Run ARCH_WORKAROUND_2 enabling code on all CPUs
+    - arm64: link with -z norelro regardless of CONFIG_RELOCATABLE
+    - x86/PCI: Fix intel_mid_pci.c build error when ACPI is not enabled
+    - bnxt_en: Check abort error state in bnxt_open_nic().
+    - bnxt_en: Send HWRM_FUNC_RESET fw command unconditionally.
+    - chelsio/chtls: fix deadlock issue
+    - chelsio/chtls: fix memory leaks in CPL handlers
+    - chelsio/chtls: fix tls record info to user
+    - cxgb4: set up filter action after rewrites
+    - gtp: fix an use-before-init in gtp_newlink()
+    - ibmvnic: fix ibmvnic_set_mac
+    - mlxsw: core: Fix memory leak on module removal
+    - netem: fix zero division in tabledist
+    - net/sched: act_mpls: Add softdep on mpls_gso.ko
+    - r8169: fix issue with forced threading in combination with shared interrupts
+    - ravb: Fix bit fields checking in ravb_hwtstamp_get()
+    - tcp: Prevent low rmem stalls with SO_RCVLOWAT.
+    - tipc: fix memory leak caused by tipc_buf_append()
+    - net: hns3: Clear the CMDQ registers before unmapping BAR region
+    - bnxt_en: Re-write PCI BARs after PCI fatal error.
+    - bnxt_en: Fix regression in workqueue cleanup logic in bnxt_remove_one().
+    - bnxt_en: Invoke cancel_delayed_work_sync() for PFs also.
+    - erofs: avoid duplicated permission check for "trusted." xattrs
+    - arch/x86/amd/ibs: Fix re-arming IBS Fetch
+    - x86/xen: disable Firmware First mode for correctable memory errors
+    - ata: ahci: mvebu: Make SATA PHY optional for Armada 3720
+    - fuse: fix page dereference after free
+    - bpf: Fix comment for helper bpf_current_task_under_cgroup()
+    - evm: Check size of security.evm before using it
+    - p54: avoid accessing the data mapped to streaming DMA
+    - cxl: Rework error message for incompatible slots
+    - RDMA/addr: Fix race with netevent_callback()/rdma_addr_cancel()
+    - mtd: lpddr: Fix bad logic in print_drs_error
+    - serial: qcom_geni_serial: To correct QUP Version detection logic
+    - serial: pl011: Fix lockdep splat when handling magic-sysrq interrupt
+    - PM: runtime: Fix timer_expires data type on 32-bit arches
+    - ata: sata_rcar: Fix DMA boundary mask
+    - xen/gntdev.c: Mark pages as dirty
+    - crypto: x86/crc32c - fix building with clang ias
+    - openrisc: Fix issue with get_user for 64-bit values
+    - misc: rtsx: do not setting OC_POWER_DOWN reg in rtsx_pci_init_ocp()
+    - phy: marvell: comphy: Convert internal SMCC firmware return codes to errno
+    - Linux 5.4.74
+  * Bionic: btrfs: kernel BUG at /build/linux-
+    eTBZpZ/linux-4.15.0/fs/btrfs/ctree.c:3233! (LP: #1902254)
+    - btrfs: tree-checker: fix incorrect printk format
+  * NULL pointer dereference when configuring multi-function with devfn != 0
+    before devfn == 0 (LP: #1903682)
+    - s390/pci: fix hot-plug of PCI function missing bus
+
+  [ Ubuntu: 5.4.0-58.64 ]
+
+  * focal/linux: 5.4.0-58.64 -proposed tracker (LP: #1907390)
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+  * raid10: discard leads to corrupted file system (LP: #1907262)
+    - Revert "dm raid: remove unnecessary discard limits for raid10"
+    - Revert "dm raid: fix discard limits for raid1 and raid10"
+    - Revert "md/raid10: improve discard request for far layout"
+    - Revert "md/raid10: improve raid10 discard request"
+    - Revert "md/raid10: pull codes that wait for blocked dev into one function"
+    - Revert "md/raid10: extend r10bio devs to raid disks"
+    - Revert "md: add md_submit_discard_bio() for submitting discard bio"
+
+  [ Ubuntu: 5.4.0-56.62 ]
+
+  * focal/linux: 5.4.0-56.62 -proposed tracker (LP: #1905300)
+  * CVE-2020-4788
+    - selftests/powerpc: rfi_flush: disable entry flush if present
+    - powerpc/64s: flush L1D on kernel entry
+    - powerpc/64s: flush L1D after user accesses
+    - selftests/powerpc: entry flush test
+
+  [ Ubuntu: 5.4.0-55.61 ]
+
+  * focal/linux: 5.4.0-55.61 -proposed tracker (LP: #1903175)
+  * Update kernel packaging to support forward porting kernels (LP: #1902957)
+    - [Debian] Update for leader included in BACKPORT_SUFFIX
+  * Avoid double newline when running insertchanges (LP: #1903293)
+    - [Packaging] insertchanges: avoid double newline
+  * EFI: Fails when BootCurrent entry does not exist (LP: #1899993)
+    - efivarfs: Replace invalid slashes with exclamation marks in dentries.
+  * CVE-2020-14351
+    - perf/core: Fix race in the perf_mmap_close() function
+  * raid10: Block discard is very slow, causing severe delays for mkfs and
+    fstrim operations (LP: #1896578)
+    - md: add md_submit_discard_bio() for submitting discard bio
+    - md/raid10: extend r10bio devs to raid disks
+    - md/raid10: pull codes that wait for blocked dev into one function
+    - md/raid10: improve raid10 discard request
+    - md/raid10: improve discard request for far layout
+    - dm raid: fix discard limits for raid1 and raid10
+    - dm raid: remove unnecessary discard limits for raid10
+  * Bionic: btrfs: kernel BUG at /build/linux-
+    eTBZpZ/linux-4.15.0/fs/btrfs/ctree.c:3233! (LP: #1902254)
+    - btrfs: drop unnecessary offset_in_page in extent buffer helpers
+    - btrfs: extent_io: do extra check for extent buffer read write functions
+    - btrfs: extent-tree: kill BUG_ON() in __btrfs_free_extent()
+    - btrfs: extent-tree: kill the BUG_ON() in insert_inline_extent_backref()
+    - btrfs: ctree: check key order before merging tree blocks
+  * Ethernet no link lights after reboot (Intel i225-v 2.5G) (LP: #1902578)
+    - igc: Add PHY power management control
+  * Undetected Data corruption in MPI workloads that use VSX for reductions on
+    POWER9 DD2.1 systems (LP: #1902694)
+    - powerpc: Fix undetected data corruption with P9N DD2.1 VSX CI load emulation
+    - selftests/powerpc: Make alignment handler test P9N DD2.1 vector CI load
+      workaround
+  * [20.04 FEAT] Support/enhancement of NVMe IPL (LP: #1902179)
+    - s390: nvme ipl
+    - s390: nvme reipl
+    - s390/ipl: support NVMe IPL kernel parameters
+  * uvcvideo: add mapping for HEVC payloads (LP: #1895803)
+    - media: uvcvideo: Add mapping for HEVC payloads
+  * Focal update: v5.4.73 upstream stable release (LP: #1902115)
+    - ibmveth: Switch order of ibmveth_helper calls.
+    - ibmveth: Identify ingress large send packets.
+    - ipv4: Restore flowi4_oif update before call to xfrm_lookup_route
+    - mlx4: handle non-napi callers to napi_poll
+    - net: fec: Fix phy_device lookup for phy_reset_after_clk_enable()
+    - net: fec: Fix PHY init after phy_reset_after_clk_enable()
+    - net: fix pos incrementment in ipv6_route_seq_next
+    - net/smc: fix valid DMBE buffer sizes
+    - net/tls: sendfile fails with ktls offload
+    - net: usb: qmi_wwan: add Cellient MPL200 card
+    - tipc: fix the skb_unshare() in tipc_buf_append()
+    - socket: fix option SO_TIMESTAMPING_NEW
+    - can: m_can_platform: don't call m_can_class_suspend in runtime suspend
+    - can: j1935: j1939_tp_tx_dat_new(): fix missing initialization of skbcnt
+    - net: j1939: j1939_session_fresh_new(): fix missing initialization of skbcnt
+    - net/ipv4: always honour route mtu during forwarding
+    - net_sched: remove a redundant goto chain check
+    - r8169: fix data corruption issue on RTL8402
+    - cxgb4: handle 4-tuple PEDIT to NAT mode translation
+    - binder: fix UAF when releasing todo list
+    - ALSA: bebob: potential info leak in hwdep_read()
+    - ALSA: hda/hdmi: fix incorrect locking in hdmi_pcm_close
+    - nvme-pci: disable the write zeros command for Intel 600P/P3100
+    - chelsio/chtls: fix socket lock
+    - chelsio/chtls: correct netdevice for vlan interface
+    - chelsio/chtls: correct function return and return type
+    - ibmvnic: save changed mac address to adapter->mac_addr
+    - net: ftgmac100: Fix Aspeed ast2600 TX hang issue
+    - net: hdlc: In hdlc_rcv, check to make sure dev is an HDLC device
+    - net: hdlc_raw_eth: Clear the IFF_TX_SKB_SHARING flag after calling
+      ether_setup
+    - net: Properly typecast int values to set sk_max_pacing_rate
+    - net/sched: act_tunnel_key: fix OOB write in case of IPv6 ERSPAN tunnels
+    - nexthop: Fix performance regression in nexthop deletion
+    - nfc: Ensure presence of NFC_ATTR_FIRMWARE_NAME attribute in
+      nfc_genl_fw_download()
+    - r8169: fix operation under forced interrupt threading
+    - selftests: forwarding: Add missing 'rp_filter' configuration
+    - tcp: fix to update snd_wl1 in bulk receiver fast path
+    - icmp: randomize the global rate limiter
+    - ALSA: hda/realtek - set mic to auto detect on a HP AIO machine
+    - ALSA: hda/realtek - Add mute Led support for HP Elitebook 845 G7
+    - ALSA: hda/realtek: Enable audio jacks of ASUS D700SA with ALC887
+    - cifs: remove bogus debug code
+    - cifs: Return the error from crypt_message when enc/dec key not found.
+    - SMB3: Resolve data corruption of TCP server info fields
+    - KVM: nVMX: Reset the segment cache when stuffing guest segs
+    - KVM: nVMX: Reload vmcs01 if getting vmcs12's pages fails
+    - KVM: x86/mmu: Commit zap of remaining invalid pages when recovering lpages
+    - KVM: SVM: Initialize prev_ga_tag before use
+    - ima: Don't ignore errors from crypto_shash_update()
+    - crypto: algif_aead - Do not set MAY_BACKLOG on the async path
+    - crypto: caam/qi - add fallback for XTS with more than 8B IV
+    - EDAC/i5100: Fix error handling order in i5100_init_one()
+    - EDAC/aspeed: Fix handling of platform_get_irq() error
+    - EDAC/ti: Fix handling of platform_get_irq() error
+    - perf/x86/intel/ds: Fix x86_pmu_stop warning for large PEBS
+    - x86/fpu: Allow multiple bits in clearcpuid= parameter
+    - drivers/perf: xgene_pmu: Fix uninitialized resource struct
+    - drivers/perf: thunderx2_pmu: Fix memory resource error handling
+    - sched/fair: Fix wrong cpu selecting from isolated domain
+    - perf/x86/intel/uncore: Update Ice Lake uncore units
+    - perf/x86/intel/uncore: Reduce the number of CBOX counters
+    - x86/nmi: Fix nmi_handle() duration miscalculation
+    - x86/events/amd/iommu: Fix sizeof mismatch
+    - crypto: algif_skcipher - EBUSY on aio should be an error
+    - crypto: mediatek - Fix wrong return value in mtk_desc_ring_alloc()
+    - crypto: ixp4xx - Fix the size used in a 'dma_free_coherent()' call
+    - crypto: picoxcell - Fix potential race condition bug
+    - media: tuner-simple: fix regression in simple_set_radio_freq
+    - media: Revert "media: exynos4-is: Add missed check for
+      pinctrl_lookup_state()"
+    - media: ov5640: Correct Bit Div register in clock tree diagram
+    - media: m5mols: Check function pointer in m5mols_sensor_power
+    - media: uvcvideo: Set media controller entity functions
+    - media: uvcvideo: Silence shift-out-of-bounds warning
+    - media: staging/intel-ipu3: css: Correctly reset some memory
+    - media: omap3isp: Fix memleak in isp_probe
+    - media: i2c: ov5640: Remain in power down for DVP mode unless streaming
+    - media: i2c: ov5640: Separate out mipi configuration from s_power
+    - media: i2c: ov5640: Enable data pins on poweron for DVP mode
+    - media: rcar_drif: Fix fwnode reference leak when parsing DT
+    - media: rcar_drif: Allocate v4l2_async_subdev dynamically
+    - media: rcar-csi2: Allocate v4l2_async_subdev dynamically
+    - crypto: omap-sham - fix digcnt register handling with export/import
+    - hwmon: (pmbus/max34440) Fix status register reads for MAX344{51,60,61}
+    - cypto: mediatek - fix leaks in mtk_desc_ring_alloc
+    - media: mx2_emmaprp: Fix memleak in emmaprp_probe
+    - media: tc358743: initialize variable
+    - media: tc358743: cleanup tc358743_cec_isr
+    - media: rcar-vin: Fix a reference count leak.
+    - media: rockchip/rga: Fix a reference count leak.
+    - media: platform: fcp: Fix a reference count leak.
+    - media: camss: Fix a reference count leak.
+    - media: s5p-mfc: Fix a reference count leak
+    - media: stm32-dcmi: Fix a reference count leak
+    - media: ti-vpe: Fix a missing check and reference count leak
+    - regulator: resolve supply after creating regulator
+    - pinctrl: bcm: fix kconfig dependency warning when !GPIOLIB
+    - spi: spi-s3c64xx: swap s3c64xx_spi_set_cs() and s3c64xx_enable_datapath()
+    - spi: spi-s3c64xx: Check return values
+    - blk-mq: move cancel of hctx->run_work to the front of blk_exit_queue
+    - ath10k: provide survey info as accumulated data
+    - drm/vkms: fix xrgb on compute crc
+    - Bluetooth: hci_uart: Cancel init work before unregistering
+    - drm/amd/display: Fix wrong return value in dm_update_plane_state()
+    - drm: panel: Fix bus format for OrtusTech COM43H4M85ULC panel
+    - ath6kl: prevent potential array overflow in ath6kl_add_new_sta()
+    - ath9k: Fix potential out of bounds in ath9k_htc_txcompletion_cb()
+    - ath10k: Fix the size used in a 'dma_free_coherent()' call in an error
+      handling path
+    - wcn36xx: Fix reported 802.11n rx_highest rate wcn3660/wcn3680
+    - ASoC: qcom: lpass-platform: fix memory leak
+    - ASoC: qcom: lpass-cpu: fix concurrency issue
+    - brcmfmac: check ndev pointer
+    - mwifiex: Do not use GFP_KERNEL in atomic context
+    - staging: rtl8192u: Do not use GFP_KERNEL in atomic context
+    - drm/gma500: fix error check
+    - scsi: qla4xxx: Fix an error handling path in 'qla4xxx_get_host_stats()'
+    - scsi: qla2xxx: Fix wrong return value in qlt_chk_unresolv_exchg()
+    - scsi: qla2xxx: Fix wrong return value in qla_nvme_register_hba()
+    - scsi: csiostor: Fix wrong return value in csio_hw_prep_fw()
+    - backlight: sky81452-backlight: Fix refcount imbalance on error
+    - staging: emxx_udc: Fix passing of NULL to dma_alloc_coherent()
+    - VMCI: check return value of get_user_pages_fast() for errors
+    - mm/error_inject: Fix allow_error_inject function signatures.
+    - drm: panel: Fix bpc for OrtusTech COM43H4M85ULC panel
+    - drm/crc-debugfs: Fix memleak in crc_control_write
+    - binder: Remove bogus warning on failed same-process transaction
+    - tty: serial: earlycon dependency
+    - pty: do tty_flip_buffer_push without port->lock in pty_write
+    - pwm: lpss: Fix off by one error in base_unit math in pwm_lpss_prepare()
+    - pwm: lpss: Add range limit check for the base_unit register value
+    - drivers/virt/fsl_hypervisor: Fix error handling path
+    - video: fbdev: vga16fb: fix setting of pixclock because a pass-by-value error
+    - video: fbdev: sis: fix null ptr dereference
+    - video: fbdev: radeon: Fix memleak in radeonfb_pci_register
+    - ASoC: fsl: imx-es8328: add missing put_device() call in imx_es8328_probe()
+    - HID: roccat: add bounds checking in kone_sysfs_write_settings()
+    - drm/msm: Avoid div-by-zero in dpu_crtc_atomic_check()
+    - drm/panfrost: Ensure GPU quirks are always initialised
+    - iomap: Clear page error before beginning a write
+    - pinctrl: mcp23s08: Fix mcp23x17_regmap initialiser
+    - pinctrl: mcp23s08: Fix mcp23x17 precious range
+    - net/mlx5: Don't call timecounter cyc2time directly from 1PPS flow
+    - scsi: mpt3sas: Fix sync irqs
+    - net: stmmac: use netif_tx_start|stop_all_queues() function
+    - cpufreq: armada-37xx: Add missing MODULE_DEVICE_TABLE
+    - drm: mxsfb: check framebuffer pitch
+    - coresight: etm4x: Handle unreachable sink in perf mode
+    - xhci: don't create endpoint debugfs entry before ring buffer is set.
+    - net: dsa: rtl8366: Check validity of passed VLANs
+    - net: dsa: rtl8366: Refactor VLAN/PVID init
+    - net: dsa: rtl8366: Skip PVID setting if not requested
+    - net: wilc1000: clean up resource in error path of init mon interface
+    - ASoC: tlv320aic32x4: Fix bdiv clock rate derivation
+    - net: dsa: rtl8366rb: Support all 4096 VLANs
+    - spi: omap2-mcspi: Improve performance waiting for CHSTAT
+    - ath6kl: wmi: prevent a shift wrapping bug in ath6kl_wmi_delete_pstream_cmd()
+    - dmaengine: dmatest: Check list for emptiness before access its last entry
+    - misc: mic: scif: Fix error handling path
+    - ALSA: seq: oss: Avoid mutex lock for a long-time ioctl
+    - usb: dwc2: Fix parameter type in function pointer prototype
+    - quota: clear padding in v2r1_mem2diskdqb()
+    - slimbus: core: check get_addr before removing laddr ida
+    - slimbus: core: do not enter to clock pause mode in core
+    - slimbus: qcom-ngd-ctrl: disable ngd in qmi server down callback
+    - ASoC: fsl_sai: Instantiate snd_soc_dai_driver
+    - HID: hid-input: fix stylus battery reporting
+    - nvmem: core: fix possibly memleak when use nvmem_cell_info_to_nvmem_cell()
+    - nl80211: fix OBSS PD min and max offset validation
+    - coresight: etm: perf: Fix warning caused by etm_setup_aux failure
+    - ibmvnic: set up 200GBPS speed
+    - qtnfmac: fix resource leaks on unsupported iftype error return path
+    - iio: adc: stm32-adc: fix runtime autosuspend delay when slow polling
+    - net: enic: Cure the enic api locking trainwreck
+    - mfd: sm501: Fix leaks in probe()
+    - iwlwifi: mvm: split a print to avoid a WARNING in ROC
+    - usb: gadget: f_ncm: fix ncm_bitrate for SuperSpeed and above.
+    - usb: gadget: u_ether: enable qmult on SuperSpeed Plus as well
+    - nl80211: fix non-split wiphy information
+    - usb: dwc2: Fix INTR OUT transfers in DDMA mode.
+    - scsi: target: tcmu: Fix warning: 'page' may be used uninitialized
+    - scsi: be2iscsi: Fix a theoretical leak in beiscsi_create_eqs()
+    - ipmi_si: Fix wrong return value in try_smi_init()
+    - platform/x86: mlx-platform: Remove PSU EEPROM configuration
+    - mwifiex: fix double free
+    - ipvs: clear skb->tstamp in forwarding path
+    - net: korina: fix kfree of rx/tx descriptor array
+    - netfilter: nf_log: missing vlan offload tag and proto
+    - mm/swapfile.c: fix potential memory leak in sys_swapon
+    - mm/memcg: fix device private memcg accounting
+    - mm, oom_adj: don't loop through tasks in __set_oom_adj when not necessary
+    - fs: fix NULL dereference due to data race in prepend_path()
+    - selftests/ftrace: Change synthetic event name for inter-event-combined test
+    - i3c: master add i3c_master_attach_boardinfo to preserve boardinfo
+    - IB/mlx4: Fix starvation in paravirt mux/demux
+    - IB/mlx4: Adjust delayed work when a dup is observed
+    - powerpc/pseries: Fix missing of_node_put() in rng_init()
+    - powerpc/icp-hv: Fix missing of_node_put() in success path
+    - RDMA/ucma: Fix locking for ctx->events_reported
+    - RDMA/ucma: Add missing locking around rdma_leave_multicast()
+    - mtd: lpddr: fix excessive stack usage with clang
+    - RDMA/hns: Add a check for current state before modifying QP
+    - RDMA/umem: Fix signature of stub ib_umem_find_best_pgsz()
+    - powerpc/pseries: explicitly reschedule during drmem_lmb list traversal
+    - pseries/drmem: don't cache node id in drmem_lmb struct
+    - RDMA/mlx5: Fix potential race between destroy and CQE poll
+    - mtd: mtdoops: Don't write panic data twice
+    - ARM: 9007/1: l2c: fix prefetch bits init in L2X0_AUX_CTRL using DT values
+    - arc: plat-hsdk: fix kconfig dependency warning when !RESET_CONTROLLER
+    - ida: Free allocated bitmap in error path
+    - xfs: limit entries returned when counting fsmap records
+    - xfs: fix deadlock and streamline xfs_getfsmap performance
+    - xfs: fix high key handling in the rt allocator's query_range function
+    - RDMA/umem: Fix ib_umem_find_best_pgsz() for mappings that cross a page
+      boundary
+    - RDMA/umem: Prevent small pages from being returned by
+      ib_umem_find_best_pgsz()
+    - RDMA/qedr: Fix qp structure memory leak
+    - RDMA/qedr: Fix use of uninitialized field
+    - RDMA/qedr: Fix return code if accept is called on a destroyed qp
+    - RDMA/qedr: Fix inline size returned for iWARP
+    - powerpc/book3s64/hash/4k: Support large linear mapping range with 4K
+    - powerpc/tau: Use appropriate temperature sample interval
+    - powerpc/tau: Convert from timer to workqueue
+    - powerpc/tau: Remove duplicated set_thresholds() call
+    - powerpc/tau: Check processor type before enabling TAU interrupt
+    - powerpc/tau: Disable TAU between measurements
+    - powerpc/64s/radix: Fix mm_cpumask trimming race vs kthread_use_mm
+    - RDMA/cma: Remove dead code for kernel rdmacm multicast
+    - RDMA/cma: Consolidate the destruction of a cma_multicast in one place
+    - perf intel-pt: Fix "context_switch event has no tid" error
+    - RDMA/hns: Set the unsupported wr opcode
+    - RDMA/mlx5: Disable IB_DEVICE_MEM_MGT_EXTENSIONS if IB_WR_REG_MR can't work
+    - i40iw: Add support to make destroy QP synchronous
+    - perf stat: Skip duration_time in setup_system_wide
+    - RDMA/hns: Fix the wrong value of rnr_retry when querying qp
+    - RDMA/hns: Fix missing sq_sig_type when querying QP
+    - mtd: rawnand: vf610: disable clk on error handling path in probe
+    - mtd: spinand: gigadevice: Only one dummy byte in QUADIO
+    - mtd: spinand: gigadevice: Add QE Bit
+    - kdb: Fix pager search for multi-line strings
+    - overflow: Include header file with SIZE_MAX declaration
+    - RDMA/ipoib: Set rtnl_link_ops for ipoib interfaces
+    - powerpc/perf: Exclude pmc5/6 from the irrelevant PMU group constraints
+    - powerpc/perf/hv-gpci: Fix starting index value
+    - i3c: master: Fix error return in cdns_i3c_master_probe()
+    - cpufreq: powernv: Fix frame-size-overflow in powernv_cpufreq_reboot_notifier
+    - IB/rdmavt: Fix sizeof mismatch
+    - RDMA/rxe: Fix skb lifetime in rxe_rcv_mcast_pkt()
+    - maiblox: mediatek: Fix handling of platform_get_irq() error
+    - selftests/powerpc: Fix eeh-basic.sh exit codes
+    - f2fs: wait for sysfs kobject removal before freeing f2fs_sb_info
+    - RDMA/rxe: Handle skb_clone() failure in rxe_recv.c
+    - mm/page_owner: change split_page_owner to take a count
+    - lib/crc32.c: fix trivial typo in preprocessor condition
+    - ramfs: fix nommu mmap with gaps in the page cache
+    - rapidio: fix error handling path
+    - rapidio: fix the missed put_device() for rio_mport_add_riodev
+    - mailbox: avoid timer start from callback
+    - i2c: rcar: Auto select RESET_CONTROLLER
+    - clk: meson: g12a: mark fclk_div2 as critical
+    - PCI: aardvark: Check for errors from pci_bridge_emul_init() call
+    - PCI: iproc: Set affinity mask on MSI interrupts
+    - rpmsg: smd: Fix a kobj leak in in qcom_smd_parse_edge()
+    - PCI/IOV: Mark VFs as not implementing PCI_COMMAND_MEMORY
+    - vfio/pci: Decouple PCI_COMMAND_MEMORY bit checks from is_virtfn
+    - clk: qcom: gcc-sdm660: Fix wrong parent_map
+    - clk: keystone: sci-clk: fix parsing assigned-clock data during probe
+    - pwm: img: Fix null pointer access in probe
+    - clk: rockchip: Initialize hw to error to avoid undefined behavior
+    - clk: mediatek: add UART0 clock support
+    - module: statically initialize init section freeing data
+    - clk: at91: clk-main: update key before writing AT91_CKGR_MOR
+    - clk: bcm2835: add missing release if devm_clk_hw_register fails
+    - watchdog: Fix memleak in watchdog_cdev_register
+    - watchdog: Use put_device on error
+    - watchdog: sp5100: Fix definition of EFCH_PM_DECODEEN3
+    - svcrdma: fix bounce buffers for unaligned offsets and multiple pages
+    - ext4: limit entries returned when counting fsmap records
+    - vfio/pci: Clear token on bypass registration failure
+    - vfio iommu type1: Fix memory leak in vfio_iommu_type1_pin_pages
+    - clk: imx8mq: Fix usdhc parents order
+    - SUNRPC: fix copying of multiple pages in gss_read_proxy_verf()
+    - Input: imx6ul_tsc - clean up some errors in imx6ul_tsc_resume()
+    - Input: stmfts - fix a & vs && typo
+    - Input: ep93xx_keypad - fix handling of platform_get_irq() error
+    - Input: omap4-keypad - fix handling of platform_get_irq() error
+    - Input: twl4030_keypad - fix handling of platform_get_irq() error
+    - Input: sun4i-ps2 - fix handling of platform_get_irq() error
+    - KVM: x86: emulating RDPID failure shall return #UD rather than #GP
+    - scsi: bfa: Fix error return in bfad_pci_init()
+    - netfilter: conntrack: connection timeout after re-register
+    - netfilter: ebtables: Fixes dropping of small packets in bridge nat
+    - netfilter: nf_fwd_netdev: clear timestamp in forwarding path
+    - arm64: dts: meson: vim3: correct led polarity
+    - ARM: dts: imx6sl: fix rng node
+    - ARM: at91: pm: of_node_put() after its usage
+    - ARM: s3c24xx: fix mmc gpio lookup tables
+    - ARM: dts: sun8i: r40: bananapi-m2-ultra: Fix dcdc1 regulator
+    - arm64: dts: allwinner: h5: remove Mali GPU PMU module
+    - memory: omap-gpmc: Fix a couple off by ones
+    - memory: omap-gpmc: Fix build error without CONFIG_OF
+    - memory: fsl-corenet-cf: Fix handling of platform_get_irq() error
+    - arm64: dts: imx8mq: Add missing interrupts to GPC
+    - arm64: dts: qcom: msm8916: Remove one more thermal trip point unit name
+    - arm64: dts: qcom: pm8916: Remove invalid reg size from wcd_codec
+    - arm64: dts: qcom: msm8916: Fix MDP/DSI interrupts
+    - arm64: dts: renesas: r8a77990: Fix MSIOF1 DMA channels
+    - arm64: dts: renesas: r8a774c0: Fix MSIOF1 DMA channels
+    - arm64: dts: actions: limit address range for pinctrl node
+    - ARM: dts: owl-s500: Fix incorrect PPI interrupt specifiers
+    - soc: fsl: qbman: Fix return value on success
+    - ARM: OMAP2+: Restore MPU power domain if cpu_cluster_pm_enter() fails
+    - arm64: dts: zynqmp: Remove additional compatible string for i2c IPs
+    - ARM: dts: meson8: remove two invalid interrupt lines from the GPU node
+    - lightnvm: fix out-of-bounds write to array devices->info[]
+    - powerpc/powernv/dump: Fix race while processing OPAL dump
+    - powerpc/pseries: Avoid using addr_to_pfn in real mode
+    - nvmet: fix uninitialized work for zero kato
+    - NTB: hw: amd: fix an issue about leak system resources
+    - sched/features: Fix !CONFIG_JUMP_LABEL case
+    - perf: correct SNOOPX field offset
+    - i2c: core: Restore acpi_walk_dep_device_list() getting called after
+      registering the ACPI i2c devs
+    - md/bitmap: fix memory leak of temporary bitmap
+    - block: ratelimit handle_bad_sector() message
+    - crypto: ccp - fix error handling
+    - x86/asm: Replace __force_order with a memory clobber
+    - x86/mce: Add Skylake quirk for patrol scrub reported errors
+    - media: firewire: fix memory leak
+    - media: ati_remote: sanity check for both endpoints
+    - media: st-delta: Fix reference count leak in delta_run_work
+    - media: sti: Fix reference count leaks
+    - media: exynos4-is: Fix several reference count leaks due to
+      pm_runtime_get_sync
+    - media: exynos4-is: Fix a reference count leak due to pm_runtime_get_sync
+    - media: exynos4-is: Fix a reference count leak
+    - media: vsp1: Fix runtime PM imbalance on error
+    - media: platform: s3c-camif: Fix runtime PM imbalance on error
+    - media: platform: sti: hva: Fix runtime PM imbalance on error
+    - media: bdisp: Fix runtime PM imbalance on error
+    - media: media/pci: prevent memory leak in bttv_probe
+    - x86/mce: Make mce_rdmsrl() panic on an inaccessible MSR
+    - media: uvcvideo: Ensure all probed info is returned to v4l2
+    - mmc: sdio: Check for CISTPL_VERS_1 buffer size
+    - media: saa7134: avoid a shift overflow
+    - media: venus: fixes for list corruption
+    - fs: dlm: fix configfs memory leak
+    - media: venus: core: Fix runtime PM imbalance in venus_probe
+    - ntfs: add check for mft record size in superblock
+    - ip_gre: set dev->hard_header_len and dev->needed_headroom properly
+    - mac80211: handle lack of sband->bitrates in rates
+    - PM: hibernate: remove the bogus call to get_gendisk() in software_resume()
+    - scsi: mvumi: Fix error return in mvumi_io_attach()
+    - scsi: target: core: Add CONTROL field for trace events
+    - mic: vop: copy data to kernel space then write to io memory
+    - misc: vop: add round_up(x,4) for vring_size to avoid kernel panic
+    - usb: dwc3: Add splitdisable quirk for Hisilicon Kirin Soc
+    - usb: gadget: function: printer: fix use-after-free in __lock_acquire
+    - udf: Limit sparing table size
+    - udf: Avoid accessing uninitialized data on failed inode read
+    - rtw88: increse the size of rx buffer size
+    - USB: cdc-acm: handle broken union descriptors
+    - usb: dwc3: simple: add support for Hikey 970
+    - can: flexcan: flexcan_chip_stop(): add error handling and propagate error
+      value
+    - ath9k: hif_usb: fix race condition between usb_get_urb() and
+      usb_kill_anchored_urbs()
+    - drm/panfrost: add amlogic reset quirk callback
+    - bpf: Limit caller's stack depth 256 for subprogs with tailcalls
+    - misc: rtsx: Fix memory leak in rtsx_pci_probe
+    - reiserfs: only call unlock_new_inode() if I_NEW
+    - opp: Prevent memory leak in dev_pm_opp_attach_genpd()
+    - xfs: make sure the rt allocator doesn't run off the end
+    - usb: ohci: Default to per-port over-current protection
+    - Bluetooth: Only mark socket zapped after unlocking
+    - drm/msm/a6xx: fix a potential overflow issue
+    - iomap: fix WARN_ON_ONCE() from unprivileged users
+    - scsi: ibmvfc: Fix error return in ibmvfc_probe()
+    - scsi: qla2xxx: Warn if done() or free() are called on an already freed srb
+    - selftests/bpf: Fix test_sysctl_loop{1, 2} failure due to clang change
+    - brcmsmac: fix memory leak in wlc_phy_attach_lcnphy
+    - rtl8xxxu: prevent potential memory leak
+    - Fix use after free in get_capset_info callback.
+    - HID: ite: Add USB id match for Acer One S1003 keyboard dock
+    - scsi: qedf: Return SUCCESS if stale rport is encountered
+    - scsi: qedi: Protect active command list to avoid list corruption
+    - scsi: qedi: Fix list_del corruption while removing active I/O
+    - fbmem: add margin check to fb_check_caps()
+    - tty: ipwireless: fix error handling
+    - Bluetooth: btusb: Fix memleak in btusb_mtk_submit_wmt_recv_urb
+    - ipvs: Fix uninit-value in do_ip_vs_set_ctl()
+    - reiserfs: Fix memory leak in reiserfs_parse_options()
+    - mwifiex: don't call del_timer_sync() on uninitialized timer
+    - ALSA: hda/ca0132 - Add AE-7 microphone selection commands.
+    - ALSA: hda/ca0132 - Add new quirk ID for SoundBlaster AE-7.
+    - scsi: smartpqi: Avoid crashing kernel for controller issues
+    - brcm80211: fix possible memleak in brcmf_proto_msgbuf_attach
+    - usb: core: Solve race condition in anchor cleanup functions
+    - scsi: ufs: ufs-qcom: Fix race conditions caused by ufs_qcom_testbus_config()
+    - dmaengine: dw: Add DMA-channels mask cell support
+    - dmaengine: dw: Activate FIFO-mode for memory peripherals only
+    - ath10k: check idx validity in __ath10k_htt_rx_ring_fill_n()
+    - net: korina: cast KSEG0 address to pointer in kfree
+    - s390/qeth: don't let HW override the configured port role
+    - tty: serial: lpuart: fix lpuart32_write usage
+    - tty: serial: fsl_lpuart: fix lpuart32_poll_get_char
+    - usb: cdc-acm: add quirk to blacklist ETAS ES58X devices
+    - USB: cdc-wdm: Make wdm_flush() interruptible and add wdm_fsync().
+    - usb: cdns3: gadget: free interrupt after gadget has deleted
+    - eeprom: at25: set minimum read/write access stride to 1
+    - usb: gadget: f_ncm: allow using NCM in SuperSpeed Plus gadgets.
+    - Linux 5.4.73
+  * Focal update: v5.4.72 upstream stable release (LP: #1902111)
+    - perf cs-etm: Move definition of 'traceid_list' global variable from header
+      file
+    - btrfs: don't pass system_chunk into can_overcommit
+    - btrfs: take overcommit into account in inc_block_group_ro
+    - ARM: 8939/1: kbuild: use correct nm executable
+    - ACPI: Always build evged in
+    - Bluetooth: Consolidate encryption handling in hci_encrypt_cfm
+    - Bluetooth: Fix update of connection state in `hci_encrypt_cfm`
+    - Bluetooth: Disconnect if E0 is used for Level 4
+    - media: usbtv: Fix refcounting mixup
+    - USB: serial: option: add Cellient MPL200 card
+    - USB: serial: option: Add Telit FT980-KS composition
+    - staging: comedi: check validity of wMaxPacketSize of usb endpoints found
+    - USB: serial: pl2303: add device-id for HP GC device
+    - USB: serial: ftdi_sio: add support for FreeCalypso JTAG+UART adapters
+    - reiserfs: Initialize inode keys properly
+    - reiserfs: Fix oops during mount
+    - xen/events: don't use chip_data for legacy IRQs
+    - crypto: bcm - Verify GCM/CCM key length in setkey
+    - crypto: qat - check cipher length for aead AES-CBC-HMAC-SHA
+    - Linux 5.4.72
+  * Focal update: v5.4.71 upstream stable release (LP: #1902110)
+    - fbdev, newport_con: Move FONT_EXTRA_WORDS macros into linux/font.h
+    - Fonts: Support FONT_EXTRA_WORDS macros for built-in fonts
+    - fbcon: Fix global-out-of-bounds read in fbcon_get_font()
+    - Revert "ravb: Fixed to be able to unload modules"
+    - io_uring: Fix resource leaking when kill the process
+    - io_uring: Fix missing smp_mb() in io_cancel_async_work()
+    - io_uring: Fix remove irrelevant req from the task_list
+    - io_uring: Fix double list add in io_queue_async_work()
+    - net: wireless: nl80211: fix out-of-bounds access in nl80211_del_key()
+    - drm/nouveau/mem: guard against NULL pointer access in mem_del
+    - vhost: Don't call access_ok() when using IOTLB
+    - vhost: Use vhost_get_used_size() in vhost_vring_set_addr()
+    - usermodehelper: reset umask to default before executing user process
+    - Platform: OLPC: Fix memleak in olpc_ec_probe
+    - platform/x86: intel-vbtn: Fix SW_TABLET_MODE always reporting 1 on the HP
+      Pavilion 11 x360
+    - platform/x86: thinkpad_acpi: initialize tp_nvram_state variable
+    - bpf: Fix sysfs export of empty BTF section
+    - bpf: Prevent .BTF section elimination
+    - platform/x86: intel-vbtn: Switch to an allow-list for SW_TABLET_MODE
+      reporting
+    - platform/x86: thinkpad_acpi: re-initialize ACPI buffer size when reuse
+    - driver core: Fix probe_count imbalance in really_probe()
+    - perf test session topology: Fix data path
+    - perf top: Fix stdio interface input handling with glibc 2.28+
+    - i2c: i801: Exclude device from suspend direct complete optimization
+    - arm64: dts: stratix10: add status to qspi dts node
+    - Btrfs: send, allow clone operations within the same file
+    - Btrfs: send, fix emission of invalid clone operations within the same file
+    - btrfs: volumes: Use more straightforward way to calculate map length
+    - btrfs: Ensure we trim ranges across block group boundary
+    - btrfs: fix RWF_NOWAIT write not failling when we need to cow
+    - btrfs: allow btrfs_truncate_block() to fallback to nocow for data space
+      reservation
+    - nvme-core: put ctrl ref when module ref get fail
+    - macsec: avoid use-after-free in macsec_handle_frame()
+    - mm/khugepaged: fix filemap page_to_pgoff(page) != offset
+    - net: introduce helper sendpage_ok() in include/linux/net.h
+    - tcp: use sendpage_ok() to detect misused .sendpage
+    - nvme-tcp: check page by sendpage_ok() before calling kernel_sendpage()
+    - xfrmi: drop ignore_df check before updating pmtu
+    - cifs: Fix incomplete memory allocation on setxattr path
+    - i2c: meson: fix clock setting overwrite
+    - i2c: meson: fixup rate calculation with filter delay
+    - i2c: owl: Clear NACK and BUS error bits
+    - sctp: fix sctp_auth_init_hmacs() error path
+    - team: set dev->needed_headroom in team_setup_by_port()
+    - net: team: fix memory leak in __team_options_register
+    - openvswitch: handle DNAT tuple collision
+    - drm/amdgpu: prevent double kfree ttm->sg
+    - iommu/vt-d: Fix lockdep splat in iommu_flush_dev_iotlb()
+    - xfrm: clone XFRMA_SET_MARK in xfrm_do_migrate
+    - xfrm: clone XFRMA_REPLAY_ESN_VAL in xfrm_do_migrate
+    - xfrm: clone XFRMA_SEC_CTX in xfrm_do_migrate
+    - xfrm: clone whole liftime_cur structure in xfrm_do_migrate
+    - net: stmmac: removed enabling eee in EEE set callback
+    - platform/x86: fix kconfig dependency warning for FUJITSU_LAPTOP
+    - xfrm: Use correct address family in xfrm_state_find
+    - iavf: use generic power management
+    - iavf: Fix incorrect adapter get in iavf_resume
+    - net: ethernet: cavium: octeon_mgmt: use phy_start and phy_stop
+    - bonding: set dev->needed_headroom in bond_setup_by_slave()
+    - mdio: fix mdio-thunder.c dependency & build error
+    - mlxsw: spectrum_acl: Fix mlxsw_sp_acl_tcam_group_add()'s error path
+    - r8169: fix RTL8168f/RTL8411 EPHY config
+    - net: usb: ax88179_178a: fix missing stop entry in driver_info
+    - virtio-net: don't disable guest csum when disable LRO
+    - net/mlx5: Avoid possible free of command entry while timeout comp handler
+    - net/mlx5: Fix request_irqs error flow
+    - net/mlx5e: Add resiliency in Striding RQ mode for packets larger than MTU
+    - net/mlx5e: Fix VLAN cleanup flow
+    - net/mlx5e: Fix VLAN create flow
+    - rxrpc: Fix rxkad token xdr encoding
+    - rxrpc: Downgrade the BUG() for unsupported token type in rxrpc_read()
+    - rxrpc: Fix some missing _bh annotations on locking conn->state_lock
+    - rxrpc: The server keyring isn't network-namespaced
+    - rxrpc: Fix server keyring leak
+    - perf: Fix task_function_call() error handling
+    - mmc: core: don't set limits.discard_granularity as 0
+    - mm: khugepaged: recalculate min_free_kbytes after memory hotplug as expected
+      by khugepaged
+    - tcp: fix receive window update in tcp_add_backlog()
+    - net/core: check length before updating Ethertype in skb_mpls_{push,pop}
+    - net/tls: race causes kernel panic
+    - net/mlx5e: Fix driver's declaration to support GRE offload
+    - Input: ati_remote2 - add missing newlines when printing module parameters
+    - net: usb: rtl8150: set random MAC address when set_ethernet_addr() fails
+    - net_sched: defer tcf_idr_insert() in tcf_action_init_1()
+    - net_sched: commit action insertions together
+    - Linux 5.4.71
+  * kci_test_encap_fou() in rtnetlink.sh from kselftests/net failed with "FAIL:
+    can't add fou port 7777, skipping test" (LP: #1891421)
+    - selftests: rtnetlink: load fou module for kci_test_encap_fou() test
+  * alsa/hda/realtek - The front Mic on a HP machine doesn't work (LP: #1899508)
+    - ALSA: hda/realtek - The front Mic on a HP machine doesn't work
+  * Enable brightness control on HP DreamColor panel (LP: #1898865)
+    - drm/i915/dpcd_bl: Unbreak enable_dpcd_backlight modparam
+    - SAUCE: drm/i915/dpcd_bl: Skip testing control capability with force DPCD
+      quirk
+    - SAUCE: drm/dp: HP DreamColor panel brigntness fix
+  * Fix non-working Intel NVMe after S3 (LP: #1900847)
+    - SAUCE: PCI: Enable ACS quirk on all CML root ports
+  * bcache: Issues with large IO wait in bch_mca_scan() when shrinker is enabled
+    (LP: #1898786)
+    - bcache: remove member accessed from struct btree
+    - bcache: reap c->btree_cache_freeable from the tail in bch_mca_scan()
+    - bcache: reap from tail of c->btree_cache in bch_mca_scan()
+  * Improve descriptions for XFAIL cases in kselftests/net/psock_snd
+    (LP: #1900088)
+    - selftests/net: improve descriptions for XFAIL cases in psock_snd.sh
+  * ceph: fix inode number handling on arches with 32-bit ino_t (LP: #1899582)
+    - ceph: fix inode number handling on arches with 32-bit ino_t
+  * Fix system reboot when disconnecting WiFi (LP: #1899726)
+    - iwlwifi: msix: limit max RX queues for 9000 family
+  * Fix broken MSI interrupt after HDA controller was suspended (LP: #1899586)
+    - ALSA: hda: fix jack detection with Realtek codecs when in D3
+  * Focal update: v5.4.70 upstream stable release (LP: #1900632)
+    - btrfs: fix filesystem corruption after a device replace
+    - mmc: sdhci: Workaround broken command queuing on Intel GLK based IRBIS
+      models
+    - USB: gadget: f_ncm: Fix NDP16 datagram validation
+    - gpio: siox: explicitly support only threaded irqs
+    - gpio: mockup: fix resource leak in error path
+    - gpio: tc35894: fix up tc35894 interrupt configuration
+    - clk: socfpga: stratix10: fix the divider for the emac_ptp_free_clk
+    - vsock/virtio: add transport parameter to the
+      virtio_transport_reset_no_sock()
+    - net: virtio_vsock: Enhance connection semantics
+    - xfs: trim IO to found COW extent limit
+    - Input: i8042 - add nopnp quirk for Acer Aspire 5 A515
+    - iio: adc: qcom-spmi-adc5: fix driver name
+    - ftrace: Move RCU is watching check after recursion check
+    - memstick: Skip allocating card when removing host
+    - drm/amdgpu: restore proper ref count in amdgpu_display_crtc_set_config
+    - clocksource/drivers/timer-gx6605s: Fixup counter reload
+    - libbpf: Remove arch-specific include path in Makefile
+    - drivers/net/wan/hdlc_fr: Add needed_headroom for PVC devices
+    - drm/sun4i: mixer: Extend regmap max_register
+    - net: dec: de2104x: Increase receive ring size for Tulip
+    - rndis_host: increase sleep time in the query-response loop
+    - nvme-core: get/put ctrl and transport module in nvme_dev_open/release()
+    - fuse: fix the ->direct_IO() treatment of iov_iter
+    - drivers/net/wan/lapbether: Make skb->protocol consistent with the header
+    - drivers/net/wan/hdlc: Set skb->protocol before transmitting
+    - mac80211: Fix radiotap header channel flag for 6GHz band
+    - mac80211: do not allow bigger VHT MPDUs than the hardware supports
+    - tracing: Make the space reserved for the pid wider
+    - tools/io_uring: fix compile breakage
+    - spi: fsl-espi: Only process interrupts for expected events
+    - nvme-pci: fix NULL req in completion handler
+    - nvme-fc: fail new connections to a deleted host or remote port
+    - gpio: sprd: Clear interrupt when setting the type as edge
+    - phy: ti: am654: Fix a leak in serdes_am654_probe()
+    - pinctrl: mvebu: Fix i2c sda definition for 98DX3236
+    - nfs: Fix security label length not being reset
+    - clk: tegra: Always program PLL_E when enabled
+    - clk: samsung: exynos4: mark 'chipid' clock as CLK_IGNORE_UNUSED
+    - iommu/exynos: add missing put_device() call in exynos_iommu_of_xlate()
+    - gpio/aspeed-sgpio: enable access to all 80 input & output sgpios
+    - gpio/aspeed-sgpio: don't enable all interrupts by default
+    - gpio: aspeed: fix ast2600 bank properties
+    - i2c: cpm: Fix i2c_ram structure
+    - Input: trackpoint - enable Synaptics trackpoints
+    - scripts/dtc: only append to HOST_EXTRACFLAGS instead of overwriting
+    - random32: Restore __latent_entropy attribute on net_rand_state
+    - block/diskstats: more accurate approximation of io_ticks for slow disks
+    - mm: replace memmap_context by meminit_context
+    - mm: don't rely on system state to detect hot-plug operations
+    - nvme: Cleanup and rename nvme_block_nr()
+    - nvme: Introduce nvme_lba_to_sect()
+    - nvme: consolidate chunk_sectors settings
+    - epoll: do not insert into poll queues until all sanity checks are done
+    - epoll: replace ->visited/visited_list with generation count
+    - epoll: EPOLL_CTL_ADD: close the race in decision to take fast path
+    - ep_create_wakeup_source(): dentry name can change under you...
+    - netfilter: ctnetlink: add a range check for l3/l4 protonum
+    - Linux 5.4.70
+  * Focal update: v5.4.69 upstream stable release (LP: #1900624)
+    - kernel/sysctl-test: Add null pointer test for sysctl.c:proc_dointvec()
+    - selinux: allow labeling before policy is loaded
+    - media: mc-device.c: fix memleak in media_device_register_entity
+    - drm/amd/display: Do not double-buffer DTO adjustments
+    - drm/amdkfd: Fix race in gfx10 context restore handler
+    - dma-fence: Serialise signal enabling (dma_fence_enable_sw_signaling)
+    - scsi: qla2xxx: Add error handling for PLOGI ELS passthrough
+    - ath10k: fix array out-of-bounds access
+    - ath10k: fix memory leak for tpc_stats_final
+    - PCI/IOV: Serialize sysfs sriov_numvfs reads vs writes
+    - mm: fix double page fault on arm64 if PTE_AF is cleared
+    - scsi: aacraid: fix illegal IO beyond last LBA
+    - m68k: q40: Fix info-leak in rtc_ioctl
+    - xfs: fix inode fork extent count overflow
+    - gma/gma500: fix a memory disclosure bug due to uninitialized bytes
+    - ASoC: kirkwood: fix IRQ error handling
+    - soundwire: intel/cadence: fix startup sequence
+    - media: smiapp: Fix error handling at NVM reading
+    - drm/amd/display: Free gamma after calculating legacy transfer function
+    - xfs: properly serialise fallocate against AIO+DIO
+    - leds: mlxreg: Fix possible buffer overflow
+    - dm table: do not allow request-based DM to stack on partitions
+    - PM / devfreq: tegra30: Fix integer overflow on CPU's freq max out
+    - scsi: fnic: fix use after free
+    - powerpc/64s: Always disable branch profiling for prom_init.o
+    - net: silence data-races on sk_backlog.tail
+    - dax: Fix alloc_dax_region() compile warning
+    - iomap: Fix overflow in iomap_page_mkwrite
+    - f2fs: avoid kernel panic on corruption test
+    - clk/ti/adpll: allocate room for terminating null
+    - drm/amdgpu/powerplay: fix AVFS handling with custom powerplay table
+    - ice: Fix to change Rx/Tx ring descriptor size via ethtool with DCBx
+    - mtd: cfi_cmdset_0002: don't free cfi->cfiq in error path of
+      cfi_amdstd_setup()
+    - mfd: mfd-core: Protect against NULL call-back function pointer
+    - drm/amdgpu/powerplay/smu7: fix AVFS handling with custom powerplay table
+    - tpm_crb: fix fTPM on AMD Zen+ CPUs
+    - tracing: Verify if trace array exists before destroying it.
+    - tracing: Adding NULL checks for trace_array descriptor pointer
+    - bcache: fix a lost wake-up problem caused by mca_cannibalize_lock
+    - dmaengine: mediatek: hsdma_probe: fixed a memory leak when devm_request_irq
+      fails
+    - x86/kdump: Always reserve the low 1M when the crashkernel option is
+      specified
+    - RDMA/qedr: Fix potential use after free
+    - RDMA/i40iw: Fix potential use after free
+    - PCI: Avoid double hpmemsize MMIO window assignment
+    - fix dget_parent() fastpath race
+    - xfs: fix attr leaf header freemap.size underflow
+    - RDMA/iw_cgxb4: Fix an error handling path in 'c4iw_connect()'
+    - ubi: Fix producing anchor PEBs
+    - mmc: core: Fix size overflow for mmc partitions
+    - gfs2: clean up iopen glock mess in gfs2_create_inode
+    - scsi: pm80xx: Cleanup command when a reset times out
+    - mt76: do not use devm API for led classdev
+    - mt76: add missing locking around ampdu action
+    - debugfs: Fix !DEBUG_FS debugfs_create_automount
+    - SUNRPC: Capture completion of all RPC tasks
+    - CIFS: Use common error handling code in smb2_ioctl_query_info()
+    - CIFS: Properly process SMB3 lease breaks
+    - f2fs: stop GC when the victim becomes fully valid
+    - ASoC: max98090: remove msleep in PLL unlocked workaround
+    - xtensa: fix system_call interaction with ptrace
+    - s390: avoid misusing CALL_ON_STACK for task stack setup
+    - xfs: fix realtime file data space leak
+    - drm/amdgpu: fix calltrace during kmd unload(v3)
+    - arm64: insn: consistently handle exit text
+    - selftests/bpf: De-flake test_tcpbpf
+    - kernel/notifier.c: intercept duplicate registrations to avoid infinite loops
+    - kernel/sys.c: avoid copying possible padding bytes in copy_to_user
+    - KVM: arm/arm64: vgic: Fix potential double free dist->spis in
+      __kvm_vgic_destroy()
+    - module: Remove accidental change of module_enable_x()
+    - xfs: fix log reservation overflows when allocating large rt extents
+    - ALSA: hda: enable regmap internal locking
+    - tipc: fix link overflow issue at socket shutdown
+    - vcc_seq_next should increase position index
+    - neigh_stat_seq_next() should increase position index
+    - rt_cpu_seq_next should increase position index
+    - ipv6_route_seq_next should increase position index
+    - drm/mcde: Handle pending vblank while disabling display
+    - seqlock: Require WRITE_ONCE surrounding raw_seqcount_barrier
+    - drm/scheduler: Avoid accessing freed bad job.
+    - media: ti-vpe: cal: Restrict DMA to avoid memory corruption
+    - opp: Replace list_kref with a local counter
+    - scsi: qla2xxx: Fix stuck session in GNL
+    - sctp: move trace_sctp_probe_path into sctp_outq_sack
+    - ACPI: EC: Reference count query handlers under lock
+    - scsi: ufs: Make ufshcd_add_command_trace() easier to read
+    - scsi: ufs: Fix a race condition in the tracing code
+    - drm/amd/display: Initialize DSC PPS variables to 0
+    - i2c: tegra: Prevent interrupt triggering after transfer timeout
+    - btrfs: tree-checker: Check leaf chunk item size
+    - dmaengine: zynqmp_dma: fix burst length configuration
+    - s390/cpum_sf: Use kzalloc and minor changes
+    - nfsd: Fix a soft lockup race in nfsd_file_mark_find_or_create()
+    - powerpc/eeh: Only dump stack once if an MMIO loop is detected
+    - Bluetooth: btrtl: Use kvmalloc for FW allocations
+    - tracing: Set kernel_stack's caller size properly
+    - ARM: 8948/1: Prevent OOB access in stacktrace
+    - ar5523: Add USB ID of SMCWUSBT-G2 wireless adapter
+    - ceph: ensure we have a new cap before continuing in fill_inode
+    - selftests/ftrace: fix glob selftest
+    - tools/power/x86/intel_pstate_tracer: changes for python 3 compatibility
+    - Bluetooth: Fix refcount use-after-free issue
+    - mm/swapfile.c: swap_next should increase position index
+    - mm: pagewalk: fix termination condition in walk_pte_range()
+    - Bluetooth: prefetch channel before killing sock
+    - ALSA: hda: Clear RIRB status before reading WP
+    - skbuff: fix a data race in skb_queue_len()
+    - nfsd: Fix a perf warning
+    - drm/amd/display: fix workaround for incorrect double buffer register for DLG
+      ADL and TTU
+    - audit: CONFIG_CHANGE don't log internal bookkeeping as an event
+    - selinux: sel_avc_get_stat_idx should increase position index
+    - drm/omap: fix possible object reference leak
+    - locking/lockdep: Decrement IRQ context counters when removing lock chain
+    - clk: stratix10: use do_div() for 64-bit calculation
+    - crypto: chelsio - This fixes the kernel panic which occurs during a libkcapi
+      test
+    - mt76: clear skb pointers from rx aggregation reorder buffer during cleanup
+    - mt76: fix handling full tx queues in mt76_dma_tx_queue_skb_raw
+    - ALSA: usb-audio: Don't create a mixer element with bogus volume range
+    - perf test: Fix test trace+probe_vfs_getname.sh on s390
+    - RDMA/rxe: Fix configuration of atomic queue pair attributes
+    - KVM: x86: fix incorrect comparison in trace event
+    - KVM: nVMX: Hold KVM's srcu lock when syncing vmcs12->shadow
+    - dmaengine: stm32-mdma: use vchan_terminate_vdesc() in .terminate_all
+    - media: staging/imx: Missing assignment in
+      imx_media_capture_device_register()
+    - x86/pkeys: Add check for pkey "overflow"
+    - bpf: Remove recursion prevention from rcu free callback
+    - dmaengine: stm32-dma: use vchan_terminate_vdesc() in .terminate_all
+    - dmaengine: tegra-apb: Prevent race conditions on channel's freeing
+    - soundwire: bus: disable pm_runtime in sdw_slave_delete
+    - drm/amd/display: dal_ddc_i2c_payloads_create can fail causing panic
+    - drm/omap: dss: Cleanup DSS ports on initialisation failure
+    - iavf: use tc_cls_can_offload_and_chain0() instead of chain check
+    - firmware: arm_sdei: Use cpus_read_lock() to avoid races with cpuhp
+    - random: fix data races at timer_rand_state
+    - bus: hisi_lpc: Fixup IO ports addresses to avoid use-after-free in host
+      removal
+    - ASoC: SOF: ipc: check ipc return value before data copy
+    - media: go7007: Fix URB type for interrupt handling
+    - Bluetooth: guard against controllers sending zero'd events
+    - timekeeping: Prevent 32bit truncation in scale64_check_overflow()
+    - powerpc/book3s64: Fix error handling in mm_iommu_do_alloc()
+    - drm/amd/display: fix image corruption with ODM 2:1 DSC 2 slice
+    - ext4: fix a data race at inode->i_disksize
+    - perf jevents: Fix leak of mapfile memory
+    - mm: avoid data corruption on CoW fault into PFN-mapped VMA
+    - drm/amdgpu: increase atombios cmd timeout
+    - ARM: OMAP2+: Handle errors for cpu_pm
+    - clk: imx: Fix division by zero warning on pfdv2
+    - cpu-topology: Fix the potential data corruption
+    - s390/irq: replace setup_irq() by request_irq()
+    - perf cs-etm: Swap packets for instruction samples
+    - perf cs-etm: Correct synthesizing instruction samples
+    - ath10k: use kzalloc to read for ath10k_sdio_hif_diag_read
+    - scsi: aacraid: Disabling TM path and only processing IOP reset
+    - Bluetooth: L2CAP: handle l2cap config request during open state
+    - media: tda10071: fix unsigned sign extension overflow
+    - tty: sifive: Finish transmission before changing the clock
+    - xfs: don't ever return a stale pointer from __xfs_dir3_free_read
+    - xfs: mark dir corrupt when lookup-by-hash fails
+    - ext4: mark block bitmap corrupted when found instead of BUGON
+    - tpm: ibmvtpm: Wait for buffer to be set before proceeding
+    - rtc: sa1100: fix possible race condition
+    - rtc: ds1374: fix possible race condition
+    - nfsd: Don't add locks to closed or closing open stateids
+    - RDMA/cm: Remove a race freeing timewait_info
+    - intel_th: Disallow multi mode on devices where it's broken
+    - KVM: PPC: Book3S HV: Treat TM-related invalid form instructions on P9 like
+      the valid ones
+    - drm/msm: fix leaks if initialization fails
+    - drm/msm/a5xx: Always set an OPP supported hardware value
+    - tracing: Use address-of operator on section symbols
+    - thermal: rcar_thermal: Handle probe error gracefully
+    - KVM: LAPIC: Mark hrtimer for period or oneshot mode to expire in hard
+      interrupt context
+    - perf parse-events: Fix 3 use after frees found with clang ASAN
+    - btrfs: do not init a reloc root if we aren't relocating
+    - btrfs: free the reloc_control in a consistent way
+    - r8169: improve RTL8168b FIFO overflow workaround
+    - serial: 8250_port: Don't service RX FIFO if throttled
+    - serial: 8250_omap: Fix sleeping function called from invalid context during
+      probe
+    - serial: 8250: 8250_omap: Terminate DMA before pushing data on RX timeout
+    - perf cpumap: Fix snprintf overflow check
+    - net: axienet: Convert DMA error handler to a work queue
+    - net: axienet: Propagate failure of DMA descriptor setup
+    - cpufreq: powernv: Fix frame-size-overflow in powernv_cpufreq_work_fn
+    - tools: gpio-hammer: Avoid potential overflow in main
+    - exec: Add exec_update_mutex to replace cred_guard_mutex
+    - exec: Fix a deadlock in strace
+    - selftests/ptrace: add test cases for dead-locks
+    - kernel/kcmp.c: Use new infrastructure to fix deadlocks in execve
+    - proc: Use new infrastructure to fix deadlocks in execve
+    - proc: io_accounting: Use new infrastructure to fix deadlocks in execve
+    - perf: Use new infrastructure to fix deadlocks in execve
+    - nvme-multipath: do not reset on unknown status
+    - nvme: Fix ctrl use-after-free during sysfs deletion
+    - nvme: Fix controller creation races with teardown flow
+    - brcmfmac: Fix double freeing in the fmac usb data path
+    - xfs: prohibit fs freezing when using empty transactions
+    - RDMA/rxe: Set sys_image_guid to be aligned with HW IB devices
+    - IB/iser: Always check sig MR before putting it to the free pool
+    - scsi: hpsa: correct race condition in offload enabled
+    - SUNRPC: Fix a potential buffer overflow in 'svc_print_xprts()'
+    - svcrdma: Fix leak of transport addresses
+    - netfilter: nf_tables: silence a RCU-list warning in nft_table_lookup()
+    - PCI: Use ioremap(), not phys_to_virt() for platform ROM
+    - ubifs: ubifs_jnl_write_inode: Fix a memory leak bug
+    - ubifs: ubifs_add_orphan: Fix a memory leak bug
+    - ubifs: Fix out-of-bounds memory access caused by abnormal value of node_len
+    - ALSA: usb-audio: Fix case when USB MIDI interface has more than one extra
+      endpoint descriptor
+    - PCI: pciehp: Fix MSI interrupt race
+    - NFS: Fix races nfs_page_group_destroy() vs
+      nfs_destroy_unlinked_subrequests()
+    - drm/amdgpu/vcn2.0: stall DPG when WPTR/RPTR reset
+    - powerpc/perf: Implement a global lock to avoid races between trace, core and
+      thread imc events.
+    - mm/kmemleak.c: use address-of operator on section symbols
+    - mm/filemap.c: clear page error before actual read
+    - mm/swapfile: fix data races in try_to_unuse()
+    - mm/vmscan.c: fix data races using kswapd_classzone_idx
+    - SUNRPC: Don't start a timer on an already queued rpc task
+    - nvmet-rdma: fix double free of rdma queue
+    - workqueue: Remove the warning in wq_worker_sleeping()
+    - drm/amdgpu/sriov add amdgpu_amdkfd_pre_reset in gpu reset
+    - mm/mmap.c: initialize align_offset explicitly for vm_unmapped_area
+    - ALSA: hda: Skip controller resume if not needed
+    - scsi: qedi: Fix termination timeouts in session logout
+    - serial: uartps: Wait for tx_empty in console setup
+    - btrfs: fix setting last_trans for reloc roots
+    - KVM: Remove CREATE_IRQCHIP/SET_PIT2 race
+    - perf stat: Force error in fallback on :k events
+    - bdev: Reduce time holding bd_mutex in sync in blkdev_close()
+    - drivers: char: tlclk.c: Avoid data race between init and interrupt handler
+    - KVM: arm64: vgic-v3: Retire all pending LPIs on vcpu destroy
+    - KVM: arm64: vgic-its: Fix memory leak on the error path of vgic_add_lpi()
+    - net: openvswitch: use u64 for meter bucket
+    - scsi: aacraid: Fix error handling paths in aac_probe_one()
+    - staging:r8188eu: avoid skb_clone for amsdu to msdu conversion
+    - sparc64: vcc: Fix error return code in vcc_probe()
+    - arm64: cpufeature: Relax checks for AArch32 support at EL[0-2]
+    - sched/fair: Eliminate bandwidth race between throttling and distribution
+    - dpaa2-eth: fix error return code in setup_dpni()
+    - dt-bindings: sound: wm8994: Correct required supplies based on actual
+      implementaion
+    - devlink: Fix reporter's recovery condition
+    - atm: fix a memory leak of vcc->user_back
+    - media: venus: vdec: Init registered list unconditionally
+    - perf mem2node: Avoid double free related to realloc
+    - mm/slub: fix incorrect interpretation of s->offset
+    - i2c: tegra: Restore pinmux on system resume
+    - power: supply: max17040: Correct voltage reading
+    - phy: samsung: s5pv210-usb2: Add delay after reset
+    - Bluetooth: Handle Inquiry Cancel error after Inquiry Complete
+    - USB: EHCI: ehci-mv: fix error handling in mv_ehci_probe()
+    - KVM: x86: handle wrap around 32-bit address space
+    - tipc: fix memory leak in service subscripting
+    - tty: serial: samsung: Correct clock selection logic
+    - ALSA: hda: Fix potential race in unsol event handler
+    - drm/exynos: dsi: Remove bridge node reference in error handling path in
+      probe function
+    - ipmi:bt-bmc: Fix error handling and status check
+    - powerpc/traps: Make unrecoverable NMIs die instead of panic
+    - svcrdma: Fix backchannel return code
+    - fuse: don't check refcount after stealing page
+    - fuse: update attr_version counter on fuse_notify_inval_inode()
+    - USB: EHCI: ehci-mv: fix less than zero comparison of an unsigned int
+    - coresight: etm4x: Fix use-after-free of per-cpu etm drvdata
+    - arm64: acpi: Make apei_claim_sea() synchronise with APEI's irq work
+    - scsi: cxlflash: Fix error return code in cxlflash_probe()
+    - arm64/cpufeature: Drop TraceFilt feature exposure from ID_DFR0 register
+    - drm/amdkfd: fix restore worker race condition
+    - e1000: Do not perform reset in reset_task if we are already down
+    - drm/nouveau/debugfs: fix runtime pm imbalance on error
+    - drm/nouveau: fix runtime pm imbalance on error
+    - drm/nouveau/dispnv50: fix runtime pm imbalance on error
+    - printk: handle blank console arguments passed in.
+    - usb: dwc3: Increase timeout for CmdAct cleared by device controller
+    - btrfs: don't force read-only after error in drop snapshot
+    - btrfs: fix double __endio_write_update_ordered in direct I/O
+    - gpio: rcar: Fix runtime PM imbalance on error
+    - vfio/pci: fix memory leaks of eventfd ctx
+    - KVM: PPC: Book3S HV: Close race with page faults around memslot flushes
+    - perf evsel: Fix 2 memory leaks
+    - perf trace: Fix the selection for architectures to generate the errno name
+      tables
+    - perf stat: Fix duration_time value for higher intervals
+    - perf util: Fix memory leak of prefix_if_not_in
+    - perf metricgroup: Free metric_events on error
+    - perf kcore_copy: Fix module map when there are no modules loaded
+    - PCI: tegra194: Fix runtime PM imbalance on error
+    - ASoC: img-i2s-out: Fix runtime PM imbalance on error
+    - wlcore: fix runtime pm imbalance in wl1271_tx_work
+    - wlcore: fix runtime pm imbalance in wlcore_regdomain_config
+    - mtd: rawnand: gpmi: Fix runtime PM imbalance on error
+    - mtd: rawnand: omap_elm: Fix runtime PM imbalance on error
+    - PCI: tegra: Fix runtime PM imbalance on error
+    - ceph: fix potential race in ceph_check_caps
+    - mm/swap_state: fix a data race in swapin_nr_pages
+    - mm: memcontrol: fix stat-corrupting race in charge moving
+    - rapidio: avoid data race between file operation callbacks and
+      mport_cdev_add().
+    - mtd: parser: cmdline: Support MTD names containing one or more colons
+    - x86/speculation/mds: Mark mds_user_clear_cpu_buffers() __always_inline
+    - NFS: nfs_xdr_status should record the procedure name
+    - vfio/pci: Clear error and request eventfd ctx after releasing
+    - cifs: Fix double add page to memcg when cifs_readpages
+    - nvme: fix possible deadlock when I/O is blocked
+    - mac80211: skip mpath lookup also for control port tx
+    - scsi: libfc: Handling of extra kref
+    - scsi: libfc: Skip additional kref updating work event
+    - selftests/x86/syscall_nt: Clear weird flags after each test
+    - vfio/pci: fix racy on error and request eventfd ctx
+    - btrfs: qgroup: fix data leak caused by race between writeback and truncate
+    - perf tests: Fix test 68 zstd compression for s390
+    - scsi: qla2xxx: Retry PLOGI on FC-NVMe PRLI failure
+    - ubi: fastmap: Free unused fastmap anchor peb during detach
+    - mt76: fix LED link time failure
+    - opp: Increase parsed_static_opps in _of_add_opp_table_v1()
+    - perf parse-events: Use strcmp() to compare the PMU name
+    - ALSA: hda: Always use jackpoll helper for jack update after resume
+    - ALSA: hda: Workaround for spurious wakeups on some Intel platforms
+    - net: openvswitch: use div_u64() for 64-by-32 divisions
+    - nvme: explicitly update mpath disk capacity on revalidation
+    - device_cgroup: Fix RCU list debugging warning
+    - ASoC: pcm3168a: ignore 0 Hz settings
+    - ASoC: wm8994: Skip setting of the WM8994_MICBIAS register for WM1811
+    - ASoC: wm8994: Ensure the device is resumed in wm89xx_mic_detect functions
+    - ASoC: Intel: bytcr_rt5640: Add quirk for MPMAN Converter9 2-in-1
+    - RISC-V: Take text_mutex in ftrace_init_nop()
+    - i2c: aspeed: Mask IRQ status to relevant bits
+    - s390/init: add missing __init annotations
+    - lockdep: fix order in trace_hardirqs_off_caller()
+    - EDAC/ghes: Check whether the driver is on the safe list correctly
+    - drm/amdkfd: fix a memory leak issue
+    - drm/amd/display: update nv1x stutter latencies
+    - drm/amdgpu/dc: Require primary plane to be enabled whenever the CRTC is
+    - objtool: Fix noreturn detection for ignored functions
+    - ieee802154: fix one possible memleak in ca8210_dev_com_init
+    - ieee802154/adf7242: check status of adf7242_read_reg
+    - clocksource/drivers/h8300_timer8: Fix wrong return value in
+      h8300_8timer_init()
+    - batman-adv: bla: fix type misuse for backbone_gw hash indexing
+    - atm: eni: fix the missed pci_disable_device() for eni_init_one()
+    - batman-adv: mcast/TT: fix wrongly dropped or rerouted packets
+    - netfilter: conntrack: nf_conncount_init is failing with IPv6 disabled
+    - mac802154: tx: fix use-after-free
+    - bpf: Fix clobbering of r2 in bpf_gen_ld_abs
+    - drm/vc4/vc4_hdmi: fill ASoC card owner
+    - net: qed: Disable aRFS for NPAR and 100G
+    - net: qede: Disable aRFS for NPAR and 100G
+    - net: qed: RDMA personality shouldn't fail VF load
+    - drm/sun4i: sun8i-csc: Secondary CSC register correction
+    - batman-adv: Add missing include for in_interrupt()
+    - nvme-tcp: fix kconfig dependency warning when !CRYPTO
+    - batman-adv: mcast: fix duplicate mcast packets in BLA backbone from LAN
+    - batman-adv: mcast: fix duplicate mcast packets in BLA backbone from mesh
+    - batman-adv: mcast: fix duplicate mcast packets from BLA backbone to mesh
+    - bpf: Fix a rcu warning for bpffs map pretty-print
+    - lib80211: fix unmet direct dependendices config warning when !CRYPTO
+    - ALSA: asihpi: fix iounmap in error handler
+    - regmap: fix page selection for noinc reads
+    - regmap: fix page selection for noinc writes
+    - MIPS: Add the missing 'CPU_1074K' into __get_cpu_type()
+    - regulator: axp20x: fix LDO2/4 description
+    - KVM: x86: Reset MMU context if guest toggles CR4.SMAP or CR4.PKE
+    - KVM: SVM: Add a dedicated INVD intercept routine
+    - mm: validate pmd after splitting
+    - arch/x86/lib/usercopy_64.c: fix __copy_user_flushcache() cache writeback
+    - x86/ioapic: Unbreak check_timer()
+    - scsi: lpfc: Fix initial FLOGI failure due to BBSCN not supported
+    - ALSA: usb-audio: Add delay quirk for H570e USB headsets
+    - ALSA: hda/realtek - Couldn't detect Mic if booting with headset plugged
+    - ALSA: hda/realtek: Enable front panel headset LED on Lenovo ThinkStation
+      P520
+    - lib/string.c: implement stpcpy
+    - tracing: fix double free
+    - s390/dasd: Fix zero write for FBA devices
+    - kprobes: Fix to check probe enabled before disarm_kprobe_ftrace()
+    - kprobes: tracing/kprobes: Fix to kill kprobes on initmem after boot
+    - btrfs: fix overflow when copying corrupt csums for a message
+    - dmabuf: fix NULL pointer dereference in dma_buf_release()
+    - mm, THP, swap: fix allocating cluster for swapfile by mistake
+    - mm/gup: fix gup_fast with dynamic page table folding
+    - s390/zcrypt: Fix ZCRYPT_PERDEV_REQCNT ioctl
+    - KVM: arm64: Assume write fault on S1PTW permission fault on instruction
+      fetch
+    - dm: fix bio splitting and its bio completion order for regular IO
+    - ata: define AC_ERR_OK
+    - ata: make qc_prep return ata_completion_errors
+    - ata: sata_mv, avoid trigerrable BUG_ON
+    - Linux 5.4.69
+  * Focal update: v5.4.68 upstream stable release (LP: #1899511)
+    - af_key: pfkey_dump needs parameter validation
+    - ibmvnic fix NULL tx_pools and rx_tools issue at do_reset
+    - ibmvnic: add missing parenthesis in do_reset()
+    - kprobes: fix kill kprobe which has been marked as gone
+    - mm/thp: fix __split_huge_pmd_locked() for migration PMD
+    - act_ife: load meta modules before tcf_idr_check_alloc()
+    - bnxt_en: Avoid sending firmware messages when AER error is detected.
+    - bnxt_en: Fix NULL ptr dereference crash in bnxt_fw_reset_task()
+    - cxgb4: fix memory leak during module unload
+    - cxgb4: Fix offset when clearing filter byte counters
+    - geneve: add transport ports in route lookup for geneve
+    - hdlc_ppp: add range checks in ppp_cp_parse_cr()
+    - ip: fix tos reflection in ack and reset packets
+    - ipv4: Initialize flowi4_multipath_hash in data path
+    - ipv4: Update exception handling for multipath routes via same device
+    - ipv6: avoid lockdep issue in fib6_del()
+    - net: bridge: br_vlan_get_pvid_rcu() should dereference the VLAN group under
+      RCU
+    - net: DCB: Validate DCB_ATTR_DCB_BUFFER argument
+    - net: dsa: rtl8366: Properly clear member config
+    - net: Fix bridge enslavement failure
+    - net: ipv6: fix kconfig dependency warning for IPV6_SEG6_HMAC
+    - net/mlx5: Fix FTE cleanup
+    - net: sch_generic: aviod concurrent reset and enqueue op for lockless qdisc
+    - net: sctp: Fix IPv6 ancestor_size calc in sctp_copy_descendant
+    - nfp: use correct define to return NONE fec
+    - taprio: Fix allowing too small intervals
+    - tipc: Fix memory leak in tipc_group_create_member()
+    - tipc: fix shutdown() of connection oriented socket
+    - tipc: use skb_unshare() instead in tipc_buf_append()
+    - net/mlx5e: Enable adding peer miss rules only if merged eswitch is supported
+    - net/mlx5e: TLS, Do not expose FPGA TLS counter if not supported
+    - bnxt_en: return proper error codes in bnxt_show_temp
+    - bnxt_en: Protect bnxt_set_eee() and bnxt_set_pauseparam() with mutex.
+    - net: lantiq: Wake TX queue again
+    - net: lantiq: use netif_tx_napi_add() for TX NAPI
+    - net: lantiq: Use napi_complete_done()
+    - net: lantiq: Disable IRQs only if NAPI gets scheduled
+    - net: phy: Avoid NPD upon phy_detach() when driver is unbound
+    - net: phy: Do not warn in phy_stop() on PHY_DOWN
+    - net: qrtr: check skb_put_padto() return value
+    - net: add __must_check to skb_put_padto()
+    - mm: memcg: fix memcg reclaim soft lockup
+    - iommu/amd: Use cmpxchg_double() when updating 128-bit IRTE
+    - Linux 5.4.68
+  * *-tools-common packages descriptions have typo "PGKVER" (LP: #1898903)
+    - [Packaging] Fix typo in -tools template s/PGKVER/PKGVER/
+  * tc/ebpf: unable to use BPF_FUNC_skb_change_head (LP: #1896504)
+    - net: bpf: Allow TC programs to call BPF_FUNC_skb_change_head
+  * HP Zbook Studio G7 boots into corrupted screen with PSR featured panel
+    (LP: #1897501)
+    - SAUCE: drm/i915/psr: allow overriding PSR disable param by quirk
+    - SAUCE: drm/dp: add DP_QUIRK_FORCE_PSR_CHIP_DEFAULT quirk to CMN prod-ID
+      19-15
+  * Fix broken e1000e device after S3 (LP: #1897755)
+    - SAUCE: e1000e: Increase polling timeout on MDIC ready bit
+  * debian/rules editconfigs does not work on s390x to change s390x only configs
+    (LP: #1863116)
+    - [Packaging] kernelconfig -- only update/edit configurations on architectures
+      we have compiler support
+  * acpi event detection crashes (LP: #1896482)
+    - ACPI: EC: tweak naming in preparation for GpioInt support
+    - ACPI: EC: add support for hardware-reduced systems
+    - ACPI: EC: Avoid passing redundant argument to functions
+    - ACPI: EC: Consolidate event handler installation code
+  * mwifiex stops working after kernel upgrade (LP: #1897299)
+    - mwifiex: Increase AES key storage size to 256 bits
+  * Remove NVMe suspend-to-idle workaround (LP: #1897227)
+    - Revert "UBUTU: SAUCE: pci: prevent Intel NVMe SSDPEKKF from entering D3"
+    - Revert "UBUNTU: SAUCE: pci: prevent sk hynix nvme from entering D3"
+  * Request for CIFS patches to be available in 5.4 kernel (LP: #1896642)
+    - smb3: remove unused flag passed into close functions
+    - smb3: query attributes on file close
+  * Lenovo ThinkBook 14-IML Touchpad not showing up in /proc/bus/input/devices
+    (LP: #1853277)
+    - i2c: core: Call i2c_acpi_install_space_handler() before
+      i2c_acpi_register_devices()
+  * [Ubuntu 20.10] zPCI DMA tables and bitmap leak on hard unplug (PCI Event
+    0x0304) (LP: #1896216)
+    - s390/pci: fix leak of DMA tables on hard unplug
+  * Thunderbolt3 daisy chain sometimes doesn't work (LP: #1895606)
+    - thunderbolt: Retry DROM read once if parsing fails
+  * btrfs: trimming a btrfs device which has been shrunk previously fails and
+    fills root disk with garbage data (LP: #1896154)
+    - btrfs: trim: fix underflow in trim length to prevent access beyond device
+      boundary
+  * EFA: add support for 0xefa1 devices (LP: #1896791)
+    - RDMA/efa: Expose maximum TX doorbell batch
+    - RDMA/efa: Expose minimum SQ size
+    - RDMA/efa: User/kernel compatibility handshake mechanism
+    - RDMA/efa: Add EFA 0xefa1 PCI ID
+  * Focal update: v5.4.67 upstream stable release (LP: #1896828)
+    - gfs2: initialize transaction tr_ailX_lists earlier
+    - RDMA/bnxt_re: Restrict the max_gids to 256
+    - dsa: Allow forwarding of redirected IGMP traffic
+    - net: handle the return value of pskb_carve_frag_list() correctly
+    - hv_netvsc: Remove "unlikely" from netvsc_select_queue
+    - firmware_loader: fix memory leak for paged buffer
+    - NFSv4.1 handle ERR_DELAY error reclaiming locking state on delegation recall
+    - scsi: pm8001: Fix memleak in pm8001_exec_internal_task_abort
+    - scsi: libfc: Fix for double free()
+    - scsi: lpfc: Fix FLOGI/PLOGI receive race condition in pt2pt discovery
+    - regulator: pwm: Fix machine constraints application
+    - spi: spi-loopback-test: Fix out-of-bounds read
+    - NFS: Zero-stateid SETATTR should first return delegation
+    - SUNRPC: stop printk reading past end of string
+    - rapidio: Replace 'select' DMAENGINES 'with depends on'
+    - cifs: fix DFS mount with cifsacl/modefromsid
+    - openrisc: Fix cache API compile issue when not inlining
+    - nvme-fc: cancel async events before freeing event struct
+    - nvme-rdma: cancel async events before freeing event struct
+    - nvme-tcp: cancel async events before freeing event struct
+    - block: only call sched requeue_request() for scheduled requests
+    - f2fs: fix indefinite loop scanning for free nid
+    - f2fs: Return EOF on unaligned end of file DIO read
+    - i2c: algo: pca: Reapply i2c bus settings after reset
+    - spi: Fix memory leak on splited transfers
+    - KVM: MIPS: Change the definition of kvm type
+    - clk: davinci: Use the correct size when allocating memory
+    - clk: rockchip: Fix initialization of mux_pll_src_4plls_p
+    - ASoC: qcom: Set card->owner to avoid warnings
+    - ASoC: qcom: common: Fix refcount imbalance on error
+    - powerpc/book3s64/radix: Fix boot failure with large amount of guest memory
+    - ASoC: meson: axg-toddr: fix channel order on g12 platforms
+    - Drivers: hv: vmbus: hibernation: do not hang forever in vmbus_bus_resume()
+    - scsi: libsas: Fix error path in sas_notify_lldd_dev_found()
+    - arm64: Allow CPUs unffected by ARM erratum 1418040 to come in late
+    - Drivers: hv: vmbus: Add timeout to vmbus_wait_for_unload
+    - perf test: Fix the "signal" test inline assembly
+    - MIPS: SNI: Fix MIPS_L1_CACHE_SHIFT
+    - perf evlist: Fix cpu/thread map leak
+    - perf parse-event: Fix memory leak in evsel->unit
+    - perf test: Free formats for perf pmu parse test
+    - fbcon: Fix user font detection test at fbcon_resize().
+    - MIPS: SNI: Fix spurious interrupts
+    - drm/mediatek: Add exception handing in mtk_drm_probe() if component init
+      fail
+    - drm/mediatek: Add missing put_device() call in mtk_hdmi_dt_parse_pdata()
+    - arm64: bpf: Fix branch offset in JIT
+    - iommu/amd: Fix potential @entry null deref
+    - i2c: mxs: use MXS_DMA_CTRL_WAIT4END instead of DMA_CTRL_ACK
+    - riscv: Add sfence.vma after early page table changes
+    - drm/i915: Filter wake_flags passed to default_wake_function
+    - USB: quirks: Add USB_QUIRK_IGNORE_REMOTE_WAKEUP quirk for BYD zhaoxin
+      notebook
+    - USB: UAS: fix disconnect by unplugging a hub
+    - usblp: fix race between disconnect() and read()
+    - i2c: i801: Fix resume bug
+    - Revert "ALSA: hda - Fix silent audio output and corrupted input on MSI
+      X570-A PRO"
+    - ALSA: hda: fixup headset for ASUS GX502 laptop
+    - ALSA: hda/realtek - The Mic on a RedmiBook doesn't work
+    - percpu: fix first chunk size calculation for populated bitmap
+    - Input: trackpoint - add new trackpoint variant IDs
+    - Input: i8042 - add Entroware Proteus EL07R4 to nomux and reset lists
+    - serial: 8250_pci: Add Realtek 816a and 816b
+    - x86/boot/compressed: Disable relocation relaxation
+    - s390/zcrypt: fix kmalloc 256k failure
+    - ehci-hcd: Move include to keep CRC stable
+    - powerpc/dma: Fix dma_map_ops::get_required_mask
+    - selftests/vm: fix display of page size in map_hugetlb
+    - dm/dax: Fix table reference counts
+    - mm/memory_hotplug: drain per-cpu pages again during memory offline
+    - dm: Call proper helper to determine dax support
+    - dax: Fix compilation for CONFIG_DAX && !CONFIG_FS_DAX
+    - Linux 5.4.67
+  * Focal update: v5.4.67 upstream stable release (LP: #1896828) // Cherry Pick
+    needed for Critical upstream patch for Kernel null pointer dereference -
+    usb-c altmode (LP: #1897963)
+    - usb: typec: ucsi: Prevent mode overrun
+  * Focal update: v5.4.66 upstream stable release (LP: #1896824)
+    - ARM: dts: logicpd-torpedo-baseboard: Fix broken audio
+    - ARM: dts: logicpd-som-lv-baseboard: Fix broken audio
+    - ARM: dts: logicpd-som-lv-baseboard: Fix missing video
+    - regulator: push allocation in regulator_ena_gpio_request() out of lock
+    - regulator: remove superfluous lock in regulator_resolve_coupling()
+    - ARM: dts: socfpga: fix register entry for timer3 on Arria10
+    - ARM: dts: ls1021a: fix QuadSPI-memory reg range
+    - ARM: dts: imx7ulp: Correct gpio ranges
+    - RDMA/rxe: Fix memleak in rxe_mem_init_user
+    - RDMA/rxe: Drop pointless checks in rxe_init_ports
+    - RDMA/rxe: Fix panic when calling kmem_cache_create()
+    - RDMA/bnxt_re: Do not report transparent vlan from QP1
+    - drm/sun4i: add missing put_device() call in sun8i_r40_tcon_tv_set_mux()
+    - arm64: dts: imx8mq: Fix TMU interrupt property
+    - drm/sun4i: Fix dsi dcs long write function
+    - iio: adc: mcp3422: fix locking on error path
+    - iio: adc: mcp3422: fix locking scope
+    - scsi: libsas: Set data_dir as DMA_NONE if libata marks qc as NODATA
+    - RDMA/core: Fix reported speed and width
+    - scsi: megaraid_sas: Don't call disable_irq from process IRQ poll
+    - scsi: mpt3sas: Don't call disable_irq from IRQ poll handler
+    - soundwire: fix double free of dangling pointer
+    - drm/sun4i: backend: Support alpha property on lowest plane
+    - drm/sun4i: backend: Disable alpha on the lowest plane on the A20
+    - mmc: sdhci-acpi: Clear amd_sdhci_host on reset
+    - mmc: sdhci-msm: Add retries when all tuning phases are found valid
+    - spi: stm32: Rate-limit the 'Communication suspended' message
+    - nvme-fabrics: allow to queue requests for live queues
+    - spi: stm32: fix pm_runtime_get_sync() error checking
+    - block: Set same_page to false in __bio_try_merge_page if ret is false
+    - IB/isert: Fix unaligned immediate-data handling
+    - ARM: dts: bcm: HR2: Fixed QSPI compatible string
+    - ARM: dts: NSP: Fixed QSPI compatible string
+    - ARM: dts: BCM5301X: Fixed QSPI compatible string
+    - arm64: dts: ns2: Fixed QSPI compatible string
+    - ARC: HSDK: wireup perf irq
+    - dmaengine: acpi: Put the CSRT table after using it
+    - netfilter: conntrack: allow sctp hearbeat after connection re-use
+    - drivers/net/wan/lapbether: Added needed_tailroom
+    - NFC: st95hf: Fix memleak in st95hf_in_send_cmd
+    - firestream: Fix memleak in fs_open
+    - ALSA: hda: Fix 2 channel swapping for Tegra
+    - ALSA: hda/tegra: Program WAKEEN register for Tegra
+    - drivers/dma/dma-jz4780: Fix race condition between probe and irq handler
+    - net: hns3: Fix for geneve tx checksum bug
+    - xfs: fix off-by-one in inode alloc block reservation calculation
+    - drivers/net/wan/lapbether: Set network_header before transmitting
+    - cfg80211: Adjust 6 GHz frequency to channel conversion
+    - xfs: initialize the shortform attr header padding entry
+    - irqchip/eznps: Fix build error for !ARC700 builds
+    - nvmet-tcp: Fix NULL dereference when a connect data comes in h2cdata pdu
+    - nvme-fabrics: don't check state NVME_CTRL_NEW for request acceptance
+    - nvme: have nvme_wait_freeze_timeout return if it timed out
+    - nvme-tcp: serialize controller teardown sequences
+    - nvme-tcp: fix timeout handler
+    - nvme-tcp: fix reset hang if controller died in the middle of a reset
+    - nvme-rdma: serialize controller teardown sequences
+    - nvme-rdma: fix timeout handler
+    - nvme-rdma: fix reset hang if controller died in the middle of a reset
+    - nvme-pci: cancel nvme device request before disabling
+    - HID: quirks: Set INCREMENT_USAGE_ON_DUPLICATE for all Saitek X52 devices
+    - HID: microsoft: Add rumble support for the 8bitdo SN30 Pro+ controller
+    - drivers/net/wan/hdlc_cisco: Add hard_header_len
+    - HID: elan: Fix memleak in elan_input_configured
+    - ARC: [plat-hsdk]: Switch ethernet phy-mode to rgmii-id
+    - cpufreq: intel_pstate: Refuse to turn off with HWP enabled
+    - cpufreq: intel_pstate: Fix intel_pstate_get_hwp_max() for turbo disabled
+    - arm64/module: set trampoline section flags regardless of
+      CONFIG_DYNAMIC_FTRACE
+    - ALSA: hda: hdmi - add Rocketlake support
+    - ALSA: hda: fix a runtime pm issue in SOF when integrated GPU is disabled
+    - drm/amdgpu: Fix bug in reporting voltage for CIK
+    - iommu/amd: Do not use IOMMUv2 functionality when SME is active
+    - gcov: Disable gcov build with GCC 10
+    - iio: adc: ti-ads1015: fix conversion when CONFIG_PM is not set
+    - iio: cros_ec: Set Gyroscope default frequency to 25Hz
+    - iio:light:ltr501 Fix timestamp alignment issue.
+    - iio:proximity:mb1232: Fix timestamp alignment and prevent data leak.
+    - iio:accel:bmc150-accel: Fix timestamp alignment and prevent data leak.
+    - iio:adc:ti-adc084s021 Fix alignment and data leak issues.
+    - iio:adc:ina2xx Fix timestamp alignment issue.
+    - iio:adc:max1118 Fix alignment of timestamp and data leak issues
+    - iio:adc:ti-adc081c Fix alignment and data leak issues
+    - iio:magnetometer:ak8975 Fix alignment and data leak issues.
+    - iio:light:max44000 Fix timestamp alignment and prevent data leak.
+    - iio:chemical:ccs811: Fix timestamp alignment and prevent data leak.
+    - iio: accel: kxsd9: Fix alignment of local buffer.
+    - iio:accel:mma7455: Fix timestamp alignment and prevent data leak.
+    - iio:accel:mma8452: Fix timestamp alignment and prevent data leak.
+    - staging: wlan-ng: fix out of bounds read in prism2sta_probe_usb()
+    - btrfs: require only sector size alignment for parent eb bytenr
+    - btrfs: fix lockdep splat in add_missing_dev
+    - btrfs: fix wrong address when faulting in pages in the search ioctl
+    - kobject: Restore old behaviour of kobject_del(NULL)
+    - regulator: push allocation in regulator_init_coupling() outside of lock
+    - regulator: push allocations in create_regulator() outside of lock
+    - regulator: push allocation in set_consumer_device_supply() out of lock
+    - regulator: plug of_node leak in regulator_register()'s error path
+    - regulator: core: Fix slab-out-of-bounds in regulator_unlock_recursive()
+    - scsi: target: iscsi: Fix data digest calculation
+    - scsi: target: iscsi: Fix hang in iscsit_access_np() when getting
+      tpg->np_login_sem
+    - drm/i915/gvt: do not check len & max_len for lri
+    - drm/tve200: Stabilize enable/disable
+    - drm/msm: Disable preemption on all 5xx targets
+    - mmc: sdio: Use mmc_pre_req() / mmc_post_req()
+    - mmc: sdhci-of-esdhc: Don't walk device-tree on every interrupt
+    - rbd: require global CAP_SYS_ADMIN for mapping and unmapping
+    - RDMA/rxe: Fix the parent sysfs read when the interface has 15 chars
+    - RDMA/mlx4: Read pkey table length instead of hardcoded value
+    - fbcon: remove soft scrollback code
+    - fbcon: remove now unusued 'softback_lines' cursor() argument
+    - vgacon: remove software scrollback support
+    - [Config] updateconfigs for VGACON_SOFT_SCROLLBACK
+    - KVM: VMX: Don't freeze guest when event delivery causes an APIC-access exit
+    - KVM: arm64: Do not try to map PUDs when they are folded into PMD
+    - KVM: fix memory leak in kvm_io_bus_unregister_dev()
+    - debugfs: Fix module state check condition
+    - ARM: dts: vfxxx: Add syscon compatible with OCOTP
+    - video: fbdev: fix OOB read in vga_8planes_imageblit()
+    - staging: greybus: audio: fix uninitialized value issue
+    - phy: qcom-qmp: Use correct values for ipq8074 PCIe Gen2 PHY init
+    - usb: core: fix slab-out-of-bounds Read in read_descriptors
+    - USB: serial: ftdi_sio: add IDs for Xsens Mti USB converter
+    - USB: serial: option: support dynamic Quectel USB compositions
+    - USB: serial: option: add support for SIM7070/SIM7080/SIM7090 modules
+    - usb: Fix out of sync data toggle if a configured device is reconfigured
+    - usb: typec: ucsi: acpi: Check the _DEP dependencies
+    - drm/msm/gpu: make ringbuffer readonly
+    - drm/msm: Disable the RPTR shadow
+    - gcov: add support for GCC 10.1
+    - Linux 5.4.66
+
+  [ Ubuntu: 5.4.0-54.60 ]
+
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+  * Introduce the new NVIDIA 455 series (LP: #1902093)
+    - [Packaging] NVIDIA -- Add the NVIDIA 455 driver
+
+  [ Ubuntu: 5.4.0-53.59 ]
+
+  * CVE-2020-8694
+    - powercap: make attributes only readable by root
+
+ -- Hsuan-Yu Lin <shane.lin@canonical.com>  Sat, 28 Aug 2021 17:07:02 +0800
+
+linux-xilinx-zynqmp (5.4.0-1015.18) focal; urgency=medium
+
+  * INVALID or PRIVATE BUG (LP: #1931882)
+    - SAUCE: move zocl_ioctl.h to include/drm
+
+ -- Hsuan-Yu Lin <shane.lin@canonical.com>  Tue, 13 Jul 2021 14:08:18 +0800
+
+linux-xilinx-zynqmp (5.4.0-1014.16) focal; urgency=medium
+
+  * Define suspend/resume wake up sources (LP: #1921001)
+    - [Config] Enable keyboard drive
+
+  * Kernel config review (LP: #1925667)
+    - [Config] Disable CONFIG_ARM_PSCI_CPUIDLE
+
+  * Update kernel config for Xilinx SOM (LP: #1927147)
+    - [Config] Support for Xilinx SOM
+
+  * Import changes from Xilinx new kernel release (LP: #1928298)
+    - [Config] Update kernel configs to Xilinx rebase 5.4 branch
+
+  * Enable kernel debug features (LP: #1917874)
+    - [Config] enable kernel features for debug
+
+  * Fixes for wake from USB (LP: #1932244)
+    - usb: dwc3: Corrected wake up capability conditional check for board specific
+    - usb: dwc3: Disable phy suspend after power-on reset
+
+  * Publish zocl ioctl header file (LP: #1931882)
+    - SAUCE: move zynq_ioctl.h to include/drm
+
+  * Miscellaneous upstream changes
+    - mtd: spi-nor: Fix call trace when qspi driver built as module
+    - iio: adc: versal-sysmon: Additional documentation for production silicon
+      support.
+    - spi: spi-zynqmp-gqspi: Avoid multiple writes to tapdelay registers
+    - dt-bindings: regulator: DA9121: Add DA9121 bindings
+    - drivers: regulator: Add driver for DA9121 family of devices
+    - regulator: da9121: Add details for da9121
+    - regulator: da9121: Use gpio descriptors instead of numbers
+    - regulator: da9121: Use core regulator lock
+    - regulator: da9121: Modify the variant code as per hardware
+    - regulator: da9121: Fix coding style issues
+    - arm64: xilinx: Enable TPM for xilinx platforms
+    - arm64: xilinx: Enable DA9121 regulator driver
+    - dt-bindings: iio: adc: Add ti,ina260.yaml
+    - drivers: iio: Add support for TI INA260 power monitors
+    - arm64: xilinx: Enable INA260 IIO driver
+    - regulator: da9121: Init regmap to avoid compilation warning
+    - dt-bindings: usb: misc: Add binding for Microchip usb5744 hub
+    - usb: misc: usb5744: add support for USB hub controller
+    - xilinx: Enable USB hub driver for 5744
+    - pinctrl: core: Handling pinmux and pinconf separately
+    - crypto: aes: zynqmp: Remove carriage return from one print
+    - drm: xlnx: zynqmp_dp: Fix possible crtc searching
+    - drm/of: Correct documentation for drm_of_find_possible_crtcs()
+    - drm: xlnx: zynqmp: Only register DP CRTC if there is no other CRTC
+    - drm: xlnx: mixer: Add port OF node to DRM CRTC
+    - drm: xlnx: zynqmp_disp: Move live bridges registration to probe
+    - drm: xlnx: zynqmp_disp: Move bridge functions
+    - drm: xlnx: zynqmp_disp: Enable DP encoder during bridge enable
+    - drm: xlnx: zynqmp_disp: Force alpha to 0 when external CRTC used
+    - drm: xlnx: zynqmp: Ignore DP vblank interrupts if external CRTC used
+    - drm: xlnx: zynqmp_disp: Fix live format config
+    - drm: xlnx: zynqmp_disp: Add set_timing support for live bridge
+    - drm: xlnx: mixer: Print out mixer CRTC id
+    - drm: xlnx: mixer: Add DP live bridge support
+    - arm64: xilinx: Enable VTC bridge for xilinx platforms
+    - drm: xlnx: zynqmp_disp: Add VTC bridge support
+    - arm64: zynqmp: Label DP layers by default
+    - drm: xlnx: zynqmp_dpsub: Only init drm master when DP CRTC used
+    - media: uapi: Add an entity type for Image Signal Processors
+    - media: dt-bindings: media: i2c: Add bindings for AP1302
+    - media: i2c: Add ON Semiconductor AP1302 ISP driver
+    - media: i2c: ap1302: Add NV12 format support
+    - media: i2c: ap1302: Update yuv420 to xilinx NV12 media bus format
+    - arm64: xilinx: config: Enable ap1302 ISP driver
+    - dt: bindings: sound: Add DT bindings for new compatible strings
+    - sound: xilinx: pcm: Assign device name per compatible string
+    - arm64: zynqmp: Use new compatible strings for DP snd pcm
+    - drm: xlnx: zynqmp_dpsub: Pass pcm auxdata when populating sound nodes
+    - drm: xlnx: zynqmp_disp: Release VTC bridge in unbind stage
+    - media: i2c: ap1302: Update MIPI TCLK POST and PRE timing values
+    - media: i2c: ap1302: Add debugfs entry for MIPI TCLK timings
+    - media: i2c: ap1302: Increase MIPI TCLK POST timing value
+    - dt-bindings: soc: xilinx: Add optional property to vcu
+    - soc: xilinx: vcu: update gasket isolation
+    - drm: xlnx: zynqmp_dp: fix suspend/resume issue
+    - net: macb: Add ethtool support to advertise WOL
+    - arm64: xilinx: Enable keyboard driver
+    - arm64: xilinx: Enable Xilinx Synchronizer driver
+    - xilinx: defconfig: Enable mulitple sensor drivers
+
+ -- Wen-chien Jesse Sung <jesse.sung@canonical.com>  Wed, 23 Jun 2021 22:56:41 +0800
+
+linux-xilinx-zynqmp (5.4.0-1013.14) focal; urgency=medium
+
+  * INVALID or PRIVATE BUG (LP: #1925667)
+    - [Config] Update configs for ZynqMP platform
+
+  * INVALID or PRIVATE BUG (LP: #1905563)
+    - [Config] Enable CONFIG_FPGA_MGR_DEBUG_FS
+
+  * INVALID or PRIVATE BUG (LP: #1922906)
+    - [Config] Enable kernel configs for Xilinx AXI4-Stream Video Broadcaster
+
+  * Miscellaneous upstream changes
+    - dt: bindings: media: xilinx: Doc for Xilinx AXI4-Stream Broadcaster driver
+    - v4l: xilinx: Driver support for Xilinx AXI4-Stream Broadcaster
+    - arm64: xilinx: Enable Xilinx AXI4-Stream Video Broadcaster
+
+ -- Hsuan-Yu Lin <shane.lin@canonical.com>  Tue, 11 May 2021 11:49:50 +0800
+
+linux-xilinx-zynqmp (5.4.0-1012.13) focal; urgency=medium
+
+  * INVALID or PRIVATE BUG (LP: #1920935)
+    - [Config] Enable kernel configs for CONFIG_KEYBOARD_GPIO
+
+ -- Hsuan-Yu Lin <shane.lin@canonical.com>  Thu, 01 Apr 2021 17:39:11 +0800
+
+linux-xilinx-zynqmp (5.4.0-1011.12) focal; urgency=medium
+
+  * INVALID or PRIVATE BUG (LP: #1920935)
+    - [Config] Enable kernel configs for required devices
+
+ -- Hsuan-Yu Lin <shane.lin@canonical.com>  Mon, 29 Mar 2021 14:02:48 +0800
+
+linux-xilinx-zynqmp (5.4.0-1010.11) focal; urgency=medium
+
+  * INVALID or PRIVATE BUG (LP: #1917886)
+    - [Config] Enable kernel configs for lxd
+
+  * INVALID or PRIVATE BUG (LP: #1917874)
+    - [Config] Enable Kprobes
+
+  * INVALID or PRIVATE BUG (LP: #1916027)
+    - XRT driver version update to 2.8.0
+
+  * INVALID or PRIVATE BUG (LP: #1905326)
+    - drm: xlnx: zynqmp_dp: Fix DP link train issue
+
+ -- Hsuan-Yu Lin <shane.lin@canonical.com>  Mon, 22 Mar 2021 09:59:47 +0800
+
+linux-xilinx-zynqmp (5.4.0-1009.10) focal; urgency=medium
+
+  * INVALID or PRIVATE BUG (LP: #1906202)
+    - [Config] Enable CONFIG_CGROUP_DEBUG
+
+  * Miscellaneous upstream changes
+    - arm64: xilinx: Enable IDT8T49N24x clock driver
+    - mmc: arasan: Fix the issue in reading tap values from DT
+
+ -- Hsuan-Yu Lin <shane.lin@canonical.com>  Thu, 28 Jan 2021 16:16:33 +0800
+
+linux-xilinx-zynqmp (5.4.0-1008.9) focal; urgency=medium
+
+  * cloud-config.service is blocked by snapd.seeded.service (LP: #1912476)
+    - [Config] update configs for snapd
+
+ -- Hsuan-Yu Lin <shane.lin@canonical.com>  Wed, 27 Jan 2021 17:34:38 +0800
+
+linux-xilinx-zynqmp (5.4.0-1007.8) focal; urgency=medium
+
+  * cloud-config.service is blocked by snapd.seeded.service (LP: #1912476
+    - [Config] update configs for snapd
+
+  * rename kernel debian packages (LP: #1904136
+    - [Packaging] rename the package as linux-xilinx-zynqmp
+
+  * INVALID or PRIVATE BUG (LP: #1912352)
+    - Import XRT 2020.2 kernel modules
+    - Fix XRT 2020.2 build error
+
+  * Miscellaneous upstream changes
+    - watchdog: of_xilinx_wdt: Use a proper variable to handle overflow
+    - watchdog: of_xilinx_wdt: Remove passing null pointer
+    - drm: xlnx: zynqmp: Use switch - case for link rate downshift
+    - drm: xlnx: mixer: Fix async update kernel warning
+    - dt-bindings: display: xlnx: mixer: Updated layer max height and width ranges
+    - misc: xilinx-ai-engine: replace u32 with __u32 in ioctl struct
+    - misc: xilinx-ai-engine: use correct printk formats
+    - misc: xilinx-ai-engine: include stdlib.h for size_t in uapi header
+    - misc: xilinx-ai-engine: use IS_ENABLED() compile guard
+    - arm64: xilinx: Enable xilinx PCS/PMA phy driver
+    - clk: zynq: Update the parameters to zynq_clk_register_periph_clk
+    - dt-bindings: media: xilinx: csi2rxss: Add YUV 420 8bits support
+    - v4l: xilinx: xcsi2rxss: Add support for YUV420 8bpc
+    - dt-bindings: dma: xilinx_frmbuf: Fix Y10 v4l2 pixel format
+    - dmaengine: xilinx: frmbuf: Fix Y10 v4l2 pixel format
+    - v4l: xilinx: vipp: Perform stream start/stop at pipeline level
+    - v4l: xilinx: vipp: remove unused variable
+    - v4l: xilinx: dma: Remove struct xventity_list
+    - net: emaclite: Add variable and conditions to check the return value
+    - misc: xilinx-ai-engine: gate columns first in partition reset
+    - iio: Fixed IIO_VAL_FRACTIONAL calculation for negative values
+    - v4l: xilinx: xcsi2rxss: Add YUV 420 video format code
+    - dt-bindings: display: xlnx: sdi: Add gpio reset
+    - drm: xlnx: sdi: Add GT and picxo cores reset through gpio
+    - misc: xilinx-ai-engine: add set/clear and test bit for resource function
+    - misc: xilinx-ai-engine: add scan and set clocks implementation
+    - misc: xilinx-ai-engine: add clock scanning when requesting partition and
+      tiles requesting
+    - dt-bindings: iio: xilinx: Add Documentation for Sysmon
+    - iio: versal-sysmon: add driver for Versal Sysmon
+    - arm64: xilinx: Added sysmon driver for versal
+    - dt-bindings: display: xlnx: Add DisplayPort Tx bindings
+    - drm: xlnx: dptx: Add DisplayPort tx driver
+    - arm64: xilinx: Enable the DP TX drm driver
+    - drm: xlnx: sdi: Add clock config to support integer and fractional framerate
+    - v4l: xilinx: multi-scaler: Fix warnings for UNUSED_VALUE
+    - v4l: xilinx: multi-scaler: Fix warnings for MIXED_ENUM_TYPE
+    - v4l: xilinx: multi-scaler: Fix warnings for INCOMPATIBLE_PARAM
+    - v4l: xilinx: multi-scaler: Fix warnings for NULL_RETURNS
+    - v4l: xilinx: vip: Fix V4L2_PIX_FMT_XY10 bpl_factor
+    - misc: xilinx-ai-engine: rename ai-engine-v1
+    - spi: spi-zynq-qspi: Check return value of clk_enable api
+    - spi: spi-zynq-qspi: Simplify logic for slave select
+    - misc: xilinx-ai-engine: add ioctl to pass dmabuf fd to set shimdma bd
+    - usb: chipidea: Fix return value handling
+    - usb: chipidea: core: Add return value function check
+    - usb: phy: Add NULL checks for return type function
+    - v4l: xilinx: sdirxss: Decode EOTF from ST352 payload
+    - v4l: xilinx: vpss-scaler: Fix the compatible string deprecated message
+    - v4l: xilinx: multi-scaler: Derive the caps from video device node
+    - v4l: xilinx: multi-scaler: Added streaming capabilities to device
+    - drm: xlnx: pl_disp: Release DMA when probe deferred
+    - v4l: xilinx: sdirxss: Decode colorimetry from ST352
+    - media: videodev2.h: add Hybrid Log Gamma transfer function define
+    - v4l: xilinx: sdirxss: Update the xfer_func
+    - v4l: xilinx: sdirxss: Update the ycbcr_enc
+    - v4l: xilinx: sdirxss: Update the quantization
+    - v4l: xilinx: axis-switch: Remove an invalid if check condition
+    - v4l: xilinx: m2m: Remove an unused variable
+    - v4l: xilinx: scaler: Set the pm ops
+    - dt-bindings: fpga: Add compatible value for Xilinx DFX AXI shutdown manger
+    - fpga: Add support for Xilinx DFX AXI Shutdown manager
+    - PCI: xdma: Use unique name for pci-xdma-pl.c
+    - xilinx: Enable several xilinx drivers
+    - misc: xilinx-ai-engine: fix scanning gated tiles logic
+    - ASoC: xlnx: Decouple sound card config dependency form all interfaces
+    - v4l: xilinx: vip: Fix CHECKED_RETURN warnings
+    - v4l: xilinx: vip: Fix UNINIT warnings
+    - v4l: xilinx: dma: Fix OVERFLOW_BEFORE_WIDEN warnings
+    - v4l: xilinx: dma: Fix PW.INCOMPATIBLE_PARAM warnings
+    - v4l: xilinx: dma: Fix UININT warnings
+    - v4l: xilinx: dma: Fix INFINITE_LOOP warning
+    - firmware: xilinx: sync firmware pm_query_id entries with PLM query id
+      entries
+    - i2c: xiic: Add wait for FIFO empty in send_tx
+    - i2c: xiic: Use 'nmsgs' variable instead of repeated_start
+    - i2c: xiic: Add smbus_block_read functionality
+    - arm64: xilinx: Added ubifs support
+    - misc: xilinx-ai-engine: Add support to request device management services
+    - dt-bindings: soc: xilinx: ai-engine: Add interrupt and power-domain
+      properties for AIE device
+    - misc: xilinx-ai-engine: Add helper functions to service interrupt
+      controllers and event registers
+    - firmware: xilinx: Add IOCTL support for AIE ISR Clear
+    - misc: xilinx-ai-engine: Add support for servicing error interrupts
+    - misc: xilinx-ai-engine: Log error events and classify them into categories
+    - misc: xilinx-ai-engine: Add APIs for kernel modules to handle error
+      interrupts
+    - dt-bindings: soc: xilinx: ai-engine: Add 64bit bus to example
+    - misc: xilinx-ai-engine: add tiles in use bitmap
+    - watchdog: of_xilinx_wdt: Skip printing pointer value
+    - watchdog: of_xilinx_wdt: Add interrupt and pretimeout properties for Versal
+      watchdog
+    - watchdog: of_xilinx_wdt: Add Versal Window watchdog support
+    - misc: xilinx-ai-engine: avoid creating multiple dmabufs for AIE mems
+    - misc: xilinx-ai-engine: Add AI engine partition reset function
+    - misc: xilinx-ai-engine: Add extern functions to reset partition
+    - memory: pl353: Fixed incompatible assignment
+    - mtd: rawnand: pl353: Removed unused variable
+    - mtd: rawnand: pl353: Initialized variable before using it
+    - misc: xilinx-ai-engine: remove unnecessary print
+    - misc: xilinx-ai-engine: fix PTR_ERR warning
+    - arm64: xilinx: zynqmp: Enable missed fbdev config during migration
+    - drm: xlnx: dsi: Add Generic long write command support
+    - reset: reset-zynqmp: Fixed the argument data type
+    - firmware: xilinx: Updated the reset function prototypes
+    - edac: synopsys: Fix the wrong value assignment for edac_mode
+    - misc: xilinx-ai-engine: Add function to clear an AI engine resource
+    - misc: xilinx-ai-engine: update reset API to use resource clear all function
+    - misc: xilinx-ai-engine: clear cached events of partition in reset/release
+    - dt-bindings: edac: Add bindings for Xilinx Versal EDAC for DDRMC
+    - edac: xilinx: Added EDAC support for Xilinx DDR controller
+    - arm64: xilinx: Enable Xilinx Versal DDR EDAC support
+    - net: xilinx: axiethernet: Pass phy interface to of_phy_connect()
+    - net: xilinx: Use prandom with range to avoid corner cases
+    - net: xilinx: XXV Ethernet HW timestamp fixes
+    - dt-bindings: net: Add devicetree documentation for MRMAC
+    - net: xilinx: Add MRMAC support
+    - dt-bindings: Add devicetree documentation for Xilinx PTP timer
+    - ptp: Add Xilinx PTP timer driver
+    - net: xilinx: Add HW timestamping support for MRMAC
+    - net: xilinx: Add missing kernel-doc descriptions
+    - can: xilinx_can: avoid non-requested bus error frames
+    - can: xilinx_can: fix checkpatch warnings
+    - drm: xlnx: bridge: Fix UNUSED_VALUE type warning
+    - drm: xlnx: bridge: Fix UNINIT type warnings
+    - drm: xlnx: bridge: Fix RESOURCE_LEAK type warning
+    - drm: xlnx: bridge: Fix PW.PARAMETER_HIDDEN type warning
+    - drm: xlnx: bridge: Fix NULL_RETURNS type warning
+    - drm: xlnx: fb: Fix OVERFLOW_BEFORE_WIDEN type warnings
+    - v4l: xilinx: xcsi2rxss: Fix warnings for NULL_RETURNS
+    - v4l: xilinx: sdirxss: Fix warnings for UNUSED_VALUE
+    - v4l: xilinx: sdirxss: Fix warnings for CONSTANT_EXPRESSION_RESULT
+    - v4l: xilinx: sdirxss: Fix warnings for NULL_RETURNS
+    - v4l: xilinx-demosaic: Fix warnings for NULL_RETURNS
+    - v4l: xilinx-demosaic: Fix for warning UNUSED_VALUE
+    - media: xilinx: vtc: Fix warning for OVERFLOW_BEFORE_WIDEN
+    - v4l: xilinx: tpg: Fix warnings for NULL_RETURNS
+    - v4l: xilinx: tpg: Fix warnings for CHECKED_RETURN
+    - v4l: xilinx: vpss-scaler: Fix warnings for NULL_RETURNS
+    - v4l: xilinx: vpss-scaler: Fix warnings for UNINIT
+    - v4l: xilinx: vpss-csc: Fix warnings for NULL_RETURNS
+    - v4l: xilinx: vpss-csc: Fix warning for UNINIT
+    - v4l: xilinx: vpss-csc: Fix warning for PW.MIXED_ENUM_TYPE
+    - v4l: xilinx: axis-switch: Fix warnings for NULL_RETURNS
+    - v4l: xilinx: axis-switch: Fix warnings for UNINIT
+    - v4l: xilinx-gamma: Fix warnings for NULL_RETURNS
+    - v4l: xilinx-gamma: Fix warnings for UNUSED_VALUE
+    - v4l: xilinx: cfa: Fix warnings for NULL_RETURNS
+    - v4l: xilinx: cresample: Fix warnings for NULL_RETURNS
+    - v4l: xilinx: dprx: Fix warnings for NULL_RETURNS
+    - v4l: xilinx: dprx: Fix warnings for UNINIT
+    - media: xilinx: hls: Fix warnings for NULL_RETURNS
+    - v4l: xilinx: remapper: Fix warning for UNINIT
+    - v4l: xilinx: remapper: Fix warnings for NULL_RETURNS
+    - v4l: xilinx: remapper: Fix warnings for CHECKED_RETURN
+    - v4l: xilinx: rgb2yuv: Fix warnings for NULL_RETURNS
+    - v4l: xilinx: scaler: Fix warnings for NULL_RETURNS
+    - v4l: xilinx: switch: Fix warnings for NULL_RETURNS
+    - v4l: xilinx: switch: Fix warnings for UNINIT
+    - v4l: xilinx: switch: Fix warnings for OVERFLOW_BEFORE_WIDEN
+    - dmaengine: xilinx: frmbuf: Fix warnings for PW.MIXED_ENUM_TYPE
+    - dmaengine: xilinx: frmbuf: Fix warnings for UNINIT
+    - misc: xilinx-ai-engine: Add error category to the AIE error struct
+    - misc: xilinx-ai-engine: use error category property in get errors categories
+    - misc: xilinx-ai-engine: Add errors categories masks macro
+    - dt-bindings: serial: Add xilinx compatible
+    - tty: pl011: Add support for xilinx uart
+    - ASoC: xlnx: formatter: Fix warnings for PW.SET_BUT_NOT_USED
+    - ASoC: xlnx: formatter: Fix warnings for NULL_RETURNS
+    - ASoC: xlnx: formatter: Fix warnings for UNINIT
+    - ASoC: xlnx: formatter: Fix warnings for UNUSED_VALUE
+    - ASoC: xlnx: formatter: Fix warnings for PW.SET_BUT_NOT_USED
+    - ASoC: xlnx: i2s: Fix warnings for UNINIT
+    - ASoC: xlnx: spdif: Fix warnings for PW.SET_BUT_NOT_USED
+    - ASoC: xlnx: sdiaudio: Fix warnings for PW.SET_BUT_NOT_USED
+    - ASoC: xlnx: sdiaudio: Fix warnings for DEADCODE
+    - drm: xlnx: pl_disp: Fix MIXED_ENUM_TYPE type warning
+    - drm: xlnx: zynqmp_dp: Fix UNINIT type warning
+    - drm: xlnx: zynqmp_dp: Fix CHECKED_RETURN type warnings
+    - drm: xlnx: zynqmp_dp: Fix OVERRUN type warning
+    - drm: xlnx: zynqmp_disp: Fix UNINIT type warning
+    - drm: xlnx: zynqmp_disp: Fix CHECKED_RETURN type warnings
+    - drm: xlnx: zynqmp_disp: Fix OVERFLOW_BEFORE_WIDEN type warnings
+    - drm: xlnx: zynqmp_disp: Fix MIXED_ENUM_TYPE type warnings
+    - net: xilinx: Fix indentation issues
+    - net: xilinx: axiethernet: Add check for transmit data FIFO vacancy
+    - media: videodev2.h: Add control type for HDR
+    - Revert "microblaze: Fix TLB mapping"
+    - pinctrl: zynqmp: Remove unused variable zynqmp_pins
+    - pinctrl: zynqmp: Return 'ret' instead of Success always
+    - pinctrl: zynqmp: Initialize the ret variable with zero
+    - v4l: xilinx: sdirxss: Update HDR control type
+    - drm: xlnx: sdi: Fix dynamic clock config to support QPLL1 reset.
+    - misc: xilinx-ai-engine: Create bitmaps to manage level 2 controller
+    - misc: xilinx-ai-engine: Handle interrupts in kthreads
+    - misc: xilinx-ai-engine: Handle error interrupts for partitions not yet
+      requested
+    - misc: xilinx-ai-engine: Clear broadcast event status
+    - misc: xilinx-ai-engine: Fix for-loop control limits
+    - misc: xilinx-ai-engine: Return NULL if no errors were found
+    - fpga: zynq: Fix incorrect variable type
+    - fpga: zynqmp: Initialized variables before using it
+    - fpga: zynqmp: Fix incorrect variables type
+    - fpga: versal: Initialized variables before using it
+    - i2c-cadence: Check the return value of pin-ctrl
+    - i2c-cadence: Replace the value with enum
+    - i2c-xiic: return value of xiic_reinit
+    - staging: xlnxsync: Remove channel interrupt mask handling at enable/disable
+    - staging: xlnxsync: Add new ioctl to set interrupt mask
+    - staging: xlnxsync: Rename interrupt mask register macro
+    - staging: xlnxsync: Mask the interrupt bit as soon as interrupt occurs
+    - staging: xlnxsync: Switch to rising edge interrupt
+    - staging: xlnxsync: Reset channel error status after it is read
+    - staging: xlnxsync: Unmask the interrupt in clear channel error IOCTL
+    - staging: xlnxsync: Reuse the xlnxsync_err_intr structure
+    - mtd: spi-nor: Fix for setting quad mode on Spansion Flash in dual parallel
+    - v4l: xilinx: sdirxss: Fix colorimetry dectection for HD mode
+    - v4l: xilinx: sdirxss: Update video params when stream changes without unlock
+    - drm: xlnx: sdi: Update EOTF and colorimetry fields in payload.
+    - Revert "mtd: spi-nor: Fix for setting quad mode on Spansion Flash in dual
+      parallel"
+    - mtd: spi-nor: Fix for setting quad mode on Spansion Flash in dual parallel
+    - clk: clock-wizard: Revert "Use all stages of the MMCM"
+    - xilinx: Enable HWMON and PMBUS
+    - mmc: sdhci-of-arasan: Allow configuring zero Tap values
+    - mmc: sdhci-of-arasan: Use Mask writes for Tap delays
+    - mmc: sdhci-of-arasan: Issue DLL reset explicitly
+    - usb: dwc3: otg: Enable OTG support in dwc3-core driver
+    - v4l: xilinx: m2m: Fix spelling of driver model
+    - v4l: xilinx: m2m: Fix kernel crash for async notifier
+    - v4l: xilinx: m2m: Fix kernel crash for link creation to video entity
+    - dt: bindings: media: xilinx: sdirxss : Add optional PICXO gpio handle
+    - v4l: xilinx: sdirxss: Add support for PICXO
+    - dt-bindings: display: xlnx: sdi: Update for PICXO
+    - drm: xlnx: sdi: Add support to non-picxo designs
+    - dmaengine: xilinx: frmbuf: Replace AP_READY with AP_DONE
+    - usb: dwc3: Make dwc3 work with CONFIG_PM disabled
+    - dt-bindings: media: xilinx: Fix compatible string
+    - v4l: xilinx: Fix compatible string
+    - v4l: xilinx: update the bits per component
+    - drm: xlnx: sdi: Add supported EOTF's list to connector.
+    - drm: xlnx: sdi_modes: Updated timing parameters at frame level
+    - drm: xlnx: sdi: Add mode_valid helper function
+    - v4l: xilinx: sdirxss: Fix PLL reference clock to 148.5MHz for SD mode
+    - dt-bindings: display: xlnx: dptx: Fix compatible string and remove Remapper
+    - drm: xlnx: dptx: Fix compilation string and remove AXI Remapper support
+    - drm: xlnx: dptx: Correct FIELD_GET function and fix the training issue
+    - v4l: xilinx: sdirxss: Rate limit irq handler error messages
+    - hdmi-common: Add helpers to parse and generate HDR Aux packets
+    - hdmirxss: Add infra for DRM infoframe reporting
+    - hdmitxss: Add infra for DRM infoframe reporting
+    - hdmirx: Add g_volatile_ctrl handling to v4l subdev
+    - hdmitx: Program Tx with HDR metadata set by user
+    - dp159: Fix probe failure on multi instance load
+    - hdmitx: fix to reset drm metadata type on stream down
+    - hdmi: Report EOTF in the info
+    - hdmi-common: Fix length of HDR payload
+    - hdmitx: Add AR24 and AB24 to list of supported DRM formats
+    - hdmitx: Fix bridge enablement
+    - hdmitx: Add audio register changes in core
+    - hdmirx: Add audio register changes in core
+    - hdmitx: program audio channels based on hw_params
+    - hdmitx: parse and store ELD
+    - hdmirx: Modify EDID for 8 channel
+    - hdmitx: fix coverity warning for CHECKED_RETURN
+    - hdmitx: fix coverity warning for COPY_PASTE_ERROR
+    - hdmitx: Check NULL return on kzalloc in Decrypt()
+    - hdmitx: Fix potential infinite loop error in Decrypt()
+    - hdmitx: Check for null pointer returned by of_match_node()
+    - hdmitx: Fix coverity NULL_RETURNS warning for resource
+    - hdmitx: Fix the coverity warning OVERFLOW_BEFORE_WIDEN
+    - hdmitx: Fix coverity warning type PW.DECLARED_BUT_NOT_REFERNCED
+    - hdmitx : Fix coverity warning of UNINIT type
+    - hdmitx: Fix coverity warning for RESOURCE_LEAK
+    - hdmitx: Fix coverity warnings for typecasting
+    - hdmitx: Fix coverity warning PW.SET_BUT_NOT_USED type
+    - hdmirx: Fix CHECKED_RETURN coverity warning
+    - hdmirx: Fix COPY_PASTE_ERROR coverity warning
+    - hdmirx: Fix INFINITE_LOOP coverity warning
+    - hdmirx: Fix NULL_RETURNS coverity warning
+    - hdmirx: Fix OVERFLOW_BEFORE_WIDEN coverity warning
+    - hdmirx: Fix PW.DECLARED_BUT_NOT_REFERENCED coverity warning
+    - hdmirx: Fix PW.INCOMPATIBLE_PARAM coverity warning
+    - hdmirx: Fix PW.SET_BUT_NOT_USED coverity warning.
+    - hdmirx: Fix UNINIT coverity warning
+    - hdmirx: Fix REVERSE_INULL coverity warning.
+    - hdmirx: Update HDR control type
+    - hdmirx: Set color format based on AVI Infoframe
+    - hdmitx: Set AVI infoframe based on properties set by user
+    - hdmirx: report source change on change in AVI infoframe
+    - Fixes in hdmirx and hdmirxss till 20200921
+    - Fixes in vphy and hdmiphy till 20200921
+    - phy: hdmigtctrl: remove GT workaround on pll type
+    - license: Update the license 2020.2
+    - Add the rc_plugin_fd field
+    - Add __GFP_NOWARN to avoid CMA allocation warnings
+    - Update kernel configs to 2020.2
+    - merge: close
+
+ -- Wen-chien Jesse Sung <jesse.sung@canonical.com>  Thu, 21 Jan 2021 23:16:39 +0800
+
+linux-xilinx-zynqmp (5.4.0-1006.7) focal; urgency=medium
+
+  * System hang with sdhci: ADMA Err while running stress-ng os test // System
+    hang with soft lockup while running cpu stress test // System hang with soft
+    lockup while running warm boot stress test
+    - crypto: zynqmp_sha: Make driver thread-safe
+
+  * System could not be woken up by WOL from S3 or S5
+    - SAUCE: net: macb: Consolidate wakeup settings onto platform device
+
+ -- Hsuan-Yu Lin <shane.lin@canonical.com>  Wed, 13 Jan 2021 14:40:35 +0800
+
+linux-xilinx-zynqmp (5.4.0-1005.6) focal; urgency=medium
+
+  * INVALID or PRIVATE BUG (LP: #1904021)
+    - Enable CONFIG_UBIFS_FS_ADVANCED_COMPR
+
+  * dmatest: write error: Device or resource busy // omx_encoder: DMAMemory:
+    Device or resource busy
+    - [Config] Disable ASYNC and RAID related functions
+
+  * Miscellaneous Ubuntu changes
+    - [Config] Align configs with ZynqMP configs
+    - [Config] Disable DKMS: zfs and wireguard
+    - [Config] Remove unnecessary kernel module names
+
+ -- Hsuan-Yu Lin <shane.lin@canonical.com>  Thu, 26 Nov 2020 16:13:20 +0800
+
+linux-xilinx-zynqmp (5.4.0-1004.5) focal; urgency=medium
+
+  * Miscellaneous upstream changes
+    - Disable CONFIG_VIDEO_ALLEGRO_DVT
+
+ -- Hsuan-Yu Lin <shane.lin@canonical.com>  Thu, 29 Oct 2020 14:44:45 +0800
+
+linux-xilinx-zynqmp (5.4.0-1003.4) focal; urgency=medium
+
+  * Miscellaneous upstream changes
+    - Enable Xilinx HDMI kernel modules
+    - Import Xilinx VCU kernel modules
+    - Enable VCU kernel modules as default
+
+ -- Hsuan-Yu Lin <shane.lin@canonical.com>  Wed, 28 Oct 2020 15:04:36 +0800
+
+linux-xilinx-zynqmp (5.4.0-1002.3) focal; urgency=medium
+
+  * CVE-2020-12351 // CVE-2020-12352 // CVE-2020-24490
+    - [Config] Disable BlueZ highspeed support
+
+  * INVALID or PRIVATE BUG (LP: #1900871)
+    - Remove unnecessary debug messages from zocl
+
+  * Miscellaneous Ubuntu changes
+    - [Config] enable tracing/profiling options
+
+  * Miscellaneous upstream changes
+    - Import Mali source code
+    - Change Makefile to be compatible with Yocto
+    - staging: mali: r8p0-01rel0: Add the ZYNQ/ZYNQMP platform
+    - staging: mali: r8p0-01rel0: Remove unused trace macros
+    - staging: mali: r8p0-01rel0: Don't include mali_read_phys() for zynq/zynqmp
+    - linux/mali_kernel_linux.c: Handle clock when probed and removed
+    - arm.c: global variable dma_ops is removed from the kernel 4.7
+    - common/mali_pm.c: Add PM runtime barrier after removing suspend
+    - linux/mali_kernel_linux.c: Enable/disable clock for runtime resume/suspend
+    - linux: mali_memory_os_alloc: Remove __GFP_COLD
+    - linux: mali_memory_secure: Add header file dma-direct.h
+    - linux: mali_*timer: Get rid of init_timer
+    - Fix driver failed to check map error
+    - mali_memory_secure: Kernel 5.0 onwards 'access_ok' API does not take 'type'
+      as input parameter
+    - Support for vm_insert_pfn deprecated from kernel 4.20
+    - Change return type to vm_fault_t for fault handler
+    - "get_monotonic_boottime(&ts)" deprecated from kernel 4.20 onwards
+    - Enable Mali kernel module and fix build directories for ZYNQMP platform
+
+  [ Ubuntu: 5.4.0-52.57 ]
+
+  * focal/linux: 5.4.0-52.57 -proposed tracker (LP: #1899920)
+  * CVE-2020-12351 // CVE-2020-12352 // CVE-2020-24490
+    - Bluetooth: Disable High Speed by default
+    - Bluetooth: MGMT: Fix not checking if BT_HS is enabled
+    - [Config] Disable BlueZ highspeed support
+  * CVE-2020-12351
+    - Bluetooth: L2CAP: Fix calling sk_filter on non-socket based channel
+  * CVE-2020-12352
+    - Bluetooth: A2MP: Fix not initializing all members
+
+ -- Hsuan-Yu Lin <shane.lin@canonical.com>  Mon, 26 Oct 2020 15:36:42 +0800
+
+linux-xilinx-zynqmp (5.4.0-1001.2) focal; urgency=medium
+
+  * Focal update: v5.4.61 upstream stable release (LP: #1893115)
+    - [Config] update config for SPI_DYNAMIC
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update variants
+    - [Packaging] update update.conf
+
+  * Disable CONFIG_ARCH_VEXPRESS
+    - [Config] disable target platforms other than Xilinx ZynqMP
+
+  * Miscellaneous upstream changes
+    - clk, clk-si5341: Support multiple input ports
+    - Enable XRT
+
+  [ Ubuntu: 5.4.0-51.56 ]
+
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+
+  [ Ubuntu: 5.4.0-50.55 ]
+
+  * CVE-2020-16119
+    - SAUCE: dccp: avoid double free of ccid on child socket
+  * CVE-2020-16120
+    - Revert "UBUNTU: SAUCE: overlayfs: ensure mounter privileges when reading
+      directories"
+    - ovl: pass correct flags for opening real directory
+    - ovl: switch to mounter creds in readdir
+    - ovl: verify permissions in ovl_path_open()
+    - ovl: call secutiry hook in ovl_real_ioctl()
+    - ovl: check permission to open real file
+
+  [ Ubuntu: 5.4.0-49.53 ]
+
+  * focal/linux: 5.4.0-49.53 -proposed tracker (LP: #1896007)
+  * Comet Lake PCH-H RAID not support on Ubuntu20.04 (LP: #1892288)
+    - ahci: Add Intel Comet Lake PCH-H PCI ID
+  * Novalink (mkvterm command failure) (LP: #1892546)
+    - tty: hvcs: Don't NULL tty->driver_data until hvcs_cleanup()
+  * Oops and hang when starting LVM snapshots on 5.4.0-47 (LP: #1894780)
+    - SAUCE: Revert "mm: memcg/slab: fix memory leak at non-root kmem_cache
+      destroy"
+  * Intel x710 LOMs do not work on Focal (LP: #1893956)
+    - i40e: Fix LED blinking flow for X710T*L devices
+    - i40e: enable X710 support
+  * Add/Backport EPYC-v3 and EPYC-Rome CPU model (LP: #1887490)
+    - kvm: svm: Update svm_xsaves_supported
+  * Fix non-working NVMe after S3 (LP: #1895718)
+    - SAUCE: PCI: Enable ACS quirk on CML root port
+  * Focal update: v5.4.65 upstream stable release (LP: #1895881)
+    - ipv4: Silence suspicious RCU usage warning
+    - ipv6: Fix sysctl max for fib_multipath_hash_policy
+    - netlabel: fix problems with mapping removal
+    - net: usb: dm9601: Add USB ID of Keenetic Plus DSL
+    - sctp: not disable bh in the whole sctp_get_port_local()
+    - taprio: Fix using wrong queues in gate mask
+    - tipc: fix shutdown() of connectionless socket
+    - net: disable netpoll on fresh napis
+    - Linux 5.4.65
+  * Focal update: v5.4.64 upstream stable release (LP: #1895880)
+    - HID: quirks: Always poll three more Lenovo PixArt mice
+    - drm/msm/dpu: Fix scale params in plane validation
+    - tty: serial: qcom_geni_serial: Drop __init from qcom_geni_console_setup
+    - drm/msm: add shutdown support for display platform_driver
+    - hwmon: (applesmc) check status earlier.
+    - nvmet: Disable keep-alive timer when kato is cleared to 0h
+    - drm/msm: enable vblank during atomic commits
+    - habanalabs: validate FW file size
+    - habanalabs: check correct vmalloc return code
+    - drm/msm/a6xx: fix gmu start on newer firmware
+    - ceph: don't allow setlease on cephfs
+    - drm/omap: fix incorrect lock state
+    - cpuidle: Fixup IRQ state
+    - nbd: restore default timeout when setting it to zero
+    - s390: don't trace preemption in percpu macros
+    - drm/amd/display: Reject overlay plane configurations in multi-display
+      scenarios
+    - drivers: gpu: amd: Initialize amdgpu_dm_backlight_caps object to 0 in
+      amdgpu_dm_update_backlight_caps
+    - drm/amd/display: Retry AUX write when fail occurs
+    - drm/amd/display: Fix memleak in amdgpu_dm_mode_config_init
+    - xen/xenbus: Fix granting of vmalloc'd memory
+    - fsldma: fix very broken 32-bit ppc ioread64 functionality
+    - dmaengine: of-dma: Fix of_dma_router_xlate's of_dma_xlate handling
+    - batman-adv: Avoid uninitialized chaddr when handling DHCP
+    - batman-adv: Fix own OGM check in aggregated OGMs
+    - batman-adv: bla: use netif_rx_ni when not in interrupt context
+    - dmaengine: at_hdmac: check return value of of_find_device_by_node() in
+      at_dma_xlate()
+    - rxrpc: Keep the ACK serial in a var in rxrpc_input_ack()
+    - rxrpc: Make rxrpc_kernel_get_srtt() indicate validity
+    - MIPS: mm: BMIPS5000 has inclusive physical caches
+    - MIPS: BMIPS: Also call bmips_cpu_setup() for secondary cores
+    - mmc: sdhci-acpi: Fix HS400 tuning for AMDI0040
+    - netfilter: nf_tables: add NFTA_SET_USERDATA if not null
+    - netfilter: nf_tables: incorrect enum nft_list_attributes definition
+    - netfilter: nf_tables: fix destination register zeroing
+    - net: hns: Fix memleak in hns_nic_dev_probe
+    - net: systemport: Fix memleak in bcm_sysport_probe
+    - ravb: Fixed to be able to unload modules
+    - net: arc_emac: Fix memleak in arc_mdio_probe
+    - dmaengine: pl330: Fix burst length if burst size is smaller than bus width
+    - gtp: add GTPA_LINK info to msg sent to userspace
+    - net: ethernet: ti: cpsw: fix clean up of vlan mc entries for host port
+    - bnxt_en: Don't query FW when netif_running() is false.
+    - bnxt_en: Check for zero dir entries in NVRAM.
+    - bnxt_en: Fix PCI AER error recovery flow
+    - bnxt_en: Fix possible crash in bnxt_fw_reset_task().
+    - bnxt_en: fix HWRM error when querying VF temperature
+    - xfs: fix boundary test in xfs_attr_shortform_verify
+    - bnxt: don't enable NAPI until rings are ready
+    - media: vicodec: add missing v4l2_ctrl_request_hdl_put()
+    - media: cedrus: Add missing v4l2_ctrl_request_hdl_put()
+    - selftests/bpf: Fix massive output from test_maps
+    - net: dsa: mt7530: fix advertising unsupported 1000baseT_Half
+    - netfilter: nfnetlink: nfnetlink_unicast() reports EAGAIN instead of ENOBUFS
+    - nvmet-fc: Fix a missed _irqsave version of spin_lock in
+      'nvmet_fc_fod_op_done()'
+    - nvme: fix controller instance leak
+    - cxgb4: fix thermal zone device registration
+    - perf tools: Correct SNOOPX field offset
+    - net: ethernet: mlx4: Fix memory allocation in mlx4_buddy_init()
+    - fix regression in "epoll: Keep a reference on files added to the check list"
+    - net: gemini: Fix another missing clk_disable_unprepare() in probe
+    - MIPS: add missing MSACSR and upper MSA initialization
+    - xfs: fix xfs_bmap_validate_extent_raw when checking attr fork of rt files
+    - perf jevents: Fix suspicious code in fixregex()
+    - tg3: Fix soft lockup when tg3_reset_task() fails.
+    - x86, fakenuma: Fix invalid starting node ID
+    - iommu/vt-d: Serialize IOMMU GCMD register modifications
+    - thermal: ti-soc-thermal: Fix bogus thermal shutdowns for omap4430
+    - thermal: qcom-spmi-temp-alarm: Don't suppress negative temp
+    - iommu/amd: Restore IRTE.RemapEn bit after programming IRTE
+    - include/linux/log2.h: add missing () around n in roundup_pow_of_two()
+    - iommu/vt-d: Handle 36bit addressing for x86-32
+    - tracing/kprobes, x86/ptrace: Fix regs argument order for i386
+    - ext2: don't update mtime on COW faults
+    - xfs: don't update mtime on COW faults
+    - ARC: perf: don't bail setup if pct irq missing in device-tree
+    - btrfs: drop path before adding new uuid tree entry
+    - btrfs: allocate scrub workqueues outside of locks
+    - btrfs: set the correct lockdep class for new nodes
+    - btrfs: set the lockdep class for log tree extent buffers
+    - btrfs: tree-checker: fix the error message for transid error
+    - net: core: use listified Rx for GRO_NORMAL in napi_gro_receive()
+    - btrfs: fix potential deadlock in the search ioctl
+    - ALSA: ca0106: fix error code handling
+    - ALSA: usb-audio: Add implicit feedback quirk for UR22C
+    - ALSA: pcm: oss: Remove superfluous WARN_ON() for mulaw sanity check
+    - ALSA: hda/hdmi: always check pin power status in i915 pin fixup
+    - ALSA: firewire-digi00x: exclude Avid Adrenaline from detection
+    - ALSA: hda - Fix silent audio output and corrupted input on MSI X570-A PRO
+    - ALSA; firewire-tascam: exclude Tascam FE-8 from detection
+    - ALSA: hda/realtek: Add quirk for Samsung Galaxy Book Ion NT950XCJ-X716A
+    - ALSA: hda/realtek - Improved routing for Thinkpad X1 7th/8th Gen
+    - arm64: dts: mt7622: add reset node for mmc device
+    - mmc: mediatek: add optional module reset property
+    - mmc: dt-bindings: Add resets/reset-names for Mediatek MMC bindings
+    - mmc: cqhci: Add cqhci_deactivate()
+    - mmc: sdhci-pci: Fix SDHCI_RESET_ALL for CQHCI for Intel GLK-based
+      controllers
+    - media: rc: do not access device via sysfs after rc_unregister_device()
+    - media: rc: uevent sysfs file races with rc_unregister_device()
+    - affs: fix basic permission bits to actually work
+    - block: allow for_each_bvec to support zero len bvec
+    - block: ensure bdi->io_pages is always initialized
+    - libata: implement ATA_HORKAGE_MAX_TRIM_128M and apply to Sandisks
+    - blk-iocost: ioc_pd_free() shouldn't assume irq disabled
+    - dmaengine: dw-edma: Fix scatter-gather address calculation
+    - drm/amd/pm: avoid false alarm due to confusing softwareshutdowntemp setting
+    - dm writecache: handle DAX to partitions on persistent memory correctly
+    - dm mpath: fix racey management of PG initialization
+    - dm integrity: fix error reporting in bitmap mode after creation
+    - dm crypt: Initialize crypto wait structures
+    - dm cache metadata: Avoid returning cmd->bm wild pointer on error
+    - dm thin metadata: Avoid returning cmd->bm wild pointer on error
+    - dm thin metadata: Fix use-after-free in dm_bm_set_read_only
+    - mm: slub: fix conversion of freelist_corrupted()
+    - mm: madvise: fix vma user-after-free
+    - vfio/pci: Fix SR-IOV VF handling with MMIO blocking
+    - perf record: Correct the help info of option "--no-bpf-event"
+    - sdhci: tegra: Add missing TMCLK for data timeout
+    - checkpatch: fix the usage of capture group ( ... )
+    - mm/hugetlb: fix a race between hugetlb sysctl handlers
+    - mm/khugepaged.c: fix khugepaged's request size in collapse_file
+    - cfg80211: regulatory: reject invalid hints
+    - net: usb: Fix uninit-was-stored issue in asix_read_phy_addr()
+    - Linux 5.4.64
+  * Focal update: v5.4.63 upstream stable release (LP: #1895879)
+    - HID: core: Correctly handle ReportSize being zero
+    - HID: core: Sanitize event code and type when mapping input
+    - perf record/stat: Explicitly call out event modifiers in the documentation
+    - drm/sched: Fix passing zero to 'PTR_ERR' warning v2
+    - drm/etnaviv: fix TS cache flushing on GPUs with BLT engine
+    - KVM: arm64: Add kvm_extable for vaxorcism code
+    - KVM: arm64: Survive synchronous exceptions caused by AT instructions
+    - KVM: arm64: Set HCR_EL2.PTW to prevent AT taking synchronous exception
+    - dt-bindings: mmc: tegra: Add tmclk for Tegra210 and later
+    - arm64: tegra: Add missing timeout clock to Tegra194 SDMMC nodes
+    - arm64: tegra: Add missing timeout clock to Tegra186 SDMMC nodes
+    - arm64: tegra: Add missing timeout clock to Tegra210 SDMMC
+    - sdhci: tegra: Remove SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK for Tegra210
+    - sdhci: tegra: Remove SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK for Tegra186
+    - scsi: target: tcmu: Fix size in calls to tcmu_flush_dcache_range
+    - scsi: target: tcmu: Optimize use of flush_dcache_page
+    - Linux 5.4.63
+  * Focal update: v5.4.62 upstream stable release (LP: #1895174)
+    - binfmt_flat: revert "binfmt_flat: don't offset the data start"
+    - gre6: Fix reception with IP6_TNL_F_RCV_DSCP_COPY
+    - net: Fix potential wrong skb->protocol in skb_vlan_untag()
+    - net: nexthop: don't allow empty NHA_GROUP
+    - net: qrtr: fix usage of idr in port assignment to socket
+    - net: sctp: Fix negotiation of the number of data streams.
+    - net/smc: Prevent kernel-infoleak in __smc_diag_dump()
+    - tipc: fix uninit skb->data in tipc_nl_compat_dumpit()
+    - net: ena: Make missed_tx stat incremental
+    - net/sched: act_ct: Fix skb double-free in tcf_ct_handle_fragments() error
+      flow
+    - ipvlan: fix device features
+    - ALSA: pci: delete repeated words in comments
+    - ASoC: img: Fix a reference count leak in img_i2s_in_set_fmt
+    - ASoC: img-parallel-out: Fix a reference count leak
+    - ASoC: tegra: Fix reference count leaks.
+    - mfd: intel-lpss: Add Intel Emmitsburg PCH PCI IDs
+    - arm64: dts: qcom: msm8916: Pull down PDM GPIOs during sleep
+    - powerpc/xive: Ignore kmemleak false positives
+    - media: pci: ttpci: av7110: fix possible buffer overflow caused by bad DMA
+      value in debiirq()
+    - blktrace: ensure our debugfs dir exists
+    - scsi: target: tcmu: Fix crash on ARM during cmd completion
+    - mfd: intel-lpss: Add Intel Tiger Lake PCH-H PCI IDs
+    - iommu/iova: Don't BUG on invalid PFNs
+    - drm/amdkfd: Fix reference count leaks.
+    - drm/radeon: fix multiple reference count leak
+    - drm/amdgpu: fix ref count leak in amdgpu_driver_open_kms
+    - drm/amd/display: fix ref count leak in amdgpu_drm_ioctl
+    - drm/amdgpu: fix ref count leak in amdgpu_display_crtc_set_config
+    - drm/amdgpu/display: fix ref count leak when pm_runtime_get_sync fails
+    - scsi: lpfc: Fix shost refcount mismatch when deleting vport
+    - xfs: Don't allow logging of XFS_ISTALE inodes
+    - scsi: target: Fix xcopy sess release leak
+    - selftests/powerpc: Purge extra count_pmc() calls of ebb selftests
+    - f2fs: fix error path in do_recover_data()
+    - omapfb: fix multiple reference count leaks due to pm_runtime_get_sync
+    - PCI: Fix pci_create_slot() reference count leak
+    - ARM: dts: ls1021a: output PPS signal on FIPER2
+    - rtlwifi: rtl8192cu: Prevent leaking urb
+    - mips/vdso: Fix resource leaks in genvdso.c
+    - cec-api: prevent leaking memory through hole in structure
+    - HID: quirks: add NOGET quirk for Logitech GROUP
+    - f2fs: fix use-after-free issue
+    - drm/nouveau/drm/noveau: fix reference count leak in nouveau_fbcon_open
+    - drm/nouveau: fix reference count leak in nv50_disp_atomic_commit
+    - drm/nouveau: Fix reference count leak in nouveau_connector_detect
+    - locking/lockdep: Fix overflow in presentation of average lock-time
+    - btrfs: file: reserve qgroup space after the hole punch range is locked
+    - btrfs: make btrfs_qgroup_check_reserved_leak take btrfs_inode
+    - scsi: iscsi: Do not put host in iscsi_set_flashnode_param()
+    - ceph: fix potential mdsc use-after-free crash
+    - ceph: do not access the kiocb after aio requests
+    - scsi: fcoe: Memory leak fix in fcoe_sysfs_fcf_del()
+    - EDAC/ie31200: Fallback if host bridge device is already initialized
+    - hugetlbfs: prevent filesystem stacking of hugetlbfs
+    - media: davinci: vpif_capture: fix potential double free
+    - KVM: arm64: Fix symbol dependency in __hyp_call_panic_nvhe
+    - powerpc/spufs: add CONFIG_COREDUMP dependency
+    - USB: sisusbvga: Fix a potential UB casued by left shifting a negative value
+    - brcmfmac: Set timeout value when configuring power save
+    - efi: provide empty efi_enter_virtual_mode implementation
+    - arm64: Fix __cpu_logical_map undefined issue
+    - Revert "ath10k: fix DMA related firmware crashes on multiple devices"
+    - sched/uclamp: Protect uclamp fast path code with static key
+    - sched/uclamp: Fix a deadlock when enabling uclamp static key
+    - usb: cdns3: gadget: always zeroed TRB buffer when enable endpoint
+    - PM / devfreq: rk3399_dmc: Add missing of_node_put()
+    - PM / devfreq: rk3399_dmc: Disable devfreq-event device when fails
+    - PM / devfreq: rk3399_dmc: Fix kernel oops when rockchip,pmu is absent
+    - drm/xen: fix passing zero to 'PTR_ERR' warning
+    - drm/xen-front: Fix misused IS_ERR_OR_NULL checks
+    - s390/numa: set node distance to LOCAL_DISTANCE
+    - btrfs: factor out inode items copy loop from btrfs_log_inode()
+    - btrfs: only commit the delayed inode when doing a full fsync
+    - btrfs: only commit delayed items at fsync if we are logging a directory
+    - mm/shuffle: don't move pages between zones and don't read garbage memmaps
+    - mm: fix kthread_use_mm() vs TLB invalidate
+    - mm/cma.c: switch to bitmap_zalloc() for cma bitmap allocation
+    - cma: don't quit at first error when activating reserved areas
+    - gpu/drm: ingenic: Use the plane's src_[x,y] to configure DMA length
+    - drm/ingenic: Fix incorrect assumption about plane->index
+    - drm/amd/display: Trigger modesets on MST DSC connectors
+    - drm/amd/display: Add additional config guards for DCN
+    - drm/amd/display: Fix dmesg warning from setting abm level
+    - mm/vunmap: add cond_resched() in vunmap_pmd_range
+    - EDAC: sb_edac: get rid of unused vars
+    - EDAC: skx_common: get rid of unused type var
+    - EDAC/{i7core,sb,pnd2,skx}: Fix error event severity
+    - PCI: qcom: Add missing ipq806x clocks in PCIe driver
+    - PCI: qcom: Change duplicate PCI reset to phy reset
+    - PCI: qcom: Add missing reset for ipq806x
+    - cpufreq: intel_pstate: Fix EPP setting via sysfs in active mode
+    - ALSA: usb-audio: Add capture support for Saffire 6 (USB 1.1)
+    - media: gpio-ir-tx: improve precision of transmitted signal due to scheduling
+    - block: respect queue limit of max discard segment
+    - block: virtio_blk: fix handling single range discard request
+    - drm/msm/adreno: fix updating ring fence
+    - block: Fix page_is_mergeable() for compound pages
+    - bfq: fix blkio cgroup leakage v4
+    - hwmon: (nct7904) Correct divide by 0
+    - blk-mq: insert request not through ->queue_rq into sw/scheduler queue
+    - blkcg: fix memleak for iolatency
+    - nvme-fc: Fix wrong return value in __nvme_fc_init_request()
+    - nvme: multipath: round-robin: fix single non-optimized path case
+    - null_blk: fix passing of REQ_FUA flag in null_handle_rq
+    - i2c: core: Don't fail PRP0001 enumeration when no ID table exist
+    - i2c: rcar: in slave mode, clear NACK earlier
+    - usb: gadget: f_tcm: Fix some resource leaks in some error paths
+    - spi: stm32: clear only asserted irq flags on interrupt
+    - jbd2: make sure jh have b_transaction set in refile/unfile_buffer
+    - ext4: don't BUG on inconsistent journal feature
+    - ext4: handle read only external journal device
+    - jbd2: abort journal if free a async write error metadata buffer
+    - ext4: handle option set by mount flags correctly
+    - ext4: handle error of ext4_setup_system_zone() on remount
+    - ext4: correctly restore system zone info when remount fails
+    - fs: prevent BUG_ON in submit_bh_wbc()
+    - spi: stm32h7: fix race condition at end of transfer
+    - spi: stm32: fix fifo threshold level in case of short transfer
+    - spi: stm32: fix stm32_spi_prepare_mbr in case of odd clk_rate
+    - spi: stm32: always perform registers configuration prior to transfer
+    - drm/amd/powerplay: correct Vega20 cached smu feature state
+    - drm/amd/powerplay: correct UVD/VCE PG state on custom pptable uploading
+    - drm/amd/display: Switch to immediate mode for updating infopackets
+    - netfilter: avoid ipv6 -> nf_defrag_ipv6 module dependency
+    - can: j1939: transport: j1939_xtp_rx_dat_one(): compare own packets to detect
+      corruptions
+    - ALSA: hda/realtek: Add model alc298-samsung-headphone
+    - s390/cio: add cond_resched() in the slow_eval_known_fn() loop
+    - ASoC: wm8994: Avoid attempts to read unreadable registers
+    - selftests: disable rp_filter for icmp_redirect.sh
+    - scsi: fcoe: Fix I/O path allocation
+    - scsi: ufs: Fix possible infinite loop in ufshcd_hold
+    - scsi: ufs: Improve interrupt handling for shared interrupts
+    - scsi: ufs: Clean up completed request without interrupt notification
+    - scsi: qla2xxx: Fix login timeout
+    - scsi: qla2xxx: Check if FW supports MQ before enabling
+    - scsi: qla2xxx: Fix null pointer access during disconnect from subsystem
+    - Revert "scsi: qla2xxx: Fix crash on qla2x00_mailbox_command"
+    - macvlan: validate setting of multiple remote source MAC addresses
+    - net: gianfar: Add of_node_put() before goto statement
+    - powerpc/perf: Fix soft lockups due to missed interrupt accounting
+    - arm64: Move handling of erratum 1418040 into C code
+    - arm64: Allow booting of late CPUs affected by erratum 1418040
+    - block: fix get_max_io_size()
+    - block: loop: set discard granularity and alignment for block device backed
+      loop
+    - HID: i2c-hid: Always sleep 60ms after I2C_HID_PWR_ON commands
+    - blk-mq: order adding requests to hctx->dispatch and checking SCHED_RESTART
+    - btrfs: reset compression level for lzo on remount
+    - btrfs: check the right error variable in btrfs_del_dir_entries_in_log
+    - btrfs: fix space cache memory leak after transaction abort
+    - btrfs: detect nocow for swap after snapshot delete
+    - fbcon: prevent user font height or width change from causing potential out-
+      of-bounds access
+    - USB: lvtest: return proper error code in probe
+    - vt: defer kfree() of vc_screenbuf in vc_do_resize()
+    - vt_ioctl: change VT_RESIZEX ioctl to check for error return from vc_resize()
+    - serial: samsung: Removes the IRQ not found warning
+    - serial: pl011: Fix oops on -EPROBE_DEFER
+    - serial: pl011: Don't leak amba_ports entry on driver register error
+    - serial: stm32: avoid kernel warning on absence of optional IRQ
+    - serial: 8250_exar: Fix number of ports for Commtech PCIe cards
+    - serial: 8250: change lock order in serial8250_do_startup()
+    - writeback: Protect inode->i_io_list with inode->i_lock
+    - writeback: Avoid skipping inode writeback
+    - writeback: Fix sync livelock due to b_dirty_time processing
+    - XEN uses irqdesc::irq_data_common::handler_data to store a per interrupt XEN
+      data pointer which contains XEN specific information.
+    - usb: host: xhci: fix ep context print mismatch in debugfs
+    - xhci: Do warm-reset when both CAS and XDEV_RESUME are set
+    - xhci: Always restore EP_SOFT_CLEAR_TOGGLE even if ep reset failed
+    - ARM64: vdso32: Install vdso32 from vdso_install
+    - arm64: vdso32: make vdso32 install conditional
+    - PM: sleep: core: Fix the handling of pending runtime resume requests
+    - powerpc/perf: Fix crashes with generic_compat_pmu & BHRB
+    - device property: Fix the secondary firmware node handling in
+      set_primary_fwnode()
+    - crypto: af_alg - Work around empty control messages without MSG_MORE
+    - genirq/matrix: Deal with the sillyness of for_each_cpu() on UP
+    - irqchip/stm32-exti: Avoid losing interrupts due to clearing pending bits by
+      mistake
+    - x86/hotplug: Silence APIC only after all interrupts are migrated
+    - drm/amdgpu: Fix buffer overflow in INFO ioctl
+    - drm/amdgpu/gfx10: refine mgcg setting
+    - drm/amd/powerplay: Fix hardmins not being sent to SMU for RV
+    - drm/amd/pm: correct Vega10 swctf limit setting
+    - drm/amd/pm: correct Vega12 swctf limit setting
+    - drm/amd/pm: correct Vega20 swctf limit setting
+    - drm/amd/pm: correct the thermal alert temperature limit settings
+    - USB: yurex: Fix bad gfp argument
+    - usb: uas: Add quirk for PNY Pro Elite
+    - USB: quirks: Ignore duplicate endpoint on Sound Devices MixPre-D
+    - USB: Ignore UAS for JMicron JMS567 ATA/ATAPI Bridge
+    - usb: host: ohci-exynos: Fix error handling in exynos_ohci_probe()
+    - USB: gadget: u_f: add overflow checks to VLA macros
+    - USB: gadget: f_ncm: add bounds checks to ncm_unwrap_ntb()
+    - USB: gadget: u_f: Unbreak offset calculation in VLAs
+    - USB: cdc-acm: rework notification_buffer resizing
+    - usb: storage: Add unusual_uas entry for Sony PSZ drives
+    - drm/i915: Fix cmd parser desc matching with masks
+    - usb: dwc3: gadget: Don't setup more than requested
+    - usb: dwc3: gadget: Fix handling ZLP
+    - usb: dwc3: gadget: Handle ZLP for sg requests
+    - fbmem: pull fbcon_update_vcs() out of fb_set_var()
+    - kheaders: remove unneeded 'cat' command piped to 'head' / 'tail'
+    - kheaders: optimize md5sum calculation for in-tree builds
+    - kheaders: optimize header copy for in-tree builds
+    - kheaders: remove the last bashism to allow sh to run it
+    - kheaders: explain why include/config/autoconf.h is excluded from md5sum
+    - kbuild: add variables for compression tools
+    - kbuild: fix broken builds because of GZIP,BZIP2,LZOP variables
+    - HID: hiddev: Fix slab-out-of-bounds write in hiddev_ioctl_usage()
+    - ALSA: usb-audio: Update documentation comment for MS2109 quirk
+    - io_uring: Fix NULL pointer dereference in io_sq_wq_submit_work()
+    - Linux 5.4.62
+  * DELL LATITUDE 5491 touchscreen doesn't work (LP: #1889446) // Focal update:
+    v5.4.62 upstream stable release (LP: #1895174)
+    - USB: quirks: Add no-lpm quirk for another Raydium touchscreen
+  * [NUC8CCHK][HDA-Intel - HDA Intel PCH, playback] No sound at all
+    (LP: #1875199) // Focal update: v5.4.62 upstream stable release
+    (LP: #1895174)
+    - ALSA: hda/realtek: Fix pin default on Intel NUC 8 Rugged
+  * Focal update: v5.4.61 upstream stable release (LP: #1893115)
+    - Documentation/llvm: add documentation on building w/ Clang/LLVM
+    - Documentation/llvm: fix the name of llvm-size
+    - net: wan: wanxl: use allow to pass CROSS_COMPILE_M68k for rebuilding
+      firmware
+    - net: wan: wanxl: use $(M68KCC) instead of $(M68KAS) for rebuilding firmware
+    - x86/boot: kbuild: allow readelf executable to be specified
+    - kbuild: remove PYTHON2 variable
+    - kbuild: remove AS variable
+    - kbuild: replace AS=clang with LLVM_IAS=1
+    - kbuild: support LLVM=1 to switch the default tools to Clang/LLVM
+    - drm/vgem: Replace opencoded version of drm_gem_dumb_map_offset()
+    - gfs2: Improve mmap write vs. punch_hole consistency
+    - gfs2: Never call gfs2_block_zero_range with an open transaction
+    - perf probe: Fix memory leakage when the probe point is not found
+    - khugepaged: khugepaged_test_exit() check mmget_still_valid()
+    - khugepaged: adjust VM_BUG_ON_MM() in __khugepaged_enter()
+    - bcache: avoid nr_stripes overflow in bcache_device_init()
+    - btrfs: export helpers for subvolume name/id resolution
+    - btrfs: don't show full path of bind mounts in subvol=
+    - btrfs: return EROFS for BTRFS_FS_STATE_ERROR cases
+    - btrfs: add wrapper for transaction abort predicate
+    - ALSA: hda/realtek: Add quirk for Samsung Galaxy Flex Book
+    - ALSA: hda/realtek: Add quirk for Samsung Galaxy Book Ion
+    - can: j1939: transport: j1939_session_tx_dat(): fix use-after-free read in
+      j1939_tp_txtimer()
+    - can: j1939: socket: j1939_sk_bind(): make sure ml_priv is allocated
+    - [Config] update config for SPI_DYNAMIC
+    - spi: Prevent adding devices below an unregistering controller
+    - romfs: fix uninitialized memory leak in romfs_dev_read()
+    - kernel/relay.c: fix memleak on destroy relay channel
+    - uprobes: __replace_page() avoid BUG in munlock_vma_page()
+    - mm: include CMA pages in lowmem_reserve at boot
+    - mm, page_alloc: fix core hung in free_pcppages_bulk()
+    - RDMA/hfi1: Correct an interlock issue for TID RDMA WRITE request
+    - ext4: fix checking of directory entry validity for inline directories
+    - jbd2: add the missing unlock_buffer() in the error path of
+      jbd2_write_superblock()
+    - scsi: zfcp: Fix use-after-free in request timeout handlers
+    - drm/amdgpu/display: use GFP_ATOMIC in dcn20_validate_bandwidth_internal
+    - drm/amd/display: Fix EDID parsing after resume from suspend
+    - drm/amd/display: fix pow() crashing when given base 0
+    - kthread: Do not preempt current task if it is going to call schedule()
+    - opp: Enable resources again if they were disabled earlier
+    - scsi: ufs: Add DELAY_BEFORE_LPM quirk for Micron devices
+    - scsi: target: tcmu: Fix crash in tcmu_flush_dcache_range on ARM
+    - media: budget-core: Improve exception handling in budget_register()
+    - rtc: goldfish: Enable interrupt in set_alarm() when necessary
+    - media: vpss: clean up resources in init
+    - Input: psmouse - add a newline when printing 'proto' by sysfs
+    - MIPS: Fix unable to reserve memory for Crash kernel
+    - m68knommu: fix overwriting of bits in ColdFire V3 cache control
+    - svcrdma: Fix another Receive buffer leak
+    - xfs: fix inode quota reservation checks
+    - drm/ttm: fix offset in VMAs with a pg_offs in ttm_bo_vm_access
+    - jffs2: fix UAF problem
+    - ceph: fix use-after-free for fsc->mdsc
+    - swiotlb-xen: use vmalloc_to_page on vmalloc virt addresses
+    - cpufreq: intel_pstate: Fix cpuinfo_max_freq when MSR_TURBO_RATIO_LIMIT is 0
+    - scsi: libfc: Free skb in fc_disc_gpn_id_resp() for valid cases
+    - virtio_ring: Avoid loop when vq is broken in virtqueue_poll
+    - media: camss: fix memory leaks on error handling paths in probe
+    - tools/testing/selftests/cgroup/cgroup_util.c: cg_read_strcmp: fix null
+      pointer dereference
+    - xfs: Fix UBSAN null-ptr-deref in xfs_sysfs_init
+    - alpha: fix annotation of io{read,write}{16,32}be()
+    - fs/signalfd.c: fix inconsistent return codes for signalfd4
+    - ext4: fix potential negative array index in do_split()
+    - ext4: don't allow overlapping system zones
+    - netfilter: nf_tables: nft_exthdr: the presence return value should be
+      little-endian
+    - spi: stm32: fixes suspend/resume management
+    - ASoC: q6afe-dai: mark all widgets registers as SND_SOC_NOPM
+    - ASoC: q6routing: add dummy register read/write function
+    - bpf: sock_ops sk access may stomp registers when dst_reg = src_reg
+    - can: j1939: fix kernel-infoleak in j1939_sk_sock2sockaddr_can()
+    - can: j1939: transport: j1939_simple_recv(): ignore local J1939 messages send
+      not by J1939 stack
+    - can: j1939: transport: add j1939_session_skb_find_by_offset() function
+    - i40e: Set RX_ONLY mode for unicast promiscuous on VLAN
+    - i40e: Fix crash during removing i40e driver
+    - net: fec: correct the error path for regulator disable in probe
+    - bonding: show saner speed for broadcast mode
+    - can: j1939: fix support for multipacket broadcast message
+    - can: j1939: cancel rxtimer on multipacket broadcast session complete
+    - can: j1939: abort multipacket broadcast session when timeout occurs
+    - can: j1939: add rxtimer for multipacket broadcast session
+    - bonding: fix a potential double-unregister
+    - s390/runtime_instrumentation: fix storage key handling
+    - s390/ptrace: fix storage key handling
+    - ASoC: msm8916-wcd-analog: fix register Interrupt offset
+    - ASoC: intel: Fix memleak in sst_media_open
+    - vfio/type1: Add proper error unwind for vfio_iommu_replay()
+    - kvm: x86: Toggling CR4.SMAP does not load PDPTEs in PAE mode
+    - kvm: x86: Toggling CR4.PKE does not load PDPTEs in PAE mode
+    - Revert "scsi: qla2xxx: Disable T10-DIF feature with FC-NVMe during probe"
+    - kconfig: qconf: do not limit the pop-up menu to the first row
+    - kconfig: qconf: fix signal connection to invalid slots
+    - efi: avoid error message when booting under Xen
+    - Fix build error when CONFIG_ACPI is not set/enabled:
+    - RDMA/bnxt_re: Do not add user qps to flushlist
+    - afs: Fix NULL deref in afs_dynroot_depopulate()
+    - bonding: fix active-backup failover for current ARP slave
+    - net: ena: Prevent reset after device destruction
+    - net: gemini: Fix missing free_netdev() in error path of
+      gemini_ethernet_port_probe()
+    - hv_netvsc: Fix the queue_mapping in netvsc_vf_xmit()
+    - net: dsa: b53: check for timeout
+    - powerpc/pseries: Do not initiate shutdown when system is running on UPS
+    - efi: add missed destroy_workqueue when efisubsys_init fails
+    - epoll: Keep a reference on files added to the check list
+    - do_epoll_ctl(): clean the failure exits up a bit
+    - mm/hugetlb: fix calculation of adjust_range_if_pmd_sharing_possible
+    - xen: don't reschedule in preemption off sections
+    - KVM: Pass MMU notifier range flags to kvm_unmap_hva_range()
+    - KVM: arm64: Only reschedule if MMU_NOTIFIER_RANGE_BLOCKABLE is not set
+    - Linux 5.4.61
+  * [UBUNTU 20.04] zPCI device hot-plug during boot may result in unusable
+    device (LP: #1893778)
+    - s390/pci: ignore stale configuration request event
+  * [SRU] [Focal/OEM-5.6/Groovy]Fix AMD usb host controller lost after stress S3
+    (LP: #1893914)
+    - SAUCE: xhci: workaround for S3 issue on AMD SNPS 3.0 xHC
+
+  [ Ubuntu: 5.4.0-48.52 ]
+
+  * focal/linux: 5.4.0-48.52 -proposed tracker (LP: #1894654)
+  * mm/slub kernel oops on focal kernel 5.4.0-45 (LP: #1895109)
+    - SAUCE: Revert "mm/slub: fix a memory leak in sysfs_slab_add()"
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+    - update dkms package versions
+  * Introduce the new NVIDIA 450-server and the 450 UDA series (LP: #1887674)
+    - [packaging] add signed modules for nvidia 450 and 450-server
+  * [UBUNTU 20.04] zPCI attach/detach issues with PF/VF linking support
+    (LP: #1892849)
+    - s390/pci: fix zpci_bus_link_virtfn()
+    - s390/pci: re-introduce zpci_remove_device()
+    - s390/pci: fix PF/VF linking on hot plug
+  * [UBUNTU 20.04] kernel: s390/cpum_cf,perf: changeDFLT_CCERROR counter name
+    (LP: #1891454)
+    - s390/cpum_cf, perf: change DFLT_CCERROR counter name
+  * [UBUNTU 20.04] zPCI: Enabling of a reserved PCI function regression
+    introduced by multi-function support (LP: #1891437)
+    - s390/pci: fix enabling a reserved PCI function
+  * CVE-2020-12888
+    - vfio/type1: Support faulting PFNMAP vmas
+    - vfio-pci: Fault mmaps to enable vma tracking
+    - vfio-pci: Invalidate mmaps and block MMIO access on disabled memory
+  *  [Hyper-V] VSS and File Copy daemons intermittently fails to start
+    (LP: #1891224)
+    - [Packaging] Bind hv_vss_daemon startup to hv_vss device
+    - [Packaging] bind hv_fcopy_daemon startup to hv_fcopy device
+  * alsa/hdmi: support nvidia mst hdmi/dp audio (LP: #1867704)
+    - ALSA: hda - Rename snd_hda_pin_sense to snd_hda_jack_pin_sense
+    - ALSA: hda - Add DP-MST jack support
+    - ALSA: hda - Add DP-MST support for non-acomp codecs
+    - ALSA: hda - Add DP-MST support for NVIDIA codecs
+    - ALSA: hda: hdmi - fix regression in connect list handling
+    - ALSA: hda: hdmi - fix kernel oops caused by invalid PCM idx
+    - ALSA: hda: hdmi - preserve non-MST PCM routing for Intel platforms
+    - ALSA: hda: hdmi - Keep old slot assignment behavior for Intel platforms
+    - ALSA: hda - Fix DP-MST support for NVIDIA codecs
+  * Focal update: v5.4.60 upstream stable release (LP: #1892899)
+    - smb3: warn on confusing error scenario with sec=krb5
+    - genirq/affinity: Make affinity setting if activated opt-in
+    - genirq/PM: Always unlock IRQ descriptor in rearm_wake_irq()
+    - PCI: hotplug: ACPI: Fix context refcounting in acpiphp_grab_context()
+    - PCI: Add device even if driver attach failed
+    - PCI: qcom: Define some PARF params needed for ipq8064 SoC
+    - PCI: qcom: Add support for tx term offset for rev 2.1.0
+    - btrfs: allow use of global block reserve for balance item deletion
+    - btrfs: free anon block device right after subvolume deletion
+    - btrfs: don't allocate anonymous block device for user invisible roots
+    - btrfs: ref-verify: fix memory leak in add_block_entry
+    - btrfs: stop incremening log_batch for the log root tree when syncing log
+    - btrfs: remove no longer needed use of log_writers for the log root tree
+    - btrfs: don't traverse into the seed devices in show_devname
+    - btrfs: open device without device_list_mutex
+    - btrfs: move the chunk_mutex in btrfs_read_chunk_tree
+    - btrfs: relocation: review the call sites which can be interrupted by signal
+    - btrfs: add missing check for nocow and compression inode flags
+    - btrfs: avoid possible signal interruption of btrfs_drop_snapshot() on
+      relocation tree
+    - btrfs: sysfs: use NOFS for device creation
+    - btrfs: don't WARN if we abort a transaction with EROFS
+    - btrfs: fix race between page release and a fast fsync
+    - btrfs: fix messages after changing compression level by remount
+    - btrfs: only search for left_info if there is no right_info in
+      try_merge_free_space
+    - btrfs: inode: fix NULL pointer dereference if inode doesn't need compression
+    - btrfs: fix memory leaks after failure to lookup checksums during inode
+      logging
+    - btrfs: make sure SB_I_VERSION doesn't get unset by remount
+    - btrfs: fix return value mixup in btrfs_get_extent
+    - arm64: perf: Correct the event index in sysfs
+    - dt-bindings: iio: io-channel-mux: Fix compatible string in example code
+    - iio: dac: ad5592r: fix unbalanced mutex unlocks in ad5592r_read_raw()
+    - xtensa: add missing exclusive access state management
+    - xtensa: fix xtensa_pmu_setup prototype
+    - cifs: Fix leak when handling lease break for cached root fid
+    - powerpc/ptdump: Fix build failure in hashpagetable.c
+    - powerpc: Allow 4224 bytes of stack expansion for the signal frame
+    - powerpc: Fix circular dependency between percpu.h and mmu.h
+    - pinctrl: ingenic: Enhance support for IRQ_TYPE_EDGE_BOTH
+    - media: vsp1: dl: Fix NULL pointer dereference on unbind
+    - net: ethernet: stmmac: Disable hardware multicast filter
+    - net: stmmac: dwmac1000: provide multicast filter fallback
+    - net/compat: Add missing sock updates for SCM_RIGHTS
+    - md/raid5: Fix Force reconstruct-write io stuck in degraded raid5
+    - bcache: allocate meta data pages as compound pages
+    - bcache: fix overflow in offset_to_stripe()
+    - mac80211: fix misplaced while instead of if
+    - driver core: Avoid binding drivers to dead devices
+    - MIPS: CPU#0 is not hotpluggable
+    - MIPS: qi_lb60: Fix routing to audio amplifier
+    - ext2: fix missing percpu_counter_inc
+    - khugepaged: collapse_pte_mapped_thp() flush the right range
+    - khugepaged: collapse_pte_mapped_thp() protect the pmd lock
+    - ocfs2: change slot number type s16 to u16
+    - mm/page_counter.c: fix protection usage propagation
+    - mm/memory_hotplug: fix unpaired mem_hotplug_begin/done
+    - ftrace: Setup correct FTRACE_FL_REGS flags for module
+    - kprobes: Fix NULL pointer dereference at kprobe_ftrace_handler
+    - tracing/hwlat: Honor the tracing_cpumask
+    - tracing: Use trace_sched_process_free() instead of exit() for pid tracing
+    - tracing: Move pipe reference to trace array instead of current_tracer
+    - watchdog: f71808e_wdt: indicate WDIOF_CARDRESET support in
+      watchdog_info.options
+    - watchdog: f71808e_wdt: remove use of wrong watchdog_info option
+    - watchdog: f71808e_wdt: clear watchdog timeout occurred flag
+    - ceph: set sec_context xattr on symlink creation
+    - ceph: handle zero-length feature mask in session messages
+    - pseries: Fix 64 bit logical memory block panic
+    - module: Correctly truncate sysfs sections output
+    - perf intel-pt: Fix FUP packet state
+    - perf intel-pt: Fix duplicate branch after CBR
+    - remoteproc: qcom: q6v5: Update running state before requesting stop
+    - remoteproc: qcom_q6v5_mss: Validate MBA firmware size before load
+    - remoteproc: qcom_q6v5_mss: Validate modem blob firmware size before load
+    - drm/imx: imx-ldb: Disable both channels for split mode in enc->disable()
+    - orangefs: get rid of knob code...
+    - pinctrl: ingenic: Properly detect GPIO direction when configured for IRQ
+    - crypto: algif_aead - Only wake up when ctx->more is zero
+    - mfd: arizona: Ensure 32k clock is put on driver unbind and error
+    - octeontx2-af: change (struct qmem)->entry_sz from u8 to u16
+    - mtd: rawnand: fsl_upm: Remove unused mtd var
+    - platform/chrome: cros_ec_ishtp: Fix a double-unlock issue
+    - RDMA/ipoib: Return void from ipoib_ib_dev_stop()
+    - RDMA/ipoib: Fix ABBA deadlock with ipoib_reap_ah()
+    - media: rockchip: rga: Introduce color fmt macros and refactor CSC mode logic
+    - media: rockchip: rga: Only set output CSC mode for RGB input
+    - IB/uverbs: Set IOVA on IB MR in uverbs layer
+    - selftests/bpf: Test_progs indicate to shell on non-actions
+    - selftests/bpf: test_progs use another shell exit on non-actions
+    - USB: serial: ftdi_sio: make process-packet buffer unsigned
+    - USB: serial: ftdi_sio: clean up receive processing
+    - crypto: af_alg - Fix regression on empty requests
+    - devres: keep both device name and resource name in pretty name
+    - RDMA/counter: Only bind user QPs in auto mode
+    - RDMA/counter: Allow manually bind QPs with different pids to same counter
+    - mmc: renesas_sdhi_internal_dmac: clean up the code for dma complete
+    - crypto: caam - Remove broken arc4 support
+    - gpu: ipu-v3: image-convert: Combine rotate/no-rotate irq handlers
+    - gpu: ipu-v3: image-convert: Wait for all EOFs before completing a tile
+    - dm rq: don't call blk_mq_queue_stopped() in dm_stop_queue()
+    - clk: actions: Fix h_clk for Actions S500 SoC
+    - selftests/powerpc: ptrace-pkey: Rename variables to make it easier to follow
+      code
+    - selftests/powerpc: ptrace-pkey: Update the test to mark an invalid pkey
+      correctly
+    - selftests/powerpc: ptrace-pkey: Don't update expected UAMOR value
+    - iommu/omap: Check for failure of a call to omap_iommu_dump_ctx
+    - clk: qcom: gcc: fix sm8150 GPU and NPU clocks
+    - clk: qcom: clk-alpha-pll: remove unused/incorrect PLL_CAL_VAL
+    - iommu/vt-d: Enforce PASID devTLB field mask
+    - i2c: rcar: slave: only send STOP event when we have been addressed
+    - clk: qcom: gcc-sdm660: Fix up gcc_mss_mnoc_bimc_axi_clk
+    - clk: clk-atlas6: fix return value check in atlas6_clk_init()
+    - pwm: bcm-iproc: handle clk_get_rate() return
+    - tools build feature: Use CC and CXX from parent
+    - i2c: rcar: avoid race when unregistering slave
+    - nfs: ensure correct writeback errors are returned on close()
+    - ubifs: Fix wrong orphan node deletion in ubifs_jnl_update|rename
+    - clk: bcm2835: Do not use prediv with bcm2711's PLLs
+    - libnvdimm/security: fix a typo
+    - libnvdimm/security: ensure sysfs poll thread woke up and fetch updated attr
+    - openrisc: Fix oops caused when dumping stack
+    - scsi: lpfc: nvmet: Avoid hang / use-after-free again when destroying
+      targetport
+    - nfs: nfs_file_write() should check for writeback errors
+    - watchdog: initialize device before misc_register
+    - md-cluster: Fix potential error pointer dereference in resize_bitmaps()
+    - x86/tsr: Fix tsc frequency enumeration bug on Lightning Mountain SoC
+    - Input: sentelic - fix error return when fsp_reg_write fails
+    - recordmcount: Fix build failure on non arm64
+    - drm/vmwgfx: Use correct vmw_legacy_display_unit pointer
+    - drm/vmwgfx: Fix two list_for_each loop exit tests
+    - net: qcom/emac: add missed clk_disable_unprepare in error path of
+      emac_clks_phase1_init
+    - nfs: Fix getxattr kernel panic and memory overflow
+    - fs/minix: set s_maxbytes correctly
+    - fs/minix: fix block limit check for V1 filesystems
+    - fs/minix: remove expected error message in block_to_path()
+    - fs/ufs: avoid potential u32 multiplication overflow
+    - test_kmod: avoid potential double free in trigger_config_run_type()
+    - i2c: iproc: fix race between client unreg and isr
+    - mfd: dln2: Run event handler loop under spinlock
+    - crypto: algif_aead - fix uninitialized ctx->init
+    - ALSA: echoaudio: Fix potential Oops in snd_echo_resume()
+    - perf bench mem: Always memset source before memcpy
+    - tools build feature: Quote CC and CXX for their arguments
+    - perf/x86/rapl: Fix missing psys sysfs attributes
+    - sh: landisk: Add missing initialization of sh_io_port_base
+    - khugepaged: retract_page_tables() remember to test exit
+    - arm64: dts: marvell: espressobin: add ethernet alias
+    - drm/panfrost: Use kvfree() to free bo->sgts
+    - drm: Added orientation quirk for ASUS tablet model T103HAF
+    - drm: fix drm_dp_mst_port refcount leaks in drm_dp_mst_allocate_vcpi
+    - drm/amdgpu: Fix bug where DPM is not enabled after hibernate and resume
+    - drm/amd/display: dchubbub p-state warning during surface planes switch
+    - Linux 5.4.60
+    - kprobes: Fix compiler warning for !CONFIG_KPROBES_ON_FTRACE
+  * Focal update: v5.4.59 upstream stable release (LP: #1892417)
+    - tracepoint: Mark __tracepoint_string's __used
+    - HID: input: Fix devices that return multiple bytes in battery report
+    - nvme: add a Identify Namespace Identification Descriptor list quirk
+    - fs/io_uring.c: Fix uninitialized variable is referenced in io_submit_sqe
+    - clk: qcom: clk-rpmh: Wait for completion when enabling clocks
+    - x86/mce/inject: Fix a wrong assignment of i_mce.status
+    - sched/fair: Fix NOHZ next idle balance
+    - sched: correct SD_flags returned by tl->sd_flags()
+    - arm64: dts: rockchip: fix rk3368-lion gmac reset gpio
+    - arm64: dts: rockchip: fix rk3399-puma vcc5v0-host gpio
+    - arm64: dts: rockchip: fix rk3399-puma gmac reset gpio
+    - EDAC: Fix reference count leaks
+    - crc-t10dif: Fix potential crypto notify dead-lock
+    - arm64: dts: qcom: msm8916: Replace invalid bias-pull-none property
+    - crypto: ccree - fix resource leak on error path
+    - ARM: exynos: MCPM: Restore big.LITTLE cpuidle support
+    - firmware: arm_scmi: Fix SCMI genpd domain probing
+    - arm64: dts: exynos: Fix silent hang after boot on Espresso
+    - sched/uclamp: Fix initialization of struct uclamp_rq
+    - clk: scmi: Fix min and max rate when registering clocks with discrete rates
+    - m68k: mac: Don't send IOP message until channel is idle
+    - m68k: mac: Fix IOP status/control register writes
+    - platform/x86: intel-hid: Fix return value check in check_acpi_dev()
+    - platform/x86: intel-vbtn: Fix return value check in check_acpi_dev()
+    - ARM: dts: gose: Fix ports node name for adv7180
+    - ARM: dts: gose: Fix ports node name for adv7612
+    - ARM: at91: pm: add missing put_device() call in at91_pm_sram_init()
+    - ARM: dts: sunxi: bananapi-m2-plus-v1.2: Add regulator supply to all CPU
+      cores
+    - ARM: dts: sunxi: bananapi-m2-plus-v1.2: Fix CPU supply voltages
+    - spi: lantiq: fix: Rx overflow error in full duplex mode
+    - tpm: Require that all digests are present in TCG_PCR_EVENT2 structures
+    - recordmcount: only record relocation of type R_AARCH64_CALL26 on arm64.
+    - regulator: fix memory leak on error path of regulator_register()
+    - io_uring: fix sq array offset calculation
+    - spi: rockchip: Fix error in SPI slave pio read
+    - ARM: socfpga: PM: add missing put_device() call in
+      socfpga_setup_ocram_self_refresh()
+    - iocost: Fix check condition of iocg abs_vdebt
+    - irqchip/ti-sci-inta: Fix return value about devm_ioremap_resource()
+    - seccomp: Fix ioctl number for SECCOMP_IOCTL_NOTIF_ID_VALID
+    - md: raid0/linear: fix dereference before null check on pointer mddev
+    - nvme-tcp: fix controller reset hang during traffic
+    - nvme-rdma: fix controller reset hang during traffic
+    - nvme-multipath: fix logic for non-optimized paths
+    - nvme-multipath: do not fall back to __nvme_find_path() for non-optimized
+      paths
+    - drm/tilcdc: fix leak & null ref in panel_connector_get_modes
+    - soc: qcom: rpmh-rsc: Set suppress_bind_attrs flag
+    - Bluetooth: add a mutex lock to avoid UAF in do_enale_set
+    - loop: be paranoid on exit and prevent new additions / removals
+    - fs/btrfs: Add cond_resched() for try_release_extent_mapping() stalls
+    - drm/amdgpu: avoid dereferencing a NULL pointer
+    - drm/radeon: Fix reference count leaks caused by pm_runtime_get_sync
+    - crypto: aesni - Fix build with LLVM_IAS=1
+    - video: fbdev: savage: fix memory leak on error handling path in probe
+    - video: fbdev: neofb: fix memory leak in neo_scan_monitor()
+    - bus: ti-sysc: Add missing quirk flags for usb_host_hs
+    - md-cluster: fix wild pointer of unlock_all_bitmaps()
+    - drm/nouveau/kms/nv50-: Fix disabling dithering
+    - arm64: dts: hisilicon: hikey: fixes to comply with adi, adv7533 DT binding
+    - drm/etnaviv: fix ref count leak via pm_runtime_get_sync
+    - drm/nouveau: fix reference count leak in nouveau_debugfs_strap_peek
+    - drm/nouveau: fix multiple instances of reference count leaks
+    - mmc: sdhci-cadence: do not use hardware tuning for SD mode
+    - btrfs: fix lockdep splat from btrfs_dump_space_info
+    - usb: mtu3: clear dual mode of u3port when disable device
+    - drm: msm: a6xx: fix gpu failure after system resume
+    - drm/msm: Fix a null pointer access in msm_gem_shrinker_count()
+    - drm/debugfs: fix plain echo to connector "force" attribute
+    - drm/radeon: disable AGP by default
+    - irqchip/irq-mtk-sysirq: Replace spinlock with raw_spinlock
+    - mm/mmap.c: Add cond_resched() for exit_mmap() CPU stalls
+    - drm/amdgpu/display bail early in dm_pp_get_static_clocks
+    - drm/amd/powerplay: fix compile error with ARCH=arc
+    - bpf: Fix fds_example SIGSEGV error
+    - brcmfmac: keep SDIO watchdog running when console_interval is non-zero
+    - brcmfmac: To fix Bss Info flag definition Bug
+    - brcmfmac: set state of hanger slot to FREE when flushing PSQ
+    - platform/x86: asus-nb-wmi: add support for ASUS ROG Zephyrus G14 and G15
+    - iwlegacy: Check the return value of pcie_capability_read_*()
+    - gpu: host1x: debug: Fix multiple channels emitting messages simultaneously
+    - ionic: update eid test for overflow
+    - mmc: sdhci-pci-o2micro: Bug fix for O2 host controller Seabird1
+    - usb: gadget: net2280: fix memory leak on probe error handling paths
+    - bdc: Fix bug causing crash after multiple disconnects
+    - usb: bdc: Halt controller on suspend
+    - dyndbg: fix a BUG_ON in ddebug_describe_flags
+    - bcache: fix super block seq numbers comparision in register_cache_set()
+    - ACPICA: Do not increment operation_region reference counts for field units
+    - drm/msm: ratelimit crtc event overflow error
+    - drm/gem: Fix a leak in drm_gem_objects_lookup()
+    - drm/bridge: ti-sn65dsi86: Clear old error bits before AUX transfers
+    - agp/intel: Fix a memory leak on module initialisation failure
+    - mwifiex: Fix firmware filename for sd8977 chipset
+    - mwifiex: Fix firmware filename for sd8997 chipset
+    - btmrvl: Fix firmware filename for sd8977 chipset
+    - btmrvl: Fix firmware filename for sd8997 chipset
+    - video: fbdev: sm712fb: fix an issue about iounmap for a wrong address
+    - console: newport_con: fix an issue about leak related system resources
+    - video: pxafb: Fix the function used to balance a 'dma_alloc_coherent()' call
+    - ath10k: Acquire tx_lock in tx error paths
+    - iio: improve IIO_CONCENTRATION channel type description
+    - drm/etnaviv: Fix error path on failure to enable bus clk
+    - drm/arm: fix unintentional integer overflow on left shift
+    - clk: bcm63xx-gate: fix last clock availability
+    - leds: lm355x: avoid enum conversion warning
+    - Bluetooth: btusb: fix up firmware download sequence
+    - Bluetooth: btmtksdio: fix up firmware download sequence
+    - media: cxusb-analog: fix V4L2 dependency
+    - media: marvell-ccic: Add missed v4l2_async_notifier_cleanup()
+    - media: omap3isp: Add missed v4l2_ctrl_handler_free() for
+      preview_init_entities()
+    - ASoC: SOF: nocodec: add missing .owner field
+    - ASoC: Intel: bxt_rt298: add missing .owner field
+    - scsi: cumana_2: Fix different dev_id between request_irq() and free_irq()
+    - drm/mipi: use dcs write for mipi_dsi_dcs_set_tear_scanline
+    - cxl: Fix kobject memleak
+    - drm/radeon: fix array out-of-bounds read and write issues
+    - staging: vchiq_arm: Add a matching unregister call
+    - iavf: fix error return code in iavf_init_get_resources()
+    - iavf: Fix updating statistics
+    - RDMA/core: Fix bogus WARN_ON during ib_unregister_device_queued()
+    - scsi: powertec: Fix different dev_id between request_irq() and free_irq()
+    - scsi: eesox: Fix different dev_id between request_irq() and free_irq()
+    - ipvs: allow connection reuse for unconfirmed conntrack
+    - media: firewire: Using uninitialized values in node_probe()
+    - media: exynos4-is: Add missed check for pinctrl_lookup_state()
+    - media: cros-ec-cec: do not bail on device_init_wakeup failure
+    - xfs: don't eat an EIO/ENOSPC writeback error when scrubbing data fork
+    - xfs: fix reflink quota reservation accounting error
+    - RDMA/rxe: Skip dgid check in loopback mode
+    - PCI: Fix pci_cfg_wait queue locking problem
+    - drm/stm: repair runtime power management
+    - kobject: Avoid premature parent object freeing in kobject_cleanup()
+    - leds: core: Flush scheduled work for system suspend
+    - drm: panel: simple: Fix bpc for LG LB070WV8 panel
+    - phy: exynos5-usbdrd: Calibrating makes sense only for USB2.0 PHY
+    - drm/bridge: sil_sii8620: initialize return of sii8620_readb
+    - scsi: scsi_debug: Add check for sdebug_max_queue during module init
+    - mwifiex: Prevent memory corruption handling keys
+    - kernfs: do not call fsnotify() with name without a parent
+    - powerpc/rtas: don't online CPUs for partition suspend
+    - powerpc/vdso: Fix vdso cpu truncation
+    - RDMA/qedr: SRQ's bug fixes
+    - RDMA/rxe: Prevent access to wr->next ptr afrer wr is posted to send queue
+    - ima: Have the LSM free its audit rule
+    - staging: rtl8192u: fix a dubious looking mask before a shift
+    - ASoC: meson: fixes the missed kfree() for axg_card_add_tdm_loopback
+    - PCI/ASPM: Add missing newline in sysfs 'policy'
+    - phy: renesas: rcar-gen3-usb2: move irq registration to init
+    - powerpc/book3s64/pkeys: Use PVR check instead of cpu feature
+    - drm/imx: fix use after free
+    - drm/imx: tve: fix regulator_disable error path
+    - gpu: ipu-v3: Restore RGB32, BGR32
+    - spi: lantiq-ssc: Fix warning by using WQ_MEM_RECLAIM
+    - USB: serial: iuu_phoenix: fix led-activity helpers
+    - usb: core: fix quirks_param_set() writing to a const pointer
+    - thermal: ti-soc-thermal: Fix reversed condition in
+      ti_thermal_expose_sensor()
+    - coresight: tmc: Fix TMC mode read in tmc_read_unprepare_etb()
+    - powerpc/perf: Fix missing is_sier_aviable() during build
+    - mt76: mt7615: fix potential memory leak in mcu message handler
+    - phy: armada-38x: fix NETA lockup when repeatedly switching speeds
+    - MIPS: OCTEON: add missing put_device() call in dwc3_octeon_device_init()
+    - usb: dwc2: Fix error path in gadget registration
+    - usb: gadget: f_uac2: fix AC Interface Header Descriptor wTotalLength
+    - scsi: megaraid_sas: Clear affinity hint
+    - scsi: mesh: Fix panic after host or bus reset
+    - net: dsa: mv88e6xxx: MV88E6097 does not support jumbo configuration
+    - macintosh/via-macii: Access autopoll_devs when inside lock
+    - PCI: cadence: Fix updating Vendor ID and Subsystem Vendor ID register
+    - RDMA/core: Fix return error value in _ib_modify_qp() to negative
+    - Smack: fix another vsscanf out of bounds
+    - Smack: prevent underflow in smk_set_cipso()
+    - power: supply: check if calc_soc succeeded in pm860x_init_battery
+    - Bluetooth: hci_h5: Set HCI_UART_RESET_ON_INIT to correct flags
+    - Bluetooth: hci_serdev: Only unregister device if it was registered
+    - net: dsa: rtl8366: Fix VLAN semantics
+    - net: dsa: rtl8366: Fix VLAN set-up
+    - xfs: fix inode allocation block res calculation precedence
+    - selftests/powerpc: Squash spurious errors due to device removal
+    - powerpc/32s: Fix CONFIG_BOOK3S_601 uses
+    - powerpc/boot: Fix CONFIG_PPC_MPC52XX references
+    - selftests/powerpc: Fix CPU affinity for child process
+    - RDMA/netlink: Remove CAP_NET_RAW check when dump a raw QP
+    - PCI: Release IVRS table in AMD ACS quirk
+    - [Config] update config for ARMADA_AP_CPU_CLK
+    - cpufreq: ap806: fix cpufreq driver needs ap cpu clk
+    - selftests/powerpc: Fix online CPU selection
+    - ASoC: meson: axg-tdm-interface: fix link fmt setup
+    - ASoC: meson: axg-tdmin: fix g12a skew
+    - ASoC: meson: axg-tdm-formatters: fix sclk inversion
+    - ASoC: fsl_sai: Fix value of FSL_SAI_CR1_RFW_MASK
+    - s390/qeth: don't process empty bridge port events
+    - ice: Graceful error handling in HW table calloc failure
+    - rtw88: fix LDPC field for RA info
+    - rtw88: fix short GI capability based on current bandwidth
+    - rtw88: coex: only skip coex triggered by BT info
+    - wl1251: fix always return 0 error
+    - tools, build: Propagate build failures from tools/build/Makefile.build
+    - tools, bpftool: Fix wrong return value in do_dump()
+    - net/mlx5: DR, Change push vlan action sequence
+    - net/mlx5: Delete extra dump stack that gives nothing
+    - net: ethernet: aquantia: Fix wrong return value
+    - liquidio: Fix wrong return value in cn23xx_get_pf_num()
+    - net: spider_net: Fix the size used in a 'dma_free_coherent()' call
+    - fsl/fman: use 32-bit unsigned integer
+    - fsl/fman: fix dereference null return value
+    - fsl/fman: fix unreachable code
+    - fsl/fman: check dereferencing null pointer
+    - fsl/fman: fix eth hash table allocation
+    - net: thunderx: initialize VF's mailbox mutex before first usage
+    - dlm: Fix kobject memleak
+    - ocfs2: fix unbalanced locking
+    - pinctrl-single: fix pcs_parse_pinconf() return value
+    - svcrdma: Fix page leak in svc_rdma_recv_read_chunk()
+    - x86/fsgsbase/64: Fix NULL deref in 86_fsgsbase_read_task
+    - crypto: aesni - add compatibility with IAS
+    - af_packet: TPACKET_V3: fix fill status rwlock imbalance
+    - drivers/net/wan/lapbether: Added needed_headroom and a skb->len check
+    - net: Fix potential memory leak in proto_register()
+    - net/nfc/rawsock.c: add CAP_NET_RAW check.
+    - net: phy: fix memory leak in device-create error path
+    - net: Set fput_needed iff FDPUT_FPUT is set
+    - net/tls: Fix kmap usage
+    - vmxnet3: use correct tcp hdr length when packet is encapsulated
+    - net: refactor bind_bucket fastreuse into helper
+    - net: initialize fastreuse on inet_inherit_port
+    - USB: serial: cp210x: re-enable auto-RTS on open
+    - USB: serial: cp210x: enable usb generic throttle/unthrottle
+    - ALSA: hda - fix the micmute led status for Lenovo ThinkCentre AIO
+    - ALSA: usb-audio: Creative USB X-Fi Pro SB1095 volume knob support
+    - ALSA: usb-audio: fix overeager device match for MacroSilicon MS2109
+    - ALSA: usb-audio: work around streaming quirk for MacroSilicon MS2109
+    - 9p: Fix memory leak in v9fs_mount
+    - media: media-request: Fix crash if memory allocation fails
+    - drm/ttm/nouveau: don't call tt destroy callback on alloc failure.
+    - io_uring: set ctx sq/cq entry count earlier
+    - NFS: Don't move layouts to plh_return_segs list while in use
+    - NFS: Don't return layout segments that are in use
+    - cpufreq: Fix locking issues with governors
+    - cpufreq: dt: fix oops on armada37xx
+    - include/asm-generic/vmlinux.lds.h: align ro_after_init
+    - spi: spidev: Align buffers for DMA
+    - mtd: rawnand: qcom: avoid write to unavailable register
+    - erofs: fix extended inode could cross boundary
+    - Revert "parisc: Drop LDCW barrier in CAS code when running UP"
+    - Revert "parisc: Use ldcw instruction for SMP spinlock release barrier"
+    - Revert "parisc: Revert "Release spinlocks using ordered store""
+    - parisc: Do not use an ordered store in pa_tlb_lock()
+    - parisc: Implement __smp_store_release and __smp_load_acquire barriers
+    - parisc: mask out enable and reserved bits from sba imask
+    - ARM: 8992/1: Fix unwind_frame for clang-built kernels
+    - irqdomain/treewide: Free firmware node after domain removal
+    - ALSA: usb-audio: add quirk for Pioneer DDJ-RB
+    - tpm: Unify the mismatching TPM space buffer sizes
+    - pstore: Fix linking when crypto API disabled
+    - crypto: hisilicon - don't sleep of CRYPTO_TFM_REQ_MAY_SLEEP was not
+      specified
+    - crypto: qat - fix double free in qat_uclo_create_batch_init_list
+    - crypto: ccp - Fix use of merged scatterlists
+    - crypto: cpt - don't sleep of CRYPTO_TFM_REQ_MAY_SLEEP was not specified
+    - bitfield.h: don't compile-time validate _val in FIELD_FIT
+    - fs/minix: check return value of sb_getblk()
+    - fs/minix: don't allow getting deleted inodes
+    - fs/minix: reject too-large maximum file size
+    - xen/balloon: fix accounting in alloc_xenballooned_pages error path
+    - xen/balloon: make the balloon wait interruptible
+    - xen/gntdev: Fix dmabuf import with non-zero sgt offset
+    - s390/dasd: fix inability to use DASD with DIAG driver
+    - s390/gmap: improve THP splitting
+    - io_uring: Fix NULL pointer dereference in loop_rw_iter()
+    - Linux 5.4.59
+  * Regression on NFS: unable to handle page fault in mempool_alloc_slab
+    (LP: #1886277) // Focal update: v5.4.59 upstream stable release
+    (LP: #1892417)
+    - SUNRPC: Fix ("SUNRPC: Add "@len" parameter to gss_unwrap()")
+  * Focal update: v5.4.59 upstream stable release (LP: #1892417) //
+    CVE-2019-19770 which shows this issue is not a core debugfs issue, but
+    - blktrace: fix debugfs use after free
+  * update ENA driver for LLQ acceleration mode, new hw support (LP: #1890845)
+    - net: ena: change num_queues to num_io_queues for clarity and consistency
+    - net: ena: multiple queue creation related cleanups
+    - net: ena: ethtool: get_channels: use combined only
+    - net: ena: make ethtool -l show correct max number of queues
+    - net: ena: remove redundant print of number of queues
+    - net: ena: ethtool: support set_channels callback
+    - net: ena: implement XDP drop support
+    - net: ena: Implement XDP_TX action
+    - net: ena: Add first_interrupt field to napi struct
+    - net: ena: fix default tx interrupt moderation interval
+    - net: ena: remove set but not used variable 'rx_ring'
+    - net: ena: remove set but not used variable 'hash_key'
+    - net: ena: ethtool: remove redundant non-zero check on rc
+    - net/amazon: Ensure that driver version is aligned to the linux kernel
+    - net: ena: fix broken interface between ENA driver and FW
+    - net: ena: ethtool: clean up minor indentation issue
+    - net: ena: fix incorrect setting of the number of msix vectors
+    - net: ena: fix request of incorrect number of IRQ vectors
+    - net: ena: avoid memory access violation by validating req_id properly
+    - net: ena: fix continuous keep-alive resets
+    - net: ena: Make some functions static
+    - net: ena: avoid unnecessary admin command when RSS function set fails
+    - net: ena: allow setting the hash function without changing the key
+    - net: ena: change default RSS hash function to Toeplitz
+    - net: ena: changes to RSS hash key allocation
+    - net: ena: remove code that does nothing
+    - net: ena: add unmask interrupts statistics to ethtool
+    - net: ena: add support for reporting of packet drops
+    - net: ena: drop superfluous prototype
+    - net: ena: use SHUTDOWN as reset reason when closing interface
+    - net: ena: cosmetic: remove unnecessary spaces and tabs in ena_com.h macros
+    - net: ena: cosmetic: extract code to ena_indirection_table_set()
+    - net: ena: add support for the rx offset feature
+    - net: ena: rename ena_com_free_desc to make API more uniform
+    - net: ena: use explicit variable size for clarity
+    - net: ena: fix ena_com_comp_status_to_errno() return value
+    - net: ena: simplify ena_com_update_intr_delay_resolution()
+    - net: ena: cosmetic: set queue sizes to u32 for consistency
+    - net: ena: cosmetic: fix spelling and grammar mistakes in comments
+    - net: ena: cosmetic: fix line break issues
+    - net: ena: cosmetic: remove unnecessary code
+    - net: ena: cosmetic: code reorderings
+    - net: ena: cosmetic: fix spacing issues
+    - net: ena: cosmetic: minor code changes
+    - net: ena: reduce driver load time
+    - net: ena: xdp: XDP_TX: fix memory leak
+    - net: ena: xdp: update napi budget for DROP and ABORTED
+    - ena_netdev: use generic power management
+    - net: ena: Fix using plain integer as NULL pointer in ena_init_napi_in_range
+    - net: ena: avoid unnecessary rearming of interrupt vector when busy-polling
+    - net: ena: add reserved PCI device ID
+    - net: ena: cosmetic: satisfy gcc warning
+    - net: ena: cosmetic: change ena_com_stats_admin stats to u64
+    - net: ena: add support for traffic mirroring
+    - net: ena: enable support of rss hash key and function changes
+    - net: ena: move llq configuration from ena_probe to ena_device_init()
+    - net: ena: support new LLQ acceleration mode
+  * [SRU] Fix acpi backlight issue on some thinkpads (LP: #1892010)
+    - platform/x86: thinkpad_acpi: not loading brightness_init when _BCL invalid
+  * [SRU][F/OEM-5.6] add a new OLED panel support for brightness control
+    (LP: #1887909)
+    - drm/dp: Lenovo X13 Yoga OLED panel brightness fix
+  * Realtek [10ec:c82f] Subsystem [17aa:c02f] Wifi adapter not found
+    (LP: #1886247)
+    - SAUCE: rtw88: 8822ce: add support for device ID 0xc82f
+  * KVM: Fix zero_page reference counter overflow when using KSM on KVM compute
+    host (LP: #1837810)
+    - KVM: fix overflow of zero page refcount with ksm running
+  * Fix missing HDMI Audio on another HP Desktop (LP: #1891617)
+    - ALSA: hda/hdmi: Use force connectivity quirk on another HP desktop
+  * alsa/sof: support 1 and 3 dmics (LP: #1891585)
+    - SAUCE: ASoC: SOF: intel: hda: support also devices with 1 and 3 dmics
+  * tcp_fastopen_backup_key.sh from net in ubuntu_kernel_selftests failed on
+    Eoan LPAR (LP: #1869134)
+    - tcp: correct read of TFO keys on big endian systems
+  * Fix false-negative return value for rtnetlink.sh in kselftests/net
+    (LP: #1890136)
+    - selftests: rtnetlink: correct the final return value for the test
+    - selftests: rtnetlink: make kci_test_encap() return sub-test result
+  * Focal update: v5.4.58 upstream stable release (LP: #1891387)
+    - USB: serial: qcserial: add EM7305 QDL product ID
+    - perf/core: Fix endless multiplex timer
+    - USB: iowarrior: fix up report size handling for some devices
+    - usb: xhci: define IDs for various ASMedia host controllers
+    - usb: xhci: Fix ASMedia ASM1142 DMA addressing
+    - io_uring: prevent re-read of sqe->opcode
+    - io_uring: Fix use-after-free in io_sq_wq_submit_work()
+    - Revert "ALSA: hda: call runtime_allow() for all hda controllers"
+    - ALSA: hda/realtek: Add alc269/alc662 pin-tables for Loongson-3 laptops
+    - ALSA: hda/ca0132 - Add new quirk ID for Recon3D.
+    - ALSA: hda/ca0132 - Fix ZxR Headphone gain control get value.
+    - ALSA: hda/ca0132 - Fix AE-5 microphone selection commands.
+    - ALSA: seq: oss: Serialize ioctls
+    - staging: android: ashmem: Fix lockdep warning for write operation
+    - staging: rtl8712: handle firmware load failure
+    - Staging: rtl8188eu: rtw_mlme: Fix uninitialized variable authmode
+    - Bluetooth: Fix slab-out-of-bounds read in hci_extended_inquiry_result_evt()
+    - Bluetooth: Prevent out-of-bounds read in hci_inquiry_result_evt()
+    - Bluetooth: Prevent out-of-bounds read in hci_inquiry_result_with_rssi_evt()
+    - omapfb: dss: Fix max fclk divider for omap36xx
+    - binder: Prevent context manager from incrementing ref 0
+    - Smack: fix use-after-free in smk_write_relabel_self()
+    - scripts: add dummy report mode to add_namespace.cocci
+    - vgacon: Fix for missing check in scrollback handling
+    - mtd: properly check all write ioctls for permissions
+    - leds: wm831x-status: fix use-after-free on unbind
+    - leds: lm36274: fix use-after-free on unbind
+    - leds: da903x: fix use-after-free on unbind
+    - leds: lm3533: fix use-after-free on unbind
+    - leds: 88pm860x: fix use-after-free on unbind
+    - net/9p: validate fds in p9_fd_open
+    - drm/nouveau/fbcon: fix module unload when fbcon init has failed for some
+      reason
+    - drm/nouveau/fbcon: zero-initialise the mode_cmd2 structure
+    - drm/drm_fb_helper: fix fbdev with sparc64
+    - i2c: slave: improve sanity check when registering
+    - i2c: slave: add sanity check when unregistering
+    - usb: hso: check for return value in hso_serial_common_create()
+    - net: ethernet: mtk_eth_soc: Always call mtk_gmac0_rgmii_adjust() for mt7623
+    - ALSA: hda: fix NULL pointer dereference during suspend
+    - firmware: Fix a reference count leak.
+    - cfg80211: check vendor command doit pointer before use
+    - igb: reinit_locked() should be called with rtnl_lock
+    - atm: fix atm_dev refcnt leaks in atmtcp_remove_persistent
+    - tools lib traceevent: Fix memory leak in process_dynamic_array_len
+    - Drivers: hv: vmbus: Ignore CHANNELMSG_TL_CONNECT_RESULT(23)
+    - xattr: break delegations in {set,remove}xattr
+    - Revert "powerpc/kasan: Fix shadow pages allocation failure"
+    - PCI: tegra: Revert tegra124 raw_violation_fixup
+    - ipv4: Silence suspicious RCU usage warning
+    - ipv6: fix memory leaks on IPV6_ADDRFORM path
+    - ipv6: Fix nexthop refcnt leak when creating ipv6 route info
+    - net: ethernet: mtk_eth_soc: fix MTU warnings
+    - rxrpc: Fix race between recvmsg and sendmsg on immediate call failure
+    - vxlan: Ensure FDB dump is performed under RCU
+    - net: lan78xx: replace bogus endpoint lookup
+    - appletalk: Fix atalk_proc_init() return path
+    - dpaa2-eth: Fix passing zero to 'PTR_ERR' warning
+    - hv_netvsc: do not use VF device if link is down
+    - net: gre: recompute gre csum for sctp over gre tunnels
+    - net: thunderx: use spin_lock_bh in nicvf_set_rx_mode_task()
+    - openvswitch: Prevent kernel-infoleak in ovs_ct_put_key()
+    - Revert "vxlan: fix tos value before xmit"
+    - tcp: apply a floor of 1 for RTT samples from TCP timestamps
+    - ima: move APPRAISE_BOOTPARAM dependency on ARCH_POLICY to runtime
+    - [Config] update annotations for IMA_APPRAISE_BOOTPARAM
+    - nfsd: Fix NFSv4 READ on RDMA when using readv
+    - Linux 5.4.58
+  * Focal update: v5.4.57 upstream stable release (LP: #1891064)
+    - random32: update the net random state on interrupt and activity
+    - ARM: percpu.h: fix build error
+    - random: fix circular include dependency on arm64 after addition of percpu.h
+    - random32: remove net_rand_state from the latent entropy gcc plugin
+    - random32: move the pseudo-random 32-bit definitions to prandom.h
+    - arm64: Workaround circular dependency in pointer_auth.h
+    - ext4: fix direct I/O read error
+    - selftests: bpf: Fix detach from sockmap tests
+    - bpf: sockmap: Require attach_bpf_fd when detaching a program
+    - Linux 5.4.57
+  * Focal update: v5.4.56 upstream stable release (LP: #1891063)
+    - crypto: ccp - Release all allocated memory if sha type is invalid
+    - media: rc: prevent memory leak in cx23888_ir_probe
+    - sunrpc: check that domain table is empty at module unload.
+    - ath10k: enable transmit data ack RSSI for QCA9884
+    - PCI/ASPM: Disable ASPM on ASMedia ASM1083/1085 PCIe-to-PCI bridge
+    - mm/filemap.c: don't bother dropping mmap_sem for zero size readahead
+    - ALSA: usb-audio: Add implicit feedback quirk for SSL2
+    - ALSA: hda/realtek: enable headset mic of ASUS ROG Zephyrus G15(GA502) series
+      with ALC289
+    - ALSA: hda/realtek: typo_fix: enable headset mic of ASUS ROG Zephyrus
+      G14(GA401) series with ALC289
+    - ALSA: hda/realtek: Fix add a "ultra_low_power" function for intel reference
+      board (alc256)
+    - ALSA: hda/hdmi: Fix keep_power assignment for non-component devices
+    - IB/rdmavt: Fix RQ counting issues causing use of an invalid RWQE
+    - vhost/scsi: fix up req type endian-ness
+    - 9p/trans_fd: Fix concurrency del of req_list in p9_fd_cancelled/p9_read_work
+    - wireless: Use offsetof instead of custom macro.
+    - ARM: 8986/1: hw_breakpoint: Don't invoke overflow handler on uaccess
+      watchpoints
+    - ARM: dts: imx6sx-sabreauto: Fix the phy-mode on fec2
+    - ARM: dts: imx6sx-sdb: Fix the phy-mode on fec2
+    - ARM: dts: imx6qdl-icore: Fix OTG_ID pin and sdcard detect
+    - virtio_balloon: fix up endian-ness for free cmd id
+    - Revert "drm/amdgpu: Fix NULL dereference in dpm sysfs handlers"
+    - drm/amd/display: Clear dm_state for fast updates
+    - drm/amdgpu: Prevent kernel-infoleak in amdgpu_info_ioctl()
+    - drm/dbi: Fix SPI Type 1 (9-bit) transfer
+    - drm: hold gem reference until object is no longer accessed
+    - rds: Prevent kernel-infoleak in rds_notify_queue_get()
+    - libtraceevent: Fix build with binutils 2.35
+    - net/x25: Fix x25_neigh refcnt leak when x25 disconnect
+    - net/x25: Fix null-ptr-deref in x25_disconnect
+    - ARM: dts sunxi: Relax a bit the CMA pool allocation range
+    - xfrm: Fix crash when the hold queue is used.
+    - ARM: dts: armada-38x: fix NETA lockup when repeatedly switching speeds
+    - nvme-tcp: fix possible hang waiting for icresp response
+    - selftests/net: rxtimestamp: fix clang issues for target arch PowerPC
+    - selftests/net: psock_fanout: fix clang issues for target arch PowerPC
+    - selftests/net: so_txtime: fix clang issues for target arch PowerPC
+    - sh/tlb: Fix PGTABLE_LEVELS > 2
+    - sh: Fix validation of system call number
+    - net: hns3: fix a TX timeout issue
+    - net: hns3: fix aRFS FD rules leftover after add a user FD rule
+    - net/mlx5: E-switch, Destroy TSAR when fail to enable the mode
+    - net/mlx5e: Fix error path of device attach
+    - net/mlx5: Verify Hardware supports requested ptp function on a given pin
+    - net/mlx5e: Modify uplink state on interface up/down
+    - net/mlx5e: Fix kernel crash when setting vf VLANID on a VF dev
+    - net: lan78xx: add missing endpoint sanity check
+    - net: lan78xx: fix transfer-buffer memory leak
+    - rhashtable: Fix unprotected RCU dereference in __rht_ptr
+    - mlx4: disable device on shutdown
+    - mlxsw: core: Increase scope of RCU read-side critical section
+    - mlxsw: core: Free EMAD transactions using kfree_rcu()
+    - ibmvnic: Fix IRQ mapping disposal in error path
+    - bpf: Fix map leak in HASH_OF_MAPS map
+    - mac80211: mesh: Free ie data when leaving mesh
+    - mac80211: mesh: Free pending skb when destroying a mpath
+    - arm64/alternatives: move length validation inside the subsection
+    - arm64: csum: Fix handling of bad packets
+    - Bluetooth: fix kernel oops in store_pending_adv_report
+    - net: nixge: fix potential memory leak in nixge_probe()
+    - net: gemini: Fix missing clk_disable_unprepare() in error path of
+      gemini_ethernet_port_probe()
+    - net/mlx5e: fix bpf_prog reference count leaks in mlx5e_alloc_rq
+    - perf tools: Fix record failure when mixed with ARM SPE event
+    - vxlan: fix memleak of fdb
+    - usb: hso: Fix debug compile warning on sparc32
+    - selftests: fib_nexthop_multiprefix: fix cleanup() netns deletion
+    - qed: Disable "MFW indication via attention" SPAM every 5 minutes
+    - selftests: net: ip_defrag: modprobe missing nf_defrag_ipv6 support
+    - nfc: s3fwrn5: add missing release on skb in s3fwrn5_recv_frame
+    - scsi: core: Run queue in case of I/O resource contention failure
+    - parisc: add support for cmpxchg on u8 pointers
+    - net: ethernet: ravb: exit if re-initialization fails in tx timeout
+    - Revert "i2c: cadence: Fix the hold bit setting"
+    - x86/unwind/orc: Fix ORC for newly forked tasks
+    - x86/stacktrace: Fix reliable check for empty user task stacks
+    - cxgb4: add missing release on skb in uld_send()
+    - xen-netfront: fix potential deadlock in xennet_remove()
+    - RISC-V: Set maximum number of mapped pages correctly
+    - drivers/net/wan: lapb: Corrected the usage of skb_cow
+    - KVM: arm64: Don't inherit exec permission across page-table levels
+    - KVM: LAPIC: Prevent setting the tscdeadline timer if the lapic is hw
+      disabled
+    - x86/i8259: Use printk_deferred() to prevent deadlock
+    - perf tests bp_account: Make global variable static
+    - perf env: Do not return pointers to local variables
+    - perf bench: Share some global variables to fix build with gcc 10
+    - Linux 5.4.56
+
+  [ Ubuntu: 5.4.0-47.51 ]
+
+  * focal/linux: 5.4.0-47.51 -proposed tracker (LP: #1894315)
+  * CVE-2020-14386
+    - SAUCE: net/packet: fix overflow in tpacket_rcv
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update helper scripts
+
+  [ Ubuntu: 5.4.0-45.49 ]
+
+  * focal/linux: 5.4.0-45.49 -proposed tracker (LP: #1893050)
+  * [Potential Regression] dscr_inherit_exec_test from powerpc in
+    ubuntu_kernel_selftests failed on B/E/F (LP: #1888332)
+    - powerpc/64s: Don't init FSCR_DSCR in __init_FSCR()
+
+ -- Wen-chien Jesse Sung <jesse.sung@canonical.com>  Mon, 19 Oct 2020 19:29:32 +0800
+
+linux-xilinx-zynqmp (5.4.0-1000.1) focal; urgency=medium
+
+  * Miscellaneous Ubuntu changes
+    - [Config] import configs
+
+  * Miscellaneous upstream changes
+    - microblaze: entry: Remove unneeded need_resched() loop
+    - microblaze: defconfig: Enable devtmps and tmpfs
+    - microblaze: Enable SPARSE_IRQ
+    - microblaze: Increase max dtb size to 64K from 32K
+    - PCI: Remove PCI_MSI_IRQ_DOMAIN architecture whitelist
+    - soc: xilinx: Set CAP_UNUSABLE requirement for versal while powering down
+      domain
+    - dt-bindings: firmware: Add bindings for Versal firmware
+    - firmware: xilinx: Add support for versal soc
+    - arm64: zynqmp: Add firmware DT node
+    - arm64: zynqmp: Add support for zynqmp fpga manager
+    - arm64: zynqmp: Label whole PL part as fpga_full region
+    - arm64: zynqmp: Add support for zynqmp nvmem firmware driver
+    - dt-bindings: clock: Add bindings for versal clock driver
+    - clk: zynqmp: Extend driver for versal
+    - mtd: rawnand: Add sync and async timing mode support
+    - mtd: rawnand: Add jedec_id to struct onfi_params
+    - dt-bindings: mtd: Document ARASAN NAND bindings
+    - arm64: dts: Add NAND Device support
+    - mtd: rawnand: Add support for ARASAN NAND controller
+    - mtd: rawnand: arasan: Add runtime support
+    - can: xilinx_can: skip error message on deferred probe
+    - can: xilinx_can: Fix usage of skb memory
+    - serial: xilinx_uartps: Let get_mctrl return status
+    - serial: xilinx_uartps: set_termios sets flowcontrol
+    - serial: xilinx_uartps: set_mctrl sets RTS and DTR
+    - dt-bindings: add documentation of xilinx clocking wizard
+    - clk: clock-wizard: Move the clockwizard to clk
+    - clk: clock-wizard: Fix kernel-doc warning
+    - clk: clock-wizard: Add support for dynamic reconfiguration
+    - clk: clock-wizard: Add support for fractional support
+    - clk: clock-wizard: Remove the hardcoding of the clock outputs
+    - clk: clock-wizard: Update the fixed factor divisors
+    - staging: clocking-wizard: Delete the driver from the staging
+    - clk: zynqmp: Add support for clock with CLK_DIVIDER_POWER_OF_TWO flag
+    - clk: zynqmp: Add support for custom type flags
+    - clk: zynqmp: Correct bit index for divider flag
+    - clk: zynqmp: Fix divider calculation
+    - clk: zynqmp: Warn user if clock user are more than allowed
+    - drivers: firmware: xilinx: Add support for feature check
+    - arm64: dts: xilinx: Add the clock nodes for zynqmp
+    - arm64: dts: xilinx: Remove dtsi for fixed clock
+    - arm64: dts: xilinx: Add the power nodes for zynqmp
+    - dt-bindings: power: reset: xilinx: Add bindings for ipi mailbox
+    - drivers: soc: xilinx: Use mailbox IPI callback
+    - firmware: xilinx: provides support to access efuse
+    - firmware: xilinx: Add pinctrl interface
+    - firmware: xilinx: Added pm api functions for RSA and SHA
+    - firmware: xilinx: Adds zynqmp-aes support
+    - firmware: xilinx: Adds new eemi call for reg access
+    - firmware: xilinx: xilinx: Add sysfs interface
+    - firmware: xilinx: Add missing debug firmware interfaces
+    - firmware: xilinx: Add pm api function for PL readback
+    - firmware: xilinx: Add AFI ioctl support
+    - firmware: xilinx: Add ULPI reset support
+    - firmware: xilinx: Add zynqmp SGMII firmware support
+    - firmware: xilinx: Add sysfs to set shutdown scope
+    - firmware: xilinx: Add sysfs and IOCTL to set boot health status
+    - firmware: xilinx: Add qspi firmware interface
+    - firmware: xilinx: Add firmware support for remoteproc
+    - firmware: xilinx: Add Pdi load API support
+    - firmware: xilinx: xilinx: Add IOCTL ids for probe counter
+    - firmware: xilinx: sync firmware pm_ioctl_id entries with PLM pm_ioctl_id
+      entries
+    - firmware: xilinx: Add IOCTL for handling usb power requests
+    - firmware: xilinx: Allow valid IOCTL ids only for versal
+    - dt-bindings: Add dt bindings for flex noc Performance Monitor
+    - misc: xilinx_flex: Add support for the flex noc Performance Monitor
+    - Documentation: short descriptions for Flexnoc Performance Monitor driver
+    - rtc: xilinx: Fix calibval variable type
+    - rtc: zynqmp: re-use rtc_time64_to_tm operation
+    - rtc: zynqmp: Clear alarm interrupt status before interrupt enable
+    - dt-bindings: dmaengine: xilinx_dma: Remove axidma multichannel support
+    - dmaengine: xilinx_dma: use devm_platform_ioremap_resource()
+    - dmaengine: xilinx_dma: Remove clk_get error message for probe defer
+    - dmaengine: xilinx_dma: Remove desc_callback_valid check
+    - dmaengine: xilinx_dma: Merge get_callback and _invoke
+    - dmaengine: xilinx_dma: Remove residue from channel data
+    - dmaengine: xilinx_dma: Introduce xilinx_dma_get_residue
+    - dmaengine: xilinx_dma: Add callback_result support
+    - dmaengine: xilinx_dma: Print debug message when no free tx segments
+    - dmaengine: xilinx_dma: Remove axidma multichannel mode support
+    - dt-bindings: dmaengine: xilinx_dma: Fix formatting and style
+    - dt-bindings: dmaengine: xilinx_dma: Add binding for Xilinx MCDMA IP
+    - dmaengine: xilinx_dma: Extend dma_config struct to store irq routine handle
+    - dmaengine: xilinx_dma: Add Xilinx AXI MCDMA Engine driver support
+    - dt-bindings: dmaengine: Add binding for xilinx axidma test client
+    - dmaengine: xilinx: Add axidmatest test client code
+    - dt-bindings: dmaengine: Add binding for vdmatest client
+    - dmaengine: xilinx: Add vdmatest test client code
+    - mm: page_alloc: Demote the PFNs busy message to debug
+    - uio: Add dma-buf import ioctls
+    - dt-bindings: soc: xilinx: Add the dt binding for AI engine
+    - uio: Add the UIO driver for AI engine
+    - uio: xilinx_ai_engine: Map the dynamic memory as write-combine
+    - staging: dt-bindings: Add doc about APF
+    - apf: Add kernel modules to the kernel
+    - dt: bindings: sound: Add DT bindings for Xilinx ZynqMP DP audio
+    - sound: soc: xilinx: Add ZynqMP DP subsystem audio drivers
+    - sound: xilinx: pcm: Set the shorter device name
+    - sound: soc: xilinx: Remove empty xilinx_dp_remove()
+    - sound: soc: xilinx: Remove empty xilinx_dp_pcm_dev_remove()
+    - AsoC: xlnx: add platform driver to support SDI audio
+    - ASoC: xlnx: add capture component DAI
+    - ASoC: xlnx: add playback component DAI
+    - ASoC: xlnx: add pcm formatter platform driver
+    - ASoC: xlnx: Enable audio formatter build
+    - ASoC: xlnx: add alsa pcm device support
+    - ASoC: xlnx: Enable SDI audio build
+    - ASoC: xlnx: add PL sound card device creation
+    - ASoC: xlnx: add PL sound card support
+    - ASoC: xlnx: update SDI audio driver to v2.0
+    - ASoC: xlnx: Use graph API instead of phandle
+    - ASoC: xlnx: add new supported formats
+    - ASoC: xlnx: remove SDI Rx AES parsing
+    - ASoC: xlnx: correct the audio formatter masks
+    - ASoC: xlnx: Move audio interface node names to driver data
+    - ASoC: xlnx: Add AES channel status parsing
+    - ASoC: xlnx: Reset S2MM for next channel status update
+    - ASoC: xlnx: enable axi clock in audio formatter
+    - ASoC: xlnx: support multiple sampling rates for HDMI
+    - ASoC: xlnx: support multiple sampling rates for SDI
+    - ASoC: xlnx: Set missing/invalid channel count to default value in consumer
+      format
+    - ASoC: xlnx: disable strict check of AES parameters
+    - ASoC: xlnx: Disable clock wizard usage in audio driver
+    - dt-bindings: ASoC: xlnx,spdif: Document spdif bindings
+    - ASoC: xlnx: add SPDIF audio driver
+    - ASoC: xlnx: add SPDIF sound card support
+    - ASoC: xlnx: enable SPDIF build
+    - ASoC: xlnx: Fixes in audio formatter driver
+    - ASoC: xlnx: refine audio formatter irq enablement
+    - ASoC: xlnx: support multiple instances of sound card
+    - ASoC: xlnx: enable multi sample rate support for I2S sound card
+    - ASoC: xlnx: enable multi sample rate support for HDMI sound card
+    - ASoC: xlnx: enable multi sample rate support for SPDIF sound card
+    - dt-bindings: ASoC: xlnx-v-uhdsdi-audio: document sdi audio bindings
+    - dt-bindings: ASoC: Document audio formatter bindings for xlnx,audio-
+      formatter
+    - ASoC: xlnx,i2s: dt-bindings: add reference to audio formatter
+    - ASoC: xlnx: add audio support in 4k mode
+    - ASoC: xlnx: add multi sample rate support for SDI audio
+    - ASoC: xlnx: clear bits before assigning desired value
+    - ASoC: xlnx: reuse framework macros to parse AES audio header
+    - dt-bindings: dma: xilinx: dpdma: DT bindings for Xilinx DPDMA
+    - dma: xilinx: dpdma: Add the Xilinx DisplayPort DMA engine driver
+    - dma: xilinx: dpdma: Implement the synchronize callback
+    - drm: drm_fourcc: Introduce macro-pixel info to drm_format_info
+    - drm: fourcc: Add drm_format_plane_width_bytes()
+    - drm: drm_fourcc: Add new formats for Xilinx IPs
+    - drm: fourcc: Add new formats needed by Xilinx IP
+    - drm: drm_fourcc: Correct the DRM YUV444 10bpc
+    - uapi: drm: Add AVUY fourcc
+    - drm: Add new flags for interlaced alternate fields
+    - uapi: media: New fourcc codes needed by Xilinx Video IP
+    - media: Add documentation for YUV420 bus format
+    - dt-bindings: dmaengine: xilinx_frmbuf: Video Framebuffer IP
+    - dmaengine: xilinx_frmbuf: New driver for Video Framebuffer IP
+    - dmaengine: xilinx_frmbuf: Update Framebuffer Driver with support for new
+      8-bit/10-bit formats
+    - dmaengine: xilinx_frmbuf: Add support for BGR8 color format in Framebuffer
+    - dmaengine: xilinx_frmbuf: Add support for XV15 and XV20 contiguous formats
+    - dmaengine: xilinx_frmbuf: Add interlaced support to Xilinx Framebuffer
+      driver
+    - dmaengine: xilinx_frmbuf: Add alpha formats support for Framebuffer Read
+    - dmaengine: xilinx_frmbuf: Get DMA alignment from device tree for Framebuffer
+    - dmaengine: xilinx_frmbuf: Flush the framebuffer FIFO on halt
+    - dmaengine: xilinx_frmbuf: Add fid property for interlaced support in
+      framebuffer
+    - dmaengine: xilinx_frmbuf: Add check for max width and height in Framebuffer
+      Read/Write
+    - dmaengine: xilinx_frmbuf: Mark previous active decriptor as complete in irq
+      handler
+    - dmaengine: xilinx_frmbuf: Add API to set framebuffer IP mode
+    - dmaengine: xilinx_frmbuf: Add early callback support to Framebuffer Driver
+    - dmaengine: xilinx_frmbuf: Add clock framework support to Framebuffer driver
+    - dmaengine: xilinx_frmbuf: Fix compilation errors when kernel config doesn't
+      have Framebuffer
+    - drm: panel: Added timing for AUO B101UAN01 display panel
+    - drm: Add adv7511 encoder driver
+    - media: entity: Add has_route entity operation
+    - media: entity: Add media_entity_has_route() function
+    - v4l: subdev: Add [GS]_ROUTING subdev ioctls and operations
+    - v4l: Add RGB 8:8:8 media bus format on 24 and 32 bit busses
+    - v4l: Add VUY8 24 bits bus format
+    - uvcvideo: Xilinx: Bump up URBS and MAX_PACKETS
+    - drm: ZynQ OpenCL driver
+    - v4l: xilinx: Kconfig: Add missing DMADEVICES dependencies
+    - media: xilinx: Ensure Video Framebuffer selected by Kconfig
+    - v4l: xilinx: Add Video Remapper driver
+    - media: xilinx: Add Color Filter Array (CFA) driver
+    - media: xilinx: Add Chroma Resampler (CRESAMPLE) driver
+    - media: xilinx: Add RGB to YUV (RGB2YUV) driver
+    - media: xilinx: Add Scaler driver (SCALER) driver
+    - media: xilinx: Add AXI4 stream switch driver
+    - media: xilinx: Add HLS core driver
+    - media: xilinx: Integrate TPG v7 support
+    - media: xilinx: Use xvip_write to update background pattern
+    - media: xilinx: Add "Pseudorandom" pattern support
+    - media: xilinx: Make use of MEDIA_BUS_FMT definitions
+    - media: xilinx: Skip checking bayer phase
+    - media: xilinx: Use GPIO to assert TPG reset
+    - media: xilinx: Fix TPG incorrect pattern on resolution switch
+    - media: xilinx: Fix "maybe used uninitialized" warning
+    - media: xilinx: tpg: Block comments
+    - media: xilinx: Refactor VTC configuration code
+    - media: xilinx: vip: Add the pixel format for RGB24
+    - v4l: xilinx-dma: Update xvip_dma_init routine to allow for probe defer
+    - v4l: xilinx: dma: Terminate DMA when stream on fails
+    - media: xilinx: dma: Enable use of Framebuffer Write IP in V4L2 Driver
+    - v4l: xilinx: dma: Remove colorspace check in xvip_dma_verify_format
+    - media: xilinx: Improve pipeline management code
+    - xcsi2rxss: Add DT documentation for Xilinx MIPI CSI-2 Receiver Subsystem
+      driver
+    - xcsi2rxss: Add support for Xilinx CSI-2 Receiver Subsystem
+    - documentation: dt: add bindings documentation for xilinx video demosaic
+      driver
+    - v4l: xilinx-demosaic: driver support for xilinx video demosaic
+    - documentation: dt: add bindings documentation for vpss scaler
+    - v4l: xilinx-vpss-scaler: driver support for xilinx vpss scaler
+    - dt: bindings: media: xilinx: Documentation for Xilinx UHDSDI Rx driver
+    - v4l: xilinx: Driver support for Xilinx UHDSDI Rx subsystem
+    - documentation: dt: add bindings documentation for gamma lut ip
+    - v4l: xilinx-gamma: initial driver support for xilinx video gamma lut ip
+    - Documentation: DT: Add bindings documentation for VPSS CSC
+    - v4l: xilinx-vpss-csc: driver support for xilinx vpss csc
+    - drivers: media: Customized adv7511 for Xylon LogiCVC (deprecated)
+    - drm: mipi: Bring DT format description closer to the hardware
+    - v4l: xilinx: sdirxss: Decode ST352 in irq context
+    - v4l: xilinx: sdirxss: Add ST352 decode macros
+    - v4l: xilinx: sdirxss: Add support for subdev get frame interval
+    - v4l: xilinx: sdirxss: Add v4l control for transport stream type
+    - v4l: xilinx: sdirxss: Add V4L control for Active streams
+    - v4l: xilinx: sdirxss: Add V4L control for 3G Level B support
+    - v4l: xilinx: sdirxss: Remove useless semicolon
+    - drm: xlnx: Xilinx DRM KMS driver
+    - dt-bindings: display: xlnx: Add ZynqMP DP subsystem bindings
+    - drm: xlnx: DRM KMS driver for Xilinx ZynqMP DP subsystem display
+    - drm: xlnx: DRM KMS driver for Xilinx ZynqMP DisplayPort
+    - drm: xlnx: ZynqMP DP subsystem DRM KMS driver
+    - drm: xlnx: zynqmp_disp: Add drm properties
+    - drm: xlnx: zynqmp_dp: Add drm properties
+    - dt-bindings: display: xlnx: Add bridge bindings
+    - drm: xlnx: drv: Add Xilinx bridge support
+    - drm: xlnx: zynqmp: Add Xlnx bridge support
+    - drm: xlnx: Kconfig: Select dpdma for ZynqMP DP
+    - drm: xilinx: Kconfig: Add missing DMADEVICES dependencies
+    - dt-bindings: display: xlnx: Adding dsi bindings
+    - drm: xlnx: dsi: Adding dsi driver to new framework
+    - drm: xlnx: adding cursor width / height support
+    - dt-bindings: display: xlnx: Adding mixer bindings
+    - drm: xlnx: mixer: Initial video mixer driver
+    - dt-bindings: display: xlnx: Adding sdi bindings
+    - drm: xlnx: sdi: Adding sdi-tx driver
+    - dt-bindings: display: xlnx: Adding pl_disp bindings
+    - drm: xlnx: DRM KMS driver for xilinx display pipeline
+    - v4l: xilinx: sdirxss: Update Video lockout Window to 32 bit
+    - drm: xlnx: bridge: Fix the multiple definition error
+    - drm: xlnx: bridge: Add support for set and get output parameters
+    - dt: bindings: display: xlnx: Adding csc bindings
+    - drm: xlnx: csc: Adding vpss-color space converter driver
+    - dt: bindings: display: xlnx: Adding scaler bindings
+    - drm: xlnx: scaler: Adding vpss-scaler driver
+    - dt: bindings: media: xilinx: Add rev 3.0 to csi2rxss compatible string
+    - v4l: xilinx: csi2rxss: Add rev 3.0 compatible string
+    - drm: xlnx: xlnx_drv: Remove the dt binding
+    - drm: xlnx: zynqmp: Use xlnx pipeline calls
+    - dt-bindings: display: xlnx: zynqmp-dpsub: Update the documentation
+    - drm: xlnx: zynqmp: disp: Use the device node for layers
+    - drm: xlnx: xlnx_drv: Move xlnx bridge helper initialization
+    - dt-bindings: display: xlnx: zynqmp-dpsub: Make layers as child node
+    - Revert "drm: xlnx: zynqmp: disp: Use the device node for layers"
+    - drm: xlnx: pl_disp: Use xlnx pipeline calls
+    - drm: xlnx: mixer: Use xlnx pipeline call
+    - dt-bindings: display: xlnx: Added vpss bridge phandle as optional property
+    - drm: xlnx: bridge: Add Xilinx bridge support to set and get output
+      parameters
+    - drm: xlnx: sdi: Adding xlnx bridge support
+    - drm: xlnx: zynqmp: Add XV15 and XV20 formats
+    - dt-bindings: display: xlnx: Added vpss bridge phandle as optional property
+    - drm: xlnx: dsi: Adding xlnx bridge support
+    - dt: bindings: display: xlnx: Adding gpio reset entry
+    - drm: xlnx: scaler: Adding vpss-scaler reset through gpio
+    - media: xilinx-vpss-scaler: Zero out H-phase array before changing resolution
+    - drm: xlnx: mixer: logo layer fix
+    - drm: xlnx: drv: Allow multiple masters on a drm device
+    - drm: xlnx: scaler: Adding Zero out H-phase array before changing resolution
+    - drm: xlnx: mixer: Removing dead code
+    - drm: xlnx: mixer: Correcting the cursor width and height
+    - drm: xlnx: correcting data type for cursor with and height
+    - media: Add new dt-bindings/vf_codes for supported formats
+    - media-bus: uapi: Add YCrCb 420 media bus format
+    - v4l: xilinx: dma: Update video format descriptor
+    - v4l: xilinx: dma: Add multi-planar support
+    - v4l: xilinx: dma: Fix v4l2 enumeration callback for multiplanar
+    - v4l: xilinx: dma: Add scaling and padding factor functions
+    - v4l: xilinx: dma: Get scaling and padding factor to calculate DMA params
+    - drm: xlnx: scaler: Add YUV420 support
+    - drm: xlnx: csc: Add YUV420 support
+    - v4l: xilinx-vpss-scaler: Add YUV 420 to VPSS Scaler Driver
+    - v4l: xilinx-demosaic: Remove Output Video format register
+    - v4l: xilinx-gamma: Add 10-bit IP support for Video Gammma IP.
+    - v4l: xilinx-gamma: Add kernel-doc for xgamma_dev struct
+    - v4l: xilinx-gamma: Fix compile error in debug mode
+    - Documentation: media: Correct dt-bindings doc for Gamma LUT IP
+    - Documentation: media: Update dt-bindings doc for 10-bit color depth in vpss-
+      csc
+    - v4l: xilinx-vpss-csc: Support for any-to-any color space converison
+    - dt-bindings: display: xlnx: Modifing mixer compatible string
+    - drm: xlnx: mixer: Adding mixer 3.0 IP support
+    - drm: xlnx: mixer: Adding more colors in supported list
+    - drm: xlnx: mixer: Correcting loop termination condition
+    - drm: xlnx: mixer: Fixing wrong stride alignment
+    - v4l: xilinx-tpg: Add YUV 420 media bus format support to TPG driver
+    - drm: xlnx: sdi: Adding yuv 420 support
+    - dt: bindings: media: xilinx: Add YUV420 decoding support in UHDSDI Rx
+    - v4l: xilinx: sdirxss: Add support for YUV420 decoding
+    - media: v4l2-core: Update V4L2 framework with new fourcc codes
+    - v4l: xilinx: dma: Fix sizeimage calculation
+    - v4l: xilinx: dma: Handle 10 bit format calucations for XV20
+    - v4l: xilinx: dma: Fix bytes per line calculation
+    - v4l: xilinx: Add BGR color format support.
+    - media: xilinx: vip: Correct the fourcc code for BGRX8 format.
+    - dt: bindings: media: xilinx: Remove unimplemented TPG compatible string
+    - drm: xlnx: mixer: remove deprecated dmaengine_terminate_all
+    - drm: xlnx: mixer: reset the mixer IP before programming
+    - v4l: xilinx: dma: Add XV15 and XV20 contiguous format support
+    - v4l2-core: Update entries for XV15 and XV20 contiguous formats
+    - uvcvideo: Prevent new URBs being processed at stream stop
+    - dt: bindings: display: xlnx: Updated gpio reset entry
+    - drm: xlnx: scaler: Updating vpss-scaler reset logic
+    - dt: bindings: display: xlnx: Adding gpio reset entry
+    - drm: xlnx: csc: Adding vpss-csc reset through gpio
+    - drm: xlnx: zynqmp_dp: Use the correct number of lanes
+    - xilinx: v4l2: dma: Bug fix in single plane support
+    - drm: xlnx: drv: Shutdown the drm device properly
+    - drm: xlnx: zynqmp: Disable a plane when the fb format changes
+    - bindings: display: xlnx: Fixing device tree documentation
+    - v4l: xilinx: sdirxss: Correct the v4l2_field to V4L2_FIELD_ALTERNATE
+    - drm: xlnx: pl_disp: fix odd_ptr_err.cocci warnings
+    - dt-bindings: display: xlnx: mixer: Add supported formats table
+    - dt-bindings: display: xlnx: mixer: Update example to fix format strings
+    - drm: xlnx: fb: Prefer the current format depth over depth from fb helper
+    - v4l: xilinx: dma: Add interlaced support
+    - drm: xlnx: zynqmp: Update planes asynchronously in the legacy entry
+    - v4l: xilinx: dma: Terminate DMA when media pipeline fails to start
+    - xilinx: v4l2: dma: Add multiple output support
+    - drm: xlnx: mixer: Update planes asynchronously in the legacy entry
+    - drm: xlnx: pl_disp: fix vblank time out issue
+    - dt-bindings: display: xlnx: mixer: Added xlnx,num-layers description
+    - drm: xlnx: mixer: making logo layer optional
+    - drm: xlnx: mixer: Added the atomic check for invalid coordinates
+    - dt-bindings: display: xlnx: mixer: Adding xlnx,layer-primary property
+    - drm: xlnx: zynqmp: Don't update the plane for the same fb
+    - drm: xlnx: zynqmp_dp: Initialize dpsub without phy
+    - v4l: xilinx: sdirxss: Correct the height of SD 525i to 486
+    - drm: xlnx: bridge: Add support for VTC as bridge
+    - dt-bindings: display: xlnx: Add VTC bindings
+    - drm: xlnx: Add a Video Timing Controller(VTC) driver
+    - drm: xlnx: vtc: Remove xilinx_vtc_remove()
+    - drm: xlnx: vtc: Fix the kernel-doc warnings
+    - drm: xlnx: vtc: Use of_match_node()
+    - drm: xlnx: vtc: Return IRQ_NONE for no interrupt
+    - drm: xlnx: vtc: Block comments using a trailing */ on a separate line
+    - drm: xlnx: vtc: adding interlaced support
+    - drm: xlnx: vtc: removing hard coded values for signal polarity
+    - drm: xlnx: vtc: exporting interrupt APIs
+    - drm: xlnx: vtc: Adding VTC as bridge driver
+    - dt-bindings: display: xlnx: mixer: Adding xlnx vtc bridge support
+    - drm: xlnx: mixer: Add VTC bridge support.
+    - dt-bindings: display: xlnx: Add VTC bridge support to PL display
+    - drm: xlnx: pl_disp: Add VTC bridge support
+    - drm: xlnx: vtc: Update license to SPDX
+    - drm: xlnx: sdi: Fix VTC polarity for SD modes
+    - drm: xlnx: sdi: Fix the HSIZE calculation
+    - drm: xlnx: sdi: Fix the Vertical Field 1 Size calculation
+    - drm: xlnx: sdi: Fix the VSync_Start and VSync_End for interlaced modes
+    - drm: xlnx: zynqmp_disp: handle software vblank
+    - drm: xlnx: zynqmp_dpsub handling for DP PM
+    - drm: xlnx: zynqmp_dpsub: Support reserved memory
+    - drm: xlnx: zynqmp_disp: Modul param for initial format of gfx layer
+    - xilinx: v4l: dma: Multi-threading issue
+    - drm: xlnx: mixer: Fix bug in programming 64-bit address
+    - drm: xlnx: sdi: Add support for Field 1 Active size
+    - drm: xlnx: sdi: Program Field 1 VTC registers in interlaced mode only
+    - drm: xlnx: vtc: Add support for Field 1 Active size
+    - drm: xlnx: vtc: Program Field 1 VTC registers in interlaced mode only
+    - drm: xlnx: sdi: enable audio
+    - drm: xlnx: zynqmp_disp: Configure the coefficients for TPG
+    - dt: bindings: media: xilinx: sdirxss : Add clock framework support
+    - v4l: xilinx: sdirxss: Add support for clock framework
+    - xilinx: v4l: dma: Fix bug in calculating interlaced height
+    - dt: bindings: media: xilinx: Doc for Xilinx AXI4-Stream Switch driver
+    - v4l: xilinx: Driver support for Xilinx AXI4-Stream Switch
+    - drm: xlnx: sdi: Fix timing for 720x486i SD mode
+    - drm: xlnx: sdi: add video mode hdisplay, flags to the shared data
+    - media: platform: xilinx: Fix Kconfig indentation
+    - xilinx: v4l: dma: Add ioctl operations for v4l2 output device
+    - xilinx: v4l: dma: Add DMA input direction support
+    - xilinx: v4l: dma: Add format enumeration for output
+    - v4l: xilinx: scd: Add v4l2 custom events
+    - documentation: dt: add bindings documentation for Scene Change Detection
+    - v4l: xilinx: scd: New Scene Change Detection driver
+    - xilinx: v4l: xilinx: Fix order in Makefile
+    - documentation: dt: add bindings documentation for multi-scaler
+    - platform: xilinx: Add mem to mem Multi-Scaler driver (XM2MSC)
+    - dt: bindings: media: xilinx: Documentation for mem2mem driver
+    - xilinx: v4l: mem2mem: Initial version of driver
+    - dt-bindings: display: xlnx: Add support for ancillary port
+    - drm: xlnx: sdi: Enable support for ancillary data
+    - dt-bindings: display: xlnx: Add ST352 payload insertion in Chroma stream
+    - drm: xlnx: sdi: Add ST352 payload insertion in Chroma stream
+    - drm: xlnx: sdi: Add support for DS2 payload in 3GA mode
+    - drm: xlnx: mixer: Fix linking failure for ARCH arm
+    - v4l: dma: Use media graph traversal to stream on/off subdevs
+    - drm: fb: Modify check to ensure correctness of flags
+    - drm: xlnx: sdi: Fix clearing en_st352_c and use_ds2_3ga drm properties
+    - documentation: dt: vtpg: Add support for max width and height
+    - v4l: xilinx: tpg: Add check for max width and height
+    - documentation: dt: demosaic: add support for max width and height
+    - v4l: xilinx-demosaic: Add check for max width and height
+    - documentation: dt: gamma: Add support for max width and height
+    - v4l: xilinx-gamma: Add check for max width and height
+    - documentation: dt: vpss-csc: Add support for max width and height
+    - v4l: xilinx-vpss-csc: Add check for max width and height
+    - documentation: dt: vpss-scaler: Add support for max width and height
+    - v4l: xilinx-vpss-scaler: Add check for max width and height
+    - xilinx: v4l: m2m: Terminate the dma engine before releasing buffers
+    - drm: xlnx: pl_disp: Pass interlaced field info to frmbuf DMA
+    - v4l: xilinx: vpss-scaler: Fix array out of bound access
+    - drm: xlnx: scaler: Fix array out of bound access
+    - dt-bindings: csi2rxss: Enable VCX support
+    - v4l: xilinx: xcsi2rxss: Add VCX support
+    - drm: xlnx: mixer: Fix switching to 4K after 1080p
+    - xilinx: v4l: dma: Remove unused function definition
+    - dt-bindings: media: xilinx: demosaic: Make max width, height mandatory
+    - v4l: xilinx-demosaic: Correct default values when width, height dt property
+      absent
+    - dt-bindings: media: xilinx: vpss-csc: Make max width, height mandatory
+    - v4l: xilinx-gamma: Correct default values when max width, height dt property
+      absent
+    - v4l: xilinx: vpss-scaler: Correct default values when max width, height dt
+      property absent
+    - drm: xlnx: zynqmp_disp: Fixing potential segmentation fault
+    - xilinx: v4l: dma: In case of error xvip_pipeline_start_stop should return
+      gracefully
+    - v4l: xilinx-multi-scaler: Remove unsupported formats
+    - v4l: xilinx-multi-scaler: Add support for VIDIOC_CREATE_BUFS for Dmabuf
+      io_mode
+    - v4l: xilinx-multi-scaler: Remove unused variables min_col and min_row
+    - v4l: xilinx-multi-scaler: Return the proper parameters in S_FMT
+    - v4l: xilinx-multi-scaler: Corrects the format struct in TRY_FMT
+    - v4l: xilinx-multi-scaler: Fix buffer type in enum_fmt_vid_out
+    - v4l: xilinx-multi-scaler: ENUM_FMT map index with enabled format
+    - v4l: xilinx-multi-scaler: Allow abort for individual channels
+    - v4l: xilinx-multi-scaler: Fix stop streaming
+    - v4l: xilinx-multi-scaler: Allow device run for single channel
+    - v4l: xilinx-multi-scaler: Restructuring of functions
+    - v4l: xilinx-multi-scaler: Allow stream on for the immediate next channel
+    - v4l: xilinx-multi-scaler: Do not allow new task when device is busy
+    - v4l: xilinx-multi-scaler: Wait for all running channels to get buffer
+    - v4l: xilinx-multi-scaler: Add number of frames processed per channel
+    - v4l: xilinx-multi-scaler: Check any channel is still running in streamoff
+    - v4l: xilinx-multi-scaler: Fix pointers in set chk chan_stream
+    - v4l: xilinx-multi-scaler: Add reserve area between channel 4 and 5
+    - xilinx: v4l: vipp: Avoid decrementing refcount of a node twice
+    - xilinx: v4l: dma: Invoke s_power function of subdevice
+    - drm: xlnx: Select VIDEOMODE_HELPERS when DRM_XLNX_PL_DISP is selected
+    - xilinx: v4l: m2m: Set default mode for framebuffer IP
+    - media: ov5640: fix get_light_freq on auto
+    - media: ov5640: Don't access ctrl regs when off
+    - media: ov5640: Add additional media bus formats
+    - media: xilinx: csi2rxss: store format size
+    - drm: xlnx: pl_disp: Enable early callback
+    - v4l: xilinx-multi-scaler: Remove volatile
+    - v4l: xilinx-multi-scaler: Change maximum supported height and width
+    - v4l: xilinx-multi-scaler: Move tap parameter to xm2msc_dev from channel
+      context
+    - v4l: xilinx-multi-scaler: Read tap from the device-tree
+    - v4l: xilinx-multi-scaler: Adding coefficients for 8, 10, 12 taps
+    - v4l: xilinx-multi-scaler: Select taps as per scaling ratio
+    - v4l: xilinx-multi-scaler: Change function names
+    - v4l: xilinx-multi-scaler: Noncontiguous planes support
+    - xilinx: v4l: dma: Stop subdevs in reverse order of starting
+    - drm: xlnx: sdi: Disable bridge instance
+    - drm: xlnx: dsi: Disable bridge instance
+    - documentation: dt: Add bindings documentation for Streaming SCD
+    - xilinx: v4l: scd: Initial version of streaming based driver
+    - xilinx: v4l: scd: Validate interrupt number
+    - xilinx: v4l: scd: Implement generic event notification
+    - v4l: xilinx-multi-scaler: Fix the size of 2nd plane for 4:2:2 video formats
+    - drm: xlnx: dsi: Fix kernel panic when "halt" is run
+    - drm: xlnx: crtc: Fix max width and height overflow
+    - dt-bindings: display: xlnx: mixer: Correct DRM fourcc for BGR8 and RGB8
+    - dt-bindings: csi2rxss: Add clock framework support
+    - v4l: xilinx: xcsi2rxss: Add support for clock framework
+    - documentation: dt: vpss-scaler: Fix support for clock framework
+    - v4l: xilinx: vpss-scaler: Fix clock framework support
+    - dt: bindings: media: xilinx: Add clock support to AXI4 Stream switch
+    - v4l: xilinx: axis-switch: Add support for clock framework
+    - dt-bindings: display: xlnx: Add device tree binding for xlnx control drivers
+    - drm: xlnx: zynqmp_disp: Add Y only formats support
+    - media: xilinx: tpg: Add pixel per clock dt support
+    - dt: bindings: media: xilinx: tpg: Add ppc dt bindings.
+    - media: xilinx: tpg: v4l subdevice controls to set fps
+    - media: xilinx: vtc: Dynamically calculate pixel clock
+    - media: xilinx: multi-scaler: support VB2_USERPTR IO mode
+    - media: xilinx: multi-scaler: Replace dev_info with dev_dbg if all jobs are
+      not ready
+    - documentation: dt: multi-scaler: Add properties for pixels per clock
+    - media: xilinx: multi-scaler: Add extra padding bytes after each row of
+      pixels
+    - media: xilinx: multi-scaler: Align width to pixels per clock
+    - media: xilinx: multi-scaler: Add support for formats having contiguous
+      buffers for two planes.
+    - drm: xlnx: zynqmp: Handle the event when there's no fb
+    - drm: xlnx: zynqmp: Remove unused variable
+    - documentation: dt: multi-scaler: Add clock framework support
+    - media: xilinx: multi-scaler: Add clock framework support
+    - media: xilinx: multi-scaler: Support stride and height alignment
+    - dt-bindings: display: xlnx: Add clock framework support to DSI Tx
+    - drm: xlnx: dsi: Add support for clock framework
+    - dt-bindings: display: xlnx: Add clock framework support to SDI Tx
+    - drm: xlnx: sdi: Add clock framework support
+    - dt-bindings: display: xlnx: Add clock framework support to VPSS CSC bridge
+      driver
+    - drm: xlnx: csc: Add clock framework support
+    - dt-bindings: display: xlnx: Add clock framework support to VPSS Scaler
+      bridge driver
+    - drm: xlnx: scaler: Add support for clock framework
+    - dt-bindings: display: xlnx: Add clock framework support to VTC bridge driver
+    - drm: xlnx: vtc: Add clock framework support
+    - media: xilinx: tpg: dt pixel per clock validate.
+    - media: xilinx: m2m: Xilinx M2M composite video framework
+    - ASoC: xlnx: move mm2s/s2mm configuration to functions
+    - dt-bindings: ASoC: xlnx,audio-formatter.txt: update clocks
+    - ASoC: xlnx: use clock framework for clocks to audio formatter
+    - ASoC: xlnx: change I2S driver data
+    - ASoC: xlnx,i2s: dt-bindings: update with I2S clocks
+    - ASoC: xlnx: use clock framework for clocks to I2S
+    - dt-bindings: ASoC: xlnx,v-uhdsdi-audio.txt: update input clocks
+    - ASoC: xlnx: use clock framework for clocks to SDI audio
+    - dt-bindings: ASoC: xlnx,spdif: update input clocks
+    - ASoC: xlnx: use clock framework for clocks to SPDIF
+    - drm: xlnx: sdi: Correcting drm property creation logic
+    - drm: xlnx: pl_disp: handle software vblank
+    - dma: xilinx: Define early callback modes
+    - dma: xilinx: Support early callback modes
+    - drm: xlnx: pl_disp: Pass early callback mode
+    - dma: xilinx: Release buffers before DMA transfer
+    - v4l: xilinx: dma: Add control for low latency
+    - v4l: xilinx: dma: Add s_ctrl ioctl for low latency capture
+    - media: v4l: Add 10, 12 and 16 bpc RBG media bus formats
+    - media: v4l2-ioctl: Add 12 and 16 bpc RGB pixel formats
+    - dt-bindings: dma: xilinx_frmbuf: Add support for 12 and 16 bpc RGB formats
+    - dmaengine: xilinx: frmbuf: Add support for 12 and 16 bpc RGB formats
+    - v4l: xilinx: vip: Add 12 and 16 bpc RAW and RGB color formats
+    - dt-bindings: media: xilinx: csi2rxss: Add RAW16 and RAW20 pixel format
+      strings
+    - v4l: xilinx: xcsi2rxss: Add support for RAW16 format
+    - v4l: xilinx-demosaic: Add support for 10,12,16 bpc RAW and RGB bus formats
+    - v4l: xilinx: multi-scaler: Fix precedence error
+    - v4l: xilinx: multi-scaler: Set channel parameters to default values
+    - drm: xlnx: zynqmp_dp: Fix DP aux related issues
+    - drm: xlnx: dsi: Fix the drm property creation
+    - media: v4l: Add YUV 12bit and 16bit media bus formats
+    - media: v4l2-ioctl: Add YUV 12bit and 16bit pixel formats
+    - v4l: xilinx: dma: Add YUV 12bit and 16bit format support
+    - dt-bindings: media: xilinx: tpg: Update for v8.0
+    - media: xilinx: tpg: Add support for v8.0
+    - v4l: xilinx-demosaic: Make max width and height properties mandatory
+    - v4l: xilinx-gamma: Make max-width and max-height mandatory dt properties
+    - dt-bindings: dma: xilinx_frmbuf: Make max-width and max-height as mandatory
+      properties
+    - dmaengine: xilinx: frmbuf: Make max-width and max-height mandatory
+      properties
+    - dt-bindings: media: vpss-csc: Make max width and height mandatory properties
+    - v4l: xilinx-vpss-csc: Make max width and height mandatory properties
+    - dt-bindings: media: vpss-scaler: Make max width and height mandatory
+      properties
+    - v4l: xilinx: vpss-scaler: Make max width and height mandatory properties
+    - dt-bindings: display: xlnx: vpss-csc: Add max width and height properties
+    - drm: xlnx: csc: Add max width and height dt properties
+    - dt-bindings: display: xlnx: Add max width and height as mandatory properties
+    - drm: xlnx: scaler: Add max width and height properties
+    - v4l: xilinx: scd: Fix video format configuration for YUV420
+    - media: v4l: Add YUV 10bit media bus format
+    - v4l: xilinx: vip: Add YUV 10bit media bus formats
+    - v4l: xilinx: vip: Add scaling and padding factor for XY10
+    - v4l: xilinx: vip: Use correct media bus code for RGB 10bit format
+    - v4l: xilinx: vpss-scaler: Use 10bit media bus codes
+    - v4l: xilinx: tpg: Use 10bit media bus codes
+    - v4l: xilinx: vpss-csc: Use 10bit media bus codes
+    - v4l: xilinx: scd: Enable 10 bit formats support for memory based IP
+    - v4l: xilinx: scd: Use correct threshold value
+    - v4l: xilinx: m2m: Add S_SELECTION and G_SELECTION ioctls
+    - v4l: xilinx: m2m: Use crop parameters set on output port
+    - drm: xlnx: zynqmp_disp: Skip the modeset for same fb
+    - v4l: xilinx: tpg: Dynamically modify TPG output format
+    - v4l: xilinx: sdirxss: Fix the media bus formats to 10bpc type
+    - ASoC: xlnx: change HDMI audio mclk
+    - v4l: xilinx: scd: Consolidate register definitions
+    - v4l: xilinx: scd: Consolidate structure definitions
+    - v4l: xilinx: scd: Make local functions static
+    - v4l: xilinx: scd: Reorder structure definitions
+    - v4l: xilinx: scd: Merge the V4L2 support in the main SCD driver
+    - v4l: xilinx: scd: Merge the main and V4L2 IRQ handlers
+    - v4l: xilinx: scd: Merge the DMA support in the main SCD driver
+    - v4l: xilinx: scd: Cleanup the DMA engine at remove() time
+    - v4l: xilinx: scd: Merge the main and DMA IRQ handlers
+    - v4l: xilinx: scd: Compile all SCD source files in a single module
+    - v4l: xilinx: scd: Refactor the xscd_device structure
+    - v4l: xilinx: scd: Allocate pads array statically
+    - v4l: xilinx: scd: Store channel registers address in iomem field
+    - v4l: xilinx: scd: Request IRQ after completing initialization
+    - v4l: xilinx: scd: Initialize DMA channels in xilinx-scenechange-dma.c
+    - v4l: xilinx: scd: Allocate all channels in one go
+    - v4l: xilinx: scd: Inline the xscd_dma_alloc_tx_descriptor() function
+    - v4l: xilinx: scd: Clean up #include statements
+    - v4l: xilinx: scd: Cleanup the xscd_dma_chan structure
+    - v4l: xilinx: scd: Rewrite core start/stop and interrupt handling
+    - v4l: xilinx: scd: Don't mark channel as disabled in .s_stream(0)
+    - uio: xilinx_ai_engine: Set the uio device as pdev driver data
+    - uio: xilinx_ai_engine: Unreference correct pdev
+    - dt-bindings: soc: xilinx: ai_engine: Add interrupts
+    - uio: xilinx_ai_engine: Enable the irq
+    - uio: xilinx_ai_engine: Simulate the irq if no hw irq is available
+    - dt-bindings: soc: xilinx: ai-engine-npi: Add the binding for AIE NPI
+    - uio: xilinx_ai_engine: Enable platform genirq driver
+    - drm: xlnx: pl_disp: Added plane atomic check function
+    - ASoC: xlnx: revert HDMI audio mclk mutliplier
+    - media: v4l2-ioctl: Use correct fourcc for YUV444 10bit format
+    - v4l: xilinx: vip: Fix stride calculation
+    - media: v4l: Add YUV444 12bit and 16bit media bus format
+    - media: v4l2-ioctl: Add YUV444 12bit and 16bit pixel formats
+    - v4l: xilinx: vip: Add YUV444 12bit and 16bit formats
+    - dt-bindings: display: xlnx: mixer: Updated compatible string
+    - drm: xlnx: mixer: Adding 16 layer support
+    - v4l: xilinx: m2m: Fix buftype for s_selection ioctl
+    - v4l: xilinx: dma: add input ioctls
+    - v4l: xilinx: dma: add v4l2_ctrl_handler
+    - v4l: xilinx: xcsi2rxss: Use external reset in a SLBF condition
+    - dt-bindings: media: xilinx: Add optional external reset for core reset
+    - v4l: xilinx: sdirxss: Make structures constant
+    - v4l: xilinx: sdirxss: Use clk_bulk_* apis
+    - v4l: xilinx: sdirxss: Replace single element array with variable
+    - v4l: xilinx: sdirxss: Add support to enumerate media bus formats
+    - v4l: xilinx: sdirxss: Clear processed interrupts only
+    - v4l: xilinx: sdirxss: Correct handling of combined lock/unlock interrupts
+    - v4l: xilinx: sdirxss: Fix code formatting and comments
+    - v4l: xilinx: sdirxss: Make functions static inline
+    - v4l: xilinx: sdirxss: Call xsdirx_streamflow_control() directly
+    - v4l: xilinx: sdirxss: Check for 10bpc in dt
+    - v4l: xilinx: sdirxss: Uninitialize the subsystem correctly
+    - v4l: xilinx: vpss-csc: Fix xcsc_set_format() for RBG 10 bpc
+    - v4l: xilinx: dma: Copy format resolution to crop rectangle
+    - v4l: xilinx: dma: Check subdev resolution against crop rectangle
+    - v4l: xilinx: dma: Add S_SELECTION and G_SELECTION ioctls
+    - v4l: xilinx: dma: Use crop rectangle to prepare dma descriptor
+    - drm: xlnx: mixer: Added bridge instance check in remove function
+    - uio: rename uio.c -> uio_core.c & unify into uio.ko
+    - dt-bindings: soc: xilinx: Correct ai_engine reg property
+    - drm: xlnx: zynqmp_dp: initialize delayed work before enable interrupts
+    - v4l: xilinx: dma: Don't set low latency capture mode on dma
+    - Revert "dma: xilinx: Release buffers before DMA transfer"
+    - v4l: xilinx: dma: Don't start DMA in STREAM_ON for low latency capture
+    - v4l: xilinx: dma: Perform early callback on queued buffers
+    - v4l: xilinx: dma: Add support to start DMA using s_ctrl
+    - media: v4l: Group Xilinx downstream formats
+    - v4l: xilinx: vip: Keep NV16 first in vip table
+    - v4l: xilinx: vip: Use the right media code for 422 16bit formats
+    - v4l: xilinx: scd: Enable configuration of scene change threshold
+    - v4l: xilinx: scd: Proper unregister from V4L2 framework
+    - Revert "Revert "dma: xilinx: Release buffers before DMA transfer""
+    - v4l: xilinx: dma: Use early callback mode for low latency capture
+    - v4l: xilinx: dma: Early dequeue first buffer for low latency capture
+    - v4l: xilinx: dma: Disable auto restart for low latency capture
+    - v4l: xilinx: scd: Fixed resolution switch issue
+    - v4l: xilinx: vpss-scaler: Add support for 4 ppc
+    - v4l: xilinx: dma: Attach s_ctrl to ctrl_handler instead of ioctl
+    - dt-bindings: display: xlnx: dsi: Add command mode support
+    - drm: xlnx: dsi: Add command mode support
+    - drm: xlnx: mixer: Add a delay for timing generation to be stable
+    - dt-bindings: display: xlnx: Add support for vpss ip version 2.2
+    - drm: xlnx: scaler: Add support for ip version 2.2
+    - dt-bindings: media: vpss-scaler: Add rev 2.2 to compatible string
+    - v4l: xilinx: vpss-scaler: Add support for ip version 2.2
+    - dma: xilinx: Disable low latency capture in file ops open
+    - v4l: xilinx: m2m: Fix crop support on capture port
+    - dma: xilinx: dpdma: alloc xilinx_dpdma_tx_desc using GFP_ATOMIC
+    - dmaengine: xilinx: dpdma: fix implicit fall-through statements
+    - drm: xlnx: sdi: Use the named IRQ when available
+    - v4l: xilinx: xcsi2rxss: Source pad has same format as sink pad
+    - v4l: xilinx: axis-switch: sink and source pad should have same value in
+      TDEST routing mode
+    - v4l: xilinx: xcsi2rxss: Set default active lanes to max
+    - drm: xlnx: drv: drop master only while releasing last master on a drm device
+    - drm: xlnx: zynqmp_disp: Perform additional checks for plane update
+    - v4l: xilinx: sdirxss: Add YUV444 10 bpc support
+    - firmware: zynqmp: Add Node IDs in xlnx-zynqmp.h
+    - watchdog: cadence: Do not show error in case of deferred probe
+    - watchdog: cadence: Skip printing pointer value
+    - OF: DT-Overlay configfs interface (v8)
+    - fpga: Add firmware store function
+    - fpga: mgr: Adopted Encrypted BitStream loading support for Xilinx zynqmp
+    - fpga: fpga-mgr: Add readback support
+    - fpga: zynqmp-fpga: Add support for pl configuration readback
+    - fpga: zynqmp-fpga: fix compile warning in fpga_mgr_register
+    - fpga: mgr: Update the status for fpga-manager
+    - fpga: zynqmp-fpga: Adds status interface
+    - fpga: Adopted Authenticated BitStream loading support for Xilinx
+    - mtd: rawnand: nand_micron: Do not over write driver's (read/write)_page()
+      hooks
+    - mtd: rawnand: arasan: Add on-die ecc support
+    - ARM: zynq: Add smcc node
+    - mtd: rawnand: pl353: Add driver for arm pl353 smc nand interface
+    - net: can: Limit CANFD brp to 2
+    - gpio: zynq: protect direction in/out with a spinlock
+    - dt-bindings: gpio: Add binding for Versal gpio
+    - devicetree-binding: Add pmc gpio node
+    - gpio: zynq: Add Versal support
+    - gpio: zynq: Disable the irq if it is not a wakeup source
+    - gpio: zynq: Add pmc gpio support
+    - gpio: zynq: Remove error prints in EPROBE_DEFER
+    - microblaze: Align comments with register usage
+    - microblaze: Fix message about compiled-in FDT location
+    - microblaze: Permit pcibios_set_master override
+    - microblaze: pci: Support generic Xilinx AXI PCIe Host Bridge IP driver
+    - ARM: zynq: use physical cpuid in zynq_slcr_cpu_stop/start
+    - dt-bindings: ARM: zynq: Add DT binding for eFuse controller
+    - ARM: zynq: Add support for Zynq-7000S devices
+    - ARM: zynq: Fix prefetch option
+    - zynq: slcr: Introduce new get_ocm_config()
+    - zynq: Add OCM driver
+    - Xilinx: ARM: Devcfg and SLCR drivers updated to support reconfiguration.
+    - arm: zynq: Suspend support
+    - xilinx: Documentation/devicetree - add description for "port-number"
+      property
+    - Bluetooth: hci_ll: Extend timeout between start and communication
+    - dt-binding: iio: Add optional label property
+    - iio: core: Add optional symbolic label to device attributes
+    - hvc: dcc: Add earlycon support
+    - tty: serial: of_serial: Do not allocate greater space than required
+    - dt-bindings: fpga: Add doc for the xilinx afi config driver
+    - fpga: Add xilinx AFI config driver
+    - dt-bindings: fpga: Add binding doc for the afi config driver
+    - fpga: zynq: Add AFI config driver
+    - dt-bindings: fpga: Add binding doc for versal fpga manager
+    - fpga: versal-fpga: Add versal fpga manager driver
+    - dt-bindings: misc: Add dt bindings for traffic generator
+    - trafgen: xilinx: add axi traffic generator driver
+    - trafgen: Document sysfs entries
+    - fpga: xilinx-pr-decoupler: Remove clk_get error message for probe defer
+    - fpga: fpga-bridge: Add manual set option via sysfs
+    - dt-bindings: Add doc for xilinx fclk
+    - staging: fclk: Enable pl clock with sysfs entry for set_rate
+    - i2c: cadence: Fix error printing in case of defer
+    - i2c: cadence: Fix power management order of operations
+    - i2c: cadence: Implement save restore
+    - i2c: cadence: Recover bus after controller reset
+    - i2c: cadence: Added slave support
+    - i2c: cadence: Fix wording in i2c-cadence driver
+    - i2c: cadence: Handling Slave monitor mode
+    - ARM: zynq: Add/Update/Sync DTs for xilinx platforms
+    - microblaze: defconfig: Disable EXT2 driver and Enable EXT3 & EXT4 drivers
+    - arm64: zynqmp: Use ethernet-phy as node name for ethernet phys
+    - arm64: zynqmp: Remove addition number in node name
+    - arm64: zynqmp: Fix address for tca6416_u97 chip on zcu104
+    - arm64: zynqmp: Turn comment to gpio-line-names
+    - arm64: zynqmp: Setup clock-output-names for si570 chips
+    - arm64: zynqmp: Fix the si570 clock frequency on zcu111
+    - arm64: zynqmp: Remove broken-cd from zcu100-revC
+    - arm64: zynqmp: Setup default number of chipselects for zcu100
+    - arm64: zynqmp: Enable iio-hwmon for ina226 on zcu100
+    - arm64: zynqmp: Enable iio-hwmon for ina226 on zcu111
+    - arm64: zynqmp: Add label property to all ina226 on zcu111
+    - arm64: zynqmp: Enable iio-hwmon for ina226 on zcu102
+    - arm64: zynqmp: Add label property to all ina226 on zcu102
+    - arm64: zynqmp: Enable iio-hwmon for ina226 on zcu106
+    - arm64: zynqmp: Add label property to all ina226 on zcu106
+    - dt-bindings: Add the binding doc for xilinx APM
+    - uio: uio_xilinx_apm: Add Xilinx AXI performance monitor driver
+    - i2c: xiic: Fix kerneldoc warnings
+    - i2c: xiic: Add timeout to the rx fifo wait loop
+    - i2c: xiic: defer the probe if clock is not found
+    - i2c: xiic: Fix the clocking across bind unbind
+    - tty: pl011: Add suspend resume support
+    - tty: pl011: Add support for configurable wordlength
+    - irqchip: gic: Add remoteproc changes to the driver
+    - arm: Add support for dynamic IPI allocation
+    - serial: uartps: Fix stuck ISR if RX disabled with non-empty FIFO
+    - serial: uartps: Prevent writes when the controller is disabled
+    - serial: uartps: Fix the ignore_status
+    - serial-uartlite: Change logic how console_port is setup
+    - serial-uartlite: Remove ULITE_NR_PORTS macro
+    - mmc: sdhci-of-arasan: Separate out clk related data to another structure
+    - dt-bindings: mmc: arasan: Update Documentation for the input clock
+    - mmc: sdhci-of-arasan: Add sampling clock for a phy to use
+    - dt-bindings: mmc: Add optional generic properties for mmc
+    - mmc: sdhci-of-arasan: Add support to set clock phase delays for SD
+    - firmware: xilinx: Add SDIO Tap Delay nodes
+    - dt-bindings: mmc: arasan: Document 'xlnx,zynqmp-8.9a' controller
+    - mmc: sdhci-of-arasan: Add support for ZynqMP Platform Tap Delays Setup
+    - firmware: xilinx: Add DLL reset support
+    - mmc: sdhci-of-arasan: Add support for DLL reset for ZynqMP platforms
+    - arm64: zynqmp: Add ZynqMP SDHCI compatible string
+    - sdhci: arasan: Remove quirk for broken base clock
+    - dt-bindings: dma: xilinx_frmbuf: Add support for 8 ppc
+    - dmaengine: xilinx: frmbuf: Add support for 8 ppc
+    - v4l: xilinx: sdirxss: Add support to modify GT clock
+    - dt-bindings: media: xilinx: csi2rxss: Add 4.1 compatible string
+    - v4l: xilinx: xcsi2rxss: Add v4.1 compatible string
+    - soc: xilinx: vcu: Add exported functions
+    - soc: xilinx: vcu: Provided API to get core clock
+    - soc: xilinx: vcu: Provided API to get number of cores
+    - soc: xilinx: vcu: Divisor calculation for MCU clock is updated.
+    - soc: xilinx: vcu: Optimize the VCU PLL calculation.
+    - dt-bindings: soc: xilinx: Update VCU bindings
+    - soc: xilinx: vcu: Move structure definition to header file
+    - soc: xilinx: vcu: Add VCU MFD core driver
+    - soc: xilinx: vcu: Use CCF to use clocks
+    - dt-bindings: soc: xilinx: Update VCU bindings for vcu reset pin
+    - soc: xilinx: vcu: Update vcu init/reset sequence
+    - dt-bindings: soc: xilinx: Update vcu compatible string in example
+    - i2c: cadence: Fix the driver in interrupt flurry case
+    - watchdog: of_xilinx_wdt: Add comment to spinlock
+    - watchdog: of_xilinx_wdt: Used BIT macro
+    - watchdog: of_xilinx_wdt: Used dev_dbg()
+    - watchdog: of_xilinx_wdt: Initialize watchdog via data structure
+    - watchdog: of_xilinx_wdt: Introduce wdttype enum for identification
+    - dt-bindings: watchdog: xilinx: Add binding for Versal watchdog
+    - watchdog: of_xilinx_wdt: Add Versal support
+    - watchdog: of_xilinx_wdt: Wire setting up timeout via module parameter/DT
+    - PCI: XDMA PL PCIe: Adding device tree binding for XDMA PL PCIe
+    - PCI: XDMA PL PCIe: Adding XDMA PL PCIe Root Port
+    - PCI: XDMA PL PCIe: Request host bridge window resources
+    - PCI: XDMA PL PCIe: Convert PCI scan API to pci_scan_root_bus_bridge()
+    - PCI: XDMA PL PCIe: Move to struct pci_host_bridge IRQ mapping functions
+    - PCI: XDMA PL PCIe: Remove unused platform data
+    - PCI: XDMA PL PCIe: Translate INTx range to hwirqs 0-3
+    - PCI: XDMA PL PCIe: Fix 64-bit MSI address programming
+    - PCI: XDMA PL PCIe: Program hwirq to MSI data
+    - PCI: XDMA PL PCIe: Fix number of MSI interrupts supported
+    - PCI: XDMA PL PCIe: Fix Multi MSI data programming
+    - PCI: XDMA PL PCIe: Add documentation for MSI DECODE mode.
+    - PCI: XDMA PL PCIe: Add support MSI DECODE mode
+    - PCI: XDMA PL PCIe: Fixing legacy interrupt handling bug
+    - pci: xdma: pl: Remove of_pci_get_host_bridge_resources
+    - pci: xdma: pl: Fix Multi MSI data
+    - pci: xdma: pl:: Remove unused variable
+    - pci: xdma: pl: Moving misc IRQ line registration to separate function
+    - pci: xdma: pl: Moving MSI IRQ lines registration to separate function
+    - pci: xdma: pl: Parse device tree based on compatible string
+    - dt-bindings: pci: xdma: Add device tree binding for Versal CPM
+    - pci: xdma: pl: Add support for Versal CPM Root Port driver
+    - PCI: XDMA: Remove unsupported error bits
+    - PCI: CPM: Adding support for versal specific errors
+    - PCI: XDMA PL: Move to PCI version of mask and unmask MSI IRQ
+    - drivers: clocksource: Use ttc driver as platform driver
+    - remoteproc: Add support for peek from remote and acking kick from remote
+    - remoteproc: sysfs: allow kick to pass small data
+    - remoteproc: returns message for peek remote kick function
+    - dt-bindings: Add Zynq remoteproc binding
+    - remoteproc: Add support for AMP on Zynq platform
+    - dt-bindings: Add documentation for ZynqMP R5 rproc bindings
+    - remoteproc: Add initial zynqmp R5 remoteproc driver
+    - i2c: mux: pca954x: write to mux channel always
+    - dt-bindings: Add binding for IDT 8T49N24x UFT
+    - clk: Add ccf driver for IDT 8T49N24x UFT
+    - spi: Add Zynq QSPI controller driver
+    - mtd: spi-nor: Add dual parallel and stacked support for Zynq QSPI controller
+    - mtd: spi-nor: Add 4byte support for Zynq QSPI controller
+    - dt-bindings: spi: Update dt bindings document
+    - spi: Update ZynqMP and Versal QSPI controller driver
+    - mtd: spi-nor: Add support for ZynqMP and Versal QSPI Controller
+    - dt-bindings: mtd: Update dt binding documentation
+    - spi: Add multi-die info in spi_device structure
+    - mtd: spi-nor: Add multi-die read support
+    - mtd: spi-nor: Update flags for serial NOR flash devices
+    - dt-binding: Added versal-ospi compatible string
+    - mtd: cadence-quadspi: Added xilinx compatible string
+    - mtd: cadence-quadspi: Added support for DMA read
+    - mtd: cadence-quadspi: Added support STIG write
+    - mtd: spi-nor: Added support for OCTAL write
+    - mtd: spi-nor: Add entry for mt35xu01g flash
+    - dt-bindings: mtd: Document "reset-gpios" property
+    - mtd: cadence-quadspi: Added support for OSPI device reset
+    - mtd: cadence-quadspi: Added support for DDR PHY mode
+    - dt-bindings: mmc: arasan: Document 'xlnx,versal-8.9a' controller
+    - sdhci: arasan: Add support for Versal Tap Delays
+    - fpga: support loading from a pre-allocated buffer
+    - staging: dt-bindings: xlnxsync: Add initial bindings for Xilinx Synchronizer
+    - staging: xlnxsync: Add driver for Xilinx Synchronizer
+    - net: axienet: In kconfig remove arch dependency for axi_emac
+    - net: emaclite: Fix coding style
+    - net: emaclite: In kconfig remove arch dependency
+    - net: emaclite: Fix arm64 compilation warnings
+    - dt-bindings: nvmem: Added efuse nodes
+    - nvmem: zynqmp: Added support to access efuse
+    - dt-bindings: Add device tree binding for xilinx mpeg2tsmux driver
+    - staging: xlnx_tsmux: Initial version of xlnx mpeg2tsmux driver
+    - nvmem: zynqmp: Added zynqmp nvmem get_silicon_version()
+    - phy: zynqmp: Add dt bindings for ZynqMP PHY
+    - phy: zynqmp: Add phy driver for xilinx zynqmp phy core
+    - usb: gadget: udc-xilinx: Add clock support
+    - usb: xilinx: Add suspend resume support
+    - usb: phy: Add platform driver support for ULPI phys
+    - usb: gadget: udc: udc-xilinx: Add identifier to read_fn function arg
+    - usb: gadget: udc: udc-xilinx: Resolve compilation warnings
+    - usb: host: ehci-xilinx: modified driver to resolve formatting warnings
+    - usb: host: ehci-xilinx: Resolve kernel-doc Warnings
+    - usb: host: xhci: plat: add support for otg_set_host() call
+    - usb: host: xhci: add support for Light Reset for DWC3 DRD
+    - usb: xhci: Add workaround for fixing ep stream ring hang issue
+    - usb: uas: Add workaround for DATA IN urb's returned with status -EAGAIN
+    - uas: Add US_FL_NO_ATA_1X for linux tcm_usb_gadget
+    - usb: gadget: f_tcm: adjust write length with max packet size
+    - usb: gadget: f_tcm: comp_descriptor workaround during SS gadget
+    - usb: gadget: f_tcm: queue multiple commands request
+    - usb: gadget: f_tcm: add TARGET_SCF_ACK_KREF flag in BOT
+    - usb: gadget: f_tcm: support to set maxburst through configfs
+    - usb: function: f_tcm: Add support for getting alt interface number
+    - usb: dwc3: gadget: add support for OTG in gadget framework
+    - usb: dwc3: hibernation: fix scratch buffer allocation
+    - usb: dwc3: correct ignoring hibernation event
+    - dwc3: Add support for setting USB control registers as phy platform data
+    - dwc3: core: Enable GUCTL1 chicken bit 10 for fixing crc error after resume
+      bug
+    - dwc3: core: Enable GUCTL1 chicken bit 9 for correcting Inter Packet
+      Delay(IPD)
+    - usb: Add quirk for enabling workaround for BULK IN streams
+    - usb: dwc3: Add support for clock disabling during suspend
+    - usb: dwc3: Add support for removing vbus when suspended
+    - usb: dwc3: of-simple: Enable CCI support in dwc3 driver
+    - usb: dwc3: Correct errors when dwc3 loaded as module
+    - usb: dwc3: enable transfer complete event for stream endpoint
+    - usb: dwc3: Add code for supporting entering into D3 state during suspend
+    - usb: xhci-plat: Add remote wakeup support
+    - usb: dwc3: update GFLADJ_REFCLK_FLADJ in dwc3_frame_length_adjustment
+    - usb: dwc3: don't setup event buffers when operating in device mode
+    - usb: dwc3: Fix the logic for allocating and setting scratchpad buffers
+    - usb: dwc3: Add hibernation support when operating as gadget
+    - usb: dwc3: add support for enabling/disabling hibernation dynamically
+    - usb: dwc3: fix the logic for setting GBLHIBERNATIONEN in GCTL
+    - usb: dwc3: don't wait for end transfer to finish for isoc endpoints
+    - usb: xhci: don't clean shared_hcd when otg is enabled
+    - usb: gadget: configfs: Add support for setting maximum supported speed
+    - usb: dwc3: Fix missing peripheral irq error message
+    - usb: dwc3: Fix the broken suspend/resume functionality in dwc3
+    - usb: gadget: uvc_video: unlock before submitting a request to ep
+    - usb: dwc3: Correct usb dma mask for making SMMU work in device mode
+    - usb: xhci: wait for atleast 1ms after exiting U3
+    - usb: dwc3: gadget: ISOC transfers should be stopped before starting a
+      transfer
+    - usb: dwc3: otg: fix broken OTG HNP feature
+    - usb: dwc3: Check for IOC/LST bit in both event->status and TRB->ctrl fields
+    - usb: dwc3: gadget: Don't kick transfer if LST or SHORT bits are set
+    - usb: dwc3: Add DRD support for versal
+    - usb: dwc3: core: use first_trb_index instead of start_slot
+    - usb: host: xhci: Add xhci_hcd to xhci_ring for use in
+      stream_timeout_function
+    - usb: dwc3: gadget: get irq number for hibernation interrupts
+    - usb: dwc3: gadget: Add new platform_data.h file
+    - usb: gadget: send usb_gadget as an argument in get_config_params
+    - usb: dwc3: Disabling usb3 phy suspend checks into a separate function
+    - usb: dwc3: Add support for masking phy reset signal
+    - usb: dwc3: otg: Update Kconfig and Makefile for enabling OTG
+    - usb: dwc3: Implement stream transfer timeout
+    - usb: dwc3: otg: add support for OTG in DWC3 host driver
+    - usb: dwc3: retain resource index for unforced stops
+    - mtd: spi-nor: Updated spi_nor_write_ear() api with dual parallel and stacked
+      support.
+    - dt-bindings: spi-xilinx: Updated devicetree bindings for spi-xilinx
+    - mtd: spi-nor: Added axi-qspi support in spi-nor framework
+    - spi: spi-xilinx: Updated axi-qspi controller driver
+    - Revert "net: axienet: document axistream-connected attribute"
+    - Revert "net: axienet: make use of axistream-connected attribute optional"
+    - net: axienet: Add NAPI support
+    - dt-bindings: net: Add bindings documentation for Xilinx PCS/PMA PHY
+    - net: phy: Add support for xilinx SGMII and 1000BASE-X phys
+    - net: axienet: Use barriers at relevant places
+    - net: axienet: Fix lost wake-up scenario in xmit
+    - dt-bindings: net: axienet: Add binding for 2.5G, 10G and usxgmii mac
+      variants
+    - dt-bindings: net: axienet: Update binding doc for 10G/25G MAC 1588
+    - dt-bindings: net: axienet: Add clock support
+    - dt-bindings: net: axienet: Add support for mcdma
+    - net: axienet: Add support for non-processor mode
+    - net: axienet: Add support for config structure
+    - net: axienet: Add support for 2.5G MAC
+    - net: axienet: Add support for 10G MAC
+    - net: axienet: Add support for 10G/25G MAC
+    - net: axienet: Add support for 1588
+    - net: axienet: Add support for ZynqMP
+    - net: axienet: Adding highmem support
+    - net: axienet: Remove unnecessary phy defines
+    - net: axienet: Allow unaligned transfers
+    - net: axienet: Use ether_addr_copy()
+    - net: axienet: Fix coding style issues
+    - net: axienet: Fix issues when DRE is not enabled in the h/w
+    - net: axienet: Add clock support
+    - net: axienet: added multichannel DMA support
+    - net: xilinx: axiethernet: Add USXGMII support
+    - net: xilinx: axiethernet: Check for queue full in transmit path
+    - net: xilinx: axiethernet: Fix axiethernet register description
+    - net: xilinx: axiethernet: Fix crash in axienet_recv
+    - Revert "net: axienet: convert to phylink API"
+    - v4l: xilinx: vpss-scaler: Improve quality by adding more coefficients
+    - drm: xlnx: scaler: Improve quality by adding more coefficients
+    - firmware: zynqmp: Add support for secure_image
+    - zynqmp: firmware: Adds a driver for loading secure partition from Linux
+    - net: macb: Add PCS caps mask and enable autoneg
+    - net: macb: add support for mdio phy nodes
+    - dt-bindings: net: macb: update for partial store and forward
+    - net: macb: Add support for partial store and forward
+    - net: macb: PTP fixes
+    - net: macb: Add provision for queue tie off
+    - net: macb: Use WOL via ARP
+    - net: macb: Initialize bool to false instead of zero
+    - net: macb: Increment rx bd head after allocating skb and buffer
+    - net: macb: Process tx timestamp only on ptp packets
+    - net: macb: Disable macb pad and fcs for fragmented packets
+    - net: macb: Optimize reading HW timestamp
+    - dt-bindings: net: macb: Add GEM versal compatible string
+    - net: macb: Update tsu clk usage in runtime suspend/resume for Versal
+    - net: macb: Use queue disable instead of tieoff in Versal suspend
+    - net: macb: Handle phy reset for PCS PMA IP
+    - net: macb: Increase halt timeout to accommodate 10Mbps link
+    - net: macb: Reset TX when TX halt times out
+    - net: macb: Update type of "mac" from char to u8
+    - net: macb: Add a NULL check on desc_ptp
+    - net: macb: Remove unnecessary check
+    - net: macb: Reorder probe and fix exit path
+    - dt-bindings: pmbus: Add tps544 bindings
+    - pmbus: Add new tps544 power regulator driver
+    - net: macb: Remove unnecessary alignment check for TSO
+    - net: macb: Limit maximum GEM TX length in TSO
+    - crypto: Adds user space interface for ALG_SET_KEY_TYPE
+    - dt-bindings: crypto: zynqmp-aes documentation
+    - crypto: zynqmp-aes: Adds zynqmp-aes driver
+    - arm64: zynqmp: Added device tree node for zynqmp-aes driver
+    - dt-bindings: crypto: Added binding docs for Xilinx ZynqMP SHA3 H/W
+      accelerator
+    - crypto: zynqmp-sha: Adopted SHA3 support for ZynqMP Soc
+    - arm64: zynqmp: Add Xilinx SHA3 node
+    - dt-bindings: crypto: Added binding docs for Xilinx ZynqMP RSA H/W
+      accelerator
+    - crypto: zynqmp-rsa: Adopted RSA support for ZynqMP SoC
+    - arm64: zynqmp: Add support for ZynqMP RSA H/W accelerator
+    - phy: dp83867: Add support for SGMII
+    - clk: zynqmp: Fix power of two divider calculation
+    - drm: xlnx: zynqmp: Use ZynqMP phy API
+    - include: dt-bindings: Add mscc-vsc8531 RGMII clock delay definitions
+    - phy: mscc: Use common RGMII delay definitions
+    - dt-bindings: mscc: Add RGMII RX and TX delay tuning
+    - phy: mscc: Add support for VSC8531_02 with RGMII tuning
+    - dmaengine: xilinx_dma: Reset DMA channel in dma_terminate_all
+    - dmaengine: xilinx_dma: Extend dma_config structure to store max channel
+      count
+    - dmaengine: xilinx_dma: In dma channel probe fix node order dependency
+    - dmaengine: xilinx: axidmatest: First enable receive path
+    - dt-bindings: clock: Adding si5324 bindings
+    - clk: Adding Silicon labs si5324 clock driver
+    - edac: add support for ARM PL310 L2 cache parity
+    - dt-bindings: edac: Add bindings for ZynqMP OCM Controller
+    - edac: zynqmp: Add EDAC support for ZynqMP OCM Controller
+    - dt-bindings: edac: Add bindings for cortex_arm64
+    - EDAC: Add ARM64 EDAC
+    - edac: Add documentation for cortexa53 edac sysfs
+    - edac: Add sysfs entries for cortex arm64
+    - arm64: zynqmp: Change Kconfig dependency for cortexa53 edac
+    - irqchip: xilinx: Add support for multiple instances
+    - tty: pl011: Add support for parity configuration
+    - drivers: ata: Add CCI support for SATA if CCI is enabled
+    - samples: xilinx_apm: Add sample application for xilinx_apm
+    - microblaze: Wire CMA allocator
+    - microblaze: Kernel parameters should be parsed earlier
+    - usb: gadget: udc-xilinx: Fix xudc_stop() kernel-doc format
+    - xilinx: Update MAINTAINERS fragment
+    - dt-bindings: display: xlnx: Added interrupt-names
+    - staging: xroeframer: Add README to describe roe framer
+    - staging: xroeframer: Add devicetree binding
+    - staging: xroeframer: Add register map header files
+    - staging: xroeframer: Add support for radio over ethernet frame
+    - staging: xroeframer: main sysfs source file commit
+    - staging: xroeframer: IPv4 sysfs source file commit
+    - staging: xroeframer: IPv6 sysfs source file commit
+    - staging: xroeframer: UDP sysfs source file commit
+    - staging: xroeframer: add support for multi-port Ethernet
+    - staging: xroeframer: add sysfs entries for "stats" registers
+    - staging: xroeframer: extending sysfs entries for "stats" registers
+    - staging: xroeframer: removing /dev/ entries
+    - staging: xroetrafficgen: initial commit of roe traffic generator driver
+    - mtd: Expand the ecc placement locations to 1260
+    - dt-bindings: power: Add versal power domain bindings
+    - docs: misc: xilinx_sdfec: Actually add documentation
+    - dt-bindings: pinctrl: Add DT binding doc for new pin control driver
+    - pinctrl: zynqmp: Add pin controller driver
+    - dt-bindings: Add Xilinx AMS binding documentation
+    - iio: adc: Add Xilinx AMS driver
+    - dt-bindings: iio: xadc: Add bindings for ultrascale sysmon
+    - iio: xadc: add support for ultrascale sysmon
+    - iio: xadc: fix for extended name remains same issue
+    - iio: adc: Fix checkpatch warning
+    - PCI: ZYNQMP EP driver: Adding support for ZynqMP ep driver
+    - PCI: ZYNQMP EP client driver: Adding support for ZynqMP dma test client
+    - dt-bindings: pci: ZYNQMP PS PCIe Driver Root DMA dt bindings
+    - PCI: ZYNQMP EP driver: Adding Root DMA support
+    - dt-bindings: irqchip: Add Xilinx Interrupt Controller bindings
+    - dt-bindings: misc: Add documentation for jesd204b
+    - misc: jesd204b: Add driver for Xilinx jesd204b
+    - dt-bindings: misc: Add bindings for JESD phy
+    - misc: jesd204b driver support
+    - mtd: spi-nor: update ptr pointer after spi_nor_read_data
+    - usb: chipidea: Add support for VBUS control with PHY
+    - usb: chipidea: Use usb2 phy for Zynq platform
+    - usb: chipidea: Check usb_phy exists before using it
+    - fpga: zynq: Remove clk_get error message for probe defer
+    - dt-bindings: serial: Added documentation for xilinx axi Uartlite
+    - dt-bindings: video: Add device tree bindings for xilinx axi tft
+    - mtd: fixing CFI for Numonyx CFI bug
+    - spi: zynqmp: Fix kerneldoc warnings
+    - spi: zynqmp: fix style issues from checkpatch
+    - spi: spi-zynqmp-gqspi: Resolved slab-out-of-bounds bug
+    - PCI: XDMA PL PCIe: Enable XDMA PL PCIe for Microblaze
+    - asm-generic: Make msi.h a mandatory include/asm header
+    - asm-generic: Make dma-contiguous.h a mandatory include/asm header
+    - microblaze: Swap location of bss and INIT_RAM_FS
+    - microblaze: Change TLB mapping and free space allocation
+    - microblaze: Fix TLB mapping
+    - dt-bindings: Update binding for pinctrl in arasan SD driver
+    - mmc: arasan: Add pinctrl support to the driver
+    - dt-bindings: usb: Add clock support for udc-xilinx
+    - mtd: spi-nor: Fix compilation warnings
+    - mtd: spi-nor: Fix the issue in checking 4Byte opcode support in
+      spi/qspi/ospi controller
+    - mtd: spi-nor: Remove unwanted spi-nor framework changes
+    - dt-bindings: Add devicetree documentation for TSN
+    - net: xilinx: Add support for PL TSN IP features
+    - dt-bindings: Add devicetree documentation for ep
+    - net: xilinx: Add support for PL TSN endpoint interface
+    - net: xilinx: Add Qci support to the PL TSN IP driver
+    - net: xilinx: Add Support for CB/FRER feature of PL TSN IP
+    - net: xilinx: Add support for Qbu/br feature of PL TSN IP
+    - firmware: xilinx: Add OSPI MUX selection support
+    - mtd: cadence-quadspi: Add support for register writes with address
+    - mtd: cadence-quadspi: Add support to switch between DMA and NON-DMA
+    - Revert "mtd: cadence-quadspi: Added support STIG write"
+    - mtd: cadence-quadspi: Add support for odd byte count read/write in DDR mode
+    - mtd: cadence-quadspi: Fix the issue in unaligned byte count read
+    - gpio: xilinx: Add clock adaptation support
+    - gpio: xilinx: Add irq support to the driver
+    - staging: xlnx_tsmux: Add stream table update logic
+    - media: v4l2-ioctl: Add description for new pixel formats
+    - mtd: spi-nor: Fix kernel crash in case of spi flash
+    - dt-bindings: PCI: Xilinx NWL PCIe: Add a clock specifier
+    - PCI: xilinx-nwl: Enable the clock through CCF
+    - arm64: zynqmp: Do not duplicate flash partition label property
+    - ARM: dts: zynq: enablement of coresight topology
+    - ARM: dts: Sync address/size-cells with the rest of zynq-7000
+    - arm64: zynqmp: Fix GIC compatible property
+    - dt-bindings: xilinx: Document new evaluation boards
+    - dt-bindings: pinctrl: Convert generic pin mux and config properties to
+      schema
+    - drivers: clk: Fix invalid clock name queries
+    - drivers: soc: xilinx: fix build failure due to missing COMMON_CLK dependency
+    - mmc: sdhci-of-arasan: Modified SD default speed to 19MHz for ZynqMP
+    - mmc: sdhci-of-arasan: Add "SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12" quirk.
+    - mmc: sdhci-of-arasan: Skip Auto tuning for DDR50 mode in ZynqMP platform
+    - ARM: zynq: Fix addresses in partition definitions
+    - mtd: spi-nor: Added support for sst26vf016b spi flash
+    - clk: zynqmp: Update CLK_FRAC support as per upstream
+    - rtc: zynqmp: Add calibration set and get support
+    - clk: zynqmp: Sync divider.c with upstream'ed version
+    - clk: zynqmp: Fix divider2 calculation
+    - microblaze: Convert headers to SPDX license
+    - microblaze: Fix unistd_32.h generation format
+    - microblaze: Fix _reset() function
+    - microblaze: Add ID for Microblaze v11
+    - microblaze: Remove architecture tlb.h and use generic one
+    - microblaze: Remove early printk setup
+    - microblaze: Remove empty headers
+    - microblaze: Define microblaze barrier
+    - microblaze: Add missing irqflags.h header
+    - microblaze: Remove unused boot_cpuid variable
+    - microblaze: Define percpu sestion in linker file
+    - microblaze: timer: Don't use cpu timer setting
+    - microblaze: timer: Separate clocksource timer from clockevent one
+    - microblaze: timer: Pass timer freq via parameter
+    - microblaze: timer: Squash clocksource code together
+    - microblaze: timer: Covert timer to use cpu hotplug
+    - microblaze: timer: Move irq code to clockevent function
+    - microblaze: timer: Create per cpu clockevent device
+    - microblaze: timer: Remove global variables
+    - microblaze: timer: Make sure that clockevent timer is initialized properly
+    - microblaze: timer: Group clockevent setting together
+    - microblaze: timer: Detect cpu_id from DT
+    - microblaze: timer: Change timer initialization setting
+    - microblaze: timer: Make timer SMP aware
+    - microblaze: Define SMP safe bit operations
+    - microblaze: Make cpuinfo structure SMP aware
+    - microblaze: Use asm generic cmpxchg.h for !SMP case
+    - microblaze: Add SMP implementation of xchg and cmpxchg
+    - irqchip: xilinx: Make per cpu primary controller entries
+    - irqchip: xilinx: Fill error code when irq domain registration fails
+    - irqchip: xilinx: Enable generic irq multi handler
+    - irqchip: xilinx: Use handle_domain_irq()
+    - irqchip: xilinx: Move early initialization to own function
+    - irqchip: xilinx: Add support for sw interrupts
+    - irqchip: xilinx: Support only LE/BE irqc by the same driver
+    - irqchip: xilinx: Rename root_domain just to domain
+    - irqchip: xilinx: Add support for cpu hotplug
+    - irqchip: xilinx: Add support for Microblaze SMP
+    - microblaze: Remove disabling IRQ while pte_update() run
+    - microblaze: Implement architecture spinlock
+    - microblaze: Do atomic operations by using exclusive
+    - microblaze: Add sync to tlb operations
+    - microblaze: Prepare entry.S for SMP implementation
+    - microblaze: Rework mmu context management to prepare
+    - microblaze: Enable experimental SMP functionality
+    - Revert "mtd: rawnand: nand_micron: Do not over write driver's
+      (read/write)_page() hooks"
+    - mtd: rawnand: pl353: Fix column and row address calculation
+    - mtd: rawnand: pl353: Increase the data in/out lengths
+    - mtd: rawnand: pl353: Add new pattern to support write only
+    - i2c: xiic: Fix Tx Interrupt path for grouped messages
+    - i2c: xiic: Add standard mode support for > 255 byte read transfers
+    - i2c: xiic: Fix coding style issues
+    - mtd: cadence-quadspi: Added support for master DLL mode
+    - mtd:cadence-quadspi: Added periodic Tuning support for RX
+    - mtd: cadence-quadspi: Fix the issues in DMA intr disable
+    - clk: zynqmp: Fix missing max_div description in kernel-doc format
+    - v4l: xilinx: multi-scaler: suppress info prints in vidioc_try_fmt API
+    - staging: xlnxsync: Optimize the driver for multi-channel use-cases
+    - v4l: xilinx: sdirxss: Add the missing timings
+    - net: macb: Enable WOL capability in probe
+    - mtd: cadence-quadspi: Fixed compilation warnings
+    - mtd: spi-nor: Flash devices with quad mode support added.
+    - drm/fb_helper: Enable drm_leak_fbdev_smem by default for zynqmp
+    - dt-bindings: display: xlnx: mixer: Add rev 5.0 to compatible string
+    - drm: xlnx: mixer: Add support to update the color space conversion
+      coefficients
+    - sound: soc: xilinx: Use unique dai link per device
+    - i2c: xiic: Enter standard mode only for > 255 byte read transfers
+    - staging: xlnx_tsmux: replace dma_zalloc_coherent API with dma_alloc_coherent
+    - dma: xilinx: Replace dma_zalloc_coherent API with dma_alloc_coherent
+    - v4l: xilinx: sdirxss: Fix returning error on stream off
+    - dt-bindings: media: xilinx: csi2rxss: Add 5.0 compatible string
+    - v4l: xilinx: xcsi2rxss: Move DPHY offset to 4K instead of 64K
+    - v4l: xilinx: dma: Prevent divide by zero error
+    - clk: zynqmp: Fix CLK_FRAC bit index
+    - i2c: xiic: Correct the datatype for rx_watermark
+    - i2c: xiic: Fix Rx and Tx paths in standard mode repeated start
+    - clk: clock-wizard: Remove a unnessary type cast
+    - v4l: xilinx: sdirxss: Fix IP reset on gt clock switch in 12G mode
+    - dt: bindings: media: xilinx: sdirxss : Add GT reset gpio handle
+    - v4l: xilinx: sdirxss: Add support for optional gt reset gpio
+    - dt: bindings: media: xilinx: sdirxss : Add bit depth optional property
+    - v4l: xilinx: sdirxss: Add new 10/12 bit support
+    - v4l: xilinx: sdirxss: Add support for ST2081-10 Mode 2 in 6G mode
+    - v4l: xilinx: xsdirxss: Fix format height for interlaced and pSF mode
+    - v4l: xilinx: vipp: move xvip_entity_start_stop() to xilinx-vipp
+    - v4l: xilinx: vipp: use async list for start and stop
+    - v4l: xilinx: vipp: do enabling in the dependency check
+    - v4l: xilinx: vipp: remove a loop for graph start / stop
+    - v4l: xilinx: vipp: Change xvip_entity_start/stop to take graph entity
+    - v4l: xilinx: vipp: Remove set streaming on subdev
+    - clk: idt: Fix i2cwritebulk() failure
+    - dt-bindings: firmware: ixp4xx: Drop redundant minItems/maxItems
+    - dt-bindings: interrupt-controller: arm,gic-v3: Add missing type to
+      interrupt-partition-* nodes
+    - dt-bindings: bus: Drop empty compatible string in example
+    - mtd: spi-nor: Fix warnings
+    - drm: xlnx: bridge: make xlnx_bridge_set_timing() static inline
+    - pinctrl: zynqmp: use module_platform_driver to simplify the code
+    - pinctrl: zynq: use module_platform_driver to simplify the code
+    - usb: dwc3: when enters in d3 state
+    - dt-bindings: versal: Add new PM_DEV_AI and PM_DEV_GPIO_PMC macros
+    - irqchip: xilinx: Change level for cpu-id warning
+    - mtd: cadence-quadspi: Fix the issues in Rx Periodic tuning
+    - drm/i2c: adv7511: add missing include to drm/drm_probe_helper.h
+    - drm: xlnx: fix some typos in the Kconfig help texts
+    - phy: zynqmp: check the config correctly
+    - misc: xilinx_flex: Fix the lock definitions
+    - staging: apf: Make the APF config as a boolean state
+    - serial: uartps: Remove unconditional wait inside set_termios
+    - serial: uartps: Add TACTIVE check in cdns_uart_tx_empty function
+    - dt-bindings: Add versal clocking wizard
+    - clocking-wizard: Add versal clocking wizard support
+    - dt-bindings: Fix the apm binding warnings
+    - remoteproc: zynqmp_r5: Add explicit nodes for vrings
+    - ASoC: xlnx: Fixed I2S sound card registration issue
+    - v4l: xilinx: multi-scaler: fix a printk format specifier
+    - spi: spi-mem: Modify update_stripe api to handle different commands with
+      same opcode value
+    - spi: spi-zynqmp-gqspi: Update driver to write appropriate dummy cycles as
+      per the tx_buswidth
+    - Revert "PCI: ZYNQMP EP driver: Adding Root DMA support"
+    - PCI: ZYNQMP EP driver: Adding Root DMA support
+    - fpga: versal: Use 32-bit DMA addressing
+    - usb: dwc3: otg: fix the function call used to get otg descriptor
+    - usb: dwc3: otg: remove otg static export warning
+    - remoteproc: zynq: Add explicit nodes for vrings
+    - clk: fixed-factor: Don't register fixed factor clk until parent clk is
+      registered
+    - usb: dwc3: Enable clock when USB resume occurs
+    - mtd: spi-nor: Fix page size calculation
+    - drm: xlnx: pl_disp: make the incoming interlaced fields in order
+    - serial: uartps: Wait for tx_empty in console setup
+    - serial: uartps: Use cdns_uart_tx_empty in console_write
+    - gpio: zynq: use module_platform_driver to simplify the code
+    - PCI: xilinx-nwl: Fix coding style violations
+    - Revert "net: phy: ensure phylib state machine is stopped after calling
+      phy_stop"
+    - Revert "net: phy: call state machine synchronously in phy_stop"
+    - dt-bindings: gpio: xilinx: Update binding to reflect changes
+    - gpio: xilinx: Use xilinx tested gpio driver
+    - dt-bindings: net: Add binding documentation for axi emaclite
+    - dt-bindings: usb: dwc3: Update binding to reflect latest state
+    - dt-bindings: udc-xilinx: Fix coding style in binding doc
+    - dt-bindings: usb: host: ehci-xilinx: Add binding doc
+    - arm64: zynqmp: Add/Update/Sync DTs for xilinx platforms
+    - ARM: xilinx: Add zynq defconfig
+    - arm64: xilinx: Add defconfig fragments
+    - xilinx: Add a github template telling people to not use pull requests there
+    - arm64: zynqmp: Fix irps5401 device nodes
+    - Revert "i2c: cadence: Fix the hold bit setting"
+    - tty: xilinx_uartps: Add the id to the console
+    - xilinx: versal: Enable Xilinx soft interrupt controller
+    - dma: zynqmp_dma: Initialize descriptor list after freeing during reset
+    - v4l: xilinx: csi: Fix the uapi header license
+    - v4l: xilinx: sdi: Fix the uapi header license
+    - v4l: xilinx: hls: Fix the uapi header license
+    - v4l: xilinx: events: Fix the uapi header license
+    - staging: xlnx_tsmux: Fix the uapi header license
+    - staging: xlnxsync: Fix the uapi header license
+    - xilinx: Disable strict devmem access control
+    - arm64: zynqmp: Enable IRPS5401 sensor
+    - mtd: spi-nor: Add support for macronix qspi flash
+    - arm64: xilinx: Enable i2c slave functionality
+    - mtd: spi-nor: Fix spi_nor_read for multi die flash connected in dual
+      parallel mode
+    - mtd: spi-nor: Add support for ISSI serial nor flashes
+    - mtd: cadence-quadspi: Added support for GD25LX256E
+    - clk: zynqmp: Handle divider specific read only flag
+    - mtd: spi-nor: Add 4byte opcode support for Macronix flash parts
+    - mtd: cadence-quadspi: Added support for is25wx256
+    - Revert "clk: fixed-factor: Don't register fixed factor clk until parent clk
+      is registered"
+    - dmaengine: xilinx: axidmatest: Fix variable length array usage
+    - dmaengine: xilinx: axidmatest: In init_srcs remove unnecessary buffer
+      increment
+    - drm: xlnx: pl_disp: fix missing xlnx_crtc_unregister
+    - drm: xlnx: fb: Guard with CONFIG_DRM_FBDEV_EMULATION
+    - dmaengine: xilinx_dma: use readl_poll_timeout_atomic variant
+    - v4l: xilinx: tpg: Don't read version if HLS IP
+    - v4l: xilinx: dma: Add control handler to v4l2 device
+    - spi-xilinx.c: correct multibyte writes
+    - net: xilinx: axiethernet: Fix swiotlb buffer full error
+    - soc: xilinx: Call InitFinalize from late_initcall_sync instead of probe
+    - dt-bindings: Fix paths in schema $id fields
+    - soc: xilinx: Fix error code in zynqmp_pm_probe()
+    - dmaengine: xilinx_dma: Add missing check for empty list
+    - dmaengine: xilinx: add mcdma reference in axidmatest documentation
+    - mtd: cadence-quadspi: Added support for Stacked mode
+    - dt-binding: soc: xilinx: ai-engine: Add new AI engine binding
+    - misc: ai-engine: Move AI engine reg access to kernel
+    - dt-binding: soc: xilinx: ai-engine: Add FPGA bridge for AI engine partition
+    - misc: ai-engine: Add FPGA bridge to AI engine partition
+    - arm64: xilinx: Enable Xilinx AI engine misc driver
+    - ARM: zynq: Fix spurious BUG with old DT
+    - misc: ai-engine: change driver name
+    - media: v4l: Add HDR support through compound controls
+    - drm: Add generic HDR support
+    - v4l: xilinx: sdirxss: Add HFR support
+    - xilinx: versal: Enable 48bit virtual address space size
+    - xilinx: configs: Setup maximum number of CPUs in defconfigs
+    - firmware: xilinx: Add support for GET_LAST_RESET_REASON IOCTL
+    - xilinx: firmware: Add sysfs to get last reset reason
+    - i2c: cadence: Handle transfer_size rollover
+    - i2c: cadence: Clear HOLD bit at correct time in Rx path
+    - clk: zynqmp: Use firmware specific common clock flags
+    - clk: zynqmp: Use firmware specific divider clock flags
+    - clk: zynqmp: Use firmware specific mux clock flags
+    - clk: zynqmp: Add missing checking of eemi_ops
+    - mtd: spi-nor: Fix wrong cr value in write_sr_modify_protection
+    - usb: dwc3: use PROPERTY_ENTRY_BOOL to initialize property entries
+    - misc: jesd204b: Remove unused function
+    - spi: spi-cadence: Fix mixed_enum_type coverity warning
+    - spi: spi-cadence: Fix uninit_use coverity warning
+    - clk: zynqmp: Map ZYNQMP_CLK_SET_RATE_GATE with CCF
+    - dt-binding: soc: xilinx: ai-engine: Include SHIM row in partition
+    - misc: xilinx-ai-engine: Update AI engine partition request parameter
+    - misc: ai-engine: Use the return value of mutex_lock_interruptible()
+    - misc: ai-engine: use correct printk formats
+    - misc: xilinx-ai-engine: export AI engine program and data memory to
+      userspace
+    - mtd: cadence-quadspi: Fixed UNUSED_VALUE warning
+    - mmc: host: sdhci-of-arasan: fix timings allocation code
+    - Revert "tty: xilinx_uartps: Fix missing id assignment to the console"
+    - spi: spi-xilinx: Check return value of of_property_read_u32
+    - spi: spi-xilinx: Fix incorrect variable type
+    - spi: spi-xilinx: Fix type mismatch in xilinx_spi_irq API
+    - soc: xilinx: vcu: Add proper error checking
+    - media: hdr-ctrls: Add a missing include
+    - mmc: host: sdhci-of-arasan: Check return value of non-void funtions
+    - mmc: host: sdhci-of-arasan: Use appropriate type of division macro
+    - mmc: host: sdhci-of-arasan: Resolve uninitialized return value
+    - mmc: host: sdhci-of-arasan: Modify data type of the clk_phase array
+    - spi: spi-zynqmp-gqspi: Do hardware initialization later in probe
+    - spi: spi-zynqmp-gqspi: Update correct value for DLY1 bit field
+    - spi: spi-zynqmp-gqspi: Set correct clock and data tap delay values in probe
+    - net: gmii2rgmii: Fix warning for return variable check
+    - clk: clock-wizard: Refactor internal clocks
+    - clk: clock-wizard: Use all stages of the MMCM
+    - clk: clock-wizard: Add ascii art block diagram of MMCM
+    - dmaengine: xilinx: frmbuf: add missing controller free when removing module
+    - net: macb: Limit DMA mapping to 39 bits
+    - clk: zynqmp: Check the return type
+    - clk: zynqmp: Fix a memory leak
+    - misc: trafgen: fix out of scope warning
+    - v4l: xilinx: scd: Correct max/min supported resolutions
+    - v4l: xilinx: scd: Allow setting field on MM SCD subdev
+    - dt: bindings: media: xilinx: Documentation for Xilinx DP Rx subsystem
+    - v4l: xilinx: Driver support for Xilinx DP Rx subsystem
+    - staging: apf: simple include clean-up
+    - staging: apf: remove a not needed variable
+    - staging: apf: move functions around in hierarchical order
+    - staging: apf: remove uio related codes
+    - staging: apf: small ifdef - else
+    - staging: apf: remove some dead codes
+    - staging: apf: free buffers in release
+    - dmaengine: xilinx_dma: Fix usage of xilinx_aximcdma_tx_segment
+    - dmaengine: xilinx_dma: Fix SG capability check for MCDMA
+    - spi: spi-zynqmp-gqspi: Disable interrupts before registering interrupt
+      handler
+    - firmware: xilinx: Use u32 for reset ID in reset APIs
+    - usb: dwc3: use proper typecast to handle overflow
+    - usb: dwc3: Initialized variable with a proper value
+    - usb: dwc3: Remove unused variable and values warnings
+    - usb: gadget: udc: Remove useless variable assignment in xudc_read_fifo()
+    - usb: gadget: udc: Add return value error handling of function
+    - usb: dwc3: Error handling for a function return value
+    - sound: xilinx: pcm: Set the platform device name correctly
+    - phy: Add DisplayPort configuration options
+    - v4l: xilinx: dprx: Remove unused variables
+    - v4l: xilinx: dprx: Fix incorrect comparisons
+    - v4l: xilinx: dprx: Fix uninitialized variables
+    - arm64: xilinx: Enable the DP rx v4l driver
+    - drm: xlnx: zynqmp_dp: include zynqmp_dp.h and fix the return type
+    - drm: xlnx: zynqmp: fix -Wunused-but-set-variable warnings
+    - xilinx: Fix xlnx,mio_bank property
+    - clk: zynqmp: Make zynqmp_clk_get_max_divisor static
+    - clk: zynqmp: Add a check for NULL pointer
+    - clk: zynqmp: make bestdiv unsigned
+    - misc: xilinx-ai-engine: Add extern functions to request AI engine partition
+    - PCI: xdma: Use SPDX license header
+    - PCI: xdma: Add documentation for versal PL PCIe as Root Port
+    - PCI: xdma: Add support for versal PL PCIe as Root Port
+    - drm: xlnx: Fix typo in parameter description
+    - misc: xilinx-ai-engine: remove duplicate module init/exit
+    - sound: soc: xilinx: Enable 8-channel SDI audio
+    - drm: xlnx: mixer: handle software vblank
+    - dt-bindings: media: vpss-csc: Fix description of color conversion
+    - drm: xlnx: mixer: fix comparison of unsigned expression < 0
+    - drm: xlnx: mixer: remove unused variables
+    - drm: xlnx: pl_disp: remove unused variables
+    - staging: xlnxsync: Don't write back Interrupt status register(ISR)
+    - staging: xlnxsync: Check valid bit for luma/chroma done interrupts
+    - staging: xlnxsync: Check synchronization and watchdog error for consumer
+    - drm: xlnx: mixer: Add support to 8K resolution
+    - swiotlb-xen: use vmalloc_to_page on vmalloc virt addresses
+    - misc: xilinx-ai-engine: replace number with macro in regoff definition
+    - misc: xilinx-ai-engine: implement shim reset
+    - misc: xilinx-ai-engine: Implement AI engine cleanup sequence
+    - misc: xilinx-ai-engine: Add partition control flag
+    - android: ion: properly clean caches for uncached allocations
+    - fpga: add bindings document for secure flags
+    - fpga: mgr: Adds secure BitStream loading support
+    - fpga: versal: Use the scatterlist interface
+    - fpga: zynqmp: Use the scatterlist interface
+    - can: xilinx_can: Fix incorrect variable and initialize with a default value
+    - can: xilinx_can: Check return value of set_reset_mode
+    - can: xilinx_can: Add comment for spinlock_t
+    - can: xilinx_can: Fix alignment match check
+    - can: xilinx_can: Remove unnecessary braces
+    - gpio: zynq: Check return value of pm_runtime_get_sync
+    - gpio: zynq: Check return value of irq_get_irq_data
+    - gpio: gpio-xilinx: Initialize ngpio variable in the declaration
+    - gpio: gpio-xilinx: Check return value of irq_get_handler_data
+    - misc: xilinx-ai-engine: Add function to enquire if a partition is available
+    - misc: xilinx-ai-engine: use bitmask for AI engine tile type
+    - gpio: gpio-xilinx: Check return value of of_property_read_u32
+    - misc: xilinx-ai-engine: reg access from userspace uses relative address
+    - misc: xilinx-ai-engine: add setting shim dma bd operation
+
+ -- Wen-chien Jesse Sung <jesse.sung@canonical.com>  Wed, 19 Aug 2020 18:36:12 +0800
+
+linux-xilinx-zynqmp (5.4.0-1000.0) focal; urgency=medium
+
+  * empty entry
+
+ -- Wen-chien Jesse Sung <jesse.sung@canonical.com>  Sun, 16 Aug 2020 15:59:56 +0800
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/config/annotations
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/config/annotations
@@ -0,0 +1,8376 @@
+# Menu: HEADER
+# FORMAT: 4
+# ARCH: arm64
+# FLAVOUR: arm64-xilinx-zynqmp
+
+include "../../debian.master/config/annotations"
+
+CONFIG_ACPI_CUSTOM_METHOD                       policy<{'arm64': '-'}>
+CONFIG_ACPI_CUSTOM_METHOD                       note<'SECURITY: allows arbitrary execution'>
+
+CONFIG_ARCH_ROCKCHIP                            policy<{'arm64': 'n'}>
+CONFIG_ARCH_ROCKCHIP                            note<'LP:1566283 / LP:1825222'>
+
+CONFIG_ARM64_LSE_ATOMICS                        policy<{'arm64': '-'}>
+CONFIG_ARM64_LSE_ATOMICS                        note<'LP:1691614'>
+
+CONFIG_ARMV8_DEPRECATED                         policy<{'arm64': 'n'}>
+CONFIG_ARMV8_DEPRECATED                         note<'LP:1545542'>
+
+CONFIG_ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT       policy<{'arm64': '-'}>
+CONFIG_ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT       note<'LP:1845820'>
+
+CONFIG_ATA_PIIX                                 policy<{'arm64': '-'}>
+CONFIG_ATA_PIIX                                 note<'LP:1627324'>
+
+CONFIG_AUFS_EXPORT                              policy<{'arm64': '-'}>
+CONFIG_AUFS_EXPORT                              note<'LP:1121699'>
+
+CONFIG_BLK_DEV_DM                               policy<{'arm64': 'm'}>
+CONFIG_BLK_DEV_DM                               note<'LP:#560717'>
+
+CONFIG_BLK_DEV_NVME                             policy<{'arm64': 'n'}>
+CONFIG_BLK_DEV_NVME                             note<'LP:#1759893'>
+
+CONFIG_BLK_DEV_RAM                              policy<{'arm64': 'y'}>
+CONFIG_BLK_DEV_RAM                              note<'LP #1593293'>
+
+CONFIG_BLK_DEV_SR                               policy<{'arm64': 'n'}>
+CONFIG_BLK_DEV_SR                               note<'LP:1627330'>
+
+CONFIG_BLK_DEV_THROTTLING                       policy<{'arm64': 'n'}>
+CONFIG_BLK_DEV_THROTTLING                       note<'CGROUP disk consumption control'>
+
+CONFIG_BLK_DEV_UMEM                             policy<{'arm64': 'n'}>
+CONFIG_BLK_DEV_UMEM                             note<'experimental NVRAM disk driver -- opt-in'>
+
+CONFIG_BT_HS                                    policy<{'arm64': 'y'}>
+CONFIG_BT_HS                                    note<'https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00435.html'>
+
+CONFIG_CHR_DEV_SG                               policy<{'arm64': 'n'}>
+CONFIG_CHR_DEV_SG                               note<'not autoloadable'>
+
+CONFIG_CMA_SIZE_MBYTES                          policy<{'arm64': '256'}>
+CONFIG_CMA_SIZE_MBYTES                          note<'LP:1823753'>
+
+CONFIG_CP15_BARRIER_EMULATION                   policy<{'arm64': '-'}>
+CONFIG_CP15_BARRIER_EMULATION                   note<'LP:1545542'>
+
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE         policy<{'arm64': 'n'}>
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE         note<'for bootspeed'>
+
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE                policy<{'arm64': 'n'}>
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE                note<'not autoloadable'>
+
+CONFIG_CPU_FREQ_GOV_ONDEMAND                    policy<{'arm64': 'n'}>
+CONFIG_CPU_FREQ_GOV_ONDEMAND                    note<'not autoloadable'>
+
+CONFIG_CPU_FREQ_GOV_PERFORMANCE                 policy<{'arm64': 'n'}>
+CONFIG_CPU_FREQ_GOV_PERFORMANCE                 note<'not autoloadable'>
+
+CONFIG_CPU_FREQ_GOV_POWERSAVE                   policy<{'arm64': 'n'}>
+CONFIG_CPU_FREQ_GOV_POWERSAVE                   note<'not autoloadable'>
+
+CONFIG_CPU_FREQ_STAT                            policy<{'arm64': 'n'}>
+CONFIG_CPU_FREQ_STAT                            note<'dependancy of boot essential'>
+
+CONFIG_CRYPTO_SHA512                            policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_SHA512                            note<'module signing'>
+
+CONFIG_DRM_AMDGPU_CIK                           policy<{'arm64': '-'}>
+CONFIG_DRM_AMDGPU_CIK                           note<'LP:1661887 for zesty'>
+
+CONFIG_DRM_BOCHS                                policy<{'arm64': 'n'}>
+CONFIG_DRM_BOCHS                                note<'LP#1916290'>
+
+CONFIG_DRM_HISI_HIBMC                           policy<{'arm64': 'n'}>
+CONFIG_DRM_HISI_HIBMC                           note<'LP:1762940'>
+
+CONFIG_DRM_MGAG200                              policy<{'arm64': 'n'}>
+CONFIG_DRM_MGAG200                              note<'LP#1693337'>
+
+CONFIG_DVB_DUMMY_FE                             policy<{'arm64': '-'}>
+CONFIG_DVB_DUMMY_FE                             note<'expert use only'>
+
+CONFIG_EFIVAR_FS                                policy<{'arm64': 'm'}>
+CONFIG_EFIVAR_FS                                note<'needed for variable EFI update'>
+
+CONFIG_EFI_VARS                                 policy<{'arm64': 'n'}>
+CONFIG_EFI_VARS                                 note<'EFI boot requirement (d-i) LP:#837332'>
+
+CONFIG_EVM                                      policy<{'arm64': 'n'}>
+CONFIG_EVM                                      note<'LP:1643652'>
+
+CONFIG_EVM_ATTR_FSUUID                          policy<{'arm64': '-'}>
+CONFIG_EVM_ATTR_FSUUID                          note<'LP:1643652'>
+
+CONFIG_EVM_LOAD_X509                            policy<{'arm64': '-'}>
+CONFIG_EVM_LOAD_X509                            note<'LP:1643652'>
+
+CONFIG_EXT3_FS                                  policy<{'arm64': 'y'}>
+CONFIG_EXT3_FS                                  note<'ext4 handling via EXT4_USE_FOR_EXT23'>
+
+CONFIG_FUSE_FS                                  policy<{'arm64': 'm'}>
+CONFIG_FUSE_FS                                  note<'not autoloadable'>
+
+CONFIG_FW_LOADER_USER_HELPER_FALLBACK           policy<{'arm64': '-'}>
+CONFIG_FW_LOADER_USER_HELPER_FALLBACK           note<'LP#1398458'>
+
+CONFIG_GPIO_TWL4030                             policy<{'arm64': '-'}>
+CONFIG_GPIO_TWL4030                             note<'LP:#921934'>
+
+CONFIG_HOTPLUG_PCI_PCIE                         policy<{'arm64': '-'}>
+CONFIG_HOTPLUG_PCI_PCIE                         note<'LP#1374440'>
+
+CONFIG_HOTPLUG_PCI_SHPC                         policy<{'arm64': '-'}>
+CONFIG_HOTPLUG_PCI_SHPC                         note<'LP#1374440'>
+
+CONFIG_IDLE_PAGE_TRACKING                       policy<{'arm64': 'n'}>
+CONFIG_IDLE_PAGE_TRACKING                       note<'is there a cost associated with this?'>
+
+CONFIG_IIO_SIMPLE_DUMMY_BUFFER                  policy<{'arm64': '-'}>
+CONFIG_IIO_SIMPLE_DUMMY_BUFFER                  note<'dummy driver'>
+
+CONFIG_IIO_SIMPLE_DUMMY_EVENTS                  policy<{'arm64': '-'}>
+CONFIG_IIO_SIMPLE_DUMMY_EVENTS                  note<'dummy driver'>
+
+CONFIG_IMA                                      policy<{'arm64': 'n'}>
+CONFIG_IMA                                      note<'LP:1643652'>
+
+CONFIG_IMA_APPRAISE                             policy<{'arm64': '-'}>
+CONFIG_IMA_APPRAISE                             note<'LP:1643652'>
+
+CONFIG_IMA_ARCH_POLICY                          policy<{'arm64': '-'}>
+CONFIG_IMA_ARCH_POLICY                          note<'LP:1866909'>
+
+CONFIG_IMA_DEFAULT_HASH_SHA256                  policy<{'arm64': '-'}>
+CONFIG_IMA_DEFAULT_HASH_SHA256                  note<'LP:1643652'>
+
+CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY policy<{'arm64': '-'}>
+CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY note<'LP:1667490'>
+
+CONFIG_IMA_READ_POLICY                          policy<{'arm64': '-'}>
+CONFIG_IMA_READ_POLICY                          note<'LP:1866909'>
+
+CONFIG_IMA_SIG_TEMPLATE                         policy<{'arm64': '-'}>
+CONFIG_IMA_SIG_TEMPLATE                         note<'LP:1643652'>
+
+CONFIG_IMA_WRITE_POLICY                         policy<{'arm64': '-'}>
+CONFIG_IMA_WRITE_POLICY                         note<'LP:1667490'>
+
+CONFIG_INPUT_UINPUT                             policy<{'arm64': 'n'}>
+CONFIG_INPUT_UINPUT                             note<'LP:584812'>
+
+CONFIG_INTEGRITY_PLATFORM_KEYRING               policy<{'arm64': '-'}>
+CONFIG_INTEGRITY_PLATFORM_KEYRING               note<'Required for lockdown'>
+
+CONFIG_IPDDP                                    policy<{'arm64': '-'}>
+CONFIG_IPDDP                                    note<'LP:1559772'>
+
+CONFIG_IPMMU_VMSA                               policy<{'arm64': '-'}>
+CONFIG_IPMMU_VMSA                               note<'LP:1718734'>
+
+CONFIG_IP_PNP                                   policy<{'arm64': 'y'}>
+CONFIG_IP_PNP                                   note<'LP:1259861'>
+
+CONFIG_KGDB_SERIAL_CONSOLE                      policy<{'arm64': '-'}>
+CONFIG_KGDB_SERIAL_CONSOLE                      note<'early debugging support'>
+
+CONFIG_KVM                                      policy<{'arm64': '-'}>
+CONFIG_KVM                                      note<'LP:1532886'>
+
+CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE            policy<{'arm64': 'n'}>
+CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE            note<'LP:1709171 LP:1848492'>
+
+CONFIG_MFD_SM501                                policy<{'arm64': 'n'}>
+CONFIG_MFD_SM501                                note<'boot essential on OMAP4'>
+
+CONFIG_MFD_TPS65217                             policy<{'arm64': 'n'}>
+CONFIG_MFD_TPS65217                             note<'boot essential on AM335x'>
+
+CONFIG_MMC_SDHCI                                policy<{'arm64': 'y'}>
+CONFIG_MMC_SDHCI                                note<'installation essential on omap/highbank'>
+
+CONFIG_MMC_SDHCI_PLTFM                          policy<{'arm64': 'y'}>
+CONFIG_MMC_SDHCI_PLTFM                          note<'boot essential on highbank'>
+
+CONFIG_MODVERSIONS                              policy<{'arm64': 'n'}>
+CONFIG_MODVERSIONS                              note<'LP:1898716 -- required as we have a livepatch/drivers modules signing key'>
+
+CONFIG_MTD                                      policy<{'arm64': 'y'}>
+CONFIG_MTD                                      note<'boot essential on arm'>
+
+CONFIG_MTD_BLOCK                                policy<{'arm64': 'y'}>
+CONFIG_MTD_BLOCK                                note<'boot essential on arm'>
+
+CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE             policy<{'arm64': '-'}>
+CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE             note<'can be enabled at runtime'>
+
+CONFIG_MTD_OF_PARTS                             policy<{'arm64': 'y'}>
+CONFIG_MTD_OF_PARTS                             note<'boot essential on arm'>
+
+CONFIG_MTD_ONENAND_VERIFY_WRITE                 policy<{'arm64': '-'}>
+CONFIG_MTD_ONENAND_VERIFY_WRITE                 note<'writes here are not checked in full without'>
+
+CONFIG_MTD_RAW_NAND                             policy<{'arm64': 'y'}>
+CONFIG_MTD_RAW_NAND                             note<'boot essential on arm'>
+
+CONFIG_NETWORK_PHY_TIMESTAMPING                 policy<{'arm64': 'n'}>
+CONFIG_NETWORK_PHY_TIMESTAMPING                 note<'LP:1785816'>
+
+CONFIG_NET_9P                                   policy<{'arm64': 'y'}>
+CONFIG_NET_9P                                   note<'LP:1557994'>
+
+CONFIG_NET_DROP_MONITOR                         policy<{'arm64': 'n'}>
+CONFIG_NET_DROP_MONITOR                         note<'LP #1660634'>
+
+CONFIG_NET_SWITCHDEV                            policy<{'arm64': 'n'}>
+CONFIG_NET_SWITCHDEV                            note<'LP: #1865452, updated to y for s390x starting with focal'>
+
+CONFIG_NOP_USB_XCEIV                            policy<{'arm64': 'n'}>
+CONFIG_NOP_USB_XCEIV                            note<'boot essential on omap/highbank'>
+
+CONFIG_NOUVEAU_LEGACY_CTX_SUPPORT               policy<{'arm64': '-'}>
+CONFIG_NOUVEAU_LEGACY_CTX_SUPPORT               note<'Selects CONFIG_DRM_LEGACY which is not wanted'>
+
+CONFIG_NR_CPUS                                  policy<{'arm64': '4'}>
+CONFIG_NR_CPUS                                  note<'LP:1864198'>
+
+CONFIG_NUMA                                     policy<{'arm64': 'n'}>
+CONFIG_NUMA                                     note<'LP:1543165 LP:1557690'>
+
+CONFIG_NUMA_BALANCING_DEFAULT_ENABLED           policy<{'arm64': '-'}>
+CONFIG_NUMA_BALANCING_DEFAULT_ENABLED           note<'LP:1557690'>
+
+CONFIG_N_GSM                                    policy<{'arm64': 'n'}>
+CONFIG_N_GSM                                    note<'LP#1404670'>
+
+CONFIG_PATA_HPT3X3_DMA                          policy<{'arm64': '-'}>
+CONFIG_PATA_HPT3X3_DMA                          note<'DMA mode is documented problematic'>
+
+CONFIG_PCIEASPM_DEFAULT                         policy<{'arm64': '-'}>
+CONFIG_PCIEASPM_DEFAULT                         note<'LP#1398544'>
+
+CONFIG_PCIEPORTBUS                              policy<{'arm64': 'n'}>
+CONFIG_PCIEPORTBUS                              note<'LP#1665404'>
+
+CONFIG_PREEMPT_NONE                             policy<{'arm64': 'y'}>
+CONFIG_PREEMPT_NONE                             note<'LP:1543165'>
+
+CONFIG_PSI_DEFAULT_DISABLED                     policy<{'arm64': '-'}>
+CONFIG_PSI_DEFAULT_DISABLED                     note<'LP: #1876044'>
+
+CONFIG_REGULATOR_FIXED_VOLTAGE                  policy<{'arm64': 'y'}>
+CONFIG_REGULATOR_FIXED_VOLTAGE                  note<'boot essential on arm'>
+
+CONFIG_REGULATOR_TPS65217                       policy<{'arm64': '-'}>
+CONFIG_REGULATOR_TPS65217                       note<'boot essential on AM335x'>
+
+CONFIG_REGULATOR_TWL4030                        policy<{'arm64': '-'}>
+CONFIG_REGULATOR_TWL4030                        note<'boot requisite for omap4'>
+
+CONFIG_RTC_DRV_EFI                              policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_EFI                              note<'LP:#1583738'>
+
+CONFIG_RTC_DRV_TWL4030                          policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_TWL4030                          note<'boot essential on OMAP3/OMAP4'>
+
+CONFIG_SAMPLE_TRACE_PRINTK                      policy<{'arm64': '-'}>
+CONFIG_SAMPLE_TRACE_PRINTK                      note<'Required for ftrace selftests'>
+
+CONFIG_SATA_AHCI_PLATFORM                       policy<{'arm64': 'y'}>
+CONFIG_SATA_AHCI_PLATFORM                       note<'boot essential on highbank'>
+
+CONFIG_SCSI_IPR_DUMP                            policy<{'arm64': '-'}>
+CONFIG_SCSI_IPR_DUMP                            note<'LP:1343109'>
+
+CONFIG_SCSI_IPR_TRACE                           policy<{'arm64': '-'}>
+CONFIG_SCSI_IPR_TRACE                           note<'LP:1343109'>
+
+CONFIG_SCSI_VIRTIO                              policy<{'arm64': 'n'}>
+CONFIG_SCSI_VIRTIO                              note<'tech preview of new feature'>
+
+CONFIG_SECURITY_SAFESETID                       policy<{'arm64': 'n'}>
+CONFIG_SECURITY_SAFESETID                       note<'LP:#1845391'>
+
+CONFIG_SERIAL_SH_SCI                            policy<{'arm64': '-'}>
+CONFIG_SERIAL_SH_SCI                            note<'LP: #2022361'>
+
+CONFIG_SERIAL_SH_SCI_CONSOLE                    policy<{'arm64': '-'}>
+CONFIG_SERIAL_SH_SCI_CONSOLE                    note<'LP: #2022361'>
+
+CONFIG_SERIAL_SH_SCI_EARLYCON                   policy<{'arm64': '-'}>
+CONFIG_SERIAL_SH_SCI_EARLYCON                   note<'LP: #2022361'>
+
+CONFIG_SETEND_EMULATION                         policy<{'arm64': '-'}>
+CONFIG_SETEND_EMULATION                         note<'LP:1545542'>
+
+CONFIG_SMC                                      policy<{'arm64': '-'}>
+CONFIG_SMC                                      note<'LP:1789934'>
+
+CONFIG_SMC_DIAG                                 policy<{'arm64': '-'}>
+CONFIG_SMC_DIAG                                 note<'LP:1789934'>
+
+CONFIG_SND                                      policy<{'arm64': 'y'}>
+CONFIG_SND                                      note<'not autoloadable on omap'>
+
+CONFIG_SND_HDA_POWER_SAVE_DEFAULT               policy<{'arm64': '-'}>
+CONFIG_SND_HDA_POWER_SAVE_DEFAULT               note<'LP:1804265'>
+
+CONFIG_SND_HDA_RECONFIG                         policy<{'arm64': '-'}>
+CONFIG_SND_HDA_RECONFIG                         note<'allows fixes to be tested live'>
+
+CONFIG_SND_PCM_OSS                              policy<{'arm64': '-'}>
+CONFIG_SND_PCM_OSS                              note<'deprecated in favour of pulseaudio emulation'>
+
+CONFIG_SND_SOC                                  policy<{'arm64': 'y'}>
+CONFIG_SND_SOC                                  note<'not autoloadable on omap'>
+
+CONFIG_SND_SOC_SOF_NOCODEC_SUPPORT              policy<{'arm64': '-'}>
+CONFIG_SND_SOC_SOF_NOCODEC_SUPPORT              note<'LP:1848490'>
+
+CONFIG_SOUND                                    policy<{'arm64': 'y'}>
+CONFIG_SOUND                                    note<'not autoloadable on omap'>
+
+CONFIG_SOUNDWIRE                                policy<{'arm64': 'n'}>
+CONFIG_SOUNDWIRE                                note<'LP:1855685'>
+
+CONFIG_SOUND_OSS_CORE_PRECLAIM                  policy<{'arm64': '-'}>
+CONFIG_SOUND_OSS_CORE_PRECLAIM                  note<'LP#1105230 LP#1385510'>
+
+CONFIG_SWP_EMULATION                            policy<{'arm64': '-'}>
+CONFIG_SWP_EMULATION                            note<'LP:1545542'>
+
+CONFIG_TCG_TIS_I2C_ATMEL                        policy<{'arm64': 'n'}>
+CONFIG_TCG_TIS_I2C_ATMEL                        note<'LP:1643652'>
+
+CONFIG_TCG_TIS_I2C_INFINEON                     policy<{'arm64': 'n'}>
+CONFIG_TCG_TIS_I2C_INFINEON                     note<'LP:1643652'>
+
+CONFIG_TCG_TIS_I2C_NUVOTON                      policy<{'arm64': 'n'}>
+CONFIG_TCG_TIS_I2C_NUVOTON                      note<'LP:1643652'>
+
+CONFIG_TCG_TPM                                  policy<{'arm64': 'm'}>
+CONFIG_TCG_TPM                                  note<'needed for early validation'>
+
+CONFIG_TOUCHSCREEN_ELAN                         policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_ELAN                         note<'LP #1630238'>
+
+CONFIG_USB_EHCI_HCD                             policy<{'arm64': 'n'}>
+CONFIG_USB_EHCI_HCD                             note<'ensures USB 2.0/1.1 probe ordering'>
+
+CONFIG_USB_EHCI_HCD_PLATFORM                    policy<{'arm64': '-'}>
+CONFIG_USB_EHCI_HCD_PLATFORM                    note<'Dont use the generic ehci/ohci code on omap, it doesnt work'>
+
+CONFIG_USB_HCD_BCMA                             policy<{'arm64': '-'}>
+CONFIG_USB_HCD_BCMA                             note<'USB_{O,E}HCI_HCD_PLATFORM must be off on omap'>
+
+CONFIG_USB_HCD_SSB                              policy<{'arm64': '-'}>
+CONFIG_USB_HCD_SSB                              note<'USB_{O,E}HCI_HCD_PLATFORM must be off on omap'>
+
+CONFIG_USB_MUSB_HDRC                            policy<{'arm64': 'n'}>
+CONFIG_USB_MUSB_HDRC                            note<'not autoloadable on omap'>
+
+CONFIG_USB_OHCI_HCD                             policy<{'arm64': 'n'}>
+CONFIG_USB_OHCI_HCD                             note<'ensures USB 2.0/1.1 probe ordering'>
+
+CONFIG_USB_OTG                                  policy<{'arm64': 'y'}>
+CONFIG_USB_OTG                                  note<'triggers breakage on x86 LP:1047527, LP:1411295'>
+
+CONFIG_USB_SERIAL_DEBUG                         policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_DEBUG                         note<'not actually debug'>
+
+CONFIG_USB_UHCI_HCD                             policy<{'arm64': 'n'}>
+CONFIG_USB_UHCI_HCD                             note<'ensures USB 2.0/1.1 probe ordering'>
+
+CONFIG_USB_XHCI_DBGCAP                          policy<{'arm64': 'n'}>
+CONFIG_USB_XHCI_DBGCAP                          note<'LP:1730832'>
+
+CONFIG_VFIO                                     policy<{'arm64': 'n'}>
+CONFIG_VFIO                                     note<'LP#1636733'>
+
+CONFIG_VFIO_PCI                                 policy<{'arm64': '-'}>
+CONFIG_VFIO_PCI                                 note<'LP#1636733'>
+
+CONFIG_VIDEO_VIMC                               policy<{'arm64': '-'}>
+CONFIG_VIDEO_VIMC                               note<'LP#1831482'>
+
+CONFIG_VIRTIO_BLK                               policy<{'arm64': 'n'}>
+CONFIG_VIRTIO_BLK                               note<'KVM paravirt support -- not autoloadable'>
+
+CONFIG_VIRTIO_MMIO                              policy<{'arm64': 'n'}>
+CONFIG_VIRTIO_MMIO                              note<'LP:1557689'>
+
+CONFIG_VIRTIO_NET                               policy<{'arm64': 'n'}>
+CONFIG_VIRTIO_NET                               note<'KVM paravirt support -- not autoloadable'>
+
+
+# ---- Annotations without notes ----
+
+CONFIG_6LOWPAN                                  policy<{'arm64': 'n'}>
+CONFIG_6LOWPAN_DEBUGFS                          policy<{'arm64': '-'}>
+CONFIG_6LOWPAN_GHC_EXT_HDR_DEST                 policy<{'arm64': '-'}>
+CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG                 policy<{'arm64': '-'}>
+CONFIG_6LOWPAN_GHC_EXT_HDR_HOP                  policy<{'arm64': '-'}>
+CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE                policy<{'arm64': '-'}>
+CONFIG_6LOWPAN_GHC_ICMPV6                       policy<{'arm64': '-'}>
+CONFIG_6LOWPAN_GHC_UDP                          policy<{'arm64': '-'}>
+CONFIG_6LOWPAN_NHC                              policy<{'arm64': '-'}>
+CONFIG_6LOWPAN_NHC_DEST                         policy<{'arm64': '-'}>
+CONFIG_6LOWPAN_NHC_FRAGMENT                     policy<{'arm64': '-'}>
+CONFIG_6LOWPAN_NHC_HOP                          policy<{'arm64': '-'}>
+CONFIG_6LOWPAN_NHC_IPV6                         policy<{'arm64': '-'}>
+CONFIG_6LOWPAN_NHC_MOBILITY                     policy<{'arm64': '-'}>
+CONFIG_6LOWPAN_NHC_ROUTING                      policy<{'arm64': '-'}>
+CONFIG_6LOWPAN_NHC_UDP                          policy<{'arm64': '-'}>
+CONFIG_6PACK                                    policy<{'arm64': '-'}>
+CONFIG_8139CP                                   policy<{'arm64': 'n'}>
+CONFIG_8139TOO                                  policy<{'arm64': 'n'}>
+CONFIG_8139TOO_8129                             policy<{'arm64': '-'}>
+CONFIG_8139TOO_PIO                              policy<{'arm64': '-'}>
+CONFIG_8139TOO_TUNE_TWISTER                     policy<{'arm64': '-'}>
+CONFIG_8139_OLD_RX_RESET                        policy<{'arm64': '-'}>
+CONFIG_842_COMPRESS                             policy<{'arm64': '-'}>
+CONFIG_842_DECOMPRESS                           policy<{'arm64': '-'}>
+CONFIG_88EU_AP_MODE                             policy<{'arm64': '-'}>
+CONFIG_9P_FS                                    policy<{'arm64': 'n'}>
+CONFIG_9P_FSCACHE                               policy<{'arm64': '-'}>
+CONFIG_9P_FS_POSIX_ACL                          policy<{'arm64': '-'}>
+CONFIG_9P_FS_SECURITY                           policy<{'arm64': '-'}>
+CONFIG_AB3100_CORE                              policy<{'arm64': '-'}>
+CONFIG_AB3100_OTP                               policy<{'arm64': '-'}>
+CONFIG_ABP060MG                                 policy<{'arm64': 'n'}>
+CONFIG_ABX500_CORE                              policy<{'arm64': 'n'}>
+CONFIG_AC97_BUS                                 policy<{'arm64': '-'}>
+CONFIG_ACENIC                                   policy<{'arm64': 'n'}>
+CONFIG_ACENIC_OMIT_TIGON_I                      policy<{'arm64': '-'}>
+CONFIG_ACORN_PARTITION                          policy<{'arm64': '-'}>
+CONFIG_ACPI                                     policy<{'arm64': 'n'}>
+CONFIG_ACPI_AC                                  policy<{'arm64': '-'}>
+CONFIG_ACPI_ALS                                 policy<{'arm64': '-'}>
+CONFIG_ACPI_APEI                                policy<{'arm64': '-'}>
+CONFIG_ACPI_APEI_EINJ                           policy<{'arm64': '-'}>
+CONFIG_ACPI_APEI_ERST_DEBUG                     policy<{'arm64': '-'}>
+CONFIG_ACPI_APEI_GHES                           policy<{'arm64': '-'}>
+CONFIG_ACPI_APEI_MEMORY_FAILURE                 policy<{'arm64': '-'}>
+CONFIG_ACPI_APEI_PCIEAER                        policy<{'arm64': '-'}>
+CONFIG_ACPI_APEI_SEA                            policy<{'arm64': '-'}>
+CONFIG_ACPI_BATTERY                             policy<{'arm64': '-'}>
+CONFIG_ACPI_BGRT                                policy<{'arm64': '-'}>
+CONFIG_ACPI_BUTTON                              policy<{'arm64': '-'}>
+CONFIG_ACPI_CCA_REQUIRED                        policy<{'arm64': '-'}>
+CONFIG_ACPI_CONFIGFS                            policy<{'arm64': '-'}>
+CONFIG_ACPI_CONTAINER                           policy<{'arm64': '-'}>
+CONFIG_ACPI_CPPC_CPUFREQ                        policy<{'arm64': '-'}>
+CONFIG_ACPI_CPPC_LIB                            policy<{'arm64': '-'}>
+CONFIG_ACPI_DEBUG                               policy<{'arm64': '-'}>
+CONFIG_ACPI_DEBUGGER                            policy<{'arm64': '-'}>
+CONFIG_ACPI_DOCK                                policy<{'arm64': '-'}>
+CONFIG_ACPI_EC_DEBUGFS                          policy<{'arm64': '-'}>
+CONFIG_ACPI_FAN                                 policy<{'arm64': '-'}>
+CONFIG_ACPI_GENERIC_GSI                         policy<{'arm64': '-'}>
+CONFIG_ACPI_GTDT                                policy<{'arm64': '-'}>
+CONFIG_ACPI_HED                                 policy<{'arm64': '-'}>
+CONFIG_ACPI_HMAT                                policy<{'arm64': '-'}>
+CONFIG_ACPI_HOTPLUG_CPU                         policy<{'arm64': '-'}>
+CONFIG_ACPI_HOTPLUG_MEMORY                      policy<{'arm64': '-'}>
+CONFIG_ACPI_I2C_OPREGION                        policy<{'arm64': '-'}>
+CONFIG_ACPI_IORT                                policy<{'arm64': '-'}>
+CONFIG_ACPI_IPMI                                policy<{'arm64': '-'}>
+CONFIG_ACPI_MCFG                                policy<{'arm64': '-'}>
+CONFIG_ACPI_NFIT                                policy<{'arm64': '-'}>
+CONFIG_ACPI_NUMA                                policy<{'arm64': '-'}>
+CONFIG_ACPI_PCI_SLOT                            policy<{'arm64': '-'}>
+CONFIG_ACPI_PPTT                                policy<{'arm64': '-'}>
+CONFIG_ACPI_PROCESSOR                           policy<{'arm64': '-'}>
+CONFIG_ACPI_PROCESSOR_IDLE                      policy<{'arm64': '-'}>
+CONFIG_ACPI_REDUCED_HARDWARE_ONLY               policy<{'arm64': '-'}>
+CONFIG_ACPI_SPCR_TABLE                          policy<{'arm64': '-'}>
+CONFIG_ACPI_TABLE_UPGRADE                       policy<{'arm64': '-'}>
+CONFIG_ACPI_TAD                                 policy<{'arm64': '-'}>
+CONFIG_ACPI_THERMAL                             policy<{'arm64': '-'}>
+CONFIG_ACPI_WATCHDOG                            policy<{'arm64': '-'}>
+CONFIG_AD2S1200                                 policy<{'arm64': 'n'}>
+CONFIG_AD2S1210                                 policy<{'arm64': 'n'}>
+CONFIG_AD2S90                                   policy<{'arm64': 'n'}>
+CONFIG_AD5064                                   policy<{'arm64': 'n'}>
+CONFIG_AD525X_DPOT                              policy<{'arm64': 'n'}>
+CONFIG_AD525X_DPOT_I2C                          policy<{'arm64': '-'}>
+CONFIG_AD525X_DPOT_SPI                          policy<{'arm64': '-'}>
+CONFIG_AD5272                                   policy<{'arm64': 'n'}>
+CONFIG_AD5360                                   policy<{'arm64': 'n'}>
+CONFIG_AD5380                                   policy<{'arm64': 'n'}>
+CONFIG_AD5421                                   policy<{'arm64': 'n'}>
+CONFIG_AD5446                                   policy<{'arm64': 'n'}>
+CONFIG_AD5449                                   policy<{'arm64': 'n'}>
+CONFIG_AD5504                                   policy<{'arm64': 'n'}>
+CONFIG_AD5592R                                  policy<{'arm64': 'n'}>
+CONFIG_AD5592R_BASE                             policy<{'arm64': '-'}>
+CONFIG_AD5593R                                  policy<{'arm64': 'n'}>
+CONFIG_AD5624R_SPI                              policy<{'arm64': 'n'}>
+CONFIG_AD5686                                   policy<{'arm64': '-'}>
+CONFIG_AD5686_SPI                               policy<{'arm64': 'n'}>
+CONFIG_AD5696_I2C                               policy<{'arm64': 'n'}>
+CONFIG_AD5755                                   policy<{'arm64': 'n'}>
+CONFIG_AD5758                                   policy<{'arm64': 'n'}>
+CONFIG_AD5761                                   policy<{'arm64': 'n'}>
+CONFIG_AD5764                                   policy<{'arm64': 'n'}>
+CONFIG_AD5791                                   policy<{'arm64': 'n'}>
+CONFIG_AD5933                                   policy<{'arm64': 'n'}>
+CONFIG_AD7124                                   policy<{'arm64': 'n'}>
+CONFIG_AD7150                                   policy<{'arm64': 'n'}>
+CONFIG_AD7192                                   policy<{'arm64': 'n'}>
+CONFIG_AD7266                                   policy<{'arm64': 'n'}>
+CONFIG_AD7280                                   policy<{'arm64': 'n'}>
+CONFIG_AD7291                                   policy<{'arm64': 'n'}>
+CONFIG_AD7298                                   policy<{'arm64': 'n'}>
+CONFIG_AD7303                                   policy<{'arm64': 'n'}>
+CONFIG_AD7476                                   policy<{'arm64': 'n'}>
+CONFIG_AD7606                                   policy<{'arm64': '-'}>
+CONFIG_AD7606_IFACE_PARALLEL                    policy<{'arm64': 'n'}>
+CONFIG_AD7606_IFACE_SPI                         policy<{'arm64': 'n'}>
+CONFIG_AD7746                                   policy<{'arm64': 'n'}>
+CONFIG_AD7766                                   policy<{'arm64': 'n'}>
+CONFIG_AD7768_1                                 policy<{'arm64': 'n'}>
+CONFIG_AD7780                                   policy<{'arm64': 'n'}>
+CONFIG_AD7791                                   policy<{'arm64': 'n'}>
+CONFIG_AD7793                                   policy<{'arm64': 'n'}>
+CONFIG_AD7816                                   policy<{'arm64': 'n'}>
+CONFIG_AD7887                                   policy<{'arm64': 'n'}>
+CONFIG_AD7923                                   policy<{'arm64': 'n'}>
+CONFIG_AD7949                                   policy<{'arm64': 'n'}>
+CONFIG_AD799X                                   policy<{'arm64': 'n'}>
+CONFIG_AD8366                                   policy<{'arm64': 'n'}>
+CONFIG_AD8801                                   policy<{'arm64': 'n'}>
+CONFIG_AD9523                                   policy<{'arm64': 'n'}>
+CONFIG_AD9832                                   policy<{'arm64': 'n'}>
+CONFIG_AD9834                                   policy<{'arm64': 'n'}>
+CONFIG_ADAPTEC_STARFIRE                         policy<{'arm64': 'n'}>
+CONFIG_ADE7854                                  policy<{'arm64': 'n'}>
+CONFIG_ADE7854_I2C                              policy<{'arm64': '-'}>
+CONFIG_ADE7854_SPI                              policy<{'arm64': '-'}>
+CONFIG_ADF4350                                  policy<{'arm64': 'n'}>
+CONFIG_ADF4371                                  policy<{'arm64': 'n'}>
+CONFIG_ADFS_FS                                  policy<{'arm64': 'n'}>
+CONFIG_ADFS_FS_RW                               policy<{'arm64': '-'}>
+CONFIG_ADIN_PHY                                 policy<{'arm64': 'n'}>
+CONFIG_ADIS16080                                policy<{'arm64': 'n'}>
+CONFIG_ADIS16130                                policy<{'arm64': 'n'}>
+CONFIG_ADIS16136                                policy<{'arm64': 'n'}>
+CONFIG_ADIS16201                                policy<{'arm64': 'n'}>
+CONFIG_ADIS16203                                policy<{'arm64': 'n'}>
+CONFIG_ADIS16209                                policy<{'arm64': 'n'}>
+CONFIG_ADIS16240                                policy<{'arm64': 'n'}>
+CONFIG_ADIS16260                                policy<{'arm64': 'n'}>
+CONFIG_ADIS16400                                policy<{'arm64': 'n'}>
+CONFIG_ADIS16460                                policy<{'arm64': 'n'}>
+CONFIG_ADIS16480                                policy<{'arm64': 'n'}>
+CONFIG_ADJD_S311                                policy<{'arm64': 'n'}>
+CONFIG_ADM8211                                  policy<{'arm64': 'n'}>
+CONFIG_ADT7316                                  policy<{'arm64': 'n'}>
+CONFIG_ADT7316_I2C                              policy<{'arm64': '-'}>
+CONFIG_ADT7316_SPI                              policy<{'arm64': '-'}>
+CONFIG_ADXL345_I2C                              policy<{'arm64': 'n'}>
+CONFIG_ADXL345_SPI                              policy<{'arm64': 'n'}>
+CONFIG_ADXL372                                  policy<{'arm64': '-'}>
+CONFIG_ADXL372_I2C                              policy<{'arm64': 'n'}>
+CONFIG_ADXL372_SPI                              policy<{'arm64': 'n'}>
+CONFIG_ADXRS450                                 policy<{'arm64': 'n'}>
+CONFIG_AD_SIGMA_DELTA                           policy<{'arm64': '-'}>
+CONFIG_AFE4403                                  policy<{'arm64': 'n'}>
+CONFIG_AFE4404                                  policy<{'arm64': 'n'}>
+CONFIG_AFFS_FS                                  policy<{'arm64': 'n'}>
+CONFIG_AFS_DEBUG                                policy<{'arm64': '-'}>
+CONFIG_AFS_DEBUG_CURSOR                         policy<{'arm64': '-'}>
+CONFIG_AFS_FS                                   policy<{'arm64': 'n'}>
+CONFIG_AFS_FSCACHE                              policy<{'arm64': '-'}>
+CONFIG_AF_KCM                                   policy<{'arm64': 'n'}>
+CONFIG_AF_RXRPC                                 policy<{'arm64': 'n'}>
+CONFIG_AF_RXRPC_DEBUG                           policy<{'arm64': '-'}>
+CONFIG_AF_RXRPC_INJECT_LOSS                     policy<{'arm64': '-'}>
+CONFIG_AF_RXRPC_IPV6                            policy<{'arm64': '-'}>
+CONFIG_AHCI_BRCM                                policy<{'arm64': '-'}>
+CONFIG_AHCI_CEVA                                policy<{'arm64': 'y'}>
+CONFIG_AHCI_IMX                                 policy<{'arm64': '-'}>
+CONFIG_AHCI_MTK                                 policy<{'arm64': '-'}>
+CONFIG_AHCI_MVEBU                               policy<{'arm64': '-'}>
+CONFIG_AHCI_QORIQ                               policy<{'arm64': 'n'}>
+CONFIG_AHCI_SUNXI                               policy<{'arm64': '-'}>
+CONFIG_AHCI_XGENE                               policy<{'arm64': '-'}>
+CONFIG_AIC79XX_CMDS_PER_DEVICE                  policy<{'arm64': '-'}>
+CONFIG_AIC79XX_DEBUG_ENABLE                     policy<{'arm64': '-'}>
+CONFIG_AIC79XX_DEBUG_MASK                       policy<{'arm64': '-'}>
+CONFIG_AIC79XX_REG_PRETTY_PRINT                 policy<{'arm64': '-'}>
+CONFIG_AIC79XX_RESET_DELAY_MS                   policy<{'arm64': '-'}>
+CONFIG_AIC7XXX_CMDS_PER_DEVICE                  policy<{'arm64': '-'}>
+CONFIG_AIC7XXX_DEBUG_ENABLE                     policy<{'arm64': '-'}>
+CONFIG_AIC7XXX_DEBUG_MASK                       policy<{'arm64': '-'}>
+CONFIG_AIC7XXX_REG_PRETTY_PRINT                 policy<{'arm64': '-'}>
+CONFIG_AIC7XXX_RESET_DELAY_MS                   policy<{'arm64': '-'}>
+CONFIG_AIC94XX_DEBUG                            policy<{'arm64': '-'}>
+CONFIG_AIX_PARTITION                            policy<{'arm64': '-'}>
+CONFIG_AK09911                                  policy<{'arm64': 'n'}>
+CONFIG_AK8974                                   policy<{'arm64': 'n'}>
+CONFIG_AK8975                                   policy<{'arm64': 'n'}>
+CONFIG_AL3320A                                  policy<{'arm64': 'n'}>
+CONFIG_ALIM7101_WDT                             policy<{'arm64': 'n'}>
+CONFIG_ALTERA_FREEZE_BRIDGE                     policy<{'arm64': 'n'}>
+CONFIG_ALTERA_MBOX                              policy<{'arm64': 'n'}>
+CONFIG_ALTERA_MSGDMA                            policy<{'arm64': 'n'}>
+CONFIG_ALTERA_PR_IP_CORE                        policy<{'arm64': 'n'}>
+CONFIG_ALTERA_PR_IP_CORE_PLAT                   policy<{'arm64': '-'}>
+CONFIG_ALTERA_STAPL                             policy<{'arm64': 'n'}>
+CONFIG_ALTERA_TSE                               policy<{'arm64': 'n'}>
+CONFIG_ALX                                      policy<{'arm64': 'n'}>
+CONFIG_AL_FIC                                   policy<{'arm64': 'n'}>
+CONFIG_AM2315                                   policy<{'arm64': 'n'}>
+CONFIG_AMBA_PL08X                               policy<{'arm64': 'n'}>
+CONFIG_AMD8111_ETH                              policy<{'arm64': 'n'}>
+CONFIG_AMD_PHY                                  policy<{'arm64': 'y'}>
+CONFIG_AMD_XGBE                                 policy<{'arm64': 'n'}>
+CONFIG_AMD_XGBE_DCB                             policy<{'arm64': '-'}>
+CONFIG_AMIGA_PARTITION                          policy<{'arm64': '-'}>
+CONFIG_ANDROID_BINDERFS                         policy<{'arm64': '-'}>
+CONFIG_ANDROID_BINDER_DEVICES                   policy<{'arm64': '-'}>
+CONFIG_ANDROID_BINDER_IPC                       policy<{'arm64': 'n'}>
+CONFIG_ANDROID_BINDER_IPC_SELFTEST              policy<{'arm64': '-'}>
+CONFIG_APDS9300                                 policy<{'arm64': 'n'}>
+CONFIG_APDS9802ALS                              policy<{'arm64': 'n'}>
+CONFIG_APDS9960                                 policy<{'arm64': 'n'}>
+CONFIG_APPLICOM                                 policy<{'arm64': 'n'}>
+CONFIG_APQ_GCC_8084                             policy<{'arm64': '-'}>
+CONFIG_APQ_MMCC_8084                            policy<{'arm64': '-'}>
+CONFIG_AQTION                                   policy<{'arm64': 'n'}>
+CONFIG_AQUANTIA_PHY                             policy<{'arm64': 'n'}>
+CONFIG_AR5523                                   policy<{'arm64': 'n'}>
+CONFIG_ARCH_ACTIONS                             policy<{'arm64': 'n'}>
+CONFIG_ARCH_AGILEX                              policy<{'arm64': 'n'}>
+CONFIG_ARCH_BCM2835                             policy<{'arm64': 'n'}>
+CONFIG_ARCH_BCM_IPROC                           policy<{'arm64': 'n'}>
+CONFIG_ARCH_BERLIN                              policy<{'arm64': 'n'}>
+CONFIG_ARCH_BITMAIN                             policy<{'arm64': 'n'}>
+CONFIG_ARCH_BRCMSTB                             policy<{'arm64': 'n'}>
+CONFIG_ARCH_FLATMEM_ENABLE                      policy<{'arm64': 'y'}>
+CONFIG_ARCH_HAS_ACPI_TABLE_UPGRADE              policy<{'arm64': '-'}>
+CONFIG_ARCH_HAS_PMEM_API                        policy<{'arm64': '-'}>
+CONFIG_ARCH_HAS_RESET_CONTROLLER                policy<{'arm64': '-'}>
+CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE              policy<{'arm64': '-'}>
+CONFIG_ARCH_HISI                                policy<{'arm64': 'n'}>
+CONFIG_ARCH_K3                                  policy<{'arm64': 'n'}>
+CONFIG_ARCH_K3_AM6_SOC                          policy<{'arm64': '-'}>
+CONFIG_ARCH_K3_J721E_SOC                        policy<{'arm64': '-'}>
+CONFIG_ARCH_LAYERSCAPE                          policy<{'arm64': 'n'}>
+CONFIG_ARCH_LG1K                                policy<{'arm64': 'n'}>
+CONFIG_ARCH_MEDIATEK                            policy<{'arm64': 'n'}>
+CONFIG_ARCH_MESON                               policy<{'arm64': 'n'}>
+CONFIG_ARCH_MVEBU                               policy<{'arm64': 'n'}>
+CONFIG_ARCH_MXC                                 policy<{'arm64': 'n'}>
+CONFIG_ARCH_QCOM                                policy<{'arm64': 'n'}>
+CONFIG_ARCH_R8A774A1                            policy<{'arm64': '-'}>
+CONFIG_ARCH_R8A774C0                            policy<{'arm64': '-'}>
+CONFIG_ARCH_R8A7795                             policy<{'arm64': '-'}>
+CONFIG_ARCH_R8A7796                             policy<{'arm64': '-'}>
+CONFIG_ARCH_R8A77965                            policy<{'arm64': '-'}>
+CONFIG_ARCH_R8A77970                            policy<{'arm64': '-'}>
+CONFIG_ARCH_R8A77980                            policy<{'arm64': '-'}>
+CONFIG_ARCH_R8A77990                            policy<{'arm64': '-'}>
+CONFIG_ARCH_R8A77995                            policy<{'arm64': '-'}>
+CONFIG_ARCH_RCAR_GEN3                           policy<{'arm64': '-'}>
+CONFIG_ARCH_REALTEK                             policy<{'arm64': 'n'}>
+CONFIG_ARCH_RENESAS                             policy<{'arm64': 'n'}>
+CONFIG_ARCH_SEATTLE                             policy<{'arm64': 'n'}>
+CONFIG_ARCH_SPRD                                policy<{'arm64': 'n'}>
+CONFIG_ARCH_STRATIX10                           policy<{'arm64': 'n'}>
+CONFIG_ARCH_SUNXI                               policy<{'arm64': 'n'}>
+CONFIG_ARCH_SYNQUACER                           policy<{'arm64': 'n'}>
+CONFIG_ARCH_THUNDER                             policy<{'arm64': 'n'}>
+CONFIG_ARCH_THUNDER2                            policy<{'arm64': 'n'}>
+CONFIG_ARCH_VEXPRESS                            policy<{'arm64': 'n'}>
+CONFIG_ARCH_XGENE                               policy<{'arm64': 'n'}>
+CONFIG_ARCNET                                   policy<{'arm64': 'n'}>
+CONFIG_ARCNET_1051                              policy<{'arm64': '-'}>
+CONFIG_ARCNET_1201                              policy<{'arm64': '-'}>
+CONFIG_ARCNET_CAP                               policy<{'arm64': '-'}>
+CONFIG_ARCNET_COM20020                          policy<{'arm64': '-'}>
+CONFIG_ARCNET_COM20020_PCI                      policy<{'arm64': '-'}>
+CONFIG_ARCNET_COM90xx                           policy<{'arm64': '-'}>
+CONFIG_ARCNET_COM90xxIO                         policy<{'arm64': '-'}>
+CONFIG_ARCNET_RAW                               policy<{'arm64': '-'}>
+CONFIG_ARCNET_RIM_I                             policy<{'arm64': '-'}>
+CONFIG_ARCX_ANYBUS_CONTROLLER                   policy<{'arm64': '-'}>
+CONFIG_ARC_EMAC_CORE                            policy<{'arm64': '-'}>
+CONFIG_ARM64_ACPI_PARKING_PROTOCOL              policy<{'arm64': '-'}>
+CONFIG_ARM64_DEBUG_PRIORITY_MASKING             policy<{'arm64': '-'}>
+CONFIG_ARM64_ERRATUM_1542419                    policy<{'arm64': 'n'}>
+CONFIG_ARM64_ERRATUM_834220                     policy<{'arm64': '-'}>
+CONFIG_ARM64_PMEM                               policy<{'arm64': 'n'}>
+CONFIG_ARM64_PSEUDO_NMI                         policy<{'arm64': 'n'}>
+CONFIG_ARMADA_37XX_CLK                          policy<{'arm64': '-'}>
+CONFIG_ARMADA_37XX_RWTM_MBOX                    policy<{'arm64': '-'}>
+CONFIG_ARMADA_37XX_WATCHDOG                     policy<{'arm64': '-'}>
+CONFIG_ARMADA_AP806_SYSCON                      policy<{'arm64': '-'}>
+CONFIG_ARMADA_AP_CPU_CLK                        policy<{'arm64': '-'}>
+CONFIG_ARMADA_AP_CP_HELPER                      policy<{'arm64': '-'}>
+CONFIG_ARMADA_CP110_SYSCON                      policy<{'arm64': '-'}>
+CONFIG_ARMADA_THERMAL                           policy<{'arm64': '-'}>
+CONFIG_ARM_ALLWINNER_SUN50I_CPUFREQ_NVMEM       policy<{'arm64': '-'}>
+CONFIG_ARM_ARCH_TIMER_EVTSTREAM                 policy<{'arm64': 'n'}>
+CONFIG_ARM_ARMADA_37XX_CPUFREQ                  policy<{'arm64': '-'}>
+CONFIG_ARM_ARMADA_8K_CPUFREQ                    policy<{'arm64': '-'}>
+CONFIG_ARM_BRCMSTB_AVS_CPUFREQ                  policy<{'arm64': '-'}>
+CONFIG_ARM_CCN                                  policy<{'arm64': 'n'}>
+CONFIG_ARM_DSU_PMU                              policy<{'arm64': 'n'}>
+CONFIG_ARM_GIC_V3_ITS_FSL_MC                    policy<{'arm64': '-'}>
+CONFIG_ARM_IMX6Q_CPUFREQ                        policy<{'arm64': '-'}>
+CONFIG_ARM_IMX_CPUFREQ_DT                       policy<{'arm64': '-'}>
+CONFIG_ARM_MEDIATEK_CPUFREQ                     policy<{'arm64': '-'}>
+CONFIG_ARM_MHU                                  policy<{'arm64': 'n'}>
+CONFIG_ARM_PL172_MPMC                           policy<{'arm64': '-'}>
+CONFIG_ARM_PMU                                  policy<{'arm64': 'n'}>
+CONFIG_ARM_PMU_ACPI                             policy<{'arm64': '-'}>
+CONFIG_ARM_PSCI_CPUIDLE                         policy<{'arm64': 'n'}>
+CONFIG_ARM_QCOM_CPUFREQ_HW                      policy<{'arm64': '-'}>
+CONFIG_ARM_QCOM_CPUFREQ_NVMEM                   policy<{'arm64': '-'}>
+CONFIG_ARM_RASPBERRYPI_CPUFREQ                  policy<{'arm64': '-'}>
+CONFIG_ARM_RK3399_DMC_DEVFREQ                   policy<{'arm64': '-'}>
+CONFIG_ARM_SBSA_WATCHDOG                        policy<{'arm64': 'n'}>
+CONFIG_ARM_SCMI_CPUFREQ                         policy<{'arm64': '-'}>
+CONFIG_ARM_SCMI_POWER_DOMAIN                    policy<{'arm64': '-'}>
+CONFIG_ARM_SCMI_PROTOCOL                        policy<{'arm64': 'n'}>
+CONFIG_ARM_SCPI_CPUFREQ                         policy<{'arm64': '-'}>
+CONFIG_ARM_SCPI_POWER_DOMAIN                    policy<{'arm64': '-'}>
+CONFIG_ARM_SCPI_PROTOCOL                        policy<{'arm64': 'n'}>
+CONFIG_ARM_SDE_INTERFACE                        policy<{'arm64': 'n'}>
+CONFIG_ARM_SMMU                                 policy<{'arm64': 'n'}>
+CONFIG_ARM_SMMU_V3                              policy<{'arm64': 'n'}>
+CONFIG_ARM_SMMU_V3_PMU                          policy<{'arm64': '-'}>
+CONFIG_ARM_SP805_WATCHDOG                       policy<{'arm64': 'n'}>
+CONFIG_ARM_SPE_PMU                              policy<{'arm64': 'n'}>
+CONFIG_ARM_TIMER_SP804                          policy<{'arm64': '-'}>
+CONFIG_AS3935                                   policy<{'arm64': 'n'}>
+CONFIG_ASHMEM                                   policy<{'arm64': 'n'}>
+CONFIG_ASM_MODVERSIONS                          policy<{'arm64': '-'}>
+CONFIG_ASYMMETRIC_TPM_KEY_SUBTYPE               policy<{'arm64': '-'}>
+CONFIG_ASYNC_CORE                               policy<{'arm64': '-'}>
+CONFIG_ASYNC_MEMCPY                             policy<{'arm64': '-'}>
+CONFIG_ASYNC_PQ                                 policy<{'arm64': '-'}>
+CONFIG_ASYNC_RAID6_RECOV                        policy<{'arm64': '-'}>
+CONFIG_ASYNC_RAID6_TEST                         policy<{'arm64': '-'}>
+CONFIG_ASYNC_TX_DISABLE_PQ_VAL_DMA              policy<{'arm64': '-'}>
+CONFIG_ASYNC_TX_DISABLE_XOR_VAL_DMA             policy<{'arm64': '-'}>
+CONFIG_ASYNC_TX_DMA                             policy<{'arm64': 'n'}>
+CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH           policy<{'arm64': '-'}>
+CONFIG_ASYNC_XOR                                policy<{'arm64': '-'}>
+CONFIG_AT76C50X_USB                             policy<{'arm64': 'n'}>
+CONFIG_AT803X_PHY                               policy<{'arm64': 'y'}>
+CONFIG_ATALK                                    policy<{'arm64': 'n'}>
+CONFIG_ATARI_PARTITION                          policy<{'arm64': '-'}>
+CONFIG_ATA_ACPI                                 policy<{'arm64': '-'}>
+CONFIG_ATA_BMDMA                                policy<{'arm64': '-'}>
+CONFIG_ATA_GENERIC                              policy<{'arm64': '-'}>
+CONFIG_ATA_OVER_ETH                             policy<{'arm64': 'n'}>
+CONFIG_ATA_SFF                                  policy<{'arm64': 'n'}>
+CONFIG_ATH10K                                   policy<{'arm64': 'n'}>
+CONFIG_ATH10K_AHB                               policy<{'arm64': '-'}>
+CONFIG_ATH10K_CE                                policy<{'arm64': '-'}>
+CONFIG_ATH10K_DEBUG                             policy<{'arm64': '-'}>
+CONFIG_ATH10K_DEBUGFS                           policy<{'arm64': '-'}>
+CONFIG_ATH10K_PCI                               policy<{'arm64': '-'}>
+CONFIG_ATH10K_SDIO                              policy<{'arm64': '-'}>
+CONFIG_ATH10K_SNOC                              policy<{'arm64': '-'}>
+CONFIG_ATH10K_SPECTRAL                          policy<{'arm64': '-'}>
+CONFIG_ATH10K_TRACING                           policy<{'arm64': '-'}>
+CONFIG_ATH10K_USB                               policy<{'arm64': '-'}>
+CONFIG_ATH5K                                    policy<{'arm64': 'n'}>
+CONFIG_ATH5K_DEBUG                              policy<{'arm64': '-'}>
+CONFIG_ATH5K_PCI                                policy<{'arm64': 'n'}>
+CONFIG_ATH5K_TRACER                             policy<{'arm64': '-'}>
+CONFIG_ATH6KL                                   policy<{'arm64': 'n'}>
+CONFIG_ATH6KL_DEBUG                             policy<{'arm64': '-'}>
+CONFIG_ATH6KL_SDIO                              policy<{'arm64': '-'}>
+CONFIG_ATH6KL_TRACING                           policy<{'arm64': '-'}>
+CONFIG_ATH6KL_USB                               policy<{'arm64': '-'}>
+CONFIG_ATH9K                                    policy<{'arm64': 'n'}>
+CONFIG_ATH9K_AHB                                policy<{'arm64': '-'}>
+CONFIG_ATH9K_BTCOEX_SUPPORT                     policy<{'arm64': '-'}>
+CONFIG_ATH9K_CHANNEL_CONTEXT                    policy<{'arm64': '-'}>
+CONFIG_ATH9K_COMMON                             policy<{'arm64': '-'}>
+CONFIG_ATH9K_COMMON_DEBUG                       policy<{'arm64': '-'}>
+CONFIG_ATH9K_COMMON_SPECTRAL                    policy<{'arm64': '-'}>
+CONFIG_ATH9K_DEBUGFS                            policy<{'arm64': '-'}>
+CONFIG_ATH9K_DYNACK                             policy<{'arm64': '-'}>
+CONFIG_ATH9K_HTC                                policy<{'arm64': 'n'}>
+CONFIG_ATH9K_HTC_DEBUGFS                        policy<{'arm64': '-'}>
+CONFIG_ATH9K_HW                                 policy<{'arm64': '-'}>
+CONFIG_ATH9K_HWRNG                              policy<{'arm64': '-'}>
+CONFIG_ATH9K_PCI                                policy<{'arm64': '-'}>
+CONFIG_ATH9K_PCI_NO_EEPROM                      policy<{'arm64': '-'}>
+CONFIG_ATH9K_PCOEM                              policy<{'arm64': '-'}>
+CONFIG_ATH9K_RFKILL                             policy<{'arm64': '-'}>
+CONFIG_ATH9K_STATION_STATISTICS                 policy<{'arm64': '-'}>
+CONFIG_ATH9K_WOW                                policy<{'arm64': '-'}>
+CONFIG_ATH_COMMON                               policy<{'arm64': '-'}>
+CONFIG_ATH_REG_DYNAMIC_USER_REG_HINTS           policy<{'arm64': 'n'}>
+CONFIG_ATL1                                     policy<{'arm64': 'n'}>
+CONFIG_ATL1C                                    policy<{'arm64': 'n'}>
+CONFIG_ATL1E                                    policy<{'arm64': 'n'}>
+CONFIG_ATL2                                     policy<{'arm64': 'n'}>
+CONFIG_ATLAS_PH_SENSOR                          policy<{'arm64': 'n'}>
+CONFIG_ATM                                      policy<{'arm64': 'n'}>
+CONFIG_ATMEL                                    policy<{'arm64': 'n'}>
+CONFIG_ATM_BR2684                               policy<{'arm64': '-'}>
+CONFIG_ATM_BR2684_IPFILTER                      policy<{'arm64': '-'}>
+CONFIG_ATM_CLIP                                 policy<{'arm64': '-'}>
+CONFIG_ATM_CLIP_NO_ICMP                         policy<{'arm64': '-'}>
+CONFIG_ATM_DRIVERS                              policy<{'arm64': '-'}>
+CONFIG_ATM_DUMMY                                policy<{'arm64': '-'}>
+CONFIG_ATM_ENI                                  policy<{'arm64': '-'}>
+CONFIG_ATM_ENI_DEBUG                            policy<{'arm64': '-'}>
+CONFIG_ATM_ENI_TUNE_BURST                       policy<{'arm64': '-'}>
+CONFIG_ATM_FORE200E                             policy<{'arm64': '-'}>
+CONFIG_ATM_FORE200E_DEBUG                       policy<{'arm64': '-'}>
+CONFIG_ATM_FORE200E_TX_RETRY                    policy<{'arm64': '-'}>
+CONFIG_ATM_FORE200E_USE_TASKLET                 policy<{'arm64': '-'}>
+CONFIG_ATM_HE                                   policy<{'arm64': '-'}>
+CONFIG_ATM_HE_USE_SUNI                          policy<{'arm64': '-'}>
+CONFIG_ATM_IA                                   policy<{'arm64': '-'}>
+CONFIG_ATM_IA_DEBUG                             policy<{'arm64': '-'}>
+CONFIG_ATM_IDT77252                             policy<{'arm64': '-'}>
+CONFIG_ATM_IDT77252_DEBUG                       policy<{'arm64': '-'}>
+CONFIG_ATM_IDT77252_RCV_ALL                     policy<{'arm64': '-'}>
+CONFIG_ATM_IDT77252_USE_SUNI                    policy<{'arm64': '-'}>
+CONFIG_ATM_LANAI                                policy<{'arm64': '-'}>
+CONFIG_ATM_LANE                                 policy<{'arm64': '-'}>
+CONFIG_ATM_MPOA                                 policy<{'arm64': '-'}>
+CONFIG_ATM_NICSTAR                              policy<{'arm64': '-'}>
+CONFIG_ATM_NICSTAR_USE_IDT77105                 policy<{'arm64': '-'}>
+CONFIG_ATM_NICSTAR_USE_SUNI                     policy<{'arm64': '-'}>
+CONFIG_ATM_SOLOS                                policy<{'arm64': '-'}>
+CONFIG_ATM_TCP                                  policy<{'arm64': '-'}>
+CONFIG_AUFS_BDEV_LOOP                           policy<{'arm64': '-'}>
+CONFIG_AUFS_BRANCH_MAX_1023                     policy<{'arm64': '-'}>
+CONFIG_AUFS_BRANCH_MAX_127                      policy<{'arm64': '-'}>
+CONFIG_AUFS_BRANCH_MAX_32767                    policy<{'arm64': '-'}>
+CONFIG_AUFS_BRANCH_MAX_511                      policy<{'arm64': '-'}>
+CONFIG_AUFS_BR_FUSE                             policy<{'arm64': '-'}>
+CONFIG_AUFS_BR_HFSPLUS                          policy<{'arm64': '-'}>
+CONFIG_AUFS_BR_RAMFS                            policy<{'arm64': '-'}>
+CONFIG_AUFS_DEBUG                               policy<{'arm64': '-'}>
+CONFIG_AUFS_DIRREN                              policy<{'arm64': '-'}>
+CONFIG_AUFS_FHSM                                policy<{'arm64': '-'}>
+CONFIG_AUFS_FS                                  policy<{'arm64': 'n'}>
+CONFIG_AUFS_HNOTIFY                             policy<{'arm64': '-'}>
+CONFIG_AUFS_INO_T_64                            policy<{'arm64': '-'}>
+CONFIG_AUFS_RDU                                 policy<{'arm64': '-'}>
+CONFIG_AUFS_SBILIST                             policy<{'arm64': '-'}>
+CONFIG_AUFS_SHWH                                policy<{'arm64': '-'}>
+CONFIG_AUFS_XATTR                               policy<{'arm64': '-'}>
+CONFIG_AURORA_NB8800                            policy<{'arm64': 'n'}>
+CONFIG_AUTOFS4_FS                               policy<{'arm64': 'y'}>
+CONFIG_AUTOFS_FS                                policy<{'arm64': 'y'}>
+CONFIG_AUXDISPLAY                               policy<{'arm64': 'n'}>
+CONFIG_AX25                                     policy<{'arm64': '-'}>
+CONFIG_AX25_DAMA_SLAVE                          policy<{'arm64': '-'}>
+CONFIG_AX88796B_PHY                             policy<{'arm64': 'n'}>
+CONFIG_AXIENET_HAS_MCDMA                        policy<{'arm64': 'n'}>
+CONFIG_AXI_DMAC                                 policy<{'arm64': 'n'}>
+CONFIG_AXP20X_ADC                               policy<{'arm64': '-'}>
+CONFIG_AXP20X_POWER                             policy<{'arm64': '-'}>
+CONFIG_AXP288_ADC                               policy<{'arm64': '-'}>
+CONFIG_AXP288_FUEL_GAUGE                        policy<{'arm64': '-'}>
+CONFIG_B43                                      policy<{'arm64': 'n'}>
+CONFIG_B43LEGACY                                policy<{'arm64': 'n'}>
+CONFIG_B43LEGACY_DEBUG                          policy<{'arm64': '-'}>
+CONFIG_B43LEGACY_DMA                            policy<{'arm64': '-'}>
+CONFIG_B43LEGACY_DMA_AND_PIO_MODE               policy<{'arm64': '-'}>
+CONFIG_B43LEGACY_DMA_MODE                       policy<{'arm64': '-'}>
+CONFIG_B43LEGACY_HWRNG                          policy<{'arm64': '-'}>
+CONFIG_B43LEGACY_LEDS                           policy<{'arm64': '-'}>
+CONFIG_B43LEGACY_PCICORE_AUTOSELECT             policy<{'arm64': '-'}>
+CONFIG_B43LEGACY_PCI_AUTOSELECT                 policy<{'arm64': '-'}>
+CONFIG_B43LEGACY_PIO                            policy<{'arm64': '-'}>
+CONFIG_B43LEGACY_PIO_MODE                       policy<{'arm64': '-'}>
+CONFIG_B43_BCMA                                 policy<{'arm64': '-'}>
+CONFIG_B43_BCMA_PIO                             policy<{'arm64': '-'}>
+CONFIG_B43_BUSES_BCMA                           policy<{'arm64': '-'}>
+CONFIG_B43_BUSES_BCMA_AND_SSB                   policy<{'arm64': '-'}>
+CONFIG_B43_BUSES_SSB                            policy<{'arm64': '-'}>
+CONFIG_B43_DEBUG                                policy<{'arm64': '-'}>
+CONFIG_B43_HWRNG                                policy<{'arm64': '-'}>
+CONFIG_B43_LEDS                                 policy<{'arm64': '-'}>
+CONFIG_B43_PCICORE_AUTOSELECT                   policy<{'arm64': '-'}>
+CONFIG_B43_PCI_AUTOSELECT                       policy<{'arm64': '-'}>
+CONFIG_B43_PHY_G                                policy<{'arm64': '-'}>
+CONFIG_B43_PHY_HT                               policy<{'arm64': '-'}>
+CONFIG_B43_PHY_LP                               policy<{'arm64': '-'}>
+CONFIG_B43_PHY_N                                policy<{'arm64': '-'}>
+CONFIG_B43_PIO                                  policy<{'arm64': '-'}>
+CONFIG_B43_SDIO                                 policy<{'arm64': '-'}>
+CONFIG_B43_SSB                                  policy<{'arm64': '-'}>
+CONFIG_B44                                      policy<{'arm64': 'n'}>
+CONFIG_B44_PCI                                  policy<{'arm64': '-'}>
+CONFIG_B44_PCICORE_AUTOSELECT                   policy<{'arm64': '-'}>
+CONFIG_B44_PCI_AUTOSELECT                       policy<{'arm64': '-'}>
+CONFIG_B53                                      policy<{'arm64': '-'}>
+CONFIG_B53_MDIO_DRIVER                          policy<{'arm64': '-'}>
+CONFIG_B53_MMAP_DRIVER                          policy<{'arm64': '-'}>
+CONFIG_B53_SERDES                               policy<{'arm64': '-'}>
+CONFIG_B53_SPI_DRIVER                           policy<{'arm64': '-'}>
+CONFIG_B53_SRAB_DRIVER                          policy<{'arm64': '-'}>
+CONFIG_BACKLIGHT_88PM860X                       policy<{'arm64': '-'}>
+CONFIG_BACKLIGHT_AAT2870                        policy<{'arm64': '-'}>
+CONFIG_BACKLIGHT_ADP5520                        policy<{'arm64': '-'}>
+CONFIG_BACKLIGHT_ADP8860                        policy<{'arm64': 'n'}>
+CONFIG_BACKLIGHT_ADP8870                        policy<{'arm64': 'n'}>
+CONFIG_BACKLIGHT_ARCXCNN                        policy<{'arm64': 'n'}>
+CONFIG_BACKLIGHT_AS3711                         policy<{'arm64': '-'}>
+CONFIG_BACKLIGHT_BD6107                         policy<{'arm64': 'n'}>
+CONFIG_BACKLIGHT_DA903X                         policy<{'arm64': '-'}>
+CONFIG_BACKLIGHT_DA9052                         policy<{'arm64': '-'}>
+CONFIG_BACKLIGHT_GENERIC                        policy<{'arm64': 'y'}>
+CONFIG_BACKLIGHT_GPIO                           policy<{'arm64': 'n'}>
+CONFIG_BACKLIGHT_LM3533                         policy<{'arm64': '-'}>
+CONFIG_BACKLIGHT_LM3630A                        policy<{'arm64': '-'}>
+CONFIG_BACKLIGHT_LM3639                         policy<{'arm64': 'n'}>
+CONFIG_BACKLIGHT_LP855X                         policy<{'arm64': '-'}>
+CONFIG_BACKLIGHT_LP8788                         policy<{'arm64': '-'}>
+CONFIG_BACKLIGHT_LV5207LP                       policy<{'arm64': 'n'}>
+CONFIG_BACKLIGHT_MAX8925                        policy<{'arm64': '-'}>
+CONFIG_BACKLIGHT_PANDORA                        policy<{'arm64': '-'}>
+CONFIG_BACKLIGHT_PCF50633                       policy<{'arm64': '-'}>
+CONFIG_BACKLIGHT_PM8941_WLED                    policy<{'arm64': 'n'}>
+CONFIG_BACKLIGHT_PWM                            policy<{'arm64': '-'}>
+CONFIG_BACKLIGHT_RAVE_SP                        policy<{'arm64': '-'}>
+CONFIG_BACKLIGHT_SKY81452                       policy<{'arm64': '-'}>
+CONFIG_BACKLIGHT_TPS65217                       policy<{'arm64': '-'}>
+CONFIG_BACKLIGHT_WM831X                         policy<{'arm64': '-'}>
+CONFIG_BALLOON_COMPACTION                       policy<{'arm64': '-'}>
+CONFIG_BATMAN_ADV                               policy<{'arm64': 'n'}>
+CONFIG_BATMAN_ADV_BATMAN_V                      policy<{'arm64': '-'}>
+CONFIG_BATMAN_ADV_BLA                           policy<{'arm64': '-'}>
+CONFIG_BATMAN_ADV_DAT                           policy<{'arm64': '-'}>
+CONFIG_BATMAN_ADV_DEBUG                         policy<{'arm64': '-'}>
+CONFIG_BATMAN_ADV_DEBUGFS                       policy<{'arm64': '-'}>
+CONFIG_BATMAN_ADV_MCAST                         policy<{'arm64': '-'}>
+CONFIG_BATMAN_ADV_NC                            policy<{'arm64': '-'}>
+CONFIG_BATMAN_ADV_SYSFS                         policy<{'arm64': '-'}>
+CONFIG_BATMAN_ADV_TRACING                       policy<{'arm64': '-'}>
+CONFIG_BATTERY_88PM860X                         policy<{'arm64': '-'}>
+CONFIG_BATTERY_ACT8945A                         policy<{'arm64': '-'}>
+CONFIG_BATTERY_AXP20X                           policy<{'arm64': '-'}>
+CONFIG_BATTERY_BQ27XXX                          policy<{'arm64': 'n'}>
+CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM           policy<{'arm64': '-'}>
+CONFIG_BATTERY_BQ27XXX_HDQ                      policy<{'arm64': '-'}>
+CONFIG_BATTERY_BQ27XXX_I2C                      policy<{'arm64': '-'}>
+CONFIG_BATTERY_CPCAP                            policy<{'arm64': '-'}>
+CONFIG_BATTERY_DA9030                           policy<{'arm64': '-'}>
+CONFIG_BATTERY_DA9052                           policy<{'arm64': '-'}>
+CONFIG_BATTERY_DA9150                           policy<{'arm64': '-'}>
+CONFIG_BATTERY_DS2760                           policy<{'arm64': '-'}>
+CONFIG_BATTERY_DS2780                           policy<{'arm64': 'n'}>
+CONFIG_BATTERY_DS2781                           policy<{'arm64': 'n'}>
+CONFIG_BATTERY_DS2782                           policy<{'arm64': 'n'}>
+CONFIG_BATTERY_GAUGE_LTC2941                    policy<{'arm64': 'n'}>
+CONFIG_BATTERY_LEGO_EV3                         policy<{'arm64': 'n'}>
+CONFIG_BATTERY_MAX17040                         policy<{'arm64': 'n'}>
+CONFIG_BATTERY_MAX17042                         policy<{'arm64': 'n'}>
+CONFIG_BATTERY_MAX1721X                         policy<{'arm64': '-'}>
+CONFIG_BATTERY_RT5033                           policy<{'arm64': 'n'}>
+CONFIG_BATTERY_RX51                             policy<{'arm64': '-'}>
+CONFIG_BATTERY_SBS                              policy<{'arm64': 'n'}>
+CONFIG_BATTERY_TWL4030_MADC                     policy<{'arm64': '-'}>
+CONFIG_BAYCOM_PAR                               policy<{'arm64': '-'}>
+CONFIG_BAYCOM_SER_FDX                           policy<{'arm64': '-'}>
+CONFIG_BAYCOM_SER_HDX                           policy<{'arm64': '-'}>
+CONFIG_BCACHE                                   policy<{'arm64': 'n'}>
+CONFIG_BCACHE_CLOSURES_DEBUG                    policy<{'arm64': '-'}>
+CONFIG_BCACHE_DEBUG                             policy<{'arm64': '-'}>
+CONFIG_BCH                                      policy<{'arm64': '-'}>
+CONFIG_BCM2835_MBOX                             policy<{'arm64': '-'}>
+CONFIG_BCM2835_POWER                            policy<{'arm64': '-'}>
+CONFIG_BCM2835_THERMAL                          policy<{'arm64': '-'}>
+CONFIG_BCM2835_VCHIQ                            policy<{'arm64': '-'}>
+CONFIG_BCM2835_WDT                              policy<{'arm64': '-'}>
+CONFIG_BCM7038_L1_IRQ                           policy<{'arm64': '-'}>
+CONFIG_BCM7038_WDT                              policy<{'arm64': '-'}>
+CONFIG_BCM7XXX_PHY                              policy<{'arm64': 'y'}>
+CONFIG_BCM87XX_PHY                              policy<{'arm64': 'y'}>
+CONFIG_BCMA                                     policy<{'arm64': 'n'}>
+CONFIG_BCMA_BLOCKIO                             policy<{'arm64': '-'}>
+CONFIG_BCMA_DEBUG                               policy<{'arm64': '-'}>
+CONFIG_BCMA_DRIVER_GMAC_CMN                     policy<{'arm64': '-'}>
+CONFIG_BCMA_DRIVER_GPIO                         policy<{'arm64': '-'}>
+CONFIG_BCMA_DRIVER_PCI                          policy<{'arm64': '-'}>
+CONFIG_BCMA_HOST_PCI                            policy<{'arm64': '-'}>
+CONFIG_BCMA_HOST_PCI_POSSIBLE                   policy<{'arm64': '-'}>
+CONFIG_BCMA_HOST_SOC                            policy<{'arm64': '-'}>
+CONFIG_BCMA_SFLASH                              policy<{'arm64': '-'}>
+CONFIG_BCMGENET                                 policy<{'arm64': 'n'}>
+CONFIG_BCM_FLEXRM_MBOX                          policy<{'arm64': '-'}>
+CONFIG_BCM_IPROC_ADC                            policy<{'arm64': '-'}>
+CONFIG_BCM_KONA_USB2_PHY                        policy<{'arm64': 'n'}>
+CONFIG_BCM_NET_PHYLIB                           policy<{'arm64': 'y'}>
+CONFIG_BCM_NS_THERMAL                           policy<{'arm64': '-'}>
+CONFIG_BCM_PDC_MBOX                             policy<{'arm64': '-'}>
+CONFIG_BCM_SBA_RAID                             policy<{'arm64': 'n'}>
+CONFIG_BCM_SR_THERMAL                           policy<{'arm64': '-'}>
+CONFIG_BCM_VIDEOCORE                            policy<{'arm64': '-'}>
+CONFIG_BD70528_WATCHDOG                         policy<{'arm64': '-'}>
+CONFIG_BE2ISCSI                                 policy<{'arm64': 'n'}>
+CONFIG_BE2NET                                   policy<{'arm64': 'n'}>
+CONFIG_BE2NET_BE2                               policy<{'arm64': '-'}>
+CONFIG_BE2NET_BE3                               policy<{'arm64': '-'}>
+CONFIG_BE2NET_HWMON                             policy<{'arm64': '-'}>
+CONFIG_BE2NET_LANCER                            policy<{'arm64': '-'}>
+CONFIG_BE2NET_SKYHAWK                           policy<{'arm64': '-'}>
+CONFIG_BEFS_DEBUG                               policy<{'arm64': '-'}>
+CONFIG_BEFS_FS                                  policy<{'arm64': 'n'}>
+CONFIG_BERLIN2_ADC                              policy<{'arm64': '-'}>
+CONFIG_BFQ_CGROUP_DEBUG                         policy<{'arm64': '-'}>
+CONFIG_BFQ_GROUP_IOSCHED                        policy<{'arm64': '-'}>
+CONFIG_BFS_FS                                   policy<{'arm64': 'n'}>
+CONFIG_BGMAC                                    policy<{'arm64': '-'}>
+CONFIG_BGMAC_PLATFORM                           policy<{'arm64': '-'}>
+CONFIG_BH1750                                   policy<{'arm64': 'n'}>
+CONFIG_BH1780                                   policy<{'arm64': 'n'}>
+CONFIG_BIG_KEYS                                 policy<{'arm64': 'n'}>
+CONFIG_BINFMT_MISC                              policy<{'arm64': 'n'}>
+CONFIG_BLK_CMDLINE_PARSER                       policy<{'arm64': 'n'}>
+CONFIG_BLK_DEBUG_FS_ZONED                       policy<{'arm64': '-'}>
+CONFIG_BLK_DEV_3W_XXXX_RAID                     policy<{'arm64': 'n'}>
+CONFIG_BLK_DEV_BSGLIB                           policy<{'arm64': 'n'}>
+CONFIG_BLK_DEV_CRYPTOLOOP                       policy<{'arm64': 'n'}>
+CONFIG_BLK_DEV_DRBD                             policy<{'arm64': 'n'}>
+CONFIG_BLK_DEV_INTEGRITY                        policy<{'arm64': 'n'}>
+CONFIG_BLK_DEV_IO_TRACE                         policy<{'arm64': 'n'}>
+CONFIG_BLK_DEV_MD                               policy<{'arm64': 'n'}>
+CONFIG_BLK_DEV_NBD                              policy<{'arm64': 'n'}>
+CONFIG_BLK_DEV_NULL_BLK                         policy<{'arm64': 'n'}>
+CONFIG_BLK_DEV_PCIESSD_MTIP32XX                 policy<{'arm64': 'n'}>
+CONFIG_BLK_DEV_PMEM                             policy<{'arm64': '-'}>
+CONFIG_BLK_DEV_RBD                              policy<{'arm64': 'n'}>
+CONFIG_BLK_DEV_RSXX                             policy<{'arm64': 'n'}>
+CONFIG_BLK_DEV_SKD                              policy<{'arm64': 'n'}>
+CONFIG_BLK_DEV_THROTTLING_LOW                   policy<{'arm64': '-'}>
+CONFIG_BLK_DEV_ZONED                            policy<{'arm64': 'n'}>
+CONFIG_BLK_MQ_RDMA                              policy<{'arm64': '-'}>
+CONFIG_BLK_SED_OPAL                             policy<{'arm64': 'n'}>
+CONFIG_BLK_WBT                                  policy<{'arm64': 'n'}>
+CONFIG_BLK_WBT_MQ                               policy<{'arm64': '-'}>
+CONFIG_BMA180                                   policy<{'arm64': 'n'}>
+CONFIG_BMA220                                   policy<{'arm64': 'n'}>
+CONFIG_BMC150_ACCEL                             policy<{'arm64': 'n'}>
+CONFIG_BMC150_ACCEL_I2C                         policy<{'arm64': '-'}>
+CONFIG_BMC150_ACCEL_SPI                         policy<{'arm64': '-'}>
+CONFIG_BMC150_MAGN                              policy<{'arm64': '-'}>
+CONFIG_BMC150_MAGN_I2C                          policy<{'arm64': 'n'}>
+CONFIG_BMC150_MAGN_SPI                          policy<{'arm64': 'n'}>
+CONFIG_BME680                                   policy<{'arm64': 'n'}>
+CONFIG_BME680_I2C                               policy<{'arm64': '-'}>
+CONFIG_BME680_SPI                               policy<{'arm64': '-'}>
+CONFIG_BMG160                                   policy<{'arm64': 'n'}>
+CONFIG_BMG160_I2C                               policy<{'arm64': '-'}>
+CONFIG_BMG160_SPI                               policy<{'arm64': '-'}>
+CONFIG_BMI160                                   policy<{'arm64': '-'}>
+CONFIG_BMI160_I2C                               policy<{'arm64': 'n'}>
+CONFIG_BMI160_SPI                               policy<{'arm64': 'n'}>
+CONFIG_BMP280                                   policy<{'arm64': 'n'}>
+CONFIG_BMP280_I2C                               policy<{'arm64': '-'}>
+CONFIG_BMP280_SPI                               policy<{'arm64': '-'}>
+CONFIG_BNA                                      policy<{'arm64': 'n'}>
+CONFIG_BNX2                                     policy<{'arm64': 'n'}>
+CONFIG_BNX2X                                    policy<{'arm64': 'n'}>
+CONFIG_BNX2X_SRIOV                              policy<{'arm64': '-'}>
+CONFIG_BNXT                                     policy<{'arm64': 'n'}>
+CONFIG_BNXT_DCB                                 policy<{'arm64': '-'}>
+CONFIG_BNXT_FLOWER_OFFLOAD                      policy<{'arm64': '-'}>
+CONFIG_BNXT_HWMON                               policy<{'arm64': '-'}>
+CONFIG_BNXT_SRIOV                               policy<{'arm64': '-'}>
+CONFIG_BOARD_TPCI200                            policy<{'arm64': '-'}>
+CONFIG_BONDING                                  policy<{'arm64': 'n'}>
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC                policy<{'arm64': '-'}>
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE          policy<{'arm64': '-'}>
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC               policy<{'arm64': '-'}>
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE         policy<{'arm64': '-'}>
+CONFIG_BOOT_PRINTK_DELAY                        policy<{'arm64': 'n'}>
+CONFIG_BPFILTER                                 policy<{'arm64': 'n'}>
+CONFIG_BPFILTER_UMH                             policy<{'arm64': '-'}>
+CONFIG_BPF_JIT                                  policy<{'arm64': 'n'}>
+CONFIG_BPF_JIT_ALWAYS_ON                        policy<{'arm64': '-'}>
+CONFIG_BPF_KPROBE_OVERRIDE                      policy<{'arm64': 'n'}>
+CONFIG_BPF_STREAM_PARSER                        policy<{'arm64': '-'}>
+CONFIG_BPQETHER                                 policy<{'arm64': '-'}>
+CONFIG_BRCMDBG                                  policy<{'arm64': '-'}>
+CONFIG_BRCMFMAC                                 policy<{'arm64': 'n'}>
+CONFIG_BRCMFMAC_PCIE                            policy<{'arm64': '-'}>
+CONFIG_BRCMFMAC_PROTO_BCDC                      policy<{'arm64': '-'}>
+CONFIG_BRCMFMAC_PROTO_MSGBUF                    policy<{'arm64': '-'}>
+CONFIG_BRCMFMAC_SDIO                            policy<{'arm64': '-'}>
+CONFIG_BRCMFMAC_USB                             policy<{'arm64': '-'}>
+CONFIG_BRCMSMAC                                 policy<{'arm64': 'n'}>
+CONFIG_BRCMSTB_GISB_ARB                         policy<{'arm64': 'n'}>
+CONFIG_BRCMSTB_L2_IRQ                           policy<{'arm64': '-'}>
+CONFIG_BRCMSTB_PM                               policy<{'arm64': '-'}>
+CONFIG_BRCMSTB_THERMAL                          policy<{'arm64': '-'}>
+CONFIG_BRCMUTIL                                 policy<{'arm64': '-'}>
+CONFIG_BRCM_TRACING                             policy<{'arm64': '-'}>
+CONFIG_BRIDGE                                   policy<{'arm64': 'y'}>
+CONFIG_BRIDGE_EBT_802_3                         policy<{'arm64': 'n'}>
+CONFIG_BRIDGE_EBT_AMONG                         policy<{'arm64': 'n'}>
+CONFIG_BRIDGE_EBT_ARP                           policy<{'arm64': 'n'}>
+CONFIG_BRIDGE_EBT_ARPREPLY                      policy<{'arm64': 'n'}>
+CONFIG_BRIDGE_EBT_BROUTE                        policy<{'arm64': 'n'}>
+CONFIG_BRIDGE_EBT_DNAT                          policy<{'arm64': 'n'}>
+CONFIG_BRIDGE_EBT_IP                            policy<{'arm64': 'n'}>
+CONFIG_BRIDGE_EBT_IP6                           policy<{'arm64': 'n'}>
+CONFIG_BRIDGE_EBT_LIMIT                         policy<{'arm64': 'n'}>
+CONFIG_BRIDGE_EBT_LOG                           policy<{'arm64': 'n'}>
+CONFIG_BRIDGE_EBT_MARK                          policy<{'arm64': 'n'}>
+CONFIG_BRIDGE_EBT_NFLOG                         policy<{'arm64': 'n'}>
+CONFIG_BRIDGE_EBT_PKTTYPE                       policy<{'arm64': 'n'}>
+CONFIG_BRIDGE_EBT_REDIRECT                      policy<{'arm64': 'n'}>
+CONFIG_BRIDGE_EBT_SNAT                          policy<{'arm64': 'n'}>
+CONFIG_BRIDGE_EBT_STP                           policy<{'arm64': 'n'}>
+CONFIG_BRIDGE_EBT_VLAN                          policy<{'arm64': 'n'}>
+CONFIG_BRIDGE_VLAN_FILTERING                    policy<{'arm64': 'n'}>
+CONFIG_BROADCOM_PHY                             policy<{'arm64': 'y'}>
+CONFIG_BSD_DISKLABEL                            policy<{'arm64': '-'}>
+CONFIG_BSD_PROCESS_ACCT_V3                      policy<{'arm64': 'n'}>
+CONFIG_BT                                       policy<{'arm64': 'y'}>
+CONFIG_BTREE                                    policy<{'arm64': '-'}>
+CONFIG_BTRFS_FS                                 policy<{'arm64': 'y'}>
+CONFIG_BTRFS_FS_POSIX_ACL                       policy<{'arm64': 'n'}>
+CONFIG_BTT                                      policy<{'arm64': '-'}>
+CONFIG_BT_6LOWPAN                               policy<{'arm64': '-'}>
+CONFIG_BT_ATH3K                                 policy<{'arm64': 'y'}>
+CONFIG_BT_BCM                                   policy<{'arm64': 'y'}>
+CONFIG_BT_BNEP                                  policy<{'arm64': 'y'}>
+CONFIG_BT_CMTP                                  policy<{'arm64': '-'}>
+CONFIG_BT_HCIBCM203X                            policy<{'arm64': 'y'}>
+CONFIG_BT_HCIBFUSB                              policy<{'arm64': 'y'}>
+CONFIG_BT_HCIBPA10X                             policy<{'arm64': 'y'}>
+CONFIG_BT_HCIBTSDIO                             policy<{'arm64': 'y'}>
+CONFIG_BT_HCIBTUSB                              policy<{'arm64': 'y'}>
+CONFIG_BT_HCIBTUSB_AUTOSUSPEND                  policy<{'arm64': 'n'}>
+CONFIG_BT_HCIBTUSB_MTK                          policy<{'arm64': 'n'}>
+CONFIG_BT_HCIRSI                                policy<{'arm64': '-'}>
+CONFIG_BT_HCIUART                               policy<{'arm64': 'y'}>
+CONFIG_BT_HCIUART_AG6XX                         policy<{'arm64': 'n'}>
+CONFIG_BT_HCIUART_BCM                           policy<{'arm64': 'n'}>
+CONFIG_BT_HCIUART_MRVL                          policy<{'arm64': 'n'}>
+CONFIG_BT_HCIUART_NOKIA                         policy<{'arm64': 'n'}>
+CONFIG_BT_HCIUART_RTL                           policy<{'arm64': '-'}>
+CONFIG_BT_HCIVHCI                               policy<{'arm64': 'y'}>
+CONFIG_BT_HIDP                                  policy<{'arm64': 'y'}>
+CONFIG_BT_INTEL                                 policy<{'arm64': 'y'}>
+CONFIG_BT_MRVL                                  policy<{'arm64': 'y'}>
+CONFIG_BT_MRVL_SDIO                             policy<{'arm64': 'y'}>
+CONFIG_BT_MTKSDIO                               policy<{'arm64': 'n'}>
+CONFIG_BT_MTKUART                               policy<{'arm64': 'n'}>
+CONFIG_BT_QCA                                   policy<{'arm64': 'y'}>
+CONFIG_BT_QCOMSMD                               policy<{'arm64': '-'}>
+CONFIG_BT_RFCOMM                                policy<{'arm64': 'y'}>
+CONFIG_BT_RTL                                   policy<{'arm64': 'y'}>
+CONFIG_BT_WILINK                                policy<{'arm64': 'y'}>
+CONFIG_C2PORT                                   policy<{'arm64': 'n'}>
+CONFIG_CACHEFILES                               policy<{'arm64': '-'}>
+CONFIG_CACHEFILES_DEBUG                         policy<{'arm64': '-'}>
+CONFIG_CACHEFILES_HISTOGRAM                     policy<{'arm64': '-'}>
+CONFIG_CADENCE_WATCHDOG                         policy<{'arm64': 'y'}>
+CONFIG_CAIF                                     policy<{'arm64': 'n'}>
+CONFIG_CAIF_DEBUG                               policy<{'arm64': '-'}>
+CONFIG_CAIF_HSI                                 policy<{'arm64': '-'}>
+CONFIG_CAIF_NETDEV                              policy<{'arm64': '-'}>
+CONFIG_CAIF_SPI_SLAVE                           policy<{'arm64': '-'}>
+CONFIG_CAIF_SPI_SYNC                            policy<{'arm64': '-'}>
+CONFIG_CAIF_TTY                                 policy<{'arm64': '-'}>
+CONFIG_CAIF_USB                                 policy<{'arm64': '-'}>
+CONFIG_CAIF_VIRTIO                              policy<{'arm64': '-'}>
+CONFIG_CAN                                      policy<{'arm64': 'y'}>
+CONFIG_CAN_8DEV_USB                             policy<{'arm64': 'n'}>
+CONFIG_CAN_BCM                                  policy<{'arm64': 'y'}>
+CONFIG_CAN_CC770                                policy<{'arm64': 'n'}>
+CONFIG_CAN_CC770_ISA                            policy<{'arm64': '-'}>
+CONFIG_CAN_CC770_PLATFORM                       policy<{'arm64': '-'}>
+CONFIG_CAN_C_CAN                                policy<{'arm64': 'n'}>
+CONFIG_CAN_C_CAN_PCI                            policy<{'arm64': '-'}>
+CONFIG_CAN_C_CAN_PLATFORM                       policy<{'arm64': '-'}>
+CONFIG_CAN_DEV                                  policy<{'arm64': 'y'}>
+CONFIG_CAN_EMS_PCI                              policy<{'arm64': '-'}>
+CONFIG_CAN_EMS_USB                              policy<{'arm64': 'n'}>
+CONFIG_CAN_ESD_USB2                             policy<{'arm64': 'n'}>
+CONFIG_CAN_F81601                               policy<{'arm64': '-'}>
+CONFIG_CAN_FLEXCAN                              policy<{'arm64': 'n'}>
+CONFIG_CAN_GRCAN                                policy<{'arm64': 'n'}>
+CONFIG_CAN_GS_USB                               policy<{'arm64': 'n'}>
+CONFIG_CAN_GW                                   policy<{'arm64': 'y'}>
+CONFIG_CAN_HI311X                               policy<{'arm64': 'n'}>
+CONFIG_CAN_IFI_CANFD                            policy<{'arm64': 'n'}>
+CONFIG_CAN_J1939                                policy<{'arm64': 'n'}>
+CONFIG_CAN_JANZ_ICAN3                           policy<{'arm64': '-'}>
+CONFIG_CAN_KVASER_PCI                           policy<{'arm64': '-'}>
+CONFIG_CAN_KVASER_PCIEFD                        policy<{'arm64': 'n'}>
+CONFIG_CAN_KVASER_USB                           policy<{'arm64': 'n'}>
+CONFIG_CAN_MCBA_USB                             policy<{'arm64': 'n'}>
+CONFIG_CAN_MCP251X                              policy<{'arm64': 'n'}>
+CONFIG_CAN_M_CAN                                policy<{'arm64': 'n'}>
+CONFIG_CAN_M_CAN_PLATFORM                       policy<{'arm64': '-'}>
+CONFIG_CAN_M_CAN_TCAN4X5X                       policy<{'arm64': '-'}>
+CONFIG_CAN_PEAK_PCI                             policy<{'arm64': '-'}>
+CONFIG_CAN_PEAK_PCIEC                           policy<{'arm64': '-'}>
+CONFIG_CAN_PEAK_PCIEFD                          policy<{'arm64': 'n'}>
+CONFIG_CAN_PEAK_USB                             policy<{'arm64': 'n'}>
+CONFIG_CAN_PLX_PCI                              policy<{'arm64': '-'}>
+CONFIG_CAN_RAW                                  policy<{'arm64': 'y'}>
+CONFIG_CAN_RCAR                                 policy<{'arm64': '-'}>
+CONFIG_CAN_RCAR_CANFD                           policy<{'arm64': '-'}>
+CONFIG_CAN_SJA1000                              policy<{'arm64': 'n'}>
+CONFIG_CAN_SJA1000_ISA                          policy<{'arm64': '-'}>
+CONFIG_CAN_SJA1000_PLATFORM                     policy<{'arm64': '-'}>
+CONFIG_CAN_SLCAN                                policy<{'arm64': 'n'}>
+CONFIG_CAN_SOFTING                              policy<{'arm64': 'n'}>
+CONFIG_CAN_UCAN                                 policy<{'arm64': 'n'}>
+CONFIG_CAN_VCAN                                 policy<{'arm64': 'n'}>
+CONFIG_CAN_VXCAN                                policy<{'arm64': 'n'}>
+CONFIG_CAN_XILINXCAN                            policy<{'arm64': 'y'}>
+CONFIG_CAPI_AVM                                 policy<{'arm64': '-'}>
+CONFIG_CAPI_TRACE                               policy<{'arm64': '-'}>
+CONFIG_CARDBUS                                  policy<{'arm64': '-'}>
+CONFIG_CARL9170                                 policy<{'arm64': 'n'}>
+CONFIG_CARL9170_DEBUGFS                         policy<{'arm64': '-'}>
+CONFIG_CARL9170_HWRNG                           policy<{'arm64': '-'}>
+CONFIG_CARL9170_LEDS                            policy<{'arm64': '-'}>
+CONFIG_CARL9170_WPC                             policy<{'arm64': '-'}>
+CONFIG_CARMINE_DRAM_CUSTOM                      policy<{'arm64': '-'}>
+CONFIG_CASSINI                                  policy<{'arm64': 'n'}>
+CONFIG_CAVIUM_CPT                               policy<{'arm64': '-'}>
+CONFIG_CAVIUM_ERRATUM_23144                     policy<{'arm64': '-'}>
+CONFIG_CAVIUM_PTP                               policy<{'arm64': 'n'}>
+CONFIG_CB710_CORE                               policy<{'arm64': 'n'}>
+CONFIG_CB710_DEBUG                              policy<{'arm64': '-'}>
+CONFIG_CB710_DEBUG_ASSUMPTIONS                  policy<{'arm64': '-'}>
+CONFIG_CC10001_ADC                              policy<{'arm64': 'n'}>
+CONFIG_CCS811                                   policy<{'arm64': 'n'}>
+CONFIG_CDNS_I3C_MASTER                          policy<{'arm64': '-'}>
+CONFIG_CDROM                                    policy<{'arm64': '-'}>
+CONFIG_CDROM_PKTCDVD                            policy<{'arm64': 'n'}>
+CONFIG_CDROM_PKTCDVD_BUFFERS                    policy<{'arm64': '-'}>
+CONFIG_CDROM_PKTCDVD_WCACHE                     policy<{'arm64': '-'}>
+CONFIG_CEC_CORE                                 policy<{'arm64': '-'}>
+CONFIG_CEC_NOTIFIER                             policy<{'arm64': '-'}>
+CONFIG_CEC_PIN                                  policy<{'arm64': '-'}>
+CONFIG_CEC_PIN_ERROR_INJ                        policy<{'arm64': '-'}>
+CONFIG_CEC_PLATFORM_DRIVERS                     policy<{'arm64': '-'}>
+CONFIG_CEPH_FS                                  policy<{'arm64': 'n'}>
+CONFIG_CEPH_FSCACHE                             policy<{'arm64': '-'}>
+CONFIG_CEPH_FS_POSIX_ACL                        policy<{'arm64': '-'}>
+CONFIG_CEPH_FS_SECURITY_LABEL                   policy<{'arm64': '-'}>
+CONFIG_CEPH_LIB                                 policy<{'arm64': 'n'}>
+CONFIG_CEPH_LIB_PRETTYDEBUG                     policy<{'arm64': '-'}>
+CONFIG_CEPH_LIB_USE_DNS_RESOLVER                policy<{'arm64': '-'}>
+CONFIG_CFG80211                                 policy<{'arm64': 'y'}>
+CONFIG_CFG80211_CERTIFICATION_ONUS              policy<{'arm64': 'y'}>
+CONFIG_CFG80211_DEBUGFS                         policy<{'arm64': 'n'}>
+CONFIG_CFG80211_EXTRA_REGDB_KEYDIR              policy<{'arm64': '""'}>
+CONFIG_CFG80211_REG_CELLULAR_HINTS              policy<{'arm64': 'y'}>
+CONFIG_CFG80211_REG_RELAX_NO_IR                 policy<{'arm64': 'y'}>
+CONFIG_CFG80211_WEXT_EXPORT                     policy<{'arm64': '-'}>
+CONFIG_CFS_BANDWIDTH                            policy<{'arm64': 'n'}>
+CONFIG_CGROUP_BPF                               policy<{'arm64': 'n'}>
+CONFIG_CGROUP_DEBUG                             policy<{'arm64': 'y'}>
+CONFIG_CHARGER_88PM860X                         policy<{'arm64': '-'}>
+CONFIG_CHARGER_ADP5061                          policy<{'arm64': 'n'}>
+CONFIG_CHARGER_AXP20X                           policy<{'arm64': '-'}>
+CONFIG_CHARGER_BD70528                          policy<{'arm64': '-'}>
+CONFIG_CHARGER_BQ2415X                          policy<{'arm64': 'n'}>
+CONFIG_CHARGER_BQ24190                          policy<{'arm64': 'n'}>
+CONFIG_CHARGER_BQ24257                          policy<{'arm64': 'n'}>
+CONFIG_CHARGER_BQ24735                          policy<{'arm64': 'n'}>
+CONFIG_CHARGER_BQ25890                          policy<{'arm64': 'n'}>
+CONFIG_CHARGER_CPCAP                            policy<{'arm64': '-'}>
+CONFIG_CHARGER_CROS_USBPD                       policy<{'arm64': '-'}>
+CONFIG_CHARGER_DA9150                           policy<{'arm64': '-'}>
+CONFIG_CHARGER_DETECTOR_MAX14656                policy<{'arm64': 'n'}>
+CONFIG_CHARGER_GPIO                             policy<{'arm64': 'n'}>
+CONFIG_CHARGER_ISP1704                          policy<{'arm64': 'n'}>
+CONFIG_CHARGER_LP8727                           policy<{'arm64': 'n'}>
+CONFIG_CHARGER_LP8788                           policy<{'arm64': '-'}>
+CONFIG_CHARGER_LT3651                           policy<{'arm64': 'n'}>
+CONFIG_CHARGER_MANAGER                          policy<{'arm64': 'n'}>
+CONFIG_CHARGER_MAX14577                         policy<{'arm64': '-'}>
+CONFIG_CHARGER_MAX77650                         policy<{'arm64': '-'}>
+CONFIG_CHARGER_MAX77693                         policy<{'arm64': '-'}>
+CONFIG_CHARGER_MAX8903                          policy<{'arm64': 'n'}>
+CONFIG_CHARGER_MAX8997                          policy<{'arm64': '-'}>
+CONFIG_CHARGER_MAX8998                          policy<{'arm64': '-'}>
+CONFIG_CHARGER_PCF50633                         policy<{'arm64': '-'}>
+CONFIG_CHARGER_QCOM_SMBB                        policy<{'arm64': '-'}>
+CONFIG_CHARGER_RT9455                           policy<{'arm64': 'n'}>
+CONFIG_CHARGER_SBS                              policy<{'arm64': 'n'}>
+CONFIG_CHARGER_SC2731                           policy<{'arm64': '-'}>
+CONFIG_CHARGER_SMB347                           policy<{'arm64': 'n'}>
+CONFIG_CHARGER_TPS65090                         policy<{'arm64': '-'}>
+CONFIG_CHARGER_TPS65217                         policy<{'arm64': '-'}>
+CONFIG_CHARGER_TWL4030                          policy<{'arm64': '-'}>
+CONFIG_CHARGER_UCS1002                          policy<{'arm64': 'n'}>
+CONFIG_CHARLCD                                  policy<{'arm64': '-'}>
+CONFIG_CHARLCD_BL_FLASH                         policy<{'arm64': '-'}>
+CONFIG_CHARLCD_BL_OFF                           policy<{'arm64': '-'}>
+CONFIG_CHARLCD_BL_ON                            policy<{'arm64': '-'}>
+CONFIG_CHECK_SIGNATURE                          policy<{'arm64': '-'}>
+CONFIG_CHELSIO_IPSEC_INLINE                     policy<{'arm64': '-'}>
+CONFIG_CHELSIO_LIB                              policy<{'arm64': '-'}>
+CONFIG_CHELSIO_T1                               policy<{'arm64': 'n'}>
+CONFIG_CHELSIO_T1_1G                            policy<{'arm64': '-'}>
+CONFIG_CHELSIO_T3                               policy<{'arm64': 'n'}>
+CONFIG_CHELSIO_T4                               policy<{'arm64': 'n'}>
+CONFIG_CHELSIO_T4VF                             policy<{'arm64': 'n'}>
+CONFIG_CHELSIO_T4_DCB                           policy<{'arm64': '-'}>
+CONFIG_CHELSIO_T4_FCOE                          policy<{'arm64': '-'}>
+CONFIG_CHROMEOS_TBMC                            policy<{'arm64': '-'}>
+CONFIG_CHROME_PLATFORMS                         policy<{'arm64': 'n'}>
+CONFIG_CHR_DEV_SCH                              policy<{'arm64': 'n'}>
+CONFIG_CHR_DEV_ST                               policy<{'arm64': 'n'}>
+CONFIG_CICADA_PHY                               policy<{'arm64': 'y'}>
+CONFIG_CIFS                                     policy<{'arm64': 'n'}>
+CONFIG_CIFS_ALLOW_INSECURE_LEGACY               policy<{'arm64': '-'}>
+CONFIG_CIFS_DEBUG                               policy<{'arm64': '-'}>
+CONFIG_CIFS_DEBUG2                              policy<{'arm64': '-'}>
+CONFIG_CIFS_DEBUG_DUMP_KEYS                     policy<{'arm64': '-'}>
+CONFIG_CIFS_DFS_UPCALL                          policy<{'arm64': '-'}>
+CONFIG_CIFS_FSCACHE                             policy<{'arm64': '-'}>
+CONFIG_CIFS_POSIX                               policy<{'arm64': '-'}>
+CONFIG_CIFS_SMB_DIRECT                          policy<{'arm64': '-'}>
+CONFIG_CIFS_STATS2                              policy<{'arm64': '-'}>
+CONFIG_CIFS_UPCALL                              policy<{'arm64': '-'}>
+CONFIG_CIFS_WEAK_PW_HASH                        policy<{'arm64': '-'}>
+CONFIG_CIFS_XATTR                               policy<{'arm64': '-'}>
+CONFIG_CLEANCACHE                               policy<{'arm64': 'n'}>
+CONFIG_CLKSRC_MMIO                              policy<{'arm64': '-'}>
+CONFIG_CLKSRC_VERSATILE                         policy<{'arm64': '-'}>
+CONFIG_CLK_ACTIONS                              policy<{'arm64': '-'}>
+CONFIG_CLK_BCM2835                              policy<{'arm64': '-'}>
+CONFIG_CLK_BCM_NS2                              policy<{'arm64': '-'}>
+CONFIG_CLK_BCM_SR                               policy<{'arm64': '-'}>
+CONFIG_CLK_HSDK                                 policy<{'arm64': 'n'}>
+CONFIG_CLK_IMX8MM                               policy<{'arm64': '-'}>
+CONFIG_CLK_IMX8MN                               policy<{'arm64': '-'}>
+CONFIG_CLK_IMX8MQ                               policy<{'arm64': '-'}>
+CONFIG_CLK_IMX8QXP                              policy<{'arm64': '-'}>
+CONFIG_CLK_OWL_S500                             policy<{'arm64': '-'}>
+CONFIG_CLK_OWL_S700                             policy<{'arm64': '-'}>
+CONFIG_CLK_OWL_S900                             policy<{'arm64': '-'}>
+CONFIG_CLK_QORIQ                                policy<{'arm64': 'n'}>
+CONFIG_CLK_R8A774A1                             policy<{'arm64': '-'}>
+CONFIG_CLK_R8A774C0                             policy<{'arm64': '-'}>
+CONFIG_CLK_R8A7795                              policy<{'arm64': '-'}>
+CONFIG_CLK_R8A7796                              policy<{'arm64': '-'}>
+CONFIG_CLK_R8A77965                             policy<{'arm64': '-'}>
+CONFIG_CLK_R8A77970                             policy<{'arm64': '-'}>
+CONFIG_CLK_R8A77980                             policy<{'arm64': '-'}>
+CONFIG_CLK_R8A77990                             policy<{'arm64': '-'}>
+CONFIG_CLK_R8A77995                             policy<{'arm64': '-'}>
+CONFIG_CLK_R9A06G032                            policy<{'arm64': '-'}>
+CONFIG_CLK_RASPBERRYPI                          policy<{'arm64': '-'}>
+CONFIG_CLK_RCAR_GEN3_CPG                        policy<{'arm64': '-'}>
+CONFIG_CLK_RCAR_USB2_CLOCK_SEL                  policy<{'arm64': '-'}>
+CONFIG_CLK_RENESAS                              policy<{'arm64': '-'}>
+CONFIG_CLK_RENESAS_CPG_MSSR                     policy<{'arm64': '-'}>
+CONFIG_CLK_RENESAS_DIV6                         policy<{'arm64': '-'}>
+CONFIG_CLK_SP810                                policy<{'arm64': '-'}>
+CONFIG_CLK_SUNXI                                policy<{'arm64': '-'}>
+CONFIG_CLK_SUNXI_CLOCKS                         policy<{'arm64': '-'}>
+CONFIG_CLK_SUNXI_PRCM_SUN6I                     policy<{'arm64': '-'}>
+CONFIG_CLK_SUNXI_PRCM_SUN8I                     policy<{'arm64': '-'}>
+CONFIG_CLK_SUNXI_PRCM_SUN9I                     policy<{'arm64': '-'}>
+CONFIG_CLK_TWL6040                              policy<{'arm64': '-'}>
+CONFIG_CLK_VEXPRESS_OSC                         policy<{'arm64': '-'}>
+CONFIG_CLOCK_THERMAL                            policy<{'arm64': '-'}>
+CONFIG_CLS_U32_MARK                             policy<{'arm64': '-'}>
+CONFIG_CLS_U32_PERF                             policy<{'arm64': '-'}>
+CONFIG_CM32181                                  policy<{'arm64': 'n'}>
+CONFIG_CM3232                                   policy<{'arm64': 'n'}>
+CONFIG_CM3323                                   policy<{'arm64': 'n'}>
+CONFIG_CM3605                                   policy<{'arm64': 'n'}>
+CONFIG_CM36651                                  policy<{'arm64': 'n'}>
+CONFIG_CMDLINE                                  policy<{'arm64': '""'}>
+CONFIG_CMDLINE_PARTITION                        policy<{'arm64': '-'}>
+CONFIG_CNIC                                     policy<{'arm64': 'n'}>
+CONFIG_CODA_FS                                  policy<{'arm64': 'n'}>
+CONFIG_COMEDI                                   policy<{'arm64': 'n'}>
+CONFIG_COMEDI_8254                              policy<{'arm64': '-'}>
+CONFIG_COMEDI_8255                              policy<{'arm64': '-'}>
+CONFIG_COMEDI_8255_PCI                          policy<{'arm64': '-'}>
+CONFIG_COMEDI_8255_SA                           policy<{'arm64': '-'}>
+CONFIG_COMEDI_ADDI_APCI_1032                    policy<{'arm64': '-'}>
+CONFIG_COMEDI_ADDI_APCI_1500                    policy<{'arm64': '-'}>
+CONFIG_COMEDI_ADDI_APCI_1516                    policy<{'arm64': '-'}>
+CONFIG_COMEDI_ADDI_APCI_1564                    policy<{'arm64': '-'}>
+CONFIG_COMEDI_ADDI_APCI_16XX                    policy<{'arm64': '-'}>
+CONFIG_COMEDI_ADDI_APCI_2032                    policy<{'arm64': '-'}>
+CONFIG_COMEDI_ADDI_APCI_2200                    policy<{'arm64': '-'}>
+CONFIG_COMEDI_ADDI_APCI_3120                    policy<{'arm64': '-'}>
+CONFIG_COMEDI_ADDI_APCI_3501                    policy<{'arm64': '-'}>
+CONFIG_COMEDI_ADDI_APCI_3XXX                    policy<{'arm64': '-'}>
+CONFIG_COMEDI_ADDI_WATCHDOG                     policy<{'arm64': '-'}>
+CONFIG_COMEDI_ADL_PCI6208                       policy<{'arm64': '-'}>
+CONFIG_COMEDI_ADL_PCI7X3X                       policy<{'arm64': '-'}>
+CONFIG_COMEDI_ADL_PCI8164                       policy<{'arm64': '-'}>
+CONFIG_COMEDI_ADL_PCI9111                       policy<{'arm64': '-'}>
+CONFIG_COMEDI_ADL_PCI9118                       policy<{'arm64': '-'}>
+CONFIG_COMEDI_ADQ12B                            policy<{'arm64': '-'}>
+CONFIG_COMEDI_ADV_PCI1710                       policy<{'arm64': '-'}>
+CONFIG_COMEDI_ADV_PCI1720                       policy<{'arm64': '-'}>
+CONFIG_COMEDI_ADV_PCI1723                       policy<{'arm64': '-'}>
+CONFIG_COMEDI_ADV_PCI1724                       policy<{'arm64': '-'}>
+CONFIG_COMEDI_ADV_PCI1760                       policy<{'arm64': '-'}>
+CONFIG_COMEDI_ADV_PCI_DIO                       policy<{'arm64': '-'}>
+CONFIG_COMEDI_AIO_AIO12_8                       policy<{'arm64': '-'}>
+CONFIG_COMEDI_AIO_IIRO_16                       policy<{'arm64': '-'}>
+CONFIG_COMEDI_AMPLC_DIO200                      policy<{'arm64': '-'}>
+CONFIG_COMEDI_AMPLC_DIO200_ISA                  policy<{'arm64': '-'}>
+CONFIG_COMEDI_AMPLC_DIO200_PCI                  policy<{'arm64': '-'}>
+CONFIG_COMEDI_AMPLC_PC236                       policy<{'arm64': '-'}>
+CONFIG_COMEDI_AMPLC_PC236_ISA                   policy<{'arm64': '-'}>
+CONFIG_COMEDI_AMPLC_PC236_PCI                   policy<{'arm64': '-'}>
+CONFIG_COMEDI_AMPLC_PC263_ISA                   policy<{'arm64': '-'}>
+CONFIG_COMEDI_AMPLC_PC263_PCI                   policy<{'arm64': '-'}>
+CONFIG_COMEDI_AMPLC_PCI224                      policy<{'arm64': '-'}>
+CONFIG_COMEDI_AMPLC_PCI230                      policy<{'arm64': '-'}>
+CONFIG_COMEDI_BOND                              policy<{'arm64': '-'}>
+CONFIG_COMEDI_C6XDIGIO                          policy<{'arm64': '-'}>
+CONFIG_COMEDI_CB_PCIDAS                         policy<{'arm64': '-'}>
+CONFIG_COMEDI_CB_PCIDAS64                       policy<{'arm64': '-'}>
+CONFIG_COMEDI_CB_PCIDDA                         policy<{'arm64': '-'}>
+CONFIG_COMEDI_CB_PCIMDAS                        policy<{'arm64': '-'}>
+CONFIG_COMEDI_CB_PCIMDDA                        policy<{'arm64': '-'}>
+CONFIG_COMEDI_CONTEC_PCI_DIO                    policy<{'arm64': '-'}>
+CONFIG_COMEDI_DAC02                             policy<{'arm64': '-'}>
+CONFIG_COMEDI_DAQBOARD2000                      policy<{'arm64': '-'}>
+CONFIG_COMEDI_DAS08                             policy<{'arm64': '-'}>
+CONFIG_COMEDI_DAS08_ISA                         policy<{'arm64': '-'}>
+CONFIG_COMEDI_DAS08_PCI                         policy<{'arm64': '-'}>
+CONFIG_COMEDI_DAS16                             policy<{'arm64': '-'}>
+CONFIG_COMEDI_DAS16M1                           policy<{'arm64': '-'}>
+CONFIG_COMEDI_DAS1800                           policy<{'arm64': '-'}>
+CONFIG_COMEDI_DAS6402                           policy<{'arm64': '-'}>
+CONFIG_COMEDI_DAS800                            policy<{'arm64': '-'}>
+CONFIG_COMEDI_DEBUG                             policy<{'arm64': '-'}>
+CONFIG_COMEDI_DEFAULT_BUF_MAXSIZE_KB            policy<{'arm64': '-'}>
+CONFIG_COMEDI_DEFAULT_BUF_SIZE_KB               policy<{'arm64': '-'}>
+CONFIG_COMEDI_DMM32AT                           policy<{'arm64': '-'}>
+CONFIG_COMEDI_DT2801                            policy<{'arm64': '-'}>
+CONFIG_COMEDI_DT2811                            policy<{'arm64': '-'}>
+CONFIG_COMEDI_DT2814                            policy<{'arm64': '-'}>
+CONFIG_COMEDI_DT2815                            policy<{'arm64': '-'}>
+CONFIG_COMEDI_DT2817                            policy<{'arm64': '-'}>
+CONFIG_COMEDI_DT282X                            policy<{'arm64': '-'}>
+CONFIG_COMEDI_DT3000                            policy<{'arm64': '-'}>
+CONFIG_COMEDI_DT9812                            policy<{'arm64': '-'}>
+CONFIG_COMEDI_DYNA_PCI10XX                      policy<{'arm64': '-'}>
+CONFIG_COMEDI_FL512                             policy<{'arm64': '-'}>
+CONFIG_COMEDI_GSC_HPDI                          policy<{'arm64': '-'}>
+CONFIG_COMEDI_ICP_MULTI                         policy<{'arm64': '-'}>
+CONFIG_COMEDI_II_PCI20KC                        policy<{'arm64': '-'}>
+CONFIG_COMEDI_ISA_DRIVERS                       policy<{'arm64': '-'}>
+CONFIG_COMEDI_JR3_PCI                           policy<{'arm64': '-'}>
+CONFIG_COMEDI_KCOMEDILIB                        policy<{'arm64': '-'}>
+CONFIG_COMEDI_KE_COUNTER                        policy<{'arm64': '-'}>
+CONFIG_COMEDI_ME4000                            policy<{'arm64': '-'}>
+CONFIG_COMEDI_ME_DAQ                            policy<{'arm64': '-'}>
+CONFIG_COMEDI_MF6X4                             policy<{'arm64': '-'}>
+CONFIG_COMEDI_MISC_DRIVERS                      policy<{'arm64': '-'}>
+CONFIG_COMEDI_MITE                              policy<{'arm64': '-'}>
+CONFIG_COMEDI_MPC624                            policy<{'arm64': '-'}>
+CONFIG_COMEDI_MULTIQ3                           policy<{'arm64': '-'}>
+CONFIG_COMEDI_NI_6527                           policy<{'arm64': '-'}>
+CONFIG_COMEDI_NI_65XX                           policy<{'arm64': '-'}>
+CONFIG_COMEDI_NI_660X                           policy<{'arm64': '-'}>
+CONFIG_COMEDI_NI_670X                           policy<{'arm64': '-'}>
+CONFIG_COMEDI_NI_ATMIO                          policy<{'arm64': '-'}>
+CONFIG_COMEDI_NI_ATMIO16D                       policy<{'arm64': '-'}>
+CONFIG_COMEDI_NI_AT_A2150                       policy<{'arm64': '-'}>
+CONFIG_COMEDI_NI_AT_AO                          policy<{'arm64': '-'}>
+CONFIG_COMEDI_NI_LABPC                          policy<{'arm64': '-'}>
+CONFIG_COMEDI_NI_LABPC_ISA                      policy<{'arm64': '-'}>
+CONFIG_COMEDI_NI_LABPC_PCI                      policy<{'arm64': '-'}>
+CONFIG_COMEDI_NI_PCIDIO                         policy<{'arm64': '-'}>
+CONFIG_COMEDI_NI_PCIMIO                         policy<{'arm64': '-'}>
+CONFIG_COMEDI_NI_ROUTING                        policy<{'arm64': '-'}>
+CONFIG_COMEDI_NI_TIO                            policy<{'arm64': '-'}>
+CONFIG_COMEDI_NI_TIOCMD                         policy<{'arm64': '-'}>
+CONFIG_COMEDI_NI_USB6501                        policy<{'arm64': '-'}>
+CONFIG_COMEDI_PARPORT                           policy<{'arm64': '-'}>
+CONFIG_COMEDI_PCI_DRIVERS                       policy<{'arm64': '-'}>
+CONFIG_COMEDI_PCL711                            policy<{'arm64': '-'}>
+CONFIG_COMEDI_PCL724                            policy<{'arm64': '-'}>
+CONFIG_COMEDI_PCL726                            policy<{'arm64': '-'}>
+CONFIG_COMEDI_PCL730                            policy<{'arm64': '-'}>
+CONFIG_COMEDI_PCL812                            policy<{'arm64': '-'}>
+CONFIG_COMEDI_PCL816                            policy<{'arm64': '-'}>
+CONFIG_COMEDI_PCL818                            policy<{'arm64': '-'}>
+CONFIG_COMEDI_PCM3724                           policy<{'arm64': '-'}>
+CONFIG_COMEDI_PCMAD                             policy<{'arm64': '-'}>
+CONFIG_COMEDI_PCMDA12                           policy<{'arm64': '-'}>
+CONFIG_COMEDI_PCMMIO                            policy<{'arm64': '-'}>
+CONFIG_COMEDI_PCMUIO                            policy<{'arm64': '-'}>
+CONFIG_COMEDI_RTD520                            policy<{'arm64': '-'}>
+CONFIG_COMEDI_RTI800                            policy<{'arm64': '-'}>
+CONFIG_COMEDI_RTI802                            policy<{'arm64': '-'}>
+CONFIG_COMEDI_S526                              policy<{'arm64': '-'}>
+CONFIG_COMEDI_S626                              policy<{'arm64': '-'}>
+CONFIG_COMEDI_TEST                              policy<{'arm64': '-'}>
+CONFIG_COMEDI_USBDUX                            policy<{'arm64': '-'}>
+CONFIG_COMEDI_USBDUXFAST                        policy<{'arm64': '-'}>
+CONFIG_COMEDI_USBDUXSIGMA                       policy<{'arm64': '-'}>
+CONFIG_COMEDI_USB_DRIVERS                       policy<{'arm64': '-'}>
+CONFIG_COMEDI_VMK80XX                           policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_AXG                           policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_AXG_AUDIO                     policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_BD718XX                       policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_CDCE706                       policy<{'arm64': 'n'}>
+CONFIG_COMMON_CLK_CDCE925                       policy<{'arm64': 'n'}>
+CONFIG_COMMON_CLK_CS2000_CP                     policy<{'arm64': 'n'}>
+CONFIG_COMMON_CLK_FIXED_MMIO                    policy<{'arm64': 'n'}>
+CONFIG_COMMON_CLK_G12A                          policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_GXBB                          policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_HI3516CV300                   policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_HI3519                        policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_HI3660                        policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_HI3670                        policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_HI3798CV200                   policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_HI6220                        policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_HI655X                        policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_IDT8T49N24X                   policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_IPROC                         policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_LOCHNAGAR                     policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MAX77686                      policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MAX9485                       policy<{'arm64': 'n'}>
+CONFIG_COMMON_CLK_MEDIATEK                      policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MESON_AO_CLKC                 policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MESON_CPU_DYNDIV              policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MESON_DUALDIV                 policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MESON_EE_CLKC                 policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MESON_MPLL                    policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MESON_PHASE                   policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MESON_PLL                     policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MESON_REGMAP                  policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MESON_SCLK_DIV                policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MESON_VID_PLL_DIV             policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT2712                        policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT2712_BDPSYS                 policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT2712_IMGSYS                 policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT2712_JPGDECSYS              policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT2712_MFGCFG                 policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT2712_MMSYS                  policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT2712_VDECSYS                policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT2712_VENCSYS                policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT6779                        policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT6779_AUDSYS                 policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT6779_CAMSYS                 policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT6779_IMGSYS                 policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT6779_IPESYS                 policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT6779_MFGCFG                 policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT6779_MMSYS                  policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT6779_VDECSYS                policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT6779_VENCSYS                policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT6797                        policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT6797_IMGSYS                 policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT6797_MMSYS                  policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT6797_VDECSYS                policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT6797_VENCSYS                policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT7622                        policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT7622_AUDSYS                 policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT7622_ETHSYS                 policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT7622_HIFSYS                 policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT8173                        policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT8183                        policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT8183_AUDIOSYS               policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT8183_CAMSYS                 policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT8183_IMGSYS                 policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT8183_IPU_ADL                policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT8183_IPU_CONN               policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT8183_IPU_CORE0              policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT8183_IPU_CORE1              policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT8183_MFGCFG                 policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT8183_MMSYS                  policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT8183_VDECSYS                policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT8183_VENCSYS                policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT8516                        policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_MT8516_AUDSYS                 policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_PALMAS                        policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_PWM                           policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_QCOM                          policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_RK808                         policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_S2MPS11                       policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_SCMI                          policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_SCPI                          policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_SI514                         policy<{'arm64': 'n'}>
+CONFIG_COMMON_CLK_SI5324                        policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_SI5341                        policy<{'arm64': 'n'}>
+CONFIG_COMMON_CLK_SI5351                        policy<{'arm64': 'n'}>
+CONFIG_COMMON_CLK_SI544                         policy<{'arm64': 'n'}>
+CONFIG_COMMON_CLK_SI570                         policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_VC5                           policy<{'arm64': 'n'}>
+CONFIG_COMMON_CLK_VERSATILE                     policy<{'arm64': 'n'}>
+CONFIG_COMMON_CLK_WM831X                        policy<{'arm64': '-'}>
+CONFIG_COMMON_CLK_XGENE                         policy<{'arm64': 'n'}>
+CONFIG_COMMON_CLK_XLNX_CLKWZRD                  policy<{'arm64': 'y'}>
+CONFIG_COMMON_CLK_XLNX_CLKWZRD_V                policy<{'arm64': 'n'}>
+CONFIG_COMMON_RESET_HI3660                      policy<{'arm64': '-'}>
+CONFIG_COMMON_RESET_HI6220                      policy<{'arm64': '-'}>
+CONFIG_CONSOLE_POLL                             policy<{'arm64': '-'}>
+CONFIG_CORDIC                                   policy<{'arm64': 'n'}>
+CONFIG_CORTINA_PHY                              policy<{'arm64': 'n'}>
+CONFIG_COUNTER                                  policy<{'arm64': 'n'}>
+CONFIG_CPCAP_ADC                                policy<{'arm64': '-'}>
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE           policy<{'arm64': 'y'}>
+CONFIG_CPU_FREQ_GOV_ATTR_SET                    policy<{'arm64': '-'}>
+CONFIG_CPU_FREQ_GOV_COMMON                      policy<{'arm64': '-'}>
+CONFIG_CPU_FREQ_GOV_SCHEDUTIL                   policy<{'arm64': 'n'}>
+CONFIG_CPU_IDLE_GOV_LADDER                      policy<{'arm64': 'n'}>
+CONFIG_CPU_IDLE_GOV_TEO                         policy<{'arm64': 'n'}>
+CONFIG_CPU_THERMAL                              policy<{'arm64': '-'}>
+CONFIG_CRAMFS                                   policy<{'arm64': 'y'}>
+CONFIG_CRAMFS_MTD                               policy<{'arm64': 'n'}>
+CONFIG_CRC4                                     policy<{'arm64': 'n'}>
+CONFIG_CRC64                                    policy<{'arm64': 'n'}>
+CONFIG_CRC7                                     policy<{'arm64': 'y'}>
+CONFIG_CRC8                                     policy<{'arm64': 'n'}>
+CONFIG_CRC_ITU_T                                policy<{'arm64': 'n'}>
+CONFIG_CRC_T10DIF                               policy<{'arm64': 'n'}>
+CONFIG_CROS_EC                                  policy<{'arm64': '-'}>
+CONFIG_CROS_EC_CHARDEV                          policy<{'arm64': '-'}>
+CONFIG_CROS_EC_DEBUGFS                          policy<{'arm64': '-'}>
+CONFIG_CROS_EC_I2C                              policy<{'arm64': '-'}>
+CONFIG_CROS_EC_LIGHTBAR                         policy<{'arm64': '-'}>
+CONFIG_CROS_EC_PROTO                            policy<{'arm64': '-'}>
+CONFIG_CROS_EC_RPMSG                            policy<{'arm64': '-'}>
+CONFIG_CROS_EC_SPI                              policy<{'arm64': '-'}>
+CONFIG_CROS_EC_SYSFS                            policy<{'arm64': '-'}>
+CONFIG_CROS_EC_VBC                              policy<{'arm64': '-'}>
+CONFIG_CROS_KBD_LED_BACKLIGHT                   policy<{'arm64': '-'}>
+CONFIG_CROS_USBPD_LOGGER                        policy<{'arm64': '-'}>
+CONFIG_CRYPTO_842                               policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_ADIANTUM                          policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_AEGIS128                          policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_AEGIS128_SIMD                     policy<{'arm64': '-'}>
+CONFIG_CRYPTO_AES_ARM64                         policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_AES_ARM64_BS                      policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_AES_ARM64_CE                      policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_AES_ARM64_CE_BLK                  policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_AES_ARM64_CE_CCM                  policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_AES_ARM64_NEON_BLK                policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_AES_TI                            policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_ANSI_CPRNG                        policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_ANUBIS                            policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_ARC4                              policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_AUTHENC                           policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_BLOWFISH                          policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_BLOWFISH_COMMON                   policy<{'arm64': '-'}>
+CONFIG_CRYPTO_CAMELLIA                          policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_CAST5                             policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_CAST6                             policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_CAST_COMMON                       policy<{'arm64': '-'}>
+CONFIG_CRYPTO_CCM                               policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_CFB                               policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_CHACHA20                          policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_CHACHA20POLY1305                  policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_CHACHA20_NEON                     policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_CMAC                              policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_CRC32                             policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_CRCT10DIF_ARM64_CE                policy<{'arm64': '-'}>
+CONFIG_CRYPTO_CRYPTD                            policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_CTS                               policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_DES                               policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_DEV_ATMEL_ECC                     policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_DEV_ATMEL_I2C                     policy<{'arm64': '-'}>
+CONFIG_CRYPTO_DEV_ATMEL_SHA204A                 policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_DEV_BCM_SPU                       policy<{'arm64': '-'}>
+CONFIG_CRYPTO_DEV_CAVIUM_ZIP                    policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_DEV_CCP                           policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_DEV_CCP_CRYPTO                    policy<{'arm64': '-'}>
+CONFIG_CRYPTO_DEV_CCP_DD                        policy<{'arm64': '-'}>
+CONFIG_CRYPTO_DEV_CCP_DEBUGFS                   policy<{'arm64': '-'}>
+CONFIG_CRYPTO_DEV_CCREE                         policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_DEV_CHELSIO                       policy<{'arm64': '-'}>
+CONFIG_CRYPTO_DEV_CHELSIO_TLS                   policy<{'arm64': '-'}>
+CONFIG_CRYPTO_DEV_CPT                           policy<{'arm64': '-'}>
+CONFIG_CRYPTO_DEV_FSL_CAAM                      policy<{'arm64': '-'}>
+CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API            policy<{'arm64': '-'}>
+CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API_DESC       policy<{'arm64': '-'}>
+CONFIG_CRYPTO_DEV_FSL_CAAM_COMMON               policy<{'arm64': '-'}>
+CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API           policy<{'arm64': '-'}>
+CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_DESC      policy<{'arm64': '-'}>
+CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI        policy<{'arm64': '-'}>
+CONFIG_CRYPTO_DEV_FSL_CAAM_DEBUG                policy<{'arm64': '-'}>
+CONFIG_CRYPTO_DEV_FSL_CAAM_INTC                 policy<{'arm64': '-'}>
+CONFIG_CRYPTO_DEV_FSL_CAAM_INTC_COUNT_THLD      policy<{'arm64': '-'}>
+CONFIG_CRYPTO_DEV_FSL_CAAM_INTC_TIME_THLD       policy<{'arm64': '-'}>
+CONFIG_CRYPTO_DEV_FSL_CAAM_JR                   policy<{'arm64': '-'}>
+CONFIG_CRYPTO_DEV_FSL_CAAM_PKC_API              policy<{'arm64': '-'}>
+CONFIG_CRYPTO_DEV_FSL_CAAM_RINGSIZE             policy<{'arm64': '-'}>
+CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API              policy<{'arm64': '-'}>
+CONFIG_CRYPTO_DEV_FSL_DPAA2_CAAM                policy<{'arm64': '-'}>
+CONFIG_CRYPTO_DEV_HISI_HPRE                     policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_DEV_HISI_QM                       policy<{'arm64': '-'}>
+CONFIG_CRYPTO_DEV_HISI_SEC                      policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_DEV_HISI_SEC2                     policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_DEV_HISI_ZIP                      policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_DEV_MARVELL_CESA                  policy<{'arm64': '-'}>
+CONFIG_CRYPTO_DEV_MXS_DCP                       policy<{'arm64': '-'}>
+CONFIG_CRYPTO_DEV_NITROX                        policy<{'arm64': '-'}>
+CONFIG_CRYPTO_DEV_NITROX_CNN55XX                policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_DEV_QCE                           policy<{'arm64': '-'}>
+CONFIG_CRYPTO_DEV_QCOM_RNG                      policy<{'arm64': '-'}>
+CONFIG_CRYPTO_DEV_ROCKCHIP                      policy<{'arm64': '-'}>
+CONFIG_CRYPTO_DEV_SAFEXCEL                      policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_DEV_SAHARA                        policy<{'arm64': '-'}>
+CONFIG_CRYPTO_DEV_SP_CCP                        policy<{'arm64': '-'}>
+CONFIG_CRYPTO_DEV_XILINX_RSA                    policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_DEV_ZYNQMP_AES                    policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_DEV_ZYNQMP_SHA3                   policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_DH                                policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_DRBG_CTR                          policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_DRBG_HASH                         policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_ECC                               policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_ECDH                              policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_ECHAINIV                          policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_ECRDSA                            policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_ESSIV                             policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_FCRYPT                            policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_FIPS                              policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_GHASH_ARM64_CE                    policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_KEYWRAP                           policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_KHAZAD                            policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_LIB_ARC4                          policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_LIB_DES                           policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_LRW                               policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_LZ4                               policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_LZ4HC                             policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_LZO                               policy<{'arm64': 'm'}>
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS             policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_MANAGER_EXTRA_TESTS               policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_MD4                               policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_MICHAEL_MIC                       policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_NHPOLY1305                        policy<{'arm64': '-'}>
+CONFIG_CRYPTO_NHPOLY1305_NEON                   policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_OFB                               policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_PCBC                              policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_PCRYPT                            policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_POLY1305                          policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_RMD128                            policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_RMD160                            policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_RMD256                            policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_RMD320                            policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_SALSA20                           policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_SEED                              policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_SERPENT                           policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_SHA1_ARM64_CE                     policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_SHA256_ARM64                      policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_SHA2_ARM64_CE                     policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_SHA3                              policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_SHA3_ARM64                        policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_SHA512_ARM64                      policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_SHA512_ARM64_CE                   policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_SIMD                              policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_SM3                               policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_SM3_ARM64_CE                      policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_SM4                               policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_SM4_ARM64_CE                      policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_STATS                             policy<{'arm64': '-'}>
+CONFIG_CRYPTO_STREEBOG                          policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_TEA                               policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_TEST                              policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_TGR192                            policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_TWOFISH                           policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_TWOFISH_COMMON                    policy<{'arm64': '-'}>
+CONFIG_CRYPTO_USER                              policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_USER_API                          policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_USER_API_AEAD                     policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_USER_API_HASH                     policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_USER_API_RNG                      policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_USER_API_SKCIPHER                 policy<{'arm64': 'y'}>
+CONFIG_CRYPTO_VMAC                              policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_WP512                             policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_XCBC                              policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_XTS                               policy<{'arm64': 'n'}>
+CONFIG_CRYPTO_XXHASH                            policy<{'arm64': 'n'}>
+CONFIG_CUSE                                     policy<{'arm64': 'n'}>
+CONFIG_CW1200                                   policy<{'arm64': 'n'}>
+CONFIG_CW1200_WLAN_SDIO                         policy<{'arm64': '-'}>
+CONFIG_CW1200_WLAN_SPI                          policy<{'arm64': '-'}>
+CONFIG_CXD2880_SPI_DRV                          policy<{'arm64': '-'}>
+CONFIG_CYCLADES                                 policy<{'arm64': '-'}>
+CONFIG_CYPRESS_FIRMWARE                         policy<{'arm64': 'n'}>
+CONFIG_CYZ_INTR                                 policy<{'arm64': '-'}>
+CONFIG_DA280                                    policy<{'arm64': 'n'}>
+CONFIG_DA311                                    policy<{'arm64': 'n'}>
+CONFIG_DA9052_WATCHDOG                          policy<{'arm64': '-'}>
+CONFIG_DA9055_WATCHDOG                          policy<{'arm64': '-'}>
+CONFIG_DA9062_THERMAL                           policy<{'arm64': '-'}>
+CONFIG_DA9062_WATCHDOG                          policy<{'arm64': '-'}>
+CONFIG_DA9063_WATCHDOG                          policy<{'arm64': '-'}>
+CONFIG_DA9150_GPADC                             policy<{'arm64': '-'}>
+CONFIG_DAVICOM_PHY                              policy<{'arm64': 'y'}>
+CONFIG_DAX                                      policy<{'arm64': 'n'}>
+CONFIG_DAX_DRIVER                               policy<{'arm64': '-'}>
+CONFIG_DCB                                      policy<{'arm64': 'n'}>
+CONFIG_DE2104X                                  policy<{'arm64': '-'}>
+CONFIG_DE2104X_DSL                              policy<{'arm64': '-'}>
+CONFIG_DEBUG_INFO_BTF                           policy<{'arm64': 'n'}>
+CONFIG_DEBUG_INFO_DWARF4                        policy<{'arm64': 'n'}>
+CONFIG_DEBUG_KERNEL_DC                          policy<{'arm64': '-'}>
+CONFIG_DEBUG_SLAB                               policy<{'arm64': 'n'}>
+CONFIG_DEFAULT_CUBIC                            policy<{'arm64': '-'}>
+CONFIG_DEFAULT_HUNG_TASK_TIMEOUT                policy<{'arm64': '-'}>
+CONFIG_DEFAULT_RENO                             policy<{'arm64': '-'}>
+CONFIG_DEFXX                                    policy<{'arm64': '-'}>
+CONFIG_DEFXX_MMIO                               policy<{'arm64': '-'}>
+CONFIG_DETECT_HUNG_TASK                         policy<{'arm64': 'n'}>
+CONFIG_DEVFREQ_EVENT_ROCKCHIP_DFI               policy<{'arm64': '-'}>
+CONFIG_DEVFREQ_GOV_PASSIVE                      policy<{'arm64': '-'}>
+CONFIG_DEVFREQ_GOV_PERFORMANCE                  policy<{'arm64': '-'}>
+CONFIG_DEVFREQ_GOV_POWERSAVE                    policy<{'arm64': '-'}>
+CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND              policy<{'arm64': '-'}>
+CONFIG_DEVFREQ_GOV_USERSPACE                    policy<{'arm64': '-'}>
+CONFIG_DEVFREQ_THERMAL                          policy<{'arm64': '-'}>
+CONFIG_DEV_APPLETALK                            policy<{'arm64': '-'}>
+CONFIG_DEV_DAX                                  policy<{'arm64': '-'}>
+CONFIG_DEV_DAX_KMEM                             policy<{'arm64': '-'}>
+CONFIG_DHT11                                    policy<{'arm64': 'n'}>
+CONFIG_DIMLIB                                   policy<{'arm64': '-'}>
+CONFIG_DL2K                                     policy<{'arm64': 'n'}>
+CONFIG_DLCI                                     policy<{'arm64': '-'}>
+CONFIG_DLCI_MAX                                 policy<{'arm64': '-'}>
+CONFIG_DLM                                      policy<{'arm64': 'n'}>
+CONFIG_DLM_DEBUG                                policy<{'arm64': '-'}>
+CONFIG_DLN2_ADC                                 policy<{'arm64': '-'}>
+CONFIG_DM9102                                   policy<{'arm64': '-'}>
+CONFIG_DMARD06                                  policy<{'arm64': 'n'}>
+CONFIG_DMARD09                                  policy<{'arm64': 'n'}>
+CONFIG_DMARD10                                  policy<{'arm64': 'n'}>
+CONFIG_DMATEST                                  policy<{'arm64': 'y'}>
+CONFIG_DMA_ACPI                                 policy<{'arm64': '-'}>
+CONFIG_DMA_BCM2835                              policy<{'arm64': '-'}>
+CONFIG_DMA_SUN6I                                policy<{'arm64': '-'}>
+CONFIG_DMA_VIRTUAL_CHANNELS                     policy<{'arm64': '-'}>
+CONFIG_DMA_VIRT_OPS                             policy<{'arm64': '-'}>
+CONFIG_DMI_SYSFS                                policy<{'arm64': 'n'}>
+CONFIG_DM_BIO_PRISON                            policy<{'arm64': '-'}>
+CONFIG_DM_BUFIO                                 policy<{'arm64': '-'}>
+CONFIG_DM_CACHE                                 policy<{'arm64': 'n'}>
+CONFIG_DM_CACHE_SMQ                             policy<{'arm64': '-'}>
+CONFIG_DM_CLONE                                 policy<{'arm64': 'n'}>
+CONFIG_DM_CRYPT                                 policy<{'arm64': 'n'}>
+CONFIG_DM_DEBUG_BLOCK_MANAGER_LOCKING           policy<{'arm64': '-'}>
+CONFIG_DM_DELAY                                 policy<{'arm64': 'n'}>
+CONFIG_DM_ERA                                   policy<{'arm64': 'n'}>
+CONFIG_DM_FLAKEY                                policy<{'arm64': 'n'}>
+CONFIG_DM_INIT                                  policy<{'arm64': '-'}>
+CONFIG_DM_INTEGRITY                             policy<{'arm64': 'n'}>
+CONFIG_DM_LOG_USERSPACE                         policy<{'arm64': '-'}>
+CONFIG_DM_LOG_WRITES                            policy<{'arm64': 'n'}>
+CONFIG_DM_MIRROR                                policy<{'arm64': 'n'}>
+CONFIG_DM_MULTIPATH_QL                          policy<{'arm64': 'n'}>
+CONFIG_DM_MULTIPATH_ST                          policy<{'arm64': 'n'}>
+CONFIG_DM_PERSISTENT_DATA                       policy<{'arm64': '-'}>
+CONFIG_DM_RAID                                  policy<{'arm64': 'n'}>
+CONFIG_DM_SNAPSHOT                              policy<{'arm64': 'n'}>
+CONFIG_DM_SWITCH                                policy<{'arm64': 'n'}>
+CONFIG_DM_THIN_PROVISIONING                     policy<{'arm64': 'n'}>
+CONFIG_DM_UEVENT                                policy<{'arm64': 'n'}>
+CONFIG_DM_UNSTRIPED                             policy<{'arm64': 'n'}>
+CONFIG_DM_VERITY                                policy<{'arm64': 'n'}>
+CONFIG_DM_VERITY_FEC                            policy<{'arm64': '-'}>
+CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG            policy<{'arm64': '-'}>
+CONFIG_DM_WRITECACHE                            policy<{'arm64': 'n'}>
+CONFIG_DM_ZERO                                  policy<{'arm64': 'n'}>
+CONFIG_DM_ZONED                                 policy<{'arm64': '-'}>
+CONFIG_DNET                                     policy<{'arm64': 'n'}>
+CONFIG_DP83640_PHY                              policy<{'arm64': '-'}>
+CONFIG_DP83822_PHY                              policy<{'arm64': 'n'}>
+CONFIG_DP83848_PHY                              policy<{'arm64': 'y'}>
+CONFIG_DP83867_PHY                              policy<{'arm64': 'y'}>
+CONFIG_DP83TC811_PHY                            policy<{'arm64': 'n'}>
+CONFIG_DPAA2_CONSOLE                            policy<{'arm64': '-'}>
+CONFIG_DPAA_ERRATUM_A050385                     policy<{'arm64': '-'}>
+CONFIG_DPM_WATCHDOG                             policy<{'arm64': '-'}>
+CONFIG_DPOT_DAC                                 policy<{'arm64': 'n'}>
+CONFIG_DPS310                                   policy<{'arm64': 'n'}>
+CONFIG_DRAGONRISE_FF                            policy<{'arm64': '-'}>
+CONFIG_DRBD_FAULT_INJECTION                     policy<{'arm64': '-'}>
+CONFIG_DRM                                      policy<{'arm64': 'y'}>
+CONFIG_DRM_AMDGPU                               policy<{'arm64': 'n'}>
+CONFIG_DRM_AMDGPU_GART_DEBUGFS                  policy<{'arm64': '-'}>
+CONFIG_DRM_AMDGPU_SI                            policy<{'arm64': '-'}>
+CONFIG_DRM_AMDGPU_USERPTR                       policy<{'arm64': '-'}>
+CONFIG_DRM_AMD_ACP                              policy<{'arm64': '-'}>
+CONFIG_DRM_AMD_DC                               policy<{'arm64': '-'}>
+CONFIG_DRM_ANALOGIX_ANX78XX                     policy<{'arm64': 'n'}>
+CONFIG_DRM_ANALOGIX_DP                          policy<{'arm64': '-'}>
+CONFIG_DRM_ARCPGU                               policy<{'arm64': 'n'}>
+CONFIG_DRM_AST                                  policy<{'arm64': 'n'}>
+CONFIG_DRM_CDNS_DSI                             policy<{'arm64': 'n'}>
+CONFIG_DRM_CIRRUS_QEMU                          policy<{'arm64': 'n'}>
+CONFIG_DRM_DEBUG_MM                             policy<{'arm64': 'n'}>
+CONFIG_DRM_DP_AUX_CHARDEV                       policy<{'arm64': 'n'}>
+CONFIG_DRM_DP_CEC                               policy<{'arm64': 'n'}>
+CONFIG_DRM_DUMB_VGA_DAC                         policy<{'arm64': 'n'}>
+CONFIG_DRM_DW_HDMI                              policy<{'arm64': '-'}>
+CONFIG_DRM_DW_HDMI_AHB_AUDIO                    policy<{'arm64': '-'}>
+CONFIG_DRM_DW_HDMI_CEC                          policy<{'arm64': '-'}>
+CONFIG_DRM_DW_HDMI_I2S_AUDIO                    policy<{'arm64': '-'}>
+CONFIG_DRM_DW_MIPI_DSI                          policy<{'arm64': '-'}>
+CONFIG_DRM_ETNAVIV                              policy<{'arm64': 'n'}>
+CONFIG_DRM_ETNAVIV_THERMAL                      policy<{'arm64': '-'}>
+CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM                 policy<{'arm64': 'y'}>
+CONFIG_DRM_GEM_SHMEM_HELPER                     policy<{'arm64': '-'}>
+CONFIG_DRM_GM12U320                             policy<{'arm64': 'n'}>
+CONFIG_DRM_HDLCD                                policy<{'arm64': 'n'}>
+CONFIG_DRM_HDLCD_SHOW_UNDERRUN                  policy<{'arm64': '-'}>
+CONFIG_DRM_HISI_KIRIN                           policy<{'arm64': 'n'}>
+CONFIG_DRM_I2C_ADV7511                          policy<{'arm64': 'n'}>
+CONFIG_DRM_I2C_ADV7511_AUDIO                    policy<{'arm64': '-'}>
+CONFIG_DRM_I2C_ADV7511_CEC                      policy<{'arm64': '-'}>
+CONFIG_DRM_I2C_ADV7511_LEGACY                   policy<{'arm64': 'n'}>
+CONFIG_DRM_I2C_ADV7533                          policy<{'arm64': '-'}>
+CONFIG_DRM_I2C_CH7006                           policy<{'arm64': 'n'}>
+CONFIG_DRM_I2C_NXP_TDA9950                      policy<{'arm64': 'n'}>
+CONFIG_DRM_I2C_NXP_TDA998X                      policy<{'arm64': 'n'}>
+CONFIG_DRM_I2C_SIL164                           policy<{'arm64': 'n'}>
+CONFIG_DRM_KMS_HELPER                           policy<{'arm64': 'y'}>
+CONFIG_DRM_KOMEDA                               policy<{'arm64': 'n'}>
+CONFIG_DRM_LIMA                                 policy<{'arm64': 'n'}>
+CONFIG_DRM_LOAD_EDID_FIRMWARE                   policy<{'arm64': 'n'}>
+CONFIG_DRM_LVDS_ENCODER                         policy<{'arm64': 'n'}>
+CONFIG_DRM_MALI_DISPLAY                         policy<{'arm64': 'n'}>
+CONFIG_DRM_MEDIATEK                             policy<{'arm64': '-'}>
+CONFIG_DRM_MEDIATEK_HDMI                        policy<{'arm64': '-'}>
+CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW      policy<{'arm64': 'n'}>
+CONFIG_DRM_MESON                                policy<{'arm64': '-'}>
+CONFIG_DRM_MESON_DW_HDMI                        policy<{'arm64': '-'}>
+CONFIG_DRM_MIPI_DBI                             policy<{'arm64': '-'}>
+CONFIG_DRM_MSM                                  policy<{'arm64': '-'}>
+CONFIG_DRM_MSM_DSI                              policy<{'arm64': '-'}>
+CONFIG_DRM_MSM_DSI_10NM_PHY                     policy<{'arm64': '-'}>
+CONFIG_DRM_MSM_DSI_14NM_PHY                     policy<{'arm64': '-'}>
+CONFIG_DRM_MSM_DSI_20NM_PHY                     policy<{'arm64': '-'}>
+CONFIG_DRM_MSM_DSI_28NM_8960_PHY                policy<{'arm64': '-'}>
+CONFIG_DRM_MSM_DSI_28NM_PHY                     policy<{'arm64': '-'}>
+CONFIG_DRM_MSM_DSI_PLL                          policy<{'arm64': '-'}>
+CONFIG_DRM_MSM_GPU_STATE                        policy<{'arm64': '-'}>
+CONFIG_DRM_MSM_GPU_SUDO                         policy<{'arm64': '-'}>
+CONFIG_DRM_MSM_HDMI_HDCP                        policy<{'arm64': '-'}>
+CONFIG_DRM_MSM_REGISTER_LOGGING                 policy<{'arm64': '-'}>
+CONFIG_DRM_MXS                                  policy<{'arm64': '-'}>
+CONFIG_DRM_MXSFB                                policy<{'arm64': '-'}>
+CONFIG_DRM_NOUVEAU                              policy<{'arm64': 'n'}>
+CONFIG_DRM_NOUVEAU_BACKLIGHT                    policy<{'arm64': '-'}>
+CONFIG_DRM_NXP_PTN3460                          policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_ARM_VERSATILE                  policy<{'arm64': '-'}>
+CONFIG_DRM_PANEL_FEIYANG_FY07024DI26A30D        policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_ILITEK_IL9322                  policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_ILITEK_ILI9881C                policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_INNOLUX_P079ZCA                policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_JDI_LT070ME05000               policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_KINGDISPLAY_KD097D04           policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_LG_LB035Q02                    policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_LG_LG4573                      policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_LVDS                           policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_NEC_NL8048HL11                 policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_NOVATEK_NT39016                policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_OLIMEX_LCD_OLINUXINO           policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_ORISETECH_OTM8009A             policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_OSD_OSD101T2587_53TS           policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00         policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN        policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_RAYDIUM_RM67191                policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_RAYDIUM_RM68200                policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_ROCKTECH_JH057N00900           policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_RONBO_RB070D30                 policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_SAMSUNG_LD9040                 policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_SAMSUNG_S6D16D0                policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2                policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03             policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_SAMSUNG_S6E63M0                policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0                policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_SEIKO_43WVF1G                  policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_SHARP_LQ101R1SX01              policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_SHARP_LS037V7DW01              policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_SHARP_LS043T1LE01              policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_SIMPLE                         policy<{'arm64': 'y'}>
+CONFIG_DRM_PANEL_SITRONIX_ST7701                policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_SITRONIX_ST7789V               policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_SONY_ACX565AKM                 policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_TPO_TD028TTEC1                 policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_TPO_TD043MTEA1                 policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_TPO_TPG110                     policy<{'arm64': 'n'}>
+CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA            policy<{'arm64': 'n'}>
+CONFIG_DRM_PANFROST                             policy<{'arm64': 'n'}>
+CONFIG_DRM_PARADE_PS8622                        policy<{'arm64': 'n'}>
+CONFIG_DRM_PL111                                policy<{'arm64': 'n'}>
+CONFIG_DRM_QXL                                  policy<{'arm64': 'n'}>
+CONFIG_DRM_RADEON                               policy<{'arm64': 'n'}>
+CONFIG_DRM_RADEON_USERPTR                       policy<{'arm64': '-'}>
+CONFIG_DRM_RCAR_DU                              policy<{'arm64': '-'}>
+CONFIG_DRM_RCAR_DW_HDMI                         policy<{'arm64': 'n'}>
+CONFIG_DRM_RCAR_LVDS                            policy<{'arm64': 'n'}>
+CONFIG_DRM_RCAR_VSP                             policy<{'arm64': '-'}>
+CONFIG_DRM_ROCKCHIP                             policy<{'arm64': '-'}>
+CONFIG_DRM_SCHED                                policy<{'arm64': '-'}>
+CONFIG_DRM_SII902X                              policy<{'arm64': 'n'}>
+CONFIG_DRM_SII9234                              policy<{'arm64': 'n'}>
+CONFIG_DRM_SIL_SII8620                          policy<{'arm64': 'n'}>
+CONFIG_DRM_SUN4I                                policy<{'arm64': '-'}>
+CONFIG_DRM_SUN4I_BACKEND                        policy<{'arm64': '-'}>
+CONFIG_DRM_SUN4I_HDMI                           policy<{'arm64': '-'}>
+CONFIG_DRM_SUN4I_HDMI_CEC                       policy<{'arm64': '-'}>
+CONFIG_DRM_SUN6I_DSI                            policy<{'arm64': '-'}>
+CONFIG_DRM_SUN8I_DW_HDMI                        policy<{'arm64': '-'}>
+CONFIG_DRM_SUN8I_MIXER                          policy<{'arm64': '-'}>
+CONFIG_DRM_SUN8I_TCON_TOP                       policy<{'arm64': '-'}>
+CONFIG_DRM_THINE_THC63LVD1024                   policy<{'arm64': 'n'}>
+CONFIG_DRM_TI_SN65DSI86                         policy<{'arm64': 'n'}>
+CONFIG_DRM_TI_TFP410                            policy<{'arm64': 'n'}>
+CONFIG_DRM_TOSHIBA_TC358764                     policy<{'arm64': 'n'}>
+CONFIG_DRM_TOSHIBA_TC358767                     policy<{'arm64': 'n'}>
+CONFIG_DRM_TTM                                  policy<{'arm64': '-'}>
+CONFIG_DRM_UDL                                  policy<{'arm64': 'n'}>
+CONFIG_DRM_VC4                                  policy<{'arm64': '-'}>
+CONFIG_DRM_VC4_HDMI_CEC                         policy<{'arm64': '-'}>
+CONFIG_DRM_VGEM                                 policy<{'arm64': 'n'}>
+CONFIG_DRM_VIRTIO_GPU                           policy<{'arm64': 'n'}>
+CONFIG_DRM_VKMS                                 policy<{'arm64': 'n'}>
+CONFIG_DRM_VRAM_HELPER                          policy<{'arm64': '-'}>
+CONFIG_DRM_XEN                                  policy<{'arm64': 'n'}>
+CONFIG_DRM_XEN_FRONTEND                         policy<{'arm64': '-'}>
+CONFIG_DRM_XLNX                                 policy<{'arm64': 'y'}>
+CONFIG_DRM_XLNX_BRIDGE                          policy<{'arm64': 'y'}>
+CONFIG_DRM_XLNX_BRIDGE_CSC                      policy<{'arm64': 'y'}>
+CONFIG_DRM_XLNX_BRIDGE_DEBUG_FS                 policy<{'arm64': 'y'}>
+CONFIG_DRM_XLNX_BRIDGE_SCALER                   policy<{'arm64': 'y'}>
+CONFIG_DRM_XLNX_BRIDGE_VTC                      policy<{'arm64': 'y'}>
+CONFIG_DRM_XLNX_DPTX                            policy<{'arm64': 'y'}>
+CONFIG_DRM_XLNX_DSI                             policy<{'arm64': 'y'}>
+CONFIG_DRM_XLNX_MIXER                           policy<{'arm64': 'y'}>
+CONFIG_DRM_XLNX_PL_DISP                         policy<{'arm64': 'y'}>
+CONFIG_DRM_XLNX_SDI                             policy<{'arm64': 'y'}>
+CONFIG_DRM_ZOCL                                 policy<{'arm64': 'm'}>
+CONFIG_DRM_ZYNQMP_DPSUB                         policy<{'arm64': 'y'}>
+CONFIG_DS1682                                   policy<{'arm64': 'n'}>
+CONFIG_DS1803                                   policy<{'arm64': 'n'}>
+CONFIG_DS4424                                   policy<{'arm64': 'n'}>
+CONFIG_DUMMY                                    policy<{'arm64': 'n'}>
+CONFIG_DUMMY_IRQ                                policy<{'arm64': 'n'}>
+CONFIG_DVB_A8293                                policy<{'arm64': '-'}>
+CONFIG_DVB_AF9013                               policy<{'arm64': '-'}>
+CONFIG_DVB_AF9033                               policy<{'arm64': '-'}>
+CONFIG_DVB_AS102                                policy<{'arm64': '-'}>
+CONFIG_DVB_AS102_FE                             policy<{'arm64': '-'}>
+CONFIG_DVB_ASCOT2E                              policy<{'arm64': '-'}>
+CONFIG_DVB_ATBM8830                             policy<{'arm64': '-'}>
+CONFIG_DVB_AU8522                               policy<{'arm64': '-'}>
+CONFIG_DVB_AU8522_DTV                           policy<{'arm64': '-'}>
+CONFIG_DVB_AU8522_V4L                           policy<{'arm64': '-'}>
+CONFIG_DVB_AV7110                               policy<{'arm64': '-'}>
+CONFIG_DVB_AV7110_IR                            policy<{'arm64': '-'}>
+CONFIG_DVB_AV7110_OSD                           policy<{'arm64': '-'}>
+CONFIG_DVB_B2C2_FLEXCOP                         policy<{'arm64': '-'}>
+CONFIG_DVB_B2C2_FLEXCOP_PCI                     policy<{'arm64': '-'}>
+CONFIG_DVB_B2C2_FLEXCOP_PCI_DEBUG               policy<{'arm64': '-'}>
+CONFIG_DVB_B2C2_FLEXCOP_USB                     policy<{'arm64': '-'}>
+CONFIG_DVB_B2C2_FLEXCOP_USB_DEBUG               policy<{'arm64': '-'}>
+CONFIG_DVB_BCM3510                              policy<{'arm64': '-'}>
+CONFIG_DVB_BT8XX                                policy<{'arm64': '-'}>
+CONFIG_DVB_BUDGET                               policy<{'arm64': '-'}>
+CONFIG_DVB_BUDGET_AV                            policy<{'arm64': '-'}>
+CONFIG_DVB_BUDGET_CI                            policy<{'arm64': '-'}>
+CONFIG_DVB_BUDGET_CORE                          policy<{'arm64': '-'}>
+CONFIG_DVB_BUDGET_PATCH                         policy<{'arm64': '-'}>
+CONFIG_DVB_CORE                                 policy<{'arm64': '-'}>
+CONFIG_DVB_CX22700                              policy<{'arm64': '-'}>
+CONFIG_DVB_CX22702                              policy<{'arm64': '-'}>
+CONFIG_DVB_CX24110                              policy<{'arm64': '-'}>
+CONFIG_DVB_CX24116                              policy<{'arm64': '-'}>
+CONFIG_DVB_CX24117                              policy<{'arm64': '-'}>
+CONFIG_DVB_CX24120                              policy<{'arm64': '-'}>
+CONFIG_DVB_CX24123                              policy<{'arm64': '-'}>
+CONFIG_DVB_CXD2099                              policy<{'arm64': '-'}>
+CONFIG_DVB_CXD2820R                             policy<{'arm64': '-'}>
+CONFIG_DVB_CXD2841ER                            policy<{'arm64': '-'}>
+CONFIG_DVB_CXD2880                              policy<{'arm64': '-'}>
+CONFIG_DVB_DDBRIDGE                             policy<{'arm64': '-'}>
+CONFIG_DVB_DDBRIDGE_MSIENABLE                   policy<{'arm64': '-'}>
+CONFIG_DVB_DEMUX_SECTION_LOSS_LOG               policy<{'arm64': '-'}>
+CONFIG_DVB_DIB3000MB                            policy<{'arm64': '-'}>
+CONFIG_DVB_DIB3000MC                            policy<{'arm64': '-'}>
+CONFIG_DVB_DIB7000M                             policy<{'arm64': '-'}>
+CONFIG_DVB_DIB7000P                             policy<{'arm64': '-'}>
+CONFIG_DVB_DIB8000                              policy<{'arm64': '-'}>
+CONFIG_DVB_DIB9000                              policy<{'arm64': '-'}>
+CONFIG_DVB_DM1105                               policy<{'arm64': '-'}>
+CONFIG_DVB_DRX39XYJ                             policy<{'arm64': '-'}>
+CONFIG_DVB_DRXD                                 policy<{'arm64': '-'}>
+CONFIG_DVB_DRXK                                 policy<{'arm64': '-'}>
+CONFIG_DVB_DS3000                               policy<{'arm64': '-'}>
+CONFIG_DVB_DYNAMIC_MINORS                       policy<{'arm64': '-'}>
+CONFIG_DVB_EC100                                policy<{'arm64': '-'}>
+CONFIG_DVB_FIREDTV                              policy<{'arm64': '-'}>
+CONFIG_DVB_FIREDTV_INPUT                        policy<{'arm64': '-'}>
+CONFIG_DVB_GP8PSK_FE                            policy<{'arm64': '-'}>
+CONFIG_DVB_HELENE                               policy<{'arm64': '-'}>
+CONFIG_DVB_HOPPER                               policy<{'arm64': '-'}>
+CONFIG_DVB_HORUS3A                              policy<{'arm64': '-'}>
+CONFIG_DVB_ISL6405                              policy<{'arm64': '-'}>
+CONFIG_DVB_ISL6421                              policy<{'arm64': '-'}>
+CONFIG_DVB_ISL6423                              policy<{'arm64': '-'}>
+CONFIG_DVB_IX2505V                              policy<{'arm64': '-'}>
+CONFIG_DVB_L64781                               policy<{'arm64': '-'}>
+CONFIG_DVB_LG2160                               policy<{'arm64': '-'}>
+CONFIG_DVB_LGDT3305                             policy<{'arm64': '-'}>
+CONFIG_DVB_LGDT3306A                            policy<{'arm64': '-'}>
+CONFIG_DVB_LGDT330X                             policy<{'arm64': '-'}>
+CONFIG_DVB_LGS8GL5                              policy<{'arm64': '-'}>
+CONFIG_DVB_LGS8GXX                              policy<{'arm64': '-'}>
+CONFIG_DVB_LNBH25                               policy<{'arm64': '-'}>
+CONFIG_DVB_LNBH29                               policy<{'arm64': '-'}>
+CONFIG_DVB_LNBP21                               policy<{'arm64': '-'}>
+CONFIG_DVB_LNBP22                               policy<{'arm64': '-'}>
+CONFIG_DVB_M88DS3103                            policy<{'arm64': '-'}>
+CONFIG_DVB_M88RS2000                            policy<{'arm64': '-'}>
+CONFIG_DVB_MANTIS                               policy<{'arm64': '-'}>
+CONFIG_DVB_MAX_ADAPTERS                         policy<{'arm64': '-'}>
+CONFIG_DVB_MB86A16                              policy<{'arm64': '-'}>
+CONFIG_DVB_MB86A20S                             policy<{'arm64': '-'}>
+CONFIG_DVB_MMAP                                 policy<{'arm64': '-'}>
+CONFIG_DVB_MN88443X                             policy<{'arm64': '-'}>
+CONFIG_DVB_MN88472                              policy<{'arm64': '-'}>
+CONFIG_DVB_MN88473                              policy<{'arm64': '-'}>
+CONFIG_DVB_MT312                                policy<{'arm64': '-'}>
+CONFIG_DVB_MT352                                policy<{'arm64': '-'}>
+CONFIG_DVB_MXL5XX                               policy<{'arm64': '-'}>
+CONFIG_DVB_NET                                  policy<{'arm64': '-'}>
+CONFIG_DVB_NETUP_UNIDVB                         policy<{'arm64': '-'}>
+CONFIG_DVB_NGENE                                policy<{'arm64': '-'}>
+CONFIG_DVB_NXT200X                              policy<{'arm64': '-'}>
+CONFIG_DVB_NXT6000                              policy<{'arm64': '-'}>
+CONFIG_DVB_OR51132                              policy<{'arm64': '-'}>
+CONFIG_DVB_OR51211                              policy<{'arm64': '-'}>
+CONFIG_DVB_PLATFORM_DRIVERS                     policy<{'arm64': '-'}>
+CONFIG_DVB_PLL                                  policy<{'arm64': '-'}>
+CONFIG_DVB_PLUTO2                               policy<{'arm64': '-'}>
+CONFIG_DVB_PT1                                  policy<{'arm64': '-'}>
+CONFIG_DVB_PT3                                  policy<{'arm64': '-'}>
+CONFIG_DVB_RTL2830                              policy<{'arm64': '-'}>
+CONFIG_DVB_RTL2832                              policy<{'arm64': '-'}>
+CONFIG_DVB_RTL2832_SDR                          policy<{'arm64': '-'}>
+CONFIG_DVB_S5H1409                              policy<{'arm64': '-'}>
+CONFIG_DVB_S5H1411                              policy<{'arm64': '-'}>
+CONFIG_DVB_S5H1420                              policy<{'arm64': '-'}>
+CONFIG_DVB_S5H1432                              policy<{'arm64': '-'}>
+CONFIG_DVB_S921                                 policy<{'arm64': '-'}>
+CONFIG_DVB_SI2165                               policy<{'arm64': '-'}>
+CONFIG_DVB_SI2168                               policy<{'arm64': '-'}>
+CONFIG_DVB_SI21XX                               policy<{'arm64': '-'}>
+CONFIG_DVB_SMIPCIE                              policy<{'arm64': '-'}>
+CONFIG_DVB_SP2                                  policy<{'arm64': '-'}>
+CONFIG_DVB_SP8870                               policy<{'arm64': '-'}>
+CONFIG_DVB_SP887X                               policy<{'arm64': '-'}>
+CONFIG_DVB_STB0899                              policy<{'arm64': '-'}>
+CONFIG_DVB_STB6000                              policy<{'arm64': '-'}>
+CONFIG_DVB_STB6100                              policy<{'arm64': '-'}>
+CONFIG_DVB_STV0288                              policy<{'arm64': '-'}>
+CONFIG_DVB_STV0297                              policy<{'arm64': '-'}>
+CONFIG_DVB_STV0299                              policy<{'arm64': '-'}>
+CONFIG_DVB_STV0367                              policy<{'arm64': '-'}>
+CONFIG_DVB_STV0900                              policy<{'arm64': '-'}>
+CONFIG_DVB_STV090x                              policy<{'arm64': '-'}>
+CONFIG_DVB_STV0910                              policy<{'arm64': '-'}>
+CONFIG_DVB_STV6110                              policy<{'arm64': '-'}>
+CONFIG_DVB_STV6110x                             policy<{'arm64': '-'}>
+CONFIG_DVB_STV6111                              policy<{'arm64': '-'}>
+CONFIG_DVB_TC90522                              policy<{'arm64': '-'}>
+CONFIG_DVB_TDA10021                             policy<{'arm64': '-'}>
+CONFIG_DVB_TDA10023                             policy<{'arm64': '-'}>
+CONFIG_DVB_TDA10048                             policy<{'arm64': '-'}>
+CONFIG_DVB_TDA1004X                             policy<{'arm64': '-'}>
+CONFIG_DVB_TDA10071                             policy<{'arm64': '-'}>
+CONFIG_DVB_TDA10086                             policy<{'arm64': '-'}>
+CONFIG_DVB_TDA18271C2DD                         policy<{'arm64': '-'}>
+CONFIG_DVB_TDA665x                              policy<{'arm64': '-'}>
+CONFIG_DVB_TDA8083                              policy<{'arm64': '-'}>
+CONFIG_DVB_TDA8261                              policy<{'arm64': '-'}>
+CONFIG_DVB_TDA826X                              policy<{'arm64': '-'}>
+CONFIG_DVB_TS2020                               policy<{'arm64': '-'}>
+CONFIG_DVB_TTUSB_BUDGET                         policy<{'arm64': '-'}>
+CONFIG_DVB_TTUSB_DEC                            policy<{'arm64': '-'}>
+CONFIG_DVB_TUA6100                              policy<{'arm64': '-'}>
+CONFIG_DVB_TUNER_CX24113                        policy<{'arm64': '-'}>
+CONFIG_DVB_TUNER_DIB0070                        policy<{'arm64': '-'}>
+CONFIG_DVB_TUNER_DIB0090                        policy<{'arm64': '-'}>
+CONFIG_DVB_TUNER_ITD1000                        policy<{'arm64': '-'}>
+CONFIG_DVB_ULE_DEBUG                            policy<{'arm64': '-'}>
+CONFIG_DVB_USB                                  policy<{'arm64': '-'}>
+CONFIG_DVB_USB_A800                             policy<{'arm64': '-'}>
+CONFIG_DVB_USB_AF9005                           policy<{'arm64': '-'}>
+CONFIG_DVB_USB_AF9005_REMOTE                    policy<{'arm64': '-'}>
+CONFIG_DVB_USB_AF9015                           policy<{'arm64': '-'}>
+CONFIG_DVB_USB_AF9035                           policy<{'arm64': '-'}>
+CONFIG_DVB_USB_ANYSEE                           policy<{'arm64': '-'}>
+CONFIG_DVB_USB_AU6610                           policy<{'arm64': '-'}>
+CONFIG_DVB_USB_AZ6007                           policy<{'arm64': '-'}>
+CONFIG_DVB_USB_AZ6027                           policy<{'arm64': '-'}>
+CONFIG_DVB_USB_CE6230                           policy<{'arm64': '-'}>
+CONFIG_DVB_USB_CINERGY_T2                       policy<{'arm64': '-'}>
+CONFIG_DVB_USB_CXUSB                            policy<{'arm64': '-'}>
+CONFIG_DVB_USB_CXUSB_ANALOG                     policy<{'arm64': '-'}>
+CONFIG_DVB_USB_DEBUG                            policy<{'arm64': '-'}>
+CONFIG_DVB_USB_DIB0700                          policy<{'arm64': '-'}>
+CONFIG_DVB_USB_DIB3000MC                        policy<{'arm64': '-'}>
+CONFIG_DVB_USB_DIBUSB_MB                        policy<{'arm64': '-'}>
+CONFIG_DVB_USB_DIBUSB_MB_FAULTY                 policy<{'arm64': '-'}>
+CONFIG_DVB_USB_DIBUSB_MC                        policy<{'arm64': '-'}>
+CONFIG_DVB_USB_DIGITV                           policy<{'arm64': '-'}>
+CONFIG_DVB_USB_DTT200U                          policy<{'arm64': '-'}>
+CONFIG_DVB_USB_DTV5100                          policy<{'arm64': '-'}>
+CONFIG_DVB_USB_DVBSKY                           policy<{'arm64': '-'}>
+CONFIG_DVB_USB_DW2102                           policy<{'arm64': '-'}>
+CONFIG_DVB_USB_EC168                            policy<{'arm64': '-'}>
+CONFIG_DVB_USB_GL861                            policy<{'arm64': '-'}>
+CONFIG_DVB_USB_GP8PSK                           policy<{'arm64': '-'}>
+CONFIG_DVB_USB_LME2510                          policy<{'arm64': '-'}>
+CONFIG_DVB_USB_M920X                            policy<{'arm64': '-'}>
+CONFIG_DVB_USB_MXL111SF                         policy<{'arm64': '-'}>
+CONFIG_DVB_USB_NOVA_T_USB2                      policy<{'arm64': '-'}>
+CONFIG_DVB_USB_OPERA1                           policy<{'arm64': '-'}>
+CONFIG_DVB_USB_PCTV452E                         policy<{'arm64': '-'}>
+CONFIG_DVB_USB_RTL28XXU                         policy<{'arm64': '-'}>
+CONFIG_DVB_USB_TECHNISAT_USB2                   policy<{'arm64': '-'}>
+CONFIG_DVB_USB_TTUSB2                           policy<{'arm64': '-'}>
+CONFIG_DVB_USB_UMT_010                          policy<{'arm64': '-'}>
+CONFIG_DVB_USB_V2                               policy<{'arm64': '-'}>
+CONFIG_DVB_USB_VP702X                           policy<{'arm64': '-'}>
+CONFIG_DVB_USB_VP7045                           policy<{'arm64': '-'}>
+CONFIG_DVB_USB_ZD1301                           policy<{'arm64': '-'}>
+CONFIG_DVB_VES1820                              policy<{'arm64': '-'}>
+CONFIG_DVB_VES1X93                              policy<{'arm64': '-'}>
+CONFIG_DVB_ZD1301_DEMOD                         policy<{'arm64': '-'}>
+CONFIG_DVB_ZL10036                              policy<{'arm64': '-'}>
+CONFIG_DVB_ZL10039                              policy<{'arm64': '-'}>
+CONFIG_DVB_ZL10353                              policy<{'arm64': '-'}>
+CONFIG_DWC_XLGMAC                               policy<{'arm64': 'n'}>
+CONFIG_DWC_XLGMAC_PCI                           policy<{'arm64': '-'}>
+CONFIG_DWMAC_DWC_QOS_ETH                        policy<{'arm64': '-'}>
+CONFIG_DWMAC_GENERIC                            policy<{'arm64': '-'}>
+CONFIG_DWMAC_IPQ806X                            policy<{'arm64': '-'}>
+CONFIG_DWMAC_MEDIATEK                           policy<{'arm64': '-'}>
+CONFIG_DWMAC_MESON                              policy<{'arm64': '-'}>
+CONFIG_DWMAC_QCOM_ETHQOS                        policy<{'arm64': '-'}>
+CONFIG_DWMAC_ROCKCHIP                           policy<{'arm64': '-'}>
+CONFIG_DWMAC_SOCFPGA                            policy<{'arm64': '-'}>
+CONFIG_DWMAC_SUN8I                              policy<{'arm64': '-'}>
+CONFIG_DWMAC_SUNXI                              policy<{'arm64': '-'}>
+CONFIG_DW_APB_ICTL                              policy<{'arm64': '-'}>
+CONFIG_DW_APB_TIMER                             policy<{'arm64': '-'}>
+CONFIG_DW_APB_TIMER_OF                          policy<{'arm64': '-'}>
+CONFIG_DW_AXI_DMAC                              policy<{'arm64': 'n'}>
+CONFIG_DW_DMAC                                  policy<{'arm64': 'n'}>
+CONFIG_DW_DMAC_CORE                             policy<{'arm64': '-'}>
+CONFIG_DW_DMAC_PCI                              policy<{'arm64': 'n'}>
+CONFIG_DW_EDMA                                  policy<{'arm64': 'n'}>
+CONFIG_DW_EDMA_PCIE                             policy<{'arm64': 'n'}>
+CONFIG_DW_I3C_MASTER                            policy<{'arm64': '-'}>
+CONFIG_DW_WATCHDOG                              policy<{'arm64': 'n'}>
+CONFIG_DYNAMIC_DEBUG                            policy<{'arm64': 'n'}>
+CONFIG_E100                                     policy<{'arm64': 'n'}>
+CONFIG_E1000                                    policy<{'arm64': 'n'}>
+CONFIG_E1000E                                   policy<{'arm64': 'n'}>
+CONFIG_ECHO                                     policy<{'arm64': 'n'}>
+CONFIG_ECRYPT_FS_MESSAGING                      policy<{'arm64': 'n'}>
+CONFIG_EDAC_ALTERA                              policy<{'arm64': '-'}>
+CONFIG_EDAC_ALTERA_ETHERNET                     policy<{'arm64': '-'}>
+CONFIG_EDAC_ALTERA_NAND                         policy<{'arm64': '-'}>
+CONFIG_EDAC_ALTERA_OCRAM                        policy<{'arm64': '-'}>
+CONFIG_EDAC_ALTERA_QSPI                         policy<{'arm64': '-'}>
+CONFIG_EDAC_ALTERA_SDMMC                        policy<{'arm64': '-'}>
+CONFIG_EDAC_ALTERA_SDRAM                        policy<{'arm64': '-'}>
+CONFIG_EDAC_ALTERA_USB                          policy<{'arm64': '-'}>
+CONFIG_EDAC_BLUEFIELD                           policy<{'arm64': '-'}>
+CONFIG_EDAC_GHES                                policy<{'arm64': '-'}>
+CONFIG_EDAC_LAYERSCAPE                          policy<{'arm64': '-'}>
+CONFIG_EDAC_LEGACY_SYSFS                        policy<{'arm64': 'y'}>
+CONFIG_EDAC_QCOM                                policy<{'arm64': '-'}>
+CONFIG_EDAC_SYNOPSYS                            policy<{'arm64': 'y'}>
+CONFIG_EDAC_THUNDERX                            policy<{'arm64': 'n'}>
+CONFIG_EDAC_XGENE                               policy<{'arm64': 'n'}>
+CONFIG_EDAC_XILINX_DDR                          policy<{'arm64': 'y'}>
+CONFIG_EDAC_ZYNQMP_OCM                          policy<{'arm64': 'y'}>
+CONFIG_EEPROM_93CX6                             policy<{'arm64': 'n'}>
+CONFIG_EEPROM_93XX46                            policy<{'arm64': 'n'}>
+CONFIG_EEPROM_AT24                              policy<{'arm64': 'y'}>
+CONFIG_EEPROM_AT25                              policy<{'arm64': 'y'}>
+CONFIG_EEPROM_EE1004                            policy<{'arm64': 'n'}>
+CONFIG_EEPROM_IDT_89HPESX                       policy<{'arm64': 'n'}>
+CONFIG_EEPROM_LEGACY                            policy<{'arm64': 'n'}>
+CONFIG_EEPROM_MAX6875                           policy<{'arm64': 'n'}>
+CONFIG_EFI_ARMSTUB_DTB_LOADER                   policy<{'arm64': 'y'}>
+CONFIG_EFI_BOOTLOADER_CONTROL                   policy<{'arm64': '-'}>
+CONFIG_EFI_CAPSULE_LOADER                       policy<{'arm64': 'n'}>
+CONFIG_EFI_CUSTOM_SSDT_OVERLAYS                 policy<{'arm64': '-'}>
+CONFIG_EFI_TEST                                 policy<{'arm64': 'n'}>
+CONFIG_EFI_VARS_PSTORE                          policy<{'arm64': '-'}>
+CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE          policy<{'arm64': '-'}>
+CONFIG_EFS_FS                                   policy<{'arm64': 'n'}>
+CONFIG_EINT_MTK                                 policy<{'arm64': '-'}>
+CONFIG_EMAC_ROCKCHIP                            policy<{'arm64': '-'}>
+CONFIG_EMBEDDED                                 policy<{'arm64': 'y'}>
+CONFIG_ENABLE_MUST_CHECK                        policy<{'arm64': 'y'}>
+CONFIG_ENA_ETHERNET                             policy<{'arm64': 'n'}>
+CONFIG_ENC28J60                                 policy<{'arm64': 'n'}>
+CONFIG_ENC28J60_WRITEVERIFY                     policy<{'arm64': '-'}>
+CONFIG_ENCLOSURE_SERVICES                       policy<{'arm64': 'n'}>
+CONFIG_ENCX24J600                               policy<{'arm64': 'n'}>
+CONFIG_ENIC                                     policy<{'arm64': 'n'}>
+CONFIG_ENVELOPE_DETECTOR                        policy<{'arm64': 'n'}>
+CONFIG_EPIC100                                  policy<{'arm64': 'n'}>
+CONFIG_EQUALIZER                                policy<{'arm64': 'n'}>
+CONFIG_EROFS_FS                                 policy<{'arm64': 'n'}>
+CONFIG_EROFS_FS_CLUSTER_PAGE_LIMIT              policy<{'arm64': '-'}>
+CONFIG_EROFS_FS_DEBUG                           policy<{'arm64': '-'}>
+CONFIG_EROFS_FS_POSIX_ACL                       policy<{'arm64': '-'}>
+CONFIG_EROFS_FS_SECURITY                        policy<{'arm64': '-'}>
+CONFIG_EROFS_FS_XATTR                           policy<{'arm64': '-'}>
+CONFIG_EROFS_FS_ZIP                             policy<{'arm64': '-'}>
+CONFIG_ET131X                                   policy<{'arm64': 'n'}>
+CONFIG_ETHOC                                    policy<{'arm64': 'n'}>
+CONFIG_EVM_ADD_XATTRS                           policy<{'arm64': '-'}>
+CONFIG_EVM_EXTRA_SMACK_XATTRS                   policy<{'arm64': '-'}>
+CONFIG_EXFAT_DEBUG_MSG                          policy<{'arm64': '-'}>
+CONFIG_EXFAT_DEFAULT_CODEPAGE                   policy<{'arm64': '-'}>
+CONFIG_EXFAT_DEFAULT_IOCHARSET                  policy<{'arm64': '-'}>
+CONFIG_EXFAT_DELAYED_SYNC                       policy<{'arm64': '-'}>
+CONFIG_EXFAT_DISCARD                            policy<{'arm64': '-'}>
+CONFIG_EXFAT_DONT_MOUNT_VFAT                    policy<{'arm64': '-'}>
+CONFIG_EXFAT_FS                                 policy<{'arm64': 'n'}>
+CONFIG_EXFAT_KERNEL_DEBUG                       policy<{'arm64': '-'}>
+CONFIG_EXT3_FS_POSIX_ACL                        policy<{'arm64': 'n'}>
+CONFIG_EXT3_FS_SECURITY                         policy<{'arm64': 'n'}>
+CONFIG_EXTCON_ADC_JACK                          policy<{'arm64': 'n'}>
+CONFIG_EXTCON_ARIZONA                           policy<{'arm64': '-'}>
+CONFIG_EXTCON_FSA9480                           policy<{'arm64': 'n'}>
+CONFIG_EXTCON_GPIO                              policy<{'arm64': 'n'}>
+CONFIG_EXTCON_MAX14577                          policy<{'arm64': '-'}>
+CONFIG_EXTCON_MAX3355                           policy<{'arm64': 'n'}>
+CONFIG_EXTCON_MAX77693                          policy<{'arm64': '-'}>
+CONFIG_EXTCON_MAX77843                          policy<{'arm64': '-'}>
+CONFIG_EXTCON_MAX8997                           policy<{'arm64': '-'}>
+CONFIG_EXTCON_PALMAS                            policy<{'arm64': '-'}>
+CONFIG_EXTCON_PTN5150                           policy<{'arm64': 'n'}>
+CONFIG_EXTCON_QCOM_SPMI_MISC                    policy<{'arm64': '-'}>
+CONFIG_EXTCON_RT8973A                           policy<{'arm64': 'n'}>
+CONFIG_EXTCON_SM5502                            policy<{'arm64': 'n'}>
+CONFIG_EXTCON_USBC_CROS_EC                      policy<{'arm64': '-'}>
+CONFIG_EXTCON_USB_GPIO                          policy<{'arm64': 'n'}>
+CONFIG_EZCHIP_NPS_MANAGEMENT_ENET               policy<{'arm64': 'n'}>
+CONFIG_EZX_PCAP                                 policy<{'arm64': 'n'}>
+CONFIG_F2FS_CHECK_FS                            policy<{'arm64': '-'}>
+CONFIG_F2FS_FAULT_INJECTION                     policy<{'arm64': '-'}>
+CONFIG_F2FS_FS                                  policy<{'arm64': 'n'}>
+CONFIG_F2FS_FS_POSIX_ACL                        policy<{'arm64': '-'}>
+CONFIG_F2FS_FS_SECURITY                         policy<{'arm64': '-'}>
+CONFIG_F2FS_FS_XATTR                            policy<{'arm64': '-'}>
+CONFIG_F2FS_IO_TRACE                            policy<{'arm64': '-'}>
+CONFIG_F2FS_STAT_FS                             policy<{'arm64': '-'}>
+CONFIG_FAILOVER                                 policy<{'arm64': 'n'}>
+CONFIG_FANOTIFY                                 policy<{'arm64': 'n'}>
+CONFIG_FANOTIFY_ACCESS_PERMISSIONS              policy<{'arm64': '-'}>
+CONFIG_FARSYNC                                  policy<{'arm64': '-'}>
+CONFIG_FB_3DFX                                  policy<{'arm64': 'n'}>
+CONFIG_FB_3DFX_ACCEL                            policy<{'arm64': '-'}>
+CONFIG_FB_3DFX_I2C                              policy<{'arm64': '-'}>
+CONFIG_FB_ARK                                   policy<{'arm64': 'n'}>
+CONFIG_FB_ARMCLCD                               policy<{'arm64': 'n'}>
+CONFIG_FB_ASILIANT                              policy<{'arm64': 'n'}>
+CONFIG_FB_ATY                                   policy<{'arm64': 'n'}>
+CONFIG_FB_ATY128                                policy<{'arm64': 'n'}>
+CONFIG_FB_ATY128_BACKLIGHT                      policy<{'arm64': '-'}>
+CONFIG_FB_ATY_BACKLIGHT                         policy<{'arm64': '-'}>
+CONFIG_FB_ATY_CT                                policy<{'arm64': '-'}>
+CONFIG_FB_ATY_GENERIC_LCD                       policy<{'arm64': '-'}>
+CONFIG_FB_ATY_GX                                policy<{'arm64': '-'}>
+CONFIG_FB_BACKLIGHT                             policy<{'arm64': '-'}>
+CONFIG_FB_CARMINE                               policy<{'arm64': 'n'}>
+CONFIG_FB_CARMINE_DRAM_EVAL                     policy<{'arm64': '-'}>
+CONFIG_FB_CIRRUS                                policy<{'arm64': 'n'}>
+CONFIG_FB_CYBER2000                             policy<{'arm64': 'n'}>
+CONFIG_FB_CYBER2000_DDC                         policy<{'arm64': '-'}>
+CONFIG_FB_DDC                                   policy<{'arm64': '-'}>
+CONFIG_FB_EFI                                   policy<{'arm64': 'n'}>
+CONFIG_FB_I740                                  policy<{'arm64': 'n'}>
+CONFIG_FB_IMSTT                                 policy<{'arm64': 'n'}>
+CONFIG_FB_IMX                                   policy<{'arm64': '-'}>
+CONFIG_FB_KYRO                                  policy<{'arm64': 'n'}>
+CONFIG_FB_MATROX                                policy<{'arm64': 'n'}>
+CONFIG_FB_MATROX_G                              policy<{'arm64': '-'}>
+CONFIG_FB_MATROX_I2C                            policy<{'arm64': '-'}>
+CONFIG_FB_MATROX_MAVEN                          policy<{'arm64': '-'}>
+CONFIG_FB_MATROX_MILLENIUM                      policy<{'arm64': '-'}>
+CONFIG_FB_MATROX_MYSTIQUE                       policy<{'arm64': '-'}>
+CONFIG_FB_MB862XX                               policy<{'arm64': 'n'}>
+CONFIG_FB_MB862XX_I2C                           policy<{'arm64': '-'}>
+CONFIG_FB_MB862XX_PCI_GDC                       policy<{'arm64': '-'}>
+CONFIG_FB_METRONOME                             policy<{'arm64': 'n'}>
+CONFIG_FB_MODE_HELPERS                          policy<{'arm64': 'n'}>
+CONFIG_FB_MX3                                   policy<{'arm64': '-'}>
+CONFIG_FB_NEOMAGIC                              policy<{'arm64': 'n'}>
+CONFIG_FB_NVIDIA                                policy<{'arm64': 'n'}>
+CONFIG_FB_NVIDIA_BACKLIGHT                      policy<{'arm64': '-'}>
+CONFIG_FB_NVIDIA_DEBUG                          policy<{'arm64': '-'}>
+CONFIG_FB_NVIDIA_I2C                            policy<{'arm64': '-'}>
+CONFIG_FB_OPENCORES                             policy<{'arm64': 'n'}>
+CONFIG_FB_PM2                                   policy<{'arm64': 'n'}>
+CONFIG_FB_PM2_FIFO_DISCONNECT                   policy<{'arm64': '-'}>
+CONFIG_FB_PM3                                   policy<{'arm64': 'n'}>
+CONFIG_FB_RADEON                                policy<{'arm64': 'n'}>
+CONFIG_FB_RADEON_BACKLIGHT                      policy<{'arm64': '-'}>
+CONFIG_FB_RADEON_DEBUG                          policy<{'arm64': '-'}>
+CONFIG_FB_RADEON_I2C                            policy<{'arm64': '-'}>
+CONFIG_FB_RIVA                                  policy<{'arm64': 'n'}>
+CONFIG_FB_RIVA_BACKLIGHT                        policy<{'arm64': '-'}>
+CONFIG_FB_RIVA_DEBUG                            policy<{'arm64': '-'}>
+CONFIG_FB_RIVA_I2C                              policy<{'arm64': '-'}>
+CONFIG_FB_S1D13XXX                              policy<{'arm64': 'n'}>
+CONFIG_FB_S3                                    policy<{'arm64': 'n'}>
+CONFIG_FB_S3_DDC                                policy<{'arm64': '-'}>
+CONFIG_FB_SAVAGE                                policy<{'arm64': 'n'}>
+CONFIG_FB_SAVAGE_ACCEL                          policy<{'arm64': '-'}>
+CONFIG_FB_SAVAGE_I2C                            policy<{'arm64': '-'}>
+CONFIG_FB_SH_MOBILE_LCDC                        policy<{'arm64': '-'}>
+CONFIG_FB_SIMPLE                                policy<{'arm64': 'n'}>
+CONFIG_FB_SIS                                   policy<{'arm64': 'n'}>
+CONFIG_FB_SIS_300                               policy<{'arm64': '-'}>
+CONFIG_FB_SIS_315                               policy<{'arm64': '-'}>
+CONFIG_FB_SM501                                 policy<{'arm64': '-'}>
+CONFIG_FB_SM712                                 policy<{'arm64': 'n'}>
+CONFIG_FB_SM750                                 policy<{'arm64': 'n'}>
+CONFIG_FB_SMSCUFX                               policy<{'arm64': 'n'}>
+CONFIG_FB_SSD1307                               policy<{'arm64': 'n'}>
+CONFIG_FB_SVGALIB                               policy<{'arm64': '-'}>
+CONFIG_FB_SYS_COPYAREA                          policy<{'arm64': 'y'}>
+CONFIG_FB_SYS_FILLRECT                          policy<{'arm64': 'y'}>
+CONFIG_FB_SYS_FOPS                              policy<{'arm64': 'y'}>
+CONFIG_FB_SYS_IMAGEBLIT                         policy<{'arm64': 'y'}>
+CONFIG_FB_TFT                                   policy<{'arm64': 'n'}>
+CONFIG_FB_TFT_AGM1264K_FL                       policy<{'arm64': '-'}>
+CONFIG_FB_TFT_BD663474                          policy<{'arm64': '-'}>
+CONFIG_FB_TFT_HX8340BN                          policy<{'arm64': '-'}>
+CONFIG_FB_TFT_HX8347D                           policy<{'arm64': '-'}>
+CONFIG_FB_TFT_HX8353D                           policy<{'arm64': '-'}>
+CONFIG_FB_TFT_HX8357D                           policy<{'arm64': '-'}>
+CONFIG_FB_TFT_ILI9163                           policy<{'arm64': '-'}>
+CONFIG_FB_TFT_ILI9320                           policy<{'arm64': '-'}>
+CONFIG_FB_TFT_ILI9325                           policy<{'arm64': '-'}>
+CONFIG_FB_TFT_ILI9340                           policy<{'arm64': '-'}>
+CONFIG_FB_TFT_ILI9341                           policy<{'arm64': '-'}>
+CONFIG_FB_TFT_ILI9481                           policy<{'arm64': '-'}>
+CONFIG_FB_TFT_ILI9486                           policy<{'arm64': '-'}>
+CONFIG_FB_TFT_PCD8544                           policy<{'arm64': '-'}>
+CONFIG_FB_TFT_RA8875                            policy<{'arm64': '-'}>
+CONFIG_FB_TFT_S6D02A1                           policy<{'arm64': '-'}>
+CONFIG_FB_TFT_S6D1121                           policy<{'arm64': '-'}>
+CONFIG_FB_TFT_SH1106                            policy<{'arm64': '-'}>
+CONFIG_FB_TFT_SSD1289                           policy<{'arm64': '-'}>
+CONFIG_FB_TFT_SSD1305                           policy<{'arm64': '-'}>
+CONFIG_FB_TFT_SSD1306                           policy<{'arm64': '-'}>
+CONFIG_FB_TFT_SSD1331                           policy<{'arm64': '-'}>
+CONFIG_FB_TFT_SSD1351                           policy<{'arm64': '-'}>
+CONFIG_FB_TFT_ST7735R                           policy<{'arm64': '-'}>
+CONFIG_FB_TFT_ST7789V                           policy<{'arm64': '-'}>
+CONFIG_FB_TFT_TINYLCD                           policy<{'arm64': '-'}>
+CONFIG_FB_TFT_TLS8204                           policy<{'arm64': '-'}>
+CONFIG_FB_TFT_UC1611                            policy<{'arm64': '-'}>
+CONFIG_FB_TFT_UC1701                            policy<{'arm64': '-'}>
+CONFIG_FB_TFT_UPD161704                         policy<{'arm64': '-'}>
+CONFIG_FB_TFT_WATTEROTT                         policy<{'arm64': '-'}>
+CONFIG_FB_TILEBLITTING                          policy<{'arm64': 'n'}>
+CONFIG_FB_TRIDENT                               policy<{'arm64': 'n'}>
+CONFIG_FB_UDL                                   policy<{'arm64': 'n'}>
+CONFIG_FB_UVESA                                 policy<{'arm64': 'n'}>
+CONFIG_FB_VOODOO1                               policy<{'arm64': 'n'}>
+CONFIG_FB_VT8623                                policy<{'arm64': 'n'}>
+CONFIG_FB_XILINX                                policy<{'arm64': 'y'}>
+CONFIG_FCOE                                     policy<{'arm64': '-'}>
+CONFIG_FDDI                                     policy<{'arm64': 'n'}>
+CONFIG_FEALNX                                   policy<{'arm64': 'n'}>
+CONFIG_FEC                                      policy<{'arm64': '-'}>
+CONFIG_FIELDBUS_DEV                             policy<{'arm64': 'n'}>
+CONFIG_FIREWIRE                                 policy<{'arm64': 'n'}>
+CONFIG_FIREWIRE_NET                             policy<{'arm64': '-'}>
+CONFIG_FIREWIRE_NOSY                            policy<{'arm64': 'n'}>
+CONFIG_FIREWIRE_OHCI                            policy<{'arm64': '-'}>
+CONFIG_FIREWIRE_SBP2                            policy<{'arm64': '-'}>
+CONFIG_FIREWIRE_SERIAL                          policy<{'arm64': '-'}>
+CONFIG_FIRMWARE_EDID                            policy<{'arm64': 'n'}>
+CONFIG_FIRMWARE_MEMMAP                          policy<{'arm64': 'n'}>
+CONFIG_FLATMEM_MANUAL                           policy<{'arm64': 'n'}>
+CONFIG_FM10K                                    policy<{'arm64': 'n'}>
+CONFIG_FONTS                                    policy<{'arm64': 'n'}>
+CONFIG_FONT_10x18                               policy<{'arm64': '-'}>
+CONFIG_FONT_6x10                                policy<{'arm64': '-'}>
+CONFIG_FONT_6x11                                policy<{'arm64': '-'}>
+CONFIG_FONT_7x14                                policy<{'arm64': '-'}>
+CONFIG_FONT_ACORN_8x8                           policy<{'arm64': '-'}>
+CONFIG_FONT_MINI_4x6                            policy<{'arm64': '-'}>
+CONFIG_FONT_PEARL_8x8                           policy<{'arm64': '-'}>
+CONFIG_FONT_SUN12x22                            policy<{'arm64': '-'}>
+CONFIG_FONT_SUN8x16                             policy<{'arm64': '-'}>
+CONFIG_FONT_TER16x32                            policy<{'arm64': '-'}>
+CONFIG_FORCEDETH                                policy<{'arm64': 'n'}>
+CONFIG_FORCE_MAX_ZONEORDER                      policy<{'arm64': '11'}>
+CONFIG_FPGA                                     policy<{'arm64': 'y'}>
+CONFIG_FPGA_BRIDGE                              policy<{'arm64': 'y'}>
+CONFIG_FPGA_DFL                                 policy<{'arm64': 'n'}>
+CONFIG_FPGA_DFL_AFU                             policy<{'arm64': '-'}>
+CONFIG_FPGA_DFL_FME                             policy<{'arm64': '-'}>
+CONFIG_FPGA_DFL_FME_BRIDGE                      policy<{'arm64': '-'}>
+CONFIG_FPGA_DFL_FME_MGR                         policy<{'arm64': '-'}>
+CONFIG_FPGA_DFL_FME_REGION                      policy<{'arm64': '-'}>
+CONFIG_FPGA_DFL_PCI                             policy<{'arm64': '-'}>
+CONFIG_FPGA_MGR_ALTERA_CVP                      policy<{'arm64': 'n'}>
+CONFIG_FPGA_MGR_ALTERA_PS_SPI                   policy<{'arm64': 'n'}>
+CONFIG_FPGA_MGR_DEBUG_FS                        policy<{'arm64': 'y'}>
+CONFIG_FPGA_MGR_ICE40_SPI                       policy<{'arm64': 'n'}>
+CONFIG_FPGA_MGR_MACHXO2_SPI                     policy<{'arm64': 'n'}>
+CONFIG_FPGA_MGR_STRATIX10_SOC                   policy<{'arm64': '-'}>
+CONFIG_FPGA_MGR_VERSAL_FPGA                     policy<{'arm64': 'y'}>
+CONFIG_FPGA_MGR_XILINX_SPI                      policy<{'arm64': 'n'}>
+CONFIG_FPGA_MGR_ZYNQMP_FPGA                     policy<{'arm64': 'y'}>
+CONFIG_FPGA_REGION                              policy<{'arm64': 'y'}>
+CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER    policy<{'arm64': 'n'}>
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION             policy<{'arm64': 'n'}>
+CONFIG_FRAME_WARN                               policy<{'arm64': '2048'}>
+CONFIG_FRONTSWAP                                policy<{'arm64': 'n'}>
+CONFIG_FSCACHE                                  policy<{'arm64': 'n'}>
+CONFIG_FSCACHE_DEBUG                            policy<{'arm64': '-'}>
+CONFIG_FSCACHE_HISTOGRAM                        policy<{'arm64': '-'}>
+CONFIG_FSCACHE_OBJECT_LIST                      policy<{'arm64': '-'}>
+CONFIG_FSCACHE_STATS                            policy<{'arm64': '-'}>
+CONFIG_FSI                                      policy<{'arm64': 'n'}>
+CONFIG_FSI_MASTER_GPIO                          policy<{'arm64': '-'}>
+CONFIG_FSI_MASTER_HUB                           policy<{'arm64': '-'}>
+CONFIG_FSI_NEW_DEV_NODE                         policy<{'arm64': '-'}>
+CONFIG_FSI_OCC                                  policy<{'arm64': '-'}>
+CONFIG_FSI_SBEFIFO                              policy<{'arm64': '-'}>
+CONFIG_FSI_SCOM                                 policy<{'arm64': '-'}>
+CONFIG_FSL_BMAN_TEST                            policy<{'arm64': '-'}>
+CONFIG_FSL_BMAN_TEST_API                        policy<{'arm64': '-'}>
+CONFIG_FSL_DPAA                                 policy<{'arm64': '-'}>
+CONFIG_FSL_DPAA2                                policy<{'arm64': '-'}>
+CONFIG_FSL_DPAA2_ETH                            policy<{'arm64': '-'}>
+CONFIG_FSL_DPAA2_ETHSW                          policy<{'arm64': '-'}>
+CONFIG_FSL_DPAA2_PTP_CLOCK                      policy<{'arm64': '-'}>
+CONFIG_FSL_DPAA_CHECKING                        policy<{'arm64': '-'}>
+CONFIG_FSL_DPAA_ETH                             policy<{'arm64': '-'}>
+CONFIG_FSL_EDMA                                 policy<{'arm64': 'n'}>
+CONFIG_FSL_ENETC                                policy<{'arm64': '-'}>
+CONFIG_FSL_ENETC_HW_TIMESTAMPING                policy<{'arm64': '-'}>
+CONFIG_FSL_ENETC_MDIO                           policy<{'arm64': '-'}>
+CONFIG_FSL_ENETC_PTP_CLOCK                      policy<{'arm64': '-'}>
+CONFIG_FSL_ENETC_VF                             policy<{'arm64': '-'}>
+CONFIG_FSL_ERRATUM_A008585                      policy<{'arm64': 'n'}>
+CONFIG_FSL_FMAN                                 policy<{'arm64': '-'}>
+CONFIG_FSL_GUTS                                 policy<{'arm64': '-'}>
+CONFIG_FSL_IFC                                  policy<{'arm64': '-'}>
+CONFIG_FSL_IMX8_DDR_PMU                         policy<{'arm64': '-'}>
+CONFIG_FSL_MC_BUS                               policy<{'arm64': '-'}>
+CONFIG_FSL_MC_DPIO                              policy<{'arm64': '-'}>
+CONFIG_FSL_PQ_MDIO                              policy<{'arm64': '-'}>
+CONFIG_FSL_QDMA                                 policy<{'arm64': 'n'}>
+CONFIG_FSL_QMAN_TEST                            policy<{'arm64': '-'}>
+CONFIG_FSL_XGMAC_MDIO                           policy<{'arm64': '-'}>
+CONFIG_FS_DAX                                   policy<{'arm64': 'n'}>
+CONFIG_FS_ENCRYPTION                            policy<{'arm64': 'n'}>
+CONFIG_FS_VERITY                                policy<{'arm64': 'n'}>
+CONFIG_FS_VERITY_BUILTIN_SIGNATURES             policy<{'arm64': '-'}>
+CONFIG_FS_VERITY_DEBUG                          policy<{'arm64': '-'}>
+CONFIG_FTL                                      policy<{'arm64': 'n'}>
+CONFIG_FTM_QUADDEC                              policy<{'arm64': '-'}>
+CONFIG_FUEL_GAUGE_SC27XX                        policy<{'arm64': '-'}>
+CONFIG_FUJITSU_ES                               policy<{'arm64': '-'}>
+CONFIG_FUNCTION_PROFILER                        policy<{'arm64': 'n'}>
+CONFIG_FUSION                                   policy<{'arm64': 'n'}>
+CONFIG_FUSION_CTL                               policy<{'arm64': '-'}>
+CONFIG_FUSION_FC                                policy<{'arm64': '-'}>
+CONFIG_FUSION_LAN                               policy<{'arm64': '-'}>
+CONFIG_FUSION_LOGGING                           policy<{'arm64': '-'}>
+CONFIG_FUSION_MAX_SGE                           policy<{'arm64': '-'}>
+CONFIG_FUSION_SAS                               policy<{'arm64': '-'}>
+CONFIG_FUSION_SPI                               policy<{'arm64': '-'}>
+CONFIG_FWTTY_MAX_CARD_PORTS                     policy<{'arm64': '-'}>
+CONFIG_FWTTY_MAX_TOTAL_PORTS                    policy<{'arm64': '-'}>
+CONFIG_FW_CFG_SYSFS                             policy<{'arm64': 'n'}>
+CONFIG_FW_CFG_SYSFS_CMDLINE                     policy<{'arm64': '-'}>
+CONFIG_FW_LOADER_COMPRESS                       policy<{'arm64': 'n'}>
+CONFIG_FW_LOADER_PAGED_BUF                      policy<{'arm64': '-'}>
+CONFIG_FW_LOADER_USER_HELPER                    policy<{'arm64': 'n'}>
+CONFIG_FXAS21002C                               policy<{'arm64': 'n'}>
+CONFIG_FXAS21002C_I2C                           policy<{'arm64': '-'}>
+CONFIG_FXAS21002C_SPI                           policy<{'arm64': '-'}>
+CONFIG_GACT_PROB                                policy<{'arm64': '-'}>
+CONFIG_GADGET_UAC1                              policy<{'arm64': '-'}>
+CONFIG_GADGET_UAC1_LEGACY                       policy<{'arm64': '-'}>
+CONFIG_GAMEPORT                                 policy<{'arm64': 'n'}>
+CONFIG_GAMEPORT_EMU10K1                         policy<{'arm64': '-'}>
+CONFIG_GAMEPORT_FM801                           policy<{'arm64': '-'}>
+CONFIG_GAMEPORT_L4                              policy<{'arm64': '-'}>
+CONFIG_GAMEPORT_NS558                           policy<{'arm64': '-'}>
+CONFIG_GARP                                     policy<{'arm64': '-'}>
+CONFIG_GDB_SCRIPTS                              policy<{'arm64': 'n'}>
+CONFIG_GEMINI_ETHERNET                          policy<{'arm64': 'n'}>
+CONFIG_GENERIC_ADC_BATTERY                      policy<{'arm64': 'n'}>
+CONFIG_GENERIC_ADC_THERMAL                      policy<{'arm64': '-'}>
+CONFIG_GENERIC_IRQ_CHIP                         policy<{'arm64': '-'}>
+CONFIG_GENERIC_PHY_MIPI_DPHY                    policy<{'arm64': '-'}>
+CONFIG_GENERIC_PINCTRL_GROUPS                   policy<{'arm64': '-'}>
+CONFIG_GENERIC_PINMUX_FUNCTIONS                 policy<{'arm64': '-'}>
+CONFIG_GENEVE                                   policy<{'arm64': 'n'}>
+CONFIG_GENWQE                                   policy<{'arm64': 'n'}>
+CONFIG_GENWQE_PLATFORM_ERROR_RECOVERY           policy<{'arm64': '-'}>
+CONFIG_GFS2_FS                                  policy<{'arm64': 'n'}>
+CONFIG_GFS2_FS_LOCKING_DLM                      policy<{'arm64': '-'}>
+CONFIG_GIANFAR                                  policy<{'arm64': '-'}>
+CONFIG_GIGASET_BASE                             policy<{'arm64': '-'}>
+CONFIG_GIGASET_CAPI                             policy<{'arm64': '-'}>
+CONFIG_GIGASET_DEBUG                            policy<{'arm64': '-'}>
+CONFIG_GIGASET_M101                             policy<{'arm64': '-'}>
+CONFIG_GIGASET_M105                             policy<{'arm64': '-'}>
+CONFIG_GNSS                                     policy<{'arm64': 'n'}>
+CONFIG_GNSS_MTK_SERIAL                          policy<{'arm64': '-'}>
+CONFIG_GNSS_SERIAL                              policy<{'arm64': '-'}>
+CONFIG_GNSS_SIRF_SERIAL                         policy<{'arm64': '-'}>
+CONFIG_GNSS_UBX_SERIAL                          policy<{'arm64': '-'}>
+CONFIG_GP2AP020A00F                             policy<{'arm64': 'n'}>
+CONFIG_GPIO_74X164                              policy<{'arm64': 'n'}>
+CONFIG_GPIO_74XX_MMIO                           policy<{'arm64': 'n'}>
+CONFIG_GPIO_ACPI                                policy<{'arm64': '-'}>
+CONFIG_GPIO_ADNP                                policy<{'arm64': 'n'}>
+CONFIG_GPIO_ADP5520                             policy<{'arm64': '-'}>
+CONFIG_GPIO_ADP5588                             policy<{'arm64': 'n'}>
+CONFIG_GPIO_ALTERA                              policy<{'arm64': 'n'}>
+CONFIG_GPIO_AMDPT                               policy<{'arm64': '-'}>
+CONFIG_GPIO_AMD_FCH                             policy<{'arm64': 'n'}>
+CONFIG_GPIO_ARIZONA                             policy<{'arm64': '-'}>
+CONFIG_GPIO_BD70528                             policy<{'arm64': '-'}>
+CONFIG_GPIO_BD9571MWV                           policy<{'arm64': '-'}>
+CONFIG_GPIO_BRCMSTB                             policy<{'arm64': '-'}>
+CONFIG_GPIO_BT8XX                               policy<{'arm64': 'n'}>
+CONFIG_GPIO_CADENCE                             policy<{'arm64': 'n'}>
+CONFIG_GPIO_DA9052                              policy<{'arm64': '-'}>
+CONFIG_GPIO_DA9055                              policy<{'arm64': '-'}>
+CONFIG_GPIO_DAVINCI                             policy<{'arm64': '-'}>
+CONFIG_GPIO_DLN2                                policy<{'arm64': '-'}>
+CONFIG_GPIO_DWAPB                               policy<{'arm64': 'n'}>
+CONFIG_GPIO_EIC_SPRD                            policy<{'arm64': '-'}>
+CONFIG_GPIO_EXAR                                policy<{'arm64': 'n'}>
+CONFIG_GPIO_FTGPIO010                           policy<{'arm64': 'n'}>
+CONFIG_GPIO_GENERIC                             policy<{'arm64': '-'}>
+CONFIG_GPIO_GENERIC_PLATFORM                    policy<{'arm64': 'n'}>
+CONFIG_GPIO_GRGPIO                              policy<{'arm64': 'n'}>
+CONFIG_GPIO_GW_PLD                              policy<{'arm64': 'n'}>
+CONFIG_GPIO_HLWD                                policy<{'arm64': 'n'}>
+CONFIG_GPIO_JANZ_TTL                            policy<{'arm64': '-'}>
+CONFIG_GPIO_KEMPLD                              policy<{'arm64': '-'}>
+CONFIG_GPIO_LP3943                              policy<{'arm64': '-'}>
+CONFIG_GPIO_LP873X                              policy<{'arm64': '-'}>
+CONFIG_GPIO_LP87565                             policy<{'arm64': '-'}>
+CONFIG_GPIO_MADERA                              policy<{'arm64': '-'}>
+CONFIG_GPIO_MAX3191X                            policy<{'arm64': 'n'}>
+CONFIG_GPIO_MAX7300                             policy<{'arm64': 'n'}>
+CONFIG_GPIO_MAX7301                             policy<{'arm64': 'n'}>
+CONFIG_GPIO_MAX730X                             policy<{'arm64': '-'}>
+CONFIG_GPIO_MAX732X                             policy<{'arm64': 'n'}>
+CONFIG_GPIO_MAX77620                            policy<{'arm64': '-'}>
+CONFIG_GPIO_MAX77650                            policy<{'arm64': '-'}>
+CONFIG_GPIO_MB86S7X                             policy<{'arm64': 'n'}>
+CONFIG_GPIO_MC33880                             policy<{'arm64': 'n'}>
+CONFIG_GPIO_MENZ127                             policy<{'arm64': '-'}>
+CONFIG_GPIO_MLXBF                               policy<{'arm64': '-'}>
+CONFIG_GPIO_MOXTET                              policy<{'arm64': '-'}>
+CONFIG_GPIO_MPC8XXX                             policy<{'arm64': '-'}>
+CONFIG_GPIO_MVEBU                               policy<{'arm64': '-'}>
+CONFIG_GPIO_MXC                                 policy<{'arm64': '-'}>
+CONFIG_GPIO_PALMAS                              policy<{'arm64': '-'}>
+CONFIG_GPIO_PCA953X                             policy<{'arm64': 'y'}>
+CONFIG_GPIO_PCA953X_IRQ                         policy<{'arm64': 'n'}>
+CONFIG_GPIO_PCF857X                             policy<{'arm64': 'n'}>
+CONFIG_GPIO_PCIE_IDIO_24                        policy<{'arm64': 'n'}>
+CONFIG_GPIO_PCI_IDIO_16                         policy<{'arm64': 'n'}>
+CONFIG_GPIO_PISOSR                              policy<{'arm64': 'n'}>
+CONFIG_GPIO_PL061                               policy<{'arm64': 'n'}>
+CONFIG_GPIO_PMIC_EIC_SPRD                       policy<{'arm64': '-'}>
+CONFIG_GPIO_RASPBERRYPI_EXP                     policy<{'arm64': '-'}>
+CONFIG_GPIO_RC5T583                             policy<{'arm64': '-'}>
+CONFIG_GPIO_RCAR                                policy<{'arm64': '-'}>
+CONFIG_GPIO_RDC321X                             policy<{'arm64': 'n'}>
+CONFIG_GPIO_SAMA5D2_PIOBU                       policy<{'arm64': '-'}>
+CONFIG_GPIO_SIOX                                policy<{'arm64': '-'}>
+CONFIG_GPIO_SPRD                                policy<{'arm64': '-'}>
+CONFIG_GPIO_STMPE                               policy<{'arm64': '-'}>
+CONFIG_GPIO_SYSCON                              policy<{'arm64': '-'}>
+CONFIG_GPIO_TC3589X                             policy<{'arm64': '-'}>
+CONFIG_GPIO_THUNDERX                            policy<{'arm64': '-'}>
+CONFIG_GPIO_TPIC2810                            policy<{'arm64': 'n'}>
+CONFIG_GPIO_TPS65086                            policy<{'arm64': 'y'}>
+CONFIG_GPIO_TPS65218                            policy<{'arm64': '-'}>
+CONFIG_GPIO_TPS6586X                            policy<{'arm64': '-'}>
+CONFIG_GPIO_TPS65910                            policy<{'arm64': '-'}>
+CONFIG_GPIO_TPS65912                            policy<{'arm64': '-'}>
+CONFIG_GPIO_TPS68470                            policy<{'arm64': '-'}>
+CONFIG_GPIO_TQMX86                              policy<{'arm64': '-'}>
+CONFIG_GPIO_TWL6040                             policy<{'arm64': '-'}>
+CONFIG_GPIO_UCB1400                             policy<{'arm64': '-'}>
+CONFIG_GPIO_VIPERBOARD                          policy<{'arm64': '-'}>
+CONFIG_GPIO_WATCHDOG                            policy<{'arm64': 'n'}>
+CONFIG_GPIO_WM831X                              policy<{'arm64': '-'}>
+CONFIG_GPIO_WM8350                              policy<{'arm64': '-'}>
+CONFIG_GPIO_WM8994                              policy<{'arm64': '-'}>
+CONFIG_GPIO_XGENE                               policy<{'arm64': 'n'}>
+CONFIG_GPIO_XGENE_SB                            policy<{'arm64': '-'}>
+CONFIG_GPIO_XLP                                 policy<{'arm64': '-'}>
+CONFIG_GPIO_XRA1403                             policy<{'arm64': 'n'}>
+CONFIG_GPIO_ZYNQ                                policy<{'arm64': 'y'}>
+CONFIG_GRACE_PERIOD                             policy<{'arm64': 'y'}>
+CONFIG_GREENASIA_FF                             policy<{'arm64': '-'}>
+CONFIG_GREYBUS                                  policy<{'arm64': 'n'}>
+CONFIG_GREYBUS_AUDIO                            policy<{'arm64': '-'}>
+CONFIG_GREYBUS_BOOTROM                          policy<{'arm64': '-'}>
+CONFIG_GREYBUS_BRIDGED_PHY                      policy<{'arm64': '-'}>
+CONFIG_GREYBUS_ES2                              policy<{'arm64': '-'}>
+CONFIG_GREYBUS_FIRMWARE                         policy<{'arm64': '-'}>
+CONFIG_GREYBUS_GPIO                             policy<{'arm64': '-'}>
+CONFIG_GREYBUS_HID                              policy<{'arm64': '-'}>
+CONFIG_GREYBUS_I2C                              policy<{'arm64': '-'}>
+CONFIG_GREYBUS_LIGHT                            policy<{'arm64': '-'}>
+CONFIG_GREYBUS_LOG                              policy<{'arm64': '-'}>
+CONFIG_GREYBUS_LOOPBACK                         policy<{'arm64': '-'}>
+CONFIG_GREYBUS_POWER                            policy<{'arm64': '-'}>
+CONFIG_GREYBUS_PWM                              policy<{'arm64': '-'}>
+CONFIG_GREYBUS_RAW                              policy<{'arm64': '-'}>
+CONFIG_GREYBUS_SDIO                             policy<{'arm64': '-'}>
+CONFIG_GREYBUS_SPI                              policy<{'arm64': '-'}>
+CONFIG_GREYBUS_UART                             policy<{'arm64': '-'}>
+CONFIG_GREYBUS_USB                              policy<{'arm64': '-'}>
+CONFIG_GREYBUS_VIBRATOR                         policy<{'arm64': '-'}>
+CONFIG_GS_FPGABOOT                              policy<{'arm64': 'n'}>
+CONFIG_GTP                                      policy<{'arm64': 'n'}>
+CONFIG_GVE                                      policy<{'arm64': 'n'}>
+CONFIG_HABANA_AI                                policy<{'arm64': 'n'}>
+CONFIG_HAMACHI                                  policy<{'arm64': 'n'}>
+CONFIG_HAMRADIO                                 policy<{'arm64': 'n'}>
+CONFIG_HAPPYMEAL                                policy<{'arm64': 'n'}>
+CONFIG_HAVE_ACPI_APEI                           policy<{'arm64': '-'}>
+CONFIG_HAVE_ALIGNED_STRUCT_PAGE                 policy<{'arm64': '-'}>
+CONFIG_HAVE_KVM_ARCH_TLB_FLUSH_ALL              policy<{'arm64': '-'}>
+CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT             policy<{'arm64': '-'}>
+CONFIG_HAVE_KVM_EVENTFD                         policy<{'arm64': '-'}>
+CONFIG_HAVE_KVM_IRQCHIP                         policy<{'arm64': '-'}>
+CONFIG_HAVE_KVM_IRQFD                           policy<{'arm64': '-'}>
+CONFIG_HAVE_KVM_IRQ_BYPASS                      policy<{'arm64': '-'}>
+CONFIG_HAVE_KVM_IRQ_ROUTING                     policy<{'arm64': '-'}>
+CONFIG_HAVE_KVM_MSI                             policy<{'arm64': '-'}>
+CONFIG_HAVE_KVM_VCPU_RUN_PID_CHANGE             policy<{'arm64': '-'}>
+CONFIG_HAVE_MEMBLOCK_NODE_MAP                   policy<{'arm64': '-'}>
+CONFIG_HAVE_SETUP_PER_CPU_AREA                  policy<{'arm64': '-'}>
+CONFIG_HBMC_AM654                               policy<{'arm64': '-'}>
+CONFIG_HD44780                                  policy<{'arm64': '-'}>
+CONFIG_HDC100X                                  policy<{'arm64': 'n'}>
+CONFIG_HDLC                                     policy<{'arm64': '-'}>
+CONFIG_HDLC_CISCO                               policy<{'arm64': '-'}>
+CONFIG_HDLC_FR                                  policy<{'arm64': '-'}>
+CONFIG_HDLC_PPP                                 policy<{'arm64': '-'}>
+CONFIG_HDLC_RAW                                 policy<{'arm64': '-'}>
+CONFIG_HDLC_RAW_ETH                             policy<{'arm64': '-'}>
+CONFIG_HDLC_X25                                 policy<{'arm64': '-'}>
+CONFIG_HERMES                                   policy<{'arm64': 'n'}>
+CONFIG_HERMES_CACHE_FW_ON_INIT                  policy<{'arm64': '-'}>
+CONFIG_HERMES_PRISM                             policy<{'arm64': '-'}>
+CONFIG_HFSPLUS_FS                               policy<{'arm64': 'n'}>
+CONFIG_HFS_FS                                   policy<{'arm64': 'n'}>
+CONFIG_HI13X1_GMAC                              policy<{'arm64': '-'}>
+CONFIG_HI3660_MBOX                              policy<{'arm64': '-'}>
+CONFIG_HI6220_MBOX                              policy<{'arm64': '-'}>
+CONFIG_HI8435                                   policy<{'arm64': 'n'}>
+CONFIG_HID                                      policy<{'arm64': 'y'}>
+CONFIG_HIDRAW                                   policy<{'arm64': 'n'}>
+CONFIG_HID_A4TECH                               policy<{'arm64': 'n'}>
+CONFIG_HID_ACCUTOUCH                            policy<{'arm64': 'n'}>
+CONFIG_HID_ACRUX                                policy<{'arm64': 'n'}>
+CONFIG_HID_ACRUX_FF                             policy<{'arm64': '-'}>
+CONFIG_HID_ALPS                                 policy<{'arm64': 'n'}>
+CONFIG_HID_APPLE                                policy<{'arm64': 'n'}>
+CONFIG_HID_APPLEIR                              policy<{'arm64': 'n'}>
+CONFIG_HID_ASUS                                 policy<{'arm64': 'n'}>
+CONFIG_HID_AUREAL                               policy<{'arm64': 'n'}>
+CONFIG_HID_BATTERY_STRENGTH                     policy<{'arm64': 'n'}>
+CONFIG_HID_BELKIN                               policy<{'arm64': 'n'}>
+CONFIG_HID_BETOP_FF                             policy<{'arm64': 'n'}>
+CONFIG_HID_BIGBEN_FF                            policy<{'arm64': 'n'}>
+CONFIG_HID_CHERRY                               policy<{'arm64': 'n'}>
+CONFIG_HID_CHICONY                              policy<{'arm64': 'n'}>
+CONFIG_HID_CMEDIA                               policy<{'arm64': 'n'}>
+CONFIG_HID_CORSAIR                              policy<{'arm64': 'n'}>
+CONFIG_HID_COUGAR                               policy<{'arm64': 'n'}>
+CONFIG_HID_CP2112                               policy<{'arm64': '-'}>
+CONFIG_HID_CREATIVE_SB0540                      policy<{'arm64': 'n'}>
+CONFIG_HID_CYPRESS                              policy<{'arm64': 'n'}>
+CONFIG_HID_DRAGONRISE                           policy<{'arm64': 'n'}>
+CONFIG_HID_ELAN                                 policy<{'arm64': 'n'}>
+CONFIG_HID_ELECOM                               policy<{'arm64': 'n'}>
+CONFIG_HID_ELO                                  policy<{'arm64': 'n'}>
+CONFIG_HID_EMS_FF                               policy<{'arm64': 'n'}>
+CONFIG_HID_EZKEY                                policy<{'arm64': 'n'}>
+CONFIG_HID_GEMBIRD                              policy<{'arm64': 'n'}>
+CONFIG_HID_GENERIC                              policy<{'arm64': 'y'}>
+CONFIG_HID_GFRM                                 policy<{'arm64': 'n'}>
+CONFIG_HID_GOOGLE_HAMMER                        policy<{'arm64': '-'}>
+CONFIG_HID_GREENASIA                            policy<{'arm64': 'n'}>
+CONFIG_HID_GT683R                               policy<{'arm64': 'n'}>
+CONFIG_HID_GYRATION                             policy<{'arm64': 'n'}>
+CONFIG_HID_HOLTEK                               policy<{'arm64': 'n'}>
+CONFIG_HID_ICADE                                policy<{'arm64': 'n'}>
+CONFIG_HID_ITE                                  policy<{'arm64': 'n'}>
+CONFIG_HID_JABRA                                policy<{'arm64': 'n'}>
+CONFIG_HID_KENSINGTON                           policy<{'arm64': 'n'}>
+CONFIG_HID_KEYTOUCH                             policy<{'arm64': 'n'}>
+CONFIG_HID_KYE                                  policy<{'arm64': 'n'}>
+CONFIG_HID_LCPOWER                              policy<{'arm64': 'n'}>
+CONFIG_HID_LED                                  policy<{'arm64': 'n'}>
+CONFIG_HID_LENOVO                               policy<{'arm64': 'n'}>
+CONFIG_HID_LOGITECH                             policy<{'arm64': 'n'}>
+CONFIG_HID_LOGITECH_DJ                          policy<{'arm64': '-'}>
+CONFIG_HID_LOGITECH_HIDPP                       policy<{'arm64': '-'}>
+CONFIG_HID_MACALLY                              policy<{'arm64': 'n'}>
+CONFIG_HID_MAGICMOUSE                           policy<{'arm64': 'n'}>
+CONFIG_HID_MALTRON                              policy<{'arm64': 'n'}>
+CONFIG_HID_MAYFLASH                             policy<{'arm64': 'n'}>
+CONFIG_HID_MICROSOFT                            policy<{'arm64': 'n'}>
+CONFIG_HID_MONTEREY                             policy<{'arm64': 'n'}>
+CONFIG_HID_MULTITOUCH                           policy<{'arm64': 'n'}>
+CONFIG_HID_NTI                                  policy<{'arm64': 'n'}>
+CONFIG_HID_NTRIG                                policy<{'arm64': 'n'}>
+CONFIG_HID_ORTEK                                policy<{'arm64': 'n'}>
+CONFIG_HID_PANTHERLORD                          policy<{'arm64': 'n'}>
+CONFIG_HID_PENMOUNT                             policy<{'arm64': 'n'}>
+CONFIG_HID_PETALYNX                             policy<{'arm64': 'n'}>
+CONFIG_HID_PICOLCD                              policy<{'arm64': 'n'}>
+CONFIG_HID_PICOLCD_BACKLIGHT                    policy<{'arm64': '-'}>
+CONFIG_HID_PICOLCD_CIR                          policy<{'arm64': '-'}>
+CONFIG_HID_PICOLCD_FB                           policy<{'arm64': '-'}>
+CONFIG_HID_PICOLCD_LCD                          policy<{'arm64': '-'}>
+CONFIG_HID_PICOLCD_LEDS                         policy<{'arm64': '-'}>
+CONFIG_HID_PID                                  policy<{'arm64': 'n'}>
+CONFIG_HID_PLANTRONICS                          policy<{'arm64': 'n'}>
+CONFIG_HID_PRIMAX                               policy<{'arm64': 'n'}>
+CONFIG_HID_PRODIKEYS                            policy<{'arm64': 'n'}>
+CONFIG_HID_REDRAGON                             policy<{'arm64': 'n'}>
+CONFIG_HID_RETRODE                              policy<{'arm64': 'n'}>
+CONFIG_HID_RMI                                  policy<{'arm64': 'n'}>
+CONFIG_HID_ROCCAT                               policy<{'arm64': 'n'}>
+CONFIG_HID_SAITEK                               policy<{'arm64': 'n'}>
+CONFIG_HID_SAMSUNG                              policy<{'arm64': 'n'}>
+CONFIG_HID_SENSOR_ACCEL_3D                      policy<{'arm64': '-'}>
+CONFIG_HID_SENSOR_ALS                           policy<{'arm64': '-'}>
+CONFIG_HID_SENSOR_CUSTOM_SENSOR                 policy<{'arm64': '-'}>
+CONFIG_HID_SENSOR_DEVICE_ROTATION               policy<{'arm64': '-'}>
+CONFIG_HID_SENSOR_GYRO_3D                       policy<{'arm64': '-'}>
+CONFIG_HID_SENSOR_HUB                           policy<{'arm64': 'n'}>
+CONFIG_HID_SENSOR_HUMIDITY                      policy<{'arm64': '-'}>
+CONFIG_HID_SENSOR_IIO_COMMON                    policy<{'arm64': '-'}>
+CONFIG_HID_SENSOR_IIO_TRIGGER                   policy<{'arm64': '-'}>
+CONFIG_HID_SENSOR_INCLINOMETER_3D               policy<{'arm64': '-'}>
+CONFIG_HID_SENSOR_MAGNETOMETER_3D               policy<{'arm64': '-'}>
+CONFIG_HID_SENSOR_PRESS                         policy<{'arm64': '-'}>
+CONFIG_HID_SENSOR_PROX                          policy<{'arm64': '-'}>
+CONFIG_HID_SENSOR_TEMP                          policy<{'arm64': '-'}>
+CONFIG_HID_SMARTJOYPLUS                         policy<{'arm64': 'n'}>
+CONFIG_HID_SONY                                 policy<{'arm64': 'n'}>
+CONFIG_HID_SPEEDLINK                            policy<{'arm64': 'n'}>
+CONFIG_HID_STEAM                                policy<{'arm64': 'n'}>
+CONFIG_HID_STEELSERIES                          policy<{'arm64': 'n'}>
+CONFIG_HID_SUNPLUS                              policy<{'arm64': 'n'}>
+CONFIG_HID_THINGM                               policy<{'arm64': 'n'}>
+CONFIG_HID_THRUSTMASTER                         policy<{'arm64': 'n'}>
+CONFIG_HID_TIVO                                 policy<{'arm64': 'n'}>
+CONFIG_HID_TOPSEED                              policy<{'arm64': 'n'}>
+CONFIG_HID_TWINHAN                              policy<{'arm64': 'n'}>
+CONFIG_HID_U2FZERO                              policy<{'arm64': '-'}>
+CONFIG_HID_UCLOGIC                              policy<{'arm64': 'n'}>
+CONFIG_HID_UDRAW_PS3                            policy<{'arm64': 'n'}>
+CONFIG_HID_VIEWSONIC                            policy<{'arm64': 'n'}>
+CONFIG_HID_WACOM                                policy<{'arm64': 'n'}>
+CONFIG_HID_WALTOP                               policy<{'arm64': 'n'}>
+CONFIG_HID_WIIMOTE                              policy<{'arm64': 'n'}>
+CONFIG_HID_XINMO                                policy<{'arm64': 'n'}>
+CONFIG_HID_ZEROPLUS                             policy<{'arm64': 'n'}>
+CONFIG_HID_ZYDACRON                             policy<{'arm64': 'n'}>
+CONFIG_HINIC                                    policy<{'arm64': 'n'}>
+CONFIG_HIP04_ETH                                policy<{'arm64': 'n'}>
+CONFIG_HISILICON_IRQ_MBIGEN                     policy<{'arm64': '-'}>
+CONFIG_HISILICON_LPC                            policy<{'arm64': '-'}>
+CONFIG_HISI_FEMAC                               policy<{'arm64': 'n'}>
+CONFIG_HISI_PMU                                 policy<{'arm64': '-'}>
+CONFIG_HISI_THERMAL                             policy<{'arm64': '-'}>
+CONFIG_HIST_TRIGGERS                            policy<{'arm64': 'n'}>
+CONFIG_HIX5HD2_GMAC                             policy<{'arm64': 'n'}>
+CONFIG_HMC6352                                  policy<{'arm64': 'n'}>
+CONFIG_HMEM_REPORTING                           policy<{'arm64': '-'}>
+CONFIG_HMM_MIRROR                               policy<{'arm64': '-'}>
+CONFIG_HMS_ANYBUSS_BUS                          policy<{'arm64': '-'}>
+CONFIG_HMS_PROFINET                             policy<{'arm64': '-'}>
+CONFIG_HNS                                      policy<{'arm64': 'n'}>
+CONFIG_HNS3                                     policy<{'arm64': 'n'}>
+CONFIG_HNS3_DCB                                 policy<{'arm64': '-'}>
+CONFIG_HNS3_ENET                                policy<{'arm64': '-'}>
+CONFIG_HNS3_HCLGE                               policy<{'arm64': '-'}>
+CONFIG_HNS3_HCLGEVF                             policy<{'arm64': '-'}>
+CONFIG_HNS_DSAF                                 policy<{'arm64': 'n'}>
+CONFIG_HNS_ENET                                 policy<{'arm64': 'n'}>
+CONFIG_HNS_MDIO                                 policy<{'arm64': '-'}>
+CONFIG_HOLTEK_FF                                policy<{'arm64': '-'}>
+CONFIG_HOSTAP                                   policy<{'arm64': 'n'}>
+CONFIG_HOSTAP_FIRMWARE                          policy<{'arm64': '-'}>
+CONFIG_HOSTAP_FIRMWARE_NVRAM                    policy<{'arm64': '-'}>
+CONFIG_HOSTAP_PCI                               policy<{'arm64': '-'}>
+CONFIG_HOSTAP_PLX                               policy<{'arm64': '-'}>
+CONFIG_HOTPLUG_PCI                              policy<{'arm64': 'n'}>
+CONFIG_HOTPLUG_PCI_ACPI                         policy<{'arm64': '-'}>
+CONFIG_HOTPLUG_PCI_ACPI_IBM                     policy<{'arm64': '-'}>
+CONFIG_HOTPLUG_PCI_CPCI                         policy<{'arm64': '-'}>
+CONFIG_HP03                                     policy<{'arm64': 'n'}>
+CONFIG_HP100                                    policy<{'arm64': 'n'}>
+CONFIG_HP206C                                   policy<{'arm64': 'n'}>
+CONFIG_HPFS_FS                                  policy<{'arm64': 'n'}>
+CONFIG_HP_ILO                                   policy<{'arm64': 'n'}>
+CONFIG_HSA_AMD                                  policy<{'arm64': '-'}>
+CONFIG_HSI                                      policy<{'arm64': 'n'}>
+CONFIG_HSI_BOARDINFO                            policy<{'arm64': '-'}>
+CONFIG_HSI_CHAR                                 policy<{'arm64': '-'}>
+CONFIG_HSR                                      policy<{'arm64': 'n'}>
+CONFIG_HT16K33                                  policy<{'arm64': '-'}>
+CONFIG_HTC_I2CPLD                               policy<{'arm64': 'n'}>
+CONFIG_HTC_PASIC3                               policy<{'arm64': 'n'}>
+CONFIG_HTS221                                   policy<{'arm64': 'n'}>
+CONFIG_HTS221_I2C                               policy<{'arm64': '-'}>
+CONFIG_HTS221_SPI                               policy<{'arm64': '-'}>
+CONFIG_HTU21                                    policy<{'arm64': 'n'}>
+CONFIG_HWLAT_TRACER                             policy<{'arm64': 'n'}>
+CONFIG_HWMON_VID                                policy<{'arm64': '-'}>
+CONFIG_HWPOISON_INJECT                          policy<{'arm64': '-'}>
+CONFIG_HWSPINLOCK                               policy<{'arm64': 'n'}>
+CONFIG_HWSPINLOCK_OMAP                          policy<{'arm64': '-'}>
+CONFIG_HWSPINLOCK_QCOM                          policy<{'arm64': '-'}>
+CONFIG_HWSPINLOCK_SPRD                          policy<{'arm64': '-'}>
+CONFIG_HW_PERF_EVENTS                           policy<{'arm64': '-'}>
+CONFIG_HW_RANDOM                                policy<{'arm64': 'n'}>
+CONFIG_HW_RANDOM_BCM2835                        policy<{'arm64': '-'}>
+CONFIG_HW_RANDOM_CAVIUM                         policy<{'arm64': '-'}>
+CONFIG_HW_RANDOM_HISI                           policy<{'arm64': '-'}>
+CONFIG_HW_RANDOM_HISI_V2                        policy<{'arm64': '-'}>
+CONFIG_HW_RANDOM_IMX_RNGC                       policy<{'arm64': '-'}>
+CONFIG_HW_RANDOM_IPROC_RNG200                   policy<{'arm64': '-'}>
+CONFIG_HW_RANDOM_MESON                          policy<{'arm64': '-'}>
+CONFIG_HW_RANDOM_MTK                            policy<{'arm64': '-'}>
+CONFIG_HW_RANDOM_OMAP                           policy<{'arm64': '-'}>
+CONFIG_HW_RANDOM_OPTEE                          policy<{'arm64': '-'}>
+CONFIG_HW_RANDOM_TIMERIOMEM                     policy<{'arm64': '-'}>
+CONFIG_HW_RANDOM_TPM                            policy<{'arm64': '-'}>
+CONFIG_HW_RANDOM_VIRTIO                         policy<{'arm64': '-'}>
+CONFIG_HW_RANDOM_XGENE                          policy<{'arm64': '-'}>
+CONFIG_HX711                                    policy<{'arm64': 'n'}>
+CONFIG_HYSDN                                    policy<{'arm64': '-'}>
+CONFIG_HYSDN_CAPI                               policy<{'arm64': '-'}>
+CONFIG_I2C_ALGOBIT                              policy<{'arm64': 'y'}>
+CONFIG_I2C_ALGOPCA                              policy<{'arm64': '-'}>
+CONFIG_I2C_ALI1535                              policy<{'arm64': 'n'}>
+CONFIG_I2C_ALI1563                              policy<{'arm64': 'n'}>
+CONFIG_I2C_ALI15X3                              policy<{'arm64': 'n'}>
+CONFIG_I2C_AMD756                               policy<{'arm64': 'n'}>
+CONFIG_I2C_AMD8111                              policy<{'arm64': 'n'}>
+CONFIG_I2C_AMD_MP2                              policy<{'arm64': '-'}>
+CONFIG_I2C_ARB_GPIO_CHALLENGE                   policy<{'arm64': 'n'}>
+CONFIG_I2C_BCM2835                              policy<{'arm64': '-'}>
+CONFIG_I2C_BCM_IPROC                            policy<{'arm64': '-'}>
+CONFIG_I2C_BRCMSTB                              policy<{'arm64': '-'}>
+CONFIG_I2C_CADENCE                              policy<{'arm64': 'y'}>
+CONFIG_I2C_CBUS_GPIO                            policy<{'arm64': 'n'}>
+CONFIG_I2C_CROS_EC_TUNNEL                       policy<{'arm64': '-'}>
+CONFIG_I2C_DEMUX_PINCTRL                        policy<{'arm64': 'n'}>
+CONFIG_I2C_DESIGNWARE_CORE                      policy<{'arm64': '-'}>
+CONFIG_I2C_DESIGNWARE_PCI                       policy<{'arm64': 'n'}>
+CONFIG_I2C_DESIGNWARE_PLATFORM                  policy<{'arm64': 'n'}>
+CONFIG_I2C_DESIGNWARE_SLAVE                     policy<{'arm64': '-'}>
+CONFIG_I2C_DIOLAN_U2C                           policy<{'arm64': 'n'}>
+CONFIG_I2C_DLN2                                 policy<{'arm64': '-'}>
+CONFIG_I2C_FSI                                  policy<{'arm64': '-'}>
+CONFIG_I2C_GPIO                                 policy<{'arm64': 'n'}>
+CONFIG_I2C_GPIO_FAULT_INJECTOR                  policy<{'arm64': '-'}>
+CONFIG_I2C_HID                                  policy<{'arm64': 'n'}>
+CONFIG_I2C_HIX5HD2                              policy<{'arm64': '-'}>
+CONFIG_I2C_I801                                 policy<{'arm64': 'n'}>
+CONFIG_I2C_IMX                                  policy<{'arm64': '-'}>
+CONFIG_I2C_IMX_LPI2C                            policy<{'arm64': '-'}>
+CONFIG_I2C_ISCH                                 policy<{'arm64': 'n'}>
+CONFIG_I2C_KEMPLD                               policy<{'arm64': '-'}>
+CONFIG_I2C_MESON                                policy<{'arm64': '-'}>
+CONFIG_I2C_MT65XX                               policy<{'arm64': '-'}>
+CONFIG_I2C_MUX                                  policy<{'arm64': 'y'}>
+CONFIG_I2C_MUX_GPIO                             policy<{'arm64': 'n'}>
+CONFIG_I2C_MUX_GPMUX                            policy<{'arm64': 'n'}>
+CONFIG_I2C_MUX_LTC4306                          policy<{'arm64': 'n'}>
+CONFIG_I2C_MUX_MLXCPLD                          policy<{'arm64': 'n'}>
+CONFIG_I2C_MUX_PCA9541                          policy<{'arm64': 'y'}>
+CONFIG_I2C_MUX_PCA954x                          policy<{'arm64': 'y'}>
+CONFIG_I2C_MUX_PINCTRL                          policy<{'arm64': 'n'}>
+CONFIG_I2C_MUX_REG                              policy<{'arm64': 'n'}>
+CONFIG_I2C_MV64XXX                              policy<{'arm64': '-'}>
+CONFIG_I2C_NFORCE2                              policy<{'arm64': 'n'}>
+CONFIG_I2C_NOMADIK                              policy<{'arm64': 'n'}>
+CONFIG_I2C_NVIDIA_GPU                           policy<{'arm64': 'n'}>
+CONFIG_I2C_OCORES                               policy<{'arm64': 'n'}>
+CONFIG_I2C_OMAP                                 policy<{'arm64': '-'}>
+CONFIG_I2C_OWL                                  policy<{'arm64': '-'}>
+CONFIG_I2C_PARPORT                              policy<{'arm64': '-'}>
+CONFIG_I2C_PARPORT_LIGHT                        policy<{'arm64': 'n'}>
+CONFIG_I2C_PCA_PLATFORM                         policy<{'arm64': 'n'}>
+CONFIG_I2C_PIIX4                                policy<{'arm64': 'n'}>
+CONFIG_I2C_PXA                                  policy<{'arm64': '-'}>
+CONFIG_I2C_PXA_SLAVE                            policy<{'arm64': '-'}>
+CONFIG_I2C_QCOM_GENI                            policy<{'arm64': '-'}>
+CONFIG_I2C_QUP                                  policy<{'arm64': '-'}>
+CONFIG_I2C_RCAR                                 policy<{'arm64': '-'}>
+CONFIG_I2C_RIIC                                 policy<{'arm64': '-'}>
+CONFIG_I2C_RK3X                                 policy<{'arm64': 'n'}>
+CONFIG_I2C_ROBOTFUZZ_OSIF                       policy<{'arm64': 'n'}>
+CONFIG_I2C_SCMI                                 policy<{'arm64': '-'}>
+CONFIG_I2C_SH_MOBILE                            policy<{'arm64': '-'}>
+CONFIG_I2C_SI470X                               policy<{'arm64': '-'}>
+CONFIG_I2C_SI4713                               policy<{'arm64': '-'}>
+CONFIG_I2C_SIMTEC                               policy<{'arm64': 'n'}>
+CONFIG_I2C_SIS5595                              policy<{'arm64': 'n'}>
+CONFIG_I2C_SIS630                               policy<{'arm64': 'n'}>
+CONFIG_I2C_SIS96X                               policy<{'arm64': 'n'}>
+CONFIG_I2C_SLAVE                                policy<{'arm64': 'n'}>
+CONFIG_I2C_SLAVE_EEPROM                         policy<{'arm64': '-'}>
+CONFIG_I2C_SMBUS                                policy<{'arm64': '-'}>
+CONFIG_I2C_SPRD                                 policy<{'arm64': '-'}>
+CONFIG_I2C_STUB                                 policy<{'arm64': 'n'}>
+CONFIG_I2C_SYNQUACER                            policy<{'arm64': '-'}>
+CONFIG_I2C_TAOS_EVM                             policy<{'arm64': 'n'}>
+CONFIG_I2C_THUNDERX                             policy<{'arm64': 'n'}>
+CONFIG_I2C_TINY_USB                             policy<{'arm64': 'n'}>
+CONFIG_I2C_VERSATILE                            policy<{'arm64': '-'}>
+CONFIG_I2C_VIA                                  policy<{'arm64': 'n'}>
+CONFIG_I2C_VIAPRO                               policy<{'arm64': 'n'}>
+CONFIG_I2C_VIPERBOARD                           policy<{'arm64': '-'}>
+CONFIG_I2C_XGENE_SLIMPRO                        policy<{'arm64': '-'}>
+CONFIG_I2C_XILINX                               policy<{'arm64': 'y'}>
+CONFIG_I2C_XLP9XX                               policy<{'arm64': '-'}>
+CONFIG_I3C                                      policy<{'arm64': 'n'}>
+CONFIG_I40E                                     policy<{'arm64': 'n'}>
+CONFIG_I40EVF                                   policy<{'arm64': 'n'}>
+CONFIG_I40E_DCB                                 policy<{'arm64': '-'}>
+CONFIG_I6300ESB_WDT                             policy<{'arm64': 'n'}>
+CONFIG_IAQCORE                                  policy<{'arm64': 'n'}>
+CONFIG_IAVF                                     policy<{'arm64': '-'}>
+CONFIG_ICE                                      policy<{'arm64': 'n'}>
+CONFIG_ICPLUS_PHY                               policy<{'arm64': 'y'}>
+CONFIG_ICS932S401                               policy<{'arm64': 'n'}>
+CONFIG_IDLE_INJECT                              policy<{'arm64': '-'}>
+CONFIG_IEEE802154                               policy<{'arm64': 'n'}>
+CONFIG_IEEE802154_6LOWPAN                       policy<{'arm64': '-'}>
+CONFIG_IEEE802154_ADF7242                       policy<{'arm64': '-'}>
+CONFIG_IEEE802154_AT86RF230                     policy<{'arm64': '-'}>
+CONFIG_IEEE802154_AT86RF230_DEBUGFS             policy<{'arm64': '-'}>
+CONFIG_IEEE802154_ATUSB                         policy<{'arm64': '-'}>
+CONFIG_IEEE802154_CA8210                        policy<{'arm64': '-'}>
+CONFIG_IEEE802154_CA8210_DEBUGFS                policy<{'arm64': '-'}>
+CONFIG_IEEE802154_CC2520                        policy<{'arm64': '-'}>
+CONFIG_IEEE802154_DRIVERS                       policy<{'arm64': '-'}>
+CONFIG_IEEE802154_FAKELB                        policy<{'arm64': '-'}>
+CONFIG_IEEE802154_HWSIM                         policy<{'arm64': '-'}>
+CONFIG_IEEE802154_MCR20A                        policy<{'arm64': '-'}>
+CONFIG_IEEE802154_MRF24J40                      policy<{'arm64': '-'}>
+CONFIG_IEEE802154_NL802154_EXPERIMENTAL         policy<{'arm64': '-'}>
+CONFIG_IEEE802154_SOCKET                        policy<{'arm64': '-'}>
+CONFIG_IFB                                      policy<{'arm64': '-'}>
+CONFIG_IGB                                      policy<{'arm64': 'n'}>
+CONFIG_IGBVF                                    policy<{'arm64': 'n'}>
+CONFIG_IGB_HWMON                                policy<{'arm64': '-'}>
+CONFIG_IGC                                      policy<{'arm64': 'n'}>
+CONFIG_IIO                                      policy<{'arm64': 'y'}>
+CONFIG_IIO_ADIS_LIB                             policy<{'arm64': '-'}>
+CONFIG_IIO_ADIS_LIB_BUFFER                      policy<{'arm64': '-'}>
+CONFIG_IIO_BUFFER_CB                            policy<{'arm64': 'n'}>
+CONFIG_IIO_BUFFER_HW_CONSUMER                   policy<{'arm64': 'n'}>
+CONFIG_IIO_CONFIGFS                             policy<{'arm64': 'n'}>
+CONFIG_IIO_CROS_EC_ACCEL_LEGACY                 policy<{'arm64': '-'}>
+CONFIG_IIO_CROS_EC_BARO                         policy<{'arm64': '-'}>
+CONFIG_IIO_CROS_EC_LIGHT_PROX                   policy<{'arm64': '-'}>
+CONFIG_IIO_CROS_EC_SENSORS                      policy<{'arm64': '-'}>
+CONFIG_IIO_CROS_EC_SENSORS_CORE                 policy<{'arm64': '-'}>
+CONFIG_IIO_CROS_EC_SENSORS_LID_ANGLE            policy<{'arm64': '-'}>
+CONFIG_IIO_HRTIMER_TRIGGER                      policy<{'arm64': '-'}>
+CONFIG_IIO_INTERRUPT_TRIGGER                    policy<{'arm64': 'n'}>
+CONFIG_IIO_KFIFO_BUF                            policy<{'arm64': 'y'}>
+CONFIG_IIO_MS_SENSORS_I2C                       policy<{'arm64': '-'}>
+CONFIG_IIO_MUX                                  policy<{'arm64': 'n'}>
+CONFIG_IIO_RESCALE                              policy<{'arm64': 'n'}>
+CONFIG_IIO_SIMPLE_DUMMY                         policy<{'arm64': '-'}>
+CONFIG_IIO_SSP_SENSORHUB                        policy<{'arm64': 'n'}>
+CONFIG_IIO_SSP_SENSORS_COMMONS                  policy<{'arm64': '-'}>
+CONFIG_IIO_ST_ACCEL_3AXIS                       policy<{'arm64': 'n'}>
+CONFIG_IIO_ST_ACCEL_I2C_3AXIS                   policy<{'arm64': '-'}>
+CONFIG_IIO_ST_ACCEL_SPI_3AXIS                   policy<{'arm64': '-'}>
+CONFIG_IIO_ST_GYRO_3AXIS                        policy<{'arm64': 'n'}>
+CONFIG_IIO_ST_GYRO_I2C_3AXIS                    policy<{'arm64': '-'}>
+CONFIG_IIO_ST_GYRO_SPI_3AXIS                    policy<{'arm64': '-'}>
+CONFIG_IIO_ST_LSM6DSX                           policy<{'arm64': 'n'}>
+CONFIG_IIO_ST_LSM6DSX_I2C                       policy<{'arm64': '-'}>
+CONFIG_IIO_ST_LSM6DSX_I3C                       policy<{'arm64': '-'}>
+CONFIG_IIO_ST_LSM6DSX_SPI                       policy<{'arm64': '-'}>
+CONFIG_IIO_ST_MAGN_3AXIS                        policy<{'arm64': 'n'}>
+CONFIG_IIO_ST_MAGN_I2C_3AXIS                    policy<{'arm64': '-'}>
+CONFIG_IIO_ST_MAGN_SPI_3AXIS                    policy<{'arm64': '-'}>
+CONFIG_IIO_ST_PRESS                             policy<{'arm64': 'n'}>
+CONFIG_IIO_ST_PRESS_I2C                         policy<{'arm64': '-'}>
+CONFIG_IIO_ST_PRESS_SPI                         policy<{'arm64': '-'}>
+CONFIG_IIO_ST_SENSORS_CORE                      policy<{'arm64': '-'}>
+CONFIG_IIO_ST_SENSORS_I2C                       policy<{'arm64': '-'}>
+CONFIG_IIO_ST_SENSORS_SPI                       policy<{'arm64': '-'}>
+CONFIG_IIO_SW_DEVICE                            policy<{'arm64': 'n'}>
+CONFIG_IIO_SW_TRIGGER                           policy<{'arm64': 'n'}>
+CONFIG_IIO_SYSFS_TRIGGER                        policy<{'arm64': 'n'}>
+CONFIG_IIO_TIGHTLOOP_TRIGGER                    policy<{'arm64': '-'}>
+CONFIG_IIO_TRIGGERED_BUFFER                     policy<{'arm64': 'y'}>
+CONFIG_IIO_TRIGGERED_EVENT                      policy<{'arm64': '-'}>
+CONFIG_IKCONFIG                                 policy<{'arm64': 'y'}>
+CONFIG_IKCONFIG_PROC                            policy<{'arm64': 'y'}>
+CONFIG_IKHEADERS                                policy<{'arm64': 'n'}>
+CONFIG_IMA_APPRAISE_BOOTPARAM                   policy<{'arm64': '-'}>
+CONFIG_IMA_APPRAISE_BUILD_POLICY                policy<{'arm64': '-'}>
+CONFIG_IMA_APPRAISE_MODSIG                      policy<{'arm64': '-'}>
+CONFIG_IMA_BLACKLIST_KEYRING                    policy<{'arm64': '-'}>
+CONFIG_IMA_DEFAULT_HASH                         policy<{'arm64': '-'}>
+CONFIG_IMA_DEFAULT_HASH_SHA1                    policy<{'arm64': '-'}>
+CONFIG_IMA_DEFAULT_HASH_SHA512                  policy<{'arm64': '-'}>
+CONFIG_IMA_DEFAULT_TEMPLATE                     policy<{'arm64': '-'}>
+CONFIG_IMA_LOAD_X509                            policy<{'arm64': '-'}>
+CONFIG_IMA_LSM_RULES                            policy<{'arm64': '-'}>
+CONFIG_IMA_MEASURE_PCR_IDX                      policy<{'arm64': '-'}>
+CONFIG_IMA_NG_TEMPLATE                          policy<{'arm64': '-'}>
+CONFIG_IMG_ASCII_LCD                            policy<{'arm64': '-'}>
+CONFIG_IMX2_WDT                                 policy<{'arm64': '-'}>
+CONFIG_IMX7D_ADC                                policy<{'arm64': '-'}>
+CONFIG_IMX7ULP_WDT                              policy<{'arm64': '-'}>
+CONFIG_IMX_DMA                                  policy<{'arm64': '-'}>
+CONFIG_IMX_DSP                                  policy<{'arm64': '-'}>
+CONFIG_IMX_GPCV2                                policy<{'arm64': '-'}>
+CONFIG_IMX_GPCV2_PM_DOMAINS                     policy<{'arm64': '-'}>
+CONFIG_IMX_IRQSTEER                             policy<{'arm64': '-'}>
+CONFIG_IMX_MBOX                                 policy<{'arm64': '-'}>
+CONFIG_IMX_REMOTEPROC                           policy<{'arm64': '-'}>
+CONFIG_IMX_SCU                                  policy<{'arm64': '-'}>
+CONFIG_IMX_SCU_PD                               policy<{'arm64': '-'}>
+CONFIG_IMX_SCU_SOC                              policy<{'arm64': '-'}>
+CONFIG_IMX_SC_WDT                               policy<{'arm64': '-'}>
+CONFIG_IMX_SDMA                                 policy<{'arm64': '-'}>
+CONFIG_IMX_THERMAL                              policy<{'arm64': '-'}>
+CONFIG_IMX_WEIM                                 policy<{'arm64': '-'}>
+CONFIG_INA260_ADC                               policy<{'arm64': 'm'}>
+CONFIG_INDIRECT_PIO                             policy<{'arm64': 'n'}>
+CONFIG_INET6_AH                                 policy<{'arm64': 'y'}>
+CONFIG_INET6_ESP                                policy<{'arm64': 'y'}>
+CONFIG_INET6_ESP_OFFLOAD                        policy<{'arm64': 'n'}>
+CONFIG_INET6_IPCOMP                             policy<{'arm64': 'y'}>
+CONFIG_INET6_TUNNEL                             policy<{'arm64': 'y'}>
+CONFIG_INET6_XFRM_TUNNEL                        policy<{'arm64': 'y'}>
+CONFIG_INET_AH                                  policy<{'arm64': 'y'}>
+CONFIG_INET_DCCP_DIAG                           policy<{'arm64': '-'}>
+CONFIG_INET_DIAG                                policy<{'arm64': 'y'}>
+CONFIG_INET_DIAG_DESTROY                        policy<{'arm64': 'n'}>
+CONFIG_INET_ESP                                 policy<{'arm64': 'y'}>
+CONFIG_INET_ESP_OFFLOAD                         policy<{'arm64': 'n'}>
+CONFIG_INET_IPCOMP                              policy<{'arm64': 'y'}>
+CONFIG_INET_RAW_DIAG                            policy<{'arm64': 'n'}>
+CONFIG_INET_SCTP_DIAG                           policy<{'arm64': '-'}>
+CONFIG_INET_TCP_DIAG                            policy<{'arm64': 'y'}>
+CONFIG_INET_TUNNEL                              policy<{'arm64': 'y'}>
+CONFIG_INET_UDP_DIAG                            policy<{'arm64': 'n'}>
+CONFIG_INET_XFRM_TUNNEL                         policy<{'arm64': 'y'}>
+CONFIG_INFINIBAND                               policy<{'arm64': 'n'}>
+CONFIG_INFINIBAND_ADDR_TRANS                    policy<{'arm64': '-'}>
+CONFIG_INFINIBAND_ADDR_TRANS_CONFIGFS           policy<{'arm64': '-'}>
+CONFIG_INFINIBAND_BNXT_RE                       policy<{'arm64': '-'}>
+CONFIG_INFINIBAND_CXGB3                         policy<{'arm64': '-'}>
+CONFIG_INFINIBAND_CXGB4                         policy<{'arm64': '-'}>
+CONFIG_INFINIBAND_EFA                           policy<{'arm64': '-'}>
+CONFIG_INFINIBAND_EXP_LEGACY_VERBS_NEW_UAPI     policy<{'arm64': '-'}>
+CONFIG_INFINIBAND_HNS                           policy<{'arm64': '-'}>
+CONFIG_INFINIBAND_HNS_HIP06                     policy<{'arm64': '-'}>
+CONFIG_INFINIBAND_HNS_HIP08                     policy<{'arm64': '-'}>
+CONFIG_INFINIBAND_I40IW                         policy<{'arm64': '-'}>
+CONFIG_INFINIBAND_IPOIB                         policy<{'arm64': '-'}>
+CONFIG_INFINIBAND_IPOIB_CM                      policy<{'arm64': '-'}>
+CONFIG_INFINIBAND_IPOIB_DEBUG                   policy<{'arm64': '-'}>
+CONFIG_INFINIBAND_ISER                          policy<{'arm64': '-'}>
+CONFIG_INFINIBAND_ISERT                         policy<{'arm64': '-'}>
+CONFIG_INFINIBAND_MTHCA                         policy<{'arm64': '-'}>
+CONFIG_INFINIBAND_MTHCA_DEBUG                   policy<{'arm64': '-'}>
+CONFIG_INFINIBAND_OCRDMA                        policy<{'arm64': '-'}>
+CONFIG_INFINIBAND_ON_DEMAND_PAGING              policy<{'arm64': '-'}>
+CONFIG_INFINIBAND_QEDR                          policy<{'arm64': '-'}>
+CONFIG_INFINIBAND_SRP                           policy<{'arm64': '-'}>
+CONFIG_INFINIBAND_SRPT                          policy<{'arm64': '-'}>
+CONFIG_INFINIBAND_USER_ACCESS                   policy<{'arm64': '-'}>
+CONFIG_INFINIBAND_USER_MAD                      policy<{'arm64': '-'}>
+CONFIG_INFINIBAND_USER_MEM                      policy<{'arm64': '-'}>
+CONFIG_INFINIBAND_VIRT_DMA                      policy<{'arm64': '-'}>
+CONFIG_INFINIBAND_VMWARE_PVRDMA                 policy<{'arm64': '-'}>
+CONFIG_INFTL                                    policy<{'arm64': 'n'}>
+CONFIG_INIT_ON_ALLOC_DEFAULT_ON                 policy<{'arm64': 'n'}>
+CONFIG_INPUT_88PM80X_ONKEY                      policy<{'arm64': '-'}>
+CONFIG_INPUT_88PM860X_ONKEY                     policy<{'arm64': '-'}>
+CONFIG_INPUT_AD714X                             policy<{'arm64': 'n'}>
+CONFIG_INPUT_AD714X_I2C                         policy<{'arm64': '-'}>
+CONFIG_INPUT_AD714X_SPI                         policy<{'arm64': '-'}>
+CONFIG_INPUT_ADXL34X                            policy<{'arm64': 'n'}>
+CONFIG_INPUT_ADXL34X_I2C                        policy<{'arm64': '-'}>
+CONFIG_INPUT_ADXL34X_SPI                        policy<{'arm64': '-'}>
+CONFIG_INPUT_ARIZONA_HAPTICS                    policy<{'arm64': '-'}>
+CONFIG_INPUT_ATI_REMOTE2                        policy<{'arm64': 'n'}>
+CONFIG_INPUT_ATMEL_CAPTOUCH                     policy<{'arm64': 'n'}>
+CONFIG_INPUT_AXP20X_PEK                         policy<{'arm64': '-'}>
+CONFIG_INPUT_BMA150                             policy<{'arm64': 'n'}>
+CONFIG_INPUT_CM109                              policy<{'arm64': 'n'}>
+CONFIG_INPUT_CMA3000                            policy<{'arm64': 'n'}>
+CONFIG_INPUT_CMA3000_I2C                        policy<{'arm64': '-'}>
+CONFIG_INPUT_CPCAP_PWRBUTTON                    policy<{'arm64': '-'}>
+CONFIG_INPUT_DA9052_ONKEY                       policy<{'arm64': '-'}>
+CONFIG_INPUT_DA9055_ONKEY                       policy<{'arm64': '-'}>
+CONFIG_INPUT_DA9063_ONKEY                       policy<{'arm64': '-'}>
+CONFIG_INPUT_DRV260X_HAPTICS                    policy<{'arm64': 'n'}>
+CONFIG_INPUT_DRV2665_HAPTICS                    policy<{'arm64': 'n'}>
+CONFIG_INPUT_DRV2667_HAPTICS                    policy<{'arm64': 'n'}>
+CONFIG_INPUT_E3X0_BUTTON                        policy<{'arm64': 'n'}>
+CONFIG_INPUT_EVBUG                              policy<{'arm64': 'n'}>
+CONFIG_INPUT_FF_MEMLESS                         policy<{'arm64': 'n'}>
+CONFIG_INPUT_GP2A                               policy<{'arm64': 'n'}>
+CONFIG_INPUT_GPIO_BEEPER                        policy<{'arm64': 'n'}>
+CONFIG_INPUT_GPIO_DECODER                       policy<{'arm64': 'n'}>
+CONFIG_INPUT_GPIO_ROTARY_ENCODER                policy<{'arm64': 'n'}>
+CONFIG_INPUT_GPIO_VIBRA                         policy<{'arm64': 'n'}>
+CONFIG_INPUT_HISI_POWERKEY                      policy<{'arm64': '-'}>
+CONFIG_INPUT_IMS_PCU                            policy<{'arm64': 'n'}>
+CONFIG_INPUT_JOYDEV                             policy<{'arm64': 'n'}>
+CONFIG_INPUT_JOYSTICK                           policy<{'arm64': 'n'}>
+CONFIG_INPUT_KEYSPAN_REMOTE                     policy<{'arm64': 'n'}>
+CONFIG_INPUT_KXTJ9                              policy<{'arm64': 'n'}>
+CONFIG_INPUT_KXTJ9_POLLED_MODE                  policy<{'arm64': '-'}>
+CONFIG_INPUT_LEDS                               policy<{'arm64': 'y'}>
+CONFIG_INPUT_MATRIXKMAP                         policy<{'arm64': 'n'}>
+CONFIG_INPUT_MAX77650_ONKEY                     policy<{'arm64': '-'}>
+CONFIG_INPUT_MAX77693_HAPTIC                    policy<{'arm64': '-'}>
+CONFIG_INPUT_MAX8925_ONKEY                      policy<{'arm64': '-'}>
+CONFIG_INPUT_MAX8997_HAPTIC                     policy<{'arm64': '-'}>
+CONFIG_INPUT_MC13783_PWRBUTTON                  policy<{'arm64': '-'}>
+CONFIG_INPUT_MMA8450                            policy<{'arm64': 'n'}>
+CONFIG_INPUT_MOUSE                              policy<{'arm64': 'n'}>
+CONFIG_INPUT_MOUSEDEV                           policy<{'arm64': 'n'}>
+CONFIG_INPUT_MOUSEDEV_PSAUX                     policy<{'arm64': '-'}>
+CONFIG_INPUT_MOUSEDEV_SCREEN_X                  policy<{'arm64': '-'}>
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y                  policy<{'arm64': '-'}>
+CONFIG_INPUT_MSM_VIBRATOR                       policy<{'arm64': 'n'}>
+CONFIG_INPUT_PALMAS_PWRBUTTON                   policy<{'arm64': '-'}>
+CONFIG_INPUT_PCAP                               policy<{'arm64': '-'}>
+CONFIG_INPUT_PCF50633_PMU                       policy<{'arm64': '-'}>
+CONFIG_INPUT_PCF8574                            policy<{'arm64': 'n'}>
+CONFIG_INPUT_PM8941_PWRKEY                      policy<{'arm64': '-'}>
+CONFIG_INPUT_PM8XXX_VIBRATOR                    policy<{'arm64': '-'}>
+CONFIG_INPUT_POLLDEV                            policy<{'arm64': 'y'}>
+CONFIG_INPUT_POWERMATE                          policy<{'arm64': 'n'}>
+CONFIG_INPUT_PWM_BEEPER                         policy<{'arm64': '-'}>
+CONFIG_INPUT_PWM_VIBRA                          policy<{'arm64': '-'}>
+CONFIG_INPUT_RAVE_SP_PWRBUTTON                  policy<{'arm64': '-'}>
+CONFIG_INPUT_REGULATOR_HAPTIC                   policy<{'arm64': 'n'}>
+CONFIG_INPUT_RETU_PWRBUTTON                     policy<{'arm64': '-'}>
+CONFIG_INPUT_RK805_PWRKEY                       policy<{'arm64': '-'}>
+CONFIG_INPUT_SC27XX_VIBRA                       policy<{'arm64': '-'}>
+CONFIG_INPUT_SOC_BUTTON_ARRAY                   policy<{'arm64': '-'}>
+CONFIG_INPUT_SPARSEKMAP                         policy<{'arm64': 'n'}>
+CONFIG_INPUT_STPMIC1_ONKEY                      policy<{'arm64': '-'}>
+CONFIG_INPUT_TABLET                             policy<{'arm64': 'n'}>
+CONFIG_INPUT_TOUCHSCREEN                        policy<{'arm64': 'n'}>
+CONFIG_INPUT_TPS65218_PWRBUTTON                 policy<{'arm64': '-'}>
+CONFIG_INPUT_TWL4030_PWRBUTTON                  policy<{'arm64': '-'}>
+CONFIG_INPUT_TWL4030_VIBRA                      policy<{'arm64': '-'}>
+CONFIG_INPUT_TWL6040_VIBRA                      policy<{'arm64': '-'}>
+CONFIG_INPUT_WM831X_ON                          policy<{'arm64': '-'}>
+CONFIG_INPUT_XEN_KBDDEV_FRONTEND                policy<{'arm64': 'y'}>
+CONFIG_INPUT_YEALINK                            policy<{'arm64': 'n'}>
+CONFIG_INTEGRITY_ASYMMETRIC_KEYS                policy<{'arm64': '-'}>
+CONFIG_INTEGRITY_SIGNATURE                      policy<{'arm64': 'n'}>
+CONFIG_INTEGRITY_TRUSTED_KEYRING                policy<{'arm64': '-'}>
+CONFIG_INTEL_IDMA64                             policy<{'arm64': 'n'}>
+CONFIG_INTEL_STRATIX10_RSU                      policy<{'arm64': '-'}>
+CONFIG_INTEL_STRATIX10_SERVICE                  policy<{'arm64': '-'}>
+CONFIG_INTEL_TH                                 policy<{'arm64': 'n'}>
+CONFIG_INTEL_TH_ACPI                            policy<{'arm64': '-'}>
+CONFIG_INTEL_TH_DEBUG                           policy<{'arm64': '-'}>
+CONFIG_INTEL_TH_GTH                             policy<{'arm64': '-'}>
+CONFIG_INTEL_TH_MSU                             policy<{'arm64': '-'}>
+CONFIG_INTEL_TH_PCI                             policy<{'arm64': '-'}>
+CONFIG_INTEL_TH_PTI                             policy<{'arm64': '-'}>
+CONFIG_INTEL_TH_STH                             policy<{'arm64': '-'}>
+CONFIG_INTEL_XWAY_PHY                           policy<{'arm64': 'n'}>
+CONFIG_INTERCONNECT                             policy<{'arm64': 'n'}>
+CONFIG_INTERCONNECT_QCOM                        policy<{'arm64': '-'}>
+CONFIG_INTERCONNECT_QCOM_QCS404                 policy<{'arm64': '-'}>
+CONFIG_INTERCONNECT_QCOM_SDM845                 policy<{'arm64': '-'}>
+CONFIG_INTERCONNECT_QCOM_SMD_RPM                policy<{'arm64': '-'}>
+CONFIG_INTERVAL_TREE                            policy<{'arm64': '-'}>
+CONFIG_INV_MPU6050_I2C                          policy<{'arm64': 'n'}>
+CONFIG_INV_MPU6050_IIO                          policy<{'arm64': '-'}>
+CONFIG_INV_MPU6050_SPI                          policy<{'arm64': 'n'}>
+CONFIG_IOMMU_IO_PGTABLE                         policy<{'arm64': '-'}>
+CONFIG_IOMMU_IO_PGTABLE_LPAE                    policy<{'arm64': 'n'}>
+CONFIG_IOMMU_IO_PGTABLE_LPAE_SELFTEST           policy<{'arm64': '-'}>
+CONFIG_ION                                      policy<{'arm64': 'y'}>
+CONFIG_IONIC                                    policy<{'arm64': 'n'}>
+CONFIG_ION_CMA_HEAP                             policy<{'arm64': 'y'}>
+CONFIG_ION_SYSTEM_HEAP                          policy<{'arm64': 'y'}>
+CONFIG_IOSCHED_BFQ                              policy<{'arm64': 'n'}>
+CONFIG_IP6_NF_FILTER                            policy<{'arm64': 'y'}>
+CONFIG_IP6_NF_IPTABLES                          policy<{'arm64': 'y'}>
+CONFIG_IP6_NF_MANGLE                            policy<{'arm64': 'y'}>
+CONFIG_IP6_NF_MATCH_AH                          policy<{'arm64': 'n'}>
+CONFIG_IP6_NF_MATCH_EUI64                       policy<{'arm64': 'n'}>
+CONFIG_IP6_NF_MATCH_FRAG                        policy<{'arm64': 'n'}>
+CONFIG_IP6_NF_MATCH_HL                          policy<{'arm64': 'n'}>
+CONFIG_IP6_NF_MATCH_IPV6HEADER                  policy<{'arm64': 'n'}>
+CONFIG_IP6_NF_MATCH_MH                          policy<{'arm64': 'n'}>
+CONFIG_IP6_NF_MATCH_OPTS                        policy<{'arm64': 'n'}>
+CONFIG_IP6_NF_MATCH_RPFILTER                    policy<{'arm64': 'n'}>
+CONFIG_IP6_NF_MATCH_RT                          policy<{'arm64': 'n'}>
+CONFIG_IP6_NF_MATCH_SRH                         policy<{'arm64': 'n'}>
+CONFIG_IP6_NF_RAW                               policy<{'arm64': 'n'}>
+CONFIG_IP6_NF_SECURITY                          policy<{'arm64': 'n'}>
+CONFIG_IP6_NF_TARGET_HL                         policy<{'arm64': 'n'}>
+CONFIG_IP6_NF_TARGET_NPT                        policy<{'arm64': 'n'}>
+CONFIG_IP6_NF_TARGET_REJECT                     policy<{'arm64': 'y'}>
+CONFIG_IP6_NF_TARGET_SYNPROXY                   policy<{'arm64': 'n'}>
+CONFIG_IPACK_BUS                                policy<{'arm64': 'n'}>
+CONFIG_IPMB_DEVICE_INTERFACE                    policy<{'arm64': '-'}>
+CONFIG_IPMI_DEVICE_INTERFACE                    policy<{'arm64': '-'}>
+CONFIG_IPMI_DMI_DECODE                          policy<{'arm64': '-'}>
+CONFIG_IPMI_HANDLER                             policy<{'arm64': 'n'}>
+CONFIG_IPMI_PANIC_EVENT                         policy<{'arm64': '-'}>
+CONFIG_IPMI_PLAT_DATA                           policy<{'arm64': '-'}>
+CONFIG_IPMI_POWEROFF                            policy<{'arm64': '-'}>
+CONFIG_IPMI_SI                                  policy<{'arm64': '-'}>
+CONFIG_IPMI_SSIF                                policy<{'arm64': '-'}>
+CONFIG_IPMI_WATCHDOG                            policy<{'arm64': '-'}>
+CONFIG_IPQ_GCC_4019                             policy<{'arm64': '-'}>
+CONFIG_IPQ_GCC_806X                             policy<{'arm64': '-'}>
+CONFIG_IPQ_GCC_8074                             policy<{'arm64': '-'}>
+CONFIG_IPQ_LCC_806X                             policy<{'arm64': '-'}>
+CONFIG_IPV6_FOU                                 policy<{'arm64': '-'}>
+CONFIG_IPV6_FOU_TUNNEL                          policy<{'arm64': '-'}>
+CONFIG_IPV6_GRE                                 policy<{'arm64': '-'}>
+CONFIG_IPV6_ILA                                 policy<{'arm64': 'n'}>
+CONFIG_IPV6_MIP6                                policy<{'arm64': 'n'}>
+CONFIG_IPV6_MROUTE                              policy<{'arm64': 'n'}>
+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES              policy<{'arm64': '-'}>
+CONFIG_IPV6_PIMSM_V2                            policy<{'arm64': '-'}>
+CONFIG_IPV6_ROUTER_PREF                         policy<{'arm64': 'n'}>
+CONFIG_IPV6_ROUTE_INFO                          policy<{'arm64': '-'}>
+CONFIG_IPV6_SEG6_BPF                            policy<{'arm64': '-'}>
+CONFIG_IPV6_SEG6_HMAC                           policy<{'arm64': 'n'}>
+CONFIG_IPV6_SEG6_LWTUNNEL                       policy<{'arm64': 'n'}>
+CONFIG_IPV6_SIT                                 policy<{'arm64': 'y'}>
+CONFIG_IPV6_SIT_6RD                             policy<{'arm64': 'n'}>
+CONFIG_IPV6_SUBTREES                            policy<{'arm64': 'n'}>
+CONFIG_IPV6_TUNNEL                              policy<{'arm64': 'n'}>
+CONFIG_IPV6_VTI                                 policy<{'arm64': 'n'}>
+CONFIG_IPVLAN                                   policy<{'arm64': 'n'}>
+CONFIG_IPVLAN_L3S                               policy<{'arm64': '-'}>
+CONFIG_IPVTAP                                   policy<{'arm64': '-'}>
+CONFIG_IPW2100                                  policy<{'arm64': 'n'}>
+CONFIG_IPW2100_DEBUG                            policy<{'arm64': '-'}>
+CONFIG_IPW2100_MONITOR                          policy<{'arm64': '-'}>
+CONFIG_IPW2200                                  policy<{'arm64': 'n'}>
+CONFIG_IPW2200_DEBUG                            policy<{'arm64': '-'}>
+CONFIG_IPW2200_MONITOR                          policy<{'arm64': '-'}>
+CONFIG_IPW2200_PROMISCUOUS                      policy<{'arm64': '-'}>
+CONFIG_IPW2200_QOS                              policy<{'arm64': '-'}>
+CONFIG_IPW2200_RADIOTAP                         policy<{'arm64': '-'}>
+CONFIG_IP_DCCP                                  policy<{'arm64': 'n'}>
+CONFIG_IP_DCCP_CCID2_DEBUG                      policy<{'arm64': '-'}>
+CONFIG_IP_DCCP_CCID3                            policy<{'arm64': '-'}>
+CONFIG_IP_DCCP_DEBUG                            policy<{'arm64': '-'}>
+CONFIG_IP_FIB_TRIE_STATS                        policy<{'arm64': 'n'}>
+CONFIG_IP_MROUTE                                policy<{'arm64': 'n'}>
+CONFIG_IP_MROUTE_COMMON                         policy<{'arm64': '-'}>
+CONFIG_IP_MROUTE_MULTIPLE_TABLES                policy<{'arm64': '-'}>
+CONFIG_IP_NF_ARPFILTER                          policy<{'arm64': '-'}>
+CONFIG_IP_NF_ARPTABLES                          policy<{'arm64': 'n'}>
+CONFIG_IP_NF_ARP_MANGLE                         policy<{'arm64': '-'}>
+CONFIG_IP_NF_IPTABLES                           policy<{'arm64': 'y'}>
+CONFIG_IP_NF_MANGLE                             policy<{'arm64': 'y'}>
+CONFIG_IP_NF_MATCH_AH                           policy<{'arm64': 'n'}>
+CONFIG_IP_NF_MATCH_ECN                          policy<{'arm64': 'n'}>
+CONFIG_IP_NF_MATCH_RPFILTER                     policy<{'arm64': 'n'}>
+CONFIG_IP_NF_MATCH_TTL                          policy<{'arm64': 'n'}>
+CONFIG_IP_NF_RAW                                policy<{'arm64': 'n'}>
+CONFIG_IP_NF_SECURITY                           policy<{'arm64': 'n'}>
+CONFIG_IP_NF_TARGET_CLUSTERIP                   policy<{'arm64': 'n'}>
+CONFIG_IP_NF_TARGET_ECN                         policy<{'arm64': 'n'}>
+CONFIG_IP_NF_TARGET_NETMAP                      policy<{'arm64': 'n'}>
+CONFIG_IP_NF_TARGET_REDIRECT                    policy<{'arm64': 'n'}>
+CONFIG_IP_NF_TARGET_SYNPROXY                    policy<{'arm64': 'n'}>
+CONFIG_IP_NF_TARGET_TTL                         policy<{'arm64': 'n'}>
+CONFIG_IP_PIMSM_V1                              policy<{'arm64': '-'}>
+CONFIG_IP_PIMSM_V2                              policy<{'arm64': '-'}>
+CONFIG_IP_PNP_BOOTP                             policy<{'arm64': 'y'}>
+CONFIG_IP_PNP_DHCP                              policy<{'arm64': 'y'}>
+CONFIG_IP_PNP_RARP                              policy<{'arm64': 'y'}>
+CONFIG_IP_ROUTE_CLASSID                         policy<{'arm64': '-'}>
+CONFIG_IP_ROUTE_MULTIPATH                       policy<{'arm64': 'n'}>
+CONFIG_IP_ROUTE_VERBOSE                         policy<{'arm64': 'n'}>
+CONFIG_IP_SCTP                                  policy<{'arm64': 'n'}>
+CONFIG_IP_SET                                   policy<{'arm64': 'n'}>
+CONFIG_IP_SET_BITMAP_IP                         policy<{'arm64': '-'}>
+CONFIG_IP_SET_BITMAP_IPMAC                      policy<{'arm64': '-'}>
+CONFIG_IP_SET_BITMAP_PORT                       policy<{'arm64': '-'}>
+CONFIG_IP_SET_HASH_IP                           policy<{'arm64': '-'}>
+CONFIG_IP_SET_HASH_IPMAC                        policy<{'arm64': '-'}>
+CONFIG_IP_SET_HASH_IPMARK                       policy<{'arm64': '-'}>
+CONFIG_IP_SET_HASH_IPPORT                       policy<{'arm64': '-'}>
+CONFIG_IP_SET_HASH_IPPORTIP                     policy<{'arm64': '-'}>
+CONFIG_IP_SET_HASH_IPPORTNET                    policy<{'arm64': '-'}>
+CONFIG_IP_SET_HASH_MAC                          policy<{'arm64': '-'}>
+CONFIG_IP_SET_HASH_NET                          policy<{'arm64': '-'}>
+CONFIG_IP_SET_HASH_NETIFACE                     policy<{'arm64': '-'}>
+CONFIG_IP_SET_HASH_NETNET                       policy<{'arm64': '-'}>
+CONFIG_IP_SET_HASH_NETPORT                      policy<{'arm64': '-'}>
+CONFIG_IP_SET_HASH_NETPORTNET                   policy<{'arm64': '-'}>
+CONFIG_IP_SET_LIST_SET                          policy<{'arm64': '-'}>
+CONFIG_IP_SET_MAX                               policy<{'arm64': '-'}>
+CONFIG_IP_VS                                    policy<{'arm64': 'n'}>
+CONFIG_IP_VS_DEBUG                              policy<{'arm64': '-'}>
+CONFIG_IP_VS_DH                                 policy<{'arm64': '-'}>
+CONFIG_IP_VS_FO                                 policy<{'arm64': '-'}>
+CONFIG_IP_VS_FTP                                policy<{'arm64': '-'}>
+CONFIG_IP_VS_IPV6                               policy<{'arm64': '-'}>
+CONFIG_IP_VS_LBLC                               policy<{'arm64': '-'}>
+CONFIG_IP_VS_LBLCR                              policy<{'arm64': '-'}>
+CONFIG_IP_VS_LC                                 policy<{'arm64': '-'}>
+CONFIG_IP_VS_MH                                 policy<{'arm64': '-'}>
+CONFIG_IP_VS_MH_TAB_INDEX                       policy<{'arm64': '-'}>
+CONFIG_IP_VS_NFCT                               policy<{'arm64': '-'}>
+CONFIG_IP_VS_NQ                                 policy<{'arm64': '-'}>
+CONFIG_IP_VS_OVF                                policy<{'arm64': '-'}>
+CONFIG_IP_VS_PE_SIP                             policy<{'arm64': '-'}>
+CONFIG_IP_VS_PROTO_AH                           policy<{'arm64': '-'}>
+CONFIG_IP_VS_PROTO_AH_ESP                       policy<{'arm64': '-'}>
+CONFIG_IP_VS_PROTO_ESP                          policy<{'arm64': '-'}>
+CONFIG_IP_VS_PROTO_SCTP                         policy<{'arm64': '-'}>
+CONFIG_IP_VS_PROTO_TCP                          policy<{'arm64': '-'}>
+CONFIG_IP_VS_PROTO_UDP                          policy<{'arm64': '-'}>
+CONFIG_IP_VS_RR                                 policy<{'arm64': '-'}>
+CONFIG_IP_VS_SED                                policy<{'arm64': '-'}>
+CONFIG_IP_VS_SH                                 policy<{'arm64': '-'}>
+CONFIG_IP_VS_SH_TAB_BITS                        policy<{'arm64': '-'}>
+CONFIG_IP_VS_TAB_BITS                           policy<{'arm64': '-'}>
+CONFIG_IP_VS_WLC                                policy<{'arm64': '-'}>
+CONFIG_IP_VS_WRR                                policy<{'arm64': '-'}>
+CONFIG_IRQ_BYPASS_MANAGER                       policy<{'arm64': '-'}>
+CONFIG_IRQ_FASTEOI_HIERARCHY_HANDLERS           policy<{'arm64': '-'}>
+CONFIG_IRQ_POLL                                 policy<{'arm64': 'n'}>
+CONFIG_IRQ_SIM                                  policy<{'arm64': 'y'}>
+CONFIG_IR_ENE                                   policy<{'arm64': '-'}>
+CONFIG_IR_FINTEK                                policy<{'arm64': '-'}>
+CONFIG_IR_GPIO_CIR                              policy<{'arm64': '-'}>
+CONFIG_IR_GPIO_TX                               policy<{'arm64': '-'}>
+CONFIG_IR_HIX5HD2                               policy<{'arm64': '-'}>
+CONFIG_IR_IGORPLUGUSB                           policy<{'arm64': '-'}>
+CONFIG_IR_IGUANA                                policy<{'arm64': '-'}>
+CONFIG_IR_IMON                                  policy<{'arm64': '-'}>
+CONFIG_IR_IMON_DECODER                          policy<{'arm64': '-'}>
+CONFIG_IR_IMON_RAW                              policy<{'arm64': '-'}>
+CONFIG_IR_ITE_CIR                               policy<{'arm64': '-'}>
+CONFIG_IR_JVC_DECODER                           policy<{'arm64': '-'}>
+CONFIG_IR_MCEUSB                                policy<{'arm64': '-'}>
+CONFIG_IR_MCE_KBD_DECODER                       policy<{'arm64': '-'}>
+CONFIG_IR_MESON                                 policy<{'arm64': '-'}>
+CONFIG_IR_MTK                                   policy<{'arm64': '-'}>
+CONFIG_IR_NEC_DECODER                           policy<{'arm64': '-'}>
+CONFIG_IR_NUVOTON                               policy<{'arm64': '-'}>
+CONFIG_IR_PWM_TX                                policy<{'arm64': '-'}>
+CONFIG_IR_RC5_DECODER                           policy<{'arm64': '-'}>
+CONFIG_IR_RC6_DECODER                           policy<{'arm64': '-'}>
+CONFIG_IR_RCMM_DECODER                          policy<{'arm64': '-'}>
+CONFIG_IR_REDRAT3                               policy<{'arm64': '-'}>
+CONFIG_IR_SANYO_DECODER                         policy<{'arm64': '-'}>
+CONFIG_IR_SERIAL                                policy<{'arm64': '-'}>
+CONFIG_IR_SERIAL_TRANSMITTER                    policy<{'arm64': '-'}>
+CONFIG_IR_SHARP_DECODER                         policy<{'arm64': '-'}>
+CONFIG_IR_SIR                                   policy<{'arm64': '-'}>
+CONFIG_IR_SONY_DECODER                          policy<{'arm64': '-'}>
+CONFIG_IR_SPI                                   policy<{'arm64': '-'}>
+CONFIG_IR_STREAMZAP                             policy<{'arm64': '-'}>
+CONFIG_IR_SUNXI                                 policy<{'arm64': '-'}>
+CONFIG_IR_TTUSBIR                               policy<{'arm64': '-'}>
+CONFIG_IR_XMP_DECODER                           policy<{'arm64': '-'}>
+CONFIG_ISCSI_BOOT_SYSFS                         policy<{'arm64': 'n'}>
+CONFIG_ISCSI_IBFT                               policy<{'arm64': '-'}>
+CONFIG_ISCSI_TARGET                             policy<{'arm64': '-'}>
+CONFIG_ISCSI_TARGET_CXGB4                       policy<{'arm64': '-'}>
+CONFIG_ISCSI_TCP                                policy<{'arm64': 'n'}>
+CONFIG_ISDN                                     policy<{'arm64': 'n'}>
+CONFIG_ISDN_CAPI                                policy<{'arm64': '-'}>
+CONFIG_ISDN_CAPI_CAPI20                         policy<{'arm64': '-'}>
+CONFIG_ISDN_CAPI_MIDDLEWARE                     policy<{'arm64': '-'}>
+CONFIG_ISDN_DRV_AVMB1_B1PCI                     policy<{'arm64': '-'}>
+CONFIG_ISDN_DRV_AVMB1_B1PCIV4                   policy<{'arm64': '-'}>
+CONFIG_ISDN_DRV_AVMB1_C4                        policy<{'arm64': '-'}>
+CONFIG_ISDN_DRV_AVMB1_T1PCI                     policy<{'arm64': '-'}>
+CONFIG_ISDN_DRV_GIGASET                         policy<{'arm64': '-'}>
+CONFIG_ISI                                      policy<{'arm64': '-'}>
+CONFIG_ISL29003                                 policy<{'arm64': 'n'}>
+CONFIG_ISL29020                                 policy<{'arm64': 'n'}>
+CONFIG_ISL29125                                 policy<{'arm64': 'n'}>
+CONFIG_ISL29501                                 policy<{'arm64': 'n'}>
+CONFIG_ISO9660_FS                               policy<{'arm64': 'y'}>
+CONFIG_ITG3200                                  policy<{'arm64': 'n'}>
+CONFIG_IWL3945                                  policy<{'arm64': 'n'}>
+CONFIG_IWL4965                                  policy<{'arm64': 'n'}>
+CONFIG_IWLDVM                                   policy<{'arm64': '-'}>
+CONFIG_IWLEGACY                                 policy<{'arm64': '-'}>
+CONFIG_IWLEGACY_DEBUG                           policy<{'arm64': '-'}>
+CONFIG_IWLEGACY_DEBUGFS                         policy<{'arm64': '-'}>
+CONFIG_IWLMVM                                   policy<{'arm64': '-'}>
+CONFIG_IWLWIFI                                  policy<{'arm64': 'n'}>
+CONFIG_IWLWIFI_BCAST_FILTERING                  policy<{'arm64': '-'}>
+CONFIG_IWLWIFI_DEBUG                            policy<{'arm64': '-'}>
+CONFIG_IWLWIFI_DEBUGFS                          policy<{'arm64': '-'}>
+CONFIG_IWLWIFI_DEVICE_TRACING                   policy<{'arm64': '-'}>
+CONFIG_IWLWIFI_LEDS                             policy<{'arm64': '-'}>
+CONFIG_IWLWIFI_OPMODE_MODULAR                   policy<{'arm64': '-'}>
+CONFIG_IXGB                                     policy<{'arm64': 'n'}>
+CONFIG_IXGBE                                    policy<{'arm64': 'n'}>
+CONFIG_IXGBEVF                                  policy<{'arm64': 'n'}>
+CONFIG_IXGBEVF_IPSEC                            policy<{'arm64': '-'}>
+CONFIG_IXGBE_DCB                                policy<{'arm64': '-'}>
+CONFIG_IXGBE_HWMON                              policy<{'arm64': '-'}>
+CONFIG_IXGBE_IPSEC                              policy<{'arm64': '-'}>
+CONFIG_JFFS2_CMODE_FAVOURLZO                    policy<{'arm64': 'n'}>
+CONFIG_JFFS2_CMODE_PRIORITY                     policy<{'arm64': 'y'}>
+CONFIG_JFFS2_FS                                 policy<{'arm64': 'y'}>
+CONFIG_JFFS2_RUBIN                              policy<{'arm64': 'y'}>
+CONFIG_JFFS2_SUMMARY                            policy<{'arm64': 'y'}>
+CONFIG_JFS_DEBUG                                policy<{'arm64': '-'}>
+CONFIG_JFS_FS                                   policy<{'arm64': 'n'}>
+CONFIG_JFS_POSIX_ACL                            policy<{'arm64': '-'}>
+CONFIG_JFS_SECURITY                             policy<{'arm64': '-'}>
+CONFIG_JFS_STATISTICS                           policy<{'arm64': '-'}>
+CONFIG_JME                                      policy<{'arm64': 'n'}>
+CONFIG_JOYSTICK_A3D                             policy<{'arm64': '-'}>
+CONFIG_JOYSTICK_ADI                             policy<{'arm64': '-'}>
+CONFIG_JOYSTICK_ANALOG                          policy<{'arm64': '-'}>
+CONFIG_JOYSTICK_AS5011                          policy<{'arm64': '-'}>
+CONFIG_JOYSTICK_COBRA                           policy<{'arm64': '-'}>
+CONFIG_JOYSTICK_DB9                             policy<{'arm64': '-'}>
+CONFIG_JOYSTICK_FSIA6B                          policy<{'arm64': '-'}>
+CONFIG_JOYSTICK_GAMECON                         policy<{'arm64': '-'}>
+CONFIG_JOYSTICK_GF2K                            policy<{'arm64': '-'}>
+CONFIG_JOYSTICK_GRIP                            policy<{'arm64': '-'}>
+CONFIG_JOYSTICK_GRIP_MP                         policy<{'arm64': '-'}>
+CONFIG_JOYSTICK_GUILLEMOT                       policy<{'arm64': '-'}>
+CONFIG_JOYSTICK_IFORCE                          policy<{'arm64': '-'}>
+CONFIG_JOYSTICK_IFORCE_232                      policy<{'arm64': '-'}>
+CONFIG_JOYSTICK_IFORCE_USB                      policy<{'arm64': '-'}>
+CONFIG_JOYSTICK_INTERACT                        policy<{'arm64': '-'}>
+CONFIG_JOYSTICK_JOYDUMP                         policy<{'arm64': '-'}>
+CONFIG_JOYSTICK_MAGELLAN                        policy<{'arm64': '-'}>
+CONFIG_JOYSTICK_PSXPAD_SPI                      policy<{'arm64': '-'}>
+CONFIG_JOYSTICK_PSXPAD_SPI_FF                   policy<{'arm64': '-'}>
+CONFIG_JOYSTICK_PXRC                            policy<{'arm64': '-'}>
+CONFIG_JOYSTICK_SIDEWINDER                      policy<{'arm64': '-'}>
+CONFIG_JOYSTICK_SPACEBALL                       policy<{'arm64': '-'}>
+CONFIG_JOYSTICK_SPACEORB                        policy<{'arm64': '-'}>
+CONFIG_JOYSTICK_STINGER                         policy<{'arm64': '-'}>
+CONFIG_JOYSTICK_TMDC                            policy<{'arm64': '-'}>
+CONFIG_JOYSTICK_TURBOGRAFX                      policy<{'arm64': '-'}>
+CONFIG_JOYSTICK_TWIDJOY                         policy<{'arm64': '-'}>
+CONFIG_JOYSTICK_WALKERA0701                     policy<{'arm64': '-'}>
+CONFIG_JOYSTICK_WARRIOR                         policy<{'arm64': '-'}>
+CONFIG_JOYSTICK_XPAD                            policy<{'arm64': '-'}>
+CONFIG_JOYSTICK_XPAD_FF                         policy<{'arm64': '-'}>
+CONFIG_JOYSTICK_XPAD_LEDS                       policy<{'arm64': '-'}>
+CONFIG_JOYSTICK_ZHENHUA                         policy<{'arm64': '-'}>
+CONFIG_JSA1212                                  policy<{'arm64': 'n'}>
+CONFIG_JUMP_LABEL                               policy<{'arm64': 'n'}>
+CONFIG_K3_DMA                                   policy<{'arm64': '-'}>
+CONFIG_KALLSYMS_ALL                             policy<{'arm64': 'n'}>
+CONFIG_KARMA_PARTITION                          policy<{'arm64': '-'}>
+CONFIG_KDB_CONTINUE_CATASTROPHIC                policy<{'arm64': '-'}>
+CONFIG_KDB_DEFAULT_ENABLE                       policy<{'arm64': '-'}>
+CONFIG_KDB_KEYBOARD                             policy<{'arm64': '-'}>
+CONFIG_KEMPLD_WDT                               policy<{'arm64': '-'}>
+CONFIG_KEXEC_FILE                               policy<{'arm64': 'n'}>
+CONFIG_KEXEC_IMAGE_VERIFY_SIG                   policy<{'arm64': '-'}>
+CONFIG_KEXEC_SIG                                policy<{'arm64': '-'}>
+CONFIG_KEYBOARD_ADC                             policy<{'arm64': 'n'}>
+CONFIG_KEYBOARD_ADP5520                         policy<{'arm64': '-'}>
+CONFIG_KEYBOARD_ADP5588                         policy<{'arm64': 'n'}>
+CONFIG_KEYBOARD_ADP5589                         policy<{'arm64': 'n'}>
+CONFIG_KEYBOARD_BCM                             policy<{'arm64': 'n'}>
+CONFIG_KEYBOARD_CAP11XX                         policy<{'arm64': 'n'}>
+CONFIG_KEYBOARD_CROS_EC                         policy<{'arm64': '-'}>
+CONFIG_KEYBOARD_DLINK_DIR685                    policy<{'arm64': 'n'}>
+CONFIG_KEYBOARD_GPIO                            policy<{'arm64': 'y'}>
+CONFIG_KEYBOARD_GPIO_POLLED                     policy<{'arm64': 'y'}>
+CONFIG_KEYBOARD_IMX                             policy<{'arm64': '-'}>
+CONFIG_KEYBOARD_LKKBD                           policy<{'arm64': 'n'}>
+CONFIG_KEYBOARD_LM8323                          policy<{'arm64': 'n'}>
+CONFIG_KEYBOARD_LM8333                          policy<{'arm64': 'n'}>
+CONFIG_KEYBOARD_MATRIX                          policy<{'arm64': 'n'}>
+CONFIG_KEYBOARD_MAX7359                         policy<{'arm64': 'n'}>
+CONFIG_KEYBOARD_MCS                             policy<{'arm64': 'n'}>
+CONFIG_KEYBOARD_MPR121                          policy<{'arm64': 'n'}>
+CONFIG_KEYBOARD_MTK_PMIC                        policy<{'arm64': '-'}>
+CONFIG_KEYBOARD_NEWTON                          policy<{'arm64': 'n'}>
+CONFIG_KEYBOARD_OMAP4                           policy<{'arm64': 'n'}>
+CONFIG_KEYBOARD_OPENCORES                       policy<{'arm64': 'n'}>
+CONFIG_KEYBOARD_QT1050                          policy<{'arm64': 'n'}>
+CONFIG_KEYBOARD_QT1070                          policy<{'arm64': 'n'}>
+CONFIG_KEYBOARD_QT2160                          policy<{'arm64': 'n'}>
+CONFIG_KEYBOARD_SAMSUNG                         policy<{'arm64': 'n'}>
+CONFIG_KEYBOARD_SNVS_PWRKEY                     policy<{'arm64': '-'}>
+CONFIG_KEYBOARD_STMPE                           policy<{'arm64': '-'}>
+CONFIG_KEYBOARD_STOWAWAY                        policy<{'arm64': 'n'}>
+CONFIG_KEYBOARD_SUN4I_LRADC                     policy<{'arm64': '-'}>
+CONFIG_KEYBOARD_SUNKBD                          policy<{'arm64': 'n'}>
+CONFIG_KEYBOARD_TC3589X                         policy<{'arm64': '-'}>
+CONFIG_KEYBOARD_TCA6416                         policy<{'arm64': 'n'}>
+CONFIG_KEYBOARD_TCA8418                         policy<{'arm64': 'n'}>
+CONFIG_KEYBOARD_TM2_TOUCHKEY                    policy<{'arm64': 'n'}>
+CONFIG_KEYBOARD_TWL4030                         policy<{'arm64': '-'}>
+CONFIG_KEYBOARD_XTKBD                           policy<{'arm64': 'n'}>
+CONFIG_KEYS_REQUEST_CACHE                       policy<{'arm64': 'n'}>
+CONFIG_KEY_DH_OPERATIONS                        policy<{'arm64': 'n'}>
+CONFIG_KGDB                                     policy<{'arm64': 'n'}>
+CONFIG_KGDB_KDB                                 policy<{'arm64': '-'}>
+CONFIG_KGDB_TESTS                               policy<{'arm64': '-'}>
+CONFIG_KMX61                                    policy<{'arm64': 'n'}>
+CONFIG_KPC2000                                  policy<{'arm64': 'n'}>
+CONFIG_KPC2000_CORE                             policy<{'arm64': '-'}>
+CONFIG_KPC2000_DMA                              policy<{'arm64': '-'}>
+CONFIG_KPC2000_I2C                              policy<{'arm64': '-'}>
+CONFIG_KPC2000_SPI                              policy<{'arm64': '-'}>
+CONFIG_KPSS_XCC                                 policy<{'arm64': '-'}>
+CONFIG_KS7010                                   policy<{'arm64': 'n'}>
+CONFIG_KS8842                                   policy<{'arm64': 'n'}>
+CONFIG_KS8851                                   policy<{'arm64': 'n'}>
+CONFIG_KS8851_MLL                               policy<{'arm64': 'n'}>
+CONFIG_KSM                                      policy<{'arm64': 'n'}>
+CONFIG_KSZ884X_PCI                              policy<{'arm64': 'n'}>
+CONFIG_KVM_ARM_HOST                             policy<{'arm64': '-'}>
+CONFIG_KVM_ARM_PMU                              policy<{'arm64': '-'}>
+CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT        policy<{'arm64': '-'}>
+CONFIG_KVM_INDIRECT_VECTORS                     policy<{'arm64': '-'}>
+CONFIG_KVM_MMIO                                 policy<{'arm64': '-'}>
+CONFIG_KVM_VFIO                                 policy<{'arm64': '-'}>
+CONFIG_KXCJK1013                                policy<{'arm64': 'n'}>
+CONFIG_KXSD9                                    policy<{'arm64': 'n'}>
+CONFIG_KXSD9_I2C                                policy<{'arm64': '-'}>
+CONFIG_KXSD9_SPI                                policy<{'arm64': '-'}>
+CONFIG_L2TP                                     policy<{'arm64': 'n'}>
+CONFIG_L2TP_DEBUGFS                             policy<{'arm64': '-'}>
+CONFIG_L2TP_ETH                                 policy<{'arm64': '-'}>
+CONFIG_L2TP_IP                                  policy<{'arm64': '-'}>
+CONFIG_L2TP_V3                                  policy<{'arm64': '-'}>
+CONFIG_LAN743X                                  policy<{'arm64': 'n'}>
+CONFIG_LAPB                                     policy<{'arm64': 'n'}>
+CONFIG_LAPBETHER                                policy<{'arm64': '-'}>
+CONFIG_LATTICE_ECP3_CONFIG                      policy<{'arm64': 'n'}>
+CONFIG_LCD_AMS369FG06                           policy<{'arm64': '-'}>
+CONFIG_LCD_CLASS_DEVICE                         policy<{'arm64': 'n'}>
+CONFIG_LCD_HX8357                               policy<{'arm64': '-'}>
+CONFIG_LCD_ILI922X                              policy<{'arm64': '-'}>
+CONFIG_LCD_ILI9320                              policy<{'arm64': '-'}>
+CONFIG_LCD_L4F00242T03                          policy<{'arm64': '-'}>
+CONFIG_LCD_LMS283GF05                           policy<{'arm64': '-'}>
+CONFIG_LCD_LMS501KF03                           policy<{'arm64': '-'}>
+CONFIG_LCD_LTV350QV                             policy<{'arm64': '-'}>
+CONFIG_LCD_OTM3225A                             policy<{'arm64': '-'}>
+CONFIG_LCD_PLATFORM                             policy<{'arm64': '-'}>
+CONFIG_LCD_TDO24M                               policy<{'arm64': '-'}>
+CONFIG_LCD_VGG2432A4                            policy<{'arm64': '-'}>
+CONFIG_LDM_DEBUG                                policy<{'arm64': '-'}>
+CONFIG_LDM_PARTITION                            policy<{'arm64': '-'}>
+CONFIG_LEDS_88PM860X                            policy<{'arm64': '-'}>
+CONFIG_LEDS_AAT1290                             policy<{'arm64': '-'}>
+CONFIG_LEDS_ADP5520                             policy<{'arm64': '-'}>
+CONFIG_LEDS_AN30259A                            policy<{'arm64': 'n'}>
+CONFIG_LEDS_AS3645A                             policy<{'arm64': '-'}>
+CONFIG_LEDS_BCM6328                             policy<{'arm64': 'n'}>
+CONFIG_LEDS_BCM6358                             policy<{'arm64': 'n'}>
+CONFIG_LEDS_BD2802                              policy<{'arm64': 'n'}>
+CONFIG_LEDS_BLINKM                              policy<{'arm64': 'n'}>
+CONFIG_LEDS_BRIGHTNESS_HW_CHANGED               policy<{'arm64': 'n'}>
+CONFIG_LEDS_CLASS_FLASH                         policy<{'arm64': 'n'}>
+CONFIG_LEDS_CPCAP                               policy<{'arm64': '-'}>
+CONFIG_LEDS_CR0014114                           policy<{'arm64': 'n'}>
+CONFIG_LEDS_DA903X                              policy<{'arm64': '-'}>
+CONFIG_LEDS_DA9052                              policy<{'arm64': '-'}>
+CONFIG_LEDS_DAC124S085                          policy<{'arm64': 'n'}>
+CONFIG_LEDS_GPIO                                policy<{'arm64': 'y'}>
+CONFIG_LEDS_IS31FL319X                          policy<{'arm64': 'n'}>
+CONFIG_LEDS_IS31FL32XX                          policy<{'arm64': 'n'}>
+CONFIG_LEDS_KTD2692                             policy<{'arm64': '-'}>
+CONFIG_LEDS_LM3530                              policy<{'arm64': 'n'}>
+CONFIG_LEDS_LM3532                              policy<{'arm64': 'n'}>
+CONFIG_LEDS_LM3533                              policy<{'arm64': '-'}>
+CONFIG_LEDS_LM355x                              policy<{'arm64': 'n'}>
+CONFIG_LEDS_LM3601X                             policy<{'arm64': '-'}>
+CONFIG_LEDS_LM36274                             policy<{'arm64': '-'}>
+CONFIG_LEDS_LM3642                              policy<{'arm64': 'n'}>
+CONFIG_LEDS_LM3692X                             policy<{'arm64': 'n'}>
+CONFIG_LEDS_LM3697                              policy<{'arm64': '-'}>
+CONFIG_LEDS_LP3944                              policy<{'arm64': 'n'}>
+CONFIG_LEDS_LP3952                              policy<{'arm64': 'n'}>
+CONFIG_LEDS_LP5521                              policy<{'arm64': 'n'}>
+CONFIG_LEDS_LP5523                              policy<{'arm64': 'n'}>
+CONFIG_LEDS_LP5562                              policy<{'arm64': 'n'}>
+CONFIG_LEDS_LP55XX_COMMON                       policy<{'arm64': '-'}>
+CONFIG_LEDS_LP8501                              policy<{'arm64': 'n'}>
+CONFIG_LEDS_LP8788                              policy<{'arm64': '-'}>
+CONFIG_LEDS_LP8860                              policy<{'arm64': 'n'}>
+CONFIG_LEDS_LT3593                              policy<{'arm64': 'n'}>
+CONFIG_LEDS_MAX77650                            policy<{'arm64': '-'}>
+CONFIG_LEDS_MAX77693                            policy<{'arm64': '-'}>
+CONFIG_LEDS_MAX8997                             policy<{'arm64': '-'}>
+CONFIG_LEDS_MC13783                             policy<{'arm64': '-'}>
+CONFIG_LEDS_MENF21BMC                           policy<{'arm64': '-'}>
+CONFIG_LEDS_MLXREG                              policy<{'arm64': 'n'}>
+CONFIG_LEDS_MT6323                              policy<{'arm64': '-'}>
+CONFIG_LEDS_PCA9532                             policy<{'arm64': 'n'}>
+CONFIG_LEDS_PCA9532_GPIO                        policy<{'arm64': '-'}>
+CONFIG_LEDS_PCA955X                             policy<{'arm64': 'n'}>
+CONFIG_LEDS_PCA955X_GPIO                        policy<{'arm64': '-'}>
+CONFIG_LEDS_PCA963X                             policy<{'arm64': 'n'}>
+CONFIG_LEDS_PWM                                 policy<{'arm64': '-'}>
+CONFIG_LEDS_REGULATOR                           policy<{'arm64': 'n'}>
+CONFIG_LEDS_SC27XX_BLTC                         policy<{'arm64': '-'}>
+CONFIG_LEDS_SPI_BYTE                            policy<{'arm64': 'n'}>
+CONFIG_LEDS_SYSCON                              policy<{'arm64': '-'}>
+CONFIG_LEDS_TCA6507                             policy<{'arm64': 'n'}>
+CONFIG_LEDS_TI_LMU_COMMON                       policy<{'arm64': 'n'}>
+CONFIG_LEDS_TLC591XX                            policy<{'arm64': 'n'}>
+CONFIG_LEDS_TRIGGER_ACTIVITY                    policy<{'arm64': 'n'}>
+CONFIG_LEDS_TRIGGER_AUDIO                       policy<{'arm64': 'n'}>
+CONFIG_LEDS_TRIGGER_BACKLIGHT                   policy<{'arm64': 'y'}>
+CONFIG_LEDS_TRIGGER_CAMERA                      policy<{'arm64': 'y'}>
+CONFIG_LEDS_TRIGGER_DEFAULT_ON                  policy<{'arm64': 'y'}>
+CONFIG_LEDS_TRIGGER_DISK                        policy<{'arm64': 'n'}>
+CONFIG_LEDS_TRIGGER_GPIO                        policy<{'arm64': 'y'}>
+CONFIG_LEDS_TRIGGER_HEARTBEAT                   policy<{'arm64': 'y'}>
+CONFIG_LEDS_TRIGGER_MTD                         policy<{'arm64': 'n'}>
+CONFIG_LEDS_TRIGGER_NETDEV                      policy<{'arm64': 'n'}>
+CONFIG_LEDS_TRIGGER_ONESHOT                     policy<{'arm64': 'y'}>
+CONFIG_LEDS_TRIGGER_PANIC                       policy<{'arm64': 'n'}>
+CONFIG_LEDS_TRIGGER_PATTERN                     policy<{'arm64': 'n'}>
+CONFIG_LEDS_TRIGGER_TIMER                       policy<{'arm64': 'y'}>
+CONFIG_LEDS_TRIGGER_TRANSIENT                   policy<{'arm64': 'y'}>
+CONFIG_LEDS_USER                                policy<{'arm64': 'n'}>
+CONFIG_LEDS_WM831X_STATUS                       policy<{'arm64': '-'}>
+CONFIG_LEDS_WM8350                              policy<{'arm64': '-'}>
+CONFIG_LED_TRIGGER_PHY                          policy<{'arm64': 'n'}>
+CONFIG_LEGACY_PTY_COUNT                         policy<{'arm64': '256'}>
+CONFIG_LIB80211                                 policy<{'arm64': '-'}>
+CONFIG_LIB80211_CRYPT_CCMP                      policy<{'arm64': '-'}>
+CONFIG_LIB80211_CRYPT_TKIP                      policy<{'arm64': '-'}>
+CONFIG_LIB80211_CRYPT_WEP                       policy<{'arm64': '-'}>
+CONFIG_LIB80211_DEBUG                           policy<{'arm64': '-'}>
+CONFIG_LIBCRC32C                                policy<{'arm64': 'y'}>
+CONFIG_LIBERTAS                                 policy<{'arm64': 'n'}>
+CONFIG_LIBERTAS_DEBUG                           policy<{'arm64': '-'}>
+CONFIG_LIBERTAS_MESH                            policy<{'arm64': '-'}>
+CONFIG_LIBERTAS_SDIO                            policy<{'arm64': '-'}>
+CONFIG_LIBERTAS_SPI                             policy<{'arm64': '-'}>
+CONFIG_LIBERTAS_THINFIRM                        policy<{'arm64': 'n'}>
+CONFIG_LIBERTAS_THINFIRM_DEBUG                  policy<{'arm64': '-'}>
+CONFIG_LIBERTAS_THINFIRM_USB                    policy<{'arm64': '-'}>
+CONFIG_LIBERTAS_USB                             policy<{'arm64': '-'}>
+CONFIG_LIBFC                                    policy<{'arm64': '-'}>
+CONFIG_LIBFCOE                                  policy<{'arm64': '-'}>
+CONFIG_LIBIPW                                   policy<{'arm64': '-'}>
+CONFIG_LIBIPW_DEBUG                             policy<{'arm64': '-'}>
+CONFIG_LIBNVDIMM                                policy<{'arm64': 'n'}>
+CONFIG_LIDAR_LITE_V2                            policy<{'arm64': 'n'}>
+CONFIG_LIQUIDIO                                 policy<{'arm64': 'n'}>
+CONFIG_LIQUIDIO_VF                              policy<{'arm64': 'n'}>
+CONFIG_LIRC                                     policy<{'arm64': '-'}>
+CONFIG_LLC                                      policy<{'arm64': 'y'}>
+CONFIG_LLC2                                     policy<{'arm64': 'n'}>
+CONFIG_LMP91000                                 policy<{'arm64': 'n'}>
+CONFIG_LOAD_UEFI_KEYS                           policy<{'arm64': '-'}>
+CONFIG_LOCKD                                    policy<{'arm64': 'y'}>
+CONFIG_LOCKUP_DETECTOR                          policy<{'arm64': '-'}>
+CONFIG_LOCK_DOWN_IN_SECURE_BOOT                 policy<{'arm64': '-'}>
+CONFIG_LOGIG940_FF                              policy<{'arm64': '-'}>
+CONFIG_LOGIRUMBLEPAD2_FF                        policy<{'arm64': '-'}>
+CONFIG_LOGITECH_FF                              policy<{'arm64': '-'}>
+CONFIG_LOGIWHEELS_FF                            policy<{'arm64': '-'}>
+CONFIG_LOG_BUF_SHIFT                            policy<{'arm64': '16'}>
+CONFIG_LOOPBACK_TARGET                          policy<{'arm64': '-'}>
+CONFIG_LP8788_ADC                               policy<{'arm64': '-'}>
+CONFIG_LPC_ICH                                  policy<{'arm64': 'n'}>
+CONFIG_LPC_SCH                                  policy<{'arm64': 'n'}>
+CONFIG_LP_CONSOLE                               policy<{'arm64': '-'}>
+CONFIG_LRU_CACHE                                policy<{'arm64': '-'}>
+CONFIG_LSI_ET1011C_PHY                          policy<{'arm64': 'y'}>
+CONFIG_LSM                                      policy<{'arm64': '"lockdown,yama,loadpin,safesetid,integrity,apparmor"'}>
+CONFIG_LS_SCFG_MSI                              policy<{'arm64': '-'}>
+CONFIG_LTC1660                                  policy<{'arm64': 'n'}>
+CONFIG_LTC2471                                  policy<{'arm64': 'n'}>
+CONFIG_LTC2485                                  policy<{'arm64': 'n'}>
+CONFIG_LTC2497                                  policy<{'arm64': 'n'}>
+CONFIG_LTC2632                                  policy<{'arm64': 'n'}>
+CONFIG_LTE_GDM724X                              policy<{'arm64': 'n'}>
+CONFIG_LTR501                                   policy<{'arm64': 'n'}>
+CONFIG_LV0104CS                                 policy<{'arm64': 'n'}>
+CONFIG_LWTUNNEL                                 policy<{'arm64': 'n'}>
+CONFIG_LWTUNNEL_BPF                             policy<{'arm64': '-'}>
+CONFIG_LXT_PHY                                  policy<{'arm64': 'y'}>
+CONFIG_LZ4HC_COMPRESS                           policy<{'arm64': '-'}>
+CONFIG_LZ4_COMPRESS                             policy<{'arm64': '-'}>
+CONFIG_M62332                                   policy<{'arm64': 'n'}>
+CONFIG_MAC80211                                 policy<{'arm64': 'y'}>
+CONFIG_MAC80211_DEBUGFS                         policy<{'arm64': 'n'}>
+CONFIG_MAC80211_DEBUG_MENU                      policy<{'arm64': 'y'}>
+CONFIG_MAC80211_HT_DEBUG                        policy<{'arm64': 'n'}>
+CONFIG_MAC80211_HWSIM                           policy<{'arm64': 'n'}>
+CONFIG_MAC80211_IBSS_DEBUG                      policy<{'arm64': 'n'}>
+CONFIG_MAC80211_MESH                            policy<{'arm64': 'n'}>
+CONFIG_MAC80211_MLME_DEBUG                      policy<{'arm64': 'n'}>
+CONFIG_MAC80211_NOINLINE                        policy<{'arm64': 'n'}>
+CONFIG_MAC80211_OCB_DEBUG                       policy<{'arm64': 'n'}>
+CONFIG_MAC80211_PS_DEBUG                        policy<{'arm64': 'n'}>
+CONFIG_MAC80211_STA_DEBUG                       policy<{'arm64': 'n'}>
+CONFIG_MAC80211_TDLS_DEBUG                      policy<{'arm64': 'n'}>
+CONFIG_MAC80211_VERBOSE_DEBUG                   policy<{'arm64': 'n'}>
+CONFIG_MAC802154                                policy<{'arm64': '-'}>
+CONFIG_MACB                                     policy<{'arm64': 'y'}>
+CONFIG_MACB_PCI                                 policy<{'arm64': 'n'}>
+CONFIG_MACSEC                                   policy<{'arm64': 'n'}>
+CONFIG_MACVLAN                                  policy<{'arm64': 'y'}>
+CONFIG_MACVTAP                                  policy<{'arm64': 'n'}>
+CONFIG_MAC_PARTITION                            policy<{'arm64': '-'}>
+CONFIG_MADERA_IRQ                               policy<{'arm64': '-'}>
+CONFIG_MAG3110                                  policy<{'arm64': 'n'}>
+CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE               policy<{'arm64': '0x1'}>
+CONFIG_MAILBOX_TEST                             policy<{'arm64': 'n'}>
+CONFIG_MALI400                                  policy<{'arm64': 'm'}>
+CONFIG_MALI400_DEBUG                            policy<{'arm64': 'n'}>
+CONFIG_MALI400_PROFILING                        policy<{'arm64': 'n'}>
+CONFIG_MALI400_UMP                              policy<{'arm64': 'n'}>
+CONFIG_MALI450                                  policy<{'arm64': 'n'}>
+CONFIG_MALI470                                  policy<{'arm64': 'n'}>
+CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH               policy<{'arm64': 'n'}>
+CONFIG_MALI_DT                                  policy<{'arm64': 'y'}>
+CONFIG_MALI_DVFS                                policy<{'arm64': 'n'}>
+CONFIG_MALI_PMU_PARALLEL_POWER_UP               policy<{'arm64': 'n'}>
+CONFIG_MALI_QUIET                               policy<{'arm64': 'y'}>
+CONFIG_MALI_SHARED_INTERRUPTS                   policy<{'arm64': 'y'}>
+CONFIG_MANAGER_SBS                              policy<{'arm64': 'n'}>
+CONFIG_MANTIS_CORE                              policy<{'arm64': '-'}>
+CONFIG_MARVELL_10G_PHY                          policy<{'arm64': 'n'}>
+CONFIG_MARVELL_PHY                              policy<{'arm64': 'y'}>
+CONFIG_MAX1027                                  policy<{'arm64': 'n'}>
+CONFIG_MAX11100                                 policy<{'arm64': 'n'}>
+CONFIG_MAX1118                                  policy<{'arm64': 'n'}>
+CONFIG_MAX1363                                  policy<{'arm64': 'n'}>
+CONFIG_MAX30100                                 policy<{'arm64': 'n'}>
+CONFIG_MAX30102                                 policy<{'arm64': 'n'}>
+CONFIG_MAX31856                                 policy<{'arm64': 'n'}>
+CONFIG_MAX44000                                 policy<{'arm64': 'n'}>
+CONFIG_MAX44009                                 policy<{'arm64': 'n'}>
+CONFIG_MAX517                                   policy<{'arm64': 'n'}>
+CONFIG_MAX5432                                  policy<{'arm64': 'n'}>
+CONFIG_MAX5481                                  policy<{'arm64': 'n'}>
+CONFIG_MAX5487                                  policy<{'arm64': 'n'}>
+CONFIG_MAX5821                                  policy<{'arm64': 'n'}>
+CONFIG_MAX63XX_WATCHDOG                         policy<{'arm64': 'n'}>
+CONFIG_MAX77620_THERMAL                         policy<{'arm64': '-'}>
+CONFIG_MAX77620_WATCHDOG                        policy<{'arm64': '-'}>
+CONFIG_MAX8925_POWER                            policy<{'arm64': '-'}>
+CONFIG_MAX9611                                  policy<{'arm64': 'n'}>
+CONFIG_MAXIM_THERMOCOUPLE                       policy<{'arm64': 'n'}>
+CONFIG_MAX_RAW_DEVS                             policy<{'arm64': '-'}>
+CONFIG_MB1232                                   policy<{'arm64': 'n'}>
+CONFIG_MC3230                                   policy<{'arm64': 'n'}>
+CONFIG_MCB                                      policy<{'arm64': 'n'}>
+CONFIG_MCB_LPC                                  policy<{'arm64': '-'}>
+CONFIG_MCB_PCI                                  policy<{'arm64': '-'}>
+CONFIG_MCP320X                                  policy<{'arm64': 'n'}>
+CONFIG_MCP3422                                  policy<{'arm64': 'n'}>
+CONFIG_MCP3911                                  policy<{'arm64': 'n'}>
+CONFIG_MCP4018                                  policy<{'arm64': 'n'}>
+CONFIG_MCP41010                                 policy<{'arm64': 'n'}>
+CONFIG_MCP4131                                  policy<{'arm64': 'n'}>
+CONFIG_MCP4531                                  policy<{'arm64': 'n'}>
+CONFIG_MCP4725                                  policy<{'arm64': 'n'}>
+CONFIG_MCP4922                                  policy<{'arm64': 'n'}>
+CONFIG_MDIO                                     policy<{'arm64': '-'}>
+CONFIG_MDIO_BCM_IPROC                           policy<{'arm64': '-'}>
+CONFIG_MDIO_BCM_UNIMAC                          policy<{'arm64': 'n'}>
+CONFIG_MDIO_BITBANG                             policy<{'arm64': 'n'}>
+CONFIG_MDIO_BUS_MUX                             policy<{'arm64': '-'}>
+CONFIG_MDIO_BUS_MUX_BCM_IPROC                   policy<{'arm64': '-'}>
+CONFIG_MDIO_BUS_MUX_GPIO                        policy<{'arm64': 'n'}>
+CONFIG_MDIO_BUS_MUX_MESON_G12A                  policy<{'arm64': '-'}>
+CONFIG_MDIO_BUS_MUX_MMIOREG                     policy<{'arm64': 'n'}>
+CONFIG_MDIO_BUS_MUX_MULTIPLEXER                 policy<{'arm64': 'n'}>
+CONFIG_MDIO_CAVIUM                              policy<{'arm64': '-'}>
+CONFIG_MDIO_GPIO                                policy<{'arm64': '-'}>
+CONFIG_MDIO_HISI_FEMAC                          policy<{'arm64': 'n'}>
+CONFIG_MDIO_I2C                                 policy<{'arm64': '-'}>
+CONFIG_MDIO_MSCC_MIIM                           policy<{'arm64': 'n'}>
+CONFIG_MDIO_OCTEON                              policy<{'arm64': 'n'}>
+CONFIG_MDIO_SUN4I                               policy<{'arm64': '-'}>
+CONFIG_MDIO_THUNDER                             policy<{'arm64': 'n'}>
+CONFIG_MDIO_XGENE                               policy<{'arm64': '-'}>
+CONFIG_MDM_GCC_9615                             policy<{'arm64': '-'}>
+CONFIG_MDM_LCC_9615                             policy<{'arm64': '-'}>
+CONFIG_MD_AUTODETECT                            policy<{'arm64': '-'}>
+CONFIG_MD_CLUSTER                               policy<{'arm64': '-'}>
+CONFIG_MD_FAULTY                                policy<{'arm64': '-'}>
+CONFIG_MD_LINEAR                                policy<{'arm64': '-'}>
+CONFIG_MD_MULTIPATH                             policy<{'arm64': '-'}>
+CONFIG_MD_RAID0                                 policy<{'arm64': '-'}>
+CONFIG_MD_RAID1                                 policy<{'arm64': '-'}>
+CONFIG_MD_RAID10                                policy<{'arm64': '-'}>
+CONFIG_MD_RAID456                               policy<{'arm64': '-'}>
+CONFIG_MEDIATEK_MT6577_AUXADC                   policy<{'arm64': '-'}>
+CONFIG_MEDIATEK_WATCHDOG                        policy<{'arm64': '-'}>
+CONFIG_MEDIA_ALTERA_CI                          policy<{'arm64': '-'}>
+CONFIG_MEDIA_ANALOG_TV_SUPPORT                  policy<{'arm64': 'n'}>
+CONFIG_MEDIA_ATTACH                             policy<{'arm64': '-'}>
+CONFIG_MEDIA_CEC_SUPPORT                        policy<{'arm64': 'n'}>
+CONFIG_MEDIA_COMMON_OPTIONS                     policy<{'arm64': '-'}>
+CONFIG_MEDIA_CONTROLLER_DVB                     policy<{'arm64': '-'}>
+CONFIG_MEDIA_CONTROLLER_REQUEST_API             policy<{'arm64': '-'}>
+CONFIG_MEDIA_DIGITAL_TV_SUPPORT                 policy<{'arm64': 'n'}>
+CONFIG_MEDIA_PCI_SUPPORT                        policy<{'arm64': 'n'}>
+CONFIG_MEDIA_RADIO_SUPPORT                      policy<{'arm64': 'n'}>
+CONFIG_MEDIA_SDR_SUPPORT                        policy<{'arm64': 'n'}>
+CONFIG_MEDIA_SUBDRV_AUTOSELECT                  policy<{'arm64': 'n'}>
+CONFIG_MEDIA_SUPPORT                            policy<{'arm64': 'y'}>
+CONFIG_MEDIA_TUNER                              policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_E4000                        policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_FC0011                       policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_FC0012                       policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_FC0013                       policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_FC2580                       policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_IT913X                       policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_M88RS6000T                   policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_MAX2165                      policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_MC44S803                     policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_MSI001                       policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_MT2060                       policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_MT2063                       policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_MT20XX                       policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_MT2131                       policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_MT2266                       policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_MXL301RF                     policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_MXL5005S                     policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_MXL5007T                     policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_QM1D1B0004                   policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_QM1D1C0042                   policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_QT1010                       policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_R820T                        policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_SI2157                       policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_SIMPLE                       policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_TDA18212                     policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_TDA18218                     policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_TDA18250                     policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_TDA18271                     policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_TDA827X                      policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_TDA8290                      policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_TDA9887                      policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_TEA5761                      policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_TEA5767                      policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_TUA9001                      policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_XC2028                       policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_XC4000                       policy<{'arm64': '-'}>
+CONFIG_MEDIA_TUNER_XC5000                       policy<{'arm64': '-'}>
+CONFIG_MEGARAID_LEGACY                          policy<{'arm64': 'n'}>
+CONFIG_MEGARAID_MAILBOX                         policy<{'arm64': '-'}>
+CONFIG_MEGARAID_MM                              policy<{'arm64': '-'}>
+CONFIG_MEGARAID_NEWGEN                          policy<{'arm64': 'n'}>
+CONFIG_MEGARAID_SAS                             policy<{'arm64': 'n'}>
+CONFIG_MELLANOX_PLATFORM                        policy<{'arm64': 'n'}>
+CONFIG_MEMCG_SWAP_ENABLED                       policy<{'arm64': 'y'}>
+CONFIG_MEMORY                                   policy<{'arm64': 'n'}>
+CONFIG_MEMORY_BALLOON                           policy<{'arm64': '-'}>
+CONFIG_MEMORY_FAILURE                           policy<{'arm64': 'n'}>
+CONFIG_MEMORY_NOTIFIER_ERROR_INJECT             policy<{'arm64': '-'}>
+CONFIG_MEMSTICK                                 policy<{'arm64': 'n'}>
+CONFIG_MEMSTICK_DEBUG                           policy<{'arm64': '-'}>
+CONFIG_MEMSTICK_JMICRON_38X                     policy<{'arm64': '-'}>
+CONFIG_MEMSTICK_R592                            policy<{'arm64': '-'}>
+CONFIG_MEMSTICK_REALTEK_PCI                     policy<{'arm64': '-'}>
+CONFIG_MEMSTICK_REALTEK_USB                     policy<{'arm64': '-'}>
+CONFIG_MEMSTICK_TIFM_MS                         policy<{'arm64': '-'}>
+CONFIG_MEMSTICK_UNSAFE_RESUME                   policy<{'arm64': '-'}>
+CONFIG_MEMTEST                                  policy<{'arm64': 'n'}>
+CONFIG_MENF21BMC_WATCHDOG                       policy<{'arm64': '-'}>
+CONFIG_MENZ069_WATCHDOG                         policy<{'arm64': '-'}>
+CONFIG_MEN_A21_WDT                              policy<{'arm64': 'n'}>
+CONFIG_MEN_Z188_ADC                             policy<{'arm64': '-'}>
+CONFIG_MESON_CANVAS                             policy<{'arm64': '-'}>
+CONFIG_MESON_CLK_MEASURE                        policy<{'arm64': '-'}>
+CONFIG_MESON_EE_PM_DOMAINS                      policy<{'arm64': '-'}>
+CONFIG_MESON_EFUSE                              policy<{'arm64': '-'}>
+CONFIG_MESON_GXBB_WATCHDOG                      policy<{'arm64': '-'}>
+CONFIG_MESON_GXL_PHY                            policy<{'arm64': '-'}>
+CONFIG_MESON_GX_PM_DOMAINS                      policy<{'arm64': '-'}>
+CONFIG_MESON_GX_SOCINFO                         policy<{'arm64': '-'}>
+CONFIG_MESON_IRQ_GPIO                           policy<{'arm64': '-'}>
+CONFIG_MESON_MX_EFUSE                           policy<{'arm64': '-'}>
+CONFIG_MESON_MX_SOCINFO                         policy<{'arm64': '-'}>
+CONFIG_MESON_SARADC                             policy<{'arm64': '-'}>
+CONFIG_MESON_SM                                 policy<{'arm64': '-'}>
+CONFIG_MESON_WATCHDOG                           policy<{'arm64': '-'}>
+CONFIG_MFD_88PM800                              policy<{'arm64': 'n'}>
+CONFIG_MFD_88PM805                              policy<{'arm64': 'n'}>
+CONFIG_MFD_88PM860X                             policy<{'arm64': 'n'}>
+CONFIG_MFD_AAT2870_CORE                         policy<{'arm64': 'n'}>
+CONFIG_MFD_AC100                                policy<{'arm64': '-'}>
+CONFIG_MFD_ACT8945A                             policy<{'arm64': 'n'}>
+CONFIG_MFD_ALTERA_SYSMGR                        policy<{'arm64': '-'}>
+CONFIG_MFD_ARIZONA                              policy<{'arm64': '-'}>
+CONFIG_MFD_ARIZONA_I2C                          policy<{'arm64': 'n'}>
+CONFIG_MFD_ARIZONA_SPI                          policy<{'arm64': 'n'}>
+CONFIG_MFD_AS3711                               policy<{'arm64': 'n'}>
+CONFIG_MFD_AS3722                               policy<{'arm64': 'n'}>
+CONFIG_MFD_ATMEL_FLEXCOM                        policy<{'arm64': 'n'}>
+CONFIG_MFD_ATMEL_HLCDC                          policy<{'arm64': 'n'}>
+CONFIG_MFD_AXP20X                               policy<{'arm64': '-'}>
+CONFIG_MFD_AXP20X_I2C                           policy<{'arm64': 'n'}>
+CONFIG_MFD_AXP20X_RSB                           policy<{'arm64': '-'}>
+CONFIG_MFD_BCM590XX                             policy<{'arm64': 'n'}>
+CONFIG_MFD_BD9571MWV                            policy<{'arm64': 'n'}>
+CONFIG_MFD_CPCAP                                policy<{'arm64': 'n'}>
+CONFIG_MFD_CROS_EC                              policy<{'arm64': 'n'}>
+CONFIG_MFD_CROS_EC_DEV                          policy<{'arm64': '-'}>
+CONFIG_MFD_CS47L15                              policy<{'arm64': '-'}>
+CONFIG_MFD_CS47L24                              policy<{'arm64': '-'}>
+CONFIG_MFD_CS47L35                              policy<{'arm64': '-'}>
+CONFIG_MFD_CS47L85                              policy<{'arm64': '-'}>
+CONFIG_MFD_CS47L90                              policy<{'arm64': '-'}>
+CONFIG_MFD_CS47L92                              policy<{'arm64': '-'}>
+CONFIG_MFD_DA9052_I2C                           policy<{'arm64': 'n'}>
+CONFIG_MFD_DA9052_SPI                           policy<{'arm64': 'n'}>
+CONFIG_MFD_DA9055                               policy<{'arm64': 'n'}>
+CONFIG_MFD_DA9062                               policy<{'arm64': 'n'}>
+CONFIG_MFD_DA9063                               policy<{'arm64': 'n'}>
+CONFIG_MFD_DA9150                               policy<{'arm64': 'n'}>
+CONFIG_MFD_DLN2                                 policy<{'arm64': 'n'}>
+CONFIG_MFD_HI6421_PMIC                          policy<{'arm64': 'n'}>
+CONFIG_MFD_HI655X_PMIC                          policy<{'arm64': '-'}>
+CONFIG_MFD_JANZ_CMODIO                          policy<{'arm64': 'n'}>
+CONFIG_MFD_KEMPLD                               policy<{'arm64': 'n'}>
+CONFIG_MFD_LM3533                               policy<{'arm64': 'n'}>
+CONFIG_MFD_LOCHNAGAR                            policy<{'arm64': 'n'}>
+CONFIG_MFD_LP3943                               policy<{'arm64': 'n'}>
+CONFIG_MFD_LP8788                               policy<{'arm64': 'n'}>
+CONFIG_MFD_MADERA                               policy<{'arm64': 'n'}>
+CONFIG_MFD_MADERA_I2C                           policy<{'arm64': '-'}>
+CONFIG_MFD_MADERA_SPI                           policy<{'arm64': '-'}>
+CONFIG_MFD_MAX14577                             policy<{'arm64': 'n'}>
+CONFIG_MFD_MAX77620                             policy<{'arm64': 'n'}>
+CONFIG_MFD_MAX77650                             policy<{'arm64': 'n'}>
+CONFIG_MFD_MAX77686                             policy<{'arm64': 'n'}>
+CONFIG_MFD_MAX77693                             policy<{'arm64': 'n'}>
+CONFIG_MFD_MAX77843                             policy<{'arm64': 'n'}>
+CONFIG_MFD_MAX8907                              policy<{'arm64': 'n'}>
+CONFIG_MFD_MAX8925                              policy<{'arm64': 'n'}>
+CONFIG_MFD_MAX8997                              policy<{'arm64': 'n'}>
+CONFIG_MFD_MAX8998                              policy<{'arm64': 'n'}>
+CONFIG_MFD_MC13XXX                              policy<{'arm64': '-'}>
+CONFIG_MFD_MC13XXX_I2C                          policy<{'arm64': 'n'}>
+CONFIG_MFD_MC13XXX_SPI                          policy<{'arm64': 'n'}>
+CONFIG_MFD_MENF21BMC                            policy<{'arm64': 'n'}>
+CONFIG_MFD_MT6397                               policy<{'arm64': 'n'}>
+CONFIG_MFD_PALMAS                               policy<{'arm64': 'n'}>
+CONFIG_MFD_PCF50633                             policy<{'arm64': 'n'}>
+CONFIG_MFD_QCOM_RPM                             policy<{'arm64': '-'}>
+CONFIG_MFD_RC5T583                              policy<{'arm64': 'n'}>
+CONFIG_MFD_RDC321X                              policy<{'arm64': 'n'}>
+CONFIG_MFD_RETU                                 policy<{'arm64': 'n'}>
+CONFIG_MFD_RK808                                policy<{'arm64': 'n'}>
+CONFIG_MFD_RN5T618                              policy<{'arm64': 'n'}>
+CONFIG_MFD_ROHM_BD70528                         policy<{'arm64': 'n'}>
+CONFIG_MFD_ROHM_BD718XX                         policy<{'arm64': 'n'}>
+CONFIG_MFD_RT5033                               policy<{'arm64': 'n'}>
+CONFIG_MFD_SC27XX_PMIC                          policy<{'arm64': '-'}>
+CONFIG_MFD_SEC_CORE                             policy<{'arm64': 'n'}>
+CONFIG_MFD_SI476X_CORE                          policy<{'arm64': 'n'}>
+CONFIG_MFD_SKY81452                             policy<{'arm64': 'n'}>
+CONFIG_MFD_SM501_GPIO                           policy<{'arm64': '-'}>
+CONFIG_MFD_SMSC                                 policy<{'arm64': 'n'}>
+CONFIG_MFD_SPMI_PMIC                            policy<{'arm64': '-'}>
+CONFIG_MFD_STMFX                                policy<{'arm64': 'n'}>
+CONFIG_MFD_STMPE                                policy<{'arm64': 'n'}>
+CONFIG_MFD_STPMIC1                              policy<{'arm64': 'n'}>
+CONFIG_MFD_SUN4I_GPADC                          policy<{'arm64': '-'}>
+CONFIG_MFD_SUN6I_PRCM                           policy<{'arm64': '-'}>
+CONFIG_MFD_SYSCON                               policy<{'arm64': 'n'}>
+CONFIG_MFD_TC3589X                              policy<{'arm64': 'n'}>
+CONFIG_MFD_TI_AM335X_TSCADC                     policy<{'arm64': '-'}>
+CONFIG_MFD_TI_LMU                               policy<{'arm64': 'n'}>
+CONFIG_MFD_TI_LP873X                            policy<{'arm64': 'n'}>
+CONFIG_MFD_TI_LP87565                           policy<{'arm64': 'n'}>
+CONFIG_MFD_TPS65086                             policy<{'arm64': 'y'}>
+CONFIG_MFD_TPS65090                             policy<{'arm64': 'n'}>
+CONFIG_MFD_TPS65218                             policy<{'arm64': 'n'}>
+CONFIG_MFD_TPS6586X                             policy<{'arm64': 'n'}>
+CONFIG_MFD_TPS65910                             policy<{'arm64': 'n'}>
+CONFIG_MFD_TPS65912                             policy<{'arm64': '-'}>
+CONFIG_MFD_TPS65912_I2C                         policy<{'arm64': 'n'}>
+CONFIG_MFD_TPS65912_SPI                         policy<{'arm64': 'n'}>
+CONFIG_MFD_TPS68470                             policy<{'arm64': '-'}>
+CONFIG_MFD_TPS80031                             policy<{'arm64': 'n'}>
+CONFIG_MFD_TQMX86                               policy<{'arm64': 'n'}>
+CONFIG_MFD_TWL4030_AUDIO                        policy<{'arm64': '-'}>
+CONFIG_MFD_VEXPRESS_SYSREG                      policy<{'arm64': '-'}>
+CONFIG_MFD_VIPERBOARD                           policy<{'arm64': 'n'}>
+CONFIG_MFD_VX855                                policy<{'arm64': 'n'}>
+CONFIG_MFD_WL1273_CORE                          policy<{'arm64': 'n'}>
+CONFIG_MFD_WM5102                               policy<{'arm64': '-'}>
+CONFIG_MFD_WM5110                               policy<{'arm64': '-'}>
+CONFIG_MFD_WM831X                               policy<{'arm64': '-'}>
+CONFIG_MFD_WM831X_I2C                           policy<{'arm64': 'n'}>
+CONFIG_MFD_WM831X_SPI                           policy<{'arm64': 'n'}>
+CONFIG_MFD_WM8350                               policy<{'arm64': '-'}>
+CONFIG_MFD_WM8350_I2C                           policy<{'arm64': 'n'}>
+CONFIG_MFD_WM8400                               policy<{'arm64': 'n'}>
+CONFIG_MFD_WM8994                               policy<{'arm64': 'n'}>
+CONFIG_MFD_WM8997                               policy<{'arm64': '-'}>
+CONFIG_MFD_WM8998                               policy<{'arm64': '-'}>
+CONFIG_MICREL_KS8995MA                          policy<{'arm64': 'n'}>
+CONFIG_MICREL_PHY                               policy<{'arm64': 'y'}>
+CONFIG_MICROCHIP_PHY                            policy<{'arm64': 'n'}>
+CONFIG_MICROCHIP_T1_PHY                         policy<{'arm64': 'n'}>
+CONFIG_MICROSEMI_PHY                            policy<{'arm64': 'y'}>
+CONFIG_MINIX_FS                                 policy<{'arm64': 'n'}>
+CONFIG_MINIX_SUBPARTITION                       policy<{'arm64': '-'}>
+CONFIG_MISC_ALCOR_PCI                           policy<{'arm64': 'n'}>
+CONFIG_MISC_RTSX                                policy<{'arm64': '-'}>
+CONFIG_MISC_RTSX_PCI                            policy<{'arm64': 'n'}>
+CONFIG_MISC_RTSX_USB                            policy<{'arm64': 'n'}>
+CONFIG_MISDN                                    policy<{'arm64': '-'}>
+CONFIG_MISDN_AVMFRITZ                           policy<{'arm64': '-'}>
+CONFIG_MISDN_DSP                                policy<{'arm64': '-'}>
+CONFIG_MISDN_HDLC                               policy<{'arm64': '-'}>
+CONFIG_MISDN_HFCMULTI                           policy<{'arm64': '-'}>
+CONFIG_MISDN_HFCPCI                             policy<{'arm64': '-'}>
+CONFIG_MISDN_HFCUSB                             policy<{'arm64': '-'}>
+CONFIG_MISDN_INFINEON                           policy<{'arm64': '-'}>
+CONFIG_MISDN_IPAC                               policy<{'arm64': '-'}>
+CONFIG_MISDN_ISAR                               policy<{'arm64': '-'}>
+CONFIG_MISDN_L1OIP                              policy<{'arm64': '-'}>
+CONFIG_MISDN_NETJET                             policy<{'arm64': '-'}>
+CONFIG_MISDN_SPEEDFAX                           policy<{'arm64': '-'}>
+CONFIG_MISDN_W6692                              policy<{'arm64': '-'}>
+CONFIG_MKISS                                    policy<{'arm64': '-'}>
+CONFIG_MLX4_CORE                                policy<{'arm64': '-'}>
+CONFIG_MLX4_CORE_GEN2                           policy<{'arm64': '-'}>
+CONFIG_MLX4_DEBUG                               policy<{'arm64': '-'}>
+CONFIG_MLX4_EN                                  policy<{'arm64': 'n'}>
+CONFIG_MLX4_EN_DCB                              policy<{'arm64': '-'}>
+CONFIG_MLX4_INFINIBAND                          policy<{'arm64': '-'}>
+CONFIG_MLX5_ACCEL                               policy<{'arm64': '-'}>
+CONFIG_MLX5_CORE                                policy<{'arm64': 'n'}>
+CONFIG_MLX5_CORE_EN                             policy<{'arm64': '-'}>
+CONFIG_MLX5_CORE_EN_DCB                         policy<{'arm64': '-'}>
+CONFIG_MLX5_CORE_IPOIB                          policy<{'arm64': '-'}>
+CONFIG_MLX5_EN_ARFS                             policy<{'arm64': '-'}>
+CONFIG_MLX5_EN_IPSEC                            policy<{'arm64': '-'}>
+CONFIG_MLX5_EN_RXNFC                            policy<{'arm64': '-'}>
+CONFIG_MLX5_EN_TLS                              policy<{'arm64': '-'}>
+CONFIG_MLX5_ESWITCH                             policy<{'arm64': '-'}>
+CONFIG_MLX5_FPGA                                policy<{'arm64': '-'}>
+CONFIG_MLX5_FPGA_IPSEC                          policy<{'arm64': '-'}>
+CONFIG_MLX5_FPGA_TLS                            policy<{'arm64': '-'}>
+CONFIG_MLX5_INFINIBAND                          policy<{'arm64': '-'}>
+CONFIG_MLX5_MPFS                                policy<{'arm64': '-'}>
+CONFIG_MLX5_SW_STEERING                         policy<{'arm64': '-'}>
+CONFIG_MLX5_TLS                                 policy<{'arm64': '-'}>
+CONFIG_MLX90614                                 policy<{'arm64': 'n'}>
+CONFIG_MLX90632                                 policy<{'arm64': 'n'}>
+CONFIG_MLXBF_TMFIFO                             policy<{'arm64': '-'}>
+CONFIG_MLXFW                                    policy<{'arm64': 'n'}>
+CONFIG_MLXREG_HOTPLUG                           policy<{'arm64': '-'}>
+CONFIG_MLXREG_IO                                policy<{'arm64': '-'}>
+CONFIG_MLXSW_CORE                               policy<{'arm64': 'n'}>
+CONFIG_MLXSW_CORE_HWMON                         policy<{'arm64': '-'}>
+CONFIG_MLXSW_CORE_THERMAL                       policy<{'arm64': '-'}>
+CONFIG_MLXSW_I2C                                policy<{'arm64': '-'}>
+CONFIG_MLXSW_MINIMAL                            policy<{'arm64': '-'}>
+CONFIG_MLXSW_PCI                                policy<{'arm64': '-'}>
+CONFIG_MLXSW_SPECTRUM                           policy<{'arm64': '-'}>
+CONFIG_MLXSW_SPECTRUM_DCB                       policy<{'arm64': '-'}>
+CONFIG_MLXSW_SWITCHIB                           policy<{'arm64': '-'}>
+CONFIG_MLXSW_SWITCHX2                           policy<{'arm64': '-'}>
+CONFIG_MLX_WDT                                  policy<{'arm64': '-'}>
+CONFIG_MMA7455                                  policy<{'arm64': '-'}>
+CONFIG_MMA7455_I2C                              policy<{'arm64': 'n'}>
+CONFIG_MMA7455_SPI                              policy<{'arm64': 'n'}>
+CONFIG_MMA7660                                  policy<{'arm64': 'n'}>
+CONFIG_MMA8452                                  policy<{'arm64': 'n'}>
+CONFIG_MMA9551                                  policy<{'arm64': 'n'}>
+CONFIG_MMA9551_CORE                             policy<{'arm64': '-'}>
+CONFIG_MMA9553                                  policy<{'arm64': 'n'}>
+CONFIG_MMC35240                                 policy<{'arm64': 'n'}>
+CONFIG_MMC_ALCOR                                policy<{'arm64': '-'}>
+CONFIG_MMC_ARMMMCI                              policy<{'arm64': 'n'}>
+CONFIG_MMC_BCM2835                              policy<{'arm64': '-'}>
+CONFIG_MMC_CAVIUM_THUNDERX                      policy<{'arm64': '-'}>
+CONFIG_MMC_CB710                                policy<{'arm64': 'n'}>
+CONFIG_MMC_CQHCI                                policy<{'arm64': 'y'}>
+CONFIG_MMC_DW                                   policy<{'arm64': 'n'}>
+CONFIG_MMC_DW_BLUEFIELD                         policy<{'arm64': '-'}>
+CONFIG_MMC_DW_EXYNOS                            policy<{'arm64': '-'}>
+CONFIG_MMC_DW_HI3798CV200                       policy<{'arm64': '-'}>
+CONFIG_MMC_DW_K3                                policy<{'arm64': '-'}>
+CONFIG_MMC_DW_PCI                               policy<{'arm64': '-'}>
+CONFIG_MMC_DW_PLTFM                             policy<{'arm64': '-'}>
+CONFIG_MMC_DW_ROCKCHIP                          policy<{'arm64': '-'}>
+CONFIG_MMC_MESON_GX                             policy<{'arm64': '-'}>
+CONFIG_MMC_MESON_MX_SDIO                        policy<{'arm64': '-'}>
+CONFIG_MMC_MTK                                  policy<{'arm64': 'n'}>
+CONFIG_MMC_MXC                                  policy<{'arm64': '-'}>
+CONFIG_MMC_QCOM_DML                             policy<{'arm64': '-'}>
+CONFIG_MMC_REALTEK_PCI                          policy<{'arm64': '-'}>
+CONFIG_MMC_REALTEK_USB                          policy<{'arm64': '-'}>
+CONFIG_MMC_RICOH_MMC                            policy<{'arm64': '-'}>
+CONFIG_MMC_SDHCI_ACPI                           policy<{'arm64': '-'}>
+CONFIG_MMC_SDHCI_AM654                          policy<{'arm64': '-'}>
+CONFIG_MMC_SDHCI_BRCMSTB                        policy<{'arm64': '-'}>
+CONFIG_MMC_SDHCI_CADENCE                        policy<{'arm64': 'n'}>
+CONFIG_MMC_SDHCI_ESDHC_IMX                      policy<{'arm64': '-'}>
+CONFIG_MMC_SDHCI_F_SDH30                        policy<{'arm64': 'n'}>
+CONFIG_MMC_SDHCI_IO_ACCESSORS                   policy<{'arm64': '-'}>
+CONFIG_MMC_SDHCI_IPROC                          policy<{'arm64': '-'}>
+CONFIG_MMC_SDHCI_MSM                            policy<{'arm64': '-'}>
+CONFIG_MMC_SDHCI_OF_ARASAN                      policy<{'arm64': 'y'}>
+CONFIG_MMC_SDHCI_OF_ASPEED                      policy<{'arm64': 'n'}>
+CONFIG_MMC_SDHCI_OF_AT91                        policy<{'arm64': 'n'}>
+CONFIG_MMC_SDHCI_OF_DWCMSHC                     policy<{'arm64': 'n'}>
+CONFIG_MMC_SDHCI_OF_ESDHC                       policy<{'arm64': '-'}>
+CONFIG_MMC_SDHCI_PCI                            policy<{'arm64': 'n'}>
+CONFIG_MMC_SDHCI_PXAV3                          policy<{'arm64': '-'}>
+CONFIG_MMC_SDHCI_SPRD                           policy<{'arm64': '-'}>
+CONFIG_MMC_SDHCI_XENON                          policy<{'arm64': 'n'}>
+CONFIG_MMC_SDHI                                 policy<{'arm64': '-'}>
+CONFIG_MMC_SDHI_INTERNAL_DMAC                   policy<{'arm64': '-'}>
+CONFIG_MMC_SDHI_SYS_DMAC                        policy<{'arm64': '-'}>
+CONFIG_MMC_SH_MMCIF                             policy<{'arm64': '-'}>
+CONFIG_MMC_SPI                                  policy<{'arm64': 'n'}>
+CONFIG_MMC_STM32_SDMMC                          policy<{'arm64': '-'}>
+CONFIG_MMC_SUNXI                                policy<{'arm64': '-'}>
+CONFIG_MMC_TIFM_SD                              policy<{'arm64': 'n'}>
+CONFIG_MMC_TMIO_CORE                            policy<{'arm64': '-'}>
+CONFIG_MMC_TOSHIBA_PCI                          policy<{'arm64': 'n'}>
+CONFIG_MMC_USDHI6ROL0                           policy<{'arm64': 'n'}>
+CONFIG_MMC_USHC                                 policy<{'arm64': 'n'}>
+CONFIG_MMC_VIA_SDMMC                            policy<{'arm64': 'n'}>
+CONFIG_MMC_VUB300                               policy<{'arm64': 'n'}>
+CONFIG_MODULE_FORCE_UNLOAD                      policy<{'arm64': 'y'}>
+CONFIG_MODULE_SIG_HASH                          policy<{'arm64': '"sha1"'}>
+CONFIG_MODULE_SIG_SHA1                          policy<{'arm64': 'y'}>
+CONFIG_MODULE_SIG_SHA512                        policy<{'arm64': 'n'}>
+CONFIG_MODULE_SRCVERSION_ALL                    policy<{'arm64': 'n'}>
+CONFIG_MOST                                     policy<{'arm64': 'n'}>
+CONFIG_MOST_CDEV                                policy<{'arm64': '-'}>
+CONFIG_MOST_DIM2                                policy<{'arm64': '-'}>
+CONFIG_MOST_I2C                                 policy<{'arm64': '-'}>
+CONFIG_MOST_NET                                 policy<{'arm64': '-'}>
+CONFIG_MOST_SOUND                               policy<{'arm64': '-'}>
+CONFIG_MOST_USB                                 policy<{'arm64': '-'}>
+CONFIG_MOST_VIDEO                               policy<{'arm64': '-'}>
+CONFIG_MOUSE_APPLETOUCH                         policy<{'arm64': '-'}>
+CONFIG_MOUSE_BCM5974                            policy<{'arm64': '-'}>
+CONFIG_MOUSE_CYAPA                              policy<{'arm64': '-'}>
+CONFIG_MOUSE_ELAN_I2C                           policy<{'arm64': '-'}>
+CONFIG_MOUSE_ELAN_I2C_I2C                       policy<{'arm64': '-'}>
+CONFIG_MOUSE_ELAN_I2C_SMBUS                     policy<{'arm64': '-'}>
+CONFIG_MOUSE_GPIO                               policy<{'arm64': '-'}>
+CONFIG_MOUSE_PS2                                policy<{'arm64': '-'}>
+CONFIG_MOUSE_PS2_ALPS                           policy<{'arm64': '-'}>
+CONFIG_MOUSE_PS2_BYD                            policy<{'arm64': '-'}>
+CONFIG_MOUSE_PS2_CYPRESS                        policy<{'arm64': '-'}>
+CONFIG_MOUSE_PS2_ELANTECH                       policy<{'arm64': '-'}>
+CONFIG_MOUSE_PS2_ELANTECH_SMBUS                 policy<{'arm64': '-'}>
+CONFIG_MOUSE_PS2_FOCALTECH                      policy<{'arm64': '-'}>
+CONFIG_MOUSE_PS2_LOGIPS2PP                      policy<{'arm64': '-'}>
+CONFIG_MOUSE_PS2_SENTELIC                       policy<{'arm64': '-'}>
+CONFIG_MOUSE_PS2_SMBUS                          policy<{'arm64': '-'}>
+CONFIG_MOUSE_PS2_SYNAPTICS                      policy<{'arm64': '-'}>
+CONFIG_MOUSE_PS2_SYNAPTICS_SMBUS                policy<{'arm64': '-'}>
+CONFIG_MOUSE_PS2_TOUCHKIT                       policy<{'arm64': '-'}>
+CONFIG_MOUSE_PS2_TRACKPOINT                     policy<{'arm64': '-'}>
+CONFIG_MOUSE_SERIAL                             policy<{'arm64': '-'}>
+CONFIG_MOUSE_SYNAPTICS_I2C                      policy<{'arm64': '-'}>
+CONFIG_MOUSE_SYNAPTICS_USB                      policy<{'arm64': '-'}>
+CONFIG_MOUSE_VSXXXAA                            policy<{'arm64': '-'}>
+CONFIG_MOXA_INTELLIO                            policy<{'arm64': '-'}>
+CONFIG_MOXA_SMARTIO                             policy<{'arm64': '-'}>
+CONFIG_MOXTET                                   policy<{'arm64': 'n'}>
+CONFIG_MPL115                                   policy<{'arm64': '-'}>
+CONFIG_MPL115_I2C                               policy<{'arm64': 'n'}>
+CONFIG_MPL115_SPI                               policy<{'arm64': 'n'}>
+CONFIG_MPL3115                                  policy<{'arm64': 'n'}>
+CONFIG_MPLS_IPTUNNEL                            policy<{'arm64': '-'}>
+CONFIG_MPLS_ROUTING                             policy<{'arm64': 'n'}>
+CONFIG_MPU3050                                  policy<{'arm64': '-'}>
+CONFIG_MPU3050_I2C                              policy<{'arm64': 'n'}>
+CONFIG_MQ_IOSCHED_KYBER                         policy<{'arm64': 'y'}>
+CONFIG_MRP                                      policy<{'arm64': '-'}>
+CONFIG_MS5611                                   policy<{'arm64': 'n'}>
+CONFIG_MS5611_I2C                               policy<{'arm64': '-'}>
+CONFIG_MS5611_SPI                               policy<{'arm64': '-'}>
+CONFIG_MS5637                                   policy<{'arm64': 'n'}>
+CONFIG_MSCC_OCELOT_SWITCH                       policy<{'arm64': '-'}>
+CONFIG_MSCC_OCELOT_SWITCH_OCELOT                policy<{'arm64': '-'}>
+CONFIG_MSDOS_FS                                 policy<{'arm64': 'y'}>
+CONFIG_MSM_GCC_8660                             policy<{'arm64': '-'}>
+CONFIG_MSM_GCC_8916                             policy<{'arm64': '-'}>
+CONFIG_MSM_GCC_8960                             policy<{'arm64': '-'}>
+CONFIG_MSM_GCC_8974                             policy<{'arm64': '-'}>
+CONFIG_MSM_GCC_8994                             policy<{'arm64': '-'}>
+CONFIG_MSM_GCC_8996                             policy<{'arm64': '-'}>
+CONFIG_MSM_GCC_8998                             policy<{'arm64': '-'}>
+CONFIG_MSM_LCC_8960                             policy<{'arm64': '-'}>
+CONFIG_MSM_MMCC_8960                            policy<{'arm64': '-'}>
+CONFIG_MSM_MMCC_8974                            policy<{'arm64': '-'}>
+CONFIG_MSM_MMCC_8996                            policy<{'arm64': '-'}>
+CONFIG_MSPRO_BLOCK                              policy<{'arm64': '-'}>
+CONFIG_MS_BLOCK                                 policy<{'arm64': '-'}>
+CONFIG_MT7601U                                  policy<{'arm64': 'n'}>
+CONFIG_MT7603E                                  policy<{'arm64': 'n'}>
+CONFIG_MT7615E                                  policy<{'arm64': 'n'}>
+CONFIG_MT76_CORE                                policy<{'arm64': '-'}>
+CONFIG_MT76_LEDS                                policy<{'arm64': '-'}>
+CONFIG_MT76_USB                                 policy<{'arm64': '-'}>
+CONFIG_MT76x02_LIB                              policy<{'arm64': '-'}>
+CONFIG_MT76x02_USB                              policy<{'arm64': '-'}>
+CONFIG_MT76x0E                                  policy<{'arm64': 'n'}>
+CONFIG_MT76x0U                                  policy<{'arm64': 'n'}>
+CONFIG_MT76x0_COMMON                            policy<{'arm64': '-'}>
+CONFIG_MT76x2E                                  policy<{'arm64': 'n'}>
+CONFIG_MT76x2U                                  policy<{'arm64': 'n'}>
+CONFIG_MT76x2_COMMON                            policy<{'arm64': '-'}>
+CONFIG_MTDRAM_ERASE_SIZE                        policy<{'arm64': '-'}>
+CONFIG_MTDRAM_TOTAL_SIZE                        policy<{'arm64': '-'}>
+CONFIG_MTD_ABSENT                               policy<{'arm64': 'n'}>
+CONFIG_MTD_AFS_PARTS                            policy<{'arm64': 'n'}>
+CONFIG_MTD_AR7_PARTS                            policy<{'arm64': 'n'}>
+CONFIG_MTD_BLKDEVS                              policy<{'arm64': 'y'}>
+CONFIG_MTD_BLOCK2MTD                            policy<{'arm64': 'n'}>
+CONFIG_MTD_BLOCK_RO                             policy<{'arm64': '-'}>
+CONFIG_MTD_CFI                                  policy<{'arm64': 'y'}>
+CONFIG_MTD_CFI_AMDSTD                           policy<{'arm64': 'n'}>
+CONFIG_MTD_CFI_INTELEXT                         policy<{'arm64': 'y'}>
+CONFIG_MTD_CFI_STAA                             policy<{'arm64': 'n'}>
+CONFIG_MTD_CFI_UTIL                             policy<{'arm64': 'y'}>
+CONFIG_MTD_CMDLINE_PARTS                        policy<{'arm64': 'y'}>
+CONFIG_MTD_COMPLEX_MAPPINGS                     policy<{'arm64': 'n'}>
+CONFIG_MTD_DATAFLASH                            policy<{'arm64': 'y'}>
+CONFIG_MTD_DATAFLASH_OTP                        policy<{'arm64': 'n'}>
+CONFIG_MTD_GEN_PROBE                            policy<{'arm64': 'y'}>
+CONFIG_MTD_HYPERBUS                             policy<{'arm64': 'n'}>
+CONFIG_MTD_INTEL_VR_NOR                         policy<{'arm64': 'n'}>
+CONFIG_MTD_JEDECPROBE                           policy<{'arm64': 'n'}>
+CONFIG_MTD_LPDDR                                policy<{'arm64': 'n'}>
+CONFIG_MTD_MCHP23K256                           policy<{'arm64': 'n'}>
+CONFIG_MTD_MTDRAM                               policy<{'arm64': 'n'}>
+CONFIG_MTD_NAND_ARASAN                          policy<{'arm64': 'y'}>
+CONFIG_MTD_NAND_BRCMNAND                        policy<{'arm64': 'n'}>
+CONFIG_MTD_NAND_CAFE                            policy<{'arm64': 'n'}>
+CONFIG_MTD_NAND_CORE                            policy<{'arm64': 'y'}>
+CONFIG_MTD_NAND_DENALI                          policy<{'arm64': '-'}>
+CONFIG_MTD_NAND_DENALI_DT                       policy<{'arm64': 'n'}>
+CONFIG_MTD_NAND_DENALI_PCI                      policy<{'arm64': 'n'}>
+CONFIG_MTD_NAND_DISKONCHIP                      policy<{'arm64': 'n'}>
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS        policy<{'arm64': '-'}>
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED       policy<{'arm64': '-'}>
+CONFIG_MTD_NAND_ECC_SW_BCH                      policy<{'arm64': 'n'}>
+CONFIG_MTD_NAND_ECC_SW_HAMMING                  policy<{'arm64': 'y'}>
+CONFIG_MTD_NAND_FSL_IFC                         policy<{'arm64': '-'}>
+CONFIG_MTD_NAND_GPIO                            policy<{'arm64': 'n'}>
+CONFIG_MTD_NAND_GPMI_NAND                       policy<{'arm64': '-'}>
+CONFIG_MTD_NAND_HISI504                         policy<{'arm64': '-'}>
+CONFIG_MTD_NAND_MARVELL                         policy<{'arm64': '-'}>
+CONFIG_MTD_NAND_MESON                           policy<{'arm64': '-'}>
+CONFIG_MTD_NAND_MTK                             policy<{'arm64': '-'}>
+CONFIG_MTD_NAND_MXC                             policy<{'arm64': '-'}>
+CONFIG_MTD_NAND_MXIC                            policy<{'arm64': 'n'}>
+CONFIG_MTD_NAND_NANDSIM                         policy<{'arm64': 'n'}>
+CONFIG_MTD_NAND_PLATFORM                        policy<{'arm64': 'n'}>
+CONFIG_MTD_NAND_QCOM                            policy<{'arm64': '-'}>
+CONFIG_MTD_NAND_RICOH                           policy<{'arm64': 'n'}>
+CONFIG_MTD_NAND_SUNXI                           policy<{'arm64': '-'}>
+CONFIG_MTD_ONENAND                              policy<{'arm64': 'n'}>
+CONFIG_MTD_ONENAND_2X_PROGRAM                   policy<{'arm64': '-'}>
+CONFIG_MTD_ONENAND_GENERIC                      policy<{'arm64': '-'}>
+CONFIG_MTD_ONENAND_OTP                          policy<{'arm64': '-'}>
+CONFIG_MTD_OOPS                                 policy<{'arm64': 'y'}>
+CONFIG_MTD_PCI                                  policy<{'arm64': '-'}>
+CONFIG_MTD_PHRAM                                policy<{'arm64': 'n'}>
+CONFIG_MTD_PHYSMAP                              policy<{'arm64': 'n'}>
+CONFIG_MTD_PHYSMAP_COMPAT                       policy<{'arm64': '-'}>
+CONFIG_MTD_PHYSMAP_GEMINI                       policy<{'arm64': '-'}>
+CONFIG_MTD_PHYSMAP_GPIO_ADDR                    policy<{'arm64': '-'}>
+CONFIG_MTD_PHYSMAP_OF                           policy<{'arm64': '-'}>
+CONFIG_MTD_PHYSMAP_VERSATILE                    policy<{'arm64': '-'}>
+CONFIG_MTD_PLATRAM                              policy<{'arm64': 'n'}>
+CONFIG_MTD_PMC551                               policy<{'arm64': 'n'}>
+CONFIG_MTD_PMC551_BUGFIX                        policy<{'arm64': '-'}>
+CONFIG_MTD_PMC551_DEBUG                         policy<{'arm64': '-'}>
+CONFIG_MTD_QINFO_PROBE                          policy<{'arm64': '-'}>
+CONFIG_MTD_RAM                                  policy<{'arm64': 'n'}>
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK              policy<{'arm64': '-'}>
+CONFIG_MTD_REDBOOT_PARTS                        policy<{'arm64': 'n'}>
+CONFIG_MTD_REDBOOT_PARTS_READONLY               policy<{'arm64': '-'}>
+CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED            policy<{'arm64': '-'}>
+CONFIG_MTD_ROM                                  policy<{'arm64': 'n'}>
+CONFIG_MTD_SLRAM                                policy<{'arm64': 'n'}>
+CONFIG_MTD_SM_COMMON                            policy<{'arm64': '-'}>
+CONFIG_MTD_SPI_NAND                             policy<{'arm64': 'n'}>
+CONFIG_MTD_SPI_NOR                              policy<{'arm64': 'y'}>
+CONFIG_MTD_SST25L                               policy<{'arm64': 'n'}>
+CONFIG_MTD_SWAP                                 policy<{'arm64': 'n'}>
+CONFIG_MTD_TESTS                                policy<{'arm64': 'm'}>
+CONFIG_MTK_CMDQ                                 policy<{'arm64': '-'}>
+CONFIG_MTK_CMDQ_MBOX                            policy<{'arm64': '-'}>
+CONFIG_MTK_CQDMA                                policy<{'arm64': '-'}>
+CONFIG_MTK_EFUSE                                policy<{'arm64': '-'}>
+CONFIG_MTK_HSDMA                                policy<{'arm64': '-'}>
+CONFIG_MTK_INFRACFG                             policy<{'arm64': '-'}>
+CONFIG_MTK_IOMMU                                policy<{'arm64': '-'}>
+CONFIG_MTK_PMIC_WRAP                            policy<{'arm64': '-'}>
+CONFIG_MTK_SCPSYS                               policy<{'arm64': '-'}>
+CONFIG_MTK_SMI                                  policy<{'arm64': '-'}>
+CONFIG_MTK_THERMAL                              policy<{'arm64': '-'}>
+CONFIG_MTK_TIMER                                policy<{'arm64': '-'}>
+CONFIG_MTK_UART_APDMA                           policy<{'arm64': '-'}>
+CONFIG_MULTIPLEXER                              policy<{'arm64': '-'}>
+CONFIG_MUSB_PIO_ONLY                            policy<{'arm64': '-'}>
+CONFIG_MUX_ADG792A                              policy<{'arm64': '-'}>
+CONFIG_MUX_ADGS1408                             policy<{'arm64': '-'}>
+CONFIG_MUX_GPIO                                 policy<{'arm64': '-'}>
+CONFIG_MUX_MMIO                                 policy<{'arm64': '-'}>
+CONFIG_MVEBU_GICP                               policy<{'arm64': '-'}>
+CONFIG_MVEBU_ICU                                policy<{'arm64': '-'}>
+CONFIG_MVEBU_ODMI                               policy<{'arm64': '-'}>
+CONFIG_MVEBU_PIC                                policy<{'arm64': '-'}>
+CONFIG_MVEBU_SEI                                policy<{'arm64': '-'}>
+CONFIG_MVMDIO                                   policy<{'arm64': 'n'}>
+CONFIG_MVNETA                                   policy<{'arm64': '-'}>
+CONFIG_MVPP2                                    policy<{'arm64': '-'}>
+CONFIG_MV_XOR                                   policy<{'arm64': '-'}>
+CONFIG_MV_XOR_V2                                policy<{'arm64': 'n'}>
+CONFIG_MWIFIEX                                  policy<{'arm64': 'n'}>
+CONFIG_MWIFIEX_PCIE                             policy<{'arm64': '-'}>
+CONFIG_MWIFIEX_SDIO                             policy<{'arm64': '-'}>
+CONFIG_MWIFIEX_USB                              policy<{'arm64': '-'}>
+CONFIG_MWL8K                                    policy<{'arm64': 'n'}>
+CONFIG_MX3_IPU                                  policy<{'arm64': '-'}>
+CONFIG_MX3_IPU_IRQS                             policy<{'arm64': '-'}>
+CONFIG_MXC4005                                  policy<{'arm64': 'n'}>
+CONFIG_MXC6255                                  policy<{'arm64': 'n'}>
+CONFIG_MXC_CLK                                  policy<{'arm64': '-'}>
+CONFIG_MXC_CLK_SCU                              policy<{'arm64': '-'}>
+CONFIG_MXS_DMA                                  policy<{'arm64': '-'}>
+CONFIG_MYRI10GE                                 policy<{'arm64': 'n'}>
+CONFIG_NATIONAL_PHY                             policy<{'arm64': 'y'}>
+CONFIG_NATSEMI                                  policy<{'arm64': 'n'}>
+CONFIG_NAU7802                                  policy<{'arm64': 'n'}>
+CONFIG_NCSI_OEM_CMD_GET_MAC                     policy<{'arm64': '-'}>
+CONFIG_ND_BLK                                   policy<{'arm64': '-'}>
+CONFIG_ND_BTT                                   policy<{'arm64': '-'}>
+CONFIG_ND_CLAIM                                 policy<{'arm64': '-'}>
+CONFIG_NE2K_PCI                                 policy<{'arm64': 'n'}>
+CONFIG_NEED_MULTIPLE_NODES                      policy<{'arm64': '-'}>
+CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK           policy<{'arm64': '-'}>
+CONFIG_NETCONSOLE                               policy<{'arm64': 'n'}>
+CONFIG_NETCONSOLE_DYNAMIC                       policy<{'arm64': '-'}>
+CONFIG_NETDEVSIM                                policy<{'arm64': 'n'}>
+CONFIG_NETDEV_NOTIFIER_ERROR_INJECT             policy<{'arm64': '-'}>
+CONFIG_NETFILTER_CONNCOUNT                      policy<{'arm64': '-'}>
+CONFIG_NETFILTER_FAMILY_ARP                     policy<{'arm64': '-'}>
+CONFIG_NETFILTER_NETLINK                        policy<{'arm64': 'y'}>
+CONFIG_NETFILTER_NETLINK_ACCT                   policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_NETLINK_GLUE_CT                policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_NETLINK_LOG                    policy<{'arm64': 'y'}>
+CONFIG_NETFILTER_NETLINK_OSF                    policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_NETLINK_QUEUE                  policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_SYNPROXY                       policy<{'arm64': '-'}>
+CONFIG_NETFILTER_XTABLES                        policy<{'arm64': 'y'}>
+CONFIG_NETFILTER_XT_CONNMARK                    policy<{'arm64': 'y'}>
+CONFIG_NETFILTER_XT_MARK                        policy<{'arm64': 'y'}>
+CONFIG_NETFILTER_XT_MATCH_BPF                   policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_MATCH_CLUSTER               policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES             policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_MATCH_CONNLABEL             policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT             policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_MATCH_CPU                   policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_MATCH_DCCP                  policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_MATCH_DEVGROUP              policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_MATCH_DSCP                  policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_MATCH_ECN                   policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_MATCH_ESP                   policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT             policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_MATCH_HELPER                policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_MATCH_HL                    policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_MATCH_IPCOMP                policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_MATCH_IPRANGE               policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_MATCH_IPVS                  policy<{'arm64': '-'}>
+CONFIG_NETFILTER_XT_MATCH_L2TP                  policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_MATCH_LENGTH                policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_MATCH_LIMIT                 policy<{'arm64': 'y'}>
+CONFIG_NETFILTER_XT_MATCH_MAC                   policy<{'arm64': 'y'}>
+CONFIG_NETFILTER_XT_MATCH_MARK                  policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT             policy<{'arm64': 'y'}>
+CONFIG_NETFILTER_XT_MATCH_NFACCT                policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_MATCH_OSF                   policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_MATCH_OWNER                 policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV               policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE               policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_MATCH_POLICY                policy<{'arm64': 'y'}>
+CONFIG_NETFILTER_XT_MATCH_QUOTA                 policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_MATCH_RATEEST               policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_MATCH_REALM                 policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_MATCH_RECENT                policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_MATCH_SCTP                  policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_MATCH_SOCKET                policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_MATCH_STATISTIC             policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_MATCH_STRING                policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_MATCH_TCPMSS                policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_MATCH_TIME                  policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_MATCH_U32                   policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_SET                         policy<{'arm64': '-'}>
+CONFIG_NETFILTER_XT_TARGET_AUDIT                policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY             policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_TARGET_CONNMARK             policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK          policy<{'arm64': '-'}>
+CONFIG_NETFILTER_XT_TARGET_CT                   policy<{'arm64': '-'}>
+CONFIG_NETFILTER_XT_TARGET_DSCP                 policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_TARGET_HL                   policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_TARGET_HMARK                policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER            policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_TARGET_LED                  policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_TARGET_LOG                  policy<{'arm64': 'y'}>
+CONFIG_NETFILTER_XT_TARGET_MARK                 policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_TARGET_NETMAP               policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_TARGET_NFLOG                policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE              policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_TARGET_NOTRACK              policy<{'arm64': '-'}>
+CONFIG_NETFILTER_XT_TARGET_RATEEST              policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_TARGET_REDIRECT             policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_TARGET_SECMARK              policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_TARGET_TCPMSS               policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP          policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_TARGET_TEE                  policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_TARGET_TPROXY               policy<{'arm64': 'n'}>
+CONFIG_NETFILTER_XT_TARGET_TRACE                policy<{'arm64': '-'}>
+CONFIG_NETPOLL                                  policy<{'arm64': '-'}>
+CONFIG_NETROM                                   policy<{'arm64': '-'}>
+CONFIG_NETXEN_NIC                               policy<{'arm64': 'n'}>
+CONFIG_NET_9P_RDMA                              policy<{'arm64': '-'}>
+CONFIG_NET_9P_VIRTIO                            policy<{'arm64': 'n'}>
+CONFIG_NET_9P_XEN                               policy<{'arm64': 'n'}>
+CONFIG_NET_ACT_BPF                              policy<{'arm64': '-'}>
+CONFIG_NET_ACT_CONNMARK                         policy<{'arm64': '-'}>
+CONFIG_NET_ACT_CSUM                             policy<{'arm64': '-'}>
+CONFIG_NET_ACT_CT                               policy<{'arm64': '-'}>
+CONFIG_NET_ACT_CTINFO                           policy<{'arm64': '-'}>
+CONFIG_NET_ACT_GACT                             policy<{'arm64': '-'}>
+CONFIG_NET_ACT_IFE                              policy<{'arm64': '-'}>
+CONFIG_NET_ACT_IPT                              policy<{'arm64': '-'}>
+CONFIG_NET_ACT_MIRRED                           policy<{'arm64': '-'}>
+CONFIG_NET_ACT_MPLS                             policy<{'arm64': '-'}>
+CONFIG_NET_ACT_NAT                              policy<{'arm64': '-'}>
+CONFIG_NET_ACT_PEDIT                            policy<{'arm64': '-'}>
+CONFIG_NET_ACT_POLICE                           policy<{'arm64': '-'}>
+CONFIG_NET_ACT_SAMPLE                           policy<{'arm64': '-'}>
+CONFIG_NET_ACT_SIMP                             policy<{'arm64': '-'}>
+CONFIG_NET_ACT_SKBEDIT                          policy<{'arm64': '-'}>
+CONFIG_NET_ACT_SKBMOD                           policy<{'arm64': '-'}>
+CONFIG_NET_ACT_TUNNEL_KEY                       policy<{'arm64': '-'}>
+CONFIG_NET_ACT_VLAN                             policy<{'arm64': '-'}>
+CONFIG_NET_CLS                                  policy<{'arm64': '-'}>
+CONFIG_NET_CLS_ACT                              policy<{'arm64': '-'}>
+CONFIG_NET_CLS_BASIC                            policy<{'arm64': '-'}>
+CONFIG_NET_CLS_BPF                              policy<{'arm64': '-'}>
+CONFIG_NET_CLS_CGROUP                           policy<{'arm64': '-'}>
+CONFIG_NET_CLS_FLOW                             policy<{'arm64': '-'}>
+CONFIG_NET_CLS_FLOWER                           policy<{'arm64': '-'}>
+CONFIG_NET_CLS_FW                               policy<{'arm64': '-'}>
+CONFIG_NET_CLS_MATCHALL                         policy<{'arm64': '-'}>
+CONFIG_NET_CLS_ROUTE4                           policy<{'arm64': '-'}>
+CONFIG_NET_CLS_U32                              policy<{'arm64': '-'}>
+CONFIG_NET_DEVLINK                              policy<{'arm64': '-'}>
+CONFIG_NET_DSA                                  policy<{'arm64': 'n'}>
+CONFIG_NET_DSA_BCM_SF2                          policy<{'arm64': '-'}>
+CONFIG_NET_DSA_LANTIQ_GSWIP                     policy<{'arm64': '-'}>
+CONFIG_NET_DSA_LOOP                             policy<{'arm64': '-'}>
+CONFIG_NET_DSA_MICROCHIP_KSZ8795                policy<{'arm64': '-'}>
+CONFIG_NET_DSA_MICROCHIP_KSZ8795_SPI            policy<{'arm64': '-'}>
+CONFIG_NET_DSA_MICROCHIP_KSZ9477                policy<{'arm64': '-'}>
+CONFIG_NET_DSA_MICROCHIP_KSZ9477_I2C            policy<{'arm64': '-'}>
+CONFIG_NET_DSA_MICROCHIP_KSZ9477_SPI            policy<{'arm64': '-'}>
+CONFIG_NET_DSA_MICROCHIP_KSZ_COMMON             policy<{'arm64': '-'}>
+CONFIG_NET_DSA_MT7530                           policy<{'arm64': '-'}>
+CONFIG_NET_DSA_MV88E6060                        policy<{'arm64': '-'}>
+CONFIG_NET_DSA_MV88E6XXX                        policy<{'arm64': '-'}>
+CONFIG_NET_DSA_MV88E6XXX_GLOBAL2                policy<{'arm64': '-'}>
+CONFIG_NET_DSA_MV88E6XXX_PTP                    policy<{'arm64': '-'}>
+CONFIG_NET_DSA_QCA8K                            policy<{'arm64': '-'}>
+CONFIG_NET_DSA_REALTEK_SMI                      policy<{'arm64': '-'}>
+CONFIG_NET_DSA_SJA1105                          policy<{'arm64': '-'}>
+CONFIG_NET_DSA_SJA1105_PTP                      policy<{'arm64': '-'}>
+CONFIG_NET_DSA_SJA1105_TAS                      policy<{'arm64': '-'}>
+CONFIG_NET_DSA_SMSC_LAN9303                     policy<{'arm64': '-'}>
+CONFIG_NET_DSA_SMSC_LAN9303_I2C                 policy<{'arm64': '-'}>
+CONFIG_NET_DSA_SMSC_LAN9303_MDIO                policy<{'arm64': '-'}>
+CONFIG_NET_DSA_TAG_8021Q                        policy<{'arm64': '-'}>
+CONFIG_NET_DSA_TAG_BRCM                         policy<{'arm64': '-'}>
+CONFIG_NET_DSA_TAG_BRCM_COMMON                  policy<{'arm64': '-'}>
+CONFIG_NET_DSA_TAG_BRCM_PREPEND                 policy<{'arm64': '-'}>
+CONFIG_NET_DSA_TAG_DSA                          policy<{'arm64': '-'}>
+CONFIG_NET_DSA_TAG_EDSA                         policy<{'arm64': '-'}>
+CONFIG_NET_DSA_TAG_GSWIP                        policy<{'arm64': '-'}>
+CONFIG_NET_DSA_TAG_KSZ                          policy<{'arm64': '-'}>
+CONFIG_NET_DSA_TAG_LAN9303                      policy<{'arm64': '-'}>
+CONFIG_NET_DSA_TAG_MTK                          policy<{'arm64': '-'}>
+CONFIG_NET_DSA_TAG_QCA                          policy<{'arm64': '-'}>
+CONFIG_NET_DSA_TAG_SJA1105                      policy<{'arm64': '-'}>
+CONFIG_NET_DSA_TAG_TRAILER                      policy<{'arm64': '-'}>
+CONFIG_NET_DSA_VITESSE_VSC73XX                  policy<{'arm64': '-'}>
+CONFIG_NET_DSA_VITESSE_VSC73XX_PLATFORM         policy<{'arm64': '-'}>
+CONFIG_NET_DSA_VITESSE_VSC73XX_SPI              policy<{'arm64': '-'}>
+CONFIG_NET_EGRESS                               policy<{'arm64': '-'}>
+CONFIG_NET_EMATCH                               policy<{'arm64': '-'}>
+CONFIG_NET_EMATCH_CANID                         policy<{'arm64': '-'}>
+CONFIG_NET_EMATCH_CMP                           policy<{'arm64': '-'}>
+CONFIG_NET_EMATCH_IPSET                         policy<{'arm64': '-'}>
+CONFIG_NET_EMATCH_IPT                           policy<{'arm64': '-'}>
+CONFIG_NET_EMATCH_META                          policy<{'arm64': '-'}>
+CONFIG_NET_EMATCH_NBYTE                         policy<{'arm64': '-'}>
+CONFIG_NET_EMATCH_STACK                         policy<{'arm64': '-'}>
+CONFIG_NET_EMATCH_TEXT                          policy<{'arm64': '-'}>
+CONFIG_NET_EMATCH_U32                           policy<{'arm64': '-'}>
+CONFIG_NET_FAILOVER                             policy<{'arm64': 'n'}>
+CONFIG_NET_FC                                   policy<{'arm64': 'n'}>
+CONFIG_NET_FOU                                  policy<{'arm64': 'n'}>
+CONFIG_NET_FOU_IP_TUNNELS                       policy<{'arm64': 'n'}>
+CONFIG_NET_IFE                                  policy<{'arm64': 'n'}>
+CONFIG_NET_IPGRE                                policy<{'arm64': '-'}>
+CONFIG_NET_IPGRE_BROADCAST                      policy<{'arm64': '-'}>
+CONFIG_NET_IPGRE_DEMUX                          policy<{'arm64': 'n'}>
+CONFIG_NET_IPIP                                 policy<{'arm64': 'n'}>
+CONFIG_NET_IPVTI                                policy<{'arm64': 'n'}>
+CONFIG_NET_IP_TUNNEL                            policy<{'arm64': 'y'}>
+CONFIG_NET_KEY                                  policy<{'arm64': 'y'}>
+CONFIG_NET_KEY_MIGRATE                          policy<{'arm64': 'y'}>
+CONFIG_NET_L3_MASTER_DEV                        policy<{'arm64': 'n'}>
+CONFIG_NET_NCSI                                 policy<{'arm64': 'n'}>
+CONFIG_NET_PKTGEN                               policy<{'arm64': 'y'}>
+CONFIG_NET_POLL_CONTROLLER                      policy<{'arm64': '-'}>
+CONFIG_NET_REDIRECT                             policy<{'arm64': '-'}>
+CONFIG_NET_SB1000                               policy<{'arm64': '-'}>
+CONFIG_NET_SCHED                                policy<{'arm64': 'n'}>
+CONFIG_NET_SCH_ATM                              policy<{'arm64': '-'}>
+CONFIG_NET_SCH_CAKE                             policy<{'arm64': '-'}>
+CONFIG_NET_SCH_CBQ                              policy<{'arm64': '-'}>
+CONFIG_NET_SCH_CBS                              policy<{'arm64': '-'}>
+CONFIG_NET_SCH_CHOKE                            policy<{'arm64': '-'}>
+CONFIG_NET_SCH_CODEL                            policy<{'arm64': '-'}>
+CONFIG_NET_SCH_DEFAULT                          policy<{'arm64': '-'}>
+CONFIG_NET_SCH_DRR                              policy<{'arm64': '-'}>
+CONFIG_NET_SCH_DSMARK                           policy<{'arm64': '-'}>
+CONFIG_NET_SCH_ETF                              policy<{'arm64': '-'}>
+CONFIG_NET_SCH_FIFO                             policy<{'arm64': '-'}>
+CONFIG_NET_SCH_FQ                               policy<{'arm64': '-'}>
+CONFIG_NET_SCH_FQ_CODEL                         policy<{'arm64': '-'}>
+CONFIG_NET_SCH_GRED                             policy<{'arm64': '-'}>
+CONFIG_NET_SCH_HFSC                             policy<{'arm64': '-'}>
+CONFIG_NET_SCH_HHF                              policy<{'arm64': '-'}>
+CONFIG_NET_SCH_HTB                              policy<{'arm64': '-'}>
+CONFIG_NET_SCH_INGRESS                          policy<{'arm64': '-'}>
+CONFIG_NET_SCH_MQPRIO                           policy<{'arm64': '-'}>
+CONFIG_NET_SCH_MULTIQ                           policy<{'arm64': '-'}>
+CONFIG_NET_SCH_NETEM                            policy<{'arm64': '-'}>
+CONFIG_NET_SCH_PIE                              policy<{'arm64': '-'}>
+CONFIG_NET_SCH_PLUG                             policy<{'arm64': '-'}>
+CONFIG_NET_SCH_PRIO                             policy<{'arm64': '-'}>
+CONFIG_NET_SCH_QFQ                              policy<{'arm64': '-'}>
+CONFIG_NET_SCH_RED                              policy<{'arm64': '-'}>
+CONFIG_NET_SCH_SFB                              policy<{'arm64': '-'}>
+CONFIG_NET_SCH_SFQ                              policy<{'arm64': '-'}>
+CONFIG_NET_SCH_SKBPRIO                          policy<{'arm64': '-'}>
+CONFIG_NET_SCH_TAPRIO                           policy<{'arm64': '-'}>
+CONFIG_NET_SCH_TBF                              policy<{'arm64': '-'}>
+CONFIG_NET_SCH_TEQL                             policy<{'arm64': '-'}>
+CONFIG_NET_SOCK_MSG                             policy<{'arm64': '-'}>
+CONFIG_NET_TC_SKB_EXT                           policy<{'arm64': '-'}>
+CONFIG_NET_TEAM                                 policy<{'arm64': 'n'}>
+CONFIG_NET_TEAM_MODE_ACTIVEBACKUP               policy<{'arm64': '-'}>
+CONFIG_NET_TEAM_MODE_BROADCAST                  policy<{'arm64': '-'}>
+CONFIG_NET_TEAM_MODE_LOADBALANCE                policy<{'arm64': '-'}>
+CONFIG_NET_TEAM_MODE_RANDOM                     policy<{'arm64': '-'}>
+CONFIG_NET_TEAM_MODE_ROUNDROBIN                 policy<{'arm64': '-'}>
+CONFIG_NET_TULIP                                policy<{'arm64': 'n'}>
+CONFIG_NET_VENDOR_ALLWINNER                     policy<{'arm64': '-'}>
+CONFIG_NET_VENDOR_FREESCALE                     policy<{'arm64': '-'}>
+CONFIG_NET_VENDOR_MEDIATEK                      policy<{'arm64': '-'}>
+CONFIG_NET_VENDOR_XILINX                        policy<{'arm64': 'y'}>
+CONFIG_NET_VRF                                  policy<{'arm64': '-'}>
+CONFIG_NET_XGENE                                policy<{'arm64': '-'}>
+CONFIG_NET_XGENE_V2                             policy<{'arm64': '-'}>
+CONFIG_NFC                                      policy<{'arm64': 'n'}>
+CONFIG_NFC_DIGITAL                              policy<{'arm64': '-'}>
+CONFIG_NFC_FDP                                  policy<{'arm64': '-'}>
+CONFIG_NFC_FDP_I2C                              policy<{'arm64': '-'}>
+CONFIG_NFC_HCI                                  policy<{'arm64': '-'}>
+CONFIG_NFC_MICROREAD                            policy<{'arm64': '-'}>
+CONFIG_NFC_MICROREAD_I2C                        policy<{'arm64': '-'}>
+CONFIG_NFC_MRVL                                 policy<{'arm64': '-'}>
+CONFIG_NFC_MRVL_I2C                             policy<{'arm64': '-'}>
+CONFIG_NFC_MRVL_SPI                             policy<{'arm64': '-'}>
+CONFIG_NFC_MRVL_UART                            policy<{'arm64': '-'}>
+CONFIG_NFC_MRVL_USB                             policy<{'arm64': '-'}>
+CONFIG_NFC_NCI                                  policy<{'arm64': '-'}>
+CONFIG_NFC_NCI_SPI                              policy<{'arm64': '-'}>
+CONFIG_NFC_NCI_UART                             policy<{'arm64': '-'}>
+CONFIG_NFC_NXP_NCI                              policy<{'arm64': '-'}>
+CONFIG_NFC_NXP_NCI_I2C                          policy<{'arm64': '-'}>
+CONFIG_NFC_PN533                                policy<{'arm64': '-'}>
+CONFIG_NFC_PN533_I2C                            policy<{'arm64': '-'}>
+CONFIG_NFC_PN533_USB                            policy<{'arm64': '-'}>
+CONFIG_NFC_PN544                                policy<{'arm64': '-'}>
+CONFIG_NFC_PN544_I2C                            policy<{'arm64': '-'}>
+CONFIG_NFC_PORT100                              policy<{'arm64': '-'}>
+CONFIG_NFC_S3FWRN5                              policy<{'arm64': '-'}>
+CONFIG_NFC_S3FWRN5_I2C                          policy<{'arm64': '-'}>
+CONFIG_NFC_SHDLC                                policy<{'arm64': '-'}>
+CONFIG_NFC_SIM                                  policy<{'arm64': '-'}>
+CONFIG_NFC_ST21NFCA                             policy<{'arm64': '-'}>
+CONFIG_NFC_ST21NFCA_I2C                         policy<{'arm64': '-'}>
+CONFIG_NFC_ST95HF                               policy<{'arm64': '-'}>
+CONFIG_NFC_ST_NCI                               policy<{'arm64': '-'}>
+CONFIG_NFC_ST_NCI_I2C                           policy<{'arm64': '-'}>
+CONFIG_NFC_ST_NCI_SPI                           policy<{'arm64': '-'}>
+CONFIG_NFC_TRF7970A                             policy<{'arm64': '-'}>
+CONFIG_NFIT_SECURITY_DEBUG                      policy<{'arm64': '-'}>
+CONFIG_NFP                                      policy<{'arm64': 'n'}>
+CONFIG_NFP_APP_ABM_NIC                          policy<{'arm64': '-'}>
+CONFIG_NFP_APP_FLOWER                           policy<{'arm64': '-'}>
+CONFIG_NFP_DEBUG                                policy<{'arm64': '-'}>
+CONFIG_NFS_ACL_SUPPORT                          policy<{'arm64': 'y'}>
+CONFIG_NFS_DEBUG                                policy<{'arm64': '-'}>
+CONFIG_NFS_FS                                   policy<{'arm64': 'y'}>
+CONFIG_NFS_FSCACHE                              policy<{'arm64': '-'}>
+CONFIG_NFS_SWAP                                 policy<{'arm64': 'n'}>
+CONFIG_NFS_V2                                   policy<{'arm64': 'y'}>
+CONFIG_NFS_V3                                   policy<{'arm64': 'y'}>
+CONFIG_NFS_V4                                   policy<{'arm64': 'y'}>
+CONFIG_NFS_V4_1_MIGRATION                       policy<{'arm64': 'n'}>
+CONFIG_NFTL                                     policy<{'arm64': 'n'}>
+CONFIG_NFTL_RW                                  policy<{'arm64': '-'}>
+CONFIG_NFT_BRIDGE_META                          policy<{'arm64': '-'}>
+CONFIG_NFT_BRIDGE_REJECT                        policy<{'arm64': '-'}>
+CONFIG_NFT_COMPAT                               policy<{'arm64': '-'}>
+CONFIG_NFT_CONNLIMIT                            policy<{'arm64': '-'}>
+CONFIG_NFT_COUNTER                              policy<{'arm64': '-'}>
+CONFIG_NFT_CT                                   policy<{'arm64': '-'}>
+CONFIG_NFT_DUP_IPV4                             policy<{'arm64': '-'}>
+CONFIG_NFT_DUP_IPV6                             policy<{'arm64': '-'}>
+CONFIG_NFT_DUP_NETDEV                           policy<{'arm64': '-'}>
+CONFIG_NFT_FIB                                  policy<{'arm64': '-'}>
+CONFIG_NFT_FIB_INET                             policy<{'arm64': '-'}>
+CONFIG_NFT_FIB_IPV4                             policy<{'arm64': '-'}>
+CONFIG_NFT_FIB_IPV6                             policy<{'arm64': '-'}>
+CONFIG_NFT_FIB_NETDEV                           policy<{'arm64': '-'}>
+CONFIG_NFT_FLOW_OFFLOAD                         policy<{'arm64': '-'}>
+CONFIG_NFT_FWD_NETDEV                           policy<{'arm64': '-'}>
+CONFIG_NFT_HASH                                 policy<{'arm64': '-'}>
+CONFIG_NFT_LIMIT                                policy<{'arm64': '-'}>
+CONFIG_NFT_LOG                                  policy<{'arm64': '-'}>
+CONFIG_NFT_MASQ                                 policy<{'arm64': '-'}>
+CONFIG_NFT_NAT                                  policy<{'arm64': '-'}>
+CONFIG_NFT_NUMGEN                               policy<{'arm64': '-'}>
+CONFIG_NFT_OBJREF                               policy<{'arm64': '-'}>
+CONFIG_NFT_OSF                                  policy<{'arm64': '-'}>
+CONFIG_NFT_QUEUE                                policy<{'arm64': '-'}>
+CONFIG_NFT_QUOTA                                policy<{'arm64': '-'}>
+CONFIG_NFT_REDIR                                policy<{'arm64': '-'}>
+CONFIG_NFT_REJECT                               policy<{'arm64': '-'}>
+CONFIG_NFT_REJECT_INET                          policy<{'arm64': '-'}>
+CONFIG_NFT_REJECT_IPV4                          policy<{'arm64': '-'}>
+CONFIG_NFT_REJECT_IPV6                          policy<{'arm64': '-'}>
+CONFIG_NFT_SOCKET                               policy<{'arm64': '-'}>
+CONFIG_NFT_SYNPROXY                             policy<{'arm64': '-'}>
+CONFIG_NFT_TPROXY                               policy<{'arm64': '-'}>
+CONFIG_NFT_TUNNEL                               policy<{'arm64': '-'}>
+CONFIG_NFT_XFRM                                 policy<{'arm64': '-'}>
+CONFIG_NF_CONNTRACK                             policy<{'arm64': 'y'}>
+CONFIG_NF_CONNTRACK_AMANDA                      policy<{'arm64': 'n'}>
+CONFIG_NF_CONNTRACK_BRIDGE                      policy<{'arm64': 'n'}>
+CONFIG_NF_CONNTRACK_BROADCAST                   policy<{'arm64': 'y'}>
+CONFIG_NF_CONNTRACK_EVENTS                      policy<{'arm64': 'n'}>
+CONFIG_NF_CONNTRACK_FTP                         policy<{'arm64': 'y'}>
+CONFIG_NF_CONNTRACK_H323                        policy<{'arm64': 'n'}>
+CONFIG_NF_CONNTRACK_IRC                         policy<{'arm64': 'n'}>
+CONFIG_NF_CONNTRACK_LABELS                      policy<{'arm64': 'n'}>
+CONFIG_NF_CONNTRACK_NETBIOS_NS                  policy<{'arm64': 'n'}>
+CONFIG_NF_CONNTRACK_PPTP                        policy<{'arm64': 'n'}>
+CONFIG_NF_CONNTRACK_PROCFS                      policy<{'arm64': 'y'}>
+CONFIG_NF_CONNTRACK_SANE                        policy<{'arm64': 'n'}>
+CONFIG_NF_CONNTRACK_SECMARK                     policy<{'arm64': 'n'}>
+CONFIG_NF_CONNTRACK_SIP                         policy<{'arm64': 'n'}>
+CONFIG_NF_CONNTRACK_SNMP                        policy<{'arm64': 'y'}>
+CONFIG_NF_CONNTRACK_TFTP                        policy<{'arm64': 'y'}>
+CONFIG_NF_CONNTRACK_TIMEOUT                     policy<{'arm64': 'n'}>
+CONFIG_NF_CONNTRACK_TIMESTAMP                   policy<{'arm64': 'n'}>
+CONFIG_NF_CONNTRACK_ZONES                       policy<{'arm64': 'n'}>
+CONFIG_NF_CT_NETLINK                            policy<{'arm64': 'y'}>
+CONFIG_NF_CT_NETLINK_HELPER                     policy<{'arm64': '-'}>
+CONFIG_NF_CT_NETLINK_TIMEOUT                    policy<{'arm64': '-'}>
+CONFIG_NF_CT_PROTO_GRE                          policy<{'arm64': '-'}>
+CONFIG_NF_DEFRAG_IPV4                           policy<{'arm64': 'y'}>
+CONFIG_NF_DEFRAG_IPV6                           policy<{'arm64': 'y'}>
+CONFIG_NF_DUP_IPV4                              policy<{'arm64': 'n'}>
+CONFIG_NF_DUP_IPV6                              policy<{'arm64': 'n'}>
+CONFIG_NF_DUP_NETDEV                            policy<{'arm64': '-'}>
+CONFIG_NF_FLOW_TABLE                            policy<{'arm64': '-'}>
+CONFIG_NF_FLOW_TABLE_INET                       policy<{'arm64': '-'}>
+CONFIG_NF_FLOW_TABLE_IPV4                       policy<{'arm64': '-'}>
+CONFIG_NF_FLOW_TABLE_IPV6                       policy<{'arm64': '-'}>
+CONFIG_NF_LOG_ARP                               policy<{'arm64': 'n'}>
+CONFIG_NF_LOG_BRIDGE                            policy<{'arm64': '-'}>
+CONFIG_NF_LOG_COMMON                            policy<{'arm64': 'y'}>
+CONFIG_NF_LOG_IPV4                              policy<{'arm64': 'y'}>
+CONFIG_NF_LOG_IPV6                              policy<{'arm64': 'y'}>
+CONFIG_NF_LOG_NETDEV                            policy<{'arm64': 'n'}>
+CONFIG_NF_NAT_AMANDA                            policy<{'arm64': '-'}>
+CONFIG_NF_NAT_H323                              policy<{'arm64': '-'}>
+CONFIG_NF_NAT_IRC                               policy<{'arm64': '-'}>
+CONFIG_NF_NAT_PPTP                              policy<{'arm64': '-'}>
+CONFIG_NF_NAT_REDIRECT                          policy<{'arm64': '-'}>
+CONFIG_NF_NAT_SIP                               policy<{'arm64': '-'}>
+CONFIG_NF_REJECT_IPV6                           policy<{'arm64': 'y'}>
+CONFIG_NF_SOCKET_IPV4                           policy<{'arm64': 'n'}>
+CONFIG_NF_SOCKET_IPV6                           policy<{'arm64': 'n'}>
+CONFIG_NF_TABLES                                policy<{'arm64': 'n'}>
+CONFIG_NF_TABLES_ARP                            policy<{'arm64': '-'}>
+CONFIG_NF_TABLES_BRIDGE                         policy<{'arm64': '-'}>
+CONFIG_NF_TABLES_INET                           policy<{'arm64': '-'}>
+CONFIG_NF_TABLES_IPV4                           policy<{'arm64': '-'}>
+CONFIG_NF_TABLES_IPV6                           policy<{'arm64': '-'}>
+CONFIG_NF_TABLES_NETDEV                         policy<{'arm64': '-'}>
+CONFIG_NF_TABLES_SET                            policy<{'arm64': '-'}>
+CONFIG_NF_TPROXY_IPV4                           policy<{'arm64': 'n'}>
+CONFIG_NF_TPROXY_IPV6                           policy<{'arm64': 'n'}>
+CONFIG_NILFS2_FS                                policy<{'arm64': 'n'}>
+CONFIG_NIU                                      policy<{'arm64': 'n'}>
+CONFIG_NI_XGE_MANAGEMENT_ENET                   policy<{'arm64': 'n'}>
+CONFIG_NL80211_TESTMODE                         policy<{'arm64': 'y'}>
+CONFIG_NLMON                                    policy<{'arm64': 'n'}>
+CONFIG_NLS_ASCII                                policy<{'arm64': 'n'}>
+CONFIG_NLS_CODEPAGE_1250                        policy<{'arm64': 'n'}>
+CONFIG_NLS_CODEPAGE_1251                        policy<{'arm64': 'n'}>
+CONFIG_NLS_CODEPAGE_737                         policy<{'arm64': 'n'}>
+CONFIG_NLS_CODEPAGE_775                         policy<{'arm64': 'n'}>
+CONFIG_NLS_CODEPAGE_850                         policy<{'arm64': 'n'}>
+CONFIG_NLS_CODEPAGE_852                         policy<{'arm64': 'n'}>
+CONFIG_NLS_CODEPAGE_855                         policy<{'arm64': 'n'}>
+CONFIG_NLS_CODEPAGE_857                         policy<{'arm64': 'n'}>
+CONFIG_NLS_CODEPAGE_860                         policy<{'arm64': 'n'}>
+CONFIG_NLS_CODEPAGE_861                         policy<{'arm64': 'n'}>
+CONFIG_NLS_CODEPAGE_862                         policy<{'arm64': 'n'}>
+CONFIG_NLS_CODEPAGE_863                         policy<{'arm64': 'n'}>
+CONFIG_NLS_CODEPAGE_864                         policy<{'arm64': 'n'}>
+CONFIG_NLS_CODEPAGE_865                         policy<{'arm64': 'n'}>
+CONFIG_NLS_CODEPAGE_866                         policy<{'arm64': 'n'}>
+CONFIG_NLS_CODEPAGE_869                         policy<{'arm64': 'n'}>
+CONFIG_NLS_CODEPAGE_874                         policy<{'arm64': 'n'}>
+CONFIG_NLS_CODEPAGE_932                         policy<{'arm64': 'n'}>
+CONFIG_NLS_CODEPAGE_936                         policy<{'arm64': 'n'}>
+CONFIG_NLS_CODEPAGE_949                         policy<{'arm64': 'n'}>
+CONFIG_NLS_CODEPAGE_950                         policy<{'arm64': 'n'}>
+CONFIG_NLS_DEFAULT                              policy<{'arm64': '"iso8859-1"'}>
+CONFIG_NLS_ISO8859_1                            policy<{'arm64': 'y'}>
+CONFIG_NLS_ISO8859_13                           policy<{'arm64': 'n'}>
+CONFIG_NLS_ISO8859_14                           policy<{'arm64': 'n'}>
+CONFIG_NLS_ISO8859_15                           policy<{'arm64': 'n'}>
+CONFIG_NLS_ISO8859_2                            policy<{'arm64': 'n'}>
+CONFIG_NLS_ISO8859_3                            policy<{'arm64': 'n'}>
+CONFIG_NLS_ISO8859_4                            policy<{'arm64': 'n'}>
+CONFIG_NLS_ISO8859_5                            policy<{'arm64': 'n'}>
+CONFIG_NLS_ISO8859_6                            policy<{'arm64': 'n'}>
+CONFIG_NLS_ISO8859_7                            policy<{'arm64': 'n'}>
+CONFIG_NLS_ISO8859_8                            policy<{'arm64': 'n'}>
+CONFIG_NLS_ISO8859_9                            policy<{'arm64': 'n'}>
+CONFIG_NLS_KOI8_R                               policy<{'arm64': 'n'}>
+CONFIG_NLS_KOI8_U                               policy<{'arm64': 'n'}>
+CONFIG_NLS_MAC_CELTIC                           policy<{'arm64': 'n'}>
+CONFIG_NLS_MAC_CENTEURO                         policy<{'arm64': 'n'}>
+CONFIG_NLS_MAC_CROATIAN                         policy<{'arm64': 'n'}>
+CONFIG_NLS_MAC_CYRILLIC                         policy<{'arm64': 'n'}>
+CONFIG_NLS_MAC_GAELIC                           policy<{'arm64': 'n'}>
+CONFIG_NLS_MAC_GREEK                            policy<{'arm64': 'n'}>
+CONFIG_NLS_MAC_ICELAND                          policy<{'arm64': 'n'}>
+CONFIG_NLS_MAC_INUIT                            policy<{'arm64': 'n'}>
+CONFIG_NLS_MAC_ROMAN                            policy<{'arm64': 'n'}>
+CONFIG_NLS_MAC_ROMANIAN                         policy<{'arm64': 'n'}>
+CONFIG_NLS_MAC_TURKISH                          policy<{'arm64': 'n'}>
+CONFIG_NLS_UTF8                                 policy<{'arm64': 'n'}>
+CONFIG_NOA1305                                  policy<{'arm64': 'n'}>
+CONFIG_NODES_SHIFT                              policy<{'arm64': '-'}>
+CONFIG_NORTEL_HERMES                            policy<{'arm64': '-'}>
+CONFIG_NOTIFIER_ERROR_INJECTION                 policy<{'arm64': 'n'}>
+CONFIG_NOUVEAU_DEBUG                            policy<{'arm64': '-'}>
+CONFIG_NOUVEAU_DEBUG_DEFAULT                    policy<{'arm64': '-'}>
+CONFIG_NOUVEAU_DEBUG_MMU                        policy<{'arm64': '-'}>
+CONFIG_NOZOMI                                   policy<{'arm64': 'n'}>
+CONFIG_NS83820                                  policy<{'arm64': 'n'}>
+CONFIG_NTB                                      policy<{'arm64': 'n'}>
+CONFIG_NTB_IDT                                  policy<{'arm64': '-'}>
+CONFIG_NTB_MSI                                  policy<{'arm64': '-'}>
+CONFIG_NTB_MSI_TEST                             policy<{'arm64': '-'}>
+CONFIG_NTB_NETDEV                               policy<{'arm64': '-'}>
+CONFIG_NTB_PERF                                 policy<{'arm64': '-'}>
+CONFIG_NTB_PINGPONG                             policy<{'arm64': '-'}>
+CONFIG_NTB_SWITCHTEC                            policy<{'arm64': '-'}>
+CONFIG_NTB_TOOL                                 policy<{'arm64': '-'}>
+CONFIG_NTB_TRANSPORT                            policy<{'arm64': '-'}>
+CONFIG_NTFS_DEBUG                               policy<{'arm64': '-'}>
+CONFIG_NTFS_FS                                  policy<{'arm64': 'n'}>
+CONFIG_NTFS_RW                                  policy<{'arm64': '-'}>
+CONFIG_NULL_TTY                                 policy<{'arm64': 'n'}>
+CONFIG_NUMA_BALANCING                           policy<{'arm64': '-'}>
+CONFIG_NVDIMM_KEYS                              policy<{'arm64': '-'}>
+CONFIG_NVMEM_BCM_OCOTP                          policy<{'arm64': '-'}>
+CONFIG_NVMEM_IMX_IIM                            policy<{'arm64': '-'}>
+CONFIG_NVMEM_IMX_OCOTP                          policy<{'arm64': '-'}>
+CONFIG_NVMEM_IMX_OCOTP_SCU                      policy<{'arm64': '-'}>
+CONFIG_NVMEM_REBOOT_MODE                        policy<{'arm64': 'n'}>
+CONFIG_NVMEM_SNVS_LPGPR                         policy<{'arm64': '-'}>
+CONFIG_NVMEM_SUNXI_SID                          policy<{'arm64': '-'}>
+CONFIG_NVME_CORE                                policy<{'arm64': '-'}>
+CONFIG_NVME_FABRICS                             policy<{'arm64': '-'}>
+CONFIG_NVME_FC                                  policy<{'arm64': 'n'}>
+CONFIG_NVME_MULTIPATH                           policy<{'arm64': '-'}>
+CONFIG_NVME_RDMA                                policy<{'arm64': '-'}>
+CONFIG_NVME_TARGET                              policy<{'arm64': 'n'}>
+CONFIG_NVME_TARGET_FC                           policy<{'arm64': '-'}>
+CONFIG_NVME_TARGET_FCLOOP                       policy<{'arm64': '-'}>
+CONFIG_NVME_TARGET_LOOP                         policy<{'arm64': '-'}>
+CONFIG_NVME_TARGET_RDMA                         policy<{'arm64': '-'}>
+CONFIG_NVME_TARGET_TCP                          policy<{'arm64': '-'}>
+CONFIG_NVME_TCP                                 policy<{'arm64': 'n'}>
+CONFIG_NXP_TJA11XX_PHY                          policy<{'arm64': 'n'}>
+CONFIG_N_HDLC                                   policy<{'arm64': '-'}>
+CONFIG_OBJAGG                                   policy<{'arm64': '-'}>
+CONFIG_OCFS2_DEBUG_FS                           policy<{'arm64': '-'}>
+CONFIG_OCFS2_DEBUG_MASKLOG                      policy<{'arm64': '-'}>
+CONFIG_OCFS2_FS                                 policy<{'arm64': 'n'}>
+CONFIG_OCFS2_FS_O2CB                            policy<{'arm64': '-'}>
+CONFIG_OCFS2_FS_STATS                           policy<{'arm64': '-'}>
+CONFIG_OCFS2_FS_USERSPACE_CLUSTER               policy<{'arm64': '-'}>
+CONFIG_OCTEONTX2_AF                             policy<{'arm64': 'n'}>
+CONFIG_OCTEONTX2_MBOX                           policy<{'arm64': '-'}>
+CONFIG_OF_CONFIGFS                              policy<{'arm64': 'y'}>
+CONFIG_OF_FPGA_REGION                           policy<{'arm64': 'y'}>
+CONFIG_OF_NUMA                                  policy<{'arm64': '-'}>
+CONFIG_OF_PMEM                                  policy<{'arm64': '-'}>
+CONFIG_OF_RECONFIG_NOTIFIER_ERROR_INJECT        policy<{'arm64': '-'}>
+CONFIG_OMAP2PLUS_MBOX                           policy<{'arm64': '-'}>
+CONFIG_OMAP_MBOX_KFIFO_SIZE                     policy<{'arm64': '-'}>
+CONFIG_OMAP_USB2                                policy<{'arm64': '-'}>
+CONFIG_OMFS_FS                                  policy<{'arm64': 'n'}>
+CONFIG_OPENVSWITCH_GENEVE                       policy<{'arm64': '-'}>
+CONFIG_OPENVSWITCH_GRE                          policy<{'arm64': '-'}>
+CONFIG_OPT3001                                  policy<{'arm64': 'n'}>
+CONFIG_OPTEE                                    policy<{'arm64': '-'}>
+CONFIG_OPTEE_SHM_NUM_PRIV_PAGES                 policy<{'arm64': '-'}>
+CONFIG_ORANGEFS_FS                              policy<{'arm64': 'n'}>
+CONFIG_ORINOCO_USB                              policy<{'arm64': '-'}>
+CONFIG_OSF_PARTITION                            policy<{'arm64': '-'}>
+CONFIG_OVERLAY_FS                               policy<{'arm64': 'y'}>
+CONFIG_OVERLAY_FS_XINO_AUTO                     policy<{'arm64': 'n'}>
+CONFIG_OWL_DMA                                  policy<{'arm64': '-'}>
+CONFIG_OWL_PM_DOMAINS                           policy<{'arm64': '-'}>
+CONFIG_OWL_PM_DOMAINS_HELPER                    policy<{'arm64': '-'}>
+CONFIG_OWL_TIMER                                policy<{'arm64': '-'}>
+CONFIG_P54_COMMON                               policy<{'arm64': 'n'}>
+CONFIG_P54_LEDS                                 policy<{'arm64': '-'}>
+CONFIG_P54_PCI                                  policy<{'arm64': '-'}>
+CONFIG_P54_SPI                                  policy<{'arm64': '-'}>
+CONFIG_P54_SPI_DEFAULT_EEPROM                   policy<{'arm64': '-'}>
+CONFIG_P54_USB                                  policy<{'arm64': '-'}>
+CONFIG_PA12203001                               policy<{'arm64': 'n'}>
+CONFIG_PACKING                                  policy<{'arm64': 'n'}>
+CONFIG_PADATA                                   policy<{'arm64': '-'}>
+CONFIG_PAGE_POOL                                policy<{'arm64': '-'}>
+CONFIG_PALMAS_GPADC                             policy<{'arm64': '-'}>
+CONFIG_PANEL                                    policy<{'arm64': '-'}>
+CONFIG_PANEL_CHANGE_MESSAGE                     policy<{'arm64': '-'}>
+CONFIG_PANEL_PARPORT                            policy<{'arm64': '-'}>
+CONFIG_PANEL_PROFILE                            policy<{'arm64': '-'}>
+CONFIG_PANTHERLORD_FF                           policy<{'arm64': '-'}>
+CONFIG_PARMAN                                   policy<{'arm64': '-'}>
+CONFIG_PARPORT                                  policy<{'arm64': 'n'}>
+CONFIG_PARPORT_1284                             policy<{'arm64': '-'}>
+CONFIG_PARPORT_AX88796                          policy<{'arm64': '-'}>
+CONFIG_PARPORT_NOT_PC                           policy<{'arm64': '-'}>
+CONFIG_PARPORT_PANEL                            policy<{'arm64': '-'}>
+CONFIG_PARTITION_ADVANCED                       policy<{'arm64': 'n'}>
+CONFIG_PATA_ACPI                                policy<{'arm64': '-'}>
+CONFIG_PATA_ALI                                 policy<{'arm64': '-'}>
+CONFIG_PATA_AMD                                 policy<{'arm64': '-'}>
+CONFIG_PATA_ARTOP                               policy<{'arm64': '-'}>
+CONFIG_PATA_ATIIXP                              policy<{'arm64': '-'}>
+CONFIG_PATA_ATP867X                             policy<{'arm64': '-'}>
+CONFIG_PATA_CMD640_PCI                          policy<{'arm64': '-'}>
+CONFIG_PATA_CMD64X                              policy<{'arm64': '-'}>
+CONFIG_PATA_CYPRESS                             policy<{'arm64': '-'}>
+CONFIG_PATA_EFAR                                policy<{'arm64': '-'}>
+CONFIG_PATA_HPT366                              policy<{'arm64': '-'}>
+CONFIG_PATA_HPT37X                              policy<{'arm64': '-'}>
+CONFIG_PATA_HPT3X2N                             policy<{'arm64': '-'}>
+CONFIG_PATA_HPT3X3                              policy<{'arm64': '-'}>
+CONFIG_PATA_IMX                                 policy<{'arm64': '-'}>
+CONFIG_PATA_IT8213                              policy<{'arm64': '-'}>
+CONFIG_PATA_IT821X                              policy<{'arm64': '-'}>
+CONFIG_PATA_JMICRON                             policy<{'arm64': '-'}>
+CONFIG_PATA_LEGACY                              policy<{'arm64': '-'}>
+CONFIG_PATA_MARVELL                             policy<{'arm64': '-'}>
+CONFIG_PATA_MPIIX                               policy<{'arm64': '-'}>
+CONFIG_PATA_NETCELL                             policy<{'arm64': '-'}>
+CONFIG_PATA_NINJA32                             policy<{'arm64': '-'}>
+CONFIG_PATA_NS87410                             policy<{'arm64': '-'}>
+CONFIG_PATA_NS87415                             policy<{'arm64': '-'}>
+CONFIG_PATA_OF_PLATFORM                         policy<{'arm64': '-'}>
+CONFIG_PATA_OLDPIIX                             policy<{'arm64': '-'}>
+CONFIG_PATA_OPTI                                policy<{'arm64': '-'}>
+CONFIG_PATA_OPTIDMA                             policy<{'arm64': '-'}>
+CONFIG_PATA_PDC2027X                            policy<{'arm64': '-'}>
+CONFIG_PATA_PDC_OLD                             policy<{'arm64': '-'}>
+CONFIG_PATA_PLATFORM                            policy<{'arm64': '-'}>
+CONFIG_PATA_RADISYS                             policy<{'arm64': '-'}>
+CONFIG_PATA_RDC                                 policy<{'arm64': '-'}>
+CONFIG_PATA_RZ1000                              policy<{'arm64': '-'}>
+CONFIG_PATA_SCH                                 policy<{'arm64': '-'}>
+CONFIG_PATA_SERVERWORKS                         policy<{'arm64': '-'}>
+CONFIG_PATA_SIL680                              policy<{'arm64': '-'}>
+CONFIG_PATA_SIS                                 policy<{'arm64': '-'}>
+CONFIG_PATA_TOSHIBA                             policy<{'arm64': '-'}>
+CONFIG_PATA_TRIFLEX                             policy<{'arm64': '-'}>
+CONFIG_PATA_VIA                                 policy<{'arm64': '-'}>
+CONFIG_PATA_WINBOND                             policy<{'arm64': '-'}>
+CONFIG_PC104                                    policy<{'arm64': 'n'}>
+CONFIG_PC300TOO                                 policy<{'arm64': '-'}>
+CONFIG_PCC                                      policy<{'arm64': '-'}>
+CONFIG_PCCARD                                   policy<{'arm64': 'n'}>
+CONFIG_PCF50633_ADC                             policy<{'arm64': '-'}>
+CONFIG_PCF50633_GPIO                            policy<{'arm64': '-'}>
+CONFIG_PCI200SYN                                policy<{'arm64': '-'}>
+CONFIG_PCIEAER                                  policy<{'arm64': '-'}>
+CONFIG_PCIEAER_INJECT                           policy<{'arm64': '-'}>
+CONFIG_PCIEASPM                                 policy<{'arm64': '-'}>
+CONFIG_PCIEASPM_PERFORMANCE                     policy<{'arm64': '-'}>
+CONFIG_PCIEASPM_POWERSAVE                       policy<{'arm64': '-'}>
+CONFIG_PCIEASPM_POWER_SUPERSAVE                 policy<{'arm64': '-'}>
+CONFIG_PCIE_AL                                  policy<{'arm64': 'n'}>
+CONFIG_PCIE_ALTERA                              policy<{'arm64': 'n'}>
+CONFIG_PCIE_ALTERA_MSI                          policy<{'arm64': '-'}>
+CONFIG_PCIE_ARMADA_8K                           policy<{'arm64': '-'}>
+CONFIG_PCIE_BW                                  policy<{'arm64': '-'}>
+CONFIG_PCIE_CADENCE                             policy<{'arm64': '-'}>
+CONFIG_PCIE_CADENCE_EP                          policy<{'arm64': '-'}>
+CONFIG_PCIE_CADENCE_HOST                        policy<{'arm64': 'n'}>
+CONFIG_PCIE_DPC                                 policy<{'arm64': '-'}>
+CONFIG_PCIE_DW                                  policy<{'arm64': '-'}>
+CONFIG_PCIE_DW_EP                               policy<{'arm64': '-'}>
+CONFIG_PCIE_DW_HOST                             policy<{'arm64': '-'}>
+CONFIG_PCIE_DW_PLAT                             policy<{'arm64': '-'}>
+CONFIG_PCIE_DW_PLAT_EP                          policy<{'arm64': '-'}>
+CONFIG_PCIE_DW_PLAT_HOST                        policy<{'arm64': 'n'}>
+CONFIG_PCIE_ECRC                                policy<{'arm64': '-'}>
+CONFIG_PCIE_HISI_STB                            policy<{'arm64': '-'}>
+CONFIG_PCIE_IPROC                               policy<{'arm64': '-'}>
+CONFIG_PCIE_IPROC_MSI                           policy<{'arm64': '-'}>
+CONFIG_PCIE_IPROC_PLATFORM                      policy<{'arm64': '-'}>
+CONFIG_PCIE_KIRIN                               policy<{'arm64': 'n'}>
+CONFIG_PCIE_MEDIATEK                            policy<{'arm64': '-'}>
+CONFIG_PCIE_MOBIVEIL                            policy<{'arm64': 'n'}>
+CONFIG_PCIE_PME                                 policy<{'arm64': '-'}>
+CONFIG_PCIE_PTM                                 policy<{'arm64': '-'}>
+CONFIG_PCIE_QCOM                                policy<{'arm64': '-'}>
+CONFIG_PCIE_RCAR                                policy<{'arm64': '-'}>
+CONFIG_PCIE_ROCKCHIP                            policy<{'arm64': '-'}>
+CONFIG_PCIE_ROCKCHIP_EP                         policy<{'arm64': '-'}>
+CONFIG_PCIE_ROCKCHIP_HOST                       policy<{'arm64': '-'}>
+CONFIG_PCIE_XDMA_PL                             policy<{'arm64': 'y'}>
+CONFIG_PCIPCWATCHDOG                            policy<{'arm64': 'n'}>
+CONFIG_PCI_AARDVARK                             policy<{'arm64': '-'}>
+CONFIG_PCI_ATMEL                                policy<{'arm64': '-'}>
+CONFIG_PCI_ATS                                  policy<{'arm64': '-'}>
+CONFIG_PCI_BRIDGE_EMUL                          policy<{'arm64': '-'}>
+CONFIG_PCI_ECAM                                 policy<{'arm64': '-'}>
+CONFIG_PCI_ENDPOINT                             policy<{'arm64': 'n'}>
+CONFIG_PCI_ENDPOINT_CONFIGFS                    policy<{'arm64': '-'}>
+CONFIG_PCI_EPF_TEST                             policy<{'arm64': '-'}>
+CONFIG_PCI_FTPCI100                             policy<{'arm64': 'n'}>
+CONFIG_PCI_HISI                                 policy<{'arm64': 'n'}>
+CONFIG_PCI_HOST_COMMON                          policy<{'arm64': '-'}>
+CONFIG_PCI_HOST_GENERIC                         policy<{'arm64': 'n'}>
+CONFIG_PCI_HOST_THUNDER_ECAM                    policy<{'arm64': 'n'}>
+CONFIG_PCI_HOST_THUNDER_PEM                     policy<{'arm64': 'n'}>
+CONFIG_PCI_IMX6                                 policy<{'arm64': '-'}>
+CONFIG_PCI_IOV                                  policy<{'arm64': 'n'}>
+CONFIG_PCI_KEYSTONE                             policy<{'arm64': '-'}>
+CONFIG_PCI_KEYSTONE_EP                          policy<{'arm64': '-'}>
+CONFIG_PCI_KEYSTONE_HOST                        policy<{'arm64': '-'}>
+CONFIG_PCI_LAYERSCAPE                           policy<{'arm64': '-'}>
+CONFIG_PCI_LAYERSCAPE_EP                        policy<{'arm64': '-'}>
+CONFIG_PCI_PASID                                policy<{'arm64': 'n'}>
+CONFIG_PCI_PF_STUB                              policy<{'arm64': '-'}>
+CONFIG_PCI_PRI                                  policy<{'arm64': 'n'}>
+CONFIG_PCI_REALLOC_ENABLE_AUTO                  policy<{'arm64': '-'}>
+CONFIG_PCI_STUB                                 policy<{'arm64': 'n'}>
+CONFIG_PCI_SW_SWITCHTEC                         policy<{'arm64': 'n'}>
+CONFIG_PCI_XGENE                                policy<{'arm64': 'n'}>
+CONFIG_PCI_XGENE_MSI                            policy<{'arm64': '-'}>
+CONFIG_PCMCIA                                   policy<{'arm64': '-'}>
+CONFIG_PCMCIA_XIRCOM                            policy<{'arm64': '-'}>
+CONFIG_PCNET32                                  policy<{'arm64': 'n'}>
+CONFIG_PDA_POWER                                policy<{'arm64': 'n'}>
+CONFIG_PDC_ADMA                                 policy<{'arm64': '-'}>
+CONFIG_PERSISTENT_KEYRINGS                      policy<{'arm64': 'n'}>
+CONFIG_PHANTOM                                  policy<{'arm64': 'n'}>
+CONFIG_PHONET                                   policy<{'arm64': 'n'}>
+CONFIG_PHYLINK                                  policy<{'arm64': '-'}>
+CONFIG_PHY_AM654_SERDES                         policy<{'arm64': '-'}>
+CONFIG_PHY_BCM_NS_USB2                          policy<{'arm64': '-'}>
+CONFIG_PHY_BCM_NS_USB3                          policy<{'arm64': '-'}>
+CONFIG_PHY_BCM_SR_PCIE                          policy<{'arm64': '-'}>
+CONFIG_PHY_BCM_SR_USB                           policy<{'arm64': '-'}>
+CONFIG_PHY_BERLIN_SATA                          policy<{'arm64': '-'}>
+CONFIG_PHY_BERLIN_USB                           policy<{'arm64': '-'}>
+CONFIG_PHY_BRCM_SATA                            policy<{'arm64': '-'}>
+CONFIG_PHY_BRCM_USB                             policy<{'arm64': '-'}>
+CONFIG_PHY_CADENCE_DP                           policy<{'arm64': 'n'}>
+CONFIG_PHY_CADENCE_DPHY                         policy<{'arm64': 'n'}>
+CONFIG_PHY_CADENCE_SIERRA                       policy<{'arm64': 'n'}>
+CONFIG_PHY_CPCAP_USB                            policy<{'arm64': 'n'}>
+CONFIG_PHY_FSL_IMX8MQ_USB                       policy<{'arm64': 'n'}>
+CONFIG_PHY_HI3660_USB                           policy<{'arm64': '-'}>
+CONFIG_PHY_HI6220_USB                           policy<{'arm64': '-'}>
+CONFIG_PHY_HISI_INNO_USB2                       policy<{'arm64': '-'}>
+CONFIG_PHY_HISTB_COMBPHY                        policy<{'arm64': '-'}>
+CONFIG_PHY_MAPPHONE_MDM6600                     policy<{'arm64': 'n'}>
+CONFIG_PHY_MESON8B_USB2                         policy<{'arm64': '-'}>
+CONFIG_PHY_MESON_G12A_USB2                      policy<{'arm64': '-'}>
+CONFIG_PHY_MESON_G12A_USB3_PCIE                 policy<{'arm64': '-'}>
+CONFIG_PHY_MESON_GXL_USB2                       policy<{'arm64': '-'}>
+CONFIG_PHY_MESON_GXL_USB3                       policy<{'arm64': '-'}>
+CONFIG_PHY_MIXEL_MIPI_DPHY                      policy<{'arm64': 'n'}>
+CONFIG_PHY_MTK_TPHY                             policy<{'arm64': '-'}>
+CONFIG_PHY_MTK_UFS                              policy<{'arm64': '-'}>
+CONFIG_PHY_MTK_XSPHY                            policy<{'arm64': '-'}>
+CONFIG_PHY_MVEBU_A3700_COMPHY                   policy<{'arm64': '-'}>
+CONFIG_PHY_MVEBU_A3700_UTMI                     policy<{'arm64': '-'}>
+CONFIG_PHY_MVEBU_A38X_COMPHY                    policy<{'arm64': '-'}>
+CONFIG_PHY_MVEBU_CP110_COMPHY                   policy<{'arm64': '-'}>
+CONFIG_PHY_NS2_PCIE                             policy<{'arm64': '-'}>
+CONFIG_PHY_NS2_USB_DRD                          policy<{'arm64': '-'}>
+CONFIG_PHY_OCELOT_SERDES                        policy<{'arm64': '-'}>
+CONFIG_PHY_PXA_28NM_HSIC                        policy<{'arm64': 'n'}>
+CONFIG_PHY_PXA_28NM_USB2                        policy<{'arm64': 'n'}>
+CONFIG_PHY_QCOM_APQ8064_SATA                    policy<{'arm64': '-'}>
+CONFIG_PHY_QCOM_IPQ806X_SATA                    policy<{'arm64': '-'}>
+CONFIG_PHY_QCOM_PCIE2                           policy<{'arm64': '-'}>
+CONFIG_PHY_QCOM_QMP                             policy<{'arm64': '-'}>
+CONFIG_PHY_QCOM_QUSB2                           policy<{'arm64': '-'}>
+CONFIG_PHY_QCOM_UFS                             policy<{'arm64': '-'}>
+CONFIG_PHY_QCOM_UFS_14NM                        policy<{'arm64': '-'}>
+CONFIG_PHY_QCOM_USB_HS                          policy<{'arm64': '-'}>
+CONFIG_PHY_QCOM_USB_HSIC                        policy<{'arm64': '-'}>
+CONFIG_PHY_RCAR_GEN2                            policy<{'arm64': '-'}>
+CONFIG_PHY_RCAR_GEN3_PCIE                       policy<{'arm64': '-'}>
+CONFIG_PHY_RCAR_GEN3_USB2                       policy<{'arm64': '-'}>
+CONFIG_PHY_RCAR_GEN3_USB3                       policy<{'arm64': '-'}>
+CONFIG_PHY_ROCKCHIP_DP                          policy<{'arm64': '-'}>
+CONFIG_PHY_ROCKCHIP_EMMC                        policy<{'arm64': '-'}>
+CONFIG_PHY_ROCKCHIP_INNO_HDMI                   policy<{'arm64': '-'}>
+CONFIG_PHY_ROCKCHIP_INNO_USB2                   policy<{'arm64': '-'}>
+CONFIG_PHY_ROCKCHIP_PCIE                        policy<{'arm64': '-'}>
+CONFIG_PHY_ROCKCHIP_TYPEC                       policy<{'arm64': '-'}>
+CONFIG_PHY_ROCKCHIP_USB                         policy<{'arm64': '-'}>
+CONFIG_PHY_SAMSUNG_USB2                         policy<{'arm64': '-'}>
+CONFIG_PHY_SUN4I_USB                            policy<{'arm64': '-'}>
+CONFIG_PHY_SUN6I_MIPI_DPHY                      policy<{'arm64': '-'}>
+CONFIG_PHY_SUN9I_USB                            policy<{'arm64': '-'}>
+CONFIG_PHY_TUSB1210                             policy<{'arm64': '-'}>
+CONFIG_PHY_XGENE                                policy<{'arm64': 'n'}>
+CONFIG_PHY_XILINX_ZYNQMP                        policy<{'arm64': 'y'}>
+CONFIG_PI433                                    policy<{'arm64': 'n'}>
+CONFIG_PINCTRL_AMD                              policy<{'arm64': 'n'}>
+CONFIG_PINCTRL_APQ8064                          policy<{'arm64': '-'}>
+CONFIG_PINCTRL_APQ8084                          policy<{'arm64': '-'}>
+CONFIG_PINCTRL_ARMADA_37XX                      policy<{'arm64': '-'}>
+CONFIG_PINCTRL_ARMADA_AP806                     policy<{'arm64': '-'}>
+CONFIG_PINCTRL_ARMADA_CP110                     policy<{'arm64': '-'}>
+CONFIG_PINCTRL_AS370                            policy<{'arm64': '-'}>
+CONFIG_PINCTRL_AS3722                           policy<{'arm64': '-'}>
+CONFIG_PINCTRL_AXP209                           policy<{'arm64': '-'}>
+CONFIG_PINCTRL_BCM2835                          policy<{'arm64': '-'}>
+CONFIG_PINCTRL_BERLIN                           policy<{'arm64': '-'}>
+CONFIG_PINCTRL_BERLIN_BG4CT                     policy<{'arm64': '-'}>
+CONFIG_PINCTRL_BM1880                           policy<{'arm64': '-'}>
+CONFIG_PINCTRL_CS47L15                          policy<{'arm64': '-'}>
+CONFIG_PINCTRL_CS47L35                          policy<{'arm64': '-'}>
+CONFIG_PINCTRL_CS47L85                          policy<{'arm64': '-'}>
+CONFIG_PINCTRL_CS47L90                          policy<{'arm64': '-'}>
+CONFIG_PINCTRL_CS47L92                          policy<{'arm64': '-'}>
+CONFIG_PINCTRL_IMX                              policy<{'arm64': '-'}>
+CONFIG_PINCTRL_IMX8MM                           policy<{'arm64': '-'}>
+CONFIG_PINCTRL_IMX8MN                           policy<{'arm64': '-'}>
+CONFIG_PINCTRL_IMX8MQ                           policy<{'arm64': '-'}>
+CONFIG_PINCTRL_IMX8QM                           policy<{'arm64': '-'}>
+CONFIG_PINCTRL_IMX8QXP                          policy<{'arm64': '-'}>
+CONFIG_PINCTRL_IMX_SCU                          policy<{'arm64': '-'}>
+CONFIG_PINCTRL_IPQ4019                          policy<{'arm64': '-'}>
+CONFIG_PINCTRL_IPQ8064                          policy<{'arm64': '-'}>
+CONFIG_PINCTRL_IPQ8074                          policy<{'arm64': '-'}>
+CONFIG_PINCTRL_IPROC_GPIO                       policy<{'arm64': '-'}>
+CONFIG_PINCTRL_LOCHNAGAR                        policy<{'arm64': '-'}>
+CONFIG_PINCTRL_MADERA                           policy<{'arm64': '-'}>
+CONFIG_PINCTRL_MAX77620                         policy<{'arm64': '-'}>
+CONFIG_PINCTRL_MCP23S08                         policy<{'arm64': 'n'}>
+CONFIG_PINCTRL_MDM9615                          policy<{'arm64': '-'}>
+CONFIG_PINCTRL_MESON                            policy<{'arm64': '-'}>
+CONFIG_PINCTRL_MESON8_PMX                       policy<{'arm64': '-'}>
+CONFIG_PINCTRL_MESON_AXG                        policy<{'arm64': '-'}>
+CONFIG_PINCTRL_MESON_AXG_PMX                    policy<{'arm64': '-'}>
+CONFIG_PINCTRL_MESON_G12A                       policy<{'arm64': '-'}>
+CONFIG_PINCTRL_MESON_GXBB                       policy<{'arm64': '-'}>
+CONFIG_PINCTRL_MESON_GXL                        policy<{'arm64': '-'}>
+CONFIG_PINCTRL_MSM                              policy<{'arm64': '-'}>
+CONFIG_PINCTRL_MSM8660                          policy<{'arm64': '-'}>
+CONFIG_PINCTRL_MSM8916                          policy<{'arm64': '-'}>
+CONFIG_PINCTRL_MSM8960                          policy<{'arm64': '-'}>
+CONFIG_PINCTRL_MSM8994                          policy<{'arm64': '-'}>
+CONFIG_PINCTRL_MSM8996                          policy<{'arm64': '-'}>
+CONFIG_PINCTRL_MSM8998                          policy<{'arm64': '-'}>
+CONFIG_PINCTRL_MSM8X74                          policy<{'arm64': '-'}>
+CONFIG_PINCTRL_MT2712                           policy<{'arm64': '-'}>
+CONFIG_PINCTRL_MT6397                           policy<{'arm64': '-'}>
+CONFIG_PINCTRL_MT6765                           policy<{'arm64': '-'}>
+CONFIG_PINCTRL_MT6797                           policy<{'arm64': '-'}>
+CONFIG_PINCTRL_MT7622                           policy<{'arm64': '-'}>
+CONFIG_PINCTRL_MT8173                           policy<{'arm64': '-'}>
+CONFIG_PINCTRL_MT8183                           policy<{'arm64': '-'}>
+CONFIG_PINCTRL_MT8516                           policy<{'arm64': '-'}>
+CONFIG_PINCTRL_MTK                              policy<{'arm64': '-'}>
+CONFIG_PINCTRL_MTK_MOORE                        policy<{'arm64': '-'}>
+CONFIG_PINCTRL_MTK_PARIS                        policy<{'arm64': '-'}>
+CONFIG_PINCTRL_MVEBU                            policy<{'arm64': '-'}>
+CONFIG_PINCTRL_NS2_MUX                          policy<{'arm64': '-'}>
+CONFIG_PINCTRL_OCELOT                           policy<{'arm64': 'n'}>
+CONFIG_PINCTRL_OWL                              policy<{'arm64': '-'}>
+CONFIG_PINCTRL_PALMAS                           policy<{'arm64': '-'}>
+CONFIG_PINCTRL_PFC_R8A774A1                     policy<{'arm64': '-'}>
+CONFIG_PINCTRL_PFC_R8A774C0                     policy<{'arm64': '-'}>
+CONFIG_PINCTRL_PFC_R8A7795                      policy<{'arm64': '-'}>
+CONFIG_PINCTRL_PFC_R8A7796                      policy<{'arm64': '-'}>
+CONFIG_PINCTRL_PFC_R8A77965                     policy<{'arm64': '-'}>
+CONFIG_PINCTRL_PFC_R8A77970                     policy<{'arm64': '-'}>
+CONFIG_PINCTRL_PFC_R8A77980                     policy<{'arm64': '-'}>
+CONFIG_PINCTRL_PFC_R8A77990                     policy<{'arm64': '-'}>
+CONFIG_PINCTRL_PFC_R8A77995                     policy<{'arm64': '-'}>
+CONFIG_PINCTRL_QCOM_SPMI_PMIC                   policy<{'arm64': '-'}>
+CONFIG_PINCTRL_QCOM_SSBI_PMIC                   policy<{'arm64': '-'}>
+CONFIG_PINCTRL_QCS404                           policy<{'arm64': '-'}>
+CONFIG_PINCTRL_QDF2XXX                          policy<{'arm64': '-'}>
+CONFIG_PINCTRL_RK805                            policy<{'arm64': '-'}>
+CONFIG_PINCTRL_ROCKCHIP                         policy<{'arm64': '-'}>
+CONFIG_PINCTRL_S700                             policy<{'arm64': '-'}>
+CONFIG_PINCTRL_S900                             policy<{'arm64': '-'}>
+CONFIG_PINCTRL_SC7180                           policy<{'arm64': '-'}>
+CONFIG_PINCTRL_SDM660                           policy<{'arm64': '-'}>
+CONFIG_PINCTRL_SDM845                           policy<{'arm64': '-'}>
+CONFIG_PINCTRL_SH_PFC                           policy<{'arm64': '-'}>
+CONFIG_PINCTRL_SINGLE                           policy<{'arm64': 'n'}>
+CONFIG_PINCTRL_SM8150                           policy<{'arm64': '-'}>
+CONFIG_PINCTRL_SPRD                             policy<{'arm64': '-'}>
+CONFIG_PINCTRL_SPRD_SC9860                      policy<{'arm64': '-'}>
+CONFIG_PINCTRL_STMFX                            policy<{'arm64': 'n'}>
+CONFIG_PINCTRL_SUN4I_A10                        policy<{'arm64': '-'}>
+CONFIG_PINCTRL_SUN50I_A64                       policy<{'arm64': '-'}>
+CONFIG_PINCTRL_SUN50I_A64_R                     policy<{'arm64': '-'}>
+CONFIG_PINCTRL_SUN50I_H5                        policy<{'arm64': '-'}>
+CONFIG_PINCTRL_SUN50I_H6                        policy<{'arm64': '-'}>
+CONFIG_PINCTRL_SUN50I_H6_R                      policy<{'arm64': '-'}>
+CONFIG_PINCTRL_SUN5I                            policy<{'arm64': '-'}>
+CONFIG_PINCTRL_SUN6I_A31                        policy<{'arm64': '-'}>
+CONFIG_PINCTRL_SUN6I_A31_R                      policy<{'arm64': '-'}>
+CONFIG_PINCTRL_SUN8I_A23                        policy<{'arm64': '-'}>
+CONFIG_PINCTRL_SUN8I_A23_R                      policy<{'arm64': '-'}>
+CONFIG_PINCTRL_SUN8I_A33                        policy<{'arm64': '-'}>
+CONFIG_PINCTRL_SUN8I_A83T                       policy<{'arm64': '-'}>
+CONFIG_PINCTRL_SUN8I_A83T_R                     policy<{'arm64': '-'}>
+CONFIG_PINCTRL_SUN8I_H3                         policy<{'arm64': '-'}>
+CONFIG_PINCTRL_SUN8I_H3_R                       policy<{'arm64': '-'}>
+CONFIG_PINCTRL_SUN8I_V3S                        policy<{'arm64': '-'}>
+CONFIG_PINCTRL_SUN9I_A80                        policy<{'arm64': '-'}>
+CONFIG_PINCTRL_SUN9I_A80_R                      policy<{'arm64': '-'}>
+CONFIG_PINCTRL_SUNXI                            policy<{'arm64': '-'}>
+CONFIG_PINCTRL_SX150X                           policy<{'arm64': 'n'}>
+CONFIG_PINCTRL_ZYNQMP                           policy<{'arm64': 'y'}>
+CONFIG_PKCS7_TEST_KEY                           policy<{'arm64': 'n'}>
+CONFIG_PKCS8_PRIVATE_KEY_PARSER                 policy<{'arm64': 'n'}>
+CONFIG_PL320_MBOX                               policy<{'arm64': 'n'}>
+CONFIG_PL330_DMA                                policy<{'arm64': 'n'}>
+CONFIG_PLATFORM_MHU                             policy<{'arm64': 'n'}>
+CONFIG_PLATFORM_SI4713                          policy<{'arm64': '-'}>
+CONFIG_PLIP                                     policy<{'arm64': '-'}>
+CONFIG_PLX_HERMES                               policy<{'arm64': '-'}>
+CONFIG_PM8916_WATCHDOG                          policy<{'arm64': '-'}>
+CONFIG_PMBUS                                    policy<{'arm64': 'y'}>
+CONFIG_PMIC_ADP5520                             policy<{'arm64': 'n'}>
+CONFIG_PMIC_DA903X                              policy<{'arm64': 'n'}>
+CONFIG_PMIC_DA9052                              policy<{'arm64': '-'}>
+CONFIG_PMIC_OPREGION                            policy<{'arm64': '-'}>
+CONFIG_PMS7003                                  policy<{'arm64': 'n'}>
+CONFIG_PM_ADVANCED_DEBUG                        policy<{'arm64': '-'}>
+CONFIG_PM_DEBUG                                 policy<{'arm64': 'n'}>
+CONFIG_PM_DEVFREQ                               policy<{'arm64': 'n'}>
+CONFIG_PM_DEVFREQ_EVENT                         policy<{'arm64': '-'}>
+CONFIG_PM_NOTIFIER_ERROR_INJECT                 policy<{'arm64': '-'}>
+CONFIG_PM_SLEEP_DEBUG                           policy<{'arm64': '-'}>
+CONFIG_PM_TEST_SUSPEND                          policy<{'arm64': '-'}>
+CONFIG_PM_WAKELOCKS                             policy<{'arm64': 'n'}>
+CONFIG_PM_WAKELOCKS_GC                          policy<{'arm64': '-'}>
+CONFIG_PM_WAKELOCKS_LIMIT                       policy<{'arm64': '-'}>
+CONFIG_PNFS_FILE_LAYOUT                         policy<{'arm64': 'y'}>
+CONFIG_PNFS_FLEXFILE_LAYOUT                     policy<{'arm64': 'y'}>
+CONFIG_PNP                                      policy<{'arm64': '-'}>
+CONFIG_PNPACPI                                  policy<{'arm64': '-'}>
+CONFIG_PNP_DEBUG_MESSAGES                       policy<{'arm64': '-'}>
+CONFIG_POWERCAP                                 policy<{'arm64': 'n'}>
+CONFIG_POWER_AVS                                policy<{'arm64': 'n'}>
+CONFIG_POWER_RESET_AS3722                       policy<{'arm64': '-'}>
+CONFIG_POWER_RESET_BRCMSTB                      policy<{'arm64': '-'}>
+CONFIG_POWER_RESET_GPIO                         policy<{'arm64': 'n'}>
+CONFIG_POWER_RESET_GPIO_RESTART                 policy<{'arm64': 'n'}>
+CONFIG_POWER_RESET_HISI                         policy<{'arm64': '-'}>
+CONFIG_POWER_RESET_MSM                          policy<{'arm64': '-'}>
+CONFIG_POWER_RESET_QCOM_PON                     policy<{'arm64': '-'}>
+CONFIG_POWER_RESET_RESTART                      policy<{'arm64': 'n'}>
+CONFIG_POWER_RESET_SC27XX                       policy<{'arm64': '-'}>
+CONFIG_POWER_RESET_SYSCON                       policy<{'arm64': 'n'}>
+CONFIG_POWER_RESET_SYSCON_POWEROFF              policy<{'arm64': 'n'}>
+CONFIG_POWER_RESET_VEXPRESS                     policy<{'arm64': '-'}>
+CONFIG_PPDEV                                    policy<{'arm64': '-'}>
+CONFIG_PPP                                      policy<{'arm64': 'n'}>
+CONFIG_PPPOATM                                  policy<{'arm64': '-'}>
+CONFIG_PPPOE                                    policy<{'arm64': '-'}>
+CONFIG_PPPOL2TP                                 policy<{'arm64': '-'}>
+CONFIG_PPP_ASYNC                                policy<{'arm64': '-'}>
+CONFIG_PPP_BSDCOMP                              policy<{'arm64': '-'}>
+CONFIG_PPP_DEFLATE                              policy<{'arm64': '-'}>
+CONFIG_PPP_FILTER                               policy<{'arm64': '-'}>
+CONFIG_PPP_MPPE                                 policy<{'arm64': '-'}>
+CONFIG_PPP_MULTILINK                            policy<{'arm64': '-'}>
+CONFIG_PPP_SYNC_TTY                             policy<{'arm64': '-'}>
+CONFIG_PPS_CLIENT_GPIO                          policy<{'arm64': 'n'}>
+CONFIG_PPS_CLIENT_LDISC                         policy<{'arm64': 'n'}>
+CONFIG_PPS_CLIENT_PARPORT                       policy<{'arm64': '-'}>
+CONFIG_PPTP                                     policy<{'arm64': '-'}>
+CONFIG_PREEMPT_NOTIFIERS                        policy<{'arm64': '-'}>
+CONFIG_PREEMPT_VOLUNTARY                        policy<{'arm64': 'n'}>
+CONFIG_PRINTER                                  policy<{'arm64': '-'}>
+CONFIG_PRINT_QUOTA_WARNING                      policy<{'arm64': 'y'}>
+CONFIG_PRISM2_USB                               policy<{'arm64': 'n'}>
+CONFIG_PROC_KCORE                               policy<{'arm64': 'n'}>
+CONFIG_PROC_VMCORE_DEVICE_DUMP                  policy<{'arm64': 'n'}>
+CONFIG_PSAMPLE                                  policy<{'arm64': 'n'}>
+CONFIG_PSI                                      policy<{'arm64': 'n'}>
+CONFIG_PSTORE                                   policy<{'arm64': 'n'}>
+CONFIG_PSTORE_842_COMPRESS                      policy<{'arm64': '-'}>
+CONFIG_PSTORE_COMPRESS                          policy<{'arm64': '-'}>
+CONFIG_PSTORE_COMPRESS_DEFAULT                  policy<{'arm64': '-'}>
+CONFIG_PSTORE_CONSOLE                           policy<{'arm64': '-'}>
+CONFIG_PSTORE_DEFLATE_COMPRESS                  policy<{'arm64': '-'}>
+CONFIG_PSTORE_DEFLATE_COMPRESS_DEFAULT          policy<{'arm64': '-'}>
+CONFIG_PSTORE_FTRACE                            policy<{'arm64': '-'}>
+CONFIG_PSTORE_LZ4HC_COMPRESS                    policy<{'arm64': '-'}>
+CONFIG_PSTORE_LZ4_COMPRESS                      policy<{'arm64': '-'}>
+CONFIG_PSTORE_LZO_COMPRESS                      policy<{'arm64': '-'}>
+CONFIG_PSTORE_PMSG                              policy<{'arm64': '-'}>
+CONFIG_PSTORE_RAM                               policy<{'arm64': '-'}>
+CONFIG_PSTORE_ZSTD_COMPRESS                     policy<{'arm64': '-'}>
+CONFIG_PTP_1588_CLOCK_DTE                       policy<{'arm64': '-'}>
+CONFIG_PTP_1588_CLOCK_QORIQ                     policy<{'arm64': '-'}>
+CONFIG_PTP_1588_CLOCK_XILINX                    policy<{'arm64': 'n'}>
+CONFIG_PVPANIC                                  policy<{'arm64': 'n'}>
+CONFIG_PWM                                      policy<{'arm64': 'n'}>
+CONFIG_PWM_ATMEL_HLCDC_PWM                      policy<{'arm64': '-'}>
+CONFIG_PWM_BCM2835                              policy<{'arm64': '-'}>
+CONFIG_PWM_BCM_IPROC                            policy<{'arm64': '-'}>
+CONFIG_PWM_BERLIN                               policy<{'arm64': '-'}>
+CONFIG_PWM_BRCMSTB                              policy<{'arm64': '-'}>
+CONFIG_PWM_CROS_EC                              policy<{'arm64': '-'}>
+CONFIG_PWM_FSL_FTM                              policy<{'arm64': '-'}>
+CONFIG_PWM_HIBVT                                policy<{'arm64': '-'}>
+CONFIG_PWM_IMX1                                 policy<{'arm64': '-'}>
+CONFIG_PWM_IMX27                                policy<{'arm64': '-'}>
+CONFIG_PWM_IMX_TPM                              policy<{'arm64': '-'}>
+CONFIG_PWM_LP3943                               policy<{'arm64': '-'}>
+CONFIG_PWM_MEDIATEK                             policy<{'arm64': '-'}>
+CONFIG_PWM_MESON                                policy<{'arm64': '-'}>
+CONFIG_PWM_MTK_DISP                             policy<{'arm64': '-'}>
+CONFIG_PWM_PCA9685                              policy<{'arm64': '-'}>
+CONFIG_PWM_RCAR                                 policy<{'arm64': '-'}>
+CONFIG_PWM_RENESAS_TPU                          policy<{'arm64': '-'}>
+CONFIG_PWM_ROCKCHIP                             policy<{'arm64': '-'}>
+CONFIG_PWM_SPRD                                 policy<{'arm64': '-'}>
+CONFIG_PWM_STMPE                                policy<{'arm64': '-'}>
+CONFIG_PWM_SUN4I                                policy<{'arm64': '-'}>
+CONFIG_PWM_SYSFS                                policy<{'arm64': '-'}>
+CONFIG_PWM_TIECAP                               policy<{'arm64': '-'}>
+CONFIG_PWM_TIEHRPWM                             policy<{'arm64': '-'}>
+CONFIG_PWM_TWL                                  policy<{'arm64': '-'}>
+CONFIG_PWM_TWL_LED                              policy<{'arm64': '-'}>
+CONFIG_PWRSEQ_EMMC                              policy<{'arm64': 'y'}>
+CONFIG_PWRSEQ_SD8787                            policy<{'arm64': 'n'}>
+CONFIG_PWRSEQ_SIMPLE                            policy<{'arm64': 'y'}>
+CONFIG_PXA168_ETH                               policy<{'arm64': '-'}>
+CONFIG_QCA7000                                  policy<{'arm64': '-'}>
+CONFIG_QCA7000_SPI                              policy<{'arm64': 'n'}>
+CONFIG_QCA7000_UART                             policy<{'arm64': 'n'}>
+CONFIG_QCOM_A53PLL                              policy<{'arm64': '-'}>
+CONFIG_QCOM_AOSS_QMP                            policy<{'arm64': '-'}>
+CONFIG_QCOM_APCS_IPC                            policy<{'arm64': '-'}>
+CONFIG_QCOM_APR                                 policy<{'arm64': '-'}>
+CONFIG_QCOM_BAM_DMA                             policy<{'arm64': '-'}>
+CONFIG_QCOM_CLK_APCS_MSM8916                    policy<{'arm64': '-'}>
+CONFIG_QCOM_CLK_RPM                             policy<{'arm64': '-'}>
+CONFIG_QCOM_CLK_RPMH                            policy<{'arm64': '-'}>
+CONFIG_QCOM_CLK_SMD_RPM                         policy<{'arm64': '-'}>
+CONFIG_QCOM_COINCELL                            policy<{'arm64': '-'}>
+CONFIG_QCOM_COMMAND_DB                          policy<{'arm64': '-'}>
+CONFIG_QCOM_EBI2                                policy<{'arm64': '-'}>
+CONFIG_QCOM_EMAC                                policy<{'arm64': 'n'}>
+CONFIG_QCOM_FASTRPC                             policy<{'arm64': '-'}>
+CONFIG_QCOM_GDSC                                policy<{'arm64': '-'}>
+CONFIG_QCOM_GENI_SE                             policy<{'arm64': '-'}>
+CONFIG_QCOM_GLINK_SSR                           policy<{'arm64': '-'}>
+CONFIG_QCOM_GSBI                                policy<{'arm64': '-'}>
+CONFIG_QCOM_HFPLL                               policy<{'arm64': '-'}>
+CONFIG_QCOM_HIDMA                               policy<{'arm64': 'n'}>
+CONFIG_QCOM_HIDMA_MGMT                          policy<{'arm64': 'n'}>
+CONFIG_QCOM_IOMMU                               policy<{'arm64': '-'}>
+CONFIG_QCOM_IRQ_COMBINER                        policy<{'arm64': '-'}>
+CONFIG_QCOM_L2_PMU                              policy<{'arm64': '-'}>
+CONFIG_QCOM_L3_PMU                              policy<{'arm64': '-'}>
+CONFIG_QCOM_LLCC                                policy<{'arm64': '-'}>
+CONFIG_QCOM_MDT_LOADER                          policy<{'arm64': '-'}>
+CONFIG_QCOM_PDC                                 policy<{'arm64': '-'}>
+CONFIG_QCOM_Q6V5_ADSP                           policy<{'arm64': '-'}>
+CONFIG_QCOM_Q6V5_COMMON                         policy<{'arm64': '-'}>
+CONFIG_QCOM_Q6V5_MSS                            policy<{'arm64': '-'}>
+CONFIG_QCOM_Q6V5_PAS                            policy<{'arm64': '-'}>
+CONFIG_QCOM_Q6V5_WCSS                           policy<{'arm64': '-'}>
+CONFIG_QCOM_QFPROM                              policy<{'arm64': '-'}>
+CONFIG_QCOM_QMI_HELPERS                         policy<{'arm64': '-'}>
+CONFIG_QCOM_RMTFS_MEM                           policy<{'arm64': '-'}>
+CONFIG_QCOM_RPMCC                               policy<{'arm64': '-'}>
+CONFIG_QCOM_RPMH                                policy<{'arm64': '-'}>
+CONFIG_QCOM_RPMHPD                              policy<{'arm64': '-'}>
+CONFIG_QCOM_RPROC_COMMON                        policy<{'arm64': '-'}>
+CONFIG_QCOM_SCM                                 policy<{'arm64': '-'}>
+CONFIG_QCOM_SCM_64                              policy<{'arm64': '-'}>
+CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT           policy<{'arm64': '-'}>
+CONFIG_QCOM_SMD_RPM                             policy<{'arm64': '-'}>
+CONFIG_QCOM_SMEM                                policy<{'arm64': '-'}>
+CONFIG_QCOM_SMEM_STATE                          policy<{'arm64': '-'}>
+CONFIG_QCOM_SMP2P                               policy<{'arm64': '-'}>
+CONFIG_QCOM_SMSM                                policy<{'arm64': '-'}>
+CONFIG_QCOM_SOCINFO                             policy<{'arm64': '-'}>
+CONFIG_QCOM_SPMI_ADC5                           policy<{'arm64': '-'}>
+CONFIG_QCOM_SPMI_IADC                           policy<{'arm64': '-'}>
+CONFIG_QCOM_SPMI_TEMP_ALARM                     policy<{'arm64': '-'}>
+CONFIG_QCOM_SPMI_VADC                           policy<{'arm64': '-'}>
+CONFIG_QCOM_SYSMON                              policy<{'arm64': '-'}>
+CONFIG_QCOM_TSENS                               policy<{'arm64': '-'}>
+CONFIG_QCOM_VADC_COMMON                         policy<{'arm64': '-'}>
+CONFIG_QCOM_WCNSS_CTRL                          policy<{'arm64': '-'}>
+CONFIG_QCOM_WCNSS_PIL                           policy<{'arm64': '-'}>
+CONFIG_QCOM_WDT                                 policy<{'arm64': '-'}>
+CONFIG_QCS_GCC_404                              policy<{'arm64': '-'}>
+CONFIG_QCS_TURING_404                           policy<{'arm64': '-'}>
+CONFIG_QED                                      policy<{'arm64': 'n'}>
+CONFIG_QEDE                                     policy<{'arm64': '-'}>
+CONFIG_QEDF                                     policy<{'arm64': '-'}>
+CONFIG_QEDI                                     policy<{'arm64': '-'}>
+CONFIG_QED_FCOE                                 policy<{'arm64': '-'}>
+CONFIG_QED_ISCSI                                policy<{'arm64': '-'}>
+CONFIG_QED_LL2                                  policy<{'arm64': '-'}>
+CONFIG_QED_OOO                                  policy<{'arm64': '-'}>
+CONFIG_QED_RDMA                                 policy<{'arm64': '-'}>
+CONFIG_QED_SRIOV                                policy<{'arm64': '-'}>
+CONFIG_QFMT_V1                                  policy<{'arm64': 'n'}>
+CONFIG_QFMT_V2                                  policy<{'arm64': 'y'}>
+CONFIG_QLA3XXX                                  policy<{'arm64': 'n'}>
+CONFIG_QLCNIC                                   policy<{'arm64': 'n'}>
+CONFIG_QLCNIC_DCB                               policy<{'arm64': '-'}>
+CONFIG_QLCNIC_HWMON                             policy<{'arm64': '-'}>
+CONFIG_QLCNIC_SRIOV                             policy<{'arm64': '-'}>
+CONFIG_QLGE                                     policy<{'arm64': 'n'}>
+CONFIG_QNX4FS_FS                                policy<{'arm64': 'n'}>
+CONFIG_QNX6FS_DEBUG                             policy<{'arm64': '-'}>
+CONFIG_QNX6FS_FS                                policy<{'arm64': 'n'}>
+CONFIG_QORIQ_CPUFREQ                            policy<{'arm64': 'n'}>
+CONFIG_QORIQ_THERMAL                            policy<{'arm64': '-'}>
+CONFIG_QRTR                                     policy<{'arm64': '-'}>
+CONFIG_QRTR_SMD                                 policy<{'arm64': '-'}>
+CONFIG_QRTR_TUN                                 policy<{'arm64': '-'}>
+CONFIG_QSEMI_PHY                                policy<{'arm64': 'y'}>
+CONFIG_QTNFMAC                                  policy<{'arm64': '-'}>
+CONFIG_QTNFMAC_PCIE                             policy<{'arm64': 'n'}>
+CONFIG_QUOTA_NETLINK_INTERFACE                  policy<{'arm64': 'n'}>
+CONFIG_QUOTA_TREE                               policy<{'arm64': 'y'}>
+CONFIG_R6040                                    policy<{'arm64': 'n'}>
+CONFIG_R8169                                    policy<{'arm64': 'n'}>
+CONFIG_R8188EU                                  policy<{'arm64': 'n'}>
+CONFIG_R8712U                                   policy<{'arm64': 'n'}>
+CONFIG_RADIO_ADAPTERS                           policy<{'arm64': '-'}>
+CONFIG_RADIO_MAXIRADIO                          policy<{'arm64': '-'}>
+CONFIG_RADIO_SAA7706H                           policy<{'arm64': '-'}>
+CONFIG_RADIO_SHARK                              policy<{'arm64': '-'}>
+CONFIG_RADIO_SHARK2                             policy<{'arm64': '-'}>
+CONFIG_RADIO_SI470X                             policy<{'arm64': '-'}>
+CONFIG_RADIO_SI4713                             policy<{'arm64': '-'}>
+CONFIG_RADIO_SI476X                             policy<{'arm64': '-'}>
+CONFIG_RADIO_TEA575X                            policy<{'arm64': '-'}>
+CONFIG_RADIO_TEA5764                            policy<{'arm64': '-'}>
+CONFIG_RADIO_TEF6862                            policy<{'arm64': '-'}>
+CONFIG_RADIO_WL1273                             policy<{'arm64': '-'}>
+CONFIG_RADIO_WL128X                             policy<{'arm64': '-'}>
+CONFIG_RAID6_PQ                                 policy<{'arm64': 'y'}>
+CONFIG_RAID_ATTRS                               policy<{'arm64': 'n'}>
+CONFIG_RANDOM_TRUST_BOOTLOADER                  policy<{'arm64': 'n'}>
+CONFIG_RAPIDIO                                  policy<{'arm64': 'n'}>
+CONFIG_RAPIDIO_CHMAN                            policy<{'arm64': '-'}>
+CONFIG_RAPIDIO_CPS_GEN2                         policy<{'arm64': '-'}>
+CONFIG_RAPIDIO_CPS_XX                           policy<{'arm64': '-'}>
+CONFIG_RAPIDIO_DEBUG                            policy<{'arm64': '-'}>
+CONFIG_RAPIDIO_DISC_TIMEOUT                     policy<{'arm64': '-'}>
+CONFIG_RAPIDIO_DMA_ENGINE                       policy<{'arm64': '-'}>
+CONFIG_RAPIDIO_ENABLE_RX_TX_PORTS               policy<{'arm64': '-'}>
+CONFIG_RAPIDIO_ENUM_BASIC                       policy<{'arm64': '-'}>
+CONFIG_RAPIDIO_MPORT_CDEV                       policy<{'arm64': '-'}>
+CONFIG_RAPIDIO_RXS_GEN3                         policy<{'arm64': '-'}>
+CONFIG_RAPIDIO_TSI568                           policy<{'arm64': '-'}>
+CONFIG_RAPIDIO_TSI57X                           policy<{'arm64': '-'}>
+CONFIG_RAPIDIO_TSI721                           policy<{'arm64': '-'}>
+CONFIG_RASPBERRYPI_FIRMWARE                     policy<{'arm64': '-'}>
+CONFIG_RASPBERRYPI_POWER                        policy<{'arm64': '-'}>
+CONFIG_RAVB                                     policy<{'arm64': '-'}>
+CONFIG_RAVE_SP_CORE                             policy<{'arm64': 'n'}>
+CONFIG_RAVE_SP_EEPROM                           policy<{'arm64': '-'}>
+CONFIG_RAVE_SP_WATCHDOG                         policy<{'arm64': '-'}>
+CONFIG_RAW_DRIVER                               policy<{'arm64': 'n'}>
+CONFIG_RCAR_DMAC                                policy<{'arm64': '-'}>
+CONFIG_RCAR_GEN3_THERMAL                        policy<{'arm64': '-'}>
+CONFIG_RCAR_THERMAL                             policy<{'arm64': '-'}>
+CONFIG_RCU_CPU_STALL_TIMEOUT                    policy<{'arm64': '21'}>
+CONFIG_RCU_PERF_TEST                            policy<{'arm64': 'n'}>
+CONFIG_RCU_TRACE                                policy<{'arm64': 'y'}>
+CONFIG_RC_ATI_REMOTE                            policy<{'arm64': '-'}>
+CONFIG_RC_CORE                                  policy<{'arm64': 'n'}>
+CONFIG_RC_DECODERS                              policy<{'arm64': '-'}>
+CONFIG_RC_DEVICES                               policy<{'arm64': '-'}>
+CONFIG_RC_LOOPBACK                              policy<{'arm64': '-'}>
+CONFIG_RC_MAP                                   policy<{'arm64': '-'}>
+CONFIG_RC_XBOX_DVD                              policy<{'arm64': '-'}>
+CONFIG_RDMA_RXE                                 policy<{'arm64': '-'}>
+CONFIG_RDMA_SIW                                 policy<{'arm64': '-'}>
+CONFIG_RDS                                      policy<{'arm64': 'n'}>
+CONFIG_RDS_DEBUG                                policy<{'arm64': '-'}>
+CONFIG_RDS_RDMA                                 policy<{'arm64': '-'}>
+CONFIG_RDS_TCP                                  policy<{'arm64': '-'}>
+CONFIG_REALTEK_AUTOPM                           policy<{'arm64': '-'}>
+CONFIG_REALTEK_PHY                              policy<{'arm64': 'y'}>
+CONFIG_REBOOT_MODE                              policy<{'arm64': '-'}>
+CONFIG_REED_SOLOMON                             policy<{'arm64': '-'}>
+CONFIG_REED_SOLOMON_DEC16                       policy<{'arm64': '-'}>
+CONFIG_REED_SOLOMON_DEC8                        policy<{'arm64': '-'}>
+CONFIG_REED_SOLOMON_ENC8                        policy<{'arm64': '-'}>
+CONFIG_REGMAP_I3C                               policy<{'arm64': '-'}>
+CONFIG_REGMAP_MMIO                              policy<{'arm64': '-'}>
+CONFIG_REGMAP_SCCB                              policy<{'arm64': '-'}>
+CONFIG_REGMAP_SLIMBUS                           policy<{'arm64': '-'}>
+CONFIG_REGMAP_SPMI                              policy<{'arm64': '-'}>
+CONFIG_REGMAP_W1                                policy<{'arm64': '-'}>
+CONFIG_REGULATOR_88PG86X                        policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_88PM800                        policy<{'arm64': '-'}>
+CONFIG_REGULATOR_88PM8607                       policy<{'arm64': '-'}>
+CONFIG_REGULATOR_AAT2870                        policy<{'arm64': '-'}>
+CONFIG_REGULATOR_AB3100                         policy<{'arm64': '-'}>
+CONFIG_REGULATOR_ACT8865                        policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_ACT8945A                       policy<{'arm64': '-'}>
+CONFIG_REGULATOR_AD5398                         policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_ANATOP                         policy<{'arm64': '-'}>
+CONFIG_REGULATOR_ARIZONA_LDO1                   policy<{'arm64': '-'}>
+CONFIG_REGULATOR_ARIZONA_MICSUPP                policy<{'arm64': '-'}>
+CONFIG_REGULATOR_AS3711                         policy<{'arm64': '-'}>
+CONFIG_REGULATOR_AS3722                         policy<{'arm64': '-'}>
+CONFIG_REGULATOR_AXP20X                         policy<{'arm64': '-'}>
+CONFIG_REGULATOR_BCM590XX                       policy<{'arm64': '-'}>
+CONFIG_REGULATOR_BD70528                        policy<{'arm64': '-'}>
+CONFIG_REGULATOR_BD718XX                        policy<{'arm64': '-'}>
+CONFIG_REGULATOR_BD9571MWV                      policy<{'arm64': '-'}>
+CONFIG_REGULATOR_CPCAP                          policy<{'arm64': '-'}>
+CONFIG_REGULATOR_DA903X                         policy<{'arm64': '-'}>
+CONFIG_REGULATOR_DA9052                         policy<{'arm64': '-'}>
+CONFIG_REGULATOR_DA9055                         policy<{'arm64': '-'}>
+CONFIG_REGULATOR_DA9062                         policy<{'arm64': '-'}>
+CONFIG_REGULATOR_DA9063                         policy<{'arm64': '-'}>
+CONFIG_REGULATOR_DA9121                         policy<{'arm64': 'y'}>
+CONFIG_REGULATOR_DA9210                         policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_DA9211                         policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_FAN53555                       policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_GPIO                           policy<{'arm64': 'y'}>
+CONFIG_REGULATOR_HI6421                         policy<{'arm64': '-'}>
+CONFIG_REGULATOR_HI6421V530                     policy<{'arm64': '-'}>
+CONFIG_REGULATOR_HI655X                         policy<{'arm64': '-'}>
+CONFIG_REGULATOR_ISL6271A                       policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_ISL9305                        policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_LM363X                         policy<{'arm64': '-'}>
+CONFIG_REGULATOR_LOCHNAGAR                      policy<{'arm64': '-'}>
+CONFIG_REGULATOR_LP3971                         policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_LP3972                         policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_LP872X                         policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_LP873X                         policy<{'arm64': '-'}>
+CONFIG_REGULATOR_LP8755                         policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_LP87565                        policy<{'arm64': '-'}>
+CONFIG_REGULATOR_LP8788                         policy<{'arm64': '-'}>
+CONFIG_REGULATOR_LTC3589                        policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_LTC3676                        policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_MAX14577                       policy<{'arm64': '-'}>
+CONFIG_REGULATOR_MAX1586                        policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_MAX77620                       policy<{'arm64': '-'}>
+CONFIG_REGULATOR_MAX77650                       policy<{'arm64': '-'}>
+CONFIG_REGULATOR_MAX77686                       policy<{'arm64': '-'}>
+CONFIG_REGULATOR_MAX77693                       policy<{'arm64': '-'}>
+CONFIG_REGULATOR_MAX77802                       policy<{'arm64': '-'}>
+CONFIG_REGULATOR_MAX8649                        policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_MAX8660                        policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_MAX8907                        policy<{'arm64': '-'}>
+CONFIG_REGULATOR_MAX8925                        policy<{'arm64': '-'}>
+CONFIG_REGULATOR_MAX8952                        policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_MAX8973                        policy<{'arm64': '-'}>
+CONFIG_REGULATOR_MAX8997                        policy<{'arm64': '-'}>
+CONFIG_REGULATOR_MAX8998                        policy<{'arm64': '-'}>
+CONFIG_REGULATOR_MC13783                        policy<{'arm64': '-'}>
+CONFIG_REGULATOR_MC13892                        policy<{'arm64': '-'}>
+CONFIG_REGULATOR_MC13XXX_CORE                   policy<{'arm64': '-'}>
+CONFIG_REGULATOR_MCP16502                       policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_MT6311                         policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_MT6323                         policy<{'arm64': '-'}>
+CONFIG_REGULATOR_MT6380                         policy<{'arm64': '-'}>
+CONFIG_REGULATOR_MT6397                         policy<{'arm64': '-'}>
+CONFIG_REGULATOR_PALMAS                         policy<{'arm64': '-'}>
+CONFIG_REGULATOR_PCAP                           policy<{'arm64': '-'}>
+CONFIG_REGULATOR_PCF50633                       policy<{'arm64': '-'}>
+CONFIG_REGULATOR_PFUZE100                       policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_PV88060                        policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_PV88080                        policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_PV88090                        policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_PWM                            policy<{'arm64': '-'}>
+CONFIG_REGULATOR_QCOM_RPM                       policy<{'arm64': '-'}>
+CONFIG_REGULATOR_QCOM_RPMH                      policy<{'arm64': '-'}>
+CONFIG_REGULATOR_QCOM_SMD_RPM                   policy<{'arm64': '-'}>
+CONFIG_REGULATOR_QCOM_SPMI                      policy<{'arm64': '-'}>
+CONFIG_REGULATOR_RC5T583                        policy<{'arm64': '-'}>
+CONFIG_REGULATOR_RK808                          policy<{'arm64': '-'}>
+CONFIG_REGULATOR_RN5T618                        policy<{'arm64': '-'}>
+CONFIG_REGULATOR_RT5033                         policy<{'arm64': '-'}>
+CONFIG_REGULATOR_S2MPA01                        policy<{'arm64': '-'}>
+CONFIG_REGULATOR_S2MPS11                        policy<{'arm64': '-'}>
+CONFIG_REGULATOR_S5M8767                        policy<{'arm64': '-'}>
+CONFIG_REGULATOR_SC2731                         policy<{'arm64': '-'}>
+CONFIG_REGULATOR_SKY81452                       policy<{'arm64': '-'}>
+CONFIG_REGULATOR_SLG51000                       policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_STPMIC1                        policy<{'arm64': '-'}>
+CONFIG_REGULATOR_SY8106A                        policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_SY8824X                        policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_TPS51632                       policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_TPS6105X                       policy<{'arm64': '-'}>
+CONFIG_REGULATOR_TPS62360                       policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_TPS65023                       policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_TPS6507X                       policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_TPS65086                       policy<{'arm64': 'y'}>
+CONFIG_REGULATOR_TPS65090                       policy<{'arm64': '-'}>
+CONFIG_REGULATOR_TPS65132                       policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_TPS65218                       policy<{'arm64': '-'}>
+CONFIG_REGULATOR_TPS6524X                       policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_TPS6586X                       policy<{'arm64': '-'}>
+CONFIG_REGULATOR_TPS65910                       policy<{'arm64': '-'}>
+CONFIG_REGULATOR_TPS65912                       policy<{'arm64': '-'}>
+CONFIG_REGULATOR_TPS80031                       policy<{'arm64': '-'}>
+CONFIG_REGULATOR_USERSPACE_CONSUMER             policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_VCTRL                          policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_VEXPRESS                       policy<{'arm64': '-'}>
+CONFIG_REGULATOR_VIRTUAL_CONSUMER               policy<{'arm64': 'n'}>
+CONFIG_REGULATOR_WM831X                         policy<{'arm64': '-'}>
+CONFIG_REGULATOR_WM8350                         policy<{'arm64': '-'}>
+CONFIG_REGULATOR_WM8400                         policy<{'arm64': '-'}>
+CONFIG_REGULATOR_WM8994                         policy<{'arm64': '-'}>
+CONFIG_REISERFS_CHECK                           policy<{'arm64': '-'}>
+CONFIG_REISERFS_FS                              policy<{'arm64': 'n'}>
+CONFIG_REISERFS_FS_POSIX_ACL                    policy<{'arm64': '-'}>
+CONFIG_REISERFS_FS_SECURITY                     policy<{'arm64': '-'}>
+CONFIG_REISERFS_FS_XATTR                        policy<{'arm64': '-'}>
+CONFIG_REISERFS_PROC_INFO                       policy<{'arm64': '-'}>
+CONFIG_RELAY                                    policy<{'arm64': 'n'}>
+CONFIG_RENESAS_DMA                              policy<{'arm64': '-'}>
+CONFIG_RENESAS_IRQC                             policy<{'arm64': '-'}>
+CONFIG_RENESAS_PHY                              policy<{'arm64': 'n'}>
+CONFIG_RENESAS_RZAWDT                           policy<{'arm64': '-'}>
+CONFIG_RENESAS_USB_DMAC                         policy<{'arm64': '-'}>
+CONFIG_RENESAS_WDT                              policy<{'arm64': '-'}>
+CONFIG_RESET_ATTACK_MITIGATION                  policy<{'arm64': 'n'}>
+CONFIG_RESET_BERLIN                             policy<{'arm64': '-'}>
+CONFIG_RESET_BRCMSTB                            policy<{'arm64': '-'}>
+CONFIG_RESET_HISI                               policy<{'arm64': '-'}>
+CONFIG_RESET_IMX7                               policy<{'arm64': '-'}>
+CONFIG_RESET_MESON                              policy<{'arm64': '-'}>
+CONFIG_RESET_MESON_AUDIO_ARB                    policy<{'arm64': '-'}>
+CONFIG_RESET_QCOM_AOSS                          policy<{'arm64': '-'}>
+CONFIG_RESET_QCOM_PDC                           policy<{'arm64': '-'}>
+CONFIG_RESET_SCMI                               policy<{'arm64': '-'}>
+CONFIG_RESET_SIMPLE                             policy<{'arm64': '-'}>
+CONFIG_RESET_SUNXI                              policy<{'arm64': '-'}>
+CONFIG_RESET_TI_SCI                             policy<{'arm64': '-'}>
+CONFIG_RESET_TI_SYSCON                          policy<{'arm64': 'n'}>
+CONFIG_RETU_WATCHDOG                            policy<{'arm64': '-'}>
+CONFIG_RFD77402                                 policy<{'arm64': 'n'}>
+CONFIG_RFD_FTL                                  policy<{'arm64': 'n'}>
+CONFIG_RFKILL_GPIO                              policy<{'arm64': 'y'}>
+CONFIG_RIONET                                   policy<{'arm64': '-'}>
+CONFIG_RIONET_RX_SIZE                           policy<{'arm64': '-'}>
+CONFIG_RIONET_TX_SIZE                           policy<{'arm64': '-'}>
+CONFIG_RMI4_2D_SENSOR                           policy<{'arm64': '-'}>
+CONFIG_RMI4_CORE                                policy<{'arm64': 'n'}>
+CONFIG_RMI4_F03                                 policy<{'arm64': '-'}>
+CONFIG_RMI4_F03_SERIO                           policy<{'arm64': '-'}>
+CONFIG_RMI4_F11                                 policy<{'arm64': '-'}>
+CONFIG_RMI4_F12                                 policy<{'arm64': '-'}>
+CONFIG_RMI4_F30                                 policy<{'arm64': '-'}>
+CONFIG_RMI4_F34                                 policy<{'arm64': '-'}>
+CONFIG_RMI4_F54                                 policy<{'arm64': '-'}>
+CONFIG_RMI4_F55                                 policy<{'arm64': '-'}>
+CONFIG_RMI4_I2C                                 policy<{'arm64': '-'}>
+CONFIG_RMI4_SMB                                 policy<{'arm64': '-'}>
+CONFIG_RMI4_SPI                                 policy<{'arm64': '-'}>
+CONFIG_RMNET                                    policy<{'arm64': 'n'}>
+CONFIG_RN5T618_WATCHDOG                         policy<{'arm64': '-'}>
+CONFIG_ROCKCHIP_ANALOGIX_DP                     policy<{'arm64': '-'}>
+CONFIG_ROCKCHIP_CDN_DP                          policy<{'arm64': '-'}>
+CONFIG_ROCKCHIP_DW_HDMI                         policy<{'arm64': '-'}>
+CONFIG_ROCKCHIP_DW_MIPI_DSI                     policy<{'arm64': '-'}>
+CONFIG_ROCKCHIP_EFUSE                           policy<{'arm64': '-'}>
+CONFIG_ROCKCHIP_GRF                             policy<{'arm64': '-'}>
+CONFIG_ROCKCHIP_INNO_HDMI                       policy<{'arm64': '-'}>
+CONFIG_ROCKCHIP_IODOMAIN                        policy<{'arm64': '-'}>
+CONFIG_ROCKCHIP_IOMMU                           policy<{'arm64': '-'}>
+CONFIG_ROCKCHIP_LVDS                            policy<{'arm64': '-'}>
+CONFIG_ROCKCHIP_MBOX                            policy<{'arm64': '-'}>
+CONFIG_ROCKCHIP_PHY                             policy<{'arm64': 'n'}>
+CONFIG_ROCKCHIP_PM_DOMAINS                      policy<{'arm64': '-'}>
+CONFIG_ROCKCHIP_RGB                             policy<{'arm64': '-'}>
+CONFIG_ROCKCHIP_RK3066_HDMI                     policy<{'arm64': '-'}>
+CONFIG_ROCKCHIP_SARADC                          policy<{'arm64': '-'}>
+CONFIG_ROCKCHIP_THERMAL                         policy<{'arm64': '-'}>
+CONFIG_ROCKCHIP_TIMER                           policy<{'arm64': '-'}>
+CONFIG_ROCKER                                   policy<{'arm64': '-'}>
+CONFIG_ROCKETPORT                               policy<{'arm64': '-'}>
+CONFIG_ROMFS_BACKED_BY_BLOCK                    policy<{'arm64': '-'}>
+CONFIG_ROMFS_BACKED_BY_BOTH                     policy<{'arm64': '-'}>
+CONFIG_ROMFS_BACKED_BY_MTD                      policy<{'arm64': '-'}>
+CONFIG_ROMFS_FS                                 policy<{'arm64': 'n'}>
+CONFIG_ROMFS_ON_BLOCK                           policy<{'arm64': '-'}>
+CONFIG_ROOT_NFS                                 policy<{'arm64': 'y'}>
+CONFIG_ROSE                                     policy<{'arm64': '-'}>
+CONFIG_RPCSEC_GSS_KRB5                          policy<{'arm64': '-'}>
+CONFIG_RPMSG_QCOM_GLINK_NATIVE                  policy<{'arm64': '-'}>
+CONFIG_RPMSG_QCOM_GLINK_RPM                     policy<{'arm64': 'n'}>
+CONFIG_RPMSG_QCOM_GLINK_SMEM                    policy<{'arm64': '-'}>
+CONFIG_RPMSG_QCOM_SMD                           policy<{'arm64': '-'}>
+CONFIG_RPR0521                                  policy<{'arm64': 'n'}>
+CONFIG_RSI_91X                                  policy<{'arm64': 'n'}>
+CONFIG_RSI_COEX                                 policy<{'arm64': '-'}>
+CONFIG_RSI_DEBUGFS                              policy<{'arm64': '-'}>
+CONFIG_RSI_SDIO                                 policy<{'arm64': '-'}>
+CONFIG_RSI_USB                                  policy<{'arm64': '-'}>
+CONFIG_RST_RCAR                                 policy<{'arm64': '-'}>
+CONFIG_RT2400PCI                                policy<{'arm64': '-'}>
+CONFIG_RT2500PCI                                policy<{'arm64': '-'}>
+CONFIG_RT2500USB                                policy<{'arm64': '-'}>
+CONFIG_RT2800PCI                                policy<{'arm64': '-'}>
+CONFIG_RT2800PCI_RT3290                         policy<{'arm64': '-'}>
+CONFIG_RT2800PCI_RT33XX                         policy<{'arm64': '-'}>
+CONFIG_RT2800PCI_RT35XX                         policy<{'arm64': '-'}>
+CONFIG_RT2800PCI_RT53XX                         policy<{'arm64': '-'}>
+CONFIG_RT2800USB                                policy<{'arm64': '-'}>
+CONFIG_RT2800USB_RT33XX                         policy<{'arm64': '-'}>
+CONFIG_RT2800USB_RT3573                         policy<{'arm64': '-'}>
+CONFIG_RT2800USB_RT35XX                         policy<{'arm64': '-'}>
+CONFIG_RT2800USB_RT53XX                         policy<{'arm64': '-'}>
+CONFIG_RT2800USB_RT55XX                         policy<{'arm64': '-'}>
+CONFIG_RT2800USB_UNKNOWN                        policy<{'arm64': '-'}>
+CONFIG_RT2800_LIB                               policy<{'arm64': '-'}>
+CONFIG_RT2800_LIB_MMIO                          policy<{'arm64': '-'}>
+CONFIG_RT2X00                                   policy<{'arm64': 'n'}>
+CONFIG_RT2X00_DEBUG                             policy<{'arm64': '-'}>
+CONFIG_RT2X00_LIB                               policy<{'arm64': '-'}>
+CONFIG_RT2X00_LIB_CRYPTO                        policy<{'arm64': '-'}>
+CONFIG_RT2X00_LIB_DEBUGFS                       policy<{'arm64': '-'}>
+CONFIG_RT2X00_LIB_FIRMWARE                      policy<{'arm64': '-'}>
+CONFIG_RT2X00_LIB_LEDS                          policy<{'arm64': '-'}>
+CONFIG_RT2X00_LIB_MMIO                          policy<{'arm64': '-'}>
+CONFIG_RT2X00_LIB_PCI                           policy<{'arm64': '-'}>
+CONFIG_RT2X00_LIB_USB                           policy<{'arm64': '-'}>
+CONFIG_RT61PCI                                  policy<{'arm64': '-'}>
+CONFIG_RT73USB                                  policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_88PM80X                          policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_88PM860X                         policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_AB3100                           policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_ABB5ZES3                         policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_ABEOZ9                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_ABX80X                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_AM1805                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_ARMADA38X                        policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_AS3722                           policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_BD70528                          policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_BQ32K                            policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_BQ4802                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_BRCMSTB                          policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_CADENCE                          policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_CPCAP                            policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_CROS_EC                          policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_DA9052                           policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_DA9055                           policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_DA9063                           policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_DS1286                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_DS1302                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_DS1305                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_DS1307                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_DS1307_CENTURY                   policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_DS1343                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_DS1347                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_DS1374                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_DS1374_WDT                       policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_DS1390                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_DS1511                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_DS1553                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_DS1672                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_DS1685                           policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_DS1685_FAMILY                    policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_DS1689                           policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_DS17285                          policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_DS1742                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_DS17485                          policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_DS17885                          policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_DS2404                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_DS3232                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_DS3232_HWMON                     policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_EM3027                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_FM3130                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_FSL_FTM_ALARM                    policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_FTRTC010                         policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_HID_SENSOR_TIME                  policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_HYM8563                          policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_IMXDI                            policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_IMX_SC                           policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_ISL12022                         policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_ISL12026                         policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_ISL1208                          policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_LP8788                           policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_M41T80                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_M41T80_WDT                       policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_M41T93                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_M41T94                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_M48T35                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_M48T59                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_M48T86                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_MAX6900                          policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_MAX6902                          policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_MAX6916                          policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_MAX77686                         policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_MAX8907                          policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_MAX8925                          policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_MAX8997                          policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_MAX8998                          policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_MC13XXX                          policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_MCP795                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_MESON_VRTC                       policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_MSM6242                          policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_MT6397                           policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_MT7622                           policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_MV                               policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_MXC                              policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_MXC_V2                           policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_PALMAS                           policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_PCAP                             policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_PCF2123                          policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_PCF2127                          policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_PCF50633                         policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_PCF85063                         policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_PCF8523                          policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_PCF85363                         policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_PCF8563                          policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_PCF8583                          policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_PL030                            policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_PL031                            policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_PM8XXX                           policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_R7301                            policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_R9701                            policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_RC5T583                          policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_RK808                            policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_RP5C01                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_RS5C348                          policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_RS5C372                          policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_RTD119X                          policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_RV3028                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_RV3029C2                         policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_RV3029_HWMON                     policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_RV8803                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_RX4581                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_RX6110                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_RX8010                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_RX8025                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_RX8581                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_S35390A                          policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_S5M                              policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_SC27XX                           policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_SD3078                           policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_SH                               policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_SNVS                             policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_STK17TA8                         policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_SUN6I                            policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_TPS6586X                         policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_TPS65910                         policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_TPS80031                         policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_V3020                            policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_WM831X                           policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_WM8350                           policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_X1205                            policy<{'arm64': 'n'}>
+CONFIG_RTC_DRV_XGENE                            policy<{'arm64': '-'}>
+CONFIG_RTC_DRV_ZYNQMP                           policy<{'arm64': 'y'}>
+CONFIG_RTD119X_WATCHDOG                         policy<{'arm64': '-'}>
+CONFIG_RTL8180                                  policy<{'arm64': 'n'}>
+CONFIG_RTL8187                                  policy<{'arm64': 'n'}>
+CONFIG_RTL8187_LEDS                             policy<{'arm64': '-'}>
+CONFIG_RTL8188EE                                policy<{'arm64': 'n'}>
+CONFIG_RTL8192CE                                policy<{'arm64': 'n'}>
+CONFIG_RTL8192CU                                policy<{'arm64': 'n'}>
+CONFIG_RTL8192C_COMMON                          policy<{'arm64': '-'}>
+CONFIG_RTL8192DE                                policy<{'arm64': 'n'}>
+CONFIG_RTL8192E                                 policy<{'arm64': '-'}>
+CONFIG_RTL8192EE                                policy<{'arm64': 'n'}>
+CONFIG_RTL8192SE                                policy<{'arm64': 'n'}>
+CONFIG_RTL8192U                                 policy<{'arm64': 'n'}>
+CONFIG_RTL8723AE                                policy<{'arm64': 'n'}>
+CONFIG_RTL8723BE                                policy<{'arm64': 'n'}>
+CONFIG_RTL8723BS                                policy<{'arm64': 'n'}>
+CONFIG_RTL8723_COMMON                           policy<{'arm64': '-'}>
+CONFIG_RTL8821AE                                policy<{'arm64': 'n'}>
+CONFIG_RTL8XXXU                                 policy<{'arm64': 'n'}>
+CONFIG_RTL8XXXU_UNTESTED                        policy<{'arm64': '-'}>
+CONFIG_RTLBTCOEXIST                             policy<{'arm64': '-'}>
+CONFIG_RTLLIB                                   policy<{'arm64': 'n'}>
+CONFIG_RTLLIB_CRYPTO_CCMP                       policy<{'arm64': '-'}>
+CONFIG_RTLLIB_CRYPTO_TKIP                       policy<{'arm64': '-'}>
+CONFIG_RTLLIB_CRYPTO_WEP                        policy<{'arm64': '-'}>
+CONFIG_RTLWIFI                                  policy<{'arm64': '-'}>
+CONFIG_RTLWIFI_DEBUG                            policy<{'arm64': '-'}>
+CONFIG_RTLWIFI_PCI                              policy<{'arm64': '-'}>
+CONFIG_RTLWIFI_USB                              policy<{'arm64': '-'}>
+CONFIG_RTL_CARDS                                policy<{'arm64': 'y'}>
+CONFIG_RTS5208                                  policy<{'arm64': 'n'}>
+CONFIG_RTW88                                    policy<{'arm64': 'n'}>
+CONFIG_RTW88_8723DE                             policy<{'arm64': '-'}>
+CONFIG_RTW88_8822BE                             policy<{'arm64': '-'}>
+CONFIG_RTW88_8822CE                             policy<{'arm64': '-'}>
+CONFIG_RTW88_CORE                               policy<{'arm64': '-'}>
+CONFIG_RTW88_DEBUG                              policy<{'arm64': '-'}>
+CONFIG_RTW88_DEBUGFS                            policy<{'arm64': '-'}>
+CONFIG_RTW88_PCI                                policy<{'arm64': '-'}>
+CONFIG_RTW88_REGD_USER_REG_HINTS                policy<{'arm64': '-'}>
+CONFIG_RXKAD                                    policy<{'arm64': '-'}>
+CONFIG_S2IO                                     policy<{'arm64': 'n'}>
+CONFIG_SAMPLES                                  policy<{'arm64': 'n'}>
+CONFIG_SAMPLE_CONFIGFS                          policy<{'arm64': '-'}>
+CONFIG_SAMPLE_HW_BREAKPOINT                     policy<{'arm64': '-'}>
+CONFIG_SAMPLE_KDB                               policy<{'arm64': '-'}>
+CONFIG_SAMPLE_KFIFO                             policy<{'arm64': '-'}>
+CONFIG_SAMPLE_KOBJECT                           policy<{'arm64': '-'}>
+CONFIG_SAMPLE_KPROBES                           policy<{'arm64': '-'}>
+CONFIG_SAMPLE_QMI_CLIENT                        policy<{'arm64': '-'}>
+CONFIG_SAMPLE_RPMSG_CLIENT                      policy<{'arm64': '-'}>
+CONFIG_SAMPLE_TRACE_EVENTS                      policy<{'arm64': '-'}>
+CONFIG_SAMPLE_VFIO_MDEV_MBOCHS                  policy<{'arm64': '-'}>
+CONFIG_SAMPLE_VFIO_MDEV_MDPY                    policy<{'arm64': '-'}>
+CONFIG_SAMPLE_VFIO_MDEV_MDPY_FB                 policy<{'arm64': '-'}>
+CONFIG_SAMPLE_VFIO_MDEV_MTTY                    policy<{'arm64': '-'}>
+CONFIG_SATA_ACARD_AHCI                          policy<{'arm64': 'n'}>
+CONFIG_SATA_AHCI                                policy<{'arm64': 'n'}>
+CONFIG_SATA_AHCI_SEATTLE                        policy<{'arm64': '-'}>
+CONFIG_SATA_DWC                                 policy<{'arm64': '-'}>
+CONFIG_SATA_DWC_DEBUG                           policy<{'arm64': '-'}>
+CONFIG_SATA_DWC_OLD_DMA                         policy<{'arm64': '-'}>
+CONFIG_SATA_INIC162X                            policy<{'arm64': 'n'}>
+CONFIG_SATA_MOBILE_LPM_POLICY                   policy<{'arm64': '-'}>
+CONFIG_SATA_MV                                  policy<{'arm64': '-'}>
+CONFIG_SATA_NV                                  policy<{'arm64': '-'}>
+CONFIG_SATA_PROMISE                             policy<{'arm64': '-'}>
+CONFIG_SATA_QSTOR                               policy<{'arm64': '-'}>
+CONFIG_SATA_RCAR                                policy<{'arm64': '-'}>
+CONFIG_SATA_SIL                                 policy<{'arm64': '-'}>
+CONFIG_SATA_SIL24                               policy<{'arm64': 'n'}>
+CONFIG_SATA_SIS                                 policy<{'arm64': '-'}>
+CONFIG_SATA_SVW                                 policy<{'arm64': '-'}>
+CONFIG_SATA_SX4                                 policy<{'arm64': '-'}>
+CONFIG_SATA_ULI                                 policy<{'arm64': '-'}>
+CONFIG_SATA_VIA                                 policy<{'arm64': '-'}>
+CONFIG_SATA_VITESSE                             policy<{'arm64': '-'}>
+CONFIG_SATA_ZPODD                               policy<{'arm64': '-'}>
+CONFIG_SBP_TARGET                               policy<{'arm64': '-'}>
+CONFIG_SC27XX_ADC                               policy<{'arm64': '-'}>
+CONFIG_SC27XX_EFUSE                             policy<{'arm64': '-'}>
+CONFIG_SC92031                                  policy<{'arm64': 'n'}>
+CONFIG_SCA3000                                  policy<{'arm64': 'n'}>
+CONFIG_SCHEDSTATS                               policy<{'arm64': 'n'}>
+CONFIG_SCHED_AUTOGROUP                          policy<{'arm64': 'n'}>
+CONFIG_SCHED_DEBUG                              policy<{'arm64': 'n'}>
+CONFIG_SCHED_MC                                 policy<{'arm64': 'n'}>
+CONFIG_SCHED_SMT                                policy<{'arm64': 'n'}>
+CONFIG_SCHED_TRACER                             policy<{'arm64': 'n'}>
+CONFIG_SCSI_3W_9XXX                             policy<{'arm64': 'n'}>
+CONFIG_SCSI_3W_SAS                              policy<{'arm64': 'n'}>
+CONFIG_SCSI_AACRAID                             policy<{'arm64': 'n'}>
+CONFIG_SCSI_ACARD                               policy<{'arm64': 'n'}>
+CONFIG_SCSI_ADVANSYS                            policy<{'arm64': 'n'}>
+CONFIG_SCSI_AIC79XX                             policy<{'arm64': 'n'}>
+CONFIG_SCSI_AIC7XXX                             policy<{'arm64': 'n'}>
+CONFIG_SCSI_AIC94XX                             policy<{'arm64': 'n'}>
+CONFIG_SCSI_AM53C974                            policy<{'arm64': 'n'}>
+CONFIG_SCSI_ARCMSR                              policy<{'arm64': 'n'}>
+CONFIG_SCSI_BFA_FC                              policy<{'arm64': '-'}>
+CONFIG_SCSI_BNX2X_FCOE                          policy<{'arm64': '-'}>
+CONFIG_SCSI_BNX2_ISCSI                          policy<{'arm64': 'n'}>
+CONFIG_SCSI_CHELSIO_FCOE                        policy<{'arm64': '-'}>
+CONFIG_SCSI_CONSTANTS                           policy<{'arm64': 'n'}>
+CONFIG_SCSI_CXGB3_ISCSI                         policy<{'arm64': 'n'}>
+CONFIG_SCSI_CXGB4_ISCSI                         policy<{'arm64': 'n'}>
+CONFIG_SCSI_DC395x                              policy<{'arm64': 'n'}>
+CONFIG_SCSI_DEBUG                               policy<{'arm64': 'n'}>
+CONFIG_SCSI_DH                                  policy<{'arm64': 'n'}>
+CONFIG_SCSI_DH_ALUA                             policy<{'arm64': '-'}>
+CONFIG_SCSI_DH_EMC                              policy<{'arm64': '-'}>
+CONFIG_SCSI_DH_HP_SW                            policy<{'arm64': '-'}>
+CONFIG_SCSI_DH_RDAC                             policy<{'arm64': '-'}>
+CONFIG_SCSI_DMX3191D                            policy<{'arm64': 'n'}>
+CONFIG_SCSI_ENCLOSURE                           policy<{'arm64': '-'}>
+CONFIG_SCSI_ESAS2R                              policy<{'arm64': 'n'}>
+CONFIG_SCSI_FC_ATTRS                            policy<{'arm64': 'n'}>
+CONFIG_SCSI_FDOMAIN                             policy<{'arm64': '-'}>
+CONFIG_SCSI_FDOMAIN_PCI                         policy<{'arm64': 'n'}>
+CONFIG_SCSI_GDTH                                policy<{'arm64': 'n'}>
+CONFIG_SCSI_HISI_SAS                            policy<{'arm64': 'n'}>
+CONFIG_SCSI_HISI_SAS_PCI                        policy<{'arm64': '-'}>
+CONFIG_SCSI_HPSA                                policy<{'arm64': 'n'}>
+CONFIG_SCSI_HPTIOP                              policy<{'arm64': 'n'}>
+CONFIG_SCSI_INIA100                             policy<{'arm64': 'n'}>
+CONFIG_SCSI_INITIO                              policy<{'arm64': 'n'}>
+CONFIG_SCSI_IPR                                 policy<{'arm64': 'n'}>
+CONFIG_SCSI_IPS                                 policy<{'arm64': 'n'}>
+CONFIG_SCSI_ISCSI_ATTRS                         policy<{'arm64': 'n'}>
+CONFIG_SCSI_LOGGING                             policy<{'arm64': 'n'}>
+CONFIG_SCSI_LPFC                                policy<{'arm64': '-'}>
+CONFIG_SCSI_LPFC_DEBUG_FS                       policy<{'arm64': '-'}>
+CONFIG_SCSI_MPT2SAS                             policy<{'arm64': 'n'}>
+CONFIG_SCSI_MPT2SAS_MAX_SGE                     policy<{'arm64': '-'}>
+CONFIG_SCSI_MPT3SAS                             policy<{'arm64': 'n'}>
+CONFIG_SCSI_MPT3SAS_MAX_SGE                     policy<{'arm64': '-'}>
+CONFIG_SCSI_MVSAS                               policy<{'arm64': 'n'}>
+CONFIG_SCSI_MVSAS_DEBUG                         policy<{'arm64': '-'}>
+CONFIG_SCSI_MVSAS_TASKLET                       policy<{'arm64': '-'}>
+CONFIG_SCSI_MVUMI                               policy<{'arm64': 'n'}>
+CONFIG_SCSI_MYRB                                policy<{'arm64': 'n'}>
+CONFIG_SCSI_MYRS                                policy<{'arm64': 'n'}>
+CONFIG_SCSI_NETLINK                             policy<{'arm64': '-'}>
+CONFIG_SCSI_PM8001                              policy<{'arm64': 'n'}>
+CONFIG_SCSI_PMCRAID                             policy<{'arm64': 'n'}>
+CONFIG_SCSI_QLA_FC                              policy<{'arm64': '-'}>
+CONFIG_SCSI_QLA_ISCSI                           policy<{'arm64': 'n'}>
+CONFIG_SCSI_QLOGIC_1280                         policy<{'arm64': 'n'}>
+CONFIG_SCSI_SAS_ATA                             policy<{'arm64': '-'}>
+CONFIG_SCSI_SAS_ATTRS                           policy<{'arm64': 'n'}>
+CONFIG_SCSI_SAS_HOST_SMP                        policy<{'arm64': '-'}>
+CONFIG_SCSI_SAS_LIBSAS                          policy<{'arm64': 'n'}>
+CONFIG_SCSI_SCAN_ASYNC                          policy<{'arm64': 'n'}>
+CONFIG_SCSI_SMARTPQI                            policy<{'arm64': 'n'}>
+CONFIG_SCSI_SNIC                                policy<{'arm64': 'n'}>
+CONFIG_SCSI_SNIC_DEBUG_FS                       policy<{'arm64': '-'}>
+CONFIG_SCSI_SPI_ATTRS                           policy<{'arm64': 'n'}>
+CONFIG_SCSI_SRP_ATTRS                           policy<{'arm64': 'n'}>
+CONFIG_SCSI_STEX                                policy<{'arm64': 'n'}>
+CONFIG_SCSI_SYM53C8XX_2                         policy<{'arm64': 'n'}>
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS              policy<{'arm64': '-'}>
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE       policy<{'arm64': '-'}>
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS                  policy<{'arm64': '-'}>
+CONFIG_SCSI_SYM53C8XX_MMIO                      policy<{'arm64': '-'}>
+CONFIG_SCSI_UFSHCD                              policy<{'arm64': 'n'}>
+CONFIG_SCSI_UFSHCD_PCI                          policy<{'arm64': '-'}>
+CONFIG_SCSI_UFSHCD_PLATFORM                     policy<{'arm64': '-'}>
+CONFIG_SCSI_UFS_BSG                             policy<{'arm64': '-'}>
+CONFIG_SCSI_UFS_CDNS_PLATFORM                   policy<{'arm64': '-'}>
+CONFIG_SCSI_UFS_DWC_TC_PCI                      policy<{'arm64': '-'}>
+CONFIG_SCSI_UFS_DWC_TC_PLATFORM                 policy<{'arm64': '-'}>
+CONFIG_SCSI_UFS_HISI                            policy<{'arm64': '-'}>
+CONFIG_SCSI_UFS_MEDIATEK                        policy<{'arm64': '-'}>
+CONFIG_SCSI_UFS_QCOM                            policy<{'arm64': '-'}>
+CONFIG_SCSI_WD719X                              policy<{'arm64': 'n'}>
+CONFIG_SCTP_COOKIE_HMAC_MD5                     policy<{'arm64': '-'}>
+CONFIG_SCTP_COOKIE_HMAC_SHA1                    policy<{'arm64': '-'}>
+CONFIG_SCTP_DBG_OBJCNT                          policy<{'arm64': '-'}>
+CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5             policy<{'arm64': '-'}>
+CONFIG_SCTP_DEFAULT_COOKIE_HMAC_NONE            policy<{'arm64': '-'}>
+CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1            policy<{'arm64': '-'}>
+CONFIG_SDIO_UART                                policy<{'arm64': 'n'}>
+CONFIG_SDM_CAMCC_845                            policy<{'arm64': '-'}>
+CONFIG_SDM_DISPCC_845                           policy<{'arm64': '-'}>
+CONFIG_SDM_GCC_660                              policy<{'arm64': '-'}>
+CONFIG_SDM_GCC_845                              policy<{'arm64': '-'}>
+CONFIG_SDM_GPUCC_845                            policy<{'arm64': '-'}>
+CONFIG_SDM_LPASSCC_845                          policy<{'arm64': '-'}>
+CONFIG_SDM_VIDEOCC_845                          policy<{'arm64': '-'}>
+CONFIG_SDR_MAX2175                              policy<{'arm64': '-'}>
+CONFIG_SDR_PLATFORM_DRIVERS                     policy<{'arm64': '-'}>
+CONFIG_SD_ADC_MODULATOR                         policy<{'arm64': 'n'}>
+CONFIG_SECONDARY_TRUSTED_KEYRING                policy<{'arm64': 'n'}>
+CONFIG_SECURITY_INFINIBAND                      policy<{'arm64': '-'}>
+CONFIG_SECURITY_LOCKDOWN_LSM_EARLY              policy<{'arm64': 'n'}>
+CONFIG_SECURITY_NETWORK_XFRM                    policy<{'arm64': 'n'}>
+CONFIG_SENSIRION_SGP30                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_ACPI_POWER                       policy<{'arm64': '-'}>
+CONFIG_SENSORS_AD7314                           policy<{'arm64': 'n'}>
+CONFIG_SENSORS_AD7414                           policy<{'arm64': 'n'}>
+CONFIG_SENSORS_AD7418                           policy<{'arm64': 'n'}>
+CONFIG_SENSORS_ADC128D818                       policy<{'arm64': 'n'}>
+CONFIG_SENSORS_ADCXX                            policy<{'arm64': 'n'}>
+CONFIG_SENSORS_ADM1021                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_ADM1025                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_ADM1026                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_ADM1029                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_ADM1031                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_ADM1275                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_ADM9240                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_ADS7828                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_ADS7871                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_ADT7310                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_ADT7410                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_ADT7411                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_ADT7462                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_ADT7470                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_ADT7475                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_ADT7X10                          policy<{'arm64': '-'}>
+CONFIG_SENSORS_AMC6821                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_APDS990X                         policy<{'arm64': 'n'}>
+CONFIG_SENSORS_ARM_SCMI                         policy<{'arm64': '-'}>
+CONFIG_SENSORS_ARM_SCPI                         policy<{'arm64': '-'}>
+CONFIG_SENSORS_AS370                            policy<{'arm64': 'n'}>
+CONFIG_SENSORS_ASC7621                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_ASPEED                           policy<{'arm64': 'n'}>
+CONFIG_SENSORS_ATXP1                            policy<{'arm64': 'n'}>
+CONFIG_SENSORS_BH1770                           policy<{'arm64': 'n'}>
+CONFIG_SENSORS_DA9052_ADC                       policy<{'arm64': '-'}>
+CONFIG_SENSORS_DA9055                           policy<{'arm64': '-'}>
+CONFIG_SENSORS_DME1737                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_DS1621                           policy<{'arm64': 'n'}>
+CONFIG_SENSORS_DS620                            policy<{'arm64': 'n'}>
+CONFIG_SENSORS_EMC1403                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_EMC2103                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_EMC6W201                         policy<{'arm64': 'n'}>
+CONFIG_SENSORS_F71805F                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_F71882FG                         policy<{'arm64': 'n'}>
+CONFIG_SENSORS_F75375S                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_FTSTEUTATES                      policy<{'arm64': 'n'}>
+CONFIG_SENSORS_G760A                            policy<{'arm64': 'n'}>
+CONFIG_SENSORS_G762                             policy<{'arm64': 'n'}>
+CONFIG_SENSORS_GL518SM                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_GL520SM                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_GPIO_FAN                         policy<{'arm64': 'n'}>
+CONFIG_SENSORS_HIH6130                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_HMC5843                          policy<{'arm64': '-'}>
+CONFIG_SENSORS_HMC5843_I2C                      policy<{'arm64': 'n'}>
+CONFIG_SENSORS_HMC5843_SPI                      policy<{'arm64': 'n'}>
+CONFIG_SENSORS_I5K_AMB                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_IBMAEM                           policy<{'arm64': '-'}>
+CONFIG_SENSORS_IBMPEX                           policy<{'arm64': '-'}>
+CONFIG_SENSORS_IBM_CFFPS                        policy<{'arm64': 'n'}>
+CONFIG_SENSORS_IIO_HWMON                        policy<{'arm64': 'y'}>
+CONFIG_SENSORS_INA209                           policy<{'arm64': 'n'}>
+CONFIG_SENSORS_INA3221                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_INSPUR_IPSPS                     policy<{'arm64': 'n'}>
+CONFIG_SENSORS_IR35221                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_IR38064                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_ISL29018                         policy<{'arm64': 'n'}>
+CONFIG_SENSORS_ISL29028                         policy<{'arm64': 'n'}>
+CONFIG_SENSORS_ISL68137                         policy<{'arm64': 'n'}>
+CONFIG_SENSORS_IT87                             policy<{'arm64': 'n'}>
+CONFIG_SENSORS_JC42                             policy<{'arm64': 'n'}>
+CONFIG_SENSORS_LINEAGE                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_LIS3LV02D                        policy<{'arm64': '-'}>
+CONFIG_SENSORS_LIS3_I2C                         policy<{'arm64': 'n'}>
+CONFIG_SENSORS_LIS3_SPI                         policy<{'arm64': 'n'}>
+CONFIG_SENSORS_LM25066                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_LM3533                           policy<{'arm64': '-'}>
+CONFIG_SENSORS_LM70                             policy<{'arm64': 'n'}>
+CONFIG_SENSORS_LM73                             policy<{'arm64': 'n'}>
+CONFIG_SENSORS_LM75                             policy<{'arm64': 'n'}>
+CONFIG_SENSORS_LM77                             policy<{'arm64': 'n'}>
+CONFIG_SENSORS_LM78                             policy<{'arm64': 'n'}>
+CONFIG_SENSORS_LM80                             policy<{'arm64': 'n'}>
+CONFIG_SENSORS_LM83                             policy<{'arm64': 'n'}>
+CONFIG_SENSORS_LM85                             policy<{'arm64': 'n'}>
+CONFIG_SENSORS_LM87                             policy<{'arm64': 'n'}>
+CONFIG_SENSORS_LM90                             policy<{'arm64': 'n'}>
+CONFIG_SENSORS_LM92                             policy<{'arm64': 'n'}>
+CONFIG_SENSORS_LM93                             policy<{'arm64': 'n'}>
+CONFIG_SENSORS_LM95234                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_LM95241                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_LM95245                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_LOCHNAGAR                        policy<{'arm64': '-'}>
+CONFIG_SENSORS_LTC2945                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_LTC2978                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_LTC2978_REGULATOR                policy<{'arm64': '-'}>
+CONFIG_SENSORS_LTC2990                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_LTC3815                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_LTC4151                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_LTC4215                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_LTC4222                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_LTC4245                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_LTC4260                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_LTC4261                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_MAX1111                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_MAX16064                         policy<{'arm64': 'n'}>
+CONFIG_SENSORS_MAX16065                         policy<{'arm64': 'n'}>
+CONFIG_SENSORS_MAX1619                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_MAX1668                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_MAX197                           policy<{'arm64': 'n'}>
+CONFIG_SENSORS_MAX31722                         policy<{'arm64': 'n'}>
+CONFIG_SENSORS_MAX31785                         policy<{'arm64': 'n'}>
+CONFIG_SENSORS_MAX31790                         policy<{'arm64': 'n'}>
+CONFIG_SENSORS_MAX34440                         policy<{'arm64': 'n'}>
+CONFIG_SENSORS_MAX6621                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_MAX6639                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_MAX6642                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_MAX6650                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_MAX6697                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_MAX8688                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_MC13783_ADC                      policy<{'arm64': '-'}>
+CONFIG_SENSORS_MCP3021                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_MENF21BMC_HWMON                  policy<{'arm64': '-'}>
+CONFIG_SENSORS_MLXREG_FAN                       policy<{'arm64': '-'}>
+CONFIG_SENSORS_NCT6683                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_NCT6775                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_NCT7802                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_NCT7904                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_NPCM7XX                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_NTC_THERMISTOR                   policy<{'arm64': 'n'}>
+CONFIG_SENSORS_OCC_P9_SBE                       policy<{'arm64': '-'}>
+CONFIG_SENSORS_PC87360                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_PC87427                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_PCF8591                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_PMBUS                            policy<{'arm64': 'y'}>
+CONFIG_SENSORS_POWR1220                         policy<{'arm64': 'n'}>
+CONFIG_SENSORS_PWM_FAN                          policy<{'arm64': '-'}>
+CONFIG_SENSORS_PXE1610                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_RASPBERRYPI_HWMON                policy<{'arm64': '-'}>
+CONFIG_SENSORS_RM3100                           policy<{'arm64': '-'}>
+CONFIG_SENSORS_RM3100_I2C                       policy<{'arm64': 'n'}>
+CONFIG_SENSORS_RM3100_SPI                       policy<{'arm64': 'n'}>
+CONFIG_SENSORS_SCH5627                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_SCH5636                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_SCH56XX_COMMON                   policy<{'arm64': '-'}>
+CONFIG_SENSORS_SHT15                            policy<{'arm64': 'n'}>
+CONFIG_SENSORS_SHT21                            policy<{'arm64': 'n'}>
+CONFIG_SENSORS_SHT3x                            policy<{'arm64': 'n'}>
+CONFIG_SENSORS_SHTC1                            policy<{'arm64': 'n'}>
+CONFIG_SENSORS_SIS5595                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_SMM665                           policy<{'arm64': 'n'}>
+CONFIG_SENSORS_SMSC47B397                       policy<{'arm64': 'n'}>
+CONFIG_SENSORS_SMSC47M1                         policy<{'arm64': 'n'}>
+CONFIG_SENSORS_SMSC47M192                       policy<{'arm64': 'n'}>
+CONFIG_SENSORS_STTS751                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_TC654                            policy<{'arm64': 'n'}>
+CONFIG_SENSORS_TC74                             policy<{'arm64': 'n'}>
+CONFIG_SENSORS_THMC50                           policy<{'arm64': 'n'}>
+CONFIG_SENSORS_TMP102                           policy<{'arm64': 'n'}>
+CONFIG_SENSORS_TMP103                           policy<{'arm64': 'n'}>
+CONFIG_SENSORS_TMP108                           policy<{'arm64': 'n'}>
+CONFIG_SENSORS_TMP401                           policy<{'arm64': 'n'}>
+CONFIG_SENSORS_TMP421                           policy<{'arm64': 'n'}>
+CONFIG_SENSORS_TPS40422                         policy<{'arm64': 'n'}>
+CONFIG_SENSORS_TPS53679                         policy<{'arm64': 'n'}>
+CONFIG_SENSORS_TPS544                           policy<{'arm64': 'n'}>
+CONFIG_SENSORS_TSL2550                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_TSL2563                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_UCD9000                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_UCD9200                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_VEXPRESS                         policy<{'arm64': '-'}>
+CONFIG_SENSORS_VIA686A                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_VT1211                           policy<{'arm64': 'n'}>
+CONFIG_SENSORS_VT8231                           policy<{'arm64': 'n'}>
+CONFIG_SENSORS_W83627EHF                        policy<{'arm64': 'n'}>
+CONFIG_SENSORS_W83627HF                         policy<{'arm64': 'n'}>
+CONFIG_SENSORS_W83773G                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_W83781D                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_W83791D                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_W83792D                          policy<{'arm64': 'n'}>
+CONFIG_SENSORS_W83793                           policy<{'arm64': 'n'}>
+CONFIG_SENSORS_W83795                           policy<{'arm64': 'n'}>
+CONFIG_SENSORS_W83795_FANCTRL                   policy<{'arm64': '-'}>
+CONFIG_SENSORS_W83L785TS                        policy<{'arm64': 'n'}>
+CONFIG_SENSORS_W83L786NG                        policy<{'arm64': 'n'}>
+CONFIG_SENSORS_WM831X                           policy<{'arm64': '-'}>
+CONFIG_SENSORS_WM8350                           policy<{'arm64': '-'}>
+CONFIG_SENSORS_XGENE                            policy<{'arm64': '-'}>
+CONFIG_SENSORS_ZL6100                           policy<{'arm64': 'n'}>
+CONFIG_SERIAL_8250_ASPEED_VUART                 policy<{'arm64': 'n'}>
+CONFIG_SERIAL_8250_BCM2835AUX                   policy<{'arm64': '-'}>
+CONFIG_SERIAL_8250_DEPRECATED_OPTIONS           policy<{'arm64': 'y'}>
+CONFIG_SERIAL_8250_DETECT_IRQ                   policy<{'arm64': '-'}>
+CONFIG_SERIAL_8250_DW                           policy<{'arm64': 'n'}>
+CONFIG_SERIAL_8250_DWLIB                        policy<{'arm64': '-'}>
+CONFIG_SERIAL_8250_EXAR                         policy<{'arm64': 'y'}>
+CONFIG_SERIAL_8250_EXTENDED                     policy<{'arm64': 'n'}>
+CONFIG_SERIAL_8250_FINTEK                       policy<{'arm64': 'n'}>
+CONFIG_SERIAL_8250_MANY_PORTS                   policy<{'arm64': '-'}>
+CONFIG_SERIAL_8250_MEN_MCB                      policy<{'arm64': '-'}>
+CONFIG_SERIAL_8250_MT6577                       policy<{'arm64': '-'}>
+CONFIG_SERIAL_8250_NR_UARTS                     policy<{'arm64': '4'}>
+CONFIG_SERIAL_8250_OMAP                         policy<{'arm64': '-'}>
+CONFIG_SERIAL_8250_PNP                          policy<{'arm64': '-'}>
+CONFIG_SERIAL_8250_RSA                          policy<{'arm64': '-'}>
+CONFIG_SERIAL_8250_RT288X                       policy<{'arm64': 'n'}>
+CONFIG_SERIAL_8250_RUNTIME_UARTS                policy<{'arm64': '4'}>
+CONFIG_SERIAL_8250_SHARE_IRQ                    policy<{'arm64': '-'}>
+CONFIG_SERIAL_ALTERA_JTAGUART                   policy<{'arm64': 'n'}>
+CONFIG_SERIAL_ALTERA_UART                       policy<{'arm64': 'n'}>
+CONFIG_SERIAL_ALTERA_UART_BAUDRATE              policy<{'arm64': '-'}>
+CONFIG_SERIAL_ALTERA_UART_MAXPORTS              policy<{'arm64': '-'}>
+CONFIG_SERIAL_AMBA_PL010                        policy<{'arm64': 'y'}>
+CONFIG_SERIAL_AMBA_PL010_CONSOLE                policy<{'arm64': 'y'}>
+CONFIG_SERIAL_ARC                               policy<{'arm64': 'n'}>
+CONFIG_SERIAL_ARC_NR_PORTS                      policy<{'arm64': '-'}>
+CONFIG_SERIAL_CONEXANT_DIGICOLOR                policy<{'arm64': 'n'}>
+CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST             policy<{'arm64': 'n'}>
+CONFIG_SERIAL_FSL_LINFLEXUART                   policy<{'arm64': 'n'}>
+CONFIG_SERIAL_FSL_LPUART                        policy<{'arm64': 'n'}>
+CONFIG_SERIAL_IMX                               policy<{'arm64': '-'}>
+CONFIG_SERIAL_IMX_CONSOLE                       policy<{'arm64': '-'}>
+CONFIG_SERIAL_IPOCTAL                           policy<{'arm64': '-'}>
+CONFIG_SERIAL_JSM                               policy<{'arm64': 'n'}>
+CONFIG_SERIAL_KGDB_NMI                          policy<{'arm64': '-'}>
+CONFIG_SERIAL_MAX3100                           policy<{'arm64': 'n'}>
+CONFIG_SERIAL_MEN_Z135                          policy<{'arm64': '-'}>
+CONFIG_SERIAL_MESON                             policy<{'arm64': '-'}>
+CONFIG_SERIAL_MESON_CONSOLE                     policy<{'arm64': '-'}>
+CONFIG_SERIAL_MSM                               policy<{'arm64': '-'}>
+CONFIG_SERIAL_MSM_CONSOLE                       policy<{'arm64': '-'}>
+CONFIG_SERIAL_MVEBU_CONSOLE                     policy<{'arm64': '-'}>
+CONFIG_SERIAL_MVEBU_UART                        policy<{'arm64': '-'}>
+CONFIG_SERIAL_NONSTANDARD                       policy<{'arm64': 'n'}>
+CONFIG_SERIAL_OWL                               policy<{'arm64': '-'}>
+CONFIG_SERIAL_OWL_CONSOLE                       policy<{'arm64': '-'}>
+CONFIG_SERIAL_QCOM_GENI                         policy<{'arm64': '-'}>
+CONFIG_SERIAL_RP2                               policy<{'arm64': 'n'}>
+CONFIG_SERIAL_RP2_NR_UARTS                      policy<{'arm64': '-'}>
+CONFIG_SERIAL_SC16IS7XX                         policy<{'arm64': 'n'}>
+CONFIG_SERIAL_SC16IS7XX_CORE                    policy<{'arm64': '-'}>
+CONFIG_SERIAL_SC16IS7XX_I2C                     policy<{'arm64': '-'}>
+CONFIG_SERIAL_SC16IS7XX_SPI                     policy<{'arm64': '-'}>
+CONFIG_SERIAL_SCCNXP                            policy<{'arm64': 'n'}>
+CONFIG_SERIAL_SCCNXP_CONSOLE                    policy<{'arm64': '-'}>
+CONFIG_SERIAL_SH_SCI_DMA                        policy<{'arm64': '-'}>
+CONFIG_SERIAL_SH_SCI_NR_UARTS                   policy<{'arm64': '-'}>
+CONFIG_SERIAL_SIFIVE                            policy<{'arm64': 'n'}>
+CONFIG_SERIAL_SPRD                              policy<{'arm64': '-'}>
+CONFIG_SERIAL_UARTLITE                          policy<{'arm64': 'y'}>
+CONFIG_SERIAL_UARTLITE_CONSOLE                  policy<{'arm64': 'y'}>
+CONFIG_SERIAL_UARTLITE_NR_UARTS                 policy<{'arm64': '-'}>
+CONFIG_SERIAL_XILINX_PS_UART                    policy<{'arm64': 'y'}>
+CONFIG_SERIAL_XILINX_PS_UART_CONSOLE            policy<{'arm64': 'y'}>
+CONFIG_SERIO_ALTERA_PS2                         policy<{'arm64': 'n'}>
+CONFIG_SERIO_AMBAKMI                            policy<{'arm64': 'n'}>
+CONFIG_SERIO_APBPS2                             policy<{'arm64': 'n'}>
+CONFIG_SERIO_ARC_PS2                            policy<{'arm64': 'n'}>
+CONFIG_SERIO_GPIO_PS2                           policy<{'arm64': 'n'}>
+CONFIG_SERIO_PARKBD                             policy<{'arm64': '-'}>
+CONFIG_SERIO_PCIPS2                             policy<{'arm64': 'n'}>
+CONFIG_SERIO_PS2MULT                            policy<{'arm64': 'n'}>
+CONFIG_SERIO_RAW                                policy<{'arm64': 'n'}>
+CONFIG_SERIO_SERPORT                            policy<{'arm64': 'y'}>
+CONFIG_SERIO_SUN4I_PS2                          policy<{'arm64': '-'}>
+CONFIG_SFC                                      policy<{'arm64': 'n'}>
+CONFIG_SFC_FALCON                               policy<{'arm64': 'n'}>
+CONFIG_SFC_FALCON_MTD                           policy<{'arm64': '-'}>
+CONFIG_SFC_MCDI_LOGGING                         policy<{'arm64': '-'}>
+CONFIG_SFC_MCDI_MON                             policy<{'arm64': '-'}>
+CONFIG_SFC_MTD                                  policy<{'arm64': '-'}>
+CONFIG_SFC_SRIOV                                policy<{'arm64': '-'}>
+CONFIG_SFP                                      policy<{'arm64': '-'}>
+CONFIG_SGETMASK_SYSCALL                         policy<{'arm64': 'n'}>
+CONFIG_SGI_PARTITION                            policy<{'arm64': '-'}>
+CONFIG_SG_SPLIT                                 policy<{'arm64': '-'}>
+CONFIG_SHIFT_FS                                 policy<{'arm64': 'n'}>
+CONFIG_SHIFT_FS_POSIX_ACL                       policy<{'arm64': '-'}>
+CONFIG_SHUFFLE_PAGE_ALLOCATOR                   policy<{'arm64': 'n'}>
+CONFIG_SH_ETH                                   policy<{'arm64': '-'}>
+CONFIG_SH_TIMER_CMT                             policy<{'arm64': '-'}>
+CONFIG_SH_TIMER_TMU                             policy<{'arm64': '-'}>
+CONFIG_SI1133                                   policy<{'arm64': 'n'}>
+CONFIG_SI1145                                   policy<{'arm64': 'n'}>
+CONFIG_SI7005                                   policy<{'arm64': 'n'}>
+CONFIG_SI7020                                   policy<{'arm64': 'n'}>
+CONFIG_SIGNATURE                                policy<{'arm64': '-'}>
+CONFIG_SIGNED_PE_FILE_VERIFICATION              policy<{'arm64': 'n'}>
+CONFIG_SIMPLE_PM_BUS                            policy<{'arm64': 'n'}>
+CONFIG_SIOX                                     policy<{'arm64': 'n'}>
+CONFIG_SIOX_BUS_GPIO                            policy<{'arm64': '-'}>
+CONFIG_SIS190                                   policy<{'arm64': 'n'}>
+CONFIG_SIS900                                   policy<{'arm64': 'n'}>
+CONFIG_SKFP                                     policy<{'arm64': '-'}>
+CONFIG_SKGE                                     policy<{'arm64': 'n'}>
+CONFIG_SKGE_DEBUG                               policy<{'arm64': '-'}>
+CONFIG_SKGE_GENESIS                             policy<{'arm64': '-'}>
+CONFIG_SKY2                                     policy<{'arm64': 'n'}>
+CONFIG_SKY2_DEBUG                               policy<{'arm64': '-'}>
+CONFIG_SLAB                                     policy<{'arm64': 'y'}>
+CONFIG_SLAB_FREELIST_HARDENED                   policy<{'arm64': '-'}>
+CONFIG_SLHC                                     policy<{'arm64': '-'}>
+CONFIG_SLICOSS                                  policy<{'arm64': 'n'}>
+CONFIG_SLIC_DS26522                             policy<{'arm64': '-'}>
+CONFIG_SLIMBUS                                  policy<{'arm64': 'n'}>
+CONFIG_SLIM_QCOM_CTRL                           policy<{'arm64': '-'}>
+CONFIG_SLIM_QCOM_NGD_CTRL                       policy<{'arm64': '-'}>
+CONFIG_SLIP                                     policy<{'arm64': 'n'}>
+CONFIG_SLIP_COMPRESSED                          policy<{'arm64': '-'}>
+CONFIG_SLIP_MODE_SLIP6                          policy<{'arm64': '-'}>
+CONFIG_SLIP_SMART                               policy<{'arm64': '-'}>
+CONFIG_SLUB                                     policy<{'arm64': 'n'}>
+CONFIG_SLUB_CPU_PARTIAL                         policy<{'arm64': '-'}>
+CONFIG_SLUB_DEBUG                               policy<{'arm64': '-'}>
+CONFIG_SLUB_DEBUG_ON                            policy<{'arm64': '-'}>
+CONFIG_SLUB_MEMCG_SYSFS_ON                      policy<{'arm64': '-'}>
+CONFIG_SLUB_STATS                               policy<{'arm64': '-'}>
+CONFIG_SMARTJOYPLUS_FF                          policy<{'arm64': '-'}>
+CONFIG_SMC91X                                   policy<{'arm64': 'n'}>
+CONFIG_SMSC911X                                 policy<{'arm64': 'n'}>
+CONFIG_SMSC9420                                 policy<{'arm64': 'n'}>
+CONFIG_SMSC_PHY                                 policy<{'arm64': 'y'}>
+CONFIG_SMS_SDIO_DRV                             policy<{'arm64': '-'}>
+CONFIG_SMS_SIANO_DEBUGFS                        policy<{'arm64': '-'}>
+CONFIG_SMS_SIANO_MDTV                           policy<{'arm64': '-'}>
+CONFIG_SMS_SIANO_RC                             policy<{'arm64': '-'}>
+CONFIG_SMS_USB_DRV                              policy<{'arm64': '-'}>
+CONFIG_SM_FTL                                   policy<{'arm64': 'n'}>
+CONFIG_SM_GCC_8150                              policy<{'arm64': '-'}>
+CONFIG_SND_AC97_CODEC                           policy<{'arm64': '-'}>
+CONFIG_SND_AC97_POWER_SAVE                      policy<{'arm64': '-'}>
+CONFIG_SND_AC97_POWER_SAVE_DEFAULT              policy<{'arm64': '-'}>
+CONFIG_SND_AD1889                               policy<{'arm64': '-'}>
+CONFIG_SND_ALOOP                                policy<{'arm64': '-'}>
+CONFIG_SND_ATIIXP                               policy<{'arm64': '-'}>
+CONFIG_SND_ATIIXP_MODEM                         policy<{'arm64': '-'}>
+CONFIG_SND_ATMEL_SOC                            policy<{'arm64': 'n'}>
+CONFIG_SND_AU8810                               policy<{'arm64': '-'}>
+CONFIG_SND_AU8820                               policy<{'arm64': '-'}>
+CONFIG_SND_AU8830                               policy<{'arm64': '-'}>
+CONFIG_SND_AUDIO_GRAPH_CARD                     policy<{'arm64': 'n'}>
+CONFIG_SND_AW2                                  policy<{'arm64': '-'}>
+CONFIG_SND_BCD2000                              policy<{'arm64': 'n'}>
+CONFIG_SND_BCM2835                              policy<{'arm64': '-'}>
+CONFIG_SND_BCM2835_SOC_I2S                      policy<{'arm64': '-'}>
+CONFIG_SND_BEBOB                                policy<{'arm64': '-'}>
+CONFIG_SND_BT87X                                policy<{'arm64': '-'}>
+CONFIG_SND_BT87X_OVERCLOCK                      policy<{'arm64': '-'}>
+CONFIG_SND_CA0106                               policy<{'arm64': '-'}>
+CONFIG_SND_CMIPCI                               policy<{'arm64': '-'}>
+CONFIG_SND_COMPRESS_OFFLOAD                     policy<{'arm64': '-'}>
+CONFIG_SND_CS4281                               policy<{'arm64': '-'}>
+CONFIG_SND_CS46XX                               policy<{'arm64': '-'}>
+CONFIG_SND_CS46XX_NEW_DSP                       policy<{'arm64': '-'}>
+CONFIG_SND_CTXFI                                policy<{'arm64': '-'}>
+CONFIG_SND_DARLA20                              policy<{'arm64': '-'}>
+CONFIG_SND_DARLA24                              policy<{'arm64': '-'}>
+CONFIG_SND_DESIGNWARE_I2S                       policy<{'arm64': 'n'}>
+CONFIG_SND_DESIGNWARE_PCM                       policy<{'arm64': '-'}>
+CONFIG_SND_DICE                                 policy<{'arm64': '-'}>
+CONFIG_SND_DMAENGINE_PCM                        policy<{'arm64': 'y'}>
+CONFIG_SND_DRIVERS                              policy<{'arm64': 'n'}>
+CONFIG_SND_DUMMY                                policy<{'arm64': '-'}>
+CONFIG_SND_DYNAMIC_MINORS                       policy<{'arm64': 'n'}>
+CONFIG_SND_ECHO3G                               policy<{'arm64': '-'}>
+CONFIG_SND_ENS1370                              policy<{'arm64': '-'}>
+CONFIG_SND_ENS1371                              policy<{'arm64': '-'}>
+CONFIG_SND_FIREFACE                             policy<{'arm64': '-'}>
+CONFIG_SND_FIREWIRE                             policy<{'arm64': '-'}>
+CONFIG_SND_FIREWIRE_DIGI00X                     policy<{'arm64': '-'}>
+CONFIG_SND_FIREWIRE_LIB                         policy<{'arm64': '-'}>
+CONFIG_SND_FIREWIRE_MOTU                        policy<{'arm64': '-'}>
+CONFIG_SND_FIREWIRE_TASCAM                      policy<{'arm64': '-'}>
+CONFIG_SND_FIREWORKS                            policy<{'arm64': '-'}>
+CONFIG_SND_FM801                                policy<{'arm64': '-'}>
+CONFIG_SND_FM801_TEA575X_BOOL                   policy<{'arm64': '-'}>
+CONFIG_SND_GINA20                               policy<{'arm64': '-'}>
+CONFIG_SND_GINA24                               policy<{'arm64': '-'}>
+CONFIG_SND_HDA                                  policy<{'arm64': '-'}>
+CONFIG_SND_HDA_CODEC_ANALOG                     policy<{'arm64': '-'}>
+CONFIG_SND_HDA_CODEC_CA0110                     policy<{'arm64': '-'}>
+CONFIG_SND_HDA_CODEC_CA0132                     policy<{'arm64': '-'}>
+CONFIG_SND_HDA_CODEC_CA0132_DSP                 policy<{'arm64': '-'}>
+CONFIG_SND_HDA_CODEC_CIRRUS                     policy<{'arm64': '-'}>
+CONFIG_SND_HDA_CODEC_CMEDIA                     policy<{'arm64': '-'}>
+CONFIG_SND_HDA_CODEC_CONEXANT                   policy<{'arm64': '-'}>
+CONFIG_SND_HDA_CODEC_HDMI                       policy<{'arm64': '-'}>
+CONFIG_SND_HDA_CODEC_REALTEK                    policy<{'arm64': '-'}>
+CONFIG_SND_HDA_CODEC_SI3054                     policy<{'arm64': '-'}>
+CONFIG_SND_HDA_CODEC_SIGMATEL                   policy<{'arm64': '-'}>
+CONFIG_SND_HDA_CODEC_VIA                        policy<{'arm64': '-'}>
+CONFIG_SND_HDA_COMPONENT                        policy<{'arm64': '-'}>
+CONFIG_SND_HDA_CORE                             policy<{'arm64': '-'}>
+CONFIG_SND_HDA_DSP_LOADER                       policy<{'arm64': '-'}>
+CONFIG_SND_HDA_GENERIC                          policy<{'arm64': '-'}>
+CONFIG_SND_HDA_HWDEP                            policy<{'arm64': '-'}>
+CONFIG_SND_HDA_INPUT_BEEP                       policy<{'arm64': '-'}>
+CONFIG_SND_HDA_INPUT_BEEP_MODE                  policy<{'arm64': '-'}>
+CONFIG_SND_HDA_INTEL                            policy<{'arm64': '-'}>
+CONFIG_SND_HDA_PATCH_LOADER                     policy<{'arm64': '-'}>
+CONFIG_SND_HDSP                                 policy<{'arm64': '-'}>
+CONFIG_SND_HDSPM                                policy<{'arm64': '-'}>
+CONFIG_SND_HRTIMER                              policy<{'arm64': 'n'}>
+CONFIG_SND_HWDEP                                policy<{'arm64': 'y'}>
+CONFIG_SND_I2S_HI6210_I2S                       policy<{'arm64': 'n'}>
+CONFIG_SND_ICE1724                              policy<{'arm64': '-'}>
+CONFIG_SND_IMX_SOC                              policy<{'arm64': '-'}>
+CONFIG_SND_INDIGO                               policy<{'arm64': '-'}>
+CONFIG_SND_INDIGODJ                             policy<{'arm64': '-'}>
+CONFIG_SND_INDIGODJX                            policy<{'arm64': '-'}>
+CONFIG_SND_INDIGOIO                             policy<{'arm64': '-'}>
+CONFIG_SND_INDIGOIOX                            policy<{'arm64': '-'}>
+CONFIG_SND_INTEL8X0                             policy<{'arm64': '-'}>
+CONFIG_SND_INTEL8X0M                            policy<{'arm64': '-'}>
+CONFIG_SND_INTEL_DSP_CONFIG                     policy<{'arm64': '-'}>
+CONFIG_SND_INTEL_NHLT                           policy<{'arm64': '-'}>
+CONFIG_SND_ISIGHT                               policy<{'arm64': '-'}>
+CONFIG_SND_KIRKWOOD_SOC                         policy<{'arm64': '-'}>
+CONFIG_SND_KIRKWOOD_SOC_ARMADA370_DB            policy<{'arm64': '-'}>
+CONFIG_SND_KORG1212                             policy<{'arm64': '-'}>
+CONFIG_SND_LAYLA20                              policy<{'arm64': '-'}>
+CONFIG_SND_LAYLA24                              policy<{'arm64': '-'}>
+CONFIG_SND_LOLA                                 policy<{'arm64': '-'}>
+CONFIG_SND_LX6464ES                             policy<{'arm64': '-'}>
+CONFIG_SND_MAX_CARDS                            policy<{'arm64': '-'}>
+CONFIG_SND_MESON_AXG_FIFO                       policy<{'arm64': '-'}>
+CONFIG_SND_MESON_AXG_FRDDR                      policy<{'arm64': '-'}>
+CONFIG_SND_MESON_AXG_PDM                        policy<{'arm64': '-'}>
+CONFIG_SND_MESON_AXG_SOUND_CARD                 policy<{'arm64': '-'}>
+CONFIG_SND_MESON_AXG_SPDIFIN                    policy<{'arm64': '-'}>
+CONFIG_SND_MESON_AXG_SPDIFOUT                   policy<{'arm64': '-'}>
+CONFIG_SND_MESON_AXG_TDMIN                      policy<{'arm64': '-'}>
+CONFIG_SND_MESON_AXG_TDMOUT                     policy<{'arm64': '-'}>
+CONFIG_SND_MESON_AXG_TDM_FORMATTER              policy<{'arm64': '-'}>
+CONFIG_SND_MESON_AXG_TDM_INTERFACE              policy<{'arm64': '-'}>
+CONFIG_SND_MESON_AXG_TODDR                      policy<{'arm64': '-'}>
+CONFIG_SND_MESON_CARD_UTILS                     policy<{'arm64': '-'}>
+CONFIG_SND_MESON_CODEC_GLUE                     policy<{'arm64': '-'}>
+CONFIG_SND_MESON_G12A_TOHDMITX                  policy<{'arm64': '-'}>
+CONFIG_SND_MIA                                  policy<{'arm64': '-'}>
+CONFIG_SND_MIXART                               policy<{'arm64': '-'}>
+CONFIG_SND_MIXER_OSS                            policy<{'arm64': '-'}>
+CONFIG_SND_MONA                                 policy<{'arm64': '-'}>
+CONFIG_SND_MPU401                               policy<{'arm64': '-'}>
+CONFIG_SND_MPU401_UART                          policy<{'arm64': '-'}>
+CONFIG_SND_MTPAV                                policy<{'arm64': '-'}>
+CONFIG_SND_MTS64                                policy<{'arm64': '-'}>
+CONFIG_SND_NM256                                policy<{'arm64': '-'}>
+CONFIG_SND_OPL3_LIB                             policy<{'arm64': '-'}>
+CONFIG_SND_OPL3_LIB_SEQ                         policy<{'arm64': '-'}>
+CONFIG_SND_OSSEMUL                              policy<{'arm64': 'n'}>
+CONFIG_SND_OXFW                                 policy<{'arm64': '-'}>
+CONFIG_SND_OXYGEN                               policy<{'arm64': '-'}>
+CONFIG_SND_OXYGEN_LIB                           policy<{'arm64': '-'}>
+CONFIG_SND_PCI                                  policy<{'arm64': 'n'}>
+CONFIG_SND_PCM                                  policy<{'arm64': 'y'}>
+CONFIG_SND_PCXHR                                policy<{'arm64': '-'}>
+CONFIG_SND_PORTMAN2X4                           policy<{'arm64': '-'}>
+CONFIG_SND_RAWMIDI                              policy<{'arm64': 'y'}>
+CONFIG_SND_RIPTIDE                              policy<{'arm64': '-'}>
+CONFIG_SND_RME32                                policy<{'arm64': '-'}>
+CONFIG_SND_RME96                                policy<{'arm64': '-'}>
+CONFIG_SND_RME9652                              policy<{'arm64': '-'}>
+CONFIG_SND_SEQUENCER                            policy<{'arm64': 'n'}>
+CONFIG_SND_SEQUENCER_OSS                        policy<{'arm64': '-'}>
+CONFIG_SND_SEQ_DEVICE                           policy<{'arm64': '-'}>
+CONFIG_SND_SEQ_DUMMY                            policy<{'arm64': '-'}>
+CONFIG_SND_SEQ_HRTIMER_DEFAULT                  policy<{'arm64': '-'}>
+CONFIG_SND_SEQ_MIDI                             policy<{'arm64': '-'}>
+CONFIG_SND_SEQ_MIDI_EMUL                        policy<{'arm64': '-'}>
+CONFIG_SND_SEQ_MIDI_EVENT                       policy<{'arm64': '-'}>
+CONFIG_SND_SEQ_VIRMIDI                          policy<{'arm64': '-'}>
+CONFIG_SND_SERIAL_U16550                        policy<{'arm64': '-'}>
+CONFIG_SND_SIMPLE_CARD                          policy<{'arm64': 'n'}>
+CONFIG_SND_SIMPLE_CARD_UTILS                    policy<{'arm64': '-'}>
+CONFIG_SND_SOC_AC97_BUS                         policy<{'arm64': '-'}>
+CONFIG_SND_SOC_AC97_CODEC                       policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_ACPI                             policy<{'arm64': '-'}>
+CONFIG_SND_SOC_ADAU1701                         policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_ADAU1761                         policy<{'arm64': '-'}>
+CONFIG_SND_SOC_ADAU1761_I2C                     policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_ADAU1761_SPI                     policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_ADAU17X1                         policy<{'arm64': '-'}>
+CONFIG_SND_SOC_ADAU7002                         policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_ADAU_UTILS                       policy<{'arm64': '-'}>
+CONFIG_SND_SOC_AK4104                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_AK4118                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_AK4458                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_AK4554                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_AK4613                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_AK4642                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_AK5386                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_AK5558                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_ALC5623                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_AMD_ACP                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_AMD_CZ_DA7219MX98357_MACH        policy<{'arm64': '-'}>
+CONFIG_SND_SOC_AMD_CZ_RT5645_MACH               policy<{'arm64': '-'}>
+CONFIG_SND_SOC_APQ8016_SBC                      policy<{'arm64': '-'}>
+CONFIG_SND_SOC_BD28623                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_BT_SCO                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_COMPRESS                         policy<{'arm64': '-'}>
+CONFIG_SND_SOC_CPCAP                            policy<{'arm64': '-'}>
+CONFIG_SND_SOC_CROS_EC_CODEC                    policy<{'arm64': '-'}>
+CONFIG_SND_SOC_CS35L32                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_CS35L33                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_CS35L34                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_CS35L35                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_CS35L36                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_CS4265                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_CS4270                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_CS4271                           policy<{'arm64': '-'}>
+CONFIG_SND_SOC_CS4271_I2C                       policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_CS4271_SPI                       policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_CS42L42                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_CS42L51                          policy<{'arm64': '-'}>
+CONFIG_SND_SOC_CS42L51_I2C                      policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_CS42L52                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_CS42L56                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_CS42L73                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_CS42XX8                          policy<{'arm64': '-'}>
+CONFIG_SND_SOC_CS42XX8_I2C                      policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_CS43130                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_CS4341                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_CS4349                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_CS53L30                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_CX2072X                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_DA7219                           policy<{'arm64': '-'}>
+CONFIG_SND_SOC_DMIC                             policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_ES7134                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_ES7241                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_ES8316                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_ES8328                           policy<{'arm64': '-'}>
+CONFIG_SND_SOC_ES8328_I2C                       policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_ES8328_SPI                       policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_FSL_ASOC_CARD                    policy<{'arm64': '-'}>
+CONFIG_SND_SOC_FSL_ASRC                         policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_FSL_AUDMIX                       policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_FSL_ESAI                         policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_FSL_MICFIL                       policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_FSL_SAI                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_FSL_SPDIF                        policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_FSL_SSI                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_GTM601                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_HDMI_CODEC                       policy<{'arm64': 'y'}>
+CONFIG_SND_SOC_I2C_AND_SPI                      policy<{'arm64': 'y'}>
+CONFIG_SND_SOC_IMG                              policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_IMG_I2S_IN                       policy<{'arm64': '-'}>
+CONFIG_SND_SOC_IMG_I2S_OUT                      policy<{'arm64': '-'}>
+CONFIG_SND_SOC_IMG_PARALLEL_OUT                 policy<{'arm64': '-'}>
+CONFIG_SND_SOC_IMG_PISTACHIO_INTERNAL_DAC       policy<{'arm64': '-'}>
+CONFIG_SND_SOC_IMG_SPDIF_IN                     policy<{'arm64': '-'}>
+CONFIG_SND_SOC_IMG_SPDIF_OUT                    policy<{'arm64': '-'}>
+CONFIG_SND_SOC_IMX_AUDMIX                       policy<{'arm64': '-'}>
+CONFIG_SND_SOC_IMX_AUDMUX                       policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_IMX_ES8328                       policy<{'arm64': '-'}>
+CONFIG_SND_SOC_IMX_PCM_DMA                      policy<{'arm64': '-'}>
+CONFIG_SND_SOC_IMX_SGTL5000                     policy<{'arm64': '-'}>
+CONFIG_SND_SOC_IMX_SPDIF                        policy<{'arm64': '-'}>
+CONFIG_SND_SOC_INNO_RK3036                      policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_LOCHNAGAR_SC                     policy<{'arm64': '-'}>
+CONFIG_SND_SOC_LPASS_APQ8016                    policy<{'arm64': '-'}>
+CONFIG_SND_SOC_LPASS_CPU                        policy<{'arm64': '-'}>
+CONFIG_SND_SOC_LPASS_IPQ806X                    policy<{'arm64': '-'}>
+CONFIG_SND_SOC_LPASS_PLATFORM                   policy<{'arm64': '-'}>
+CONFIG_SND_SOC_MAX9759                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_MAX98088                         policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_MAX98090                         policy<{'arm64': '-'}>
+CONFIG_SND_SOC_MAX98357A                        policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_MAX98373                         policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_MAX98504                         policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_MAX9860                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_MAX9867                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_MAX98927                         policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_MEDIATEK                         policy<{'arm64': '-'}>
+CONFIG_SND_SOC_MIKROE_PROTO                     policy<{'arm64': '-'}>
+CONFIG_SND_SOC_MSM8916_WCD_ANALOG               policy<{'arm64': '-'}>
+CONFIG_SND_SOC_MSM8916_WCD_DIGITAL              policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_MSM8996                          policy<{'arm64': '-'}>
+CONFIG_SND_SOC_MT2701                           policy<{'arm64': '-'}>
+CONFIG_SND_SOC_MT6351                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_MT6358                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_MT6797                           policy<{'arm64': '-'}>
+CONFIG_SND_SOC_MT6797_MT6351                    policy<{'arm64': '-'}>
+CONFIG_SND_SOC_MT8173                           policy<{'arm64': '-'}>
+CONFIG_SND_SOC_MT8183                           policy<{'arm64': '-'}>
+CONFIG_SND_SOC_MT8183_DA7219_MAX98357A          policy<{'arm64': '-'}>
+CONFIG_SND_SOC_MT8183_MT6358_TS3A227E_MAX98357A policy<{'arm64': '-'}>
+CONFIG_SND_SOC_MTK_BTCVSD                       policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_NAU8540                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_NAU8810                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_NAU8822                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_NAU8824                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_PCM1681                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_PCM1789                          policy<{'arm64': '-'}>
+CONFIG_SND_SOC_PCM1789_I2C                      policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_PCM179X                          policy<{'arm64': '-'}>
+CONFIG_SND_SOC_PCM179X_I2C                      policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_PCM179X_SPI                      policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_PCM186X                          policy<{'arm64': '-'}>
+CONFIG_SND_SOC_PCM186X_I2C                      policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_PCM186X_SPI                      policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_PCM3060                          policy<{'arm64': '-'}>
+CONFIG_SND_SOC_PCM3060_I2C                      policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_PCM3060_SPI                      policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_PCM3168A                         policy<{'arm64': '-'}>
+CONFIG_SND_SOC_PCM3168A_I2C                     policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_PCM3168A_SPI                     policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_PCM512x                          policy<{'arm64': '-'}>
+CONFIG_SND_SOC_PCM512x_I2C                      policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_PCM512x_SPI                      policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_QCOM                             policy<{'arm64': '-'}>
+CONFIG_SND_SOC_QCOM_COMMON                      policy<{'arm64': '-'}>
+CONFIG_SND_SOC_QDSP6                            policy<{'arm64': '-'}>
+CONFIG_SND_SOC_QDSP6_ADM                        policy<{'arm64': '-'}>
+CONFIG_SND_SOC_QDSP6_AFE                        policy<{'arm64': '-'}>
+CONFIG_SND_SOC_QDSP6_AFE_DAI                    policy<{'arm64': '-'}>
+CONFIG_SND_SOC_QDSP6_ASM                        policy<{'arm64': '-'}>
+CONFIG_SND_SOC_QDSP6_ASM_DAI                    policy<{'arm64': '-'}>
+CONFIG_SND_SOC_QDSP6_COMMON                     policy<{'arm64': '-'}>
+CONFIG_SND_SOC_QDSP6_CORE                       policy<{'arm64': '-'}>
+CONFIG_SND_SOC_QDSP6_ROUTING                    policy<{'arm64': '-'}>
+CONFIG_SND_SOC_RCAR                             policy<{'arm64': '-'}>
+CONFIG_SND_SOC_RK3288_HDMI_ANALOG               policy<{'arm64': '-'}>
+CONFIG_SND_SOC_RK3328                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_RK3399_GRU_SOUND                 policy<{'arm64': '-'}>
+CONFIG_SND_SOC_RL6231                           policy<{'arm64': '-'}>
+CONFIG_SND_SOC_ROCKCHIP                         policy<{'arm64': '-'}>
+CONFIG_SND_SOC_ROCKCHIP_I2S                     policy<{'arm64': '-'}>
+CONFIG_SND_SOC_ROCKCHIP_MAX98090                policy<{'arm64': '-'}>
+CONFIG_SND_SOC_ROCKCHIP_PDM                     policy<{'arm64': '-'}>
+CONFIG_SND_SOC_ROCKCHIP_RT5645                  policy<{'arm64': '-'}>
+CONFIG_SND_SOC_ROCKCHIP_SPDIF                   policy<{'arm64': '-'}>
+CONFIG_SND_SOC_RT5514                           policy<{'arm64': '-'}>
+CONFIG_SND_SOC_RT5514_SPI                       policy<{'arm64': '-'}>
+CONFIG_SND_SOC_RT5616                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_RT5631                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_RT5645                           policy<{'arm64': '-'}>
+CONFIG_SND_SOC_RT5663                           policy<{'arm64': '-'}>
+CONFIG_SND_SOC_SDM845                           policy<{'arm64': '-'}>
+CONFIG_SND_SOC_SGTL5000                         policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_SH4_FSI                          policy<{'arm64': '-'}>
+CONFIG_SND_SOC_SI476X                           policy<{'arm64': '-'}>
+CONFIG_SND_SOC_SIGMADSP                         policy<{'arm64': '-'}>
+CONFIG_SND_SOC_SIGMADSP_I2C                     policy<{'arm64': '-'}>
+CONFIG_SND_SOC_SIGMADSP_REGMAP                  policy<{'arm64': '-'}>
+CONFIG_SND_SOC_SIMPLE_AMPLIFIER                 policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_SIRF_AUDIO_CODEC                 policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_SOF                              policy<{'arm64': '-'}>
+CONFIG_SND_SOC_SOF_ACPI                         policy<{'arm64': '-'}>
+CONFIG_SND_SOC_SOF_DEBUG                        policy<{'arm64': '-'}>
+CONFIG_SND_SOC_SOF_IMX8                         policy<{'arm64': '-'}>
+CONFIG_SND_SOC_SOF_IMX8_SUPPORT                 policy<{'arm64': '-'}>
+CONFIG_SND_SOC_SOF_IMX_TOPLEVEL                 policy<{'arm64': '-'}>
+CONFIG_SND_SOC_SOF_OF                           policy<{'arm64': '-'}>
+CONFIG_SND_SOC_SOF_OPTIONS                      policy<{'arm64': '-'}>
+CONFIG_SND_SOC_SOF_PCI                          policy<{'arm64': '-'}>
+CONFIG_SND_SOC_SOF_STRICT_ABI_CHECKS            policy<{'arm64': '-'}>
+CONFIG_SND_SOC_SOF_TOPLEVEL                     policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_SPDIF                            policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_SPRD                             policy<{'arm64': '-'}>
+CONFIG_SND_SOC_SPRD_MCDT                        policy<{'arm64': '-'}>
+CONFIG_SND_SOC_SSM2305                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_SSM2602                          policy<{'arm64': '-'}>
+CONFIG_SND_SOC_SSM2602_I2C                      policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_SSM2602_SPI                      policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_SSM4567                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_STA32X                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_STA350                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_STI_SAS                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_STORM                            policy<{'arm64': '-'}>
+CONFIG_SND_SOC_TAS2552                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_TAS5086                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_TAS571X                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_TAS5720                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_TAS6424                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_TDA7419                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_TFA9879                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_TLV320AIC23                      policy<{'arm64': '-'}>
+CONFIG_SND_SOC_TLV320AIC23_I2C                  policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_TLV320AIC23_SPI                  policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_TLV320AIC31XX                    policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_TLV320AIC32X4                    policy<{'arm64': '-'}>
+CONFIG_SND_SOC_TLV320AIC32X4_I2C                policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_TLV320AIC32X4_SPI                policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_TLV320AIC3X                      policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_TOPOLOGY                         policy<{'arm64': '-'}>
+CONFIG_SND_SOC_TPA6130A2                        policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_TS3A227E                         policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_TSCS42XX                         policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_TSCS454                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_UDA1334                          policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_WCD9335                          policy<{'arm64': '-'}>
+CONFIG_SND_SOC_WM8510                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_WM8523                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_WM8524                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_WM8580                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_WM8711                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_WM8728                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_WM8731                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_WM8737                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_WM8741                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_WM8750                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_WM8753                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_WM8770                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_WM8776                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_WM8782                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_WM8804                           policy<{'arm64': '-'}>
+CONFIG_SND_SOC_WM8804_I2C                       policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_WM8804_SPI                       policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_WM8903                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_WM8904                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_WM8960                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_WM8962                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_WM8974                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_WM8978                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_WM8985                           policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_XILINX_AUDIO_FORMATTER           policy<{'arm64': 'y'}>
+CONFIG_SND_SOC_XILINX_DP                        policy<{'arm64': 'y'}>
+CONFIG_SND_SOC_XILINX_I2S                       policy<{'arm64': 'y'}>
+CONFIG_SND_SOC_XILINX_PL_SND_CARD               policy<{'arm64': 'y'}>
+CONFIG_SND_SOC_XILINX_SDI                       policy<{'arm64': 'y'}>
+CONFIG_SND_SOC_XILINX_SPDIF                     policy<{'arm64': 'y'}>
+CONFIG_SND_SOC_XTFPGA_I2S                       policy<{'arm64': 'n'}>
+CONFIG_SND_SOC_ZX_AUD96P22                      policy<{'arm64': 'n'}>
+CONFIG_SND_SUN4I_CODEC                          policy<{'arm64': '-'}>
+CONFIG_SND_SUN4I_I2S                            policy<{'arm64': '-'}>
+CONFIG_SND_SUN4I_SPDIF                          policy<{'arm64': '-'}>
+CONFIG_SND_SUN50I_CODEC_ANALOG                  policy<{'arm64': '-'}>
+CONFIG_SND_SUN8I_ADDA_PR_REGMAP                 policy<{'arm64': '-'}>
+CONFIG_SND_SUN8I_CODEC                          policy<{'arm64': '-'}>
+CONFIG_SND_SUN8I_CODEC_ANALOG                   policy<{'arm64': '-'}>
+CONFIG_SND_TIMER                                policy<{'arm64': 'y'}>
+CONFIG_SND_USB_6FIRE                            policy<{'arm64': 'n'}>
+CONFIG_SND_USB_AUDIO                            policy<{'arm64': 'y'}>
+CONFIG_SND_USB_CAIAQ                            policy<{'arm64': 'n'}>
+CONFIG_SND_USB_CAIAQ_INPUT                      policy<{'arm64': '-'}>
+CONFIG_SND_USB_HIFACE                           policy<{'arm64': 'n'}>
+CONFIG_SND_USB_LINE6                            policy<{'arm64': '-'}>
+CONFIG_SND_USB_POD                              policy<{'arm64': 'n'}>
+CONFIG_SND_USB_PODHD                            policy<{'arm64': 'n'}>
+CONFIG_SND_USB_TONEPORT                         policy<{'arm64': 'n'}>
+CONFIG_SND_USB_UA101                            policy<{'arm64': 'n'}>
+CONFIG_SND_USB_VARIAX                           policy<{'arm64': 'n'}>
+CONFIG_SND_VIA82XX                              policy<{'arm64': '-'}>
+CONFIG_SND_VIA82XX_MODEM                        policy<{'arm64': '-'}>
+CONFIG_SND_VIRMIDI                              policy<{'arm64': '-'}>
+CONFIG_SND_VIRTUOSO                             policy<{'arm64': '-'}>
+CONFIG_SND_VMASTER                              policy<{'arm64': '-'}>
+CONFIG_SND_VX222                                policy<{'arm64': '-'}>
+CONFIG_SND_VX_LIB                               policy<{'arm64': '-'}>
+CONFIG_SND_XEN_FRONTEND                         policy<{'arm64': 'n'}>
+CONFIG_SND_YMFPCI                               policy<{'arm64': '-'}>
+CONFIG_SNI_NETSEC                               policy<{'arm64': '-'}>
+CONFIG_SOCK_VALIDATE_XMIT                       policy<{'arm64': '-'}>
+CONFIG_SOC_BRCMSTB                              policy<{'arm64': 'n'}>
+CONFIG_SOC_BUS                                  policy<{'arm64': '-'}>
+CONFIG_SOC_RENESAS                              policy<{'arm64': '-'}>
+CONFIG_SOC_TI                                   policy<{'arm64': 'n'}>
+CONFIG_SOFTLOCKUP_DETECTOR                      policy<{'arm64': 'n'}>
+CONFIG_SOFT_WATCHDOG                            policy<{'arm64': 'n'}>
+CONFIG_SOFT_WATCHDOG_PRETIMEOUT                 policy<{'arm64': '-'}>
+CONFIG_SOLARIS_X86_PARTITION                    policy<{'arm64': '-'}>
+CONFIG_SONY_FF                                  policy<{'arm64': '-'}>
+CONFIG_SOUND_OSS_CORE                           policy<{'arm64': '-'}>
+CONFIG_SPEAKUP                                  policy<{'arm64': 'n'}>
+CONFIG_SPEAKUP_SYNTH_ACNTSA                     policy<{'arm64': '-'}>
+CONFIG_SPEAKUP_SYNTH_APOLLO                     policy<{'arm64': '-'}>
+CONFIG_SPEAKUP_SYNTH_AUDPTR                     policy<{'arm64': '-'}>
+CONFIG_SPEAKUP_SYNTH_BNS                        policy<{'arm64': '-'}>
+CONFIG_SPEAKUP_SYNTH_DECEXT                     policy<{'arm64': '-'}>
+CONFIG_SPEAKUP_SYNTH_DECTLK                     policy<{'arm64': '-'}>
+CONFIG_SPEAKUP_SYNTH_DUMMY                      policy<{'arm64': '-'}>
+CONFIG_SPEAKUP_SYNTH_LTLK                       policy<{'arm64': '-'}>
+CONFIG_SPEAKUP_SYNTH_SOFT                       policy<{'arm64': '-'}>
+CONFIG_SPEAKUP_SYNTH_SPKOUT                     policy<{'arm64': '-'}>
+CONFIG_SPEAKUP_SYNTH_TXPRT                      policy<{'arm64': '-'}>
+CONFIG_SPI_ALTERA                               policy<{'arm64': 'n'}>
+CONFIG_SPI_ARMADA_3700                          policy<{'arm64': '-'}>
+CONFIG_SPI_AXI_SPI_ENGINE                       policy<{'arm64': 'n'}>
+CONFIG_SPI_BCM2835                              policy<{'arm64': '-'}>
+CONFIG_SPI_BCM2835AUX                           policy<{'arm64': '-'}>
+CONFIG_SPI_BCM_QSPI                             policy<{'arm64': '-'}>
+CONFIG_SPI_BITBANG                              policy<{'arm64': 'y'}>
+CONFIG_SPI_BUTTERFLY                            policy<{'arm64': '-'}>
+CONFIG_SPI_CADENCE                              policy<{'arm64': 'y'}>
+CONFIG_SPI_CADENCE_QUADSPI                      policy<{'arm64': 'y'}>
+CONFIG_SPI_DESIGNWARE                           policy<{'arm64': 'n'}>
+CONFIG_SPI_DLN2                                 policy<{'arm64': '-'}>
+CONFIG_SPI_DW_MID_DMA                           policy<{'arm64': '-'}>
+CONFIG_SPI_DW_MMIO                              policy<{'arm64': '-'}>
+CONFIG_SPI_DW_PCI                               policy<{'arm64': '-'}>
+CONFIG_SPI_FSL_DSPI                             policy<{'arm64': '-'}>
+CONFIG_SPI_FSL_LIB                              policy<{'arm64': '-'}>
+CONFIG_SPI_FSL_LPSPI                            policy<{'arm64': '-'}>
+CONFIG_SPI_FSL_QUADSPI                          policy<{'arm64': '-'}>
+CONFIG_SPI_FSL_SPI                              policy<{'arm64': 'n'}>
+CONFIG_SPI_GPIO                                 policy<{'arm64': 'n'}>
+CONFIG_SPI_HISI_SFC                             policy<{'arm64': '-'}>
+CONFIG_SPI_HISI_SFC_V3XX                        policy<{'arm64': '-'}>
+CONFIG_SPI_IMX                                  policy<{'arm64': '-'}>
+CONFIG_SPI_LM70_LLP                             policy<{'arm64': '-'}>
+CONFIG_SPI_LOOPBACK_TEST                        policy<{'arm64': 'n'}>
+CONFIG_SPI_MESON_SPICC                          policy<{'arm64': '-'}>
+CONFIG_SPI_MESON_SPIFC                          policy<{'arm64': '-'}>
+CONFIG_SPI_MT65XX                               policy<{'arm64': '-'}>
+CONFIG_SPI_MTK_QUADSPI                          policy<{'arm64': 'n'}>
+CONFIG_SPI_MXIC                                 policy<{'arm64': 'n'}>
+CONFIG_SPI_NXP_FLEXSPI                          policy<{'arm64': 'n'}>
+CONFIG_SPI_OC_TINY                              policy<{'arm64': 'n'}>
+CONFIG_SPI_OMAP24XX                             policy<{'arm64': '-'}>
+CONFIG_SPI_ORION                                policy<{'arm64': '-'}>
+CONFIG_SPI_PL022                                policy<{'arm64': 'n'}>
+CONFIG_SPI_PXA2XX                               policy<{'arm64': 'n'}>
+CONFIG_SPI_PXA2XX_PCI                           policy<{'arm64': '-'}>
+CONFIG_SPI_QCOM_GENI                            policy<{'arm64': '-'}>
+CONFIG_SPI_QCOM_QSPI                            policy<{'arm64': '-'}>
+CONFIG_SPI_QUP                                  policy<{'arm64': '-'}>
+CONFIG_SPI_ROCKCHIP                             policy<{'arm64': 'n'}>
+CONFIG_SPI_RSPI                                 policy<{'arm64': '-'}>
+CONFIG_SPI_SC18IS602                            policy<{'arm64': 'n'}>
+CONFIG_SPI_SH_HSPI                              policy<{'arm64': '-'}>
+CONFIG_SPI_SH_MSIOF                             policy<{'arm64': '-'}>
+CONFIG_SPI_SIFIVE                               policy<{'arm64': 'n'}>
+CONFIG_SPI_SLAVE                                policy<{'arm64': 'n'}>
+CONFIG_SPI_SLAVE_MT27XX                         policy<{'arm64': '-'}>
+CONFIG_SPI_SLAVE_SYSTEM_CONTROL                 policy<{'arm64': '-'}>
+CONFIG_SPI_SLAVE_TIME                           policy<{'arm64': '-'}>
+CONFIG_SPI_SPIDEV                               policy<{'arm64': 'n'}>
+CONFIG_SPI_SPRD                                 policy<{'arm64': '-'}>
+CONFIG_SPI_SPRD_ADI                             policy<{'arm64': '-'}>
+CONFIG_SPI_SUN4I                                policy<{'arm64': '-'}>
+CONFIG_SPI_SUN6I                                policy<{'arm64': '-'}>
+CONFIG_SPI_SYNQUACER                            policy<{'arm64': '-'}>
+CONFIG_SPI_THUNDERX                             policy<{'arm64': 'n'}>
+CONFIG_SPI_TLE62X0                              policy<{'arm64': 'n'}>
+CONFIG_SPI_XCOMM                                policy<{'arm64': 'n'}>
+CONFIG_SPI_XILINX                               policy<{'arm64': 'y'}>
+CONFIG_SPI_XLP                                  policy<{'arm64': '-'}>
+CONFIG_SPI_ZYNQMP_GQSPI                         policy<{'arm64': 'y'}>
+CONFIG_SPMI                                     policy<{'arm64': 'n'}>
+CONFIG_SPMI_MSM_PMIC_ARB                        policy<{'arm64': '-'}>
+CONFIG_SPMI_PMIC_CLKDIV                         policy<{'arm64': '-'}>
+CONFIG_SPRD_COMMON_CLK                          policy<{'arm64': '-'}>
+CONFIG_SPRD_DMA                                 policy<{'arm64': '-'}>
+CONFIG_SPRD_SC9860_CLK                          policy<{'arm64': '-'}>
+CONFIG_SPRD_TIMER                               policy<{'arm64': '-'}>
+CONFIG_SPRD_WATCHDOG                            policy<{'arm64': '-'}>
+CONFIG_SPS30                                    policy<{'arm64': 'n'}>
+CONFIG_SRF04                                    policy<{'arm64': 'n'}>
+CONFIG_SRF08                                    policy<{'arm64': 'n'}>
+CONFIG_SSB                                      policy<{'arm64': 'n'}>
+CONFIG_SSB_B43_PCI_BRIDGE                       policy<{'arm64': '-'}>
+CONFIG_SSB_BLOCKIO                              policy<{'arm64': '-'}>
+CONFIG_SSB_DRIVER_GPIO                          policy<{'arm64': '-'}>
+CONFIG_SSB_DRIVER_PCICORE                       policy<{'arm64': '-'}>
+CONFIG_SSB_DRIVER_PCICORE_POSSIBLE              policy<{'arm64': '-'}>
+CONFIG_SSB_PCIHOST                              policy<{'arm64': '-'}>
+CONFIG_SSB_PCIHOST_POSSIBLE                     policy<{'arm64': '-'}>
+CONFIG_SSB_SDIOHOST                             policy<{'arm64': '-'}>
+CONFIG_SSB_SDIOHOST_POSSIBLE                    policy<{'arm64': '-'}>
+CONFIG_SSB_SPROM                                policy<{'arm64': '-'}>
+CONFIG_SSFDC                                    policy<{'arm64': 'n'}>
+CONFIG_STACK_TRACER                             policy<{'arm64': 'n'}>
+CONFIG_STAGING_APEX_DRIVER                      policy<{'arm64': '-'}>
+CONFIG_STAGING_GASKET_FRAMEWORK                 policy<{'arm64': 'n'}>
+CONFIG_STAGING_MEDIA                            policy<{'arm64': 'n'}>
+CONFIG_STATIC_KEYS_SELFTEST                     policy<{'arm64': '-'}>
+CONFIG_STE10XP                                  policy<{'arm64': 'y'}>
+CONFIG_STK3310                                  policy<{'arm64': 'n'}>
+CONFIG_STK8312                                  policy<{'arm64': 'n'}>
+CONFIG_STK8BA50                                 policy<{'arm64': 'n'}>
+CONFIG_STM                                      policy<{'arm64': 'n'}>
+CONFIG_STMMAC_ETH                               policy<{'arm64': 'n'}>
+CONFIG_STMMAC_PCI                               policy<{'arm64': '-'}>
+CONFIG_STMMAC_PLATFORM                          policy<{'arm64': '-'}>
+CONFIG_STMMAC_SELFTESTS                         policy<{'arm64': '-'}>
+CONFIG_STMPE_ADC                                policy<{'arm64': '-'}>
+CONFIG_STMPE_I2C                                policy<{'arm64': '-'}>
+CONFIG_STMPE_SPI                                policy<{'arm64': '-'}>
+CONFIG_STMP_DEVICE                              policy<{'arm64': '-'}>
+CONFIG_STM_DUMMY                                policy<{'arm64': '-'}>
+CONFIG_STM_PROTO_BASIC                          policy<{'arm64': '-'}>
+CONFIG_STM_PROTO_SYS_T                          policy<{'arm64': '-'}>
+CONFIG_STM_SOURCE_CONSOLE                       policy<{'arm64': '-'}>
+CONFIG_STM_SOURCE_FTRACE                        policy<{'arm64': '-'}>
+CONFIG_STM_SOURCE_HEARTBEAT                     policy<{'arm64': '-'}>
+CONFIG_STP                                      policy<{'arm64': 'y'}>
+CONFIG_STPMIC1_WATCHDOG                         policy<{'arm64': '-'}>
+CONFIG_STREAM_PARSER                            policy<{'arm64': '-'}>
+CONFIG_STUB_CLK_HI3660                          policy<{'arm64': '-'}>
+CONFIG_STUB_CLK_HI6220                          policy<{'arm64': '-'}>
+CONFIG_ST_UVIS25                                policy<{'arm64': 'n'}>
+CONFIG_ST_UVIS25_I2C                            policy<{'arm64': '-'}>
+CONFIG_ST_UVIS25_SPI                            policy<{'arm64': '-'}>
+CONFIG_SUN4I_EMAC                               policy<{'arm64': '-'}>
+CONFIG_SUN4I_GPADC                              policy<{'arm64': '-'}>
+CONFIG_SUN50I_A64_CCU                           policy<{'arm64': '-'}>
+CONFIG_SUN50I_DE2_BUS                           policy<{'arm64': '-'}>
+CONFIG_SUN50I_ERRATUM_UNKNOWN1                  policy<{'arm64': '-'}>
+CONFIG_SUN50I_H6_CCU                            policy<{'arm64': '-'}>
+CONFIG_SUN50I_H6_R_CCU                          policy<{'arm64': '-'}>
+CONFIG_SUN8I_A83T_CCU                           policy<{'arm64': '-'}>
+CONFIG_SUN8I_DE2_CCU                            policy<{'arm64': '-'}>
+CONFIG_SUN8I_H3_CCU                             policy<{'arm64': '-'}>
+CONFIG_SUN8I_R_CCU                              policy<{'arm64': '-'}>
+CONFIG_SUNDANCE                                 policy<{'arm64': 'n'}>
+CONFIG_SUNDANCE_MMIO                            policy<{'arm64': '-'}>
+CONFIG_SUNGEM                                   policy<{'arm64': 'n'}>
+CONFIG_SUNGEM_PHY                               policy<{'arm64': '-'}>
+CONFIG_SUNRPC                                   policy<{'arm64': 'y'}>
+CONFIG_SUNRPC_DEBUG                             policy<{'arm64': 'n'}>
+CONFIG_SUNRPC_DISABLE_INSECURE_ENCTYPES         policy<{'arm64': '-'}>
+CONFIG_SUNRPC_GSS                               policy<{'arm64': 'y'}>
+CONFIG_SUNRPC_SWAP                              policy<{'arm64': '-'}>
+CONFIG_SUNRPC_XPRT_RDMA                         policy<{'arm64': '-'}>
+CONFIG_SUNXI_CCU                                policy<{'arm64': '-'}>
+CONFIG_SUNXI_RSB                                policy<{'arm64': '-'}>
+CONFIG_SUNXI_SRAM                               policy<{'arm64': '-'}>
+CONFIG_SUNXI_WATCHDOG                           policy<{'arm64': '-'}>
+CONFIG_SUN_PARTITION                            policy<{'arm64': '-'}>
+CONFIG_SW_SYNC                                  policy<{'arm64': 'n'}>
+CONFIG_SX9500                                   policy<{'arm64': 'n'}>
+CONFIG_SXGBE_ETH                                policy<{'arm64': 'n'}>
+CONFIG_SYNCLINKMP                               policy<{'arm64': '-'}>
+CONFIG_SYNCLINK_GT                              policy<{'arm64': '-'}>
+CONFIG_SYSCON_REBOOT_MODE                       policy<{'arm64': '-'}>
+CONFIG_SYSC_R8A774A1                            policy<{'arm64': '-'}>
+CONFIG_SYSC_R8A774C0                            policy<{'arm64': '-'}>
+CONFIG_SYSC_R8A7795                             policy<{'arm64': '-'}>
+CONFIG_SYSC_R8A7796                             policy<{'arm64': '-'}>
+CONFIG_SYSC_R8A77965                            policy<{'arm64': '-'}>
+CONFIG_SYSC_R8A77970                            policy<{'arm64': '-'}>
+CONFIG_SYSC_R8A77980                            policy<{'arm64': '-'}>
+CONFIG_SYSC_R8A77990                            policy<{'arm64': '-'}>
+CONFIG_SYSC_R8A77995                            policy<{'arm64': '-'}>
+CONFIG_SYSC_RCAR                                policy<{'arm64': '-'}>
+CONFIG_SYSTEMPORT                               policy<{'arm64': 'n'}>
+CONFIG_SYSTEM_EXTRA_CERTIFICATE                 policy<{'arm64': 'n'}>
+CONFIG_SYSTEM_EXTRA_CERTIFICATE_SIZE            policy<{'arm64': '-'}>
+CONFIG_SYSV68_PARTITION                         policy<{'arm64': '-'}>
+CONFIG_SYSV_FS                                  policy<{'arm64': 'n'}>
+CONFIG_SYS_SUPPORTS_SH_CMT                      policy<{'arm64': '-'}>
+CONFIG_SYS_SUPPORTS_SH_TMU                      policy<{'arm64': '-'}>
+CONFIG_T5403                                    policy<{'arm64': 'n'}>
+CONFIG_TABLET_SERIAL_WACOM4                     policy<{'arm64': '-'}>
+CONFIG_TABLET_USB_ACECAD                        policy<{'arm64': '-'}>
+CONFIG_TABLET_USB_AIPTEK                        policy<{'arm64': '-'}>
+CONFIG_TABLET_USB_GTCO                          policy<{'arm64': '-'}>
+CONFIG_TABLET_USB_HANWANG                       policy<{'arm64': '-'}>
+CONFIG_TABLET_USB_KBTAB                         policy<{'arm64': '-'}>
+CONFIG_TABLET_USB_PEGASUS                       policy<{'arm64': '-'}>
+CONFIG_TAHVO_USB                                policy<{'arm64': '-'}>
+CONFIG_TAHVO_USB_HOST_BY_DEFAULT                policy<{'arm64': '-'}>
+CONFIG_TAP                                      policy<{'arm64': '-'}>
+CONFIG_TARGET_CORE                              policy<{'arm64': 'n'}>
+CONFIG_TASKS_RCU                                policy<{'arm64': '-'}>
+CONFIG_TCG_ATMEL                                policy<{'arm64': 'n'}>
+CONFIG_TCG_CRB                                  policy<{'arm64': '-'}>
+CONFIG_TCG_FTPM_TEE                             policy<{'arm64': '-'}>
+CONFIG_TCG_INFINEON                             policy<{'arm64': '-'}>
+CONFIG_TCG_TIS                                  policy<{'arm64': 'n'}>
+CONFIG_TCG_TIS_CORE                             policy<{'arm64': 'm'}>
+CONFIG_TCG_TIS_ST33ZP24                         policy<{'arm64': '-'}>
+CONFIG_TCG_TIS_ST33ZP24_I2C                     policy<{'arm64': 'n'}>
+CONFIG_TCG_TIS_ST33ZP24_SPI                     policy<{'arm64': 'n'}>
+CONFIG_TCG_VTPM_PROXY                           policy<{'arm64': 'n'}>
+CONFIG_TCG_XEN                                  policy<{'arm64': 'n'}>
+CONFIG_TCM_FC                                   policy<{'arm64': '-'}>
+CONFIG_TCM_FILEIO                               policy<{'arm64': '-'}>
+CONFIG_TCM_IBLOCK                               policy<{'arm64': '-'}>
+CONFIG_TCM_PSCSI                                policy<{'arm64': '-'}>
+CONFIG_TCM_QLA2XXX                              policy<{'arm64': '-'}>
+CONFIG_TCM_QLA2XXX_DEBUG                        policy<{'arm64': '-'}>
+CONFIG_TCM_USER2                                policy<{'arm64': '-'}>
+CONFIG_TCP_CONG_ADVANCED                        policy<{'arm64': 'n'}>
+CONFIG_TCP_CONG_BBR                             policy<{'arm64': '-'}>
+CONFIG_TCP_CONG_BIC                             policy<{'arm64': '-'}>
+CONFIG_TCP_CONG_CDG                             policy<{'arm64': '-'}>
+CONFIG_TCP_CONG_DCTCP                           policy<{'arm64': '-'}>
+CONFIG_TCP_CONG_HSTCP                           policy<{'arm64': '-'}>
+CONFIG_TCP_CONG_HTCP                            policy<{'arm64': '-'}>
+CONFIG_TCP_CONG_HYBLA                           policy<{'arm64': '-'}>
+CONFIG_TCP_CONG_ILLINOIS                        policy<{'arm64': '-'}>
+CONFIG_TCP_CONG_LP                              policy<{'arm64': '-'}>
+CONFIG_TCP_CONG_NV                              policy<{'arm64': '-'}>
+CONFIG_TCP_CONG_SCALABLE                        policy<{'arm64': '-'}>
+CONFIG_TCP_CONG_VEGAS                           policy<{'arm64': '-'}>
+CONFIG_TCP_CONG_VENO                            policy<{'arm64': '-'}>
+CONFIG_TCP_CONG_WESTWOOD                        policy<{'arm64': '-'}>
+CONFIG_TCP_CONG_YEAH                            policy<{'arm64': '-'}>
+CONFIG_TCP_MD5SIG                               policy<{'arm64': 'n'}>
+CONFIG_TCS3414                                  policy<{'arm64': 'n'}>
+CONFIG_TCS3472                                  policy<{'arm64': 'n'}>
+CONFIG_TEE                                      policy<{'arm64': 'n'}>
+CONFIG_TEHUTI                                   policy<{'arm64': 'n'}>
+CONFIG_TERANETICS_PHY                           policy<{'arm64': 'n'}>
+CONFIG_TEST_OBJAGG                              policy<{'arm64': '-'}>
+CONFIG_TEST_PARMAN                              policy<{'arm64': '-'}>
+CONFIG_TEST_POWER                               policy<{'arm64': 'n'}>
+CONFIG_TEXTSEARCH                               policy<{'arm64': '-'}>
+CONFIG_TEXTSEARCH_BM                            policy<{'arm64': '-'}>
+CONFIG_TEXTSEARCH_FSM                           policy<{'arm64': '-'}>
+CONFIG_TEXTSEARCH_KMP                           policy<{'arm64': '-'}>
+CONFIG_THERMAL                                  policy<{'arm64': 'n'}>
+CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE           policy<{'arm64': '-'}>
+CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR      policy<{'arm64': '-'}>
+CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE            policy<{'arm64': '-'}>
+CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE           policy<{'arm64': '-'}>
+CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS      policy<{'arm64': '-'}>
+CONFIG_THERMAL_EMULATION                        policy<{'arm64': '-'}>
+CONFIG_THERMAL_GOV_BANG_BANG                    policy<{'arm64': '-'}>
+CONFIG_THERMAL_GOV_FAIR_SHARE                   policy<{'arm64': '-'}>
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR              policy<{'arm64': '-'}>
+CONFIG_THERMAL_GOV_STEP_WISE                    policy<{'arm64': '-'}>
+CONFIG_THERMAL_GOV_USER_SPACE                   policy<{'arm64': '-'}>
+CONFIG_THERMAL_HWMON                            policy<{'arm64': '-'}>
+CONFIG_THERMAL_MMIO                             policy<{'arm64': '-'}>
+CONFIG_THERMAL_OF                               policy<{'arm64': '-'}>
+CONFIG_THERMAL_STATISTICS                       policy<{'arm64': '-'}>
+CONFIG_THERMAL_WRITABLE_TRIPS                   policy<{'arm64': '-'}>
+CONFIG_THRUSTMASTER_FF                          policy<{'arm64': '-'}>
+CONFIG_THUNDERX2_PMU                            policy<{'arm64': '-'}>
+CONFIG_THUNDER_NIC_BGX                          policy<{'arm64': 'n'}>
+CONFIG_THUNDER_NIC_PF                           policy<{'arm64': 'n'}>
+CONFIG_THUNDER_NIC_RGX                          policy<{'arm64': 'n'}>
+CONFIG_THUNDER_NIC_VF                           policy<{'arm64': 'n'}>
+CONFIG_TIFM_7XX1                                policy<{'arm64': '-'}>
+CONFIG_TIFM_CORE                                policy<{'arm64': 'n'}>
+CONFIG_TIGON3                                   policy<{'arm64': 'n'}>
+CONFIG_TIGON3_HWMON                             policy<{'arm64': '-'}>
+CONFIG_TIMER_ACPI                               policy<{'arm64': '-'}>
+CONFIG_TIMER_IMX_SYS_CTR                        policy<{'arm64': '-'}>
+CONFIG_TINYDRM_HX8357D                          policy<{'arm64': 'n'}>
+CONFIG_TINYDRM_ILI9225                          policy<{'arm64': 'n'}>
+CONFIG_TINYDRM_ILI9341                          policy<{'arm64': 'n'}>
+CONFIG_TINYDRM_MI0283QT                         policy<{'arm64': 'n'}>
+CONFIG_TINYDRM_REPAPER                          policy<{'arm64': 'n'}>
+CONFIG_TINYDRM_ST7586                           policy<{'arm64': 'n'}>
+CONFIG_TINYDRM_ST7735R                          policy<{'arm64': 'n'}>
+CONFIG_TIPC                                     policy<{'arm64': 'n'}>
+CONFIG_TIPC_DIAG                                policy<{'arm64': '-'}>
+CONFIG_TIPC_MEDIA_IB                            policy<{'arm64': '-'}>
+CONFIG_TIPC_MEDIA_UDP                           policy<{'arm64': '-'}>
+CONFIG_TI_ADC081C                               policy<{'arm64': 'n'}>
+CONFIG_TI_ADC0832                               policy<{'arm64': 'n'}>
+CONFIG_TI_ADC084S021                            policy<{'arm64': 'n'}>
+CONFIG_TI_ADC108S102                            policy<{'arm64': 'n'}>
+CONFIG_TI_ADC12138                              policy<{'arm64': 'n'}>
+CONFIG_TI_ADC128S052                            policy<{'arm64': 'n'}>
+CONFIG_TI_ADC161S626                            policy<{'arm64': 'n'}>
+CONFIG_TI_ADS1015                               policy<{'arm64': 'n'}>
+CONFIG_TI_ADS124S08                             policy<{'arm64': 'n'}>
+CONFIG_TI_ADS7950                               policy<{'arm64': 'n'}>
+CONFIG_TI_ADS8344                               policy<{'arm64': 'n'}>
+CONFIG_TI_ADS8688                               policy<{'arm64': 'n'}>
+CONFIG_TI_AM335X_ADC                            policy<{'arm64': '-'}>
+CONFIG_TI_DAC082S085                            policy<{'arm64': 'n'}>
+CONFIG_TI_DAC5571                               policy<{'arm64': 'n'}>
+CONFIG_TI_DAC7311                               policy<{'arm64': 'n'}>
+CONFIG_TI_DAC7612                               policy<{'arm64': 'n'}>
+CONFIG_TI_MESSAGE_MANAGER                       policy<{'arm64': '-'}>
+CONFIG_TI_SCI_CLK                               policy<{'arm64': '-'}>
+CONFIG_TI_SCI_CLK_PROBE_FROM_FW                 policy<{'arm64': '-'}>
+CONFIG_TI_SCI_INTA_IRQCHIP                      policy<{'arm64': '-'}>
+CONFIG_TI_SCI_INTA_MSI_DOMAIN                   policy<{'arm64': '-'}>
+CONFIG_TI_SCI_INTR_IRQCHIP                      policy<{'arm64': '-'}>
+CONFIG_TI_SCI_PM_DOMAINS                        policy<{'arm64': '-'}>
+CONFIG_TI_SCI_PROTOCOL                          policy<{'arm64': '-'}>
+CONFIG_TI_ST                                    policy<{'arm64': 'y'}>
+CONFIG_TI_TLC4541                               policy<{'arm64': 'n'}>
+CONFIG_TLAN                                     policy<{'arm64': 'n'}>
+CONFIG_TLS                                      policy<{'arm64': 'n'}>
+CONFIG_TLS_DEVICE                               policy<{'arm64': '-'}>
+CONFIG_TMD_HERMES                               policy<{'arm64': '-'}>
+CONFIG_TMP006                                   policy<{'arm64': 'n'}>
+CONFIG_TMP007                                   policy<{'arm64': 'n'}>
+CONFIG_TORTURE_TEST                             policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_88PM860X                     policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_AD7877                       policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_AD7879                       policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_AD7879_I2C                   policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_AD7879_SPI                   policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_ADC                          policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_ADS7846                      policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_AR1021_I2C                   policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_ATMEL_MXT                    policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_ATMEL_MXT_T37                policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_AUO_PIXCIR                   policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_BU21013                      policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_BU21029                      policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_CHIPONE_ICN8318              policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_CHIPONE_ICN8505              policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_COLIBRI_VF50                 policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_CY8CTMG110                   policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_CYTTSP4_CORE                 policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_CYTTSP4_I2C                  policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_CYTTSP4_SPI                  policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_CYTTSP_CORE                  policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_CYTTSP_I2C                   policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_CYTTSP_SPI                   policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_DA9034                       policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_DA9052                       policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_DYNAPRO                      policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_EDT_FT5X06                   policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_EETI                         policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_EGALAX                       policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_EGALAX_SERIAL                policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_EKTF2127                     policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_ELO                          policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_EXC3000                      policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_FUJITSU                      policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_GOODIX                       policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_GUNZE                        policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_HAMPSHIRE                    policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_HIDEEP                       policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_ILI210X                      policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_IMX6UL_TSC                   policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_INEXIO                       policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_IPROC                        policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_IQS5XX                       policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_MAX11801                     policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_MC13783                      policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_MCS5000                      policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_MELFAS_MIP4                  policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_MK712                        policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_MMS114                       policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_MTOUCH                       policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_PCAP                         policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_PENMOUNT                     policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_PIXCIR                       policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_PROPERTIES                   policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_RASPBERRYPI_FW               policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_RM_TS                        policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_ROHM_BU21023                 policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_S6SY761                      policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_SILEAD                       policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_SIS_I2C                      policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_ST1232                       policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_STMFTS                       policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_STMPE                        policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_SUN4I                        policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_SUR40                        policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_SURFACE3_SPI                 policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_SX8654                       policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_TI_AM335X_TSC                policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_TOUCHIT213                   policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_TOUCHRIGHT                   policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_TOUCHWIN                     policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_TPS6507X                     policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_TSC2004                      policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_TSC2005                      policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_TSC2007                      policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_TSC2007_IIO                  policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_TSC200X_CORE                 policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_TSC_SERIO                    policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_UCB1400                      policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_USB_3M                       policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_USB_COMPOSITE                policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_USB_DMC_TSC10                policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_USB_E2I                      policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_USB_EASYTOUCH                policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_USB_EGALAX                   policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_USB_ELO                      policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_USB_ETT_TC45USB              policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_USB_ETURBO                   policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH            policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_USB_GOTOP                    policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_USB_GUNZE                    policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_USB_IDEALTEK                 policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_USB_IRTOUCH                  policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_USB_ITM                      policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_USB_JASTEC                   policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_USB_NEXIO                    policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_USB_PANJIT                   policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_USB_ZYTRONIC                 policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_WACOM_I2C                    policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_WACOM_W8001                  policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_WDT87XX_I2C                  policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_WM831X                       policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_WM9705                       policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_WM9712                       policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_WM9713                       policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_WM97XX                       policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_ZET6223                      policy<{'arm64': '-'}>
+CONFIG_TOUCHSCREEN_ZFORCE                       policy<{'arm64': '-'}>
+CONFIG_TPL0102                                  policy<{'arm64': 'n'}>
+CONFIG_TPM_KEY_PARSER                           policy<{'arm64': '-'}>
+CONFIG_TPS6105X                                 policy<{'arm64': 'n'}>
+CONFIG_TPS65010                                 policy<{'arm64': 'n'}>
+CONFIG_TPS6507X                                 policy<{'arm64': 'n'}>
+CONFIG_TPS68470_PMIC_OPREGION                   policy<{'arm64': '-'}>
+CONFIG_TRACER_MAX_TRACE                         policy<{'arm64': '-'}>
+CONFIG_TRACER_SNAPSHOT                          policy<{'arm64': 'n'}>
+CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP             policy<{'arm64': '-'}>
+CONFIG_TRACE_ROUTER                             policy<{'arm64': '-'}>
+CONFIG_TRACE_SINK                               policy<{'arm64': 'n'}>
+CONFIG_TRACING_MAP                              policy<{'arm64': '-'}>
+CONFIG_TRIM_UNUSED_KSYMS                        policy<{'arm64': 'n'}>
+CONFIG_TRUSTED_KEYS                             policy<{'arm64': 'n'}>
+CONFIG_TSL2583                                  policy<{'arm64': 'n'}>
+CONFIG_TSL2772                                  policy<{'arm64': 'n'}>
+CONFIG_TSL4531                                  policy<{'arm64': 'n'}>
+CONFIG_TSYS01                                   policy<{'arm64': 'n'}>
+CONFIG_TSYS02D                                  policy<{'arm64': 'n'}>
+CONFIG_TTPCI_EEPROM                             policy<{'arm64': '-'}>
+CONFIG_TTY_PRINTK                               policy<{'arm64': 'n'}>
+CONFIG_TTY_PRINTK_LEVEL                         policy<{'arm64': '-'}>
+CONFIG_TULIP                                    policy<{'arm64': '-'}>
+CONFIG_TULIP_MMIO                               policy<{'arm64': '-'}>
+CONFIG_TULIP_MWI                                policy<{'arm64': '-'}>
+CONFIG_TULIP_NAPI                               policy<{'arm64': '-'}>
+CONFIG_TURRIS_MOX_RWTM                          policy<{'arm64': '-'}>
+CONFIG_TWL4030_CORE                             policy<{'arm64': 'n'}>
+CONFIG_TWL4030_MADC                             policy<{'arm64': '-'}>
+CONFIG_TWL4030_WATCHDOG                         policy<{'arm64': '-'}>
+CONFIG_TWL6030_GPADC                            policy<{'arm64': '-'}>
+CONFIG_TWL6040_CORE                             policy<{'arm64': 'n'}>
+CONFIG_TYPEC                                    policy<{'arm64': 'n'}>
+CONFIG_TYPEC_DP_ALTMODE                         policy<{'arm64': '-'}>
+CONFIG_TYPEC_FUSB302                            policy<{'arm64': '-'}>
+CONFIG_TYPEC_MUX_PI3USB30532                    policy<{'arm64': '-'}>
+CONFIG_TYPEC_NVIDIA_ALTMODE                     policy<{'arm64': '-'}>
+CONFIG_TYPEC_RT1711H                            policy<{'arm64': '-'}>
+CONFIG_TYPEC_TCPCI                              policy<{'arm64': '-'}>
+CONFIG_TYPEC_TCPM                               policy<{'arm64': '-'}>
+CONFIG_TYPEC_TPS6598X                           policy<{'arm64': '-'}>
+CONFIG_TYPEC_UCSI                               policy<{'arm64': '-'}>
+CONFIG_TYPHOON                                  policy<{'arm64': 'n'}>
+CONFIG_UBIFS_FS_ADVANCED_COMPR                  policy<{'arm64': 'y'}>
+CONFIG_UCB1400_CORE                             policy<{'arm64': '-'}>
+CONFIG_UCLAMP_BUCKETS_COUNT                     policy<{'arm64': '-'}>
+CONFIG_UCLAMP_TASK                              policy<{'arm64': '-'}>
+CONFIG_UCLAMP_TASK_GROUP                        policy<{'arm64': '-'}>
+CONFIG_UCSI_ACPI                                policy<{'arm64': '-'}>
+CONFIG_UCSI_CCG                                 policy<{'arm64': '-'}>
+CONFIG_UDF_FS                                   policy<{'arm64': 'n'}>
+CONFIG_UDMABUF                                  policy<{'arm64': 'n'}>
+CONFIG_UEFI_CPER                                policy<{'arm64': '-'}>
+CONFIG_UEFI_CPER_ARM                            policy<{'arm64': '-'}>
+CONFIG_UEVENT_HELPER                            policy<{'arm64': 'n'}>
+CONFIG_UEVENT_HELPER_PATH                       policy<{'arm64': '-'}>
+CONFIG_UFS_DEBUG                                policy<{'arm64': '-'}>
+CONFIG_UFS_FS                                   policy<{'arm64': 'n'}>
+CONFIG_UFS_FS_WRITE                             policy<{'arm64': '-'}>
+CONFIG_UHID                                     policy<{'arm64': 'n'}>
+CONFIG_UIO                                      policy<{'arm64': 'y'}>
+CONFIG_UIO_AEC                                  policy<{'arm64': 'n'}>
+CONFIG_UIO_CIF                                  policy<{'arm64': 'n'}>
+CONFIG_UIO_DMEM_GENIRQ                          policy<{'arm64': 'y'}>
+CONFIG_UIO_MF624                                policy<{'arm64': 'n'}>
+CONFIG_UIO_NETX                                 policy<{'arm64': 'n'}>
+CONFIG_UIO_PCI_GENERIC                          policy<{'arm64': 'n'}>
+CONFIG_UIO_PDRV_GENIRQ                          policy<{'arm64': 'y'}>
+CONFIG_UIO_PRUSS                                policy<{'arm64': 'n'}>
+CONFIG_UIO_SERCOS3                              policy<{'arm64': 'n'}>
+CONFIG_UIO_XILINX_AI_ENGINE                     policy<{'arm64': 'y'}>
+CONFIG_UIO_XILINX_APM                           policy<{'arm64': 'y'}>
+CONFIG_ULI526X                                  policy<{'arm64': '-'}>
+CONFIG_ULTRIX_PARTITION                         policy<{'arm64': '-'}>
+CONFIG_UNICODE                                  policy<{'arm64': 'n'}>
+CONFIG_UNICODE_NORMALIZATION_SELFTEST           policy<{'arm64': '-'}>
+CONFIG_UNISYSSPAR                               policy<{'arm64': 'n'}>
+CONFIG_UNIXWARE_DISKLABEL                       policy<{'arm64': '-'}>
+CONFIG_UNUSED_SYMBOLS                           policy<{'arm64': 'n'}>
+CONFIG_US5182D                                  policy<{'arm64': 'n'}>
+CONFIG_USBIP_CORE                               policy<{'arm64': 'n'}>
+CONFIG_USBIP_DEBUG                              policy<{'arm64': '-'}>
+CONFIG_USBIP_HOST                               policy<{'arm64': '-'}>
+CONFIG_USBIP_VHCI_HCD                           policy<{'arm64': '-'}>
+CONFIG_USBIP_VHCI_HC_PORTS                      policy<{'arm64': '-'}>
+CONFIG_USBIP_VHCI_NR_HCS                        policy<{'arm64': '-'}>
+CONFIG_USBIP_VUDC                               policy<{'arm64': '-'}>
+CONFIG_USBPCWATCHDOG                            policy<{'arm64': 'n'}>
+CONFIG_USB_ACM                                  policy<{'arm64': 'n'}>
+CONFIG_USB_ADUTUX                               policy<{'arm64': 'n'}>
+CONFIG_USB_AIRSPY                               policy<{'arm64': '-'}>
+CONFIG_USB_ALI_M5632                            policy<{'arm64': 'n'}>
+CONFIG_USB_AMD5536UDC                           policy<{'arm64': 'n'}>
+CONFIG_USB_AN2720                               policy<{'arm64': 'n'}>
+CONFIG_USB_APPLEDISPLAY                         policy<{'arm64': 'n'}>
+CONFIG_USB_ATM                                  policy<{'arm64': '-'}>
+CONFIG_USB_AUDIO                                policy<{'arm64': 'n'}>
+CONFIG_USB_BDC_UDC                              policy<{'arm64': 'n'}>
+CONFIG_USB_C67X00_HCD                           policy<{'arm64': 'n'}>
+CONFIG_USB_CATC                                 policy<{'arm64': 'n'}>
+CONFIG_USB_CDC_COMPOSITE                        policy<{'arm64': 'n'}>
+CONFIG_USB_CDC_PHONET                           policy<{'arm64': '-'}>
+CONFIG_USB_CDNS3                                policy<{'arm64': 'n'}>
+CONFIG_USB_CDNS3_GADGET                         policy<{'arm64': '-'}>
+CONFIG_USB_CDNS3_HOST                           policy<{'arm64': '-'}>
+CONFIG_USB_CDNS3_PCI_WRAP                       policy<{'arm64': '-'}>
+CONFIG_USB_CHAOSKEY                             policy<{'arm64': '-'}>
+CONFIG_USB_CHIPIDEA                             policy<{'arm64': 'n'}>
+CONFIG_USB_CHIPIDEA_HOST                        policy<{'arm64': '-'}>
+CONFIG_USB_CHIPIDEA_OF                          policy<{'arm64': '-'}>
+CONFIG_USB_CHIPIDEA_PCI                         policy<{'arm64': '-'}>
+CONFIG_USB_CHIPIDEA_UDC                         policy<{'arm64': '-'}>
+CONFIG_USB_CONFIGFS                             policy<{'arm64': 'y'}>
+CONFIG_USB_CONFIGFS_ACM                         policy<{'arm64': 'n'}>
+CONFIG_USB_CONFIGFS_ECM                         policy<{'arm64': 'n'}>
+CONFIG_USB_CONFIGFS_ECM_SUBSET                  policy<{'arm64': 'n'}>
+CONFIG_USB_CONFIGFS_F_FS                        policy<{'arm64': 'n'}>
+CONFIG_USB_CONFIGFS_F_HID                       policy<{'arm64': 'n'}>
+CONFIG_USB_CONFIGFS_F_LB_SS                     policy<{'arm64': 'n'}>
+CONFIG_USB_CONFIGFS_F_MIDI                      policy<{'arm64': 'n'}>
+CONFIG_USB_CONFIGFS_F_PRINTER                   policy<{'arm64': 'n'}>
+CONFIG_USB_CONFIGFS_F_TCM                       policy<{'arm64': '-'}>
+CONFIG_USB_CONFIGFS_F_UAC1                      policy<{'arm64': 'n'}>
+CONFIG_USB_CONFIGFS_F_UAC1_LEGACY               policy<{'arm64': 'n'}>
+CONFIG_USB_CONFIGFS_F_UAC2                      policy<{'arm64': 'n'}>
+CONFIG_USB_CONFIGFS_F_UVC                       policy<{'arm64': 'n'}>
+CONFIG_USB_CONFIGFS_NCM                         policy<{'arm64': 'n'}>
+CONFIG_USB_CONFIGFS_OBEX                        policy<{'arm64': 'n'}>
+CONFIG_USB_CONFIGFS_PHONET                      policy<{'arm64': '-'}>
+CONFIG_USB_CONFIGFS_RNDIS                       policy<{'arm64': 'n'}>
+CONFIG_USB_CONFIGFS_SERIAL                      policy<{'arm64': 'n'}>
+CONFIG_USB_CONN_GPIO                            policy<{'arm64': 'n'}>
+CONFIG_USB_CXACRU                               policy<{'arm64': '-'}>
+CONFIG_USB_CYPRESS_CY7C63                       policy<{'arm64': 'n'}>
+CONFIG_USB_CYTHERM                              policy<{'arm64': 'n'}>
+CONFIG_USB_DEFAULT_PERSIST                      policy<{'arm64': 'n'}>
+CONFIG_USB_DSBR                                 policy<{'arm64': '-'}>
+CONFIG_USB_DWC2                                 policy<{'arm64': 'n'}>
+CONFIG_USB_DWC2_DEBUG                           policy<{'arm64': '-'}>
+CONFIG_USB_DWC2_HOST                            policy<{'arm64': '-'}>
+CONFIG_USB_DWC2_PCI                             policy<{'arm64': '-'}>
+CONFIG_USB_DWC2_TRACK_MISSED_SOFS               policy<{'arm64': '-'}>
+CONFIG_USB_DWC3                                 policy<{'arm64': 'y'}>
+CONFIG_USB_DWC3_HAPS                            policy<{'arm64': 'y'}>
+CONFIG_USB_DWC3_KEYSTONE                        policy<{'arm64': '-'}>
+CONFIG_USB_DWC3_MESON_G12A                      policy<{'arm64': '-'}>
+CONFIG_USB_DWC3_OF_SIMPLE                       policy<{'arm64': 'y'}>
+CONFIG_USB_DWC3_OTG                             policy<{'arm64': 'n'}>
+CONFIG_USB_DWC3_PCI                             policy<{'arm64': '-'}>
+CONFIG_USB_DWC3_QCOM                            policy<{'arm64': '-'}>
+CONFIG_USB_DWC3_ULPI                            policy<{'arm64': '-'}>
+CONFIG_USB_DYNAMIC_MINORS                       policy<{'arm64': 'n'}>
+CONFIG_USB_EG20T                                policy<{'arm64': 'n'}>
+CONFIG_USB_EHCI_FSL                             policy<{'arm64': '-'}>
+CONFIG_USB_EHCI_HCD_ORION                       policy<{'arm64': '-'}>
+CONFIG_USB_EHCI_MXC                             policy<{'arm64': '-'}>
+CONFIG_USB_EHCI_PCI                             policy<{'arm64': '-'}>
+CONFIG_USB_EHCI_ROOT_HUB_TT                     policy<{'arm64': '-'}>
+CONFIG_USB_EHCI_TT_NEWSCHED                     policy<{'arm64': '-'}>
+CONFIG_USB_EHSET_TEST_FIXTURE                   policy<{'arm64': 'n'}>
+CONFIG_USB_EMI26                                policy<{'arm64': 'n'}>
+CONFIG_USB_EMI62                                policy<{'arm64': 'n'}>
+CONFIG_USB_EMXX                                 policy<{'arm64': '-'}>
+CONFIG_USB_EPSON2888                            policy<{'arm64': 'n'}>
+CONFIG_USB_EZUSB_FX2                            policy<{'arm64': 'n'}>
+CONFIG_USB_FOTG210_HCD                          policy<{'arm64': 'n'}>
+CONFIG_USB_FOTG210_UDC                          policy<{'arm64': 'n'}>
+CONFIG_USB_FSL_USB2                             policy<{'arm64': '-'}>
+CONFIG_USB_FTDI_ELAN                            policy<{'arm64': 'n'}>
+CONFIG_USB_FUNCTIONFS                           policy<{'arm64': 'n'}>
+CONFIG_USB_FUNCTIONFS_ETH                       policy<{'arm64': '-'}>
+CONFIG_USB_FUNCTIONFS_GENERIC                   policy<{'arm64': '-'}>
+CONFIG_USB_FUNCTIONFS_RNDIS                     policy<{'arm64': '-'}>
+CONFIG_USB_F_ACM                                policy<{'arm64': '-'}>
+CONFIG_USB_F_EEM                                policy<{'arm64': 'y'}>
+CONFIG_USB_F_FS                                 policy<{'arm64': '-'}>
+CONFIG_USB_F_HID                                policy<{'arm64': '-'}>
+CONFIG_USB_F_MASS_STORAGE                       policy<{'arm64': 'y'}>
+CONFIG_USB_F_MIDI                               policy<{'arm64': '-'}>
+CONFIG_USB_F_NCM                                policy<{'arm64': '-'}>
+CONFIG_USB_F_OBEX                               policy<{'arm64': '-'}>
+CONFIG_USB_F_PHONET                             policy<{'arm64': '-'}>
+CONFIG_USB_F_PRINTER                            policy<{'arm64': '-'}>
+CONFIG_USB_F_SERIAL                             policy<{'arm64': '-'}>
+CONFIG_USB_F_SS_LB                              policy<{'arm64': '-'}>
+CONFIG_USB_F_TCM                                policy<{'arm64': '-'}>
+CONFIG_USB_F_UAC1                               policy<{'arm64': '-'}>
+CONFIG_USB_F_UAC1_LEGACY                        policy<{'arm64': '-'}>
+CONFIG_USB_F_UAC2                               policy<{'arm64': '-'}>
+CONFIG_USB_F_UVC                                policy<{'arm64': '-'}>
+CONFIG_USB_GADGET                               policy<{'arm64': 'y'}>
+CONFIG_USB_GADGETFS                             policy<{'arm64': 'n'}>
+CONFIG_USB_GADGET_TARGET                        policy<{'arm64': '-'}>
+CONFIG_USB_GADGET_XILINX                        policy<{'arm64': 'y'}>
+CONFIG_USB_GL860                                policy<{'arm64': 'n'}>
+CONFIG_USB_GOKU                                 policy<{'arm64': 'n'}>
+CONFIG_USB_GPIO_VBUS                            policy<{'arm64': 'n'}>
+CONFIG_USB_GR_UDC                               policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_BENQ                           policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_CONEX                          policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_CPIA1                          policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_DTCS033                        policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_ETOMS                          policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_FINEPIX                        policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_JEILINJ                        policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_JL2005BCD                      policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_KINECT                         policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_KONICA                         policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_MARS                           policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_MR97310A                       policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_NW80X                          policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_OV519                          policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_OV534                          policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_OV534_9                        policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_PAC207                         policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_PAC7302                        policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_PAC7311                        policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_SE401                          policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_SN9C2028                       policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_SN9C20X                        policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_SONIXB                         policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_SONIXJ                         policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_SPCA1528                       policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_SPCA500                        policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_SPCA501                        policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_SPCA505                        policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_SPCA506                        policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_SPCA508                        policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_SPCA561                        policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_SQ905                          policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_SQ905C                         policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_SQ930X                         policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_STK014                         policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_STK1135                        policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_STV0680                        policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_SUNPLUS                        policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_T613                           policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_TOPRO                          policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_TOUPTEK                        policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_TV8532                         policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_VC032X                         policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_VICAM                          policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_XIRLINK_CIT                    policy<{'arm64': 'n'}>
+CONFIG_USB_GSPCA_ZC3XX                          policy<{'arm64': 'n'}>
+CONFIG_USB_G_ACM_MS                             policy<{'arm64': 'n'}>
+CONFIG_USB_G_DBGP                               policy<{'arm64': 'n'}>
+CONFIG_USB_G_DBGP_PRINTK                        policy<{'arm64': '-'}>
+CONFIG_USB_G_DBGP_SERIAL                        policy<{'arm64': '-'}>
+CONFIG_USB_G_HID                                policy<{'arm64': 'n'}>
+CONFIG_USB_G_NCM                                policy<{'arm64': 'n'}>
+CONFIG_USB_G_NOKIA                              policy<{'arm64': '-'}>
+CONFIG_USB_G_PRINTER                            policy<{'arm64': 'n'}>
+CONFIG_USB_G_SERIAL                             policy<{'arm64': 'n'}>
+CONFIG_USB_G_WEBCAM                             policy<{'arm64': 'n'}>
+CONFIG_USB_HACKRF                               policy<{'arm64': '-'}>
+CONFIG_USB_HID                                  policy<{'arm64': 'y'}>
+CONFIG_USB_HIDDEV                               policy<{'arm64': 'n'}>
+CONFIG_USB_HSIC_USB3503                         policy<{'arm64': 'n'}>
+CONFIG_USB_HSIC_USB4604                         policy<{'arm64': 'n'}>
+CONFIG_USB_HSO                                  policy<{'arm64': 'n'}>
+CONFIG_USB_HUB_USB251XB                         policy<{'arm64': 'n'}>
+CONFIG_USB_HWA_HCD                              policy<{'arm64': '-'}>
+CONFIG_USB_IDMOUSE                              policy<{'arm64': 'n'}>
+CONFIG_USB_IOWARRIOR                            policy<{'arm64': 'n'}>
+CONFIG_USB_IPHETH                               policy<{'arm64': 'n'}>
+CONFIG_USB_ISIGHTFW                             policy<{'arm64': 'n'}>
+CONFIG_USB_ISP116X_HCD                          policy<{'arm64': 'n'}>
+CONFIG_USB_ISP1301                              policy<{'arm64': 'n'}>
+CONFIG_USB_ISP1760                              policy<{'arm64': 'n'}>
+CONFIG_USB_ISP1760_DUAL_ROLE                    policy<{'arm64': '-'}>
+CONFIG_USB_ISP1760_GADGET_ROLE                  policy<{'arm64': '-'}>
+CONFIG_USB_ISP1760_HCD                          policy<{'arm64': '-'}>
+CONFIG_USB_ISP1760_HOST_ROLE                    policy<{'arm64': '-'}>
+CONFIG_USB_ISP1761_UDC                          policy<{'arm64': '-'}>
+CONFIG_USB_KAWETH                               policy<{'arm64': 'n'}>
+CONFIG_USB_KBD                                  policy<{'arm64': '-'}>
+CONFIG_USB_KC2190                               policy<{'arm64': 'n'}>
+CONFIG_USB_KEENE                                policy<{'arm64': '-'}>
+CONFIG_USB_LAN78XX                              policy<{'arm64': 'n'}>
+CONFIG_USB_LCD                                  policy<{'arm64': 'n'}>
+CONFIG_USB_LD                                   policy<{'arm64': 'n'}>
+CONFIG_USB_LEDS_TRIGGER_USBPORT                 policy<{'arm64': 'n'}>
+CONFIG_USB_LED_TRIG                             policy<{'arm64': 'n'}>
+CONFIG_USB_LEGOTOWER                            policy<{'arm64': 'n'}>
+CONFIG_USB_LIBCOMPOSITE                         policy<{'arm64': 'y'}>
+CONFIG_USB_LINK_LAYER_TEST                      policy<{'arm64': 'n'}>
+CONFIG_USB_M5602                                policy<{'arm64': 'n'}>
+CONFIG_USB_MA901                                policy<{'arm64': '-'}>
+CONFIG_USB_MAX3421_HCD                          policy<{'arm64': 'n'}>
+CONFIG_USB_MDC800                               policy<{'arm64': 'n'}>
+CONFIG_USB_MICROTEK                             policy<{'arm64': 'n'}>
+CONFIG_USB_MIDI_GADGET                          policy<{'arm64': 'n'}>
+CONFIG_USB_MON                                  policy<{'arm64': 'n'}>
+CONFIG_USB_MOUSE                                policy<{'arm64': '-'}>
+CONFIG_USB_MR800                                policy<{'arm64': '-'}>
+CONFIG_USB_MSI2500                              policy<{'arm64': '-'}>
+CONFIG_USB_MTU3                                 policy<{'arm64': '-'}>
+CONFIG_USB_MTU3_DEBUG                           policy<{'arm64': '-'}>
+CONFIG_USB_MTU3_DUAL_ROLE                       policy<{'arm64': '-'}>
+CONFIG_USB_MTU3_GADGET                          policy<{'arm64': '-'}>
+CONFIG_USB_MTU3_HOST                            policy<{'arm64': '-'}>
+CONFIG_USB_MUSB_DUAL_ROLE                       policy<{'arm64': '-'}>
+CONFIG_USB_MUSB_GADGET                          policy<{'arm64': '-'}>
+CONFIG_USB_MUSB_HOST                            policy<{'arm64': '-'}>
+CONFIG_USB_MUSB_SUNXI                           policy<{'arm64': '-'}>
+CONFIG_USB_MV_U3D                               policy<{'arm64': 'n'}>
+CONFIG_USB_MV_UDC                               policy<{'arm64': 'n'}>
+CONFIG_USB_MXS_PHY                              policy<{'arm64': '-'}>
+CONFIG_USB_NET2272                              policy<{'arm64': 'n'}>
+CONFIG_USB_NET2272_DMA                          policy<{'arm64': '-'}>
+CONFIG_USB_NET2280                              policy<{'arm64': 'n'}>
+CONFIG_USB_NET_AQC111                           policy<{'arm64': 'n'}>
+CONFIG_USB_NET_AX88179_178A                     policy<{'arm64': 'y'}>
+CONFIG_USB_NET_AX8817X                          policy<{'arm64': 'y'}>
+CONFIG_USB_NET_CDCETHER                         policy<{'arm64': 'y'}>
+CONFIG_USB_NET_CDC_EEM                          policy<{'arm64': 'n'}>
+CONFIG_USB_NET_CDC_MBIM                         policy<{'arm64': 'n'}>
+CONFIG_USB_NET_CDC_NCM                          policy<{'arm64': 'y'}>
+CONFIG_USB_NET_CDC_SUBSET                       policy<{'arm64': 'y'}>
+CONFIG_USB_NET_CDC_SUBSET_ENABLE                policy<{'arm64': 'y'}>
+CONFIG_USB_NET_CH9200                           policy<{'arm64': 'n'}>
+CONFIG_USB_NET_CX82310_ETH                      policy<{'arm64': 'n'}>
+CONFIG_USB_NET_DM9601                           policy<{'arm64': 'n'}>
+CONFIG_USB_NET_DRIVERS                          policy<{'arm64': 'y'}>
+CONFIG_USB_NET_GL620A                           policy<{'arm64': 'n'}>
+CONFIG_USB_NET_HUAWEI_CDC_NCM                   policy<{'arm64': 'n'}>
+CONFIG_USB_NET_INT51X1                          policy<{'arm64': 'n'}>
+CONFIG_USB_NET_KALMIA                           policy<{'arm64': 'n'}>
+CONFIG_USB_NET_MCS7830                          policy<{'arm64': 'n'}>
+CONFIG_USB_NET_NET1080                          policy<{'arm64': 'y'}>
+CONFIG_USB_NET_PLUSB                            policy<{'arm64': 'n'}>
+CONFIG_USB_NET_QMI_WWAN                         policy<{'arm64': 'n'}>
+CONFIG_USB_NET_RNDIS_HOST                       policy<{'arm64': 'n'}>
+CONFIG_USB_NET_RNDIS_WLAN                       policy<{'arm64': 'n'}>
+CONFIG_USB_NET_SMSC75XX                         policy<{'arm64': 'n'}>
+CONFIG_USB_NET_SMSC95XX                         policy<{'arm64': 'n'}>
+CONFIG_USB_NET_SR9700                           policy<{'arm64': 'n'}>
+CONFIG_USB_NET_SR9800                           policy<{'arm64': 'n'}>
+CONFIG_USB_NET_ZAURUS                           policy<{'arm64': 'y'}>
+CONFIG_USB_OHCI_HCD_PCI                         policy<{'arm64': '-'}>
+CONFIG_USB_OHCI_HCD_PLATFORM                    policy<{'arm64': '-'}>
+CONFIG_USB_OTG_FSM                              policy<{'arm64': 'y'}>
+CONFIG_USB_OXU210HP_HCD                         policy<{'arm64': 'n'}>
+CONFIG_USB_PEGASUS                              policy<{'arm64': 'n'}>
+CONFIG_USB_PRINTER                              policy<{'arm64': 'n'}>
+CONFIG_USB_PULSE8_CEC                           policy<{'arm64': '-'}>
+CONFIG_USB_PWC                                  policy<{'arm64': 'n'}>
+CONFIG_USB_PWC_DEBUG                            policy<{'arm64': '-'}>
+CONFIG_USB_PWC_INPUT_EVDEV                      policy<{'arm64': '-'}>
+CONFIG_USB_PXA27X                               policy<{'arm64': 'n'}>
+CONFIG_USB_R8A66597                             policy<{'arm64': 'n'}>
+CONFIG_USB_R8A66597_HCD                         policy<{'arm64': 'n'}>
+CONFIG_USB_RAINSHADOW_CEC                       policy<{'arm64': '-'}>
+CONFIG_USB_RAREMONO                             policy<{'arm64': '-'}>
+CONFIG_USB_RENESAS_USB3                         policy<{'arm64': '-'}>
+CONFIG_USB_RENESAS_USBHS                        policy<{'arm64': '-'}>
+CONFIG_USB_RENESAS_USBHS_HCD                    policy<{'arm64': '-'}>
+CONFIG_USB_RENESAS_USBHS_UDC                    policy<{'arm64': '-'}>
+CONFIG_USB_ROLE_SWITCH                          policy<{'arm64': 'n'}>
+CONFIG_USB_RTL8150                              policy<{'arm64': 'n'}>
+CONFIG_USB_RTL8152                              policy<{'arm64': 'n'}>
+CONFIG_USB_S2255                                policy<{'arm64': 'n'}>
+CONFIG_USB_SERIAL                               policy<{'arm64': 'n'}>
+CONFIG_USB_SERIAL_AIRCABLE                      policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_ARK3116                       policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_BELKIN                        policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_CH341                         policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_CP210X                        policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_CYBERJACK                     policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_CYPRESS_M8                    policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT               policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_EDGEPORT                      policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_EDGEPORT_TI                   policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_EMPEG                         policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_F81232                        policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_F8153X                        policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_FTDI_SIO                      policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_GARMIN                        policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_GENERIC                       policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_IPAQ                          policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_IPW                           policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_IR                            policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_IUU                           policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_KEYSPAN                       policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_KEYSPAN_PDA                   policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_KLSI                          policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_KOBIL_SCT                     policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_MCT_U232                      policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_METRO                         policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_MOS7715_PARPORT               policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_MOS7720                       policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_MOS7840                       policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_MXUPORT                       policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_NAVMAN                        policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_OMNINET                       policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_OPTICON                       policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_OPTION                        policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_OTI6858                       policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_PL2303                        policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_QCAUX                         policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_QT2                           policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_QUALCOMM                      policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_SAFE                          policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_SAFE_PADDED                   policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_SIERRAWIRELESS                policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_SIMPLE                        policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_SPCP8X5                       policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_SSU100                        policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_SYMBOL                        policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_TI                            policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_UPD78F0730                    policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_VISOR                         policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_WHITEHEAT                     policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_WISHBONE                      policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_WWAN                          policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_XIRCOM                        policy<{'arm64': '-'}>
+CONFIG_USB_SERIAL_XSENS_MT                      policy<{'arm64': '-'}>
+CONFIG_USB_SEVSEG                               policy<{'arm64': 'n'}>
+CONFIG_USB_SI470X                               policy<{'arm64': '-'}>
+CONFIG_USB_SI4713                               policy<{'arm64': '-'}>
+CONFIG_USB_SIERRA_NET                           policy<{'arm64': 'n'}>
+CONFIG_USB_SISUSBVGA                            policy<{'arm64': '-'}>
+CONFIG_USB_SL811_HCD                            policy<{'arm64': 'n'}>
+CONFIG_USB_SL811_HCD_ISO                        policy<{'arm64': '-'}>
+CONFIG_USB_SNP_CORE                             policy<{'arm64': '-'}>
+CONFIG_USB_SNP_UDC_PLAT                         policy<{'arm64': 'n'}>
+CONFIG_USB_SPEEDTOUCH                           policy<{'arm64': '-'}>
+CONFIG_USB_STKWEBCAM                            policy<{'arm64': 'n'}>
+CONFIG_USB_STORAGE                              policy<{'arm64': 'y'}>
+CONFIG_USB_STORAGE_ALAUDA                       policy<{'arm64': 'n'}>
+CONFIG_USB_STORAGE_CYPRESS_ATACB                policy<{'arm64': 'n'}>
+CONFIG_USB_STORAGE_DATAFAB                      policy<{'arm64': 'n'}>
+CONFIG_USB_STORAGE_ENE_UB6250                   policy<{'arm64': 'n'}>
+CONFIG_USB_STORAGE_FREECOM                      policy<{'arm64': 'n'}>
+CONFIG_USB_STORAGE_ISD200                       policy<{'arm64': 'n'}>
+CONFIG_USB_STORAGE_JUMPSHOT                     policy<{'arm64': 'n'}>
+CONFIG_USB_STORAGE_KARMA                        policy<{'arm64': 'n'}>
+CONFIG_USB_STORAGE_ONETOUCH                     policy<{'arm64': 'n'}>
+CONFIG_USB_STORAGE_REALTEK                      policy<{'arm64': 'n'}>
+CONFIG_USB_STORAGE_SDDR09                       policy<{'arm64': 'n'}>
+CONFIG_USB_STORAGE_SDDR55                       policy<{'arm64': 'n'}>
+CONFIG_USB_STORAGE_USBAT                        policy<{'arm64': 'n'}>
+CONFIG_USB_STV06XX                              policy<{'arm64': 'n'}>
+CONFIG_USB_TEST                                 policy<{'arm64': 'n'}>
+CONFIG_USB_TMC                                  policy<{'arm64': 'n'}>
+CONFIG_USB_TRANCEVIBRATOR                       policy<{'arm64': 'n'}>
+CONFIG_USB_U132_HCD                             policy<{'arm64': '-'}>
+CONFIG_USB_UAS                                  policy<{'arm64': 'y'}>
+CONFIG_USB_UEAGLEATM                            policy<{'arm64': '-'}>
+CONFIG_USB_ULPI                                 policy<{'arm64': 'n'}>
+CONFIG_USB_ULPI_BUS                             policy<{'arm64': 'n'}>
+CONFIG_USB_ULPI_VIEWPORT                        policy<{'arm64': '-'}>
+CONFIG_USB_USB5744                              policy<{'arm64': 'm'}>
+CONFIG_USB_USBNET                               policy<{'arm64': 'y'}>
+CONFIG_USB_USS720                               policy<{'arm64': '-'}>
+CONFIG_USB_U_AUDIO                              policy<{'arm64': '-'}>
+CONFIG_USB_U_ETHER                              policy<{'arm64': 'y'}>
+CONFIG_USB_U_SERIAL                             policy<{'arm64': '-'}>
+CONFIG_USB_VIDEO_CLASS                          policy<{'arm64': 'y'}>
+CONFIG_USB_VL600                                policy<{'arm64': 'n'}>
+CONFIG_USB_WDM                                  policy<{'arm64': 'n'}>
+CONFIG_USB_WHCI_HCD                             policy<{'arm64': '-'}>
+CONFIG_USB_WUSB                                 policy<{'arm64': '-'}>
+CONFIG_USB_WUSB_CBAF                            policy<{'arm64': 'n'}>
+CONFIG_USB_WUSB_CBAF_DEBUG                      policy<{'arm64': '-'}>
+CONFIG_USB_XHCI_HISTB                           policy<{'arm64': '-'}>
+CONFIG_USB_XHCI_MTK                             policy<{'arm64': '-'}>
+CONFIG_USB_XHCI_MVEBU                           policy<{'arm64': '-'}>
+CONFIG_USB_XHCI_PLATFORM                        policy<{'arm64': 'y'}>
+CONFIG_USB_XHCI_RCAR                            policy<{'arm64': '-'}>
+CONFIG_USB_XUSBATM                              policy<{'arm64': '-'}>
+CONFIG_USB_YUREX                                policy<{'arm64': 'n'}>
+CONFIG_USB_ZD1201                               policy<{'arm64': 'n'}>
+CONFIG_USB_ZERO                                 policy<{'arm64': 'n'}>
+CONFIG_USB_ZR364XX                              policy<{'arm64': 'n'}>
+CONFIG_USELIB                                   policy<{'arm64': 'n'}>
+CONFIG_USERFAULTFD                              policy<{'arm64': 'n'}>
+CONFIG_USERIO                                   policy<{'arm64': 'n'}>
+CONFIG_USE_PERCPU_NUMA_NODE_ID                  policy<{'arm64': '-'}>
+CONFIG_UWB                                      policy<{'arm64': 'n'}>
+CONFIG_UWB_HWA                                  policy<{'arm64': '-'}>
+CONFIG_UWB_I1480U                               policy<{'arm64': '-'}>
+CONFIG_UWB_WHCI                                 policy<{'arm64': '-'}>
+CONFIG_U_SERIAL_CONSOLE                         policy<{'arm64': '-'}>
+CONFIG_V4L2_FLASH_LED_CLASS                     policy<{'arm64': '-'}>
+CONFIG_V4L2_FWNODE                              policy<{'arm64': 'y'}>
+CONFIG_V4L2_MEM2MEM_DEV                         policy<{'arm64': 'y'}>
+CONFIG_V4L_MEM2MEM_DRIVERS                      policy<{'arm64': 'n'}>
+CONFIG_V4L_TEST_DRIVERS                         policy<{'arm64': 'n'}>
+CONFIG_VALIDATE_FS_PARSER                       policy<{'arm64': 'n'}>
+CONFIG_VCNL4000                                 policy<{'arm64': 'n'}>
+CONFIG_VCNL4035                                 policy<{'arm64': 'n'}>
+CONFIG_VEML6070                                 policy<{'arm64': 'n'}>
+CONFIG_VERSAL_SYSMON                            policy<{'arm64': 'y'}>
+CONFIG_VERSION_SIGNATURE                        policy<{'arm64': '"Ubuntu 5.4.0-1000.1-zynqmp 5.4.55"'}>
+CONFIG_VETH                                     policy<{'arm64': 'y'}>
+CONFIG_VEXPRESS_CONFIG                          policy<{'arm64': 'n'}>
+CONFIG_VEXPRESS_SYSCFG                          policy<{'arm64': '-'}>
+CONFIG_VF610_ADC                                policy<{'arm64': 'n'}>
+CONFIG_VF610_DAC                                policy<{'arm64': 'n'}>
+CONFIG_VFIO_AMBA                                policy<{'arm64': '-'}>
+CONFIG_VFIO_IOMMU_TYPE1                         policy<{'arm64': '-'}>
+CONFIG_VFIO_MDEV                                policy<{'arm64': '-'}>
+CONFIG_VFIO_MDEV_DEVICE                         policy<{'arm64': '-'}>
+CONFIG_VFIO_NOIOMMU                             policy<{'arm64': '-'}>
+CONFIG_VFIO_PCI_INTX                            policy<{'arm64': '-'}>
+CONFIG_VFIO_PCI_MMAP                            policy<{'arm64': '-'}>
+CONFIG_VFIO_PLATFORM                            policy<{'arm64': '-'}>
+CONFIG_VFIO_PLATFORM_AMDXGBE_RESET              policy<{'arm64': '-'}>
+CONFIG_VFIO_PLATFORM_BCMFLEXRM_RESET            policy<{'arm64': '-'}>
+CONFIG_VFIO_PLATFORM_CALXEDAXGMAC_RESET         policy<{'arm64': '-'}>
+CONFIG_VFIO_VIRQFD                              policy<{'arm64': '-'}>
+CONFIG_VGASTATE                                 policy<{'arm64': '-'}>
+CONFIG_VGA_ARB                                  policy<{'arm64': 'n'}>
+CONFIG_VGA_ARB_MAX_GPUS                         policy<{'arm64': '-'}>
+CONFIG_VHOST                                    policy<{'arm64': '-'}>
+CONFIG_VHOST_CROSS_ENDIAN_LEGACY                policy<{'arm64': '-'}>
+CONFIG_VHOST_NET                                policy<{'arm64': '-'}>
+CONFIG_VHOST_RING                               policy<{'arm64': '-'}>
+CONFIG_VHOST_SCSI                               policy<{'arm64': '-'}>
+CONFIG_VHOST_VSOCK                              policy<{'arm64': '-'}>
+CONFIG_VIA_RHINE                                policy<{'arm64': 'n'}>
+CONFIG_VIA_RHINE_MMIO                           policy<{'arm64': '-'}>
+CONFIG_VIA_VELOCITY                             policy<{'arm64': 'n'}>
+CONFIG_VIDEOBUF2_CORE                           policy<{'arm64': 'y'}>
+CONFIG_VIDEOBUF2_DMA_CONTIG                     policy<{'arm64': 'y'}>
+CONFIG_VIDEOBUF2_DMA_SG                         policy<{'arm64': '-'}>
+CONFIG_VIDEOBUF2_DVB                            policy<{'arm64': '-'}>
+CONFIG_VIDEOBUF2_MEMOPS                         policy<{'arm64': 'y'}>
+CONFIG_VIDEOBUF2_V4L2                           policy<{'arm64': 'y'}>
+CONFIG_VIDEOBUF2_VMALLOC                        policy<{'arm64': 'y'}>
+CONFIG_VIDEOBUF_DMA_SG                          policy<{'arm64': '-'}>
+CONFIG_VIDEOBUF_GEN                             policy<{'arm64': '-'}>
+CONFIG_VIDEOBUF_VMALLOC                         policy<{'arm64': '-'}>
+CONFIG_VIDEO_AD5820                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_AD9389B                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_ADP1653                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_ADV7170                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_ADV7175                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_ADV7180                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_ADV7183                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_ADV7343                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_ADV7393                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_ADV748X                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_ADV7511                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_ADV7604                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_ADV7604_CEC                        policy<{'arm64': '-'}>
+CONFIG_VIDEO_ADV7842                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_ADV7842_CEC                        policy<{'arm64': '-'}>
+CONFIG_VIDEO_AK7375                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_AK881X                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_ALLEGRO_DVT                        policy<{'arm64': '-'}>
+CONFIG_VIDEO_AP1302                             policy<{'arm64': 'm'}>
+CONFIG_VIDEO_APTINA_PLL                         policy<{'arm64': '-'}>
+CONFIG_VIDEO_ASPEED                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_AU0828                             policy<{'arm64': '-'}>
+CONFIG_VIDEO_AU0828_RC                          policy<{'arm64': '-'}>
+CONFIG_VIDEO_AU0828_V4L2                        policy<{'arm64': '-'}>
+CONFIG_VIDEO_BCM2835                            policy<{'arm64': '-'}>
+CONFIG_VIDEO_BT819                              policy<{'arm64': 'n'}>
+CONFIG_VIDEO_BT848                              policy<{'arm64': '-'}>
+CONFIG_VIDEO_BT856                              policy<{'arm64': 'n'}>
+CONFIG_VIDEO_BT866                              policy<{'arm64': 'n'}>
+CONFIG_VIDEO_CADENCE                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_CADENCE_CSI2RX                     policy<{'arm64': '-'}>
+CONFIG_VIDEO_CADENCE_CSI2TX                     policy<{'arm64': '-'}>
+CONFIG_VIDEO_CAFE_CCIC                          policy<{'arm64': 'n'}>
+CONFIG_VIDEO_CODA                               policy<{'arm64': '-'}>
+CONFIG_VIDEO_CPIA2                              policy<{'arm64': 'n'}>
+CONFIG_VIDEO_CROS_EC_CEC                        policy<{'arm64': '-'}>
+CONFIG_VIDEO_CS3308                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_CS5345                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_CS53L32A                           policy<{'arm64': 'n'}>
+CONFIG_VIDEO_CX18                               policy<{'arm64': '-'}>
+CONFIG_VIDEO_CX18_ALSA                          policy<{'arm64': '-'}>
+CONFIG_VIDEO_CX231XX                            policy<{'arm64': '-'}>
+CONFIG_VIDEO_CX231XX_ALSA                       policy<{'arm64': '-'}>
+CONFIG_VIDEO_CX231XX_DVB                        policy<{'arm64': '-'}>
+CONFIG_VIDEO_CX231XX_RC                         policy<{'arm64': '-'}>
+CONFIG_VIDEO_CX2341X                            policy<{'arm64': '-'}>
+CONFIG_VIDEO_CX23885                            policy<{'arm64': '-'}>
+CONFIG_VIDEO_CX25821                            policy<{'arm64': '-'}>
+CONFIG_VIDEO_CX25821_ALSA                       policy<{'arm64': '-'}>
+CONFIG_VIDEO_CX25840                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_CX88                               policy<{'arm64': '-'}>
+CONFIG_VIDEO_CX88_ALSA                          policy<{'arm64': '-'}>
+CONFIG_VIDEO_CX88_BLACKBIRD                     policy<{'arm64': '-'}>
+CONFIG_VIDEO_CX88_DVB                           policy<{'arm64': '-'}>
+CONFIG_VIDEO_CX88_ENABLE_VP3054                 policy<{'arm64': '-'}>
+CONFIG_VIDEO_CX88_MPEG                          policy<{'arm64': '-'}>
+CONFIG_VIDEO_CX88_VP3054                        policy<{'arm64': '-'}>
+CONFIG_VIDEO_DEV                                policy<{'arm64': 'y'}>
+CONFIG_VIDEO_DT3155                             policy<{'arm64': '-'}>
+CONFIG_VIDEO_DW9714                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_DW9807_VCM                         policy<{'arm64': 'n'}>
+CONFIG_VIDEO_EM28XX                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_EM28XX_ALSA                        policy<{'arm64': '-'}>
+CONFIG_VIDEO_EM28XX_DVB                         policy<{'arm64': '-'}>
+CONFIG_VIDEO_EM28XX_RC                          policy<{'arm64': '-'}>
+CONFIG_VIDEO_EM28XX_V4L2                        policy<{'arm64': '-'}>
+CONFIG_VIDEO_ET8EK8                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_FB_IVTV                            policy<{'arm64': '-'}>
+CONFIG_VIDEO_GO7007                             policy<{'arm64': '-'}>
+CONFIG_VIDEO_GO7007_LOADER                      policy<{'arm64': '-'}>
+CONFIG_VIDEO_GO7007_USB                         policy<{'arm64': '-'}>
+CONFIG_VIDEO_GO7007_USB_S2250_BOARD             policy<{'arm64': '-'}>
+CONFIG_VIDEO_GS1662                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_HDPVR                              policy<{'arm64': '-'}>
+CONFIG_VIDEO_HEXIUM_GEMINI                      policy<{'arm64': '-'}>
+CONFIG_VIDEO_HEXIUM_ORION                       policy<{'arm64': '-'}>
+CONFIG_VIDEO_I2C                                policy<{'arm64': 'n'}>
+CONFIG_VIDEO_IMX214                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_IMX258                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_IMX319                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_IMX355                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_IMX_PXP                            policy<{'arm64': '-'}>
+CONFIG_VIDEO_IR_I2C                             policy<{'arm64': '-'}>
+CONFIG_VIDEO_IVTV                               policy<{'arm64': '-'}>
+CONFIG_VIDEO_IVTV_ALSA                          policy<{'arm64': '-'}>
+CONFIG_VIDEO_IVTV_DEPRECATED_IOCTLS             policy<{'arm64': '-'}>
+CONFIG_VIDEO_KS0127                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_LM3560                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_LM3646                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_M52790                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_M5MOLS                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_MEDIATEK_VPU                       policy<{'arm64': '-'}>
+CONFIG_VIDEO_MEM2MEM_DEINTERLACE                policy<{'arm64': '-'}>
+CONFIG_VIDEO_MESON_AO_CEC                       policy<{'arm64': '-'}>
+CONFIG_VIDEO_MESON_G12A_AO_CEC                  policy<{'arm64': '-'}>
+CONFIG_VIDEO_MESON_VDEC                         policy<{'arm64': '-'}>
+CONFIG_VIDEO_ML86V7667                          policy<{'arm64': 'n'}>
+CONFIG_VIDEO_MSP3400                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_MT9M001                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_MT9M032                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_MT9M111                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_MT9P031                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_MT9T001                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_MT9T112                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_MT9V011                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_MT9V032                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_MT9V111                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_MUX                                policy<{'arm64': 'n'}>
+CONFIG_VIDEO_MXB                                policy<{'arm64': '-'}>
+CONFIG_VIDEO_NOON010PC30                        policy<{'arm64': 'n'}>
+CONFIG_VIDEO_OV13858                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_OV2640                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_OV2659                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_OV2680                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_OV2685                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_OV5640                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_OV5645                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_OV5647                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_OV5670                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_OV5675                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_OV5695                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_OV6650                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_OV7251                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_OV7640                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_OV7670                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_OV772X                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_OV7740                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_OV8856                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_OV9640                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_OV9650                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_PCI_SKELETON                       policy<{'arm64': '-'}>
+CONFIG_VIDEO_PVRUSB2                            policy<{'arm64': '-'}>
+CONFIG_VIDEO_PVRUSB2_DEBUGIFC                   policy<{'arm64': '-'}>
+CONFIG_VIDEO_PVRUSB2_DVB                        policy<{'arm64': '-'}>
+CONFIG_VIDEO_PVRUSB2_SYSFS                      policy<{'arm64': '-'}>
+CONFIG_VIDEO_QCOM_CAMSS                         policy<{'arm64': '-'}>
+CONFIG_VIDEO_QCOM_VENUS                         policy<{'arm64': '-'}>
+CONFIG_VIDEO_RCAR_CSI2                          policy<{'arm64': '-'}>
+CONFIG_VIDEO_RCAR_DRIF                          policy<{'arm64': '-'}>
+CONFIG_VIDEO_RCAR_VIN                           policy<{'arm64': '-'}>
+CONFIG_VIDEO_RENESAS_FCP                        policy<{'arm64': '-'}>
+CONFIG_VIDEO_RENESAS_FDP1                       policy<{'arm64': '-'}>
+CONFIG_VIDEO_RENESAS_JPU                        policy<{'arm64': '-'}>
+CONFIG_VIDEO_RENESAS_VSP1                       policy<{'arm64': '-'}>
+CONFIG_VIDEO_RJ54N1                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_ROCKCHIP_RGA                       policy<{'arm64': '-'}>
+CONFIG_VIDEO_S5C73M3                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_S5K4ECGX                           policy<{'arm64': 'n'}>
+CONFIG_VIDEO_S5K5BAF                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_S5K6A3                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_S5K6AA                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_SAA6588                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_SAA6752HS                          policy<{'arm64': 'n'}>
+CONFIG_VIDEO_SAA7110                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_SAA711X                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_SAA7127                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_SAA7134                            policy<{'arm64': '-'}>
+CONFIG_VIDEO_SAA7134_ALSA                       policy<{'arm64': '-'}>
+CONFIG_VIDEO_SAA7134_DVB                        policy<{'arm64': '-'}>
+CONFIG_VIDEO_SAA7134_GO7007                     policy<{'arm64': '-'}>
+CONFIG_VIDEO_SAA7134_RC                         policy<{'arm64': '-'}>
+CONFIG_VIDEO_SAA7146                            policy<{'arm64': '-'}>
+CONFIG_VIDEO_SAA7146_VV                         policy<{'arm64': '-'}>
+CONFIG_VIDEO_SAA7164                            policy<{'arm64': '-'}>
+CONFIG_VIDEO_SAA717X                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_SAA7185                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_SH_VEU                             policy<{'arm64': '-'}>
+CONFIG_VIDEO_SMIAPP                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_SMIAPP_PLL                         policy<{'arm64': '-'}>
+CONFIG_VIDEO_SOLO6X10                           policy<{'arm64': '-'}>
+CONFIG_VIDEO_SONY_BTF_MPX                       policy<{'arm64': 'n'}>
+CONFIG_VIDEO_SR030PC30                          policy<{'arm64': 'n'}>
+CONFIG_VIDEO_STK1160                            policy<{'arm64': '-'}>
+CONFIG_VIDEO_STK1160_COMMON                     policy<{'arm64': '-'}>
+CONFIG_VIDEO_ST_MIPID02                         policy<{'arm64': 'n'}>
+CONFIG_VIDEO_SUN4I_CSI                          policy<{'arm64': '-'}>
+CONFIG_VIDEO_SUN6I_CSI                          policy<{'arm64': '-'}>
+CONFIG_VIDEO_SUNXI                              policy<{'arm64': '-'}>
+CONFIG_VIDEO_TC358743                           policy<{'arm64': 'n'}>
+CONFIG_VIDEO_TC358743_CEC                       policy<{'arm64': '-'}>
+CONFIG_VIDEO_TDA1997X                           policy<{'arm64': 'n'}>
+CONFIG_VIDEO_TDA7432                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_TDA9840                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_TEA6415C                           policy<{'arm64': 'n'}>
+CONFIG_VIDEO_TEA6420                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_THS7303                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_THS8200                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_TLV320AIC23B                       policy<{'arm64': 'n'}>
+CONFIG_VIDEO_TM6000                             policy<{'arm64': '-'}>
+CONFIG_VIDEO_TM6000_ALSA                        policy<{'arm64': '-'}>
+CONFIG_VIDEO_TM6000_DVB                         policy<{'arm64': '-'}>
+CONFIG_VIDEO_TUNER                              policy<{'arm64': '-'}>
+CONFIG_VIDEO_TVAUDIO                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_TVEEPROM                           policy<{'arm64': '-'}>
+CONFIG_VIDEO_TVP514X                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_TVP5150                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_TVP7002                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_TW2804                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_TW5864                             policy<{'arm64': '-'}>
+CONFIG_VIDEO_TW68                               policy<{'arm64': '-'}>
+CONFIG_VIDEO_TW686X                             policy<{'arm64': '-'}>
+CONFIG_VIDEO_TW9903                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_TW9906                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_TW9910                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_UDA1342                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_UPD64031A                          policy<{'arm64': 'n'}>
+CONFIG_VIDEO_UPD64083                           policy<{'arm64': 'n'}>
+CONFIG_VIDEO_USBTV                              policy<{'arm64': 'n'}>
+CONFIG_VIDEO_USBVISION                          policy<{'arm64': '-'}>
+CONFIG_VIDEO_V4L2                               policy<{'arm64': 'y'}>
+CONFIG_VIDEO_V4L2_TPG                           policy<{'arm64': '-'}>
+CONFIG_VIDEO_VICODEC                            policy<{'arm64': '-'}>
+CONFIG_VIDEO_VIM2M                              policy<{'arm64': '-'}>
+CONFIG_VIDEO_VIVID                              policy<{'arm64': '-'}>
+CONFIG_VIDEO_VIVID_CEC                          policy<{'arm64': '-'}>
+CONFIG_VIDEO_VIVID_MAX_DEVS                     policy<{'arm64': '-'}>
+CONFIG_VIDEO_VP27SMPX                           policy<{'arm64': 'n'}>
+CONFIG_VIDEO_VPX3220                            policy<{'arm64': 'n'}>
+CONFIG_VIDEO_VS6624                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_WM8739                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_WM8775                             policy<{'arm64': 'n'}>
+CONFIG_VIDEO_XILINX                             policy<{'arm64': 'y'}>
+CONFIG_VIDEO_XILINX_AXI4S_BROADCASTER           policy<{'arm64': 'y'}>
+CONFIG_VIDEO_XILINX_AXI4S_SWITCH                policy<{'arm64': 'y'}>
+CONFIG_VIDEO_XILINX_CFA                         policy<{'arm64': 'y'}>
+CONFIG_VIDEO_XILINX_CRESAMPLE                   policy<{'arm64': 'y'}>
+CONFIG_VIDEO_XILINX_CSI2RXSS                    policy<{'arm64': 'y'}>
+CONFIG_VIDEO_XILINX_DEMOSAIC                    policy<{'arm64': 'y'}>
+CONFIG_VIDEO_XILINX_DPRXSS                      policy<{'arm64': 'y'}>
+CONFIG_VIDEO_XILINX_GAMMA                       policy<{'arm64': 'y'}>
+CONFIG_VIDEO_XILINX_HLS                         policy<{'arm64': 'y'}>
+CONFIG_VIDEO_XILINX_M2M                         policy<{'arm64': 'y'}>
+CONFIG_VIDEO_XILINX_MULTISCALER                 policy<{'arm64': 'y'}>
+CONFIG_VIDEO_XILINX_REMAPPER                    policy<{'arm64': 'y'}>
+CONFIG_VIDEO_XILINX_RGB2YUV                     policy<{'arm64': 'y'}>
+CONFIG_VIDEO_XILINX_SCALER                      policy<{'arm64': 'y'}>
+CONFIG_VIDEO_XILINX_SCD                         policy<{'arm64': 'y'}>
+CONFIG_VIDEO_XILINX_SDIRXSS                     policy<{'arm64': 'y'}>
+CONFIG_VIDEO_XILINX_SWITCH                      policy<{'arm64': 'y'}>
+CONFIG_VIDEO_XILINX_TPG                         policy<{'arm64': 'y'}>
+CONFIG_VIDEO_XILINX_VPSS_CSC                    policy<{'arm64': 'y'}>
+CONFIG_VIDEO_XILINX_VPSS_SCALER                 policy<{'arm64': 'y'}>
+CONFIG_VIDEO_XILINX_VTC                         policy<{'arm64': 'y'}>
+CONFIG_VIPERBOARD_ADC                           policy<{'arm64': '-'}>
+CONFIG_VIRTIO_BALLOON                           policy<{'arm64': 'n'}>
+CONFIG_VIRTIO_BLK_SCSI                          policy<{'arm64': '-'}>
+CONFIG_VIRTIO_CONSOLE                           policy<{'arm64': 'n'}>
+CONFIG_VIRTIO_FS                                policy<{'arm64': 'n'}>
+CONFIG_VIRTIO_INPUT                             policy<{'arm64': 'n'}>
+CONFIG_VIRTIO_IOMMU                             policy<{'arm64': 'n'}>
+CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES              policy<{'arm64': '-'}>
+CONFIG_VIRTIO_PCI                               policy<{'arm64': 'n'}>
+CONFIG_VIRTIO_PCI_LEGACY                        policy<{'arm64': '-'}>
+CONFIG_VIRTIO_PMEM                              policy<{'arm64': '-'}>
+CONFIG_VIRTIO_VSOCKETS                          policy<{'arm64': '-'}>
+CONFIG_VIRTIO_VSOCKETS_COMMON                   policy<{'arm64': '-'}>
+CONFIG_VIRTUALIZATION                           policy<{'arm64': 'n'}>
+CONFIG_VIRT_DRIVERS                             policy<{'arm64': 'n'}>
+CONFIG_VIRT_WIFI                                policy<{'arm64': 'n'}>
+CONFIG_VITESSE_PHY                              policy<{'arm64': 'y'}>
+CONFIG_VL53L0X_I2C                              policy<{'arm64': 'n'}>
+CONFIG_VL6180                                   policy<{'arm64': 'n'}>
+CONFIG_VLAN_8021Q_GVRP                          policy<{'arm64': 'n'}>
+CONFIG_VLAN_8021Q_MVRP                          policy<{'arm64': 'n'}>
+CONFIG_VME_BUS                                  policy<{'arm64': 'n'}>
+CONFIG_VME_FAKE                                 policy<{'arm64': '-'}>
+CONFIG_VME_TSI148                               policy<{'arm64': '-'}>
+CONFIG_VME_USER                                 policy<{'arm64': '-'}>
+CONFIG_VMIVME_7805                              policy<{'arm64': '-'}>
+CONFIG_VMXNET3                                  policy<{'arm64': 'n'}>
+CONFIG_VORTEX                                   policy<{'arm64': 'n'}>
+CONFIG_VSOCKETS                                 policy<{'arm64': 'n'}>
+CONFIG_VSOCKETS_DIAG                            policy<{'arm64': '-'}>
+CONFIG_VSOCKMON                                 policy<{'arm64': '-'}>
+CONFIG_VT6655                                   policy<{'arm64': 'n'}>
+CONFIG_VT6656                                   policy<{'arm64': 'n'}>
+CONFIG_VXFS_FS                                  policy<{'arm64': 'n'}>
+CONFIG_VXGE                                     policy<{'arm64': 'n'}>
+CONFIG_VXGE_DEBUG_TRACE_ALL                     policy<{'arm64': '-'}>
+CONFIG_VZ89X                                    policy<{'arm64': 'n'}>
+CONFIG_W1                                       policy<{'arm64': 'n'}>
+CONFIG_W1_CON                                   policy<{'arm64': '-'}>
+CONFIG_W1_MASTER_DS1WM                          policy<{'arm64': '-'}>
+CONFIG_W1_MASTER_DS2482                         policy<{'arm64': '-'}>
+CONFIG_W1_MASTER_DS2490                         policy<{'arm64': '-'}>
+CONFIG_W1_MASTER_GPIO                           policy<{'arm64': '-'}>
+CONFIG_W1_MASTER_MATROX                         policy<{'arm64': '-'}>
+CONFIG_W1_MASTER_MXC                            policy<{'arm64': '-'}>
+CONFIG_W1_MASTER_SGI                            policy<{'arm64': '-'}>
+CONFIG_W1_SLAVE_DS2405                          policy<{'arm64': '-'}>
+CONFIG_W1_SLAVE_DS2406                          policy<{'arm64': '-'}>
+CONFIG_W1_SLAVE_DS2408                          policy<{'arm64': '-'}>
+CONFIG_W1_SLAVE_DS2408_READBACK                 policy<{'arm64': '-'}>
+CONFIG_W1_SLAVE_DS2413                          policy<{'arm64': '-'}>
+CONFIG_W1_SLAVE_DS2423                          policy<{'arm64': '-'}>
+CONFIG_W1_SLAVE_DS2431                          policy<{'arm64': '-'}>
+CONFIG_W1_SLAVE_DS2433                          policy<{'arm64': '-'}>
+CONFIG_W1_SLAVE_DS2433_CRC                      policy<{'arm64': '-'}>
+CONFIG_W1_SLAVE_DS2438                          policy<{'arm64': '-'}>
+CONFIG_W1_SLAVE_DS250X                          policy<{'arm64': '-'}>
+CONFIG_W1_SLAVE_DS2780                          policy<{'arm64': '-'}>
+CONFIG_W1_SLAVE_DS2781                          policy<{'arm64': '-'}>
+CONFIG_W1_SLAVE_DS2805                          policy<{'arm64': '-'}>
+CONFIG_W1_SLAVE_DS28E04                         policy<{'arm64': '-'}>
+CONFIG_W1_SLAVE_DS28E17                         policy<{'arm64': '-'}>
+CONFIG_W1_SLAVE_SMEM                            policy<{'arm64': '-'}>
+CONFIG_W1_SLAVE_THERM                           policy<{'arm64': '-'}>
+CONFIG_WAN                                      policy<{'arm64': 'n'}>
+CONFIG_WANXL                                    policy<{'arm64': '-'}>
+CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP     policy<{'arm64': '-'}>
+CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC    policy<{'arm64': '-'}>
+CONFIG_WATCHDOG_PRETIMEOUT_GOV                  policy<{'arm64': 'n'}>
+CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP             policy<{'arm64': '-'}>
+CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC            policy<{'arm64': '-'}>
+CONFIG_WATCHDOG_PRETIMEOUT_GOV_SEL              policy<{'arm64': '-'}>
+CONFIG_WATCHDOG_SYSFS                           policy<{'arm64': 'n'}>
+CONFIG_WCN36XX                                  policy<{'arm64': 'n'}>
+CONFIG_WCN36XX_DEBUGFS                          policy<{'arm64': '-'}>
+CONFIG_WCN36XX_SNAPDRAGON_HACKS                 policy<{'arm64': '-'}>
+CONFIG_WDAT_WDT                                 policy<{'arm64': '-'}>
+CONFIG_WDTPCI                                   policy<{'arm64': 'n'}>
+CONFIG_WEXT_PRIV                                policy<{'arm64': '-'}>
+CONFIG_WEXT_SPY                                 policy<{'arm64': '-'}>
+CONFIG_WIL6210                                  policy<{'arm64': 'n'}>
+CONFIG_WIL6210_DEBUGFS                          policy<{'arm64': '-'}>
+CONFIG_WIL6210_ISR_COR                          policy<{'arm64': '-'}>
+CONFIG_WIL6210_TRACING                          policy<{'arm64': '-'}>
+CONFIG_WILC1000                                 policy<{'arm64': '-'}>
+CONFIG_WILC1000_HW_OOB_INTR                     policy<{'arm64': '-'}>
+CONFIG_WILC1000_SDIO                            policy<{'arm64': 'n'}>
+CONFIG_WILC1000_SPI                             policy<{'arm64': 'n'}>
+CONFIG_WIMAX                                    policy<{'arm64': 'n'}>
+CONFIG_WIMAX_DEBUG_LEVEL                        policy<{'arm64': '-'}>
+CONFIG_WIMAX_I2400M                             policy<{'arm64': '-'}>
+CONFIG_WIMAX_I2400M_DEBUG_LEVEL                 policy<{'arm64': '-'}>
+CONFIG_WIMAX_I2400M_USB                         policy<{'arm64': '-'}>
+CONFIG_WINBOND_840                              policy<{'arm64': '-'}>
+CONFIG_WIRELESS_EXT                             policy<{'arm64': '-'}>
+CONFIG_WIZNET_BUS_ANY                           policy<{'arm64': '-'}>
+CONFIG_WIZNET_BUS_DIRECT                        policy<{'arm64': '-'}>
+CONFIG_WIZNET_BUS_INDIRECT                      policy<{'arm64': '-'}>
+CONFIG_WIZNET_W5100                             policy<{'arm64': 'n'}>
+CONFIG_WIZNET_W5100_SPI                         policy<{'arm64': '-'}>
+CONFIG_WIZNET_W5300                             policy<{'arm64': 'n'}>
+CONFIG_WL1251                                   policy<{'arm64': 'n'}>
+CONFIG_WL1251_SDIO                              policy<{'arm64': '-'}>
+CONFIG_WL1251_SPI                               policy<{'arm64': '-'}>
+CONFIG_WL12XX                                   policy<{'arm64': 'n'}>
+CONFIG_WL18XX                                   policy<{'arm64': 'y'}>
+CONFIG_WLCORE                                   policy<{'arm64': 'y'}>
+CONFIG_WLCORE_SDIO                              policy<{'arm64': 'y'}>
+CONFIG_WLCORE_SPI                               policy<{'arm64': 'y'}>
+CONFIG_WM831X_BACKUP                            policy<{'arm64': '-'}>
+CONFIG_WM831X_POWER                             policy<{'arm64': '-'}>
+CONFIG_WM831X_WATCHDOG                          policy<{'arm64': '-'}>
+CONFIG_WM8350_POWER                             policy<{'arm64': '-'}>
+CONFIG_WM8350_WATCHDOG                          policy<{'arm64': '-'}>
+CONFIG_WQ_POWER_EFFICIENT_DEFAULT               policy<{'arm64': 'n'}>
+CONFIG_X25                                      policy<{'arm64': 'n'}>
+CONFIG_X25_ASY                                  policy<{'arm64': '-'}>
+CONFIG_XDP_SOCKETS                              policy<{'arm64': 'n'}>
+CONFIG_XDP_SOCKETS_DIAG                         policy<{'arm64': '-'}>
+CONFIG_XENFS                                    policy<{'arm64': 'y'}>
+CONFIG_XEN_BALLOON_MEMORY_HOTPLUG               policy<{'arm64': 'n'}>
+CONFIG_XEN_DEV_EVTCHN                           policy<{'arm64': 'y'}>
+CONFIG_XEN_FBDEV_FRONTEND                       policy<{'arm64': 'y'}>
+CONFIG_XEN_FRONT_PGDIR_SHBUF                    policy<{'arm64': '-'}>
+CONFIG_XEN_GNTDEV_DMABUF                        policy<{'arm64': '-'}>
+CONFIG_XEN_GRANT_DMA_ALLOC                      policy<{'arm64': 'n'}>
+CONFIG_XEN_PRIVCMD                              policy<{'arm64': 'y'}>
+CONFIG_XEN_PVCALLS_FRONTEND                     policy<{'arm64': 'n'}>
+CONFIG_XEN_SCSI_BACKEND                         policy<{'arm64': '-'}>
+CONFIG_XFRM_ALGO                                policy<{'arm64': 'y'}>
+CONFIG_XFRM_INTERFACE                           policy<{'arm64': 'n'}>
+CONFIG_XFRM_IPCOMP                              policy<{'arm64': 'y'}>
+CONFIG_XFRM_MIGRATE                             policy<{'arm64': 'y'}>
+CONFIG_XFRM_OFFLOAD                             policy<{'arm64': '-'}>
+CONFIG_XFRM_STATISTICS                          policy<{'arm64': 'n'}>
+CONFIG_XFRM_USER                                policy<{'arm64': 'y'}>
+CONFIG_XFS_DEBUG                                policy<{'arm64': '-'}>
+CONFIG_XFS_FS                                   policy<{'arm64': 'n'}>
+CONFIG_XFS_ONLINE_SCRUB                         policy<{'arm64': '-'}>
+CONFIG_XFS_POSIX_ACL                            policy<{'arm64': '-'}>
+CONFIG_XFS_QUOTA                                policy<{'arm64': '-'}>
+CONFIG_XFS_RT                                   policy<{'arm64': '-'}>
+CONFIG_XFS_WARN                                 policy<{'arm64': '-'}>
+CONFIG_XGENE_DMA                                policy<{'arm64': '-'}>
+CONFIG_XGENE_PMU                                policy<{'arm64': '-'}>
+CONFIG_XGENE_SLIMPRO_MBOX                       policy<{'arm64': '-'}>
+CONFIG_XILINX_AFI_FPGA                          policy<{'arm64': 'y'}>
+CONFIG_XILINX_AIE                               policy<{'arm64': 'y'}>
+CONFIG_XILINX_AMS                               policy<{'arm64': 'y'}>
+CONFIG_XILINX_APF                               policy<{'arm64': 'y'}>
+CONFIG_XILINX_AXI_EMAC                          policy<{'arm64': 'y'}>
+CONFIG_XILINX_AXI_EMAC_HWTSTAMP                 policy<{'arm64': 'n'}>
+CONFIG_XILINX_DMA                               policy<{'arm64': 'y'}>
+CONFIG_XILINX_DMATEST                           policy<{'arm64': 'n'}>
+CONFIG_XILINX_DMA_APF                           policy<{'arm64': 'y'}>
+CONFIG_XILINX_DMA_ENGINES                       policy<{'arm64': 'y'}>
+CONFIG_XILINX_DPDMA                             policy<{'arm64': 'y'}>
+CONFIG_XILINX_DPDMA_DEBUG_FS                    policy<{'arm64': 'n'}>
+CONFIG_XILINX_EMACLITE                          policy<{'arm64': 'y'}>
+CONFIG_XILINX_FCLK                              policy<{'arm64': 'y'}>
+CONFIG_XILINX_FLEX_PM                           policy<{'arm64': 'y'}>
+CONFIG_XILINX_FRMBUF                            policy<{'arm64': 'y'}>
+CONFIG_XILINX_GMII2RGMII                        policy<{'arm64': 'y'}>
+CONFIG_XILINX_INTC                              policy<{'arm64': 'y'}>
+CONFIG_XILINX_JESD204B                          policy<{'arm64': 'y'}>
+CONFIG_XILINX_JESD204B_PHY                      policy<{'arm64': 'y'}>
+CONFIG_XILINX_PHY                               policy<{'arm64': 'y'}>
+CONFIG_XILINX_PR_DECOUPLER                      policy<{'arm64': 'y'}>
+CONFIG_XILINX_PS_PCIE_DMA                       policy<{'arm64': 'y'}>
+CONFIG_XILINX_PS_PCIE_DMA_TEST                  policy<{'arm64': 'n'}>
+CONFIG_XILINX_SDFEC                             policy<{'arm64': 'y'}>
+CONFIG_XILINX_TRAFGEN                           policy<{'arm64': 'y'}>
+CONFIG_XILINX_TSN                               policy<{'arm64': 'n'}>
+CONFIG_XILINX_VDMATEST                          policy<{'arm64': 'n'}>
+CONFIG_XILINX_WATCHDOG                          policy<{'arm64': 'y'}>
+CONFIG_XILINX_XADC                              policy<{'arm64': 'y'}>
+CONFIG_XILINX_ZYNQMP_DMA                        policy<{'arm64': 'y'}>
+CONFIG_XILLYBUS                                 policy<{'arm64': 'n'}>
+CONFIG_XILLYBUS_OF                              policy<{'arm64': '-'}>
+CONFIG_XILLYBUS_PCIE                            policy<{'arm64': '-'}>
+CONFIG_XIL_AXIS_FIFO                            policy<{'arm64': 'n'}>
+CONFIG_XLNX_SYNC                                policy<{'arm64': 'y'}>
+CONFIG_XLNX_TSMUX                               policy<{'arm64': 'n'}>
+CONFIG_XOR_BLOCKS                               policy<{'arm64': 'y'}>
+CONFIG_XROE_FRAMER                              policy<{'arm64': 'n'}>
+CONFIG_XROE_TRAFFIC_GEN                         policy<{'arm64': 'n'}>
+CONFIG_XZ_DEC_TEST                              policy<{'arm64': 'n'}>
+CONFIG_YAM                                      policy<{'arm64': '-'}>
+CONFIG_YELLOWFIN                                policy<{'arm64': 'n'}>
+CONFIG_YENTA                                    policy<{'arm64': '-'}>
+CONFIG_YENTA_ENE_TUNE                           policy<{'arm64': '-'}>
+CONFIG_YENTA_O2                                 policy<{'arm64': '-'}>
+CONFIG_YENTA_RICOH                              policy<{'arm64': '-'}>
+CONFIG_YENTA_TI                                 policy<{'arm64': '-'}>
+CONFIG_YENTA_TOSHIBA                            policy<{'arm64': '-'}>
+CONFIG_Z3FOLD                                   policy<{'arm64': '-'}>
+CONFIG_ZBUD                                     policy<{'arm64': 'n'}>
+CONFIG_ZD1211RW                                 policy<{'arm64': 'n'}>
+CONFIG_ZD1211RW_DEBUG                           policy<{'arm64': '-'}>
+CONFIG_ZEROPLUS_FF                              policy<{'arm64': '-'}>
+CONFIG_ZIIRAVE_WATCHDOG                         policy<{'arm64': 'n'}>
+CONFIG_ZOPT2201                                 policy<{'arm64': 'n'}>
+CONFIG_ZPA2326                                  policy<{'arm64': 'n'}>
+CONFIG_ZPA2326_I2C                              policy<{'arm64': '-'}>
+CONFIG_ZPA2326_SPI                              policy<{'arm64': '-'}>
+CONFIG_ZPOOL                                    policy<{'arm64': 'n'}>
+CONFIG_ZRAM                                     policy<{'arm64': '-'}>
+CONFIG_ZRAM_MEMORY_TRACKING                     policy<{'arm64': '-'}>
+CONFIG_ZRAM_WRITEBACK                           policy<{'arm64': '-'}>
+CONFIG_ZSMALLOC                                 policy<{'arm64': 'n'}>
+CONFIG_ZSMALLOC_STAT                            policy<{'arm64': '-'}>
+CONFIG_ZSTD_COMPRESS                            policy<{'arm64': 'y'}>
+CONFIG_ZSWAP                                    policy<{'arm64': '-'}>
+CONFIG_ZX_TDM                                   policy<{'arm64': 'n'}>
+CONFIG_ZYNQMP_FIRMWARE_DEBUG                    policy<{'arm64': 'y'}>
+CONFIG_ZYNQMP_FIRMWARE_SECURE                   policy<{'arm64': 'n'}>
+CONFIG_ZYNQMP_R5_REMOTEPROC                     policy<{'arm64': 'm'}>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/control.d/flavour-control.stub
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/control.d/flavour-control.stub
@@ -0,0 +1,131 @@
+# Items that get replaced:
+# FLAVOUR
+# DESC
+# ARCH
+# SUPPORTED
+# TARGET
+# BOOTLOADER
+# =PROVIDES=
+#
+# Items marked with =FOO= are optional
+#
+# This file describes the template for packages that are created for each flavour
+# in debian/control.d/vars.*
+#
+# This file gets edited in a couple of places. See the debian/control.stub rule in
+# debian/rules. PGGVER, ABINUM, and SRCPKGNAME are all converted in the
+# process of creating debian/control.
+#
+# The flavour specific strings (ARCH, DESC, etc) are converted using values from the various
+# flavour files in debian/control.d/vars.*
+#
+# XXX: Leave the blank line before the first package!!
+
+Package: linux-image=SIGN-ME-PKG=-PKGVER-ABINUM-FLAVOUR
+Build-Profiles: <!stage1>
+Architecture: ARCH
+Section: kernel
+Priority: optional
+Provides: linux-image, fuse-module, aufs-dkms, =PROVIDES=${linux:rprovides}
+Depends: ${misc:Depends}, ${shlibs:Depends}, kmod, linux-base (>= 4.5ubuntu1~16.04.1), linux-modules-PKGVER-ABINUM-FLAVOUR
+Recommends: initramfs-tools | linux-initramfs-tool
+Breaks: flash-kernel (<< 3.90ubuntu2) [arm64 armhf], s390-tools (<< 2.3.0-0ubuntu3) [s390x]
+Conflicts: linux-image=SIGN-PEER-PKG=-PKGVER-ABINUM-FLAVOUR
+Suggests: fdutils, linux-doc | SRCPKGNAME-source-PKGVER, SRCPKGNAME-tools, linux-headers-PKGVER-ABINUM-FLAVOUR
+Description: Linux kernel image for version PKGVER on DESC
+ This package contains the=SIGN-ME-TXT= Linux kernel image for version PKGVER on
+ DESC.
+ .
+ Supports SUPPORTED processors.
+ .
+ TARGET
+ .
+ You likely do not want to install this package directly. Instead, install
+ the linux-FLAVOUR meta-package, which will ensure that upgrades work
+ correctly, and that supporting packages are also installed.
+
+Package: linux-modules-PKGVER-ABINUM-FLAVOUR
+Build-Profiles: <!stage1>
+Architecture: ARCH
+Section: kernel
+Priority: optional
+Depends: ${misc:Depends}, ${shlibs:Depends}
+Built-Using: ${linux:BuiltUsing}
+Description: Linux kernel extra modules for version PKGVER on DESC
+ Contains the corresponding System.map file, the modules built by the
+ packager, and scripts that try to ensure that the system is not left in an
+ unbootable state after an update.
+ .
+ Supports SUPPORTED processors.
+ .
+ TARGET
+ .
+ You likely do not want to install this package directly. Instead, install
+ the linux-FLAVOUR meta-package, which will ensure that upgrades work
+ correctly, and that supporting packages are also installed.
+
+Package: linux-modules-extra-PKGVER-ABINUM-FLAVOUR
+Build-Profiles: <!stage1>
+Architecture: ARCH
+Section: kernel
+Priority: optional
+Depends: ${misc:Depends}, ${shlibs:Depends}, linux-image-PKGVER-ABINUM-FLAVOUR | linux-image-unsigned-PKGVER-ABINUM-FLAVOUR, crda | wireless-crda
+Description: Linux kernel extra modules for version PKGVER on DESC
+ This package contains the Linux kernel extra modules for version PKGVER on
+ DESC.
+ .
+ Also includes the corresponding System.map file, the modules built by the
+ packager, and scripts that try to ensure that the system is not left in an
+ unbootable state after an update.
+ .
+ Supports SUPPORTED processors.
+ .
+ TARGET
+ .
+ You likely do not want to install this package directly. Instead, install
+ the linux-FLAVOUR meta-package, which will ensure that upgrades work
+ correctly, and that supporting packages are also installed.
+
+Package: linux-headers-PKGVER-ABINUM-FLAVOUR
+Build-Profiles: <!stage1>
+Architecture: ARCH
+Section: devel
+Priority: optional
+Depends: ${misc:Depends}, SRCPKGNAME-headers-PKGVER-ABINUM, ${shlibs:Depends}
+Provides: linux-headers, linux-headers-3.0
+Description: Linux kernel headers for version PKGVER on DESC
+ This package provides kernel header files for version PKGVER on
+ DESC.
+ .
+ This is for sites that want the latest kernel headers.  Please read
+ /usr/share/doc/linux-headers-PKGVER-ABINUM/debian.README.gz for details.
+
+Package: linux-image=SIGN-ME-PKG=-PKGVER-ABINUM-FLAVOUR-dbgsym
+Build-Profiles: <!stage1>
+Architecture: ARCH
+Section: devel
+Priority: optional
+Depends: ${misc:Depends}
+Provides: linux-debug
+Description: Linux kernel debug image for version PKGVER on DESC
+ This package provides the=SIGN-ME-TXT= kernel debug image for version PKGVER on
+ DESC.
+ .
+ This is for sites that wish to debug the kernel.
+ .
+ The kernel image contained in this package is NOT meant to boot from. It
+ is uncompressed, and unstripped. This package also includes the
+ unstripped modules.
+
+Package: linux-tools-PKGVER-ABINUM-FLAVOUR
+Build-Profiles: <!stage1>
+Architecture: ARCH
+Section: devel
+Priority: optional
+Depends: ${misc:Depends}, SRCPKGNAME-tools-PKGVER-ABINUM
+Description: Linux kernel version specific tools for version PKGVER-ABINUM
+ This package provides the architecture dependant parts for kernel
+ version locked tools (such as perf and x86_energy_perf_policy) for
+ version PKGVER-ABINUM on
+ =HUMAN=.
+
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/control.d/vars.xilinx-zynqmp
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/control.d/vars.xilinx-zynqmp
@@ -0,0 +1,6 @@
+arch="arm64"
+supported="Xilinx ZYNQ Ultrascale+"
+target="Geared toward desktop and server systems."
+desc="=HUMAN= SMP"
+bootloader="grub-pc [amd64] | grub-efi-amd64 [amd64] | grub-efi-ia32 [amd64] | grub [amd64] | lilo [amd64] | flash-kernel [armhf arm64] | grub-ieee1275 [ppc64el]"
+provides="kvm-api-4, redhat-cluster-modules, ivtv-modules, virtualbox-guest-modules [amd64]"
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/control.stub.in
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/control.stub.in
@@ -0,0 +1,81 @@
+Source: SRCPKGNAME
+Section: devel
+Priority: optional
+Maintainer: Ubuntu Kernel Team <kernel-team@lists.ubuntu.com>
+Standards-Version: 3.9.4.0
+Build-Depends:
+ debhelper (>= 9),
+ dh-systemd,
+ cpio,
+ kernel-wedge,
+ kmod <!stage1>,
+ makedumpfile [amd64] <!stage1>,
+ libcap-dev <!stage1>,
+ libelf-dev <!stage1>,
+ libnewt-dev <!stage1>,
+ libiberty-dev <!stage1>,
+ default-jdk-headless <!stage1>,
+ java-common <!stage1>,
+ rsync <!stage1>,
+ libdw-dev <!stage1>,
+ libpci-dev <!stage1>,
+ pkg-config <!stage1>,
+ flex <!stage1>,
+ bison <!stage1>,
+ libunwind8-dev [amd64 arm64 armhf ppc64el] <!stage1>,
+ liblzma-dev <!stage1>,
+ openssl <!stage1>,
+ libssl-dev <!stage1>,
+ libaudit-dev <!stage1>,
+ bc <!stage1>,
+ gawk <!stage1>,
+ libudev-dev <!stage1>,
+ autoconf <!stage1>,
+ automake <!stage1>,
+ libtool <!stage1>,
+ uuid-dev <!stage1>,
+ libnuma-dev [amd64 arm64 ppc64el s390x] <!stage1>,
+ dkms <!stage1>,
+ curl <!stage1>,
+ lz4 [amd64 s390x] <!stage1>,
+Build-Depends-Indep:
+ xmlto <!stage1>,
+ docbook-utils <!stage1>,
+ ghostscript <!stage1>,
+ fig2dev <!stage1>,
+ bzip2 <!stage1>,
+ sharutils <!stage1>,
+ asciidoc <!stage1>,
+ python3-sphinx <!stage1>,
+ python3-sphinx-rtd-theme <!stage1>,
+ fontconfig <!stage1>,
+ python3-docutils <!stage1>,
+Vcs-Git: git://git.launchpad.net/~canonical-hwe-kernel/limerick/+git/linux-zynqmp
+XS-Testsuite: autopkgtest
+#XS-Testsuite-Depends: gcc-4.7 binutils
+
+Package: SRCPKGNAME-headers-PKGVER-ABINUM
+Build-Profiles: <!stage1>
+Architecture: all
+Multi-Arch: foreign
+Section: devel
+Priority: optional
+Depends: ${misc:Depends}, coreutils
+Description: Header files related to Linux kernel version PKGVER
+ This package provides kernel header files for version PKGVER, for sites
+ that want the latest kernel headers. Please read
+ /usr/share/doc/SRCPKGNAME-headers-PKGVER-ABINUM/debian.README.gz for details
+
+Package: SRCPKGNAME-tools-PKGVER-ABINUM
+Build-Profiles: <!stage1>
+Architecture: arm64
+Section: devel
+Priority: optional
+Depends: ${misc:Depends}, ${shlibs:Depends}, linux-tools-common
+Description: Linux kernel version specific tools for version PKGVER-ABINUM
+ This package provides the architecture dependant parts for kernel
+ version locked tools (such as perf and x86_energy_perf_policy) for
+ version PKGVER-ABINUM on
+ =HUMAN=.
+ You probably want to install linux-tools-PKGVER-ABINUM-<flavour>.
+
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/copyright
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/copyright
@@ -0,0 +1,29 @@
+This is the Ubuntu prepackaged version of the Linux kernel.
+Linux was written by Linus Torvalds <Linus.Torvalds@cs.Helsinki.FI>
+and others.
+
+This package was put together by the Ubuntu Kernel Team, from
+sources retrieved from upstream linux git.
+The sources may be found at most Linux ftp sites, including 
+ftp://ftp.kernel.org/pub/linux/kernel/
+
+This package is currently maintained by the
+Ubuntu Kernel Team <ubuntu-kernel@lists.ubuntu.com>
+
+Linux is copyrighted by Linus Torvalds and others.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+On Ubuntu Linux systems, the complete text of the GNU General
+Public License v2 can be found in `/usr/share/common-licenses/GPL-2'.
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/firmware/README.txt
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/firmware/README.txt
@@ -0,0 +1,4 @@
+#
+# Place the names of udeb modules into this directory that require
+# runtime firmware.
+#
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/firmware/arm64/README.txt
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/firmware/arm64/README.txt
@@ -0,0 +1,4 @@
+#
+# Place the names of udeb modules into this directory that require
+# runtime firmware.
+#
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/firmware/arm64/nic-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/firmware/arm64/nic-modules
@@ -0,0 +1 @@
+#include <nic-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/firmware/arm64/scsi-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/firmware/arm64/scsi-modules
@@ -0,0 +1 @@
+#include <scsi-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/firmware/nic-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/firmware/nic-modules
@@ -0,0 +1,14 @@
+e100/d101m_ucode.bin ?
+e100/d101s_ucode.bin ?
+e100/d102e_ucode.bin ?
+bnx2/bnx2-mips-09-6.2.1b.fw ?
+bnx2/bnx2-rv2p-06-6.0.15.fw ?
+bnx2/bnx2-mips-06-6.2.3.fw ?
+bnx2/bnx2-rv2p-09-6.0.17.fw ?
+bnx2/bnx2-rv2p-09ax-6.0.17.fw ?
+bnx2x/bnx2x-e1h-7.12.30.0.fw ?
+bnx2x/bnx2x-e1-7.12.30.0.fw ?
+bnx2x/bnx2x-e2-7.12.30.0.fw ?
+tigon/tg3_tso5.bin ?
+tigon/tg3_tso.bin ?
+tigon/tg3.bin ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/firmware/scsi-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/firmware/scsi-modules
@@ -0,0 +1,3 @@
+qlogic/1040.bin ?
+qlogic/12160.bin ?
+qlogic/1280.bin ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/kernel-versions
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/kernel-versions
@@ -0,0 +1,16 @@
+# arch	version		flavour		installedname			suffix	bdep
+amd64	-		generic		-				-	-
+
+i386	-		generic		-				-	-
+
+armhf	-		generic		-				-	-
+armhf	-		generic-lpae	-				-	-
+
+arm64	-		generic		-				-	-
+
+ppc64el	-		generic		-				-	-
+
+s390x	-		generic		-				-	-
+
+# Ports
+# arch	version		flavour		installedname			suffix	bdep
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/arm64/block-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/arm64/block-modules
@@ -0,0 +1 @@
+#include <block-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/arm64/crypto-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/arm64/crypto-modules
@@ -0,0 +1 @@
+#include <crypto-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/arm64/fat-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/arm64/fat-modules
@@ -0,0 +1 @@
+#include <fat-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/arm64/fs-core-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/arm64/fs-core-modules
@@ -0,0 +1 @@
+#include <fs-core-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/arm64/fs-secondary-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/arm64/fs-secondary-modules
@@ -0,0 +1 @@
+#include <fs-secondary-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/arm64/input-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/arm64/input-modules
@@ -0,0 +1 @@
+#include <input-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/arm64/ipmi-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/arm64/ipmi-modules
@@ -0,0 +1 @@
+#include <ipmi-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/arm64/kernel-image
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/arm64/kernel-image
@@ -0,0 +1 @@
+#include <kernel-image>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/arm64/md-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/arm64/md-modules
@@ -0,0 +1 @@
+#include <md-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/arm64/message-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/arm64/message-modules
@@ -0,0 +1 @@
+#include <message-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/arm64/mouse-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/arm64/mouse-modules
@@ -0,0 +1 @@
+#include <mouse-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/arm64/multipath-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/arm64/multipath-modules
@@ -0,0 +1 @@
+#include <multipath-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/arm64/nfs-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/arm64/nfs-modules
@@ -0,0 +1 @@
+#include <nfs-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/arm64/nic-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/arm64/nic-modules
@@ -0,0 +1 @@
+#include <nic-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/arm64/nic-shared-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/arm64/nic-shared-modules
@@ -0,0 +1 @@
+#include <nic-shared-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/arm64/nic-usb-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/arm64/nic-usb-modules
@@ -0,0 +1 @@
+#include <nic-usb-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/arm64/parport-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/arm64/parport-modules
@@ -0,0 +1 @@
+#include <parport-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/arm64/plip-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/arm64/plip-modules
@@ -0,0 +1 @@
+#include <plip-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/arm64/ppp-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/arm64/ppp-modules
@@ -0,0 +1 @@
+#include <ppp-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/arm64/sata-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/arm64/sata-modules
@@ -0,0 +1 @@
+#include <sata-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/arm64/scsi-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/arm64/scsi-modules
@@ -0,0 +1,2 @@
+#include <scsi-modules>
+ipr ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/arm64/speakup-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/arm64/speakup-modules
@@ -0,0 +1 @@
+#include <speakup-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/arm64/storage-core-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/arm64/storage-core-modules
@@ -0,0 +1 @@
+#include <storage-core-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/arm64/usb-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/arm64/usb-modules
@@ -0,0 +1 @@
+#include <usb-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/arm64/virtio-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/arm64/virtio-modules
@@ -0,0 +1 @@
+#include <virtio-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/arm64/vlan-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/arm64/vlan-modules
@@ -0,0 +1 @@
+#include <vlan-modules>
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/block-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/block-modules
@@ -0,0 +1,43 @@
+aoe ?
+aten ?
+bcm2835 ?
+bpck ?
+bpck6 ?
+cciss ?
+comm ?
+cpqarray ?
+DAC960 ?
+dstr ?
+epat ?
+epia ?
+fit2 ?
+fit3 ?
+friq ?
+frpw ?
+hpsa ?
+hio ?
+kbic ?
+ktti ?
+nbd ?
+nvme ?
+on20 ?
+on26 ?
+paride ?
+pcd ?
+pd ?
+pf ?
+pg ?
+pt ?
+sdhci-tegra ?
+sx8 ?
+umem ?
+virtio_blk ?
+xen-blkfront ?
+mtip32xx ?
+mmc_block ?
+sdhci ?
+sdhci-pci ?
+sdhci-acpi ?
+tifm_sd ?
+dw_mmc ?
+dw_mmc_pltfm ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/block-modules.powerpc
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/block-modules.powerpc
@@ -0,0 +1,31 @@
+aoe ?
+aten ?
+bpck ?
+bpck6 ?
+cciss ?
+comm ?
+cpqarray ?
+DAC960 ?
+dstr ?
+epat ?
+epia ?
+fit2 ?
+fit3 ?
+friq ?
+frpw ?
+kbic ?
+ktti ?
+nbd ?
+on20 ?
+on26 ?
+paride ?
+pcd ?
+pd ?
+pf ?
+pg ?
+ps3disk ?
+ps3vram ?
+pt ?
+sx8 ?
+umem ?
+virtio_blk ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/crypto-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/crypto-modules
@@ -0,0 +1,78 @@
+aesni-intel ?
+aes-x86_64 ?
+af_alg ?
+algif_hash ?
+algif_skcipher ?
+ansi_cprng ?
+anubis ?
+arc4 ?
+async_memcpy ?
+async_pq ?
+async_raid6_recov ?
+async_tx ?
+async_xor ?
+authenc ?
+authencesn ?
+blowfish_common ?
+blowfish_generic ?
+blowfish-x86_64 ?
+camellia ?
+cast5 ?
+cast6 ?
+ccm ?
+crc32_generic ?
+crc32c_generic ?
+crc32-vx_s390 ?
+cryptd ?
+cryptoloop ?
+crypto_null ?
+crypto_user ?
+ctr ?
+cts ?
+des_generic ?
+fcrypt ?
+gcm ?
+gf128mul ?
+ghash-clmulni-intel ?
+ghash-generic ?
+khazad ?
+lrw ?
+lzo ?
+md4 ?
+michael_mic ?
+padlock-aes ?
+padlock-sha ?
+paes_s390 ?
+pcbc ?
+pcrypt ?
+pkey ?
+raid6test ?
+rmd128 ?
+rmd160 ?
+rmd256 ?
+rmd320 ?
+salsa20_generic ?
+salsa20-x86_64 ?
+seed ?
+seqiv ?
+serpent_generic ?
+serpent-sse2-x86_64 ?
+sha1-ssse3 ?
+sha512_generic ?
+tcrypt ?
+tea ?
+tgr192 ?
+twofish_common ?
+twofish_generic ?
+twofish-x86_64 ?
+twofish-x86_64-3way ?
+vmac ?
+wp512 ?
+xcbc ?
+xor ?
+xts ?
+zcrypt ?
+zcrypt_cex2a ?
+zcrypt_cex4 ?
+zcrypt_pcixcc ?
+zlib ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/dasd-extra-modules.s390x
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/dasd-extra-modules.s390x
@@ -0,0 +1 @@
+dasd_diag_mod ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/dasd-modules.s390x
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/dasd-modules.s390x
@@ -0,0 +1,3 @@
+dasd_mod ?
+dasd_fba_mod ?
+dasd_eckd_mod ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/fat-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/fat-modules
@@ -0,0 +1,7 @@
+fat ?
+vfat ?
+
+# Supporting modules ?
+nls_cp437 ?
+nls_iso8859-1 ?
+nls_utf8 ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/fb-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/fb-modules
@@ -0,0 +1,3 @@
+fbcon ?
+vesafb ?
+vga16fb ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/firewire-core-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/firewire-core-modules
@@ -0,0 +1,4 @@
+firewire-core ?
+firewire-ohci ?
+firewire-sbp2 ?
+firewire-net ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/floppy-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/floppy-modules
@@ -0,0 +1 @@
+floppy ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/fs-core-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/fs-core-modules
@@ -0,0 +1,6 @@
+ext2 ?
+ext4 ?
+jfs ?
+reiserfs ?
+xfs ?
+zfs ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/fs-secondary-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/fs-secondary-modules
@@ -0,0 +1,5 @@
+btrfs ?
+fuse ?
+ntfs ?
+hfs ?
+hfsplus ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/input-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/input-modules
@@ -0,0 +1,71 @@
+hid ?
+hid-a4tech ?
+hid-apple ?
+hid-appleir ?
+hid-aureal ?
+hid-belkin ?
+hid-bright ?
+hid-cherry ?
+hid-chicony ?
+hid-corsair ?
+hid-cp2112 ?
+hid-cypress ?
+hid-dell ?
+hid-elecom ?
+hid-elo ?
+hid-ezkey ?
+hid-generic ?
+hid-gfrm ?
+hid-gt683r ?
+hid-gyration ?
+hid-holtek-kbd ?
+hid-holtek-mouse ?
+hid-hyperv ?
+hid-kensington ?
+hid-keytouch ?
+hid-kye ?
+hid-lcpower ?
+hid-lenovo ?
+hid-logitech ?
+hid-logitech-dj ?
+hid-logitech-hidpp ?
+hid-magicmouse ?
+hid-microsoft ?
+hid-monterey ?
+hid-multitouch ?
+hid-ntrig ?
+hid-ortek ?
+hid-penmount ?
+hid-petalynx ?
+hid-picolcd ?
+hid-pl ?
+hid-plantronics ?
+hid-primax ?
+hid-rmi ?
+hid-roccat ?
+hid-roccat-arvo ?
+hid-roccat-common ?
+hid-roccat-isku ?
+hid-roccat-kone ?
+hid-roccat-koneplus ?
+hid-roccat-konepure ?
+hid-roccat-kovaplus ?
+hid-roccat-lua ?
+hid-roccat-pyra ?
+hid-roccat-ryos ?
+hid-roccat-savu ?
+hid-samsung ?
+hid-sony ?
+hid-speedlink ?
+hid-sunplus ?
+hid-thingm ?
+hid-tivo ?
+hid-topseed ?
+hid-twinhan ?
+hid-uclogic ?
+hid-waltop ?
+hid-wiimote ?
+hid-xinmo ?
+hid-zydacron ?
+uhid ?
+usbhid ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/ipmi-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/ipmi-modules
@@ -0,0 +1,5 @@
+ipmi_devintf ?
+ipmi_msghandler ?
+ipmi_poweroff ?
+ipmi_si ?
+ipmi_watchdog ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/kernel-image
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/kernel-image
@@ -0,0 +1,31 @@
+ast ?
+gpio-pca953x ?
+gpio-regulator ?
+hibmc-drm ?
+i2c-mux ?
+i2c-mux-pinctrl ?
+i2c-tegra ?
+max8907 ?
+max8907-regulator ?
+nvec ?
+nvec_kbd ?
+nvec_paz00 ?
+nvec_power ?
+nvec_ps2 ?
+palmas-regulator ?
+rtc-em3027 ?
+rtc-max8907 ?
+rtc-palmas ?
+rtc-tps6586x ?
+rtc-tps65910 ?
+tps51632-regulator ?
+tps62360-regulator ?
+tps65090-charger ?
+tps65090-regulator ?
+tps6586x-regulator ?
+tps65910-regulator ?
+host1x ?
+tegra-drm ?
+pwm_bl ?
+pwm-tegra ?
+panel-simple ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/md-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/md-modules
@@ -0,0 +1,16 @@
+dm-crypt ?
+dm-mirror ?
+dm-raid ?
+dm-snapshot ?
+dm-zero ?
+faulty ?
+linear ?
+multipath ?
+raid0 ?
+raid1 ?
+raid10 ?
+raid456 ?
+
+# Extras
+dm-raid45 ?
+dm-loop ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/message-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/message-modules
@@ -0,0 +1,9 @@
+mptbase ?
+mptctl ?
+mptfc ?
+mptlan ?
+mptsas ?
+mpt2sas ?
+mpt3sas ?
+mptscsih ?
+mptspi ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/message-modules.powerpc
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/message-modules.powerpc
@@ -0,0 +1,7 @@
+mptbase
+mptctl
+mptfc
+mptlan
+mptsas
+mptscsih
+mptspi
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/mouse-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/mouse-modules
@@ -0,0 +1,2 @@
+psmouse ?
+usbmouse ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/multipath-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/multipath-modules
@@ -0,0 +1,4 @@
+dm-multipath ?
+dm-round-robin ?
+dm-service-time ?
+dm-queue-length ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/nfs-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/nfs-modules
@@ -0,0 +1,6 @@
+nfs ?
+nfs_acl ?
+nfsv3 ?
+lockd ?
+sunrpc ?
+cifs ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/nic-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/nic-modules
@@ -0,0 +1,209 @@
+3c359 ?
+3c501 ?
+3c503 ?
+3c505 ?
+3c507 ?
+3c509 ?
+3c515 ?
+3c523 ?
+3c527 ?
+3c59x ?
+8139cp ?
+8139too ?
+82596 ?
+abyss ?
+ac3200 ?
+adm8211 ?
+airo ?
+airport ?
+alx ?
+amd8111e ?
+amd-xgbe ?
+aquantia ?
+arcnet ?
+arc-rawmode ?
+arc-rimi ?
+arlan ?
+at1700 ?
+ath5k ?
+ath9k ?
+ath9k_htc ?
+atl1 ?
+atl1c ?
+atl1e ?
+atl2 ?
+atmel ?
+atmel_pci ?
+b44 ?
+bcm87xx ?
+be2net ?
+bmac ?
+bnx2 ?
+bnx2x ?
+bnxt_en ?
+bonding ?
+brcmfmac ?
+brcmsmac ?
+broadcom ?
+xgmac ?
+cassini ?
+ccwgroup ?
+com20020 ?
+com20020-pci ?
+com90io ?
+com90xx ?
+cs89x0 ?
+ctcm ?
+cxgb4 ?
+de2104x ?
+de4x5 ?
+de600 ?
+de620 ?
+defxx ?
+depca ?
+dl2k ?
+dmfe ?
+dummy ?
+e100 ?
+e1000 ?
+e1000e ?
+e2100 ?
+eepro ?
+eepro100 ?
+eexpress ?
+enic ?
+epic100 ?
+eql ?
+es3210 ?
+eth16i ?
+ewrk3 ?
+fealnx ?
+forcedeth ?
+fsm ?
+ibmveth ?
+ibmvnic ?
+igb ?
+ps3_gelic ?
+hamachi ?
+hclge ?
+hermes ?
+hfi1 ?
+hinic ?
+hns_dsaf ?
+hns_enet_drv ?
+hns_mdio ?
+hns3 ?
+hp ?
+hp100 ?
+hp-plus ?
+i40e ?
+i40evf ?
+ibmtr ?
+ipddp ?
+ipw2100 ?
+ipw2200 ?
+iwl3945 ?
+iwl4965 ?
+iwl-legacy ?
+iwldvm ?
+iwlmvm ?
+iwlwifi ?
+ixgb ?
+ixgbe ?
+lance ?
+lanstreamer ?
+lcs ?
+lasi_82596 ?
+lne390 ?
+lp486e ?
+mace ?
+marvell ?
+mdio-thunder ?
+mlx4_core ?
+mlx4_en ?
+mlx5_core ?
+mv643xx_eth ?
+myri_sbus ?
+natsemi ?
+ne ?
+ne2 ?
+ne2k-pci ?
+ne3210 ?
+netconsole ?
+netiucv ?
+netsec ?
+netxen_nic ?
+ni5010 ?
+ni52 ?
+ni65 ?
+nicpf ?
+nicvf ?
+niu ?
+ns83820 ?
+olympic ?
+orinoco ?
+orinoco_pci ?
+orinoco_plx ?
+orinoco_tmd ?
+pcnet32 ?
+qcom-emac ?
+qede ?
+qeth ?
+qeth_l2 ?
+qeth_l3 ?
+qlcnic ?
+r815x ?
+r8169 ?
+rate_control ?
+realtek ?
+rfc1051 ?
+rfc1201 ?
+rrunner ?
+rt2400 ?
+rt2400pci ?
+rt2500 ?
+rt2500pci ?
+rt2800pci ?
+rt61pci ?
+s2io ?
+sfc ?
+shaper ?
+sis190 ?
+sis900 ?
+spidernet ?
+skfp ?
+skge ?
+sk98lin ?
+sky2 ?
+smc9194 ?
+smc-ultra ?
+smc-ultra32 ?
+starfire ?
+strip ?
+sunbmac ?
+sundance ?
+sungem ?
+sungem_phy ?
+sunhme ?
+sunlance ?
+sunqe ?
+sunvnet ?
+tg3 ?
+tlan ?
+tms380tr ?
+tmspci ?
+tulip ?
+tun ?
+typhoon ?
+uli526x ?
+via-rhine ?
+via-velocity ?
+virtio_net ?
+wavelan ?
+wd ?
+winbond-840 ?
+yellowfin ?
+znet ?
+vmxnet3 ?
+xen-netfront ?
+xgene-enet ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/nic-modules.powerpc
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/nic-modules.powerpc
@@ -0,0 +1,152 @@
+3c359 ?
+3c501 ?
+3c503 ?
+3c505 ?
+3c507 ?
+3c509 ?
+3c515 ?
+3c523 ?
+3c527 ?
+3c59x ?
+8139cp ?
+8139too ?
+82596 ?
+abyss ?
+ac3200 ?
+adm8211 ?
+airo ?
+airport ?
+amd8111e ?
+arc4 ?
+arcnet ?
+arc-rawmode ?
+arc-rimi ?
+arlan ?
+at1700 ?
+atl1 ?
+atl1e ?
+atl2 ?
+atmel ?
+atmel_pci ?
+b44 ?
+bcm43xx ?
+bcm43xx-mac80211 ?
+bmac ?
+bnx2 ?
+bnx2x ?
+bonding ?
+cassini ?
+com20020 ?
+com20020-pci ?
+com90io ?
+com90xx ?
+cs89x0 ?
+de2104x ?
+de4x5 ?
+de600 ?
+de620 ?
+defxx ?
+depca ?
+dl2k ?
+dmfe ?
+dummy ?
+e100 ?
+e1000 ?
+e1000e ?
+e2100 ?
+eepro ?
+eepro100 ?
+eexpress ?
+epic100 ?
+eql ?
+es3210 ?
+eth16i ?
+ewrk3 ?
+fealnx ?
+forcedeth ?
+igb ?
+hamachi ?
+hermes ?
+hp ?
+hp100 ?
+hp-plus ?
+ibmtr ?
+ibmveth ?
+ipddp ?
+ipw2100 ?
+ipw2200 ?
+ipw3945 ?
+ixgb ?
+lance ?
+lanstreamer ?
+lasi_82596 ?
+lne390 ?
+lp486e ?
+mace ?
+mv643xx_eth ?
+myri_sbus ?
+natsemi ?
+ne ?
+ne2 ?
+ne2k-pci ?
+ne3210 ?
+netconsole ?
+netxen_nic ?
+ni5010 ?
+ni52 ?
+ni65 ?
+niu ?
+ns83820 ?
+olympic ?
+orinoco ?
+orinoco_pci ?
+orinoco_plx ?
+orinoco_tmd ?
+pcnet32 ?
+ps3_gelic ?
+r8169 ?
+rate_control ?
+rfc1051 ?
+rfc1201 ?
+rrunner ?
+rt2400 ?
+rt2500 ?
+rt61pci ?
+s2io ?
+shaper ?
+sis190 ?
+sis900 ?
+spidernet ?
+skfp ?
+skge ?
+sk98lin ?
+sky2 ?
+smc9194 ?
+smc-ultra ?
+smc-ultra32 ?
+starfire ?
+strip ?
+sunbmac ?
+sundance ?
+sungem ?
+sungem_phy ?
+sunhme ?
+sunlance ?
+sunqe ?
+sunvnet ?
+tg3 ?
+tlan ?
+tms380tr ?
+tmspci ?
+tulip ?
+tun ?
+typhoon ?
+uli526x ?
+via-rhine ?
+via-velocity ?
+virtio_net ?
+wavelan ?
+wd ?
+winbond-840 ?
+yellowfin ?
+znet ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/nic-pcmcia-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/nic-pcmcia-modules
@@ -0,0 +1,19 @@
+3c574_cs ?
+3c589_cs ?
+airo_cs ?
+atmel_cs ?
+axnet_cs ?
+com20020_cs ?
+fmvj18x_cs ?
+ibmtr_cs ?
+netwave_cs ?
+nmclan_cs ?
+orinoco_cs ?
+pcnet_cs ?
+ray_cs ?
+smc91c92_cs ?
+wavelan_cs ?
+wl3501_cs ?
+xirc2ps_cs ?
+xircom_cb ?
+xircom_tulip_cb ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/nic-shared-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/nic-shared-modules
@@ -0,0 +1,26 @@
+# PHY
+8390 ?
+mii ?
+
+# CRC modules
+crc-ccitt ?
+crc-itu-t ?
+libcrc32c ?
+
+# mac80211 stuff
+mac80211 ?
+cfg80211 ?
+
+# rt2x00 lib (since rt2x00 is split across usb/pci/cb
+rt2x00lib ?
+rt2800lib ?
+
+# Atheros library (since drivers are split across nic-modules/nic-usb-modules)
+ath ?
+
+# Wireless 802.11 modules
+lib80211 ?
+cfg80211 ?
+lib80211_crypt_ccmp ?
+lib80211_crypt_tkip ?
+lib80211_crypt_wep ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/nic-usb-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/nic-usb-modules
@@ -0,0 +1,34 @@
+ax88179_178a ?
+catc ?
+kaweth ?
+pegasus ?
+prism2_usb ?
+rtl8150 ?
+usbnet ?
+zd1211rw ?
+zd1201 ?
+rt2500usb ?
+rt73usb ?
+rt2570 ?
+rt2800usb ?
+rt2x00usb ?
+cdc_ether ?
+asix ?
+cdc_eem ?
+cdc_ether ?
+cdc-phonet ?
+cdc_subset ?
+dm9601 ?
+gl620a ?
+hso ?
+int51x1 ?
+mcs7830 ?
+net1080 ?
+plusb ?
+rndis_host ?
+r8152 ?
+smsc95xx ?
+zaurus ?
+carl9170 ?
+smsc75xx ?
+smsc95xx ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/parport-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/parport-modules
@@ -0,0 +1,2 @@
+parport ?
+parport_pc ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/pata-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/pata-modules
@@ -0,0 +1,47 @@
+pata_ali.ko ?
+pata_amd.ko ?
+pata_artop.ko ?
+pata_atiixp.ko ?
+pata_atp867x.ko ?
+pata_cmd640.ko ?
+pata_cmd64x.ko ?
+pata_cs5520.ko ?
+pata_cs5530.ko ?
+pata_cs5535.ko ?
+pata_cs5536.ko ?
+pata_cypress.ko ?
+pata_efar.ko ?
+pata_hpt366.ko ?
+pata_hpt37x.ko ?
+pata_hpt3x2n.ko ?
+pata_hpt3x3.ko ?
+pata_isapnp.ko ?
+pata_it8213.ko ?
+pata_it821x.ko ?
+pata_jmicron.ko ?
+pata_legacy.ko ?
+pata_macio.ko ?
+pata_marvell.ko ?
+pata_mpiix.ko ?
+pata_netcell.ko ?
+pata_ninja32.ko ?
+pata_ns87410.ko ?
+pata_ns87415.ko ?
+pata_oldpiix.ko ?
+pata_optidma.ko ?
+pata_opti.ko ?
+pata_pcmcia.ko ?
+pata_pdc2027x.ko ?
+pata_pdc202xx_old.ko ?
+pata_qdi.ko ?
+pata_radisys.ko ?
+pata_rdc.ko ?
+pata_rz1000.ko ?
+pata_sc1200.ko ?
+pata_sch.ko ?
+pata_serverworks.ko ?
+pata_sil680.ko ?
+pata_sl82c105.ko ?
+pata_triflex.ko ?
+pata_via.ko ?
+pata_winbond.ko ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/pcmcia-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/pcmcia-modules
@@ -0,0 +1,8 @@
+i82092 ?
+i82365 ?
+pcmcia ?
+pcmcia_core ?
+pd6729 ?
+rsrc_nonstatic ?
+tcic ?
+yenta_socket ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/pcmcia-storage-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/pcmcia-storage-modules
@@ -0,0 +1,6 @@
+pata_pcmcia ?
+qlogic_cs ?
+fdomain_cs ?
+aha152x_cs ?
+nsp_cs ?
+sym53c500_cs ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/plip-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/plip-modules
@@ -0,0 +1 @@
+plip ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/ppp-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/ppp-modules
@@ -0,0 +1,6 @@
+ppp_async ?
+ppp_deflate ?
+ppp_mppe ?
+pppoe ?
+pppox ?
+ppp_synctty ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/sata-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/sata-modules
@@ -0,0 +1,18 @@
+sata_inic162x.ko ?
+sata_mv.ko ?
+sata_nv.ko ?
+sata_promise.ko ?
+sata_qstor.ko ?
+sata_sil24.ko ?
+sata_sil.ko ?
+sata_sis.ko ?
+sata_svw.ko ?
+sata_sx4.ko ?
+sata_uli.ko ?
+sata_via.ko ?
+sata_vsc.ko ?
+ahci_platform ?
+ahci ?
+acard-ahci ?
+libahci ?
+ahci_xgene ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/scsi-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/scsi-modules
@@ -0,0 +1,137 @@
+# SCSI
+raid_class ?
+scsi_transport_spi ?
+scsi_transport_fc ?
+scsi_transport_iscsi ?
+scsi_transport_sas ?
+sr_mod ?
+iscsi_tcp ?
+libiscsi ?
+amiga7xx ?
+a3000 ?
+a2091 ?
+gvp11 ?
+mvme147 ?
+sgiwd93 ?
+cyberstorm ?
+cyberstormII ?
+blz2060 ?
+blz1230 ?
+fastlane ?
+oktagon_esp_mod ?
+atari_scsi ?
+mac_scsi ?
+mac_esp ?
+sun3_scsi ?
+mvme16x ?
+bvme6000 ?
+sim710 ?
+advansys ?
+pm80xx ?
+psi240i ?
+BusLogic ?
+dpt_i2o ?
+u14-34f ?
+ultrastor ?
+aha152x ?
+aha1542 ?
+aha1740 ?
+aic7xxx_old ?
+ips ?
+fd_mcs ?
+fdomain ?
+fnic ?
+in2000 ?
+g_NCR5380 ?
+g_NCR5380_mmio ?
+NCR53c406a ?
+NCR_D700 ?
+NCR_Q720_mod ?
+sym53c416 ?
+qlogicfas408 ?
+qla1280 ?
+pas16 ?
+seagate ?
+seagate ?
+t128 ?
+dmx3191d ?
+dtc ?
+zalon7xx ?
+eata_pio ?
+wd7000 ?
+mca_53c9x ?
+ibmmca ?
+eata ?
+dc395x ?
+tmscsim ?
+megaraid ?
+atp870u ?
+esp ?
+gdth ?
+initio ?
+a100u2w ?
+qlogicpti ?
+ide-scsi ?
+mesh ?
+mac53c94 ?
+pluto ?
+dec_esp ?
+3w-xxxx ?
+3w-9xxx ?
+ppa ?
+imm ?
+jazz_esp ?
+sun3x_esp ?
+fcal ?
+lasi700 ?
+nsp32 ?
+hptiop ?
+stex ?
+osst ?
+sg ?
+ch ?
+scsi_debug ?
+aacraid ?
+aic7xxx ?
+aic79xx ?
+aic94xx ?
+arcmsr ?
+acornscsi_mod ?
+arxescsi ?
+cumana_1 ?
+cumana_2 ?
+ecoscsi ?
+oak ?
+powertec ?
+eesox ?
+ibmvscsi ?
+ibmvfc ?
+libsas ?
+lpfc ?
+megaraid_mm ?
+megaraid_mbox ?
+megaraid_sas ?
+qla2xxx ?
+sym53c8xx ?
+qla4xxx ?
+mvsas ?
+vmw_pvscsi ?
+ums-cypress ?
+be2iscsi ?
+3w-sas ?
+isci ?
+mlx4_ib ?
+mlx5_ib ?
+zfcp ?
+sd_mod ?
+hisi_sas_v2_hw ?
+hisi_sas_v3_hw ?
+iscsi_ibft ?
+
+# device handlers
+scsi_dh_alua ?
+scsi_dh_emc ?
+scsi_dh_rdac ?
+scsi_dh_hp_sw ?
+
+smartpqi ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/scsi-modules.powerpc
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/scsi-modules.powerpc
@@ -0,0 +1,118 @@
+# SCSI
+raid_class ?
+scsi_transport_spi ?
+scsi_transport_fc ?
+scsi_transport_iscsi ?
+scsi_transport_sas ?
+iscsi_tcp ?
+libiscsi ?
+amiga7xx ?
+a3000 ?
+a2091 ?
+gvp11 ?
+mvme147 ?
+sgiwd93 ?
+cyberstorm ?
+cyberstormII ?
+blz2060 ?
+blz1230 ?
+fastlane ?
+oktagon_esp_mod ?
+atari_scsi ?
+mac_scsi ?
+mac_esp ?
+sun3_scsi ?
+mvme16x ?
+bvme6000 ?
+sim710 ?
+advansys ?
+psi240i ?
+BusLogic ?
+dpt_i2o ?
+u14-34f ?
+ultrastor ?
+aha152x ?
+aha1542 ?
+aha1740 ?
+aic7xxx_old ?
+ips ?
+fd_mcs ?
+fdomain ?
+in2000 ?
+g_NCR5380 ?
+g_NCR5380_mmio ?
+NCR53c406a ?
+NCR_D700 ?
+NCR_Q720_mod ?
+sym53c416 ?
+qlogicfas408 ?
+qla1280 ?
+pas16 ?
+seagate ?
+seagate ?
+t128 ?
+dmx3191d ?
+dtc ?
+zalon7xx ?
+eata_pio ?
+wd7000 ?
+mca_53c9x ?
+ibmmca ?
+ibmvfc ?
+ibmvscsi ?
+eata ?
+dc395x ?
+tmscsim ?
+megaraid ?
+atp870u ?
+esp ?
+gdth ?
+initio ?
+a100u2w ?
+qlogicpti ?
+ide-scsi ?
+mesh ?
+mac53c94 ?
+pluto ?
+dec_esp ?
+3w-xxxx ?
+3w-9xxx ?
+ppa ?
+imm ?
+jazz_esp ?
+sun3x_esp ?
+fcal ?
+lasi700 ?
+nsp32 ?
+ipr ?
+hptiop ?
+stex ?
+osst ?
+sg ?
+ch ?
+scsi_debug ?
+aacraid ?
+aic7xxx ?
+aic79xx ?
+aic94xx ?
+arcmsr ?
+acornscsi_mod ?
+arxescsi ?
+cumana_1 ?
+cumana_2 ?
+ecoscsi ?
+oak ?
+powertec ?
+eesox ?
+ibmvscsic ?
+libsas ?
+lpfc ?
+megaraid_mm ?
+megaraid_mbox ?
+megaraid_sas ?
+qla2xxx ?
+sym53c8xx ?
+qla4xxx ?
+mvsas ?
+sr_mod ?
+sd_mod ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/serial-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/serial-modules
@@ -0,0 +1,4 @@
+generic_serial ?
+serial_cs ?
+synclink_cs ?
+hyperv-keyboard ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/speakup-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/speakup-modules
@@ -0,0 +1,16 @@
+speakup ?
+speakup_acntpc ?
+speakup_acntsa ?
+speakup_apollo ?
+speakup_audptr ?
+speakup_bns ?
+speakup_decext ?
+speakup_dectlk ?
+speakup_dtlk ?
+speakup_dummy ?
+speakup_keypc ?
+speakup_ltlk ?
+speakup_soft ?
+speakup_spkout ?
+speakup_txprt ?
+speakup_decpc ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/storage-core-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/storage-core-modules
@@ -0,0 +1,15 @@
+# Core stacks
+usb-storage ?
+
+# Block level
+ata_piix ?
+ata_generic ?
+
+# Loop modules
+cryptoloop ?
+
+# Needs to be here for better cdrom initrd layout
+isofs ?
+
+# Needed for NVMe disks under VMD PCIe domains
+vmd ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/storage-core-modules.powerpc
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/storage-core-modules.powerpc
@@ -0,0 +1,13 @@
+# Core stacks
+usb-storage ?
+
+# Block level
+
+# Loop modules
+cryptoloop
+
+# Needs to be here for better cdrom initrd layout
+isofs
+
+ps3stor_lib ?
+ps3rom ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/usb-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/usb-modules
@@ -0,0 +1,15 @@
+ehci-hcd ?
+isp116x-hcd ?
+isp1760 ?
+ohci-hcd ?
+r8a66597-hcd ?
+sl811_cs ?
+sl811-hcd ?
+u132-hcd ?
+uhci-hcd ?
+xhci-hcd ?
+xhci-plat-hcd ?
+ehci-tegra ?
+ehci-msm ?
+ehci-platform ?
+uas ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/virtio-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/virtio-modules
@@ -0,0 +1,11 @@
+virtio_balloon ?
+virtio_pci ?
+virtio_ring ?
+virtio-rng ?
+virtio_scsi ?
+hv_vmbus ?
+hv_utils ?
+hv_netvsc ?
+hv_mouse ?
+hv_storvsc ?
+hv_balloon ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/modules/vlan-modules
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/modules/vlan-modules
@@ -0,0 +1,3 @@
+slp ?
+garp ?
+8021q ?
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/d-i/package-list
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/d-i/package-list
@@ -0,0 +1,203 @@
+Package: kernel-image
+Provides: ext3-modules, ext4-modules, squashfs-modules
+Provides_amd64: efi-modules, ext3-modules, ext4-modules, squashfs-modules
+Provides_i386: efi-modules, ext3-modules, ext4-modules, squashfs-modules
+Provides_ppc64el: ext3-modules, ext4-modules, fat-modules, squashfs-modules
+Provides_s390x: ext3-modules, ext4-modules, ppp-modules, squashfs-modules
+Description: kernel image and system map
+
+Package: dasd-modules
+Depends: kernel-image, storage-core-modules
+Priority: standard
+Description: DASD storage support
+
+Package: dasd-extra-modules
+Depends: dasd-modules
+Priority: extra
+Description: DASD storage support -- extras
+
+Package: fat-modules
+Depends: kernel-image
+Priority: standard
+Description: FAT filesystem support
+ This includes Windows FAT and VFAT support.
+
+Package: fb-modules
+Depends: kernel-image
+Priority: standard
+Description: Framebuffer modules
+
+Package: firewire-core-modules
+Depends: kernel-image, storage-core-modules
+Priority: standard
+Description: Firewire (IEEE-1394) Support
+
+Package: floppy-modules
+Depends: kernel-image
+Priority: standard
+Description: Floppy driver support
+
+Package: fs-core-modules
+Depends: kernel-image
+Priority: standard
+Provides: ext2-modules, jfs-modules, reiserfs-modules, xfs-modules
+Description: Base filesystem modules
+ This includes jfs, reiserfs and xfs.
+
+Package: fs-secondary-modules
+Depends: kernel-image, fat-modules
+Priority: standard
+Provides: btrfs-modules, ntfs-modules, hfs-modules
+Description: Extra filesystem modules
+ This includes support for Windows NTFS and MacOS HFS/HFSPlus
+
+Package: input-modules
+Depends: kernel-image, usb-modules
+Priority: standard
+Description: Support for various input methods
+
+Package: md-modules
+Depends: kernel-image
+Priority: standard
+Provides: crypto-dm-modules
+Description: Multi-device support (raid, device-mapper, lvm)
+
+Package: nic-modules
+Depends: kernel-image, nic-shared-modules, virtio-modules
+Priority: standard
+Description: Network interface support
+
+Package: nic-pcmcia-modules
+Depends: kernel-image, nic-shared-modules, nic-modules
+Priority: standard
+Description: PCMCIA network interface support
+
+Package: nic-usb-modules
+Depends: kernel-image, nic-shared-modules, usb-modules
+Priority: standard
+Description: USB network interface support
+
+Package: nic-shared-modules
+Depends: kernel-image, crypto-modules
+Priority: standard
+Description: nic shared modules
+  This package contains modules which support nic modules
+
+Package: parport-modules
+Depends: kernel-image
+Priority: standard
+Description: Parallel port support
+
+Package: pata-modules
+Depends: kernel-image, storage-core-modules
+Priority: standard
+Description: PATA support modules
+
+Package: pcmcia-modules
+Depends: kernel-image
+Priority: standard
+Description: PCMCIA Modules
+
+Package: pcmcia-storage-modules
+Depends: kernel-image, scsi-modules
+Priority: standard
+Description: PCMCIA storage support
+
+Package: plip-modules
+Depends: kernel-image, nic-shared-modules, parport-modules
+Priority: standard
+Description: PLIP (parallel port) networking support
+
+Package: ppp-modules
+Depends: kernel-image, nic-shared-modules, serial-modules
+Priority: standard
+Description: PPP (serial port) networking support
+
+Package: sata-modules
+Depends: kernel-image, storage-core-modules
+Priority: standard
+Description: SATA storage support
+
+Package: scsi-modules
+Depends: kernel-image, storage-core-modules
+Priority: standard
+Description: SCSI storage support
+
+Package: serial-modules
+Depends: kernel-image
+Priority: standard
+Description: Serial port support
+
+Package: storage-core-modules
+Depends: kernel-image
+Priority: standard
+Provides: loop-modules
+Description: Core storage support
+ Includes core SCSI, LibATA, USB-Storage. Also includes related block
+ devices for CD, Disk and Tape medium (and IDE Floppy).
+
+Package: usb-modules
+Depends: kernel-image, storage-core-modules
+Priority: standard
+Description: Core USB support
+
+Package: nfs-modules
+Priority: standard
+Depends: kernel-image
+Description: NFS filesystem drivers
+ Includes the NFS client driver, and supporting modules.
+
+Package: block-modules
+Priority: standard
+Provides: nbd-modules
+Depends: kernel-image, storage-core-modules, parport-modules, virtio-modules
+Description: Block storage devices
+ This package contains the block storage devices, including DAC960 and
+ paraide.
+
+Package: message-modules
+Priority: standard
+Depends: kernel-image, storage-core-modules, scsi-modules
+Description: Fusion and i2o storage modules
+ This package containes the fusion and i2o storage modules.
+
+Package: crypto-modules
+Priority: extra
+Depends: kernel-image
+Description: crypto modules
+ This package contains crypto modules.
+
+Package: virtio-modules
+Priority: standard
+Depends: kernel-image
+Description: VirtIO Modules
+ Includes modules for VirtIO (virtual machine, generally kvm guests)
+
+Package: socket-modules
+Depends: kernel-image
+Priority: standard
+Description: Unix socket support
+
+Package: mouse-modules
+Depends: kernel-image, input-modules, usb-modules
+Priority: extra
+Description: Mouse support
+ This package contains mouse drivers for the Linux kernel.
+
+Package: vlan-modules
+Depends: kernel-image
+Priority: extra
+Description: vlan modules
+ This package contains vlan (8021.Q) modules.
+
+Package: ipmi-modules
+Depends: kernel-image
+Priority: standard
+Description: ipmi modules
+
+Package: multipath-modules
+Depends: kernel-image
+Priority: extra
+Description: DM-Multipath support
+  This package contains modules for device-mapper multipath support.
+
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/dkms-versions
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/dkms-versions
@@ -0,0 +1,3 @@
+zfs-linux 0.8.3-1ubuntu12.18
+virtualbox 6.1.50-dfsg-1~ubuntu1.20.04.1
+wireguard-linux-compat 1.0.20201112-1~20.04.1
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/etc/kernelconfig
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/etc/kernelconfig
@@ -0,0 +1,7 @@
+if [ "$variant" = "ports" ]; then
+	archs=""
+	family='ports'
+else
+	archs="arm64"
+	family='ubuntu'
+fi
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/etc/update.conf
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/etc/update.conf
@@ -0,0 +1,7 @@
+# WARNING: we do not create update.conf when we are not a
+# derivative. Various cranky components make use of this.
+# If we start unconditionally creating update.conf we need
+# to fix at least cranky close and cranky rebase.
+RELEASE_REPO=https://git.launchpad.net/~canonical-kernel-esm/canonical-kernel-esm/+git/linux--focal
+SOURCE_RELEASE_BRANCH=master-next
+DEBIAN_MASTER=debian.master
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/modprobe.d/common.conf
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/modprobe.d/common.conf
@@ -0,0 +1,3 @@
+# LP:1434842 -- disable OSS drivers by default to allow pulseaudio to emulate
+blacklist snd-mixer-oss
+blacklist snd-pcm-oss
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/reconstruct
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/reconstruct
@@ -0,0 +1,136 @@
+# Recreate any symlinks created since the orig.
+chmod +x 'arch/mips/pci/pcie-octeon.c'
+chmod +x 'debian/cloud-tools/hv_get_dhcp_info'
+chmod +x 'debian/cloud-tools/hv_get_dns_info'
+chmod +x 'debian/cloud-tools/hv_set_ifconfig'
+chmod +x 'debian/rules'
+chmod +x 'debian/scripts/config-check'
+chmod +x 'debian/scripts/control-create'
+chmod +x 'debian/scripts/dkms-build'
+chmod +x 'debian/scripts/dkms-build--nvidia-N'
+chmod +x 'debian/scripts/dkms-build--virtualbox-guest'
+chmod +x 'debian/scripts/dkms-build-configure--zfs'
+chmod +x 'debian/scripts/file-downloader'
+chmod +x 'debian/scripts/link-headers'
+chmod +x 'debian/scripts/misc/annotations'
+chmod +x 'debian/scripts/misc/arch-has-odm-enabled.sh'
+chmod +x 'debian/scripts/misc/final-checks'
+chmod +x 'debian/scripts/misc/find-missing-sauce.sh'
+chmod +x 'debian/scripts/misc/find-obsolete-firmware'
+chmod +x 'debian/scripts/misc/fw-to-ihex.sh'
+chmod +x 'debian/scripts/misc/gen-auto-reconstruct'
+chmod +x 'debian/scripts/misc/get-firmware'
+chmod +x 'debian/scripts/misc/git-ubuntu-log'
+chmod +x 'debian/scripts/misc/insert-changes.pl'
+chmod +x 'debian/scripts/misc/insert-mainline-changes'
+chmod +x 'debian/scripts/misc/insert-ubuntu-changes'
+chmod +x 'debian/scripts/misc/kernel-wedge-arch.pl'
+chmod +x 'debian/scripts/misc/kernelconfig'
+chmod +x 'debian/scripts/misc/migrate-annotations'
+chmod +x 'debian/scripts/misc/retag'
+chmod +x 'debian/scripts/misc/splitconfig.pl'
+chmod +x 'debian/scripts/misc/tristate.sh'
+chmod +x 'debian/scripts/misc/update-aufs.sh'
+chmod +x 'debian/scripts/module-inclusion'
+chmod +x 'debian/scripts/retpoline-extract'
+chmod +x 'debian/scripts/retpoline-extract-one'
+chmod +x 'debian/templates/extra.postinst.in'
+chmod +x 'debian/templates/extra.postrm.in'
+chmod +x 'debian/templates/headers.postinst.in'
+chmod +x 'debian/templates/image.postinst.in'
+chmod +x 'debian/templates/image.postrm.in'
+chmod +x 'debian/templates/image.preinst.in'
+chmod +x 'debian/templates/image.prerm.in'
+chmod +x 'debian/tests-build/check-aliases'
+chmod +x 'debian/tests/rebuild'
+chmod +x 'debian/tests/ubuntu-regression-suite'
+chmod +x 'samples/bpf/lwt_len_hist.sh'
+chmod +x 'samples/bpf/test_lwt_bpf.sh'
+chmod +x 'scripts/kmsg-doc'
+chmod +x 'scripts/parse-maintainers.pl'
+chmod +x 'tools/testing/selftests/net/fib_nexthop_nongw.sh'
+chmod +x 'tools/testing/selftests/netfilter/conntrack_vrf.sh'
+# Remove any files deleted from the orig.
+rm -f 'Documentation/devicetree/bindings/clock/axi-clkgen.txt'
+rm -f 'Documentation/devicetree/bindings/gpu/samsung-rotator.txt'
+rm -f 'Documentation/devicetree/bindings/phy/amlogic,meson-g12a-usb3-pcie-phy.yaml'
+rm -f 'Documentation/networking/decnet.txt'
+rm -f 'arch/alpha/include/asm/bugs.h'
+rm -f 'arch/arm64/boot/dts/xilinx/zynqmp-zc1275-revA.dts'
+rm -f 'arch/ia64/include/asm/bugs.h'
+rm -f 'arch/m68k/include/asm/bugs.h'
+rm -f 'arch/microblaze/include/asm/cputable.h'
+rm -f 'arch/microblaze/include/asm/hw_irq.h'
+rm -f 'arch/microblaze/include/asm/tlb.h'
+rm -f 'arch/microblaze/include/asm/user.h'
+rm -f 'arch/parisc/include/asm/bugs.h'
+rm -f 'arch/parisc/kernel/module.lds'
+rm -f 'arch/parisc/lib/string.S'
+rm -f 'arch/powerpc/include/asm/bugs.h'
+rm -f 'arch/powerpc/include/uapi/asm/bpf_perf_event.h'
+rm -f 'arch/sh/include/asm/bugs.h'
+rm -f 'arch/sparc/include/asm/bugs.h'
+rm -f 'arch/um/include/asm/bugs.h'
+rm -f 'arch/um/kernel/gmon_syms.c'
+rm -f 'arch/x86/events/intel/rapl.c'
+rm -f 'arch/x86/include/asm/refcount.h'
+rm -f 'arch/xtensa/include/asm/bugs.h'
+rm -f 'drivers/block/sx8.c'
+rm -f 'drivers/crypto/hisilicon/sgl.h'
+rm -f 'drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.h'
+rm -f 'drivers/iio/adc/stx104.c'
+rm -f 'drivers/input/serio/i8042-ppcio.h'
+rm -f 'drivers/net/can/dev.c'
+rm -f 'drivers/net/can/rx-offload.c'
+rm -f 'drivers/net/phy/mdio-i2c.h'
+rm -f 'drivers/net/phy/mdio-xgene.h'
+rm -f 'drivers/soc/qcom/llcc-sdm845.c'
+rm -f 'drivers/soc/qcom/llcc-slice.c'
+rm -f 'drivers/staging/clocking-wizard/Kconfig'
+rm -f 'drivers/staging/clocking-wizard/Makefile'
+rm -f 'drivers/staging/clocking-wizard/TODO'
+rm -f 'drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c'
+rm -f 'drivers/staging/clocking-wizard/dt-binding.txt'
+rm -f 'drivers/staging/mt7621-dma/mtk-hsdma.c'
+rm -f 'drivers/uio/uio.c'
+rm -f 'include/Kbuild'
+rm -f 'include/asm-generic/bugs.h'
+rm -f 'include/linux/kd.h'
+rm -f 'include/net/dn.h'
+rm -f 'include/net/dn_dev.h'
+rm -f 'include/net/dn_fib.h'
+rm -f 'include/net/dn_neigh.h'
+rm -f 'include/net/dn_nsp.h'
+rm -f 'include/net/dn_route.h'
+rm -f 'include/trace/events/random.h'
+rm -f 'include/uapi/linux/dn.h'
+rm -f 'include/uapi/linux/netfilter_decnet.h'
+rm -f 'include/uapi/rdma/nes-abi.h'
+rm -f 'kernel/elfcore.c'
+rm -f 'net/decnet/Kconfig'
+rm -f 'net/decnet/Makefile'
+rm -f 'net/decnet/README'
+rm -f 'net/decnet/af_decnet.c'
+rm -f 'net/decnet/dn_dev.c'
+rm -f 'net/decnet/dn_fib.c'
+rm -f 'net/decnet/dn_neigh.c'
+rm -f 'net/decnet/dn_nsp_in.c'
+rm -f 'net/decnet/dn_nsp_out.c'
+rm -f 'net/decnet/dn_route.c'
+rm -f 'net/decnet/dn_rules.c'
+rm -f 'net/decnet/dn_table.c'
+rm -f 'net/decnet/dn_timer.c'
+rm -f 'net/decnet/netfilter/Kconfig'
+rm -f 'net/decnet/netfilter/Makefile'
+rm -f 'net/decnet/netfilter/dn_rtmsg.c'
+rm -f 'net/decnet/sysctl_net_decnet.c'
+rm -f 'net/sched/cls_rsvp.c'
+rm -f 'net/sched/cls_rsvp.h'
+rm -f 'net/sched/cls_rsvp6.c'
+rm -f 'net/sched/cls_tcindex.c'
+rm -f 'net/sched/sch_atm.c'
+rm -f 'net/sched/sch_cbq.c'
+rm -f 'net/sched/sch_dsmark.c'
+rm -f 'net/xfrm/xfrm_interface.c'
+rm -f 'tools/build/feature/test-libpython-version.c'
+exit 0
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/rules.d/arm64.mk
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/rules.d/arm64.mk
@@ -0,0 +1,30 @@
+human_arch	= ARMv8
+build_arch	= arm64
+header_arch	= arm64
+defconfig	= defconfig
+flavours	= xilinx-zynqmp
+build_image	= Image.gz
+kernel_file	= arch/$(build_arch)/boot/Image.gz
+install_file	= vmlinuz
+no_dumpfile = true
+
+loader		= grub
+vdso		= vdso_install
+
+do_extras_package = false
+do_tools_usbip  = true
+do_tools_cpupower = true
+do_tools_perf   = true
+do_tools_perf_jvmti = true
+do_tools_bpftool = true
+do_tools_host = false
+
+do_dtbs		= true
+do_zfs		= false
+do_dkms_wireguard = false
+do_dkms_nvidia = false
+
+disable_d_i = true
+do_source_package = false
+do_common_headers_indep = false
+do_libc_dev_package = false
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/tracking-bug
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/tracking-bug
@@ -0,0 +1 @@
+2144155 s2026.02.09-1
--- linux-xilinx-zynqmp-5.4.0.orig/debian.zynqmp/variants
+++ linux-xilinx-zynqmp-5.4.0/debian.zynqmp/variants
@@ -0,0 +1,2 @@
+-5.4
+--
--- linux-xilinx-zynqmp-5.4.0.orig/debian/canonical-certs.pem
+++ linux-xilinx-zynqmp-5.4.0/debian/canonical-certs.pem
@@ -0,0 +1,371 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            47:77:26:6d:ae:6c:57:73:eb:80:e2:96:dd:26:93:ff:e9:f5:62:5d
+        Signature Algorithm: sha512WithRSAEncryption
+        Issuer: CN=Canonical Ltd. Live Patch Signing 2025 Kmod
+        Validity
+            Not Before: May 16 09:07:40 2025 GMT
+            Not After : May 16 09:07:40 2050 GMT
+        Subject: CN=Canonical Ltd. Live Patch Signing 2025 Kmod
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (4096 bit)
+                Modulus:
+                    00:b8:a9:03:47:2e:7b:c6:86:16:f4:b7:a8:4d:3b:
+                    05:f6:c4:75:35:e9:22:8a:4e:40:06:89:15:7f:ad:
+                    99:bb:e6:90:93:61:c8:16:cf:2e:00:1b:81:36:fd:
+                    cc:31:7b:97:79:8d:5e:d2:4d:d3:2f:ab:35:2d:74:
+                    48:98:b3:d9:75:f9:bb:e1:f2:3f:6b:6d:dc:e4:bb:
+                    ee:f5:aa:f7:8a:8c:7a:a8:0b:df:b1:f8:d6:04:13:
+                    27:e9:1a:aa:c2:4d:d2:35:3a:bc:06:d7:83:7f:e8:
+                    c4:1c:63:8b:3a:ff:0e:0b:89:6e:4f:5f:ea:ad:78:
+                    df:37:ab:f9:55:1d:fb:6e:29:a4:22:43:d1:9b:12:
+                    1e:b2:84:23:1b:d2:38:91:b8:a8:6c:1c:59:3c:ff:
+                    4c:a9:18:ce:d0:7f:1d:ef:04:cf:8a:e8:29:b2:4b:
+                    68:0d:92:32:bc:9c:5d:8f:0a:d1:dd:4d:25:ba:3a:
+                    8c:6a:48:5b:1e:9c:01:10:99:c1:a7:34:ee:68:ec:
+                    a1:d3:26:be:45:c8:b4:97:ac:8a:aa:7e:13:a6:e5:
+                    43:f1:1b:3f:a1:80:0a:d2:a9:e7:f2:77:ca:e1:f5:
+                    29:36:df:75:8a:7e:02:d6:17:aa:46:12:b9:51:f0:
+                    6b:ca:22:f8:05:de:d6:02:47:76:0c:88:f1:c6:90:
+                    44:99:58:71:c7:62:1e:2b:94:c5:2b:8e:dc:ca:7b:
+                    a7:bd:cd:38:8f:4e:73:6d:b0:9b:4e:7c:12:1f:5c:
+                    c5:62:d6:82:c6:d2:78:09:52:dc:d7:78:2e:23:d0:
+                    63:1f:7d:77:91:c8:3f:66:7a:20:8a:cf:70:09:0f:
+                    a2:c0:82:a5:42:d9:be:dc:5f:78:73:f7:fa:3c:70:
+                    47:7b:39:77:89:5a:6f:ef:83:09:c9:1b:21:53:89:
+                    7c:10:bf:99:9c:05:39:32:1e:84:3b:a5:84:7e:ef:
+                    08:6d:b0:b0:31:61:d6:1a:aa:dd:7a:d6:10:02:e6:
+                    72:02:e5:40:bf:07:b9:cd:61:d1:55:04:9a:cd:02:
+                    73:41:c1:df:20:30:12:97:ca:a1:83:1a:97:8a:92:
+                    1c:47:5c:0a:60:da:41:3b:e6:0e:2c:82:ce:45:65:
+                    81:ba:45:a1:66:cc:ef:ab:65:5c:e5:a8:0c:86:dd:
+                    fc:86:54:f3:37:7c:89:a9:0c:fa:3a:da:82:c9:90:
+                    99:1e:1d:66:44:de:d3:c5:d4:0b:da:15:f8:d8:d4:
+                    63:2b:4e:6f:24:e9:c2:d7:74:9c:29:91:9f:25:39:
+                    8d:77:15:8c:cb:8e:ad:e3:80:0a:ea:79:04:72:9d:
+                    51:01:18:ae:35:51:ef:95:79:38:c4:db:99:50:47:
+                    62:38:e9
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:FALSE
+            X509v3 Key Usage: 
+                Digital Signature
+            X509v3 Subject Key Identifier: 
+                D5:41:CE:F6:1D:C7:E7:93:B7:EB:7E:89:99:70:A2:EE:F0:B5:DC:8C
+            X509v3 Authority Key Identifier: 
+                D5:41:CE:F6:1D:C7:E7:93:B7:EB:7E:89:99:70:A2:EE:F0:B5:DC:8C
+            X509v3 Extended Key Usage: 
+                Code Signing, 1.3.6.1.4.1.2312.16.1.2
+    Signature Algorithm: sha512WithRSAEncryption
+    Signature Value:
+        40:9d:5b:70:66:fe:9c:99:eb:ed:78:61:be:da:67:da:ac:80:
+        a8:c2:78:91:f8:90:11:be:9f:6a:e7:bf:79:dc:11:0c:c7:83:
+        e8:13:c4:1c:b6:fe:f0:e7:7d:1a:12:97:5d:19:56:9c:10:12:
+        1e:b9:19:88:30:95:c4:3b:2f:aa:91:6f:c1:9e:68:4a:f4:5c:
+        ef:a1:51:b5:a3:9b:58:3f:e2:ae:5c:29:a6:c4:30:fd:65:0b:
+        cc:8c:99:95:33:61:c6:07:fa:c3:bd:1a:57:80:e5:43:97:2e:
+        f3:5c:d6:1e:b7:23:9f:58:10:19:24:46:9e:f8:fd:2c:8e:88:
+        e7:ec:ef:15:4b:7a:6a:ce:b0:25:c0:01:c5:21:83:1a:d5:89:
+        0c:90:86:ad:d4:3e:6e:28:bf:6c:21:91:ff:b9:a9:ef:d4:ac:
+        de:7c:67:c1:e4:ed:75:26:15:ff:5d:67:39:24:2d:15:57:21:
+        09:76:e5:85:f3:45:e8:bf:b1:c0:39:2b:83:34:1a:f5:3f:1f:
+        ae:07:8c:82:1f:d4:dc:95:c0:4e:f3:7f:ac:db:8f:2c:db:a4:
+        d4:2a:4c:8c:de:e6:5b:84:fc:df:a3:74:d8:dc:9c:93:1f:5b:
+        c9:33:b5:b3:7d:2b:a4:4d:7a:bb:73:92:ff:8d:e9:9e:c7:a7:
+        d2:0d:83:bb:2c:2f:47:51:15:5c:6d:db:9a:d3:9e:6e:25:90:
+        01:e6:09:bd:a2:d0:1e:cf:a3:12:22:0d:56:70:bf:89:e4:be:
+        62:76:9c:d9:f5:c8:01:55:95:02:57:a1:67:59:88:97:57:f6:
+        bb:8d:c9:40:d5:e3:60:4f:43:dd:49:90:fa:a5:6d:08:96:b2:
+        4d:dd:a7:c6:e3:5c:06:ba:af:8c:30:9d:d5:a5:b0:ab:c4:e5:
+        f3:09:47:05:ba:9b:46:f4:26:70:3b:fa:da:a5:0a:47:ce:be:
+        43:87:eb:73:63:3b:cd:41:7a:78:a0:f6:7d:c5:37:fb:bb:26:
+        3b:b3:e7:44:49:06:8c:14:03:fc:b3:46:54:3b:0d:57:02:08:
+        99:79:68:a2:9c:62:95:4d:ac:8e:19:43:4e:8f:2d:52:fa:91:
+        ca:78:06:a2:b7:a3:66:6d:67:0b:13:ee:b1:01:38:e0:7c:ac:
+        9a:16:27:36:f1:45:83:5d:eb:d6:cd:65:3f:56:9a:d3:56:c4:
+        15:55:b2:64:ca:13:cb:31:1e:7e:03:85:68:61:40:02:99:4b:
+        25:01:68:8d:97:cc:39:1a:54:1b:e5:51:38:8e:ce:66:74:61:
+        5e:87:f4:31:7d:0d:be:9d:01:e1:b3:5c:bc:1a:d0:ea:5e:b2:
+        c8:ee:97:34:bc:9f:bb:98
+-----BEGIN CERTIFICATE-----
+MIIFejCCA2KgAwIBAgIUR3cmba5sV3PrgOKW3SaT/+n1Yl0wDQYJKoZIhvcNAQEN
+BQAwNjE0MDIGA1UEAwwrQ2Fub25pY2FsIEx0ZC4gTGl2ZSBQYXRjaCBTaWduaW5n
+IDIwMjUgS21vZDAgFw0yNTA1MTYwOTA3NDBaGA8yMDUwMDUxNjA5MDc0MFowNjE0
+MDIGA1UEAwwrQ2Fub25pY2FsIEx0ZC4gTGl2ZSBQYXRjaCBTaWduaW5nIDIwMjUg
+S21vZDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALipA0cue8aGFvS3
+qE07BfbEdTXpIopOQAaJFX+tmbvmkJNhyBbPLgAbgTb9zDF7l3mNXtJN0y+rNS10
+SJiz2XX5u+HyP2tt3OS77vWq94qMeqgL37H41gQTJ+kaqsJN0jU6vAbXg3/oxBxj
+izr/DguJbk9f6q143zer+VUd+24ppCJD0ZsSHrKEIxvSOJG4qGwcWTz/TKkYztB/
+He8Ez4roKbJLaA2SMrycXY8K0d1NJbo6jGpIWx6cARCZwac07mjsodMmvkXItJes
+iqp+E6blQ/EbP6GACtKp5/J3yuH1KTbfdYp+AtYXqkYSuVHwa8oi+AXe1gJHdgyI
+8caQRJlYccdiHiuUxSuO3Mp7p73NOI9Oc22wm058Eh9cxWLWgsbSeAlS3Nd4LiPQ
+Yx99d5HIP2Z6IIrPcAkPosCCpULZvtxfeHP3+jxwR3s5d4lab++DCckbIVOJfBC/
+mZwFOTIehDulhH7vCG2wsDFh1hqq3XrWEALmcgLlQL8Huc1h0VUEms0Cc0HB3yAw
+EpfKoYMal4qSHEdcCmDaQTvmDiyCzkVlgbpFoWbM76tlXOWoDIbd/IZU8zd8iakM
++jragsmQmR4dZkTe08XUC9oV+NjUYytObyTpwtd0nCmRnyU5jXcVjMuOreOACup5
+BHKdUQEYrjVR75V5OMTbmVBHYjjpAgMBAAGjfjB8MAwGA1UdEwEB/wQCMAAwCwYD
+VR0PBAQDAgeAMB0GA1UdDgQWBBTVQc72Hcfnk7frfomZcKLu8LXcjDAfBgNVHSME
+GDAWgBTVQc72Hcfnk7frfomZcKLu8LXcjDAfBgNVHSUEGDAWBggrBgEFBQcDAwYK
+KwYBBAGSCBABAjANBgkqhkiG9w0BAQ0FAAOCAgEAQJ1bcGb+nJnr7Xhhvtpn2qyA
+qMJ4kfiQEb6faue/edwRDMeD6BPEHLb+8Od9GhKXXRlWnBASHrkZiDCVxDsvqpFv
+wZ5oSvRc76FRtaObWD/irlwppsQw/WULzIyZlTNhxgf6w70aV4DlQ5cu81zWHrcj
+n1gQGSRGnvj9LI6I5+zvFUt6as6wJcABxSGDGtWJDJCGrdQ+bii/bCGR/7mp79Ss
+3nxnweTtdSYV/11nOSQtFVchCXblhfNF6L+xwDkrgzQa9T8frgeMgh/U3JXATvN/
+rNuPLNuk1CpMjN7mW4T836N02Nyckx9byTO1s30rpE16u3OS/43pnsen0g2Duywv
+R1EVXG3bmtOebiWQAeYJvaLQHs+jEiINVnC/ieS+Ynac2fXIAVWVAlehZ1mIl1f2
+u43JQNXjYE9D3UmQ+qVtCJayTd2nxuNcBrqvjDCd1aWwq8Tl8wlHBbqbRvQmcDv6
+2qUKR86+Q4frc2M7zUF6eKD2fcU3+7smO7PnREkGjBQD/LNGVDsNVwIImXloopxi
+lU2sjhlDTo8tUvqRyngGorejZm1nCxPusQE44HysmhYnNvFFg13r1s1lP1aa01bE
+FVWyZMoTyzEefgOFaGFAAplLJQFojZfMORpUG+VROI7OZnRhXof0MX0Nvp0B4bNc
+vBrQ6l6yyO6XNLyfu5g=
+-----END CERTIFICATE-----
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            c7:7e:51:6a:1c:25:cd:40
+        Signature Algorithm: sha512WithRSAEncryption
+        Issuer: CN = Canonical Ltd. Live Patch Signing
+        Validity
+            Not Before: Jul 18 23:41:27 2016 GMT
+            Not After : Jul 16 23:41:27 2026 GMT
+        Subject: CN = Canonical Ltd. Live Patch Signing
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                RSA Public-Key: (4096 bit)
+                Modulus:
+                    00:bd:74:ee:72:b3:4a:ab:e6:31:e8:29:24:c2:bd:
+                    46:98:32:c0:39:ee:a3:fb:8a:ad:fe:ab:1a:5b:a3:
+                    2e:a1:80:db:79:61:9e:47:79:2c:75:57:a2:21:f0:
+                    93:f6:87:f2:9b:4b:9d:2f:b3:58:61:28:3c:41:70:
+                    13:16:a1:72:90:c9:d5:16:71:7c:e0:30:f9:28:5e:
+                    48:20:36:00:69:b7:59:9f:a3:ec:a8:eb:55:41:9f:
+                    38:1e:22:4a:57:20:f4:83:59:49:c5:00:93:d3:33:
+                    02:92:d1:fc:f0:84:3b:4a:5b:8f:b6:73:9a:89:fa:
+                    30:1e:e6:2a:68:f2:91:ef:59:57:3d:dc:1c:52:6f:
+                    5e:e6:9b:b5:b8:7c:98:c9:13:d1:39:68:01:67:91:
+                    e0:d3:67:72:16:0a:5e:16:83:45:31:4f:b5:2b:b3:
+                    f6:40:86:89:3a:84:6e:6f:16:61:bc:70:84:be:5a:
+                    13:36:7b:82:ea:07:19:fc:18:c1:16:c6:32:0b:7d:
+                    2c:6b:c4:21:b9:38:6b:31:dc:d9:0c:ad:56:40:68:
+                    7c:e3:c6:64:8e:bf:1c:e0:72:3e:6c:db:d2:73:79:
+                    da:d7:c5:2f:5d:04:7d:b0:07:1e:95:dd:2a:47:5e:
+                    bf:3e:3a:c8:66:f6:67:0f:d4:2a:f1:e2:71:59:d2:
+                    6c:7b:a0:37:ac:e6:97:80:30:13:97:48:d5:74:fc:
+                    38:68:e4:57:cb:99:69:5a:84:27:ac:98:51:e4:64:
+                    bd:91:62:e8:58:27:06:2a:b9:0b:b8:08:e5:e5:b4:
+                    51:a7:a2:10:df:4e:07:6c:a0:3b:96:f2:6e:df:75:
+                    8c:97:1e:64:a0:9a:86:9b:98:26:f9:d8:b7:de:5b:
+                    21:b7:af:89:01:a3:f7:98:6b:da:19:ba:86:ef:ef:
+                    f1:ce:bb:2f:89:ed:c0:b6:1b:e5:5b:f8:90:11:9a:
+                    52:93:e9:be:f7:35:b9:08:cb:ba:c3:ed:2f:73:af:
+                    cc:96:07:55:b5:de:f6:03:f6:f1:89:f9:21:40:76:
+                    c1:69:f2:61:cc:9a:94:df:9c:ec:6a:65:38:be:d1:
+                    4e:2a:87:c7:2f:3e:53:ae:8b:9f:54:a1:09:59:64:
+                    25:aa:a9:d8:44:a9:a8:a0:71:e1:32:aa:4c:32:fd:
+                    44:28:cc:9c:6f:8e:db:81:7e:6f:fa:00:56:c5:e5:
+                    03:46:63:fb:8e:71:8d:e3:13:91:9f:ac:60:3e:64:
+                    f3:df:25:34:09:fa:2d:96:9f:16:05:ea:93:f5:e6:
+                    00:08:27:32:7b:3c:bd:ee:70:24:6c:3b:55:e9:db:
+                    f4:10:2d:20:06:b4:ca:e9:29:65:55:ad:f6:52:54:
+                    5f:e5:a3
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:FALSE
+            X509v3 Key Usage: 
+                Digital Signature
+            X509v3 Subject Key Identifier: 
+                14:DF:34:D1:A8:7C:F3:76:25:AB:EC:03:9E:F2:BF:52:12:49:B9:69
+            X509v3 Authority Key Identifier: 
+                keyid:14:DF:34:D1:A8:7C:F3:76:25:AB:EC:03:9E:F2:BF:52:12:49:B9:69
+
+    Signature Algorithm: sha512WithRSAEncryption
+         30:e7:48:02:37:e9:28:cf:04:a2:4d:5c:fa:d8:4e:c9:76:c7:
+         14:3f:bd:2c:51:3d:33:f0:1a:bc:49:f1:47:95:8f:69:d8:a9:
+         54:14:44:6c:4d:9f:55:82:08:1e:c6:5b:d5:91:d9:bc:2e:b0:
+         af:d6:25:65:74:96:aa:36:de:ae:31:a8:11:f2:a4:2c:5a:e1:
+         4f:73:f8:4a:c3:35:b0:76:96:71:f2:b5:7d:4b:75:ee:5d:bf:
+         86:a5:ba:0b:a9:52:cb:ec:ab:e5:23:4b:f2:74:55:28:17:1e:
+         b3:ac:27:ad:45:13:6e:69:b3:5a:be:42:36:29:48:db:e7:5c:
+         22:58:a0:90:82:2c:2a:21:2b:db:f4:64:b7:91:5d:1f:2c:48:
+         a4:1a:85:e3:86:a5:aa:19:cd:19:e8:a5:fb:a3:7b:94:77:48:
+         25:a4:cf:a0:cf:71:82:5c:6f:71:22:7c:d6:97:a0:53:bb:ec:
+         30:f6:cb:16:fb:7b:fd:16:94:7a:53:6e:bd:04:64:a2:01:10:
+         9f:f0:5b:b5:a6:73:41:9d:5f:6f:45:73:0d:05:f7:30:6d:39:
+         90:b6:7d:55:7d:4c:2f:ae:5f:38:56:2f:8b:df:f4:bf:12:06:
+         93:6e:0d:02:23:bf:71:91:57:88:e8:bd:62:72:99:00:40:29:
+         1e:c9:13:11:da:7e:8e:e1:d2:a5:0d:bf:f7:d6:ec:01:0d:89:
+         41:cd:d5:dc:d2:f7:5f:33:0d:4c:2f:85:b7:85:b7:81:e4:17:
+         29:f0:74:cf:0e:15:8c:1a:50:0b:08:63:1a:91:4f:e7:76:97:
+         f1:d4:3b:7e:72:d4:c5:45:58:0c:6a:e9:0d:f2:85:d8:91:1e:
+         37:bd:78:e3:39:4d:2e:fd:85:31:c1:a6:3b:6a:cc:2c:53:72:
+         1d:8e:7b:f0:e6:76:86:09:6f:1a:f3:e4:a1:e2:dd:76:5f:b0:
+         8c:e2:2a:54:5d:c1:88:49:90:10:15:42:7d:05:24:53:8c:54:
+         ff:48:18:1a:36:e3:31:d3:54:32:78:0d:fe:f2:3d:aa:0d:37:
+         15:84:b4:36:47:31:e8:85:6e:0b:58:38:ff:21:91:09:c9:a8:
+         43:a3:ea:60:cb:7e:ed:f7:41:6f:4e:91:c1:fd:77:46:e7:d4:
+         e7:86:c0:1b:fd:50:6c:aa:be:00:b3:63:02:ff:4e:c7:a5:57:
+         6e:29:64:e9:54:d5:30:63:38:5f:2d:5a:db:49:5f:14:14:22:
+         d2:81:1f:61:9e:ee:ee:16:66:d6:bc:bd:ac:1b:5c:fb:38:31:
+         95:33:2e:84:6e:7a:de:ee:b9:fc:97:17:06:13:bf:70:1c:6e:
+         76:ed:66:38:e2:70:08:00
+-----BEGIN CERTIFICATE-----
+MIIFODCCAyCgAwIBAgIJAMd+UWocJc1AMA0GCSqGSIb3DQEBDQUAMCwxKjAoBgNV
+BAMMIUNhbm9uaWNhbCBMdGQuIExpdmUgUGF0Y2ggU2lnbmluZzAeFw0xNjA3MTgy
+MzQxMjdaFw0yNjA3MTYyMzQxMjdaMCwxKjAoBgNVBAMMIUNhbm9uaWNhbCBMdGQu
+IExpdmUgUGF0Y2ggU2lnbmluZzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
+ggIBAL107nKzSqvmMegpJMK9RpgywDnuo/uKrf6rGlujLqGA23lhnkd5LHVXoiHw
+k/aH8ptLnS+zWGEoPEFwExahcpDJ1RZxfOAw+SheSCA2AGm3WZ+j7KjrVUGfOB4i
+Slcg9INZScUAk9MzApLR/PCEO0pbj7Zzmon6MB7mKmjyke9ZVz3cHFJvXuabtbh8
+mMkT0TloAWeR4NNnchYKXhaDRTFPtSuz9kCGiTqEbm8WYbxwhL5aEzZ7guoHGfwY
+wRbGMgt9LGvEIbk4azHc2QytVkBofOPGZI6/HOByPmzb0nN52tfFL10EfbAHHpXd
+Kkdevz46yGb2Zw/UKvHicVnSbHugN6zml4AwE5dI1XT8OGjkV8uZaVqEJ6yYUeRk
+vZFi6FgnBiq5C7gI5eW0UaeiEN9OB2ygO5bybt91jJceZKCahpuYJvnYt95bIbev
+iQGj95hr2hm6hu/v8c67L4ntwLYb5Vv4kBGaUpPpvvc1uQjLusPtL3OvzJYHVbXe
+9gP28Yn5IUB2wWnyYcyalN+c7GplOL7RTiqHxy8+U66Ln1ShCVlkJaqp2ESpqKBx
+4TKqTDL9RCjMnG+O24F+b/oAVsXlA0Zj+45xjeMTkZ+sYD5k898lNAn6LZafFgXq
+k/XmAAgnMns8ve5wJGw7Venb9BAtIAa0yukpZVWt9lJUX+WjAgMBAAGjXTBbMAwG
+A1UdEwEB/wQCMAAwCwYDVR0PBAQDAgeAMB0GA1UdDgQWBBQU3zTRqHzzdiWr7AOe
+8r9SEkm5aTAfBgNVHSMEGDAWgBQU3zTRqHzzdiWr7AOe8r9SEkm5aTANBgkqhkiG
+9w0BAQ0FAAOCAgEAMOdIAjfpKM8Eok1c+thOyXbHFD+9LFE9M/AavEnxR5WPadip
+VBREbE2fVYIIHsZb1ZHZvC6wr9YlZXSWqjberjGoEfKkLFrhT3P4SsM1sHaWcfK1
+fUt17l2/hqW6C6lSy+yr5SNL8nRVKBces6wnrUUTbmmzWr5CNilI2+dcIligkIIs
+KiEr2/Rkt5FdHyxIpBqF44alqhnNGeil+6N7lHdIJaTPoM9xglxvcSJ81pegU7vs
+MPbLFvt7/RaUelNuvQRkogEQn/BbtaZzQZ1fb0VzDQX3MG05kLZ9VX1ML65fOFYv
+i9/0vxIGk24NAiO/cZFXiOi9YnKZAEApHskTEdp+juHSpQ2/99bsAQ2JQc3V3NL3
+XzMNTC+Ft4W3geQXKfB0zw4VjBpQCwhjGpFP53aX8dQ7fnLUxUVYDGrpDfKF2JEe
+N7144zlNLv2FMcGmO2rMLFNyHY578OZ2hglvGvPkoeLddl+wjOIqVF3BiEmQEBVC
+fQUkU4xU/0gYGjbjMdNUMngN/vI9qg03FYS0Nkcx6IVuC1g4/yGRCcmoQ6PqYMt+
+7fdBb06Rwf13RufU54bAG/1QbKq+ALNjAv9Ox6VXbilk6VTVMGM4Xy1a20lfFBQi
+0oEfYZ7u7hZm1ry9rBtc+zgxlTMuhG563u65/JcXBhO/cBxudu1mOOJwCAA=
+-----END CERTIFICATE-----
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            e9:df:13:0f:92:92:a9:b7
+        Signature Algorithm: sha512WithRSAEncryption
+        Issuer: C = GB, ST = Isle of Man, L = Douglas, O = Canonical Ltd., CN = Canonical Ltd. Kernel Module Signing
+        Validity
+            Not Before: May 31 16:06:09 2016 GMT
+            Not After : May 29 16:06:09 2026 GMT
+        Subject: C = GB, ST = Isle of Man, L = Douglas, O = Canonical Ltd., CN = Canonical Ltd. Kernel Module Signing
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                RSA Public-Key: (4096 bit)
+                Modulus:
+                    00:b3:b0:4f:c6:0a:77:8b:f9:d1:53:33:34:d2:80:
+                    b5:63:6f:e1:f6:a2:83:99:d5:b6:b1:e4:99:91:fa:
+                    6c:19:c6:d0:91:2a:b9:7d:b5:98:a6:0d:28:01:b8:
+                    7c:8e:aa:38:ec:51:37:33:96:f0:b0:9b:8d:86:5f:
+                    67:23:69:2f:d7:c2:f3:fb:c5:d7:f9:04:ff:f2:e5:
+                    61:68:b7:29:b9:c6:8e:4b:4d:2d:8f:92:0c:00:b3:
+                    a3:d2:5a:08:64:cd:f2:09:0b:a5:0e:e6:64:75:d5:
+                    41:f4:4d:49:3a:0d:dc:b9:27:8e:c4:d6:b1:df:8f:
+                    6c:f0:e4:f7:31:cb:a9:04:a1:f9:a7:aa:15:da:59:
+                    03:4d:46:14:d0:dd:bf:e0:f5:9e:f0:71:0c:70:78:
+                    2b:08:fb:e0:b6:68:a4:74:12:9d:f7:f2:64:88:17:
+                    2a:8a:ed:1a:91:b5:6c:13:bd:4c:10:0a:0b:72:0b:
+                    90:db:7d:f3:78:44:4c:d2:a5:41:f7:1c:77:7d:5a:
+                    8a:54:bc:8f:fe:b7:ee:e1:bc:59:37:c4:d4:e8:14:
+                    d0:5b:42:9b:04:00:8e:6d:83:8a:25:21:5b:08:c4:
+                    7b:b2:d9:99:52:c9:5e:59:6d:c4:aa:52:59:e2:e4:
+                    2f:7e:7e:ac:05:01:99:bf:13:72:b7:45:c5:17:da:
+                    8a:d5:3e:71:73:2e:d8:aa:e6:eb:5a:d0:9a:c4:93:
+                    f3:be:eb:d2:47:25:34:16:29:fa:dd:9a:2f:b1:20:
+                    e5:41:4e:ed:ea:51:7c:23:80:ba:3d:b5:3a:0b:8c:
+                    9c:85:48:6c:3c:8b:29:2f:2f:12:c7:52:34:02:ea:
+                    0f:ac:53:23:3c:f8:3e:40:1b:30:63:e9:2d:e6:f6:
+                    58:cc:51:f9:eb:08:4a:b4:c7:16:80:d1:8b:c2:64:
+                    6a:71:a9:70:31:a4:a7:3a:c0:93:99:1b:0e:42:c1:
+                    00:6d:43:27:99:6c:e5:fd:23:16:c1:8e:b5:66:17:
+                    2b:4c:53:5a:6d:1e:96:16:13:6a:c6:d4:85:5b:74:
+                    2e:ce:7c:45:2f:ad:cb:75:9e:5e:91:bd:9a:6a:86:
+                    1a:06:bd:39:be:a3:50:56:ea:e1:f6:e3:95:69:d7:
+                    31:e4:66:f7:36:b5:51:c2:22:b4:9c:74:9c:44:0b:
+                    0e:16:5f:53:f0:23:c6:b9:40:bd:d6:b8:7d:1b:f6:
+                    73:f6:27:e7:c0:e3:65:a0:58:ab:5c:59:b7:80:8c:
+                    8c:04:b4:a9:ae:a0:51:40:10:3b:63:59:49:87:d1:
+                    9b:df:a3:8c:c4:2e:eb:70:c1:0a:18:1f:cb:22:c2:
+                    f2:4a:65:0d:e5:81:74:d8:ce:72:c6:35:be:ba:63:
+                    72:c4:f9
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:FALSE
+            X509v3 Key Usage: 
+                Digital Signature
+            X509v3 Subject Key Identifier: 
+                88:F7:52:E5:60:A1:E0:73:7E:31:16:3A:46:6A:D7:B7:0A:85:0C:19
+            X509v3 Authority Key Identifier: 
+                keyid:88:F7:52:E5:60:A1:E0:73:7E:31:16:3A:46:6A:D7:B7:0A:85:0C:19
+
+    Signature Algorithm: sha512WithRSAEncryption
+         04:85:16:27:58:ba:71:28:57:86:7b:c2:83:db:e5:72:6f:1e:
+         b2:1c:63:b0:db:ad:c0:42:96:c0:4f:65:f6:35:4d:c0:07:0d:
+         46:be:d3:1e:ec:f1:22:18:2a:18:5d:bb:69:a6:a6:d4:0d:c3:
+         57:03:b9:e7:45:49:28:ca:6d:98:17:68:97:cb:7b:36:81:0a:
+         37:9e:34:79:f3:e1:0e:5b:77:43:bb:5a:a5:45:b7:16:50:86:
+         fd:12:a4:96:0f:15:19:09:1c:e1:fa:80:a5:80:09:be:bb:c8:
+         26:0b:3e:de:03:d2:c2:18:a4:8d:0d:de:c5:32:82:0b:fb:75:
+         55:66:1a:2a:bb:e4:bd:25:91:20:15:d4:be:b8:3f:53:e3:fb:
+         a8:c3:55:e3:d5:e7:82:18:95:df:39:09:a7:fc:89:6e:b4:1c:
+         aa:2d:e8:67:c2:0d:34:34:3e:f9:fa:0b:ce:81:92:11:ae:12:
+         0a:fe:35:63:ce:46:29:c4:2b:4f:cb:4e:05:0a:a1:11:e2:35:
+         f6:5a:5d:b5:e8:d2:6f:4c:fc:3d:24:a6:03:4b:dd:98:6b:f2:
+         71:58:16:1d:a5:25:ef:d9:06:7c:e8:db:7b:88:6a:89:5c:59:
+         01:92:64:db:44:08:63:6c:7c:32:d6:55:98:63:09:26:61:67:
+         0a:fe:5d:ee:fd:23:59:b3:4d:91:c1:4d:41:8b:cd:20:58:fa:
+         2d:45:e5:bd:1d:69:5c:03:a0:49:a6:97:54:13:b6:c9:e0:f8:
+         56:83:a1:2a:c3:f4:6c:fd:ab:20:ca:3d:9c:95:c0:cf:04:bb:
+         46:39:cf:34:81:65:45:27:64:01:7d:62:b3:b8:72:ea:10:d5:
+         0f:53:7d:39:88:25:09:6f:8c:bc:e0:49:bb:39:e2:0e:8d:cf:
+         56:4d:c1:82:6d:87:d2:e7:fc:c0:9f:a7:65:60:d2:6c:65:18:
+         59:38:6e:d0:9c:d7:c3:81:9a:9a:29:8f:83:84:c3:b5:44:ff:
+         28:ac:13:17:64:f2:26:13:d9:55:06:b7:69:68:7c:bf:ec:d1:
+         8c:ef:b7:da:76:e1:07:73:c6:31:62:31:cb:b6:e1:e7:7f:0c:
+         c3:f7:4c:52:be:25:36:8e:a1:bb:60:02:c3:cb:3e:6f:29:fc:
+         7f:6a:fa:f8:ec:0a:df:49:e2:57:0e:bc:bd:93:c3:1b:d5:36:
+         8a:ff:d8:1b:17:c7:1f:cb:69:00:d2:54:9e:ad:61:89:92:95:
+         11:f8:ea:17:83:9f:9b:09:7d:b8:94:a4:ea:f5:ae:ea:dc:dd:
+         62:b9:9e:68:9c:18:ec:19:c4:13:08:c8:b1:62:ab:8e:84:69:
+         11:3c:da:ea:0d:b7:22:bd
+-----BEGIN CERTIFICATE-----
+MIIF2jCCA8KgAwIBAgIJAOnfEw+Skqm3MA0GCSqGSIb3DQEBDQUAMH0xCzAJBgNV
+BAYTAkdCMRQwEgYDVQQIDAtJc2xlIG9mIE1hbjEQMA4GA1UEBwwHRG91Z2xhczEX
+MBUGA1UECgwOQ2Fub25pY2FsIEx0ZC4xLTArBgNVBAMMJENhbm9uaWNhbCBMdGQu
+IEtlcm5lbCBNb2R1bGUgU2lnbmluZzAeFw0xNjA1MzExNjA2MDlaFw0yNjA1Mjkx
+NjA2MDlaMH0xCzAJBgNVBAYTAkdCMRQwEgYDVQQIDAtJc2xlIG9mIE1hbjEQMA4G
+A1UEBwwHRG91Z2xhczEXMBUGA1UECgwOQ2Fub25pY2FsIEx0ZC4xLTArBgNVBAMM
+JENhbm9uaWNhbCBMdGQuIEtlcm5lbCBNb2R1bGUgU2lnbmluZzCCAiIwDQYJKoZI
+hvcNAQEBBQADggIPADCCAgoCggIBALOwT8YKd4v50VMzNNKAtWNv4faig5nVtrHk
+mZH6bBnG0JEquX21mKYNKAG4fI6qOOxRNzOW8LCbjYZfZyNpL9fC8/vF1/kE//Ll
+YWi3KbnGjktNLY+SDACzo9JaCGTN8gkLpQ7mZHXVQfRNSToN3LknjsTWsd+PbPDk
+9zHLqQSh+aeqFdpZA01GFNDdv+D1nvBxDHB4Kwj74LZopHQSnffyZIgXKortGpG1
+bBO9TBAKC3ILkNt983hETNKlQfccd31ailS8j/637uG8WTfE1OgU0FtCmwQAjm2D
+iiUhWwjEe7LZmVLJXlltxKpSWeLkL35+rAUBmb8TcrdFxRfaitU+cXMu2Krm61rQ
+msST877r0kclNBYp+t2aL7Eg5UFO7epRfCOAuj21OguMnIVIbDyLKS8vEsdSNALq
+D6xTIzz4PkAbMGPpLeb2WMxR+esISrTHFoDRi8JkanGpcDGkpzrAk5kbDkLBAG1D
+J5ls5f0jFsGOtWYXK0xTWm0elhYTasbUhVt0Ls58RS+ty3WeXpG9mmqGGga9Ob6j
+UFbq4fbjlWnXMeRm9za1UcIitJx0nEQLDhZfU/AjxrlAvda4fRv2c/Yn58DjZaBY
+q1xZt4CMjAS0qa6gUUAQO2NZSYfRm9+jjMQu63DBChgfyyLC8kplDeWBdNjOcsY1
+vrpjcsT5AgMBAAGjXTBbMAwGA1UdEwEB/wQCMAAwCwYDVR0PBAQDAgeAMB0GA1Ud
+DgQWBBSI91LlYKHgc34xFjpGate3CoUMGTAfBgNVHSMEGDAWgBSI91LlYKHgc34x
+FjpGate3CoUMGTANBgkqhkiG9w0BAQ0FAAOCAgEABIUWJ1i6cShXhnvCg9vlcm8e
+shxjsNutwEKWwE9l9jVNwAcNRr7THuzxIhgqGF27aaam1A3DVwO550VJKMptmBdo
+l8t7NoEKN540efPhDlt3Q7tapUW3FlCG/RKklg8VGQkc4fqApYAJvrvIJgs+3gPS
+whikjQ3exTKCC/t1VWYaKrvkvSWRIBXUvrg/U+P7qMNV49XnghiV3zkJp/yJbrQc
+qi3oZ8INNDQ++foLzoGSEa4SCv41Y85GKcQrT8tOBQqhEeI19lpdtejSb0z8PSSm
+A0vdmGvycVgWHaUl79kGfOjbe4hqiVxZAZJk20QIY2x8MtZVmGMJJmFnCv5d7v0j
+WbNNkcFNQYvNIFj6LUXlvR1pXAOgSaaXVBO2yeD4VoOhKsP0bP2rIMo9nJXAzwS7
+RjnPNIFlRSdkAX1is7hy6hDVD1N9OYglCW+MvOBJuzniDo3PVk3Bgm2H0uf8wJ+n
+ZWDSbGUYWThu0JzXw4GamimPg4TDtUT/KKwTF2TyJhPZVQa3aWh8v+zRjO+32nbh
+B3PGMWIxy7bh538Mw/dMUr4lNo6hu2ACw8s+byn8f2r6+OwK30niVw68vZPDG9U2
+iv/YGxfHH8tpANJUnq1hiZKVEfjqF4Ofmwl9uJSk6vWu6tzdYrmeaJwY7BnEEwjI
+sWKrjoRpETza6g23Ir0=
+-----END CERTIFICATE-----
--- linux-xilinx-zynqmp-5.4.0.orig/debian/canonical-revoked-certs.pem
+++ linux-xilinx-zynqmp-5.4.0/debian/canonical-revoked-certs.pem
@@ -0,0 +1,688 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1 (0x1)
+        Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C = GB, ST = Isle of Man, L = Douglas, O = Canonical Ltd., CN = Canonical Ltd. Master Certificate Authority
+        Validity
+            Not Before: Apr 12 11:39:08 2012 GMT
+            Not After : Apr 11 11:39:08 2042 GMT
+        Subject: C = GB, ST = Isle of Man, O = Canonical Ltd., OU = Secure Boot, CN = Canonical Ltd. Secure Boot Signing
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (2048 bit)
+                Modulus:
+                    00:c9:5f:9b:62:8f:0b:b0:64:82:ac:be:c9:e2:62:
+                    e3:4b:d2:9f:1e:8a:d5:61:1a:2b:5d:38:f4:b7:ce:
+                    b9:9a:b8:43:b8:43:97:77:ab:4f:7f:0c:70:46:0b:
+                    fc:7f:6d:c6:6d:ea:80:5e:01:d2:b7:66:1e:87:de:
+                    0d:6d:d0:41:97:a8:a5:af:0c:63:4f:f7:7c:c2:52:
+                    cc:a0:31:a9:bb:89:5d:99:1e:46:6f:55:73:b9:76:
+                    69:ec:d7:c1:fc:21:d6:c6:07:e7:4f:bd:22:de:e4:
+                    a8:5b:2d:db:95:34:19:97:d6:28:4b:21:4c:ca:bb:
+                    1d:79:a6:17:7f:5a:f9:67:e6:5c:78:45:3d:10:6d:
+                    b0:17:59:26:11:c5:57:e3:7f:4e:82:ba:f6:2c:4e:
+                    c8:37:4d:ff:85:15:84:47:e0:ed:3b:7c:7f:bc:af:
+                    e9:01:05:a7:0c:6f:c3:e9:8d:a3:ce:be:a6:e3:cd:
+                    3c:b5:58:2c:9e:c2:03:1c:60:22:37:39:ff:41:02:
+                    c1:29:a4:65:51:ff:33:34:aa:42:15:f9:95:78:fc:
+                    2d:f5:da:8a:85:7c:82:9d:fb:37:2c:6b:a5:a8:df:
+                    7c:55:0b:80:2e:3c:b0:63:e1:cd:38:48:89:e8:14:
+                    06:0b:82:bc:fd:d4:07:68:1b:0f:3e:d9:15:dd:94:
+                    11:1b
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:FALSE
+            X509v3 Extended Key Usage: 
+                Code Signing, 1.3.6.1.4.1.311.10.3.6
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                61:48:2A:A2:83:0D:0A:B2:AD:5A:F1:0B:72:50:DA:90:33:DD:CE:F0
+            X509v3 Authority Key Identifier: 
+                AD:91:99:0B:C2:2A:B1:F5:17:04:8C:23:B6:65:5A:26:8E:34:5A:63
+    Signature Algorithm: sha256WithRSAEncryption
+    Signature Value:
+        8f:8a:a1:06:1f:29:b7:0a:4a:d5:c5:fd:81:ab:25:ea:c0:7d:
+        e2:fc:6a:96:a0:79:93:67:ee:05:0e:25:12:25:e4:5a:f6:aa:
+        1a:f1:12:f3:05:8d:87:5e:f1:5a:5c:cb:8d:23:73:65:1d:15:
+        b9:de:22:6b:d6:49:67:c9:a3:c6:d7:62:4e:5c:b5:f9:03:83:
+        40:81:dc:87:9c:3c:3f:1c:0d:51:9f:94:65:0a:84:48:67:e4:
+        a2:f8:a6:4a:f0:e7:cd:cd:bd:94:e3:09:d2:5d:2d:16:1b:05:
+        15:0b:cb:44:b4:3e:61:42:22:c4:2a:5c:4e:c5:1d:a3:e2:e0:
+        52:b2:eb:f4:8b:2b:dc:38:39:5d:fb:88:a1:56:65:5f:2b:4f:
+        26:ff:06:78:10:12:eb:8c:5d:32:e3:c6:45:af:25:9b:a0:ff:
+        8e:ef:47:09:a3:e9:8b:37:92:92:69:76:7e:34:3b:92:05:67:
+        4e:b0:25:ed:bc:5e:5f:8f:b4:d6:ca:40:ff:e4:e2:31:23:0c:
+        85:25:ae:0c:55:01:ec:e5:47:5e:df:5b:bc:14:33:e3:c6:f5:
+        18:b6:d9:f7:dd:b3:b4:a1:31:d3:5a:5c:5d:7d:3e:bf:0a:e4:
+        e4:e8:b4:59:7d:3b:b4:8c:a3:1b:b5:20:a3:b9:3e:84:6f:8c:
+        21:00:c3:39
+-----BEGIN CERTIFICATE-----
+MIIEIDCCAwigAwIBAgIBATANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBhMCR0Ix
+FDASBgNVBAgMC0lzbGUgb2YgTWFuMRAwDgYDVQQHDAdEb3VnbGFzMRcwFQYDVQQK
+DA5DYW5vbmljYWwgTHRkLjE0MDIGA1UEAwwrQ2Fub25pY2FsIEx0ZC4gTWFzdGVy
+IENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xMjA0MTIxMTM5MDhaFw00MjA0MTEx
+MTM5MDhaMH8xCzAJBgNVBAYTAkdCMRQwEgYDVQQIDAtJc2xlIG9mIE1hbjEXMBUG
+A1UECgwOQ2Fub25pY2FsIEx0ZC4xFDASBgNVBAsMC1NlY3VyZSBCb290MSswKQYD
+VQQDDCJDYW5vbmljYWwgTHRkLiBTZWN1cmUgQm9vdCBTaWduaW5nMIIBIjANBgkq
+hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyV+bYo8LsGSCrL7J4mLjS9KfHorVYRor
+XTj0t865mrhDuEOXd6tPfwxwRgv8f23GbeqAXgHSt2Yeh94NbdBBl6ilrwxjT/d8
+wlLMoDGpu4ldmR5Gb1VzuXZp7NfB/CHWxgfnT70i3uSoWy3blTQZl9YoSyFMyrsd
+eaYXf1r5Z+ZceEU9EG2wF1kmEcVX439Ogrr2LE7IN03/hRWER+DtO3x/vK/pAQWn
+DG/D6Y2jzr6m4808tVgsnsIDHGAiNzn/QQLBKaRlUf8zNKpCFfmVePwt9dqKhXyC
+nfs3LGulqN98VQuALjywY+HNOEiJ6BQGC4K8/dQHaBsPPtkV3ZQRGwIDAQABo4Gg
+MIGdMAwGA1UdEwEB/wQCMAAwHwYDVR0lBBgwFgYIKwYBBQUHAwMGCisGAQQBgjcK
+AwYwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRl
+MB0GA1UdDgQWBBRhSCqigw0Ksq1a8QtyUNqQM93O8DAfBgNVHSMEGDAWgBStkZkL
+wiqx9RcEjCO2ZVomjjRaYzANBgkqhkiG9w0BAQsFAAOCAQEAj4qhBh8ptwpK1cX9
+gasl6sB94vxqlqB5k2fuBQ4lEiXkWvaqGvES8wWNh17xWlzLjSNzZR0Vud4ia9ZJ
+Z8mjxtdiTly1+QODQIHch5w8PxwNUZ+UZQqESGfkovimSvDnzc29lOMJ0l0tFhsF
+FQvLRLQ+YUIixCpcTsUdo+LgUrLr9Isr3Dg5XfuIoVZlXytPJv8GeBAS64xdMuPG
+Ra8lm6D/ju9HCaPpizeSkml2fjQ7kgVnTrAl7bxeX4+01spA/+TiMSMMhSWuDFUB
+7OVHXt9bvBQz48b1GLbZ992ztKEx01pcXX0+vwrk5Oi0WX07tIyjG7Ugo7k+hG+M
+IQDDOQ==
+-----END CERTIFICATE-----
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 2 (0x2)
+        Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C = GB, ST = Isle of Man, L = Douglas, O = Canonical Ltd., CN = Canonical Ltd. Master Certificate Authority
+        Validity
+            Not Before: Sep 26 21:52:11 2017 GMT
+            Not After : Sep 25 21:52:11 2047 GMT
+        Subject: C = GB, ST = Isle of Man, O = Canonical Ltd., OU = Secure Boot, CN = Canonical Ltd. Secure Boot Signing (2017)
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (2048 bit)
+                Modulus:
+                    00:ef:9f:fa:9f:19:3a:9d:38:23:91:cc:c4:f9:42:
+                    e0:f8:54:12:82:dc:97:2c:d6:5b:c1:35:eb:ff:4a:
+                    74:06:b5:9d:32:aa:7b:f3:fc:31:5a:34:3e:a1:a4:
+                    44:db:7b:6d:16:af:35:76:e0:9b:99:ad:21:11:c6:
+                    12:4b:ae:24:8f:bb:d3:b2:00:fe:c5:1d:9b:3a:1a:
+                    4a:6c:ca:fa:16:37:85:22:f9:ff:22:fc:40:e0:58:
+                    35:c1:39:27:b4:c6:42:1a:96:d8:a5:c5:95:2e:f7:
+                    c5:1e:21:6e:36:84:f7:a9:a1:e1:f1:03:08:96:65:
+                    71:f8:eb:83:cf:82:f7:9a:44:58:72:00:14:39:29:
+                    4b:e9:78:2f:65:20:b3:80:76:3b:ba:0d:2d:46:f6:
+                    37:05:e7:05:fe:bd:6c:c7:a2:65:b5:06:6e:07:24:
+                    99:a1:c1:cf:e1:0e:5e:49:41:71:17:a8:50:e7:38:
+                    99:e5:6e:b6:db:9f:63:db:56:f4:9c:7d:89:f6:d2:
+                    03:6c:99:83:e0:99:23:39:36:bd:cb:b5:26:7c:7d:
+                    b0:c6:fe:82:7c:52:ed:f9:2c:8f:79:71:3d:a9:2f:
+                    b5:aa:7e:77:a0:fd:69:f9:97:10:a8:b2:c6:7d:88:
+                    9e:a2:19:bd:31:b8:02:2d:34:4d:9d:98:60:82:ad:
+                    04:ff
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:FALSE
+            X509v3 Extended Key Usage: 
+                Code Signing, 1.3.6.1.4.1.311.10.3.6
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                24:2A:DE:75:AC:4A:15:E5:0D:50:C8:4B:0D:45:FF:3E:AE:70:7A:03
+            X509v3 Authority Key Identifier: 
+                AD:91:99:0B:C2:2A:B1:F5:17:04:8C:23:B6:65:5A:26:8E:34:5A:63
+    Signature Algorithm: sha256WithRSAEncryption
+    Signature Value:
+        00:b2:b7:57:b5:2b:5d:16:d3:04:88:6a:d7:77:d5:0d:89:f1:
+        d2:6e:11:d1:8e:f5:62:05:c4:6a:57:df:eb:d2:86:68:f2:fd:
+        a7:37:11:3c:f4:ce:5d:fe:32:5f:31:a2:6b:3a:da:28:c2:88:
+        fa:7f:70:b5:25:99:ea:27:9a:56:6a:9d:b2:0f:14:99:e2:b7:
+        c6:39:1e:8e:a7:76:31:d9:ed:c5:05:8d:48:ae:1b:68:18:14:
+        51:a1:7d:f6:c7:df:cb:9d:eb:a4:3b:0b:ff:c2:07:c5:42:bc:
+        0d:b2:11:fa:37:17:2b:1c:b5:84:48:2d:f9:31:4a:57:49:8e:
+        61:a6:82:11:06:4c:34:ea:9c:2a:47:4d:eb:e0:26:af:da:d2:
+        c2:08:a0:37:35:7b:73:71:de:0b:c4:ba:c8:34:de:20:04:03:
+        6f:46:26:0d:b9:91:02:5b:71:76:cc:45:e4:08:d0:a6:dd:a4:
+        50:d3:d9:04:91:2b:d9:5c:34:88:fc:c2:37:fd:c6:d4:3e:57:
+        f7:6b:ba:7b:d7:02:7a:84:0c:c8:c1:19:cc:bc:fa:52:d5:7f:
+        b3:35:c4:53:5d:70:0a:f6:44:60:8d:a9:11:7a:1b:7d:ae:7b:
+        20:5a:4c:8d:44:f6:c1:a9:61:cb:dc:cb:90:37:d5:28:24:73:
+        87:d0:e0:d8
+-----BEGIN CERTIFICATE-----
+MIIEKDCCAxCgAwIBAgIBAjANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBhMCR0Ix
+FDASBgNVBAgMC0lzbGUgb2YgTWFuMRAwDgYDVQQHDAdEb3VnbGFzMRcwFQYDVQQK
+DA5DYW5vbmljYWwgTHRkLjE0MDIGA1UEAwwrQ2Fub25pY2FsIEx0ZC4gTWFzdGVy
+IENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xNzA5MjYyMTUyMTFaFw00NzA5MjUy
+MTUyMTFaMIGGMQswCQYDVQQGEwJHQjEUMBIGA1UECAwLSXNsZSBvZiBNYW4xFzAV
+BgNVBAoMDkNhbm9uaWNhbCBMdGQuMRQwEgYDVQQLDAtTZWN1cmUgQm9vdDEyMDAG
+A1UEAwwpQ2Fub25pY2FsIEx0ZC4gU2VjdXJlIEJvb3QgU2lnbmluZyAoMjAxNykw
+ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDvn/qfGTqdOCORzMT5QuD4
+VBKC3Jcs1lvBNev/SnQGtZ0yqnvz/DFaND6hpETbe20WrzV24JuZrSERxhJLriSP
+u9OyAP7FHZs6GkpsyvoWN4Ui+f8i/EDgWDXBOSe0xkIaltilxZUu98UeIW42hPep
+oeHxAwiWZXH464PPgveaRFhyABQ5KUvpeC9lILOAdju6DS1G9jcF5wX+vWzHomW1
+Bm4HJJmhwc/hDl5JQXEXqFDnOJnlbrbbn2PbVvScfYn20gNsmYPgmSM5Nr3LtSZ8
+fbDG/oJ8Uu35LI95cT2pL7Wqfneg/Wn5lxCossZ9iJ6iGb0xuAItNE2dmGCCrQT/
+AgMBAAGjgaAwgZ0wDAYDVR0TAQH/BAIwADAfBgNVHSUEGDAWBggrBgEFBQcDAwYK
+KwYBBAGCNwoDBjAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2Vy
+dGlmaWNhdGUwHQYDVR0OBBYEFCQq3nWsShXlDVDISw1F/z6ucHoDMB8GA1UdIwQY
+MBaAFK2RmQvCKrH1FwSMI7ZlWiaONFpjMA0GCSqGSIb3DQEBCwUAA4IBAQAAsrdX
+tStdFtMEiGrXd9UNifHSbhHRjvViBcRqV9/r0oZo8v2nNxE89M5d/jJfMaJrOtoo
+woj6f3C1JZnqJ5pWap2yDxSZ4rfGOR6Op3Yx2e3FBY1IrhtoGBRRoX32x9/Lneuk
+Owv/wgfFQrwNshH6NxcrHLWESC35MUpXSY5hpoIRBkw06pwqR03r4Cav2tLCCKA3
+NXtzcd4LxLrINN4gBANvRiYNuZECW3F2zEXkCNCm3aRQ09kEkSvZXDSI/MI3/cbU
+Plf3a7p71wJ6hAzIwRnMvPpS1X+zNcRTXXAK9kRgjakReht9rnsgWkyNRPbBqWHL
+3MuQN9UoJHOH0ODY
+-----END CERTIFICATE-----
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 3 (0x3)
+        Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C = GB, ST = Isle of Man, L = Douglas, O = Canonical Ltd., CN = Canonical Ltd. Master Certificate Authority
+        Validity
+            Not Before: Oct 26 18:31:14 2018 GMT
+            Not After : Oct 24 18:31:14 2048 GMT
+        Subject: C = GB, ST = Isle of Man, O = Canonical Ltd., OU = Secure Boot, CN = Canonical Ltd. Secure Boot Signing (ESM 2018)
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (2048 bit)
+                Modulus:
+                    00:bf:6a:e5:6d:55:7a:ec:7a:11:37:45:9c:4c:8f:
+                    6b:2d:56:d3:74:2b:32:ac:84:2d:ba:cb:cc:ec:8d:
+                    92:22:69:48:a5:d4:f6:75:11:66:2f:cb:b2:fd:9e:
+                    56:ab:e6:f1:52:8e:75:3e:50:bd:25:b3:50:fc:ef:
+                    3d:76:f3:3f:7f:03:f6:e2:a1:25:69:5c:14:98:54:
+                    bd:11:bf:e9:a5:ac:46:91:4b:1d:de:b7:18:2b:c8:
+                    22:83:15:a7:4a:00:8d:9d:e4:c0:da:f7:41:02:fd:
+                    9f:5f:79:93:56:cc:86:e1:b5:e0:39:0e:3c:a2:5b:
+                    fe:c0:56:f0:92:50:5a:2b:67:67:93:56:d7:7a:75:
+                    99:6a:25:b4:63:a8:5f:69:7e:3a:49:58:2a:a7:80:
+                    f6:5a:b4:be:b2:be:a8:8c:45:41:c9:f2:fc:76:a8:
+                    65:ef:99:29:0d:c9:9c:54:6b:0a:f0:4a:0e:61:0d:
+                    ed:99:32:af:12:e2:12:7b:9f:7b:ec:05:c4:e0:b6:
+                    d5:c3:71:28:ae:dd:0b:ba:97:ad:68:0b:76:e9:bf:
+                    e7:01:7e:64:54:39:23:85:36:c8:9d:dd:27:a1:ff:
+                    df:46:36:14:7e:cb:cc:a1:cd:49:0b:6d:c2:0c:45:
+                    99:56:58:7c:87:0d:59:9a:dc:4a:39:3b:1d:d9:15:
+                    2e:b5
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:FALSE
+            X509v3 Extended Key Usage: 
+                Code Signing, 1.3.6.1.4.1.311.10.3.6
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                36:51:88:C1:D3:74:D6:B0:7C:3C:8F:24:0F:8E:F7:22:43:3D:6A:8B
+            X509v3 Authority Key Identifier: 
+                AD:91:99:0B:C2:2A:B1:F5:17:04:8C:23:B6:65:5A:26:8E:34:5A:63
+    Signature Algorithm: sha256WithRSAEncryption
+    Signature Value:
+        4c:0f:cd:77:60:b4:6f:53:87:f3:3c:4f:e6:81:5f:a7:1c:cc:
+        60:29:b6:34:6c:4d:08:9b:e2:d2:bd:f6:17:1a:62:79:b8:17:
+        bc:a2:60:59:fd:03:51:c3:b7:6b:de:73:b3:48:95:f5:0b:aa:
+        b6:3c:b4:34:dc:1d:0b:c4:97:62:87:e7:48:d5:8f:c9:ea:e8:
+        91:8f:2a:40:cd:b7:b3:ee:b2:98:9e:fb:37:31:29:e6:8e:2f:
+        0a:39:99:1e:c6:aa:b8:05:62:85:d3:a8:3e:60:38:98:0f:f0:
+        fe:c7:ab:01:a5:6a:a5:7f:70:a6:26:94:76:23:2f:08:89:74:
+        97:c2:2a:ca:22:3e:7a:ea:22:22:08:07:f4:bb:f6:bc:69:9c:
+        4e:44:33:e2:8e:70:17:b0:9b:cb:33:94:66:6d:ff:9a:7d:e9:
+        50:b2:e8:90:14:e4:2b:91:cb:a0:c5:2e:0e:cf:19:ef:44:ef:
+        84:f0:bd:57:9e:26:c2:63:3d:df:fc:a1:84:de:5c:d7:5f:3b:
+        fb:94:61:f0:93:89:1f:cf:c3:b2:d1:90:97:35:7d:b9:8a:ad:
+        e6:05:f0:e8:3b:a1:7c:af:2b:c4:af:18:33:2e:5e:87:db:9d:
+        80:b5:04:fd:00:d0:60:ab:ff:85:77:0f:cb:47:22:c9:b2:85:
+        a8:48:16:e2
+-----BEGIN CERTIFICATE-----
+MIIELDCCAxSgAwIBAgIBAzANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBhMCR0Ix
+FDASBgNVBAgMC0lzbGUgb2YgTWFuMRAwDgYDVQQHDAdEb3VnbGFzMRcwFQYDVQQK
+DA5DYW5vbmljYWwgTHRkLjE0MDIGA1UEAwwrQ2Fub25pY2FsIEx0ZC4gTWFzdGVy
+IENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xODEwMjYxODMxMTRaFw00ODEwMjQx
+ODMxMTRaMIGKMQswCQYDVQQGEwJHQjEUMBIGA1UECAwLSXNsZSBvZiBNYW4xFzAV
+BgNVBAoMDkNhbm9uaWNhbCBMdGQuMRQwEgYDVQQLDAtTZWN1cmUgQm9vdDE2MDQG
+A1UEAwwtQ2Fub25pY2FsIEx0ZC4gU2VjdXJlIEJvb3QgU2lnbmluZyAoRVNNIDIw
+MTgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv2rlbVV67HoRN0Wc
+TI9rLVbTdCsyrIQtusvM7I2SImlIpdT2dRFmL8uy/Z5Wq+bxUo51PlC9JbNQ/O89
+dvM/fwP24qElaVwUmFS9Eb/ppaxGkUsd3rcYK8gigxWnSgCNneTA2vdBAv2fX3mT
+VsyG4bXgOQ48olv+wFbwklBaK2dnk1bXenWZaiW0Y6hfaX46SVgqp4D2WrS+sr6o
+jEVByfL8dqhl75kpDcmcVGsK8EoOYQ3tmTKvEuISe5977AXE4LbVw3Eort0Lupet
+aAt26b/nAX5kVDkjhTbInd0nof/fRjYUfsvMoc1JC23CDEWZVlh8hw1ZmtxKOTsd
+2RUutQIDAQABo4GgMIGdMAwGA1UdEwEB/wQCMAAwHwYDVR0lBBgwFgYIKwYBBQUH
+AwMGCisGAQQBgjcKAwYwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVk
+IENlcnRpZmljYXRlMB0GA1UdDgQWBBQ2UYjB03TWsHw8jyQPjvciQz1qizAfBgNV
+HSMEGDAWgBStkZkLwiqx9RcEjCO2ZVomjjRaYzANBgkqhkiG9w0BAQsFAAOCAQEA
+TA/Nd2C0b1OH8zxP5oFfpxzMYCm2NGxNCJvi0r32FxpiebgXvKJgWf0DUcO3a95z
+s0iV9Quqtjy0NNwdC8SXYofnSNWPyerokY8qQM23s+6ymJ77NzEp5o4vCjmZHsaq
+uAVihdOoPmA4mA/w/serAaVqpX9wpiaUdiMvCIl0l8IqyiI+euoiIggH9Lv2vGmc
+TkQz4o5wF7CbyzOUZm3/mn3pULLokBTkK5HLoMUuDs8Z70TvhPC9V54mwmM93/yh
+hN5c1187+5Rh8JOJH8/DstGQlzV9uYqt5gXw6DuhfK8rxK8YMy5eh9udgLUE/QDQ
+YKv/hXcPy0ciybKFqEgW4g==
+-----END CERTIFICATE-----
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 4 (0x4)
+        Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C = GB, ST = Isle of Man, L = Douglas, O = Canonical Ltd., CN = Canonical Ltd. Master Certificate Authority
+        Validity
+            Not Before: Sep 18 16:10:17 2019 GMT
+            Not After : Sep 16 16:10:17 2049 GMT
+        Subject: C = GB, ST = Isle of Man, O = Canonical Ltd., OU = Secure Boot, CN = Canonical Ltd. Secure Boot Signing (2019)
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (2048 bit)
+                Modulus:
+                    00:e6:47:d8:75:e5:87:59:26:87:83:7d:5b:7a:b8:
+                    58:3d:7c:ef:36:f8:a0:7a:b7:14:56:58:7d:01:f1:
+                    1c:3b:8c:e6:5b:03:77:7d:a0:ed:47:0a:45:e6:75:
+                    5c:de:95:38:0d:38:fa:41:79:89:56:31:87:e7:a3:
+                    9a:36:70:b6:cf:24:2f:99:26:89:08:39:0e:14:c3:
+                    35:be:02:8b:52:e1:8e:7b:0c:a6:9d:78:ff:01:60:
+                    d7:f5:c3:d5:f0:5e:dc:e4:23:09:59:72:93:d3:b5:
+                    22:af:7c:cd:e0:84:0f:af:11:2d:bc:c6:72:42:af:
+                    ea:67:63:c4:10:41:78:02:80:62:0d:43:74:b4:1c:
+                    ed:50:d7:94:f1:b0:bb:f9:57:80:e4:69:0f:83:4b:
+                    a2:e6:2c:4a:9a:e1:7d:7c:62:19:29:27:97:1f:4c:
+                    f1:85:f0:39:f5:31:9f:3a:39:0e:d4:4d:07:3a:40:
+                    55:4b:a6:6c:9d:04:89:51:2d:7c:b0:ef:40:b5:42:
+                    29:16:cc:65:73:38:62:21:f6:e3:2c:17:50:9d:74:
+                    34:4e:df:7c:4a:33:a4:bb:40:cf:d5:e5:ed:05:07:
+                    cd:4c:f9:af:7f:a6:5c:b9:f7:c5:16:45:4e:44:40:
+                    d7:85:32:de:ac:e5:75:ad:9b:d7:c0:26:33:1f:77:
+                    a5:37
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:FALSE
+            X509v3 Extended Key Usage: 
+                Code Signing, 1.3.6.1.4.1.311.10.3.6
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                C0:74:6F:D6:C5:DA:3A:E8:27:86:46:51:AD:66:AE:47:FE:24:B3:E8
+            X509v3 Authority Key Identifier: 
+                AD:91:99:0B:C2:2A:B1:F5:17:04:8C:23:B6:65:5A:26:8E:34:5A:63
+    Signature Algorithm: sha256WithRSAEncryption
+    Signature Value:
+        aa:12:6c:d1:9d:6a:da:f0:ec:7c:17:46:3b:57:b8:d6:76:5f:
+        24:e6:06:a2:0a:55:1f:2f:d3:5e:8f:de:cf:02:f2:ff:e0:dd:
+        d3:c7:bd:75:59:aa:cd:34:f3:28:80:73:cc:28:69:e7:a2:70:
+        88:a2:c7:dc:66:f0:92:0e:ff:64:bf:30:04:54:01:1b:96:ad:
+        15:c5:61:fd:32:61:d7:5e:b5:ba:91:fd:31:fc:6b:15:df:ee:
+        22:d9:e4:1f:f3:cc:8b:0c:9f:f5:e8:f7:e2:62:3f:40:52:c9:
+        f0:f1:1c:63:fc:6c:90:e1:5b:74:03:b9:df:d1:3e:a8:ec:db:
+        2b:6e:83:6f:9f:7f:ba:b4:79:fc:3d:e7:12:2f:4a:e7:17:8c:
+        2b:77:a5:90:74:3c:bd:cf:75:83:0d:1a:95:d5:56:ef:07:9b:
+        a6:b3:31:e3:8c:97:ce:68:11:b5:7b:25:03:72:1c:ea:67:e9:
+        7c:3e:73:c7:7c:3e:fc:f5:ae:8a:b2:07:0d:15:6a:66:09:d7:
+        23:b9:5d:80:7a:26:d6:b6:22:30:aa:84:af:c0:42:e9:75:c3:
+        59:ab:a3:84:87:6b:0c:b7:ab:4e:92:69:ae:2c:82:6f:ab:01:
+        24:ab:ff:78:6d:59:85:c2:3b:23:c0:bd:0d:d8:6e:3a:29:82:
+        e1:c4:5f:db
+-----BEGIN CERTIFICATE-----
+MIIEKDCCAxCgAwIBAgIBBDANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBhMCR0Ix
+FDASBgNVBAgMC0lzbGUgb2YgTWFuMRAwDgYDVQQHDAdEb3VnbGFzMRcwFQYDVQQK
+DA5DYW5vbmljYWwgTHRkLjE0MDIGA1UEAwwrQ2Fub25pY2FsIEx0ZC4gTWFzdGVy
+IENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xOTA5MTgxNjEwMTdaFw00OTA5MTYx
+NjEwMTdaMIGGMQswCQYDVQQGEwJHQjEUMBIGA1UECAwLSXNsZSBvZiBNYW4xFzAV
+BgNVBAoMDkNhbm9uaWNhbCBMdGQuMRQwEgYDVQQLDAtTZWN1cmUgQm9vdDEyMDAG
+A1UEAwwpQ2Fub25pY2FsIEx0ZC4gU2VjdXJlIEJvb3QgU2lnbmluZyAoMjAxOSkw
+ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDmR9h15YdZJoeDfVt6uFg9
+fO82+KB6txRWWH0B8Rw7jOZbA3d9oO1HCkXmdVzelTgNOPpBeYlWMYfno5o2cLbP
+JC+ZJokIOQ4UwzW+AotS4Y57DKadeP8BYNf1w9XwXtzkIwlZcpPTtSKvfM3ghA+v
+ES28xnJCr+pnY8QQQXgCgGINQ3S0HO1Q15TxsLv5V4DkaQ+DS6LmLEqa4X18Yhkp
+J5cfTPGF8Dn1MZ86OQ7UTQc6QFVLpmydBIlRLXyw70C1QikWzGVzOGIh9uMsF1Cd
+dDRO33xKM6S7QM/V5e0FB81M+a9/ply598UWRU5EQNeFMt6s5XWtm9fAJjMfd6U3
+AgMBAAGjgaAwgZ0wDAYDVR0TAQH/BAIwADAfBgNVHSUEGDAWBggrBgEFBQcDAwYK
+KwYBBAGCNwoDBjAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2Vy
+dGlmaWNhdGUwHQYDVR0OBBYEFMB0b9bF2jroJ4ZGUa1mrkf+JLPoMB8GA1UdIwQY
+MBaAFK2RmQvCKrH1FwSMI7ZlWiaONFpjMA0GCSqGSIb3DQEBCwUAA4IBAQCqEmzR
+nWra8Ox8F0Y7V7jWdl8k5gaiClUfL9Nej97PAvL/4N3Tx711WarNNPMogHPMKGnn
+onCIosfcZvCSDv9kvzAEVAEblq0VxWH9MmHXXrW6kf0x/GsV3+4i2eQf88yLDJ/1
+6PfiYj9AUsnw8Rxj/GyQ4Vt0A7nf0T6o7NsrboNvn3+6tHn8PecSL0rnF4wrd6WQ
+dDy9z3WDDRqV1VbvB5umszHjjJfOaBG1eyUDchzqZ+l8PnPHfD789a6KsgcNFWpm
+CdcjuV2AeibWtiIwqoSvwELpdcNZq6OEh2sMt6tOkmmuLIJvqwEkq/94bVmFwjsj
+wL0N2G46KYLhxF/b
+-----END CERTIFICATE-----
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 6 (0x6)
+        Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C = GB, ST = Isle of Man, L = Douglas, O = Canonical Ltd., CN = Canonical Ltd. Master Certificate Authority
+        Validity
+            Not Before: Sep 23 19:29:32 2021 GMT
+            Not After : Sep 22 19:29:32 2051 GMT
+        Subject: C = GB, ST = Isle of Man, O = Canonical Ltd., OU = Secure Boot, CN = Canonical Ltd. Secure Boot Signing (2021 v1)
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (2048 bit)
+                Modulus:
+                    00:aa:b8:34:5b:b6:ae:44:bf:41:e1:78:11:b9:7a:
+                    c8:88:b3:b0:26:50:10:9c:98:d1:f3:98:9f:23:50:
+                    64:f6:39:dd:50:3a:23:44:53:65:fc:f3:9f:f5:a5:
+                    8b:ae:8b:df:47:9f:e9:d5:a0:92:19:f1:21:ea:cc:
+                    59:3a:74:df:45:71:bc:de:64:15:a5:f6:db:ca:71:
+                    fa:19:d4:44:0d:12:ec:47:3a:43:e2:f2:dd:8b:fe:
+                    0d:7b:dc:4d:db:53:06:22:61:e5:8b:35:49:b6:33:
+                    c4:0a:69:5f:5b:81:09:84:6b:42:33:18:09:9d:a0:
+                    35:f7:9c:1e:de:6e:de:90:69:1a:e8:32:e4:49:ad:
+                    c3:31:e9:f8:4a:a2:28:1d:db:0d:29:b6:48:0a:44:
+                    93:86:41:62:8f:73:97:60:10:8a:74:46:66:55:fe:
+                    a0:95:35:9e:ef:9f:af:11:fa:5b:a3:7c:c2:35:64:
+                    11:67:28:1e:14:0a:7d:68:61:9c:cd:c7:46:39:30:
+                    31:79:94:56:b3:45:16:9a:b5:77:66:fe:41:43:0f:
+                    00:48:6e:99:dd:0c:d4:47:2c:86:8c:50:04:61:20:
+                    dd:aa:8e:73:4f:21:b4:ee:09:4d:d3:40:01:d0:f2:
+                    a7:5b:7d:05:3d:c1:e7:65:26:aa:8c:9a:58:5a:7c:
+                    6d:6f
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:FALSE
+            X509v3 Extended Key Usage: 
+                Code Signing, 1.3.6.1.4.1.311.10.3.6
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                A8:D5:4B:BB:38:25:CF:B9:4F:A1:3C:9F:8A:59:4A:19:5C:10:7B:8D
+            X509v3 Authority Key Identifier: 
+                AD:91:99:0B:C2:2A:B1:F5:17:04:8C:23:B6:65:5A:26:8E:34:5A:63
+    Signature Algorithm: sha256WithRSAEncryption
+    Signature Value:
+        24:25:25:7e:01:a5:c8:3d:54:8c:1b:05:73:d1:06:d8:db:d4:
+        3a:71:d5:19:9d:97:1c:85:3c:ca:38:5a:0c:25:25:39:1a:67:
+        bc:6c:9d:98:6c:f3:7d:5f:b7:40:f9:73:a0:f5:7b:40:a8:66:
+        a5:f1:53:b1:78:80:24:3f:19:50:2f:02:09:ec:a1:8a:e6:0d:
+        df:c4:ae:24:9e:69:0d:5c:dc:44:4c:38:3a:53:4e:4b:a1:4b:
+        92:9f:43:a4:9d:1e:76:33:18:1b:bf:62:e5:f5:bc:93:3c:4e:
+        21:d5:5b:20:69:11:28:c1:c5:93:b5:8e:96:1d:1b:ca:72:79:
+        24:de:67:2a:50:9d:ce:8b:41:dd:3e:82:dd:a5:04:75:54:fb:
+        35:70:98:87:b4:f3:ea:41:23:23:80:0e:99:d7:03:16:ee:7e:
+        11:e2:c8:29:ab:73:c5:6d:5c:a8:2f:32:03:9f:8e:66:d6:cb:
+        54:84:55:75:ab:9a:dd:95:fd:05:1e:11:85:37:1e:63:d2:f4:
+        7f:34:64:32:a1:63:91:91:50:39:14:1a:ea:54:78:e6:0d:04:
+        23:c7:83:51:c5:25:27:07:6c:f8:65:b7:da:95:89:76:83:cc:
+        f3:7e:06:74:d3:6c:ef:e9:17:de:29:1e:ab:5c:d7:ec:df:f1:
+        98:b8:e9:66
+-----BEGIN CERTIFICATE-----
+MIIELTCCAxWgAwIBAgIBBjANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBhMCR0Ix
+FDASBgNVBAgMC0lzbGUgb2YgTWFuMRAwDgYDVQQHDAdEb3VnbGFzMRcwFQYDVQQK
+DA5DYW5vbmljYWwgTHRkLjE0MDIGA1UEAwwrQ2Fub25pY2FsIEx0ZC4gTWFzdGVy
+IENlcnRpZmljYXRlIEF1dGhvcml0eTAgFw0yMTA5MjMxOTI5MzJaGA8yMDUxMDky
+MjE5MjkzMlowgYkxCzAJBgNVBAYTAkdCMRQwEgYDVQQIDAtJc2xlIG9mIE1hbjEX
+MBUGA1UECgwOQ2Fub25pY2FsIEx0ZC4xFDASBgNVBAsMC1NlY3VyZSBCb290MTUw
+MwYDVQQDDCxDYW5vbmljYWwgTHRkLiBTZWN1cmUgQm9vdCBTaWduaW5nICgyMDIx
+IHYxKTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKq4NFu2rkS/QeF4
+Ebl6yIizsCZQEJyY0fOYnyNQZPY53VA6I0RTZfzzn/Wli66L30ef6dWgkhnxIerM
+WTp030VxvN5kFaX228px+hnURA0S7Ec6Q+Ly3Yv+DXvcTdtTBiJh5Ys1SbYzxApp
+X1uBCYRrQjMYCZ2gNfecHt5u3pBpGugy5EmtwzHp+EqiKB3bDSm2SApEk4ZBYo9z
+l2AQinRGZlX+oJU1nu+frxH6W6N8wjVkEWcoHhQKfWhhnM3HRjkwMXmUVrNFFpq1
+d2b+QUMPAEhumd0M1EcshoxQBGEg3aqOc08htO4JTdNAAdDyp1t9BT3B52Umqoya
+WFp8bW8CAwEAAaOBoDCBnTAMBgNVHRMBAf8EAjAAMB8GA1UdJQQYMBYGCCsGAQUF
+BwMDBgorBgEEAYI3CgMGMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRl
+ZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUqNVLuzglz7lPoTyfillKGVwQe40wHwYD
+VR0jBBgwFoAUrZGZC8IqsfUXBIwjtmVaJo40WmMwDQYJKoZIhvcNAQELBQADggEB
+ACQlJX4Bpcg9VIwbBXPRBtjb1Dpx1RmdlxyFPMo4WgwlJTkaZ7xsnZhs831ft0D5
+c6D1e0CoZqXxU7F4gCQ/GVAvAgnsoYrmDd/EriSeaQ1c3ERMODpTTkuhS5KfQ6Sd
+HnYzGBu/YuX1vJM8TiHVWyBpESjBxZO1jpYdG8pyeSTeZypQnc6LQd0+gt2lBHVU
++zVwmIe08+pBIyOADpnXAxbufhHiyCmrc8VtXKgvMgOfjmbWy1SEVXWrmt2V/QUe
+EYU3HmPS9H80ZDKhY5GRUDkUGupUeOYNBCPHg1HFJScHbPhlt9qViXaDzPN+BnTT
+bO/pF94pHqtc1+zf8Zi46WY=
+-----END CERTIFICATE-----
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 7 (0x7)
+        Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C = GB, ST = Isle of Man, L = Douglas, O = Canonical Ltd., CN = Canonical Ltd. Master Certificate Authority
+        Validity
+            Not Before: Sep 23 19:29:42 2021 GMT
+            Not After : Sep 22 19:29:42 2051 GMT
+        Subject: C = GB, ST = Isle of Man, O = Canonical Ltd., OU = Secure Boot, CN = Canonical Ltd. Secure Boot Signing (2021 v2)
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (2048 bit)
+                Modulus:
+                    00:ba:06:8b:ee:58:b7:8b:49:7b:53:7a:d1:df:02:
+                    e3:f2:d8:b0:8c:03:5c:f4:2d:0b:d8:18:3b:23:fa:
+                    68:b0:e8:e9:9d:dc:a2:eb:5e:d3:06:a9:28:d4:9f:
+                    14:b6:1e:1c:1d:ef:69:0e:7f:44:f2:cc:4a:f1:b1:
+                    d0:71:30:6a:50:1e:b0:d3:f8:a4:19:d0:4a:f1:e3:
+                    eb:7a:e5:57:4c:a1:fb:d1:87:b9:48:e0:55:37:52:
+                    f9:de:99:2e:95:85:36:ce:d3:1d:67:2f:14:cb:7f:
+                    05:82:75:21:b6:aa:a5:14:ac:da:4a:f4:fe:fa:5c:
+                    33:49:3d:6f:de:fd:9d:75:ba:e2:c4:02:38:b5:69:
+                    f5:ff:a8:67:4b:3a:e0:34:f6:3b:07:03:a5:7e:59:
+                    6f:3a:d2:28:a4:2f:25:ac:d8:a9:1f:59:52:5d:24:
+                    36:58:51:b5:f0:12:a8:d3:78:56:57:b1:e0:a9:df:
+                    14:05:65:7c:b5:a5:00:f0:88:39:14:44:18:85:2d:
+                    0c:28:69:7b:b9:b4:1c:47:6f:43:66:4c:22:ad:f7:
+                    f6:19:75:e1:14:2c:0d:33:3f:c1:3f:fc:73:56:b2:
+                    68:05:b5:92:03:9b:65:6b:81:80:92:35:03:9b:66:
+                    68:58:c5:66:11:b6:8c:7f:05:09:9a:45:a6:0e:5e:
+                    5f:bf
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:FALSE
+            X509v3 Extended Key Usage: 
+                Code Signing, 1.3.6.1.4.1.311.10.3.6
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                4C:F0:46:89:2D:6F:D3:C9:A5:B0:3F:98:D8:45:F9:08:51:DC:6A:8C
+            X509v3 Authority Key Identifier: 
+                AD:91:99:0B:C2:2A:B1:F5:17:04:8C:23:B6:65:5A:26:8E:34:5A:63
+    Signature Algorithm: sha256WithRSAEncryption
+    Signature Value:
+        93:9d:49:7d:9f:3e:3e:27:79:97:d9:c2:fc:0b:f7:30:b7:f4:
+        78:b2:c9:e4:5e:42:d3:27:26:70:cf:88:96:d1:f2:ea:a0:75:
+        7e:3c:f6:b7:d2:e7:95:30:e3:a6:67:a7:ee:b9:53:8f:fd:b2:
+        cb:db:e1:98:32:be:98:79:09:46:c6:63:6a:57:87:4d:b2:26:
+        46:f6:34:5e:18:75:ca:82:80:8e:33:c2:1d:c7:76:d7:14:57:
+        ef:2e:0e:9e:58:5c:81:8e:ed:53:2c:07:46:0a:8a:fc:2f:f5:
+        b2:c8:58:f5:fa:fa:bb:f9:7d:47:13:39:f0:f2:1c:15:9c:75:
+        90:40:bd:08:04:b3:6a:de:c2:cd:34:21:7e:ba:31:48:bc:a1:
+        23:bc:ee:93:b2:62:96:27:30:86:c2:d4:f7:b4:e6:3c:71:47:
+        37:84:ff:3d:0c:1e:ec:f3:0e:da:6b:dc:64:7a:b8:c0:7e:45:
+        13:09:bf:02:b3:b7:5b:6d:09:2d:6a:4e:0b:93:94:29:4c:a6:
+        c3:c7:05:fa:69:08:04:53:3c:4c:64:c0:7e:89:00:91:1b:a6:
+        c2:d7:ea:c4:db:86:38:fe:66:03:85:7b:fc:39:24:99:4c:2a:
+        3e:10:8b:91:c3:6e:20:9d:0c:ee:51:70:b5:98:58:f3:5c:ac:
+        16:98:7b:ce
+-----BEGIN CERTIFICATE-----
+MIIELTCCAxWgAwIBAgIBBzANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBhMCR0Ix
+FDASBgNVBAgMC0lzbGUgb2YgTWFuMRAwDgYDVQQHDAdEb3VnbGFzMRcwFQYDVQQK
+DA5DYW5vbmljYWwgTHRkLjE0MDIGA1UEAwwrQ2Fub25pY2FsIEx0ZC4gTWFzdGVy
+IENlcnRpZmljYXRlIEF1dGhvcml0eTAgFw0yMTA5MjMxOTI5NDJaGA8yMDUxMDky
+MjE5Mjk0MlowgYkxCzAJBgNVBAYTAkdCMRQwEgYDVQQIDAtJc2xlIG9mIE1hbjEX
+MBUGA1UECgwOQ2Fub25pY2FsIEx0ZC4xFDASBgNVBAsMC1NlY3VyZSBCb290MTUw
+MwYDVQQDDCxDYW5vbmljYWwgTHRkLiBTZWN1cmUgQm9vdCBTaWduaW5nICgyMDIx
+IHYyKTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALoGi+5Yt4tJe1N6
+0d8C4/LYsIwDXPQtC9gYOyP6aLDo6Z3coute0wapKNSfFLYeHB3vaQ5/RPLMSvGx
+0HEwalAesNP4pBnQSvHj63rlV0yh+9GHuUjgVTdS+d6ZLpWFNs7THWcvFMt/BYJ1
+IbaqpRSs2kr0/vpcM0k9b979nXW64sQCOLVp9f+oZ0s64DT2OwcDpX5ZbzrSKKQv
+JazYqR9ZUl0kNlhRtfASqNN4Vlex4KnfFAVlfLWlAPCIORREGIUtDChpe7m0HEdv
+Q2ZMIq339hl14RQsDTM/wT/8c1ayaAW1kgObZWuBgJI1A5tmaFjFZhG2jH8FCZpF
+pg5eX78CAwEAAaOBoDCBnTAMBgNVHRMBAf8EAjAAMB8GA1UdJQQYMBYGCCsGAQUF
+BwMDBgorBgEEAYI3CgMGMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRl
+ZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUTPBGiS1v08mlsD+Y2EX5CFHcaowwHwYD
+VR0jBBgwFoAUrZGZC8IqsfUXBIwjtmVaJo40WmMwDQYJKoZIhvcNAQELBQADggEB
+AJOdSX2fPj4neZfZwvwL9zC39HiyyeReQtMnJnDPiJbR8uqgdX489rfS55Uw46Zn
+p+65U4/9ssvb4Zgyvph5CUbGY2pXh02yJkb2NF4YdcqCgI4zwh3HdtcUV+8uDp5Y
+XIGO7VMsB0YKivwv9bLIWPX6+rv5fUcTOfDyHBWcdZBAvQgEs2rews00IX66MUi8
+oSO87pOyYpYnMIbC1Pe05jxxRzeE/z0MHuzzDtpr3GR6uMB+RRMJvwKzt1ttCS1q
+TguTlClMpsPHBfppCARTPExkwH6JAJEbpsLX6sTbhjj+ZgOFe/w5JJlMKj4Qi5HD
+biCdDO5RcLWYWPNcrBaYe84=
+-----END CERTIFICATE-----
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 8 (0x8)
+        Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C = GB, ST = Isle of Man, L = Douglas, O = Canonical Ltd., CN = Canonical Ltd. Master Certificate Authority
+        Validity
+            Not Before: Sep 23 19:30:02 2021 GMT
+            Not After : Sep 22 19:30:02 2051 GMT
+        Subject: C = GB, ST = Isle of Man, O = Canonical Ltd., OU = Secure Boot, CN = Canonical Ltd. Secure Boot Signing (2021 v3)
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (2048 bit)
+                Modulus:
+                    00:d6:29:96:87:ae:07:42:45:bb:65:09:b2:9b:de:
+                    5d:8e:78:61:10:d5:6d:ae:ae:26:08:6a:06:ec:4a:
+                    dd:2b:e7:1a:a9:ad:78:e3:fc:cf:8f:d1:47:bd:1e:
+                    33:d8:7a:e3:66:9b:e9:73:c1:5f:42:e2:fe:bc:c3:
+                    41:f7:cd:d7:85:d7:42:c9:ea:31:e5:47:b1:93:5b:
+                    43:2b:07:51:b8:75:08:ad:0f:e7:0d:81:38:5a:21:
+                    df:b1:43:5b:db:37:c5:ac:aa:14:3a:33:19:6a:26:
+                    e0:05:fe:cd:41:31:af:5d:a8:ab:31:77:44:fc:da:
+                    00:e2:7a:44:33:c3:a7:ed:13:54:9f:19:5d:c9:98:
+                    a2:3b:af:4d:0d:87:29:9c:90:9e:42:9e:9a:06:6a:
+                    70:27:c5:aa:f7:a2:f2:88:e0:b9:66:9a:72:a0:f6:
+                    61:7e:30:8f:14:9f:44:0d:dd:54:ae:47:c8:82:ba:
+                    d2:b2:db:6f:24:c1:f4:0a:81:07:90:47:49:5f:57:
+                    d6:3f:bf:2a:73:98:f2:f6:24:1a:74:03:d7:35:f0:
+                    42:d8:14:c5:94:27:5d:3c:49:0c:b0:f0:7a:61:1b:
+                    d7:5a:e3:a3:40:57:e9:a4:07:ee:02:a3:32:27:94:
+                    bb:f3:36:c5:5f:ef:d3:07:04:3a:80:4c:9c:0a:b7:
+                    88:9f
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:FALSE
+            X509v3 Extended Key Usage: 
+                Code Signing, 1.3.6.1.4.1.311.10.3.6
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                10:04:37:BB:6D:E6:E4:69:B5:81:E6:1C:D6:6B:CE:3E:F4:ED:53:AF
+            X509v3 Authority Key Identifier: 
+                AD:91:99:0B:C2:2A:B1:F5:17:04:8C:23:B6:65:5A:26:8E:34:5A:63
+    Signature Algorithm: sha256WithRSAEncryption
+    Signature Value:
+        3b:37:d6:a8:8d:cd:d2:df:13:35:ac:8c:92:d6:b0:ac:d1:38:
+        a8:00:97:47:59:b8:4a:84:8c:80:a5:1d:c7:29:bf:00:66:e5:
+        10:40:26:2e:31:f5:e1:13:c0:1b:29:f3:0b:7e:2d:71:d8:db:
+        e1:32:8f:79:8e:e3:97:0c:40:a9:a0:12:c1:fc:c2:50:88:72:
+        44:c5:bc:8b:45:6e:28:fd:d2:37:d6:db:17:cf:4e:61:33:08:
+        5a:5d:08:94:73:44:e2:76:00:44:1b:b8:00:a1:86:00:64:8a:
+        f1:42:32:3c:28:11:67:7c:8b:aa:06:34:74:58:e8:b3:3a:36:
+        8d:f6:04:5d:37:f5:66:52:c9:48:b0:a7:6f:34:09:dd:60:2a:
+        86:b9:14:f1:09:f6:06:16:56:e0:51:b1:e8:75:7f:fa:37:dc:
+        e0:98:a7:69:ae:7b:1a:73:89:0d:06:67:cc:01:ef:80:31:45:
+        9e:bb:03:2a:eb:89:70:d6:19:b2:c7:ce:bc:81:df:da:c8:6f:
+        a9:4b:2d:d7:a7:e1:af:c6:e8:fb:f0:61:c9:cd:d2:91:cd:8b:
+        c2:6c:ef:e0:b6:7f:f1:c4:81:f9:bb:76:9c:26:e3:fa:a1:a0:
+        cd:5e:05:de:ee:f9:1b:5b:50:0a:8b:0f:47:e3:90:32:ac:2a:
+        e7:65:02:80
+-----BEGIN CERTIFICATE-----
+MIIELTCCAxWgAwIBAgIBCDANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBhMCR0Ix
+FDASBgNVBAgMC0lzbGUgb2YgTWFuMRAwDgYDVQQHDAdEb3VnbGFzMRcwFQYDVQQK
+DA5DYW5vbmljYWwgTHRkLjE0MDIGA1UEAwwrQ2Fub25pY2FsIEx0ZC4gTWFzdGVy
+IENlcnRpZmljYXRlIEF1dGhvcml0eTAgFw0yMTA5MjMxOTMwMDJaGA8yMDUxMDky
+MjE5MzAwMlowgYkxCzAJBgNVBAYTAkdCMRQwEgYDVQQIDAtJc2xlIG9mIE1hbjEX
+MBUGA1UECgwOQ2Fub25pY2FsIEx0ZC4xFDASBgNVBAsMC1NlY3VyZSBCb290MTUw
+MwYDVQQDDCxDYW5vbmljYWwgTHRkLiBTZWN1cmUgQm9vdCBTaWduaW5nICgyMDIx
+IHYzKTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANYploeuB0JFu2UJ
+spveXY54YRDVba6uJghqBuxK3SvnGqmteOP8z4/RR70eM9h642ab6XPBX0Li/rzD
+QffN14XXQsnqMeVHsZNbQysHUbh1CK0P5w2BOFoh37FDW9s3xayqFDozGWom4AX+
+zUExr12oqzF3RPzaAOJ6RDPDp+0TVJ8ZXcmYojuvTQ2HKZyQnkKemgZqcCfFqvei
+8ojguWaacqD2YX4wjxSfRA3dVK5HyIK60rLbbyTB9AqBB5BHSV9X1j+/KnOY8vYk
+GnQD1zXwQtgUxZQnXTxJDLDwemEb11rjo0BX6aQH7gKjMieUu/M2xV/v0wcEOoBM
+nAq3iJ8CAwEAAaOBoDCBnTAMBgNVHRMBAf8EAjAAMB8GA1UdJQQYMBYGCCsGAQUF
+BwMDBgorBgEEAYI3CgMGMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRl
+ZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUEAQ3u23m5Gm1geYc1mvOPvTtU68wHwYD
+VR0jBBgwFoAUrZGZC8IqsfUXBIwjtmVaJo40WmMwDQYJKoZIhvcNAQELBQADggEB
+ADs31qiNzdLfEzWsjJLWsKzROKgAl0dZuEqEjIClHccpvwBm5RBAJi4x9eETwBsp
+8wt+LXHY2+Eyj3mO45cMQKmgEsH8wlCIckTFvItFbij90jfW2xfPTmEzCFpdCJRz
+ROJ2AEQbuAChhgBkivFCMjwoEWd8i6oGNHRY6LM6No32BF039WZSyUiwp280Cd1g
+Koa5FPEJ9gYWVuBRseh1f/o33OCYp2muexpziQ0GZ8wB74AxRZ67AyrriXDWGbLH
+zryB39rIb6lLLden4a/G6PvwYcnN0pHNi8Js7+C2f/HEgfm7dpwm4/qhoM1eBd7u
++RtbUAqLD0fjkDKsKudlAoA=
+-----END CERTIFICATE-----
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 3 (0x3)
+        Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C = GB, ST = Isle of Man, L = Douglas, O = Canonical Ltd., CN = Canonical Ltd. Master Certificate Authority
+        Validity
+            Not Before: Mar  4 10:27:14 2020 GMT
+            Not After : Mar  3 10:27:14 2050 GMT
+        Subject: C = GB, ST = Isle of Man, O = Canonical Ltd., OU = Secure Boot, CN = Canonical Ltd. Secure Boot Signing (Ubuntu Core 2019)
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (2048 bit)
+                Modulus:
+                    00:b9:10:47:2e:75:5d:f3:10:23:bb:a0:75:d2:fa:
+                    02:2d:ff:22:df:c1:e6:cd:38:7c:36:0f:ae:74:15:
+                    6e:a5:34:52:2b:c3:a4:3a:60:d7:06:ee:1d:99:93:
+                    ff:66:91:a3:18:52:2c:8c:58:e6:b4:2f:4b:c5:fb:
+                    83:e6:f3:19:bd:1b:ca:23:ec:97:1f:d8:f1:9a:f1:
+                    04:da:da:10:04:53:4b:ec:1d:b6:26:47:7c:bb:8f:
+                    a7:0a:6e:2e:e8:91:e6:c4:bb:64:34:78:3c:fa:09:
+                    15:1c:8f:9e:eb:04:99:36:22:c6:8d:07:15:0f:b9:
+                    69:08:fa:ff:4b:45:bd:ba:2b:cd:01:0e:e7:01:23:
+                    c9:e5:7a:39:3b:91:b0:45:3c:d5:77:ba:ca:f9:29:
+                    3d:11:3f:1c:6b:5b:8e:6c:4b:3f:c9:29:05:cb:59:
+                    d6:b1:c1:c0:2d:56:88:70:27:fa:73:05:5c:c2:11:
+                    d4:27:11:f7:0b:c2:d5:68:d3:1a:cd:ed:d0:e4:10:
+                    ff:34:cb:b7:45:70:34:2c:23:53:b6:9c:30:70:b4:
+                    5c:d1:e2:64:18:82:8f:62:b1:5e:aa:0b:d4:89:f2:
+                    1c:53:c4:32:7d:ef:53:ee:9b:6e:02:ab:78:bd:25:
+                    67:8b:39:36:d8:84:3b:06:99:02:d6:75:73:4e:f2:
+                    f6:b9
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:FALSE
+            X509v3 Extended Key Usage: 
+                Code Signing, 1.3.6.1.4.1.311.10.3.6
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                C1:D5:7B:8F:6B:74:3F:23:EE:41:F4:F7:EE:29:2F:06:EE:CA:DF:B9
+            X509v3 Authority Key Identifier: 
+                AD:91:99:0B:C2:2A:B1:F5:17:04:8C:23:B6:65:5A:26:8E:34:5A:63
+    Signature Algorithm: sha256WithRSAEncryption
+    Signature Value:
+        2d:b5:11:a8:d2:a0:af:81:a0:18:22:18:2c:08:d0:f4:63:e8:
+        8f:9a:f4:f5:20:dd:eb:22:77:19:9a:1a:09:3d:7f:aa:7d:c9:
+        81:bc:26:98:65:94:46:30:4b:c2:51:7c:f7:21:41:63:87:31:
+        fc:a4:c9:41:28:c7:2e:2a:2e:d8:a8:75:7a:72:77:3b:1b:9f:
+        72:15:0d:0c:96:8d:8b:51:f3:ce:37:b6:ca:9f:ca:59:40:4a:
+        fc:73:7a:94:12:99:aa:c2:8d:52:ce:91:19:2e:b4:da:ff:e5:
+        2c:67:74:d9:58:47:38:2f:61:88:c5:cf:a7:48:e1:08:ba:bc:
+        ec:d5:3a:47:d9:8c:dc:c3:bc:cb:98:2b:79:7a:02:46:ef:85:
+        19:2f:03:4b:05:84:eb:56:98:5f:6d:cf:a5:8b:a2:b6:e5:50:
+        51:7c:33:44:bd:7a:94:2e:0d:90:39:39:3e:62:60:ae:3a:e2:
+        f5:17:fa:f1:94:06:1d:ae:a3:f8:19:20:7f:4b:4c:07:c4:e6:
+        2d:0d:e5:94:84:51:6d:6f:0f:c4:c6:79:1d:f0:e8:0e:23:9e:
+        fd:f9:46:2c:b9:ec:97:38:56:7e:b8:13:f6:d2:e1:8e:a5:93:
+        02:7b:6e:dd:33:9a:bf:10:a8:1b:3d:fa:c4:f2:15:f0:27:73:
+        26:a6:94:d1
+-----BEGIN CERTIFICATE-----
+MIIENjCCAx6gAwIBAgIBAzANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBhMCR0Ix
+FDASBgNVBAgMC0lzbGUgb2YgTWFuMRAwDgYDVQQHDAdEb3VnbGFzMRcwFQYDVQQK
+DA5DYW5vbmljYWwgTHRkLjE0MDIGA1UEAwwrQ2Fub25pY2FsIEx0ZC4gTWFzdGVy
+IENlcnRpZmljYXRlIEF1dGhvcml0eTAgFw0yMDAzMDQxMDI3MTRaGA8yMDUwMDMw
+MzEwMjcxNFowgZIxCzAJBgNVBAYTAkdCMRQwEgYDVQQIDAtJc2xlIG9mIE1hbjEX
+MBUGA1UECgwOQ2Fub25pY2FsIEx0ZC4xFDASBgNVBAsMC1NlY3VyZSBCb290MT4w
+PAYDVQQDDDVDYW5vbmljYWwgTHRkLiBTZWN1cmUgQm9vdCBTaWduaW5nIChVYnVu
+dHUgQ29yZSAyMDE5KTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALkQ
+Ry51XfMQI7ugddL6Ai3/It/B5s04fDYPrnQVbqU0UivDpDpg1wbuHZmT/2aRoxhS
+LIxY5rQvS8X7g+bzGb0byiPslx/Y8ZrxBNraEARTS+wdtiZHfLuPpwpuLuiR5sS7
+ZDR4PPoJFRyPnusEmTYixo0HFQ+5aQj6/0tFvborzQEO5wEjyeV6OTuRsEU81Xe6
+yvkpPRE/HGtbjmxLP8kpBctZ1rHBwC1WiHAn+nMFXMIR1CcR9wvC1WjTGs3t0OQQ
+/zTLt0VwNCwjU7acMHC0XNHiZBiCj2KxXqoL1InyHFPEMn3vU+6bbgKreL0lZ4s5
+NtiEOwaZAtZ1c07y9rkCAwEAAaOBoDCBnTAMBgNVHRMBAf8EAjAAMB8GA1UdJQQY
+MBYGCCsGAQUFBwMDBgorBgEEAYI3CgMGMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NM
+IEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUwdV7j2t0PyPuQfT37ikv
+Bu7K37kwHwYDVR0jBBgwFoAUrZGZC8IqsfUXBIwjtmVaJo40WmMwDQYJKoZIhvcN
+AQELBQADggEBAC21EajSoK+BoBgiGCwI0PRj6I+a9PUg3esidxmaGgk9f6p9yYG8
+JphllEYwS8JRfPchQWOHMfykyUEoxy4qLtiodXpydzsbn3IVDQyWjYtR8843tsqf
+yllASvxzepQSmarCjVLOkRkutNr/5SxndNlYRzgvYYjFz6dI4Qi6vOzVOkfZjNzD
+vMuYK3l6AkbvhRkvA0sFhOtWmF9tz6WLorblUFF8M0S9epQuDZA5OT5iYK464vUX
++vGUBh2uo/gZIH9LTAfE5i0N5ZSEUW1vD8TGeR3w6A4jnv35Riy57Jc4Vn64E/bS
+4Y6lkwJ7bt0zmr8QqBs9+sTyFfAncyamlNE=
+-----END CERTIFICATE-----
--- linux-xilinx-zynqmp-5.4.0.orig/debian/certs/canonical-livepatch-2025-all.pem
+++ linux-xilinx-zynqmp-5.4.0/debian/certs/canonical-livepatch-2025-all.pem
@@ -0,0 +1,125 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            47:77:26:6d:ae:6c:57:73:eb:80:e2:96:dd:26:93:ff:e9:f5:62:5d
+        Signature Algorithm: sha512WithRSAEncryption
+        Issuer: CN=Canonical Ltd. Live Patch Signing 2025 Kmod
+        Validity
+            Not Before: May 16 09:07:40 2025 GMT
+            Not After : May 16 09:07:40 2050 GMT
+        Subject: CN=Canonical Ltd. Live Patch Signing 2025 Kmod
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (4096 bit)
+                Modulus:
+                    00:b8:a9:03:47:2e:7b:c6:86:16:f4:b7:a8:4d:3b:
+                    05:f6:c4:75:35:e9:22:8a:4e:40:06:89:15:7f:ad:
+                    99:bb:e6:90:93:61:c8:16:cf:2e:00:1b:81:36:fd:
+                    cc:31:7b:97:79:8d:5e:d2:4d:d3:2f:ab:35:2d:74:
+                    48:98:b3:d9:75:f9:bb:e1:f2:3f:6b:6d:dc:e4:bb:
+                    ee:f5:aa:f7:8a:8c:7a:a8:0b:df:b1:f8:d6:04:13:
+                    27:e9:1a:aa:c2:4d:d2:35:3a:bc:06:d7:83:7f:e8:
+                    c4:1c:63:8b:3a:ff:0e:0b:89:6e:4f:5f:ea:ad:78:
+                    df:37:ab:f9:55:1d:fb:6e:29:a4:22:43:d1:9b:12:
+                    1e:b2:84:23:1b:d2:38:91:b8:a8:6c:1c:59:3c:ff:
+                    4c:a9:18:ce:d0:7f:1d:ef:04:cf:8a:e8:29:b2:4b:
+                    68:0d:92:32:bc:9c:5d:8f:0a:d1:dd:4d:25:ba:3a:
+                    8c:6a:48:5b:1e:9c:01:10:99:c1:a7:34:ee:68:ec:
+                    a1:d3:26:be:45:c8:b4:97:ac:8a:aa:7e:13:a6:e5:
+                    43:f1:1b:3f:a1:80:0a:d2:a9:e7:f2:77:ca:e1:f5:
+                    29:36:df:75:8a:7e:02:d6:17:aa:46:12:b9:51:f0:
+                    6b:ca:22:f8:05:de:d6:02:47:76:0c:88:f1:c6:90:
+                    44:99:58:71:c7:62:1e:2b:94:c5:2b:8e:dc:ca:7b:
+                    a7:bd:cd:38:8f:4e:73:6d:b0:9b:4e:7c:12:1f:5c:
+                    c5:62:d6:82:c6:d2:78:09:52:dc:d7:78:2e:23:d0:
+                    63:1f:7d:77:91:c8:3f:66:7a:20:8a:cf:70:09:0f:
+                    a2:c0:82:a5:42:d9:be:dc:5f:78:73:f7:fa:3c:70:
+                    47:7b:39:77:89:5a:6f:ef:83:09:c9:1b:21:53:89:
+                    7c:10:bf:99:9c:05:39:32:1e:84:3b:a5:84:7e:ef:
+                    08:6d:b0:b0:31:61:d6:1a:aa:dd:7a:d6:10:02:e6:
+                    72:02:e5:40:bf:07:b9:cd:61:d1:55:04:9a:cd:02:
+                    73:41:c1:df:20:30:12:97:ca:a1:83:1a:97:8a:92:
+                    1c:47:5c:0a:60:da:41:3b:e6:0e:2c:82:ce:45:65:
+                    81:ba:45:a1:66:cc:ef:ab:65:5c:e5:a8:0c:86:dd:
+                    fc:86:54:f3:37:7c:89:a9:0c:fa:3a:da:82:c9:90:
+                    99:1e:1d:66:44:de:d3:c5:d4:0b:da:15:f8:d8:d4:
+                    63:2b:4e:6f:24:e9:c2:d7:74:9c:29:91:9f:25:39:
+                    8d:77:15:8c:cb:8e:ad:e3:80:0a:ea:79:04:72:9d:
+                    51:01:18:ae:35:51:ef:95:79:38:c4:db:99:50:47:
+                    62:38:e9
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:FALSE
+            X509v3 Key Usage: 
+                Digital Signature
+            X509v3 Subject Key Identifier: 
+                D5:41:CE:F6:1D:C7:E7:93:B7:EB:7E:89:99:70:A2:EE:F0:B5:DC:8C
+            X509v3 Authority Key Identifier: 
+                D5:41:CE:F6:1D:C7:E7:93:B7:EB:7E:89:99:70:A2:EE:F0:B5:DC:8C
+            X509v3 Extended Key Usage: 
+                Code Signing, 1.3.6.1.4.1.2312.16.1.2
+    Signature Algorithm: sha512WithRSAEncryption
+    Signature Value:
+        40:9d:5b:70:66:fe:9c:99:eb:ed:78:61:be:da:67:da:ac:80:
+        a8:c2:78:91:f8:90:11:be:9f:6a:e7:bf:79:dc:11:0c:c7:83:
+        e8:13:c4:1c:b6:fe:f0:e7:7d:1a:12:97:5d:19:56:9c:10:12:
+        1e:b9:19:88:30:95:c4:3b:2f:aa:91:6f:c1:9e:68:4a:f4:5c:
+        ef:a1:51:b5:a3:9b:58:3f:e2:ae:5c:29:a6:c4:30:fd:65:0b:
+        cc:8c:99:95:33:61:c6:07:fa:c3:bd:1a:57:80:e5:43:97:2e:
+        f3:5c:d6:1e:b7:23:9f:58:10:19:24:46:9e:f8:fd:2c:8e:88:
+        e7:ec:ef:15:4b:7a:6a:ce:b0:25:c0:01:c5:21:83:1a:d5:89:
+        0c:90:86:ad:d4:3e:6e:28:bf:6c:21:91:ff:b9:a9:ef:d4:ac:
+        de:7c:67:c1:e4:ed:75:26:15:ff:5d:67:39:24:2d:15:57:21:
+        09:76:e5:85:f3:45:e8:bf:b1:c0:39:2b:83:34:1a:f5:3f:1f:
+        ae:07:8c:82:1f:d4:dc:95:c0:4e:f3:7f:ac:db:8f:2c:db:a4:
+        d4:2a:4c:8c:de:e6:5b:84:fc:df:a3:74:d8:dc:9c:93:1f:5b:
+        c9:33:b5:b3:7d:2b:a4:4d:7a:bb:73:92:ff:8d:e9:9e:c7:a7:
+        d2:0d:83:bb:2c:2f:47:51:15:5c:6d:db:9a:d3:9e:6e:25:90:
+        01:e6:09:bd:a2:d0:1e:cf:a3:12:22:0d:56:70:bf:89:e4:be:
+        62:76:9c:d9:f5:c8:01:55:95:02:57:a1:67:59:88:97:57:f6:
+        bb:8d:c9:40:d5:e3:60:4f:43:dd:49:90:fa:a5:6d:08:96:b2:
+        4d:dd:a7:c6:e3:5c:06:ba:af:8c:30:9d:d5:a5:b0:ab:c4:e5:
+        f3:09:47:05:ba:9b:46:f4:26:70:3b:fa:da:a5:0a:47:ce:be:
+        43:87:eb:73:63:3b:cd:41:7a:78:a0:f6:7d:c5:37:fb:bb:26:
+        3b:b3:e7:44:49:06:8c:14:03:fc:b3:46:54:3b:0d:57:02:08:
+        99:79:68:a2:9c:62:95:4d:ac:8e:19:43:4e:8f:2d:52:fa:91:
+        ca:78:06:a2:b7:a3:66:6d:67:0b:13:ee:b1:01:38:e0:7c:ac:
+        9a:16:27:36:f1:45:83:5d:eb:d6:cd:65:3f:56:9a:d3:56:c4:
+        15:55:b2:64:ca:13:cb:31:1e:7e:03:85:68:61:40:02:99:4b:
+        25:01:68:8d:97:cc:39:1a:54:1b:e5:51:38:8e:ce:66:74:61:
+        5e:87:f4:31:7d:0d:be:9d:01:e1:b3:5c:bc:1a:d0:ea:5e:b2:
+        c8:ee:97:34:bc:9f:bb:98
+-----BEGIN CERTIFICATE-----
+MIIFejCCA2KgAwIBAgIUR3cmba5sV3PrgOKW3SaT/+n1Yl0wDQYJKoZIhvcNAQEN
+BQAwNjE0MDIGA1UEAwwrQ2Fub25pY2FsIEx0ZC4gTGl2ZSBQYXRjaCBTaWduaW5n
+IDIwMjUgS21vZDAgFw0yNTA1MTYwOTA3NDBaGA8yMDUwMDUxNjA5MDc0MFowNjE0
+MDIGA1UEAwwrQ2Fub25pY2FsIEx0ZC4gTGl2ZSBQYXRjaCBTaWduaW5nIDIwMjUg
+S21vZDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALipA0cue8aGFvS3
+qE07BfbEdTXpIopOQAaJFX+tmbvmkJNhyBbPLgAbgTb9zDF7l3mNXtJN0y+rNS10
+SJiz2XX5u+HyP2tt3OS77vWq94qMeqgL37H41gQTJ+kaqsJN0jU6vAbXg3/oxBxj
+izr/DguJbk9f6q143zer+VUd+24ppCJD0ZsSHrKEIxvSOJG4qGwcWTz/TKkYztB/
+He8Ez4roKbJLaA2SMrycXY8K0d1NJbo6jGpIWx6cARCZwac07mjsodMmvkXItJes
+iqp+E6blQ/EbP6GACtKp5/J3yuH1KTbfdYp+AtYXqkYSuVHwa8oi+AXe1gJHdgyI
+8caQRJlYccdiHiuUxSuO3Mp7p73NOI9Oc22wm058Eh9cxWLWgsbSeAlS3Nd4LiPQ
+Yx99d5HIP2Z6IIrPcAkPosCCpULZvtxfeHP3+jxwR3s5d4lab++DCckbIVOJfBC/
+mZwFOTIehDulhH7vCG2wsDFh1hqq3XrWEALmcgLlQL8Huc1h0VUEms0Cc0HB3yAw
+EpfKoYMal4qSHEdcCmDaQTvmDiyCzkVlgbpFoWbM76tlXOWoDIbd/IZU8zd8iakM
++jragsmQmR4dZkTe08XUC9oV+NjUYytObyTpwtd0nCmRnyU5jXcVjMuOreOACup5
+BHKdUQEYrjVR75V5OMTbmVBHYjjpAgMBAAGjfjB8MAwGA1UdEwEB/wQCMAAwCwYD
+VR0PBAQDAgeAMB0GA1UdDgQWBBTVQc72Hcfnk7frfomZcKLu8LXcjDAfBgNVHSME
+GDAWgBTVQc72Hcfnk7frfomZcKLu8LXcjDAfBgNVHSUEGDAWBggrBgEFBQcDAwYK
+KwYBBAGSCBABAjANBgkqhkiG9w0BAQ0FAAOCAgEAQJ1bcGb+nJnr7Xhhvtpn2qyA
+qMJ4kfiQEb6faue/edwRDMeD6BPEHLb+8Od9GhKXXRlWnBASHrkZiDCVxDsvqpFv
+wZ5oSvRc76FRtaObWD/irlwppsQw/WULzIyZlTNhxgf6w70aV4DlQ5cu81zWHrcj
+n1gQGSRGnvj9LI6I5+zvFUt6as6wJcABxSGDGtWJDJCGrdQ+bii/bCGR/7mp79Ss
+3nxnweTtdSYV/11nOSQtFVchCXblhfNF6L+xwDkrgzQa9T8frgeMgh/U3JXATvN/
+rNuPLNuk1CpMjN7mW4T836N02Nyckx9byTO1s30rpE16u3OS/43pnsen0g2Duywv
+R1EVXG3bmtOebiWQAeYJvaLQHs+jEiINVnC/ieS+Ynac2fXIAVWVAlehZ1mIl1f2
+u43JQNXjYE9D3UmQ+qVtCJayTd2nxuNcBrqvjDCd1aWwq8Tl8wlHBbqbRvQmcDv6
+2qUKR86+Q4frc2M7zUF6eKD2fcU3+7smO7PnREkGjBQD/LNGVDsNVwIImXloopxi
+lU2sjhlDTo8tUvqRyngGorejZm1nCxPusQE44HysmhYnNvFFg13r1s1lP1aa01bE
+FVWyZMoTyzEefgOFaGFAAplLJQFojZfMORpUG+VROI7OZnRhXof0MX0Nvp0B4bNc
+vBrQ6l6yyO6XNLyfu5g=
+-----END CERTIFICATE-----
--- linux-xilinx-zynqmp-5.4.0.orig/debian/certs/canonical-livepatch-all.pem
+++ linux-xilinx-zynqmp-5.4.0/debian/certs/canonical-livepatch-all.pem
@@ -0,0 +1,121 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            c7:7e:51:6a:1c:25:cd:40
+        Signature Algorithm: sha512WithRSAEncryption
+        Issuer: CN = Canonical Ltd. Live Patch Signing
+        Validity
+            Not Before: Jul 18 23:41:27 2016 GMT
+            Not After : Jul 16 23:41:27 2026 GMT
+        Subject: CN = Canonical Ltd. Live Patch Signing
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                RSA Public-Key: (4096 bit)
+                Modulus:
+                    00:bd:74:ee:72:b3:4a:ab:e6:31:e8:29:24:c2:bd:
+                    46:98:32:c0:39:ee:a3:fb:8a:ad:fe:ab:1a:5b:a3:
+                    2e:a1:80:db:79:61:9e:47:79:2c:75:57:a2:21:f0:
+                    93:f6:87:f2:9b:4b:9d:2f:b3:58:61:28:3c:41:70:
+                    13:16:a1:72:90:c9:d5:16:71:7c:e0:30:f9:28:5e:
+                    48:20:36:00:69:b7:59:9f:a3:ec:a8:eb:55:41:9f:
+                    38:1e:22:4a:57:20:f4:83:59:49:c5:00:93:d3:33:
+                    02:92:d1:fc:f0:84:3b:4a:5b:8f:b6:73:9a:89:fa:
+                    30:1e:e6:2a:68:f2:91:ef:59:57:3d:dc:1c:52:6f:
+                    5e:e6:9b:b5:b8:7c:98:c9:13:d1:39:68:01:67:91:
+                    e0:d3:67:72:16:0a:5e:16:83:45:31:4f:b5:2b:b3:
+                    f6:40:86:89:3a:84:6e:6f:16:61:bc:70:84:be:5a:
+                    13:36:7b:82:ea:07:19:fc:18:c1:16:c6:32:0b:7d:
+                    2c:6b:c4:21:b9:38:6b:31:dc:d9:0c:ad:56:40:68:
+                    7c:e3:c6:64:8e:bf:1c:e0:72:3e:6c:db:d2:73:79:
+                    da:d7:c5:2f:5d:04:7d:b0:07:1e:95:dd:2a:47:5e:
+                    bf:3e:3a:c8:66:f6:67:0f:d4:2a:f1:e2:71:59:d2:
+                    6c:7b:a0:37:ac:e6:97:80:30:13:97:48:d5:74:fc:
+                    38:68:e4:57:cb:99:69:5a:84:27:ac:98:51:e4:64:
+                    bd:91:62:e8:58:27:06:2a:b9:0b:b8:08:e5:e5:b4:
+                    51:a7:a2:10:df:4e:07:6c:a0:3b:96:f2:6e:df:75:
+                    8c:97:1e:64:a0:9a:86:9b:98:26:f9:d8:b7:de:5b:
+                    21:b7:af:89:01:a3:f7:98:6b:da:19:ba:86:ef:ef:
+                    f1:ce:bb:2f:89:ed:c0:b6:1b:e5:5b:f8:90:11:9a:
+                    52:93:e9:be:f7:35:b9:08:cb:ba:c3:ed:2f:73:af:
+                    cc:96:07:55:b5:de:f6:03:f6:f1:89:f9:21:40:76:
+                    c1:69:f2:61:cc:9a:94:df:9c:ec:6a:65:38:be:d1:
+                    4e:2a:87:c7:2f:3e:53:ae:8b:9f:54:a1:09:59:64:
+                    25:aa:a9:d8:44:a9:a8:a0:71:e1:32:aa:4c:32:fd:
+                    44:28:cc:9c:6f:8e:db:81:7e:6f:fa:00:56:c5:e5:
+                    03:46:63:fb:8e:71:8d:e3:13:91:9f:ac:60:3e:64:
+                    f3:df:25:34:09:fa:2d:96:9f:16:05:ea:93:f5:e6:
+                    00:08:27:32:7b:3c:bd:ee:70:24:6c:3b:55:e9:db:
+                    f4:10:2d:20:06:b4:ca:e9:29:65:55:ad:f6:52:54:
+                    5f:e5:a3
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:FALSE
+            X509v3 Key Usage: 
+                Digital Signature
+            X509v3 Subject Key Identifier: 
+                14:DF:34:D1:A8:7C:F3:76:25:AB:EC:03:9E:F2:BF:52:12:49:B9:69
+            X509v3 Authority Key Identifier: 
+                keyid:14:DF:34:D1:A8:7C:F3:76:25:AB:EC:03:9E:F2:BF:52:12:49:B9:69
+
+    Signature Algorithm: sha512WithRSAEncryption
+         30:e7:48:02:37:e9:28:cf:04:a2:4d:5c:fa:d8:4e:c9:76:c7:
+         14:3f:bd:2c:51:3d:33:f0:1a:bc:49:f1:47:95:8f:69:d8:a9:
+         54:14:44:6c:4d:9f:55:82:08:1e:c6:5b:d5:91:d9:bc:2e:b0:
+         af:d6:25:65:74:96:aa:36:de:ae:31:a8:11:f2:a4:2c:5a:e1:
+         4f:73:f8:4a:c3:35:b0:76:96:71:f2:b5:7d:4b:75:ee:5d:bf:
+         86:a5:ba:0b:a9:52:cb:ec:ab:e5:23:4b:f2:74:55:28:17:1e:
+         b3:ac:27:ad:45:13:6e:69:b3:5a:be:42:36:29:48:db:e7:5c:
+         22:58:a0:90:82:2c:2a:21:2b:db:f4:64:b7:91:5d:1f:2c:48:
+         a4:1a:85:e3:86:a5:aa:19:cd:19:e8:a5:fb:a3:7b:94:77:48:
+         25:a4:cf:a0:cf:71:82:5c:6f:71:22:7c:d6:97:a0:53:bb:ec:
+         30:f6:cb:16:fb:7b:fd:16:94:7a:53:6e:bd:04:64:a2:01:10:
+         9f:f0:5b:b5:a6:73:41:9d:5f:6f:45:73:0d:05:f7:30:6d:39:
+         90:b6:7d:55:7d:4c:2f:ae:5f:38:56:2f:8b:df:f4:bf:12:06:
+         93:6e:0d:02:23:bf:71:91:57:88:e8:bd:62:72:99:00:40:29:
+         1e:c9:13:11:da:7e:8e:e1:d2:a5:0d:bf:f7:d6:ec:01:0d:89:
+         41:cd:d5:dc:d2:f7:5f:33:0d:4c:2f:85:b7:85:b7:81:e4:17:
+         29:f0:74:cf:0e:15:8c:1a:50:0b:08:63:1a:91:4f:e7:76:97:
+         f1:d4:3b:7e:72:d4:c5:45:58:0c:6a:e9:0d:f2:85:d8:91:1e:
+         37:bd:78:e3:39:4d:2e:fd:85:31:c1:a6:3b:6a:cc:2c:53:72:
+         1d:8e:7b:f0:e6:76:86:09:6f:1a:f3:e4:a1:e2:dd:76:5f:b0:
+         8c:e2:2a:54:5d:c1:88:49:90:10:15:42:7d:05:24:53:8c:54:
+         ff:48:18:1a:36:e3:31:d3:54:32:78:0d:fe:f2:3d:aa:0d:37:
+         15:84:b4:36:47:31:e8:85:6e:0b:58:38:ff:21:91:09:c9:a8:
+         43:a3:ea:60:cb:7e:ed:f7:41:6f:4e:91:c1:fd:77:46:e7:d4:
+         e7:86:c0:1b:fd:50:6c:aa:be:00:b3:63:02:ff:4e:c7:a5:57:
+         6e:29:64:e9:54:d5:30:63:38:5f:2d:5a:db:49:5f:14:14:22:
+         d2:81:1f:61:9e:ee:ee:16:66:d6:bc:bd:ac:1b:5c:fb:38:31:
+         95:33:2e:84:6e:7a:de:ee:b9:fc:97:17:06:13:bf:70:1c:6e:
+         76:ed:66:38:e2:70:08:00
+-----BEGIN CERTIFICATE-----
+MIIFODCCAyCgAwIBAgIJAMd+UWocJc1AMA0GCSqGSIb3DQEBDQUAMCwxKjAoBgNV
+BAMMIUNhbm9uaWNhbCBMdGQuIExpdmUgUGF0Y2ggU2lnbmluZzAeFw0xNjA3MTgy
+MzQxMjdaFw0yNjA3MTYyMzQxMjdaMCwxKjAoBgNVBAMMIUNhbm9uaWNhbCBMdGQu
+IExpdmUgUGF0Y2ggU2lnbmluZzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
+ggIBAL107nKzSqvmMegpJMK9RpgywDnuo/uKrf6rGlujLqGA23lhnkd5LHVXoiHw
+k/aH8ptLnS+zWGEoPEFwExahcpDJ1RZxfOAw+SheSCA2AGm3WZ+j7KjrVUGfOB4i
+Slcg9INZScUAk9MzApLR/PCEO0pbj7Zzmon6MB7mKmjyke9ZVz3cHFJvXuabtbh8
+mMkT0TloAWeR4NNnchYKXhaDRTFPtSuz9kCGiTqEbm8WYbxwhL5aEzZ7guoHGfwY
+wRbGMgt9LGvEIbk4azHc2QytVkBofOPGZI6/HOByPmzb0nN52tfFL10EfbAHHpXd
+Kkdevz46yGb2Zw/UKvHicVnSbHugN6zml4AwE5dI1XT8OGjkV8uZaVqEJ6yYUeRk
+vZFi6FgnBiq5C7gI5eW0UaeiEN9OB2ygO5bybt91jJceZKCahpuYJvnYt95bIbev
+iQGj95hr2hm6hu/v8c67L4ntwLYb5Vv4kBGaUpPpvvc1uQjLusPtL3OvzJYHVbXe
+9gP28Yn5IUB2wWnyYcyalN+c7GplOL7RTiqHxy8+U66Ln1ShCVlkJaqp2ESpqKBx
+4TKqTDL9RCjMnG+O24F+b/oAVsXlA0Zj+45xjeMTkZ+sYD5k898lNAn6LZafFgXq
+k/XmAAgnMns8ve5wJGw7Venb9BAtIAa0yukpZVWt9lJUX+WjAgMBAAGjXTBbMAwG
+A1UdEwEB/wQCMAAwCwYDVR0PBAQDAgeAMB0GA1UdDgQWBBQU3zTRqHzzdiWr7AOe
+8r9SEkm5aTAfBgNVHSMEGDAWgBQU3zTRqHzzdiWr7AOe8r9SEkm5aTANBgkqhkiG
+9w0BAQ0FAAOCAgEAMOdIAjfpKM8Eok1c+thOyXbHFD+9LFE9M/AavEnxR5WPadip
+VBREbE2fVYIIHsZb1ZHZvC6wr9YlZXSWqjberjGoEfKkLFrhT3P4SsM1sHaWcfK1
+fUt17l2/hqW6C6lSy+yr5SNL8nRVKBces6wnrUUTbmmzWr5CNilI2+dcIligkIIs
+KiEr2/Rkt5FdHyxIpBqF44alqhnNGeil+6N7lHdIJaTPoM9xglxvcSJ81pegU7vs
+MPbLFvt7/RaUelNuvQRkogEQn/BbtaZzQZ1fb0VzDQX3MG05kLZ9VX1ML65fOFYv
+i9/0vxIGk24NAiO/cZFXiOi9YnKZAEApHskTEdp+juHSpQ2/99bsAQ2JQc3V3NL3
+XzMNTC+Ft4W3geQXKfB0zw4VjBpQCwhjGpFP53aX8dQ7fnLUxUVYDGrpDfKF2JEe
+N7144zlNLv2FMcGmO2rMLFNyHY578OZ2hglvGvPkoeLddl+wjOIqVF3BiEmQEBVC
+fQUkU4xU/0gYGjbjMdNUMngN/vI9qg03FYS0Nkcx6IVuC1g4/yGRCcmoQ6PqYMt+
+7fdBb06Rwf13RufU54bAG/1QbKq+ALNjAv9Ox6VXbilk6VTVMGM4Xy1a20lfFBQi
+0oEfYZ7u7hZm1ry9rBtc+zgxlTMuhG563u65/JcXBhO/cBxudu1mOOJwCAA=
+-----END CERTIFICATE-----
--- linux-xilinx-zynqmp-5.4.0.orig/debian/certs/ubuntu-drivers-all.pem
+++ linux-xilinx-zynqmp-5.4.0/debian/certs/ubuntu-drivers-all.pem
@@ -0,0 +1,125 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            e9:df:13:0f:92:92:a9:b7
+        Signature Algorithm: sha512WithRSAEncryption
+        Issuer: C = GB, ST = Isle of Man, L = Douglas, O = Canonical Ltd., CN = Canonical Ltd. Kernel Module Signing
+        Validity
+            Not Before: May 31 16:06:09 2016 GMT
+            Not After : May 29 16:06:09 2026 GMT
+        Subject: C = GB, ST = Isle of Man, L = Douglas, O = Canonical Ltd., CN = Canonical Ltd. Kernel Module Signing
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                RSA Public-Key: (4096 bit)
+                Modulus:
+                    00:b3:b0:4f:c6:0a:77:8b:f9:d1:53:33:34:d2:80:
+                    b5:63:6f:e1:f6:a2:83:99:d5:b6:b1:e4:99:91:fa:
+                    6c:19:c6:d0:91:2a:b9:7d:b5:98:a6:0d:28:01:b8:
+                    7c:8e:aa:38:ec:51:37:33:96:f0:b0:9b:8d:86:5f:
+                    67:23:69:2f:d7:c2:f3:fb:c5:d7:f9:04:ff:f2:e5:
+                    61:68:b7:29:b9:c6:8e:4b:4d:2d:8f:92:0c:00:b3:
+                    a3:d2:5a:08:64:cd:f2:09:0b:a5:0e:e6:64:75:d5:
+                    41:f4:4d:49:3a:0d:dc:b9:27:8e:c4:d6:b1:df:8f:
+                    6c:f0:e4:f7:31:cb:a9:04:a1:f9:a7:aa:15:da:59:
+                    03:4d:46:14:d0:dd:bf:e0:f5:9e:f0:71:0c:70:78:
+                    2b:08:fb:e0:b6:68:a4:74:12:9d:f7:f2:64:88:17:
+                    2a:8a:ed:1a:91:b5:6c:13:bd:4c:10:0a:0b:72:0b:
+                    90:db:7d:f3:78:44:4c:d2:a5:41:f7:1c:77:7d:5a:
+                    8a:54:bc:8f:fe:b7:ee:e1:bc:59:37:c4:d4:e8:14:
+                    d0:5b:42:9b:04:00:8e:6d:83:8a:25:21:5b:08:c4:
+                    7b:b2:d9:99:52:c9:5e:59:6d:c4:aa:52:59:e2:e4:
+                    2f:7e:7e:ac:05:01:99:bf:13:72:b7:45:c5:17:da:
+                    8a:d5:3e:71:73:2e:d8:aa:e6:eb:5a:d0:9a:c4:93:
+                    f3:be:eb:d2:47:25:34:16:29:fa:dd:9a:2f:b1:20:
+                    e5:41:4e:ed:ea:51:7c:23:80:ba:3d:b5:3a:0b:8c:
+                    9c:85:48:6c:3c:8b:29:2f:2f:12:c7:52:34:02:ea:
+                    0f:ac:53:23:3c:f8:3e:40:1b:30:63:e9:2d:e6:f6:
+                    58:cc:51:f9:eb:08:4a:b4:c7:16:80:d1:8b:c2:64:
+                    6a:71:a9:70:31:a4:a7:3a:c0:93:99:1b:0e:42:c1:
+                    00:6d:43:27:99:6c:e5:fd:23:16:c1:8e:b5:66:17:
+                    2b:4c:53:5a:6d:1e:96:16:13:6a:c6:d4:85:5b:74:
+                    2e:ce:7c:45:2f:ad:cb:75:9e:5e:91:bd:9a:6a:86:
+                    1a:06:bd:39:be:a3:50:56:ea:e1:f6:e3:95:69:d7:
+                    31:e4:66:f7:36:b5:51:c2:22:b4:9c:74:9c:44:0b:
+                    0e:16:5f:53:f0:23:c6:b9:40:bd:d6:b8:7d:1b:f6:
+                    73:f6:27:e7:c0:e3:65:a0:58:ab:5c:59:b7:80:8c:
+                    8c:04:b4:a9:ae:a0:51:40:10:3b:63:59:49:87:d1:
+                    9b:df:a3:8c:c4:2e:eb:70:c1:0a:18:1f:cb:22:c2:
+                    f2:4a:65:0d:e5:81:74:d8:ce:72:c6:35:be:ba:63:
+                    72:c4:f9
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:FALSE
+            X509v3 Key Usage: 
+                Digital Signature
+            X509v3 Subject Key Identifier: 
+                88:F7:52:E5:60:A1:E0:73:7E:31:16:3A:46:6A:D7:B7:0A:85:0C:19
+            X509v3 Authority Key Identifier: 
+                keyid:88:F7:52:E5:60:A1:E0:73:7E:31:16:3A:46:6A:D7:B7:0A:85:0C:19
+
+    Signature Algorithm: sha512WithRSAEncryption
+         04:85:16:27:58:ba:71:28:57:86:7b:c2:83:db:e5:72:6f:1e:
+         b2:1c:63:b0:db:ad:c0:42:96:c0:4f:65:f6:35:4d:c0:07:0d:
+         46:be:d3:1e:ec:f1:22:18:2a:18:5d:bb:69:a6:a6:d4:0d:c3:
+         57:03:b9:e7:45:49:28:ca:6d:98:17:68:97:cb:7b:36:81:0a:
+         37:9e:34:79:f3:e1:0e:5b:77:43:bb:5a:a5:45:b7:16:50:86:
+         fd:12:a4:96:0f:15:19:09:1c:e1:fa:80:a5:80:09:be:bb:c8:
+         26:0b:3e:de:03:d2:c2:18:a4:8d:0d:de:c5:32:82:0b:fb:75:
+         55:66:1a:2a:bb:e4:bd:25:91:20:15:d4:be:b8:3f:53:e3:fb:
+         a8:c3:55:e3:d5:e7:82:18:95:df:39:09:a7:fc:89:6e:b4:1c:
+         aa:2d:e8:67:c2:0d:34:34:3e:f9:fa:0b:ce:81:92:11:ae:12:
+         0a:fe:35:63:ce:46:29:c4:2b:4f:cb:4e:05:0a:a1:11:e2:35:
+         f6:5a:5d:b5:e8:d2:6f:4c:fc:3d:24:a6:03:4b:dd:98:6b:f2:
+         71:58:16:1d:a5:25:ef:d9:06:7c:e8:db:7b:88:6a:89:5c:59:
+         01:92:64:db:44:08:63:6c:7c:32:d6:55:98:63:09:26:61:67:
+         0a:fe:5d:ee:fd:23:59:b3:4d:91:c1:4d:41:8b:cd:20:58:fa:
+         2d:45:e5:bd:1d:69:5c:03:a0:49:a6:97:54:13:b6:c9:e0:f8:
+         56:83:a1:2a:c3:f4:6c:fd:ab:20:ca:3d:9c:95:c0:cf:04:bb:
+         46:39:cf:34:81:65:45:27:64:01:7d:62:b3:b8:72:ea:10:d5:
+         0f:53:7d:39:88:25:09:6f:8c:bc:e0:49:bb:39:e2:0e:8d:cf:
+         56:4d:c1:82:6d:87:d2:e7:fc:c0:9f:a7:65:60:d2:6c:65:18:
+         59:38:6e:d0:9c:d7:c3:81:9a:9a:29:8f:83:84:c3:b5:44:ff:
+         28:ac:13:17:64:f2:26:13:d9:55:06:b7:69:68:7c:bf:ec:d1:
+         8c:ef:b7:da:76:e1:07:73:c6:31:62:31:cb:b6:e1:e7:7f:0c:
+         c3:f7:4c:52:be:25:36:8e:a1:bb:60:02:c3:cb:3e:6f:29:fc:
+         7f:6a:fa:f8:ec:0a:df:49:e2:57:0e:bc:bd:93:c3:1b:d5:36:
+         8a:ff:d8:1b:17:c7:1f:cb:69:00:d2:54:9e:ad:61:89:92:95:
+         11:f8:ea:17:83:9f:9b:09:7d:b8:94:a4:ea:f5:ae:ea:dc:dd:
+         62:b9:9e:68:9c:18:ec:19:c4:13:08:c8:b1:62:ab:8e:84:69:
+         11:3c:da:ea:0d:b7:22:bd
+-----BEGIN CERTIFICATE-----
+MIIF2jCCA8KgAwIBAgIJAOnfEw+Skqm3MA0GCSqGSIb3DQEBDQUAMH0xCzAJBgNV
+BAYTAkdCMRQwEgYDVQQIDAtJc2xlIG9mIE1hbjEQMA4GA1UEBwwHRG91Z2xhczEX
+MBUGA1UECgwOQ2Fub25pY2FsIEx0ZC4xLTArBgNVBAMMJENhbm9uaWNhbCBMdGQu
+IEtlcm5lbCBNb2R1bGUgU2lnbmluZzAeFw0xNjA1MzExNjA2MDlaFw0yNjA1Mjkx
+NjA2MDlaMH0xCzAJBgNVBAYTAkdCMRQwEgYDVQQIDAtJc2xlIG9mIE1hbjEQMA4G
+A1UEBwwHRG91Z2xhczEXMBUGA1UECgwOQ2Fub25pY2FsIEx0ZC4xLTArBgNVBAMM
+JENhbm9uaWNhbCBMdGQuIEtlcm5lbCBNb2R1bGUgU2lnbmluZzCCAiIwDQYJKoZI
+hvcNAQEBBQADggIPADCCAgoCggIBALOwT8YKd4v50VMzNNKAtWNv4faig5nVtrHk
+mZH6bBnG0JEquX21mKYNKAG4fI6qOOxRNzOW8LCbjYZfZyNpL9fC8/vF1/kE//Ll
+YWi3KbnGjktNLY+SDACzo9JaCGTN8gkLpQ7mZHXVQfRNSToN3LknjsTWsd+PbPDk
+9zHLqQSh+aeqFdpZA01GFNDdv+D1nvBxDHB4Kwj74LZopHQSnffyZIgXKortGpG1
+bBO9TBAKC3ILkNt983hETNKlQfccd31ailS8j/637uG8WTfE1OgU0FtCmwQAjm2D
+iiUhWwjEe7LZmVLJXlltxKpSWeLkL35+rAUBmb8TcrdFxRfaitU+cXMu2Krm61rQ
+msST877r0kclNBYp+t2aL7Eg5UFO7epRfCOAuj21OguMnIVIbDyLKS8vEsdSNALq
+D6xTIzz4PkAbMGPpLeb2WMxR+esISrTHFoDRi8JkanGpcDGkpzrAk5kbDkLBAG1D
+J5ls5f0jFsGOtWYXK0xTWm0elhYTasbUhVt0Ls58RS+ty3WeXpG9mmqGGga9Ob6j
+UFbq4fbjlWnXMeRm9za1UcIitJx0nEQLDhZfU/AjxrlAvda4fRv2c/Yn58DjZaBY
+q1xZt4CMjAS0qa6gUUAQO2NZSYfRm9+jjMQu63DBChgfyyLC8kplDeWBdNjOcsY1
+vrpjcsT5AgMBAAGjXTBbMAwGA1UdEwEB/wQCMAAwCwYDVR0PBAQDAgeAMB0GA1Ud
+DgQWBBSI91LlYKHgc34xFjpGate3CoUMGTAfBgNVHSMEGDAWgBSI91LlYKHgc34x
+FjpGate3CoUMGTANBgkqhkiG9w0BAQ0FAAOCAgEABIUWJ1i6cShXhnvCg9vlcm8e
+shxjsNutwEKWwE9l9jVNwAcNRr7THuzxIhgqGF27aaam1A3DVwO550VJKMptmBdo
+l8t7NoEKN540efPhDlt3Q7tapUW3FlCG/RKklg8VGQkc4fqApYAJvrvIJgs+3gPS
+whikjQ3exTKCC/t1VWYaKrvkvSWRIBXUvrg/U+P7qMNV49XnghiV3zkJp/yJbrQc
+qi3oZ8INNDQ++foLzoGSEa4SCv41Y85GKcQrT8tOBQqhEeI19lpdtejSb0z8PSSm
+A0vdmGvycVgWHaUl79kGfOjbe4hqiVxZAZJk20QIY2x8MtZVmGMJJmFnCv5d7v0j
+WbNNkcFNQYvNIFj6LUXlvR1pXAOgSaaXVBO2yeD4VoOhKsP0bP2rIMo9nJXAzwS7
+RjnPNIFlRSdkAX1is7hy6hDVD1N9OYglCW+MvOBJuzniDo3PVk3Bgm2H0uf8wJ+n
+ZWDSbGUYWThu0JzXw4GamimPg4TDtUT/KKwTF2TyJhPZVQa3aWh8v+zRjO+32nbh
+B3PGMWIxy7bh538Mw/dMUr4lNo6hu2ACw8s+byn8f2r6+OwK30niVw68vZPDG9U2
+iv/YGxfHH8tpANJUnq1hiZKVEfjqF4Ofmwl9uJSk6vWu6tzdYrmeaJwY7BnEEwjI
+sWKrjoRpETza6g23Ir0=
+-----END CERTIFICATE-----
--- linux-xilinx-zynqmp-5.4.0.orig/debian/changelog
+++ linux-xilinx-zynqmp-5.4.0/debian/changelog
@@ -0,0 +1,29327 @@
+linux-xilinx-zynqmp (5.4.0-1075.79) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1075.79 -proposed tracker (LP: #2144155)
+
+  [ Ubuntu: 5.4.0-228.248 ]
+
+  * focal/linux: 5.4.0-228.248 -proposed tracker (LP: #2144157)
+  * CVE-2024-46816
+    - drm/amd/display: Stop amdgpu_dm initialize when link nums greater than
+      max_links
+  * CVE-2022-49046
+    - i2c: dev: check return value when calling dev_set_name()
+  * CVE-2025-37849
+    - KVM: arm/arm64: vgic: Reset base address on kvm_vgic_dist_destroy()
+    - KVM: arm64: vgic: Add a non-locking primitive for
+      kvm_vgic_vcpu_destroy()
+    - KVM: arm64: vgic: Force vcpu vgic teardown on vcpu destroy
+    - KVM: arm64: Tear down vGIC on failed vCPU creation
+  * CVE-2026-23074
+    - net/sched: Enforce that teql can only be used as root qdisc
+  * CVE-2026-23060
+    - crypto: authencesn - reject too-short AAD (assoclen<8) to match ESP/ESN
+      spec
+
+ -- Changwei Zou <changwei.zou@canonical.com>  Thu, 19 Mar 2026 14:24:30 +1100
+
+linux-xilinx-zynqmp (5.4.0-1074.78) focal; urgency=medium
+
+  [ Ubuntu: 5.4.0-227.247 ]
+
+  * Miscellaneous upstream changes
+    - apparmor: validate DFA start states are in bounds in unpack_pdb
+    - apparmor: fix memory leak in verify_header
+    - apparmor: replace recursive profile removal with iterative approach
+    - apparmor: fix: limit the number of levels of policy namespaces
+    - apparmor: fix side-effect bug in match_char() macro usage
+    - apparmor: fix missing bounds check on DEFAULT table in verify_dfa()
+    - apparmor: fix unprivileged local user can do privileged policy
+      management
+    - apparmor: fix differential encoding verification
+    - apparmor: fix race on rawdata dereference
+    - apparmor: fix race between freeing data and fs accessing it
+
+ -- Mehmet Basaran <mehmet.basaran@canonical.com>  Tue, 10 Mar 2026 23:50:52 +0300
+
+linux-xilinx-zynqmp (5.4.0-1073.77) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1073.77 -proposed tracker (LP: #2140844)
+
+  [ Ubuntu: 5.4.0-226.246 ]
+
+  * focal/linux: 5.4.0-226.246 -proposed tracker (LP: #2140846)
+  * CVE-2022-49072
+    - gpio: Restrict usage of GPIO chip irq members before initialization
+    - gpio: Request interrupts after IRQ is initialized
+  * CVE-2021-47599
+    - btrfs: convert latest_bdev type to btrfs_device and rename
+    - btrfs: use latest_dev in btrfs_show_devname
+  * CVE-2022-48875
+    - wifi: mac80211: sdata can be NULL during AMPDU start
+  * ipsec_offload in rtnetlink.sh from kselftests.net fails on s390x
+    (LP: #1893921)
+    - SAUCE: Fix selftest/net/rtnetlink.sh for Big Endian
+    - SAUCE: Fix selftest/net/rtnetlink.sh for Big Endian (ip address)
+  * CVE-2024-56640
+    - net/smc: fix LGR and link use-after-free issue
+  * CVE-2025-21780
+    - drm/amdgpu: avoid buffer overflow attach in smu_sys_set_pp_table()
+  * CVE-2022-49267
+    - mmc: core: use sysfs_emit() instead of sprintf()
+  * CVE-2024-49927
+    - x86/ioapic: Handle allocation failures gracefully
+  * statx09 in ubuntu_ltp_syscalls failed on Focal 5.4 (LP: #1966620)
+    - docs: fs-verity: document first supported kernel version
+    - statx: define STATX_ATTR_VERITY
+    - ext4: support STATX_ATTR_VERITY
+    - f2fs: support STATX_ATTR_VERITY
+    - docs: fs-verity: mention statx() support
+  * CVE-2025-40215 // CVE-2025-40256
+    - xfrm: delete x->tunnel as we delete x
+    - xfrm: also call xfrm_state_delete_tunnel at destroy time for states that
+      were never added
+
+ -- Stewart Hore <stewart.hore@canonical.com>  Wed, 11 Feb 2026 16:44:55 +1100
+
+linux-xilinx-zynqmp (5.4.0-1072.76) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1072.76 -proposed tracker (LP: #2137981)
+
+  [ Ubuntu: 5.4.0-225.245 ]
+
+  * focal/linux: 5.4.0-225.245 -proposed tracker (LP: #2137983)
+  * CVE-2022-49698
+    - netfilter: use get_random_u32 instead of prandom
+  * CVE-2025-40019
+    - crypto: essiv - Check ssize for decryption and in-place encryption
+  * Focal generic kernel FTBFS when CONFIG_PROVE_LOCKING = y (LP: #2130776)
+    - SAUCE: Use current->hardirqs_enabled in lockdep preemption asserts
+  * CVE-2025-21726
+    - padata: add pd get/put refcnt helper
+    - padata: avoid UAF for reorder_work
+    - padata: do not leak refcount in reorder_work
+
+ -- Stewart Hore <stewart.hore@canonical.com>  Thu, 22 Jan 2026 11:18:44 +1100
+
+linux-xilinx-zynqmp (5.4.0-1071.75) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1071.75 -proposed tracker (LP: #2131366)
+
+  [ Ubuntu: 5.4.0-224.244 ]
+
+  * focal/linux: 5.4.0-224.244 -proposed tracker (LP: #2131368)
+  * CVE-2025-38666
+    - net: appletalk: fix kerneldoc warnings
+    - net: appletalk: Fix use-after-free in AARP proxy probe
+  * CVE-2024-50196
+    - pinctrl: ocelot: fix system hang on level based interrupts
+  * CVE-2024-49935
+    - ACPI: PAD: fix crash in exit_round_robin()
+  * CVE-2022-49390
+    - macsec: fix UAF bug for real_dev
+  * CVE-2025-37958
+    - mm/huge_memory: fix dereferencing invalid pmd migration entry
+  * CVE-2024-50095
+    - IB/mad: Issue complete whenever decrements agent refcount
+    - RDMA/mad: Improve handling of timed out WRs of mad agent
+  * CVE-2025-39964
+    - crypto: af_alg - Disallow concurrent writes in af_alg_sendmsg
+    - crypto: af_alg - Fix incorrect boolean values in af_alg_ctx
+  * CVE-2024-50067
+    - uprobes: encapsulate preparation of uprobe args buffer
+    - uprobe: avoid out-of-bounds memory access of fetching args
+  * CVE-2024-53090
+    - afs: Fix lock recursion
+  * CVE-2022-49026
+    - e100: Fix possible use after free in e100_xmit_prepare
+  * CVE-2025-21855
+    - ibmvnic: Don't reference skb after sending to VIOS
+  * CVE-2024-53218
+    - f2fs: fix race in concurrent f2fs_stop_gc_thread
+  * CVE-2024-47691
+    - f2fs: fix to avoid use-after-free in f2fs_stop_gc_thread()
+  * CVE-2025-40018
+    - ipvs: Defer ip_vs_ftp unregister during netns cleanup
+  * CVE-2025-39993
+    - media: imon: reorganize serialization
+    - media: rc: fix races with imon_disconnect()
+
+ -- Stewart Hore <stewart.hore@canonical.com>  Mon, 24 Nov 2025 14:06:32 +1100
+
+linux-xilinx-zynqmp (5.4.0-1070.74) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1070.74 -proposed tracker (LP: #2127327)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] zynqmp: Remove dwarfdump from Build-Depends
+
+  [ Ubuntu: 5.4.0-223.243 ]
+
+  * focal/linux: 5.4.0-223.243 -proposed tracker (LP: #2127329)
+  * VMSCAPE CVE-2025-40300 (LP: #2124105) // CVE-2025-40300
+    - Documentation/hw-vuln: Add VMSCAPE documentation
+    - x86/vmscape: Enumerate VMSCAPE bug
+    - x86/vmscape: Add conditional IBPB mitigation
+    - x86/vmscape: Enable the mitigation
+    - x86/bugs: Move cpu_bugs_smt_update() down
+    - x86/vmscape: Warn when STIBP is disabled with SMT
+    - x86/vmscape: Add old Intel CPUs to affected list
+  * VMSCAPE CVE-2025-40300 (LP: #2124105)
+    - [Config] Enable MITIGATION_VMSCAPE config
+  * CVE-2024-50061
+    - i3c: master: cdns: Fix use after free vulnerability in cdns_i3c_master
+      Driver Due to Race Condition
+  * CVE-2025-38352
+    - posix-cpu-timers: fix race between handle_posix_cpu_timers() and
+      posix_cpu_timer_del()
+  * CVE-2025-21727
+    - padata: fix UAF in padata_reorder
+  * CVE-2024-56664
+    - bpf, sockmap: Fix race between element replace and close()
+  * CVE-2023-52854
+    - padata: Fix refcnt handling in padata_free_shell()
+  * CVE-2025-37838
+    - HSI: ssi_protocol: Fix use after free vulnerability in ssi_protocol
+      Driver Due to Race Condition
+  * CVE-2024-35867
+    - smb: client: fix potential UAF in cifs_stats_proc_show()
+
+ -- Stewart Hore <stewart.hore@canonical.com>  Thu, 16 Oct 2025 15:48:15 +1100
+
+linux-xilinx-zynqmp (5.4.0-1069.73) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1069.73 -proposed tracker (LP: #2124153)
+
+  [ Ubuntu: 5.4.0-222.242 ]
+
+  * focal/linux: 5.4.0-222.242 -proposed tracker (LP: #2124155)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync git-ubuntu-log
+  * sources list generation using dwarfdump takes up to 0.5hr in build process
+    (LP: #2104911)
+    - [Packaging] Don't generate list of source files
+  * CVE-2025-37785
+    - ext4: optimize __ext4_check_dir_entry()
+    - ext4: fix OOB read when checking dotdot dir
+  * CVE-2025-21796
+    - nfsd: clear acl_access/acl_default after releasing them
+  * CVE-2025-38617
+    - net/packet: fix a race in packet_set_ring() and packet_notifier()
+  * CVE-2025-38618
+    - vsock: Do not allow binding to VMADDR_PORT_ANY
+  * CVE-2025-38477
+    - net/sched: sch_qfq: Fix race condition on qfq_aggregate
+    - net/sched: sch_qfq: Avoid triggering might_sleep in atomic context in
+      qfq_delete_class
+
+ -- Stewart Hore <stewart.hore@canonical.com>  Wed, 24 Sep 2025 15:11:43 +1000
+
+linux-xilinx-zynqmp (5.4.0-1068.72) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1068.72 -proposed tracker (LP: #2119816)
+
+  [ Ubuntu: 5.4.0-221.241 ]
+
+  * focal/linux: 5.4.0-221.241 -proposed tracker (LP: #2119818)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update annotations scripts
+  * CVE-2025-38350
+    - net/sched: Always pass notifications when child class becomes empty
+  * CVE-2024-57996 // CVE-2025-37752
+    - net_sched: sch_sfq: move the limit validation
+
+ -- Wei-Lin Chang <weilin.chang@canonical.com>  Tue, 19 Aug 2025 10:50:11 +0800
+
+linux-xilinx-zynqmp (5.4.0-1067.71) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1067.71 -proposed tracker (LP: #2116504)
+
+  [ Ubuntu: 5.4.0-220.240 ]
+
+  * focal/linux: 5.4.0-220.240 -proposed tracker (LP: #2116506)
+  * CVE-2023-52975
+    - scsi: iscsi: Move pool freeing
+    - scsi: iscsi_tcp: Fix UAF during logout when accessing the shost
+      ipaddress
+  * CVE-2023-52757
+    - smb: client: fix potential deadlock when releasing mids
+  * CVE-2025-38083
+    - net_sched: prio: fix a race in prio_tune()
+  * CVE-2024-49950
+    - Bluetooth: L2CAP: Fix uaf in l2cap_connect
+    - Bluetooth: hci_core: Fix calling mgmt_device_connected
+  * CVE-2024-50073
+    - tty: n_gsm: Fix use-after-free in gsm_cleanup_mux
+  * CVE-2025-37797
+    - net_sched: hfsc: Fix a UAF vulnerability in class handling
+  * CVE-2024-38541
+    - of: module: add buffer overflow check in of_modalias()
+
+ -- Wei-Lin Chang <weilin.chang@canonical.com>  Wed, 23 Jul 2025 16:16:30 +0800
+
+linux-xilinx-zynqmp (5.4.0-1066.70) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1066.70 -proposed tracker (LP: #2114446)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update variants
+
+  [ Ubuntu: 5.4.0-219.239 ]
+
+  * focal/linux: 5.4.0-219.239 -proposed tracker (LP: #2114448)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update variants
+    - [Packaging] update annotations scripts
+  * CVE-2025-37798
+    - sch_htb: make htb_qlen_notify() idempotent
+    - sch_htb: make htb_deactivate() idempotent
+    - sch_drr: make drr_qlen_notify() idempotent
+    - sch_hfsc: make hfsc_qlen_notify() idempotent
+    - sch_qfq: make qfq_qlen_notify() idempotent
+    - codel: remove sch->q.qlen check before qdisc_tree_reduce_backlog()
+  * CVE-2024-53051
+    - drm/i915/hdcp: Add encoder check in intel_hdcp_get_capability
+  * CVE-2025-37997
+    - netfilter: ipset: fix region locking in hash types
+  * CVE-2025-37890
+    - net_sched: hfsc: Fix a UAF vulnerability in class with netem as child
+      qdisc
+    - sch_hfsc: Fix qlen accounting bug when using peek in hfsc_enqueue()
+    - net_sched: hfsc: Address reentrant enqueue adding class to eltree twice
+  * CVE-2024-46787
+    - userfaultfd: fix checks for huge PMDs
+  * CVE-2025-37782
+    - Revert "UBUNTU: SAUCE: fs: hfs/hfsplus: add key_len boundary check to
+      hfs_bnode_read_key"
+    - hfs/hfsplus: fix slab-out-of-bounds in hfs_bnode_read_key
+  * CVE-2025-37750
+    - smb: client: fix UAF in decryption with multichannel
+  * CVE-2024-53185
+    - smb: client: fix NULL ptr deref in crypto_aead_setkey()
+  * CVE-2024-50047
+    - smb: client: fix UAF in async decryption
+  * CVE-2024-56662
+    - acpi: nfit: vmalloc-out-of-bounds Read in acpi_nfit_ctl
+
+ -- Abdur Rahman <abdur.rahman@canonical.com>  Tue, 17 Jun 2025 23:41:23 -0400
+
+linux-xilinx-zynqmp (5.4.0-1065.69) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1065.69 -proposed tracker (LP: #2110874)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update update.conf
+
+  [ Ubuntu: 5.4.0-218.238 ]
+
+  * focal/linux: 5.4.0-218.238 -proposed tracker (LP: #2110876)
+  * Rotate the Canonical Livepatch key (LP: #2111244)
+    - [Config] Prepare for Canonical Livepatch key rotation
+  * CVE-2025-2312 cifs.upcall could access incorrect kerberos credentials cache
+    (LP: #2099914) // CVE-2025-2312
+    - CIFS: New mount option for cifs.upcall namespace resolution
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357)
+    - vlan: fix memory leak in vlan_newlink()
+    - clockevents/drivers/i8253: Fix stop sequence for timer 0
+    - sched/isolation: Prevent boot crash when the boot CPU is nohz_full
+    - Revert "UBUNTU: SAUCE: sctp: sysctl: pass right argument to container_of"
+    - Revert "sctp: sysctl: cookie_hmac_alg: avoid using current->nsproxy"
+    - Revert "sctp: sysctl: auth_enable: avoid using current->nsproxy"
+    - sctp: sysctl: cookie_hmac_alg: avoid using current->nsproxy
+    - sctp: sysctl: auth_enable: avoid using current->nsproxy
+    - pinctrl: bcm281xx: Fix incorrect regmap max_registers value
+    - netpoll: Fix use correct return type for ndo_start_xmit()
+    - netpoll: remove dev argument from netpoll_send_skb_on_dev()
+    - netpoll: move netpoll_send_skb() out of line
+    - netpoll: netpoll_send_skb() returns transmit status
+    - netpoll: hold rcu read lock in __netpoll_send_skb()
+    - drivers/hv: Replace binary semaphore with mutex
+    - Drivers: hv: vmbus: Don't release fb_mmio resource in vmbus_free_mmio()
+    - ipvs: prevent integer overflow in do_ip_vs_get_ctl()
+    - netfilter: nft_exthdr: fix offset with ipv4_find_option()
+    - net/mlx5e: Prevent bridge link show failure for non-eswitch-allowed devices
+    - nvme-fc: go straight to connecting state when initializing
+    - hrtimers: Mark is_migration_base() with __always_inline
+    - powercap: call put_device() on an error path in
+      powercap_register_control_type()
+    - ACPI: resource: IRQ override for Eluktronics MECH-17
+    - HID: intel-ish-hid: fix the length of MNG_SYNC_FW_CLOCK in doorbell
+    - s390/cio: Fix CHPID "configure" attribute caching
+    - ASoC: rsnd: don't indicate warning on rsnd_kctrl_accept_runtime()
+    - nvmet-rdma: recheck queue state is LIVE in state lock in recv done
+    - sctp: Fix undefined behavior in left shift operation
+    - nvme: only allow entering LIVE from CONNECTING state
+    - fuse: don't truncate cached, mutated symlink
+    - x86/irq: Define trace events conditionally
+    - drm/nouveau: Do not override forced connector status
+    - block: fix 'kmem_cache of name 'bio-108' already exists'
+    - USB: serial: ftdi_sio: add support for Altera USB Blaster 3
+    - USB: serial: option: add Telit Cinterion FE990B compositions
+    - USB: serial: option: fix Telit Cinterion FE990A name
+    - USB: serial: option: match on interface class for Telit FN990B
+    - drm/atomic: Filter out redundant DPMS calls
+    - qlcnic: fix memory leak issues in qlcnic_sriov_common.c
+    - drm/gma500: Add NULL check for pci_gfx_root in mid_get_vbt_data()
+    - ASoC: codecs: wm0010: Fix error handling path in wm0010_spi_probe()
+    - i2c: ali1535: Fix an error handling path in ali1535_probe()
+    - i2c: ali15x3: Fix an error handling path in ali15x3_probe()
+    - i2c: sis630: Fix an error handling path in sis630_probe()
+    - firmware: imx-scu: fix OF node leak in .probe()
+    - xfrm_output: Force software GSO only in tunnel mode
+    - RDMA/bnxt_re: Avoid clearing VLAN_ID mask in modify qp path
+    - RDMA/hns: Fix wrong value of max_sge_rd
+    - ipv6: Set errno after ip_fib_metrics_init() in ip6_route_info_create().
+    - net/neighbor: add missing policy for NDTPA_QUEUE_LENBYTES
+    - i2c: omap: fix IRQ storms
+    - drm/v3d: Don't run jobs that have errors flagged in its fence
+    - mmc: atmel-mci: Add missing clk_disable_unprepare()
+    - ARM: shmobile: smp: Enforce shmobile_smp_* alignment
+    - batman-adv: Ignore own maximum aggregation size during RX
+    - ALSA: usb-audio: Add quirk for Plantronics headsets to fix control names
+    - HID: hid-plantronics: Add mic mute mapping and generalize quirks
+    - ARM: 9350/1: fault: Implement copy_from_kernel_nofault_allowed()
+    - ARM: 9351/1: fault: Add "cut here" line for prefetch aborts
+    - ARM: Remove address checking for MMUless devices
+    - counter: stm32-lptimer-cnt: fix error handling when enabling
+    - tty: serial: 8250: Add some more device IDs
+    - net: usb: qmi_wwan: add Telit Cinterion FN990B composition
+    - net: usb: qmi_wwan: add Telit Cinterion FE990B composition
+    - net: usb: usbnet: restore usb%d name exception for local mac addresses
+    - serial: 8250_dma: terminate correct DMA in tx_dma_flush()
+    - x86/mm/pat: cpa-test: fix length for CPA_ARRAY test
+    - cpufreq: governor: Fix negative 'idle_time' handling in dbs_update()
+    - x86/fpu: Avoid copying dynamic FP state from init_task in
+      arch_dup_task_struct()
+    - x86/platform: Only allow CONFIG_EISA for 32-bit
+    - [Config] updateconfigs for HAVE_EISA
+    - selinux: Chain up tool resolving errors in install_policy.sh
+    - EDAC/ie31200: Fix the size of EDAC_MC_LAYER_CHIP_SELECT layer
+    - EDAC/ie31200: Fix the DIMM size mask for several SoCs
+    - EDAC/ie31200: Fix the error path order of ie31200_init()
+    - PM: sleep: Fix handling devices with direct_complete set on errors
+    - lockdep: Don't disable interrupts on RT in disable_irq_nosync_lockdep.*()
+    - perf/ring_buffer: Allow the EPOLLRDNORM flag for poll
+    - ALSA: hda/realtek: Always honor no_shutup_pins
+    - drm/mediatek: mtk_hdmi: Fix typo for aud_sampe_size member
+    - PCI/portdrv: Only disable pciehp interrupts early when needed
+    - PCI: Remove stray put_device() in pci_register_host_bridge()
+    - PCI: pciehp: Don't enable HPIE when resuming in poll mode
+    - fbdev: au1100fb: Move a variable assignment behind a null pointer check
+    - mdacon: rework dependency list
+    - fbdev: sm501fb: Add some geometry checks.
+    - clk: amlogic: gxbb: drop incorrect flag on 32k clock
+    - bpf: Use preempt_count() directly in bpf_send_signal_common()
+    - lib: 842: Improve error handling in sw842_compress()
+    - pinctrl: renesas: rza2: Fix missing of_node_put() call
+    - clk: rockchip: rk3328: fix wrong clk_ref_usb3otg parent
+    - IB/mad: Check available slots before posting receive WRs
+    - clk: amlogic: g12b: fix cluster A parent data
+    - clk: amlogic: gxbb: drop non existing 32k clock parent
+    - clk: amlogic: g12a: fix mmc A peripheral clock
+    - x86/entry: Fix ORC unwinder for PUSH_REGS with save_ret=1
+    - power: supply: max77693: Fix wrong conversion of charge input threshold
+      value
+    - mfd: sm501: Switch to BIT() to mitigate integer overflows
+    - x86/dumpstack: Fix inaccurate unwinding from exception stacks due to
+      misplaced assignment
+    - isofs: fix KMSAN uninit-value bug in do_isofs_readdir()
+    - coresight: catu: Fix number of pages while using 64k pages
+    - iio: accel: mma8452: Ensure error return on failure to matching oversampling
+      ratio
+    - perf units: Fix insufficient array space
+    - kexec: initialize ELF lowest address to ULONG_MAX
+    - perf python: Fixup description of sample.id event member
+    - perf python: Decrement the refcount of just created event on failure
+    - perf python: Check if there is space to copy all the event
+    - fs/procfs: fix the comment above proc_pid_wchan()
+    - objtool, media: dib8000: Prevent divide-by-zero in dib8000_set_dds()
+    - ring-buffer: Fix bytes_dropped calculation issue
+    - octeontx2-af: Fix mbox INTR handler when num VFs > 64
+    - sched/smt: Always inline sched_smt_active()
+    - wifi: iwlwifi: fw: allocate chained SG tables for dump
+    - affs: generate OFS sequence numbers starting at 1
+    - affs: don't write overlarge OFS data block size fields
+    - sched/deadline: Use online cpus for validating runtime
+    - locking/semaphore: Use wake_q to wake up processes outside lock critical
+      section
+    - can: statistics: use atomic access in hot path
+    - hwmon: (nct6775-core) Fix out of bounds access for NCT679{8,9}
+    - ntb: intel: Fix using link status DB's
+    - vsock: avoid timeout during connect() if the socket is closing
+    - ipv6: fix omitted netlink attributes when using RTEXT_FILTER_SKIP_STATS
+    - net: dsa: mv88e6xxx: propperly shutdown PPU re-enable timer on destroy
+    - can: flexcan: only change CAN state when link up in system PM
+    - ntb_perf: Delete duplicate dmaengine_unmap_put() call in perf_copy_chunk()
+    - x86/tsc: Always save/restore TSC sched_clock() on suspend/resume
+    - ACPI: resource: Skip IRQ override on ASUS Vivobook 14 X1404VAP
+    - mmc: sdhci-pxav3: set NEED_RSP_BUSY capability
+    - jfs: add index corruption check to DT_GETPAGE()
+    - Linux 5.4.292
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-39735
+    - jfs: fix slab-out-of-bounds read in ea_get()
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22035
+    - tracing: Fix use-after-free in print_graph_function_flags during tracer
+      switching
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22045
+    - x86/mm: Fix flush_tlb_range() when used for zapping normal PMDs
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22054
+    - arcnet: Add NULL check in com20020pci_probe()
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-38637
+    - net_sched: skbprio: Remove overly strict queue assertions
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22063
+    - netlabel: Fix NULL pointer exception caused by CALIPSO on IPv4 sockets
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2023-53034
+    - ntb_hw_switchtec: Fix shift-out-of-bounds in switchtec_ntb_mw_set_trans
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22071
+    - spufs: fix a leak in spufs_create_context()
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22073
+    - spufs: fix a leak on spufs_new_file() failure
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22079
+    - ocfs2: validate l_tree_depth to avoid out-of-bounds access
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22086
+    - RDMA/mlx5: Fix mlx5_poll_one() cur_qp update flow
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2024-58093
+    - PCI/ASPM: Fix link state exit during switch upstream function removal
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-23136
+    - thermal: int340x: Add NULL check for adev
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22020
+    - memstick: rtsx_usb_ms: Fix slab-use-after-free in rtsx_usb_ms_drv_remove
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22021
+    - netfilter: socket: Lookup orig tuple for IPv6 SNAT
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22018
+    - atm: Fix NULL pointer dereference
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-21996
+    - drm/radeon: fix uninitialized size issue in radeon_vce_cs_parse()
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22004
+    - net: atm: fix use after free in lec_send()
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22005
+    - ipv6: Fix memleak of nhc_pcpu_rth_output in fib_check_nh_v6_gw().
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-22007
+    - Bluetooth: Fix error code in chan_alloc_skb_cb()
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-21956
+    - drm/amd/display: Assign normalized_pix_clk when color depth = 14
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-21991
+    - x86/microcode/AMD: Fix out-of-bounds on systems with CPU-less NUMA nodes
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-21992
+    - HID: ignore non-functional sensor in HP 5MP Camera
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-21957
+    - scsi: qla1280: Fix kernel oops when debug level > 2
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-21993
+    - iscsi_ibft: Fix UBSAN shift-out-of-bounds warning in ibft_attr_show_nic()
+  * Focal update: v5.4.292 upstream stable release (LP: #2109357) //
+    CVE-2025-21959
+    - netfilter: nf_conncount: Fully initialize struct nf_conncount_tuple in
+      insert_tree()
+  * CVE-2024-53168
+    - net: make sock_inuse_add() available
+    - sunrpc: fix one UAF issue caused by sunrpc kernel tcp socket
+  * CVE-2024-56551
+    - drm/amdgpu: fix usage slab after free
+  * CVE-2021-47211
+    - ALSA: usb-audio: fix null pointer dereference on pointer cs_desc
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update annotations scripts
+
+ -- Abdur Rahman <abdur.rahman@canonical.com>  Thu, 05 Jun 2025 17:09:47 -0400
+
+linux-xilinx-zynqmp (5.4.0-1064.68) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1064.68 -proposed tracker (LP: #2106867)
+
+  [ Ubuntu: 5.4.0-216.236 ]
+
+  * focal/linux: 5.4.0-216.236 -proposed tracker (LP: #2106869)
+  * CVE-2023-52741
+    - cifs: Fix use-after-free in rdata->read_into_pages()
+  * CVE-2021-47191
+    - scsi: scsi_debug: Fix out-of-bound read in resp_readcap16()
+  * iommu/arm-smmu-v3: Don't reserve implementation defined register space
+    (LP: #2067864)
+    - iommu/arm-smmu-v3: Don't reserve implementation defined register space
+  * CVE-2025-21971
+    - net_sched: Prevent creation of classes with TC_H_ROOT
+  * CVE-2024-56599
+    - wifi: ath10k: avoid NULL pointer error during sdio remove
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002)
+    - perf cs-etm: Add missing variable in cs_etm__process_queues()
+    - udf: Fix use of check_add_overflow() with mixed type arguments
+    - overflow: Add __must_check attribute to check_*() helpers
+    - overflow: Correct check_shl_overflow() comment
+    - overflow: Allow mixed type arguments
+    - afs: Fix directory format encoding struct
+    - partitions: ldm: remove the initial kernel-doc notation
+    - drm/etnaviv: Fix page property being used for non writecombine buffers
+    - wifi: rtlwifi: do not complete firmware loading needlessly
+    - rtlwifi: rtl8192se Rename RT_TRACE to rtl_dbg
+    - wifi: rtlwifi: rtl8192se: rise completion of firmware loading as last step
+    - wifi: rtlwifi: usb: fix workqueue leak when probe fails
+    - dt-bindings: mmc: controller: clarify the address-cells description
+    - rtlwifi: replace usage of found with dedicated list iterator variable
+    - wifi: rtlwifi: remove unused timer and related code
+    - wifi: rtlwifi: remove unused dualmac control leftovers
+    - wifi: rtlwifi: pci: wait for firmware loading before releasing memory
+    - cpupower: fix TSC MHz calculation
+    - regulator: of: Implement the unwind path of of_regulator_match()
+    - wifi: wlcore: fix unbalanced pm_runtime calls
+    - selftests/harness: Display signed values correctly
+    - selftests: harness: fix printing of mismatch values in __EXPECT()
+    - clk: analogbits: Fix incorrect calculation of vco rate delta
+    - net/mlxfw: Drop hard coded max FW flash image size
+    - tools/testing/selftests/bpf/test_tc_tunnel.sh: Fix wait for server bind
+    - ASoC: sun4i-spdif: Add clock multiplier settings
+    - perf header: Fix one memory leakage in process_bpf_btf()
+    - perf header: Fix one memory leakage in process_bpf_prog_info()
+    - ktest.pl: Remove unused declarations in run_bisect_test function
+    - padata: fix sysfs store callback check
+    - perf top: Don't complain about lack of vmlinux when not resolving some
+      kernel samples
+    - perf report: Fix misleading help message about --demangle
+    - RDMA/mlx4: Avoid false error about access to uninitialized gids array
+    - arm64: dts: mediatek: mt8173-evb: Drop regulator-compatible property
+    - arm64: dts: mediatek: mt8173-evb: Fix MT6397 PMIC sub-node names
+    - ARM: dts: mediatek: mt7623: fix IR nodename
+    - fbdev: omapfb: Fix an OF node leak in dss_of_port_get_parent_device()
+    - media: rc: iguanair: handle timeouts
+    - media: lmedm04: Use GFP_KERNEL for URB allocation/submission.
+    - media: lmedm04: Handle errors for lme2510_int_read
+    - PCI: endpoint: Destroy the EPC device in devm_pci_epc_destroy()
+    - media: mipi-csis: Add check for clk_enable()
+    - media: camif-core: Add check for clk_enable()
+    - media: uvcvideo: Propagate buf->error to userspace
+    - staging: media: imx: fix OF node leak in imx_media_add_of_subdevs()
+    - scsi: mpt3sas: Set ioc->manu_pg11.EEDPTagMode directly to 1
+    - scsi: ufs: bsg: Delete bsg_dev when setting up bsg fails
+    - ocfs2: mark dquot as inactive if failed to start trans while releasing dquot
+    - module: Extend the preempt disabled section in
+      dereference_symbol_descriptor().
+    - dmaengine: ti: edma: fix OF node reference leaks in edma_driver
+    - net: fec: implement TSO descriptor cleanup
+    - PM: hibernate: Add error handling for syscore_suspend()
+    - perf trace: Fix runtime error of index out of bounds
+    - vsock: Allow retrying on connect() failure
+    - net: sh_eth: Fix missing rtnl lock in suspend/resume path
+    - genksyms: fix memory leak when the same symbol is added from source
+    - genksyms: fix memory leak when the same symbol is read from *.symref file
+    - hexagon: fix using plain integer as NULL pointer warning in cmpxchg
+    - hexagon: Fix unbalanced spinlock in die()
+    - NFSD: Reset cb_seq_status after NFS4ERR_DELAY
+    - ktest.pl: Check kernelrelease return in get_version
+    - drivers/card_reader/rtsx_usb: Restore interrupt based detection
+    - usb: typec: tcpm: set SRC_SEND_CAPABILITIES timeout to PD_T_SENDER_RESPONSE
+    - btrfs: output the reason for open_ctree() failure
+    - btrfs: convert BUG_ON in btrfs_reloc_cow_block() to proper error handling
+    - sched: Don't try to catch up excess steal time.
+    - x86/amd_nb: Restrict init function to AMD-based systems
+    - tun: fix group permission check
+    - mmc: core: Respect quirk_max_rate for non-UHS SDIO card
+    - mfd: lpc_ich: Add another Gemini Lake ISA bridge PCI device-id
+    - HID: Wacom: Add PCI Wacom device support
+    - APEI: GHES: Have GHES honor the panic= setting
+    - x86/mm: Don't disable PCID when INVLPG has been fixed by microcode
+    - spi-mxs: Fix chipselect glitch
+    - nilfs2: move page release outside of nilfs_delete_entry and nilfs_set_link
+    - nilfs2: eliminate staggered calls to kunmap in nilfs_rename
+    - media: uvcvideo: Only save async fh if success
+    - kbuild: userprogs: use correct lld when linking through clang
+    - tasklet: Introduce new initialization API
+    - net: usb: rtl8150: use new tasklet API
+    - usb: xhci: Add timeout argument in address_device USB HCD callback
+    - nvme: handle connectivity loss in nvme_set_queue_count
+    - firmware: iscsi_ibft: fix ISCSI_IBFT Kconfig entry
+    - gpu: drm_dp_cec: fix broken CEC adapter properties check
+    - tg3: Disable tg3 PCIe AER on system reboot
+    - udp: gso: do not drop small packets when PMTU reduces
+    - tun: revert fix group permission check
+    - cpufreq: s3c64xx: Fix compilation warning
+    - leds: lp8860: Write full EEPROM, not only half of it
+    - s390/futex: Fix FUTEX_OP_ANDN implementation
+    - m68k: vga: Fix I/O defines
+    - arm64: dts: rockchip: increase gmac rx_delay on rk3399-puma
+    - KVM: s390: vsie: fix some corner-cases when grabbing vsie pages
+    - drm/komeda: Add check for komeda_get_layer_fourcc_list()
+    - clk: qcom: clk-alpha-pll: fix alpha mode configuration
+    - clk: qcom: clk-rpmh: prevent integer overflow in recalc_rate
+    - perf bench: Fix undefined behavior in cmpworker()
+    - of: Correct child specifier used as input of the 2nd nexus node
+    - of: Fix of_find_node_opts_by_path() handling of alias+path+options
+    - of: reserved-memory: Fix using wrong number of cells to get property
+      'alignment'
+    - HID: hid-sensor-hub: don't use stale platform-data on remove
+    - usb: gadget: f_tcm: Translate error to sense
+    - usb: gadget: f_tcm: Decrement command ref count on cleanup
+    - usb: gadget: f_tcm: ep_autoconfig with fullspeed endpoint
+    - usb: gadget: f_tcm: Don't prepare BOT write request twice
+    - serial: sh-sci: Drop __initdata macro for port_cfg
+    - serial: sh-sci: Do not probe the serial port if its slot in sci_ports[] is
+      in use
+    - powerpc/pseries/eeh: Fix get PE state translation
+    - kbuild: Move -Wenum-enum-conversion to W=2
+    - soc: qcom: smem_state: fix missing of_node_put in error path
+    - media: ov5640: fix get_light_freq on auto
+    - media: uvcvideo: Fix event flags in uvc_ctrl_send_events
+    - media: uvcvideo: Remove redundant NULL assignment
+    - crypto: qce - fix goto jump in error path
+    - crypto: qce - unregister previously registered algos in error path
+    - nvmem: core: improve range check for nvmem_cell_write()
+    - vfio/platform: check the bounds of read/write syscalls
+    - ocfs2: fix incorrect CPU endianness conversion causing mount failure
+    - mtd: onenand: Fix uninitialized retlen in do_otp_read()
+    - misc: fastrpc: Fix registered buffer page address
+    - net/ncsi: wait for the last response to Deselect Package before configuring
+      channel
+    - MIPS: ftrace: Declare ftrace_get_parent_ra_addr() as static
+    - ocfs2: check dir i_size in ocfs2_find_entry
+    - ndisc: ndisc_send_redirect() must use dev_get_by_index_rcu()
+    - gpio: bcm-kona: Fix GPIO lock/unlock for banks above bank 0
+    - gpio: bcm-kona: Make sure GPIO bits are unlocked when requesting IRQ
+    - gpio: bcm-kona: Add missing newline to dev_err format string
+    - xen: remove a confusing comment on auto-translated guest I/O
+    - x86/xen: allow larger contiguous memory regions in PV guests
+    - media: cxd2841er: fix 64-bit division on gcc-9
+    - vfio/pci: Enable iowrite64 and ioread64 for vfio pci
+    - Grab mm lock before grabbing pt lock
+    - ASoC: Intel: bytcr_rt5640: Add DMI quirk for Vexia Edu Atla 10 tablet 5V
+    - usb: roles: set switch registered flag early on
+    - usb: gadget: udc: renesas_usb3: Fix compiler warning
+    - usb: dwc2: gadget: remove of_node reference upon udc_stop
+    - USB: pci-quirks: Fix HCCPARAMS register error for LS7A EHCI
+    - USB: quirks: add USB_QUIRK_NO_LPM quirk for Teclast dist
+    - USB: Add USB_QUIRK_NO_LPM quirk for sony xperia xz1 smartphone
+    - USB: cdc-acm: Fill in Renesas R-Car D3 USB Download mode quirk
+    - usb: cdc-acm: Fix handling of oversized fragments
+    - USB: serial: option: add MeiG Smart SLM828
+    - USB: serial: option: add Telit Cinterion FN990B compositions
+    - USB: serial: option: fix Telit Cinterion FN990A name
+    - USB: serial: option: drop MeiG Smart defines
+    - can: c_can: fix unbalanced runtime PM disable in error path
+    - can: j1939: j1939_sk_send_loop(): fix unable to send messages with data
+      length zero
+    - alpha: make stack 16-byte aligned (most cases)
+    - serial: 8250: Fix fifo underflow on flush
+    - alpha: align stack for page fault and user unaligned trap handlers
+    - gpio: stmpe: Check return value of stmpe_reg_read in
+      stmpe_gpio_irq_sync_unlock
+    - regmap-irq: Add missing kfree()
+    - net: treat possible_net_t net pointer as an RCU one and add read_pnet_rcu()
+    - net: add dev_net_rcu() helper
+    - ipv4: use RCU protection in rt_is_expired()
+    - ipv4: use RCU protection in inet_select_addr()
+    - neighbour: delete redundant judgment statements
+    - alpha: replace hardcoded stack offsets with autogenerated ones
+    - nilfs2: do not output warnings when clearing dirty buffers
+    - can: ems_pci: move ASIX AX99100 ids to pci_ids.h
+    - serial: 8250_pci: add support for ASIX AX99100
+    - parport_pc: add support for ASIX AX99100
+    - x86/i8253: Disable PIT timer 0 when not in use
+    - Revert "btrfs: avoid monopolizing a core when activating a swap file"
+    - btrfs: avoid monopolizing a core when activating a swap file
+    - vlan: introduce vlan_dev_free_egress_priority
+    - vlan: move dev_put into vlan_dev_uninit
+    - scsi: storvsc: Set correct data length for sending SCSI command without
+      payload
+    - crypto: testmgr - fix wrong key length for pkcs1pad
+    - crypto: testmgr - Fix wrong test case of RSA
+    - crypto: testmgr - fix version number of RSA tests
+    - crypto: testmgr - populate RSA CRT parameters in RSA test vectors
+    - crypto: testmgr - some more fixes to RSA test vectors
+    - mm: update mark_victim tracepoints fields
+    - usb: dwc3: Increase DWC3 controller halt timeout
+    - usb: dwc3: Fix timeout issue during controller enter/exit from halt state
+    - usb/gadget: f_midi: convert tasklets to use new tasklet_setup() API
+    - usb/gadget: f_midi: Replace tasklet with work
+    - powerpc/64s/mm: Move __real_pte stubs into hash-4k.h
+    - powerpc/64s: Rewrite __real_pte() and __rpte_to_hidx() as static inline
+    - ALSA: hda/realtek - Add type for ALC287
+    - ALSA: hda/realtek: Fixup ALC225 depop procedure
+    - geneve: Suppress list corruption splat in geneve_destroy_tunnels().
+    - net: extract port range fields from fl_flow_key
+    - flow_dissector: Fix handling of mixed port and port-range keys
+    - flow_dissector: Fix port range key handling in BPF conversion
+    - power: supply: da9150-fg: fix potential overflow
+    - ALSA: hda/conexant: Add quirk for HP ProBook 450 G4 mute LED
+    - acct: block access to kernel internal filesystems
+    - batman-adv: Ignore neighbor throughput metrics in error case
+    - sunrpc: suppress warnings for unused procfs functions
+    - net: loopback: Avoid sending IP packets without an Ethernet header
+    - net: cadence: macb: Synchronize stats calculations
+    - ASoC: es8328: fix route from DAC to output
+    - ipvs: Always clear ipvs_property flag in skb_scrub_packet()
+    - net: mvpp2: cls: Fixed Non IP flow, with vlan tag flow defination.
+    - x86/CPU: Fix warm boot hang regression on AMD SC1100 SoC systems
+    - ftrace: Avoid potential division by zero in function_stat_show()
+    - perf/core: Fix low freq setting via IOC_PERIOD
+    - phy: tegra: xusb: reset VBUS & ID OVERRIDE
+    - phy: exynos5-usbdrd: fix MPLL_MULTIPLIER and SSC_REFCLKSEL masks in refclk
+    - kernel/acct.c: use #elif instead of #end and #elif
+    - kernel/acct.c: use dedicated helper to access rlimit values
+    - drm/amdgpu: skip BAR resizing if the bios already did it
+    - drm/amdgpu: Check extended configuration space register when system uses
+      large bar
+    - drm/amdgpu: disable BAR resize on Dell G5 SE
+    - Revert "of: reserved-memory: Fix using wrong number of cells to get property
+      'alignment'"
+    - HID: appleir: Fix potential NULL dereference at raw event handle
+    - ALSA: hda: intel: Add Dell ALC3271 to power_save denylist
+    - ALSA: hda/realtek: update ALC222 depop optimize
+    - drm/radeon: Fix rs400_gpu_init for ATI mobility radeon Xpress 200M
+    - platform/x86: thinkpad_acpi: Add battery quirk for ThinkPad X131e
+    - x86/cacheinfo: Validate CPUID leaf 0x2 EDX output
+    - x86/cpu: Validate CPUID leaf 0x2 EDX output
+    - x86/cpu: Properly parse CPUID leaf 0x2 TLB descriptor 0x63
+    - wifi: cfg80211: regulatory: improve invalid hints checking
+    - wifi: nl80211: reject cooked mode if it is set along with other flags
+    - rapidio: add check for rio_add_net() in rio_scan_alloc_net()
+    - rapidio: fix an API misues when rio_add_net() fails
+    - mm/page_alloc: fix uninitialized variable
+    - wifi: iwlwifi: limit printed string from FW file
+    - HID: google: fix unused variable warning under !CONFIG_ACPI
+    - HID: intel-ish-hid: Fix use-after-free issue in ishtp_hid_remove()
+    - net: gso: fix ownership in __udp_gso_segment
+    - caif_virtio: fix wrong pointer check in cfv_probe()
+    - hwmon: (pmbus) Initialise page count in pmbus_identify()
+    - hwmon: (ntc_thermistor) Fix the ncpXXxh103 sensor table
+    - hwmon: (ad7314) Validate leading zero bits and return error
+    - llc: do not use skb_get() before dev_queue_xmit()
+    - hwmon: fix a NULL vs IS_ERR_OR_NULL() check in xgene_hwmon_probe()
+    - drm/sched: Fix preprocessor guard
+    - be2net: fix sleeping while atomic bugs in be_ndo_bridge_getlink
+    - ppp: Fix KMSAN uninit-value warning with bpf
+    - vlan: enforce underlying device type
+    - net-timestamp: support TCP GSO case for a few missing flags
+    - net: ipv6: fix dst ref loop in ila lwtunnel
+    - net: ipv6: fix missing dst ref drop in ila lwtunnel
+    - gpio: rcar: Fix missing of_node_put() call
+    - Revert "drivers/card_reader/rtsx_usb: Restore interrupt based detection"
+    - usb: renesas_usbhs: Call clk_put()
+    - usb: renesas_usbhs: Use devm_usb_get_phy()
+    - usb: quirks: Add DELAY_INIT and NO_LPM for Prolific Mass Storage Card Reader
+    - usb: renesas_usbhs: Flush the notify_hotplug_work
+    - usb: atm: cxacru: fix a flaw in existing endpoint checks
+    - usb: typec: ucsi: increase timeout for PPM reset operations
+    - usb: typec: tcpci_rt1711h: Unmask alert interrupts to fix functionality
+    - usb: gadget: Set self-powered based on MaxPower and bmAttributes
+    - usb: gadget: Fix setting self-powered state on suspend
+    - usb: gadget: Check bmAttributes only if configuration is valid
+    - xhci: pci: Fix indentation in the PCI device ID definitions
+    - intel_th: pci: Add Arrow Lake support
+    - intel_th: pci: Add Panther Lake-H support
+    - intel_th: pci: Add Panther Lake-P/U support
+    - slimbus: messaging: Free transaction ID in delayed interrupt scenario
+    - eeprom: digsy_mtc: Make GPIO lookup table match the device
+    - Linux 5.4.291
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-26982
+    - Squashfs: check the inode number is not the invalid value of zero
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21846
+    - acct: perform last write from workqueue
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21862
+    - drop_monitor: fix incorrect initialization order
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58090
+    - sched/core: Prevent rescheduling when interrupts are disabled
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21877
+    - usbnet: gl620a: fix endpoint checking in genelink_bind()
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21823
+    - batman-adv: Drop unmanaged ELP metric worker
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21848
+    - nfp: bpf: Add check for nfp_app_ctrl_msg_alloc()
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21871
+    - tee: optee: Fix supplicant wait loop
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21865
+    - gtp: Suppress list corruption splat in gtp_net_exit_batch_rtnl().
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21858
+    - geneve: Fix use-after-free in geneve_find_dev().
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21866
+    - powerpc/code-patching: Fix KASAN hit by not flagging text patching area as
+      VM_ALLOC
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21859
+    - USB: gadget: f_midi: f_midi_complete to call queue_work
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-57977
+    - memcg: fix soft lockup in the OOM process
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-50055
+    - driver core: bus: Fix double free in driver API bus_register()
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-57979
+    - pps: Fix a use-after-free
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21811
+    - nilfs2: protect access to buffers with no active references
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21722
+    - nilfs2: do not force clear folio if buffer is referenced
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21760
+    - ndisc: extend RCU protection in ndisc_send_skb()
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21761
+    - openvswitch: use RCU protection in ovs_vport_cmd_fill_info()
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21762
+    - arp: use RCU protection in arp_xmit()
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21763
+    - neighbour: use RCU protection in __neigh_notify()
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21764
+    - ndisc: use RCU protection in ndisc_alloc_skb()
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21765
+    - ipv6: use RCU protection in ip6_default_advmss()
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21772
+    - partitions: mac: fix handling of bogus partition table
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21704
+    - usb: cdc-acm: Check control transfer buffer size before access
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21776
+    - USB: hub: Ignore non-compliant devices with too many configs or interfaces
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21835
+    - usb: gadget: f_midi: fix MIDI Streaming descriptor lengths
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21781
+    - batman-adv: fix panic during interface removal
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21782
+    - orangefs: fix a oob in orangefs_debug_write
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21785
+    - arm64: cacheinfo: Avoid out-of-bounds write to cacheinfo array
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21787
+    - team: better TEAM_OPTION_TYPE_STRING validation
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21791
+    - vrf: use RCU protection in l3mdev_l3_out()
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58020
+    - HID: multitouch: Add NULL check in mt_input_configured
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21814
+    - ptp: Ensure info->enable callback is always set
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21735
+    - NFC: nci: Add bounds checking in nci_hci_create_pipe()
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21736
+    - nilfs2: fix possible int overflows in nilfs_fiemap()
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58001
+    - ocfs2: handle a symlink read error correctly
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58007
+    - soc: qcom: socinfo: Avoid out of bounds read of serial number
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21744
+    - wifi: brcmfmac: fix NULL pointer dereference in brcmf_txfinalize()
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58009
+    - Bluetooth: L2CAP: handle NULL sock pointer in l2cap_sock_alloc
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58083
+    - KVM: Explicitly verify target vCPU is online in kvm_get_vcpu()
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58010
+    - binfmt_flat: Fix integer overflow bug on 32 bit systems
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21749
+    - net: rose: lock the socket in rose_bind()
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-57981
+    - usb: xhci: Fix NULL pointer dereference on certain command aborts
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21708
+    - net: usb: rtl8150: enable basic endpoint checking
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21647
+    - sched: sch_cake: add bounds checks to host bulk flow fairness counts
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58002
+    - media: uvcvideo: Remove dangling pointers
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21721
+    - nilfs2: handle errors that nilfs_prepare_chunk() may return
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58085
+    - tomoyo: don't emit warning in tomoyo_write_control()
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58014
+    - wifi: brcmsmac: add gain range check to wlc_phy_iqcal_gainparams_nphy()
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58017
+    - printk: Fix signed integer overflow when defining LOG_BUF_LEN_MAX
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21753
+    - btrfs: fix use-after-free when attempting to join an aborted transaction
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58055
+    - usb: gadget: f_tcm: Don't free command immediately
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-57980
+    - media: uvcvideo: Fix double free in error path
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-57986
+    - HID: core: Fix assumption that Resolution Multipliers must be in Logical
+      Collections
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21715
+    - net: davicom: fix UAF in dm9000_drv_remove
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21718
+    - net: rose: fix timer races against user threads
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21719
+    - ipmr: do not call mr_mfc_uses_dev() for unres entries
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58058
+    - ubifs: skip dumping tnc tree when zroot is null
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58069
+    - rtc: pcf85063: fix potential OOB write in PCF85063 NVMEM read
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-57973
+    - rdma/cxgb4: Prevent potential integer overflow on 32bit
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21728
+    - bpf: Send signals asynchronously if !preemptible
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21806
+    - net: let net.core.dev_weight always be non-zero
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58071
+    - team: prevent adding a device which is already a team device lower
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58063
+    - wifi: rtlwifi: fix memory leaks and invalid access at probe error path
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58072
+    - wifi: rtlwifi: remove unused check_buddy_priv
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58051
+    - ipmi: ipmb: Add check devm_kasprintf() returned value
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2024-58052
+    - drm/amdgpu: Fix potential NULL pointer dereference in
+      atomctrl_get_smc_sclk_range_table
+  * Focal update: v5.4.291 upstream stable release (LP: #2106002) //
+    CVE-2025-21731
+    - nbd: don't allow reconnect after disconnect
+  * CVE-2024-26996
+    - usb: gadget: f_ncm: Fix UAF ncm object at re-bind after usb ep transport
+      error
+  * CVE-2023-52664
+    - net: atlantic: eliminate double free in error handling logic
+  * CVE-2024-26689
+    - ceph: prevent use-after-free in encode_cap_msg()
+  * CVE-2023-52927
+    - netfilter: allow exp not to be removed in nf_ct_find_expectation
+
+ -- Wei-Lin Chang <weilin.chang@canonical.com>  Wed, 23 Apr 2025 10:31:08 +0800
+
+linux-xilinx-zynqmp (5.4.0-1063.67) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1063.67 -proposed tracker (LP: #2106917)
+
+  [ Ubuntu: 5.4.0-215.235 ]
+
+  * focal/linux: 5.4.0-215.235 -proposed tracker (LP: #2106919)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update annotations scripts
+  * CVE-2023-52664
+    - net: atlantic: eliminate double free in error handling logic
+  * CVE-2024-26689
+    - ceph: prevent use-after-free in encode_cap_msg()
+  * CVE-2023-52927
+    - netfilter: allow exp not to be removed in nf_ct_find_expectation
+
+ -- Wei-Lin Chang <weilin.chang@canonical.com>  Tue, 22 Apr 2025 10:10:46 +0800
+
+linux-xilinx-zynqmp (5.4.0-1062.66) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1062.66 -proposed tracker (LP: #2102633)
+
+  [ Ubuntu: 5.4.0-214.234 ]
+
+  * focal/linux: 5.4.0-214.234 -proposed tracker (LP: #2102635)
+  * CVE-2024-50256
+    - netfilter: nf_reject_ipv6: fix potential crash in nf_send_reset6()
+  * CVE-2025-21702
+    - pfifo_tail_enqueue: Drop new packet when sch->limit == 0
+  * CVE-2025-21703
+    - netem: Update sch->q.qlen before qdisc_tree_reduce_backlog()
+  * CVE-2024-26915
+    - drm/amdgpu: Reset IH OVERFLOW_CLEAR bit
+  * CVE-2025-21700
+    - net: sched: Disallow replacing of child qdisc from one parent to another
+  * CVE-2024-46826
+    - ELF: fix kernel.randomize_va_space double read
+  * CVE-2024-56651
+    - can: hi311x: hi3110_can_ist(): fix potential use-after-free
+  * CVE-2024-53237
+    - driver core: Introduce device_find_any_child() helper
+    - Bluetooth: fix use-after-free in device_for_each_child()
+  * CVE-2024-35958
+    - net: ena: Fix incorrect descriptor free behavior
+  * CVE-2024-49974
+    - NFSD: Limit the number of concurrent async COPY operations
+  * CVE-2021-47119
+    - ext4: fix memory leak in ext4_fill_super
+  * CVE-2024-56658
+    - net: defer final 'struct net' free in netns dismantle
+  * CVE-2024-35864
+    - smb: client: fix potential UAF in smb2_is_valid_lease_break()
+  * CVE-2024-35864/CVE-2024-26928
+    - smb: client: fix potential UAF in cifs_debug_files_proc_show()
+
+ -- Wei-Lin Chang <weilin.chang@canonical.com>  Wed, 26 Mar 2025 11:49:30 +0800
+
+linux-xilinx-zynqmp (5.4.0-1061.65) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1061.65 -proposed tracker (LP: #2102365)
+
+  [ Ubuntu: 5.4.0-212.232 ]
+
+  * focal/linux: 5.4.0-212.232 -proposed tracker (LP: #2102367)
+  * CVE-2024-56658
+    - net: defer final 'struct net' free in netns dismantle
+  * CVE-2024-35864
+    - smb: client: fix potential UAF in smb2_is_valid_lease_break()
+  * CVE-2024-35864/CVE-2024-26928
+    - smb: client: fix potential UAF in cifs_debug_files_proc_show()
+
+ -- Koichiro Den <koichiro.den@canonical.com>  Fri, 21 Mar 2025 10:35:17 +0900
+
+linux-xilinx-zynqmp (5.4.0-1060.64) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1060.64 -proposed tracker (LP: #2101994)
+
+  [ Ubuntu: 5.4.0-211.231 ]
+
+  * focal/linux: 5.4.0-211.231 -proposed tracker (LP: #2101996)
+  * cve-2018-5803 kernel panic (LP: #2101091)
+    - SAUCE: sctp: sysctl: pass right argument to container_of
+
+ -- Koichiro Den <koichiro.den@canonical.com>  Thu, 13 Mar 2025 10:04:51 +0900
+
+linux-xilinx-zynqmp (5.4.0-1059.63) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1059.63 -proposed tracker (LP: #2098351)
+
+  [ Ubuntu: 5.4.0-210.230 ]
+
+  * focal/linux: 5.4.0-210.230 -proposed tracker (LP: #2098353)
+  * Focal update: v5.4.290 upstream stable release (LP: #2098439)
+    - jbd2: flush filesystem device before updating tail sequence
+    - dm array: fix releasing a faulty array block twice in dm_array_cursor_end
+    - dm array: fix unreleased btree blocks on closing a faulty array cursor
+    - dm array: fix cursor index when skipping across block boundaries
+    - ieee802154: ca8210: Add missing check for kfifo_alloc() in ca8210_probe()
+    - net: 802: LLC+SNAP OID:PID lookup on start of skb data
+    - tcp/dccp: complete lockless accesses to sk->sk_max_ack_backlog
+    - tcp/dccp: allow a connection when sk_max_ack_backlog is zero
+    - net_sched: cls_flow: validate TCA_FLOW_RSHIFT attribute
+    - tls: Fix tls_sw_sendmsg error handling
+    - dm thin: make get_first_thin use rcu-safe list first function
+    - sctp: sysctl: cookie_hmac_alg: avoid using current->nsproxy
+    - sctp: sysctl: auth_enable: avoid using current->nsproxy
+    - drm/amd/display: Add check for granularity in dml ceil/floor helpers
+    - ACPI: resource: Add TongFang GM5HG0A to irq1_edge_low_force_override[]
+    - ACPI: resource: Add Asus Vivobook X1504VAP to irq1_level_low_skip_override[]
+    - drm/amd/display: increase MAX_SURFACES to the value supported by hw
+    - USB: serial: option: add MeiG Smart SRM815
+    - USB: serial: option: add Neoway N723-EA support
+    - staging: iio: ad9834: Correct phase range check
+    - staging: iio: ad9832: Correct phase range check
+    - usb-storage: Add max sectors quirk for Nokia 208
+    - USB: serial: cp210x: add Phoenix Contact UPS Device
+    - usb: gadget: u_serial: Disable ep before setting port to null to fix the
+      crash caused by port being null
+    - USB: usblp: return error when setting unsupported protocol
+    - USB: core: Disable LPM only for non-suspended ports
+    - usb: fix reference leak in usb_new_device()
+    - usb: gadget: f_fs: Remove WARN_ON in functionfs_bind
+    - iio: pressure: zpa2326: fix information leak in triggered buffer
+    - iio: dummy: iio_simply_dummy_buffer: fix information leak in triggered
+      buffer
+    - iio: light: vcnl4035: fix information leak in triggered buffer
+    - iio: imu: kmx61: fix information leak in triggered buffer
+    - iio: adc: ti-ads8688: fix information leak in triggered buffer
+    - iio: gyro: fxas21002c: Fix missing data update in trigger handler
+    - iio: adc: ti-ads124s08: Use gpiod_set_value_cansleep()
+    - iio: adc: at91: call input_free_device() on allocated iio_dev
+    - iio: inkern: call iio_device_put() only on mapped devices
+    - arm64: dts: rockchip: fix defines in pd_vio node for rk3399
+    - arm64: dts: rockchip: fix pd_tcpc0 and pd_tcpc1 node position on rk3399
+    - arm64: dts: rockchip: add #power-domain-cells to power domain nodes
+    - arm64: dts: rockchip: add hevc power domain clock to rk3328
+    - phy: core: fix code style in devm_of_phy_provider_unregister
+    - phy: core: Fix that API devm_of_phy_provider_unregister() fails to
+      unregister the phy provider
+    - ocfs2: correct return value of ocfs2_local_free_info()
+    - ocfs2: fix slab-use-after-free due to dangling pointer dqi_priv
+    - sctp: sysctl: rto_min/max: avoid using current->nsproxy
+    - net: ethernet: ti: cpsw_ale: Fix cpsw_ale_get_field()
+    - net: net_namespace: Optimize the code
+    - net: add exit_batch_rtnl() method
+    - gtp: use exit_batch_rtnl() method
+    - gtp: Use for_each_netdev_rcu() in gtp_genl_dump_pdp().
+    - gtp: Destroy device along with udp socket's netns dismantle.
+    - nfp: bpf: prevent integer overflow in nfp_bpf_event_output()
+    - drm/v3d: Ensure job pointer is set to NULL after job completion
+    - i2c: mux: demux-pinctrl: check initial mux selection, too
+    - mac802154: check local interfaces before deleting sdata list
+    - hfs: Sanity check the root record
+    - kheaders: Ignore silly-rename files
+    - poll_wait: add mb() to fix theoretical race between waitqueue_active() and
+      .poll()
+    - nvmet: propagate npwg topology
+    - net: ethernet: xgbe: re-add aneg to supported features in PHY quirks
+    - fs/proc: fix softlockup in __read_vmcore (part 2)
+    - irqchip/gic-v3: Handle CPU_PM_ENTER_FAILED correctly
+    - hrtimers: Handle CPU state correctly on hotplug
+    - ipv6: avoid possible NULL deref in rt6_uncached_list_flush_dev()
+    - scsi: sg: Fix slab-use-after-free read in sg_release()
+    - net: fix data-races around sk->sk_forward_alloc
+    - ASoC: wm8994: Add depends on MFD core
+    - scsi: iscsi: Fix redundant response for ISCSI_UEVENT_GET_HOST_STATS request
+    - irqchip/sunxi-nmi: Add missing SKIP_WAKE flag
+    - gfs2: Truncate address space when flipping GFS2_DIF_JDATA flag
+    - m68k: Update ->thread.esp0 before calling syscall_trace() in ret_from_signal
+    - m68k: Add missing mmap_read_lock() to sys_cacheflush()
+    - signal/m68k: Use force_sigsegv(SIGSEGV) in fpsp040_die
+    - net: xen-netback: hash.c: Use built-in RCU list checking
+    - net/xen-netback: prevent UAF in xenvif_flush_hash()
+    - vfio/platform: check the bounds of read/write syscalls
+    - ext4: avoid ext4_error()'s caused by ENOMEM in the truncate path
+    - ext4: fix slab-use-after-free in ext4_split_extent_at()
+    - USB: serial: quatech2: fix null-ptr-deref in qt2_process_read_urb()
+    - Revert "usb: gadget: u_serial: Disable ep before setting port to null to fix
+      the crash caused by port being null"
+    - Input: atkbd - map F23 key to support default copilot shortcut
+    - Input: xpad - add unofficial Xbox 360 wireless receiver clone
+    - Input: xpad - add support for wooting two he (arm)
+    - drm/v3d: Assign job pointer to NULL before signaling the fence
+    - xhci: use pm_ptr() instead of #ifdef for CONFIG_PM conditionals
+    - Partial revert of xhci: use pm_ptr() instead #ifdef for CONFIG_PM
+      conditionals
+    - Linux 5.4.290
+  * CVE-2021-47219
+    - scsi: scsi_debug: Fix out-of-bound read in resp_report_tgtpgs()
+  * CVE-2024-49925
+    - fbdev: efifb: Register sysfs groups through driver core
+  * CVE-2024-56614
+    - xsk: fix OOB map writes when deleting elements
+  * net: stmmac: kernel continually prints wol unbalance irq warning
+    (LP: #2095376)
+    - net: stmmac: ethtool: Fixed calltrace caused by unbalanced disable_irq_wake
+      calls
+  * CVE-2024-44938
+    - jfs: Fix shift-out-of-bounds in dbDiscardAG
+  * CVE-2024-43900
+    - media: xc2028: avoid use-after-free in load_firmware_cb()
+  * Focal update: v5.4.289 upstream stable release (LP: #2095437)
+    - usb: dwc2: gadget: Don't write invalid mapped sg entries into dma_desc with
+      iommu enabled
+    - PCI/AER: Disable AER service on suspend
+    - ALSA: usb: Fix UBSAN warning in parse_audio_unit()
+    - PCI: Add ACS quirk for Broadcom BCM5760X NIC
+    - i2c: pnx: Fix timeout in wait functions
+    - drm/i915: Fix memory leak by correcting cache object name in error handler
+    - erofs: fix order >= MAX_ORDER warning due to crafted negative i_size
+    - erofs: fix incorrect symlink detection in fast symlink
+    - net/smc: check sndbuf_space again after NOSPACE flag is set in smc_poll
+    - ionic: use ee->offset when returning sprom data
+    - net: hinic: Fix cleanup in create_rxqs/txqs()
+    - net: ethernet: bgmac-platform: fix an OF node reference leak
+    - netfilter: ipset: Fix for recursive locking warning
+    - mmc: sdhci-tegra: Remove SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC quirk
+    - chelsio/chtls: prevent potential integer overflow on 32bit
+    - i2c: riic: Always round-up when calculating bus period
+    - efivarfs: Fix error on non-existent file
+    - USB: serial: option: add TCL IK512 MBIM & ECM
+    - USB: serial: option: add MeiG Smart SLM770A
+    - USB: serial: option: add Netprisma LCUK54 modules for WWAN Ready
+    - USB: serial: option: add MediaTek T7XX compositions
+    - USB: serial: option: add Telit FE910C04 rmnet compositions
+    - sh: clk: Fix clk_enable() to return 0 on NULL clk
+    - zram: refuse to use zero sized block device as backing device
+    - btrfs: tree-checker: reject inline extent items with 0 ref count
+    - NFS/pnfs: Fix a live lock between recalled layouts and layoutget
+    - of/irq: Fix using uninitialized variable @addr_len in API of_irq_parse_one()
+    - nilfs2: prevent use of deleted inode
+    - udmabuf: also check for F_SEAL_FUTURE_WRITE
+    - of: Fix error path in of_parse_phandle_with_args_map()
+    - of: Fix refcount leakage for OF node returned by __of_get_dma_parent()
+    - media: dvb-frontends: dib3000mb: fix uninit-value in dib3000_write_reg
+    - bpf: Check negative offsets in __bpf_skb_min_len()
+    - nfsd: restore callback functionality for NFSv4.0
+    - mtd: diskonchip: Cast an operand to prevent potential overflow
+    - phy: core: Fix an OF node refcount leakage in _of_phy_get()
+    - phy: core: Fix an OF node refcount leakage in of_phy_provider_lookup()
+    - phy: core: Fix that API devm_phy_put() fails to release the phy
+    - phy: core: Fix that API devm_phy_destroy() fails to destroy the phy
+    - dmaengine: mv_xor: fix child node refcount handling in early exit
+    - dmaengine: at_xdmac: avoid null_prt_deref in at_xdmac_prep_dma_memset
+    - mtd: rawnand: fix double free in atmel_pmecc_create_user()
+    - tracing/kprobe: Make trace_kprobe's module callback called after jump_label
+      update
+    - scsi: qla1280: Fix hw revision numbering for ISP1020/1040
+    - scsi: megaraid_sas: Fix for a potential deadlock
+    - regmap: Use correct format specifier for logging range errors
+    - platform/x86: asus-nb-wmi: Ignore unknown event 0xCF
+    - scsi: mpt3sas: Diag-Reset when Doorbell-In-Use bit is set during driver load
+      time
+    - virtio-blk: don't keep queue frozen during system suspend
+    - epoll: Add synchronous wakeup support for ep_poll_callback
+    - MIPS: Probe toolchain support of -msym32
+    - ipv6: use skb_expand_head in ip6_finish_output2
+    - ipv6: use skb_expand_head in ip6_xmit
+    - ipv6: fix possible UAF in ip6_finish_output2()
+    - bpf: fix recursive lock when verdict program return SK_PASS
+    - tracing: Constify string literal data member in struct trace_event_call
+    - btrfs: avoid monopolizing a core when activating a swap file
+    - ipv6: prevent possible UAF in ip6_xmit()
+    - selinux: ignore unknown extended permissions
+    - Drivers: hv: util: Avoid accessing a ringbuffer not initialized yet
+    - IB/mlx5: Introduce and use mlx5_core_is_vf()
+    - net/mlx5: Make API mlx5_core_is_ecpf accept const pointer
+    - RDMA/mlx5: Enforce same type port association for multiport RoCE
+    - RDMA/bnxt_re: Add check for path mtu in modify_qp
+    - RDMA/bnxt_re: Fix reporting hw_ver in query_device
+    - RDMA/bnxt_re: Fix max_qp_wrs reported
+    - drm: bridge: adv7511: Enable SPDIF DAI
+    - drm/bridge: adv7511_audio: Update Audio InfoFrame properly
+    - netrom: check buffer length before accessing it
+    - netfilter: Replace zero-length array with flexible-array member
+    - netfilter: nft_set_hash: unaligned atomic read on struct nft_set_ext
+    - net: llc: reset skb->transport_header
+    - ALSA: usb-audio: US16x08: Initialize array before use
+    - af_packet: fix vlan_get_tci() vs MSG_PEEK
+    - af_packet: fix vlan_get_protocol_dgram() vs MSG_PEEK
+    - ila: serialize calls to nf_register_net_hooks()
+    - wifi: mac80211: wake the queues in case of failure in resume
+    - sound: usb: format: don't warn that raw DSD is unsupported
+    - bpf: fix potential error return
+    - net: usb: qmi_wwan: add Telit FE910C04 compositions
+    - irqchip/gic: Correct declaration of *percpu_base pointer in union gic_base
+    - ARC: build: Try to guess GCC variant of cross compiler
+    - modpost: fix input MODULE_DEVICE_TABLE() built for 64-bit on 32-bit host
+    - modpost: fix the missed iteration for the max bit in do_input()
+    - RDMA/uverbs: Prevent integer overflow issue
+    - pinctrl: mcp23s08: Fix sleeping in atomic context due to regmap locking
+    - sky2: Add device ID 11ab:4373 for Marvell 88E8075
+    - net/sctp: Prevent autoclose integer overflow in sctp_association_init()
+    - drm: adv7511: Drop dsi single lane support
+    - mm: vmscan: account for free pages to prevent infinite Loop in
+      throttle_direct_reclaim()
+    - ftrace: use preempt_enable/disable notrace macros to avoid double fault
+    - Linux 5.4.289
+  * Focal update: v5.4.289 upstream stable release (LP: #2095437) //
+    CVE-2024-38588
+    - ftrace: Fix possible use-after-free issue in ftrace_location()
+  * Focal update: v5.4.288 upstream stable release (LP: #2095199)
+    - usb: host: max3421-hcd: Correctly abort a USB request.
+    - ata: sata_highbank: fix OF node reference leak in highbank_initialize_phys()
+    - usb: dwc2: hcd: Fix GetPortStatus & SetPortFeature
+    - usb: ehci-hcd: fix call balance of clocks handling routines
+    - usb: gadget: u_serial: Fix the issue that gs_start_io crashed due to
+      accessing null pointer
+    - xfs: don't drop errno values when we fail to ficlone the entire range
+    - bpf, sockmap: Fix update element with same
+    - batman-adv: Do not send uninitialized TT changes
+    - batman-adv: Remove uninitialized data in full table TT response
+    - batman-adv: Do not let TT changes list grows indefinitely
+    - tipc: fix NULL deref in cleanup_bearer()
+    - net: lapb: increase LAPB_HEADER_LEN
+    - ACPI: resource: Fix memory resource type union access
+    - qca_spi: Fix clock speed for multiple QCA7000
+    - qca_spi: Make driver probing reliable
+    - net/sched: netem: account for backlog updates from child qdisc
+    - ACPICA: events/evxfregn: don't release the ContextMutex that was never
+      acquired
+    - blk-iocost: clamp inuse and skip noops in __propagate_weights()
+    - blk-iocost: fix weight updates of inner active iocgs
+    - blk-iocost: Avoid using clamp() on inuse in __propagate_weights()
+    - KVM: arm64: Ignore PMCNTENSET_EL0 while checking for overflow status
+    - tracing/kprobes: Skip symbol counting logic for module symbols in
+      create_local_trace_kprobe()
+    - xen/netfront: fix crash when removing device
+    - ALSA: usb-audio: Fix a DMA to stack memory bug
+    - Linux 5.4.288
+  * Focal update: v5.4.287 upstream stable release (LP: #2095145)
+    - netlink: terminate outstanding dump on socket close
+    - net/mlx5: fs, lock FTE when checking if active
+    - net/mlx5e: kTLS, Fix incorrect page refcounting
+    - ocfs2: uncache inode which has failed entering the group
+    - KVM: VMX: Bury Intel PT virtualization (guest/host mode) behind
+      CONFIG_BROKEN
+    - nilfs2: fix null-ptr-deref in block_touch_buffer tracepoint
+    - ocfs2: fix UBSAN warning in ocfs2_verify_volume()
+    - nilfs2: fix null-ptr-deref in block_dirty_buffer tracepoint
+    - Revert "mmc: dw_mmc: Fix IDMAC operation with pages bigger than 4K"
+    - media: dvbdev: fix the logic when DVB_DYNAMIC_MINORS is not set
+    - kbuild: Use uname for LINUX_COMPILE_HOST detection
+    - mm: revert "mm: shmem: fix data-race in shmem_getattr()"
+    - ASoC: Intel: bytcr_rt5640: Add DMI quirk for Vexia Edu Atla 10 tablet
+    - mac80211: fix user-power when emulating chanctx
+    - selftests/watchdog-test: Fix system accidentally reset after watchdog-test
+    - ALSA: hda/realtek: Add subwoofer quirk for Infinix ZERO BOOK 13
+    - x86/amd_nb: Fix compile-testing without CONFIG_AMD_NB
+    - net: usb: qmi_wwan: add Quectel RG650V
+    - soc: qcom: Add check devm_kasprintf() returned value
+    - regulator: rk808: Add apply_bit for BUCK3 on RK809
+    - ASoC: stm: Prevent potential division by zero in stm32_sai_mclk_round_rate()
+    - ASoC: stm: Prevent potential division by zero in stm32_sai_get_clk_div()
+    - proc/softirqs: replace seq_printf with seq_put_decimal_ull_width
+    - ipmr: Fix access to mfc_cache_list without lock held
+    - cifs: Fix buffer overflow when parsing NFS reparse points
+    - NFSD: Force all NFSv4.2 COPY requests to be synchronous
+    - nvme: fix metadata handling in nvme-passthrough
+    - mips: asm: fix warning when disabling MIPS_FP_SUPPORT
+    - initramfs: avoid filename buffer overrun
+    - nvme-pci: fix freeing of the HMB descriptor table
+    - m68k: mvme147: Fix SCSI controller IRQ numbers
+    - m68k: mvme16x: Add and use "mvme16x.h"
+    - m68k: mvme147: Reinstate early console
+    - acpi/arm64: Adjust error handling procedure in gtdt_parse_timer_block()
+    - s390/syscalls: Avoid creation of arch/arch/ directory
+    - hfsplus: don't query the device logical block size multiple times
+    - firmware: google: Unregister driver_info on failure and exit in gsmi
+    - firmware: google: Unregister driver_info on failure
+    - EDAC/bluefield: Fix potential integer overflow
+    - EDAC/fsl_ddr: Fix bad bit shift operations
+    - crypto: pcrypt - Call crypto layer directly when padata_do_parallel() return
+      -EBUSY
+    - crypto: cavium - Fix the if condition to exit loop after timeout
+    - crypto: bcm - add error check in the ahash_hmac_init function
+    - crypto: cavium - Fix an error handling path in cpt_ucode_load_fw()
+    - time: Fix references to _msecs_to_jiffies() handling of values
+    - soc: ti: smartreflex: Use IRQF_NO_AUTOEN flag in request_irq()
+    - soc: qcom: geni-se: fix array underflow in geni_se_clk_tbl_get()
+    - mmc: mmc_spi: drop buggy snprintf()
+    - efi/tpm: Pass correct address to memblock_reserve
+    - tpm: fix signed/unsigned bug when checking event logs
+    - ARM: dts: cubieboard4: Fix DCDC5 regulator constraints
+    - regmap: irq: Set lockdep class for hierarchical IRQ domains
+    - firmware: arm_scpi: Check the DVFS OPP count returned by the firmware
+    - drm/mm: Mark drm_mm_interval_tree*() functions with __maybe_unused
+    - wifi: ath9k: add range check for conn_rsp_epid in htc_connect_service()
+    - drm/omap: Fix locking in omap_gem_new_dmabuf()
+    - wifi: p54: Use IRQF_NO_AUTOEN flag in request_irq()
+    - wifi: mwifiex: Use IRQF_NO_AUTOEN flag in request_irq()
+    - drm/imx/ipuv3: Use IRQF_NO_AUTOEN flag in request_irq()
+    - dt-bindings: vendor-prefixes: Add NeoFidelity, Inc
+    - ASoC: fsl_micfil: Drop unnecessary register read
+    - ASoC: fsl_micfil: do not define SHIFT/MASK for single bits
+    - ASoC: fsl_micfil: use GENMASK to define register bit fields
+    - ASoC: fsl_micfil: fix regmap_write_bits usage
+    - bpf: Fix the xdp_adjust_tail sample prog issue
+    - wifi: mwifiex: Fix memcpy() field-spanning write warning in
+      mwifiex_config_scan()
+    - drm/panfrost: Remove unused id_mask from struct panfrost_model
+    - drm/msm/adreno: Use IRQF_NO_AUTOEN flag in request_irq()
+    - drm/etnaviv: dump: fix sparse warnings
+    - drm/etnaviv: fix power register offset on GC300
+    - drm/etnaviv: hold GPU lock across perfmon sampling
+    - bpf, sockmap: Several fixes to bpf_msg_push_data
+    - bpf, sockmap: Several fixes to bpf_msg_pop_data
+    - bpf, sockmap: Fix sk_msg_reset_curr
+    - selftests: net: really check for bg process completion
+    - net: rfkill: gpio: Add check for clk_enable()
+    - ALSA: us122l: Use snd_card_free_when_closed() at disconnection
+    - ALSA: caiaq: Use snd_card_free_when_closed() at disconnection
+    - ALSA: 6fire: Release resources at card release
+    - netpoll: Use rcu_access_pointer() in netpoll_poll_lock
+    - trace/trace_event_perf: remove duplicate samples on the first tracepoint
+      event
+    - powerpc/vdso: Flag VDSO64 entry points as functions
+    - mfd: tps65010: Use IRQF_NO_AUTOEN flag in request_irq() to fix race
+    - mfd: da9052-spi: Change read-mask to write-mask
+    - mfd: intel_soc_pmic_bxtwc: Use dev_err_probe()
+    - mfd: intel_soc_pmic_bxtwc: Use IRQ domain for USB Type-C device
+    - mfd: intel_soc_pmic_bxtwc: Use IRQ domain for TMU device
+    - mfd: intel_soc_pmic_bxtwc: Use IRQ domain for PMIC devices
+    - cpufreq: loongson2: Unregister platform_driver on failure
+    - mtd: rawnand: atmel: Fix possible memory leak
+    - RDMA/bnxt_re: Check cqe flags to know imm_data vs inv_irkey
+    - mfd: rt5033: Fix missing regmap_del_irq_chip()
+    - scsi: bfa: Fix use-after-free in bfad_im_module_exit()
+    - scsi: fusion: Remove unused variable 'rc'
+    - scsi: qedf: Fix a possible memory leak in qedf_alloc_and_init_sb()
+    - scsi: qedi: Fix a possible memory leak in qedi_alloc_and_init_sb()
+    - ocfs2: fix uninitialized value in ocfs2_file_read_iter()
+    - powerpc/sstep: make emulate_vsx_load and emulate_vsx_store static
+    - fbdev/sh7760fb: Alloc DMA memory from hardware device
+    - fbdev: sh7760fb: Fix a possible memory leak in sh7760fb_alloc_mem()
+    - dt-bindings: clock: adi,axi-clkgen: convert old binding to yaml format
+    - dt-bindings: clock: axi-clkgen: include AXI clk
+    - clk: axi-clkgen: use devm_platform_ioremap_resource() short-hand
+    - clk: clk-axi-clkgen: make sure to enable the AXI bus clock
+    - perf cs-etm: Don't flush when packet_queue fills up
+    - perf probe: Correct demangled symbols in C++ program
+    - PCI: cpqphp: Use PCI_POSSIBLE_ERROR() to check config reads
+    - PCI: cpqphp: Fix PCIBIOS_* return value confusion
+    - m68k: mcfgpio: Fix incorrect register offset for CONFIG_M5441x
+    - m68k: coldfire/device.c: only build FEC when HW macros are defined
+    - perf trace: Do not lose last events in a race
+    - perf trace: Avoid garbage when not printing a syscall's arguments
+    - rpmsg: glink: Add TX_DATA_CONT command while sending
+    - rpmsg: glink: Send READ_NOTIFY command in FIFO full case
+    - rpmsg: glink: Fix GLINK command prefix
+    - rpmsg: glink: use only lower 16-bits of param2 for CMD_OPEN name length
+    - NFSD: Prevent NULL dereference in nfsd4_process_cb_update()
+    - NFSD: Cap the number of bytes copied by nfs4_reset_recoverydir()
+    - NFSD: Fix nfsd4_shutdown_copy()
+    - vfio/pci: Properly hide first-in-list PCIe extended capability
+    - power: supply: core: Remove might_sleep() from power_supply_put()
+    - net: usb: lan78xx: Fix memory leak on device unplug by freeing PHY device
+    - tg3: Set coherent DMA mask bits to 31 for BCM57766 chipsets
+    - net: usb: lan78xx: Fix refcounting and autosuspend on invalid WoL
+      configuration
+    - marvell: pxa168_eth: fix call balance of pep->clk handling routines
+    - net: stmmac: dwmac-socfpga: Set RX watchdog interrupt as broken
+    - ipmr: convert /proc handlers to rcu_read_lock()
+    - ipmr: fix tables suspicious RCU usage
+    - usb: using mutex lock and supporting O_NONBLOCK flag in iowarrior_read()
+    - usb: yurex: make waiting on yurex_write interruptible
+    - USB: chaoskey: fail open after removal
+    - USB: chaoskey: Fix possible deadlock chaoskey_list_lock
+    - misc: apds990x: Fix missing pm_runtime_disable()
+    - staging: greybus: uart: clean up TIOCGSERIAL
+    - apparmor: fix 'Do simple duplicate message elimination'
+    - usb: ehci-spear: fix call balance of sehci clk handling routines
+    - cgroup: Make operations on the cgroup root_list RCU safe
+    - cgroup: Move rcu_head up near the top of cgroup_root
+    - soc: qcom: socinfo: fix revision check in qcom_socinfo_probe()
+    - ALSA: usb-audio: Fix potential out-of-bound accesses for Extigy and Mbox
+      devices
+    - ext4: supress data-race warnings in ext4_free_inodes_{count,set}()
+    - ext4: fix FS_IOC_GETFSMAP handling
+    - jfs: xattr: check invalid xattr size more strictly
+    - ASoC: codecs: Fix atomicity violation in snd_soc_component_get_drvdata()
+    - PCI: Fix use-after-free of slot->bus on hot remove
+    - comedi: Flush partial mappings in error case
+    - tty: ldsic: fix tty_ldisc_autoload sysctl's proc_handler
+    - Bluetooth: Fix type of len in rfcomm_sock_getsockopt{,_old}()
+    - Revert "usb: gadget: composite: fix OS descriptors w_value logic"
+    - serial: sh-sci: Clean sci_ports[0] after at earlycon exit
+    - Revert "serial: sh-sci: Clean sci_ports[0] after at earlycon exit"
+    - spi: Fix acpi deferred irq probe
+    - ubi: wl: Put source PEB into correct list if trying locking LEB failed
+    - um: ubd: Do not use drvdata in release
+    - um: net: Do not use drvdata in release
+    - serial: 8250: omap: Move pm_runtime_get_sync
+    - um: vector: Do not use drvdata in release
+    - sh: cpuinfo: Fix a warning for CONFIG_CPUMASK_OFFSTACK
+    - arm64: tls: Fix context-switching of tpidrro_el0 when kpti is enabled
+    - block: fix ordering between checking BLK_MQ_S_STOPPED request adding
+    - HID: wacom: Interpret tilt data from Intuos Pro BT as signed values
+    - media: wl128x: Fix atomicity violation in fmc_send_cmd()
+    - ALSA: hda/realtek: Update ALC225 depop procedure
+    - ALSA: hda/realtek: Set PCBeep to default value for ALC274
+    - ALSA: hda/realtek: Fix Internal Speaker and Mic boost of Infinix Y4 Max
+    - ALSA: hda/realtek: Apply quirk for Medion E15433
+    - usb: dwc3: gadget: Fix checking for number of TRBs left
+    - lib: string_helpers: silence snprintf() output truncation warning
+    - NFSD: Prevent a potential integer overflow
+    - SUNRPC: make sure cache entry active before cache_show
+    - rpmsg: glink: Propagate TX failures in intentless mode as well
+    - um: Fix potential integer overflow during physmem setup
+    - um: Fix the return value of elf_core_copy_task_fpregs
+    - um/sysrq: remove needless variable sp
+    - um: add show_stack_loglvl()
+    - um: Clean up stacktrace dump
+    - um: Always dump trace for specified task in show_stack
+    - NFSv4.0: Fix a use-after-free problem in the asynchronous open()
+    - rtc: st-lpc: Use IRQF_NO_AUTOEN flag in request_irq()
+    - rtc: abx80x: Fix WDT bit position of the status register
+    - rtc: check if __rtc_read_time was successful in rtc_timer_do_work()
+    - ubifs: Correct the total block count by deducting journal reservation
+    - ubi: fastmap: Fix duplicate slab cache names while attaching
+    - ubifs: authentication: Fix use-after-free in ubifs_tnc_end_commit
+    - jffs2: fix use of uninitialized variable
+    - block: return unsigned int from bdev_io_min
+    - 9p/xen: fix init sequence
+    - 9p/xen: fix release of IRQ
+    - rtc: ab-eoz9: don't fail temperature reads on undervoltage notification
+    - modpost: remove incorrect code in do_eisa_entry()
+    - SUNRPC: correct error code comment in xs_tcp_setup_socket()
+    - SUNRPC: Replace internal use of SOCKWQ_ASYNC_NOSPACE
+    - sunrpc: clear XPRT_SOCK_UPD_TIMEOUT when reset transport
+    - sh: intc: Fix use-after-free bug in register_intc_controller()
+    - ASoC: fsl_micfil: fix the naming style for mask definition
+    - quota: flush quota_release_work upon quota writeback
+    - btrfs: ref-verify: fix use-after-free after invalid ref action
+    - media: i2c: tc358743: Fix crash in the probe error path when using polling
+    - media: ts2020: fix null-ptr-deref in ts2020_probe()
+    - media: venus: Fix pm_runtime_set_suspended() with runtime pm enabled
+    - media: gspca: ov534-ov772x: Fix off-by-one error in set_frame_rate()
+    - media: platform: allegro-dvt: Fix possible memory leak in
+      allocate_buffers_internal()
+    - ovl: Filter invalid inodes with missing lookup function
+    - ftrace: Fix regression with module command in stack_trace_filter
+    - clk: qcom: gcc-qcs404: fix initial rate of GPLL3
+    - ad7780: fix division by zero in ad7780_write_raw()
+    - util_macros.h: fix/rework find_closest() macros
+    - i3c: master: Fix miss free init_dyn_addr at i3c_master_put_i3c_addrs()
+    - dm thin: Add missing destroy_work_on_stack()
+    - nfsd: make sure exp active before svc_export_show
+    - nfsd: fix nfs4_openowner leak when concurrent nfsd4_open occur
+    - drm/etnaviv: flush shader L1 cache after user commandstream
+    - iTCO_wdt: mask NMI_NOW bit for update_no_reboot_bit() call
+    - watchdog: mediatek: Make sure system reset gets asserted in
+      mtk_wdt_restart()
+    - can: sun4i_can: sun4i_can_err(): call can_change_state() even if cf is NULL
+    - can: sun4i_can: sun4i_can_err(): fix {rx,tx}_errors statistics
+    - ipvs: fix UB due to uninitialized stack access in ip_vs_protocol_init()
+    - netfilter: x_tables: fix LED ID check in led_tg_check()
+    - net/sched: tbf: correct backlog statistic for GSO packets
+    - can: j1939: j1939_session_new(): fix skb reference counting
+    - net/ipv6: release expired exception dst cached in socket
+    - dccp: Fix memory leak in dccp_feat_change_recv
+    - tipc: add reference counter to bearer
+    - tipc: enable creating a "preliminary" node
+    - tipc: add new AEAD key structure for user API
+    - tipc: Fix use-after-free of kernel socket in cleanup_bearer().
+    - net/qed: allow old cards not supporting "num_images" to work
+    - igb: Fix potential invalid memory access in igb_init_module()
+    - netfilter: ipset: Hold module reference while requesting a module
+    - netfilter: nft_set_hash: skip duplicated elements pending gc run
+    - xen/xenbus: reference count registered modules
+    - xenbus/backend: Add memory pressure handler callback
+    - xenbus/backend: Protect xenbus callback with lock
+    - xen/xenbus: fix locking
+    - xen: Fix the issue of resource not being properly released in
+      xenbus_dev_probe()
+    - x86/asm: Reorder early variables
+    - crypto: x86/aegis128 - access 32-bit arguments as 32-bit
+    - gpio: grgpio: use a helper variable to store the address of ofdev->dev
+    - gpio: grgpio: Add NULL check in grgpio_probe
+    - drm/sti: Add __iomem for mixer_dbg_mxn's parameter
+    - tcp_bpf: Fix the sk_mem_uncharge logic in tcp_bpf_sendmsg
+    - spi: mpc52xx: Add cancel_work_sync before module remove
+    - ocfs2: free inode when ocfs2_get_init_inode() fails
+    - bpf: Handle BPF_EXIST and BPF_NOEXIST for LPM trie
+    - bpf: Fix exact match conditions in trie_get_next_key()
+    - HID: wacom: fix when get product name maybe null pointer
+    - tracing: Fix cmp_entries_dup() to respect sort() comparison rules
+    - ocfs2: update seq_file index in ocfs2_dlm_seq_next
+    - scsi: qla2xxx: Fix NVMe and NPIV connect issue
+    - scsi: qla2xxx: Supported speed displayed incorrectly for VPorts
+    - scsi: qla2xxx: Remove check req_sg_cnt should be equal to rsp_sg_cnt
+    - nilfs2: fix potential out-of-bounds memory access in nilfs_find_entry()
+    - bcache: revert replacing IS_ERR_OR_NULL with IS_ERR again
+    - dma-buf: fix dma_fence_array_signaled v4
+    - regmap: detach regmap from dev on regmap_exit
+    - mmc: core: Further prevent card detect during shutdown
+    - s390/cpum_sf: Handle CPU hotplug remove during sampling
+    - media: uvcvideo: Add a quirk for the Kaiweets KTI-W02 infrared camera
+    - media: cx231xx: Add support for Dexatek USB Video Grabber 1d19:6108
+    - drm: panel-orientation-quirks: Add quirk for AYA NEO 2 model
+    - drm/mcde: Enable module autoloading
+    - drm/radeon/r600_cs: Fix possible int overflow in r600_packet3_check()
+    - samples/bpf: Fix a resource leak
+    - net: fec_mpc52xx_phy: Use %pa to format resource_size_t
+    - net: ethernet: fs_enet: Use %pa to format resource_size_t
+    - net/sched: cbs: Fix integer overflow in cbs_set_port_rate()
+    - af_packet: avoid erroring out after sock_init_data() in packet_create()
+    - Bluetooth: L2CAP: do not leave dangling sk pointer on error in
+      l2cap_sock_create()
+    - net: af_can: do not leave a dangling sk pointer in can_create()
+    - net: ieee802154: do not leave a dangling sk pointer in ieee802154_create()
+    - net: inet: do not leave a dangling sk pointer in inet_create()
+    - net: inet6: do not leave a dangling sk pointer in inet6_create()
+    - wifi: ath5k: add PCI ID for SX76X
+    - wifi: ath5k: add PCI ID for Arcadyan devices
+    - jfs: array-index-out-of-bounds fix in dtReadFirst
+    - jfs: fix shift-out-of-bounds in dbSplit
+    - jfs: fix array-index-out-of-bounds in jfs_readdir
+    - jfs: add a check to prevent array-index-out-of-bounds in dbAdjTree
+    - drm/amdgpu: set the right AMDGPU sg segment limitation
+    - wifi: ipw2x00: libipw_rx_any(): fix bad alignment
+    - wifi: brcmfmac: Fix oops due to NULL pointer dereference in
+      brcmf_sdiod_sglist_rw()
+    - Bluetooth: btusb: Add RTL8852BE device 0489:e123 to device tables
+    - ASoC: hdmi-codec: reorder channel allocation list
+    - rocker: fix link status detection in rocker_carrier_init()
+    - net/neighbor: clear error in case strict check is not set
+    - netpoll: Use rcu_access_pointer() in __netpoll_setup
+    - tracing: Use atomic64_inc_return() in trace_clock_counter()
+    - leds: class: Protect brightness_show() with led_cdev->led_access mutex
+    - scsi: st: Don't modify unknown block number in MTIOCGET
+    - scsi: st: Add MTIOCGET and MTLOAD to ioctls allowed after device reset
+    - pinctrl: qcom-pmic-gpio: add support for PM8937
+    - nvdimm: rectify the illogical code within nd_dax_probe()
+    - f2fs: fix f2fs_bug_on when uninstalling filesystem call f2fs_evict_inode.
+    - PCI: Add 'reset_subordinate' to reset hierarchy below bridge
+    - PCI: Add ACS quirk for Wangxun FF5xxx NICs
+    - i3c: Use i3cdev->desc->info instead of calling i3c_device_get_info() to
+      avoid deadlock
+    - usb: chipidea: udc: handle USB Error Interrupt if IOC not set
+    - powerpc/prom_init: Fixup missing powermac #size-cells
+    - misc: eeprom: eeprom_93cx6: Add quirk for extra read clock cycle
+    - xdp: Simplify devmap cleanup
+    - bpf: fix OOB devmap writes when deleting elements
+    - Revert "unicode: Don't special case ignorable code points"
+    - perf/x86/intel/pt: Fix buffer full but size is 0 case
+    - KVM: arm64: vgic-its: Add a data length check in vgic_its_save_*
+    - KVM: arm64: vgic-its: Clear DTE when MAPD unmaps a device
+    - KVM: arm64: vgic-its: Clear ITE when DISCARD frees an ITE
+    - jffs2: Prevent rtime decompress memory corruption
+    - jffs2: Fix rtime decompressor
+    - ocfs2: Revert "ocfs2: fix the la space leak when unmounting an ocfs2 volume"
+    - modpost: Add .irqentry.text to OTHER_SECTIONS
+    - Revert "drm/amdgpu: add missing size check in amdgpu_debugfs_gprwave_read()"
+    - PCI: rockchip-ep: Fix address translation unit programming
+    - ALSA: usb-audio: Fix out of bounds reads when finding clock sources
+    - bpf, xdp: Update devmap comments to reflect napi/rcu usage
+    - Linux 5.4.287
+  * CVE-2024-23848
+    - media: cec: abort if the current transmit was canceled
+    - media: cec: core: avoid recursive cec_claim_log_addrs
+    - media: cec: core: avoid confusing "transmit timed out" message
+
+  [ Ubuntu: 5.4.0-208.228 ]
+
+  * CVE-2025-0927
+    - SAUCE: fs: hfs/hfsplus: add key_len boundary check to hfs_bnode_read_key
+
+ -- Koichiro Den <koichiro.den@canonical.com>  Thu, 20 Feb 2025 12:02:39 +0900
+
+linux-xilinx-zynqmp (5.4.0-1058.62) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1058.62 -proposed tracker (LP: #2093783)
+
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233)
+    - [Config] xilinx-zynqmp: updateconfigs for SND_MESON_CARD_UTILS
+
+  [ Ubuntu: 5.4.0-207.227 ]
+
+  * focal/linux: 5.4.0-207.227 -proposed tracker (LP: #2095347)
+  * Remove "ftrace: Fix possible use-after-free issue in ftrace_location()" bad
+    commit from focal (LP: #2095348)
+    - Revert "ftrace: Fix possible use-after-free issue in ftrace_location()"
+
+  [ Ubuntu: 5.4.0-206.226 ]
+
+  * focal/linux: 5.4.0-206.226 -proposed tracker (LP: #2093785)
+  * nouveau keeps showing `disp: ctrl 00000080` and crippling the system
+    (LP: #2078011)
+    - drm/nouveau/disp/gv100-: halt NV_PDISP_FE_RM_INTR_STAT_CTRL_DISP_ERROR
+      storms
+    - drm/nouveau/kms/gv100-: move window ownership setup into modesetting path
+    - drm/nouveau/kms/gv100-: avoid sending a core update until the first modeset
+  * CVE-2024-43863
+    - drm/vmwgfx: Fix a deadlock in dma buf fence polling
+  * CVE-2024-40911
+    - wifi: cfg80211: Lock wiphy in cfg80211_get_station
+  * CVE-2024-35896
+    - netfilter: validate user input for expected length
+    - netfilter: complete validation of user input
+  * CVE-2023-52458
+    - block: add check that partition length needs to be aligned with block size
+  * kernel:nft "Could not process rule: Device or resource busy" on unreferenced
+    chain (LP: #2089699)
+    - SAUCE: netfilter: nf_tables: Fix EBUSY on deleting unreferenced chain
+  * CVE-2024-35887
+    - lockdep: Add preemption enabled/disabled assertion APIs
+    - timers: Don't block on ->expiry_lock for TIMER_IRQSAFE timers
+    - Documentation: Remove bogus claim about del_timer_sync()
+    - ARM: spear: Do not use timer namespace for timer_shutdown() function
+    - clocksource/drivers/arm_arch_timer: Do not use timer namespace for
+      timer_shutdown() function
+    - clocksource/drivers/sp804: Do not use timer namespace for timer_shutdown()
+      function
+    - timers: Get rid of del_singleshot_timer_sync()
+    - timers: Replace BUG_ON()s
+    - timers: Rename del_timer() to timer_delete()
+    - Documentation: Replace del_timer/del_timer_sync()
+    - timers: Silently ignore timers with a NULL function
+    - timers: Split [try_to_]del_timer[_sync]() to prepare for shutdown mode
+    - timers: Add shutdown mechanism to the internal functions
+    - timers: Provide timer_shutdown[_sync]()
+    - timers: Update the documentation to reflect on the new timer_shutdown() API
+    - ax25: fix use-after-free bugs caused by ax25_ds_del_timer
+  * CVE-2024-40965
+    - clk: Add a devm variant of clk_rate_exclusive_get()
+    - clk: Provide !COMMON_CLK dummy for devm_clk_rate_exclusive_get()
+    - i2c: lpi2c: Avoid calling clk_get_rate during transfer
+  * CVE-2024-40982
+    - ssb: Fix potential NULL pointer dereference in ssb_device_uevent()
+  * CVE-2024-41066
+    - ibmvnic: Add tx check to prevent skb leak
+  * CVE-2024-42252
+    - closures: Change BUG_ON() to WARN_ON()
+  * CVE-2024-46731
+    - drm/amd/pm: fix the Out-of-bounds read warning
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558)
+    - arm64: dts: rockchip: Fix rt5651 compatible value on rk3399-sapphire-
+      excavator
+    - arm64: dts: rockchip: Remove hdmi's 2nd interrupt on rk3328
+    - arm64: dts: rockchip: Fix bluetooth properties on Rock960 boards
+    - arm64: dts: rockchip: Remove #cooling-cells from fan on Theobroma lion
+    - ARM: dts: rockchip: fix rk3036 acodec node
+    - ARM: dts: rockchip: drop grf reference from rk3036 hdmi
+    - ARM: dts: rockchip: Fix the spi controller on rk3036
+    - ARM: dts: rockchip: Fix the realtek audio codec on rk3036-kylin
+    - enetc: simplify the return expression of enetc_vf_set_mac_addr()
+    - net: enetc: set MAC address to the VF net_device
+    - can: c_can: fix {rx,tx}_errors statistics
+    - media: stb0899_algo: initialize cfr before using it
+    - media: dvb_frontend: don't play tricks with underflow values
+    - media: adv7604: prevent underflow condition when reporting colorspace
+    - ALSA: firewire-lib: fix return value on fail in amdtp_tscm_init()
+    - pwm: imx-tpm: Use correct MODULO value for EPWM mode
+    - drm/amdgpu: prevent NULL pointer dereference if ATIF is not supported
+    - dm cache: correct the number of origin blocks to match the target length
+    - dm cache: optimize dirty bit checking with find_next_bit when resizing
+    - dm-unstriped: cast an operand to sector_t to prevent potential uint32_t
+      overflow
+    - mtd: rawnand: protect access to rawnand devices while in suspend
+    - spi: fix use-after-free of the add_lock mutex
+    - media: uvcvideo: Skip parsing frames of type UVC_VS_UNDEFINED in
+      uvc_parse_format
+    - fs/proc: fix compile warning about variable 'vmcore_mmap_ops'
+    - USB: serial: qcserial: add support for Sierra Wireless EM86xx
+    - USB: serial: option: add Fibocom FG132 0x0112 composition
+    - USB: serial: option: add Quectel RG650V
+    - irqchip/gic-v3: Force propagation of the active state with a read-back
+    - ALSA: usb-audio: Support jack detection on Dell dock
+    - ALSA: usb-audio: Add quirks for Dell WD19 dock
+    - NFSD: Fix NFSv4's PUTPUBFH operation
+    - ALSA: usb-audio: Add endianness annotations
+    - 9p: Avoid creating multiple slab caches with the same name
+    - HID: multitouch: Add quirk for HONOR MagicBook Art 14 touchpad
+    - bpf: use kvzmalloc to allocate BPF verifier environment
+    - sound: Make CONFIG_SND depend on INDIRECT_IOMEM instead of UML
+    - powerpc/powernv: Free name on error in opal_event_init()
+    - fs: Fix uninitialized value issue in from_kuid and from_kgid
+    - net: usb: qmi_wwan: add Fibocom FG132 0x0112 composition
+    - md/raid10: improve code of mrdev in raid10_sync_request
+    - mm: clarify a confusing comment for remap_pfn_range()
+    - mm: fix ambiguous comments for better code readability
+    - mm/memory.c: make remap_pfn_range() reject unaligned addr
+    - mm: add remap_pfn_range_notrack
+    - 9p: fix slab cache name creation for real
+    - Linux 5.4.286
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-47674
+    - mm: avoid leaving partial pfn mappings around in error case
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-38588
+    - ftrace: Fix possible use-after-free issue in ftrace_location()
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50265
+    - ocfs2: remove entry once instead of null-ptr-dereference in
+      ocfs2_xa_remove()
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50267
+    - USB: serial: io_edgeport: fix use after free in debug printk
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50269
+    - usb: musb: sunxi: Fix accessing an released usb phy
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2021-47469
+    - spi: Fix deadlock when adding SPI controllers on SPI buses
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50273
+    - btrfs: reinitialize delayed ref list after deleting it from the list
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-53066
+    - nfs: Fix KMSAN warning in decode_getfattr_attrs()
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50278
+    - dm cache: fix potential out-of-bounds access on the first resume
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50279
+    - dm cache: fix out-of-bounds access to the dirty bitset when resizing
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50282
+    - drm/amdgpu: add missing size check in amdgpu_debugfs_gprwave_read()
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50287
+    - media: v4l2-tpg: prevent the risk of a division by zero
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50290
+    - media: cx24116: prevent overflows on SNR calculus
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-53061
+    - media: s5p-jpeg: prevent buffer overflows
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-53063
+    - media: dvbdev: prevent the risk of out of memory access
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50296
+    - net: hns3: fix kernel crash when uninstalling driver
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50299
+    - sctp: properly validate chunk size in sctp_sf_ootb()
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50301
+    - security/keys: fix slab-out-of-bounds in key_task_permission
+  * Focal update: v5.4.286 upstream stable release (LP: #2089558) //
+    CVE-2024-50302
+    - HID: core: zero-initialize the report buffer
+  * Add list of source files to linux-buildinfo (LP: #2086606)
+    - [Packaging] Sort build dependencies alphabetically
+    - [Packaging] Add list of used source files to buildinfo package
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233)
+    - usbnet: ipheth: fix carrier detection in modes 1 and 4
+    - net: ethernet: use ip_hdrlen() instead of bit shift
+    - net: phy: vitesse: repair vsc73xx autonegotiation
+    - scripts: kconfig: merge_config: config files: add a trailing newline
+    - arm64: dts: rockchip: override BIOS_DISABLE signal via GPIO hog on RK3399
+      Puma
+    - ice: fix accounting for filters shared by multiple VSIs
+    - net/mlx5e: Add missing link modes to ptys2ethtool_map
+    - net: ftgmac100: Enable TX interrupt to avoid TX timeout
+    - soundwire: stream: Revert "soundwire: stream: fix programming slave ports
+      for non-continous port maps"
+    - selftests: breakpoints: Fix a typo of function name
+    - ASoC: allow module autoloading for table db1200_pids
+    - ALSA: hda/realtek - Fixed ALC256 headphone no sound
+    - ALSA: hda/realtek - FIxed ALC285 headphone no sound
+    - pinctrl: at91: make it work with current gpiolib
+    - microblaze: don't treat zero reserved memory regions as error
+    - net: ftgmac100: Ensure tx descriptor updates are visible
+    - wifi: iwlwifi: mvm: fix iwl_mvm_max_scan_ie_fw_cmd_room()
+    - ASoC: tda7419: fix module autoloading
+    - drm: komeda: Fix an issue related to normalized zpos
+    - spi: bcm63xx: Enable module autoloading
+    - x86/hyperv: Set X86_FEATURE_TSC_KNOWN_FREQ when Hyper-V provides frequency
+    - USB: serial: pl2303: add device id for Macrosilicon MS3020
+    - ACPI: PMIC: Remove unneeded check in tps68470_pmic_opregion_probe()
+    - wifi: ath9k: fix parameter check in ath9k_init_debug()
+    - wifi: ath9k: Remove error checks when creating debugfs entries
+    - fs: explicitly unregister per-superblock BDIs
+    - mount: warn only once about timestamp range expiration
+    - fs/namespace: fnic: Switch to use %ptTd
+    - mount: handle OOM on mnt_warn_timestamp_expiry
+    - can: j1939: use correct function name in comment
+    - netfilter: nf_tables: elements with timeout below CONFIG_HZ never expire
+    - netfilter: nf_tables: reject element expiration with no timeout
+    - netfilter: nf_tables: reject expiration higher than timeout
+    - wifi: cfg80211: fix UBSAN noise in cfg80211_wext_siwscan()
+    - wifi: cfg80211: fix two more possible UBSAN-detected off-by-one errors
+    - mac80211: parse radiotap header when selecting Tx queue
+    - Bluetooth: btusb: Fix not handling ZPL/short-transfer
+    - net: tipc: avoid possible garbage value
+    - block, bfq: choose the last bfqq from merge chain in bfq_setup_cooperator()
+    - block, bfq: don't break merge chain in bfq_split_bfqq()
+    - spi: ppc4xx: handle irq_of_parse_and_map() errors
+    - spi: ppc4xx: Avoid returning 0 when failed to parse and map IRQ
+    - ARM: dts: imx7d-zii-rmu2: fix Ethernet PHY pinctrl property
+    - ARM: versatile: fix OF node leak in CPUs prepare
+    - reset: berlin: fix OF node leak in probe() error path
+    - clocksource/drivers/qcom: Add missing iounmap() on errors in
+      msm_dt_timer_init()
+    - hwmon: (max16065) Fix overflows seen when writing limits
+    - mtd: slram: insert break after errors in parsing the map
+    - hwmon: (ntc_thermistor) fix module autoloading
+    - power: supply: axp20x_battery: allow disabling battery charging
+    - power: supply: axp20x_battery: Remove design from min and max voltage
+    - power: supply: max17042_battery: Fix SOC threshold calc w/ no current sense
+    - fbdev: hpfb: Fix an error handling path in hpfb_dio_probe()
+    - mtd: powernv: Add check devm_kasprintf() returned value
+    - drm/stm: Fix an error handling path in stm_drm_platform_probe()
+    - drm/amdgpu: Replace one-element array with flexible-array member
+    - drm/amdgpu: properly handle vbios fake edid sizing
+    - drm/radeon: Replace one-element array with flexible-array member
+    - drm/radeon: properly handle vbios fake edid sizing
+    - drm/rockchip: vop: Allow 4096px width scaling
+    - drm/rockchip: dw_hdmi: Fix reading EDID when using a forced mode
+    - drm/radeon/evergreen_cs: fix int overflow errors in cs track offsets
+    - drm/msm: Fix incorrect file name output in adreno_request_fw()
+    - drm/msm/a5xx: disable preemption in submits by default
+    - drm/msm/a5xx: properly clear preemption records on resume
+    - drm/msm/a5xx: fix races in preemption evaluation stage
+    - ipmi: docs: don't advertise deprecated sysfs entries
+    - drm/msm: fix %s null argument error
+    - drivers:drm:exynos_drm_gsc:Fix wrong assignment in gsc_bind()
+    - xen: use correct end address of kernel for conflict checking
+    - xen/swiotlb: add alignment check for dma buffers
+    - selftests/bpf: Fix compile error from rlim_t in sk_storage_map.c
+    - selftests/bpf: Fix compiling flow_dissector.c with musl-libc
+    - selftests/bpf: Fix compiling tcp_rtt.c with musl-libc
+    - selftests/bpf: Fix error compiling test_lru_map.c
+    - xz: cleanup CRC32 edits from 2018
+    - kthread: add kthread_work tracepoints
+    - kthread: fix task state in kthread worker if being frozen
+    - ext4: clear EXT4_GROUP_INFO_WAS_TRIMMED_BIT even mount with discard
+    - smackfs: Use rcu_assign_pointer() to ensure safe assignment in smk_set_cipso
+    - ext4: avoid negative min_clusters in find_group_orlov()
+    - ext4: return error on ext4_find_inline_entry
+    - nilfs2: determine empty node blocks as corrupted
+    - bpf: Fix bpf_strtol and bpf_strtoul helpers for 32bit
+    - perf sched timehist: Fix missing free of session in perf_sched__timehist()
+    - perf sched timehist: Fixed timestamp error when unable to confirm event
+      sched_in time
+    - perf time-utils: Fix 32-bit nsec parsing
+    - clk: rockchip: Set parent rate for DCLK_VOP clock on RK3228
+    - PCI: xilinx-nwl: Fix register misspelling
+    - pinctrl: single: fix missing error code in pcs_probe()
+    - clk: ti: dra7-atl: Fix leak of of_nodes
+    - pinctrl: mvebu: Fix devinit_dove_pinctrl_probe function
+    - watchdog: imx_sc_wdt: Don't disable WDT in suspend
+    - RDMA/hns: Optimize hem allocation performance
+    - riscv: Fix fp alignment bug in perf_callchain_user()
+    - f2fs: enhance to update i_mode and acl atomically in f2fs_setattr()
+    - f2fs: fix typo
+    - f2fs: fix to update i_ctime in __f2fs_setxattr()
+    - f2fs: remove unneeded check condition in __f2fs_setxattr()
+    - f2fs: reduce expensive checkpoint trigger frequency
+    - iio: adc: ad7606: fix oversampling gpio array
+    - iio: adc: ad7606: fix standby gpio state to match the documentation
+    - coresight: tmc: sg: Do not leak sg_table
+    - net: qrtr: Update packets cloning when broadcasting
+    - netfilter: ctnetlink: compile ctnetlink_label_size with
+      CONFIG_NF_CONNTRACK_EVENTS
+    - Remove *.orig pattern from .gitignore
+    - soc: versatile: integrator: fix OF node leak in probe() error path
+    - drm/amd/display: Round calculated vtotal
+    - USB: appledisplay: close race between probe and completion handler
+    - USB: misc: cypress_cy7c63: check for short transfer
+    - USB: class: CDC-ACM: fix race between get_serial and set_serial
+    - tty: rp2: Fix reset with non forgiving PCIe host bridges
+    - drbd: Fix atomicity violation in drbd_uuid_set_bm()
+    - drbd: Add NULL check for net_conf to prevent dereference in state validation
+    - ACPI: resource: Add another DMI match for the TongFang GMxXGxx
+    - wifi: rtw88: 8822c: Fix reported RX band width
+    - debugobjects: Fix conditions in fill_pool()
+    - f2fs: prevent possible int overflow in dir_block_index()
+    - f2fs: avoid potential int overflow in sanity_check_area_boundary()
+    - hwrng: mtk - Use devm_pm_runtime_enable
+    - fs: Fix file_set_fowner LSM hook inconsistencies
+    - nfs: fix memory leak in error path of nfs4_do_reclaim
+    - ASoC: meson: axg: extract sound card utils
+    - [Config] updateconfigs for SND_MESON_CARD_UTILS
+    - PCI: xilinx-nwl: Use irq_data_get_irq_chip_data()
+    - PCI: xilinx-nwl: Fix off-by-one in INTx IRQ handler
+    - soc: versatile: realview: fix memory leak during device remove
+    - soc: versatile: realview: fix soc_dev leak during device remove
+    - usb: yurex: Replace snprintf() with the safer scnprintf() variant
+    - USB: misc: yurex: fix race between read and write
+    - pps: remove usage of the deprecated ida_simple_xx() API
+    - pps: add an error check in parport_attach
+    - mm: only enforce minimum stack gap size if it's sensible
+    - i2c: aspeed: Update the stop sw state when the bus recovery occurs
+    - i2c: isch: Add missed 'else'
+    - usb: yurex: Fix inconsistent locking bug in yurex_read()
+    - mailbox: rockchip: fix a typo in module autoloading
+    - Minor fixes to the CAIF Transport drivers Kconfig file
+    - drivers: net: Fix Kconfig indentation, continued
+    - ieee802154: Fix build error
+    - net/mlx5: Added cond_resched() to crdump collection
+    - netfilter: uapi: NFTA_FLOWTABLE_HOOK is NLA_NESTED
+    - net: ieee802154: mcr20a: Use IRQF_NO_AUTOEN flag in request_irq()
+    - Bluetooth: btmrvl_sdio: Refactor irq wakeup
+    - Bluetooth: btmrvl: Use IRQF_NO_AUTOEN flag in request_irq()
+    - ipv4: ip_gre: Fix drops of small packets in ipgre_xmit
+    - ALSA: hda/realtek: Fix the push button function for the ALC257
+    - ALSA: hda/generic: Unconditionally prefer preferred_dacs pairs
+    - ALSA: hda/conexant: Fix conflicting quirk for System76 Pangolin
+    - wifi: ath9k: fix possible integer overflow in ath9k_get_et_stats()
+    - ice: Adjust over allocation of memory in ice_sched_add_root_node() and
+      ice_sched_add_node()
+    - net: hisilicon: hip04: fix OF node leak in probe()
+    - net: hisilicon: hns_dsaf_mac: fix OF node leak in hns_mac_get_info()
+    - net: hisilicon: hns_mdio: fix OF node leak in probe()
+    - ACPICA: Fix memory leak if acpi_ps_get_next_namepath() fails
+    - ACPICA: Fix memory leak if acpi_ps_get_next_field() fails
+    - net: sched: consistently use rcu_replace_pointer() in taprio_change()
+    - wifi: rtw88: select WANT_DEV_COREDUMP
+    - ACPI: EC: Do not release locks during operation region accesses
+    - net: mvpp2: Increase size of queue_name buffer
+    - ipv4: Check !in_dev earlier for ioctl(SIOCSIFADDR).
+    - ipv4: Mask upper DSCP bits and ECN bits in NETLINK_FIB_LOOKUP family
+    - tcp: avoid reusing FIN_WAIT2 when trying to find port in connect() process
+    - ACPICA: iasl: handle empty connection_node
+    - proc: add config & param to block forcing mem writes
+    - [Config] updateconfigs to select PROC_MEM_ALWAYS_FORCE
+    - nfp: Use IRQF_NO_AUTOEN flag in request_irq()
+    - signal: Replace BUG_ON()s
+    - ALSA: hdsp: Break infinite MIDI input flush loop
+    - x86/syscall: Avoid memcpy() for ia32 syscall_get_arguments()
+    - power: reset: brcmstb: Do not go into infinite loop if reset fails
+    - ata: sata_sil: Rename sil_blacklist to sil_quirks
+    - jfs: UBSAN: shift-out-of-bounds in dbFindBits
+    - drm/printer: Allow NULL data in devcoredump printer
+    - scsi: aacraid: Rearrange order of struct aac_srb_unit
+    - drm/radeon/r100: Handle unknown family in r100_cp_init_microcode()
+    - of/irq: Refer to actual buffer size in of_irq_parse_one()
+    - ext4: ext4_search_dir should return a proper error
+    - spi: s3c64xx: fix timeout counters in flush_fifo
+    - selftests: breakpoints: use remaining time to check if suspend succeed
+    - selftests: vDSO: fix vDSO symbols lookup for powerpc64
+    - i2c: xiic: Wait for TX empty to avoid missed TX NAKs
+    - firmware: tegra: bpmp: Drop unused mbox_client_to_bpmp()
+    - spi: bcm63xx: Fix module autoloading
+    - perf/core: Fix small negative period being ignored
+    - parisc: Fix itlb miss handler for 64-bit programs
+    - drm: Consistently use struct drm_mode_rect for FB_DAMAGE_CLIPS
+    - ALSA: core: add isascii() check to card ID generator
+    - ext4: propagate errors from ext4_find_extent() in ext4_insert_range()
+    - ext4: fix incorrect tid assumption in __jbd2_log_wait_for_space()
+    - ext4: fix incorrect tid assumption in ext4_wait_for_tail_page_commit()
+    - parisc: Fix 64-bit userspace syscall path
+    - parisc: Fix stack start for ADDR_NO_RANDOMIZE personality
+    - of/irq: Support #msi-cells=<0> in of_msi_get_domain
+    - mm: krealloc: consider spare memory for __GFP_ZERO
+    - ocfs2: fix the la space leak when unmounting an ocfs2 volume
+    - ocfs2: fix uninit-value in ocfs2_get_block()
+    - riscv: define ILLEGAL_POINTER_VALUE for 64bit
+    - clk: rockchip: fix error for unknown clocks
+    - media: sun4i_csi: Implement link validate for sun4i_csi subdev
+    - media: uapi/linux/cec.h: cec_msg_set_reply_to: zero flags
+    - iio: magnetometer: ak8975: Fix reading for ak099xx sensors
+    - tomoyo: fallback to realpath if symlink's pathname does not exist
+    - rtc: at91sam9: fix OF node leak in probe() error path
+    - Input: adp5589-keys - fix adp5589_gpio_get_value()
+    - ACPI: resource: Add Asus Vivobook X1704VAP to irq1_level_low_skip_override[]
+    - ACPI: resource: Add Asus ExpertBook B2502CVA to
+      irq1_level_low_skip_override[]
+    - gpio: davinci: fix lazy disable
+    - i2c: qcom-geni: Let firmware specify irq trigger flags
+    - i2c: qcom-geni: Grow a dev pointer to simplify code
+    - i2c: qcom-geni: Use IRQF_NO_AUTOEN flag in request_irq()
+    - arm64: Add Cortex-715 CPU part definition
+    - arm64: cputype: Add Neoverse-N3 definitions
+    - arm64: errata: Expand speculative SSBS workaround once more
+    - nfsd: use ktime_get_seconds() for timestamps
+    - nfsd: fix delegation_blocked() to block correctly for at least 30 seconds
+    - clk: qcom: rpmh: Simplify clk_rpmh_bcm_send_cmd()
+    - clk: qcom: clk-rpmh: Fix overflow in BCM vote
+    - r8169: Fix spelling mistake: "tx_underun" -> "tx_underrun"
+    - ACPI: battery: Simplify battery hook locking
+    - ext4: fix inode tree inconsistency caused by ENOMEM
+    - net: ethernet: cortina: Drop TSO support
+    - tracing: Remove precision vsnprintf() check from print event
+    - drm/crtc: fix uninitialized variable use even harder
+    - tracing: Have saved_cmdlines arrays all in one allocation
+    - virtio_console: fix misc probe bugs
+    - Input: synaptics-rmi4 - fix UAF of IRQ domain on driver removal
+    - bpf: Check percpu map value size first
+    - s390/facility: Disable compile time optimization for decompressor code
+    - s390/mm: Add cond_resched() to cmm_alloc/free_pages()
+    - ext4: nested locking for xattr inode
+    - s390/cpum_sf: Remove WARN_ON_ONCE statements
+    - ktest.pl: Avoid false positives with grub2 skip regex
+    - clk: bcm: bcm53573: fix OF node leak in init
+    - PCI: Add ACS quirk for Qualcomm SA8775P
+    - i2c: i801: Use a different adapter-name for IDF adapters
+    - PCI: Mark Creative Labs EMU20k2 INTx masking as broken
+    - media: videobuf2-core: clear memory related fields in
+      __vb2_plane_dmabuf_put()
+    - usb: chipidea: udc: enable suspend interrupt after usb reset
+    - usb: dwc2: Adjust the timing of USB Driver Interrupt Registration in the
+      Crashkernel Scenario
+    - tools/iio: Add memory allocation failure check for trigger_name
+    - driver core: bus: Return -EIO instead of 0 when show/store invalid bus
+      attribute
+    - ice: fix VLAN replay after reset
+    - SUNRPC: Fix integer overflow in decode_rc_list()
+    - tcp: fix to allow timestamp undo if no retransmits were sent
+    - tcp: fix tcp_enter_recovery() to zero retrans_stamp when it's safe
+    - gpio: aspeed: Add the flush write to ensure the write complete.
+    - gpio: aspeed: Use devm_clk api to manage clock source
+    - net: ibm: emac: mal: fix wrong goto
+    - net: annotate lockless accesses to sk->sk_ack_backlog
+    - net: annotate lockless accesses to sk->sk_max_ack_backlog
+    - sctp: ensure sk_state is set to CLOSED if hashing fails in sctp_listen_start
+    - locking/lockdep: Fix bad recursion pattern
+    - locking/lockdep: Rework lockdep_lock
+    - locking/lockdep: Avoid potential access of invalid memory in lock_class
+    - lockdep: fix deadlock issue between lockdep and rcu
+    - HID: plantronics: Workaround for an unexcepted opposite volume key
+    - Revert "usb: yurex: Replace snprintf() with the safer scnprintf() variant"
+    - usb: dwc3: core: Stop processing of pending events if controller is halted
+    - usb: xhci: Fix problem with xhci resume from suspend
+    - usb: storage: ignore bogus device raised by JieLi BR21 USB sound chip
+    - hid: intel-ish-hid: Fix uninitialized variable 'rv' in
+      ish_fw_xfer_direct_dma
+    - arm64: probes: Fix simulate_ldr*_literal()
+    - tracing/kprobes: Return EADDRNOTAVAIL when func matches several symbols
+    - tracing/kprobes: Fix symbol counting logic by looking at modules as well
+    - PCI: Add function 0 DMA alias quirk for Glenfly Arise chip
+    - fat: fix uninitialized variable
+    - s390/sclp_vt220: Convert newlines to CRLF instead of LFCR
+    - KVM: s390: Change virtual to physical address access in diag 0x258 handler
+    - x86/cpufeatures: Define X86_FEATURE_AMD_IBPB_RET
+    - drm/vmwgfx: Handle surface check failure correctly
+    - iio: dac: ltc1660: add missing select REGMAP_SPI in Kconfig
+    - iio: dac: stm32-dac-core: add missing select REGMAP_MMIO in Kconfig
+    - iio: adc: ti-ads8688: add missing select IIO_(TRIGGERED_)BUFFER in Kconfig
+    - iio: hid-sensors: Fix an error handling path in
+      _hid_sensor_set_report_latency()
+    - iio: light: opt3001: add missing full-scale range value
+    - iio: proximity: mb1232: add missing select IIO_(TRIGGERED_)BUFFER in Kconfig
+    - iio: adc: ti-ads124s08: add missing select IIO_(TRIGGERED_)BUFFER in Kconfig
+    - Bluetooth: Remove debugfs directory on module init failure
+    - Bluetooth: btusb: Fix regression with fake CSR controllers 0a12:0001
+    - xhci: Fix incorrect stream context type macro
+    - USB: serial: option: add support for Quectel EG916Q-GL
+    - USB: serial: option: add Telit FN920C04 MBIM compositions
+    - x86/resctrl: Annotate get_mem_config() functions as __init
+    - x86/apic: Always explicitly disarm TSC-deadline timer
+    - mac80211: Fix NULL ptr deref for injected rate info
+    - RDMA/bnxt_re: Fix incorrect AVID type in WQE structure
+    - ARM: dts: bcm2837-rpi-cm3-io3: Fix HDMI hpd-gpio pin
+    - RDMA/cxgb4: Fix RDMA_CM_EVENT_UNREACHABLE error for iWARP
+    - ipv4: give an IPv4 dev to blackhole_netdev
+    - RDMA/bnxt_re: Return more meaningful error
+    - drm/msm/dsi: fix 32-bit signed integer extension in pclk_rate calculation
+    - macsec: don't increment counters for an unrelated SA
+    - net: ethernet: aeroflex: fix potential memory leak in
+      greth_start_xmit_gbit()
+    - genetlink: hold RCU in genlmsg_mcast()
+    - arm64:uprobe fix the uprobe SWBP_INSN in big-endian
+    - KVM: s390: gaccess: Check if guest address is in memslot
+    - jfs: Fix sanity check in dbMount
+    - net: usb: usbnet: fix name regression
+    - r8169: avoid unsolicited interrupts
+    - posix-clock: posix-clock: Fix unbalanced locking in pc_clock_settime()
+    - ALSA: hda/realtek: Update default depop procedure
+    - ACPI: resource: Add LG 16T90SP to irq1_level_low_skip_override[]
+    - ACPI: button: Add DMI quirk for Samsung Galaxy Book2 to fix initial lid
+      detection issue
+    - ALSA: hda/realtek: Add subwoofer quirk for Acer Predator G9-593
+    - hv_netvsc: Fix VF namespace also in synthetic NIC NETDEV_REGISTER event
+    - selinux: improve error checking in sel_write_load()
+    - arm64/uprobes: change the uprobe_opcode_t typedef to fix the sparse warning
+    - cgroup: Fix potential overflow issue when checking max_depth
+    - wifi: mac80211: skip non-uploaded keys in ieee80211_iter_keys
+    - mac80211: do drv_reconfig_complete() before restarting all
+    - mac80211: Add support to trigger sta disconnect on hardware restart
+    - wifi: iwlwifi: mvm: disconnect station vifs if recovery failed
+    - ASoC: cs42l51: Fix some error handling paths in cs42l51_probe()
+    - dt-bindings: gpu: Convert Samsung Image Rotator to dt-schema
+    - gtp: simplify error handling code in 'gtp_encap_enable()'
+    - gtp: allow -1 to be specified as file description from userspace
+    - net: support ip generic csum processing in skb_csum_hwoffload_help
+    - net: skip offload for NETIF_F_IPV6_CSUM if ipv6 header contains extension
+    - drivers/misc: ti-st: Remove unneeded variable in st_tty_open
+    - firmware: arm_sdei: Fix the input parameter of cpuhp_remove_state()
+    - net: amd: mvme147: Fix probe banner message
+    - misc: sgi-gru: Don't disable preemption in GRU driver
+    - usbip: tools: Fix detach_port() invalid port error path
+    - usb: phy: Fix API devm_usb_put_phy() can not release the phy
+    - xhci: Fix Link TRB DMA in command ring stopped completion event
+    - Revert "driver core: Fix uevent_show() vs driver detach race"
+    - riscv: Remove unused GENERATING_ASM_OFFSETS
+    - Revert "drm/mipi-dsi: Set the fwnode for mipi_dsi_device"
+    - vt: prevent kernel-infoleak in con_font_get()
+    - mac80211: always have ieee80211_sta_restart()
+    - mm: krealloc: Fix MTE false alarm in __do_krealloc
+    - Linux 5.4.285
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50228
+    - mm: shmem: fix data-race in shmem_getattr()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50230
+    - nilfs2: fix kernel bug due to missing clearing of checked flag
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50218
+    - ocfs2: pass u64 to ocfs2_truncate_inline maybe overflow
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50229
+    - nilfs2: fix potential deadlock with newly created symlinks
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50233
+    - staging: iio: frequency: ad9832: fix division by zero in
+      ad9832_calc_freqreg()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50234
+    - wifi: iwlegacy: Clear stale interrupts before resuming device
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50236
+    - wifi: ath10k: Fix memory leak in management tx
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50237
+    - wifi: mac80211: do not pass a stopped vif to the driver in .get_txpower
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50251
+    - netfilter: nft_payload: sanitize offset and length before calling
+      skb_checksum()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50262
+    - bpf: Fix out-of-bounds write in trie_get_next_key()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-53059
+    - wifi: iwlwifi: mvm: Fix response handling in iwl_mvm_send_recovery_cmd()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50142
+    - xfrm: validate new SA's prefixlen using SA family when sel.family is unset
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50116
+    - nilfs2: fix kernel bug due to missing clearing of buffer delay flag
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50117
+    - drm/amd: Guard against bad data for ATIF ACPI method
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50205
+    - ALSA: firewire-lib: Avoid division by zero in apply_constraint_to_size()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50127
+    - net: sched: fix use-after-free in taprio_change()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50167
+    - be2net: fix potential memory leak in be_xmit()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50168
+    - net/sun3_82586: fix potential memory leak in sun3_82586_send_packet()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50131
+    - tracing: Consider the NULL character when validating the event length
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50143
+    - udf: fix uninit-value use in udf_get_fileshortad
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50134
+    - drm/vboxvideo: Replace fake VLA at end of vbva_mouse_pointer_shape with real
+      VLA
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50194
+    - arm64: probes: Fix uprobes for big-endian kernels
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50148
+    - Bluetooth: bnep: fix wild-memory-access in proto_unregister
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50150
+    - usb: typec: altmode should keep reference to parent
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50151
+    - smb: client: fix OOBs when building SMB2_IOCTL request
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50171
+    - net: systemport: fix potential memory leak in bcm_sysport_xmit()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50202
+    - nilfs2: propagate directory read errors from nilfs_find_entry()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50074
+    - parport: Proper fix for array out-of-bounds access
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50082
+    - blk-rq-qos: fix crash on rq_qos_wait vs. rq_qos_wake_function race
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-40953
+    - KVM: Fix a data race on last_boosted_vcpu in kvm_vcpu_on_spin()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50199
+    - mm/swapfile: skip HugeTLB pages for unuse_vma
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50099
+    - arm64: probes: Remove broken LDR (literal) uprobe support
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50195
+    - posix-clock: Fix missing timespec64 check in pc_clock_settime()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50096
+    - nouveau/dmem: Fix vulnerability in migrate_to_ram upon copy error
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50024
+    - net: Fix an unsafe loop on the list
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49878
+    - resource: fix region_intersects() vs add_memory_driver_managed()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50033
+    - slip: make slhc_remember() more robust against malicious packets
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50035
+    - ppp: fix ppp_async_encode() illegal access
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50039
+    - net/sched: accept TCA_STAB only for root qdisc
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50040
+    - igb: Do not bring the device up after non-fatal error
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50044
+    - Bluetooth: RFCOMM: FIX possible deadlock in rfcomm_sk_state_change
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50045
+    - netfilter: br_netfilter: fix panic with metadata_dst skb
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-38544
+    - RDMA/rxe: Fix seg fault in rxe_comp_queue_pkt
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50180
+    - fbdev: sisfb: Fix strbuf array overflow
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50184
+    - virtio_pmem: Check device status before requesting flush
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50059
+    - ntb: ntb_hw_switchtec: Fix use after free vulnerability in
+      switchtec_ntb_remove due to race condition
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50089
+    - unicode: Don't special case ignorable code points
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49955
+    - ACPI: battery: Fix possible crash when unregistering a battery hook
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49973
+    - r8169: add tally counter fields added with RTL8125
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49975
+    - uprobes: fix kernel info leak via "[uprobes]" vma
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49867
+    - btrfs: wait for fixup workers before stopping cleaner kthread during umount
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49868
+    - btrfs: fix a NULL pointer dereference when failed to start a new trasacntion
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49981
+    - media: venus: fix use after free bug in venus_remove due to race condition
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49982
+    - aoe: fix the potential use-after-free problem in more places
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49877
+    - ocfs2: fix possible null-ptr-deref in ocfs2_set_buffer_uptodate
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49957
+    - ocfs2: fix null-ptr-deref when journal load failed.
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49965
+    - ocfs2: remove unreasonable unlock in ocfs2_read_blocks
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49966
+    - ocfs2: cancel dqi_sync_work before freeing oinfo
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49958
+    - ocfs2: reserve space for inline xattr before attaching reflink tree
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49959
+    - jbd2: stop waiting for space when jbd2_cleanup_journal_tail() returns error
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49879
+    - drm: omapdrm: Add missing check for alloc_ordered_workqueue
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49882
+    - ext4: fix double brelse() the buffer of the extents path
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49883
+    - ext4: aovid use-after-free in ext4_ext_insert_extent()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49985
+    - i2c: stm32f7: Do not prepare/unprepare clock during runtime suspend/resume
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50006
+    - ext4: fix i_data_sem unlock order in ext4_ind_migrate()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49892
+    - drm/amd/display: Initialize get_bytes_per_element's default to 1
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49894
+    - drm/amd/display: Fix index out of bounds in degamma hardware format
+      translation
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49896
+    - drm/amd/display: Check stream before comparing them
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49900
+    - jfs: Fix uninit-value access of new_ea in ea_buffer
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49902
+    - jfs: check if leafidx greater than num leaves per dmap tree
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49903
+    - jfs: Fix uaf in dbFreeBits
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49924
+    - fbdev: pxafb: Fix possible use after free in pxafb_task()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50007
+    - ALSA: asihpi: Fix potential OOB array access
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50008
+    - wifi: mwifiex: Fix memcpy() field-spanning write warning in
+      mwifiex_cmd_802_11_scan_ext()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49995
+    - tipc: guard against string buffer overrun
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49962
+    - ACPICA: check null return of ACPI_ALLOCATE_ZEROED() in
+      acpi_db_convert_to_package()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49938
+    - wifi: ath9k_htc: Use __skb_set_length() for resetting urb before resubmit
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47740
+    - f2fs: Require FMODE_WRITE for atomic write ioctls
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49944
+    - sctp: set sk_state back to CLOSED if autobind fails in sctp_listen_start
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49948
+    - net: add more sanity checks to qdisc_pkt_len_init()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49949
+    - net: avoid potential underflow in qdisc_pkt_len_init() with UFO
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49997
+    - net: ethernet: lantiq_etop: fix memory disclosure
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49952
+    - netfilter: nf_tables: prevent nf_skb_duplicated corruption
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-50179
+    - ceph: remove the incorrect Fw reference check when dirtying pages
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49963
+    - mailbox: bcm2835: Fix timeout during suspend mode
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-46849
+    - ASoC: meson: axg-card: fix 'use-after-free'
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47679
+    - vfs: fix race between evice_inodes() and find_inode()&iput()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49860
+    - ACPI: sysfs: validate return type of _STR method
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47742
+    - firmware_loader: Block path traversal
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47684
+    - tcp: check skb is non-NULL in tcp_rto_delta_us()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47747
+    - net: seeq: Fix use after free vulnerability in ether3 Driver Due to Race
+      Condition
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47685
+    - netfilter: nf_reject_ipv6: fix nf_reject_ip6_tcphdr_put()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47692
+    - nfsd: return -EINVAL when namelen is 0
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47737
+    - nfsd: call cache_put if xdr_reserve_space returns NULL
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2023-52917
+    - ntb: intel: Fix the NULL vs IS_ERR() bug for debugfs_create_dir()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47749
+    - RDMA/cxgb4: Added NULL check for lookup_atid
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47696
+    - RDMA/iwcm: Fix WARNING:at_kernel/workqueue.c:#check_flush_dependency
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47756
+    - PCI: keystone: Fix if-statement expression in ks_pcie_quirk()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47697
+    - drivers: media: dvb-frontends/rtl2830: fix an out-of-bounds write error
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47698
+    - drivers: media: dvb-frontends/rtl2832: fix an out-of-bounds write error
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47757
+    - nilfs2: fix potential oob read in nilfs_btree_check_delete()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47699
+    - nilfs2: fix potential null-ptr-deref in nilfs_btree_insert()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47701
+    - ext4: avoid OOB when system.data xattr changes underneath the filesystem
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-49851
+    - tpm: Clean up TPM space after command failure
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47723
+    - jfs: fix out-of-bounds in dbNextAG() and diAlloc()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47706
+    - block, bfq: fix possible UAF for bfqq->bic with merge chain
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47709
+    - can: bcm: Clear bo->bcm_proc_read after remove_proc_entry().
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47710
+    - sock_map: Add a cond_resched() in sock_hash_free()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47712
+    - wifi: wilc1000: fix potential RCU dereference issue in
+      wilc_parse_join_bss_param
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47713
+    - wifi: mac80211: use two-phase skb reclamation in ieee80211_do_stop()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47671
+    - USB: usbtmc: prevent kernel-usb-infoleak
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-44931
+    - gpio: prevent potential speculation leaks in gpio_device_get_desc()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-41016
+    - ocfs2: strict bound check before memcmp in ocfs2_xattr_find_entry()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47670
+    - ocfs2: add bounds checking to ocfs2_xattr_find_entry()
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-47672
+    - wifi: iwlwifi: mvm: don't wait for tx queues if firmware is dead
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-46853
+    - spi: nxp-fspi: fix the KASAN report out-of-bounds bug
+  * Focal update: v5.4.285 upstream stable release (LP: #2089233) //
+    CVE-2024-46854
+    - net: dpaa: Pad packets to ETH_ZLEN
+
+ -- Benjamin Wheeler <benjamin.wheeler@canonical.com>  Fri, 31 Jan 2025 12:06:43 -0500
+
+linux-xilinx-zynqmp (5.4.0-1057.61) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1057.61 -proposed tracker (LP: #2093619)
+
+  * Add list of source files to linux-buildinfo (LP: #2086606)
+    - [Packaging] Add dwarfdump package in the Build-Depends
+
+  [ Ubuntu: 5.4.0-205.225 ]
+
+  * focal/linux: 5.4.0-205.225 -proposed tracker (LP: #2093621)
+  * Hold IOPOLL locks when triggering io_uring's deferred work (LP: #2078659) //
+    CVE-2023-21400
+    - io_uring: remove extra check in __io_commit_cqring
+    - io_uring: dont kill fasync under completion_lock
+    - io_uring: ensure IOPOLL locks around deferred work
+  * CVE-2024-40967
+    - iopoll: introduce read_poll_timeout macro
+    - iopoll: Introduce read_poll_timeout_atomic macro
+    - serial: imx: Introduce timeout when waiting on transmitter empty
+  * CVE-2024-53164
+    - net: sched: fix ordering of qlen adjustment
+  * CVE-2024-53141
+    - netfilter: ipset: add missing range check in bitmap_ip_uadt
+  * CVE-2024-53103
+    - hv_sock: Initializing vsk->trans to NULL to prevent a dangling pointer
+
+ -- Wei-Lin Chang <weilin.chang@canonical.com>  Fri, 24 Jan 2025 18:28:35 +0800
+
+linux-xilinx-zynqmp (5.4.0-1056.60) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1056.60 -proposed tracker (LP: #2090085)
+
+  [ Ubuntu: 5.4.0-204.224 ]
+
+  * focal/linux: 5.4.0-204.224 -proposed tracker (LP: #2091090)
+  * CVE-2024-50264
+    - vsock/virtio: Initialization of the dangling pointer occurring in vsk->trans
+  * CVE-2024-53057
+    - net/sched: stop qdisc_tree_reduce_backlog on TC_H_ROOT
+  * CVE-2024-49967
+    - ext4: no need to continue when the number of entries is 1
+  * CVE-2024-43892
+    - memcg: protect concurrent access to mem_cgroup_idr
+  * CVE-2024-38553
+    - net: fec: remove .ndo_poll_controller to avoid deadlocks
+  * CVE-2024-38597
+    - eth: sungem: remove .ndo_poll_controller to avoid deadlocks
+  * CVE-2023-52821
+    - drm/panel: fix a possible null pointer dereference
+  * CVE-2024-36952
+    - scsi: lpfc: Move NPIV's transport unregistration to after resource clean up
+  * CVE-2024-40910
+    - ax25: Fix refcount imbalance on inbound connections
+  * CVE-2024-35963
+    - Bluetooth: hci_sock: Fix not validating setsockopt user input
+  * CVE-2024-35965
+    - Bluetooth: L2CAP: uninitialized variables in l2cap_sock_setsockopt()
+    - Bluetooth: L2CAP: Fix not validating setsockopt user input
+  * CVE-2024-35966
+    - Bluetooth: RFCOMM: Fix not validating setsockopt user input
+  * CVE-2024-35967
+    - Bluetooth: SCO: Fix not validating setsockopt user input
+  * CVE-2021-47101
+    - net: asix: fix uninit value bugs
+    - asix: fix wrong return value in asix_check_host_enable()
+    - asix: fix uninit-value in asix_mdio_read()
+  * CVE-2022-38096
+    - drm/vmwgfx: Fix possible null pointer derefence with invalid contexts
+  * CVE-2021-47001
+    - xprtrdma: Fix cwnd update ordering
+
+ -- Wei-Lin Chang <weilin.chang@canonical.com>  Mon, 16 Dec 2024 14:34:51 +0800
+
+linux-xilinx-zynqmp (5.4.0-1055.59) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1055.59 -proposed tracker (LP: #2086449)
+
+  [ Ubuntu: 5.4.0-202.222 ]
+
+  * focal/linux: 5.4.0-202.222 -proposed tracker (LP: #2086451)
+    - [Packaging] resync git-ubuntu-log
+  * CVE-2021-47501
+    - i40e: Fix NULL pointer dereference in i40e_dbg_dump_desc
+  * CVE-2024-46724
+    - drm/amdgpu: Fix out-of-bounds read of df_v1_7_channel_number
+  * CVE-2024-42240
+    - x86/bhi: Avoid warning in #DB handler due to BHI mitigation
+  * CVE-2024-42077
+    - ocfs2: fix DIO failure due to insufficient transaction credits
+  * CVE-2024-42068
+    - bpf: Take return from set_memory_ro() into account with bpf_prog_lock_ro()
+  * CVE-2024-36968
+    - Bluetooth: L2CAP: Fix div-by-zero in l2cap_le_flowctl_init()
+  * CVE-2024-35904
+    - selinux: avoid dereference of garbage after mount failure
+  * CVE-2023-52498
+    - PM: sleep: Avoid calling put_device() under dpm_list_mtx
+    - PM: sleep: Fix error handling in dpm_prepare()
+    - async: Split async_schedule_node_domain()
+    - async: Introduce async_schedule_dev_nocall()
+    - PM: sleep: Fix possible deadlocks in core system-wide PM code
+  * CVE-2023-52488
+    - serial: sc16is7xx: convert from _raw_ to _noinc_ regmap functions for FIFO
+  * CVE-2022-48938
+    - CDC-NCM: avoid overflow in sanity checking
+  * CVE-2024-42156
+    - s390/pkey: Wipe copies of clear-key structures on failure
+  * CVE-2024-44942
+    - f2fs: fix to do sanity check on F2FS_INLINE_DATA flag in inode during GC
+  * CVE-2024-38538
+    - net: bridge: xmit: make sure we have at least eth header len bytes
+  * CVE-2021-47076
+    - RDMA/rxe: Return CQE error if invalid lkey was supplied
+  * CVE-2024-36938
+    - bpf, skmsg: Fix NULL pointer dereference in sk_psock_skb_ingress_enqueue
+  * CVE-2024-44940
+    - fou: remove warn in gue_gro_receive on unsupported protocol
+  * CVE-2024-35951
+    - drm/panfrost: Fix the error path in panfrost_mmu_map_fault_addr()
+  * CVE-2023-52497
+    - erofs: fix lz4 inplace decompression
+  * CVE-2024-36953
+    - KVM: arm64: vgic-v2: Check for non-NULL vCPU in vgic_v2_parse_attr()
+  * CVE-2022-48943
+    - KVM: x86/mmu: make apf token non-zero to fix bug
+  * CVE-2024-26947
+    - ARM: 9359/1: flush: check if the folio is reserved for no-mapping addresses
+  * CVE-2022-48733
+    - btrfs: fix use-after-free after failure to create a snapshot
+  * CVE-2023-52639
+    - KVM: s390: vsie: fix race during shadow creation
+
+ -- Hui Wang <hui.wang@canonical.com>  Fri, 15 Nov 2024 13:03:39 +0800
+
+linux-xilinx-zynqmp (5.4.0-1054.58) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1054.58 -proposed tracker (LP: #2082934)
+
+  [ Ubuntu: 5.4.0-200.220 ]
+
+  * focal/linux: 5.4.0-200.220 -proposed tracker (LP: #2082937)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] debian.master/dkms-versions -- update from kernel-versions
+      (main/2024.09.30)
+  * CVE-2024-26800
+    - tls: rx: coalesce exit paths in tls_decrypt_sg()
+    - tls: separate no-async decryption request handling from async
+    - tls: fix use-after-free on failed backlog decryption
+  * CVE-2024-26641
+    - ip6_tunnel: make sure to pull inner header in __ip6_tnl_rcv()
+  * CVE-2021-47212
+    - net/mlx5: Update error handler for UCTX and UMEM
+  * wbt:wbt_* trace event NULL pointer dereference with GENHD_FL_HIDDEN disks
+    (LP: #2081085)
+    - bdi: use bdi_dev_name() to get device name
+  * Focal update: v5.4.284 upstream stable release (LP: #2081278)
+    - drm: panel-orientation-quirks: Add quirk for OrangePi Neo
+    - i2c: Fix conditional for substituting empty ACPI functions
+    - net: usb: qmi_wwan: add MeiG Smart SRM825L
+    - drm/amdgpu: Fix uninitialized variable warning in amdgpu_afmt_acr
+    - drm/amdgpu: fix overflowed array index read warning
+    - drm/amd/display: Check gpio_id before used as array index
+    - drm/amd/display: Stop amdgpu_dm initialize when stream nums greater than 6
+    - drm/amd/display: Check num_valid_sets before accessing reader_wm_sets[]
+    - drm/amd/display: Fix Coverity INTEGER_OVERFLOW within
+      dal_gpio_service_create
+    - drm/amdgpu: fix ucode out-of-bounds read warning
+    - drm/amdgpu: fix mc_data out-of-bounds read warning
+    - drm/amdkfd: Reconcile the definition and use of oem_id in struct
+      kfd_topology_device
+    - apparmor: fix possible NULL pointer dereference
+    - ionic: fix potential irq name truncation
+    - usbip: Don't submit special requests twice
+    - usb: typec: ucsi: Fix null pointer dereference in trace
+    - smack: tcp: ipv4, fix incorrect labeling
+    - wifi: cfg80211: make hash table duplicates more survivable
+    - drm/amd/display: Skip wbscl_set_scaler_filter if filter is null
+    - media: uvcvideo: Enforce alignment of frame and interval
+    - block: initialize integrity buffer to zero before writing it to media
+    - net: set SOCK_RCU_FREE before inserting socket into hashtable
+    - virtio_net: Fix napi_skb_cache_put warning
+    - udf: Limit file size to 4TB
+    - i2c: Use IS_REACHABLE() for substituting empty ACPI functions
+    - sch/netem: fix use after free in netem_dequeue
+    - ASoC: dapm: Fix UAF for snd_soc_pcm_runtime object
+    - ALSA: hda/conexant: Add pincfg quirk to enable top speakers on Sirius
+      devices
+    - ata: libata: Fix memory leak for error path in ata_host_alloc()
+    - irqchip/gic-v2m: Fix refcount leak in gicv2m_of_init()
+    - mmc: dw_mmc: Fix IDMAC operation with pages bigger than 4K
+    - mmc: sdhci-of-aspeed: fix module autoloading
+    - fuse: update stats for pages in dropped aux writeback list
+    - fuse: use unsigned type for getxattr/listxattr size truncation
+    - reset: hi6220: Add support for AO reset controller
+    - clk: hi6220: use CLK_OF_DECLARE_DRIVER
+    - clk: qcom: clk-alpha-pll: Fix the pll post div mask
+    - clk: qcom: clk-alpha-pll: Fix the trion pll postdiv set rate API
+    - ila: call nf_unregister_net_hooks() sooner
+    - sched: sch_cake: fix bulk flow accounting logic for host fairness
+    - nilfs2: fix missing cleanup on rollforward recovery error
+    - nilfs2: fix state management in error path of log writing function
+    - ALSA: hda: Add input value sanity checks to HDMI channel map controls
+    - smack: unix sockets: fix accept()ed socket label
+    - irqchip/armada-370-xp: Do not allow mapping IRQ 0 and 1
+    - af_unix: Remove put_pid()/put_cred() in copy_peercred().
+    - netfilter: nf_conncount: fix wrong variable type
+    - udf: Avoid excessive partition lengths
+    - wifi: brcmsmac: advertise MFP_CAPABLE to enable WPA3
+    - usb: uas: set host status byte on data completion error
+    - PCI: keystone: Add workaround for Errata #i2037 (AM65x SR 1.0)
+    - media: qcom: camss: Add check for v4l2_fwnode_endpoint_parse
+    - pcmcia: Use resource_size function on resource object
+    - can: bcm: Remove proc entry when dev is unregistered.
+    - igb: Fix not clearing TimeSync interrupts for 82580
+    - platform/x86: dell-smbios: Fix error path in dell_smbios_init()
+    - tcp_bpf: fix return value of tcp_bpf_sendmsg()
+    - cx82310_eth: re-enable ethernet mode after router reboot
+    - drivers/net/usb: Remove all strcpy() uses
+    - net: usb: don't write directly to netdev->dev_addr
+    - usbnet: modern method to get random MAC
+    - net: bridge: fdb: convert is_local to bitops
+    - net: bridge: fdb: convert is_static to bitops
+    - net: bridge: fdb: convert is_sticky to bitops
+    - net: bridge: fdb: convert added_by_user to bitops
+    - net: bridge: fdb: convert added_by_external_learn to use bitops
+    - net: bridge: br_fdb_external_learn_add(): always set EXT_LEARN
+    - net: dsa: vsc73xx: fix possible subblocks range of CAPT block
+    - ASoC: topology: Properly initialize soc_enum values
+    - dm init: Handle minors larger than 255
+    - iommu/vt-d: Handle volatile descriptor status read
+    - cgroup: Protect css->cgroup write under css_set_lock
+    - um: line: always fill *error_out in setup_one_line()
+    - devres: Initialize an uninitialized struct member
+    - pci/hotplug/pnv_php: Fix hotplug driver crash on Powernv
+    - hwmon: (adc128d818) Fix underflows seen when writing limit attributes
+    - hwmon: (lm95234) Fix underflows seen when writing limit attributes
+    - hwmon: (nct6775-core) Fix underflows seen when writing limit attributes
+    - hwmon: (w83627ehf) Fix underflows seen when writing limit attributes
+    - libbpf: Add NULL checks to bpf_object__{prev_map,next_map}
+    - wifi: mwifiex: Do not return unused priv in mwifiex_get_priv_by_id()
+    - smp: Add missing destroy_work_on_stack() call in smp_call_on_cpu()
+    - btrfs: replace BUG_ON with ASSERT in walk_down_proc()
+    - btrfs: clean up our handling of refs == 0 in snapshot delete
+    - PCI: Add missing bridge lock to pci_bus_lock()
+    - btrfs: initialize location to fix -Wmaybe-uninitialized in
+      btrfs_lookup_dentry()
+    - HID: cougar: fix slab-out-of-bounds Read in cougar_report_fixup
+    - Input: uinput - reject requests with unreasonable number of slots
+    - usbnet: ipheth: race between ipheth_close and error handling
+    - Squashfs: sanity check symbolic link size
+    - of/irq: Prevent device address out-of-bounds read in interrupt map walk
+    - lib/generic-radix-tree.c: Fix rare race in __genradix_ptr_alloc()
+    - ata: pata_macio: Use WARN instead of BUG
+    - NFSv4: Add missing rescheduling points in
+      nfs_client_return_marked_delegations
+    - staging: iio: frequency: ad9834: Validate frequency parameter value
+    - iio: buffer-dmaengine: fix releasing dma channel on error
+    - iio: fix scale application in iio_convert_raw_to_processed_unlocked
+    - binder: fix UAF caused by offsets overwrite
+    - nvmem: Fix return type of devm_nvmem_device_get() in kerneldoc
+    - uio_hv_generic: Fix kernel NULL pointer dereference in hv_uio_rescind
+    - Drivers: hv: vmbus: Fix rescind handling in uio_hv_generic
+    - VMCI: Fix use-after-free when removing resource in vmci_resource_remove()
+    - clocksource/drivers/imx-tpm: Fix return -ETIME when delta exceeds INT_MAX
+    - clocksource/drivers/imx-tpm: Fix next event not taking effect sometime
+    - clocksource/drivers/timer-of: Remove percpu irq related code
+    - uprobes: Use kzalloc to allocate xol area
+    - ring-buffer: Rename ring_buffer_read() to read_buffer_iter_advance()
+    - tracing: Avoid possible softlockup in tracing_iter_reset()
+    - nilfs2: replace snprintf in show functions with sysfs_emit
+    - nilfs2: protect references to superblock parameters exposed in sysfs
+    - ACPI: processor: Return an error if acpi_processor_get_info() fails in
+      processor_add()
+    - ACPI: processor: Fix memory leaks in error paths of processor_add()
+    - arm64: acpi: Move get_cpu_for_acpi_id() to a header
+    - arm64: acpi: Harden get_cpu_for_acpi_id() against missing CPU entry
+    - nvmet-tcp: fix kernel crash if commands allocation fails
+    - drm/i915/fence: Mark debug_fence_init_onstack() with __maybe_unused
+    - drm/i915/fence: Mark debug_fence_free() with __maybe_unused
+    - rtmutex: Drop rt_mutex::wait_lock before scheduling
+    - net, sunrpc: Remap EPERM in case of connection failure in
+      xs_tcp_setup_socket
+    - cx82310_eth: fix error return code in cx82310_bind()
+    - Linux 5.4.284
+  * CVE-2024-42244
+    - USB: serial: mos7840: fix crash on resume
+  * CVE-2024-40929
+    - wifi: iwlwifi: mvm: check n_ssids before accessing the ssids
+  * CVE-2024-41073
+    - nvme: avoid double free special payload
+  * CVE-2024-41071
+    - wifi: mac80211: Avoid address calculations via out of bounds array indexing
+  * CVE-2024-42229
+    - crypto: aead, cipher - zeroize key buffer after use
+  * CVE-2024-38611
+    - media: i2c: et8ek8: Don't strip remove function when driver is builtin
+  * CVE-2024-38602
+    - ax25: Fix reference count leak issues of ax25_dev
+  * CVE-2024-35848
+    - misc: eeprom: at24: fix regulator underflow
+    - misc: eeprom: at24: register nvmem only after eeprom is ready to use
+    - eeprom: at24: fix memory corruption race condition
+  * CVE-2024-26669
+    - net/sched: flower: Fix chain template offload
+  * CVE-2024-26668
+    - netfilter: nft_limit: rename stateful structure
+    - netfilter: nft_limit: reject configurations that cause integer overflow
+  * CVE-2024-26640
+    - net-zerocopy: Refactor frag-is-remappable test.
+    - tcp: add sanity checks to rx zerocopy
+  * CVE-2024-26607
+    - drm/bridge: sii902x: Fix probing race issue
+  * CVE-2023-52614
+    - PM / devfreq: Fix buffer overflow in trans_stat_show
+  * CVE-2023-52531
+    - wifi: iwlwifi: mvm: Fix a memory corruption issue
+  * CVE-2022-36402
+    - drm/vmwgfx: Use enum to represent graphics context capabilities
+    - drm/vmwgfx: Fix shader stage validation
+  * Focal update: v5.4.283 upstream stable release (LP: #2080595)
+    - fuse: Initialize beyond-EOF page contents before setting uptodate
+    - ALSA: usb-audio: Support Yamaha P-125 quirk entry
+    - xhci: Fix Panther point NULL pointer deref at full-speed re-enumeration
+    - s390/dasd: fix error recovery leading to data corruption on ESE devices
+    - arm64: ACPI: NUMA: initialize all values of acpi_early_node_map to
+      NUMA_NO_NODE
+    - dm resume: don't return EINVAL when signalled
+    - dm persistent data: fix memory allocation failure
+    - vfs: Don't evict inode under the inode lru traversing context
+    - bitmap: introduce generic optimized bitmap_size()
+    - fix bitmap corruption on close_range() with CLOSE_RANGE_UNSHARE
+    - selinux: fix potential counting error in avc_add_xperms_decision()
+    - drm/amdgpu: Actually check flags for all context ops.
+    - memcg_write_event_control(): fix a user-triggerable oops
+    - overflow.h: Add flex_array_size() helper
+    - overflow: Implement size_t saturating arithmetic helpers
+    - s390/cio: rename bitmap_size() -> idset_bitmap_size()
+    - btrfs: rename bitmap_set_bits() -> btrfs_bitmap_set_bits()
+    - s390/uv: Panic for set and remove shared access UVC errors
+    - net/mlx5e: Correctly report errors for ethtool rx flows
+    - atm: idt77252: prevent use after free in dequeue_rx()
+    - net: axienet: Fix DMA descriptor cleanup path
+    - net: axienet: Improve DMA error handling
+    - net: axienet: Factor out TX descriptor chain cleanup
+    - net: axienet: Check for DMA mapping errors
+    - net: axienet: Drop MDIO interrupt registers from ethtools dump
+    - net: axienet: Wrap DMA pointer writes to prepare for 64 bit
+    - net: axienet: Upgrade descriptors to hold 64-bit addresses
+    - net: axienet: Autodetect 64-bit DMA capability
+    - net: axienet: Fix register defines comment description
+    - net: dsa: vsc73xx: pass value in phy_write operation
+    - net: hns3: fix a deadlock problem when config TC during resetting
+    - ALSA: hda/realtek: Fix noise from speakers on Lenovo IdeaPad 3 15IAU7
+    - ssb: Fix division by zero issue in ssb_calc_clock_rate
+    - wifi: cw1200: Avoid processing an invalid TIM IE
+    - i2c: riic: avoid potential division by zero
+    - media: radio-isa: use dev_name to fill in bus_info
+    - staging: ks7010: disable bh on tx_dev_lock
+    - binfmt_misc: cleanup on filesystem umount
+    - scsi: spi: Fix sshdr use
+    - gfs2: setattr_chown: Add missing initialization
+    - wifi: iwlwifi: abort scan when rfkill on but device enabled
+    - IB/hfi1: Fix potential deadlock on &irq_src_lock and &dd->uctxt_lock
+    - powerpc/xics: Check return value of kasprintf in icp_native_map_one_cpu
+    - nvmet-trace: avoid dereferencing pointer too early
+    - ext4: do not trim the group with corrupted block bitmap
+    - quota: Remove BUG_ON from dqget()
+    - media: pci: cx23885: check cx23885_vdev_init() return
+    - fs: binfmt_elf_efpic: don't use missing interpreter's properties
+    - scsi: lpfc: Initialize status local variable in lpfc_sli4_repost_sgl_list()
+    - net/sun3_82586: Avoid reading past buffer in debug output
+    - drm/lima: set gp bus_stop bit before hard reset
+    - virtiofs: forbid newlines in tags
+    - md: clean up invalid BUG_ON in md_ioctl
+    - x86: Increase brk randomness entropy for 64-bit systems
+    - powerpc/boot: Handle allocation failure in simple_realloc()
+    - powerpc/boot: Only free if realloc() succeeds
+    - btrfs: change BUG_ON to assertion when checking for delayed_node root
+    - btrfs: handle invalid root reference found in may_destroy_subvol()
+    - btrfs: send: handle unexpected data in header buffer in begin_cmd()
+    - btrfs: delete pointless BUG_ON check on quota root in
+      btrfs_qgroup_account_extent()
+    - f2fs: fix to do sanity check in update_sit_entry
+    - usb: gadget: fsl: Increase size of name buffer for endpoints
+    - nvme: clear caller pointer on identify failure
+    - Bluetooth: bnep: Fix out-of-bound access
+    - nvmet-tcp: do not continue for invalid icreq
+    - NFS: avoid infinite loop in pnfs_update_layout.
+    - openrisc: Call setup_memory() earlier in the init sequence
+    - s390/iucv: fix receive buffer virtual vs physical address confusion
+    - usb: dwc3: core: Skip setting event buffers for host only controllers
+    - irqchip/gic-v3-its: Remove BUG_ON in its_vpe_irq_domain_alloc
+    - ext4: set the type of max_zeroout to unsigned int to avoid overflow
+    - nvmet-rdma: fix possible bad dereference when freeing rsps
+    - hrtimer: Prevent queuing of hrtimer without a function callback
+    - gtp: pull network headers in gtp_dev_xmit()
+    - block: use "unsigned long" for blk_validate_block_size().
+    - media: solo6x10: replace max(a, min(b, c)) by clamp(b, a, c)
+    - dm mpath: pass IO start time to path selector
+    - dm: do not use waitqueue for request-based DM
+    - dm suspend: return -ERESTARTSYS instead of -EINTR
+    - Bluetooth: Make use of __check_timeout on hci_sched_le
+    - Bluetooth: hci_core: Fix not handling link timeouts propertly
+    - Bluetooth: hci_core: Fix LE quote calculation
+    - tc-testing: don't access non-existent variable on exception
+    - kcm: Serialise kcm_sendmsg() for the same socket.
+    - netfilter: nft_counter: Synchronize nft_counter_reset() against reader.
+    - net: dsa: mv88e6xxx: global2: Expose ATU stats register
+    - net: dsa: mv88e6xxx: global1_atu: Add helper for get next
+    - net: dsa: mv88e6xxx: read FID when handling ATU violations
+    - net: dsa: mv88e6xxx: replace ATU violation prints with trace points
+    - net: dsa: mv88e6xxx: Fix out-of-bound access
+    - ipv6: prevent UAF in ip6_send_skb()
+    - net: xilinx: axienet: Always disable promiscuous mode
+    - net: xilinx: axienet: Fix dangling multicast addresses
+    - drm/msm: use drm_debug_enabled() to check for debug categories
+    - drm/msm/dpu: don't play tricks with debug macros
+    - mmc: mmc_test: Fix NULL dereference on allocation failure
+    - Bluetooth: MGMT: Add error handling to pair_device()
+    - HID: wacom: Defer calculation of resolution until resolution_code is known
+    - HID: microsoft: Add rumble support to latest xbox controllers
+    - cxgb4: add forgotten u64 ivlan cast before shift
+    - mmc: dw_mmc: allow biu and ciu clocks to defer
+    - ALSA: timer: Relax start tick time check for slave timer elements
+    - Input: MT - limit max slots
+    - tools: move alignment-related macros to new <linux/align.h>
+    - pinctrl: single: fix potential NULL dereference in pcs_get_function()
+    - wifi: mwifiex: duplicate static structs used in driver instances
+    - drm/amdkfd: don't allow mapping the MMIO HDP page with large pages
+    - filelock: Correct the filelock owner in fcntl_setlk/fcntl_setlk64
+    - media: uvcvideo: Fix integer overflow calculating timestamp
+    - ata: libata-core: Fix null pointer dereference on error
+    - cgroup/cpuset: Prevent UAF in proc_cpuset_show()
+    - net:rds: Fix possible deadlock in rds_message_put
+    - soundwire: stream: fix programming slave ports for non-continous port maps
+    - r8152: Factor out OOB link list waits
+    - ethtool: check device is present when getting link settings
+    - gtp: fix a potential NULL pointer dereference
+    - net: busy-poll: use ktime_get_ns() instead of local_clock()
+    - nfc: pn533: Add dev_up/dev_down hooks to phy_ops
+    - nfc: pn533: Add autopoll capability
+    - nfc: pn533: Add poll mod list filling check
+    - soc: qcom: cmd-db: Map shared memory as WC, not WB
+    - cdc-acm: Add DISABLE_ECHO quirk for GE HealthCare UI Controller
+    - USB: serial: option: add MeiG Smart SRM825L
+    - usb: dwc3: omap: add missing depopulate in probe error path
+    - usb: dwc3: core: Prevent USB core invalid event buffer address access
+    - usb: dwc3: st: fix probed platform device ref count on probe error path
+    - usb: dwc3: st: add missing depopulate in probe error path
+    - usb: core: sysfs: Unmerge @usb3_hardware_lpm_attr_group in
+      remove_power_attributes()
+    - net: dsa: mv8e6xxx: Fix stub function parameters
+    - scsi: aacraid: Fix double-free on probe failure
+    - Linux 5.4.283
+  * CVE-2024-27051
+    - cpufreq: brcmstb-avs-cpufreq: add check for cpufreq_cpu_get's return value
+    - cpufreq: brcmstb-avs-cpufreq: ISO C90 forbids mixed declarations
+  * CVE-2024-26891
+    - PCI: Make pci_dev_is_disconnected() helper public for other drivers
+    - iommu/vt-d: Don't issue ATS Invalidation request when device is disconnected
+  * Focal update: v5.4.282 upstream stable release (LP: #2078388)
+    - EDAC, skx_common: Refactor so that we initialize "dev" in result of adxl
+      decode.
+    - EDAC, skx: Retrieve and print retry_rd_err_log registers
+    - EDAC/skx_common: Add new ADXL components for 2-level memory
+    - EDAC, i10nm: make skx_common.o a separate module
+    - platform/chrome: cros_ec_debugfs: fix wrong EC message version
+    - hfsplus: fix to avoid false alarm of circular locking
+    - x86/of: Return consistent error type from x86_of_pci_irq_enable()
+    - x86/pci/intel_mid_pci: Fix PCIBIOS_* return code handling
+    - x86/pci/xen: Fix PCIBIOS_* return code handling
+    - x86/platform/iosf_mbi: Convert PCIBIOS_* return codes to errnos
+    - hwmon: (adt7475) Fix default duty on fan is disabled
+    - pwm: stm32: Always do lazy disabling
+    - hwmon: (max6697) Fix underflow when writing limit attributes
+    - hwmon: (max6697) Fix swapped temp{1,8} critical alarms
+    - arm64: dts: qcom: sdm845: add power-domain to UFS PHY
+    - arm64: dts: qcom: msm8996: specify UFS core_clk frequencies
+    - arm64: dts: rockchip: Increase VOP clk rate on RK3328
+    - ARM: dts: imx6qdl-kontron-samx6i: move phy reset into phy-node
+    - ARM: dts: imx6qdl-kontron-samx6i: fix PHY reset
+    - ARM: dts: imx6qdl-kontron-samx6i: fix board reset
+    - ARM: dts: imx6qdl-kontron-samx6i: fix PCIe reset polarity
+    - arm64: dts: mediatek: mt7622: fix "emmc" pinctrl mux
+    - arm64: dts: amlogic: gx: correct hdmi clocks
+    - m68k: atari: Fix TT bootup freeze / unexpected (SCU) interrupt messages
+    - x86/xen: Convert comma to semicolon
+    - m68k: cmpxchg: Fix return value for default case in __arch_xchg()
+    - firmware: turris-mox-rwtm: Fix checking return value of
+      wait_for_completion_timeout()
+    - firmware: turris-mox-rwtm: Initialize completion before mailbox
+    - wifi: brcmsmac: LCN PHY code is used for BCM4313 2G-only device
+    - net/smc: Allow SMC-D 1MB DMB allocations
+    - net/smc: set rmb's SG_MAX_SINGLE_ALLOC limitation only when
+      CONFIG_ARCH_NO_SG_CHAIN is defined
+    - selftests/bpf: Check length of recv in test_sockmap
+    - lib: objagg: Fix general protection fault
+    - mlxsw: spectrum_acl_erp: Fix object nesting warning
+    - wifi: cfg80211: fix typo in cfg80211_calculate_bitrate_he()
+    - wifi: cfg80211: handle 2x996 RU allocation in
+      cfg80211_calculate_bitrate_he()
+    - net: fec: Refactor: #define magic constants
+    - net: fec: Fix FEC_ECR_EN1588 being cleared on link-down
+    - ipvs: Avoid unnecessary calls to skb_is_gso_sctp
+    - netfilter: nf_tables: rise cap on SELinux secmark context
+    - perf/x86/intel/pt: Fix pt_topa_entry_for_page() address calculation
+    - perf: Fix perf_aux_size() for greater-than 32-bit size
+    - perf: Prevent passing zero nr_pages to rb_alloc_aux()
+    - qed: Improve the stack space of filter_config()
+    - wifi: virt_wifi: avoid reporting connection success with wrong SSID
+    - gss_krb5: Fix the error handling path for crypto_sync_skcipher_setkey
+    - wifi: virt_wifi: don't use strlen() in const context
+    - bna: adjust 'name' buf size of bna_tcb and bna_ccb structures
+    - selftests: forwarding: devlink_lib: Wait for udev events after reloading
+    - media: dvb-usb: Fix unexpected infinite loop in
+      dvb_usb_read_remote_control()
+    - media: imon: Fix race getting ictx->lock
+    - saa7134: Unchecked i2c_transfer function result fixed
+    - media: uvcvideo: Allow entity-defined get_info and get_cur
+    - media: uvcvideo: Override default flags
+    - media: renesas: vsp1: Fix _irqsave and _irq mix
+    - media: renesas: vsp1: Store RPF partition configuration per RPF instance
+    - leds: trigger: Unregister sysfs attributes before calling deactivate()
+    - perf report: Fix condition in sort__sym_cmp()
+    - drm/etnaviv: fix DMA direction handling for cached RW buffers
+    - drm/qxl: Add check for drm_cvt_mode
+    - mfd: omap-usb-tll: Use struct_size to allocate tll
+    - SUNRPC: avoid soft lockup when transmitting UDP to reachable server.
+    - ext4: avoid writing unitialized memory to disk in EA inodes
+    - sparc64: Fix incorrect function signature and add prototype for
+      prom_cif_init
+    - SUNRPC: Fixup gss_status tracepoint error output
+    - PCI: Fix resource double counting on remove & rescan
+    - Input: qt1050 - handle CHIP_ID reading error
+    - RDMA/mlx4: Fix truncated output warning in mad.c
+    - RDMA/mlx4: Fix truncated output warning in alias_GUID.c
+    - RDMA/rxe: Don't set BTH_ACK_MASK for UC or UD QPs
+    - ASoC: max98088: Check for clk_prepare_enable() error
+    - mtd: make mtd_test.c a separate module
+    - RDMA/device: Return error earlier if port in not valid
+    - Input: elan_i2c - do not leave interrupt disabled on suspend failure
+    - MIPS: Octeron: remove source file executable bit
+    - powerpc/xmon: Fix disassembly CPU feature checks
+    - macintosh/therm_windtunnel: fix module unload.
+    - bnxt_re: Fix imm_data endianness
+    - netfilter: ctnetlink: use helper function to calculate expect ID
+    - pinctrl: core: fix possible memory leak when pinctrl_enable() fails
+    - pinctrl: single: fix possible memory leak when pinctrl_enable() fails
+    - pinctrl: ti: ti-iodelay: Drop if block with always false condition
+    - pinctrl: ti: ti-iodelay: fix possible memory leak when pinctrl_enable()
+      fails
+    - pinctrl: freescale: mxs: Fix refcount of child
+    - fs/nilfs2: remove some unused macros to tame gcc
+    - nilfs2: avoid undefined behavior in nilfs_cnt32_ge macro
+    - rtc: interface: Add RTC offset to alarm after fix-up
+    - tick/broadcast: Make takeover of broadcast hrtimer reliable
+    - net: netconsole: Disable target before netpoll cleanup
+    - af_packet: Handle outgoing VLAN packets without hardware offloading
+    - ipv6: take care of scope when choosing the src addr
+    - char: tpm: Fix possible memory leak in tpm_bios_measurements_open()
+    - media: venus: fix use after free in vdec_close
+    - hfs: fix to initialize fields of hfs_inode_info after hfs_alloc_inode()
+    - drm/gma500: fix null pointer dereference in cdv_intel_lvds_get_modes
+    - drm/gma500: fix null pointer dereference in psb_intel_lvds_get_modes
+    - drm/amd/display: Check for NULL pointer
+    - udf: Avoid using corrupted block bitmap buffer
+    - m68k: amiga: Turn off Warp1260 interrupts during boot
+    - ext4: check dot and dotdot of dx_root before making dir indexed
+    - ext4: make sure the first directory block is not a hole
+    - wifi: mwifiex: Fix interface type change
+    - leds: ss4200: Convert PCIBIOS_* return codes to errnos
+    - tools/memory-model: Fix bug in lock.cat
+    - hwrng: amd - Convert PCIBIOS_* return codes to errnos
+    - PCI: hv: Return zero, not garbage, when reading PCI_INTERRUPT_PIN
+    - binder: fix hang of unregistered readers
+    - scsi: qla2xxx: Return ENOBUFS if sg_cnt is more than one for ELS cmds
+    - f2fs: fix to don't dirty inode for readonly filesystem
+    - clk: davinci: da8xx-cfgchip: Initialize clk_init_data before use
+    - ubi: eba: properly rollback inside self_check_eba
+    - decompress_bunzip2: fix rare decompression failure
+    - kobject_uevent: Fix OOB access within zap_modalias_env()
+    - rtc: cmos: Fix return value of nvmem callbacks
+    - scsi: qla2xxx: During vport delete send async logout explicitly
+    - scsi: qla2xxx: Fix for possible memory corruption
+    - scsi: qla2xxx: Complete command early within lock
+    - scsi: qla2xxx: validate nvme_local_port correctly
+    - perf/x86/intel/pt: Fix topa_entry base length
+    - perf/x86/intel/pt: Fix a topa_entry base address calculation
+    - rtc: isl1208: Fix return value of nvmem callbacks
+    - watchdog/perf: properly initialize the turbo mode timestamp and rearm
+      counter
+    - platform: mips: cpu_hwmon: Disable driver on unsupported hardware
+    - RDMA/iwcm: Fix a use-after-free related to destroying CM IDs
+    - selftests/sigaltstack: Fix ppc64 GCC build
+    - rbd: don't assume rbd_is_lock_owner() for exclusive mappings
+    - drm/panfrost: Mark simple_ondemand governor as softdep
+    - rbd: rename RBD_LOCK_STATE_RELEASING and releasing_wait
+    - rbd: don't assume RBD_LOCK_STATE_LOCKED for exclusive mappings
+    - Bluetooth: btusb: Add RTL8852BE device 0489:e125 to device tables
+    - Bluetooth: btusb: Add Realtek RTL8852BE support ID 0x13d3:0x3591
+    - nilfs2: handle inconsistent state in nilfs_btnode_create_block()
+    - kdb: address -Wformat-security warnings
+    - kdb: Use the passed prompt in kdb_position_cursor()
+    - jfs: Fix array-index-out-of-bounds in diFree
+    - um: time-travel: fix time-travel-start option
+    - libbpf: Fix no-args func prototype BTF dumping syntax
+    - dma: fix call order in dmam_free_coherent
+    - MIPS: SMP-CPS: Fix address for GCR_ACCESS register for CM3 and later
+    - ipv4: Fix incorrect source address in Record Route option
+    - net: bonding: correctly annotate RCU in bond_should_notify_peers()
+    - tipc: Return non-zero value from tipc_udp_addr2str() on error
+    - net: nexthop: Initialize all fields in dumped nexthops
+    - bpf: Fix a segment issue when downgrading gso_size
+    - mISDN: Fix a use after free in hfcmulti_tx()
+    - powerpc: fix a file leak in kvm_vcpu_ioctl_enable_cap()
+    - ASoC: Intel: Convert to new X86 CPU match macros
+    - ASoC: Intel: Move soc_intel_is_foo() helpers to a generic header
+    - ASoC: Intel: use soc_intel_is_byt_cr() only when IOSF_MBI is reachable
+    - nvme-pci: add missing condition check for existence of mapped data
+    - mm: avoid overflows in dirty throttling logic
+    - PCI: rockchip: Make 'ep-gpios' DT property optional
+    - PCI: rockchip: Use GPIOD_OUT_LOW flag while requesting ep_gpio
+    - parport: Convert printk(KERN_<LEVEL> to pr_<level>(
+    - parport: Standardize use of printmode
+    - dev/parport: fix the array out-of-bounds risk
+    - driver core: Cast to (void *) with __force for __percpu pointer
+    - devres: Fix memory leakage caused by driver API devm_free_percpu()
+    - genirq: Allow the PM device to originate from irq domain
+    - irqchip/imx-irqsteer: Constify irq_chip struct
+    - irqchip/imx-irqsteer: Add runtime PM support
+    - irqchip/imx-irqsteer: Handle runtime power management correctly
+    - remoteproc: imx_rproc: ignore mapping vdev regions
+    - remoteproc: imx_rproc: Fix ignoring mapping vdev regions
+    - remoteproc: imx_rproc: Skip over memory region when node value is NULL
+    - drm/nouveau: prime: fix refcount underflow
+    - drm/vmwgfx: Fix overlay when using Screen Targets
+    - net/iucv: fix use after free in iucv_sock_close()
+    - net/mlx5e: Add a check for the return value from mlx5_port_set_eth_ptys
+    - ipv6: fix ndisc_is_useropt() handling for PIO
+    - HID: wacom: Modify pen IDs
+    - protect the fetch of ->fd[fd] in do_dup2() from mispredictions
+    - ALSA: usb-audio: Correct surround channels in UAC1 channel map
+    - net: usb: sr9700: fix uninitialized variable use in sr_mdio_read
+    - netfilter: ipset: Add list flush to cancel_gc
+    - genirq: Allow irq_chip registration functions to take a const irq_chip
+    - irqchip/mbigen: Fix mbigen node address layout
+    - x86/mm: Fix pti_clone_pgtable() alignment assumption
+    - sctp: move hlist_node and hashent out of sctp_ep_common
+    - sctp: Fix null-ptr-deref in reuseport_add_sock().
+    - net: usb: qmi_wwan: fix memory leak for not ip packets
+    - net: linkwatch: use system_unbound_wq
+    - Bluetooth: l2cap: always unlock channel in l2cap_conless_channel()
+    - net: fec: Stop PPS on driver remove
+    - md/raid5: avoid BUG_ON() while continue reshape after reassembling
+    - clocksource/drivers/sh_cmt: Address race condition for clock events
+    - ACPI: battery: create alarm sysfs attribute atomically
+    - ACPI: SBS: manage alarm sysfs attribute through psy core
+    - selftests/bpf: Fix send_signal test with nested CONFIG_PARAVIRT
+    - PCI: Add Edimax Vendor ID to pci_ids.h
+    - udf: prevent integer overflow in udf_bitmap_free_blocks()
+    - wifi: nl80211: don't give key data to userspace
+    - btrfs: fix bitmap leak when loading free space cache on duplicate entry
+    - drm/amdgpu: Fix the null pointer dereference to ras_manager
+    - media: uvcvideo: Ignore empty TS packets
+    - media: uvcvideo: Fix the bandwdith quirk on USB 3.x
+    - jbd2: avoid memleak in jbd2_journal_write_metadata_buffer
+    - s390/sclp: Prevent release of buffer in I/O
+    - SUNRPC: Fix a race to wake a sync task
+    - ext4: fix wrong unit use in ext4_mb_find_by_goal
+    - arm64: cpufeature: Force HWCAP to be based on the sysreg visible to user-
+      space
+    - arm64: Add Neoverse-V2 part
+    - arm64: cputype: Add Cortex-X4 definitions
+    - arm64: cputype: Add Neoverse-V3 definitions
+    - arm64: errata: Add workaround for Arm errata 3194386 and 3312417
+    - [Config] Set ARM64_ERRATUM_3194386=y
+    - arm64: cputype: Add Cortex-X3 definitions
+    - arm64: cputype: Add Cortex-A720 definitions
+    - arm64: cputype: Add Cortex-X925 definitions
+    - arm64: errata: Unify speculative SSBS errata logic
+    - arm64: errata: Expand speculative SSBS workaround
+    - arm64: cputype: Add Cortex-X1C definitions
+    - arm64: cputype: Add Cortex-A725 definitions
+    - arm64: errata: Expand speculative SSBS workaround (again)
+    - i2c: smbus: Don't filter out duplicate alerts
+    - i2c: smbus: Improve handling of stuck alerts
+    - i2c: smbus: Send alert notifications to all devices if source not found
+    - bpf: kprobe: remove unused declaring of bpf_kprobe_override
+    - spi: fsl-lpspi: remove unneeded array
+    - spi: spi-fsl-lpspi: Fix scldiv calculation
+    - drm/client: fix null pointer dereference in drm_client_modeset_probe
+    - ALSA: line6: Fix racy access to midibuf
+    - ALSA: hda: Add HP MP9 G4 Retail System AMS to force connect list
+    - ALSA: hda/hdmi: Yet more pin fix for HP EliteDesk 800 G4
+    - usb: vhci-hcd: Do not drop references before new references are gained
+    - USB: serial: debug: do not echo input by default
+    - usb: gadget: core: Check for unset descriptor
+    - scsi: ufs: core: Fix hba->last_dme_cmd_tstamp timestamp updating logic
+    - tick/broadcast: Move per CPU pointer access into the atomic section
+    - ntp: Clamp maxerror and esterror to operating range
+    - driver core: Fix uevent_show() vs driver detach race
+    - ntp: Safeguard against time_constant overflow
+    - scsi: mpt3sas: Remove scsi_dma_map() error messages
+    - scsi: mpt3sas: Avoid IOMMU page faults on REPORT ZONES
+    - serial: core: check uartclk for zero to avoid divide by zero
+    - genirq/irqdesc: Honor caller provided affinity in alloc_desc()
+    - power: supply: axp288_charger: Fix constant_charge_voltage writes
+    - power: supply: axp288_charger: Round constant_charge_voltage writes down
+    - tracing: Fix overflow in get_free_elt()
+    - x86/mtrr: Check if fixed MTRRs exist before saving them
+    - drm/bridge: analogix_dp: properly handle zero sized AUX transactions
+    - drm/mgag200: Set DDC timeout in milliseconds
+    - Fix gcc 4.9 build issue in 5.4.y
+    - kbuild: Fix '-S -c' in x86 stack protector scripts
+    - netfilter: nf_tables: set element extended ACK reporting support
+    - netfilter: nf_tables: prefer nft_chain_validate
+    - drm/i915/gem: Fix Virtual Memory mapping boundaries calculation
+    - arm64: cpufeature: Fix the visibility of compat hwcaps
+    - media: uvcvideo: Use entity get_cur in uvc_ctrl_set
+    - exec: Fix ToCToU between perm check and set-uid/gid usage
+    - nvme/pci: Add APST quirk for Lenovo N60z laptop
+    - ARM: dts: imx6qdl-kontron-samx6i: fix phy-mode
+    - media: Revert "media: dvb-usb: Fix unexpected infinite loop in
+      dvb_usb_read_remote_control()"
+    - Linux 5.4.282
+  * CVE-2024-26885
+    - bpf: Fix DEVMAP_HASH overflow check on 32-bit arches
+  * Focal update: v5.4.281 upstream stable release (LP: #2076097)
+    - gcc-plugins: Rename last_stmt() for GCC 14+
+    - filelock: Remove locks reliably when fcntl/close race is detected
+    - scsi: qedf: Set qed_slowpath_params to zero before use
+    - ACPI: EC: Abort address space access upon error
+    - ACPI: EC: Avoid returning AE_OK on errors in address space handler
+    - wifi: mac80211: mesh: init nonpeer_pm to active by default in mesh sdata
+    - wifi: mac80211: fix UBSAN noise in ieee80211_prep_hw_scan()
+    - Input: silead - Always support 10 fingers
+    - ila: block BH in ila_output()
+    - kconfig: gconf: give a proper initial state to the Save button
+    - kconfig: remove wrong expr_trans_bool()
+    - fs/file: fix the check in find_next_fd()
+    - mei: demote client disconnect warning on suspend to debug
+    - wifi: cfg80211: wext: add extra SIOCSIWSCAN data check
+    - KVM: PPC: Book3S HV: Prevent UAF in kvm_spapr_tce_attach_iommu_group()
+    - ALSA: hda/realtek: Add more codec ID to no shutup pins list
+    - mips: fix compat_sys_lseek syscall
+    - Input: elantech - fix touchpad state on resume for Lenovo N24
+    - bytcr_rt5640 : inverse jack detect for Archos 101 cesium
+    - ASoC: ti: davinci-mcasp: Set min period size using FIFO config
+    - ASoC: ti: omap-hdmi: Fix too long driver name
+    - can: kvaser_usb: fix return value for hif_usb_send_regout
+    - s390/sclp: Fix sclp_init() cleanup on failure
+    - ALSA: dmaengine_pcm: terminate dmaengine before synchronize
+    - net: usb: qmi_wwan: add Telit FN912 compositions
+    - net: mac802154: Fix racy device stats updates by DEV_STATS_INC() and
+      DEV_STATS_ADD()
+    - powerpc/pseries: Whitelist dtl slub object for copying to userspace
+    - powerpc/eeh: avoid possible crash when edev->pdev changes
+    - scsi: libsas: Fix exp-attached device scan after probe failure scanned in
+      again after probe failed
+    - Bluetooth: hci_core: cancel all works upon hci_unregister_dev()
+    - fs: better handle deep ancestor chains in is_subdir()
+    - spi: imx: Don't expect DMA for i.MX{25,35,50,51,53} cspi devices
+    - selftests/vDSO: fix clang build errors and warnings
+    - hfsplus: fix uninit-value in copy_name
+    - ARM: 9324/1: fix get_user() broken with veneer
+    - ACPI: processor_idle: Fix invalid comparison with insertion sort for latency
+    - drm/amdgpu: Fix signedness bug in sdma_v4_0_process_trap_irq()
+    - net: relax socket state check at accept time.
+    - ocfs2: add bounds checking to ocfs2_check_dir_entry()
+    - jfs: don't walk off the end of ealist
+    - ALSA: hda/realtek: Enable headset mic on Positivo SU C1400
+    - filelock: Fix fcntl/close race recovery compat path
+    - tun: add missing verification for short frame
+    - tap: add missing verification for short frame
+    - Linux 5.4.281
+  * Focal update: v5.4.283 upstream stable release (LP: #2080595) //
+    CVE-2024-45016
+    - netem: fix return value if duplicate enqueue fails
+  * CVE-2024-38630
+    - watchdog: cpu5wdt.c: Fix use-after-free bug caused by cpu5wdt_trigger
+  * CVE-2024-27397
+    - netfilter: nf_tables: use timestamp to check for set element timeout
+  * CVE-2024-26960
+    - mm: swap: fix race between free_swap_and_cache() and swapoff()
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Wed, 09 Oct 2024 15:45:46 +1000
+
+linux-xilinx-zynqmp (5.4.0-1053.57) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1053.57 -proposed tracker (LP: #2082230)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] debian.zynqmp/dkms-versions -- update from kernel-versions
+      (main/s2024.09.02)
+
+  [ Ubuntu: 5.4.0-198.218 ]
+
+  * focal/linux: 5.4.0-198.218 -proposed tracker (LP: #2082232)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] debian.master/dkms-versions -- update from kernel-versions
+      (main/s2024.09.02)
+  * CVE-2024-45016
+    - netem: fix return value if duplicate enqueue fails
+  * CVE-2024-38630
+    - watchdog: cpu5wdt.c: Fix use-after-free bug caused by cpu5wdt_trigger
+  * CVE-2024-27397
+    - netfilter: nf_tables: use timestamp to check for set element timeout
+  * CVE-2024-26960
+    - mm: swap: fix race between free_swap_and_cache() and swapoff()
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Fri, 04 Oct 2024 07:50:02 +1000
+
+linux-xilinx-zynqmp (5.4.0-1052.56) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1052.56 -proposed tracker (LP: #2078203)
+
+  [ Ubuntu: 5.4.0-196.216 ]
+
+  * focal/linux: 5.4.0-196.216 -proposed tracker (LP: #2078205)
+  * CVE-2024-39494
+    - ima: Fix use-after-free on a dentry's dname.name
+  * CVE-2024-42160
+    - f2fs: check validation of fault attrs in f2fs_build_fault_attr()
+    - f2fs: Add inline to f2fs_build_fault_attr() stub
+  * CVE-2024-38570
+    - gfs2: Rename sd_{ glock => kill }_wait
+    - gfs2: Fix potential glock use-after-free on unmount
+  * CVE-2024-42228
+    - drm/amdgpu: Using uninitialized value *size when calling amdgpu_vce_cs_reloc
+  * CVE-2022-48791
+    - scsi: pm80xx: Fix TMF task completion race condition
+    - scsi: pm8001: Fix use-after-free for aborted TMF sas_task
+  * CVE-2024-26787
+    - mmc: mmci_sdmmc: Rename sdmmc_priv struct to sdmmc_idma
+    - mmc: mmci: stm32: use a buffer for unaligned DMA requests
+    - mmc: mmci: stm32: fix DMA API overlapping mappings warning
+  * CVE-2024-27012
+    - netfilter: nf_tables: restore set elements when delete set fails
+  * CVE-2022-48863
+    - mISDN: Fix memory leak in dsp_pipeline_build()
+  * CVE-2021-47188
+    - scsi: ufs: core: Improve SCSI abort handling
+  * CVE-2024-26677
+    - rxrpc: Fix delayed ACKs to not set the reference serial number
+
+ -- Stefan Bader <stefan.bader@canonical.com>  Wed, 04 Sep 2024 11:13:23 +0200
+
+linux-xilinx-zynqmp (5.4.0-1051.55) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1051.55 -proposed tracker (LP: #2075952)
+
+  [ Ubuntu: 5.4.0-195.215 ]
+
+  * focal/linux: 5.4.0-195.215 -proposed tracker (LP: #2075954)
+  * Focal update: v5.4.280 upstream stable release (LP: #2075175)
+    - Compiler Attributes: Add __uninitialized macro
+    - drm/lima: fix shared irq handling on driver remove
+    - media: dvb: as102-fe: Fix as10x_register_addr packing
+    - media: dvb-usb: dib0700_devices: Add missing release_firmware()
+    - IB/core: Implement a limit on UMAD receive List
+    - scsi: qedf: Make qedf_execute_tmf() non-preemptible
+    - drm/amdgpu: Initialize timestamp for some legacy SOCs
+    - drm/amd/display: Skip finding free audio for unknown engine_id
+    - media: dw2102: Don't translate i2c read into write
+    - sctp: prefer struct_size over open coded arithmetic
+    - firmware: dmi: Stop decoding on broken entry
+    - Input: ff-core - prefer struct_size over open coded arithmetic
+    - net: dsa: mv88e6xxx: Correct check for empty list
+    - media: dvb-frontends: tda18271c2dd: Remove casting during div
+    - media: s2255: Use refcount_t instead of atomic_t for num_channels
+    - media: dvb-frontends: tda10048: Fix integer overflow
+    - i2c: i801: Annotate apanel_addr as __ro_after_init
+    - powerpc/64: Set _IO_BASE to POISON_POINTER_DELTA not 0 for CONFIG_PCI=n
+    - orangefs: fix out-of-bounds fsid access
+    - powerpc/xmon: Check cpu id in commands "c#", "dp#" and "dx#"
+    - jffs2: Fix potential illegal address access in jffs2_free_inode
+    - s390/pkey: Wipe sensitive data on failure
+    - tcp: tcp_mark_head_lost is only valid for sack-tcp
+    - tcp: add ece_ack flag to reno sack functions
+    - net: tcp better handling of reordering then loss cases
+    - UPSTREAM: tcp: fix DSACK undo in fast recovery to call tcp_try_to_open()
+    - tcp_metrics: validate source addr length
+    - wifi: wilc1000: fix ies_len type in connect path
+    - bonding: Fix out-of-bounds read in bond_option_arp_ip_targets_set()
+    - selftests: fix OOM in msg_zerocopy selftest
+    - selftests: make order checking verbose in msg_zerocopy selftest
+    - inet_diag: Initialize pad field in struct inet_diag_req_v2
+    - nilfs2: fix inode number range checks
+    - nilfs2: add missing check for inode numbers on directory entries
+    - mm: optimize the redundant loop of mm_update_owner_next()
+    - can: kvaser_usb: Explicitly initialize family in leafimx driver_info struct
+    - fsnotify: Do not generate events for O_PATH file descriptors
+    - Revert "mm/writeback: fix possible divide-by-zero in wb_dirty_limits(),
+      again"
+    - drm/nouveau: fix null pointer dereference in nouveau_connector_get_modes
+    - drm/amdgpu/atomfirmware: silence UBSAN warning
+    - media: dw2102: fix a potential buffer overflow
+    - i2c: pnx: Fix potential deadlock warning from del_timer_sync() call in isr
+    - ALSA: hda/realtek: Enable headset mic of JP-IK LEAP W502 with ALC897
+    - nvme-multipath: find NUMA path only for online numa-node
+    - nilfs2: fix incorrect inode allocation from reserved inodes
+    - filelock: fix potential use-after-free in posix_lock_inode
+    - fs/dcache: Re-use value stored to dentry->d_flags instead of re-reading
+    - vfs: don't mod negative dentry count when on shrinker list
+    - tcp: add TCP_INFO status for failed client TFO
+    - tcp: fix incorrect undo caused by DSACK of TLP retransmit
+    - octeontx2-af: Fix incorrect value output on error path in
+      rvu_check_rsrc_availability()
+    - net: lantiq_etop: add blank line after declaration
+    - net: ethernet: lantiq_etop: fix double free in detach
+    - ppp: reject claimed-as-LCP but actually malformed packets
+    - udp: Set SOCK_RCU_FREE earlier in udp_lib_get_port().
+    - s390: Mark psw in __load_psw_mask() as __unitialized
+    - ARM: davinci: Convert comma to semicolon
+    - octeontx2-af: fix detection of IP layer
+    - USB: serial: option: add Telit generic core-dump composition
+    - USB: serial: option: add Telit FN912 rmnet compositions
+    - USB: serial: option: add Fibocom FM350-GL
+    - USB: serial: option: add support for Foxconn T99W651
+    - USB: serial: option: add Netprisma LCUK54 series modules
+    - USB: serial: option: add Rolling RW350-GL variants
+    - USB: Add USB_QUIRK_NO_SET_INTF quirk for START BP-850k
+    - usb: gadget: configfs: Prevent OOB read/write in usb_string_copy()
+    - USB: core: Fix duplicate endpoint bug by clearing reserved bits in the
+      descriptor
+    - hpet: Support 32-bit userspace
+    - nvmem: meson-efuse: Fix return value of nvmem callbacks
+    - ALSA: hda/realtek: Limit mic boost on VAIO PRO PX
+    - libceph: fix race between delayed_work() and ceph_monc_stop()
+    - SUNRPC: Fix RPC client cleaned up the freed pipefs dentries
+    - tcp: refactor tcp_retransmit_timer()
+    - net: tcp: fix unexcepted socket die when snd_wnd is 0
+    - tcp: use signed arithmetic in tcp_rtx_probe0_timed_out()
+    - tcp: avoid too many retransmit packets
+    - nilfs2: fix kernel bug on rename operation of broken directory
+    - i2c: rcar: bring hardware to known state when probing
+    - Linux 5.4.280
+  * [SRU] UBSAN warnings in bnx2x kernel driver (LP: #2074215) // Focal update:
+    v5.4.280 upstream stable release (LP: #2075175)
+    - bnx2x: Fix multiple UBSAN array-index-out-of-bounds
+  * Focal update: v5.4.279 upstream stable release (LP: #2073621)
+    - wifi: mac80211: mesh: Fix leak of mesh_preq_queue objects
+    - wifi: mac80211: Fix deadlock in ieee80211_sta_ps_deliver_wakeup()
+    - wifi: cfg80211: pmsr: use correct nla_get_uX functions
+    - wifi: iwlwifi: mvm: revert gen2 TX A-MPDU size to 64
+    - wifi: iwlwifi: dbg_ini: move iwl_dbg_tlv_free outside of debugfs ifdef
+    - wifi: iwlwifi: mvm: don't read past the mfuart notifcation
+    - ipv6: sr: block BH in seg6_output_core() and seg6_input_core()
+    - net: sched: sch_multiq: fix possible OOB write in multiq_tune()
+    - vxlan: Fix regression when dropping packets due to invalid src addresses
+    - tcp: count CLOSE-WAIT sockets for TCP_MIB_CURRESTAB
+    - net/mlx5: Stop waiting for PCI if pci channel is offline
+    - net/sched: taprio: always validate TCA_TAPRIO_ATTR_PRIOMAP
+    - ptp: Fix error message on failed pin verification
+    - af_unix: Annotate data-race of sk->sk_state in unix_inq_len().
+    - af_unix: Annotate data-races around sk->sk_state in unix_write_space() and
+      poll().
+    - af_unix: Annotate data-races around sk->sk_state in sendmsg() and recvmsg().
+    - af_unix: Annotate data-races around sk->sk_state in UNIX_DIAG.
+    - af_unix: Annotate data-race of net->unx.sysctl_max_dgram_qlen.
+    - af_unix: Use unix_recvq_full_lockless() in unix_stream_connect().
+    - af_unix: Use skb_queue_len_lockless() in sk_diag_show_rqlen().
+    - af_unix: Annotate data-race of sk->sk_shutdown in sk_diag_fill().
+    - ipv6: fix possible race in __fib6_drop_pcpu_from()
+    - usb: gadget: f_fs: Fix race between aio_cancel() and AIO request complete
+    - ASoC: ti: davinci-mcasp: remove redundant assignment to variable ret
+    - ASoC: ti: davinci-mcasp: remove always zero of davinci_mcasp_get_dt_params
+    - ASoC: ti: davinci-mcasp: Use platform_get_irq_byname_optional
+    - ASoC: ti: davinci-mcasp: Remove legacy dma_request parsing
+    - ASoC: ti: davinci-mcasp: Simplify the configuration parameter handling
+    - ASoC: ti: davinci-mcasp: Handle missing required DT properties
+    - ASoC: ti: davinci-mcasp: Fix race condition during probe
+    - drm/amd/display: Handle Y carry-over in VCP X.Y calculation
+    - serial: sc16is7xx: replace hardcoded divisor value with BIT() macro
+    - serial: sc16is7xx: fix bug in sc16is7xx_set_baud() when using prescaler
+    - selftests/mm: compaction_test: fix incorrect write of zero to nr_hugepages
+    - selftests/mm: conform test to TAP format output
+    - selftests/mm: compaction_test: fix bogus test success on Aarch64
+    - nilfs2: Remove check for PageError
+    - nilfs2: return the mapped address from nilfs_get_page()
+    - nilfs2: fix nilfs_empty_dir() misjudgment and long loop on I/O errors
+    - USB: class: cdc-wdm: Fix CPU lockup caused by excessive log messages
+    - mei: me: release irq in mei_me_pci_resume error path
+    - jfs: xattr: fix buffer overflow for invalid xattr
+    - xhci: Set correct transferred length for cancelled bulk transfers
+    - xhci: Apply reset resume quirk to Etron EJ188 xHCI host
+    - xhci: Apply broken streams quirk to Etron EJ188 xHCI host
+    - scsi: mpt3sas: Avoid test/set_bit() operating in non-allocated memory
+    - Input: try trimming too long modalias strings
+    - SUNRPC: return proper error from gss_wrap_req_priv
+    - gpio: tqmx86: fix typo in Kconfig label
+    - HID: core: remove unnecessary WARN_ON() in implement()
+    - iommu/amd: Fix sysfs leak in iommu init
+    - iommu: Return right value in iommu_sva_bind_device()
+    - HID: logitech-dj: Fix memory leak in logi_dj_recv_switch_to_dj_mode()
+    - liquidio: Adjust a NULL pointer handling path in lio_vf_rep_copy_packet
+    - drm/komeda: check for error-valued pointer
+    - drm/bridge/panel: Fix runtime warning on panel bridge release
+    - tcp: fix race in tcp_v6_syn_recv_sock()
+    - net/mlx5e: Fix features validation check for tunneled UDP (non-VXLAN)
+      packets
+    - Bluetooth: L2CAP: Fix rejecting L2CAP_CONN_PARAM_UPDATE_REQ
+    - netfilter: ipset: Fix race between namespace cleanup and gc in the list:set
+      type
+    - net/ipv6: Fix the RT cache flush via sysctl using a previous delay
+    - ionic: fix use after netif_napi_del()
+    - drivers: core: synchronize really_probe() and dev_uevent()
+    - drm/exynos/vidi: fix memory leak in .get_modes()
+    - drm/exynos: hdmi: report safe 640x480 mode as a fallback when no EDID found
+    - tracing/selftests: Fix kprobe event name test for .isra. functions
+    - vmci: prevent speculation leaks by sanitizing event in event_deliver()
+    - fs/proc: fix softlockup in __read_vmcore
+    - ocfs2: use coarse time for new created files
+    - ocfs2: fix races between hole punching and AIO+DIO
+    - PCI: rockchip-ep: Remove wrong mask on subsys_vendor_id
+    - dmaengine: axi-dmac: fix possible race in remove()
+    - intel_th: pci: Add Granite Rapids support
+    - intel_th: pci: Add Granite Rapids SOC support
+    - intel_th: pci: Add Sapphire Rapids SOC support
+    - intel_th: pci: Add Meteor Lake-S support
+    - intel_th: pci: Add Lunar Lake support
+    - nilfs2: fix potential kernel bug due to lack of writeback flag waiting
+    - tick/nohz_full: Don't abuse smp_call_function_single() in
+      tick_setup_device()
+    - hv_utils: drain the timesync packets on onchannelcallback
+    - hugetlb_encode.h: fix undefined behaviour (34 << 26)
+    - greybus: Fix use-after-free bug in gb_interface_release due to race
+      condition.
+    - usb-storage: alauda: Check whether the media is initialized
+    - i2c: at91: Fix the functionality flags of the slave-only interface
+    - rcutorture: Fix rcu_torture_one_read() pipe_count overflow comment
+    - selftests/bpf: Prevent client connect before server bind in
+      test_tc_tunnel.sh
+    - batman-adv: bypass empty buckets in batadv_purge_orig_ref()
+    - drop_monitor: replace spin_lock by raw_spin_lock
+    - scsi: qedi: Fix crash while reading debugfs attribute
+    - Bluetooth: ath3k: Fix multiple issues reported by checkpatch.pl
+    - powerpc/pseries: Enforce hcall result buffer validity and size
+    - powerpc/io: Avoid clang null pointer arithmetic warnings
+    - usb: misc: uss720: check for incompatible versions of the Belkin F5U002
+    - udf: udftime: prevent overflow in udf_disk_stamp_to_time()
+    - PCI/PM: Avoid D3cold for HP Pavilion 17 PC/1972 PCIe Ports
+    - MIPS: Octeon: Add PCIe link status check
+    - MIPS: Routerboard 532: Fix vendor retry check code
+    - mips: bmips: BCM6358: make sure CBR is correctly set
+    - cipso: fix total option length computation
+    - netrom: Fix a memory leak in nr_heartbeat_expiry()
+    - ipv6: prevent possible NULL deref in fib6_nh_init()
+    - ipv6: prevent possible NULL dereference in rt6_probe()
+    - xfrm6: check ip6_dst_idev() return value in xfrm6_get_saddr()
+    - netns: Make get_net_ns() handle zero refcount net
+    - net/sched: act_api: rely on rcu in tcf_idr_check_alloc
+    - net/sched: act_api: fix possible infinite loop in tcf_idr_check_alloc()
+    - virtio_net: checksum offloading handling fix
+    - netfilter: ipset: Fix suspicious rcu_dereference_protected()
+    - net: usb: rtl8150 fix unintiatilzed variables in rtl8150_get_link_ksettings
+    - regulator: core: Fix modpost error "regulator_get_regmap" undefined
+    - dmaengine: ioatdma: Fix missing kmem_cache_destroy()
+    - ACPICA: Revert "ACPICA: avoid Info: mapping multiple BARs. Your kernel is
+      fine."
+    - drm/radeon: fix UBSAN warning in kv_dpm.c
+    - gcov: add support for GCC 14
+    - i2c: ocores: set IACK bit after core is enabled
+    - ARM: dts: samsung: smdkv310: fix keypad no-autorepeat
+    - ARM: dts: samsung: exynos4412-origen: fix keypad no-autorepeat
+    - ARM: dts: samsung: smdk4412: fix keypad no-autorepeat
+    - arm64: dts: qcom: qcs404: fix bluetooth device address
+    - tracing: Add MODULE_DESCRIPTION() to preemptirq_delay_test
+    - Revert "kheaders: substituting --sort in archive creation"
+    - kheaders: explicitly define file modes for archived headers
+    - perf/core: Fix missing wakeup when waiting for context reference
+    - PCI: Add PCI_ERROR_RESPONSE and related definitions
+    - x86/amd_nb: Check for invalid SMN reads
+    - iio: dac: ad5592r-base: Replace indio_dev->mlock with own device lock
+    - iio: dac: ad5592r: un-indent code-block for scale read
+    - iio: dac: ad5592r: fix temperature channel scaling value
+    - pinctrl: fix deadlock in create_pinctrl() when handling -EPROBE_DEFER
+    - pinctrl: rockchip: fix pinmux bits for RK3328 GPIO2-B pins
+    - pinctrl: rockchip: fix pinmux bits for RK3328 GPIO3-B pins
+    - pinctrl: rockchip: fix pinmux reset in rockchip_pmx_set
+    - drm/amdgpu: fix UBSAN warning in kv_dpm.c
+    - netfilter: nf_tables: validate family when identifying table via handle
+    - ASoC: fsl-asoc-card: set priv->pdev before using it
+    - net: dsa: microchip: fix initial port flush problem
+    - net: phy: mchp: Add support for LAN8814 QUAD PHY
+    - net: phy: micrel: add Microchip KSZ 9477 to the device table
+    - sparc: fix old compat_sys_select()
+    - parisc: use correct compat recv/recvfrom syscalls
+    - netfilter: nf_tables: fully validate NFT_DATA_VALUE on store to data
+      registers
+    - drm/panel: ilitek-ili9881c: Fix warning with GPIO controllers that sleep
+    - mtd: partitions: redboot: Added conversion of operands to a larger type
+    - net/iucv: Avoid explicit cpumask var allocation on stack
+    - net/dpaa2: Avoid explicit cpumask var allocation on stack
+    - ALSA: emux: improve patch ioctl data validation
+    - media: dvbdev: Initialize sbuf
+    - soc: ti: wkup_m3_ipc: Send NULL dummy message instead of pointer message
+    - nvme: fixup comment for nvme RDMA Provider Type
+    - gpio: davinci: Validate the obtained number of IRQs
+    - x86: stop playing stack games in profile_pc()
+    - mmc: sdhci-pci: Convert PCIBIOS_* return codes to errnos
+    - mmc: sdhci: Do not invert write-protect twice
+    - mmc: sdhci: Do not lock spinlock around mmc_gpio_get_ro()
+    - iio: adc: ad7266: Fix variable checking bug
+    - iio: chemical: bme680: Fix pressure value output
+    - iio: chemical: bme680: Fix calibration data variable
+    - iio: chemical: bme680: Fix overflows in compensate() functions
+    - iio: chemical: bme680: Fix sensor data read operation
+    - net: usb: ax88179_178a: improve link status logs
+    - usb: gadget: printer: SS+ support
+    - usb: musb: da8xx: fix a resource leak in probe()
+    - usb: atm: cxacru: fix endpoint checking in cxacru_bind()
+    - tty: mcf: MCF54418 has 10 UARTS
+    - net: can: j1939: Initialize unused data in j1939_send_one()
+    - net: can: j1939: recover socket queue on CAN bus error during BAM
+      transmission
+    - net: can: j1939: enhanced error handling for tightly received RTS messages
+      in xtp_rx_rts_session_new
+    - csky, hexagon: fix broken sys_sync_file_range
+    - hexagon: fix fadvise64_64 calling conventions
+    - drm/nouveau/dispnv04: fix null pointer dereference in nv17_tv_get_ld_modes
+    - drm/nouveau/dispnv04: fix null pointer dereference in nv17_tv_get_hd_modes
+    - batman-adv: Don't accept TT entries for out-of-spec VIDs
+    - ata: libata-core: Fix double free on error
+    - ftruncate: pass a signed offset
+    - mtd: spinand: macronix: Add support for serial NAND flash
+    - pwm: stm32: Refuse too small period requests
+    - nfs: Leave pages in the pagecache if readpage failed
+    - ARM: dts: rockchip: rk3066a: add #sound-dai-cells to hdmi node
+    - arm64: dts: rockchip: Add sound-dai-cells for RK3368
+    - Linux 5.4.279
+  * CVE-2024-26921
+    - skbuff: introduce skb_expand_head()
+    - skb_expand_head() adjust skb->truesize incorrectly
+    - inet: inet_defrag: prevent sk release while still in use
+  * CVE-2024-26929
+    - scsi: qla2xxx: Fix double free of fcport
+  * CVE-2024-39484
+    - mmc: davinci: Don't strip remove function when driver is builtin
+  * CVE-2024-36901
+    - ipv6: prevent NULL dereference in ip6_output()
+  * CVE-2024-26830
+    - i40e: Refactoring VF MAC filters counting to make more reliable
+    - i40e: Fix MAC address setting for a VF via Host/VM
+    - i40e: Do not allow untrusted VF to remove administratively set MAC
+  * CVE-2024-24860
+    - Bluetooth: Fix atomicity violation in {min, max}_key_size_set
+  * CVE-2023-52760
+    - gfs2: Fix slab-use-after-free in gfs2_qd_dealloc
+  * CVE-2024-2201
+    - [Config] Set SPECTRE_BHI_ON=y
+  * CVE-2023-52629
+    - sh: push-switch: Reorder cleanup operations to avoid use-after-free bug
+  * CVE-2021-46926
+    - ALSA: hda: intel-sdw-acpi: harden detection of controller
+
+ -- Roger Knecht <roger.knecht@canonical.com>  Wed, 14 Aug 2024 14:48:45 +0200
+
+linux-xilinx-zynqmp (5.4.0-1050.54) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1050.54 -proposed tracker (LP: #2075802)
+
+  [ Ubuntu: 5.4.0-193.213 ]
+
+  * focal/linux: 5.4.0-193.213 -proposed tracker (LP: #2075804)
+  * CVE-2024-26921
+    - skbuff: introduce skb_expand_head()
+    - skb_expand_head() adjust skb->truesize incorrectly
+    - inet: inet_defrag: prevent sk release while still in use
+  * CVE-2024-26929
+    - scsi: qla2xxx: Fix double free of fcport
+  * CVE-2024-39484
+    - mmc: davinci: Don't strip remove function when driver is builtin
+  * CVE-2024-36901
+    - ipv6: prevent NULL dereference in ip6_output()
+  * CVE-2024-26830
+    - i40e: Refactoring VF MAC filters counting to make more reliable
+    - i40e: Fix MAC address setting for a VF via Host/VM
+    - i40e: Do not allow untrusted VF to remove administratively set MAC
+  * CVE-2024-24860
+    - Bluetooth: Fix atomicity violation in {min, max}_key_size_set
+  * CVE-2023-52760
+    - gfs2: Fix slab-use-after-free in gfs2_qd_dealloc
+  * CVE-2024-2201
+    - [Config] Set SPECTRE_BHI_ON=y
+  * CVE-2023-52629
+    - sh: push-switch: Reorder cleanup operations to avoid use-after-free bug
+  * CVE-2021-46926
+    - ALSA: hda: intel-sdw-acpi: harden detection of controller
+
+ -- Roger Knecht <roger.knecht@canonical.com>  Thu, 08 Aug 2024 13:10:06 +0200
+
+linux-xilinx-zynqmp (5.4.0-1049.53) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1049.53 -proposed tracker (LP: #2072303)
+
+  [ Ubuntu: 5.4.0-192.212 ]
+
+  * focal/linux: 5.4.0-192.212 -proposed tracker (LP: #2072305)
+  * Focal update: v5.4.278 upstream stable release (LP: #2071668)
+    - x86/tsc: Trust initial offset in architectural TSC-adjust MSRs
+    - speakup: Fix sizeof() vs ARRAY_SIZE() bug
+    - ring-buffer: Fix a race between readers and resize checks
+    - net: smc91x: Fix m68k kernel compilation for ColdFire CPU
+    - nilfs2: fix unexpected freezing of nilfs_segctor_sync()
+    - nilfs2: fix potential hang in nilfs_detach_log_writer()
+    - wifi: cfg80211: fix the order of arguments for trace events of the tx_rx_evt
+      class
+    - net: usb: qmi_wwan: add Telit FN920C04 compositions
+    - drm/amd/display: Set color_mgmt_changed to true on unsuspend
+    - ASoC: rt5645: Fix the electric noise due to the CBJ contacts floating
+    - ASoC: dt-bindings: rt5645: add cbj sleeve gpio property
+    - ASoC: da7219-aad: fix usage of device_get_named_child_node()
+    - drm/amdkfd: Flush the process wq before creating a kfd_process
+    - nvme: find numa distance only if controller has valid numa id
+    - openpromfs: finish conversion to the new mount API
+    - crypto: bcm - Fix pointer arithmetic
+    - firmware: raspberrypi: Use correct device for DMA mappings
+    - ecryptfs: Fix buffer size for tag 66 packet
+    - nilfs2: fix out-of-range warning
+    - parisc: add missing export of __cmpxchg_u8()
+    - crypto: ccp - drop platform ifdef checks
+    - s390/cio: fix tracepoint subchannel type field
+    - jffs2: prevent xattr node from overflowing the eraseblock
+    - null_blk: Fix missing mutex_destroy() at module removal
+    - md: fix resync softlockup when bitmap size is less than array size
+    - wifi: ath10k: poll service ready message before failing
+    - x86/boot: Ignore relocations in .notes sections in walk_relocs() too
+    - qed: avoid truncating work queue length
+    - scsi: ufs: qcom: Perform read back after writing reset bit
+    - scsi: ufs: cdns-pltfrm: Perform read back after writing HCLKDIV
+    - scsi: ufs: core: Perform read back after disabling interrupts
+    - scsi: ufs: core: Perform read back after disabling UIC_COMMAND_COMPL
+    - irqchip/alpine-msi: Fix off-by-one in allocation error path
+    - ACPI: disable -Wstringop-truncation
+    - cpufreq: Reorganize checks in cpufreq_offline()
+    - cpufreq: Split cpufreq_offline()
+    - cpufreq: Rearrange locking in cpufreq_remove_dev()
+    - cpufreq: exit() callback is optional
+    - scsi: libsas: Fix the failure of adding phy with zero-address to port
+    - scsi: hpsa: Fix allocation size for Scsi_Host private data
+    - x86/purgatory: Switch to the position-independent small code model
+    - wifi: ath10k: Fix an error code problem in
+      ath10k_dbg_sta_write_peer_debug_trigger()
+    - wifi: ath10k: populate board data for WCN3990
+    - tcp: minor optimization in tcp_add_backlog()
+    - tcp: fix a signed-integer-overflow bug in tcp_add_backlog()
+    - tcp: avoid premature drops in tcp_add_backlog()
+    - macintosh/via-macii: Fix "BUG: sleeping function called from invalid
+      context"
+    - wifi: carl9170: add a proper sanity check for endpoints
+    - wifi: ar5523: enable proper endpoint verification
+    - sh: kprobes: Merge arch_copy_kprobe() into arch_prepare_kprobe()
+    - Revert "sh: Handle calling csum_partial with misaligned data"
+    - HID: intel-ish-hid: ipc: Add check for pci_alloc_irq_vectors
+    - scsi: bfa: Ensure the copied buf is NUL terminated
+    - scsi: qedf: Ensure the copied buf is NUL terminated
+    - wifi: mwl8k: initialize cmd->addr[] properly
+    - usb: aqc111: stop lying about skb->truesize
+    - net: usb: sr9700: stop lying about skb->truesize
+    - m68k: Fix spinlock race in kernel thread creation
+    - m68k: mac: Fix reboot hang on Mac IIci
+    - net: ethernet: cortina: Locking fixes
+    - af_unix: Fix data races in unix_release_sock/unix_stream_sendmsg
+    - net: usb: smsc95xx: stop lying about skb->truesize
+    - net: openvswitch: fix overwriting ct original tuple for ICMPv6
+    - ipv6: sr: add missing seg6_local_exit
+    - ipv6: sr: fix incorrect unregister order
+    - ipv6: sr: fix invalid unregister error path
+    - drm/amd/display: Fix potential index out of bounds in color transformation
+      function
+    - mtd: rawnand: hynix: fixed typo
+    - fbdev: shmobile: fix snprintf truncation
+    - drm/mediatek: Add 0 size check to mtk_drm_gem_obj
+    - powerpc/fsl-soc: hide unused const variable
+    - fbdev: sisfb: hide unused variables
+    - media: ngene: Add dvb_ca_en50221_init return value check
+    - media: radio-shark2: Avoid led_names truncations
+    - platform/x86: wmi: Make two functions static
+    - fbdev: sh7760fb: allow modular build
+    - drm/arm/malidp: fix a possible null pointer dereference
+    - ASoC: tracing: Export SND_SOC_DAPM_DIR_OUT to its value
+    - drm/panel: simple: Add missing Innolux G121X1-L03 format, flags, connector
+    - RDMA/hns: Use complete parentheses in macros
+    - x86/insn: Fix PUSH instruction in x86 instruction decoder opcode map
+    - ext4: avoid excessive credit estimate in ext4_tmpfile()
+    - sunrpc: removed redundant procp check
+    - SUNRPC: Fix gss_free_in_token_pages()
+    - selftests/kcmp: Make the test output consistent and clear
+    - selftests/kcmp: remove unused open mode
+    - RDMA/IPoIB: Fix format truncation compilation errors
+    - netrom: fix possible dead-lock in nr_rt_ioctl()
+    - af_packet: do not call packet_read_pending() from tpacket_destruct_skb()
+    - sched/topology: Don't set SD_BALANCE_WAKE on cpuset domain relax
+    - sched/fair: Allow disabling sched_balance_newidle with
+      sched_relax_domain_level
+    - greybus: lights: check return of get_channel_from_mode
+    - soundwire: cadence/intel: simplify PDI/port mapping
+    - soundwire: intel: don't filter out PDI0/1
+    - soundwire: cadence_master: improve PDI allocation
+    - soundwire: cadence: fix invalid PDI offset
+    - dmaengine: idma64: Add check for dma_set_max_seg_size
+    - firmware: dmi-id: add a release callback function
+    - serial: max3100: Lock port->lock when calling uart_handle_cts_change()
+    - serial: max3100: Update uart_driver_registered on driver removal
+    - serial: max3100: Fix bitwise types
+    - greybus: arche-ctrl: move device table to its right location
+    - iio: pressure: dps310: support negative temperature values
+    - microblaze: Remove gcc flag for non existing early_printk.c file
+    - microblaze: Remove early printk call from cpuinfo-static.c
+    - usb: gadget: u_audio: Clear uac pointer when freed.
+    - stm class: Fix a double free in stm_register_device()
+    - ppdev: Remove usage of the deprecated ida_simple_xx() API
+    - ppdev: Add an error check in register_device
+    - extcon: max8997: select IRQ_DOMAIN instead of depending on it
+    - f2fs: fix to release node block count in error path of f2fs_new_node_page()
+    - serial: sh-sci: protect invalidating RXDMA on shutdown
+    - libsubcmd: Fix parse-options memory leak
+    - Input: ims-pcu - fix printf string overflow
+    - Input: pm8xxx-vibrator - correct VIB_MAX_LEVELS calculation
+    - drm/msm/dpu: Always flush the slave INTF on the CTL
+    - um: Fix return value in ubd_init()
+    - um: Add winch to winch_handlers before registering winch IRQ
+    - media: stk1160: fix bounds checking in stk1160_copy_video()
+    - scsi: qla2xxx: Replace all non-returning strlcpy() with strscpy()
+    - powerpc/pseries: Add failure related checks for h_get_mpp and h_get_ppp
+    - um: Fix the -Wmissing-prototypes warning for __switch_mm
+    - media: cec: cec-adap: always cancel work in cec_transmit_msg_fh
+    - media: cec: cec-api: add locking in cec_release()
+    - null_blk: Fix the WARNING: modpost: missing MODULE_DESCRIPTION()
+    - x86/kconfig: Select ARCH_WANT_FRAME_POINTERS again when
+      UNWINDER_FRAME_POINTER=y
+    - [Config] Update CONFIG_ARCH_WANT_FRAME_POINTERS
+    - nfc: nci: Fix uninit-value in nci_rx_work
+    - sunrpc: fix NFSACL RPC retry on soft mount
+    - ipv6: sr: fix memleak in seg6_hmac_init_algo
+    - params: lift param_set_uint_minmax to common code
+    - tcp: Fix shift-out-of-bounds in dctcp_update_alpha().
+    - openvswitch: Set the skbuff pkt_type for proper pmtud support.
+    - arm64: asm-bug: Add .align 2 to the end of __BUG_ENTRY
+    - virtio: delete vq in vp_find_vqs_msix() when request_irq() fails
+    - net: fec: avoid lock evasion when reading pps_enable
+    - nfc: nci: Fix kcov check in nci_rx_work()
+    - nfc: nci: Fix handling of zero-length payload packets in nci_rx_work()
+    - netfilter: nfnetlink_queue: acquire rcu_read_lock() in
+      instance_destroy_rcu()
+    - spi: Don't mark message DMA mapped when no transfer in it is
+    - nvmet: fix ns enable/disable possible hang
+    - net/mlx5e: Use rx_missed_errors instead of rx_dropped for reporting buffer
+      exhaustion
+    - dma-buf/sw-sync: don't enable IRQ from sync_print_obj()
+    - enic: Validate length of nl attributes in enic_set_vf_port
+    - smsc95xx: remove redundant function arguments
+    - smsc95xx: use usbnet->driver_priv
+    - net: usb: smsc95xx: fix changing LED_SEL bit value updated from EEPROM
+    - net:fec: Add fec_enet_deinit()
+    - netfilter: tproxy: bail out if IP has been disabled on the device
+    - kconfig: fix comparison to constant symbols, 'm', 'n'
+    - spi: stm32: Don't warn about spurious interrupts
+    - ipvlan: Dont Use skb->sk in ipvlan_process_v{4,6}_outbound
+    - ALSA: timer: Set lower bound of start tick time
+    - genirq/cpuhotplug, x86/vector: Prevent vector leak during CPU offline
+    - SUNRPC: Fix loop termination condition in gss_free_in_token_pages()
+    - binder: fix max_thread type inconsistency
+    - mmc: core: Do not force a retune before RPMB switch
+    - io_uring: fail NOP if non-zero op flags is passed in
+    - afs: Don't cross .backup mountpoint from backup volume
+    - nilfs2: fix use-after-free of timer for log writer thread
+    - vxlan: Fix regression when dropping packets due to invalid src addresses
+    - x86/mm: Remove broken vsyscall emulation code from the page fault code
+    - f2fs: fix to do sanity check on i_xattr_nid in sanity_check_inode()
+    - media: lgdt3306a: Add a check against null-pointer-def
+    - drm/amdgpu: add error handle to avoid out-of-bounds
+    - ata: pata_legacy: make legacy_exit() work again
+    - ACPI: resource: Do IRQ override on TongFang GXxHRXx and GMxHGxx
+    - arm64: tegra: Correct Tegra132 I2C alias
+    - md/raid5: fix deadlock that raid5d() wait for itself to clear
+      MD_SB_CHANGE_PENDING
+    - wifi: rtl8xxxu: Fix the TX power of RTL8192CU, RTL8723AU
+    - arm64: dts: hi3798cv200: fix the size of GICR
+    - media: mc: mark the media devnode as registered from the, start
+    - media: mxl5xx: Move xpt structures off stack
+    - media: v4l2-core: hold videodev_lock until dev reg, finishes
+    - fbdev: savage: Handle err return when savagefb_check_var failed
+    - KVM: arm64: Allow AArch32 PSTATE.M to be restored as System mode
+    - crypto: ecrdsa - Fix module auto-load on add_key
+    - crypto: qat - Fix ADF_DEV_RESET_SYNC memory leak
+    - net/ipv6: Fix route deleting failure when metric equals 0
+    - net/9p: fix uninit-value in p9_client_rpc()
+    - intel_th: pci: Add Meteor Lake-S CPU support
+    - sparc64: Fix number of online CPUs
+    - kdb: Fix buffer overflow during tab-complete
+    - kdb: Use format-strings rather than '\0' injection in kdb_read()
+    - kdb: Fix console handling when editing and tab-completing commands
+    - kdb: Merge identical case statements in kdb_read()
+    - kdb: Use format-specifiers rather than memset() for padding in kdb_read()
+    - net: fix __dst_negative_advice() race
+    - xsk: validate user input for XDP_{UMEM|COMPLETION}_FILL_RING
+    - sparc: move struct termio to asm/termios.h
+    - ext4: fix mb_cache_entry's e_refcnt leak in ext4_xattr_block_cache_find()
+    - s390/ap: Fix crash in AP internal function modify_bitmap()
+    - nfs: fix undefined behavior in nfs_block_bits()
+    - Linux 5.4.278
+  * CVE-2024-27019
+    - netfilter: nf_tables: restrict tunnel object to NFPROTO_NETDEV
+    - netfilter: nf_tables: Fix potential data-race in __nft_obj_type_get()
+  * CVE-2024-26886
+    - Bluetooth: af_bluetooth: Fix deadlock
+  * CVE-2023-52752
+    - smb: client: fix use-after-free bug in cifs_debug_data_proc_show()
+  * CVE-2022-48674
+    - erofs: fix pcluster use-after-free on UP platforms
+  * Focal update: v5.4.277 upstream stable release (LP: #2070179)
+    - pinctrl: core: handle radix_tree_insert() errors in
+      pinctrl_register_one_pin()
+    - ext4: fix bug_on in __es_tree_search
+    - Revert "selftests: mm: fix map_hugetlb failure on 64K page size systems"
+    - Revert "net: bcmgenet: use RGMII loopback for MAC reset"
+    - net: bcmgenet: keep MAC in reset until PHY is up
+    - net: bcmgenet: synchronize EXT_RGMII_OOB_CTRL access
+    - net: bcmgenet: synchronize use of bcmgenet_set_rx_mode()
+    - net: bcmgenet: synchronize UMAC_CMD access
+    - smb: client: fix potential OOBs in smb2_parse_contexts()
+    - arm64: dts: qcom: Fix 'interrupt-map' parent address cells
+    - btrfs: add missing mutex_unlock in btrfs_relocate_sys_chunks()
+    - drm/amdgpu: Fix possible NULL dereference in
+      amdgpu_ras_query_error_status_helper()
+    - usb: typec: ucsi: displayport: Fix potential deadlock
+    - serial: kgdboc: Fix NMI-safety problems from keyboard reset code
+    - docs: kernel_include.py: Cope with docutils 0.21
+    - Linux 5.4.277
+  * Focal update: v5.4.276 upstream stable release (LP: #2069758)
+    - dmaengine: pl330: issue_pending waits until WFP state
+    - dmaengine: Revert "dmaengine: pl330: issue_pending waits until WFP state"
+    - wifi: nl80211: don't free NULL coalescing rule
+    - pinctrl: core: delete incorrect free in pinctrl_enable()
+    - pinctrl: mediatek: Check gpio pin number and use binary search in
+      mtk_hw_pin_field_lookup()
+    - pinctrl: mediatek: Supporting driving setting without mapping current to
+      register value
+    - pinctrl: mediatek: Refine mtk_pinconf_get() and mtk_pinconf_set()
+    - pinctrl: mediatek: Refine mtk_pinconf_get()
+    - pinctrl: mediatek: Backward compatible to previous Mediatek's bias-pull
+      usage
+    - pinctrl: mediatek: remove shadow variable declaration
+    - pinctrl: mediatek: paris: Fix PIN_CONFIG_BIAS_* readback
+    - pinctrl: mediatek: paris: Rework mtk_pinconf_{get,set} switch/case logic
+    - pinctrl: mediatek: paris: Rework support for
+      PIN_CONFIG_{INPUT,OUTPUT}_ENABLE
+    - sunrpc: add a struct rpc_stats arg to rpc_create_args
+    - nfs: expose /proc/net/sunrpc/nfs in net namespaces
+    - nfs: make the rpc_stat per net namespace
+    - nfs: Handle error of rpc_proc_register() in nfs_net_init().
+    - power: rt9455: hide unused rt9455_boost_voltage_values
+    - pinctrl: devicetree: fix refcount leak in pinctrl_dt_to_map()
+    - s390/mm: Fix storage key clearing for guest huge pages
+    - s390/mm: Fix clearing storage keys for huge pages
+    - bna: ensure the copied buf is NUL terminated
+    - nsh: Restore skb->{protocol,data,mac_header} for outer header in
+      nsh_gso_segment().
+    - net l2tp: drop flow hash on forward
+    - net: qede: use return from qede_parse_flow_attr() for flow_spec
+    - net: dsa: mv88e6xxx: Add number of MACs in the ATU
+    - net: dsa: mv88e6xxx: Fix number of databases for 88E6141 / 88E6341
+    - net: bridge: fix multicast-to-unicast with fraglist GSO
+    - tipc: fix a possible memleak in tipc_buf_append
+    - clk: sunxi-ng: h6: Reparent CPUX during PLL CPUX rate change
+    - scsi: lpfc: Update lpfc_ramp_down_queue_handler() logic
+    - gfs2: Fix invalid metadata access in punch_hole
+    - wifi: mac80211: fix ieee80211_bss_*_flags kernel-doc
+    - wifi: cfg80211: fix rdev_dump_mpp() arguments order
+    - net: mark racy access on sk->sk_rcvbuf
+    - scsi: bnx2fc: Remove spin_lock_bh while releasing resources after upload
+    - ALSA: line6: Zero-initialize message buffers
+    - net: bcmgenet: Reset RBUF on first open
+    - ata: sata_gemini: Check clk_enable() result
+    - firewire: ohci: mask bus reset interrupts between ISR and bottom half
+    - tools/power turbostat: Fix added raw MSR output
+    - tools/power turbostat: Fix Bzy_MHz documentation typo
+    - btrfs: make btrfs_clear_delalloc_extent() free delalloc reserve
+    - btrfs: always clear PERTRANS metadata during commit
+    - scsi: target: Fix SELinux error when systemd-modules loads the target module
+    - gpu: host1x: Do not setup DMA for virtual devices
+    - MIPS: scall: Save thread_info.syscall unconditionally on entry
+    - selftests: timers: Fix valid-adjtimex signed left-shift undefined behavior
+    - fs/9p: only translate RWX permissions for plain 9P2000
+    - fs/9p: translate O_TRUNC into OTRUNC
+    - 9p: explicitly deny setlease attempts
+    - gpio: wcove: Use -ENOTSUPP consistently
+    - gpio: crystalcove: Use -ENOTSUPP consistently
+    - clk: Don't hold prepare_lock when calling kref_put()
+    - fs/9p: drop inodes immediately on non-.L too
+    - net:usb:qmi_wwan: support Rolling modules
+    - pinctrl: mediatek: Fix fallback call path
+    - xfrm: Preserve vlan tags for transport mode software GRO
+    - tcp: defer shutdown(SEND_SHUTDOWN) for TCP_SYN_RECV sockets
+    - tcp: Use refcount_inc_not_zero() in tcp_twsk_unique().
+    - Bluetooth: Fix use-after-free bugs caused by sco_sock_timeout
+    - Bluetooth: l2cap: fix null-ptr-deref in l2cap_chan_timeout
+    - rtnetlink: Correct nested IFLA_VF_VLAN_LIST attribute validation
+    - phonet: fix rtm_phonet_notify() skb allocation
+    - net: bridge: fix corrupted ethernet header on multicast-to-unicast
+    - ipv6: fib6_rules: avoid possible NULL dereference in fib6_rule_action()
+    - net: qede: sanitize 'rc' in qede_add_tc_flower_fltr()
+    - net: qede: use return from qede_parse_flow_attr() for flower
+    - firewire: nosy: ensure user_length is taken into account when fetching
+      packet contents
+    - usb: gadget: composite: fix OS descriptors w_value logic
+    - usb: gadget: f_fs: Fix a race condition when processing setup packets.
+    - tipc: fix UAF in error path
+    - dyndbg: fix old BUG_ON in >control parser
+    - drm/vmwgfx: Fix invalid reads in fence signaled events
+    - net: fix out-of-bounds access in ops_init
+    - regulator: core: fix debugfs creation regression
+    - pinctrl: mediatek: Fix fallback behavior for bias_set_combo
+    - pinctrl: mediatek: Fix some off by one bugs
+    - pinctrl: mediatek: remove set but not used variable 'e'
+    - pinctrl: mediatek: paris: Fix PIN_CONFIG_INPUT_SCHMITT_ENABLE readback
+    - Linux 5.4.276
+  * Freezing user space processes failed after 20.008 seconds (1 tasks refusing
+    to freeze, wq_busy=0) (LP: #2061091)
+    - ALSA: Fix deadlocks with kctl removals at disconnection
+  * CVE-2024-36016
+    - tty: n_gsm: fix possible out-of-bounds in gsm0_receive()
+  * CVE-2022-48655
+    - firmware: arm_scmi: Harden accesses to the reset domains
+  * CVE-2024-26907
+    - RDMA/mlx5: Fix fortify source warning while accessing Eth segment
+  * CVE-2024-26585
+    - tls: fix race between tx work scheduling and socket close
+  * CVE-2024-26584
+    - net: tls: handle backlogging of crypto requests
+  * CVE-2024-26583
+    - net/tls: Replace TLS_RX_SYNC_RUNNING with RCU
+    - net/tls: Fix use-after-free after the TLS device goes down and up
+    - tls: splice_read: fix record type check
+    - tls splice: remove inappropriate flags checking for MSG_PEEK
+    - tls: splice_read: fix accessing pre-processed records
+    - tls: Fix context leak on tls_device_down
+    - net/tls: Check for errors in tls_device_init
+    - net/tls: Remove the context from the list in tls_device_down
+    - net/tls: pass context to tls_device_decrypted()
+    - net/tls: Perform immediate device ctx cleanup when possible
+    - net/tls: Multi-threaded calls to TX tls_dev_del
+    - net: tls: avoid discarding data on record close
+    - tls: rx: don't store the record type in socket context
+    - tls: rx: don't store the decryption status in socket context
+    - tls: rx: don't issue wake ups when data is decrypted
+    - tls: rx: refactor decrypt_skb_update()
+    - tls: hw: rx: use return value of tls_device_decrypted() to carry status
+    - tls: rx: drop unnecessary arguments from tls_setup_from_iter()
+    - tls: rx: don't report text length from the bowels of decrypt
+    - tls: rx: wrap decryption arguments in a structure
+    - tls: rx: factor out writing ContentType to cmsg
+    - tls: rx: don't track the async count
+    - tls: rx: assume crypto always calls our callback
+    - tls: rx: use async as an in-out argument
+    - tls: decrement decrypt_pending if no async completion will be called
+    - net: tls: fix async vs NIC crypto offload
+    - tls: rx: simplify async wait
+    - tls: extract context alloc/initialization out of tls_set_sw_offload
+    - net: tls: factor out tls_*crypt_async_wait()
+    - tls: fix race between async notify and socket close
+
+ -- Guoqing Jiang <guoqing.jiang@canonical.com>  Fri, 19 Jul 2024 11:03:17 +0800
+
+linux-xilinx-zynqmp (5.4.0-1048.52) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1048.52 -proposed tracker (LP: #2072106)
+
+  [ Ubuntu: 5.4.0-190.210 ]
+
+  * focal/linux: 5.4.0-190.210 -proposed tracker (LP: #2072108)
+  * CVE-2024-36016
+    - tty: n_gsm: fix possible out-of-bounds in gsm0_receive()
+  * CVE-2022-48655
+    - firmware: arm_scmi: Harden accesses to the reset domains
+  * CVE-2024-26907
+    - RDMA/mlx5: Fix fortify source warning while accessing Eth segment
+  * CVE-2024-26585
+    - tls: fix race between tx work scheduling and socket close
+  * CVE-2024-26584
+    - net: tls: handle backlogging of crypto requests
+  * CVE-2024-26583
+    - net/tls: Replace TLS_RX_SYNC_RUNNING with RCU
+    - net/tls: Fix use-after-free after the TLS device goes down and up
+    - tls: splice_read: fix record type check
+    - tls splice: remove inappropriate flags checking for MSG_PEEK
+    - tls: splice_read: fix accessing pre-processed records
+    - tls: Fix context leak on tls_device_down
+    - net/tls: Check for errors in tls_device_init
+    - net/tls: Remove the context from the list in tls_device_down
+    - net/tls: pass context to tls_device_decrypted()
+    - net/tls: Perform immediate device ctx cleanup when possible
+    - net/tls: Multi-threaded calls to TX tls_dev_del
+    - net: tls: avoid discarding data on record close
+    - tls: rx: don't store the record type in socket context
+    - tls: rx: don't store the decryption status in socket context
+    - tls: rx: don't issue wake ups when data is decrypted
+    - tls: rx: refactor decrypt_skb_update()
+    - tls: hw: rx: use return value of tls_device_decrypted() to carry status
+    - tls: rx: drop unnecessary arguments from tls_setup_from_iter()
+    - tls: rx: don't report text length from the bowels of decrypt
+    - tls: rx: wrap decryption arguments in a structure
+    - tls: rx: factor out writing ContentType to cmsg
+    - tls: rx: don't track the async count
+    - tls: rx: assume crypto always calls our callback
+    - tls: rx: use async as an in-out argument
+    - tls: decrement decrypt_pending if no async completion will be called
+    - net: tls: fix async vs NIC crypto offload
+    - tls: rx: simplify async wait
+    - tls: extract context alloc/initialization out of tls_set_sw_offload
+    - net: tls: factor out tls_*crypt_async_wait()
+    - tls: fix race between async notify and socket close
+
+ -- Guoqing Jiang <guoqing.jiang@canonical.com>  Wed, 17 Jul 2024 12:30:26 +0800
+
+linux-xilinx-zynqmp (5.4.0-1047.51) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1047.51 -proposed tracker (LP: #2068452)
+
+  [ Ubuntu: 5.4.0-189.209 ]
+
+  * focal/linux: 5.4.0-189.209 -proposed tracker (LP: #2068454)
+  * Focal update: v5.4.275 upstream stable release (LP: #2067865)
+    - batman-adv: Avoid infinite loop trying to resize local TT
+    - Bluetooth: Fix memory leak in hci_req_sync_complete()
+    - nouveau: fix function cast warning
+    - net: openvswitch: fix unwanted error log on timeout policy probing
+    - u64_stats: fix u64_stats_init() for lockdep when used repeatedly in one file
+    - geneve: fix header validation in geneve[6]_xmit_skb
+    - ipv6: fib: hide unused 'pn' variable
+    - ipv4/route: avoid unused-but-set-variable warning
+    - ipv6: fix race condition between ipv6_get_ifaddr and ipv6_del_addr
+    - net/mlx5: Properly link new fs rules into the tree
+    - net: ena: Fix potential sign extension issue
+    - btrfs: qgroup: correctly model root qgroup rsv in convert
+    - drm/client: Fully protect modes[] with dev->mode_config.mutex
+    - vhost: Add smp_rmb() in vhost_vq_avail_empty()
+    - selftests: timers: Fix abs() warning in posix_timers test
+    - x86/apic: Force native_apic_mem_read() to use the MOV instruction
+    - btrfs: record delayed inode root in transaction
+    - selftests/ftrace: Limit length in subsystem-enable tests
+    - kprobes: Fix possible use-after-free issue on kprobe registration
+    - Revert "tracing/trigger: Fix to return error if failed to alloc snapshot"
+    - netfilter: nf_tables: Fix potential data-race in __nft_expr_type_get()
+    - tun: limit printing rate when illegal packet received by tun dev
+    - RDMA/rxe: Fix the problem "mutex_destroy missing"
+    - RDMA/mlx5: Fix port number for counter query in multi-port configuration
+    - drm: nv04: Fix out of bounds access
+    - clk: Remove prepare_lock hold assertion in __clk_release()
+    - clk: Mark 'all_lists' as const
+    - clk: remove extra empty line
+    - clk: Print an info line before disabling unused clocks
+    - clk: Initialize struct clk_core kref earlier
+    - clk: Get runtime PM before walking tree during disable_unused
+    - x86/cpufeatures: Fix dependencies for GFNI, VAES, and VPCLMULQDQ
+    - comedi: vmk80xx: fix incomplete endpoint checking
+    - serial/pmac_zilog: Remove flawed mitigation for rx irq flood
+    - USB: serial: option: add Fibocom FM135-GL variants
+    - USB: serial: option: add support for Fibocom FM650/FG650
+    - USB: serial: option: add Lonsung U8300/U9300 product
+    - USB: serial: option: support Quectel EM060K sub-models
+    - USB: serial: option: add Rolling RW101-GL and RW135-GL support
+    - USB: serial: option: add Telit FN920C04 rmnet compositions
+    - usb: dwc2: host: Fix dereference issue in DDMA completion flow.
+    - speakup: Avoid crash on very long word
+    - fs: sysfs: Fix reference leak in sysfs_break_active_protection()
+    - nouveau: fix instmem race condition around ptr stores
+    - nilfs2: fix OOB in nilfs_set_de_type
+    - KVM: async_pf: Cleanup kvm_setup_async_pf()
+    - arm64: dts: rockchip: fix alphabetical ordering RK3399 puma
+    - arm64: dts: rockchip: enable internal pull-up on PCIE_WAKE# for RK3399 Puma
+    - arm64: dts: mediatek: mt7622: fix IR nodename
+    - arm64: dts: mediatek: mt7622: fix ethernet controller "compatible"
+    - arm64: dts: mediatek: mt7622: drop "reset-names" from thermal block
+    - arm64: dts: mt2712: add ethernet device node
+    - arm64: dts: mediatek: mt2712: fix validation errors
+    - ARC: [plat-hsdk]: Remove misplaced interrupt-cells property
+    - vxlan: drop packets from invalid src-address
+    - mlxsw: core: Unregister EMAD trap using FORWARD action
+    - NFC: trf7970a: disable all regulators on removal
+    - net: usb: ax88179_178a: stop lying about skb->truesize
+    - net: gtp: Fix Use-After-Free in gtp_dellink
+    - ipvs: Fix checksumming on GSO of SCTP packets
+    - net: openvswitch: Fix Use-After-Free in ovs_ct_exit
+    - mlxsw: spectrum_acl_tcam: Fix race during rehash delayed work
+    - mlxsw: spectrum_acl_tcam: Fix possible use-after-free during activity update
+    - mlxsw: spectrum_acl_tcam: Fix possible use-after-free during rehash
+    - mlxsw: spectrum_acl_tcam: Rate limit error message
+    - mlxsw: spectrum_acl_tcam: Fix memory leak during rehash
+    - mlxsw: spectrum_acl_tcam: Fix warning during rehash
+    - mlxsw: spectrum_acl_tcam: Fix incorrect list API usage
+    - mlxsw: spectrum_acl_tcam: Fix memory leak when canceling rehash work
+    - i40e: Do not use WQ_MEM_RECLAIM flag for workqueue
+    - iavf: Fix TC config comparison with existing adapter TC config
+    - af_unix: Suppress false-positive lockdep splat for spin_lock() in
+      __unix_gc().
+    - serial: core: Provide port lock wrappers
+    - serial: mxs-auart: add spinlock around changing cts state
+    - Revert "crypto: api - Disallow identical driver names"
+    - net/mlx5e: Fix a race in command alloc flow
+    - tracing: Show size of requested perf buffer
+    - tracing: Increase PERF_MAX_TRACE_SIZE to handle Sentinel1 and docker
+      together
+    - Bluetooth: Fix type of len in {l2cap,sco}_sock_getsockopt_old()
+    - Bluetooth: btusb: Add Realtek RTL8852BE support ID 0x0bda:0x4853
+    - btrfs: fix information leak in btrfs_ioctl_logical_to_ino()
+    - arm64: dts: rockchip: enable internal pull-up for Q7_THRM# on RK3399 Puma
+    - drm/amdgpu: Fix leak when GPU memory allocation fails
+    - irqchip/gic-v3-its: Prevent double free on error
+    - ethernet: Add helper for assigning packet type when dest address does not
+      match device address
+    - net: b44: set pause params only when interface is up
+    - stackdepot: respect __GFP_NOLOCKDEP allocation flag
+    - mtd: diskonchip: work around ubsan link failure
+    - tcp: Clean up kernel listener's reqsk in inet_twsk_purge()
+    - tcp: Fix NEW_SYN_RECV handling in inet_twsk_purge()
+    - dmaengine: owl: fix register access functions
+    - idma64: Don't try to serve interrupts when device is powered off
+    - i2c: smbus: fix NULL function pointer dereference
+    - HID: i2c-hid: remove I2C_HID_READ_PENDING flag to prevent lock-up
+    - bounds: Use the right number of bits for power-of-two CONFIG_NR_CPUS
+    - udp: preserve the connected status if only UDP cmsg
+    - serial: core: fix kernel-doc for uart_port_unlock_irqrestore()
+    - Linux 5.4.275
+  * Focal update: v5.4.274 upstream stable release (LP: #2067857)
+    - amdkfd: use calloc instead of kzalloc to avoid integer overflow
+    - Documentation/hw-vuln: Update spectre doc
+    - x86/cpu: Support AMD Automatic IBRS
+    - x86/bugs: Use sysfs_emit()
+    - timers: Update kernel-doc for various functions
+    - timers: Use del_timer_sync() even on UP
+    - timers: Rename del_timer_sync() to timer_delete_sync()
+    - media: staging: ipu3-imgu: Set fields before media_entity_pads_init()
+    - clk: qcom: gcc-sdm845: Add soft dependency on rpmhpd
+    - smack: Set SMACK64TRANSMUTE only for dirs in smack_inode_setxattr()
+    - smack: Handle SMACK64TRANSMUTE in smack_inode_setsecurity()
+    - ARM: dts: mmp2-brownstone: Don't redeclare phandle references
+    - arm: dts: marvell: Fix maxium->maxim typo in brownstone dts
+    - serial: max310x: fix NULL pointer dereference in I2C instantiation
+    - KVM: Always flush async #PF workqueue when vCPU is being destroyed
+    - sparc64: NMI watchdog: fix return value of __setup handler
+    - sparc: vDSO: fix return value of __setup handler
+    - crypto: qat - fix double free during reset
+    - crypto: qat - resolve race condition during AER recovery
+    - selftests/mqueue: Set timeout to 180 seconds
+    - ext4: correct best extent lstart adjustment logic
+    - fat: fix uninitialized field in nostale filehandles
+    - ubifs: Set page uptodate in the correct place
+    - ubi: Check for too small LEB size in VTBL code
+    - ubi: correct the calculation of fastmap size
+    - mtd: rawnand: meson: fix scrambling mode value in command macro
+    - parisc: Do not hardcode registers in checksum functions
+    - parisc: Fix ip_fast_csum
+    - parisc: Fix csum_ipv6_magic on 32-bit systems
+    - parisc: Fix csum_ipv6_magic on 64-bit systems
+    - parisc: Strip upper 32 bit of sum in csum_ipv6_magic for 64-bit builds
+    - PM: suspend: Set mem_sleep_current during kernel command line setup
+    - clk: qcom: gcc-ipq8074: fix terminating of frequency table arrays
+    - clk: qcom: mmcc-apq8084: fix terminating of frequency table arrays
+    - clk: qcom: mmcc-msm8974: fix terminating of frequency table arrays
+    - powerpc/fsl: Fix mfpmr build errors with newer binutils
+    - USB: serial: ftdi_sio: add support for GMC Z216C Adapter IR-USB
+    - USB: serial: add device ID for VeriFone adapter
+    - USB: serial: cp210x: add ID for MGP Instruments PDS100
+    - USB: serial: option: add MeiG Smart SLM320 product
+    - USB: serial: cp210x: add pid/vid for TDK NC0110013M and MM0110113M
+    - PM: sleep: wakeirq: fix wake irq warning in system suspend
+    - mmc: tmio: avoid concurrent runs of mmc_request_done()
+    - fuse: don't unhash root
+    - btrfs: fix off-by-one chunk length calculation at contains_pending_extent()
+    - PCI: Drop pci_device_remove() test of pci_dev->driver
+    - PCI/PM: Drain runtime-idle callbacks before driver removal
+    - Revert "Revert "md/raid5: Wait for MD_SB_CHANGE_PENDING in raid5d""
+    - dm-raid: fix lockdep waring in "pers->hot_add_disk"
+    - mmc: core: Fix switch on gp3 partition
+    - hwmon: (amc6821) add of_match table
+    - ext4: fix corruption during on-line resize
+    - firmware: meson_sm: Rework driver as a proper platform driver
+    - nvmem: meson-efuse: fix function pointer type mismatch
+    - slimbus: core: Remove usage of the deprecated ida_simple_xx() API
+    - speakup: Fix 8bit characters from direct synth
+    - kbuild: Move -Wenum-{compare-conditional,enum-conversion} into W=1
+    - vfio/platform: Disable virqfds on cleanup
+    - ring-buffer: Fix resetting of shortest_full
+    - ring-buffer: Fix full_waiters_pending in poll
+    - soc: fsl: qbman: Always disable interrupts when taking cgr_lock
+    - soc: fsl: qbman: Add helper for sanity checking cgr ops
+    - soc: fsl: qbman: Add CGR update function
+    - soc: fsl: qbman: Use raw spinlock for cgr_lock
+    - s390/zcrypt: fix reference counting on zcrypt card objects
+    - drm/exynos: do not return negative values from .get_modes()
+    - drm/imx/ipuv3: do not return negative values from .get_modes()
+    - drm/vc4: hdmi: do not return negative values from .get_modes()
+    - memtest: use {READ,WRITE}_ONCE in memory scanning
+    - nilfs2: fix failure to detect DAT corruption in btree and direct mappings
+    - nilfs2: use a more common logging style
+    - nilfs2: prevent kernel bug at submit_bh_wbc()
+    - x86/CPU/AMD: Update the Zenbleed microcode revisions
+    - ahci: asm1064: correct count of reported ports
+    - ahci: asm1064: asm1166: don't limit reported ports
+    - dm snapshot: fix lockup in dm_exception_table_exit
+    - comedi: comedi_test: Prevent timers rescheduling during deletion
+    - netfilter: nf_tables: reject constant set with timeout
+    - xfrm: Avoid clang fortify warning in copy_to_user_tmpl()
+    - ALSA: hda/realtek - Fix headset Mic no show at resume back for Lenovo ALC897
+      platform
+    - USB: usb-storage: Prevent divide-by-0 error in isd200_ata_command
+    - usb: gadget: ncm: Fix handling of zero block length packets
+    - usb: port: Don't try to peer unused USB ports based on location
+    - tty: serial: fsl_lpuart: avoid idle preamble pending if CTS is enabled
+    - vt: fix unicode buffer corruption when deleting characters
+    - fs/aio: Check IOCB_AIO_RW before the struct aio_kiocb conversion
+    - objtool: is_fentry_call() crashes if call has no destination
+    - objtool: Add support for intra-function calls
+    - x86/speculation: Support intra-function call validation
+    - xen/events: close evtchn after mapping cleanup
+    - printk: Update @console_may_schedule in console_trylock_spinning()
+    - btrfs: allocate btrfs_ioctl_defrag_range_args on stack
+    - Revert "loop: Check for overflow while configuring loop"
+    - loop: Call loop_config_discard() only after new config is applied
+    - loop: Remove sector_t truncation checks
+    - loop: Factor out setting loop device size
+    - loop: Refactor loop_set_status() size calculation
+    - loop: Factor out configuring loop from status
+    - loop: Check for overflow while configuring loop
+    - loop: loop_set_status_from_info() check before assignment
+    - perf/core: Fix reentry problem in perf_output_read_group()
+    - efivarfs: Request at most 512 bytes for variable names
+    - powerpc: xor_vmx: Add '-mhard-float' to CFLAGS
+    - bounds: support non-power-of-two CONFIG_NR_CPUS
+    - vt: fix memory overlapping when deleting chars in the buffer
+    - mm/memory-failure: fix an incorrect use of tail pages
+    - mm/migrate: set swap entry values of THP tail pages properly.
+    - wifi: mac80211: check/clear fast rx for non-4addr sta VLAN changes
+    - exec: Fix NOMMU linux_binprm::exec in transfer_args_to_stack()
+    - mmc: core: Initialize mmc_blk_ioc_data
+    - mmc: core: Avoid negative index with array access
+    - ALSA: sh: aica: reorder cleanup operations to avoid UAF bugs
+    - scsi: core: Fix unremoved procfs host directory regression
+    - usb: dwc2: host: Fix remote wakeup from hibernation
+    - usb: dwc2: host: Fix hibernation flow
+    - usb: dwc2: host: Fix ISOC flow in DDMA mode
+    - usb: dwc2: gadget: LPM flow fix
+    - usb: udc: remove warning when queue disabled ep
+    - scsi: qla2xxx: Fix command flush on cable pull
+    - x86/cpu: Enable STIBP on AMD if Automatic IBRS is enabled
+    - scsi: lpfc: Correct size for wqe for memset()
+    - USB: core: Fix deadlock in usb_deauthorize_interface()
+    - nfc: nci: Fix uninit-value in nci_dev_up and nci_ntf_packet
+    - ixgbe: avoid sleeping allocation in ixgbe_ipsec_vf_add_sa()
+    - tcp: properly terminate timers for kernel sockets
+    - dm integrity: fix out-of-range warning
+    - r8169: fix issue caused by buggy BIOS on certain boards with RTL8168d
+    - Bluetooth: hci_event: set the conn encrypted before conn establishes
+    - Bluetooth: Fix TOCTOU in HCI debugfs implementation
+    - netfilter: nf_tables: disallow timeout for anonymous sets
+    - net/rds: fix possible cp null dereference
+    - vfio/pci: Disable auto-enable of exclusive INTx IRQ
+    - vfio/pci: Lock external INTx masking ops
+    - vfio: Introduce interface to flush virqfd inject workqueue
+    - vfio/pci: Create persistent INTx handler
+    - vfio/platform: Create persistent IRQ handlers
+    - Revert "x86/mm/ident_map: Use gbpages only where full GB page should be
+      mapped."
+    - mm, vmscan: prevent infinite loop for costly GFP_NOIO | __GFP_RETRY_MAYFAIL
+      allocations
+    - netfilter: nf_tables: flush pending destroy work before exit_net release
+    - netfilter: nf_tables: Fix potential data-race in __nft_flowtable_type_get()
+    - bpf, sockmap: Prevent lock inversion deadlock in map delete elem
+    - net/sched: act_skbmod: prevent kernel-infoleak
+    - net: stmmac: fix rx queue priority assignment
+    - selftests: reuseaddr_conflict: add missing new line at the end of the output
+    - ipv6: Fix infinite recursion in fib6_dump_done().
+    - i40e: fix vf may be used uninitialized in this function warning
+    - staging: mmal-vchiq: Allocate and free components as required
+    - staging: mmal-vchiq: Fix client_component for 64 bit kernel
+    - staging: vc04_services: changen strncpy() to strscpy_pad()
+    - staging: vc04_services: fix information leak in create_component()
+    - fs: add a vfs_fchown helper
+    - fs: add a vfs_fchmod helper
+    - initramfs: switch initramfs unpacking to struct file based APIs
+    - init: open /initrd.image with O_LARGEFILE
+    - erspan: Add type I version 0 support.
+    - erspan: make sure erspan_base_hdr is present in skb->head
+    - net: ravb: Always process TX descriptor ring
+    - ASoC: ops: Fix wraparound for mask in snd_soc_get_volsw
+    - ata: sata_sx4: fix pdc20621_get_from_dimm() on 64-bit
+    - scsi: mylex: Fix sysfs buffer lengths
+    - ata: sata_mv: Fix PCI device ID table declaration compilation warning
+    - ALSA: hda/realtek: Update Panasonic CF-SZ6 quirk to support headset with
+      microphone
+    - x86/mce: Make sure to grab mce_sysfs_mutex in set_bank()
+    - s390/entry: align system call table on 8 bytes
+    - wifi: ath9k: fix LNA selection in ath_ant_try_scan()
+    - VMCI: Fix memcpy() run-time warning in dg_dispatch_as_host()
+    - panic: Flush kernel log buffer at the end
+    - arm64: dts: rockchip: fix rk3328 hdmi ports node
+    - arm64: dts: rockchip: fix rk3399 hdmi ports node
+    - ionic: set adminq irq affinity
+    - tools/power x86_energy_perf_policy: Fix file leak in get_pkg_num()
+    - btrfs: handle chunk tree lookup error in btrfs_relocate_sys_chunks()
+    - btrfs: export: handle invalid inode or root reference in btrfs_get_parent()
+    - btrfs: send: handle path ref underflow in header iterate_inode_ref()
+    - Bluetooth: btintel: Fix null ptr deref in btintel_read_version
+    - Input: synaptics-rmi4 - fail probing if memory allocation for "phys" fails
+    - sysv: don't call sb_bread() with pointers_lock held
+    - scsi: lpfc: Fix possible memory leak in lpfc_rcv_padisc()
+    - isofs: handle CDs with bad root inode but good Joliet root directory
+    - media: sta2x11: fix irq handler cast
+    - drm/amd/display: Fix nanosec stat overflow
+    - SUNRPC: increase size of rpc_wait_queue.qlen from unsigned short to unsigned
+      int
+    - Revert "ACPI: PM: Block ASUS B1400CEAE from suspend to idle by default"
+    - block: prevent division by zero in blk_rq_stat_sum()
+    - Input: allocate keycode for Display refresh rate toggle
+    - ktest: force $buildonly = 1 for 'make_warnings_file' test type
+    - tools: iio: replace seekdir() in iio_generic_buffer
+    - usb: typec: tcpci: add generic tcpci fallback compatible
+    - usb: sl811-hcd: only defined function checkdone if QUIRK2 is defined
+    - fbdev: viafb: fix typo in hw_bitblt_1 and hw_bitblt_2
+    - fbmon: prevent division by zero in fb_videomode_from_videomode()
+    - netfilter: nf_tables: reject new basechain after table flag update
+    - netfilter: nf_tables: discard table flag update with pending basechain
+      deletion
+    - tty: n_gsm: require CAP_NET_ADMIN to attach N_GSM0710 ldisc
+    - drm/vkms: call drm_atomic_helper_shutdown before drm_dev_put()
+    - virtio: reenable config if freezing device failed
+    - x86/mm/pat: fix VM_PAT handling in COW mappings
+    - drm/i915/gt: Reset queue_priority_hint on parking
+    - x86/alternative: Don't call text_poke() in lazy TLB mode
+    - Bluetooth: btintel: Fixe build regression
+    - VMCI: Fix possible memcpy() run-time warning in
+      vmci_datagram_invoke_guest_handler()
+    - erspan: Check IFLA_GRE_ERSPAN_VER is set.
+    - ip_gre: do not report erspan version on GRE interface
+    - firmware: meson_sm: fix to avoid potential NULL pointer dereference
+    - Linux 5.4.274
+  * CVE-2024-26586
+    - mlxsw: spectrum_acl_tcam: Fix stack corruption
+  * CVE-2024-26923
+    - af_unix: Do not use atomic ops for unix_sk(sk)->inflight.
+    - af_unix: Fix garbage collector racing against connect()
+  * Focal update: v5.4.273 upstream stable release (LP: #2064561)
+    - io_uring/unix: drop usage of io_uring socket
+    - io_uring: drop any code related to SCM_RIGHTS
+    - selftests: tls: use exact comparison in recv_partial
+    - ASoC: rt5645: Make LattePanda board DMI match more precise
+    - x86/xen: Add some null pointer checking to smp.c
+    - MIPS: Clear Cause.BD in instruction_pointer_set
+    - HID: multitouch: Add required quirk for Synaptics 0xcddc device
+    - RDMA/mlx5: Relax DEVX access upon modify commands
+    - net/iucv: fix the allocation size of iucv_path_table array
+    - parisc/ftrace: add missing CONFIG_DYNAMIC_FTRACE check
+    - block: sed-opal: handle empty atoms when parsing response
+    - dm-verity, dm-crypt: align "struct bvec_iter" correctly
+    - btrfs: fix data race at btrfs_use_block_rsv() when accessing block reserve
+    - scsi: mpt3sas: Prevent sending diag_reset when the controller is ready
+    - Bluetooth: rfcomm: Fix null-ptr-deref in rfcomm_check_security
+    - firewire: core: use long bus reset on gap count error
+    - ASoC: Intel: bytcr_rt5640: Add an extra entry for the Chuwi Vi8 tablet
+    - Input: gpio_keys_polled - suppress deferred probe error for gpio
+    - ASoC: wm8962: Enable oscillator if selecting WM8962_FLL_OSC
+    - ASoC: wm8962: Enable both SPKOUTR_ENA and SPKOUTL_ENA in mono mode
+    - ASoC: wm8962: Fix up incorrect error message in wm8962_set_fll
+    - do_sys_name_to_handle(): use kzalloc() to fix kernel-infoleak
+    - fs/select: rework stack allocation hack for clang
+    - timekeeping: Fix cross-timestamp interpolation on counter wrap
+    - timekeeping: Fix cross-timestamp interpolation corner case decision
+    - timekeeping: Fix cross-timestamp interpolation for non-x86
+    - wifi: ath10k: fix NULL pointer dereference in
+      ath10k_wmi_tlv_op_pull_mgmt_tx_compl_ev()
+    - b43: dma: Fix use true/false for bool type variable
+    - wifi: b43: Stop/wake correct queue in DMA Tx path when QoS is disabled
+    - wifi: b43: Stop/wake correct queue in PIO Tx path when QoS is disabled
+    - b43: main: Fix use true/false for bool type
+    - wifi: b43: Stop correct queue in DMA worker when QoS is disabled
+    - wifi: b43: Disable QoS for bcm4331
+    - wifi: wilc1000: fix declarations ordering
+    - wifi: wilc1000: fix RCU usage in connect path
+    - wifi: mwifiex: debugfs: Drop unnecessary error check for
+      debugfs_create_dir()
+    - sock_diag: annotate data-races around sock_diag_handlers[family]
+    - af_unix: Annotate data-race of gc_in_progress in wait_for_unix_gc().
+    - net: blackhole_dev: fix build warning for ethh set but not used
+    - wifi: libertas: fix some memleaks in lbs_allocate_cmd_buffer()
+    - arm64: dts: mediatek: mt7622: add missing "device_type" to memory nodes
+    - bpf: Add typecast to bpf helpers to help BTF generation
+    - bpf: Factor out bpf_spin_lock into helpers.
+    - bpf: Mark bpf_spin_{lock,unlock}() helpers with notrace correctly
+    - arm64: dts: qcom: db820c: Move non-soc entries out of /soc
+    - arm64: dts: qcom: msm8996: Use node references in db820c
+    - arm64: dts: qcom: msm8996: Move regulator consumers to db820c
+    - arm64: dts: qcom: msm8996: Pad addresses
+    - ACPI: processor_idle: Fix memory leak in acpi_processor_power_exit()
+    - bus: tegra-aconnect: Update dependency to ARCH_TEGRA
+    - [Config]: Update tegra configs
+    - iommu/amd: Mark interrupt as managed
+    - wifi: brcmsmac: avoid function pointer casts
+    - net: ena: Remove ena_select_queue
+    - ARM: dts: arm: realview: Fix development chip ROM compatible value
+    - ARM: dts: imx6dl-yapp4: Move phy reset into switch node
+    - ARM: dts: imx6dl-yapp4: Fix typo in the QCA switch register address
+    - ARM: dts: imx6dl-yapp4: Move the internal switch PHYs under the switch node
+    - ACPI: scan: Fix device check notification handling
+    - x86, relocs: Ignore relocations in .notes section
+    - SUNRPC: fix some memleaks in gssx_dec_option_array
+    - mmc: wmt-sdmmc: remove an incorrect release_mem_region() call in the .remove
+      function
+    - igb: move PEROUT and EXTTS isr logic to separate functions
+    - igb: Fix missing time sync events
+    - Bluetooth: Remove superfluous call to hci_conn_check_pending()
+    - sr9800: Add check for usbnet_get_endpoints
+    - bpf: Fix hashtab overflow check on 32-bit arches
+    - bpf: Fix stackmap overflow check on 32-bit arches
+    - ipv6: fib6_rules: flush route cache when rule is changed
+    - net: ip_tunnel: make sure to pull inner header in ip_tunnel_rcv()
+    - net: hns3: fix port duplex configure error in IMP reset
+    - tcp: fix incorrect parameter validation in the do_tcp_getsockopt() function
+    - l2tp: fix incorrect parameter validation in the pppol2tp_getsockopt()
+      function
+    - udp: fix incorrect parameter validation in the udp_lib_getsockopt() function
+    - net: kcm: fix incorrect parameter validation in the kcm_getsockopt) function
+    - net/x25: fix incorrect parameter validation in the x25_getsockopt() function
+    - nfp: flower: handle acti_netdevs allocation failure
+    - dm raid: fix false positive for requeue needed during reshape
+    - dm: call the resume method on internal suspend
+    - drm/tegra: dsi: Add missing check for of_find_device_by_node
+    - gpu: host1x: mipi: Update tegra_mipi_request() to be node based
+    - drm/tegra: dsi: Make use of the helper function dev_err_probe()
+    - drm/tegra: dsi: Fix some error handling paths in tegra_dsi_probe()
+    - drm/tegra: dsi: Fix missing pm_runtime_disable() in the error handling path
+      of tegra_dsi_probe()
+    - drm/tegra: output: Fix missing i2c_put_adapter() in the error handling paths
+      of tegra_output_probe()
+    - drm/rockchip: inno_hdmi: Fix video timing
+    - drm: Don't treat 0 as -1 in drm_fixp2int_ceil
+    - drm/rockchip: lvds: do not overwrite error code
+    - dmaengine: tegra210-adma: Update dependency to ARCH_TEGRA
+    - media: tc358743: register v4l2 async device only after successful setup
+    - PCI/DPC: Print all TLP Prefixes, not just the first
+    - perf record: Fix possible incorrect free in record__switch_output()
+    - drm/amd/display: Fix potential NULL pointer dereferences in
+      'dcn10_set_output_transfer_func()'
+    - perf evsel: Fix duplicate initialization of data->id in
+      evsel__parse_sample()
+    - media: em28xx: annotate unchecked call to media_device_register()
+    - media: v4l2-tpg: fix some memleaks in tpg_alloc
+    - media: v4l2-mem2mem: fix a memleak in v4l2_m2m_register_entity
+    - media: edia: dvbdev: fix a use-after-free
+    - clk: qcom: reset: Allow specifying custom reset delay
+    - clk: qcom: reset: support resetting multiple bits
+    - clk: qcom: reset: Commonize the de/assert functions
+    - clk: qcom: reset: Ensure write completion on reset de/assertion
+    - quota: simplify drop_dquot_ref()
+    - quota: Fix potential NULL pointer dereference
+    - quota: Fix rcu annotations of inode dquot pointers
+    - PCI: switchtec: Fix an error handling path in switchtec_pci_probe()
+    - perf thread_map: Free strlist on normal path in thread_map__new_by_tid_str()
+    - drm/radeon/ni: Fix wrong firmware size logging in ni_init_microcode()
+    - ALSA: seq: fix function cast warnings
+    - perf stat: Avoid metric-only segv
+    - media: imx: csc/scaler: fix v4l2_ctrl_handler memory leak
+    - media: go7007: add check of return value of go7007_read_addr()
+    - media: pvrusb2: remove redundant NULL check
+    - media: pvrusb2: fix pvr2_stream_callback casts
+    - clk: qcom: dispcc-sdm845: Adjust internal GDSC wait times
+    - drm/mediatek: dsi: Fix DSI RGB666 formats and definitions
+    - PCI: Mark 3ware-9650SE Root Port Extended Tags as broken
+    - clk: hisilicon: hi3519: Release the correct number of gates in
+      hi3519_clk_unregister()
+    - drm/tegra: put drm_gem_object ref on error in tegra_fb_create
+    - mfd: syscon: Call of_node_put() only when of_parse_phandle() takes a ref
+    - mfd: altera-sysmgr: Call of_node_put() only when of_parse_phandle() takes a
+      ref
+    - crypto: arm/sha - fix function cast warnings
+    - mtd: maps: physmap-core: fix flash size larger than 32-bit
+    - mtd: rawnand: lpc32xx_mlc: fix irq handler prototype
+    - ASoC: meson: axg-tdm-interface: fix mclk setup without mclk-fs
+    - drm/amdgpu: Fix missing break in ATOM_ARG_IMM Case of atom_get_src_int()
+    - media: pvrusb2: fix uaf in pvr2_context_set_notify
+    - media: dvb-frontends: avoid stack overflow warnings with clang
+    - media: go7007: fix a memleak in go7007_load_encoder
+    - media: v4l2-core: correctly validate video and metadata ioctls
+    - media: rename VFL_TYPE_GRABBER to _VIDEO
+    - media: media/pci: rename VFL_TYPE_GRABBER to _VIDEO
+    - media: ttpci: fix two memleaks in budget_av_attach
+    - drm/mediatek: Fix a null pointer crash in mtk_drm_crtc_finish_page_flip
+    - powerpc/hv-gpci: Fix the H_GET_PERF_COUNTER_INFO hcall return value checks
+    - drm/msm/dpu: add division of drm_display_mode's hskew parameter
+    - powerpc/embedded6xx: Fix no previous prototype for avr_uart_send() etc.
+    - backlight: lm3630a: Initialize backlight_properties on init
+    - backlight: lm3630a: Don't set bl->props.brightness in get_brightness
+    - backlight: da9052: Fully initialize backlight_properties during probe
+    - backlight: lm3639: Fully initialize backlight_properties during probe
+    - backlight: lp8788: Fully initialize backlight_properties during probe
+    - sparc32: Fix section mismatch in leon_pci_grpci
+    - clk: Fix clk_core_get NULL dereference
+    - ALSA: usb-audio: Stop parsing channels bits when all channels are found.
+    - scsi: csiostor: Avoid function pointer casts
+    - RDMA/device: Fix a race between mad_client and cm_client init
+    - scsi: bfa: Fix function pointer type mismatch for hcb_qe->cbfn
+    - net: sunrpc: Fix an off by one in rpc_sockaddr2uaddr()
+    - watchdog: stm32_iwdg: initialize default timeout
+    - NFS: Fix an off by one in root_nfs_cat()
+    - afs: Revert "afs: Hide silly-rename files from userspace"
+    - tty: vt: fix 20 vs 0x20 typo in EScsiignore
+    - serial: max310x: fix syntax error in IRQ error message
+    - tty: serial: samsung: fix tx_empty() to return TIOCSER_TEMT
+    - kconfig: fix infinite loop when expanding a macro at the end of file
+    - rtc: mt6397: select IRQ_DOMAIN instead of depending on it
+    - serial: 8250_exar: Don't remove GPIO device on suspend
+    - staging: greybus: fix get_channel_from_mode() failure path
+    - usb: gadget: net2272: Use irqflags in the call to net2272_probe_fin
+    - octeontx2-af: Use matching wake_up API variant in CGX command interface
+    - s390/vtime: fix average steal time calculation
+    - hsr: Fix uninit-value access in hsr_get_node()
+    - packet: annotate data-races around ignore_outgoing
+    - rds: introduce acquire/release ordering in acquire/release_in_xmit()
+    - hsr: Handle failures in module init
+    - net/bnx2x: Prevent access to a freed page in page_pool
+    - octeontx2-af: Use separate handlers for interrupts
+    - ARM: dts: sun8i-h2-plus-bananapi-m2-zero: add regulator nodes vcc-dram and
+      vcc1v2
+    - netfilter: nf_tables: do not compare internal table flags on updates
+    - rcu: add a helper to report consolidated flavor QS
+    - bpf: report RCU QS in cpumap kthread
+    - spi: spi-mt65xx: Fix NULL pointer access in interrupt handler
+    - regmap: Add missing map->bus check
+    - Linux 5.4.273
+  * Focal update: v5.4.272 upstream stable release (LP: #2064555)
+    - lan78xx: Fix white space and style issues
+    - lan78xx: Add missing return code checks
+    - lan78xx: Fix partial packet errors on suspend/resume
+    - lan78xx: Fix race conditions in suspend/resume handling
+    - net: lan78xx: fix runtime PM count underflow on link stop
+    - ixgbe: {dis, en}able irqs in ixgbe_txrx_ring_{dis, en}able
+    - geneve: make sure to pull inner header in geneve_rx()
+    - net: ice: Fix potential NULL pointer dereference in ice_bridge_setlink()
+    - net/ipv6: avoid possible UAF in ip6_route_mpath_notify()
+    - net/rds: fix WARNING in rds_conn_connect_if_down
+    - netfilter: nft_ct: fix l3num expectations with inet pseudo family
+    - netfilter: nf_conntrack_h323: Add protection for bmp length out of range
+    - netrom: Fix a data-race around sysctl_netrom_default_path_quality
+    - netrom: Fix a data-race around sysctl_netrom_obsolescence_count_initialiser
+    - netrom: Fix data-races around sysctl_netrom_network_ttl_initialiser
+    - netrom: Fix a data-race around sysctl_netrom_transport_timeout
+    - netrom: Fix a data-race around sysctl_netrom_transport_maximum_tries
+    - netrom: Fix a data-race around sysctl_netrom_transport_acknowledge_delay
+    - netrom: Fix a data-race around sysctl_netrom_transport_busy_delay
+    - netrom: Fix a data-race around sysctl_netrom_transport_requested_window_size
+    - netrom: Fix a data-race around sysctl_netrom_transport_no_activity_timeout
+    - netrom: Fix a data-race around sysctl_netrom_routing_control
+    - netrom: Fix a data-race around sysctl_netrom_link_fails_count
+    - netrom: Fix data-races around sysctl_net_busy_read
+    - selftests: mm: fix map_hugetlb failure on 64K page size systems
+    - um: allow not setting extra rpaths in the linux binary
+    - serial: max310x: Use devm_clk_get_optional() to get the input clock
+    - serial: max310x: Try to get crystal clock rate from property
+    - serial: max310x: fail probe if clock crystal is unstable
+    - serial: max310x: Make use of device properties
+    - serial: max310x: use regmap methods for SPI batch operations
+    - serial: max310x: use a separate regmap for each port
+    - serial: max310x: prevent infinite while() loop in port startup
+    - Input: i8042 - fix strange behavior of touchpad on Clevo NS70PU
+    - hv_netvsc: Make netvsc/VF binding check both MAC and serial number
+    - hv_netvsc: use netif_is_bond_master() instead of open code
+    - hv_netvsc: Register VF in netvsc_probe if NET_DEVICE_REGISTER missed
+    - y2038: rusage: use __kernel_old_timeval
+    - getrusage: add the "signal_struct *sig" local variable
+    - getrusage: move thread_group_cputime_adjusted() outside of
+      lock_task_sighand()
+    - getrusage: use __for_each_thread()
+    - getrusage: use sig->stats_lock rather than lock_task_sighand()
+    - serial: max310x: Unprepare and disable clock in error path
+    - regmap: allow to define reg_update_bits for no bus configuration
+    - regmap: Add bulk read/write callbacks into regmap_config
+    - serial: max310x: make accessing revision id interface-agnostic
+    - serial: max310x: implement I2C support
+    - serial: max310x: fix IO data corruption in batched operations
+    - arm64: dts: qcom: add PDC interrupt controller for SDM845
+    - arm64: dts: qcom: sdm845: fix USB DP/DM HS PHY interrupts
+    - Linux 5.4.272
+  * CVE-2024-23307
+    - md/raid5: fix atomicity violation in raid5_cache_count
+  * CVE-2024-26889
+    - Bluetooth: hci_core: Fix possible buffer overflow
+  * CVE-2024-26828
+    - cifs: fix underflow in parse_server_interfaces()
+  * CVE-2024-24861
+    - media: xc4000: Fix atomicity violation in xc4000_get_frequency
+  * CVE-2023-6270
+    - aoe: fix the potential use-after-free problem in aoecmd_cfg_pkts
+  * CVE-2024-26642
+    - netfilter: nf_tables: disallow anonymous set with timeout flag
+  * CVE-2024-26926
+    - binder: check offset alignment in binder_get_object()
+  * CVE-2024-26922
+    - drm/amdgpu: validate the parameters of bo mapping operations more clearly
+  * CVE-2024-26925
+    - netfilter: Cleanup nft_net->module_list from nf_tables_exit_net()
+    - netfilter: nf_tables: release batch on table validation from abort path
+    - netfilter: nf_tables: release mutex after nft_gc_seq_end from abort path
+  * CVE-2024-26643
+    - netfilter: nf_tables: mark set as dead when unbinding anonymous set with
+      timeout
+  * CVE-2024-2201
+    - x86/cpufeatures: Add new word for scattered features
+    - x86/cpufeatures: Add CPUID_LNX_5 to track recently added Linux-defined word
+    - x86/bugs: Change commas to semicolons in 'spectre_v2' sysfs file
+    - x86/bhi: Add support for clearing branch history at syscall entry
+    - x86/bhi: Define SPEC_CTRL_BHI_DIS_S
+    - x86/bhi: Enumerate Branch History Injection (BHI) bug
+    - x86/bhi: Add BHI mitigation knob
+    - x86/bhi: Mitigate KVM by default
+    - [Config] updateconfigs for CONFIG_BHI_{AUTO|ON|OFF}
+    - x86/bugs: Fix BHI documentation
+    - x86/bugs: Cache the value of MSR_IA32_ARCH_CAPABILITIES
+    - x86/bugs: Rename various 'ia32_cap' variables to 'x86_arch_cap_msr'
+    - x86/bugs: Fix BHI handling of RRSBA
+    - x86/bugs: Clarify that syscall hardening isn't a BHI mitigation
+    - x86/bugs: Fix BHI retpoline check
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Tue, 18 Jun 2024 08:47:37 +1000
+
+linux-xilinx-zynqmp (5.4.0-1046.50) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1046.50 -proposed tracker (LP: #2068289)
+
+  [ Ubuntu: 5.4.0-187.207 ]
+
+  * focal/linux: 5.4.0-187.207 -proposed tracker (LP: #2068291)
+  * CVE-2024-26925
+    - netfilter: Cleanup nft_net->module_list from nf_tables_exit_net()
+    - netfilter: nf_tables: release batch on table validation from abort path
+    - netfilter: nf_tables: release mutex after nft_gc_seq_end from abort path
+  * CVE-2024-26643
+    - netfilter: nf_tables: mark set as dead when unbinding anonymous set with
+      timeout
+  * CVE-2024-2201
+    - x86/cpufeatures: Add new word for scattered features
+    - x86/cpufeatures: Add CPUID_LNX_5 to track recently added Linux-defined word
+    - x86/bugs: Change commas to semicolons in 'spectre_v2' sysfs file
+    - x86/bhi: Add support for clearing branch history at syscall entry
+    - x86/bhi: Define SPEC_CTRL_BHI_DIS_S
+    - x86/bhi: Enumerate Branch History Injection (BHI) bug
+    - x86/bhi: Add BHI mitigation knob
+    - x86/bhi: Mitigate KVM by default
+    - [Config] updateconfigs for CONFIG_BHI_{AUTO|ON|OFF}
+    - x86/bugs: Fix BHI documentation
+    - x86/bugs: Cache the value of MSR_IA32_ARCH_CAPABILITIES
+    - x86/bugs: Rename various 'ia32_cap' variables to 'x86_arch_cap_msr'
+    - x86/bugs: Fix BHI handling of RRSBA
+    - x86/bugs: Clarify that syscall hardening isn't a BHI mitigation
+    - x86/bugs: Fix BHI retpoline check
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Fri, 14 Jun 2024 08:41:35 +1000
+
+linux-xilinx-zynqmp (5.4.0-1045.49) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1045.49 -proposed tracker (LP: #2063809)
+
+  [ Ubuntu: 5.4.0-186.206 ]
+
+  * focal/linux: 5.4.0-186.206 -proposed tracker (LP: #2063812)
+  * Mount CIFS fails with Permission denied (LP: #2061986)
+    - cifs: fix ntlmssp auth when there is no key exchange
+  * USB stick can't be detected (LP: #2040948)
+    - usb: Disable USB3 LPM at shutdown
+  * CVE-2024-26733
+    - net: dev: Convert sa_data to flexible array in struct sockaddr
+    - arp: Prevent overflow in arp_req_get().
+    - stddef: Introduce DECLARE_FLEX_ARRAY() helper
+  * CVE-2024-26712
+    - powerpc/kasan: Fix addr error caused by page alignment
+  * CVE-2023-52530
+    - wifi: mac80211: fix potential key use-after-free
+  * CVE-2021-47063
+    - drm: bridge/panel: Cleanup connector on bridge detach
+  * [Ubuntu 22.04.4/linux-image-6.5.0-26-generic] Kernel output "UBSAN: array-
+    index-out-of-bounds in /build/linux-hwe-6.5-34pCLi/linux-
+    hwe-6.5-6.5.0/drivers/net/hyperv/netvsc.c:1445:41" multiple times,
+    especially during boot. (LP: #2058477)
+    - hv: hyperv.h: Replace one-element array with flexible-array member
+  * CVE-2024-26614
+    - tcp: make sure init the accept_queue's spinlocks once
+    - ipv6: init the accept_queue's spinlocks in inet6_create
+  * Focal update: v5.4.271 upstream stable release (LP: #2060216)
+    - netlink: Fix kernel-infoleak-after-free in __skb_datagram_iter
+    - net: ip_tunnel: prevent perpetual headroom growth
+    - tun: Fix xdp_rxq_info's queue_index when detaching
+    - ipv6: fix potential "struct net" leak in inet6_rtm_getaddr()
+    - lan78xx: enable auto speed configuration for LAN7850 if no EEPROM is
+      detected
+    - net: usb: dm9601: fix wrong return value in dm9601_mdio_read
+    - Bluetooth: Avoid potential use-after-free in hci_error_reset
+    - Bluetooth: hci_event: Fix handling of HCI_EV_IO_CAPA_REQUEST
+    - Bluetooth: Enforce validation on max value of connection interval
+    - netfilter: nf_tables: allow NFPROTO_INET in nft_(match/target)_validate()
+    - rtnetlink: fix error logic of IFLA_BRIDGE_FLAGS writing back
+    - efi/capsule-loader: fix incorrect allocation size
+    - power: supply: bq27xxx-i2c: Do not free non existing IRQ
+    - ALSA: Drop leftover snd-rtctimer stuff from Makefile
+    - afs: Fix endless loop in directory parsing
+    - gtp: fix use-after-free and null-ptr-deref in gtp_newlink()
+    - wifi: nl80211: reject iftype change with mesh ID change
+    - btrfs: dev-replace: properly validate device names
+    - dmaengine: fsl-qdma: fix SoC may hang on 16 byte unaligned read
+    - dmaengine: fsl-qdma: init irq after reg initialization
+    - mmc: core: Fix eMMC initialization with 1-bit bus connection
+    - x86/cpu/intel: Detect TME keyid bits before setting MTRR mask registers
+    - cachefiles: fix memory leak in cachefiles_add_cache()
+    - fs,hugetlb: fix NULL pointer dereference in hugetlbs_fill_super
+    - gpio: 74x164: Enable output pins after registers are reset
+    - Linux 5.4.271
+  * Focal update: v5.4.270 upstream stable release (LP: #2060019)
+    - KVM: arm64: vgic-its: Test for valid IRQ in its_sync_lpi_pending_table()
+    - KVM: arm64: vgic-its: Test for valid IRQ in MOVALL handler
+    - net/sched: Retire CBQ qdisc
+    - [Config] updateconfigs for NET_SCH_CBQ
+    - net/sched: Retire ATM qdisc
+    - [Config] updateconfigs for NET_SCH_ATM
+    - net/sched: Retire dsmark qdisc
+    - [Config] updateconfigs for NET_SCH_DSMARK
+    - sched/rt: sysctl_sched_rr_timeslice show default timeslice after reset
+    - memcg: add refcnt for pcpu stock to avoid UAF problem in drain_all_stock()
+    - nilfs2: replace WARN_ONs for invalid DAT metadata block requests
+    - userfaultfd: fix mmap_changing checking in mfill_atomic_hugetlb
+    - sched/rt: Fix sysctl_sched_rr_timeslice intial value
+    - sched/rt: Disallow writing invalid values to sched_rt_period_us
+    - scsi: target: core: Add TMF to tmr_list handling
+    - dmaengine: shdma: increase size of 'dev_id'
+    - dmaengine: fsl-qdma: increase size of 'irq_name'
+    - wifi: cfg80211: fix missing interfaces when dumping
+    - wifi: mac80211: fix race condition on enabling fast-xmit
+    - fbdev: savage: Error out if pixclock equals zero
+    - fbdev: sis: Error out if pixclock equals zero
+    - ahci: asm1166: correct count of reported ports
+    - ahci: add 43-bit DMA address quirk for ASMedia ASM1061 controllers
+    - ext4: avoid allocating blocks from corrupted group in
+      ext4_mb_try_best_found()
+    - ext4: avoid allocating blocks from corrupted group in ext4_mb_find_by_goal()
+    - regulator: pwm-regulator: Add validity checks in continuous .get_voltage
+    - nvmet-tcp: fix nvme tcp ida memory leak
+    - ASoC: sunxi: sun4i-spdif: Add support for Allwinner H616
+    - netfilter: conntrack: check SCTP_CID_SHUTDOWN_ACK for vtag setting in
+      sctp_new
+    - nvmet-fc: abort command when there is no binding
+    - hwmon: (coretemp) Enlarge per package core count limit
+    - scsi: lpfc: Use unsigned type for num_sge
+    - firewire: core: send bus reset promptly on gap count error
+    - virtio-blk: Ensure no requests in virtqueues before deleting vqs.
+    - s390/qeth: Fix potential loss of L3-IP@ in case of network issues
+    - pmdomain: renesas: r8a77980-sysc: CR7 must be always on
+    - tcp: factor out __tcp_close() helper
+    - tcp: return EPOLLOUT from tcp_poll only when notsent_bytes is half the limit
+    - tcp: add annotations around sk->sk_shutdown accesses
+    - pinctrl: pinctrl-rockchip: Fix a bunch of kerneldoc misdemeanours
+    - pinctrl: rockchip: Fix refcount leak in rockchip_pinctrl_parse_groups
+    - spi: mt7621: Fix an error message in mt7621_spi_probe()
+    - net: bridge: clear bridge's private skb space on xmit
+    - selftests/bpf: Avoid running unprivileged tests with alignment requirements
+    - Revert "drm/sun4i: dsi: Change the start delay calculation"
+    - drm/amdgpu: Check for valid number of registers to read
+    - x86/alternatives: Disable KASAN in apply_alternatives()
+    - dm-integrity: don't modify bio's immutable bio_vec in integrity_metadata()
+    - iomap: Set all uptodate bits for an Uptodate page
+    - drm/amdgpu: Fix type of second parameter in trans_msg() callback
+    - arm64: dts: qcom: msm8916: Fix typo in pronto remoteproc node
+    - PCI: tegra: Fix reporting GPIO error value
+    - PCI: tegra: Fix OF node reference leak
+    - IB/hfi1: Fix sdma.h tx->num_descs off-by-one error
+    - dm-crypt: don't modify the data when using authenticated encryption
+    - gtp: fix use-after-free and null-ptr-deref in gtp_genl_dump_pdp()
+    - PCI/MSI: Prevent MSI hardware interrupt number truncation
+    - l2tp: pass correct message length to ip6_append_data
+    - ARM: ep93xx: Add terminator to gpiod_lookup_table
+    - usb: cdns3: fixed memory use after free at cdns3_gadget_ep_disable()
+    - usb: cdns3: fix memory double free when handle zero packet
+    - usb: gadget: ncm: Avoid dropping datagrams of properly parsed NTBs
+    - usb: roles: don't get/set_role() when usb_role_switch is unregistered
+    - IB/hfi1: Fix a memleak in init_credit_return
+    - RDMA/bnxt_re: Return error for SRQ resize
+    - RDMA/srpt: Make debug output more detailed
+    - RDMA/srpt: fix function pointer cast warnings
+    - scripts/bpf: teach bpf_helpers_doc.py to dump BPF helper definitions
+    - bpf, scripts: Correct GPL license name
+    - scsi: jazz_esp: Only build if SCSI core is builtin
+    - nouveau: fix function cast warnings
+    - ipv4: properly combine dev_base_seq and ipv4.dev_addr_genid
+    - ipv6: properly combine dev_base_seq and ipv6.dev_addr_genid
+    - afs: Increase buffer size in afs_update_volume_status()
+    - ipv6: sr: fix possible use-after-free and null-ptr-deref
+    - packet: move from strlcpy with unused retval to strscpy
+    - s390: use the correct count for __iowrite64_copy()
+    - tls: rx: jump to a more appropriate label
+    - tls: rx: drop pointless else after goto
+    - tls: stop recv() if initial process_rx_list gave us non-DATA
+    - netfilter: nf_tables: set dormant flag on hook register failure
+    - drm/syncobj: make lockdep complain on WAIT_FOR_SUBMIT v3
+    - drm/syncobj: call drm_syncobj_fence_add_wait when WAIT_AVAILABLE flag is set
+    - fs/aio: Restrict kiocb_set_cancel_fn() to I/O submitted via libaio
+    - scripts/bpf: Fix xdp_md forward declaration typo
+    - Linux 5.4.270
+  * CVE-2023-47233
+    - wifi: brcmfmac: Fix use-after-free bug in brcmf_cfg80211_detach
+  * CVE-2021-47070
+    - uio: uio_hv_generic: use devm_kzalloc() for private data alloc
+    - uio_hv_generic: Fix another memory leak in error handling paths
+  * CVE-2024-26622
+    - tomoyo: fix UAF write bug in tomoyo_write_control()
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Tue, 21 May 2024 12:47:20 +1000
+
+linux-xilinx-zynqmp (5.4.0-1044.48) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1044.48 -proposed tracker (LP: #2063683)
+
+  [ Ubuntu: 5.4.0-182.202 ]
+
+  * focal/linux: 5.4.0-182.202 -proposed tracker (LP: #2063685)
+  * CVE-2023-52530
+    - wifi: mac80211: fix potential key use-after-free
+  * CVE-2024-26622
+    - tomoyo: fix UAF write bug in tomoyo_write_control()
+  * CVE-2024-26614
+    - tcp: make sure init the accept_queue's spinlocks once
+    - ipv6: init the accept_queue's spinlocks in inet6_create
+  * CVE-2023-47233
+    - wifi: brcmfmac: Fix use-after-free bug in brcmf_cfg80211_detach
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Tue, 07 May 2024 10:22:39 +1000
+
+linux-xilinx-zynqmp (5.4.0-1043.47) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1043.47 -proposed tracker (LP: #2059547)
+
+  * Focal update: v5.4.269 upstream stable release (LP: #2058948)
+    - [Config] updateconfigs for MFD_TI_AM335X_TSCADC
+
+  [ Ubuntu: 5.4.0-181.201 ]
+
+  * focal/linux: 5.4.0-181.201 -proposed tracker (LP: #2059549)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] drop getabis data
+  * Drop fips-checks script from trees (LP: #2055083)
+    - [Packaging] Remove fips-checks script
+  * Remove getabis scripts (LP: #2059143)
+    - [Packaging] Remove getabis
+  * Focal update: v5.4.269 upstream stable release (LP: #2058948)
+    - PCI: mediatek: Clear interrupt status before dispatching handler
+    - include/linux/units.h: add helpers for kelvin to/from Celsius conversion
+    - units: Add Watt units
+    - units: change from 'L' to 'UL'
+    - units: add the HZ macros
+    - serial: sc16is7xx: set safe default SPI clock frequency
+    - spi: introduce SPI_MODE_X_MASK macro
+    - serial: sc16is7xx: add check for unsupported SPI modes during probe
+    - ext4: allow for the last group to be marked as trimmed
+    - crypto: api - Disallow identical driver names
+    - PM: hibernate: Enforce ordering during image compression/decompression
+    - hwrng: core - Fix page fault dead lock on mmap-ed hwrng
+    - rpmsg: virtio: Free driver_override when rpmsg_remove()
+    - parisc/firmware: Fix F-extend for PDC addresses
+    - arm64: dts: qcom: sdm845: fix USB wakeup interrupt types
+    - mmc: core: Use mrq.sbc in close-ended ffu
+    - nouveau/vmm: don't set addr on the fail path to avoid warning
+    - ubifs: ubifs_symlink: Fix memleak of inode->i_link in error path
+    - rename(): fix the locking of subdirectories
+    - block: Remove special-casing of compound pages
+    - mtd: spinand: macronix: Fix MX35LFxGE4AD page size
+    - fs: add mode_strip_sgid() helper
+    - fs: move S_ISGID stripping into the vfs_*() helpers
+    - powerpc: Use always instead of always-y in for crtsavres.o
+    - x86/CPU/AMD: Fix disabling XSAVES on AMD family 0x17 due to erratum
+    - net/smc: fix illegal rmb_desc access in SMC-D connection dump
+    - vlan: skip nested type that is not IFLA_VLAN_QOS_MAPPING
+    - llc: make llc_ui_sendmsg() more robust against bonding changes
+    - llc: Drop support for ETH_P_TR_802_2.
+    - net/rds: Fix UBSAN: array-index-out-of-bounds in rds_cmsg_recv
+    - tracing: Ensure visibility when inserting an element into tracing_map
+    - afs: Hide silly-rename files from userspace
+    - tcp: Add memory barrier to tcp_push()
+    - netlink: fix potential sleeping issue in mqueue_flush_file
+    - net/mlx5: DR, Use the right GVMI number for drop action
+    - net/mlx5: Use kfree(ft->g) in arfs_create_groups()
+    - net/mlx5e: fix a double-free in arfs_create_groups
+    - netfilter: nf_tables: restrict anonymous set and map names to 16 bytes
+    - netfilter: nf_tables: validate NFPROTO_* family
+    - fjes: fix memleaks in fjes_hw_setup
+    - net: fec: fix the unhandled context fault from smmu
+    - btrfs: ref-verify: free ref cache before clearing mount opt
+    - btrfs: tree-checker: fix inline ref size in error messages
+    - btrfs: don't warn if discard range is not aligned to sector
+    - btrfs: defrag: reject unknown flags of btrfs_ioctl_defrag_range_args
+    - rbd: don't move requests to the running list on errors
+    - gpiolib: acpi: Ignore touchpad wakeup on GPD G1619-04
+    - drm: Don't unref the same fb many times by mistake due to deadlock handling
+    - drm/bridge: nxp-ptn3460: fix i2c_master_send() error checking
+    - drm/bridge: nxp-ptn3460: simplify some error checking
+    - drm/exynos: fix accidental on-stack copy of exynos_drm_plane
+    - drm/exynos: gsc: minor fix for loop iteration in gsc_runtime_resume
+    - gpio: eic-sprd: Clear interrupt after set the interrupt type
+    - spi: bcm-qspi: fix SFDP BFPT read by usig mspi read
+    - mips: Call lose_fpu(0) before initializing fcr31 in mips_set_personality_nan
+    - tick/sched: Preserve number of idle sleeps across CPU hotplug events
+    - x86/entry/ia32: Ensure s32 is sign extended to s64
+    - powerpc/mm: Fix null-pointer dereference in pgtable_cache_add
+    - powerpc: Fix build error due to is_valid_bugaddr()
+    - powerpc/mm: Fix build failures due to arch_reserved_kernel_pages()
+    - powerpc: pmd_move_must_withdraw() is only needed for
+      CONFIG_TRANSPARENT_HUGEPAGE
+    - powerpc/lib: Validate size for vector operations
+    - x86/mce: Mark fatal MCE's page as poison to avoid panic in the kdump kernel
+    - perf/core: Fix narrow startup race when creating the perf nr_addr_filters
+      sysfs file
+    - regulator: core: Only increment use_count when enable_count changes
+    - audit: Send netlink ACK before setting connection in auditd_set
+    - ACPI: video: Add quirk for the Colorful X15 AT 23 Laptop
+    - PNP: ACPI: fix fortify warning
+    - ACPI: extlog: fix NULL pointer dereference check
+    - FS:JFS:UBSAN:array-index-out-of-bounds in dbAdjTree
+    - jfs: fix slab-out-of-bounds Read in dtSearch
+    - jfs: fix array-index-out-of-bounds in dbAdjTree
+    - pstore/ram: Fix crash when setting number of cpus to an odd number
+    - crypto: stm32/crc32 - fix parsing list of devices
+    - afs: fix the usage of read_seqbegin_or_lock() in afs_find_server*()
+    - rxrpc_find_service_conn_rcu: fix the usage of read_seqbegin_or_lock()
+    - jfs: fix array-index-out-of-bounds in diNewExt
+    - s390/ptrace: handle setting of fpc register correctly
+    - KVM: s390: fix setting of fpc register
+    - SUNRPC: Fix a suspicious RCU usage warning
+    - ecryptfs: Reject casefold directory inodes
+    - ext4: fix inconsistent between segment fstrim and full fstrim
+    - ext4: unify the type of flexbg_size to unsigned int
+    - ext4: remove unnecessary check from alloc_flex_gd()
+    - ext4: avoid online resizing failures due to oversized flex bg
+    - wifi: rt2x00: restart beacon queue when hardware reset
+    - selftests/bpf: satisfy compiler by having explicit return in btf test
+    - selftests/bpf: Fix pyperf180 compilation failure with clang18
+    - scsi: lpfc: Fix possible file string name overflow when updating firmware
+    - PCI: Add no PM reset quirk for NVIDIA Spectrum devices
+    - bonding: return -ENOMEM instead of BUG in alb_upper_dev_walk
+    - ARM: dts: imx7d: Fix coresight funnel ports
+    - ARM: dts: imx7s: Fix lcdif compatible
+    - ARM: dts: imx7s: Fix nand-controller #size-cells
+    - wifi: ath9k: Fix potential array-index-out-of-bounds read in
+      ath9k_htc_txstatus()
+    - bpf: Add map and need_defer parameters to .map_fd_put_ptr()
+    - scsi: libfc: Don't schedule abort twice
+    - scsi: libfc: Fix up timeout error in fc_fcp_rec_error()
+    - ARM: dts: rockchip: fix rk3036 hdmi ports node
+    - ARM: dts: imx25/27-eukrea: Fix RTC node name
+    - ARM: dts: imx: Use flash@0,0 pattern
+    - ARM: dts: imx27: Fix sram node
+    - ARM: dts: imx1: Fix sram node
+    - ARM: dts: imx25/27: Pass timing0
+    - ARM: dts: imx27-apf27dev: Fix LED name
+    - ARM: dts: imx23-sansa: Use preferred i2c-gpios properties
+    - ARM: dts: imx23/28: Fix the DMA controller node name
+    - block: prevent an integer overflow in bvec_try_merge_hw_page
+    - md: Whenassemble the array, consult the superblock of the freshest device
+    - arm64: dts: qcom: msm8996: Fix 'in-ports' is a required property
+    - arm64: dts: qcom: msm8998: Fix 'out-ports' is a required property
+    - wifi: rtl8xxxu: Add additional USB IDs for RTL8192EU devices
+    - wifi: rtlwifi: rtl8723{be,ae}: using calculate_bit_shift()
+    - wifi: cfg80211: free beacon_ies when overridden from hidden BSS
+    - f2fs: fix to check return value of f2fs_reserve_new_block()
+    - ASoC: doc: Fix undefined SND_SOC_DAPM_NOPM argument
+    - fast_dput(): handle underflows gracefully
+    - RDMA/IPoIB: Fix error code return in ipoib_mcast_join
+    - drm/drm_file: fix use of uninitialized variable
+    - drm/framebuffer: Fix use of uninitialized variable
+    - drm/mipi-dsi: Fix detach call without attach
+    - media: stk1160: Fixed high volume of stk1160_dbg messages
+    - media: rockchip: rga: fix swizzling for RGB formats
+    - PCI: add INTEL_HDA_ARL to pci_ids.h
+    - ALSA: hda: Intel: add HDA_ARL PCI ID support
+    - drm/exynos: Call drm_atomic_helper_shutdown() at shutdown/unbind time
+    - IB/ipoib: Fix mcast list locking
+    - media: ddbridge: fix an error code problem in ddb_probe
+    - drm/msm/dpu: Ratelimit framedone timeout msgs
+    - clk: hi3620: Fix memory leak in hi3620_mmc_clk_init()
+    - clk: mmp: pxa168: Fix memory leak in pxa168_clk_init()
+    - drm/amdgpu: Let KFD sync with VM fences
+    - drm/amdgpu: Drop 'fence' check in 'to_amdgpu_amdkfd_fence()'
+    - leds: trigger: panic: Don't register panic notifier if creating the trigger
+      failed
+    - um: Fix naming clash between UML and scheduler
+    - um: Don't use vfprintf() for os_info()
+    - um: net: Fix return type of uml_net_start_xmit()
+    - i3c: master: cdns: Update maximum prescaler value for i2c clock
+    - mfd: ti_am335x_tscadc: Fix TI SoC dependencies
+    - [Config] updateconfigs for MFD_TI_AM335X_TSCADC
+    - PCI: Only override AMD USB controller if required
+    - PCI: switchtec: Fix stdev_release() crash after surprise hot remove
+    - usb: hub: Replace hardcoded quirk value with BIT() macro
+    - fs/kernfs/dir: obey S_ISGID
+    - PCI/AER: Decode Requester ID when no error info found
+    - libsubcmd: Fix memory leak in uniq()
+    - virtio_net: Fix "‘%d’ directive writing between 1 and 11 bytes into a region
+      of size 10" warnings
+    - blk-mq: fix IO hang from sbitmap wakeup race
+    - ceph: fix deadlock or deadcode of misusing dget()
+    - drm/amdgpu: Release 'adev->pm.fw' before return in
+      'amdgpu_device_need_post()'
+    - perf: Fix the nr_addr_filters fix
+    - wifi: cfg80211: fix RCU dereference in __cfg80211_bss_update
+    - scsi: isci: Fix an error code problem in isci_io_request_build()
+    - net: remove unneeded break
+    - ixgbe: Remove non-inclusive language
+    - ixgbe: Refactor returning internal error codes
+    - ixgbe: Refactor overtemp event handling
+    - ixgbe: Fix an error handling path in ixgbe_read_iosf_sb_reg_x550()
+    - ipv6: Ensure natural alignment of const ipv6 loopback and router addresses
+    - llc: call sock_orphan() at release time
+    - netfilter: nf_log: replace BUG_ON by WARN_ON_ONCE when putting logger
+    - netfilter: nft_ct: sanitize layer 3 and 4 protocol number in custom
+      expectations
+    - net: ipv4: fix a memleak in ip_setup_cork
+    - af_unix: fix lockdep positive in sk_diag_dump_icons()
+    - SAUCE: Sync apparmor copy of af_unix.c
+    - net: sysfs: Fix /sys/class/net/<iface> path
+    - HID: apple: Add support for the 2021 Magic Keyboard
+    - HID: apple: Swap the Fn and Left Control keys on Apple keyboards
+    - HID: apple: Add 2021 magic keyboard FN key mapping
+    - bonding: remove print in bond_verify_device_path
+    - dmaengine: fsl-qdma: Fix a memory leak related to the status queue DMA
+    - dmaengine: fsl-qdma: Fix a memory leak related to the queue command DMA
+    - phy: renesas: rcar-gen3-usb2: Fix returning wrong error code
+    - dmaengine: fix is_slave_direction() return false when DMA_DEV_TO_DEV
+    - phy: ti: phy-omap-usb2: Fix NULL pointer dereference for SRP
+    - net: stmmac: xgmac: fix handling of DPP safety error for DMA channels
+    - selftests: net: avoid just another constant wait
+    - atm: idt77252: fix a memleak in open_card_ubr0
+    - hwmon: (aspeed-pwm-tacho) mutex for tach reading
+    - hwmon: (coretemp) Fix out-of-bounds memory access
+    - hwmon: (coretemp) Fix bogus core_id to attr name mapping
+    - inet: read sk->sk_family once in inet_recv_error()
+    - rxrpc: Fix response to PING RESPONSE ACKs to a dead call
+    - tipc: Check the bearer type before calling tipc_udp_nl_bearer_add()
+    - ppp_async: limit MRU to 64K
+    - netfilter: nft_compat: reject unused compat flag
+    - netfilter: nft_compat: restrict match/target protocol to u16
+    - netfilter: nft_ct: reject direction for ct id
+    - net/af_iucv: clean up a try_then_request_module()
+    - USB: serial: qcserial: add new usb-id for Dell Wireless DW5826e
+    - USB: serial: option: add Fibocom FM101-GL variant
+    - USB: serial: cp210x: add ID for IMST iM871A-USB
+    - hrtimer: Report offline hrtimer enqueue
+    - Input: atkbd - skip ATKBD_CMD_SETLEDS when skipping ATKBD_CMD_GETID
+    - net: stmmac: xgmac: use #define for string constants
+    - net: stmmac: xgmac: fix a typo of register name in DPP safety handling
+    - btrfs: forbid creating subvol qgroups
+    - btrfs: forbid deleting live subvol qgroup
+    - btrfs: send: return EOPNOTSUPP on unknown flags
+    - of: unittest: add overlay gpio test to catch gpio hog problem
+    - of: unittest: Fix compile in the non-dynamic case
+    - spi: ppc4xx: Drop write-only variable
+    - ASoC: rt5645: Fix deadlock in rt5645_jack_detect_work()
+    - MIPS: Add 'memory' clobber to csum_ipv6_magic() inline assembler
+    - i40e: Fix waiting for queues of all VSIs to be disabled
+    - tracing/trigger: Fix to return error if failed to alloc snapshot
+    - mm/writeback: fix possible divide-by-zero in wb_dirty_limits(), again
+    - HID: wacom: generic: Avoid reporting a serial of '0' to userspace
+    - HID: wacom: Do not register input devices until after hid_hw_start
+    - USB: hub: check for alternate port before enabling A_ALT_HNP_SUPPORT
+    - usb: f_mass_storage: forbid async queue when shutdown happen
+    - i2c: i801: Remove i801_set_block_buffer_mode
+    - i2c: i801: Fix block process call transactions
+    - scsi: Revert "scsi: fcoe: Fix potential deadlock on &fip->ctlr_lock"
+    - firewire: core: correct documentation of fw_csr_string() kernel API
+    - kbuild: Fix changing ELF file type for output of gen_btf for big endian
+    - nfc: nci: free rx_data_reassembly skb on NCI device cleanup
+    - xen-netback: properly sync TX responses
+    - ALSA: hda/realtek: Enable headset mic on Vaio VJFE-ADL
+    - binder: signal epoll threads of self-work
+    - misc: fastrpc: Mark all sessions as invalid in cb_remove
+    - ext4: fix double-free of blocks due to wrong extents moved_len
+    - tracing: Fix wasted memory in saved_cmdlines logic
+    - staging: iio: ad5933: fix type mismatch regression
+    - iio: magnetometer: rm3100: add boundary check for the value read from
+      RM3100_REG_TMRC
+    - ring-buffer: Clean ring_buffer_poll_wait() error return
+    - serial: max310x: set default value when reading clock ready bit
+    - serial: max310x: improve crystal stable clock detection
+    - x86/Kconfig: Transmeta Crusoe is CPU family 5, not 6
+    - x86/mm/ident_map: Use gbpages only where full GB page should be mapped.
+    - mmc: slot-gpio: Allow non-sleeping GPIO ro
+    - ALSA: hda/conexant: Add quirk for SWS JS201D
+    - nilfs2: fix data corruption in dsync block recovery for small block sizes
+    - nilfs2: fix hang in nilfs_lookup_dirty_data_buffers()
+    - nfp: use correct macro for LengthSelect in BAR config
+    - nfp: flower: prevent re-adding mac index for bonded port
+    - irqchip/irq-brcmstb-l2: Add write memory barrier before exit
+    - can: j1939: Fix UAF in j1939_sk_match_filter during
+      setsockopt(SO_J1939_FILTER)
+    - pmdomain: core: Move the unused cleanup to a _sync initcall
+    - tracing: Inform kmemleak of saved_cmdlines allocation
+    - Revert "md/raid5: Wait for MD_SB_CHANGE_PENDING in raid5d"
+    - bus: moxtet: Add spi device table
+    - arch, mm: remove stale mentions of DISCONIGMEM
+    - mips: Fix max_mapnr being uninitialized on early stages
+    - KVM: arm64: vgic-its: Avoid potential UAF in LPI translation cache
+    - netfilter: ipset: fix performance regression in swap operation
+    - netfilter: ipset: Missing gc cancellations fixed
+    - net: prevent mss overflow in skb_segment()
+    - sched/membarrier: reduce the ability to hammer on sys_membarrier
+    - nilfs2: fix potential bug in end_buffer_async_write
+    - PM: runtime: add devm_pm_runtime_enable helper
+    - PM: runtime: Have devm_pm_runtime_enable() handle
+      pm_runtime_dont_use_autosuspend()
+    - drm/msm/dsi: Enable runtime PM
+    - lsm: new security_file_ioctl_compat() hook
+    - Revert "Revert "mtd: rawnand: gpmi: Fix setting busy timeout setting""
+    - net: bcmgenet: Fix EEE implementation
+    - of: unittest: fix EXPECT text for gpio hog errors
+    - of: gpio unittest kfree() wrong object
+    - Linux 5.4.269
+  * Focal update: v5.4.269 upstream stable release (LP: #2058948) //
+    CVE-2023-52603
+    - UBSAN: array-index-out-of-bounds in dtSplitRoot
+  * CVE-2023-52600
+    - jfs: fix uaf in jfs_evict_inode
+  * CVE-2023-24023
+    - Bluetooth: Add more enc key size check
+  * CVE-2024-26581
+    - netfilter: nf_tables: nft_set_rbtree: fix spurious insertion failure
+    - netfilter: nft_set_rbtree: skip end interval element from gc
+  * CVE-2024-26589
+    - bpf: Reject variable offset alu on PTR_TO_FLOW_KEYS
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Fri, 12 Apr 2024 13:50:59 +1000
+
+linux-xilinx-zynqmp (5.4.0-1042.46) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1042.46 -proposed tracker (LP: #2059631)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] drop getabis data
+
+  [ Ubuntu: 5.4.0-177.197 ]
+
+  * focal/linux: 5.4.0-177.197 -proposed tracker (LP: #2059633)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] drop getabis data
+  * Remove getabis scripts (LP: #2059143)
+    - [Packaging] Remove getabis
+  * CVE-2023-24023
+    - Bluetooth: Add more enc key size check
+  * CVE-2023-52600
+    - jfs: fix uaf in jfs_evict_inode
+  * Focal update: v5.4.269 upstream stable release (LP: #2058948) //
+    CVE-2023-52603
+    - UBSAN: array-index-out-of-bounds in dtSplitRoot
+  * CVE-2024-26581
+    - netfilter: nf_tables: nft_set_rbtree: fix spurious insertion failure
+    - netfilter: nft_set_rbtree: skip end interval element from gc
+  * CVE-2024-26589
+    - bpf: Reject variable offset alu on PTR_TO_FLOW_KEYS
+
+  [ Ubuntu: 5.4.0-176.196 ]
+
+  * focal/linux: 5.4.0-176.196 -proposed tracker (LP: #2058756)
+  * Problems with HVCS and hotplugging (LP: #2056373)
+    - powerpc/pseries: Fix bad drc_index_start value parsing of drc-info entry
+    - powerpc/pseries: Fix of_read_drc_info_cell() to point at next record
+    - hvcs: Fix hvcs port reference counting
+    - hvcs: Use dev_groups to manage hvcs device attributes
+    - hvcs: Use driver groups to manage driver attributes
+    - hvcs: Get reference to tty in remove
+    - hvcs: Use vhangup in hotplug remove
+    - hvcs: Synchronize hotplug remove with port free
+
+ -- Aaron Jauregui <aaron.jauregui@canonical.com>  Thu, 04 Apr 2024 16:22:56 +1100
+
+linux-xilinx-zynqmp (5.4.0-1041.45) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1041.45 -proposed tracker (LP: #2055682)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] drop ABI data
+    - debian.zynqmp/dkms-versions -- update from kernel-versions (main/2024.03.04)
+
+  * Focal update: v5.4.268 upstream stable release (LP: #2055075)
+    - [Config] update annotations for CONFIG_MMC_SDHCI_OMAP
+
+  * Focal update: v5.4.267 upstream stable release (LP: #2054406)
+    - [Config] Update annotations for CONFIG_SND_MESON_CODEC_GLUE
+
+  [ Ubuntu: 5.4.0-175.195 ]
+
+  * focal/linux: 5.4.0-175.195 -proposed tracker (LP: #2055684)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] drop ABI data
+    - [Packaging] update annotations scripts
+    - debian.master/dkms-versions -- update from kernel-versions (main/2024.03.04)
+  * Drop ABI checks from kernel build (LP: #2055686)
+    - [Packaging] Remove in-tree abi checks
+    - [Packaging] Bring back install-<flavour> prerequisite for checks-<flavour>
+    - [Packaging] Remove abi-check from final-checks
+  * Cranky update-dkms-versions rollout (LP: #2055685)
+    - [Packaging] remove update-dkms-versions
+    - Move debian/dkms-versions to debian.master/dkms-versions
+    - [Packaging] Replace debian/dkms-versions with $(DEBIAN)/dkms-versions
+    - [Packaging] remove update-version-dkms
+  * linux-tools-common: man page of usbip[d] is misplaced (LP: #2054094)
+    - [Packaging] rules: Put usbip manpages in the correct directory
+  * CVE-2024-23851
+    - dm ioctl: log an error if the ioctl structure is corrupted
+    - dm: limit the number of targets and parameter size area
+  * Focal update: v5.4.268 upstream stable release (LP: #2055075)
+    - f2fs: explicitly null-terminate the xattr list
+    - pinctrl: lochnagar: Don't build on MIPS
+    - ALSA: hda - Fix speaker and headset mic pin config for CHUWI CoreBook XPro
+    - ASoC: Intel: Skylake: Fix mem leak in few functions
+    - ASoC: nau8822: Fix incorrect type in assignment and cast to restricted
+      __be16
+    - ASoC: Intel: Skylake: mem leak in skl register function
+    - ASoC: cs43130: Fix the position of const qualifier
+    - ASoC: cs43130: Fix incorrect frame delay configuration
+    - ASoC: rt5650: add mutex to avoid the jack detection failure
+    - nouveau/tu102: flush all pdbs on vmm flush
+    - net/tg3: fix race condition in tg3_reset_task()
+    - ASoC: da7219: Support low DC impedance headset
+    - nvme: introduce helper function to get ctrl state
+    - drm/exynos: fix a potential error pointer dereference
+    - drm/exynos: fix a wrong error checking
+    - clk: rockchip: rk3128: Fix HCLK_OTG gate register
+    - jbd2: correct the printing of write_flags in jbd2_write_superblock()
+    - drm/crtc: Fix uninit-value bug in drm_mode_setcrtc
+    - neighbour: Don't let neigh_forced_gc() disable preemption for long
+    - tracing: Have large events show up as '[LINE TOO BIG]' instead of nothing
+    - tracing: Add size check when printing trace_marker output
+    - ring-buffer: Do not record in NMI if the arch does not support cmpxchg in
+      NMI
+    - reset: hisilicon: hi6220: fix Wvoid-pointer-to-enum-cast warning
+    - Input: atkbd - skip ATKBD_CMD_GETID in translated mode
+    - Input: i8042 - add nomux quirk for Acer P459-G2-M
+    - s390/scm: fix virtual vs physical address confusion
+    - ARC: fix spare error
+    - Input: xpad - add Razer Wolverine V2 support
+    - ARM: sun9i: smp: fix return code check of of_property_match_string
+    - drm/crtc: fix uninitialized variable use
+    - ACPI: resource: Add another DMI match for the TongFang GMxXGxx
+    - binder: use EPOLLERR from eventpoll.h
+    - binder: fix trivial typo of binder_free_buf_locked()
+    - binder: fix comment on binder_alloc_new_buf() return value
+    - uio: Fix use-after-free in uio_open
+    - parport: parport_serial: Add Brainboxes BAR details
+    - parport: parport_serial: Add Brainboxes device IDs and geometry
+    - coresight: etm4x: Fix width of CCITMIN field
+    - x86/lib: Fix overflow when counting digits
+    - EDAC/thunderx: Fix possible out-of-bounds string access
+    - powerpc: add crtsavres.o to always-y instead of extra-y
+    - powerpc/44x: select I2C for CURRITUCK
+    - powerpc/pseries/memhotplug: Quieten some DLPAR operations
+    - powerpc/pseries/memhp: Fix access beyond end of drmem array
+    - selftests/powerpc: Fix error handling in FPU/VMX preemption tests
+    - powerpc/powernv: Add a null pointer check to scom_debug_init_one()
+    - powerpc/powernv: Add a null pointer check in opal_event_init()
+    - powerpc/powernv: Add a null pointer check in opal_powercap_init()
+    - powerpc/imc-pmu: Add a null pointer check in update_events_in_group()
+    - mtd: rawnand: Increment IFC_TIMEOUT_MSECS for nand controller response
+    - ACPI: video: check for error while searching for backlight device parent
+    - ACPI: LPIT: Avoid u32 multiplication overflow
+    - net: netlabel: Fix kerneldoc warnings
+    - netlabel: remove unused parameter in netlbl_netlink_auditinfo()
+    - calipso: fix memory leak in netlbl_calipso_add_pass()
+    - spi: sh-msiof: Enforce fixed DTDL for R-Car H3
+    - mtd: Fix gluebi NULL pointer dereference caused by ftl notifier
+    - selinux: Fix error priority for bind with AF_UNSPEC on PF_INET6 socket
+    - crypto: virtio - Handle dataq logic with tasklet
+    - crypto: virtio - don't use 'default m'
+    - virtio_crypto: Introduce VIRTIO_CRYPTO_NOSPC
+    - crypto: ccp - fix memleak in ccp_init_dm_workarea
+    - crypto: af_alg - Disallow multiple in-flight AIO requests
+    - crypto: sahara - remove FLAGS_NEW_KEY logic
+    - crypto: sahara - fix ahash selftest failure
+    - crypto: sahara - fix processing requests with cryptlen < sg->length
+    - crypto: sahara - fix error handling in sahara_hw_descriptor_create()
+    - pstore: ram_core: fix possible overflow in persistent_ram_init_ecc()
+    - gfs2: Fix kernel NULL pointer dereference in gfs2_rgrp_dump
+    - crypto: virtio - Wait for tasklet to complete on device remove
+    - crypto: sahara - fix ahash reqsize
+    - crypto: sahara - fix wait_for_completion_timeout() error handling
+    - crypto: sahara - improve error handling in sahara_sha_process()
+    - crypto: sahara - fix processing hash requests with req->nbytes < sg->length
+    - crypto: sahara - do not resize req->src when doing hash operations
+    - crypto: scomp - fix req->dst buffer overflow
+    - blocklayoutdriver: Fix reference leak of pnfs_device_node
+    - NFSv4.1/pnfs: Ensure we handle the error NFS4ERR_RETURNCONFLICT
+    - wifi: rtw88: fix RX filter in FIF_ALLMULTI flag
+    - bpf, lpm: Fix check prefixlen before walking trie
+    - wifi: libertas: stop selecting wext
+    - ARM: dts: qcom: apq8064: correct XOADC register address
+    - ncsi: internal.h: Fix a spello
+    - net/ncsi: Fix netlink major/minor version numbers
+    - firmware: ti_sci: Fix an off-by-one in ti_sci_debugfs_create()
+    - rtlwifi: Use ffs in <foo>_phy_calculate_bit_shift
+    - wifi: rtlwifi: rtl8821ae: phy: fix an undefined bitwise shift behavior
+    - scsi: fnic: Return error if vmalloc() failed
+    - arm64: dts: qcom: sdm845-db845c: correct LED panic indicator
+    - scsi: hisi_sas: Replace with standard error code return value
+    - selftests/net: fix grep checking for fib_nexthop_multiprefix
+    - virtio/vsock: fix logic which reduces credit update messages
+    - dma-mapping: clear dev->dma_mem to NULL after freeing it
+    - wifi: rtlwifi: add calculate_bit_shift()
+    - wifi: rtlwifi: rtl8188ee: phy: using calculate_bit_shift()
+    - wifi: rtlwifi: rtl8192c: using calculate_bit_shift()
+    - wifi: rtlwifi: rtl8192cu: using calculate_bit_shift()
+    - wifi: rtlwifi: rtl8192ce: using calculate_bit_shift()
+    - rtlwifi: rtl8192de: make arrays static const, makes object smaller
+    - wifi: rtlwifi: rtl8192de: using calculate_bit_shift()
+    - wifi: rtlwifi: rtl8192ee: using calculate_bit_shift()
+    - wifi: rtlwifi: rtl8192se: using calculate_bit_shift()
+    - netfilter: nf_tables: mark newset as dead on transaction abort
+    - Bluetooth: Fix bogus check for re-auth no supported with non-ssp
+    - Bluetooth: btmtkuart: fix recv_buf() return value
+    - ip6_tunnel: fix NEXTHDR_FRAGMENT handling in ip6_tnl_parse_tlv_enc_lim()
+    - ARM: davinci: always select CONFIG_CPU_ARM926T
+    - RDMA/usnic: Silence uninitialized symbol smatch warnings
+    - media: pvrusb2: fix use after free on context disconnection
+    - drm/bridge: Fix typo in post_disable() description
+    - f2fs: fix to avoid dirent corruption
+    - drm/radeon/r600_cs: Fix possible int overflows in r600_cs_check_reg()
+    - drm/radeon/r100: Fix integer overflow issues in r100_cs_track_check()
+    - drm/radeon: check return value of radeon_ring_lock()
+    - ASoC: cs35l33: Fix GPIO name and drop legacy include
+    - ASoC: cs35l34: Fix GPIO name and drop legacy include
+    - drm/msm/mdp4: flush vblank event on disable
+    - drm/msm/dsi: Use pm_runtime_resume_and_get to prevent refcnt leaks
+    - drm/drv: propagate errors from drm_modeset_register_all()
+    - drm/radeon: check the alloc_workqueue return value in radeon_crtc_init()
+    - drm/radeon/dpm: fix a memleak in sumo_parse_power_table
+    - drm/radeon/trinity_dpm: fix a memleak in trinity_parse_power_table
+    - drm/bridge: tc358767: Fix return value on error case
+    - media: cx231xx: fix a memleak in cx231xx_init_isoc
+    - media: dvbdev: drop refcount on error path in dvb_device_open()
+    - drm/amdgpu/debugfs: fix error code when smc register accessors are NULL
+    - drm/amd/pm: fix a double-free in si_dpm_init
+    - drivers/amd/pm: fix a use-after-free in kv_parse_power_table
+    - gpu/drm/radeon: fix two memleaks in radeon_vm_init
+    - drivers: clk: zynqmp: calculate closest mux rate
+    - watchdog: set cdev owner before adding
+    - watchdog/hpwdt: Only claim UNKNOWN NMI if from iLO
+    - watchdog: bcm2835_wdt: Fix WDIOC_SETTIMEOUT handling
+    - clk: si5341: fix an error code problem in si5341_output_clk_set_rate
+    - mmc: sdhci_omap: Fix TI SoC dependencies
+    - [Config] update annotations for CONFIG_MMC_SDHCI_OMAP
+    - [Config] remove sdhci-omap module for arm64/ppc64el
+    - of: Fix double free in of_parse_phandle_with_args_map
+    - of: unittest: Fix of_count_phandle_with_args() expected value message
+    - binder: fix async space check for 0-sized buffers
+    - binder: fix use-after-free in shinker's callback
+    - Input: atkbd - use ab83 as id when skipping the getid command
+    - Revert "ASoC: atmel: Remove system clock tree configuration for
+      at91sam9g20ek"
+    - binder: fix race between mmput() and do_exit()
+    - binder: fix unused alloc->free_async_space
+    - tick-sched: Fix idle and iowait sleeptime accounting vs CPU hotplug
+    - usb: phy: mxs: remove CONFIG_USB_OTG condition for mxs_phy_is_otg_host()
+    - usb: dwc: ep0: Update request status in dwc3_ep0_stall_restart
+    - Revert "usb: dwc3: Soft reset phy on probe for host"
+    - Revert "usb: dwc3: don't reset device side if dwc3 was configured as host-
+      only"
+    - usb: chipidea: wait controller resume finished for wakeup irq
+    - Revert "usb: typec: class: fix typec_altmode_put_partner to put plugs"
+    - usb: typec: class: fix typec_altmode_put_partner to put plugs
+    - usb: mon: Fix atomicity violation in mon_bin_vma_fault
+    - ALSA: oxygen: Fix right channel of capture volume mixer
+    - fbdev: flush deferred work in fb_deferred_io_fsync()
+    - rootfs: Fix support for rootfstype= when root= is given
+    - wifi: rtlwifi: Remove bogus and dangerous ASPM disable/enable code
+    - wifi: rtlwifi: Convert LNKCTL change to PCIe cap RMW accessors
+    - wifi: mwifiex: configure BSSID consistently when starting AP
+    - x86/kvm: Do not try to disable kvmclock if it was not enabled
+    - HID: wacom: Correct behavior when processing some confidence == false
+      touches
+    - mips: Fix incorrect max_low_pfn adjustment
+    - MIPS: Alchemy: Fix an out-of-bound access in db1200_dev_setup()
+    - MIPS: Alchemy: Fix an out-of-bound access in db1550_dev_setup()
+    - serial: 8250: omap: Don't skip resource freeing if
+      pm_runtime_resume_and_get() failed
+    - acpi: property: Let args be NULL in __acpi_node_get_property_reference
+    - software node: Let args be NULL in software_node_get_reference_args
+    - perf genelf: Set ELF program header addresses properly
+    - nvmet-tcp: Fix a kernel panic when host sends an invalid H2C PDU length
+    - nvmet-tcp: fix a crash in nvmet_req_complete()
+    - perf env: Add perf_env__numa_node()
+    - perf record: Move sb_evlist to 'struct record'
+    - perf top: Move sb_evlist to 'struct perf_top'
+    - perf bpf: Decouple creating the evlist from adding the SB event
+    - perf env: Avoid recursively taking env->bpf_progs.lock
+    - apparmor: avoid crash when parsed profile name is empty
+    - serial: imx: Correct clock error message in function probe()
+    - nvmet-tcp: Fix the H2C expected PDU len calculation
+    - PCI: keystone: Fix race condition when initializing PHYs
+    - s390/pci: fix max size calculation in zpci_memcpy_toio()
+    - net: qualcomm: rmnet: fix global oob in rmnet_policy
+    - net: phy: micrel: populate .soft_reset for KSZ9131
+    - net: ravb: Fix dma_addr_t truncation in error case
+    - net: dsa: vsc73xx: Add null pointer check to vsc73xx_gpio_probe
+    - netfilter: nf_tables: skip dead set elements in netlink dump
+    - ipvs: avoid stat macros calls from preemptible context
+    - kdb: Censor attempts to set PROMPT without ENABLE_MEM_READ
+    - kdb: Fix a potential buffer overflow in kdb_local()
+    - mlxsw: spectrum_acl_erp: Fix error flow of pool allocation failure
+    - i2c: s3c24xx: fix read transfers in polling mode
+    - i2c: s3c24xx: fix transferring more than one message in polling mode
+    - perf top: Skip side-band event setup if HAVE_LIBBPF_SUPPORT is not set
+    - arm64: dts: armada-3720-turris-mox: set irq type for RTC
+    - Linux 5.4.268
+  * CVE-2024-24855
+    - scsi: lpfc: Fix a possible data race in lpfc_unregister_fcf_rescan()
+  * Focal update: v5.4.267 upstream stable release (LP: #2054406)
+    - nfc: llcp_core: Hold a ref to llcp_local->dev when holding a ref to
+      llcp_local
+    - i40e: Fix filter input checks to prevent config with invalid values
+    - net: sched: em_text: fix possible memory leak in em_text_destroy()
+    - can: raw: add support for SO_TXTIME/SCM_TXTIME
+    - can: raw: add support for SO_MARK
+    - net-timestamp: extend SOF_TIMESTAMPING_OPT_ID to HW timestamps
+    - ARM: sun9i: smp: Fix array-index-out-of-bounds read in sunxi_mc_smp_init
+    - net: bcmgenet: Fix FCS generation for fragmented skbuffs
+    - net: Save and restore msg_namelen in sock_sendmsg
+    - i40e: fix use-after-free in i40e_aqc_add_filters()
+    - ASoC: meson: g12a: extract codec-to-codec utils
+    - [Config] Update annotations for CONFIG_SND_MESON_CODEC_GLUE
+    - ASoC: meson: g12a-tohdmitx: Validate written enum values
+    - ASoC: meson: g12a-tohdmitx: Fix event generation for S/PDIF mux
+    - i40e: Restore VF MSI-X state during PCI reset
+    - net/qla3xxx: switch from 'pci_' to 'dma_' API
+    - net/qla3xxx: fix potential memleak in ql_alloc_buffer_queues
+    - asix: Add check for usbnet_get_endpoints
+    - bnxt_en: Remove mis-applied code from bnxt_cfg_ntp_filters()
+    - net: Implement missing SO_TIMESTAMPING_NEW cmsg support
+    - mm/memory-failure: check the mapcount of the precise page
+    - firewire: ohci: suppress unexpected system reboot in AMD Ryzen machines and
+      ASM108x/VT630x PCIe cards
+    - i2c: core: Fix atomic xfer check for non-preempt config
+    - mm: fix unmap_mapping_range high bits shift bug
+    - mmc: rpmb: fixes pause retune on all RPMB partitions.
+    - mmc: core: Cancel delayed work before releasing host
+    - mmc: sdhci-sprd: Fix eMMC init failure after hw reset
+    - ath10k: Wait until copy complete is actually done before completing
+    - ath10k: Add interrupt summary based CE processing
+    - ath10k: Keep track of which interrupts fired, don't poll them
+    - ath10k: Get rid of "per_ce_irq" hw param
+    - PCI: Extract ATS disabling to a helper function
+    - PCI: Disable ATS for specific Intel IPU E2000 devices
+    - net/dst: use a smaller percpu_counter batch for dst entries accounting
+    - ipv6: make ip6_rt_gc_expire an atomic_t
+    - ipv6: remove max_size check inline with ipv4
+    - ASoC: meson: codec-glue: fix pcm format cast warning
+    - Linux 5.4.267
+  * CVE-2023-23000
+    - phy: tegra: xusb: Fix return value of tegra_xusb_find_port_node function
+  * CVE-2023-23004
+    - malidp: Fix NULL vs IS_ERR() checking
+  * CVE-2023-46838
+    - xen-netback: don't produce zero-size SKB frags
+  * CVE-2024-1086
+    - netfilter: nf_tables: reject QUEUE/DROP verdict parameters
+  * Focal update: v5.4.266 upstream stable release (LP: #2051655)
+    - ALSA: hda/realtek: Enable headset on Lenovo M90 Gen5
+    - ksmbd: fix wrong name of SMB2_CREATE_ALLOCATION_SIZE
+    - ARM: OMAP2+: Fix null pointer dereference and memory leak in
+      omap_soc_device_init
+    - reset: Fix crash when freeing non-existent optional resets
+    - s390/vx: fix save/restore of fpu kernel context
+    - wifi: mac80211: mesh_plink: fix matches_local logic
+    - net/mlx5: improve some comments
+    - net/mlx5: Fix fw tracer first block check
+    - net/mlx5e: Correct snprintf truncation handling for fw_version buffer used
+      by representors
+    - net: sched: ife: fix potential use-after-free
+    - ethernet: atheros: fix a memleak in atl1e_setup_ring_resources
+    - net/rose: fix races in rose_kill_by_device()
+    - net: check vlan filter feature in vlan_vids_add_by_dev() and
+      vlan_vids_del_by_dev()
+    - afs: Fix the dynamic root's d_delete to always delete unused dentries
+    - afs: Fix dynamic root lookup DNS check
+    - net: warn if gso_type isn't set for a GSO SKB
+    - net: check dev->gso_max_size in gso_features_check()
+    - afs: Fix overwriting of result of DNS query
+    - i2c: aspeed: Handle the coalesced stop conditions with the start conditions.
+    - pinctrl: at91-pio4: use dedicated lock class for IRQ
+    - ALSA: hda/hdmi: Add quirk to force pin connectivity on NUC10
+    - ALSA: hda/hdmi: add force-connect quirk for NUC5CPYB
+    - smb: client: fix NULL deref in asn1_ber_decoder()
+    - btrfs: do not allow non subvolume root targets for snapshot
+    - interconnect: Treat xlate() returning NULL node as an error
+    - iio: imu: inv_mpu6050: fix an error code problem in inv_mpu6050_read_raw
+    - Input: ipaq-micro-keys - add error handling for devm_kmemdup
+    - scsi: bnx2fc: Fix skb double free in bnx2fc_rcv()
+    - iio: common: ms_sensors: ms_sensors_i2c: fix humidity conversion time table
+    - iio: adc: ti_am335x_adc: Fix return value check of tiadc_request_dma()
+    - wifi: cfg80211: Add my certificate
+    - wifi: cfg80211: fix certs build to not depend on file order
+    - USB: serial: ftdi_sio: update Actisense PIDs constant names
+    - USB: serial: option: add Quectel EG912Y module support
+    - USB: serial: option: add Foxconn T99W265 with new baseline
+    - USB: serial: option: add Quectel RM500Q R13 firmware support
+    - Bluetooth: hci_event: Fix not checking if HCI_OP_INQUIRY has been sent
+    - net: 9p: avoid freeing uninit memory in p9pdu_vreadf
+    - net: rfkill: gpio: set GPIO direction
+    - x86/alternatives: Sync core before enabling interrupts
+    - usb: fotg210-hcd: delete an incorrect bounds test
+    - ring-buffer: Fix wake ups when buffer_percent is set to 100
+    - block: Don't invalidate pagecache for invalid falloc modes
+    - Linux 5.4.266
+  * CVE-2024-0607
+    - netfilter: nf_tables: fix pointer math issue in nft_byteorder_eval()
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Fri, 22 Mar 2024 08:57:27 +1000
+
+linux-xilinx-zynqmp (5.4.0-1040.44) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1040.44 -proposed tracker (LP: #2055976)
+
+  [ Ubuntu: 5.4.0-174.193 ]
+
+  * focal/linux: 5.4.0-174.193 -proposed tracker (LP: #2055978)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update annotations scripts
+    - debian/dkms-versions -- update from kernel-versions (main/s2024.02.05)
+  * CVE-2024-24855
+    - scsi: lpfc: Fix a possible data race in lpfc_unregister_fcf_rescan()
+  * CVE-2024-1086
+    - netfilter: nf_tables: reject QUEUE/DROP verdict parameters
+  * CVE-2023-23004
+    - malidp: Fix NULL vs IS_ERR() checking
+  * CVE-2023-23000
+    - phy: tegra: xusb: Fix return value of tegra_xusb_find_port_node function
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Tue, 12 Mar 2024 14:20:43 +1000
+
+linux-xilinx-zynqmp (5.4.0-1039.43) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1039.43 -proposed tracker (LP: #2052133)
+
+  * Focal update: v5.4.261 upstream stable release (LP: #2049049)
+    - [Config] xilinx-zynqmp: remove CONFIG_QCOM_SDM845_LLCC
+
+  * Focal update: v5.4.260 upstream stable release (LP: #2049024)
+    - [Config] xilinx-zynqmp: remove CONFIG_BLK_DEV_SX8
+
+  [ Ubuntu: 5.4.0-173.191 ]
+
+  * focal/linux: 5.4.0-173.191 -proposed tracker (LP: #2052135)
+  * Packaging resync (LP: #1786013)
+    - debian/dkms-versions -- update from kernel-versions (main/2024.02.05)
+  * CVE-2023-0340
+    - vhost: use kzalloc() instead of kmalloc() followed by memset()
+  * CVE-2023-6915
+    - ida: Fix crash in ida_free when the bitmap is empty
+  * Focal update: v5.4.265 upstream stable release (LP: #2051644)
+    - afs: Fix refcount underflow from error handling race
+    - net: ipv6: support reporting otherwise unknown prefix flags in RTM_NEWPREFIX
+    - qca_debug: Prevent crash on TX ring changes
+    - qca_debug: Fix ethtool -G iface tx behavior
+    - qca_spi: Fix reset behavior
+    - atm: solos-pci: Fix potential deadlock on &cli_queue_lock
+    - atm: solos-pci: Fix potential deadlock on &tx_queue_lock
+    - atm: Fix Use-After-Free in do_vcc_ioctl
+    - qed: Fix a potential use-after-free in qed_cxt_tables_alloc
+    - net: Remove acked SYN flag from packet in the transmit queue correctly
+    - sign-file: Fix incorrect return values check
+    - vsock/virtio: Fix unsigned integer wrap around in
+      virtio_transport_has_space()
+    - net: stmmac: use dev_err_probe() for reporting mdio bus registration failure
+    - net: stmmac: Handle disabled MDIO busses from devicetree
+    - cred: switch to using atomic_long_t
+    - ALSA: hda/hdmi: add force-connect quirks for ASUSTeK Z170 variants
+    - usb: aqc111: check packet for fixup for true limit
+    - blk-throttle: fix lockdep warning of "cgroup_mutex or RCU read lock
+      required!"
+    - bcache: avoid oversize memory allocation by small stripe_size
+    - bcache: add code comments for bch_btree_node_get() and
+      __bch_btree_node_alloc()
+    - bcache: avoid NULL checking to c->root in run_cache_set()
+    - platform/x86: intel_telemetry: Fix kernel doc descriptions
+    - HID: add ALWAYS_POLL quirk for Apple kb
+    - HID: hid-asus: reset the backlight brightness level on resume
+    - HID: multitouch: Add quirk for HONOR GLO-GXXX touchpad
+    - asm-generic: qspinlock: fix queued_spin_value_unlocked() implementation
+    - net: usb: qmi_wwan: claim interface 4 for ZTE MF290
+    - HID: hid-asus: add const to read-only outgoing usb buffer
+    - soundwire: stream: fix NULL pointer dereference for multi_link
+    - ext4: prevent the normalized size from exceeding EXT_MAX_BLOCKS
+    - arm64: mm: Always make sw-dirty PTEs hw-dirty in pte_modify
+    - team: Fix use-after-free when an option instance allocation fails
+    - ring-buffer: Fix memory leak of free page
+    - mmc: block: Be sure to wait while busy in CQE error recovery
+    - powerpc/ftrace: Create a dummy stackframe to fix stack unwind
+    - powerpc/ftrace: Fix stack teardown in ftrace_no_trace
+    - Linux 5.4.265
+  * Focal update: v5.4.264 upstream stable release (LP: #2049935)
+    - hrtimers: Push pending hrtimers away from outgoing CPU earlier
+    - netfilter: ipset: fix race condition between swap/destroy and kernel side
+      add/del/test
+    - tg3: Move the [rt]x_dropped counters to tg3_napi
+    - tg3: Increment tx_dropped in tg3_tso_bug()
+    - kconfig: fix memory leak from range properties
+    - drm/amdgpu: correct chunk_ptr to a pointer to chunk.
+    - of: base: Add of_get_cpu_state_node() to get idle states for a CPU node
+    - ACPI/IORT: Make iort_get_device_domain IRQ domain agnostic
+    - ACPI/IORT: Make iort_msi_map_rid() PCI agnostic
+    - of/iommu: Make of_map_rid() PCI agnostic
+    - of/irq: make of_msi_map_get_device_domain() bus agnostic
+    - of/irq: Make of_msi_map_rid() PCI bus agnostic
+    - of: base: Fix some formatting issues and provide missing descriptions
+    - of: Fix kerneldoc output formatting
+    - of: Add missing 'Return' section in kerneldoc comments
+    - of: dynamic: Fix of_reconfig_get_state_change() return value documentation
+    - ipv6: fix potential NULL deref in fib6_add()
+    - hv_netvsc: rndis_filter needs to select NLS
+    - net: arcnet: Fix RESET flag handling
+    - net: arcnet: com20020 fix error handling
+    - arcnet: restoring support for multiple Sohard Arcnet cards
+    - ipv4: ip_gre: Avoid skb_pull() failure in ipgre_xmit()
+    - net: hns: fix fake link up on xge port
+    - netfilter: xt_owner: Fix for unsafe access of sk->sk_socket
+    - tcp: do not accept ACK of bytes we never sent
+    - bpf: sockmap, updating the sg structure should also update curr
+    - RDMA/bnxt_re: Correct module description string
+    - hwmon: (acpi_power_meter) Fix 4.29 MW bug
+    - ASoC: wm_adsp: fix memleak in wm_adsp_buffer_populate
+    - tracing: Fix a warning when allocating buffered events fails
+    - scsi: be2iscsi: Fix a memleak in beiscsi_init_wrb_handle()
+    - ARM: imx: Check return value of devm_kasprintf in imx_mmdc_perf_init
+    - ARM: dts: imx: make gpt node name generic
+    - ARM: dts: imx7: Declare timers compatible with fsl,imx6dl-gpt
+    - ALSA: pcm: fix out-of-bounds in snd_pcm_state_names
+    - nilfs2: prevent WARNING in nilfs_sufile_set_segment_usage()
+    - tracing: Always update snapshot buffer size
+    - tracing: Fix incomplete locking when disabling buffered events
+    - tracing: Fix a possible race when disabling buffered events
+    - packet: Move reference count in packet_sock to atomic_long_t
+    - arm64: dts: mediatek: mt7622: fix memory node warning check
+    - arm64: dts: mediatek: mt8173-evb: Fix regulator-fixed node names
+    - gpiolib: sysfs: Fix error handling on failed export
+    - mmc: core: add helpers mmc_regulator_enable/disable_vqmmc
+    - mmc: sdhci-sprd: Fix vqmmc not shutting down after the card was pulled
+    - usb: gadget: f_hid: fix report descriptor allocation
+    - parport: Add support for Brainboxes IX/UC/PX parallel cards
+    - usb: typec: class: fix typec_altmode_put_partner to put plugs
+    - ARM: PL011: Fix DMA support
+    - serial: sc16is7xx: address RX timeout interrupt errata
+    - serial: 8250_omap: Add earlycon support for the AM654 UART controller
+    - x86/CPU/AMD: Check vendor in the AMD microcode callback
+    - KVM: s390/mm: Properly reset no-dat
+    - nilfs2: fix missing error check for sb_set_blocksize call
+    - io_uring/af_unix: disable sending io_uring over sockets
+    - netlink: don't call ->netlink_bind with table lock held
+    - genetlink: add CAP_NET_ADMIN test for multicast bind
+    - psample: Require 'CAP_NET_ADMIN' when joining "packets" group
+    - drop_monitor: Require 'CAP_SYS_ADMIN' when joining "events" group
+    - tools headers UAPI: Sync linux/perf_event.h with the kernel sources
+    - cifs: Fix non-availability of dedup breaking generic/304
+    - smb: client: fix potential NULL deref in parse_dfs_referrals()
+    - devcoredump : Serialize devcd_del work
+    - devcoredump: Send uevent once devcd is ready
+    - Linux 5.4.264
+  * CVE-2024-0646
+    - net: tls, update curr on splice as well
+  * CVE-2024-0565
+    - smb: client: fix OOB in receive_encrypted_standard()
+  * CVE-2023-51781
+    - appletalk: Fix Use-After-Free in atalk_ioctl
+  * CVE-2023-51782
+    - net/rose: Fix Use-After-Free in rose_ioctl
+  * Focal update: v5.4.263 upstream stable release (LP: #2049084)
+    - driver core: Release all resources during unbind before updating device
+      links
+    - RDMA/irdma: Prevent zero-length STAG registration
+    - PCI: keystone: Drop __init from ks_pcie_add_pcie_{ep,port}()
+    - afs: Make error on cell lookup failure consistent with OpenAFS
+    - drm/panel: simple: Fix Innolux G101ICE-L01 bus flags
+    - drm/panel: simple: Fix Innolux G101ICE-L01 timings
+    - ata: pata_isapnp: Add missing error check for devm_ioport_map()
+    - drm/rockchip: vop: Fix color for RGB888/BGR888 format on VOP full
+    - HID: core: store the unique system identifier in hid_device
+    - HID: fix HID device resource race between HID core and debugging support
+    - ipv4: Correct/silence an endian warning in __ip_do_redirect
+    - net: usb: ax88179_178a: fix failed operations during ax88179_reset
+    - arm/xen: fix xen_vcpu_info allocation alignment
+    - amd-xgbe: handle corner-case during sfp hotplug
+    - amd-xgbe: handle the corner-case during tx completion
+    - amd-xgbe: propagate the correct speed and duplex status
+    - net: axienet: Fix check for partial TX checksum
+    - afs: Return ENOENT if no cell DNS record can be found
+    - afs: Fix file locking on R/O volumes to operate in local mode
+    - nvmet: remove unnecessary ctrl parameter
+    - nvmet: nul-terminate the NQNs passed in the connect command
+    - MIPS: KVM: Fix a build warning about variable set but not used
+    - ext4: add a new helper to check if es must be kept
+    - ext4: factor out __es_alloc_extent() and __es_free_extent()
+    - ext4: use pre-allocated es in __es_insert_extent()
+    - ext4: use pre-allocated es in __es_remove_extent()
+    - ext4: using nofail preallocation in ext4_es_remove_extent()
+    - ext4: using nofail preallocation in ext4_es_insert_delayed_block()
+    - ext4: using nofail preallocation in ext4_es_insert_extent()
+    - ext4: fix slab-use-after-free in ext4_es_insert_extent()
+    - ext4: make sure allocate pending entry not fail
+    - arm64: cpufeature: Extract capped perfmon fields
+    - KVM: arm64: limit PMU version to PMUv3 for ARMv8.1
+    - ACPI: resource: Skip IRQ override on ASUS ExpertBook B1402CVA
+    - bcache: replace a mistaken IS_ERR() by IS_ERR_OR_NULL() in
+      btree_gc_coalesce()
+    - s390/dasd: protect device queue against concurrent access
+    - USB: serial: option: add Luat Air72*U series products
+    - hv_netvsc: Fix race of register_netdevice_notifier and VF register
+    - hv_netvsc: Mark VF as slave before exposing it to user-mode
+    - dm-delay: fix a race between delay_presuspend and delay_bio
+    - bcache: check return value from btree_node_alloc_replacement()
+    - bcache: prevent potential division by zero error
+    - USB: serial: option: add Fibocom L7xx modules
+    - USB: serial: option: fix FM101R-GL defines
+    - USB: serial: option: don't claim interface 4 for ZTE MF290
+    - USB: dwc2: write HCINT with INTMASK applied
+    - usb: dwc3: set the dma max_seg_size
+    - USB: dwc3: qcom: fix resource leaks on probe deferral
+    - USB: dwc3: qcom: fix wakeup after probe deferral
+    - io_uring: fix off-by one bvec index
+    - pinctrl: avoid reload of p state in list iteration
+    - firewire: core: fix possible memory leak in create_units()
+    - mmc: block: Do not lose cache flush during CQE error recovery
+    - ALSA: hda: Disable power-save on KONTRON SinglePC
+    - ALSA: hda/realtek: Headset Mic VREF to 100%
+    - ALSA: hda/realtek: Add supported ALC257 for ChromeOS
+    - dm-verity: align struct dm_verity_fec_io properly
+    - dm verity: don't perform FEC for failed readahead IO
+    - bcache: revert replacing IS_ERR_OR_NULL with IS_ERR
+    - powerpc: Don't clobber f0/vs0 during fp|altivec register save
+    - btrfs: fix off-by-one when checking chunk map includes logical address
+    - btrfs: send: ensure send_fd is writable
+    - btrfs: make error messages more clear when getting a chunk map
+    - Input: xpad - add HyperX Clutch Gladiate Support
+    - net: stmmac: xgmac: Disable FPE MMC interrupts
+    - ravb: Fix races between ravb_tx_timeout_work() and net related ops
+    - net: ravb: Use pm_runtime_resume_and_get()
+    - net: ravb: Start TX queues after HW initialization succeeded
+    - smb3: fix touch -h of symlink
+    - s390/mm: fix phys vs virt confusion in mark_kernel_pXd() functions family
+    - s390/cmma: fix detection of DAT pages
+    - mtd: cfi_cmdset_0001: Support the absence of protection registers
+    - mtd: cfi_cmdset_0001: Byte swap OTP info
+    - fbdev: stifb: Make the STI next font pointer a 32-bit signed offset
+    - ima: annotate iint mutex to avoid lockdep false positive warnings
+    - ovl: skip overlayfs superblocks at global sync
+    - ima: detect changes to the backing overlay file
+    - scsi: qla2xxx: Simplify the code for aborting SCSI commands
+    - scsi: core: Introduce the scsi_cmd_to_rq() function
+    - scsi: qla2xxx: Use scsi_cmd_to_rq() instead of scsi_cmnd.request
+    - scsi: qla2xxx: Fix system crash due to bad pointer access
+    - cpufreq: imx6q: don't warn for disabling a non-existing frequency
+    - cpufreq: imx6q: Don't disable 792 Mhz OPP unnecessarily
+    - mmc: cqhci: Increase recovery halt timeout
+    - mmc: cqhci: Warn of halt or task clear failure
+    - mmc: cqhci: Fix task clearing in CQE error recovery
+    - mmc: core: convert comma to semicolon
+    - mmc: block: Retry commands in CQE error recovery
+    - Linux 5.4.263
+  * Focal update: v5.4.262 upstream stable release (LP: #2049069)
+    - locking/ww_mutex/test: Fix potential workqueue corruption
+    - perf/core: Bail out early if the request AUX area is out of bound
+    - clocksource/drivers/timer-imx-gpt: Fix potential memory leak
+    - clocksource/drivers/timer-atmel-tcb: Fix initialization on SAM9 hardware
+    - x86/mm: Drop the 4 MB restriction on minimal NUMA node memory size
+    - wifi: mac80211_hwsim: fix clang-specific fortify warning
+    - wifi: mac80211: don't return unset power in ieee80211_get_tx_power()
+    - wifi: ath9k: fix clang-specific fortify warnings
+    - wifi: ath10k: fix clang-specific fortify warning
+    - net: annotate data-races around sk->sk_tx_queue_mapping
+    - net: annotate data-races around sk->sk_dst_pending_confirm
+    - wifi: ath10k: Don't touch the CE interrupt registers after power up
+    - Bluetooth: Fix double free in hci_conn_cleanup
+    - platform/x86: thinkpad_acpi: Add battery quirk for Thinkpad X120e
+    - drm/komeda: drop all currently held locks if deadlock happens
+    - drm/amd: Fix UBSAN array-index-out-of-bounds for SMU7
+    - drm/amd: Fix UBSAN array-index-out-of-bounds for Polaris and Tonga
+    - drm/amdgpu: Fix a null pointer access when the smc_rreg pointer is NULL
+    - selftests/efivarfs: create-read: fix a resource leak
+    - crypto: pcrypt - Fix hungtask for PADATA_RESET
+    - RDMA/hfi1: Use FIELD_GET() to extract Link Width
+    - fs/jfs: Add check for negative db_l2nbperpage
+    - fs/jfs: Add validity check for db_maxag and db_agpref
+    - jfs: fix array-index-out-of-bounds in dbFindLeaf
+    - jfs: fix array-index-out-of-bounds in diAlloc
+    - ARM: 9320/1: fix stack depot IRQ stack filter
+    - ALSA: hda: Fix possible null-ptr-deref when assigning a stream
+    - PCI: tegra194: Use FIELD_GET()/FIELD_PREP() with Link Width fields
+    - atm: iphase: Do PCI error checks on own line
+    - scsi: libfc: Fix potential NULL pointer dereference in fc_lport_ptp_setup()
+    - HID: Add quirk for Dell Pro Wireless Keyboard and Mouse KM5221W
+    - tty: vcc: Add check for kstrdup() in vcc_probe()
+    - usb: gadget: f_ncm: Always set current gadget in ncm_bind()
+    - i2c: sun6i-p2wi: Prevent potential division by zero
+    - media: gspca: cpia1: shift-out-of-bounds in set_flicker
+    - media: vivid: avoid integer overflow
+    - gfs2: ignore negated quota changes
+    - media: cobalt: Use FIELD_GET() to extract Link Width
+    - drm/amd/display: Avoid NULL dereference of timing generator
+    - kgdb: Flush console before entering kgdb on panic
+    - ASoC: ti: omap-mcbsp: Fix runtime PM underflow warnings
+    - pwm: Fix double shift bug
+    - wifi: iwlwifi: Use FW rate for non-data frames
+    - NFSv4.1: fix SP4_MACH_CRED protection for pnfs IO
+    - ipvlan: add ipvlan_route_v6_outbound() helper
+    - tty: Fix uninit-value access in ppp_sync_receive()
+    - net: hns3: fix variable may not initialized problem in hns3_init_mac_addr()
+    - tipc: Fix kernel-infoleak due to uninitialized TLV value
+    - ppp: limit MRU to 64K
+    - xen/events: fix delayed eoi list handling
+    - ptp: annotate data-race around q->head and q->tail
+    - bonding: stop the device in bond_setup_by_slave()
+    - net: ethernet: cortina: Fix max RX frame define
+    - net: ethernet: cortina: Handle large frames
+    - net: ethernet: cortina: Fix MTU max setting
+    - netfilter: nf_conntrack_bridge: initialize err to 0
+    - net: stmmac: Rework stmmac_rx()
+    - net: stmmac: fix rx budget limit check
+    - net/mlx5_core: Clean driver version and name
+    - net/mlx5e: Check return value of snprintf writing to fw_version buffer for
+      representors
+    - macvlan: Don't propagate promisc change to lower dev in passthru
+    - tools/power/turbostat: Fix a knl bug
+    - cifs: spnego: add ';' in HOST_KEY_LEN
+    - media: venus: hfi: add checks to perform sanity on queue pointers
+    - randstruct: Fix gcc-plugin performance mode to stay in group
+    - bpf: Fix precision tracking for BPF_ALU | BPF_TO_BE | BPF_END
+    - scsi: megaraid_sas: Increase register read retry rount from 3 to 30 for
+      selected registers
+    - x86/cpu/hygon: Fix the CPU topology evaluation for real
+    - KVM: x86: hyper-v: Don't auto-enable stimer on write from user-space
+    - KVM: x86: Ignore MSR_AMD64_TW_CFG access
+    - audit: don't take task_lock() in audit_exe_compare() code path
+    - audit: don't WARN_ON_ONCE(!current->mm) in audit_exe_compare()
+    - hvc/xen: fix error path in xen_hvc_init() to always register frontend driver
+    - PCI/sysfs: Protect driver's D3cold preference from user space
+    - ACPI: resource: Do IRQ override on TongFang GMxXGxx
+    - mmc: meson-gx: Remove setting of CMD_CFG_ERROR
+    - genirq/generic_chip: Make irq_remove_generic_chip() irqdomain aware
+    - PCI: keystone: Don't discard .remove() callback
+    - PCI: keystone: Don't discard .probe() callback
+    - parisc/pdc: Add width field to struct pdc_model
+    - clk: qcom: ipq8074: drop the CLK_SET_RATE_PARENT flag from PLL clocks
+    - mmc: vub300: fix an error code
+    - PM: hibernate: Use __get_safe_page() rather than touching the list
+    - PM: hibernate: Clean up sync_read handling in snapshot_write_next()
+    - btrfs: don't arbitrarily slow down delalloc if we're committing
+    - jbd2: fix potential data lost in recovering journal raced with synchronizing
+      fs bdev
+    - quota: explicitly forbid quota files from being encrypted
+    - kernel/reboot: emergency_restart: Set correct system_state
+    - i2c: core: Run atomic i2c xfer when !preemptible
+    - mcb: fix error handling for different scenarios when parsing
+    - dmaengine: stm32-mdma: correct desc prep when channel running
+    - mm/cma: use nth_page() in place of direct struct page manipulation
+    - i3c: master: cdns: Fix reading status register
+    - parisc: Prevent booting 64-bit kernels on PA1.x machines
+    - parisc/pgtable: Do not drop upper 5 address bits of physical address
+    - ALSA: info: Fix potential deadlock at disconnection
+    - ALSA: hda/realtek - Enable internal speaker of ASUS K6500ZC
+    - serial: meson: remove redundant initialization of variable id
+    - tty: serial: meson: retrieve port FIFO size from DT
+    - serial: meson: Use platform_get_irq() to get the interrupt
+    - tty: serial: meson: fix hard LOCKUP on crtscts mode
+    - Bluetooth: btusb: add Realtek 8822CE to usb_device_id table
+    - Bluetooth: btusb: Add Realtek RTL8852BE support ID 0x0cb8:0xc559
+    - bluetooth: Add device 0bda:887b to device tables
+    - bluetooth: Add device 13d3:3571 to device tables
+    - Bluetooth: btusb: Add RTW8852BE device 13d3:3570 to device tables
+    - Bluetooth: btusb: Add 0bda:b85b for Fn-Link RTL8852BE
+    - Revert ncsi: Propagate carrier gain/loss events to the NCSI controller
+    - net: dsa: lan9303: consequently nested-lock physical MDIO
+    - i2c: i801: fix potential race in i801_block_transaction_byte_by_byte
+    - media: lirc: drop trailing space from scancode transmit
+    - media: sharp: fix sharp encoding
+    - media: venus: hfi_parser: Add check to keep the number of codecs within
+      range
+    - media: venus: hfi: fix the check to handle session buffer requirement
+    - media: venus: hfi: add checks to handle capabilities from firmware
+    - nfsd: fix file memleak on client_opens_release
+    - ext4: apply umask if ACL support is disabled
+    - ext4: correct offset of gdb backup in non meta_bg group to update_backups
+    - ext4: correct return value of ext4_convert_meta_bg
+    - ext4: correct the start block of counting reserved clusters
+    - ext4: remove gdb backup copy for meta bg in setup_new_flex_group_blocks
+    - drm/amdgpu: fix error handling in amdgpu_bo_list_get()
+    - tracing: Have trace_event_file have ref counters
+    - netfilter: nf_tables: pass context to nft_set_destroy()
+    - netfilter: nftables: rename set element data activation/deactivation
+      functions
+    - netfilter: nf_tables: drop map element references from preparation phase
+    - netfilter: nft_set_rbtree: Switch to node list walk for overlap detection
+    - netfilter: nft_set_rbtree: fix null deref on element insertion
+    - netfilter: nft_set_rbtree: fix overlap expiration walk
+    - netfilter: nf_tables: don't skip expired elements during walk
+    - netfilter: nf_tables: GC transaction API to avoid race with control plane
+    - netfilter: nf_tables: adapt set backend to use GC transaction API
+    - netfilter: nft_set_hash: mark set element as dead when deleting from packet
+      path
+    - netfilter: nf_tables: remove busy mark and gc batch API
+    - netfilter: nf_tables: fix GC transaction races with netns and netlink event
+      exit path
+    - netfilter: nf_tables: GC transaction race with netns dismantle
+    - netfilter: nf_tables: GC transaction race with abort path
+    - netfilter: nf_tables: use correct lock to protect gc_list
+    - netfilter: nf_tables: defer gc run if previous batch is still pending
+    - netfilter: nft_set_rbtree: skip sync GC for new elements in this transaction
+    - netfilter: nft_set_rbtree: use read spinlock to avoid datapath contention
+    - netfilter: nft_set_hash: try later when GC hits EAGAIN on iteration
+    - netfilter: nf_tables: fix memleak when more than 255 elements expired
+    - netfilter: nf_tables: unregister flowtable hooks on netns exit
+    - netfilter: nf_tables: double hook unregistration in netns path
+    - netfilter: nftables: update table flags from the commit phase
+    - netfilter: nf_tables: fix table flag updates
+    - netfilter: nf_tables: disable toggling dormant table state more than once
+    - netfilter: nf_tables: bogus EBUSY when deleting flowtable after flush (for
+      5.4)
+    - Linux 5.4.262
+  * Focal update: v5.4.261 upstream stable release (LP: #2049049)
+    - vfs: fix readahead(2) on block devices
+    - genirq/matrix: Exclude managed interrupts in irq_matrix_allocated()
+    - i40e: fix potential memory leaks in i40e_remove()
+    - tcp: call tcp_try_undo_recovery when an RTOd TFO SYNACK is ACKed
+    - wifi: rtw88: debug: Fix the NULL vs IS_ERR() bug for debugfs_create_file()
+    - wifi: mt76: mt7603: rework/fix rx pse hang check
+    - tcp_metrics: add missing barriers on delete
+    - tcp_metrics: properly set tp->snd_ssthresh in tcp_init_metrics()
+    - tcp_metrics: do not create an entry from tcp_init_metrics()
+    - wifi: rtlwifi: fix EDCA limit set by BT coexistence
+    - can: dev: can_restart(): don't crash kernel if carrier is OK
+    - can: dev: can_restart(): fix race condition between controller restart and
+      netif_carrier_on()
+    - thermal: core: prevent potential string overflow
+    - r8169: use tp_to_dev instead of open code
+    - r8169: fix rare issue with broken rx after link-down on RTL8125
+    - chtls: fix tp->rcv_tstamp initialization
+    - tcp: Remove one extra ktime_get_ns() from cookie_init_timestamp
+    - tcp: fix cookie_init_timestamp() overflows
+    - ACPI: sysfs: Fix create_pnp_modalias() and create_of_modalias()
+    - ipv6: avoid atomic fragment on GSO packets
+    - net: add DEV_STATS_READ() helper
+    - ipvlan: properly track tx_errors
+    - regmap: debugfs: Fix a erroneous check after snprintf()
+    - clk: qcom: clk-rcg2: Fix clock rate overflow for high parent frequencies
+    - clk: qcom: gcc-sm8150: use ARRAY_SIZE instead of specifying num_parents
+    - clk: qcom: gcc-sm8150: Fix gcc_sdcc2_apps_clk_src
+    - clk: imx: Select MXC_CLK for CLK_IMX8QXP
+    - clk: keystone: pll: fix a couple NULL vs IS_ERR() checks
+    - clk: npcm7xx: Fix incorrect kfree
+    - clk: mediatek: clk-mt6779: Add check for mtk_alloc_clk_data
+    - clk: mediatek: clk-mt6797: Add check for mtk_alloc_clk_data
+    - clk: mediatek: clk-mt7629-eth: Add check for mtk_alloc_clk_data
+    - clk: mediatek: clk-mt7629: Add check for mtk_alloc_clk_data
+    - clk: mediatek: clk-mt2701: Add check for mtk_alloc_clk_data
+    - platform/x86: wmi: Fix probe failure when failing to register WMI devices
+    - platform/x86: wmi: remove unnecessary initializations
+    - platform/x86: wmi: Fix opening of char device
+    - hwmon: (coretemp) Fix potentially truncated sysfs attribute name
+    - drm/rockchip: vop: Fix reset of state in duplicate state crtc funcs
+    - drm/rockchip: vop: Fix call to crtc reset helper
+    - drm/radeon: possible buffer overflow
+    - drm/rockchip: cdn-dp: Fix some error handling paths in cdn_dp_probe()
+    - arm64: dts: qcom: sdm845-mtp: fix WiFi configuration
+    - ARM: dts: qcom: mdm9615: populate vsdcc fixed regulator
+    - soc: qcom: llcc cleanup to get rid of sdm845 specific driver file
+    - [Config] remove CONFIG_QCOM_SDM845_LLCC
+    - soc: qcom: Rename llcc-slice to llcc-qcom
+    - [Config] remove llcc-slice module
+    - soc: qcom: llcc: Handle a second device without data corruption
+    - firmware: ti_sci: Replace HTTP links with HTTPS ones
+    - firmware: ti_sci: Mark driver as non removable
+    - clk: scmi: Free scmi_clk allocated when the clocks with invalid info are
+      skipped
+    - hwrng: geode - fix accessing registers
+    - libnvdimm/of_pmem: Use devm_kstrdup instead of kstrdup and check its return
+      value
+    - sched/rt: Provide migrate_disable/enable() inlines
+    - nd_btt: Make BTT lanes preemptible
+    - crypto: caam/qi2 - fix Chacha20 + Poly1305 self test failure
+    - crypto: caam/jr - fix Chacha20 + Poly1305 self test failure
+    - HID: cp2112: Use irqchip template
+    - hid: cp2112: Fix duplicate workqueue initialization
+    - ARM: 9321/1: memset: cast the constant byte to unsigned char
+    - ext4: move 'ix' sanity check to corrent position
+    - scsi: ufs: core: Leave space for '\0' in utf8 desc string
+    - RDMA/hfi1: Workaround truncation compilation error
+    - sh: bios: Revive earlyprintk support
+    - ASoC: Intel: Skylake: Fix mem leak when parsing UUIDs fails
+    - ASoC: ams-delta.c: use component after check
+    - mfd: dln2: Fix double put in dln2_probe
+    - leds: pwm: simplify if condition
+    - leds: pwm: convert to atomic PWM API
+    - leds: pwm: Don't disable the PWM when the LED should be off
+    - ledtrig-cpu: Limit to 8 CPUs
+    - leds: trigger: ledtrig-cpu:: Fix 'output may be truncated' issue for 'cpu'
+    - tty: tty_jobctrl: fix pid memleak in disassociate_ctty()
+    - usb: dwc2: fix possible NULL pointer dereference caused by driver
+      concurrency
+    - dmaengine: ti: edma: handle irq_of_parse_and_map() errors
+    - misc: st_core: Do not call kfree_skb() under spin_lock_irqsave()
+    - tools: iio: privatize globals and functions in iio_generic_buffer.c file
+    - tools: iio: iio_generic_buffer: Fix some integer type and calculation
+    - tools: iio: iio_generic_buffer ensure alignment
+    - USB: usbip: fix stub_dev hub disconnect
+    - dmaengine: pxa_dma: Remove an erroneous BUG_ON() in pxad_free_desc()
+    - f2fs: fix to initialize map.m_pblk in f2fs_precache_extents()
+    - modpost: fix tee MODULE_DEVICE_TABLE built on big-endian host
+    - powerpc/xive: Fix endian conversion size
+    - powerpc/imc-pmu: Use the correct spinlock initializer.
+    - powerpc/pseries: fix potential memory leak in init_cpu_associativity()
+    - i3c: Fix potential refcount leak in i3c_master_register_new_i3c_devs
+    - rtc: pcf85363: fix wrong mask/val parameters in regmap_update_bits call
+    - pcmcia: cs: fix possible hung task and memory leak pccardd()
+    - pcmcia: ds: fix refcount leak in pcmcia_device_add()
+    - pcmcia: ds: fix possible name leak in error path in pcmcia_device_add()
+    - media: bttv: fix use after free error due to btv->timeout timer
+    - media: s3c-camif: Avoid inappropriate kfree()
+    - media: dvb-usb-v2: af9035: fix missing unlock
+    - regmap: prevent noinc writes from clobbering cache
+    - pwm: sti: Avoid conditional gotos
+    - pwm: sti: Reduce number of allocations and drop usage of chip_data
+    - pwm: brcmstb: Utilize appropriate clock APIs in suspend/resume
+    - Input: synaptics-rmi4 - fix use after free in rmi_unregister_function()
+    - llc: verify mac len before reading mac header
+    - tipc: Change nla_policy for bearer-related names to NLA_NUL_STRING
+    - inet: shrink struct flowi_common
+    - dccp: Call security_inet_conn_request() after setting IPv4 addresses.
+    - dccp/tcp: Call security_inet_conn_request() after setting IPv6 addresses.
+    - Fix termination state for idr_for_each_entry_ul()
+    - net: stmmac: xgmac: Enable support for multiple Flexible PPS outputs
+    - net/smc: fix dangling sock under state SMC_APPFINCLOSEWAIT
+    - tg3: power down device only on SYSTEM_POWER_OFF
+    - r8169: respect userspace disabling IFF_MULTICAST
+    - netfilter: xt_recent: fix (increase) ipv6 literal buffer length
+    - netfilter: nft_redir: use `struct nf_nat_range2` throughout and deduplicate
+      eval call-backs
+    - netfilter: nat: fix ipv6 nat redirect with mapped and scoped addresses
+    - drm/syncobj: fix DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE
+    - spi: spi-zynq-qspi: add spi-mem to driver kconfig dependencies
+    - fbdev: imsttfb: Fix error path of imsttfb_probe()
+    - fbdev: imsttfb: fix a resource leak in probe
+    - fbdev: fsl-diu-fb: mark wr_reg_wa() static
+    - Revert "mmc: core: Capture correct oemid-bits for eMMC cards"
+    - btrfs: use u64 for buffer sizes in the tree search ioctls
+    - Linux 5.4.261
+  * Focal update: v5.4.260 upstream stable release (LP: #2049024)
+    - mtd: rawnand: marvell: Ensure program page operations are successful
+    - selftests/ftrace: Add new test case which checks non unique symbol
+    - mcb: Return actual parsed size when reading chameleon table
+    - mcb-lpc: Reallocate memory region to avoid memory overlapping
+    - virtio_balloon: Fix endless deflation and inflation on arm64
+    - virtio-mmio: fix memory leak of vm_dev
+    - r8169: fix the KCSAN reported data-race in rtl_tx while reading
+      TxDescArray[entry].opts1
+    - r8169: fix the KCSAN reported data race in rtl_rx while reading desc->opts1
+    - treewide: Spelling fix in comment
+    - igb: Fix potential memory leak in igb_add_ethtool_nfc_entry
+    - neighbour: fix various data-races
+    - igc: Fix ambiguity in the ethtool advertising
+    - net: ieee802154: adf7242: Fix some potential buffer overflow in
+      adf7242_stats_show()
+    - r8152: Increase USB control msg timeout to 5000ms as per spec
+    - r8152: Run the unload routine if we have errors during probe
+    - r8152: Cancel hw_phy_work if we have an error in probe
+    - tcp: fix wrong RTO timeout when received SACK reneging
+    - gtp: uapi: fix GTPA_MAX
+    - gtp: fix fragmentation needed check with gso
+    - iio: exynos-adc: request second interupt only when touchscreen mode is used
+    - i2c: muxes: i2c-mux-pinctrl: Use of_get_i2c_adapter_by_node()
+    - i2c: muxes: i2c-mux-gpmux: Use of_get_i2c_adapter_by_node()
+    - i2c: muxes: i2c-demux-pinctrl: Use of_get_i2c_adapter_by_node()
+    - i2c: stm32f7: Fix PEC handling in case of SMBUS transfers
+    - i2c: aspeed: Fix i2c bus hang in slave read
+    - nvmem: imx: correct nregs for i.MX6ULL
+    - nvmem: imx: correct nregs for i.MX6SLL
+    - nvmem: imx: correct nregs for i.MX6UL
+    - perf/core: Fix potential NULL deref
+    - clk: Sanitize possible_parent_show to Handle Return Value of
+      of_clk_get_parent_name
+    - i40e: Fix wrong check for I40E_TXR_FLAGS_WB_ON_ITR
+    - x86/i8259: Skip probing when ACPI/MADT advertises PCAT compatibility
+    - drm/dp_mst: Fix NULL deref in get_mst_branch_device_by_guid_helper()
+    - arm64: fix a concurrency issue in emulation_proc_handler()
+    - smbdirect: missing rc checks while waiting for rdma events
+    - f2fs: fix to do sanity check on inode type during garbage collection
+    - nfsd: lock_rename() needs both directories to live on the same fs
+    - x86/mm: Simplify RESERVE_BRK()
+    - x86/mm: Fix RESERVE_BRK() for older binutils
+    - ext4: add two helper functions extent_logical_end() and pa_logical_end()
+    - ext4: avoid overlapping preallocations due to overflow
+    - ext4: fix BUG in ext4_mb_new_inode_pa() due to overflow
+    - driver: platform: Add helper for safer setting of driver_override
+    - rpmsg: Constify local variable in field store macro
+    - rpmsg: Fix kfree() of static memory on setting driver_override
+    - rpmsg: Fix calling device_lock() on non-initialized device
+    - rpmsg: glink: Release driver_override
+    - rpmsg: Fix possible refcount leak in rpmsg_register_device_override()
+    - x86: Fix .brk attribute in linker script
+    - Input: i8042 - add Fujitsu Lifebook E5411 to i8042 quirk table
+    - irqchip/stm32-exti: add missing DT IRQ flag translation
+    - dmaengine: ste_dma40: Fix PM disable depth imbalance in d40_probe
+    - Input: synaptics-rmi4 - handle reset delay when using SMBus trsnsport
+    - fbdev: atyfb: only use ioremap_uc() on i386 and ia64
+    - spi: npcm-fiu: Fix UMA reads when dummy.nbytes == 0
+    - netfilter: nfnetlink_log: silence bogus compiler warning
+    - ASoC: rt5650: fix the wrong result of key button
+    - fbdev: uvesafb: Call cn_del_callback() at the end of uvesafb_exit()
+    - scsi: mpt3sas: Fix in error path
+    - platform/x86: asus-wmi: Change ASUS_WMI_BRN_DOWN code from 0x20 to 0x2e
+    - platform/mellanox: mlxbf-tmfifo: Fix a warning message
+    - net: chelsio: cxgb4: add an error code check in t4_load_phy_fw
+    - ata: ahci: fix enum constants for gcc-13
+    - remove the sx8 block driver
+    - [Config] remove CONFIG_BLK_DEV_SX8
+    - Revert "ARM: dts: Move am33xx and am43xx mmc nodes to sdhci-omap driver"
+    - PCI: Prevent xHCI driver from claiming AMD VanGogh USB3 DRD device
+    - usb: storage: set 1.50 as the lower bcdDevice for older "Super Top"
+      compatibility
+    - tty: 8250: Remove UC-257 and UC-431
+    - tty: 8250: Add support for additional Brainboxes UC cards
+    - tty: 8250: Add support for Brainboxes UP cards
+    - tty: 8250: Add support for Intashield IS-100
+    - Linux 5.4.260
+  * CVE-2023-51779
+    - Bluetooth: af_bluetooth: Fix Use-After-Free in bt_sock_recvmsg
+  * CVE-2023-22995
+    - usb: dwc3: dwc3-qcom: Add missing platform_device_put() in
+      dwc3_qcom_acpi_register_core
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Wed, 21 Feb 2024 11:24:08 +1000
+
+linux-xilinx-zynqmp (5.4.0-1038.42) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1038.42 -proposed tracker (LP: #2052218)
+
+  [ Ubuntu: 5.4.0-172.190 ]
+
+  * focal/linux: 5.4.0-172.190 -proposed tracker (LP: #2052220)
+  * CVE-2023-51781
+    - appletalk: Fix Use-After-Free in atalk_ioctl
+  * CVE-2023-6915
+    - ida: Fix crash in ida_free when the bitmap is empty
+  * CVE-2024-0565
+    - smb: client: fix OOB in receive_encrypted_standard()
+  * CVE-2024-0646
+    - net: tls, update curr on splice as well
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Wed, 14 Feb 2024 09:16:12 +1000
+
+linux-xilinx-zynqmp (5.4.0-1037.41) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1037.41 -proposed tracker (LP: #2048280)
+
+  * Focal update: v5.4.258 upstream stable release (LP: #2042107)
+    - [Config] Update IMA_BLACKLIST_KEYRING and IMA_LOAD_X509
+
+  [ Ubuntu: 5.4.0-171.189 ]
+
+  * focal/linux: 5.4.0-171.189 -proposed tracker (LP: #2048282)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] remove helper scripts
+    - [Packaging] update annotations scripts
+    - debian/dkms-versions -- update from kernel-versions (main/2024.01.08)
+  * Page fault in RDMA ODP triggers BUG_ON during MMU notifier registration
+    (LP: #2046534)
+    - RDMA/odp: Ensure the mm is still alive before creating an implicit child
+  * Hotplugging SCSI disk in QEMU VM fails (LP: #2047382)
+    - Revert "PCI: acpiphp: Reassign resources on bridge if necessary"
+  * CVE-2023-6040
+    - netfilter: nf_tables: Reject tables of unsupported family
+  * kernel_selftests failures on kernel-P10d-LPAR10.ppc64el.10
+    (LP: #2032641)
+    - selftests: Skip TM tests on synthetic TM implementations
+  * [Debian] autoreconstruct - Do not generate chmod -x for deleted  files
+    (LP: #2045562)
+    - [Debian] autoreconstruct - Do not generate chmod -x for deleted files
+  * CVE-2023-6931
+    - perf/core: Add a new read format to get a number of lost samples
+    - perf: Fix perf_event_validate_size()
+    - perf: Fix perf_event_validate_size() lockdep splat
+  * CVE-2023-6932
+    - ipv4: igmp: fix refcnt uaf issue when receiving igmp query packet
+  * CVE-2023-6606
+    - smb: client: fix OOB in smbCalcSize()
+  * CVE-2023-45863
+    - kobject: Fix slab-out-of-bounds in fill_kobj_path()
+  * Focal update: v5.4.259 upstream stable release (LP: #2043724)
+    - RDMA/cxgb4: Check skb value for failure to allocate
+    - lib/test_meminit: fix off-by-one error in test_pages()
+    - pwm: hibvt: Explicitly set .polarity in .get_state()
+    - HID: logitech-hidpp: Fix kernel crash on receiver USB disconnect
+    - quota: Fix slow quotaoff
+    - net: prevent address rewrite in kernel_bind()
+    - drm: etvnaviv: fix bad backport leading to warning
+    - drm/msm/dsi: skip the wait for video mode done if not applicable
+    - ravb: Fix up dma_free_coherent() call in ravb_remove()
+    - ieee802154: ca8210: Fix a potential UAF in ca8210_probe
+    - mlxsw: fix mlxsw_sp2_nve_vxlan_learning_set() return type
+    - xen-netback: use default TX queue size for vifs
+    - drm/vmwgfx: fix typo of sizeof argument
+    - ixgbe: fix crash with empty VF macvlan list
+    - net: nfc: fix races in nfc_llcp_sock_get() and nfc_llcp_sock_get_sn()
+    - nfc: nci: assert requested protocol is valid
+    - workqueue: Override implicit ordered attribute in
+      workqueue_apply_unbound_cpumask()
+    - dmaengine: stm32-mdma: abort resume if no ongoing transfer
+    - usb: xhci: xhci-ring: Use sysdev for mapping bounce buffer
+    - net: usb: dm9601: fix uninitialized variable use in dm9601_mdio_read
+    - usb: dwc3: Soft reset phy on probe for host
+    - usb: musb: Get the musb_qh poniter after musb_giveback
+    - usb: musb: Modify the "HWVers" register address
+    - iio: pressure: bmp280: Fix NULL pointer exception
+    - iio: pressure: dps310: Adjust Timeout Settings
+    - iio: pressure: ms5611: ms5611_prom_is_valid false negative bug
+    - mcb: remove is_added flag from mcb_device struct
+    - libceph: use kernel_connect()
+    - ceph: fix incorrect revoked caps assert in ceph_fill_file_size()
+    - Input: powermate - fix use-after-free in powermate_config_complete
+    - Input: psmouse - fix fast_reconnect function for PS/2 mode
+    - Input: xpad - add PXN V900 support
+    - cgroup: Remove duplicates in cgroup v1 tasks file
+    - pinctrl: avoid unsafe code pattern in find_pinctrl()
+    - usb: gadget: udc-xilinx: replace memcpy with memcpy_toio
+    - usb: gadget: ncm: Handle decoding of multiple NTB's in unwrap call
+    - x86/cpu: Fix AMD erratum #1485 on Zen4-based CPUs
+    - dmaengine: mediatek: Fix deadlock caused by synchronize_irq()
+    - powerpc/8xx: Fix pte_access_permitted() for PAGE_NONE
+    - powerpc/64e: Fix wrong test in __ptep_test_and_clear_young()
+    - ravb: Fix use-after-free issue in ravb_tx_timeout_work()
+    - Documentation: sysctl: align cells in second content column
+    - usb: hub: Guard against accesses to uninitialized BOS descriptors
+    - Bluetooth: hci_event: Ignore NULL link key
+    - Bluetooth: Reject connection with the device which has same BD_ADDR
+    - Bluetooth: Fix a refcnt underflow problem for hci_conn
+    - Bluetooth: vhci: Fix race when opening vhci device
+    - Bluetooth: hci_event: Fix coding style
+    - Bluetooth: avoid memcmp() out of bounds warning
+    - ice: fix over-shifted variable
+    - nfc: nci: fix possible NULL pointer dereference in send_acknowledge()
+    - regmap: fix NULL deref on lookup
+    - KVM: x86: Mask LVTPC when handling a PMI
+    - netfilter: nft_payload: fix wrong mac header matching
+    - qed: fix LL2 RX buffer allocation
+    - xfrm: fix a data-race in xfrm_gen_index()
+    - xfrm: interface: use DEV_STATS_INC()
+    - net: ipv4: fix return value check in esp_remove_trailer
+    - net: ipv6: fix return value check in esp_remove_trailer
+    - net: rfkill: gpio: prevent value glitch during probe
+    - tcp: fix excessive TLP and RACK timeouts from HZ rounding
+    - tcp: tsq: relax tcp_small_queue_check() when rtx queue contains a single skb
+    - tun: prevent negative ifindex
+    - ipv4: fib: annotate races around nh->nh_saddr_genid and nh->nh_saddr
+    - net: usb: smsc95xx: Fix an error code in smsc95xx_reset()
+    - i40e: prevent crash on probe if hw registers have invalid values
+    - net/sched: sch_hfsc: upgrade 'rt' to 'sc' when it becomes a inner curve
+    - neighbor: tracing: Move pin6 inside CONFIG_IPV6=y section
+    - netfilter: nft_set_rbtree: .deactivate fails if element has expired
+    - net: pktgen: Fix interface flags printing
+    - resource: Add irqresource_disabled()
+    - ACPI: Drop acpi_dev_irqresource_disabled()
+    - ACPI: resource: Skip IRQ override on Asus Vivobook S5602ZA
+    - ACPI: resource: Add Asus ExpertBook B2502 to Asus quirks
+    - ACPI: resource: Skip IRQ override on Asus Expertbook B2402CBA
+    - ACPI: resource: Skip IRQ override on ASUS ExpertBook B1502CBA
+    - ACPI: resource: Skip IRQ override on ASUS ExpertBook B1402CBA
+    - ARM: dts: ti: omap: Fix noisy serial with overrun-throttle-ms for mapphone
+    - btrfs: return -EUCLEAN for delayed tree ref with a ref count not equals to 1
+    - btrfs: initialize start_slot in btrfs_log_prealloc_extents
+    - i2c: mux: Avoid potential false error message in i2c_mux_add_adapter
+    - overlayfs: set ctime when setting mtime and atime
+    - gpio: timberdale: Fix potential deadlock on &tgpio->lock
+    - ata: libata-eh: Fix compilation warning in ata_eh_link_report()
+    - tracing: relax trace_event_eval_update() execution with cond_resched()
+    - HID: holtek: fix slab-out-of-bounds Write in holtek_kbd_input_event
+    - Bluetooth: Avoid redundant authentication
+    - Bluetooth: hci_core: Fix build warnings
+    - wifi: mac80211: allow transmitting EAPOL frames with tainted key
+    - wifi: cfg80211: avoid leaking stack data into trace
+    - regulator/core: Revert "fix kobject release warning and memory leak in
+      regulator_register()"
+    - sky2: Make sure there is at least one frag_addr available
+    - drm: panel-orientation-quirks: Add quirk for One Mix 2S
+    - btrfs: fix some -Wmaybe-uninitialized warnings in ioctl.c
+    - HID: multitouch: Add required quirk for Synaptics 0xcd7e device
+    - Bluetooth: hci_event: Fix using memcmp when comparing keys
+    - mtd: rawnand: qcom: Unmap the right resource upon probe failure
+    - mtd: spinand: micron: correct bitmask for ecc status
+    - mtd: physmap-core: Restore map_rom fallback
+    - mmc: core: sdio: hold retuning if sdio in 1-bit mode
+    - mmc: core: Capture correct oemid-bits for eMMC cards
+    - Revert "pinctrl: avoid unsafe code pattern in find_pinctrl()"
+    - ACPI: irq: Fix incorrect return value in acpi_register_gsi()
+    - USB: serial: option: add Telit LE910C4-WWX 0x1035 composition
+    - USB: serial: option: add entry for Sierra EM9191 with new firmware
+    - USB: serial: option: add Fibocom to DELL custom modem FM101R-GL
+    - s390/pci: fix iommu bitmap allocation
+    - gpio: vf610: set value before the direction to avoid a glitch
+    - ASoC: pxa: fix a memory leak in probe()
+    - phy: mapphone-mdm6600: Fix runtime disable on probe
+    - phy: mapphone-mdm6600: Fix runtime PM for remove
+    - phy: mapphone-mdm6600: Fix pinctrl_pm handling for sleep pins
+    - Bluetooth: hci_sock: fix slab oob read in create_monitor_event
+    - Bluetooth: hci_sock: Correctly bounds check and pad HCI_MON_NEW_INDEX name
+    - xfrm6: fix inet6_dev refcount underflow problem
+    - Linux 5.4.259
+  * Focal update: v5.4.258 upstream stable release (LP: #2042107)
+    - NFS/pNFS: Report EINVAL errors from connect() to the server
+    - SUNRPC: Mark the cred for revalidation if the server rejects it
+    - tracing: Increase trace array ref count on enable and filter files
+    - ata: libahci: clear pending interrupt status
+    - ext4: remove the 'group' parameter of ext4_trim_extent
+    - ext4: add new helper interface ext4_try_to_trim_range()
+    - ext4: scope ret locally in ext4_try_to_trim_range()
+    - ext4: change s_last_trim_minblks type to unsigned long
+    - ext4: mark group as trimmed only if it was fully scanned
+    - ext4: replace the traditional ternary conditional operator with with
+      max()/min()
+    - ext4: move setting of trimmed bit into ext4_try_to_trim_range()
+    - ext4: do not let fstrim block system suspend
+    - ASoC: meson: spdifin: start hw on dai probe
+    - netfilter: nf_tables: disallow element removal on anonymous sets
+    - bpf: Avoid deadlock when using queue and stack maps from NMI
+    - selftests/tls: Add {} to avoid static checker warning
+    - selftests: tls: swap the TX and RX sockets in some tests
+    - ASoC: imx-audmix: Fix return error with devm_clk_get()
+    - i40e: Fix for persistent lldp support
+    - SAUCE: Revert "UBUNTU: SAUCE: i40e Fix GPF when deleting VMs"
+    - i40e: Remove scheduling while atomic possibility
+    - i40e: Fix warning message and call stack during rmmod i40e driver
+    - i40e: Fix VF VLAN offloading when port VLAN is configured
+    - powerpc/perf/hv-24x7: Update domain value check
+    - dccp: fix dccp_v4_err()/dccp_v6_err() again
+    - net: hns3: add 5ms delay before clear firmware reset irq source
+    - net: bridge: use DEV_STATS_INC()
+    - team: fix null-ptr-deref when team device type is changed
+    - net: rds: Fix possible NULL-pointer dereference
+    - gpio: tb10x: Fix an error handling path in tb10x_gpio_probe()
+    - i2c: mux: demux-pinctrl: check the return value of devm_kstrdup()
+    - Input: i8042 - add quirk for TUXEDO Gemini 17 Gen1/Clevo PD70PN
+    - scsi: qla2xxx: Fix update_fcport for current_topology
+    - scsi: qla2xxx: Fix deletion race condition
+    - drm/amd/display: Reinstate LFC optimization
+    - drm/amd/display: Fix LFC multiplier changing erratically
+    - drm/amd/display: prevent potential division by zero errors
+    - ata: libata: disallow dev-initiated LPM transitions to unsupported states
+    - MIPS: Alchemy: only build mmc support helpers if au1xmmc is enabled
+    - clk: tegra: fix error return case for recalc_rate
+    - ARM: dts: ti: omap: motorola-mapphone: Fix abe_clkctrl warning on boot
+    - bus: ti-sysc: Fix SYSC_QUIRK_SWSUP_SIDLE_ACT handling for uart wake-up
+    - xtensa: add default definition for XCHAL_HAVE_DIV32
+    - xtensa: iss/network: make functions static
+    - xtensa: boot: don't add include-dirs
+    - xtensa: boot/lib: fix function prototypes
+    - gpio: pmic-eic-sprd: Add can_sleep flag for PMIC EIC chip
+    - parisc: sba: Fix compile warning wrt list of SBA devices
+    - parisc: iosapic.c: Fix sparse warnings
+    - parisc: drivers: Fix sparse warning
+    - parisc: irq: Make irq_stack_union static to avoid sparse warning
+    - selftests/ftrace: Correctly enable event in instance-event.tc
+    - ring-buffer: Avoid softlockup in ring_buffer_resize()
+    - ata: libata-eh: do not clear ATA_PFLAG_EH_PENDING in ata_eh_reset()
+    - spi: nxp-fspi: reset the FLSHxCR1 registers
+    - bpf: Clarify error expectations from bpf_clone_redirect
+    - powerpc/watchpoints: Annotate atomic context in more places
+    - ncsi: Propagate carrier gain/loss events to the NCSI controller
+    - fbdev/sh7760fb: Depend on FB=y
+    - nvme-pci: do not set the NUMA node of device if it has none
+    - watchdog: iTCO_wdt: No need to stop the timer in probe
+    - watchdog: iTCO_wdt: Set NO_REBOOT if the watchdog is not already running
+    - i40e: improve locking of mac_filter_hash
+    - i40e: always propagate error value in i40e_set_vsi_promisc()
+    - i40e: fix return of uninitialized aq_ret in i40e_set_vsi_promisc
+    - smack: Record transmuting in smk_transmuted
+    - smack: Retrieve transmuting information in smack_inode_getsecurity()
+    - Smack:- Use overlay inode label in smack_inode_copy_up()
+    - serial: 8250_port: Check IRQ data before use
+    - nilfs2: fix potential use after free in nilfs_gccache_submit_read_data()
+    - ALSA: hda: Disable power save for solving pop issue on Lenovo ThinkCentre
+      M70q
+    - ata: libata-scsi: ignore reserved bits for REPORT SUPPORTED OPERATION CODES
+    - i2c: i801: unregister tco_pdev in i801_probe() error path
+    - ring-buffer: Update "shortest_full" in polling
+    - btrfs: properly report 0 avail for very full file systems
+    - net: thunderbolt: Fix TCPv6 GSO checksum calculation
+    - ata: libata-core: Fix ata_port_request_pm() locking
+    - ata: libata-core: Fix port and device removal
+    - ata: libata-core: Do not register PM operations for SAS ports
+    - ata: libata-sata: increase PMP SRST timeout to 10s
+    - fs: binfmt_elf_efpic: fix personality for ELF-FDPIC
+    - rbd: move rbd_dev_refresh() definition
+    - rbd: decouple header read-in from updating rbd_dev->header
+    - rbd: decouple parent info read-in from updating rbd_dev
+    - rbd: take header_rwsem in rbd_dev_refresh() only when updating
+    - Revert "PCI: qcom: Disable write access to read only registers for IP
+      v2.3.3"
+    - scsi: zfcp: Fix a double put in zfcp_port_enqueue()
+    - qed/red_ll2: Fix undefined behavior bug in struct qed_ll2_info
+    - wifi: mwifiex: Fix tlv_buf_left calculation
+    - net: replace calls to sock->ops->connect() with kernel_connect()
+    - net: prevent rewrite of msg_name in sock_sendmsg()
+    - wifi: iwlwifi: dbg_ini: fix structure packing
+    - wifi: mwifiex: Fix oob check condition in mwifiex_process_rx_packet
+    - drivers/net: process the result of hdlc_open() and add call of hdlc_close()
+      in uhdlc_close()
+    - wifi: mt76: mt76x02: fix MT76x0 external LNA gain handling
+    - regmap: rbtree: Fix wrong register marked as in-cache when creating new node
+    - ima: Finish deprecation of IMA_TRUSTED_KEYRING Kconfig
+    - scsi: target: core: Fix deadlock due to recursive locking
+    - NFS4: Trace state recovery operation
+    - NFS: Add a helper nfs_client_for_each_server()
+    - NFSv4: Fix a nfs4_state_manager() race
+    - modpost: add missing else to the "of" check
+    - net: fix possible store tearing in neigh_periodic_work()
+    - ipv4, ipv6: Fix handling of transhdrlen in __ip{,6}_append_data()
+    - net: dsa: mv88e6xxx: Avoid EEPROM timeout when EEPROM is absent
+    - net: usb: smsc75xx: Fix uninit-value access in __smsc75xx_read_reg
+    - net: nfc: llcp: Add lock when modifying device list
+    - netfilter: handle the connecting collision properly in
+      nf_conntrack_proto_sctp
+    - net: stmmac: dwmac-stm32: fix resume on STM32 MCU
+    - tcp: fix quick-ack counting to count actual ACKs of new data
+    - tcp: fix delayed ACKs for MSS boundary condition
+    - sctp: update transport state when processing a dupcook packet
+    - sctp: update hb timer immediately after users change hb_interval
+    - cpupower: add Makefile dependencies for install targets
+    - RDMA/core: Require admin capabilities to set system parameters
+    - IB/mlx4: Fix the size of a buffer in add_port_entries()
+    - gpio: aspeed: fix the GPIO number passed to pinctrl_gpio_set_config()
+    - gpio: pxa: disable pinctrl calls for MMP_GPIO
+    - RDMA/cma: Fix truncation compilation warning in make_cma_ports
+    - RDMA/uverbs: Fix typo of sizeof argument
+    - RDMA/siw: Fix connection failure handling
+    - RDMA/mlx5: Fix NULL string error
+    - parisc: Restore __ldcw_align for PA-RISC 2.0 processors
+    - NFS: Fix a race in __nfs_list_for_each_server()
+    - ima: rework CONFIG_IMA dependency block
+    - [Config] Update IMA_BLACKLIST_KEYRING and IMA_LOAD_X509
+    - xen/events: replace evtchn_rwlock with RCU
+    - Linux 5.4.258
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Thu, 18 Jan 2024 14:59:22 +1000
+
+linux-xilinx-zynqmp (5.4.0-1036.40) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1036.40 -proposed tracker (LP: #2048652)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] remove helper scripts
+
+  [ Ubuntu: 5.4.0-170.188 ]
+
+  * focal/linux: 5.4.0-170.188 -proposed tracker (LP: #2048654)
+  * CVE-2023-6040
+    - netfilter: nf_tables: Reject tables of unsupported family
+  * CVE-2023-6606
+    - smb: client: fix OOB in smbCalcSize()
+  * CVE-2023-6932
+    - ipv4: igmp: fix refcnt uaf issue when receiving igmp query packet
+  * CVE-2023-6931
+    - perf/core: Add a new read format to get a number of lost samples
+    - perf: Fix perf_event_validate_size()
+    - perf: Fix perf_event_validate_size() lockdep splat
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Tue, 16 Jan 2024 16:16:33 +1000
+
+linux-xilinx-zynqmp (5.4.0-1035.39) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1035.39 -proposed tracker (LP: #2041649)
+
+  * Focal update: v5.4.257 upstream stable release (LP: #2040284)
+    - [Config] Update annotations after CONFIG_IMA_TRUSTED_KEYRING removal
+
+  [ Ubuntu: 5.4.0-169.187 ]
+
+  * focal/linux: 5.4.0-169.187 -proposed tracker (LP: #2044375)
+  * USB bus error after upgrading to proposed kernel on lunar, jammy and focal
+    (LP: #2043197)
+    - USB: core: Fix oversight in SuperSpeed initialization
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync git-ubuntu-log
+    - [Packaging] resync update-dkms-versions helper
+    - [Packaging] update annotations scripts
+
+  [ Ubuntu: 5.4.0-168.186 ]
+
+  * focal/linux: 5.4.0-168.186 -proposed tracker (LP: #2041652)
+  * Focal update: v5.4.257 upstream stable release (LP: #2040284)
+    - erofs: ensure that the post-EOF tails are all zeroed
+    - ARM: pxa: remove use of symbol_get()
+    - mmc: au1xmmc: force non-modular build and remove symbol_get usage
+    - net: enetc: use EXPORT_SYMBOL_GPL for enetc_phc_index
+    - rtc: ds1685: use EXPORT_SYMBOL_GPL for ds1685_rtc_poweroff
+    - modules: only allow symbol_get of EXPORT_SYMBOL_GPL modules
+    - USB: serial: option: add Quectel EM05G variant (0x030e)
+    - USB: serial: option: add FOXCONN T99W368/T99W373 product
+    - HID: wacom: remove the battery when the EKR is off
+    - staging: rtl8712: fix race condition
+    - Bluetooth: btsdio: fix use after free bug in btsdio_remove due to race
+      condition
+    - serial: sc16is7xx: fix bug when first setting GPIO direction
+    - firmware: stratix10-svc: Fix an NULL vs IS_ERR() bug in probe
+    - fsi: master-ast-cf: Add MODULE_FIRMWARE macro
+    - nilfs2: fix general protection fault in nilfs_lookup_dirty_data_buffers()
+    - nilfs2: fix WARNING in mark_buffer_dirty due to discarded buffer reuse
+    - pinctrl: amd: Don't show `Invalid config param` errors
+    - 9p: virtio: make sure 'offs' is initialized in zc_request
+    - ASoC: da7219: Flush pending AAD IRQ when suspending
+    - ASoC: da7219: Check for failure reading AAD IRQ events
+    - ethernet: atheros: fix return value check in atl1c_tso_csum()
+    - vxlan: generalize vxlan_parse_gpe_hdr and remove unused args
+    - m68k: Fix invalid .section syntax
+    - s390/dasd: use correct number of retries for ERP requests
+    - s390/dasd: fix hanging device after request requeue
+    - fs/nls: make load_nls() take a const parameter
+    - ASoc: codecs: ES8316: Fix DMIC config
+    - ASoC: atmel: Fix the 8K sample parameter in I2SC master
+    - platform/x86: intel: hid: Always call BTNL ACPI method
+    - platform/x86: huawei-wmi: Silence ambient light sensor
+    - security: keys: perform capable check only on privileged operations
+    - clk: fixed-mmio: make COMMON_CLK_FIXED_MMIO depend on HAS_IOMEM
+    - net: usb: qmi_wwan: add Quectel EM05GV2
+    - idmaengine: make FSL_EDMA and INTEL_IDMA64 depends on HAS_IOMEM
+    - scsi: qedi: Fix potential deadlock on &qedi_percpu->p_work_lock
+    - netlabel: fix shift wrapping bug in netlbl_catmap_setlong()
+    - bnx2x: fix page fault following EEH recovery
+    - sctp: handle invalid error codes without calling BUG()
+    - cifs: add a warning when the in-flight count goes negative
+    - scsi: storvsc: Always set no_report_opcodes
+    - ALSA: seq: oss: Fix racy open/close of MIDI devices
+    - platform/mellanox: Fix mlxbf-tmfifo not handling all virtio CONSOLE
+      notifications
+    - powerpc/32s: Fix assembler warning about r0
+    - udf: Check consistency of Space Bitmap Descriptor
+    - udf: Handle error when adding extent to a file
+    - Revert "net: macsec: preserve ingress frame ordering"
+    - reiserfs: Check the return value from __getblk()
+    - eventfd: Export eventfd_ctx_do_read()
+    - eventfd: prevent underflow for eventfd semaphores
+    - new helper: lookup_positive_unlocked()
+    - fs: Fix error checking for d_hash_and_lookup()
+    - tmpfs: verify {g,u}id mount options correctly
+    - OPP: Fix passing 0 to PTR_ERR in _opp_attach_genpd()
+    - x86/asm: Make more symbols local
+    - x86/boot: Annotate local functions
+    - x86/decompressor: Don't rely on upper 32 bits of GPRs being preserved
+    - perf/imx_ddr: don't enable counter0 if none of 4 counters are used
+    - cpufreq: powernow-k8: Use related_cpus instead of cpus in driver.exit()
+    - bpf: Clear the probe_addr for uprobe
+    - tcp: tcp_enter_quickack_mode() should be static
+    - regmap: rbtree: Use alloc_flags for memory allocations
+    - spi: tegra20-sflash: fix to check return value of platform_get_irq() in
+      tegra_sflash_probe()
+    - can: gs_usb: gs_usb_receive_bulk_callback(): count RX overflow errors also
+      in case of OOM
+    - wifi: mwifiex: Fix OOB and integer underflow when rx packets
+    - mwifiex: switch from 'pci_' to 'dma_' API
+    - wifi: mwifiex: fix error recovery in PCIE buffer descriptor management
+    - crypto: stm32 - Properly handle pm_runtime_get failing
+    - Bluetooth: nokia: fix value check in nokia_bluetooth_serdev_probe()
+    - crypto: caam - fix unchecked return value error
+    - hwrng: iproc-rng200 - use semicolons rather than commas to separate
+      statements
+    - hwrng: iproc-rng200 - Implement suspend and resume calls
+    - lwt: Fix return values of BPF xmit ops
+    - lwt: Check LWTUNNEL_XMIT_CONTINUE strictly
+    - fs: ocfs2: namei: check return value of ocfs2_add_entry()
+    - wifi: mwifiex: fix memory leak in mwifiex_histogram_read()
+    - wifi: mwifiex: Fix missed return in oob checks failed path
+    - wifi: ath9k: fix races between ath9k_wmi_cmd and ath9k_wmi_ctrl_rx
+    - wifi: ath9k: protect WMI command response buffer replacement with a lock
+    - wifi: mwifiex: avoid possible NULL skb pointer dereference
+    - wifi: ath9k: use IS_ERR() with debugfs_create_dir()
+    - net: arcnet: Do not call kfree_skb() under local_irq_disable()
+    - mlxsw: i2c: Fix chunk size setting in output mailbox buffer
+    - mlxsw: i2c: Limit single transaction buffer size
+    - netrom: Deny concurrent connect().
+    - drm/bridge: tc358764: Fix debug print parameter order
+    - quota: avoid increasing DQST_LOOKUPS when iterating over dirty/inuse list
+    - quota: factor out dquot_write_dquot()
+    - quota: rename dquot_active() to inode_quota_active()
+    - quota: add new helper dquot_active()
+    - quota: fix dqput() to follow the guarantees dquot_srcu should provide
+    - drm/amdgpu: avoid integer overflow warning in amdgpu_device_resize_fb_bar()
+    - ARM: dts: BCM53573: Drop nonexistent "default-off" LED trigger
+    - ARM: dts: BCM53573: Add cells sizes to PCIe node
+    - ARM: dts: BCM53573: Use updated "spi-gpio" binding properties
+    - drm/etnaviv: fix dumping of active MMU context
+    - ARM: dts: s3c6410: move fixed clocks under root node in Mini6410
+    - ARM: dts: s3c6410: align node SROM bus node name with dtschema in Mini6410
+    - ARM: dts: s3c64xx: align pinctrl with dtschema
+    - ARM: dts: samsung: s3c6410-mini6410: correct ethernet reg addresses (split)
+    - ARM: dts: s5pv210: add RTC 32 KHz clock in SMDKV210
+    - ARM: dts: s5pv210: use defines for IRQ flags in SMDKV210
+    - ARM: dts: s5pv210: correct ethernet unit address in SMDKV210
+    - ARM: dts: s5pv210: add dummy 5V regulator for backlight on SMDKv210
+    - ARM: dts: samsung: s5pv210-smdkv210: correct ethernet reg addresses (split)
+    - drm: adv7511: Fix low refresh rate register for ADV7533/5
+    - ARM: dts: BCM53573: Fix Ethernet info for Luxul devices
+    - arm64: dts: qcom: sdm845: Add missing RPMh power domain to GCC
+    - drm/amdgpu: Update min() to min_t() in 'amdgpu_info_ioctl'
+    - md/bitmap: don't set max_write_behind if there is no write mostly device
+    - md/md-bitmap: hold 'reconfig_mutex' in backlog_store()
+    - drm/tegra: Remove superfluous error messages around platform_get_irq()
+    - drm/tegra: dpaux: Fix incorrect return value of platform_get_irq
+    - of: unittest: fix null pointer dereferencing in
+      of_unittest_find_node_by_name()
+    - drm/armada: Fix off-by-one error in armada_overlay_get_property()
+    - drm/panel: simple: Add missing connector type and pixel format for AUO
+      T215HVN01
+    - ima: Remove deprecated IMA_TRUSTED_KEYRING Kconfig
+    - [Config] Update annotations after CONFIG_IMA_TRUSTED_KEYRING removal
+    - drm/msm/mdp5: Don't leak some plane state
+    - smackfs: Prevent underflow in smk_set_cipso()
+    - audit: fix possible soft lockup in __audit_inode_child()
+    - drm/mediatek: Fix potential memory leak if vmap() fail
+    - of: unittest: Fix overlay type in apply/revert check
+    - ALSA: ac97: Fix possible error value of *rac97
+    - ipmi:ssif: Add check for kstrdup
+    - ipmi:ssif: Fix a memory leak when scanning for an adapter
+    - drivers: clk: keystone: Fix parameter judgment in _of_pll_clk_init()
+    - clk: sunxi-ng: Modify mismatched function name
+    - PCI: Mark NVIDIA T4 GPUs to avoid bus reset
+    - PCI: pciehp: Use RMW accessors for changing LNKCTL
+    - PCI/ASPM: Use RMW accessors for changing LNKCTL
+    - clk: imx: composite-8m: fix clock pauses when set_rate would be a no-op
+    - powerpc/fadump: reset dump area size if fadump memory reserve fails
+    - PCI: Add #defines for Enter Compliance, Transmit Margin
+    - drm/amdgpu: Correct Transmit Margin masks
+    - drm/amdgpu: Replace numbers with PCI_EXP_LNKCTL2 definitions
+    - drm/amdgpu: Prefer pcie_capability_read_word()
+    - drm/amdgpu: Use RMW accessors for changing LNKCTL
+    - drm/radeon: Correct Transmit Margin masks
+    - drm/radeon: Replace numbers with PCI_EXP_LNKCTL2 definitions
+    - drm/radeon: Prefer pcie_capability_read_word()
+    - drm/radeon: Use RMW accessors for changing LNKCTL
+    - wifi: ath10k: Use RMW accessors for changing LNKCTL
+    - nfs/blocklayout: Use the passed in gfp flags
+    - powerpc/iommu: Fix notifiers being shared by PCI and VIO buses
+    - jfs: validate max amount of blocks before allocation.
+    - fs: lockd: avoid possible wrong NULL parameter
+    - NFSD: da_addr_body field missing in some GETDEVICEINFO replies
+    - NFS: Guard against READDIR loop when entry names exceed MAXNAMELEN
+    - media: v4l2-fwnode: fix v4l2_fwnode_parse_link handling
+    - media: v4l2-fwnode: simplify v4l2_fwnode_parse_link
+    - media: v4l2-core: Fix a potential resource leak in v4l2_fwnode_parse_link()
+    - drivers: usb: smsusb: fix error handling code in smsusb_init_device
+    - media: dib7000p: Fix potential division by zero
+    - media: dvb-usb: m920x: Fix a potential memory leak in m920x_i2c_xfer()
+    - media: cx24120: Add retval check for cx24120_message_send()
+    - media: mediatek: vcodec: Return NULL if no vdec_fb is found
+    - usb: phy: mxs: fix getting wrong state with mxs_phy_is_otg_host()
+    - scsi: iscsi: Add strlen() check in iscsi_if_set{_host}_param()
+    - scsi: be2iscsi: Add length check when parsing nlattrs
+    - scsi: qla4xxx: Add length check when parsing nlattrs
+    - serial: sprd: getting port index via serial aliases only
+    - serial: sprd: remove redundant sprd_port cleanup
+    - serial: sprd: Assign sprd_port after initialized to avoid wrong access
+    - serial: sprd: Fix DMA buffer leak issue
+    - x86/APM: drop the duplicate APM_MINOR_DEV macro
+    - scsi: qedf: Do not touch __user pointer in
+      qedf_dbg_stop_io_on_error_cmd_read() directly
+    - scsi: qedf: Do not touch __user pointer in qedf_dbg_debug_cmd_read()
+      directly
+    - scsi: qedf: Do not touch __user pointer in qedf_dbg_fp_int_cmd_read()
+      directly
+    - coresight: tmc: Explicit type conversions to prevent integer overflow
+    - dma-buf/sync_file: Fix docs syntax
+    - driver core: test_async: fix an error code
+    - IB/uverbs: Fix an potential error pointer dereference
+    - iommu/vt-d: Fix to flush cache of PASID directory table
+    - media: go7007: Remove redundant if statement
+    - USB: gadget: f_mass_storage: Fix unused variable warning
+    - media: i2c: ov5640: Configure HVP lines in s_power callback
+    - media: ov5640: Enable MIPI interface in ov5640_set_power_mipi()
+    - media: i2c: ov2680: Set V4L2_CTRL_FLAG_MODIFY_LAYOUT on flips
+    - media: ov2680: Remove auto-gain and auto-exposure controls
+    - media: ov2680: Fix ov2680_bayer_order()
+    - media: ov2680: Fix vflip / hflip set functions
+    - media: ov2680: Fix regulators being left enabled on ov2680_power_on() errors
+    - scsi: core: Use 32-bit hostnum in scsi_host_lookup()
+    - scsi: fcoe: Fix potential deadlock on &fip->ctlr_lock
+    - serial: tegra: handle clk prepare error in tegra_uart_hw_init()
+    - amba: bus: fix refcount leak
+    - Revert "IB/isert: Fix incorrect release of isert connection"
+    - RDMA/siw: Balance the reference of cep->kref in the error path
+    - RDMA/siw: Correct wrong debug message
+    - HID: logitech-dj: Fix error handling in logi_dj_recv_switch_to_dj_mode()
+    - HID: multitouch: Correct devm device reference for hidinput input_dev name
+    - x86/speculation: Mark all Skylake CPUs as vulnerable to GDS
+    - tracing: Fix race issue between cpu buffer write and swap
+    - phy/rockchip: inno-hdmi: use correct vco_div_5 macro on rk3328
+    - phy/rockchip: inno-hdmi: round fractal pixclock in rk3328 recalc_rate
+    - phy/rockchip: inno-hdmi: do not power on rk3328 post pll on reg write
+    - rpmsg: glink: Add check for kstrdup
+    - mtd: rawnand: fsmc: handle clk prepare error in fsmc_nand_resume()
+    - um: Fix hostaudio build errors
+    - dmaengine: ste_dma40: Add missing IRQ check in d40_probe
+    - cpufreq: Fix the race condition while updating the transition_task of policy
+    - virtio_ring: fix avail_wrap_counter in virtqueue_add_packed
+    - skbuff: skb_segment, Call zero copy functions before using skbuff frags
+    - PM / devfreq: Fix leak in devfreq_dev_release()
+    - ALSA: pcm: Fix missing fixup call in compat hw_refine ioctl
+    - ipmi_si: fix a memleak in try_smi_init()
+    - ARM: OMAP2+: Fix -Warray-bounds warning in _pwrdm_state_switch()
+    - backlight/gpio_backlight: Compare against struct fb_info.device
+    - backlight/bd6107: Compare against struct fb_info.device
+    - backlight/lv5207lp: Compare against struct fb_info.device
+    - xtensa: PMU: fix base address for the newer hardware
+    - media: dvb: symbol fixup for dvb_attach()
+    - ntb: Drop packets when qp link is down
+    - ntb: Clean up tx tail index on link down
+    - ntb: Fix calculation ntb_transport_tx_free_entry()
+    - Revert "PCI: Mark NVIDIA T4 GPUs to avoid bus reset"
+    - procfs: block chmod on /proc/thread-self/comm
+    - parisc: Fix /proc/cpuinfo output for lscpu
+    - dlm: fix plock lookup when using multiple lockspaces
+    - dccp: Fix out of bounds access in DCCP error handler
+    - X.509: if signature is unsupported skip validation
+    - net: handle ARPHRD_PPP in dev_is_mac_header_xmit()
+    - fsverity: skip PKCS#7 parser when keyring is empty
+    - pstore/ram: Check start of empty przs during init
+    - s390/ipl: add missing secure/has_secure file to ipl type 'unknown'
+    - crypto: stm32 - fix loop iterating through scatterlist for DMA
+    - cpufreq: brcmstb-avs-cpufreq: Fix -Warray-bounds bug
+    - sc16is7xx: Set iobase to device index
+    - serial: sc16is7xx: fix broken port 0 uart init
+    - usb: typec: tcpci: clear the fault status bit
+    - udf: initialize newblock to 0
+    - drm: fix double free for gbo in drm_gem_vram_init and drm_gem_vram_create
+    - net/ipv6: SKB symmetric hash should incorporate transport ports
+    - scsi: qla2xxx: fix inconsistent TMF timeout
+    - scsi: qla2xxx: Fix erroneous link up failure
+    - scsi: qla2xxx: Turn off noisy message log
+    - scsi: qla2xxx: Remove unsupported ql2xenabledif option
+    - fbdev/ep93xx-fb: Do not assign to struct fb_info.dev
+    - drm/ast: Fix DRAM init on AST2200
+    - lib/test_meminit: allocate pages up to order MAX_ORDER
+    - parisc: led: Fix LAN receive and transmit LEDs
+    - parisc: led: Reduce CPU overhead for disk & lan LED computation
+    - clk: qcom: gcc-mdm9615: use proper parent for pll0_vote clock
+    - soc: qcom: qmi_encdec: Restrict string length in decode
+    - NFSv4/pnfs: minor fix for cleanup path in nfs4_get_device_info
+    - kconfig: fix possible buffer overflow
+    - perf annotate bpf: Don't enclose non-debug code with an assert()
+    - x86/virt: Drop unnecessary check on extended CPUID level in cpu_has_svm()
+    - perf top: Don't pass an ERR_PTR() directly to perf_session__delete()
+    - watchdog: intel-mid_wdt: add MODULE_ALIAS() to allow auto-load
+    - pwm: lpc32xx: Remove handling of PWM channels
+    - sctp: annotate data-races around sk->sk_wmem_queued
+    - ipv4: annotate data-races around fi->fib_dead
+    - net: read sk->sk_family once in sk_mc_loop()
+    - igb: disable virtualization features on 82580
+    - veth: Fixing transmit return status for dropped packets
+    - net: ipv6/addrconf: avoid integer underflow in ipv6_create_tempaddr
+    - af_unix: Fix data-races around user->unix_inflight.
+    - af_unix: Fix data-race around unix_tot_inflight.
+    - af_unix: Fix data-races around sk->sk_shutdown.
+    - af_unix: Fix data race around sk->sk_err.
+    - kcm: Destroy mutex in kcm_exit_net()
+    - igc: Change IGC_MIN to allow set rx/tx value between 64 and 80
+    - igbvf: Change IGBVF_MIN to allow set rx/tx value between 64 and 80
+    - igb: Change IGB_MIN to allow set rx/tx value between 64 and 80
+    - s390/zcrypt: don't leak memory if dev_set_name() fails
+    - idr: fix param name in idr_alloc_cyclic() doc
+    - ip_tunnels: use DEV_STATS_INC()
+    - net: hns3: fix the port information display when sfp is absent
+    - sh: boards: Fix CEU buffer size passed to dma_declare_coherent_memory()
+    - ata: sata_gemini: Add missing MODULE_DESCRIPTION
+    - ata: pata_ftide010: Add missing MODULE_DESCRIPTION
+    - fuse: nlookup missing decrement in fuse_direntplus_link
+    - btrfs: don't start transaction when joining with TRANS_JOIN_NOSTART
+    - btrfs: use the correct superblock to compare fsid in btrfs_validate_super
+    - mtd: rawnand: brcmnand: Fix crash during the panic_write
+    - mtd: rawnand: brcmnand: Fix potential out-of-bounds access in oob write
+    - mtd: rawnand: brcmnand: Fix potential false time out warning
+    - perf hists browser: Fix hierarchy mode header
+    - perf tools: Handle old data in PERF_RECORD_ATTR
+    - usb: typec: tcpm: Refactor tcpm_handle_vdm_request payload handling
+    - usb: typec: tcpm: Refactor tcpm_handle_vdm_request
+    - usb: typec: bus: verify partner exists in typec_altmode_attention
+    - ARM: dts: BCM5301X: Extend RAM to full 256MB for Linksys EA6500 V2
+    - clk: imx8mm: Move 1443X/1416X PLL clock structure to common place
+    - net: ipv4: fix one memleak in __inet_del_ifa()
+    - net: ethernet: mvpp2_main: fix possible OOB write in
+      mvpp2_ethtool_get_rxnfc()
+    - net: ethernet: mtk_eth_soc: fix possible NULL pointer dereference in
+      mtk_hwlro_get_fdir_all()
+    - r8152: check budget for r8152_poll()
+    - kcm: Fix memory leak in error path of kcm_sendmsg()
+    - platform/mellanox: mlxbf-tmfifo: Drop the Rx packet if no more descriptors
+    - mlxbf-tmfifo: sparse tags for config access
+    - platform/mellanox: mlxbf-tmfifo: Drop jumbo frames
+    - net/tls: do not free tls_rec on async operation in bpf_exec_tx_verdict()
+    - ixgbe: fix timestamp configuration code
+    - kcm: Fix error handling for SOCK_DGRAM in kcm_sendmsg().
+    - drm/amd/display: Fix a bug when searching for insert_above_mpcc
+    - parisc: Drop loops_per_jiffy from per_cpu struct
+    - autofs: fix memory leak of waitqueues in autofs_catatonic_mode
+    - btrfs: output extra debug info if we failed to find an inline backref
+    - locks: fix KASAN: use-after-free in trace_event_raw_event_filelock_lock
+    - ACPICA: Add AML_NO_OPERAND_RESOLVE flag to Timer
+    - kernel/fork: beware of __put_task_struct() calling context
+    - ACPI: video: Add backlight=native DMI quirk for Lenovo Ideapad Z470
+    - perf/smmuv3: Enable HiSilicon Erratum 162001900 quirk for HIP08/09
+    - hw_breakpoint: fix single-stepping when using bpf_overflow_handler
+    - devlink: remove reload failed checks in params get/set callbacks
+    - wifi: ath9k: fix printk specifier
+    - wifi: mwifiex: fix fortify warning
+    - crypto: lib/mpi - avoid null pointer deref in mpi_cmp_ui()
+    - tpm_tis: Resend command to recover from data transfer errors
+    - mmc: sdhci-esdhc-imx: improve ESDHC_FLAG_ERR010450
+    - alx: fix OOB-read compiler warning
+    - wifi: mac80211_hwsim: drop short frames
+    - drm/exynos: fix a possible null-pointer dereference due to data race in
+      exynos_drm_crtc_atomic_disable()
+    - bus: ti-sysc: Configure uart quirks for k3 SoC
+    - md: raid1: fix potential OOB in raid1_remove_disk()
+    - ext2: fix datatype of block number in ext2_xattr_set2()
+    - fs/jfs: prevent double-free in dbUnmount() after failed jfs_remount()
+    - jfs: fix invalid free of JFS_IP(ipimap)->i_imap in diUnmount
+    - powerpc/pseries: fix possible memory leak in ibmebus_bus_init()
+    - media: dvb-usb-v2: af9035: Fix null-ptr-deref in af9035_i2c_master_xfer
+    - media: dw2102: Fix null-ptr-deref in dw2102_i2c_transfer()
+    - media: af9005: Fix null-ptr-deref in af9005_i2c_xfer
+    - media: anysee: fix null-ptr-deref in anysee_master_xfer
+    - media: az6007: Fix null-ptr-deref in az6007_i2c_xfer()
+    - media: tuners: qt1010: replace BUG_ON with a regular error
+    - media: pci: cx23885: replace BUG with error return
+    - usb: gadget: fsl_qe_udc: validate endpoint index for ch9 udc
+    - scsi: target: iscsi: Fix buffer overflow in lio_target_nacl_info_show()
+    - serial: cpm_uart: Avoid suspicious locking
+    - media: pci: ipu3-cio2: Initialise timing struct to avoid a compiler warning
+    - kobject: Add sanity check for kset->kobj.ktype in kset_register()
+    - tools features: Add feature test to check if libbfd has buildid support
+    - perf jevents: Make build dependency on test JSONs
+    - perf tools: Add an option to build without libbfd
+    - btrfs: move btrfs_pinned_by_swapfile prototype into volumes.h
+    - btrfs: add a helper to read the superblock metadata_uuid
+    - btrfs: compare the correct fsid/metadata_uuid in btrfs_validate_super
+    - selftests: tracing: Fix to unmount tracefs for recovering environment
+    - md/raid1: fix error: ISO C90 forbids mixed declarations
+    - attr: block mode changes of symlinks
+    - btrfs: fix lockdep splat and potential deadlock after failure running
+      delayed items
+    - tracing: Have current_trace inc the trace array ref count
+    - tracing: Have option files inc the trace array ref count
+    - nfsd: fix change_info in NFSv4 RENAME replies
+    - tracefs: Add missing lockdown check to tracefs_create_dir()
+    - i2c: aspeed: Reset the i2c controller when timeout occurs
+    - scsi: megaraid_sas: Fix deadlock on firmware crashdump
+    - ext4: fix rec_len verify error
+    - mtd: rawnand: brcmnand: Fix ECC level field setting for v7.2 controller
+    - drm/amdgpu: fix amdgpu_cs_p1_user_fence
+    - Linux 5.4.257
+  * Focal update: v5.4.257 upstream stable release (LP: #2040284) //
+    CVE-2023-39189
+    - netfilter: nfnetlink_osf: avoid OOB read
+  * CVE-2023-45871
+    - igb: set max size RX buffer when store bad packet is enabled
+  * CVE-2023-39193
+    - netfilter: xt_sctp: validate the flag_info count
+  * CVE-2023-39192
+    - netfilter: xt_u32: validate user space input
+  * CVE-2023-31085
+    - ubi: Refuse attaching if mtd's erasesize is 0
+  * CVE-2023-5717
+    - perf: Disallow mis-matched inherited group reads
+  * CVE-2023-5178
+    - nvmet-tcp: move send/recv error handling in the send/recv methods instead of
+      call-sites
+    - nvmet-tcp: Fix a possible UAF in queue intialization setup
+  * CVE-2023-42754
+    - ipv4: fix null-deref in ipv4_link_failure
+  * Focal update: v5.4.256 upstream stable release (LP: #2039446)
+    - powerpc/pmac/smp: Avoid unused-variable warnings
+    - powerpc/pmac/smp: Drop unnecessary volatile qualifier
+    - Revert "MIPS: Alchemy: fix dbdma2"
+    - Linux 5.4.256
+  * Focal update: v5.4.255 upstream stable release (LP: #2039440)
+    - mmc: sdhci_f_sdh30: convert to devm_platform_ioremap_resource
+    - mmc: sdhci-f-sdh30: Replace with sdhci_pltfm
+    - selftests: forwarding: tc_flower: Relax success criterion
+    - macsec: Fix traffic counters/statistics
+    - macsec: use DEV_STATS_INC()
+    - drm/radeon: Fix integer overflow in radeon_cs_parser_init
+    - ALSA: emu10k1: roll up loops in DSP setup code for Audigy
+    - quota: Properly disable quotas when add_dquot_ref() fails
+    - quota: fix warning in dqgrab()
+    - HID: add quirk for 03f0:464a HP Elite Presenter Mouse
+    - ovl: check type and offset of struct vfsmount in ovl_entry
+    - udf: Fix uninitialized array access for some pathnames
+    - fs: jfs: Fix UBSAN: array-index-out-of-bounds in dbAllocDmapLev
+    - MIPS: dec: prom: Address -Warray-bounds warning
+    - FS: JFS: Fix null-ptr-deref Read in txBegin
+    - FS: JFS: Check for read-only mounted filesystem in txBegin
+    - media: v4l2-mem2mem: add lock to protect parameter num_rdy
+    - media: platform: mediatek: vpu: fix NULL ptr dereference
+    - usb: chipidea: imx: don't request QoS for imx8ulp
+    - gfs2: Fix possible data races in gfs2_show_options()
+    - pcmcia: rsrc_nonstatic: Fix memory leak in nonstatic_release_resource_db()
+    - Bluetooth: L2CAP: Fix use-after-free
+    - drm/amdgpu: Fix potential fence use-after-free v2
+    - ALSA: hda/realtek: Add quirks for Unis H3C Desktop B760 & Q760
+    - ALSA: hda: fix a possible null-pointer dereference due to data race in
+      snd_hdac_regmap_sync()
+    - powerpc/kasan: Disable KCOV in KASAN code
+    - IMA: allow/fix UML builds
+    - iio: add addac subdirectory
+    - iio: adc: stx104: Utilize iomap interface
+    - iio: adc: stx104: Implement and utilize register structures
+    - iio: stx104: Move to addac subdirectory
+    - iio: addac: stx104: Fix race condition for stx104_write_raw()
+    - iio: addac: stx104: Fix race condition when converting analog-to-digital
+    - iommu/amd: Fix "Guest Virtual APIC Table Root Pointer" configuration in IRTE
+    - PM-runtime: add tracepoints for usage_count changes
+    - PM: runtime: Add pm_runtime_get_if_active()
+    - ALSA: hda: Fix unhandled register update during auto-suspend period
+    - irqchip/mips-gic: Get rid of the reliance on irq_cpu_online()
+    - irqchip/mips-gic: Use raw spinlock for gic_lock
+    - interconnect: Move internal structs into a separate file
+    - interconnect: Add helpers for enabling/disabling a path
+    - usb: dwc3: qcom: Add helper functions to enable,disable wake irqs
+    - USB: dwc3: qcom: fix NULL-deref on suspend
+    - mmc: bcm2835: fix deferred probing
+    - mmc: sunxi: fix deferred probing
+    - leds: trigger: netdev: Recheck NETDEV_LED_MODE_LINKUP on dev rename
+    - tracing/probes: Have process_fetch_insn() take a void * instead of pt_regs
+    - tracing/probes: Fix to update dynamic data counter if fetcharg uses it
+    - net/ncsi: Fix gma flag setting after response
+    - nfsd4: kill warnings on testing stateids with mismatched clientids
+    - nfsd: Remove incorrect check in nfsd4_validate_stateid
+    - virtio-mmio: convert to devm_platform_ioremap_resource
+    - virtio-mmio: Use to_virtio_mmio_device() to simply code
+    - virtio-mmio: don't break lifecycle of vm_dev
+    - i2c: bcm-iproc: Fix bcm_iproc_i2c_isr deadlock issue
+    - fbdev: mmp: fix value check in mmphw_probe()
+    - powerpc/rtas_flash: allow user copy to flash block cache objects
+    - tty: serial: fsl_lpuart: Clear the error flags by writing 1 for lpuart32
+      platforms
+    - btrfs: fix BUG_ON condition in btrfs_cancel_balance
+    - net: xfrm: Fix xfrm_address_filter OOB read
+    - net: af_key: fix sadb_x_filter validation
+    - xfrm: interface: rename xfrm_interface.c to xfrm_interface_core.c
+    - xfrm: fix slab-use-after-free in decode_session6
+    - ip6_vti: fix slab-use-after-free in decode_session6
+    - ip_vti: fix potential slab-use-after-free in decode_session6
+    - selftests: mirror_gre_changes: Tighten up the TTL test match
+    - ipvs: fix racy memcpy in proc_do_sync_threshold
+    - netfilter: nft_dynset: disallow object maps
+    - team: Fix incorrect deletion of ETH_P_8021AD protocol vid from slaves
+    - i40e: fix misleading debug logs
+    - net: dsa: mv88e6xxx: Wait for EEPROM done before HW reset
+    - sock: Fix misuse of sk_under_memory_pressure()
+    - net: do not allow gso_size to be set to GSO_BY_FRAGS
+    - bus: ti-sysc: Improve reset to work with modules with no sysconfig
+    - bus: ti-sysc: Flush posted write on enable before reset
+    - ARM: dts: imx7s: Drop dma-apb interrupt-names
+    - ARM: dts: imx: Adjust dma-apbh node name
+    - ARM: dts: imx: Set default tuning step for imx7d usdhc
+    - ARM: dts: imx: Set default tuning step for imx6sx usdhc
+    - ASoC: rt5665: add missed regulator_bulk_disable
+    - ASoC: meson: axg-tdm-formatter: fix channel slot allocation
+    - serial: 8250: Fix oops for port->pm on uart_change_pm()
+    - ALSA: usb-audio: Add support for Mythware XA001AU capture and playback
+      interfaces.
+    - cifs: Release folio lock on fscache read hit.
+    - mmc: wbsd: fix double mmc_free_host() in wbsd_init()
+    - mmc: block: Fix in_flight[issue_type] value error
+    - netfilter: set default timeout to 3 secs for sctp shutdown send and recv
+      state
+    - virtio-net: set queues after driver_ok
+    - net: fix the RTO timer retransmitting skb every 1ms if linear option is
+      enabled
+    - net: xfrm: Amend XFRMA_SEC_CTX nla_policy structure
+    - mmc: f-sdh30: fix order of function calls in sdhci_f_sdh30_remove
+    - net: phy: broadcom: stub c45 read/write for 54810
+    - PCI: acpiphp: Reassign resources on bridge if necessary
+    - dlm: improve plock logging if interrupted
+    - dlm: replace usage of found with dedicated list iterator variable
+    - fs: dlm: add pid to debug log
+    - fs: dlm: change plock interrupted message to debug again
+    - fs: dlm: use dlm_plock_info for do_unlock_close
+    - fs: dlm: fix mismatch of plock results from userspace
+    - MIPS: cpu-features: Enable octeon_cache by cpu_type
+    - MIPS: cpu-features: Use boot_cpu_type for CPU type based features
+    - fbdev: Improve performance of sys_imageblit()
+    - fbdev: Fix sys_imageblit() for arbitrary image widths
+    - fbdev: fix potential OOB read in fast_imageblit()
+    - dm integrity: increase RECALC_SECTORS to improve recalculate speed
+    - dm integrity: reduce vmalloc space footprint on 32-bit architectures
+    - ALSA: pcm: Set per-card upper limit of PCM buffer allocations
+    - ALSA: pcm: Use SG-buffer only when direct DMA is available
+    - ALSA: pcm: Fix potential data race at PCM memory allocation helpers
+    - regmap: Account for register length in SMBus I/O limits
+    - ASoC: fsl_sai: Refine enable/disable TE/RE sequence in trigger()
+    - ASoC: fsl_sai: Add new added registers and new bit definition
+    - ASoC: fsl_sai: Disable bit clock with transmitter
+    - drm/amd/display: do not wait for mpc idle if tg is disabled
+    - drm/amd/display: check TG is non-null before checking if enabled
+    - tracing: Fix memleak due to race between current_tracer and trace
+    - octeontx2-af: SDP: fix receive link config
+    - sock: annotate data-races around prot->memory_pressure
+    - dccp: annotate data-races in dccp_poll()
+    - ipvlan: Fix a reference count leak warning in ipvlan_ns_exit()
+    - net: bgmac: Fix return value check for fixed_phy_register()
+    - net: bcmgenet: Fix return value check for fixed_phy_register()
+    - net: validate veth and vxcan peer ifindexes
+    - igb: Avoid starting unnecessary workqueues
+    - net/sched: fix a qdisc modification with ambiguous command request
+    - net: remove bond_slave_has_mac_rcu()
+    - bonding: fix macvlan over alb bond support
+    - ibmveth: Use dcbf rather than dcbfl
+    - NFSv4: Fix dropped lock for racing OPEN and delegation return
+    - clk: Fix slab-out-of-bounds error in devm_clk_release()
+    - nfsd: Fix race to FREE_STATEID and cl_revoked
+    - batman-adv: Trigger events for auto adjusted MTU
+    - batman-adv: Don't increase MTU when set by user
+    - batman-adv: Do not get eth header before batadv_check_management_packet
+    - batman-adv: Fix TT global entry leak when client roamed back
+    - batman-adv: Fix batadv_v_ogm_aggr_send memory leak
+    - batman-adv: Hold rtnl lock during MTU update via netlink
+    - lib/clz_ctz.c: Fix __clzdi2() and __ctzdi2() for 32-bit kernels
+    - radix tree: remove unused variable
+    - media: vcodec: Fix potential array out-of-bounds in encoder queue_setup
+    - PCI: acpiphp: Use pci_assign_unassigned_bridge_resources() only for non-root
+      bus
+    - drm/display/dp: Fix the DP DSC Receiver cap size
+    - mm: allow a controlled amount of unfairness in the page lock
+    - rtnetlink: Reject negative ifindexes in RTM_NEWLINK
+    - ALSA: pcm: Fix build error on m68k and others
+    - Revert "ALSA: pcm: Use SG-buffer only when direct DMA is available"
+    - interconnect: Do not skip aggregation for disabled paths
+    - ALSA: pcm: Check for null pointer of pointer substream before dereferencing
+      it
+    - Documentation/sysctl: document page_lock_unfairness
+    - irqchip/mips-gic: Don't touch vl_map if a local interrupt is not routable
+    - scsi: snic: Fix double free in snic_tgt_create()
+    - scsi: core: raid_class: Remove raid_component_add()
+    - clk: Fix undefined reference to `clk_rate_exclusive_{get,put}'
+    - pinctrl: renesas: rza2: Add lock around
+      pinctrl_generic{{add,remove}_group,{add,remove}_function}
+    - dma-buf/sw_sync: Avoid recursive lock during fence signal
+    - Linux 5.4.255
+  * Focal update: v5.4.254 upstream stable release (LP: #2039291)
+    - mmc: moxart: read scr register without changing byte order
+    - ipv6: adjust ndisc_is_useropt() to also return true for PIO
+    - dmaengine: pl330: Return DMA_PAUSED when transaction is paused
+    - drm/nouveau/gr: enable memory loads on helper invocation on all channels
+    - radix tree test suite: fix incorrect allocation size for pthreads
+    - nilfs2: fix use-after-free of nilfs_root in dirtying inodes via iput
+    - iio: cros_ec: Fix the allocation size for cros_ec_command
+    - binder: fix memory leak in binder_init()
+    - usb-storage: alauda: Fix uninit-value in alauda_check_media()
+    - usb: dwc3: Properly handle processing of pending events
+    - usb: common: usb-conn-gpio: Prevent bailing out if initial role is none
+    - x86/cpu/amd: Enable Zenbleed fix for AMD Custom APU 0405
+    - x86/mm: Fix VDSO and VVAR placement on 5-level paging machines
+    - x86: Move gds_ucode_mitigated() declaration to header
+    - drm/nouveau/disp: Revert a NULL check inside nouveau_connector_get_modes
+    - selftests/rseq: Fix build with undefined __weak
+    - mISDN: Update parameter type of dsp_cmx_send()
+    - net/packet: annotate data-races around tp->status
+    - bonding: Fix incorrect deletion of ETH_P_8021AD protocol vid from slaves
+    - dccp: fix data-race around dp->dccps_mss_cache
+    - drivers: net: prevent tun_build_skb() to exceed the packet size limit
+    - IB/hfi1: Fix possible panic during hotplug remove
+    - wifi: cfg80211: fix sband iftype data lookup for AP_VLAN
+    - dmaengine: mcf-edma: Fix a potential un-allocated memory access
+    - net/mlx5: Allow 0 for total host VFs
+    - ibmvnic: Handle DMA unmapping of login buffs in release functions
+    - btrfs: don't stop integrity writeback too early
+    - btrfs: set cache_block_group_error if we find an error
+    - nvme-tcp: fix potential unbalanced freeze & unfreeze
+    - nvme-rdma: fix potential unbalanced freeze & unfreeze
+    - netfilter: nf_tables: report use refcount overflow
+    - scsi: core: Fix legacy /proc parsing buffer overflow
+    - scsi: storvsc: Fix handling of virtual Fibre Channel timeouts
+    - scsi: 53c700: Check that command slot is not NULL
+    - scsi: snic: Fix possible memory leak if device_add() fails
+    - scsi: core: Fix possible memory leak if device_add() fails
+    - alpha: remove __init annotation from exported page_is_ram()
+    - sch_netem: fix issues in netem_change() vs get_dist_table()
+    - Linux 5.4.254
+  * Focal update: v5.4.253 upstream stable release (LP: #2038652)
+    - jbd2: fix incorrect code style
+    - jbd2: fix kernel-doc markups
+    - jbd2: remove redundant buffer io error checks
+    - jbd2: recheck chechpointing non-dirty buffer
+    - jbd2: Fix wrongly judgement for buffer head removing while doing checkpoint
+    - gpio: tps68470: Make tps68470_gpio_output() always set the initial value
+    - bcache: remove 'int n' from parameter list of bch_bucket_alloc_set()
+    - bcache: Fix __bch_btree_node_alloc to make the failure behavior consistent
+    - btrfs: qgroup: catch reserved space leaks at unmount time
+    - btrfs: fix race between quota disable and relocation
+    - btrfs: fix extent buffer leak after tree mod log failure at split_node()
+    - ext4: rename journal_dev to s_journal_dev inside ext4_sb_info
+    - ext4: Fix reusing stale buffer heads from last failed mounting
+    - PCI/ASPM: Return 0 or -ETIMEDOUT from pcie_retrain_link()
+    - PCI/ASPM: Factor out pcie_wait_for_retrain()
+    - PCI/ASPM: Avoid link retraining race
+    - dlm: cleanup plock_op vs plock_xop
+    - dlm: rearrange async condition return
+    - fs: dlm: interrupt posix locks only when process is killed
+    - ftrace: Add information on number of page groups allocated
+    - ftrace: Check if pages were allocated before calling free_pages()
+    - ftrace: Store the order of pages allocated in ftrace_page
+    - ftrace: Fix possible warning on checking all pages used in
+      ftrace_process_locs()
+    - pwm: meson: Remove redundant assignment to variable fin_freq
+    - pwm: meson: Simplify duplicated per-channel tracking
+    - pwm: meson: fix handling of period/duty if greater than UINT_MAX
+    - scsi: qla2xxx: Fix inconsistent format argument type in qla_os.c
+    - scsi: qla2xxx: Array index may go out of bound
+    - uapi: General notification queue definitions
+    - keys: Fix linking a duplicate key to a keyring's assoc_array
+    - ext4: fix to check return value of freeze_bdev() in ext4_shutdown()
+    - i40e: Fix an NULL vs IS_ERR() bug for debugfs_create_dir()
+    - vxlan: calculate correct header length for GPE
+    - phy: hisilicon: Fix an out of bounds check in hisi_inno_phy_probe()
+    - ethernet: atheros: fix return value check in atl1e_tso_csum()
+    - ipv6 addrconf: fix bug where deleting a mngtmpaddr can create a new
+      temporary address
+    - bonding: reset bond's flags when down link is P2P device
+    - team: reset team's flags when down link is P2P device
+    - platform/x86: msi-laptop: Fix rfkill out-of-sync on MSI Wind U100
+    - net/sched: mqprio: refactor nlattr parsing to a separate function
+    - net/sched: mqprio: add extack to mqprio_parse_nlattr()
+    - net/sched: mqprio: Add length check for TCA_MQPRIO_{MAX/MIN}_RATE64
+    - benet: fix return value check in be_lancer_xmit_workarounds()
+    - RDMA/mlx4: Make check for invalid flags stricter
+    - drm/msm/dpu: drop enum dpu_core_perf_data_bus_id
+    - drm/msm/adreno: Fix snapshot BINDLESS_DATA size
+    - drm/msm: Fix IS_ERR_OR_NULL() vs NULL check in a5xx_submit_in_rb()
+    - ASoC: fsl_spdif: Silence output on stop
+    - block: Fix a source code comment in include/uapi/linux/blkzoned.h
+    - dm raid: fix missing reconfig_mutex unlock in raid_ctr() error paths
+    - ata: pata_ns87415: mark ns87560_tf_read static
+    - ring-buffer: Fix wrong stat of cpu_buffer->read
+    - tracing: Fix warning in trace_buffered_event_disable()
+    - serial: 8250_dw: Preserve original value of DLF register
+    - serial: sifive: Fix sifive_serial_console_setup() section
+    - USB: serial: option: support Quectel EM060K_128
+    - USB: serial: option: add Quectel EC200A module support
+    - USB: serial: simple: add Kaufmann RKS+CAN VCP
+    - USB: serial: simple: sort driver entries
+    - can: gs_usb: gs_can_close(): add missing set of CAN state to
+      CAN_STATE_STOPPED
+    - Revert "usb: dwc3: core: Enable AutoRetry feature in the controller"
+    - usb: dwc3: pci: skip BYT GPIO lookup table for hardwired phy
+    - usb: dwc3: don't reset device side if dwc3 was configured as host-only
+    - usb: ohci-at91: Fix the unhandle interrupt when resume
+    - USB: quirks: add quirk for Focusrite Scarlett
+    - usb: xhci-mtk: set the dma max_seg_size
+    - Revert "usb: xhci: tegra: Fix error check"
+    - Documentation: security-bugs.rst: update preferences when dealing with the
+      linux-distros group
+    - Documentation: security-bugs.rst: clarify CVE handling
+    - staging: ks7010: potential buffer overflow in ks_wlan_set_encode_ext()
+    - hwmon: (nct7802) Fix for temp6 (PECI1) processed even if PECI1 disabled
+    - btrfs: check for commit error at btrfs_attach_transaction_barrier()
+    - tpm_tis: Explicitly check for error code
+    - irq-bcm6345-l1: Do not assume a fixed block to cpu mapping
+    - btrfs: check if the transaction was aborted at btrfs_wait_for_commit()
+    - virtio-net: fix race between set queues and probe
+    - s390/dasd: fix hanging device after quiesce/resume
+    - ASoC: wm8904: Fill the cache for WM8904_ADC_TEST_0 register
+    - dm cache policy smq: ensure IO doesn't prevent cleaner policy progress
+    - ACPI: processor: perflib: Use the "no limit" frequency QoS
+    - ACPI: processor: perflib: Avoid updating frequency QoS unnecessarily
+    - cpufreq: intel_pstate: Drop ACPI _PSS states table patching
+    - btrfs: qgroup: remove one-time use variables for quota_root checks
+    - btrfs: qgroup: return ENOTCONN instead of EINVAL when quotas are not enabled
+    - ASoC: cs42l51: fix driver to properly autoload with automatic module loading
+    - arm64: Add AMPERE1 to the Spectre-BHB affected list
+    - arm64: Fix bit-shifting UB in the MIDR_CPU_MODEL() macro
+    - perf: Fix function pointer case
+    - loop: Select I/O scheduler 'none' from inside add_disk()
+    - word-at-a-time: use the same return type for has_zero regardless of
+      endianness
+    - KVM: s390: fix sthyi error handling
+    - net/mlx5: DR, fix memory leak in mlx5dr_cmd_create_reformat_ctx
+    - net/mlx5e: fix return value check in mlx5e_ipsec_remove_trailer()
+    - rtnetlink: let rtnl_bridge_setlink checks IFLA_BRIDGE_MODE length
+    - perf test uprobe_from_different_cu: Skip if there is no gcc
+    - net: sched: cls_u32: Fix match key mis-addressing
+    - mISDN: hfcpci: Fix potential deadlock on &hc->lock
+    - net: annotate data-races around sk->sk_max_pacing_rate
+    - net: add missing READ_ONCE(sk->sk_rcvlowat) annotation
+    - net: add missing READ_ONCE(sk->sk_sndbuf) annotation
+    - net: add missing READ_ONCE(sk->sk_rcvbuf) annotation
+    - net: add missing data-race annotations around sk->sk_peek_off
+    - net: add missing data-race annotation for sk_ll_usec
+    - bpf: sockmap: Remove preempt_disable in sock_map_sk_acquire
+    - driver core: add device probe log helper
+    - net: ll_temac: Switch to use dev_err_probe() helper
+    - net: ll_temac: fix error checking of irq_of_parse_and_map()
+    - net: dcb: choose correct policy to parse DCB_ATTR_BCN
+    - ip6mr: Fix skb_under_panic in ip6mr_cache_report()
+    - tcp_metrics: fix addr_same() helper
+    - tcp_metrics: annotate data-races around tm->tcpm_stamp
+    - tcp_metrics: annotate data-races around tm->tcpm_lock
+    - tcp_metrics: annotate data-races around tm->tcpm_vals[]
+    - tcp_metrics: annotate data-races around tm->tcpm_net
+    - tcp_metrics: fix data-race in tcpm_suck_dst() vs fastopen
+    - scsi: zfcp: Defer fc_rport blocking until after ADISC response
+    - libceph: fix potential hang in ceph_osdc_notify()
+    - USB: zaurus: Add ID for A-300/B-500/C-700
+    - mtd: spinand: toshiba: Fix ecc_get_status
+    - mtd: rawnand: meson: fix OOB available bytes for ECC
+    - fs/sysv: Null check to prevent null-ptr-deref bug
+    - net: usbnet: Fix WARNING in usbnet_start_xmit/usb_submit_urb
+    - fs: Protect reconfiguration of sb read-write from racing writes
+    - ext2: Drop fragment support
+    - test_firmware: prevent race conditions by a correct implementation of
+      locking
+    - test_firmware: return ENOMEM instead of ENOSPC on failed memory allocation
+    - mtd: rawnand: omap_elm: Fix incorrect type in assignment
+    - powerpc/mm/altmap: Fix altmap boundary check
+    - selftests/rseq: check if libc rseq support is registered
+    - selftests/rseq: Play nice with binaries statically linked against glibc
+      2.35+
+    - PM / wakeirq: support enabling wake-up irq after runtime_suspend called
+    - PM: sleep: wakeirq: fix wake irq arming
+    - ceph: show tasks waiting on caps in debugfs caps file
+    - ceph: use kill_anon_super helper
+    - ceph: defer stopping mdsc delayed_work
+    - arm64: dts: stratix10: fix incorrect I2C property for SCL signal
+    - ARM: dts: imx6sll: Make ssi node name same as other platforms
+    - ARM: dts: imx: Align L2 cache-controller nodename with dtschema
+    - ARM: dts: imx: add usb alias
+    - ARM: dts: imx6sll: fixup of operating points
+    - ARM: dts: nxp/imx6sll: fix wrong property name in usbphy node
+    - driver core: Annotate dev_err_probe() with __must_check
+    - driver code: print symbolic error code
+    - drivers: core: fix kernel-doc markup for dev_err_probe()
+    - Revert "driver core: Annotate dev_err_probe() with __must_check"
+    - Linux 5.4.253
+    - Upstream stable to v5.4.253
+  * CVE-2023-37453
+    - USB: hub: Clean up use of port initialization schemes and retries
+    - USB: hub: Add Kconfig option to reduce number of port initialization retries
+    - USB: core: Unite old scheme and new scheme descriptor reads
+    - usb: hub: Check device descriptor before resusciation
+    - USB: core: Change usb_get_device_descriptor() API
+    - USB: core: Fix race by not overwriting udev->descriptor in hub_port_init()
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update helper scripts
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Mon, 27 Nov 2023 10:09:20 +1000
+
+linux-xilinx-zynqmp (5.4.0-1034.38) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1034.38 -proposed tracker (LP: #2041986)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync git-ubuntu-log
+    - [Packaging] resync update-dkms-versions helper
+
+  [ Ubuntu: 5.4.0-167.184 ]
+
+  * focal/linux: 5.4.0-167.184 -proposed tracker (LP: #2041988)
+  * CVE-2023-45871
+    - igb: set max size RX buffer when store bad packet is enabled
+  * CVE-2023-31085
+    - ubi: Refuse attaching if mtd's erasesize is 0
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update helper scripts
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Fri, 10 Nov 2023 10:50:11 +1000
+
+linux-xilinx-zynqmp (5.4.0-1033.37) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1033.37 -proposed tracker (LP: #2038008)
+
+  * Use new annotations model (LP: #2019000)
+    - [Config] migrate all configs into annotations
+
+  [ Ubuntu: 5.4.0-166.183 ]
+
+  * focal/linux: 5.4.0-166.183 -proposed tracker (LP: #2038010)
+  * Use new annotations model (LP: #2019000)
+    - [Packaging] new annotations model infrastructure
+    - [Packaging] config-check: Handle new annotations format 4
+    - [Packaging] rules: Use old-kernelconfig for old configs
+    - [Config] sanitize annotations
+    - [Config] import generated configs into annotation file
+    - [Packaging] kernelconfig: add i386 as supported arch
+    - [Config] Remove all old configs files
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update helper scripts
+    - [Packaging] update annotations scripts
+  * fix typo in config-checks invocation (LP: #2020413)
+    - [Packaging] fix typo when calling the old config-check
+    - [Packaging] fix typo in 4-checks.mk
+  * support python < 3.9 with annotations (LP: #2020531)
+    - [Packaging] kconfig/annotations.py: support older way of merging dicts
+  * CVE-2023-42756
+    - netfilter: ipset: Fix race between IPSET_CMD_CREATE and IPSET_CMD_SWAP
+  * CVE-2023-4623
+    - net/sched: sch_hfsc: Ensure inner classes have fsc curve
+  * Focal update: v5.4.252 upstream stable release (LP: #2036240)
+    - ia64/cpu: Switch to arch_cpu_finalize_init()
+    - m68k/cpu: Switch to arch_cpu_finalize_init()
+    - mips/cpu: Switch to arch_cpu_finalize_init()
+    - sh/cpu: Switch to arch_cpu_finalize_init()
+    - x86/cpufeatures: Add SEV-ES CPU feature
+    - x86/cpu: Add VM page flush MSR availablility as a CPUID feature
+    - x86/cpufeatures: Assign dedicated feature word for CPUID_0x8000001F[EAX]
+    - tools headers cpufeatures: Sync with the kernel sources
+    - x86/cpu, kvm: Add support for CPUID_80000021_EAX
+    - Linux 5.4.252
+    - Upstream stable to v5.4.252
+  * CVE-2023-42755
+    - net/sched: Retire rsvp classifier
+    - [Config] remove NET_CLS_RSVP and NET_CLS_RSVP6
+  * CVE-2023-42753
+    - netfilter: ipset: add the missing IP_SET_HASH_WITH_NET0 macro for
+      ip_set_hash_netportnet.c
+  * CVE-2023-34319
+    - xen/netback: Fix buffer overrun triggered by unusual packet
+  * CVE-2023-4921
+    - net: sched: sch_qfq: Fix UAF in qfq_dequeue()
+  * CVE-2023-42752
+    - igmp: limit igmpv3_newpack() packet size to IP_MAX_MTU
+  * Avoid address overwrite in kernel_connect (LP: #2035163)
+    - net: Avoid address overwrite in kernel_connect
+  * [regression] Unable to initialize SGX enclaves with XFRM other than 3
+    (LP: #2034745)
+    - x86/fpu: Set X86_FEATURE_OSXSAVE feature after enabling OSXSAVE in CR4
+  * CVE-2023-4881
+    - netfilter: nftables: exthdr: fix 4-byte stack OOB write
+  * CVE-2023-4622
+    - af_unix: Fix null-ptr-deref in unix_stream_sendpage().
+  * Focal update: v5.4.251 upstream stable release (LP: #2034918)
+    - x86/smp: Use dedicated cache-line for mwait_play_dead()
+    - video: imsttfb: check for ioremap() failures
+    - fbdev: imsttfb: Fix use after free bug in imsttfb_probe
+    - HID: wacom: Use ktime_t rather than int when dealing with timestamps
+    - drm/i915: Initialise outparam for error return from wait_for_register
+    - scripts/tags.sh: Resolve gtags empty index generation
+    - drm/amdgpu: Validate VM ioctl flags.
+    - bgmac: fix *initial* chip reset to support BCM5358
+    - x86/resctrl: Use is_closid_match() in more places
+    - x86/resctrl: Only show tasks' pid in current pid namespace
+    - md/raid10: check slab-out-of-bounds in md_bitmap_get_counter
+    - md/raid10: fix overflow of md/safe_mode_delay
+    - md/raid10: fix wrong setting of max_corr_read_errors
+    - md/raid10: fix null-ptr-deref of mreplace in raid10_sync_request
+    - md/raid10: fix io loss while replacement replace rdev
+    - irqchip/jcore-aic: Kill use of irq_create_strict_mappings()
+    - irqchip/jcore-aic: Fix missing allocation of IRQ descriptors
+    - tracing/timer: Add missing hrtimer modes to decode_hrtimer_mode().
+    - clocksource/drivers/cadence-ttc: Use ttc driver as platform driver
+    - clocksource/drivers/cadence-ttc: Fix memory leak in ttc_timer_probe
+    - PM: domains: fix integer overflow issues in genpd_parse_state()
+    - powercap: RAPL: Fix CONFIG_IOSF_MBI dependency
+    - ARM: 9303/1: kprobes: avoid missing-declaration warnings
+    - evm: Complete description of evm_inode_setattr()
+    - pstore/ram: Add check for kstrdup
+    - ima: Fix build warnings
+    - wifi: ath9k: fix AR9003 mac hardware hang check register offset calculation
+    - wifi: ath9k: avoid referencing uninit memory in ath9k_wmi_ctrl_rx
+    - samples/bpf: Fix buffer overflow in tcp_basertt
+    - spi: spi-geni-qcom: Correct CS_TOGGLE bit in SPI_TRANS_CFG
+    - wifi: mwifiex: Fix the size of a memory allocation in
+      mwifiex_ret_802_11_scan()
+    - nfc: constify several pointers to u8, char and sk_buff
+    - nfc: llcp: fix possible use of uninitialized variable in
+      nfc_llcp_send_connect()
+    - regulator: core: Fix more error checking for debugfs_create_dir()
+    - regulator: core: Streamline debugfs operations
+    - wifi: orinoco: Fix an error handling path in spectrum_cs_probe()
+    - wifi: orinoco: Fix an error handling path in orinoco_cs_probe()
+    - wifi: atmel: Fix an error handling path in atmel_probe()
+    - wl3501_cs: Fix a bunch of formatting issues related to function docs
+    - wl3501_cs: Remove unnecessary NULL check
+    - wl3501_cs: Fix misspelling and provide missing documentation
+    - net: create netdev->dev_addr assignment helpers
+    - wl3501_cs: use eth_hw_addr_set()
+    - wifi: wl3501_cs: Fix an error handling path in wl3501_probe()
+    - wifi: ray_cs: Utilize strnlen() in parse_addr()
+    - wifi: ray_cs: Drop useless status variable in parse_addr()
+    - wifi: ray_cs: Fix an error handling path in ray_probe()
+    - wifi: ath9k: don't allow to overwrite ENDPOINT0 attributes
+    - wifi: rsi: Do not set MMC_PM_KEEP_POWER in shutdown
+    - watchdog/perf: define dummy watchdog_update_hrtimer_threshold() on correct
+      config
+    - watchdog/perf: more properly prevent false positives with turbo modes
+    - kexec: fix a memory leak in crash_shrink_memory()
+    - memstick r592: make memstick_debug_get_tpc_name() static
+    - wifi: ath9k: Fix possible stall on ath9k_txq_list_has_key()
+    - rtnetlink: extend RTEXT_FILTER_SKIP_STATS to IFLA_VF_INFO
+    - wifi: iwlwifi: pull from TXQs with softirqs disabled
+    - wifi: cfg80211: rewrite merging of inherited elements
+    - wifi: ath9k: convert msecs to jiffies where needed
+    - netlink: fix potential deadlock in netlink_set_err()
+    - netlink: do not hard code device address lenth in fdb dumps
+    - selftests: rtnetlink: remove netdevsim device after ipsec offload test
+    - gtp: Fix use-after-free in __gtp_encap_destroy().
+    - lib/ts_bm: reset initial match offset for every block of text
+    - netfilter: conntrack: dccp: copy entire header to stack buffer, not just
+      basic one
+    - netfilter: nf_conntrack_sip: fix the ct_sip_parse_numerical_param() return
+      value.
+    - ipvlan: Fix return value of ipvlan_queue_xmit()
+    - netlink: Add __sock_i_ino() for __netlink_diag_dump().
+    - radeon: avoid double free in ci_dpm_init()
+    - Input: drv260x - sleep between polling GO bit
+    - ARM: dts: BCM5301X: Drop "clock-names" from the SPI node
+    - Input: adxl34x - do not hardcode interrupt trigger type
+    - drm: sun4i_tcon: use devm_clk_get_enabled in `sun4i_tcon_init_clocks`
+    - RDMA/bnxt_re: Fix to remove an unnecessary log
+    - ARM: dts: gta04: Move model property out of pinctrl node
+    - arm64: dts: qcom: msm8916: correct camss unit address
+    - drm/panel: simple: fix active size for Ampire AM-480272H3TMQW-T01H
+    - ARM: ep93xx: fix missing-prototype warnings
+    - memory: brcmstb_dpfe: fix testing array offset after use
+    - ASoC: es8316: Increment max value for ALC Capture Target Volume control
+    - ASoC: es8316: Do not set rate constraints for unsupported MCLKs
+    - soc/fsl/qe: fix usb.c build errors
+    - IB/hfi1: Fix sdma.h tx->num_descs off-by-one errors
+    - arm64: dts: renesas: ulcb-kf: Remove flow control for SCIF1
+    - fbdev: omapfb: lcd_mipid: Fix an error handling path in mipid_spi_probe()
+    - drm/amdkfd: Fix potential deallocation of previously deallocated memory.
+    - drm/radeon: fix possible division-by-zero errors
+    - clk: tegra: tegra124-emc: Fix potential memory leak
+    - ALSA: ac97: Fix possible NULL dereference in snd_ac97_mixer
+    - clk: cdce925: check return value of kasprintf()
+    - clk: keystone: sci-clk: check return value of kasprintf()
+    - ASoC: imx-audmix: check return value of devm_kasprintf()
+    - scsi: qedf: Fix NULL dereference in error handling
+    - PCI/ASPM: Disable ASPM on MFD function removal to avoid use-after-free
+    - scsi: 3w-xxxx: Add error handling for initialization failure in tw_probe()
+    - PCI: pciehp: Cancel bringup sequence if card is not present
+    - PCI: ftpci100: Release the clock resources
+    - PCI: Add pci_clear_master() stub for non-CONFIG_PCI
+    - pinctrl: cherryview: Return correct value if pin in push-pull mode
+    - perf dwarf-aux: Fix off-by-one in die_get_varname()
+    - pinctrl: at91-pio4: check return value of devm_kasprintf()
+    - powerpc/mm/dax: Fix the condition when checking if altmap vmemap can cross-
+      boundary
+    - hwrng: virtio - add an internal buffer
+    - hwrng: virtio - don't wait on cleanup
+    - hwrng: virtio - don't waste entropy
+    - hwrng: virtio - always add a pending request
+    - hwrng: virtio - Fix race on data_avail and actual data
+    - crypto: nx - fix build warnings when DEBUG_FS is not enabled
+    - modpost: fix section mismatch message for R_ARM_ABS32
+    - modpost: fix section mismatch message for R_ARM_{PC24,CALL,JUMP24}
+    - crypto: marvell/cesa - Fix type mismatch warning
+    - modpost: fix off by one in is_executable_section()
+    - ARC: define ASM_NL and __ALIGN(_STR) outside #ifdef __ASSEMBLY__ guard
+    - NFSv4.1: freeze the session table upon receiving NFS4ERR_BADSESSION
+    - hwrng: st - Fix W=1 unused variable warning
+    - hwrng: st - keep clock enabled while hwrng is registered
+    - USB: serial: option: add LARA-R6 01B PIDs
+    - usb: dwc3: gadget: Propagate core init errors to UDC during pullup
+    - block: fix signed int overflow in Amiga partition support
+    - block: change all __u32 annotations to __be32 in affs_hardblocks.h
+    - w1: fix loop in w1_fini()
+    - sh: j2: Use ioremap() to translate device tree address into kernel memory
+    - media: usb: Check az6007_read() return value
+    - media: videodev2.h: Fix struct v4l2_input tuner index comment
+    - usb: dwc3: qcom: Fix potential memory leak
+    - extcon: Fix kernel doc of property fields to avoid warnings
+    - extcon: Fix kernel doc of property capability fields to avoid warnings
+    - usb: phy: phy-tahvo: fix memory leak in tahvo_usb_probe()
+    - usb: hide unused usbfs_notify_suspend/resume functions
+    - mfd: rt5033: Drop rt5033-battery sub-device
+    - KVM: s390: fix KVM_S390_GET_CMMA_BITS for GFNs in memslot holes
+    - usb: dwc3: qcom: Release the correct resources in dwc3_qcom_remove()
+    - mfd: intel-lpss: Add missing check for platform_get_resource
+    - serial: 8250_omap: Use force_suspend and resume for system suspend
+    - mfd: stmfx: Fix error path in stmfx_chip_init
+    - KVM: s390: vsie: fix the length of APCB bitmap
+    - mfd: stmpe: Only disable the regulators if they are enabled
+    - pwm: imx-tpm: force 'real_period' to be zero in suspend
+    - pwm: sysfs: Do not apply state to already disabled PWMs
+    - rtc: st-lpc: Release some resources in st_rtc_probe() in case of error
+    - sctp: fix potential deadlock on &net->sctp.addr_wq_lock
+    - Add MODULE_FIRMWARE() for FIRMWARE_TG357766.
+    - spi: bcm-qspi: return error if neither hif_mspi nor mspi is available
+    - mailbox: ti-msgmgr: Fill non-message tx data fields with 0x0
+    - f2fs: fix error path handling in truncate_dnode()
+    - powerpc: allow PPC_EARLY_DEBUG_CPM only when SERIAL_CPM=y
+    - net: bridge: keep ports without IFF_UNICAST_FLT in BR_PROMISC mode
+    - tcp: annotate data races in __tcp_oow_rate_limited()
+    - xsk: Improve documentation for AF_XDP
+    - xsk: Honor SO_BINDTODEVICE on bind
+    - net/sched: act_pedit: Add size check for TCA_PEDIT_PARMS_EX
+    - net: dsa: tag_sja1105: fix MAC DA patching from meta frames
+    - sh: dma: Fix DMA channel offset calculation
+    - i2c: xiic: Defer xiic_wakeup() and __xiic_start_xfer() in xiic_process()
+    - i2c: xiic: Don't try to handle more interrupt events after error
+    - ALSA: jack: Fix mutex call in snd_jack_report()
+    - NFSD: add encoding of op_recall flag for write delegation
+    - mmc: core: disable TRIM on Kingston EMMC04G-M627
+    - mmc: core: disable TRIM on Micron MTFC4GACAJCN-1M
+    - mmc: sdhci: fix DMA configure compatibility issue when 64bit DMA mode is
+      used.
+    - bcache: Remove unnecessary NULL point check in node allocations
+    - integrity: Fix possible multiple allocation in integrity_inode_get()
+    - jffs2: reduce stack usage in jffs2_build_xattr_subsystem()
+    - fs: avoid empty option when generating legacy mount string
+    - ext4: Remove ext4 locking of moved directory
+    - Revert "f2fs: fix potential corruption when moving a directory"
+    - fs: Establish locking order for unrelated directories
+    - fs: Lock moved directories
+    - btrfs: fix race when deleting quota root from the dirty cow roots list
+    - ARM: orion5x: fix d2net gpio initialization
+    - fs: no need to check source
+    - fanotify: disallow mount/sb marks on kernel internal pseudo fs
+    - block: add overflow checks for Amiga partition support
+    - netfilter: nf_tables: fix nat hook table deletion
+    - netfilter: nftables: add helper function to set the base sequence number
+    - netfilter: add helper function to set up the nfnetlink header and use it
+    - netfilter: nf_tables: use net_generic infra for transaction data
+    - netfilter: nf_tables: add rescheduling points during loop detection walks
+    - netfilter: nf_tables: add NFT_TRANS_PREPARE_ERROR to deal with bound
+      set/chain
+    - netfilter: nf_tables: reject unbound anonymous set before commit phase
+    - netfilter: nf_tables: unbind non-anonymous set if rule construction fails
+    - netfilter: nf_tables: fix scheduling-while-atomic splat
+    - netfilter: conntrack: Avoid nf_ct_helper_hash uses after free
+    - tty: serial: fsl_lpuart: add earlycon for imx8ulp platform
+    - block/partition: fix signedness issue for Amiga partitions
+    - net: lan743x: Don't sleep in atomic context
+    - workqueue: clean up WORK_* constant types, clarify masking
+    - drm/panel: Initialise panel dev and funcs through drm_panel_init()
+    - drm/panel: Add and fill drm_panel type field
+    - drm/panel: simple: Add connector_type for innolux_at043tn24
+    - igc: Remove delay during TX ring configuration
+    - igc: set TP bit in 'supported' and 'advertising' fields of
+      ethtool_link_ksettings
+    - scsi: qla2xxx: Fix error code in qla2x00_start_sp()
+    - net: mvneta: fix txq_map in case of txq_number==1
+    - ionic: improve irq numa locality
+    - ionic: clean irq affinity on queue deinit
+    - ionic: move irq request to qcq alloc
+    - ionic: ionic_intr_free parameter change
+    - ionic: remove WARN_ON to prevent panic_on_warn
+    - icmp6: Fix null-ptr-deref of ip6_null_entry->rt6i_idev in icmp6_dev().
+    - udp6: fix udp6_ehashfn() typo
+    - ntb: idt: Fix error handling in idt_pci_driver_init()
+    - NTB: amd: Fix error handling in amd_ntb_pci_driver_init()
+    - ntb: intel: Fix error handling in intel_ntb_pci_driver_init()
+    - NTB: ntb_transport: fix possible memory leak while device_register() fails
+    - NTB: ntb_tool: Add check for devm_kcalloc
+    - ipv6/addrconf: fix a potential refcount underflow for idev
+    - platform/x86: wmi: Replace UUID redefinitions by their originals
+    - platform/x86: wmi: Fix indentation in some cases
+    - platform/x86: wmi: remove unnecessary argument
+    - platform/x86: wmi: use guid_t and guid_equal()
+    - platform/x86: wmi: move variables
+    - platform/x86: wmi: Break possible infinite loop when parsing GUID
+    - erofs: avoid infinite loop in z_erofs_do_read_page() when reading beyond EOF
+    - wifi: airo: avoid uninitialized warning in airo_get_rate()
+    - cls_flower: Add extack support for src and dst port range options
+    - net/sched: flower: Ensure both minimum and maximum ports are specified
+    - net/sched: make psched_mtu() RTNL-less safe
+    - pinctrl: amd: Fix mistake in handling clearing pins at startup
+    - pinctrl: amd: Detect internal GPIO0 debounce handling
+    - pinctrl: amd: Only use special debounce behavior for GPIO 0
+    - tpm: tpm_vtpm_proxy: fix a race condition in /dev/vtpmx creation
+    - mtd: rawnand: meson: fix unaligned DMA buffers handling
+    - net: bcmgenet: Ensure MDIO unregistration has clocks enabled
+    - powerpc: Fail build if using recordmcount with binutils v2.37
+    - misc: fastrpc: Create fastrpc scalar with correct buffer count
+    - SUNRPC: Fix UAF in svc_tcp_listen_data_ready()
+    - erofs: fix compact 4B support for 16k block size
+    - ext4: fix wrong unit use in ext4_mb_clear_bb
+    - ext4: only update i_reserved_data_blocks on successful block allocation
+    - jfs: jfs_dmap: Validate db_l2nbperpage while mounting
+    - PCI/PM: Avoid putting EloPOS E2/S2/H2 PCIe Ports in D3cold
+    - PCI: Add function 1 DMA alias quirk for Marvell 88SE9235
+    - PCI: qcom: Disable write access to read only registers for IP v2.3.3
+    - PCI: rockchip: Assert PCI Configuration Enable bit after probe
+    - PCI: rockchip: Write PCI Device ID to correct register
+    - PCI: rockchip: Add poll and timeout to wait for PHY PLLs to be locked
+    - PCI: rockchip: Fix legacy IRQ generation for RK3399 PCIe endpoint core
+    - PCI: rockchip: Use u32 variable to access 32-bit registers
+    - PCI: rockchip: Set address alignment for endpoint mode
+    - misc: pci_endpoint_test: Free IRQs before removing the device
+    - misc: pci_endpoint_test: Re-init completion for every test
+    - md/raid0: add discard support for the 'original' layout
+    - fs: dlm: return positive pid value for F_GETLK
+    - drm/atomic: Allow vblank-enabled + self-refresh "disable"
+    - drm/rockchip: vop: Leave vblank enabled in self-refresh
+    - serial: atmel: don't enable IRQs prematurely
+    - firmware: stratix10-svc: Fix a potential resource leak in
+      svc_create_memory_pool()
+    - hwrng: imx-rngc - fix the timeout for init and self check
+    - ceph: don't let check_caps skip sending responses for revoke msgs
+    - meson saradc: fix clock divider mask length
+    - Revert "8250: add support for ASIX devices with a FIFO bug"
+    - tty: serial: samsung_tty: Fix a memory leak in s3c24xx_serial_getclk() in
+      case of error
+    - tty: serial: samsung_tty: Fix a memory leak in s3c24xx_serial_getclk() when
+      iterating clk
+    - tracing/histograms: Add histograms to hist_vars if they have referenced
+      variables
+    - ring-buffer: Fix deadloop issue on reading trace_pipe
+    - xtensa: ISS: fix call to split_if_spec
+    - tracing: Fix null pointer dereference in tracing_err_log_open()
+    - tracing/probes: Fix not to count error code to total length
+    - scsi: qla2xxx: Wait for io return on terminate rport
+    - scsi: qla2xxx: Fix potential NULL pointer dereference
+    - scsi: qla2xxx: Check valid rport returned by fc_bsg_to_rport()
+    - scsi: qla2xxx: Correct the index of array
+    - scsi: qla2xxx: Pointer may be dereferenced
+    - scsi: qla2xxx: Remove unused nvme_ls_waitq wait queue
+    - drm/atomic: Fix potential use-after-free in nonblocking commits
+    - perf probe: Add test for regression introduced by switch to
+      die_get_decl_file()
+    - btrfs: fix warning when putting transaction with qgroups enabled after abort
+    - fuse: revalidate: don't invalidate if interrupted
+    - selftests: tc: set timeout to 15 minutes
+    - can: bcm: Fix UAF in bcm_proc_show()
+    - drm/client: Fix memory leak in drm_client_target_cloned
+    - drm/client: Fix memory leak in drm_client_modeset_probe
+    - ext4: correct inline offset when handling xattrs in inode body
+    - debugobjects: Recheck debug_objects_enabled before reporting
+    - nbd: Add the maximum limit of allocated index in nbd_dev_add
+    - md: fix data corruption for raid456 when reshape restart while grow up
+    - md/raid10: prevent soft lockup while flush writes
+    - posix-timers: Ensure timer ID search-loop limit is valid
+    - arm64: mm: fix VA-range sanity check
+    - sched/fair: Don't balance task to its current running CPU
+    - bpf: Address KCSAN report on bpf_lru_list
+    - devlink: report devlink_port_type_warn source device
+    - wifi: wext-core: Fix -Wstringop-overflow warning in
+      ioctl_standard_iw_point()
+    - wifi: iwlwifi: mvm: avoid baid size integer overflow
+    - igb: Fix igb_down hung on surprise removal
+    - spi: bcm63xx: fix max prepend length
+    - fbdev: imxfb: warn about invalid left/right margin
+    - pinctrl: amd: Use amd_pinconf_set() for all config options
+    - net: ethernet: ti: cpsw_ale: Fix cpsw_ale_get_field()/cpsw_ale_set_field()
+    - iavf: Fix use-after-free in free_netdev
+    - net:ipv6: check return value of pskb_trim()
+    - Revert "tcp: avoid the lookup process failing to get sk in ehash table"
+    - fbdev: au1200fb: Fix missing IRQ check in au1200fb_drv_probe
+    - llc: Don't drop packet from non-root netns.
+    - netfilter: nf_tables: fix spurious set element insertion failure
+    - netfilter: nf_tables: can't schedule in nft_chain_validate
+    - tcp: annotate data-races around tp->tcp_tx_delay
+    - net: Replace the limit of TCP_LINGER2 with TCP_FIN_TIMEOUT_MAX
+    - tcp: annotate data-races around tp->linger2
+    - tcp: annotate data-races around rskq_defer_accept
+    - tcp: annotate data-races around tp->notsent_lowat
+    - tcp: annotate data-races around fastopenq.max_qlen
+    - tracing/histograms: Return an error if we fail to add histogram to hist_vars
+      list
+    - Linux 5.4.251
+  * Focal update: v5.4.250 upstream stable release (LP: #2033297)
+    - x86/microcode/AMD: Load late on both threads too
+    - Linux 5.4.250
+  * Focal update: v5.4.249 upstream stable release (LP: #2033278)
+    - nilfs2: reject devices with insufficient block count
+    - mm: rewrite wait_on_page_bit_common() logic
+    - list: add "list_del_init_careful()" to go with "list_empty_careful()"
+    - epoll: ep_autoremove_wake_function should use list_del_init_careful
+    - tracing: Add tracing_reset_all_online_cpus_unlocked() function
+    - x86/purgatory: remove PGO flags
+    - tick/common: Align tick period during sched_timer setup
+    - media: dvbdev: Fix memleak in dvb_register_device
+    - media: dvbdev: fix error logic at dvb_register_device()
+    - media: dvb-core: Fix use-after-free due to race at dvb_register_device()
+    - nilfs2: fix buffer corruption due to concurrent device reads
+    - Drivers: hv: vmbus: Fix vmbus_wait_for_unload() to scan present CPUs
+    - PCI: hv: Fix a race condition bug in hv_pci_query_relations()
+    - cgroup: Do not corrupt task iteration when rebinding subsystem
+    - mmc: meson-gx: remove redundant mmc_request_done() call from irq context
+    - ip_tunnels: allow VXLAN/GENEVE to inherit TOS/TTL from VLAN
+    - writeback: fix dereferencing NULL mapping->host on writeback_page_template
+    - nilfs2: prevent general protection fault in nilfs_clear_dirty_page()
+    - cifs: Clean up DFS referral cache
+    - cifs: Get rid of kstrdup_const()'d paths
+    - cifs: Introduce helpers for finding TCP connection
+    - cifs: Merge is_path_valid() into get_normalized_path()
+    - cifs: Fix potential deadlock when updating vol in cifs_reconnect()
+    - x86/mm: Avoid using set_pgd() outside of real PGD pages
+    - ieee802154: hwsim: Fix possible memory leaks
+    - xfrm: Linearize the skb after offloading if needed.
+    - net: qca_spi: Avoid high load if QCA7000 is not available
+    - mmc: mtk-sd: fix deferred probing
+    - mmc: mvsdio: convert to devm_platform_ioremap_resource
+    - mmc: mvsdio: fix deferred probing
+    - mmc: omap: fix deferred probing
+    - mmc: omap_hsmmc: fix deferred probing
+    - mmc: sdhci-acpi: fix deferred probing
+    - mmc: sh_mmcif: fix deferred probing
+    - mmc: usdhi60rol0: fix deferred probing
+    - ipvs: align inner_mac_header for encapsulation
+    - net: dsa: mt7530: fix trapping frames on non-MT7621 SoC MT7530 switch
+    - be2net: Extend xmit workaround to BE3 chip
+    - netfilter: nf_tables: disallow element updates of bound anonymous sets
+    - netfilter: nfnetlink_osf: fix module autoload
+    - Revert "net: phy: dp83867: perform soft reset and retain established link"
+    - sch_netem: acquire qdisc lock in netem_change()
+    - scsi: target: iscsi: Prevent login threads from racing between each other
+    - HID: wacom: Add error check to wacom_parse_and_register()
+    - arm64: Add missing Set/Way CMO encodings
+    - media: cec: core: don't set last_initiator if tx in progress
+    - nfcsim.c: Fix error checking for debugfs_create_dir
+    - usb: gadget: udc: fix NULL dereference in remove()
+    - s390/cio: unregister device when the only path is gone
+    - ASoC: nau8824: Add quirk to active-high jack-detect
+    - ARM: dts: Fix erroneous ADS touchscreen polarities
+    - drm/exynos: vidi: fix a wrong error return
+    - drm/exynos: fix race condition UAF in exynos_g2d_exec_ioctl
+    - drm/radeon: fix race condition UAF in radeon_gem_set_domain_ioctl
+    - x86/apic: Fix kernel panic when booting with intremap=off and x2apic_phys
+    - i2c: imx-lpi2c: fix type char overflow issue when calculating the clock
+      cycle
+    - mm: fix VM_BUG_ON(PageTail) and BUG_ON(PageWriteback)
+    - mm: make wait_on_page_writeback() wait for multiple pending writebacks
+    - Linux 5.4.249
+  * allow io_uring to be disabled in runtime (LP: #2035116)
+    - io_uring: add a sysctl to disable io_uring system-wide
+  * CVE-2023-31083
+    - Bluetooth: hci_ldisc: check HCI_UART_PROTO_READY flag in HCIUARTGETPROTO
+  * CVE-2023-4132
+    - media: usb: siano: Fix warning due to null work_func_t function pointer
+  * CVE-2023-3772
+    - xfrm: add NULL check in xfrm_update_ae_params
+  * CVE-2023-0597
+    - random32: add noise from network and scheduling activity
+    - x86/kasan: Map shadow for percpu pages on demand
+    - x86/mm: Randomize per-cpu entry area
+    - x86/mm: Recompute physical address for every page of per-CPU CEA mapping
+    - x86/mm: Populate KASAN shadow for entire per-CPU range of CPU entry area
+    - x86/mm: Do not shuffle CPU entry areas without KASLR
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Wed, 11 Oct 2023 15:25:26 +1000
+
+linux-xilinx-zynqmp (5.4.0-1031.35) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1031.35 -proposed tracker (LP: #2033865)
+
+  * Firefox doesn't export URL (LP: #203112)
+    - [Config] updateconfigs for DECNET
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update helper scripts
+
+  [ Ubuntu: 5.4.0-164.181 ]
+
+  * focal/linux: 5.4.0-164.181 -proposed tracker (LP: #2033867)
+  * Please enable Renesas RZ platform serial installer (LP: #2022361)
+    - [Config] enable hihope RZ/G2M serial console
+  * Azure: hv_netvsc: add support for vlans in AF_PACKET mode (LP: #2030872)
+    - hv_netvsc: add support for vlans in AF_PACKET mode
+  * systemd mount units fail during boot, while file system is correctly mounted
+    (LP: #1837227)
+    - list: introduce list_for_each_continue()
+    - proc/mounts: add cursor
+  * CVE-2023-40283
+    - Bluetooth: L2CAP: Fix use-after-free in l2cap_sock_ready_cb
+  * CVE-2023-20588
+    - x86/bugs: Increase the x86 bugs vector size to two u32s
+    - x86/CPU/AMD: Do not leak quotient data after a division by 0
+    - x86/CPU/AMD: Fix the DIV(0) initial fix attempt
+  * CVE-2023-4194
+    - net: tun_chr_open(): set sk_uid from current_fsuid()
+    - net: tap_open(): set sk_uid from current_fsuid()
+  * CVE-2023-1206
+    - tcp: Reduce chance of collisions in inet6_hashfn().
+  * CVE-2021-4001
+    - bpf: Fix toctou on read-only map's constant scalar tracking
+  * Focal update: v5.4.248 upstream stable release (LP: #2031121)
+    - test_firmware: fix a memory leak with reqs buffer
+    - KEYS: asymmetric: Copy sig and digest in public_key_verify_signature()
+    - dasd: refactor dasd_ioctl_information
+    - s390/dasd: Use correct lock while counting channel queue length
+    - power: supply: ab8500: Fix external_power_changed race
+    - power: supply: sc27xx: Fix external_power_changed race
+    - power: supply: bq27xxx: Use mod_delayed_work() instead of cancel() +
+      schedule()
+    - ARM: dts: vexpress: add missing cache properties
+    - power: supply: Ratelimit no data debug output
+    - platform/x86: asus-wmi: Ignore WMI events with codes 0x7B, 0xC0
+    - regulator: Fix error checking for debugfs_create_dir
+    - irqchip/meson-gpio: Mark OF related data as maybe unused
+    - power: supply: Fix logic checking if system is running from battery
+    - btrfs: handle memory allocation failure in btrfs_csum_one_bio
+    - parisc: Improve cache flushing for PCXL in arch_sync_dma_for_cpu()
+    - parisc: Flush gatt writes and adjust gatt mask in parisc_agp_mask_memory()
+    - MIPS: Alchemy: fix dbdma2
+    - mips: Move initrd_start check after initrd address sanitisation.
+    - xen/blkfront: Only check REQ_FUA for writes
+    - drm:amd:amdgpu: Fix missing buffer object unlock in failure path
+    - ocfs2: fix use-after-free when unmounting read-only filesystem
+    - ocfs2: check new file size on fallocate call
+    - nios2: dts: Fix tse_mac "max-frame-size" property
+    - nilfs2: fix incomplete buffer cleanup in nilfs_btnode_abort_change_key()
+    - nilfs2: fix possible out-of-bounds segment allocation in resize ioctl
+    - kexec: support purgatories with .text.hot sections
+    - powerpc/purgatory: remove PGO flags
+    - nouveau: fix client work fence deletion race
+    - RDMA/uverbs: Restrict usage of privileged QKEYs
+    - net: usb: qmi_wwan: add support for Compal RXM-G1
+    - ALSA: hda/realtek: Add a quirk for Compaq N14JP6
+    - Remove DECnet support from kernel
+    - [Config] updateconfigs for DECNET
+    - USB: serial: option: add Quectel EM061KGL series
+    - serial: lantiq: add missing interrupt ack
+    - usb: dwc3: gadget: Reset num TRBs before giving back the request
+    - spi: spi-fsl-dspi: Remove unused chip->void_write_data
+    - spi: fsl-dspi: avoid SCK glitches with continuous transfers
+    - netfilter: nfnetlink: skip error delivery on batch in case of ENOMEM
+    - ping6: Fix send to link-local addresses with VRF.
+    - RDMA/rxe: Remove the unused variable obj
+    - RDMA/rxe: Removed unused name from rxe_task struct
+    - RDMA/rxe: Fix the use-before-initialization error of resp_pkts
+    - iavf: remove mask from iavf_irq_enable_queues()
+    - IB/uverbs: Fix to consider event queue closing also upon non-blocking mode
+    - IB/isert: Fix dead lock in ib_isert
+    - IB/isert: Fix possible list corruption in CMA handler
+    - IB/isert: Fix incorrect release of isert connection
+    - ipvlan: fix bound dev checking for IPv6 l3s mode
+    - sctp: fix an error code in sctp_sf_eat_auth()
+    - igb: fix nvm.ops.read() error handling
+    - drm/nouveau/dp: check for NULL nv_connector->native_mode
+    - drm/nouveau/kms: Don't change EDID when it hasn't actually changed
+    - drm/nouveau: add nv_encoder pointer check for NULL
+    - net/sched: cls_api: Fix lockup on flushing explicitly created chain
+    - net: lapbether: only support ethernet devices
+    - net: tipc: resize nlattr array to correct size
+    - selftests/ptp: Fix timestamp printf format for PTP_SYS_OFFSET
+    - afs: Fix vlserver probe RTT handling
+    - neighbour: Remove unused inline function neigh_key_eq16()
+    - net: Remove unused inline function dst_hold_and_use()
+    - neighbour: delete neigh_lookup_nodev as not used
+    - drm/nouveau/kms: Fix NULL pointer dereference in
+      nouveau_connector_detect_depth
+    - mmc: block: ensure error propagation for non-blk
+    - Linux 5.4.248
+  * Focal update: v5.4.247 upstream stable release (LP: #2030818)
+    - blk-iocost: avoid 64-bit division in ioc_timer_fn
+    - block/blk-iocost (gcc13): keep large values in a new enum
+    - i40iw: fix build warning in i40iw_manage_apbvt()
+    - i40e: fix build warnings in i40e_alloc.h
+    - spi: qup: Request DMA before enabling clocks
+    - neighbour: Replace zero-length array with flexible-array member
+    - neighbour: fix unaligned access to pneigh_entry
+    - net: dsa: lan9303: allow vid != 0 in port_fdb_{add|del} methods
+    - Bluetooth: Fix l2cap_disconnect_req deadlock
+    - Bluetooth: L2CAP: Add missing checks for invalid DCID
+    - netfilter: conntrack: fix NULL pointer dereference in nf_confirm_cthelper
+    - netfilter: ipset: Add schedule point in call_ad().
+    - rfs: annotate lockless accesses to sk->sk_rxhash
+    - rfs: annotate lockless accesses to RFS sock flow table
+    - net: sched: move rtm_tca_policy declaration to include file
+    - net: sched: fix possible refcount leak in tc_chain_tmplt_add()
+    - lib: cpu_rmap: Fix potential use-after-free in irq_cpu_rmap_release()
+    - bnxt_en: Query default VLAN before VNIC setup on a VF
+    - batman-adv: Broken sync while rescheduling delayed work
+    - Input: xpad - delete a Razer DeathAdder mouse VID/PID entry
+    - Input: psmouse - fix OOB access in Elantech protocol
+    - ALSA: hda/realtek: Add a quirk for HP Slim Desktop S01
+    - ALSA: hda/realtek: Add Lenovo P3 Tower platform
+    - drm/amdgpu: fix xclk freq on CHIP_STONEY
+    - can: j1939: j1939_sk_send_loop_abort(): improved error queue handling in
+      J1939 Socket
+    - can: j1939: change j1939_netdev_lock type to mutex
+    - can: j1939: avoid possible use-after-free when j1939_can_rx_register fails
+    - ceph: fix use-after-free bug for inodes when flushing capsnaps
+    - Bluetooth: Fix use-after-free in hci_remove_ltk/hci_remove_irk
+    - rbd: move RBD_OBJ_FLAG_COPYUP_ENABLED flag setting
+    - pinctrl: meson-axg: add missing GPIOA_18 gpio group
+    - usb: usbfs: Enforce page requirements for mmap
+    - usb: usbfs: Use consistent mmap functions
+    - bonding (gcc13): synchronize bond_{a,t}lb_xmit() types
+    - i2c: sprd: Delete i2c adapter in .remove's error path
+    - eeprom: at24: also select REGMAP
+    - ext4: only check dquot_initialize_needed() when debugging
+    - drm/atomic: Don't pollute crtc_state->mode_blob with error pointers
+    - rbd: get snapshot context after exclusive lock is ensured to be held
+    - mtd: spinand: macronix: Add support for MX35LFxGE4AD
+    - Linux 5.4.247
+  * CVE-2023-4128
+    - net/sched: cls_u32: No longer copy tcf_result on update to avoid use-after-
+      free
+    - net/sched: cls_fw: No longer copy tcf_result on update to avoid use-after-
+      free
+    - net/sched: cls_route: No longer copy tcf_result on update to avoid use-
+      after-free
+  * CVE-2023-3863
+    - nfc: llcp: simplify llcp_sock_connect() error paths
+    - net: nfc: Fix use-after-free caused by nfc_llcp_find_local
+  * CVE-2023-3212
+    - gfs2: Don't deref jdesc in evict
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Thu, 14 Sep 2023 20:09:45 +1000
+
+linux-xilinx-zynqmp (5.4.0-1030.34) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1030.34 -proposed tracker (LP: #2034245)
+
+  [ Ubuntu: 5.4.0-163.180 ]
+
+  * focal/linux: 5.4.0-163.180 -proposed tracker (LP: #2034247)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update helper scripts
+  * CVE-2023-40283
+    - Bluetooth: L2CAP: Fix use-after-free in l2cap_sock_ready_cb
+  * CVE-2023-20588
+    - x86/bugs: Increase the x86 bugs vector size to two u32s
+    - x86/CPU/AMD: Do not leak quotient data after a division by 0
+    - x86/CPU/AMD: Fix the DIV(0) initial fix attempt
+  * CVE-2023-4128
+    - net/sched: cls_u32: No longer copy tcf_result on update to avoid use-after-
+      free
+    - net/sched: cls_fw: No longer copy tcf_result on update to avoid use-after-
+      free
+    - net/sched: cls_route: No longer copy tcf_result on update to avoid use-
+      after-free
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Fri, 08 Sep 2023 10:43:09 +1000
+
+linux-xilinx-zynqmp (5.4.0-1029.33) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1029.33 -proposed tracker (LP: #2031015)
+
+  * Focal update: v5.4.246 upstream stable release (LP: #2028981)
+    - [Config] updateconfigs for SCSI_DPT_I2O
+
+  [ Ubuntu: 5.4.0-162.179 ]
+
+  * focal/linux: 5.4.0-162.179 -proposed tracker (LP: #2031128)
+  * libgnutls report "trap invalid opcode" when trying to install packages over
+    https (LP: #2031093)
+    - [Config]: disable CONFIG_GDS_FORCE_MITIGATION
+
+  [ Ubuntu: 5.4.0-160.177 ]
+
+  * focal/linux: 5.4.0-160.177 -proposed tracker (LP: #2031017)
+  * Fix boot test warning for log_check "CPU: 0 PID: 0 at
+    arch/x86/kernel/fpu/xstate.c:878 get_xsave_addr+0x98/0xb0" (LP: #2031022)
+    - x86/pkeys: Revert a5eff7259790 ("x86/pkeys: Add PKRU value to init_fpstate")
+
+ -- Wen-chien Jesse Sung <jesse.sung@canonical.com>  Fri, 25 Aug 2023 19:46:01 +0800
+
+linux-xilinx-zynqmp (5.4.0-1028.32) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1028.32 -proposed tracker (LP: #2030630)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync update-dkms-versions helper
+
+  [ Ubuntu: 5.4.0-159.176 ]
+
+  * focal/linux: 5.4.0-159.176 -proposed tracker (LP: #2031149)
+  * libgnutls report "trap invalid opcode" when trying to install packages over
+    https (LP: #2031093)
+    - [Config]: disable CONFIG_GDS_FORCE_MITIGATION
+  * Fix boot test warning for log_check "CPU: 0 PID: 0 at
+    arch/x86/kernel/fpu/xstate.c:878 get_xsave_addr+0x98/0xb0" (LP: #2031022)
+    - x86/pkeys: Revert a5eff7259790 ("x86/pkeys: Add PKRU value to init_fpstate")
+
+  [ Ubuntu: 5.4.0-157.174 ]
+
+  * focal/linux: 5.4.0-157.174 -proposed tracker (LP: #2030632)
+  * CVE-2022-40982
+    - x86/mm: Initialize text poking earlier
+    - x86/mm: fix poking_init() for Xen PV guests
+    - x86/mm: Use mm_alloc() in poking_init()
+    - mm: Move mm_cachep initialization to mm_init()
+    - init: Provide arch_cpu_finalize_init()
+    - x86/cpu: Switch to arch_cpu_finalize_init()
+    - ARM: cpu: Switch to arch_cpu_finalize_init()
+    - sparc/cpu: Switch to arch_cpu_finalize_init()
+    - um/cpu: Switch to arch_cpu_finalize_init()
+    - init: Remove check_bugs() leftovers
+    - init: Invoke arch_cpu_finalize_init() earlier
+    - init, x86: Move mem_encrypt_init() into arch_cpu_finalize_init()
+    - x86/fpu: Remove cpuinfo argument from init functions
+    - x86/fpu: Mark init functions __init
+    - x86/fpu: Move FPU initialization into arch_cpu_finalize_init()
+    - x86/xen: Fix secondary processors' FPU initialization
+    - x86/speculation: Add Gather Data Sampling mitigation
+    - x86/speculation: Add force option to GDS mitigation
+    - x86/speculation: Add Kconfig option for GDS
+    - KVM: Add GDS_NO support to KVM
+    - Documentation/x86: Fix backwards on/off logic about YMM support
+    - [Config]: Enable CONFIG_ARCH_HAS_CPU_FINALIZE_INIT and
+      CONFIG_GDS_FORCE_MITIGATION
+  * CVE-2023-20593
+    - x86/cpu/amd: Move the errata checking functionality up
+    - x86/cpu/amd: Add a Zenbleed fix
+  * CVE-2023-3776
+    - net/sched: cls_fw: Fix improper refcount update leads to use-after-free
+  * CVE-2023-3611
+    - net/sched: sch_qfq: account for stab overhead in qfq_enqueue
+  * CVE-2023-3609
+    - net/sched: cls_u32: Fix reference counter leak leading to overflow
+
+ -- Wen-chien Jesse Sung <jesse.sung@canonical.com>  Thu, 17 Aug 2023 22:00:01 +0800
+
+linux-xilinx-zynqmp (5.4.0-1027.31) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1027.31 -proposed tracker (LP: #2026582)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync update-dkms-versions helper
+    - [Packaging] resync getabis
+
+  [ Ubuntu: 5.4.0-156.173 ]
+
+  * focal/linux: 5.4.0-156.173 -proposed tracker (LP: #2026585)
+  * CVE-2023-3390
+    - netfilter: nf_tables: incorrect error path handling with NFT_MSG_NEWRULE
+  * Focal update: v5.4.241 upstream stable release (LP: #2023930)
+    - scsi: ses: Handle enclosure with just a primary component gracefully
+    - x86/PCI: Add quirk for AMD XHCI controller that loses MSI-X state in D3hot
+    - cgroup/cpuset: Wake up cpuset_attach_wq tasks in cpuset_cancel_attach()
+    - treewide: Replace DECLARE_TASKLET() with DECLARE_TASKLET_OLD()
+    - smb3: fix problem with null cifs super block with previous patch
+    - pinctrl: amd: Use irqchip template
+    - pinctrl: amd: disable and mask interrupts on probe
+    - pinctrl: amd: Disable and mask interrupts on resume
+    - pwm: cros-ec: Explicitly set .polarity in .get_state()
+    - pwm: sprd: Explicitly set .polarity in .get_state()
+    - wifi: mac80211: fix invalid drv_sta_pre_rcu_remove calls for non-uploaded
+      sta
+    - icmp: guard against too small mtu
+    - net: don't let netpoll invoke NAPI if in xmit context
+    - sctp: check send stream number after wait_for_sndbuf
+    - ipv6: Fix an uninit variable access bug in __ip6_make_skb()
+    - gpio: davinci: Add irq chip flag to skip set wake
+    - sunrpc: only free unix grouplist after RCU settles
+    - NFSD: callback request does not use correct credential for AUTH_SYS
+    - xhci: also avoid the XHCI_ZERO_64B_REGS quirk with a passthrough iommu
+    - USB: serial: cp210x: add Silicon Labs IFS-USB-DATACABLE IDs
+    - usb: typec: altmodes/displayport: Fix configure initial pin assignment
+    - USB: serial: option: add Telit FE990 compositions
+    - USB: serial: option: add Quectel RM500U-CN modem
+    - iio: adc: ti-ads7950: Set `can_sleep` flag for GPIO chip
+    - iio: dac: cio-dac: Fix max DAC write value check for 12-bit
+    - tty: serial: sh-sci: Fix transmit end interrupt handler
+    - tty: serial: sh-sci: Fix Rx on RZ/G2L SCI
+    - tty: serial: fsl_lpuart: avoid checking for transfer complete when
+      UARTCTRL_SBK is asserted in lpuart32_tx_empty
+    - nilfs2: fix potential UAF of struct nilfs_sc_info in nilfs_segctor_thread()
+    - nilfs2: fix sysfs interface lifetime
+    - ALSA: hda/realtek: Add quirk for Clevo X370SNW
+    - perf/core: Fix the same task check in perf_event_set_output
+    - ftrace: Mark get_lock_parent_ip() __always_inline
+    - can: j1939: j1939_tp_tx_dat_new(): fix out-of-bounds memory access
+    - tracing: Free error logs of tracing instances
+    - net_sched: prevent NULL dereference if default qdisc setup failed
+    - drm/panfrost: Fix the panfrost_mmu_map_fault_addr() error path
+    - ring-buffer: Fix race while reader and writer are on the same page
+    - mm/swap: fix swap_info_struct race between swapoff and get_swap_pages()
+    - irqdomain: Look for existing mapping only once
+    - irqdomain: Refactor __irq_domain_alloc_irqs()
+    - irqdomain: Fix mapping-creation race
+    - Revert "pinctrl: amd: Disable and mask interrupts on resume"
+    - ALSA: emu10k1: fix capture interrupt handler unlinking
+    - ALSA: hda/sigmatel: add pin overrides for Intel DP45SG motherboard
+    - ALSA: i2c/cs8427: fix iec958 mixer control deactivation
+    - ALSA: firewire-tascam: add missing unwind goto in
+      snd_tscm_stream_start_duplex()
+    - ALSA: hda/sigmatel: fix S/PDIF out on Intel D*45* motherboards
+    - Bluetooth: L2CAP: Fix use-after-free in l2cap_disconnect_{req,rsp}
+    - Bluetooth: Fix race condition in hidp_session_thread
+    - btrfs: print checksum type and implementation at mount time
+    - btrfs: fix fast csum implementation detection
+    - mtdblock: tolerate corrected bit-flips
+    - mtd: rawnand: meson: fix bitmask for length in command word
+    - mtd: rawnand: stm32_fmc2: remove unsupported EDO mode
+    - niu: Fix missing unwind goto in niu_alloc_channels()
+    - qlcnic: check pci_reset_function result
+    - sctp: fix a potential overflow in sctp_ifwdtsn_skip
+    - RDMA/core: Fix GID entry ref leak when create_ah fails
+    - udp6: fix potential access to stale information
+    - net: macb: fix a memory corruption in extended buffer descriptor mode
+    - power: supply: cros_usbpd: reclassify "default case!" as debug
+    - i2c: imx-lpi2c: clean rx/tx buffers upon new message
+    - efi: sysfb_efi: Add quirk for Lenovo Yoga Book X91F/L
+    - drm: panel-orientation-quirks: Add quirk for Lenovo Yoga Book X90F
+    - verify_pefile: relax wrapper length check
+    - asymmetric_keys: log on fatal failures in PE/pkcs7
+    - ubi: Fix failure attaching when vid_hdr offset equals to (sub)page size
+    - mtd: ubi: wl: Fix a couple of kernel-doc issues
+    - ubi: Fix deadlock caused by recursively holding work_sem
+    - i2c: ocores: generate stop condition after timeout in polling mode
+    - watchdog: sbsa_wdog: Make sure the timeout programming is within the limits
+    - coresight-etm4: Fix for() loop drvdata->nr_addr_cmp range bug
+    - xfs: show the proper user quota options
+    - xfs: remove the kuid/kgid conversion wrappers
+    - xfs: add a new xfs_sb_version_has_v3inode helper
+    - xfs: only check the superblock version for dinode size calculation
+    - xfs: simplify di_flags2 inheritance in xfs_ialloc
+    - xfs: simplify a check in xfs_ioctl_setattr_check_cowextsize
+    - xfs: remove the di_version field from struct icdinode
+    - xfs: set inode size after creating symlink
+    - xfs: report corruption only as a regular error
+    - xfs: shut down the filesystem if we screw up quota reservation
+    - xfs: consider shutdown in bmapbt cursor delete assert
+    - xfs: don't reuse busy extents on extent trim
+    - xfs: force log and push AIL to clear pinned inodes when aborting mount
+    - Linux 5.4.241
+  * [UBUNTU 20.04] [HPS] Kernel panic with "refcount_t: underflow" in mlx5
+    driver (LP: #2019011)
+    - net/mlx5: cmdif, Avoid skipping reclaim pages if FW is not accessible
+    - net/mlx5: Fix handling of entry refcount when command is not issued to FW
+  * Disable hv-kvp-daemon if /dev/vmbus/hv_kvp is not present (LP: #2024900)
+    - [Packaging] disable hv-kvp-daemon if needed
+  * CVE-2023-35001
+    - netfilter: nf_tables: prevent OOB access in nft_byteorder_eval
+  * CVE-2023-32629
+    - ovl: adhere to the vfs_ vs. ovl_do_ conventions for xattrs
+  * CVE-2023-3141
+    - memstick: r592: Fix UAF bug in r592_remove due to race condition
+  * CVE-2023-3111
+    - btrfs: check return value of btrfs_commit_transaction in relocation
+    - btrfs: unset reloc control if transaction commit fails in
+      prepare_to_relocate()
+  * CVE-2023-3090
+    - ipvlan:Fix out-of-bounds caused by unclear skb->cb
+  * CVE-2023-1611
+    - btrfs: fix race between quota disable and quota assign ioctls
+  * CVE-2022-0168
+    - cifs: move some variables off the stack in smb2_ioctl_query_info
+    - cifs: prevent bad output lengths in smb2_ioctl_query_info()
+    - cifs: fix NULL ptr dereference in smb2_ioctl_query_info()
+  * CVE-2022-27672
+    - x86/speculation: Identify processors vulnerable to SMT RSB predictions
+    - KVM: x86: Mitigate the cross-thread return address predictions bug
+    - Documentation/hw-vuln: Add documentation for Cross-Thread Return Predictions
+  * Severe NFS performance degradation after LP #2003053 (LP: #2022098)
+    - SAUCE: Make NFS file-access stale cache behaviour opt-in
+  * Encountering an issue with memcpy_fromio causing failed boot of SEV-enabled
+    guest (LP: #2020319)
+    - x86/sev: Unroll string mmio with CC_ATTR_GUEST_UNROLL_STRING_IO
+  * Focal update: v5.4.240 upstream stable release (LP: #2023601)
+    - net: tls: fix possible race condition between do_tls_getsockopt_conf() and
+      do_tls_setsockopt_conf()
+    - power: supply: da9150: Fix use after free bug in da9150_charger_remove due
+      to race condition
+    - iavf: fix inverted Rx hash condition leading to disabled hash
+    - iavf: fix non-tunneled IPv6 UDP packet type and hashing
+    - intel/igbvf: free irq on the error path in igbvf_request_msix()
+    - igbvf: Regard vf reset nack as success
+    - i2c: imx-lpi2c: check only for enabled interrupt flags
+    - scsi: scsi_dh_alua: Fix memleak for 'qdata' in alua_activate()
+    - net: usb: smsc95xx: Limit packet length to skb->len
+    - qed/qed_sriov: guard against NULL derefs from qed_iov_get_vf_info
+    - net: qcom/emac: Fix use after free bug in emac_remove due to race condition
+    - net/ps3_gelic_net: Fix RX sk_buff length
+    - net/ps3_gelic_net: Use dma_mapping_error
+    - keys: Do not cache key in task struct if key is requested from kernel thread
+    - bpf: Adjust insufficient default bpf_jit_limit
+    - net/mlx5: Read the TC mapping of all priorities on ETS query
+    - atm: idt77252: fix kmemleak when rmmod idt77252
+    - erspan: do not use skb_mac_header() in ndo_start_xmit()
+    - net/sonic: use dma_mapping_error() for error check
+    - nvme-tcp: fix nvme_tcp_term_pdu to match spec
+    - hvc/xen: prevent concurrent accesses to the shared ring
+    - net: mdio: thunder: Add missing fwnode_handle_put()
+    - Bluetooth: btqcomsmd: Fix command timeout after setting BD address
+    - platform/chrome: cros_ec_chardev: fix kernel data leak from ioctl
+    - hwmon (it87): Fix voltage scaling for chips with 10.9mV ADCs
+    - scsi: qla2xxx: Perform lockless command completion in abort path
+    - uas: Add US_FL_NO_REPORT_OPCODES for JMicron JMS583Gen 2
+    - thunderbolt: Use const qualifier for `ring_interrupt_index`
+    - riscv: Bump COMMAND_LINE_SIZE value to 1024
+    - ca8210: fix mac_len negative array access
+    - m68k: Only force 030 bus error if PC not in exception table
+    - selftests/bpf: check that modifier resolves after pointer
+    - scsi: target: iscsi: Fix an error message in iscsi_check_key()
+    - scsi: ufs: core: Add soft dependency on governor_simpleondemand
+    - scsi: lpfc: Avoid usage of list iterator variable after loop
+    - net: usb: cdc_mbim: avoid altsetting toggling for Telit FE990
+    - net: usb: qmi_wwan: add Telit 0x1080 composition
+    - sh: sanitize the flags on sigreturn
+    - cifs: empty interface list when server doesn't support query interfaces
+    - scsi: core: Add BLIST_SKIP_VPD_PAGES for SKhynix H28U74301AMR
+    - usb: gadget: u_audio: don't let userspace block driver unbind
+    - fsverity: Remove WQ_UNBOUND from fsverity read workqueue
+    - igb: revert rtnl_lock() that causes deadlock
+    - dm thin: fix deadlock when swapping to thin device
+    - usb: cdns3: Fix issue with using incorrect PCI device function
+    - usb: chipdea: core: fix return -EINVAL if request role is the same with
+      current role
+    - usb: chipidea: core: fix possible concurrent when switch role
+    - wifi: mac80211: fix qos on mesh interfaces
+    - nilfs2: fix kernel-infoleak in nilfs_ioctl_wrap_copy()
+    - i2c: xgene-slimpro: Fix out-of-bounds bug in xgene_slimpro_i2c_xfer()
+    - dm stats: check for and propagate alloc_percpu failure
+    - dm crypt: add cond_resched() to dmcrypt_write()
+    - sched/fair: sanitize vruntime of entity being placed
+    - sched/fair: Sanitize vruntime of entity being migrated
+    - tun: avoid double free in tun_free_netdev
+    - ocfs2: fix data corruption after failed write
+    - fsverity: don't drop pagecache at end of FS_IOC_ENABLE_VERITY
+    - bus: imx-weim: fix branch condition evaluates to a garbage value
+    - md: avoid signed overflow in slot_store()
+    - ALSA: asihpi: check pao in control_message()
+    - ALSA: hda/ca0132: fixup buffer overrun at tuning_ctl_set()
+    - fbdev: tgafb: Fix potential divide by zero
+    - sched_getaffinity: don't assume 'cpumask_size()' is fully initialized
+    - fbdev: nvidia: Fix potential divide by zero
+    - fbdev: intelfb: Fix potential divide by zero
+    - fbdev: lxfb: Fix potential divide by zero
+    - fbdev: au1200fb: Fix potential divide by zero
+    - ca8210: Fix unsigned mac_len comparison with zero in ca8210_skb_tx()
+    - dma-mapping: drop the dev argument to arch_sync_dma_for_*
+    - mips: bmips: BCM6358: disable RAC flush for TP1
+    - mtd: rawnand: meson: invalidate cache on polling ECC bit
+    - scsi: megaraid_sas: Fix crash after a double completion
+    - ptp_qoriq: fix memory leak in probe()
+    - regulator: fix spelling mistake "Cant" -> "Can't"
+    - regulator: Handle deferred clk
+    - net/net_failover: fix txq exceeding warning
+    - can: bcm: bcm_tx_setup(): fix KMSAN uninit-value in vfs_write
+    - s390/vfio-ap: fix memory leak in vfio_ap device driver
+    - i40e: fix registers dump after run ethtool adapter self test
+    - bnxt_en: Fix typo in PCI id to device description string mapping
+    - net: dsa: mv88e6xxx: Enable IGMP snooping on user ports only
+    - net: mvneta: make tx buffer array agnostic
+    - pinctrl: ocelot: Fix alt mode for ocelot
+    - Input: alps - fix compatibility with -funsigned-char
+    - Input: focaltech - use explicitly signed char type
+    - cifs: prevent infinite recursion in CIFSGetDFSRefer()
+    - cifs: fix DFS traversal oops without CONFIG_CIFS_DFS_UPCALL
+    - Input: goodix - add Lenovo Yoga Book X90F to nine_bytes_report DMI table
+    - xen/netback: don't do grant copy across page boundary
+    - pinctrl: at91-pio4: fix domain name assignment
+    - NFSv4: Fix hangs when recovering open state after a server reboot
+    - ALSA: hda/conexant: Partial revert of a quirk for Lenovo
+    - ALSA: usb-audio: Fix regression on detection of Roland VS-100
+    - drm/etnaviv: fix reference leak when mmaping imported buffer
+    - btrfs: scan device in non-exclusive mode
+    - ext4: fix kernel BUG in 'ext4_write_inline_data_end()'
+    - net_sched: add __rcu annotation to netdev->qdisc
+    - net: sched: fix race condition in qdisc_graft()
+    - firmware: arm_scmi: Fix device node validation for mailbox transport
+    - gfs2: Always check inode size of inline inodes
+    - Linux 5.4.240
+  * Focal update: v5.4.239 upstream stable release (LP: #2023600)
+    - Linux 5.4.239
+  * CVE-2023-2124
+    - xfs: verify buffer contents when we skip log replay
+  * CVE-2020-36691
+    - netlink: limit recursion depth in policy validation
+  * CVE-2022-1184
+    - ext4: check if directory block is within i_size
+    - ext4: fix check for block being out of directory size
+  * CVE-2022-4269
+    - net: sched: extract qstats update code into functions
+    - net: sched: don't expose action qstats to skb_tc_reinsert()
+    - net/sched: act_mirred: refactor the handle of xmit
+    - net: sched: remove unused tcf_result extension
+    - net/sched: act_mirred: better wording on protection against excessive stack
+      growth
+    - act_mirred: use the backlog for nested calls to mirred ingress
+  * Focal update: v5.4.238 upstream stable release (LP: #2023427)
+    - ext4: fix cgroup writeback accounting with fs-layer encryption
+    - xfrm: Allow transport-mode states with AF_UNSPEC selector
+    - drm/panfrost: Don't sync rpm suspension after mmu flushing
+    - cifs: Move the in_send statistic to __smb_send_rqst()
+    - drm/meson: fix 1px pink line on GXM when scaling video overlay
+    - clk: HI655X: select REGMAP instead of depending on it
+    - docs: Correct missing "d_" prefix for dentry_operations member
+      d_weak_revalidate
+    - scsi: mpt3sas: Fix NULL pointer access in mpt3sas_transport_port_add()
+    - ALSA: hda - add Intel DG1 PCI and HDMI ids
+    - ALSA: hda - controller is in GPU on the DG1
+    - ALSA: hda: Add Alderlake-S PCI ID and HDMI codec vid
+    - ALSA: hda: Add Intel DG2 PCI ID and HDMI codec vid
+    - ALSA: hda: Match only Intel devices with CONTROLLER_IN_GPU()
+    - netfilter: nft_redir: correct value of inet type `.maxattrs`
+    - scsi: core: Fix a comment in function scsi_host_dev_release()
+    - scsi: core: Fix a procfs host directory removal regression
+    - tcp: tcp_make_synack() can be called from process context
+    - nfc: pn533: initialize struct pn533_out_arg properly
+    - ipvlan: Make skb->skb_iif track skb->dev for l3s mode
+    - i40e: Fix kernel crash during reboot when adapter is in recovery mode
+    - qed/qed_dev: guard against a possible division by zero
+    - net: tunnels: annotate lockless accesses to dev->needed_headroom
+    - net: phy: smsc: bail out in lan87xx_read_status if genphy_read_status fails
+    - nfc: st-nci: Fix use after free bug in ndlc_remove due to race condition
+    - net: usb: smsc75xx: Limit packet length to skb->len
+    - nvmet: avoid potential UAF in nvmet_req_complete()
+    - block: sunvdc: add check for mdesc_grab() returning NULL
+    - ipv4: Fix incorrect table ID in IOCTL path
+    - net: usb: smsc75xx: Move packet length check to prevent kernel panic in
+      skb_pull
+    - net/iucv: Fix size of interrupt data
+    - ethernet: sun: add check for the mdesc_grab()
+    - hwmon: (adt7475) Display smoothing attributes in correct order
+    - hwmon: (adt7475) Fix masking of hysteresis registers
+    - hwmon: (xgene) Fix use after free bug in xgene_hwmon_remove due to race
+      condition
+    - hwmon: (ina3221) return prober error code
+    - media: m5mols: fix off-by-one loop termination error
+    - mmc: atmel-mci: fix race between stop command and start of next command
+    - jffs2: correct logic when creating a hole in jffs2_write_begin
+    - ext4: fail ext4_iget if special inode unallocated
+    - ext4: fix task hung in ext4_xattr_delete_inode
+    - drm/amdkfd: Fix an illegal memory access
+    - sh: intc: Avoid spurious sizeof-pointer-div warning
+    - ext4: fix possible double unlock when moving a directory
+    - tty: serial: fsl_lpuart: skip waiting for transmission complete when
+      UARTCTRL_SBK is asserted
+    - interconnect: fix mem leak when freeing nodes
+    - tracing: Check field value in hist_field_name()
+    - tracing: Make tracepoint lockdep check actually test something
+    - ftrace: Fix invalid address access in lookup_rec() when index is 0
+    - fbdev: stifb: Provide valid pixelclock and add fb_check_var() checks
+    - x86/mm: Fix use of uninitialized buffer in sme_enable()
+    - drm/i915: Don't use stolen memory for ring buffers with LLC
+    - serial: 8250_em: Fix UART port type
+    - s390/ipl: add missing intersection check to ipl_report handling
+    - PCI: Unify delay handling for reset and resume
+    - HID: core: Provide new max_buffer_size attribute to over-ride the default
+    - HID: uhid: Over-ride the default maximum data buffer value with our own
+    - Linux 5.4.238
+  * Focal update: v5.4.237 upstream stable release (LP: #2023420)
+    - fs: prevent out-of-bounds array speculation when closing a file descriptor
+    - x86/CPU/AMD: Disable XSAVES on AMD family 0x17
+    - drm/connector: print max_requested_bpc in state debugfs
+    - ext4: fix RENAME_WHITEOUT handling for inline directories
+    - ext4: fix another off-by-one fsmap error on 1k block filesystems
+    - ext4: move where set the MAY_INLINE_DATA flag is set
+    - ext4: fix WARNING in ext4_update_inline_data
+    - ext4: zero i_disksize when initializing the bootloader inode
+    - nfc: change order inside nfc_se_io error path
+    - iommu/amd: Add PCI segment support for ivrs_[ioapic/hpet/acpihid] commands
+    - iommu/amd: Fix ill-formed ivrs_ioapic, ivrs_hpet and ivrs_acpihid options
+    - iommu/amd: Add a length limitation for the ivrs_acpihid command-line
+      parameter
+    - ipmi:ssif: make ssif_i2c_send() void
+    - ipmi:ssif: resend_msg() cannot fail
+    - ipmi:ssif: Remove rtc_us_timer
+    - ipmi:ssif: Increase the message retry time
+    - ipmi:ssif: Add a timer between request retries
+    - irqdomain: Change the type of 'size' in __irq_domain_add() to be consistent
+    - irqdomain: Fix domain registration race
+    - iommu/vt-d: Fix PASID directory pointer coherency
+    - SMB3: Backup intent flag missing from some more ops
+    - cifs: Fix uninitialized memory read in smb3_qfs_tcon()
+    - scsi: core: Remove the /proc/scsi/${proc_name} directory earlier
+    - ext4: Fix possible corruption when moving a directory
+    - drm/msm/a5xx: fix setting of the CP_PREEMPT_ENABLE_LOCAL register
+    - nfc: fdp: add null check of devm_kmalloc_array in
+      fdp_nci_i2c_read_device_properties
+    - ila: do not generate empty messages in ila_xlat_nl_cmd_get_mapping()
+    - selftests: nft_nat: ensuring the listening side is up before starting the
+      client
+    - net: usb: lan78xx: Remove lots of set but unused 'ret' variables
+    - net: lan78xx: fix accessing the LAN7800's internal phy specific registers
+      from the MAC driver
+    - net: caif: Fix use-after-free in cfusbl_device_notify()
+    - bnxt_en: Avoid order-5 memory allocation for TPA data
+    - netfilter: tproxy: fix deadlock due to missing BH disable
+    - btf: fix resolving BTF_KIND_VAR after ARRAY, STRUCT, UNION, PTR
+    - scsi: megaraid_sas: Update max supported LD IDs to 240
+    - net/smc: fix fallback failed while sendmsg with fastopen
+    - riscv: Use READ_ONCE_NOCHECK in imprecise unwinding stack mode
+    - ext4: Fix deadlock during directory rename
+    - MIPS: Fix a compilation issue
+    - alpha: fix R_ALPHA_LITERAL reloc for large modules
+    - macintosh: windfarm: Use unsigned type for 1-bit bitfields
+    - PCI: Add SolidRun vendor ID
+    - media: ov5640: Fix analogue gain control
+    - ipmi/watchdog: replace atomic_add() and atomic_sub()
+    - ipmi:watchdog: Set panic count to proper value on a panic
+    - drm/i915: Don't use BAR mappings for ring buffers with LLC
+    - x86, vmlinux.lds: Add RUNTIME_DISCARD_EXIT to generic DISCARDS
+    - arch: fix broken BuildID for arm64 and riscv
+    - powerpc/vmlinux.lds: Define RUNTIME_DISCARD_EXIT
+    - powerpc/vmlinux.lds: Don't discard .rela* for relocatable builds
+    - s390: define RUNTIME_DISCARD_EXIT to fix link error with GNU ld < 2.36
+    - sh: define RUNTIME_DISCARD_EXIT
+    - UML: define RUNTIME_DISCARD_EXIT
+    - s390/dasd: add missing discipline function
+    - Linux 5.4.237
+  * Focal update: v5.4.236 upstream stable release (LP: #2020390)
+    - staging: rtl8192e: Remove function ..dm_check_ac_dc_power calling a script
+    - staging: rtl8192e: Remove call_usermodehelper starting RadioPower.sh
+    - Linux 5.4.236
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync update-dkms-versions helper
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Fri, 28 Jul 2023 05:30:21 +1000
+
+linux-xilinx-zynqmp (5.4.0-1026.30) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1026.30 -proposed tracker (LP: #2026398)
+
+  [ Ubuntu: 5.4.0-155.172 ]
+
+  * focal/linux: 5.4.0-155.172 -proposed tracker (LP: #2026401)
+  * CVE-2023-3390
+    - netfilter: nf_tables: incorrect error path handling with NFT_MSG_NEWRULE
+  * CVE-2023-35001
+    - netfilter: nf_tables: prevent OOB access in nft_byteorder_eval
+  * CVE-2023-32629
+    - ovl: adhere to the vfs_ vs. ovl_do_ conventions for xattrs
+  * CVE-2023-3090
+    - ipvlan:Fix out-of-bounds caused by unclear skb->cb
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync update-dkms-versions helper
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Thu, 13 Jul 2023 10:31:41 +1000
+
+linux-xilinx-zynqmp (5.4.0-1025.29) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1025.29 -proposed tracker (LP: #2024105)
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync update-dkms-versions helper
+
+  [ Ubuntu: 5.4.0-153.170 ]
+
+  * focal/linux: 5.4.0-153.170 -proposed tracker (LP: #2024108)
+  * cls_flower: off-by-one in fl_set_geneve_opt (LP: #2023577)
+    - net/sched: flower: fix possible OOB write in fl_set_geneve_opt()
+  * Some INVLPG implementations can leave Global translations unflushed when
+    PCIDs are enabled (LP: #2023220)
+    - x86/mm: Avoid incomplete Global INVLPG flushes
+
+  [ Ubuntu: 5.4.0-152.169 ]
+
+  * focal/linux: 5.4.0-152.169 -proposed tracker (LP: #2023070)
+  * Focal update: v5.4.236 upstream stable release (LP: #2020390)
+    - wifi: cfg80211: Partial revert "wifi: cfg80211: Fix use after free for wext"
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync git-ubuntu-log
+    - [Packaging] resync getabis
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Tue, 11 Jul 2023 08:48:45 +1000
+
+linux-xilinx-zynqmp (5.4.0-1024.28) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1024.28 -proposed tracker (LP: #2019372)
+
+  * Focal update: Focal update: v5.4.235 upstream stable release (LP: #2017706)
+    - [Config] update annotations for CONFIG_DRM_MXSFB
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync git-ubuntu-log
+    - [Packaging] resync getabis
+
+  [ Ubuntu: 5.4.0-151.168 ]
+
+  * focal/linux: 5.4.0-151.168 -proposed tracker (LP: #2019375)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update helper scripts
+    - debian/dkms-versions -- update from kernel-versions (main/2023.05.15)
+  * CVE-2023-32233
+    - netfilter: nf_tables: deactivate anonymous set from preparation phase
+  * CVE-2023-2612
+    - SAUCE: shiftfs: prevent lock unbalance in shiftfs_create_object()
+  * CVE-2023-31436
+    - net: sched: sch_qfq: prevent slab-out-of-bounds in qfq_activate_agg
+  * CVE-2023-1380
+    - wifi: brcmfmac: slab-out-of-bounds read in brcmf_get_assoc_ies()
+  * Focal update: Focal update: v5.4.235 upstream stable release (LP: #2017706)
+    - HID: asus: Remove check for same LED brightness on set
+    - HID: asus: use spinlock to protect concurrent accesses
+    - HID: asus: use spinlock to safely schedule workers
+    - ARM: OMAP2+: Fix memory leak in realtime_counter_init()
+    - arm64: dts: qcom: qcs404: use symbol names for PCIe resets
+    - ARM: zynq: Fix refcount leak in zynq_early_slcr_init
+    - arm64: dts: meson-gx: Fix Ethernet MAC address unit name
+    - arm64: dts: meson-g12a: Fix internal Ethernet PHY unit name
+    - arm64: dts: meson-gx: Fix the SCPI DVFS node name and unit address
+    - arm64: dts: meson: remove CPU opps below 1GHz for G12A boards
+    - ARM: OMAP1: call platform_device_put() in error case in
+      omap1_dm_timer_init()
+    - ARM: dts: exynos: correct wr-active property in Exynos3250 Rinato
+    - ARM: imx: Call ida_simple_remove() for ida_simple_get
+    - arm64: dts: amlogic: meson-gx: fix SCPI clock dvfs node name
+    - arm64: dts: amlogic: meson-axg: fix SCPI clock dvfs node name
+    - arm64: dts: amlogic: meson-gx: add missing SCPI sensors compatible
+    - arm64: dts: amlogic: meson-gx: add missing unit address to rng node name
+    - arm64: dts: amlogic: meson-gxl: add missing unit address to eth-phy-mux node
+      name
+    - arm64: dts: amlogic: meson-gxl-s905d-phicomm-n1: fix led node name
+    - ARM: dts: imx7s: correct iomuxc gpr mux controller cells
+    - arm64: dts: mediatek: mt7622: Add missing pwm-cells to pwm node
+    - Revert "scsi: core: run queue if SCSI device queue isn't ready and queue is
+      idle"
+    - block: Limit number of items taken from the I/O scheduler in one go
+    - blk-mq: remove stale comment for blk_mq_sched_mark_restart_hctx
+    - blk-mq: wait on correct sbitmap_queue in blk_mq_mark_tag_wait
+    - blk-mq: correct stale comment of .get_budget
+    - s390/dasd: Prepare for additional path event handling
+    - s390/dasd: Fix potential memleak in dasd_eckd_init()
+    - sched/deadline,rt: Remove unused parameter from pick_next_[rt|dl]_entity()
+    - sched/rt: pick_next_rt_entity(): check list_entry
+    - block: bio-integrity: Copy flags when bio_integrity_payload is cloned
+    - wifi: rsi: Fix memory leak in rsi_coex_attach()
+    - net/wireless: Delete unnecessary checks before the macro call
+      “dev_kfree_skb”
+    - wifi: iwlegacy: common: don't call dev_kfree_skb() under spin_lock_irqsave()
+    - wifi: libertas: fix memory leak in lbs_init_adapter()
+    - wifi: rtl8xxxu: don't call dev_kfree_skb() under spin_lock_irqsave()
+    - rtlwifi: fix -Wpointer-sign warning
+    - wifi: rtlwifi: Fix global-out-of-bounds bug in
+      _rtl8812ae_phy_set_txpower_limit()
+    - ipw2x00: switch from 'pci_' to 'dma_' API
+    - wifi: ipw2x00: don't call dev_kfree_skb() under spin_lock_irqsave()
+    - wifi: ipw2200: fix memory leak in ipw_wdev_init()
+    - wilc1000: let wilc_mac_xmit() return NETDEV_TX_OK
+    - wifi: wilc1000: fix potential memory leak in wilc_mac_xmit()
+    - wifi: brcmfmac: fix potential memory leak in brcmf_netdev_start_xmit()
+    - wifi: brcmfmac: unmap dma buffer in brcmf_msgbuf_alloc_pktid()
+    - wifi: libertas_tf: don't call kfree_skb() under spin_lock_irqsave()
+    - wifi: libertas: if_usb: don't call kfree_skb() under spin_lock_irqsave()
+    - wifi: libertas: main: don't call kfree_skb() under spin_lock_irqsave()
+    - wifi: libertas: cmdresp: don't call kfree_skb() under spin_lock_irqsave()
+    - wifi: wl3501_cs: don't call kfree_skb() under spin_lock_irqsave()
+    - crypto: x86/ghash - fix unaligned access in ghash_setkey()
+    - ACPICA: Drop port I/O validation for some regions
+    - genirq: Fix the return type of kstat_cpu_irqs_sum()
+    - lib/mpi: Fix buffer overrun when SG is too long
+    - ACPICA: nsrepair: handle cases without a return value correctly
+    - wifi: orinoco: check return value of hermes_write_wordrec()
+    - wifi: ath9k: htc_hst: free skb in ath9k_htc_rx_msg() if there is no callback
+      function
+    - ath9k: hif_usb: simplify if-if to if-else
+    - ath9k: htc: clean up statistics macros
+    - wifi: ath9k: hif_usb: clean up skbs if ath9k_hif_usb_rx_stream() fails
+    - wifi: ath9k: Fix potential stack-out-of-bounds write in
+      ath9k_wmi_rsp_callback()
+    - ACPI: battery: Fix missing NUL-termination with large strings
+    - crypto: ccp - Failure on re-initialization due to duplicate sysfs filename
+    - crypto: essiv - remove redundant null pointer check before kfree
+    - crypto: essiv - Handle EBUSY correctly
+    - crypto: seqiv - Handle EBUSY correctly
+    - powercap: fix possible name leak in powercap_register_zone()
+    - net/mlx5: Enhance debug print in page allocation failure
+    - irqchip/alpine-msi: Fix refcount leak in alpine_msix_init_domains
+    - irqchip/irq-mvebu-gicp: Fix refcount leak in mvebu_gicp_probe
+    - irqchip/ti-sci: Fix refcount leak in ti_sci_intr_irq_domain_probe
+    - mptcp: add sk_stop_timer_sync helper
+    - net: add sock_init_data_uid()
+    - tun: tun_chr_open(): correctly initialize socket uid
+    - tap: tap_open(): correctly initialize socket uid
+    - OPP: fix error checking in opp_migrate_dentry()
+    - Bluetooth: L2CAP: Fix potential user-after-free
+    - libbpf: Fix alen calculation in libbpf_nla_dump_errormsg()
+    - rds: rds_rm_zerocopy_callback() correct order for list_add_tail()
+    - crypto: rsa-pkcs1pad - Use akcipher_request_complete
+    - m68k: /proc/hardware should depend on PROC_FS
+    - RISC-V: time: initialize hrtimer based broadcast clock event device
+    - usb: gadget: udc: Avoid tasklet passing a global
+    - wifi: iwl3945: Add missing check for create_singlethread_workqueue
+    - wifi: iwl4965: Add missing check for create_singlethread_workqueue()
+    - wifi: mwifiex: fix loop iterator in mwifiex_update_ampdu_txwinsize()
+    - crypto: crypto4xx - Call dma_unmap_page when done
+    - wifi: mac80211: make rate u32 in sta_set_rate_info_rx()
+    - thermal/drivers/hisi: Drop second sensor hi3660
+    - can: esd_usb: Move mislocated storage of SJA1000_ECC_SEG bits in case of a
+      bus error
+    - irqchip/irq-brcmstb-l2: Set IRQ_LEVEL for level triggered interrupts
+    - irqchip/irq-bcm7120-l2: Set IRQ_LEVEL for level triggered interrupts
+    - selftests/net: Interpret UDP_GRO cmsg data as an int value
+    - drm/fourcc: Add missing big-endian XRGB1555 and RGB565 formats
+    - drm: mxsfb: DRM_MXSFB should depend on ARCH_MXS || ARCH_MXC
+    - drm/bridge: megachips: Fix error handling in i2c_register_driver()
+    - drm/vc4: dpi: Add option for inverting pixel clock and output enable
+    - drm/vc4: dpi: Fix format mapping for RGB565
+    - gpu: ipu-v3: common: Add of_node_put() for reference returned by
+      of_graph_get_port_by_id()
+    - drm/msm/hdmi: Add missing check for alloc_ordered_workqueue
+    - pinctrl: stm32: Fix refcount leak in stm32_pctrl_get_irq_domain
+    - ASoC: fsl_sai: initialize is_dsp_mode flag
+    - ALSA: hda/ca0132: minor fix for allocation size
+    - drm/mipi-dsi: Fix byte order of 16-bit DCS set/get brightness
+    - drm/msm: use strscpy instead of strncpy
+    - drm/msm/dpu: Add check for cstate
+    - drm/msm/dpu: Add check for pstates
+    - drm/exynos: Don't reset bridge->next
+    - drm/bridge: Rename bridge helpers targeting a bridge chain
+    - drm/bridge: Introduce drm_bridge_get_next_bridge()
+    - drm: Initialize struct drm_crtc_state.no_vblank from device settings
+    - drm/msm/mdp5: Add check for kzalloc
+    - gpu: host1x: Don't skip assigning syncpoints to channels
+    - drm/mediatek: remove cast to pointers passed to kfree
+    - drm/mediatek: Use NULL instead of 0 for NULL pointer
+    - drm/mediatek: Drop unbalanced obj unref
+    - drm/mediatek: Clean dangling pointer on bind error path
+    - ASoC: soc-compress.c: fixup private_data on snd_soc_new_compress()
+    - gpio: vf610: connect GPIO label to dev name
+    - hwmon: (ltc2945) Handle error case in ltc2945_value_store
+    - scsi: aic94xx: Add missing check for dma_map_single()
+    - spi: bcm63xx-hsspi: fix pm_runtime
+    - spi: bcm63xx-hsspi: Fix multi-bit mode setting
+    - hwmon: (mlxreg-fan) Return zero speed for broken fan
+    - dm: remove flush_scheduled_work() during local_exit()
+    - spi: synquacer: Fix timeout handling in synquacer_spi_transfer_one()
+    - ASoC: dapm: declare missing structure prototypes
+    - ASoC: soc-dapm.h: fixup warning struct snd_pcm_substream not declared
+    - HID: bigben: use spinlock to protect concurrent accesses
+    - HID: bigben_worker() remove unneeded check on report_field
+    - HID: bigben: use spinlock to safely schedule workers
+    - HID: asus: Only set EV_REP if we are adding a mapping
+    - HID: asus: Add report_size to struct asus_touchpad_info
+    - HID: asus: Add support for multi-touch touchpad on Medion Akoya E1239T
+    - HID: asus: Fix mute and touchpad-toggle keys on Medion Akoya E1239T
+    - hid: bigben_probe(): validate report count
+    - nfsd: fix race to check ls_layouts
+    - cifs: Fix lost destroy smbd connection when MR allocate failed
+    - cifs: Fix warning and UAF when destroy the MR list
+    - gfs2: jdata writepage fix
+    - perf llvm: Fix inadvertent file creation
+    - perf tools: Fix auto-complete on aarch64
+    - sparc: allow PM configs for sparc32 COMPILE_TEST
+    - mfd: pcf50633-adc: Fix potential memleak in pcf50633_adc_async_read()
+    - clk: qcom: gcc-qcs404: disable gpll[04]_out_aux parents
+    - clk: qcom: gcc-qcs404: fix names of the DSI clocks used as parents
+    - mtd: rawnand: sunxi: Fix the size of the last OOB region
+    - clk: renesas: cpg-mssr: Fix use after free if cpg_mssr_common_init() failed
+    - clk: renesas: cpg-mssr: Use enum clk_reg_layout instead of a boolean flag
+    - clk: renesas: cpg-mssr: Remove superfluous check in resume code
+    - Input: ads7846 - don't report pressure for ads7845
+    - Input: ads7846 - don't check penirq immediately for 7845
+    - clk: qcom: gpucc-sdm845: fix clk_dis_wait being programmed for CX GDSC
+    - powerpc/powernv/ioda: Skip unallocated resources when mapping to PE
+    - clk: Honor CLK_OPS_PARENT_ENABLE in clk_core_is_enabled()
+    - powerpc/pseries/lpar: add missing RTAS retry status handling
+    - powerpc/pseries/lparcfg: add missing RTAS retry status handling
+    - powerpc/rtas: make all exports GPL
+    - powerpc/rtas: ensure 4KB alignment for rtas_data_buf
+    - powerpc/eeh: Small refactor of eeh_handle_normal_event()
+    - powerpc/eeh: Set channel state after notifying the drivers
+    - MIPS: SMP-CPS: fix build error when HOTPLUG_CPU not set
+    - MIPS: vpe-mt: drop physical_memsize
+    - remoteproc: qcom_q6v5_mss: Use a carveout to authenticate modem headers
+    - media: platform: ti: Add missing check for devm_regulator_get
+    - powerpc: Remove linker flag from KBUILD_AFLAGS
+    - media: ov5675: Fix memleak in ov5675_init_controls()
+    - media: i2c: ov772x: Fix memleak in ov772x_probe()
+    - media: i2c: ov7670: 0 instead of -EINVAL was returned
+    - media: usb: siano: Fix use after free bugs caused by do_submit_urb
+    - rpmsg: glink: Avoid infinite loop on intent for missing channel
+    - udf: Define EFSCORRUPTED error code
+    - ARM: dts: exynos: Use Exynos5420 compatible for the MIPI video phy
+    - blk-iocost: fix divide by 0 error in calc_lcoefs()
+    - wifi: brcmfmac: Fix potential stack-out-of-bounds in brcmf_c_preinit_dcmds()
+    - rcu: Suppress smp_processor_id() complaint in
+      synchronize_rcu_expedited_wait()
+    - thermal: intel: Fix unsigned comparison with less than zero
+    - timers: Prevent union confusion from unexpected restart_syscall()
+    - x86/bugs: Reset speculation control settings on init
+    - wifi: brcmfmac: ensure CLM version is null-terminated to prevent stack-out-
+      of-bounds
+    - wifi: mt7601u: fix an integer underflow
+    - inet: fix fast path in __inet_hash_connect()
+    - ice: add missing checks for PF vsi type
+    - ACPI: Don't build ACPICA with '-Os'
+    - net: bcmgenet: Add a check for oversized packets
+    - m68k: Check syscall_trace_enter() return code
+    - wifi: mt76: dma: free rx_head in mt76_dma_rx_cleanup
+    - ACPI: video: Fix Lenovo Ideapad Z570 DMI match
+    - net/mlx5: fw_tracer: Fix debug print
+    - coda: Avoid partial allocation of sig_inputArgs
+    - uaccess: Add minimum bounds check on kernel buffer size
+    - drm/amd/display: Fix potential null-deref in dm_resume
+    - drm/omap: dsi: Fix excessive stack usage
+    - HID: Add Mapping for System Microphone Mute
+    - drm/radeon: free iio for atombios when driver shutdown
+    - drm/msm/dsi: Add missing check for alloc_ordered_workqueue
+    - docs/scripts/gdb: add necessary make scripts_gdb step
+    - ASoC: kirkwood: Iterate over array indexes instead of using pointer math
+    - regulator: max77802: Bounds check regulator id against opmode
+    - regulator: s5m8767: Bounds check id indexing into arrays
+    - hwmon: (coretemp) Simplify platform device handling
+    - pinctrl: at91: use devm_kasprintf() to avoid potential leaks
+    - drm: panel-orientation-quirks: Add quirk for Lenovo IdeaPad Duet 3 10IGL5
+    - dm thin: add cond_resched() to various workqueue loops
+    - dm cache: add cond_resched() to various workqueue loops
+    - nfsd: zero out pointers after putting nfsd_files on COPY setup error
+    - wifi: rtl8xxxu: fixing transmisison failure for rtl8192eu
+    - firmware: coreboot: framebuffer: Ignore reserved pixel color bits
+    - rtc: pm8xxx: fix set-alarm race
+    - ipmi_ssif: Rename idle state and check
+    - s390: discard .interp section
+    - s390/kprobes: fix irq mask clobbering on kprobe reenter from post_handler
+    - s390/kprobes: fix current_kprobe never cleared after kprobes reenter
+    - ARM: dts: exynos: correct HDMI phy compatible in Exynos4
+    - hfs: fix missing hfs_bnode_get() in __hfs_bnode_create
+    - fs: hfsplus: fix UAF issue in hfsplus_put_super
+    - f2fs: fix information leak in f2fs_move_inline_dirents()
+    - f2fs: fix cgroup writeback accounting with fs-layer encryption
+    - ocfs2: fix defrag path triggering jbd2 ASSERT
+    - ocfs2: fix non-auto defrag path not working issue
+    - udf: Truncate added extents on failed expansion
+    - udf: Do not bother merging very long extents
+    - udf: Do not update file length for failed writes to inline files
+    - udf: Preserve link count of system files
+    - udf: Detect system inodes linked into directory hierarchy
+    - udf: Fix file corruption when appending just after end of preallocated
+      extent
+    - KVM: Destroy target device if coalesced MMIO unregistration fails
+    - KVM: s390: disable migration mode when dirty tracking is disabled
+    - x86/virt: Force GIF=1 prior to disabling SVM (for reboot flows)
+    - x86/crash: Disable virt in core NMI crash handler to avoid double shootdown
+    - x86/reboot: Disable virtualization in an emergency if SVM is supported
+    - x86/reboot: Disable SVM, not just VMX, when stopping CPUs
+    - x86/kprobes: Fix __recover_optprobed_insn check optimizing logic
+    - x86/kprobes: Fix arch_check_optimized_kprobe check within optimized_kprobe
+      range
+    - x86/microcode/amd: Remove load_microcode_amd()'s bsp parameter
+    - x86/microcode/AMD: Add a @cpu parameter to the reloading functions
+    - x86/microcode/AMD: Fix mixed steppings support
+    - x86/speculation: Allow enabling STIBP with legacy IBRS
+    - Documentation/hw-vuln: Document the interaction between IBRS and STIBP
+    - ima: Align ima_file_mmap() parameters with mmap_file LSM hook
+    - irqdomain: Fix association race
+    - irqdomain: Fix disassociation race
+    - irqdomain: Drop bogus fwspec-mapping error handling
+    - ALSA: ice1712: Do not left ice->gpio_mutex locked in aureon_add_controls()
+    - ALSA: hda/realtek: Add quirk for HP EliteDesk 800 G6 Tower PC
+    - ext4: optimize ea_inode block expansion
+    - ext4: refuse to create ea block when umounted
+    - wifi: rtl8xxxu: Use a longer retry limit of 48
+    - wifi: cfg80211: Fix use after free for wext
+    - thermal: intel: powerclamp: Fix cur_state for multi package system
+    - dm flakey: fix logic when corrupting a bio
+    - dm flakey: don't corrupt the zero page
+    - ARM: dts: exynos: correct TMU phandle in Exynos4
+    - ARM: dts: exynos: correct TMU phandle in Odroid XU
+    - rbd: avoid use-after-free in do_rbd_add() when rbd_dev_create() fails
+    - alpha: fix FEN fault handling
+    - mips: fix syscall_get_nr
+    - media: ipu3-cio2: Fix PM runtime usage_count in driver unbind
+    - mm: memcontrol: deprecate charge moving
+    - mm/thp: check and bail out if page in deferred queue already
+    - ktest.pl: Give back console on Ctrt^C on monitor
+    - ktest.pl: Fix missing "end_monitor" when machine check fails
+    - ktest.pl: Add RUN_TIMEOUT option with default unlimited
+    - scsi: qla2xxx: Fix link failure in NPIV environment
+    - scsi: qla2xxx: Fix DMA-API call trace on NVMe LS requests
+    - scsi: qla2xxx: Fix erroneous link down
+    - scsi: ses: Don't attach if enclosure has no components
+    - scsi: ses: Fix slab-out-of-bounds in ses_enclosure_data_process()
+    - scsi: ses: Fix possible addl_desc_ptr out-of-bounds accesses
+    - scsi: ses: Fix possible desc_ptr out-of-bounds accesses
+    - scsi: ses: Fix slab-out-of-bounds in ses_intf_remove()
+    - PCI/PM: Observe reset delay irrespective of bridge_d3
+    - PCI: hotplug: Allow marking devices as disconnected during bind/unbind
+    - PCI: Avoid FLR for AMD FCH AHCI adapters
+    - drm/i915/quirks: Add inverted backlight quirk for HP 14-r206nv
+    - drm/radeon: Fix eDP for single-display iMac11,2
+    - wifi: ath9k: use proper statements in conditionals
+    - kbuild: Port silent mode detection to future gnu make.
+    - fs/jfs: fix shift exponent db_agl2size negative
+    - pwm: sifive: Reduce time the controller lock is held
+    - pwm: sifive: Always let the first pwm_apply_state succeed
+    - pwm: stm32-lp: fix the check on arr and cmp registers update
+    - f2fs: use memcpy_{to,from}_page() where possible
+    - fs: f2fs: initialize fsdata in pagecache_write()
+    - um: vector: Fix memory leak in vector_config
+    - ubi: ensure that VID header offset + VID header size <= alloc, size
+    - ubifs: Fix build errors as symbol undefined
+    - ubifs: Rectify space budget for ubifs_symlink() if symlink is encrypted
+    - ubifs: Rectify space budget for ubifs_xrename()
+    - ubifs: Fix wrong dirty space budget for dirty inode
+    - ubifs: do_rename: Fix wrong space budget when target inode's nlink > 1
+    - ubifs: Reserve one leb for each journal head while doing budget
+    - ubi: Fix use-after-free when volume resizing failed
+    - ubi: Fix unreferenced object reported by kmemleak in ubi_resize_volume()
+    - ubifs: Fix memory leak in alloc_wbufs()
+    - ubi: Fix possible null-ptr-deref in ubi_free_volume()
+    - ubifs: Re-statistic cleaned znode count if commit failed
+    - ubifs: dirty_cow_znode: Fix memleak in error handling path
+    - ubifs: ubifs_writepage: Mark page dirty after writing inode failed
+    - ubi: Fix UAF wear-leveling entry in eraseblk_count_seq_show()
+    - ubi: ubi_wl_put_peb: Fix infinite loop when wear-leveling work failed
+    - x86: um: vdso: Add '%rcx' and '%r11' to the syscall clobber list
+    - watchdog: at91sam9_wdt: use devm_request_irq to avoid missing free_irq() in
+      error path
+    - watchdog: Fix kmemleak in watchdog_cdev_register
+    - watchdog: pcwd_usb: Fix attempting to access uninitialized memory
+    - netfilter: ctnetlink: fix possible refcount leak in
+      ctnetlink_create_conntrack()
+    - ipv6: Add lwtunnel encap size of all siblings in nexthop calculation
+    - sctp: add a refcnt in sctp_stream_priorities to avoid a nested loop
+    - net: fix __dev_kfree_skb_any() vs drop monitor
+    - 9p/xen: fix version parsing
+    - 9p/xen: fix connection sequence
+    - 9p/rdma: unmap receive dma buffer in rdma_request()/post_recv()
+    - net/mlx5: Geneve, Fix handling of Geneve object id as error code
+    - nfc: fix memory leak of se_io context in nfc_genl_se_io
+    - net/sched: act_sample: fix action bind logic
+    - ARM: dts: spear320-hmi: correct STMPE GPIO compatible
+    - tcp: tcp_check_req() can be called from process context
+    - vc_screen: modify vcs_size() handling in vcs_read()
+    - rtc: sun6i: Make external 32k oscillator optional
+    - rtc: sun6i: Always export the internal oscillator
+    - scsi: ipr: Work around fortify-string warning
+    - thermal: intel: quark_dts: fix error pointer dereference
+    - thermal: intel: BXT_PMIC: select REGMAP instead of depending on it
+    - tracing: Add NULL checks for buffer in ring_buffer_free_read_page()
+    - firmware/efi sysfb_efi: Add quirk for Lenovo IdeaPad Duet 3
+    - mfd: arizona: Use pm_runtime_resume_and_get() to prevent refcnt leak
+    - media: uvcvideo: Handle cameras with invalid descriptors
+    - media: uvcvideo: Handle errors from calls to usb_string
+    - media: uvcvideo: Quirk for autosuspend in Logitech B910 and C910
+    - media: uvcvideo: Silence memcpy() run-time false positive warnings
+    - staging: emxx_udc: Add checks for dma_alloc_coherent()
+    - tty: fix out-of-bounds access in tty_driver_lookup_tty()
+    - tty: serial: fsl_lpuart: disable the CTS when send break signal
+    - mei: bus-fixup:upon error print return values of send and receive
+    - tools/iio/iio_utils:fix memory leak
+    - iio: accel: mma9551_core: Prevent uninitialized variable in
+      mma9551_read_status_word()
+    - iio: accel: mma9551_core: Prevent uninitialized variable in
+      mma9551_read_config_word()
+    - usb: host: xhci: mvebu: Iterate over array indexes instead of using pointer
+      math
+    - USB: ene_usb6250: Allocate enough memory for full object
+    - usb: uvc: Enumerate valid values for color matching
+    - kernel/fail_function: fix memory leak with using debugfs_lookup()
+    - PCI: Add ACS quirk for Wangxun NICs
+    - phy: rockchip-typec: Fix unsigned comparison with less than zero
+    - net: tls: avoid hanging tasks on the tx_lock
+    - x86/resctrl: Apply READ_ONCE/WRITE_ONCE to task_struct.{rmid,closid}
+    - x86/resctl: fix scheduler confusion with 'current'
+    - Bluetooth: hci_sock: purge socket queues in the destruct() callback
+    - SAUCE: Revert "UBUNTU: SAUCE: Fix inet_csk_listen_start after CVE-2023-0461"
+    - tcp: Fix listen() regression in 5.4.229.
+    - media: uvcvideo: Provide sync and async uvc_ctrl_status_event
+    - media: uvcvideo: Fix race condition with usb_kill_urb
+    - dt-bindings: rtc: sun6i-a31-rtc: Loosen the requirements on the clocks
+    - Linux 5.4.235
+    - [Config] Drop mxsfb for armhf:generic-lpae
+  * Focal update: v5.4.234 upstream stable release (LP: #2017691)
+    - arm64: dts: rockchip: drop unused LED mode property from rk3328-roc-cc
+    - ARM: dts: rockchip: add power-domains property to dp node on rk3288
+    - ACPI: NFIT: fix a potential deadlock during NFIT teardown
+    - btrfs: send: limit number of clones and allocated memory size
+    - IB/hfi1: Assign npages earlier
+    - neigh: make sure used and confirmed times are valid
+    - HID: core: Fix deadloop in hid_apply_multiplier.
+    - bpf: bpf_fib_lookup should not return neigh in NUD_FAILED state
+    - net: Remove WARN_ON_ONCE(sk->sk_forward_alloc) from sk_stream_kill_queues().
+    - vc_screen: don't clobber return value in vcs_read
+    - dmaengine: sh: rcar-dmac: Check for error num after dma_set_max_seg_size
+    - USB: serial: option: add support for VW/Skoda "Carstick LTE"
+    - USB: core: Don't hold device lock while reading the "descriptors" sysfs file
+    - Linux 5.4.234
+  * CVE-2023-30456
+    - KVM: nVMX: add missing consistency checks for CR0 and CR4
+  * CVE-2023-1859
+    - 9p/xen : Fix use after free bug in xen_9pfs_front_remove due to race
+      condition
+  * CVE-2023-1670
+    - xirc2ps_cs: Fix use after free bug in xirc2ps_detach
+
+  [ Ubuntu: 5.4.0-149.166 ]
+
+  * focal/linux: 5.4.0-149.166 -proposed tracker (LP: #2016591)
+  * Focal update: v5.4.233 upstream stable release (LP: #2015909)
+    - dma-mapping: add generic helpers for mapping sgtable objects
+    - scatterlist: add generic wrappers for iterating over sgtable objects
+    - drm: etnaviv: fix common struct sg_table related issues
+    - drm/etnaviv: don't truncate physical page address
+    - wifi: rtl8xxxu: gen2: Turn on the rate control
+    - powerpc: dts: t208x: Mark MAC1 and MAC2 as 10G
+    - random: always mix cycle counter in add_latent_entropy()
+    - KVM: x86: Fail emulation during EMULTYPE_SKIP on any exception
+    - can: kvaser_usb: hydra: help gcc-13 to figure out cmd_len
+    - powerpc: dts: t208x: Disable 10G on MAC1 and MAC2
+    - alarmtimer: Prevent starvation by small intervals and SIG_IGN
+    - drm/i915/gvt: fix double free bug in split_2MB_gtt_entry
+    - mac80211: mesh: embedd mesh_paths and mpp_paths into ieee80211_if_mesh
+    - uaccess: Add speculation barrier to copy_from_user()
+    - wifi: mwifiex: Add missing compatible string for SD8787
+    - ext4: Fix function prototype mismatch for ext4_feat_ktype
+    - Revert "net/sched: taprio: make qdisc_leaf() see the per-netdev-queue pfifo
+      child qdiscs"
+    - bpf: add missing header file include
+    - Linux 5.4.233
+  *  selftest: fib_tests: Always cleanup before exit  (LP: #2015956)
+    - selftest: fib_tests: Always cleanup before exit
+  * fib_tests.sh in ubuntu_kernel_selftests was skipped silently on Focal
+    (LP: #2015440)
+    - selftests: Fix the executable permissions for fib_tests.sh
+  * Debian autoreconstruct Fix restoration of execute permissions (LP: #2015498)
+    - [Debian] autoreconstruct - fix restoration of execute permissions
+  * kernel: fix __clear_user() inline assembly constraints (LP: #2013088)
+    - s390/uaccess: add missing earlyclobber annotations to __clear_user()
+  * i/o error if next unused loop device is queried (LP: #1856871)
+    - loop: fix I/O error on fsync() in detached loop devices
+  * CVE-2023-1075
+    - net/tls: tls_is_tx_ready() checked list_entry
+  * Focal update: v5.4.232 upstream stable release (LP: #2011625)
+    - firewire: fix memory leak for payload of request subaction to IEC 61883-1
+      FCP region
+    - bus: sunxi-rsb: Fix error handling in sunxi_rsb_init()
+    - ASoC: Intel: bytcr_rt5651: Drop reference count of ACPI device after use
+    - ALSA: hda/via: Avoid potential array out-of-bound in add_secret_dac_path()
+    - arm64: dts: imx8mm: Fix pad control for UART1_DTE_RX
+    - scsi: Revert "scsi: core: map PQ=1, PDT=other values to
+      SCSI_SCAN_TARGET_PRESENT"
+    - WRITE is "data source", not destination...
+    - fix iov_iter_bvec() "direction" argument
+    - fix "direction" argument of iov_iter_kvec()
+    - netrom: Fix use-after-free caused by accept on already connected socket
+    - netfilter: br_netfilter: disable sabotage_in hook after first suppression
+    - squashfs: harden sanity check in squashfs_read_xattr_id_table
+    - net: phy: meson-gxl: Add generic dummy stubs for MMD register access
+    - can: j1939: fix errant WARN_ON_ONCE in j1939_session_deactivate
+    - ata: libata: Fix sata_down_spd_limit() when no link speed is reported
+    - selftests: net: udpgso_bench_rx: Fix 'used uninitialized' compiler warning
+    - selftests: net: udpgso_bench_rx/tx: Stop when wrong CLI args are provided
+    - selftests: net: udpgso_bench_tx: Cater for pending datagrams zerocopy
+      benchmarking
+    - virtio-net: Keep stop() to follow mirror sequence of open()
+    - net: openvswitch: fix flow memory leak in ovs_flow_cmd_new
+    - efi: fix potential NULL deref in efi_mem_reserve_persistent
+    - scsi: target: core: Fix warning on RT kernels
+    - scsi: iscsi_tcp: Fix UAF during login when accessing the shost ipaddress
+    - i2c: rk3x: fix a bunch of kernel-doc warnings
+    - net/x25: Fix to not accept on connected socket
+    - iio: adc: stm32-dfsdm: fill module aliases
+    - usb: dwc3: dwc3-qcom: Fix typo in the dwc3 vbus override API
+    - usb: dwc3: qcom: enable vbus override when in OTG dr-mode
+    - usb: gadget: f_fs: Fix unbalanced spinlock in __ffs_ep0_queue_wait
+    - vc_screen: move load of struct vc_data pointer in vcs_read() to avoid UAF
+    - Input: i8042 - move __initconst to fix code styling warning
+    - Input: i8042 - merge quirk tables
+    - Input: i8042 - add TUXEDO devices to i8042 quirk tables
+    - Input: i8042 - add Clevo PCX0DX to i8042 quirk table
+    - fbcon: Check font dimension limits
+    - watchdog: diag288_wdt: do not use stack buffers for hardware data
+    - watchdog: diag288_wdt: fix __diag288() inline assembly
+    - efi: Accept version 2 of memory attributes table
+    - iio: hid: fix the retval in accel_3d_capture_sample
+    - iio: adc: berlin2-adc: Add missing of_node_put() in error path
+    - iio:adc:twl6030: Enable measurements of VUSB, VBAT and others
+    - parisc: Fix return code of pdc_iodc_print()
+    - parisc: Wire up PTRACE_GETREGS/PTRACE_SETREGS for compat case
+    - riscv: disable generation of unwind tables
+    - mm: hugetlb: proc: check for hugetlb shared PMD in /proc/PID/smaps
+    - fpga: stratix10-soc: Fix return value check in s10_ops_write_init()
+    - mm/swapfile: add cond_resched() in get_swap_pages()
+    - Squashfs: fix handling and sanity checking of xattr_ids count
+    - nvmem: core: fix cell removal on error
+    - mm: swap: properly update readahead statistics in unuse_pte_range()
+    - xprtrdma: Fix regbuf data not freed in rpcrdma_req_create()
+    - serial: 8250_dma: Fix DMA Rx completion race
+    - serial: 8250_dma: Fix DMA Rx rearm race
+    - powerpc/imc-pmu: Revert nest_init_lock to being a mutex
+    - fbdev: smscufx: fix error handling code in ufx_usb_probe
+    - f2fs: fix to do sanity check on i_extra_isize in is_alive()
+    - wifi: brcmfmac: Check the count value of channel spec to prevent out-of-
+      bounds reads
+    - iio:adc:twl6030: Enable measurement of VAC
+    - btrfs: limit device extents to the device size
+    - btrfs: zlib: zero-initialize zlib workspace
+    - ALSA: emux: Avoid potential array out-of-bound in snd_emux_xg_control()
+    - tracing: Fix poll() and select() do not work on per_cpu trace_pipe and
+      trace_pipe_raw
+    - can: j1939: do not wait 250 ms if the same addr was already claimed
+    - IB/hfi1: Restore allocated resources on failed copyout
+    - IB/IPoIB: Fix legacy IPoIB due to wrong number of queues
+    - iommu: Add gfp parameter to iommu_ops::map
+    - RDMA/usnic: use iommu_map_atomic() under spin_lock()
+    - xfrm: fix bug with DSCP copy to v6 from v4 tunnel
+    - bonding: fix error checking in bond_debug_reregister()
+    - net: phy: meson-gxl: use MMD access dummy stubs for GXL, internal PHY
+    - ionic: clean interrupt before enabling queue to avoid credit race
+    - ice: Do not use WQ_MEM_RECLAIM flag for workqueue
+    - rds: rds_rm_zerocopy_callback() use list_first_entry()
+    - selftests: forwarding: lib: quote the sysctl values
+    - ALSA: pci: lx6464es: fix a debug loop
+    - pinctrl: aspeed: Fix confusing types in return value
+    - pinctrl: single: fix potential NULL dereference
+    - pinctrl: intel: Restore the pins that used to be in Direct IRQ mode
+    - net: USB: Fix wrong-direction WARNING in plusb.c
+    - usb: core: add quirk for Alcor Link AK9563 smartcard reader
+    - usb: typec: altmodes/displayport: Fix probe pin assign check
+    - ceph: flush cap releases when the session is flushed
+    - riscv: Fixup race condition on PG_dcache_clean in flush_icache_pte
+    - arm64: dts: meson-gx: Make mmc host controller interrupts level-sensitive
+    - arm64: dts: meson-g12-common: Make mmc host controller interrupts level-
+      sensitive
+    - arm64: dts: meson-axg: Make mmc host controller interrupts level-sensitive
+    - nvme-pci: Move enumeration by class to be last in the table
+    - bpf: Always return target ifindex in bpf_fib_lookup
+    - migrate: hugetlb: check for hugetlb shared PMD in node migration
+    - selftests/bpf: Verify copy_register_state() preserves parent/live fields
+    - ASoC: cs42l56: fix DT probe
+    - tools/virtio: fix the vringh test for virtio ring changes
+    - net/rose: Fix to not accept on connected socket
+    - net: stmmac: do not stop RX_CLK in Rx LPI state for qcs404 SoC
+    - net: sched: sch: Bounds check priority
+    - s390/decompressor: specify __decompress() buf len to avoid overflow
+    - nvme-fc: fix a missing queue put in nvmet_fc_ls_create_association
+    - aio: fix mremap after fork null-deref
+    - btrfs: free device in btrfs_close_devices for a single device filesystem
+    - netfilter: nft_tproxy: restrict to prerouting hook
+    - xfs: remove the xfs_efi_log_item_t typedef
+    - xfs: remove the xfs_efd_log_item_t typedef
+    - xfs: remove the xfs_inode_log_item_t typedef
+    - xfs: factor out a xfs_defer_create_intent helper
+    - xfs: merge the ->log_item defer op into ->create_intent
+    - xfs: merge the ->diff_items defer op into ->create_intent
+    - xfs: turn dfp_intent into a xfs_log_item
+    - xfs: refactor xfs_defer_finish_noroll
+    - xfs: log new intent items created as part of finishing recovered intent
+      items
+    - xfs: fix finobt btree block recovery ordering
+    - xfs: proper replay of deferred ops queued during log recovery
+    - xfs: xfs_defer_capture should absorb remaining block reservations
+    - xfs: xfs_defer_capture should absorb remaining transaction reservation
+    - xfs: clean up bmap intent item recovery checking
+    - xfs: clean up xfs_bui_item_recover iget/trans_alloc/ilock ordering
+    - xfs: fix an incore inode UAF in xfs_bui_recover
+    - xfs: change the order in which child and parent defer ops are finished
+    - xfs: periodically relog deferred intent items
+    - xfs: expose the log push threshold
+    - xfs: only relog deferred intent items if free space in the log gets low
+    - xfs: fix missing CoW blocks writeback conversion retry
+    - xfs: ensure inobt record walks always make forward progress
+    - xfs: fix the forward progress assertion in xfs_iwalk_run_callbacks
+    - xfs: prevent UAF in xfs_log_item_in_current_chkpt
+    - xfs: sync lazy sb accounting on quiesce of read-only mounts
+    - Revert "ipv4: Fix incorrect route flushing when source address is deleted"
+    - ipv4: Fix incorrect route flushing when source address is deleted
+    - mmc: sdio: fix possible resource leaks in some error paths
+    - mmc: mmc_spi: fix error handling in mmc_spi_probe()
+    - ALSA: hda/conexant: add a new hda codec SN6180
+    - ALSA: hda/realtek - fixed wrong gpio assigned
+    - sched/psi: Fix use-after-free in ep_remove_wait_queue()
+    - hugetlb: check for undefined shift on 32 bit architectures
+    - Revert "mm: Always release pages to the buddy allocator in
+      memblock_free_late()."
+    - net: Fix unwanted sign extension in netdev_stats_to_stats64()
+    - revert "squashfs: harden sanity check in squashfs_read_xattr_id_table"
+    - ixgbe: allow to increase MTU to 3K with XDP enabled
+    - i40e: add double of VLAN header when computing the max MTU
+    - net: bgmac: fix BCM5358 support by setting correct flags
+    - sctp: sctp_sock_filter(): avoid list_entry() on possibly empty list
+    - dccp/tcp: Avoid negative sk_forward_alloc by ipv6_pinfo.pktoptions.
+    - net/usb: kalmia: Don't pass act_len in usb_bulk_msg error path
+    - net: stmmac: fix order of dwmac5 FlexPPS parametrization sequence
+    - bnxt_en: Fix mqprio and XDP ring checking logic
+    - net: stmmac: Restrict warning on disabling DMA store and fwd mode
+    - ixgbe: add double of VLAN header when computing the max MTU
+    - ipv6: Fix datagram socket connection with DSCP.
+    - ipv6: Fix tcp socket connection with DSCP.
+    - i40e: Add checking for null for nlmsg_find_attr()
+    - kvm: initialize all of the kvm_debugregs structure before sending it to
+      userspace
+    - nilfs2: fix underflow in second superblock position calculations
+    - ASoC: SOF: Intel: hda-dai: fix possible stream_tag leak
+    - net: sched: sch: Fix off by one in htb_activate_prios()
+    - iommu/amd: Pass gfp flags to iommu_map_page() in amd_iommu_map()
+    - Linux 5.4.232
+  * CVE-2023-1118
+    - media: rc: Fix use-after-free bugs caused by ene_tx_irqsim()
+
+  [ Ubuntu: 5.4.0-148.165 ]
+
+  * focal/linux: 5.4.0-148.165 -proposed tracker (LP: #2016777)
+  * CVE-2023-1829
+    - net/sched: Retire tcindex classifier
+    - [Config]: Make sure CONFIG_NET_CLS_TCINDEX is not available
+
+  [ Ubuntu: 5.4.0-147.164 ]
+
+  * focal/linux: 5.4.0-147.164 -proposed tracker (LP: #2011959)
+  * CVE-2023-26545
+    - net: mpls: fix stale pointer if allocation fails during device rename
+  * CVE-2023-1281
+    - rcu: Upgrade rcu_swap_protected() to rcu_replace_pointer()
+    - net/sched: tcindex: update imperfect hash filters respecting rcu
+  * Focal update: v5.4.231 upstream stable release (LP: #2011226)
+    - clk: generalize devm_clk_get() a bit
+    - clk: Provide new devm_clk helpers for prepared and enabled clocks
+    - memory: atmel-sdramc: Fix missing clk_disable_unprepare in
+      atmel_ramc_probe()
+    - memory: mvebu-devbus: Fix missing clk_disable_unprepare in
+      mvebu_devbus_probe()
+    - ARM: dts: imx6qdl-gw560x: Remove incorrect 'uart-has-rtscts'
+    - ARM: imx27: Retrieve the SYSCTRL base address from devicetree
+    - ARM: imx31: Retrieve the IIM base address from devicetree
+    - ARM: imx35: Retrieve the IIM base address from devicetree
+    - ARM: imx: add missing of_node_put()
+    - HID: intel_ish-hid: Add check for ishtp_dma_tx_map
+    - EDAC/highbank: Fix memory leak in highbank_mc_probe()
+    - tomoyo: fix broken dependency on *.conf.default
+    - RDMA/core: Fix ib block iterator counter overflow
+    - IB/hfi1: Reject a zero-length user expected buffer
+    - IB/hfi1: Reserve user expected TIDs
+    - IB/hfi1: Fix expected receive setup error exit issues
+    - affs: initialize fsdata in affs_truncate()
+    - amd-xgbe: TX Flow Ctrl Registers are h/w ver dependent
+    - amd-xgbe: Delay AN timeout during KR training
+    - bpf: Fix pointer-leak due to insufficient speculative store bypass
+      mitigation
+    - phy: rockchip-inno-usb2: Fix missing clk_disable_unprepare() in
+      rockchip_usb2phy_power_on()
+    - net: nfc: Fix use-after-free in local_cleanup()
+    - net: wan: Add checks for NULL for utdm in undo_uhdlc_init and unmap_si_regs
+    - gpio: mxc: Always set GPIOs used as interrupt source to INPUT mode
+    - net/sched: sch_taprio: fix possible use-after-free
+    - net: fix a concurrency bug in l2tp_tunnel_register()
+    - l2tp: Serialize access to sk_user_data with sk_callback_lock
+    - l2tp: Don't sleep and disable BH under writer-side sk_callback_lock
+    - net: usb: sr9700: Handle negative len
+    - net: mdio: validate parameter addr in mdiobus_get_phy()
+    - HID: check empty report_list in hid_validate_values()
+    - HID: check empty report_list in bigben_probe()
+    - net: stmmac: fix invalid call to mdiobus_get_phy()
+    - HID: revert CHERRY_MOUSE_000C quirk
+    - usb: gadget: f_fs: Prevent race during ffs_ep0_queue_wait
+    - usb: gadget: f_fs: Ensure ep0req is dequeued before free_request
+    - net: mlx5: eliminate anonymous module_init & module_exit
+    - drm/panfrost: fix GENERIC_ATOMIC64 dependency
+    - dmaengine: Fix double increment of client_count in dma_chan_get()
+    - net: macb: fix PTP TX timestamp failure due to packet padding
+    - HID: betop: check shape of output reports
+    - dmaengine: xilinx_dma: use devm_platform_ioremap_resource()
+    - dmaengine: xilinx_dma: Fix devm_platform_ioremap_resource error handling
+    - dmaengine: xilinx_dma: call of_node_put() when breaking out of
+      for_each_child_of_node()
+    - tcp: avoid the lookup process failing to get sk in ehash table
+    - w1: fix deadloop in __w1_remove_master_device()
+    - w1: fix WARNING after calling w1_process()
+    - driver core: Fix test_async_probe_init saves device in wrong array
+    - net: dsa: microchip: ksz9477: port map correction in ALU table entry
+      register
+    - tcp: fix rate_app_limited to default to 1
+    - cpufreq: Add Tegra234 to cpufreq-dt-platdev blocklist
+    - ASoC: fsl_micfil: Correct the number of steps on SX controls
+    - drm: Add orientation quirk for Lenovo ideapad D330-10IGL
+    - s390/debug: add _ASM_S390_ prefix to header guard
+    - cpufreq: armada-37xx: stop using 0 as NULL pointer
+    - ASoC: fsl_ssi: Rename AC'97 streams to avoid collisions with AC'97 CODEC
+    - ASoC: fsl-asoc-card: Fix naming of AC'97 CODEC widgets
+    - spi: spidev: remove debug messages that access spidev->spi without locking
+    - KVM: s390: interrupt: use READ_ONCE() before cmpxchg()
+    - scsi: hisi_sas: Set a port invalid only if there are no devices attached
+      when refreshing port id
+    - platform/x86: touchscreen_dmi: Add info for the CSL Panther Tab HD
+    - platform/x86: asus-nb-wmi: Add alternate mapping for KEY_SCREENLOCK
+    - lockref: stop doing cpu_relax in the cmpxchg loop
+    - mmc: sdhci-esdhc-imx: clear pending interrupt and halt cqhci
+    - mmc: sdhci-esdhc-imx: disable the CMD CRC check for standard tuning
+    - mmc: sdhci-esdhc-imx: correct the tuning start tap and step setting
+    - netfilter: conntrack: do not renew entry stuck in tcp SYN_SENT state
+    - fs: reiserfs: remove useless new_opts in reiserfs_remount
+    - Bluetooth: hci_sync: cancel cmd_timer if hci_open failed
+    - scsi: hpsa: Fix allocation size for scsi_host_alloc()
+    - module: Don't wait for GOING modules
+    - tracing: Make sure trace_printk() can output as soon as it can be used
+    - trace_events_hist: add check for return value of 'create_hist_field'
+    - ftrace/scripts: Update the instructions for ftrace-bisect.sh
+    - cifs: Fix oops due to uncleared server->smbd_conn in reconnect
+    - KVM: x86/vmx: Do not skip segment attributes if unusable bit is set
+    - thermal: intel: int340x: Protect trip temperature from concurrent updates
+    - ARM: 9280/1: mm: fix warning on phys_addr_t to void pointer assignment
+    - EDAC/device: Respect any driver-supplied workqueue polling value
+    - EDAC/qcom: Do not pass llcc_driv_data as edac_device_ctl_info's pvt_info
+    - netlink: prevent potential spectre v1 gadgets
+    - net: fix UaF in netns ops registration error path
+    - netfilter: nft_set_rbtree: skip elements in transaction from garbage
+      collection
+    - netlink: annotate data races around nlk->portid
+    - netlink: annotate data races around dst_portid and dst_group
+    - netlink: annotate data races around sk_state
+    - ipv4: prevent potential spectre v1 gadget in ip_metrics_convert()
+    - ipv4: prevent potential spectre v1 gadget in fib_metrics_match()
+    - netfilter: conntrack: fix vtag checks for ABORT/SHUTDOWN_COMPLETE
+    - netrom: Fix use-after-free of a listening socket.
+    - net/sched: sch_taprio: do not schedule in taprio_reset()
+    - sctp: fail if no bound addresses can be used for a given scope
+    - net: ravb: Fix possible hang if RIS2_QFF1 happen
+    - thermal: intel: int340x: Add locking to int340x_thermal_get_trip_type()
+    - net/tg3: resolve deadlock in tg3_reset_task() during EEH
+    - net/phy/mdio-i2c: Move header file to include/linux/mdio
+    - net: xgene: Move shared header file into include/linux
+    - net: mdio-mux-meson-g12a: force internal PHY off on mux switch
+    - Revert "Input: synaptics - switch touchpad on HP Laptop 15-da3001TU to RMI
+      mode"
+    - nfsd: Ensure knfsd shuts down when the "nfsd" pseudofs is unmounted
+    - block: fix and cleanup bio_check_ro
+    - x86/i8259: Mark legacy PIC interrupts with IRQ_LEVEL
+    - netfilter: conntrack: unify established states for SCTP paths
+    - perf/x86/amd: fix potential integer overflow on shift of a int
+    - clk: Fix pointer casting to prevent oops in devm_clk_release()
+    - x86/asm: Fix an assembler warning with current binutils
+    - ARM: dts: imx: Fix pca9547 i2c-mux node name
+    - bpf: Skip task with pid=1 in send_signal_common()
+    - blk-cgroup: fix missing pd_online_fn() while activating policy
+    - dmaengine: imx-sdma: Fix a possible memory leak in sdma_transfer_init
+    - sysctl: add a new register_sysctl_init() interface
+    - panic: unset panic_on_warn inside panic()
+    - mm: kasan: do not panic if both panic_on_warn and kasan_multishot set
+    - exit: Add and use make_task_dead.
+    - objtool: Add a missing comma to avoid string concatenation
+    - hexagon: Fix function name in die()
+    - h8300: Fix build errors from do_exit() to make_task_dead() transition
+    - csky: Fix function name in csky_alignment() and die()
+    - ia64: make IA64_MCA_RECOVERY bool instead of tristate
+    - exit: Put an upper limit on how often we can oops
+    - exit: Expose "oops_count" to sysfs
+    - exit: Allow oops_limit to be disabled
+    - panic: Consolidate open-coded panic_on_warn checks
+    - panic: Introduce warn_limit
+    - panic: Expose "warn_count" to sysfs
+    - docs: Fix path paste-o for /sys/kernel/warn_count
+    - exit: Use READ_ONCE() for all oops/warn limit reads
+    - ipv6: ensure sane device mtu in tunnels
+    - Bluetooth: fix null ptr deref on hci_sync_conn_complete_evt
+    - usb: host: xhci-plat: add wakeup entry at sysfs
+    - Revert "xprtrdma: Fix regbuf data not freed in rpcrdma_req_create()"
+    - Linux 5.4.231
+  * CVE-2022-3903
+    - USB: add usb_control_msg_send() and usb_control_msg_recv()
+    - USB: correct API of usb_control_msg_send/recv
+    - USB: move snd_usb_pipe_sanity_check into the USB core
+    - media: mceusb: Use new usb_control_msg_*() routines
+  * CVE-2022-3108
+    - drm/amdkfd: Check for null pointer after calling kmemdup
+  * Focal update: v5.4.230 upstream stable release (LP: #2008946)
+    - pNFS/filelayout: Fix coalescing test for single DS
+    - net/ethtool/ioctl: return -EOPNOTSUPP if we have no phy stats
+    - RDMA/srp: Move large values to a new enum for gcc13
+    - f2fs: let's avoid panic if extent_tree is not created
+    - wifi: brcmfmac: fix regression for Broadcom PCIe wifi devices
+    - Add exception protection processing for vd in axi_chan_handle_err function
+    - nilfs2: fix general protection fault in nilfs_btree_insert()
+    - efi: fix userspace infinite retry read efivars after EFI runtime services
+      page fault
+    - drm/i915/gt: Reset twice
+    - ALSA: hda/realtek - Turn on power early
+    - xhci-pci: set the dma max_seg_size
+    - usb: xhci: Check endpoint is valid before dereferencing it
+    - xhci: Fix null pointer dereference when host dies
+    - xhci: Add update_hub_device override for PCI xHCI hosts
+    - xhci: Add a flag to disable USB3 lpm on a xhci root port level.
+    - usb: acpi: add helper to check port lpm capability using acpi _DSM
+    - xhci: Detect lpm incapable xHC USB3 roothub ports from ACPI tables
+    - prlimit: do_prlimit needs to have a speculation check
+    - USB: serial: option: add Quectel EM05-G (GR) modem
+    - USB: serial: option: add Quectel EM05-G (CS) modem
+    - USB: serial: option: add Quectel EM05-G (RS) modem
+    - USB: serial: option: add Quectel EC200U modem
+    - USB: serial: option: add Quectel EM05CN (SG) modem
+    - USB: serial: option: add Quectel EM05CN modem
+    - USB: misc: iowarrior: fix up header size for USB_DEVICE_ID_CODEMERCS_IOW100
+    - misc: fastrpc: Don't remove map on creater_process and device_release
+    - misc: fastrpc: Fix use-after-free race condition for maps
+    - usb: core: hub: disable autosuspend for TI TUSB8041
+    - comedi: adv_pci1760: Fix PWM instruction handling
+    - mmc: sunxi-mmc: Fix clock refcount imbalance during unbind
+    - btrfs: fix race between quota rescan and disable leading to NULL pointer
+      deref
+    - cifs: do not include page data when checking signature
+    - USB: serial: cp210x: add SCALANCE LPE-9000 device id
+    - usb: host: ehci-fsl: Fix module alias
+    - usb: typec: altmodes/displayport: Add pin assignment helper
+    - usb: typec: altmodes/displayport: Fix pin assignment calculation
+    - usb: gadget: g_webcam: Send color matching descriptor per frame
+    - usb: gadget: f_ncm: fix potential NULL ptr deref in ncm_bitrate()
+    - usb-storage: apply IGNORE_UAS only for HIKSEMI MD202 on RTL9210
+    - dt-bindings: phy: g12a-usb3-pcie-phy: fix compatible string documentation
+    - serial: pch_uart: Pass correct sg to dma_unmap_sg()
+    - dmaengine: tegra210-adma: fix global intr clear
+    - serial: atmel: fix incorrect baudrate setup
+    - gsmi: fix null-deref in gsmi_get_variable
+    - drm/i915: re-disable RC6p on Sandy Bridge
+    - drm/amd/display: Fix set scaling doesn's work
+    - drm/amd/display: Fix COLOR_SPACE_YCBCR2020_TYPE matrix
+    - x86/fpu: Use _Alignof to avoid undefined behavior in TYPE_ALIGN
+    - mm/khugepaged: fix collapse_pte_mapped_thp() to allow anon_vma
+    - Linux 5.4.230
+
+  [ Ubuntu: 5.4.0-146.163 ]
+
+  * focal/linux: 5.4.0-146.163 -proposed tracker (LP: #2012094)
+  * NFS deathlock with last Kernel 5.4.0-144.161 and 5.15.0-67.74 (LP: #2009325)
+    - NFS: Correct timing for assigning access cache timestamp
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Mon, 19 Jun 2023 15:02:18 +1000
+
+linux-xilinx-zynqmp (5.4.0-1023.27) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1023.27 -proposed tracker (LP: #2008386)
+
+  [ Ubuntu: 5.4.0-145.162 ]
+
+  * focal/linux: 5.4.0-145.162 -proposed tracker (LP: #2008389)
+  * [SRU]Update ice driver to support E823 devices (LP: #1986717)
+    - ice: Add device ids for E822 devices
+    - ice: add support for E823 devices
+  * btrfs/154: rename fails with EOVERFLOW when calculating item size during
+    item key collision (LP: #2004132)
+    - btrfs: correctly calculate item size used when item key collision happens
+  * rtcpie in timers from ubuntu_kernel_selftests randomly failing
+    (LP: #1814234)
+    - SAUCE: selftest: rtcpie: Force passing unreliable subtest
+  * [UBUNTU 20.04] KVM: s390: pv: don't allow userspace to set the clock under
+    PV - kernel part (LP: #1999882)
+    - KVM: s390x: fix SCK locking
+    - KVM: s390: pv: don't allow userspace to set the clock under PV
+  * CVE-2021-3669
+    - ipc: replace costly bailout check in sysvipc_find_ipc()
+  * net:fcnal-test.sh 'nettest' command not found on F/K (LP: #2006391)
+    - selftests/net: Find nettest in current directory
+  * xfs: Preallocated ioend transactions cause deadlock due to log buffer
+    exhaustion (LP: #2007219)
+    - xfs: drop submit side trans alloc for append ioends
+  * CVE-2022-4382
+    - USB: gadgetfs: Fix race between mounting and unmounting
+  * CVE-2022-2196
+    - KVM: VMX: Execute IBPB on emulated VM-exit when guest has IBRS
+  * ubuntu_kernel_selftests: net:udpgso_bench.sh failed (LP: #1951447)
+    - selftests: net: udpgso_bench: Fix racing bug between the rx/tx programs
+  * net:fcnal-test.sh didn't return a non-zero value even with some sub-tests
+    failed (LP: #2006692)
+    - selftests: net/fcnal-test.sh: add exit code
+  * Fix selftests/ftracetests/Meta-selftests in Focal (LP: #2006453)
+    - SAUCE: Fix ftrace/Meta-selftests bashism check
+  * CVE-2023-23559
+    - wifi: rndis_wlan: Prevent buffer overflow in rndis_query_oid
+
+ -- Masahiro Yamada <masahiro.yamada@canonical.com>  Fri, 17 Mar 2023 14:40:43 +0900
+
+linux-xilinx-zynqmp (5.4.0-1022.26) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1022.26 -proposed tracker (LP: #2007326)
+
+  * Focal update: v5.4.226 upstream stable release (LP: #2003896)
+    - [Config] updateconfigs for INET_TABLE_PERTURB_ORDER
+
+  [ Ubuntu: 5.4.0-144.161 ]
+
+  * focal/linux: 5.4.0-144.161 -proposed tracker (LP: #2004653)
+  * CVE-2023-0461
+    - SAUCE: Fix inet_csk_listen_start after CVE-2023-0461
+
+  [ Ubuntu: 5.4.0-143.160 ]
+
+  * focal/linux: 5.4.0-143.160 -proposed tracker (LP: #2004385)
+  * NFS: client permission error after adding user to permissible group
+    (LP: #2003053)
+    - NFS: Clear the file access cache upon login
+    - NFS: Judge the file access cache's timestamp in rcu path
+    - NFS: Fix up a sparse warning
+  * Focal update: v5.4.229 upstream stable release (LP: #2003914)
+    - tracing/ring-buffer: Only do full wait when cpu != RING_BUFFER_ALL_CPUS
+    - udf: Discard preallocation before extending file with a hole
+    - udf: Fix preallocation discarding at indirect extent boundary
+    - udf: Do not bother looking for prealloc extents if i_lenExtents matches
+      i_size
+    - udf: Fix extending file within last block
+    - usb: gadget: uvc: Prevent buffer overflow in setup handler
+    - USB: serial: option: add Quectel EM05-G modem
+    - USB: serial: cp210x: add Kamstrup RF sniffer PIDs
+    - USB: serial: f81232: fix division by zero on line-speed change
+    - USB: serial: f81534: fix division by zero on line-speed change
+    - igb: Initialize mailbox message for VF reset
+    - xen-netback: move removal of "hotplug-status" to the right place
+    - HID: ite: Add support for Acer S1002 keyboard-dock
+    - HID: ite: Enable QUIRK_TOUCHPAD_ON_OFF_REPORT on Acer Aspire Switch 10E
+    - HID: ite: Enable QUIRK_TOUCHPAD_ON_OFF_REPORT on Acer Aspire Switch V 10
+    - HID: uclogic: Add HID_QUIRK_HIDINPUT_FORCE quirk
+    - net: loopback: use NET_NAME_PREDICTABLE for name_assign_type
+    - usb: musb: remove extra check in musb_gadget_vbus_draw
+    - ARM: dts: qcom: apq8064: fix coresight compatible
+    - arm64: dts: qcom: sdm845-cheza: fix AP suspend pin bias
+    - drivers: soc: ti: knav_qmss_queue: Mark knav_acc_firmwares as static
+    - arm: dts: spear600: Fix clcd interrupt
+    - soc: ti: knav_qmss_queue: Use pm_runtime_resume_and_get instead of
+      pm_runtime_get_sync
+    - soc: ti: knav_qmss_queue: Fix PM disable depth imbalance in knav_queue_probe
+    - soc: ti: smartreflex: Fix PM disable depth imbalance in omap_sr_probe
+    - perf: arm_dsu: Fix hotplug callback leak in dsu_pmu_init()
+    - perf/smmuv3: Fix hotplug callback leak in arm_smmu_pmu_init()
+    - arm64: dts: mt2712e: Fix unit_address_vs_reg warning for oscillators
+    - arm64: dts: mt2712e: Fix unit address for pinctrl node
+    - arm64: dts: mt2712-evb: Fix vproc fixed regulators unit names
+    - arm64: dts: mt2712-evb: Fix usb vbus regulators unit names
+    - arm64: dts: mediatek: mt6797: Fix 26M oscillator unit name
+    - ARM: dts: dove: Fix assigned-addresses for every PCIe Root Port
+    - ARM: dts: armada-370: Fix assigned-addresses for every PCIe Root Port
+    - ARM: dts: armada-xp: Fix assigned-addresses for every PCIe Root Port
+    - ARM: dts: armada-375: Fix assigned-addresses for every PCIe Root Port
+    - ARM: dts: armada-38x: Fix assigned-addresses for every PCIe Root Port
+    - ARM: dts: armada-39x: Fix assigned-addresses for every PCIe Root Port
+    - ARM: dts: turris-omnia: Add ethernet aliases
+    - ARM: dts: turris-omnia: Add switch port 6 node
+    - arm64: dts: armada-3720-turris-mox: Add missing interrupt for RTC
+    - pstore/ram: Fix error return code in ramoops_probe()
+    - ARM: mmp: fix timer_read delay
+    - pstore: Avoid kcore oops by vmap()ing with VM_IOREMAP
+    - tpm/tpm_crb: Fix error message in __crb_relinquish_locality()
+    - cpuidle: dt: Return the correct numbers of parsed idle states
+    - alpha: fix syscall entry in !AUDUT_SYSCALL case
+    - PM: hibernate: Fix mistake in kerneldoc comment
+    - fs: don't audit the capability check in simple_xattr_list()
+    - selftests/ftrace: event_triggers: wait longer for test_event_enable
+    - perf: Fix possible memleak in pmu_dev_alloc()
+    - timerqueue: Use rb_entry_safe() in timerqueue_getnext()
+    - proc: fixup uptime selftest
+    - lib/fonts: fix undefined behavior in bit shift for get_default_font
+    - ocfs2: fix memory leak in ocfs2_stack_glue_init()
+    - MIPS: vpe-mt: fix possible memory leak while module exiting
+    - MIPS: vpe-cmp: fix possible memory leak while module exiting
+    - selftests/efivarfs: Add checking of the test return value
+    - PNP: fix name memory leak in pnp_alloc_dev()
+    - perf/x86/intel/uncore: Fix reference count leak in hswep_has_limit_sbox()
+    - irqchip: gic-pm: Use pm_runtime_resume_and_get() in gic_probe()
+    - EDAC/i10nm: fix refcount leak in pci_get_dev_wrapper()
+    - nfsd: don't call nfsd_file_put from client states seqfile display
+    - genirq/irqdesc: Don't try to remove non-existing sysfs files
+    - cpufreq: amd_freq_sensitivity: Add missing pci_dev_put()
+    - libfs: add DEFINE_SIMPLE_ATTRIBUTE_SIGNED for signed value
+    - lib/notifier-error-inject: fix error when writing -errno to debugfs file
+    - docs: fault-injection: fix non-working usage of negative values
+    - debugfs: fix error when writing negative value to atomic_t debugfs file
+    - ocfs2: ocfs2_mount_volume does cleanup job before return error
+    - ocfs2: rewrite error handling of ocfs2_fill_super
+    - ocfs2: fix memory leak in ocfs2_mount_volume()
+    - rapidio: fix possible name leaks when rio_add_device() fails
+    - rapidio: rio: fix possible name leak in rio_register_mport()
+    - clocksource/drivers/sh_cmt: Make sure channel clock supply is enabled
+    - ACPICA: Fix use-after-free in acpi_ut_copy_ipackage_to_ipackage()
+    - uprobes/x86: Allow to probe a NOP instruction with 0x66 prefix
+    - xen/events: only register debug interrupt for 2-level events
+    - x86/xen: Fix memory leak in xen_smp_intr_init{_pv}()
+    - x86/xen: Fix memory leak in xen_init_lock_cpu()
+    - xen/privcmd: Fix a possible warning in privcmd_ioctl_mmap_resource()
+    - PM: runtime: Improve path in rpm_idle() when no callback
+    - PM: runtime: Do not call __rpm_callback() from rpm_idle()
+    - platform/x86: mxm-wmi: fix memleak in mxm_wmi_call_mx[ds|mx]()
+    - MIPS: BCM63xx: Add check for NULL for clk in clk_enable
+    - MIPS: OCTEON: warn only once if deprecated link status is being used
+    - fs: sysv: Fix sysv_nblocks() returns wrong value
+    - rapidio: fix possible UAF when kfifo_alloc() fails
+    - eventfd: change int to __u64 in eventfd_signal() ifndef CONFIG_EVENTFD
+    - relay: fix type mismatch when allocating memory in relay_create_buf()
+    - hfs: Fix OOB Write in hfs_asc2mac
+    - rapidio: devices: fix missing put_device in mport_cdev_open
+    - wifi: ath9k: hif_usb: fix memory leak of urbs in
+      ath9k_hif_usb_dealloc_tx_urbs()
+    - wifi: ath9k: hif_usb: Fix use-after-free in ath9k_hif_usb_reg_in_cb()
+    - wifi: rtl8xxxu: Fix reading the vendor of combo chips
+    - pata_ipx4xx_cf: Fix unsigned comparison with less than zero
+    - media: i2c: ad5820: Fix error path
+    - can: kvaser_usb: do not increase tx statistics when sending error message
+      frames
+    - can: kvaser_usb: kvaser_usb_leaf: Get capabilities from device
+    - can: kvaser_usb: kvaser_usb_leaf: Rename {leaf,usbcan}_cmd_error_event to
+      {leaf,usbcan}_cmd_can_error_event
+    - can: kvaser_usb: kvaser_usb_leaf: Handle CMD_ERROR_EVENT
+    - can: kvaser_usb_leaf: Set Warning state even without bus errors
+    - can: kvaser_usb_leaf: Fix improved state not being reported
+    - can: kvaser_usb_leaf: Fix wrong CAN state after stopping
+    - can: kvaser_usb_leaf: Fix bogus restart events
+    - can: kvaser_usb: Add struct kvaser_usb_busparams
+    - can: kvaser_usb: Compare requested bittiming parameters with actual
+      parameters in do_set_{,data}_bittiming
+    - clk: renesas: r9a06g032: Repair grave increment error
+    - spi: Update reference to struct spi_controller
+    - drm/panel/panel-sitronix-st7701: Remove panel on DSI attach failure
+    - ima: Rename internal filter rule functions
+    - ima: Fix fall-through warnings for Clang
+    - ima: Handle -ESTALE returned by ima_filter_rule_match()
+    - media: vivid: fix compose size exceed boundary
+    - bpf: propagate precision in ALU/ALU64 operations
+    - mtd: Fix device name leak when register device failed in add_mtd_device()
+    - wifi: rsi: Fix handling of 802.3 EAPOL frames sent via control port
+    - media: camss: Clean up received buffers on failed start of streaming
+    - net, proc: Provide PROC_FS=n fallback for proc_create_net_single_write()
+    - rxrpc: Fix ack.bufferSize to be 0 when generating an ack
+    - drm/radeon: Add the missed acpi_put_table() to fix memory leak
+    - drm/mediatek: Modify dpi power on/off sequence.
+    - ASoC: pxa: fix null-pointer dereference in filter()
+    - regulator: core: fix unbalanced of node refcount in regulator_dev_lookup()
+    - amdgpu/pm: prevent array underflow in vega20_odn_edit_dpm_table()
+    - integrity: Fix memory leakage in keyring allocation error path
+    - ima: Fix misuse of dereference of pointer in template_desc_init_fields()
+    - wifi: ath10k: Fix return value in ath10k_pci_init()
+    - mtd: lpddr2_nvm: Fix possible null-ptr-deref
+    - Input: elants_i2c - properly handle the reset GPIO when power is off
+    - media: solo6x10: fix possible memory leak in solo_sysfs_init()
+    - media: platform: exynos4-is: Fix error handling in fimc_md_init()
+    - media: videobuf-dma-contig: use dma_mmap_coherent
+    - bpf: Move skb->len == 0 checks into __bpf_redirect
+    - HID: hid-sensor-custom: set fixed size for custom attributes
+    - ALSA: pcm: fix undefined behavior in bit shift for SNDRV_PCM_RATE_KNOT
+    - ALSA: seq: fix undefined behavior in bit shift for
+      SNDRV_SEQ_FILTER_USE_EVENT
+    - regulator: core: use kfree_const() to free space conditionally
+    - clk: rockchip: Fix memory leak in rockchip_clk_register_pll()
+    - bonding: Export skip slave logic to function
+    - bonding: Rename slave_arr to usable_slaves
+    - bonding: fix link recovery in mode 2 when updelay is nonzero
+    - mtd: maps: pxa2xx-flash: fix memory leak in probe
+    - media: imon: fix a race condition in send_packet()
+    - clk: imx8mn: correct the usb1_ctrl parent to be usb_bus
+    - clk: imx: replace osc_hdmi with dummy
+    - pinctrl: pinconf-generic: add missing of_node_put()
+    - media: dvb-core: Fix ignored return value in dvb_register_frontend()
+    - media: dvb-usb: az6027: fix null-ptr-deref in az6027_i2c_xfer()
+    - media: s5p-mfc: Add variant data for MFC v7 hardware for Exynos 3250 SoC
+    - drm/tegra: Add missing clk_disable_unprepare() in tegra_dc_probe()
+    - ASoC: dt-bindings: wcd9335: fix reset line polarity in example
+    - ASoC: mediatek: mtk-btcvsd: Add checks for write and read of mtk_btcvsd_snd
+    - NFSv4.2: Clear FATTR4_WORD2_SECURITY_LABEL when done decoding
+    - NFSv4.2: Fix a memory stomp in decode_attr_security_label
+    - NFSv4.2: Fix initialisation of struct nfs4_label
+    - NFSv4: Fix a deadlock between nfs4_open_recover_helper() and delegreturn
+    - ALSA: asihpi: fix missing pci_disable_device()
+    - wifi: iwlwifi: mvm: fix double free on tx path.
+    - ASoC: mediatek: mt8173: Enable IRQ when pdata is ready
+    - drm/radeon: Fix PCI device refcount leak in radeon_atrm_get_bios()
+    - drm/amdgpu: Fix PCI device refcount leak in amdgpu_atrm_get_bios()
+    - ASoC: pcm512x: Fix PM disable depth imbalance in pcm512x_probe
+    - netfilter: conntrack: set icmpv6 redirects as RELATED
+    - bpf, sockmap: Fix repeated calls to sock_put() when msg has more_data
+    - bpf, sockmap: Fix data loss caused by using apply_bytes on ingress redirect
+    - bonding: uninitialized variable in bond_miimon_inspect()
+    - spi: spidev: mask SPI_CS_HIGH in SPI_IOC_RD_MODE
+    - wifi: cfg80211: Fix not unregister reg_pdev when load_builtin_regdb_keys()
+      fails
+    - regulator: core: fix module refcount leak in set_supply()
+    - clk: qcom: clk-krait: fix wrong div2 functions
+    - hsr: Avoid double remove of a node.
+    - configfs: fix possible memory leak in configfs_create_dir()
+    - regulator: core: fix resource leak in regulator_register()
+    - bpf, sockmap: fix race in sock_map_free()
+    - media: saa7164: fix missing pci_disable_device()
+    - ALSA: mts64: fix possible null-ptr-defer in snd_mts64_interrupt
+    - xprtrdma: Fix regbuf data not freed in rpcrdma_req_create()
+    - SUNRPC: Fix missing release socket in rpc_sockname()
+    - NFSv4.x: Fail client initialisation if state manager thread can't run
+    - mmc: alcor: fix return value check of mmc_add_host()
+    - mmc: moxart: fix return value check of mmc_add_host()
+    - mmc: mxcmmc: fix return value check of mmc_add_host()
+    - mmc: pxamci: fix return value check of mmc_add_host()
+    - mmc: rtsx_usb_sdmmc: fix return value check of mmc_add_host()
+    - mmc: toshsd: fix return value check of mmc_add_host()
+    - mmc: vub300: fix return value check of mmc_add_host()
+    - mmc: wmt-sdmmc: fix return value check of mmc_add_host()
+    - mmc: atmel-mci: fix return value check of mmc_add_host()
+    - mmc: omap_hsmmc: fix return value check of mmc_add_host()
+    - mmc: meson-gx: fix return value check of mmc_add_host()
+    - mmc: via-sdmmc: fix return value check of mmc_add_host()
+    - mmc: wbsd: fix return value check of mmc_add_host()
+    - mmc: mmci: fix return value check of mmc_add_host()
+    - media: c8sectpfe: Add of_node_put() when breaking out of loop
+    - media: coda: Add check for dcoda_iram_alloc
+    - media: coda: Add check for kmalloc
+    - clk: samsung: Fix memory leak in _samsung_clk_register_pll()
+    - spi: spi-gpio: Don't set MOSI as an input if not 3WIRE mode
+    - wifi: rtl8xxxu: Add __packed to struct rtl8723bu_c2h
+    - wifi: brcmfmac: Fix error return code in brcmf_sdio_download_firmware()
+    - blktrace: Fix output non-blktrace event when blk_classic option enabled
+    - clk: socfpga: clk-pll: Remove unused variable 'rc'
+    - clk: socfpga: use clk_hw_register for a5/c5
+    - clk: socfpga: Fix memory leak in socfpga_gate_init()
+    - net: vmw_vsock: vmci: Check memcpy_from_msg()
+    - net: defxx: Fix missing err handling in dfx_init()
+    - net: stmmac: selftests: fix potential memleak in stmmac_test_arpoffload()
+    - drivers: net: qlcnic: Fix potential memory leak in qlcnic_sriov_init()
+    - of: overlay: fix null pointer dereferencing in find_dup_cset_node_entry()
+      and find_dup_cset_prop()
+    - ethernet: s2io: don't call dev_kfree_skb() under spin_lock_irqsave()
+    - net: farsync: Fix kmemleak when rmmods farsync
+    - net/tunnel: wait until all sk_user_data reader finish before releasing the
+      sock
+    - net: apple: mace: don't call dev_kfree_skb() under spin_lock_irqsave()
+    - net: apple: bmac: don't call dev_kfree_skb() under spin_lock_irqsave()
+    - net: emaclite: don't call dev_kfree_skb() under spin_lock_irqsave()
+    - net: ethernet: dnet: don't call dev_kfree_skb() under spin_lock_irqsave()
+    - hamradio: don't call dev_kfree_skb() under spin_lock_irqsave()
+    - net: amd: lance: don't call dev_kfree_skb() under spin_lock_irqsave()
+    - net: amd-xgbe: Fix logic around active and passive cables
+    - net: amd-xgbe: Check only the minimum speed for active/passive cables
+    - can: tcan4x5x: Remove invalid write in clear_interrupts
+    - net: lan9303: Fix read error execution path
+    - ntb_netdev: Use dev_kfree_skb_any() in interrupt context
+    - Bluetooth: btusb: don't call kfree_skb() under spin_lock_irqsave()
+    - Bluetooth: hci_qca: don't call kfree_skb() under spin_lock_irqsave()
+    - Bluetooth: hci_ll: don't call kfree_skb() under spin_lock_irqsave()
+    - Bluetooth: hci_h5: don't call kfree_skb() under spin_lock_irqsave()
+    - Bluetooth: hci_bcsp: don't call kfree_skb() under spin_lock_irqsave()
+    - Bluetooth: hci_core: don't call kfree_skb() under spin_lock_irqsave()
+    - Bluetooth: RFCOMM: don't call kfree_skb() under spin_lock_irqsave()
+    - stmmac: fix potential division by 0
+    - apparmor: fix a memleak in multi_transaction_new()
+    - apparmor: fix lockdep warning when removing a namespace
+    - apparmor: Fix abi check to include v8 abi
+    - apparmor: Use pointer to struct aa_label for lbs_cred
+    - RDMA/core: Fix order of nldev_exit call
+    - f2fs: fix normal discard process
+    - RDMA/siw: Fix immediate work request flush to completion queue
+    - RDMA/nldev: Return "-EAGAIN" if the cm_id isn't from expected port
+    - RDMA/siw: Set defined status for work completion with undefined status
+    - scsi: scsi_debug: Fix a warning in resp_write_scat()
+    - crypto: ccree - swap SHA384 and SHA512 larval hashes at build time
+    - crypto: ccree - Remove debugfs when platform_driver_register failed
+    - PCI: Check for alloc failure in pci_request_irq()
+    - RDMA/hfi: Decrease PCI device reference count in error path
+    - crypto: ccree - Make cc_debugfs_global_fini() available for module init
+      function
+    - RDMA/rxe: Fix NULL-ptr-deref in rxe_qp_do_cleanup() when socket create
+      failed
+    - scsi: hpsa: Fix possible memory leak in hpsa_init_one()
+    - crypto: tcrypt - Fix multibuffer skcipher speed test mem leak
+    - scsi: mpt3sas: Fix possible resource leaks in mpt3sas_transport_port_add()
+    - scsi: hpsa: Fix error handling in hpsa_add_sas_host()
+    - scsi: hpsa: Fix possible memory leak in hpsa_add_sas_device()
+    - scsi: fcoe: Fix possible name leak when device_register() fails
+    - scsi: ipr: Fix WARNING in ipr_init()
+    - scsi: fcoe: Fix transport not deattached when fcoe_if_init() fails
+    - scsi: snic: Fix possible UAF in snic_tgt_create()
+    - RDMA/nldev: Add checks for nla_nest_start() in fill_stat_counter_qps()
+    - f2fs: avoid victim selection from previous victim section
+    - crypto: omap-sham - Use pm_runtime_resume_and_get() in omap_sham_probe()
+    - RDMA/hfi1: Fix error return code in parse_platform_config()
+    - orangefs: Fix sysfs not cleanup when dev init failed
+    - crypto: img-hash - Fix variable dereferenced before check 'hdev->req'
+    - hwrng: amd - Fix PCI device refcount leak
+    - hwrng: geode - Fix PCI device refcount leak
+    - IB/IPoIB: Fix queue count inconsistency for PKEY child interfaces
+    - drivers: dio: fix possible memory leak in dio_init()
+    - tty: serial: tegra: Activate RX DMA transfer by request
+    - serial: tegra: Read DMA status before terminating
+    - class: fix possible memory leak in __class_register()
+    - vfio: platform: Do not pass return buffer to ACPI _RST method
+    - uio: uio_dmem_genirq: Fix missing unlock in irq configuration
+    - uio: uio_dmem_genirq: Fix deadlock between irq config and handling
+    - usb: fotg210-udc: Fix ages old endianness issues
+    - staging: vme_user: Fix possible UAF in tsi148_dma_list_add
+    - usb: typec: Check for ops->exit instead of ops->enter in altmode_exit
+    - usb: typec: tcpci: fix of node refcount leak in tcpci_register_port()
+    - serial: amba-pl011: avoid SBSA UART accessing DMACR register
+    - serial: pl011: Do not clear RX FIFO & RX interrupt in unthrottle.
+    - serial: pch: Fix PCI device refcount leak in pch_request_dma()
+    - tty: serial: clean up stop-tx part in altera_uart_tx_chars()
+    - tty: serial: altera_uart_{r,t}x_chars() need only uart_port
+    - serial: altera_uart: fix locking in polling mode
+    - serial: sunsab: Fix error handling in sunsab_init()
+    - test_firmware: fix memory leak in test_firmware_init()
+    - misc: ocxl: fix possible name leak in ocxl_file_register_afu()
+    - misc: tifm: fix possible memory leak in tifm_7xx1_switch_media()
+    - misc: sgi-gru: fix use-after-free error in gru_set_context_option, gru_fault
+      and gru_handle_user_call_os
+    - cxl: fix possible null-ptr-deref in cxl_guest_init_afu|adapter()
+    - cxl: fix possible null-ptr-deref in cxl_pci_init_afu|adapter()
+    - counter: stm32-lptimer-cnt: fix the check on arr and cmp registers update
+    - usb: roles: fix of node refcount leak in usb_role_switch_is_parent()
+    - usb: gadget: f_hid: optional SETUP/SET_REPORT mode
+    - usb: gadget: f_hid: fix f_hidg lifetime vs cdev
+    - usb: gadget: f_hid: fix refcount leak on error path
+    - drivers: mcb: fix resource leak in mcb_probe()
+    - mcb: mcb-parse: fix error handing in chameleon_parse_gdd()
+    - chardev: fix error handling in cdev_device_add()
+    - i2c: pxa-pci: fix missing pci_disable_device() on error in ce4100_i2c_probe
+    - staging: rtl8192u: Fix use after free in ieee80211_rx()
+    - staging: rtl8192e: Fix potential use-after-free in rtllib_rx_Monitor()
+    - vme: Fix error not catched in fake_init()
+    - i2c: ismt: Fix an out-of-bounds bug in ismt_access()
+    - usb: storage: Add check for kcalloc
+    - tracing/hist: Fix issue of losting command info in error_log
+    - samples: vfio-mdev: Fix missing pci_disable_device() in mdpy_fb_probe()
+    - fbdev: ssd1307fb: Drop optional dependency
+    - fbdev: pm2fb: fix missing pci_disable_device()
+    - fbdev: via: Fix error in via_core_init()
+    - fbdev: vermilion: decrease reference count in error path
+    - fbdev: uvesafb: Fixes an error handling path in uvesafb_probe()
+    - HSI: omap_ssi_core: fix unbalanced pm_runtime_disable()
+    - HSI: omap_ssi_core: fix possible memory leak in ssi_probe()
+    - power: supply: fix residue sysfs file in error handle route of
+      __power_supply_register()
+    - perf trace: Return error if a system call doesn't exist
+    - perf trace: Separate 'struct syscall_fmt' definition from syscall_fmts
+      variable
+    - perf trace: Factor out the initialization of syscal_arg_fmt->scnprintf
+    - perf trace: Add the syscall_arg_fmt pointer to syscall_arg
+    - perf trace: Allow associating scnprintf routines with well known arg names
+    - perf trace: Add a strtoul() method to 'struct syscall_arg_fmt'
+    - perf trace: Use macro RAW_SYSCALL_ARGS_NUM to replace number
+    - perf trace: Handle failure when trace point folder is missed
+    - perf symbol: correction while adjusting symbol
+    - HSI: omap_ssi_core: Fix error handling in ssi_init()
+    - power: supply: fix null pointer dereferencing in
+      power_supply_get_battery_info
+    - RDMA/siw: Fix pointer cast warning
+    - include/uapi/linux/swab: Fix potentially missing __always_inline
+    - rtc: snvs: Allow a time difference on clock register read
+    - rtc: pcf85063: Fix reading alarm
+    - iommu/amd: Fix pci device refcount leak in ppr_notifier()
+    - iommu/fsl_pamu: Fix resource leak in fsl_pamu_probe()
+    - macintosh: fix possible memory leak in macio_add_one_device()
+    - macintosh/macio-adb: check the return value of ioremap()
+    - powerpc/52xx: Fix a resource leak in an error handling path
+    - cxl: Fix refcount leak in cxl_calc_capp_routing
+    - powerpc/xive: add missing iounmap() in error path in
+      xive_spapr_populate_irq_data()
+    - powerpc/perf: callchain validate kernel stack pointer bounds
+    - powerpc/83xx/mpc832x_rdb: call platform_device_put() in error case in
+      of_fsl_spi_probe()
+    - powerpc/hv-gpci: Fix hv_gpci event list
+    - selftests/powerpc: Fix resource leaks
+    - pwm: sifive: Call pwm_sifive_update_clock() while mutex is held
+    - remoteproc: sysmon: fix memory leak in qcom_add_sysmon_subdev()
+    - remoteproc: qcom_q6v5_pas: Fix missing of_node_put() in
+      adsp_alloc_memory_region()
+    - rtc: st-lpc: Add missing clk_disable_unprepare in st_rtc_probe()
+    - rtc: pic32: Move devm_rtc_allocate_device earlier in pic32_rtc_probe()
+    - nfsd: Define the file access mode enum for tracing
+    - NFSD: Add tracepoints to NFSD's duplicate reply cache
+    - nfsd: under NFSv4.1, fix double svc_xprt_put on rpc_create failure
+    - mISDN: hfcsusb: don't call dev_kfree_skb/kfree_skb() under
+      spin_lock_irqsave()
+    - mISDN: hfcpci: don't call dev_kfree_skb/kfree_skb() under
+      spin_lock_irqsave()
+    - mISDN: hfcmulti: don't call dev_kfree_skb/kfree_skb() under
+      spin_lock_irqsave()
+    - nfc: pn533: Clear nfc_target before being used
+    - r6040: Fix kmemleak in probe and remove
+    - rtc: mxc_v2: Add missing clk_disable_unprepare()
+    - openvswitch: Fix flow lookup to use unmasked key
+    - skbuff: Account for tail adjustment during pull operations
+    - mailbox: zynq-ipi: fix error handling while device_register() fails
+    - net_sched: reject TCF_EM_SIMPLE case for complex ematch module
+    - rxrpc: Fix missing unlock in rxrpc_do_sendmsg()
+    - myri10ge: Fix an error handling path in myri10ge_probe()
+    - net: stream: purge sk_error_queue in sk_stream_kill_queues()
+    - rcu: Fix __this_cpu_read() lockdep warning in rcu_force_quiescent_state()
+    - binfmt_misc: fix shift-out-of-bounds in check_special_flags
+    - fs: jfs: fix shift-out-of-bounds in dbAllocAG
+    - udf: Avoid double brelse() in udf_rename()
+    - fs: jfs: fix shift-out-of-bounds in dbDiscardAG
+    - ACPICA: Fix error code path in acpi_ds_call_control_method()
+    - nilfs2: fix shift-out-of-bounds/overflow in nilfs_sb2_bad_offset()
+    - acct: fix potential integer overflow in encode_comp_t()
+    - hfs: fix OOB Read in __hfs_brec_find
+    - drm/etnaviv: add missing quirks for GC300
+    - brcmfmac: return error when getting invalid max_flowrings from dongle
+    - wifi: ath9k: verify the expected usb_endpoints are present
+    - wifi: ar5523: Fix use-after-free on ar5523_cmd() timed out
+    - ASoC: codecs: rt298: Add quirk for KBL-R RVP platform
+    - ipmi: fix memleak when unload ipmi driver
+    - bpf: make sure skb->len != 0 when redirecting to a tunneling device
+    - net: ethernet: ti: Fix return type of netcp_ndo_start_xmit()
+    - hamradio: baycom_epp: Fix return type of baycom_send_packet()
+    - wifi: brcmfmac: Fix potential shift-out-of-bounds in
+      brcmf_fw_alloc_request()
+    - igb: Do not free q_vector unless new one was allocated
+    - s390/ctcm: Fix return type of ctc{mp,}m_tx()
+    - s390/netiucv: Fix return type of netiucv_tx()
+    - s390/lcs: Fix return type of lcs_start_xmit()
+    - drm/rockchip: Use drm_mode_copy()
+    - drm/sti: Use drm_mode_copy()
+    - drivers/md/md-bitmap: check the return value of md_bitmap_get_counter()
+    - md/raid1: stop mdx_raid1 thread when raid1 array run failed
+    - net: add atomic_long_t to net_device_stats fields
+    - mrp: introduce active flags to prevent UAF when applicant uninit
+    - ppp: associate skb with a device at tx
+    - bpf: Prevent decl_tag from being referenced in func_proto arg
+    - media: dvb-frontends: fix leak of memory fw
+    - media: dvbdev: adopts refcnt to avoid UAF
+    - media: dvb-usb: fix memory leak in dvb_usb_adapter_init()
+    - blk-mq: fix possible memleak when register 'hctx' failed
+    - regulator: core: fix use_count leakage when handling boot-on
+    - mmc: f-sdh30: Add quirks for broken timeout clock capability
+    - media: si470x: Fix use-after-free in si470x_int_in_callback()
+    - clk: st: Fix memory leak in st_of_quadfs_setup()
+    - hugetlbfs: fix null-ptr-deref in hugetlbfs_parse_param()
+    - drm/fsl-dcu: Fix return type of fsl_dcu_drm_connector_mode_valid()
+    - drm/sti: Fix return type of sti_{dvo,hda,hdmi}_connector_mode_valid()
+    - orangefs: Fix kmemleak in orangefs_prepare_debugfs_help_string()
+    - orangefs: Fix kmemleak in orangefs_{kernel,client}_debug_init()
+    - ALSA/ASoC: hda: move/rename snd_hdac_ext_stop_streams to hdac_stream.c
+    - ALSA: hda: add snd_hdac_stop_streams() helper
+    - ASoC: Intel: Skylake: Fix driver hang during shutdown
+    - ASoC: mediatek: mt8173-rt5650-rt5514: fix refcount leak in
+      mt8173_rt5650_rt5514_dev_probe()
+    - ASoC: audio-graph-card: fix refcount leak of cpu_ep in
+      __graph_for_each_link()
+    - ASoC: rockchip: pdm: Add missing clk_disable_unprepare() in
+      rockchip_pdm_runtime_resume()
+    - ASoC: wm8994: Fix potential deadlock
+    - ASoC: rockchip: spdif: Add missing clk_disable_unprepare() in
+      rk_spdif_runtime_resume()
+    - ASoC: rt5670: Remove unbalanced pm_runtime_put()
+    - pstore: Switch pmsg_lock to an rt_mutex to avoid priority inversion
+    - pstore: Make sure CONFIG_PSTORE_PMSG selects CONFIG_RT_MUTEXES
+    - ALSA: hda/realtek: Add quirk for Lenovo TianYi510Pro-14IOB
+    - ALSA: hda/hdmi: Add HP Device 0x8711 to force connect list
+    - usb: dwc3: core: defer probe on ulpi_read_id timeout
+    - HID: wacom: Ensure bootloader PID is usable in hidraw mode
+    - reiserfs: Add missing calls to reiserfs_security_free()
+    - iio: adc: ad_sigma_delta: do not use internal iio_dev lock
+    - iio: adc128s052: add proper .data members in adc128_of_match table
+    - regulator: core: fix deadlock on regulator enable
+    - gcov: add support for checksum field
+    - media: dvbdev: fix build warning due to comments
+    - media: dvbdev: fix refcnt bug
+    - cifs: fix oops during encryption
+    - nvme-pci: fix doorbell buffer value endianness
+    - ata: ahci: Fix PCS quirk application for suspend
+    - nvme: fix the NVME_CMD_EFFECTS_CSE_MASK definition
+    - objtool: Fix SEGFAULT
+    - powerpc/rtas: avoid device tree lookups in rtas_os_term()
+    - powerpc/rtas: avoid scheduling in rtas_os_term()
+    - HID: multitouch: fix Asus ExpertBook P2 P2451FA trackpoint
+    - HID: plantronics: Additional PIDs for double volume key presses quirk
+    - hfsplus: fix bug causing custom uid and gid being unable to be assigned with
+      mount
+    - ovl: Use ovl mounter's fsuid and fsgid in ovl_link()
+    - ALSA: line6: correct midi status byte when receiving data from podxt
+    - ALSA: line6: fix stack overflow in line6_midi_transmit
+    - pnode: terminate at peers of source
+    - md: fix a crash in mempool_free
+    - mm, compaction: fix fast_isolate_around() to stay within boundaries
+    - f2fs: should put a page when checking the summary info
+    - mmc: vub300: fix warning - do not call blocking ops when !TASK_RUNNING
+    - tpm: tpm_crb: Add the missed acpi_put_table() to fix memory leak
+    - tpm: tpm_tis: Add the missed acpi_put_table() to fix memory leak
+    - SUNRPC: Don't leak netobj memory when gss_read_proxy_verf() fails
+    - net/af_packet: add VLAN support for AF_PACKET SOCK_RAW GSO
+    - net/af_packet: make sure to pull mac header
+    - media: stv0288: use explicitly signed char
+    - soc: qcom: Select REMAP_MMIO for LLCC driver
+    - kest.pl: Fix grub2 menu handling for rebooting
+    - ktest.pl minconfig: Unset configs instead of just removing them
+    - mmc: sdhci-sprd: Disable CLK_AUTO when the clock is less than 400K
+    - btrfs: fix resolving backrefs for inline extent followed by prealloc
+    - ARM: ux500: do not directly dereference __iomem
+    - arm64: dts: qcom: sdm850-lenovo-yoga-c630: correct I2C12 pins drive strength
+    - selftests: Use optional USERCFLAGS and USERLDFLAGS
+    - cpufreq: Init completion before kobject_init_and_add()
+    - binfmt: Move install_exec_creds after setup_new_exec to match binfmt_elf
+    - binfmt: Fix error return code in load_elf_fdpic_binary()
+    - dm cache: Fix ABBA deadlock between shrink_slab and dm_cache_metadata_abort
+    - dm thin: Fix ABBA deadlock between shrink_slab and dm_pool_abort_metadata
+    - dm thin: Use last transaction's pmd->root when commit failed
+    - dm thin: Fix UAF in run_timer_softirq()
+    - dm integrity: Fix UAF in dm_integrity_dtr()
+    - dm clone: Fix UAF in clone_dtr()
+    - dm cache: Fix UAF in destroy()
+    - dm cache: set needs_check flag after aborting metadata
+    - tracing/hist: Fix out-of-bound write on 'action_data.var_ref_idx'
+    - x86/microcode/intel: Do not retry microcode reloading on the APs
+    - tracing/hist: Fix wrong return value in parse_action_params()
+    - tracing: Fix infinite loop in tracing_read_pipe on overflowed
+      print_trace_line
+    - ARM: 9256/1: NWFPE: avoid compiler-generated __aeabi_uldivmod
+    - media: dvb-core: Fix double free in dvb_register_device()
+    - cifs: fix confusing debug message
+    - cifs: fix missing display of three mount options
+    - md/bitmap: Fix bitmap chunk size overflow issues
+    - efi: Add iMac Pro 2017 to uefi skip cert quirk
+    - ipmi: fix long wait in unload when IPMI disconnect
+    - mtd: spi-nor: Check for zero erase size in spi_nor_find_best_erase_type()
+    - ima: Fix a potential NULL pointer access in ima_restore_measurement_list
+    - ipmi: fix use after free in _ipmi_destroy_user()
+    - PCI: Fix pci_device_is_present() for VFs by checking PF
+    - PCI/sysfs: Fix double free in error path
+    - crypto: n2 - add missing hash statesize
+    - iommu/amd: Fix ivrs_acpihid cmdline parsing code
+    - parisc: led: Fix potential null-ptr-deref in start_task()
+    - device_cgroup: Roll back to original exceptions after copy failure
+    - drm/connector: send hotplug uevent on connector cleanup
+    - drm/vmwgfx: Validate the box size for the snooped cursor
+    - ext4: add inode table check in __ext4_get_inode_loc to aovid possible
+      infinite loop
+    - ext4: fix undefined behavior in bit shift for ext4_check_flag_values
+    - ext4: add EXT4_IGET_BAD flag to prevent unexpected bad inode
+    - ext4: add helper to check quota inums
+    - ext4: fix reserved cluster accounting in __es_remove_extent()
+    - ext4: fix bug_on in __es_tree_search caused by bad boot loader inode
+    - ext4: init quota for 'old.inode' in 'ext4_rename'
+    - ext4: fix delayed allocation bug in ext4_clu_mapped for bigalloc + inline
+    - ext4: fix corruption when online resizing a 1K bigalloc fs
+    - ext4: fix error code return to user-space in ext4_get_branch()
+    - ext4: avoid BUG_ON when creating xattrs
+    - ext4: fix inode leak in ext4_xattr_inode_create() on an error path
+    - ext4: initialize quota before expanding inode in setproject ioctl
+    - ext4: avoid unaccounted block allocation when expanding inode
+    - ext4: allocate extended attribute value in vmalloc area
+    - btrfs: replace strncpy() with strscpy()
+    - PM/devfreq: governor: Add a private governor_data for governor
+    - media: s5p-mfc: Fix to handle reference queue during finishing
+    - media: s5p-mfc: Clear workbit to handle error condition
+    - media: s5p-mfc: Fix in register read and write for H264
+    - dm thin: resume even if in FAIL mode
+    - perf probe: Use dwarf_attr_integrate as generic DWARF attr accessor
+    - perf probe: Fix to get the DW_AT_decl_file and DW_AT_call_file as unsinged
+      data
+    - KVM: x86: optimize more exit handlers in vmx.c
+    - KVM: retpolines: x86: eliminate retpoline from vmx.c exit handlers
+    - KVM: VMX: Rename INTERRUPT_PENDING to INTERRUPT_WINDOW
+    - KVM: VMX: Rename NMI_PENDING to NMI_WINDOW
+    - KVM: VMX: Fix the spelling of CPU_BASED_USE_TSC_OFFSETTING
+    - KVM: nVMX: Properly expose ENABLE_USR_WAIT_PAUSE control to L1
+    - ravb: Fix "failed to switch device to config mode" message during unbind
+    - ext4: goto right label 'failed_mount3a'
+    - ext4: correct inconsistent error msg in nojournal mode
+    - mm/highmem: Lift memcpy_[to|from]_page to core
+    - ext4: use memcpy_to_page() in pagecache_write()
+    - fs: ext4: initialize fsdata in pagecache_write()
+    - ext4: use kmemdup() to replace kmalloc + memcpy
+    - mbcache: don't reclaim used entries
+    - mbcache: add functions to delete entry if unused
+    - ext4: remove EA inode entry from mbcache on inode eviction
+    - ext4: unindent codeblock in ext4_xattr_block_set()
+    - ext4: fix race when reusing xattr blocks
+    - mbcache: automatically delete entries from cache on freeing
+    - ext4: fix deadlock due to mbcache entry corruption
+    - SUNRPC: ensure the matching upcall is in-flight upon downcall
+    - bpf: pull before calling skb_postpull_rcsum()
+    - nfsd: shut down the NFSv4 state objects before the filecache
+    - net: hns3: add interrupts re-initialization while doing VF FLR
+    - net: sched: fix memory leak in tcindex_set_parms
+    - qlcnic: prevent ->dcb use-after-free on qlcnic_dcb_enable() failure
+    - nfc: Fix potential resource leaks
+    - vhost: fix range used in translate_desc()
+    - net: amd-xgbe: add missed tasklet_kill
+    - net: phy: xgmiitorgmii: Fix refcount leak in xgmiitorgmii_probe
+    - RDMA/uverbs: Silence shiftTooManyBitsSigned warning
+    - RDMA/mlx5: Fix validation of max_rd_atomic caps for DC
+    - net: sched: atm: dont intepret cls results when asked to drop
+    - net: sched: cbq: dont intepret cls results when asked to drop
+    - perf tools: Fix resources leak in perf_data__open_dir()
+    - drivers/net/bonding/bond_3ad: return when there's no aggregator
+    - usb: rndis_host: Secure rndis_query check against int overflow
+    - drm/i915: unpin on error in intel_vgpu_shadow_mm_pin()
+    - caif: fix memory leak in cfctrl_linkup_request()
+    - udf: Fix extension of the last extent in the file
+    - ASoC: Intel: bytcr_rt5640: Add quirk for the Advantech MICA-071 tablet
+    - x86/bugs: Flush IBP in ib_prctl_set()
+    - nfsd: fix handling of readdir in v4root vs. mount upcall timeout
+    - riscv: uaccess: fix type of 0 variable on error in get_user()
+    - ext4: don't allow journal inode to have encrypt flag
+    - hfs/hfsplus: use WARN_ON for sanity check
+    - hfs/hfsplus: avoid WARN_ON() for sanity check, use proper error handling
+    - mbcache: Avoid nesting of cache->c_list_lock under bit locks
+    - parisc: Align parisc MADV_XXX constants with all other architectures
+    - selftests: Fix kselftest O=objdir build from cluttering top level objdir
+    - selftests: set the BUILD variable to absolute path
+    - driver core: Fix bus_type.match() error handling in __driver_attach()
+    - net: sched: disallow noqueue for qdisc classes
+    - KVM: arm64: Fix S1PTW handling on RO memslots
+    - efi: tpm: Avoid READ_ONCE() for accessing the event log
+    - docs: Fix the docs build with Sphinx 6.0
+    - perf auxtrace: Fix address filter duplicate symbol selection
+    - s390/kexec: fix ipl report address for kdump
+    - s390/percpu: add READ_ONCE() to arch_this_cpu_to_op_simple()
+    - net/ulp: prevent ULP without clone op from entering the LISTEN status
+    - ALSA: hda/hdmi: Add a HP device 0x8715 to force connect list
+    - cifs: Fix uninitialized memory read for smb311 posix symlink create
+    - drm/msm/adreno: Make adreno quirks not overwrite each other
+    - platform/x86: sony-laptop: Don't turn off 0x153 keyboard backlight during
+      probe
+    - ixgbe: fix pci device refcount leak
+    - ipv6: raw: Deduct extension header length in rawv6_push_pending_frames
+    - wifi: wilc1000: sdio: fix module autoloading
+    - usb: ulpi: defer ulpi_register on ulpi_read_id timeout
+    - jbd2: use the correct print format
+    - quota: Factor out setup of quota inode
+    - ext4: fix bug_on in __es_tree_search caused by bad quota inode
+    - ext4: lost matching-pair of trace in ext4_truncate
+    - ext4: fix use-after-free in ext4_orphan_cleanup
+    - ext4: fix uninititialized value in 'ext4_evict_inode'
+    - netfilter: ipset: Fix overflow before widen in the bitmap_ip_create()
+      function.
+    - powerpc/imc-pmu: Fix use of mutex in IRQs disabled section
+    - x86/boot: Avoid using Intel mnemonics in AT&T syntax asm
+    - EDAC/device: Fix period calculation in edac_device_reset_delay_period()
+    - regulator: da9211: Use irq handler when ready
+    - tipc: improve throughput between nodes in netns
+    - tipc: eliminate checking netns if node established
+    - tipc: fix unexpected link reset due to discovery messages
+    - hvc/xen: lock console list traversal
+    - nfc: pn533: Wait for out_urb's completion in pn533_usb_send_frame()
+    - net/sched: act_mpls: Fix warning during failed attribute validation
+    - net/mlx5: Rename ptp clock info
+    - net/mlx5: Fix ptp max frequency adjustment range
+    - iommu/mediatek-v1: Add error handle for mtk_iommu_probe
+    - iommu/mediatek-v1: Fix an error handling path in mtk_iommu_v1_probe()
+    - x86/resctrl: Use task_curr() instead of task_struct->on_cpu to prevent
+      unnecessary IPI
+    - x86/resctrl: Fix task CLOSID/RMID update race
+    - drm/virtio: Fix GEM handle creation UAF
+    - arm64: atomics: format whitespace consistently
+    - arm64: atomics: remove LL/SC trampolines
+    - arm64: cmpxchg_double*: hazard against entire exchange variable
+    - efi: fix NULL-deref in init error path
+    - mm: Always release pages to the buddy allocator in memblock_free_late().
+    - Revert "usb: ulpi: defer ulpi_register on ulpi_read_id timeout"
+    - tipc: fix use-after-free in tipc_disc_rcv()
+    - tty: serial: tegra: Handle RX transfer in PIO mode if DMA wasn't started
+    - tipc: Add a missing case of TIPC_DIRECT_MSG type
+    - ocfs2: fix freeing uninitialized resource on ocfs2_dlm_shutdown
+    - tipc: call tipc_lxc_xmit without holding node_read_lock
+    - Linux 5.4.229
+  * Focal update: v5.4.229 upstream stable release (LP: #2003914) //
+    CVE-2023-0266 was assigned for this issue.
+    - ALSA: pcm: Move rwsem lock inside snd_ctl_elem_read to prevent UAF
+  * Focal update: v5.4.229 upstream stable release (LP: #2003914) //
+    CVE-2022-41218 is assigned to those bugs above.
+    - media: dvb-core: Fix UAF due to refcount races at releasing
+  * Focal update: v5.4.228 upstream stable release (LP: #2003904)
+    - x86/smpboot: Move rcu_cpu_starting() earlier
+    - mm/hugetlb: fix races when looking up a CONT-PTE/PMD size hugetlb page
+    - block: unhash blkdev part inode when the part is deleted
+    - ASoC: ops: Check bounds for second channel in snd_soc_put_volsw_sx()
+    - pinctrl: meditatek: Startup with the IRQs disabled
+    - can: sja1000: fix size of OCR_MODE_MASK define
+    - can: mcba_usb: Fix termination command argument
+    - ASoC: ops: Correct bounds check for second channel on SX controls
+    - Linux 5.4.228
+  * Focal update: v5.4.227 upstream stable release (LP: #2003901)
+    - arm64: dts: rockchip: keep I2S1 disabled for GPIO function on ROCK Pi 4
+      series
+    - arm: dts: rockchip: fix node name for hym8563 rtc
+    - ARM: dts: rockchip: fix ir-receiver node names
+    - ARM: dts: rockchip: rk3188: fix lcdc1-rgb24 node name
+    - ARM: 9251/1: perf: Fix stacktraces for tracepoint events in THUMB2 kernels
+    - ARM: 9266/1: mm: fix no-MMU ZERO_PAGE() implementation
+    - ARM: dts: rockchip: disable arm_global_timer on rk3066 and rk3188
+    - 9p/fd: Use P9_HDRSZ for header size
+    - regulator: slg51000: Wait after asserting CS pin
+    - ALSA: seq: Fix function prototype mismatch in snd_seq_expand_var_event
+    - btrfs: send: avoid unaligned encoded writes when attempting to clone range
+    - ASoC: soc-pcm: Add NULL check in BE reparenting
+    - regulator: twl6030: fix get status of twl6032 regulators
+    - fbcon: Use kzalloc() in fbcon_prepare_logo()
+    - 9p/xen: check logical size for buffer size
+    - net: usb: qmi_wwan: add u-blox 0x1342 composition
+    - mm/khugepaged: take the right locks for page table retraction
+    - mm/khugepaged: fix GUP-fast interaction by sending IPI
+    - mm/khugepaged: invoke MMU notifiers in shmem/file collapse paths
+    - xen/netback: do some code cleanup
+    - xen/netback: don't call kfree_skb() with interrupts disabled
+    - Revert "net: dsa: b53: Fix valid setting for MDB entries"
+    - media: v4l2-dv-timings.c: fix too strict blanking sanity checks
+    - memcg: fix possible use-after-free in memcg_write_event_control()
+    - mm/gup: fix gup_pud_range() for dax
+    - KVM: s390: vsie: Fix the initialization of the epoch extension (epdx) field
+    - drm/shmem-helper: Remove errant put in error path
+    - HID: usbhid: Add ALWAYS_POLL quirk for some mice
+    - HID: hid-lg4ff: Add check for empty lbuf
+    - HID: core: fix shift-out-of-bounds in hid_report_raw_event
+    - can: af_can: fix NULL pointer dereference in can_rcv_filter
+    - ieee802154: cc2520: Fix error return code in cc2520_hw_init()
+    - ca8210: Fix crash by zero initializing data
+    - drm/bridge: ti-sn65dsi86: Fix output polarity setting bug
+    - gpio: amd8111: Fix PCI device reference count leak
+    - e1000e: Fix TX dispatch condition
+    - igb: Allocate MSI-X vector when testing
+    - af_unix: Get user_ns from in_skb in unix_diag_get_exact().
+    - Bluetooth: 6LoWPAN: add missing hci_dev_put() in get_l2cap_conn()
+    - Bluetooth: Fix not cleanup led when bt_init fails
+    - net: dsa: ksz: Check return value
+    - selftests: rtnetlink: correct xfrm policy rule in kci_test_ipsec_offload
+    - mac802154: fix missing INIT_LIST_HEAD in ieee802154_if_add()
+    - net: encx24j600: Add parentheses to fix precedence
+    - net: encx24j600: Fix invalid logic in reading of MISTAT register
+    - xen-netfront: Fix NULL sring after live migration
+    - net: mvneta: Prevent out of bounds read in mvneta_config_rss()
+    - i40e: Fix not setting default xps_cpus after reset
+    - i40e: Fix for VF MAC address 0
+    - i40e: Disallow ip4 and ip6 l4_4_bytes
+    - NFC: nci: Bounds check struct nfc_target arrays
+    - nvme initialize core quirks before calling nvme_init_subsystem
+    - net: stmmac: fix "snps,axi-config" node property parsing
+    - net: thunderx: Fix missing destroy_workqueue of nicvf_rx_mode_wq
+    - net: hisilicon: Fix potential use-after-free in hisi_femac_rx()
+    - net: hisilicon: Fix potential use-after-free in hix5hd2_rx()
+    - tipc: Fix potential OOB in tipc_link_proto_rcv()
+    - ipv4: Fix incorrect route flushing when source address is deleted
+    - ipv4: Fix incorrect route flushing when table ID 0 is used
+    - ethernet: aeroflex: fix potential skb leak in greth_init_rings()
+    - net: plip: don't call kfree_skb/dev_kfree_skb() under spin_lock_irq()
+    - ipv6: avoid use-after-free in ip6_fragment()
+    - net: mvneta: Fix an out of bounds check
+    - can: esd_usb: Allow REC and TEC to return to zero
+    - Linux 5.4.227
+  * 5.15.0-58.64 breaks xen bridge networking (pvh domU) (LP: #2002889) // Focal
+    update: v5.4.227 upstream stable release (LP: #2003901)
+    - xen/netback: fix build warning
+  * Focal update: v5.4.226 upstream stable release (LP: #2003896)
+    - wifi: mac80211: fix memory free error when registering wiphy fail
+    - wifi: mac80211_hwsim: fix debugfs attribute ps with rc table support
+    - audit: fix undefined behavior in bit shift for AUDIT_BIT
+    - wifi: mac80211: Fix ack frame idr leak when mesh has no route
+    - spi: stm32: fix stm32_spi_prepare_mbr() that halves spi clk for every run
+    - drm: panel-orientation-quirks: Add quirk for Acer Switch V 10 (SW5-017)
+    - block, bfq: fix null pointer dereference in bfq_bio_bfqg()
+    - arm64/syscall: Include asm/ptrace.h in syscall_wrapper header.
+    - RISC-V: vdso: Do not add missing symbols to version section in linker script
+    - MIPS: pic32: treat port as signed integer
+    - af_key: Fix send_acquire race with pfkey_register
+    - ARM: dts: am335x-pcm-953: Define fixed regulators in root node
+    - ASoC: sgtl5000: Reset the CHIP_CLK_CTRL reg on remove
+    - regulator: core: fix kobject release warning and memory leak in
+      regulator_register()
+    - regulator: core: fix UAF in destroy_regulator()
+    - bus: sunxi-rsb: Support atomic transfers
+    - tee: optee: fix possible memory leak in optee_register_device()
+    - ARM: dts: at91: sam9g20ek: enable udc vbus gpio pinctrl
+    - net: liquidio: simplify if expression
+    - nfc/nci: fix race with opening and closing
+    - net: pch_gbe: fix potential memleak in pch_gbe_tx_queue()
+    - 9p/fd: fix issue of list_del corruption in p9_fd_cancel()
+    - ARM: mxs: fix memory leak in mxs_machine_init()
+    - net/mlx4: Check retval of mlx4_bitmap_init
+    - net/qla3xxx: fix potential memleak in ql3xxx_send()
+    - net: pch_gbe: fix pci device refcount leak while module exiting
+    - nfp: add port from netdev validation for EEPROM access
+    - Drivers: hv: vmbus: fix double free in the error path of
+      vmbus_add_channel_work()
+    - Drivers: hv: vmbus: fix possible memory leak in vmbus_device_register()
+    - net/mlx5: Fix FW tracer timestamp calculation
+    - tipc: set con sock in tipc_conn_alloc
+    - tipc: add an extra conn_get in tipc_conn_alloc
+    - tipc: check skb_linearize() return value in tipc_disc_rcv()
+    - xfrm: Fix ignored return value in xfrm6_init()
+    - NFC: nci: fix memory leak in nci_rx_data_packet()
+    - regulator: twl6030: re-add TWL6032_SUBCLASS
+    - bnx2x: fix pci device refcount leak in bnx2x_vf_is_pcie_pending()
+    - dccp/tcp: Reset saddr on failure after inet6?_hash_connect().
+    - s390/dasd: fix no record found for raw_track_access
+    - nfc: st-nci: fix incorrect validating logic in EVT_TRANSACTION
+    - nfc: st-nci: fix memory leaks in EVT_TRANSACTION
+    - net: thunderx: Fix the ACPI memory leak
+    - s390/crashdump: fix TOD programmable field size
+    - lib/vdso: use "grep -E" instead of "egrep"
+    - usb: dwc3: exynos: Fix remove() function
+    - arm64: dts: rockchip: lower rk3399-puma-haikou SD controller clock frequency
+    - iio: light: apds9960: fix wrong register for gesture gain
+    - iio: core: Fix entry not deleted when iio_register_sw_trigger_type() fails
+    - init/Kconfig: fix CC_HAS_ASM_GOTO_TIED_OUTPUT test with dash
+    - nios2: add FORCE for vmlinuz.gz
+    - iio: ms5611: Simplify IO callback parameters
+    - iio: pressure: ms5611: fixed value compensation bug
+    - ceph: do not update snapshot context when there is no new snapshot
+    - ceph: avoid putting the realm twice when decoding snaps fails
+    - firmware: google: Release devices before unregistering the bus
+    - firmware: coreboot: Register bus in module init
+    - nilfs2: fix nilfs_sufile_mark_dirty() not set segment usage as dirty
+    - gcov: clang: fix the buffer overflow issue
+    - Input: synaptics - switch touchpad on HP Laptop 15-da3001TU to RMI mode
+    - ASoC: Intel: bytcht_es8316: Add quirk for the Nanote UMPC-01
+    - serial: 8250: 8250_omap: Avoid RS485 RTS glitch on ->set_termios()
+    - xen/platform-pci: add missing free_irq() in error path
+    - platform/x86: asus-wmi: add missing pci_dev_put() in asus_wmi_set_xusb2pr()
+    - platform/x86: acer-wmi: Enable SW_TABLET_MODE on Switch V 10 (SW5-017)
+    - platform/x86: hp-wmi: Ignore Smart Experience App event
+    - [Config] updateconfigs for INET_TABLE_PERTURB_ORDER
+    - tcp: configurable source port perturb table size
+    - net: usb: qmi_wwan: add Telit 0x103a composition
+    - dm integrity: flush the journal on suspend
+    - binder: avoid potential data leakage when copying txn
+    - binder: read pre-translated fds from sender buffer
+    - binder: defer copies of pre-patched txn data
+    - binder: fix pointer cast warning
+    - binder: Address corner cases in deferred copy and fixup
+    - binder: Gracefully handle BINDER_TYPE_FDA objects with num_fds=0
+    - btrfs: free btrfs_path before copying root refs to userspace
+    - btrfs: free btrfs_path before copying fspath to userspace
+    - btrfs: free btrfs_path before copying subvol info to userspace
+    - btrfs: sysfs: normalize the error handling branch in btrfs_init_sysfs()
+    - drm/amd/dc/dce120: Fix audio register mapping, stop triggering KASAN
+    - drm/amdgpu: always register an MMU notifier for userptr
+    - fuse: lock inode unconditionally in fuse_fallocate()
+    - btrfs: free btrfs_path before copying inodes to userspace
+    - spi: spi-imx: Fix spi_bus_clk if requested clock is higher than input clock
+    - btrfs: move QUOTA_ENABLED check to rescan_should_stop from
+      btrfs_qgroup_rescan_worker
+    - drm/amdgpu: update drm_display_info correctly when the edid is read
+    - drm/amdgpu: Partially revert "drm/amdgpu: update drm_display_info correctly
+      when the edid is read"
+    - btrfs: qgroup: fix sleep from invalid context bug in btrfs_qgroup_inherit()
+    - iio: health: afe4403: Fix oob read in afe4403_read_raw
+    - iio: health: afe4404: Fix oob read in afe4404_[read|write]_raw
+    - iio: light: rpr0521: add missing Kconfig dependencies
+    - scripts/faddr2line: Fix regression in name resolution on ppc64le
+    - hwmon: (i5500_temp) fix missing pci_disable_device()
+    - hwmon: (ibmpex) Fix possible UAF when ibmpex_register_bmc() fails
+    - of: property: decrement node refcount in of_fwnode_get_reference_args()
+    - net/mlx5: Fix uninitialized variable bug in outlen_write()
+    - net/mlx5e: Fix use-after-free when reverting termination table
+    - can: sja1000_isa: sja1000_isa_probe(): add missing free_sja1000dev()
+    - can: cc770: cc770_isa_probe(): add missing free_cc770dev()
+    - qlcnic: fix sleep-in-atomic-context bugs caused by msleep
+    - wifi: cfg80211: fix buffer overflow in elem comparison
+    - net: phy: fix null-ptr-deref while probe() failed
+    - net: net_netdev: Fix error handling in ntb_netdev_init_module()
+    - net/9p: Fix a potential socket leak in p9_socket_open
+    - net: ethernet: nixge: fix NULL dereference
+    - dsa: lan9303: Correct stat name
+    - net: hsr: Fix potential use-after-free
+    - afs: Fix fileserver probe RTT handling
+    - net: tun: Fix use-after-free in tun_detach()
+    - packet: do not set TP_STATUS_CSUM_VALID on CHECKSUM_COMPLETE
+    - sctp: fix memory leak in sctp_stream_outq_migrate()
+    - net: ethernet: renesas: ravb: Fix promiscuous mode after system resumed
+    - hwmon: (coretemp) Check for null before removing sysfs attrs
+    - hwmon: (coretemp) fix pci device refcount leak in nv1a_ram_new()
+    - net/mlx5: DR, Fix uninitialized var warning
+    - error-injection: Add prompt for function error injection
+    - tools/vm/slabinfo-gnuplot: use "grep -E" instead of "egrep"
+    - nilfs2: fix NULL pointer dereference in nilfs_palloc_commit_free_entry()
+    - x86/bugs: Make sure MSR_SPEC_CTRL is updated properly upon resume from S3
+    - pinctrl: intel: Save and restore pins in "direct IRQ" mode
+    - mmc: mmc_test: Fix removal of debugfs file
+    - mmc: core: Fix ambiguous TRIM and DISCARD arg
+    - mmc: sdhci-esdhc-imx: correct CQHCI exit halt state check
+    - mmc: sdhci-sprd: Fix no reset data and command after voltage switch
+    - tracing: Free buffers when a used dynamic event is removed
+    - arm64: Fix panic() when Spectre-v2 causes Spectre-BHB to re-allocate KVM
+      vectors
+    - arm64: errata: Fix KVM Spectre-v2 mitigation selection for Cortex-A57/A72
+    - mm: Fix '.data.once' orphan section warning
+    - ASoC: ops: Fix bounds check for _sx controls
+    - pinctrl: single: Fix potential division by zero
+    - iommu/vt-d: Fix PCI device refcount leak in dmar_dev_scope_init()
+    - parisc: Increase size of gcc stack frame check
+    - xtensa: increase size of gcc stack frame check
+    - parisc: Increase FRAME_WARN to 2048 bytes on parisc
+    - Kconfig.debug: provide a little extra FRAME_WARN leeway when KASAN is
+      enabled
+    - selftests: net: add delete nexthop route warning test
+    - selftests: net: fix nexthop warning cleanup double ip typo
+    - ipv4: Handle attempt to delete multipath route when fib_info contains an nh
+      reference
+    - ipv4: Fix route deletion when nexthop info is not specified
+    - tracing/ring-buffer: Have polling block on watermark
+    - nvme: restrict management ioctls to admin
+    - nvme: ensure subsystem reset is single threaded
+    - x86/tsx: Add a feature bit for TSX control MSR support
+    - x86/pm: Add enumeration check before spec MSRs save/restore setup
+    - x86/ioremap: Fix page aligned size calculation in __ioremap_caller()
+    - Revert "clocksource/drivers/riscv: Events are stopped during CPU suspend"
+    - char: tpm: Protect tpm_pm_suspend with locks
+    - mmc: sdhci: use FIELD_GET for preset value bit masks
+    - mmc: sdhci: Fix voltage switch delay
+    - proc: avoid integer type confusion in get_proc_long
+    - proc: proc_skip_spaces() shouldn't think it is working on C strings
+    - v4l2: don't fall back to follow_pfn() if pin_user_pages_fast() fails
+    - ipc/sem: Fix dangling sem_array access in semtimedop race
+    - Linux 5.4.226
+  * CVE-2022-4139
+    - drm/i915: fix TLB invalidation for Gen12 video and compute engines
+  * Focal update: v5.4.225 upstream stable release (LP: #2002347)
+    - xfs: preserve rmapbt swapext block reservation from freed blocks
+    - xfs: rename xfs_bmap_is_real_extent to is_written_extent
+    - xfs: redesign the reflink remap loop to fix blkres depletion crash
+    - xfs: use MMAPLOCK around filemap_map_pages()
+    - xfs: preserve inode versioning across remounts
+    - xfs: drain the buf delwri queue before xfsaild idles
+    - phy: stm32: fix an error code in probe
+    - wifi: cfg80211: silence a sparse RCU warning
+    - wifi: cfg80211: fix memory leak in query_regdb_file()
+    - bpf, sockmap: Fix the sk->sk_forward_alloc warning of sk_stream_kill_queues
+    - HID: hyperv: fix possible memory leak in mousevsc_probe()
+    - net: gso: fix panic on frag_list with mixed head alloc types
+    - net: tun: Fix memory leaks of napi_get_frags
+    - bnxt_en: Fix possible crash in bnxt_hwrm_set_coal()
+    - bnxt_en: fix potentially incorrect return value for ndo_rx_flow_steer
+    - net: fman: Unregister ethernet device on removal
+    - capabilities: fix undefined behavior in bit shift for CAP_TO_MASK
+    - net: lapbether: fix issue of dev reference count leakage in
+      lapbeth_device_event()
+    - hamradio: fix issue of dev reference count leakage in bpq_device_event()
+    - drm/vc4: Fix missing platform_unregister_drivers() call in
+      vc4_drm_register()
+    - ipv6: addrlabel: fix infoleak when sending struct ifaddrlblmsg to network
+    - can: af_can: fix NULL pointer dereference in can_rx_register()
+    - tipc: fix the msg->req tlv len check in
+      tipc_nl_compat_name_table_dump_header
+    - dmaengine: pxa_dma: use platform_get_irq_optional
+    - dmaengine: mv_xor_v2: Fix a resource leak in mv_xor_v2_remove()
+    - drivers: net: xgene: disable napi when register irq failed in
+      xgene_enet_open()
+    - perf stat: Fix printing os->prefix in CSV metrics output
+    - net: nixge: disable napi when enable interrupts failed in nixge_open()
+    - net/mlx5: Allow async trigger completion execution on single CPU systems
+    - net: cpsw: disable napi in cpsw_ndo_open()
+    - net: cxgb3_main: disable napi when bind qsets failed in cxgb_up()
+    - cxgb4vf: shut down the adapter when t4vf_update_port_info() failed in
+      cxgb4vf_open()
+    - ethernet: s2io: disable napi when start nic failed in s2io_card_up()
+    - net: mv643xx_eth: disable napi when init rxq or txq failed in
+      mv643xx_eth_open()
+    - ethernet: tundra: free irq when alloc ring failed in tsi108_open()
+    - net: macvlan: fix memory leaks of macvlan_common_newlink
+    - riscv: process: fix kernel info leakage
+    - arm64: efi: Fix handling of misaligned runtime regions and drop warning
+    - MIPS: jump_label: Fix compat branch range check
+    - mmc: cqhci: Provide helper for resetting both SDHCI and CQHCI
+    - mmc: sdhci-of-arasan: Fix SDHCI_RESET_ALL for CQHCI
+    - mmc: sdhci-tegra: Fix SDHCI_RESET_ALL for CQHCI
+    - ALSA: hda/ca0132: add quirk for EVGA Z390 DARK
+    - ALSA: hda: fix potential memleak in 'add_widget_node'
+    - ALSA: usb-audio: Add quirk entry for M-Audio Micro
+    - ALSA: usb-audio: Add DSD support for Accuphase DAC-60
+    - vmlinux.lds.h: Fix placement of '.data..decrypted' section
+    - nilfs2: fix deadlock in nilfs_count_free_blocks()
+    - nilfs2: fix use-after-free bug of ns_writer on remount
+    - drm/i915/dmabuf: fix sg_table handling in map_dma_buf
+    - btrfs: selftests: fix wrong error check in btrfs_free_dummy_root()
+    - udf: Fix a slab-out-of-bounds write bug in udf_find_entry()
+    - can: j1939: j1939_send_one(): fix missing CAN header initialization
+    - cert host tools: Stop complaining about deprecated OpenSSL functions
+    - dmaengine: at_hdmac: Fix at_lli struct definition
+    - dmaengine: at_hdmac: Don't start transactions at tx_submit level
+    - dmaengine: at_hdmac: Fix completion of unissued descriptor in case of errors
+    - dmaengine: at_hdmac: Don't allow CPU to reorder channel enable
+    - dmaengine: at_hdmac: Fix impossible condition
+    - dmaengine: at_hdmac: Check return code of dma_async_device_register
+    - net: tun: call napi_schedule_prep() to ensure we own a napi
+    - x86/cpu: Restore AMD's DE_CFG MSR after resume
+    - ASoC: wm5102: Revert "ASoC: wm5102: Fix PM disable depth imbalance in
+      wm5102_probe"
+    - ASoC: wm5110: Revert "ASoC: wm5110: Fix PM disable depth imbalance in
+      wm5110_probe"
+    - ASoC: wm8997: Revert "ASoC: wm8997: Fix PM disable depth imbalance in
+      wm8997_probe"
+    - ASoC: wm8962: Add an event handler for TEMP_HP and TEMP_SPK
+    - spi: intel: Fix the offset to get the 64K erase opcode
+    - ASoC: codecs: jz4725b: add missed Line In power control bit
+    - ASoC: codecs: jz4725b: fix reported volume for Master ctl
+    - ASoC: codecs: jz4725b: use right control for Capture Volume
+    - ASoC: codecs: jz4725b: fix capture selector naming
+    - selftests/futex: fix build for clang
+    - selftests/intel_pstate: fix build for ARCH=x86_64
+    - NFSv4: Retry LOCK on OLD_STATEID during delegation return
+    - i2c: i801: add lis3lv02d's I2C address for Vostro 5568
+    - drm/imx: imx-tve: Fix return type of imx_tve_connector_mode_valid
+    - btrfs: remove pointless and double ulist frees in error paths of qgroup
+      tests
+    - ASoC: codecs: jz4725b: Fix spelling mistake "Sourc" -> "Source", "Routee" ->
+      "Route"
+    - spi: stm32: Print summary 'callbacks suppressed' message
+    - ASoC: core: Fix use-after-free in snd_soc_exit()
+    - serial: 8250_omap: remove wait loop from Errata i202 workaround
+    - serial: 8250: omap: Fix unpaired pm_runtime_put_sync() in omap8250_remove()
+    - serial: 8250: omap: Flush PM QOS work on remove
+    - serial: imx: Add missing .thaw_noirq hook
+    - tty: n_gsm: fix sleep-in-atomic-context bug in gsm_control_send
+    - ASoC: soc-utils: Remove __exit for snd_soc_util_exit()
+    - block: sed-opal: kmalloc the cmd/resp buffers
+    - siox: fix possible memory leak in siox_device_add()
+    - parport_pc: Avoid FIFO port location truncation
+    - pinctrl: devicetree: fix null pointer dereferencing in pinctrl_dt_to_map
+    - arm64: dts: imx8mm: Fix NAND controller size-cells
+    - arm64: dts: imx8mn: Fix NAND controller size-cells
+    - ata: libata-transport: fix double ata_host_put() in ata_tport_add()
+    - net: bgmac: Drop free_netdev() from bgmac_enet_remove()
+    - mISDN: fix possible memory leak in mISDN_dsp_element_register()
+    - net: liquidio: release resources when liquidio driver open failed
+    - mISDN: fix misuse of put_device() in mISDN_register_device()
+    - net: macvlan: Use built-in RCU list checking
+    - net: caif: fix double disconnect client in chnl_net_open()
+    - bnxt_en: Remove debugfs when pci_register_driver failed
+    - xen/pcpu: fix possible memory leak in register_pcpu()
+    - drbd: use after free in drbd_create_device()
+    - platform/x86/intel: pmc: Don't unconditionally attach Intel PMC when
+      virtualized
+    - net/x25: Fix skb leak in x25_lapb_receive_frame()
+    - cifs: Fix wrong return value checking when GETFLAGS
+    - net: thunderbolt: Fix error handling in tbnet_init()
+    - cifs: add check for returning value of SMB2_set_info_init
+    - ftrace: Fix the possible incorrect kernel message
+    - ftrace: Optimize the allocation for mcount entries
+    - ftrace: Fix null pointer dereference in ftrace_add_mod()
+    - ring_buffer: Do not deactivate non-existant pages
+    - ALSA: usb-audio: Drop snd_BUG_ON() from snd_usbmidi_output_open()
+    - Revert "usb: dwc3: disable USB core PHY management"
+    - slimbus: stream: correct presence rate frequencies
+    - speakup: fix a segfault caused by switching consoles
+    - USB: serial: option: add Sierra Wireless EM9191
+    - USB: serial: option: remove old LARA-R6 PID
+    - USB: serial: option: add u-blox LARA-R6 00B modem
+    - USB: serial: option: add u-blox LARA-L6 modem
+    - USB: serial: option: add Fibocom FM160 0x0111 composition
+    - usb: add NO_LPM quirk for Realforce 87U Keyboard
+    - usb: chipidea: fix deadlock in ci_otg_del_timer
+    - iio: adc: at91_adc: fix possible memory leak in at91_adc_allocate_trigger()
+    - iio: trigger: sysfs: fix possible memory leak in iio_sysfs_trig_init()
+    - iio: pressure: ms5611: changed hardcoded SPI speed to value limited
+    - dm ioctl: fix misbehavior if list_versions races with module loading
+    - serial: 8250: Fall back to non-DMA Rx if IIR_RDI occurs
+    - serial: 8250_lpss: Configure DMA also w/o DMA filter
+    - Input: iforce - invert valid length check when fetching device IDs
+    - scsi: zfcp: Fix double free of FSF request when qdio send fails
+    - mmc: core: properly select voltage range without power cycle
+    - mmc: sdhci-pci-o2micro: fix card detect fail issue caused by CD# debounce
+      timeout
+    - mmc: sdhci-pci: Fix possible memory leak caused by missing pci_dev_put()
+    - docs: update mediator contact information in CoC doc
+    - misc/vmw_vmci: fix an infoleak in vmci_host_do_receive_datagram()
+    - serial: 8250: Flush DMA Rx on RLSI
+    - ring-buffer: Include dropped pages in counting dirty patches
+    - scsi: target: tcm_loop: Fix possible name leak in tcm_loop_setup_hba_bus()
+    - kprobes: Skip clearing aggrprobe's post_handler in kprobe-on-ftrace case
+    - Input: i8042 - fix leaking of platform device on module removal
+    - macvlan: enforce a consistent minimal mtu
+    - tcp: cdg: allow tcp_cdg_release() to be called multiple times
+    - kcm: avoid potential race in kcm_tx_work
+    - bpf, test_run: Fix alignment problem in bpf_prog_test_run_skb()
+    - kcm: close race conditions on sk_receive_queue
+    - 9p: trans_fd/p9_conn_cancel: drop client lock earlier
+    - gfs2: Check sb_bsize_shift after reading superblock
+    - gfs2: Switch from strlcpy to strscpy
+    - 9p/trans_fd: always use O_NONBLOCK read/write
+    - mm: fs: initialize fsdata passed to write_begin/write_end interface
+    - ntfs: fix use-after-free in ntfs_attr_find()
+    - ntfs: fix out-of-bounds read in ntfs_attr_find()
+    - ntfs: check overflow when iterating ATTR_RECORDs
+    - Linux 5.4.225
+  * CVE-2022-47520
+    - wifi: wilc1000: validate pairwise and authentication suite offsets
+  * CVE-2022-3545
+    - nfp: fix use-after-free in area_cache_get()
+
+  [ Ubuntu: 5.4.0-139.156 ]
+
+  * focal/linux: 5.4.0-139.156 -proposed tracker (LP: #2003486)
+  * Revoke & rotate to new signing key (LP: #2002812)
+    - [Packaging] Revoke and rotate to new signing key
+
+ -- Masahiro Yamada <masahiro.yamada@canonical.com>  Wed, 15 Feb 2023 19:38:53 +0900
+
+linux-xilinx-zynqmp (5.4.0-1021.25) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1021.25 -proposed tracker (LP: #2003295)
+
+  * Focal update: v5.4.221 upstream stable release (LP: #1997993)
+    - [Config] updateconfigs for ARM64_ERRATUM_1742098
+
+  [ Ubuntu: 5.4.0-138.155 ]
+
+  * focal/linux: 5.4.0-138.155 -proposed tracker (LP: #2001845)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update helper scripts
+  * Focal update: v5.4.224 upstream stable release (LP: #1999273)
+    - RDMA/cma: Use output interface for net_dev check
+    - IB/hfi1: Correctly move list in sc_disable()
+    - NFSv4.1: Handle RECLAIM_COMPLETE trunking errors
+    - NFSv4.1: We must always send RECLAIM_COMPLETE after a reboot
+    - nfs4: Fix kmemleak when allocate slot failed
+    - net: dsa: Fix possible memory leaks in dsa_loop_init()
+    - RDMA/core: Fix null-ptr-deref in ib_core_cleanup()
+    - RDMA/qedr: clean up work queue on failure in qedr_alloc_resources()
+    - nfc: s3fwrn5: Fix potential memory leak in s3fwrn5_nci_send()
+    - nfc: nfcmrvl: Fix potential memory leak in nfcmrvl_i2c_nci_send()
+    - net: fec: fix improper use of NETDEV_TX_BUSY
+    - ata: pata_legacy: fix pdc20230_set_piomode()
+    - net: sched: Fix use after free in red_enqueue()
+    - net: tun: fix bugs for oversize packet when napi frags enabled
+    - netfilter: nf_tables: release flow rule object from commit path
+    - ipvs: use explicitly signed chars
+    - ipvs: fix WARNING in __ip_vs_cleanup_batch()
+    - ipvs: fix WARNING in ip_vs_app_net_cleanup()
+    - rose: Fix NULL pointer dereference in rose_send_frame()
+    - mISDN: fix possible memory leak in mISDN_register_device()
+    - isdn: mISDN: netjet: fix wrong check of device registration
+    - btrfs: fix inode list leak during backref walking at resolve_indirect_refs()
+    - btrfs: fix inode list leak during backref walking at find_parent_nodes()
+    - btrfs: fix ulist leaks in error paths of qgroup self tests
+    - Bluetooth: L2CAP: fix use-after-free in l2cap_conn_del()
+    - net: mdio: fix undefined behavior in bit shift for __mdiobus_register
+    - net, neigh: Fix null-ptr-deref in neigh_table_clear()
+    - ipv6: fix WARNING in ip6_route_net_exit_late()
+    - media: s5p_cec: limit msg.len to CEC_MAX_MSG_SIZE
+    - media: cros-ec-cec: limit msg.len to CEC_MAX_MSG_SIZE
+    - media: dvb-frontends/drxk: initialize err to 0
+    - media: meson: vdec: fix possible refcount leak in vdec_probe()
+    - scsi: core: Restrict legal sdev_state transitions via sysfs
+    - HID: saitek: add madcatz variant of MMO7 mouse device ID
+    - i2c: xiic: Add platform module alias
+    - xfs: don't fail verifier on empty attr3 leaf block
+    - xfs: use ordered buffers to initialize dquot buffers during quotacheck
+    - xfs: gut error handling in xfs_trans_unreserve_and_mod_sb()
+    - xfs: group quota should return EDQUOT when prj quota enabled
+    - xfs: don't fail unwritten extent conversion on writeback due to edquot
+    - xfs: Add the missed xfs_perag_put() for xfs_ifree_cluster()
+    - Bluetooth: L2CAP: Fix attempting to access uninitialized memory
+    - block, bfq: protect 'bfqd->queued' by 'bfqd->lock'
+    - binder: fix UAF of alloc->vma in race with munmap()
+    - btrfs: fix type of parameter generation in btrfs_get_dentry
+    - tcp/udp: Make early_demux back namespacified.
+    - kprobe: reverse kp->flags when arm_kprobe failed
+    - tools/nolibc/string: Fix memcmp() implementation
+    - tracing/histogram: Update document for KEYS_MAX size
+    - capabilities: fix potential memleak on error path from vfs_getxattr_alloc()
+    - fuse: add file_modified() to fallocate
+    - efi: random: reduce seed size to 32 bytes
+    - perf/x86/intel: Fix pebs event constraints for ICL
+    - perf/x86/intel: Add Cooper Lake stepping to isolation_ucodes[]
+    - ALSA: usb-audio: Add quirks for MacroSilicon MS2100/MS2106 devices
+    - parisc: Make 8250_gsc driver dependend on CONFIG_PARISC
+    - parisc: Export iosapic_serial_irq() symbol for serial port driver
+    - parisc: Avoid printing the hardware path twice
+    - ext4: fix warning in 'ext4_da_release_space'
+    - ext4: fix BUG_ON() when directory entry has invalid rec_len
+    - KVM: x86: Mask off reserved bits in CPUID.8000001AH
+    - KVM: x86: Mask off reserved bits in CPUID.80000008H
+    - KVM: x86: emulator: em_sysexit should update ctxt->mode
+    - KVM: x86: emulator: introduce emulator_recalc_and_set_mode
+    - KVM: x86: emulator: update the emulation mode after CR0 write
+    - mtd: rawnand: gpmi: Set WAIT_FOR_READY timeout based on program/erase times
+    - drm/rockchip: dsi: Force synchronous probe
+    - drm/i915/sdvo: Filter out invalid outputs more sensibly
+    - drm/i915/sdvo: Setup DDC fully before output init
+    - wifi: brcmfmac: Fix potential buffer overflow in brcmf_fweh_event_worker()
+    - ipc: remove memcg accounting for sops objects in do_semtimedop()
+    - Linux 5.4.224
+  * Focal update: v5.4.223 upstream stable release (LP: #1999179)
+    - can: j1939: transport: j1939_session_skb_drop_old():
+      spin_unlock_irqrestore() before kfree_skb()
+    - can: kvaser_usb: Fix possible completions during init_completion
+    - ALSA: Use del_timer_sync() before freeing timer
+    - ALSA: au88x0: use explicitly signed char
+    - USB: add RESET_RESUME quirk for NVIDIA Jetson devices in RCM
+    - usb: dwc3: gadget: Stop processing more requests on IMI
+    - usb: dwc3: gadget: Don't set IMI for no_interrupt
+    - usb: bdc: change state when port disconnected
+    - usb: xhci: add XHCI_SPURIOUS_SUCCESS to ASM1042 despite being a V0.96
+      controller
+    - mtd: rawnand: marvell: Use correct logic for nand-keep-config
+    - xhci: Remove device endpoints from bandwidth list when freeing the device
+    - tools: iio: iio_utils: fix digit calculation
+    - iio: light: tsl2583: Fix module unloading
+    - fbdev: smscufx: Fix several use-after-free bugs
+    - mac802154: Fix LQI recording
+    - drm/msm/dsi: fix memory corruption with too many bridges
+    - drm/msm/hdmi: fix memory corruption with too many bridges
+    - mmc: core: Fix kernel panic when remove non-standard SDIO card
+    - kernfs: fix use-after-free in __kernfs_remove
+    - perf auxtrace: Fix address filter symbol name match for modules
+    - s390/futex: add missing EX_TABLE entry to __futex_atomic_op()
+    - s390/pci: add missing EX_TABLE entries to
+      __pcistg_mio_inuser()/__pcilg_mio_inuser()
+    - xfs: finish dfops on every insert range shift iteration
+    - xfs: clear XFS_DQ_FREEING if we can't lock the dquot buffer to flush
+    - xfs: force the log after remapping a synchronous-writes file
+    - Xen/gntdev: don't ignore kernel unmapping error
+    - xen/gntdev: Prevent leaking grants
+    - mm,hugetlb: take hugetlb_lock before decrementing h->resv_huge_pages
+    - net: ieee802154: fix error return code in dgram_bind()
+    - media: v4l2: Fix v4l2_i2c_subdev_set_name function documentation
+    - drm/msm: Fix return type of mdp4_lvds_connector_mode_valid
+    - arc: iounmap() arg is volatile
+    - ALSA: ac97: fix possible memory leak in snd_ac97_dev_register()
+    - tipc: fix a null-ptr-deref in tipc_topsrv_accept
+    - net: netsec: fix error handling in netsec_register_mdio()
+    - x86/unwind/orc: Fix unreliable stack dump with gcov
+    - amd-xgbe: fix the SFP compliance codes check for DAC cables
+    - amd-xgbe: add the bit rate quirk for Molex cables
+    - kcm: annotate data-races around kcm->rx_psock
+    - kcm: annotate data-races around kcm->rx_wait
+    - net: fix UAF issue in nfqnl_nf_hook_drop() when ops_init() failed
+    - net: lantiq_etop: don't free skb when returning NETDEV_TX_BUSY
+    - tcp: fix indefinite deferral of RTO with SACK reneging
+    - can: mscan: mpc5xxx: mpc5xxx_can_probe(): add missing put_clock() in error
+      path
+    - PM: hibernate: Allow hybrid sleep to work with s2idle
+    - media: vivid: s_fbuf: add more sanity checks
+    - media: vivid: dev->bitmap_cap wasn't freed in all cases
+    - media: v4l2-dv-timings: add sanity checks for blanking values
+    - media: videodev2.h: V4L2_DV_BT_BLANKING_HEIGHT should check 'interlaced'
+    - i40e: Fix ethtool rx-flow-hash setting for X722
+    - i40e: Fix VF hang when reset is triggered on another VF
+    - i40e: Fix flow-type by setting GL_HASH_INSET registers
+    - net: ksz884x: fix missing pci_disable_device() on error in pcidev_init()
+    - PM: domains: Fix handling of unavailable/disabled idle states
+    - ALSA: aoa: i2sbus: fix possible memory leak in i2sbus_add_dev()
+    - ALSA: aoa: Fix I2S device accounting
+    - openvswitch: switch from WARN to pr_warn
+    - net: ehea: fix possible memory leak in ehea_register_port()
+    - nh: fix scope used to find saddr when adding non gw nh
+    - net/mlx5e: Do not increment ESN when updating IPsec ESN state
+    - net/mlx5: Fix possible use-after-free in async command interface
+    - net: enetc: survive memory pressure without crashing
+    - can: rcar_canfd: rcar_canfd_handle_global_receive(): fix IRQ storm on global
+      FIFO receive
+    - Linux 5.4.223
+  * Focal update: v5.4.222 upstream stable release (LP: #1997994)
+    - once: fix section mismatch on clang builds
+    - Linux 5.4.222
+  * Focal update: v5.4.221 upstream stable release (LP: #1997993)
+    - xfs: open code insert range extent split helper
+    - xfs: rework insert range into an atomic operation
+    - xfs: rework collapse range into an atomic operation
+    - xfs: add a function to deal with corrupt buffers post-verifiers
+    - xfs: xfs_buf_corruption_error should take __this_address
+    - xfs: fix buffer corruption reporting when xfs_dir3_free_header_check fails
+    - xfs: check owner of dir3 data blocks
+    - xfs: check owner of dir3 blocks
+    - xfs: Use scnprintf() for avoiding potential buffer overflow
+    - xfs: remove the xfs_disk_dquot_t and xfs_dquot_t
+    - xfs: remove the xfs_dq_logitem_t typedef
+    - xfs: remove the xfs_qoff_logitem_t typedef
+    - xfs: Replace function declaration by actual definition
+    - xfs: factor out quotaoff intent AIL removal and memory free
+    - xfs: fix unmount hang and memory leak on shutdown during quotaoff
+    - xfs: preserve default grace interval during quotacheck
+    - xfs: Lower CIL flush limit for large logs
+    - xfs: Throttle commits on delayed background CIL push
+    - xfs: factor common AIL item deletion code
+    - xfs: tail updates only need to occur when LSN changes
+    - xfs: don't write a corrupt unmount record to force summary counter recalc
+    - xfs: trylock underlying buffer on dquot flush
+    - xfs: factor out a new xfs_log_force_inode helper
+    - xfs: reflink should force the log out if mounted with wsync
+    - xfs: move inode flush to the sync workqueue
+    - xfs: fix use-after-free on CIL context on shutdown
+    - ocfs2: clear dinode links count in case of error
+    - ocfs2: fix BUG when iput after ocfs2_mknod fails
+    - x86/microcode/AMD: Apply the patch early on every logical thread
+    - hwmon/coretemp: Handle large core ID value
+    - ata: ahci-imx: Fix MODULE_ALIAS
+    - ata: ahci: Match EM_MAX_SLOTS with SATA_PMP_MAX_PORTS
+    - KVM: arm64: vgic: Fix exit condition in scan_its_table()
+    - media: venus: dec: Handle the case where find_format fails
+    - [Config] updateconfigs for ARM64_ERRATUM_1742098
+    - arm64: errata: Remove AES hwcap for COMPAT tasks
+    - r8152: add PID for the Lenovo OneLink+ Dock
+    - btrfs: fix processing of delayed data refs during backref walking
+    - btrfs: fix processing of delayed tree block refs during backref walking
+    - ACPI: extlog: Handle multiple records
+    - tipc: Fix recognition of trial period
+    - tipc: fix an information leak in tipc_topsrv_kern_subscr
+    - HID: magicmouse: Do not set BTN_MOUSE on double report
+    - net/atm: fix proc_mpc_write incorrect return value
+    - net: phy: dp83867: Extend RX strap quirk for SGMII mode
+    - net: sched: cake: fix null pointer access issue when cake_init() fails
+    - net: hns: fix possible memory leak in hnae_ae_register()
+    - iommu/vt-d: Clean up si_domain in the init_dmars() error path
+    - arm64: topology: move store_cpu_topology() to shared code
+    - riscv: topology: fix default topology reporting
+    - ACPI: video: Force backlight native for more TongFang devices
+    - Makefile.debug: re-enable debug info for .S files
+    - hv_netvsc: Fix race between VF offering and VF association message from host
+    - mm: /proc/pid/smaps_rollup: fix no vma's null-deref
+    - Linux 5.4.221
+  * Focal update: v5.4.220 upstream stable release (LP: #1996812)
+    - ALSA: oss: Fix potential deadlock at unregistration
+    - ALSA: rawmidi: Drop register_mutex in snd_rawmidi_free()
+    - ALSA: usb-audio: Fix potential memory leaks
+    - ALSA: usb-audio: Fix NULL dererence at error path
+    - ALSA: hda/realtek: remove ALC289_FIXUP_DUAL_SPK for Dell 5530
+    - ALSA: hda/realtek: Correct pin configs for ASUS G533Z
+    - ALSA: hda/realtek: Add quirk for ASUS GV601R laptop
+    - ALSA: hda/realtek: Add Intel Reference SSID to support headset keys
+    - mtd: rawnand: atmel: Unmap streaming DMA mappings
+    - cifs: destage dirty pages before re-reading them for cache=none
+    - cifs: Fix the error length of VALIDATE_NEGOTIATE_INFO message
+    - iio: dac: ad5593r: Fix i2c read protocol requirements
+    - iio: pressure: dps310: Refactor startup procedure
+    - iio: pressure: dps310: Reset chip after timeout
+    - usb: add quirks for Lenovo OneLink+ Dock
+    - can: kvaser_usb: Fix use of uninitialized completion
+    - can: kvaser_usb_leaf: Fix overread with an invalid command
+    - can: kvaser_usb_leaf: Fix TX queue out of sync after restart
+    - can: kvaser_usb_leaf: Fix CAN state after restart
+    - mmc: sdhci-sprd: Fix minimum clock limit
+    - fs: dlm: fix race between test_bit() and queue_work()
+    - fs: dlm: handle -EBUSY first in lock arg validation
+    - HID: multitouch: Add memory barriers
+    - quota: Check next/prev free block number after reading from quota file
+    - ASoC: wcd9335: fix order of Slimbus unprepare/disable
+    - regulator: qcom_rpm: Fix circular deferral regression
+    - RISC-V: Make port I/O string accessors actually work
+    - parisc: fbdev/stifb: Align graphics memory size to 4MB
+    - riscv: Allow PROT_WRITE-only mmap()
+    - riscv: Pass -mno-relax only on lld < 15.0.0
+    - UM: cpuinfo: Fix a warning for CONFIG_CPUMASK_OFFSTACK
+    - PCI: Sanitise firmware BAR assignments behind a PCI-PCI bridge
+    - powerpc/boot: Explicitly disable usage of SPE instructions
+    - fbdev: smscufx: Fix use-after-free in ufx_ops_open()
+    - btrfs: fix race between quota enable and quota rescan ioctl
+    - f2fs: increase the limit for reserve_root
+    - f2fs: fix to do sanity check on destination blkaddr during recovery
+    - f2fs: fix to do sanity check on summary info
+    - nilfs2: fix use-after-free bug of struct nilfs_root
+    - jbd2: wake up journal waiters in FIFO order, not LIFO
+    - ext4: avoid crash when inline data creation follows DIO write
+    - ext4: fix null-ptr-deref in ext4_write_info
+    - ext4: make ext4_lazyinit_thread freezable
+    - ext4: place buffer head allocation before handle start
+    - livepatch: fix race between fork and KLP transition
+    - ftrace: Properly unset FTRACE_HASH_FL_MOD
+    - ring-buffer: Allow splice to read previous partially read pages
+    - ring-buffer: Have the shortest_full queue be the shortest not longest
+    - ring-buffer: Check pending waiters when doing wake ups as well
+    - ring-buffer: Fix race between reset page and reading page
+    - media: cedrus: Set the platform driver data earlier
+    - KVM: x86/emulator: Fix handing of POP SS to correctly set interruptibility
+    - KVM: nVMX: Unconditionally purge queued/injected events on nested "exit"
+    - KVM: VMX: Drop bits 31:16 when shoving exception error code into VMCS
+    - gcov: support GCC 12.1 and newer compilers
+    - drm/nouveau: fix a use-after-free in nouveau_gem_prime_import_sg_table()
+    - selinux: use "grep -E" instead of "egrep"
+    - tracing: Disable interrupt or preemption before acquiring arch_spinlock_t
+    - userfaultfd: open userfaultfds with O_RDONLY
+    - sh: machvec: Use char[] for section boundaries
+    - ARM: 9247/1: mm: set readonly for MT_MEMORY_RO with ARM_LPAE
+    - nfsd: Fix a memory leak in an error handling path
+    - wifi: ath10k: add peer map clean up for peer delete in ath10k_sta_state()
+    - wifi: mac80211: allow bw change during channel switch in mesh
+    - bpftool: Fix a wrong type cast in btf_dumper_int
+    - x86/resctrl: Fix to restore to original value when re-enabling hardware
+      prefetch register
+    - wifi: rtl8xxxu: tighten bounds checking in rtl8xxxu_read_efuse()
+    - spi: qup: add missing clk_disable_unprepare on error in spi_qup_resume()
+    - spi: qup: add missing clk_disable_unprepare on error in
+      spi_qup_pm_resume_runtime()
+    - wifi: rtl8xxxu: Fix skb misuse in TX queue selection
+    - bpf: btf: fix truncated last_member_type_id in btf_struct_resolve
+    - wifi: rtl8xxxu: gen2: Fix mistake in path B IQ calibration
+    - net: fs_enet: Fix wrong check in do_pd_setup
+    - bpf: Ensure correct locking around vulnerable function find_vpid()
+    - x86/microcode/AMD: Track patch allocation size explicitly
+    - spi/omap100k:Fix PM disable depth imbalance in omap1_spi100k_probe
+    - netfilter: nft_fib: Fix for rpath check with VRF devices
+    - spi: s3c64xx: Fix large transfers with DMA
+    - vhost/vsock: Use kvmalloc/kvfree for larger packets.
+    - sctp: handle the error returned from sctp_auth_asoc_init_active_key
+    - tcp: fix tcp_cwnd_validate() to not forget is_cwnd_limited
+    - net: rds: don't hold sock lock when cancelling work from
+      rds_tcp_reset_callbacks()
+    - bnx2x: fix potential memory leak in bnx2x_tpa_stop()
+    - net/ieee802154: reject zero-sized raw_sendmsg()
+    - once: add DO_ONCE_SLOW() for sleepable contexts
+    - net: mvpp2: fix mvpp2 debugfs leak
+    - drm: bridge: adv7511: fix CEC power down control register offset
+    - drm/mipi-dsi: Detach devices when removing the host
+    - platform/chrome: fix double-free in chromeos_laptop_prepare()
+    - platform/chrome: fix memory corruption in ioctl
+    - platform/x86: msi-laptop: Fix old-ec check for backlight registering
+    - platform/x86: msi-laptop: Fix resource cleanup
+    - drm: fix drm_mipi_dbi build errors
+    - drm/bridge: megachips: Fix a null pointer dereference bug
+    - ASoC: rsnd: Add check for rsnd_mod_power_on
+    - ALSA: hda: beep: Simplify keep-power-at-enable behavior
+    - drm/omap: dss: Fix refcount leak bugs
+    - mmc: au1xmmc: Fix an error handling path in au1xmmc_probe()
+    - ASoC: eureka-tlv320: Hold reference returned from of_find_xxx API
+    - drm/msm/dpu: index dpu_kms->hw_vbif using vbif_idx
+    - ALSA: dmaengine: increment buffer pointer atomically
+    - mmc: wmt-sdmmc: Fix an error handling path in wmt_mci_probe()
+    - ASoC: wm8997: Fix PM disable depth imbalance in wm8997_probe
+    - ASoC: wm5110: Fix PM disable depth imbalance in wm5110_probe
+    - ASoC: wm5102: Fix PM disable depth imbalance in wm5102_probe
+    - ALSA: hda/hdmi: Don't skip notification handling during PM operation
+    - memory: pl353-smc: Fix refcount leak bug in pl353_smc_probe()
+    - memory: of: Fix refcount leak bug in of_get_ddr_timings()
+    - soc: qcom: smsm: Fix refcount leak bugs in qcom_smsm_probe()
+    - soc: qcom: smem_state: Add refcounting for the 'state->of_node'
+    - ARM: dts: turris-omnia: Fix mpp26 pin name and comment
+    - ARM: dts: kirkwood: lsxl: fix serial line
+    - ARM: dts: kirkwood: lsxl: remove first ethernet port
+    - ARM: dts: exynos: correct s5k6a3 reset polarity on Midas family
+    - ARM: Drop CMDLINE_* dependency on ATAGS
+    - ARM: dts: exynos: fix polarity of VBUS GPIO of Origen
+    - iio: adc: at91-sama5d2_adc: fix AT91_SAMA5D2_MR_TRACKTIM_MAX
+    - iio: adc: at91-sama5d2_adc: check return status for pressure and touch
+    - iio: adc: at91-sama5d2_adc: lock around oversampling and sample freq
+    - iio: inkern: only release the device node when done with it
+    - iio: ABI: Fix wrong format of differential capacitance channel ABI.
+    - clk: meson: Hold reference returned by of_get_parent()
+    - clk: oxnas: Hold reference returned by of_get_parent()
+    - clk: berlin: Add of_node_put() for of_get_parent()
+    - clk: tegra: Fix refcount leak in tegra210_clock_init
+    - clk: tegra: Fix refcount leak in tegra114_clock_init
+    - clk: tegra20: Fix refcount leak in tegra20_clock_init
+    - HSI: omap_ssi: Fix refcount leak in ssi_probe
+    - HSI: omap_ssi_port: Fix dma_map_sg error check
+    - media: exynos4-is: fimc-is: Add of_node_put() when breaking out of loop
+    - tty: xilinx_uartps: Fix the ignore_status
+    - media: xilinx: vipp: Fix refcount leak in xvip_graph_dma_init
+    - RDMA/rxe: Fix "kernel NULL pointer dereference" error
+    - RDMA/rxe: Fix the error caused by qp->sk
+    - misc: ocxl: fix possible refcount leak in afu_ioctl()
+    - dyndbg: fix module.dyndbg handling
+    - dyndbg: let query-modname override actual module name
+    - mtd: devices: docg3: check the return value of devm_ioremap() in the probe
+    - RDMA/siw: Always consume all skbuf data in sk_data_ready() upcall.
+    - ata: fix ata_id_sense_reporting_enabled() and ata_id_has_sense_reporting()
+    - ata: fix ata_id_has_devslp()
+    - ata: fix ata_id_has_ncq_autosense()
+    - ata: fix ata_id_has_dipm()
+    - mtd: rawnand: meson: fix bit map use in meson_nfc_ecc_correct()
+    - md/raid5: Ensure stripe_fill happens on non-read IO with journal
+    - xhci: Don't show warning for reinit on known broken suspend
+    - usb: gadget: function: fix dangling pnp_string in f_printer.c
+    - drivers: serial: jsm: fix some leaks in probe
+    - tty: serial: fsl_lpuart: disable dma rx/tx use flags in lpuart_dma_shutdown
+    - phy: qualcomm: call clk_disable_unprepare in the error handling
+    - staging: vt6655: fix some erroneous memory clean-up loops
+    - firmware: google: Test spinlock on panic path to avoid lockups
+    - serial: 8250: Fix restoring termios speed after suspend
+    - scsi: libsas: Fix use-after-free bug in smp_execute_task_sg()
+    - fsi: core: Check error number after calling ida_simple_get
+    - mfd: intel_soc_pmic: Fix an error handling path in
+      intel_soc_pmic_i2c_probe()
+    - mfd: fsl-imx25: Fix an error handling path in mx25_tsadc_setup_irq()
+    - mfd: lp8788: Fix an error handling path in lp8788_probe()
+    - mfd: lp8788: Fix an error handling path in lp8788_irq_init() and
+      lp8788_irq_init()
+    - mfd: fsl-imx25: Fix check for platform_get_irq() errors
+    - mfd: sm501: Add check for platform_driver_register()
+    - clk: mediatek: mt8183: mfgcfg: Propagate rate changes to parent
+    - dmaengine: ioat: stop mod_timer from resurrecting deleted timer in
+      __cleanup()
+    - spmi: pmic-arb: correct duplicate APID to PPID mapping logic
+    - clk: bcm2835: fix bcm2835_clock_rate_from_divisor declaration
+    - clk: ti: dra7-atl: Fix reference leak in of_dra7_atl_clk_probe
+    - clk: ast2600: BCLK comes from EPLL
+    - mailbox: bcm-ferxrm-mailbox: Fix error check for dma_map_sg
+    - powerpc/math_emu/efp: Include module.h
+    - powerpc/sysdev/fsl_msi: Add missing of_node_put()
+    - powerpc/pci_dn: Add missing of_node_put()
+    - powerpc/powernv: add missing of_node_put() in opal_export_attrs()
+    - x86/hyperv: Fix 'struct hv_enlightened_vmcs' definition
+    - powerpc/64s: Fix GENERIC_CPU build flags for PPC970 / G5
+    - powerpc: Fix SPE Power ISA properties for e500v1 platforms
+    - cgroup/cpuset: Enable update_tasks_cpumask() on top_cpuset
+    - iommu/omap: Fix buffer overflow in debugfs
+    - crypto: akcipher - default implementation for setting a private key
+    - crypto: ccp - Release dma channels before dmaengine unrgister
+    - iommu/iova: Fix module config properly
+    - kbuild: remove the target in signal traps when interrupted
+    - crypto: cavium - prevent integer overflow loading firmware
+    - f2fs: fix race condition on setting FI_NO_EXTENT flag
+    - ACPI: video: Add Toshiba Satellite/Portege Z830 quirk
+    - MIPS: BCM47XX: Cast memcmp() of function to (void *)
+    - powercap: intel_rapl: fix UBSAN shift-out-of-bounds issue
+    - thermal: intel_powerclamp: Use get_cpu() instead of smp_processor_id() to
+      avoid crash
+    - NFSD: Return nfserr_serverfault if splice_ok but buf->pages have data
+    - wifi: brcmfmac: fix invalid address access when enabling SCAN log level
+    - bpftool: Clear errno after libcap's checks
+    - openvswitch: Fix double reporting of drops in dropwatch
+    - openvswitch: Fix overreporting of drops in dropwatch
+    - tcp: annotate data-race around tcp_md5sig_pool_populated
+    - wifi: ath9k: avoid uninit memory read in ath9k_htc_rx_msg()
+    - xfrm: Update ipcomp_scratches with NULL when freed
+    - wifi: brcmfmac: fix use-after-free bug in brcmf_netdev_start_xmit()
+    - Bluetooth: L2CAP: initialize delayed works at l2cap_chan_create()
+    - Bluetooth: hci_sysfs: Fix attempting to call device_add multiple times
+    - can: bcm: check the result of can_send() in bcm_can_tx()
+    - wifi: rt2x00: don't run Rt5592 IQ calibration on MT7620
+    - wifi: rt2x00: set correct TX_SW_CFG1 MAC register for MT7620
+    - wifi: rt2x00: set VGC gain for both chains of MT7620
+    - wifi: rt2x00: set SoC wmac clock register
+    - wifi: rt2x00: correctly set BBP register 86 for MT7620
+    - net: If sock is dead don't access sock's sk_wq in sk_stream_wait_memory
+    - Bluetooth: L2CAP: Fix user-after-free
+    - drm/nouveau/nouveau_bo: fix potential memory leak in nouveau_bo_alloc()
+    - drm: Use size_t type for len variable in drm_copy_field()
+    - drm: Prevent drm_copy_field() to attempt copying a NULL pointer
+    - drm/amd/display: fix overflow on MIN_I64 definition
+    - drm/vc4: vec: Fix timings for VEC modes
+    - drm: panel-orientation-quirks: Add quirk for Anbernic Win600
+    - platform/x86: msi-laptop: Change DMI match / alias strings to fix module
+      autoloading
+    - drm/amdgpu: fix initial connector audio value
+    - mmc: sdhci-msm: add compatible string check for sdm670
+    - ARM: dts: imx7d-sdb: config the max pressure for tsc2046
+    - ARM: dts: imx6q: add missing properties for sram
+    - ARM: dts: imx6dl: add missing properties for sram
+    - ARM: dts: imx6qp: add missing properties for sram
+    - ARM: dts: imx6sl: add missing properties for sram
+    - ARM: dts: imx6sll: add missing properties for sram
+    - ARM: dts: imx6sx: add missing properties for sram
+    - btrfs: scrub: try to fix super block errors
+    - clk: zynqmp: Fix stack-out-of-bounds in strncpy`
+    - media: cx88: Fix a null-ptr-deref bug in buffer_prepare()
+    - clk: zynqmp: pll: rectify rate rounding in zynqmp_pll_round_rate
+    - scsi: 3w-9xxx: Avoid disabling device if failing to enable it
+    - nbd: Fix hung when signal interrupts nbd_start_device_ioctl()
+    - power: supply: adp5061: fix out-of-bounds read in adp5061_get_chg_type()
+    - staging: vt6655: fix potential memory leak
+    - ata: libahci_platform: Sanity check the DT child nodes number
+    - bcache: fix set_at_max_writeback_rate() for multiple attached devices
+    - HID: roccat: Fix use-after-free in roccat_read()
+    - md/raid5: Wait for MD_SB_CHANGE_PENDING in raid5d
+    - usb: host: xhci: Fix potential memory leak in xhci_alloc_stream_info()
+    - usb: musb: Fix musb_gadget.c rxstate overflow bug
+    - Revert "usb: storage: Add quirk for Samsung Fit flash"
+    - staging: rtl8723bs: fix a potential memory leak in rtw_init_cmd_priv()
+    - nvme: copy firmware_rev on each init
+    - nvmet-tcp: add bounds check on Transfer Tag
+    - usb: idmouse: fix an uninit-value in idmouse_open
+    - clk: bcm2835: Make peripheral PLLC critical
+    - perf intel-pt: Fix segfault in intel_pt_print_info() with uClibc
+    - net: ieee802154: return -EINVAL for unknown addr type
+    - Revert "net/ieee802154: reject zero-sized raw_sendmsg()"
+    - net/ieee802154: don't warn zero-sized raw_sendmsg()
+    - ext4: continue to expand file system when the target size doesn't reach
+    - efi: libstub: drop pointless get_memory_map() call
+    - inet: fully convert sk->sk_rx_dst to RCU rules
+    - thermal: intel_powerclamp: Use first online CPU as control_cpu
+    - Linux 5.4.220
+  * Focal update: v5.4.219 upstream stable release (LP: #1996804)
+    - Linux 5.4.219
+
+  [ Ubuntu: 5.4.0-137.154 ]
+
+  * focal/linux: 5.4.0-137.154 -proposed tracker (LP: #2001969)
+  * CVE-2022-3643
+    - xen/netback: Ensure protocol headers don't fall in the non-linear area
+  * CVE-2022-43945
+    - NFSD: Cap rsize_bop result based on send buffer size
+  * CVE-2022-45934
+    - Bluetooth: L2CAP: Fix u8 overflow
+  * CVE-2022-42896
+    - Bluetooth: L2CAP: Fix accepting connection request for invalid SPSM
+    - Bluetooth: L2CAP: Fix l2cap_global_chan_by_psm
+
+ -- Masahiro Yamada <masahiro.yamada@canonical.com>  Mon, 23 Jan 2023 15:25:45 +0900
+
+linux-xilinx-zynqmp (5.4.0-1020.24) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1020.24 -proposed tracker (LP: #1999000)
+
+  [ Ubuntu: 5.4.0-136.153 ]
+
+  * focal/linux: 5.4.0-136.153 -proposed tracker (LP: #1997835)
+  * Expose built-in trusted and revoked certificates (LP: #1996892)
+    - [Packaging] Expose built-in trusted and revoked certificates
+  * [UBUNTU 20.04] KVM: PV: ext call delivered twice when receiver in PSW wait
+    (LP: #1995941)
+    - KVM: s390: pv: don't present the ecall interrupt twice
+  * [UBUNTU 20.04] boot: Add s390x secure boot trailer (LP: #1996071)
+    - s390/boot: add secure boot trailer
+  * Fix rfkill causing soft blocked wifi (LP: #1996198)
+    - platform/x86: hp_wmi: Fix rfkill causing soft blocked wifi
+  * md: Replace snprintf with scnprintf (LP: #1993315)
+    - md: Replace snprintf with scnprintf
+  * input/keyboard: the keyboard on some Asus laptops can't work (LP: #1992266)
+    - ACPI: resource: Skip IRQ override on Asus Vivobook K3402ZA/K3502ZA
+    - ACPI: resource: Add ASUS model S5402ZA to quirks
+  * Focal update: v5.4.218 upstream stable release (LP: #1995530)
+    - mm: pagewalk: Fix race between unmap and page walker
+    - perf tools: Fixup get_current_dir_name() compilation
+    - firmware: arm_scmi: Add SCMI PM driver remove routine
+    - dmaengine: xilinx_dma: cleanup for fetching xlnx,num-fstores property
+    - dmaengine: xilinx_dma: Report error in case of dma_set_mask_and_coherent API
+      failure
+    - ARM: dts: fix Moxa SDIO 'compatible', remove 'sdhci' misnomer
+    - scsi: qedf: Fix a UAF bug in __qedf_probe()
+    - net/ieee802154: fix uninit value bug in dgram_sendmsg
+    - um: Cleanup syscall_handler_t cast in syscalls_32.h
+    - um: Cleanup compiler warning in arch/x86/um/tls_32.c
+    - arch: um: Mark the stack non-executable to fix a binutils warning
+    - usb: mon: make mmapped memory read only
+    - USB: serial: ftdi_sio: fix 300 bps rate for SIO
+    - mmc: core: Replace with already defined values for readability
+    - mmc: core: Terminate infinite loop in SD-UHS voltage switch
+    - rpmsg: qcom: glink: replace strncpy() with strscpy_pad()
+    - nilfs2: fix leak of nilfs_root in case of writer thread creation failure
+    - nilfs2: replace WARN_ONs by nilfs_error for checkpoint acquisition failure
+    - ceph: don't truncate file in atomic_open
+    - random: clamp credited irq bits to maximum mixed
+    - ALSA: hda: Fix position reporting on Poulsbo
+    - efi: Correct Macmini DMI match in uefi cert quirk
+    - USB: serial: qcserial: add new usb-id for Dell branded EM7455
+    - random: restore O_NONBLOCK support
+    - random: avoid reading two cache lines on irq randomness
+    - random: use expired timer rather than wq for mixing fast pool
+    - Input: xpad - add supported devices as contributed on github
+    - Input: xpad - fix wireless 360 controller breaking after suspend
+    - Linux 5.4.218
+  * Focal update: v5.4.217 upstream stable release (LP: #1995528)
+    - xfs: fix misuse of the XFS_ATTR_INCOMPLETE flag
+    - xfs: introduce XFS_MAX_FILEOFF
+    - xfs: truncate should remove all blocks, not just to the end of the page
+      cache
+    - xfs: fix s_maxbytes computation on 32-bit kernels
+    - xfs: fix IOCB_NOWAIT handling in xfs_file_dio_aio_read
+    - xfs: refactor remote attr value buffer invalidation
+    - xfs: fix memory corruption during remote attr value buffer invalidation
+    - xfs: move incore structures out of xfs_da_format.h
+    - xfs: streamline xfs_attr3_leaf_inactive
+    - xfs: fix uninitialized variable in xfs_attr3_leaf_inactive
+    - xfs: remove unused variable 'done'
+    - Makefile.extrawarn: Move -Wcast-function-type-strict to W=1
+    - docs: update mediator information in CoC docs
+    - Linux 5.4.217
+  * Focal update: v5.4.216 upstream stable release (LP: #1995526)
+    - uas: add no-uas quirk for Hiksemi usb_disk
+    - usb-storage: Add Hiksemi USB3-FW to IGNORE_UAS
+    - uas: ignore UAS for Thinkplus chips
+    - net: usb: qmi_wwan: Add new usb-id for Dell branded EM7455
+    - clk: ingenic-tcu: Properly enable registers before accessing timers
+    - ARM: dts: integrator: Tag PCI host with device_type
+    - ntfs: fix BUG_ON in ntfs_lookup_inode_by_name()
+    - libata: add ATA_HORKAGE_NOLPM for Pioneer BDR-207M and BDR-205
+    - mmc: moxart: fix 4-bit bus width and remove 8-bit bus width
+    - mm/page_alloc: fix race condition between build_all_zonelists and page
+      allocation
+    - mm: prevent page_frag_alloc() from corrupting the memory
+    - mm/migrate_device.c: flush TLB while holding PTL
+    - mm: fix madivse_pageout mishandling on non-LRU page
+    - media: dvb_vb2: fix possible out of bound access
+    - ARM: dts: Move am33xx and am43xx mmc nodes to sdhci-omap driver
+    - ARM: dts: am33xx: Fix MMCHS0 dma properties
+    - soc: sunxi: sram: Actually claim SRAM regions
+    - soc: sunxi: sram: Prevent the driver from being unbound
+    - soc: sunxi_sram: Make use of the helper function
+      devm_platform_ioremap_resource()
+    - soc: sunxi: sram: Fix probe function ordering issues
+    - soc: sunxi: sram: Fix debugfs info for A64 SRAM C
+    - Revert "drm: bridge: analogix/dp: add panel prepare/unprepare in
+      suspend/resume time"
+    - Input: melfas_mip4 - fix return value check in mip4_probe()
+    - usbnet: Fix memory leak in usbnet_disconnect()
+    - nvme: add new line after variable declatation
+    - nvme: Fix IOC_PR_CLEAR and IOC_PR_RELEASE ioctls for nvme devices
+    - selftests: Fix the if conditions of in test_extra_filter()
+    - clk: imx: imx6sx: remove the SET_RATE_PARENT flag for QSPI clocks
+    - clk: iproc: Do not rely on node name for correct PLL setup
+    - Linux 5.4.216
+  * Focal update: v5.4.215 upstream stable release (LP: #1993203)
+    - of: fdt: fix off-by-one error in unflatten_dt_nodes()
+    - NFSv4: Turn off open-by-filehandle and NFS re-export for NFSv4.0
+    - gpio: mpc8xxx: Fix support for IRQ_TYPE_LEVEL_LOW flow_type in mpc85xx
+    - drm/meson: Correct OSD1 global alpha value
+    - drm/meson: Fix OSD1 RGB to YCbCr coefficient
+    - parisc: ccio-dma: Add missing iounmap in error path in ccio_probe()
+    - ALSA: pcm: oss: Fix race at SNDCTL_DSP_SYNC
+    - task_stack, x86/cea: Force-inline stack helpers
+    - tracing: hold caller_addr to hardirq_{enable,disable}_ip
+    - cifs: revalidate mapping when doing direct writes
+    - cifs: don't send down the destination address to sendmsg for a SOCK_STREAM
+    - MAINTAINERS: add Chandan as xfs maintainer for 5.4.y
+    - iomap: iomap that extends beyond EOF should be marked dirty
+    - ASoC: nau8824: Fix semaphore unbalance at error paths
+    - regulator: pfuze100: Fix the global-out-of-bounds access in
+      pfuze100_regulator_probe()
+    - rxrpc: Fix local destruction being repeated
+    - rxrpc: Fix calc of resend age
+    - ALSA: hda/sigmatel: Keep power up while beep is enabled
+    - ALSA: hda/tegra: Align BDL entry to 4KB boundary
+    - net: usb: qmi_wwan: add Quectel RM520N
+    - afs: Return -EAGAIN, not -EREMOTEIO, when a file already locked
+    - MIPS: OCTEON: irq: Fix octeon_irq_force_ciu_mapping()
+    - mksysmap: Fix the mismatch of 'L0' symbols in System.map
+    - video: fbdev: pxa3xx-gcu: Fix integer overflow in pxa3xx_gcu_write
+    - cgroup: Add missing cpus_read_lock() to cgroup_attach_task_all()
+    - ALSA: hda/sigmatel: Fix unused variable warning for beep power change
+    - usb: dwc3: gadget: Avoid starting DWC3 gadget during UDC unbind
+    - usb: dwc3: Issue core soft reset before enabling run/stop
+    - usb: dwc3: gadget: Prevent repeat pullup()
+    - usb: dwc3: gadget: Refactor pullup()
+    - usb: dwc3: gadget: Don't modify GEVNTCOUNT in pullup()
+    - usb: dwc3: gadget: Avoid duplicate requests to enable Run/Stop
+    - usb: xhci-mtk: get the microframe boundary for ESIT
+    - usb: xhci-mtk: add only one extra CS for FS/LS INTR
+    - usb: xhci-mtk: use @sch_tt to check whether need do TT schedule
+    - usb: xhci-mtk: add a function to (un)load bandwidth info
+    - usb: xhci-mtk: add some schedule error number
+    - usb: xhci-mtk: allow multiple Start-Split in a microframe
+    - usb: xhci-mtk: relax TT periodic bandwidth allocation
+    - wifi: mac80211: Fix UAF in ieee80211_scan_rx()
+    - tty/serial: atmel: RS485 & ISO7816: wait for TXRDY before sending data
+    - serial: atmel: remove redundant assignment in rs485_config
+    - tty: serial: atmel: Preserve previous USART mode if RS485 disabled
+    - usb: add quirks for Lenovo OneLink+ Dock
+    - usb: gadget: udc-xilinx: replace memcpy with memcpy_toio
+    - usb: cdns3: fix issue with rearming ISO OUT endpoint
+    - Revert "usb: add quirks for Lenovo OneLink+ Dock"
+    - Revert "usb: gadget: udc-xilinx: replace memcpy with memcpy_toio"
+    - USB: core: Fix RST error in hub.c
+    - USB: serial: option: add Quectel BG95 0x0203 composition
+    - USB: serial: option: add Quectel RM520N
+    - ALSA: hda/tegra: set depop delay for tegra
+    - ALSA: hda: add Intel 5 Series / 3400 PCI DID
+    - ALSA: hda/realtek: Add quirk for Huawei WRT-WX9
+    - ALSA: hda/realtek: Re-arrange quirk table entries
+    - ALSA: hda/realtek: Add pincfg for ASUS G513 HP jack
+    - ALSA: hda/realtek: Add pincfg for ASUS G533Z HP jack
+    - ALSA: hda/realtek: Add quirk for ASUS GA503R laptop
+    - ALSA: hda/realtek: Enable 4-speaker output Dell Precision 5530 laptop
+    - efi: libstub: check Shim mode using MokSBStateRT
+    - mm/slub: fix to return errno if kmalloc() fails
+    - arm64: dts: rockchip: Pull up wlan wake# on Gru-Bob
+    - arm64: dts: rockchip: Set RK3399-Gru PCLK_EDP to 24 MHz
+    - arm64: dts: rockchip: Remove 'enable-active-low' from rk3399-puma
+    - netfilter: nf_conntrack_sip: fix ct_sip_walk_headers
+    - netfilter: nf_conntrack_irc: Tighten matching on DCC message
+    - netfilter: nfnetlink_osf: fix possible bogus match in nf_osf_find()
+    - iavf: Fix cached head and tail value for iavf_get_tx_pending
+    - ipvlan: Fix out-of-bound bugs caused by unset skb->mac_header
+    - net: team: Unsync device addresses on ndo_stop
+    - MIPS: lantiq: export clk_get_io() for lantiq_wdt.ko
+    - MIPS: Loongson32: Fix PHY-mode being left unspecified
+    - iavf: Fix bad page state
+    - i40e: Fix set max_tx_rate when it is lower than 1 Mbps
+    - of: mdio: Add of_node_put() when breaking out of for_each_xx
+    - net/sched: taprio: avoid disabling offload when it was never enabled
+    - net/sched: taprio: make qdisc_leaf() see the per-netdev-queue pfifo child
+      qdiscs
+    - netfilter: ebtables: fix memory leak when blob is malformed
+    - can: gs_usb: gs_can_open(): fix race dev->can.state condition
+    - perf jit: Include program header in ELF files
+    - perf kcore_copy: Do not check /proc/modules is unchanged
+    - net: sunhme: Fix packet reception for len < RX_COPY_THRESHOLD
+    - net: sched: fix possible refcount leak in tc_new_tfilter()
+    - serial: Create uart_xmit_advance()
+    - serial: tegra: Use uart_xmit_advance(), fixes icount.tx accounting
+    - serial: tegra-tcu: Use uart_xmit_advance(), fixes icount.tx accounting
+    - s390/dasd: fix Oops in dasd_alias_get_start_dev due to missing pavgroup
+    - usb: xhci-mtk: fix issue of out-of-bounds array access
+    - cifs: always initialize struct msghdr smb_msg completely
+    - Drivers: hv: Never allocate anything besides framebuffer from framebuffer
+      memory region
+    - drm/amd/display: Limit user regamma to a valid value
+    - drm/rockchip: Fix return type of cdn_dp_connector_mode_valid
+    - workqueue: don't skip lockdep work dependency in cancel_work_sync()
+    - ext4: fix bug in extents parsing when eh_entries == 0 and eh_depth > 0
+    - xfs: replace -EIO with -EFSCORRUPTED for corrupt metadata
+    - xfs: slightly tweak an assert in xfs_fs_map_blocks
+    - xfs: add missing assert in xfs_fsmap_owner_from_rmap
+    - xfs: range check ri_cnt when recovering log items
+    - xfs: attach dquots and reserve quota blocks during unwritten conversion
+    - xfs: convert EIO to EFSCORRUPTED when log contents are invalid
+    - xfs: constify the buffer pointer arguments to error functions
+    - xfs: always log corruption errors
+    - xfs: fix some memory leaks in log recovery
+    - xfs: stabilize insert range start boundary to avoid COW writeback race
+    - xfs: use bitops interface for buf log item AIL flag check
+    - xfs: refactor agfl length computation function
+    - xfs: split the sunit parameter update into two parts
+    - xfs: don't commit sunit/swidth updates to disk if that would cause repair
+      failures
+    - xfs: fix an ABBA deadlock in xfs_rename
+    - xfs: fix use-after-free when aborting corrupt attr inactivation
+    - ext4: make directory inode spreading reflect flexbg size
+    - Linux 5.4.215
+  * Focal update: v5.4.214 upstream stable release (LP: #1993196)
+    - drm/msm/rd: Fix FIFO-full deadlock
+    - HID: ishtp-hid-clientHID: ishtp-hid-client: Fix comment typo
+    - hid: intel-ish-hid: ishtp: Fix ishtp client sending disordered message
+    - tg3: Disable tg3 device on system reboot to avoid triggering AER
+    - ieee802154: cc2520: add rc code in cc2520_tx()
+    - Input: iforce - add support for Boeder Force Feedback Wheel
+    - nvmet-tcp: fix unhandled tcp states in nvmet_tcp_state_change()
+    - perf/arm_pmu_platform: fix tests for platform_get_irq() failure
+    - platform/x86: acer-wmi: Acer Aspire One AOD270/Packard Bell Dot keymap fixes
+    - usb: storage: Add ASUS <0x0b05:0x1932> to IGNORE_UAS
+    - mm: Fix TLB flush for not-first PFNMAP mappings in unmap_region()
+    - net: dp83822: disable rx error interrupt
+    - soc: fsl: select FSL_GUTS driver for DPIO
+    - tracefs: Only clobber mode/uid/gid on remount if asked
+    - Linux 5.4.214
+  * Focal update: v5.4.213 upstream stable release (LP: #1992211)
+    - efi: capsule-loader: Fix use-after-free in efi_capsule_write
+    - wifi: iwlegacy: 4965: corrected fix for potential off-by-one overflow in
+      il4965_rs_fill_link_cmd()
+    - fs: only do a memory barrier for the first set_buffer_uptodate()
+    - Revert "mm: kmemleak: take a full lowmem check in kmemleak_*_phys()"
+    - net: dp83822: disable false carrier interrupt
+    - drm/msm/dsi: fix the inconsistent indenting
+    - drm/msm/dsi: Fix number of regulators for msm8996_dsi_cfg
+    - platform/x86: pmc_atom: Fix SLP_TYPx bitfield mask
+    - iio: adc: mcp3911: make use of the sign bit
+    - ieee802154/adf7242: defer destroy_workqueue call
+    - wifi: cfg80211: debugfs: fix return type in ht40allow_map_read()
+    - Revert "xhci: turn off port power in shutdown"
+    - net: sched: tbf: don't call qdisc_put() while holding tree lock
+    - ethernet: rocker: fix sleep in atomic context bug in neigh_timer_handler
+    - kcm: fix strp_init() order and cleanup
+    - sch_cake: Return __NET_XMIT_STOLEN when consuming enqueued skb
+    - tcp: annotate data-race around challenge_timestamp
+    - Revert "sch_cake: Return __NET_XMIT_STOLEN when consuming enqueued skb"
+    - net/smc: Remove redundant refcount increase
+    - serial: fsl_lpuart: RS485 RTS polariy is inverse
+    - staging: rtl8712: fix use after free bugs
+    - powerpc: align syscall table for ppc32
+    - vt: Clear selection before changing the font
+    - tty: serial: lpuart: disable flow control while waiting for the transmit
+      engine to complete
+    - Input: iforce - wake up after clearing IFORCE_XMIT_RUNNING flag
+    - iio: adc: mcp3911: use correct formula for AD conversion
+    - misc: fastrpc: fix memory corruption on probe
+    - misc: fastrpc: fix memory corruption on open
+    - USB: serial: ftdi_sio: add Omron CS1W-CIF31 device id
+    - binder: fix UAF of ref->proc caused by race condition
+    - usb: dwc3: qcom: fix use-after-free on runtime-PM wakeup
+    - drm/i915/reg: Fix spelling mistake "Unsupport" -> "Unsupported"
+    - clk: core: Honor CLK_OPS_PARENT_ENABLE for clk gate ops
+    - Revert "clk: core: Honor CLK_OPS_PARENT_ENABLE for clk gate ops"
+    - clk: core: Fix runtime PM sequence in clk_core_unprepare()
+    - Input: rk805-pwrkey - fix module autoloading
+    - clk: bcm: rpi: Fix error handling of raspberrypi_fw_get_rate
+    - hwmon: (gpio-fan) Fix array out of bounds access
+    - gpio: pca953x: Add mutex_lock for regcache sync in PM
+    - thunderbolt: Use the actual buffer in tb_async_error()
+    - xhci: Add grace period after xHC start to prevent premature runtime suspend.
+    - USB: serial: cp210x: add Decagon UCA device id
+    - USB: serial: option: add support for OPPO R11 diag port
+    - USB: serial: option: add Quectel EM060K modem
+    - USB: serial: option: add support for Cinterion MV32-WA/WB RmNet mode
+    - usb: typec: altmodes/displayport: correct pin assignment for UFP receptacles
+    - usb: dwc2: fix wrong order of phy_power_on and phy_init
+    - USB: cdc-acm: Add Icom PMR F3400 support (0c26:0020)
+    - usb-storage: Add ignore-residue quirk for NXP PN7462AU
+    - s390/hugetlb: fix prepare_hugepage_range() check for 2 GB hugepages
+    - s390: fix nospec table alignments
+    - USB: core: Prevent nested device-reset calls
+    - usb: gadget: mass_storage: Fix cdrom data transfers on MAC-OS
+    - driver core: Don't probe devices after bus_type.match() probe deferral
+    - wifi: mac80211: Don't finalize CSA in IBSS mode if state is disconnected
+    - net: mac802154: Fix a condition in the receive path
+    - ALSA: seq: oss: Fix data-race for max_midi_devs access
+    - ALSA: seq: Fix data-race at module auto-loading
+    - drm/i915/glk: ECS Liva Q2 needs GLK HDMI port timing quirk
+    - btrfs: harden identification of a stale device
+    - usb: dwc3: fix PHY disable sequence
+    - usb: dwc3: disable USB core PHY management
+    - USB: serial: ch341: fix lost character on LCR updates
+    - USB: serial: ch341: fix disabled rx timer on older devices
+    - scsi: megaraid_sas: Fix double kfree()
+    - drm/gem: Fix GEM handle release errors
+    - drm/amdgpu: Check num_gfx_rings for gfx v9_0 rb setup.
+    - drm/radeon: add a force flush to delay work when radeon
+    - parisc: ccio-dma: Handle kmalloc failure in ccio_init_resources()
+    - parisc: Add runtime check to prevent PA2.0 kernels on PA1.x machines
+    - arm64: cacheinfo: Fix incorrect assignment of signed error value to unsigned
+      fw_level
+    - fbdev: chipsfb: Add missing pci_disable_device() in chipsfb_pci_init()
+    - drm/amdgpu: mmVM_L2_CNTL3 register not initialized correctly
+    - ALSA: emu10k1: Fix out of bounds access in snd_emu10k1_pcm_channel_alloc()
+    - ALSA: aloop: Fix random zeros in capture data when using jiffies timer
+    - ALSA: usb-audio: Fix an out-of-bounds bug in
+      __snd_usb_parse_audio_interface()
+    - kprobes: Prohibit probes in gate area
+    - debugfs: add debugfs_lookup_and_remove()
+    - nvmet: fix a use-after-free
+    - scsi: mpt3sas: Fix use-after-free warning
+    - scsi: lpfc: Add missing destroy_workqueue() in error path
+    - cgroup: Optimize single thread migration
+    - cgroup: Elide write-locking threadgroup_rwsem when updating csses on an
+      empty subtree
+    - cgroup: Fix threadgroup_rwsem <-> cpus_read_lock() deadlock
+    - smb3: missing inode locks in punch hole
+    - ARM: dts: imx6qdl-kontron-samx6i: remove duplicated node
+    - regulator: core: Clean up on enable failure
+    - RDMA/cma: Fix arguments order in net device validation
+    - soc: brcmstb: pm-arm: Fix refcount leak and __iomem leak bugs
+    - RDMA/hns: Fix supported page size
+    - netfilter: br_netfilter: Drop dst references before setting.
+    - rxrpc: Fix an insufficiently large sglist in rxkad_verify_packet_2()
+    - afs: Use the operation issue time instead of the reply time for callbacks
+    - sch_sfb: Don't assume the skb is still around after enqueueing to child
+    - tipc: fix shift wrapping bug in map_get()
+    - i40e: Fix kernel crash during module removal
+    - RDMA/siw: Pass a pointer to virt_to_page()
+    - ipv6: sr: fix out-of-bounds read when setting HMAC data.
+    - RDMA/mlx5: Set local port to one when accessing counters
+    - nvme-tcp: fix UAF when detecting digest errors
+    - tcp: fix early ETIMEDOUT after spurious non-SACK RTO
+    - sch_sfb: Also store skb len before calling child enqueue
+    - x86/nospec: Fix i386 RSB stuffing
+    - MIPS: loongson32: ls1c: Fix hang during startup
+    - Linux 5.4.213
+  * CVE-2022-2663
+    - netfilter: nf_conntrack_irc: Fix forged IP logic
+  * CVE-2022-3061
+    - video: fbdev: i740fb: Error out if 'pixclock' equals zero
+
+  [ Ubuntu: 5.4.0-135.152 ]
+
+  * focal/linux: 5.4.0-135.152 -proposed tracker (LP: #1997412)
+  * containerd sporadic timeouts (LP: #1996678)
+    - epoll: call final ep_events_available() check under the lock
+    - epoll: check for events when removing a timed out thread from the wait queue
+    - Revert "fs: check FMODE_LSEEK to control internal pipe splicing"
+  * CVE-2022-3621
+    - nilfs2: fix NULL pointer dereference at nilfs_bmap_lookup_at_level()
+  * CVE-2022-3565
+    - mISDN: fix use-after-free bugs in l1oip timer handlers
+  * CVE-2022-3566
+    - tcp: Fix data races around icsk->icsk_af_ops.
+  * CVE-2022-3567
+    - ipv6: annotate some data-races around sk->sk_prot
+    - ipv6: Fix data races around sk->sk_prot.
+  * CVE-2022-3564
+    - Bluetooth: L2CAP: Fix use-after-free caused by l2cap_reassemble_sdu
+  * CVE-2022-3524
+    - tcp/udp: Fix memory leak in ipv6_renew_options().
+  * CVE-2022-3594
+    - r8152: Rate limit overflow messages
+  * CVE-2022-42703
+    - mm/rmap.c: don't reuse anon_vma if we just want a copy
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Mon, 12 Dec 2022 14:14:24 +1000
+
+linux-xilinx-zynqmp (5.4.0-1019.22) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1019.22 -proposed tracker (LP: #1996060)
+
+  * linux-xilinx-zynqmp/focal fails ubuntu_qrt_kernel_security. (LP: #1995465)
+    - [Config] updateconfigs for ubuntu_qrt_kernel_security
+    - [Config] Update abi modules based off updated configs
+
+  * linux-xilinx-zynqmp/focal: main(): sched_setscheduler(): Operation not
+    permitted (LP: #1992912)
+    - [Config] updateconfigs to disable RT_GROUP_SCHED
+
+  [ Ubuntu: 5.4.0-133.149 ]
+
+  * focal/linux: 5.4.0-133.149 -proposed tracker (LP: #1996385)
+  * CVE-2022-42703
+    - mm/rmap.c: don't reuse anon_vma if we just want a copy
+  * [UBUNTU 20.04] KVM: PV: ext call delivered twice when receiver in PSW wait
+    (LP: #1995941)
+    - KVM: s390: pv: don't present the ecall interrupt twice
+  * [UBUNTU 20.04] boot: Add s390x secure boot trailer (LP: #1996071)
+    - s390/boot: add secure boot trailer
+  * Fix rfkill causing soft blocked wifi (LP: #1996198)
+    - platform/x86: hp_wmi: Fix rfkill causing soft blocked wifi
+  * md: Replace snprintf with scnprintf (LP: #1993315)
+    - md: Replace snprintf with scnprintf
+  * input/keyboard: the keyboard on some Asus laptops can't work (LP: #1992266)
+    - ACPI: resource: Skip IRQ override on Asus Vivobook K3402ZA/K3502ZA
+    - ACPI: resource: Add ASUS model S5402ZA to quirks
+  * Focal update: v5.4.218 upstream stable release (LP: #1995530)
+    - mm: pagewalk: Fix race between unmap and page walker
+    - perf tools: Fixup get_current_dir_name() compilation
+    - firmware: arm_scmi: Add SCMI PM driver remove routine
+    - dmaengine: xilinx_dma: cleanup for fetching xlnx,num-fstores property
+    - dmaengine: xilinx_dma: Report error in case of dma_set_mask_and_coherent API
+      failure
+    - ARM: dts: fix Moxa SDIO 'compatible', remove 'sdhci' misnomer
+    - scsi: qedf: Fix a UAF bug in __qedf_probe()
+    - net/ieee802154: fix uninit value bug in dgram_sendmsg
+    - um: Cleanup syscall_handler_t cast in syscalls_32.h
+    - um: Cleanup compiler warning in arch/x86/um/tls_32.c
+    - arch: um: Mark the stack non-executable to fix a binutils warning
+    - usb: mon: make mmapped memory read only
+    - USB: serial: ftdi_sio: fix 300 bps rate for SIO
+    - mmc: core: Replace with already defined values for readability
+    - mmc: core: Terminate infinite loop in SD-UHS voltage switch
+    - rpmsg: qcom: glink: replace strncpy() with strscpy_pad()
+    - nilfs2: fix NULL pointer dereference at nilfs_bmap_lookup_at_level()
+    - nilfs2: fix leak of nilfs_root in case of writer thread creation failure
+    - nilfs2: replace WARN_ONs by nilfs_error for checkpoint acquisition failure
+    - ceph: don't truncate file in atomic_open
+    - random: clamp credited irq bits to maximum mixed
+    - ALSA: hda: Fix position reporting on Poulsbo
+    - efi: Correct Macmini DMI match in uefi cert quirk
+    - USB: serial: qcserial: add new usb-id for Dell branded EM7455
+    - random: restore O_NONBLOCK support
+    - random: avoid reading two cache lines on irq randomness
+    - random: use expired timer rather than wq for mixing fast pool
+    - Input: xpad - add supported devices as contributed on github
+    - Input: xpad - fix wireless 360 controller breaking after suspend
+    - Linux 5.4.218
+  * Focal update: v5.4.217 upstream stable release (LP: #1995528)
+    - xfs: fix misuse of the XFS_ATTR_INCOMPLETE flag
+    - xfs: introduce XFS_MAX_FILEOFF
+    - xfs: truncate should remove all blocks, not just to the end of the page
+      cache
+    - xfs: fix s_maxbytes computation on 32-bit kernels
+    - xfs: fix IOCB_NOWAIT handling in xfs_file_dio_aio_read
+    - xfs: refactor remote attr value buffer invalidation
+    - xfs: fix memory corruption during remote attr value buffer invalidation
+    - xfs: move incore structures out of xfs_da_format.h
+    - xfs: streamline xfs_attr3_leaf_inactive
+    - xfs: fix uninitialized variable in xfs_attr3_leaf_inactive
+    - xfs: remove unused variable 'done'
+    - Makefile.extrawarn: Move -Wcast-function-type-strict to W=1
+    - docs: update mediator information in CoC docs
+    - Linux 5.4.217
+  * Focal update: v5.4.216 upstream stable release (LP: #1995526)
+    - uas: add no-uas quirk for Hiksemi usb_disk
+    - usb-storage: Add Hiksemi USB3-FW to IGNORE_UAS
+    - uas: ignore UAS for Thinkplus chips
+    - net: usb: qmi_wwan: Add new usb-id for Dell branded EM7455
+    - clk: ingenic-tcu: Properly enable registers before accessing timers
+    - ARM: dts: integrator: Tag PCI host with device_type
+    - ntfs: fix BUG_ON in ntfs_lookup_inode_by_name()
+    - libata: add ATA_HORKAGE_NOLPM for Pioneer BDR-207M and BDR-205
+    - mmc: moxart: fix 4-bit bus width and remove 8-bit bus width
+    - mm/page_alloc: fix race condition between build_all_zonelists and page
+      allocation
+    - mm: prevent page_frag_alloc() from corrupting the memory
+    - mm/migrate_device.c: flush TLB while holding PTL
+    - mm: fix madivse_pageout mishandling on non-LRU page
+    - media: dvb_vb2: fix possible out of bound access
+    - ARM: dts: Move am33xx and am43xx mmc nodes to sdhci-omap driver
+    - ARM: dts: am33xx: Fix MMCHS0 dma properties
+    - soc: sunxi: sram: Actually claim SRAM regions
+    - soc: sunxi: sram: Prevent the driver from being unbound
+    - soc: sunxi_sram: Make use of the helper function
+      devm_platform_ioremap_resource()
+    - soc: sunxi: sram: Fix probe function ordering issues
+    - soc: sunxi: sram: Fix debugfs info for A64 SRAM C
+    - Revert "drm: bridge: analogix/dp: add panel prepare/unprepare in
+      suspend/resume time"
+    - Input: melfas_mip4 - fix return value check in mip4_probe()
+    - usbnet: Fix memory leak in usbnet_disconnect()
+    - nvme: add new line after variable declatation
+    - nvme: Fix IOC_PR_CLEAR and IOC_PR_RELEASE ioctls for nvme devices
+    - selftests: Fix the if conditions of in test_extra_filter()
+    - clk: imx: imx6sx: remove the SET_RATE_PARENT flag for QSPI clocks
+    - clk: iproc: Do not rely on node name for correct PLL setup
+    - Linux 5.4.216
+  * Focal update: v5.4.215 upstream stable release (LP: #1993203)
+    - of: fdt: fix off-by-one error in unflatten_dt_nodes()
+    - NFSv4: Turn off open-by-filehandle and NFS re-export for NFSv4.0
+    - gpio: mpc8xxx: Fix support for IRQ_TYPE_LEVEL_LOW flow_type in mpc85xx
+    - drm/meson: Correct OSD1 global alpha value
+    - drm/meson: Fix OSD1 RGB to YCbCr coefficient
+    - parisc: ccio-dma: Add missing iounmap in error path in ccio_probe()
+    - ALSA: pcm: oss: Fix race at SNDCTL_DSP_SYNC
+    - task_stack, x86/cea: Force-inline stack helpers
+    - tracing: hold caller_addr to hardirq_{enable,disable}_ip
+    - cifs: revalidate mapping when doing direct writes
+    - cifs: don't send down the destination address to sendmsg for a SOCK_STREAM
+    - MAINTAINERS: add Chandan as xfs maintainer for 5.4.y
+    - iomap: iomap that extends beyond EOF should be marked dirty
+    - ASoC: nau8824: Fix semaphore unbalance at error paths
+    - regulator: pfuze100: Fix the global-out-of-bounds access in
+      pfuze100_regulator_probe()
+    - rxrpc: Fix local destruction being repeated
+    - rxrpc: Fix calc of resend age
+    - ALSA: hda/sigmatel: Keep power up while beep is enabled
+    - ALSA: hda/tegra: Align BDL entry to 4KB boundary
+    - net: usb: qmi_wwan: add Quectel RM520N
+    - afs: Return -EAGAIN, not -EREMOTEIO, when a file already locked
+    - MIPS: OCTEON: irq: Fix octeon_irq_force_ciu_mapping()
+    - mksysmap: Fix the mismatch of 'L0' symbols in System.map
+    - video: fbdev: pxa3xx-gcu: Fix integer overflow in pxa3xx_gcu_write
+    - cgroup: Add missing cpus_read_lock() to cgroup_attach_task_all()
+    - ALSA: hda/sigmatel: Fix unused variable warning for beep power change
+    - usb: dwc3: gadget: Avoid starting DWC3 gadget during UDC unbind
+    - usb: dwc3: Issue core soft reset before enabling run/stop
+    - usb: dwc3: gadget: Prevent repeat pullup()
+    - usb: dwc3: gadget: Refactor pullup()
+    - usb: dwc3: gadget: Don't modify GEVNTCOUNT in pullup()
+    - usb: dwc3: gadget: Avoid duplicate requests to enable Run/Stop
+    - usb: xhci-mtk: get the microframe boundary for ESIT
+    - usb: xhci-mtk: add only one extra CS for FS/LS INTR
+    - usb: xhci-mtk: use @sch_tt to check whether need do TT schedule
+    - usb: xhci-mtk: add a function to (un)load bandwidth info
+    - usb: xhci-mtk: add some schedule error number
+    - usb: xhci-mtk: allow multiple Start-Split in a microframe
+    - usb: xhci-mtk: relax TT periodic bandwidth allocation
+    - wifi: mac80211: Fix UAF in ieee80211_scan_rx()
+    - tty/serial: atmel: RS485 & ISO7816: wait for TXRDY before sending data
+    - serial: atmel: remove redundant assignment in rs485_config
+    - tty: serial: atmel: Preserve previous USART mode if RS485 disabled
+    - usb: add quirks for Lenovo OneLink+ Dock
+    - usb: gadget: udc-xilinx: replace memcpy with memcpy_toio
+    - usb: cdns3: fix issue with rearming ISO OUT endpoint
+    - Revert "usb: add quirks for Lenovo OneLink+ Dock"
+    - Revert "usb: gadget: udc-xilinx: replace memcpy with memcpy_toio"
+    - USB: core: Fix RST error in hub.c
+    - USB: serial: option: add Quectel BG95 0x0203 composition
+    - USB: serial: option: add Quectel RM520N
+    - ALSA: hda/tegra: set depop delay for tegra
+    - ALSA: hda: add Intel 5 Series / 3400 PCI DID
+    - ALSA: hda/realtek: Add quirk for Huawei WRT-WX9
+    - ALSA: hda/realtek: Re-arrange quirk table entries
+    - ALSA: hda/realtek: Add pincfg for ASUS G513 HP jack
+    - ALSA: hda/realtek: Add pincfg for ASUS G533Z HP jack
+    - ALSA: hda/realtek: Add quirk for ASUS GA503R laptop
+    - ALSA: hda/realtek: Enable 4-speaker output Dell Precision 5530 laptop
+    - efi: libstub: check Shim mode using MokSBStateRT
+    - mm/slub: fix to return errno if kmalloc() fails
+    - arm64: dts: rockchip: Pull up wlan wake# on Gru-Bob
+    - arm64: dts: rockchip: Set RK3399-Gru PCLK_EDP to 24 MHz
+    - arm64: dts: rockchip: Remove 'enable-active-low' from rk3399-puma
+    - netfilter: nf_conntrack_sip: fix ct_sip_walk_headers
+    - netfilter: nf_conntrack_irc: Tighten matching on DCC message
+    - netfilter: nfnetlink_osf: fix possible bogus match in nf_osf_find()
+    - iavf: Fix cached head and tail value for iavf_get_tx_pending
+    - ipvlan: Fix out-of-bound bugs caused by unset skb->mac_header
+    - net: team: Unsync device addresses on ndo_stop
+    - MIPS: lantiq: export clk_get_io() for lantiq_wdt.ko
+    - MIPS: Loongson32: Fix PHY-mode being left unspecified
+    - iavf: Fix bad page state
+    - i40e: Fix set max_tx_rate when it is lower than 1 Mbps
+    - of: mdio: Add of_node_put() when breaking out of for_each_xx
+    - net/sched: taprio: avoid disabling offload when it was never enabled
+    - net/sched: taprio: make qdisc_leaf() see the per-netdev-queue pfifo child
+      qdiscs
+    - netfilter: ebtables: fix memory leak when blob is malformed
+    - can: gs_usb: gs_can_open(): fix race dev->can.state condition
+    - perf jit: Include program header in ELF files
+    - perf kcore_copy: Do not check /proc/modules is unchanged
+    - net: sunhme: Fix packet reception for len < RX_COPY_THRESHOLD
+    - net: sched: fix possible refcount leak in tc_new_tfilter()
+    - serial: Create uart_xmit_advance()
+    - serial: tegra: Use uart_xmit_advance(), fixes icount.tx accounting
+    - serial: tegra-tcu: Use uart_xmit_advance(), fixes icount.tx accounting
+    - s390/dasd: fix Oops in dasd_alias_get_start_dev due to missing pavgroup
+    - usb: xhci-mtk: fix issue of out-of-bounds array access
+    - cifs: always initialize struct msghdr smb_msg completely
+    - Drivers: hv: Never allocate anything besides framebuffer from framebuffer
+      memory region
+    - drm/amd/display: Limit user regamma to a valid value
+    - drm/rockchip: Fix return type of cdn_dp_connector_mode_valid
+    - workqueue: don't skip lockdep work dependency in cancel_work_sync()
+    - ext4: fix bug in extents parsing when eh_entries == 0 and eh_depth > 0
+    - xfs: replace -EIO with -EFSCORRUPTED for corrupt metadata
+    - xfs: slightly tweak an assert in xfs_fs_map_blocks
+    - xfs: add missing assert in xfs_fsmap_owner_from_rmap
+    - xfs: range check ri_cnt when recovering log items
+    - xfs: attach dquots and reserve quota blocks during unwritten conversion
+    - xfs: convert EIO to EFSCORRUPTED when log contents are invalid
+    - xfs: constify the buffer pointer arguments to error functions
+    - xfs: always log corruption errors
+    - xfs: fix some memory leaks in log recovery
+    - xfs: stabilize insert range start boundary to avoid COW writeback race
+    - xfs: use bitops interface for buf log item AIL flag check
+    - xfs: refactor agfl length computation function
+    - xfs: split the sunit parameter update into two parts
+    - xfs: don't commit sunit/swidth updates to disk if that would cause repair
+      failures
+    - xfs: fix an ABBA deadlock in xfs_rename
+    - xfs: fix use-after-free when aborting corrupt attr inactivation
+    - ext4: make directory inode spreading reflect flexbg size
+    - Linux 5.4.215
+  * Focal update: v5.4.214 upstream stable release (LP: #1993196)
+    - drm/msm/rd: Fix FIFO-full deadlock
+    - HID: ishtp-hid-clientHID: ishtp-hid-client: Fix comment typo
+    - hid: intel-ish-hid: ishtp: Fix ishtp client sending disordered message
+    - tg3: Disable tg3 device on system reboot to avoid triggering AER
+    - ieee802154: cc2520: add rc code in cc2520_tx()
+    - Input: iforce - add support for Boeder Force Feedback Wheel
+    - nvmet-tcp: fix unhandled tcp states in nvmet_tcp_state_change()
+    - perf/arm_pmu_platform: fix tests for platform_get_irq() failure
+    - platform/x86: acer-wmi: Acer Aspire One AOD270/Packard Bell Dot keymap fixes
+    - usb: storage: Add ASUS <0x0b05:0x1932> to IGNORE_UAS
+    - mm: Fix TLB flush for not-first PFNMAP mappings in unmap_region()
+    - net: dp83822: disable rx error interrupt
+    - soc: fsl: select FSL_GUTS driver for DPIO
+    - tracefs: Only clobber mode/uid/gid on remount if asked
+    - Linux 5.4.214
+  * Focal update: v5.4.213 upstream stable release (LP: #1992211)
+    - efi: capsule-loader: Fix use-after-free in efi_capsule_write
+    - wifi: iwlegacy: 4965: corrected fix for potential off-by-one overflow in
+      il4965_rs_fill_link_cmd()
+    - fs: only do a memory barrier for the first set_buffer_uptodate()
+    - Revert "mm: kmemleak: take a full lowmem check in kmemleak_*_phys()"
+    - net: dp83822: disable false carrier interrupt
+    - drm/msm/dsi: fix the inconsistent indenting
+    - drm/msm/dsi: Fix number of regulators for msm8996_dsi_cfg
+    - platform/x86: pmc_atom: Fix SLP_TYPx bitfield mask
+    - iio: adc: mcp3911: make use of the sign bit
+    - ieee802154/adf7242: defer destroy_workqueue call
+    - wifi: cfg80211: debugfs: fix return type in ht40allow_map_read()
+    - Revert "xhci: turn off port power in shutdown"
+    - net: sched: tbf: don't call qdisc_put() while holding tree lock
+    - ethernet: rocker: fix sleep in atomic context bug in neigh_timer_handler
+    - kcm: fix strp_init() order and cleanup
+    - sch_cake: Return __NET_XMIT_STOLEN when consuming enqueued skb
+    - tcp: annotate data-race around challenge_timestamp
+    - Revert "sch_cake: Return __NET_XMIT_STOLEN when consuming enqueued skb"
+    - net/smc: Remove redundant refcount increase
+    - serial: fsl_lpuart: RS485 RTS polariy is inverse
+    - staging: rtl8712: fix use after free bugs
+    - powerpc: align syscall table for ppc32
+    - vt: Clear selection before changing the font
+    - tty: serial: lpuart: disable flow control while waiting for the transmit
+      engine to complete
+    - Input: iforce - wake up after clearing IFORCE_XMIT_RUNNING flag
+    - iio: adc: mcp3911: use correct formula for AD conversion
+    - misc: fastrpc: fix memory corruption on probe
+    - misc: fastrpc: fix memory corruption on open
+    - USB: serial: ftdi_sio: add Omron CS1W-CIF31 device id
+    - binder: fix UAF of ref->proc caused by race condition
+    - usb: dwc3: qcom: fix use-after-free on runtime-PM wakeup
+    - drm/i915/reg: Fix spelling mistake "Unsupport" -> "Unsupported"
+    - clk: core: Honor CLK_OPS_PARENT_ENABLE for clk gate ops
+    - Revert "clk: core: Honor CLK_OPS_PARENT_ENABLE for clk gate ops"
+    - clk: core: Fix runtime PM sequence in clk_core_unprepare()
+    - Input: rk805-pwrkey - fix module autoloading
+    - clk: bcm: rpi: Fix error handling of raspberrypi_fw_get_rate
+    - hwmon: (gpio-fan) Fix array out of bounds access
+    - gpio: pca953x: Add mutex_lock for regcache sync in PM
+    - thunderbolt: Use the actual buffer in tb_async_error()
+    - xhci: Add grace period after xHC start to prevent premature runtime suspend.
+    - USB: serial: cp210x: add Decagon UCA device id
+    - USB: serial: option: add support for OPPO R11 diag port
+    - USB: serial: option: add Quectel EM060K modem
+    - USB: serial: option: add support for Cinterion MV32-WA/WB RmNet mode
+    - usb: typec: altmodes/displayport: correct pin assignment for UFP receptacles
+    - usb: dwc2: fix wrong order of phy_power_on and phy_init
+    - USB: cdc-acm: Add Icom PMR F3400 support (0c26:0020)
+    - usb-storage: Add ignore-residue quirk for NXP PN7462AU
+    - s390/hugetlb: fix prepare_hugepage_range() check for 2 GB hugepages
+    - s390: fix nospec table alignments
+    - USB: core: Prevent nested device-reset calls
+    - usb: gadget: mass_storage: Fix cdrom data transfers on MAC-OS
+    - driver core: Don't probe devices after bus_type.match() probe deferral
+    - wifi: mac80211: Don't finalize CSA in IBSS mode if state is disconnected
+    - net: mac802154: Fix a condition in the receive path
+    - ALSA: seq: oss: Fix data-race for max_midi_devs access
+    - ALSA: seq: Fix data-race at module auto-loading
+    - drm/i915/glk: ECS Liva Q2 needs GLK HDMI port timing quirk
+    - btrfs: harden identification of a stale device
+    - usb: dwc3: fix PHY disable sequence
+    - usb: dwc3: disable USB core PHY management
+    - USB: serial: ch341: fix lost character on LCR updates
+    - USB: serial: ch341: fix disabled rx timer on older devices
+    - scsi: megaraid_sas: Fix double kfree()
+    - drm/gem: Fix GEM handle release errors
+    - drm/amdgpu: Check num_gfx_rings for gfx v9_0 rb setup.
+    - drm/radeon: add a force flush to delay work when radeon
+    - parisc: ccio-dma: Handle kmalloc failure in ccio_init_resources()
+    - parisc: Add runtime check to prevent PA2.0 kernels on PA1.x machines
+    - arm64: cacheinfo: Fix incorrect assignment of signed error value to unsigned
+      fw_level
+    - fbdev: chipsfb: Add missing pci_disable_device() in chipsfb_pci_init()
+    - drm/amdgpu: mmVM_L2_CNTL3 register not initialized correctly
+    - ALSA: emu10k1: Fix out of bounds access in snd_emu10k1_pcm_channel_alloc()
+    - ALSA: aloop: Fix random zeros in capture data when using jiffies timer
+    - ALSA: usb-audio: Fix an out-of-bounds bug in
+      __snd_usb_parse_audio_interface()
+    - kprobes: Prohibit probes in gate area
+    - debugfs: add debugfs_lookup_and_remove()
+    - nvmet: fix a use-after-free
+    - scsi: mpt3sas: Fix use-after-free warning
+    - scsi: lpfc: Add missing destroy_workqueue() in error path
+    - cgroup: Optimize single thread migration
+    - cgroup: Elide write-locking threadgroup_rwsem when updating csses on an
+      empty subtree
+    - cgroup: Fix threadgroup_rwsem <-> cpus_read_lock() deadlock
+    - smb3: missing inode locks in punch hole
+    - ARM: dts: imx6qdl-kontron-samx6i: remove duplicated node
+    - regulator: core: Clean up on enable failure
+    - RDMA/cma: Fix arguments order in net device validation
+    - soc: brcmstb: pm-arm: Fix refcount leak and __iomem leak bugs
+    - RDMA/hns: Fix supported page size
+    - netfilter: br_netfilter: Drop dst references before setting.
+    - rxrpc: Fix an insufficiently large sglist in rxkad_verify_packet_2()
+    - afs: Use the operation issue time instead of the reply time for callbacks
+    - sch_sfb: Don't assume the skb is still around after enqueueing to child
+    - tipc: fix shift wrapping bug in map_get()
+    - i40e: Fix kernel crash during module removal
+    - RDMA/siw: Pass a pointer to virt_to_page()
+    - ipv6: sr: fix out-of-bounds read when setting HMAC data.
+    - RDMA/mlx5: Set local port to one when accessing counters
+    - nvme-tcp: fix UAF when detecting digest errors
+    - tcp: fix early ETIMEDOUT after spurious non-SACK RTO
+    - sch_sfb: Also store skb len before calling child enqueue
+    - x86/nospec: Fix i386 RSB stuffing
+    - MIPS: loongson32: ls1c: Fix hang during startup
+    - Linux 5.4.213
+  * CVE-2022-2663
+    - netfilter: nf_conntrack_irc: Fix forged IP logic
+  * CVE-2022-3061
+    - video: fbdev: i740fb: Error out if 'pixclock' equals zero
+
+  [ Ubuntu: 5.4.0-132.148 ]
+
+  * CVE-2022-42719
+    - mac80211: mlme: find auth challenge directly
+    - wifi: mac80211: don't parse mbssid in assoc response
+    - wifi: mac80211: fix MBSSID parsing use-after-free
+  * iavf: SR-IOV VFs error with no traffic flow when MTU greater than 1500
+    (LP: #1983656)
+    - iavf: Fix set max MTU size with port VLAN and jumbo frames
+    - i40e: Fix VF set max MTU size
+  * fib_nexthop_nongw.sh from ubuntu_kernel_selftests failed on B-5.4
+    (LP: #1990800)
+    - SAUCE: selftests/net: skipping tests for older ip command releases
+  * CVE-2022-29901
+    - Revert "x86/speculation: Add RSB VM Exit protections"
+    - Revert "x86/cpu: Add a steppings field to struct x86_cpu_id"
+    - x86/devicetable: Move x86 specific macro out of generic code
+    - x86/cpu: Add consistent CPU match macros
+    - x86/cpu: Add a steppings field to struct x86_cpu_id
+    - x86/kvm/vmx: Make noinstr clean
+    - x86/cpufeatures: Move RETPOLINE flags to word 11
+    - x86/bugs: Report AMD retbleed vulnerability
+    - x86/bugs: Add AMD retbleed= boot parameter
+    - x86/bugs: Keep a per-CPU IA32_SPEC_CTRL value
+    - x86/entry: Remove skip_r11rcx
+    - x86/entry: Add kernel IBRS implementation
+    - x86/bugs: Optimize SPEC_CTRL MSR writes
+    - x86/speculation: Add spectre_v2=ibrs option to support Kernel IBRS
+    - x86/bugs: Split spectre_v2_select_mitigation() and
+      spectre_v2_user_select_mitigation()
+    - x86/bugs: Report Intel retbleed vulnerability
+    - intel_idle: Disable IBRS during long idle
+    - x86/speculation: Change FILL_RETURN_BUFFER to work with objtool
+    - x86/speculation: Fix RSB filling with CONFIG_RETPOLINE=n
+    - x86/speculation: Fix firmware entry SPEC_CTRL handling
+    - x86/speculation: Fix SPEC_CTRL write on SMT state change
+    - x86/speculation: Use cached host SPEC_CTRL value for guest entry/exit
+    - x86/speculation: Remove x86_spec_ctrl_mask
+    - KVM/VMX: Use TEST %REG,%REG instead of CMP $0,%REG in vmenter.S
+    - KVM/nVMX: Use __vmx_vcpu_run in nested_vmx_check_vmentry_hw
+    - KVM: VMX: Flatten __vmx_vcpu_run()
+    - KVM: VMX: Convert launched argument to flags
+    - KVM: VMX: Prevent guest RSB poisoning attacks with eIBRS
+    - KVM: VMX: Fix IBRS handling after vmexit
+    - x86/speculation: Fill RSB on vmexit for IBRS
+    - x86/common: Stamp out the stepping madness
+    - x86/cpu/amd: Enumerate BTC_NO
+    - x86/bugs: Add Cannon lake to RETBleed affected CPU list
+    - x86/speculation: Disable RRSBA behavior
+    - x86/speculation: Use DECLARE_PER_CPU for x86_spec_ctrl_current
+    - x86/bugs: Warn when "ibrs" mitigation is selected on Enhanced IBRS parts
+    - x86/speculation: Add RSB VM Exit protections
+  * ACPI: processor idle: Practically limit "Dummy wait" workaround to old Intel
+    systems (LP: #1990985)
+    - ACPI: processor_idle: Skip dummy wait if kernel is in guest
+    - ACPI: processor idle: Practically limit "Dummy wait" workaround to old Intel
+      systems
+  * cgroup: all controllers mounted when using 'cgroup_no_v1=' (LP: #1988584)
+    - cgroup-v1: add disabled controller check in cgroup1_parse_param()
+  * Focal update: v5.4.212 upstream stable release (LP: #1991156)
+    - audit: fix potential double free on error path from fsnotify_add_inode_mark
+    - parisc: Fix exception handler for fldw and fstw instructions
+    - kernel/sys_ni: add compat entry for fadvise64_64
+    - usb: cdns3: Fix issue for clear halt endpoint
+    - pinctrl: amd: Don't save/restore interrupt status and wake status bits
+    - sched/deadline: Unthrottle PI boosted threads while enqueuing
+    - sched/deadline: Fix stale throttling on de-/boosted tasks
+    - sched/deadline: Fix priority inheritance with multiple scheduling classes
+    - kernel/sched: Remove dl_boosted flag comment
+    - xfrm: fix refcount leak in __xfrm_policy_check()
+    - SUNRPC: RPC level errors should set task->tk_rpc_status
+    - rose: check NULL rose_loopback_neigh->loopback
+    - net/mlx5e: Properly disable vlan strip on non-UL reps
+    - net: moxa: get rid of asymmetry in DMA mapping/unmapping
+    - bonding: 802.3ad: fix no transmission of LACPDUs
+    - net: ipvtap - add __init/__exit annotations to module init/exit funcs
+    - netfilter: ebtables: reject blobs that don't provide all entry points
+    - bnxt_en: fix NQ resource accounting during vf creation on 57500 chips
+    - netfilter: nft_payload: report ERANGE for too long offset and length
+    - netfilter: nft_payload: do not truncate csum_offset and csum_type
+    - netfilter: nft_osf: restrict osf to ipv4, ipv6 and inet families
+    - netfilter: nft_tunnel: restrict it to netdev family
+    - net: Fix data-races around weight_p and dev_weight_[rt]x_bias.
+    - net: Fix data-races around netdev_tstamp_prequeue.
+    - ratelimit: Fix data-races in ___ratelimit().
+    - net: Fix a data-race around sysctl_tstamp_allow_data.
+    - net: Fix a data-race around sysctl_net_busy_poll.
+    - net: Fix a data-race around sysctl_net_busy_read.
+    - net: Fix a data-race around netdev_budget.
+    - net: Fix a data-race around netdev_budget_usecs.
+    - net: Fix a data-race around sysctl_somaxconn.
+    - ixgbe: stop resetting SYSTIME in ixgbe_ptp_start_cyclecounter
+    - btrfs: fix silent failure when deleting root reference
+    - btrfs: replace: drop assert for suspended replace
+    - btrfs: add info when mount fails due to stale replace target
+    - btrfs: check if root is readonly while setting security xattr
+    - x86/unwind/orc: Unwind ftrace trampolines with correct ORC entry
+    - loop: Check for overflow while configuring loop
+    - asm-generic: sections: refactor memory_intersects
+    - s390: fix double free of GS and RI CBs on fork() failure
+    - ACPI: processor: Remove freq Qos request for all CPUs
+    - mm/hugetlb: fix hugetlb not supporting softdirty tracking
+    - md: call __md_stop_writes in md_stop
+    - perf/x86/intel/uncore: Fix broken read_counter() for SNB IMC PMU
+    - scsi: storvsc: Remove WQ_MEM_RECLAIM from storvsc_error_wq
+    - mm: Force TLB flush for PFNMAP mappings before unlink_file_vma()
+    - s390/mm: do not trigger write fault when vma does not allow VM_WRITE
+    - x86/bugs: Add "unknown" reporting for MMIO Stale Data
+    - kbuild: Fix include path in scripts/Makefile.modpost
+    - Bluetooth: L2CAP: Fix build errors in some archs
+    - HID: steam: Prevent NULL pointer dereference in steam_{recv,send}_report
+    - udmabuf: Set the DMA mask for the udmabuf device (v2)
+    - media: pvrusb2: fix memory leak in pvr_probe
+    - HID: hidraw: fix memory leak in hidraw_release()
+    - fbdev: fb_pm2fb: Avoid potential divide by zero error
+    - ftrace: Fix NULL pointer dereference in is_ftrace_trampoline when ftrace is
+      dead
+    - bpf: Don't redirect packets with invalid pkt_len
+    - mm/rmap: Fix anon_vma->degree ambiguity leading to double-reuse
+    - btrfs: introduce btrfs_lookup_match_dir
+    - btrfs: do not pin logs too early during renames
+    - btrfs: unify lookup return value when dir entry is missing
+    - drm/amd/display: Avoid MPC infinite loop
+    - drm/amd/display: clear optc underflow before turn off odm clock
+    - neigh: fix possible DoS due to net iface start/stop loop
+    - s390/hypfs: avoid error message under KVM
+    - drm/amd/display: Fix pixel clock programming
+    - netfilter: conntrack: NF_CONNTRACK_PROCFS should no longer default to y
+    - btrfs: tree-checker: check for overlapping extent items
+    - lib/vdso: Let do_coarse() return 0 to simplify the callsite
+    - lib/vdso: Mark do_hres() and do_coarse() as __always_inline
+    - kprobes: don't call disarm_kprobe() for disabled kprobes
+    - net/af_packet: check len when min_header_len equals to 0
+    - net: neigh: don't call kfree_skb() under spin_lock_irqsave()
+    - Linux 5.4.212
+  * Focal update: v5.4.211 upstream stable release (LP: #1990190)
+    - Makefile: link with -z noexecstack --no-warn-rwx-segments
+    - x86: link vdso and boot with -z noexecstack --no-warn-rwx-segments
+    - scsi: Revert "scsi: qla2xxx: Fix disk failure to rediscover"
+    - ALSA: bcd2000: Fix a UAF bug on the error path of probing
+    - igc: Remove _I_PHY_ID checking
+    - wifi: mac80211_hwsim: fix race condition in pending packet
+    - wifi: mac80211_hwsim: add back erroneously removed cast
+    - wifi: mac80211_hwsim: use 32-bit skb cookie
+    - add barriers to buffer_uptodate and set_buffer_uptodate
+    - HID: wacom: Only report rotation for art pen
+    - HID: wacom: Don't register pad_input for touch switch
+    - KVM: nVMX: Snapshot pre-VM-Enter BNDCFGS for !nested_run_pending case
+    - KVM: nVMX: Snapshot pre-VM-Enter DEBUGCTL for !nested_run_pending case
+    - KVM: SVM: Don't BUG if userspace injects an interrupt with GIF=0
+    - KVM: nVMX: Let userspace set nVMX MSR to any _host_ supported value
+    - KVM: x86: Mark TSS busy during LTR emulation _after_ all fault checks
+    - KVM: x86: Set error code to segment selector on LLDT/LTR non-canonical #GP
+    - mm/mremap: hold the rmap lock in write mode when moving page table entries.
+    - ALSA: hda/conexant: Add quirk for LENOVO 20149 Notebook model
+    - ALSA: hda/cirrus - support for iMac 12,1 model
+    - ALSA: hda/realtek: Add quirk for another Asus K42JZ model
+    - tty: vt: initialize unicode screen buffer
+    - vfs: Check the truncate maximum size in inode_newsize_ok()
+    - fs: Add missing umask strip in vfs_tmpfile
+    - thermal: sysfs: Fix cooling_device_stats_setup() error code path
+    - fbcon: Fix boundary checks for fbcon=vc:n1-n2 parameters
+    - usbnet: Fix linkwatch use-after-free on disconnect
+    - ovl: drop WARN_ON() dentry is NULL in ovl_encode_fh()
+    - parisc: Fix device names in /proc/iomem
+    - parisc: io_pgetevents_time64() needs compat syscall in 32-bit compat mode
+    - drm/gem: Properly annotate WW context on drm_gem_lock_reservations() error
+    - drm/nouveau: fix another off-by-one in nvbios_addr
+    - drm/amdgpu: Check BO's requested pinning domains against its
+      preferred_domains
+    - iio: light: isl29028: Fix the warning in isl29028_remove()
+    - fuse: limit nsec
+    - serial: mvebu-uart: uart2 error bits clearing
+    - md-raid10: fix KASAN warning
+    - ia64, processor: fix -Wincompatible-pointer-types in ia64_get_irr()
+    - PCI: Add defines for normal and subtractive PCI bridges
+    - powerpc/fsl-pci: Fix Class Code of PCIe Root Port
+    - powerpc/ptdump: Fix display of RW pages on FSL_BOOK3E
+    - powerpc/powernv: Avoid crashing if rng is NULL
+    - MIPS: cpuinfo: Fix a warning for CONFIG_CPUMASK_OFFSTACK
+    - coresight: Clear the connection field properly
+    - USB: HCD: Fix URB giveback issue in tasklet function
+    - ARM: dts: uniphier: Fix USB interrupts for PXs2 SoC
+    - arm64: dts: uniphier: Fix USB interrupts for PXs3 SoC
+    - netfilter: nf_tables: fix null deref due to zeroed list head
+    - epoll: autoremove wakers even more aggressively
+    - x86: Handle idle=nomwait cmdline properly for x86_idle
+    - arm64: Do not forget syscall when starting a new thread.
+    - arm64: fix oops in concurrently setting insn_emulation sysctls
+    - ext2: Add more validity checks for inode counts
+    - genirq: Don't return error on missing optional irq_request_resources()
+    - wait: Fix __wait_event_hrtimeout for RT/DL tasks
+    - ARM: dts: imx6ul: add missing properties for sram
+    - ARM: dts: imx6ul: change operating-points to uint32-matrix
+    - ARM: dts: imx6ul: fix csi node compatible
+    - ARM: dts: imx6ul: fix lcdif node compatible
+    - ARM: dts: imx6ul: fix qspi node compatible
+    - spi: synquacer: Add missing clk_disable_unprepare()
+    - ARM: OMAP2+: display: Fix refcount leak bug
+    - ACPI: EC: Remove duplicate ThinkPad X1 Carbon 6th entry from DMI quirks
+    - ACPI: PM: save NVS memory for Lenovo G40-45
+    - ACPI: LPSS: Fix missing check in register_device_clock()
+    - arm64: dts: qcom: ipq8074: fix NAND node name
+    - arm64: dts: allwinner: a64: orangepi-win: Fix LED node name
+    - ARM: shmobile: rcar-gen2: Increase refcount for new reference
+    - PM: hibernate: defer device probing when resuming from hibernation
+    - selinux: Add boundary check in put_entry()
+    - spi: spi-rspi: Fix PIO fallback on RZ platforms
+    - ARM: findbit: fix overflowing offset
+    - meson-mx-socinfo: Fix refcount leak in meson_mx_socinfo_init
+    - ARM: bcm: Fix refcount leak in bcm_kona_smc_init
+    - x86/pmem: Fix platform-device leak in error path
+    - ARM: dts: ast2500-evb: fix board compatible
+    - ARM: dts: ast2600-evb: fix board compatible
+    - soc: fsl: guts: machine variable might be unset
+    - ARM: dts: qcom: mdm9615: add missing PMIC GPIO reg
+    - ARM: OMAP2+: Fix refcount leak in omapdss_init_of
+    - ARM: OMAP2+: Fix refcount leak in omap3xxx_prm_late_init
+    - cpufreq: zynq: Fix refcount leak in zynq_get_revision
+    - soc: qcom: aoss: Fix refcount leak in qmp_cooling_devices_register
+    - ARM: dts: qcom: pm8841: add required thermal-sensor-cells
+    - bus: hisi_lpc: fix missing platform_device_put() in hisi_lpc_acpi_probe()
+    - arm64: dts: mt7622: fix BPI-R64 WPS button
+    - erofs: avoid consecutive detection for Highmem memory
+    - blk-mq: don't create hctx debugfs dir until q->debugfs_dir is created
+    - regulator: of: Fix refcount leak bug in of_get_regulation_constraints()
+    - nohz/full, sched/rt: Fix missed tick-reenabling bug in dequeue_task_rt()
+    - thermal/tools/tmon: Include pthread and time headers in tmon.h
+    - dm: return early from dm_pr_call() if DM device is suspended
+    - ath10k: do not enforce interrupt trigger type
+    - wifi: rtlwifi: fix error codes in rtl_debugfs_set_write_h2c()
+    - drm/mipi-dbi: align max_chunk to 2 in spi_transfer
+    - drm/radeon: fix potential buffer overflow in ni_set_mc_special_registers()
+    - drm/mediatek: Add pull-down MIPI operation in mtk_dsi_poweroff function
+    - drm: adv7511: override i2c address of cec before accessing it
+    - i2c: Fix a potential use after free
+    - media: tw686x: Register the irq at the end of probe
+    - wifi: iwlegacy: 4965: fix potential off-by-one overflow in
+      il4965_rs_fill_link_cmd()
+    - drm: bridge: adv7511: Add check for mipi_dsi_driver_register
+    - drm/mcde: Fix refcount leak in mcde_dsi_bind
+    - media: hdpvr: fix error value returns in hdpvr_read
+    - drm/vc4: plane: Remove subpixel positioning check
+    - drm/vc4: plane: Fix margin calculations for the right/bottom edges
+    - drm/vc4: dsi: Correct DSI divider calculations
+    - crypto: arm64/gcm - Select AEAD for GHASH_ARM64_CE
+    - drm/rockchip: vop: Don't crash for invalid duplicate_state()
+    - drm/rockchip: Fix an error handling path rockchip_dp_probe()
+    - drm/mediatek: dpi: Remove output format of YUV
+    - drm/mediatek: dpi: Only enable dpi after the bridge is enabled
+    - drm: bridge: sii8620: fix possible off-by-one
+    - drm/msm/mdp5: Fix global state lock backoff
+    - crypto: hisilicon - Kunpeng916 crypto driver don't sleep when in softirq
+    - media: platform: mtk-mdp: Fix mdp_ipi_comm structure alignment
+    - mediatek: mt76: mac80211: Fix missing of_node_put() in mt76_led_init()
+    - drm/exynos/exynos7_drm_decon: free resources when clk_set_parent() failed.
+    - tcp: make retransmitted SKB fit into the send window
+    - libbpf: Fix the name of a reused map
+    - selftests: timers: valid-adjtimex: build fix for newer toolchains
+    - selftests: timers: clocksource-switch: fix passing errors from child
+    - fs: check FMODE_LSEEK to control internal pipe splicing
+    - wifi: wil6210: debugfs: fix info leak in wil_write_file_wmi()
+    - wifi: p54: Fix an error handling path in p54spi_probe()
+    - wifi: p54: add missing parentheses in p54_flush()
+    - selftests/bpf: fix a test for snprintf() overflow
+    - can: pch_can: do not report txerr and rxerr during bus-off
+    - can: rcar_can: do not report txerr and rxerr during bus-off
+    - can: sja1000: do not report txerr and rxerr during bus-off
+    - can: hi311x: do not report txerr and rxerr during bus-off
+    - can: sun4i_can: do not report txerr and rxerr during bus-off
+    - can: kvaser_usb_hydra: do not report txerr and rxerr during bus-off
+    - can: kvaser_usb_leaf: do not report txerr and rxerr during bus-off
+    - can: usb_8dev: do not report txerr and rxerr during bus-off
+    - can: error: specify the values of data[5..7] of CAN error frames
+    - can: pch_can: pch_can_error(): initialize errc before using it
+    - Bluetooth: hci_intel: Add check for platform_driver_register
+    - i2c: cadence: Support PEC for SMBus block read
+    - i2c: mux-gpmux: Add of_node_put() when breaking out of loop
+    - wifi: wil6210: debugfs: fix uninitialized variable use in
+      `wil_write_file_wmi()`
+    - wifi: iwlwifi: mvm: fix double list_add at iwl_mvm_mac_wake_tx_queue
+    - wifi: libertas: Fix possible refcount leak in if_usb_probe()
+    - net/mlx5e: Fix the value of MLX5E_MAX_RQ_NUM_MTTS
+    - crypto: inside-secure - Add missing MODULE_DEVICE_TABLE for of
+    - iavf: Fix max_rate limiting
+    - netdevsim: Avoid allocation warnings triggered from user space
+    - net: rose: fix netdev reference changes
+    - dccp: put dccp_qpolicy_full() and dccp_qpolicy_push() in the same lock
+    - clk: renesas: r9a06g032: Fix UART clkgrp bitsel
+    - mtd: maps: Fix refcount leak in of_flash_probe_versatile
+    - mtd: maps: Fix refcount leak in ap_flash_init
+    - mtd: rawnand: meson: Fix a potential double free issue
+    - HID: cp2112: prevent a buffer overflow in cp2112_xfer()
+    - mtd: sm_ftl: Fix deadlock caused by cancel_work_sync in sm_release
+    - mtd: partitions: Fix refcount leak in parse_redboot_of
+    - mtd: st_spi_fsm: Add a clk_disable_unprepare() in .probe()'s error path
+    - fpga: altera-pr-ip: fix unsigned comparison with less than zero
+    - usb: host: Fix refcount leak in ehci_hcd_ppc_of_probe
+    - usb: ohci-nxp: Fix refcount leak in ohci_hcd_nxp_probe
+    - usb: xhci: tegra: Fix error check
+    - clk: mediatek: reset: Fix written reset bit offset
+    - misc: rtsx: Fix an error handling path in rtsx_pci_probe()
+    - driver core: fix potential deadlock in __driver_attach
+    - clk: qcom: clk-krait: unlock spin after mux completion
+    - usb: host: xhci: use snprintf() in xhci_decode_trb()
+    - clk: qcom: ipq8074: fix NSS port frequency tables
+    - clk: qcom: ipq8074: set BRANCH_HALT_DELAY flag for UBI clocks
+    - clk: qcom: camcc-sdm845: Fix topology around titan_top power domain
+    - soundwire: bus_type: fix remove and shutdown support
+    - intel_th: Fix a resource leak in an error handling path
+    - intel_th: msu-sink: Potential dereference of null pointer
+    - intel_th: msu: Fix vmalloced buffers
+    - staging: rtl8192u: Fix sleep in atomic context bug in
+      dm_fsync_timer_callback
+    - mmc: sdhci-of-esdhc: Fix refcount leak in esdhc_signal_voltage_switch
+    - memstick/ms_block: Fix some incorrect memory allocation
+    - memstick/ms_block: Fix a memory leak
+    - mmc: sdhci-of-at91: fix set_uhs_signaling rewriting of MC1R
+    - scsi: smartpqi: Fix DMA direction for RAID requests
+    - usb: gadget: udc: amd5536 depends on HAS_DMA
+    - RDMA/hns: Fix incorrect clearing of interrupt status register
+    - RDMA/siw: Fix duplicated reported IW_CM_EVENT_CONNECT_REPLY event
+    - RDMA/hfi1: fix potential memory leak in setup_base_ctxt()
+    - gpio: gpiolib-of: Fix refcount bugs in of_mm_gpiochip_add_data()
+    - mmc: cavium-octeon: Add of_node_put() when breaking out of loop
+    - mmc: cavium-thunderx: Add of_node_put() when breaking out of loop
+    - HID: alps: Declare U1_UNICORN_LEGACY support
+    - PCI: tegra194: Fix Root Port interrupt handling
+    - PCI: tegra194: Fix link up retry sequence
+    - USB: serial: fix tty-port initialized comments
+    - platform/olpc: Fix uninitialized data in debugfs write
+    - mm/mmap.c: fix missing call to vm_unacct_memory in mmap_region
+    - RDMA/rxe: Fix error unwind in rxe_create_qp()
+    - null_blk: fix ida error handling in null_add_dev()
+    - jbd2: fix outstanding credits assert in jbd2_journal_commit_transaction()
+    - ext4: recover csum seed of tmp_inode after migrating to extents
+    - jbd2: fix assertion 'jh->b_frozen_data == NULL' failure when journal aborted
+    - opp: Fix error check in dev_pm_opp_attach_genpd()
+    - ASoC: mediatek: mt8173: Fix refcount leak in mt8173_rt5650_rt5676_dev_probe
+    - ASoC: mt6797-mt6351: Fix refcount leak in mt6797_mt6351_dev_probe
+    - ASoC: codecs: da7210: add check for i2c_add_driver
+    - ASoC: mediatek: mt8173-rt5650: Fix refcount leak in mt8173_rt5650_dev_probe
+    - serial: 8250_dw: Store LSR into lsr_saved_flags in dw8250_tx_wait_empty()
+    - ASoC: codecs: msm8916-wcd-digital: move gains from SX_TLV to S8_TLV
+    - ASoC: codecs: wcd9335: move gains from SX_TLV to S8_TLV
+    - profiling: fix shift too large makes kernel panic
+    - tty: n_gsm: fix non flow control frames during mux flow off
+    - tty: n_gsm: fix packet re-transmission without open control channel
+    - tty: n_gsm: fix race condition in gsmld_write()
+    - remoteproc: qcom: wcnss: Fix handling of IRQs
+    - vfio/ccw: Do not change FSM state in subchannel event
+    - tty: n_gsm: fix wrong T1 retry count handling
+    - tty: n_gsm: fix DM command
+    - tty: n_gsm: fix missing corner cases in gsmld_poll()
+    - iommu/exynos: Handle failed IOMMU device registration properly
+    - rpmsg: qcom_smd: Fix refcount leak in qcom_smd_parse_edge
+    - kfifo: fix kfifo_to_user() return type
+    - mfd: t7l66xb: Drop platform disable callback
+    - mfd: max77620: Fix refcount leak in max77620_initialise_fps
+    - iommu/arm-smmu: qcom_iommu: Add of_node_put() when breaking out of loop
+    - s390/zcore: fix race when reading from hardware system area
+    - ASoC: qcom: q6dsp: Fix an off-by-one in q6adm_alloc_copp()
+    - fuse: Remove the control interface for virtio-fs
+    - ASoC: audio-graph-card: Add of_node_put() in fail path
+    - watchdog: armada_37xx_wdt: check the return value of devm_ioremap() in
+      armada_37xx_wdt_probe()
+    - video: fbdev: amba-clcd: Fix refcount leak bugs
+    - video: fbdev: sis: fix typos in SiS_GetModeID()
+    - powerpc/32: Do not allow selection of e5500 or e6500 CPUs on PPC32
+    - powerpc/pci: Prefer PCI domain assignment via DT 'linux,pci-domain' and
+      alias
+    - powerpc/spufs: Fix refcount leak in spufs_init_isolated_loader
+    - powerpc/xive: Fix refcount leak in xive_get_max_prio
+    - powerpc/cell/axon_msi: Fix refcount leak in setup_msi_msg_address
+    - perf symbol: Fail to read phdr workaround
+    - kprobes: Forbid probing on trampoline and BPF code areas
+    - powerpc/pci: Fix PHB numbering when using opal-phbid
+    - genelf: Use HAVE_LIBCRYPTO_SUPPORT, not the never defined HAVE_LIBCRYPTO
+    - scripts/faddr2line: Fix vmlinux detection on arm64
+    - x86/numa: Use cpumask_available instead of hardcoded NULL check
+    - video: fbdev: arkfb: Fix a divide-by-zero bug in ark_set_pixclock()
+    - tools/thermal: Fix possible path truncations
+    - video: fbdev: vt8623fb: Check the size of screen before memset_io()
+    - video: fbdev: arkfb: Check the size of screen before memset_io()
+    - video: fbdev: s3fb: Check the size of screen before memset_io()
+    - scsi: zfcp: Fix missing auto port scan and thus missing target ports
+    - scsi: qla2xxx: Fix discovery issues in FC-AL topology
+    - scsi: qla2xxx: Turn off multi-queue for 8G adapters
+    - scsi: qla2xxx: Fix erroneous mailbox timeout after PCI error injection
+    - x86/olpc: fix 'logical not is only applied to the left hand side'
+    - spmi: trace: fix stack-out-of-bound access in SPMI tracing functions
+    - kexec, KEYS, s390: Make use of built-in and secondary keyring for signature
+      verification
+    - tpm: eventlog: Fix section mismatch for DEBUG_SECTION_MISMATCH
+    - btrfs: reset block group chunk force if we have to wait
+    - ext4: add EXT4_INODE_HAS_XATTR_SPACE macro in xattr.h
+    - ext4: make sure ext4_append() always allocates new block
+    - ext4: fix use-after-free in ext4_xattr_set_entry
+    - ext4: update s_overhead_clusters in the superblock during an on-line resize
+    - ext4: fix extent status tree race in writeback error recovery path
+    - ext4: correct max_inline_xattr_value_size computing
+    - ext4: correct the misjudgment in ext4_iget_extra_inode
+    - intel_th: pci: Add Raptor Lake-S CPU support
+    - intel_th: pci: Add Raptor Lake-S PCH support
+    - intel_th: pci: Add Meteor Lake-P support
+    - dm raid: fix address sanitizer warning in raid_resume
+    - dm raid: fix address sanitizer warning in raid_status
+    - dm thin: fix use-after-free crash in dm_sm_register_threshold_callback
+    - dm writecache: set a default MAX_WRITEBACK_JOBS
+    - ACPI: CPPC: Do not prevent CPPC from working in the future
+    - timekeeping: contribute wall clock to rng on time change
+    - firmware: arm_scpi: Ensure scpi_info is not assigned if the probe fails
+    - iommu/vt-d: avoid invalid memory access via node_online(NUMA_NO_NODE)
+    - btrfs: reject log replay if there is unsupported RO compat flag
+    - KVM: Add infrastructure and macro to mark VM as bugged
+    - KVM: x86: Check lapic_in_kernel() before attempting to set a SynIC irq
+    - KVM: x86: Avoid theoretical NULL pointer dereference in
+      kvm_irq_delivery_to_apic_fast()
+    - tcp: fix over estimation in sk_forced_mem_schedule()
+    - scsi: sg: Allow waiting for commands to complete on removed device
+    - Bluetooth: L2CAP: Fix l2cap_global_chan_by_psm regression
+    - net/9p: Initialize the iounit field during fid creation
+    - net_sched: cls_route: disallow handle of 0
+    - ALSA: info: Fix llseek return value when using callback
+    - rds: add missing barrier to release_refill
+    - ata: libata-eh: Add missing command name
+    - mmc: pxamci: Fix another error handling path in pxamci_probe()
+    - mmc: pxamci: Fix an error handling path in pxamci_probe()
+    - btrfs: fix lost error handling when looking up extended ref on log replay
+    - tracing: Have filter accept "common_cpu" to be consistent
+    - can: ems_usb: fix clang's -Wunaligned-access warning
+    - apparmor: fix quiet_denied for file rules
+    - apparmor: fix absroot causing audited secids to begin with =
+    - apparmor: Fix failed mount permission check error message
+    - apparmor: fix aa_label_asxprint return check
+    - apparmor: fix overlapping attachment computation
+    - apparmor: fix reference count leak in aa_pivotroot()
+    - apparmor: Fix memleak in aa_simple_write_to_buffer()
+    - Documentation: ACPI: EINJ: Fix obsolete example
+    - NFSv4.1: Don't decrease the value of seq_nr_highest_sent
+    - NFSv4.1: Handle NFS4ERR_DELAY replies to OP_SEQUENCE correctly
+    - NFSv4: Fix races in the legacy idmapper upcall
+    - NFSv4.1: RECLAIM_COMPLETE must handle EACCES
+    - NFSv4/pnfs: Fix a use-after-free bug in open
+    - can: mcp251x: Fix race condition on receive interrupt
+    - sunrpc: fix expiry of auth creds
+    - SUNRPC: Reinitialise the backchannel request buffers before reuse
+    - devlink: Fix use-after-free after a failed reload
+    - net: bgmac: Fix a BUG triggered by wrong bytes_compl
+    - pinctrl: nomadik: Fix refcount leak in nmk_pinctrl_dt_subnode_to_map
+    - pinctrl: qcom: msm8916: Allow CAMSS GP clocks to be muxed
+    - pinctrl: sunxi: Add I/O bias setting for H6 R-PIO
+    - ACPI: property: Return type of acpi_add_nondev_subnodes() should be bool
+    - geneve: do not use RT_TOS for IPv6 flowlabel
+    - plip: avoid rcu debug splat
+    - vsock: Fix memory leak in vsock_connect()
+    - vsock: Set socket state back to SS_UNCONNECTED in vsock_connect_timeout()
+    - dt-bindings: arm: qcom: fix MSM8916 MTP compatibles
+    - tools/vm/slabinfo: use alphabetic order when two values are equal
+    - tools build: Switch to new openssl API for test-libcrypto
+    - NTB: ntb_tool: uninitialized heap data in tool_fn_write()
+    - nfp: ethtool: fix the display error of `ethtool -m DEVNAME`
+    - xen/xenbus: fix return type in xenbus_file_read()
+    - atm: idt77252: fix use-after-free bugs caused by tst_timer
+    - dpaa2-eth: trace the allocated address instead of page struct
+    - tee: add overflow check in register_shm_helper()
+    - nios2: page fault et.al. are *not* restartable syscalls...
+    - nios2: don't leave NULLs in sys_call_table[]
+    - nios2: traced syscall does need to check the syscall number
+    - nios2: fix syscall restart checks
+    - nios2: restarts apply only to the first sigframe we build...
+    - nios2: add force_successful_syscall_return()
+    - iavf: Fix adminq error handling
+    - clk: rockchip: add sclk_mac_lbtest to rk3188_critical_clocks
+    - netfilter: nf_tables: really skip inactive sets when allocating name
+    - powerpc/pci: Fix get_phb_number() locking
+    - net: dsa: mv88e6060: prevent crash on an unused port
+    - net: moxa: pass pdev instead of ndev to DMA functions
+    - net: dsa: microchip: ksz9477: fix fdb_dump last invalid entry
+    - ice: Ignore EEXIST when setting promisc mode
+    - i40e: Fix to stop tx_timeout recovery if GLOBR fails
+    - fec: Fix timer capture timing in `fec_ptp_enable_pps()`
+    - igb: Add lock to avoid data race
+    - gcc-plugins: Undefine LATENT_ENTROPY_PLUGIN when plugin disabled for a file
+    - locking/atomic: Make test_and_*_bit() ordered on failure
+    - drm/meson: Fix refcount bugs in meson_vpu_has_available_connectors()
+    - PCI: Add ACS quirk for Broadcom BCM5750x NICs
+    - usb: cdns3 fix use-after-free at workaround 2
+    - usb: gadget: uvc: call uvc uvcg_warn on completed status instead of
+      uvcg_info
+    - irqchip/tegra: Fix overflow implicit truncation warnings
+    - drm/meson: Fix overflow implicit truncation warnings
+    - usb: host: ohci-ppc-of: Fix refcount leak bug
+    - usb: renesas: Fix refcount leak bug
+    - vboxguest: Do not use devm for irq
+    - clk: qcom: ipq8074: dont disable gcc_sleep_clk_src
+    - scsi: lpfc: Prevent buffer overflow crashes in debugfs with malformed user
+      input
+    - gadgetfs: ep_io - wait until IRQ finishes
+    - cxl: Fix a memory leak in an error handling path
+    - PCI/ACPI: Guard ARM64-specific mcfg_quirks
+    - um: add "noreboot" command line option for PANIC_TIMEOUT=-1 setups
+    - selftests/kprobe: Do not test for GRP/ without event failures
+    - dmaengine: sprd: Cleanup in .remove() after pm_runtime_get_sync() failed
+    - nvmet-tcp: fix lockdep complaint on nvmet_tcp_wq flush during queue teardown
+    - drivers:md:fix a potential use-after-free bug
+    - ext4: avoid remove directory when directory is corrupted
+    - ext4: avoid resizing to a partial cluster size
+    - lib/list_debug.c: Detect uninitialized lists
+    - tty: serial: Fix refcount leak bug in ucc_uart.c
+    - vfio: Clear the caps->buf to NULL after free
+    - mips: cavium-octeon: Fix missing of_node_put() in octeon2_usb_clocks_start
+    - riscv: mmap with PROT_WRITE but no PROT_READ is invalid
+    - RISC-V: Add fast call path of crash_kexec()
+    - watchdog: export lockup_detector_reconfigure
+    - powerpc/32: Don't always pass -mcpu=powerpc to the compiler
+    - ALSA: core: Add async signal helpers
+    - ALSA: timer: Use deferred fasync helper
+    - f2fs: fix to avoid use f2fs_bug_on() in f2fs_new_node_page()
+    - smb3: check xattr value length earlier
+    - powerpc/64: Init jump labels before parse_early_param()
+    - video: fbdev: i740fb: Check the argument of i740_calc_vclk()
+    - MIPS: tlbex: Explicitly compare _PAGE_NO_EXEC against 0
+    - tracing/probes: Have kprobes and uprobes use $COMM too
+    - can: j1939: j1939_sk_queue_activate_next_locked(): replace WARN_ON_ONCE with
+      netdev_warn_once()
+    - can: j1939: j1939_session_destroy(): fix memory leak of skbs
+    - btrfs: only write the sectors in the vertical stripe which has data stripes
+    - btrfs: raid56: don't trust any cached sector in __raid56_parity_recover()
+    - Linux 5.4.211
+  * CVE-2022-3028
+    - af_key: Do not call xfrm_probe_algs in parallel
+  * CVE-2022-2978
+    - fs: fix UAF/GPF bug in nilfs_mdt_destroy
+  * CVE-2022-40768
+    - scsi: stex: Properly zero out the passthrough command structure
+
+  [ Ubuntu: 5.4.0-131.147 ]
+
+  * CVE-2022-2602
+    - SAUCE: io_uring/af_unix: defer registered files gc to io_uring release
+    - SAUCE: io_uring/af_unix: fix memleak during unix GC
+  * CVE-2022-41674
+    - SAUCE: wifi: cfg80211: fix u8 overflow in
+      cfg80211_update_notlisted_nontrans()
+    - SAUCE: wifi: cfg80211/mac80211: reject bad MBSSID elements
+    - SAUCE: wifi: cfg80211: ensure length byte is present before access
+    - SAUCE: wifi: mac80211_hwsim: avoid mac80211 warning on bad rate
+    - SAUCE: wifi: cfg80211: update hidden BSSes to avoid WARN_ON
+  * CVE-2022-42721
+    - SAUCE: wifi: cfg80211: avoid nontransmitted BSS list corruption
+  * CVE-2022-42720
+    - SAUCE: wifi: cfg80211: fix BSS refcounting bugs
+
+  [ Ubuntu: 5.4.0-128.144 ]
+
+  * focal/linux: 5.4.0-128.144 -proposed tracker (LP: #1990152)
+  * CVE-2022-3176
+    - io_uring: disable polling pollfree files
+  * ip/nexthop: fix default address selection for connected nexthop
+    (LP: #1988809)
+    - selftests/net: test nexthop without gw
+  * ip/nexthop: fix default address selection for connected nexthop
+    (LP: #1988809) // icmp_redirect.sh in ubuntu_kernel_selftests failed on
+    Jammy 5.15.0-49.55 (LP: #1990124)
+    - ip: fix triggering of 'icmp redirect'
+
+  [ Ubuntu: 5.4.0-127.143 ]
+
+  * focal/linux: 5.4.0-127.143 -proposed tracker (LP: #1989892)
+  * Packaging resync (LP: #1786013)
+    - debian/dkms-versions -- update from kernel-versions (main/2022.09.19)
+  * [UBUNTU 20.04] mlx5 driver crashes on accessing device attributes during
+    recovery (LP: #1987287)
+    - net/mlx5: Avoid processing commands before cmdif is ready
+  * Focal update: v5.4.210 upstream stable release (LP: #1989230)
+    - thermal: Fix NULL pointer dereferences in of_thermal_ functions
+    - ACPI: video: Force backlight native for some TongFang devices
+    - ACPI: video: Shortening quirk list by identifying Clevo by board_name only
+    - ACPI: APEI: Better fix to avoid spamming the console with old error logs
+    - bpf: Verifer, adjust_scalar_min_max_vals to always call update_reg_bounds()
+    - selftests/bpf: Extend verifier and bpf_sock tests for dst_port loads
+    - bpf: Test_verifier, #70 error message updates for 32-bit right shift
+    - KVM: Don't null dereference ops->destroy
+    - selftests: KVM: Handle compiler optimizations in ucall
+    - media: v4l2-mem2mem: Apply DST_QUEUE_OFF_BASE on MMAP buffers across ioctls
+    - macintosh/adb: fix oob read in do_adb_query() function
+    - x86/speculation: Add RSB VM Exit protections
+    - x86/speculation: Add LFENCE to RSB fill sequence
+    - Linux 5.4.210
+  * Focal update: v5.4.209 upstream stable release (LP: #1989228)
+    - Bluetooth: L2CAP: Fix use-after-free caused by l2cap_chan_put
+    - ntfs: fix use-after-free in ntfs_ucsncmp()
+    - s390/archrandom: prevent CPACF trng invocations in interrupt context
+    - tcp: Fix data-races around sysctl_tcp_dsack.
+    - tcp: Fix a data-race around sysctl_tcp_app_win.
+    - tcp: Fix a data-race around sysctl_tcp_adv_win_scale.
+    - tcp: Fix a data-race around sysctl_tcp_frto.
+    - tcp: Fix a data-race around sysctl_tcp_nometrics_save.
+    - ice: check (DD | EOF) bits on Rx descriptor rather than (EOP | RS)
+    - ice: do not setup vlan for loopback VSI
+    - scsi: ufs: host: Hold reference returned by of_parse_phandle()
+    - tcp: Fix a data-race around sysctl_tcp_limit_output_bytes.
+    - tcp: Fix a data-race around sysctl_tcp_challenge_ack_limit.
+    - net: ping6: Fix memleak in ipv6_renew_options().
+    - ipv6/addrconf: fix a null-ptr-deref bug for ip6_ptr
+    - igmp: Fix data-races around sysctl_igmp_qrv.
+    - net: sungem_phy: Add of_node_put() for reference returned by of_get_parent()
+    - tcp: Fix a data-race around sysctl_tcp_min_tso_segs.
+    - tcp: Fix a data-race around sysctl_tcp_min_rtt_wlen.
+    - tcp: Fix a data-race around sysctl_tcp_autocorking.
+    - tcp: Fix a data-race around sysctl_tcp_invalid_ratelimit.
+    - Documentation: fix sctp_wmem in ip-sysctl.rst
+    - tcp: Fix a data-race around sysctl_tcp_comp_sack_delay_ns.
+    - tcp: Fix a data-race around sysctl_tcp_comp_sack_nr.
+    - i40e: Fix interface init with MSI interrupts (no MSI-X)
+    - sctp: fix sleep in atomic context bug in timer handlers
+    - virtio-net: fix the race between refill work and close
+    - perf symbol: Correct address for bss symbols
+    - sfc: disable softirqs for ptp TX
+    - sctp: leave the err path free in sctp_stream_init to sctp_stream_free
+    - ARM: crypto: comment out gcc warning that breaks clang builds
+    - mt7601u: add USB device ID for some versions of XiaoDu WiFi Dongle.
+    - scsi: core: Fix race between handling STS_RESOURCE and completion
+    - Linux 5.4.209
+  * Focal update: v5.4.208 upstream stable release (LP: #1988225)
+    - pinctrl: stm32: fix optional IRQ support to gpios
+    - riscv: add as-options for modules with assembly compontents
+    - mlxsw: spectrum_router: Fix IPv4 nexthop gateway indication
+    - lockdown: Fix kexec lockdown bypass with ima policy
+    - xen/gntdev: Ignore failure to unmap INVALID_GRANT_HANDLE
+    - PCI: hv: Fix multi-MSI to allow more than one MSI vector
+    - PCI: hv: Fix hv_arch_irq_unmask() for multi-MSI
+    - PCI: hv: Reuse existing IRTE allocation in compose_msi_msg()
+    - PCI: hv: Fix interrupt mapping for multi-MSI
+    - serial: mvebu-uart: correctly report configured baudrate value
+    - xfrm: xfrm_policy: fix a possible double xfrm_pols_put() in
+      xfrm_bundle_lookup()
+    - power/reset: arm-versatile: Fix refcount leak in versatile_reboot_probe
+    - pinctrl: ralink: Check for null return of devm_kcalloc
+    - perf/core: Fix data race between perf_event_set_output() and
+      perf_mmap_close()
+    - igc: Reinstate IGC_REMOVED logic and implement it properly
+    - ip: Fix data-races around sysctl_ip_no_pmtu_disc.
+    - ip: Fix data-races around sysctl_ip_fwd_use_pmtu.
+    - ip: Fix data-races around sysctl_ip_nonlocal_bind.
+    - ip: Fix a data-race around sysctl_fwmark_reflect.
+    - tcp/dccp: Fix a data-race around sysctl_tcp_fwmark_accept.
+    - tcp: Fix data-races around sysctl_tcp_mtu_probing.
+    - tcp: Fix data-races around sysctl_tcp_base_mss.
+    - tcp: Fix data-races around sysctl_tcp_min_snd_mss.
+    - tcp: Fix a data-race around sysctl_tcp_mtu_probe_floor.
+    - tcp: Fix a data-race around sysctl_tcp_probe_threshold.
+    - tcp: Fix a data-race around sysctl_tcp_probe_interval.
+    - i2c: cadence: Change large transfer count reset logic to be unconditional
+    - net: stmmac: fix dma queue left shift overflow issue
+    - net/tls: Fix race in TLS device down flow
+    - igmp: Fix data-races around sysctl_igmp_llm_reports.
+    - igmp: Fix a data-race around sysctl_igmp_max_memberships.
+    - tcp: Fix data-races around sysctl_tcp_syncookies.
+    - tcp: Fix data-races around sysctl_tcp_reordering.
+    - tcp: Fix data-races around some timeout sysctl knobs.
+    - tcp: Fix a data-race around sysctl_tcp_notsent_lowat.
+    - tcp: Fix a data-race around sysctl_tcp_tw_reuse.
+    - tcp: Fix data-races around sysctl_max_syn_backlog.
+    - tcp: Fix data-races around sysctl_tcp_fastopen.
+    - iavf: Fix handling of dummy receive descriptors
+    - i40e: Fix erroneous adapter reinitialization during recovery process
+    - ixgbe: Add locking to prevent panic when setting sriov_numvfs to zero
+    - gpio: pca953x: only use single read/write for No AI mode
+    - be2net: Fix buffer overflow in be_get_module_eeprom
+    - ipv4: Fix a data-race around sysctl_fib_multipath_use_neigh.
+    - udp: Fix a data-race around sysctl_udp_l3mdev_accept.
+    - tcp: Fix data-races around sysctl knobs related to SYN option.
+    - tcp: Fix a data-race around sysctl_tcp_early_retrans.
+    - tcp: Fix data-races around sysctl_tcp_recovery.
+    - tcp: Fix a data-race around sysctl_tcp_thin_linear_timeouts.
+    - tcp: Fix data-races around sysctl_tcp_slow_start_after_idle.
+    - tcp: Fix a data-race around sysctl_tcp_retrans_collapse.
+    - tcp: Fix a data-race around sysctl_tcp_stdurg.
+    - tcp: Fix a data-race around sysctl_tcp_rfc1337.
+    - tcp: Fix data-races around sysctl_tcp_max_reordering.
+    - spi: bcm2835: bcm2835_spi_handle_err(): fix NULL pointer deref for non DMA
+      transfers
+    - mm/mempolicy: fix uninit-value in mpol_rebind_policy()
+    - bpf: Make sure mac_header was set before using it
+    - dlm: fix pending remove if msg allocation fails
+    - ima: remove the IMA_TEMPLATE Kconfig option
+    - [Config] updateconfigs for IMA_TEMPLATE
+    - locking/refcount: Define constants for saturation and max refcount values
+    - locking/refcount: Ensure integer operands are treated as signed
+    - locking/refcount: Remove unused refcount_*_checked() variants
+    - locking/refcount: Move the bulk of the REFCOUNT_FULL implementation into the
+      <linux/refcount.h> header
+    - locking/refcount: Improve performance of generic REFCOUNT_FULL code
+    - locking/refcount: Move saturation warnings out of line
+    - locking/refcount: Consolidate REFCOUNT_{MAX,SATURATED} definitions
+    - locking/refcount: Consolidate implementations of refcount_t
+    - [Config] updateconfigs for REFCOUNT_FULL
+    - x86: get rid of small constant size cases in raw_copy_{to,from}_user()
+    - x86/uaccess: Implement macros for CMPXCHG on user addresses
+    - mmap locking API: initial implementation as rwsem wrappers
+    - x86/mce: Deduplicate exception handling
+    - bitfield.h: Fix "type of reg too small for mask" test
+    - ALSA: memalloc: Align buffer allocations in page size
+    - Bluetooth: Add bt_skb_sendmsg helper
+    - Bluetooth: Add bt_skb_sendmmsg helper
+    - Bluetooth: SCO: Replace use of memcpy_from_msg with bt_skb_sendmsg
+    - Bluetooth: RFCOMM: Replace use of memcpy_from_msg with bt_skb_sendmmsg
+    - Bluetooth: Fix passing NULL to PTR_ERR
+    - Bluetooth: SCO: Fix sco_send_frame returning skb->len
+    - Bluetooth: Fix bt_skb_sendmmsg not allocating partial chunks
+    - tty: drivers/tty/, stop using tty_schedule_flip()
+    - tty: the rest, stop using tty_schedule_flip()
+    - tty: drop tty_schedule_flip()
+    - tty: extract tty_flip_buffer_commit() from tty_flip_buffer_push()
+    - tty: use new tty_insert_flip_string_and_push_buffer() in pty_write()
+    - x86: drop bogus "cc" clobber from __try_cmpxchg_user_asm()
+    - Linux 5.4.208
+  * Focal update: v5.4.207 upstream stable release (LP: #1988219)
+    - ALSA: hda - Add fixup for Dell Latitidue E5430
+    - ALSA: hda/conexant: Apply quirk for another HP ProDesk 600 G3 model
+    - ALSA: hda/realtek - Fix headset mic problem for a HP machine with alc671
+    - ALSA: hda/realtek - Fix headset mic problem for a HP machine with alc221
+    - ALSA: hda/realtek - Enable the headset-mic on a Xiaomi's laptop
+    - xen/netback: avoid entering xenvif_rx_next_skb() with an empty rx queue
+    - tracing/histograms: Fix memory leak problem
+    - net: sock: tracing: Fix sock_exceed_buf_limit not to dereference stale
+      pointer
+    - ip: fix dflt addr selection for connected nexthop
+    - ARM: 9213/1: Print message about disabled Spectre workarounds only once
+    - ARM: 9214/1: alignment: advance IT state after emulating Thumb instruction
+    - wifi: mac80211: fix queue selection for mesh/OCB interfaces
+    - cgroup: Use separate src/dst nodes when preloading css_sets for migration
+    - drm/panfrost: Fix shrinker list corruption by madvise IOCTL
+    - nilfs2: fix incorrect masking of permission flags for symlinks
+    - Revert "evm: Fix memleak in init_desc"
+    - sched/rt: Disable RT_RUNTIME_SHARE by default
+    - ext4: fix race condition between ext4_write and ext4_convert_inline_data
+    - ARM: dts: imx6qdl-ts7970: Fix ngpio typo and count
+    - ARM: 9209/1: Spectre-BHB: avoid pr_info() every time a CPU comes out of idle
+    - ARM: 9210/1: Mark the FDT_FIXED sections as shareable
+    - drm/i915: fix a possible refcount leak in intel_dp_add_mst_connector()
+    - ima: Fix a potential integer overflow in ima_appraise_measurement
+    - ASoC: sgtl5000: Fix noise on shutdown/remove
+    - net: stmmac: dwc-qos: Disable split header for Tegra194
+    - inetpeer: Fix data-races around sysctl.
+    - net: Fix data-races around sysctl_mem.
+    - cipso: Fix data-races around sysctl.
+    - icmp: Fix data-races around sysctl.
+    - ipv4: Fix a data-race around sysctl_fib_sync_mem.
+    - ARM: dts: at91: sama5d2: Fix typo in i2s1 node
+    - ARM: dts: sunxi: Fix SPI NOR campatible on Orange Pi Zero
+    - drm/i915/gt: Serialize TLB invalidates with GT resets
+    - icmp: Fix a data-race around sysctl_icmp_ratelimit.
+    - icmp: Fix a data-race around sysctl_icmp_ratemask.
+    - raw: Fix a data-race around sysctl_raw_l3mdev_accept.
+    - ipv4: Fix data-races around sysctl_ip_dynaddr.
+    - net: ftgmac100: Hold reference returned by of_get_child_by_name()
+    - sfc: fix use after free when disabling sriov
+    - seg6: fix skb checksum evaluation in SRH encapsulation/insertion
+    - seg6: fix skb checksum in SRv6 End.B6 and End.B6.Encaps behaviors
+    - seg6: bpf: fix skb checksum in bpf_push_seg6_encap()
+    - sfc: fix kernel panic when creating VF
+    - mm: sysctl: fix missing numa_stat when !CONFIG_HUGETLB_PAGE
+    - virtio_mmio: Add missing PM calls to freeze/restore
+    - virtio_mmio: Restore guest page size on resume
+    - netfilter: br_netfilter: do not skip all hooks with 0 priority
+    - cpufreq: pmac32-cpufreq: Fix refcount leak bug
+    - platform/x86: hp-wmi: Ignore Sanitization Mode event
+    - net: tipc: fix possible refcount leak in tipc_sk_create()
+    - NFC: nxp-nci: don't print header length mismatch on i2c error
+    - nvme: fix regression when disconnect a recovering ctrl
+    - net: sfp: fix memory leak in sfp_probe()
+    - ASoC: ops: Fix off by one in range control validation
+    - ASoC: wm5110: Fix DRE control
+    - ASoC: cs47l15: Fix event generation for low power mux control
+    - ASoC: madera: Fix event generation for OUT1 demux
+    - ASoC: madera: Fix event generation for rate controls
+    - irqchip: or1k-pic: Undefine mask_ack for level triggered hardware
+    - x86: Clear .brk area at early boot
+    - soc: ixp4xx/npe: Fix unused match warning
+    - ARM: dts: stm32: use the correct clock source for CEC on stm32mp151
+    - signal handling: don't use BUG_ON() for debugging
+    - USB: serial: ftdi_sio: add Belimo device ids
+    - usb: typec: add missing uevent when partner support PD
+    - usb: dwc3: gadget: Fix event pending check
+    - tty: serial: samsung_tty: set dma burst_size to 1
+    - serial: 8250: fix return error code in serial8250_request_std_resource()
+    - serial: stm32: Clear prev values before setting RTS delays
+    - serial: pl011: UPSTAT_AUTORTS requires .throttle/unthrottle
+    - can: m_can: m_can_tx_handler(): fix use after free of skb
+    - Linux 5.4.207
+  * Focal update: v5.4.206 upstream stable release (LP: #1988215)
+    - Linux 5.4.206
+  * Focal update: v5.4.205 upstream stable release (LP: #1988214)
+    - esp: limit skb_page_frag_refill use to a single page
+    - mm/slub: add missing TID updates on slab deactivation
+    - can: bcm: use call_rcu() instead of costly synchronize_rcu()
+    - can: grcan: grcan_probe(): remove extra of_node_get()
+    - can: gs_usb: gs_usb_open/close(): fix memory leak
+    - usbnet: fix memory leak in error case
+    - net: rose: fix UAF bug caused by rose_t0timer_expiry
+    - iommu/vt-d: Fix PCI bus rescan device hot add
+    - fbdev: fbmem: Fix logo center image dx issue
+    - video: of_display_timing.h: include errno.h
+    - powerpc/powernv: delay rng platform device creation until later in boot
+    - can: kvaser_usb: replace run-time checks with struct kvaser_usb_driver_info
+    - can: kvaser_usb: kvaser_usb_leaf: fix CAN clock frequency regression
+    - can: kvaser_usb: kvaser_usb_leaf: fix bittiming limits
+    - xfs: remove incorrect ASSERT in xfs_rename
+    - ARM: meson: Fix refcount leak in meson_smp_prepare_cpus
+    - pinctrl: sunxi: a83t: Fix NAND function name for some pins
+    - pinctrl: sunxi: sunxi_pconf_set: use correct offset
+    - ARM: at91: pm: use proper compatible for sama5d2's rtc
+    - ARM: at91: pm: use proper compatibles for sam9x60's rtc and rtt
+    - ibmvnic: Properly dispose of all skbs during a failover.
+    - selftests: forwarding: fix flood_unicast_test when h2 supports
+      IFF_UNICAST_FLT
+    - selftests: forwarding: fix learning_test when h1 supports IFF_UNICAST_FLT
+    - selftests: forwarding: fix error message in learning_test
+    - i2c: cadence: Unregister the clk notifier in error path
+    - dmaengine: imx-sdma: Allow imx8m for imx7 FW revs
+    - misc: rtsx_usb: fix use of dma mapped buffer for usb bulk transfer
+    - misc: rtsx_usb: use separate command and response buffers
+    - misc: rtsx_usb: set return value in rsp_buf alloc err path
+    - dt-bindings: dma: allwinner,sun50i-a64-dma: Fix min/max typo
+    - ida: don't use BUG_ON() for debugging
+    - dmaengine: pl330: Fix lockdep warning about non-static key
+    - dmaengine: at_xdma: handle errors of at_xdmac_alloc_desc() correctly
+    - dmaengine: ti: Fix refcount leak in ti_dra7_xbar_route_allocate
+    - dmaengine: ti: Add missing put_device in ti_dra7_xbar_route_allocate
+    - Linux 5.4.205
+  * Focal update: v5.4.204 upstream stable release (LP: #1988212)
+    - ipv6: take care of disable_policy when restoring routes
+    - nvdimm: Fix badblocks clear off-by-one error
+    - powerpc/prom_init: Fix kernel config grep
+    - powerpc/bpf: Fix use of user_pt_regs in uapi
+    - dm raid: fix accesses beyond end of raid member array
+    - dm raid: fix KASAN warning in raid5_add_disks
+    - s390/archrandom: simplify back to earlier design and initialize earlier
+    - SUNRPC: Fix READ_PLUS crasher
+    - net: rose: fix UAF bugs caused by timer handler
+    - net: usb: ax88179_178a: Fix packet receiving
+    - virtio-net: fix race between ndo_open() and virtio_device_ready()
+    - selftests/net: pass ipv6_args to udpgso_bench's IPv6 TCP test
+    - net: tun: unlink NAPI from device on destruction
+    - net: tun: stop NAPI when detaching queues
+    - RDMA/qedr: Fix reporting QP timeout attribute
+    - linux/dim: Fix divide by 0 in RDMA DIM
+    - usbnet: fix memory allocation in helpers
+    - net: ipv6: unexport __init-annotated seg6_hmac_net_init()
+    - caif_virtio: fix race between virtio_device_ready() and ndo_open()
+    - PM / devfreq: exynos-ppmu: Fix refcount leak in of_get_devfreq_events
+    - s390: remove unneeded 'select BUILD_BIN2C'
+    - netfilter: nft_dynset: restore set element counter when failing to update
+    - net/sched: act_api: Notify user space if any actions were flushed before
+      error
+    - net: bonding: fix possible NULL deref in rlb code
+    - net: bonding: fix use-after-free after 802.3ad slave unbind
+    - nfc: nfcmrvl: Fix irq_of_parse_and_map() return value
+    - NFC: nxp-nci: Don't issue a zero length i2c_master_read()
+    - net: tun: avoid disabling NAPI twice
+    - xen/gntdev: Avoid blocking in unmap_grant_pages()
+    - hwmon: (ibmaem) don't call platform_device_del() if platform_device_add()
+      fails
+    - net: dsa: bcm_sf2: force pause link settings
+    - sit: use min
+    - ipv6/sit: fix ipip6_tunnel_get_prl return value
+    - rseq/selftests,x86_64: Add rseq_offset_deref_addv()
+    - selftests/rseq: remove ARRAY_SIZE define from individual tests
+    - selftests/rseq: introduce own copy of rseq uapi header
+    - selftests/rseq: Remove useless assignment to cpu variable
+    - selftests/rseq: Remove volatile from __rseq_abi
+    - selftests/rseq: Introduce rseq_get_abi() helper
+    - selftests/rseq: Introduce thread pointer getters
+    - selftests/rseq: Uplift rseq selftests for compatibility with glibc-2.35
+    - selftests/rseq: Fix ppc32: wrong rseq_cs 32-bit field pointer on big endian
+    - selftests/rseq: Fix ppc32 missing instruction selection "u" and "x" for
+      load/store
+    - selftests/rseq: Fix ppc32 offsets by using long rather than off_t
+    - selftests/rseq: Fix warnings about #if checks of undefined tokens
+    - selftests/rseq: Remove arm/mips asm goto compiler work-around
+    - selftests/rseq: Fix: work-around asm goto compiler bugs
+    - selftests/rseq: x86-64: use %fs segment selector for accessing rseq thread
+      area
+    - selftests/rseq: x86-32: use %gs segment selector for accessing rseq thread
+      area
+    - selftests/rseq: Change type of rseq_offset to ptrdiff_t
+    - xen/blkfront: fix leaking data in shared pages
+    - xen/netfront: fix leaking data in shared pages
+    - xen/netfront: force data bouncing when backend is untrusted
+    - xen/blkfront: force data bouncing when backend is untrusted
+    - xen/arm: Fix race in RB-tree based P2M accounting
+    - net: usb: qmi_wwan: add Telit 0x1060 composition
+    - net: usb: qmi_wwan: add Telit 0x1070 composition
+    - clocksource/drivers/ixp4xx: remove EXPORT_SYMBOL_GPL from
+      ixp4xx_timer_setup()
+    - Linux 5.4.204
+
+  [ Ubuntu: 5.4.0-126.142 ]
+
+  * focal/linux: 5.4.0-126.142 -proposed tracker (LP: #1987819)
+  * [SRU] fnic driver on needs to be updated to 1.6.0.53 on Focal (LP: #1984011)
+    - scsi: fnic: Change shost_printk() to FNIC_FCS_DBG()
+    - scsi: fnic: Avoid looping in TRANS ETH on unload
+    - scsi: fnic: Change shost_printk() to FNIC_MAIN_DBG()
+    - scsi: fnic: Set scsi_set_resid() only for underflow
+    - scsi: fnic: Validate io_req before others
+  * Focal update: v5.4.203 upstream stable release (LP: #1986999)
+    - drm: remove drm_fb_helper_modinit
+    - powerpc/ftrace: Remove ftrace init tramp once kernel init is complete
+    - kexec_file: drop weak attribute from arch_kexec_apply_relocations[_add]
+    - net: mscc: ocelot: allow unregistered IP multicast flooding
+    - ARM: 8989/1: use .fpu assembler directives instead of assembler arguments
+    - ARM: 8990/1: use VFP assembler mnemonics in register load/store macros
+    - ARM: 8971/1: replace the sole use of a symbol with its definition
+    - crypto: arm/sha256-neon - avoid ADRL pseudo instruction
+    - crypto: arm/sha512-neon - avoid ADRL pseudo instruction
+    - ARM: 8933/1: replace Sun/Solaris style flag on section directive
+    - ARM: 8929/1: use APSR_nzcv instead of r15 as mrc operand
+    - ARM: OMAP2+: drop unnecessary adrl
+    - ARM: 9029/1: Make iwmmxt.S support Clang's integrated assembler
+    - crypto: arm - use Kconfig based compiler checks for crypto opcodes
+    - crypto: arm/ghash-ce - define fpu before fpu registers are referenced
+    - Linux 5.4.203
+  * Focal update: v5.4.202 upstream stable release (LP: #1986995)
+    - random: schedule mix_interrupt_randomness() less often
+    - ALSA: hda/via: Fix missing beep setup
+    - ALSA: hda/conexant: Fix missing beep setup
+    - ALSA: hda/realtek - ALC897 headset MIC no sound
+    - ALSA: hda/realtek: Add quirk for Clevo PD70PNT
+    - net: openvswitch: fix parsing of nw_proto for IPv6 fragments
+    - mmc: sdhci-pci-o2micro: Fix card detect by dealing with debouncing
+    - ata: libata: add qc->flags in ata_qc_complete_template tracepoint
+    - dm era: commit metadata in postsuspend after worker stops
+    - dm mirror log: clear log bits up to BITS_PER_LONG boundary
+    - random: quiet urandom warning ratelimit suppression message
+    - USB: serial: option: add Telit LE910Cx 0x1250 composition
+    - USB: serial: option: add Quectel EM05-G modem
+    - USB: serial: option: add Quectel RM500K module support
+    - bpf: Fix request_sock leak in sk lookup helpers
+    - phy: aquantia: Fix AN when higher speeds than 1G are not advertised
+    - bonding: ARP monitor spams NETDEV_NOTIFY_PEERS notifiers
+    - net/sched: sch_netem: Fix arithmetic in netem_dump() for 32-bit platforms
+    - drm/msm/mdp4: Fix refcount leak in mdp4_modeset_init_intf
+    - erspan: do not assume transport header is always set
+    - net/tls: fix tls_sk_proto_close executed repeatedly
+    - udmabuf: add back sanity check
+    - x86/xen: Remove undefined behavior in setup_features()
+    - MIPS: Remove repetitive increase irq_err_count
+    - afs: Fix dynamic root getattr
+    - ice: ethtool: advertise 1000M speeds properly
+    - regmap-irq: Fix a bug in regmap_irq_enable() for type_in_mask chips
+    - igb: Make DMA faster when CPU is active on the PCIe link
+    - virtio_net: fix xdp_rxq_info bug after suspend/resume
+    - Revert "net/tls: fix tls_sk_proto_close executed repeatedly"
+    - gpio: winbond: Fix error code in winbond_gpio_get()
+    - s390/cpumf: Handle events cycles and instructions identical
+    - iio: adc: vf610: fix conversion mode sysfs node name
+    - xhci: turn off port power in shutdown
+    - usb: chipidea: udc: check request status before setting device address
+    - iio:chemical:ccs811: rearrange iio trigger get and register
+    - iio:accel:bma180: rearrange iio trigger get and register
+    - iio:accel:mxc4005: rearrange iio trigger get and register
+    - iio: accel: mma8452: ignore the return value of reset operation
+    - iio: gyro: mpu3050: Fix the error handling in mpu3050_power_up()
+    - iio: trigger: sysfs: fix use-after-free on remove
+    - iio: adc: stm32: fix maximum clock rate for stm32mp15x
+    - iio: adc: axp288: Override TS pin bias current for some models
+    - xtensa: xtfpga: Fix refcount leak bug in setup
+    - xtensa: Fix refcount leak bug in time.c
+    - parisc: Enable ARCH_HAS_STRICT_MODULE_RWX
+    - powerpc: Enable execve syscall exit tracepoint
+    - powerpc/rtas: Allow ibm,platform-dump RTAS call with null buffer address
+    - powerpc/powernv: wire up rng during setup_arch
+    - ARM: dts: imx6qdl: correct PU regulator ramp delay
+    - ARM: exynos: Fix refcount leak in exynos_map_pmu
+    - soc: bcm: brcmstb: pm: pm-arm: Fix refcount leak in brcmstb_pm_probe
+    - ARM: Fix refcount leak in axxia_boot_secondary
+    - ARM: cns3xxx: Fix refcount leak in cns3xxx_init
+    - modpost: fix section mismatch check for exported init/exit sections
+    - random: update comment from copy_to_user() -> copy_to_iter()
+    - kbuild: link vmlinux only once for CONFIG_TRIM_UNUSED_KSYMS (2nd attempt)
+    - powerpc/pseries: wire up rng during setup_arch()
+    - Linux 5.4.202
+  * Focal update: v5.4.201 upstream stable release (LP: #1986993)
+    - dm: remove special-casing of bio-based immutable singleton target on NVMe
+    - usb: gadget: u_ether: fix regression in setting fixed MAC address
+    - tcp: add some entropy in __inet_hash_connect()
+    - tcp: use different parts of the port_offset for index and offset
+    - tcp: add small random increments to the source port
+    - tcp: dynamically allocate the perturb table used by source ports
+    - tcp: increase source port perturb table to 2^16
+    - tcp: drop the hash_32() part from the index calculation
+    - arm64: mm: Don't invalidate FROM_DEVICE buffers at start of DMA transfer
+    - Linux 5.4.201
+  * Focal update: v5.4.200 upstream stable release (LP: #1983152)
+    - Revert "UBUNTU: SAUCE: random: Make getrandom() ready earlier"
+    - 9p: missing chunk of "fs/9p: Don't update file type when updating file
+      attributes"
+    - bpf: Fix incorrect memory charge cost calculation in stack_map_alloc()
+    - nfc: st21nfca: fix incorrect sizing calculations in EVT_TRANSACTION
+    - crypto: blake2s - generic C library implementation and selftest
+    - lib/crypto: blake2s: move hmac construction into wireguard
+    - lib/crypto: sha1: re-roll loops to reduce code size
+    - compat_ioctl: remove /dev/random commands
+    - random: don't forget compat_ioctl on urandom
+    - random: Don't wake crng_init_wait when crng_init == 1
+    - random: Add a urandom_read_nowait() for random APIs that don't warn
+    - random: add GRND_INSECURE to return best-effort non-cryptographic bytes
+    - random: ignore GRND_RANDOM in getentropy(2)
+    - random: make /dev/random be almost like /dev/urandom
+    - random: remove the blocking pool
+    - random: delete code to pull data into pools
+    - random: remove kernel.random.read_wakeup_threshold
+    - random: remove unnecessary unlikely()
+    - random: convert to ENTROPY_BITS for better code readability
+    - random: Add and use pr_fmt()
+    - random: fix typo in add_timer_randomness()
+    - random: remove some dead code of poolinfo
+    - random: split primary/secondary crng init paths
+    - random: avoid warnings for !CONFIG_NUMA builds
+    - x86: Remove arch_has_random, arch_has_random_seed
+    - powerpc: Remove arch_has_random, arch_has_random_seed
+    - s390: Remove arch_has_random, arch_has_random_seed
+    - linux/random.h: Remove arch_has_random, arch_has_random_seed
+    - linux/random.h: Use false with bool
+    - linux/random.h: Mark CONFIG_ARCH_RANDOM functions __must_check
+    - powerpc: Use bool in archrandom.h
+    - random: add arch_get_random_*long_early()
+    - random: avoid arch_get_random_seed_long() when collecting IRQ randomness
+    - random: remove dead code left over from blocking pool
+    - MAINTAINERS: co-maintain random.c
+    - crypto: blake2s - include <linux/bug.h> instead of <asm/bug.h>
+    - crypto: blake2s - adjust include guard naming
+    - random: document add_hwgenerator_randomness() with other input functions
+    - random: remove unused irq_flags argument from add_interrupt_randomness()
+    - random: use BLAKE2s instead of SHA1 in extraction
+    - random: do not sign extend bytes for rotation when mixing
+    - random: do not re-init if crng_reseed completes before primary init
+    - random: mix bootloader randomness into pool
+    - random: harmonize "crng init done" messages
+    - random: use IS_ENABLED(CONFIG_NUMA) instead of ifdefs
+    - random: initialize ChaCha20 constants with correct endianness
+    - random: early initialization of ChaCha constants
+    - random: avoid superfluous call to RDRAND in CRNG extraction
+    - random: don't reset crng_init_cnt on urandom_read()
+    - random: fix typo in comments
+    - random: cleanup poolinfo abstraction
+    - random: cleanup integer types
+    - random: remove incomplete last_data logic
+    - random: remove unused extract_entropy() reserved argument
+    - random: rather than entropy_store abstraction, use global
+    - random: remove unused OUTPUT_POOL constants
+    - random: de-duplicate INPUT_POOL constants
+    - random: prepend remaining pool constants with POOL_
+    - random: cleanup fractional entropy shift constants
+    - random: access input_pool_data directly rather than through pointer
+    - random: selectively clang-format where it makes sense
+    - random: simplify arithmetic function flow in account()
+    - random: continually use hwgenerator randomness
+    - random: access primary_pool directly rather than through pointer
+    - random: only call crng_finalize_init() for primary_crng
+    - random: use computational hash for entropy extraction
+    - random: simplify entropy debiting
+    - random: use linear min-entropy accumulation crediting
+    - random: always wake up entropy writers after extraction
+    - random: make credit_entropy_bits() always safe
+    - random: remove use_input_pool parameter from crng_reseed()
+    - random: remove batched entropy locking
+    - random: fix locking in crng_fast_load()
+    - random: use RDSEED instead of RDRAND in entropy extraction
+    - random: get rid of secondary crngs
+    - random: inline leaves of rand_initialize()
+    - random: ensure early RDSEED goes through mixer on init
+    - random: do not xor RDRAND when writing into /dev/random
+    - random: absorb fast pool into input pool after fast load
+    - random: use simpler fast key erasure flow on per-cpu keys
+    - random: use hash function for crng_slow_load()
+    - random: make more consistent use of integer types
+    - random: remove outdated INT_MAX >> 6 check in urandom_read()
+    - random: zero buffer after reading entropy from userspace
+    - random: fix locking for crng_init in crng_reseed()
+    - random: tie batched entropy generation to base_crng generation
+    - random: remove ifdef'd out interrupt bench
+    - random: remove unused tracepoints
+    - random: add proper SPDX header
+    - random: deobfuscate irq u32/u64 contributions
+    - random: introduce drain_entropy() helper to declutter crng_reseed()
+    - random: remove useless header comment
+    - random: remove whitespace and reorder includes
+    - random: group initialization wait functions
+    - random: group crng functions
+    - random: group entropy extraction functions
+    - random: group entropy collection functions
+    - random: group userspace read/write functions
+    - random: group sysctl functions
+    - random: rewrite header introductory comment
+    - random: defer fast pool mixing to worker
+    - random: do not take pool spinlock at boot
+    - random: unify early init crng load accounting
+    - random: check for crng_init == 0 in add_device_randomness()
+    - random: pull add_hwgenerator_randomness() declaration into random.h
+    - random: clear fast pool, crng, and batches in cpuhp bring up
+    - random: round-robin registers as ulong, not u32
+    - random: only wake up writers after zap if threshold was passed
+    - random: cleanup UUID handling
+    - random: unify cycles_t and jiffies usage and types
+    - random: do crng pre-init loading in worker rather than irq
+    - random: give sysctl_random_min_urandom_seed a more sensible value
+    - random: don't let 644 read-only sysctls be written to
+    - random: replace custom notifier chain with standard one
+    - random: use SipHash as interrupt entropy accumulator
+    - random: make consistent usage of crng_ready()
+    - random: reseed more often immediately after booting
+    - random: check for signal and try earlier when generating entropy
+    - random: skip fast_init if hwrng provides large chunk of entropy
+    - random: treat bootloader trust toggle the same way as cpu trust toggle
+    - random: re-add removed comment about get_random_{u32,u64} reseeding
+    - random: mix build-time latent entropy into pool at init
+    - random: do not split fast init input in add_hwgenerator_randomness()
+    - random: do not allow user to keep crng key around on stack
+    - random: check for signal_pending() outside of need_resched() check
+    - random: check for signals every PAGE_SIZE chunk of /dev/[u]random
+    - random: allow partial reads if later user copies fail
+    - random: make random_get_entropy() return an unsigned long
+    - random: document crng_fast_key_erasure() destination possibility
+    - random: fix sysctl documentation nits
+    - init: call time_init() before rand_initialize()
+    - ia64: define get_cycles macro for arch-override
+    - s390: define get_cycles macro for arch-override
+    - parisc: define get_cycles macro for arch-override
+    - alpha: define get_cycles macro for arch-override
+    - powerpc: define get_cycles macro for arch-override
+    - timekeeping: Add raw clock fallback for random_get_entropy()
+    - m68k: use fallback for random_get_entropy() instead of zero
+    - mips: use fallback for random_get_entropy() instead of just c0 random
+    - arm: use fallback for random_get_entropy() instead of zero
+    - nios2: use fallback for random_get_entropy() instead of zero
+    - x86/tsc: Use fallback for random_get_entropy() instead of zero
+    - um: use fallback for random_get_entropy() instead of zero
+    - sparc: use fallback for random_get_entropy() instead of zero
+    - xtensa: use fallback for random_get_entropy() instead of zero
+    - random: insist on random_get_entropy() existing in order to simplify
+    - random: do not use batches when !crng_ready()
+    - random: use first 128 bits of input as fast init
+    - random: do not pretend to handle premature next security model
+    - random: order timer entropy functions below interrupt functions
+    - random: do not use input pool from hard IRQs
+    - random: help compiler out with fast_mix() by using simpler arguments
+    - siphash: use one source of truth for siphash permutations
+    - random: use symbolic constants for crng_init states
+    - random: avoid initializing twice in credit race
+    - random: move initialization out of reseeding hot path
+    - random: remove ratelimiting for in-kernel unseeded randomness
+    - random: use proper jiffies comparison macro
+    - random: handle latent entropy and command line from random_init()
+    - random: credit architectural init the exact amount
+    - random: use static branch for crng_ready()
+    - random: remove extern from functions in header
+    - random: use proper return types on get_random_{int,long}_wait()
+    - random: make consistent use of buf and len
+    - random: move initialization functions out of hot pages
+    - random: move randomize_page() into mm where it belongs
+    - random: unify batched entropy implementations
+    - random: convert to using fops->read_iter()
+    - random: convert to using fops->write_iter()
+    - random: wire up fops->splice_{read,write}_iter()
+    - random: check for signals after page of pool writes
+    - Revert "random: use static branch for crng_ready()"
+    - crypto: drbg - always seeded with SP800-90B compliant noise source
+    - crypto: drbg - prepare for more fine-grained tracking of seeding state
+    - crypto: drbg - track whether DRBG was seeded with !rng_is_initialized()
+    - crypto: drbg - move dynamic ->reseed_threshold adjustments to __drbg_seed()
+    - crypto: drbg - always try to free Jitter RNG instance
+    - crypto: drbg - make reseeding from get_random_bytes() synchronous
+    - random: avoid checking crng_ready() twice in random_init()
+    - random: mark bootloader randomness code as __init
+    - random: account for arch randomness in bits
+    - powerpc/kasan: Silence KASAN warnings in __get_wchan()
+    - ASoC: nau8822: Add operation for internal PLL off and on
+    - dma-debug: make things less spammy under memory pressure
+    - ASoC: cs42l52: Fix TLV scales for mixer controls
+    - ASoC: cs35l36: Update digital volume TLV
+    - ASoC: cs53l30: Correct number of volume levels on SX controls
+    - ASoC: cs42l52: Correct TLV for Bypass Volume
+    - ASoC: cs42l56: Correct typo in minimum level for SX volume controls
+    - ata: libata-core: fix NULL pointer deref in ata_host_alloc_pinfo()
+    - ASoC: wm8962: Fix suspend while playing music
+    - ASoC: es8328: Fix event generation for deemphasis control
+    - ASoC: wm_adsp: Fix event generation for wm_adsp_fw_put()
+    - scsi: vmw_pvscsi: Expand vcpuHint to 16 bits
+    - scsi: lpfc: Fix port stuck in bypassed state after LIP in PT2PT topology
+    - scsi: lpfc: Allow reduced polling rate for nvme_admin_async_event cmd
+      completion
+    - scsi: ipr: Fix missing/incorrect resource cleanup in error case
+    - scsi: pmcraid: Fix missing resource cleanup in error case
+    - ALSA: hda/realtek - Add HW8326 support
+    - virtio-mmio: fix missing put_device() when vm_cmdline_parent registration
+      failed
+    - nfc: nfcmrvl: Fix memory leak in nfcmrvl_play_deferred
+    - ipv6: Fix signed integer overflow in l2tp_ip6_sendmsg
+    - net: ethernet: mtk_eth_soc: fix misuse of mem alloc interface
+      netdev[napi]_alloc_frag
+    - random: credit cpu and bootloader seeds by default
+    - pNFS: Don't keep retrying if the server replied NFS4ERR_LAYOUTUNAVAILABLE
+    - clocksource: hyper-v: unexport __init-annotated hv_init_clocksource()
+    - i40e: Fix adding ADQ filter to TC0
+    - i40e: Fix calculating the number of queue pairs
+    - i40e: Fix call trace in setup_tx_descriptors
+    - tty: goldfish: Fix free_irq() on remove
+    - misc: atmel-ssc: Fix IRQ check in ssc_probe
+    - mlxsw: spectrum_cnt: Reorder counter pools
+    - net: bgmac: Fix an erroneous kfree() in bgmac_remove()
+    - arm64: ftrace: fix branch range checks
+    - certs/blacklist_hashes.c: fix const confusion in certs blacklist
+    - faddr2line: Fix overlapping text section failures, the sequel
+    - irqchip/gic/realview: Fix refcount leak in realview_gic_of_init
+    - irqchip/gic-v3: Fix error handling in gic_populate_ppi_partitions
+    - irqchip/gic-v3: Fix refcount leak in gic_populate_ppi_partitions
+    - i2c: designware: Use standard optional ref clock implementation
+    - comedi: vmk80xx: fix expression for tx buffer size
+    - USB: serial: option: add support for Cinterion MV31 with new baseline
+    - USB: serial: io_ti: add Agilent E5805A support
+    - usb: dwc2: Fix memory leak in dwc2_hcd_init
+    - usb: gadget: lpc32xx_udc: Fix refcount leak in lpc32xx_udc_probe
+    - serial: 8250: Store to lsr_save_flags after lsr read
+    - dm mirror log: round up region bitmap size to BITS_PER_LONG
+    - ext4: fix bug_on ext4_mb_use_inode_pa
+    - ext4: make variable "count" signed
+    - ext4: add reserved GDT blocks check
+    - ALSA: hda/realtek: fix right sounds and mute/micmute LEDs for HP machine
+    - virtio-pci: Remove wrong address verification in vp_del_vqs()
+    - net/sched: act_police: more accurate MTU policing
+    - net: openvswitch: fix leak of nested actions
+    - arm64: kprobes: Use BRK instead of single-step when executing instructions
+      out-of-line
+    - RISC-V: fix barrier() use in <vdso/processor.h>
+    - riscv: Less inefficient gcc tishift helpers (and export their symbols)
+    - powerpc/mm: Switch obsolete dssall to .long
+    - Linux 5.4.200
+  * Focal update: v5.4.199 upstream stable release (LP: #1983150)
+    - Linux 5.4.199
+  * Focal update: v5.4.198 upstream stable release (LP: #1982409)
+    - binfmt_flat: do not stop relocating GOT entries prematurely on riscv
+    - ALSA: hda/realtek - Fix microphone noise on ASUS TUF B550M-PLUS
+    - USB: serial: option: add Quectel BG95 modem
+    - USB: new quirk for Dell Gen 2 devices
+    - perf/x86/intel: Fix event constraints for ICL
+    - ptrace/um: Replace PT_DTRACE with TIF_SINGLESTEP
+    - ptrace/xtensa: Replace PT_SINGLESTEP with TIF_SINGLESTEP
+    - ptrace: Reimplement PTRACE_KILL by always sending SIGKILL
+    - btrfs: add "0x" prefix for unsupported optional features
+    - btrfs: repair super block num_devices automatically
+    - drm/virtio: fix NULL pointer dereference in virtio_gpu_conn_get_modes
+    - mwifiex: add mutex lock for call in mwifiex_dfs_chan_sw_work_queue
+    - b43legacy: Fix assigning negative value to unsigned variable
+    - b43: Fix assigning negative value to unsigned variable
+    - ipw2x00: Fix potential NULL dereference in libipw_xmit()
+    - ipv6: fix locking issues with loops over idev->addr_list
+    - fbcon: Consistently protect deferred_takeover with console_lock()
+    - ACPICA: Avoid cache flush inside virtual machines
+    - drm/komeda: return early if drm_universal_plane_init() fails.
+    - ALSA: jack: Access input_dev under mutex
+    - spi: spi-rspi: Remove setting {src,dst}_{addr,addr_width} based on DMA
+      direction
+    - tools/power turbostat: fix ICX DRAM power numbers
+    - drm/amd/pm: fix double free in si_parse_power_table()
+    - ath9k: fix QCA9561 PA bias level
+    - media: venus: hfi: avoid null dereference in deinit
+    - media: pci: cx23885: Fix the error handling in cx23885_initdev()
+    - media: cx25821: Fix the warning when removing the module
+    - md/bitmap: don't set sb values if can't pass sanity check
+    - mmc: jz4740: Apply DMA engine limits to maximum segment size
+    - scsi: megaraid: Fix error check return value of register_chrdev()
+    - drm/plane: Move range check for format_count earlier
+    - drm/amd/pm: fix the compile warning
+    - arm64: compat: Do not treat syscall number as ESR_ELx for a bad syscall
+    - drm: msm: fix error check return value of irq_of_parse_and_map()
+    - ipv6: Don't send rs packets to the interface of ARPHRD_TUNNEL
+    - net/mlx5: fs, delete the FTE when there are no rules attached to it
+    - ASoC: dapm: Don't fold register value changes into notifications
+    - mlxsw: spectrum_dcb: Do not warn about priority changes
+    - drm/amdgpu/ucode: Remove firmware load type check in amdgpu_ucode_free_bo
+    - HID: bigben: fix slab-out-of-bounds Write in bigben_probe
+    - ASoC: tscs454: Add endianness flag in snd_soc_component_driver
+    - s390/preempt: disable __preempt_count_add() optimization for
+      PROFILE_ALL_BRANCHES
+    - spi: stm32-qspi: Fix wait_cmd timeout in APM mode
+    - dma-debug: change allocation mode from GFP_NOWAIT to GFP_ATIOMIC
+    - ACPI: PM: Block ASUS B1400CEAE from suspend to idle by default
+    - ipmi:ssif: Check for NULL msg when handling events and messages
+    - ipmi: Fix pr_fmt to avoid compilation issues
+    - rtlwifi: Use pr_warn instead of WARN_ONCE
+    - media: coda: limit frame interval enumeration to supported encoder frame
+      sizes
+    - media: cec-adap.c: fix is_configuring state
+    - openrisc: start CPU timer early in boot
+    - nvme-pci: fix a NULL pointer dereference in nvme_alloc_admin_tags
+    - ASoC: rt5645: Fix errorenous cleanup order
+    - nbd: Fix hung on disconnect request if socket is closed before
+    - net: phy: micrel: Allow probing without .driver_data
+    - media: exynos4-is: Fix compile warning
+    - ASoC: max98357a: remove dependency on GPIOLIB
+    - rxrpc: Return an error to sendmsg if call failed
+    - eth: tg3: silence the GCC 12 array-bounds warning
+    - selftests/bpf: fix btf_dump/btf_dump due to recent clang change
+    - IB/rdmavt: add missing locks in rvt_ruc_loopback
+    - ARM: dts: ox820: align interrupt controller node name with dtschema
+    - PM / devfreq: rk3399_dmc: Disable edev on remove()
+    - fs: jfs: fix possible NULL pointer dereference in dbFree()
+    - ARM: OMAP1: clock: Fix UART rate reporting algorithm
+    - powerpc/fadump: Fix fadump to work with a different endian capture kernel
+    - fat: add ratelimit to fat*_ent_bread()
+    - ARM: versatile: Add missing of_node_put in dcscb_init
+    - ARM: dts: exynos: add atmel,24c128 fallback to Samsung EEPROM
+    - ARM: hisi: Add missing of_node_put after of_find_compatible_node
+    - PCI: Avoid pci_dev_lock() AB/BA deadlock with sriov_numvfs_store()
+    - tracing: incorrect isolate_mote_t cast in mm_vmscan_lru_isolate
+    - powerpc/xics: fix refcount leak in icp_opal_init()
+    - powerpc/powernv: fix missing of_node_put in uv_init()
+    - macintosh/via-pmu: Fix build failure when CONFIG_INPUT is disabled
+    - powerpc/iommu: Add missing of_node_put in iommu_init_early_dart
+    - RDMA/hfi1: Prevent panic when SDMA is disabled
+    - drm: fix EDID struct for old ARM OABI format
+    - ath9k: fix ar9003_get_eepmisc
+    - drm/edid: fix invalid EDID extension block filtering
+    - drm/bridge: adv7511: clean up CEC adapter when probe fails
+    - ASoC: mediatek: Fix error handling in mt8173_max98090_dev_probe
+    - ASoC: mediatek: Fix missing of_node_put in mt2701_wm8960_machine_probe
+    - x86/delay: Fix the wrong asm constraint in delay_loop()
+    - drm/mediatek: Fix mtk_cec_mask()
+    - drm/vc4: txp: Don't set TXP_VSTART_AT_EOF
+    - drm/vc4: txp: Force alpha to be 0xff if it's disabled
+    - bpf: Fix excessive memory allocation in stack_map_alloc()
+    - nl80211: show SSID for P2P_GO interfaces
+    - drm/komeda: Fix an undefined behavior bug in komeda_plane_add()
+    - drm: mali-dp: potential dereference of null pointer
+    - spi: spi-ti-qspi: Fix return value handling of wait_for_completion_timeout
+    - NFC: NULL out the dev->rfkill to prevent UAF
+    - efi: Add missing prototype for efi_capsule_setup_info
+    - drbd: fix duplicate array initializer
+    - HID: hid-led: fix maximum brightness for Dream Cheeky
+    - HID: elan: Fix potential double free in elan_input_configured
+    - drm/bridge: Fix error handling in analogix_dp_probe
+    - sched/fair: Fix cfs_rq_clock_pelt() for throttled cfs_rq
+    - spi: img-spfi: Fix pm_runtime_get_sync() error checking
+    - cpufreq: Fix possible race in cpufreq online error path
+    - ath9k_htc: fix potential out of bounds access with invalid
+      rxstatus->rs_keyix
+    - inotify: show inotify mask flags in proc fdinfo
+    - fsnotify: fix wrong lockdep annotations
+    - of: overlay: do not break notify on NOTIFY_{OK|STOP}
+    - scsi: ufs: core: Exclude UECxx from SFR dump list
+    - x86/pm: Fix false positive kmemleak report in msr_build_context()
+    - x86/speculation: Add missing prototype for unpriv_ebpf_notify()
+    - ASoC: rk3328: fix disabling mclk on pclk probe failure
+    - perf tools: Add missing headers needed by util/data.h
+    - drm/msm/disp/dpu1: set vbif hw config to NULL to avoid use after memory free
+      during pm runtime resume
+    - drm/msm/dsi: fix error checks and return values for DSI xmit functions
+    - drm/msm/hdmi: check return value after calling
+      platform_get_resource_byname()
+    - drm/msm/hdmi: fix error check return value of irq_of_parse_and_map()
+    - drm/rockchip: vop: fix possible null-ptr-deref in vop_bind()
+    - virtio_blk: fix the discard_granularity and discard_alignment queue limits
+    - x86: Fix return value of __setup handlers
+    - irqchip/exiu: Fix acknowledgment of edge triggered interrupts
+    - irqchip/aspeed-i2c-ic: Fix irq_of_parse_and_map() return value
+    - x86/mm: Cleanup the control_va_addr_alignment() __setup handler
+    - regulator: core: Fix enable_count imbalance with EXCLUSIVE_GET
+    - drm/msm/mdp5: Return error code in mdp5_pipe_release when deadlock is
+      detected
+    - drm/msm/mdp5: Return error code in mdp5_mixer_release when deadlock is
+      detected
+    - drm/msm: return an error pointer in msm_gem_prime_get_sg_table()
+    - media: uvcvideo: Fix missing check to determine if element is found in list
+    - iomap: iomap_write_failed fix
+    - Revert "cpufreq: Fix possible race in cpufreq online error path"
+    - perf/amd/ibs: Use interrupt regs ip for stack unwinding
+    - ASoC: fsl: Fix refcount leak in imx_sgtl5000_probe
+    - ASoC: mxs-saif: Fix refcount leak in mxs_saif_probe
+    - regulator: pfuze100: Fix refcount leak in pfuze_parse_regulators_dt
+    - scripts/faddr2line: Fix overlapping text section failures
+    - media: aspeed: Fix an error handling path in aspeed_video_probe()
+    - media: st-delta: Fix PM disable depth imbalance in delta_probe
+    - media: exynos4-is: Change clk_disable to clk_disable_unprepare
+    - media: pvrusb2: fix array-index-out-of-bounds in pvr2_i2c_core_init
+    - media: vsp1: Fix offset calculation for plane cropping
+    - Bluetooth: fix dangling sco_conn and use-after-free in sco_sock_timeout
+    - m68k: math-emu: Fix dependencies of math emulation support
+    - sctp: read sk->sk_bound_dev_if once in sctp_rcv()
+    - media: ov7670: remove ov7670_power_off from ov7670_remove
+    - ext4: reject the 'commit' option on ext2 filesystems
+    - drm/msm/a6xx: Fix refcount leak in a6xx_gpu_init
+    - drm: msm: fix possible memory leak in mdp5_crtc_cursor_set()
+    - thermal/drivers/broadcom: Fix potential NULL dereference in sr_thermal_probe
+    - ASoC: wm2000: fix missing clk_disable_unprepare() on error in
+      wm2000_anc_transition()
+    - NFC: hci: fix sleep in atomic context bugs in nfc_hci_hcp_message_tx
+    - rxrpc: Fix listen() setting the bar too high for the prealloc rings
+    - rxrpc: Don't try to resend the request if we're receiving the reply
+    - rxrpc: Fix overlapping ACK accounting
+    - rxrpc: Don't let ack.previousPacket regress
+    - rxrpc: Fix decision on when to generate an IDLE ACK
+    - net/smc: postpone sk_refcnt increment in connect()
+    - arm64: dts: rockchip: Move drive-impedance-ohm to emmc phy on rk3399
+    - ARM: dts: suniv: F1C100: fix watchdog compatible
+    - soc: qcom: smp2p: Fix missing of_node_put() in smp2p_parse_ipc
+    - soc: qcom: smsm: Fix missing of_node_put() in smsm_parse_ipc
+    - PCI: cadence: Fix find_first_zero_bit() limit
+    - PCI: rockchip: Fix find_first_zero_bit() limit
+    - KVM: nVMX: Leave most VM-Exit info fields unmodified on failed VM-Entry
+    - can: xilinx_can: mark bit timing constants as const
+    - ARM: dts: bcm2835-rpi-zero-w: Fix GPIO line name for Wifi/BT
+    - ARM: dts: bcm2837-rpi-cm3-io3: Fix GPIO line names for SMPS I2C
+    - ARM: dts: bcm2837-rpi-3-b-plus: Fix GPIO line name of power LED
+    - ARM: dts: bcm2835-rpi-b: Fix GPIO line names
+    - misc: ocxl: fix possible double free in ocxl_file_register_afu
+    - crypto: marvell/cesa - ECB does not IV
+    - arm: mediatek: select arch timer for mt7629
+    - powerpc/fadump: fix PT_LOAD segment for boot memory area
+    - mfd: ipaq-micro: Fix error check return value of platform_get_irq()
+    - scsi: fcoe: Fix Wstringop-overflow warnings in fcoe_wwn_from_mac()
+    - firmware: arm_scmi: Fix list protocols enumeration in the base protocol
+    - nvdimm: Allow overwrite in the presence of disabled dimms
+    - pinctrl: mvebu: Fix irq_of_parse_and_map() return value
+    - drivers/base/node.c: fix compaction sysfs file leak
+    - dax: fix cache flush on PMD-mapped pages
+    - powerpc/8xx: export 'cpm_setbrg' for modules
+    - powerpc/idle: Fix return value of __setup() handler
+    - powerpc/4xx/cpm: Fix return value of __setup() handler
+    - proc: fix dentry/inode overinstantiating under /proc/${pid}/net
+    - ipc/mqueue: use get_tree_nodev() in mqueue_get_tree()
+    - PCI: imx6: Fix PERST# start-up sequence
+    - tty: fix deadlock caused by calling printk() under tty_port->lock
+    - crypto: cryptd - Protect per-CPU resource by disabling BH.
+    - Input: sparcspkr - fix refcount leak in bbc_beep_probe
+    - powerpc/64: Only WARN if __pa()/__va() called with bad addresses
+    - powerpc/perf: Fix the threshold compare group constraint for power9
+    - macintosh: via-pmu and via-cuda need RTC_LIB
+    - powerpc/fsl_rio: Fix refcount leak in fsl_rio_setup
+    - mfd: davinci_voicecodec: Fix possible null-ptr-deref davinci_vc_probe()
+    - mailbox: forward the hrtimer if not queued and under a lock
+    - RDMA/hfi1: Prevent use of lock before it is initialized
+    - Input: stmfts - do not leave device disabled in stmfts_input_open
+    - f2fs: fix dereference of stale list iterator after loop body
+    - iommu/mediatek: Add list_del in mtk_iommu_remove
+    - i2c: at91: use dma safe buffers
+    - i2c: at91: Initialize dma_buf in at91_twi_xfer()
+    - NFS: Do not report EINTR/ERESTARTSYS as mapping errors
+    - NFS: Do not report flush errors in nfs_write_end()
+    - NFS: Don't report errors from nfs_pageio_complete() more than once
+    - NFSv4/pNFS: Do not fail I/O when we fail to allocate the pNFS layout
+    - video: fbdev: clcdfb: Fix refcount leak in clcdfb_of_vram_setup
+    - dmaengine: stm32-mdma: remove GISR1 register
+    - iommu/amd: Increase timeout waiting for GA log enablement
+    - perf c2c: Use stdio interface if slang is not supported
+    - perf jevents: Fix event syntax error caused by ExtSel
+    - f2fs: fix to avoid f2fs_bug_on() in dec_valid_node_count()
+    - f2fs: fix to do sanity check on block address in f2fs_do_zero_range()
+    - f2fs: fix to clear dirty inode in f2fs_evict_inode()
+    - f2fs: fix deadloop in foreground GC
+    - f2fs: don't need inode lock for system hidden quota
+    - f2fs: fix fallocate to use file_modified to update permissions consistently
+    - wifi: mac80211: fix use-after-free in chanctx code
+    - iwlwifi: mvm: fix assert 1F04 upon reconfig
+    - fs-writeback: writeback_sb_inodes：Recalculate 'wrote' according skipped
+      pages
+    - efi: Do not import certificates from UEFI Secure Boot for T2 Macs
+    - bfq: Split shared queues on move between cgroups
+    - bfq: Update cgroup information before merging bio
+    - bfq: Track whether bfq_group is still online
+    - ext4: fix use-after-free in ext4_rename_dir_prepare
+    - ext4: fix warning in ext4_handle_inode_extension
+    - ext4: fix bug_on in ext4_writepages
+    - ext4: verify dir block before splitting it
+    - ext4: avoid cycles in directory h-tree
+    - ACPI: property: Release subnode properties with data nodes
+    - tracing: Fix potential double free in create_var_ref()
+    - PCI/PM: Fix bridge_d3_blacklist[] Elo i2 overwrite of Gigabyte X299
+    - PCI: qcom: Fix runtime PM imbalance on probe errors
+    - PCI: qcom: Fix unbalanced PHY init on probe errors
+    - mm, compaction: fast_find_migrateblock() should return pfn in the target
+      zone
+    - dlm: fix plock invalid read
+    - dlm: fix missing lkb refcount handling
+    - ocfs2: dlmfs: fix error handling of user_dlm_destroy_lock
+    - scsi: dc395x: Fix a missing check on list iterator
+    - scsi: ufs: qcom: Add a readl() to make sure ref_clk gets enabled
+    - drm/amdgpu/cs: make commands with 0 chunks illegal behaviour.
+    - drm/etnaviv: check for reaped mapping in etnaviv_iommu_unmap_gem
+    - drm/nouveau/clk: Fix an incorrect NULL check on list iterator
+    - drm/bridge: analogix_dp: Grab runtime PM reference for DP-AUX
+    - md: fix an incorrect NULL check in does_sb_need_changing
+    - md: fix an incorrect NULL check in md_reload_sb
+    - mtd: cfi_cmdset_0002: Move and rename
+      chip_check/chip_ready/chip_good_for_write
+    - media: coda: Fix reported H264 profile
+    - media: coda: Add more H264 levels for CODA960
+    - Kconfig: Add option for asm goto w/ tied outputs to workaround clang-13 bug
+    - RDMA/hfi1: Fix potential integer multiplication overflow errors
+    - irqchip/armada-370-xp: Do not touch Performance Counter Overflow on A375,
+      A38x, A39x
+    - irqchip: irq-xtensa-mx: fix initial IRQ affinity
+    - mac80211: upgrade passive scan to active scan on DFS channels after beacon
+      rx
+    - um: chan_user: Fix winch_tramp() return value
+    - um: Fix out-of-bounds read in LDT setup
+    - iommu/msm: Fix an incorrect NULL check on list iterator
+    - nodemask.h: fix compilation error with GCC12
+    - hugetlb: fix huge_pmd_unshare address update
+    - rtl818x: Prevent using not initialized queues
+    - ASoC: rt5514: Fix event generation for "DSP Voice Wake Up" control
+    - carl9170: tx: fix an incorrect use of list iterator
+    - serial: pch: don't overwrite xmit->buf[0] by x_char
+    - tilcdc: tilcdc_external: fix an incorrect NULL check on list iterator
+    - gma500: fix an incorrect NULL check on list iterator
+    - arm64: dts: qcom: ipq8074: fix the sleep clock frequency
+    - phy: qcom-qmp: fix struct clk leak on probe errors
+    - ARM: pxa: maybe fix gpio lookup tables
+    - docs/conf.py: Cope with removal of language=None in Sphinx 5.0.0
+    - dt-bindings: gpio: altera: correct interrupt-cells
+    - blk-iolatency: Fix inflight count imbalances and IO hangs on offline
+    - phy: qcom-qmp: fix reset-controller leak on probe errors
+    - Kconfig: add config option for asm goto w/ outputs
+    - RDMA/rxe: Generate a completion for unsupported/invalid opcode
+    - MIPS: IP27: Remove incorrect `cpu_has_fpu' override
+    - bfq: Avoid merging queues with different parents
+    - bfq: Drop pointless unlock-lock pair
+    - bfq: Remove pointless bfq_init_rq() calls
+    - bfq: Get rid of __bio_blkcg() usage
+    - bfq: Make sure bfqg for which we are queueing requests is online
+    - block: fix bio_clone_blkg_association() to associate with proper blkcg_gq
+    - md: bcache: check the return value of kzalloc() in detached_dev_do_request()
+    - pcmcia: db1xxx_ss: restrict to MIPS_DB1XXX boards
+    - staging: greybus: codecs: fix type confusion of list iterator variable
+    - iio: adc: ad7124: Remove shift from scan_type
+    - tty: goldfish: Use tty_port_destroy() to destroy port
+    - tty: serial: owl: Fix missing clk_disable_unprepare() in owl_uart_probe
+    - tty: serial: fsl_lpuart: fix potential bug when using both of_alias_get_id
+      and ida_simple_get
+    - usb: usbip: fix a refcount leak in stub_probe()
+    - usb: usbip: add missing device lock on tweak configuration cmd
+    - USB: storage: karma: fix rio_karma_init return
+    - usb: musb: Fix missing of_node_put() in omap2430_probe
+    - staging: fieldbus: Fix the error handling path in
+      anybuss_host_common_probe()
+    - pwm: lp3943: Fix duty calculation in case period was clamped
+    - rpmsg: qcom_smd: Fix irq_of_parse_and_map() return value
+    - usb: dwc3: pci: Fix pm_runtime_get_sync() error checking
+    - firmware: stratix10-svc: fix a missing check on list iterator
+    - iio: adc: stmpe-adc: Fix wait_for_completion_timeout return value check
+    - iio: adc: sc27xx: fix read big scale voltage not right
+    - iio: adc: sc27xx: Fine tune the scale calibration values
+    - rpmsg: qcom_smd: Fix returning 0 if irq_of_parse_and_map() fails
+    - phy: qcom-qmp: fix pipe-clock imbalance on power-on failure
+    - serial: sifive: Report actual baud base rather than fixed 115200
+    - coresight: cpu-debug: Replace mutex with mutex_trylock on panic notifier
+    - soc: rockchip: Fix refcount leak in rockchip_grf_init
+    - clocksource/drivers/riscv: Events are stopped during CPU suspend
+    - rtc: mt6397: check return value after calling platform_get_resource()
+    - serial: meson: acquire port->lock in startup()
+    - serial: 8250_fintek: Check SER_RS485_RTS_* only with RS485
+    - serial: digicolor-usart: Don't allow CS5-6
+    - serial: rda-uart: Don't allow CS5-6
+    - serial: txx9: Don't allow CS5-6
+    - serial: sh-sci: Don't allow CS5-6
+    - serial: sifive: Sanitize CSIZE and c_iflag
+    - serial: st-asc: Sanitize CSIZE and correct PARENB for CS7
+    - serial: stm32-usart: Correct CSIZE, bits, and parity
+    - firmware: dmi-sysfs: Fix memory leak in dmi_sysfs_register_handle
+    - bus: ti-sysc: Fix warnings for unbind for serial
+    - driver: base: fix UAF when driver_attach failed
+    - driver core: fix deadlock in __device_attach
+    - watchdog: ts4800_wdt: Fix refcount leak in ts4800_wdt_probe
+    - ASoC: fsl_sai: Fix FSL_SAI_xDR/xFR definition
+    - clocksource/drivers/oxnas-rps: Fix irq_of_parse_and_map() return value
+    - s390/crypto: fix scatterwalk_unmap() callers in AES-GCM
+    - net: sched: fixed barrier to prevent skbuff sticking in qdisc backlog
+    - net: ethernet: mtk_eth_soc: out of bounds read in mtk_hwlro_get_fdir_entry()
+    - net: dsa: mv88e6xxx: Fix refcount leak in mv88e6xxx_mdios_register
+    - modpost: fix removing numeric suffixes
+    - jffs2: fix memory leak in jffs2_do_fill_super
+    - ubi: ubi_create_volume: Fix use-after-free when volume creation failed
+    - nfp: only report pause frame configuration for physical device
+    - net/mlx5: Don't use already freed action pointer
+    - net/mlx5e: Update netdev features after changing XDP state
+    - net: sched: add barrier to fix packet stuck problem for lockless qdisc
+    - tcp: tcp_rtx_synack() can be called from process context
+    - afs: Fix infinite loop found by xfstest generic/676
+    - tipc: check attribute length for bearer name
+    - perf c2c: Fix sorting in percent_rmt_hitm_cmp()
+    - mips: cpc: Fix refcount leak in mips_cpc_default_phys_base
+    - tracing: Fix sleeping function called from invalid context on RT kernel
+    - tracing: Avoid adding tracer option before update_tracer_options
+    - f2fs: remove WARN_ON in f2fs_is_valid_blkaddr
+    - i2c: cadence: Increase timeout per message if necessary
+    - m68knommu: set ZERO_PAGE() to the allocated zeroed page
+    - m68knommu: fix undefined reference to `_init_sp'
+    - dmaengine: zynqmp_dma: In struct zynqmp_dma_chan fix desc_size data type
+    - NFSv4: Don't hold the layoutget locks across multiple RPC calls
+    - video: fbdev: pxa3xx-gcu: release the resources correctly in
+      pxa3xx_gcu_probe/remove()
+    - xprtrdma: treat all calls not a bcall when bc_serv is NULL
+    - netfilter: nat: really support inet nat without l3 address
+    - ata: pata_octeon_cf: Fix refcount leak in octeon_cf_probe
+    - netfilter: nf_tables: memleak flow rule from commit path
+    - xen: unexport __init-annotated xen_xlate_map_ballooned_pages()
+    - af_unix: Fix a data-race in unix_dgram_peer_wake_me().
+    - bpf, arm64: Clear prog->jited_len along prog->jited
+    - net: dsa: lantiq_gswip: Fix refcount leak in gswip_gphy_fw_list
+    - net/mlx4_en: Fix wrong return value on ioctl EEPROM query failure
+    - SUNRPC: Fix the calculation of xdr->end in xdr_get_next_encode_buffer()
+    - net: mdio: unexport __init-annotated mdio_bus_init()
+    - net: xfrm: unexport __init-annotated xfrm4_protocol_init()
+    - net: ipv6: unexport __init-annotated seg6_hmac_init()
+    - net/mlx5: Rearm the FW tracer after each tracer event
+    - net/mlx5: fs, fail conflicting actions
+    - ip_gre: test csum_start instead of transport header
+    - net: altera: Fix refcount leak in altera_tse_mdio_create
+    - drm: imx: fix compiler warning with gcc-12
+    - iio: dummy: iio_simple_dummy: check the return value of kstrdup()
+    - iio: st_sensors: Add a local lock for protecting odr
+    - lkdtm/usercopy: Expand size of "out of frame" object
+    - tty: synclink_gt: Fix null-pointer-dereference in slgt_clean()
+    - tty: Fix a possible resource leak in icom_probe
+    - drivers: staging: rtl8192u: Fix deadlock in ieee80211_beacons_stop()
+    - drivers: staging: rtl8192e: Fix deadlock in rtllib_beacons_stop()
+    - USB: host: isp116x: check return value after calling platform_get_resource()
+    - drivers: tty: serial: Fix deadlock in sa1100_set_termios()
+    - drivers: usb: host: Fix deadlock in oxu_bus_suspend()
+    - USB: hcd-pci: Fully suspend across freeze/thaw cycle
+    - usb: dwc2: gadget: don't reset gadget's driver->bus
+    - misc: rtsx: set NULL intfdata when probe fails
+    - extcon: Modify extcon device to be created after driver data is set
+    - clocksource/drivers/sp804: Avoid error on multiple instances
+    - staging: rtl8712: fix uninit-value in usb_read8() and friends
+    - staging: rtl8712: fix uninit-value in r871xu_drv_init()
+    - serial: msm_serial: disable interrupts in __msm_console_write()
+    - kernfs: Separate kernfs_pr_cont_buf and rename_lock.
+    - watchdog: wdat_wdt: Stop watchdog when rebooting the system
+    - md: protect md_unregister_thread from reentrancy
+    - scsi: myrb: Fix up null pointer access on myrb_cleanup()
+    - ceph: allow ceph.dir.rctime xattr to be updatable
+    - drm/radeon: fix a possible null pointer dereference
+    - modpost: fix undefined behavior of is_arm_mapping_symbol()
+    - x86/cpu: Elide KCSAN for cpu_has() and friends
+    - nbd: call genl_unregister_family() first in nbd_cleanup()
+    - nbd: fix race between nbd_alloc_config() and module removal
+    - cifs: version operations for smb20 unneeded when legacy support disabled
+    - nodemask: Fix return values to be unsigned
+    - vringh: Fix loop descriptors check in the indirect cases
+    - scripts/gdb: change kernel config dumping method
+    - ALSA: hda/conexant - Fix loopback issue with CX20632
+    - cifs: return errors during session setup during reconnects
+    - ata: libata-transport: fix {dma|pio|xfer}_mode sysfs files
+    - mmc: block: Fix CQE recovery reset success
+    - nfc: st21nfca: fix incorrect validating logic in EVT_TRANSACTION
+    - nfc: st21nfca: fix memory leaks in EVT_TRANSACTION handling
+    - ixgbe: fix bcast packets Rx on VF after promisc removal
+    - ixgbe: fix unexpected VLAN Rx in promisc mode on VF
+    - Input: bcm5974 - set missing URB_NO_TRANSFER_DMA_MAP urb flag
+    - powerpc/32: Fix overread/overwrite of thread_struct via ptrace
+    - md/raid0: Ignore RAID0 layout if the second zone has only one device
+    - mtd: cfi_cmdset_0002: Use chip_ready() for write on S29GL064N
+    - tcp: fix tcp_mtup_probe_success vs wrong snd_cwnd
+    - Linux 5.4.198
+  * Focal update: v5.4.197 upstream stable release (LP: #1981758)
+    - x86/pci/xen: Disable PCI/MSI[-X] masking for XEN_HVM guests
+    - staging: rtl8723bs: prevent ->Ssid overflow in rtw_wx_set_scan()
+    - Input: goodix - fix spurious key release events
+    - tcp: change source port randomizarion at connect() time
+    - secure_seq: use the 64 bits of the siphash for port offset calculation
+    - media: vim2m: Register video device after setting up internals
+    - media: vim2m: initialize the media device earlier
+    - ACPI: sysfs: Make sparse happy about address space in use
+    - ACPI: sysfs: Fix BERT error region memory mapping
+    - pinctrl: sunxi: fix f1c100s uart2 function
+    - net: af_key: check encryption module availability consistency
+    - net: ftgmac100: Disable hardware checksum on AST2600
+    - i2c: ismt: Provide a DMA buffer for Interrupt Cause Logging
+    - drivers: i2c: thunderx: Allow driver to work with ACPI defined TWSI
+      controllers
+    - assoc_array: Fix BUG_ON during garbage collect
+    - cfg80211: set custom regdomain after wiphy registration
+    - drm/i915: Fix -Wstringop-overflow warning in call to intel_read_wm_latency()
+    - exec: Force single empty string when argv is empty
+    - netfilter: conntrack: re-fetch conntrack after insertion
+    - crypto: ecrdsa - Fix incorrect use of vli_cmp
+    - zsmalloc: fix races between asynchronous zspage free and page migration
+    - dm integrity: fix error code in dm_integrity_ctr()
+    - dm crypt: make printing of the key constant-time
+    - dm stats: add cond_resched when looping over entries
+    - dm verity: set DM_TARGET_IMMUTABLE feature flag
+    - raid5: introduce MD_BROKEN
+    - HID: multitouch: Add support for Google Whiskers Touchpad
+    - tpm: Fix buffer access in tpm2_get_tpm_pt()
+    - tpm: ibmvtpm: Correct the return value in tpm_ibmvtpm_probe()
+    - docs: submitting-patches: Fix crossref to 'The canonical patch format'
+    - NFS: Memory allocation failures are not server fatal errors
+    - NFSD: Fix possible sleep during nfsd4_release_lockowner()
+    - bpf: Enlarge offset check value to INT_MAX in bpf_skb_{load,store}_bytes
+    - Linux 5.4.197
+  * Focal update: v5.4.196 upstream stable release (LP: #1981111)
+    - x86/xen: Make the boot CPU idle task reliable
+    - x86/xen: Make the secondary CPU idle tasks reliable
+    - rtc: fix use-after-free on device removal
+    - um: Cleanup syscall_handler_t definition/cast, fix warning
+    - Input: add bounds checking to input_set_capability()
+    - Input: stmfts - fix reference leak in stmfts_input_open
+    - crypto: stm32 - fix reference leak in stm32_crc_remove
+    - crypto: x86/chacha20 - Avoid spurious jumps to other functions
+    - ALSA: hda/realtek: Enable headset mic on Lenovo P360
+    - nvme-multipath: fix hang when disk goes live over reconnect
+    - rtc: mc146818-lib: Fix the AltCentury for AMD platforms
+    - MIPS: lantiq: check the return value of kzalloc()
+    - drbd: remove usage of list iterator variable after loop
+    - platform/chrome: cros_ec_debugfs: detach log reader wq from devm
+    - ARM: 9191/1: arm/stacktrace, kasan: Silence KASAN warnings in unwind_frame()
+    - nilfs2: fix lockdep warnings in page operations for btree nodes
+    - nilfs2: fix lockdep warnings during disk space reclamation
+    - mmc: core: Specify timeouts for BKOPS and CACHE_FLUSH for eMMC
+    - mmc: block: Use generic_cmd6_time when modifying INAND_CMD38_ARG_EXT_CSD
+    - mmc: core: Default to generic_cmd6_time as timeout in __mmc_switch()
+    - SUNRPC: Clean up scheduling of autoclose
+    - SUNRPC: Prevent immediate close+reconnect
+    - SUNRPC: Don't call connect() more than once on a TCP socket
+    - ALSA: wavefront: Proper check of get_user() error
+    - perf: Fix sys_perf_event_open() race against self
+    - Fix double fget() in vhost_net_set_backend()
+    - PCI/PM: Avoid putting Elo i2 PCIe Ports in D3cold
+    - KVM: x86/mmu: Update number of zapped pages even if page list is stable
+    - crypto: qcom-rng - fix infinite loop on requests not multiple of WORD_SZ
+    - drm/dp/mst: fix a possible memory leak in fetch_monitor_name()
+    - dma-buf: fix use of DMA_BUF_SET_NAME_{A,B} in userspace
+    - ARM: dts: aspeed-g6: remove FWQSPID group in pinctrl dtsi
+    - ARM: dts: aspeed-g6: fix SPI1/SPI2 quad pin group
+    - net: macb: Increment rx bd head after allocating skb and buffer
+    - net/sched: act_pedit: sanitize shift argument before usage
+    - net: vmxnet3: fix possible use-after-free bugs in vmxnet3_rq_alloc_rx_buf()
+    - net: vmxnet3: fix possible NULL pointer dereference in vmxnet3_rq_cleanup()
+    - ice: fix possible under reporting of ethtool Tx and Rx statistics
+    - clk: at91: generated: consider range when calculating best rate
+    - net/qla3xxx: Fix a test in ql_reset_work()
+    - NFC: nci: fix sleep in atomic context bugs caused by nci_skb_alloc
+    - net/mlx5e: Properly block LRO when XDP is enabled
+    - ARM: 9196/1: spectre-bhb: enable for Cortex-A15
+    - ARM: 9197/1: spectre-bhb: fix loop8 sequence for Thumb2
+    - igb: skip phy status check where unavailable
+    - net: bridge: Clear offload_fwd_mark when passing frame up bridge interface.
+    - gpio: gpio-vf610: do not touch other bits when set the target bit
+    - gpio: mvebu/pwm: Refuse requests with inverted polarity
+    - perf bench numa: Address compiler error on s390
+    - scsi: qla2xxx: Fix missed DMA unmap for aborted commands
+    - mac80211: fix rx reordering with non explicit / psmp ack policy
+    - selftests: add ping test with ping_group_range tuned
+    - ethernet: tulip: fix missing pci_disable_device() on error in
+      tulip_init_one()
+    - net: stmmac: fix missing pci_disable_device() on error in stmmac_pci_probe()
+    - net: atlantic: verify hw_head_ lies within TX buffer ring
+    - Input: ili210x - fix reset timing
+    - block: return ELEVATOR_DISCARD_MERGE if possible
+    - net: stmmac: disable Split Header (SPH) for Intel platforms
+    - firmware_loader: use kernel credentials when reading firmware
+    - ARM: dts: imx7: Use audio_mclk_post_div instead audio_mclk_root_clk
+    - Reinstate some of "swiotlb: rework "fix info leak with DMA_FROM_DEVICE""
+    - x86/xen: fix booting 32-bit pv guest
+    - x86/xen: Mark cpu_bringup_and_idle() as dead_end_function
+    - i2c: mt7621: fix missing clk_disable_unprepare() on error in mtk_i2c_probe()
+    - afs: Fix afs_getattr() to refetch file status if callback break occurred
+    - Linux 5.4.196
+  * CVE-2022-36946
+    - netfilter: nf_queue: do not allow packet truncation below transport header
+      offset
+  * CVE-2021-33655
+    - fbcon: Disallow setting font bigger than screen size
+    - fbcon: Prevent that screen size is smaller than font size
+    - fbmem: Check virtual screen sizes in fb_set_var()
+
+ -- Portia Stephens <portia.stephens@canonical.com>  Wed, 16 Nov 2022 15:21:39 +1000
+
+linux-xilinx-zynqmp (5.4.0-1018.21) focal; urgency=medium
+
+  * focal/linux-xilinx-zynqmp: 5.4.0-1018.21 -proposed tracker (LP: #1987968)
+
+  * Support builtin revoked certificates (LP: #1932029)
+    - [Config] Configure CONFIG_SYSTEM_REVOCATION_KEYS with revoked keys
+
+  * Please trust Canonical Livepatch Service kmod signing key (LP: #1898716)
+    - [Config] Add canonical-certs.pem
+
+  * CVE-2022-23960
+    - [Config] updateconfigs for CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY
+
+  * Focal update: upstream stable patchset v5.4.192 (LP: #1979014)
+    - [Config] updateconfigs for NVM
+
+  * Focal update: v5.4.141 upstream stable release (LP: #1943484)
+    - SAUCE: usb: dwc3: Fix dwc3_gadget_disable_irq declaration
+
+  * Focal update: v5.4.174 upstream stable release (LP: #1960566)
+    - SAUCE: tty: pl011: Remove release and request port callback in
+      xlnx_sbsa_uart_pops
+
+  * Focal update: v5.4.178 upstream stable release (LP: #1964634)
+    - ASoC: xilinx: xlnx_formatter_pcm: Make buffer bytes multiple of period bytes
+
+  * Focal update: v5.4.142 upstream stable release (LP: #1944202)
+    - ASoC: xilinx: Fix reference to PCM buffer address
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update Ubuntu.md
+
+  * Unable to handle kernel NULL pointer dereference on reboot (LP: #1950962)
+    - drm: xlnx: drv: unbind all components before framebuffer cleanup
+
+  [ Ubuntu: 5.4.0-125.141 ]
+
+  * focal/linux: 5.4.0-125.141 -proposed tracker (LP: #1983947)
+  * nbd: requests can become stuck when disconnecting from server with qemu-nbd
+    (LP: #1896350)
+    - blk-mq: blk-mq: provide forced completion method
+    - blk-mq: move failure injection out of blk_mq_complete_request
+    - nbd: don't handle response without a corresponding request message
+    - nbd: make sure request completion won't concurrent
+    - nbd: don't clear 'NBD_CMD_INFLIGHT' flag if request is not completed
+    - nbd: fix io hung while disconnecting device
+  * CVE-2021-33656
+    - vt: drop old FONT ioctls
+  * CVE-2021-33061
+    - ixgbe: add the ability for the PF to disable VF link state
+    - ixgbe: add improvement for MDD response functionality
+    - ixgbevf: add disable link state
+
+  [ Ubuntu: 5.4.0-124.140 ]
+
+  * CVE-2022-2586
+    - SAUCE: netfilter: nf_tables: do not allow SET_ID to refer to another table
+    - SAUCE: netfilter: nf_tables: do not allow RULE_ID to refer to another chain
+  * CVE-2022-2588
+    - SAUCE: net_sched: cls_route: remove from list when handle is 0
+  * CVE-2022-34918
+    - netfilter: nf_tables: stricter validation of element data
+
+  [ Ubuntu: 5.4.0-123.139 ]
+
+  * focal/linux: 5.4.0-123.139 -proposed tracker (LP: #1981284)
+  * Packaging resync (LP: #1786013)
+    - debian/dkms-versions -- update from kernel-versions (main/2022.07.11)
+  * Hairpin traffic does not work with centralized NAT gw (LP: #1967856)
+    - net: openvswitch: fix misuse of the cached connection on tuple changes
+  * [UBUNTU 20.04] Include patches to avoid self-detected stall with Secure
+    Execution (LP: #1979296)
+    - KVM: s390: pv: add macros for UVC CC values
+    - KVM: s390: pv: avoid stalls when making pages secure
+    - KVM: s390: pv: avoid stalls for kvm_s390_pv_init_vm
+  * Focal update: v5.4.195 upstream stable release (LP: #1980407)
+    - batman-adv: Don't skb_split skbuffs with frag_list
+    - hwmon: (tmp401) Add OF device ID table
+    - mac80211: Reset MBSSID parameters upon connection
+    - net: Fix features skip in for_each_netdev_feature()
+    - ipv4: drop dst in multicast routing path
+    - drm/nouveau: Fix a potential theorical leak in nouveau_get_backlight_name()
+    - netlink: do not reset transport header in netlink_recvmsg()
+    - mac80211_hwsim: call ieee80211_tx_prepare_skb under RCU protection
+    - dim: initialize all struct fields
+    - hwmon: (ltq-cputemp) restrict it to SOC_XWAY
+    - s390/ctcm: fix variable dereferenced before check
+    - s390/ctcm: fix potential memory leak
+    - s390/lcs: fix variable dereferenced before check
+    - net/sched: act_pedit: really ensure the skb is writable
+    - net/smc: non blocking recvmsg() return -EAGAIN when no data and
+      signal_pending
+    - net: sfc: ef10: fix memory leak in efx_ef10_mtd_probe()
+    - gfs2: Fix filesystem block deallocation for short writes
+    - hwmon: (f71882fg) Fix negative temperature
+    - ASoC: max98090: Reject invalid values in custom control put()
+    - ASoC: max98090: Generate notifications on changes for custom control
+    - ASoC: ops: Validate input values in snd_soc_put_volsw_range()
+    - s390: disable -Warray-bounds
+    - net: emaclite: Don't advertise 1000BASE-T and do auto negotiation
+    - tcp: resalt the secret every 10 seconds
+    - tty: n_gsm: fix mux activation issues in gsm_config()
+    - usb: cdc-wdm: fix reading stuck on device close
+    - usb: typec: tcpci: Don't skip cleanup in .remove() on error
+    - USB: serial: pl2303: add device id for HP LM930 Display
+    - USB: serial: qcserial: add support for Sierra Wireless EM7590
+    - USB: serial: option: add Fibocom L610 modem
+    - USB: serial: option: add Fibocom MA510 modem
+    - slimbus: qcom: Fix IRQ check in qcom_slim_probe
+    - serial: 8250_mtk: Fix UART_EFR register address
+    - serial: 8250_mtk: Fix register address for XON/XOFF character
+    - drm/nouveau/tegra: Stop using iommu_present()
+    - i40e: i40e_main: fix a missing check on list iterator
+    - cgroup/cpuset: Remove cpus_allowed/mems_allowed setup in cpuset_init_smp()
+    - drm/vmwgfx: Initialize drm_mode_fb_cmd2
+    - MIPS: fix build with gcc-12
+    - net: phy: Fix race condition on link status change
+    - arm[64]/memremap: don't abuse pfn_valid() to ensure presence of linear map
+    - ping: fix address binding wrt vrf
+    - tty/serial: digicolor: fix possible null-ptr-deref in digicolor_uart_probe()
+    - Linux 5.4.195
+  * Focal update: v5.4.194 upstream stable release (LP: #1980399)
+    - MIPS: Use address-of operator on section symbols
+    - block: drbd: drbd_nl: Make conversion to 'enum drbd_ret_code' explicit
+    - drm/amd/display/dc/gpio/gpio_service: Pass around correct dce_{version,
+      environment} types
+    - drm/i915: Cast remain to unsigned long in eb_relocate_vma
+    - nfp: bpf: silence bitwise vs. logical OR warning
+    - can: grcan: grcan_probe(): fix broken system id check for errata workaround
+      needs
+    - can: grcan: only use the NAPI poll budget for RX
+    - arm: remove CONFIG_ARCH_HAS_HOLES_MEMORYMODEL
+    - [Config] updateconfigs for ARCH_HAS_HOLES_MEMORYMODEL
+    - KVM: x86/pmu: Refactoring find_arch_event() to pmc_perf_hw_id()
+    - x86/asm: Allow to pass macros to __ASM_FORM()
+    - x86: xen: kvm: Gather the definition of emulate prefixes
+    - x86: xen: insn: Decode Xen and KVM emulate-prefix signature
+    - x86: kprobes: Prohibit probing on instruction which has emulate prefix
+    - KVM: x86/svm: Account for family 17h event renumberings in
+      amd_pmc_perf_hw_id
+    - Bluetooth: Fix the creation of hdev->name
+    - mm: fix missing cache flush for all tail pages of compound page
+    - mm: hugetlb: fix missing cache flush in copy_huge_page_from_user()
+    - mm: userfaultfd: fix missing cache flush in mcopy_atomic_pte() and
+      __mcopy_atomic()
+    - Linux 5.4.194
+  * Focal update: v5.4.193 upstream stable release (LP: #1979566)
+    - MIPS: Fix CP0 counter erratum detection for R4k CPUs
+    - parisc: Merge model and model name into one line in /proc/cpuinfo
+    - ALSA: fireworks: fix wrong return count shorter than expected by 4 bytes
+    - gpiolib: of: fix bounds check for 'gpio-reserved-ranges'
+    - Revert "SUNRPC: attempt AF_LOCAL connect on setup"
+    - firewire: fix potential uaf in outbound_phy_packet_callback()
+    - firewire: remove check of list iterator against head past the loop body
+    - firewire: core: extend card->lock in fw_core_handle_bus_reset
+    - ACPICA: Always create namespace nodes using acpi_ns_create_node()
+    - genirq: Synchronize interrupt thread startup
+    - ASoC: da7219: Fix change notifications for tone generator frequency
+    - ASoC: wm8958: Fix change notifications for DSP controls
+    - ASoC: meson: Fix event generation for G12A tohdmi mux
+    - s390/dasd: fix data corruption for ESE devices
+    - s390/dasd: prevent double format of tracks for ESE devices
+    - s390/dasd: Fix read for ESE with blksize < 4k
+    - s390/dasd: Fix read inconsistency for ESE DASD devices
+    - can: grcan: grcan_close(): fix deadlock
+    - can: grcan: use ofdev->dev when allocating DMA memory
+    - nfc: replace improper check device_is_registered() in netlink related
+      functions
+    - NFC: netlink: fix sleep in atomic bug when firmware download timeout
+    - hwmon: (adt7470) Fix warning on module removal
+    - ASoC: dmaengine: Restore NULL prepare_slave_config() callback
+    - RDMA/siw: Fix a condition race issue in MPA request processing
+    - net: ethernet: mediatek: add missing of_node_put() in mtk_sgmii_init()
+    - net: stmmac: dwmac-sun8i: add missing of_node_put() in
+      sun8i_dwmac_register_mdio_mux()
+    - net: emaclite: Add error handling for of_address_to_resource()
+    - selftests: mirror_gre_bridge_1q: Avoid changing PVID while interface is
+      operational
+    - bnxt_en: Fix possible bnxt_open() failure caused by wrong RFS flag
+    - smsc911x: allow using IRQ0
+    - btrfs: always log symlinks in full mode
+    - net: igmp: respect RCU rules in ip_mc_source() and ip_mc_msfilter()
+    - drm/amdkfd: Use drm_priv to pass VM from KFD to amdgpu
+    - NFSv4: Don't invalidate inode attributes on delegation return
+    - kvm: x86/cpuid: Only provide CPUID leaf 0xA if host has architectural PMU
+    - x86/kvm: Preserve BSP MSR_KVM_POLL_CONTROL across suspend/resume
+    - KVM: LAPIC: Enable timer posted-interrupt only when mwait/hlt is advertised
+    - net: ipv6: ensure we call ipv6_mc_down() at most once
+    - block-map: add __GFP_ZERO flag for alloc_page in function bio_copy_kern
+    - mm: fix unexpected zeroed page mapping with zram swap
+    - ALSA: pcm: Fix races among concurrent hw_params and hw_free calls
+    - ALSA: pcm: Fix races among concurrent read/write and buffer changes
+    - ALSA: pcm: Fix races among concurrent prepare and hw_params/hw_free calls
+    - ALSA: pcm: Fix races among concurrent prealloc proc writes
+    - ALSA: pcm: Fix potential AB/BA lock with buffer_mutex and mmap_lock
+    - tcp: make sure treq->af_specific is initialized
+    - dm: fix mempool NULL pointer race when completing IO
+    - dm: interlock pending dm_io and dm_wait_for_bios_completion
+    - PCI: aardvark: Clear all MSIs at setup
+    - PCI: aardvark: Fix reading MSI interrupt number
+    - mmc: rtsx: add 74 Clocks in power on flow
+    - Linux 5.4.193
+  * CVE-2022-1679
+    - SAUCE: ath9k: fix use-after-free in ath9k_hif_usb_rx_cb
+  * CVE-2022-28893
+    - SUNRPC: Ensure we flush any closed sockets before xs_xprt_free()
+    - SUNRPC: Don't leak sockets in xs_local_connect()
+  * CVE-2022-1734
+    - nfc: nfcmrvl: main: reorder destructive operations in
+      nfcmrvl_nci_unregister_dev to avoid bugs
+  * CVE-2022-1652
+    - floppy: use a statically allocated error counter
+
+  [ Ubuntu: 5.4.0-122.138 ]
+
+  * focal/linux: 5.4.0-122.138 -proposed tracker (LP: #1979489)
+  * Remove SAUCE patches from test_vxlan_under_vrf.sh in net of
+    ubuntu_kernel_selftests (LP: #1975691)
+    - Revert "UBUNTU: SAUCE: selftests: net: Don't fail test_vxlan_under_vrf on
+      xfail"
+    - Revert "UBUNTU: SAUCE: selftests: net: Make test for VXLAN underlay in non-
+      default VRF an expected failure"
+  * Enable Asus USB-BT500 Bluetooth dongle(0b05:190e) (LP: #1976613)
+    - Bluetooth: btusb: Add flag to define wideband speech capability
+    - Bluetooth: btrtl: Add support for RTL8761B
+    - Bluetooth: btusb: Add 0x0b05:0x190e Realtek 8761BU (ASUS BT500) device.
+  * [UBUNTU 20.04] rcu stalls with many storage key guests (LP: #1975582)
+    - s390/gmap: voluntarily schedule during key setting
+    - s390/mm: use non-quiescing sske for KVM switch to keyed guest
+  * Ubuntu 5.4.0-117.132-generic 5.4.189 has BUG: kernel NULL pointer
+    dereference, address: 0000000000000034 (LP: #1978719)
+    - mm: rmap: explicitly reset vma->anon_vma in unlink_anon_vmas()
+  * Focal update: upstream stable patchset v5.4.192 (LP: #1979014)
+    - floppy: disable FDRAWCMD by default
+    - [Config] updateconfigs for BLK_DEV_FD_RAWCMD
+    - hamradio: defer 6pack kfree after unregister_netdev
+    - hamradio: remove needs_free_netdev to avoid UAF
+    - lightnvm: disable the subsystem
+    - [Config] updateconfigs for NVM, NVM_PBLK
+    - usb: mtu3: fix USB 3.0 dual-role-switch from device to host
+    - USB: quirks: add a Realtek card reader
+    - USB: quirks: add STRING quirk for VCOM device
+    - USB: serial: whiteheat: fix heap overflow in WHITEHEAT_GET_DTR_RTS
+    - USB: serial: cp210x: add PIDs for Kamstrup USB Meter Reader
+    - USB: serial: option: add support for Cinterion MV32-WA/MV32-WB
+    - USB: serial: option: add Telit 0x1057, 0x1058, 0x1075 compositions
+    - xhci: stop polling roothubs after shutdown
+    - xhci: increase usb U3 -> U0 link resume timeout from 100ms to 500ms
+    - iio: dac: ad5592r: Fix the missing return value.
+    - iio: dac: ad5446: Fix read_raw not returning set value
+    - iio: magnetometer: ak8975: Fix the error handling in ak8975_power_on()
+    - usb: misc: fix improper handling of refcount in uss720_probe()
+    - usb: typec: ucsi: Fix role swapping
+    - usb: gadget: uvc: Fix crash when encoding data for usb request
+    - usb: gadget: configfs: clear deactivation flag in
+      configfs_composite_unbind()
+    - usb: dwc3: core: Fix tx/rx threshold settings
+    - usb: dwc3: gadget: Return proper request status
+    - serial: imx: fix overrun interrupts in DMA mode
+    - serial: 8250: Also set sticky MCR bits in console restoration
+    - serial: 8250: Correct the clock for EndRun PTP/1588 PCIe device
+    - arch_topology: Do not set llc_sibling if llc_id is invalid
+    - hex2bin: make the function hex_to_bin constant-time
+    - hex2bin: fix access beyond string end
+    - video: fbdev: udlfb: properly check endpoint type
+    - arm64: dts: meson: remove CPU opps below 1GHz for G12B boards
+    - arm64: dts: meson: remove CPU opps below 1GHz for SM1 boards
+    - mtd: rawnand: fix ecc parameters for mt7622
+    - USB: Fix xhci event ring dequeue pointer ERDP update issue
+    - ARM: dts: imx6qdl-apalis: Fix sgtl5000 detection issue
+    - phy: samsung: Fix missing of_node_put() in exynos_sata_phy_probe
+    - phy: samsung: exynos5250-sata: fix missing device put in probe error paths
+    - ARM: OMAP2+: Fix refcount leak in omap_gic_of_init
+    - phy: ti: omap-usb2: Fix error handling in omap_usb2_enable_clocks
+    - ARM: dts: at91: Map MCLK for wm8731 on at91sam9g20ek
+    - phy: mapphone-mdm6600: Fix PM error handling in phy_mdm6600_probe
+    - phy: ti: Add missing pm_runtime_disable() in serdes_am654_probe
+    - ARM: dts: Fix mmc order for omap3-gta04
+    - ARM: dts: am3517-evm: Fix misc pinmuxing
+    - ARM: dts: logicpd-som-lv: Fix wrong pinmuxing on OMAP35
+    - ipvs: correctly print the memory size of ip_vs_conn_tab
+    - mtd: rawnand: Fix return value check of wait_for_completion_timeout
+    - bpf, lwt: Fix crash when using bpf_skb_set_tunnel_key() from bpf_xmit lwt
+      hook
+    - tcp: md5: incorrect tcp_header_len for incoming connections
+    - tcp: ensure to use the most recently sent skb when filling the rate sample
+    - sctp: check asoc strreset_chunk in sctp_generate_reconf_event
+    - ARM: dts: imx6ull-colibri: fix vqmmc regulator
+    - arm64: dts: imx8mn-ddr4-evk: Describe the 32.768 kHz PMIC clock
+    - pinctrl: pistachio: fix use of irq_of_parse_and_map()
+    - cpufreq: fix memory leak in sun50i_cpufreq_nvmem_probe
+    - net: hns3: add validity check for message data length
+    - net/smc: sync err code when tcp connection was refused
+    - ip_gre: Make o_seqno start from 0 in native mode
+    - tcp: fix potential xmit stalls caused by TCP_NOTSENT_LOWAT
+    - bus: sunxi-rsb: Fix the return value of sunxi_rsb_device_create()
+    - clk: sunxi: sun9i-mmc: check return value after calling
+      platform_get_resource()
+    - net: bcmgenet: hide status block before TX timestamping
+    - net: dsa: lantiq_gswip: Don't set GSWIP_MII_CFG_RMII_CLK
+    - drm/amd/display: Fix memory leak in dcn21_clock_source_create
+    - tls: Skip tls_append_frag on zero copy size
+    - bnx2x: fix napi API usage sequence
+    - ixgbe: ensure IPsec VF<->PF compatibility
+    - tcp: fix F-RTO may not work correctly when receiving DSACK
+    - ASoC: wm8731: Disable the regulator when probing fails
+    - ip6_gre: Avoid updating tunnel->tun_hlen in __gre6_xmit()
+    - x86: __memcpy_flushcache: fix wrong alignment if size > 2^32
+    - cifs: destage any unwritten data to the server before calling
+      copychunk_write
+    - drivers: net: hippi: Fix deadlock in rr_close()
+    - net: ethernet: stmmac: fix write to sgmii_adapter_base
+    - x86/cpu: Load microcode during restore_processor_state()
+    - tty: n_gsm: fix wrong signal octet encoding in convergence layer type 2
+    - tty: n_gsm: fix malformed counter for out of frame data
+    - netfilter: nft_socket: only do sk lookups when indev is available
+    - tty: n_gsm: fix insufficient txframe size
+    - tty: n_gsm: fix missing explicit ldisc flush
+    - tty: n_gsm: fix wrong command retry handling
+    - tty: n_gsm: fix wrong command frame length field encoding
+    - tty: n_gsm: fix incorrect UA handling
+    - hugetlbfs: get unmapped area below TASK_UNMAPPED_BASE for hugetlbfs
+    - mm, hugetlb: allow for "high" userspace addresses
+    - Linux 5.4.192
+  * CVE-2022-1789
+    - KVM: x86/mmu: fix NULL pointer dereference on guest INVPCID
+  * Focal update: v5.4.191 upstream stable release (LP: #1976116)
+    - etherdevice: Adjust ether_addr* prototypes to silence -Wstringop-overead
+    - mm: page_alloc: fix building error on -Werror=array-compare
+    - tracing: Dump stacktrace trigger to the corresponding instance
+    - gfs2: assign rgrp glock before compute_bitstructs
+    - tcp: fix race condition when creating child sockets from syncookies
+    - tcp: Fix potential use-after-free due to double kfree()
+    - ALSA: usb-audio: Clear MIDI port active flag after draining
+    - ASoC: atmel: Remove system clock tree configuration for at91sam9g20ek
+    - ASoC: msm8916-wcd-digital: Check failure for devm_snd_soc_register_component
+    - dmaengine: imx-sdma: Fix error checking in sdma_event_remap
+    - dmaengine: mediatek:Fix PM usage reference leak of
+      mtk_uart_apdma_alloc_chan_resources
+    - igc: Fix infinite loop in release_swfw_sync
+    - igc: Fix BUG: scheduling while atomic
+    - rxrpc: Restore removed timer deletion
+    - net/smc: Fix sock leak when release after smc_shutdown()
+    - net/packet: fix packet_sock xmit return value checking
+    - net/sched: cls_u32: fix possible leak in u32_init_knode()
+    - l3mdev: l3mdev_master_upper_ifindex_by_index_rcu should be using
+      netdev_master_upper_dev_get_rcu
+    - netlink: reset network and mac headers in netlink_dump()
+    - selftests: mlxsw: vxlan_flooding: Prevent flooding of unwanted packets
+    - ARM: vexpress/spc: Avoid negative array index when !SMP
+    - reset: tegra-bpmp: Restore Handle errors in BPMP response
+    - platform/x86: samsung-laptop: Fix an unsigned comparison which can never be
+      negative
+    - ALSA: usb-audio: Fix undefined behavior due to shift overflowing the
+      constant
+    - vxlan: fix error return code in vxlan_fdb_append
+    - cifs: Check the IOCB_DIRECT flag, not O_DIRECT
+    - mt76: Fix undefined behavior due to shift overflowing the constant
+    - brcmfmac: sdio: Fix undefined behavior due to shift overflowing the constant
+    - dpaa_eth: Fix missing of_node_put in dpaa_get_ts_info()
+    - drm/msm/mdp5: check the return of kzalloc()
+    - net: macb: Restart tx only if queue pointer is lagging
+    - scsi: qedi: Fix failed disconnect handling
+    - stat: fix inconsistency between struct stat and struct compat_stat
+    - EDAC/synopsys: Read the error count from the correct register
+    - oom_kill.c: futex: delay the OOM reaper to allow time for proper futex
+      cleanup
+    - ata: pata_marvell: Check the 'bmdma_addr' beforing reading
+    - dma: at_xdmac: fix a missing check on list iterator
+    - drm/panel/raspberrypi-touchscreen: Avoid NULL deref if not initialised
+    - drm/panel/raspberrypi-touchscreen: Initialise the bridge in prepare
+    - KVM: PPC: Fix TCE handling for VFIO
+    - drm/vc4: Use pm_runtime_resume_and_get to fix pm_runtime_get_sync() usage
+    - powerpc/perf: Fix power9 event alternatives
+    - xtensa: patch_text: Fixup last cpu should be master
+    - xtensa: fix a7 clobbering in coprocessor context load/store
+    - openvswitch: fix OOB access in reserve_sfa_size()
+    - ASoC: soc-dapm: fix two incorrect uses of list iterator
+    - e1000e: Fix possible overflow in LTR decoding
+    - ARC: entry: fix syscall_trace_exit argument
+    - arm_pmu: Validate single/group leader events
+    - ext4: fix symlink file size not match to file content
+    - ext4: fix use-after-free in ext4_search_dir
+    - ext4, doc: fix incorrect h_reserved size
+    - ext4: fix overhead calculation to account for the reserved gdt blocks
+    - ext4: force overhead calculation if the s_overhead_cluster makes no sense
+    - jbd2: fix a potential race while discarding reserved buffers after an abort
+    - spi: atmel-quadspi: Fix the buswidth adjustment between spi-mem and
+      controller
+    - staging: ion: Prevent incorrect reference counting behavour
+    - block/compat_ioctl: fix range check in BLKGETSIZE
+    - Linux 5.4.191
+  * Focal update: v5.4.190 upstream stable release (LP: #1973085)
+    - memory: atmel-ebi: Fix missing of_node_put in atmel_ebi_probe
+    - net/sched: flower: fix parsing of ethertype following VLAN header
+    - veth: Ensure eth header is in skb's linear part
+    - gpiolib: acpi: use correct format characters
+    - mlxsw: i2c: Fix initialization error flow
+    - net/sched: fix initialization order when updating chain 0 head
+    - net: ethernet: stmmac: fix altr_tse_pcs function when using a fixed-link
+    - net/sched: taprio: Check if socket flags are valid
+    - cfg80211: hold bss_lock while updating nontrans_list
+    - drm/msm/dsi: Use connector directly in msm_dsi_manager_connector_init()
+    - net/smc: Fix NULL pointer dereference in smc_pnet_find_ib()
+    - sctp: Initialize daddr on peeled off socket
+    - testing/selftests/mqueue: Fix mq_perf_tests to free the allocated cpu set
+    - nfc: nci: add flush_workqueue to prevent uaf
+    - cifs: potential buffer overflow in handling symlinks
+    - drm/amd: Add USBC connector ID
+    - drm/amd/display: fix audio format not updated after edid updated
+    - drm/amd/display: Update VTEM Infopacket definition
+    - drm/amdkfd: Fix Incorrect VMIDs passed to HWS
+    - drm/amdkfd: Check for potential null return of kmalloc_array()
+    - Drivers: hv: vmbus: Prevent load re-ordering when reading ring buffer
+    - scsi: target: tcmu: Fix possible page UAF
+    - scsi: ibmvscsis: Increase INITIAL_SRP_LIMIT to 1024
+    - ata: libata-core: Disable READ LOG DMA EXT for Samsung 840 EVOs
+    - gpu: ipu-v3: Fix dev_dbg frequency output
+    - regulator: wm8994: Add an off-on delay for WM8994 variant
+    - arm64: alternatives: mark patch_alternative() as `noinstr`
+    - tlb: hugetlb: Add more sizes to tlb_remove_huge_tlb_entry
+    - net: usb: aqc111: Fix out-of-bounds accesses in RX fixup
+    - drm/amd/display: Fix allocate_mst_payload assert on resume
+    - powerpc: Fix virt_addr_valid() for 64-bit Book3E & 32-bit
+    - scsi: mvsas: Add PCI ID of RocketRaid 2640
+    - scsi: megaraid_sas: Target with invalid LUN ID is deleted during scan
+    - drivers: net: slip: fix NPD bug in sl_tx_timeout()
+    - perf/imx_ddr: Fix undefined behavior due to shift overflowing the constant
+    - mm, page_alloc: fix build_zonerefs_node()
+    - mm: kmemleak: take a full lowmem check in kmemleak_*_phys()
+    - gcc-plugins: latent_entropy: use /dev/urandom
+    - ath9k: Properly clear TX status area before reporting to mac80211
+    - ath9k: Fix usage of driver-private space in tx_info
+    - btrfs: remove unused variable in btrfs_{start,write}_dirty_block_groups()
+    - btrfs: mark resumed async balance as writing
+    - ALSA: hda/realtek: Add quirk for Clevo PD50PNT
+    - ALSA: pcm: Test for "silence" field in struct "pcm_format_data"
+    - ipv6: fix panic when forwarding a pkt with no in6 dev
+    - drm/amd/display: don't ignore alpha property on pre-multiplied mode
+    - genirq/affinity: Consider that CPUs on nodes can be unbalanced
+    - tick/nohz: Use WARN_ON_ONCE() to prevent console saturation
+    - ARM: davinci: da850-evm: Avoid NULL pointer dereference
+    - dm integrity: fix memory corruption when tag_size is less than digest size
+    - smp: Fix offline cpu check in flush_smp_call_function_queue()
+    - i2c: pasemi: Wait for write xfers to finish
+    - dma-direct: avoid redundant memory sync for swiotlb
+    - ax25: add refcount in ax25_dev to avoid UAF bugs
+    - ax25: fix reference count leaks of ax25_dev
+    - ax25: fix UAF bugs of net_device caused by rebinding operation
+    - ax25: Fix refcount leaks caused by ax25_cb_del()
+    - ax25: fix UAF bug in ax25_send_control()
+    - ax25: fix NPD bug in ax25_disconnect
+    - ax25: Fix NULL pointer dereferences in ax25 timers
+    - ax25: Fix UAF bugs in ax25 timers
+    - Linux 5.4.190
+
+  [ Ubuntu: 5.4.0-121.137 ]
+
+  * focal/linux: 5.4.0-121.137 -proposed tracker (LP: #1978666)
+  * Packaging resync (LP: #1786013)
+    - debian/dkms-versions -- update from kernel-versions (main/2022.05.30)
+  * CVE-2022-28388
+    - can: usb_8dev: usb_8dev_start_xmit(): fix double dev_kfree_skb() in error
+      path
+  * test_vxlan_under_vrf.sh in net from ubuntu_kernel_selftests failed (Check VM
+    connectivity through VXLAN (underlay in the default VRF) [FAIL])
+    (LP: #1871015)
+    - selftests: net: test_vxlan_under_vrf: fix HV connectivity test
+  * [UBUNTU 20.04] CPU-MF: add extended counter set definitions for new IBM z16
+    (LP: #1974433)
+    - s390/cpumf: add new extended counter set for IBM z16
+  * [UBUNTU 20.04] KVM nesting support leaks too much memory, might result in
+    stalls during cleanup (LP: #1974017)
+    - KVM: s390: vsie/gmap: reduce gmap_rmap overhead
+  * [UBUNTU 20.04] Null Pointer issue in nfs code running Ubuntu on IBM Z
+    (LP: #1968096)
+    - NFS: Fix up nfs_ctx_key_to_expire()
+
+  [ Ubuntu: 5.4.0-120.136 ]
+
+  * CVE-2022-21123 // CVE-2022-21125 // CVE-2022-21166
+    - cpu/speculation: Add prototype for cpu_show_srbds()
+    - x86/cpu: Add Jasper Lake to Intel family
+    - x86/cpu: Add Lakefield, Alder Lake and Rocket Lake models to the to Intel
+      CPU family
+    - x86/cpu: Add another Alder Lake CPU to the Intel family
+    - Documentation: Add documentation for Processor MMIO Stale Data
+    - x86/speculation/mmio: Enumerate Processor MMIO Stale Data bug
+    - x86/speculation: Add a common function for MD_CLEAR mitigation update
+    - x86/speculation/mmio: Add mitigation for Processor MMIO Stale Data
+    - x86/bugs: Group MDS, TAA & Processor MMIO Stale Data mitigations
+    - x86/speculation/mmio: Enable CPU Fill buffer clearing on idle
+    - x86/speculation/mmio: Add sysfs reporting for Processor MMIO Stale Data
+    - x86/speculation/srbds: Update SRBDS mitigation selection
+    - x86/speculation/mmio: Reuse SRBDS mitigation for SBDS
+    - KVM: x86/speculation: Disable Fill buffer clear within guests
+    - x86/speculation/mmio: Print SMT warning
+
+  [ Ubuntu: 5.4.0-117.132 ]
+
+  * CVE-2022-1966
+    - netfilter: nf_tables: add nft_set_elem_expr_alloc()
+    - netfilter: nf_tables: disallow non-stateful expression in sets earlier
+
+  [ Ubuntu: 5.4.0-115.129 ]
+
+  * CVE-2022-21499
+    - SAUCE: debug: Lock down kgdb
+
+  [ Ubuntu: 5.4.0-114.128 ]
+
+  * focal/linux: 5.4.0-114.128 -proposed tracker (LP: #1974391)
+  * 32 GT/s PCI link speeds reporting "Unknown speed" in sysfs (LP: #1970798)
+    - PCI: Add 32 GT/s decoding in some macros
+    - PCI: Add pci_speed_string()
+    - PCI: Use pci_speed_string() for all PCI/PCI-X/PCIe strings
+    - PCI: Add PCIE_LNKCAP2_SLS2SPEED() macro
+  * issuing invalid ioctl to /dev/vsock may spam dmesg (LP: #1971480)
+    - vsock: remove ratelimit unknown ioctl message
+  * config CONFIG_HISI_PMU for  kunpeng920 (LP: #1956086)
+    - drivers/perf: hisi: Permit modular builds of HiSilicon uncore drivers
+    - [Config] CONFIG_HISI_PMU=m
+  * Focal update: v5.4.189 upstream stable release (LP: #1971497)
+    - swiotlb: fix info leak with DMA_FROM_DEVICE
+    - USB: serial: pl2303: add IBM device IDs
+    - USB: serial: simple: add Nokia phone driver
+    - netdevice: add the case if dev is NULL
+    - HID: logitech-dj: add new lightspeed receiver id
+    - xfrm: fix tunnel model fragmentation behavior
+    - virtio_console: break out of buf poll on remove
+    - ethernet: sun: Free the coherent when failing in probing
+    - spi: Fix invalid sgs value
+    - net:mcf8390: Use platform_get_irq() to get the interrupt
+    - spi: Fix erroneous sgs value with min_t()
+    - af_key: add __GFP_ZERO flag for compose_sadb_supported in function
+      pfkey_register
+    - net: dsa: microchip: add spi_device_id tables
+    - iommu/iova: Improve 32-bit free space estimate
+    - tpm: fix reference counting for struct tpm_chip
+    - block: Add a helper to validate the block size
+    - virtio-blk: Use blk_validate_block_size() to validate block size
+    - USB: usb-storage: Fix use of bitfields for hardware data in ene_ub6250.c
+    - xhci: fix runtime PM imbalance in USB2 resume
+    - xhci: make xhci_handshake timeout for xhci_reset() adjustable
+    - xhci: fix uninitialized string returned by xhci_decode_ctrl_ctx()
+    - coresight: Fix TRCCONFIGR.QE sysfs interface
+    - iio: afe: rescale: use s64 for temporary scale calculations
+    - iio: inkern: apply consumer scale on IIO_VAL_INT cases
+    - iio: inkern: apply consumer scale when no channel scale is available
+    - iio: inkern: make a best effort on offset calculation
+    - greybus: svc: fix an error handling bug in gb_svc_hello()
+    - clk: uniphier: Fix fixed-rate initialization
+    - KEYS: fix length validation in keyctl_pkey_params_get_2()
+    - Documentation: add link to stable release candidate tree
+    - Documentation: update stable tree link
+    - HID: intel-ish-hid: Use dma_alloc_coherent for firmware update
+    - SUNRPC: avoid race between mod_timer() and del_timer_sync()
+    - NFSD: prevent underflow in nfssvc_decode_writeargs()
+    - NFSD: prevent integer overflow on 32 bit systems
+    - f2fs: fix to unlock page correctly in error path of is_alive()
+    - f2fs: quota: fix loop condition at f2fs_quota_sync()
+    - f2fs: fix to do sanity check on .cp_pack_total_block_count
+    - pinctrl: samsung: drop pin banks references on error paths
+    - spi: mxic: Fix the transmit path
+    - jffs2: fix use-after-free in jffs2_clear_xattr_subsystem
+    - jffs2: fix memory leak in jffs2_do_mount_fs
+    - jffs2: fix memory leak in jffs2_scan_medium
+    - mm/pages_alloc.c: don't create ZONE_MOVABLE beyond the end of a node
+    - mm: invalidate hwpoison page cache page in fault path
+    - mempolicy: mbind_range() set_policy() after vma_merge()
+    - scsi: libsas: Fix sas_ata_qc_issue() handling of NCQ NON DATA commands
+    - qed: display VF trust config
+    - qed: validate and restrict untrusted VFs vlan promisc mode
+    - riscv: Fix fill_callchain return value
+    - Revert "Input: clear BTN_RIGHT/MIDDLE on buttonpads"
+    - ALSA: cs4236: fix an incorrect NULL check on list iterator
+    - ALSA: hda/realtek: Fix audio regression on Mi Notebook Pro 2020
+    - mm,hwpoison: unmap poisoned page before invalidation
+    - mm/kmemleak: reset tag when compare object pointer
+    - drbd: fix potential silent data corruption
+    - powerpc/kvm: Fix kvm_use_magic_page
+    - udp: call udp_encap_enable for v6 sockets when enabling encap
+    - ACPI: properties: Consistently return -ENOENT if there are no more
+      references
+    - drivers: hamradio: 6pack: fix UAF bug caused by mod_timer()
+    - mailbox: tegra-hsp: Flush whole channel
+    - block: don't merge across cgroup boundaries if blkcg is enabled
+    - drm/edid: check basic audio support on CEA extension block
+    - video: fbdev: sm712fb: Fix crash in smtcfb_read()
+    - video: fbdev: atari: Atari 2 bpp (STe) palette bugfix
+    - ARM: dts: at91: sama5d2: Fix PMERRLOC resource size
+    - ARM: dts: exynos: fix UART3 pins configuration in Exynos5250
+    - ARM: dts: exynos: add missing HDMI supplies on SMDK5250
+    - ARM: dts: exynos: add missing HDMI supplies on SMDK5420
+    - carl9170: fix missing bit-wise or operator for tx_params
+    - thermal: int340x: Increase bitmap size
+    - lib/raid6/test: fix multiple definition linking error
+    - crypto: rsa-pkcs1pad - correctly get hash from source scatterlist
+    - crypto: rsa-pkcs1pad - restore signature length check
+    - crypto: rsa-pkcs1pad - fix buffer overread in pkcs1pad_verify_complete()
+    - DEC: Limit PMAX memory probing to R3k systems
+    - media: davinci: vpif: fix unbalanced runtime PM get
+    - xtensa: fix stop_machine_cpuslocked call in patch_text
+    - xtensa: fix xtensa_wsr always writing 0
+    - brcmfmac: firmware: Allocate space for default boardrev in nvram
+    - brcmfmac: pcie: Release firmwares in the brcmf_pcie_setup error path
+    - brcmfmac: pcie: Replace brcmf_pcie_copy_mem_todev with memcpy_toio
+    - brcmfmac: pcie: Fix crashes due to early IRQs
+    - PCI: pciehp: Clear cmd_busy bit in polling mode
+    - regulator: qcom_smd: fix for_each_child.cocci warnings
+    - crypto: authenc - Fix sleep in atomic context in decrypt_tail
+    - crypto: mxs-dcp - Fix scatterlist processing
+    - spi: tegra114: Add missing IRQ check in tegra_spi_probe
+    - selftests/x86: Add validity check and allow field splitting
+    - audit: log AUDIT_TIME_* records only from rules
+    - crypto: ccree - don't attempt 0 len DMA mappings
+    - spi: pxa2xx-pci: Balance reference count for PCI DMA device
+    - hwmon: (pmbus) Add mutex to regulator ops
+    - hwmon: (sch56xx-common) Replace WDOG_ACTIVE with WDOG_HW_RUNNING
+    - block: don't delete queue kobject before its children
+    - PM: hibernate: fix __setup handler error handling
+    - PM: suspend: fix return value of __setup handler
+    - hwrng: atmel - disable trng on failure path
+    - crypto: vmx - add missing dependencies
+    - clocksource/drivers/timer-of: Check return value of of_iomap in
+      timer_of_base_init()
+    - ACPI: APEI: fix return value of __setup handlers
+    - crypto: ccp - ccp_dmaengine_unregister release dma channels
+    - hwmon: (pmbus) Add Vin unit off handling
+    - clocksource: acpi_pm: fix return value of __setup handler
+    - sched/debug: Remove mpol_get/put and task_lock/unlock from sched_show_numa
+    - perf/core: Fix address filter parser for multiple filters
+    - perf/x86/intel/pt: Fix address filter config for 32-bit kernel
+    - f2fs: fix missing free nid in f2fs_handle_failed_inode
+    - f2fs: fix to avoid potential deadlock
+    - media: bttv: fix WARNING regression on tunerless devices
+    - media: coda: Fix missing put_device() call in coda_get_vdoa_data
+    - media: hantro: Fix overfill bottom register field name
+    - media: aspeed: Correct value for h-total-pixels
+    - video: fbdev: smscufx: Fix null-ptr-deref in ufx_usb_probe()
+    - video: fbdev: atmel_lcdfb: fix an error code in atmel_lcdfb_probe()
+    - video: fbdev: fbcvt.c: fix printing in fb_cvt_print_name()
+    - ARM: dts: qcom: ipq4019: fix sleep clock
+    - soc: qcom: rpmpd: Check for null return of devm_kcalloc
+    - soc: qcom: aoss: remove spurious IRQF_ONESHOT flags
+    - arm64: dts: qcom: sm8150: Correct TCS configuration for apps rsc
+    - soc: ti: wkup_m3_ipc: Fix IRQ check in wkup_m3_ipc_probe
+    - ARM: dts: imx: Add missing LVDS decoder on M53Menlo
+    - media: video/hdmi: handle short reads of hdmi info frame.
+    - media: em28xx: initialize refcount before kref_get
+    - media: usb: go7007: s2250-board: fix leak in probe()
+    - uaccess: fix nios2 and microblaze get_user_8()
+    - ASoC: rt5663: check the return value of devm_kzalloc() in rt5663_parse_dp()
+    - ASoC: ti: davinci-i2s: Add check for clk_enable()
+    - ALSA: spi: Add check for clk_enable()
+    - arm64: dts: ns2: Fix spi-cpol and spi-cpha property
+    - arm64: dts: broadcom: Fix sata nodename
+    - printk: fix return value of printk.devkmsg __setup handler
+    - ASoC: mxs-saif: Handle errors for clk_enable
+    - ASoC: atmel_ssc_dai: Handle errors for clk_enable
+    - ASoC: soc-compress: prevent the potentially use of null pointer
+    - memory: emif: Add check for setup_interrupts
+    - memory: emif: check the pointer temp in get_device_details()
+    - ALSA: firewire-lib: fix uninitialized flag for AV/C deferred transaction
+    - arm64: dts: rockchip: Fix SDIO regulator supply properties on rk3399-firefly
+    - media: stk1160: If start stream fails, return buffers with
+      VB2_BUF_STATE_QUEUED
+    - ASoC: atmel: Add missing of_node_put() in at91sam9g20ek_audio_probe
+    - ASoC: wm8350: Handle error for wm8350_register_irq
+    - ASoC: fsi: Add check for clk_enable
+    - video: fbdev: omapfb: Add missing of_node_put() in dvic_probe_of
+    - ivtv: fix incorrect device_caps for ivtvfb
+    - ASoC: dmaengine: do not use a NULL prepare_slave_config() callback
+    - ASoC: mxs: Fix error handling in mxs_sgtl5000_probe
+    - ASoC: imx-es8328: Fix error return code in imx_es8328_probe()
+    - ASoC: msm8916-wcd-digital: Fix missing clk_disable_unprepare() in
+      msm8916_wcd_digital_probe
+    - mmc: davinci_mmc: Handle error for clk_enable
+    - ASoC: msm8916-wcd-analog: Fix error handling in pm8916_wcd_analog_spmi_probe
+    - drm/bridge: Fix free wrong object in sii8620_init_rcp_input_dev
+    - drm/bridge: Add missing pm_runtime_disable() in __dw_mipi_dsi_probe
+    - ath10k: fix memory overwrite of the WoWLAN wakeup packet pattern
+    - udmabuf: validate ubuf->pagecount
+    - Bluetooth: hci_serdev: call init_rwsem() before p->open()
+    - mtd: onenand: Check for error irq
+    - mtd: rawnand: gpmi: fix controller timings setting
+    - drm/edid: Don't clear formats if using deep color
+    - drm/amd/display: Fix a NULL pointer dereference in
+      amdgpu_dm_connector_add_common_modes()
+    - ath9k_htc: fix uninit value bugs
+    - KVM: PPC: Fix vmx/vsx mixup in mmio emulation
+    - i40e: don't reserve excessive XDP_PACKET_HEADROOM on XSK Rx to skb
+    - power: reset: gemini-poweroff: Fix IRQ check in gemini_poweroff_probe
+    - ray_cs: Check ioremap return value
+    - powerpc/perf: Don't use perf_hw_context for trace IMC PMU
+    - mt76: mt7603: check sta_rates pointer in mt7603_sta_rate_tbl_update
+    - mt76: mt7615: check sta_rates pointer in mt7615_sta_rate_tbl_update
+    - net: dsa: mv88e6xxx: Enable port policy support on 6097
+    - PCI: aardvark: Fix reading PCI_EXP_RTSTA_PME bit on emulated bridge
+    - power: supply: ab8500: Fix memory leak in ab8500_fg_sysfs_init
+    - HID: i2c-hid: fix GET/SET_REPORT for unnumbered reports
+    - iommu/ipmmu-vmsa: Check for error num after setting mask
+    - drm/amd/display: Add affected crtcs to atomic state for dsc mst unplug
+    - IB/cma: Allow XRC INI QPs to set their local ACK timeout
+    - dax: make sure inodes are flushed before destroy cache
+    - iwlwifi: Fix -EIO error code that is never returned
+    - iwlwifi: mvm: Fix an error code in iwl_mvm_up()
+    - dm crypt: fix get_key_size compiler warning if !CONFIG_KEYS
+    - scsi: pm8001: Fix command initialization in pm80XX_send_read_log()
+    - scsi: pm8001: Fix command initialization in pm8001_chip_ssp_tm_req()
+    - scsi: pm8001: Fix payload initialization in pm80xx_set_thermal_config()
+    - scsi: pm8001: Fix abort all task initialization
+    - drm/amd/display: Remove vupdate_int_entry definition
+    - TOMOYO: fix __setup handlers return values
+    - ext2: correct max file size computing
+    - drm/tegra: Fix reference leak in tegra_dsi_ganged_probe
+    - power: supply: bq24190_charger: Fix bq24190_vbus_is_enabled() wrong false
+      return
+    - scsi: hisi_sas: Change permission of parameter prot_mask
+    - drm/bridge: cdns-dsi: Make sure to to create proper aliases for dt
+    - bpf, arm64: Call build_prologue() first in first JIT pass
+    - bpf, arm64: Feed byte-offset into bpf line info
+    - libbpf: Skip forward declaration when counting duplicated type names
+    - powerpc/Makefile: Don't pass -mcpu=powerpc64 when building 32-bit
+    - KVM: x86: Fix emulation in writing cr8
+    - KVM: x86/emulator: Defer not-present segment check in
+      __load_segment_descriptor()
+    - hv_balloon: rate-limit "Unhandled message" warning
+    - i2c: xiic: Make bus names unique
+    - power: supply: wm8350-power: Handle error for wm8350_register_irq
+    - power: supply: wm8350-power: Add missing free in free_charger_irq
+    - PCI: Reduce warnings on possible RW1C corruption
+    - mips: DEC: honor CONFIG_MIPS_FP_SUPPORT=n
+    - powerpc/sysdev: fix incorrect use to determine if list is empty
+    - mfd: mc13xxx: Add check for mc13xxx_irq_request
+    - selftests/bpf: Make test_lwt_ip_encap more stable and faster
+    - powerpc: 8xx: fix a return value error in mpc8xx_pic_init
+    - vxcan: enable local echo for sent CAN frames
+    - MIPS: RB532: fix return value of __setup handler
+    - mtd: rawnand: atmel: fix refcount issue in atmel_nand_controller_init
+    - RDMA/mlx5: Fix memory leak in error flow for subscribe event routine
+    - bpf, sockmap: Fix memleak in tcp_bpf_sendmsg while sk msg is full
+    - bpf, sockmap: Fix more uncharged while msg has more_data
+    - bpf, sockmap: Fix double uncharge the mem of sk_msg
+    - USB: storage: ums-realtek: fix error code in rts51x_read_mem()
+    - Bluetooth: btmtksdio: Fix kernel oops in btmtksdio_interrupt
+    - af_netlink: Fix shift out of bounds in group mask calculation
+    - i2c: mux: demux-pinctrl: do not deactivate a master that is not active
+    - selftests/bpf/test_lirc_mode2.sh: Exit with proper code
+    - tcp: ensure PMTU updates are processed during fastopen
+    - openvswitch: always update flow key after nat
+    - tipc: fix the timer expires after interval 100ms
+    - mfd: asic3: Add missing iounmap() on error asic3_mfd_probe
+    - mxser: fix xmit_buf leak in activate when LSR == 0xff
+    - pwm: lpc18xx-sct: Initialize driver data and hardware before pwmchip_add()
+    - misc: alcor_pci: Fix an error handling path
+    - staging:iio:adc:ad7280a: Fix handing of device address bit reversing.
+    - pinctrl: renesas: r8a77470: Reduce size for narrow VIN1 channel
+    - clk: qcom: ipq8074: Use floor ops for SDCC1 clock
+    - phy: dphy: Correct lpx parameter and its derivatives(ta_{get,go,sure})
+    - serial: 8250_mid: Balance reference count for PCI DMA device
+    - serial: 8250: Fix race condition in RTS-after-send handling
+    - iio: adc: Add check for devm_request_threaded_irq
+    - NFS: Return valid errors from nfs2/3_decode_dirent()
+    - dma-debug: fix return value of __setup handlers
+    - clk: imx7d: Remove audio_mclk_root_clk
+    - clk: qcom: clk-rcg2: Update logic to calculate D value for RCG
+    - clk: qcom: clk-rcg2: Update the frac table for pixel clock
+    - remoteproc: qcom: Fix missing of_node_put in adsp_alloc_memory_region
+    - remoteproc: qcom_wcnss: Add missing of_node_put() in
+      wcnss_alloc_memory_region
+    - clk: actions: Terminate clk_div_table with sentinel element
+    - clk: loongson1: Terminate clk_div_table with sentinel element
+    - clk: clps711x: Terminate clk_div_table with sentinel element
+    - clk: tegra: tegra124-emc: Fix missing put_device() call in
+      emc_ensure_emc_driver
+    - NFS: remove unneeded check in decode_devicenotify_args()
+    - staging: mt7621-dts: fix LEDs and pinctrl on GB-PC1 devicetree
+    - pinctrl: mediatek: Fix missing of_node_put() in mtk_pctrl_init
+    - pinctrl: mediatek: paris: Fix "argument" argument type for mtk_pinconf_get()
+    - pinctrl: mediatek: paris: Fix pingroup pin config state readback
+    - pinctrl: nomadik: Add missing of_node_put() in nmk_pinctrl_probe
+    - pinctrl/rockchip: Add missing of_node_put() in rockchip_pinctrl_probe
+    - tty: hvc: fix return value of __setup handler
+    - kgdboc: fix return value of __setup handler
+    - kgdbts: fix return value of __setup handler
+    - firmware: google: Properly state IOMEM dependency
+    - driver core: dd: fix return value of __setup handler
+    - jfs: fix divide error in dbNextAG
+    - netfilter: nf_conntrack_tcp: preserve liberal flag in tcp options
+    - NFSv4.1: don't retry BIND_CONN_TO_SESSION on session error
+    - clk: qcom: gcc-msm8994: Fix gpll4 width
+    - clk: Initialize orphan req_rate
+    - xen: fix is_xen_pmu()
+    - net: phy: broadcom: Fix brcm_fet_config_init()
+    - selftests: test_vxlan_under_vrf: Fix broken test case
+    - qlcnic: dcb: default to returning -EOPNOTSUPP
+    - net/x25: Fix null-ptr-deref caused by x25_disconnect
+    - NFSv4/pNFS: Fix another issue with a list iterator pointing to the head
+    - net: dsa: bcm_sf2_cfp: fix an incorrect NULL check on list iterator
+    - lib/test: use after free in register_test_dev_kmod()
+    - LSM: general protection fault in legacy_parse_param
+    - gcc-plugins/stackleak: Exactly match strings instead of prefixes
+    - pinctrl: npcm: Fix broken references to chip->parent_device
+    - block, bfq: don't move oom_bfqq
+    - selinux: use correct type for context length
+    - loop: use sysfs_emit() in the sysfs xxx show()
+    - Fix incorrect type in assignment of ipv6 port for audit
+    - irqchip/qcom-pdc: Fix broken locking
+    - irqchip/nvic: Release nvic_base upon failure
+    - bfq: fix use-after-free in bfq_dispatch_request
+    - ACPICA: Avoid walking the ACPI Namespace if it is not there
+    - lib/raid6/test/Makefile: Use $(pound) instead of \# for Make 4.3
+    - Revert "Revert "block, bfq: honor already-setup queue merges""
+    - ACPI/APEI: Limit printable size of BERT table data
+    - PM: core: keep irq flags in device_pm_check_callbacks()
+    - spi: tegra20: Use of_device_get_match_data()
+    - ext4: don't BUG if someone dirty pages without asking ext4 first
+    - ntfs: add sanity check on allocation size
+    - video: fbdev: nvidiafb: Use strscpy() to prevent buffer overflow
+    - video: fbdev: w100fb: Reset global state
+    - video: fbdev: cirrusfb: check pixclock to avoid divide by zero
+    - video: fbdev: omapfb: acx565akm: replace snprintf with sysfs_emit
+    - ARM: dts: qcom: fix gic_irq_domain_translate warnings for msm8960
+    - ARM: dts: bcm2837: Add the missing L1/L2 cache information
+    - ASoC: madera: Add dependencies on MFD
+    - video: fbdev: omapfb: panel-dsi-cm: Use sysfs_emit() instead of snprintf()
+    - video: fbdev: omapfb: panel-tpo-td043mtea1: Use sysfs_emit() instead of
+      snprintf()
+    - video: fbdev: udlfb: replace snprintf in show functions with sysfs_emit
+    - ASoC: soc-core: skip zero num_dai component in searching dai name
+    - media: cx88-mpeg: clear interrupt status register before streaming video
+    - ARM: tegra: tamonten: Fix I2C3 pad setting
+    - ARM: mmp: Fix failure to remove sram device
+    - video: fbdev: sm712fb: Fix crash in smtcfb_write()
+    - media: Revert "media: em28xx: add missing em28xx_close_extension"
+    - media: hdpvr: initialize dev->worker at hdpvr_register_videodev
+    - mmc: host: Return an error when ->enable_sdio_irq() ops is missing
+    - ALSA: hda/realtek: Add alc256-samsung-headphone fixup
+    - powerpc/lib/sstep: Fix 'sthcx' instruction
+    - powerpc/lib/sstep: Fix build errors with newer binutils
+    - powerpc: Fix build errors with newer binutils
+    - scsi: qla2xxx: Fix stuck session in gpdb
+    - scsi: qla2xxx: Fix wrong FDMI data for 64G adapter
+    - scsi: qla2xxx: Fix warning for missing error code
+    - scsi: qla2xxx: Fix device reconnect in loop topology
+    - scsi: qla2xxx: Add devids and conditionals for 28xx
+    - scsi: qla2xxx: Check for firmware dump already collected
+    - scsi: qla2xxx: Suppress a kernel complaint in qla_create_qpair()
+    - scsi: qla2xxx: Fix disk failure to rediscover
+    - scsi: qla2xxx: Fix incorrect reporting of task management failure
+    - scsi: qla2xxx: Fix hang due to session stuck
+    - scsi: qla2xxx: Fix missed DMA unmap for NVMe ls requests
+    - scsi: qla2xxx: Fix N2N inconsistent PLOGI
+    - scsi: qla2xxx: Reduce false trigger to login
+    - scsi: qla2xxx: Use correct feature type field during RFF_ID processing
+    - KVM: Prevent module exit until all VMs are freed
+    - KVM: x86: fix sending PV IPI
+    - ASoC: SOF: Intel: Fix NULL ptr dereference when ENOMEM
+    - ubifs: rename_whiteout: Fix double free for whiteout_ui->data
+    - ubifs: Fix deadlock in concurrent rename whiteout and inode writeback
+    - ubifs: Add missing iput if do_tmpfile() failed in rename whiteout
+    - ubifs: setflags: Make dirtied_ino_d 8 bytes aligned
+    - ubifs: Fix read out-of-bounds in ubifs_wbuf_write_nolock()
+    - ubifs: rename_whiteout: correct old_dir size computing
+    - XArray: Fix xas_create_range() when multi-order entry present
+    - can: mcba_usb: mcba_usb_start_xmit(): fix double dev_kfree_skb in error path
+    - can: mcba_usb: properly check endpoint type
+    - XArray: Update the LRU list in xas_split()
+    - rtc: check if __rtc_read_time was successful
+    - gfs2: Make sure FITRIM minlen is rounded up to fs block size
+    - net: hns3: fix software vlan talbe of vlan 0 inconsistent with hardware
+    - pinctrl: pinconf-generic: Print arguments for bias-pull-*
+    - pinctrl: nuvoton: npcm7xx: Rename DS() macro to DSTR()
+    - pinctrl: nuvoton: npcm7xx: Use %zu printk format for ARRAY_SIZE()
+    - ASoC: mediatek: mt6358: add missing EXPORT_SYMBOLs
+    - ubi: Fix race condition between ctrl_cdev_ioctl and ubi_cdev_ioctl
+    - ARM: iop32x: offset IRQ numbers by 1
+    - ACPI: CPPC: Avoid out of bounds access when parsing _CPC data
+    - powerpc/kasan: Fix early region not updated correctly
+    - ASoC: soc-compress: Change the check for codec_dai
+    - mm/mmap: return 1 from stack_guard_gap __setup() handler
+    - mm/memcontrol: return 1 from cgroup.memory __setup() handler
+    - mm/usercopy: return 1 from hardened_usercopy __setup() handler
+    - bpf: Fix comment for helper bpf_current_task_under_cgroup()
+    - dt-bindings: mtd: nand-controller: Fix the reg property description
+    - dt-bindings: mtd: nand-controller: Fix a comment in the examples
+    - dt-bindings: spi: mxic: The interrupt property is not mandatory
+    - ubi: fastmap: Return error code if memory allocation fails in add_aeb()
+    - ASoC: topology: Allow TLV control to be either read or write
+    - ARM: dts: spear1340: Update serial node properties
+    - ARM: dts: spear13xx: Update SPI dma properties
+    - um: Fix uml_mconsole stop/go
+    - openvswitch: Fixed nd target mask field in the flow dump.
+    - KVM: x86/mmu: do compare-and-exchange of gPTE via the user address
+    - KVM: x86: Forbid VMM to set SYNIC/STIMER MSRs when SynIC wasn't activated
+    - ubifs: Rectify space amount budget for mkdir/tmpfile operations
+    - rtc: wm8350: Handle error for wm8350_register_irq
+    - riscv module: remove (NOLOAD)
+    - ARM: 9187/1: JIVE: fix return value of __setup handler
+    - KVM: x86/svm: Clear reserved bits written to PerfEvtSeln MSRs
+    - drm: Add orientation quirk for GPD Win Max
+    - ath5k: fix OOB in ath5k_eeprom_read_pcal_info_5111
+    - drm/amd/amdgpu/amdgpu_cs: fix refcount leak of a dma_fence obj
+    - ptp: replace snprintf with sysfs_emit
+    - powerpc: dts: t104xrdb: fix phy type for FMAN 4/5
+    - bpf: Make dst_port field in struct bpf_sock 16-bit wide
+    - scsi: mvsas: Replace snprintf() with sysfs_emit()
+    - scsi: bfa: Replace snprintf() with sysfs_emit()
+    - power: supply: axp20x_battery: properly report current when discharging
+    - ipv6: make mc_forwarding atomic
+    - powerpc: Set crashkernel offset to mid of RMA region
+    - drm/amdgpu: Fix recursive locking warning
+    - PCI: aardvark: Fix support for MSI interrupts
+    - iommu/arm-smmu-v3: fix event handling soft lockup
+    - usb: ehci: add pci device support for Aspeed platforms
+    - PCI: pciehp: Add Qualcomm quirk for Command Completed erratum
+    - power: supply: axp288-charger: Set Vhold to 4.4V
+    - ipv4: Invalidate neighbour for broadcast address upon address addition
+    - dm ioctl: prevent potential spectre v1 gadget
+    - drm/amdkfd: make CRAT table missing message informational only
+    - scsi: pm8001: Fix pm8001_mpi_task_abort_resp()
+    - scsi: aha152x: Fix aha152x_setup() __setup handler return value
+    - net/smc: correct settings of RMB window update limit
+    - mips: ralink: fix a refcount leak in ill_acc_of_setup()
+    - macvtap: advertise link netns via netlink
+    - tuntap: add sanity checks about msg_controllen in sendmsg
+    - bnxt_en: Eliminate unintended link toggle during FW reset
+    - MIPS: fix fortify panic when copying asm exception handlers
+    - scsi: libfc: Fix use after free in fc_exch_abts_resp()
+    - usb: dwc3: omap: fix "unbalanced disables for smps10_out1" on omap5evm
+    - xtensa: fix DTC warning unit_address_format
+    - Bluetooth: Fix use after free in hci_send_acl
+    - netlabel: fix out-of-bounds memory accesses
+    - init/main.c: return 1 from handled __setup() functions
+    - minix: fix bug when opening a file with O_DIRECT
+    - clk: si5341: fix reported clk_rate when output divider is 2
+    - w1: w1_therm: fixes w1_seq for ds28ea00 sensors
+    - NFSv4: Protect the state recovery thread against direct reclaim
+    - xen: delay xen_hvm_init_time_ops() if kdump is boot on vcpu>=32
+    - clk: Enforce that disjoints limits are invalid
+    - SUNRPC/call_alloc: async tasks mustn't block waiting for memory
+    - NFS: swap IO handling is slightly different for O_DIRECT IO
+    - NFS: swap-out must always use STABLE writes.
+    - serial: samsung_tty: do not unlock port->lock for uart_write_wakeup()
+    - virtio_console: eliminate anonymous module_init & module_exit
+    - jfs: prevent NULL deref in diFree
+    - SUNRPC: Fix socket waits for write buffer space
+    - parisc: Fix CPU affinity for Lasi, WAX and Dino chips
+    - parisc: Fix patch code locking and flushing
+    - mm: fix race between MADV_FREE reclaim and blkdev direct IO read
+    - KVM: arm64: Check arm64_get_bp_hardening_data() didn't return NULL
+    - drm/amdgpu: fix off by one in amdgpu_gfx_kiq_acquire()
+    - Drivers: hv: vmbus: Fix potential crash on module unload
+    - scsi: zorro7xx: Fix a resource leak in zorro7xx_remove_one()
+    - net/tls: fix slab-out-of-bounds bug in decrypt_internal
+    - net: ipv4: fix route with nexthop object delete warning
+    - net: stmmac: Fix unset max_speed difference between DT and non-DT platforms
+    - drm/imx: Fix memory leak in imx_pd_connector_get_modes
+    - bnxt_en: reserve space inside receive page for skb_shared_info
+    - IB/rdmavt: add lock to call to rvt_error_qp to prevent a race condition
+    - dpaa2-ptp: Fix refcount leak in dpaa2_ptp_probe
+    - ipv6: Fix stats accounting in ip6_pkt_drop
+    - net: openvswitch: don't send internal clone attribute to the userspace.
+    - rxrpc: fix a race in rxrpc_exit_net()
+    - qede: confirm skb is allocated before using
+    - spi: bcm-qspi: fix MSPI only access with bcm_qspi_exec_mem_op()
+    - bpf: Support dual-stack sockets in bpf_tcp_check_syncookie
+    - drbd: Fix five use after free bugs in get_initial_state
+    - SUNRPC: Handle ENOMEM in call_transmit_status()
+    - SUNRPC: Handle low memory situations in call_status()
+    - perf tools: Fix perf's libperf_print callback
+    - perf session: Remap buf if there is no space for event
+    - Revert "mmc: sdhci-xenon: fix annoying 1.8V regulator warning"
+    - mmc: renesas_sdhi: don't overwrite TAP settings when HS400 tuning is
+      complete
+    - lz4: fix LZ4_decompress_safe_partial read out of bound
+    - mmmremap.c: avoid pointless invalidate_range_start/end on mremap(old_size=0)
+    - mm/mempolicy: fix mpol_new leak in shared_policy_replace
+    - x86/pm: Save the MSR validity status at context setup
+    - x86/speculation: Restore speculation related MSRs during S3 resume
+    - btrfs: fix qgroup reserve overflow the qgroup limit
+    - arm64: patch_text: Fixup last cpu should be master
+    - ata: sata_dwc_460ex: Fix crash due to OOB write
+    - perf: qcom_l2_pmu: fix an incorrect NULL check on list iterator
+    - irqchip/gic-v3: Fix GICR_CTLR.RWP polling
+    - tools build: Filter out options and warnings not supported by clang
+    - tools build: Use $(shell ) instead of `` to get embedded libperl's ccopts
+    - dmaengine: Revert "dmaengine: shdma: Fix runtime PM imbalance on error"
+    - mmc: mmci_sdmmc: Replace sg_dma_xxx macros
+    - mmc: mmci: stm32: correctly check all elements of sg list
+    - mm: don't skip swap entry even if zap_details specified
+    - arm64: module: remove (NOLOAD) from linker script
+    - mm/sparsemem: fix 'mem_section' will never be NULL gcc 12 warning
+    - drm/amdkfd: add missing void argument to function kgd2kfd_init
+    - drm/amdkfd: Fix -Wstrict-prototypes from
+      amdgpu_amdkfd_gfx_10_0_get_functions()
+    - cgroup: Use open-time credentials for process migraton perm checks
+    - cgroup: Allocate cgroup_file_ctx for kernfs_open_file->priv
+    - cgroup: Use open-time cgroup namespace for process migration perm checks
+    - selftests: cgroup: Make cg_create() use 0755 for permission instead of 0644
+    - selftests: cgroup: Test open-time credential usage for migration checks
+    - selftests: cgroup: Test open-time cgroup namespace usage for migration
+      checks
+    - cpuidle: PSCI: Move the `has_lpi` check to the beginning of the function
+    - ACPI: processor idle: Check for architectural support for LPI
+    - Linux 5.4.189
+  * Focal update: v5.4.188 upstream stable release (LP: #1971496)
+    - nfsd: cleanup nfsd_file_lru_dispose()
+    - nfsd: Containerise filecache laundrette
+    - net: ipv6: fix skb_over_panic in __ip6_append_data
+    - tpm: Fix error handling in async work
+    - staging: fbtft: fb_st7789v: reset display before initialization
+    - thermal: int340x: fix memory leak in int3400_notify()
+    - llc: fix netdevice reference leaks in llc_ui_bind()
+    - ALSA: pcm: Add stream lock during PCM reset ioctl operations
+    - ALSA: usb-audio: Add mute TLV for playback volumes on RODE NT-USB
+    - ALSA: cmipci: Restore aux vol on suspend/resume
+    - ALSA: pci: fix reading of swapped values from pcmreg in AC97 codec
+    - drivers: net: xgene: Fix regression in CRC stripping
+    - ASoC: sti: Fix deadlock via snd_pcm_stop_xrun() call
+    - ALSA: oss: Fix PCM OSS buffer allocation overflow
+    - ALSA: hda/realtek - Fix headset mic problem for a HP machine with alc671
+    - ALSA: hda/realtek: Add quirk for ASUS GA402
+    - ACPI / x86: Work around broken XSDT on Advantech DAC-BJ01 board
+    - ACPI: battery: Add device HID and quirk for Microsoft Surface Go 3
+    - ACPI: video: Force backlight native for Clevo NL5xRU and NL5xNU
+    - crypto: qat - disable registration of algorithms
+    - rcu: Don't deboost before reporting expedited quiescent state
+    - mac80211: fix potential double free on mesh join
+    - tpm: use try_get_ops() in tpm-space.c
+    - nds32: fix access_ok() checks in get/put_user
+    - llc: only change llc->dev when bind() succeeds
+    - Linux 5.4.188
+  * Focal update: v5.4.187 upstream stable release (LP: #1971493)
+    - crypto: qcom-rng - ensure buffer for generate is completely filled
+    - ocfs2: fix crash when initialize filecheck kobj fails
+    - efi: fix return value of __setup handlers
+    - net: phy: marvell: Fix invalid comparison in the resume and suspend
+      functions
+    - net/packet: fix slab-out-of-bounds access in packet_recvmsg()
+    - atm: eni: Add check for dma_map_single
+    - hv_netvsc: Add check for kvmalloc_array
+    - drm/panel: simple: Fix Innolux G070Y2-L01 BPP settings
+    - net: handle ARPHRD_PIMREG in dev_is_mac_header_xmit()
+    - net: dsa: Add missing of_node_put() in dsa_port_parse_of
+    - arm64: fix clang warning about TRAMP_VALIAS
+    - usb: gadget: rndis: prevent integer overflow in rndis_set_response()
+    - usb: gadget: Fix use-after-free bug by not setting udc->dev.driver
+    - usb: usbtmc: Fix bug in pipe direction for control transfers
+    - Input: aiptek - properly check endpoint type
+    - perf symbols: Fix symbol size calculation condition
+    - Linux 5.4.187
+  * Focal update: v5.4.186 upstream stable release (LP: #1969678)
+    - Revert "xfrm: state and policy should fail if XFRMA_IF_ID 0"
+    - sctp: fix the processing for INIT chunk
+    - xfrm: Check if_id in xfrm_migrate
+    - xfrm: Fix xfrm migrate issues when address family changes
+    - arm64: dts: rockchip: fix rk3399-puma eMMC HS400 signal integrity
+    - arm64: dts: rockchip: reorder rk3399 hdmi clocks
+    - arm64: dts: agilex: use the compatible "intel,socfpga-agilex-hsotg"
+    - ARM: dts: rockchip: reorder rk322x hmdi clocks
+    - ARM: dts: rockchip: fix a typo on rk3288 crypto-controller
+    - mac80211: refuse aggregations sessions before authorized
+    - MIPS: smp: fill in sibling and core maps earlier
+    - ARM: 9178/1: fix unmet dependency on BITREVERSE for HAVE_ARCH_BITREVERSE
+    - can: rcar_canfd: rcar_canfd_channel_probe(): register the CAN device when
+      fully ready
+    - atm: firestream: check the return value of ioremap() in fs_init()
+    - iwlwifi: don't advertise TWT support
+    - drm/vrr: Set VRR capable prop only if it is attached to connector
+    - nl80211: Update bss channel on channel switch for P2P_CLIENT
+    - tcp: make tcp_read_sock() more robust
+    - sfc: extend the locking on mcdi->seqno
+    - kselftest/vm: fix tests build with old libc
+    - fixup for "arm64 entry: Add macro for reading symbol address from the
+      trampoline"
+    - Linux 5.4.186
+  * Focal update: v5.4.185 upstream stable release (LP: #1969672)
+    - clk: qcom: gdsc: Add support to update GDSC transition delay
+    - arm64: dts: armada-3720-turris-mox: Add missing ethernet0 alias
+    - virtio-blk: Don't use MAX_DISCARD_SEGMENTS if max_discard_seg is zero
+    - net: qlogic: check the return value of dma_alloc_coherent() in
+      qed_vf_hw_prepare()
+    - qed: return status of qed_iov_get_link
+    - drm/sun4i: mixer: Fix P010 and P210 format numbers
+    - ARM: dts: aspeed: Fix AST2600 quad spi group
+    - ethernet: Fix error handling in xemaclite_of_probe
+    - net: ethernet: ti: cpts: Handle error for clk_enable
+    - net: ethernet: lpc_eth: Handle error for clk_enable
+    - ax25: Fix NULL pointer dereference in ax25_kill_by_device
+    - net/mlx5: Fix size field in bufferx_reg struct
+    - net/mlx5: Fix a race on command flush flow
+    - NFC: port100: fix use-after-free in port100_send_complete
+    - selftests: pmtu.sh: Kill tcpdump processes launched by subshell.
+    - gpio: ts4900: Do not set DAT and OE together
+    - gianfar: ethtool: Fix refcount leak in gfar_get_ts_info
+    - net: phy: DP83822: clear MISR2 register to disable interrupts
+    - sctp: fix kernel-infoleak for SCTP sockets
+    - net: bcmgenet: Don't claim WOL when its not available
+    - net-sysfs: add check for netdevice being present to speed_show
+    - Revert "xen-netback: remove 'hotplug-status' once it has served its purpose"
+    - Revert "xen-netback: Check for hotplug-status existence before watching"
+    - ipv6: prevent a possible race condition with lifetimes
+    - tracing: Ensure trace buffer is at least 4096 bytes large
+    - selftest/vm: fix map_fixed_noreplace test failure
+    - selftests/memfd: clean up mapping in mfd_fail_write
+    - ARM: Spectre-BHB: provide empty stub for non-config
+    - fuse: fix pipe buffer lifetime for direct_io
+    - staging: gdm724x: fix use after free in gdm_lte_rx()
+    - net: macb: Fix lost RX packet wakeup race in NAPI receive
+    - mmc: meson: Fix usage of meson_mmc_post_req()
+    - riscv: Fix auipc+jalr relocation range checks
+    - arm64: dts: marvell: armada-37xx: Remap IO space to bus address 0x0
+    - virtio: unexport virtio_finalize_features
+    - virtio: acknowledge all features before access
+    - ARM: fix Thumb2 regression with Spectre BHB
+    - ext4: add check to prevent attempting to resize an fs with sparse_super2
+    - x86/cpufeatures: Mark two free bits in word 3
+    - x86/cpu: Add hardware-enforced cache coherency as a CPUID feature
+    - x86/mm/pat: Don't flush cache if hardware enforces cache coherency across
+      encryption domnains
+    - KVM: SVM: Don't flush cache if hardware enforces cache coherency across
+      encryption domains
+    - Linux 5.4.185
+  * Focal update: v5.4.184 upstream stable release (LP: #1969242)
+    - arm/arm64: Provide a wrapper for SMCCC 1.1 calls
+    - arm/arm64: smccc/psci: add arm_smccc_1_1_get_conduit()
+    - ARM: report Spectre v2 status through sysfs
+    - ARM: early traps initialisation
+    - ARM: use LOADADDR() to get load address of sections
+    - [Config] updateconfigs for HARDEN_BRANCH_HISTORY
+    - ARM: Spectre-BHB workaround
+    - ARM: include unprivileged BPF status in Spectre V2 reporting
+    - ARM: fix build error when BPF_SYSCALL is disabled
+    - ARM: fix co-processor register typo
+    - ARM: Do not use NOCROSSREFS directive with ld.lld
+    - ARM: fix build warning in proc-v7-bugs.c
+    - xen/xenbus: don't let xenbus_grant_ring() remove grants in error case
+    - xen/grant-table: add gnttab_try_end_foreign_access()
+    - xen/blkfront: don't use gnttab_query_foreign_access() for mapped status
+    - xen/netfront: don't use gnttab_query_foreign_access() for mapped status
+    - xen/scsifront: don't use gnttab_query_foreign_access() for mapped status
+    - xen/gntalloc: don't use gnttab_query_foreign_access()
+    - xen: remove gnttab_query_foreign_access()
+    - xen/9p: use alloc/free_pages_exact()
+    - xen/pvcalls: use alloc/free_pages_exact()
+    - xen/gnttab: fix gnttab_end_foreign_access() without page specified
+    - xen/netfront: react properly to failing gnttab_end_foreign_access_ref()
+    - Linux 5.4.184
+  * Focal update: v5.4.183 upstream stable release (LP: #1969239)
+    - mac80211_hwsim: report NOACK frames in tx_status
+    - mac80211_hwsim: initialize ieee80211_tx_info at hw_scan_work
+    - i2c: bcm2835: Avoid clock stretching timeouts
+    - ASoC: rt5668: do not block workqueue if card is unbound
+    - ASoC: rt5682: do not block workqueue if card is unbound
+    - Input: clear BTN_RIGHT/MIDDLE on buttonpads
+    - cifs: fix double free race when mount fails in cifs_get_root()
+    - dmaengine: shdma: Fix runtime PM imbalance on error
+    - i2c: cadence: allow COMPILE_TEST
+    - i2c: qup: allow COMPILE_TEST
+    - net: usb: cdc_mbim: avoid altsetting toggling for Telit FN990
+    - usb: gadget: don't release an existing dev->buf
+    - usb: gadget: clear related members when goto fail
+    - ata: pata_hpt37x: fix PCI clock detection
+    - ALSA: intel_hdmi: Fix reference to PCM buffer address
+    - ASoC: ops: Shift tested values in snd_soc_put_volsw() by +min
+    - xfrm: fix MTU regression
+    - netfilter: fix use-after-free in __nf_register_net_hook()
+    - xfrm: enforce validity of offload input flags
+    - netfilter: nf_queue: don't assume sk is full socket
+    - netfilter: nf_queue: fix possible use-after-free
+    - batman-adv: Request iflink once in batadv-on-batadv check
+    - batman-adv: Request iflink once in batadv_get_real_netdevice
+    - batman-adv: Don't expect inter-netns unique iflink indices
+    - net: dcb: flush lingering app table entries for unregistered devices
+    - net/smc: fix unexpected SMC_CLC_DECL_ERR_REGRMB error generated by client
+    - net/smc: fix unexpected SMC_CLC_DECL_ERR_REGRMB error cause by server
+    - block: Fix fsync always failed if once failed
+    - xen/netfront: destroy queues before real_num_tx_queues is zeroed
+    - sched/topology: Make sched_init_numa() use a set for the deduplicating sort
+    - sched/topology: Fix sched_domain_topology_level alloc in sched_init_numa()
+    - ia64: ensure proper NUMA distance and possible map initialization
+    - mac80211: fix forwarded mesh frames AC & queue selection
+    - net: stmmac: fix return value of __setup handler
+    - iavf: Fix missing check for running netdev
+    - net: sxgbe: fix return value of __setup handler
+    - net: arcnet: com20020: Fix null-ptr-deref in com20020pci_probe()
+    - ixgbe: xsk: change !netif_carrier_ok() handling in ixgbe_xmit_zc()
+    - efivars: Respect "block" flag in efivar_entry_set_safe()
+    - firmware: arm_scmi: Remove space in MODULE_ALIAS name
+    - ASoC: cs4265: Fix the duplicated control name
+    - can: gs_usb: change active_channels's type from atomic_t to u8
+    - arm64: dts: rockchip: Switch RK3399-Gru DP to SPDIF output
+    - igc: igc_read_phy_reg_gpy: drop premature return
+    - ARM: Fix kgdb breakpoint for Thumb2
+    - ARM: 9182/1: mmu: fix returns from early_param() and __setup() functions
+    - igc: igc_write_phy_reg_gpy: drop premature return
+    - ibmvnic: free reset-work-item when flushing
+    - memfd: fix F_SEAL_WRITE after shmem huge page allocated
+    - soc: fsl: qe: Check of ioremap return value
+    - net: chelsio: cxgb3: check the return value of pci_find_capability()
+    - nl80211: Handle nla_memdup failures in handle_nan_filter
+    - Input: elan_i2c - move regulator_[en|dis]able() out of
+      elan_[en|dis]able_power()
+    - Input: elan_i2c - fix regulator enable count imbalance after suspend/resume
+    - HID: add mapping for KEY_DICTATE
+    - HID: add mapping for KEY_ALL_APPLICATIONS
+    - tracing/histogram: Fix sorting on old "cpu" value
+    - tracing: Fix return value of __setup handlers
+    - btrfs: fix lost prealloc extents beyond eof after full fsync
+    - btrfs: qgroup: fix deadlock between rescan worker and remove qgroup
+    - btrfs: add missing run of delayed items after unlink during log replay
+    - Revert "xfrm: xfrm_state_mtu should return at least 1280 for ipv6"
+    - net: dcb: disable softirqs in dcbnl_flush_dev()
+    - hamradio: fix macro redefine warning
+    - Linux 5.4.183
+  * Focal update: v5.4.182 upstream stable release (LP: #1969236)
+    - cgroup/cpuset: Fix a race between cpuset_attach() and cpu hotplug
+    - clk: jz4725b: fix mmc0 clock gating
+    - vhost/vsock: don't check owner in vhost_vsock_stop() while releasing
+    - parisc/unaligned: Fix fldd and fstd unaligned handlers on 32-bit kernel
+    - parisc/unaligned: Fix ldw() and stw() unalignment handlers
+    - drm/amdgpu: disable MMHUB PG for Picasso
+    - sr9700: sanity check for packet length
+    - USB: zaurus: support another broken Zaurus
+    - x86/fpu: Correct pkru/xstate inconsistency
+    - tee: export teedev_open() and teedev_close_context()
+    - optee: use driver internal tee_context for some rpc
+    - lan743x: fix deadlock in lan743x_phy_link_status_change()
+    - ping: remove pr_err from ping_lookup
+    - perf data: Fix double free in perf_session__delete()
+    - bpf: Do not try bpf_msg_push_data with len 0
+    - net: __pskb_pull_tail() & pskb_carve_frag_list() drop_monitor friends
+    - tipc: Fix end of loop tests for list_for_each_entry()
+    - gso: do not skip outer ip header in case of ipip and net_failover
+    - openvswitch: Fix setting ipv6 fields causing hw csum failure
+    - drm/edid: Always set RGB444
+    - net/mlx5e: Fix wrong return value on ioctl EEPROM query failure
+    - net: ll_temac: check the return value of devm_kmalloc()
+    - net: Force inlining of checksum functions in net/checksum.h
+    - nfp: flower: Fix a potential leak in nfp_tunnel_add_shared_mac()
+    - netfilter: nf_tables: fix memory leak during stateful obj update
+    - net/mlx5: Fix possible deadlock on rule deletion
+    - net/mlx5: Fix wrong limitation of metadata match on ecpf
+    - spi: spi-zynq-qspi: Fix a NULL pointer dereference in
+      zynq_qspi_exec_mem_op()
+    - configfs: fix a race in configfs_{,un}register_subsystem()
+    - RDMA/ib_srp: Fix a deadlock
+    - tracing: Have traceon and traceoff trigger honor the instance
+    - iio: adc: men_z188_adc: Fix a resource leak in an error handling path
+    - iio: adc: ad7124: fix mask used for setting AIN_BUFP & AIN_BUFM bits
+    - iio: Fix error handling for PM
+    - ata: pata_hpt37x: disable primary channel on HPT371
+    - Revert "USB: serial: ch341: add new Product ID for CH341A"
+    - usb: gadget: rndis: add spinlock for rndis response list
+    - tracefs: Set the group ownership in apply_options() not parse_options()
+    - USB: serial: option: add support for DW5829e
+    - USB: serial: option: add Telit LE910R1 compositions
+    - usb: dwc3: pci: Fix Bay Trail phy GPIO mappings
+    - usb: dwc3: gadget: Let the interrupt handler disable bottom halves.
+    - xhci: re-initialize the HC during resume if HCE was set
+    - xhci: Prevent futile URB re-submissions due to incorrect return value.
+    - tty: n_gsm: fix encoding of control signal octet bit DV
+    - tty: n_gsm: fix proper link termination after failed open
+    - tty: n_gsm: fix NULL pointer access due to DLCI release
+    - gpio: tegra186: Fix chip_data type confusion
+    - Revert "drm/nouveau/pmu/gm200-: avoid touching PMU outside of
+      DEVINIT/PREOS/ACR"
+    - memblock: use kfree() to release kmalloced memblock regions
+    - fget: clarify and improve __fget_files() implementation
+    - Linux 5.4.182
+  * CVE-2022-28390
+    - can: ems_usb: ems_usb_start_xmit(): fix double dev_kfree_skb() in error path
+
+  [ Ubuntu: 5.4.0-113.127 ]
+
+  * focal/linux: 5.4.0-113.127 -proposed tracker (LP: #1973980)
+  * CVE-2022-29581
+    - net/sched: cls_u32: fix netns refcount changes in u32_change()
+  * CVE-2022-1116
+    - io_uring: fix fs->users overflow
+  * ext4: limit length to bitmap_maxbytes (LP: #1972281)
+    - ext4: limit length to bitmap_maxbytes - blocksize in punch_hole
+  * Unprivileged users may use PTRACE_SEIZE to set PTRACE_O_SUSPEND_SECCOMP
+    option (LP: #1972740)
+    - ptrace: Check PTRACE_O_SUSPEND_SECCOMP permission on PTRACE_SEIZE
+
+  [ Ubuntu: 5.4.0-110.124 ]
+
+  * focal/linux: 5.4.0-110.124 -proposed tracker (LP: #1969053)
+  * net/mlx5e: Fix page DMA map/unmap attributes (LP: #1967292)
+    - net/mlx5e: Fix page DMA map/unmap attributes
+  * xfs: Fix deadlock between AGI and AGF when target_ip exists in xfs_rename()
+    (LP: #1966803)
+    - xfs: Fix deadlock between AGI and AGF when target_ip exists in xfs_rename()
+  * LRMv6: add multi-architecture support (LP: #1968774)
+    - [Packaging] resync dkms-build{,--nvidia-N}
+  * xfrm interface cannot be changed anymore (LP: #1968591)
+    - xfrm: fix the if_id check in changelink
+  * Use kernel-testing repo from launchpad for ADT tests (LP: #1968016)
+    - [Debian] Use kernel-testing repo from launchpad
+  * vmx_ldtr_test in ubuntu_kvm_unit_tests failed (FAIL: Expected 0 for L1 LDTR
+    selector (got 50)) (LP: #1956315)
+    - KVM: nVMX: Set LDTR to its architecturally defined value on nested VM-Exit
+  * [SRU][Regression] Revert "PM: ACPI: reboot: Use S5 for reboot" which causes
+    Bus Fatal Error when rebooting system with BCM5720 NIC (LP: #1917471)
+    - Revert "PM: ACPI: reboot: Use S5 for reboot"
+  * Focal update: v5.4.181 upstream stable release (LP: #1967582)
+    - Makefile.extrawarn: Move -Wunaligned-access to W=1
+    - HID:Add support for UGTABLET WP5540
+    - Revert "svm: Add warning message for AVIC IPI invalid target"
+    - serial: parisc: GSC: fix build when IOSAPIC is not set
+    - parisc: Drop __init from map_pages declaration
+    - parisc: Fix data TLB miss in sba_unmap_sg
+    - parisc: Fix sglist access in ccio-dma.c
+    - btrfs: send: in case of IO error log it
+    - platform/x86: ISST: Fix possible circular locking dependency detected
+    - selftests: rtc: Increase test timeout so that all tests run
+    - net: ieee802154: at86rf230: Stop leaking skb's
+    - selftests/zram: Skip max_comp_streams interface on newer kernel
+    - selftests/zram01.sh: Fix compression ratio calculation
+    - selftests/zram: Adapt the situation that /dev/zram0 is being used
+    - ax25: improve the incomplete fix to avoid UAF and NPD bugs
+    - vfs: make freeze_super abort when sync_filesystem returns error
+    - quota: make dquot_quota_sync return errors from ->sync_fs
+    - nvme: fix a possible use-after-free in controller reset during load
+    - nvme-tcp: fix possible use-after-free in transport error_recovery work
+    - nvme-rdma: fix possible use-after-free in transport error_recovery work
+    - drm/amdgpu: fix logic inversion in check
+    - Revert "module, async: async_synchronize_full() on module init iff async is
+      used"
+    - ftrace: add ftrace_init_nop()
+    - module/ftrace: handle patchable-function-entry
+    - arm64: module: rework special section handling
+    - arm64: module/ftrace: intialize PLT at load time
+    - iwlwifi: fix use-after-free
+    - drm/radeon: Fix backlight control on iMac 12,1
+    - ext4: check for out-of-order index extents in ext4_valid_extent_entries()
+    - ext4: check for inconsistent extents between index and leaf block
+    - ext4: prevent partial update of the extent blocks
+    - taskstats: Cleanup the use of task->exit_code
+    - dmaengine: at_xdmac: Start transfer for cyclic channels in issue_pending
+    - vsock: remove vsock from connected table when connect is interrupted by a
+      signal
+    - mmc: block: fix read single on recovery logic
+    - iwlwifi: pcie: fix locking when "HW not ready"
+    - iwlwifi: pcie: gen2: fix locking when "HW not ready"
+    - netfilter: nft_synproxy: unregister hooks on init error path
+    - net: dsa: lan9303: fix reset on probe
+    - net: ieee802154: ca8210: Fix lifs/sifs periods
+    - ping: fix the dif and sdif check in ping_lookup
+    - bonding: force carrier update when releasing slave
+    - drop_monitor: fix data-race in dropmon_net_event / trace_napi_poll_hit
+    - bonding: fix data-races around agg_select_timer
+    - libsubcmd: Fix use-after-free for realloc(..., 0)
+    - ALSA: hda: Fix regression on forced probe mask option
+    - ALSA: hda: Fix missing codec probe on Shenker Dock 15
+    - ASoC: ops: Fix stereo change notifications in snd_soc_put_volsw()
+    - ASoC: ops: Fix stereo change notifications in snd_soc_put_volsw_range()
+    - powerpc/lib/sstep: fix 'ptesync' build error
+    - mtd: rawnand: gpmi: don't leak PM reference in error path
+    - block/wbt: fix negative inflight counter when remove scsi device
+    - NFS: LOOKUP_DIRECTORY is also ok with symlinks
+    - NFS: Do not report writeback errors in nfs_getattr()
+    - mtd: rawnand: qcom: Fix clock sequencing in qcom_nandc_probe()
+    - mtd: rawnand: brcmnand: Fixed incorrect sub-page ECC status
+    - scsi: lpfc: Fix pt2pt NVMe PRLI reject LOGO loop
+    - EDAC: Fix calculation of returned address and next offset in
+      edac_align_ptr()
+    - net: sched: limit TC_ACT_REPEAT loops
+    - dmaengine: sh: rcar-dmac: Check for error num after setting mask
+    - copy_process(): Move fd_install() out of sighand->siglock critical section
+    - i2c: brcmstb: fix support for DSL and CM variants
+    - Drivers: hv: vmbus: Fix memory leak in vmbus_add_channel_kobj
+    - KVM: x86/pmu: Use AMD64_RAW_EVENT_MASK for PERF_TYPE_RAW
+    - ARM: OMAP2+: hwmod: Add of_node_put() before break
+    - ARM: OMAP2+: adjust the location of put_device() call in omapdss_init_of
+    - irqchip/sifive-plic: Add missing thead,c900-plic match string
+    - netfilter: conntrack: don't refresh sctp entries in closed state
+    - arm64: dts: meson-gx: add ATF BL32 reserved-memory region
+    - arm64: dts: meson-g12: add ATF BL32 reserved-memory region
+    - arm64: dts: meson-g12: drop BL32 region from SEI510/SEI610
+    - kconfig: let 'shell' return enough output for deep path names
+    - ata: libata-core: Disable TRIM on M88V29
+    - drm/rockchip: dw_hdmi: Do not leave clock enabled in error case
+    - tracing: Fix tp_printk option related with tp_printk_stop_on_boot
+    - net: usb: qmi_wwan: Add support for Dell DW5829e
+    - net: macb: Align the dma and coherent dma masks
+    - kconfig: fix failing to generate auto.conf
+    - Linux 5.4.181
+  * Focal update: v5.4.180 upstream stable release (LP: #1966118)
+    - integrity: check the return value of audit_log_start()
+    - ima: Remove ima_policy file before directory
+    - ima: Allow template selection with ima_template[_fmt]= after ima_hash=
+    - ima: Do not print policy rule with inactive LSM labels
+    - mmc: sdhci-of-esdhc: Check for error num after setting mask
+    - net: phy: marvell: Fix RGMII Tx/Rx delays setting in 88e1121-compatible PHYs
+    - net: phy: marvell: Fix MDI-x polarity setting in 88e1118-compatible PHYs
+    - NFS: Fix initialisation of nfs_client cl_flags field
+    - NFSD: Clamp WRITE offsets
+    - NFSD: Fix offset type in I/O trace points
+    - NFSv4 only print the label when its queried
+    - nfs: nfs4clinet: check the return value of kstrdup()
+    - NFSv4.1: Fix uninitialised variable in devicenotify
+    - NFSv4 remove zero number of fs_locations entries error check
+    - NFSv4 expose nfs_parse_server_name function
+    - drm: panel-orientation-quirks: Add quirk for the 1Netbook OneXPlayer
+    - net: sched: Clarify error message when qdisc kind is unknown
+    - scsi: target: iscsi: Make sure the np under each tpg is unique
+    - scsi: qedf: Fix refcount issue when LOGO is received during TMF
+    - scsi: myrs: Fix crash in error case
+    - PM: hibernate: Remove register_nosave_region_late()
+    - usb: dwc2: gadget: don't try to disable ep0 in dwc2_hsotg_suspend
+    - net: stmmac: dwmac-sun8i: use return val of readl_poll_timeout()
+    - KVM: nVMX: eVMCS: Filter out VM_EXIT_SAVE_VMX_PREEMPTION_TIMER
+    - riscv: fix build with binutils 2.38
+    - ARM: dts: imx23-evk: Remove MX23_PAD_SSP1_DETECT from hog group
+    - ARM: socfpga: fix missing RESET_CONTROLLER
+    - nvme-tcp: fix bogus request completion when failing to send AER
+    - ACPI/IORT: Check node revision for PMCG resources
+    - PM: s2idle: ACPI: Fix wakeup interrupts handling
+    - net: bridge: fix stale eth hdr pointer in br_dev_xmit
+    - perf probe: Fix ppc64 'perf probe add events failed' case
+    - ARM: dts: meson: Fix the UART compatible strings
+    - staging: fbtft: Fix error path in fbtft_driver_module_init()
+    - ARM: dts: imx6qdl-udoo: Properly describe the SD card detect
+    - usb: f_fs: Fix use-after-free for epfile
+    - misc: fastrpc: avoid double fput() on failed usercopy
+    - ixgbevf: Require large buffers for build_skb on 82599VF
+    - bonding: pair enable_port with slave_arr_updates
+    - ipmr,ip6mr: acquire RTNL before calling ip[6]mr_free_table() on failure path
+    - nfp: flower: fix ida_idx not being released
+    - net: do not keep the dst cache when uncloning an skb dst and its metadata
+    - net: fix a memleak when uncloning an skb dst and its metadata
+    - veth: fix races around rq->rx_notify_masked
+    - net: mdio: aspeed: Add missing MODULE_DEVICE_TABLE
+    - tipc: rate limit warning for received illegal binding update
+    - net: amd-xgbe: disable interrupts during pci removal
+    - vt_ioctl: fix array_index_nospec in vt_setactivate
+    - vt_ioctl: add array_index_nospec to VT_ACTIVATE
+    - n_tty: wake up poll(POLLRDNORM) on receiving data
+    - eeprom: ee1004: limit i2c reads to I2C_SMBUS_BLOCK_MAX
+    - net: usb: ax88179_178a: Fix out-of-bounds accesses in RX fixup
+    - usb: ulpi: Move of_node_put to ulpi_dev_release
+    - usb: ulpi: Call of_node_put correctly
+    - usb: dwc3: gadget: Prevent core from processing stale TRBs
+    - usb: gadget: udc: renesas_usb3: Fix host to USB_ROLE_NONE transition
+    - USB: gadget: validate interface OS descriptor requests
+    - usb: gadget: rndis: check size of RNDIS_MSG_SET command
+    - usb: gadget: f_uac2: Define specific wTerminalType
+    - USB: serial: ftdi_sio: add support for Brainboxes US-159/235/320
+    - USB: serial: option: add ZTE MF286D modem
+    - USB: serial: ch341: add support for GW Instek USB2.0-Serial devices
+    - USB: serial: cp210x: add NCR Retail IO box id
+    - USB: serial: cp210x: add CPI Bulk Coin Recycler id
+    - seccomp: Invalidate seccomp mode to catch death failures
+    - hwmon: (dell-smm) Speed up setting of fan speed
+    - scsi: lpfc: Remove NVMe support if kernel has NVME_FC disabled
+    - perf: Fix list corruption in perf_cgroup_switch()
+    - Linux 5.4.180
+  * Focal update: v5.4.179 upstream stable release (LP: #1965591)
+    - moxart: fix potential use-after-free on remove path
+    - Linux 5.4.179
+  * CVE-2020-27820
+    - drm/nouveau: Add a dedicated mutex for the clients list
+    - drm/nouveau: clean up all clients on device removal
+  * CVE-2022-1016
+    - netfilter: nf_tables: initialize registers in nft_do_chain()
+  * CVE-2022-27223
+    - USB: gadget: validate endpoint index for xilinx udc
+  * CVE-2022-26490
+    - nfc: st21nfca: Fix potential buffer overflows in EVT_TRANSACTION
+  * CVE-2021-26401
+    - x86/speculation: Use generic retpoline by default on AMD
+    - x86/speculation: Update link to AMD speculation whitepaper
+    - x86/speculation: Warn about Spectre v2 LFENCE mitigation
+    - x86/speculation: Warn about eIBRS + LFENCE + Unprivileged eBPF + SMT
+  * CVE-2022-0001
+    - x86/speculation: Include unprivileged eBPF status in Spectre v2 mitigation
+      reporting
+
+  [ Ubuntu: 5.4.0-109.123 ]
+
+  * focal/linux: 5.4.0-109.123 -proposed tracker (LP: #1968290)
+  * USB devices not detected during boot on USB 3.0 hubs (LP: #1968210)
+    - SAUCE: Revert "Revert "xhci: Set HCD flag to defer primary roothub
+      registration""
+    - SAUCE: Revert "Revert "usb: core: hcd: Add support for deferring roothub
+      registration""
+
+  [ Ubuntu: 5.4.0-108.122 ]
+
+  * focal/linux: 5.4.0-108.122 -proposed tracker (LP: #1966740)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync dkms-build{,--nvidia-N} from LRMv5
+    - debian/dkms-versions -- update from kernel-versions (main/2022.03.21)
+  * Low RX performance for 40G Solarflare NICs (LP: #1964512)
+    - SAUCE: sfc: The size of the RX recycle ring should be more flexible
+  * [UBUNTU 20.04] KVM: Enable storage key checking for intercepted instruction
+    (LP: #1962831)
+    - selftests: kvm: add _vm_ioctl
+    - selftests: kvm: Introduce the TEST_FAIL macro
+    - KVM: selftests: Add GUEST_ASSERT variants to pass values to host
+    - KVM: s390: gaccess: Refactor gpa and length calculation
+    - KVM: s390: gaccess: Refactor access address range check
+    - KVM: s390: gaccess: Cleanup access to guest pages
+    - s390/uaccess: introduce bit field for OAC specifier
+    - s390/uaccess: fix compile error
+    - s390/uaccess: Add copy_from/to_user_key functions
+    - KVM: s390: Honor storage keys when accessing guest memory
+    - KVM: s390: handle_tprot: Honor storage keys
+    - KVM: s390: selftests: Test TEST PROTECTION emulation
+    - KVM: s390: Add optional storage key checking to MEMOP IOCTL
+    - KVM: s390: Add vm IOCTL for key checked guest absolute memory access
+    - KVM: s390: Rename existing vcpu memop functions
+    - KVM: s390: Add capability for storage key extension of MEM_OP IOCTL
+    - KVM: s390: Update api documentation for memop ioctl
+    - KVM: s390: Clarify key argument for MEM_OP in api docs
+    - KVM: s390: Add missing vm MEM_OP size check
+  * 【sec-0911】 fail to reset sec module (LP: #1943301)
+    - crypto: hisilicon/sec2 - Add workqueue for SEC driver.
+    - crypto: hisilicon/sec2 - update SEC initialization and reset
+  * Lots of hisi_qm zombie task slow down system after stress test
+    (LP: #1932117)
+    - crypto: hisilicon - Use one workqueue per qm instead of per qp
+  * Lots of hisi_qm zombie task slow down system after stress test
+    (LP: #1932117) // 【sec-0911】 fail to reset sec module (LP: #1943301)
+    - crypto: hisilicon - Unify hardware error init/uninit into QM
+  * [UBUNTU 20.04] Fix SIGP processing on KVM/s390 (LP: #1962578)
+    - KVM: s390: Simplify SIGP Set Arch handling
+    - KVM: s390: Add a routine for setting userspace CPU state
+  * Move virtual graphics drivers from linux-modules-extra to linux-modules
+    (LP: #1960633)
+    - [Packaging] Move VM DRM drivers into modules
+  * Focal update: v5.4.178 upstream stable release (LP: #1964634)
+    - audit: improve audit queue handling when "audit=1" on cmdline
+    - ASoC: ops: Reject out of bounds values in snd_soc_put_volsw()
+    - ASoC: ops: Reject out of bounds values in snd_soc_put_volsw_sx()
+    - ASoC: ops: Reject out of bounds values in snd_soc_put_xr_sx()
+    - ALSA: usb-audio: Simplify quirk entries with a macro
+    - ALSA: hda/realtek: Add quirk for ASUS GU603
+    - ALSA: hda/realtek: Add missing fixup-model entry for Gigabyte X570 ALC1220
+      quirks
+    - ALSA: hda/realtek: Fix silent output on Gigabyte X570S Aorus Master (newer
+      chipset)
+    - ALSA: hda/realtek: Fix silent output on Gigabyte X570 Aorus Xtreme after
+      reboot from Windows
+    - btrfs: fix deadlock between quota disable and qgroup rescan worker
+    - drm/nouveau: fix off by one in BIOS boundary checking
+    - mm/kmemleak: avoid scanning potential huge holes
+    - block: bio-integrity: Advance seed correctly for larger interval sizes
+    - memcg: charge fs_context and legacy_fs_context
+    - IB/rdmavt: Validate remote_addr during loopback atomic tests
+    - RDMA/siw: Fix broken RDMA Read Fence/Resume logic.
+    - RDMA/mlx4: Don't continue event handler after memory allocation failure
+    - iommu/vt-d: Fix potential memory leak in intel_setup_irq_remapping()
+    - iommu/amd: Fix loop timeout issue in iommu_ga_log_enable()
+    - spi: bcm-qspi: check for valid cs before applying chip select
+    - spi: mediatek: Avoid NULL pointer crash in interrupt
+    - spi: meson-spicc: add IRQ check in meson_spicc_probe
+    - net: ieee802154: hwsim: Ensure proper channel selection at probe time
+    - net: ieee802154: mcr20a: Fix lifs/sifs periods
+    - net: ieee802154: ca8210: Stop leaking skb's
+    - net: ieee802154: Return meaningful error codes from the netlink helpers
+    - net: macsec: Verify that send_sci is on when setting Tx sci explicitly
+    - net: stmmac: dump gmac4 DMA registers correctly
+    - net: stmmac: ensure PTP time register reads are consistent
+    - drm/i915/overlay: Prevent divide by zero bugs in scaling
+    - ASoC: fsl: Add missing error handling in pcm030_fabric_probe
+    - ASoC: xilinx: xlnx_formatter_pcm: Make buffer bytes multiple of period bytes
+    - ASoC: cpcap: Check for NULL pointer after calling of_get_child_by_name
+    - ASoC: max9759: fix underflow in speaker_gain_control_put()
+    - pinctrl: bcm2835: Fix a few error paths
+    - scsi: bnx2fc: Make bnx2fc_recv_frame() mp safe
+    - nfsd: nfsd4_setclientid_confirm mistakenly expires confirmed client.
+    - selftests: futex: Use variable MAKE instead of make
+    - rtc: cmos: Evaluate century appropriate
+    - EDAC/altera: Fix deferred probing
+    - EDAC/xgene: Fix deferred probing
+    - ext4: fix error handling in ext4_restore_inline_data()
+    - cgroup/cpuset: Fix "suspicious RCU usage" lockdep warning
+    - Linux 5.4.178
+  * Focal update: v5.4.177 upstream stable release (LP: #1964628)
+    - PCI: pciehp: Fix infinite loop in IRQ handler upon power fault
+    - psi: Fix uaf issue when psi trigger is destroyed while being polled
+    - ipheth: fix EOVERFLOW in ipheth_rcvbulk_callback
+    - net: amd-xgbe: ensure to reset the tx_timer_active flag
+    - net: amd-xgbe: Fix skb data length underflow
+    - rtnetlink: make sure to refresh master_dev/m_ops in __rtnl_newlink()
+    - cpuset: Fix the bug that subpart_cpus updated wrongly in update_cpumask()
+    - af_packet: fix data-race in packet_setsockopt / packet_setsockopt
+    - Linux 5.4.177
+  * Focal update: v5.4.176 upstream stable release (LP: #1962345)
+    - s390/hypfs: include z/VM guests with access control group set
+    - scsi: zfcp: Fix failed recovery on gone remote port with non-NPIV FCP
+      devices
+    - udf: Restore i_lenAlloc when inode expansion fails
+    - udf: Fix NULL ptr deref when converting from inline format
+    - PM: wakeup: simplify the output logic of pm_show_wakelocks()
+    - tracing/histogram: Fix a potential memory leak for kstrdup()
+    - tracing: Don't inc err_log entry count if entry allocation fails
+    - fsnotify: fix fsnotify hooks in pseudo filesystems
+    - drm/etnaviv: relax submit size limits
+    - arm64: errata: Fix exec handling in erratum 1418040 workaround
+    - netfilter: nft_payload: do not update layer 4 checksum when mangling
+      fragments
+    - serial: 8250: of: Fix mapped region size when using reg-offset property
+    - serial: stm32: fix software flow control transfer
+    - tty: n_gsm: fix SW flow control encoding/handling
+    - tty: Add support for Brainboxes UC cards.
+    - usb-storage: Add unusual-devs entry for VL817 USB-SATA bridge
+    - usb: common: ulpi: Fix crash in ulpi_match()
+    - usb: gadget: f_sourcesink: Fix isoc transfer for USB_SPEED_SUPER_PLUS
+    - USB: core: Fix hang in usb_kill_urb by adding memory barriers
+    - usb: typec: tcpm: Do not disconnect while receiving VBUS off
+    - ucsi_ccg: Check DEV_INT bit only when starting CCG4
+    - net: sfp: ignore disabled SFP node
+    - powerpc/32: Fix boot failure with GCC latent entropy plugin
+    - i40e: Increase delay to 1 s after global EMP reset
+    - i40e: Fix issue when maximum queues is exceeded
+    - i40e: Fix queues reservation for XDP
+    - i40e: fix unsigned stat widths
+    - rpmsg: char: Fix race between the release of rpmsg_ctrldev and cdev
+    - rpmsg: char: Fix race between the release of rpmsg_eptdev and cdev
+    - scsi: bnx2fc: Flush destroy_work queue before calling bnx2fc_interface_put()
+    - ipv6_tunnel: Rate limit warning messages
+    - net: fix information leakage in /proc/net/ptype
+    - hwmon: (lm90) Mark alert as broken for MAX6646/6647/6649
+    - hwmon: (lm90) Mark alert as broken for MAX6680
+    - ping: fix the sk_bound_dev_if match in ping_lookup
+    - ipv4: avoid using shared IP generator for connected sockets
+    - hwmon: (lm90) Reduce maximum conversion rate for G781
+    - NFSv4: Handle case where the lookup of a directory fails
+    - NFSv4: nfs_atomic_open() can race when looking up a non-regular file
+    - net-procfs: show net devices bound packet types
+    - drm/msm: Fix wrong size calculation
+    - drm/msm/dsi: Fix missing put_device() call in dsi_get_phy
+    - drm/msm/dsi: invalid parameter check in msm_dsi_phy_enable
+    - ipv6: annotate accesses to fn->fn_sernum
+    - NFS: Ensure the server has an up to date ctime before hardlinking
+    - NFS: Ensure the server has an up to date ctime before renaming
+    - netfilter: conntrack: don't increment invalid counter on NF_REPEAT
+    - net: phy: broadcom: hook up soft_reset for BCM54616S
+    - phylib: fix potential use-after-free
+    - rxrpc: Adjust retransmission backoff
+    - hwmon: (lm90) Mark alert as broken for MAX6654
+    - ibmvnic: init ->running_cap_crqs early
+    - ibmvnic: don't spin in tasklet
+    - drm/msm/hdmi: Fix missing put_device() call in msm_hdmi_get_phy
+    - yam: fix a memory leak in yam_siocdevprivate()
+    - net: hns3: handle empty unknown interrupt for VF
+    - ipv4: raw: lock the socket in raw_bind()
+    - ipv4: tcp: send zero IPID in SYNACK messages
+    - ipv4: remove sparse error in ip_neigh_gw4()
+    - dt-bindings: can: tcan4x5x: fix mram-cfg RX FIFO config
+    - fsnotify: invalidate dcache before IN_DELETE event
+    - block: Fix wrong offset in bio_truncate()
+    - mtd: rawnand: mpc5121: Remove unused variable in ads5121_select_chip()
+    - Linux 5.4.176
+  * Focal update: v5.4.175 upstream stable release (LP: #1962330)
+    - rcu: Tighten rcu_advance_cbs_nowake() checks
+    - pinctrl: bcm2835: Drop unused define
+    - pinctrl: bcm2835: Refactor platform data
+    - pinctrl: bcm2835: Add support for all GPIOs on BCM2711
+    - pinctrl: bcm2835: Match BCM7211 compatible string
+    - pinctrl: bcm2835: Add support for wake-up interrupts
+    - pinctrl: bcm2835: Change init order for gpio hogs
+    - ARM: dts: gpio-ranges property is now required
+    - mmc: sdhci-esdhc-imx: disable CMDQ support
+    - select: Fix indefinitely sleeping task in poll_schedule_timeout()
+    - Linux 5.4.175
+
+  [ Ubuntu: 5.4.0-107.121 ]
+
+  * focal/linux: 5.4.0-107.121 -proposed tracker (LP: #1966275)
+  * CVE-2022-27666
+    - esp: Fix possible buffer overflow in ESP transformation
+  * CVE-2022-1055
+    - net: sched: fix use-after-free in tc_new_tfilter()
+  * Pick fixup from v5.4.176 upstream stable release to address cert
+    failure with clock jitter test in NUC7i3DNHE (LP: #1964204)
+    - Bluetooth: refactor malicious adv data check
+
+  [ Ubuntu: 5.4.0-105.119 ]
+
+  * CVE-2022-0847
+    - lib/iov_iter: initialize "flags" in new pipe_buffer
+  * Broken network on some AWS instances with focal/impish kernels
+    (LP: #1961968)
+    - SAUCE: Revert "PCI/MSI: Mask MSI-X vectors only on success"
+  * [UBUNTU 20.04] kernel: Add support for CPU-MF counter second version 7
+    (LP: #1960182)
+    - s390/cpumf: Support for CPU Measurement Facility CSVN 7
+    - s390/cpumf: Support for CPU Measurement Sampling Facility LS bit
+  * Hipersocket page allocation failure on Ubuntu 20.04 based SSC environments
+    (LP: #1959529)
+    - s390/qeth: use memory reserves to back RX buffers
+  * CVE-2022-0516
+    - KVM: s390: Return error on SIDA memop on normal guest
+  * CVE-2022-0435
+    - tipc: improve size validations for received domain records
+  * CVE-2022-0492
+    - cgroup-v1: Require capabilities to set release_agent
+  * Recalled NFSv4 files delegations overwhelm server (LP: #1957986)
+    - NFSv4: Fix delegation handling in update_open_stateid()
+    - NFSv4: nfs4_callback_getattr() should ignore revoked delegations
+    - NFSv4: Delegation recalls should not find revoked delegations
+    - NFSv4: fail nfs4_refresh_delegation_stateid() when the delegation was
+      revoked
+    - NFS: Rename nfs_inode_return_delegation_noreclaim()
+    - NFSv4: Don't remove the delegation from the super_list more than once
+    - NFSv4: Hold the delegation spinlock when updating the seqid
+    - NFSv4: Clear the NFS_DELEGATION_REVOKED flag in
+      nfs_update_inplace_delegation()
+    - NFSv4: Update the stateid seqid in nfs_revoke_delegation()
+    - NFSv4: Revoke the delegation on success in nfs4_delegreturn_done()
+    - NFSv4: Ignore requests to return the delegation if it was revoked
+    - NFSv4: Don't reclaim delegations that have been returned or revoked
+    - NFSv4: nfs4_return_incompatible_delegation() should check delegation
+      validity
+    - NFSv4: Fix nfs4_inode_make_writeable()
+    - NFS: nfs_inode_find_state_and_recover() fix stateid matching
+    - NFSv4: Fix races between open and delegreturn
+    - NFSv4: Handle NFS4ERR_OLD_STATEID in delegreturn
+    - NFSv4: Don't retry the GETATTR on old stateid in nfs4_delegreturn_done()
+    - NFSv4: nfs_inode_evict_delegation() should set NFS_DELEGATION_RETURNING
+    - NFS: Clear NFS_DELEGATION_RETURN_IF_CLOSED when the delegation is returned
+    - NFSv4: Try to return the delegation immediately when marked for return on
+      close
+    - NFSv4: Add accounting for the number of active delegations held
+    - NFSv4: Limit the total number of cached delegations
+    - NFSv4: Ensure the delegation is pinned in nfs_do_return_delegation()
+    - NFSv4: Ensure the delegation cred is pinned when we call delegreturn
+  * Focal update: v5.4.174 upstream stable release (LP: #1960566)
+    - HID: uhid: Fix worker destroying device without any protection
+    - HID: wacom: Reset expected and received contact counts at the same time
+    - HID: wacom: Ignore the confidence flag when a touch is removed
+    - HID: wacom: Avoid using stale array indicies to read contact count
+    - f2fs: fix to do sanity check in is_alive()
+    - nfc: llcp: fix NULL error pointer dereference on sendmsg() after failed
+      bind()
+    - mtd: rawnand: gpmi: Add ERR007117 protection for nfc_apply_timings
+    - mtd: rawnand: gpmi: Remove explicit default gpmi clock setting for i.MX6
+    - x86/gpu: Reserve stolen memory for first integrated Intel GPU
+    - tools/nolibc: x86-64: Fix startup code bug
+    - tools/nolibc: i386: fix initial stack alignment
+    - tools/nolibc: fix incorrect truncation of exit code
+    - rtc: cmos: take rtc_lock while reading from CMOS
+    - media: v4l2-ioctl.c: readbuffers depends on V4L2_CAP_READWRITE
+    - media: flexcop-usb: fix control-message timeouts
+    - media: mceusb: fix control-message timeouts
+    - media: em28xx: fix control-message timeouts
+    - media: cpia2: fix control-message timeouts
+    - media: s2255: fix control-message timeouts
+    - media: dib0700: fix undefined behavior in tuner shutdown
+    - media: redrat3: fix control-message timeouts
+    - media: pvrusb2: fix control-message timeouts
+    - media: stk1160: fix control-message timeouts
+    - can: softing_cs: softingcs_probe(): fix memleak on registration failure
+    - lkdtm: Fix content of section containing lkdtm_rodata_do_nothing()
+    - iommu/io-pgtable-arm-v7s: Add error handle for page table allocation failure
+    - dma_fence_array: Fix PENDING_ERROR leak in dma_fence_array_signaled()
+    - PCI: Add function 1 DMA alias quirk for Marvell 88SE9125 SATA controller
+    - mm_zone: add function to check if managed dma zone exists
+    - mm/page_alloc.c: do not warn allocation failure on zone DMA if no managed
+      pages
+    - shmem: fix a race between shmem_unused_huge_shrink and shmem_evict_inode
+    - drm/rockchip: dsi: Hold pm-runtime across bind/unbind
+    - drm/rockchip: dsi: Reconfigure hardware on resume()
+    - drm/panel: kingdisplay-kd097d04: Delete panel on attach() failure
+    - drm/panel: innolux-p079zca: Delete panel on attach() failure
+    - drm/rockchip: dsi: Fix unbalanced clock on probe error
+    - Bluetooth: cmtp: fix possible panic when cmtp_init_sockets() fails
+    - clk: bcm-2835: Pick the closest clock rate
+    - clk: bcm-2835: Remove rounding up the dividers
+    - wcn36xx: Indicate beacon not connection loss on MISSED_BEACON_IND
+    - wcn36xx: Release DMA channel descriptor allocations
+    - media: videobuf2: Fix the size printk format
+    - media: aspeed: fix mode-detect always time out at 2nd run
+    - media: em28xx: fix memory leak in em28xx_init_dev
+    - media: aspeed: Update signal status immediately to ensure sane hw state
+    - arm64: dts: meson-gxbb-wetek: fix HDMI in early boot
+    - arm64: dts: meson-gxbb-wetek: fix missing GPIO binding
+    - Bluetooth: stop proccessing malicious adv data
+    - tee: fix put order in teedev_close_context()
+    - media: dmxdev: fix UAF when dvb_register_device() fails
+    - crypto: qce - fix uaf on qce_ahash_register_one
+    - arm64: dts: ti: k3-j721e: correct cache-sets info
+    - tty: serial: atmel: Check return code of dmaengine_submit()
+    - tty: serial: atmel: Call dma_async_issue_pending()
+    - media: rcar-csi2: Correct the selection of hsfreqrange
+    - media: imx-pxp: Initialize the spinlock prior to using it
+    - media: si470x-i2c: fix possible memory leak in si470x_i2c_probe()
+    - media: mtk-vcodec: call v4l2_m2m_ctx_release first when file is released
+    - media: venus: core: Fix a resource leak in the error handling path of
+      'venus_probe()'
+    - netfilter: bridge: add support for pppoe filtering
+    - arm64: dts: qcom: msm8916: fix MMC controller aliases
+    - ACPI: EC: Rework flushing of EC work while suspended to idle
+    - drm/amdgpu: Fix a NULL pointer dereference in
+      amdgpu_connector_lcd_native_mode()
+    - drm/radeon/radeon_kms: Fix a NULL pointer dereference in
+      radeon_driver_open_kms()
+    - arm64: dts: ti: k3-j721e: Fix the L2 cache sets
+    - tty: serial: uartlite: allow 64 bit address
+    - serial: amba-pl011: do not request memory region twice
+    - floppy: Fix hang in watchdog when disk is ejected
+    - staging: rtl8192e: return error code from rtllib_softmac_init()
+    - staging: rtl8192e: rtllib_module: fix error handle case in alloc_rtllib()
+    - Bluetooth: btmtksdio: fix resume failure
+    - media: dib8000: Fix a memleak in dib8000_init()
+    - media: saa7146: mxb: Fix a NULL pointer dereference in mxb_attach()
+    - media: si2157: Fix "warm" tuner state detection
+    - sched/rt: Try to restart rt period timer when rt runtime exceeded
+    - rcu/exp: Mark current CPU as exp-QS in IPI loop second pass
+    - mwifiex: Fix possible ABBA deadlock
+    - xfrm: fix a small bug in xfrm_sa_len()
+    - crypto: stm32/cryp - fix xts and race condition in crypto_engine requests
+    - crypto: stm32/cryp - fix double pm exit
+    - crypto: stm32/cryp - fix lrw chaining mode
+    - ARM: dts: gemini: NAS4220-B: fis-index-block with 128 KiB sectors
+    - media: dw2102: Fix use after free
+    - media: msi001: fix possible null-ptr-deref in msi001_probe()
+    - media: coda/imx-vdoa: Handle dma_set_coherent_mask error codes
+    - drm/msm/dpu: fix safe status debugfs file
+    - drm/bridge: ti-sn65dsi86: Set max register for regmap
+    - media: hantro: Fix probe func error path
+    - xfrm: interface with if_id 0 should return error
+    - xfrm: state and policy should fail if XFRMA_IF_ID 0
+    - ARM: 9159/1: decompressor: Avoid UNPREDICTABLE NOP encoding
+    - usb: ftdi-elan: fix memory leak on device disconnect
+    - ARM: dts: armada-38x: Add generic compatible to UART nodes
+    - mmc: meson-mx-sdio: add IRQ check
+    - selinux: fix potential memleak in selinux_add_opt()
+    - bpftool: Enable line buffering for stdout
+    - x86/mce/inject: Avoid out-of-bounds write when setting flags
+    - ACPI: scan: Create platform device for BCM4752 and LNV4752 ACPI nodes
+    - pcmcia: rsrc_nonstatic: Fix a NULL pointer dereference in
+      __nonstatic_find_io_region()
+    - pcmcia: rsrc_nonstatic: Fix a NULL pointer dereference in
+      nonstatic_find_mem_region()
+    - netfilter: ipt_CLUSTERIP: fix refcount leak in clusterip_tg_check()
+    - bpf: Fix SO_RCVBUF/SO_SNDBUF handling in _bpf_setsockopt().
+    - ppp: ensure minimum packet size in ppp_write()
+    - rocker: fix a sleeping in atomic bug
+    - staging: greybus: audio: Check null pointer
+    - fsl/fman: Check for null pointer after calling devm_ioremap
+    - Bluetooth: hci_bcm: Check for error irq
+    - HID: hid-uclogic-params: Invalid parameter check in uclogic_params_init
+    - HID: hid-uclogic-params: Invalid parameter check in
+      uclogic_params_get_str_desc
+    - HID: hid-uclogic-params: Invalid parameter check in
+      uclogic_params_huion_init
+    - HID: hid-uclogic-params: Invalid parameter check in
+      uclogic_params_frame_init_v1_buttonpad
+    - debugfs: lockdown: Allow reading debugfs files that are not world readable
+    - net/mlx5e: Don't block routes with nexthop objects in SW
+    - Revert "net/mlx5e: Block offload of outer header csum for UDP tunnels"
+    - net/mlx5: Set command entry semaphore up once got index free
+    - spi: spi-meson-spifc: Add missing pm_runtime_disable() in meson_spifc_probe
+    - tpm: add request_locality before write TPM_INT_ENABLE
+    - can: softing: softing_startstop(): fix set but not used variable warning
+    - can: xilinx_can: xcan_probe(): check for error irq
+    - pcmcia: fix setting of kthread task states
+    - net: mcs7830: handle usb read errors properly
+    - ext4: avoid trim error on fs with small groups
+    - ALSA: jack: Add missing rwsem around snd_ctl_remove() calls
+    - ALSA: PCM: Add missing rwsem around snd_ctl_remove() calls
+    - ALSA: hda: Add missing rwsem around snd_ctl_remove() calls
+    - RDMA/hns: Validate the pkey index
+    - clk: imx8mn: Fix imx8mn_clko1_sels
+    - powerpc/prom_init: Fix improper check of prom_getprop()
+    - ASoC: uniphier: drop selecting non-existing SND_SOC_UNIPHIER_AIO_DMA
+    - ALSA: oss: fix compile error when OSS_DEBUG is enabled
+    - char/mwave: Adjust io port register size
+    - binder: fix handling of error during copy
+    - iommu/io-pgtable-arm: Fix table descriptor paddr formatting
+    - scsi: ufs: Fix race conditions related to driver data
+    - PCI/MSI: Fix pci_irq_vector()/pci_irq_get_affinity()
+    - powerpc/powermac: Add additional missing lockdep_register_key()
+    - RDMA/core: Let ib_find_gid() continue search even after empty entry
+    - RDMA/cma: Let cma_resolve_ib_dev() continue search even after empty entry
+    - ASoC: rt5663: Handle device_property_read_u32_array error codes
+    - clk: stm32: Fix ltdc's clock turn off by clk_disable_unused() after system
+      enter shell
+    - dmaengine: pxa/mmp: stop referencing config->slave_id
+    - iommu/iova: Fix race between FQ timeout and teardown
+    - phy: uniphier-usb3ss: fix unintended writing zeros to PHY register
+    - ASoC: samsung: idma: Check of ioremap return value
+    - misc: lattice-ecp3-config: Fix task hung when firmware load failed
+    - mips: lantiq: add support for clk_set_parent()
+    - mips: bcm63xx: add support for clk_set_parent()
+    - RDMA/cxgb4: Set queue pair state when being queried
+    - of: base: Fix phandle argument length mismatch error message
+    - Bluetooth: Fix debugfs entry leak in hci_register_dev()
+    - fs: dlm: filter user dlm messages for kernel locks
+    - drm/lima: fix warning when CONFIG_DEBUG_SG=y & CONFIG_DMA_API_DEBUG=y
+    - ar5523: Fix null-ptr-deref with unexpected WDCMSG_TARGET_START reply
+    - drm/nouveau/pmu/gm200-: avoid touching PMU outside of DEVINIT/PREOS/ACR
+    - ARM: shmobile: rcar-gen2: Add missing of_node_put()
+    - batman-adv: allow netlink usage in unprivileged containers
+    - usb: gadget: f_fs: Use stream_open() for endpoint files
+    - drm: panel-orientation-quirks: Add quirk for the Lenovo Yoga Book X91F/L
+    - HID: apple: Do not reset quirks when the Fn key is not found
+    - media: b2c2: Add missing check in flexcop_pci_isr:
+    - EDAC/synopsys: Use the quirk for version instead of ddr version
+    - mlxsw: pci: Add shutdown method in PCI driver
+    - drm/bridge: megachips: Ensure both bridges are probed before registration
+    - gpiolib: acpi: Do not set the IRQ type if the IRQ is already in use
+    - HSI: core: Fix return freed object in hsi_new_client
+    - mwifiex: Fix skb_over_panic in mwifiex_usb_recv()
+    - rsi: Fix use-after-free in rsi_rx_done_handler()
+    - rsi: Fix out-of-bounds read in rsi_read_pkt()
+    - usb: uhci: add aspeed ast2600 uhci support
+    - floppy: Add max size check for user space request
+    - x86/mm: Flush global TLB when switching to trampoline page-table
+    - media: uvcvideo: Increase UVC_CTRL_CONTROL_TIMEOUT to 5 seconds.
+    - media: saa7146: hexium_orion: Fix a NULL pointer dereference in
+      hexium_attach()
+    - media: m920x: don't use stack on USB reads
+    - iwlwifi: mvm: synchronize with FW after multicast commands
+    - ath10k: Fix tx hanging
+    - net-sysfs: update the queue counts in the unregistration path
+    - net: phy: prefer 1000baseT over 1000baseKX
+    - gpio: aspeed: Convert aspeed_gpio.lock to raw_spinlock
+    - x86/mce: Mark mce_panic() noinstr
+    - x86/mce: Mark mce_end() noinstr
+    - x86/mce: Mark mce_read_aux() noinstr
+    - net: bonding: debug: avoid printing debug logs when bond is not notifying
+      peers
+    - bpf: Do not WARN in bpf_warn_invalid_xdp_action()
+    - HID: quirks: Allow inverting the absolute X/Y values
+    - media: igorplugusb: receiver overflow should be reported
+    - media: saa7146: hexium_gemini: Fix a NULL pointer dereference in
+      hexium_attach()
+    - mmc: core: Fixup storing of OCR for MMC_QUIRK_NONSTD_SDIO
+    - audit: ensure userspace is penalized the same as the kernel when under
+      pressure
+    - arm64: dts: ls1028a-qds: move rtc node to the correct i2c bus
+    - arm64: tegra: Adjust length of CCPLEX cluster MMIO region
+    - cpufreq: Fix initialization of min and max frequency QoS requests
+    - usb: hub: Add delay for SuperSpeed hub resume to let links transit to U0
+    - ath9k: Fix out-of-bound memcpy in ath9k_hif_usb_rx_stream
+    - iwlwifi: fix leaks/bad data after failed firmware load
+    - iwlwifi: remove module loading failure message
+    - iwlwifi: mvm: Fix calculation of frame length
+    - um: registers: Rename function names to avoid conflicts and build problems
+    - jffs2: GC deadlock reading a page that is used in jffs2_write_begin()
+    - ACPICA: actypes.h: Expand the ACPI_ACCESS_ definitions
+    - ACPICA: Utilities: Avoid deleting the same object twice in a row
+    - ACPICA: Executer: Fix the REFCLASS_REFOF case in acpi_ex_opcode_1A_0T_1R()
+    - ACPICA: Fix wrong interpretation of PCC address
+    - ACPICA: Hardware: Do not flush CPU cache when entering S4 and S5
+    - drm/amdgpu: fixup bad vram size on gmc v8
+    - ACPI: battery: Add the ThinkPad "Not Charging" quirk
+    - btrfs: remove BUG_ON() in find_parent_nodes()
+    - btrfs: remove BUG_ON(!eie) in find_parent_nodes
+    - net: mdio: Demote probed message to debug print
+    - mac80211: allow non-standard VHT MCS-10/11
+    - dm btree: add a defensive bounds check to insert_at()
+    - dm space map common: add bounds check to sm_ll_lookup_bitmap()
+    - net: phy: marvell: configure RGMII delays for 88E1118
+    - net: gemini: allow any RGMII interface mode
+    - regulator: qcom_smd: Align probe function with rpmh-regulator
+    - serial: pl010: Drop CR register reset on set_termios
+    - serial: core: Keep mctrl register state and cached copy in sync
+    - random: do not throw away excess input to crng_fast_load
+    - parisc: Avoid calling faulthandler_disabled() twice
+    - powerpc/6xx: add missing of_node_put
+    - powerpc/powernv: add missing of_node_put
+    - powerpc/cell: add missing of_node_put
+    - powerpc/btext: add missing of_node_put
+    - powerpc/watchdog: Fix missed watchdog reset due to memory ordering race
+    - i2c: i801: Don't silently correct invalid transfer size
+    - powerpc/smp: Move setup_profiling_timer() under CONFIG_PROFILING
+    - i2c: mpc: Correct I2C reset procedure
+    - clk: meson: gxbb: Fix the SDM_EN bit for MPLL0 on GXBB
+    - powerpc/powermac: Add missing lockdep_register_key()
+    - KVM: PPC: Book3S: Suppress failed alloc warning in H_COPY_TOFROM_GUEST
+    - w1: Misuse of get_user()/put_user() reported by sparse
+    - scsi: lpfc: Trigger SLI4 firmware dump before doing driver cleanup
+    - ALSA: seq: Set upper limit of processed events
+    - powerpc: handle kdump appropriately with crash_kexec_post_notifiers option
+    - MIPS: OCTEON: add put_device() after of_find_device_by_node()
+    - i2c: designware-pci: Fix to change data types of hcnt and lcnt parameters
+    - MIPS: Octeon: Fix build errors using clang
+    - scsi: sr: Don't use GFP_DMA
+    - ASoC: mediatek: mt8173: fix device_node leak
+    - power: bq25890: Enable continuous conversion for ADC at charging
+    - rpmsg: core: Clean up resources on announce_create failure.
+    - crypto: omap-aes - Fix broken pm_runtime_and_get() usage
+    - crypto: stm32/crc32 - Fix kernel BUG triggered in probe()
+    - crypto: caam - replace this_cpu_ptr with raw_cpu_ptr
+    - ubifs: Error path in ubifs_remount_rw() seems to wrongly free write buffers
+    - fuse: Pass correct lend value to filemap_write_and_wait_range()
+    - serial: Fix incorrect rs485 polarity on uart open
+    - cputime, cpuacct: Include guest time in user time in cpuacct.stat
+    - tracing/kprobes: 'nmissed' not showed correctly for kretprobe
+    - iwlwifi: mvm: Increase the scan timeout guard to 30 seconds
+    - s390/mm: fix 2KB pgtable release race
+    - drm/etnaviv: limit submit sizes
+    - drm/nouveau/kms/nv04: use vzalloc for nv04_display
+    - drm/bridge: analogix_dp: Make PSR-exit block less
+    - PCI: pci-bridge-emul: Properly mark reserved PCIe bits in PCI config space
+    - PCI: pci-bridge-emul: Correctly set PCIe capabilities
+    - PCI: pci-bridge-emul: Set PCI_STATUS_CAP_LIST for PCIe device
+    - xfrm: fix policy lookup for ipv6 gre packets
+    - btrfs: fix deadlock between quota enable and other quota operations
+    - btrfs: check the root node for uptodate before returning it
+    - btrfs: respect the max size in the header when activating swap file
+    - ext4: make sure to reset inode lockdep class when quota enabling fails
+    - ext4: make sure quota gets properly shutdown on error
+    - ext4: set csum seed in tmp inode while migrating to extents
+    - ext4: Fix BUG_ON in ext4_bread when write quota data
+    - ext4: don't use the orphan list when migrating an inode
+    - drm/radeon: fix error handling in radeon_driver_open_kms
+    - of: base: Improve argument length mismatch error
+    - firmware: Update Kconfig help text for Google firmware
+    - media: rcar-csi2: Optimize the selection PHTW register
+    - Documentation: dmaengine: Correctly describe dmatest with channel unset
+    - Documentation: ACPI: Fix data node reference documentation
+    - Documentation: refer to config RANDOMIZE_BASE for kernel address-space
+      randomization
+    - Documentation: fix firewire.rst ABI file path error
+    - scsi: core: Show SCMD_LAST in text form
+    - RDMA/hns: Modify the mapping attribute of doorbell to device
+    - RDMA/rxe: Fix a typo in opcode name
+    - dmaengine: stm32-mdma: fix STM32_MDMA_CTBR_TSEL_MASK
+    - Revert "net/mlx5: Add retry mechanism to the command entry index allocation"
+    - powerpc/cell: Fix clang -Wimplicit-fallthrough warning
+    - powerpc/fsl/dts: Enable WA for erratum A-009885 on fman3l MDIO buses
+    - bpftool: Remove inclusion of utilities.mak from Makefiles
+    - ipv4: avoid quadratic behavior in netns dismantle
+    - net/fsl: xgmac_mdio: Fix incorrect iounmap when removing module
+    - parisc: pdc_stable: Fix memory leak in pdcs_register_pathentries
+    - f2fs: fix to reserve space for IO align feature
+    - af_unix: annote lockless accesses to unix_tot_inflight & gc_in_progress
+    - clk: si5341: Fix clock HW provider cleanup
+    - net: axienet: limit minimum TX ring size
+    - net: axienet: fix number of TX ring slots for available check
+    - net: axienet: increase default TX ring size to 128
+    - rtc: pxa: fix null pointer dereference
+    - inet: frags: annotate races around fqdir->dead and fqdir->high_thresh
+    - netns: add schedule point in ops_exit_list()
+    - xfrm: Don't accidentally set RTO_ONLINK in decode_session4()
+    - gre: Don't accidentally set RTO_ONLINK in gre_fill_metadata_dst()
+    - libcxgb: Don't accidentally set RTO_ONLINK in cxgb_find_route()
+    - perf script: Fix hex dump character output
+    - dmaengine: at_xdmac: Don't start transactions at tx_submit level
+    - dmaengine: at_xdmac: Print debug message after realeasing the lock
+    - dmaengine: at_xdmac: Fix concurrency over xfers_list
+    - dmaengine: at_xdmac: Fix lld view setting
+    - dmaengine: at_xdmac: Fix at_xdmac_lld struct definition
+    - arm64: dts: qcom: msm8996: drop not documented adreno properties
+    - net_sched: restore "mpu xxx" handling
+    - bcmgenet: add WOL IRQ check
+    - net: ethernet: mtk_eth_soc: fix error checking in mtk_mac_config()
+    - dt-bindings: display: meson-dw-hdmi: add missing sound-name-prefix property
+    - dt-bindings: display: meson-vpu: Add missing amlogic,canvas property
+    - scripts/dtc: dtx_diff: remove broken example from help text
+    - lib82596: Fix IRQ check in sni_82596_probe
+    - lib/test_meminit: destroy cache in kmem_cache_alloc_bulk() test
+    - mtd: nand: bbt: Fix corner case in bad block table handling
+    - Revert "ia64: kprobes: Use generic kretprobe trampoline handler"
+    - Linux 5.4.174
+  * Focal update: v5.4.173 upstream stable release (LP: #1959701)
+    - kbuild: Add $(KBUILD_HOSTLDFLAGS) to 'has_libelf' test
+    - devtmpfs regression fix: reconfigure on each mount
+    - orangefs: Fix the size of a memory allocation in orangefs_bufmap_alloc()
+    - perf: Protect perf_guest_cbs with RCU
+    - KVM: s390: Clarify SIGP orders versus STOP/RESTART
+    - media: uvcvideo: fix division by zero at stream start
+    - rtlwifi: rtl8192cu: Fix WARNING when calling local_irq_restore() with
+      interrupts enabled
+    - firmware: qemu_fw_cfg: fix sysfs information leak
+    - firmware: qemu_fw_cfg: fix NULL-pointer deref on duplicate entries
+    - firmware: qemu_fw_cfg: fix kobject leak in probe error path
+    - KVM: x86: remove PMU FIXED_CTR3 from msrs_to_save_all
+    - ALSA: hda/realtek - Fix silent output on Gigabyte X570 Aorus Master after
+      reboot from Windows
+    - mtd: fixup CFI on ixp4xx
+    - ARM: 9025/1: Kconfig: CPU_BIG_ENDIAN depends on !LD_IS_LLD
+    - Linux 5.4.173
+  * Focal update: v5.4.172 upstream stable release (LP: #1959698)
+    - workqueue: Fix unbind_workers() VS wq_worker_running() race
+    - Bluetooth: btusb: fix memory leak in btusb_mtk_submit_wmt_recv_urb()
+    - Bluetooth: bfusb: fix division by zero in send path
+    - USB: core: Fix bug in resuming hub's handling of wakeup requests
+    - USB: Fix "slab-out-of-bounds Write" bug in usb_hcd_poll_rh_status
+    - mmc: sdhci-pci: Add PCI ID for Intel ADL
+    - veth: Do not record rx queue hint in veth_xmit
+    - mfd: intel-lpss: Fix too early PM enablement in the ACPI ->probe()
+    - drivers core: Use sysfs_emit and sysfs_emit_at for show(device *...)
+      functions
+    - can: gs_usb: fix use of uninitialized variable, detach device on reception
+      of invalid USB data
+    - can: gs_usb: gs_can_start_xmit(): zero-initialize hf->{flags,reserved}
+    - random: fix data race on crng_node_pool
+    - random: fix data race on crng init time
+    - random: fix crash on multiple early calls to add_bootloader_randomness()
+    - media: Revert "media: uvcvideo: Set unique vdev name based in type"
+    - staging: wlan-ng: Avoid bitwise vs logical OR warning in
+      hfa384x_usb_throttlefn()
+    - drm/i915: Avoid bitwise vs logical OR warning in snb_wm_latency_quirk()
+    - staging: greybus: fix stack size warning with UBSAN
+    - Linux 5.4.172
+  * Focal update: v5.4.171 upstream stable release (LP: #1959437)
+    - f2fs: quota: fix potential deadlock
+    - Input: touchscreen - Fix backport of
+      a02dcde595f7cbd240ccd64de96034ad91cffc40
+    - selftests: x86: fix [-Wstringop-overread] warn in test_process_vm_readv()
+    - tracing: Fix check for trace_percpu_buffer validity in get_trace_buf()
+    - tracing: Tag trace_percpu_buffer as a percpu pointer
+    - ieee802154: atusb: fix uninit value in atusb_set_extended_addr
+    - iavf: Fix limit of total number of queues to active queues of VF
+    - RDMA/core: Don't infoleak GRH fields
+    - RDMA/uverbs: Check for null return of kmalloc_array
+    - mac80211: initialize variable have_higher_than_11mbit
+    - i40e: fix use-after-free in i40e_sync_filters_subtask()
+    - i40e: Fix for displaying message regarding NVM version
+    - i40e: Fix incorrect netdev's real number of RX/TX queues
+    - ipv4: Check attribute length for RTA_GATEWAY in multipath route
+    - ipv4: Check attribute length for RTA_FLOW in multipath route
+    - ipv6: Check attribute length for RTA_GATEWAY in multipath route
+    - ipv6: Check attribute length for RTA_GATEWAY when deleting multipath route
+    - lwtunnel: Validate RTA_ENCAP_TYPE attribute length
+    - batman-adv: mcast: don't send link-local multicast to mcast routers
+    - sch_qfq: prevent shift-out-of-bounds in qfq_init_qdisc
+    - net: phy: micrel: set soft_reset callback to genphy_soft_reset for KSZ8081
+    - power: supply: core: Break capacity loop
+    - power: reset: ltc2952: Fix use of floating point literals
+    - rndis_host: support Hytera digital radios
+    - phonet: refcount leak in pep_sock_accep
+    - ipv6: Continue processing multipath route even if gateway attribute is
+      invalid
+    - ipv6: Do cleanup if attribute validation fails in multipath route
+    - usb: mtu3: fix interval value for intr and isoc
+    - scsi: libiscsi: Fix UAF in iscsi_conn_get_param()/iscsi_conn_teardown()
+    - ip6_vti: initialize __ip6_tnl_parm struct in vti6_siocdevprivate
+    - net: udp: fix alignment problem in udp4_seq_show()
+    - atlantic: Fix buff_ring OOB in aq_ring_rx_clean
+    - mISDN: change function names to avoid conflicts
+    - Linux 5.4.171
+  * Focal update: v5.4.170 upstream stable release (LP: #1958898)
+    - tee: handle lookup of shm with reference count 0
+    - Input: i8042 - add deferred probe support
+    - Input: i8042 - enable deferred probe quirk for ASUS UM325UA
+    - tomoyo: Check exceeded quota early in tomoyo_domain_quota_is_ok().
+    - platform/x86: apple-gmux: use resource_size() with res
+    - memblock: fix memblock_phys_alloc() section mismatch error
+    - recordmcount.pl: fix typo in s390 mcount regex
+    - selinux: initialize proto variable in selinux_ip_postroute_compat()
+    - scsi: lpfc: Terminate string in lpfc_debugfs_nvmeio_trc_write()
+    - net/mlx5: DR, Fix NULL vs IS_ERR checking in dr_domain_init_resources
+    - sctp: use call_rcu to free endpoint
+    - net: usb: pegasus: Do not drop long Ethernet frames
+    - net: lantiq_xrx200: fix statistics of received bytes
+    - NFC: st21nfca: Fix memory leak in device probe and remove
+    - ionic: Initialize the 'lif->dbid_inuse' bitmap
+    - net/mlx5e: Fix wrong features assignment in case of error
+    - selftests/net: udpgso_bench_tx: fix dst ip argument
+    - net/ncsi: check for error return from call to nla_put_u32
+    - fsl/fman: Fix missing put_device() call in fman_port_probe
+    - i2c: validate user data in compat ioctl
+    - nfc: uapi: use kernel size_t to fix user-space builds
+    - uapi: fix linux/nfc.h userspace compilation errors
+    - xhci: Fresco FL1100 controller should not have BROKEN_MSI quirk set.
+    - usb: gadget: f_fs: Clear ffs_eventfd in ffs_data_clear.
+    - usb: mtu3: add memory barrier before set GPD's HWO
+    - usb: mtu3: fix list_head check warning
+    - usb: mtu3: set interval of FS intr and isoc endpoint
+    - binder: fix async_free_space accounting for empty parcels
+    - scsi: vmw_pvscsi: Set residual data length conditionally
+    - Input: appletouch - initialize work before device registration
+    - Input: spaceball - fix parsing of movement data packets
+    - net: fix use-after-free in tw_timer_handler
+    - perf script: Fix CPU filtering of a script's switch events
+    - Linux 5.4.170
+  * Focal update: v5.4.170 upstream stable release (LP: #1958898) // HID_ASUS
+    should depend on USB_HID in stable v4.15 backports (LP: #1959762)
+    - HID: asus: Add depends on USB_HID to HID_ASUS Kconfig option
+  * Focal update: v5.4.169 upstream stable release (LP: #1958557)
+    - net: usb: lan78xx: add Allied Telesis AT29M2-AF
+    - serial: 8250_fintek: Fix garbled text for console
+    - arm64: dts: allwinner: orangepi-zero-plus: fix PHY mode
+    - spi: change clk_disable_unprepare to clk_unprepare
+    - IB/qib: Fix memory leak in qib_user_sdma_queue_pkts()
+    - netfilter: fix regression in looped (broad|multi)cast's MAC handling
+    - qlcnic: potential dereference null pointer of rx_queue->page_ring
+    - net: accept UFOv6 packages in virtio_net_hdr_to_skb
+    - net: skip virtio_net_hdr_set_proto if protocol already set
+    - ipmi: Fix UAF when uninstall ipmi_si and ipmi_msghandler module
+    - bonding: fix ad_actor_system option setting to default
+    - fjes: Check for error irq
+    - drivers: net: smc911x: Check for error irq
+    - sfc: falcon: Check null pointer of rx_queue->page_ring
+    - Input: elantech - fix stack out of bound access in
+      elantech_change_report_id()
+    - hwmon: (lm90) Fix usage of CONFIG2 register in detect function
+    - hwmon: (lm90) Add max6654 support to lm90 driver
+    - hwmon: (lm90) Add basic support for TI TMP461
+    - hwmon: (lm90) Introduce flag indicating extended temperature support
+    - hwmon: (lm90) Drop critical attribute support for MAX6654
+    - ALSA: jack: Check the return value of kstrdup()
+    - ALSA: drivers: opl3: Fix incorrect use of vp->state
+    - ALSA: hda/realtek: Amp init fixup for HP ZBook 15 G6
+    - Input: atmel_mxt_ts - fix double free in mxt_read_info_block
+    - ipmi: bail out if init_srcu_struct fails
+    - ipmi: ssif: initialize ssif_info->client early
+    - ipmi: fix initialization when workqueue allocation fails
+    - parisc: Correct completer in lws start
+    - x86/pkey: Fix undefined behaviour with PKRU_WD_BIT
+    - pinctrl: stm32: consider the GPIO offset to expose all the GPIO lines
+    - mmc: sdhci-tegra: Fix switch to HS400ES mode
+    - mmc: core: Disable card detect during shutdown
+    - ARM: 9169/1: entry: fix Thumb2 bug in iWMMXt exception handling
+    - tee: optee: Fix incorrect page free bug
+    - f2fs: fix to do sanity check on last xattr entry in __f2fs_setxattr()
+    - usb: gadget: u_ether: fix race in setting MAC address in setup phase
+    - KVM: VMX: Fix stale docs for kvm-intel.emulate_invalid_guest_state
+    - mm: mempolicy: fix THP allocations escaping mempolicy restrictions
+    - pinctrl: mediatek: fix global-out-of-bounds issue
+    - hwmom: (lm90) Fix citical alarm status for MAX6680/MAX6681
+    - hwmon: (lm90) Do not report 'busy' status bit as alarm
+    - ax25: NPD bug when detaching AX25 device
+    - hamradio: defer ax25 kfree after unregister_netdev
+    - hamradio: improve the incomplete fix to avoid NPD
+    - phonet/pep: refuse to enable an unbound pipe
+    - Linux 5.4.169
+  * Focal update: v5.4.168 upstream stable release (LP: #1957991)
+    - KVM: selftests: Make sure kvm_create_max_vcpus test won't hit RLIMIT_NOFILE
+    - mac80211: mark TX-during-stop for TX in in_reconfig
+    - mac80211: send ADDBA requests using the tid/queue of the aggregation session
+    - firmware: arm_scpi: Fix string overflow in SCPI genpd driver
+    - virtio_ring: Fix querying of maximum DMA mapping size for virtio device
+    - recordmcount.pl: look for jgnop instruction as well as bcrl on s390
+    - dm btree remove: fix use after free in rebalance_children()
+    - audit: improve robustness of the audit queue handling
+    - iio: adc: stm32: fix a current leak by resetting pcsel before disabling vdda
+    - nfsd: fix use-after-free due to delegation race
+    - arm64: dts: rockchip: remove mmc-hs400-enhanced-strobe from rk3399-khadas-
+      edge
+    - arm64: dts: rockchip: fix rk3399-leez-p710 vcc3v3-lan supply
+    - arm64: dts: rockchip: fix audio-supply for Rock Pi 4
+    - mac80211: track only QoS data frames for admission control
+    - ARM: socfpga: dts: fix qspi node compatible
+    - clk: Don't parent clks until the parent is fully registered
+    - selftests: net: Correct ping6 expected rc from 2 to 1
+    - s390/kexec_file: fix error handling when applying relocations
+    - sch_cake: do not call cake_destroy() from cake_init()
+    - inet_diag: use jiffies_delta_to_msecs()
+    - inet_diag: fix kernel-infoleak for UDP sockets
+    - selftests: Fix raw socket bind tests with VRF
+    - selftests: Fix IPv6 address bind tests
+    - dmaengine: st_fdma: fix MODULE_ALIAS
+    - selftest/net/forwarding: declare NETIFS p9 p10
+    - mac80211: agg-tx: refactor sending addba
+    - mac80211: agg-tx: don't schedule_and_wake_txq() under sta->lock
+    - mac80211: accept aggregation sessions on 6 GHz
+    - mac80211: fix lookup when adding AddBA extension element
+    - net: sched: lock action when translating it to flow_action infra
+    - flow_offload: return EOPNOTSUPP for the unsupported mpls action type
+    - rds: memory leak in __rds_conn_create()
+    - soc/tegra: fuse: Fix bitwise vs. logical OR warning
+    - igb: Fix removal of unicast MAC filters of VFs
+    - igbvf: fix double free in `igbvf_probe`
+    - ixgbe: set X550 MDIO speed before talking to PHY
+    - netdevsim: Zero-initialize memory for new map's value in function
+      nsim_bpf_map_alloc
+    - net: Fix double 0x prefix print in SKB dump
+    - net/smc: Prevent smc_release() from long blocking
+    - net: systemport: Add global locking for descriptor lifecycle
+    - sit: do not call ipip6_dev_free() from sit_init_net()
+    - USB: NO_LPM quirk Lenovo USB-C to Ethernet Adapher(RTL8153-04)
+    - PCI/MSI: Clear PCI_MSIX_FLAGS_MASKALL on error
+    - PCI/MSI: Mask MSI-X vectors only on success
+    - usb: xhci: Extend support for runtime power management for AMD's Yellow
+      carp.
+    - USB: serial: cp210x: fix CP2105 GPIO registration
+    - USB: serial: option: add Telit FN990 compositions
+    - timekeeping: Really make sure wall_to_monotonic isn't positive
+    - libata: if T_LENGTH is zero, dma direction should be DMA_NONE
+    - drm/amdgpu: correct register access for RLC_JUMP_TABLE_RESTORE
+    - mac80211: validate extended element ID is present
+    - mwifiex: Remove unnecessary braces from HostCmd_SET_SEQ_NO_BSS_INFO
+    - Input: touchscreen - avoid bitwise vs logical OR warning
+    - ARM: dts: imx6ull-pinfunc: Fix CSI_DATA07__ESAI_TX0 pad name
+    - xsk: Do not sleep in poll() when need_wakeup set
+    - media: mxl111sf: change mutex_init() location
+    - fuse: annotate lock in fuse_reverse_inval_entry()
+    - ovl: fix warning in ovl_create_real()
+    - scsi: scsi_debug: Sanity check block descriptor length in resp_mode_select()
+    - rcu: Mark accesses to rcu_state.n_force_qs
+    - mac80211: fix regression in SSN handling of addba tx
+    - net: sched: Fix suspicious RCU usage while accessing tcf_tunnel_info
+    - Revert "xsk: Do not sleep in poll() when need_wakeup set"
+    - xen/blkfront: harden blkfront against event channel storms
+    - xen/netfront: harden netfront against event channel storms
+    - xen/console: harden hvc_xen against event channel storms
+    - xen/netback: fix rx queue stall detection
+    - xen/netback: don't queue unlimited number of packages
+    - Linux 5.4.168
+  * Focal update: v5.4.167 upstream stable release (LP: #1957987)
+    - nfc: fix segfault in nfc_genl_dump_devices_done
+    - drm/msm/dsi: set default num_data_lanes
+    - net/mlx4_en: Update reported link modes for 1/10G
+    - parisc/agp: Annotate parisc agp init functions with __init
+    - i2c: rk3x: Handle a spurious start completion interrupt flag
+    - net: netlink: af_netlink: Prevent empty skb by adding a check on len.
+    - drm/amd/display: Fix for the no Audio bug with Tiled Displays
+    - drm/amd/display: add connector type check for CRC source set
+    - tracing: Fix a kmemleak false positive in tracing_map
+    - KVM: x86: Ignore sparse banks size for an "all CPUs", non-sparse IPI req
+    - selinux: fix race condition when computing ocontext SIDs
+    - bpf: Fix integer overflow in argument calculation for bpf_map_area_alloc
+    - hwmon: (dell-smm) Fix warning on /proc/i8k creation error
+    - memblock: free_unused_memmap: use pageblock units instead of MAX_ORDER
+    - memblock: align freed memory map on pageblock boundaries with SPARSEMEM
+    - memblock: ensure there is no overflow in memblock_overlaps_region()
+    - arm: extend pfn_valid to take into account freed memory map alignment
+    - arm: ioremap: don't abuse pfn_valid() to check if pfn is in RAM
+    - Linux 5.4.167
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync getabis
+
+  [ Ubuntu: 5.4.0-104.118 ]
+
+  * CVE-2022-23960
+    - SAUCE: kvm: arm: fix build on 32-bit
+
+  [ Ubuntu: 5.4.0-103.117 ]
+
+  * CVE-2022-23960
+    - arm64: Add part number for Arm Cortex-A77
+    - arm64: Add Neoverse-N2, Cortex-A710 CPU part definition
+    - arm64: Add Cortex-X2 CPU part definition
+    - arm64: add ID_AA64ISAR2_EL1 sys register
+    - SAUCE: arm64: entry.S: Add ventry overflow sanity checks
+    - SAUCE: arm64: entry: Make the trampoline cleanup optional
+    - SAUCE: arm64: entry: Free up another register on kpti's tramp_exit path
+    - SAUCE: arm64: entry: Move the trampoline data page before the text page
+    - SAUCE: arm64: entry: Allow tramp_alias to access symbols after the 4K
+      boundary
+    - SAUCE: arm64: entry: Don't assume tramp_vectors is the start of the vectors
+    - SAUCE: arm64: entry: Move trampoline macros out of ifdef'd section
+    - SAUCE: arm64: entry: Make the kpti trampoline's kpti sequence optional
+    - SAUCE: arm64: entry: Allow the trampoline text to occupy multiple pages
+    - SAUCE: arm64: entry: Add non-kpti __bp_harden_el1_vectors for mitigations
+    - SAUCE: arm64: entry: Add vectors that have the bhb mitigation sequences
+    - SAUCE: arm64: entry: Add macro for reading symbol addresses from the
+      trampoline
+    - SAUCE: arm64: Add percpu vectors for EL1
+    - SAUCE: arm64: proton-pack: Report Spectre-BHB vulnerabilities as part of
+      Spectre-v2
+    - SAUCE: KVM: arm64: Add templates for BHB mitigation sequences
+    - SAUCE: arm64: Mitigate spectre style branch history side channels
+    - SAUCE: KVM: arm64: Allow SMCCC_ARCH_WORKAROUND_3 to be discovered and
+      migrated
+    - SAUCE: arm64: Use the clearbhb instruction in mitigations
+    - [Config]: set CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY=y
+  * CVE-2022-25636
+    - netfilter: nf_tables_offload: incorrect flow offload action array size
+  * CVE-2022-0001
+    - x86/speculation: Merge one test in spectre_v2_user_select_mitigation()
+    - x86,bugs: Unconditionally allow spectre_v2=retpoline,amd
+    - SAUCE: x86/speculation: Rename RETPOLINE_AMD to RETPOLINE_LFENCE
+    - SAUCE: x86/speculation: Add eIBRS + Retpoline options
+    - SAUCE: Documentation/hw-vuln: Update spectre doc
+  * Disable unprivileged BPF by default (LP: #1961338)
+    - bpf: Add kconfig knob for disabling unpriv bpf by default
+    - [Config] set CONFIG_BPF_UNPRIV_DEFAULT_OFF=y
+
+  [ Ubuntu: 5.4.0-100.113 ]
+
+  * focal/linux: 5.4.0-100.113 -proposed tracker (LP: #1959900)
+  * CVE-2022-22942
+    - SAUCE: drm/vmwgfx: Fix stale file descriptors on failed usercopy
+  * CVE-2022-0330
+    - drm/i915: Flush TLBs before releasing backing store
+  * Focal update: v5.4.166 upstream stable release (LP: #1957008)
+    - netfilter: selftest: conntrack_vrf.sh: fix file permission
+    - Linux 5.4.166
+    - net/packet: rx_owner_map depends on pg_vec
+    - USB: gadget: bRequestType is a bitfield, not a enum
+    - HID: holtek: fix mouse probing
+    - udp: using datalen to cap ipv6 udp max gso segments
+    - selftests: Calculate udpgso segment count without header adjustment
+  * Focal update: v5.4.165 upstream stable release (LP: #1957007)
+    - serial: tegra: Change lower tolerance baud rate limit for tegra20 and
+      tegra30
+    - ntfs: fix ntfs_test_inode and ntfs_init_locked_inode function type
+    - HID: quirks: Add quirk for the Microsoft Surface 3 type-cover
+    - HID: google: add eel USB id
+    - HID: add hid_is_usb() function to make it simpler for USB detection
+    - HID: add USB_HID dependancy to hid-prodikeys
+    - HID: add USB_HID dependancy to hid-chicony
+    - HID: add USB_HID dependancy on some USB HID drivers
+    - HID: bigbenff: prevent null pointer dereference
+    - HID: wacom: fix problems when device is not a valid USB device
+    - HID: check for valid USB device for many HID drivers
+    - can: kvaser_usb: get CAN clock frequency from device
+    - can: kvaser_pciefd: kvaser_pciefd_rx_error_frame(): increase correct
+      stats->{rx,tx}_errors counter
+    - can: sja1000: fix use after free in ems_pcmcia_add_card()
+    - nfc: fix potential NULL pointer deref in nfc_genl_dump_ses_done
+    - selftests: netfilter: add a vrf+conntrack testcase
+    - vrf: don't run conntrack on vrf with !dflt qdisc
+    - bpf: Fix the off-by-two error in range markings
+    - ice: ignore dropped packets during init
+    - bonding: make tx_rebalance_counter an atomic
+    - nfp: Fix memory leak in nfp_cpp_area_cache_add()
+    - seg6: fix the iif in the IPv6 socket control block
+    - udp: using datalen to cap max gso segments
+    - iavf: restore MSI state on reset
+    - iavf: Fix reporting when setting descriptor count
+    - IB/hfi1: Correct guard on eager buffer deallocation
+    - mm: bdi: initialize bdi_min_ratio when bdi is unregistered
+    - ALSA: ctl: Fix copy of updated id with element read/write
+    - ALSA: hda/realtek - Add headset Mic support for Lenovo ALC897 platform
+    - ALSA: pcm: oss: Fix negative period/buffer sizes
+    - ALSA: pcm: oss: Limit the period size to 16MB
+    - ALSA: pcm: oss: Handle missing errors in snd_pcm_oss_change_params*()
+    - btrfs: clear extent buffer uptodate when we fail to write it
+    - btrfs: replace the BUG_ON in btrfs_del_root_ref with proper error handling
+    - nfsd: Fix nsfd startup race (again)
+    - tracefs: Have new files inherit the ownership of their parent
+    - clk: qcom: regmap-mux: fix parent clock lookup
+    - drm/syncobj: Deal with signalled fences in drm_syncobj_find_fence.
+    - can: pch_can: pch_can_rx_normal: fix use after free
+    - can: m_can: Disable and ignore ELO interrupt
+    - x86/sme: Explicitly map new EFI memmap table as encrypted
+    - libata: add horkage for ASMedia 1092
+    - wait: add wake_up_pollfree()
+    - SAUCE: binder: export __wake_up_pollfree for binder module
+    - binder: use wake_up_pollfree()
+    - signalfd: use wake_up_pollfree()
+    - aio: keep poll requests on waitqueue until completed
+    - aio: fix use-after-free due to missing POLLFREE handling
+    - tracefs: Set all files to the same group ownership as the mount option
+    - block: fix ioprio_get(IOPRIO_WHO_PGRP) vs setuid(2)
+    - qede: validate non LSO skb length
+    - ASoC: qdsp6: q6routing: Fix return value from msm_routing_put_audio_mixer
+    - i40e: Fix failed opcode appearing if handling messages from VF
+    - i40e: Fix pre-set max number of queues for VF
+    - mtd: rawnand: fsmc: Take instruction delay into account
+    - mtd: rawnand: fsmc: Fix timing computation
+    - dt-bindings: net: Reintroduce PHY no lane swap binding
+    - tools build: Remove needless libpython-version feature check that breaks
+      test-all fast path
+    - net: cdc_ncm: Allow for dwNtbOutMaxSize to be unset or zero
+    - net: altera: set a couple error code in probe()
+    - net: fec: only clear interrupt of handling queue in fec_enet_rx_queue()
+    - net, neigh: clear whole pneigh_entry at alloc time
+    - net/qla3xxx: fix an error code in ql_adapter_up()
+    - Revert "UBUNTU: SAUCE: selftests: fib_tests: assign address to dummy1 for
+      rp_filter tests"
+    - selftests/fib_tests: Rework fib_rp_filter_test()
+    - USB: gadget: detect too-big endpoint 0 requests
+    - USB: gadget: zero allocate endpoint 0 buffers
+    - usb: core: config: fix validation of wMaxPacketValue entries
+    - xhci: Remove CONFIG_USB_DEFAULT_PERSIST to prevent xHCI from runtime
+      suspending
+    - usb: core: config: using bit mask instead of individual bits
+    - xhci: avoid race between disable slot command and host runtime suspend
+    - iio: trigger: Fix reference counting
+    - iio: trigger: stm32-timer: fix MODULE_ALIAS
+    - iio: stk3310: Don't return error code in interrupt handler
+    - iio: mma8452: Fix trigger reference couting
+    - iio: ltr501: Don't return error code in trigger handler
+    - iio: kxsd9: Don't return error code in trigger handler
+    - iio: itg3200: Call iio_trigger_notify_done() on error
+    - iio: dln2-adc: Fix lockdep complaint
+    - iio: dln2: Check return value of devm_iio_trigger_register()
+    - iio: at91-sama5d2: Fix incorrect sign extension
+    - iio: adc: axp20x_adc: fix charging current reporting on AXP22x
+    - iio: ad7768-1: Call iio_trigger_notify_done() on error
+    - iio: accel: kxcjk-1013: Fix possible memory leak in probe and remove
+    - irqchip/armada-370-xp: Fix return value of armada_370_xp_msi_alloc()
+    - irqchip/armada-370-xp: Fix support for Multi-MSI interrupts
+    - irqchip/irq-gic-v3-its.c: Force synchronisation when issuing INVALL
+    - irqchip: nvic: Fix offset for Interrupt Priority Offsets
+    - misc: fastrpc: fix improper packet size calculation
+    - bpf: Add selftests to cover packet access corner cases
+    - Linux 5.4.165
+  * Focal update: v5.4.164 upstream stable release (LP: #1956381)
+    - NFSv42: Fix pagecache invalidation after COPY/CLONE
+    - of: clk: Make <linux/of_clk.h> self-contained
+    - arm64: dts: mcbin: support 2W SFP modules
+    - can: j1939: j1939_tp_cmd_recv(): check the dst address of TP.CM_BAM
+    - gfs2: Fix length of holes reported at end-of-file
+    - drm/sun4i: fix unmet dependency on RESET_CONTROLLER for PHY_SUN6I_MIPI_DPHY
+    - mac80211: do not access the IV when it was stripped
+    - net/smc: Transfer remaining wait queue entries during fallback
+    - atlantic: Fix OOB read and write in hw_atl_utils_fw_rpc_wait
+    - net: return correct error code
+    - platform/x86: thinkpad_acpi: Fix WWAN device disabled issue after S3 deep
+    - s390/setup: avoid using memblock_enforce_memory_limit
+    - btrfs: check-integrity: fix a warning on write caching disabled disk
+    - thermal: core: Reset previous low and high trip during thermal zone init
+    - scsi: iscsi: Unblock session then wake up error handler
+    - ata: ahci: Add Green Sardine vendor ID as board_ahci_mobile
+    - ethernet: hisilicon: hns: hns_dsaf_misc: fix a possible array overflow in
+      hns_dsaf_ge_srst_by_port()
+    - net: tulip: de4x5: fix the problem that the array 'lp->phy[8]' may be out of
+      bound
+    - net: ethernet: dec: tulip: de4x5: fix possible array overflows in
+      type3_infoblock()
+    - perf hist: Fix memory leak of a perf_hpp_fmt
+    - perf report: Fix memory leaks around perf_tip()
+    - net/smc: Avoid warning of possible recursive locking
+    - vrf: Reset IPCB/IP6CB when processing outbound pkts in vrf dev xmit
+    - kprobes: Limit max data_size of the kretprobe instances
+    - rt2x00: do not mark device gone on EPROTO errors during start
+    - cpufreq: Fix get_cpu_device() failure in add_cpu_dev_symlink()
+    - s390/pci: move pseudo-MMIO to prevent MIO overlap
+    - sata_fsl: fix UAF in sata_fsl_port_stop when rmmod sata_fsl
+    - sata_fsl: fix warning in remove_proc_entry when rmmod sata_fsl
+    - i2c: stm32f7: flush TX FIFO upon transfer errors
+    - i2c: stm32f7: recover the bus on access timeout
+    - i2c: stm32f7: stop dma transfer in case of NACK
+    - i2c: cbus-gpio: set atomic transfer callback
+    - natsemi: xtensa: fix section mismatch warnings
+    - net: qlogic: qlcnic: Fix a NULL pointer dereference in
+      qlcnic_83xx_add_rings()
+    - net: mpls: Fix notifications when deleting a device
+    - siphash: use _unaligned version by default
+    - net/mlx4_en: Fix an use-after-free bug in mlx4_en_try_alloc_resources()
+    - selftests: net: Correct case name
+    - rxrpc: Fix rxrpc_local leak in rxrpc_lookup_peer()
+    - net: usb: lan78xx: lan78xx_phy_init(): use PHY_POLL instead of "0" if no IRQ
+      is available
+    - net: marvell: mvpp2: Fix the computation of shared CPUs
+    - net: annotate data-races on txq->xmit_lock_owner
+    - ipv4: convert fib_num_tclassid_users to atomic_t
+    - net/rds: correct socket tunable error in rds_tcp_tune()
+    - net/smc: Keep smc_close_final rc during active close
+    - drm/msm: Do hw_init() before capturing GPU state
+    - ipv6: fix memory leak in fib6_rule_suppress
+    - KVM: x86/pmu: Fix reserved bits for AMD PerfEvtSeln register
+    - sched/uclamp: Fix rq->uclamp_max not set on first enqueue
+    - parisc: Fix KBUILD_IMAGE for self-extracting kernel
+    - parisc: Fix "make install" on newer debian releases
+    - vgacon: Propagate console boot parameters before calling `vc_resize'
+    - xhci: Fix commad ring abort, write all 64 bits to CRCR register.
+    - USB: NO_LPM quirk Lenovo Powered USB-C Travel Hub
+    - usb: typec: tcpm: Wait in SNK_DEBOUNCED until disconnect
+    - x86/tsc: Add a timer to make sure TSC_adjust is always checked
+    - x86/tsc: Disable clocksource watchdog for TSC on qualified platorms
+    - x86/64/mm: Map all kernel memory into trampoline_pgd
+    - tty: serial: msm_serial: Deactivate RX DMA for polling support
+    - serial: pl011: Add ACPI SBSA UART match id
+    - serial: core: fix transmit-buffer reset and memleak
+    - serial: 8250_pci: Fix ACCES entries in pci_serial_quirks array
+    - serial: 8250_pci: rewrite pericom_do_set_divisor()
+    - iwlwifi: mvm: retry init flow if failed
+    - parisc: Mark cr16 CPU clocksource unstable on all SMP machines
+    - net/tls: Fix authentication failure in CCM mode
+    - Linux 5.4.164
+  * Focal update: v5.4.163 upstream stable release (LP: #1956380)
+    - USB: serial: option: add Telit LE910S1 0x9200 composition
+    - USB: serial: option: add Fibocom FM101-GL variants
+    - usb: dwc2: gadget: Fix ISOC flow for elapsed frames
+    - usb: dwc2: hcd_queue: Fix use of floating point literal
+    - net: nexthop: fix null pointer dereference when IPv6 is not enabled
+    - usb: typec: fusb302: Fix masking of comparator and bc_lvl interrupts
+    - usb: hub: Fix usb enumeration issue due to address0 race
+    - usb: hub: Fix locking issues with address0_mutex
+    - binder: fix test regression due to sender_euid change
+    - ALSA: ctxfi: Fix out-of-range access
+    - media: cec: copy sequence field for the reply
+    - HID: wacom: Use "Confidence" flag to prevent reporting invalid contacts
+    - staging/fbtft: Fix backlight
+    - staging: rtl8192e: Fix use after free in _rtl92e_pci_disconnect()
+    - xen: don't continue xenstore initialization in case of errors
+    - xen: detect uninitialized xenbus in xenbus_init
+    - KVM: PPC: Book3S HV: Prevent POWER7/8 TLB flush flushing SLB
+    - tracing/uprobe: Fix uprobe_perf_open probes iteration
+    - tracing: Fix pid filtering when triggers are attached
+    - mmc: sdhci: Fix ADMA for PAGE_SIZE >= 64KiB
+    - mdio: aspeed: Fix "Link is Down" issue
+    - PCI: aardvark: Deduplicate code in advk_pcie_rd_conf()
+    - PCI: aardvark: Wait for endpoint to be ready before training link
+    - PCI: aardvark: Fix big endian support
+    - PCI: aardvark: Train link immediately after enabling training
+    - PCI: aardvark: Improve link training
+    - PCI: aardvark: Issue PERST via GPIO
+    - PCI: aardvark: Replace custom macros by standard linux/pci_regs.h macros
+    - PCI: aardvark: Don't touch PCIe registers if no card connected
+    - PCI: aardvark: Fix compilation on s390
+    - PCI: aardvark: Move PCIe reset card code to advk_pcie_train_link()
+    - PCI: aardvark: Update comment about disabling link training
+    - PCI: pci-bridge-emul: Fix array overruns, improve safety
+    - PCI: aardvark: Configure PCIe resources from 'ranges' DT property
+    - PCI: aardvark: Fix PCIe Max Payload Size setting
+    - PCI: aardvark: Implement re-issuing config requests on CRS response
+    - PCI: aardvark: Simplify initialization of rootcap on virtual bridge
+    - PCI: aardvark: Fix link training
+    - PCI: aardvark: Fix support for bus mastering and PCI_COMMAND on emulated
+      bridge
+    - PCI: aardvark: Set PCI Bridge Class Code to PCI Bridge
+    - PCI: aardvark: Fix support for PCI_BRIDGE_CTL_BUS_RESET on emulated bridge
+    - pinctrl: armada-37xx: Correct PWM pins definitions
+    - arm64: dts: marvell: armada-37xx: Set pcie_reset_pin to gpio function
+    - proc/vmcore: fix clearing user buffer by properly using clear_user()
+    - netfilter: ipvs: Fix reuse connection if RS weight is 0
+    - ARM: dts: BCM5301X: Fix I2C controller interrupt
+    - ARM: dts: BCM5301X: Add interrupt properties to GPIO node
+    - ASoC: qdsp6: q6routing: Conditionally reset FrontEnd Mixer
+    - ASoC: topology: Add missing rwsem around snd_ctl_remove() calls
+    - net: ieee802154: handle iftypes as u32
+    - firmware: arm_scmi: pm: Propagate return value to caller
+    - NFSv42: Don't fail clone() unless the OP_CLONE operation failed
+    - ARM: socfpga: Fix crash with CONFIG_FORTIRY_SOURCE
+    - scsi: mpt3sas: Fix kernel panic during drive powercycle test
+    - drm/vc4: fix error code in vc4_create_object()
+    - iavf: Prevent changing static ITR values if adaptive moderation is on
+    - ipv6: fix typos in __ip6_finish_output()
+    - nfp: checking parameter process for rx-usecs/tx-usecs is invalid
+    - net: ipv6: add fib6_nh_release_dsts stub
+    - net: nexthop: release IPv6 per-cpu dsts when replacing a nexthop group
+    - scsi: core: sysfs: Fix setting device state to SDEV_RUNNING
+    - net/smc: Ensure the active closing peer first closes clcsock
+    - nvmet-tcp: fix incomplete data digest send
+    - net/ncsi : Add payload to be 32-bit aligned to fix dropped packets
+    - PM: hibernate: use correct mode for swsusp_close()
+    - tcp_cubic: fix spurious Hystart ACK train detections for not-cwnd-limited
+      flows
+    - nvmet: use IOCB_NOWAIT only if the filesystem supports it
+    - igb: fix netpoll exit with traffic
+    - MIPS: use 3-level pgtable for 64KB page size on MIPS_VA_BITS_48
+    - net: vlan: fix underflow for the real_dev refcnt
+    - net/smc: Don't call clcsock shutdown twice when smc shutdown
+    - net: hns3: fix VF RSS failed problem after PF enable multi-TCs
+    - net: mscc: ocelot: don't downgrade timestamping RX filters in SIOCSHWTSTAMP
+    - net: mscc: ocelot: correctly report the timestamping RX filters in ethtool
+    - f2fs: set SBI_NEED_FSCK flag when inconsistent node block found
+    - smb3: do not error on fsync when readonly
+    - vhost/vsock: fix incorrect used length reported to the guest
+    - tracing: Check pid filtering when creating events
+    - s390/mm: validate VMA in PGSTE manipulation functions
+    - shm: extend forced shm destroy to support objects from several IPC nses
+    - NFC: add NCI_UNREG flag to eliminate the race
+    - fuse: release pipe buf after last use
+    - xen: sync include/xen/interface/io/ring.h with Xen's newest version
+    - xen/blkfront: read response from backend only once
+    - xen/blkfront: don't take local copy of a request from the ring page
+    - xen/blkfront: don't trust the backend response data blindly
+    - xen/netfront: read response from backend only once
+    - xen/netfront: don't read data from request on the ring page
+    - xen/netfront: disentangle tx_skb_freelist
+    - xen/netfront: don't trust the backend response data blindly
+    - tty: hvc: replace BUG_ON() with negative return value
+    - Linux 5.4.163
+  * net/mlx5e: EPERM on vlan 0 programming (LP: #1957753)
+    - net/mlx5e: Unblock setting vid 0 for VF in case PF isn't eswitch manager
+  * CVE-2021-4083
+    - fget: check that the fd still exists after getting a ref to it
+  * CVE-2021-4155
+    - xfs: map unwritten blocks in XFS_IOC_{ALLOC, FREE}SP just like fallocate
+
+  [ Ubuntu: 5.4.0-99.112 ]
+
+  * focal/linux: 5.4.0-99.112 -proposed tracker (LP: #1959817)
+  * linux-image-5.4.0-97.110 freezes by accessing cifs shares (LP: #1959665)
+    - Revert "cifs: To match file servers, make sure the server hostname matches"
+    - Revert "cifs: set a minimum of 120s for next dns resolution"
+    - Revert "cifs: use the expiry output of dns_query to schedule next
+      resolution"
+
+  [ Ubuntu: 5.4.0-97.110 ]
+
+  * icmp_redirect from selftests fails on F/kvm (unary operator expected)
+    (LP: #1938964)
+    - selftests: icmp_redirect: pass xfail=0 to log_test()
+  * Focal: CIFS stable updates (LP: #1954926)
+    - cifs: use the expiry output of dns_query to schedule next resolution
+    - cifs: set a minimum of 120s for next dns resolution
+    - cifs: To match file servers, make sure the server hostname matches
+  * seccomp_bpf in seccomp from ubuntu_kernel_selftests failed to build on B-5.4
+    (LP: #1896420)
+    - SAUCE: selftests/seccomp: fix "storage size of 'md' isn't known" build issue
+    - SAUCE: selftests/seccomp: Fix s390x regs not defined issue
+  * system crash when removing ipmi_msghandler module (LP: #1950666)
+    - ipmi: Move remove_work to dedicated workqueue
+    - ipmi: msghandler: Make symbol 'remove_work_wq' static
+  * zcrypt DD: Toleration for new IBM Z Crypto Hardware - (Backport to Ubuntu
+    20.04) (LP: #1954680)
+    - s390/AP: support new dynamic AP bus size limit
+  * [UBUNTU 20.04] KVM hardware diagnose data improvements for guest kernel -
+    kernel part (LP: #1953334)
+    - s390/setup: diag 318: refactor struct
+    - s390/kvm: diagnose 0x318 sync and reset
+    - KVM: s390: remove diag318 reset code
+    - KVM: s390: add debug statement for diag 318 CPNC data
+  * Updates to ib_peer_memory requested by Nvidia (LP: #1947206)
+    - SAUCE: RDMA/core: Updated ib_peer_memory
+  * Include Infiniband Peer Memory interface (LP: #1923104)
+    - IB: Allow calls to ib_umem_get from kernel ULPs
+    - SAUCE: RDMA/core: Introduce peer memory interface
+  * Focal update: v5.4.162 upstream stable release (LP: #1954834)
+    - arm64: zynqmp: Do not duplicate flash partition label property
+    - arm64: zynqmp: Fix serial compatible string
+    - ARM: dts: NSP: Fix mpcore, mmc node names
+    - scsi: lpfc: Fix list_add() corruption in lpfc_drain_txq()
+    - arm64: dts: hisilicon: fix arm,sp805 compatible string
+    - RDMA/bnxt_re: Check if the vlan is valid before reporting
+    - usb: musb: tusb6010: check return value after calling
+      platform_get_resource()
+    - usb: typec: tipd: Remove WARN_ON in tps6598x_block_read
+    - arm64: dts: qcom: msm8998: Fix CPU/L2 idle state latency and residency
+    - arm64: dts: freescale: fix arm,sp805 compatible string
+    - ASoC: SOF: Intel: hda-dai: fix potential locking issue
+    - clk: imx: imx6ul: Move csi_sel mux to correct base register
+    - ASoC: nau8824: Add DMI quirk mechanism for active-high jack-detect
+    - scsi: advansys: Fix kernel pointer leak
+    - firmware_loader: fix pre-allocated buf built-in firmware use
+    - ARM: dts: omap: fix gpmc,mux-add-data type
+    - usb: host: ohci-tmio: check return value after calling
+      platform_get_resource()
+    - ARM: dts: ls1021a: move thermal-zones node out of soc/
+    - ARM: dts: ls1021a-tsn: use generic "jedec,spi-nor" compatible for flash
+    - ALSA: ISA: not for M68K
+    - tty: tty_buffer: Fix the softlockup issue in flush_to_ldisc
+    - MIPS: sni: Fix the build
+    - scsi: target: Fix ordered tag handling
+    - scsi: target: Fix alua_tg_pt_gps_count tracking
+    - iio: imu: st_lsm6dsx: Avoid potential array overflow in st_lsm6dsx_set_odr()
+    - powerpc/5200: dts: fix memory node unit name
+    - ALSA: gus: fix null pointer dereference on pointer block
+    - powerpc/dcr: Use cmplwi instead of 3-argument cmpli
+    - sh: check return code of request_irq
+    - maple: fix wrong return value of maple_bus_init().
+    - f2fs: fix up f2fs_lookup tracepoints
+    - sh: fix kconfig unmet dependency warning for FRAME_POINTER
+    - sh: math-emu: drop unused functions
+    - sh: define __BIG_ENDIAN for math-emu
+    - clk: ingenic: Fix bugs with divided dividers
+    - clk/ast2600: Fix soc revision for AHB
+    - clk: qcom: gcc-msm8996: Drop (again) gcc_aggre1_pnoc_ahb_clk
+    - mips: BCM63XX: ensure that CPU_SUPPORTS_32BIT_KERNEL is set
+    - sched/core: Mitigate race cpus_share_cache()/update_top_cache_domain()
+    - tracing: Save normal string variables
+    - tracing/histogram: Do not copy the fixed-size char array field over the
+      field size
+    - RDMA/netlink: Add __maybe_unused to static inline in C file
+    - perf bpf: Avoid memory leak from perf_env__insert_btf()
+    - perf bench futex: Fix memory leak of perf_cpu_map__new()
+    - perf tests: Remove bash construct from record+zstd_comp_decomp.sh
+    - net: bnx2x: fix variable dereferenced before check
+    - iavf: check for null in iavf_fix_features
+    - iavf: free q_vectors before queues in iavf_disable_vf
+    - iavf: Fix failure to exit out from last all-multicast mode
+    - iavf: prevent accidental free of filter structure
+    - iavf: validate pointers
+    - iavf: Fix for the false positive ASQ/ARQ errors while issuing VF reset
+    - MIPS: generic/yamon-dt: fix uninitialized variable error
+    - mips: bcm63xx: add support for clk_get_parent()
+    - mips: lantiq: add support for clk_get_parent()
+    - platform/x86: hp_accel: Fix an error handling path in 'lis3lv02d_probe()'
+    - scsi: core: sysfs: Fix hang when device state is set via sysfs
+    - net: sched: act_mirred: drop dst for the direction from egress to ingress
+    - net: dpaa2-eth: fix use-after-free in dpaa2_eth_remove
+    - net: virtio_net_hdr_to_skb: count transport header in UFO
+    - i40e: Fix correct max_pkt_size on VF RX queue
+    - i40e: Fix NULL ptr dereference on VSI filter sync
+    - i40e: Fix changing previously set num_queue_pairs for PFs
+    - i40e: Fix ping is lost after configuring ADq on VF
+    - i40e: Fix creation of first queue by omitting it if is not power of two
+    - i40e: Fix display error code in dmesg
+    - NFC: reorganize the functions in nci_request
+    - drm/nouveau: hdmigv100.c: fix corrupted HDMI Vendor InfoFrame
+    - NFC: reorder the logic in nfc_{un,}register_device
+    - KVM: PPC: Book3S HV: Use GLOBAL_TOC for kvmppc_h_set_dabr/xdabr()
+    - perf/x86/intel/uncore: Fix filter_tid mask for CHA events on Skylake Server
+    - perf/x86/intel/uncore: Fix IIO event constraints for Skylake Server
+    - s390/kexec: fix return code handling
+    - arm64: vdso32: suppress error message for 'make mrproper'
+    - tun: fix bonding active backup with arp monitoring
+    - hexagon: export raw I/O routines for modules
+    - ipc: WARN if trying to remove ipc object which is absent
+    - mm: kmemleak: slob: respect SLAB_NOLEAKTRACE flag
+    - x86/hyperv: Fix NULL deref in set_hv_tscchange_cb() if Hyper-V setup fails
+    - s390/kexec: fix memory leak of ipl report buffer
+    - udf: Fix crash after seekdir
+    - btrfs: fix memory ordering between normal and ordered work functions
+    - parisc/sticon: fix reverse colors
+    - cfg80211: call cfg80211_stop_ap when switch from P2P_GO type
+    - drm/udl: fix control-message timeout
+    - drm/nouveau: use drm_dev_unplug() during device removal
+    - drm/i915/dp: Ensure sink rate values are always valid
+    - drm/amdgpu: fix set scaling mode Full/Full aspect/Center not works on vga
+      and dvi connectors
+    - Revert "net: mvpp2: disable force link UP during port init procedure"
+    - perf/core: Avoid put_page() when GUP fails
+    - batman-adv: Consider fragmentation for needed_headroom
+    - batman-adv: Reserve needed_*room for fragments
+    - batman-adv: Don't always reallocate the fragmentation skb head
+    - ASoC: DAPM: Cover regression by kctl change notification fix
+    - usb: max-3421: Use driver data instead of maintaining a list of bound
+      devices
+    - ice: Delete always true check of PF pointer
+    - ALSA: hda: hdac_ext_stream: fix potential locking issues
+    - ALSA: hda: hdac_stream: fix potential locking issue in
+      snd_hdac_stream_assign()
+    - Linux 5.4.162
+  * Focal update: v5.4.161 upstream stable release (LP: #1954828)
+    - scsi: ufs: Fix interrupt error message for shared interrupts
+    - MIPS: Fix assembly error from MIPSr2 code used within MIPS_ISA_ARCH_LEVEL
+    - ext4: fix lazy initialization next schedule time computation in more
+      granular unit
+    - scsi: ufs: Fix tm request when non-fatal error happens
+    - fortify: Explicitly disable Clang support
+    - parisc/entry: fix trace test in syscall exit path
+    - PCI/MSI: Destroy sysfs before freeing entries
+    - PCI/MSI: Deal with devices lying about their MSI mask capability
+    - PCI: Add MSI masking quirk for Nvidia ION AHCI
+    - erofs: remove the occupied parameter from z_erofs_pagevec_enqueue()
+    - erofs: fix unsafe pagevec reuse of hooked pclusters
+    - Linux 5.4.161
+  * Focal update: v5.4.160 upstream stable release (LP: #1953387)
+    - xhci: Fix USB 3.1 enumeration issues by increasing roothub power-on-good
+      delay
+    - usb: xhci: Enable runtime-pm by default on AMD Yellow Carp platform
+    - binder: use euid from cred instead of using task
+    - binder: use cred instead of task for selinux checks
+    - binder: use cred instead of task for getsecid
+    - Input: iforce - fix control-message timeout
+    - Input: elantench - fix misreporting trackpoint coordinates
+    - Input: i8042 - Add quirk for Fujitsu Lifebook T725
+    - libata: fix read log timeout value
+    - ocfs2: fix data corruption on truncate
+    - scsi: qla2xxx: Fix kernel crash when accessing port_speed sysfs file
+    - scsi: qla2xxx: Fix use after free in eh_abort path
+    - mmc: dw_mmc: Dont wait for DRTO on Write RSP error
+    - parisc: Fix ptrace check on syscall return
+    - tpm: Check for integer overflow in tpm2_map_response_body()
+    - firmware/psci: fix application of sizeof to pointer
+    - crypto: s5p-sss - Add error handling in s5p_aes_probe()
+    - media: ite-cir: IR receiver stop working after receive overflow
+    - media: ir-kbd-i2c: improve responsiveness of hauppauge zilog receivers
+    - media: v4l2-ioctl: Fix check_ext_ctrls
+    - ALSA: hda/realtek: Add quirk for Clevo PC70HS
+    - ALSA: hda/realtek: Add a quirk for Acer Spin SP513-54N
+    - ALSA: hda/realtek: Add quirk for ASUS UX550VE
+    - ALSA: hda/realtek: Add quirk for HP EliteBook 840 G7 mute LED
+    - ALSA: ua101: fix division by zero at probe
+    - ALSA: 6fire: fix control and bulk message timeouts
+    - ALSA: line6: fix control and interrupt message timeouts
+    - ALSA: usb-audio: Add registration quirk for JBL Quantum 400
+    - ALSA: synth: missing check for possible NULL after the call to kstrdup
+    - ALSA: timer: Fix use-after-free problem
+    - ALSA: timer: Unconditionally unlink slave instances, too
+    - fuse: fix page stealing
+    - x86/sme: Use #define USE_EARLY_PGTABLE_L5 in mem_encrypt_identity.c
+    - x86/cpu: Fix migration safety with X86_BUG_NULL_SEL
+    - x86/irq: Ensure PI wakeup handler is unregistered before module unload
+    - cavium: Return negative value when pci_alloc_irq_vectors() fails
+    - scsi: qla2xxx: Return -ENOMEM if kzalloc() fails
+    - scsi: qla2xxx: Fix unmap of already freed sgl
+    - cavium: Fix return values of the probe function
+    - sfc: Don't use netif_info before net_device setup
+    - hyperv/vmbus: include linux/bitops.h
+    - ARM: dts: sun7i: A20-olinuxino-lime2: Fix ethernet phy-mode
+    - reset: socfpga: add empty driver allowing consumers to probe
+    - mmc: winbond: don't build on M68K
+    - drm: panel-orientation-quirks: Add quirk for Aya Neo 2021
+    - bpf: Define bpf_jit_alloc_exec_limit for arm64 JIT
+    - bpf: Prevent increasing bpf_jit_limit above max
+    - xen/netfront: stop tx queues during live migration
+    - nvmet-tcp: fix a memory leak when releasing a queue
+    - spi: spl022: fix Microwire full duplex mode
+    - net: multicast: calculate csum of looped-back and forwarded packets
+    - watchdog: Fix OMAP watchdog early handling
+    - drm: panel-orientation-quirks: Add quirk for GPD Win3
+    - nvmet-tcp: fix header digest verification
+    - r8169: Add device 10ec:8162 to driver r8169
+    - vmxnet3: do not stop tx queues after netif_device_detach()
+    - nfp: bpf: relax prog rejection for mtu check through max_pkt_offset
+    - net/smc: Correct spelling mistake to TCPF_SYN_RECV
+    - btrfs: clear MISSING device status bit in btrfs_close_one_device
+    - btrfs: fix lost error handling when replaying directory deletes
+    - btrfs: call btrfs_check_rw_degradable only if there is a missing device
+    - ia64: kprobes: Fix to pass correct trampoline address to the handler
+    - hwmon: (pmbus/lm25066) Add offset coefficients
+    - regulator: s5m8767: do not use reset value as DVS voltage if GPIO DVS is
+      disabled
+    - regulator: dt-bindings: samsung,s5m8767: correct s5m8767,pmic-buck-default-
+      dvs-idx property
+    - EDAC/sb_edac: Fix top-of-high-memory value for Broadwell/Haswell
+    - mwifiex: fix division by zero in fw download path
+    - ath6kl: fix division by zero in send path
+    - ath6kl: fix control-message timeout
+    - ath10k: fix control-message timeout
+    - ath10k: fix division by zero in send path
+    - PCI: Mark Atheros QCA6174 to avoid bus reset
+    - rtl8187: fix control-message timeouts
+    - evm: mark evm_fixmode as __ro_after_init
+    - wcn36xx: Fix HT40 capability for 2Ghz band
+    - mwifiex: Read a PCI register after writing the TX ring write pointer
+    - libata: fix checking of DMA state
+    - wcn36xx: handle connection loss indication
+    - rsi: fix occasional initialisation failure with BT coex
+    - rsi: fix key enabled check causing unwanted encryption for vap_id > 0
+    - rsi: fix rate mask set leading to P2P failure
+    - rsi: Fix module dev_oper_mode parameter description
+    - RDMA/qedr: Fix NULL deref for query_qp on the GSI QP
+    - signal: Remove the bogus sigkill_pending in ptrace_stop
+    - signal/mips: Update (_save|_restore)_fp_context to fail with -EFAULT
+    - power: supply: max17042_battery: Prevent int underflow in set_soc_threshold
+    - power: supply: max17042_battery: use VFSOC for capacity when no rsns
+    - KVM: nVMX: Query current VMCS when determining if MSR bitmaps are in use
+    - can: j1939: j1939_tp_cmd_recv(): ignore abort message in the BAM transport
+    - can: j1939: j1939_can_recv(): ignore messages with invalid source address
+    - powerpc/85xx: Fix oops when mpc85xx_smp_guts_ids node cannot be found
+    - serial: core: Fix initializing and restoring termios speed
+    - ALSA: mixer: oss: Fix racy access to slots
+    - ALSA: mixer: fix deadlock in snd_mixer_oss_set_volume
+    - xen/balloon: add late_initcall_sync() for initial ballooning done
+    - PCI: pci-bridge-emul: Fix emulation of W1C bits
+    - PCI: aardvark: Do not clear status bits of masked interrupts
+    - PCI: aardvark: Fix checking for link up via LTSSM state
+    - PCI: aardvark: Do not unmask unused interrupts
+    - PCI: aardvark: Fix reporting Data Link Layer Link Active
+    - PCI: aardvark: Fix return value of MSI domain .alloc() method
+    - PCI: aardvark: Read all 16-bits from PCIE_MSI_PAYLOAD_REG
+    - quota: check block number when reading the block in quota file
+    - quota: correct error number in free_dqentry()
+    - pinctrl: core: fix possible memory leak in pinctrl_enable()
+    - iio: dac: ad5446: Fix ad5622_write() return value
+    - USB: serial: keyspan: fix memleak on probe errors
+    - USB: iowarrior: fix control-message timeouts
+    - USB: chipidea: fix interrupt deadlock
+    - dma-buf: WARN on dmabuf release with pending attachments
+    - drm: panel-orientation-quirks: Update the Lenovo Ideapad D330 quirk (v2)
+    - drm: panel-orientation-quirks: Add quirk for KD Kurio Smart C15200 2-in-1
+    - drm: panel-orientation-quirks: Add quirk for the Samsung Galaxy Book 10.6
+    - Bluetooth: sco: Fix lock_sock() blockage by memcpy_from_msg()
+    - Bluetooth: fix use-after-free error in lock_sock_nested()
+    - drm/panel-orientation-quirks: add Valve Steam Deck
+    - platform/x86: wmi: do not fail if disabling fails
+    - MIPS: lantiq: dma: add small delay after reset
+    - MIPS: lantiq: dma: reset correct number of channel
+    - locking/lockdep: Avoid RCU-induced noinstr fail
+    - net: sched: update default qdisc visibility after Tx queue cnt changes
+    - smackfs: Fix use-after-free in netlbl_catmap_walk()
+    - x86: Increase exception stack sizes
+    - mwifiex: Run SET_BSS_MODE when changing from P2P to STATION vif-type
+    - mwifiex: Properly initialize private structure on interface type changes
+    - ath10k: high latency fixes for beacon buffer
+    - media: mt9p031: Fix corrupted frame after restarting stream
+    - media: netup_unidvb: handle interrupt properly according to the firmware
+    - media: stm32: Potential NULL pointer dereference in dcmi_irq_thread()
+    - media: uvcvideo: Set capability in s_param
+    - media: uvcvideo: Return -EIO for control errors
+    - media: uvcvideo: Set unique vdev name based in type
+    - media: s5p-mfc: fix possible null-pointer dereference in s5p_mfc_probe()
+    - media: s5p-mfc: Add checking to s5p_mfc_probe().
+    - media: imx: set a media_device bus_info string
+    - media: mceusb: return without resubmitting URB in case of -EPROTO error.
+    - ia64: don't do IA64_CMPXCHG_DEBUG without CONFIG_PRINTK
+    - brcmfmac: Add DMI nvram filename quirk for Cyberbook T116 tablet
+    - media: rcar-csi2: Add checking to rcsi2_start_receiver()
+    - ipmi: Disable some operations during a panic
+    - ACPICA: Avoid evaluating methods too early during system resume
+    - media: ipu3-imgu: imgu_fmt: Handle properly try
+    - media: ipu3-imgu: VIDIOC_QUERYCAP: Fix bus_info
+    - media: usb: dvd-usb: fix uninit-value bug in dibusb_read_eeprom_byte()
+    - net-sysfs: try not to restart the syscall if it will fail eventually
+    - tracefs: Have tracefs directories not set OTH permission bits by default
+    - ath: dfs_pattern_detector: Fix possible null-pointer dereference in
+      channel_detector_create()
+    - iov_iter: Fix iov_iter_get_pages{,_alloc} page fault return value
+    - ACPI: battery: Accept charges over the design capacity as full
+    - leaking_addresses: Always print a trailing newline
+    - memstick: r592: Fix a UAF bug when removing the driver
+    - lib/xz: Avoid overlapping memcpy() with invalid input with in-place
+      decompression
+    - lib/xz: Validate the value before assigning it to an enum variable
+    - workqueue: make sysfs of unbound kworker cpumask more clever
+    - tracing/cfi: Fix cmp_entries_* functions signature mismatch
+    - mwl8k: Fix use-after-free in mwl8k_fw_state_machine()
+    - block: remove inaccurate requeue check
+    - nvmet: fix use-after-free when a port is removed
+    - nvmet-tcp: fix use-after-free when a port is removed
+    - nvme: drop scan_lock and always kick requeue list when removing namespaces
+    - PM: hibernate: Get block device exclusively in swsusp_check()
+    - selftests: kvm: fix mismatched fclose() after popen()
+    - iwlwifi: mvm: disable RX-diversity in powersave
+    - smackfs: use __GFP_NOFAIL for smk_cipso_doi()
+    - ARM: clang: Do not rely on lr register for stacktrace
+    - gre/sit: Don't generate link-local addr if addr_gen_mode is
+      IN6_ADDR_GEN_MODE_NONE
+    - ARM: 9136/1: ARMv7-M uses BE-8, not BE-32
+    - vrf: run conntrack only in context of lower/physdev for locally generated
+      packets
+    - net: annotate data-race in neigh_output()
+    - btrfs: do not take the uuid_mutex in btrfs_rm_device
+    - spi: bcm-qspi: Fix missing clk_disable_unprepare() on error in
+      bcm_qspi_probe()
+    - x86/hyperv: Protect set_hv_tscchange_cb() against getting preempted
+    - parisc: fix warning in flush_tlb_all
+    - task_stack: Fix end_of_stack() for architectures with upwards-growing stack
+    - parisc/unwind: fix unwinder when CONFIG_64BIT is enabled
+    - parisc/kgdb: add kgdb_roundup() to make kgdb work with idle polling
+    - netfilter: conntrack: set on IPS_ASSURED if flows enters internal stream
+      state
+    - selftests/bpf: Fix strobemeta selftest regression
+    - Bluetooth: fix init and cleanup of sco_conn.timeout_work
+    - rcu: Fix existing exp request check in sync_sched_exp_online_cleanup()
+    - drm/v3d: fix wait for TMU write combiner flush
+    - virtio-gpu: fix possible memory allocation failure
+    - net: net_namespace: Fix undefined member in key_remove_domain()
+    - cgroup: Make rebind_subsystems() disable v2 controllers all at once
+    - wilc1000: fix possible memory leak in cfg_scan_result()
+    - Bluetooth: btmtkuart: fix a memleak in mtk_hci_wmt_sync
+    - crypto: caam - disable pkc for non-E SoCs
+    - rxrpc: Fix _usecs_to_jiffies() by using usecs_to_jiffies()
+    - net: dsa: rtl8366rb: Fix off-by-one bug
+    - ath10k: Fix missing frame timestamp for beacon/probe-resp
+    - drm/amdgpu: fix warning for overflow check
+    - media: em28xx: add missing em28xx_close_extension
+    - media: cxd2880-spi: Fix a null pointer dereference on error handling path
+    - media: dvb-usb: fix ununit-value in az6027_rc_query
+    - media: TDA1997x: handle short reads of hdmi info frame.
+    - media: mtk-vpu: Fix a resource leak in the error handling path of
+      'mtk_vpu_probe()'
+    - media: radio-wl1273: Avoid card name truncation
+    - media: si470x: Avoid card name truncation
+    - media: tm6000: Avoid card name truncation
+    - media: cx23885: Fix snd_card_free call on null card pointer
+    - kprobes: Do not use local variable when creating debugfs file
+    - crypto: ecc - fix CRYPTO_DEFAULT_RNG dependency
+    - cpuidle: Fix kobject memory leaks in error paths
+    - media: em28xx: Don't use ops->suspend if it is NULL
+    - ath9k: Fix potential interrupt storm on queue reset
+    - EDAC/amd64: Handle three rank interleaving mode
+    - netfilter: nft_dynset: relax superfluous check on set updates
+    - media: dvb-frontends: mn88443x: Handle errors of clk_prepare_enable()
+    - crypto: qat - detect PFVF collision after ACK
+    - crypto: qat - disregard spurious PFVF interrupts
+    - hwrng: mtk - Force runtime pm ops for sleep ops
+    - b43legacy: fix a lower bounds test
+    - b43: fix a lower bounds test
+    - mmc: sdhci-omap: Fix NULL pointer exception if regulator is not configured
+    - memstick: avoid out-of-range warning
+    - memstick: jmb38x_ms: use appropriate free function in jmb38x_ms_alloc_host()
+    - net, neigh: Fix NTF_EXT_LEARNED in combination with NTF_USE
+    - hwmon: Fix possible memleak in __hwmon_device_register()
+    - hwmon: (pmbus/lm25066) Let compiler determine outer dimension of
+      lm25066_coeff
+    - ath10k: fix max antenna gain unit
+    - drm/msm: uninitialized variable in msm_gem_import()
+    - net: stream: don't purge sk_error_queue in sk_stream_kill_queues()
+    - mmc: mxs-mmc: disable regulator on error and in the remove function
+    - block: ataflop: fix breakage introduced at blk-mq refactoring
+    - platform/x86: thinkpad_acpi: Fix bitwise vs. logical warning
+    - mt76: mt76x02: fix endianness warnings in mt76x02_mac.c
+    - rsi: stop thread firstly in rsi_91x_init() error handling
+    - mwifiex: Send DELBA requests according to spec
+    - phy: micrel: ksz8041nl: do not use power down mode
+    - nvme-rdma: fix error code in nvme_rdma_setup_ctrl
+    - PM: hibernate: fix sparse warnings
+    - clocksource/drivers/timer-ti-dm: Select TIMER_OF
+    - drm/msm: Fix potential NULL dereference in DPU SSPP
+    - smackfs: use netlbl_cfg_cipsov4_del() for deleting cipso_v4_doi
+    - libbpf: Fix BTF data layout checks and allow empty BTF
+    - s390/gmap: don't unconditionally call pte_unmap_unlock() in __gmap_zap()
+    - irq: mips: avoid nested irq_enter()
+    - tcp: don't free a FIN sk_buff in tcp_remove_empty_skb()
+    - samples/kretprobes: Fix return value if register_kretprobe() failed
+    - KVM: s390: Fix handle_sske page fault handling
+    - libertas_tf: Fix possible memory leak in probe and disconnect
+    - libertas: Fix possible memory leak in probe and disconnect
+    - wcn36xx: add proper DMA memory barriers in rx path
+    - drm/amdgpu/gmc6: fix DMA mask from 44 to 40 bits
+    - net: amd-xgbe: Toggle PLL settings during rate change
+    - net: phylink: avoid mvneta warning when setting pause parameters
+    - crypto: pcrypt - Delay write to padata->info
+    - selftests/bpf: Fix fclose/pclose mismatch in test_progs
+    - udp6: allow SO_MARK ctrl msg to affect routing
+    - ibmvnic: don't stop queue in xmit
+    - ibmvnic: Process crqs after enabling interrupts
+    - RDMA/rxe: Fix wrong port_cap_flags
+    - clk: mvebu: ap-cpu-clk: Fix a memory leak in error handling paths
+    - ARM: s3c: irq-s3c24xx: Fix return value check for s3c24xx_init_intc()
+    - arm64: dts: rockchip: Fix GPU register width for RK3328
+    - ARM: dts: qcom: msm8974: Add xo_board reference clock to DSI0 PHY
+    - RDMA/bnxt_re: Fix query SRQ failure
+    - arm64: dts: meson-g12a: Fix the pwm regulator supply properties
+    - ARM: dts: at91: tse850: the emac<->phy interface is rmii
+    - scsi: dc395: Fix error case unwinding
+    - MIPS: loongson64: make CPU_LOONGSON64 depends on MIPS_FP_SUPPORT
+    - JFS: fix memleak in jfs_mount
+    - ALSA: hda: Reduce udelay() at SKL+ position reporting
+    - arm: dts: omap3-gta04a4: accelerometer irq fix
+    - soc/tegra: Fix an error handling path in tegra_powergate_power_up()
+    - memory: fsl_ifc: fix leak of irq and nand_irq in fsl_ifc_ctrl_probe
+    - clk: at91: check pmc node status before registering syscore ops
+    - video: fbdev: chipsfb: use memset_io() instead of memset()
+    - serial: 8250_dw: Drop wrong use of ACPI_PTR()
+    - usb: gadget: hid: fix error code in do_config()
+    - power: supply: rt5033_battery: Change voltage values to µV
+    - scsi: csiostor: Uninitialized data in csio_ln_vnp_read_cbfn()
+    - RDMA/mlx4: Return missed an error if device doesn't support steering
+    - staging: ks7010: select CRYPTO_HASH/CRYPTO_MICHAEL_MIC
+    - ARM: dts: stm32: fix SAI sub nodes register range
+    - ASoC: cs42l42: Correct some register default values
+    - ASoC: cs42l42: Defer probe if request_threaded_irq() returns EPROBE_DEFER
+    - phy: qcom-qusb2: Fix a memory leak on probe
+    - serial: xilinx_uartps: Fix race condition causing stuck TX
+    - HID: u2fzero: clarify error check and length calculations
+    - HID: u2fzero: properly handle timeouts in usb_submit_urb
+    - powerpc/44x/fsp2: add missing of_node_put
+    - mips: cm: Convert to bitfield API to fix out-of-bounds access
+    - power: supply: bq27xxx: Fix kernel crash on IRQ handler register error
+    - apparmor: fix error check
+    - rpmsg: Fix rpmsg_create_ept return when RPMSG config is not defined
+    - pnfs/flexfiles: Fix misplaced barrier in nfs4_ff_layout_prepare_ds
+    - drm/plane-helper: fix uninitialized variable reference
+    - PCI: aardvark: Don't spam about PIO Response Status
+    - PCI: aardvark: Fix preserving PCI_EXP_RTCTL_CRSSVE flag on emulated bridge
+    - opp: Fix return in _opp_add_static_v2()
+    - NFS: Fix deadlocks in nfs_scan_commit_list()
+    - fs: orangefs: fix error return code of orangefs_revalidate_lookup()
+    - mtd: spi-nor: hisi-sfc: Remove excessive clk_disable_unprepare()
+    - mtd: core: don't remove debugfs directory if device is in use
+    - dmaengine: at_xdmac: fix AT_XDMAC_CC_PERID() macro
+    - auxdisplay: img-ascii-lcd: Fix lock-up when displaying empty string
+    - auxdisplay: ht16k33: Connect backlight to fbdev
+    - auxdisplay: ht16k33: Fix frame buffer device blanking
+    - soc: fsl: dpaa2-console: free buffer before returning from
+      dpaa2_console_read
+    - netfilter: nfnetlink_queue: fix OOB when mac header was cleared
+    - dmaengine: dmaengine_desc_callback_valid(): Check for `callback_result`
+    - signal/sh: Use force_sig(SIGKILL) instead of do_group_exit(SIGKILL)
+    - m68k: set a default value for MEMORY_RESERVE
+    - watchdog: f71808e_wdt: fix inaccurate report in WDIOC_GETTIMEOUT
+    - ar7: fix kernel builds for compiler test
+    - scsi: qla2xxx: Fix gnl list corruption
+    - scsi: qla2xxx: Turn off target reset during issue_lip
+    - NFSv4: Fix a regression in nfs_set_open_stateid_locked()
+    - i2c: xlr: Fix a resource leak in the error handling path of
+      'xlr_i2c_probe()'
+    - xen-pciback: Fix return in pm_ctrl_init()
+    - net: davinci_emac: Fix interrupt pacing disable
+    - net: vlan: fix a UAF in vlan_dev_real_dev()
+    - ACPI: PMIC: Fix intel_pmic_regs_handler() read accesses
+    - bonding: Fix a use-after-free problem when bond_sysfs_slave_add() failed
+    - mm/zsmalloc.c: close race window between zs_pool_dec_isolated() and
+      zs_unregister_migration()
+    - zram: off by one in read_block_state()
+    - perf bpf: Add missing free to bpf_event__print_bpf_prog_info()
+    - llc: fix out-of-bound array index in llc_sk_dev_hash()
+    - nfc: pn533: Fix double free when pn533_fill_fragment_skbs() fails
+    - arm64: pgtable: make __pte_to_phys/__phys_to_pte_val inline functions
+    - bpf: sockmap, strparser, and tls are reusing qdisc_skb_cb and colliding
+    - net/sched: sch_taprio: fix undefined behavior in ktime_mono_to_any
+    - net: hns3: allow configure ETS bandwidth of all TCs
+    - vsock: prevent unnecessary refcnt inc for nonblocking connect
+    - net/smc: fix sk_refcnt underflow on linkdown and fallback
+    - cxgb4: fix eeprom len when diagnostics not implemented
+    - selftests/net: udpgso_bench_rx: fix port argument
+    - ARM: 9155/1: fix early early_iounmap()
+    - ARM: 9156/1: drop cc-option fallbacks for architecture selection
+    - parisc: Fix set_fixmap() on PA1.x CPUs
+    - irqchip/sifive-plic: Fixup EOI failed when masked
+    - f2fs: should use GFP_NOFS for directory inodes
+    - net, neigh: Enable state migration between NUD_PERMANENT and NTF_USE
+    - 9p/net: fix missing error check in p9_check_errors
+    - ovl: fix deadlock in splice write
+    - powerpc/lib: Add helper to check if offset is within conditional branch
+      range
+    - powerpc/bpf: Validate branch ranges
+    - powerpc/bpf: Fix BPF_SUB when imm == 0x80000000
+    - powerpc/security: Add a helper to query stf_barrier type
+    - powerpc/bpf: Emit stf barrier instruction sequences for BPF_NOSPEC
+    - mm, oom: pagefault_out_of_memory: don't force global OOM for dying tasks
+    - mm, oom: do not trigger out_of_memory from the #PF
+    - video: backlight: Drop maximum brightness override for brightness zero
+    - s390/cio: check the subchannel validity for dev_busid
+    - s390/tape: fix timer initialization in tape_std_assign()
+    - s390/cio: make ccw_device_dma_* more robust
+    - powerpc/powernv/prd: Unregister OPAL_MSG_PRD2 notifier during module unload
+    - PCI: Add PCI_EXP_DEVCTL_PAYLOAD_* macros
+    - SUNRPC: Partial revert of commit 6f9f17287e78
+    - ath10k: fix invalid dma_addr_t token assignment
+    - selftests/bpf: Fix also no-alu32 strobemeta selftest
+    - Linux 5.4.160
+    - soc/tegra: pmc: Fix imbalanced clock disabling in error code path
+  * Focal update: v5.4.159 upstream stable release (LP: #1953071)
+    - Revert "x86/kvm: fix vcpu-id indexed array sizes"
+    - usb: ehci: handshake CMD_RUN instead of STS_HALT
+    - usb: gadget: Mark USB_FSL_QE broken on 64-bit
+    - usb: musb: Balance list entry in musb_gadget_queue
+    - usb-storage: Add compatibility quirk flags for iODD 2531/2541
+    - binder: don't detect sender/target during buffer cleanup
+    - printk/console: Allow to disable console output by using console="" or
+      console=null
+    - isofs: Fix out of bound access for corrupted isofs image
+    - comedi: dt9812: fix DMA buffers on stack
+    - comedi: ni_usb6501: fix NULL-deref in command paths
+    - comedi: vmk80xx: fix transfer-buffer overflows
+    - comedi: vmk80xx: fix bulk-buffer overflow
+    - comedi: vmk80xx: fix bulk and interrupt message timeouts
+    - staging: r8712u: fix control-message timeout
+    - staging: rtl8192u: fix control-message timeouts
+    - media: staging/intel-ipu3: css: Fix wrong size comparison imgu_css_fw_init
+    - rsi: fix control-message timeout
+    - Linux 5.4.159
+  * Focal update: v5.4.158 upstream stable release (LP: #1953066)
+    - scsi: core: Put LLD module refcnt after SCSI device is released
+    - vrf: Revert "Reset skb conntrack connection..."
+    - net: ethernet: microchip: lan743x: Fix skb allocation failure
+    - media: firewire: firedtv-avc: fix a buffer overflow in avc_ca_pmt()
+    - Revert "xhci: Set HCD flag to defer primary roothub registration"
+    - Revert "usb: core: hcd: Add support for deferring roothub registration"
+    - sfc: Fix reading non-legacy supported link modes
+    - ARM: 9120/1: Revert "amba: make use of -1 IRQs warn"
+    - Linux 5.4.158
+  * [Ubuntu 20.04] Problem leading IUCV service down (on s390x) (LP: #1913442)
+    - usercopy: mark dma-kmalloc caches as usercopy caches
+
+  [ Ubuntu: 5.4.0-96.109 ]
+
+  * Support builtin revoked certificates (LP: #1932029)
+    - [Config]: add i386 to CONFIG_SYSTEM_REVOCATION_KEYS annotation
+  * CVE-2022-0185
+    - SAUCE: vfs: Out-of-bounds write of heap buffer in fs_context.c
+    - SAUCE: vfs: test that one given mount param is not larger than PAGE_SIZE
+
+  [ Ubuntu: 5.4.0-94.106 ]
+
+  * focal/linux: 5.4.0-94.106 -proposed tracker (LP: #1956628)
+  * [Regression] Focal kernel  5.4.0-92.103 fails to boot when Secure Encrypted
+    Virtualization(SEV) is enabled (LP: #1956575)
+    - x86/ioremap: Map EFI-reserved memory as encrypted for SEV
+
+  [ Ubuntu: 5.4.0-92.103 ]
+
+  * focal/linux: 5.4.0-92.103 -proposed tracker (LP: #1952316)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync update-dkms-versions helper
+    - debian/dkms-versions -- update from kernel-versions (main/2021.11.29)
+  * CVE-2021-4002
+    - tlb: mmu_gather: add tlb_flush_*_range APIs
+    - hugetlbfs: flush TLBs correctly after huge_pmd_unshare
+  * Re-enable DEBUG_INFO_BTF where it was disabled (LP: #1945632)
+    - [Config] Enable CONFIG_DEBUG_INFO_BTF on all arches
+  * Focal linux-azure: Vm crash on Dv5/Ev5 (LP: #1950462)
+    - KVM: VMX: eVMCS: make evmcs_sanitize_exec_ctrls() work again
+    - jump_label: Fix usage in module __init
+  * Support builtin revoked certificates (LP: #1932029)
+    - Revert "UBUNTU: SAUCE: (lockdown) Make get_cert_list() not complain about
+      cert lists that aren't present."
+    - integrity: Move import of MokListRT certs to a separate routine
+    - integrity: Load certs from the EFI MOK config table
+    - certs: Add ability to preload revocation certs
+    - integrity: Load mokx variables into the blacklist keyring
+    - certs: add 'x509_revocation_list' to gitignore
+    - SAUCE: Dump stack when X.509 certificates cannot be loaded
+    - [Packaging] build canonical-revoked-certs.pem from branch/arch certs
+    - [Packaging] Revoke 2012 UEFI signing certificate as built-in
+    - [Config] Configure CONFIG_SYSTEM_REVOCATION_KEYS with revoked keys
+  * Support importing mokx keys into revocation list from the mok table
+    (LP: #1928679)
+    - efi: Support for MOK variable config table
+    - efi: mokvar-table: fix some issues in new code
+    - efi: mokvar: add missing include of asm/early_ioremap.h
+    - efi/mokvar: Reserve the table only if it is in boot services data
+    - SAUCE: integrity: add informational messages when revoking certs
+  * Support importing mokx keys into revocation list from the mok table
+    (LP: #1928679) // CVE-2020-26541 when certificates are revoked via
+    MokListXRT.
+    - SAUCE: integrity: Load mokx certs from the EFI MOK config table
+  * Focal update: v5.4.157 upstream stable release (LP: #1951883)
+    - ARM: 9133/1: mm: proc-macros: ensure *_tlb_fns are 4B aligned
+    - ARM: 9134/1: remove duplicate memcpy() definition
+    - ARM: 9139/1: kprobes: fix arch_init_kprobes() prototype
+    - ARM: 9141/1: only warn about XIP address when not compile testing
+    - ipv6: use siphash in rt6_exception_hash()
+    - ipv4: use siphash instead of Jenkins in fnhe_hashfun()
+    - usbnet: sanity check for maxpacket
+    - usbnet: fix error return code in usbnet_probe()
+    - Revert "pinctrl: bcm: ns: support updated DT binding as syscon subnode"
+    - ata: sata_mv: Fix the error handling of mv_chip_id()
+    - nfc: port100: fix using -ERRNO as command type mask
+    - net/tls: Fix flipped sign in tls_err_abort() calls
+    - mmc: vub300: fix control-message timeouts
+    - mmc: cqhci: clear HALT state after CQE enable
+    - mmc: dw_mmc: exynos: fix the finding clock sample value
+    - mmc: sdhci: Map more voltage level to SDHCI_POWER_330
+    - mmc: sdhci-esdhc-imx: clear the buffer_read_ready to reset standard tuning
+      circuit
+    - cfg80211: scan: fix RCU in cfg80211_add_nontrans_list()
+    - net: lan78xx: fix division by zero in send path
+    - tcp_bpf: Fix one concurrency problem in the tcp_bpf_send_verdict function
+    - IB/qib: Protect from buffer overflow in struct qib_user_sdma_pkt fields
+    - IB/hfi1: Fix abba locking issue with sc_disable()
+    - nvmet-tcp: fix data digest pointer calculation
+    - nvme-tcp: fix data digest pointer calculation
+    - RDMA/mlx5: Set user priority for DCT
+    - arm64: dts: allwinner: h5: NanoPI Neo 2: Fix ethernet node
+    - regmap: Fix possible double-free in regcache_rbtree_exit()
+    - net: batman-adv: fix error handling
+    - net: Prevent infinite while loop in skb_tx_hash()
+    - RDMA/sa_query: Use strscpy_pad instead of memcpy to copy a string
+    - nios2: Make NIOS2_DTB_SOURCE_BOOL depend on !COMPILE_TEST
+    - net: ethernet: microchip: lan743x: Fix driver crash when lan743x_pm_resume
+      fails
+    - net: ethernet: microchip: lan743x: Fix dma allocation failure by using
+      dma_set_mask_and_coherent
+    - net: nxp: lpc_eth.c: avoid hang when bringing interface down
+    - net/tls: Fix flipped sign in async_wait.err assignment
+    - phy: phy_ethtool_ksettings_get: Lock the phy for consistency
+    - phy: phy_start_aneg: Add an unlocked version
+    - sctp: use init_tag from inithdr for ABORT chunk
+    - sctp: fix the processing for INIT_ACK chunk
+    - sctp: fix the processing for COOKIE_ECHO chunk
+    - sctp: add vtag check in sctp_sf_violation
+    - sctp: add vtag check in sctp_sf_do_8_5_1_E_sa
+    - sctp: add vtag check in sctp_sf_ootb
+    - net: use netif_is_bridge_port() to check for IFF_BRIDGE_PORT
+    - cfg80211: correct bridge/4addr mode check
+    - KVM: s390: clear kicked_mask before sleeping again
+    - KVM: s390: preserve deliverable_mask in __airqs_kick_single_vcpu
+    - perf script: Check session->header.env.arch before using it
+    - Linux 5.4.157
+  * keyboard not working on Medion notebook s17 series (LP: #1950536)
+    - ACPI: resources: Add one more Medion model in IRQ override quirk
+  * creat09 from ubuntu_ltp_syscalls and cve-2018-13405 from ubuntu_ltp/cve
+    failed with XFS (LP: #1950239)
+    - xfs: ensure that the inode uid/gid match values match the icdinode ones
+    - xfs: merge the projid fields in struct xfs_icdinode
+    - xfs: remove the icdinode di_uid/di_gid members
+    - xfs: fix up non-directory creation in SGID directories
+  * reuseport_bpf_numa in net from ubuntu_kernel_selftests fails on ppc64le
+    (LP: #1867570)
+    - selftests/net: Fix reuseport_bpf_numa by skipping unavailable nodes
+  * Focal update: v5.4.156 upstream stable release (LP: #1951295)
+    - parisc: math-emu: Fix fall-through warnings
+    - net: switchdev: do not propagate bridge updates across bridges
+    - tee: optee: Fix missing devices unregister during optee_remove
+    - ARM: dts: at91: sama5d2_som1_ek: disable ISC node by default
+    - xtensa: xtfpga: use CONFIG_USE_OF instead of CONFIG_OF
+    - xtensa: xtfpga: Try software restart before simulating CPU reset
+    - NFSD: Keep existing listeners on portlist error
+    - dma-debug: fix sg checks in debug_dma_map_sg()
+    - ASoC: wm8960: Fix clock configuration on slave mode
+    - netfilter: ipvs: make global sysctl readonly in non-init netns
+    - lan78xx: select CRC32
+    - net: dsa: lantiq_gswip: fix register definition
+    - NIOS2: irqflags: rename a redefined register name
+    - net: hns3: reset DWRR of unused tc to zero
+    - net: hns3: add limit ets dwrr bandwidth cannot be 0
+    - net: hns3: disable sriov before unload hclge layer
+    - net: stmmac: Fix E2E delay mechanism
+    - net: enetc: fix ethtool counter name for PM0_TERR
+    - can: rcar_can: fix suspend/resume
+    - can: peak_usb: pcan_usb_fd_decode_status(): fix back to ERROR_ACTIVE state
+      notification
+    - can: peak_pci: peak_pci_remove(): fix UAF
+    - can: j1939: j1939_tp_rxtimer(): fix errant alert in j1939_tp_rxtimer
+    - can: j1939: j1939_netdev_start(): fix UAF for rx_kref of j1939_priv
+    - can: j1939: j1939_xtp_rx_dat_one(): cancel session if receive TP.DT with
+      error length
+    - can: j1939: j1939_xtp_rx_rts_session_new(): abort TP less than 9 bytes
+    - ceph: fix handling of "meta" errors
+    - ocfs2: fix data corruption after conversion from inline format
+    - ocfs2: mount fails with buffer overflow in strlen
+    - elfcore: correct reference to CONFIG_UML
+    - ALSA: usb-audio: Provide quirk for Sennheiser GSP670 Headset
+    - ALSA: hda/realtek: Add quirk for Clevo PC50HS
+    - ASoC: DAPM: Fix missing kctl change notifications
+    - audit: fix possible null-pointer dereference in audit_filter_rules
+    - powerpc64/idle: Fix SP offsets when saving GPRs
+    - KVM: PPC: Book3S HV: Fix stack handling in idle_kvm_start_guest()
+    - KVM: PPC: Book3S HV: Make idle_kvm_start_guest() return 0 if it went to
+      guest
+    - powerpc/idle: Don't corrupt back chain when going idle
+    - mm, slub: fix mismatch between reconstructed freelist depth and cnt
+    - mm, slub: fix potential memoryleak in kmem_cache_open()
+    - nfc: nci: fix the UAF of rf_conn_info object
+    - isdn: cpai: check ctr->cnr to avoid array index out of bound
+    - netfilter: Kconfig: use 'default y' instead of 'm' for bool config option
+    - selftests: netfilter: remove stray bash debug line
+    - gcc-plugins/structleak: add makefile var for disabling structleak
+    - btrfs: deal with errors when checking if a dir entry exists during log
+      replay
+    - net: stmmac: add support for dwmac 3.40a
+    - ARM: dts: spear3xx: Fix gmac node
+    - isdn: mISDN: Fix sleeping function called from invalid context
+    - platform/x86: intel_scu_ipc: Update timeout value in comment
+    - ALSA: hda: avoid write to STATESTS if controller is in reset
+    - Input: snvs_pwrkey - add clk handling
+    - scsi: core: Fix shost->cmd_per_lun calculation in scsi_add_host_with_dma()
+    - tracing: Have all levels of checks prevent recursion
+    - ARM: 9122/1: select HAVE_FUTEX_CMPXCHG
+    - pinctrl: stm32: use valid pin identifier in stm32_pinctrl_resume()
+    - Linux 5.4.156
+  * ubuntu_ltp / finit_module02 fails on v4.15 and other kernels
+    (LP: #1950644) // Focal update: v5.4.156 upstream stable release
+    (LP: #1951295)
+    - vfs: check fd has read access in kernel_read_file_from_fd()
+  * Focal update: v5.4.155 upstream stable release (LP: #1951291)
+    - ovl: simplify file splice
+    - ALSA: usb-audio: Add quirk for VF0770
+    - ALSA: seq: Fix a potential UAF by wrong private_free call order
+    - ALSA: hda/realtek: Complete partial device name to avoid ambiguity
+    - ALSA: hda/realtek: Add quirk for Clevo X170KM-G
+    - ALSA: hda/realtek - ALC236 headset MIC recording issue
+    - ALSA: hda/realtek: Fix the mic type detection issue for ASUS G551JW
+    - nds32/ftrace: Fix Error: invalid operands (*UND* and *UND* sections) for `^'
+    - s390: fix strrchr() implementation
+    - csky: don't let sigreturn play with priveleged bits of status register
+    - csky: Fixup regs.sr broken in ptrace
+    - btrfs: unlock newly allocated extent buffer after error
+    - btrfs: deal with errors when replaying dir entry during log replay
+    - btrfs: deal with errors when adding inode reference during log replay
+    - btrfs: check for error when looking up inode during dir entry replay
+    - watchdog: orion: use 0 for unset heartbeat
+    - x86/resctrl: Free the ctrlval arrays when domain_setup_mon_state() fails
+    - mei: me: add Ice Lake-N device id.
+    - xhci: guard accesses to ep_state in xhci_endpoint_reset()
+    - xhci: Fix command ring pointer corruption while aborting a command
+    - xhci: Enable trust tx length quirk for Fresco FL11 USB controller
+    - cb710: avoid NULL pointer subtraction
+    - efi/cper: use stack buffer for error record decoding
+    - efi: Change down_interruptible() in virt_efi_reset_system() to
+      down_trylock()
+    - usb: musb: dsps: Fix the probe error path
+    - Input: xpad - add support for another USB ID of Nacon GC-100
+    - USB: serial: qcserial: add EM9191 QDL support
+    - USB: serial: option: add Quectel EC200S-CN module support
+    - USB: serial: option: add Telit LE910Cx composition 0x1204
+    - USB: serial: option: add prod. id for Quectel EG91
+    - EDAC/armada-xp: Fix output of uncorrectable error counter
+    - nvmem: Fix shift-out-of-bound (UBSAN) with byte size cells
+    - x86/Kconfig: Do not enable AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT automatically
+    - powerpc/xive: Discard disabled interrupts in get_irqchip_state()
+    - iio: adc: aspeed: set driver data when adc probe.
+    - iio: adc128s052: Fix the error handling path of 'adc128_probe()'
+    - iio: mtk-auxadc: fix case IIO_CHAN_INFO_PROCESSED
+    - iio: light: opt3001: Fixed timeout error when 0 lux
+    - iio: ssp_sensors: add more range checking in ssp_parse_dataframe()
+    - iio: ssp_sensors: fix error code in ssp_print_mcu_debug()
+    - iio: dac: ti-dac5571: fix an error code in probe()
+    - sctp: account stream padding length for reconf chunk
+    - gpio: pca953x: Improve bias setting
+    - net: arc: select CRC32
+    - net: korina: select CRC32
+    - net/mlx5e: Mutually exclude RX-FCS and RX-port-timestamp
+    - net: stmmac: fix get_hw_feature() on old hardware
+    - net: encx24j600: check error in devm_regmap_init_encx24j600
+    - ethernet: s2io: fix setting mac address during resume
+    - nfc: fix error handling of nfc_proto_register()
+    - NFC: digital: fix possible memory leak in digital_tg_listen_mdaa()
+    - NFC: digital: fix possible memory leak in digital_in_send_sdd_req()
+    - pata_legacy: fix a couple uninitialized variable bugs
+    - ata: ahci_platform: fix null-ptr-deref in ahci_platform_enable_regulators()
+    - mlxsw: thermal: Fix out-of-bounds memory accesses
+    - platform/mellanox: mlxreg-io: Fix argument base in kstrtou32() call
+    - drm/panel: olimex-lcd-olinuxino: select CRC32
+    - drm/msm: Fix null pointer dereference on pointer edp
+    - drm/msm/dsi: Fix an error code in msm_dsi_modeset_init()
+    - drm/msm/dsi: fix off by one in dsi_bus_clk_enable error handling
+    - acpi/arm64: fix next_platform_timer() section mismatch error
+    - mqprio: Correct stats in mqprio_dump_class_stats().
+    - qed: Fix missing error code in qed_slowpath_start()
+    - r8152: select CRC32 and CRYPTO/CRYPTO_HASH/CRYPTO_SHA256
+    - ionic: don't remove netdev->dev_addr when syncing uc list
+    - Linux 5.4.155
+  * [UBUNTU 20.04] kernel:  unable to read partitions on virtio-block dasd (kvm)
+    (LP: #1950144) // Focal update: v5.4.155 upstream stable release
+    (LP: #1951291)
+    - virtio: write back F_VERSION_1 before validate
+  * Focal update: v5.4.154 upstream stable release (LP: #1951288)
+    - net: phy: bcm7xxx: Fixed indirect MMD operations
+    - ext4: correct the error path of ext4_write_inline_data_end()
+    - HID: apple: Fix logical maximum and usage maximum of Magic Keyboard JIS
+    - netfilter: ip6_tables: zero-initialize fragment offset
+    - HID: wacom: Add new Intuos BT (CTL-4100WL/CTL-6100WL) device IDs
+    - netfilter: nf_nat_masquerade: make async masq_inet6_event handling generic
+    - netfilter: nf_nat_masquerade: defer conntrack walk to work queue
+    - mac80211: Drop frames from invalid MAC address in ad-hoc mode
+    - m68k: Handle arrivals of multiple signals correctly
+    - net: prevent user from passing illegal stab size
+    - mac80211: check return value of rhashtable_init
+    - net: sun: SUNVNET_COMMON should depend on INET
+    - drm/amdgpu: fix gart.bo pin_count leak
+    - scsi: ses: Fix unsigned comparison with less than zero
+    - scsi: virtio_scsi: Fix spelling mistake "Unsupport" -> "Unsupported"
+    - sched: Always inline is_percpu_thread()
+    - Linux 5.4.154
+  * Focal update: v5.4.153 upstream stable release (LP: #1950014)
+    - Partially revert "usb: Kconfig: using select for USB_COMMON dependency"
+    - USB: cdc-acm: fix racy tty buffer accesses
+    - USB: cdc-acm: fix break reporting
+    - usb: typec: tcpm: handle SRC_STARTUP state if cc changes
+    - xen/privcmd: fix error handling in mmap-resource processing
+    - mmc: meson-gx: do not use memcpy_to/fromio for dram-access-quirk
+    - ovl: fix missing negative dentry check in ovl_rename()
+    - nfsd: fix error handling of register_pernet_subsys() in init_nfsd()
+    - nfsd4: Handle the NFSv4 READDIR 'dircount' hint being zero
+    - xen/balloon: fix cancelled balloon action
+    - ARM: dts: omap3430-sdp: Fix NAND device node
+    - ARM: dts: qcom: apq8064: use compatible which contains chipid
+    - MIPS: BPF: Restore MIPS32 cBPF JIT
+    - bpf, mips: Validate conditional branch offsets
+    - soc: qcom: socinfo: Fixed argument passed to platform_set_data()
+    - ARM: dts: qcom: apq8064: Use 27MHz PXO clock as DSI PLL reference
+    - soc: qcom: mdt_loader: Drop PT_LOAD check on hash segment
+    - ARM: dts: imx: Add missing pinctrl-names for panel on M53Menlo
+    - ARM: dts: imx: Fix USB host power regulator polarity on M53Menlo
+    - arm64: dts: qcom: pm8150: use qcom,pm8998-pon binding
+    - xtensa: move XCHAL_KIO_* definitions to kmem_layout.h
+    - xtensa: use CONFIG_USE_OF instead of CONFIG_OF
+    - xtensa: call irqchip_init only when CONFIG_USE_OF is selected
+    - bpf, arm: Fix register clobbering in div/mod implementation
+    - bpf: Fix integer overflow in prealloc_elems_and_freelist()
+    - phy: mdio: fix memory leak
+    - net_sched: fix NULL deref in fifo_set_limit()
+    - powerpc/fsl/dts: Fix phy-connection-type for fm1mac3
+    - ptp_pch: Load module automatically if ID matches
+    - arm64: dts: freescale: Fix SP805 clock-names
+    - arm64: dts: ls1028a: add missing CAN nodes
+    - ARM: imx6: disable the GIC CPU interface before calling stby-poweroff
+      sequence
+    - net: bridge: use nla_total_size_64bit() in br_get_linkxstats_size()
+    - net/sched: sch_taprio: properly cancel timer from taprio_destroy()
+    - net: sfp: Fix typo in state machine debug string
+    - netlink: annotate data races around nlk->bound
+    - bus: ti-sysc: Use CLKDM_NOAUTO for dra7 dcan1 for errata i893
+    - video: fbdev: gbefb: Only instantiate device when built for IP32
+    - drm/nouveau/debugfs: fix file release memory leak
+    - gve: Correct available tx qpl check
+    - rtnetlink: fix if_nlmsg_stats_size() under estimation
+    - gve: fix gve_get_stats()
+    - i40e: fix endless loop under rtnl
+    - i40e: Fix freeing of uninitialized misc IRQ vector
+    - net: prefer socket bound to interface when not in VRF
+    - i2c: acpi: fix resource leak in reconfiguration device addition
+    - bpf, s390: Fix potential memory leak about jit_data
+    - RISC-V: Include clone3() on rv32
+    - x86/platform/olpc: Correct ifdef symbol to intended CONFIG_OLPC_XO15_SCI
+    - x86/hpet: Use another crystalball to evaluate HPET usability
+    - x86/Kconfig: Correct reference to MWINCHIP3D
+    - Linux 5.4.153
+  * Focal update: v5.4.152 upstream stable release (LP: #1950009)
+    - net: mdio: introduce a shutdown method to mdio device drivers
+    - xen-netback: correct success/error reporting for the SKB-with-fraglist case
+    - sparc64: fix pci_iounmap() when CONFIG_PCI is not set
+    - ext2: fix sleeping in atomic bugs on error
+    - scsi: sd: Free scsi_disk device via put_device()
+    - usb: testusb: Fix for showing the connection speed
+    - usb: dwc2: check return value after calling platform_get_resource()
+    - selftests: be sure to make khdr before other targets
+    - selftests:kvm: fix get_warnings_count() ignoring fscanf() return warn
+    - scsi: ses: Retry failed Send/Receive Diagnostic commands
+    - tools/vm/page-types: remove dependency on opt_file for idle page tracking
+    - KVM: do not shrink halt_poll_ns below grow_start
+    - kvm: x86: Add AMD PMU MSRs to msrs_to_save_all[]
+    - perf/x86: Reset destroy callback on event init failure
+    - silence nfscache allocation warnings with kvzalloc
+    - libata: Add ATA_HORKAGE_NO_NCQ_ON_ATI for Samsung 860 and 870 SSD.
+    - Linux 5.4.152
+  * linux-aws: Fix backport of RDMA/efa: Expose maximum  TX doorbell batch
+    (LP: #1949882)
+    - SAUCE: aws: Fix backport of RDMA/efa: Expose maximum TX doorbell batch
+
+  [ Ubuntu: 5.4.0-91.102 ]
+
+  * focal/linux: 5.4.0-91.102 -proposed tracker (LP: #1949840)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update Ubuntu.md
+    - debian/dkms-versions -- update from kernel-versions (main/2021.11.08)
+  * KVM emulation failure when booting into  VM crash kernel with multiple CPUs
+    (LP: #1948862)
+    - KVM: x86: Properly reset MMU context at vCPU RESET/INIT
+  * aufs: kernel bug with apparmor and fuseblk (LP: #1948470)
+    - SAUCE: aufs: bugfix, stop omitting path->mnt
+  * ebpf:  bpf_redirect fails with ip6 gre interfaces (LP: #1947164)
+    - net: handle ARPHRD_IP6GRE in dev_is_mac_header_xmit()
+  * require CAP_NET_ADMIN to attach N_HCI ldisc (LP: #1949516)
+    - Bluetooth: hci_ldisc: require CAP_NET_ADMIN to attach N_HCI ldisc
+  * ACL updates on OCFS2 are not revalidated (LP: #1947161)
+    - ocfs2: fix remounting needed after setfacl command
+  * ppc64 BPF JIT mod by 1 will not return 0 (LP: #1948351)
+    - powerpc/bpf: Fix BPF_MOD when imm == 1
+  * Drop "UBUNTU: SAUCE: cachefiles: Page leaking in
+    cachefiles_read_backing_file while vmscan is active" (LP: #1947709)
+    - Revert "UBUNTU: SAUCE: cachefiles: Page leaking in
+      cachefiles_read_backing_file while vmscan is active"
+  * Reassign I/O Path of ConnectX-5 Port 1 before Port 2 causes NULL dereference
+    (LP: #1943464)
+    - s390/pci: fix leak of PCI device structure
+    - s390/pci: fix use after free of zpci_dev
+    - s390/pci: fix zpci_zdev_put() on reserve
+  * [SRU][F] USB: serial: pl2303: add support for PL2303HXN (LP: #1948377)
+    - USB: serial: pl2303: add support for PL2303HXN
+    - USB: serial: pl2303: fix line-speed handling on newer chips
+  * Focal update: v5.4.151 upstream stable release (LP: #1947888)
+    - tty: Fix out-of-bound vmalloc access in imageblit
+    - cpufreq: schedutil: Use kobject release() method to free sugov_tunables
+    - cpufreq: schedutil: Destroy mutex before kobject_put() frees the memory
+    - usb: cdns3: fix race condition before setting doorbell
+    - fs-verity: fix signed integer overflow with i_size near S64_MAX
+    - hwmon: (w83793) Fix NULL pointer dereference by removing unnecessary
+      structure field
+    - hwmon: (w83792d) Fix NULL pointer dereference by removing unnecessary
+      structure field
+    - hwmon: (w83791d) Fix NULL pointer dereference by removing unnecessary
+      structure field
+    - scsi: ufs: Fix illegal offset in UPIU event trace
+    - mac80211: fix use-after-free in CCMP/GCMP RX
+    - x86/kvmclock: Move this_cpu_pvti into kvmclock.h
+    - drm/amd/display: Pass PCI deviceid into DC
+    - ipvs: check that ip_vs_conn_tab_bits is between 8 and 20
+    - hwmon: (mlxreg-fan) Return non-zero value when fan current state is enforced
+      from sysfs
+    - mac80211: Fix ieee80211_amsdu_aggregate frag_tail bug
+    - mac80211: limit injected vht mcs/nss in ieee80211_parse_tx_radiotap
+    - mac80211: mesh: fix potentially unaligned access
+    - mac80211-hwsim: fix late beacon hrtimer handling
+    - sctp: break out if skb_header_pointer returns NULL in sctp_rcv_ootb
+    - hwmon: (tmp421) report /PVLD condition as fault
+    - hwmon: (tmp421) fix rounding for negative values
+    - net: ipv4: Fix rtnexthop len when RTA_FLOW is present
+    - e100: fix length calculation in e100_get_regs_len
+    - e100: fix buffer overrun in e100_get_regs
+    - selftests, bpf: test_lwt_ip_encap: Really disable rp_filter
+    - scsi: csiostor: Add module softdep on cxgb4
+    - net: hns3: do not allow call hns3_nic_net_open repeatedly
+    - net: sched: flower: protect fl_walk() with rcu
+    - af_unix: fix races in sk_peer_pid and sk_peer_cred accesses
+    - perf/x86/intel: Update event constraints for ICX
+    - elf: don't use MAP_FIXED_NOREPLACE for elf interpreter mappings
+    - debugfs: debugfs_create_file_size(): use IS_ERR to check for error
+    - ipack: ipoctal: fix stack information leak
+    - ipack: ipoctal: fix tty registration race
+    - ipack: ipoctal: fix tty-registration error handling
+    - ipack: ipoctal: fix missing allocation-failure check
+    - ipack: ipoctal: fix module reference leak
+    - ext4: fix loff_t overflow in ext4_max_bitmap_size()
+    - ext4: fix reserved space counter leakage
+    - ext4: fix potential infinite loop in ext4_dx_readdir()
+    - HID: u2fzero: ignore incomplete packets without data
+    - net: udp: annotate data race around udp_sk(sk)->corkflag
+    - net: stmmac: don't attach interface until resume finishes
+    - PCI: Fix pci_host_bridge struct device release/free handling
+    - libnvdimm/pmem: Fix crash triggered when I/O in-flight during unbind
+    - hso: fix bailout in error case of probe
+    - usb: hso: fix error handling code of hso_create_net_device
+    - usb: hso: remove the bailout parameter
+    - crypto: ccp - fix resource leaks in ccp_run_aes_gcm_cmd()
+    - HID: betop: fix slab-out-of-bounds Write in betop_probe
+    - netfilter: ipset: Fix oversized kvmalloc() calls
+    - HID: usbhid: free raw_report buffers in usbhid_stop
+    - Linux 5.4.151
+  * Focal update: v5.4.150 upstream stable release (LP: #1947886)
+    - usb: gadget: r8a66597: fix a loop in set_feature()
+    - usb: dwc2: gadget: Fix ISOC flow for BDMA and Slave
+    - usb: dwc2: gadget: Fix ISOC transfer complete handling for DDMA
+    - usb: musb: tusb6010: uninitialized data in tusb_fifo_write_unaligned()
+    - cifs: fix incorrect check for null pointer in header_assemble
+    - xen/x86: fix PV trap handling on secondary processors
+    - usb-storage: Add quirk for ScanLogic SL11R-IDE older than 2.6c
+    - USB: serial: cp210x: add ID for GW Instek GDM-834x Digital Multimeter
+    - USB: cdc-acm: fix minor-number release
+    - binder: make sure fd closes complete
+    - staging: greybus: uart: fix tty use after free
+    - Re-enable UAS for LaCie Rugged USB3-FW with fk quirk
+    - USB: serial: mos7840: remove duplicated 0xac24 device ID
+    - USB: serial: option: add Telit LN920 compositions
+    - USB: serial: option: remove duplicate USB device ID
+    - USB: serial: option: add device id for Foxconn T99W265
+    - mcb: fix error handling in mcb_alloc_bus()
+    - erofs: fix up erofs_lookup tracepoint
+    - btrfs: prevent __btrfs_dump_space_info() to underflow its free space
+    - serial: mvebu-uart: fix driver's tx_empty callback
+    - net: hso: fix muxed tty registration
+    - afs: Fix incorrect triggering of sillyrename on 3rd-party invalidation
+    - platform/x86/intel: punit_ipc: Drop wrong use of ACPI_PTR()
+    - enetc: Fix illegal access when reading affinity_hint
+    - bnxt_en: Fix TX timeout when TX ring size is set to the smallest
+    - net/smc: add missing error check in smc_clc_prfx_set()
+    - gpio: uniphier: Fix void functions to remove return value
+    - qed: rdma - don't wait for resources under hw error recovery flow
+    - net/mlx4_en: Don't allow aRFS for encapsulated packets
+    - scsi: iscsi: Adjust iface sysfs attr detection
+    - tty: synclink_gt, drop unneeded forward declarations
+    - tty: synclink_gt: rename a conflicting function name
+    - fpga: machxo2-spi: Return an error on failure
+    - fpga: machxo2-spi: Fix missing error code in machxo2_write_complete()
+    - thermal/core: Potential buffer overflow in thermal_build_list_of_policies()
+    - cifs: fix a sign extension bug
+    - scsi: qla2xxx: Restore initiator in dual mode
+    - scsi: lpfc: Use correct scnprintf() limit
+    - irqchip/goldfish-pic: Select GENERIC_IRQ_CHIP to fix build
+    - irqchip/gic-v3-its: Fix potential VPE leak on error
+    - md: fix a lock order reversal in md_alloc
+    - blktrace: Fix uaf in blk_trace access after removing by sysfs
+    - net: macb: fix use after free on rmmod
+    - net: stmmac: allow CSR clock of 300MHz
+    - m68k: Double cast io functions to unsigned long
+    - ipv6: delay fib6_sernum increase in fib6_add
+    - bpf: Add oversize check before call kvcalloc()
+    - xen/balloon: use a kernel thread instead a workqueue
+    - nvme-multipath: fix ANA state updates when a namespace is not present
+    - sparc32: page align size in arch_dma_alloc
+    - blk-cgroup: fix UAF by grabbing blkcg lock before destroying blkg pd
+    - compiler.h: Introduce absolute_pointer macro
+    - net: i825xx: Use absolute_pointer for memcpy from fixed memory location
+    - sparc: avoid stringop-overread errors
+    - qnx4: avoid stringop-overread errors
+    - parisc: Use absolute_pointer() to define PAGE0
+    - arm64: Mark __stack_chk_guard as __ro_after_init
+    - alpha: Declare virt_to_phys and virt_to_bus parameter as pointer to volatile
+    - net: 6pack: Fix tx timeout and slot time
+    - spi: Fix tegra20 build with CONFIG_PM=n
+    - EDAC/synopsys: Fix wrong value type assignment for edac_mode
+    - thermal/drivers/int340x: Do not set a wrong tcc offset on resume
+    - arm64: dts: marvell: armada-37xx: Extend PCIe MEM space
+    - xen/balloon: fix balloon kthread freezing
+    - qnx4: work around gcc false positive warning bug
+    - Linux 5.4.150
+  * ACL updates on OCFS2 are not revalidated (LP: #1947161) // Focal update:
+    v5.4.150 upstream stable release (LP: #1947886)
+    - ocfs2: drop acl cache for directories too
+  * Focal update: v5.4.149 upstream stable release (LP: #1947885)
+    - PCI: pci-bridge-emul: Fix big-endian support
+    - PCI: aardvark: Indicate error in 'val' when config read fails
+    - PCI: pci-bridge-emul: Add PCIe Root Capabilities Register
+    - PCI: aardvark: Fix reporting CRS value
+    - PCI/ACPI: Add Ampere Altra SOC MCFG quirk
+    - KVM: remember position in kvm->vcpus array
+    - console: consume APC, DM, DCS
+    - s390/pci_mmio: fully validate the VMA before calling follow_pte()
+    - ARM: Qualify enabling of swiotlb_init()
+    - apparmor: remove duplicate macro list_entry_is_head()
+    - ARM: 9077/1: PLT: Move struct plt_entries definition to header
+    - ARM: 9078/1: Add warn suppress parameter to arm_gen_branch_link()
+    - ARM: 9079/1: ftrace: Add MODULE_PLTS support
+    - ARM: 9098/1: ftrace: MODULE_PLT: Fix build problem without DYNAMIC_FTRACE
+    - sctp: validate chunk size in __rcv_asconf_lookup
+    - sctp: add param size validation for SCTP_PARAM_SET_PRIMARY
+    - staging: rtl8192u: Fix bitwise vs logical operator in
+      TranslateRxSignalStuff819xUsb()
+    - um: virtio_uml: fix memory leak on init failures
+    - dmaengine: acpi: Avoid comparison GSI with Linux vIRQ
+    - thermal/drivers/exynos: Fix an error code in exynos_tmu_probe()
+    - 9p/trans_virtio: Remove sysfs file on probe failure
+    - prctl: allow to setup brk for et_dyn executables
+    - nilfs2: use refcount_dec_and_lock() to fix potential UAF
+    - profiling: fix shift-out-of-bounds bugs
+    - pwm: lpc32xx: Don't modify HW state in .probe() after the PWM chip was
+      registered
+    - phy: avoid unnecessary link-up delay in polling mode
+    - net: stmmac: reset Tx desc base address before restarting Tx
+    - Kconfig.debug: drop selecting non-existing HARDLOCKUP_DETECTOR_ARCH
+    - thermal/core: Fix thermal_cooling_device_register() prototype
+    - drivers: base: cacheinfo: Get rid of DEFINE_SMP_CALL_CACHE_FUNCTION()
+    - parisc: Move pci_dev_is_behind_card_dino to where it is used
+    - dmaengine: sprd: Add missing MODULE_DEVICE_TABLE
+    - dmaengine: ioat: depends on !UML
+    - dmaengine: xilinx_dma: Set DMA mask for coherent APIs
+    - ceph: request Fw caps before updating the mtime in ceph_write_iter
+    - ceph: lockdep annotations for try_nonblocking_invalidate
+    - btrfs: fix lockdep warning while mounting sprout fs
+    - nilfs2: fix memory leak in nilfs_sysfs_create_device_group
+    - nilfs2: fix NULL pointer in nilfs_##name##_attr_release
+    - nilfs2: fix memory leak in nilfs_sysfs_create_##name##_group
+    - nilfs2: fix memory leak in nilfs_sysfs_delete_##name##_group
+    - nilfs2: fix memory leak in nilfs_sysfs_create_snapshot_group
+    - nilfs2: fix memory leak in nilfs_sysfs_delete_snapshot_group
+    - pwm: img: Don't modify HW state in .remove() callback
+    - pwm: rockchip: Don't modify HW state in .remove() callback
+    - pwm: stm32-lp: Don't modify HW state in .remove() callback
+    - blk-throttle: fix UAF by deleteing timer in blk_throtl_exit()
+    - rtc: rx8010: select REGMAP_I2C
+    - drm/nouveau/nvkm: Replace -ENOSYS with -ENODEV
+    - Linux 5.4.149
+
+  [ Ubuntu: 5.4.0-90.101 ]
+
+  * focal/linux: 5.4.0-90.101 -proposed tracker (LP: #1947260)
+  * Packaging resync (LP: #1786013)
+    - debian/dkms-versions -- update from kernel-versions (main/2021.10.18)
+  * Add final-checks to check certificates (LP: #1947174)
+    - [Packaging] Add system trusted and revocation keys final check
+  * No sound on Lenovo laptop models Legion 15IMHG05, Yoga 7 14ITL5, and 13s
+    Gen2 (LP: #1939052)
+    - ALSA: hda/realtek: Quirks to enable speaker output for Lenovo Legion 7i
+      15IMHG05, Yoga 7i 14ITL5/15ITL5, and 13s Gen2 laptops.
+    - ALSA: hda/realtek: Fix for quirk to enable speaker output on the Lenovo 13s
+      Gen2
+  * CVE-2020-36385
+    - RDMA/cma: Add missing locking to rdma_accept()
+    - RDMA/ucma: Fix the locking of ctx->file
+    - RDMA/ucma: Rework ucma_migrate_id() to avoid races with destroy
+  * Focal update: v5.4.148 upstream stable release (LP: #1946802)
+    - rtc: tps65910: Correct driver module alias
+    - btrfs: wake up async_delalloc_pages waiters after submit
+    - btrfs: reset replace target device to allocation state on close
+    - blk-zoned: allow zone management send operations without CAP_SYS_ADMIN
+    - blk-zoned: allow BLKREPORTZONE without CAP_SYS_ADMIN
+    - PCI/MSI: Skip masking MSI-X on Xen PV
+    - powerpc/perf/hv-gpci: Fix counter value parsing
+    - xen: fix setting of max_pfn in shared_info
+    - include/linux/list.h: add a macro to test if entry is pointing to the head
+    - 9p/xen: Fix end of loop tests for list_for_each_entry
+    - tools/thermal/tmon: Add cross compiling support
+    - pinctrl: stmfx: Fix hazardous u8[] to unsigned long cast
+    - pinctrl: ingenic: Fix incorrect pull up/down info
+    - soc: qcom: aoss: Fix the out of bound usage of cooling_devs
+    - soc: aspeed: lpc-ctrl: Fix boundary check for mmap
+    - soc: aspeed: p2a-ctrl: Fix boundary check for mmap
+    - arm64: head: avoid over-mapping in map_memory
+    - crypto: public_key: fix overflow during implicit conversion
+    - block: bfq: fix bfq_set_next_ioprio_data()
+    - power: supply: max17042: handle fails of reading status register
+    - dm crypt: Avoid percpu_counter spinlock contention in crypt_page_alloc()
+    - VMCI: fix NULL pointer dereference when unmapping queue pair
+    - media: uvc: don't do DMA on stack
+    - media: rc-loopback: return number of emitters rather than error
+    - Revert "dmaengine: imx-sdma: refine to load context only once"
+    - dmaengine: imx-sdma: remove duplicated sdma_load_context
+    - libata: add ATA_HORKAGE_NO_NCQ_TRIM for Samsung 860 and 870 SSDs
+    - ARM: 9105/1: atags_to_fdt: don't warn about stack size
+    - PCI/portdrv: Enable Bandwidth Notification only if port supports it
+    - PCI: Restrict ASMedia ASM1062 SATA Max Payload Size Supported
+    - PCI: Return ~0 data on pciconfig_read() CAP_SYS_ADMIN failure
+    - PCI: xilinx-nwl: Enable the clock through CCF
+    - PCI: aardvark: Fix checking for PIO status
+    - PCI: aardvark: Increase polling delay to 1.5s while waiting for PIO response
+    - PCI: aardvark: Fix masking and unmasking legacy INTx interrupts
+    - HID: input: do not report stylus battery state as "full"
+    - f2fs: quota: fix potential deadlock
+    - scsi: bsg: Remove support for SCSI_IOCTL_SEND_COMMAND
+    - IB/hfi1: Adjust pkey entry in index 0
+    - RDMA/iwcm: Release resources if iw_cm module initialization fails
+    - docs: Fix infiniband uverbs minor number
+    - pinctrl: samsung: Fix pinctrl bank pin count
+    - vfio: Use config not menuconfig for VFIO_NOIOMMU
+    - powerpc/stacktrace: Include linux/delay.h
+    - RDMA/efa: Remove double QP type assignment
+    - f2fs: show f2fs instance in printk_ratelimited
+    - f2fs: reduce the scope of setting fsck tag when de->name_len is zero
+    - openrisc: don't printk() unconditionally
+    - dma-debug: fix debugfs initialization order
+    - SUNRPC: Fix potential memory corruption
+    - scsi: fdomain: Fix error return code in fdomain_probe()
+    - pinctrl: single: Fix error return code in pcs_parse_bits_in_pinctrl_entry()
+    - scsi: smartpqi: Fix an error code in pqi_get_raid_map()
+    - scsi: qedi: Fix error codes in qedi_alloc_global_queues()
+    - scsi: qedf: Fix error codes in qedf_alloc_global_queues()
+    - powerpc/config: Renable MTD_PHYSMAP_OF
+    - scsi: target: avoid per-loop XCOPY buffer allocations
+    - HID: i2c-hid: Fix Elan touchpad regression
+    - KVM: PPC: Book3S HV Nested: Reflect guest PMU in-use to L0 when guest SPRs
+      are live
+    - platform/x86: dell-smbios-wmi: Add missing kfree in error-exit from
+      run_smbios_call
+    - fscache: Fix cookie key hashing
+    - clk: at91: sam9x60: Don't use audio PLL
+    - clk: at91: clk-generated: pass the id of changeable parent at registration
+    - clk: at91: clk-generated: Limit the requested rate to our range
+    - KVM: PPC: Fix clearing never mapped TCEs in realmode
+    - f2fs: fix to account missing .skipped_gc_rwsem
+    - f2fs: fix unexpected ENOENT comes from f2fs_map_blocks()
+    - f2fs: fix to unmap pages from userspace process in punch_hole()
+    - MIPS: Malta: fix alignment of the devicetree buffer
+    - kbuild: Fix 'no symbols' warning when CONFIG_TRIM_UNUSD_KSYMS=y
+    - userfaultfd: prevent concurrent API initialization
+    - drm/amdgpu: Fix amdgpu_ras_eeprom_init()
+    - ASoC: atmel: ATMEL drivers don't need HAS_DMA
+    - media: dib8000: rewrite the init prbs logic
+    - crypto: mxs-dcp - Use sg_mapping_iter to copy data
+    - PCI: Use pci_update_current_state() in pci_enable_device_flags()
+    - tipc: keep the skb in rcv queue until the whole data is read
+    - iio: dac: ad5624r: Fix incorrect handling of an optional regulator.
+    - iavf: do not override the adapter state in the watchdog task
+    - iavf: fix locking of critical sections
+    - ARM: dts: qcom: apq8064: correct clock names
+    - video: fbdev: kyro: fix a DoS bug by restricting user input
+    - netlink: Deal with ESRCH error in nlmsg_notify()
+    - Smack: Fix wrong semantics in smk_access_entry()
+    - drm: avoid blocking in drm_clients_info's rcu section
+    - igc: Check if num of q_vectors is smaller than max before array access
+    - usb: host: fotg210: fix the endpoint's transactional opportunities
+      calculation
+    - usb: host: fotg210: fix the actual_length of an iso packet
+    - usb: gadget: u_ether: fix a potential null pointer dereference
+    - USB: EHCI: ehci-mv: improve error handling in mv_ehci_enable()
+    - usb: gadget: composite: Allow bMaxPower=0 if self-powered
+    - staging: board: Fix uninitialized spinlock when attaching genpd
+    - tty: serial: jsm: hold port lock when reporting modem line changes
+    - drm/amd/display: Fix timer_per_pixel unit error
+    - drm/amd/amdgpu: Update debugfs link_settings output link_rate field in hex
+    - bpf/tests: Fix copy-and-paste error in double word test
+    - bpf/tests: Do not PASS tests without actually testing the result
+    - video: fbdev: asiliantfb: Error out if 'pixclock' equals zero
+    - video: fbdev: kyro: Error out if 'pixclock' equals zero
+    - video: fbdev: riva: Error out if 'pixclock' equals zero
+    - ipv4: ip_output.c: Fix out-of-bounds warning in ip_copy_addrs()
+    - flow_dissector: Fix out-of-bounds warnings
+    - s390/jump_label: print real address in a case of a jump label bug
+    - s390: make PCI mio support a machine flag
+    - serial: 8250: Define RX trigger levels for OxSemi 950 devices
+    - xtensa: ISS: don't panic in rs_init
+    - hvsi: don't panic on tty_register_driver failure
+    - serial: 8250_pci: make setup_port() parameters explicitly unsigned
+    - staging: ks7010: Fix the initialization of the 'sleep_status' structure
+    - samples: bpf: Fix tracex7 error raised on the missing argument
+    - ata: sata_dwc_460ex: No need to call phy_exit() befre phy_init()
+    - Bluetooth: skip invalid hci_sync_conn_complete_evt
+    - workqueue: Fix possible memory leaks in wq_numa_init()
+    - bonding: 3ad: fix the concurrency between __bond_release_one() and
+      bond_3ad_state_machine_handler()
+    - arm64: tegra: Fix Tegra194 PCIe EP compatible string
+    - ASoC: Intel: bytcr_rt5640: Move "Platform Clock" routes to the maps for the
+      matching in-/output
+    - media: imx258: Rectify mismatch of VTS value
+    - media: imx258: Limit the max analogue gain to 480
+    - media: v4l2-dv-timings.c: fix wrong condition in two for-loops
+    - media: TDA1997x: fix tda1997x_query_dv_timings() return value
+    - media: tegra-cec: Handle errors of clk_prepare_enable()
+    - ARM: dts: imx53-ppd: Fix ACHC entry
+    - arm64: dts: qcom: sdm660: use reg value for memory node
+    - net: ethernet: stmmac: Do not use unreachable() in ipq806x_gmac_probe()
+    - drm/msm: mdp4: drop vblank get/put from prepare/complete_commit
+    - selftests/bpf: Fix xdp_tx.c prog section name
+    - Bluetooth: schedule SCO timeouts with delayed_work
+    - Bluetooth: avoid circular locks in sco_sock_connect
+    - net/mlx5: Fix variable type to match 64bit
+    - gpu: drm: amd: amdgpu: amdgpu_i2c: fix possible uninitialized-variable
+      access in amdgpu_i2c_router_select_ddc_port()
+    - drm/display: fix possible null-pointer dereference in dcn10_set_clock()
+    - mac80211: Fix monitor MTU limit so that A-MSDUs get through
+    - ARM: tegra: tamonten: Fix UART pad setting
+    - arm64: tegra: Fix compatible string for Tegra132 CPUs
+    - arm64: dts: ls1046a: fix eeprom entries
+    - nvme-tcp: don't check blk_mq_tag_to_rq when receiving pdu data
+    - Bluetooth: Fix handling of LE Enhanced Connection Complete
+    - opp: Don't print an error if required-opps is missing
+    - serial: sh-sci: fix break handling for sysrq
+    - tcp: enable data-less, empty-cookie SYN with TFO_SERVER_COOKIE_NOT_REQD
+    - rpc: fix gss_svc_init cleanup on failure
+    - staging: rts5208: Fix get_ms_information() heap buffer size
+    - gfs2: Don't call dlm after protocol is unmounted
+    - usb: chipidea: host: fix port index underflow and UBSAN complains
+    - lockd: lockd server-side shouldn't set fl_ops
+    - drm/exynos: Always initialize mapping in exynos_drm_register_dma()
+    - m68knommu: only set CONFIG_ISA_DMA_API for ColdFire sub-arch
+    - btrfs: tree-log: check btrfs_lookup_data_extent return value
+    - ASoC: Intel: Skylake: Fix module configuration for KPB and MIXER
+    - ASoC: Intel: Skylake: Fix passing loadable flag for module
+    - of: Don't allow __of_attached_node_sysfs() without CONFIG_SYSFS
+    - mmc: sdhci-of-arasan: Check return value of non-void funtions
+    - mmc: rtsx_pci: Fix long reads when clock is prescaled
+    - selftests/bpf: Enlarge select() timeout for test_maps
+    - mmc: core: Return correct emmc response in case of ioctl error
+    - cifs: fix wrong release in sess_alloc_buffer() failed path
+    - Revert "USB: xhci: fix U1/U2 handling for hardware with XHCI_INTEL_HOST
+      quirk set"
+    - usb: musb: musb_dsps: request_irq() after initializing musb
+    - usbip: give back URBs for unsent unlink requests during cleanup
+    - usbip:vhci_hcd USB port can get stuck in the disabled state
+    - ASoC: rockchip: i2s: Fix regmap_ops hang
+    - ASoC: rockchip: i2s: Fixup config for DAIFMT_DSP_A/B
+    - drm/amdkfd: Account for SH/SE count when setting up cu masks.
+    - iwlwifi: mvm: fix a memory leak in iwl_mvm_mac_ctxt_beacon_changed
+    - iwlwifi: mvm: avoid static queue number aliasing
+    - iwlwifi: mvm: fix access to BSS elements
+    - net/mlx5: DR, Enable QP retransmission
+    - parport: remove non-zero check on count
+    - ath9k: fix OOB read ar9300_eeprom_restore_internal
+    - ath9k: fix sleeping in atomic context
+    - net: fix NULL pointer reference in cipso_v4_doi_free
+    - fix array-index-out-of-bounds in taprio_change
+    - net: w5100: check return value after calling platform_get_resource()
+    - parisc: fix crash with signals and alloca
+    - ovl: fix BUG_ON() in may_delete() when called from ovl_cleanup()
+    - scsi: BusLogic: Fix missing pr_cont() use
+    - scsi: qla2xxx: Changes to support kdump kernel
+    - scsi: qla2xxx: Sync queue idx with queue_pair_map idx
+    - cpufreq: powernv: Fix init_chip_info initialization in numa=off
+    - s390/pv: fix the forcing of the swiotlb
+    - mm/hugetlb: initialize hugetlb_usage in mm_init
+    - mm,vmscan: fix divide by zero in get_scan_count
+    - memcg: enable accounting for pids in nested pid namespaces
+    - platform/chrome: cros_ec_proto: Send command again when timeout occurs
+    - lib/test_stackinit: Fix static initializer test
+    - net: dsa: lantiq_gswip: fix maximum frame length
+    - drm/msi/mdp4: populate priv->kms in mdp4_kms_init
+    - drm/amdgpu: Fix BUG_ON assert
+    - drm/panfrost: Simplify lock_region calculation
+    - drm/panfrost: Use u64 for size in lock_region
+    - drm/panfrost: Clamp lock region to Bifrost minimum
+    - btrfs: fix upper limit for max_inline for page size 64K
+    - xen: reset legacy rtc flag for PV domU
+    - bnx2x: Fix enabling network interfaces without VFs
+    - arm64/sve: Use correct size when reinitialising SVE state
+    - PM: base: power: don't try to use non-existing RTC for storing data
+    - PCI: Add AMD GPU multi-function power dependencies
+    - drm/amd/amdgpu: Increase HWIP_MAX_INSTANCE to 10
+    - drm/etnaviv: return context from etnaviv_iommu_context_get
+    - drm/etnaviv: put submit prev MMU context when it exists
+    - drm/etnaviv: stop abusing mmu_context as FE running marker
+    - drm/etnaviv: keep MMU context across runtime suspend/resume
+    - drm/etnaviv: exec and MMU state is lost when resetting the GPU
+    - drm/etnaviv: fix MMU context leak on GPU reset
+    - drm/etnaviv: reference MMU context when setting up hardware state
+    - drm/etnaviv: add missing MMU context put when reaping MMU mapping
+    - s390/sclp: fix Secure-IPL facility detection
+    - x86/mm: Fix kern_addr_valid() to cope with existing but not present entries
+    - tipc: fix an use-after-free issue in tipc_recvmsg
+    - net-caif: avoid user-triggerable WARN_ON(1)
+    - ptp: dp83640: don't define PAGE0
+    - net/l2tp: Fix reference count leak in l2tp_udp_recv_core
+    - r6040: Restore MDIO clock frequency after MAC reset
+    - tipc: increase timeout in tipc_sk_enqueue()
+    - perf machine: Initialize srcline string member in add_location struct
+    - net/mlx5: FWTrace, cancel work on alloc pd error flow
+    - net/mlx5: Fix potential sleeping in atomic context
+    - events: Reuse value read using READ_ONCE instead of re-reading it
+    - vhost_net: fix OoB on sendmsg() failure.
+    - net/af_unix: fix a data-race in unix_dgram_poll
+    - net: dsa: destroy the phylink instance on any error in dsa_slave_phy_setup
+    - tcp: fix tp->undo_retrans accounting in tcp_sacktag_one()
+    - qed: Handle management FW error
+    - dt-bindings: arm: Fix Toradex compatible typo
+    - ibmvnic: check failover_pending in login response
+    - KVM: PPC: Book3S HV: Tolerate treclaim. in fake-suspend mode changing
+      registers
+    - net: hns3: pad the short tunnel frame before sending to hardware
+    - net: hns3: change affinity_mask to numa node range
+    - net: hns3: disable mac in flr process
+    - net: hns3: fix the timing issue of VF clearing interrupt sources
+    - mm/memory_hotplug: use "unsigned long" for PFN in zone_for_pfn_range()
+    - dt-bindings: mtd: gpmc: Fix the ECC bytes vs. OOB bytes equation
+    - mfd: db8500-prcmu: Adjust map to reality
+    - PCI: Add ACS quirks for NXP LX2xx0 and LX2xx2 platforms
+    - fuse: fix use after free in fuse_read_interrupt()
+    - mfd: Don't use irq_create_mapping() to resolve a mapping
+    - tracing/probes: Reject events which have the same name of existing one
+    - PCI: Add ACS quirks for Cavium multi-function devices
+    - Set fc_nlinfo in nh_create_ipv4, nh_create_ipv6
+    - net: usb: cdc_mbim: avoid altsetting toggling for Telit LN920
+    - PCI: ibmphp: Fix double unmap of io_mem
+    - ethtool: Fix an error code in cxgb2.c
+    - NTB: Fix an error code in ntb_msit_probe()
+    - NTB: perf: Fix an error code in perf_setup_inbuf()
+    - mfd: axp20x: Update AXP288 volatile ranges
+    - PCI: Fix pci_dev_str_match_path() alloc while atomic bug
+    - mfd: tqmx86: Clear GPIO IRQ resource when no IRQ is set
+    - KVM: arm64: Handle PSCI resets before userspace touches vCPU state
+    - PCI: Sync __pci_register_driver() stub for CONFIG_PCI=n
+    - mtd: rawnand: cafe: Fix a resource leak in the error handling path of
+      'cafe_nand_probe()'
+    - ARC: export clear_user_page() for modules
+    - perf unwind: Do not overwrite FEATURE_CHECK_LDFLAGS-libunwind-{x86,aarch64}
+    - net: dsa: b53: Fix calculating number of switch ports
+    - netfilter: socket: icmp6: fix use-after-scope
+    - fq_codel: reject silly quantum parameters
+    - qlcnic: Remove redundant unlock in qlcnic_pinit_from_rom
+    - ip_gre: validate csum_start only on pull
+    - net: renesas: sh_eth: Fix freeing wrong tx descriptor
+    - Linux 5.4.148
+  * Focal update: v5.4.147 upstream stable release (LP: #1946795)
+    - Linux 5.4.147
+    - upstream stable to v5.4.147
+  * CVE-2021-3428
+    - ext4: save the error code which triggered an ext4_error() in the superblock
+    - ext4: simulate various I/O and checksum errors when reading metadata
+    - ext4: save all error info in save_error_info() and drop ext4_set_errno()
+    - ext4: check journal inode extents more carefully
+  * ip6gretap / erspan / ip6erspan in rtnetlink.sh from net of
+    ubuntu_kernel_selftests failed on B-5.4-aws / B-5.4-gke / B-5.4-oracle /
+    B-5.4-azure / B-5.4 (LP: #1896448)
+    - SAUCE: selftests: rtnetlink: fixes for older iproute2
+  * CVE-2019-19449
+    - f2fs: fix wrong total_sections check and fsmeta check
+    - f2fs: fix to do sanity check on segment/section count
+  * kernel bug found when disconnecting one fiber channel interface on Cisco
+    Chassis with fnic DRV_VERSION "1.6.0.47" (LP: #1944586)
+    - scsi: fnic: Do not call 'scsi_done()' for unhandled commands
+  * memfd from ubuntu_kernel_selftests failed to build on B-5.4 (unknown type
+    name ‘__u64’) (LP: #1944613)
+    - SAUCE: selftests/memfd: fix __u64 not defined build issue
+  * Medion Notebook Keyboard not working (LP: #1909814)
+    - ACPI: resources: Add DMI-based legacy IRQ override quirk
+  * vrf: fix refcnt leak with vxlan slaves (LP: #1945180)
+    - ipv4: Fix device used for dst_alloc with local routes
+  * Check for changes relevant for security certifications (LP: #1945989)
+    - [Packaging] Add a new fips-checks script
+    - [Packaging] Add fips-checks as part of finalchecks
+  * Fix cold plugged USB device on certain PCIe USB cards (LP: #1945211)
+    - Revert "UBUNTU: SAUCE: Revert "usb: core: reduce power-on-good delay time of
+      root hub""
+    - usb: core: hcd: Add support for deferring roothub registration
+    - xhci: Set HCD flag to defer primary roothub registration
+    - usb: core: hcd: Modularize HCD stop configuration in usb_stop_hcd()
+  * CVE-2021-3759
+    - memcg: enable accounting of ipc resources
+  * Focal update: v5.4.146 upstream stable release (LP: #1946024)
+    - locking/mutex: Fix HANDOFF condition
+    - regmap: fix the offset of register error log
+    - crypto: mxs-dcp - Check for DMA mapping errors
+    - sched/deadline: Fix reset_on_fork reporting of DL tasks
+    - power: supply: axp288_fuel_gauge: Report register-address on readb / writeb
+      errors
+    - crypto: omap-sham - clear dma flags only after omap_sham_update_dma_stop()
+    - sched/deadline: Fix missing clock update in migrate_task_rq_dl()
+    - rcu/tree: Handle VM stoppage in stall detection
+    - hrtimer: Avoid double reprogramming in __hrtimer_start_range_ns()
+    - hrtimer: Ensure timerfd notification for HIGHRES=n
+    - udf: Check LVID earlier
+    - udf: Fix iocharset=utf8 mount option
+    - isofs: joliet: Fix iocharset=utf8 mount option
+    - bcache: add proper error unwinding in bcache_device_init
+    - nvme-tcp: don't update queue count when failing to set io queues
+    - nvme-rdma: don't update queue count when failing to set io queues
+    - nvmet: pass back cntlid on successful completion
+    - power: supply: max17042_battery: fix typo in MAx17042_TOFF
+    - s390/cio: add dev_busid sysfs entry for each subchannel
+    - libata: fix ata_host_start()
+    - crypto: qat - do not ignore errors from enable_vf2pf_comms()
+    - crypto: qat - handle both source of interrupt in VF ISR
+    - crypto: qat - fix reuse of completion variable
+    - crypto: qat - fix naming for init/shutdown VF to PF notifications
+    - crypto: qat - do not export adf_iov_putmsg()
+    - fcntl: fix potential deadlock for &fasync_struct.fa_lock
+    - udf_get_extendedattr() had no boundary checks.
+    - s390/kasan: fix large PMD pages address alignment check
+    - s390/debug: fix debug area life cycle
+    - m68k: emu: Fix invalid free in nfeth_cleanup()
+    - sched: Fix UCLAMP_FLAG_IDLE setting
+    - spi: spi-fsl-dspi: Fix issue with uninitialized dma_slave_config
+    - spi: spi-pic32: Fix issue with uninitialized dma_slave_config
+    - genirq/timings: Fix error return code in irq_timings_test_irqs()
+    - lib/mpi: use kcalloc in mpi_resize
+    - clocksource/drivers/sh_cmt: Fix wrong setting if don't request IRQ for clock
+      source channel
+    - crypto: qat - use proper type for vf_mask
+    - certs: Trigger creation of RSA module signing key if it's not an RSA key
+    - regulator: vctrl: Use locked regulator_get_voltage in probe path
+    - regulator: vctrl: Avoid lockdep warning in enable/disable ops
+    - spi: sprd: Fix the wrong WDG_LOAD_VAL
+    - spi: spi-zynq-qspi: use wait_for_completion_timeout to make
+      zynq_qspi_exec_mem_op not interruptible
+    - EDAC/i10nm: Fix NVDIMM detection
+    - drm/panfrost: Fix missing clk_disable_unprepare() on error in
+      panfrost_clk_init()
+    - media: TDA1997x: enable EDID support
+    - soc: rockchip: ROCKCHIP_GRF should not default to y, unconditionally
+    - media: cxd2880-spi: Fix an error handling path
+    - bpf: Fix a typo of reuseport map in bpf.h.
+    - bpf: Fix potential memleak and UAF in the verifier.
+    - ARM: dts: aspeed-g6: Fix HVI3C function-group in pinctrl dtsi
+    - arm64: dts: renesas: r8a77995: draak: Remove bogus adv7511w properties
+    - soc: qcom: rpmhpd: Use corner in power_off
+    - media: dvb-usb: fix uninit-value in dvb_usb_adapter_dvb_init
+    - media: dvb-usb: fix uninit-value in vp702x_read_mac_addr
+    - media: dvb-usb: Fix error handling in dvb_usb_i2c_init
+    - media: go7007: remove redundant initialization
+    - media: coda: fix frame_mem_ctrl for YUV420 and YVU420 formats
+    - Bluetooth: sco: prevent information leak in sco_conn_defer_accept()
+    - 6lowpan: iphc: Fix an off-by-one check of array index
+    - netns: protect netns ID lookups with RCU
+    - tcp: seq_file: Avoid skipping sk during tcp_seek_last_pos
+    - ARM: dts: meson8: Use a higher default GPU clock frequency
+    - ARM: dts: meson8b: odroidc1: Fix the pwm regulator supply properties
+    - ARM: dts: meson8b: mxq: Fix the pwm regulator supply properties
+    - ARM: dts: meson8b: ec100: Fix the pwm regulator supply properties
+    - net/mlx5e: Prohibit inner indir TIRs in IPoIB
+    - cgroup/cpuset: Fix a partition bug with hotplug
+    - net: cipso: fix warnings in netlbl_cipsov4_add_std
+    - i2c: highlander: add IRQ check
+    - leds: lt3593: Put fwnode in any case during ->probe()
+    - leds: trigger: audio: Add an activate callback to ensure the initial
+      brightness is set
+    - media: em28xx-input: fix refcount bug in em28xx_usb_disconnect
+    - media: venus: venc: Fix potential null pointer dereference on pointer fmt
+    - PCI: PM: Avoid forcing PCI_D0 for wakeup reasons inconsistently
+    - PCI: PM: Enable PME if it can be signaled from D3cold
+    - soc: qcom: smsm: Fix missed interrupts if state changes while masked
+    - debugfs: Return error during {full/open}_proxy_open() on rmmod
+    - Bluetooth: increase BTNAMSIZ to 21 chars to fix potential buffer overflow
+    - PM: EM: Increase energy calculation precision
+    - drm/msm/dpu: make dpu_hw_ctl_clear_all_blendstages clear necessary LMs
+    - arm64: dts: exynos: correct GIC CPU interfaces address range on Exynos7
+    - counter: 104-quad-8: Return error when invalid mode during ceiling_write
+    - Bluetooth: fix repeated calls to sco_sock_kill
+    - drm/msm/dsi: Fix some reference counted resource leaks
+    - usb: gadget: udc: at91: add IRQ check
+    - usb: phy: fsl-usb: add IRQ check
+    - usb: phy: twl6030: add IRQ checks
+    - usb: gadget: udc: renesas_usb3: Fix soc_device_match() abuse
+    - usb: host: ohci-tmio: add IRQ check
+    - usb: phy: tahvo: add IRQ check
+    - mac80211: Fix insufficient headroom issue for AMSDU
+    - lockd: Fix invalid lockowner cast after vfs_test_lock
+    - nfsd4: Fix forced-expiry locking
+    - usb: gadget: mv_u3d: request_irq() after initializing UDC
+    - mm/swap: consider max pages in iomap_swapfile_add_extent
+    - Bluetooth: add timeout sanity check to hci_inquiry
+    - i2c: iop3xx: fix deferred probing
+    - i2c: s3c2410: fix IRQ check
+    - rsi: fix error code in rsi_load_9116_firmware()
+    - rsi: fix an error code in rsi_probe()
+    - ASoC: Intel: Skylake: Leave data as is when invoking TLV IPCs
+    - ASoC: Intel: Skylake: Fix module resource and format selection
+    - mmc: dw_mmc: Fix issue with uninitialized dma_slave_config
+    - mmc: moxart: Fix issue with uninitialized dma_slave_config
+    - bpf: Fix possible out of bound write in narrow load handling
+    - CIFS: Fix a potencially linear read overflow
+    - i2c: mt65xx: fix IRQ check
+    - usb: ehci-orion: Handle errors of clk_prepare_enable() in probe
+    - usb: bdc: Fix an error handling path in 'bdc_probe()' when no suitable DMA
+      config is available
+    - tty: serial: fsl_lpuart: fix the wrong mapbase value
+    - ASoC: wcd9335: Fix a double irq free in the remove function
+    - ASoC: wcd9335: Fix a memory leak in the error handling path of the probe
+      function
+    - ASoC: wcd9335: Disable irq on slave ports in the remove function
+    - ath6kl: wmi: fix an error code in ath6kl_wmi_sync_point()
+    - bcma: Fix memory leak for internally-handled cores
+    - brcmfmac: pcie: fix oops on failure to resume and reprobe
+    - ipv6: make exception cache less predictible
+    - ipv4: make exception cache less predictible
+    - net: sched: Fix qdisc_rate_table refcount leak when get tcf_block failed
+    - net: qualcomm: fix QCA7000 checksum handling
+    - octeontx2-af: Fix loop in free and unmap counter
+    - ipv4: fix endianness issue in inet_rtm_getroute_build_skb()
+    - bpf: Introduce BPF nospec instruction for mitigating Spectre v4
+    - bpf: Fix leakage due to insufficient speculative store bypass mitigation
+    - bpf: verifier: Allocate idmap scratch in verifier env
+    - bpf: Fix pointer arithmetic mask tightening under state pruning
+    - tty: Fix data race between tiocsti() and flush_to_ldisc()
+    - perf/x86/amd/ibs: Extend PERF_PMU_CAP_NO_EXCLUDE to IBS Op
+    - x86/resctrl: Fix a maybe-uninitialized build warning treated as error
+    - KVM: s390: index kvm->arch.idle_mask by vcpu_idx
+    - KVM: x86: Update vCPU's hv_clock before back to guest when tsc_offset is
+      adjusted
+    - KVM: nVMX: Unconditionally clear nested.pi_pending on nested VM-Enter
+    - fuse: truncate pagecache on atomic_o_trunc
+    - fuse: flush extending writes
+    - IMA: remove -Wmissing-prototypes warning
+    - IMA: remove the dependency on CRYPTO_MD5
+    - fbmem: don't allow too huge resolutions
+    - backlight: pwm_bl: Improve bootloader/kernel device handover
+    - clk: kirkwood: Fix a clocking boot regression
+    - Linux 5.4.146
+  * AMD A8-7680 (amdgpu): broken Xorg acceleration and hibernation
+    (LP: #1920674) // Focal update: v5.4.146 upstream stable release
+    (LP: #1946024)
+    - drm/amdgpu/acp: Make PM domain really work
+  * Focal update: v5.4.145 upstream stable release (LP: #1945517)
+    - fscrypt: add fscrypt_symlink_getattr() for computing st_size
+    - ext4: report correct st_size for encrypted symlinks
+    - f2fs: report correct st_size for encrypted symlinks
+    - ubifs: report correct st_size for encrypted symlinks
+    - kthread: Fix PF_KTHREAD vs to_kthread() race
+    - xtensa: fix kconfig unmet dependency warning for HAVE_FUTEX_CMPXCHG
+    - gpu: ipu-v3: Fix i.MX IPU-v3 offset calculations for (semi)planar U/V
+      formats
+    - reset: reset-zynqmp: Fixed the argument data type
+    - qed: Fix the VF msix vectors flow
+    - net: macb: Add a NULL check on desc_ptp
+    - qede: Fix memset corruption
+    - perf/x86/intel/pt: Fix mask of num_address_ranges
+    - perf/x86/amd/ibs: Work around erratum #1197
+    - perf/x86/amd/power: Assign pmu.module
+    - cryptoloop: add a deprecation warning
+    - ARM: 8918/2: only build return_address() if needed
+    - ALSA: hda/realtek: Workaround for conflicting SSID on ASUS ROG Strix G17
+    - ALSA: pcm: fix divide error in snd_pcm_lib_ioctl
+    - ARC: wireup clone3 syscall
+    - media: stkwebcam: fix memory leak in stk_camera_probe
+    - igmp: Add ip_mc_list lock in ip_check_mc_rcu
+    - USB: serial: mos7720: improve OOM-handling in read_mos_reg()
+    - ipv4/icmp: l3mdev: Perform icmp error route lookup on source device routing
+      table (v2)
+    - powerpc/boot: Delete unneeded .globl _zimage_start
+    - net: ll_temac: Remove left-over debug message
+    - mm/page_alloc: speed up the iteration of max_order
+    - Revert "r8169: avoid link-up interrupt issue on RTL8106e if user enables
+      ASPM"
+    - x86/events/amd/iommu: Fix invalid Perf result due to IOMMU PMC power-gating
+    - Revert "btrfs: compression: don't try to compress if we don't have enough
+      pages"
+    - ALSA: usb-audio: Add registration quirk for JBL Quantum 800
+    - usb: host: xhci-rcar: Don't reload firmware after the completion
+    - usb: mtu3: use @mult for HS isoc or intr
+    - usb: mtu3: fix the wrong HS mult value
+    - xhci: fix unsafe memory usage in xhci tracing
+    - x86/reboot: Limit Dell Optiplex 990 quirk to early BIOS versions
+    - PCI: Call Max Payload Size-related fixup quirks early
+    - Linux 5.4.145
+  * Focal update: v5.4.144 upstream stable release (LP: #1944756)
+    - net: qrtr: fix another OOB Read in qrtr_endpoint_post
+    - ARC: Fix CONFIG_STACKDEPOT
+    - netfilter: conntrack: collect all entries in one cycle
+    - once: Fix panic when module unload
+    - ovl: fix uninitialized pointer read in ovl_lookup_real_one()
+    - mmc: sdhci-msm: Update the software timeout value for sdhc
+    - mm, oom: make the calculation of oom badness more accurate
+    - can: usb: esd_usb2: esd_usb2_rx_event(): fix the interchange of the CAN RX
+      and TX error counters
+    - Revert "USB: serial: ch341: fix character loss at high transfer rates"
+    - USB: serial: option: add new VID/PID to support Fibocom FG150
+    - usb: dwc3: gadget: Fix dwc3_calc_trbs_left()
+    - usb: dwc3: gadget: Stop EP0 transfers during pullup disable
+    - scsi: core: Fix hang of freezing queue between blocking and running device
+    - RDMA/bnxt_re: Add missing spin lock initialization
+    - IB/hfi1: Fix possible null-pointer dereference in _extend_sdma_tx_descs()
+    - e1000e: Fix the max snoop/no-snoop latency for 10M
+    - RDMA/efa: Free IRQ vectors on error flow
+    - ip_gre: add validation for csum_start
+    - xgene-v2: Fix a resource leak in the error handling path of 'xge_probe()'
+    - net: marvell: fix MVNETA_TX_IN_PRGRS bit number
+    - rtnetlink: Return correct error on changing device netns
+    - net: hns3: clear hardware resource when loading driver
+    - net: hns3: fix duplicate node in VLAN list
+    - net: hns3: fix get wrong pfc_en when query PFC configuration
+    - drm/i915: Fix syncmap memory leak
+    - usb: gadget: u_audio: fix race condition on endpoint stop
+    - perf/x86/intel/uncore: Fix integer overflow on 23 bit left shift of a u32
+    - opp: remove WARN when no valid OPPs remain
+    - virtio: Improve vq->broken access to avoid any compiler optimization
+    - virtio_pci: Support surprise removal of virtio pci device
+    - vringh: Use wiov->used to check for read/write desc order
+    - qed: qed ll2 race condition fixes
+    - qed: Fix null-pointer dereference in qed_rdma_create_qp()
+    - drm: Copy drm_wait_vblank to user before returning
+    - drm/nouveau/disp: power down unused DP links during init
+    - net/rds: dma_map_sg is entitled to merge entries
+    - btrfs: fix race between marking inode needs to be logged and log syncing
+    - vt_kdsetmode: extend console locking
+    - bpf: Track contents of read-only maps as scalars
+    - bpf: Fix cast to pointer from integer of different size warning
+    - net: dsa: mt7530: fix VLAN traffic leaks again
+    - KVM: x86/mmu: Treat NX as used (not reserved) for all !TDP shadow MMUs
+    - arm64: dts: qcom: msm8994-angler: Fix gpio-reserved-ranges 85-88
+    - btrfs: fix NULL pointer dereference when deleting device by invalid id
+    - Revert "floppy: reintroduce O_NDELAY fix"
+    - Revert "parisc: Add assembly implementations for memset, strlen, strcpy,
+      strncpy and strcat"
+    - net: don't unconditionally copy_from_user a struct ifreq for socket ioctls
+    - audit: move put_tree() to avoid trim_trees refcount underflow and UAF
+    - Linux 5.4.144
+
+  [ Ubuntu: 5.4.0-89.100 ]
+
+  * focal/linux: 5.4.0-89.100 -proposed tracker (LP: #1944901)
+  * Packaging resync (LP: #1786013)
+    - debian/dkms-versions -- update from kernel-versions (main/2021.09.27)
+  * ext4 journal recovery fails w/ data=journal + mmap (LP: #1847340)
+    - jbd2: introduce/export functions
+      jbd2_journal_submit|finish_inode_data_buffers()
+    - jbd2, ext4, ocfs2: introduce/use journal callbacks
+      j_submit|finish_inode_data_buffers()
+    - ext4: data=journal: fixes for ext4_page_mkwrite()
+    - ext4: data=journal: write-protect pages on j_submit_inode_data_buffers()
+    - ext4: fix mmap write protection for data=journal mode
+  * CVE-2021-40490
+    - ext4: fix race writing to an inline_data file while its xattrs are changing
+  * Obsolete patch "UBUNTU: SAUCE: ext4: fix directory index node split
+    corruption" (LP: #1942902)
+    - Revert "UBUNTU: SAUCE: ext4: fix directory index node split corruption"
+  * psock_snd.sh in net from ubuntu_kernel_selftests ADT failure with
+    focal/groovy/hirsute/impish (LP: #1892213)
+    - selftests/net: remove min gso test in packet_snd
+  * Focal update: v5.4.143 upstream stable release (LP: #1944212)
+    - ext4: fix EXT4_MAX_LOGICAL_BLOCK macro
+    - x86/fpu: Make init_fpstate correct with optimized XSAVE
+    - ath: Use safer key clearing with key cache entries
+    - ath9k: Clear key cache explicitly on disabling hardware
+    - ath: Export ath_hw_keysetmac()
+    - ath: Modify ath_key_delete() to not need full key entry
+    - ath9k: Postpone key cache entry deletion for TXQ frames reference it
+    - mtd: cfi_cmdset_0002: fix crash when erasing/writing AMD cards
+    - media: zr364xx: propagate errors from zr364xx_start_readpipe()
+    - media: zr364xx: fix memory leaks in probe()
+    - media: drivers/media/usb: fix memory leak in zr364xx_probe
+    - USB: core: Avoid WARNings for 0-length descriptor requests
+    - dmaengine: xilinx_dma: Fix read-after-free bug when terminating transfers
+    - dmaengine: usb-dmac: Fix PM reference leak in usb_dmac_probe()
+    - ARM: dts: am43x-epos-evm: Reduce i2c0 bus speed for tps65218
+    - dmaengine: of-dma: router_xlate to return -EPROBE_DEFER if controller is not
+      yet available
+    - scsi: megaraid_mm: Fix end of loop tests for list_for_each_entry()
+    - scsi: scsi_dh_rdac: Avoid crash during rdac_bus_attach()
+    - scsi: core: Avoid printing an error if target_alloc() returns -ENXIO
+    - scsi: core: Fix capacity set to zero after offlinining device
+    - ARM: dts: nomadik: Fix up interrupt controller node names
+    - net: usb: lan78xx: don't modify phy_device state concurrently
+    - drm/amd/display: Fix Dynamic bpp issue with 8K30 with Navi 1X
+    - Bluetooth: hidp: use correct wait queue when removing ctrl_wait
+    - iommu: Check if group is NULL before remove device
+    - cpufreq: armada-37xx: forbid cpufreq for 1.2 GHz variant
+    - dccp: add do-while-0 stubs for dccp_pr_debug macros
+    - virtio: Protect vqs list access
+    - vhost: Fix the calculation in vhost_overflow()
+    - bpf: Clear zext_dst of dead insns
+    - bnxt: don't lock the tx queue from napi poll
+    - bnxt: disable napi before canceling DIM
+    - net: 6pack: fix slab-out-of-bounds in decode_data
+    - ptp_pch: Restore dependency on PCI
+    - bnxt_en: Add missing DMA memory barriers
+    - vrf: Reset skb conntrack connection on VRF rcv
+    - virtio-net: support XDP when not more queues
+    - virtio-net: use NETIF_F_GRO_HW instead of NETIF_F_LRO
+    - net: qlcnic: add missed unlock in qlcnic_83xx_flash_read32
+    - net: mdio-mux: Don't ignore memory allocation errors
+    - net: mdio-mux: Handle -EPROBE_DEFER correctly
+    - ovs: clear skb->tstamp in forwarding path
+    - i40e: Fix ATR queue selection
+    - iavf: Fix ping is lost after untrusted VF had tried to change MAC
+    - ovl: add splice file read write helper
+    - mmc: dw_mmc: Fix hang on data CRC error
+    - ALSA: hda - fix the 'Capture Switch' value change notifications
+    - tracing / histogram: Fix NULL pointer dereference on strcmp() on NULL event
+      name
+    - slimbus: messaging: start transaction ids from 1 instead of zero
+    - slimbus: messaging: check for valid transaction id
+    - slimbus: ngd: reset dma setup during runtime pm
+    - ipack: tpci200: fix many double free issues in tpci200_pci_probe
+    - ipack: tpci200: fix memory leak in the tpci200_register
+    - btrfs: prevent rename2 from exchanging a subvol with a directory from
+      different parents
+    - PCI: Increase D3 delay for AMD Renoir/Cezanne XHCI
+    - ASoC: intel: atom: Fix breakage for PCM buffer address setup
+    - mm, memcg: avoid stale protection values when cgroup is above protection
+    - mm: memcontrol: fix occasional OOMs due to proportional memory.low reclaim
+    - fs: warn about impending deprecation of mandatory locks
+    - netfilter: nft_exthdr: fix endianness of tcp option cast
+    - Linux 5.4.143
+  * Focal update: v5.4.142 upstream stable release (LP: #1944202)
+    - iio: adc: ti-ads7950: Ensure CS is deasserted after reading channels
+    - iio: humidity: hdc100x: Add margin to the conversion time
+    - iio: adc: Fix incorrect exit of for-loop
+    - ASoC: xilinx: Fix reference to PCM buffer address
+    - ASoC: intel: atom: Fix reference to PCM buffer address
+    - i2c: dev: zero out array used for i2c reads from userspace
+    - ceph: reduce contention in ceph_check_delayed_caps()
+    - ACPI: NFIT: Fix support for virtual SPA ranges
+    - libnvdimm/region: Fix label activation vs errors
+    - ieee802154: hwsim: fix GPF in hwsim_set_edge_lqi
+    - ieee802154: hwsim: fix GPF in hwsim_new_edge_nl
+    - ASoC: cs42l42: Correct definition of ADC Volume control
+    - ASoC: cs42l42: Don't allow SND_SOC_DAIFMT_LEFT_J
+    - ASoC: cs42l42: Fix inversion of ADC Notch Switch control
+    - ASoC: cs42l42: Remove duplicate control for WNF filter frequency
+    - netfilter: nf_conntrack_bridge: Fix memory leak when error
+    - ASoC: cs42l42: Fix LRCLK frame start edge
+    - net: dsa: mt7530: add the missing RxUnicast MIB counter
+    - platform/x86: pcengines-apuv2: revert wiring up simswitch GPIO as LED
+    - platform/x86: pcengines-apuv2: Add missing terminating entries to gpio-
+      lookup tables
+    - net: phy: micrel: Fix link detection on ksz87xx switch"
+    - ppp: Fix generating ifname when empty IFLA_IFNAME is specified
+    - net: sched: act_mirred: Reset ct info when mirror/redirect skb
+    - iavf: Set RSS LUT and key in reset handle path
+    - psample: Add a fwd declaration for skbuff
+    - net/mlx5: Fix return value from tracer initialization
+    - drm/meson: fix colour distortion from HDR set during vendor u-boot
+    - net: dsa: microchip: Fix ksz_read64()
+    - net: Fix memory leak in ieee802154_raw_deliver
+    - net: igmp: fix data-race in igmp_ifc_timer_expire()
+    - net: dsa: lan9303: fix broken backpressure in .port_fdb_dump
+    - net: dsa: lantiq: fix broken backpressure in .port_fdb_dump
+    - net: dsa: sja1105: fix broken backpressure in .port_fdb_dump
+    - net: bridge: fix memleak in br_add_if()
+    - net: linkwatch: fix failure to restore device state across suspend/resume
+    - tcp_bbr: fix u32 wrap bug in round logic if bbr_init() called after 2B
+      packets
+    - net: igmp: increase size of mr_ifc_count
+    - xen/events: Fix race in set_evtchn_to_irq
+    - vsock/virtio: avoid potential deadlock when vsock device remove
+    - nbd: Aovid double completion of a request
+    - powerpc/kprobes: Fix kprobe Oops happens in booke
+    - x86/tools: Fix objdump version check again
+    - genirq: Provide IRQCHIP_AFFINITY_PRE_STARTUP
+    - x86/msi: Force affinity setup before startup
+    - x86/ioapic: Force affinity setup before startup
+    - x86/resctrl: Fix default monitoring groups reporting
+    - genirq/msi: Ensure deactivation on teardown
+    - genirq/timings: Prevent potential array overflow in __irq_timings_store()
+    - PCI/MSI: Enable and mask MSI-X early
+    - PCI/MSI: Mask all unused MSI-X entries
+    - PCI/MSI: Enforce that MSI-X table entry is masked for update
+    - PCI/MSI: Enforce MSI[X] entry updates to be visible
+    - PCI/MSI: Do not set invalid bits in MSI mask
+    - PCI/MSI: Correct misleading comments
+    - PCI/MSI: Use msi_mask_irq() in pci_msi_shutdown()
+    - PCI/MSI: Protect msi_desc::masked for multi-MSI
+    - KVM: VMX: Use current VMCS to query WAITPKG support for MSR emulation
+    - ceph: add some lockdep assertions around snaprealm handling
+    - ceph: clean up locking annotation for ceph_get_snap_realm and
+      __lookup_snap_realm
+    - ceph: take snap_empty_lock atomically with snaprealm refcount change
+    - vmlinux.lds.h: Handle clang's module.{c,d}tor sections
+    - iommu/vt-d: Fix agaw for a supported 48 bit guest address width
+    - Linux 5.4.142
+  * Focal update: v5.4.141 upstream stable release (LP: #1943484)
+    - KVM: SVM: Fix off-by-one indexing when nullifying last used SEV VMCB
+    - tee: Correct inappropriate usage of TEE_SHM_DMA_BUF flag
+    - media: v4l2-mem2mem: always consider OUTPUT queue during poll
+    - tracing: Reject string operand in the histogram expression
+    - usb: dwc3: Stop active transfers before halting the controller
+    - usb: dwc3: gadget: Allow runtime suspend if UDC unbinded
+    - usb: dwc3: gadget: Restart DWC3 gadget when enabling pullup
+    - usb: dwc3: gadget: Prevent EP queuing while stopping transfers
+    - usb: dwc3: gadget: Clear DEP flags after stop transfers in ep disable
+    - usb: dwc3: gadget: Disable gadget IRQ during pullup disable
+    - usb: dwc3: gadget: Avoid runtime resume if disabling pullup
+    - KVM: X86: MMU: Use the correct inherited permissions to get shadow page
+    - USB:ehci:fix Kunpeng920 ehci hardware problem
+    - ALSA: hda: Add quirk for ASUS Flow x13
+    - ppp: Fix generating ppp unit id when ifname is not specified
+    - ovl: prevent private clone if bind mount is not allowed
+    - btrfs: make qgroup_free_reserved_data take btrfs_inode
+    - btrfs: make btrfs_qgroup_reserve_data take btrfs_inode
+    - btrfs: qgroup: allow to unreserve range without releasing other ranges
+    - btrfs: qgroup: try to flush qgroup space when we get -EDQUOT
+    - btrfs: transaction: Cleanup unused TRANS_STATE_BLOCKED
+    - btrfs: qgroup: remove ASYNC_COMMIT mechanism in favor of reserve retry-
+      after-EDQUOT
+    - btrfs: fix lockdep splat when enabling and disabling qgroups
+    - net: xilinx_emaclite: Do not print real IOMEM pointer
+    - btrfs: qgroup: don't commit transaction when we already hold the handle
+    - btrfs: export and rename qgroup_reserve_meta
+    - btrfs: don't flush from btrfs_delayed_inode_reserve_metadata
+    - Linux 5.4.141
+
+ -- Wen-chien Jesse Sung <jesse.sung@canonical.com>  Mon, 12 Sep 2022 20:10:56 +0800
+
+linux-xilinx-zynqmp (5.4.0-1017.20) focal; urgency=medium
+
+  * INVALID or PRIVATE BUG (LP: #1949221)
+    - [Config] Enable NFS Server configs
+
+  * Miscellaneous upstream changes
+    - usb: dwc3: gadget: Don't send unintended link state change
+    - usb: dwc3: gadget: Set link state to RX_Detect on disconnect
+    - usb: dwc3: gadget: Clear DCTL.ULSTCHNGREQ before set
+    - spi: spi-zynqmp-gqspi: Set tapdelay as per spi-max-frequency
+    - spi: spi-cadence: Fix SPI CS gets toggling sporadically
+
+  [ Ubuntu: 5.4.0-88.99 ]
+
+  * focal/linux: 5.4.0-88.99 -proposed tracker (LP: #1944747)
+  * Packaging resync (LP: #1786013)
+    - debian/dkms-versions -- update from kernel-versions (main/2021.09.06)
+  * please drop virtualbox-guest-dkms virtualbox-guest-source (LP: #1933248)
+    - Revert "UBUNTU: [Config] Disable virtualbox dkms build"
+
+  [ Ubuntu: 5.4.0-87.98 ]
+
+  * please drop virtualbox-guest-dkms virtualbox-guest-source (LP: #1933248)
+    - [Config] Disable virtualbox dkms build
+  * Packaging resync (LP: #1786013)
+    - debian/dkms-versions -- update from kernel-versions (main/2021.09.06)
+  *  LRMv5: switch primary version handling to kernel-versions data set
+    (LP: #1928921)
+    - [Packaging] switch to kernel-versions
+  * disable “CONFIG_HISI_DMA” config for ubuntu version (LP: #1936771)
+    - Disable CONFIG_HISI_DMA
+    - [Config] Record hisi_dma no longer built for arm64
+  * memory leaking when removing a profile (LP: #1939915)
+    - apparmor: Fix memory leak of profile proxy
+  * CryptoExpress EP11 cards are going offline (LP: #1939618)
+    - s390/zcrypt: Support for CCA protected key block version 2
+    - s390: Replace zero-length array with flexible-array member
+    - s390/zcrypt: Use scnprintf() for avoiding potential buffer overflow
+    - s390/zcrypt: replace snprintf/sprintf with scnprintf
+    - s390/ap: Remove ap device suspend and resume callbacks
+    - s390/zcrypt: use fallthrough;
+    - s390/zcrypt: use kvmalloc instead of kmalloc for 256k alloc
+    - s390/ap: remove power management code from ap bus and drivers
+    - s390/ap: introduce new ap function ap_get_qdev()
+    - s390/zcrypt: use kzalloc
+    - s390/zcrypt: fix smatch warnings
+    - s390/zcrypt: code beautification and struct field renames
+    - s390/zcrypt: split ioctl function into smaller code units
+    - s390/ap: rename and clarify ap state machine related stuff
+    - s390/zcrypt: provide cex4 cca sysfs attributes for cex3
+    - s390/ap: rework crypto config info and default domain code
+    - s390/zcrypt: simplify cca_findcard2 loop code
+    - s390/zcrypt: remove set_fs() invocation in zcrypt device driver
+    - s390/ap: remove unnecessary spin_lock_init()
+    - s390/zcrypt: Support for CCA APKA master keys
+    - s390/zcrypt: introduce msg tracking in zcrypt functions
+    - s390/ap: split ap queue state machine state from device state
+    - s390/ap: add error response code field for ap queue devices
+    - s390/ap: add card/queue deconfig state
+    - s390/sclp: Add support for SCLP AP adapter config/deconfig
+    - s390/ap: Support AP card SCLP config and deconfig operations
+    - s390/ap/zcrypt: revisit ap and zcrypt error handling
+    - s390/zcrypt: move ap_msg param one level up the call chain
+    - s390/zcrypt: Introduce Failure Injection feature
+    - s390/zcrypt: fix wrong format specifications
+    - s390/ap: fix ap devices reference counting
+    - s390/zcrypt: return EIO when msg retry limit reached
+    - s390/zcrypt: fix zcard and zqueue hot-unplug memleak
+    - s390/ap: Fix hanging ioctl caused by wrong msg counter
+  * memfd from ubuntu_kernel_selftests failed to build on B-5.4 (LP: #1926142)
+    - SAUCE: selftests/memfd: fix build when F_SEAL_FUTURE_WRITE is not defined
+  * [SRU] Ice driver causes the kernel to crash with Ubuntu 20.04.2 with ethtool
+    specific register commands (LP: #1939855)
+    - ice: Fix bad register reads
+  * ubunut_kernel_selftests: memory-hotplug: avoid spamming logs with
+    dump_page() (LP: #1941829)
+    - selftests: memory-hotplug: avoid spamming logs with dump_page(), ratio limit
+      hot-remove error test
+  * e1000e blocks the boot process when it tried to write checksum to its NVM
+    (LP: #1936998)
+    - e1000e: Do not take care about recovery NVM checksum
+  * Focal update: v5.4.140 upstream stable release (LP: #1941798)
+    - Revert "ACPICA: Fix memory leak caused by _CID repair function"
+    - ALSA: seq: Fix racy deletion of subscriber
+    - arm64: dts: ls1028a: fix node name for the sysclk
+    - ARM: imx: add missing iounmap()
+    - ARM: imx: add missing clk_disable_unprepare()
+    - ARM: dts: imx6qdl-sr-som: Increase the PHY reset duration to 10ms
+    - ARM: dts: colibri-imx6ull: limit SDIO clock to 25MHz
+    - ARM: imx: fix missing 3rd argument in macro imx_mmdc_perf_init
+    - ARM: dts: imx: Swap M53Menlo pinctrl_power_button/pinctrl_power_out pins
+    - arm64: dts: armada-3720-turris-mox: remove mrvl,i2c-fast-mode
+    - ALSA: usb-audio: fix incorrect clock source setting
+    - clk: stm32f4: fix post divisor setup for I2S/SAI PLLs
+    - ARM: dts: am437x-l4: fix typo in can@0 node
+    - omap5-board-common: remove not physically existing vdds_1v8_main fixed-
+      regulator
+    - spi: imx: mx51-ecspi: Reinstate low-speed CONFIGREG delay
+    - spi: imx: mx51-ecspi: Fix low-speed CONFIGREG delay calculation
+    - scsi: sr: Return correct event when media event code is 3
+    - media: videobuf2-core: dequeue if start_streaming fails
+    - dmaengine: imx-dma: configure the generic DMA type to make it work
+    - net, gro: Set inner transport header offset in tcp/udp GRO hook
+    - net: dsa: sja1105: overwrite dynamic FDB entries with static ones in
+      .port_fdb_add
+    - net: dsa: sja1105: invalidate dynamic FDB entries learned concurrently with
+      statically added ones
+    - net: phy: micrel: Fix detection of ksz87xx switch
+    - net: natsemi: Fix missing pci_disable_device() in probe and remove
+    - gpio: tqmx86: really make IRQ optional
+    - sctp: move the active_key update after sh_keys is added
+    - nfp: update ethtool reporting of pauseframe control
+    - net: ipv6: fix returned variable type in ip6_skb_dst_mtu
+    - mips: Fix non-POSIX regexp
+    - bnx2x: fix an error code in bnx2x_nic_load()
+    - net: pegasus: fix uninit-value in get_interrupt_interval
+    - net: fec: fix use-after-free in fec_drv_remove
+    - net: vxge: fix use-after-free in vxge_device_unregister
+    - blk-iolatency: error out if blk_get_queue() failed in iolatency_set_limit()
+    - Bluetooth: defer cleanup of resources in hci_unregister_dev()
+    - USB: usbtmc: Fix RCU stall warning
+    - USB: serial: option: add Telit FD980 composition 0x1056
+    - USB: serial: ch341: fix character loss at high transfer rates
+    - USB: serial: ftdi_sio: add device ID for Auto-M3 OP-COM v2
+    - firmware_loader: use -ETIMEDOUT instead of -EAGAIN in fw_load_sysfs_fallback
+    - firmware_loader: fix use-after-free in firmware_fallback_sysfs
+    - ALSA: hda/realtek: add mic quirk for Acer SF314-42
+    - ALSA: usb-audio: Add registration quirk for JBL Quantum 600
+    - usb: cdns3: Fixed incorrect gadget state
+    - usb: gadget: f_hid: added GET_IDLE and SET_IDLE handlers
+    - usb: gadget: f_hid: fixed NULL pointer dereference
+    - usb: gadget: f_hid: idle uses the highest byte for duration
+    - usb: otg-fsm: Fix hrtimer list corruption
+    - clk: fix leak on devm_clk_bulk_get_all() unwind
+    - scripts/tracing: fix the bug that can't parse raw_trace_func
+    - tracing / histogram: Give calculation hist_fields a size
+    - optee: Clear stale cache entries during initialization
+    - tee: add tee_shm_alloc_kernel_buf()
+    - optee: Fix memory leak when failing to register shm pages
+    - tpm_ftpm_tee: Free and unregister TEE shared memory during kexec
+    - staging: rtl8723bs: Fix a resource leak in sd_int_dpc
+    - staging: rtl8712: get rid of flush_scheduled_work
+    - media: rtl28xxu: fix zero-length control request
+    - pipe: increase minimum default pipe size to 2 pages
+    - ext4: fix potential htree corruption when growing large_dir directories
+    - serial: tegra: Only print FIFO error message when an error occurs
+    - serial: 8250_mtk: fix uart corruption issue when rx power off
+    - serial: 8250: Mask out floating 16/32-bit bus bits
+    - MIPS: Malta: Do not byte-swap accesses to the CBUS UART
+    - serial: 8250_pci: Enumerate Elkhart Lake UARTs via dedicated driver
+    - serial: 8250_pci: Avoid irq sharing for MSI(-X) interrupts.
+    - timers: Move clearing of base::timer_running under base:: Lock
+    - pcmcia: i82092: fix a null pointer dereference bug
+    - md/raid10: properly indicate failure when ending a failed write request
+    - KVM: x86: accept userspace interrupt only if no event is injected
+    - KVM: Do not leak memory for duplicate debugfs directories
+    - KVM: x86/mmu: Fix per-cpu counter corruption on 32-bit builds
+    - arm64: vdso: Avoid ISB after reading from cntvct_el0
+    - soc: ixp4xx: fix printing resources
+    - spi: meson-spicc: fix memory leak in meson_spicc_remove
+    - soc: ixp4xx/qmgr: fix invalid __iomem access
+    - perf/x86/amd: Don't touch the AMD64_EVENTSEL_HOSTONLY bit inside the guest
+    - bpf, selftests: Adjust few selftest result_unpriv outcomes
+    - libata: fix ata_pio_sector for CONFIG_HIGHMEM
+    - reiserfs: add check for root_inode in reiserfs_fill_super
+    - reiserfs: check directory items on read from disk
+    - virt_wifi: fix error on connect
+    - alpha: Send stop IPI to send to online CPUs
+    - net/qla3xxx: fix schedule while atomic in ql_wait_for_drvr_lock and
+      ql_adapter_reset
+    - arm64: fix compat syscall return truncation
+    - Linux 5.4.140
+  * Focal update: v5.4.139 upstream stable release (LP: #1941796)
+    - btrfs: delete duplicated words + other fixes in comments
+    - btrfs: do not commit logs and transactions during link and rename operations
+    - btrfs: fix race causing unnecessary inode logging during link and rename
+    - btrfs: fix lost inode on log replay after mix of fsync, rename and inode
+      eviction
+    - regulator: rt5033: Fix n_voltages settings for BUCK and LDO
+    - spi: stm32h7: fix full duplex irq handler handling
+    - ASoC: tlv320aic31xx: fix reversed bclk/wclk master bits
+    - r8152: Fix potential PM refcount imbalance
+    - qed: fix possible unpaired spin_{un}lock_bh in _qed_mcp_cmd_and_union()
+    - net: Fix zero-copy head len calculation.
+    - nvme: fix nvme_setup_command metadata trace event
+    - ACPI: fix NULL pointer dereference
+    - Revert "Bluetooth: Shutdown controller after workqueues are flushed or
+      cancelled"
+    - firmware: arm_scmi: Ensure drivers provide a probe function
+    - firmware: arm_scmi: Add delayed response status check
+    - bpf: Inherit expanded/patched seen count from old aux data
+    - bpf: Do not mark insn as seen under speculative path verification
+    - bpf: Fix leakage under speculation on mispredicted branches
+    - bpf: Test_verifier, add alu32 bounds tracking tests
+    - bpf, selftests: Add a verifier test for assigning 32bit reg states to 64bit
+      ones
+    - bpf, selftests: Adjust few selftest outcomes wrt unreachable code
+    - spi: mediatek: Fix fifo transfer
+    - Linux 5.4.139
+  * Focal update: v5.4.138 upstream stable release (LP: #1940559)
+    - net_sched: check error pointer in tcf_dump_walker()
+    - x86/asm: Ensure asm/proto.h can be included stand-alone
+    - btrfs: fix rw device counting in __btrfs_free_extra_devids
+    - btrfs: mark compressed range uptodate only if all bio succeed
+    - x86/kvm: fix vcpu-id indexed array sizes
+    - KVM: add missing compat KVM_CLEAR_DIRTY_LOG
+    - ocfs2: fix zero out valid data
+    - ocfs2: issue zeroout to EOF blocks
+    - can: j1939: j1939_xtp_rx_dat_one(): fix rxtimer value between consecutive
+      TP.DT to 750ms
+    - can: raw: raw_setsockopt(): fix raw_rcv panic for sock UAF
+    - can: mcba_usb_start(): add missing urb->transfer_dma initialization
+    - can: usb_8dev: fix memory leak
+    - can: ems_usb: fix memory leak
+    - can: esd_usb2: fix memory leak
+    - HID: wacom: Re-enable touch by default for Cintiq 24HDT / 27QHDT
+    - NIU: fix incorrect error return, missed in previous revert
+    - nfc: nfcsim: fix use after free during module unload
+    - cfg80211: Fix possible memory leak in function cfg80211_bss_update
+    - netfilter: conntrack: adjust stop timestamp to real expiry value
+    - netfilter: nft_nat: allow to specify layer 4 protocol NAT only
+    - i40e: Fix logic of disabling queues
+    - i40e: Fix firmware LLDP agent related warning
+    - i40e: Fix queue-to-TC mapping on Tx
+    - i40e: Fix log TC creation failure when max num of queues is exceeded
+    - tipc: fix sleeping in tipc accept routine
+    - net: Set true network header for ECN decapsulation
+    - mlx4: Fix missing error code in mlx4_load_one()
+    - net: llc: fix skb_over_panic
+    - net/mlx5: Fix flow table chaining
+    - net/mlx5e: Fix nullptr in mlx5e_hairpin_get_mdev()
+    - sctp: fix return value check in __sctp_rcv_asconf_lookup
+    - tulip: windbond-840: Fix missing pci_disable_device() in probe and remove
+    - sis900: Fix missing pci_disable_device() in probe and remove
+    - can: hi311x: fix a signedness bug in hi3110_cmd()
+    - PCI: mvebu: Setup BAR0 in order to fix MSI
+    - powerpc/pseries: Fix regression while building external modules
+    - i40e: Add additional info to PHY type error
+    - can: j1939: j1939_session_deactivate(): clarify lifetime of session object
+    - Linux 5.4.138
+  * Focal update: v5.4.137 upstream stable release (LP: #1940557)
+    - selftest: fix build error in tools/testing/selftests/vm/userfaultfd.c
+    - tools: Allow proper CC/CXX/... override with LLVM=1 in Makefile.include
+    - KVM: x86: determine if an exception has an error code only when injecting
+      it.
+    - af_unix: fix garbage collect vs MSG_PEEK
+    - workqueue: fix UAF in pwq_unbound_release_workfn()
+    - cgroup1: fix leaked context root causing sporadic NULL deref in LTP
+    - net/802/mrp: fix memleak in mrp_request_join()
+    - net/802/garp: fix memleak in garp_request_join()
+    - net: annotate data race around sk_ll_usec
+    - sctp: move 198 addresses from unusable to private scope
+    - ipv6: allocate enough headroom in ip6_finish_output2()
+    - hfs: add missing clean-up in hfs_fill_super
+    - hfs: fix high memory mapping in hfs_bnode_read
+    - hfs: add lock nesting notation to hfs_find_init
+    - firmware: arm_scmi: Fix possible scmi_linux_errmap buffer overflow
+    - firmware: arm_scmi: Fix range check for the maximum number of pending
+      messages
+    - cifs: fix the out of range assignment to bit fields in
+      parse_server_interfaces
+    - iomap: remove the length variable in iomap_seek_data
+    - iomap: remove the length variable in iomap_seek_hole
+    - ARM: dts: versatile: Fix up interrupt controller node names
+    - ipv6: ip6_finish_output2: set sk into newly allocated nskb
+    - Linux 5.4.137
+  * Focal update: v5.4.136 upstream stable release (LP: #1939899)
+    - igc: Fix use-after-free error during reset
+    - igb: Fix use-after-free error during reset
+    - igc: change default return of igc_read_phy_reg()
+    - ixgbe: Fix an error handling path in 'ixgbe_probe()'
+    - igc: Prefer to use the pci_release_mem_regions method
+    - igc: Fix an error handling path in 'igc_probe()'
+    - igb: Fix an error handling path in 'igb_probe()'
+    - fm10k: Fix an error handling path in 'fm10k_probe()'
+    - e1000e: Fix an error handling path in 'e1000_probe()'
+    - iavf: Fix an error handling path in 'iavf_probe()'
+    - igb: Check if num of q_vectors is smaller than max before array access
+    - igb: Fix position of assignment to *ring
+    - gve: Fix an error handling path in 'gve_probe()'
+    - ipv6: fix 'disable_policy' for fwd packets
+    - selftests: icmp_redirect: remove from checking for IPv6 route get
+    - selftests: icmp_redirect: IPv6 PMTU info should be cleared after redirect
+    - pwm: sprd: Ensure configuring period and duty_cycle isn't wrongly skipped
+    - cxgb4: fix IRQ free race during driver unload
+    - nvme-pci: do not call nvme_dev_remove_admin from nvme_remove
+    - perf probe: Fix dso->nsinfo refcounting
+    - perf env: Fix sibling_dies memory leak
+    - perf test session_topology: Delete session->evlist
+    - perf test event_update: Fix memory leak of evlist
+    - perf dso: Fix memory leak in dso__new_map()
+    - perf script: Fix memory 'threads' and 'cpus' leaks on exit
+    - perf lzma: Close lzma stream on exit
+    - perf probe-file: Delete namelist in del_events() on the error path
+    - perf data: Close all files in close_dir()
+    - spi: imx: add a check for speed_hz before calculating the clock
+    - spi: stm32: Use dma_request_chan() instead dma_request_slave_channel()
+    - spi: stm32: fixes pm_runtime calls in probe/remove
+    - regulator: hi6421: Use correct variable type for regmap api val argument
+    - regulator: hi6421: Fix getting wrong drvdata
+    - spi: mediatek: fix fifo rx mode
+    - ASoC: rt5631: Fix regcache sync errors on resume
+    - liquidio: Fix unintentional sign extension issue on left shift of u16
+    - s390/bpf: Perform r1 range checking before accessing jit->seen_reg[r1]
+    - bpf, sockmap, tcp: sk_prot needs inuse_idx set for proc stats
+    - bpftool: Check malloc return value in mount_bpffs_for_pin
+    - net: fix uninit-value in caif_seqpkt_sendmsg
+    - efi/tpm: Differentiate missing and invalid final event log table.
+    - net: decnet: Fix sleeping inside in af_decnet
+    - KVM: PPC: Book3S: Fix CONFIG_TRANSACTIONAL_MEM=n crash
+    - KVM: PPC: Fix kvm_arch_vcpu_ioctl vcpu_load leak
+    - net: sched: fix memory leak in tcindex_partial_destroy_work
+    - netrom: Decrease sock refcount when sock timers expire
+    - scsi: iscsi: Fix iface sysfs attr detection
+    - scsi: target: Fix protect handling in WRITE SAME(32)
+    - spi: cadence: Correct initialisation of runtime PM again
+    - bnxt_en: Improve bnxt_ulp_stop()/bnxt_ulp_start() call sequence.
+    - bnxt_en: Refresh RoCE capabilities in bnxt_ulp_probe()
+    - bnxt_en: Add missing check for BNXT_STATE_ABORT_ERR in bnxt_fw_rset_task()
+    - bnxt_en: Check abort error state in bnxt_half_open_nic()
+    - net: hisilicon: rename CACHE_LINE_MASK to avoid redefinition
+    - net/tcp_fastopen: fix data races around tfo_active_disable_stamp
+    - net: hns3: fix rx VLAN offload state inconsistent issue
+    - net/sched: act_skbmod: Skip non-Ethernet packets
+    - ipv6: fix another slab-out-of-bounds in fib6_nh_flush_exceptions
+    - nvme-pci: don't WARN_ON in nvme_reset_work if ctrl.state is not RESETTING
+    - Revert "USB: quirks: ignore remote wake-up on Fibocom L850-GL LTE modem"
+    - afs: Fix tracepoint string placement with built-in AFS
+    - r8169: Avoid duplicate sysfs entry creation error
+    - nvme: set the PRACT bit when using Write Zeroes with T10 PI
+    - sctp: update active_key for asoc when old key is being replaced
+    - net: sched: cls_api: Fix the the wrong parameter
+    - drm/panel: raspberrypi-touchscreen: Prevent double-free
+    - proc: Avoid mixing integer types in mem_rw()
+    - s390/ftrace: fix ftrace_update_ftrace_func implementation
+    - s390/boot: fix use of expolines in the DMA code
+    - ALSA: usb-audio: Add missing proc text entry for BESPOKEN type
+    - ALSA: usb-audio: Add registration quirk for JBL Quantum headsets
+    - ALSA: sb: Fix potential ABBA deadlock in CSP driver
+    - ALSA: hdmi: Expose all pins on MSI MS-7C94 board
+    - xhci: Fix lost USB 2 remote wake
+    - KVM: PPC: Book3S: Fix H_RTAS rets buffer overflow
+    - KVM: PPC: Book3S HV Nested: Sanitise H_ENTER_NESTED TM state
+    - usb: hub: Disable USB 3 device initiated lpm if exit latency is too high
+    - usb: hub: Fix link power management max exit latency (MEL) calculations
+    - USB: usb-storage: Add LaCie Rugged USB3-FW to IGNORE_UAS
+    - usb: max-3421: Prevent corruption of freed memory
+    - usb: renesas_usbhs: Fix superfluous irqs happen after usb_pkt_pop()
+    - USB: serial: option: add support for u-blox LARA-R6 family
+    - USB: serial: cp210x: fix comments for GE CS1000
+    - USB: serial: cp210x: add ID for CEL EM3588 USB ZigBee stick
+    - usb: dwc2: gadget: Fix sending zero length packet in DDMA mode.
+    - firmware/efi: Tell memblock about EFI iomem reservations
+    - tracing/histogram: Rename "cpu" to "common_cpu"
+    - tracing: Fix bug in rb_per_cpu_empty() that might cause deadloop.
+    - btrfs: check for missing device in btrfs_trim_fs
+    - media: ngene: Fix out-of-bounds bug in ngene_command_config_free_buf()
+    - ixgbe: Fix packet corruption due to missing DMA sync
+    - selftest: use mmap instead of posix_memalign to allocate memory
+    - userfaultfd: do not untag user pointers
+    - hugetlbfs: fix mount mode command line processing
+    - rbd: don't hold lock_rwsem while running_list is being drained
+    - rbd: always kick acquire on "acquired" and "released" notifications
+    - nds32: fix up stack guard gap
+    - drm: Return -ENOTTY for non-drm ioctls
+    - net: dsa: mv88e6xxx: use correct .stats_set_histogram() on Topaz
+    - net: bcmgenet: ensure EXT_ENERGY_DET_MASK is clear
+    - iio: accel: bma180: Use explicit member assignment
+    - iio: accel: bma180: Fix BMA25x bandwidth register values
+    - btrfs: compression: don't try to compress if we don't have enough pages
+    - PCI: Mark AMD Navi14 GPU ATS as broken
+    - perf inject: Close inject.output on exit
+    - xhci: add xhci_get_virt_ep() helper
+    - Linux 5.4.136
+  * Focal update: v5.4.135 upstream stable release (LP: #1939442)
+    - ARM: dts: gemini: rename mdio to the right name
+    - ARM: dts: gemini: add device_type on pci
+    - ARM: dts: rockchip: fix pinctrl sleep nodename for rk3036-kylin and rk3288
+    - arm64: dts: rockchip: fix pinctrl sleep nodename for rk3399.dtsi
+    - ARM: dts: rockchip: Fix the timer clocks order
+    - ARM: dts: rockchip: Fix IOMMU nodes properties on rk322x
+    - ARM: dts: rockchip: Fix power-controller node names for rk3066a
+    - ARM: dts: rockchip: Fix power-controller node names for rk3188
+    - ARM: dts: rockchip: Fix power-controller node names for rk3288
+    - arm64: dts: rockchip: Fix power-controller node names for px30
+    - arm64: dts: rockchip: Fix power-controller node names for rk3328
+    - reset: ti-syscon: fix to_ti_syscon_reset_data macro
+    - ARM: brcmstb: dts: fix NAND nodes names
+    - ARM: Cygnus: dts: fix NAND nodes names
+    - ARM: NSP: dts: fix NAND nodes names
+    - ARM: dts: BCM63xx: Fix NAND nodes names
+    - ARM: dts: Hurricane 2: Fix NAND nodes names
+    - ARM: dts: imx6: phyFLEX: Fix UART hardware flow control
+    - ARM: imx: pm-imx5: Fix references to imx5_cpu_suspend_info
+    - rtc: mxc_v2: add missing MODULE_DEVICE_TABLE
+    - kbuild: sink stdout from cmd for silent build
+    - ARM: dts: am57xx-cl-som-am57x: fix ti,no-reset-on-init flag for gpios
+    - ARM: dts: am437x-gp-evm: fix ti,no-reset-on-init flag for gpios
+    - ARM: dts: stm32: fix gpio-keys node on STM32 MCU boards
+    - ARM: dts: stm32: fix RCC node name on stm32f429 MCU
+    - ARM: dts: stm32: fix timer nodes on STM32 MCU to prevent warnings
+    - arm64: dts: juno: Update SCPI nodes as per the YAML schema
+    - ARM: dts: rockchip: fix supply properties in io-domains nodes
+    - ARM: dts: stm32: fix i2c node name on stm32f746 to prevent warnings
+    - ARM: dts: stm32: move stmmac axi config in ethernet node on stm32mp15
+    - soc/tegra: fuse: Fix Tegra234-only builds
+    - firmware: tegra: bpmp: Fix Tegra234-only builds
+    - arm64: dts: ls208xa: remove bus-num from dspi node
+    - arm64: dts: imx8mq: assign PCIe clocks
+    - thermal/core: Correct function name thermal_zone_device_unregister()
+    - kbuild: mkcompile_h: consider timestamp if KBUILD_BUILD_TIMESTAMP is set
+    - rtc: max77686: Do not enforce (incorrect) interrupt trigger type
+    - scsi: aic7xxx: Fix unintentional sign extension issue on left shift of u8
+    - scsi: libsas: Add LUN number check in .slave_alloc callback
+    - scsi: libfc: Fix array index out of bound exception
+    - scsi: qedf: Add check to synchronize abort and flush
+    - sched/fair: Fix CFS bandwidth hrtimer expiry type
+    - s390: introduce proper type handling call_on_stack() macro
+    - cifs: prevent NULL deref in cifs_compose_mount_options()
+    - arm64: dts: armada-3720-turris-mox: add firmware node
+    - firmware: turris-mox-rwtm: add marvell,armada-3700-rwtm-firmware compatible
+      string
+    - arm64: dts: marvell: armada-37xx: move firmware node to generic dtsi file
+    - f2fs: Show casefolding support only when supported
+    - usb: cdns3: Enable TDL_CHK only for OUT ep
+    - Revert "UBUNTU: SAUCE: Revert "mm: memcg/slab: fix memory leak at non-root
+      kmem_cache destroy""
+    - mm: slab: fix kmem_cache_create failed when sysfs node not destroyed
+    - dm writecache: return the exact table values that were set
+    - net: dsa: mv88e6xxx: enable .port_set_policy() on Topaz
+    - net: dsa: mv88e6xxx: enable .rmu_disable() on Topaz
+    - net: ipv6: fix return value of ip6_skb_dst_mtu
+    - netfilter: ctnetlink: suspicious RCU usage in ctnetlink_dump_helpinfo
+    - net/sched: act_ct: fix err check for nf_conntrack_confirm
+    - net: bridge: sync fdb to new unicast-filtering ports
+    - net: bcmgenet: Ensure all TX/RX queues DMAs are disabled
+    - net: ip_tunnel: fix mtu calculation for ETHER tunnel devices
+    - net: moxa: fix UAF in moxart_mac_probe
+    - net: qcom/emac: fix UAF in emac_remove
+    - net: ti: fix UAF in tlan_remove_one
+    - net: send SYNACK packet with accepted fwmark
+    - net: validate lwtstate->data before returning from skb_tunnel_info()
+    - net: fddi: fix UAF in fza_probe
+    - dma-buf/sync_file: Don't leak fences on merge failure
+    - tcp: annotate data races around tp->mtu_info
+    - ipv6: tcp: drop silly ICMPv6 packet too big messages
+    - bpftool: Properly close va_list 'ap' by va_end() on error
+    - perf test bpf: Free obj_buf
+    - udp: annotate data races around unix_sk(sk)->gso_size
+    - Linux 5.4.135
+  * Focal update: v5.4.134 upstream stable release (LP: #1939440)
+    - KVM: mmio: Fix use-after-free Read in kvm_vm_ioctl_unregister_coalesced_mmio
+    - KVM: x86: Use guest MAXPHYADDR from CPUID.0x8000_0008 iff TDP is enabled
+    - KVM: X86: Disable hardware breakpoints unconditionally before kvm_x86->run()
+    - scsi: core: Fix bad pointer dereference when ehandler kthread is invalid
+    - tracing: Do not reference char * as a string in histograms
+    - cgroup: verify that source is a string
+    - fbmem: Do not delete the mode that is still in use
+    - net: moxa: Use devm_platform_get_and_ioremap_resource()
+    - dmaengine: fsl-qdma: check dma_set_mask return value
+    - srcu: Fix broken node geometry after early ssp init
+    - tty: serial: fsl_lpuart: fix the potential risk of division or modulo by
+      zero
+    - misc/libmasm/module: Fix two use after free in ibmasm_init_one
+    - misc: alcor_pci: fix null-ptr-deref when there is no PCI bridge
+    - iio: gyro: fxa21002c: Balance runtime pm + use pm_runtime_resume_and_get().
+    - iio: magn: bmc150: Balance runtime pm + use pm_runtime_resume_and_get()
+    - ALSA: usx2y: Don't call free_pages_exact() with NULL address
+    - Revert "ALSA: bebob/oxfw: fix Kconfig entry for Mackie d.2 Pro"
+    - w1: ds2438: fixing bug that would always get page0
+    - scsi: hisi_sas: Propagate errors in interrupt_init_v1_hw()
+    - scsi: lpfc: Fix "Unexpected timeout" error in direct attach topology
+    - scsi: lpfc: Fix crash when lpfc_sli4_hba_setup() fails to initialize the
+      SGLs
+    - scsi: core: Cap scsi_host cmd_per_lun at can_queue
+    - ALSA: ac97: fix PM reference leak in ac97_bus_remove()
+    - tty: serial: 8250: serial_cs: Fix a memory leak in error handling path
+    - scsi: scsi_dh_alua: Check for negative result value
+    - fs/jfs: Fix missing error code in lmLogInit()
+    - scsi: megaraid_sas: Fix resource leak in case of probe failure
+    - scsi: megaraid_sas: Early detection of VD deletion through RaidMap update
+    - scsi: megaraid_sas: Handle missing interrupts while re-enabling IRQs
+    - scsi: iscsi: Add iscsi_cls_conn refcount helpers
+    - scsi: iscsi: Fix conn use after free during resets
+    - scsi: iscsi: Fix shost->max_id use
+    - scsi: qedi: Fix null ref during abort handling
+    - mfd: da9052/stmpe: Add and modify MODULE_DEVICE_TABLE
+    - mfd: cpcap: Fix cpcap dmamask not set warnings
+    - ASoC: img: Fix PM reference leak in img_i2s_in_probe()
+    - serial: tty: uartlite: fix console setup
+    - s390/sclp_vt220: fix console name to match device
+    - ALSA: sb: Fix potential double-free of CSP mixer elements
+    - powerpc/ps3: Add dma_mask to ps3_dma_region
+    - iommu/arm-smmu: Fix arm_smmu_device refcount leak when arm_smmu_rpm_get
+      fails
+    - iommu/arm-smmu: Fix arm_smmu_device refcount leak in address translation
+    - gpio: zynq: Check return value of pm_runtime_get_sync
+    - ALSA: ppc: fix error return code in snd_pmac_probe()
+    - selftests/powerpc: Fix "no_handler" EBB selftest
+    - gpio: pca953x: Add support for the On Semi pca9655
+    - ASoC: soc-core: Fix the error return code in
+      snd_soc_of_parse_audio_routing()
+    - s390/processor: always inline stap() and __load_psw_mask()
+    - s390/ipl_parm: fix program check new psw handling
+    - s390/mem_detect: fix diag260() program check new psw handling
+    - s390/mem_detect: fix tprot() program check new psw handling
+    - Input: hideep - fix the uninitialized use in hideep_nvm_unlock()
+    - ALSA: bebob: add support for ToneWeal FW66
+    - ALSA: usb-audio: scarlett2: Fix 18i8 Gen 2 PCM Input count
+    - ALSA: usb-audio: scarlett2: Fix data_mutex lock
+    - ALSA: usb-audio: scarlett2: Fix scarlett2_*_ctl_put() return values
+    - usb: gadget: f_hid: fix endianness issue with descriptors
+    - usb: gadget: hid: fix error return code in hid_bind()
+    - powerpc/boot: Fixup device-tree on little endian
+    - ASoC: Intel: kbl_da7219_max98357a: shrink platform_id below 20 characters
+    - backlight: lm3630a: Fix return code of .update_status() callback
+    - ALSA: hda: Add IRQ check for platform_get_irq()
+    - ALSA: usb-audio: scarlett2: Fix 6i6 Gen 2 line out descriptions
+    - staging: rtl8723bs: fix macro value for 2.4Ghz only device
+    - intel_th: Wait until port is in reset before programming it
+    - i2c: core: Disable client irq on reboot/shutdown
+    - power: supply: sc27xx: Add missing MODULE_DEVICE_TABLE
+    - power: supply: sc2731_charger: Add missing MODULE_DEVICE_TABLE
+    - pwm: spear: Don't modify HW state in .remove callback
+    - power: supply: ab8500: Avoid NULL pointers
+    - power: supply: max17042: Do not enforce (incorrect) interrupt trigger type
+    - power: reset: gpio-poweroff: add missing MODULE_DEVICE_TABLE
+    - ARM: 9087/1: kprobes: test-thumb: fix for LLVM_IAS=1
+    - PCI/P2PDMA: Avoid pci_get_slot(), which may sleep
+    - watchdog: Fix possible use-after-free in wdt_startup()
+    - watchdog: sc520_wdt: Fix possible use-after-free in wdt_turnoff()
+    - watchdog: Fix possible use-after-free by calling del_timer_sync()
+    - watchdog: imx_sc_wdt: fix pretimeout
+    - x86/fpu: Return proper error codes from user access functions
+    - PCI: tegra: Add missing MODULE_DEVICE_TABLE
+    - orangefs: fix orangefs df output.
+    - ceph: remove bogus checks and WARN_ONs from ceph_set_page_dirty
+    - NFS: nfs_find_open_context() may only select open files
+    - power: supply: charger-manager: add missing MODULE_DEVICE_TABLE
+    - power: supply: ab8500: add missing MODULE_DEVICE_TABLE
+    - pwm: img: Fix PM reference leak in img_pwm_enable()
+    - pwm: tegra: Don't modify HW state in .remove callback
+    - ACPI: AMBA: Fix resource name in /proc/iomem
+    - ACPI: video: Add quirk for the Dell Vostro 3350
+    - virtio-blk: Fix memory leak among suspend/resume procedure
+    - virtio_net: Fix error handling in virtnet_restore()
+    - virtio_console: Assure used length from device is limited
+    - x86/signal: Detect and prevent an alternate signal stack overflow
+    - f2fs: add MODULE_SOFTDEP to ensure crc32 is included in the initramfs
+    - PCI/sysfs: Fix dsm_label_utf16s_to_utf8s() buffer overrun
+    - power: supply: rt5033_battery: Fix device tree enumeration
+    - NFSv4: Initialise connection to the server in nfs4_alloc_client()
+    - um: fix error return code in slip_open()
+    - um: fix error return code in winch_tramp()
+    - watchdog: aspeed: fix hardware timeout calculation
+    - nfs: fix acl memory leak of posix_acl_create()
+    - ubifs: Set/Clear I_LINKABLE under i_lock for whiteout inode
+    - PCI: iproc: Fix multi-MSI base vector number allocation
+    - PCI: iproc: Support multi-MSI only on uniprocessor kernel
+    - x86/fpu: Limit xstate copy size in xstateregs_set()
+    - pwm: imx1: Don't disable clocks at device remove time
+    - virtio_net: move tx vq operation under tx queue lock
+    - nvme-tcp: can't set sk_user_data without write_lock
+    - ALSA: isa: Fix error return code in snd_cmi8330_probe()
+    - NFSv4/pNFS: Don't call _nfs4_pnfs_v3_ds_connect multiple times
+    - hexagon: use common DISCARDS macro
+    - ARM: dts: gemini-rut1xx: remove duplicate ethernet node
+    - reset: a10sr: add missing of_match_table reference
+    - ARM: exynos: add missing of_node_put for loop iteration
+    - ARM: dts: exynos: fix PWM LED max brightness on Odroid XU/XU3
+    - ARM: dts: exynos: fix PWM LED max brightness on Odroid HC1
+    - ARM: dts: exynos: fix PWM LED max brightness on Odroid XU4
+    - memory: atmel-ebi: add missing of_node_put for loop iteration
+    - reset: brcmstb: Add missing MODULE_DEVICE_TABLE
+    - memory: pl353: Fix error return code in pl353_smc_probe()
+    - rtc: fix snprintf() checking in is_rtc_hctosys()
+    - arm64: dts: renesas: v3msk: Fix memory size
+    - ARM: dts: r8a7779, marzen: Fix DU clock names
+    - firmware: tegra: Fix error return code in tegra210_bpmp_init()
+    - firmware: arm_scmi: Reset Rx buffer to max size during async commands
+    - ARM: dts: BCM5301X: Fixup SPI binding
+    - reset: bail if try_module_get() fails
+    - memory: fsl_ifc: fix leak of IO mapping on probe failure
+    - memory: fsl_ifc: fix leak of private memory on probe failure
+    - ARM: dts: am335x: align ti,pindir-d0-out-d1-in property with dt-shema
+    - ARM: dts: am437x: align ti,pindir-d0-out-d1-in property with dt-shema
+    - ARM: dts: imx6q-dhcom: Fix ethernet reset time properties
+    - ARM: dts: imx6q-dhcom: Fix ethernet plugin detection problems
+    - ARM: dts: imx6q-dhcom: Add gpios pinctrl for i2c bus recovery
+    - thermal/drivers/rcar_gen3_thermal: Fix coefficient calculations
+    - firmware: turris-mox-rwtm: fix reply status decoding function
+    - firmware: turris-mox-rwtm: report failures better
+    - firmware: turris-mox-rwtm: fail probing when firmware does not support hwrng
+    - scsi: be2iscsi: Fix an error handling path in beiscsi_dev_probe()
+    - mips: always link byteswap helpers into decompressor
+    - mips: disable branch profiling in boot/decompress.o
+    - MIPS: vdso: Invalid GIC access through VDSO
+    - scsi: scsi_dh_alua: Fix signedness bug in alua_rtpg()
+    - misc: alcor_pci: fix inverted branch condition
+    - Linux 5.4.134
+
+  [ Ubuntu: 5.4.0-86.97 ]
+
+  * s390x BPF JIT vulnerabilities (LP: #1943960)
+    - SAUCE: s390/bpf: Fix 64-bit subtraction of the -0x80000000 constant
+    - SAUCE: s390/bpf: Fix optimizing out zero-extensions
+
+ -- Hsuan-Yu Lin <shane.lin@canonical.com>  Wed, 03 Nov 2021 16:44:30 +0800
+
+linux-xilinx-zynqmp (5.4.0-1016.19) focal; urgency=medium
+
+  * Miscellaneous Ubuntu changes
+    - [Config] Update configs for built-in nfs_layout_flexfiles
+
+  [ Ubuntu: 5.4.0-84.94 ]
+
+  * focal/linux: 5.4.0-84.94 -proposed tracker (LP: #1941767)
+  * Server boot failure after adding checks for ACPI IRQ override (LP: #1941657)
+    - Revert "ACPI: resources: Add checks for ACPI IRQ override"
+
+  [ Ubuntu: 5.4.0-83.93 ]
+
+  * focal/linux: 5.4.0-83.93 -proposed tracker (LP: #1940159)
+  * fails to launch linux L2 guests on AMD (LP: #1940134) // CVE-2021-3653
+    - KVM: nSVM: avoid picking up unsupported bits from L2 in int_ctl
+      (CVE-2021-3653)
+  * fails to launch linux L2 guests on AMD (LP: #1940134)
+    - SAUCE: Revert "UBUNTU: SAUCE: KVM: nSVM: avoid picking up unsupported bits
+      from L2 in int_ctl"
+
+  [ Ubuntu: 5.4.0-82.92 ]
+
+  * focal/linux: 5.4.0-82.92 -proposed tracker (LP: #1939799)
+  * Packaging resync (LP: #1786013)
+    - debian/dkms-versions -- update from kernel-versions (main/2021.08.16)
+  * CVE-2021-3656
+    - SAUCE: KVM: nSVM: always intercept VMLOAD/VMSAVE when nested
+  * CVE-2021-3653
+    - SAUCE: KVM: nSVM: avoid picking up unsupported bits from L2 in int_ctl
+  * [regression] USB device is not detected during boot (LP: #1939638)
+    - SAUCE: Revert "usb: core: reduce power-on-good delay time of root hub"
+  * dev_forward_skb: do not scrub skb mark within the same name space
+    (LP: #1935040)
+    - dev_forward_skb: do not scrub skb mark within the same name space
+  * XPS 9510 (TGL) Screen Brightness could not be changed (LP: #1933566)
+    - SAUCE: drm/i915: Force DPCD backlight mode for Dell XPS 9510(TGL)
+  * Acer Aspire 5 sound driver issues (LP: #1930188)
+    - ALSA: hda/realtek: headphone and mic don't work on an Acer laptop
+  * Sony Dualshock 4 usb dongle crashes the whole system (LP: #1935846)
+    - HID: sony: Workaround for DS4 dongle hotplug kernel crash.
+  * [21.10 FEAT] KVM: Provide a secure guest indication (LP: #1933173)
+    - s390/uv: add prot virt guest/host indication files
+    - s390/uv: fix prot virt host indication compilation
+  * Skip rtcpie test in kselftests/timers if the default RTC device does not
+    exist (LP: #1937991)
+    - selftests: timers: rtcpie: skip test if default RTC device does not exist
+  * Focal update: v5.4.133 upstream stable release (LP: #1938713)
+    - drm/mxsfb: Don't select DRM_KMS_FB_HELPER
+    - drm/zte: Don't select DRM_KMS_FB_HELPER
+    - drm/amd/amdgpu/sriov disable all ip hw status by default
+    - drm/vc4: fix argument ordering in vc4_crtc_get_margins()
+    - net: pch_gbe: Use proper accessors to BE data in pch_ptp_match()
+    - drm/amd/display: fix use_max_lb flag for 420 pixel formats
+    - hugetlb: clear huge pte during flush function on mips platform
+    - atm: iphase: fix possible use-after-free in ia_module_exit()
+    - mISDN: fix possible use-after-free in HFC_cleanup()
+    - atm: nicstar: Fix possible use-after-free in nicstar_cleanup()
+    - net: Treat __napi_schedule_irqoff() as __napi_schedule() on PREEMPT_RT
+    - drm/mediatek: Fix PM reference leak in mtk_crtc_ddp_hw_init()
+    - reiserfs: add check for invalid 1st journal block
+    - drm/virtio: Fix double free on probe failure
+    - drm/sched: Avoid data corruptions
+    - udf: Fix NULL pointer dereference in udf_symlink function
+    - e100: handle eeprom as little endian
+    - igb: handle vlan types with checker enabled
+    - drm/bridge: cdns: Fix PM reference leak in cdns_dsi_transfer()
+    - clk: renesas: r8a77995: Add ZA2 clock
+    - clk: tegra: Ensure that PLLU configuration is applied properly
+    - ipv6: use prandom_u32() for ID generation
+    - RDMA/cxgb4: Fix missing error code in create_qp()
+    - dm space maps: don't reset space map allocation cursor when committing
+    - pinctrl: mcp23s08: fix race condition in irq handler
+    - ice: set the value of global config lock timeout longer
+    - virtio_net: Remove BUG() to avoid machine dead
+    - net: bcmgenet: check return value after calling platform_get_resource()
+    - net: mvpp2: check return value after calling platform_get_resource()
+    - net: micrel: check return value after calling platform_get_resource()
+    - drm/amd/display: Update scaling settings on modeset
+    - drm/amd/display: Release MST resources on switch from MST to SST
+    - drm/amd/display: Set DISPCLK_MAX_ERRDET_CYCLES to 7
+    - drm/amdkfd: use allowed domain for vmbo validation
+    - fjes: check return value after calling platform_get_resource()
+    - selinux: use __GFP_NOWARN with GFP_NOWAIT in the AVC
+    - r8169: avoid link-up interrupt issue on RTL8106e if user enables ASPM
+    - drm/amd/display: Verify Gamma & Degamma LUT sizes in amdgpu_dm_atomic_check
+    - xfrm: Fix error reporting in xfrm_state_construct.
+    - wlcore/wl12xx: Fix wl12xx get_mac error if device is in ELP
+    - wl1251: Fix possible buffer overflow in wl1251_cmd_scan
+    - cw1200: add missing MODULE_DEVICE_TABLE
+    - bpf: Fix up register-based shifts in interpreter to silence KUBSAN
+    - mt76: mt7615: fix fixed-rate tx status reporting
+    - net: fix mistake path for netdev_features_strings
+    - net: sched: fix error return code in tcf_del_walker()
+    - drm/amdkfd: Walk through list with dqm lock hold
+    - rtl8xxxu: Fix device info for RTL8192EU devices
+    - atm: nicstar: use 'dma_free_coherent' instead of 'kfree'
+    - atm: nicstar: register the interrupt handler in the right place
+    - vsock: notify server to shutdown when client has pending signal
+    - RDMA/rxe: Don't overwrite errno from ib_umem_get()
+    - iwlwifi: mvm: don't change band on bound PHY contexts
+    - iwlwifi: pcie: free IML DMA memory allocation
+    - iwlwifi: pcie: fix context info freeing
+    - sfc: avoid double pci_remove of VFs
+    - sfc: error code if SRIOV cannot be disabled
+    - wireless: wext-spy: Fix out-of-bounds warning
+    - media, bpf: Do not copy more entries than user space requested
+    - net: ip: avoid OOM kills with large UDP sends over loopback
+    - RDMA/cma: Fix rdma_resolve_route() memory leak
+    - Bluetooth: btusb: Fixed too many in-token issue for Mediatek Chip.
+    - Bluetooth: Fix the HCI to MGMT status conversion table
+    - Bluetooth: Shutdown controller after workqueues are flushed or cancelled
+    - Bluetooth: btusb: fix bt fiwmare downloading failure issue for qca btsoc.
+    - sctp: validate from_addr_param return
+    - sctp: add size validation when walking chunks
+    - MIPS: loongsoon64: Reserve memory below starting pfn to prevent Oops
+    - MIPS: set mips32r5 for virt extensions
+    - fscrypt: don't ignore minor_hash when hash is 0
+    - crypto: ccp - Annotate SEV Firmware file names
+    - perf bench: Fix 2 memory sanitizer warnings
+    - powerpc/mm: Fix lockup on kernel exec fault
+    - powerpc/barrier: Avoid collision with clang's __lwsync macro
+    - drm/amdgpu: Update NV SIMD-per-CU to 2
+    - drm/radeon: Add the missed drm_gem_object_put() in
+      radeon_user_framebuffer_create()
+    - drm/rockchip: dsi: remove extra component_del() call
+    - drm/amd/display: fix incorrrect valid irq check
+    - pinctrl/amd: Add device HID for new AMD GPIO controller
+    - drm/tegra: Don't set allow_fb_modifiers explicitly
+    - drm/msm/mdp4: Fix modifier support enabling
+    - drm/arm/malidp: Always list modifiers
+    - mmc: sdhci: Fix warning message when accessing RPMB in HS400 mode
+    - mmc: core: clear flags before allowing to retune
+    - mmc: core: Allow UHS-I voltage switch for SDSC cards if supported
+    - ata: ahci_sunxi: Disable DIPM
+    - cpu/hotplug: Cure the cpusets trainwreck
+    - clocksource/arm_arch_timer: Improve Allwinner A64 timer workaround
+    - fpga: stratix10-soc: Add missing fpga_mgr_free() call
+    - MIPS: fix "mipsel-linux-ld: decompress.c:undefined reference to `memmove'"
+    - ASoC: tegra: Set driver_name=tegra for all machine drivers
+    - qemu_fw_cfg: Make fw_cfg_rev_attr a proper kobj_attribute
+    - ipmi/watchdog: Stop watchdog timer when the current action is 'none'
+    - thermal/drivers/int340x/processor_thermal: Fix tcc setting
+    - ubifs: Fix races between xattr_{set|get} and listxattr operations
+    - power: supply: ab8500: Fix an old bug
+    - nvmem: core: add a missing of_node_put
+    - extcon: intel-mrfld: Sync hardware and software state on init
+    - seq_buf: Fix overflow in seq_buf_putmem_hex()
+    - rq-qos: fix missed wake-ups in rq_qos_throttle try two
+    - tracing: Simplify & fix saved_tgids logic
+    - tracing: Resize tgid_map to pid_max, not PID_MAX_DEFAULT
+    - ipack/carriers/tpci200: Fix a double free in tpci200_pci_probe
+    - coresight: tmc-etf: Fix global-out-of-bounds in tmc_update_etf_buffer()
+    - dm btree remove: assign new_root only when removal succeeds
+    - PCI: Leave Apple Thunderbolt controllers on for s2idle or standby
+    - PCI: aardvark: Fix checking for PIO Non-posted Request
+    - PCI: aardvark: Implement workaround for the readback value of VEND_ID
+    - media: subdev: disallow ioctl for saa6588/davinci
+    - media: dtv5100: fix control-request directions
+    - media: zr364xx: fix memory leak in zr364xx_start_readpipe
+    - media: gspca/sq905: fix control-request direction
+    - media: gspca/sunplus: fix zero-length control requests
+    - pinctrl: mcp23s08: Fix missing unlock on error in mcp23s08_irq()
+    - jfs: fix GPF in diFree
+    - smackfs: restrict bytes count in smk_set_cipso()
+    - Linux 5.4.133
+  * Focal update: v5.4.132 upstream stable release (LP: #1938199)
+    - ALSA: usb-audio: fix rate on Ozone Z90 USB headset
+    - ALSA: usb-audio: Fix OOB access at proc output
+    - ALSA: usb-audio: scarlett2: Fix wrong resume call
+    - ALSA: intel8x0: Fix breakage at ac97 clock measurement
+    - ALSA: hda/realtek: Add another ALC236 variant support
+    - ALSA: hda/realtek: Improve fixup for HP Spectre x360 15-df0xxx
+    - ALSA: hda/realtek: Fix bass speaker DAC mapping for Asus UM431D
+    - ALSA: hda/realtek: Apply LED fixup for HP Dragonfly G1, too
+    - media: dvb-usb: fix wrong definition
+    - Input: usbtouchscreen - fix control-request directions
+    - net: can: ems_usb: fix use-after-free in ems_usb_disconnect()
+    - usb: gadget: eem: fix echo command packet response issue
+    - USB: cdc-acm: blacklist Heimann USB Appset device
+    - usb: dwc3: Fix debugfs creation flow
+    - usb: typec: Add the missed altmode_id_remove() in typec_register_altmode()
+    - xhci: solve a double free problem while doing s4
+    - ntfs: fix validity check for file name attribute
+    - copy_page_to_iter(): fix ITER_DISCARD case
+    - iov_iter_fault_in_readable() should do nothing in xarray case
+    - Input: joydev - prevent use of not validated data in JSIOCSBTNMAP ioctl
+    - arm_pmu: Fix write counter incorrect in ARMv7 big-endian mode
+    - ARM: dts: at91: sama5d4: fix pinctrl muxing
+    - btrfs: send: fix invalid path for unlink operations after parent
+      orphanization
+    - btrfs: clear defrag status of a root if starting transaction fails
+    - ext4: cleanup in-core orphan list if ext4_truncate() failed to get a
+      transaction handle
+    - ext4: fix kernel infoleak via ext4_extent_header
+    - ext4: return error code when ext4_fill_flex_info() fails
+    - ext4: correct the cache_nr in tracepoint ext4_es_shrink_exit
+    - ext4: remove check for zero nr_to_scan in ext4_es_scan()
+    - ext4: fix avefreec in find_group_orlov
+    - ext4: use ext4_grp_locked_error in mb_find_extent
+    - can: gw: synchronize rcu operations before removing gw job entry
+    - can: j1939: j1939_sk_init(): set SOCK_RCU_FREE to call sk_destruct() after
+      RCU is done
+    - can: peak_pciefd: pucan_handle_status(): fix a potential starvation issue in
+      TX path
+    - mac80211: remove iwlwifi specific workaround that broke sta NDP tx
+    - SUNRPC: Fix the batch tasks count wraparound.
+    - SUNRPC: Should wake up the privileged task firstly.
+    - perf/smmuv3: Don't trample existing events with global filter
+    - KVM: PPC: Book3S HV: Workaround high stack usage with clang
+    - s390/cio: dont call css_wait_for_slow_path() inside a lock
+    - rtc: stm32: Fix unbalanced clk_disable_unprepare() on probe error path
+    - iio: light: tcs3472: do not free unallocated IRQ
+    - iio: ltr501: mark register holding upper 8 bits of ALS_DATA{0,1} and PS_DATA
+      as volatile, too
+    - iio: ltr501: ltr559: fix initialization of LTR501_ALS_CONTR
+    - iio: ltr501: ltr501_read_ps(): add missing endianness conversion
+    - serial: mvebu-uart: fix calculation of clock divisor
+    - serial: sh-sci: Stop dmaengine transfer in sci_stop_tx()
+    - serial_cs: Add Option International GSM-Ready 56K/ISDN modem
+    - serial_cs: remove wrong GLOBETROTTER.cis entry
+    - ath9k: Fix kernel NULL pointer dereference during ath_reset_internal()
+    - ssb: sdio: Don't overwrite const buffer if block_write fails
+    - rsi: Assign beacon rate settings to the correct rate_info descriptor field
+    - rsi: fix AP mode with WPA failure due to encrypted EAPOL
+    - tracing/histograms: Fix parsing of "sym-offset" modifier
+    - tracepoint: Add tracepoint_probe_register_may_exist() for BPF tracing
+    - seq_buf: Make trace_seq_putmem_hex() support data longer than 8
+    - powerpc/stacktrace: Fix spurious "stale" traces in raise_backtrace_ipi()
+    - evm: Execute evm_inode_init_security() only when an HMAC key is loaded
+    - evm: Refuse EVM_ALLOW_METADATA_WRITES only if an HMAC key is loaded
+    - fuse: ignore PG_workingset after stealing
+    - fuse: check connected before queueing on fpq->io
+    - fuse: reject internal errno
+    - spi: Make of_register_spi_device also set the fwnode
+    - media: mdk-mdp: fix pm_runtime_get_sync() usage count
+    - media: s5p: fix pm_runtime_get_sync() usage count
+    - media: sh_vou: fix pm_runtime_get_sync() usage count
+    - media: mtk-vcodec: fix PM runtime get logic
+    - media: s5p-jpeg: fix pm_runtime_get_sync() usage count
+    - media: sti/bdisp: fix pm_runtime_get_sync() usage count
+    - media: exynos-gsc: fix pm_runtime_get_sync() usage count
+    - spi: spi-loopback-test: Fix 'tx_buf' might be 'rx_buf'
+    - spi: spi-topcliff-pch: Fix potential double free in
+      pch_spi_process_messages()
+    - spi: omap-100k: Fix the length judgment problem
+    - regulator: uniphier: Add missing MODULE_DEVICE_TABLE
+    - hwrng: exynos - Fix runtime PM imbalance on error
+    - crypto: nx - add missing MODULE_DEVICE_TABLE
+    - media: sti: fix obj-$(config) targets
+    - media: cpia2: fix memory leak in cpia2_usb_probe
+    - media: cobalt: fix race condition in setting HPD
+    - media: pvrusb2: fix warning in pvr2_i2c_core_done
+    - media: imx: imx7_mipi_csis: Fix logging of only error event counters
+    - crypto: qat - check return code of qat_hal_rd_rel_reg()
+    - crypto: qat - remove unused macro in FW loader
+    - sched/fair: Fix ascii art by relpacing tabs
+    - media: em28xx: Fix possible memory leak of em28xx struct
+    - media: v4l2-core: Avoid the dangling pointer in v4l2_fh_release
+    - media: bt8xx: Fix a missing check bug in bt878_probe
+    - media: st-hva: Fix potential NULL pointer dereferences
+    - Makefile: fix GDB warning with CONFIG_RELR
+    - media: dvd_usb: memory leak in cinergyt2_fe_attach
+    - memstick: rtsx_usb_ms: fix UAF
+    - mmc: sdhci-sprd: use sdhci_sprd_writew
+    - mmc: via-sdmmc: add a check against NULL pointer dereference
+    - crypto: shash - avoid comparing pointers to exported functions under CFI
+    - media: dvb_net: avoid speculation from net slot
+    - media: siano: fix device register error path
+    - media: imx-csi: Skip first few frames from a BT.656 source
+    - hwmon: (max31790) Report correct current pwm duty cycles
+    - hwmon: (max31790) Fix pwmX_enable attributes
+    - drivers/perf: fix the missed ida_simple_remove() in ddr_perf_probe()
+    - KVM: PPC: Book3S HV: Fix TLB management on SMT8 POWER9 and POWER10
+      processors
+    - btrfs: fix error handling in __btrfs_update_delayed_inode
+    - btrfs: abort transaction if we fail to update the delayed inode
+    - btrfs: disable build on platforms having page size 256K
+    - locking/lockdep: Fix the dep path printing for backwards BFS
+    - lockding/lockdep: Avoid to find wrong lock dep path in check_irq_usage()
+    - KVM: s390: get rid of register asm usage
+    - regulator: mt6358: Fix vdram2 .vsel_mask
+    - regulator: da9052: Ensure enough delay time for .set_voltage_time_sel
+    - media: Fix Media Controller API config checks
+    - HID: do not use down_interruptible() when unbinding devices
+    - EDAC/ti: Add missing MODULE_DEVICE_TABLE
+    - ACPI: processor idle: Fix up C-state latency if not ordered
+    - hv_utils: Fix passing zero to 'PTR_ERR' warning
+    - lib: vsprintf: Fix handling of number field widths in vsscanf
+    - ACPI: EC: Make more Asus laptops use ECDT _GPE
+    - block_dump: remove block_dump feature in mark_inode_dirty()
+    - fs: dlm: cancel work sync othercon
+    - random32: Fix implicit truncation warning in prandom_seed_state()
+    - fs: dlm: fix memory leak when fenced
+    - ACPICA: Fix memory leak caused by _CID repair function
+    - ACPI: bus: Call kobject_put() in acpi_init() error path
+    - block: fix race between adding/removing rq qos and normal IO
+    - platform/x86: toshiba_acpi: Fix missing error code in
+      toshiba_acpi_setup_keyboard()
+    - nvmet-fc: do not check for invalid target port in nvmet_fc_handle_fcp_rqst()
+    - EDAC/Intel: Do not load EDAC driver when running as a guest
+    - PCI: hv: Add check for hyperv_initialized in init_hv_pci_drv()
+    - clocksource: Retry clock read if long delays detected
+    - ACPI: tables: Add custom DSDT file as makefile prerequisite
+    - HID: wacom: Correct base usage for capacitive ExpressKey status bits
+    - cifs: fix missing spinlock around update to ses->status
+    - block: fix discard request merge
+    - kthread_worker: fix return value when kthread_mod_delayed_work() races with
+      kthread_cancel_delayed_work_sync()
+    - ia64: mca_drv: fix incorrect array size calculation
+    - writeback, cgroup: increment isw_nr_in_flight before grabbing an inode
+    - media: s5p_cec: decrement usage count if disabled
+    - crypto: ixp4xx - dma_unmap the correct address
+    - crypto: ux500 - Fix error return code in hash_hw_final()
+    - sata_highbank: fix deferred probing
+    - pata_rb532_cf: fix deferred probing
+    - media: I2C: change 'RST' to "RSET" to fix multiple build errors
+    - sched/uclamp: Fix wrong implementation of cpu.uclamp.min
+    - sched/uclamp: Fix locking around cpu_util_update_eff()
+    - kbuild: run the checker after the compiler
+    - kbuild: Fix objtool dependency for 'OBJECT_FILES_NON_STANDARD_<obj> := n'
+    - pata_octeon_cf: avoid WARN_ON() in ata_host_activate()
+    - evm: fix writing <securityfs>/evm overflow
+    - crypto: ccp - Fix a resource leak in an error handling path
+    - media: rc: i2c: Fix an error message
+    - pata_ep93xx: fix deferred probing
+    - media: exynos4-is: Fix a use after free in isp_video_release
+    - media: au0828: fix a NULL vs IS_ERR() check
+    - media: tc358743: Fix error return code in tc358743_probe_of()
+    - media: gspca/gl860: fix zero-length control requests
+    - m68k: atari: Fix ATARI_KBD_CORE kconfig unmet dependency warning
+    - media: siano: Fix out-of-bounds warnings in smscore_load_firmware_family2()
+    - crypto: nitrox - fix unchecked variable in nitrox_register_interrupts
+    - crypto: omap-sham - Fix PM reference leak in omap sham ops
+    - mmc: usdhi6rol0: fix error return code in usdhi6_probe()
+    - arm64: consistently use reserved_pg_dir
+    - arm64/mm: Fix ttbr0 values stored in struct thread_info for software-pan
+    - media: s5p-g2d: Fix a memory leak on ctx->fh.m2m_ctx
+    - hwmon: (max31722) Remove non-standard ACPI device IDs
+    - hwmon: (max31790) Fix fan speed reporting for fan7..12
+    - KVM: nVMX: Ensure 64-bit shift when checking VMFUNC bitmap
+    - regulator: hi655x: Fix pass wrong pointer to config.driver_data
+    - btrfs: clear log tree recovering status if starting transaction fails
+    - sched/rt: Fix RT utilization tracking during policy change
+    - sched/rt: Fix Deadline utilization tracking during policy change
+    - sched/uclamp: Fix uclamp_tg_restrict()
+    - spi: spi-sun6i: Fix chipselect/clock bug
+    - crypto: nx - Fix RCU warning in nx842_OF_upd_status
+    - ACPI: sysfs: Fix a buffer overrun problem with description_show()
+    - extcon: extcon-max8997: Fix IRQ freeing at error path
+    - blk-wbt: introduce a new disable state to prevent false positive by
+      rwb_enabled()
+    - blk-wbt: make sure throttle is enabled properly
+    - ACPI: Use DEVICE_ATTR_<RW|RO|WO> macros
+    - ACPI: bgrt: Fix CFI violation
+    - cpufreq: Make cpufreq_online() call driver->offline() on errors
+    - ocfs2: fix snprintf() checking
+    - dax: fix ENOMEM handling in grab_mapping_entry()
+    - xfrm: xfrm_state_mtu should return at least 1280 for ipv6
+    - video: fbdev: imxfb: Fix an error message
+    - net: mvpp2: Put fwnode in error case during ->probe()
+    - net: pch_gbe: Propagate error from devm_gpio_request_one()
+    - pinctrl: renesas: r8a7796: Add missing bias for PRESET# pin
+    - pinctrl: renesas: r8a77990: JTAG pins do not have pull-down capabilities
+    - clk: meson: g12a: fix gp0 and hifi ranges
+    - net: ftgmac100: add missing error return code in ftgmac100_probe()
+    - drm/rockchip: cdn-dp-core: add missing clk_disable_unprepare() on error in
+      cdn_dp_grf_write()
+    - drm/rockchip: dsi: move all lane config except LCDC mux to bind()
+    - ehea: fix error return code in ehea_restart_qps()
+    - net/sched: act_vlan: Fix modify to allow 0
+    - RDMA/core: Sanitize WQ state received from the userspace
+    - RDMA/rxe: Fix failure during driver load
+    - drm: qxl: ensure surf.data is ininitialized
+    - tools/bpftool: Fix error return code in do_batch()
+    - ath10k: go to path err_unsupported when chip id is not supported
+    - ath10k: add missing error return code in ath10k_pci_probe()
+    - wireless: carl9170: fix LEDS build errors & warnings
+    - ieee802154: hwsim: Fix possible memory leak in hwsim_subscribe_all_others
+    - wcn36xx: Move hal_buf allocation to devm_kmalloc in probe
+    - ssb: Fix error return code in ssb_bus_scan()
+    - brcmfmac: fix setting of station info chains bitmask
+    - brcmfmac: correctly report average RSSI in station info
+    - brcmsmac: mac80211_if: Fix a resource leak in an error handling path
+    - ath10k: Fix an error code in ath10k_add_interface()
+    - netlabel: Fix memory leak in netlbl_mgmt_add_common
+    - RDMA/mlx5: Don't add slave port to unaffiliated list
+    - netfilter: nft_exthdr: check for IPv6 packet before further processing
+    - netfilter: nft_osf: check for TCP packet before further processing
+    - netfilter: nft_tproxy: restrict support to TCP and UDP transport protocols
+    - RDMA/rxe: Fix qp reference counting for atomic ops
+    - samples/bpf: Fix the error return code of xdp_redirect's main()
+    - net: ethernet: aeroflex: fix UAF in greth_of_remove
+    - net: ethernet: ezchip: fix UAF in nps_enet_remove
+    - net: ethernet: ezchip: fix error handling
+    - vrf: do not push non-ND strict packets with a source LLA through packet taps
+      again
+    - net: sched: add barrier to ensure correct ordering for lockless qdisc
+    - tls: prevent oversized sendfile() hangs by ignoring MSG_MORE
+    - pkt_sched: sch_qfq: fix qfq_change_class() error path
+    - vxlan: add missing rcu_read_lock() in neigh_reduce()
+    - net/ipv4: swap flow ports when validating source
+    - tc-testing: fix list handling
+    - ieee802154: hwsim: Fix memory leak in hwsim_add_one
+    - ieee802154: hwsim: avoid possible crash in hwsim_del_edge_nl()
+    - mac80211: remove iwlwifi specific workaround NDPs of null_response
+    - net: bcmgenet: Fix attaching to PYH failed on RPi 4B
+    - ipv6: exthdrs: do not blindly use init_net
+    - bpf: Do not change gso_size during bpf_skb_change_proto()
+    - i40e: Fix error handling in i40e_vsi_open
+    - i40e: Fix autoneg disabling for non-10GBaseT links
+    - Revert "ibmvnic: remove duplicate napi_schedule call in open function"
+    - ibmvnic: free tx_pool if tso_pool alloc fails
+    - ipv6: fix out-of-bound access in ip6_parse_tlv()
+    - e1000e: Check the PCIm state
+    - bpfilter: Specify the log level for the kmsg message
+    - gve: Fix swapped vars when fetching max queues
+    - Revert "be2net: disable bh with spin_lock in be_process_mcc"
+    - Bluetooth: mgmt: Fix slab-out-of-bounds in tlv_data_is_valid
+    - Bluetooth: Fix handling of HCI_LE_Advertising_Set_Terminated event
+    - clk: actions: Fix UART clock dividers on Owl S500 SoC
+    - clk: actions: Fix SD clocks factor table on Owl S500 SoC
+    - clk: actions: Fix bisp_factor_table based clocks on Owl S500 SoC
+    - clk: si5341: Avoid divide errors due to bogus register contents
+    - clk: si5341: Update initialization magic
+    - writeback: fix obtain a reference to a freeing memcg css
+    - net: lwtunnel: handle MTU calculation in forwading
+    - net: sched: fix warning in tcindex_alloc_perfect_hash
+    - RDMA/mlx5: Don't access NULL-cleared mpi pointer
+    - MIPS: Fix PKMAP with 32-bit MIPS huge page support
+    - staging: fbtft: Rectify GPIO handling
+    - rcu: Invoke rcu_spawn_core_kthreads() from rcu_spawn_gp_kthread()
+    - tty: nozomi: Fix a resource leak in an error handling function
+    - mwifiex: re-fix for unaligned accesses
+    - iio: adis_buffer: do not return ints in irq handlers
+    - iio: adis16400: do not return ints in irq handlers
+    - iio: accel: bma180: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: accel: bma220: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: accel: hid: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: accel: kxcjk-1013: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio:accel:mxc4005: Drop unnecessary explicit casts in regmap_bulk_read calls
+    - iio: accel: mxc4005: Fix overread of data and alignment issue.
+    - iio: accel: stk8312: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: accel: stk8ba50: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: adc: ti-ads1015: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: adc: vf610: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: gyro: bmg160: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: humidity: am2315: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: prox: srf08: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: prox: pulsed-light: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: prox: as3935: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: magn: hmc5843: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: magn: bmc150: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: light: isl29125: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: light: tcs3414: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: light: tcs3472: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: cros_ec_sensors: Fix alignment of buffer in
+      iio_push_to_buffers_with_timestamp()
+    - iio: potentiostat: lmp91000: Fix alignment of buffer in
+      iio_push_to_buffers_with_timestamp()
+    - ASoC: rk3328: fix missing clk_disable_unprepare() on error in
+      rk3328_platform_probe()
+    - ASoC: hisilicon: fix missing clk_disable_unprepare() on error in
+      hi6210_i2s_startup()
+    - backlight: lm3630a_bl: Put fwnode in error case during ->probe()
+    - ASoC: rsnd: tidyup loop on rsnd_adg_clk_query()
+    - Input: hil_kbd - fix error return code in hil_dev_connect()
+    - mtd: partitions: redboot: seek fis-index-block in the right node
+    - char: pcmcia: error out if 'num_bytes_read' is greater than 4 in
+      set_protocol()
+    - firmware: stratix10-svc: Fix a resource leak in an error handling path
+    - tty: nozomi: Fix the error handling path of 'nozomi_card_init()'
+    - leds: lm3532: select regmap I2C API
+    - leds: lm36274: cosmetic: rename lm36274_data to chip
+    - leds: lm3692x: Put fwnode in any case during ->probe()
+    - scsi: FlashPoint: Rename si_flags field
+    - fsi: core: Fix return of error values on failures
+    - fsi: scom: Reset the FSI2PIB engine for any error
+    - fsi: occ: Don't accept response from un-initialized OCC
+    - fsi/sbefifo: Clean up correct FIFO when receiving reset request from SBE
+    - fsi/sbefifo: Fix reset timeout
+    - visorbus: fix error return code in visorchipset_init()
+    - s390: appldata depends on PROC_SYSCTL
+    - iommu/dma: Fix IOVA reserve dma ranges
+    - ASoC: mediatek: mtk-btcvsd: Fix an error handling path in
+      'mtk_btcvsd_snd_probe()'
+    - usb: gadget: f_fs: Fix setting of device and driver data cross-references
+    - usb: dwc2: Don't reset the core after setting turnaround time
+    - eeprom: idt_89hpesx: Put fwnode in matching case during ->probe()
+    - eeprom: idt_89hpesx: Restore printing the unsupported fwnode name
+    - iio: at91-sama5d2_adc: remove usage of iio_priv_to_dev() helper
+    - iio: adc: at91-sama5d2: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: adc: hx711: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: adc: mxs-lradc: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: adc: ti-ads8688: Fix alignment of buffer in
+      iio_push_to_buffers_with_timestamp()
+    - iio: magn: rm3100: Fix alignment of buffer in
+      iio_push_to_buffers_with_timestamp()
+    - staging: gdm724x: check for buffer overflow in gdm_lte_multi_sdu_pkt()
+    - staging: gdm724x: check for overflow in gdm_lte_netif_rx()
+    - staging: rtl8712: remove redundant check in r871xu_drv_init
+    - staging: rtl8712: fix memory leak in rtl871x_load_fw_cb
+    - staging: mt7621-dts: fix pci address for PCI memory range
+    - serial: 8250: Actually allow UPF_MAGIC_MULTIPLIER baud rates
+    - iio: light: vcnl4035: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - iio: prox: isl29501: Fix buffer alignment in
+      iio_push_to_buffers_with_timestamp()
+    - ASoC: cs42l42: Correct definition of CS42L42_ADC_PDN_MASK
+    - of: Fix truncation of memory sizes on 32-bit platforms
+    - mtd: rawnand: marvell: add missing clk_disable_unprepare() on error in
+      marvell_nfc_resume()
+    - scsi: mpt3sas: Fix error return value in _scsih_expander_add()
+    - soundwire: stream: Fix test for DP prepare complete
+    - phy: uniphier-pcie: Fix updating phy parameters
+    - phy: ti: dm816x: Fix the error handling path in 'dm816x_usb_phy_probe()
+    - extcon: sm5502: Drop invalid register write in sm5502_reg_data
+    - extcon: max8997: Add missing modalias string
+    - ASoC: atmel-i2s: Fix usage of capture and playback at the same time
+    - configfs: fix memleak in configfs_release_bin_file
+    - leds: as3645a: Fix error return code in as3645a_parse_node()
+    - leds: ktd2692: Fix an error handling path
+    - powerpc: Offline CPU in stop_this_cpu()
+    - serial: mvebu-uart: do not allow changing baudrate when uartclk is not
+      available
+    - serial: mvebu-uart: correctly calculate minimal possible baudrate
+    - arm64: dts: marvell: armada-37xx: Fix reg for standard variant of UART
+    - vfio/pci: Handle concurrent vma faults
+    - mm/huge_memory.c: don't discard hugepage if other processes are mapping it
+    - mm/z3fold: fix potential memory leak in z3fold_destroy_pool()
+    - selftests/vm/pkeys: fix alloc_random_pkey() to make it really, really random
+    - perf llvm: Return -ENOMEM when asprintf() fails
+    - scsi: target: cxgbit: Unmap DMA buffer before calling target_execute_cmd()
+    - mmc: block: Disable CMDQ on the ioctl path
+    - mmc: vub3000: fix control-request direction
+    - scsi: core: Retry I/O for Notify (Enable Spinup) Required error
+    - iommu/dma: Fix compile warning in 32-bit builds
+    - Linux 5.4.132
+  * Keyboard not working (LP: #1909814) // Focal update: v5.4.132 upstream
+    stable release (LP: #1938199)
+    - ACPI: resources: Add checks for ACPI IRQ override
+  * Focal update: v5.4.131 upstream stable release (LP: #1936245)
+    - KVM: SVM: Periodically schedule when unregistering regions on destroy
+    - s390/stack: fix possible register corruption with stack switch helper
+    - KVM: SVM: Call SEV Guest Decommission if ASID binding fails
+    - xen/events: reset active flag for lateeoi events later
+    - Linux 5.4.131
+  * Focal update: v5.4.130 upstream stable release (LP: #1936244)
+    - scsi: sr: Return appropriate error code when disk is ejected
+    - drm/nouveau: fix dma_address check for CPU/GPU sync
+    - gpio: AMD8111 and TQMX86 require HAS_IOPORT_MAP
+    - RDMA/mlx5: Block FDB rules when not in switchdev mode
+    - Linux 5.4.130
+  * Focal update: v5.4.129 upstream stable release (LP: #1936242)
+    - module: limit enabling module.sig_enforce
+    - drm/nouveau: wait for moving fence after pinning v2
+    - drm/radeon: wait for moving fence after pinning
+    - ARM: 9081/1: fix gcc-10 thumb2-kernel regression
+    - mmc: meson-gx: use memcpy_to/fromio for dram-access-quirk
+    - kbuild: add CONFIG_LD_IS_LLD
+    - arm64: link with -z norelro for LLD or aarch64-elf
+    - MIPS: generic: Update node names to avoid unit addresses
+    - spi: spi-nxp-fspi: move the register operation after the clock enable
+    - Revert "PCI: PM: Do not read power state in pci_enable_device_flags()"
+    - dmaengine: zynqmp_dma: Fix PM reference leak in
+      zynqmp_dma_alloc_chan_resourc()
+    - mac80211: remove warning in ieee80211_get_sband()
+    - mac80211_hwsim: drop pending frames on stop
+    - cfg80211: call cfg80211_leave_ocb when switching away from OCB
+    - dmaengine: rcar-dmac: Fix PM reference leak in rcar_dmac_probe()
+    - dmaengine: mediatek: free the proper desc in desc_free handler
+    - dmaengine: mediatek: do not issue a new desc if one is still current
+    - dmaengine: mediatek: use GFP_NOWAIT instead of GFP_ATOMIC in prep_dma
+    - net: ipv4: Remove unneed BUG() function
+    - mac80211: drop multicast fragments
+    - net: ethtool: clear heap allocations for ethtool function
+    - ping: Check return value of function 'ping_queue_rcv_skb'
+    - inet: annotate date races around sk->sk_txhash
+    - net: phy: dp83867: perform soft reset and retain established link
+    - net: caif: fix memory leak in ldisc_open
+    - net/packet: annotate accesses to po->bind
+    - net/packet: annotate accesses to po->ifindex
+    - r8152: Avoid memcpy() over-reading of ETH_SS_STATS
+    - sh_eth: Avoid memcpy() over-reading of ETH_SS_STATS
+    - r8169: Avoid memcpy() over-reading of ETH_SS_STATS
+    - KVM: selftests: Fix kvm_check_cap() assertion
+    - net: qed: Fix memcpy() overflow of qed_dcbx_params()
+    - recordmcount: Correct st_shndx handling
+    - PCI: Add AMD RS690 quirk to enable 64-bit DMA
+    - net: ll_temac: Add memory-barriers for TX BD access
+    - net: ll_temac: Avoid ndo_start_xmit returning NETDEV_TX_BUSY
+    - pinctrl: stm32: fix the reported number of GPIO lines per bank
+    - nilfs2: fix memory leak in nilfs_sysfs_delete_device_group
+    - KVM: do not allow mapping valid but non-reference-counted pages
+    - i2c: robotfuzz-osif: fix control-request directions
+    - kthread_worker: split code for canceling the delayed work timer
+    - kthread: prevent deadlock when kthread_mod_delayed_work() races with
+      kthread_cancel_delayed_work_sync()
+    - mm: add VM_WARN_ON_ONCE_PAGE() macro
+    - mm/rmap: remove unneeded semicolon in page_not_mapped()
+    - mm/rmap: use page_not_mapped in try_to_unmap()
+    - mm, thp: use head page in __migration_entry_wait()
+    - mm/thp: fix __split_huge_pmd_locked() on shmem migration entry
+    - mm/thp: make is_huge_zero_pmd() safe and quicker
+    - mm/thp: try_to_unmap() use TTU_SYNC for safe splitting
+    - mm/thp: fix vma_address() if virtual address below file offset
+    - mm/thp: fix page_address_in_vma() on file THP tails
+    - mm/thp: unmap_mapping_page() to fix THP truncate_cleanup_page()
+    - mm: thp: replace DEBUG_VM BUG with VM_WARN when unmap fails for split
+    - mm: page_vma_mapped_walk(): use page for pvmw->page
+    - mm: page_vma_mapped_walk(): settle PageHuge on entry
+    - mm: page_vma_mapped_walk(): use pmde for *pvmw->pmd
+    - mm: page_vma_mapped_walk(): prettify PVMW_MIGRATION block
+    - mm: page_vma_mapped_walk(): crossing page table boundary
+    - mm: page_vma_mapped_walk(): add a level of indentation
+    - mm: page_vma_mapped_walk(): use goto instead of while (1)
+    - mm: page_vma_mapped_walk(): get vma_address_end() earlier
+    - mm/thp: fix page_vma_mapped_walk() if THP mapped by ptes
+    - mm/thp: another PVMW_SYNC fix in page_vma_mapped_walk()
+    - mm, futex: fix shared futex pgoff on shmem huge page
+    - [Config] enable CONFIG_SYSTEM_REVOCATION_LIST
+    - certs: Add EFI_CERT_X509_GUID support for dbx entries
+    - certs: Move load_system_certificate_list to a common function
+    - Linux 5.4.129
+  * Patch To Fix Bug in the Linux Block Layer Responsible For  Merging BIOs
+    (LP: #1931497)
+    - block: return the correct bvec when checking for gaps
+
+  [ Ubuntu: 5.4.0-81.91 ]
+
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+  * large_dir in ext4 broken (LP: #1933074)
+    - SAUCE: ext4: fix directory index node split corruption
+  * Some test in kselftest/net on focal source tree were not tested at all
+    (LP: #1934282)
+    - selftests/net: add missing tests to Makefile
+  * curtin: install flash-kernel in arm64 UEFI unexpected (LP: #1918427)
+    - [Packaging] Allow grub-efi-arm* to satisfy recommends on ARM
+  * Add l2tp.sh in net from ubuntu_kernel_selftests back (LP: #1934293)
+    - Revert "UBUNTU: SAUCE: selftests/net -- disable l2tp.sh test"
+  * icmp_redirect.sh in net from ubuntu_kernel_selftests failed on F-OEM-5.6 /
+    F-OEM-5.10 / F-OEM-5.13 / F / G / H (LP: #1880645)
+    - selftests: icmp_redirect: support expected failures
+  * Focal update: v5.4.128 upstream stable release (LP: #1934179)
+    - dmaengine: ALTERA_MSGDMA depends on HAS_IOMEM
+    - dmaengine: QCOM_HIDMA_MGMT depends on HAS_IOMEM
+    - dmaengine: stedma40: add missing iounmap() on error in d40_probe()
+    - afs: Fix an IS_ERR() vs NULL check
+    - mm/memory-failure: make sure wait for page writeback in memory_failure
+    - kvm: LAPIC: Restore guard to prevent illegal APIC register access
+    - batman-adv: Avoid WARN_ON timing related checks
+    - net: ipv4: fix memory leak in netlbl_cipsov4_add_std
+    - vrf: fix maximum MTU
+    - net: rds: fix memory leak in rds_recvmsg
+    - net: lantiq: disable interrupt before sheduling NAPI
+    - udp: fix race between close() and udp_abort()
+    - rtnetlink: Fix regression in bridge VLAN configuration
+    - net/sched: act_ct: handle DNAT tuple collision
+    - net/mlx5e: Remove dependency in IPsec initialization flows
+    - net/mlx5e: Fix page reclaim for dead peer hairpin
+    - net/mlx5: Consider RoCE cap before init RDMA resources
+    - net/mlx5e: allow TSO on VXLAN over VLAN topologies
+    - net/mlx5e: Block offload of outer header csum for UDP tunnels
+    - netfilter: synproxy: Fix out of bounds when parsing TCP options
+    - sch_cake: Fix out of bounds when parsing TCP options and header
+    - alx: Fix an error handling path in 'alx_probe()'
+    - net: stmmac: dwmac1000: Fix extended MAC address registers definition
+    - net: make get_net_ns return error if NET_NS is disabled
+    - qlcnic: Fix an error handling path in 'qlcnic_probe()'
+    - netxen_nic: Fix an error handling path in 'netxen_nic_probe()'
+    - net: qrtr: fix OOB Read in qrtr_endpoint_post
+    - ptp: improve max_adj check against unreasonable values
+    - net: cdc_ncm: switch to eth%d interface naming
+    - lantiq: net: fix duplicated skb in rx descriptor ring
+    - net: usb: fix possible use-after-free in smsc75xx_bind
+    - net: fec_ptp: fix issue caused by refactor the fec_devtype
+    - net: ipv4: fix memory leak in ip_mc_add1_src
+    - net/af_unix: fix a data-race in unix_dgram_sendmsg / unix_release_sock
+    - be2net: Fix an error handling path in 'be_probe()'
+    - net: hamradio: fix memory leak in mkiss_close
+    - net: cdc_eem: fix tx fixup skb leak
+    - cxgb4: fix wrong shift.
+    - bnxt_en: Rediscover PHY capabilities after firmware reset
+    - bnxt_en: Call bnxt_ethtool_free() in bnxt_init_one() error path
+    - icmp: don't send out ICMP messages with a source address of 0.0.0.0
+    - net: ethernet: fix potential use-after-free in ec_bhf_remove
+    - regulator: bd70528: Fix off-by-one for buck123 .n_voltages setting
+    - ASoC: rt5659: Fix the lost powers for the HDA header
+    - spi: stm32-qspi: Always wait BUSY bit to be cleared in stm32_qspi_wait_cmd()
+    - pinctrl: ralink: rt2880: avoid to error in calls is pin is already enabled
+    - radeon: use memcpy_to/fromio for UVD fw upload
+    - hwmon: (scpi-hwmon) shows the negative temperature properly
+    - can: bcm: fix infoleak in struct bcm_msg_head
+    - can: bcm/raw/isotp: use per module netdevice notifier
+    - can: j1939: fix Use-after-Free, hold skb ref while in use
+    - can: mcba_usb: fix memory leak in mcba_usb
+    - usb: core: hub: Disable autosuspend for Cypress CY7C65632
+    - tracing: Do not stop recording cmdlines when tracing is off
+    - tracing: Do not stop recording comms if the trace file is being read
+    - tracing: Do no increment trace_clock_global() by one
+    - PCI: Mark TI C667X to avoid bus reset
+    - PCI: Mark some NVIDIA GPUs to avoid bus reset
+    - PCI: aardvark: Don't rely on jiffies while holding spinlock
+    - PCI: aardvark: Fix kernel panic during PIO transfer
+    - PCI: Add ACS quirk for Broadcom BCM57414 NIC
+    - PCI: Work around Huawei Intelligent NIC VF FLR erratum
+    - KVM: x86: Immediately reset the MMU context when the SMM flag is cleared
+    - ARCv2: save ABI registers across signal handling
+    - x86/process: Check PF_KTHREAD and not current->mm for kernel threads
+    - x86/pkru: Write hardware init value to PKRU when xstate is init
+    - x86/fpu: Reset state for all signal restore failures
+    - dmaengine: pl330: fix wrong usage of spinlock flags in dma_cyclc
+    - cfg80211: make certificate generation more robust
+    - cfg80211: avoid double free of PMSR request
+    - net: ll_temac: Make sure to free skb when it is completely used
+    - net: ll_temac: Fix TX BD buffer overwrite
+    - net: bridge: fix vlan tunnel dst null pointer dereference
+    - net: bridge: fix vlan tunnel dst refcnt when egressing
+    - mm/slub: clarify verification reporting
+    - mm/slub: fix redzoning for small allocations
+    - mm/slub.c: include swab.h
+    - net: stmmac: disable clocks in stmmac_remove_config_dt()
+    - net: fec_ptp: add clock rate zero check
+    - tools headers UAPI: Sync linux/in.h copy with the kernel sources
+    - KVM: arm/arm64: Fix KVM_VGIC_V3_ADDR_TYPE_REDIST read
+    - ARM: OMAP: replace setup_irq() by request_irq()
+    - clocksource/drivers/timer-ti-dm: Add clockevent and clocksource support
+    - clocksource/drivers/timer-ti-dm: Prepare to handle dra7 timer wrap issue
+    - clocksource/drivers/timer-ti-dm: Handle dra7 timer wrap errata i940
+    - usb: dwc3: debugfs: Add and remove endpoint dirs dynamically
+    - usb: dwc3: core: fix kernel panic when do reboot
+    - Linux 5.4.128
+  * linux-azure CIFS DFS oops (LP: #1935833)
+    - cifs: get rid of unused parameter in reconn_setup_dfs_targets()
+    - cifs: handle empty list of targets in cifs_reconnect()
+  * pmtu.sh from net in ubuntu_kernel_selftests failed with no error message
+    (LP: #1887661)
+    - selftests: pmtu.sh: improve the test result processing
+  * cifs: On cifs_reconnect, resolve the hostname again (LP: #1929831)
+    - cifs: rename reconn_inval_dfs_target()
+    - cifs: Simplify reconnect code when dfs upcall is enabled
+    - cifs: Avoid error pointer dereference
+    - cifs: On cifs_reconnect, resolve the hostname again.
+  * Pixel format change broken for Elgato Cam Link 4K (LP: #1932367)
+    - (upstream) media: uvcvideo: Fix pixel format change for Elgato Cam Link 4K
+  * Focal update: v5.4.127 upstream stable release (LP: #1933851)
+    - net: ieee802154: fix null deref in parse dev addr
+    - HID: quirks: Set INCREMENT_USAGE_ON_DUPLICATE for Saitek X65
+    - HID: hid-input: add mapping for emoji picker key
+    - HID: hid-sensor-hub: Return error for hid_set_field() failure
+    - HID: quirks: Add quirk for Lenovo optical mouse
+    - HID: multitouch: set Stylus suffix for Stylus-application devices, too
+    - HID: Add BUS_VIRTUAL to hid_connect logging
+    - HID: usbhid: fix info leak in hid_submit_ctrl
+    - drm/tegra: sor: Do not leak runtime PM reference
+    - ARM: OMAP2+: Fix build warning when mmc_omap is not built
+    - gfs2: Prevent direct-I/O write fallback errors from getting lost
+    - HID: gt683r: add missing MODULE_DEVICE_TABLE
+    - riscv: Use -mno-relax when using lld linker
+    - gfs2: Fix use-after-free in gfs2_glock_shrink_scan
+    - scsi: target: core: Fix warning on realtime kernels
+    - ethernet: myri10ge: Fix missing error code in myri10ge_probe()
+    - scsi: qedf: Do not put host in qedf_vport_create() unconditionally
+    - scsi: scsi_devinfo: Add blacklist entry for HPE OPEN-V
+    - nvme-loop: reset queue count to 1 in nvme_loop_destroy_io_queues()
+    - nvme-loop: clear NVME_LOOP_Q_LIVE when nvme_loop_configure_admin_queue()
+      fails
+    - nvme-loop: check for NVME_LOOP_Q_LIVE in nvme_loop_destroy_admin_queue()
+    - net: ipconfig: Don't override command-line hostnames or domains
+    - drm/amd/display: Allow bandwidth validation for 0 streams.
+    - rtnetlink: Fix missing error code in rtnl_bridge_notify()
+    - net/x25: Return the correct errno code
+    - net: Return the correct errno code
+    - fib: Return the correct errno code
+    - Linux 5.4.127
+  * Focal update: v5.4.126 upstream stable release (LP: #1933369)
+    - proc: Check /proc/$pid/attr/ writes against file opener
+    - proc: Track /proc/$pid/attr/ opener mm_struct
+    - ASoC: max98088: fix ni clock divider calculation
+    - spi: Fix spi device unregister flow
+    - net/nfc/rawsock.c: fix a permission check bug
+    - usb: cdns3: Fix runtime PM imbalance on error
+    - ASoC: Intel: bytcr_rt5640: Add quirk for the Glavey TM800A550L tablet
+    - ASoC: Intel: bytcr_rt5640: Add quirk for the Lenovo Miix 3-830 tablet
+    - vfio-ccw: Serialize FSM IDLE state with I/O completion
+    - ASoC: sti-sas: add missing MODULE_DEVICE_TABLE
+    - spi: sprd: Add missing MODULE_DEVICE_TABLE
+    - isdn: mISDN: netjet: Fix crash in nj_probe:
+    - bonding: init notify_work earlier to avoid uninitialized use
+    - netlink: disable IRQs for netlink_lock_table()
+    - net: mdiobus: get rid of a BUG_ON()
+    - cgroup: disable controllers at parse time
+    - wq: handle VM suspension in stall detection
+    - net/qla3xxx: fix schedule while atomic in ql_sem_spinlock
+    - RDS tcp loopback connection can hang
+    - scsi: bnx2fc: Return failure if io_req is already in ABTS processing
+    - scsi: vmw_pvscsi: Set correct residual data length
+    - scsi: hisi_sas: Drop free_irq() of devm_request_irq() allocated irq
+    - scsi: target: qla2xxx: Wait for stop_phase1 at WWN removal
+    - net: macb: ensure the device is available before accessing GEMGXL control
+      registers
+    - net: appletalk: cops: Fix data race in cops_probe1
+    - net: dsa: microchip: enable phy errata workaround on 9567
+    - nvme-fabrics: decode host pathing error for connect
+    - MIPS: Fix kernel hang under FUNCTION_GRAPH_TRACER and PREEMPT_TRACER
+    - dm verity: fix require_signatures module_param permissions
+    - bnx2x: Fix missing error code in bnx2x_iov_init_one()
+    - nvme-tcp: remove incorrect Kconfig dep in BLK_DEV_NVME
+    - powerpc/fsl: set fsl,i2c-erratum-a004447 flag for P2041 i2c controllers
+    - powerpc/fsl: set fsl,i2c-erratum-a004447 flag for P1010 i2c controllers
+    - spi: Don't have controller clean up spi device before driver unbind
+    - spi: Cleanup on failure of initial setup
+    - i2c: mpc: Make use of i2c_recover_bus()
+    - i2c: mpc: implement erratum A-004447 workaround
+    - x86/boot: Add .text.* to setup.ld
+    - spi: bcm2835: Fix out-of-bounds access with more than 4 slaves
+    - drm: Fix use-after-free read in drm_getunique()
+    - drm: Lock pointer access in drm_master_release()
+    - kvm: avoid speculation-based attacks from out-of-range memslot accesses
+    - staging: rtl8723bs: Fix uninitialized variables
+    - btrfs: return value from btrfs_mark_extent_written() in case of error
+    - btrfs: promote debugging asserts to full-fledged checks in validate_super
+    - cgroup1: don't allow '\n' in renaming
+    - USB: f_ncm: ncm_bitrate (speed) is unsigned
+    - usb: f_ncm: only first packet of aggregate needs to start timer
+    - usb: pd: Set PD_T_SINK_WAIT_CAP to 310ms
+    - usb: dwc3: ep0: fix NULL pointer exception
+    - usb: musb: fix MUSB_QUIRK_B_DISCONNECT_99 handling
+    - usb: typec: wcove: Use LE to CPU conversion when accessing msg->header
+    - usb: typec: ucsi: Clear PPM capability data in ucsi_init() error path
+    - usb: gadget: f_fs: Ensure io_completion_wq is idle during unbind
+    - USB: serial: ftdi_sio: add NovaTech OrionMX product ID
+    - USB: serial: omninet: add device id for Zyxel Omni 56K Plus
+    - USB: serial: quatech2: fix control-request directions
+    - USB: serial: cp210x: fix alternate function for CP2102N QFN20
+    - usb: gadget: eem: fix wrong eem header operation
+    - usb: fix various gadgets null ptr deref on 10gbps cabling.
+    - usb: fix various gadget panics on 10gbps cabling
+    - regulator: core: resolve supply for boot-on/always-on regulators
+    - regulator: max77620: Use device_set_of_node_from_dev()
+    - usb: typec: mux: Fix copy-paste mistake in typec_mux_match
+    - RDMA/ipoib: Fix warning caused by destroying non-initial netns
+    - RDMA/mlx4: Do not map the core_clock page to user space unless enabled
+    - vmlinux.lds.h: Avoid orphan section with !SMP
+    - perf: Fix data race between pin_count increment/decrement
+    - sched/fair: Make sure to update tg contrib for blocked load
+    - KVM: x86: Ensure liveliness of nested VM-Enter fail tracepoint message
+    - IB/mlx5: Fix initializing CQ fragments buffer
+    - NFS: Fix a potential NULL dereference in nfs_get_client()
+    - NFSv4: Fix deadlock between nfs4_evict_inode() and nfs4_opendata_get_inode()
+    - perf session: Correct buffer copying when peeking events
+    - kvm: fix previous commit for 32-bit builds
+    - NFS: Fix use-after-free in nfs4_init_client()
+    - NFSv4: Fix second deadlock in nfs4_evict_inode()
+    - NFSv4: nfs4_proc_set_acl needs to restore NFS_CAP_UIDGID_NOMAP on error.
+    - scsi: core: Fix error handling of scsi_host_alloc()
+    - scsi: core: Fix failure handling of scsi_add_host_with_dma()
+    - scsi: core: Put .shost_dev in failure path if host state changes to RUNNING
+    - scsi: core: Only put parent device if host state differs from SHOST_CREATED
+    - ftrace: Do not blindly read the ip address in ftrace_bug()
+    - tracing: Correct the length check which causes memory corruption
+    - proc: only require mm_struct for writing
+    - Linux 5.4.126
+  * Focal update: v5.4.125 upstream stable release (LP: #1932957)
+    - btrfs: tree-checker: do not error out if extent ref hash doesn't match
+    - net: usb: cdc_ncm: don't spew notifications
+    - ALSA: usb: update old-style static const declaration
+    - nl80211: validate key indexes for cfg80211_registered_device
+    - hwmon: (dell-smm-hwmon) Fix index values
+    - netfilter: conntrack: unregister ipv4 sockopts on error unwind
+    - efi: Allow EFI_MEMORY_XP and EFI_MEMORY_RO both to be cleared
+    - efi: cper: fix snprintf() use in cper_dimm_err_location()
+    - vfio/pci: Fix error return code in vfio_ecap_init()
+    - vfio/pci: zap_vma_ptes() needs MMU
+    - samples: vfio-mdev: fix error handing in mdpy_fb_probe()
+    - vfio/platform: fix module_put call in error flow
+    - ipvs: ignore IP_VS_SVC_F_HASHED flag when adding service
+    - HID: pidff: fix error return code in hid_pidff_init()
+    - HID: i2c-hid: fix format string mismatch
+    - net/sched: act_ct: Fix ct template allocation for zone 0
+    - ACPICA: Clean up context mutex during object deletion
+    - netfilter: nft_ct: skip expectations for confirmed conntrack
+    - netfilter: nfnetlink_cthelper: hit EBUSY on updates if size mismatches
+    - ieee802154: fix error return code in ieee802154_add_iface()
+    - ieee802154: fix error return code in ieee802154_llsec_getparams()
+    - ixgbevf: add correct exception tracing for XDP
+    - ipv6: Fix KASAN: slab-out-of-bounds Read in fib6_nh_flush_exceptions
+    - ice: write register with correct offset
+    - ice: Fix VFR issues for AVF drivers that expect ATQLEN cleared
+    - ice: Allow all LLDP packets from PF to Tx
+    - i2c: qcom-geni: Add shutdown callback for i2c
+    - i40e: optimize for XDP_REDIRECT in xsk path
+    - i40e: add correct exception tracing for XDP
+    - arm64: dts: ls1028a: fix memory node
+    - arm64: dts: zii-ultra: fix 12V_MAIN voltage
+    - ARM: dts: imx7d-meerkat96: Fix the 'tuning-step' property
+    - ARM: dts: imx7d-pico: Fix the 'tuning-step' property
+    - ARM: dts: imx: emcon-avari: Fix nxp,pca8574 #gpio-cells
+    - bus: ti-sysc: Fix flakey idling of uarts and stop using swsup_sidle_act
+    - tipc: add extack messages for bearer/media failure
+    - tipc: fix unique bearer names sanity check
+    - Bluetooth: fix the erroneous flush_work() order
+    - Bluetooth: use correct lock to prevent UAF of hdev object
+    - net: caif: added cfserl_release function
+    - net: caif: add proper error handling
+    - net: caif: fix memory leak in caif_device_notify
+    - net: caif: fix memory leak in cfusbl_device_notify
+    - HID: i2c-hid: Skip ELAN power-on command after reset
+    - HID: magicmouse: fix NULL-deref on disconnect
+    - HID: multitouch: require Finger field to mark Win8 reports as MT
+    - ALSA: timer: Fix master timer notification
+    - ALSA: hda: Fix for mute key LED for HP Pavilion 15-CK0xx
+    - ARM: dts: imx6dl-yapp4: Fix RGMII connection to QCA8334 switch
+    - ARM: dts: imx6q-dhcom: Add PU,VDD1P1,VDD2P5 regulators
+    - ext4: fix bug on in ext4_es_cache_extent as ext4_split_extent_at failed
+    - usb: dwc2: Fix build in periphal-only mode
+    - pid: take a reference when initializing `cad_pid`
+    - ocfs2: fix data corruption by fallocate
+    - nfc: fix NULL ptr dereference in llcp_sock_getname() after failed connect
+    - drm/amdgpu: Don't query CE and UE errors
+    - drm/amdgpu: make sure we unpin the UVD BO
+    - x86/apic: Mark _all_ legacy interrupts when IO/APIC is missing
+    - btrfs: mark ordered extent and inode with error if we fail to finish
+    - btrfs: fix error handling in btrfs_del_csums
+    - btrfs: return errors from btrfs_del_csums in cleanup_ref_head
+    - btrfs: fixup error handling in fixup_inode_link_counts
+    - mm, hugetlb: fix simple resv_huge_pages underflow on UFFDIO_COPY
+    - bnxt_en: Remove the setting of dev_port.
+    - mm: add thp_order
+    - XArray: add xa_get_order
+    - XArray: add xas_split
+    - mm/filemap: fix storing to a THP shadow entry
+    - btrfs: fix unmountable seed device after fstrim
+    - KVM: SVM: Truncate GPR value for DR and CR accesses in !64-bit mode
+    - KVM: arm64: Fix debug register indexing
+    - lib/lz4: explicitly support in-place decompression
+    - xen-pciback: redo VF placement in the virtual topology
+    - i2c: qcom-geni: Suspend and resume the bus during SYSTEM_SLEEP_PM ops
+    - neighbour: allow NUD_NOARP entries to be forced GCed
+    - Linux 5.4.125
+
+  [ Ubuntu: 5.4.0-80.90 ]
+
+  * CVE-2021-33909
+    - SAUCE: seq_file: Disallow extremely large seq buffer allocations
+
+  [ Ubuntu: 5.4.0-79.88 ]
+
+  * focal/linux: 5.4.0-79.88 -proposed tracker (LP: #1934343)
+  * lxd exec fails (LP: #1934187)
+    - SAUCE: Revert "proc: Check /proc/$pid/attr/ writes against file opener"
+
+  [ Ubuntu: 5.4.0-78.87 ]
+
+  * focal/linux: 5.4.0-78.87 -proposed tracker (LP: #1932478)
+  * Packaging resync (LP: #1786013)
+    - [Packaging] resync getabis
+    - [Packaging] update helper scripts
+    - update dkms package versions
+  * Disable hv-kvp-daemon.service on certain instance types (LP: #1932081)
+    - [Packaging]: Add kernel command line condition to hv-kvp-daemon service
+  * QLogic Direct-Connect host can't discover SCSI-FC or NVMe/FC devices
+    (LP: #1860724)
+    - scsi: qla2xxx: Serialize fc_port alloc in N2N
+    - scsi: qla2xxx: Set Nport ID for N2N
+    - scsi: qla2xxx: Fix point-to-point (N2N) device discovery issue
+    - scsi: qla2xxx: Fix N2N and NVMe connect retry failure
+  * [SRU] Add support for E810 NIC to Ice Driver in Focal (LP: #1912511)
+    - ice: add additional E810 device id
+  * Focal update: v5.4.124 upstream stable release (LP: #1931166)
+    - ALSA: hda/realtek: Headphone volume is controlled by Front mixer
+    - ALSA: usb-audio: scarlett2: Fix device hang with ehci-pci
+    - ALSA: usb-audio: scarlett2: Improve driver startup messages
+    - cifs: set server->cipher_type to AES-128-CCM for SMB3.0
+    - NFSv4: Fix a NULL pointer dereference in pnfs_mark_matching_lsegs_return()
+    - iommu/vt-d: Fix sysfs leak in alloc_iommu()
+    - perf intel-pt: Fix sample instruction bytes
+    - perf intel-pt: Fix transaction abort handling
+    - perf scripts python: exported-sql-viewer.py: Fix copy to clipboard from Top
+      Calls by elapsed Time report
+    - perf scripts python: exported-sql-viewer.py: Fix Array TypeError
+    - perf scripts python: exported-sql-viewer.py: Fix warning display
+    - proc: Check /proc/$pid/attr/ writes against file opener
+    - net: hso: fix control-request directions
+    - ath10k: Validate first subframe of A-MSDU before processing the list
+    - dm snapshot: properly fix a crash when an origin has no snapshots
+    - drm/amdgpu/vcn1: add cancel_delayed_work_sync before power gate
+    - drm/amdgpu/vcn2.0: add cancel_delayed_work_sync before power gate
+    - drm/amdgpu/vcn2.5: add cancel_delayed_work_sync before power gate
+    - selftests/gpio: Use TEST_GEN_PROGS_EXTENDED
+    - selftests/gpio: Move include of lib.mk up
+    - selftests/gpio: Fix build when source tree is read only
+    - kgdb: fix gcc-11 warnings harder
+    - Documentation: seccomp: Fix user notification documentation
+    - serial: core: fix suspicious security_locked_down() call
+    - misc/uss720: fix memory leak in uss720_probe
+    - thunderbolt: dma_port: Fix NVM read buffer bounds and offset issue
+    - mei: request autosuspend after sending rx flow control
+    - staging: iio: cdc: ad7746: avoid overwrite of num_channels
+    - iio: gyro: fxas21002c: balance runtime power in error path
+    - iio: adc: ad7768-1: Fix too small buffer passed to
+      iio_push_to_buffers_with_timestamp()
+    - iio: adc: ad7124: Fix missbalanced regulator enable / disable on error.
+    - iio: adc: ad7124: Fix potential overflow due to non sequential channel
+      numbers
+    - iio: adc: ad7793: Add missing error code in ad7793_setup()
+    - serial: 8250_pci: Add support for new HPE serial device
+    - serial: 8250_pci: handle FL_NOIRQ board flag
+    - USB: trancevibrator: fix control-request direction
+    - USB: usbfs: Don't WARN about excessively large memory allocations
+    - serial: tegra: Fix a mask operation that is always true
+    - serial: sh-sci: Fix off-by-one error in FIFO threshold register setting
+    - serial: rp2: use 'request_firmware' instead of 'request_firmware_nowait'
+    - USB: serial: ti_usb_3410_5052: add startech.com device id
+    - USB: serial: option: add Telit LE910-S1 compositions 0x7010, 0x7011
+    - USB: serial: ftdi_sio: add IDs for IDS GmbH Products
+    - USB: serial: pl2303: add device id for ADLINK ND-6530 GC
+    - thermal/drivers/intel: Initialize RW trip to THERMAL_TEMP_INVALID
+    - usb: dwc3: gadget: Properly track pending and queued SG
+    - usb: gadget: udc: renesas_usb3: Fix a race in usb3_start_pipen()
+    - net: usb: fix memory leak in smsc75xx_bind
+    - spi: spi-geni-qcom: Fix use-after-free on unbind
+    - Bluetooth: cmtp: fix file refcount when cmtp_attach_device fails
+    - fs/nfs: Use fatal_signal_pending instead of signal_pending
+    - NFS: fix an incorrect limit in filelayout_decode_layout()
+    - NFS: Fix an Oopsable condition in __nfs_pageio_add_request()
+    - NFS: Don't corrupt the value of pg_bytes_written in nfs_do_recoalesce()
+    - NFSv4: Fix v4.0/v4.1 SEEK_DATA return -ENOTSUPP when set NFS_V4_2 config
+    - drm/meson: fix shutdown crash when component not probed
+    - net/mlx5e: Fix multipath lag activation
+    - net/mlx5e: Fix nullptr in add_vlan_push_action()
+    - net/mlx4: Fix EEPROM dump support
+    - Revert "net:tipc: Fix a double free in tipc_sk_mcast_rcv"
+    - tipc: wait and exit until all work queues are done
+    - tipc: skb_linearize the head skb when reassembling msgs
+    - spi: spi-fsl-dspi: Fix a resource leak in an error handling path
+    - net: dsa: mt7530: fix VLAN traffic leaks
+    - net: dsa: fix a crash if ->get_sset_count() fails
+    - net: dsa: sja1105: error out on unsupported PHY mode
+    - i2c: s3c2410: fix possible NULL pointer deref on read message after write
+    - i2c: i801: Don't generate an interrupt on bus reset
+    - i2c: sh_mobile: Use new clock calculation formulas for RZ/G2E
+    - perf jevents: Fix getting maximum number of fds
+    - platform/x86: hp_accel: Avoid invoking _INI to speed up resume
+    - gpio: cadence: Add missing MODULE_DEVICE_TABLE
+    - Revert "media: usb: gspca: add a missed check for goto_low_power"
+    - Revert "ALSA: sb: fix a missing check of snd_ctl_add"
+    - Revert "serial: max310x: pass return value of spi_register_driver"
+    - serial: max310x: unregister uart driver in case of failure and abort
+    - Revert "net: fujitsu: fix a potential NULL pointer dereference"
+    - net: fujitsu: fix potential null-ptr-deref
+    - Revert "net/smc: fix a NULL pointer dereference"
+    - net: caif: remove BUG_ON(dev == NULL) in caif_xmit
+    - Revert "char: hpet: fix a missing check of ioremap"
+    - char: hpet: add checks after calling ioremap
+    - Revert "ALSA: gus: add a check of the status of snd_ctl_add"
+    - Revert "ALSA: usx2y: Fix potential NULL pointer dereference"
+    - Revert "isdn: mISDNinfineon: fix potential NULL pointer dereference"
+    - isdn: mISDNinfineon: check/cleanup ioremap failure correctly in setup_io
+    - Revert "ath6kl: return error code in ath6kl_wmi_set_roam_lrssi_cmd()"
+    - ath6kl: return error code in ath6kl_wmi_set_roam_lrssi_cmd()
+    - Revert "isdn: mISDN: Fix potential NULL pointer dereference of kzalloc"
+    - isdn: mISDN: correctly handle ph_info allocation failure in hfcsusb_ph_info
+    - Revert "dmaengine: qcom_hidma: Check for driver register failure"
+    - dmaengine: qcom_hidma: comment platform_driver_register call
+    - Revert "libertas: add checks for the return value of sysfs_create_group"
+    - libertas: register sysfs groups properly
+    - Revert "ASoC: cs43130: fix a NULL pointer dereference"
+    - ASoC: cs43130: handle errors in cs43130_probe() properly
+    - Revert "media: dvb: Add check on sp8870_readreg"
+    - media: dvb: Add check on sp8870_readreg return
+    - Revert "media: gspca: mt9m111: Check write_bridge for timeout"
+    - media: gspca: mt9m111: Check write_bridge for timeout
+    - Revert "media: gspca: Check the return value of write_bridge for timeout"
+    - media: gspca: properly check for errors in po1030_probe()
+    - Revert "net: liquidio: fix a NULL pointer dereference"
+    - net: liquidio: Add missing null pointer checks
+    - Revert "brcmfmac: add a check for the status of usb_register"
+    - brcmfmac: properly check for bus register errors
+    - btrfs: return whole extents in fiemap
+    - scsi: BusLogic: Fix 64-bit system enumeration error for Buslogic
+    - openrisc: Define memory barrier mb
+    - btrfs: do not BUG_ON in link_to_fixup_dir
+    - platform/x86: hp-wireless: add AMD's hardware id to the supported list
+    - platform/x86: intel_punit_ipc: Append MODULE_DEVICE_TABLE for ACPI
+    - platform/x86: touchscreen_dmi: Add info for the Mediacom Winpad 7.0 W700
+      tablet
+    - SMB3: incorrect file id in requests compounded with open
+    - drm/amd/display: Disconnect non-DP with no EDID
+    - drm/amd/amdgpu: fix refcount leak
+    - drm/amdgpu: Fix a use-after-free
+    - drm/amd/amdgpu: fix a potential deadlock in gpu reset
+    - net: netcp: Fix an error message
+    - net: dsa: fix error code getting shifted with 4 in dsa_slave_get_sset_count
+    - ASoC: cs42l42: Regmap must use_single_read/write
+    - vfio-ccw: Check initialized flag in cp_init()
+    - net: really orphan skbs tied to closing sk
+    - net: fec: fix the potential memory leak in fec_enet_init()
+    - net: mdio: thunder: Fix a double free issue in the .remove function
+    - net: mdio: octeon: Fix some double free issues
+    - openvswitch: meter: fix race when getting now_ms.
+    - tls splice: check SPLICE_F_NONBLOCK instead of MSG_DONTWAIT
+    - net: sched: fix packet stuck problem for lockless qdisc
+    - net: sched: fix tx action rescheduling issue during deactivation
+    - net: sched: fix tx action reschedule issue with stopped queue
+    - net: hso: check for allocation failure in hso_create_bulk_serial_device()
+    - net: bnx2: Fix error return code in bnx2_init_board()
+    - bnxt_en: Include new P5 HV definition in VF check.
+    - mld: fix panic in mld_newpack()
+    - gve: Check TX QPL was actually assigned
+    - gve: Update mgmt_msix_idx if num_ntfy changes
+    - gve: Add NULL pointer checks when freeing irqs.
+    - gve: Upgrade memory barrier in poll routine
+    - gve: Correct SKB queue index validation.
+    - cxgb4: avoid accessing registers when clearing filters
+    - staging: emxx_udc: fix loop in _nbu2ss_nuke()
+    - ASoC: cs35l33: fix an error code in probe()
+    - bpf: Set mac_len in bpf_skb_change_head
+    - ixgbe: fix large MTU request from VF
+    - scsi: libsas: Use _safe() loop in sas_resume_port()
+    - net: lantiq: fix memory corruption in RX ring
+    - ipv6: record frag_max_size in atomic fragments in input path
+    - ALSA: usb-audio: scarlett2: snd_scarlett_gen2_controls_create() can be
+      static
+    - net: ethernet: mtk_eth_soc: Fix packet statistics support for MT7628/88
+    - sch_dsmark: fix a NULL deref in qdisc_reset()
+    - MIPS: alchemy: xxs1500: add gpio-au1000.h header file
+    - MIPS: ralink: export rt_sysc_membase for rt2880_wdt.c
+    - drm/i915/display: fix compiler warning about array overrun
+    - i915: fix build warning in intel_dp_get_link_status()
+    - drivers/net/ethernet: clean up unused assignments
+    - net: hns3: check the return of skb_checksum_help()
+    - Revert "Revert "ALSA: usx2y: Fix potential NULL pointer dereference""
+    - net: hso: bail out on interrupt URB allocation failure
+    - neighbour: Prevent Race condition in neighbour subsytem
+    - usb: core: reduce power-on-good delay time of root hub
+    - Linux 5.4.124
+  * Focal update: v5.4.123 upstream stable release (LP: #1931160)
+    - usb: dwc3: gadget: Enable suspend events
+    - perf unwind: Fix separate debug info files when using elfutils' libdw's
+      unwinder
+    - perf unwind: Set userdata for all __report_module() paths
+    - NFC: nci: fix memory leak in nci_allocate_device
+    - Linux 5.4.123
+  * Focal update: v5.4.122 upstream stable release (LP: #1931159)
+    - firmware: arm_scpi: Prevent the ternary sign expansion bug
+    - openrisc: Fix a memory leak
+    - RDMA/siw: Properly check send and receive CQ pointers
+    - RDMA/siw: Release xarray entry
+    - RDMA/rxe: Clear all QP fields if creation failed
+    - scsi: ufs: core: Increase the usable queue depth
+    - scsi: qla2xxx: Fix error return code in qla82xx_write_flash_dword()
+    - RDMA/mlx5: Recover from fatal event in dual port mode
+    - RDMA/core: Don't access cm_id after its destruction
+    - platform/mellanox: mlxbf-tmfifo: Fix a memory barrier issue
+    - platform/x86: dell-smbios-wmi: Fix oops on rmmod dell_smbios
+    - RDMA/uverbs: Fix a NULL vs IS_ERR() bug
+    - ptrace: make ptrace() fail if the tracee changed its pid unexpectedly
+    - nvmet: seset ns->file when open fails
+    - locking/mutex: clear MUTEX_FLAGS if wait_list is empty due to signal
+    - btrfs: avoid RCU stalls while running delayed iputs
+    - cifs: fix memory leak in smb2_copychunk_range
+    - ALSA: dice: fix stream format for TC Electronic Konnekt Live at high
+      sampling transfer frequency
+    - ALSA: intel8x0: Don't update period unless prepared
+    - ALSA: line6: Fix racy initialization of LINE6 MIDI
+    - ALSA: dice: fix stream format at middle sampling rate for Alesis iO 26
+    - ALSA: firewire-lib: fix calculation for size of IR context payload
+    - ALSA: usb-audio: Validate MS endpoint descriptors
+    - ALSA: bebob/oxfw: fix Kconfig entry for Mackie d.2 Pro
+    - ALSA: hda: fixup headset for ASUS GU502 laptop
+    - Revert "ALSA: sb8: add a check for request_region"
+    - ALSA: firewire-lib: fix check for the size of isochronous packet payload
+    - ALSA: hda/realtek: reset eapd coeff to default value for alc287
+    - ALSA: hda/realtek: Add some CLOVE SSIDs of ALC293
+    - ALSA: hda/realtek: Fix silent headphone output on ASUS UX430UA
+    - ALSA: hda/realtek: Add fixup for HP OMEN laptop
+    - ALSA: hda/realtek: Add fixup for HP Spectre x360 15-df0xxx
+    - uio_hv_generic: Fix a memory leak in error handling paths
+    - Revert "rapidio: fix a NULL pointer dereference when create_workqueue()
+      fails"
+    - rapidio: handle create_workqueue() failure
+    - Revert "serial: mvebu-uart: Fix to avoid a potential NULL pointer
+      dereference"
+    - drm/amdgpu: disable 3DCGCG on picasso/raven1 to avoid compute hang
+    - drm/amdgpu: update gc golden setting for Navi12
+    - drm/amdgpu: update sdma golden setting for Navi12
+    - mmc: sdhci-pci-gli: increase 1.8V regulator wait
+    - xen-pciback: reconfigure also from backend watch handler
+    - dm snapshot: fix crash with transient storage and zero chunk size
+    - Revert "video: hgafb: fix potential NULL pointer dereference"
+    - Revert "net: stmicro: fix a missing check of clk_prepare"
+    - Revert "leds: lp5523: fix a missing check of return value of lp55xx_read"
+    - Revert "hwmon: (lm80) fix a missing check of bus read in lm80 probe"
+    - Revert "video: imsttfb: fix potential NULL pointer dereferences"
+    - Revert "ecryptfs: replace BUG_ON with error handling code"
+    - Revert "scsi: ufs: fix a missing check of devm_reset_control_get"
+    - Revert "gdrom: fix a memory leak bug"
+    - cdrom: gdrom: deallocate struct gdrom_unit fields in remove_gdrom
+    - cdrom: gdrom: initialize global variable at init time
+    - Revert "media: rcar_drif: fix a memory disclosure"
+    - Revert "rtlwifi: fix a potential NULL pointer dereference"
+    - Revert "qlcnic: Avoid potential NULL pointer dereference"
+    - Revert "niu: fix missing checks of niu_pci_eeprom_read"
+    - ethernet: sun: niu: fix missing checks of niu_pci_eeprom_read()
+    - net: stmicro: handle clk_prepare() failure during init
+    - scsi: ufs: handle cleanup correctly on devm_reset_control_get error
+    - net: rtlwifi: properly check for alloc_workqueue() failure
+    - ics932s401: fix broken handling of errors when word reading fails
+    - leds: lp5523: check return value of lp5xx_read and jump to cleanup code
+    - qlcnic: Add null check after calling netdev_alloc_skb
+    - video: hgafb: fix potential NULL pointer dereference
+    - vgacon: Record video mode changes with VT_RESIZEX
+    - vt: Fix character height handling with VT_RESIZEX
+    - tty: vt: always invoke vc->vc_sw->con_resize callback
+    - nvme-multipath: fix double initialization of ANA state
+    - ext4: fix error handling in ext4_end_enable_verity()
+    - Bluetooth: L2CAP: Fix handling LE modes by L2CAP_OPTIONS
+    - nvmet: use new ana_log_size instead the old one
+    - video: hgafb: correctly handle card detect failure during probe
+    - Bluetooth: SMP: Fail if remote and local public keys are identical
+    - Linux 5.4.122
+  * Focal update: v5.4.121 upstream stable release (LP: #1931158)
+    - x86/msr: Fix wr/rdmsr_safe_regs_on_cpu() prototypes
+    - kgdb: fix gcc-11 warning on indentation
+    - usb: sl811-hcd: improve misleading indentation
+    - cxgb4: Fix the -Wmisleading-indentation warning
+    - isdn: capi: fix mismatched prototypes
+    - pinctrl: ingenic: Improve unreachable code generation
+    - xsk: Simplify detection of empty and full rings
+    - virtio_net: Do not pull payload in skb->head
+    - PCI: thunder: Fix compile testing
+    - dmaengine: dw-edma: Fix crash on loading/unloading driver
+    - ARM: 9066/1: ftrace: pause/unpause function graph tracer in cpu_suspend()
+    - ACPI / hotplug / PCI: Fix reference count leak in enable_slot()
+    - Input: elants_i2c - do not bind to i2c-hid compatible ACPI instantiated
+      devices
+    - Input: silead - add workaround for x86 BIOS-es which bring the chip up in a
+      stuck state
+    - um: Mark all kernel symbols as local
+    - um: Disable CONFIG_GCOV with MODULES
+    - ARM: 9075/1: kernel: Fix interrupted SMC calls
+    - scripts/recordmcount.pl: Fix RISC-V regex for clang
+    - riscv: Workaround mcount name prior to clang-13
+    - scsi: lpfc: Fix illegal memory access on Abort IOCBs
+    - ceph: fix fscache invalidation
+    - scsi: target: tcmu: Return from tcmu_handle_completions() if cmd_id not
+      found
+    - bridge: Fix possible races between assigning rx_handler_data and setting
+      IFF_BRIDGE_PORT bit
+    - drm/amd/display: Fix two cursor duplication when using overlay
+    - gpiolib: acpi: Add quirk to ignore EC wakeups on Dell Venue 10 Pro 5055
+    - ALSA: hda: generic: change the DAC ctl name for LO+SPK or LO+HP
+    - block: reexpand iov_iter after read/write
+    - lib: stackdepot: turn depot_lock spinlock to raw_spinlock
+    - net: stmmac: Do not enable RX FIFO overflow interrupts
+    - ip6_gre: proper dev_{hold|put} in ndo_[un]init methods
+    - sit: proper dev_{hold|put} in ndo_[un]init methods
+    - ip6_tunnel: sit: proper dev_{hold|put} in ndo_[un]init methods
+    - ipv6: remove extra dev_hold() for fallback tunnels
+    - KVM: arm64: Initialize VCPU mdcr_el2 before loading it
+    - tweewide: Fix most Shebang lines
+    - scripts: switch explicitly to Python 3
+    - Linux 5.4.121
+  * Focal update: v5.4.120 upstream stable release (LP: #1930474)
+    - tpm: fix error return code in tpm2_get_cc_attrs_tbl()
+    - tpm, tpm_tis: Extend locality handling to TPM2 in tpm_tis_gen_interrupt()
+    - tpm, tpm_tis: Reserve locality in tpm_tis_resume()
+    - KVM: x86/mmu: Remove the defunct update_pte() paging hook
+    - PM: runtime: Fix unpaired parent child_count for force_resume
+    - fs: dlm: fix debugfs dump
+    - tipc: convert dest node's address to network order
+    - ASoC: Intel: bytcr_rt5640: Enable jack-detect support on Asus T100TAF
+    - net: stmmac: Set FIFO sizes for ipq806x
+    - ASoC: rsnd: core: Check convert rate in rsnd_hw_params
+    - i2c: bail out early when RDWR parameters are wrong
+    - ALSA: hdsp: don't disable if not enabled
+    - ALSA: hdspm: don't disable if not enabled
+    - ALSA: rme9652: don't disable if not enabled
+    - ALSA: bebob: enable to deliver MIDI messages for multiple ports
+    - Bluetooth: Set CONF_NOT_COMPLETE as l2cap_chan default
+    - Bluetooth: initialize skb_queue_head at l2cap_chan_create()
+    - net: bridge: when suppression is enabled exclude RARP packets
+    - Bluetooth: check for zapped sk before connecting
+    - ip6_vti: proper dev_{hold|put} in ndo_[un]init methods
+    - ASoC: Intel: bytcr_rt5640: Add quirk for the Chuwi Hi8 tablet
+    - i2c: Add I2C_AQ_NO_REP_START adapter quirk
+    - mac80211: clear the beacon's CRC after channel switch
+    - pinctrl: samsung: use 'int' for register masks in Exynos
+    - mt76: mt76x0: disable GTK offloading
+    - cuse: prevent clone
+    - ASoC: rsnd: call rsnd_ssi_master_clk_start() from rsnd_ssi_init()
+    - Revert "iommu/amd: Fix performance counter initialization"
+    - iommu/amd: Remove performance counter pre-initialization test
+    - drm/amd/display: Force vsync flip when reconfiguring MPCC
+    - selftests: Set CC to clang in lib.mk if LLVM is set
+    - kconfig: nconf: stop endless search loops
+    - ALSA: hda/hdmi: fix race in handling acomp ELD notification at resume
+    - sctp: Fix out-of-bounds warning in sctp_process_asconf_param()
+    - flow_dissector: Fix out-of-bounds warning in __skb_flow_bpf_to_target()
+    - powerpc/smp: Set numa node before updating mask
+    - ASoC: rt286: Generalize support for ALC3263 codec
+    - ethtool: ioctl: Fix out-of-bounds warning in store_link_ksettings_for_user()
+    - net: sched: tapr: prevent cycle_time == 0 in parse_taprio_schedule
+    - samples/bpf: Fix broken tracex1 due to kprobe argument change
+    - powerpc/pseries: Stop calling printk in rtas_stop_self()
+    - drm/amd/display: fixed divide by zero kernel crash during dsc enablement
+    - wl3501_cs: Fix out-of-bounds warnings in wl3501_send_pkt
+    - wl3501_cs: Fix out-of-bounds warnings in wl3501_mgmt_join
+    - qtnfmac: Fix possible buffer overflow in qtnf_event_handle_external_auth
+    - powerpc/iommu: Annotate nested lock for lockdep
+    - iavf: remove duplicate free resources calls
+    - net: ethernet: mtk_eth_soc: fix RX VLAN offload
+    - bnxt_en: Add PCI IDs for Hyper-V VF devices.
+    - ia64: module: fix symbolizer crash on fdescr
+    - ASoC: rt286: Make RT286_SET_GPIO_* readable and writable
+    - thermal: thermal_of: Fix error return code of
+      thermal_of_populate_bind_params()
+    - f2fs: fix a redundant call to f2fs_balance_fs if an error occurs
+    - PCI: iproc: Fix return value of iproc_msi_irq_domain_alloc()
+    - PCI: Release OF node in pci_scan_device()'s error path
+    - ARM: 9064/1: hw_breakpoint: Do not directly check the event's
+      overflow_handler hook
+    - rpmsg: qcom_glink_native: fix error return code of qcom_glink_rx_data()
+    - NFSv4.2: Always flush out writes in nfs42_proc_fallocate()
+    - NFS: Deal correctly with attribute generation counter overflow
+    - PCI: endpoint: Fix missing destroy_workqueue()
+    - pNFS/flexfiles: fix incorrect size check in decode_nfs_fh()
+    - NFSv4.2 fix handling of sr_eof in SEEK's reply
+    - rtc: fsl-ftm-alarm: add MODULE_TABLE()
+    - ceph: fix inode leak on getattr error in __fh_to_dentry
+    - rtc: ds1307: Fix wday settings for rx8130
+    - net: hns3: fix incorrect configuration for igu_egu_hw_err
+    - net: hns3: initialize the message content in hclge_get_link_mode()
+    - net: hns3: add check for HNS3_NIC_STATE_INITED in
+      hns3_reset_notify_up_enet()
+    - net: hns3: fix for vxlan gpe tx checksum bug
+    - net: hns3: use netif_tx_disable to stop the transmit queue
+    - net: hns3: disable phy loopback setting in hclge_mac_start_phy
+    - sctp: do asoc update earlier in sctp_sf_do_dupcook_a
+    - RISC-V: Fix error code returned by riscv_hartid_to_cpuid()
+    - sunrpc: Fix misplaced barrier in call_decode
+    - ethernet:enic: Fix a use after free bug in enic_hard_start_xmit
+    - sctp: fix a SCTP_MIB_CURRESTAB leak in sctp_sf_do_dupcook_b
+    - netfilter: xt_SECMARK: add new revision to fix structure layout
+    - drm/radeon: Fix off-by-one power_state index heap overwrite
+    - drm/radeon: Avoid power table parsing memory leaks
+    - khugepaged: fix wrong result value for trace_mm_collapse_huge_page_isolate()
+    - mm/hugeltb: handle the error case in hugetlb_fix_reserve_counts()
+    - mm/migrate.c: fix potential indeterminate pte entry in
+      migrate_vma_insert_page()
+    - ksm: fix potential missing rmap_item for stable_node
+    - net: fix nla_strcmp to handle more then one trailing null character
+    - smc: disallow TCP_ULP in smc_setsockopt()
+    - netfilter: nfnetlink_osf: Fix a missing skb_header_pointer() NULL check
+    - can: m_can: m_can_tx_work_queue(): fix tx_skb race condition
+    - sched: Fix out-of-bound access in uclamp
+    - sched/fair: Fix unfairness caused by missing load decay
+    - kernel: kexec_file: fix error return code of kexec_calculate_store_digests()
+    - netfilter: nftables: avoid overflows in nft_hash_buckets()
+    - i40e: Fix use-after-free in i40e_client_subtask()
+    - i40e: fix the restart auto-negotiation after FEC modified
+    - i40e: Fix PHY type identifiers for 2.5G and 5G adapters
+    - ARC: entry: fix off-by-one error in syscall number validation
+    - ARC: mm: PAE: use 40-bit physical page mask
+    - powerpc/64s: Fix crashes when toggling stf barrier
+    - powerpc/64s: Fix crashes when toggling entry flush barrier
+    - hfsplus: prevent corruption in shrinking truncate
+    - squashfs: fix divide error in calculate_skip()
+    - userfaultfd: release page in error path to avoid BUG_ON
+    - mm/hugetlb: fix F_SEAL_FUTURE_WRITE
+    - drm/radeon/dpm: Disable sclk switching on Oland when two 4K 60Hz monitors
+      are connected
+    - drm/i915: Avoid div-by-zero on gen2
+    - iio: proximity: pulsedlight: Fix rumtime PM imbalance on error
+    - usb: fotg210-hcd: Fix an error message
+    - hwmon: (occ) Fix poll rate limiting
+    - ACPI: scan: Fix a memory leak in an error handling path
+    - kyber: fix out of bounds access when preempted
+    - nbd: Fix NULL pointer in flush_workqueue
+    - blk-mq: Swap two calls in blk_mq_exit_queue()
+    - iomap: fix sub-page uptodate handling
+    - usb: dwc3: omap: improve extcon initialization
+    - usb: dwc3: pci: Enable usb2-gadget-lpm-disable for Intel Merrifield
+    - usb: xhci: Increase timeout for HC halt
+    - usb: dwc2: Fix gadget DMA unmap direction
+    - usb: core: hub: fix race condition about TRSMRCY of resume
+    - usb: dwc3: gadget: Return success always for kick transfer in ep queue
+    - xhci: Do not use GFP_KERNEL in (potentially) atomic context
+    - xhci: Add reset resume quirk for AMD xhci controller.
+    - iio: gyro: mpu3050: Fix reported temperature value
+    - iio: tsl2583: Fix division by a zero lux_val
+    - cdc-wdm: untangle a circular dependency between callback and softint
+    - KVM: x86: Cancel pvclock_gtod_work on module removal
+    - mm: fix struct page layout on 32-bit systems
+    - FDDI: defxx: Make MMIO the configuration default except for EISA
+    - MIPS: Reinstate platform `__div64_32' handler
+    - MIPS: Avoid DIVU in `__div64_32' is result would be zero
+    - MIPS: Avoid handcoded DIVU in `__div64_32' altogether
+    - thermal/core/fair share: Lock the thermal zone while looping over instances
+    - f2fs: fix error handling in f2fs_end_enable_verity()
+    - ARM: 9011/1: centralize phys-to-virt conversion of DT/ATAGS address
+    - ARM: 9012/1: move device tree mapping out of linear region
+    - ARM: 9020/1: mm: use correct section size macro to describe the FDT virtual
+      address
+    - ARM: 9027/1: head.S: explicitly map DT even if it lives in the first
+      physical section
+    - usb: typec: tcpm: Fix error while calculating PPS out values
+    - kobject_uevent: remove warning in init_uevent_argv()
+    - netfilter: conntrack: Make global sysctls readonly in non-init netns
+    - clk: exynos7: Mark aclk_fsys1_200 as critical
+    - nvme: do not try to reconfigure APST when the controller is not live
+    - ASoC: rsnd: check all BUSIF status when error
+    - Linux 5.4.120
+  * scsi: storvsc: Parameterize number hardware queues (LP: #1930626)
+    - scsi: storvsc: Parameterize number hardware queues
+
+  [ Ubuntu: 5.4.0-77.86 ]
+
+  * UAF on CAN J1939 j1939_can_recv (LP: #1932209)
+    - SAUCE: can: j1939: delay release of j1939_priv after synchronize_rcu
+  * UAF on CAN BCM bcm_rx_handler (LP: #1931855)
+    - SAUCE: can: bcm: delay release of struct bcm_op after synchronize_rcu
+
+  [ Ubuntu: 5.4.0-76.85 ]
+
+  * focal/linux: 5.4.0-76.85 -proposed tracker (LP: #1932123)
+  * Upstream v5.9 introduced 'module' patches that removed exported symbols
+    (LP: #1932065)
+    - SAUCE: Revert "modules: inherit TAINT_PROPRIETARY_MODULE"
+    - SAUCE: Revert "modules: return licensing information from find_symbol"
+    - SAUCE: Revert "modules: rename the licence field in struct symsearch to
+      license"
+    - SAUCE: Revert "modules: unexport __module_address"
+    - SAUCE: Revert "modules: unexport __module_text_address"
+    - SAUCE: Revert "modules: mark each_symbol_section static"
+    - SAUCE: Revert "modules: mark find_symbol static"
+    - SAUCE: Revert "modules: mark ref_module static"
+
+  [ Ubuntu: 5.4.0-75.84 ]
+
+  * focal/linux: 5.4.0-75.84 -proposed tracker (LP: #1930032)
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+  * CVE-2021-33200
+    - bpf: Wrap aux data inside bpf_sanitize_info container
+    - bpf: Fix mask direction swap upon off reg sign change
+    - bpf: No need to simulate speculative domain for immediates
+  * Realtek USB hubs in Dell WD19SC/DC/TB fail to work after exiting s2idle
+    (LP: #1928242)
+    - USB: Verify the port status when timeout happens during port suspend
+  * CVE-2020-26145
+    - ath10k: drop fragments with multicast DA for SDIO
+    - ath10k: add CCMP PN replay protection for fragmented frames for PCIe
+    - ath10k: drop fragments with multicast DA for PCIe
+  * CVE-2020-26141
+    - ath10k: Fix TKIP Michael MIC verification for PCIe
+  * CVE-2020-24588
+    - mac80211: properly handle A-MSDUs that start with an RFC 1042 header
+    - cfg80211: mitigate A-MSDU aggregation attacks
+    - mac80211: drop A-MSDUs on old ciphers
+    - ath10k: drop MPDU which has discard flag set by firmware for SDIO
+  * CVE-2020-26139
+    - mac80211: do not accept/forward invalid EAPOL frames
+  * CVE-2020-24586 // CVE-2020-24587 // CVE-2020-24587 for such cases.
+    - mac80211: extend protection against mixed key and fragment cache attacks
+  * CVE-2020-24586 // CVE-2020-24587
+    - mac80211: prevent mixed key and fragment cache attacks
+    - mac80211: add fragment cache to sta_info
+    - mac80211: check defrag PN against current frame
+    - mac80211: prevent attacks on TKIP/WEP as well
+  * CVE-2020-26147
+    - mac80211: assure all fragments are encrypted
+  * raid10: Block discard is very slow, causing severe delays for mkfs and
+    fstrim operations (LP: #1896578)
+    - md: add md_submit_discard_bio() for submitting discard bio
+    - md/raid10: extend r10bio devs to raid disks
+    - md/raid10: pull the code that wait for blocked dev into one function
+    - md/raid10: improve raid10 discard request
+    - md/raid10: improve discard request for far layout
+    - dm raid: remove unnecessary discard limits for raid0 and raid10
+  * [SRU] mpt3sas: only one vSES is handy even IOC has multi vSES (LP: #1926517)
+    - scsi: mpt3sas: Only one vSES is present even when IOC has multi vSES
+  * kvm: properly tear down PV features on hibernate (LP: #1920944)
+    - x86/kvm: Fix pr_info() for async PF setup/teardown
+    - x86/kvm: Teardown PV features on boot CPU as well
+    - x86/kvm: Disable kvmclock on all CPUs on shutdown
+    - x86/kvm: Disable all PV features on crash
+    - x86/kvm: Unify kvm_pv_guest_cpu_reboot() with kvm_guest_cpu_offline()
+  * Focal update: v5.4.119 upstream stable release (LP: #1929615)
+    - Bluetooth: verify AMP hci_chan before amp_destroy
+    - hsr: use netdev_err() instead of WARN_ONCE()
+    - bluetooth: eliminate the potential race condition when removing the HCI
+      controller
+    - net/nfc: fix use-after-free llcp_sock_bind/connect
+    - Revert "USB: cdc-acm: fix rounding error in TIOCSSERIAL"
+    - tty: moxa: fix TIOCSSERIAL jiffies conversions
+    - tty: amiserial: fix TIOCSSERIAL permission check
+    - USB: serial: usb_wwan: fix TIOCSSERIAL jiffies conversions
+    - staging: greybus: uart: fix TIOCSSERIAL jiffies conversions
+    - USB: serial: ti_usb_3410_5052: fix TIOCSSERIAL permission check
+    - staging: fwserial: fix TIOCSSERIAL jiffies conversions
+    - tty: moxa: fix TIOCSSERIAL permission check
+    - staging: fwserial: fix TIOCSSERIAL permission check
+    - usb: typec: tcpm: Address incorrect values of tcpm psy for fixed supply
+    - usb: typec: tcpm: Address incorrect values of tcpm psy for pps supply
+    - usb: typec: tcpm: update power supply once partner accepts
+    - usb: xhci-mtk: remove or operator for setting schedule parameters
+    - usb: xhci-mtk: improve bandwidth scheduling with TT
+    - ASoC: samsung: tm2_wm5110: check of of_parse return value
+    - ASoC: Intel: kbl_da7219_max98927: Fix kabylake_ssp_fixup function
+    - MIPS: pci-mt7620: fix PLL lock check
+    - MIPS: pci-rt2880: fix slot 0 configuration
+    - FDDI: defxx: Bail out gracefully with unassigned PCI resource for CSR
+    - PCI: Allow VPD access for QLogic ISP2722
+    - iio:accel:adis16201: Fix wrong axis assignment that prevents loading
+    - misc: lis3lv02d: Fix false-positive WARN on various HP models
+    - misc: vmw_vmci: explicitly initialize vmci_notify_bm_set_msg struct
+    - misc: vmw_vmci: explicitly initialize vmci_datagram payload
+    - md/bitmap: wait for external bitmap writes to complete during tear down
+    - md-cluster: fix use-after-free issue when removing rdev
+    - md: split mddev_find
+    - md: factor out a mddev_find_locked helper from mddev_find
+    - md: md_open returns -EBUSY when entering racing area
+    - md: Fix missing unused status line of /proc/mdstat
+    - ipw2x00: potential buffer overflow in libipw_wx_set_encodeext()
+    - cfg80211: scan: drop entry from hidden_list on overflow
+    - rtw88: Fix array overrun in rtw_get_tx_power_params()
+    - drm/panfrost: Clear MMU irqs before handling the fault
+    - drm/panfrost: Don't try to map pages that are already mapped
+    - drm/radeon: fix copy of uninitialized variable back to userspace
+    - drm/amd/display: Reject non-zero src_y and src_x for video planes
+    - ALSA: hda/realtek: Re-order ALC882 Acer quirk table entries
+    - ALSA: hda/realtek: Re-order ALC882 Sony quirk table entries
+    - ALSA: hda/realtek: Re-order ALC882 Clevo quirk table entries
+    - ALSA: hda/realtek: Re-order ALC269 HP quirk table entries
+    - ALSA: hda/realtek: Re-order ALC269 Acer quirk table entries
+    - ALSA: hda/realtek: Re-order ALC269 Dell quirk table entries
+    - ALSA: hda/realtek: Re-order ALC269 ASUS quirk table entries
+    - ALSA: hda/realtek: Re-order ALC269 Sony quirk table entries
+    - ALSA: hda/realtek: Re-order ALC269 Lenovo quirk table entries
+    - ALSA: hda/realtek: Re-order remaining ALC269 quirk table entries
+    - ALSA: hda/realtek: Re-order ALC662 quirk table entries
+    - ALSA: hda/realtek: Remove redundant entry for ALC861 Haier/Uniwill devices
+    - ALSA: hda/realtek: ALC285 Thinkpad jack pin quirk is unreachable
+    - KVM: s390: split kvm_s390_logical_to_effective
+    - KVM: s390: fix guarded storage control register handling
+    - s390: fix detection of vector enhancements facility 1 vs. vector packed
+      decimal facility
+    - KVM: s390: split kvm_s390_real_to_abs
+    - KVM: nVMX: Truncate bits 63:32 of VMCS field on nested check in !64-bit
+    - KVM: Stop looking for coalesced MMIO zones if the bus is destroyed
+    - Revert "i3c master: fix missing destroy_workqueue() on error in
+      i3c_master_register"
+    - ovl: fix missing revert_creds() on error path
+    - usb: gadget: pch_udc: Revert d3cb25a12138 completely
+    - memory: gpmc: fix out of bounds read and dereference on gpmc_cs[]
+    - ARM: dts: exynos: correct fuel gauge interrupt trigger level on Midas family
+    - ARM: dts: exynos: correct MUIC interrupt trigger level on Midas family
+    - ARM: dts: exynos: correct PMIC interrupt trigger level on Midas family
+    - ARM: dts: exynos: correct PMIC interrupt trigger level on Odroid X/U3 family
+    - ARM: dts: exynos: correct PMIC interrupt trigger level on SMDK5250
+    - ARM: dts: exynos: correct PMIC interrupt trigger level on Snow
+    - serial: stm32: fix incorrect characters on console
+    - serial: stm32: fix tx_empty condition
+    - usb: typec: tcpci: Check ROLE_CONTROL while interpreting CC_STATUS
+    - regmap: set debugfs_name to NULL after it is freed
+    - mtd: rawnand: fsmc: Fix error code in fsmc_nand_probe()
+    - mtd: rawnand: brcmnand: fix OOB R/W with Hamming ECC
+    - mtd: Handle possible -EPROBE_DEFER from parse_mtd_partitions()
+    - mtd: rawnand: qcom: Return actual error code instead of -ENODEV
+    - arm64: dts: qcom: sm8150: fix number of pins in 'gpio-ranges'
+    - spi: stm32: drop devres version of spi_register_master
+    - arm64: dts: renesas: r8a77980: Fix vin4-7 endpoint binding
+    - x86/microcode: Check for offline CPUs before requesting new microcode
+    - usb: gadget: pch_udc: Replace cpu_to_le32() by lower_32_bits()
+    - usb: gadget: pch_udc: Check if driver is present before calling ->setup()
+    - usb: gadget: pch_udc: Check for DMA mapping error
+    - crypto: qat - don't release uninitialized resources
+    - crypto: qat - ADF_STATUS_PF_RUNNING should be set after adf_dev_init
+    - fotg210-udc: Fix DMA on EP0 for length > max packet size
+    - fotg210-udc: Fix EP0 IN requests bigger than two packets
+    - fotg210-udc: Remove a dubious condition leading to fotg210_done
+    - fotg210-udc: Mask GRP2 interrupts we don't handle
+    - fotg210-udc: Don't DMA more than the buffer can take
+    - fotg210-udc: Complete OUT requests on short packets
+    - mtd: require write permissions for locking and badblock ioctls
+    - bus: qcom: Put child node before return
+    - soundwire: bus: Fix device found flag correctly
+    - phy: marvell: ARMADA375_USBCLUSTER_PHY should not default to y,
+      unconditionally
+    - crypto: qat - fix error path in adf_isr_resource_alloc()
+    - usb: gadget: aspeed: fix dma map failure
+    - USB: gadget: udc: fix wrong pointer passed to IS_ERR() and PTR_ERR()
+    - memory: pl353: fix mask of ECC page_size config register
+    - soundwire: stream: fix memory leak in stream config error path
+    - m68k: mvme147,mvme16x: Don't wipe PCC timer config bits
+    - mtd: rawnand: gpmi: Fix a double free in gpmi_nand_init
+    - irqchip/gic-v3: Fix OF_BAD_ADDR error handling
+    - staging: rtl8192u: Fix potential infinite loop
+    - staging: greybus: uart: fix unprivileged TIOCCSERIAL
+    - PM / devfreq: Use more accurate returned new_freq as resume_freq
+    - spi: Fix use-after-free with devm_spi_alloc_*
+    - soc: qcom: mdt_loader: Validate that p_filesz < p_memsz
+    - soc: qcom: mdt_loader: Detect truncated read of segments
+    - ACPI: CPPC: Replace cppc_attr with kobj_attribute
+    - crypto: qat - Fix a double free in adf_create_ring
+    - cpufreq: armada-37xx: Fix setting TBG parent for load levels
+    - clk: mvebu: armada-37xx-periph: remove .set_parent method for CPU PM clock
+    - cpufreq: armada-37xx: Fix the AVS value for load L1
+    - clk: mvebu: armada-37xx-periph: Fix switching CPU freq from 250 Mhz to 1 GHz
+    - clk: mvebu: armada-37xx-periph: Fix workaround for switching from L1 to L0
+    - cpufreq: armada-37xx: Fix driver cleanup when registration failed
+    - cpufreq: armada-37xx: Fix determining base CPU frequency
+    - spi: fsl-lpspi: Fix PM reference leak in lpspi_prepare_xfer_hardware()
+    - usb: gadget: r8a66597: Add missing null check on return from
+      platform_get_resource
+    - USB: cdc-acm: fix unprivileged TIOCCSERIAL
+    - USB: cdc-acm: fix TIOCGSERIAL implementation
+    - tty: fix return value for unsupported ioctls
+    - serial: core: return early on unsupported ioctls
+    - firmware: qcom-scm: Fix QCOM_SCM configuration
+    - node: fix device cleanups in error handling code
+    - usbip: vudc: fix missing unlock on error in usbip_sockfd_store()
+    - platform/x86: pmc_atom: Match all Beckhoff Automation baytrail boards with
+      critclk_systems DMI table
+    - x86/platform/uv: Fix !KEXEC build failure
+    - usb: dwc2: Fix host mode hibernation exit with remote wakeup flow.
+    - usb: dwc2: Fix hibernation between host and device modes.
+    - ttyprintk: Add TTY hangup callback.
+    - xen-blkback: fix compatibility bug with single page rings
+    - soc: aspeed: fix a ternary sign expansion bug
+    - media: vivid: fix assignment of dev->fbuf_out_flags
+    - media: omap4iss: return error code when omap4iss_get() failed
+    - media: aspeed: fix clock handling logic
+    - media: platform: sunxi: sun6i-csi: fix error return code of
+      sun6i_video_start_streaming()
+    - media: m88rs6000t: avoid potential out-of-bounds reads on arrays
+    - drm/amdkfd: fix build error with AMD_IOMMU_V2=m
+    - x86/kprobes: Fix to check non boostable prefixes correctly
+    - pata_arasan_cf: fix IRQ check
+    - pata_ipx4xx_cf: fix IRQ check
+    - sata_mv: add IRQ checks
+    - ata: libahci_platform: fix IRQ check
+    - nvme-tcp: block BH in sk state_change sk callback
+    - nvmet-tcp: fix incorrect locking in state_change sk callback
+    - nvme: retrigger ANA log update if group descriptor isn't found
+    - media: v4l2-ctrls.c: fix race condition in hdl->requests list
+    - vfio/mdev: Do not allow a mdev_type to have a NULL parent pointer
+    - clk: zynqmp: move zynqmp_pll_set_mode out of round_rate callback
+    - clk: qcom: a53-pll: Add missing MODULE_DEVICE_TABLE
+    - clk: uniphier: Fix potential infinite loop
+    - scsi: hisi_sas: Fix IRQ checks
+    - scsi: jazz_esp: Add IRQ check
+    - scsi: sun3x_esp: Add IRQ check
+    - scsi: sni_53c710: Add IRQ check
+    - scsi: ibmvfc: Fix invalid state machine BUG_ON()
+    - mfd: stm32-timers: Avoid clearing auto reload register
+    - nvme-pci: don't simple map sgl when sgls are disabled
+    - HSI: core: fix resource leaks in hsi_add_client_from_dt()
+    - x86/events/amd/iommu: Fix sysfs type mismatch
+    - sched/debug: Fix cgroup_path[] serialization
+    - drivers/block/null_blk/main: Fix a double free in null_init.
+    - HID: plantronics: Workaround for double volume key presses
+    - perf symbols: Fix dso__fprintf_symbols_by_name() to return the number of
+      printed chars
+    - net: lapbether: Prevent racing when checking whether the netif is running
+    - powerpc/fadump: Mark fadump_calculate_reserve_size as __init
+    - powerpc/prom: Mark identical_pvr_fixup as __init
+    - inet: use bigger hash table for IP ID generation
+    - powerpc: Fix HAVE_HARDLOCKUP_DETECTOR_ARCH build configuration
+    - ALSA: core: remove redundant spin_lock pair in snd_card_disconnect
+    - bug: Remove redundant condition check in report_bug
+    - nfc: pn533: prevent potential memory corruption
+    - net: hns3: Limiting the scope of vector_ring_chain variable
+    - mips: bmips: fix syscon-reboot nodes
+    - ALSA: usb-audio: Add error checks for usb_driver_claim_interface() calls
+    - ASoC: simple-card: fix possible uninitialized single_cpu local variable
+    - liquidio: Fix unintented sign extension of a left shift of a u16
+    - powerpc/64s: Fix pte update for kernel memory on radix
+    - powerpc/perf: Fix PMU constraint check for EBB events
+    - powerpc: iommu: fix build when neither PCI or IBMVIO is set
+    - mac80211: bail out if cipher schemes are invalid
+    - mt7601u: fix always true expression
+    - KVM: PPC: Book3S HV P9: Restore host CTRL SPR after guest exit
+    - RDMA/qedr: Fix error return code in qedr_iw_connect()
+    - IB/hfi1: Fix error return code in parse_platform_config()
+    - cxgb4: Fix unintentional sign extension issues
+    - net: thunderx: Fix unintentional sign extension issue
+    - RDMA/srpt: Fix error return code in srpt_cm_req_recv()
+    - i2c: img-scb: fix reference leak when pm_runtime_get_sync fails
+    - i2c: imx-lpi2c: fix reference leak when pm_runtime_get_sync fails
+    - i2c: omap: fix reference leak when pm_runtime_get_sync fails
+    - i2c: sprd: fix reference leak when pm_runtime_get_sync fails
+    - i2c: cadence: add IRQ check
+    - i2c: emev2: add IRQ check
+    - i2c: jz4780: add IRQ check
+    - i2c: sh7760: add IRQ check
+    - powerpc/xive: Fix xmon command "dxi"
+    - ASoC: ak5558: correct reset polarity
+    - drm/i915/gvt: Fix error code in intel_gvt_init_device()
+    - perf beauty: Fix fsconfig generator
+    - MIPS: pci-legacy: stop using of_pci_range_to_resource
+    - powerpc/pseries: extract host bridge from pci_bus prior to bus removal
+    - rtlwifi: 8821ae: upgrade PHY and RF parameters
+    - i2c: sh7760: fix IRQ error path
+    - mwl8k: Fix a double Free in mwl8k_probe_hw
+    - vsock/vmci: log once the failed queue pair allocation
+    - gro: fix napi_gro_frags() Fast GRO breakage due to IP alignment check
+    - RDMA/cxgb4: add missing qpid increment
+    - RDMA/i40iw: Fix error unwinding when i40iw_hmc_sd_one fails
+    - ALSA: usb: midi: don't return -ENOMEM when usb_urb_ep_type_check fails
+    - net: davinci_emac: Fix incorrect masking of tx and rx error channel
+    - net: renesas: ravb: Fix a stuck issue when a lot of frames are received
+    - net: phy: intel-xway: enable integrated led functions
+    - ath9k: Fix error check in ath9k_hw_read_revisions() for PCI devices
+    - ath10k: Fix ath10k_wmi_tlv_op_pull_peer_stats_info() unlock without lock
+    - powerpc/52xx: Fix an invalid ASM expression ('addi' used instead of 'add')
+    - bnxt_en: fix ternary sign extension bug in bnxt_show_temp()
+    - ARM: dts: uniphier: Change phy-mode to RGMII-ID to enable delay pins for
+      RTL8211E
+    - arm64: dts: uniphier: Change phy-mode to RGMII-ID to enable delay pins for
+      RTL8211E
+    - net: geneve: modify IP header check in geneve6_xmit_skb and geneve_xmit_skb
+    - selftests: net: mirror_gre_vlan_bridge_1q: Make an FDB entry static
+    - bnxt_en: Fix RX consumer index logic in the error path.
+    - net:emac/emac-mac: Fix a use after free in emac_mac_tx_buf_send
+    - RDMA/siw: Fix a use after free in siw_alloc_mr
+    - RDMA/bnxt_re: Fix a double free in bnxt_qplib_alloc_res
+    - net: bridge: mcast: fix broken length + header check for MRDv6 Adv.
+    - net:nfc:digital: Fix a double free in digital_tg_recv_dep_req
+    - kfifo: fix ternary sign extension bugs
+    - mm/sparse: add the missing sparse_buffer_fini() in error branch
+    - mm/memory-failure: unnecessary amount of unmapping
+    - net: Only allow init netns to set default tcp cong to a restricted algo
+    - smp: Fix smp_call_function_single_async prototype
+    - Revert "net/sctp: fix race condition in sctp_destroy_sock"
+    - sctp: delay auto_asconf init until binding the first addr
+    - Revert "of/fdt: Make sure no-map does not remove already reserved regions"
+    - Revert "fdt: Properly handle "no-map" field in the memory region"
+    - Linux 5.4.119
+  * seccomp_bpf:syscall_faked from kselftests fail on s390x (LP: #1928522)
+    - selftests/seccomp: s390 shares the syscall and return value register
+  * Can't detect intel wifi 6235 (LP: #1920180)
+    - SAUCE: iwlwifi: add new pci id for 6235
+  * Mark kprobe_args_user.tc in kselftest/ftrace as unsupported (LP: #1929527)
+    - selftests/ftrace: Return unsupported for the unconfigured features
+  * pmtu.sh from net in ubuntu_kernel_selftests failed with no error message
+    (LP: #1887661)
+    - selftests: pmtu.sh: use $ksft_skip for skipped return code
+  * alsa/sof: make sof driver work in the case of without i915 (focal kernel)
+    (LP: #1927672)
+    - SAUCE: ASoC: SOF: Intel: hda: move the probe_bus ahead of creation of mach
+      device
+  * Fix kdump failures (LP: #1927518)
+    - video: hyperv_fb: Add ratelimit on error message
+    - Drivers: hv: vmbus: Increase wait time for VMbus unload
+    - Drivers: hv: vmbus: Initialize unload_event statically
+  * Ubuntu 20.04 - 'Support flow counters offset for bulk counters'
+    (LP: #1922494)
+    - IB/mlx5: Support flow counters offset for bulk counters
+  * Focal update: v5.4.118 upstream stable release (LP: #1928825)
+    - s390/disassembler: increase ebpf disasm buffer size
+    - ACPI: custom_method: fix potential use-after-free issue
+    - ACPI: custom_method: fix a possible memory leak
+    - ftrace: Handle commands when closing set_ftrace_filter file
+    - ARM: 9056/1: decompressor: fix BSS size calculation for LLVM ld.lld
+    - arm64: dts: marvell: armada-37xx: add syscon compatible to NB clk node
+    - arm64: dts: mt8173: fix property typo of 'phys' in dsi node
+    - ecryptfs: fix kernel panic with null dev_name
+    - mtd: spinand: core: add missing MODULE_DEVICE_TABLE()
+    - mtd: rawnand: atmel: Update ecc_stats.corrected counter
+    - erofs: add unsupported inode i_format check
+    - spi: spi-ti-qspi: Free DMA resources
+    - scsi: qla2xxx: Fix crash in qla2xxx_mqueuecommand()
+    - scsi: mpt3sas: Block PCI config access from userspace during reset
+    - mmc: uniphier-sd: Fix an error handling path in uniphier_sd_probe()
+    - mmc: uniphier-sd: Fix a resource leak in the remove function
+    - mmc: sdhci: Check for reset prior to DMA address unmap
+    - mmc: sdhci-pci: Fix initialization of some SD cards for Intel BYT-based
+      controllers
+    - mmc: block: Update ext_csd.cache_ctrl if it was written
+    - mmc: block: Issue a cache flush only when it's enabled
+    - mmc: core: Do a power cycle when the CMD11 fails
+    - mmc: core: Set read only for SD cards with permanent write protect bit
+    - mmc: core: Fix hanging on I/O during system suspend for removable cards
+    - modules: mark ref_module static
+    - modules: mark find_symbol static
+    - modules: mark each_symbol_section static
+    - modules: unexport __module_text_address
+    - modules: unexport __module_address
+    - modules: rename the licence field in struct symsearch to license
+    - modules: return licensing information from find_symbol
+    - modules: inherit TAINT_PROPRIETARY_MODULE
+    - irqchip/gic-v3: Do not enable irqs when handling spurious interrups
+    - cifs: Return correct error code from smb2_get_enc_key
+    - btrfs: fix metadata extent leak after failure to create subvolume
+    - intel_th: pci: Add Rocket Lake CPU support
+    - posix-timers: Preserve return value in clock_adjtime32()
+    - fbdev: zero-fill colormap in fbcmap.c
+    - bus: ti-sysc: Probe for l4_wkup and l4_cfg interconnect devices first
+    - staging: wimax/i2400m: fix byte-order issue
+    - spi: ath79: always call chipselect function
+    - spi: ath79: remove spi-master setup and cleanup assignment
+    - crypto: api - check for ERR pointers in crypto_destroy_tfm()
+    - crypto: qat - fix unmap invalid dma address
+    - usb: gadget: uvc: add bInterval checking for HS mode
+    - usb: webcam: Invalid size of Processing Unit Descriptor
+    - genirq/matrix: Prevent allocation counter corruption
+    - usb: gadget: f_uac2: validate input parameters
+    - usb: gadget: f_uac1: validate input parameters
+    - usb: dwc3: gadget: Ignore EP queue requests during bus reset
+    - usb: xhci: Fix port minor revision
+    - PCI: PM: Do not read power state in pci_enable_device_flags()
+    - x86/build: Propagate $(CLANG_FLAGS) to $(REALMODE_FLAGS)
+    - tee: optee: do not check memref size on return from Secure World
+    - perf/arm_pmu_platform: Fix error handling
+    - usb: xhci-mtk: support quirk to disable usb2 lpm
+    - xhci: check control context is valid before dereferencing it.
+    - xhci: fix potential array out of bounds with several interrupters
+    - spi: dln2: Fix reference leak to master
+    - spi: omap-100k: Fix reference leak to master
+    - spi: qup: fix PM reference leak in spi_qup_remove()
+    - usb: musb: fix PM reference leak in musb_irq_work()
+    - usb: core: hub: Fix PM reference leak in usb_port_resume()
+    - tty: n_gsm: check error while registering tty devices
+    - intel_th: Consistency and off-by-one fix
+    - phy: phy-twl4030-usb: Fix possible use-after-free in twl4030_usb_remove()
+    - crypto: stm32/hash - Fix PM reference leak on stm32-hash.c
+    - crypto: stm32/cryp - Fix PM reference leak on stm32-cryp.c
+    - crypto: omap-aes - Fix PM reference leak on omap-aes.c
+    - platform/x86: intel_pmc_core: Don't use global pmcdev in quirks
+    - btrfs: convert logic BUG_ON()'s in replace_path to ASSERT()'s
+    - drm: Added orientation quirk for OneGX1 Pro
+    - drm/qxl: release shadow on shutdown
+    - drm/amd/display: Check for DSC support instead of ASIC revision
+    - drm/amd/display: Don't optimize bandwidth before disabling planes
+    - scsi: lpfc: Fix incorrect dbde assignment when building target abts wqe
+    - scsi: lpfc: Fix pt2pt connection does not recover after LOGO
+    - scsi: target: pscsi: Fix warning in pscsi_complete_cmd()
+    - media: ite-cir: check for receive overflow
+    - media: drivers: media: pci: sta2x11: fix Kconfig dependency on GPIOLIB
+    - media: imx: capture: Return -EPIPE from __capture_legacy_try_fmt()
+    - power: supply: bq27xxx: fix power_avg for newer ICs
+    - extcon: arizona: Fix some issues when HPDET IRQ fires after the jack has
+      been unplugged
+    - extcon: arizona: Fix various races on driver unbind
+    - media: media/saa7164: fix saa7164_encoder_register() memory leak bugs
+    - media: gspca/sq905.c: fix uninitialized variable
+    - power: supply: Use IRQF_ONESHOT
+    - drm/amdgpu: mask the xgmi number of hops reported from psp to kfd
+    - drm/amdkfd: Fix UBSAN shift-out-of-bounds warning
+    - drm/amdgpu : Fix asic reset regression issue introduce by 8f211fe8ac7c4f
+    - drm/amd/display: Fix UBSAN warning for not a valid value for type '_Bool'
+    - drm/amd/display: fix dml prefetch validation
+    - scsi: qla2xxx: Always check the return value of qla24xx_get_isp_stats()
+    - drm/vkms: fix misuse of WARN_ON
+    - scsi: qla2xxx: Fix use after free in bsg
+    - mmc: sdhci-pci: Add PCI IDs for Intel LKF
+    - ata: ahci: Disable SXS for Hisilicon Kunpeng920
+    - scsi: smartpqi: Correct request leakage during reset operations
+    - scsi: smartpqi: Add new PCI IDs
+    - scsi: scsi_dh_alua: Remove check for ASC 24h in alua_rtpg()
+    - media: em28xx: fix memory leak
+    - media: vivid: update EDID
+    - clk: socfpga: arria10: Fix memory leak of socfpga_clk on error return
+    - power: supply: generic-adc-battery: fix possible use-after-free in
+      gab_remove()
+    - power: supply: s3c_adc_battery: fix possible use-after-free in
+      s3c_adc_bat_remove()
+    - media: tc358743: fix possible use-after-free in tc358743_remove()
+    - media: adv7604: fix possible use-after-free in adv76xx_remove()
+    - media: i2c: adv7511-v4l2: fix possible use-after-free in adv7511_remove()
+    - media: i2c: tda1997: Fix possible use-after-free in tda1997x_remove()
+    - media: i2c: adv7842: fix possible use-after-free in adv7842_remove()
+    - media: platform: sti: Fix runtime PM imbalance in regs_show
+    - media: dvb-usb: fix memory leak in dvb_usb_adapter_init
+    - media: gscpa/stv06xx: fix memory leak
+    - sched/fair: Ignore percpu threads for imbalance pulls
+    - drm/msm/mdp5: Configure PP_SYNC_HEIGHT to double the vtotal
+    - drm/msm/mdp5: Do not multiply vclk line count by 100
+    - drm/amdkfd: Fix cat debugfs hang_hws file causes system crash bug
+    - amdgpu: avoid incorrect %hu format string
+    - drm/amdgpu: fix NULL pointer dereference
+    - scsi: lpfc: Fix crash when a REG_RPI mailbox fails triggering a LOGO
+      response
+    - scsi: lpfc: Fix error handling for mailboxes completed in MBX_POLL mode
+    - scsi: lpfc: Remove unsupported mbox PORT_CAPABILITIES logic
+    - mfd: arizona: Fix rumtime PM imbalance on error
+    - scsi: libfc: Fix a format specifier
+    - s390/archrandom: add parameter check for s390_arch_random_generate
+    - ALSA: emu8000: Fix a use after free in snd_emu8000_create_mixer
+    - ALSA: hda/conexant: Re-order CX5066 quirk table entries
+    - ALSA: sb: Fix two use after free in snd_sb_qsound_build
+    - ALSA: usb-audio: Explicitly set up the clock selector
+    - ALSA: usb-audio: More constifications
+    - ALSA: usb-audio: Add dB range mapping for Sennheiser Communications Headset
+      PC 8
+    - ALSA: hda/realtek: GA503 use same quirks as GA401
+    - ALSA: hda/realtek: fix mic boost on Intel NUC 8
+    - ALSA: hda/realtek: fix static noise on ALC285 Lenovo laptops
+    - ALSA: hda/realtek: Add quirk for Intel Clevo PCx0Dx
+    - btrfs: fix race when picking most recent mod log operation for an old root
+    - arm64/vdso: Discard .note.gnu.property sections in vDSO
+    - Makefile: Move -Wno-unused-but-set-variable out of GCC only block
+    - virtiofs: fix memory leak in virtio_fs_probe()
+    - ubifs: Only check replay with inode type to judge if inode linked
+    - f2fs: fix to avoid out-of-bounds memory access
+    - mlxsw: spectrum_mr: Update egress RIF list before route's action
+    - openvswitch: fix stack OOB read while fragmenting IPv4 packets
+    - ACPI: GTDT: Don't corrupt interrupt mappings on watchdow probe failure
+    - NFS: Don't discard pNFS layout segments that are marked for return
+    - NFSv4: Don't discard segments marked for return in _pnfs_return_layout()
+    - Input: ili210x - add missing negation for touch indication on ili210x
+    - jffs2: Fix kasan slab-out-of-bounds problem
+    - powerpc/eeh: Fix EEH handling for hugepages in ioremap space.
+    - powerpc: fix EDEADLOCK redefinition error in uapi/asm/errno.h
+    - intel_th: pci: Add Alder Lake-M support
+    - tpm: efi: Use local variable for calculating final log size
+    - tpm: vtpm_proxy: Avoid reading host log when using a virtual device
+    - crypto: rng - fix crypto_rng_reset() refcounting when !CRYPTO_STATS
+    - md/raid1: properly indicate failure when ending a failed write request
+    - dm raid: fix inconclusive reshape layout on fast raid4/5/6 table reload
+      sequences
+    - fuse: fix write deadlock
+    - security: commoncap: fix -Wstringop-overread warning
+    - Fix misc new gcc warnings
+    - jffs2: check the validity of dstlen in jffs2_zlib_compress()
+    - Revert 337f13046ff0 ("futex: Allow FUTEX_CLOCK_REALTIME with FUTEX_WAIT op")
+    - x86/cpu: Initialize MSR_TSC_AUX if RDTSCP *or* RDPID is supported
+    - kbuild: update config_data.gz only when the content of .config is changed
+    - ext4: fix check to prevent false positive report of incorrect used inodes
+    - ext4: do not set SB_ACTIVE in ext4_orphan_cleanup()
+    - ext4: fix error code in ext4_commit_super
+    - media: dvbdev: Fix memory leak in dvb_media_device_free()
+    - media: dvb-usb: Fix use-after-free access
+    - media: dvb-usb: Fix memory leak at error in dvb_usb_device_init()
+    - media: staging/intel-ipu3: Fix memory leak in imu_fmt
+    - media: staging/intel-ipu3: Fix set_fmt error handling
+    - media: staging/intel-ipu3: Fix race condition during set_fmt
+    - usb: gadget: dummy_hcd: fix gpf in gadget_setup
+    - usb: gadget: Fix double free of device descriptor pointers
+    - usb: gadget/function/f_fs string table fix for multiple languages
+    - usb: dwc3: gadget: Fix START_TRANSFER link state check
+    - usb: dwc2: Fix session request interrupt handler
+    - tty: fix memory leak in vc_deallocate
+    - rsi: Use resume_noirq for SDIO
+    - tracing: Map all PIDs to command lines
+    - tracing: Restructure trace_clock_global() to never block
+    - dm persistent data: packed struct should have an aligned() attribute too
+    - dm space map common: fix division bug in sm_ll_find_free_block()
+    - dm integrity: fix missing goto in bitmap_flush_interval error handling
+    - dm rq: fix double free of blk_mq_tag_set in dev remove after table load
+      fails
+    - Linux 5.4.118
+  * Focal update: v5.4.117 upstream stable release (LP: #1928823)
+    - mips: Do not include hi and lo in clobber list for R6
+    - ACPI: tables: x86: Reserve memory occupied by ACPI tables
+    - ACPI: x86: Call acpi_boot_table_init() after acpi_table_upgrade()
+    - net: usb: ax88179_178a: initialize local variables before use
+    - igb: Enable RSS for Intel I211 Ethernet Controller
+    - iwlwifi: Fix softirq/hardirq disabling in iwl_pcie_enqueue_hcmd()
+    - bpf: Fix masking negation logic upon negative dst register
+    - bpf: Fix leakage of uninitialized bpf stack under speculation
+    - avoid __memcat_p link failure
+    - iwlwifi: Fix softirq/hardirq disabling in iwl_pcie_gen2_enqueue_hcmd()
+    - perf data: Fix error return code in perf_data__create_dir()
+    - perf ftrace: Fix access to pid in array when setting a pid filter
+    - ALSA: usb-audio: Add MIDI quirk for Vox ToneLab EX
+    - USB: Add reset-resume quirk for WD19's Realtek Hub
+    - platform/x86: thinkpad_acpi: Correct thermal sensor allocation
+    - scsi: ufs: Unlock on a couple error paths
+    - ovl: allow upperdir inside lowerdir
+    - perf/core: Fix unconditional security_locked_down() call
+    - vfio: Depend on MMU
+    - Linux 5.4.117
+  * r8152 tx status -71 (LP: #1922651) // Focal update: v5.4.117 upstream stable
+    release (LP: #1928823)
+    - USB: Add LPM quirk for Lenovo ThinkPad USB-C Dock Gen2 Ethernet
+  * Focal update: v5.4.116 upstream stable release (LP: #1928821)
+    - bpf: Move off_reg into sanitize_ptr_alu
+    - bpf: Ensure off_reg has no mixed signed bounds for all types
+    - bpf: Rework ptr_limit into alu_limit and add common error path
+    - bpf: Improve verifier error messages for users
+    - bpf: Refactor and streamline bounds check into helper
+    - bpf: Move sanitize_val_alu out of op switch
+    - bpf: Tighten speculative pointer arithmetic mask
+    - bpf: Update selftests to reflect new error states
+    - Linux 5.4.116
+  * Focal update: v5.4.115 upstream stable release (LP: #1927997)
+    - gpio: omap: Save and restore sysconfig
+    - pinctrl: lewisburg: Update number of pins in community
+    - arm64: dts: allwinner: Revert SD card CD GPIO for Pine64-LTS
+    - perf/x86/intel/uncore: Remove uncore extra PCI dev HSWEP_PCI_PCU_3
+    - perf/x86/kvm: Fix Broadwell Xeon stepping in isolation_ucodes[]
+    - perf auxtrace: Fix potential NULL pointer dereference
+    - HID: google: add don USB id
+    - HID: alps: fix error return code in alps_input_configured()
+    - HID: wacom: Assign boolean values to a bool variable
+    - ARM: dts: Fix swapped mmc order for omap3
+    - net: geneve: check skb is large enough for IPv4/IPv6 header
+    - s390/entry: save the caller of psw_idle
+    - xen-netback: Check for hotplug-status existence before watching
+    - cavium/liquidio: Fix duplicate argument
+    - csky: change a Kconfig symbol name to fix e1000 build error
+    - ia64: fix discontig.c section mismatches
+    - ia64: tools: remove duplicate definition of ia64_mf() on ia64
+    - x86/crash: Fix crash_setup_memmap_entries() out-of-bounds access
+    - net: hso: fix NULL-deref on disconnect regression
+    - USB: CDC-ACM: fix poison/unpoison imbalance
+    - Linux 5.4.115
+
+  [ Ubuntu: 5.4.0-74.83 ]
+
+  * focal/linux: 5.4.0-74.83 -proposed tracker (LP: #1927619)
+  * Introduce the 465 driver series, fabric-manager, and libnvidia-nscq
+    (LP: #1925522)
+    - debian/dkms-versions -- add NVIDIA 465 and migrate 450 to 460
+  * linux-image-5.0.0-35-generic breaks checkpointing of container
+    (LP: #1857257)
+    - SAUCE: overlayfs: fix incorrect mnt_id of files opened from map_files
+  * Enable CIFS GCM256 (LP: #1921916)
+    - smb3: add defines for new crypto algorithms
+    - smb3.1.1: add new module load parm require_gcm_256
+    - smb3.1.1: add new module load parm enable_gcm_256
+    - smb3.1.1: print warning if server does not support requested encryption type
+    - smb3.1.1: rename nonces used for GCM and CCM encryption
+    - smb3.1.1: set gcm256 when requested
+    - cifs: Adjust key sizes and key generation routines for AES256 encryption
+  * locking/qrwlock: Fix ordering in queued_write_lock_slowpath() (LP: #1926184)
+    - locking/qrwlock: Fix ordering in queued_write_lock_slowpath()
+  * [Ubuntu 21.04] net/mlx5: Fix HW spec violation configuring uplink
+    (LP: #1925452)
+    - net/mlx5: Fix HW spec violation configuring uplink
+  * Focal update: v5.4.114 upstream stable release (LP: #1926493)
+    - Revert "scsi: qla2xxx: Retry PLOGI on FC-NVMe PRLI failure"
+    - Revert "scsi: qla2xxx: Fix stuck login session using prli_pend_timer"
+    - scsi: qla2xxx: Dual FCP-NVMe target port support
+    - scsi: qla2xxx: Fix device connect issues in P2P configuration
+    - scsi: qla2xxx: Retry PLOGI on FC-NVMe PRLI failure
+    - scsi: qla2xxx: Add a shadow variable to hold disc_state history of fcport
+    - scsi: qla2xxx: Fix stuck login session using prli_pend_timer
+    - scsi: qla2xxx: Fix fabric scan hang
+    - net/sctp: fix race condition in sctp_destroy_sock
+    - Input: nspire-keypad - enable interrupts only when opened
+    - gpio: sysfs: Obey valid_mask
+    - dmaengine: dw: Make it dependent to HAS_IOMEM
+    - ARM: dts: Drop duplicate sha2md5_fck to fix clk_disable race
+    - ARM: dts: Fix moving mmc devices with aliases for omap4 & 5
+    - lockdep: Add a missing initialization hint to the "INFO: Trying to register
+      non-static key" message
+    - arc: kernel: Return -EFAULT if copy_to_user() fails
+    - ASoC: max98373: Added 30ms turn on/off time delay
+    - neighbour: Disregard DEAD dst in neigh_update
+    - ARM: keystone: fix integer overflow warning
+    - ARM: omap1: fix building with clang IAS
+    - drm/msm: Fix a5xx/a6xx timestamps
+    - ASoC: fsl_esai: Fix TDM slot setup for I2S mode
+    - scsi: scsi_transport_srp: Don't block target in SRP_PORT_LOST state
+    - net: ieee802154: stop dump llsec keys for monitors
+    - net: ieee802154: forbid monitor for add llsec key
+    - net: ieee802154: forbid monitor for del llsec key
+    - net: ieee802154: stop dump llsec devs for monitors
+    - net: ieee802154: forbid monitor for add llsec dev
+    - net: ieee802154: forbid monitor for del llsec dev
+    - net: ieee802154: stop dump llsec devkeys for monitors
+    - net: ieee802154: forbid monitor for add llsec devkey
+    - net: ieee802154: forbid monitor for del llsec devkey
+    - net: ieee802154: stop dump llsec seclevels for monitors
+    - net: ieee802154: forbid monitor for add llsec seclevel
+    - pcnet32: Use pci_resource_len to validate PCI resource
+    - mac80211: clear sta->fast_rx when STA removed from 4-addr VLAN
+    - virt_wifi: Return micros for BSS TSF values
+    - Input: s6sy761 - fix coordinate read bit shift
+    - Input: i8042 - fix Pegatron C15B ID entry
+    - HID: wacom: set EV_KEY and EV_ABS only for non-HID_GENERIC type of devices
+    - dm verity fec: fix misaligned RS roots IO
+    - readdir: make sure to verify directory entry for legacy interfaces too
+    - arm64: fix inline asm in load_unaligned_zeropad()
+    - arm64: alternatives: Move length validation in alternative_{insn, endif}
+    - vfio/pci: Add missing range check in vfio_pci_mmap
+    - riscv: Fix spelling mistake "SPARSEMEM" to "SPARSMEM"
+    - scsi: libsas: Reset num_scatter if libata marks qc as NODATA
+    - netfilter: conntrack: do not print icmpv6 as unknown via /proc
+    - libnvdimm/region: Fix nvdimm_has_flush() to handle ND_REGION_ASYNC
+    - netfilter: bridge: add pre_exit hooks for ebtable unregistration
+    - netfilter: arp_tables: add pre_exit hook for table unregister
+    - net: macb: fix the restore of cmp registers
+    - netfilter: nft_limit: avoid possible divide error in nft_limit_init
+    - net: davicom: Fix regulator not turned off on failed probe
+    - net: sit: Unregister catch-all devices
+    - net: ip6_tunnel: Unregister catch-all devices
+    - i40e: fix the panic when running bpf in xdpdrv mode
+    - ibmvnic: avoid calling napi_disable() twice
+    - ibmvnic: remove duplicate napi_schedule call in do_reset function
+    - ibmvnic: remove duplicate napi_schedule call in open function
+    - gro: ensure frag0 meets IP header alignment
+    - ARM: footbridge: fix PCI interrupt mapping
+    - arm64: dts: allwinner: Fix SD card CD GPIO for SOPine systems
+    - r8169: remove fiddling with the PCIe max read request size
+    - r8169: simplify setting PCI_EXP_DEVCTL_NOSNOOP_EN
+    - r8169: fix performance regression related to PCIe max read request size
+    - r8169: improve rtl_jumbo_config
+    - r8169: tweak max read request size for newer chips also in jumbo mtu mode
+    - r8169: don't advertise pause in jumbo mode
+    - ARM: 9071/1: uprobes: Don't hook on thumb instructions
+    - net: phy: marvell: fix detection of PHY on Topaz switches
+    - Linux 5.4.114
+  * Focal update: v5.4.113 upstream stable release (LP: #1926490)
+    - interconnect: core: fix error return code of icc_link_destroy()
+    - KVM: arm64: Hide system instruction access to Trace registers
+    - KVM: arm64: Disable guest access to trace filter controls
+    - drm/imx: imx-ldb: fix out of bounds array access warning
+    - gfs2: report "already frozen/thawed" errors
+    - drm/tegra: dc: Don't set PLL clock to 0Hz
+    - block: only update parent bi_status when bio fail
+    - radix tree test suite: Register the main thread with the RCU library
+    - idr test suite: Take RCU read lock in idr_find_test_1
+    - idr test suite: Create anchor before launching throbber
+    - riscv,entry: fix misaligned base for excp_vect_table
+    - block: don't ignore REQ_NOWAIT for direct IO
+    - netfilter: x_tables: fix compat match/target pad out-of-bound write
+    - driver core: Fix locking bug in deferred_probe_timeout_work_func()
+    - perf tools: Use %define api.pure full instead of %pure-parser
+    - perf tools: Use %zd for size_t printf formats on 32-bit
+    - perf map: Tighten snprintf() string precision to pass gcc check on some
+      32-bit arches
+    - xen/events: fix setting irq affinity
+    - Linux 5.4.113
+  * Focal update: v5.4.112 upstream stable release (LP: #1926489)
+    - counter: stm32-timer-cnt: fix ceiling miss-alignment with reload register
+    - ALSA: aloop: Fix initialization of controls
+    - ALSA: hda/realtek: Fix speaker amp setup on Acer Aspire E1
+    - ASoC: intel: atom: Stop advertising non working S24LE support
+    - nfc: fix refcount leak in llcp_sock_bind()
+    - nfc: fix refcount leak in llcp_sock_connect()
+    - nfc: fix memory leak in llcp_sock_connect()
+    - nfc: Avoid endless loops caused by repeated llcp_sock_connect()
+    - xen/evtchn: Change irq_info lock to raw_spinlock_t
+    - net: ipv6: check for validity before dereferencing cfg->fc_nlinfo.nlh
+    - net: dsa: lantiq_gswip: Let GSWIP automatically set the xMII clock
+    - drm/i915: Fix invalid access to ACPI _DSM objects
+    - gcov: re-fix clang-11+ support
+    - ia64: fix user_stack_pointer() for ptrace()
+    - nds32: flush_dcache_page: use page_mapping_file to avoid races with swapoff
+    - ocfs2: fix deadlock between setattr and dio_end_io_write
+    - fs: direct-io: fix missing sdio->boundary
+    - parisc: parisc-agp requires SBA IOMMU driver
+    - parisc: avoid a warning on u8 cast for cmpxchg on u8 pointers
+    - ARM: dts: turris-omnia: configure LED[2]/INTn pin as interrupt pin
+    - batman-adv: initialize "struct batadv_tvlv_tt_vlan_data"->reserved field
+    - ice: Increase control queue timeout
+    - ice: Fix for dereference of NULL pointer
+    - ice: Cleanup fltr list in case of allocation issues
+    - net: hso: fix null-ptr-deref during tty device unregistration
+    - ethernet/netronome/nfp: Fix a use after free in nfp_bpf_ctrl_msg_rx
+    - bpf, sockmap: Fix sk->prot unhash op reset
+    - net: ensure mac header is set in virtio_net_hdr_to_skb()
+    - i40e: Fix sparse warning: missing error code 'err'
+    - i40e: Fix sparse error: 'vsi->netdev' could be null
+    - net: sched: sch_teql: fix null-pointer dereference
+    - mac80211: fix TXQ AC confusion
+    - net: hsr: Reset MAC header for Tx path
+    - net-ipv6: bugfix - raw & sctp - switch to ipv6_can_nonlocal_bind()
+    - net: let skb_orphan_partial wake-up waiters.
+    - usbip: add sysfs_lock to synchronize sysfs code paths
+    - usbip: stub-dev synchronize sysfs code paths
+    - usbip: vudc synchronize sysfs code paths
+    - usbip: synchronize event handler with sysfs code paths
+    - i2c: turn recovery error on init to debug
+    - virtio_net: Add XDP meta data support
+    - net: dsa: lantiq_gswip: Don't use PHY auto polling
+    - net: dsa: lantiq_gswip: Configure all remaining GSWIP_MII_CFG bits
+    - xfrm: interface: fix ipv4 pmtu check to honor ip header df
+    - regulator: bd9571mwv: Fix AVS and DVFS voltage range
+    - net: xfrm: Localize sequence counter per network namespace
+    - esp: delete NETIF_F_SCTP_CRC bit from features for esp offload
+    - ASoC: SOF: Intel: hda: remove unnecessary parentheses
+    - ASoC: SOF: Intel: HDA: fix core status verification
+    - ASoC: wm8960: Fix wrong bclk and lrclk with pll enabled for some chips
+    - xfrm: Fix NULL pointer dereference on policy lookup
+    - i40e: Added Asym_Pause to supported link modes
+    - i40e: Fix kernel oops when i40e driver removes VF's
+    - hostfs: Use kasprintf() instead of fixed buffer formatting
+    - hostfs: fix memory handling in follow_link()
+    - amd-xgbe: Update DMA coherency values
+    - sch_red: fix off-by-one checks in red_check_params()
+    - arm64: dts: imx8mm/q: Fix pad control of SD1_DATA0
+    - can: bcm/raw: fix msg_namelen values depending on CAN_REQUIRED_SIZE
+    - gianfar: Handle error code at MAC address change
+    - cxgb4: avoid collecting SGE_QBASE regs during traffic
+    - net:tipc: Fix a double free in tipc_sk_mcast_rcv
+    - ARM: dts: imx6: pbab01: Set vmmc supply for both SD interfaces
+    - net/ncsi: Avoid channel_monitor hrtimer deadlock
+    - nfp: flower: ignore duplicate merge hints from FW
+    - net: phy: broadcom: Only advertise EEE for supported modes
+    - ASoC: sunxi: sun4i-codec: fill ASoC card owner
+    - net/mlx5e: Fix ethtool indication of connector type
+    - net/mlx5: Don't request more than supported EQs
+    - net/rds: Fix a use after free in rds_message_map_pages
+    - soc/fsl: qbman: fix conflicting alignment attributes
+    - i40e: Fix display statistics for veb_tc
+    - drm/msm: Set drvdata to NULL when msm_drm_init() fails
+    - net: udp: Add support for getsockopt(..., ..., UDP_GRO, ..., ...);
+    - scsi: ufs: Fix irq return code
+    - scsi: ufs: Avoid busy-waiting by eliminating tag conflicts
+    - scsi: ufs: Use blk_{get,put}_request() to allocate and free TMFs
+    - scsi: ufs: core: Fix task management request completion timeout
+    - scsi: ufs: core: Fix wrong Task Tag used in task management request UPIUs
+    - net: macb: restore cmp registers on resume path
+    - clk: fix invalid usage of list cursor in register
+    - clk: fix invalid usage of list cursor in unregister
+    - workqueue: Move the position of debug_work_activate() in __queue_work()
+    - s390/cpcmd: fix inline assembly register clobbering
+    - perf inject: Fix repipe usage
+    - net: openvswitch: conntrack: simplify the return expression of
+      ovs_ct_limit_get_default_limit()
+    - openvswitch: fix send of uninitialized stack memory in ct limit reply
+    - net: hns3: clear VF down state bit before request link status
+    - net/mlx5: Fix placement of log_max_flow_counter
+    - net/mlx5: Fix PBMC register mapping
+    - RDMA/cxgb4: check for ipv6 address properly while destroying listener
+    - RDMA/addr: Be strict with gid size
+    - RAS/CEC: Correct ce_add_elem()'s returned values
+    - clk: socfpga: fix iomem pointer cast on 64-bit
+    - dt-bindings: net: ethernet-controller: fix typo in NVMEM
+    - net: sched: bump refcount for new action in ACT replace mode
+    - cfg80211: remove WARN_ON() in cfg80211_sme_connect
+    - net: tun: set tun->dev->addr_len during TUNSETLINK processing
+    - drivers: net: fix memory leak in atusb_probe
+    - drivers: net: fix memory leak in peak_usb_create_dev
+    - net: mac802154: Fix general protection fault
+    - net: ieee802154: nl-mac: fix check on panid
+    - net: ieee802154: fix nl802154 del llsec key
+    - net: ieee802154: fix nl802154 del llsec dev
+    - net: ieee802154: fix nl802154 add llsec key
+    - net: ieee802154: fix nl802154 del llsec devkey
+    - net: ieee802154: forbid monitor for set llsec params
+    - net: ieee802154: forbid monitor for del llsec seclevel
+    - net: ieee802154: stop dump llsec params for monitors
+    - Linux 5.4.112
+  * crash utility fails on arm64 with  cannot determine VA_BITS_ACTUAL
+    (LP: #1919275)
+    - arm64/crash_core: Export TCR_EL1.T1SZ in vmcoreinfo
+  * Focal update: v5.4.111 upstream stable release (LP: #1923874)
+    - ARM: dts: am33xx: add aliases for mmc interfaces
+    - bus: ti-sysc: Fix warning on unbind if reset is not deasserted
+    - platform/x86: intel-hid: Support Lenovo ThinkPad X1 Tablet Gen 2
+    - bpf, x86: Use kvmalloc_array instead kmalloc_array in bpf_jit_comp
+    - net/mlx5e: Enforce minimum value check for ICOSQ size
+    - net: pxa168_eth: Fix a potential data race in pxa168_eth_remove
+    - mISDN: fix crash in fritzpci
+    - mac80211: choose first enabled channel for monitor
+    - drm/msm/adreno: a5xx_power: Don't apply A540 lm_setup to other GPUs
+    - drm/msm: Ratelimit invalid-fence message
+    - netfilter: conntrack: Fix gre tunneling over ipv6
+    - platform/x86: thinkpad_acpi: Allow the FnLock LED to change state
+    - x86/build: Turn off -fcf-protection for realmode targets
+    - scsi: target: pscsi: Clean up after failure in pscsi_map_sg()
+    - ia64: mca: allocate early mca with GFP_ATOMIC
+    - ia64: fix format strings for err_inject
+    - cifs: revalidate mapping when we open files for SMB1 POSIX
+    - cifs: Silently ignore unknown oplock break handle
+    - nvme-mpath: replace direct_make_request with generic_make_request
+    - init/Kconfig: make COMPILE_TEST depend on !S390
+    - init/Kconfig: make COMPILE_TEST depend on HAS_IOMEM
+    - Linux 5.4.111
+  * Focal update: v5.4.110 upstream stable release (LP: #1923869)
+    - selinux: vsock: Set SID for socket returned by accept()
+    - ipv6: weaken the v4mapped source check
+    - modsign: print module name along with error message
+    - module: merge repetitive strings in module_sig_check()
+    - module: avoid *goto*s in module_sig_check()
+    - module: harden ELF info handling
+    - ext4: shrink race window in ext4_should_retry_alloc()
+    - ext4: fix bh ref count on error paths
+    - fs: nfsd: fix kconfig dependency warning for NFSD_V4
+    - rpc: fix NULL dereference on kmalloc failure
+    - iomap: Fix negative assignment to unsigned sis->pages in
+      iomap_swapfile_activate
+    - ASoC: rt5640: Fix dac- and adc- vol-tlv values being off by a factor of 10
+    - ASoC: rt5651: Fix dac- and adc- vol-tlv values being off by a factor of 10
+    - ASoC: sgtl5000: set DAP_AVC_CTRL register to correct default value on probe
+    - ASoC: es8316: Simplify adc_pga_gain_tlv table
+    - ASoC: cs42l42: Fix Bitclock polarity inversion
+    - ASoC: cs42l42: Fix channel width support
+    - ASoC: cs42l42: Fix mixer volume control
+    - ASoC: cs42l42: Always wait at least 3ms after reset
+    - NFSD: fix error handling in NFSv4.0 callbacks
+    - powerpc: Force inlining of cpu_has_feature() to avoid build failure
+    - vhost: Fix vhost_vq_reset()
+    - scsi: st: Fix a use after free in st_open()
+    - scsi: qla2xxx: Fix broken #endif placement
+    - staging: comedi: cb_pcidas: fix request_irq() warn
+    - staging: comedi: cb_pcidas64: fix request_irq() warn
+    - ASoC: rt5659: Update MCLK rate in set_sysclk()
+    - thermal/core: Add NULL pointer check before using cooling device stats
+    - locking/ww_mutex: Simplify use_ww_ctx & ww_ctx handling
+    - ext4: do not iput inode under running transaction in ext4_rename()
+    - net: mvpp2: fix interrupt mask/unmask skip condition
+    - flow_dissector: fix TTL and TOS dissection on IPv4 fragments
+    - can: dev: move driver related infrastructure into separate subdir
+    - net: introduce CAN specific pointer in the struct net_device
+    - can: tcan4x5x: fix max register value
+    - brcmfmac: clear EAP/association status bits on linkdown events
+    - ath10k: hold RCU lock when calling ieee80211_find_sta_by_ifaddr()
+    - net: ethernet: aquantia: Handle error cleanup of start on open
+    - appletalk: Fix skb allocation size in loopback case
+    - net: wan/lmc: unregister device when no matching device is found
+    - bpf: Remove MTU check in __bpf_skb_max_len
+    - ALSA: usb-audio: Apply sample rate quirk to Logitech Connect
+    - ALSA: hda: Re-add dropped snd_poewr_change_state() calls
+    - ALSA: hda: Add missing sanity checks in PM prepare/complete callbacks
+    - ALSA: hda/realtek: fix a determine_headset_type issue for a Dell AIO
+    - ALSA: hda/realtek: call alc_update_headset_mode() in hp_automute_hook
+    - xtensa: move coprocessor_flush to the .text section
+    - PM: runtime: Fix race getting/putting suppliers at probe
+    - PM: runtime: Fix ordering in pm_runtime_get_suppliers()
+    - tracing: Fix stack trace event size
+    - mm: fix race by making init_zero_pfn() early_initcall
+    - drm/amdgpu: fix offset calculation in amdgpu_vm_bo_clear_mappings()
+    - drm/amdgpu: check alignment on CPU page for bo map
+    - reiserfs: update reiserfs_xattrs_initialized() condition
+    - vfio/nvlink: Add missing SPAPR_TCE_IOMMU depends
+    - pinctrl: rockchip: fix restore error in resume
+    - extcon: Add stubs for extcon_register_notifier_all() functions
+    - extcon: Fix error handling in extcon_dev_register
+    - firewire: nosy: Fix a use-after-free bug in nosy_ioctl()
+    - usbip: vhci_hcd fix shift out-of-bounds in vhci_hub_control()
+    - USB: quirks: ignore remote wake-up on Fibocom L850-GL LTE modem
+    - usb: musb: Fix suspend with devices connected for a64
+    - usb: xhci-mtk: fix broken streams issue on 0.96 xHCI
+    - cdc-acm: fix BREAK rx code path adding necessary calls
+    - USB: cdc-acm: untangle a circular dependency between callback and softint
+    - USB: cdc-acm: downgrade message to debug
+    - USB: cdc-acm: fix double free on probe failure
+    - USB: cdc-acm: fix use-after-free after probe failure
+    - usb: gadget: udc: amd5536udc_pci fix null-ptr-dereference
+    - usb: dwc2: Fix HPRT0.PrtSusp bit setting for HiKey 960 board.
+    - usb: dwc2: Prevent core suspend when port connection flag is 0
+    - staging: rtl8192e: Fix incorrect source in memcpy()
+    - staging: rtl8192e: Change state information from u16 to u8
+    - drivers: video: fbcon: fix NULL dereference in fbcon_cursor()
+    - Linux 5.4.110
+  * Focal update: v5.4.109 upstream stable release (LP: #1923220)
+    - hugetlbfs: hugetlb_fault_mutex_hash() cleanup
+    - net: fec: ptp: avoid register access when ipg clock is disabled
+    - powerpc/4xx: Fix build errors from mfdcr()
+    - atm: eni: dont release is never initialized
+    - atm: lanai: dont run lanai_dev_close if not open
+    - Revert "r8152: adjust the settings about MAC clock speed down for RTL8153"
+    - ALSA: hda: ignore invalid NHLT table
+    - ixgbe: Fix memleak in ixgbe_configure_clsu32
+    - net: tehuti: fix error return code in bdx_probe()
+    - net: intel: iavf: fix error return code of iavf_init_get_resources()
+    - sun/niu: fix wrong RXMAC_BC_FRM_CNT_COUNT count
+    - gianfar: fix jumbo packets+napi+rx overrun crash
+    - cifs: ask for more credit on async read/write code paths
+    - cpufreq: blacklist Arm Vexpress platforms in cpufreq-dt-platdev
+    - gpiolib: acpi: Add missing IRQF_ONESHOT
+    - nfs: fix PNFS_FLEXFILE_LAYOUT Kconfig default
+    - NFS: Correct size calculation for create reply length
+    - net: hisilicon: hns: fix error return code of hns_nic_clear_all_rx_fetch()
+    - net: wan: fix error return code of uhdlc_init()
+    - net: davicom: Use platform_get_irq_optional()
+    - atm: uPD98402: fix incorrect allocation
+    - atm: idt77252: fix null-ptr-dereference
+    - cifs: change noisy error message to FYI
+    - irqchip/ingenic: Add support for the JZ4760
+    - sparc64: Fix opcode filtering in handling of no fault loads
+    - habanalabs: Call put_pid() when releasing control device
+    - u64_stats,lockdep: Fix u64_stats_init() vs lockdep
+    - regulator: qcom-rpmh: Correct the pmic5_hfsmps515 buck
+    - drm/amd/display: Revert dram_clock_change_latency for DCN2.1
+    - drm/amdgpu: fb BO should be ttm_bo_type_device
+    - drm/radeon: fix AGP dependency
+    - nvme: add NVME_REQ_CANCELLED flag in nvme_cancel_request()
+    - nvme-fc: return NVME_SC_HOST_ABORTED_CMD when a command has been aborted
+    - nvme-pci: add the DISABLE_WRITE_ZEROES quirk for a Samsung PM1725a
+    - nfs: we don't support removing system.nfs4_acl
+    - block: Suppress uevent for hidden device when removed
+    - ia64: fix ia64_syscall_get_set_arguments() for break-based syscalls
+    - ia64: fix ptrace(PTRACE_SYSCALL_INFO_EXIT) sign
+    - netsec: restore phy power state after controller reset
+    - platform/x86: intel-vbtn: Stop reporting SW_DOCK events
+    - squashfs: fix inode lookup sanity checks
+    - squashfs: fix xattr id and id lookup sanity checks
+    - kasan: fix per-page tags for non-page_alloc pages
+    - gcov: fix clang-11+ support
+    - ACPI: video: Add missing callback back for Sony VPCEH3U1E
+    - arm64: dts: ls1046a: mark crypto engine dma coherent
+    - arm64: dts: ls1012a: mark crypto engine dma coherent
+    - arm64: dts: ls1043a: mark crypto engine dma coherent
+    - ARM: dts: at91-sama5d27_som1: fix phy address to 7
+    - integrity: double check iint_cache was initialized
+    - dm verity: fix DM_VERITY_OPTS_MAX value
+    - dm ioctl: fix out of bounds array access when no devices
+    - bus: omap_l3_noc: mark l3 irqs as IRQF_NO_THREAD
+    - veth: Store queue_mapping independently of XDP prog presence
+    - libbpf: Fix INSTALL flag order
+    - net/mlx5e: Don't match on Geneve options in case option masks are all zero
+    - ipv6: fix suspecious RCU usage warning
+    - macvlan: macvlan_count_rx() needs to be aware of preemption
+    - net: sched: validate stab values
+    - net: dsa: bcm_sf2: Qualify phydev->dev_flags based on port
+    - igc: Fix Pause Frame Advertising
+    - igc: Fix Supported Pause Frame Link Setting
+    - e1000e: add rtnl_lock() to e1000_reset_task
+    - e1000e: Fix error handling in e1000_set_d0_lplu_state_82571
+    - net/qlcnic: Fix a use after free in qlcnic_83xx_get_minidump_template
+    - ftgmac100: Restart MAC HW once
+    - selftests/bpf: Set gopt opt_class to 0 if get tunnel opt failed
+    - netfilter: ctnetlink: fix dump of the expect mask attribute
+    - tcp: relookup sock for RST+ACK packets handled by obsolete req sock
+    - can: peak_usb: add forgotten supported devices
+    - can: flexcan: flexcan_chip_freeze(): fix chip freeze for missing bitrate
+    - can: kvaser_pciefd: Always disable bus load reporting
+    - can: c_can_pci: c_can_pci_remove(): fix use-after-free
+    - can: c_can: move runtime PM enable/disable to c_can_platform
+    - can: m_can: m_can_do_rx_poll(): fix extraneous msg loss warning
+    - can: m_can: m_can_rx_peripheral(): fix RX being blocked by errors
+    - mac80211: fix rate mask reset
+    - nfp: flower: fix pre_tun mask id allocation
+    - libbpf: Use SOCK_CLOEXEC when opening the netlink socket
+    - octeontx2-af: Fix irq free in rvu teardown
+    - octeontx2-af: fix infinite loop in unmapping NPC counter
+    - net: cdc-phonet: fix data-interface release on probe failure
+    - r8152: limit the RX buffer size of RTL8153A for USB 2.0
+    - net: stmmac: dwmac-sun8i: Provide TX and RX fifo sizes
+    - selftests: forwarding: vxlan_bridge_1d: Fix vxlan ecn decapsulate value
+    - libbpf: Fix BTF dump of pointer-to-array-of-struct
+    - drm/msm: fix shutdown hook in case GPU components failed to bind
+    - arm64: kdump: update ppos when reading elfcorehdr
+    - PM: runtime: Defer suspending suppliers
+    - net/mlx5e: Fix error path for ethtool set-priv-flag
+    - PM: EM: postpone creating the debugfs dir till fs_initcall
+    - RDMA/cxgb4: Fix adapter LE hash errors while destroying ipv6 listening
+      server
+    - bpf: Don't do bpf_cgroup_storage_set() for kuprobe/tp programs
+    - ACPI: scan: Rearrange memory allocation in acpi_device_add()
+    - ACPI: scan: Use unique number for instance_no
+    - perf auxtrace: Fix auxtrace queue conflict
+    - block: recalculate segment count for multi-segment discards correctly
+    - scsi: Revert "qla2xxx: Make sure that aborted commands are freed"
+    - scsi: qedi: Fix error return code of qedi_alloc_global_queues()
+    - scsi: mpt3sas: Fix error return code of mpt3sas_base_attach()
+    - locking/mutex: Fix non debug version of mutex_lock_io_nested()
+    - x86/mem_encrypt: Correct physical address calculation in __set_clr_pte_enc()
+    - can: dev: Move device back to init netns on owning netns delete
+    - net: dsa: b53: VLAN filtering is global to all users
+    - net: qrtr: fix a kernel-infoleak in qrtr_recvmsg()
+    - mac80211: fix double free in ibss_leave
+    - ext4: add reclaim checks to xattr code
+    - can: peak_usb: Revert "can: peak_usb: add forgotten supported devices"
+    - xen-blkback: don't leak persistent grants from xen_blkbk_map()
+    - Linux 5.4.109
+  * Focal update: v5.4.108 upstream stable release (LP: #1923214)
+    - ASoC: ak4458: Add MODULE_DEVICE_TABLE
+    - ASoC: ak5558: Add MODULE_DEVICE_TABLE
+    - ALSA: dice: fix null pointer dereference when node is disconnected
+    - ALSA: hda/realtek: apply pin quirk for XiaomiNotebook Pro
+    - ALSA: hda: generic: Fix the micmute led init state
+    - ALSA: hda/realtek: Apply headset-mic quirks for Xiaomi Redmibook Air
+    - Revert "PM: runtime: Update device status before letting suppliers suspend"
+    - ARM: 9030/1: entry: omit FP emulation for UND exceptions taken in kernel
+      mode
+    - ARM: 9044/1: vfp: use undef hook for VFP support detection
+    - btrfs: fix race when cloning extent buffer during rewind of an old root
+    - btrfs: fix slab cache flags for free space tree bitmap
+    - ASoC: fsl_ssi: Fix TDM slot setup for I2S mode
+    - ASoC: SOF: Intel: unregister DMIC device on probe error
+    - ASoC: SOF: intel: fix wrong poll bits in dsp power down
+    - ASoC: simple-card-utils: Do not handle device clock
+    - afs: Stop listxattr() from listing "afs.*" attributes
+    - nvme: fix Write Zeroes limitations
+    - nvme-tcp: fix possible hang when failing to set io queues
+    - nvme-tcp: fix a NULL deref when receiving a 0-length r2t PDU
+    - nvmet: don't check iosqes,iocqes for discovery controllers
+    - nfsd: Don't keep looking up unhashed files in the nfsd file cache
+    - NFSD: Repair misuse of sv_lock in 5.10.16-rt30.
+    - svcrdma: disable timeouts on rdma backchannel
+    - vfio: IOMMU_API should be selected
+    - sunrpc: fix refcount leak for rpc auth modules
+    - net/qrtr: fix __netdev_alloc_skb call
+    - kbuild: Fix <linux/version.h> for empty SUBLEVEL or PATCHLEVEL again
+    - riscv: Correct SPARSEMEM configuration
+    - scsi: lpfc: Fix some error codes in debugfs
+    - scsi: myrs: Fix a double free in myrs_cleanup()
+    - counter: stm32-timer-cnt: Report count function when SLAVE_MODE_DISABLED
+    - nvme-rdma: fix possible hang when failing to set io queues
+    - usb-storage: Add quirk to defeat Kindle's automatic unload
+    - usbip: Fix incorrect double assignment to udc->ud.tcp_rx
+    - USB: replace hardcode maximum usb string length by definition
+    - usb: gadget: configfs: Fix KASAN use-after-free
+    - usb: typec: tcpm: Invoke power_supply_changed for tcpm-source-psy-
+    - iio:adc:stm32-adc: Add HAS_IOMEM dependency
+    - iio:adc:qcom-spmi-vadc: add default scale to LR_MUX2_BAT_ID channel
+    - iio: adis16400: Fix an error code in adis16400_initial_setup()
+    - iio: gyro: mpu3050: Fix error handling in mpu3050_trigger_handler
+    - iio: adc: ad7949: fix wrong ADC result due to incorrect bit mask
+    - iio: hid-sensor-humidity: Fix alignment issue of timestamp channel
+    - iio: hid-sensor-prox: Fix scale not correct issue
+    - iio: hid-sensor-temperature: Fix issues of timestamp channel
+    - counter: stm32-timer-cnt: fix ceiling write max value
+    - PCI: rpadlpar: Fix potential drc_name corruption in store functions
+    - perf/x86/intel: Fix a crash caused by zero PEBS status
+    - x86/ioapic: Ignore IRQ2 again
+    - kernel, fs: Introduce and use set_restart_fn() and arch_set_restart_data()
+    - x86: Move TS_COMPAT back to asm/thread_info.h
+    - x86: Introduce TS_COMPAT_RESTART to fix get_nr_restart_syscall()
+    - ext4: find old entry again if failed to rename whiteout
+    - ext4: do not try to set xattr into ea_inode if value is empty
+    - ext4: fix potential error in ext4_do_update_inode
+    - efi: use 32-bit alignment for efi_guid_t literals
+    - firmware/efi: Fix a use after bug in efi_mem_reserve_persistent
+    - genirq: Disable interrupts for force threaded handlers
+    - x86/apic/of: Fix CPU devicetree-node lookups
+    - cifs: Fix preauth hash corruption
+    - Linux 5.4.108
+  * Focal update: v5.4.107 upstream stable release (LP: #1923210)
+    - KVM: arm64: nvhe: Save the SPE context early
+    - btrfs: scrub: Don't check free space before marking a block group RO
+    - drm/i915/gvt: Set SNOOP for PAT3 on BXT/APL to workaround GPU BB hang
+    - drm/i915/gvt: Fix mmio handler break on BXT/APL.
+    - drm/i915/gvt: Fix virtual display setup for BXT/APL
+    - drm/i915/gvt: Fix port number for BDW on EDID region setup
+    - drm/i915/gvt: Fix vfio_edid issue for BXT/APL
+    - fuse: fix live lock in fuse_iget()
+    - crypto: x86 - Regularize glue function prototypes
+    - crypto: aesni - Use TEST %reg,%reg instead of CMP $0,%reg
+    - crypto: x86/aes-ni-xts - use direct calls to and 4-way stride
+    - net: dsa: tag_mtk: fix 802.1ad VLAN egress
+    - net: dsa: b53: Support setting learning on port
+    - Linux 5.4.107
+
+  [ Ubuntu: 5.4.0-73.82 ]
+
+  * focal/linux: 5.4.0-73.82 -proposed tracker (LP: #1923781)
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+  * CIFS DFS entries not accessible with 5.4.0-71.74-generic (LP: #1923670)
+    - Revert "cifs: Set CIFS_MOUNT_USE_PREFIX_PATH flag on setting
+      cifs_sb->prepath."
+  * CVE-2021-29650
+    - Revert "netfilter: x_tables: Update remaining dereference to RCU"
+    - Revert "netfilter: x_tables: Switch synchronization to RCU"
+    - netfilter: x_tables: Use correct memory barriers.
+  * LRMv4: switch to signing nvidia modules via the Ubuntu Modules signing key
+    (LP: #1918134)
+    - [Packaging] dkms-build{,--nvidia-N} sync back from LRMv4
+  * 5.4 kernel: when iommu is on crashdump fails (LP: #1922738)
+    - iommu/vt-d: Refactor find_domain() helper
+    - iommu/vt-d: Add attach_deferred() helper
+    - iommu/vt-d: Move deferred device attachment into helper function
+    - iommu/vt-d: Do deferred attachment in iommu_need_mapping()
+    - iommu/vt-d: Remove deferred_attach_domain()
+    - iommu/vt-d: Simplify check in identity_mapping()
+  * Backport mlx5e fix for tunnel offload (LP: #1921769)
+    - net/mlx5e: Check tunnel offload is required before setting SWP
+  * Bcache bypasse writeback on caching device with fragmentation (LP: #1900438)
+    - bcache: consider the fragmentation when update the writeback rate
+  * Fix implicit declaration warnings for kselftests/memfd test on newer
+    releases (LP: #1910323)
+    - selftests/memfd: Fix implicit declaration warnings
+  * net/mlx5e: Add missing capability check for uplink follow (LP: #1921104)
+    - net/mlx5e: Add missing capability check for uplink follow
+  * [UBUNUT 21.04] s390/vtime: fix increased steal time accounting
+    (LP: #1921498)
+    - s390/vtime: fix increased steal time accounting
+  * Mute/Mic-mute LEDs are not work on HP 850/840/440 G8 Laptops (LP: #1920030)
+    - ALSA: hda/realtek: fix mute/micmute LEDs for HP 840 G8
+    - ALSA: hda/realtek: fix mute/micmute LEDs for HP 440 G8
+    - ALSA: hda/realtek: fix mute/micmute LEDs for HP 850 G8
+  * Focal update: v5.4.106 upstream stable release (LP: #1920246)
+    - uapi: nfnetlink_cthelper.h: fix userspace compilation error
+    - powerpc/pseries: Don't enforce MSI affinity with kdump
+    - ath9k: fix transmitting to stations in dynamic SMPS mode
+    - net: Fix gro aggregation for udp encaps with zero csum
+    - net: check if protocol extracted by virtio_net_hdr_set_proto is correct
+    - net: avoid infinite loop in mpls_gso_segment when mpls_hlen == 0
+    - sh_eth: fix TRSCER mask for SH771x
+    - can: skb: can_skb_set_owner(): fix ref counting if socket was closed before
+      setting skb ownership
+    - can: flexcan: assert FRZ bit in flexcan_chip_freeze()
+    - can: flexcan: enable RX FIFO after FRZ/HALT valid
+    - can: flexcan: invoke flexcan_chip_freeze() to enter freeze mode
+    - can: tcan4x5x: tcan4x5x_init(): fix initialization - clear MRAM before
+      entering Normal Mode
+    - tcp: add sanity tests to TCP_QUEUE_SEQ
+    - netfilter: nf_nat: undo erroneous tcp edemux lookup
+    - netfilter: x_tables: gpf inside xt_find_revision()
+    - selftests/bpf: No need to drop the packet when there is no geneve opt
+    - selftests/bpf: Mask bpf_csum_diff() return value to 16 bits in test_verifier
+    - samples, bpf: Add missing munmap in xdpsock
+    - ibmvnic: always store valid MAC address
+    - mt76: dma: do not report truncated frames to mac80211
+    - powerpc/603: Fix protection of user pages mapped with PROT_NONE
+    - mount: fix mounting of detached mounts onto targets that reside on shared
+      mounts
+    - cifs: return proper error code in statfs(2)
+    - Revert "mm, slub: consider rest of partial list if acquire_slab() fails"
+    - net: enetc: don't overwrite the RSS indirection table when initializing
+    - net/mlx4_en: update moderation when config reset
+    - net: stmmac: fix incorrect DMA channel intr enable setting of EQoS v4.10
+    - nexthop: Do not flush blackhole nexthops when loopback goes down
+    - net: sched: avoid duplicates in classes dump
+    - net: usb: qmi_wwan: allow qmimux add/del with master up
+    - netdevsim: init u64 stats for 32bit hardware
+    - cipso,calipso: resolve a number of problems with the DOI refcounts
+    - net: lapbether: Remove netif_start_queue / netif_stop_queue
+    - net: davicom: Fix regulator not turned off on failed probe
+    - net: davicom: Fix regulator not turned off on driver removal
+    - net: qrtr: fix error return code of qrtr_sendmsg()
+    - ixgbe: fail to create xfrm offload of IPsec tunnel mode SA
+    - net: stmmac: stop each tx channel independently
+    - net: stmmac: fix watchdog timeout during suspend/resume stress test
+    - selftests: forwarding: Fix race condition in mirror installation
+    - perf traceevent: Ensure read cmdlines are null terminated.
+    - net: hns3: fix query vlan mask value error for flow director
+    - net: hns3: fix bug when calculating the TCAM table info
+    - s390/cio: return -EFAULT if copy_to_user() fails again
+    - bnxt_en: reliably allocate IRQ table on reset to avoid crash
+    - drm/compat: Clear bounce structures
+    - drm/shmem-helper: Check for purged buffers in fault handler
+    - drm/shmem-helper: Don't remove the offset in vm_area_struct pgoff
+    - drm: meson_drv add shutdown function
+    - s390/cio: return -EFAULT if copy_to_user() fails
+    - s390/crypto: return -EFAULT if copy_to_user() fails
+    - qxl: Fix uninitialised struct field head.surface_id
+    - sh_eth: fix TRSCER mask for R7S9210
+    - media: usbtv: Fix deadlock on suspend
+    - media: v4l: vsp1: Fix uif null pointer access
+    - media: v4l: vsp1: Fix bru null pointer access
+    - media: rc: compile rc-cec.c into rc-core
+    - [Config] update abi for rc-cec
+    - net: hns3: fix error mask definition of flow director
+    - net: enetc: initialize RFS/RSS memories for unused ports too
+    - net: phy: fix save wrong speed and duplex problem if autoneg is on
+    - i2c: rcar: faster irq code to minimize HW race condition
+    - i2c: rcar: optimize cacheline to minimize HW race condition
+    - udf: fix silent AED tagLocation corruption
+    - mmc: mxs-mmc: Fix a resource leak in an error handling path in
+      'mxs_mmc_probe()'
+    - mmc: mediatek: fix race condition between msdc_request_timeout and irq
+    - Platform: OLPC: Fix probe error handling
+    - powerpc/pci: Add ppc_md.discover_phbs()
+    - spi: stm32: make spurious and overrun interrupts visible
+    - powerpc: improve handling of unrecoverable system reset
+    - powerpc/perf: Record counter overflow always if SAMPLE_IP is unset
+    - HID: logitech-dj: add support for the new lightspeed connection iteration
+    - powerpc/64: Fix stack trace not displaying final frame
+    - iommu/amd: Fix performance counter initialization
+    - sparc32: Limit memblock allocation to low memory
+    - sparc64: Use arch_validate_flags() to validate ADI flag
+    - Input: applespi - don't wait for responses to commands indefinitely.
+    - PCI: xgene-msi: Fix race in installing chained irq handler
+    - PCI: mediatek: Add missing of_node_put() to fix reference leak
+    - kbuild: clamp SUBLEVEL to 255
+    - PCI: Fix pci_register_io_range() memory leak
+    - i40e: Fix memory leak in i40e_probe
+    - s390/smp: __smp_rescan_cpus() - move cpumask away from stack
+    - sysctl.c: fix underflow value setting risk in vm_table
+    - scsi: libiscsi: Fix iscsi_prep_scsi_cmd_pdu() error handling
+    - scsi: target: core: Add cmd length set before cmd complete
+    - scsi: target: core: Prevent underflow for service actions
+    - ALSA: usb: Add Plantronics C320-M USB ctrl msg delay quirk
+    - ALSA: hda/hdmi: Cancel pending works before suspend
+    - ALSA: hda/ca0132: Add Sound BlasterX AE-5 Plus support
+    - ALSA: hda: Drop the BATCH workaround for AMD controllers
+    - ALSA: hda: Flush pending unsolicited events before suspend
+    - ALSA: hda: Avoid spurious unsol event handling during S3/S4
+    - ALSA: usb-audio: Fix "cannot get freq eq" errors on Dell AE515 sound bar
+    - ALSA: usb-audio: Apply the control quirk to Plantronics headsets
+    - Revert 95ebabde382c ("capabilities: Don't allow writing ambiguous v3 file
+      capabilities")
+    - arm64: kasan: fix page_alloc tagging with DEBUG_VIRTUAL
+    - s390/dasd: fix hanging DASD driver unbind
+    - s390/dasd: fix hanging IO request during DASD driver unbind
+    - software node: Fix node registration
+    - mmc: core: Fix partition switch time for eMMC
+    - mmc: cqhci: Fix random crash when remove mmc module/card
+    - Goodix Fingerprint device is not a modem
+    - USB: gadget: u_ether: Fix a configfs return code
+    - usb: gadget: f_uac2: always increase endpoint max_packet_size by one audio
+      slot
+    - usb: gadget: f_uac1: stop playback on function disable
+    - usb: dwc3: qcom: Add missing DWC3 OF node refcount decrement
+    - usb: dwc3: qcom: Honor wakeup enabled/disabled state
+    - USB: usblp: fix a hang in poll() if disconnected
+    - usb: renesas_usbhs: Clear PIPECFG for re-enabling pipe with other EPNUM
+    - usb: xhci: do not perform Soft Retry for some xHCI hosts
+    - xhci: Improve detection of device initiated wake signal.
+    - usb: xhci: Fix ASMedia ASM1042A and ASM3242 DMA addressing
+    - xhci: Fix repeated xhci wake after suspend due to uncleared internal wake
+      state
+    - USB: serial: io_edgeport: fix memory leak in edge_startup
+    - USB: serial: ch341: add new Product ID
+    - USB: serial: cp210x: add ID for Acuity Brands nLight Air Adapter
+    - USB: serial: cp210x: add some more GE USB IDs
+    - usbip: fix stub_dev to check for stream socket
+    - usbip: fix vhci_hcd to check for stream socket
+    - usbip: fix vudc to check for stream socket
+    - usbip: fix stub_dev usbip_sockfd_store() races leading to gpf
+    - usbip: fix vhci_hcd attach_store() races leading to gpf
+    - usbip: fix vudc usbip_sockfd_store races leading to gpf
+    - misc/pvpanic: Export module FDT device table
+    - misc: fastrpc: restrict user apps from sending kernel RPC messages
+    - staging: rtl8192u: fix ->ssid overflow in r8192_wx_set_scan()
+    - staging: rtl8188eu: prevent ->ssid overflow in rtw_wx_set_scan()
+    - staging: rtl8712: unterminated string leads to read overflow
+    - staging: rtl8188eu: fix potential memory corruption in
+      rtw_check_beacon_data()
+    - staging: ks7010: prevent buffer overflow in ks_wlan_set_scan()
+    - staging: rtl8712: Fix possible buffer overflow in r8712_sitesurvey_cmd
+    - staging: rtl8192e: Fix possible buffer overflow in _rtl92e_wx_set_scan
+    - staging: comedi: addi_apci_1032: Fix endian problem for COS sample
+    - staging: comedi: addi_apci_1500: Fix endian problem for command sample
+    - staging: comedi: adv_pci1710: Fix endian problem for AI command data
+    - staging: comedi: das6402: Fix endian problem for AI command data
+    - staging: comedi: das800: Fix endian problem for AI command data
+    - staging: comedi: dmm32at: Fix endian problem for AI command data
+    - staging: comedi: me4000: Fix endian problem for AI command data
+    - staging: comedi: pcl711: Fix endian problem for AI command data
+    - staging: comedi: pcl818: Fix endian problem for AI command data
+    - sh_eth: fix TRSCER mask for R7S72100
+    - arm64/mm: Fix pfn_valid() for ZONE_DEVICE based memory
+    - SUNRPC: Set memalloc_nofs_save() for sync tasks
+    - NFS: Don't revalidate the directory permissions on a lookup failure
+    - NFS: Don't gratuitously clear the inode cache when lookup failed
+    - NFSv4.2: fix return value of _nfs4_get_security_label()
+    - block: rsxx: fix error return code of rsxx_pci_probe()
+    - configfs: fix a use-after-free in __configfs_open_file
+    - arm64: mm: use a 48-bit ID map when possible on 52-bit VA builds
+    - hrtimer: Update softirq_expires_next correctly after
+      __hrtimer_get_next_event()
+    - stop_machine: mark helpers __always_inline
+    - include/linux/sched/mm.h: use rcu_dereference in in_vfork()
+    - zram: fix return value on writeback_store
+    - sched/membarrier: fix missing local execution of ipi_sync_rq_state()
+    - powerpc/64s: Fix instruction encoding for lis in ppc_function_entry()
+    - binfmt_misc: fix possible deadlock in bm_register_write
+    - x86/unwind/orc: Disable KASAN checking in the ORC unwinder, part 2
+    - KVM: arm64: Fix exclusive limit for IPA size
+    - nvme: unlink head after removing last namespace
+    - nvme: release namespace head reference on error
+    - KVM: arm64: Ensure I-cache isolation between vcpus of a same VM
+    - KVM: arm64: Reject VM creation when the default IPA size is unsupported
+    - xen/events: reset affinity of 2-level event when tearing it down
+    - xen/events: don't unmask an event channel when an eoi is pending
+    - xen/events: avoid handling the same event on two cpus at the same time
+    - Linux 5.4.106
+  * Focal update: v5.4.105 upstream stable release (LP: #1920244)
+    - net: dsa: add GRO support via gro_cells
+    - dm table: fix iterate_devices based device capability checks
+    - dm table: fix DAX iterate_devices based device capability checks
+    - dm table: fix zoned iterate_devices based device capability checks
+    - ACPICA: Fix race in generic_serial_bus (I2C) and GPIO op_region parameter
+      handling
+    - iommu/amd: Fix sleeping in atomic in increase_address_space()
+    - mwifiex: pcie: skip cancel_work_sync() on reset failure path
+    - platform/x86: acer-wmi: Cleanup ACER_CAP_FOO defines
+    - platform/x86: acer-wmi: Cleanup accelerometer device handling
+    - platform/x86: acer-wmi: Add new force_caps module parameter
+    - platform/x86: acer-wmi: Add ACER_CAP_SET_FUNCTION_MODE capability flag
+    - platform/x86: acer-wmi: Add support for SW_TABLET_MODE on Switch devices
+    - platform/x86: acer-wmi: Add ACER_CAP_KBD_DOCK quirk for the Aspire Switch
+      10E SW3-016
+    - HID: mf: add support for 0079:1846 Mayflash/Dragonrise USB Gamecube Adapter
+    - media: cx23885: add more quirks for reset DMA on some AMD IOMMU
+    - ACPI: video: Add DMI quirk for GIGABYTE GB-BXBT-2807
+    - ASoC: Intel: bytcr_rt5640: Add quirk for ARCHOS Cesium 140
+    - PCI: Add function 1 DMA alias quirk for Marvell 9215 SATA controller
+    - misc: eeprom_93xx46: Add quirk to support Microchip 93LC46B eeprom
+    - drm/msm/a5xx: Remove overwriting A5XX_PC_DBG_ECO_CNTL register
+    - mmc: sdhci-of-dwcmshc: set SDHCI_QUIRK2_PRESET_VALUE_BROKEN
+    - HID: i2c-hid: Add I2C_HID_QUIRK_NO_IRQ_AFTER_RESET for ITE8568 EC on Voyo
+      Winpad A15
+    - nvme-pci: mark Seagate Nytro XM1440 as QUIRK_NO_NS_DESC_LIST.
+    - nvme-pci: add quirks for Lexar 256GB SSD
+    - Linux 5.4.105
+  * Focal update: v5.4.104 upstream stable release (LP: #1920238)
+    - tpm, tpm_tis: Decorate tpm_tis_gen_interrupt() with request_locality()
+    - tpm, tpm_tis: Decorate tpm_get_timeouts() with request_locality()
+    - btrfs: raid56: simplify tracking of Q stripe presence
+    - btrfs: fix raid6 qstripe kmap
+    - btrfs: validate qgroup inherit for SNAP_CREATE_V2 ioctl
+    - btrfs: free correct amount of space in btrfs_delayed_inode_reserve_metadata
+    - btrfs: unlock extents in btrfs_zero_range in case of quota reservation
+      errors
+    - btrfs: fix warning when creating a directory with smack enabled
+    - PM: runtime: Update device status before letting suppliers suspend
+    - dm bufio: subtract the number of initial sectors in dm_bufio_get_device_size
+    - dm verity: fix FEC for RS roots unaligned to block size
+    - drm/amdgpu: fix parameter error of RREG32_PCIE() in amdgpu_regs_pcie
+    - arm64: ptrace: Fix seccomp of traced syscall -1 (NO_SYSCALL)
+    - crypto - shash: reduce minimum alignment of shash_desc structure
+    - usbip: tools: fix build error for multiple definition
+    - ALSA: ctxfi: cthw20k2: fix mask on conf to allow 4 bits
+    - RDMA/rxe: Fix missing kconfig dependency on CRYPTO
+    - IB/mlx5: Add missing error code
+    - ALSA: hda: intel-nhlt: verify config type
+    - ftrace: Have recordmcount use w8 to read relp->r_info in
+      arm64_is_fake_mcount
+    - rsxx: Return -EFAULT if copy_to_user() fails
+    - r8169: fix resuming from suspend on RTL8105e if machine runs on battery
+    - Linux 5.4.104
+  * Focal update: v5.4.103 upstream stable release (LP: #1920235)
+    - net: usb: qmi_wwan: support ZTE P685M modem
+    - nvme-pci: refactor nvme_unmap_data
+    - nvme-pci: fix error unwind in nvme_map_data
+    - arm64 module: set plt* section addresses to 0x0
+    - MIPS: VDSO: Use CLANG_FLAGS instead of filtering out '--target='
+    - JFS: more checks for invalid superblock
+    - udlfb: Fix memory leak in dlfb_usb_probe
+    - media: mceusb: sanity check for prescaler value
+    - erofs: fix shift-out-of-bounds of blkszbits
+    - media: v4l2-ctrls.c: fix shift-out-of-bounds in std_validate
+    - xfs: Fix assert failure in xfs_setattr_size()
+    - net/af_iucv: remove WARN_ONCE on malformed RX packets
+    - smackfs: restrict bytes count in smackfs write functions
+    - net: fix up truesize of cloned skb in skb_prepare_for_shift()
+    - nbd: handle device refs for DESTROY_ON_DISCONNECT properly
+    - mm/hugetlb.c: fix unnecessary address expansion of pmd sharing
+    - net: bridge: use switchdev for port flags set through sysfs too
+    - net: ag71xx: remove unnecessary MTU reservation
+    - net: fix dev_ifsioc_locked() race condition
+    - dt-bindings: ethernet-controller: fix fixed-link specification
+    - dt-bindings: net: btusb: DT fix s/interrupt-name/interrupt-names/
+    - MIPS: Drop 32-bit asm string functions
+    - drm/virtio: use kvmalloc for large allocations
+    - rsi: Fix TX EAPOL packet handling against iwlwifi AP
+    - rsi: Move card interrupt handling to RX thread
+    - staging: fwserial: Fix error handling in fwserial_create
+    - x86/reboot: Add Zotac ZBOX CI327 nano PCI reboot quirk
+    - vt/consolemap: do font sum unsigned
+    - wlcore: Fix command execute failure 19 for wl12xx
+    - Bluetooth: hci_h5: Set HCI_QUIRK_SIMULTANEOUS_DISCOVERY for btrtl
+    - pktgen: fix misuse of BUG_ON() in pktgen_thread_worker()
+    - ath10k: fix wmi mgmt tx queue full due to race condition
+    - x86/build: Treat R_386_PLT32 relocation as R_386_PC32
+    - Bluetooth: Fix null pointer dereference in amp_read_loc_assoc_final_data
+    - staging: most: sound: add sanity check for function argument
+    - staging: bcm2835-audio: Replace unsafe strcpy() with strscpy()
+    - brcmfmac: Add DMI nvram filename quirk for Predia Basic tablet
+    - brcmfmac: Add DMI nvram filename quirk for Voyo winpad A15 tablet
+    - drm/hisilicon: Fix use-after-free
+    - crypto: tcrypt - avoid signed overflow in byte count
+    - drm/amdgpu: Add check to prevent IH overflow
+    - PCI: Add a REBAR size quirk for Sapphire RX 5600 XT Pulse
+    - drm/amd/display: Guard against NULL pointer deref when get_i2c_info fails
+    - media: uvcvideo: Allow entities with no pads
+    - f2fs: handle unallocated section and zone on pinned/atgc
+    - f2fs: fix to set/clear I_LINKABLE under i_lock
+    - nvme-core: add cancel tagset helpers
+    - nvme-rdma: add clean action for failed reconnection
+    - nvme-tcp: add clean action for failed reconnection
+    - ASoC: Intel: Add DMI quirk table to soc_intel_is_byt_cr()
+    - btrfs: fix error handling in commit_fs_roots
+    - perf/x86/kvm: Add Cascade Lake Xeon steppings to isolation_ucodes[]
+    - parisc: Bump 64-bit IRQ stack size to 64 KB
+    - sched/features: Fix hrtick reprogramming
+    - ASoC: Intel: bytcr_rt5640: Add quirk for the Estar Beauty HD MID 7316R
+      tablet
+    - ASoC: Intel: bytcr_rt5640: Add quirk for the Voyo Winpad A15 tablet
+    - ASoC: Intel: bytcr_rt5651: Add quirk for the Jumper EZpad 7 tablet
+    - ASoC: Intel: bytcr_rt5640: Add quirk for the Acer One S1002 tablet
+    - Xen/gnttab: handle p2m update errors on a per-slot basis
+    - xen-netback: respect gnttab_map_refs()'s return value
+    - zsmalloc: account the number of compacted pages correctly
+    - swap: fix swapfile read/write offset
+    - media: v4l: ioctl: Fix memory leak in video_usercopy
+    - ALSA: hda/realtek: Add quirk for Clevo NH55RZQ
+    - ALSA: hda/realtek: Add quirk for Intel NUC 10
+    - ALSA: hda/realtek: Apply dual codec quirks for MSI Godlike X570 board
+    - Linux 5.4.103
+  * Focal update: v5.4.102 upstream stable release (LP: #1918974)
+    - vmlinux.lds.h: add DWARF v5 sections
+    - kvm: x86: replace kvm_spec_ctrl_test_value with runtime test on the host
+    - debugfs: be more robust at handling improper input in debugfs_lookup()
+    - debugfs: do not attempt to create a new file before the filesystem is
+      initalized
+    - kdb: Make memory allocations more robust
+    - PCI: qcom: Use PHY_REFCLK_USE_PAD only for ipq8064
+    - PCI: Decline to resize resources if boot config must be preserved
+    - virt: vbox: Do not use wait_event_interruptible when called from kernel
+      context
+    - bfq: Avoid false bfq queue merging
+    - ALSA: usb-audio: Fix PCM buffer allocation in non-vmalloc mode
+    - MIPS: vmlinux.lds.S: add missing PAGE_ALIGNED_DATA() section
+    - random: fix the RNDRESEEDCRNG ioctl
+    - ath10k: Fix error handling in case of CE pipe init failure
+    - Bluetooth: btqcomsmd: Fix a resource leak in error handling paths in the
+      probe function
+    - Bluetooth: hci_uart: Fix a race for write_work scheduling
+    - Bluetooth: Fix initializing response id after clearing struct
+    - ARM: dts: exynos: correct PMIC interrupt trigger level on Artik 5
+    - ARM: dts: exynos: correct PMIC interrupt trigger level on Monk
+    - ARM: dts: exynos: correct PMIC interrupt trigger level on Rinato
+    - ARM: dts: exynos: correct PMIC interrupt trigger level on Spring
+    - ARM: dts: exynos: correct PMIC interrupt trigger level on Arndale Octa
+    - ARM: dts: exynos: correct PMIC interrupt trigger level on Odroid XU3 family
+    - arm64: dts: exynos: correct PMIC interrupt trigger level on TM2
+    - arm64: dts: exynos: correct PMIC interrupt trigger level on Espresso
+    - memory: mtk-smi: Fix PM usage counter unbalance in mtk_smi ops
+    - bpf: Add bpf_patch_call_args prototype to include/linux/bpf.h
+    - bpf: Avoid warning when re-casting __bpf_call_base into __bpf_call_base_args
+    - arm64: dts: allwinner: A64: properly connect USB PHY to port 0
+    - arm64: dts: allwinner: H6: properly connect USB PHY to port 0
+    - arm64: dts: allwinner: Drop non-removable from SoPine/LTS SD card
+    - arm64: dts: allwinner: H6: Allow up to 150 MHz MMC bus frequency
+    - arm64: dts: allwinner: A64: Limit MMC2 bus frequency to 150 MHz
+    - cpufreq: brcmstb-avs-cpufreq: Free resources in error path
+    - cpufreq: brcmstb-avs-cpufreq: Fix resource leaks in ->remove()
+    - ACPICA: Fix exception code class checks
+    - usb: gadget: u_audio: Free requests only after callback
+    - Bluetooth: drop HCI device reference before return
+    - Bluetooth: Put HCI device if inquiry procedure interrupts
+    - memory: ti-aemif: Drop child node when jumping out loop
+    - ARM: dts: Configure missing thermal interrupt for 4430
+    - usb: dwc2: Do not update data length if it is 0 on inbound transfers
+    - usb: dwc2: Abort transaction after errors with unknown reason
+    - usb: dwc2: Make "trimming xfer length" a debug message
+    - staging: rtl8723bs: wifi_regd.c: Fix incorrect number of regulatory rules
+    - ARM: dts: armada388-helios4: assign pinctrl to LEDs
+    - ARM: dts: armada388-helios4: assign pinctrl to each fan
+    - arm64: dts: armada-3720-turris-mox: rename u-boot mtd partition to
+      a53-firmware
+    - Bluetooth: btusb: Fix memory leak in btusb_mtk_wmt_recv
+    - arm64: dts: msm8916: Fix reserved and rfsa nodes unit address
+    - ARM: s3c: fix fiq for clang IAS
+    - soc: aspeed: snoop: Add clock control logic
+    - bpf_lru_list: Read double-checked variable once without lock
+    - ath9k: fix data bus crash when setting nf_override via debugfs
+    - ibmvnic: Set to CLOSED state even on error
+    - bnxt_en: reverse order of TX disable and carrier off
+    - xen/netback: fix spurious event detection for common event case
+    - mac80211: fix potential overflow when multiplying to u32 integers
+    - bpf: Fix bpf_fib_lookup helper MTU check for SKB ctx
+    - tcp: fix SO_RCVLOWAT related hangs under mem pressure
+    - net: axienet: Handle deferred probe on clock properly
+    - cxgb4/chtls/cxgbit: Keeping the max ofld immediate data size same in cxgb4
+      and ulds
+    - b43: N-PHY: Fix the update of coef for the PHY revision >= 3case
+    - ibmvnic: add memory barrier to protect long term buffer
+    - ibmvnic: skip send_request_unmap for timeout reset
+    - net: amd-xgbe: Reset the PHY rx data path when mailbox command timeout
+    - net: amd-xgbe: Fix NETDEV WATCHDOG transmit queue timeout warning
+    - net: amd-xgbe: Reset link when the link never comes back
+    - net: amd-xgbe: Fix network fluctuations when using 1G BELFUSE SFP
+    - net: mvneta: Remove per-cpu queue mapping for Armada 3700
+    - fbdev: aty: SPARC64 requires FB_ATY_CT
+    - drm/gma500: Fix error return code in psb_driver_load()
+    - gma500: clean up error handling in init
+    - drm/fb-helper: Add missed unlocks in setcmap_legacy()
+    - crypto: sun4i-ss - linearize buffers content must be kept
+    - crypto: sun4i-ss - fix kmap usage
+    - crypto: arm64/aes-ce - really hide slower algos when faster ones are enabled
+    - drm/amdgpu: Fix macro name _AMDGPU_TRACE_H_ in preprocessor if condition
+    - MIPS: c-r4k: Fix section mismatch for loongson2_sc_init
+    - MIPS: lantiq: Explicitly compare LTQ_EBU_PCC_ISTAT against 0
+    - media: i2c: ov5670: Fix PIXEL_RATE minimum value
+    - media: imx: Unregister csc/scaler only if registered
+    - media: imx: Fix csc/scaler unregister
+    - media: camss: missing error code in msm_video_register()
+    - media: vsp1: Fix an error handling path in the probe function
+    - media: em28xx: Fix use-after-free in em28xx_alloc_urbs
+    - media: media/pci: Fix memleak in empress_init
+    - media: tm6000: Fix memleak in tm6000_start_stream
+    - media: aspeed: fix error return code in aspeed_video_setup_video()
+    - ASoC: cs42l56: fix up error handling in probe
+    - evm: Fix memleak in init_desc
+    - crypto: bcm - Rename struct device_private to bcm_device_private
+    - drm/sun4i: tcon: fix inverted DCLK polarity
+    - MIPS: properly stop .eh_frame generation
+    - bsg: free the request before return error code
+    - drm/amd/display: Fix 10/12 bpc setup in DCE output bit depth reduction.
+    - drm/amd/display: Fix HDMI deep color output for DCE 6-11.
+    - media: software_node: Fix refcounts in software_node_get_next_child()
+    - media: lmedm04: Fix misuse of comma
+    - media: qm1d1c0042: fix error return code in qm1d1c0042_init()
+    - media: cx25821: Fix a bug when reallocating some dma memory
+    - media: pxa_camera: declare variable when DEBUG is defined
+    - media: uvcvideo: Accept invalid bFormatIndex and bFrameIndex values
+    - sched/eas: Don't update misfit status if the task is pinned
+    - mtd: parser: imagetag: fix error codes in
+      bcm963xx_parse_imagetag_partitions()
+    - crypto: talitos - Work around SEC6 ERRATA (AES-CTR mode data size error)
+    - drm/nouveau: bail out of nouveau_channel_new if channel init fails
+    - ata: ahci_brcm: Add back regulators management
+    - ASoC: cpcap: fix microphone timeslot mask
+    - mtd: parsers: afs: Fix freeing the part name memory in failure
+    - f2fs: fix to avoid inconsistent quota data
+    - drm/amdgpu: Prevent shift wrapping in amdgpu_read_mask()
+    - f2fs: fix a wrong condition in __submit_bio
+    - Drivers: hv: vmbus: Avoid use-after-free in vmbus_onoffer_rescind()
+    - ASoC: SOF: debug: Fix a potential issue on string buffer termination
+    - btrfs: clarify error returns values in __load_free_space_cache
+    - hwrng: timeriomem - Fix cooldown period calculation
+    - crypto: ecdh_helper - Ensure 'len >= secret.len' in decode_key()
+    - ima: Free IMA measurement buffer on error
+    - ima: Free IMA measurement buffer after kexec syscall
+    - ASoC: simple-card-utils: Fix device module clock
+    - fs/jfs: fix potential integer overflow on shift of a int
+    - jffs2: fix use after free in jffs2_sum_write_data()
+    - ubifs: Fix memleak in ubifs_init_authentication
+    - ubifs: Fix error return code in alloc_wbufs()
+    - capabilities: Don't allow writing ambiguous v3 file capabilities
+    - HSI: Fix PM usage counter unbalance in ssi_hw_init
+    - clk: meson: clk-pll: fix initializing the old rate (fallback) for a PLL
+    - clk: meson: clk-pll: make "ret" a signed integer
+    - clk: meson: clk-pll: propagate the error from meson_clk_pll_set_rate()
+    - quota: Fix memory leak when handling corrupted quota file
+    - i2c: iproc: handle only slave interrupts which are enabled
+    - i2c: iproc: update slave isr mask (ISR_MASK_SLAVE)
+    - i2c: iproc: handle master read request
+    - spi: cadence-quadspi: Abort read if dummy cycles required are too many
+    - clk: sunxi-ng: h6: Fix CEC clock
+    - HID: core: detect and skip invalid inputs to snto32()
+    - RDMA/siw: Fix handling of zero-sized Read and Receive Queues.
+    - dmaengine: fsldma: Fix a resource leak in the remove function
+    - dmaengine: fsldma: Fix a resource leak in an error handling path of the
+      probe function
+    - dmaengine: owl-dma: Fix a resource leak in the remove function
+    - dmaengine: hsu: disable spurious interrupt
+    - mfd: bd9571mwv: Use devm_mfd_add_devices()
+    - fdt: Properly handle "no-map" field in the memory region
+    - of/fdt: Make sure no-map does not remove already reserved regions
+    - power: reset: at91-sama5d2_shdwc: fix wkupdbc mask
+    - rtc: s5m: select REGMAP_I2C
+    - clocksource/drivers/ixp4xx: Select TIMER_OF when needed
+    - clocksource/drivers/mxs_timer: Add missing semicolon when DEBUG is defined
+    - RDMA/mlx5: Use the correct obj_id upon DEVX TIR creation
+    - clk: sunxi-ng: h6: Fix clock divider range on some clocks
+    - regulator: axp20x: Fix reference cout leak
+    - certs: Fix blacklist flag type confusion
+    - regulator: s5m8767: Fix reference count leak
+    - spi: atmel: Put allocated master before return
+    - regulator: s5m8767: Drop regulators OF node reference
+    - regulator: core: Avoid debugfs: Directory ... already present! error
+    - isofs: release buffer head before return
+    - auxdisplay: ht16k33: Fix refresh rate handling
+    - objtool: Fix error handling for STD/CLD warnings
+    - objtool: Fix ".cold" section suffix check for newer versions of GCC
+    - IB/umad: Return EIO in case of when device disassociated
+    - IB/umad: Return EPOLLERR in case of when device disassociated
+    - KVM: PPC: Make the VMX instruction emulation routines static
+    - powerpc/47x: Disable 256k page size
+    - mmc: sdhci-sprd: Fix some resource leaks in the remove function
+    - mmc: usdhi6rol0: Fix a resource leak in the error handling path of the probe
+    - mmc: renesas_sdhi_internal_dmac: Fix DMA buffer alignment from 8 to
+      128-bytes
+    - ARM: 9046/1: decompressor: Do not clear SCTLR.nTLSMD for ARMv7+ cores
+    - i2c: qcom-geni: Store DMA mapping data in geni_i2c_dev struct
+    - amba: Fix resource leak for drivers without .remove
+    - IB/mlx5: Return appropriate error code instead of ENOMEM
+    - IB/cm: Avoid a loop when device has 255 ports
+    - tracepoint: Do not fail unregistering a probe due to memory failure
+    - perf tools: Fix DSO filtering when not finding a map for a sampled address
+    - perf vendor events arm64: Fix Ampere eMag event typo
+    - RDMA/rxe: Fix coding error in rxe_recv.c
+    - RDMA/rxe: Fix coding error in rxe_rcv_mcast_pkt
+    - RDMA/rxe: Correct skb on loopback path
+    - spi: stm32: properly handle 0 byte transfer
+    - mfd: wm831x-auxadc: Prevent use after free in wm831x_auxadc_read_irq()
+    - powerpc/pseries/dlpar: handle ibm, configure-connector delay status
+    - powerpc/8xx: Fix software emulation interrupt
+    - clk: qcom: gcc-msm8998: Fix Alpha PLL type for all GPLLs
+    - RDMA/hns: Fixed wrong judgments in the goto branch
+    - RDMA/siw: Fix calculation of tx_valid_cpus size
+    - RDMA/hns: Fix type of sq_signal_bits
+    - spi: pxa2xx: Fix the controller numbering for Wildcat Point
+    - regulator: qcom-rpmh: fix pm8009 ldo7
+    - clk: aspeed: Fix APLL calculate formula from ast2600-A2
+    - nfsd: register pernet ops last, unregister first
+    - RDMA/hns: Fixes missing error code of CMDQ
+    - Input: sur40 - fix an error code in sur40_probe()
+    - perf intel-pt: Fix missing CYC processing in PSB
+    - perf intel-pt: Fix premature IPC
+    - perf test: Fix unaligned access in sample parsing test
+    - Input: elo - fix an error code in elo_connect()
+    - sparc64: only select COMPAT_BINFMT_ELF if BINFMT_ELF is set
+    - misc: eeprom_93xx46: Fix module alias to enable module autoprobe
+    - phy: rockchip-emmc: emmc_phy_init() always return 0
+    - misc: eeprom_93xx46: Add module alias to avoid breaking support for non
+      device tree users
+    - soundwire: cadence: fix ACK/NAK handling
+    - pwm: rockchip: rockchip_pwm_probe(): Remove superfluous clk_unprepare()
+    - VMCI: Use set_page_dirty_lock() when unregistering guest memory
+    - PCI: Align checking of syscall user config accessors
+    - mei: hbm: call mei_set_devstate() on hbm stop response
+    - drm/msm/dsi: Correct io_start for MSM8994 (20nm PHY)
+    - drm/msm/mdp5: Fix wait-for-commit for cmd panels
+    - vfio/iommu_type1: Fix some sanity checks in detach group
+    - ext4: fix potential htree index checksum corruption
+    - nvmem: core: Fix a resource leak on error in nvmem_add_cells_from_of()
+    - nvmem: core: skip child nodes not matching binding
+    - regmap: sdw: use _no_pm functions in regmap_read/write
+    - i40e: Fix flow for IPv6 next header (extension header)
+    - i40e: Add zero-initialization of AQ command structures
+    - i40e: Fix overwriting flow control settings during driver loading
+    - i40e: Fix addition of RX filters after enabling FW LLDP agent
+    - i40e: Fix VFs not created
+    - i40e: Fix add TC filter for IPv6
+    - vfio/type1: Use follow_pte()
+    - net/mlx4_core: Add missed mlx4_free_cmd_mailbox()
+    - vxlan: move debug check after netdev unregister
+    - ocfs2: fix a use after free on error
+    - mm/memory.c: fix potential pte_unmap_unlock pte error
+    - mm/hugetlb: fix potential double free in hugetlb_register_node() error path
+    - mm/compaction: fix misbehaviors of fast_find_migrateblock()
+    - r8169: fix jumbo packet handling on RTL8168e
+    - arm64: Add missing ISB after invalidating TLB in __primary_switch
+    - i2c: brcmstb: Fix brcmstd_send_i2c_cmd condition
+    - mm/rmap: fix potential pte_unmap on an not mapped pte
+    - scsi: bnx2fc: Fix Kconfig warning & CNIC build errors
+    - blk-settings: align max_sectors on "logical_block_size" boundary
+    - ACPI: property: Fix fwnode string properties matching
+    - ACPI: configfs: add missing check after configfs_register_default_group()
+    - HID: logitech-dj: add support for keyboard events in eQUAD step 4 Gaming
+    - HID: wacom: Ignore attempts to overwrite the touch_max value from HID
+    - Input: raydium_ts_i2c - do not send zero length
+    - Input: xpad - add support for PowerA Enhanced Wired Controller for Xbox
+      Series X|S
+    - Input: joydev - prevent potential read overflow in ioctl
+    - Input: i8042 - add ASUS Zenbook Flip to noselftest list
+    - media: mceusb: Fix potential out-of-bounds shift
+    - USB: serial: option: update interface mapping for ZTE P685M
+    - usb: musb: Fix runtime PM race in musb_queue_resume_work
+    - usb: dwc3: gadget: Fix setting of DEPCFG.bInterval_m1
+    - usb: dwc3: gadget: Fix dep->interval for fullspeed interrupt
+    - USB: serial: ftdi_sio: fix FTX sub-integer prescaler
+    - USB: serial: mos7840: fix error code in mos7840_write()
+    - USB: serial: mos7720: fix error code in mos7720_write()
+    - ALSA: hda: Add another CometLake-H PCI ID
+    - ALSA: hda/realtek: modify EAPD in the ALC886
+    - Revert "bcache: Kill btree_io_wq"
+    - bcache: Give btree_io_wq correct semantics again
+    - bcache: Move journal work to new flush wq
+    - drm/amd/display: Add vupdate_no_lock interrupts for DCN2.1
+    - drm/amdgpu: Set reference clock to 100Mhz on Renoir (v2)
+    - drm/nouveau/kms: handle mDP connectors
+    - drm/sched: Cancel and flush all outstanding jobs before finish.
+    - erofs: initialized fields can only be observed after bit is set
+    - tpm_tis: Fix check_locality for correct locality acquisition
+    - tpm_tis: Clean up locality release
+    - KEYS: trusted: Fix migratable=1 failing
+    - btrfs: abort the transaction if we fail to inc ref in btrfs_copy_root
+    - btrfs: fix reloc root leak with 0 ref reloc roots on recovery
+    - btrfs: splice remaining dirty_bg's onto the transaction dirty bg list
+    - btrfs: fix extent buffer leak on failure to copy root
+    - crypto: arm64/sha - add missing module aliases
+    - crypto: aesni - prevent misaligned buffers on the stack
+    - crypto: sun4i-ss - checking sg length is not sufficient
+    - crypto: sun4i-ss - handle BigEndian for cipher
+    - crypto: sun4i-ss - initialize need_fallback
+    - seccomp: Add missing return in non-void function
+    - misc: rtsx: init of rts522a add OCP power off when no card is present
+    - drivers/misc/vmw_vmci: restrict too big queue size in qp_host_alloc_queue
+    - pstore: Fix typo in compression option name
+    - dts64: mt7622: fix slow sd card access
+    - staging/mt7621-dma: mtk-hsdma.c->hsdma-mt7621.c
+    - staging: gdm724x: Fix DMA from stack
+    - staging: rtl8188eu: Add Edimax EW-7811UN V2 to device table
+    - media: ipu3-cio2: Fix mbus_code processing in cio2_subdev_set_fmt()
+    - x86/virt: Eat faults on VMXOFF in reboot flows
+    - x86/reboot: Force all cpus to exit VMX root if VMX is supported
+    - powerpc/prom: Fix "ibm,arch-vec-5-platform-support" scan
+    - rcu: Pull deferred rcuog wake up to rcu_eqs_enter() callers
+    - rcu/nocb: Perform deferred wake up before last idle's need_resched() check
+    - floppy: reintroduce O_NDELAY fix
+    - arm64: kexec_file: fix memory leakage in create_dtb() when fdt_open_into()
+      fails
+    - arm64: uprobe: Return EOPNOTSUPP for AARCH32 instruction probing
+    - watchdog: qcom: Remove incorrect usage of QCOM_WDT_ENABLE_IRQ
+    - watchdog: mei_wdt: request stop on unregister
+    - mtd: spi-nor: sfdp: Fix last erase region marking
+    - mtd: spi-nor: sfdp: Fix wrong erase type bitmask for overlaid region
+    - mtd: spi-nor: core: Fix erase type discovery for overlaid region
+    - mtd: spi-nor: core: Add erase size check for erase command initialization
+    - mtd: spi-nor: hisi-sfc: Put child node np on error path
+    - fs/affs: release old buffer head on error path
+    - seq_file: document how per-entry resources are managed.
+    - x86: fix seq_file iteration for pat/memtype.c
+    - hugetlb: fix update_and_free_page contig page struct assumption
+    - hugetlb: fix copy_huge_page_from_user contig page struct assumption
+    - arm64: Extend workaround for erratum 1024718 to all versions of Cortex-A55
+    - media: smipcie: fix interrupt handling and IR timeout
+    - module: Ignore _GLOBAL_OFFSET_TABLE_ when warning for undefined symbols
+    - mmc: sdhci-esdhc-imx: fix kernel panic when remove module
+    - powerpc/32s: Add missing call to kuep_lock on syscall entry
+    - spmi: spmi-pmic-arb: Fix hw_irq overflow
+    - gpio: pcf857x: Fix missing first interrupt
+    - printk: fix deadlock when kernel panic
+    - cpufreq: intel_pstate: Get per-CPU max freq via MSR_HWP_CAPABILITIES if
+      available
+    - s390/vtime: fix inline assembly clobber list
+    - virtio/s390: implement virtio-ccw revision 2 correctly
+    - um: mm: check more comprehensively for stub changes
+    - f2fs: fix out-of-repair __setattr_copy()
+    - sparc32: fix a user-triggerable oops in clear_user()
+    - spi: spi-synquacer: fix set_cs handling
+    - gfs2: Don't skip dlm unlock if glock has an lvb
+    - gfs2: Recursive gfs2_quota_hold in gfs2_iomap_end
+    - dm: fix deadlock when swapping to encrypted device
+    - dm writecache: fix writing beyond end of underlying device when shrinking
+    - dm era: Recover committed writeset after crash
+    - dm era: Verify the data block size hasn't changed
+    - dm era: Fix bitset memory leaks
+    - dm era: Use correct value size in equality function of writeset tree
+    - dm era: Reinitialize bitset cache before digesting a new writeset
+    - dm era: only resize metadata in preresume
+    - drm/i915: Reject 446-480MHz HDMI clock on GLK
+    - icmp: introduce helper for nat'd source address in network device context
+    - icmp: allow icmpv6_ndo_send to work with CONFIG_IPV6=n
+    - gtp: use icmp_ndo_send helper
+    - sunvnet: use icmp_ndo_send helper
+    - xfrm: interface: use icmp_ndo_send helper
+    - ipv6: icmp6: avoid indirect call for icmpv6_send()
+    - ipv6: silence compilation warning for non-IPV6 builds
+    - net: icmp: pass zeroed opts from icmp{,v6}_ndo_send before sending
+    - net: sched: fix police ext initialization
+    - dm era: Update in-core bitset after committing the metadata
+    - net: qrtr: Fix memory leak in qrtr_tun_open
+    - ARM: dts: aspeed: Add LCLK to lpc-snoop
+    - Linux 5.4.102
+  * eeh-basic.sh from powerpc in ubuntu_kernel_selftests failed with unexpected
+    operator on F-5.8 (LP: #1909428)
+    - selftests/powerpc: Make the test check in eeh-basic.sh posix compliant
+
+  [ Ubuntu: 5.4.0-72.80 ]
+
+  * overlayfs calls vfs_setxattr without cap_convert_nscap
+    - vfs: move cap_convert_nscap() call into vfs_setxattr()
+  * CVE-2021-3492
+    - SAUCE: shiftfs: free allocated memory in shiftfs_btrfs_ioctl_fd_replace()
+      error paths
+    - SAUCE: shiftfs: handle copy_to_user() return values correctly
+  * CVE-2021-29154
+    - SAUCE: bpf, x86: Validate computation of branch displacements for x86-64
+    - SAUCE: bpf, x86: Validate computation of branch displacements for x86-32
+
+  [ Ubuntu: 5.4.0-71.79 ]
+
+  * focal/linux: 5.4.0-71.79 -proposed tracker (LP: #1921040)
+  * selftests: bpf verifier fails after sanitize_ptr_alu fixes (LP: #1920995)
+    - bpf: Simplify alu_limit masking for pointer arithmetic
+    - bpf: Add sanity check for upper ptr_limit
+    - bpf, selftests: Fix up some test_verifier cases for unprivileged
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+  * Fix missing HDMI/DP audio on NVidia card after S3 (LP: #1918228)
+    - ALSA: hda/hdmi: Reduce hda_jack_tbl lookup at unsol event handling
+    - ALSA: hda/hdmi: Don't use standard hda_jack for generic HDMI jacks
+    - ALSA: hda/hdmi: Move runtime PM resume into hdmi_present_sense_via_verbs()
+    - ALSA: hda/hdmi: Move ELD parse and jack reporting into update_eld()
+  * Focal update: v5.4.101 upstream stable release (LP: #1918170)
+    - HID: make arrays usage and value to be the same
+    - USB: quirks: sort quirk entries
+    - usb: quirks: add quirk to start video capture on ELMO L-12F document camera
+      reliable
+    - ntfs: check for valid standard information attribute
+    - arm64: tegra: Add power-domain for Tegra210 HDA
+    - scripts: use pkg-config to locate libcrypto
+    - scripts: set proper OpenSSL include dir also for sign-file
+    - mm: unexport follow_pte_pmd
+    - mm: simplify follow_pte{,pmd}
+    - KVM: do not assume PTE is writable after follow_pfn
+    - mm: provide a saner PTE walking API for modules
+    - KVM: Use kvm_pfn_t for local PFN variable in hva_to_pfn_remapped()
+    - NET: usb: qmi_wwan: Adding support for Cinterion MV31
+    - cxgb4: Add new T6 PCI device id 0x6092
+    - cifs: Set CIFS_MOUNT_USE_PREFIX_PATH flag on setting cifs_sb->prepath.
+    - scripts/recordmcount.pl: support big endian for ARCH sh
+    - Linux 5.4.101
+  * Focal update: v5.4.100 upstream stable release (LP: #1918168)
+    - KVM: SEV: fix double locking due to incorrect backport
+    - net: qrtr: Fix port ID for control messages
+    - net: bridge: Fix a warning when del bridge sysfs
+    - Xen/x86: don't bail early from clear_foreign_p2m_mapping()
+    - Xen/x86: also check kernel mapping in set_foreign_p2m_mapping()
+    - Xen/gntdev: correct dev_bus_addr handling in gntdev_map_grant_pages()
+    - Xen/gntdev: correct error checking in gntdev_map_grant_pages()
+    - xen/arm: don't ignore return errors from set_phys_to_machine
+    - xen-blkback: don't "handle" error by BUG()
+    - xen-netback: don't "handle" error by BUG()
+    - xen-scsiback: don't "handle" error by BUG()
+    - xen-blkback: fix error handling in xen_blkbk_map()
+    - media: pwc: Use correct device for DMA
+    - btrfs: fix backport of 2175bf57dc952 in 5.4.95
+    - Linux 5.4.100
+  * Focal update: v5.4.99 upstream stable release (LP: #1918167)
+    - gpio: ep93xx: fix BUG_ON port F usage
+    - gpio: ep93xx: Fix single irqchip with multi gpiochips
+    - tracing: Do not count ftrace events in top level enable output
+    - tracing: Check length before giving out the filter buffer
+    - arm/xen: Don't probe xenbus as part of an early initcall
+    - cgroup: fix psi monitor for root cgroup
+    - arm64: dts: rockchip: Fix PCIe DT properties on rk3399
+    - arm64: dts: qcom: sdm845: Reserve LPASS clocks in gcc
+    - ARM: OMAP2+: Fix suspcious RCU usage splats for omap_enter_idle_coupled
+    - platform/x86: hp-wmi: Disable tablet-mode reporting by default
+    - ovl: perform vfs_getxattr() with mounter creds
+    - cap: fix conversions on getxattr
+    - ovl: skip getxattr of security labels
+    - nvme-pci: ignore the subsysem NQN on Phison E16
+    - drm/amd/display: Add more Clock Sources to DCN2.1
+    - drm/amd/display: Fix dc_sink kref count in emulated_link_detect
+    - drm/amd/display: Free atomic state after drm_atomic_commit
+    - drm/amd/display: Decrement refcount of dc_sink before reassignment
+    - riscv: virt_addr_valid must check the address belongs to linear mapping
+    - bfq-iosched: Revert "bfq: Fix computation of shallow depth"
+    - ARM: dts: lpc32xx: Revert set default clock rate of HCLK PLL
+    - ARM: ensure the signal page contains defined contents
+    - ARM: kexec: fix oops after TLB are invalidated
+    - vmlinux.lds.h: Create section for protection against instrumentation
+    - lkdtm: don't move ctors to .rodata
+    - mt76: dma: fix a possible memory leak in mt76_add_fragment()
+    - drm/vc4: hvs: Fix buffer overflow with the dlist handling
+    - bpf: Check for integer overflow when using roundup_pow_of_two()
+    - netfilter: xt_recent: Fix attempt to update deleted entry
+    - netfilter: nftables: fix possible UAF over chains from packet path in netns
+    - netfilter: flowtable: fix tcp and udp header checksum update
+    - xen/netback: avoid race in xenvif_rx_ring_slots_available()
+    - net: enetc: initialize the RFS and RSS memories
+    - selftests: txtimestamp: fix compilation issue
+    - net: stmmac: set TxQ mode back to DCB after disabling CBS
+    - ibmvnic: Clear failover_pending if unable to schedule
+    - netfilter: conntrack: skip identical origin tuple in same zone only
+    - x86/build: Disable CET instrumentation in the kernel for 32-bit too
+    - net: hns3: add a check for queue_id in hclge_reset_vf_queue()
+    - firmware_loader: align .builtin_fw to 8
+    - drm/sun4i: tcon: set sync polarity for tcon1 channel
+    - drm/sun4i: Fix H6 HDMI PHY configuration
+    - drm/sun4i: dw-hdmi: Fix max. frequency for H6
+    - clk: sunxi-ng: mp: fix parent rate change flag check
+    - i2c: stm32f7: fix configuration of the digital filter
+    - h8300: fix PREEMPTION build, TI_PRE_COUNT undefined
+    - usb: dwc3: ulpi: fix checkpatch warning
+    - usb: dwc3: ulpi: Replace CPU-based busyloop with Protocol-based one
+    - rxrpc: Fix clearance of Tx/Rx ring when releasing a call
+    - udp: fix skb_copy_and_csum_datagram with odd segment sizes
+    - net: dsa: call teardown method on probe failure
+    - net: gro: do not keep too many GRO packets in napi->rx_list
+    - net: fix iteration for sctp transport seq_files
+    - net/vmw_vsock: improve locking in vsock_connect_timeout()
+    - net: watchdog: hold device global xmit lock during tx disable
+    - vsock/virtio: update credit only if socket is not closed
+    - vsock: fix locking in vsock_shutdown()
+    - net/rds: restrict iovecs length for RDS_CMSG_RDMA_ARGS
+    - net/qrtr: restrict user-controlled length in qrtr_tun_write_iter()
+    - ovl: expand warning in ovl_d_real()
+    - Linux 5.4.99
+  * Focal update: v5.4.98 upstream stable release (LP: #1918158)
+    - tracing/kprobe: Fix to support kretprobe events on unloaded modules
+    - af_key: relax availability checks for skb size calculation
+    - regulator: core: avoid regulator_resolve_supply() race condition
+    - mac80211: 160MHz with extended NSS BW in CSA
+    - ASoC: Intel: Skylake: Zero snd_ctl_elem_value
+    - chtls: Fix potential resource leak
+    - pNFS/NFSv4: Try to return invalid layout in pnfs_layout_process()
+    - ASoC: ak4458: correct reset polarity
+    - iwlwifi: mvm: skip power command when unbinding vif during CSA
+    - iwlwifi: mvm: take mutex for calling iwl_mvm_get_sync_time()
+    - iwlwifi: pcie: add a NULL check in iwl_pcie_txq_unmap
+    - iwlwifi: pcie: fix context info memory leak
+    - iwlwifi: mvm: invalidate IDs of internal stations at mvm start
+    - iwlwifi: mvm: guard against device removal in reprobe
+    - SUNRPC: Move simple_get_bytes and simple_get_netobj into private header
+    - SUNRPC: Handle 0 length opaque XDR object data properly
+    - i2c: mediatek: Move suspend and resume handling to NOIRQ phase
+    - blk-cgroup: Use cond_resched() when destroy blkgs
+    - regulator: Fix lockdep warning resolving supplies
+    - Fix unsynchronized access to sev members through svm_register_enc_region
+    - squashfs: add more sanity checks in id lookup
+    - squashfs: add more sanity checks in inode lookup
+    - squashfs: add more sanity checks in xattr id lookup
+    - Linux 5.4.98
+  * Enforce CONFIG_DRM_BOCHS=m (LP: #1916290)
+    - [Config] Enforce CONFIG_DRM_BOCHS=m
+  * powerpc/eeh-basic.sh in kselftest make P8 node stopped working
+    (LP: #1916468)
+    - selftests/eeh: Skip ahci adapters
+  * Focal update: v5.4.97 upstream stable release (LP: #1916066)
+    - USB: serial: cp210x: add pid/vid for WSDA-200-USB
+    - USB: serial: cp210x: add new VID/PID for supporting Teraoka AD2000
+    - USB: serial: option: Adding support for Cinterion MV31
+    - arm64: dts: qcom: c630: keep both touchpad devices enabled
+    - arm64: dts: amlogic: meson-g12: Set FL-adj property value
+    - arm64: dts: rockchip: fix vopl iommu irq on px30
+    - bpf, cgroup: Fix optlen WARN_ON_ONCE toctou
+    - bpf, cgroup: Fix problematic bounds check
+    - um: virtio: free vu_dev only with the contained struct device
+    - rxrpc: Fix deadlock around release of dst cached on udp tunnel
+    - arm64: dts: ls1046a: fix dcfg address range
+    - igc: set the default return value to -IGC_ERR_NVM in igc_write_nvm_srwr
+    - igc: check return value of ret_val in igc_config_fc_after_link_up
+    - i40e: Revert "i40e: don't report link up for a VF who hasn't enabled queues"
+    - net/mlx5: Fix leak upon failure of rule creation
+    - net: lapb: Copy the skb before sending a packet
+    - net: mvpp2: TCAM entry enable should be written after SRAM data
+    - r8169: fix WoL on shutdown if CONFIG_DEBUG_SHIRQ is set
+    - ARM: dts: sun7i: a20: bananapro: Fix ethernet phy-mode
+    - nvmet-tcp: fix out-of-bounds access when receiving multiple h2cdata PDUs
+    - memblock: do not start bottom-up allocations with kernel_end
+    - USB: gadget: legacy: fix an error code in eth_bind()
+    - USB: usblp: don't call usb_set_interface if there's a single alt
+    - usb: renesas_usbhs: Clear pipe running flag in usbhs_pkt_pop()
+    - usb: dwc2: Fix endpoint direction check in ep_from_windex
+    - usb: dwc3: fix clock issue during resume in OTG mode
+    - usb: xhci-mtk: fix unreleased bandwidth data
+    - usb: xhci-mtk: skip dropping bandwidth of unchecked endpoints
+    - usb: xhci-mtk: break loop when find the endpoint to drop
+    - usb: host: xhci-plat: add priv quirk for skip PHY initialization
+    - ovl: fix dentry leak in ovl_get_redirect
+    - mac80211: fix station rate table updates on assoc
+    - fgraph: Initialize tracing_graph_pause at task creation
+    - kretprobe: Avoid re-registration of the same kretprobe earlier
+    - libnvdimm/dimm: Avoid race between probe and available_slots_show()
+    - genirq/msi: Activate Multi-MSI early when MSI_FLAG_ACTIVATE_EARLY is set
+    - xhci: fix bounce buffer usage for non-sg list case
+    - cifs: report error instead of invalid when revalidating a dentry fails
+    - smb3: Fix out-of-bounds bug in SMB2_negotiate()
+    - smb3: fix crediting for compounding when only one request in flight
+    - mmc: core: Limit retries when analyse of SDIO tuples fails
+    - drm/amd/display: Revert "Fix EDID parsing after resume from suspend"
+    - nvme-pci: avoid the deepest sleep state on Kingston A2000 SSDs
+    - KVM: SVM: Treat SVM as unsupported when running as an SEV guest
+    - KVM: x86: Update emulator context mode if SYSENTER xfers to 64-bit mode
+    - ARM: footbridge: fix dc21285 PCI configuration accessors
+    - mm: hugetlbfs: fix cannot migrate the fallocated HugeTLB page
+    - mm: hugetlb: fix a race between freeing and dissolving the page
+    - mm: hugetlb: fix a race between isolating and freeing page
+    - mm: hugetlb: remove VM_BUG_ON_PAGE from page_huge_active
+    - mm, compaction: move high_pfn to the for loop scope
+    - mm: thp: fix MADV_REMOVE deadlock on shmem THP
+    - x86/build: Disable CET instrumentation in the kernel
+    - x86/apic: Add extra serialization for non-serializing MSRs
+    - iwlwifi: mvm: don't send RFH_QUEUE_CONFIG_CMD with no queues
+    - Input: xpad - sync supported devices with fork on GitHub
+    - iommu/vt-d: Do not use flush-queue when caching-mode is on
+    - md: Set prev_flush_start and flush_bio in an atomic way
+    - neighbour: Prevent a dead entry from updating gc_list
+    - net: ip_tunnel: fix mtu calculation
+    - net: dsa: mv88e6xxx: override existent unicast portvec in port_fdb_add
+    - net: sched: replaced invalid qdisc tree flush helper in qdisc_replace
+    - usb: host: xhci: mvebu: make USB 3.0 PHY optional for Armada 3720
+    - Linux 5.4.97
+  * Focal update: v5.4.96 upstream stable release (LP: #1916061)
+    - net: dsa: bcm_sf2: put device node before return
+    - net: switchdev: don't set port_obj_info->handled true when -EOPNOTSUPP
+    - ibmvnic: Ensure that CRQ entry read are correctly ordered
+    - Revert "Revert "block: end bio with BLK_STS_AGAIN in case of non-mq devs and
+      REQ_NOWAIT""
+    - ACPI: thermal: Do not call acpi_thermal_check() directly
+    - arm64: Fix kernel address detection of __is_lm_address()
+    - arm64: Do not pass tagged addresses to __is_lm_address()
+    - tcp: make TCP_USER_TIMEOUT accurate for zero window probes
+    - btrfs: backref, only collect file extent items matching backref offset
+    - btrfs: backref, don't add refs from shared block when resolving normal
+      backref
+    - btrfs: backref, only search backref entries from leaves of the same root
+    - btrfs: backref, use correct count to resolve normal data refs
+    - net_sched: gen_estimator: support large ewma log
+    - phy: cpcap-usb: Fix warning for missing regulator_disable
+    - platform/x86: touchscreen_dmi: Add swap-x-y quirk for Goodix touchscreen on
+      Estar Beauty HD tablet
+    - platform/x86: intel-vbtn: Support for tablet mode on Dell Inspiron 7352
+    - x86: __always_inline __{rd,wr}msr()
+    - scsi: scsi_transport_srp: Don't block target in failfast state
+    - scsi: libfc: Avoid invoking response handler twice if ep is already
+      completed
+    - scsi: fnic: Fix memleak in vnic_dev_init_devcmd2
+    - ASoC: SOF: Intel: hda: Resume codec to do jack detection
+    - mac80211: fix fast-rx encryption check
+    - scsi: ibmvfc: Set default timeout to avoid crash during migration
+    - udf: fix the problem that the disc content is not displayed
+    - nvme: check the PRINFO bit before deciding the host buffer length
+    - selftests/powerpc: Only test lwm/stmw on big endian
+    - drm/amd/display: Update dram_clock_change_latency for DCN2.1
+    - drm/amd/display: Change function decide_dp_link_settings to avoid infinite
+      looping
+    - objtool: Don't fail on missing symbol table
+    - kthread: Extract KTHREAD_IS_PER_CPU
+    - workqueue: Restrict affinity change to rescuer
+    - Linux 5.4.96
+  * Focal update: v5.4.95 upstream stable release (LP: #1916056)
+    - ICMPv6: Add ICMPv6 Parameter Problem, code 3 definition
+    - IPv6: reply ICMP error if the first fragment don't include all headers
+    - nbd: freeze the queue while we're adding connections
+    - ACPI: sysfs: Prefer "compatible" modalias
+    - kernel: kexec: remove the lock operation of system_transition_mutex
+    - ALSA: hda/realtek: Enable headset of ASUS B1400CEPE with ALC256
+    - ALSA: hda/via: Apply the workaround generically for Clevo machines
+    - media: rc: ensure that uevent can be read directly after rc device register
+    - ARM: dts: imx6qdl-gw52xx: fix duplicate regulator naming
+    - wext: fix NULL-ptr-dereference with cfg80211's lack of commit()
+    - net: usb: qmi_wwan: added support for Thales Cinterion PLSx3 modem family
+    - s390/vfio-ap: No need to disable IRQ after queue reset
+    - PM: hibernate: flush swap writer after marking
+    - drivers: soc: atmel: Avoid calling at91_soc_init on non AT91 SoCs
+    - drivers: soc: atmel: add null entry at the end of at91_soc_allowed_list[]
+    - btrfs: fix possible free space tree corruption with online conversion
+    - KVM: x86/pmu: Fix HW_REF_CPU_CYCLES event pseudo-encoding in
+      intel_arch_events[]
+    - KVM: x86/pmu: Fix UBSAN shift-out-of-bounds warning in intel_pmu_refresh()
+    - KVM: nVMX: Sync unsync'd vmcs02 state to vmcs12 on migration
+    - KVM: x86: get smi pending status correctly
+    - KVM: Forbid the use of tagged userspace addresses for memslots
+    - xen: Fix XenStore initialisation for XS_LOCAL
+    - leds: trigger: fix potential deadlock with libata
+    - arm64: dts: broadcom: Fix USB DMA address translation for Stingray
+    - mt7601u: fix kernel crash unplugging the device
+    - mt7601u: fix rx buffer refcounting
+    - drm/nouveau/svm: fail NOUVEAU_SVM_INIT ioctl on unsupported devices
+    - drm/i915: Check for all subplatform bits
+    - tee: optee: replace might_sleep with cond_resched
+    - xen-blkfront: allow discard-* nodes to be optional
+    - ARM: imx: build suspend-imx6.S with arm instruction set
+    - netfilter: nft_dynset: add timeout extension to template
+    - xfrm: Fix oops in xfrm_replay_advance_bmp
+    - xfrm: fix disable_xfrm sysctl when used on xfrm interfaces
+    - selftests: xfrm: fix test return value override issue in xfrm_policy.sh
+    - xfrm: Fix wraparound in xfrm_policy_addr_delta()
+    - arm64: dts: ls1028a: fix the offset of the reset register
+    - ARM: dts: imx6qdl-kontron-samx6i: fix i2c_lcd/cam default status
+    - firmware: imx: select SOC_BUS to fix firmware build
+    - RDMA/cxgb4: Fix the reported max_recv_sge value
+    - ASoC: Intel: Skylake: skl-topology: Fix OOPs ib skl_tplg_complete
+    - pNFS/NFSv4: Fix a layout segment leak in pnfs_layout_process()
+    - iwlwifi: pcie: use jiffies for memory read spin time limit
+    - iwlwifi: pcie: reschedule in long-running memory reads
+    - mac80211: pause TX while changing interface type
+    - i40e: acquire VSI pointer only after VF is initialized
+    - igc: fix link speed advertising
+    - net/mlx5: Fix memory leak on flow table creation error flow
+    - net/mlx5e: E-switch, Fix rate calculation for overflow
+    - net/mlx5e: Reduce tc unsupported key print level
+    - can: dev: prevent potential information leak in can_fill_info()
+    - nvme-multipath: Early exit if no path is available
+    - selftests: forwarding: Specify interface when invoking mausezahn
+    - iommu/vt-d: Gracefully handle DMAR units with no supported address widths
+    - iommu/vt-d: Don't dereference iommu_device if IOMMU_API is not built
+    - rxrpc: Fix memory leak in rxrpc_lookup_local
+    - NFC: fix resource leak when target index is invalid
+    - NFC: fix possible resource leak
+    - ASoC: topology: Fix memory corruption in soc_tplg_denum_create_values()
+    - team: protect features update by RCU to avoid deadlock
+    - tcp: fix TLP timer not set when CA_STATE changes from DISORDER to OPEN
+    - Linux 5.4.95
+
+  [ Ubuntu: 5.4.0-70.78 ]
+
+  * CVE-2020-27170
+    - bpf: Fix off-by-one for area size in creating mask to left
+  * CVE-2020-27171
+    - bpf: Prohibit alu ops for pointer types not defining ptr_limit
+  * binary assembly failures with CONFIG_MODVERSIONS present (LP: #1919315)
+    - [Packaging] quiet (nomially) benign errors in BUILD script
+
+  [ Ubuntu: 5.4.0-69.77 ]
+
+  * CVE-2021-3444
+    - bpf: Fix 32 bit src register truncation on div/mod
+    - bpf: Fix truncation handling for mod32 dst reg wrt zero
+  * CVE-2021-27365
+    - scsi: iscsi: Verify lengths on passthrough PDUs
+    - sysfs: Add sysfs_emit and sysfs_emit_at to format sysfs output
+    - scsi: iscsi: Ensure sysfs attributes are limited to PAGE_SIZE
+  * CVE-2021-27363 // CVE-2021-27364
+    - scsi: iscsi: Restrict sessions and handles to admin capabilities
+
+  [ Ubuntu: 5.4.0-67.75 ]
+
+  * focal/linux: 5.4.0-67.75 -proposed tracker (LP: #1916169)
+  * Please trust Canonical Livepatch Service kmod signing key (LP: #1898716)
+    - [Config] enable CONFIG_MODVERSIONS=y
+    - [Packaging] build canonical-certs.pem from branch/arch certs
+    - [Config] add Canonical Livepatch Service key to SYSTEM_TRUSTED_KEYS
+    - [Config] add ubuntu-drivers key to SYSTEM_TRUSTED_KEYS
+    - [Config] Allow ASM_MODVERSIONS and MODULE_REL_CRCS
+  * geneve overlay network on vlan interface broken with offload enabled
+    (LP: #1914447)
+    - net/mlx5e: Fix SWP offsets when vlan inserted by driver
+  * Add support for selective build of special drivers (LP: #1912789)
+    - [Packaging] Fix ODM support in actual build
+  * devlink: don't do reporter recovery if the state is healthy (LP: #1915403)
+    - devlink: don't do reporter recovery if the state is healthy
+  * Missing device id for Intel TGL-H ISH [8086:43fc] in intel-ish-hid driver
+    (LP: #1914543)
+    - HID: intel-ish-hid: ipc: Add Tiger Lake H PCI device ID
+  * Focal update: v5.4.94 upstream stable release (LP: #1915200)
+    - gpio: mvebu: fix pwm .get_state period calculation
+    - futex: Ensure the correct return value from futex_lock_pi()
+    - futex: Replace pointless printk in fixup_owner()
+    - futex: Provide and use pi_state_update_owner()
+    - rtmutex: Remove unused argument from rt_mutex_proxy_unlock()
+    - futex: Use pi_state_update_owner() in put_pi_state()
+    - futex: Simplify fixup_pi_state_owner()
+    - futex: Handle faults correctly for PI futexes
+    - HID: wacom: Correct NULL dereference on AES pen proximity
+    - io_uring: Fix current->fs handling in io_sq_wq_submit_work()
+    - tracing: Fix race in trace_open and buffer resize call
+    - arm64: mm: use single quantity to represent the PA to VA translation
+    - SMB3.1.1: do not log warning message if server doesn't populate salt
+    - tools: Factor HOSTCC, HOSTLD, HOSTAR definitions
+    - dm integrity: conditionally disable "recalculate" feature
+    - writeback: Drop I_DIRTY_TIME_EXPIRE
+    - fs: fix lazytime expiration handling in __writeback_single_inode()
+    - Linux 5.4.94
+  * Focal update: v5.4.93 upstream stable release (LP: #1915195)
+    - i2c: bpmp-tegra: Ignore unknown I2C_M flags
+    - platform/x86: ideapad-laptop: Disable touchpad_switch for ELAN0634
+    - ALSA: seq: oss: Fix missing error check in snd_seq_oss_synth_make_info()
+    - ALSA: hda/via: Add minimum mute flag
+    - ACPI: scan: Make acpi_bus_get_device() clear return pointer on error
+    - btrfs: don't get an EINTR during drop_snapshot for reloc
+    - btrfs: fix lockdep splat in btrfs_recover_relocation
+    - btrfs: don't clear ret in btrfs_start_dirty_block_groups
+    - btrfs: send: fix invalid clone operations when cloning from the same file
+      and root
+    - mmc: core: don't initialize block size from ext_csd if not present
+    - mmc: sdhci-xenon: fix 1.8v regulator stabilization
+    - dm: avoid filesystem lookup in dm_get_dev_t()
+    - dm integrity: fix a crash if "recalculate" used without "internal_hash"
+    - drm/atomic: put state on error path
+    - drm/syncobj: Fix use-after-free
+    - drm/i915/gt: Prevent use of engine->wa_ctx after error
+    - ASoC: Intel: haswell: Add missing pm_ops
+    - dm integrity: select CRYPTO_SKCIPHER
+    - scsi: ufs: Correct the LUN used in eh_device_reset_handler() callback
+    - scsi: qedi: Correct max length of CHAP secret
+    - scsi: sd: Suppress spurious errors when WRITE SAME is being disabled
+    - riscv: Fix kernel time_init()
+    - riscv: Fix sifive serial driver
+    - HID: logitech-dj: add the G602 receiver
+    - HID: Ignore battery for Elan touchscreen on ASUS UX550
+    - clk: tegra30: Add hda clock default rates to clock driver
+    - arm64: make atomic helpers __always_inline
+    - xen: Fix event channel callback via INTX/GSI
+    - x86/xen: Add xen_no_vector_callback option to test PCI INTX delivery
+    - dts: phy: fix missing mdio device and probe failure of vsc8541-01 device
+    - riscv: defconfig: enable gpio support for HiFive Unleashed
+    - drm/amdgpu/psp: fix psp gfx ctrl cmds
+    - drm/amd/display: Fix to be able to stop crc calculation
+    - drm/nouveau/bios: fix issue shadowing expansion ROMs
+    - drm/nouveau/privring: ack interrupts the same way as RM
+    - drm/nouveau/i2c/gm200: increase width of aux semaphore owner fields
+    - drm/nouveau/mmu: fix vram heap sizing
+    - drm/nouveau/kms/nv50-: fix case where notifier buffer is at offset 0
+    - powerpc: Use the common INIT_DATA_SECTION macro in vmlinux.lds.S
+    - pinctrl: aspeed: g6: Fix PWMG0 pinctrl setting
+    - scsi: megaraid_sas: Fix MEGASAS_IOC_FIRMWARE regression
+    - powerpc: Fix alignment bug within the init sections
+    - i2c: octeon: check correct size of maximum RECV_LEN packet
+    - platform/x86: intel-vbtn: Drop HP Stream x360 Convertible PC 11 from allow-
+      list
+    - selftests: net: fib_tests: remove duplicate log test
+    - can: dev: can_restart: fix use after free bug
+    - can: vxcan: vxcan_xmit: fix use after free bug
+    - can: peak_usb: fix use after free bugs
+    - iio: ad5504: Fix setting power-down state
+    - cifs: do not fail __smb_send_rqst if non-fatal signals are pending
+    - irqchip/mips-cpu: Set IPI domain parent chip
+    - x86/fpu: Add kernel_fpu_begin_mask() to selectively initialize state
+    - x86/topology: Make __max_die_per_package available unconditionally
+    - x86/mmx: Use KFPU_387 for MMX string operations
+    - intel_th: pci: Add Alder Lake-P support
+    - stm class: Fix module init return on allocation failure
+    - serial: mvebu-uart: fix tx lost characters at power off
+    - ehci: fix EHCI host controller initialization sequence
+    - USB: ehci: fix an interrupt calltrace error
+    - usb: gadget: aspeed: fix stop dma register setting.
+    - usb: udc: core: Use lock when write to soft_connect
+    - [Config] updateconfigs for USB_BDC_PCI
+    - usb: bdc: Make bdc pci driver depend on BROKEN
+    - xhci: make sure TRB is fully written before giving it to the controller
+    - xhci: tegra: Delay for disabling LFPS detector
+    - driver core: Extend device_is_dependent()
+    - pinctrl: ingenic: Fix JZ4760 support
+    - x86/cpu/amd: Set __max_die_per_package on AMD
+    - netfilter: rpfilter: mask ecn bits before fib lookup
+    - sh: dma: fix kconfig dependency for G2_DMA
+    - net: dsa: mv88e6xxx: also read STU state in mv88e6250_g1_vtu_getnext
+    - sh_eth: Fix power down vs. is_opened flag ordering
+    - lightnvm: fix memory leak when submit fails
+    - skbuff: back tiny skbs with kmalloc() in __netdev_alloc_skb() too
+    - kasan: fix unaligned address is unhandled in kasan_remove_zero_shadow
+    - kasan: fix incorrect arguments passing in kasan_add_zero_shadow
+    - udp: mask TOS bits in udp_v4_early_demux()
+    - ipv6: create multicast route with RTPROT_KERNEL
+    - net_sched: avoid shift-out-of-bounds in tcindex_set_parms()
+    - net_sched: reject silly cell_log in qdisc_get_rtab()
+    - ipv6: set multicast flag on the multicast route
+    - net: mscc: ocelot: allow offloading of bridge on top of LAG
+    - net: Disable NETIF_F_HW_TLS_RX when RXCSUM is disabled
+    - net: dsa: b53: fix an off by one in checking "vlan->vid"
+    - tcp: do not mess with cloned skbs in tcp_add_backlog()
+    - tcp: fix TCP_USER_TIMEOUT with zero window
+    - Linux 5.4.93
+  * High load from process irq/65-i2c-INT3  - kernel module tps6598x
+    (LP: #1883511) // Focal update: v5.4.93 upstream stable release
+    (LP: #1915195)
+    - platform/x86: i2c-multi-instantiate: Don't create platform device for
+      INT3515 ACPI nodes
+  * Focal update: v5.4.92 upstream stable release (LP: #1915186)
+    - usb: ohci: Make distrust_firmware param default to false
+    - compiler.h: Raise minimum version of GCC to 5.1 for arm64
+    - xen/privcmd: allow fetching resource sizes
+    - elfcore: fix building with clang
+    - scsi: lpfc: Make lpfc_defer_acc_rsp static
+    - spi: npcm-fiu: simplify the return expression of npcm_fiu_probe()
+    - spi: npcm-fiu: Disable clock in probe error path
+    - nfsd4: readdirplus shouldn't return parent of export
+    - bpf: Don't leak memory in bpf getsockopt when optlen == 0
+    - bpf: Fix helper bpf_map_peek_elem_proto pointing to wrong callback
+    - udp: Prevent reuseport_select_sock from reading uninitialized socks
+    - netxen_nic: fix MSI/MSI-x interrupts
+    - net: introduce skb_list_walk_safe for skb segment walking
+    - net: skbuff: disambiguate argument and member for skb_list_walk_safe helper
+    - net: ipv6: Validate GSO SKB before finish IPv6 processing
+    - mlxsw: core: Add validation of transceiver temperature thresholds
+    - mlxsw: core: Increase critical threshold for ASIC thermal zone
+    - net: mvpp2: Remove Pause and Asym_Pause support
+    - rndis_host: set proper input size for OID_GEN_PHYSICAL_MEDIUM request
+    - esp: avoid unneeded kmap_atomic call
+    - net: dcb: Validate netlink message in DCB handler
+    - net: dcb: Accept RTM_GETDCB messages carrying set-like DCB commands
+    - rxrpc: Call state should be read with READ_ONCE() under some circumstances
+    - net: stmmac: Fixed mtu channged by cache aligned
+    - net: sit: unregister_netdevice on newlink's error path
+    - net: avoid 32 x truesize under-estimation for tiny skbs
+    - rxrpc: Fix handling of an unsupported token type in rxrpc_read()
+    - net, sctp, filter: remap copy_from_user failure error
+    - tipc: fix NULL deref in tipc_link_xmit()
+    - mac80211: do not drop tx nulldata packets on encrypted links
+    - mac80211: check if atf has been disabled in __ieee80211_schedule_txq
+    - spi: cadence: cache reference clock rate during probe
+    - Linux 5.4.92
+  * intel-hid is not loaded on new Intel platform (LP: #1907160)
+    - platform/x86: intel-hid: Add Tiger Lake ACPI device ID
+    - platform/x86: intel-hid: fix: Update Tiger Lake ACPI device ID
+    - platform/x86: intel-hid: Move MODULE_DEVICE_TABLE() closer to the table
+    - platform/x86: intel-hid: add Rocket Lake ACPI device ID
+  * Support Advantech UNO-420 platform (LP: #1902672)
+    - ODM: MAINTAINERS: Add Advantech AHC1EC0 embedded controller entry
+    - ODM: mfd: ahc1ec0: Add Advantech EC include file used by dt-bindings
+    - ODM: dt-bindings: mfd: ahc1ec0.yaml: Add Advantech embedded controller -
+      AHC1EC0
+    - ODM: mfd: ahc1ec0: Add support for Advantech embedded controller
+    - ODM: hwmon: ahc1ec0-hwmon: Add sub-device hwmon for Advantech embedded
+      controller
+    - ODM: watchdog: ahc1ec0-wdt: Add sub-device watchdog for Advantech embedded
+      controller
+    - ODM: [Config] update config for Advantech devices
+  * Remove scary stack trace from Realtek WiFi driver (LP: #1913263)
+    - rtw88: reduce the log level for failure of tx report
+  * Focal update: v5.4.91 upstream stable release (LP: #1914654)
+    - kbuild: enforce -Werror=return-type
+    - btrfs: prevent NULL pointer dereference in extent_io_tree_panic
+    - ASoC: dapm: remove widget from dirty list on free
+    - x86/hyperv: check cpu mask after interrupt has been disabled
+    - tracing/kprobes: Do the notrace functions check without kprobes on ftrace
+    - [Config] update annotations for KPROBE_EVENTS_ON_NOTRACE
+    - mips: fix Section mismatch in reference
+    - mips: lib: uncached: fix non-standard usage of variable 'sp'
+    - MIPS: boot: Fix unaligned access with CONFIG_MIPS_RAW_APPENDED_DTB
+    - MIPS: relocatable: fix possible boot hangup with KASLR enabled
+    - RDMA/ocrdma: Fix use after free in ocrdma_dealloc_ucontext_pd()
+    - ACPI: scan: Harden acpi_device_add() against device ID overflows
+    - mm/hugetlb: fix potential missing huge page size info
+    - dm raid: fix discard limits for raid1
+    - dm snapshot: flush merged data before committing metadata
+    - dm integrity: fix the maximum number of arguments
+    - r8152: Add Lenovo Powered USB-C Travel Hub
+    - btrfs: tree-checker: check if chunk item end overflows
+    - drm/i915/backlight: fix CPU mode backlight takeover on LPT
+    - ext4: fix bug for rename with RENAME_WHITEOUT
+    - ext4: don't leak old mountpoint samples
+    - cifs: fix interrupted close commands
+    - dm integrity: fix flush with external metadata device
+    - ARC: build: remove non-existing bootpImage from KBUILD_IMAGE
+    - ARC: build: add uImage.lzma to the top-level target
+    - ARC: build: add boot_targets to PHONY
+    - ARC: build: move symlink creation to arch/arc/Makefile to avoid race
+    - netfilter: ipset: fixes possible oops in mtype_resize
+    - btrfs: fix transaction leak and crash after RO remount caused by qgroup
+      rescan
+    - regulator: bd718x7: Add enable times
+    - ethernet: ucc_geth: fix definition and size of ucc_geth_tx_global_pram
+    - habanalabs: register to pci shutdown callback
+    - habanalabs: Fix memleak in hl_device_reset
+    - hwmon: (pwm-fan) Ensure that calculation doesn't discard big period values
+    - lib/raid6: Let $(UNROLL) rules work with macOS userland
+    - bfq: Fix computation of shallow depth
+    - arch/arc: add copy_user_page() to <asm/page.h> to fix build error on ARC
+    - misdn: dsp: select CONFIG_BITREVERSE
+    - net: ethernet: fs_enet: Add missing MODULE_LICENSE
+    - nvme-pci: mark Samsung PM1725a as IGNORE_DEV_SUBNQN
+    - nvmet-rdma: Fix list_del corruption on queue establishment failure
+    - drm/amdgpu: fix a GPU hang issue when remove device
+    - usb: typec: Fix copy paste error for NVIDIA alt-mode description
+    - ACPI: scan: add stub acpi_create_platform_device() for !CONFIG_ACPI
+    - drm/msm: Call msm_init_vram before binding the gpu
+    - ARM: picoxcell: fix missing interrupt-parent properties
+    - perf intel-pt: Fix 'CPU too large' error
+    - dump_common_audit_data(): fix racy accesses to ->d_name
+    - ASoC: meson: axg-tdm-interface: fix loopback
+    - ASoC: meson: axg-tdmin: fix axg skew offset
+    - ASoC: Intel: fix error code cnl_set_dsp_D0()
+    - nvme-tcp: fix possible data corruption with bio merges
+    - NFS4: Fix use-after-free in trace_event_raw_event_nfs4_set_lock
+    - pNFS: We want return-on-close to complete when evicting the inode
+    - pNFS: Mark layout for return if return-on-close was not sent
+    - pNFS: Stricter ordering of layoutget and layoutreturn
+    - NFS/pNFS: Fix a leak of the layout 'plh_outstanding' counter
+    - NFS: nfs_igrab_and_active must first reference the superblock
+    - ext4: fix superblock checksum failure when setting password salt
+    - RDMA/restrack: Don't treat as an error allocation ID wrapping
+    - RDMA/usnic: Fix memleak in find_free_vf_and_create_qp_grp
+    - bnxt_en: Improve stats context resource accounting with RDMA driver loaded.
+    - RDMA/mlx5: Fix wrong free of blue flame register on error
+    - IB/mlx5: Fix error unwinding when set_has_smi_cap fails
+    - drm/i915/dsi: Use unconditional msleep for the panel_on_delay when there is
+      no reset-deassert MIPI-sequence
+    - mm, slub: consider rest of partial list if acquire_slab() fails
+    - iommu/vt-d: Fix unaligned addresses for intel_flush_svm_range_dev()
+    - net: sunrpc: interpret the return value of kstrtou32 correctly
+    - dm: eliminate potential source of excessive kernel log noise
+    - ALSA: fireface: Fix integer overflow in transmit_midi_msg()
+    - ALSA: firewire-tascam: Fix integer overflow in midi_port_work()
+    - netfilter: conntrack: fix reading nf_conntrack_buckets
+    - netfilter: nf_nat: Fix memleak in nf_nat_init
+    - netfilter: nft_compat: remove flush counter optimization
+    - Linux 5.4.91
+  * Focal update: v5.4.90 upstream stable release (LP: #1913487)
+    - x86/asm/32: Add ENDs to some functions and relabel with SYM_CODE_*
+    - vfio iommu: Add dma available capability
+    - net: cdc_ncm: correct overhead in delayed_ndp_size
+    - net: hns3: fix the number of queues actually used by ARQ
+    - net: hns3: fix a phy loopback fail issue
+    - net: stmmac: dwmac-sun8i: Balance internal PHY resource references
+    - net: stmmac: dwmac-sun8i: Balance internal PHY power
+    - net: vlan: avoid leaks on register_vlan_dev() failures
+    - net/sonic: Fix some resource leaks in error handling paths
+    - net: ipv6: fib: flush exceptions when purging route
+    - tools: selftests: add test for changing routes with PTMU exceptions
+    - net: fix pmtu check in nopmtudisc mode
+    - net: ip: always refragment ip defragmented packets
+    - octeontx2-af: fix memory leak of lmac and lmac->name
+    - nexthop: Fix off-by-one error in error path
+    - nexthop: Unlink nexthop group entry in error path
+    - s390/qeth: fix L2 header access in qeth_l3_osa_features_check()
+    - net: dsa: lantiq_gswip: Exclude RMII from modes that report 1 GbE
+    - net/mlx5: Use port_num 1 instead of 0 when delete a RoCE address
+    - net/mlx5e: ethtool, Fix restriction of autoneg with 56G
+    - chtls: Fix hardware tid leak
+    - chtls: Remove invalid set_tcb call
+    - chtls: Fix panic when route to peer not configured
+    - chtls: Replace skb_dequeue with skb_peek
+    - chtls: Added a check to avoid NULL pointer dereference
+    - chtls: Fix chtls resources release sequence
+    - x86/resctrl: Use an IPI instead of task_work_add() to update PQR_ASSOC MSR
+    - x86/resctrl: Don't move a task to the same resource group
+    - exfat: Month timestamp metadata accidentally incremented
+    - vmlinux.lds.h: Add PGO and AutoFDO input sections
+    - iio: imu: st_lsm6dsx: fix edge-trigger interrupts
+    - HID: wacom: Fix memory leakage caused by kfifo_alloc
+    - ARM: OMAP2+: omap_device: fix idling of devices during probe
+    - i2c: sprd: use a specific timeout to avoid system hang up issue
+    - dmaengine: dw-edma: Fix use after free in dw_edma_alloc_chunk()
+    - can: tcan4x5x: fix bittiming const, use common bittiming from m_can driver
+    - can: m_can: m_can_class_unregister(): remove erroneous m_can_clk_stop()
+    - can: kvaser_pciefd: select CONFIG_CRC32
+    - cpufreq: powernow-k8: pass policy rather than use cpufreq_cpu_get()
+    - spi: stm32: FIFO threshold level - fix align packet size
+    - i2c: i801: Fix the i2c-mux gpiod_lookup_table not being properly terminated
+    - dmaengine: mediatek: mtk-hsdma: Fix a resource leak in the error handling
+      path of the probe function
+    - dmaengine: xilinx_dma: check dma_async_device_register return value
+    - dmaengine: xilinx_dma: fix incompatible param warning in _child_probe()
+    - dmaengine: xilinx_dma: fix mixed_enum_type coverity warning
+    - qed: select CONFIG_CRC32
+    - wil6210: select CONFIG_CRC32
+    - block: rsxx: select CONFIG_CRC32
+    - lightnvm: select CONFIG_CRC32
+    - iommu/intel: Fix memleak in intel_irq_remapping_alloc
+    - bpftool: Fix compilation failure for net.o with older glibc
+    - net/mlx5e: Fix memleak in mlx5e_create_l2_table_groups
+    - net/mlx5e: Fix two double free cases
+    - regmap: debugfs: Fix a memory leak when calling regmap_attach_dev
+    - wan: ds26522: select CONFIG_BITREVERSE
+    - regulator: qcom-rpmh-regulator: correct hfsmps515 definition
+    - net: mvpp2: disable force link UP during port init procedure
+    - KVM: arm64: Don't access PMCR_EL0 when no PMU is available
+    - block: fix use-after-free in disk_part_iter_next
+    - net: drop bogus skb with CHECKSUM_PARTIAL and offset beyond end of trimmed
+      packet
+    - regmap: debugfs: Fix a reversed if statement in regmap_debugfs_init()
+    - Linux 5.4.90
+  * Focal update: v5.4.89 upstream stable release (LP: #1913486)
+    - workqueue: Kick a worker based on the actual activation of delayed works
+    - scsi: ufs: Fix wrong print message in dev_err()
+    - scsi: ufs-pci: Ensure UFS device is in PowerDown mode for suspend-to-disk
+      ->poweroff()
+    - scsi: ide: Do not set the RQF_PREEMPT flag for sense requests
+    - scsi: scsi_transport_spi: Set RQF_PM for domain validation commands
+    - lib/genalloc: fix the overflow when size is too big
+    - depmod: handle the case of /sbin/depmod without /sbin in PATH
+    - proc: change ->nlink under proc_subdir_lock
+    - proc: fix lookup in /proc/net subdirectories after setns(2)
+    - i40e: Fix Error I40E_AQ_RC_EINVAL when removing VFs
+    - iavf: fix double-release of rtnl_lock
+    - net: mvpp2: Add TCAM entry to drop flow control pause frames
+    - net: mvpp2: prs: fix PPPoE with ipv6 packet parse
+    - net: systemport: set dev->max_mtu to UMAC_MAX_MTU_SIZE
+    - ethernet: ucc_geth: fix use-after-free in ucc_geth_remove()
+    - ethernet: ucc_geth: set dev->max_mtu to 1518
+    - atm: idt77252: call pci_disable_device() on error path
+    - net: mvpp2: Fix GoP port 3 Networking Complex Control configurations
+    - ibmvnic: continue fatal error reset after passive init
+    - net: ethernet: mvneta: Fix error handling in mvneta_probe
+    - virtio_net: Fix recursive call to cpus_read_lock()
+    - net/ncsi: Use real net-device for response handler
+    - net: ethernet: Fix memleak in ethoc_probe
+    - net-sysfs: take the rtnl lock when storing xps_cpus
+    - net-sysfs: take the rtnl lock when accessing xps_cpus_map and num_tc
+    - net-sysfs: take the rtnl lock when storing xps_rxqs
+    - net-sysfs: take the rtnl lock when accessing xps_rxqs_map and num_tc
+    - net: ethernet: ti: cpts: fix ethtool output when no ptp_clock registered
+    - tun: fix return value when the number of iovs exceeds MAX_SKB_FRAGS
+    - net: mvpp2: fix pkt coalescing int-threshold configuration
+    - ipv4: Ignore ECN bits for fib lookups in fib_compute_spec_dst()
+    - net: sched: prevent invalid Scell_log shift count
+    - net: hns: fix return value check in __lb_other_process()
+    - erspan: fix version 1 check in gre_parse_header()
+    - net: hdlc_ppp: Fix issues when mod_timer is called while timer is running
+    - r8169: work around power-saving bug on some chip versions
+    - net: dsa: lantiq_gswip: Enable GSWIP_MII_CFG_EN also for internal PHYs
+    - net: dsa: lantiq_gswip: Fix GSWIP_MII_CFG(p) register access
+    - CDC-NCM: remove "connected" log message
+    - net: usb: qmi_wwan: add Quectel EM160R-GL
+    - vhost_net: fix ubuf refcount incorrectly when sendmsg fails
+    - ionic: account for vlan tag len in rx buffer len
+    - net/sched: sch_taprio: ensure to reset/destroy all child qdiscs
+    - kbuild: don't hardcode depmod path
+    - Bluetooth: revert: hci_h5: close serdev device and free hu in h5_close
+    - video: hyperv_fb: Fix the mmap() regression for v5.4.y and older
+    - crypto: ecdh - avoid buffer overflow in ecdh_set_secret()
+    - crypto: asym_tpm: correct zero out potential secrets
+    - powerpc: Handle .text.{hot,unlikely}.* in linker script
+    - staging: mt7621-dma: Fix a resource leak in an error handling path
+    - usb: gadget: enable super speed plus
+    - USB: cdc-acm: blacklist another IR Droid device
+    - USB: cdc-wdm: Fix use after free in service_outstanding_interrupt().
+    - usb: dwc3: ulpi: Use VStsDone to detect PHY regs access completion
+    - usb: chipidea: ci_hdrc_imx: add missing put_device() call in
+      usbmisc_get_init_data()
+    - USB: xhci: fix U1/U2 handling for hardware with XHCI_INTEL_HOST quirk set
+    - usb: usbip: vhci_hcd: protect shift size
+    - usb: uas: Add PNY USB Portable SSD to unusual_uas
+    - USB: serial: iuu_phoenix: fix DMA from stack
+    - USB: serial: option: add LongSung M5710 module support
+    - USB: serial: option: add Quectel EM160R-GL
+    - USB: yurex: fix control-URB timeout handling
+    - USB: usblp: fix DMA to stack
+    - ALSA: usb-audio: Fix UBSAN warnings for MIDI jacks
+    - usb: gadget: select CONFIG_CRC32
+    - usb: gadget: f_uac2: reset wMaxPacketSize
+    - usb: gadget: function: printer: Fix a memory leak for interface descriptor
+    - usb: gadget: u_ether: Fix MTU size mismatch with RX packet size
+    - USB: gadget: legacy: fix return error code in acm_ms_bind()
+    - usb: gadget: Fix spinlock lockup on usb_function_deactivate
+    - usb: gadget: configfs: Preserve function ordering after bind failure
+    - usb: gadget: configfs: Fix use-after-free issue with udc_name
+    - USB: serial: keyspan_pda: remove unused variable
+    - x86/mm: Fix leak of pmd ptlock
+    - kvm: check tlbs_dirty directly
+    - ALSA: hda/via: Fix runtime PM for Clevo W35xSS
+    - ALSA: hda/conexant: add a new hda codec CX11970
+    - ALSA: hda/realtek - Fix speaker volume control on Lenovo C940
+    - ALSA: hda/realtek: Add two "Intel Reference board" SSID in the ALC256.
+    - btrfs: send: fix wrong file path when there is an inode with a pending rmdir
+    - Revert "device property: Keep secondary firmware node secondary by type"
+    - dmabuf: fix use-after-free of dmabuf's file->f_inode
+    - drm/i915: clear the gpu reloc batch
+    - netfilter: x_tables: Update remaining dereference to RCU
+    - netfilter: ipset: fix shift-out-of-bounds in htable_bits()
+    - netfilter: xt_RATEEST: reject non-null terminated string from userspace
+    - netfilter: nft_dynset: report EOPNOTSUPP on missing set feature
+    - x86/mtrr: Correct the range check before performing MTRR type lookups
+    - KVM: x86: fix shift out of bounds reported by UBSAN
+    - Linux 5.4.89
+  * Focal update: v5.4.88 upstream stable release (LP: #1913223)
+    - Revert "drm/amd/display: Fix memory leaks in S3 resume"
+    - Revert "mtd: spinand: Fix OOB read"
+    - dmaengine: at_hdmac: Substitute kzalloc with kmalloc
+    - dmaengine: at_hdmac: add missing put_device() call in at_dma_xlate()
+    - dmaengine: at_hdmac: add missing kfree() call in at_dma_xlate()
+    - kdev_t: always inline major/minor helper functions
+    - iio:imu:bmi160: Fix alignment and data leak issues
+    - fuse: fix bad inode
+    - perf: Break deadlock involving exec_update_mutex
+    - rwsem: Implement down_read_killable_nested
+    - rwsem: Implement down_read_interruptible
+    - exec: Transform exec_update_mutex into a rw_semaphore
+    - mwifiex: Fix possible buffer overflows in mwifiex_cmd_802_11_ad_hoc_start
+    - Linux 5.4.88
+  * Focal update: v5.4.87 upstream stable release (LP: #1912681)
+    - net/sched: sch_taprio: reset child qdiscs before freeing them
+    - md/raid10: initialize r10_bio->read_slot before use.
+    - thermal/drivers/cpufreq_cooling: Update cpufreq_state only if state has
+      changed
+    - ext4: prevent creating duplicate encrypted filenames
+    - ubifs: prevent creating duplicate encrypted filenames
+    - f2fs: prevent creating duplicate encrypted filenames
+    - fscrypt: add fscrypt_is_nokey_name()
+    - fscrypt: remove kernel-internal constants from UAPI header
+    - vfio/pci: Move dummy_resources_list init in vfio_pci_probe()
+    - btrfs: fix race when defragmenting leads to unnecessary IO
+    - ext4: don't remount read-only with errors=continue on reboot
+    - KVM: x86: avoid incorrect writes to host MSR_IA32_SPEC_CTRL
+    - KVM: SVM: relax conditions for allowing MSR_IA32_SPEC_CTRL accesses
+    - KVM: x86: reinstate vendor-agnostic check on SPEC_CTRL cpuid bits
+    - powerpc/bitops: Fix possible undefined behaviour with fls() and fls64()
+    - jffs2: Allow setting rp_size to zero during remounting
+    - jffs2: Fix NULL pointer dereference in rp_size fs option parsing
+    - scsi: block: Fix a race in the runtime power management code
+    - uapi: move constants from <linux/kernel.h> to <linux/const.h>
+    - tools headers UAPI: Sync linux/const.h with the kernel headers
+    - null_blk: Fix zone size initialization
+    - of: fix linker-section match-table corruption
+    - cgroup: Fix memory leak when parsing multiple source parameters
+    - scsi: cxgb4i: Fix TLS dependency
+    - Bluetooth: hci_h5: close serdev device and free hu in h5_close
+    - reiserfs: add check for an invalid ih_entry_count
+    - misc: vmw_vmci: fix kernel info-leak by initializing dbells in
+      vmci_ctx_get_chkpt_doorbells()
+    - media: gp8psk: initialize stats at power control logic
+    - f2fs: fix shift-out-of-bounds in sanity_check_raw_super()
+    - ALSA: seq: Use bool for snd_seq_queue internal flags
+    - ALSA: rawmidi: Access runtime->avail always in spinlock
+    - bfs: don't use WARNING: string when it's just info.
+    - fcntl: Fix potential deadlock in send_sig{io, urg}()
+    - rtc: sun6i: Fix memleak in sun6i_rtc_clk_init
+    - module: set MODULE_STATE_GOING state when a module fails to load
+    - quota: Don't overflow quota file offsets
+    - rtc: pl031: fix resource leak in pl031_probe
+    - powerpc: sysdev: add missing iounmap() on error in mpic_msgr_probe()
+    - i3c master: fix missing destroy_workqueue() on error in i3c_master_register
+    - NFSv4: Fix a pNFS layout related use-after-free race when freeing the inode
+    - f2fs: avoid race condition for shrinker count
+    - module: delay kobject uevent until after module init call
+    - fs/namespace.c: WARN if mnt_count has become negative
+    - um: ubd: Submit all data segments atomically
+    - tick/sched: Remove bogus boot "safety" check
+    - ALSA: pcm: Clear the full allocated memory at hw_params
+    - dm verity: skip verity work if I/O error when system is shutting down
+    - Linux 5.4.87
+
+  [ Ubuntu: 5.4.0-66.74 ]
+
+  * focal/linux: 5.4.0-66.74 -proposed tracker (LP: #1913152)
+  * Add support for selective build of special drivers (LP: #1912789)
+    - [Packaging] Add support for ODM drivers
+    - [Packaging] Turn on ODM support for amd64
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+    - update dkms package versions
+  * Introduce the new NVIDIA 460-server series and update the 460 series
+    (LP: #1913200)
+    - [Config] dkms-versions -- drop NVIDIA 435 455 and 440-server
+    - [Config] dkms-versions -- add the 460-server nvidia driver
+  * Enable mute and micmute LED on HP EliteBook 850 G7 (LP: #1910102)
+    - ALSA: hda/realtek: Enable mute and micmute LED on HP EliteBook 850 G7
+  * SYNA30B4:00 06CB:CE09 Mouse  on HP EliteBook 850 G7 not working at all
+    (LP: #1908992)
+    - HID: multitouch: Enable multi-input for Synaptics pointstick/touchpad device
+  * HD Audio Device PCI ID for the Intel Cometlake-R platform (LP: #1912427)
+    - SAUCE: ALSA: hda: Add Cometlake-R PCI ID
+  * switch to an autogenerated nvidia series based core via dkms-versions
+    (LP: #1912803)
+    - [Packaging] nvidia -- use dkms-versions to define versions built
+    - [Packaging] update-version-dkms -- maintain flags fields
+    - [Config] dkms-versions -- add transitional/skip information for nvidia
+      packages
+  * udpgro.sh in net from ubuntu_kernel_selftests seems not reflecting sub-test
+    result (LP: #1908499)
+    - selftests: fix the return value for UDP GRO test
+  * qede: Kubernetes Internal DNS Failure due to QL41xxx NIC not supporting IPIP
+    tx csum offload (LP: #1909062)
+    - qede: fix offload for IPIP tunnel packets
+  * Use DCPD to control HP DreamColor panel (LP: #1911001)
+    - SAUCE: drm/dp: Another HP DreamColor panel brigntness fix
+  * kvm: Windows 2k19 with Hyper-v role gets stuck on pending hypervisor
+    requests on cascadelake based kvm hosts (LP: #1911848)
+    - KVM: x86: Set KVM_REQ_EVENT if run is canceled with req_immediate_exit set
+  * Ubuntu 20.10 four needed fixes to 'Add driver for Mellanox Connect-IB
+    adapters' (LP: #1905574)
+    - net/mlx5: Fix a race when moving command interface to polling mode
+  * Fix right sounds and mute/micmute LEDs for HP ZBook Fury 15/17 G7 Mobile
+    Workstation (LP: #1910561)
+    - ALSA: hda/realtek: fix right sounds and mute/micmute LEDs for HP machines
+  * Ubuntu 20.04 - multicast counter is not increased in ip -s (LP: #1901842)
+    - net/mlx5e: Fix multicast counter not up-to-date in "ip -s"
+  * eeh-basic.sh in powerpc from ubuntu_kernel_selftests timeout with 5.4 P8 /
+    P9 (LP: #1882503)
+    - selftests/powerpc/eeh: disable kselftest timeout setting for eeh-basic
+  * DMI entry syntax fix for Pegatron / ByteSpeed C15B (LP: #1910639)
+    - Input: i8042 - unbreak Pegatron C15B
+  * CVE-2020-29372
+    - mm: check that mm is still valid in madvise()
+  * update ENA driver, incl. new ethtool stats (LP: #1910291)
+    - net: ena: Change WARN_ON expression in ena_del_napi_in_range()
+    - net: ena: ethtool: convert stat_offset to 64 bit resolution
+    - net: ena: ethtool: Add new device statistics
+    - net: ena: ethtool: add stats printing to XDP queues
+    - net: ena: xdp: add queue counters for xdp actions
+    - net: ena: Change license into format to SPDX in all files
+    - net: ena: Change log message to netif/dev function
+    - net: ena: Capitalize all log strings and improve code readability
+    - net: ena: Remove redundant print of placement policy
+    - net: ena: Change RSS related macros and variables names
+    - net: ena: Fix all static chekers' warnings
+    - drivers/net/ethernet: remove incorrectly formatted doc
+    - net: ena: handle bad request id in ena_netdev
+    - net: ena: fix packet's addresses for rx_offset feature
+  * s390x broken with unknown syscall number on kernels < 5.8 (LP: #1895132)
+    - s390/ptrace: return -ENOSYS when invalid syscall is supplied
+  * Focal update: v5.4.86 upstream stable release (LP: #1910822)
+    - ARM: dts: sun7i: bananapi: Enable RGMII RX/TX delay on Ethernet PHY
+    - ARM: dts: sun8i: r40: bananapi-m2-berry: Fix dcdc1 regulator
+    - ARM: dts: sun8i: v40: bananapi-m2-berry: Fix ethernet node
+    - pinctrl: merrifield: Set default bias in case no particular value given
+    - pinctrl: baytrail: Avoid clearing debounce value when turning it off
+    - ARM: dts: sun8i: v3s: fix GIC node memory range
+    - ARM: dts: sun7i: pcduino3-nano: enable RGMII RX/TX delay on PHY
+    - ARM: dts: imx6qdl-wandboard-revd1: Remove PAD_GPIO_6 from enetgrp
+    - ARM: dts: imx6qdl-kontron-samx6i: fix I2C_PM scl pin
+    - PM: runtime: Add pm_runtime_resume_and_get to deal with usage counter
+    - gpio: zynq: fix reference leak in zynq_gpio functions
+    - gpio: mvebu: fix potential user-after-free on probe
+    - scsi: bnx2i: Requires MMU
+    - xsk: Fix xsk_poll()'s return type
+    - xsk: Replace datagram_poll by sock_poll_wait
+    - can: softing: softing_netdev_open(): fix error handling
+    - clk: renesas: r9a06g032: Drop __packed for portability
+    - block: Simplify REQ_OP_ZONE_RESET_ALL handling
+    - block: factor out requeue handling from dispatch code
+    - blk-mq: In blk_mq_dispatch_rq_list() "no budget" is a reason to kick
+    - pinctrl: aspeed: Fix GPIO requests on pass-through banks
+    - netfilter: x_tables: Switch synchronization to RCU
+    - netfilter: nft_compat: make sure xtables destructors have run
+    - netfilter: nft_dynset: fix timeouts later than 23 days
+    - afs: Fix memory leak when mounting with multiple source parameters
+    - Revert "gpio: eic-sprd: Use devm_platform_ioremap_resource()"
+    - gpio: eic-sprd: break loop when getting NULL device resource
+    - netfilter: nft_ct: Remove confirmation check for NFT_CT_ID
+    - selftests/bpf/test_offload.py: Reset ethtool features after failed setting
+    - RDMA/cm: Fix an attempt to use non-valid pointer when cleaning timewait
+    - i40e: Refactor rx_bi accesses
+    - i40e: optimise prefetch page refcount
+    - i40e: avoid premature Rx buffer reuse
+    - ixgbe: avoid premature Rx buffer reuse
+    - selftests: fix poll error in udpgro.sh
+    - net: mvpp2: add mvpp2_phylink_to_port() helper
+    - drm/tegra: replace idr_init() by idr_init_base()
+    - kernel/cpu: add arch override for clear_tasks_mm_cpumask() mm handling
+    - drm/tegra: sor: Disable clocks on error in tegra_sor_init()
+    - habanalabs: put devices before driver removal
+    - arm64: syscall: exit userspace before unmasking exceptions
+    - vxlan: Add needed_headroom for lower device
+    - vxlan: Copy needed_tailroom from lowerdev
+    - scsi: mpt3sas: Increase IOCInit request timeout to 30s
+    - dm table: Remove BUG_ON(in_interrupt())
+    - iwlwifi: pcie: add one missing entry for AX210
+    - drm/amd/display: Init clock value by current vbios CLKs
+    - perf/x86/intel: Check PEBS status correctly
+    - kbuild: avoid split lines in .mod files
+    - soc/tegra: fuse: Fix index bug in get_process_id
+    - usb: mtu3: fix memory corruption in mtu3_debugfs_regset()
+    - USB: serial: option: add interface-number sanity check to flag handling
+    - USB: gadget: f_acm: add support for SuperSpeed Plus
+    - USB: gadget: f_midi: setup SuperSpeed Plus descriptors
+    - usb: gadget: f_fs: Re-use SS descriptors for SuperSpeedPlus
+    - USB: gadget: f_rndis: fix bitrate for SuperSpeed and above
+    - usb: chipidea: ci_hdrc_imx: Pass DISABLE_DEVICE_STREAMING flag to imx6ul
+    - ARM: dts: exynos: fix roles of USB 3.0 ports on Odroid XU
+    - ARM: dts: exynos: fix USB 3.0 VBUS control and over-current pins on
+      Exynos5410
+    - ARM: dts: exynos: fix USB 3.0 pins supply being turned off on Odroid XU
+    - coresight: tmc-etf: Fix NULL ptr dereference in tmc_enable_etf_sink_perf()
+    - coresight: tmc-etr: Check if page is valid before dma_map_page()
+    - coresight: tmc-etr: Fix barrier packet insertion for perf buffer
+    - coresight: etb10: Fix possible NULL ptr dereference in etb_enable_perf()
+    - scsi: megaraid_sas: Check user-provided offsets
+    - HID: i2c-hid: add Vero K147 to descriptor override
+    - serial_core: Check for port state when tty is in error state
+    - Bluetooth: Fix slab-out-of-bounds read in hci_le_direct_adv_report_evt()
+    - quota: Sanity-check quota file headers on load
+    - media: msi2500: assign SPI bus number dynamically
+    - crypto: af_alg - avoid undefined behavior accessing salg_name
+    - md: fix a warning caused by a race between concurrent md_ioctl()s
+    - drm/gma500: fix double free of gma_connector
+    - drm/aspeed: Fix Kconfig warning & subsequent build errors
+    - drm/mcde: Fix handling of platform_get_irq() error
+    - drm/tve200: Fix handling of platform_get_irq() error
+    - arm64: dts: renesas: hihope-rzg2-ex: Drop rxc-skew-ps from ethernet-phy node
+    - arm64: dts: renesas: cat875: Remove rxc-skew-ps from ethernet-phy node
+    - soc: renesas: rmobile-sysc: Fix some leaks in rmobile_init_pm_domains()
+    - soc: mediatek: Check if power domains can be powered on at boot time
+    - soc: qcom: geni: More properly switch to DMA mode
+    - Revert "i2c: i2c-qcom-geni: Fix DMA transfer race"
+    - RDMA/bnxt_re: Set queue pair state when being queried
+    - rtc: pcf2127: fix pcf2127_nvmem_read/write() returns
+    - selinux: fix error initialization in inode_doinit_with_dentry()
+    - ARM: dts: aspeed: s2600wf: Fix VGA memory region location
+    - RDMA/rxe: Compute PSN windows correctly
+    - x86/mm/ident_map: Check for errors from ident_pud_init()
+    - ARM: p2v: fix handling of LPAE translation in BE mode
+    - x86/apic: Fix x2apic enablement without interrupt remapping
+    - sched/deadline: Fix sched_dl_global_validate()
+    - sched: Reenable interrupts in do_sched_yield()
+    - drm/amdgpu: fix incorrect enum type
+    - crypto: talitos - Endianess in current_desc_hdr()
+    - crypto: talitos - Fix return type of current_desc_hdr()
+    - crypto: inside-secure - Fix sizeof() mismatch
+    - ASoC: sun4i-i2s: Fix lrck_period computation for I2S justified mode
+    - ARM: dts: aspeed: tiogapass: Remove vuart
+    - drm/amdgpu: fix build_coefficients() argument
+    - powerpc/64: Set up a kernel stack for secondaries before cpu_restore()
+    - spi: img-spfi: fix reference leak in img_spfi_resume
+    - f2fs: call f2fs_get_meta_page_retry for nat page
+    - drm/msm/dsi_pll_10nm: restore VCO rate during restore_state
+    - spi: spi-mem: fix reference leak in spi_mem_access_start
+    - ASoC: pcm: DRAIN support reactivation
+    - selinux: fix inode_doinit_with_dentry() LABEL_INVALID error handling
+    - spi: stm32: fix reference leak in stm32_spi_resume
+    - brcmfmac: Fix memory leak for unpaired brcmf_{alloc/free}
+    - arm64: dts: exynos: Include common syscon restart/poweroff for Exynos7
+    - arm64: dts: exynos: Correct psci compatible used on Exynos7
+    - Bluetooth: Fix null pointer dereference in hci_event_packet()
+    - Bluetooth: hci_h5: fix memory leak in h5_close
+    - spi: spi-ti-qspi: fix reference leak in ti_qspi_setup
+    - spi: mt7621: fix missing clk_disable_unprepare() on error in
+      mt7621_spi_probe
+    - spi: tegra20-slink: fix reference leak in slink ops of tegra20
+    - spi: tegra20-sflash: fix reference leak in tegra_sflash_resume
+    - spi: tegra114: fix reference leak in tegra spi ops
+    - spi: bcm63xx-hsspi: fix missing clk_disable_unprepare() on error in
+      bcm63xx_hsspi_resume
+    - mwifiex: fix mwifiex_shutdown_sw() causing sw reset failure
+    - selftest/bpf: Add missed ip6ip6 test back
+    - ASoC: wm8998: Fix PM disable depth imbalance on error
+    - spi: sprd: fix reference leak in sprd_spi_remove
+    - ASoC: arizona: Fix a wrong free in wm8997_probe
+    - RDMa/mthca: Work around -Wenum-conversion warning
+    - MIPS: BCM47XX: fix kconfig dependency bug for BCM47XX_BCMA
+    - crypto: qat - fix status check in qat_hal_put_rel_rd_xfer()
+    - staging: greybus: codecs: Fix reference counter leak in error handling
+    - staging: gasket: interrupt: fix the missed eventfd_ctx_put() in
+      gasket_interrupt.c
+    - media: tm6000: Fix sizeof() mismatches
+    - media: mtk-vcodec: add missing put_device() call in mtk_vcodec_init_dec_pm()
+    - media: mtk-vcodec: add missing put_device() call in
+      mtk_vcodec_release_dec_pm()
+    - media: mtk-vcodec: add missing put_device() call in mtk_vcodec_init_enc_pm()
+    - media: v4l2-fwnode: Return -EINVAL for invalid bus-type
+    - ASoC: meson: fix COMPILE_TEST error
+    - scsi: core: Fix VPD LUN ID designator priorities
+    - media: solo6x10: fix missing snd_card_free in error handling case
+    - video: fbdev: atmel_lcdfb: fix return error code in atmel_lcdfb_of_init()
+    - drm/omap: dmm_tiler: fix return error code in omap_dmm_probe()
+    - Input: ads7846 - fix race that causes missing releases
+    - Input: ads7846 - fix integer overflow on Rt calculation
+    - Input: ads7846 - fix unaligned access on 7845
+    - usb/max3421: fix return error code in max3421_probe()
+    - spi: mxs: fix reference leak in mxs_spi_probe
+    - selftests/bpf: Fix broken riscv build
+    - powerpc: Avoid broken GCC __attribute__((optimize))
+    - powerpc/feature: Fix CPU_FTRS_ALWAYS by removing CPU_FTRS_GENERIC_32
+    - EDAC/mce_amd: Use struct cpuinfo_x86.cpu_die_id for AMD NodeId
+    - crypto: crypto4xx - Replace bitwise OR with logical OR in crypto4xx_build_pd
+    - crypto: omap-aes - Fix PM disable depth imbalance in omap_aes_probe
+    - spi: fix resource leak for drivers without .remove callback
+    - soc: ti: knav_qmss: fix reference leak in knav_queue_probe
+    - soc: ti: Fix reference imbalance in knav_dma_probe
+    - drivers: soc: ti: knav_qmss_queue: Fix error return code in knav_queue_probe
+    - Input: omap4-keypad - fix runtime PM error handling
+    - clk: meson: Kconfig: fix dependency for G12A
+    - RDMA/cxgb4: Validate the number of CQEs
+    - memstick: fix a double-free bug in memstick_check
+    - ARM: dts: at91: sama5d4_xplained: add pincontrol for USB Host
+    - ARM: dts: at91: sama5d3_xplained: add pincontrol for USB Host
+    - mmc: pxamci: Fix error return code in pxamci_probe
+    - orinoco: Move context allocation after processing the skb
+    - qtnfmac: fix error return code in qtnf_pcie_probe()
+    - rsi: fix error return code in rsi_reset_card()
+    - cw1200: fix missing destroy_workqueue() on error in cw1200_init_common
+    - dmaengine: mv_xor_v2: Fix error return code in mv_xor_v2_probe()
+    - arm64: tegra: Fix DT binding for IO High Voltage entry
+    - media: siano: fix memory leak of debugfs members in smsdvb_hotplug
+    - platform/x86: mlx-platform: Remove PSU EEPROM from default platform
+      configuration
+    - platform/x86: mlx-platform: Remove PSU EEPROM from MSN274x platform
+      configuration
+    - samples: bpf: Fix lwt_len_hist reusing previous BPF map
+    - media: imx214: Fix stop streaming
+    - mips: cdmm: fix use-after-free in mips_cdmm_bus_discover
+    - media: max2175: fix max2175_set_csm_mode() error code
+    - slimbus: qcom-ngd-ctrl: Avoid sending power requests without QMI
+    - HSI: omap_ssi: Don't jump to free ID in ssi_add_controller()
+    - ARM: dts: Remove non-existent i2c1 from 98dx3236
+    - arm64: dts: armada-3720-turris-mox: update ethernet-phy handle name
+    - arm64: dts: rockchip: Set dr_mode to "host" for OTG on rk3328-roc-cc
+    - power: supply: axp288_charger: Fix HP Pavilion x2 10 DMI matching
+    - power: supply: bq24190_charger: fix reference leak
+    - genirq/irqdomain: Don't try to free an interrupt that has no mapping
+    - arm64: dts: ls1028a: fix ENETC PTP clock input
+    - arm64: dts: qcom: c630: Polish i2c-hid devices
+    - PCI: Bounds-check command-line resource alignment requests
+    - PCI: Fix overflow in command-line resource alignment requests
+    - PCI: iproc: Fix out-of-bound array accesses
+    - arm64: dts: meson: fix spi-max-frequency on Khadas VIM2
+    - arm64: dts: meson-sm1: fix typo in opp table
+    - soc: amlogic: canvas: add missing put_device() call in meson_canvas_get()
+    - ARM: dts: at91: at91sam9rl: fix ADC triggers
+    - platform/x86: dell-smbios-base: Fix error return code in dell_smbios_init
+    - ath10k: Fix the parsing error in service available event
+    - ath10k: Fix an error handling path
+    - ath10k: Release some resources in an error handling path
+    - SUNRPC: rpc_wake_up() should wake up tasks in the correct order
+    - NFSv4.2: condition READDIR's mask for security label based on LSM state
+    - SUNRPC: xprt_load_transport() needs to support the netid "rdma6"
+    - NFSv4: Fix the alignment of page data in the getdeviceinfo reply
+    - net: sunrpc: Fix 'snprintf' return value check in 'do_xprt_debugfs'
+    - lockd: don't use interval-based rebinding over TCP
+    - NFS: switch nfsiod to be an UNBOUND workqueue.
+    - selftests/seccomp: Update kernel config
+    - vfio-pci: Use io_remap_pfn_range() for PCI IO memory
+    - hwmon: (ina3221) Fix PM usage counter unbalance in ina3221_write_enable
+    - media: saa7146: fix array overflow in vidioc_s_audio()
+    - powerpc/perf: Fix crash with is_sier_available when pmu is not set
+    - powerpc/64: Fix an EMIT_BUG_ENTRY in head_64.S
+    - clocksource/drivers/orion: Add missing clk_disable_unprepare() on error path
+    - clocksource/drivers/cadence_ttc: Fix memory leak in ttc_setup_clockevent()
+    - iio: hrtimer-trigger: Mark hrtimer to expire in hard interrupt context
+    - ARM: dts: at91: sama5d2: map securam as device
+    - bpf: Fix bpf_put_raw_tracepoint()'s use of __module_address()
+    - pinctrl: falcon: add missing put_device() call in pinctrl_falcon_probe()
+    - arm64: dts: rockchip: Fix UART pull-ups on rk3328
+    - memstick: r592: Fix error return in r592_probe()
+    - MIPS: Don't round up kernel sections size for memblock_add()
+    - net/mlx5: Properly convey driver version to firmware
+    - ASoC: jz4740-i2s: add missed checks for clk_get()
+    - dm ioctl: fix error return code in target_message
+    - phy: renesas: rcar-gen3-usb2: disable runtime pm in case of failure
+    - clocksource/drivers/arm_arch_timer: Use stable count reader in erratum sne
+    - clocksource/drivers/arm_arch_timer: Correct fault programming of
+      CNTKCTL_EL1.EVNTI
+    - cpufreq: ap806: Add missing MODULE_DEVICE_TABLE
+    - cpufreq: highbank: Add missing MODULE_DEVICE_TABLE
+    - cpufreq: mediatek: Add missing MODULE_DEVICE_TABLE
+    - cpufreq: qcom: Add missing MODULE_DEVICE_TABLE
+    - cpufreq: st: Add missing MODULE_DEVICE_TABLE
+    - cpufreq: sun50i: Add missing MODULE_DEVICE_TABLE
+    - cpufreq: loongson1: Add missing MODULE_ALIAS
+    - cpufreq: scpi: Add missing MODULE_ALIAS
+    - Bluetooth: btusb: Add the missed release_firmware() in
+      btusb_mtk_setup_firmware()
+    - Bluetooth: btmtksdio: Add the missed release_firmware() in
+      mtk_setup_firmware()
+    - arm64: dts: meson: fix PHY deassert timing requirements
+    - ARM: dts: meson: fix PHY deassert timing requirements
+    - arm64: dts: meson: g12a: x96-max: fix PHY deassert timing requirements
+    - scsi: qedi: Fix missing destroy_workqueue() on error in __qedi_probe
+    - scsi: pm80xx: Fix error return in pm8001_pci_probe()
+    - seq_buf: Avoid type mismatch for seq_buf_init
+    - scsi: fnic: Fix error return code in fnic_probe()
+    - platform/x86: mlx-platform: Fix item counter assignment for MSN2700, MSN24xx
+      systems
+    - powerpc/pseries/hibernation: drop pseries_suspend_begin() from suspend ops
+    - powerpc/pseries/hibernation: remove redundant cacheinfo update
+    - drm/mediatek: avoid dereferencing a null hdmi_phy on an error message
+    - ASoC: amd: change clk_get() to devm_clk_get() and add missed checks
+    - powerpc/mm: sanity_check_fault() should work for all, not only BOOK3S
+    - usb: ehci-omap: Fix PM disable depth umbalance in ehci_hcd_omap_probe
+    - usb: oxu210hp-hcd: Fix memory leak in oxu_create
+    - speakup: fix uninitialized flush_lock
+    - nfsd: Fix message level for normal termination
+    - nfs_common: need lock during iterate through the list
+    - x86/kprobes: Restore BTF if the single-stepping is cancelled
+    - platform/chrome: cros_ec_spi: Don't overwrite spi::mode
+    - bus: fsl-mc: fix error return code in fsl_mc_object_allocate()
+    - s390/cio: fix use-after-free in ccw_device_destroy_console
+    - iwlwifi: mvm: hook up missing RX handlers
+    - erofs: avoid using generic_block_bmap
+    - can: m_can: m_can_config_endisable(): remove double clearing of clock stop
+      request bit
+    - RDMA/core: Do not indicate device ready when device enablement fails
+    - remoteproc: q6v5-mss: fix error handling in q6v5_pds_enable
+    - remoteproc: qcom: fix reference leak in adsp_start
+    - remoteproc: qcom: Fix potential NULL dereference in adsp_init_mmio()
+    - clk: tegra: Fix duplicated SE clock entry
+    - mtd: rawnand: gpmi: fix reference count leak in gpmi ops
+    - mtd: rawnand: meson: Fix a resource leak in init
+    - mtd: rawnand: gpmi: Fix the random DMA timeout issue
+    - extcon: max77693: Fix modalias string
+    - crypto: atmel-i2c - select CONFIG_BITREVERSE
+    - mac80211: don't set set TDLS STA bandwidth wider than possible
+    - ASoC: wm_adsp: remove "ctl" from list on error in wm_adsp_create_control()
+    - irqchip/alpine-msi: Fix freeing of interrupts on allocation error path
+    - watchdog: armada_37xx: Add missing dependency on HAS_IOMEM
+    - watchdog: sirfsoc: Add missing dependency on HAS_IOMEM
+    - watchdog: sprd: remove watchdog disable from resume fail path
+    - watchdog: sprd: check busy bit before new loading rather than after that
+    - watchdog: Fix potential dereferencing of null pointer
+    - ubifs: Fix error return code in ubifs_init_authentication()
+    - um: Monitor error events in IRQ controller
+    - um: tty: Fix handling of close in tty lines
+    - um: chan_xterm: Fix fd leak
+    - sunrpc: fix xs_read_xdr_buf for partial pages receive
+    - RDMA/cma: Don't overwrite sgid_attr after device is released
+    - nfc: s3fwrn5: Release the nfc firmware
+    - powerpc/ps3: use dma_mapping_error()
+    - sparc: fix handling of page table constructor failure
+    - mm: don't wake kswapd prematurely when watermark boosting is disabled
+    - checkpatch: fix unescaped left brace
+    - lan743x: fix rx_napi_poll/interrupt ping-pong
+    - net: bcmgenet: Fix a resource leak in an error handling path in the probe
+      functin
+    - net: allwinner: Fix some resources leak in the error handling path of the
+      probe and in the remove function
+    - net: korina: fix return value
+    - libnvdimm/label: Return -ENXIO for no slot in __blk_label_update
+    - watchdog: qcom: Avoid context switch in restart handler
+    - watchdog: coh901327: add COMMON_CLK dependency
+    - clk: ti: Fix memleak in ti_fapll_synth_setup
+    - pwm: zx: Add missing cleanup in error path
+    - pwm: lp3943: Dynamically allocate PWM chip base
+    - perf record: Fix memory leak when using '--user-regs=?' to list registers
+    - qlcnic: Fix error code in probe
+    - virtio_ring: Cut and paste bugs in vring_create_virtqueue_packed()
+    - virtio_net: Fix error code in probe()
+    - virtio_ring: Fix two use after free bugs
+    - clk: at91: sam9x60: remove atmel,osc-bypass support
+    - clk: s2mps11: Fix a resource leak in error handling paths in the probe
+      function
+    - clk: sunxi-ng: Make sure divider tables have sentinel
+    - kconfig: fix return value of do_error_if()
+    - perf probe: Fix memory leak when synthesizing SDT probes
+    - ARM: sunxi: Add machine match for the Allwinner V3 SoC
+    - cfg80211: initialize rekey_data
+    - fix namespaced fscaps when !CONFIG_SECURITY
+    - lwt: Disable BH too in run_lwt_bpf()
+    - drm/amd/display: Prevent bandwidth overflow
+    - drm/amdkfd: Fix leak in dmabuf import
+    - Input: cros_ec_keyb - send 'scancodes' in addition to key events
+    - initramfs: fix clang build failure
+    - Input: goodix - add upside-down quirk for Teclast X98 Pro tablet
+    - vfio/pci/nvlink2: Do not attempt NPU2 setup on POWER8NVL NPU
+    - media: gspca: Fix memory leak in probe
+    - media: sunxi-cir: ensure IR is handled when it is continuous
+    - media: netup_unidvb: Don't leak SPI master in probe error path
+    - media: ipu3-cio2: Remove traces of returned buffers
+    - media: ipu3-cio2: Return actual subdev format
+    - media: ipu3-cio2: Serialise access to pad format
+    - media: ipu3-cio2: Validate mbus format in setting subdev format
+    - media: ipu3-cio2: Make the field on subdev format V4L2_FIELD_NONE
+    - Input: cyapa_gen6 - fix out-of-bounds stack access
+    - ALSA: hda/ca0132 - Change Input Source enum strings.
+    - Revert "ACPI / resources: Use AE_CTRL_TERMINATE to terminate resources
+      walks"
+    - ACPI: PNP: compare the string length in the matching_id()
+    - ALSA: hda: Fix regressions on clear and reconfig sysfs
+    - ALSA: hda/ca0132 - Fix AE-5 rear headphone pincfg.
+    - ALSA: hda/realtek: make bass spk volume adjustable on a yoga laptop
+    - ALSA: hda/realtek - Enable headset mic of ASUS X430UN with ALC256
+    - ALSA: hda/realtek - Enable headset mic of ASUS Q524UQK with ALC255
+    - ALSA: hda/realtek - Add supported for more Lenovo ALC285 Headset Button
+    - ALSA: pcm: oss: Fix a few more UBSAN fixes
+    - ALSA/hda: apply jack fixup for the Acer Veriton N4640G/N6640G/N2510G
+    - ALSA: hda/realtek: Add quirk for MSI-GP73
+    - ALSA: hda/realtek: Apply jack fixup for Quanta NL3
+    - ALSA: usb-audio: Add VID to support native DSD reproduction on FiiO devices
+    - ALSA: usb-audio: Disable sample read check if firmware doesn't give back
+    - ALSA: core: memalloc: add page alignment for iram
+    - s390/smp: perform initial CPU reset also for SMT siblings
+    - s390/kexec_file: fix diag308 subcode when loading crash kernel
+    - s390/dasd: fix hanging device offline processing
+    - s390/dasd: prevent inconsistent LCU device data
+    - s390/dasd: fix list corruption of pavgroup group list
+    - s390/dasd: fix list corruption of lcu list
+    - binder: add flag to clear buffer on txn complete
+    - ASoC: cx2072x: Fix doubly definitions of Playback and Capture streams
+    - staging: comedi: mf6x4: Fix AI end-of-conversion detection
+    - perf/x86/intel: Add event constraint for CYCLE_ACTIVITY.STALLS_MEM_ANY
+    - perf/x86/intel: Fix rtm_abort_event encoding on Ice Lake
+    - powerpc/perf: Exclude kernel samples while counting events in user space.
+    - crypto: ecdh - avoid unaligned accesses in ecdh_set_secret()
+    - crypto: arm/aes-ce - work around Cortex-A57/A72 silion errata
+    - EDAC/i10nm: Use readl() to access MMIO registers
+    - EDAC/amd64: Fix PCI component registration
+    - cpuset: fix race between hotplug work and later CPU offline
+    - USB: serial: mos7720: fix parallel-port state restore
+    - USB: serial: digi_acceleport: fix write-wakeup deadlocks
+    - USB: serial: keyspan_pda: fix dropped unthrottle interrupts
+    - USB: serial: keyspan_pda: fix write deadlock
+    - USB: serial: keyspan_pda: fix stalled writes
+    - USB: serial: keyspan_pda: fix write-wakeup use-after-free
+    - USB: serial: keyspan_pda: fix tx-unthrottle use-after-free
+    - USB: serial: keyspan_pda: fix write unthrottling
+    - btrfs: do not shorten unpin len for caching block groups
+    - ext4: fix a memory leak of ext4_free_data
+    - ext4: fix deadlock with fs freezing and EA inodes
+    - KVM: arm64: Introduce handling of AArch32 TTBCR2 traps
+    - ARM: dts: pandaboard: fix pinmux for gpio user button of Pandaboard ES
+    - ARM: dts: at91: sama5d2: fix CAN message ram offset and size
+    - xprtrdma: Fix XDRBUF_SPARSE_PAGES support
+    - powerpc: Fix incorrect stw{, ux, u, x} instructions in __set_pte_at
+    - powerpc/rtas: Fix typo of ibm,open-errinjct in RTAS filter
+    - powerpc/feature: Add CPU_FTR_NOEXECUTE to G2_LE
+    - powerpc/xmon: Change printk() to pr_cont()
+    - powerpc/8xx: Fix early debug when SMC1 is relocated
+    - powerpc/mm: Fix verification of MMU_FTR_TYPE_44x
+    - powerpc/powernv/npu: Do not attempt NPU2 setup on POWER8NVL NPU
+    - powerpc/powernv/memtrace: Don't leak kernel memory to user space
+    - powerpc/powernv/memtrace: Fix crashing the kernel when enabling concurrently
+    - ima: Don't modify file descriptor mode on the fly
+    - um: Remove use of asprinf in umid.c
+    - ceph: fix race in concurrent __ceph_remove_cap invocations
+    - SMB3: avoid confusing warning message on mount to Azure
+    - ubifs: wbuf: Don't leak kernel memory to flash
+    - jffs2: Fix GC exit abnormally
+    - jffs2: Fix ignoring mounting options problem during remounting
+    - jfs: Fix array index bounds check in dbAdjTree
+    - platform/x86: mlx-platform: remove an unused variable
+    - drm/amd/display: Fix memory leaks in S3 resume
+    - drm/dp_aux_dev: check aux_dev before use in drm_dp_aux_dev_get_by_minor()
+    - drm/i915: Fix mismatch between misplaced vma check and vma insert
+    - spi: pxa2xx: Fix use-after-free on unbind
+    - spi: spi-sh: Fix use-after-free on unbind
+    - spi: atmel-quadspi: Fix use-after-free on unbind
+    - spi: davinci: Fix use-after-free on unbind
+    - spi: fsl: fix use of spisel_boot signal on MPC8309
+    - spi: gpio: Don't leak SPI master in probe error path
+    - spi: mxic: Don't leak SPI master in probe error path
+    - spi: pic32: Don't leak DMA channels in probe error path
+    - spi: rb4xx: Don't leak SPI master in probe error path
+    - spi: sc18is602: Don't leak SPI master in probe error path
+    - spi: st-ssc4: Fix unbalanced pm_runtime_disable() in probe error path
+    - spi: synquacer: Disable clock in probe error path
+    - spi: mt7621: Disable clock in probe error path
+    - spi: mt7621: Don't leak SPI master in probe error path
+    - spi: atmel-quadspi: Disable clock in probe error path
+    - spi: atmel-quadspi: Fix AHB memory accesses
+    - soc: qcom: smp2p: Safely acquire spinlock without IRQs
+    - mtd: spinand: Fix OOB read
+    - mtd: parser: cmdline: Fix parsing of part-names with colons
+    - mtd: rawnand: qcom: Fix DMA sync on FLASH_STATUS register read
+    - mtd: rawnand: meson: fix meson_nfc_dma_buffer_release() arguments
+    - scsi: qla2xxx: Fix crash during driver load on big endian machines
+    - scsi: lpfc: Fix invalid sleeping context in lpfc_sli4_nvmet_alloc()
+    - scsi: lpfc: Re-fix use after free in lpfc_rq_buf_free()
+    - iio: buffer: Fix demux update
+    - iio: adc: rockchip_saradc: fix missing clk_disable_unprepare() on error in
+      rockchip_saradc_resume
+    - iio:light:rpr0521: Fix timestamp alignment and prevent data leak.
+    - iio:light:st_uvis25: Fix timestamp alignment and prevent data leak.
+    - iio:magnetometer:mag3110: Fix alignment and data leak issues.
+    - iio:pressure:mpl3115: Force alignment of buffer
+    - iio:imu:bmi160: Fix too large a buffer.
+    - iio:adc:ti-ads124s08: Fix buffer being too long.
+    - iio:adc:ti-ads124s08: Fix alignment and data leak issues.
+    - md/cluster: block reshape with remote resync job
+    - md/cluster: fix deadlock when node is doing resync job
+    - pinctrl: sunxi: Always call chained_irq_{enter, exit} in
+      sunxi_pinctrl_irq_handler
+    - clk: ingenic: Fix divider calculation with div tables
+    - clk: mvebu: a3700: fix the XTAL MODE pin to MPP1_9
+    - clk: tegra: Do not return 0 on failure
+    - device-dax/core: Fix memory leak when rmmod dax.ko
+    - dma-buf/dma-resv: Respect num_fences when initializing the shared fence
+      list.
+    - xen-blkback: set ring->xenblkd to NULL after kthread_stop()
+    - xen/xenbus: Allow watches discard events before queueing
+    - xen/xenbus: Add 'will_handle' callback support in xenbus_watch_path()
+    - xen/xenbus/xen_bus_type: Support will_handle watch callback
+    - xen/xenbus: Count pending messages for each watch
+    - xenbus/xenbus_backend: Disallow pending watch messages
+    - libnvdimm/namespace: Fix reaping of invalidated block-window-namespace
+      labels
+    - platform/x86: intel-vbtn: Allow switch events on Acer Switch Alpha 12
+    - PCI: Fix pci_slot_release() NULL pointer dereference
+    - regulator: axp20x: Fix DLDO2 voltage control register mask for AXP22x
+    - rtc: ep93xx: Fix NULL pointer dereference in ep93xx_rtc_read_time
+    - Revert: "ring-buffer: Remove HAVE_64BIT_ALIGNED_ACCESS"
+    - x86/CPU/AMD: Save AMD NodeId as cpu_die_id
+    - Linux 5.4.86
+  * Focal update: v5.4.85 upstream stable release (LP: #1910817)
+    - ptrace: Prevent kernel-infoleak in ptrace_get_syscall_info()
+    - ipv4: fix error return code in rtm_to_fib_config()
+    - mac80211: mesh: fix mesh_pathtbl_init() error path
+    - net: bridge: vlan: fix error return code in __vlan_add()
+    - vrf: packets with lladdr src needs dst at input with orig_iif when needs
+      strict
+    - net: hns3: remove a misused pragma packed
+    - udp: fix the proto value passed to ip_protocol_deliver_rcu for the segments
+    - enetc: Fix reporting of h/w packet counters
+    - bridge: Fix a deadlock when enabling multicast snooping
+    - net: stmmac: free tx skb buffer in stmmac_resume()
+    - tcp: select sane initial rcvq_space.space for big MSS
+    - tcp: fix cwnd-limited bug for TSO deferral where we send nothing
+    - net/mlx4_en: Avoid scheduling restart task if it is already running
+    - lan743x: fix for potential NULL pointer dereference with bare card
+    - net/mlx4_en: Handle TX error CQE
+    - net: ll_temac: Fix potential NULL dereference in temac_probe()
+    - net: stmmac: dwmac-meson8b: fix mask definition of the m250_sel mux
+    - net: stmmac: delete the eee_ctrl_timer after napi disabled
+    - ktest.pl: If size of log is too big to email, email error message
+    - USB: dummy-hcd: Fix uninitialized array use in init()
+    - USB: add RESET_RESUME quirk for Snapscan 1212
+    - ALSA: usb-audio: Fix potential out-of-bounds shift
+    - ALSA: usb-audio: Fix control 'access overflow' errors from chmap
+    - xhci: Give USB2 ports time to enter U3 in bus suspend
+    - xhci-pci: Allow host runtime PM as default for Intel Alpine Ridge LP
+    - USB: UAS: introduce a quirk to set no_write_same
+    - USB: sisusbvga: Make console support depend on BROKEN
+    - [Config] updateconfigs for USB_SISUSBVGA_CON
+    - ALSA: pcm: oss: Fix potential out-of-bounds shift
+    - serial: 8250_omap: Avoid FIFO corruption caused by MDR1 access
+    - KVM: mmu: Fix SPTE encoding of MMIO generation upper half
+    - membarrier: Explicitly sync remote cores when SYNC_CORE is requested
+    - x86/resctrl: Remove unused struct mbm_state::chunks_bw
+    - x86/resctrl: Fix incorrect local bandwidth when mba_sc is enabled
+    - Linux 5.4.85
+  * Focal update: v5.4.84 upstream stable release (LP: #1910816)
+    - Kbuild: do not emit debug info for assembly with LLVM_IAS=1
+    - x86/lib: Change .weak to SYM_FUNC_START_WEAK for arch/x86/lib/mem*_64.S
+    - iwlwifi: pcie: limit memory read spin time
+    - arm64: dts: rockchip: Assign a fixed index to mmc devices on rk3399 boards.
+    - iwlwifi: pcie: set LTR to avoid completion timeout
+    - iwlwifi: mvm: fix kernel panic in case of assert during CSA
+    - powerpc: Drop -me200 addition to build flags
+    - arm64: dts: broadcom: clear the warnings caused by empty dma-ranges
+    - ARC: stack unwinding: don't assume non-current task is sleeping
+    - scsi: ufs: Make sure clk scaling happens only when HBA is runtime ACTIVE
+    - interconnect: qcom: qcs404: Remove GPU and display RPM IDs
+    - ibmvnic: skip tx timeout reset while in resetting
+    - irqchip/gic-v3-its: Unconditionally save/restore the ITS state on suspend
+    - spi: spi-nxp-fspi: fix fspi panic by unexpected interrupts
+    - soc: fsl: dpio: Get the cpumask through cpumask_of(cpu)
+    - arm64: tegra: Disable the ACONNECT for Jetson TX2
+    - platform/x86: thinkpad_acpi: Do not report SW_TABLET_MODE on Yoga 11e
+    - platform/x86: thinkpad_acpi: Add BAT1 is primary battery quirk for Thinkpad
+      Yoga 11e 4th gen
+    - platform/x86: acer-wmi: add automatic keyboard background light toggle key
+      as KEY_LIGHTS_TOGGLE
+    - platform/x86: intel-vbtn: Support for tablet mode on HP Pavilion 13 x360 PC
+    - platform/x86: touchscreen_dmi: Add info for the Irbis TW118 tablet
+    - can: m_can: m_can_dev_setup(): add support for bosch mcan version 3.3.0
+    - ktest.pl: Fix incorrect reboot for grub2bls
+    - Input: cm109 - do not stomp on control URB
+    - Input: i8042 - add Acer laptops to the i8042 reset list
+    - mmc: block: Fixup condition for CMD13 polling for RPMB requests
+    - drm/i915/display/dp: Compute the correct slice count for VDSC on DP
+    - kbuild: avoid static_assert for genksyms
+    - proc: use untagged_addr() for pagemap_read addresses
+    - scsi: be2iscsi: Revert "Fix a theoretical leak in beiscsi_create_eqs()"
+    - x86/mm/mem_encrypt: Fix definition of PMD_FLAGS_DEC_WP
+    - x86/membarrier: Get rid of a dubious optimization
+    - x86/apic/vector: Fix ordering in vector assignment
+    - mm/zsmalloc.c: drop ZSMALLOC_PGTABLE_MAPPING
+    - [Config] updateconfigs for PGTABLE_MAPPING
+    - compiler.h: fix barrier_data() on clang
+    - Linux 5.4.84
+  * MSFT Touchpad not working on Lenovo Legion-5 15ARH05 (LP: #1887190) // Focal
+    update: v5.4.84 upstream stable release (LP: #1910816)
+    - pinctrl: amd: remove debounce filter setting in IRQ type setting
+  * Focal update: v5.4.83 upstream stable release (LP: #1910784)
+    - pinctrl: baytrail: Replace WARN with dev_info_once when setting direct-irq
+      pin to output
+    - pinctrl: baytrail: Fix pin being driven low for a while on gpiod_get(...,
+      GPIOD_OUT_HIGH)
+    - usb: gadget: f_fs: Use local copy of descriptors for userspace copy
+    - USB: serial: kl5kusb105: fix memleak on open
+    - USB: serial: ch341: add new Product ID for CH341A
+    - USB: serial: ch341: sort device-id entries
+    - USB: serial: option: add Fibocom NL668 variants
+    - USB: serial: option: add support for Thales Cinterion EXS82
+    - USB: serial: option: fix Quectel BG96 matching
+    - tty: Fix ->pgrp locking in tiocspgrp()
+    - tty: Fix ->session locking
+    - ALSA: hda/realtek: Fix bass speaker DAC assignment on Asus Zephyrus G14
+    - ALSA: hda/realtek: Add mute LED quirk to yet another HP x360 model
+    - ALSA: hda/realtek: Enable headset of ASUS UX482EG & B9400CEA with ALC294
+    - ALSA: hda/realtek - Add new codec supported for ALC897
+    - ALSA: hda/generic: Add option to enforce preferred_dacs pairs
+    - ftrace: Fix updating FTRACE_FL_TRAMP
+    - cifs: allow syscalls to be restarted in __smb_send_rqst()
+    - cifs: fix potential use-after-free in cifs_echo_request()
+    - i2c: imx: Don't generate STOP condition if arbitration has been lost
+    - thunderbolt: Fix use-after-free in remove_unplugged_switch()
+    - drm/i915/gt: Program mocs:63 for cache eviction on gen9
+    - scsi: mpt3sas: Fix ioctl timeout
+    - dm writecache: fix the maximum number of arguments
+    - powerpc/64s/powernv: Fix memory corruption when saving SLB entries on MCE
+    - genirq/irqdomain: Add an irq_create_mapping_affinity() function
+    - powerpc/pseries: Pass MSI affinity to irq_create_mapping()
+    - dm: fix bug with RCU locking in dm_blk_report_zones
+    - dm: remove invalid sparse __acquires and __releases annotations
+    - x86/uprobes: Do not use prefixes.nbytes when looping over prefixes.bytes
+    - coredump: fix core_pattern parse error
+    - mm: list_lru: set shrinker map bit when child nr_items is not zero
+    - mm/swapfile: do not sleep with a spin lock held
+    - speakup: Reject setting the speakup line discipline outside of speakup
+    - i2c: imx: Fix reset of I2SR_IAL flag
+    - i2c: imx: Check for I2SR_IAL after every byte
+    - spi: bcm2835: Release the DMA channel if probe fails after dma_init
+    - iommu/amd: Set DTE[IntTabLen] to represent 512 IRTEs
+    - tracing: Fix userstacktrace option for instances
+    - lib/syscall: fix syscall registers retrieval on 32-bit platforms
+    - can: af_can: can_rx_unregister(): remove WARN() statement from list
+      operation sanity check
+    - gfs2: check for empty rgrp tree in gfs2_ri_update
+    - netfilter: ipset: prevent uninit-value in hash_ip6_add
+    - tipc: fix a deadlock when flushing scheduled work
+    - ASoC: wm_adsp: fix error return code in wm_adsp_load()
+    - rtw88: debug: Fix uninitialized memory in debugfs code
+    - i2c: qup: Fix error return code in qup_i2c_bam_schedule_desc()
+    - dm writecache: remove BUG() and fail gracefully instead
+    - Input: i8042 - fix error return code in i8042_setup_aux()
+    - netfilter: nf_tables: avoid false-postive lockdep splat
+    - netfilter: nftables_offload: set address type in control dissector
+    - x86/insn-eval: Use new for_each_insn_prefix() macro to loop over prefixes
+      bytes
+    - Linux 5.4.83
+  * dep-8 ubuntu-regression-suite tests are not run for all linux-hwe-* kernels
+    (LP: #1908529)
+    - [dep-8] Allow all hwe kernels
+  * failing ftrace self tests from 5.7+ onwards (LP: #1893024)
+    - SAUCE: Revert "selftests/ftrace: check for do_sys_openat2 in user-memory
+      test"
+  * selftests: test_vxlan_under_vrf: mute unnecessary error message
+    (LP: #1908342)
+    - selftests: test_vxlan_under_vrf: mute unnecessary error message
+  * Focal update: v5.4.82 upstream stable release (LP: #1908564)
+    - devlink: Hold rtnl lock while reading netdev attributes
+    - ipv6: addrlabel: fix possible memory leak in ip6addrlbl_net_init
+    - net/af_iucv: set correct sk_protocol for child sockets
+    - net/tls: missing received data after fast remote close
+    - net/tls: Protect from calling tls_dev_del for TLS RX twice
+    - rose: Fix Null pointer dereference in rose_send_frame()
+    - sock: set sk_err to ee_errno on dequeue from errq
+    - tcp: Set INET_ECN_xmit configuration in tcp_reinit_congestion_control
+    - tun: honor IOCB_NOWAIT flag
+    - usbnet: ipheth: fix connectivity with iOS 14
+    - bonding: wait for sysfs kobject destruction before freeing struct slave
+    - staging/octeon: fix up merge error
+    - ima: extend boot_aggregate with kernel measurements
+    - sched/fair: Fix unthrottle_cfs_rq() for leaf_cfs_rq list
+    - netfilter: bridge: reset skb->pkt_type after NF_INET_POST_ROUTING traversal
+    - ipv4: Fix tos mask in inet_rtm_getroute()
+    - dt-bindings: net: correct interrupt flags in examples
+    - chelsio/chtls: fix panic during unload reload chtls
+    - ibmvnic: Ensure that SCRQ entry reads are correctly ordered
+    - ibmvnic: Fix TX completion error handling
+    - inet_ecn: Fix endianness of checksum update when setting ECT(1)
+    - net: ip6_gre: set dev->hard_header_len when using header_ops
+    - net/x25: prevent a couple of overflows
+    - cxgb3: fix error return code in t3_sge_alloc_qset()
+    - net: pasemi: fix error return code in pasemi_mac_open()
+    - vxlan: fix error return code in __vxlan_dev_create()
+    - chelsio/chtls: fix a double free in chtls_setkey()
+    - net: mvpp2: Fix error return code in mvpp2_open()
+    - net: skbuff: ensure LSE is pullable before decrementing the MPLS ttl
+    - net: openvswitch: ensure LSE is pullable before reading it
+    - net/sched: act_mpls: ensure LSE is pullable before reading it
+    - net/mlx5: DR, Proper handling of unsupported Connect-X6DX SW steering
+    - net/mlx5: Fix wrong address reclaim when command interface is down
+    - ALSA: usb-audio: US16x08: fix value count for level meters
+    - Input: xpad - support Ardwiino Controllers
+    - tracing: Remove WARN_ON in start_thread()
+    - RDMA/i40iw: Address an mmap handler exploit in i40iw
+    - Linux 5.4.82
+  * Focal update: v5.4.81 upstream stable release (LP: #1908562)
+    - spi: bcm-qspi: Fix use-after-free on unbind
+    - spi: bcm2835: Fix use-after-free on unbind
+    - ipv4: use IS_ENABLED instead of ifdef
+    - netfilter: clear skb->next in NF_HOOK_LIST()
+    - btrfs: tree-checker: add missing return after error in root_item
+    - btrfs: tree-checker: add missing returns after data_ref alignment checks
+    - btrfs: don't access possibly stale fs_info data for printing duplicate
+      device
+    - btrfs: fix lockdep splat when reading qgroup config on mount
+    - wireless: Use linux/stddef.h instead of stddef.h
+    - smb3: Call cifs reconnect from demultiplex thread
+    - smb3: Avoid Mid pending list corruption
+    - smb3: Handle error case during offload read path
+    - cifs: fix a memleak with modefromsid
+    - KVM: PPC: Book3S HV: XIVE: Fix possible oops when accessing ESB page
+    - KVM: arm64: vgic-v3: Drop the reporting of GICR_TYPER.Last for userspace
+    - KVM: x86: handle !lapic_in_kernel case in kvm_cpu_*_extint
+    - KVM: x86: Fix split-irqchip vs interrupt injection window request
+    - trace: fix potenial dangerous pointer
+    - arm64: pgtable: Fix pte_accessible()
+    - arm64: pgtable: Ensure dirty bit is preserved across pte_wrprotect()
+    - HID: uclogic: Add ID for Trust Flex Design Tablet
+    - HID: ite: Replace ABS_MISC 120/121 events with touchpad on/off keypresses
+    - HID: cypress: Support Varmilo Keyboards' media hotkeys
+    - HID: add support for Sega Saturn
+    - Input: i8042 - allow insmod to succeed on devices without an i8042
+      controller
+    - HID: hid-sensor-hub: Fix issue with devices with no report ID
+    - staging: ralink-gdma: fix kconfig dependency bug for DMA_RALINK
+    - HID: add HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE for Gamevice devices
+    - dmaengine: xilinx_dma: use readl_poll_timeout_atomic variant
+    - x86/xen: don't unbind uninitialized lock_kicker_irq
+    - HID: logitech-hidpp: Add HIDPP_CONSUMER_VENDOR_KEYS quirk for the Dinovo
+      Edge
+    - HID: Add Logitech Dinovo Edge battery quirk
+    - proc: don't allow async path resolution of /proc/self components
+    - nvme: free sq/cq dbbuf pointers when dbbuf set fails
+    - vhost scsi: fix cmd completion race
+    - dmaengine: pl330: _prep_dma_memcpy: Fix wrong burst size
+    - scsi: libiscsi: Fix NOP race condition
+    - scsi: target: iscsi: Fix cmd abort fabric stop race
+    - perf/x86: fix sysfs type mismatches
+    - xtensa: uaccess: Add missing __user to strncpy_from_user() prototype
+    - net: dsa: mv88e6xxx: Wait for EEPROM done after HW reset
+    - bus: ti-sysc: Fix bogus resetdone warning on enable for cpsw
+    - ARM: OMAP2+: Manage MPU state properly for omap_enter_idle_coupled()
+    - phy: tegra: xusb: Fix dangling pointer on probe failure
+    - iwlwifi: mvm: write queue_sync_state only for sync
+    - batman-adv: set .owner to THIS_MODULE
+    - arch: pgtable: define MAX_POSSIBLE_PHYSMEM_BITS where needed
+    - ARM: dts: dra76x: m_can: fix order of clocks
+    - scsi: ufs: Fix race between shutdown and runtime resume flow
+    - bnxt_en: fix error return code in bnxt_init_one()
+    - bnxt_en: fix error return code in bnxt_init_board()
+    - video: hyperv_fb: Fix the cache type when mapping the VRAM
+    - bnxt_en: Release PCI regions when DMA mask setup fails during probe.
+    - cxgb4: fix the panic caused by non smac rewrite
+    - s390/qeth: make af_iucv TX notification call more robust
+    - s390/qeth: fix af_iucv notification race
+    - s390/qeth: fix tear down of async TX buffers
+    - ibmvnic: fix call_netdevice_notifiers in do_reset
+    - ibmvnic: notify peers when failover and migration happen
+    - powerpc/64s: Fix allnoconfig build since uaccess flush
+    - IB/mthca: fix return value of error branch in mthca_init_cq()
+    - i40e: Fix removing driver while bare-metal VFs pass traffic
+    - nfc: s3fwrn5: use signed integer for parsing GPIO numbers
+    - net: ena: set initial DMA width to avoid intel iommu issue
+    - ibmvnic: fix NULL pointer dereference in reset_sub_crq_queues
+    - ibmvnic: fix NULL pointer dereference in ibmvic_reset_crq
+    - optee: add writeback to valid memory type
+    - arm64: tegra: Wrong AON HSP reg property size
+    - efivarfs: revert "fix memory leak in efivarfs_create()"
+    - efi: EFI_EARLYCON should depend on EFI
+    - can: gs_usb: fix endianess problem with candleLight firmware
+    - platform/x86: thinkpad_acpi: Send tablet mode switch at wakeup time
+    - platform/x86: toshiba_acpi: Fix the wrong variable assignment
+    - RDMA/hns: Fix retry_cnt and rnr_cnt when querying QP
+    - RDMA/hns: Bugfix for memory window mtpt configuration
+    - can: m_can: m_can_open(): remove IRQF_TRIGGER_FALLING from
+      request_threaded_irq()'s flags
+    - can: m_can: fix nominal bitiming tseg2 min for version >= 3.1
+    - perf stat: Use proper cpu for shadow stats
+    - perf probe: Fix to die_entrypc() returns error correctly
+    - spi: bcm2835aux: Restore err assignment in bcm2835aux_spi_probe
+    - USB: core: Change %pK for __user pointers to %px
+    - usb: gadget: f_midi: Fix memleak in f_midi_alloc
+    - USB: quirks: Add USB_QUIRK_DISCONNECT_SUSPEND quirk for Lenovo A630Z TIO
+      built-in usb-audio card
+    - usb: gadget: Fix memleak in gadgetfs_fill_super
+    - irqchip/exiu: Fix the index of fwspec for IRQ type
+    - x86/mce: Do not overwrite no_way_out if mce_end() fails
+    - x86/speculation: Fix prctl() when spectre_v2_user={seccomp,prctl},ibpb
+    - x86/resctrl: Remove superfluous kernfs_get() calls to prevent refcount leak
+    - x86/resctrl: Add necessary kernfs_put() calls to prevent refcount leak
+    - USB: core: Fix regression in Hercules audio card
+    - ASoC: Intel: Skylake: Remove superfluous chip initialization
+    - ASoC: Intel: Skylake: Select hda configuration permissively
+    - ASoC: Intel: Skylake: Enable codec wakeup during chip init
+    - ASoC: Intel: Skylake: Shield against no-NHLT configurations
+    - ASoC: Intel: Allow for ROM init retry on CNL platforms
+    - ASoC: Intel: Skylake: Await purge request ack on CNL
+    - ASoC: Intel: Multiple I/O PCM format support for pipe
+    - ASoC: Intel: Skylake: Automatic DMIC format configuration according to
+      information from NHLT
+    - Linux 5.4.81
+  * Focal update: v5.4.80 upstream stable release (LP: #1908561)
+    - ah6: fix error return code in ah6_input()
+    - atm: nicstar: Unmap DMA on send error
+    - bnxt_en: read EEPROM A2h address using page 0
+    - devlink: Add missing genlmsg_cancel() in devlink_nl_sb_port_pool_fill()
+    - Exempt multicast addresses from five-second neighbor lifetime
+    - inet_diag: Fix error path to cancel the meseage in inet_req_diag_fill()
+    - ipv6: Fix error path to cancel the meseage
+    - lan743x: fix issue causing intermittent kernel log warnings
+    - lan743x: prevent entire kernel HANG on open, for some platforms
+    - mlxsw: core: Use variable timeout for EMAD retries
+    - net: b44: fix error return code in b44_init_one()
+    - net: bridge: add missing counters to ndo_get_stats64 callback
+    - net: dsa: mv88e6xxx: Avoid VTU corruption on 6097
+    - net: ethernet: ti: cpsw: fix error return code in cpsw_probe()
+    - net: Have netpoll bring-up DSA management interface
+    - netlabel: fix our progress tracking in netlbl_unlabel_staticlist()
+    - netlabel: fix an uninitialized warning in netlbl_unlabel_staticlist()
+    - net: lantiq: Wait for the GPHY firmware to be ready
+    - net/mlx4_core: Fix init_hca fields offset
+    - net: qualcomm: rmnet: Fix incorrect receive packet handling during cleanup
+    - net/smc: fix direct access to ib_gid_addr->ndev in smc_ib_determine_gid()
+    - net/tls: fix corrupted data in recvmsg
+    - net: x25: Increase refcnt of "struct x25_neigh" in x25_rx_call_request
+    - page_frag: Recover from memory pressure
+    - qed: fix error return code in qed_iwarp_ll2_start()
+    - qlcnic: fix error return code in qlcnic_83xx_restart_hw()
+    - sctp: change to hold/put transport for proto_unreach_timer
+    - tcp: only postpone PROBE_RTT if RTT is < current min_rtt estimate
+    - net/mlx5: Add handling of port type in rule deletion
+    - net/mlx5: Disable QoS when min_rates on all VFs are zero
+    - net: usb: qmi_wwan: Set DTR quirk for MR400
+    - net/ncsi: Fix netlink registration
+    - net: ftgmac100: Fix crash when removing driver
+    - pinctrl: rockchip: enable gpio pclk for rockchip_gpio_to_irq
+    - scsi: ufs: Fix unbalanced scsi_block_reqs_cnt caused by ufshcd_hold()
+    - selftests: kvm: Fix the segment descriptor layout to match the actual layout
+    - ACPI: button: Add DMI quirk for Medion Akoya E2228T
+    - arm64: errata: Fix handling of 1418040 with late CPU onlining
+    - arm64: psci: Avoid printing in cpu_psci_cpu_die()
+    - arm64: smp: Tell RCU about CPUs that fail to come online
+    - vfs: remove lockdep bogosity in __sb_start_write
+    - gfs2: fix possible reference leak in gfs2_check_blk_type
+    - hwmon: (pwm-fan) Fix RPM calculation
+    - arm64: dts: allwinner: beelink-gs1: Enable both RGMII RX/TX delay
+    - arm64: dts: allwinner: Pine H64: Enable both RGMII RX/TX delay
+    - arm64: dts: allwinner: a64: OrangePi Win: Fix ethernet node
+    - arm64: dts: allwinner: a64: Pine64 Plus: Fix ethernet node
+    - arm64: dts: allwinner: h5: OrangePi PC2: Fix ethernet node
+    - ARM: dts: sun8i: r40: bananapi-m2-ultra: Fix ethernet node
+    - Revert "arm: sun8i: orangepi-pc-plus: Set EMAC activity LEDs to active high"
+    - ARM: dts: sun6i: a31-hummingbird: Enable RGMII RX/TX delay on Ethernet PHY
+    - ARM: dts: sun7i: cubietruck: Enable RGMII RX/TX delay on Ethernet PHY
+    - ARM: dts: sun7i: bananapi-m1-plus: Enable RGMII RX/TX delay on Ethernet PHY
+    - ARM: dts: sun8i: h3: orangepi-plus2e: Enable RGMII RX/TX delay on Ethernet
+      PHY
+    - ARM: dts: sun8i: a83t: Enable both RGMII RX/TX delay on Ethernet PHY
+    - ARM: dts: sun9i: Enable both RGMII RX/TX delay on Ethernet PHY
+    - ARM: dts: sunxi: bananapi-m2-plus: Enable RGMII RX/TX delay on Ethernet PHY
+    - arm64: dts: allwinner: a64: bananapi-m64: Enable RGMII RX/TX delay on PHY
+    - Input: adxl34x - clean up a data type in adxl34x_probe()
+    - MIPS: export has_transparent_hugepage() for modules
+    - arm64: dts: allwinner: h5: OrangePi Prime: Fix ethernet node
+    - arm64: dts imx8mn: Remove non-existent USB OTG2
+    - arm: dts: imx6qdl-udoo: fix rgmii phy-mode for ksz9031 phy
+    - swiotlb: using SIZE_MAX needs limits.h included
+    - arm64: dts: imx8mm: fix voltage for 1.6GHz CPU operating point
+    - ARM: dts: imx50-evk: Fix the chip select 1 IOMUX
+    - Input: resistive-adc-touch - fix kconfig dependency on IIO_BUFFER
+    - rfkill: Fix use-after-free in rfkill_resume()
+    - RDMA/pvrdma: Fix missing kfree() in pvrdma_register_device()
+    - [Config] updateconfigs for INFINIBAND_VIRT_DMA
+    - RMDA/sw: Don't allow drivers using dma_virt_ops on highmem configs
+    - perf lock: Don't free "lock_seq_stat" if read_count isn't zero
+    - tools, bpftool: Add missing close before bpftool net attach exit
+    - ip_tunnels: Set tunnel option flag when tunnel metadata is present
+    - can: af_can: prevent potential access of uninitialized member in can_rcv()
+    - can: af_can: prevent potential access of uninitialized member in canfd_rcv()
+    - can: dev: can_restart(): post buffer from the right context
+    - can: ti_hecc: Fix memleak in ti_hecc_probe
+    - can: mcba_usb: mcba_usb_start_xmit(): first fill skb, then pass to
+      can_put_echo_skb()
+    - can: peak_usb: fix potential integer overflow on shift of a int
+    - can: flexcan: fix failure handling of pm_runtime_get_sync()
+    - can: tcan4x5x: replace depends on REGMAP_SPI with depends on SPI
+    - can: tcan4x5x: tcan4x5x_can_probe(): add missing error checking for
+      devm_regmap_init()
+    - can: tcan4x5x: tcan4x5x_can_remove(): fix order of deregistration
+    - can: m_can: m_can_handle_state_change(): fix state change
+    - can: m_can: m_can_class_free_dev(): introduce new function
+    - can: m_can: m_can_stop(): set device to software init mode before closing
+    - ASoC: qcom: lpass-platform: Fix memory leak
+    - selftests/bpf: Fix error return code in run_getsockopt_test()
+    - MIPS: Alchemy: Fix memleak in alchemy_clk_setup_cpu
+    - drm/sun4i: dw-hdmi: fix error return code in sun8i_dw_hdmi_bind()
+    - net/mlx5: E-Switch, Fail mlx5_esw_modify_vport_rate if qos disabled
+    - bpf, sockmap: Fix partial copy_page_to_iter so progress can still be made
+    - bpf, sockmap: Ensure SO_RCVBUF memory is observed on ingress redirect
+    - can: kvaser_pciefd: Fix KCAN bittiming limits
+    - can: kvaser_usb: kvaser_usb_hydra: Fix KCAN bittiming limits
+    - iommu/vt-d: Move intel_iommu_gfx_mapped to Intel IOMMU header
+    - iommu/vt-d: Avoid panic if iommu init fails in tboot system
+    - can: flexcan: flexcan_chip_start(): fix erroneous
+      flexcan_transceiver_enable() during bus-off recovery
+    - can: m_can: process interrupt only when not runtime suspended
+    - xfs: fix the minrecs logic when dealing with inode root child blocks
+    - xfs: strengthen rmap record flags checking
+    - xfs: return corresponding errcode if xfs_initialize_perag() fail
+    - regulator: ti-abb: Fix array out of bound read access on the first
+      transition
+    - fail_function: Remove a redundant mutex unlock
+    - xfs: revert "xfs: fix rmap key and record comparison functions"
+    - bpf, sockmap: Skb verdict SK_PASS to self already checked rmem limits
+    - bpf, sockmap: On receive programs try to fast track SK_PASS ingress
+    - bpf, sockmap: Use truesize with sk_rmem_schedule()
+    - bpf, sockmap: Avoid returning unneeded EAGAIN when redirecting to self
+    - efi/x86: Free efi_pgd with free_pages()
+    - libfs: fix error cast of negative value in simple_attr_write()
+    - HID: logitech-hidpp: Add PID for MX Anywhere 2
+    - HID: logitech-dj: Handle quad/bluetooth keyboards with a builtin trackpad
+    - HID: logitech-dj: Fix Dinovo Mini when paired with a MX5x00 receiver
+    - speakup: Do not let the line discipline be used several times
+    - ALSA: firewire: Clean up a locking issue in copy_resp_to_buf()
+    - ALSA: usb-audio: Add delay quirk for all Logitech USB devices
+    - ALSA: ctl: fix error path at adding user-defined element set
+    - ALSA: mixart: Fix mutex deadlock
+    - ALSA: hda/realtek - Add supported for Lenovo ThinkPad Headset Button
+    - ALSA: hda/realtek: Add some Clove SSID in the ALC293(ALC1220)
+    - tty: serial: imx: fix potential deadlock
+    - tty: serial: imx: keep console clocks always on
+    - HID: logitech-dj: Fix an error in mse_bluetooth_descriptor
+    - efivarfs: fix memory leak in efivarfs_create()
+    - staging: rtl8723bs: Add 024c:0627 to the list of SDIO device-ids
+    - iio: light: fix kconfig dependency bug for VCNL4035
+    - ext4: fix bogus warning in ext4_update_dx_flag()
+    - iio: accel: kxcjk1013: Replace is_smo8500_device with an acpi_type enum
+    - iio: accel: kxcjk1013: Add support for KIOX010A ACPI DSM for setting tablet-
+      mode
+    - iio: adc: mediatek: fix unset field
+    - spi: lpspi: Fix use-after-free on unbind
+    - spi: Introduce device-managed SPI controller allocation
+    - spi: npcm-fiu: Don't leak SPI master in probe error path
+    - spi: bcm2835aux: Fix use-after-free on unbind
+    - regulator: pfuze100: limit pfuze-support-disable-sw to pfuze{100,200}
+    - regulator: fix memory leak with repeated set_machine_constraints()
+    - regulator: avoid resolve_supply() infinite recursion
+    - regulator: workaround self-referent regulators
+    - xtensa: fix TLBTEMP area placement
+    - xtensa: disable preemption around cache alias management calls
+    - mac80211: minstrel: remove deferred sampling code
+    - mac80211: minstrel: fix tx status processing corner case
+    - mac80211: free sta in sta_info_insert_finish() on errors
+    - s390/cpum_sf.c: fix file permission for cpum_sfb_size
+    - s390/dasd: fix null pointer dereference for ERP requests
+    - Drivers: hv: vmbus: Allow cleanup of VMBUS_CONNECT_CPU if disconnected
+    - drm/amd/display: Add missing pflip irq for dcn2.0
+    - drm/i915: Handle max_bpc==16
+    - mmc: sdhci-pci: Prefer SDR25 timing for High Speed mode for BYT-based Intel
+      controllers
+    - ptrace: Set PF_SUPERPRIV when checking capability
+    - seccomp: Set PF_SUPERPRIV when checking capability
+    - x86/microcode/intel: Check patch signature before saving microcode for early
+      loading
+    - mm: memcg/slab: fix root memcg vmstats
+    - mm/userfaultfd: do not access vma->vm_mm after calling handle_userfault()
+    - mm, page_alloc: skip ->waternark_boost for atomic order-0 allocations
+    - sched/fair: Fix overutilized update in enqueue_task_fair()
+    - Linux 5.4.80
+  * [SRU][F/G/H/U/OEM-5.6] Fix i2c report error on elan trackpoint
+    (LP: #1908335)
+    - Input: elan_i2c - add support for high resolution reports
+    - Input: elan_i2c - add new trackpoint report type 0x5F
+    - Input: elantech - fix protocol errors for some trackpoints in SMBus mode
+  * rtwpci driver blocks the system to enter PC10, stuck at PC3 (LP: #1907200)
+    - SAUCE: rtw88: 8723de: let cpu enter c10
+  * [UBUNTU 21.04] s390/pci: vfio-pci mmio being disabled erroneously
+    (LP: #1907265)
+    - s390/pci: Mark all VFs as not implementing PCI_COMMAND_MEMORY
+  * Touchpad not detected on ByteSpeed C15B laptop (LP: #1906128)
+    - Input: i8042 - add ByteSpeed touchpad to noloop table
+  * Fix reading speed and duplex sysfs on igc device (LP: #1906851)
+    - SAUCE: igc: Report speed and duplex as unknown when device is runtime
+      suspended
+  * stack trace in kernel (LP: #1903596)
+    - net: napi: remove useless stack trace
+  * Refresh ACPI wakeup power to make Thunderbolt hotplug detection work
+    (LP: #1906229)
+    - PM: ACPI: PCI: Drop acpi_pm_set_bridge_wakeup()
+    - PM: ACPI: Refresh wakeup device power configuration every time
+  * CVE-2020-27777
+    - [Config]: Set CONFIG_PPC_RTAS_FILTER
+  * Add dpcd backlight control for 0x4c83 0x4f41 (LP: #1905663)
+    - SAUCE: drm/dp: Add dpcd backlight control for 0x4c83 0x4f41
+  * Focal update: v5.4.79 upstream stable release (LP: #1907151)
+    - powerpc: Only include kup-radix.h for 64-bit Book3S
+    - MIPS: PCI: Fix MIPS build
+    - powerpc/8xx: Always fault when _PAGE_ACCESSED is not set
+    - net: lantiq: Add locking for TX DMA channel
+    - Input: sunkbd - avoid use-after-free in teardown paths
+    - mac80211: always wind down STA state
+    - can: proc: can_remove_proc(): silence remove_proc_entry warning
+    - KVM: x86: clflushopt should be treated as a no-op by emulation
+    - ACPI: GED: fix -Wformat
+    - Linux 5.4.79
+
+  [ Ubuntu: 5.4.0-65.73 ]
+
+  * focal/linux: 5.4.0-65.73 -proposed tracker (LP: #1912220)
+  * initramfs unpacking failed (LP: #1835660)
+    - SAUCE: lib/decompress_unlz4.c: correctly handle zero-padding around initrds.
+  * overlay: permission regression in 5.4.0-51.56 due to patches related to
+    CVE-2020-16120 (LP: #1900141)
+    - ovl: do not fail because of O_NOATIME
+  * Focal update: v5.4.79 upstream stable release (LP: #1907151)
+    - net/mlx5: Use async EQ setup cleanup helpers for multiple EQs
+    - net/mlx5: poll cmd EQ in case of command timeout
+    - net/mlx5: Fix a race when moving command interface to events mode
+    - net/mlx5: Add retry mechanism to the command entry index allocation
+  * Kernel 5.4.0-56 Wi-Fi does not connect (LP: #1906770)
+    - mt76: fix fix ampdu locking
+  * [Ubuntu 21.04 FEAT] mpt3sas: Request to include the patch set which supports
+    topology where zoning is enabled in expander (LP: #1899802)
+    - scsi: mpt3sas: Define hba_port structure
+    - scsi: mpt3sas: Allocate memory for hba_port objects
+    - scsi: mpt3sas: Rearrange _scsih_mark_responding_sas_device()
+    - scsi: mpt3sas: Update hba_port's sas_address & phy_mask
+    - scsi: mpt3sas: Get device objects using sas_address & portID
+    - scsi: mpt3sas: Rename transport_del_phy_from_an_existing_port()
+    - scsi: mpt3sas: Get sas_device objects using device's rphy
+    - scsi: mpt3sas: Update hba_port objects after host reset
+    - scsi: mpt3sas: Set valid PhysicalPort in SMPPassThrough
+    - scsi: mpt3sas: Handling HBA vSES device
+    - scsi: mpt3sas: Add bypass_dirty_port_flag parameter
+    - scsi: mpt3sas: Handle vSES vphy object during HBA reset
+    - scsi: mpt3sas: Add module parameter multipath_on_hba
+    - scsi: mpt3sas: Bump driver version to 35.101.00.00
+
+  [ Ubuntu: 5.4.0-64.72 ]
+
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+
+  [ Ubuntu: 5.4.0-62.70 ]
+
+  * focal/linux: 5.4.0-62.70 -proposed tracker (LP: #1911144)
+  * CVE-2020-28374
+    - SAUCE: target: fix XCOPY NAA identifier lookup
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+
+  [ Ubuntu: 5.4.0-60.67 ]
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update variants
+    - update dkms package versions
+  * CVE-2021-1052 // CVE-2021-1053
+    - [Packaging] NVIDIA -- Add the NVIDIA 460 driver
+
+  [ Ubuntu: 5.4.0-59.65 ]
+
+  * focal/linux: 5.4.0-59.65 -proposed tracker (LP: #1907604)
+  * focal: selftests/bpf build broken: test_map_init.skel.h: No such file or
+    directory (LP: #1906866)
+    - SAUCE: Revert selftests/ "bpf: Zero-fill re-used per-cpu map element"
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+  * memory is leaked when tasks are moved to net_prio (LP: #1886859)
+    - netprio_cgroup: Fix unlimited memory leak of v2 cgroups
+  * Focal update: v5.4.78 upstream stable release (LP: #1905618)
+    - drm/i915/gem: Flush coherency domains on first set-domain-ioctl
+    - time: Prevent undefined behaviour in timespec64_to_ns()
+    - nbd: don't update block size after device is started
+    - KVM: arm64: Force PTE mapping on fault resulting in a device mapping
+    - PCI: qcom: Make sure PCIe is reset before init for rev 2.1.0
+    - usb: dwc3: gadget: Continue to process pending requests
+    - usb: dwc3: gadget: Reclaim extra TRBs after request completion
+    - btrfs: tracepoints: output proper root owner for trace_find_free_extent()
+    - btrfs: sysfs: init devices outside of the chunk_mutex
+    - btrfs: reschedule when cloning lots of extents
+    - ASoC: Intel: kbl_rt5663_max98927: Fix kabylake_ssp_fixup function
+    - genirq: Let GENERIC_IRQ_IPI select IRQ_DOMAIN_HIERARCHY
+    - hv_balloon: disable warning when floor reached
+    - net: xfrm: fix a race condition during allocing spi
+    - ASoC: codecs: wcd9335: Set digital gain range correctly
+    - xfs: set xefi_discard when creating a deferred agfl free log intent item
+    - netfilter: use actual socket sk rather than skb sk when routing harder
+    - netfilter: nf_tables: missing validation from the abort path
+    - netfilter: ipset: Update byte and packet counters regardless of whether they
+      match
+    - powerpc/eeh_cache: Fix a possible debugfs deadlock
+    - perf trace: Fix segfault when trying to trace events by cgroup
+    - perf tools: Add missing swap for ino_generation
+    - ALSA: hda: prevent undefined shift in snd_hdac_ext_bus_get_link()
+    - iommu/vt-d: Fix a bug for PDP check in prq_event_thread
+    - afs: Fix warning due to unadvanced marshalling pointer
+    - can: rx-offload: don't call kfree_skb() from IRQ context
+    - can: dev: can_get_echo_skb(): prevent call to kfree_skb() in hard IRQ
+      context
+    - can: dev: __can_get_echo_skb(): fix real payload length return value for RTR
+      frames
+    - can: can_create_echo_skb(): fix echo skb generation: always use skb_clone()
+    - can: j1939: swap addr and pgn in the send example
+    - can: j1939: j1939_sk_bind(): return failure if netdev is down
+    - can: ti_hecc: ti_hecc_probe(): add missed clk_disable_unprepare() in error
+      path
+    - can: xilinx_can: handle failure cases of pm_runtime_get_sync
+    - can: peak_usb: add range checking in decode operations
+    - can: peak_usb: peak_usb_get_ts_time(): fix timestamp wrapping
+    - can: peak_canfd: pucan_handle_can_rx(): fix echo management when loopback is
+      on
+    - can: flexcan: remove FLEXCAN_QUIRK_DISABLE_MECR quirk for LS1021A
+    - can: flexcan: flexcan_remove(): disable wakeup completely
+    - xfs: flush new eof page on truncate to avoid post-eof corruption
+    - xfs: fix scrub flagging rtinherit even if there is no rt device
+    - tpm: efi: Don't create binary_bios_measurements file for an empty log
+    - random32: make prandom_u32() output unpredictable
+    - KVM: arm64: ARM_SMCCC_ARCH_WORKAROUND_1 doesn't return
+      SMCCC_RET_NOT_REQUIRED
+    - KVM: x86: don't expose MSR_IA32_UMWAIT_CONTROL unconditionally
+    - ath9k_htc: Use appropriate rs_datalen type
+    - ASoC: qcom: sdm845: set driver name correctly
+    - ASoC: cs42l51: manage mclk shutdown delay
+    - usb: dwc3: pci: add support for the Intel Alder Lake-S
+    - opp: Reduce the size of critical section in _opp_table_kref_release()
+    - usb: gadget: goku_udc: fix potential crashes in probe
+    - selftests/ftrace: check for do_sys_openat2 in user-memory test
+    - selftests: pidfd: fix compilation errors due to wait.h
+    - ALSA: hda: Separate runtime and system suspend
+    - ALSA: hda: Reinstate runtime_allow() for all hda controllers
+    - gfs2: Free rd_bits later in gfs2_clear_rgrpd to fix use-after-free
+    - gfs2: Add missing truncate_inode_pages_final for sd_aspace
+    - gfs2: check for live vs. read-only file system in gfs2_fitrim
+    - scsi: hpsa: Fix memory leak in hpsa_init_one()
+    - drm/amdgpu: perform srbm soft reset always on SDMA resume
+    - drm/amd/pm: perform SMC reset on suspend/hibernation
+    - drm/amd/pm: do not use ixFEATURE_STATUS for checking smc running
+    - mac80211: fix use of skb payload instead of header
+    - cfg80211: initialize wdev data earlier
+    - cfg80211: regulatory: Fix inconsistent format argument
+    - tracing: Fix the checking of stackidx in __ftrace_trace_stack
+    - scsi: scsi_dh_alua: Avoid crash during alua_bus_detach()
+    - scsi: mpt3sas: Fix timeouts observed while reenabling IRQ
+    - nvme: introduce nvme_sync_io_queues
+    - nvme-rdma: avoid race between time out and tear down
+    - nvme-tcp: avoid race between time out and tear down
+    - nvme-rdma: avoid repeated request completion
+    - nvme-tcp: avoid repeated request completion
+    - iommu/amd: Increase interrupt remapping table limit to 512 entries
+    - s390/smp: move rcu_cpu_starting() earlier
+    - vfio: platform: fix reference leak in vfio_platform_open
+    - vfio/pci: Bypass IGD init in case of -ENODEV
+    - i2c: mediatek: move dma reset before i2c reset
+    - amd/amdgpu: Disable VCN DPG mode for Picasso
+    - selftests: proc: fix warning: _GNU_SOURCE redefined
+    - riscv: Set text_offset correctly for M-Mode
+    - i2c: sh_mobile: implement atomic transfers
+    - tpm_tis: Disable interrupts on ThinkPad T490s
+    - spi: bcm2835: remove use of uninitialized gpio flags variable
+    - tick/common: Touch watchdog in tick_unfreeze() on all CPUs
+    - mfd: sprd: Add wakeup capability for PMIC IRQ
+    - pinctrl: intel: Set default bias in case no particular value given
+    - ARM: 9019/1: kprobes: Avoid fortify_panic() when copying optprobe template
+    - bpf: Don't rely on GCC __attribute__((optimize)) to disable GCSE
+    - pinctrl: aspeed: Fix GPI only function problem.
+    - net/mlx5: Fix deletion of duplicate rules
+    - SUNRPC: Fix general protection fault in trace_rpc_xdr_overflow()
+    - bpf: Zero-fill re-used per-cpu map element
+    - nbd: fix a block_device refcount leak in nbd_release
+    - igc: Fix returning wrong statistics
+    - xfs: fix flags argument to rmap lookup when converting shared file rmaps
+    - xfs: set the unwritten bit in rmap lookup flags in xchk_bmap_get_rmapextents
+    - xfs: fix rmap key and record comparison functions
+    - xfs: fix brainos in the refcount scrubber's rmap fragment processor
+    - lan743x: fix "BUG: invalid wait context" when setting rx mode
+    - xfs: fix a missing unlock on error in xfs_fs_map_blocks
+    - of/address: Fix of_node memory leak in of_dma_is_coherent
+    - cosa: Add missing kfree in error path of cosa_write
+    - vrf: Fix fast path output packet handling with async Netfilter rules
+    - perf: Fix get_recursion_context()
+    - erofs: derive atime instead of leaving it empty
+    - ext4: correctly report "not supported" for {usr,grp}jquota when
+      !CONFIG_QUOTA
+    - ext4: unlock xattr_sem properly in ext4_inline_data_truncate()
+    - btrfs: ref-verify: fix memory leak in btrfs_ref_tree_mod
+    - btrfs: fix min reserved size calculation in merge_reloc_root
+    - btrfs: dev-replace: fail mount if we don't have replace item with target
+      device
+    - KVM: arm64: Don't hide ID registers from userspace
+    - thunderbolt: Fix memory leak if ida_simple_get() fails in
+      enumerate_services()
+    - thunderbolt: Add the missed ida_simple_remove() in ring_request_msix()
+    - uio: Fix use-after-free in uio_unregister_device()
+    - usb: cdc-acm: Add DISABLE_ECHO for Renesas USB Download mode
+    - xhci: hisilicon: fix refercence leak in xhci_histb_probe
+    - virtio: virtio_console: fix DMA memory allocation for rproc serial
+    - mei: protect mei_cl_mtu from null dereference
+    - futex: Don't enable IRQs unconditionally in put_pi_state()
+    - jbd2: fix up sparse warnings in checkpoint code
+    - mm/slub: fix panic in slab_alloc_node()
+    - Revert "kernel/reboot.c: convert simple_strtoul to kstrtoint"
+    - reboot: fix overflow parsing reboot cpu number
+    - ocfs2: initialize ip_next_orphan
+    - btrfs: fix potential overflow in cluster_pages_for_defrag on 32bit arch
+    - selinux: Fix error return code in sel_ib_pkey_sid_slow()
+    - gpio: pcie-idio-24: Fix irq mask when masking
+    - gpio: pcie-idio-24: Fix IRQ Enable Register value
+    - gpio: pcie-idio-24: Enable PEX8311 interrupts
+    - mmc: sdhci-of-esdhc: Handle pulse width detection erratum for more SoCs
+    - mmc: renesas_sdhi_core: Add missing tmio_mmc_host_free() at remove
+    - don't dump the threads that had been already exiting when zapped.
+    - drm/gma500: Fix out-of-bounds access to struct drm_device.vblank[]
+    - pinctrl: amd: use higher precision for 512 RtcClk
+    - pinctrl: amd: fix incorrect way to disable debounce filter
+    - swiotlb: fix "x86: Don't panic if can not alloc buffer for swiotlb"
+    - IPv6: Set SIT tunnel hard_header_len to zero
+    - net/af_iucv: fix null pointer dereference on shutdown
+    - net: udp: fix UDP header access on Fast/frag0 UDP GRO
+    - net: Update window_clamp if SOCK_RCVBUF is set
+    - net/x25: Fix null-ptr-deref in x25_connect
+    - tipc: fix memory leak in tipc_topsrv_start()
+    - r8169: fix potential skb double free in an error path
+    - drm/i915: Correctly set SFC capability for video engines
+    - powerpc/603: Always fault when _PAGE_ACCESSED is not set
+    - x86/speculation: Allow IBPB to be conditionally enabled on CPUs with always-
+      on STIBP
+    - perf scripting python: Avoid declaring function pointers with a visibility
+      attribute
+    - net: sch_generic: fix the missing new qdisc assignment bug
+    - Convert trailing spaces and periods in path components
+    - Linux 5.4.78
+  * Focal update: v5.4.77 upstream stable release (LP: #1905614)
+    - Linux 5.4.77
+  * Focal update: v5.4.76 upstream stable release (LP: #1905612)
+    - drm/i915: Break up error capture compression loops with cond_resched()
+    - drm/i915/gt: Delay execlist processing for tgl
+    - drm/i915: Drop runtime-pm assert from vgpu io accessors
+    - ASoC: Intel: Skylake: Add alternative topology binary name
+    - update dkms package versions
+    - linkage: Introduce new macros for assembler symbols
+    - arm64: asm: Add new-style position independent function annotations
+    - arm64: lib: Use modern annotations for assembly functions
+    - arm64: Change .weak to SYM_FUNC_START_WEAK_PI for arch/arm64/lib/mem*.S
+    - tipc: fix use-after-free in tipc_bcast_get_mode
+    - ptrace: fix task_join_group_stop() for the case when current is traced
+    - cadence: force nonlinear buffers to be cloned
+    - chelsio/chtls: fix memory leaks caused by a race
+    - chelsio/chtls: fix always leaking ctrl_skb
+    - gianfar: Replace skb_realloc_headroom with skb_cow_head for PTP
+    - gianfar: Account for Tx PTP timestamp in the skb headroom
+    - ionic: check port ptr before use
+    - ip_tunnel: fix over-mtu packet send fail without TUNNEL_DONT_FRAGMENT flags
+    - net: usb: qmi_wwan: add Telit LE910Cx 0x1230 composition
+    - powerpc/vnic: Extend "failover pending" window
+    - sctp: Fix COMM_LOST/CANT_STR_ASSOC err reporting on big-endian platforms
+    - sfp: Fix error handing in sfp_probe()
+    - Fonts: Replace discarded const qualifier
+    - ALSA: hda/realtek - Fixed HP headset Mic can't be detected
+    - ALSA: hda/realtek - Enable headphone for ASUS TM420
+    - ALSA: usb-audio: Add implicit feedback quirk for Zoom UAC-2
+    - ALSA: usb-audio: add usb vendor id as DSD-capable for Khadas devices
+    - ALSA: usb-audio: Add implicit feedback quirk for Qu-16
+    - ALSA: usb-audio: Add implicit feedback quirk for MODX
+    - mm: mempolicy: fix potential pte_unmap_unlock pte error
+    - lib/crc32test: remove extra local_irq_disable/enable
+    - kthread_worker: prevent queuing delayed work from timer_fn when it is being
+      canceled
+    - mm: always have io_remap_pfn_range() set pgprot_decrypted()
+    - gfs2: Wake up when sd_glock_disposal becomes zero
+    - ring-buffer: Fix recursion protection transitions between interrupt context
+    - mtd: spi-nor: Don't copy self-pointing struct around
+    - ftrace: Fix recursion check for NMI test
+    - ftrace: Handle tracing when switching between context
+    - regulator: defer probe when trying to get voltage from unresolved supply
+    - spi: bcm2835: fix gpio cs level inversion
+    - tracing: Fix out of bounds write in get_trace_buf
+    - futex: Handle transient "ownerless" rtmutex state correctly
+    - ARM: dts: sun4i-a10: fix cpu_alert temperature
+    - arm64: dts: meson: add missing g12 rng clock
+    - x86/kexec: Use up-to-dated screen_info copy to fill boot params
+    - of: Fix reserved-memory overlap detection
+    - drm/sun4i: frontend: Rework a bit the phase data
+    - drm/sun4i: frontend: Reuse the ch0 phase for RGB formats
+    - drm/sun4i: frontend: Fix the scaler phase on A33
+    - blk-cgroup: Fix memleak on error path
+    - blk-cgroup: Pre-allocate tree node on blkg_conf_prep
+    - scsi: core: Don't start concurrent async scan on same host
+    - drm/amdgpu: add DID for navi10 blockchain SKU
+    - scsi: ibmvscsi: Fix potential race after loss of transport
+    - vsock: use ns_capable_noaudit() on socket create
+    - nvme-rdma: handle unexpected nvme completion data length
+    - nvmet: fix a NULL pointer dereference when tracing the flush command
+    - drm/vc4: drv: Add error handding for bind
+    - ACPI: NFIT: Fix comparison to '-ENXIO'
+    - usb: cdns3: gadget: suspicious implicit sign extension
+    - drm/nouveau/nouveau: fix the start/end range for migration
+    - drm/nouveau/gem: fix "refcount_t: underflow; use-after-free"
+    - arm64/smp: Move rcu_cpu_starting() earlier
+    - vt: Disable KD_FONT_OP_COPY
+    - fork: fix copy_process(CLONE_PARENT) race with the exiting ->real_parent
+    - s390/pkey: fix paes selftest failure with paes and pkey static build
+    - serial: 8250_mtk: Fix uart_get_baud_rate warning
+    - serial: txx9: add missing platform_driver_unregister() on error in
+      serial_txx9_init
+    - USB: serial: cyberjack: fix write-URB completion race
+    - USB: serial: option: add Quectel EC200T module support
+    - USB: serial: option: add LE910Cx compositions 0x1203, 0x1230, 0x1231
+    - USB: serial: option: add Telit FN980 composition 0x1055
+    - tty: serial: fsl_lpuart: add LS1028A support
+    - tty: serial: fsl_lpuart: LS1021A has a FIFO size of 16 words, like LS1028A
+    - usb: dwc3: ep0: Fix delay status handling
+    - USB: Add NO_LPM quirk for Kingston flash drive
+    - usb: mtu3: fix panic in mtu3_gadget_stop()
+    - drm/panfrost: Fix a deadlock between the shrinker and madvise path
+    - ARC: stack unwinding: avoid indefinite looping
+    - PM: runtime: Drop runtime PM references to supplier on link removal
+    - PM: runtime: Drop pm_runtime_clean_up_links()
+    - PM: runtime: Resume the device earlier in __device_release_driver()
+    - xfs: flush for older, xfs specific ioctls
+    - perf/core: Fix a memory leak in perf_event_parse_addr_filter()
+    - arm64: dts: marvell: espressobin: Add ethernet switch aliases
+    - Linux 5.4.76
+  * s390: dbginfo.sh triggers kernel panic, reading from
+    /sys/kernel/mm/page_idle/bitmap (LP: #1904884)
+    - mm/page_idle.c: skip offline pages
+  * Ask 8821C Bluetooth controller to drop old firmware (LP: #1904221)
+    - Bluetooth: btrtl: Ask 8821C to drop old firmware
+    - Bluetooth: btrtl: fix incorrect skb allocation failure check
+  * Use ACPI S5 for reboot (LP: #1904225)
+    - PM: ACPI: reboot: Use S5 for reboot
+  * Focal update: v5.4.75 upstream stable release (LP: #1904450)
+    - xen/events: avoid removing an event channel while handling it
+    - xen/events: add a proper barrier to 2-level uevent unmasking
+    - xen/events: fix race in evtchn_fifo_unmask()
+    - xen/events: add a new "late EOI" evtchn framework
+    - xen/blkback: use lateeoi irq binding
+    - xen/netback: use lateeoi irq binding
+    - xen/scsiback: use lateeoi irq binding
+    - xen/pvcallsback: use lateeoi irq binding
+    - xen/pciback: use lateeoi irq binding
+    - xen/events: switch user event channels to lateeoi model
+    - xen/events: use a common cpu hotplug hook for event channels
+    - xen/events: defer eoi in case of excessive number of events
+    - xen/events: block rogue events for some time
+    - firmware: arm_scmi: Fix ARCH_COLD_RESET
+    - firmware: arm_scmi: Add missing Rx size re-initialisation
+    - x86/unwind/orc: Fix inactive tasks with stack pointer in %sp on GCC 10
+      compiled kernels
+    - mlxsw: core: Fix use-after-free in mlxsw_emad_trans_finish()
+    - RDMA/qedr: Fix memory leak in iWARP CM
+    - ata: sata_nv: Fix retrieving of active qcs
+    - futex: Fix incorrect should_fail_futex() handling
+    - powerpc/powernv/smp: Fix spurious DBG() warning
+    - [Config] update config for ARCH_WANT_IRQS_OFF_ACTIVATE_MM
+    - mm: fix exec activate_mm vs TLB shootdown and lazy tlb switching race
+    - powerpc: select ARCH_WANT_IRQS_OFF_ACTIVATE_MM
+    - sparc64: remove mm_cpumask clearing to fix kthread_use_mm race
+    - f2fs: add trace exit in exception path
+    - f2fs: fix uninit-value in f2fs_lookup
+    - f2fs: fix to check segment boundary during SIT page readahead
+    - s390/startup: avoid save_area_sync overflow
+    - um: change sigio_spinlock to a mutex
+    - f2fs: handle errors of f2fs_get_meta_page_nofail
+    - ARM: 8997/2: hw_breakpoint: Handle inexact watchpoint addresses
+    - NFS4: Fix oops when copy_file_range is attempted with NFS4.0 source
+    - power: supply: bq27xxx: report "not charging" on all types
+    - xfs: fix realtime bitmap/summary file truncation when growing rt volume
+    - video: fbdev: pvr2fb: initialize variables
+    - ath10k: start recovery process when payload length exceeds max htc length
+      for sdio
+    - ath10k: fix VHT NSS calculation when STBC is enabled
+    - drm/brige/megachips: Add checking if ge_b850v3_lvds_init() is working
+      correctly
+    - selftests/x86/fsgsbase: Reap a forgotten child
+    - media: videodev2.h: RGB BT2020 and HSV are always full range
+    - media: platform: Improve queue set up flow for bug fixing
+    - usb: typec: tcpm: During PR_SWAP, source caps should be sent only after
+      tSwapSourceStart
+    - media: tw5864: check status of tw5864_frameinterval_get
+    - media: imx274: fix frame interval handling
+    - mmc: via-sdmmc: Fix data race bug
+    - drm/bridge/synopsys: dsi: add support for non-continuous HS clock
+    - arm64: topology: Stop using MPIDR for topology information
+    - printk: reduce LOG_BUF_SHIFT range for H8300
+    - ia64: kprobes: Use generic kretprobe trampoline handler
+    - kgdb: Make "kgdbcon" work properly with "kgdb_earlycon"
+    - bpf: Permit map_ptr arithmetic with opcode add and offset 0
+    - media: uvcvideo: Fix dereference of out-of-bound list iterator
+    - selftests/bpf: Define string const as global for test_sysctl_prog.c
+    - samples/bpf: Fix possible deadlock in xdpsock
+    - riscv: Define AT_VECTOR_SIZE_ARCH for ARCH_DLINFO
+    - cpufreq: sti-cpufreq: add stih418 support
+    - USB: adutux: fix debugging
+    - uio: free uio id after uio file node is freed
+    - usb: xhci: omit duplicate actions when suspending a runtime suspended host.
+    - SUNRPC: Mitigate cond_resched() in xprt_transmit()
+    - arm64/mm: return cpu_all_mask when node is NUMA_NO_NODE
+    - can: flexcan: disable clocks during stop mode
+    - xfs: don't free rt blocks when we're doing a REMAP bunmapi call
+    - ACPI: Add out of bounds and numa_off protections to pxm_to_node()
+    - brcmfmac: Fix warning message after dongle setup failed
+    - drivers/net/wan/hdlc_fr: Correctly handle special skb->protocol values
+    - bus/fsl_mc: Do not rely on caller to provide non NULL mc_io
+    - ACPI: HMAT: Fix handling of changes from ACPI 6.2 to ACPI 6.3
+    - power: supply: test_power: add missing newlines when printing parameters by
+      sysfs
+    - drm/amd/display: HDMI remote sink need mode validation for Linux
+    - ARC: [dts] fix the errors detected by dtbs_check
+    - btrfs: fix replace of seed device
+    - md/bitmap: md_bitmap_get_counter returns wrong blocks
+    - bnxt_en: Log unknown link speed appropriately.
+    - rpmsg: glink: Use complete_all for open states
+    - clk: ti: clockdomain: fix static checker warning
+    - net: 9p: initialize sun_server.sun_path to have addr's value only when addr
+      is valid
+    - drivers: watchdog: rdc321x_wdt: Fix race condition bugs
+    - ext4: Detect already used quota file early
+    - KVM: PPC: Book3S HV: Do not allocate HPT for a nested guest
+    - gfs2: use-after-free in sysfs deregistration
+    - gfs2: add validation checks for size of superblock
+    - cifs: handle -EINTR in cifs_setattr
+    - arm64: dts: renesas: ulcb: add full-pwr-cycle-in-suspend into eMMC nodes
+    - ARM: dts: omap4: Fix sgx clock rate for 4430
+    - memory: emif: Remove bogus debugfs error handling
+    - ARM: dts: s5pv210: remove DMA controller bus node name to fix dtschema
+      warnings
+    - ARM: dts: s5pv210: move fixed clocks under root node
+    - ARM: dts: s5pv210: move PMU node out of clock controller
+    - ARM: dts: s5pv210: remove dedicated 'audio-subsystem' node
+    - nbd: make the config put is called before the notifying the waiter
+    - sgl_alloc_order: fix memory leak
+    - nvme-rdma: fix crash when connect rejected
+    - md/raid5: fix oops during stripe resizing
+    - mmc: sdhci: Add LTR support for some Intel BYT based controllers
+    - mmc: sdhci-acpi: AMDI0040: Set SDHCI_QUIRK2_PRESET_VALUE_BROKEN
+    - seccomp: Make duplicate listener detection non-racy
+    - selftests/x86/fsgsbase: Test PTRACE_PEEKUSER for GSBASE with invalid LDT GS
+    - perf/x86/intel: Fix Ice Lake event constraint table
+    - perf/x86/amd/ibs: Don't include randomized bits in get_ibs_op_count()
+    - perf/x86/amd/ibs: Fix raw sample data accumulation
+    - spi: sprd: Release DMA channel also on probe deferral
+    - extcon: ptn5150: Fix usage of atomic GPIO with sleeping GPIO chips
+    - leds: bcm6328, bcm6358: use devres LED registering function
+    - media: uvcvideo: Fix uvc_ctrl_fixup_xu_info() not having any effect
+    - fs: Don't invalidate page buffers in block_write_full_page()
+    - NFS: fix nfs_path in case of a rename retry
+    - ACPI: button: fix handling lid state changes when input device closed
+    - ACPI / extlog: Check for RDMSR failure
+    - ACPI: debug: don't allow debugging when ACPI is disabled
+    - PCI/ACPI: Whitelist hotplug ports for D3 if power managed by ACPI
+    - ACPI: EC: PM: Flush EC work unconditionally after wakeup
+    - ACPI: EC: PM: Drop ec_no_wakeup check from acpi_ec_dispatch_gpe()
+    - acpi-cpufreq: Honor _PSD table setting on new AMD CPUs
+    - w1: mxc_w1: Fix timeout resolution problem leading to bus error
+    - scsi: mptfusion: Fix null pointer dereferences in mptscsih_remove()
+    - scsi: qla2xxx: Fix crash on session cleanup with unload
+    - PM: runtime: Remove link state checks in rpm_get/put_supplier()
+    - btrfs: qgroup: fix wrong qgroup metadata reserve for delayed inode
+    - btrfs: improve device scanning messages
+    - btrfs: reschedule if necessary when logging directory items
+    - btrfs: send, orphanize first all conflicting inodes when processing
+      references
+    - btrfs: send, recompute reference path after orphanization of a directory
+    - btrfs: use kvzalloc() to allocate clone_roots in btrfs_ioctl_send()
+    - btrfs: tree-checker: fix false alert caused by legacy btrfs root item
+    - btrfs: cleanup cow block on error
+    - btrfs: tree-checker: validate number of chunk stripes and parity
+    - btrfs: fix use-after-free on readahead extent after failure to create it
+    - btrfs: fix readahead hang and use-after-free after removing a device
+    - Revert "UBUNTU: SAUCE: xhci: workaround for S3 issue on AMD SNPS 3.0 xHC"
+    - usb: xhci: Workaround for S3 issue on AMD SNPS 3.0 xHC
+    - usb: dwc3: pci: Allow Elkhart Lake to utilize DSM method for PM
+      functionality
+    - usb: dwc3: ep0: Fix ZLP for OUT ep0 requests
+    - usb: dwc3: gadget: Check MPS of the request length
+    - usb: dwc3: core: add phy cleanup for probe error handling
+    - usb: dwc3: core: don't trigger runtime pm when remove driver
+    - usb: dwc3: gadget: Resume pending requests after CLEAR_STALL
+    - usb: dwc3: gadget: END_TRANSFER before CLEAR_STALL command
+    - usb: cdc-acm: fix cooldown mechanism
+    - usb: typec: tcpm: reset hard_reset_count for any disconnect
+    - usb: host: fsl-mph-dr-of: check return of dma_set_mask()
+    - drm/i915: Force VT'd workarounds when running as a guest OS
+    - vt: keyboard, simplify vt_kdgkbsent
+    - vt: keyboard, extend func_buf_lock to readers
+    - HID: wacom: Avoid entering wacom_wac_pen_report for pad / battery
+    - udf: Fix memory leak when mounting
+    - dmaengine: dma-jz4780: Fix race in jz4780_dma_tx_status
+    - iio:light:si1145: Fix timestamp alignment and prevent data leak.
+    - iio: adc: gyroadc: fix leak of device node iterator
+    - iio:adc:ti-adc0832 Fix alignment issue with timestamp
+    - iio:adc:ti-adc12138 Fix alignment issue with timestamp
+    - iio:gyro:itg3200: Fix timestamp alignment and prevent data leak.
+    - powerpc/drmem: Make lmb_size 64 bit
+    - MIPS: DEC: Restore bootmem reservation for firmware working memory area
+    - s390/stp: add locking to sysfs functions
+    - [Config] update config for PPC_RTAS_FILTER
+    - powerpc/rtas: Restrict RTAS requests from userspace
+    - powerpc: Warn about use of smt_snooze_delay
+    - powerpc/memhotplug: Make lmb size 64bit
+    - powerpc/powernv/elog: Fix race while processing OPAL error log event.
+    - powerpc/powermac: Fix low_sleep_handler with KUAP and KUEP
+    - NFSv4: Wait for stateid updates after CLOSE/OPEN_DOWNGRADE
+    - NFSv4.2: support EXCHGID4_FLAG_SUPP_FENCE_OPS 4.2 EXCHANGE_ID flag
+    - NFSD: Add missing NFSv2 .pc_func methods
+    - ubifs: dent: Fix some potential memory leaks while iterating entries
+    - ubifs: xattr: Fix some potential memory leaks while iterating entries
+    - ubifs: journal: Make sure to not dirty twice for auth nodes
+    - ubifs: Fix a memleak after dumping authentication mount options
+    - ubifs: Don't parse authentication mount options in remount process
+    - ubifs: mount_ubifs: Release authentication resource in error handling path
+    - perf python scripting: Fix printable strings in python3 scripts
+    - ARC: perf: redo the pct irq missing in device-tree handling
+    - ubi: check kthread_should_stop() after the setting of task state
+    - ia64: fix build error with !COREDUMP
+    - rtc: rx8010: don't modify the global rtc ops
+    - i2c: imx: Fix external abort on interrupt in exit paths
+    - drm/amdgpu: don't map BO in reserved region
+    - drm/amd/display: Increase timeout for DP Disable
+    - drm/amdgpu: correct the gpu reset handling for job != NULL case
+    - drm/amdkfd: Use same SQ prefetch setting as amdgpu
+    - drm/amd/display: Avoid MST manager resource leak.
+    - drm/amdgpu: increase the reserved VM size to 2MB
+    - drm/amd/display: Don't invoke kgdb_breakpoint() unconditionally
+    - drm/amd/display: Fix kernel panic by dal_gpio_open() error
+    - ceph: promote to unsigned long long before shifting
+    - libceph: clear con->out_msg on Policy::stateful_server faults
+    - 9P: Cast to loff_t before multiplying
+    - ring-buffer: Return 0 on success from ring_buffer_resize()
+    - vringh: fix __vringh_iov() when riov and wiov are different
+    - ext4: fix leaking sysfs kobject after failed mount
+    - ext4: fix error handling code in add_new_gdb
+    - ext4: fix invalid inode checksum
+    - drm/ttm: fix eviction valuable range check.
+    - mmc: sdhci-of-esdhc: set timeout to max before tuning
+    - mmc: sdhci: Use Auto CMD Auto Select only when v4_mode is true
+    - drm/amd/pm: increase mclk switch threshold to 200 us
+    - tty: make FONTX ioctl use the tty pointer they were actually passed
+    - arm64: berlin: Select DW_APB_TIMER_OF
+    - [Config] update annotations for DW_APB_TIMER
+    - cachefiles: Handle readpage error correctly
+    - hil/parisc: Disable HIL driver when it gets stuck
+    - arm: dts: mt7623: add missing pause for switchport
+    - ARM: samsung: fix PM debug build with DEBUG_LL but !MMU
+    - ARM: s3c24xx: fix missing system reset
+    - device property: Keep secondary firmware node secondary by type
+    - device property: Don't clear secondary pointer for shared primary firmware
+      node
+    - KVM: arm64: Fix AArch32 handling of DBGD{CCINT,SCRext} and DBGVCR
+    - staging: fieldbus: anybuss: jump to correct label in an error path
+    - staging: comedi: cb_pcidas: Allow 2-channel commands for AO subdevice
+    - staging: octeon: repair "fixed-link" support
+    - staging: octeon: Drop on uncorrectable alignment or FCS error
+    - Linux 5.4.75
+  * [HP 635] Radeon 6310 brightness control does not work (LP: #1894667) //
+    Focal update: v5.4.75 upstream stable release (LP: #1904450)
+    - ACPI: video: use ACPI backlight for HP 635 Notebook
+  * Focal update: v5.4.74 upstream stable release (LP: #1904445)
+    - netfilter: nftables_offload: KASAN slab-out-of-bounds Read in
+      nft_flow_rule_create
+    - socket: don't clear SOCK_TSTAMP_NEW when SO_TIMESTAMPNS is disabled
+    - objtool: Support Clang non-section symbols in ORC generation
+    - scripts/setlocalversion: make git describe output more reliable
+    - arm64: Run ARCH_WORKAROUND_1 enabling code on all CPUs
+    - arm64: Run ARCH_WORKAROUND_2 enabling code on all CPUs
+    - arm64: link with -z norelro regardless of CONFIG_RELOCATABLE
+    - x86/PCI: Fix intel_mid_pci.c build error when ACPI is not enabled
+    - bnxt_en: Check abort error state in bnxt_open_nic().
+    - bnxt_en: Send HWRM_FUNC_RESET fw command unconditionally.
+    - chelsio/chtls: fix deadlock issue
+    - chelsio/chtls: fix memory leaks in CPL handlers
+    - chelsio/chtls: fix tls record info to user
+    - cxgb4: set up filter action after rewrites
+    - gtp: fix an use-before-init in gtp_newlink()
+    - ibmvnic: fix ibmvnic_set_mac
+    - mlxsw: core: Fix memory leak on module removal
+    - netem: fix zero division in tabledist
+    - net/sched: act_mpls: Add softdep on mpls_gso.ko
+    - r8169: fix issue with forced threading in combination with shared interrupts
+    - ravb: Fix bit fields checking in ravb_hwtstamp_get()
+    - tcp: Prevent low rmem stalls with SO_RCVLOWAT.
+    - tipc: fix memory leak caused by tipc_buf_append()
+    - net: hns3: Clear the CMDQ registers before unmapping BAR region
+    - bnxt_en: Re-write PCI BARs after PCI fatal error.
+    - bnxt_en: Fix regression in workqueue cleanup logic in bnxt_remove_one().
+    - bnxt_en: Invoke cancel_delayed_work_sync() for PFs also.
+    - erofs: avoid duplicated permission check for "trusted." xattrs
+    - arch/x86/amd/ibs: Fix re-arming IBS Fetch
+    - x86/xen: disable Firmware First mode for correctable memory errors
+    - ata: ahci: mvebu: Make SATA PHY optional for Armada 3720
+    - fuse: fix page dereference after free
+    - bpf: Fix comment for helper bpf_current_task_under_cgroup()
+    - evm: Check size of security.evm before using it
+    - p54: avoid accessing the data mapped to streaming DMA
+    - cxl: Rework error message for incompatible slots
+    - RDMA/addr: Fix race with netevent_callback()/rdma_addr_cancel()
+    - mtd: lpddr: Fix bad logic in print_drs_error
+    - serial: qcom_geni_serial: To correct QUP Version detection logic
+    - serial: pl011: Fix lockdep splat when handling magic-sysrq interrupt
+    - PM: runtime: Fix timer_expires data type on 32-bit arches
+    - ata: sata_rcar: Fix DMA boundary mask
+    - xen/gntdev.c: Mark pages as dirty
+    - crypto: x86/crc32c - fix building with clang ias
+    - openrisc: Fix issue with get_user for 64-bit values
+    - misc: rtsx: do not setting OC_POWER_DOWN reg in rtsx_pci_init_ocp()
+    - phy: marvell: comphy: Convert internal SMCC firmware return codes to errno
+    - Linux 5.4.74
+  * Bionic: btrfs: kernel BUG at /build/linux-
+    eTBZpZ/linux-4.15.0/fs/btrfs/ctree.c:3233! (LP: #1902254)
+    - btrfs: tree-checker: fix incorrect printk format
+  * NULL pointer dereference when configuring multi-function with devfn != 0
+    before devfn == 0 (LP: #1903682)
+    - s390/pci: fix hot-plug of PCI function missing bus
+
+  [ Ubuntu: 5.4.0-58.64 ]
+
+  * focal/linux: 5.4.0-58.64 -proposed tracker (LP: #1907390)
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+  * raid10: discard leads to corrupted file system (LP: #1907262)
+    - Revert "dm raid: remove unnecessary discard limits for raid10"
+    - Revert "dm raid: fix discard limits for raid1 and raid10"
+    - Revert "md/raid10: improve discard request for far layout"
+    - Revert "md/raid10: improve raid10 discard request"
+    - Revert "md/raid10: pull codes that wait for blocked dev into one function"
+    - Revert "md/raid10: extend r10bio devs to raid disks"
+    - Revert "md: add md_submit_discard_bio() for submitting discard bio"
+
+  [ Ubuntu: 5.4.0-56.62 ]
+
+  * focal/linux: 5.4.0-56.62 -proposed tracker (LP: #1905300)
+  * CVE-2020-4788
+    - selftests/powerpc: rfi_flush: disable entry flush if present
+    - powerpc/64s: flush L1D on kernel entry
+    - powerpc/64s: flush L1D after user accesses
+    - selftests/powerpc: entry flush test
+
+  [ Ubuntu: 5.4.0-55.61 ]
+
+  * focal/linux: 5.4.0-55.61 -proposed tracker (LP: #1903175)
+  * Update kernel packaging to support forward porting kernels (LP: #1902957)
+    - [Debian] Update for leader included in BACKPORT_SUFFIX
+  * Avoid double newline when running insertchanges (LP: #1903293)
+    - [Packaging] insertchanges: avoid double newline
+  * EFI: Fails when BootCurrent entry does not exist (LP: #1899993)
+    - efivarfs: Replace invalid slashes with exclamation marks in dentries.
+  * CVE-2020-14351
+    - perf/core: Fix race in the perf_mmap_close() function
+  * raid10: Block discard is very slow, causing severe delays for mkfs and
+    fstrim operations (LP: #1896578)
+    - md: add md_submit_discard_bio() for submitting discard bio
+    - md/raid10: extend r10bio devs to raid disks
+    - md/raid10: pull codes that wait for blocked dev into one function
+    - md/raid10: improve raid10 discard request
+    - md/raid10: improve discard request for far layout
+    - dm raid: fix discard limits for raid1 and raid10
+    - dm raid: remove unnecessary discard limits for raid10
+  * Bionic: btrfs: kernel BUG at /build/linux-
+    eTBZpZ/linux-4.15.0/fs/btrfs/ctree.c:3233! (LP: #1902254)
+    - btrfs: drop unnecessary offset_in_page in extent buffer helpers
+    - btrfs: extent_io: do extra check for extent buffer read write functions
+    - btrfs: extent-tree: kill BUG_ON() in __btrfs_free_extent()
+    - btrfs: extent-tree: kill the BUG_ON() in insert_inline_extent_backref()
+    - btrfs: ctree: check key order before merging tree blocks
+  * Ethernet no link lights after reboot (Intel i225-v 2.5G) (LP: #1902578)
+    - igc: Add PHY power management control
+  * Undetected Data corruption in MPI workloads that use VSX for reductions on
+    POWER9 DD2.1 systems (LP: #1902694)
+    - powerpc: Fix undetected data corruption with P9N DD2.1 VSX CI load emulation
+    - selftests/powerpc: Make alignment handler test P9N DD2.1 vector CI load
+      workaround
+  * [20.04 FEAT] Support/enhancement of NVMe IPL (LP: #1902179)
+    - s390: nvme ipl
+    - s390: nvme reipl
+    - s390/ipl: support NVMe IPL kernel parameters
+  * uvcvideo: add mapping for HEVC payloads (LP: #1895803)
+    - media: uvcvideo: Add mapping for HEVC payloads
+  * Focal update: v5.4.73 upstream stable release (LP: #1902115)
+    - ibmveth: Switch order of ibmveth_helper calls.
+    - ibmveth: Identify ingress large send packets.
+    - ipv4: Restore flowi4_oif update before call to xfrm_lookup_route
+    - mlx4: handle non-napi callers to napi_poll
+    - net: fec: Fix phy_device lookup for phy_reset_after_clk_enable()
+    - net: fec: Fix PHY init after phy_reset_after_clk_enable()
+    - net: fix pos incrementment in ipv6_route_seq_next
+    - net/smc: fix valid DMBE buffer sizes
+    - net/tls: sendfile fails with ktls offload
+    - net: usb: qmi_wwan: add Cellient MPL200 card
+    - tipc: fix the skb_unshare() in tipc_buf_append()
+    - socket: fix option SO_TIMESTAMPING_NEW
+    - can: m_can_platform: don't call m_can_class_suspend in runtime suspend
+    - can: j1935: j1939_tp_tx_dat_new(): fix missing initialization of skbcnt
+    - net: j1939: j1939_session_fresh_new(): fix missing initialization of skbcnt
+    - net/ipv4: always honour route mtu during forwarding
+    - net_sched: remove a redundant goto chain check
+    - r8169: fix data corruption issue on RTL8402
+    - cxgb4: handle 4-tuple PEDIT to NAT mode translation
+    - binder: fix UAF when releasing todo list
+    - ALSA: bebob: potential info leak in hwdep_read()
+    - ALSA: hda/hdmi: fix incorrect locking in hdmi_pcm_close
+    - nvme-pci: disable the write zeros command for Intel 600P/P3100
+    - chelsio/chtls: fix socket lock
+    - chelsio/chtls: correct netdevice for vlan interface
+    - chelsio/chtls: correct function return and return type
+    - ibmvnic: save changed mac address to adapter->mac_addr
+    - net: ftgmac100: Fix Aspeed ast2600 TX hang issue
+    - net: hdlc: In hdlc_rcv, check to make sure dev is an HDLC device
+    - net: hdlc_raw_eth: Clear the IFF_TX_SKB_SHARING flag after calling
+      ether_setup
+    - net: Properly typecast int values to set sk_max_pacing_rate
+    - net/sched: act_tunnel_key: fix OOB write in case of IPv6 ERSPAN tunnels
+    - nexthop: Fix performance regression in nexthop deletion
+    - nfc: Ensure presence of NFC_ATTR_FIRMWARE_NAME attribute in
+      nfc_genl_fw_download()
+    - r8169: fix operation under forced interrupt threading
+    - selftests: forwarding: Add missing 'rp_filter' configuration
+    - tcp: fix to update snd_wl1 in bulk receiver fast path
+    - icmp: randomize the global rate limiter
+    - ALSA: hda/realtek - set mic to auto detect on a HP AIO machine
+    - ALSA: hda/realtek - Add mute Led support for HP Elitebook 845 G7
+    - ALSA: hda/realtek: Enable audio jacks of ASUS D700SA with ALC887
+    - cifs: remove bogus debug code
+    - cifs: Return the error from crypt_message when enc/dec key not found.
+    - SMB3: Resolve data corruption of TCP server info fields
+    - KVM: nVMX: Reset the segment cache when stuffing guest segs
+    - KVM: nVMX: Reload vmcs01 if getting vmcs12's pages fails
+    - KVM: x86/mmu: Commit zap of remaining invalid pages when recovering lpages
+    - KVM: SVM: Initialize prev_ga_tag before use
+    - ima: Don't ignore errors from crypto_shash_update()
+    - crypto: algif_aead - Do not set MAY_BACKLOG on the async path
+    - crypto: caam/qi - add fallback for XTS with more than 8B IV
+    - EDAC/i5100: Fix error handling order in i5100_init_one()
+    - EDAC/aspeed: Fix handling of platform_get_irq() error
+    - EDAC/ti: Fix handling of platform_get_irq() error
+    - perf/x86/intel/ds: Fix x86_pmu_stop warning for large PEBS
+    - x86/fpu: Allow multiple bits in clearcpuid= parameter
+    - drivers/perf: xgene_pmu: Fix uninitialized resource struct
+    - drivers/perf: thunderx2_pmu: Fix memory resource error handling
+    - sched/fair: Fix wrong cpu selecting from isolated domain
+    - perf/x86/intel/uncore: Update Ice Lake uncore units
+    - perf/x86/intel/uncore: Reduce the number of CBOX counters
+    - x86/nmi: Fix nmi_handle() duration miscalculation
+    - x86/events/amd/iommu: Fix sizeof mismatch
+    - crypto: algif_skcipher - EBUSY on aio should be an error
+    - crypto: mediatek - Fix wrong return value in mtk_desc_ring_alloc()
+    - crypto: ixp4xx - Fix the size used in a 'dma_free_coherent()' call
+    - crypto: picoxcell - Fix potential race condition bug
+    - media: tuner-simple: fix regression in simple_set_radio_freq
+    - media: Revert "media: exynos4-is: Add missed check for
+      pinctrl_lookup_state()"
+    - media: ov5640: Correct Bit Div register in clock tree diagram
+    - media: m5mols: Check function pointer in m5mols_sensor_power
+    - media: uvcvideo: Set media controller entity functions
+    - media: uvcvideo: Silence shift-out-of-bounds warning
+    - media: staging/intel-ipu3: css: Correctly reset some memory
+    - media: omap3isp: Fix memleak in isp_probe
+    - media: i2c: ov5640: Remain in power down for DVP mode unless streaming
+    - media: i2c: ov5640: Separate out mipi configuration from s_power
+    - media: i2c: ov5640: Enable data pins on poweron for DVP mode
+    - media: rcar_drif: Fix fwnode reference leak when parsing DT
+    - media: rcar_drif: Allocate v4l2_async_subdev dynamically
+    - media: rcar-csi2: Allocate v4l2_async_subdev dynamically
+    - crypto: omap-sham - fix digcnt register handling with export/import
+    - hwmon: (pmbus/max34440) Fix status register reads for MAX344{51,60,61}
+    - cypto: mediatek - fix leaks in mtk_desc_ring_alloc
+    - media: mx2_emmaprp: Fix memleak in emmaprp_probe
+    - media: tc358743: initialize variable
+    - media: tc358743: cleanup tc358743_cec_isr
+    - media: rcar-vin: Fix a reference count leak.
+    - media: rockchip/rga: Fix a reference count leak.
+    - media: platform: fcp: Fix a reference count leak.
+    - media: camss: Fix a reference count leak.
+    - media: s5p-mfc: Fix a reference count leak
+    - media: stm32-dcmi: Fix a reference count leak
+    - media: ti-vpe: Fix a missing check and reference count leak
+    - regulator: resolve supply after creating regulator
+    - pinctrl: bcm: fix kconfig dependency warning when !GPIOLIB
+    - spi: spi-s3c64xx: swap s3c64xx_spi_set_cs() and s3c64xx_enable_datapath()
+    - spi: spi-s3c64xx: Check return values
+    - blk-mq: move cancel of hctx->run_work to the front of blk_exit_queue
+    - ath10k: provide survey info as accumulated data
+    - drm/vkms: fix xrgb on compute crc
+    - Bluetooth: hci_uart: Cancel init work before unregistering
+    - drm/amd/display: Fix wrong return value in dm_update_plane_state()
+    - drm: panel: Fix bus format for OrtusTech COM43H4M85ULC panel
+    - ath6kl: prevent potential array overflow in ath6kl_add_new_sta()
+    - ath9k: Fix potential out of bounds in ath9k_htc_txcompletion_cb()
+    - ath10k: Fix the size used in a 'dma_free_coherent()' call in an error
+      handling path
+    - wcn36xx: Fix reported 802.11n rx_highest rate wcn3660/wcn3680
+    - ASoC: qcom: lpass-platform: fix memory leak
+    - ASoC: qcom: lpass-cpu: fix concurrency issue
+    - brcmfmac: check ndev pointer
+    - mwifiex: Do not use GFP_KERNEL in atomic context
+    - staging: rtl8192u: Do not use GFP_KERNEL in atomic context
+    - drm/gma500: fix error check
+    - scsi: qla4xxx: Fix an error handling path in 'qla4xxx_get_host_stats()'
+    - scsi: qla2xxx: Fix wrong return value in qlt_chk_unresolv_exchg()
+    - scsi: qla2xxx: Fix wrong return value in qla_nvme_register_hba()
+    - scsi: csiostor: Fix wrong return value in csio_hw_prep_fw()
+    - backlight: sky81452-backlight: Fix refcount imbalance on error
+    - staging: emxx_udc: Fix passing of NULL to dma_alloc_coherent()
+    - VMCI: check return value of get_user_pages_fast() for errors
+    - mm/error_inject: Fix allow_error_inject function signatures.
+    - drm: panel: Fix bpc for OrtusTech COM43H4M85ULC panel
+    - drm/crc-debugfs: Fix memleak in crc_control_write
+    - binder: Remove bogus warning on failed same-process transaction
+    - tty: serial: earlycon dependency
+    - pty: do tty_flip_buffer_push without port->lock in pty_write
+    - pwm: lpss: Fix off by one error in base_unit math in pwm_lpss_prepare()
+    - pwm: lpss: Add range limit check for the base_unit register value
+    - drivers/virt/fsl_hypervisor: Fix error handling path
+    - video: fbdev: vga16fb: fix setting of pixclock because a pass-by-value error
+    - video: fbdev: sis: fix null ptr dereference
+    - video: fbdev: radeon: Fix memleak in radeonfb_pci_register
+    - ASoC: fsl: imx-es8328: add missing put_device() call in imx_es8328_probe()
+    - HID: roccat: add bounds checking in kone_sysfs_write_settings()
+    - drm/msm: Avoid div-by-zero in dpu_crtc_atomic_check()
+    - drm/panfrost: Ensure GPU quirks are always initialised
+    - iomap: Clear page error before beginning a write
+    - pinctrl: mcp23s08: Fix mcp23x17_regmap initialiser
+    - pinctrl: mcp23s08: Fix mcp23x17 precious range
+    - net/mlx5: Don't call timecounter cyc2time directly from 1PPS flow
+    - scsi: mpt3sas: Fix sync irqs
+    - net: stmmac: use netif_tx_start|stop_all_queues() function
+    - cpufreq: armada-37xx: Add missing MODULE_DEVICE_TABLE
+    - drm: mxsfb: check framebuffer pitch
+    - coresight: etm4x: Handle unreachable sink in perf mode
+    - xhci: don't create endpoint debugfs entry before ring buffer is set.
+    - net: dsa: rtl8366: Check validity of passed VLANs
+    - net: dsa: rtl8366: Refactor VLAN/PVID init
+    - net: dsa: rtl8366: Skip PVID setting if not requested
+    - net: wilc1000: clean up resource in error path of init mon interface
+    - ASoC: tlv320aic32x4: Fix bdiv clock rate derivation
+    - net: dsa: rtl8366rb: Support all 4096 VLANs
+    - spi: omap2-mcspi: Improve performance waiting for CHSTAT
+    - ath6kl: wmi: prevent a shift wrapping bug in ath6kl_wmi_delete_pstream_cmd()
+    - dmaengine: dmatest: Check list for emptiness before access its last entry
+    - misc: mic: scif: Fix error handling path
+    - ALSA: seq: oss: Avoid mutex lock for a long-time ioctl
+    - usb: dwc2: Fix parameter type in function pointer prototype
+    - quota: clear padding in v2r1_mem2diskdqb()
+    - slimbus: core: check get_addr before removing laddr ida
+    - slimbus: core: do not enter to clock pause mode in core
+    - slimbus: qcom-ngd-ctrl: disable ngd in qmi server down callback
+    - ASoC: fsl_sai: Instantiate snd_soc_dai_driver
+    - HID: hid-input: fix stylus battery reporting
+    - nvmem: core: fix possibly memleak when use nvmem_cell_info_to_nvmem_cell()
+    - nl80211: fix OBSS PD min and max offset validation
+    - coresight: etm: perf: Fix warning caused by etm_setup_aux failure
+    - ibmvnic: set up 200GBPS speed
+    - qtnfmac: fix resource leaks on unsupported iftype error return path
+    - iio: adc: stm32-adc: fix runtime autosuspend delay when slow polling
+    - net: enic: Cure the enic api locking trainwreck
+    - mfd: sm501: Fix leaks in probe()
+    - iwlwifi: mvm: split a print to avoid a WARNING in ROC
+    - usb: gadget: f_ncm: fix ncm_bitrate for SuperSpeed and above.
+    - usb: gadget: u_ether: enable qmult on SuperSpeed Plus as well
+    - nl80211: fix non-split wiphy information
+    - usb: dwc2: Fix INTR OUT transfers in DDMA mode.
+    - scsi: target: tcmu: Fix warning: 'page' may be used uninitialized
+    - scsi: be2iscsi: Fix a theoretical leak in beiscsi_create_eqs()
+    - ipmi_si: Fix wrong return value in try_smi_init()
+    - platform/x86: mlx-platform: Remove PSU EEPROM configuration
+    - mwifiex: fix double free
+    - ipvs: clear skb->tstamp in forwarding path
+    - net: korina: fix kfree of rx/tx descriptor array
+    - netfilter: nf_log: missing vlan offload tag and proto
+    - mm/swapfile.c: fix potential memory leak in sys_swapon
+    - mm/memcg: fix device private memcg accounting
+    - mm, oom_adj: don't loop through tasks in __set_oom_adj when not necessary
+    - fs: fix NULL dereference due to data race in prepend_path()
+    - selftests/ftrace: Change synthetic event name for inter-event-combined test
+    - i3c: master add i3c_master_attach_boardinfo to preserve boardinfo
+    - IB/mlx4: Fix starvation in paravirt mux/demux
+    - IB/mlx4: Adjust delayed work when a dup is observed
+    - powerpc/pseries: Fix missing of_node_put() in rng_init()
+    - powerpc/icp-hv: Fix missing of_node_put() in success path
+    - RDMA/ucma: Fix locking for ctx->events_reported
+    - RDMA/ucma: Add missing locking around rdma_leave_multicast()
+    - mtd: lpddr: fix excessive stack usage with clang
+    - RDMA/hns: Add a check for current state before modifying QP
+    - RDMA/umem: Fix signature of stub ib_umem_find_best_pgsz()
+    - powerpc/pseries: explicitly reschedule during drmem_lmb list traversal
+    - pseries/drmem: don't cache node id in drmem_lmb struct
+    - RDMA/mlx5: Fix potential race between destroy and CQE poll
+    - mtd: mtdoops: Don't write panic data twice
+    - ARM: 9007/1: l2c: fix prefetch bits init in L2X0_AUX_CTRL using DT values
+    - arc: plat-hsdk: fix kconfig dependency warning when !RESET_CONTROLLER
+    - ida: Free allocated bitmap in error path
+    - xfs: limit entries returned when counting fsmap records
+    - xfs: fix deadlock and streamline xfs_getfsmap performance
+    - xfs: fix high key handling in the rt allocator's query_range function
+    - RDMA/umem: Fix ib_umem_find_best_pgsz() for mappings that cross a page
+      boundary
+    - RDMA/umem: Prevent small pages from being returned by
+      ib_umem_find_best_pgsz()
+    - RDMA/qedr: Fix qp structure memory leak
+    - RDMA/qedr: Fix use of uninitialized field
+    - RDMA/qedr: Fix return code if accept is called on a destroyed qp
+    - RDMA/qedr: Fix inline size returned for iWARP
+    - powerpc/book3s64/hash/4k: Support large linear mapping range with 4K
+    - powerpc/tau: Use appropriate temperature sample interval
+    - powerpc/tau: Convert from timer to workqueue
+    - powerpc/tau: Remove duplicated set_thresholds() call
+    - powerpc/tau: Check processor type before enabling TAU interrupt
+    - powerpc/tau: Disable TAU between measurements
+    - powerpc/64s/radix: Fix mm_cpumask trimming race vs kthread_use_mm
+    - RDMA/cma: Remove dead code for kernel rdmacm multicast
+    - RDMA/cma: Consolidate the destruction of a cma_multicast in one place
+    - perf intel-pt: Fix "context_switch event has no tid" error
+    - RDMA/hns: Set the unsupported wr opcode
+    - RDMA/mlx5: Disable IB_DEVICE_MEM_MGT_EXTENSIONS if IB_WR_REG_MR can't work
+    - i40iw: Add support to make destroy QP synchronous
+    - perf stat: Skip duration_time in setup_system_wide
+    - RDMA/hns: Fix the wrong value of rnr_retry when querying qp
+    - RDMA/hns: Fix missing sq_sig_type when querying QP
+    - mtd: rawnand: vf610: disable clk on error handling path in probe
+    - mtd: spinand: gigadevice: Only one dummy byte in QUADIO
+    - mtd: spinand: gigadevice: Add QE Bit
+    - kdb: Fix pager search for multi-line strings
+    - overflow: Include header file with SIZE_MAX declaration
+    - RDMA/ipoib: Set rtnl_link_ops for ipoib interfaces
+    - powerpc/perf: Exclude pmc5/6 from the irrelevant PMU group constraints
+    - powerpc/perf/hv-gpci: Fix starting index value
+    - i3c: master: Fix error return in cdns_i3c_master_probe()
+    - cpufreq: powernv: Fix frame-size-overflow in powernv_cpufreq_reboot_notifier
+    - IB/rdmavt: Fix sizeof mismatch
+    - RDMA/rxe: Fix skb lifetime in rxe_rcv_mcast_pkt()
+    - maiblox: mediatek: Fix handling of platform_get_irq() error
+    - selftests/powerpc: Fix eeh-basic.sh exit codes
+    - f2fs: wait for sysfs kobject removal before freeing f2fs_sb_info
+    - RDMA/rxe: Handle skb_clone() failure in rxe_recv.c
+    - mm/page_owner: change split_page_owner to take a count
+    - lib/crc32.c: fix trivial typo in preprocessor condition
+    - ramfs: fix nommu mmap with gaps in the page cache
+    - rapidio: fix error handling path
+    - rapidio: fix the missed put_device() for rio_mport_add_riodev
+    - mailbox: avoid timer start from callback
+    - i2c: rcar: Auto select RESET_CONTROLLER
+    - clk: meson: g12a: mark fclk_div2 as critical
+    - PCI: aardvark: Check for errors from pci_bridge_emul_init() call
+    - PCI: iproc: Set affinity mask on MSI interrupts
+    - rpmsg: smd: Fix a kobj leak in in qcom_smd_parse_edge()
+    - PCI/IOV: Mark VFs as not implementing PCI_COMMAND_MEMORY
+    - vfio/pci: Decouple PCI_COMMAND_MEMORY bit checks from is_virtfn
+    - clk: qcom: gcc-sdm660: Fix wrong parent_map
+    - clk: keystone: sci-clk: fix parsing assigned-clock data during probe
+    - pwm: img: Fix null pointer access in probe
+    - clk: rockchip: Initialize hw to error to avoid undefined behavior
+    - clk: mediatek: add UART0 clock support
+    - module: statically initialize init section freeing data
+    - clk: at91: clk-main: update key before writing AT91_CKGR_MOR
+    - clk: bcm2835: add missing release if devm_clk_hw_register fails
+    - watchdog: Fix memleak in watchdog_cdev_register
+    - watchdog: Use put_device on error
+    - watchdog: sp5100: Fix definition of EFCH_PM_DECODEEN3
+    - svcrdma: fix bounce buffers for unaligned offsets and multiple pages
+    - ext4: limit entries returned when counting fsmap records
+    - vfio/pci: Clear token on bypass registration failure
+    - vfio iommu type1: Fix memory leak in vfio_iommu_type1_pin_pages
+    - clk: imx8mq: Fix usdhc parents order
+    - SUNRPC: fix copying of multiple pages in gss_read_proxy_verf()
+    - Input: imx6ul_tsc - clean up some errors in imx6ul_tsc_resume()
+    - Input: stmfts - fix a & vs && typo
+    - Input: ep93xx_keypad - fix handling of platform_get_irq() error
+    - Input: omap4-keypad - fix handling of platform_get_irq() error
+    - Input: twl4030_keypad - fix handling of platform_get_irq() error
+    - Input: sun4i-ps2 - fix handling of platform_get_irq() error
+    - KVM: x86: emulating RDPID failure shall return #UD rather than #GP
+    - scsi: bfa: Fix error return in bfad_pci_init()
+    - netfilter: conntrack: connection timeout after re-register
+    - netfilter: ebtables: Fixes dropping of small packets in bridge nat
+    - netfilter: nf_fwd_netdev: clear timestamp in forwarding path
+    - arm64: dts: meson: vim3: correct led polarity
+    - ARM: dts: imx6sl: fix rng node
+    - ARM: at91: pm: of_node_put() after its usage
+    - ARM: s3c24xx: fix mmc gpio lookup tables
+    - ARM: dts: sun8i: r40: bananapi-m2-ultra: Fix dcdc1 regulator
+    - arm64: dts: allwinner: h5: remove Mali GPU PMU module
+    - memory: omap-gpmc: Fix a couple off by ones
+    - memory: omap-gpmc: Fix build error without CONFIG_OF
+    - memory: fsl-corenet-cf: Fix handling of platform_get_irq() error
+    - arm64: dts: imx8mq: Add missing interrupts to GPC
+    - arm64: dts: qcom: msm8916: Remove one more thermal trip point unit name
+    - arm64: dts: qcom: pm8916: Remove invalid reg size from wcd_codec
+    - arm64: dts: qcom: msm8916: Fix MDP/DSI interrupts
+    - arm64: dts: renesas: r8a77990: Fix MSIOF1 DMA channels
+    - arm64: dts: renesas: r8a774c0: Fix MSIOF1 DMA channels
+    - arm64: dts: actions: limit address range for pinctrl node
+    - ARM: dts: owl-s500: Fix incorrect PPI interrupt specifiers
+    - soc: fsl: qbman: Fix return value on success
+    - ARM: OMAP2+: Restore MPU power domain if cpu_cluster_pm_enter() fails
+    - arm64: dts: zynqmp: Remove additional compatible string for i2c IPs
+    - ARM: dts: meson8: remove two invalid interrupt lines from the GPU node
+    - lightnvm: fix out-of-bounds write to array devices->info[]
+    - powerpc/powernv/dump: Fix race while processing OPAL dump
+    - powerpc/pseries: Avoid using addr_to_pfn in real mode
+    - nvmet: fix uninitialized work for zero kato
+    - NTB: hw: amd: fix an issue about leak system resources
+    - sched/features: Fix !CONFIG_JUMP_LABEL case
+    - perf: correct SNOOPX field offset
+    - i2c: core: Restore acpi_walk_dep_device_list() getting called after
+      registering the ACPI i2c devs
+    - md/bitmap: fix memory leak of temporary bitmap
+    - block: ratelimit handle_bad_sector() message
+    - crypto: ccp - fix error handling
+    - x86/asm: Replace __force_order with a memory clobber
+    - x86/mce: Add Skylake quirk for patrol scrub reported errors
+    - media: firewire: fix memory leak
+    - media: ati_remote: sanity check for both endpoints
+    - media: st-delta: Fix reference count leak in delta_run_work
+    - media: sti: Fix reference count leaks
+    - media: exynos4-is: Fix several reference count leaks due to
+      pm_runtime_get_sync
+    - media: exynos4-is: Fix a reference count leak due to pm_runtime_get_sync
+    - media: exynos4-is: Fix a reference count leak
+    - media: vsp1: Fix runtime PM imbalance on error
+    - media: platform: s3c-camif: Fix runtime PM imbalance on error
+    - media: platform: sti: hva: Fix runtime PM imbalance on error
+    - media: bdisp: Fix runtime PM imbalance on error
+    - media: media/pci: prevent memory leak in bttv_probe
+    - x86/mce: Make mce_rdmsrl() panic on an inaccessible MSR
+    - media: uvcvideo: Ensure all probed info is returned to v4l2
+    - mmc: sdio: Check for CISTPL_VERS_1 buffer size
+    - media: saa7134: avoid a shift overflow
+    - media: venus: fixes for list corruption
+    - fs: dlm: fix configfs memory leak
+    - media: venus: core: Fix runtime PM imbalance in venus_probe
+    - ntfs: add check for mft record size in superblock
+    - ip_gre: set dev->hard_header_len and dev->needed_headroom properly
+    - mac80211: handle lack of sband->bitrates in rates
+    - PM: hibernate: remove the bogus call to get_gendisk() in software_resume()
+    - scsi: mvumi: Fix error return in mvumi_io_attach()
+    - scsi: target: core: Add CONTROL field for trace events
+    - mic: vop: copy data to kernel space then write to io memory
+    - misc: vop: add round_up(x,4) for vring_size to avoid kernel panic
+    - usb: dwc3: Add splitdisable quirk for Hisilicon Kirin Soc
+    - usb: gadget: function: printer: fix use-after-free in __lock_acquire
+    - udf: Limit sparing table size
+    - udf: Avoid accessing uninitialized data on failed inode read
+    - rtw88: increse the size of rx buffer size
+    - USB: cdc-acm: handle broken union descriptors
+    - usb: dwc3: simple: add support for Hikey 970
+    - can: flexcan: flexcan_chip_stop(): add error handling and propagate error
+      value
+    - ath9k: hif_usb: fix race condition between usb_get_urb() and
+      usb_kill_anchored_urbs()
+    - drm/panfrost: add amlogic reset quirk callback
+    - bpf: Limit caller's stack depth 256 for subprogs with tailcalls
+    - misc: rtsx: Fix memory leak in rtsx_pci_probe
+    - reiserfs: only call unlock_new_inode() if I_NEW
+    - opp: Prevent memory leak in dev_pm_opp_attach_genpd()
+    - xfs: make sure the rt allocator doesn't run off the end
+    - usb: ohci: Default to per-port over-current protection
+    - Bluetooth: Only mark socket zapped after unlocking
+    - drm/msm/a6xx: fix a potential overflow issue
+    - iomap: fix WARN_ON_ONCE() from unprivileged users
+    - scsi: ibmvfc: Fix error return in ibmvfc_probe()
+    - scsi: qla2xxx: Warn if done() or free() are called on an already freed srb
+    - selftests/bpf: Fix test_sysctl_loop{1, 2} failure due to clang change
+    - brcmsmac: fix memory leak in wlc_phy_attach_lcnphy
+    - rtl8xxxu: prevent potential memory leak
+    - Fix use after free in get_capset_info callback.
+    - HID: ite: Add USB id match for Acer One S1003 keyboard dock
+    - scsi: qedf: Return SUCCESS if stale rport is encountered
+    - scsi: qedi: Protect active command list to avoid list corruption
+    - scsi: qedi: Fix list_del corruption while removing active I/O
+    - fbmem: add margin check to fb_check_caps()
+    - tty: ipwireless: fix error handling
+    - Bluetooth: btusb: Fix memleak in btusb_mtk_submit_wmt_recv_urb
+    - ipvs: Fix uninit-value in do_ip_vs_set_ctl()
+    - reiserfs: Fix memory leak in reiserfs_parse_options()
+    - mwifiex: don't call del_timer_sync() on uninitialized timer
+    - ALSA: hda/ca0132 - Add AE-7 microphone selection commands.
+    - ALSA: hda/ca0132 - Add new quirk ID for SoundBlaster AE-7.
+    - scsi: smartpqi: Avoid crashing kernel for controller issues
+    - brcm80211: fix possible memleak in brcmf_proto_msgbuf_attach
+    - usb: core: Solve race condition in anchor cleanup functions
+    - scsi: ufs: ufs-qcom: Fix race conditions caused by ufs_qcom_testbus_config()
+    - dmaengine: dw: Add DMA-channels mask cell support
+    - dmaengine: dw: Activate FIFO-mode for memory peripherals only
+    - ath10k: check idx validity in __ath10k_htt_rx_ring_fill_n()
+    - net: korina: cast KSEG0 address to pointer in kfree
+    - s390/qeth: don't let HW override the configured port role
+    - tty: serial: lpuart: fix lpuart32_write usage
+    - tty: serial: fsl_lpuart: fix lpuart32_poll_get_char
+    - usb: cdc-acm: add quirk to blacklist ETAS ES58X devices
+    - USB: cdc-wdm: Make wdm_flush() interruptible and add wdm_fsync().
+    - usb: cdns3: gadget: free interrupt after gadget has deleted
+    - eeprom: at25: set minimum read/write access stride to 1
+    - usb: gadget: f_ncm: allow using NCM in SuperSpeed Plus gadgets.
+    - Linux 5.4.73
+  * Focal update: v5.4.72 upstream stable release (LP: #1902111)
+    - perf cs-etm: Move definition of 'traceid_list' global variable from header
+      file
+    - btrfs: don't pass system_chunk into can_overcommit
+    - btrfs: take overcommit into account in inc_block_group_ro
+    - ARM: 8939/1: kbuild: use correct nm executable
+    - ACPI: Always build evged in
+    - Bluetooth: Consolidate encryption handling in hci_encrypt_cfm
+    - Bluetooth: Fix update of connection state in `hci_encrypt_cfm`
+    - Bluetooth: Disconnect if E0 is used for Level 4
+    - media: usbtv: Fix refcounting mixup
+    - USB: serial: option: add Cellient MPL200 card
+    - USB: serial: option: Add Telit FT980-KS composition
+    - staging: comedi: check validity of wMaxPacketSize of usb endpoints found
+    - USB: serial: pl2303: add device-id for HP GC device
+    - USB: serial: ftdi_sio: add support for FreeCalypso JTAG+UART adapters
+    - reiserfs: Initialize inode keys properly
+    - reiserfs: Fix oops during mount
+    - xen/events: don't use chip_data for legacy IRQs
+    - crypto: bcm - Verify GCM/CCM key length in setkey
+    - crypto: qat - check cipher length for aead AES-CBC-HMAC-SHA
+    - Linux 5.4.72
+  * Focal update: v5.4.71 upstream stable release (LP: #1902110)
+    - fbdev, newport_con: Move FONT_EXTRA_WORDS macros into linux/font.h
+    - Fonts: Support FONT_EXTRA_WORDS macros for built-in fonts
+    - fbcon: Fix global-out-of-bounds read in fbcon_get_font()
+    - Revert "ravb: Fixed to be able to unload modules"
+    - io_uring: Fix resource leaking when kill the process
+    - io_uring: Fix missing smp_mb() in io_cancel_async_work()
+    - io_uring: Fix remove irrelevant req from the task_list
+    - io_uring: Fix double list add in io_queue_async_work()
+    - net: wireless: nl80211: fix out-of-bounds access in nl80211_del_key()
+    - drm/nouveau/mem: guard against NULL pointer access in mem_del
+    - vhost: Don't call access_ok() when using IOTLB
+    - vhost: Use vhost_get_used_size() in vhost_vring_set_addr()
+    - usermodehelper: reset umask to default before executing user process
+    - Platform: OLPC: Fix memleak in olpc_ec_probe
+    - platform/x86: intel-vbtn: Fix SW_TABLET_MODE always reporting 1 on the HP
+      Pavilion 11 x360
+    - platform/x86: thinkpad_acpi: initialize tp_nvram_state variable
+    - bpf: Fix sysfs export of empty BTF section
+    - bpf: Prevent .BTF section elimination
+    - platform/x86: intel-vbtn: Switch to an allow-list for SW_TABLET_MODE
+      reporting
+    - platform/x86: thinkpad_acpi: re-initialize ACPI buffer size when reuse
+    - driver core: Fix probe_count imbalance in really_probe()
+    - perf test session topology: Fix data path
+    - perf top: Fix stdio interface input handling with glibc 2.28+
+    - i2c: i801: Exclude device from suspend direct complete optimization
+    - arm64: dts: stratix10: add status to qspi dts node
+    - Btrfs: send, allow clone operations within the same file
+    - Btrfs: send, fix emission of invalid clone operations within the same file
+    - btrfs: volumes: Use more straightforward way to calculate map length
+    - btrfs: Ensure we trim ranges across block group boundary
+    - btrfs: fix RWF_NOWAIT write not failling when we need to cow
+    - btrfs: allow btrfs_truncate_block() to fallback to nocow for data space
+      reservation
+    - nvme-core: put ctrl ref when module ref get fail
+    - macsec: avoid use-after-free in macsec_handle_frame()
+    - mm/khugepaged: fix filemap page_to_pgoff(page) != offset
+    - net: introduce helper sendpage_ok() in include/linux/net.h
+    - tcp: use sendpage_ok() to detect misused .sendpage
+    - nvme-tcp: check page by sendpage_ok() before calling kernel_sendpage()
+    - xfrmi: drop ignore_df check before updating pmtu
+    - cifs: Fix incomplete memory allocation on setxattr path
+    - i2c: meson: fix clock setting overwrite
+    - i2c: meson: fixup rate calculation with filter delay
+    - i2c: owl: Clear NACK and BUS error bits
+    - sctp: fix sctp_auth_init_hmacs() error path
+    - team: set dev->needed_headroom in team_setup_by_port()
+    - net: team: fix memory leak in __team_options_register
+    - openvswitch: handle DNAT tuple collision
+    - drm/amdgpu: prevent double kfree ttm->sg
+    - iommu/vt-d: Fix lockdep splat in iommu_flush_dev_iotlb()
+    - xfrm: clone XFRMA_SET_MARK in xfrm_do_migrate
+    - xfrm: clone XFRMA_REPLAY_ESN_VAL in xfrm_do_migrate
+    - xfrm: clone XFRMA_SEC_CTX in xfrm_do_migrate
+    - xfrm: clone whole liftime_cur structure in xfrm_do_migrate
+    - net: stmmac: removed enabling eee in EEE set callback
+    - platform/x86: fix kconfig dependency warning for FUJITSU_LAPTOP
+    - xfrm: Use correct address family in xfrm_state_find
+    - iavf: use generic power management
+    - iavf: Fix incorrect adapter get in iavf_resume
+    - net: ethernet: cavium: octeon_mgmt: use phy_start and phy_stop
+    - bonding: set dev->needed_headroom in bond_setup_by_slave()
+    - mdio: fix mdio-thunder.c dependency & build error
+    - mlxsw: spectrum_acl: Fix mlxsw_sp_acl_tcam_group_add()'s error path
+    - r8169: fix RTL8168f/RTL8411 EPHY config
+    - net: usb: ax88179_178a: fix missing stop entry in driver_info
+    - virtio-net: don't disable guest csum when disable LRO
+    - net/mlx5: Avoid possible free of command entry while timeout comp handler
+    - net/mlx5: Fix request_irqs error flow
+    - net/mlx5e: Add resiliency in Striding RQ mode for packets larger than MTU
+    - net/mlx5e: Fix VLAN cleanup flow
+    - net/mlx5e: Fix VLAN create flow
+    - rxrpc: Fix rxkad token xdr encoding
+    - rxrpc: Downgrade the BUG() for unsupported token type in rxrpc_read()
+    - rxrpc: Fix some missing _bh annotations on locking conn->state_lock
+    - rxrpc: The server keyring isn't network-namespaced
+    - rxrpc: Fix server keyring leak
+    - perf: Fix task_function_call() error handling
+    - mmc: core: don't set limits.discard_granularity as 0
+    - mm: khugepaged: recalculate min_free_kbytes after memory hotplug as expected
+      by khugepaged
+    - tcp: fix receive window update in tcp_add_backlog()
+    - net/core: check length before updating Ethertype in skb_mpls_{push,pop}
+    - net/tls: race causes kernel panic
+    - net/mlx5e: Fix driver's declaration to support GRE offload
+    - Input: ati_remote2 - add missing newlines when printing module parameters
+    - net: usb: rtl8150: set random MAC address when set_ethernet_addr() fails
+    - net_sched: defer tcf_idr_insert() in tcf_action_init_1()
+    - net_sched: commit action insertions together
+    - Linux 5.4.71
+  * kci_test_encap_fou() in rtnetlink.sh from kselftests/net failed with "FAIL:
+    can't add fou port 7777, skipping test" (LP: #1891421)
+    - selftests: rtnetlink: load fou module for kci_test_encap_fou() test
+  * alsa/hda/realtek - The front Mic on a HP machine doesn't work (LP: #1899508)
+    - ALSA: hda/realtek - The front Mic on a HP machine doesn't work
+  * Enable brightness control on HP DreamColor panel (LP: #1898865)
+    - drm/i915/dpcd_bl: Unbreak enable_dpcd_backlight modparam
+    - SAUCE: drm/i915/dpcd_bl: Skip testing control capability with force DPCD
+      quirk
+    - SAUCE: drm/dp: HP DreamColor panel brigntness fix
+  * Fix non-working Intel NVMe after S3 (LP: #1900847)
+    - SAUCE: PCI: Enable ACS quirk on all CML root ports
+  * bcache: Issues with large IO wait in bch_mca_scan() when shrinker is enabled
+    (LP: #1898786)
+    - bcache: remove member accessed from struct btree
+    - bcache: reap c->btree_cache_freeable from the tail in bch_mca_scan()
+    - bcache: reap from tail of c->btree_cache in bch_mca_scan()
+  * Improve descriptions for XFAIL cases in kselftests/net/psock_snd
+    (LP: #1900088)
+    - selftests/net: improve descriptions for XFAIL cases in psock_snd.sh
+  * ceph: fix inode number handling on arches with 32-bit ino_t (LP: #1899582)
+    - ceph: fix inode number handling on arches with 32-bit ino_t
+  * Fix system reboot when disconnecting WiFi (LP: #1899726)
+    - iwlwifi: msix: limit max RX queues for 9000 family
+  * Fix broken MSI interrupt after HDA controller was suspended (LP: #1899586)
+    - ALSA: hda: fix jack detection with Realtek codecs when in D3
+  * Focal update: v5.4.70 upstream stable release (LP: #1900632)
+    - btrfs: fix filesystem corruption after a device replace
+    - mmc: sdhci: Workaround broken command queuing on Intel GLK based IRBIS
+      models
+    - USB: gadget: f_ncm: Fix NDP16 datagram validation
+    - gpio: siox: explicitly support only threaded irqs
+    - gpio: mockup: fix resource leak in error path
+    - gpio: tc35894: fix up tc35894 interrupt configuration
+    - clk: socfpga: stratix10: fix the divider for the emac_ptp_free_clk
+    - vsock/virtio: add transport parameter to the
+      virtio_transport_reset_no_sock()
+    - net: virtio_vsock: Enhance connection semantics
+    - xfs: trim IO to found COW extent limit
+    - Input: i8042 - add nopnp quirk for Acer Aspire 5 A515
+    - iio: adc: qcom-spmi-adc5: fix driver name
+    - ftrace: Move RCU is watching check after recursion check
+    - memstick: Skip allocating card when removing host
+    - drm/amdgpu: restore proper ref count in amdgpu_display_crtc_set_config
+    - clocksource/drivers/timer-gx6605s: Fixup counter reload
+    - libbpf: Remove arch-specific include path in Makefile
+    - drivers/net/wan/hdlc_fr: Add needed_headroom for PVC devices
+    - drm/sun4i: mixer: Extend regmap max_register
+    - net: dec: de2104x: Increase receive ring size for Tulip
+    - rndis_host: increase sleep time in the query-response loop
+    - nvme-core: get/put ctrl and transport module in nvme_dev_open/release()
+    - fuse: fix the ->direct_IO() treatment of iov_iter
+    - drivers/net/wan/lapbether: Make skb->protocol consistent with the header
+    - drivers/net/wan/hdlc: Set skb->protocol before transmitting
+    - mac80211: Fix radiotap header channel flag for 6GHz band
+    - mac80211: do not allow bigger VHT MPDUs than the hardware supports
+    - tracing: Make the space reserved for the pid wider
+    - tools/io_uring: fix compile breakage
+    - spi: fsl-espi: Only process interrupts for expected events
+    - nvme-pci: fix NULL req in completion handler
+    - nvme-fc: fail new connections to a deleted host or remote port
+    - gpio: sprd: Clear interrupt when setting the type as edge
+    - phy: ti: am654: Fix a leak in serdes_am654_probe()
+    - pinctrl: mvebu: Fix i2c sda definition for 98DX3236
+    - nfs: Fix security label length not being reset
+    - clk: tegra: Always program PLL_E when enabled
+    - clk: samsung: exynos4: mark 'chipid' clock as CLK_IGNORE_UNUSED
+    - iommu/exynos: add missing put_device() call in exynos_iommu_of_xlate()
+    - gpio/aspeed-sgpio: enable access to all 80 input & output sgpios
+    - gpio/aspeed-sgpio: don't enable all interrupts by default
+    - gpio: aspeed: fix ast2600 bank properties
+    - i2c: cpm: Fix i2c_ram structure
+    - Input: trackpoint - enable Synaptics trackpoints
+    - scripts/dtc: only append to HOST_EXTRACFLAGS instead of overwriting
+    - random32: Restore __latent_entropy attribute on net_rand_state
+    - block/diskstats: more accurate approximation of io_ticks for slow disks
+    - mm: replace memmap_context by meminit_context
+    - mm: don't rely on system state to detect hot-plug operations
+    - nvme: Cleanup and rename nvme_block_nr()
+    - nvme: Introduce nvme_lba_to_sect()
+    - nvme: consolidate chunk_sectors settings
+    - epoll: do not insert into poll queues until all sanity checks are done
+    - epoll: replace ->visited/visited_list with generation count
+    - epoll: EPOLL_CTL_ADD: close the race in decision to take fast path
+    - ep_create_wakeup_source(): dentry name can change under you...
+    - netfilter: ctnetlink: add a range check for l3/l4 protonum
+    - Linux 5.4.70
+  * Focal update: v5.4.69 upstream stable release (LP: #1900624)
+    - kernel/sysctl-test: Add null pointer test for sysctl.c:proc_dointvec()
+    - selinux: allow labeling before policy is loaded
+    - media: mc-device.c: fix memleak in media_device_register_entity
+    - drm/amd/display: Do not double-buffer DTO adjustments
+    - drm/amdkfd: Fix race in gfx10 context restore handler
+    - dma-fence: Serialise signal enabling (dma_fence_enable_sw_signaling)
+    - scsi: qla2xxx: Add error handling for PLOGI ELS passthrough
+    - ath10k: fix array out-of-bounds access
+    - ath10k: fix memory leak for tpc_stats_final
+    - PCI/IOV: Serialize sysfs sriov_numvfs reads vs writes
+    - mm: fix double page fault on arm64 if PTE_AF is cleared
+    - scsi: aacraid: fix illegal IO beyond last LBA
+    - m68k: q40: Fix info-leak in rtc_ioctl
+    - xfs: fix inode fork extent count overflow
+    - gma/gma500: fix a memory disclosure bug due to uninitialized bytes
+    - ASoC: kirkwood: fix IRQ error handling
+    - soundwire: intel/cadence: fix startup sequence
+    - media: smiapp: Fix error handling at NVM reading
+    - drm/amd/display: Free gamma after calculating legacy transfer function
+    - xfs: properly serialise fallocate against AIO+DIO
+    - leds: mlxreg: Fix possible buffer overflow
+    - dm table: do not allow request-based DM to stack on partitions
+    - PM / devfreq: tegra30: Fix integer overflow on CPU's freq max out
+    - scsi: fnic: fix use after free
+    - powerpc/64s: Always disable branch profiling for prom_init.o
+    - net: silence data-races on sk_backlog.tail
+    - dax: Fix alloc_dax_region() compile warning
+    - iomap: Fix overflow in iomap_page_mkwrite
+    - f2fs: avoid kernel panic on corruption test
+    - clk/ti/adpll: allocate room for terminating null
+    - drm/amdgpu/powerplay: fix AVFS handling with custom powerplay table
+    - ice: Fix to change Rx/Tx ring descriptor size via ethtool with DCBx
+    - mtd: cfi_cmdset_0002: don't free cfi->cfiq in error path of
+      cfi_amdstd_setup()
+    - mfd: mfd-core: Protect against NULL call-back function pointer
+    - drm/amdgpu/powerplay/smu7: fix AVFS handling with custom powerplay table
+    - tpm_crb: fix fTPM on AMD Zen+ CPUs
+    - tracing: Verify if trace array exists before destroying it.
+    - tracing: Adding NULL checks for trace_array descriptor pointer
+    - bcache: fix a lost wake-up problem caused by mca_cannibalize_lock
+    - dmaengine: mediatek: hsdma_probe: fixed a memory leak when devm_request_irq
+      fails
+    - x86/kdump: Always reserve the low 1M when the crashkernel option is
+      specified
+    - RDMA/qedr: Fix potential use after free
+    - RDMA/i40iw: Fix potential use after free
+    - PCI: Avoid double hpmemsize MMIO window assignment
+    - fix dget_parent() fastpath race
+    - xfs: fix attr leaf header freemap.size underflow
+    - RDMA/iw_cgxb4: Fix an error handling path in 'c4iw_connect()'
+    - ubi: Fix producing anchor PEBs
+    - mmc: core: Fix size overflow for mmc partitions
+    - gfs2: clean up iopen glock mess in gfs2_create_inode
+    - scsi: pm80xx: Cleanup command when a reset times out
+    - mt76: do not use devm API for led classdev
+    - mt76: add missing locking around ampdu action
+    - debugfs: Fix !DEBUG_FS debugfs_create_automount
+    - SUNRPC: Capture completion of all RPC tasks
+    - CIFS: Use common error handling code in smb2_ioctl_query_info()
+    - CIFS: Properly process SMB3 lease breaks
+    - f2fs: stop GC when the victim becomes fully valid
+    - ASoC: max98090: remove msleep in PLL unlocked workaround
+    - xtensa: fix system_call interaction with ptrace
+    - s390: avoid misusing CALL_ON_STACK for task stack setup
+    - xfs: fix realtime file data space leak
+    - drm/amdgpu: fix calltrace during kmd unload(v3)
+    - arm64: insn: consistently handle exit text
+    - selftests/bpf: De-flake test_tcpbpf
+    - kernel/notifier.c: intercept duplicate registrations to avoid infinite loops
+    - kernel/sys.c: avoid copying possible padding bytes in copy_to_user
+    - KVM: arm/arm64: vgic: Fix potential double free dist->spis in
+      __kvm_vgic_destroy()
+    - module: Remove accidental change of module_enable_x()
+    - xfs: fix log reservation overflows when allocating large rt extents
+    - ALSA: hda: enable regmap internal locking
+    - tipc: fix link overflow issue at socket shutdown
+    - vcc_seq_next should increase position index
+    - neigh_stat_seq_next() should increase position index
+    - rt_cpu_seq_next should increase position index
+    - ipv6_route_seq_next should increase position index
+    - drm/mcde: Handle pending vblank while disabling display
+    - seqlock: Require WRITE_ONCE surrounding raw_seqcount_barrier
+    - drm/scheduler: Avoid accessing freed bad job.
+    - media: ti-vpe: cal: Restrict DMA to avoid memory corruption
+    - opp: Replace list_kref with a local counter
+    - scsi: qla2xxx: Fix stuck session in GNL
+    - sctp: move trace_sctp_probe_path into sctp_outq_sack
+    - ACPI: EC: Reference count query handlers under lock
+    - scsi: ufs: Make ufshcd_add_command_trace() easier to read
+    - scsi: ufs: Fix a race condition in the tracing code
+    - drm/amd/display: Initialize DSC PPS variables to 0
+    - i2c: tegra: Prevent interrupt triggering after transfer timeout
+    - btrfs: tree-checker: Check leaf chunk item size
+    - dmaengine: zynqmp_dma: fix burst length configuration
+    - s390/cpum_sf: Use kzalloc and minor changes
+    - nfsd: Fix a soft lockup race in nfsd_file_mark_find_or_create()
+    - powerpc/eeh: Only dump stack once if an MMIO loop is detected
+    - Bluetooth: btrtl: Use kvmalloc for FW allocations
+    - tracing: Set kernel_stack's caller size properly
+    - ARM: 8948/1: Prevent OOB access in stacktrace
+    - ar5523: Add USB ID of SMCWUSBT-G2 wireless adapter
+    - ceph: ensure we have a new cap before continuing in fill_inode
+    - selftests/ftrace: fix glob selftest
+    - tools/power/x86/intel_pstate_tracer: changes for python 3 compatibility
+    - Bluetooth: Fix refcount use-after-free issue
+    - mm/swapfile.c: swap_next should increase position index
+    - mm: pagewalk: fix termination condition in walk_pte_range()
+    - Bluetooth: prefetch channel before killing sock
+    - ALSA: hda: Clear RIRB status before reading WP
+    - skbuff: fix a data race in skb_queue_len()
+    - nfsd: Fix a perf warning
+    - drm/amd/display: fix workaround for incorrect double buffer register for DLG
+      ADL and TTU
+    - audit: CONFIG_CHANGE don't log internal bookkeeping as an event
+    - selinux: sel_avc_get_stat_idx should increase position index
+    - drm/omap: fix possible object reference leak
+    - locking/lockdep: Decrement IRQ context counters when removing lock chain
+    - clk: stratix10: use do_div() for 64-bit calculation
+    - crypto: chelsio - This fixes the kernel panic which occurs during a libkcapi
+      test
+    - mt76: clear skb pointers from rx aggregation reorder buffer during cleanup
+    - mt76: fix handling full tx queues in mt76_dma_tx_queue_skb_raw
+    - ALSA: usb-audio: Don't create a mixer element with bogus volume range
+    - perf test: Fix test trace+probe_vfs_getname.sh on s390
+    - RDMA/rxe: Fix configuration of atomic queue pair attributes
+    - KVM: x86: fix incorrect comparison in trace event
+    - KVM: nVMX: Hold KVM's srcu lock when syncing vmcs12->shadow
+    - dmaengine: stm32-mdma: use vchan_terminate_vdesc() in .terminate_all
+    - media: staging/imx: Missing assignment in
+      imx_media_capture_device_register()
+    - x86/pkeys: Add check for pkey "overflow"
+    - bpf: Remove recursion prevention from rcu free callback
+    - dmaengine: stm32-dma: use vchan_terminate_vdesc() in .terminate_all
+    - dmaengine: tegra-apb: Prevent race conditions on channel's freeing
+    - soundwire: bus: disable pm_runtime in sdw_slave_delete
+    - drm/amd/display: dal_ddc_i2c_payloads_create can fail causing panic
+    - drm/omap: dss: Cleanup DSS ports on initialisation failure
+    - iavf: use tc_cls_can_offload_and_chain0() instead of chain check
+    - firmware: arm_sdei: Use cpus_read_lock() to avoid races with cpuhp
+    - random: fix data races at timer_rand_state
+    - bus: hisi_lpc: Fixup IO ports addresses to avoid use-after-free in host
+      removal
+    - ASoC: SOF: ipc: check ipc return value before data copy
+    - media: go7007: Fix URB type for interrupt handling
+    - Bluetooth: guard against controllers sending zero'd events
+    - timekeeping: Prevent 32bit truncation in scale64_check_overflow()
+    - powerpc/book3s64: Fix error handling in mm_iommu_do_alloc()
+    - drm/amd/display: fix image corruption with ODM 2:1 DSC 2 slice
+    - ext4: fix a data race at inode->i_disksize
+    - perf jevents: Fix leak of mapfile memory
+    - mm: avoid data corruption on CoW fault into PFN-mapped VMA
+    - drm/amdgpu: increase atombios cmd timeout
+    - ARM: OMAP2+: Handle errors for cpu_pm
+    - clk: imx: Fix division by zero warning on pfdv2
+    - cpu-topology: Fix the potential data corruption
+    - s390/irq: replace setup_irq() by request_irq()
+    - perf cs-etm: Swap packets for instruction samples
+    - perf cs-etm: Correct synthesizing instruction samples
+    - ath10k: use kzalloc to read for ath10k_sdio_hif_diag_read
+    - scsi: aacraid: Disabling TM path and only processing IOP reset
+    - Bluetooth: L2CAP: handle l2cap config request during open state
+    - media: tda10071: fix unsigned sign extension overflow
+    - tty: sifive: Finish transmission before changing the clock
+    - xfs: don't ever return a stale pointer from __xfs_dir3_free_read
+    - xfs: mark dir corrupt when lookup-by-hash fails
+    - ext4: mark block bitmap corrupted when found instead of BUGON
+    - tpm: ibmvtpm: Wait for buffer to be set before proceeding
+    - rtc: sa1100: fix possible race condition
+    - rtc: ds1374: fix possible race condition
+    - nfsd: Don't add locks to closed or closing open stateids
+    - RDMA/cm: Remove a race freeing timewait_info
+    - intel_th: Disallow multi mode on devices where it's broken
+    - KVM: PPC: Book3S HV: Treat TM-related invalid form instructions on P9 like
+      the valid ones
+    - drm/msm: fix leaks if initialization fails
+    - drm/msm/a5xx: Always set an OPP supported hardware value
+    - tracing: Use address-of operator on section symbols
+    - thermal: rcar_thermal: Handle probe error gracefully
+    - KVM: LAPIC: Mark hrtimer for period or oneshot mode to expire in hard
+      interrupt context
+    - perf parse-events: Fix 3 use after frees found with clang ASAN
+    - btrfs: do not init a reloc root if we aren't relocating
+    - btrfs: free the reloc_control in a consistent way
+    - r8169: improve RTL8168b FIFO overflow workaround
+    - serial: 8250_port: Don't service RX FIFO if throttled
+    - serial: 8250_omap: Fix sleeping function called from invalid context during
+      probe
+    - serial: 8250: 8250_omap: Terminate DMA before pushing data on RX timeout
+    - perf cpumap: Fix snprintf overflow check
+    - net: axienet: Convert DMA error handler to a work queue
+    - net: axienet: Propagate failure of DMA descriptor setup
+    - cpufreq: powernv: Fix frame-size-overflow in powernv_cpufreq_work_fn
+    - tools: gpio-hammer: Avoid potential overflow in main
+    - exec: Add exec_update_mutex to replace cred_guard_mutex
+    - exec: Fix a deadlock in strace
+    - selftests/ptrace: add test cases for dead-locks
+    - kernel/kcmp.c: Use new infrastructure to fix deadlocks in execve
+    - proc: Use new infrastructure to fix deadlocks in execve
+    - proc: io_accounting: Use new infrastructure to fix deadlocks in execve
+    - perf: Use new infrastructure to fix deadlocks in execve
+    - nvme-multipath: do not reset on unknown status
+    - nvme: Fix ctrl use-after-free during sysfs deletion
+    - nvme: Fix controller creation races with teardown flow
+    - brcmfmac: Fix double freeing in the fmac usb data path
+    - xfs: prohibit fs freezing when using empty transactions
+    - RDMA/rxe: Set sys_image_guid to be aligned with HW IB devices
+    - IB/iser: Always check sig MR before putting it to the free pool
+    - scsi: hpsa: correct race condition in offload enabled
+    - SUNRPC: Fix a potential buffer overflow in 'svc_print_xprts()'
+    - svcrdma: Fix leak of transport addresses
+    - netfilter: nf_tables: silence a RCU-list warning in nft_table_lookup()
+    - PCI: Use ioremap(), not phys_to_virt() for platform ROM
+    - ubifs: ubifs_jnl_write_inode: Fix a memory leak bug
+    - ubifs: ubifs_add_orphan: Fix a memory leak bug
+    - ubifs: Fix out-of-bounds memory access caused by abnormal value of node_len
+    - ALSA: usb-audio: Fix case when USB MIDI interface has more than one extra
+      endpoint descriptor
+    - PCI: pciehp: Fix MSI interrupt race
+    - NFS: Fix races nfs_page_group_destroy() vs
+      nfs_destroy_unlinked_subrequests()
+    - drm/amdgpu/vcn2.0: stall DPG when WPTR/RPTR reset
+    - powerpc/perf: Implement a global lock to avoid races between trace, core and
+      thread imc events.
+    - mm/kmemleak.c: use address-of operator on section symbols
+    - mm/filemap.c: clear page error before actual read
+    - mm/swapfile: fix data races in try_to_unuse()
+    - mm/vmscan.c: fix data races using kswapd_classzone_idx
+    - SUNRPC: Don't start a timer on an already queued rpc task
+    - nvmet-rdma: fix double free of rdma queue
+    - workqueue: Remove the warning in wq_worker_sleeping()
+    - drm/amdgpu/sriov add amdgpu_amdkfd_pre_reset in gpu reset
+    - mm/mmap.c: initialize align_offset explicitly for vm_unmapped_area
+    - ALSA: hda: Skip controller resume if not needed
+    - scsi: qedi: Fix termination timeouts in session logout
+    - serial: uartps: Wait for tx_empty in console setup
+    - btrfs: fix setting last_trans for reloc roots
+    - KVM: Remove CREATE_IRQCHIP/SET_PIT2 race
+    - perf stat: Force error in fallback on :k events
+    - bdev: Reduce time holding bd_mutex in sync in blkdev_close()
+    - drivers: char: tlclk.c: Avoid data race between init and interrupt handler
+    - KVM: arm64: vgic-v3: Retire all pending LPIs on vcpu destroy
+    - KVM: arm64: vgic-its: Fix memory leak on the error path of vgic_add_lpi()
+    - net: openvswitch: use u64 for meter bucket
+    - scsi: aacraid: Fix error handling paths in aac_probe_one()
+    - staging:r8188eu: avoid skb_clone for amsdu to msdu conversion
+    - sparc64: vcc: Fix error return code in vcc_probe()
+    - arm64: cpufeature: Relax checks for AArch32 support at EL[0-2]
+    - sched/fair: Eliminate bandwidth race between throttling and distribution
+    - dpaa2-eth: fix error return code in setup_dpni()
+    - dt-bindings: sound: wm8994: Correct required supplies based on actual
+      implementaion
+    - devlink: Fix reporter's recovery condition
+    - atm: fix a memory leak of vcc->user_back
+    - media: venus: vdec: Init registered list unconditionally
+    - perf mem2node: Avoid double free related to realloc
+    - mm/slub: fix incorrect interpretation of s->offset
+    - i2c: tegra: Restore pinmux on system resume
+    - power: supply: max17040: Correct voltage reading
+    - phy: samsung: s5pv210-usb2: Add delay after reset
+    - Bluetooth: Handle Inquiry Cancel error after Inquiry Complete
+    - USB: EHCI: ehci-mv: fix error handling in mv_ehci_probe()
+    - KVM: x86: handle wrap around 32-bit address space
+    - tipc: fix memory leak in service subscripting
+    - tty: serial: samsung: Correct clock selection logic
+    - ALSA: hda: Fix potential race in unsol event handler
+    - drm/exynos: dsi: Remove bridge node reference in error handling path in
+      probe function
+    - ipmi:bt-bmc: Fix error handling and status check
+    - powerpc/traps: Make unrecoverable NMIs die instead of panic
+    - svcrdma: Fix backchannel return code
+    - fuse: don't check refcount after stealing page
+    - fuse: update attr_version counter on fuse_notify_inval_inode()
+    - USB: EHCI: ehci-mv: fix less than zero comparison of an unsigned int
+    - coresight: etm4x: Fix use-after-free of per-cpu etm drvdata
+    - arm64: acpi: Make apei_claim_sea() synchronise with APEI's irq work
+    - scsi: cxlflash: Fix error return code in cxlflash_probe()
+    - arm64/cpufeature: Drop TraceFilt feature exposure from ID_DFR0 register
+    - drm/amdkfd: fix restore worker race condition
+    - e1000: Do not perform reset in reset_task if we are already down
+    - drm/nouveau/debugfs: fix runtime pm imbalance on error
+    - drm/nouveau: fix runtime pm imbalance on error
+    - drm/nouveau/dispnv50: fix runtime pm imbalance on error
+    - printk: handle blank console arguments passed in.
+    - usb: dwc3: Increase timeout for CmdAct cleared by device controller
+    - btrfs: don't force read-only after error in drop snapshot
+    - btrfs: fix double __endio_write_update_ordered in direct I/O
+    - gpio: rcar: Fix runtime PM imbalance on error
+    - vfio/pci: fix memory leaks of eventfd ctx
+    - KVM: PPC: Book3S HV: Close race with page faults around memslot flushes
+    - perf evsel: Fix 2 memory leaks
+    - perf trace: Fix the selection for architectures to generate the errno name
+      tables
+    - perf stat: Fix duration_time value for higher intervals
+    - perf util: Fix memory leak of prefix_if_not_in
+    - perf metricgroup: Free metric_events on error
+    - perf kcore_copy: Fix module map when there are no modules loaded
+    - PCI: tegra194: Fix runtime PM imbalance on error
+    - ASoC: img-i2s-out: Fix runtime PM imbalance on error
+    - wlcore: fix runtime pm imbalance in wl1271_tx_work
+    - wlcore: fix runtime pm imbalance in wlcore_regdomain_config
+    - mtd: rawnand: gpmi: Fix runtime PM imbalance on error
+    - mtd: rawnand: omap_elm: Fix runtime PM imbalance on error
+    - PCI: tegra: Fix runtime PM imbalance on error
+    - ceph: fix potential race in ceph_check_caps
+    - mm/swap_state: fix a data race in swapin_nr_pages
+    - mm: memcontrol: fix stat-corrupting race in charge moving
+    - rapidio: avoid data race between file operation callbacks and
+      mport_cdev_add().
+    - mtd: parser: cmdline: Support MTD names containing one or more colons
+    - x86/speculation/mds: Mark mds_user_clear_cpu_buffers() __always_inline
+    - NFS: nfs_xdr_status should record the procedure name
+    - vfio/pci: Clear error and request eventfd ctx after releasing
+    - cifs: Fix double add page to memcg when cifs_readpages
+    - nvme: fix possible deadlock when I/O is blocked
+    - mac80211: skip mpath lookup also for control port tx
+    - scsi: libfc: Handling of extra kref
+    - scsi: libfc: Skip additional kref updating work event
+    - selftests/x86/syscall_nt: Clear weird flags after each test
+    - vfio/pci: fix racy on error and request eventfd ctx
+    - btrfs: qgroup: fix data leak caused by race between writeback and truncate
+    - perf tests: Fix test 68 zstd compression for s390
+    - scsi: qla2xxx: Retry PLOGI on FC-NVMe PRLI failure
+    - ubi: fastmap: Free unused fastmap anchor peb during detach
+    - mt76: fix LED link time failure
+    - opp: Increase parsed_static_opps in _of_add_opp_table_v1()
+    - perf parse-events: Use strcmp() to compare the PMU name
+    - ALSA: hda: Always use jackpoll helper for jack update after resume
+    - ALSA: hda: Workaround for spurious wakeups on some Intel platforms
+    - net: openvswitch: use div_u64() for 64-by-32 divisions
+    - nvme: explicitly update mpath disk capacity on revalidation
+    - device_cgroup: Fix RCU list debugging warning
+    - ASoC: pcm3168a: ignore 0 Hz settings
+    - ASoC: wm8994: Skip setting of the WM8994_MICBIAS register for WM1811
+    - ASoC: wm8994: Ensure the device is resumed in wm89xx_mic_detect functions
+    - ASoC: Intel: bytcr_rt5640: Add quirk for MPMAN Converter9 2-in-1
+    - RISC-V: Take text_mutex in ftrace_init_nop()
+    - i2c: aspeed: Mask IRQ status to relevant bits
+    - s390/init: add missing __init annotations
+    - lockdep: fix order in trace_hardirqs_off_caller()
+    - EDAC/ghes: Check whether the driver is on the safe list correctly
+    - drm/amdkfd: fix a memory leak issue
+    - drm/amd/display: update nv1x stutter latencies
+    - drm/amdgpu/dc: Require primary plane to be enabled whenever the CRTC is
+    - objtool: Fix noreturn detection for ignored functions
+    - ieee802154: fix one possible memleak in ca8210_dev_com_init
+    - ieee802154/adf7242: check status of adf7242_read_reg
+    - clocksource/drivers/h8300_timer8: Fix wrong return value in
+      h8300_8timer_init()
+    - batman-adv: bla: fix type misuse for backbone_gw hash indexing
+    - atm: eni: fix the missed pci_disable_device() for eni_init_one()
+    - batman-adv: mcast/TT: fix wrongly dropped or rerouted packets
+    - netfilter: conntrack: nf_conncount_init is failing with IPv6 disabled
+    - mac802154: tx: fix use-after-free
+    - bpf: Fix clobbering of r2 in bpf_gen_ld_abs
+    - drm/vc4/vc4_hdmi: fill ASoC card owner
+    - net: qed: Disable aRFS for NPAR and 100G
+    - net: qede: Disable aRFS for NPAR and 100G
+    - net: qed: RDMA personality shouldn't fail VF load
+    - drm/sun4i: sun8i-csc: Secondary CSC register correction
+    - batman-adv: Add missing include for in_interrupt()
+    - nvme-tcp: fix kconfig dependency warning when !CRYPTO
+    - batman-adv: mcast: fix duplicate mcast packets in BLA backbone from LAN
+    - batman-adv: mcast: fix duplicate mcast packets in BLA backbone from mesh
+    - batman-adv: mcast: fix duplicate mcast packets from BLA backbone to mesh
+    - bpf: Fix a rcu warning for bpffs map pretty-print
+    - lib80211: fix unmet direct dependendices config warning when !CRYPTO
+    - ALSA: asihpi: fix iounmap in error handler
+    - regmap: fix page selection for noinc reads
+    - regmap: fix page selection for noinc writes
+    - MIPS: Add the missing 'CPU_1074K' into __get_cpu_type()
+    - regulator: axp20x: fix LDO2/4 description
+    - KVM: x86: Reset MMU context if guest toggles CR4.SMAP or CR4.PKE
+    - KVM: SVM: Add a dedicated INVD intercept routine
+    - mm: validate pmd after splitting
+    - arch/x86/lib/usercopy_64.c: fix __copy_user_flushcache() cache writeback
+    - x86/ioapic: Unbreak check_timer()
+    - scsi: lpfc: Fix initial FLOGI failure due to BBSCN not supported
+    - ALSA: usb-audio: Add delay quirk for H570e USB headsets
+    - ALSA: hda/realtek - Couldn't detect Mic if booting with headset plugged
+    - ALSA: hda/realtek: Enable front panel headset LED on Lenovo ThinkStation
+      P520
+    - lib/string.c: implement stpcpy
+    - tracing: fix double free
+    - s390/dasd: Fix zero write for FBA devices
+    - kprobes: Fix to check probe enabled before disarm_kprobe_ftrace()
+    - kprobes: tracing/kprobes: Fix to kill kprobes on initmem after boot
+    - btrfs: fix overflow when copying corrupt csums for a message
+    - dmabuf: fix NULL pointer dereference in dma_buf_release()
+    - mm, THP, swap: fix allocating cluster for swapfile by mistake
+    - mm/gup: fix gup_fast with dynamic page table folding
+    - s390/zcrypt: Fix ZCRYPT_PERDEV_REQCNT ioctl
+    - KVM: arm64: Assume write fault on S1PTW permission fault on instruction
+      fetch
+    - dm: fix bio splitting and its bio completion order for regular IO
+    - ata: define AC_ERR_OK
+    - ata: make qc_prep return ata_completion_errors
+    - ata: sata_mv, avoid trigerrable BUG_ON
+    - Linux 5.4.69
+  * Focal update: v5.4.68 upstream stable release (LP: #1899511)
+    - af_key: pfkey_dump needs parameter validation
+    - ibmvnic fix NULL tx_pools and rx_tools issue at do_reset
+    - ibmvnic: add missing parenthesis in do_reset()
+    - kprobes: fix kill kprobe which has been marked as gone
+    - mm/thp: fix __split_huge_pmd_locked() for migration PMD
+    - act_ife: load meta modules before tcf_idr_check_alloc()
+    - bnxt_en: Avoid sending firmware messages when AER error is detected.
+    - bnxt_en: Fix NULL ptr dereference crash in bnxt_fw_reset_task()
+    - cxgb4: fix memory leak during module unload
+    - cxgb4: Fix offset when clearing filter byte counters
+    - geneve: add transport ports in route lookup for geneve
+    - hdlc_ppp: add range checks in ppp_cp_parse_cr()
+    - ip: fix tos reflection in ack and reset packets
+    - ipv4: Initialize flowi4_multipath_hash in data path
+    - ipv4: Update exception handling for multipath routes via same device
+    - ipv6: avoid lockdep issue in fib6_del()
+    - net: bridge: br_vlan_get_pvid_rcu() should dereference the VLAN group under
+      RCU
+    - net: DCB: Validate DCB_ATTR_DCB_BUFFER argument
+    - net: dsa: rtl8366: Properly clear member config
+    - net: Fix bridge enslavement failure
+    - net: ipv6: fix kconfig dependency warning for IPV6_SEG6_HMAC
+    - net/mlx5: Fix FTE cleanup
+    - net: sch_generic: aviod concurrent reset and enqueue op for lockless qdisc
+    - net: sctp: Fix IPv6 ancestor_size calc in sctp_copy_descendant
+    - nfp: use correct define to return NONE fec
+    - taprio: Fix allowing too small intervals
+    - tipc: Fix memory leak in tipc_group_create_member()
+    - tipc: fix shutdown() of connection oriented socket
+    - tipc: use skb_unshare() instead in tipc_buf_append()
+    - net/mlx5e: Enable adding peer miss rules only if merged eswitch is supported
+    - net/mlx5e: TLS, Do not expose FPGA TLS counter if not supported
+    - bnxt_en: return proper error codes in bnxt_show_temp
+    - bnxt_en: Protect bnxt_set_eee() and bnxt_set_pauseparam() with mutex.
+    - net: lantiq: Wake TX queue again
+    - net: lantiq: use netif_tx_napi_add() for TX NAPI
+    - net: lantiq: Use napi_complete_done()
+    - net: lantiq: Disable IRQs only if NAPI gets scheduled
+    - net: phy: Avoid NPD upon phy_detach() when driver is unbound
+    - net: phy: Do not warn in phy_stop() on PHY_DOWN
+    - net: qrtr: check skb_put_padto() return value
+    - net: add __must_check to skb_put_padto()
+    - mm: memcg: fix memcg reclaim soft lockup
+    - iommu/amd: Use cmpxchg_double() when updating 128-bit IRTE
+    - Linux 5.4.68
+  * *-tools-common packages descriptions have typo "PGKVER" (LP: #1898903)
+    - [Packaging] Fix typo in -tools template s/PGKVER/PKGVER/
+  * tc/ebpf: unable to use BPF_FUNC_skb_change_head (LP: #1896504)
+    - net: bpf: Allow TC programs to call BPF_FUNC_skb_change_head
+  * HP Zbook Studio G7 boots into corrupted screen with PSR featured panel
+    (LP: #1897501)
+    - SAUCE: drm/i915/psr: allow overriding PSR disable param by quirk
+    - SAUCE: drm/dp: add DP_QUIRK_FORCE_PSR_CHIP_DEFAULT quirk to CMN prod-ID
+      19-15
+  * Fix broken e1000e device after S3 (LP: #1897755)
+    - SAUCE: e1000e: Increase polling timeout on MDIC ready bit
+  * debian/rules editconfigs does not work on s390x to change s390x only configs
+    (LP: #1863116)
+    - [Packaging] kernelconfig -- only update/edit configurations on architectures
+      we have compiler support
+  * acpi event detection crashes (LP: #1896482)
+    - ACPI: EC: tweak naming in preparation for GpioInt support
+    - ACPI: EC: add support for hardware-reduced systems
+    - ACPI: EC: Avoid passing redundant argument to functions
+    - ACPI: EC: Consolidate event handler installation code
+  * mwifiex stops working after kernel upgrade (LP: #1897299)
+    - mwifiex: Increase AES key storage size to 256 bits
+  * Remove NVMe suspend-to-idle workaround (LP: #1897227)
+    - Revert "UBUTU: SAUCE: pci: prevent Intel NVMe SSDPEKKF from entering D3"
+    - Revert "UBUNTU: SAUCE: pci: prevent sk hynix nvme from entering D3"
+  * Request for CIFS patches to be available in 5.4 kernel (LP: #1896642)
+    - smb3: remove unused flag passed into close functions
+    - smb3: query attributes on file close
+  * Lenovo ThinkBook 14-IML Touchpad not showing up in /proc/bus/input/devices
+    (LP: #1853277)
+    - i2c: core: Call i2c_acpi_install_space_handler() before
+      i2c_acpi_register_devices()
+  * [Ubuntu 20.10] zPCI DMA tables and bitmap leak on hard unplug (PCI Event
+    0x0304) (LP: #1896216)
+    - s390/pci: fix leak of DMA tables on hard unplug
+  * Thunderbolt3 daisy chain sometimes doesn't work (LP: #1895606)
+    - thunderbolt: Retry DROM read once if parsing fails
+  * btrfs: trimming a btrfs device which has been shrunk previously fails and
+    fills root disk with garbage data (LP: #1896154)
+    - btrfs: trim: fix underflow in trim length to prevent access beyond device
+      boundary
+  * EFA: add support for 0xefa1 devices (LP: #1896791)
+    - RDMA/efa: Expose maximum TX doorbell batch
+    - RDMA/efa: Expose minimum SQ size
+    - RDMA/efa: User/kernel compatibility handshake mechanism
+    - RDMA/efa: Add EFA 0xefa1 PCI ID
+  * Focal update: v5.4.67 upstream stable release (LP: #1896828)
+    - gfs2: initialize transaction tr_ailX_lists earlier
+    - RDMA/bnxt_re: Restrict the max_gids to 256
+    - dsa: Allow forwarding of redirected IGMP traffic
+    - net: handle the return value of pskb_carve_frag_list() correctly
+    - hv_netvsc: Remove "unlikely" from netvsc_select_queue
+    - firmware_loader: fix memory leak for paged buffer
+    - NFSv4.1 handle ERR_DELAY error reclaiming locking state on delegation recall
+    - scsi: pm8001: Fix memleak in pm8001_exec_internal_task_abort
+    - scsi: libfc: Fix for double free()
+    - scsi: lpfc: Fix FLOGI/PLOGI receive race condition in pt2pt discovery
+    - regulator: pwm: Fix machine constraints application
+    - spi: spi-loopback-test: Fix out-of-bounds read
+    - NFS: Zero-stateid SETATTR should first return delegation
+    - SUNRPC: stop printk reading past end of string
+    - rapidio: Replace 'select' DMAENGINES 'with depends on'
+    - cifs: fix DFS mount with cifsacl/modefromsid
+    - openrisc: Fix cache API compile issue when not inlining
+    - nvme-fc: cancel async events before freeing event struct
+    - nvme-rdma: cancel async events before freeing event struct
+    - nvme-tcp: cancel async events before freeing event struct
+    - block: only call sched requeue_request() for scheduled requests
+    - f2fs: fix indefinite loop scanning for free nid
+    - f2fs: Return EOF on unaligned end of file DIO read
+    - i2c: algo: pca: Reapply i2c bus settings after reset
+    - spi: Fix memory leak on splited transfers
+    - KVM: MIPS: Change the definition of kvm type
+    - clk: davinci: Use the correct size when allocating memory
+    - clk: rockchip: Fix initialization of mux_pll_src_4plls_p
+    - ASoC: qcom: Set card->owner to avoid warnings
+    - ASoC: qcom: common: Fix refcount imbalance on error
+    - powerpc/book3s64/radix: Fix boot failure with large amount of guest memory
+    - ASoC: meson: axg-toddr: fix channel order on g12 platforms
+    - Drivers: hv: vmbus: hibernation: do not hang forever in vmbus_bus_resume()
+    - scsi: libsas: Fix error path in sas_notify_lldd_dev_found()
+    - arm64: Allow CPUs unffected by ARM erratum 1418040 to come in late
+    - Drivers: hv: vmbus: Add timeout to vmbus_wait_for_unload
+    - perf test: Fix the "signal" test inline assembly
+    - MIPS: SNI: Fix MIPS_L1_CACHE_SHIFT
+    - perf evlist: Fix cpu/thread map leak
+    - perf parse-event: Fix memory leak in evsel->unit
+    - perf test: Free formats for perf pmu parse test
+    - fbcon: Fix user font detection test at fbcon_resize().
+    - MIPS: SNI: Fix spurious interrupts
+    - drm/mediatek: Add exception handing in mtk_drm_probe() if component init
+      fail
+    - drm/mediatek: Add missing put_device() call in mtk_hdmi_dt_parse_pdata()
+    - arm64: bpf: Fix branch offset in JIT
+    - iommu/amd: Fix potential @entry null deref
+    - i2c: mxs: use MXS_DMA_CTRL_WAIT4END instead of DMA_CTRL_ACK
+    - riscv: Add sfence.vma after early page table changes
+    - drm/i915: Filter wake_flags passed to default_wake_function
+    - USB: quirks: Add USB_QUIRK_IGNORE_REMOTE_WAKEUP quirk for BYD zhaoxin
+      notebook
+    - USB: UAS: fix disconnect by unplugging a hub
+    - usblp: fix race between disconnect() and read()
+    - i2c: i801: Fix resume bug
+    - Revert "ALSA: hda - Fix silent audio output and corrupted input on MSI
+      X570-A PRO"
+    - ALSA: hda: fixup headset for ASUS GX502 laptop
+    - ALSA: hda/realtek - The Mic on a RedmiBook doesn't work
+    - percpu: fix first chunk size calculation for populated bitmap
+    - Input: trackpoint - add new trackpoint variant IDs
+    - Input: i8042 - add Entroware Proteus EL07R4 to nomux and reset lists
+    - serial: 8250_pci: Add Realtek 816a and 816b
+    - x86/boot/compressed: Disable relocation relaxation
+    - s390/zcrypt: fix kmalloc 256k failure
+    - ehci-hcd: Move include to keep CRC stable
+    - powerpc/dma: Fix dma_map_ops::get_required_mask
+    - selftests/vm: fix display of page size in map_hugetlb
+    - dm/dax: Fix table reference counts
+    - mm/memory_hotplug: drain per-cpu pages again during memory offline
+    - dm: Call proper helper to determine dax support
+    - dax: Fix compilation for CONFIG_DAX && !CONFIG_FS_DAX
+    - Linux 5.4.67
+  * Focal update: v5.4.67 upstream stable release (LP: #1896828) // Cherry Pick
+    needed for Critical upstream patch for Kernel null pointer dereference -
+    usb-c altmode (LP: #1897963)
+    - usb: typec: ucsi: Prevent mode overrun
+  * Focal update: v5.4.66 upstream stable release (LP: #1896824)
+    - ARM: dts: logicpd-torpedo-baseboard: Fix broken audio
+    - ARM: dts: logicpd-som-lv-baseboard: Fix broken audio
+    - ARM: dts: logicpd-som-lv-baseboard: Fix missing video
+    - regulator: push allocation in regulator_ena_gpio_request() out of lock
+    - regulator: remove superfluous lock in regulator_resolve_coupling()
+    - ARM: dts: socfpga: fix register entry for timer3 on Arria10
+    - ARM: dts: ls1021a: fix QuadSPI-memory reg range
+    - ARM: dts: imx7ulp: Correct gpio ranges
+    - RDMA/rxe: Fix memleak in rxe_mem_init_user
+    - RDMA/rxe: Drop pointless checks in rxe_init_ports
+    - RDMA/rxe: Fix panic when calling kmem_cache_create()
+    - RDMA/bnxt_re: Do not report transparent vlan from QP1
+    - drm/sun4i: add missing put_device() call in sun8i_r40_tcon_tv_set_mux()
+    - arm64: dts: imx8mq: Fix TMU interrupt property
+    - drm/sun4i: Fix dsi dcs long write function
+    - iio: adc: mcp3422: fix locking on error path
+    - iio: adc: mcp3422: fix locking scope
+    - scsi: libsas: Set data_dir as DMA_NONE if libata marks qc as NODATA
+    - RDMA/core: Fix reported speed and width
+    - scsi: megaraid_sas: Don't call disable_irq from process IRQ poll
+    - scsi: mpt3sas: Don't call disable_irq from IRQ poll handler
+    - soundwire: fix double free of dangling pointer
+    - drm/sun4i: backend: Support alpha property on lowest plane
+    - drm/sun4i: backend: Disable alpha on the lowest plane on the A20
+    - mmc: sdhci-acpi: Clear amd_sdhci_host on reset
+    - mmc: sdhci-msm: Add retries when all tuning phases are found valid
+    - spi: stm32: Rate-limit the 'Communication suspended' message
+    - nvme-fabrics: allow to queue requests for live queues
+    - spi: stm32: fix pm_runtime_get_sync() error checking
+    - block: Set same_page to false in __bio_try_merge_page if ret is false
+    - IB/isert: Fix unaligned immediate-data handling
+    - ARM: dts: bcm: HR2: Fixed QSPI compatible string
+    - ARM: dts: NSP: Fixed QSPI compatible string
+    - ARM: dts: BCM5301X: Fixed QSPI compatible string
+    - arm64: dts: ns2: Fixed QSPI compatible string
+    - ARC: HSDK: wireup perf irq
+    - dmaengine: acpi: Put the CSRT table after using it
+    - netfilter: conntrack: allow sctp hearbeat after connection re-use
+    - drivers/net/wan/lapbether: Added needed_tailroom
+    - NFC: st95hf: Fix memleak in st95hf_in_send_cmd
+    - firestream: Fix memleak in fs_open
+    - ALSA: hda: Fix 2 channel swapping for Tegra
+    - ALSA: hda/tegra: Program WAKEEN register for Tegra
+    - drivers/dma/dma-jz4780: Fix race condition between probe and irq handler
+    - net: hns3: Fix for geneve tx checksum bug
+    - xfs: fix off-by-one in inode alloc block reservation calculation
+    - drivers/net/wan/lapbether: Set network_header before transmitting
+    - cfg80211: Adjust 6 GHz frequency to channel conversion
+    - xfs: initialize the shortform attr header padding entry
+    - irqchip/eznps: Fix build error for !ARC700 builds
+    - nvmet-tcp: Fix NULL dereference when a connect data comes in h2cdata pdu
+    - nvme-fabrics: don't check state NVME_CTRL_NEW for request acceptance
+    - nvme: have nvme_wait_freeze_timeout return if it timed out
+    - nvme-tcp: serialize controller teardown sequences
+    - nvme-tcp: fix timeout handler
+    - nvme-tcp: fix reset hang if controller died in the middle of a reset
+    - nvme-rdma: serialize controller teardown sequences
+    - nvme-rdma: fix timeout handler
+    - nvme-rdma: fix reset hang if controller died in the middle of a reset
+    - nvme-pci: cancel nvme device request before disabling
+    - HID: quirks: Set INCREMENT_USAGE_ON_DUPLICATE for all Saitek X52 devices
+    - HID: microsoft: Add rumble support for the 8bitdo SN30 Pro+ controller
+    - drivers/net/wan/hdlc_cisco: Add hard_header_len
+    - HID: elan: Fix memleak in elan_input_configured
+    - ARC: [plat-hsdk]: Switch ethernet phy-mode to rgmii-id
+    - cpufreq: intel_pstate: Refuse to turn off with HWP enabled
+    - cpufreq: intel_pstate: Fix intel_pstate_get_hwp_max() for turbo disabled
+    - arm64/module: set trampoline section flags regardless of
+      CONFIG_DYNAMIC_FTRACE
+    - ALSA: hda: hdmi - add Rocketlake support
+    - ALSA: hda: fix a runtime pm issue in SOF when integrated GPU is disabled
+    - drm/amdgpu: Fix bug in reporting voltage for CIK
+    - iommu/amd: Do not use IOMMUv2 functionality when SME is active
+    - gcov: Disable gcov build with GCC 10
+    - iio: adc: ti-ads1015: fix conversion when CONFIG_PM is not set
+    - iio: cros_ec: Set Gyroscope default frequency to 25Hz
+    - iio:light:ltr501 Fix timestamp alignment issue.
+    - iio:proximity:mb1232: Fix timestamp alignment and prevent data leak.
+    - iio:accel:bmc150-accel: Fix timestamp alignment and prevent data leak.
+    - iio:adc:ti-adc084s021 Fix alignment and data leak issues.
+    - iio:adc:ina2xx Fix timestamp alignment issue.
+    - iio:adc:max1118 Fix alignment of timestamp and data leak issues
+    - iio:adc:ti-adc081c Fix alignment and data leak issues
+    - iio:magnetometer:ak8975 Fix alignment and data leak issues.
+    - iio:light:max44000 Fix timestamp alignment and prevent data leak.
+    - iio:chemical:ccs811: Fix timestamp alignment and prevent data leak.
+    - iio: accel: kxsd9: Fix alignment of local buffer.
+    - iio:accel:mma7455: Fix timestamp alignment and prevent data leak.
+    - iio:accel:mma8452: Fix timestamp alignment and prevent data leak.
+    - staging: wlan-ng: fix out of bounds read in prism2sta_probe_usb()
+    - btrfs: require only sector size alignment for parent eb bytenr
+    - btrfs: fix lockdep splat in add_missing_dev
+    - btrfs: fix wrong address when faulting in pages in the search ioctl
+    - kobject: Restore old behaviour of kobject_del(NULL)
+    - regulator: push allocation in regulator_init_coupling() outside of lock
+    - regulator: push allocations in create_regulator() outside of lock
+    - regulator: push allocation in set_consumer_device_supply() out of lock
+    - regulator: plug of_node leak in regulator_register()'s error path
+    - regulator: core: Fix slab-out-of-bounds in regulator_unlock_recursive()
+    - scsi: target: iscsi: Fix data digest calculation
+    - scsi: target: iscsi: Fix hang in iscsit_access_np() when getting
+      tpg->np_login_sem
+    - drm/i915/gvt: do not check len & max_len for lri
+    - drm/tve200: Stabilize enable/disable
+    - drm/msm: Disable preemption on all 5xx targets
+    - mmc: sdio: Use mmc_pre_req() / mmc_post_req()
+    - mmc: sdhci-of-esdhc: Don't walk device-tree on every interrupt
+    - rbd: require global CAP_SYS_ADMIN for mapping and unmapping
+    - RDMA/rxe: Fix the parent sysfs read when the interface has 15 chars
+    - RDMA/mlx4: Read pkey table length instead of hardcoded value
+    - fbcon: remove soft scrollback code
+    - fbcon: remove now unusued 'softback_lines' cursor() argument
+    - vgacon: remove software scrollback support
+    - [Config] updateconfigs for VGACON_SOFT_SCROLLBACK
+    - KVM: VMX: Don't freeze guest when event delivery causes an APIC-access exit
+    - KVM: arm64: Do not try to map PUDs when they are folded into PMD
+    - KVM: fix memory leak in kvm_io_bus_unregister_dev()
+    - debugfs: Fix module state check condition
+    - ARM: dts: vfxxx: Add syscon compatible with OCOTP
+    - video: fbdev: fix OOB read in vga_8planes_imageblit()
+    - staging: greybus: audio: fix uninitialized value issue
+    - phy: qcom-qmp: Use correct values for ipq8074 PCIe Gen2 PHY init
+    - usb: core: fix slab-out-of-bounds Read in read_descriptors
+    - USB: serial: ftdi_sio: add IDs for Xsens Mti USB converter
+    - USB: serial: option: support dynamic Quectel USB compositions
+    - USB: serial: option: add support for SIM7070/SIM7080/SIM7090 modules
+    - usb: Fix out of sync data toggle if a configured device is reconfigured
+    - usb: typec: ucsi: acpi: Check the _DEP dependencies
+    - drm/msm/gpu: make ringbuffer readonly
+    - drm/msm: Disable the RPTR shadow
+    - gcov: add support for GCC 10.1
+    - Linux 5.4.66
+
+  [ Ubuntu: 5.4.0-54.60 ]
+
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+  * Introduce the new NVIDIA 455 series (LP: #1902093)
+    - [Packaging] NVIDIA -- Add the NVIDIA 455 driver
+
+  [ Ubuntu: 5.4.0-53.59 ]
+
+  * CVE-2020-8694
+    - powercap: make attributes only readable by root
+
+ -- Hsuan-Yu Lin <shane.lin@canonical.com>  Sat, 28 Aug 2021 17:07:02 +0800
+
+linux-xilinx-zynqmp (5.4.0-1015.18) focal; urgency=medium
+
+  * INVALID or PRIVATE BUG (LP: #1931882)
+    - SAUCE: move zocl_ioctl.h to include/drm
+
+ -- Hsuan-Yu Lin <shane.lin@canonical.com>  Tue, 13 Jul 2021 14:08:18 +0800
+
+linux-xilinx-zynqmp (5.4.0-1014.16) focal; urgency=medium
+
+  * Define suspend/resume wake up sources (LP: #1921001)
+    - [Config] Enable keyboard drive
+
+  * Kernel config review (LP: #1925667)
+    - [Config] Disable CONFIG_ARM_PSCI_CPUIDLE
+
+  * Update kernel config for Xilinx SOM (LP: #1927147)
+    - [Config] Support for Xilinx SOM
+
+  * Import changes from Xilinx new kernel release (LP: #1928298)
+    - [Config] Update kernel configs to Xilinx rebase 5.4 branch
+
+  * Enable kernel debug features (LP: #1917874)
+    - [Config] enable kernel features for debug
+
+  * Fixes for wake from USB (LP: #1932244)
+    - usb: dwc3: Corrected wake up capability conditional check for board specific
+    - usb: dwc3: Disable phy suspend after power-on reset
+
+  * Publish zocl ioctl header file (LP: #1931882)
+    - SAUCE: move zynq_ioctl.h to include/drm
+
+  * Miscellaneous upstream changes
+    - mtd: spi-nor: Fix call trace when qspi driver built as module
+    - iio: adc: versal-sysmon: Additional documentation for production silicon
+      support.
+    - spi: spi-zynqmp-gqspi: Avoid multiple writes to tapdelay registers
+    - dt-bindings: regulator: DA9121: Add DA9121 bindings
+    - drivers: regulator: Add driver for DA9121 family of devices
+    - regulator: da9121: Add details for da9121
+    - regulator: da9121: Use gpio descriptors instead of numbers
+    - regulator: da9121: Use core regulator lock
+    - regulator: da9121: Modify the variant code as per hardware
+    - regulator: da9121: Fix coding style issues
+    - arm64: xilinx: Enable TPM for xilinx platforms
+    - arm64: xilinx: Enable DA9121 regulator driver
+    - dt-bindings: iio: adc: Add ti,ina260.yaml
+    - drivers: iio: Add support for TI INA260 power monitors
+    - arm64: xilinx: Enable INA260 IIO driver
+    - regulator: da9121: Init regmap to avoid compilation warning
+    - dt-bindings: usb: misc: Add binding for Microchip usb5744 hub
+    - usb: misc: usb5744: add support for USB hub controller
+    - xilinx: Enable USB hub driver for 5744
+    - pinctrl: core: Handling pinmux and pinconf separately
+    - crypto: aes: zynqmp: Remove carriage return from one print
+    - drm: xlnx: zynqmp_dp: Fix possible crtc searching
+    - drm/of: Correct documentation for drm_of_find_possible_crtcs()
+    - drm: xlnx: zynqmp: Only register DP CRTC if there is no other CRTC
+    - drm: xlnx: mixer: Add port OF node to DRM CRTC
+    - drm: xlnx: zynqmp_disp: Move live bridges registration to probe
+    - drm: xlnx: zynqmp_disp: Move bridge functions
+    - drm: xlnx: zynqmp_disp: Enable DP encoder during bridge enable
+    - drm: xlnx: zynqmp_disp: Force alpha to 0 when external CRTC used
+    - drm: xlnx: zynqmp: Ignore DP vblank interrupts if external CRTC used
+    - drm: xlnx: zynqmp_disp: Fix live format config
+    - drm: xlnx: zynqmp_disp: Add set_timing support for live bridge
+    - drm: xlnx: mixer: Print out mixer CRTC id
+    - drm: xlnx: mixer: Add DP live bridge support
+    - arm64: xilinx: Enable VTC bridge for xilinx platforms
+    - drm: xlnx: zynqmp_disp: Add VTC bridge support
+    - arm64: zynqmp: Label DP layers by default
+    - drm: xlnx: zynqmp_dpsub: Only init drm master when DP CRTC used
+    - media: uapi: Add an entity type for Image Signal Processors
+    - media: dt-bindings: media: i2c: Add bindings for AP1302
+    - media: i2c: Add ON Semiconductor AP1302 ISP driver
+    - media: i2c: ap1302: Add NV12 format support
+    - media: i2c: ap1302: Update yuv420 to xilinx NV12 media bus format
+    - arm64: xilinx: config: Enable ap1302 ISP driver
+    - dt: bindings: sound: Add DT bindings for new compatible strings
+    - sound: xilinx: pcm: Assign device name per compatible string
+    - arm64: zynqmp: Use new compatible strings for DP snd pcm
+    - drm: xlnx: zynqmp_dpsub: Pass pcm auxdata when populating sound nodes
+    - drm: xlnx: zynqmp_disp: Release VTC bridge in unbind stage
+    - media: i2c: ap1302: Update MIPI TCLK POST and PRE timing values
+    - media: i2c: ap1302: Add debugfs entry for MIPI TCLK timings
+    - media: i2c: ap1302: Increase MIPI TCLK POST timing value
+    - dt-bindings: soc: xilinx: Add optional property to vcu
+    - soc: xilinx: vcu: update gasket isolation
+    - drm: xlnx: zynqmp_dp: fix suspend/resume issue
+    - net: macb: Add ethtool support to advertise WOL
+    - arm64: xilinx: Enable keyboard driver
+    - arm64: xilinx: Enable Xilinx Synchronizer driver
+    - xilinx: defconfig: Enable mulitple sensor drivers
+
+ -- Wen-chien Jesse Sung <jesse.sung@canonical.com>  Wed, 23 Jun 2021 22:56:41 +0800
+
+linux-xilinx-zynqmp (5.4.0-1013.14) focal; urgency=medium
+
+  * INVALID or PRIVATE BUG (LP: #1925667)
+    - [Config] Update configs for ZynqMP platform
+
+  * INVALID or PRIVATE BUG (LP: #1905563)
+    - [Config] Enable CONFIG_FPGA_MGR_DEBUG_FS
+
+  * INVALID or PRIVATE BUG (LP: #1922906)
+    - [Config] Enable kernel configs for Xilinx AXI4-Stream Video Broadcaster
+
+  * Miscellaneous upstream changes
+    - dt: bindings: media: xilinx: Doc for Xilinx AXI4-Stream Broadcaster driver
+    - v4l: xilinx: Driver support for Xilinx AXI4-Stream Broadcaster
+    - arm64: xilinx: Enable Xilinx AXI4-Stream Video Broadcaster
+
+ -- Hsuan-Yu Lin <shane.lin@canonical.com>  Tue, 11 May 2021 11:49:50 +0800
+
+linux-xilinx-zynqmp (5.4.0-1012.13) focal; urgency=medium
+
+  * INVALID or PRIVATE BUG (LP: #1920935)
+    - [Config] Enable kernel configs for CONFIG_KEYBOARD_GPIO
+
+ -- Hsuan-Yu Lin <shane.lin@canonical.com>  Thu, 01 Apr 2021 17:39:11 +0800
+
+linux-xilinx-zynqmp (5.4.0-1011.12) focal; urgency=medium
+
+  * INVALID or PRIVATE BUG (LP: #1920935)
+    - [Config] Enable kernel configs for required devices
+
+ -- Hsuan-Yu Lin <shane.lin@canonical.com>  Mon, 29 Mar 2021 14:02:48 +0800
+
+linux-xilinx-zynqmp (5.4.0-1010.11) focal; urgency=medium
+
+  * INVALID or PRIVATE BUG (LP: #1917886)
+    - [Config] Enable kernel configs for lxd
+
+  * INVALID or PRIVATE BUG (LP: #1917874)
+    - [Config] Enable Kprobes
+
+  * INVALID or PRIVATE BUG (LP: #1916027)
+    - XRT driver version update to 2.8.0
+
+  * INVALID or PRIVATE BUG (LP: #1905326)
+    - drm: xlnx: zynqmp_dp: Fix DP link train issue
+
+ -- Hsuan-Yu Lin <shane.lin@canonical.com>  Mon, 22 Mar 2021 09:59:47 +0800
+
+linux-xilinx-zynqmp (5.4.0-1009.10) focal; urgency=medium
+
+  * INVALID or PRIVATE BUG (LP: #1906202)
+    - [Config] Enable CONFIG_CGROUP_DEBUG
+
+  * Miscellaneous upstream changes
+    - arm64: xilinx: Enable IDT8T49N24x clock driver
+    - mmc: arasan: Fix the issue in reading tap values from DT
+
+ -- Hsuan-Yu Lin <shane.lin@canonical.com>  Thu, 28 Jan 2021 16:16:33 +0800
+
+linux-xilinx-zynqmp (5.4.0-1008.9) focal; urgency=medium
+
+  * cloud-config.service is blocked by snapd.seeded.service (LP: #1912476)
+    - [Config] update configs for snapd
+
+ -- Hsuan-Yu Lin <shane.lin@canonical.com>  Wed, 27 Jan 2021 17:34:38 +0800
+
+linux-xilinx-zynqmp (5.4.0-1007.8) focal; urgency=medium
+
+  * cloud-config.service is blocked by snapd.seeded.service (LP: #1912476
+    - [Config] update configs for snapd
+
+  * rename kernel debian packages (LP: #1904136
+    - [Packaging] rename the package as linux-xilinx-zynqmp
+
+  * INVALID or PRIVATE BUG (LP: #1912352)
+    - Import XRT 2020.2 kernel modules
+    - Fix XRT 2020.2 build error
+
+  * Miscellaneous upstream changes
+    - watchdog: of_xilinx_wdt: Use a proper variable to handle overflow
+    - watchdog: of_xilinx_wdt: Remove passing null pointer
+    - drm: xlnx: zynqmp: Use switch - case for link rate downshift
+    - drm: xlnx: mixer: Fix async update kernel warning
+    - dt-bindings: display: xlnx: mixer: Updated layer max height and width ranges
+    - misc: xilinx-ai-engine: replace u32 with __u32 in ioctl struct
+    - misc: xilinx-ai-engine: use correct printk formats
+    - misc: xilinx-ai-engine: include stdlib.h for size_t in uapi header
+    - misc: xilinx-ai-engine: use IS_ENABLED() compile guard
+    - arm64: xilinx: Enable xilinx PCS/PMA phy driver
+    - clk: zynq: Update the parameters to zynq_clk_register_periph_clk
+    - dt-bindings: media: xilinx: csi2rxss: Add YUV 420 8bits support
+    - v4l: xilinx: xcsi2rxss: Add support for YUV420 8bpc
+    - dt-bindings: dma: xilinx_frmbuf: Fix Y10 v4l2 pixel format
+    - dmaengine: xilinx: frmbuf: Fix Y10 v4l2 pixel format
+    - v4l: xilinx: vipp: Perform stream start/stop at pipeline level
+    - v4l: xilinx: vipp: remove unused variable
+    - v4l: xilinx: dma: Remove struct xventity_list
+    - net: emaclite: Add variable and conditions to check the return value
+    - misc: xilinx-ai-engine: gate columns first in partition reset
+    - iio: Fixed IIO_VAL_FRACTIONAL calculation for negative values
+    - v4l: xilinx: xcsi2rxss: Add YUV 420 video format code
+    - dt-bindings: display: xlnx: sdi: Add gpio reset
+    - drm: xlnx: sdi: Add GT and picxo cores reset through gpio
+    - misc: xilinx-ai-engine: add set/clear and test bit for resource function
+    - misc: xilinx-ai-engine: add scan and set clocks implementation
+    - misc: xilinx-ai-engine: add clock scanning when requesting partition and
+      tiles requesting
+    - dt-bindings: iio: xilinx: Add Documentation for Sysmon
+    - iio: versal-sysmon: add driver for Versal Sysmon
+    - arm64: xilinx: Added sysmon driver for versal
+    - dt-bindings: display: xlnx: Add DisplayPort Tx bindings
+    - drm: xlnx: dptx: Add DisplayPort tx driver
+    - arm64: xilinx: Enable the DP TX drm driver
+    - drm: xlnx: sdi: Add clock config to support integer and fractional framerate
+    - v4l: xilinx: multi-scaler: Fix warnings for UNUSED_VALUE
+    - v4l: xilinx: multi-scaler: Fix warnings for MIXED_ENUM_TYPE
+    - v4l: xilinx: multi-scaler: Fix warnings for INCOMPATIBLE_PARAM
+    - v4l: xilinx: multi-scaler: Fix warnings for NULL_RETURNS
+    - v4l: xilinx: vip: Fix V4L2_PIX_FMT_XY10 bpl_factor
+    - misc: xilinx-ai-engine: rename ai-engine-v1
+    - spi: spi-zynq-qspi: Check return value of clk_enable api
+    - spi: spi-zynq-qspi: Simplify logic for slave select
+    - misc: xilinx-ai-engine: add ioctl to pass dmabuf fd to set shimdma bd
+    - usb: chipidea: Fix return value handling
+    - usb: chipidea: core: Add return value function check
+    - usb: phy: Add NULL checks for return type function
+    - v4l: xilinx: sdirxss: Decode EOTF from ST352 payload
+    - v4l: xilinx: vpss-scaler: Fix the compatible string deprecated message
+    - v4l: xilinx: multi-scaler: Derive the caps from video device node
+    - v4l: xilinx: multi-scaler: Added streaming capabilities to device
+    - drm: xlnx: pl_disp: Release DMA when probe deferred
+    - v4l: xilinx: sdirxss: Decode colorimetry from ST352
+    - media: videodev2.h: add Hybrid Log Gamma transfer function define
+    - v4l: xilinx: sdirxss: Update the xfer_func
+    - v4l: xilinx: sdirxss: Update the ycbcr_enc
+    - v4l: xilinx: sdirxss: Update the quantization
+    - v4l: xilinx: axis-switch: Remove an invalid if check condition
+    - v4l: xilinx: m2m: Remove an unused variable
+    - v4l: xilinx: scaler: Set the pm ops
+    - dt-bindings: fpga: Add compatible value for Xilinx DFX AXI shutdown manger
+    - fpga: Add support for Xilinx DFX AXI Shutdown manager
+    - PCI: xdma: Use unique name for pci-xdma-pl.c
+    - xilinx: Enable several xilinx drivers
+    - misc: xilinx-ai-engine: fix scanning gated tiles logic
+    - ASoC: xlnx: Decouple sound card config dependency form all interfaces
+    - v4l: xilinx: vip: Fix CHECKED_RETURN warnings
+    - v4l: xilinx: vip: Fix UNINIT warnings
+    - v4l: xilinx: dma: Fix OVERFLOW_BEFORE_WIDEN warnings
+    - v4l: xilinx: dma: Fix PW.INCOMPATIBLE_PARAM warnings
+    - v4l: xilinx: dma: Fix UININT warnings
+    - v4l: xilinx: dma: Fix INFINITE_LOOP warning
+    - firmware: xilinx: sync firmware pm_query_id entries with PLM query id
+      entries
+    - i2c: xiic: Add wait for FIFO empty in send_tx
+    - i2c: xiic: Use 'nmsgs' variable instead of repeated_start
+    - i2c: xiic: Add smbus_block_read functionality
+    - arm64: xilinx: Added ubifs support
+    - misc: xilinx-ai-engine: Add support to request device management services
+    - dt-bindings: soc: xilinx: ai-engine: Add interrupt and power-domain
+      properties for AIE device
+    - misc: xilinx-ai-engine: Add helper functions to service interrupt
+      controllers and event registers
+    - firmware: xilinx: Add IOCTL support for AIE ISR Clear
+    - misc: xilinx-ai-engine: Add support for servicing error interrupts
+    - misc: xilinx-ai-engine: Log error events and classify them into categories
+    - misc: xilinx-ai-engine: Add APIs for kernel modules to handle error
+      interrupts
+    - dt-bindings: soc: xilinx: ai-engine: Add 64bit bus to example
+    - misc: xilinx-ai-engine: add tiles in use bitmap
+    - watchdog: of_xilinx_wdt: Skip printing pointer value
+    - watchdog: of_xilinx_wdt: Add interrupt and pretimeout properties for Versal
+      watchdog
+    - watchdog: of_xilinx_wdt: Add Versal Window watchdog support
+    - misc: xilinx-ai-engine: avoid creating multiple dmabufs for AIE mems
+    - misc: xilinx-ai-engine: Add AI engine partition reset function
+    - misc: xilinx-ai-engine: Add extern functions to reset partition
+    - memory: pl353: Fixed incompatible assignment
+    - mtd: rawnand: pl353: Removed unused variable
+    - mtd: rawnand: pl353: Initialized variable before using it
+    - misc: xilinx-ai-engine: remove unnecessary print
+    - misc: xilinx-ai-engine: fix PTR_ERR warning
+    - arm64: xilinx: zynqmp: Enable missed fbdev config during migration
+    - drm: xlnx: dsi: Add Generic long write command support
+    - reset: reset-zynqmp: Fixed the argument data type
+    - firmware: xilinx: Updated the reset function prototypes
+    - edac: synopsys: Fix the wrong value assignment for edac_mode
+    - misc: xilinx-ai-engine: Add function to clear an AI engine resource
+    - misc: xilinx-ai-engine: update reset API to use resource clear all function
+    - misc: xilinx-ai-engine: clear cached events of partition in reset/release
+    - dt-bindings: edac: Add bindings for Xilinx Versal EDAC for DDRMC
+    - edac: xilinx: Added EDAC support for Xilinx DDR controller
+    - arm64: xilinx: Enable Xilinx Versal DDR EDAC support
+    - net: xilinx: axiethernet: Pass phy interface to of_phy_connect()
+    - net: xilinx: Use prandom with range to avoid corner cases
+    - net: xilinx: XXV Ethernet HW timestamp fixes
+    - dt-bindings: net: Add devicetree documentation for MRMAC
+    - net: xilinx: Add MRMAC support
+    - dt-bindings: Add devicetree documentation for Xilinx PTP timer
+    - ptp: Add Xilinx PTP timer driver
+    - net: xilinx: Add HW timestamping support for MRMAC
+    - net: xilinx: Add missing kernel-doc descriptions
+    - can: xilinx_can: avoid non-requested bus error frames
+    - can: xilinx_can: fix checkpatch warnings
+    - drm: xlnx: bridge: Fix UNUSED_VALUE type warning
+    - drm: xlnx: bridge: Fix UNINIT type warnings
+    - drm: xlnx: bridge: Fix RESOURCE_LEAK type warning
+    - drm: xlnx: bridge: Fix PW.PARAMETER_HIDDEN type warning
+    - drm: xlnx: bridge: Fix NULL_RETURNS type warning
+    - drm: xlnx: fb: Fix OVERFLOW_BEFORE_WIDEN type warnings
+    - v4l: xilinx: xcsi2rxss: Fix warnings for NULL_RETURNS
+    - v4l: xilinx: sdirxss: Fix warnings for UNUSED_VALUE
+    - v4l: xilinx: sdirxss: Fix warnings for CONSTANT_EXPRESSION_RESULT
+    - v4l: xilinx: sdirxss: Fix warnings for NULL_RETURNS
+    - v4l: xilinx-demosaic: Fix warnings for NULL_RETURNS
+    - v4l: xilinx-demosaic: Fix for warning UNUSED_VALUE
+    - media: xilinx: vtc: Fix warning for OVERFLOW_BEFORE_WIDEN
+    - v4l: xilinx: tpg: Fix warnings for NULL_RETURNS
+    - v4l: xilinx: tpg: Fix warnings for CHECKED_RETURN
+    - v4l: xilinx: vpss-scaler: Fix warnings for NULL_RETURNS
+    - v4l: xilinx: vpss-scaler: Fix warnings for UNINIT
+    - v4l: xilinx: vpss-csc: Fix warnings for NULL_RETURNS
+    - v4l: xilinx: vpss-csc: Fix warning for UNINIT
+    - v4l: xilinx: vpss-csc: Fix warning for PW.MIXED_ENUM_TYPE
+    - v4l: xilinx: axis-switch: Fix warnings for NULL_RETURNS
+    - v4l: xilinx: axis-switch: Fix warnings for UNINIT
+    - v4l: xilinx-gamma: Fix warnings for NULL_RETURNS
+    - v4l: xilinx-gamma: Fix warnings for UNUSED_VALUE
+    - v4l: xilinx: cfa: Fix warnings for NULL_RETURNS
+    - v4l: xilinx: cresample: Fix warnings for NULL_RETURNS
+    - v4l: xilinx: dprx: Fix warnings for NULL_RETURNS
+    - v4l: xilinx: dprx: Fix warnings for UNINIT
+    - media: xilinx: hls: Fix warnings for NULL_RETURNS
+    - v4l: xilinx: remapper: Fix warning for UNINIT
+    - v4l: xilinx: remapper: Fix warnings for NULL_RETURNS
+    - v4l: xilinx: remapper: Fix warnings for CHECKED_RETURN
+    - v4l: xilinx: rgb2yuv: Fix warnings for NULL_RETURNS
+    - v4l: xilinx: scaler: Fix warnings for NULL_RETURNS
+    - v4l: xilinx: switch: Fix warnings for NULL_RETURNS
+    - v4l: xilinx: switch: Fix warnings for UNINIT
+    - v4l: xilinx: switch: Fix warnings for OVERFLOW_BEFORE_WIDEN
+    - dmaengine: xilinx: frmbuf: Fix warnings for PW.MIXED_ENUM_TYPE
+    - dmaengine: xilinx: frmbuf: Fix warnings for UNINIT
+    - misc: xilinx-ai-engine: Add error category to the AIE error struct
+    - misc: xilinx-ai-engine: use error category property in get errors categories
+    - misc: xilinx-ai-engine: Add errors categories masks macro
+    - dt-bindings: serial: Add xilinx compatible
+    - tty: pl011: Add support for xilinx uart
+    - ASoC: xlnx: formatter: Fix warnings for PW.SET_BUT_NOT_USED
+    - ASoC: xlnx: formatter: Fix warnings for NULL_RETURNS
+    - ASoC: xlnx: formatter: Fix warnings for UNINIT
+    - ASoC: xlnx: formatter: Fix warnings for UNUSED_VALUE
+    - ASoC: xlnx: formatter: Fix warnings for PW.SET_BUT_NOT_USED
+    - ASoC: xlnx: i2s: Fix warnings for UNINIT
+    - ASoC: xlnx: spdif: Fix warnings for PW.SET_BUT_NOT_USED
+    - ASoC: xlnx: sdiaudio: Fix warnings for PW.SET_BUT_NOT_USED
+    - ASoC: xlnx: sdiaudio: Fix warnings for DEADCODE
+    - drm: xlnx: pl_disp: Fix MIXED_ENUM_TYPE type warning
+    - drm: xlnx: zynqmp_dp: Fix UNINIT type warning
+    - drm: xlnx: zynqmp_dp: Fix CHECKED_RETURN type warnings
+    - drm: xlnx: zynqmp_dp: Fix OVERRUN type warning
+    - drm: xlnx: zynqmp_disp: Fix UNINIT type warning
+    - drm: xlnx: zynqmp_disp: Fix CHECKED_RETURN type warnings
+    - drm: xlnx: zynqmp_disp: Fix OVERFLOW_BEFORE_WIDEN type warnings
+    - drm: xlnx: zynqmp_disp: Fix MIXED_ENUM_TYPE type warnings
+    - net: xilinx: Fix indentation issues
+    - net: xilinx: axiethernet: Add check for transmit data FIFO vacancy
+    - media: videodev2.h: Add control type for HDR
+    - Revert "microblaze: Fix TLB mapping"
+    - pinctrl: zynqmp: Remove unused variable zynqmp_pins
+    - pinctrl: zynqmp: Return 'ret' instead of Success always
+    - pinctrl: zynqmp: Initialize the ret variable with zero
+    - v4l: xilinx: sdirxss: Update HDR control type
+    - drm: xlnx: sdi: Fix dynamic clock config to support QPLL1 reset.
+    - misc: xilinx-ai-engine: Create bitmaps to manage level 2 controller
+    - misc: xilinx-ai-engine: Handle interrupts in kthreads
+    - misc: xilinx-ai-engine: Handle error interrupts for partitions not yet
+      requested
+    - misc: xilinx-ai-engine: Clear broadcast event status
+    - misc: xilinx-ai-engine: Fix for-loop control limits
+    - misc: xilinx-ai-engine: Return NULL if no errors were found
+    - fpga: zynq: Fix incorrect variable type
+    - fpga: zynqmp: Initialized variables before using it
+    - fpga: zynqmp: Fix incorrect variables type
+    - fpga: versal: Initialized variables before using it
+    - i2c-cadence: Check the return value of pin-ctrl
+    - i2c-cadence: Replace the value with enum
+    - i2c-xiic: return value of xiic_reinit
+    - staging: xlnxsync: Remove channel interrupt mask handling at enable/disable
+    - staging: xlnxsync: Add new ioctl to set interrupt mask
+    - staging: xlnxsync: Rename interrupt mask register macro
+    - staging: xlnxsync: Mask the interrupt bit as soon as interrupt occurs
+    - staging: xlnxsync: Switch to rising edge interrupt
+    - staging: xlnxsync: Reset channel error status after it is read
+    - staging: xlnxsync: Unmask the interrupt in clear channel error IOCTL
+    - staging: xlnxsync: Reuse the xlnxsync_err_intr structure
+    - mtd: spi-nor: Fix for setting quad mode on Spansion Flash in dual parallel
+    - v4l: xilinx: sdirxss: Fix colorimetry dectection for HD mode
+    - v4l: xilinx: sdirxss: Update video params when stream changes without unlock
+    - drm: xlnx: sdi: Update EOTF and colorimetry fields in payload.
+    - Revert "mtd: spi-nor: Fix for setting quad mode on Spansion Flash in dual
+      parallel"
+    - mtd: spi-nor: Fix for setting quad mode on Spansion Flash in dual parallel
+    - clk: clock-wizard: Revert "Use all stages of the MMCM"
+    - xilinx: Enable HWMON and PMBUS
+    - mmc: sdhci-of-arasan: Allow configuring zero Tap values
+    - mmc: sdhci-of-arasan: Use Mask writes for Tap delays
+    - mmc: sdhci-of-arasan: Issue DLL reset explicitly
+    - usb: dwc3: otg: Enable OTG support in dwc3-core driver
+    - v4l: xilinx: m2m: Fix spelling of driver model
+    - v4l: xilinx: m2m: Fix kernel crash for async notifier
+    - v4l: xilinx: m2m: Fix kernel crash for link creation to video entity
+    - dt: bindings: media: xilinx: sdirxss : Add optional PICXO gpio handle
+    - v4l: xilinx: sdirxss: Add support for PICXO
+    - dt-bindings: display: xlnx: sdi: Update for PICXO
+    - drm: xlnx: sdi: Add support to non-picxo designs
+    - dmaengine: xilinx: frmbuf: Replace AP_READY with AP_DONE
+    - usb: dwc3: Make dwc3 work with CONFIG_PM disabled
+    - dt-bindings: media: xilinx: Fix compatible string
+    - v4l: xilinx: Fix compatible string
+    - v4l: xilinx: update the bits per component
+    - drm: xlnx: sdi: Add supported EOTF's list to connector.
+    - drm: xlnx: sdi_modes: Updated timing parameters at frame level
+    - drm: xlnx: sdi: Add mode_valid helper function
+    - v4l: xilinx: sdirxss: Fix PLL reference clock to 148.5MHz for SD mode
+    - dt-bindings: display: xlnx: dptx: Fix compatible string and remove Remapper
+    - drm: xlnx: dptx: Fix compilation string and remove AXI Remapper support
+    - drm: xlnx: dptx: Correct FIELD_GET function and fix the training issue
+    - v4l: xilinx: sdirxss: Rate limit irq handler error messages
+    - hdmi-common: Add helpers to parse and generate HDR Aux packets
+    - hdmirxss: Add infra for DRM infoframe reporting
+    - hdmitxss: Add infra for DRM infoframe reporting
+    - hdmirx: Add g_volatile_ctrl handling to v4l subdev
+    - hdmitx: Program Tx with HDR metadata set by user
+    - dp159: Fix probe failure on multi instance load
+    - hdmitx: fix to reset drm metadata type on stream down
+    - hdmi: Report EOTF in the info
+    - hdmi-common: Fix length of HDR payload
+    - hdmitx: Add AR24 and AB24 to list of supported DRM formats
+    - hdmitx: Fix bridge enablement
+    - hdmitx: Add audio register changes in core
+    - hdmirx: Add audio register changes in core
+    - hdmitx: program audio channels based on hw_params
+    - hdmitx: parse and store ELD
+    - hdmirx: Modify EDID for 8 channel
+    - hdmitx: fix coverity warning for CHECKED_RETURN
+    - hdmitx: fix coverity warning for COPY_PASTE_ERROR
+    - hdmitx: Check NULL return on kzalloc in Decrypt()
+    - hdmitx: Fix potential infinite loop error in Decrypt()
+    - hdmitx: Check for null pointer returned by of_match_node()
+    - hdmitx: Fix coverity NULL_RETURNS warning for resource
+    - hdmitx: Fix the coverity warning OVERFLOW_BEFORE_WIDEN
+    - hdmitx: Fix coverity warning type PW.DECLARED_BUT_NOT_REFERNCED
+    - hdmitx : Fix coverity warning of UNINIT type
+    - hdmitx: Fix coverity warning for RESOURCE_LEAK
+    - hdmitx: Fix coverity warnings for typecasting
+    - hdmitx: Fix coverity warning PW.SET_BUT_NOT_USED type
+    - hdmirx: Fix CHECKED_RETURN coverity warning
+    - hdmirx: Fix COPY_PASTE_ERROR coverity warning
+    - hdmirx: Fix INFINITE_LOOP coverity warning
+    - hdmirx: Fix NULL_RETURNS coverity warning
+    - hdmirx: Fix OVERFLOW_BEFORE_WIDEN coverity warning
+    - hdmirx: Fix PW.DECLARED_BUT_NOT_REFERENCED coverity warning
+    - hdmirx: Fix PW.INCOMPATIBLE_PARAM coverity warning
+    - hdmirx: Fix PW.SET_BUT_NOT_USED coverity warning.
+    - hdmirx: Fix UNINIT coverity warning
+    - hdmirx: Fix REVERSE_INULL coverity warning.
+    - hdmirx: Update HDR control type
+    - hdmirx: Set color format based on AVI Infoframe
+    - hdmitx: Set AVI infoframe based on properties set by user
+    - hdmirx: report source change on change in AVI infoframe
+    - Fixes in hdmirx and hdmirxss till 20200921
+    - Fixes in vphy and hdmiphy till 20200921
+    - phy: hdmigtctrl: remove GT workaround on pll type
+    - license: Update the license 2020.2
+    - Add the rc_plugin_fd field
+    - Add __GFP_NOWARN to avoid CMA allocation warnings
+    - Update kernel configs to 2020.2
+    - merge: close
+
+ -- Wen-chien Jesse Sung <jesse.sung@canonical.com>  Thu, 21 Jan 2021 23:16:39 +0800
+
+linux-xilinx-zynqmp (5.4.0-1006.7) focal; urgency=medium
+
+  * System hang with sdhci: ADMA Err while running stress-ng os test // System
+    hang with soft lockup while running cpu stress test // System hang with soft
+    lockup while running warm boot stress test
+    - crypto: zynqmp_sha: Make driver thread-safe
+
+  * System could not be woken up by WOL from S3 or S5
+    - SAUCE: net: macb: Consolidate wakeup settings onto platform device
+
+ -- Hsuan-Yu Lin <shane.lin@canonical.com>  Wed, 13 Jan 2021 14:40:35 +0800
+
+linux-xilinx-zynqmp (5.4.0-1005.6) focal; urgency=medium
+
+  * INVALID or PRIVATE BUG (LP: #1904021)
+    - Enable CONFIG_UBIFS_FS_ADVANCED_COMPR
+
+  * dmatest: write error: Device or resource busy // omx_encoder: DMAMemory:
+    Device or resource busy
+    - [Config] Disable ASYNC and RAID related functions
+
+  * Miscellaneous Ubuntu changes
+    - [Config] Align configs with ZynqMP configs
+    - [Config] Disable DKMS: zfs and wireguard
+    - [Config] Remove unnecessary kernel module names
+
+ -- Hsuan-Yu Lin <shane.lin@canonical.com>  Thu, 26 Nov 2020 16:13:20 +0800
+
+linux-xilinx-zynqmp (5.4.0-1004.5) focal; urgency=medium
+
+  * Miscellaneous upstream changes
+    - Disable CONFIG_VIDEO_ALLEGRO_DVT
+
+ -- Hsuan-Yu Lin <shane.lin@canonical.com>  Thu, 29 Oct 2020 14:44:45 +0800
+
+linux-xilinx-zynqmp (5.4.0-1003.4) focal; urgency=medium
+
+  * Miscellaneous upstream changes
+    - Enable Xilinx HDMI kernel modules
+    - Import Xilinx VCU kernel modules
+    - Enable VCU kernel modules as default
+
+ -- Hsuan-Yu Lin <shane.lin@canonical.com>  Wed, 28 Oct 2020 15:04:36 +0800
+
+linux-xilinx-zynqmp (5.4.0-1002.3) focal; urgency=medium
+
+  * CVE-2020-12351 // CVE-2020-12352 // CVE-2020-24490
+    - [Config] Disable BlueZ highspeed support
+
+  * INVALID or PRIVATE BUG (LP: #1900871)
+    - Remove unnecessary debug messages from zocl
+
+  * Miscellaneous Ubuntu changes
+    - [Config] enable tracing/profiling options
+
+  * Miscellaneous upstream changes
+    - Import Mali source code
+    - Change Makefile to be compatible with Yocto
+    - staging: mali: r8p0-01rel0: Add the ZYNQ/ZYNQMP platform
+    - staging: mali: r8p0-01rel0: Remove unused trace macros
+    - staging: mali: r8p0-01rel0: Don't include mali_read_phys() for zynq/zynqmp
+    - linux/mali_kernel_linux.c: Handle clock when probed and removed
+    - arm.c: global variable dma_ops is removed from the kernel 4.7
+    - common/mali_pm.c: Add PM runtime barrier after removing suspend
+    - linux/mali_kernel_linux.c: Enable/disable clock for runtime resume/suspend
+    - linux: mali_memory_os_alloc: Remove __GFP_COLD
+    - linux: mali_memory_secure: Add header file dma-direct.h
+    - linux: mali_*timer: Get rid of init_timer
+    - Fix driver failed to check map error
+    - mali_memory_secure: Kernel 5.0 onwards 'access_ok' API does not take 'type'
+      as input parameter
+    - Support for vm_insert_pfn deprecated from kernel 4.20
+    - Change return type to vm_fault_t for fault handler
+    - "get_monotonic_boottime(&ts)" deprecated from kernel 4.20 onwards
+    - Enable Mali kernel module and fix build directories for ZYNQMP platform
+
+  [ Ubuntu: 5.4.0-52.57 ]
+
+  * focal/linux: 5.4.0-52.57 -proposed tracker (LP: #1899920)
+  * CVE-2020-12351 // CVE-2020-12352 // CVE-2020-24490
+    - Bluetooth: Disable High Speed by default
+    - Bluetooth: MGMT: Fix not checking if BT_HS is enabled
+    - [Config] Disable BlueZ highspeed support
+  * CVE-2020-12351
+    - Bluetooth: L2CAP: Fix calling sk_filter on non-socket based channel
+  * CVE-2020-12352
+    - Bluetooth: A2MP: Fix not initializing all members
+
+ -- Hsuan-Yu Lin <shane.lin@canonical.com>  Mon, 26 Oct 2020 15:36:42 +0800
+
+linux-xilinx-zynqmp (5.4.0-1001.2) focal; urgency=medium
+
+  * Focal update: v5.4.61 upstream stable release (LP: #1893115)
+    - [Config] update config for SPI_DYNAMIC
+
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update variants
+    - [Packaging] update update.conf
+
+  * Disable CONFIG_ARCH_VEXPRESS
+    - [Config] disable target platforms other than Xilinx ZynqMP
+
+  * Miscellaneous upstream changes
+    - clk, clk-si5341: Support multiple input ports
+    - Enable XRT
+
+  [ Ubuntu: 5.4.0-51.56 ]
+
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+
+  [ Ubuntu: 5.4.0-50.55 ]
+
+  * CVE-2020-16119
+    - SAUCE: dccp: avoid double free of ccid on child socket
+  * CVE-2020-16120
+    - Revert "UBUNTU: SAUCE: overlayfs: ensure mounter privileges when reading
+      directories"
+    - ovl: pass correct flags for opening real directory
+    - ovl: switch to mounter creds in readdir
+    - ovl: verify permissions in ovl_path_open()
+    - ovl: call secutiry hook in ovl_real_ioctl()
+    - ovl: check permission to open real file
+
+  [ Ubuntu: 5.4.0-49.53 ]
+
+  * focal/linux: 5.4.0-49.53 -proposed tracker (LP: #1896007)
+  * Comet Lake PCH-H RAID not support on Ubuntu20.04 (LP: #1892288)
+    - ahci: Add Intel Comet Lake PCH-H PCI ID
+  * Novalink (mkvterm command failure) (LP: #1892546)
+    - tty: hvcs: Don't NULL tty->driver_data until hvcs_cleanup()
+  * Oops and hang when starting LVM snapshots on 5.4.0-47 (LP: #1894780)
+    - SAUCE: Revert "mm: memcg/slab: fix memory leak at non-root kmem_cache
+      destroy"
+  * Intel x710 LOMs do not work on Focal (LP: #1893956)
+    - i40e: Fix LED blinking flow for X710T*L devices
+    - i40e: enable X710 support
+  * Add/Backport EPYC-v3 and EPYC-Rome CPU model (LP: #1887490)
+    - kvm: svm: Update svm_xsaves_supported
+  * Fix non-working NVMe after S3 (LP: #1895718)
+    - SAUCE: PCI: Enable ACS quirk on CML root port
+  * Focal update: v5.4.65 upstream stable release (LP: #1895881)
+    - ipv4: Silence suspicious RCU usage warning
+    - ipv6: Fix sysctl max for fib_multipath_hash_policy
+    - netlabel: fix problems with mapping removal
+    - net: usb: dm9601: Add USB ID of Keenetic Plus DSL
+    - sctp: not disable bh in the whole sctp_get_port_local()
+    - taprio: Fix using wrong queues in gate mask
+    - tipc: fix shutdown() of connectionless socket
+    - net: disable netpoll on fresh napis
+    - Linux 5.4.65
+  * Focal update: v5.4.64 upstream stable release (LP: #1895880)
+    - HID: quirks: Always poll three more Lenovo PixArt mice
+    - drm/msm/dpu: Fix scale params in plane validation
+    - tty: serial: qcom_geni_serial: Drop __init from qcom_geni_console_setup
+    - drm/msm: add shutdown support for display platform_driver
+    - hwmon: (applesmc) check status earlier.
+    - nvmet: Disable keep-alive timer when kato is cleared to 0h
+    - drm/msm: enable vblank during atomic commits
+    - habanalabs: validate FW file size
+    - habanalabs: check correct vmalloc return code
+    - drm/msm/a6xx: fix gmu start on newer firmware
+    - ceph: don't allow setlease on cephfs
+    - drm/omap: fix incorrect lock state
+    - cpuidle: Fixup IRQ state
+    - nbd: restore default timeout when setting it to zero
+    - s390: don't trace preemption in percpu macros
+    - drm/amd/display: Reject overlay plane configurations in multi-display
+      scenarios
+    - drivers: gpu: amd: Initialize amdgpu_dm_backlight_caps object to 0 in
+      amdgpu_dm_update_backlight_caps
+    - drm/amd/display: Retry AUX write when fail occurs
+    - drm/amd/display: Fix memleak in amdgpu_dm_mode_config_init
+    - xen/xenbus: Fix granting of vmalloc'd memory
+    - fsldma: fix very broken 32-bit ppc ioread64 functionality
+    - dmaengine: of-dma: Fix of_dma_router_xlate's of_dma_xlate handling
+    - batman-adv: Avoid uninitialized chaddr when handling DHCP
+    - batman-adv: Fix own OGM check in aggregated OGMs
+    - batman-adv: bla: use netif_rx_ni when not in interrupt context
+    - dmaengine: at_hdmac: check return value of of_find_device_by_node() in
+      at_dma_xlate()
+    - rxrpc: Keep the ACK serial in a var in rxrpc_input_ack()
+    - rxrpc: Make rxrpc_kernel_get_srtt() indicate validity
+    - MIPS: mm: BMIPS5000 has inclusive physical caches
+    - MIPS: BMIPS: Also call bmips_cpu_setup() for secondary cores
+    - mmc: sdhci-acpi: Fix HS400 tuning for AMDI0040
+    - netfilter: nf_tables: add NFTA_SET_USERDATA if not null
+    - netfilter: nf_tables: incorrect enum nft_list_attributes definition
+    - netfilter: nf_tables: fix destination register zeroing
+    - net: hns: Fix memleak in hns_nic_dev_probe
+    - net: systemport: Fix memleak in bcm_sysport_probe
+    - ravb: Fixed to be able to unload modules
+    - net: arc_emac: Fix memleak in arc_mdio_probe
+    - dmaengine: pl330: Fix burst length if burst size is smaller than bus width
+    - gtp: add GTPA_LINK info to msg sent to userspace
+    - net: ethernet: ti: cpsw: fix clean up of vlan mc entries for host port
+    - bnxt_en: Don't query FW when netif_running() is false.
+    - bnxt_en: Check for zero dir entries in NVRAM.
+    - bnxt_en: Fix PCI AER error recovery flow
+    - bnxt_en: Fix possible crash in bnxt_fw_reset_task().
+    - bnxt_en: fix HWRM error when querying VF temperature
+    - xfs: fix boundary test in xfs_attr_shortform_verify
+    - bnxt: don't enable NAPI until rings are ready
+    - media: vicodec: add missing v4l2_ctrl_request_hdl_put()
+    - media: cedrus: Add missing v4l2_ctrl_request_hdl_put()
+    - selftests/bpf: Fix massive output from test_maps
+    - net: dsa: mt7530: fix advertising unsupported 1000baseT_Half
+    - netfilter: nfnetlink: nfnetlink_unicast() reports EAGAIN instead of ENOBUFS
+    - nvmet-fc: Fix a missed _irqsave version of spin_lock in
+      'nvmet_fc_fod_op_done()'
+    - nvme: fix controller instance leak
+    - cxgb4: fix thermal zone device registration
+    - perf tools: Correct SNOOPX field offset
+    - net: ethernet: mlx4: Fix memory allocation in mlx4_buddy_init()
+    - fix regression in "epoll: Keep a reference on files added to the check list"
+    - net: gemini: Fix another missing clk_disable_unprepare() in probe
+    - MIPS: add missing MSACSR and upper MSA initialization
+    - xfs: fix xfs_bmap_validate_extent_raw when checking attr fork of rt files
+    - perf jevents: Fix suspicious code in fixregex()
+    - tg3: Fix soft lockup when tg3_reset_task() fails.
+    - x86, fakenuma: Fix invalid starting node ID
+    - iommu/vt-d: Serialize IOMMU GCMD register modifications
+    - thermal: ti-soc-thermal: Fix bogus thermal shutdowns for omap4430
+    - thermal: qcom-spmi-temp-alarm: Don't suppress negative temp
+    - iommu/amd: Restore IRTE.RemapEn bit after programming IRTE
+    - include/linux/log2.h: add missing () around n in roundup_pow_of_two()
+    - iommu/vt-d: Handle 36bit addressing for x86-32
+    - tracing/kprobes, x86/ptrace: Fix regs argument order for i386
+    - ext2: don't update mtime on COW faults
+    - xfs: don't update mtime on COW faults
+    - ARC: perf: don't bail setup if pct irq missing in device-tree
+    - btrfs: drop path before adding new uuid tree entry
+    - btrfs: allocate scrub workqueues outside of locks
+    - btrfs: set the correct lockdep class for new nodes
+    - btrfs: set the lockdep class for log tree extent buffers
+    - btrfs: tree-checker: fix the error message for transid error
+    - net: core: use listified Rx for GRO_NORMAL in napi_gro_receive()
+    - btrfs: fix potential deadlock in the search ioctl
+    - ALSA: ca0106: fix error code handling
+    - ALSA: usb-audio: Add implicit feedback quirk for UR22C
+    - ALSA: pcm: oss: Remove superfluous WARN_ON() for mulaw sanity check
+    - ALSA: hda/hdmi: always check pin power status in i915 pin fixup
+    - ALSA: firewire-digi00x: exclude Avid Adrenaline from detection
+    - ALSA: hda - Fix silent audio output and corrupted input on MSI X570-A PRO
+    - ALSA; firewire-tascam: exclude Tascam FE-8 from detection
+    - ALSA: hda/realtek: Add quirk for Samsung Galaxy Book Ion NT950XCJ-X716A
+    - ALSA: hda/realtek - Improved routing for Thinkpad X1 7th/8th Gen
+    - arm64: dts: mt7622: add reset node for mmc device
+    - mmc: mediatek: add optional module reset property
+    - mmc: dt-bindings: Add resets/reset-names for Mediatek MMC bindings
+    - mmc: cqhci: Add cqhci_deactivate()
+    - mmc: sdhci-pci: Fix SDHCI_RESET_ALL for CQHCI for Intel GLK-based
+      controllers
+    - media: rc: do not access device via sysfs after rc_unregister_device()
+    - media: rc: uevent sysfs file races with rc_unregister_device()
+    - affs: fix basic permission bits to actually work
+    - block: allow for_each_bvec to support zero len bvec
+    - block: ensure bdi->io_pages is always initialized
+    - libata: implement ATA_HORKAGE_MAX_TRIM_128M and apply to Sandisks
+    - blk-iocost: ioc_pd_free() shouldn't assume irq disabled
+    - dmaengine: dw-edma: Fix scatter-gather address calculation
+    - drm/amd/pm: avoid false alarm due to confusing softwareshutdowntemp setting
+    - dm writecache: handle DAX to partitions on persistent memory correctly
+    - dm mpath: fix racey management of PG initialization
+    - dm integrity: fix error reporting in bitmap mode after creation
+    - dm crypt: Initialize crypto wait structures
+    - dm cache metadata: Avoid returning cmd->bm wild pointer on error
+    - dm thin metadata: Avoid returning cmd->bm wild pointer on error
+    - dm thin metadata: Fix use-after-free in dm_bm_set_read_only
+    - mm: slub: fix conversion of freelist_corrupted()
+    - mm: madvise: fix vma user-after-free
+    - vfio/pci: Fix SR-IOV VF handling with MMIO blocking
+    - perf record: Correct the help info of option "--no-bpf-event"
+    - sdhci: tegra: Add missing TMCLK for data timeout
+    - checkpatch: fix the usage of capture group ( ... )
+    - mm/hugetlb: fix a race between hugetlb sysctl handlers
+    - mm/khugepaged.c: fix khugepaged's request size in collapse_file
+    - cfg80211: regulatory: reject invalid hints
+    - net: usb: Fix uninit-was-stored issue in asix_read_phy_addr()
+    - Linux 5.4.64
+  * Focal update: v5.4.63 upstream stable release (LP: #1895879)
+    - HID: core: Correctly handle ReportSize being zero
+    - HID: core: Sanitize event code and type when mapping input
+    - perf record/stat: Explicitly call out event modifiers in the documentation
+    - drm/sched: Fix passing zero to 'PTR_ERR' warning v2
+    - drm/etnaviv: fix TS cache flushing on GPUs with BLT engine
+    - KVM: arm64: Add kvm_extable for vaxorcism code
+    - KVM: arm64: Survive synchronous exceptions caused by AT instructions
+    - KVM: arm64: Set HCR_EL2.PTW to prevent AT taking synchronous exception
+    - dt-bindings: mmc: tegra: Add tmclk for Tegra210 and later
+    - arm64: tegra: Add missing timeout clock to Tegra194 SDMMC nodes
+    - arm64: tegra: Add missing timeout clock to Tegra186 SDMMC nodes
+    - arm64: tegra: Add missing timeout clock to Tegra210 SDMMC
+    - sdhci: tegra: Remove SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK for Tegra210
+    - sdhci: tegra: Remove SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK for Tegra186
+    - scsi: target: tcmu: Fix size in calls to tcmu_flush_dcache_range
+    - scsi: target: tcmu: Optimize use of flush_dcache_page
+    - Linux 5.4.63
+  * Focal update: v5.4.62 upstream stable release (LP: #1895174)
+    - binfmt_flat: revert "binfmt_flat: don't offset the data start"
+    - gre6: Fix reception with IP6_TNL_F_RCV_DSCP_COPY
+    - net: Fix potential wrong skb->protocol in skb_vlan_untag()
+    - net: nexthop: don't allow empty NHA_GROUP
+    - net: qrtr: fix usage of idr in port assignment to socket
+    - net: sctp: Fix negotiation of the number of data streams.
+    - net/smc: Prevent kernel-infoleak in __smc_diag_dump()
+    - tipc: fix uninit skb->data in tipc_nl_compat_dumpit()
+    - net: ena: Make missed_tx stat incremental
+    - net/sched: act_ct: Fix skb double-free in tcf_ct_handle_fragments() error
+      flow
+    - ipvlan: fix device features
+    - ALSA: pci: delete repeated words in comments
+    - ASoC: img: Fix a reference count leak in img_i2s_in_set_fmt
+    - ASoC: img-parallel-out: Fix a reference count leak
+    - ASoC: tegra: Fix reference count leaks.
+    - mfd: intel-lpss: Add Intel Emmitsburg PCH PCI IDs
+    - arm64: dts: qcom: msm8916: Pull down PDM GPIOs during sleep
+    - powerpc/xive: Ignore kmemleak false positives
+    - media: pci: ttpci: av7110: fix possible buffer overflow caused by bad DMA
+      value in debiirq()
+    - blktrace: ensure our debugfs dir exists
+    - scsi: target: tcmu: Fix crash on ARM during cmd completion
+    - mfd: intel-lpss: Add Intel Tiger Lake PCH-H PCI IDs
+    - iommu/iova: Don't BUG on invalid PFNs
+    - drm/amdkfd: Fix reference count leaks.
+    - drm/radeon: fix multiple reference count leak
+    - drm/amdgpu: fix ref count leak in amdgpu_driver_open_kms
+    - drm/amd/display: fix ref count leak in amdgpu_drm_ioctl
+    - drm/amdgpu: fix ref count leak in amdgpu_display_crtc_set_config
+    - drm/amdgpu/display: fix ref count leak when pm_runtime_get_sync fails
+    - scsi: lpfc: Fix shost refcount mismatch when deleting vport
+    - xfs: Don't allow logging of XFS_ISTALE inodes
+    - scsi: target: Fix xcopy sess release leak
+    - selftests/powerpc: Purge extra count_pmc() calls of ebb selftests
+    - f2fs: fix error path in do_recover_data()
+    - omapfb: fix multiple reference count leaks due to pm_runtime_get_sync
+    - PCI: Fix pci_create_slot() reference count leak
+    - ARM: dts: ls1021a: output PPS signal on FIPER2
+    - rtlwifi: rtl8192cu: Prevent leaking urb
+    - mips/vdso: Fix resource leaks in genvdso.c
+    - cec-api: prevent leaking memory through hole in structure
+    - HID: quirks: add NOGET quirk for Logitech GROUP
+    - f2fs: fix use-after-free issue
+    - drm/nouveau/drm/noveau: fix reference count leak in nouveau_fbcon_open
+    - drm/nouveau: fix reference count leak in nv50_disp_atomic_commit
+    - drm/nouveau: Fix reference count leak in nouveau_connector_detect
+    - locking/lockdep: Fix overflow in presentation of average lock-time
+    - btrfs: file: reserve qgroup space after the hole punch range is locked
+    - btrfs: make btrfs_qgroup_check_reserved_leak take btrfs_inode
+    - scsi: iscsi: Do not put host in iscsi_set_flashnode_param()
+    - ceph: fix potential mdsc use-after-free crash
+    - ceph: do not access the kiocb after aio requests
+    - scsi: fcoe: Memory leak fix in fcoe_sysfs_fcf_del()
+    - EDAC/ie31200: Fallback if host bridge device is already initialized
+    - hugetlbfs: prevent filesystem stacking of hugetlbfs
+    - media: davinci: vpif_capture: fix potential double free
+    - KVM: arm64: Fix symbol dependency in __hyp_call_panic_nvhe
+    - powerpc/spufs: add CONFIG_COREDUMP dependency
+    - USB: sisusbvga: Fix a potential UB casued by left shifting a negative value
+    - brcmfmac: Set timeout value when configuring power save
+    - efi: provide empty efi_enter_virtual_mode implementation
+    - arm64: Fix __cpu_logical_map undefined issue
+    - Revert "ath10k: fix DMA related firmware crashes on multiple devices"
+    - sched/uclamp: Protect uclamp fast path code with static key
+    - sched/uclamp: Fix a deadlock when enabling uclamp static key
+    - usb: cdns3: gadget: always zeroed TRB buffer when enable endpoint
+    - PM / devfreq: rk3399_dmc: Add missing of_node_put()
+    - PM / devfreq: rk3399_dmc: Disable devfreq-event device when fails
+    - PM / devfreq: rk3399_dmc: Fix kernel oops when rockchip,pmu is absent
+    - drm/xen: fix passing zero to 'PTR_ERR' warning
+    - drm/xen-front: Fix misused IS_ERR_OR_NULL checks
+    - s390/numa: set node distance to LOCAL_DISTANCE
+    - btrfs: factor out inode items copy loop from btrfs_log_inode()
+    - btrfs: only commit the delayed inode when doing a full fsync
+    - btrfs: only commit delayed items at fsync if we are logging a directory
+    - mm/shuffle: don't move pages between zones and don't read garbage memmaps
+    - mm: fix kthread_use_mm() vs TLB invalidate
+    - mm/cma.c: switch to bitmap_zalloc() for cma bitmap allocation
+    - cma: don't quit at first error when activating reserved areas
+    - gpu/drm: ingenic: Use the plane's src_[x,y] to configure DMA length
+    - drm/ingenic: Fix incorrect assumption about plane->index
+    - drm/amd/display: Trigger modesets on MST DSC connectors
+    - drm/amd/display: Add additional config guards for DCN
+    - drm/amd/display: Fix dmesg warning from setting abm level
+    - mm/vunmap: add cond_resched() in vunmap_pmd_range
+    - EDAC: sb_edac: get rid of unused vars
+    - EDAC: skx_common: get rid of unused type var
+    - EDAC/{i7core,sb,pnd2,skx}: Fix error event severity
+    - PCI: qcom: Add missing ipq806x clocks in PCIe driver
+    - PCI: qcom: Change duplicate PCI reset to phy reset
+    - PCI: qcom: Add missing reset for ipq806x
+    - cpufreq: intel_pstate: Fix EPP setting via sysfs in active mode
+    - ALSA: usb-audio: Add capture support for Saffire 6 (USB 1.1)
+    - media: gpio-ir-tx: improve precision of transmitted signal due to scheduling
+    - block: respect queue limit of max discard segment
+    - block: virtio_blk: fix handling single range discard request
+    - drm/msm/adreno: fix updating ring fence
+    - block: Fix page_is_mergeable() for compound pages
+    - bfq: fix blkio cgroup leakage v4
+    - hwmon: (nct7904) Correct divide by 0
+    - blk-mq: insert request not through ->queue_rq into sw/scheduler queue
+    - blkcg: fix memleak for iolatency
+    - nvme-fc: Fix wrong return value in __nvme_fc_init_request()
+    - nvme: multipath: round-robin: fix single non-optimized path case
+    - null_blk: fix passing of REQ_FUA flag in null_handle_rq
+    - i2c: core: Don't fail PRP0001 enumeration when no ID table exist
+    - i2c: rcar: in slave mode, clear NACK earlier
+    - usb: gadget: f_tcm: Fix some resource leaks in some error paths
+    - spi: stm32: clear only asserted irq flags on interrupt
+    - jbd2: make sure jh have b_transaction set in refile/unfile_buffer
+    - ext4: don't BUG on inconsistent journal feature
+    - ext4: handle read only external journal device
+    - jbd2: abort journal if free a async write error metadata buffer
+    - ext4: handle option set by mount flags correctly
+    - ext4: handle error of ext4_setup_system_zone() on remount
+    - ext4: correctly restore system zone info when remount fails
+    - fs: prevent BUG_ON in submit_bh_wbc()
+    - spi: stm32h7: fix race condition at end of transfer
+    - spi: stm32: fix fifo threshold level in case of short transfer
+    - spi: stm32: fix stm32_spi_prepare_mbr in case of odd clk_rate
+    - spi: stm32: always perform registers configuration prior to transfer
+    - drm/amd/powerplay: correct Vega20 cached smu feature state
+    - drm/amd/powerplay: correct UVD/VCE PG state on custom pptable uploading
+    - drm/amd/display: Switch to immediate mode for updating infopackets
+    - netfilter: avoid ipv6 -> nf_defrag_ipv6 module dependency
+    - can: j1939: transport: j1939_xtp_rx_dat_one(): compare own packets to detect
+      corruptions
+    - ALSA: hda/realtek: Add model alc298-samsung-headphone
+    - s390/cio: add cond_resched() in the slow_eval_known_fn() loop
+    - ASoC: wm8994: Avoid attempts to read unreadable registers
+    - selftests: disable rp_filter for icmp_redirect.sh
+    - scsi: fcoe: Fix I/O path allocation
+    - scsi: ufs: Fix possible infinite loop in ufshcd_hold
+    - scsi: ufs: Improve interrupt handling for shared interrupts
+    - scsi: ufs: Clean up completed request without interrupt notification
+    - scsi: qla2xxx: Fix login timeout
+    - scsi: qla2xxx: Check if FW supports MQ before enabling
+    - scsi: qla2xxx: Fix null pointer access during disconnect from subsystem
+    - Revert "scsi: qla2xxx: Fix crash on qla2x00_mailbox_command"
+    - macvlan: validate setting of multiple remote source MAC addresses
+    - net: gianfar: Add of_node_put() before goto statement
+    - powerpc/perf: Fix soft lockups due to missed interrupt accounting
+    - arm64: Move handling of erratum 1418040 into C code
+    - arm64: Allow booting of late CPUs affected by erratum 1418040
+    - block: fix get_max_io_size()
+    - block: loop: set discard granularity and alignment for block device backed
+      loop
+    - HID: i2c-hid: Always sleep 60ms after I2C_HID_PWR_ON commands
+    - blk-mq: order adding requests to hctx->dispatch and checking SCHED_RESTART
+    - btrfs: reset compression level for lzo on remount
+    - btrfs: check the right error variable in btrfs_del_dir_entries_in_log
+    - btrfs: fix space cache memory leak after transaction abort
+    - btrfs: detect nocow for swap after snapshot delete
+    - fbcon: prevent user font height or width change from causing potential out-
+      of-bounds access
+    - USB: lvtest: return proper error code in probe
+    - vt: defer kfree() of vc_screenbuf in vc_do_resize()
+    - vt_ioctl: change VT_RESIZEX ioctl to check for error return from vc_resize()
+    - serial: samsung: Removes the IRQ not found warning
+    - serial: pl011: Fix oops on -EPROBE_DEFER
+    - serial: pl011: Don't leak amba_ports entry on driver register error
+    - serial: stm32: avoid kernel warning on absence of optional IRQ
+    - serial: 8250_exar: Fix number of ports for Commtech PCIe cards
+    - serial: 8250: change lock order in serial8250_do_startup()
+    - writeback: Protect inode->i_io_list with inode->i_lock
+    - writeback: Avoid skipping inode writeback
+    - writeback: Fix sync livelock due to b_dirty_time processing
+    - XEN uses irqdesc::irq_data_common::handler_data to store a per interrupt XEN
+      data pointer which contains XEN specific information.
+    - usb: host: xhci: fix ep context print mismatch in debugfs
+    - xhci: Do warm-reset when both CAS and XDEV_RESUME are set
+    - xhci: Always restore EP_SOFT_CLEAR_TOGGLE even if ep reset failed
+    - ARM64: vdso32: Install vdso32 from vdso_install
+    - arm64: vdso32: make vdso32 install conditional
+    - PM: sleep: core: Fix the handling of pending runtime resume requests
+    - powerpc/perf: Fix crashes with generic_compat_pmu & BHRB
+    - device property: Fix the secondary firmware node handling in
+      set_primary_fwnode()
+    - crypto: af_alg - Work around empty control messages without MSG_MORE
+    - genirq/matrix: Deal with the sillyness of for_each_cpu() on UP
+    - irqchip/stm32-exti: Avoid losing interrupts due to clearing pending bits by
+      mistake
+    - x86/hotplug: Silence APIC only after all interrupts are migrated
+    - drm/amdgpu: Fix buffer overflow in INFO ioctl
+    - drm/amdgpu/gfx10: refine mgcg setting
+    - drm/amd/powerplay: Fix hardmins not being sent to SMU for RV
+    - drm/amd/pm: correct Vega10 swctf limit setting
+    - drm/amd/pm: correct Vega12 swctf limit setting
+    - drm/amd/pm: correct Vega20 swctf limit setting
+    - drm/amd/pm: correct the thermal alert temperature limit settings
+    - USB: yurex: Fix bad gfp argument
+    - usb: uas: Add quirk for PNY Pro Elite
+    - USB: quirks: Ignore duplicate endpoint on Sound Devices MixPre-D
+    - USB: Ignore UAS for JMicron JMS567 ATA/ATAPI Bridge
+    - usb: host: ohci-exynos: Fix error handling in exynos_ohci_probe()
+    - USB: gadget: u_f: add overflow checks to VLA macros
+    - USB: gadget: f_ncm: add bounds checks to ncm_unwrap_ntb()
+    - USB: gadget: u_f: Unbreak offset calculation in VLAs
+    - USB: cdc-acm: rework notification_buffer resizing
+    - usb: storage: Add unusual_uas entry for Sony PSZ drives
+    - drm/i915: Fix cmd parser desc matching with masks
+    - usb: dwc3: gadget: Don't setup more than requested
+    - usb: dwc3: gadget: Fix handling ZLP
+    - usb: dwc3: gadget: Handle ZLP for sg requests
+    - fbmem: pull fbcon_update_vcs() out of fb_set_var()
+    - kheaders: remove unneeded 'cat' command piped to 'head' / 'tail'
+    - kheaders: optimize md5sum calculation for in-tree builds
+    - kheaders: optimize header copy for in-tree builds
+    - kheaders: remove the last bashism to allow sh to run it
+    - kheaders: explain why include/config/autoconf.h is excluded from md5sum
+    - kbuild: add variables for compression tools
+    - kbuild: fix broken builds because of GZIP,BZIP2,LZOP variables
+    - HID: hiddev: Fix slab-out-of-bounds write in hiddev_ioctl_usage()
+    - ALSA: usb-audio: Update documentation comment for MS2109 quirk
+    - io_uring: Fix NULL pointer dereference in io_sq_wq_submit_work()
+    - Linux 5.4.62
+  * DELL LATITUDE 5491 touchscreen doesn't work (LP: #1889446) // Focal update:
+    v5.4.62 upstream stable release (LP: #1895174)
+    - USB: quirks: Add no-lpm quirk for another Raydium touchscreen
+  * [NUC8CCHK][HDA-Intel - HDA Intel PCH, playback] No sound at all
+    (LP: #1875199) // Focal update: v5.4.62 upstream stable release
+    (LP: #1895174)
+    - ALSA: hda/realtek: Fix pin default on Intel NUC 8 Rugged
+  * Focal update: v5.4.61 upstream stable release (LP: #1893115)
+    - Documentation/llvm: add documentation on building w/ Clang/LLVM
+    - Documentation/llvm: fix the name of llvm-size
+    - net: wan: wanxl: use allow to pass CROSS_COMPILE_M68k for rebuilding
+      firmware
+    - net: wan: wanxl: use $(M68KCC) instead of $(M68KAS) for rebuilding firmware
+    - x86/boot: kbuild: allow readelf executable to be specified
+    - kbuild: remove PYTHON2 variable
+    - kbuild: remove AS variable
+    - kbuild: replace AS=clang with LLVM_IAS=1
+    - kbuild: support LLVM=1 to switch the default tools to Clang/LLVM
+    - drm/vgem: Replace opencoded version of drm_gem_dumb_map_offset()
+    - gfs2: Improve mmap write vs. punch_hole consistency
+    - gfs2: Never call gfs2_block_zero_range with an open transaction
+    - perf probe: Fix memory leakage when the probe point is not found
+    - khugepaged: khugepaged_test_exit() check mmget_still_valid()
+    - khugepaged: adjust VM_BUG_ON_MM() in __khugepaged_enter()
+    - bcache: avoid nr_stripes overflow in bcache_device_init()
+    - btrfs: export helpers for subvolume name/id resolution
+    - btrfs: don't show full path of bind mounts in subvol=
+    - btrfs: return EROFS for BTRFS_FS_STATE_ERROR cases
+    - btrfs: add wrapper for transaction abort predicate
+    - ALSA: hda/realtek: Add quirk for Samsung Galaxy Flex Book
+    - ALSA: hda/realtek: Add quirk for Samsung Galaxy Book Ion
+    - can: j1939: transport: j1939_session_tx_dat(): fix use-after-free read in
+      j1939_tp_txtimer()
+    - can: j1939: socket: j1939_sk_bind(): make sure ml_priv is allocated
+    - [Config] update config for SPI_DYNAMIC
+    - spi: Prevent adding devices below an unregistering controller
+    - romfs: fix uninitialized memory leak in romfs_dev_read()
+    - kernel/relay.c: fix memleak on destroy relay channel
+    - uprobes: __replace_page() avoid BUG in munlock_vma_page()
+    - mm: include CMA pages in lowmem_reserve at boot
+    - mm, page_alloc: fix core hung in free_pcppages_bulk()
+    - RDMA/hfi1: Correct an interlock issue for TID RDMA WRITE request
+    - ext4: fix checking of directory entry validity for inline directories
+    - jbd2: add the missing unlock_buffer() in the error path of
+      jbd2_write_superblock()
+    - scsi: zfcp: Fix use-after-free in request timeout handlers
+    - drm/amdgpu/display: use GFP_ATOMIC in dcn20_validate_bandwidth_internal
+    - drm/amd/display: Fix EDID parsing after resume from suspend
+    - drm/amd/display: fix pow() crashing when given base 0
+    - kthread: Do not preempt current task if it is going to call schedule()
+    - opp: Enable resources again if they were disabled earlier
+    - scsi: ufs: Add DELAY_BEFORE_LPM quirk for Micron devices
+    - scsi: target: tcmu: Fix crash in tcmu_flush_dcache_range on ARM
+    - media: budget-core: Improve exception handling in budget_register()
+    - rtc: goldfish: Enable interrupt in set_alarm() when necessary
+    - media: vpss: clean up resources in init
+    - Input: psmouse - add a newline when printing 'proto' by sysfs
+    - MIPS: Fix unable to reserve memory for Crash kernel
+    - m68knommu: fix overwriting of bits in ColdFire V3 cache control
+    - svcrdma: Fix another Receive buffer leak
+    - xfs: fix inode quota reservation checks
+    - drm/ttm: fix offset in VMAs with a pg_offs in ttm_bo_vm_access
+    - jffs2: fix UAF problem
+    - ceph: fix use-after-free for fsc->mdsc
+    - swiotlb-xen: use vmalloc_to_page on vmalloc virt addresses
+    - cpufreq: intel_pstate: Fix cpuinfo_max_freq when MSR_TURBO_RATIO_LIMIT is 0
+    - scsi: libfc: Free skb in fc_disc_gpn_id_resp() for valid cases
+    - virtio_ring: Avoid loop when vq is broken in virtqueue_poll
+    - media: camss: fix memory leaks on error handling paths in probe
+    - tools/testing/selftests/cgroup/cgroup_util.c: cg_read_strcmp: fix null
+      pointer dereference
+    - xfs: Fix UBSAN null-ptr-deref in xfs_sysfs_init
+    - alpha: fix annotation of io{read,write}{16,32}be()
+    - fs/signalfd.c: fix inconsistent return codes for signalfd4
+    - ext4: fix potential negative array index in do_split()
+    - ext4: don't allow overlapping system zones
+    - netfilter: nf_tables: nft_exthdr: the presence return value should be
+      little-endian
+    - spi: stm32: fixes suspend/resume management
+    - ASoC: q6afe-dai: mark all widgets registers as SND_SOC_NOPM
+    - ASoC: q6routing: add dummy register read/write function
+    - bpf: sock_ops sk access may stomp registers when dst_reg = src_reg
+    - can: j1939: fix kernel-infoleak in j1939_sk_sock2sockaddr_can()
+    - can: j1939: transport: j1939_simple_recv(): ignore local J1939 messages send
+      not by J1939 stack
+    - can: j1939: transport: add j1939_session_skb_find_by_offset() function
+    - i40e: Set RX_ONLY mode for unicast promiscuous on VLAN
+    - i40e: Fix crash during removing i40e driver
+    - net: fec: correct the error path for regulator disable in probe
+    - bonding: show saner speed for broadcast mode
+    - can: j1939: fix support for multipacket broadcast message
+    - can: j1939: cancel rxtimer on multipacket broadcast session complete
+    - can: j1939: abort multipacket broadcast session when timeout occurs
+    - can: j1939: add rxtimer for multipacket broadcast session
+    - bonding: fix a potential double-unregister
+    - s390/runtime_instrumentation: fix storage key handling
+    - s390/ptrace: fix storage key handling
+    - ASoC: msm8916-wcd-analog: fix register Interrupt offset
+    - ASoC: intel: Fix memleak in sst_media_open
+    - vfio/type1: Add proper error unwind for vfio_iommu_replay()
+    - kvm: x86: Toggling CR4.SMAP does not load PDPTEs in PAE mode
+    - kvm: x86: Toggling CR4.PKE does not load PDPTEs in PAE mode
+    - Revert "scsi: qla2xxx: Disable T10-DIF feature with FC-NVMe during probe"
+    - kconfig: qconf: do not limit the pop-up menu to the first row
+    - kconfig: qconf: fix signal connection to invalid slots
+    - efi: avoid error message when booting under Xen
+    - Fix build error when CONFIG_ACPI is not set/enabled:
+    - RDMA/bnxt_re: Do not add user qps to flushlist
+    - afs: Fix NULL deref in afs_dynroot_depopulate()
+    - bonding: fix active-backup failover for current ARP slave
+    - net: ena: Prevent reset after device destruction
+    - net: gemini: Fix missing free_netdev() in error path of
+      gemini_ethernet_port_probe()
+    - hv_netvsc: Fix the queue_mapping in netvsc_vf_xmit()
+    - net: dsa: b53: check for timeout
+    - powerpc/pseries: Do not initiate shutdown when system is running on UPS
+    - efi: add missed destroy_workqueue when efisubsys_init fails
+    - epoll: Keep a reference on files added to the check list
+    - do_epoll_ctl(): clean the failure exits up a bit
+    - mm/hugetlb: fix calculation of adjust_range_if_pmd_sharing_possible
+    - xen: don't reschedule in preemption off sections
+    - KVM: Pass MMU notifier range flags to kvm_unmap_hva_range()
+    - KVM: arm64: Only reschedule if MMU_NOTIFIER_RANGE_BLOCKABLE is not set
+    - Linux 5.4.61
+  * [UBUNTU 20.04] zPCI device hot-plug during boot may result in unusable
+    device (LP: #1893778)
+    - s390/pci: ignore stale configuration request event
+  * [SRU] [Focal/OEM-5.6/Groovy]Fix AMD usb host controller lost after stress S3
+    (LP: #1893914)
+    - SAUCE: xhci: workaround for S3 issue on AMD SNPS 3.0 xHC
+
+  [ Ubuntu: 5.4.0-48.52 ]
+
+  * focal/linux: 5.4.0-48.52 -proposed tracker (LP: #1894654)
+  * mm/slub kernel oops on focal kernel 5.4.0-45 (LP: #1895109)
+    - SAUCE: Revert "mm/slub: fix a memory leak in sysfs_slab_add()"
+  * Packaging resync (LP: #1786013)
+    - update dkms package versions
+    - update dkms package versions
+  * Introduce the new NVIDIA 450-server and the 450 UDA series (LP: #1887674)
+    - [packaging] add signed modules for nvidia 450 and 450-server
+  * [UBUNTU 20.04] zPCI attach/detach issues with PF/VF linking support
+    (LP: #1892849)
+    - s390/pci: fix zpci_bus_link_virtfn()
+    - s390/pci: re-introduce zpci_remove_device()
+    - s390/pci: fix PF/VF linking on hot plug
+  * [UBUNTU 20.04] kernel: s390/cpum_cf,perf: changeDFLT_CCERROR counter name
+    (LP: #1891454)
+    - s390/cpum_cf, perf: change DFLT_CCERROR counter name
+  * [UBUNTU 20.04] zPCI: Enabling of a reserved PCI function regression
+    introduced by multi-function support (LP: #1891437)
+    - s390/pci: fix enabling a reserved PCI function
+  * CVE-2020-12888
+    - vfio/type1: Support faulting PFNMAP vmas
+    - vfio-pci: Fault mmaps to enable vma tracking
+    - vfio-pci: Invalidate mmaps and block MMIO access on disabled memory
+  *  [Hyper-V] VSS and File Copy daemons intermittently fails to start
+    (LP: #1891224)
+    - [Packaging] Bind hv_vss_daemon startup to hv_vss device
+    - [Packaging] bind hv_fcopy_daemon startup to hv_fcopy device
+  * alsa/hdmi: support nvidia mst hdmi/dp audio (LP: #1867704)
+    - ALSA: hda - Rename snd_hda_pin_sense to snd_hda_jack_pin_sense
+    - ALSA: hda - Add DP-MST jack support
+    - ALSA: hda - Add DP-MST support for non-acomp codecs
+    - ALSA: hda - Add DP-MST support for NVIDIA codecs
+    - ALSA: hda: hdmi - fix regression in connect list handling
+    - ALSA: hda: hdmi - fix kernel oops caused by invalid PCM idx
+    - ALSA: hda: hdmi - preserve non-MST PCM routing for Intel platforms
+    - ALSA: hda: hdmi - Keep old slot assignment behavior for Intel platforms
+    - ALSA: hda - Fix DP-MST support for NVIDIA codecs
+  * Focal update: v5.4.60 upstream stable release (LP: #1892899)
+    - smb3: warn on confusing error scenario with sec=krb5
+    - genirq/affinity: Make affinity setting if activated opt-in
+    - genirq/PM: Always unlock IRQ descriptor in rearm_wake_irq()
+    - PCI: hotplug: ACPI: Fix context refcounting in acpiphp_grab_context()
+    - PCI: Add device even if driver attach failed
+    - PCI: qcom: Define some PARF params needed for ipq8064 SoC
+    - PCI: qcom: Add support for tx term offset for rev 2.1.0
+    - btrfs: allow use of global block reserve for balance item deletion
+    - btrfs: free anon block device right after subvolume deletion
+    - btrfs: don't allocate anonymous block device for user invisible roots
+    - btrfs: ref-verify: fix memory leak in add_block_entry
+    - btrfs: stop incremening log_batch for the log root tree when syncing log
+    - btrfs: remove no longer needed use of log_writers for the log root tree
+    - btrfs: don't traverse into the seed devices in show_devname
+    - btrfs: open device without device_list_mutex
+    - btrfs: move the chunk_mutex in btrfs_read_chunk_tree
+    - btrfs: relocation: review the call sites which can be interrupted by signal
+    - btrfs: add missing check for nocow and compression inode flags
+    - btrfs: avoid possible signal interruption of btrfs_drop_snapshot() on
+      relocation tree
+    - btrfs: sysfs: use NOFS for device creation
+    - btrfs: don't WARN if we abort a transaction with EROFS
+    - btrfs: fix race between page release and a fast fsync
+    - btrfs: fix messages after changing compression level by remount
+    - btrfs: only search for left_info if there is no right_info in
+      try_merge_free_space
+    - btrfs: inode: fix NULL pointer dereference if inode doesn't need compression
+    - btrfs: fix memory leaks after failure to lookup checksums during inode
+      logging
+    - btrfs: make sure SB_I_VERSION doesn't get unset by remount
+    - btrfs: fix return value mixup in btrfs_get_extent
+    - arm64: perf: Correct the event index in sysfs
+    - dt-bindings: iio: io-channel-mux: Fix compatible string in example code
+    - iio: dac: ad5592r: fix unbalanced mutex unlocks in ad5592r_read_raw()
+    - xtensa: add missing exclusive access state management
+    - xtensa: fix xtensa_pmu_setup prototype
+    - cifs: Fix leak when handling lease break for cached root fid
+    - powerpc/ptdump: Fix build failure in hashpagetable.c
+    - powerpc: Allow 4224 bytes of stack expansion for the signal frame
+    - powerpc: Fix circular dependency between percpu.h and mmu.h
+    - pinctrl: ingenic: Enhance support for IRQ_TYPE_EDGE_BOTH
+    - media: vsp1: dl: Fix NULL pointer dereference on unbind
+    - net: ethernet: stmmac: Disable hardware multicast filter
+    - net: stmmac: dwmac1000: provide multicast filter fallback
+    - net/compat: Add missing sock updates for SCM_RIGHTS
+    - md/raid5: Fix Force reconstruct-write io stuck in degraded raid5
+    - bcache: allocate meta data pages as compound pages
+    - bcache: fix overflow in offset_to_stripe()
+    - mac80211: fix misplaced while instead of if
+    - driver core: Avoid binding drivers to dead devices
+    - MIPS: CPU#0 is not hotpluggable
+    - MIPS: qi_lb60: Fix routing to audio amplifier
+    - ext2: fix missing percpu_counter_inc
+    - khugepaged: collapse_pte_mapped_thp() flush the right range
+    - khugepaged: collapse_pte_mapped_thp() protect the pmd lock
+    - ocfs2: change slot number type s16 to u16
+    - mm/page_counter.c: fix protection usage propagation
+    - mm/memory_hotplug: fix unpaired mem_hotplug_begin/done
+    - ftrace: Setup correct FTRACE_FL_REGS flags for module
+    - kprobes: Fix NULL pointer dereference at kprobe_ftrace_handler
+    - tracing/hwlat: Honor the tracing_cpumask
+    - tracing: Use trace_sched_process_free() instead of exit() for pid tracing
+    - tracing: Move pipe reference to trace array instead of current_tracer
+    - watchdog: f71808e_wdt: indicate WDIOF_CARDRESET support in
+      watchdog_info.options
+    - watchdog: f71808e_wdt: remove use of wrong watchdog_info option
+    - watchdog: f71808e_wdt: clear watchdog timeout occurred flag
+    - ceph: set sec_context xattr on symlink creation
+    - ceph: handle zero-length feature mask in session messages
+    - pseries: Fix 64 bit logical memory block panic
+    - module: Correctly truncate sysfs sections output
+    - perf intel-pt: Fix FUP packet state
+    - perf intel-pt: Fix duplicate branch after CBR
+    - remoteproc: qcom: q6v5: Update running state before requesting stop
+    - remoteproc: qcom_q6v5_mss: Validate MBA firmware size before load
+    - remoteproc: qcom_q6v5_mss: Validate modem blob firmware size before load
+    - drm/imx: imx-ldb: Disable both channels for split mode in enc->disable()
+    - orangefs: get rid of knob code...
+    - pinctrl: ingenic: Properly detect GPIO direction when configured for IRQ
+    - crypto: algif_aead - Only wake up when ctx->more is zero
+    - mfd: arizona: Ensure 32k clock is put on driver unbind and error
+    - octeontx2-af: change (struct qmem)->entry_sz from u8 to u16
+    - mtd: rawnand: fsl_upm: Remove unused mtd var
+    - platform/chrome: cros_ec_ishtp: Fix a double-unlock issue
+    - RDMA/ipoib: Return void from ipoib_ib_dev_stop()
+    - RDMA/ipoib: Fix ABBA deadlock with ipoib_reap_ah()
+    - media: rockchip: rga: Introduce color fmt macros and refactor CSC mode logic
+    - media: rockchip: rga: Only set output CSC mode for RGB input
+    - IB/uverbs: Set IOVA on IB MR in uverbs layer
+    - selftests/bpf: Test_progs indicate to shell on non-actions
+    - selftests/bpf: test_progs use another shell exit on non-actions
+    - USB: serial: ftdi_sio: make process-packet buffer unsigned
+    - USB: serial: ftdi_sio: clean up receive processing
+    - crypto: af_alg - Fix regression on empty requests
+    - devres: keep both device name and resource name in pretty name
+    - RDMA/counter: Only bind user QPs in auto mode
+    - RDMA/counter: Allow manually bind QPs with different pids to same counter
+    - mmc: renesas_sdhi_internal_dmac: clean up the code for dma complete
+    - crypto: caam - Remove broken arc4 support
+    - gpu: ipu-v3: image-convert: Combine rotate/no-rotate irq handlers
+    - gpu: ipu-v3: image-convert: Wait for all EOFs before completing a tile
+    - dm rq: don't call blk_mq_queue_stopped() in dm_stop_queue()
+    - clk: actions: Fix h_clk for Actions S500 SoC
+    - selftests/powerpc: ptrace-pkey: Rename variables to make it easier to follow
+      code
+    - selftests/powerpc: ptrace-pkey: Update the test to mark an invalid pkey
+      correctly
+    - selftests/powerpc: ptrace-pkey: Don't update expected UAMOR value
+    - iommu/omap: Check for failure of a call to omap_iommu_dump_ctx
+    - clk: qcom: gcc: fix sm8150 GPU and NPU clocks
+    - clk: qcom: clk-alpha-pll: remove unused/incorrect PLL_CAL_VAL
+    - iommu/vt-d: Enforce PASID devTLB field mask
+    - i2c: rcar: slave: only send STOP event when we have been addressed
+    - clk: qcom: gcc-sdm660: Fix up gcc_mss_mnoc_bimc_axi_clk
+    - clk: clk-atlas6: fix return value check in atlas6_clk_init()
+    - pwm: bcm-iproc: handle clk_get_rate() return
+    - tools build feature: Use CC and CXX from parent
+    - i2c: rcar: avoid race when unregistering slave
+    - nfs: ensure correct writeback errors are returned on close()
+    - ubifs: Fix wrong orphan node deletion in ubifs_jnl_update|rename
+    - clk: bcm2835: Do not use prediv with bcm2711's PLLs
+    - libnvdimm/security: fix a typo
+    - libnvdimm/security: ensure sysfs poll thread woke up and fetch updated attr
+    - openrisc: Fix oops caused when dumping stack
+    - scsi: lpfc: nvmet: Avoid hang / use-after-free again when destroying
+      targetport
+    - nfs: nfs_file_write() should check for writeback errors
+    - watchdog: initialize device before misc_register
+    - md-cluster: Fix potential error pointer dereference in resize_bitmaps()
+    - x86/tsr: Fix tsc frequency enumeration bug on Lightning Mountain SoC
+    - Input: sentelic - fix error return when fsp_reg_write fails
+    - recordmcount: Fix build failure on non arm64
+    - drm/vmwgfx: Use correct vmw_legacy_display_unit pointer
+    - drm/vmwgfx: Fix two list_for_each loop exit tests
+    - net: qcom/emac: add missed clk_disable_unprepare in error path of
+      emac_clks_phase1_init
+    - nfs: Fix getxattr kernel panic and memory overflow
+    - fs/minix: set s_maxbytes correctly
+    - fs/minix: fix block limit check for V1 filesystems
+    - fs/minix: remove expected error message in block_to_path()
+    - fs/ufs: avoid potential u32 multiplication overflow
+    - test_kmod: avoid potential double free in trigger_config_run_type()
+    - i2c: iproc: fix race between client unreg and isr
+    - mfd: dln2: Run event handler loop under spinlock
+    - crypto: algif_aead - fix uninitialized ctx->init
+    - ALSA: echoaudio: Fix potential Oops in snd_echo_resume()
+    - perf bench mem: Always memset source before memcpy
+    - tools build feature: Quote CC and CXX for their arguments
+    - perf/x86/rapl: Fix missing psys sysfs attributes
+    - sh: landisk: Add missing initialization of sh_io_port_base
+    - khugepaged: retract_page_tables() remember to test exit
+    - arm64: dts: marvell: espressobin: add ethernet alias
+    - drm/panfrost: Use kvfree() to free bo->sgts
+    - drm: Added orientation quirk for ASUS tablet model T103HAF
+    - drm: fix drm_dp_mst_port refcount leaks in drm_dp_mst_allocate_vcpi
+    - drm/amdgpu: Fix bug where DPM is not enabled after hibernate and resume
+    - drm/amd/display: dchubbub p-state warning during surface planes switch
+    - Linux 5.4.60
+    - kprobes: Fix compiler warning for !CONFIG_KPROBES_ON_FTRACE
+  * Focal update: v5.4.59 upstream stable release (LP: #1892417)
+    - tracepoint: Mark __tracepoint_string's __used
+    - HID: input: Fix devices that return multiple bytes in battery report
+    - nvme: add a Identify Namespace Identification Descriptor list quirk
+    - fs/io_uring.c: Fix uninitialized variable is referenced in io_submit_sqe
+    - clk: qcom: clk-rpmh: Wait for completion when enabling clocks
+    - x86/mce/inject: Fix a wrong assignment of i_mce.status
+    - sched/fair: Fix NOHZ next idle balance
+    - sched: correct SD_flags returned by tl->sd_flags()
+    - arm64: dts: rockchip: fix rk3368-lion gmac reset gpio
+    - arm64: dts: rockchip: fix rk3399-puma vcc5v0-host gpio
+    - arm64: dts: rockchip: fix rk3399-puma gmac reset gpio
+    - EDAC: Fix reference count leaks
+    - crc-t10dif: Fix potential crypto notify dead-lock
+    - arm64: dts: qcom: msm8916: Replace invalid bias-pull-none property
+    - crypto: ccree - fix resource leak on error path
+    - ARM: exynos: MCPM: Restore big.LITTLE cpuidle support
+    - firmware: arm_scmi: Fix SCMI genpd domain probing
+    - arm64: dts: exynos: Fix silent hang after boot on Espresso
+    - sched/uclamp: Fix initialization of struct uclamp_rq
+    - clk: scmi: Fix min and max rate when registering clocks with discrete rates
+    - m68k: mac: Don't send IOP message until channel is idle
+    - m68k: mac: Fix IOP status/control register writes
+    - platform/x86: intel-hid: Fix return value check in check_acpi_dev()
+    - platform/x86: intel-vbtn: Fix return value check in check_acpi_dev()
+    - ARM: dts: gose: Fix ports node name for adv7180
+    - ARM: dts: gose: Fix ports node name for adv7612
+    - ARM: at91: pm: add missing put_device() call in at91_pm_sram_init()
+    - ARM: dts: sunxi: bananapi-m2-plus-v1.2: Add regulator supply to all CPU
+      cores
+    - ARM: dts: sunxi: bananapi-m2-plus-v1.2: Fix CPU supply voltages
+    - spi: lantiq: fix: Rx overflow error in full duplex mode
+    - tpm: Require that all digests are present in TCG_PCR_EVENT2 structures
+    - recordmcount: only record relocation of type R_AARCH64_CALL26 on arm64.
+    - regulator: fix memory leak on error path of regulator_register()
+    - io_uring: fix sq array offset calculation
+    - spi: rockchip: Fix error in SPI slave pio read
+    - ARM: socfpga: PM: add missing put_device() call in
+      socfpga_setup_ocram_self_refresh()
+    - iocost: Fix check condition of iocg abs_vdebt
+    - irqchip/ti-sci-inta: Fix return value about devm_ioremap_resource()
+    - seccomp: Fix ioctl number for SECCOMP_IOCTL_NOTIF_ID_VALID
+    - md: raid0/linear: fix dereference before null check on pointer mddev
+    - nvme-tcp: fix controller reset hang during traffic
+    - nvme-rdma: fix controller reset hang during traffic
+    - nvme-multipath: fix logic for non-optimized paths
+    - nvme-multipath: do not fall back to __nvme_find_path() for non-optimized
+      paths
+    - drm/tilcdc: fix leak & null ref in panel_connector_get_modes
+    - soc: qcom: rpmh-rsc: Set suppress_bind_attrs flag
+    - Bluetooth: add a mutex lock to avoid UAF in do_enale_set
+    - loop: be paranoid on exit and prevent new additions / removals
+    - fs/btrfs: Add cond_resched() for try_release_extent_mapping() stalls
+    - drm/amdgpu: avoid dereferencing a NULL pointer
+    - drm/radeon: Fix reference count leaks caused by pm_runtime_get_sync
+    - crypto: aesni - Fix build with LLVM_IAS=1
+    - video: fbdev: savage: fix memory leak on error handling path in probe
+    - video: fbdev: neofb: fix memory leak in neo_scan_monitor()
+    - bus: ti-sysc: Add missing quirk flags for usb_host_hs
+    - md-cluster: fix wild pointer of unlock_all_bitmaps()
+    - drm/nouveau/kms/nv50-: Fix disabling dithering
+    - arm64: dts: hisilicon: hikey: fixes to comply with adi, adv7533 DT binding
+    - drm/etnaviv: fix ref count leak via pm_runtime_get_sync
+    - drm/nouveau: fix reference count leak in nouveau_debugfs_strap_peek
+    - drm/nouveau: fix multiple instances of reference count leaks
+    - mmc: sdhci-cadence: do not use hardware tuning for SD mode
+    - btrfs: fix lockdep splat from btrfs_dump_space_info
+    - usb: mtu3: clear dual mode of u3port when disable device
+    - drm: msm: a6xx: fix gpu failure after system resume
+    - drm/msm: Fix a null pointer access in msm_gem_shrinker_count()
+    - drm/debugfs: fix plain echo to connector "force" attribute
+    - drm/radeon: disable AGP by default
+    - irqchip/irq-mtk-sysirq: Replace spinlock with raw_spinlock
+    - mm/mmap.c: Add cond_resched() for exit_mmap() CPU stalls
+    - drm/amdgpu/display bail early in dm_pp_get_static_clocks
+    - drm/amd/powerplay: fix compile error with ARCH=arc
+    - bpf: Fix fds_example SIGSEGV error
+    - brcmfmac: keep SDIO watchdog running when console_interval is non-zero
+    - brcmfmac: To fix Bss Info flag definition Bug
+    - brcmfmac: set state of hanger slot to FREE when flushing PSQ
+    - platform/x86: asus-nb-wmi: add support for ASUS ROG Zephyrus G14 and G15
+    - iwlegacy: Check the return value of pcie_capability_read_*()
+    - gpu: host1x: debug: Fix multiple channels emitting messages simultaneously
+    - ionic: update eid test for overflow
+    - mmc: sdhci-pci-o2micro: Bug fix for O2 host controller Seabird1
+    - usb: gadget: net2280: fix memory leak on probe error handling paths
+    - bdc: Fix bug causing crash after multiple disconnects
+    - usb: bdc: Halt controller on suspend
+    - dyndbg: fix a BUG_ON in ddebug_describe_flags
+    - bcache: fix super block seq numbers comparision in register_cache_set()
+    - ACPICA: Do not increment operation_region reference counts for field units
+    - drm/msm: ratelimit crtc event overflow error
+    - drm/gem: Fix a leak in drm_gem_objects_lookup()
+    - drm/bridge: ti-sn65dsi86: Clear old error bits before AUX transfers
+    - agp/intel: Fix a memory leak on module initialisation failure
+    - mwifiex: Fix firmware filename for sd8977 chipset
+    - mwifiex: Fix firmware filename for sd8997 chipset
+    - btmrvl: Fix firmware filename for sd8977 chipset
+    - btmrvl: Fix firmware filename for sd8997 chipset
+    - video: fbdev: sm712fb: fix an issue about iounmap for a wrong address
+    - console: newport_con: fix an issue about leak related system resources
+    - video: pxafb: Fix the function used to balance a 'dma_alloc_coherent()' call
+    - ath10k: Acquire tx_lock in tx error paths
+    - iio: improve IIO_CONCENTRATION channel type description
+    - drm/etnaviv: Fix error path on failure to enable bus clk
+    - drm/arm: fix unintentional integer overflow on left shift
+    - clk: bcm63xx-gate: fix last clock availability
+    - leds: lm355x: avoid enum conversion warning
+    - Bluetooth: btusb: fix up firmware download sequence
+    - Bluetooth: btmtksdio: fix up firmware download sequence
+    - media: cxusb-analog: fix V4L2 dependency
+    - media: marvell-ccic: Add missed v4l2_async_notifier_cleanup()
+    - media: omap3isp: Add missed v4l2_ctrl_handler_free() for
+      preview_init_entities()
+    - ASoC: SOF: nocodec: add missing .owner field
+    - ASoC: Intel: bxt_rt298: add missing .owner field
+    - scsi: cumana_2: Fix different dev_id between request_irq() and free_irq()
+    - drm/mipi: use dcs write for mipi_dsi_dcs_set_tear_scanline
+    - cxl: Fix kobject memleak
+    - drm/radeon: fix array out-of-bounds read and write issues
+    - staging: vchiq_arm: Add a matching unregister call
+    - iavf: fix error return code in iavf_init_get_resources()
+    - iavf: Fix updating statistics
+    - RDMA/core: Fix bogus WARN_ON during ib_unregister_device_queued()
+    - scsi: powertec: Fix different dev_id between request_irq() and free_irq()
+    - scsi: eesox: Fix different dev_id between request_irq() and free_irq()
+    - ipvs: allow connection reuse for unconfirmed conntrack
+    - media: firewire: Using uninitialized values in node_probe()
+    - media: exynos4-is: Add missed check for pinctrl_lookup_state()
+    - media: cros-ec-cec: do not bail on device_init_wakeup failure
+    - xfs: don't eat an EIO/ENOSPC writeback error when scrubbing data fork
+    - xfs: fix reflink quota reservation accounting error
+    - RDMA/rxe: Skip dgid check in loopback mode
+    - PCI: Fix pci_cfg_wait queue locking problem
+    - drm/stm: repair runtime power management
+    - kobject: Avoid premature parent object freeing in kobject_cleanup()
+    - leds: core: Flush scheduled work for system suspend
+    - drm: panel: simple: Fix bpc for LG LB070WV8 panel
+    - phy: exynos5-usbdrd: Calibrating makes sense only for USB2.0 PHY
+    - drm/bridge: sil_sii8620: initialize return of sii8620_readb
+    - scsi: scsi_debug: Add check for sdebug_max_queue during module init
+    - mwifiex: Prevent memory corruption handling keys
+    - kernfs: do not call fsnotify() with name without a parent
+    - powerpc/rtas: don't online CPUs for partition suspend
+    - powerpc/vdso: Fix vdso cpu truncation
+    - RDMA/qedr: SRQ's bug fixes
+    - RDMA/rxe: Prevent access to wr->next ptr afrer wr is posted to send queue
+    - ima: Have the LSM free its audit rule
+    - staging: rtl8192u: fix a dubious looking mask before a shift
+    - ASoC: meson: fixes the missed kfree() for axg_card_add_tdm_loopback
+    - PCI/ASPM: Add missing newline in sysfs 'policy'
+    - phy: renesas: rcar-gen3-usb2: move irq registration to init
+    - powerpc/book3s64/pkeys: Use PVR check instead of cpu feature
+    - drm/imx: fix use after free
+    - drm/imx: tve: fix regulator_disable error path
+    - gpu: ipu-v3: Restore RGB32, BGR32
+    - spi: lantiq-ssc: Fix warning by using WQ_MEM_RECLAIM
+    - USB: serial: iuu_phoenix: fix led-activity helpers
+    - usb: core: fix quirks_param_set() writing to a const pointer
+    - thermal: ti-soc-thermal: Fix reversed condition in
+      ti_thermal_expose_sensor()
+    - coresight: tmc: Fix TMC mode read in tmc_read_unprepare_etb()
+    - powerpc/perf: Fix missing is_sier_aviable() during build
+    - mt76: mt7615: fix potential memory leak in mcu message handler
+    - phy: armada-38x: fix NETA lockup when repeatedly switching speeds
+    - MIPS: OCTEON: add missing put_device() call in dwc3_octeon_device_init()
+    - usb: dwc2: Fix error path in gadget registration
+    - usb: gadget: f_uac2: fix AC Interface Header Descriptor wTotalLength
+    - scsi: megaraid_sas: Clear affinity hint
+    - scsi: mesh: Fix panic after host or bus reset
+    - net: dsa: mv88e6xxx: MV88E6097 does not support jumbo configuration
+    - macintosh/via-macii: Access autopoll_devs when inside lock
+    - PCI: cadence: Fix updating Vendor ID and Subsystem Vendor ID register
+    - RDMA/core: Fix return error value in _ib_modify_qp() to negative
+    - Smack: fix another vsscanf out of bounds
+    - Smack: prevent underflow in smk_set_cipso()
+    - power: supply: check if calc_soc succeeded in pm860x_init_battery
+    - Bluetooth: hci_h5: Set HCI_UART_RESET_ON_INIT to correct flags
+    - Bluetooth: hci_serdev: Only unregister device if it was registered
+    - net: dsa: rtl8366: Fix VLAN semantics
+    - net: dsa: rtl8366: Fix VLAN set-up
+    - xfs: fix inode allocation block res calculation precedence
+    - selftests/powerpc: Squash spurious errors due to device removal
+    - powerpc/32s: Fix CONFIG_BOOK3S_601 uses
+    - powerpc/boot: Fix CONFIG_PPC_MPC52XX references
+    - selftests/powerpc: Fix CPU affinity for child process
+    - RDMA/netlink: Remove CAP_NET_RAW check when dump a raw QP
+    - PCI: Release IVRS table in AMD ACS quirk
+    - [Config] update config for ARMADA_AP_CPU_CLK
+    - cpufreq: ap806: fix cpufreq driver needs ap cpu clk
+    - selftests/powerpc: Fix online CPU selection
+    - ASoC: meson: axg-tdm-interface: fix link fmt setup
+    - ASoC: meson: axg-tdmin: fix g12a skew
+    - ASoC: meson: axg-tdm-formatters: fix sclk inversion
+    - ASoC: fsl_sai: Fix value of FSL_SAI_CR1_RFW_MASK
+    - s390/qeth: don't process empty bridge port events
+    - ice: Graceful error handling in HW table calloc failure
+    - rtw88: fix LDPC field for RA info
+    - rtw88: fix short GI capability based on current bandwidth
+    - rtw88: coex: only skip coex triggered by BT info
+    - wl1251: fix always return 0 error
+    - tools, build: Propagate build failures from tools/build/Makefile.build
+    - tools, bpftool: Fix wrong return value in do_dump()
+    - net/mlx5: DR, Change push vlan action sequence
+    - net/mlx5: Delete extra dump stack that gives nothing
+    - net: ethernet: aquantia: Fix wrong return value
+    - liquidio: Fix wrong return value in cn23xx_get_pf_num()
+    - net: spider_net: Fix the size used in a 'dma_free_coherent()' call
+    - fsl/fman: use 32-bit unsigned integer
+    - fsl/fman: fix dereference null return value
+    - fsl/fman: fix unreachable code
+    - fsl/fman: check dereferencing null pointer
+    - fsl/fman: fix eth hash table allocation
+    - net: thunderx: initialize VF's mailbox mutex before first usage
+    - dlm: Fix kobject memleak
+    - ocfs2: fix unbalanced locking
+    - pinctrl-single: fix pcs_parse_pinconf() return value
+    - svcrdma: Fix page leak in svc_rdma_recv_read_chunk()
+    - x86/fsgsbase/64: Fix NULL deref in 86_fsgsbase_read_task
+    - crypto: aesni - add compatibility with IAS
+    - af_packet: TPACKET_V3: fix fill status rwlock imbalance
+    - drivers/net/wan/lapbether: Added needed_headroom and a skb->len check
+    - net: Fix potential memory leak in proto_register()
+    - net/nfc/rawsock.c: add CAP_NET_RAW check.
+    - net: phy: fix memory leak in device-create error path
+    - net: Set fput_needed iff FDPUT_FPUT is set
+    - net/tls: Fix kmap usage
+    - vmxnet3: use correct tcp hdr length when packet is encapsulated
+    - net: refactor bind_bucket fastreuse into helper
+    - net: initialize fastreuse on inet_inherit_port
+    - USB: serial: cp210x: re-enable auto-RTS on open
+    - USB: serial: cp210x: enable usb generic throttle/unthrottle
+    - ALSA: hda - fix the micmute led status for Lenovo ThinkCentre AIO
+    - ALSA: usb-audio: Creative USB X-Fi Pro SB1095 volume knob support
+    - ALSA: usb-audio: fix overeager device match for MacroSilicon MS2109
+    - ALSA: usb-audio: work around streaming quirk for MacroSilicon MS2109
+    - 9p: Fix memory leak in v9fs_mount
+    - media: media-request: Fix crash if memory allocation fails
+    - drm/ttm/nouveau: don't call tt destroy callback on alloc failure.
+    - io_uring: set ctx sq/cq entry count earlier
+    - NFS: Don't move layouts to plh_return_segs list while in use
+    - NFS: Don't return layout segments that are in use
+    - cpufreq: Fix locking issues with governors
+    - cpufreq: dt: fix oops on armada37xx
+    - include/asm-generic/vmlinux.lds.h: align ro_after_init
+    - spi: spidev: Align buffers for DMA
+    - mtd: rawnand: qcom: avoid write to unavailable register
+    - erofs: fix extended inode could cross boundary
+    - Revert "parisc: Drop LDCW barrier in CAS code when running UP"
+    - Revert "parisc: Use ldcw instruction for SMP spinlock release barrier"
+    - Revert "parisc: Revert "Release spinlocks using ordered store""
+    - parisc: Do not use an ordered store in pa_tlb_lock()
+    - parisc: Implement __smp_store_release and __smp_load_acquire barriers
+    - parisc: mask out enable and reserved bits from sba imask
+    - ARM: 8992/1: Fix unwind_frame for clang-built kernels
+    - irqdomain/treewide: Free firmware node after domain removal
+    - ALSA: usb-audio: add quirk for Pioneer DDJ-RB
+    - tpm: Unify the mismatching TPM space buffer sizes
+    - pstore: Fix linking when crypto API disabled
+    - crypto: hisilicon - don't sleep of CRYPTO_TFM_REQ_MAY_SLEEP was not
+      specified
+    - crypto: qat - fix double free in qat_uclo_create_batch_init_list
+    - crypto: ccp - Fix use of merged scatterlists
+    - crypto: cpt - don't sleep of CRYPTO_TFM_REQ_MAY_SLEEP was not specified
+    - bitfield.h: don't compile-time validate _val in FIELD_FIT
+    - fs/minix: check return value of sb_getblk()
+    - fs/minix: don't allow getting deleted inodes
+    - fs/minix: reject too-large maximum file size
+    - xen/balloon: fix accounting in alloc_xenballooned_pages error path
+    - xen/balloon: make the balloon wait interruptible
+    - xen/gntdev: Fix dmabuf import with non-zero sgt offset
+    - s390/dasd: fix inability to use DASD with DIAG driver
+    - s390/gmap: improve THP splitting
+    - io_uring: Fix NULL pointer dereference in loop_rw_iter()
+    - Linux 5.4.59
+  * Regression on NFS: unable to handle page fault in mempool_alloc_slab
+    (LP: #1886277) // Focal update: v5.4.59 upstream stable release
+    (LP: #1892417)
+    - SUNRPC: Fix ("SUNRPC: Add "@len" parameter to gss_unwrap()")
+  * Focal update: v5.4.59 upstream stable release (LP: #1892417) //
+    CVE-2019-19770 which shows this issue is not a core debugfs issue, but
+    - blktrace: fix debugfs use after free
+  * update ENA driver for LLQ acceleration mode, new hw support (LP: #1890845)
+    - net: ena: change num_queues to num_io_queues for clarity and consistency
+    - net: ena: multiple queue creation related cleanups
+    - net: ena: ethtool: get_channels: use combined only
+    - net: ena: make ethtool -l show correct max number of queues
+    - net: ena: remove redundant print of number of queues
+    - net: ena: ethtool: support set_channels callback
+    - net: ena: implement XDP drop support
+    - net: ena: Implement XDP_TX action
+    - net: ena: Add first_interrupt field to napi struct
+    - net: ena: fix default tx interrupt moderation interval
+    - net: ena: remove set but not used variable 'rx_ring'
+    - net: ena: remove set but not used variable 'hash_key'
+    - net: ena: ethtool: remove redundant non-zero check on rc
+    - net/amazon: Ensure that driver version is aligned to the linux kernel
+    - net: ena: fix broken interface between ENA driver and FW
+    - net: ena: ethtool: clean up minor indentation issue
+    - net: ena: fix incorrect setting of the number of msix vectors
+    - net: ena: fix request of incorrect number of IRQ vectors
+    - net: ena: avoid memory access violation by validating req_id properly
+    - net: ena: fix continuous keep-alive resets
+    - net: ena: Make some functions static
+    - net: ena: avoid unnecessary admin command when RSS function set fails
+    - net: ena: allow setting the hash function without changing the key
+    - net: ena: change default RSS hash function to Toeplitz
+    - net: ena: changes to RSS hash key allocation
+    - net: ena: remove code that does nothing
+    - net: ena: add unmask interrupts statistics to ethtool
+    - net: ena: add support for reporting of packet drops
+    - net: ena: drop superfluous prototype
+    - net: ena: use SHUTDOWN as reset reason when closing interface
+    - net: ena: cosmetic: remove unnecessary spaces and tabs in ena_com.h macros
+    - net: ena: cosmetic: extract code to ena_indirection_table_set()
+    - net: ena: add support for the rx offset feature
+    - net: ena: rename ena_com_free_desc to make API more uniform
+    - net: ena: use explicit variable size for clarity
+    - net: ena: fix ena_com_comp_status_to_errno() return value
+    - net: ena: simplify ena_com_update_intr_delay_resolution()
+    - net: ena: cosmetic: set queue sizes to u32 for consistency
+    - net: ena: cosmetic: fix spelling and grammar mistakes in comments
+    - net: ena: cosmetic: fix line break issues
+    - net: ena: cosmetic: remove unnecessary code
+    - net: ena: cosmetic: code reorderings
+    - net: ena: cosmetic: fix spacing issues
+    - net: ena: cosmetic: minor code changes
+    - net: ena: reduce driver load time
+    - net: ena: xdp: XDP_TX: fix memory leak
+    - net: ena: xdp: update napi budget for DROP and ABORTED
+    - ena_netdev: use generic power management
+    - net: ena: Fix using plain integer as NULL pointer in ena_init_napi_in_range
+    - net: ena: avoid unnecessary rearming of interrupt vector when busy-polling
+    - net: ena: add reserved PCI device ID
+    - net: ena: cosmetic: satisfy gcc warning
+    - net: ena: cosmetic: change ena_com_stats_admin stats to u64
+    - net: ena: add support for traffic mirroring
+    - net: ena: enable support of rss hash key and function changes
+    - net: ena: move llq configuration from ena_probe to ena_device_init()
+    - net: ena: support new LLQ acceleration mode
+  * [SRU] Fix acpi backlight issue on some thinkpads (LP: #1892010)
+    - platform/x86: thinkpad_acpi: not loading brightness_init when _BCL invalid
+  * [SRU][F/OEM-5.6] add a new OLED panel support for brightness control
+    (LP: #1887909)
+    - drm/dp: Lenovo X13 Yoga OLED panel brightness fix
+  * Realtek [10ec:c82f] Subsystem [17aa:c02f] Wifi adapter not found
+    (LP: #1886247)
+    - SAUCE: rtw88: 8822ce: add support for device ID 0xc82f
+  * KVM: Fix zero_page reference counter overflow when using KSM on KVM compute
+    host (LP: #1837810)
+    - KVM: fix overflow of zero page refcount with ksm running
+  * Fix missing HDMI Audio on another HP Desktop (LP: #1891617)
+    - ALSA: hda/hdmi: Use force connectivity quirk on another HP desktop
+  * alsa/sof: support 1 and 3 dmics (LP: #1891585)
+    - SAUCE: ASoC: SOF: intel: hda: support also devices with 1 and 3 dmics
+  * tcp_fastopen_backup_key.sh from net in ubuntu_kernel_selftests failed on
+    Eoan LPAR (LP: #1869134)
+    - tcp: correct read of TFO keys on big endian systems
+  * Fix false-negative return value for rtnetlink.sh in kselftests/net
+    (LP: #1890136)
+    - selftests: rtnetlink: correct the final return value for the test
+    - selftests: rtnetlink: make kci_test_encap() return sub-test result
+  * Focal update: v5.4.58 upstream stable release (LP: #1891387)
+    - USB: serial: qcserial: add EM7305 QDL product ID
+    - perf/core: Fix endless multiplex timer
+    - USB: iowarrior: fix up report size handling for some devices
+    - usb: xhci: define IDs for various ASMedia host controllers
+    - usb: xhci: Fix ASMedia ASM1142 DMA addressing
+    - io_uring: prevent re-read of sqe->opcode
+    - io_uring: Fix use-after-free in io_sq_wq_submit_work()
+    - Revert "ALSA: hda: call runtime_allow() for all hda controllers"
+    - ALSA: hda/realtek: Add alc269/alc662 pin-tables for Loongson-3 laptops
+    - ALSA: hda/ca0132 - Add new quirk ID for Recon3D.
+    - ALSA: hda/ca0132 - Fix ZxR Headphone gain control get value.
+    - ALSA: hda/ca0132 - Fix AE-5 microphone selection commands.
+    - ALSA: seq: oss: Serialize ioctls
+    - staging: android: ashmem: Fix lockdep warning for write operation
+    - staging: rtl8712: handle firmware load failure
+    - Staging: rtl8188eu: rtw_mlme: Fix uninitialized variable authmode
+    - Bluetooth: Fix slab-out-of-bounds read in hci_extended_inquiry_result_evt()
+    - Bluetooth: Prevent out-of-bounds read in hci_inquiry_result_evt()
+    - Bluetooth: Prevent out-of-bounds read in hci_inquiry_result_with_rssi_evt()
+    - omapfb: dss: Fix max fclk divider for omap36xx
+    - binder: Prevent context manager from incrementing ref 0
+    - Smack: fix use-after-free in smk_write_relabel_self()
+    - scripts: add dummy report mode to add_namespace.cocci
+    - vgacon: Fix for missing check in scrollback handling
+    - mtd: properly check all write ioctls for permissions
+    - leds: wm831x-status: fix use-after-free on unbind
+    - leds: lm36274: fix use-after-free on unbind
+    - leds: da903x: fix use-after-free on unbind
+    - leds: lm3533: fix use-after-free on unbind
+    - leds: 88pm860x: fix use-after-free on unbind
+    - net/9p: validate fds in p9_fd_open
+    - drm/nouveau/fbcon: fix module unload when fbcon init has failed for some
+      reason
+    - drm/nouveau/fbcon: zero-initialise the mode_cmd2 structure
+    - drm/drm_fb_helper: fix fbdev with sparc64
+    - i2c: slave: improve sanity check when registering
+    - i2c: slave: add sanity check when unregistering
+    - usb: hso: check for return value in hso_serial_common_create()
+    - net: ethernet: mtk_eth_soc: Always call mtk_gmac0_rgmii_adjust() for mt7623
+    - ALSA: hda: fix NULL pointer dereference during suspend
+    - firmware: Fix a reference count leak.
+    - cfg80211: check vendor command doit pointer before use
+    - igb: reinit_locked() should be called with rtnl_lock
+    - atm: fix atm_dev refcnt leaks in atmtcp_remove_persistent
+    - tools lib traceevent: Fix memory leak in process_dynamic_array_len
+    - Drivers: hv: vmbus: Ignore CHANNELMSG_TL_CONNECT_RESULT(23)
+    - xattr: break delegations in {set,remove}xattr
+    - Revert "powerpc/kasan: Fix shadow pages allocation failure"
+    - PCI: tegra: Revert tegra124 raw_violation_fixup
+    - ipv4: Silence suspicious RCU usage warning
+    - ipv6: fix memory leaks on IPV6_ADDRFORM path
+    - ipv6: Fix nexthop refcnt leak when creating ipv6 route info
+    - net: ethernet: mtk_eth_soc: fix MTU warnings
+    - rxrpc: Fix race between recvmsg and sendmsg on immediate call failure
+    - vxlan: Ensure FDB dump is performed under RCU
+    - net: lan78xx: replace bogus endpoint lookup
+    - appletalk: Fix atalk_proc_init() return path
+    - dpaa2-eth: Fix passing zero to 'PTR_ERR' warning
+    - hv_netvsc: do not use VF device if link is down
+    - net: gre: recompute gre csum for sctp over gre tunnels
+    - net: thunderx: use spin_lock_bh in nicvf_set_rx_mode_task()
+    - openvswitch: Prevent kernel-infoleak in ovs_ct_put_key()
+    - Revert "vxlan: fix tos value before xmit"
+    - tcp: apply a floor of 1 for RTT samples from TCP timestamps
+    - ima: move APPRAISE_BOOTPARAM dependency on ARCH_POLICY to runtime
+    - [Config] update annotations for IMA_APPRAISE_BOOTPARAM
+    - nfsd: Fix NFSv4 READ on RDMA when using readv
+    - Linux 5.4.58
+  * Focal update: v5.4.57 upstream stable release (LP: #1891064)
+    - random32: update the net random state on interrupt and activity
+    - ARM: percpu.h: fix build error
+    - random: fix circular include dependency on arm64 after addition of percpu.h
+    - random32: remove net_rand_state from the latent entropy gcc plugin
+    - random32: move the pseudo-random 32-bit definitions to prandom.h
+    - arm64: Workaround circular dependency in pointer_auth.h
+    - ext4: fix direct I/O read error
+    - selftests: bpf: Fix detach from sockmap tests
+    - bpf: sockmap: Require attach_bpf_fd when detaching a program
+    - Linux 5.4.57
+  * Focal update: v5.4.56 upstream stable release (LP: #1891063)
+    - crypto: ccp - Release all allocated memory if sha type is invalid
+    - media: rc: prevent memory leak in cx23888_ir_probe
+    - sunrpc: check that domain table is empty at module unload.
+    - ath10k: enable transmit data ack RSSI for QCA9884
+    - PCI/ASPM: Disable ASPM on ASMedia ASM1083/1085 PCIe-to-PCI bridge
+    - mm/filemap.c: don't bother dropping mmap_sem for zero size readahead
+    - ALSA: usb-audio: Add implicit feedback quirk for SSL2
+    - ALSA: hda/realtek: enable headset mic of ASUS ROG Zephyrus G15(GA502) series
+      with ALC289
+    - ALSA: hda/realtek: typo_fix: enable headset mic of ASUS ROG Zephyrus
+      G14(GA401) series with ALC289
+    - ALSA: hda/realtek: Fix add a "ultra_low_power" function for intel reference
+      board (alc256)
+    - ALSA: hda/hdmi: Fix keep_power assignment for non-component devices
+    - IB/rdmavt: Fix RQ counting issues causing use of an invalid RWQE
+    - vhost/scsi: fix up req type endian-ness
+    - 9p/trans_fd: Fix concurrency del of req_list in p9_fd_cancelled/p9_read_work
+    - wireless: Use offsetof instead of custom macro.
+    - ARM: 8986/1: hw_breakpoint: Don't invoke overflow handler on uaccess
+      watchpoints
+    - ARM: dts: imx6sx-sabreauto: Fix the phy-mode on fec2
+    - ARM: dts: imx6sx-sdb: Fix the phy-mode on fec2
+    - ARM: dts: imx6qdl-icore: Fix OTG_ID pin and sdcard detect
+    - virtio_balloon: fix up endian-ness for free cmd id
+    - Revert "drm/amdgpu: Fix NULL dereference in dpm sysfs handlers"
+    - drm/amd/display: Clear dm_state for fast updates
+    - drm/amdgpu: Prevent kernel-infoleak in amdgpu_info_ioctl()
+    - drm/dbi: Fix SPI Type 1 (9-bit) transfer
+    - drm: hold gem reference until object is no longer accessed
+    - rds: Prevent kernel-infoleak in rds_notify_queue_get()
+    - libtraceevent: Fix build with binutils 2.35
+    - net/x25: Fix x25_neigh refcnt leak when x25 disconnect
+    - net/x25: Fix null-ptr-deref in x25_disconnect
+    - ARM: dts sunxi: Relax a bit the CMA pool allocation range
+    - xfrm: Fix crash when the hold queue is used.
+    - ARM: dts: armada-38x: fix NETA lockup when repeatedly switching speeds
+    - nvme-tcp: fix possible hang waiting for icresp response
+    - selftests/net: rxtimestamp: fix clang issues for target arch PowerPC
+    - selftests/net: psock_fanout: fix clang issues for target arch PowerPC
+    - selftests/net: so_txtime: fix clang issues for target arch PowerPC
+    - sh/tlb: Fix PGTABLE_LEVELS > 2
+    - sh: Fix validation of system call number
+    - net: hns3: fix a TX timeout issue
+    - net: hns3: fix aRFS FD rules leftover after add a user FD rule
+    - net/mlx5: E-switch, Destroy TSAR when fail to enable the mode
+    - net/mlx5e: Fix error path of device attach
+    - net/mlx5: Verify Hardware supports requested ptp function on a given pin
+    - net/mlx5e: Modify uplink state on interface up/down
+    - net/mlx5e: Fix kernel crash when setting vf VLANID on a VF dev
+    - net: lan78xx: add missing endpoint sanity check
+    - net: lan78xx: fix transfer-buffer memory leak
+    - rhashtable: Fix unprotected RCU dereference in __rht_ptr
+    - mlx4: disable device on shutdown
+    - mlxsw: core: Increase scope of RCU read-side critical section
+    - mlxsw: core: Free EMAD transactions using kfree_rcu()
+    - ibmvnic: Fix IRQ mapping disposal in error path
+    - bpf: Fix map leak in HASH_OF_MAPS map
+    - mac80211: mesh: Free ie data when leaving mesh
+    - mac80211: mesh: Free pending skb when destroying a mpath
+    - arm64/alternatives: move length validation inside the subsection
+    - arm64: csum: Fix handling of bad packets
+    - Bluetooth: fix kernel oops in store_pending_adv_report
+    - net: nixge: fix potential memory leak in nixge_probe()
+    - net: gemini: Fix missing clk_disable_unprepare() in error path of
+      gemini_ethernet_port_probe()
+    - net/mlx5e: fix bpf_prog reference count leaks in mlx5e_alloc_rq
+    - perf tools: Fix record failure when mixed with ARM SPE event
+    - vxlan: fix memleak of fdb
+    - usb: hso: Fix debug compile warning on sparc32
+    - selftests: fib_nexthop_multiprefix: fix cleanup() netns deletion
+    - qed: Disable "MFW indication via attention" SPAM every 5 minutes
+    - selftests: net: ip_defrag: modprobe missing nf_defrag_ipv6 support
+    - nfc: s3fwrn5: add missing release on skb in s3fwrn5_recv_frame
+    - scsi: core: Run queue in case of I/O resource contention failure
+    - parisc: add support for cmpxchg on u8 pointers
+    - net: ethernet: ravb: exit if re-initialization fails in tx timeout
+    - Revert "i2c: cadence: Fix the hold bit setting"
+    - x86/unwind/orc: Fix ORC for newly forked tasks
+    - x86/stacktrace: Fix reliable check for empty user task stacks
+    - cxgb4: add missing release on skb in uld_send()
+    - xen-netfront: fix potential deadlock in xennet_remove()
+    - RISC-V: Set maximum number of mapped pages correctly
+    - drivers/net/wan: lapb: Corrected the usage of skb_cow
+    - KVM: arm64: Don't inherit exec permission across page-table levels
+    - KVM: LAPIC: Prevent setting the tscdeadline timer if the lapic is hw
+      disabled
+    - x86/i8259: Use printk_deferred() to prevent deadlock
+    - perf tests bp_account: Make global variable static
+    - perf env: Do not return pointers to local variables
+    - perf bench: Share some global variables to fix build with gcc 10
+    - Linux 5.4.56
+
+  [ Ubuntu: 5.4.0-47.51 ]
+
+  * focal/linux: 5.4.0-47.51 -proposed tracker (LP: #1894315)
+  * CVE-2020-14386
+    - SAUCE: net/packet: fix overflow in tpacket_rcv
+  * Packaging resync (LP: #1786013)
+    - [Packaging] update helper scripts
+
+  [ Ubuntu: 5.4.0-45.49 ]
+
+  * focal/linux: 5.4.0-45.49 -proposed tracker (LP: #1893050)
+  * [Potential Regression] dscr_inherit_exec_test from powerpc in
+    ubuntu_kernel_selftests failed on B/E/F (LP: #1888332)
+    - powerpc/64s: Don't init FSCR_DSCR in __init_FSCR()
+
+ -- Wen-chien Jesse Sung <jesse.sung@canonical.com>  Mon, 19 Oct 2020 19:29:32 +0800
+
+linux-xilinx-zynqmp (5.4.0-1000.1) focal; urgency=medium
+
+  * Miscellaneous Ubuntu changes
+    - [Config] import configs
+
+  * Miscellaneous upstream changes
+    - microblaze: entry: Remove unneeded need_resched() loop
+    - microblaze: defconfig: Enable devtmps and tmpfs
+    - microblaze: Enable SPARSE_IRQ
+    - microblaze: Increase max dtb size to 64K from 32K
+    - PCI: Remove PCI_MSI_IRQ_DOMAIN architecture whitelist
+    - soc: xilinx: Set CAP_UNUSABLE requirement for versal while powering down
+      domain
+    - dt-bindings: firmware: Add bindings for Versal firmware
+    - firmware: xilinx: Add support for versal soc
+    - arm64: zynqmp: Add firmware DT node
+    - arm64: zynqmp: Add support for zynqmp fpga manager
+    - arm64: zynqmp: Label whole PL part as fpga_full region
+    - arm64: zynqmp: Add support for zynqmp nvmem firmware driver
+    - dt-bindings: clock: Add bindings for versal clock driver
+    - clk: zynqmp: Extend driver for versal
+    - mtd: rawnand: Add sync and async timing mode support
+    - mtd: rawnand: Add jedec_id to struct onfi_params
+    - dt-bindings: mtd: Document ARASAN NAND bindings
+    - arm64: dts: Add NAND Device support
+    - mtd: rawnand: Add support for ARASAN NAND controller
+    - mtd: rawnand: arasan: Add runtime support
+    - can: xilinx_can: skip error message on deferred probe
+    - can: xilinx_can: Fix usage of skb memory
+    - serial: xilinx_uartps: Let get_mctrl return status
+    - serial: xilinx_uartps: set_termios sets flowcontrol
+    - serial: xilinx_uartps: set_mctrl sets RTS and DTR
+    - dt-bindings: add documentation of xilinx clocking wizard
+    - clk: clock-wizard: Move the clockwizard to clk
+    - clk: clock-wizard: Fix kernel-doc warning
+    - clk: clock-wizard: Add support for dynamic reconfiguration
+    - clk: clock-wizard: Add support for fractional support
+    - clk: clock-wizard: Remove the hardcoding of the clock outputs
+    - clk: clock-wizard: Update the fixed factor divisors
+    - staging: clocking-wizard: Delete the driver from the staging
+    - clk: zynqmp: Add support for clock with CLK_DIVIDER_POWER_OF_TWO flag
+    - clk: zynqmp: Add support for custom type flags
+    - clk: zynqmp: Correct bit index for divider flag
+    - clk: zynqmp: Fix divider calculation
+    - clk: zynqmp: Warn user if clock user are more than allowed
+    - drivers: firmware: xilinx: Add support for feature check
+    - arm64: dts: xilinx: Add the clock nodes for zynqmp
+    - arm64: dts: xilinx: Remove dtsi for fixed clock
+    - arm64: dts: xilinx: Add the power nodes for zynqmp
+    - dt-bindings: power: reset: xilinx: Add bindings for ipi mailbox
+    - drivers: soc: xilinx: Use mailbox IPI callback
+    - firmware: xilinx: provides support to access efuse
+    - firmware: xilinx: Add pinctrl interface
+    - firmware: xilinx: Added pm api functions for RSA and SHA
+    - firmware: xilinx: Adds zynqmp-aes support
+    - firmware: xilinx: Adds new eemi call for reg access
+    - firmware: xilinx: xilinx: Add sysfs interface
+    - firmware: xilinx: Add missing debug firmware interfaces
+    - firmware: xilinx: Add pm api function for PL readback
+    - firmware: xilinx: Add AFI ioctl support
+    - firmware: xilinx: Add ULPI reset support
+    - firmware: xilinx: Add zynqmp SGMII firmware support
+    - firmware: xilinx: Add sysfs to set shutdown scope
+    - firmware: xilinx: Add sysfs and IOCTL to set boot health status
+    - firmware: xilinx: Add qspi firmware interface
+    - firmware: xilinx: Add firmware support for remoteproc
+    - firmware: xilinx: Add Pdi load API support
+    - firmware: xilinx: xilinx: Add IOCTL ids for probe counter
+    - firmware: xilinx: sync firmware pm_ioctl_id entries with PLM pm_ioctl_id
+      entries
+    - firmware: xilinx: Add IOCTL for handling usb power requests
+    - firmware: xilinx: Allow valid IOCTL ids only for versal
+    - dt-bindings: Add dt bindings for flex noc Performance Monitor
+    - misc: xilinx_flex: Add support for the flex noc Performance Monitor
+    - Documentation: short descriptions for Flexnoc Performance Monitor driver
+    - rtc: xilinx: Fix calibval variable type
+    - rtc: zynqmp: re-use rtc_time64_to_tm operation
+    - rtc: zynqmp: Clear alarm interrupt status before interrupt enable
+    - dt-bindings: dmaengine: xilinx_dma: Remove axidma multichannel support
+    - dmaengine: xilinx_dma: use devm_platform_ioremap_resource()
+    - dmaengine: xilinx_dma: Remove clk_get error message for probe defer
+    - dmaengine: xilinx_dma: Remove desc_callback_valid check
+    - dmaengine: xilinx_dma: Merge get_callback and _invoke
+    - dmaengine: xilinx_dma: Remove residue from channel data
+    - dmaengine: xilinx_dma: Introduce xilinx_dma_get_residue
+    - dmaengine: xilinx_dma: Add callback_result support
+    - dmaengine: xilinx_dma: Print debug message when no free tx segments
+    - dmaengine: xilinx_dma: Remove axidma multichannel mode support
+    - dt-bindings: dmaengine: xilinx_dma: Fix formatting and style
+    - dt-bindings: dmaengine: xilinx_dma: Add binding for Xilinx MCDMA IP
+    - dmaengine: xilinx_dma: Extend dma_config struct to store irq routine handle
+    - dmaengine: xilinx_dma: Add Xilinx AXI MCDMA Engine driver support
+    - dt-bindings: dmaengine: Add binding for xilinx axidma test client
+    - dmaengine: xilinx: Add axidmatest test client code
+    - dt-bindings: dmaengine: Add binding for vdmatest client
+    - dmaengine: xilinx: Add vdmatest test client code
+    - mm: page_alloc: Demote the PFNs busy message to debug
+    - uio: Add dma-buf import ioctls
+    - dt-bindings: soc: xilinx: Add the dt binding for AI engine
+    - uio: Add the UIO driver for AI engine
+    - uio: xilinx_ai_engine: Map the dynamic memory as write-combine
+    - staging: dt-bindings: Add doc about APF
+    - apf: Add kernel modules to the kernel
+    - dt: bindings: sound: Add DT bindings for Xilinx ZynqMP DP audio
+    - sound: soc: xilinx: Add ZynqMP DP subsystem audio drivers
+    - sound: xilinx: pcm: Set the shorter device name
+    - sound: soc: xilinx: Remove empty xilinx_dp_remove()
+    - sound: soc: xilinx: Remove empty xilinx_dp_pcm_dev_remove()
+    - AsoC: xlnx: add platform driver to support SDI audio
+    - ASoC: xlnx: add capture component DAI
+    - ASoC: xlnx: add playback component DAI
+    - ASoC: xlnx: add pcm formatter platform driver
+    - ASoC: xlnx: Enable audio formatter build
+    - ASoC: xlnx: add alsa pcm device support
+    - ASoC: xlnx: Enable SDI audio build
+    - ASoC: xlnx: add PL sound card device creation
+    - ASoC: xlnx: add PL sound card support
+    - ASoC: xlnx: update SDI audio driver to v2.0
+    - ASoC: xlnx: Use graph API instead of phandle
+    - ASoC: xlnx: add new supported formats
+    - ASoC: xlnx: remove SDI Rx AES parsing
+    - ASoC: xlnx: correct the audio formatter masks
+    - ASoC: xlnx: Move audio interface node names to driver data
+    - ASoC: xlnx: Add AES channel status parsing
+    - ASoC: xlnx: Reset S2MM for next channel status update
+    - ASoC: xlnx: enable axi clock in audio formatter
+    - ASoC: xlnx: support multiple sampling rates for HDMI
+    - ASoC: xlnx: support multiple sampling rates for SDI
+    - ASoC: xlnx: Set missing/invalid channel count to default value in consumer
+      format
+    - ASoC: xlnx: disable strict check of AES parameters
+    - ASoC: xlnx: Disable clock wizard usage in audio driver
+    - dt-bindings: ASoC: xlnx,spdif: Document spdif bindings
+    - ASoC: xlnx: add SPDIF audio driver
+    - ASoC: xlnx: add SPDIF sound card support
+    - ASoC: xlnx: enable SPDIF build
+    - ASoC: xlnx: Fixes in audio formatter driver
+    - ASoC: xlnx: refine audio formatter irq enablement
+    - ASoC: xlnx: support multiple instances of sound card
+    - ASoC: xlnx: enable multi sample rate support for I2S sound card
+    - ASoC: xlnx: enable multi sample rate support for HDMI sound card
+    - ASoC: xlnx: enable multi sample rate support for SPDIF sound card
+    - dt-bindings: ASoC: xlnx-v-uhdsdi-audio: document sdi audio bindings
+    - dt-bindings: ASoC: Document audio formatter bindings for xlnx,audio-
+      formatter
+    - ASoC: xlnx,i2s: dt-bindings: add reference to audio formatter
+    - ASoC: xlnx: add audio support in 4k mode
+    - ASoC: xlnx: add multi sample rate support for SDI audio
+    - ASoC: xlnx: clear bits before assigning desired value
+    - ASoC: xlnx: reuse framework macros to parse AES audio header
+    - dt-bindings: dma: xilinx: dpdma: DT bindings for Xilinx DPDMA
+    - dma: xilinx: dpdma: Add the Xilinx DisplayPort DMA engine driver
+    - dma: xilinx: dpdma: Implement the synchronize callback
+    - drm: drm_fourcc: Introduce macro-pixel info to drm_format_info
+    - drm: fourcc: Add drm_format_plane_width_bytes()
+    - drm: drm_fourcc: Add new formats for Xilinx IPs
+    - drm: fourcc: Add new formats needed by Xilinx IP
+    - drm: drm_fourcc: Correct the DRM YUV444 10bpc
+    - uapi: drm: Add AVUY fourcc
+    - drm: Add new flags for interlaced alternate fields
+    - uapi: media: New fourcc codes needed by Xilinx Video IP
+    - media: Add documentation for YUV420 bus format
+    - dt-bindings: dmaengine: xilinx_frmbuf: Video Framebuffer IP
+    - dmaengine: xilinx_frmbuf: New driver for Video Framebuffer IP
+    - dmaengine: xilinx_frmbuf: Update Framebuffer Driver with support for new
+      8-bit/10-bit formats
+    - dmaengine: xilinx_frmbuf: Add support for BGR8 color format in Framebuffer
+    - dmaengine: xilinx_frmbuf: Add support for XV15 and XV20 contiguous formats
+    - dmaengine: xilinx_frmbuf: Add interlaced support to Xilinx Framebuffer
+      driver
+    - dmaengine: xilinx_frmbuf: Add alpha formats support for Framebuffer Read
+    - dmaengine: xilinx_frmbuf: Get DMA alignment from device tree for Framebuffer
+    - dmaengine: xilinx_frmbuf: Flush the framebuffer FIFO on halt
+    - dmaengine: xilinx_frmbuf: Add fid property for interlaced support in
+      framebuffer
+    - dmaengine: xilinx_frmbuf: Add check for max width and height in Framebuffer
+      Read/Write
+    - dmaengine: xilinx_frmbuf: Mark previous active decriptor as complete in irq
+      handler
+    - dmaengine: xilinx_frmbuf: Add API to set framebuffer IP mode
+    - dmaengine: xilinx_frmbuf: Add early callback support to Framebuffer Driver
+    - dmaengine: xilinx_frmbuf: Add clock framework support to Framebuffer driver
+    - dmaengine: xilinx_frmbuf: Fix compilation errors when kernel config doesn't
+      have Framebuffer
+    - drm: panel: Added timing for AUO B101UAN01 display panel
+    - drm: Add adv7511 encoder driver
+    - media: entity: Add has_route entity operation
+    - media: entity: Add media_entity_has_route() function
+    - v4l: subdev: Add [GS]_ROUTING subdev ioctls and operations
+    - v4l: Add RGB 8:8:8 media bus format on 24 and 32 bit busses
+    - v4l: Add VUY8 24 bits bus format
+    - uvcvideo: Xilinx: Bump up URBS and MAX_PACKETS
+    - drm: ZynQ OpenCL driver
+    - v4l: xilinx: Kconfig: Add missing DMADEVICES dependencies
+    - media: xilinx: Ensure Video Framebuffer selected by Kconfig
+    - v4l: xilinx: Add Video Remapper driver
+    - media: xilinx: Add Color Filter Array (CFA) driver
+    - media: xilinx: Add Chroma Resampler (CRESAMPLE) driver
+    - media: xilinx: Add RGB to YUV (RGB2YUV) driver
+    - media: xilinx: Add Scaler driver (SCALER) driver
+    - media: xilinx: Add AXI4 stream switch driver
+    - media: xilinx: Add HLS core driver
+    - media: xilinx: Integrate TPG v7 support
+    - media: xilinx: Use xvip_write to update background pattern
+    - media: xilinx: Add "Pseudorandom" pattern support
+    - media: xilinx: Make use of MEDIA_BUS_FMT definitions
+    - media: xilinx: Skip checking bayer phase
+    - media: xilinx: Use GPIO to assert TPG reset
+    - media: xilinx: Fix TPG incorrect pattern on resolution switch
+    - media: xilinx: Fix "maybe used uninitialized" warning
+    - media: xilinx: tpg: Block comments
+    - media: xilinx: Refactor VTC configuration code
+    - media: xilinx: vip: Add the pixel format for RGB24
+    - v4l: xilinx-dma: Update xvip_dma_init routine to allow for probe defer
+    - v4l: xilinx: dma: Terminate DMA when stream on fails
+    - media: xilinx: dma: Enable use of Framebuffer Write IP in V4L2 Driver
+    - v4l: xilinx: dma: Remove colorspace check in xvip_dma_verify_format
+    - media: xilinx: Improve pipeline management code
+    - xcsi2rxss: Add DT documentation for Xilinx MIPI CSI-2 Receiver Subsystem
+      driver
+    - xcsi2rxss: Add support for Xilinx CSI-2 Receiver Subsystem
+    - documentation: dt: add bindings documentation for xilinx video demosaic
+      driver
+    - v4l: xilinx-demosaic: driver support for xilinx video demosaic
+    - documentation: dt: add bindings documentation for vpss scaler
+    - v4l: xilinx-vpss-scaler: driver support for xilinx vpss scaler
+    - dt: bindings: media: xilinx: Documentation for Xilinx UHDSDI Rx driver
+    - v4l: xilinx: Driver support for Xilinx UHDSDI Rx subsystem
+    - documentation: dt: add bindings documentation for gamma lut ip
+    - v4l: xilinx-gamma: initial driver support for xilinx video gamma lut ip
+    - Documentation: DT: Add bindings documentation for VPSS CSC
+    - v4l: xilinx-vpss-csc: driver support for xilinx vpss csc
+    - drivers: media: Customized adv7511 for Xylon LogiCVC (deprecated)
+    - drm: mipi: Bring DT format description closer to the hardware
+    - v4l: xilinx: sdirxss: Decode ST352 in irq context
+    - v4l: xilinx: sdirxss: Add ST352 decode macros
+    - v4l: xilinx: sdirxss: Add support for subdev get frame interval
+    - v4l: xilinx: sdirxss: Add v4l control for transport stream type
+    - v4l: xilinx: sdirxss: Add V4L control for Active streams
+    - v4l: xilinx: sdirxss: Add V4L control for 3G Level B support
+    - v4l: xilinx: sdirxss: Remove useless semicolon
+    - drm: xlnx: Xilinx DRM KMS driver
+    - dt-bindings: display: xlnx: Add ZynqMP DP subsystem bindings
+    - drm: xlnx: DRM KMS driver for Xilinx ZynqMP DP subsystem display
+    - drm: xlnx: DRM KMS driver for Xilinx ZynqMP DisplayPort
+    - drm: xlnx: ZynqMP DP subsystem DRM KMS driver
+    - drm: xlnx: zynqmp_disp: Add drm properties
+    - drm: xlnx: zynqmp_dp: Add drm properties
+    - dt-bindings: display: xlnx: Add bridge bindings
+    - drm: xlnx: drv: Add Xilinx bridge support
+    - drm: xlnx: zynqmp: Add Xlnx bridge support
+    - drm: xlnx: Kconfig: Select dpdma for ZynqMP DP
+    - drm: xilinx: Kconfig: Add missing DMADEVICES dependencies
+    - dt-bindings: display: xlnx: Adding dsi bindings
+    - drm: xlnx: dsi: Adding dsi driver to new framework
+    - drm: xlnx: adding cursor width / height support
+    - dt-bindings: display: xlnx: Adding mixer bindings
+    - drm: xlnx: mixer: Initial video mixer driver
+    - dt-bindings: display: xlnx: Adding sdi bindings
+    - drm: xlnx: sdi: Adding sdi-tx driver
+    - dt-bindings: display: xlnx: Adding pl_disp bindings
+    - drm: xlnx: DRM KMS driver for xilinx display pipeline
+    - v4l: xilinx: sdirxss: Update Video lockout Window to 32 bit
+    - drm: xlnx: bridge: Fix the multiple definition error
+    - drm: xlnx: bridge: Add support for set and get output parameters
+    - dt: bindings: display: xlnx: Adding csc bindings
+    - drm: xlnx: csc: Adding vpss-color space converter driver
+    - dt: bindings: display: xlnx: Adding scaler bindings
+    - drm: xlnx: scaler: Adding vpss-scaler driver
+    - dt: bindings: media: xilinx: Add rev 3.0 to csi2rxss compatible string
+    - v4l: xilinx: csi2rxss: Add rev 3.0 compatible string
+    - drm: xlnx: xlnx_drv: Remove the dt binding
+    - drm: xlnx: zynqmp: Use xlnx pipeline calls
+    - dt-bindings: display: xlnx: zynqmp-dpsub: Update the documentation
+    - drm: xlnx: zynqmp: disp: Use the device node for layers
+    - drm: xlnx: xlnx_drv: Move xlnx bridge helper initialization
+    - dt-bindings: display: xlnx: zynqmp-dpsub: Make layers as child node
+    - Revert "drm: xlnx: zynqmp: disp: Use the device node for layers"
+    - drm: xlnx: pl_disp: Use xlnx pipeline calls
+    - drm: xlnx: mixer: Use xlnx pipeline call
+    - dt-bindings: display: xlnx: Added vpss bridge phandle as optional property
+    - drm: xlnx: bridge: Add Xilinx bridge support to set and get output
+      parameters
+    - drm: xlnx: sdi: Adding xlnx bridge support
+    - drm: xlnx: zynqmp: Add XV15 and XV20 formats
+    - dt-bindings: display: xlnx: Added vpss bridge phandle as optional property
+    - drm: xlnx: dsi: Adding xlnx bridge support
+    - dt: bindings: display: xlnx: Adding gpio reset entry
+    - drm: xlnx: scaler: Adding vpss-scaler reset through gpio
+    - media: xilinx-vpss-scaler: Zero out H-phase array before changing resolution
+    - drm: xlnx: mixer: logo layer fix
+    - drm: xlnx: drv: Allow multiple masters on a drm device
+    - drm: xlnx: scaler: Adding Zero out H-phase array before changing resolution
+    - drm: xlnx: mixer: Removing dead code
+    - drm: xlnx: mixer: Correcting the cursor width and height
+    - drm: xlnx: correcting data type for cursor with and height
+    - media: Add new dt-bindings/vf_codes for supported formats
+    - media-bus: uapi: Add YCrCb 420 media bus format
+    - v4l: xilinx: dma: Update video format descriptor
+    - v4l: xilinx: dma: Add multi-planar support
+    - v4l: xilinx: dma: Fix v4l2 enumeration callback for multiplanar
+    - v4l: xilinx: dma: Add scaling and padding factor functions
+    - v4l: xilinx: dma: Get scaling and padding factor to calculate DMA params
+    - drm: xlnx: scaler: Add YUV420 support
+    - drm: xlnx: csc: Add YUV420 support
+    - v4l: xilinx-vpss-scaler: Add YUV 420 to VPSS Scaler Driver
+    - v4l: xilinx-demosaic: Remove Output Video format register
+    - v4l: xilinx-gamma: Add 10-bit IP support for Video Gammma IP.
+    - v4l: xilinx-gamma: Add kernel-doc for xgamma_dev struct
+    - v4l: xilinx-gamma: Fix compile error in debug mode
+    - Documentation: media: Correct dt-bindings doc for Gamma LUT IP
+    - Documentation: media: Update dt-bindings doc for 10-bit color depth in vpss-
+      csc
+    - v4l: xilinx-vpss-csc: Support for any-to-any color space converison
+    - dt-bindings: display: xlnx: Modifing mixer compatible string
+    - drm: xlnx: mixer: Adding mixer 3.0 IP support
+    - drm: xlnx: mixer: Adding more colors in supported list
+    - drm: xlnx: mixer: Correcting loop termination condition
+    - drm: xlnx: mixer: Fixing wrong stride alignment
+    - v4l: xilinx-tpg: Add YUV 420 media bus format support to TPG driver
+    - drm: xlnx: sdi: Adding yuv 420 support
+    - dt: bindings: media: xilinx: Add YUV420 decoding support in UHDSDI Rx
+    - v4l: xilinx: sdirxss: Add support for YUV420 decoding
+    - media: v4l2-core: Update V4L2 framework with new fourcc codes
+    - v4l: xilinx: dma: Fix sizeimage calculation
+    - v4l: xilinx: dma: Handle 10 bit format calucations for XV20
+    - v4l: xilinx: dma: Fix bytes per line calculation
+    - v4l: xilinx: Add BGR color format support.
+    - media: xilinx: vip: Correct the fourcc code for BGRX8 format.
+    - dt: bindings: media: xilinx: Remove unimplemented TPG compatible string
+    - drm: xlnx: mixer: remove deprecated dmaengine_terminate_all
+    - drm: xlnx: mixer: reset the mixer IP before programming
+    - v4l: xilinx: dma: Add XV15 and XV20 contiguous format support
+    - v4l2-core: Update entries for XV15 and XV20 contiguous formats
+    - uvcvideo: Prevent new URBs being processed at stream stop
+    - dt: bindings: display: xlnx: Updated gpio reset entry
+    - drm: xlnx: scaler: Updating vpss-scaler reset logic
+    - dt: bindings: display: xlnx: Adding gpio reset entry
+    - drm: xlnx: csc: Adding vpss-csc reset through gpio
+    - drm: xlnx: zynqmp_dp: Use the correct number of lanes
+    - xilinx: v4l2: dma: Bug fix in single plane support
+    - drm: xlnx: drv: Shutdown the drm device properly
+    - drm: xlnx: zynqmp: Disable a plane when the fb format changes
+    - bindings: display: xlnx: Fixing device tree documentation
+    - v4l: xilinx: sdirxss: Correct the v4l2_field to V4L2_FIELD_ALTERNATE
+    - drm: xlnx: pl_disp: fix odd_ptr_err.cocci warnings
+    - dt-bindings: display: xlnx: mixer: Add supported formats table
+    - dt-bindings: display: xlnx: mixer: Update example to fix format strings
+    - drm: xlnx: fb: Prefer the current format depth over depth from fb helper
+    - v4l: xilinx: dma: Add interlaced support
+    - drm: xlnx: zynqmp: Update planes asynchronously in the legacy entry
+    - v4l: xilinx: dma: Terminate DMA when media pipeline fails to start
+    - xilinx: v4l2: dma: Add multiple output support
+    - drm: xlnx: mixer: Update planes asynchronously in the legacy entry
+    - drm: xlnx: pl_disp: fix vblank time out issue
+    - dt-bindings: display: xlnx: mixer: Added xlnx,num-layers description
+    - drm: xlnx: mixer: making logo layer optional
+    - drm: xlnx: mixer: Added the atomic check for invalid coordinates
+    - dt-bindings: display: xlnx: mixer: Adding xlnx,layer-primary property
+    - drm: xlnx: zynqmp: Don't update the plane for the same fb
+    - drm: xlnx: zynqmp_dp: Initialize dpsub without phy
+    - v4l: xilinx: sdirxss: Correct the height of SD 525i to 486
+    - drm: xlnx: bridge: Add support for VTC as bridge
+    - dt-bindings: display: xlnx: Add VTC bindings
+    - drm: xlnx: Add a Video Timing Controller(VTC) driver
+    - drm: xlnx: vtc: Remove xilinx_vtc_remove()
+    - drm: xlnx: vtc: Fix the kernel-doc warnings
+    - drm: xlnx: vtc: Use of_match_node()
+    - drm: xlnx: vtc: Return IRQ_NONE for no interrupt
+    - drm: xlnx: vtc: Block comments using a trailing */ on a separate line
+    - drm: xlnx: vtc: adding interlaced support
+    - drm: xlnx: vtc: removing hard coded values for signal polarity
+    - drm: xlnx: vtc: exporting interrupt APIs
+    - drm: xlnx: vtc: Adding VTC as bridge driver
+    - dt-bindings: display: xlnx: mixer: Adding xlnx vtc bridge support
+    - drm: xlnx: mixer: Add VTC bridge support.
+    - dt-bindings: display: xlnx: Add VTC bridge support to PL display
+    - drm: xlnx: pl_disp: Add VTC bridge support
+    - drm: xlnx: vtc: Update license to SPDX
+    - drm: xlnx: sdi: Fix VTC polarity for SD modes
+    - drm: xlnx: sdi: Fix the HSIZE calculation
+    - drm: xlnx: sdi: Fix the Vertical Field 1 Size calculation
+    - drm: xlnx: sdi: Fix the VSync_Start and VSync_End for interlaced modes
+    - drm: xlnx: zynqmp_disp: handle software vblank
+    - drm: xlnx: zynqmp_dpsub handling for DP PM
+    - drm: xlnx: zynqmp_dpsub: Support reserved memory
+    - drm: xlnx: zynqmp_disp: Modul param for initial format of gfx layer
+    - xilinx: v4l: dma: Multi-threading issue
+    - drm: xlnx: mixer: Fix bug in programming 64-bit address
+    - drm: xlnx: sdi: Add support for Field 1 Active size
+    - drm: xlnx: sdi: Program Field 1 VTC registers in interlaced mode only
+    - drm: xlnx: vtc: Add support for Field 1 Active size
+    - drm: xlnx: vtc: Program Field 1 VTC registers in interlaced mode only
+    - drm: xlnx: sdi: enable audio
+    - drm: xlnx: zynqmp_disp: Configure the coefficients for TPG
+    - dt: bindings: media: xilinx: sdirxss : Add clock framework support
+    - v4l: xilinx: sdirxss: Add support for clock framework
+    - xilinx: v4l: dma: Fix bug in calculating interlaced height
+    - dt: bindings: media: xilinx: Doc for Xilinx AXI4-Stream Switch driver
+    - v4l: xilinx: Driver support for Xilinx AXI4-Stream Switch
+    - drm: xlnx: sdi: Fix timing for 720x486i SD mode
+    - drm: xlnx: sdi: add video mode hdisplay, flags to the shared data
+    - media: platform: xilinx: Fix Kconfig indentation
+    - xilinx: v4l: dma: Add ioctl operations for v4l2 output device
+    - xilinx: v4l: dma: Add DMA input direction support
+    - xilinx: v4l: dma: Add format enumeration for output
+    - v4l: xilinx: scd: Add v4l2 custom events
+    - documentation: dt: add bindings documentation for Scene Change Detection
+    - v4l: xilinx: scd: New Scene Change Detection driver
+    - xilinx: v4l: xilinx: Fix order in Makefile
+    - documentation: dt: add bindings documentation for multi-scaler
+    - platform: xilinx: Add mem to mem Multi-Scaler driver (XM2MSC)
+    - dt: bindings: media: xilinx: Documentation for mem2mem driver
+    - xilinx: v4l: mem2mem: Initial version of driver
+    - dt-bindings: display: xlnx: Add support for ancillary port
+    - drm: xlnx: sdi: Enable support for ancillary data
+    - dt-bindings: display: xlnx: Add ST352 payload insertion in Chroma stream
+    - drm: xlnx: sdi: Add ST352 payload insertion in Chroma stream
+    - drm: xlnx: sdi: Add support for DS2 payload in 3GA mode
+    - drm: xlnx: mixer: Fix linking failure for ARCH arm
+    - v4l: dma: Use media graph traversal to stream on/off subdevs
+    - drm: fb: Modify check to ensure correctness of flags
+    - drm: xlnx: sdi: Fix clearing en_st352_c and use_ds2_3ga drm properties
+    - documentation: dt: vtpg: Add support for max width and height
+    - v4l: xilinx: tpg: Add check for max width and height
+    - documentation: dt: demosaic: add support for max width and height
+    - v4l: xilinx-demosaic: Add check for max width and height
+    - documentation: dt: gamma: Add support for max width and height
+    - v4l: xilinx-gamma: Add check for max width and height
+    - documentation: dt: vpss-csc: Add support for max width and height
+    - v4l: xilinx-vpss-csc: Add check for max width and height
+    - documentation: dt: vpss-scaler: Add support for max width and height
+    - v4l: xilinx-vpss-scaler: Add check for max width and height
+    - xilinx: v4l: m2m: Terminate the dma engine before releasing buffers
+    - drm: xlnx: pl_disp: Pass interlaced field info to frmbuf DMA
+    - v4l: xilinx: vpss-scaler: Fix array out of bound access
+    - drm: xlnx: scaler: Fix array out of bound access
+    - dt-bindings: csi2rxss: Enable VCX support
+    - v4l: xilinx: xcsi2rxss: Add VCX support
+    - drm: xlnx: mixer: Fix switching to 4K after 1080p
+    - xilinx: v4l: dma: Remove unused function definition
+    - dt-bindings: media: xilinx: demosaic: Make max width, height mandatory
+    - v4l: xilinx-demosaic: Correct default values when width, height dt property
+      absent
+    - dt-bindings: media: xilinx: vpss-csc: Make max width, height mandatory
+    - v4l: xilinx-gamma: Correct default values when max width, height dt property
+      absent
+    - v4l: xilinx: vpss-scaler: Correct default values when max width, height dt
+      property absent
+    - drm: xlnx: zynqmp_disp: Fixing potential segmentation fault
+    - xilinx: v4l: dma: In case of error xvip_pipeline_start_stop should return
+      gracefully
+    - v4l: xilinx-multi-scaler: Remove unsupported formats
+    - v4l: xilinx-multi-scaler: Add support for VIDIOC_CREATE_BUFS for Dmabuf
+      io_mode
+    - v4l: xilinx-multi-scaler: Remove unused variables min_col and min_row
+    - v4l: xilinx-multi-scaler: Return the proper parameters in S_FMT
+    - v4l: xilinx-multi-scaler: Corrects the format struct in TRY_FMT
+    - v4l: xilinx-multi-scaler: Fix buffer type in enum_fmt_vid_out
+    - v4l: xilinx-multi-scaler: ENUM_FMT map index with enabled format
+    - v4l: xilinx-multi-scaler: Allow abort for individual channels
+    - v4l: xilinx-multi-scaler: Fix stop streaming
+    - v4l: xilinx-multi-scaler: Allow device run for single channel
+    - v4l: xilinx-multi-scaler: Restructuring of functions
+    - v4l: xilinx-multi-scaler: Allow stream on for the immediate next channel
+    - v4l: xilinx-multi-scaler: Do not allow new task when device is busy
+    - v4l: xilinx-multi-scaler: Wait for all running channels to get buffer
+    - v4l: xilinx-multi-scaler: Add number of frames processed per channel
+    - v4l: xilinx-multi-scaler: Check any channel is still running in streamoff
+    - v4l: xilinx-multi-scaler: Fix pointers in set chk chan_stream
+    - v4l: xilinx-multi-scaler: Add reserve area between channel 4 and 5
+    - xilinx: v4l: vipp: Avoid decrementing refcount of a node twice
+    - xilinx: v4l: dma: Invoke s_power function of subdevice
+    - drm: xlnx: Select VIDEOMODE_HELPERS when DRM_XLNX_PL_DISP is selected
+    - xilinx: v4l: m2m: Set default mode for framebuffer IP
+    - media: ov5640: fix get_light_freq on auto
+    - media: ov5640: Don't access ctrl regs when off
+    - media: ov5640: Add additional media bus formats
+    - media: xilinx: csi2rxss: store format size
+    - drm: xlnx: pl_disp: Enable early callback
+    - v4l: xilinx-multi-scaler: Remove volatile
+    - v4l: xilinx-multi-scaler: Change maximum supported height and width
+    - v4l: xilinx-multi-scaler: Move tap parameter to xm2msc_dev from channel
+      context
+    - v4l: xilinx-multi-scaler: Read tap from the device-tree
+    - v4l: xilinx-multi-scaler: Adding coefficients for 8, 10, 12 taps
+    - v4l: xilinx-multi-scaler: Select taps as per scaling ratio
+    - v4l: xilinx-multi-scaler: Change function names
+    - v4l: xilinx-multi-scaler: Noncontiguous planes support
+    - xilinx: v4l: dma: Stop subdevs in reverse order of starting
+    - drm: xlnx: sdi: Disable bridge instance
+    - drm: xlnx: dsi: Disable bridge instance
+    - documentation: dt: Add bindings documentation for Streaming SCD
+    - xilinx: v4l: scd: Initial version of streaming based driver
+    - xilinx: v4l: scd: Validate interrupt number
+    - xilinx: v4l: scd: Implement generic event notification
+    - v4l: xilinx-multi-scaler: Fix the size of 2nd plane for 4:2:2 video formats
+    - drm: xlnx: dsi: Fix kernel panic when "halt" is run
+    - drm: xlnx: crtc: Fix max width and height overflow
+    - dt-bindings: display: xlnx: mixer: Correct DRM fourcc for BGR8 and RGB8
+    - dt-bindings: csi2rxss: Add clock framework support
+    - v4l: xilinx: xcsi2rxss: Add support for clock framework
+    - documentation: dt: vpss-scaler: Fix support for clock framework
+    - v4l: xilinx: vpss-scaler: Fix clock framework support
+    - dt: bindings: media: xilinx: Add clock support to AXI4 Stream switch
+    - v4l: xilinx: axis-switch: Add support for clock framework
+    - dt-bindings: display: xlnx: Add device tree binding for xlnx control drivers
+    - drm: xlnx: zynqmp_disp: Add Y only formats support
+    - media: xilinx: tpg: Add pixel per clock dt support
+    - dt: bindings: media: xilinx: tpg: Add ppc dt bindings.
+    - media: xilinx: tpg: v4l subdevice controls to set fps
+    - media: xilinx: vtc: Dynamically calculate pixel clock
+    - media: xilinx: multi-scaler: support VB2_USERPTR IO mode
+    - media: xilinx: multi-scaler: Replace dev_info with dev_dbg if all jobs are
+      not ready
+    - documentation: dt: multi-scaler: Add properties for pixels per clock
+    - media: xilinx: multi-scaler: Add extra padding bytes after each row of
+      pixels
+    - media: xilinx: multi-scaler: Align width to pixels per clock
+    - media: xilinx: multi-scaler: Add support for formats having contiguous
+      buffers for two planes.
+    - drm: xlnx: zynqmp: Handle the event when there's no fb
+    - drm: xlnx: zynqmp: Remove unused variable
+    - documentation: dt: multi-scaler: Add clock framework support
+    - media: xilinx: multi-scaler: Add clock framework support
+    - media: xilinx: multi-scaler: Support stride and height alignment
+    - dt-bindings: display: xlnx: Add clock framework support to DSI Tx
+    - drm: xlnx: dsi: Add support for clock framework
+    - dt-bindings: display: xlnx: Add clock framework support to SDI Tx
+    - drm: xlnx: sdi: Add clock framework support
+    - dt-bindings: display: xlnx: Add clock framework support to VPSS CSC bridge
+      driver
+    - drm: xlnx: csc: Add clock framework support
+    - dt-bindings: display: xlnx: Add clock framework support to VPSS Scaler
+      bridge driver
+    - drm: xlnx: scaler: Add support for clock framework
+    - dt-bindings: display: xlnx: Add clock framework support to VTC bridge driver
+    - drm: xlnx: vtc: Add clock framework support
+    - media: xilinx: tpg: dt pixel per clock validate.
+    - media: xilinx: m2m: Xilinx M2M composite video framework
+    - ASoC: xlnx: move mm2s/s2mm configuration to functions
+    - dt-bindings: ASoC: xlnx,audio-formatter.txt: update clocks
+    - ASoC: xlnx: use clock framework for clocks to audio formatter
+    - ASoC: xlnx: change I2S driver data
+    - ASoC: xlnx,i2s: dt-bindings: update with I2S clocks
+    - ASoC: xlnx: use clock framework for clocks to I2S
+    - dt-bindings: ASoC: xlnx,v-uhdsdi-audio.txt: update input clocks
+    - ASoC: xlnx: use clock framework for clocks to SDI audio
+    - dt-bindings: ASoC: xlnx,spdif: update input clocks
+    - ASoC: xlnx: use clock framework for clocks to SPDIF
+    - drm: xlnx: sdi: Correcting drm property creation logic
+    - drm: xlnx: pl_disp: handle software vblank
+    - dma: xilinx: Define early callback modes
+    - dma: xilinx: Support early callback modes
+    - drm: xlnx: pl_disp: Pass early callback mode
+    - dma: xilinx: Release buffers before DMA transfer
+    - v4l: xilinx: dma: Add control for low latency
+    - v4l: xilinx: dma: Add s_ctrl ioctl for low latency capture
+    - media: v4l: Add 10, 12 and 16 bpc RBG media bus formats
+    - media: v4l2-ioctl: Add 12 and 16 bpc RGB pixel formats
+    - dt-bindings: dma: xilinx_frmbuf: Add support for 12 and 16 bpc RGB formats
+    - dmaengine: xilinx: frmbuf: Add support for 12 and 16 bpc RGB formats
+    - v4l: xilinx: vip: Add 12 and 16 bpc RAW and RGB color formats
+    - dt-bindings: media: xilinx: csi2rxss: Add RAW16 and RAW20 pixel format
+      strings
+    - v4l: xilinx: xcsi2rxss: Add support for RAW16 format
+    - v4l: xilinx-demosaic: Add support for 10,12,16 bpc RAW and RGB bus formats
+    - v4l: xilinx: multi-scaler: Fix precedence error
+    - v4l: xilinx: multi-scaler: Set channel parameters to default values
+    - drm: xlnx: zynqmp_dp: Fix DP aux related issues
+    - drm: xlnx: dsi: Fix the drm property creation
+    - media: v4l: Add YUV 12bit and 16bit media bus formats
+    - media: v4l2-ioctl: Add YUV 12bit and 16bit pixel formats
+    - v4l: xilinx: dma: Add YUV 12bit and 16bit format support
+    - dt-bindings: media: xilinx: tpg: Update for v8.0
+    - media: xilinx: tpg: Add support for v8.0
+    - v4l: xilinx-demosaic: Make max width and height properties mandatory
+    - v4l: xilinx-gamma: Make max-width and max-height mandatory dt properties
+    - dt-bindings: dma: xilinx_frmbuf: Make max-width and max-height as mandatory
+      properties
+    - dmaengine: xilinx: frmbuf: Make max-width and max-height mandatory
+      properties
+    - dt-bindings: media: vpss-csc: Make max width and height mandatory properties
+    - v4l: xilinx-vpss-csc: Make max width and height mandatory properties
+    - dt-bindings: media: vpss-scaler: Make max width and height mandatory
+      properties
+    - v4l: xilinx: vpss-scaler: Make max width and height mandatory properties
+    - dt-bindings: display: xlnx: vpss-csc: Add max width and height properties
+    - drm: xlnx: csc: Add max width and height dt properties
+    - dt-bindings: display: xlnx: Add max width and height as mandatory properties
+    - drm: xlnx: scaler: Add max width and height properties
+    - v4l: xilinx: scd: Fix video format configuration for YUV420
+    - media: v4l: Add YUV 10bit media bus format
+    - v4l: xilinx: vip: Add YUV 10bit media bus formats
+    - v4l: xilinx: vip: Add scaling and padding factor for XY10
+    - v4l: xilinx: vip: Use correct media bus code for RGB 10bit format
+    - v4l: xilinx: vpss-scaler: Use 10bit media bus codes
+    - v4l: xilinx: tpg: Use 10bit media bus codes
+    - v4l: xilinx: vpss-csc: Use 10bit media bus codes
+    - v4l: xilinx: scd: Enable 10 bit formats support for memory based IP
+    - v4l: xilinx: scd: Use correct threshold value
+    - v4l: xilinx: m2m: Add S_SELECTION and G_SELECTION ioctls
+    - v4l: xilinx: m2m: Use crop parameters set on output port
+    - drm: xlnx: zynqmp_disp: Skip the modeset for same fb
+    - v4l: xilinx: tpg: Dynamically modify TPG output format
+    - v4l: xilinx: sdirxss: Fix the media bus formats to 10bpc type
+    - ASoC: xlnx: change HDMI audio mclk
+    - v4l: xilinx: scd: Consolidate register definitions
+    - v4l: xilinx: scd: Consolidate structure definitions
+    - v4l: xilinx: scd: Make local functions static
+    - v4l: xilinx: scd: Reorder structure definitions
+    - v4l: xilinx: scd: Merge the V4L2 support in the main SCD driver
+    - v4l: xilinx: scd: Merge the main and V4L2 IRQ handlers
+    - v4l: xilinx: scd: Merge the DMA support in the main SCD driver
+    - v4l: xilinx: scd: Cleanup the DMA engine at remove() time
+    - v4l: xilinx: scd: Merge the main and DMA IRQ handlers
+    - v4l: xilinx: scd: Compile all SCD source files in a single module
+    - v4l: xilinx: scd: Refactor the xscd_device structure
+    - v4l: xilinx: scd: Allocate pads array statically
+    - v4l: xilinx: scd: Store channel registers address in iomem field
+    - v4l: xilinx: scd: Request IRQ after completing initialization
+    - v4l: xilinx: scd: Initialize DMA channels in xilinx-scenechange-dma.c
+    - v4l: xilinx: scd: Allocate all channels in one go
+    - v4l: xilinx: scd: Inline the xscd_dma_alloc_tx_descriptor() function
+    - v4l: xilinx: scd: Clean up #include statements
+    - v4l: xilinx: scd: Cleanup the xscd_dma_chan structure
+    - v4l: xilinx: scd: Rewrite core start/stop and interrupt handling
+    - v4l: xilinx: scd: Don't mark channel as disabled in .s_stream(0)
+    - uio: xilinx_ai_engine: Set the uio device as pdev driver data
+    - uio: xilinx_ai_engine: Unreference correct pdev
+    - dt-bindings: soc: xilinx: ai_engine: Add interrupts
+    - uio: xilinx_ai_engine: Enable the irq
+    - uio: xilinx_ai_engine: Simulate the irq if no hw irq is available
+    - dt-bindings: soc: xilinx: ai-engine-npi: Add the binding for AIE NPI
+    - uio: xilinx_ai_engine: Enable platform genirq driver
+    - drm: xlnx: pl_disp: Added plane atomic check function
+    - ASoC: xlnx: revert HDMI audio mclk mutliplier
+    - media: v4l2-ioctl: Use correct fourcc for YUV444 10bit format
+    - v4l: xilinx: vip: Fix stride calculation
+    - media: v4l: Add YUV444 12bit and 16bit media bus format
+    - media: v4l2-ioctl: Add YUV444 12bit and 16bit pixel formats
+    - v4l: xilinx: vip: Add YUV444 12bit and 16bit formats
+    - dt-bindings: display: xlnx: mixer: Updated compatible string
+    - drm: xlnx: mixer: Adding 16 layer support
+    - v4l: xilinx: m2m: Fix buftype for s_selection ioctl
+    - v4l: xilinx: dma: add input ioctls
+    - v4l: xilinx: dma: add v4l2_ctrl_handler
+    - v4l: xilinx: xcsi2rxss: Use external reset in a SLBF condition
+    - dt-bindings: media: xilinx: Add optional external reset for core reset
+    - v4l: xilinx: sdirxss: Make structures constant
+    - v4l: xilinx: sdirxss: Use clk_bulk_* apis
+    - v4l: xilinx: sdirxss: Replace single element array with variable
+    - v4l: xilinx: sdirxss: Add support to enumerate media bus formats
+    - v4l: xilinx: sdirxss: Clear processed interrupts only
+    - v4l: xilinx: sdirxss: Correct handling of combined lock/unlock interrupts
+    - v4l: xilinx: sdirxss: Fix code formatting and comments
+    - v4l: xilinx: sdirxss: Make functions static inline
+    - v4l: xilinx: sdirxss: Call xsdirx_streamflow_control() directly
+    - v4l: xilinx: sdirxss: Check for 10bpc in dt
+    - v4l: xilinx: sdirxss: Uninitialize the subsystem correctly
+    - v4l: xilinx: vpss-csc: Fix xcsc_set_format() for RBG 10 bpc
+    - v4l: xilinx: dma: Copy format resolution to crop rectangle
+    - v4l: xilinx: dma: Check subdev resolution against crop rectangle
+    - v4l: xilinx: dma: Add S_SELECTION and G_SELECTION ioctls
+    - v4l: xilinx: dma: Use crop rectangle to prepare dma descriptor
+    - drm: xlnx: mixer: Added bridge instance check in remove function
+    - uio: rename uio.c -> uio_core.c & unify into uio.ko
+    - dt-bindings: soc: xilinx: Correct ai_engine reg property
+    - drm: xlnx: zynqmp_dp: initialize delayed work before enable interrupts
+    - v4l: xilinx: dma: Don't set low latency capture mode on dma
+    - Revert "dma: xilinx: Release buffers before DMA transfer"
+    - v4l: xilinx: dma: Don't start DMA in STREAM_ON for low latency capture
+    - v4l: xilinx: dma: Perform early callback on queued buffers
+    - v4l: xilinx: dma: Add support to start DMA using s_ctrl
+    - media: v4l: Group Xilinx downstream formats
+    - v4l: xilinx: vip: Keep NV16 first in vip table
+    - v4l: xilinx: vip: Use the right media code for 422 16bit formats
+    - v4l: xilinx: scd: Enable configuration of scene change threshold
+    - v4l: xilinx: scd: Proper unregister from V4L2 framework
+    - Revert "Revert "dma: xilinx: Release buffers before DMA transfer""
+    - v4l: xilinx: dma: Use early callback mode for low latency capture
+    - v4l: xilinx: dma: Early dequeue first buffer for low latency capture
+    - v4l: xilinx: dma: Disable auto restart for low latency capture
+    - v4l: xilinx: scd: Fixed resolution switch issue
+    - v4l: xilinx: vpss-scaler: Add support for 4 ppc
+    - v4l: xilinx: dma: Attach s_ctrl to ctrl_handler instead of ioctl
+    - dt-bindings: display: xlnx: dsi: Add command mode support
+    - drm: xlnx: dsi: Add command mode support
+    - drm: xlnx: mixer: Add a delay for timing generation to be stable
+    - dt-bindings: display: xlnx: Add support for vpss ip version 2.2
+    - drm: xlnx: scaler: Add support for ip version 2.2
+    - dt-bindings: media: vpss-scaler: Add rev 2.2 to compatible string
+    - v4l: xilinx: vpss-scaler: Add support for ip version 2.2
+    - dma: xilinx: Disable low latency capture in file ops open
+    - v4l: xilinx: m2m: Fix crop support on capture port
+    - dma: xilinx: dpdma: alloc xilinx_dpdma_tx_desc using GFP_ATOMIC
+    - dmaengine: xilinx: dpdma: fix implicit fall-through statements
+    - drm: xlnx: sdi: Use the named IRQ when available
+    - v4l: xilinx: xcsi2rxss: Source pad has same format as sink pad
+    - v4l: xilinx: axis-switch: sink and source pad should have same value in
+      TDEST routing mode
+    - v4l: xilinx: xcsi2rxss: Set default active lanes to max
+    - drm: xlnx: drv: drop master only while releasing last master on a drm device
+    - drm: xlnx: zynqmp_disp: Perform additional checks for plane update
+    - v4l: xilinx: sdirxss: Add YUV444 10 bpc support
+    - firmware: zynqmp: Add Node IDs in xlnx-zynqmp.h
+    - watchdog: cadence: Do not show error in case of deferred probe
+    - watchdog: cadence: Skip printing pointer value
+    - OF: DT-Overlay configfs interface (v8)
+    - fpga: Add firmware store function
+    - fpga: mgr: Adopted Encrypted BitStream loading support for Xilinx zynqmp
+    - fpga: fpga-mgr: Add readback support
+    - fpga: zynqmp-fpga: Add support for pl configuration readback
+    - fpga: zynqmp-fpga: fix compile warning in fpga_mgr_register
+    - fpga: mgr: Update the status for fpga-manager
+    - fpga: zynqmp-fpga: Adds status interface
+    - fpga: Adopted Authenticated BitStream loading support for Xilinx
+    - mtd: rawnand: nand_micron: Do not over write driver's (read/write)_page()
+      hooks
+    - mtd: rawnand: arasan: Add on-die ecc support
+    - ARM: zynq: Add smcc node
+    - mtd: rawnand: pl353: Add driver for arm pl353 smc nand interface
+    - net: can: Limit CANFD brp to 2
+    - gpio: zynq: protect direction in/out with a spinlock
+    - dt-bindings: gpio: Add binding for Versal gpio
+    - devicetree-binding: Add pmc gpio node
+    - gpio: zynq: Add Versal support
+    - gpio: zynq: Disable the irq if it is not a wakeup source
+    - gpio: zynq: Add pmc gpio support
+    - gpio: zynq: Remove error prints in EPROBE_DEFER
+    - microblaze: Align comments with register usage
+    - microblaze: Fix message about compiled-in FDT location
+    - microblaze: Permit pcibios_set_master override
+    - microblaze: pci: Support generic Xilinx AXI PCIe Host Bridge IP driver
+    - ARM: zynq: use physical cpuid in zynq_slcr_cpu_stop/start
+    - dt-bindings: ARM: zynq: Add DT binding for eFuse controller
+    - ARM: zynq: Add support for Zynq-7000S devices
+    - ARM: zynq: Fix prefetch option
+    - zynq: slcr: Introduce new get_ocm_config()
+    - zynq: Add OCM driver
+    - Xilinx: ARM: Devcfg and SLCR drivers updated to support reconfiguration.
+    - arm: zynq: Suspend support
+    - xilinx: Documentation/devicetree - add description for "port-number"
+      property
+    - Bluetooth: hci_ll: Extend timeout between start and communication
+    - dt-binding: iio: Add optional label property
+    - iio: core: Add optional symbolic label to device attributes
+    - hvc: dcc: Add earlycon support
+    - tty: serial: of_serial: Do not allocate greater space than required
+    - dt-bindings: fpga: Add doc for the xilinx afi config driver
+    - fpga: Add xilinx AFI config driver
+    - dt-bindings: fpga: Add binding doc for the afi config driver
+    - fpga: zynq: Add AFI config driver
+    - dt-bindings: fpga: Add binding doc for versal fpga manager
+    - fpga: versal-fpga: Add versal fpga manager driver
+    - dt-bindings: misc: Add dt bindings for traffic generator
+    - trafgen: xilinx: add axi traffic generator driver
+    - trafgen: Document sysfs entries
+    - fpga: xilinx-pr-decoupler: Remove clk_get error message for probe defer
+    - fpga: fpga-bridge: Add manual set option via sysfs
+    - dt-bindings: Add doc for xilinx fclk
+    - staging: fclk: Enable pl clock with sysfs entry for set_rate
+    - i2c: cadence: Fix error printing in case of defer
+    - i2c: cadence: Fix power management order of operations
+    - i2c: cadence: Implement save restore
+    - i2c: cadence: Recover bus after controller reset
+    - i2c: cadence: Added slave support
+    - i2c: cadence: Fix wording in i2c-cadence driver
+    - i2c: cadence: Handling Slave monitor mode
+    - ARM: zynq: Add/Update/Sync DTs for xilinx platforms
+    - microblaze: defconfig: Disable EXT2 driver and Enable EXT3 & EXT4 drivers
+    - arm64: zynqmp: Use ethernet-phy as node name for ethernet phys
+    - arm64: zynqmp: Remove addition number in node name
+    - arm64: zynqmp: Fix address for tca6416_u97 chip on zcu104
+    - arm64: zynqmp: Turn comment to gpio-line-names
+    - arm64: zynqmp: Setup clock-output-names for si570 chips
+    - arm64: zynqmp: Fix the si570 clock frequency on zcu111
+    - arm64: zynqmp: Remove broken-cd from zcu100-revC
+    - arm64: zynqmp: Setup default number of chipselects for zcu100
+    - arm64: zynqmp: Enable iio-hwmon for ina226 on zcu100
+    - arm64: zynqmp: Enable iio-hwmon for ina226 on zcu111
+    - arm64: zynqmp: Add label property to all ina226 on zcu111
+    - arm64: zynqmp: Enable iio-hwmon for ina226 on zcu102
+    - arm64: zynqmp: Add label property to all ina226 on zcu102
+    - arm64: zynqmp: Enable iio-hwmon for ina226 on zcu106
+    - arm64: zynqmp: Add label property to all ina226 on zcu106
+    - dt-bindings: Add the binding doc for xilinx APM
+    - uio: uio_xilinx_apm: Add Xilinx AXI performance monitor driver
+    - i2c: xiic: Fix kerneldoc warnings
+    - i2c: xiic: Add timeout to the rx fifo wait loop
+    - i2c: xiic: defer the probe if clock is not found
+    - i2c: xiic: Fix the clocking across bind unbind
+    - tty: pl011: Add suspend resume support
+    - tty: pl011: Add support for configurable wordlength
+    - irqchip: gic: Add remoteproc changes to the driver
+    - arm: Add support for dynamic IPI allocation
+    - serial: uartps: Fix stuck ISR if RX disabled with non-empty FIFO
+    - serial: uartps: Prevent writes when the controller is disabled
+    - serial: uartps: Fix the ignore_status
+    - serial-uartlite: Change logic how console_port is setup
+    - serial-uartlite: Remove ULITE_NR_PORTS macro
+    - mmc: sdhci-of-arasan: Separate out clk related data to another structure
+    - dt-bindings: mmc: arasan: Update Documentation for the input clock
+    - mmc: sdhci-of-arasan: Add sampling clock for a phy to use
+    - dt-bindings: mmc: Add optional generic properties for mmc
+    - mmc: sdhci-of-arasan: Add support to set clock phase delays for SD
+    - firmware: xilinx: Add SDIO Tap Delay nodes
+    - dt-bindings: mmc: arasan: Document 'xlnx,zynqmp-8.9a' controller
+    - mmc: sdhci-of-arasan: Add support for ZynqMP Platform Tap Delays Setup
+    - firmware: xilinx: Add DLL reset support
+    - mmc: sdhci-of-arasan: Add support for DLL reset for ZynqMP platforms
+    - arm64: zynqmp: Add ZynqMP SDHCI compatible string
+    - sdhci: arasan: Remove quirk for broken base clock
+    - dt-bindings: dma: xilinx_frmbuf: Add support for 8 ppc
+    - dmaengine: xilinx: frmbuf: Add support for 8 ppc
+    - v4l: xilinx: sdirxss: Add support to modify GT clock
+    - dt-bindings: media: xilinx: csi2rxss: Add 4.1 compatible string
+    - v4l: xilinx: xcsi2rxss: Add v4.1 compatible string
+    - soc: xilinx: vcu: Add exported functions
+    - soc: xilinx: vcu: Provided API to get core clock
+    - soc: xilinx: vcu: Provided API to get number of cores
+    - soc: xilinx: vcu: Divisor calculation for MCU clock is updated.
+    - soc: xilinx: vcu: Optimize the VCU PLL calculation.
+    - dt-bindings: soc: xilinx: Update VCU bindings
+    - soc: xilinx: vcu: Move structure definition to header file
+    - soc: xilinx: vcu: Add VCU MFD core driver
+    - soc: xilinx: vcu: Use CCF to use clocks
+    - dt-bindings: soc: xilinx: Update VCU bindings for vcu reset pin
+    - soc: xilinx: vcu: Update vcu init/reset sequence
+    - dt-bindings: soc: xilinx: Update vcu compatible string in example
+    - i2c: cadence: Fix the driver in interrupt flurry case
+    - watchdog: of_xilinx_wdt: Add comment to spinlock
+    - watchdog: of_xilinx_wdt: Used BIT macro
+    - watchdog: of_xilinx_wdt: Used dev_dbg()
+    - watchdog: of_xilinx_wdt: Initialize watchdog via data structure
+    - watchdog: of_xilinx_wdt: Introduce wdttype enum for identification
+    - dt-bindings: watchdog: xilinx: Add binding for Versal watchdog
+    - watchdog: of_xilinx_wdt: Add Versal support
+    - watchdog: of_xilinx_wdt: Wire setting up timeout via module parameter/DT
+    - PCI: XDMA PL PCIe: Adding device tree binding for XDMA PL PCIe
+    - PCI: XDMA PL PCIe: Adding XDMA PL PCIe Root Port
+    - PCI: XDMA PL PCIe: Request host bridge window resources
+    - PCI: XDMA PL PCIe: Convert PCI scan API to pci_scan_root_bus_bridge()
+    - PCI: XDMA PL PCIe: Move to struct pci_host_bridge IRQ mapping functions
+    - PCI: XDMA PL PCIe: Remove unused platform data
+    - PCI: XDMA PL PCIe: Translate INTx range to hwirqs 0-3
+    - PCI: XDMA PL PCIe: Fix 64-bit MSI address programming
+    - PCI: XDMA PL PCIe: Program hwirq to MSI data
+    - PCI: XDMA PL PCIe: Fix number of MSI interrupts supported
+    - PCI: XDMA PL PCIe: Fix Multi MSI data programming
+    - PCI: XDMA PL PCIe: Add documentation for MSI DECODE mode.
+    - PCI: XDMA PL PCIe: Add support MSI DECODE mode
+    - PCI: XDMA PL PCIe: Fixing legacy interrupt handling bug
+    - pci: xdma: pl: Remove of_pci_get_host_bridge_resources
+    - pci: xdma: pl: Fix Multi MSI data
+    - pci: xdma: pl:: Remove unused variable
+    - pci: xdma: pl: Moving misc IRQ line registration to separate function
+    - pci: xdma: pl: Moving MSI IRQ lines registration to separate function
+    - pci: xdma: pl: Parse device tree based on compatible string
+    - dt-bindings: pci: xdma: Add device tree binding for Versal CPM
+    - pci: xdma: pl: Add support for Versal CPM Root Port driver
+    - PCI: XDMA: Remove unsupported error bits
+    - PCI: CPM: Adding support for versal specific errors
+    - PCI: XDMA PL: Move to PCI version of mask and unmask MSI IRQ
+    - drivers: clocksource: Use ttc driver as platform driver
+    - remoteproc: Add support for peek from remote and acking kick from remote
+    - remoteproc: sysfs: allow kick to pass small data
+    - remoteproc: returns message for peek remote kick function
+    - dt-bindings: Add Zynq remoteproc binding
+    - remoteproc: Add support for AMP on Zynq platform
+    - dt-bindings: Add documentation for ZynqMP R5 rproc bindings
+    - remoteproc: Add initial zynqmp R5 remoteproc driver
+    - i2c: mux: pca954x: write to mux channel always
+    - dt-bindings: Add binding for IDT 8T49N24x UFT
+    - clk: Add ccf driver for IDT 8T49N24x UFT
+    - spi: Add Zynq QSPI controller driver
+    - mtd: spi-nor: Add dual parallel and stacked support for Zynq QSPI controller
+    - mtd: spi-nor: Add 4byte support for Zynq QSPI controller
+    - dt-bindings: spi: Update dt bindings document
+    - spi: Update ZynqMP and Versal QSPI controller driver
+    - mtd: spi-nor: Add support for ZynqMP and Versal QSPI Controller
+    - dt-bindings: mtd: Update dt binding documentation
+    - spi: Add multi-die info in spi_device structure
+    - mtd: spi-nor: Add multi-die read support
+    - mtd: spi-nor: Update flags for serial NOR flash devices
+    - dt-binding: Added versal-ospi compatible string
+    - mtd: cadence-quadspi: Added xilinx compatible string
+    - mtd: cadence-quadspi: Added support for DMA read
+    - mtd: cadence-quadspi: Added support STIG write
+    - mtd: spi-nor: Added support for OCTAL write
+    - mtd: spi-nor: Add entry for mt35xu01g flash
+    - dt-bindings: mtd: Document "reset-gpios" property
+    - mtd: cadence-quadspi: Added support for OSPI device reset
+    - mtd: cadence-quadspi: Added support for DDR PHY mode
+    - dt-bindings: mmc: arasan: Document 'xlnx,versal-8.9a' controller
+    - sdhci: arasan: Add support for Versal Tap Delays
+    - fpga: support loading from a pre-allocated buffer
+    - staging: dt-bindings: xlnxsync: Add initial bindings for Xilinx Synchronizer
+    - staging: xlnxsync: Add driver for Xilinx Synchronizer
+    - net: axienet: In kconfig remove arch dependency for axi_emac
+    - net: emaclite: Fix coding style
+    - net: emaclite: In kconfig remove arch dependency
+    - net: emaclite: Fix arm64 compilation warnings
+    - dt-bindings: nvmem: Added efuse nodes
+    - nvmem: zynqmp: Added support to access efuse
+    - dt-bindings: Add device tree binding for xilinx mpeg2tsmux driver
+    - staging: xlnx_tsmux: Initial version of xlnx mpeg2tsmux driver
+    - nvmem: zynqmp: Added zynqmp nvmem get_silicon_version()
+    - phy: zynqmp: Add dt bindings for ZynqMP PHY
+    - phy: zynqmp: Add phy driver for xilinx zynqmp phy core
+    - usb: gadget: udc-xilinx: Add clock support
+    - usb: xilinx: Add suspend resume support
+    - usb: phy: Add platform driver support for ULPI phys
+    - usb: gadget: udc: udc-xilinx: Add identifier to read_fn function arg
+    - usb: gadget: udc: udc-xilinx: Resolve compilation warnings
+    - usb: host: ehci-xilinx: modified driver to resolve formatting warnings
+    - usb: host: ehci-xilinx: Resolve kernel-doc Warnings
+    - usb: host: xhci: plat: add support for otg_set_host() call
+    - usb: host: xhci: add support for Light Reset for DWC3 DRD
+    - usb: xhci: Add workaround for fixing ep stream ring hang issue
+    - usb: uas: Add workaround for DATA IN urb's returned with status -EAGAIN
+    - uas: Add US_FL_NO_ATA_1X for linux tcm_usb_gadget
+    - usb: gadget: f_tcm: adjust write length with max packet size
+    - usb: gadget: f_tcm: comp_descriptor workaround during SS gadget
+    - usb: gadget: f_tcm: queue multiple commands request
+    - usb: gadget: f_tcm: add TARGET_SCF_ACK_KREF flag in BOT
+    - usb: gadget: f_tcm: support to set maxburst through configfs
+    - usb: function: f_tcm: Add support for getting alt interface number
+    - usb: dwc3: gadget: add support for OTG in gadget framework
+    - usb: dwc3: hibernation: fix scratch buffer allocation
+    - usb: dwc3: correct ignoring hibernation event
+    - dwc3: Add support for setting USB control registers as phy platform data
+    - dwc3: core: Enable GUCTL1 chicken bit 10 for fixing crc error after resume
+      bug
+    - dwc3: core: Enable GUCTL1 chicken bit 9 for correcting Inter Packet
+      Delay(IPD)
+    - usb: Add quirk for enabling workaround for BULK IN streams
+    - usb: dwc3: Add support for clock disabling during suspend
+    - usb: dwc3: Add support for removing vbus when suspended
+    - usb: dwc3: of-simple: Enable CCI support in dwc3 driver
+    - usb: dwc3: Correct errors when dwc3 loaded as module
+    - usb: dwc3: enable transfer complete event for stream endpoint
+    - usb: dwc3: Add code for supporting entering into D3 state during suspend
+    - usb: xhci-plat: Add remote wakeup support
+    - usb: dwc3: update GFLADJ_REFCLK_FLADJ in dwc3_frame_length_adjustment
+    - usb: dwc3: don't setup event buffers when operating in device mode
+    - usb: dwc3: Fix the logic for allocating and setting scratchpad buffers
+    - usb: dwc3: Add hibernation support when operating as gadget
+    - usb: dwc3: add support for enabling/disabling hibernation dynamically
+    - usb: dwc3: fix the logic for setting GBLHIBERNATIONEN in GCTL
+    - usb: dwc3: don't wait for end transfer to finish for isoc endpoints
+    - usb: xhci: don't clean shared_hcd when otg is enabled
+    - usb: gadget: configfs: Add support for setting maximum supported speed
+    - usb: dwc3: Fix missing peripheral irq error message
+    - usb: dwc3: Fix the broken suspend/resume functionality in dwc3
+    - usb: gadget: uvc_video: unlock before submitting a request to ep
+    - usb: dwc3: Correct usb dma mask for making SMMU work in device mode
+    - usb: xhci: wait for atleast 1ms after exiting U3
+    - usb: dwc3: gadget: ISOC transfers should be stopped before starting a
+      transfer
+    - usb: dwc3: otg: fix broken OTG HNP feature
+    - usb: dwc3: Check for IOC/LST bit in both event->status and TRB->ctrl fields
+    - usb: dwc3: gadget: Don't kick transfer if LST or SHORT bits are set
+    - usb: dwc3: Add DRD support for versal
+    - usb: dwc3: core: use first_trb_index instead of start_slot
+    - usb: host: xhci: Add xhci_hcd to xhci_ring for use in
+      stream_timeout_function
+    - usb: dwc3: gadget: get irq number for hibernation interrupts
+    - usb: dwc3: gadget: Add new platform_data.h file
+    - usb: gadget: send usb_gadget as an argument in get_config_params
+    - usb: dwc3: Disabling usb3 phy suspend checks into a separate function
+    - usb: dwc3: Add support for masking phy reset signal
+    - usb: dwc3: otg: Update Kconfig and Makefile for enabling OTG
+    - usb: dwc3: Implement stream transfer timeout
+    - usb: dwc3: otg: add support for OTG in DWC3 host driver
+    - usb: dwc3: retain resource index for unforced stops
+    - mtd: spi-nor: Updated spi_nor_write_ear() api with dual parallel and stacked
+      support.
+    - dt-bindings: spi-xilinx: Updated devicetree bindings for spi-xilinx
+    - mtd: spi-nor: Added axi-qspi support in spi-nor framework
+    - spi: spi-xilinx: Updated axi-qspi controller driver
+    - Revert "net: axienet: document axistream-connected attribute"
+    - Revert "net: axienet: make use of axistream-connected attribute optional"
+    - net: axienet: Add NAPI support
+    - dt-bindings: net: Add bindings documentation for Xilinx PCS/PMA PHY
+    - net: phy: Add support for xilinx SGMII and 1000BASE-X phys
+    - net: axienet: Use barriers at relevant places
+    - net: axienet: Fix lost wake-up scenario in xmit
+    - dt-bindings: net: axienet: Add binding for 2.5G, 10G and usxgmii mac
+      variants
+    - dt-bindings: net: axienet: Update binding doc for 10G/25G MAC 1588
+    - dt-bindings: net: axienet: Add clock support
+    - dt-bindings: net: axienet: Add support for mcdma
+    - net: axienet: Add support for non-processor mode
+    - net: axienet: Add support for config structure
+    - net: axienet: Add support for 2.5G MAC
+    - net: axienet: Add support for 10G MAC
+    - net: axienet: Add support for 10G/25G MAC
+    - net: axienet: Add support for 1588
+    - net: axienet: Add support for ZynqMP
+    - net: axienet: Adding highmem support
+    - net: axienet: Remove unnecessary phy defines
+    - net: axienet: Allow unaligned transfers
+    - net: axienet: Use ether_addr_copy()
+    - net: axienet: Fix coding style issues
+    - net: axienet: Fix issues when DRE is not enabled in the h/w
+    - net: axienet: Add clock support
+    - net: axienet: added multichannel DMA support
+    - net: xilinx: axiethernet: Add USXGMII support
+    - net: xilinx: axiethernet: Check for queue full in transmit path
+    - net: xilinx: axiethernet: Fix axiethernet register description
+    - net: xilinx: axiethernet: Fix crash in axienet_recv
+    - Revert "net: axienet: convert to phylink API"
+    - v4l: xilinx: vpss-scaler: Improve quality by adding more coefficients
+    - drm: xlnx: scaler: Improve quality by adding more coefficients
+    - firmware: zynqmp: Add support for secure_image
+    - zynqmp: firmware: Adds a driver for loading secure partition from Linux
+    - net: macb: Add PCS caps mask and enable autoneg
+    - net: macb: add support for mdio phy nodes
+    - dt-bindings: net: macb: update for partial store and forward
+    - net: macb: Add support for partial store and forward
+    - net: macb: PTP fixes
+    - net: macb: Add provision for queue tie off
+    - net: macb: Use WOL via ARP
+    - net: macb: Initialize bool to false instead of zero
+    - net: macb: Increment rx bd head after allocating skb and buffer
+    - net: macb: Process tx timestamp only on ptp packets
+    - net: macb: Disable macb pad and fcs for fragmented packets
+    - net: macb: Optimize reading HW timestamp
+    - dt-bindings: net: macb: Add GEM versal compatible string
+    - net: macb: Update tsu clk usage in runtime suspend/resume for Versal
+    - net: macb: Use queue disable instead of tieoff in Versal suspend
+    - net: macb: Handle phy reset for PCS PMA IP
+    - net: macb: Increase halt timeout to accommodate 10Mbps link
+    - net: macb: Reset TX when TX halt times out
+    - net: macb: Update type of "mac" from char to u8
+    - net: macb: Add a NULL check on desc_ptp
+    - net: macb: Remove unnecessary check
+    - net: macb: Reorder probe and fix exit path
+    - dt-bindings: pmbus: Add tps544 bindings
+    - pmbus: Add new tps544 power regulator driver
+    - net: macb: Remove unnecessary alignment check for TSO
+    - net: macb: Limit maximum GEM TX length in TSO
+    - crypto: Adds user space interface for ALG_SET_KEY_TYPE
+    - dt-bindings: crypto: zynqmp-aes documentation
+    - crypto: zynqmp-aes: Adds zynqmp-aes driver
+    - arm64: zynqmp: Added device tree node for zynqmp-aes driver
+    - dt-bindings: crypto: Added binding docs for Xilinx ZynqMP SHA3 H/W
+      accelerator
+    - crypto: zynqmp-sha: Adopted SHA3 support for ZynqMP Soc
+    - arm64: zynqmp: Add Xilinx SHA3 node
+    - dt-bindings: crypto: Added binding docs for Xilinx ZynqMP RSA H/W
+      accelerator
+    - crypto: zynqmp-rsa: Adopted RSA support for ZynqMP SoC
+    - arm64: zynqmp: Add support for ZynqMP RSA H/W accelerator
+    - phy: dp83867: Add support for SGMII
+    - clk: zynqmp: Fix power of two divider calculation
+    - drm: xlnx: zynqmp: Use ZynqMP phy API
+    - include: dt-bindings: Add mscc-vsc8531 RGMII clock delay definitions
+    - phy: mscc: Use common RGMII delay definitions
+    - dt-bindings: mscc: Add RGMII RX and TX delay tuning
+    - phy: mscc: Add support for VSC8531_02 with RGMII tuning
+    - dmaengine: xilinx_dma: Reset DMA channel in dma_terminate_all
+    - dmaengine: xilinx_dma: Extend dma_config structure to store max channel
+      count
+    - dmaengine: xilinx_dma: In dma channel probe fix node order dependency
+    - dmaengine: xilinx: axidmatest: First enable receive path
+    - dt-bindings: clock: Adding si5324 bindings
+    - clk: Adding Silicon labs si5324 clock driver
+    - edac: add support for ARM PL310 L2 cache parity
+    - dt-bindings: edac: Add bindings for ZynqMP OCM Controller
+    - edac: zynqmp: Add EDAC support for ZynqMP OCM Controller
+    - dt-bindings: edac: Add bindings for cortex_arm64
+    - EDAC: Add ARM64 EDAC
+    - edac: Add documentation for cortexa53 edac sysfs
+    - edac: Add sysfs entries for cortex arm64
+    - arm64: zynqmp: Change Kconfig dependency for cortexa53 edac
+    - irqchip: xilinx: Add support for multiple instances
+    - tty: pl011: Add support for parity configuration
+    - drivers: ata: Add CCI support for SATA if CCI is enabled
+    - samples: xilinx_apm: Add sample application for xilinx_apm
+    - microblaze: Wire CMA allocator
+    - microblaze: Kernel parameters should be parsed earlier
+    - usb: gadget: udc-xilinx: Fix xudc_stop() kernel-doc format
+    - xilinx: Update MAINTAINERS fragment
+    - dt-bindings: display: xlnx: Added interrupt-names
+    - staging: xroeframer: Add README to describe roe framer
+    - staging: xroeframer: Add devicetree binding
+    - staging: xroeframer: Add register map header files
+    - staging: xroeframer: Add support for radio over ethernet frame
+    - staging: xroeframer: main sysfs source file commit
+    - staging: xroeframer: IPv4 sysfs source file commit
+    - staging: xroeframer: IPv6 sysfs source file commit
+    - staging: xroeframer: UDP sysfs source file commit
+    - staging: xroeframer: add support for multi-port Ethernet
+    - staging: xroeframer: add sysfs entries for "stats" registers
+    - staging: xroeframer: extending sysfs entries for "stats" registers
+    - staging: xroeframer: removing /dev/ entries
+    - staging: xroetrafficgen: initial commit of roe traffic generator driver
+    - mtd: Expand the ecc placement locations to 1260
+    - dt-bindings: power: Add versal power domain bindings
+    - docs: misc: xilinx_sdfec: Actually add documentation
+    - dt-bindings: pinctrl: Add DT binding doc for new pin control driver
+    - pinctrl: zynqmp: Add pin controller driver
+    - dt-bindings: Add Xilinx AMS binding documentation
+    - iio: adc: Add Xilinx AMS driver
+    - dt-bindings: iio: xadc: Add bindings for ultrascale sysmon
+    - iio: xadc: add support for ultrascale sysmon
+    - iio: xadc: fix for extended name remains same issue
+    - iio: adc: Fix checkpatch warning
+    - PCI: ZYNQMP EP driver: Adding support for ZynqMP ep driver
+    - PCI: ZYNQMP EP client driver: Adding support for ZynqMP dma test client
+    - dt-bindings: pci: ZYNQMP PS PCIe Driver Root DMA dt bindings
+    - PCI: ZYNQMP EP driver: Adding Root DMA support
+    - dt-bindings: irqchip: Add Xilinx Interrupt Controller bindings
+    - dt-bindings: misc: Add documentation for jesd204b
+    - misc: jesd204b: Add driver for Xilinx jesd204b
+    - dt-bindings: misc: Add bindings for JESD phy
+    - misc: jesd204b driver support
+    - mtd: spi-nor: update ptr pointer after spi_nor_read_data
+    - usb: chipidea: Add support for VBUS control with PHY
+    - usb: chipidea: Use usb2 phy for Zynq platform
+    - usb: chipidea: Check usb_phy exists before using it
+    - fpga: zynq: Remove clk_get error message for probe defer
+    - dt-bindings: serial: Added documentation for xilinx axi Uartlite
+    - dt-bindings: video: Add device tree bindings for xilinx axi tft
+    - mtd: fixing CFI for Numonyx CFI bug
+    - spi: zynqmp: Fix kerneldoc warnings
+    - spi: zynqmp: fix style issues from checkpatch
+    - spi: spi-zynqmp-gqspi: Resolved slab-out-of-bounds bug
+    - PCI: XDMA PL PCIe: Enable XDMA PL PCIe for Microblaze
+    - asm-generic: Make msi.h a mandatory include/asm header
+    - asm-generic: Make dma-contiguous.h a mandatory include/asm header
+    - microblaze: Swap location of bss and INIT_RAM_FS
+    - microblaze: Change TLB mapping and free space allocation
+    - microblaze: Fix TLB mapping
+    - dt-bindings: Update binding for pinctrl in arasan SD driver
+    - mmc: arasan: Add pinctrl support to the driver
+    - dt-bindings: usb: Add clock support for udc-xilinx
+    - mtd: spi-nor: Fix compilation warnings
+    - mtd: spi-nor: Fix the issue in checking 4Byte opcode support in
+      spi/qspi/ospi controller
+    - mtd: spi-nor: Remove unwanted spi-nor framework changes
+    - dt-bindings: Add devicetree documentation for TSN
+    - net: xilinx: Add support for PL TSN IP features
+    - dt-bindings: Add devicetree documentation for ep
+    - net: xilinx: Add support for PL TSN endpoint interface
+    - net: xilinx: Add Qci support to the PL TSN IP driver
+    - net: xilinx: Add Support for CB/FRER feature of PL TSN IP
+    - net: xilinx: Add support for Qbu/br feature of PL TSN IP
+    - firmware: xilinx: Add OSPI MUX selection support
+    - mtd: cadence-quadspi: Add support for register writes with address
+    - mtd: cadence-quadspi: Add support to switch between DMA and NON-DMA
+    - Revert "mtd: cadence-quadspi: Added support STIG write"
+    - mtd: cadence-quadspi: Add support for odd byte count read/write in DDR mode
+    - mtd: cadence-quadspi: Fix the issue in unaligned byte count read
+    - gpio: xilinx: Add clock adaptation support
+    - gpio: xilinx: Add irq support to the driver
+    - staging: xlnx_tsmux: Add stream table update logic
+    - media: v4l2-ioctl: Add description for new pixel formats
+    - mtd: spi-nor: Fix kernel crash in case of spi flash
+    - dt-bindings: PCI: Xilinx NWL PCIe: Add a clock specifier
+    - PCI: xilinx-nwl: Enable the clock through CCF
+    - arm64: zynqmp: Do not duplicate flash partition label property
+    - ARM: dts: zynq: enablement of coresight topology
+    - ARM: dts: Sync address/size-cells with the rest of zynq-7000
+    - arm64: zynqmp: Fix GIC compatible property
+    - dt-bindings: xilinx: Document new evaluation boards
+    - dt-bindings: pinctrl: Convert generic pin mux and config properties to
+      schema
+    - drivers: clk: Fix invalid clock name queries
+    - drivers: soc: xilinx: fix build failure due to missing COMMON_CLK dependency
+    - mmc: sdhci-of-arasan: Modified SD default speed to 19MHz for ZynqMP
+    - mmc: sdhci-of-arasan: Add "SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12" quirk.
+    - mmc: sdhci-of-arasan: Skip Auto tuning for DDR50 mode in ZynqMP platform
+    - ARM: zynq: Fix addresses in partition definitions
+    - mtd: spi-nor: Added support for sst26vf016b spi flash
+    - clk: zynqmp: Update CLK_FRAC support as per upstream
+    - rtc: zynqmp: Add calibration set and get support
+    - clk: zynqmp: Sync divider.c with upstream'ed version
+    - clk: zynqmp: Fix divider2 calculation
+    - microblaze: Convert headers to SPDX license
+    - microblaze: Fix unistd_32.h generation format
+    - microblaze: Fix _reset() function
+    - microblaze: Add ID for Microblaze v11
+    - microblaze: Remove architecture tlb.h and use generic one
+    - microblaze: Remove early printk setup
+    - microblaze: Remove empty headers
+    - microblaze: Define microblaze barrier
+    - microblaze: Add missing irqflags.h header
+    - microblaze: Remove unused boot_cpuid variable
+    - microblaze: Define percpu sestion in linker file
+    - microblaze: timer: Don't use cpu timer setting
+    - microblaze: timer: Separate clocksource timer from clockevent one
+    - microblaze: timer: Pass timer freq via parameter
+    - microblaze: timer: Squash clocksource code together
+    - microblaze: timer: Covert timer to use cpu hotplug
+    - microblaze: timer: Move irq code to clockevent function
+    - microblaze: timer: Create per cpu clockevent device
+    - microblaze: timer: Remove global variables
+    - microblaze: timer: Make sure that clockevent timer is initialized properly
+    - microblaze: timer: Group clockevent setting together
+    - microblaze: timer: Detect cpu_id from DT
+    - microblaze: timer: Change timer initialization setting
+    - microblaze: timer: Make timer SMP aware
+    - microblaze: Define SMP safe bit operations
+    - microblaze: Make cpuinfo structure SMP aware
+    - microblaze: Use asm generic cmpxchg.h for !SMP case
+    - microblaze: Add SMP implementation of xchg and cmpxchg
+    - irqchip: xilinx: Make per cpu primary controller entries
+    - irqchip: xilinx: Fill error code when irq domain registration fails
+    - irqchip: xilinx: Enable generic irq multi handler
+    - irqchip: xilinx: Use handle_domain_irq()
+    - irqchip: xilinx: Move early initialization to own function
+    - irqchip: xilinx: Add support for sw interrupts
+    - irqchip: xilinx: Support only LE/BE irqc by the same driver
+    - irqchip: xilinx: Rename root_domain just to domain
+    - irqchip: xilinx: Add support for cpu hotplug
+    - irqchip: xilinx: Add support for Microblaze SMP
+    - microblaze: Remove disabling IRQ while pte_update() run
+    - microblaze: Implement architecture spinlock
+    - microblaze: Do atomic operations by using exclusive
+    - microblaze: Add sync to tlb operations
+    - microblaze: Prepare entry.S for SMP implementation
+    - microblaze: Rework mmu context management to prepare
+    - microblaze: Enable experimental SMP functionality
+    - Revert "mtd: rawnand: nand_micron: Do not over write driver's
+      (read/write)_page() hooks"
+    - mtd: rawnand: pl353: Fix column and row address calculation
+    - mtd: rawnand: pl353: Increase the data in/out lengths
+    - mtd: rawnand: pl353: Add new pattern to support write only
+    - i2c: xiic: Fix Tx Interrupt path for grouped messages
+    - i2c: xiic: Add standard mode support for > 255 byte read transfers
+    - i2c: xiic: Fix coding style issues
+    - mtd: cadence-quadspi: Added support for master DLL mode
+    - mtd:cadence-quadspi: Added periodic Tuning support for RX
+    - mtd: cadence-quadspi: Fix the issues in DMA intr disable
+    - clk: zynqmp: Fix missing max_div description in kernel-doc format
+    - v4l: xilinx: multi-scaler: suppress info prints in vidioc_try_fmt API
+    - staging: xlnxsync: Optimize the driver for multi-channel use-cases
+    - v4l: xilinx: sdirxss: Add the missing timings
+    - net: macb: Enable WOL capability in probe
+    - mtd: cadence-quadspi: Fixed compilation warnings
+    - mtd: spi-nor: Flash devices with quad mode support added.
+    - drm/fb_helper: Enable drm_leak_fbdev_smem by default for zynqmp
+    - dt-bindings: display: xlnx: mixer: Add rev 5.0 to compatible string
+    - drm: xlnx: mixer: Add support to update the color space conversion
+      coefficients
+    - sound: soc: xilinx: Use unique dai link per device
+    - i2c: xiic: Enter standard mode only for > 255 byte read transfers
+    - staging: xlnx_tsmux: replace dma_zalloc_coherent API with dma_alloc_coherent
+    - dma: xilinx: Replace dma_zalloc_coherent API with dma_alloc_coherent
+    - v4l: xilinx: sdirxss: Fix returning error on stream off
+    - dt-bindings: media: xilinx: csi2rxss: Add 5.0 compatible string
+    - v4l: xilinx: xcsi2rxss: Move DPHY offset to 4K instead of 64K
+    - v4l: xilinx: dma: Prevent divide by zero error
+    - clk: zynqmp: Fix CLK_FRAC bit index
+    - i2c: xiic: Correct the datatype for rx_watermark
+    - i2c: xiic: Fix Rx and Tx paths in standard mode repeated start
+    - clk: clock-wizard: Remove a unnessary type cast
+    - v4l: xilinx: sdirxss: Fix IP reset on gt clock switch in 12G mode
+    - dt: bindings: media: xilinx: sdirxss : Add GT reset gpio handle
+    - v4l: xilinx: sdirxss: Add support for optional gt reset gpio
+    - dt: bindings: media: xilinx: sdirxss : Add bit depth optional property
+    - v4l: xilinx: sdirxss: Add new 10/12 bit support
+    - v4l: xilinx: sdirxss: Add support for ST2081-10 Mode 2 in 6G mode
+    - v4l: xilinx: xsdirxss: Fix format height for interlaced and pSF mode
+    - v4l: xilinx: vipp: move xvip_entity_start_stop() to xilinx-vipp
+    - v4l: xilinx: vipp: use async list for start and stop
+    - v4l: xilinx: vipp: do enabling in the dependency check
+    - v4l: xilinx: vipp: remove a loop for graph start / stop
+    - v4l: xilinx: vipp: Change xvip_entity_start/stop to take graph entity
+    - v4l: xilinx: vipp: Remove set streaming on subdev
+    - clk: idt: Fix i2cwritebulk() failure
+    - dt-bindings: firmware: ixp4xx: Drop redundant minItems/maxItems
+    - dt-bindings: interrupt-controller: arm,gic-v3: Add missing type to
+      interrupt-partition-* nodes
+    - dt-bindings: bus: Drop empty compatible string in example
+    - mtd: spi-nor: Fix warnings
+    - drm: xlnx: bridge: make xlnx_bridge_set_timing() static inline
+    - pinctrl: zynqmp: use module_platform_driver to simplify the code
+    - pinctrl: zynq: use module_platform_driver to simplify the code
+    - usb: dwc3: when enters in d3 state
+    - dt-bindings: versal: Add new PM_DEV_AI and PM_DEV_GPIO_PMC macros
+    - irqchip: xilinx: Change level for cpu-id warning
+    - mtd: cadence-quadspi: Fix the issues in Rx Periodic tuning
+    - drm/i2c: adv7511: add missing include to drm/drm_probe_helper.h
+    - drm: xlnx: fix some typos in the Kconfig help texts
+    - phy: zynqmp: check the config correctly
+    - misc: xilinx_flex: Fix the lock definitions
+    - staging: apf: Make the APF config as a boolean state
+    - serial: uartps: Remove unconditional wait inside set_termios
+    - serial: uartps: Add TACTIVE check in cdns_uart_tx_empty function
+    - dt-bindings: Add versal clocking wizard
+    - clocking-wizard: Add versal clocking wizard support
+    - dt-bindings: Fix the apm binding warnings
+    - remoteproc: zynqmp_r5: Add explicit nodes for vrings
+    - ASoC: xlnx: Fixed I2S sound card registration issue
+    - v4l: xilinx: multi-scaler: fix a printk format specifier
+    - spi: spi-mem: Modify update_stripe api to handle different commands with
+      same opcode value
+    - spi: spi-zynqmp-gqspi: Update driver to write appropriate dummy cycles as
+      per the tx_buswidth
+    - Revert "PCI: ZYNQMP EP driver: Adding Root DMA support"
+    - PCI: ZYNQMP EP driver: Adding Root DMA support
+    - fpga: versal: Use 32-bit DMA addressing
+    - usb: dwc3: otg: fix the function call used to get otg descriptor
+    - usb: dwc3: otg: remove otg static export warning
+    - remoteproc: zynq: Add explicit nodes for vrings
+    - clk: fixed-factor: Don't register fixed factor clk until parent clk is
+      registered
+    - usb: dwc3: Enable clock when USB resume occurs
+    - mtd: spi-nor: Fix page size calculation
+    - drm: xlnx: pl_disp: make the incoming interlaced fields in order
+    - serial: uartps: Wait for tx_empty in console setup
+    - serial: uartps: Use cdns_uart_tx_empty in console_write
+    - gpio: zynq: use module_platform_driver to simplify the code
+    - PCI: xilinx-nwl: Fix coding style violations
+    - Revert "net: phy: ensure phylib state machine is stopped after calling
+      phy_stop"
+    - Revert "net: phy: call state machine synchronously in phy_stop"
+    - dt-bindings: gpio: xilinx: Update binding to reflect changes
+    - gpio: xilinx: Use xilinx tested gpio driver
+    - dt-bindings: net: Add binding documentation for axi emaclite
+    - dt-bindings: usb: dwc3: Update binding to reflect latest state
+    - dt-bindings: udc-xilinx: Fix coding style in binding doc
+    - dt-bindings: usb: host: ehci-xilinx: Add binding doc
+    - arm64: zynqmp: Add/Update/Sync DTs for xilinx platforms
+    - ARM: xilinx: Add zynq defconfig
+    - arm64: xilinx: Add defconfig fragments
+    - xilinx: Add a github template telling people to not use pull requests there
+    - arm64: zynqmp: Fix irps5401 device nodes
+    - Revert "i2c: cadence: Fix the hold bit setting"
+    - tty: xilinx_uartps: Add the id to the console
+    - xilinx: versal: Enable Xilinx soft interrupt controller
+    - dma: zynqmp_dma: Initialize descriptor list after freeing during reset
+    - v4l: xilinx: csi: Fix the uapi header license
+    - v4l: xilinx: sdi: Fix the uapi header license
+    - v4l: xilinx: hls: Fix the uapi header license
+    - v4l: xilinx: events: Fix the uapi header license
+    - staging: xlnx_tsmux: Fix the uapi header license
+    - staging: xlnxsync: Fix the uapi header license
+    - xilinx: Disable strict devmem access control
+    - arm64: zynqmp: Enable IRPS5401 sensor
+    - mtd: spi-nor: Add support for macronix qspi flash
+    - arm64: xilinx: Enable i2c slave functionality
+    - mtd: spi-nor: Fix spi_nor_read for multi die flash connected in dual
+      parallel mode
+    - mtd: spi-nor: Add support for ISSI serial nor flashes
+    - mtd: cadence-quadspi: Added support for GD25LX256E
+    - clk: zynqmp: Handle divider specific read only flag
+    - mtd: spi-nor: Add 4byte opcode support for Macronix flash parts
+    - mtd: cadence-quadspi: Added support for is25wx256
+    - Revert "clk: fixed-factor: Don't register fixed factor clk until parent clk
+      is registered"
+    - dmaengine: xilinx: axidmatest: Fix variable length array usage
+    - dmaengine: xilinx: axidmatest: In init_srcs remove unnecessary buffer
+      increment
+    - drm: xlnx: pl_disp: fix missing xlnx_crtc_unregister
+    - drm: xlnx: fb: Guard with CONFIG_DRM_FBDEV_EMULATION
+    - dmaengine: xilinx_dma: use readl_poll_timeout_atomic variant
+    - v4l: xilinx: tpg: Don't read version if HLS IP
+    - v4l: xilinx: dma: Add control handler to v4l2 device
+    - spi-xilinx.c: correct multibyte writes
+    - net: xilinx: axiethernet: Fix swiotlb buffer full error
+    - soc: xilinx: Call InitFinalize from late_initcall_sync instead of probe
+    - dt-bindings: Fix paths in schema $id fields
+    - soc: xilinx: Fix error code in zynqmp_pm_probe()
+    - dmaengine: xilinx_dma: Add missing check for empty list
+    - dmaengine: xilinx: add mcdma reference in axidmatest documentation
+    - mtd: cadence-quadspi: Added support for Stacked mode
+    - dt-binding: soc: xilinx: ai-engine: Add new AI engine binding
+    - misc: ai-engine: Move AI engine reg access to kernel
+    - dt-binding: soc: xilinx: ai-engine: Add FPGA bridge for AI engine partition
+    - misc: ai-engine: Add FPGA bridge to AI engine partition
+    - arm64: xilinx: Enable Xilinx AI engine misc driver
+    - ARM: zynq: Fix spurious BUG with old DT
+    - misc: ai-engine: change driver name
+    - media: v4l: Add HDR support through compound controls
+    - drm: Add generic HDR support
+    - v4l: xilinx: sdirxss: Add HFR support
+    - xilinx: versal: Enable 48bit virtual address space size
+    - xilinx: configs: Setup maximum number of CPUs in defconfigs
+    - firmware: xilinx: Add support for GET_LAST_RESET_REASON IOCTL
+    - xilinx: firmware: Add sysfs to get last reset reason
+    - i2c: cadence: Handle transfer_size rollover
+    - i2c: cadence: Clear HOLD bit at correct time in Rx path
+    - clk: zynqmp: Use firmware specific common clock flags
+    - clk: zynqmp: Use firmware specific divider clock flags
+    - clk: zynqmp: Use firmware specific mux clock flags
+    - clk: zynqmp: Add missing checking of eemi_ops
+    - mtd: spi-nor: Fix wrong cr value in write_sr_modify_protection
+    - usb: dwc3: use PROPERTY_ENTRY_BOOL to initialize property entries
+    - misc: jesd204b: Remove unused function
+    - spi: spi-cadence: Fix mixed_enum_type coverity warning
+    - spi: spi-cadence: Fix uninit_use coverity warning
+    - clk: zynqmp: Map ZYNQMP_CLK_SET_RATE_GATE with CCF
+    - dt-binding: soc: xilinx: ai-engine: Include SHIM row in partition
+    - misc: xilinx-ai-engine: Update AI engine partition request parameter
+    - misc: ai-engine: Use the return value of mutex_lock_interruptible()
+    - misc: ai-engine: use correct printk formats
+    - misc: xilinx-ai-engine: export AI engine program and data memory to
+      userspace
+    - mtd: cadence-quadspi: Fixed UNUSED_VALUE warning
+    - mmc: host: sdhci-of-arasan: fix timings allocation code
+    - Revert "tty: xilinx_uartps: Fix missing id assignment to the console"
+    - spi: spi-xilinx: Check return value of of_property_read_u32
+    - spi: spi-xilinx: Fix incorrect variable type
+    - spi: spi-xilinx: Fix type mismatch in xilinx_spi_irq API
+    - soc: xilinx: vcu: Add proper error checking
+    - media: hdr-ctrls: Add a missing include
+    - mmc: host: sdhci-of-arasan: Check return value of non-void funtions
+    - mmc: host: sdhci-of-arasan: Use appropriate type of division macro
+    - mmc: host: sdhci-of-arasan: Resolve uninitialized return value
+    - mmc: host: sdhci-of-arasan: Modify data type of the clk_phase array
+    - spi: spi-zynqmp-gqspi: Do hardware initialization later in probe
+    - spi: spi-zynqmp-gqspi: Update correct value for DLY1 bit field
+    - spi: spi-zynqmp-gqspi: Set correct clock and data tap delay values in probe
+    - net: gmii2rgmii: Fix warning for return variable check
+    - clk: clock-wizard: Refactor internal clocks
+    - clk: clock-wizard: Use all stages of the MMCM
+    - clk: clock-wizard: Add ascii art block diagram of MMCM
+    - dmaengine: xilinx: frmbuf: add missing controller free when removing module
+    - net: macb: Limit DMA mapping to 39 bits
+    - clk: zynqmp: Check the return type
+    - clk: zynqmp: Fix a memory leak
+    - misc: trafgen: fix out of scope warning
+    - v4l: xilinx: scd: Correct max/min supported resolutions
+    - v4l: xilinx: scd: Allow setting field on MM SCD subdev
+    - dt: bindings: media: xilinx: Documentation for Xilinx DP Rx subsystem
+    - v4l: xilinx: Driver support for Xilinx DP Rx subsystem
+    - staging: apf: simple include clean-up
+    - staging: apf: remove a not needed variable
+    - staging: apf: move functions around in hierarchical order
+    - staging: apf: remove uio related codes
+    - staging: apf: small ifdef - else
+    - staging: apf: remove some dead codes
+    - staging: apf: free buffers in release
+    - dmaengine: xilinx_dma: Fix usage of xilinx_aximcdma_tx_segment
+    - dmaengine: xilinx_dma: Fix SG capability check for MCDMA
+    - spi: spi-zynqmp-gqspi: Disable interrupts before registering interrupt
+      handler
+    - firmware: xilinx: Use u32 for reset ID in reset APIs
+    - usb: dwc3: use proper typecast to handle overflow
+    - usb: dwc3: Initialized variable with a proper value
+    - usb: dwc3: Remove unused variable and values warnings
+    - usb: gadget: udc: Remove useless variable assignment in xudc_read_fifo()
+    - usb: gadget: udc: Add return value error handling of function
+    - usb: dwc3: Error handling for a function return value
+    - sound: xilinx: pcm: Set the platform device name correctly
+    - phy: Add DisplayPort configuration options
+    - v4l: xilinx: dprx: Remove unused variables
+    - v4l: xilinx: dprx: Fix incorrect comparisons
+    - v4l: xilinx: dprx: Fix uninitialized variables
+    - arm64: xilinx: Enable the DP rx v4l driver
+    - drm: xlnx: zynqmp_dp: include zynqmp_dp.h and fix the return type
+    - drm: xlnx: zynqmp: fix -Wunused-but-set-variable warnings
+    - xilinx: Fix xlnx,mio_bank property
+    - clk: zynqmp: Make zynqmp_clk_get_max_divisor static
+    - clk: zynqmp: Add a check for NULL pointer
+    - clk: zynqmp: make bestdiv unsigned
+    - misc: xilinx-ai-engine: Add extern functions to request AI engine partition
+    - PCI: xdma: Use SPDX license header
+    - PCI: xdma: Add documentation for versal PL PCIe as Root Port
+    - PCI: xdma: Add support for versal PL PCIe as Root Port
+    - drm: xlnx: Fix typo in parameter description
+    - misc: xilinx-ai-engine: remove duplicate module init/exit
+    - sound: soc: xilinx: Enable 8-channel SDI audio
+    - drm: xlnx: mixer: handle software vblank
+    - dt-bindings: media: vpss-csc: Fix description of color conversion
+    - drm: xlnx: mixer: fix comparison of unsigned expression < 0
+    - drm: xlnx: mixer: remove unused variables
+    - drm: xlnx: pl_disp: remove unused variables
+    - staging: xlnxsync: Don't write back Interrupt status register(ISR)
+    - staging: xlnxsync: Check valid bit for luma/chroma done interrupts
+    - staging: xlnxsync: Check synchronization and watchdog error for consumer
+    - drm: xlnx: mixer: Add support to 8K resolution
+    - swiotlb-xen: use vmalloc_to_page on vmalloc virt addresses
+    - misc: xilinx-ai-engine: replace number with macro in regoff definition
+    - misc: xilinx-ai-engine: implement shim reset
+    - misc: xilinx-ai-engine: Implement AI engine cleanup sequence
+    - misc: xilinx-ai-engine: Add partition control flag
+    - android: ion: properly clean caches for uncached allocations
+    - fpga: add bindings document for secure flags
+    - fpga: mgr: Adds secure BitStream loading support
+    - fpga: versal: Use the scatterlist interface
+    - fpga: zynqmp: Use the scatterlist interface
+    - can: xilinx_can: Fix incorrect variable and initialize with a default value
+    - can: xilinx_can: Check return value of set_reset_mode
+    - can: xilinx_can: Add comment for spinlock_t
+    - can: xilinx_can: Fix alignment match check
+    - can: xilinx_can: Remove unnecessary braces
+    - gpio: zynq: Check return value of pm_runtime_get_sync
+    - gpio: zynq: Check return value of irq_get_irq_data
+    - gpio: gpio-xilinx: Initialize ngpio variable in the declaration
+    - gpio: gpio-xilinx: Check return value of irq_get_handler_data
+    - misc: xilinx-ai-engine: Add function to enquire if a partition is available
+    - misc: xilinx-ai-engine: use bitmask for AI engine tile type
+    - gpio: gpio-xilinx: Check return value of of_property_read_u32
+    - misc: xilinx-ai-engine: reg access from userspace uses relative address
+    - misc: xilinx-ai-engine: add setting shim dma bd operation
+
+ -- Wen-chien Jesse Sung <jesse.sung@canonical.com>  Wed, 19 Aug 2020 18:36:12 +0800
+
+linux-xilinx-zynqmp (5.4.0-1000.0) focal; urgency=medium
+
+  * empty entry
+
+ -- Wen-chien Jesse Sung <jesse.sung@canonical.com>  Sun, 16 Aug 2020 15:59:56 +0800
--- linux-xilinx-zynqmp-5.4.0.orig/debian/cloud-tools/hv_get_dhcp_info
+++ linux-xilinx-zynqmp-5.4.0/debian/cloud-tools/hv_get_dhcp_info
@@ -0,0 +1,55 @@
+#!/bin/bash
+
+# This example script retrieves the DHCP state of a given interface.
+# In the interest of keeping the KVP daemon code free of distro specific
+# information; the kvp daemon code invokes this external script to gather
+# DHCP setting for the specific interface.
+#
+# Input: Name of the interface
+#
+# Output: The script prints the string "Enabled" to stdout to indicate
+#	that DHCP is enabled on the interface. If DHCP is not enabled,
+#	the script prints the string "Disabled" to stdout.
+#
+# Each Distro is expected to implement this script in a distro specific
+# fashion. 
+
+#set -x
+
+IF_FILE="/etc/network/interfaces"
+NMCMD="nmcli"
+
+function checknetworkmanager {
+	#Assumes if $NMCMD exists, inteface exists and interface is not
+	#  in $IF_FILE then dhcp is being used by NM
+        if  hash $NMCMD >/dev/null 2>&1  ; then
+                if  $NMCMD  dev status |grep -q $1  ; then
+                        echo "Enabled"
+                else
+                        echo "Disabled"
+                fi
+        else
+                #Give up
+                echo "Disabled"
+        fi
+}
+
+if [ -z $1 ]  ; then echo "Disabled"; exit; fi
+
+if [ -e $IF_FILE ]; then
+	if grep -v -e "^#" $IF_FILE|grep -q $1 ; then
+		#interface exists so
+		if grep -q -e $1\.\*dhcp $IF_FILE; then 
+			echo "Enabled"; exit;
+		else
+			echo "Disabled"; exit;
+		fi
+	else
+		checknetworkmanager $1
+		exit
+	fi
+else
+	checknetworkmanager $1
+	exit
+fi
+
--- linux-xilinx-zynqmp-5.4.0.orig/debian/cloud-tools/hv_get_dns_info
+++ linux-xilinx-zynqmp-5.4.0/debian/cloud-tools/hv_get_dns_info
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+# This example script parses /etc/resolv.conf to retrive DNS information.
+# In the interest of keeping the KVP daemon code free of distro specific
+# information; the kvp daemon code invokes this external script to gather
+# DNS information.
+# This script is expected to print the nameserver values to stdout.
+# Each Distro is expected to implement this script in a distro specific
+# fashion. For instance on Distros that ship with Network Manager enabled,
+# this script can be based on the Network Manager APIs for retrieving DNS
+# entries.
+
+cat /etc/resolv.conf 2>/dev/null | awk '/^nameserver/ { print $2 }'
--- linux-xilinx-zynqmp-5.4.0.orig/debian/cloud-tools/hv_set_ifconfig
+++ linux-xilinx-zynqmp-5.4.0/debian/cloud-tools/hv_set_ifconfig
@@ -0,0 +1,288 @@
+#!/usr/bin/python3
+#
+# hv_set_ifconfig <config> -- take the hv_kvp_daemon generated configuration
+#                             file and apply it to the Ubuntu configuration.
+#
+
+# CONFIG example:
+# HWADDR=11:22:33:44:55:66
+# DEVICE=foo1
+# DHCP=yes
+
+# CONFIG example:
+# HWADDR=11:22:33:44:55:66
+# DEVICE=foo1
+# IPADDR=192.168.99.10
+# GATEWAY=192.168.99.1
+# DNS1=192.168.88.250
+# IPADDR2=192.168.99.11
+# IPV6ADDR=2001:DB8:99::10
+# IPV6NETMASK=64
+# IPV6_DEFAULTGW=2001:DB8:99::10
+
+# set interfaces in hv_kvp_daemon style
+import fileinput
+import sys
+import errno
+import os
+import shutil
+import tempfile
+import subprocess
+
+if_filename="/etc/network/interfaces"
+
+# Drop our output (XXX?)
+sys.stdout = open(os.devnull, 'w')
+sys.stderr = open(os.devnull, 'w')
+
+# Confirm we can open the network configuration.
+try:
+    if_file=open(if_filename,"r+")
+except IOError as e:
+    exit(e.errno)
+else:
+    if_file.close()
+
+# Usage: hv_set_ifconfig <config>
+if len(sys.argv) != 2 :
+    exit(errno.EINVAL)
+
+#
+# Here is the format of the ip configuration file:
+#
+# HWADDR=macaddr
+# DEVICE=interface name
+# BOOTPROTO=<protocol> (where <protocol> is "dhcp" if DHCP is configured
+#                       or "none" if no boot-time protocol should be used)
+#
+# IPADDR0=ipaddr1
+# IPADDR1=ipaddr2
+# IPADDRx=ipaddry (where y = x + 1)
+#
+# NETMASK0=netmask1
+# NETMASKx=netmasky (where y = x + 1)
+#
+# GATEWAY=ipaddr1
+# GATEWAYx=ipaddry (where y = x + 1)
+#
+# DNSx=ipaddrx (where first DNS address is tagged as DNS1 etc)
+#
+# IPV6 addresses will be tagged as IPV6ADDR, IPV6 gateway will be
+# tagged as IPV6_DEFAULTGW and IPV6 NETMASK will be tagged as
+# IPV6NETMASK.
+#
+
+kvp=dict(line.strip().split("=") for line in fileinput.input())
+
+# Setting the hwaddress to something azure is not expecting is fatal
+# to networking.
+if not "HWADDR" in kvp :
+    exit(errno.EPROTO)
+
+# Confirm we have a device specified.
+if not "DEVICE" in kvp :
+    exit(1)
+
+autolist = []
+output=[]
+basename=kvp["DEVICE"]
+
+# DNS entries will go with the first interface and there can be a max
+# of three.  These will be emitted with the first interface.
+dns = []
+for count in (1, 2, 3):
+    key = "DNS" + str(count)
+    if key in kvp:
+        dns += [kvp[key]]
+dns_emitted = False
+
+# IPV4 may either be dhcp or static.
+if ("DHCP" in kvp and kvp["DHCP"] == "yes") or \
+   ("BOOTPROTO" in kvp and kvp["BOOTPROTO"] == "dhcp"):
+    autolist.append(basename)
+    output += ["iface " + basename  + " inet dhcp"]
+    output += [""]
+else:
+    # Matchup the interface specific lines
+
+    # No real max for the number of interface + aliases ...
+    # only required is the address (but mate everything up that comes in.
+
+    # IPv4 -- ensure we sort by numeric suffixes.
+    v4names = [ int(name[6:]) for name in kvp.keys() if name.startswith("IPADDR") ]
+    v4names.sort()
+
+    for if_count in v4names:
+        ifname = basename
+        which = str(if_count)
+
+        if if_count:
+            ifname += ":" + str(if_count)
+            which_gw = which
+        else:
+            which_gw = ""
+
+        if not ifname in autolist:
+            autolist += [ifname]
+
+        output += [ "iface " + ifname + " inet static" ]
+        output += [ "\t" + "address " + kvp["IPADDR" + which] ]
+        if "NETMASK" + which in kvp:
+            output += [ "\tnetmask " + kvp["NETMASK" + which] ]
+        if "GATEWAY" + which_gw in kvp:
+            output += ["\tgateway " + kvp["GATEWAY" + which_gw]]
+
+        if not dns_emitted:
+            dns_emitted = True
+            output += ["\tdns-nameservers " + ' '.join(dns)]
+        output += [""]
+
+# IPv6 requires a netmask
+# If an ipv6 exists, you'll want to turn off /proc/sys/net/ipv6/conf/all/autoconf with
+# echo 0 > /proc/sys/net/ipv6/conf/all/autoconf
+v6names = [ int(name[8:]) for name in kvp.keys() if name.startswith("IPV6ADDR") ]
+v6names.sort()
+
+for if6_count in v6names:
+    ifname = basename
+    which = str(if6_count)
+
+    if if6_count:
+        ifname += ":" + str(if6_count)
+        which_gw = which
+    else:
+        which_gw = ""
+
+    if not ifname in autolist:
+        autolist += [ifname]
+
+    if "IPV6NETMASK" + which in kvp:
+        output += [ "iface " + ifname + " inet6 static"]
+        output += [ "\taddress " + kvp["IPV6ADDR" + which]]
+        output += [ "\tnetmask " + kvp["IPV6NETMASK" + which]]
+        if "IPV6_DEFAULTGW" + which_gw in kvp:
+            output += [ "\tgateway " + kvp["IPV6_DEFAULTGW" + which_gw] ]
+        if not dns_emitted:
+            dns_emitted = True
+            output += ["\tdns-nameservers " + ' '.join(dns)]
+        output += [""]
+
+# Mark this new interface for automatic up.
+if len(autolist):
+    output = ["auto "+" ".join(autolist)] + output
+
+print("===================================")
+print(output)
+print("===================================")
+
+
+# Time to clean out the existing interface file
+
+# Markers.
+start_mark = "# The following stanza(s) added by hv_set_ifconfig"
+end_mark = "#End of hv_set_ifconfig stanzas"
+
+f=open(if_filename,"r")
+flines=f.readlines()
+f.close()
+newfile=[]
+pitchstanza=0
+inastanza=0
+stanza=[]
+prev_line=None
+for line in flines:
+    if line.startswith("auto"):
+        if inastanza:
+            if not pitchstanza:
+                newfile.extend(stanza)
+            stanza=[]
+        inastanza=0
+        newline=""
+        autoline=line.strip().split(" ")
+        for word in autoline:
+            if (not word == basename) and (not word.startswith(basename+":")):
+                newline+=word + " "
+        newline = newline.strip()
+        if not newline == "auto":
+            newfile += [newline.strip()]
+    elif line.startswith(("iface","mapping","source")):
+        '''Read a stanza'''
+        '''A Stanza can also start with allow- ie allow-hotplug'''
+        if inastanza:
+            if not pitchstanza:
+                newfile.extend(stanza)
+            stanza=[]
+        inastanza=1
+        pitchstanza=0
+        autoline=line.strip().split(" ")
+        for word in autoline:
+            if (word == basename) or (word.startswith(basename+":")):
+                pitchstanza=1
+        if not pitchstanza:
+            stanza+=[line.strip()]
+    elif line.strip() in (start_mark, end_mark):
+        if inastanza:
+            if not pitchstanza:
+                newfile.extend(stanza)
+            stanza=[]
+        inastanza = 0
+        pitchstanza = 0
+        # Deduplicate markers.
+        if line != prev_line:
+            newfile += [line.strip()]
+    else:
+        if inastanza:
+            if not pitchstanza:
+                stanza+=[line.strip()]
+        else:
+            if not pitchstanza:
+                newfile += [line.strip()]
+    prev_line=line
+
+# Include pending stanza if any.
+if inastanza and not pitchstanza:
+    newfile.extend(stanza)
+
+
+def emit(line):
+    print(line)
+    output = line + "\n"
+    os.write(fd, output.encode('utf-8'))
+
+# Insert the new output at the end and inside the existing markers if found.
+emitted = False
+fd, path = tempfile.mkstemp()
+for line in newfile:
+    if line == end_mark:
+        emit("\n".join(output))
+        emitted = True
+    emit(line)
+if not emitted:
+    emit(start_mark)
+    emit("\n".join(output))
+    emit(end_mark)
+os.close(fd)
+
+shutil.copy(path,if_filename)
+os.chmod(if_filename,0o644)
+
+#print("TMPFILE is at: " + path)
+#print("Copied file is at: " + if_filename)
+
+try:
+    retcode = subprocess.call("ifdown "+basename , shell=True)
+    if retcode < 0:
+        print("Child was terminated by signal", -retcode, file=sys.stderr)
+    else:
+        print("Child returned", retcode, file=sys.stderr)
+except OSError as e:
+    print("Execution failed:", e, file=sys.stderr)
+
+try:
+    retcode = subprocess.call("ifup "+basename , shell=True)
+    if retcode < 0:
+        print("Child was terminated by signal", -retcode, file=sys.stderr)
+    else:
+        print("Child returned", retcode, file=sys.stderr)
+except OSError as e:
+    print("Execution failed:", e, file=sys.stderr)
--- linux-xilinx-zynqmp-5.4.0.orig/debian/commit-templates/bumpabi
+++ linux-xilinx-zynqmp-5.4.0/debian/commit-templates/bumpabi
@@ -0,0 +1,3 @@
+UBUNTU: Bump ABI
+
+Ignore: yes
--- linux-xilinx-zynqmp-5.4.0.orig/debian/commit-templates/config-updates
+++ linux-xilinx-zynqmp-5.4.0/debian/commit-templates/config-updates
@@ -0,0 +1,15 @@
+#
+# This template is used for commit messages that don't need to
+# show up in debian/changelog. Administrative stuff like config
+# updates, ABI bumps, etc. Setting 'Ignore: yes' prevents
+# 'debian/rules insertchanges' from inserting this commit meesage
+# as a changelog entry.
+#
+# Please give a one-line description of the config change followed
+# by a detailed explanation if necessary
+
+UBUNTU: [Config] XXXX
+
+# BugLink: http://bugs.launchpad.net/bugs/<enter bug# here>
+# Ignore: yes
+# Other text below here.
--- linux-xilinx-zynqmp-5.4.0.orig/debian/commit-templates/external-driver
+++ linux-xilinx-zynqmp-5.4.0/debian/commit-templates/external-driver
@@ -0,0 +1,20 @@
+# Ubuntu external driver commit.
+#
+# NOTE: This gets reformatted for README.Ubuntu-External-Drivers and
+# debian/changelog.
+#
+# This is only needed when a driver is added, updated or removed. It is
+# not needed when patches or fixes are applied to the driver. If the
+# driver is being removed, add the line:
+#
+# Removing: yes
+#
+# to the commit, and you can remove all other tags (except UBUNTU:).
+#
+UBUNTU: 
+
+ExternalDriver: 
+Description:
+Url:
+Mask:
+Version:
--- linux-xilinx-zynqmp-5.4.0.orig/debian/commit-templates/missing-modules
+++ linux-xilinx-zynqmp-5.4.0/debian/commit-templates/missing-modules
@@ -0,0 +1,3 @@
+UBUNTU: build/modules: Add modules that have intentionally gone missing
+
+Ignore: yes
--- linux-xilinx-zynqmp-5.4.0.orig/debian/commit-templates/newrelease
+++ linux-xilinx-zynqmp-5.4.0/debian/commit-templates/newrelease
@@ -0,0 +1,3 @@
+UBUNTU: Start new release
+
+Ignore: yes
--- linux-xilinx-zynqmp-5.4.0.orig/debian/commit-templates/sauce-patch
+++ linux-xilinx-zynqmp-5.4.0/debian/commit-templates/sauce-patch
@@ -0,0 +1,40 @@
+# Ubuntu commit template.
+#
+# NOTE: This gets reformatted for debian/changelog
+#
+#
+# SAUCE refers to the fact that this patch might not go upstream, but we need to
+# carry it to successive releases. In most cases you DONOT want to use this
+# template. 
+#
+# An example of a SAUCE patch is the ACPI DSDT-in-initramfs patch which has been
+# refused upstream, but still provides useful functionality to users with broken
+# BIOSes.
+#
+#-------------------------------------------------------------------------
+#
+# The initial UBUNTU is a flag that this is an Ubuntu commit. It will be
+# referenced to the Author in the debian/changelog entry.
+#
+# The text following is the short message that will be placed in the
+# changelog. Extra text on the following lines will be ignored, but left
+# in the git commit. Lines with # will be ignored in the commit.
+#
+# OriginalAuthor allows for alternate attribution.
+#
+# OriginalLocation allows for a URL or description of where the patch came
+# from.
+#
+# BugLink is a URL to a Malone bug.
+#
+# Ignore: yes will keep this commit from showing up in the changelog.
+#
+UBUNTU: SAUCE: 
+
+<Why is this patch not going upstream?>
+
+# OriginalAuthor: 
+# OriginalLocation: 
+# BugLink: http://bugs.launchpad.net/bugs/<enter bug# here>
+# Ignore: yes
+# Other text below here.
--- linux-xilinx-zynqmp-5.4.0.orig/debian/commit-templates/upstream-patch
+++ linux-xilinx-zynqmp-5.4.0/debian/commit-templates/upstream-patch
@@ -0,0 +1,27 @@
+# Ubuntu commit template.
+#
+# NOTE: This gets reformatted for debian/changelog
+#
+# The initial UBUNTU is a flag that this is an Ubuntu commit. It will be
+# referenced to the Author in the debian/changelog entry.
+#
+# The text following is the short message that will be placed in the
+# changelog. Extra text on the following lines will be ignored, but left
+# in the git commit. Lines with # will be ignored in the commit.
+#
+# OriginalAuthor allows for alternate attribution.
+#
+# OriginalLocation allows for a URL or description of where the patch came
+# from.
+#
+# BugLink is a URL to a Malone bug.
+#
+# Ignore: yes will keep this commit from showing up in the changelog.
+#
+UBUNTU: [Upstream]
+
+# OriginalAuthor: 
+# OriginalLocation: 
+# BugLink: http://bugs.launchpad.net/bugs/<enter bug# here>
+# Ignore: yes
+# Other text below here.
--- linux-xilinx-zynqmp-5.4.0.orig/debian/compat
+++ linux-xilinx-zynqmp-5.4.0/debian/compat
@@ -0,0 +1 @@
+9
--- linux-xilinx-zynqmp-5.4.0.orig/debian/control
+++ linux-xilinx-zynqmp-5.4.0/debian/control
@@ -0,0 +1,205 @@
+Source: linux-xilinx-zynqmp
+Section: devel
+Priority: optional
+Maintainer: Ubuntu Kernel Team <kernel-team@lists.ubuntu.com>
+XSC-Ubuntu-Compatible-Signing: ubuntu/4 pro/3
+Standards-Version: 3.9.4.0
+Build-Depends:
+ debhelper (>= 9),
+ dh-systemd,
+ cpio,
+ kernel-wedge,
+ kmod <!stage1>,
+ makedumpfile [amd64] <!stage1>,
+ libcap-dev <!stage1>,
+ libelf-dev <!stage1>,
+ libnewt-dev <!stage1>,
+ libiberty-dev <!stage1>,
+ default-jdk-headless <!stage1>,
+ java-common <!stage1>,
+ rsync <!stage1>,
+ libdw-dev <!stage1>,
+ libpci-dev <!stage1>,
+ pkg-config <!stage1>,
+ flex <!stage1>,
+ bison <!stage1>,
+ libunwind8-dev [amd64 arm64 armhf ppc64el] <!stage1>,
+ liblzma-dev <!stage1>,
+ openssl <!stage1>,
+ libssl-dev <!stage1>,
+ libaudit-dev <!stage1>,
+ bc <!stage1>,
+ gawk <!stage1>,
+ libudev-dev <!stage1>,
+ autoconf <!stage1>,
+ automake <!stage1>,
+ libtool <!stage1>,
+ uuid-dev <!stage1>,
+ libnuma-dev [amd64 arm64 ppc64el s390x] <!stage1>,
+ dkms <!stage1>,
+ curl <!stage1>,
+ lz4 [amd64 s390x] <!stage1>,
+Build-Depends-Indep:
+ xmlto <!stage1>,
+ docbook-utils <!stage1>,
+ ghostscript <!stage1>,
+ fig2dev <!stage1>,
+ bzip2 <!stage1>,
+ sharutils <!stage1>,
+ asciidoc <!stage1>,
+ python3-sphinx <!stage1>,
+ python3-sphinx-rtd-theme <!stage1>,
+ fontconfig <!stage1>,
+ python3-docutils <!stage1>,
+Vcs-Git: git://git.launchpad.net/~canonical-hwe-kernel/limerick/+git/linux-zynqmp
+XS-Testsuite: autopkgtest
+#XS-Testsuite-Depends: gcc-4.7 binutils
+
+Package: linux-xilinx-zynqmp-headers-5.4.0-1075
+Build-Profiles: <!stage1>
+Architecture: all
+Multi-Arch: foreign
+Section: devel
+Priority: optional
+Depends: ${misc:Depends}, coreutils
+Description: Header files related to Linux kernel version 5.4.0
+ This package provides kernel header files for version 5.4.0, for sites
+ that want the latest kernel headers. Please read
+ /usr/share/doc/linux-xilinx-zynqmp-headers-5.4.0-1075/debian.README.gz for details
+
+Package: linux-xilinx-zynqmp-tools-5.4.0-1075
+Build-Profiles: <!stage1>
+Architecture: arm64
+Section: devel
+Priority: optional
+Depends: ${misc:Depends}, ${shlibs:Depends}, linux-tools-common
+Description: Linux kernel version specific tools for version 5.4.0-1075
+ This package provides the architecture dependant parts for kernel
+ version locked tools (such as perf and x86_energy_perf_policy) for
+ version 5.4.0-1075 on
+ .
+ You probably want to install linux-tools-5.4.0-1075-<flavour>.
+
+
+
+Package: linux-image-5.4.0-1075-xilinx-zynqmp
+Build-Profiles: <!stage1>
+Architecture: arm64
+Section: kernel
+Priority: optional
+Provides: linux-image, fuse-module, aufs-dkms, kvm-api-4, redhat-cluster-modules, ivtv-modules, virtualbox-guest-modules [amd64], ${linux:rprovides}
+Depends: ${misc:Depends}, ${shlibs:Depends}, kmod, linux-base (>= 4.5ubuntu1~16.04.1), linux-modules-5.4.0-1075-xilinx-zynqmp
+Recommends: initramfs-tools | linux-initramfs-tool
+Breaks: flash-kernel (<< 3.90ubuntu2) [arm64 armhf], s390-tools (<< 2.3.0-0ubuntu3) [s390x]
+Conflicts: linux-image-unsigned-5.4.0-1075-xilinx-zynqmp
+Suggests: fdutils, linux-doc | linux-xilinx-zynqmp-source-5.4.0, linux-xilinx-zynqmp-tools, linux-headers-5.4.0-1075-xilinx-zynqmp
+Description: Linux kernel image for version 5.4.0 on  SMP
+ This package contains the Linux kernel image for version 5.4.0 on
+  SMP.
+ .
+ Supports Xilinx ZYNQ Ultrascale+ processors.
+ .
+ Geared toward desktop and server systems.
+ .
+ You likely do not want to install this package directly. Instead, install
+ the linux-xilinx-zynqmp meta-package, which will ensure that upgrades work
+ correctly, and that supporting packages are also installed.
+
+Package: linux-modules-5.4.0-1075-xilinx-zynqmp
+Build-Profiles: <!stage1>
+Architecture: arm64
+Section: kernel
+Priority: optional
+Depends: ${misc:Depends}, ${shlibs:Depends}
+Built-Using: ${linux:BuiltUsing}
+Description: Linux kernel extra modules for version 5.4.0 on  SMP
+ Contains the corresponding System.map file, the modules built by the
+ packager, and scripts that try to ensure that the system is not left in an
+ unbootable state after an update.
+ .
+ Supports Xilinx ZYNQ Ultrascale+ processors.
+ .
+ Geared toward desktop and server systems.
+ .
+ You likely do not want to install this package directly. Instead, install
+ the linux-xilinx-zynqmp meta-package, which will ensure that upgrades work
+ correctly, and that supporting packages are also installed.
+
+Package: linux-modules-extra-5.4.0-1075-xilinx-zynqmp
+Build-Profiles: <!stage1>
+Architecture: arm64
+Section: kernel
+Priority: optional
+Depends: ${misc:Depends}, ${shlibs:Depends}, linux-image-5.4.0-1075-xilinx-zynqmp | linux-image-unsigned-5.4.0-1075-xilinx-zynqmp, crda | wireless-crda
+Description: Linux kernel extra modules for version 5.4.0 on  SMP
+ This package contains the Linux kernel extra modules for version 5.4.0 on
+  SMP.
+ .
+ Also includes the corresponding System.map file, the modules built by the
+ packager, and scripts that try to ensure that the system is not left in an
+ unbootable state after an update.
+ .
+ Supports Xilinx ZYNQ Ultrascale+ processors.
+ .
+ Geared toward desktop and server systems.
+ .
+ You likely do not want to install this package directly. Instead, install
+ the linux-xilinx-zynqmp meta-package, which will ensure that upgrades work
+ correctly, and that supporting packages are also installed.
+
+Package: linux-headers-5.4.0-1075-xilinx-zynqmp
+Build-Profiles: <!stage1>
+Architecture: arm64
+Section: devel
+Priority: optional
+Depends: ${misc:Depends}, linux-xilinx-zynqmp-headers-5.4.0-1075, ${shlibs:Depends}
+Provides: linux-headers, linux-headers-3.0
+Description: Linux kernel headers for version 5.4.0 on  SMP
+ This package provides kernel header files for version 5.4.0 on
+  SMP.
+ .
+ This is for sites that want the latest kernel headers.  Please read
+ /usr/share/doc/linux-headers-5.4.0-1075/debian.README.gz for details.
+
+Package: linux-image-5.4.0-1075-xilinx-zynqmp-dbgsym
+Build-Profiles: <!stage1>
+Architecture: arm64
+Section: devel
+Priority: optional
+Depends: ${misc:Depends}
+Provides: linux-debug
+Description: Linux kernel debug image for version 5.4.0 on  SMP
+ This package provides the kernel debug image for version 5.4.0 on
+  SMP.
+ .
+ This is for sites that wish to debug the kernel.
+ .
+ The kernel image contained in this package is NOT meant to boot from. It
+ is uncompressed, and unstripped. This package also includes the
+ unstripped modules.
+
+Package: linux-tools-5.4.0-1075-xilinx-zynqmp
+Build-Profiles: <!stage1>
+Architecture: arm64
+Section: devel
+Priority: optional
+Depends: ${misc:Depends}, linux-xilinx-zynqmp-tools-5.4.0-1075
+Description: Linux kernel version specific tools for version 5.4.0-1075
+ This package provides the architecture dependant parts for kernel
+ version locked tools (such as perf and x86_energy_perf_policy) for
+ version 5.4.0-1075 on
+ .
+
+
+Package: linux-buildinfo-5.4.0-1075-xilinx-zynqmp
+Build-Profiles: <!stage1>
+Architecture: arm64
+Section: kernel
+Priority: optional
+Depends: ${misc:Depends}, ${shlibs:Depends}
+Built-Using: ${linux:BuiltUsing}
+Description: Linux kernel buildinfo for version 5.4.0 on  SMP
+ This package contains the Linux kernel buildinfo for version 5.4.0 on
+  SMP.
+ .
+ You likely do not want to install this package.
--- linux-xilinx-zynqmp-5.4.0.orig/debian/control.d/flavour-buildinfo.stub
+++ linux-xilinx-zynqmp-5.4.0/debian/control.d/flavour-buildinfo.stub
@@ -0,0 +1,13 @@
+
+Package: linux-buildinfo-PKGVER-ABINUM-FLAVOUR
+Build-Profiles: <!stage1>
+Architecture: ARCH
+Section: kernel
+Priority: optional
+Depends: ${misc:Depends}, ${shlibs:Depends}
+Built-Using: ${linux:BuiltUsing}
+Description: Linux kernel buildinfo for version PKGVER on DESC
+ This package contains the Linux kernel buildinfo for version PKGVER on
+ DESC.
+ .
+ You likely do not want to install this package.
--- linux-xilinx-zynqmp-5.4.0.orig/debian/copyright
+++ linux-xilinx-zynqmp-5.4.0/debian/copyright
@@ -0,0 +1,29 @@
+This is the Ubuntu prepackaged version of the Linux kernel.
+Linux was written by Linus Torvalds <Linus.Torvalds@cs.Helsinki.FI>
+and others.
+
+This package was put together by the Ubuntu Kernel Team, from
+sources retrieved from upstream linux git.
+The sources may be found at most Linux ftp sites, including 
+ftp://ftp.kernel.org/pub/linux/kernel/
+
+This package is currently maintained by the
+Ubuntu Kernel Team <ubuntu-kernel@lists.ubuntu.com>
+
+Linux is copyrighted by Linus Torvalds and others.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+On Ubuntu Linux systems, the complete text of the GNU General
+Public License v2 can be found in `/usr/share/common-licenses/GPL-2'.
--- linux-xilinx-zynqmp-5.4.0.orig/debian/debian.env
+++ linux-xilinx-zynqmp-5.4.0/debian/debian.env
@@ -0,0 +1 @@
+DEBIAN=debian.zynqmp
--- linux-xilinx-zynqmp-5.4.0.orig/debian/docs/README.inclusion-list
+++ linux-xilinx-zynqmp-5.4.0/debian/docs/README.inclusion-list
@@ -0,0 +1,51 @@
+This README describes the reason for, and the use of, module
+inclusion lists.
+
+The original Hardy release had the notion of sub-flavours,
+e.g., a flavour that was constructed as a subset of an existing flavour.
+For example, the virtual flavour was extracted from the server flavour using
+a subset of the server flavour modules. However, there were some difficult
+mainteneance issues with regard to packaging, make rules, and scripts. This
+re-implementation of the sub-flavours philosophy is hopefully simpler,
+and retrofitable to all releases.
+
+A module inclusion list looks at the problem of of constructing a package
+from the perspective of what modules do we _want_ in the package, as opposed
+to what modules we _don't_ want. As the kernel matures, more and more devices are added
+which makes the problem of configuration maintenance a real pain in the ass.
+If we took the approach of disabling all of the config options that we don't want,
+then the differences between flavours will quickly become quite large, making
+it difficult to quickly compare the individual flavour configs.  Each time a
+new config option is added then we also have to make a decision about disabling in
+order to continue to keep the minimal number of modules.
+
+A module inclusion list is applied on a per-flavour basis. For example,
+debian.<BRANCH>/control.d/${flavour}.inclusion-list. For example, the
+config for virtual is very close to server and generic, but the inclusion list
+causes the virtual package to be constructed with _only_ the modules described 
+in the inclusion list.
+
+The inclusion list format is a simple bash regular expression list of files. For example,
+
+arch/*/{crypto,kernel,oprofile}
+drivers/acpi/*
+drivers/ata/ahci.ko
+
+These 3 regular expression forms are suitable for expansion by bash and as inputs to 'find'.
+See debian/scripts/module-inclusion for details.
+
+There are 2 log files created as a side effect of the application of the module
+inclusion list; $(flavour).inclusion-list.log and $(flavour).depmod.log.
+
+$(flavour).inclusion-list.log : This log is created while the inclusion list
+modules are being copied. If any are missing, then those warnings go in this log.
+While its not considered a fatal error, you should endevour to correct your inclusion
+list such that there are no missing modules.
+
+$(flavour).depmod.log : The log is created as a result of running depmod on the
+resulting set of modules. If there are missing symbols then you'll find that information
+here. Again, you should modify your inclusion list such that there are no missing
+symbols.
+
+Tim Gardner <tim.gardner@canonical.com>
+June 2, 2010
--- linux-xilinx-zynqmp-5.4.0.orig/debian/gbp.conf
+++ linux-xilinx-zynqmp-5.4.0/debian/gbp.conf
@@ -0,0 +1,2 @@
+[buildpackage]
+debian-tag = Ubuntu-%(version)s
--- linux-xilinx-zynqmp-5.4.0.orig/debian/linux-cloud-tools-common.hv-fcopy-daemon.service
+++ linux-xilinx-zynqmp-5.4.0/debian/linux-cloud-tools-common.hv-fcopy-daemon.service
@@ -0,0 +1,14 @@
+# On Azure/Hyper-V systems start the hv_fcopy_daemon
+#
+# author "Andy Whitcroft <apw@canonical.com>"
+[Unit]
+Description=Hyper-V File Copy Protocol Daemon
+ConditionVirtualization=microsoft
+ConditionPathExists=/dev/vmbus/hv_fcopy
+BindsTo=sys-devices-virtual-misc-vmbus\x21hv_fcopy.device
+
+[Service]
+ExecStart=/usr/sbin/hv_fcopy_daemon -n
+
+[Install]
+WantedBy=multi-user.target
--- linux-xilinx-zynqmp-5.4.0.orig/debian/linux-cloud-tools-common.hv-fcopy-daemon.udev
+++ linux-xilinx-zynqmp-5.4.0/debian/linux-cloud-tools-common.hv-fcopy-daemon.udev
@@ -0,0 +1 @@
+SUBSYSTEM=="misc", KERNEL=="vmbus/hv_fcopy", TAG+="systemd", ENV{SYSTEMD_WANTS}+="hv-fcopy-daemon.service"
--- linux-xilinx-zynqmp-5.4.0.orig/debian/linux-cloud-tools-common.hv-fcopy-daemon.upstart
+++ linux-xilinx-zynqmp-5.4.0/debian/linux-cloud-tools-common.hv-fcopy-daemon.upstart
@@ -0,0 +1,22 @@
+# On Azure/Hyper-V systems start the hv_fcopy_daemon
+#
+description "Hyper-V File Copy Protocol Daemon"
+author "Andy Whitcroft <apw@canonical.com>"
+
+start on runlevel [2345]
+stop on runlevel [!2345]
+console log
+
+pre-start script
+        if [ -e "/etc/default/hv-kvp-daemon-init" ]; then
+                . /etc/default/hv-kvp-daemon-init
+        fi
+        [ "$RUN_FCOPY_DAEMON" -eq 0 ] && { stop; exit 0; }
+	if [ -d /sys/class/dmi/id/. ]; then
+		read company </sys/class/dmi/id/sys_vendor
+		read product </sys/class/dmi/id/product_name
+		[ "$company:$product" = 'Microsoft Corporation:Virtual Machine' ] || { stop; exit 0; }
+	fi
+end script
+
+exec /usr/sbin/hv_fcopy_daemon -n
--- linux-xilinx-zynqmp-5.4.0.orig/debian/linux-cloud-tools-common.hv-kvp-daemon.service
+++ linux-xilinx-zynqmp-5.4.0/debian/linux-cloud-tools-common.hv-kvp-daemon.service
@@ -0,0 +1,20 @@
+# On Azure/Hyper-V systems start the hv_kvp_daemon
+#
+# author "Andy Whitcroft <apw@canonical.com>"
+[Unit]
+Description=Hyper-V KVP Protocol Daemon
+ConditionVirtualization=microsoft
+ConditionKernelCommandLine=!snapd_recovery_mode
+DefaultDependencies=no
+BindsTo=sys-devices-virtual-misc-vmbus\x21hv_kvp.device
+After=sys-devices-virtual-misc-vmbus\x21hv_kvp.device systemd-remount-fs.service
+Before=shutdown.target cloud-init-local.service walinuxagent.service
+Conflicts=shutdown.target
+RequiresMountsFor=/var/lib/hyperv
+ConditionPathExists=/dev/vmbus/hv_kvp
+
+[Service]
+ExecStart=/usr/sbin/hv_kvp_daemon -n
+
+[Install]
+WantedBy=multi-user.target
--- linux-xilinx-zynqmp-5.4.0.orig/debian/linux-cloud-tools-common.hv-kvp-daemon.udev
+++ linux-xilinx-zynqmp-5.4.0/debian/linux-cloud-tools-common.hv-kvp-daemon.udev
@@ -0,0 +1 @@
+SUBSYSTEM=="misc", KERNEL=="vmbus/hv_kvp", TAG+="systemd", ENV{SYSTEMD_WANTS}+="hv-kvp-daemon.service"
--- linux-xilinx-zynqmp-5.4.0.orig/debian/linux-cloud-tools-common.hv-kvp-daemon.upstart
+++ linux-xilinx-zynqmp-5.4.0/debian/linux-cloud-tools-common.hv-kvp-daemon.upstart
@@ -0,0 +1,22 @@
+# On Azure/Hyper-V systems start the hv_kvp_daemon
+#
+description "Hyper-V KVP Protocol Daemon"
+author "Adam Conrad <adconrad@canonical.com>"
+
+start on runlevel [2345]
+stop on runlevel [!2345]
+console log
+
+pre-start script
+        if [ -e "/etc/default/hv-kvp-daemon-init" ]; then
+                . /etc/default/hv-kvp-daemon-init
+        fi
+        [ "$RUN_KVP_DAEMON" = 0 ] && { stop; exit 0; }
+	if [ -d /sys/class/dmi/id/. ]; then
+		read company </sys/class/dmi/id/sys_vendor
+		read product </sys/class/dmi/id/product_name
+		[ "$company:$product" = 'Microsoft Corporation:Virtual Machine' ] || { stop; exit 0; }
+	fi
+end script
+
+exec /usr/sbin/hv_kvp_daemon -n
--- linux-xilinx-zynqmp-5.4.0.orig/debian/linux-cloud-tools-common.hv-vss-daemon.service
+++ linux-xilinx-zynqmp-5.4.0/debian/linux-cloud-tools-common.hv-vss-daemon.service
@@ -0,0 +1,14 @@
+# On Azure/Hyper-V systems start the hv_vss_daemon
+#
+# author "Andy Whitcroft <apw@canonical.com>"
+[Unit]
+Description=Hyper-V VSS Protocol Daemon
+ConditionVirtualization=microsoft
+ConditionPathExists=/dev/vmbus/hv_vss
+BindsTo=sys-devices-virtual-misc-vmbus\x21hv_vss.device
+
+[Service]
+ExecStart=/usr/sbin/hv_vss_daemon -n
+
+[Install]
+WantedBy=multi-user.target
--- linux-xilinx-zynqmp-5.4.0.orig/debian/linux-cloud-tools-common.hv-vss-daemon.udev
+++ linux-xilinx-zynqmp-5.4.0/debian/linux-cloud-tools-common.hv-vss-daemon.udev
@@ -0,0 +1 @@
+SUBSYSTEM=="misc", KERNEL=="vmbus/hv_vss", TAG+="systemd", ENV{SYSTEMD_WANTS}+="hv-vss-daemon.service"
--- linux-xilinx-zynqmp-5.4.0.orig/debian/linux-cloud-tools-common.hv-vss-daemon.upstart
+++ linux-xilinx-zynqmp-5.4.0/debian/linux-cloud-tools-common.hv-vss-daemon.upstart
@@ -0,0 +1,22 @@
+# On Azure/Hyper-V systems start the hv_vss_daemon
+#
+description "Hyper-V VSS Protocol Daemon"
+author "Ben Howard <ben.howard@canonical.com>"
+
+start on runlevel [2345]
+stop on runlevel [!2345]
+console log
+
+pre-start script
+        if [ -e "/etc/default/hv-kvp-daemon-init" ]; then
+                . /etc/default/hv-kvp-daemon-init
+        fi
+        [ "$RUN_VSS_DAEMON" -eq 0 ] && { stop; exit 0; }
+	if [ -d /sys/class/dmi/id/. ]; then
+		read company </sys/class/dmi/id/sys_vendor
+		read product </sys/class/dmi/id/product_name
+		[ "$company:$product" = 'Microsoft Corporation:Virtual Machine' ] || { stop; exit 0; }
+	fi
+end script
+
+exec /usr/sbin/hv_vss_daemon -n
--- linux-xilinx-zynqmp-5.4.0.orig/debian/linux-cloud-tools-common.intel-sgx-load-module.service
+++ linux-xilinx-zynqmp-5.4.0/debian/linux-cloud-tools-common.intel-sgx-load-module.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=Install SGX kernel module
+DefaultDependencies=false
+ConditionVirtualization=microsoft
+
+[Service]
+Type=oneshot
+RemainAfterExit=true
+ExecStart=/sbin/modprobe intel_sgx
+ExecStop=/sbin/modprobe -r intel_sgx
+
+[Install]
+WantedBy=multi-user.target
--- linux-xilinx-zynqmp-5.4.0.orig/debian/revoked-certs/canonical-uefi-2012-all.pem
+++ linux-xilinx-zynqmp-5.4.0/debian/revoked-certs/canonical-uefi-2012-all.pem
@@ -0,0 +1,86 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1 (0x1)
+        Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C = GB, ST = Isle of Man, L = Douglas, O = Canonical Ltd., CN = Canonical Ltd. Master Certificate Authority
+        Validity
+            Not Before: Apr 12 11:39:08 2012 GMT
+            Not After : Apr 11 11:39:08 2042 GMT
+        Subject: C = GB, ST = Isle of Man, O = Canonical Ltd., OU = Secure Boot, CN = Canonical Ltd. Secure Boot Signing
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (2048 bit)
+                Modulus:
+                    00:c9:5f:9b:62:8f:0b:b0:64:82:ac:be:c9:e2:62:
+                    e3:4b:d2:9f:1e:8a:d5:61:1a:2b:5d:38:f4:b7:ce:
+                    b9:9a:b8:43:b8:43:97:77:ab:4f:7f:0c:70:46:0b:
+                    fc:7f:6d:c6:6d:ea:80:5e:01:d2:b7:66:1e:87:de:
+                    0d:6d:d0:41:97:a8:a5:af:0c:63:4f:f7:7c:c2:52:
+                    cc:a0:31:a9:bb:89:5d:99:1e:46:6f:55:73:b9:76:
+                    69:ec:d7:c1:fc:21:d6:c6:07:e7:4f:bd:22:de:e4:
+                    a8:5b:2d:db:95:34:19:97:d6:28:4b:21:4c:ca:bb:
+                    1d:79:a6:17:7f:5a:f9:67:e6:5c:78:45:3d:10:6d:
+                    b0:17:59:26:11:c5:57:e3:7f:4e:82:ba:f6:2c:4e:
+                    c8:37:4d:ff:85:15:84:47:e0:ed:3b:7c:7f:bc:af:
+                    e9:01:05:a7:0c:6f:c3:e9:8d:a3:ce:be:a6:e3:cd:
+                    3c:b5:58:2c:9e:c2:03:1c:60:22:37:39:ff:41:02:
+                    c1:29:a4:65:51:ff:33:34:aa:42:15:f9:95:78:fc:
+                    2d:f5:da:8a:85:7c:82:9d:fb:37:2c:6b:a5:a8:df:
+                    7c:55:0b:80:2e:3c:b0:63:e1:cd:38:48:89:e8:14:
+                    06:0b:82:bc:fd:d4:07:68:1b:0f:3e:d9:15:dd:94:
+                    11:1b
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:FALSE
+            X509v3 Extended Key Usage: 
+                Code Signing, 1.3.6.1.4.1.311.10.3.6
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                61:48:2A:A2:83:0D:0A:B2:AD:5A:F1:0B:72:50:DA:90:33:DD:CE:F0
+            X509v3 Authority Key Identifier: 
+                AD:91:99:0B:C2:2A:B1:F5:17:04:8C:23:B6:65:5A:26:8E:34:5A:63
+    Signature Algorithm: sha256WithRSAEncryption
+    Signature Value:
+        8f:8a:a1:06:1f:29:b7:0a:4a:d5:c5:fd:81:ab:25:ea:c0:7d:
+        e2:fc:6a:96:a0:79:93:67:ee:05:0e:25:12:25:e4:5a:f6:aa:
+        1a:f1:12:f3:05:8d:87:5e:f1:5a:5c:cb:8d:23:73:65:1d:15:
+        b9:de:22:6b:d6:49:67:c9:a3:c6:d7:62:4e:5c:b5:f9:03:83:
+        40:81:dc:87:9c:3c:3f:1c:0d:51:9f:94:65:0a:84:48:67:e4:
+        a2:f8:a6:4a:f0:e7:cd:cd:bd:94:e3:09:d2:5d:2d:16:1b:05:
+        15:0b:cb:44:b4:3e:61:42:22:c4:2a:5c:4e:c5:1d:a3:e2:e0:
+        52:b2:eb:f4:8b:2b:dc:38:39:5d:fb:88:a1:56:65:5f:2b:4f:
+        26:ff:06:78:10:12:eb:8c:5d:32:e3:c6:45:af:25:9b:a0:ff:
+        8e:ef:47:09:a3:e9:8b:37:92:92:69:76:7e:34:3b:92:05:67:
+        4e:b0:25:ed:bc:5e:5f:8f:b4:d6:ca:40:ff:e4:e2:31:23:0c:
+        85:25:ae:0c:55:01:ec:e5:47:5e:df:5b:bc:14:33:e3:c6:f5:
+        18:b6:d9:f7:dd:b3:b4:a1:31:d3:5a:5c:5d:7d:3e:bf:0a:e4:
+        e4:e8:b4:59:7d:3b:b4:8c:a3:1b:b5:20:a3:b9:3e:84:6f:8c:
+        21:00:c3:39
+-----BEGIN CERTIFICATE-----
+MIIEIDCCAwigAwIBAgIBATANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBhMCR0Ix
+FDASBgNVBAgMC0lzbGUgb2YgTWFuMRAwDgYDVQQHDAdEb3VnbGFzMRcwFQYDVQQK
+DA5DYW5vbmljYWwgTHRkLjE0MDIGA1UEAwwrQ2Fub25pY2FsIEx0ZC4gTWFzdGVy
+IENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xMjA0MTIxMTM5MDhaFw00MjA0MTEx
+MTM5MDhaMH8xCzAJBgNVBAYTAkdCMRQwEgYDVQQIDAtJc2xlIG9mIE1hbjEXMBUG
+A1UECgwOQ2Fub25pY2FsIEx0ZC4xFDASBgNVBAsMC1NlY3VyZSBCb290MSswKQYD
+VQQDDCJDYW5vbmljYWwgTHRkLiBTZWN1cmUgQm9vdCBTaWduaW5nMIIBIjANBgkq
+hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyV+bYo8LsGSCrL7J4mLjS9KfHorVYRor
+XTj0t865mrhDuEOXd6tPfwxwRgv8f23GbeqAXgHSt2Yeh94NbdBBl6ilrwxjT/d8
+wlLMoDGpu4ldmR5Gb1VzuXZp7NfB/CHWxgfnT70i3uSoWy3blTQZl9YoSyFMyrsd
+eaYXf1r5Z+ZceEU9EG2wF1kmEcVX439Ogrr2LE7IN03/hRWER+DtO3x/vK/pAQWn
+DG/D6Y2jzr6m4808tVgsnsIDHGAiNzn/QQLBKaRlUf8zNKpCFfmVePwt9dqKhXyC
+nfs3LGulqN98VQuALjywY+HNOEiJ6BQGC4K8/dQHaBsPPtkV3ZQRGwIDAQABo4Gg
+MIGdMAwGA1UdEwEB/wQCMAAwHwYDVR0lBBgwFgYIKwYBBQUHAwMGCisGAQQBgjcK
+AwYwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRl
+MB0GA1UdDgQWBBRhSCqigw0Ksq1a8QtyUNqQM93O8DAfBgNVHSMEGDAWgBStkZkL
+wiqx9RcEjCO2ZVomjjRaYzANBgkqhkiG9w0BAQsFAAOCAQEAj4qhBh8ptwpK1cX9
+gasl6sB94vxqlqB5k2fuBQ4lEiXkWvaqGvES8wWNh17xWlzLjSNzZR0Vud4ia9ZJ
+Z8mjxtdiTly1+QODQIHch5w8PxwNUZ+UZQqESGfkovimSvDnzc29lOMJ0l0tFhsF
+FQvLRLQ+YUIixCpcTsUdo+LgUrLr9Isr3Dg5XfuIoVZlXytPJv8GeBAS64xdMuPG
+Ra8lm6D/ju9HCaPpizeSkml2fjQ7kgVnTrAl7bxeX4+01spA/+TiMSMMhSWuDFUB
+7OVHXt9bvBQz48b1GLbZ992ztKEx01pcXX0+vwrk5Oi0WX07tIyjG7Ugo7k+hG+M
+IQDDOQ==
+-----END CERTIFICATE-----
--- linux-xilinx-zynqmp-5.4.0.orig/debian/revoked-certs/canonical-uefi-2017-all.pem
+++ linux-xilinx-zynqmp-5.4.0/debian/revoked-certs/canonical-uefi-2017-all.pem
@@ -0,0 +1,86 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 2 (0x2)
+        Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C = GB, ST = Isle of Man, L = Douglas, O = Canonical Ltd., CN = Canonical Ltd. Master Certificate Authority
+        Validity
+            Not Before: Sep 26 21:52:11 2017 GMT
+            Not After : Sep 25 21:52:11 2047 GMT
+        Subject: C = GB, ST = Isle of Man, O = Canonical Ltd., OU = Secure Boot, CN = Canonical Ltd. Secure Boot Signing (2017)
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (2048 bit)
+                Modulus:
+                    00:ef:9f:fa:9f:19:3a:9d:38:23:91:cc:c4:f9:42:
+                    e0:f8:54:12:82:dc:97:2c:d6:5b:c1:35:eb:ff:4a:
+                    74:06:b5:9d:32:aa:7b:f3:fc:31:5a:34:3e:a1:a4:
+                    44:db:7b:6d:16:af:35:76:e0:9b:99:ad:21:11:c6:
+                    12:4b:ae:24:8f:bb:d3:b2:00:fe:c5:1d:9b:3a:1a:
+                    4a:6c:ca:fa:16:37:85:22:f9:ff:22:fc:40:e0:58:
+                    35:c1:39:27:b4:c6:42:1a:96:d8:a5:c5:95:2e:f7:
+                    c5:1e:21:6e:36:84:f7:a9:a1:e1:f1:03:08:96:65:
+                    71:f8:eb:83:cf:82:f7:9a:44:58:72:00:14:39:29:
+                    4b:e9:78:2f:65:20:b3:80:76:3b:ba:0d:2d:46:f6:
+                    37:05:e7:05:fe:bd:6c:c7:a2:65:b5:06:6e:07:24:
+                    99:a1:c1:cf:e1:0e:5e:49:41:71:17:a8:50:e7:38:
+                    99:e5:6e:b6:db:9f:63:db:56:f4:9c:7d:89:f6:d2:
+                    03:6c:99:83:e0:99:23:39:36:bd:cb:b5:26:7c:7d:
+                    b0:c6:fe:82:7c:52:ed:f9:2c:8f:79:71:3d:a9:2f:
+                    b5:aa:7e:77:a0:fd:69:f9:97:10:a8:b2:c6:7d:88:
+                    9e:a2:19:bd:31:b8:02:2d:34:4d:9d:98:60:82:ad:
+                    04:ff
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:FALSE
+            X509v3 Extended Key Usage: 
+                Code Signing, 1.3.6.1.4.1.311.10.3.6
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                24:2A:DE:75:AC:4A:15:E5:0D:50:C8:4B:0D:45:FF:3E:AE:70:7A:03
+            X509v3 Authority Key Identifier: 
+                AD:91:99:0B:C2:2A:B1:F5:17:04:8C:23:B6:65:5A:26:8E:34:5A:63
+    Signature Algorithm: sha256WithRSAEncryption
+    Signature Value:
+        00:b2:b7:57:b5:2b:5d:16:d3:04:88:6a:d7:77:d5:0d:89:f1:
+        d2:6e:11:d1:8e:f5:62:05:c4:6a:57:df:eb:d2:86:68:f2:fd:
+        a7:37:11:3c:f4:ce:5d:fe:32:5f:31:a2:6b:3a:da:28:c2:88:
+        fa:7f:70:b5:25:99:ea:27:9a:56:6a:9d:b2:0f:14:99:e2:b7:
+        c6:39:1e:8e:a7:76:31:d9:ed:c5:05:8d:48:ae:1b:68:18:14:
+        51:a1:7d:f6:c7:df:cb:9d:eb:a4:3b:0b:ff:c2:07:c5:42:bc:
+        0d:b2:11:fa:37:17:2b:1c:b5:84:48:2d:f9:31:4a:57:49:8e:
+        61:a6:82:11:06:4c:34:ea:9c:2a:47:4d:eb:e0:26:af:da:d2:
+        c2:08:a0:37:35:7b:73:71:de:0b:c4:ba:c8:34:de:20:04:03:
+        6f:46:26:0d:b9:91:02:5b:71:76:cc:45:e4:08:d0:a6:dd:a4:
+        50:d3:d9:04:91:2b:d9:5c:34:88:fc:c2:37:fd:c6:d4:3e:57:
+        f7:6b:ba:7b:d7:02:7a:84:0c:c8:c1:19:cc:bc:fa:52:d5:7f:
+        b3:35:c4:53:5d:70:0a:f6:44:60:8d:a9:11:7a:1b:7d:ae:7b:
+        20:5a:4c:8d:44:f6:c1:a9:61:cb:dc:cb:90:37:d5:28:24:73:
+        87:d0:e0:d8
+-----BEGIN CERTIFICATE-----
+MIIEKDCCAxCgAwIBAgIBAjANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBhMCR0Ix
+FDASBgNVBAgMC0lzbGUgb2YgTWFuMRAwDgYDVQQHDAdEb3VnbGFzMRcwFQYDVQQK
+DA5DYW5vbmljYWwgTHRkLjE0MDIGA1UEAwwrQ2Fub25pY2FsIEx0ZC4gTWFzdGVy
+IENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xNzA5MjYyMTUyMTFaFw00NzA5MjUy
+MTUyMTFaMIGGMQswCQYDVQQGEwJHQjEUMBIGA1UECAwLSXNsZSBvZiBNYW4xFzAV
+BgNVBAoMDkNhbm9uaWNhbCBMdGQuMRQwEgYDVQQLDAtTZWN1cmUgQm9vdDEyMDAG
+A1UEAwwpQ2Fub25pY2FsIEx0ZC4gU2VjdXJlIEJvb3QgU2lnbmluZyAoMjAxNykw
+ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDvn/qfGTqdOCORzMT5QuD4
+VBKC3Jcs1lvBNev/SnQGtZ0yqnvz/DFaND6hpETbe20WrzV24JuZrSERxhJLriSP
+u9OyAP7FHZs6GkpsyvoWN4Ui+f8i/EDgWDXBOSe0xkIaltilxZUu98UeIW42hPep
+oeHxAwiWZXH464PPgveaRFhyABQ5KUvpeC9lILOAdju6DS1G9jcF5wX+vWzHomW1
+Bm4HJJmhwc/hDl5JQXEXqFDnOJnlbrbbn2PbVvScfYn20gNsmYPgmSM5Nr3LtSZ8
+fbDG/oJ8Uu35LI95cT2pL7Wqfneg/Wn5lxCossZ9iJ6iGb0xuAItNE2dmGCCrQT/
+AgMBAAGjgaAwgZ0wDAYDVR0TAQH/BAIwADAfBgNVHSUEGDAWBggrBgEFBQcDAwYK
+KwYBBAGCNwoDBjAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2Vy
+dGlmaWNhdGUwHQYDVR0OBBYEFCQq3nWsShXlDVDISw1F/z6ucHoDMB8GA1UdIwQY
+MBaAFK2RmQvCKrH1FwSMI7ZlWiaONFpjMA0GCSqGSIb3DQEBCwUAA4IBAQAAsrdX
+tStdFtMEiGrXd9UNifHSbhHRjvViBcRqV9/r0oZo8v2nNxE89M5d/jJfMaJrOtoo
+woj6f3C1JZnqJ5pWap2yDxSZ4rfGOR6Op3Yx2e3FBY1IrhtoGBRRoX32x9/Lneuk
+Owv/wgfFQrwNshH6NxcrHLWESC35MUpXSY5hpoIRBkw06pwqR03r4Cav2tLCCKA3
+NXtzcd4LxLrINN4gBANvRiYNuZECW3F2zEXkCNCm3aRQ09kEkSvZXDSI/MI3/cbU
+Plf3a7p71wJ6hAzIwRnMvPpS1X+zNcRTXXAK9kRgjakReht9rnsgWkyNRPbBqWHL
+3MuQN9UoJHOH0ODY
+-----END CERTIFICATE-----
--- linux-xilinx-zynqmp-5.4.0.orig/debian/revoked-certs/canonical-uefi-2018-all.pem
+++ linux-xilinx-zynqmp-5.4.0/debian/revoked-certs/canonical-uefi-2018-all.pem
@@ -0,0 +1,86 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 3 (0x3)
+        Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C = GB, ST = Isle of Man, L = Douglas, O = Canonical Ltd., CN = Canonical Ltd. Master Certificate Authority
+        Validity
+            Not Before: Oct 26 18:31:14 2018 GMT
+            Not After : Oct 24 18:31:14 2048 GMT
+        Subject: C = GB, ST = Isle of Man, O = Canonical Ltd., OU = Secure Boot, CN = Canonical Ltd. Secure Boot Signing (ESM 2018)
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (2048 bit)
+                Modulus:
+                    00:bf:6a:e5:6d:55:7a:ec:7a:11:37:45:9c:4c:8f:
+                    6b:2d:56:d3:74:2b:32:ac:84:2d:ba:cb:cc:ec:8d:
+                    92:22:69:48:a5:d4:f6:75:11:66:2f:cb:b2:fd:9e:
+                    56:ab:e6:f1:52:8e:75:3e:50:bd:25:b3:50:fc:ef:
+                    3d:76:f3:3f:7f:03:f6:e2:a1:25:69:5c:14:98:54:
+                    bd:11:bf:e9:a5:ac:46:91:4b:1d:de:b7:18:2b:c8:
+                    22:83:15:a7:4a:00:8d:9d:e4:c0:da:f7:41:02:fd:
+                    9f:5f:79:93:56:cc:86:e1:b5:e0:39:0e:3c:a2:5b:
+                    fe:c0:56:f0:92:50:5a:2b:67:67:93:56:d7:7a:75:
+                    99:6a:25:b4:63:a8:5f:69:7e:3a:49:58:2a:a7:80:
+                    f6:5a:b4:be:b2:be:a8:8c:45:41:c9:f2:fc:76:a8:
+                    65:ef:99:29:0d:c9:9c:54:6b:0a:f0:4a:0e:61:0d:
+                    ed:99:32:af:12:e2:12:7b:9f:7b:ec:05:c4:e0:b6:
+                    d5:c3:71:28:ae:dd:0b:ba:97:ad:68:0b:76:e9:bf:
+                    e7:01:7e:64:54:39:23:85:36:c8:9d:dd:27:a1:ff:
+                    df:46:36:14:7e:cb:cc:a1:cd:49:0b:6d:c2:0c:45:
+                    99:56:58:7c:87:0d:59:9a:dc:4a:39:3b:1d:d9:15:
+                    2e:b5
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:FALSE
+            X509v3 Extended Key Usage: 
+                Code Signing, 1.3.6.1.4.1.311.10.3.6
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                36:51:88:C1:D3:74:D6:B0:7C:3C:8F:24:0F:8E:F7:22:43:3D:6A:8B
+            X509v3 Authority Key Identifier: 
+                AD:91:99:0B:C2:2A:B1:F5:17:04:8C:23:B6:65:5A:26:8E:34:5A:63
+    Signature Algorithm: sha256WithRSAEncryption
+    Signature Value:
+        4c:0f:cd:77:60:b4:6f:53:87:f3:3c:4f:e6:81:5f:a7:1c:cc:
+        60:29:b6:34:6c:4d:08:9b:e2:d2:bd:f6:17:1a:62:79:b8:17:
+        bc:a2:60:59:fd:03:51:c3:b7:6b:de:73:b3:48:95:f5:0b:aa:
+        b6:3c:b4:34:dc:1d:0b:c4:97:62:87:e7:48:d5:8f:c9:ea:e8:
+        91:8f:2a:40:cd:b7:b3:ee:b2:98:9e:fb:37:31:29:e6:8e:2f:
+        0a:39:99:1e:c6:aa:b8:05:62:85:d3:a8:3e:60:38:98:0f:f0:
+        fe:c7:ab:01:a5:6a:a5:7f:70:a6:26:94:76:23:2f:08:89:74:
+        97:c2:2a:ca:22:3e:7a:ea:22:22:08:07:f4:bb:f6:bc:69:9c:
+        4e:44:33:e2:8e:70:17:b0:9b:cb:33:94:66:6d:ff:9a:7d:e9:
+        50:b2:e8:90:14:e4:2b:91:cb:a0:c5:2e:0e:cf:19:ef:44:ef:
+        84:f0:bd:57:9e:26:c2:63:3d:df:fc:a1:84:de:5c:d7:5f:3b:
+        fb:94:61:f0:93:89:1f:cf:c3:b2:d1:90:97:35:7d:b9:8a:ad:
+        e6:05:f0:e8:3b:a1:7c:af:2b:c4:af:18:33:2e:5e:87:db:9d:
+        80:b5:04:fd:00:d0:60:ab:ff:85:77:0f:cb:47:22:c9:b2:85:
+        a8:48:16:e2
+-----BEGIN CERTIFICATE-----
+MIIELDCCAxSgAwIBAgIBAzANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBhMCR0Ix
+FDASBgNVBAgMC0lzbGUgb2YgTWFuMRAwDgYDVQQHDAdEb3VnbGFzMRcwFQYDVQQK
+DA5DYW5vbmljYWwgTHRkLjE0MDIGA1UEAwwrQ2Fub25pY2FsIEx0ZC4gTWFzdGVy
+IENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xODEwMjYxODMxMTRaFw00ODEwMjQx
+ODMxMTRaMIGKMQswCQYDVQQGEwJHQjEUMBIGA1UECAwLSXNsZSBvZiBNYW4xFzAV
+BgNVBAoMDkNhbm9uaWNhbCBMdGQuMRQwEgYDVQQLDAtTZWN1cmUgQm9vdDE2MDQG
+A1UEAwwtQ2Fub25pY2FsIEx0ZC4gU2VjdXJlIEJvb3QgU2lnbmluZyAoRVNNIDIw
+MTgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv2rlbVV67HoRN0Wc
+TI9rLVbTdCsyrIQtusvM7I2SImlIpdT2dRFmL8uy/Z5Wq+bxUo51PlC9JbNQ/O89
+dvM/fwP24qElaVwUmFS9Eb/ppaxGkUsd3rcYK8gigxWnSgCNneTA2vdBAv2fX3mT
+VsyG4bXgOQ48olv+wFbwklBaK2dnk1bXenWZaiW0Y6hfaX46SVgqp4D2WrS+sr6o
+jEVByfL8dqhl75kpDcmcVGsK8EoOYQ3tmTKvEuISe5977AXE4LbVw3Eort0Lupet
+aAt26b/nAX5kVDkjhTbInd0nof/fRjYUfsvMoc1JC23CDEWZVlh8hw1ZmtxKOTsd
+2RUutQIDAQABo4GgMIGdMAwGA1UdEwEB/wQCMAAwHwYDVR0lBBgwFgYIKwYBBQUH
+AwMGCisGAQQBgjcKAwYwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVk
+IENlcnRpZmljYXRlMB0GA1UdDgQWBBQ2UYjB03TWsHw8jyQPjvciQz1qizAfBgNV
+HSMEGDAWgBStkZkLwiqx9RcEjCO2ZVomjjRaYzANBgkqhkiG9w0BAQsFAAOCAQEA
+TA/Nd2C0b1OH8zxP5oFfpxzMYCm2NGxNCJvi0r32FxpiebgXvKJgWf0DUcO3a95z
+s0iV9Quqtjy0NNwdC8SXYofnSNWPyerokY8qQM23s+6ymJ77NzEp5o4vCjmZHsaq
+uAVihdOoPmA4mA/w/serAaVqpX9wpiaUdiMvCIl0l8IqyiI+euoiIggH9Lv2vGmc
+TkQz4o5wF7CbyzOUZm3/mn3pULLokBTkK5HLoMUuDs8Z70TvhPC9V54mwmM93/yh
+hN5c1187+5Rh8JOJH8/DstGQlzV9uYqt5gXw6DuhfK8rxK8YMy5eh9udgLUE/QDQ
+YKv/hXcPy0ciybKFqEgW4g==
+-----END CERTIFICATE-----
--- linux-xilinx-zynqmp-5.4.0.orig/debian/revoked-certs/canonical-uefi-2019-all.pem
+++ linux-xilinx-zynqmp-5.4.0/debian/revoked-certs/canonical-uefi-2019-all.pem
@@ -0,0 +1,86 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 4 (0x4)
+        Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C = GB, ST = Isle of Man, L = Douglas, O = Canonical Ltd., CN = Canonical Ltd. Master Certificate Authority
+        Validity
+            Not Before: Sep 18 16:10:17 2019 GMT
+            Not After : Sep 16 16:10:17 2049 GMT
+        Subject: C = GB, ST = Isle of Man, O = Canonical Ltd., OU = Secure Boot, CN = Canonical Ltd. Secure Boot Signing (2019)
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (2048 bit)
+                Modulus:
+                    00:e6:47:d8:75:e5:87:59:26:87:83:7d:5b:7a:b8:
+                    58:3d:7c:ef:36:f8:a0:7a:b7:14:56:58:7d:01:f1:
+                    1c:3b:8c:e6:5b:03:77:7d:a0:ed:47:0a:45:e6:75:
+                    5c:de:95:38:0d:38:fa:41:79:89:56:31:87:e7:a3:
+                    9a:36:70:b6:cf:24:2f:99:26:89:08:39:0e:14:c3:
+                    35:be:02:8b:52:e1:8e:7b:0c:a6:9d:78:ff:01:60:
+                    d7:f5:c3:d5:f0:5e:dc:e4:23:09:59:72:93:d3:b5:
+                    22:af:7c:cd:e0:84:0f:af:11:2d:bc:c6:72:42:af:
+                    ea:67:63:c4:10:41:78:02:80:62:0d:43:74:b4:1c:
+                    ed:50:d7:94:f1:b0:bb:f9:57:80:e4:69:0f:83:4b:
+                    a2:e6:2c:4a:9a:e1:7d:7c:62:19:29:27:97:1f:4c:
+                    f1:85:f0:39:f5:31:9f:3a:39:0e:d4:4d:07:3a:40:
+                    55:4b:a6:6c:9d:04:89:51:2d:7c:b0:ef:40:b5:42:
+                    29:16:cc:65:73:38:62:21:f6:e3:2c:17:50:9d:74:
+                    34:4e:df:7c:4a:33:a4:bb:40:cf:d5:e5:ed:05:07:
+                    cd:4c:f9:af:7f:a6:5c:b9:f7:c5:16:45:4e:44:40:
+                    d7:85:32:de:ac:e5:75:ad:9b:d7:c0:26:33:1f:77:
+                    a5:37
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:FALSE
+            X509v3 Extended Key Usage: 
+                Code Signing, 1.3.6.1.4.1.311.10.3.6
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                C0:74:6F:D6:C5:DA:3A:E8:27:86:46:51:AD:66:AE:47:FE:24:B3:E8
+            X509v3 Authority Key Identifier: 
+                AD:91:99:0B:C2:2A:B1:F5:17:04:8C:23:B6:65:5A:26:8E:34:5A:63
+    Signature Algorithm: sha256WithRSAEncryption
+    Signature Value:
+        aa:12:6c:d1:9d:6a:da:f0:ec:7c:17:46:3b:57:b8:d6:76:5f:
+        24:e6:06:a2:0a:55:1f:2f:d3:5e:8f:de:cf:02:f2:ff:e0:dd:
+        d3:c7:bd:75:59:aa:cd:34:f3:28:80:73:cc:28:69:e7:a2:70:
+        88:a2:c7:dc:66:f0:92:0e:ff:64:bf:30:04:54:01:1b:96:ad:
+        15:c5:61:fd:32:61:d7:5e:b5:ba:91:fd:31:fc:6b:15:df:ee:
+        22:d9:e4:1f:f3:cc:8b:0c:9f:f5:e8:f7:e2:62:3f:40:52:c9:
+        f0:f1:1c:63:fc:6c:90:e1:5b:74:03:b9:df:d1:3e:a8:ec:db:
+        2b:6e:83:6f:9f:7f:ba:b4:79:fc:3d:e7:12:2f:4a:e7:17:8c:
+        2b:77:a5:90:74:3c:bd:cf:75:83:0d:1a:95:d5:56:ef:07:9b:
+        a6:b3:31:e3:8c:97:ce:68:11:b5:7b:25:03:72:1c:ea:67:e9:
+        7c:3e:73:c7:7c:3e:fc:f5:ae:8a:b2:07:0d:15:6a:66:09:d7:
+        23:b9:5d:80:7a:26:d6:b6:22:30:aa:84:af:c0:42:e9:75:c3:
+        59:ab:a3:84:87:6b:0c:b7:ab:4e:92:69:ae:2c:82:6f:ab:01:
+        24:ab:ff:78:6d:59:85:c2:3b:23:c0:bd:0d:d8:6e:3a:29:82:
+        e1:c4:5f:db
+-----BEGIN CERTIFICATE-----
+MIIEKDCCAxCgAwIBAgIBBDANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBhMCR0Ix
+FDASBgNVBAgMC0lzbGUgb2YgTWFuMRAwDgYDVQQHDAdEb3VnbGFzMRcwFQYDVQQK
+DA5DYW5vbmljYWwgTHRkLjE0MDIGA1UEAwwrQ2Fub25pY2FsIEx0ZC4gTWFzdGVy
+IENlcnRpZmljYXRlIEF1dGhvcml0eTAeFw0xOTA5MTgxNjEwMTdaFw00OTA5MTYx
+NjEwMTdaMIGGMQswCQYDVQQGEwJHQjEUMBIGA1UECAwLSXNsZSBvZiBNYW4xFzAV
+BgNVBAoMDkNhbm9uaWNhbCBMdGQuMRQwEgYDVQQLDAtTZWN1cmUgQm9vdDEyMDAG
+A1UEAwwpQ2Fub25pY2FsIEx0ZC4gU2VjdXJlIEJvb3QgU2lnbmluZyAoMjAxOSkw
+ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDmR9h15YdZJoeDfVt6uFg9
+fO82+KB6txRWWH0B8Rw7jOZbA3d9oO1HCkXmdVzelTgNOPpBeYlWMYfno5o2cLbP
+JC+ZJokIOQ4UwzW+AotS4Y57DKadeP8BYNf1w9XwXtzkIwlZcpPTtSKvfM3ghA+v
+ES28xnJCr+pnY8QQQXgCgGINQ3S0HO1Q15TxsLv5V4DkaQ+DS6LmLEqa4X18Yhkp
+J5cfTPGF8Dn1MZ86OQ7UTQc6QFVLpmydBIlRLXyw70C1QikWzGVzOGIh9uMsF1Cd
+dDRO33xKM6S7QM/V5e0FB81M+a9/ply598UWRU5EQNeFMt6s5XWtm9fAJjMfd6U3
+AgMBAAGjgaAwgZ0wDAYDVR0TAQH/BAIwADAfBgNVHSUEGDAWBggrBgEFBQcDAwYK
+KwYBBAGCNwoDBjAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2Vy
+dGlmaWNhdGUwHQYDVR0OBBYEFMB0b9bF2jroJ4ZGUa1mrkf+JLPoMB8GA1UdIwQY
+MBaAFK2RmQvCKrH1FwSMI7ZlWiaONFpjMA0GCSqGSIb3DQEBCwUAA4IBAQCqEmzR
+nWra8Ox8F0Y7V7jWdl8k5gaiClUfL9Nej97PAvL/4N3Tx711WarNNPMogHPMKGnn
+onCIosfcZvCSDv9kvzAEVAEblq0VxWH9MmHXXrW6kf0x/GsV3+4i2eQf88yLDJ/1
+6PfiYj9AUsnw8Rxj/GyQ4Vt0A7nf0T6o7NsrboNvn3+6tHn8PecSL0rnF4wrd6WQ
+dDy9z3WDDRqV1VbvB5umszHjjJfOaBG1eyUDchzqZ+l8PnPHfD789a6KsgcNFWpm
+CdcjuV2AeibWtiIwqoSvwELpdcNZq6OEh2sMt6tOkmmuLIJvqwEkq/94bVmFwjsj
+wL0N2G46KYLhxF/b
+-----END CERTIFICATE-----
--- linux-xilinx-zynqmp-5.4.0.orig/debian/revoked-certs/canonical-uefi-2021v1-all.pem
+++ linux-xilinx-zynqmp-5.4.0/debian/revoked-certs/canonical-uefi-2021v1-all.pem
@@ -0,0 +1,86 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 6 (0x6)
+        Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C = GB, ST = Isle of Man, L = Douglas, O = Canonical Ltd., CN = Canonical Ltd. Master Certificate Authority
+        Validity
+            Not Before: Sep 23 19:29:32 2021 GMT
+            Not After : Sep 22 19:29:32 2051 GMT
+        Subject: C = GB, ST = Isle of Man, O = Canonical Ltd., OU = Secure Boot, CN = Canonical Ltd. Secure Boot Signing (2021 v1)
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (2048 bit)
+                Modulus:
+                    00:aa:b8:34:5b:b6:ae:44:bf:41:e1:78:11:b9:7a:
+                    c8:88:b3:b0:26:50:10:9c:98:d1:f3:98:9f:23:50:
+                    64:f6:39:dd:50:3a:23:44:53:65:fc:f3:9f:f5:a5:
+                    8b:ae:8b:df:47:9f:e9:d5:a0:92:19:f1:21:ea:cc:
+                    59:3a:74:df:45:71:bc:de:64:15:a5:f6:db:ca:71:
+                    fa:19:d4:44:0d:12:ec:47:3a:43:e2:f2:dd:8b:fe:
+                    0d:7b:dc:4d:db:53:06:22:61:e5:8b:35:49:b6:33:
+                    c4:0a:69:5f:5b:81:09:84:6b:42:33:18:09:9d:a0:
+                    35:f7:9c:1e:de:6e:de:90:69:1a:e8:32:e4:49:ad:
+                    c3:31:e9:f8:4a:a2:28:1d:db:0d:29:b6:48:0a:44:
+                    93:86:41:62:8f:73:97:60:10:8a:74:46:66:55:fe:
+                    a0:95:35:9e:ef:9f:af:11:fa:5b:a3:7c:c2:35:64:
+                    11:67:28:1e:14:0a:7d:68:61:9c:cd:c7:46:39:30:
+                    31:79:94:56:b3:45:16:9a:b5:77:66:fe:41:43:0f:
+                    00:48:6e:99:dd:0c:d4:47:2c:86:8c:50:04:61:20:
+                    dd:aa:8e:73:4f:21:b4:ee:09:4d:d3:40:01:d0:f2:
+                    a7:5b:7d:05:3d:c1:e7:65:26:aa:8c:9a:58:5a:7c:
+                    6d:6f
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:FALSE
+            X509v3 Extended Key Usage: 
+                Code Signing, 1.3.6.1.4.1.311.10.3.6
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                A8:D5:4B:BB:38:25:CF:B9:4F:A1:3C:9F:8A:59:4A:19:5C:10:7B:8D
+            X509v3 Authority Key Identifier: 
+                AD:91:99:0B:C2:2A:B1:F5:17:04:8C:23:B6:65:5A:26:8E:34:5A:63
+    Signature Algorithm: sha256WithRSAEncryption
+    Signature Value:
+        24:25:25:7e:01:a5:c8:3d:54:8c:1b:05:73:d1:06:d8:db:d4:
+        3a:71:d5:19:9d:97:1c:85:3c:ca:38:5a:0c:25:25:39:1a:67:
+        bc:6c:9d:98:6c:f3:7d:5f:b7:40:f9:73:a0:f5:7b:40:a8:66:
+        a5:f1:53:b1:78:80:24:3f:19:50:2f:02:09:ec:a1:8a:e6:0d:
+        df:c4:ae:24:9e:69:0d:5c:dc:44:4c:38:3a:53:4e:4b:a1:4b:
+        92:9f:43:a4:9d:1e:76:33:18:1b:bf:62:e5:f5:bc:93:3c:4e:
+        21:d5:5b:20:69:11:28:c1:c5:93:b5:8e:96:1d:1b:ca:72:79:
+        24:de:67:2a:50:9d:ce:8b:41:dd:3e:82:dd:a5:04:75:54:fb:
+        35:70:98:87:b4:f3:ea:41:23:23:80:0e:99:d7:03:16:ee:7e:
+        11:e2:c8:29:ab:73:c5:6d:5c:a8:2f:32:03:9f:8e:66:d6:cb:
+        54:84:55:75:ab:9a:dd:95:fd:05:1e:11:85:37:1e:63:d2:f4:
+        7f:34:64:32:a1:63:91:91:50:39:14:1a:ea:54:78:e6:0d:04:
+        23:c7:83:51:c5:25:27:07:6c:f8:65:b7:da:95:89:76:83:cc:
+        f3:7e:06:74:d3:6c:ef:e9:17:de:29:1e:ab:5c:d7:ec:df:f1:
+        98:b8:e9:66
+-----BEGIN CERTIFICATE-----
+MIIELTCCAxWgAwIBAgIBBjANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBhMCR0Ix
+FDASBgNVBAgMC0lzbGUgb2YgTWFuMRAwDgYDVQQHDAdEb3VnbGFzMRcwFQYDVQQK
+DA5DYW5vbmljYWwgTHRkLjE0MDIGA1UEAwwrQ2Fub25pY2FsIEx0ZC4gTWFzdGVy
+IENlcnRpZmljYXRlIEF1dGhvcml0eTAgFw0yMTA5MjMxOTI5MzJaGA8yMDUxMDky
+MjE5MjkzMlowgYkxCzAJBgNVBAYTAkdCMRQwEgYDVQQIDAtJc2xlIG9mIE1hbjEX
+MBUGA1UECgwOQ2Fub25pY2FsIEx0ZC4xFDASBgNVBAsMC1NlY3VyZSBCb290MTUw
+MwYDVQQDDCxDYW5vbmljYWwgTHRkLiBTZWN1cmUgQm9vdCBTaWduaW5nICgyMDIx
+IHYxKTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKq4NFu2rkS/QeF4
+Ebl6yIizsCZQEJyY0fOYnyNQZPY53VA6I0RTZfzzn/Wli66L30ef6dWgkhnxIerM
+WTp030VxvN5kFaX228px+hnURA0S7Ec6Q+Ly3Yv+DXvcTdtTBiJh5Ys1SbYzxApp
+X1uBCYRrQjMYCZ2gNfecHt5u3pBpGugy5EmtwzHp+EqiKB3bDSm2SApEk4ZBYo9z
+l2AQinRGZlX+oJU1nu+frxH6W6N8wjVkEWcoHhQKfWhhnM3HRjkwMXmUVrNFFpq1
+d2b+QUMPAEhumd0M1EcshoxQBGEg3aqOc08htO4JTdNAAdDyp1t9BT3B52Umqoya
+WFp8bW8CAwEAAaOBoDCBnTAMBgNVHRMBAf8EAjAAMB8GA1UdJQQYMBYGCCsGAQUF
+BwMDBgorBgEEAYI3CgMGMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRl
+ZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUqNVLuzglz7lPoTyfillKGVwQe40wHwYD
+VR0jBBgwFoAUrZGZC8IqsfUXBIwjtmVaJo40WmMwDQYJKoZIhvcNAQELBQADggEB
+ACQlJX4Bpcg9VIwbBXPRBtjb1Dpx1RmdlxyFPMo4WgwlJTkaZ7xsnZhs831ft0D5
+c6D1e0CoZqXxU7F4gCQ/GVAvAgnsoYrmDd/EriSeaQ1c3ERMODpTTkuhS5KfQ6Sd
+HnYzGBu/YuX1vJM8TiHVWyBpESjBxZO1jpYdG8pyeSTeZypQnc6LQd0+gt2lBHVU
++zVwmIe08+pBIyOADpnXAxbufhHiyCmrc8VtXKgvMgOfjmbWy1SEVXWrmt2V/QUe
+EYU3HmPS9H80ZDKhY5GRUDkUGupUeOYNBCPHg1HFJScHbPhlt9qViXaDzPN+BnTT
+bO/pF94pHqtc1+zf8Zi46WY=
+-----END CERTIFICATE-----
--- linux-xilinx-zynqmp-5.4.0.orig/debian/revoked-certs/canonical-uefi-2021v2-all.pem
+++ linux-xilinx-zynqmp-5.4.0/debian/revoked-certs/canonical-uefi-2021v2-all.pem
@@ -0,0 +1,86 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 7 (0x7)
+        Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C = GB, ST = Isle of Man, L = Douglas, O = Canonical Ltd., CN = Canonical Ltd. Master Certificate Authority
+        Validity
+            Not Before: Sep 23 19:29:42 2021 GMT
+            Not After : Sep 22 19:29:42 2051 GMT
+        Subject: C = GB, ST = Isle of Man, O = Canonical Ltd., OU = Secure Boot, CN = Canonical Ltd. Secure Boot Signing (2021 v2)
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (2048 bit)
+                Modulus:
+                    00:ba:06:8b:ee:58:b7:8b:49:7b:53:7a:d1:df:02:
+                    e3:f2:d8:b0:8c:03:5c:f4:2d:0b:d8:18:3b:23:fa:
+                    68:b0:e8:e9:9d:dc:a2:eb:5e:d3:06:a9:28:d4:9f:
+                    14:b6:1e:1c:1d:ef:69:0e:7f:44:f2:cc:4a:f1:b1:
+                    d0:71:30:6a:50:1e:b0:d3:f8:a4:19:d0:4a:f1:e3:
+                    eb:7a:e5:57:4c:a1:fb:d1:87:b9:48:e0:55:37:52:
+                    f9:de:99:2e:95:85:36:ce:d3:1d:67:2f:14:cb:7f:
+                    05:82:75:21:b6:aa:a5:14:ac:da:4a:f4:fe:fa:5c:
+                    33:49:3d:6f:de:fd:9d:75:ba:e2:c4:02:38:b5:69:
+                    f5:ff:a8:67:4b:3a:e0:34:f6:3b:07:03:a5:7e:59:
+                    6f:3a:d2:28:a4:2f:25:ac:d8:a9:1f:59:52:5d:24:
+                    36:58:51:b5:f0:12:a8:d3:78:56:57:b1:e0:a9:df:
+                    14:05:65:7c:b5:a5:00:f0:88:39:14:44:18:85:2d:
+                    0c:28:69:7b:b9:b4:1c:47:6f:43:66:4c:22:ad:f7:
+                    f6:19:75:e1:14:2c:0d:33:3f:c1:3f:fc:73:56:b2:
+                    68:05:b5:92:03:9b:65:6b:81:80:92:35:03:9b:66:
+                    68:58:c5:66:11:b6:8c:7f:05:09:9a:45:a6:0e:5e:
+                    5f:bf
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:FALSE
+            X509v3 Extended Key Usage: 
+                Code Signing, 1.3.6.1.4.1.311.10.3.6
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                4C:F0:46:89:2D:6F:D3:C9:A5:B0:3F:98:D8:45:F9:08:51:DC:6A:8C
+            X509v3 Authority Key Identifier: 
+                AD:91:99:0B:C2:2A:B1:F5:17:04:8C:23:B6:65:5A:26:8E:34:5A:63
+    Signature Algorithm: sha256WithRSAEncryption
+    Signature Value:
+        93:9d:49:7d:9f:3e:3e:27:79:97:d9:c2:fc:0b:f7:30:b7:f4:
+        78:b2:c9:e4:5e:42:d3:27:26:70:cf:88:96:d1:f2:ea:a0:75:
+        7e:3c:f6:b7:d2:e7:95:30:e3:a6:67:a7:ee:b9:53:8f:fd:b2:
+        cb:db:e1:98:32:be:98:79:09:46:c6:63:6a:57:87:4d:b2:26:
+        46:f6:34:5e:18:75:ca:82:80:8e:33:c2:1d:c7:76:d7:14:57:
+        ef:2e:0e:9e:58:5c:81:8e:ed:53:2c:07:46:0a:8a:fc:2f:f5:
+        b2:c8:58:f5:fa:fa:bb:f9:7d:47:13:39:f0:f2:1c:15:9c:75:
+        90:40:bd:08:04:b3:6a:de:c2:cd:34:21:7e:ba:31:48:bc:a1:
+        23:bc:ee:93:b2:62:96:27:30:86:c2:d4:f7:b4:e6:3c:71:47:
+        37:84:ff:3d:0c:1e:ec:f3:0e:da:6b:dc:64:7a:b8:c0:7e:45:
+        13:09:bf:02:b3:b7:5b:6d:09:2d:6a:4e:0b:93:94:29:4c:a6:
+        c3:c7:05:fa:69:08:04:53:3c:4c:64:c0:7e:89:00:91:1b:a6:
+        c2:d7:ea:c4:db:86:38:fe:66:03:85:7b:fc:39:24:99:4c:2a:
+        3e:10:8b:91:c3:6e:20:9d:0c:ee:51:70:b5:98:58:f3:5c:ac:
+        16:98:7b:ce
+-----BEGIN CERTIFICATE-----
+MIIELTCCAxWgAwIBAgIBBzANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBhMCR0Ix
+FDASBgNVBAgMC0lzbGUgb2YgTWFuMRAwDgYDVQQHDAdEb3VnbGFzMRcwFQYDVQQK
+DA5DYW5vbmljYWwgTHRkLjE0MDIGA1UEAwwrQ2Fub25pY2FsIEx0ZC4gTWFzdGVy
+IENlcnRpZmljYXRlIEF1dGhvcml0eTAgFw0yMTA5MjMxOTI5NDJaGA8yMDUxMDky
+MjE5Mjk0MlowgYkxCzAJBgNVBAYTAkdCMRQwEgYDVQQIDAtJc2xlIG9mIE1hbjEX
+MBUGA1UECgwOQ2Fub25pY2FsIEx0ZC4xFDASBgNVBAsMC1NlY3VyZSBCb290MTUw
+MwYDVQQDDCxDYW5vbmljYWwgTHRkLiBTZWN1cmUgQm9vdCBTaWduaW5nICgyMDIx
+IHYyKTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALoGi+5Yt4tJe1N6
+0d8C4/LYsIwDXPQtC9gYOyP6aLDo6Z3coute0wapKNSfFLYeHB3vaQ5/RPLMSvGx
+0HEwalAesNP4pBnQSvHj63rlV0yh+9GHuUjgVTdS+d6ZLpWFNs7THWcvFMt/BYJ1
+IbaqpRSs2kr0/vpcM0k9b979nXW64sQCOLVp9f+oZ0s64DT2OwcDpX5ZbzrSKKQv
+JazYqR9ZUl0kNlhRtfASqNN4Vlex4KnfFAVlfLWlAPCIORREGIUtDChpe7m0HEdv
+Q2ZMIq339hl14RQsDTM/wT/8c1ayaAW1kgObZWuBgJI1A5tmaFjFZhG2jH8FCZpF
+pg5eX78CAwEAAaOBoDCBnTAMBgNVHRMBAf8EAjAAMB8GA1UdJQQYMBYGCCsGAQUF
+BwMDBgorBgEEAYI3CgMGMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRl
+ZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUTPBGiS1v08mlsD+Y2EX5CFHcaowwHwYD
+VR0jBBgwFoAUrZGZC8IqsfUXBIwjtmVaJo40WmMwDQYJKoZIhvcNAQELBQADggEB
+AJOdSX2fPj4neZfZwvwL9zC39HiyyeReQtMnJnDPiJbR8uqgdX489rfS55Uw46Zn
+p+65U4/9ssvb4Zgyvph5CUbGY2pXh02yJkb2NF4YdcqCgI4zwh3HdtcUV+8uDp5Y
+XIGO7VMsB0YKivwv9bLIWPX6+rv5fUcTOfDyHBWcdZBAvQgEs2rews00IX66MUi8
+oSO87pOyYpYnMIbC1Pe05jxxRzeE/z0MHuzzDtpr3GR6uMB+RRMJvwKzt1ttCS1q
+TguTlClMpsPHBfppCARTPExkwH6JAJEbpsLX6sTbhjj+ZgOFe/w5JJlMKj4Qi5HD
+biCdDO5RcLWYWPNcrBaYe84=
+-----END CERTIFICATE-----
--- linux-xilinx-zynqmp-5.4.0.orig/debian/revoked-certs/canonical-uefi-2021v3-all.pem
+++ linux-xilinx-zynqmp-5.4.0/debian/revoked-certs/canonical-uefi-2021v3-all.pem
@@ -0,0 +1,86 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 8 (0x8)
+        Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C = GB, ST = Isle of Man, L = Douglas, O = Canonical Ltd., CN = Canonical Ltd. Master Certificate Authority
+        Validity
+            Not Before: Sep 23 19:30:02 2021 GMT
+            Not After : Sep 22 19:30:02 2051 GMT
+        Subject: C = GB, ST = Isle of Man, O = Canonical Ltd., OU = Secure Boot, CN = Canonical Ltd. Secure Boot Signing (2021 v3)
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (2048 bit)
+                Modulus:
+                    00:d6:29:96:87:ae:07:42:45:bb:65:09:b2:9b:de:
+                    5d:8e:78:61:10:d5:6d:ae:ae:26:08:6a:06:ec:4a:
+                    dd:2b:e7:1a:a9:ad:78:e3:fc:cf:8f:d1:47:bd:1e:
+                    33:d8:7a:e3:66:9b:e9:73:c1:5f:42:e2:fe:bc:c3:
+                    41:f7:cd:d7:85:d7:42:c9:ea:31:e5:47:b1:93:5b:
+                    43:2b:07:51:b8:75:08:ad:0f:e7:0d:81:38:5a:21:
+                    df:b1:43:5b:db:37:c5:ac:aa:14:3a:33:19:6a:26:
+                    e0:05:fe:cd:41:31:af:5d:a8:ab:31:77:44:fc:da:
+                    00:e2:7a:44:33:c3:a7:ed:13:54:9f:19:5d:c9:98:
+                    a2:3b:af:4d:0d:87:29:9c:90:9e:42:9e:9a:06:6a:
+                    70:27:c5:aa:f7:a2:f2:88:e0:b9:66:9a:72:a0:f6:
+                    61:7e:30:8f:14:9f:44:0d:dd:54:ae:47:c8:82:ba:
+                    d2:b2:db:6f:24:c1:f4:0a:81:07:90:47:49:5f:57:
+                    d6:3f:bf:2a:73:98:f2:f6:24:1a:74:03:d7:35:f0:
+                    42:d8:14:c5:94:27:5d:3c:49:0c:b0:f0:7a:61:1b:
+                    d7:5a:e3:a3:40:57:e9:a4:07:ee:02:a3:32:27:94:
+                    bb:f3:36:c5:5f:ef:d3:07:04:3a:80:4c:9c:0a:b7:
+                    88:9f
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:FALSE
+            X509v3 Extended Key Usage: 
+                Code Signing, 1.3.6.1.4.1.311.10.3.6
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                10:04:37:BB:6D:E6:E4:69:B5:81:E6:1C:D6:6B:CE:3E:F4:ED:53:AF
+            X509v3 Authority Key Identifier: 
+                AD:91:99:0B:C2:2A:B1:F5:17:04:8C:23:B6:65:5A:26:8E:34:5A:63
+    Signature Algorithm: sha256WithRSAEncryption
+    Signature Value:
+        3b:37:d6:a8:8d:cd:d2:df:13:35:ac:8c:92:d6:b0:ac:d1:38:
+        a8:00:97:47:59:b8:4a:84:8c:80:a5:1d:c7:29:bf:00:66:e5:
+        10:40:26:2e:31:f5:e1:13:c0:1b:29:f3:0b:7e:2d:71:d8:db:
+        e1:32:8f:79:8e:e3:97:0c:40:a9:a0:12:c1:fc:c2:50:88:72:
+        44:c5:bc:8b:45:6e:28:fd:d2:37:d6:db:17:cf:4e:61:33:08:
+        5a:5d:08:94:73:44:e2:76:00:44:1b:b8:00:a1:86:00:64:8a:
+        f1:42:32:3c:28:11:67:7c:8b:aa:06:34:74:58:e8:b3:3a:36:
+        8d:f6:04:5d:37:f5:66:52:c9:48:b0:a7:6f:34:09:dd:60:2a:
+        86:b9:14:f1:09:f6:06:16:56:e0:51:b1:e8:75:7f:fa:37:dc:
+        e0:98:a7:69:ae:7b:1a:73:89:0d:06:67:cc:01:ef:80:31:45:
+        9e:bb:03:2a:eb:89:70:d6:19:b2:c7:ce:bc:81:df:da:c8:6f:
+        a9:4b:2d:d7:a7:e1:af:c6:e8:fb:f0:61:c9:cd:d2:91:cd:8b:
+        c2:6c:ef:e0:b6:7f:f1:c4:81:f9:bb:76:9c:26:e3:fa:a1:a0:
+        cd:5e:05:de:ee:f9:1b:5b:50:0a:8b:0f:47:e3:90:32:ac:2a:
+        e7:65:02:80
+-----BEGIN CERTIFICATE-----
+MIIELTCCAxWgAwIBAgIBCDANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBhMCR0Ix
+FDASBgNVBAgMC0lzbGUgb2YgTWFuMRAwDgYDVQQHDAdEb3VnbGFzMRcwFQYDVQQK
+DA5DYW5vbmljYWwgTHRkLjE0MDIGA1UEAwwrQ2Fub25pY2FsIEx0ZC4gTWFzdGVy
+IENlcnRpZmljYXRlIEF1dGhvcml0eTAgFw0yMTA5MjMxOTMwMDJaGA8yMDUxMDky
+MjE5MzAwMlowgYkxCzAJBgNVBAYTAkdCMRQwEgYDVQQIDAtJc2xlIG9mIE1hbjEX
+MBUGA1UECgwOQ2Fub25pY2FsIEx0ZC4xFDASBgNVBAsMC1NlY3VyZSBCb290MTUw
+MwYDVQQDDCxDYW5vbmljYWwgTHRkLiBTZWN1cmUgQm9vdCBTaWduaW5nICgyMDIx
+IHYzKTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANYploeuB0JFu2UJ
+spveXY54YRDVba6uJghqBuxK3SvnGqmteOP8z4/RR70eM9h642ab6XPBX0Li/rzD
+QffN14XXQsnqMeVHsZNbQysHUbh1CK0P5w2BOFoh37FDW9s3xayqFDozGWom4AX+
+zUExr12oqzF3RPzaAOJ6RDPDp+0TVJ8ZXcmYojuvTQ2HKZyQnkKemgZqcCfFqvei
+8ojguWaacqD2YX4wjxSfRA3dVK5HyIK60rLbbyTB9AqBB5BHSV9X1j+/KnOY8vYk
+GnQD1zXwQtgUxZQnXTxJDLDwemEb11rjo0BX6aQH7gKjMieUu/M2xV/v0wcEOoBM
+nAq3iJ8CAwEAAaOBoDCBnTAMBgNVHRMBAf8EAjAAMB8GA1UdJQQYMBYGCCsGAQUF
+BwMDBgorBgEEAYI3CgMGMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRl
+ZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUEAQ3u23m5Gm1geYc1mvOPvTtU68wHwYD
+VR0jBBgwFoAUrZGZC8IqsfUXBIwjtmVaJo40WmMwDQYJKoZIhvcNAQELBQADggEB
+ADs31qiNzdLfEzWsjJLWsKzROKgAl0dZuEqEjIClHccpvwBm5RBAJi4x9eETwBsp
+8wt+LXHY2+Eyj3mO45cMQKmgEsH8wlCIckTFvItFbij90jfW2xfPTmEzCFpdCJRz
+ROJ2AEQbuAChhgBkivFCMjwoEWd8i6oGNHRY6LM6No32BF039WZSyUiwp280Cd1g
+Koa5FPEJ9gYWVuBRseh1f/o33OCYp2muexpziQ0GZ8wB74AxRZ67AyrriXDWGbLH
+zryB39rIb6lLLden4a/G6PvwYcnN0pHNi8Js7+C2f/HEgfm7dpwm4/qhoM1eBd7u
++RtbUAqLD0fjkDKsKudlAoA=
+-----END CERTIFICATE-----
--- linux-xilinx-zynqmp-5.4.0.orig/debian/revoked-certs/canonical-uefi-uc2019-all.pem
+++ linux-xilinx-zynqmp-5.4.0/debian/revoked-certs/canonical-uefi-uc2019-all.pem
@@ -0,0 +1,86 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 3 (0x3)
+        Signature Algorithm: sha256WithRSAEncryption
+        Issuer: C = GB, ST = Isle of Man, L = Douglas, O = Canonical Ltd., CN = Canonical Ltd. Master Certificate Authority
+        Validity
+            Not Before: Mar  4 10:27:14 2020 GMT
+            Not After : Mar  3 10:27:14 2050 GMT
+        Subject: C = GB, ST = Isle of Man, O = Canonical Ltd., OU = Secure Boot, CN = Canonical Ltd. Secure Boot Signing (Ubuntu Core 2019)
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (2048 bit)
+                Modulus:
+                    00:b9:10:47:2e:75:5d:f3:10:23:bb:a0:75:d2:fa:
+                    02:2d:ff:22:df:c1:e6:cd:38:7c:36:0f:ae:74:15:
+                    6e:a5:34:52:2b:c3:a4:3a:60:d7:06:ee:1d:99:93:
+                    ff:66:91:a3:18:52:2c:8c:58:e6:b4:2f:4b:c5:fb:
+                    83:e6:f3:19:bd:1b:ca:23:ec:97:1f:d8:f1:9a:f1:
+                    04:da:da:10:04:53:4b:ec:1d:b6:26:47:7c:bb:8f:
+                    a7:0a:6e:2e:e8:91:e6:c4:bb:64:34:78:3c:fa:09:
+                    15:1c:8f:9e:eb:04:99:36:22:c6:8d:07:15:0f:b9:
+                    69:08:fa:ff:4b:45:bd:ba:2b:cd:01:0e:e7:01:23:
+                    c9:e5:7a:39:3b:91:b0:45:3c:d5:77:ba:ca:f9:29:
+                    3d:11:3f:1c:6b:5b:8e:6c:4b:3f:c9:29:05:cb:59:
+                    d6:b1:c1:c0:2d:56:88:70:27:fa:73:05:5c:c2:11:
+                    d4:27:11:f7:0b:c2:d5:68:d3:1a:cd:ed:d0:e4:10:
+                    ff:34:cb:b7:45:70:34:2c:23:53:b6:9c:30:70:b4:
+                    5c:d1:e2:64:18:82:8f:62:b1:5e:aa:0b:d4:89:f2:
+                    1c:53:c4:32:7d:ef:53:ee:9b:6e:02:ab:78:bd:25:
+                    67:8b:39:36:d8:84:3b:06:99:02:d6:75:73:4e:f2:
+                    f6:b9
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: critical
+                CA:FALSE
+            X509v3 Extended Key Usage: 
+                Code Signing, 1.3.6.1.4.1.311.10.3.6
+            Netscape Comment: 
+                OpenSSL Generated Certificate
+            X509v3 Subject Key Identifier: 
+                C1:D5:7B:8F:6B:74:3F:23:EE:41:F4:F7:EE:29:2F:06:EE:CA:DF:B9
+            X509v3 Authority Key Identifier: 
+                AD:91:99:0B:C2:2A:B1:F5:17:04:8C:23:B6:65:5A:26:8E:34:5A:63
+    Signature Algorithm: sha256WithRSAEncryption
+    Signature Value:
+        2d:b5:11:a8:d2:a0:af:81:a0:18:22:18:2c:08:d0:f4:63:e8:
+        8f:9a:f4:f5:20:dd:eb:22:77:19:9a:1a:09:3d:7f:aa:7d:c9:
+        81:bc:26:98:65:94:46:30:4b:c2:51:7c:f7:21:41:63:87:31:
+        fc:a4:c9:41:28:c7:2e:2a:2e:d8:a8:75:7a:72:77:3b:1b:9f:
+        72:15:0d:0c:96:8d:8b:51:f3:ce:37:b6:ca:9f:ca:59:40:4a:
+        fc:73:7a:94:12:99:aa:c2:8d:52:ce:91:19:2e:b4:da:ff:e5:
+        2c:67:74:d9:58:47:38:2f:61:88:c5:cf:a7:48:e1:08:ba:bc:
+        ec:d5:3a:47:d9:8c:dc:c3:bc:cb:98:2b:79:7a:02:46:ef:85:
+        19:2f:03:4b:05:84:eb:56:98:5f:6d:cf:a5:8b:a2:b6:e5:50:
+        51:7c:33:44:bd:7a:94:2e:0d:90:39:39:3e:62:60:ae:3a:e2:
+        f5:17:fa:f1:94:06:1d:ae:a3:f8:19:20:7f:4b:4c:07:c4:e6:
+        2d:0d:e5:94:84:51:6d:6f:0f:c4:c6:79:1d:f0:e8:0e:23:9e:
+        fd:f9:46:2c:b9:ec:97:38:56:7e:b8:13:f6:d2:e1:8e:a5:93:
+        02:7b:6e:dd:33:9a:bf:10:a8:1b:3d:fa:c4:f2:15:f0:27:73:
+        26:a6:94:d1
+-----BEGIN CERTIFICATE-----
+MIIENjCCAx6gAwIBAgIBAzANBgkqhkiG9w0BAQsFADCBhDELMAkGA1UEBhMCR0Ix
+FDASBgNVBAgMC0lzbGUgb2YgTWFuMRAwDgYDVQQHDAdEb3VnbGFzMRcwFQYDVQQK
+DA5DYW5vbmljYWwgTHRkLjE0MDIGA1UEAwwrQ2Fub25pY2FsIEx0ZC4gTWFzdGVy
+IENlcnRpZmljYXRlIEF1dGhvcml0eTAgFw0yMDAzMDQxMDI3MTRaGA8yMDUwMDMw
+MzEwMjcxNFowgZIxCzAJBgNVBAYTAkdCMRQwEgYDVQQIDAtJc2xlIG9mIE1hbjEX
+MBUGA1UECgwOQ2Fub25pY2FsIEx0ZC4xFDASBgNVBAsMC1NlY3VyZSBCb290MT4w
+PAYDVQQDDDVDYW5vbmljYWwgTHRkLiBTZWN1cmUgQm9vdCBTaWduaW5nIChVYnVu
+dHUgQ29yZSAyMDE5KTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALkQ
+Ry51XfMQI7ugddL6Ai3/It/B5s04fDYPrnQVbqU0UivDpDpg1wbuHZmT/2aRoxhS
+LIxY5rQvS8X7g+bzGb0byiPslx/Y8ZrxBNraEARTS+wdtiZHfLuPpwpuLuiR5sS7
+ZDR4PPoJFRyPnusEmTYixo0HFQ+5aQj6/0tFvborzQEO5wEjyeV6OTuRsEU81Xe6
+yvkpPRE/HGtbjmxLP8kpBctZ1rHBwC1WiHAn+nMFXMIR1CcR9wvC1WjTGs3t0OQQ
+/zTLt0VwNCwjU7acMHC0XNHiZBiCj2KxXqoL1InyHFPEMn3vU+6bbgKreL0lZ4s5
+NtiEOwaZAtZ1c07y9rkCAwEAAaOBoDCBnTAMBgNVHRMBAf8EAjAAMB8GA1UdJQQY
+MBYGCCsGAQUFBwMDBgorBgEEAYI3CgMGMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NM
+IEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUwdV7j2t0PyPuQfT37ikv
+Bu7K37kwHwYDVR0jBBgwFoAUrZGZC8IqsfUXBIwjtmVaJo40WmMwDQYJKoZIhvcN
+AQELBQADggEBAC21EajSoK+BoBgiGCwI0PRj6I+a9PUg3esidxmaGgk9f6p9yYG8
+JphllEYwS8JRfPchQWOHMfykyUEoxy4qLtiodXpydzsbn3IVDQyWjYtR8843tsqf
+yllASvxzepQSmarCjVLOkRkutNr/5SxndNlYRzgvYYjFz6dI4Qi6vOzVOkfZjNzD
+vMuYK3l6AkbvhRkvA0sFhOtWmF9tz6WLorblUFF8M0S9epQuDZA5OT5iYK464vUX
++vGUBh2uo/gZIH9LTAfE5i0N5ZSEUW1vD8TGeR3w6A4jnv35Riy57Jc4Vn64E/bS
+4Y6lkwJ7bt0zmr8QqBs9+sTyFfAncyamlNE=
+-----END CERTIFICATE-----
--- linux-xilinx-zynqmp-5.4.0.orig/debian/rules
+++ linux-xilinx-zynqmp-5.4.0/debian/rules
@@ -0,0 +1,254 @@
+#!/usr/bin/make -f
+#
+# $(DEBIAN)/rules for Ubuntu linux
+#
+# Use this however you want, just give credit where credit is due.
+#
+# Copyright (c) 2007 Ben Collins <bcollins@ubuntu.com>
+#
+
+DEBIAN=$(shell awk -F= '($$1 == "DEBIAN") { print $$2 }' <debian/debian.env)
+
+# dpkg-buildpackage passes options that are incomptatible
+# with the kernel build.
+unexport CFLAGS
+unexport LDFLAGS
+
+export LC_ALL=C
+export SHELL=/bin/bash -e
+
+# Where do we find the common configuration.
+export DROOT=debian
+
+# Common variables for all architectures
+include $(DROOT)/rules.d/0-common-vars.mk
+
+# Pull in some arch specific stuff
+-include $(DEBIAN)/rules.d/$(arch).mk
+
+# Pull in some branch specific stuff. Used by LTS backport
+# branches to override master branch settings such as do_tools_common.
+-include $(DEBIAN)/rules.d/hooks.mk
+
+# Maintainer targets
+include $(DROOT)/rules.d/1-maintainer.mk
+
+do_linux_tools=$(sort $(filter-out false,$(do_tools_usbip) $(do_tools_cpupower) $(do_tools_perf) $(do_tools_bpftool) $(do_tools_x86)))
+do_cloud_tools=$(sort $(filter-out false,$(do_tools_hyperv)))
+do_tools_common?=true
+do_tools_host?=false
+do_tools_perf_jvmti?=false
+do_enforce_all?=false
+
+# Don't build tools or udebs in a cross compile environment.
+ifneq ($(DEB_HOST_ARCH),$(DEB_BUILD_ARCH))
+	do_tools=false
+	disable_d_i=true
+	do_zfs=false
+	do_dkms_nvidia=false
+	do_dkms_nvidia_server=false
+	do_dkms_vbox=false
+	do_dkms_wireguard=false
+endif
+
+# Are any of the kernel signing options enabled.
+any_signed=$(sort $(filter-out false,$(uefi_signed) $(opal_signed) $(sipl_signed)))
+ifeq ($(any_signed),true)
+bin_pkg_name=$(bin_pkg_name_unsigned)
+else
+bin_pkg_name=$(bin_pkg_name_signed)
+endif
+
+# Stages -- support both DEB_STAGE=stage1 and DEB_BUILD_PROFILE=bootstrap
+ifeq ($(DEB_STAGE),stage1)
+    DEB_BUILD_PROFILES=stage1
+endif
+ifneq ($(DEB_BUILD_PROFILE),)
+    DEB_BUILD_PROFILES=$(DEB_BUILD_PROFILE)
+endif
+ifneq ($(filter stage1,$(DEB_BUILD_PROFILES)),)
+    do_tools=false
+    do_doc_package=false
+    do_source_package=false
+    do_flavour_image_package=false
+    do_flavour_header_package=false
+endif
+
+# autopkgtest -- rebuild support
+#  - only build the first flavour on the assumption it is representative
+#  - disable dkms builds as the versions used may have been deleted
+ifneq ($(filter autopkgtest,$(DEB_BUILD_PROFILES)),)
+	flavours := $(firstword $(flavours))
+	disable_d_i=true
+	do_zfs=false
+	do_dkms_nvidia=false
+	do_dkms_nvidia_server=false
+	do_dkms_vbox=false
+endif
+
+# Being used to build a mainline build -- turn off things which do not work.
+ifeq ($(do_mainline_build),true)
+	do_extras_package=false
+	do_tools=false
+	no_dumpfile=1
+	do_zfs=false
+	do_dkms_nvidia=false
+	do_dkms_nvidia_server=false
+	do_dkms_vbox=false
+	skipabi=true
+	skipmodule=true
+	skipretpoline=true
+endif
+
+# Disable tools build and packaging if do_tools != true
+ifneq ($(do_tools),true)
+	do_linux_tools=
+	do_cloud_tools=
+	do_tools_common=
+	do_tools_host=
+endif
+
+# Either tools package needs the common source preparation
+do_any_tools=$(sort $(filter-out false,$(do_linux_tools) $(do_cloud_tools)))
+
+# Versions of dkms packages.
+dkms_zfs_linux_version=$(shell gawk '/^zfs-linux / { print $$2; }' $(DEBIAN)/dkms-versions)
+dkms_vbox_guest_version=$(shell gawk '/^virtualbox/ { print $$2; }' $(DEBIAN)/dkms-versions)
+dkms_wireguard_version=$(shell gawk '/^wireguard-linux-compat / { print $$2; }' $(DEBIAN)/dkms-versions)
+
+# NVIDIA DKMS package gross series split into desktop and server.
+nvidia_desktop_series=$(shell sed -n -e 's/^nvidia-graphics-drivers-\([0-9][0-9]*\) .*/\1/p' $(DEBIAN)/dkms-versions)
+nvidia_server_series=$(shell sed -n -e 's/^nvidia-graphics-drivers-\([0-9][0-9]*-server\) .*/\1/p' $(DEBIAN)/dkms-versions)
+
+# Debian Build System targets
+binary: binary-indep binary-arch
+
+build: build-arch build-indep
+
+clean: debian/control debian/canonical-certs.pem debian/canonical-revoked-certs.pem
+	dh_testdir
+	dh_testroot
+	dh_clean
+
+	# d-i stuff
+	rm -rf $(DEBIAN)/d-i-$(arch)
+	# Generated on the fly.
+	rm -f $(DEBIAN)/d-i/firmware/$(arch)/kernel-image
+
+	# normal build junk
+	rm -rf $(DEBIAN)/abi
+	rm -rf $(builddir)
+	rm -f $(stampdir)/stamp-*
+	rm -rf $(DEBIAN)/linux-*
+
+	# This gets rid of the d-i packages in control
+	cp -f $(DEBIAN)/control.stub $(DROOT)/control
+	cp $(DEBIAN)/changelog debian/changelog
+
+	# Install the copyright information.
+	cp $(DEBIAN)/copyright debian/copyright
+
+	# Install the retpoline extractor.
+	cp $(DROOT)/scripts/retpoline-extract-one scripts/ubuntu-retpoline-extract-one
+
+	# If we have a reconstruct script use it.
+	[ -f $(DEBIAN)/reconstruct ] && bash $(DEBIAN)/reconstruct || true
+
+	# Remove generated intermediate files
+	rm -f $(DROOT)/control.stub $(DEBIAN)/control.stub
+	rm -f $(DROOT)/scripts/fix-filenames
+
+distclean: clean
+	rm -rf $(DROOT)/control debian/changelog \
+		debian/control debian/control.stub debian/copyright \
+		scripts/ubuntu-retpoline-extract-one
+
+# Builds the image, arch headers and debug packages
+include $(DROOT)/rules.d/2-binary-arch.mk
+
+# Rules for building the udebs ($(DEBIAN)-installer)
+include $(DROOT)/rules.d/5-udebs.mk
+
+# Builds the source, doc and linux-headers indep packages
+include $(DROOT)/rules.d/3-binary-indep.mk
+
+# Various checks to be performed on builds
+include $(DROOT)/rules.d/4-checks.mk
+
+control_files := $(DEBIAN)/control.stub.in
+ifeq ($(do_libc_dev_package),true)
+ifneq (,$(wildcard $(DEBIAN)/control.d/linux-libc-dev.stub))
+	control_files += $(DEBIAN)/control.d/linux-libc-dev.stub
+endif
+endif
+ifeq ($(do_doc_package),true)
+ifneq (,$(wildcard $(DEBIAN)/control.d/linux-doc.stub))
+	control_files += $(DEBIAN)/control.d/linux-doc.stub
+endif
+endif
+
+# Calculate Ubuntu Compatible Signing levels
+UBUNTU_COMPATIBLE_SIGNING=$(shell grep -qx ' *Subject: C = GB, ST = Isle of Man, O = Canonical Ltd., OU = Secure Boot, CN = Canonical Ltd. Secure Boot Signing (2021 v3)' debian/canonical-revoked-certs.pem && echo ubuntu/4 pro/3)
+
+# Misc stuff
+.PHONY: $(DEBIAN)/control.stub
+$(DEBIAN)/control.stub: 				\
+		$(DROOT)/scripts/control-create		\
+		$(control_files)			\
+		debian/canonical-revoked-certs.pem	\
+		$(DEBIAN)/changelog			\
+		$(wildcard $(DEBIAN)/control.d/* $(DEBIAN)/sub-flavours/*.vars)
+	for i in $(control_files); do                                           \
+	  cat $$i;                                                              \
+	  echo "";                                                              \
+	done | sed -e 's/PKGVER/$(release)/g'                                   \
+	        -e 's/ABINUM/$(abinum)/g'                                       \
+		-e 's/SRCPKGNAME/$(src_pkg_name)/g'                             \
+		-e 's/=HUMAN=/$(human_arch)/g'                                  \
+		-e 's/=SERIES=/$(series)/g'                                     \
+		-e 's|\(^Maintainer:.*\)|\1\nXSC-Ubuntu-Compatible-Signing: $(UBUNTU_COMPATIBLE_SIGNING)|g' \
+	  > $(DEBIAN)/control.stub;
+	flavours="$(sort $(wildcard $(DEBIAN)/control.d/vars.* $(DEBIAN)/sub-flavours/*.vars))";\
+	for i in $$flavours; do							\
+	  $(SHELL) $(DROOT)/scripts/control-create $$i "$(any_signed)" |	\
+		sed -e 's/PKGVER/$(release)/g'                                  \
+		-e 's/ABINUM/$(abinum)/g'                                       \
+		-e 's/SRCPKGNAME/$(src_pkg_name)/g'                             \
+		-e 's/=HUMAN=/$(human_arch)/g'                                  \
+		-e 's/=SERIES=/$(series)/g'                                     \
+		>> $(DEBIAN)/control.stub;                                      \
+	done
+
+.PHONY: debian/control
+debian/control: $(DEBIAN)/control.stub
+	echo "# placebo control.stub for kernel-wedge flow change" >debian/control.stub
+	cp $(DEBIAN)/control.stub debian/control
+	export KW_DEFCONFIG_DIR=$(DEBIAN)/d-i && \
+	export KW_CONFIG_DIR=$(DEBIAN)/d-i && \
+	LANG=C kernel-wedge gen-control $(release)-$(abinum) | \
+		perl -f $(DROOT)/scripts/misc/kernel-wedge-arch.pl $(arch) \
+		>>$(CURDIR)/debian/control
+
+debian/canonical-certs.pem: $(wildcard $(DROOT)/certs/*-all.pem) $(wildcard $(DROOT)/certs/*-$(arch).pem) $(wildcard $(DEBIAN)/certs/*-all.pem) $(wildcard $(DEBIAN)/certs/*-$(arch).pem)
+	for cert in $(sort $(notdir $^));					\
+	do									\
+		for dir in $(DEBIAN) $(DROOT);					\
+		do								\
+			if [ -f "$$dir/certs/$$cert" ]; then			\
+				cat "$$dir/certs/$$cert";			\
+				break;						\
+			fi;							\
+		done;								\
+	done >"$@"
+
+debian/canonical-revoked-certs.pem: $(wildcard $(DROOT)/revoked-certs/*-all.pem) $(wildcard $(DROOT)/revoked-certs/*-$(arch).pem) $(wildcard $(DEBIAN)/revoked-certs/*-all.pem) $(wildcard $(DEBIAN)/revoked-certs/*-$(arch).pem)
+	for cert in $(sort $(notdir $^));					\
+	do									\
+		for dir in $(DEBIAN) $(DROOT);					\
+		do								\
+			if [ -f "$$dir/revoked-certs/$$cert" ]; then		\
+				cat "$$dir/revoked-certs/$$cert";		\
+				break;						\
+			fi;							\
+		done;								\
+	done >"$@"
--- linux-xilinx-zynqmp-5.4.0.orig/debian/rules.d/0-common-vars.mk
+++ linux-xilinx-zynqmp-5.4.0/debian/rules.d/0-common-vars.mk
@@ -0,0 +1,278 @@
+# Used when you need to 'escape' a comma.
+comma = ,
+
+#
+# The source package name will be the first token from $(DEBIAN)/changelog
+#
+src_pkg_name=$(shell sed -n '1s/^\(.*\) (.*).*$$/\1/p' $(DEBIAN)/changelog)
+
+# Get the series
+series=$(shell dpkg-parsechangelog -l$(DEBIAN)/changelog | sed -ne 's/^Distribution: *//p' | sed -e 's/-\(security\|updates\|proposed\)$$//')
+
+# Get some version info
+release := $(shell sed -n '1s/^$(src_pkg_name).*(\(.*\)-.*).*$$/\1/p' $(DEBIAN)/changelog)
+revisions := $(shell sed -n 's/^$(src_pkg_name)\ .*($(release)-\(.*\)).*$$/\1/p' $(DEBIAN)/changelog | tac)
+revision ?= $(word $(words $(revisions)),$(revisions))
+prev_revisions := $(filter-out $(revision),0.0 $(revisions))
+prev_revision := $(word $(words $(prev_revisions)),$(prev_revisions))
+
+prev_fullver ?= $(shell dpkg-parsechangelog -l$(DEBIAN)/changelog -o1 -c1 | sed -ne 's/^Version: *//p')
+
+# Get variants. Assume primary if debian/variants is not present.
+variants = --
+ifneq (,$(wildcard $(DEBIAN)/variants))
+	variants := $(shell cat $(DEBIAN)/variants)
+endif
+
+# Get upstream version info
+upstream_version := $(shell sed -n 's/^VERSION = \(.*\)$$/\1/p' Makefile)
+upstream_patchlevel := $(shell sed -n 's/^PATCHLEVEL = \(.*\)$$/\1/p' Makefile)
+upstream_tag := "v$(upstream_version).$(upstream_patchlevel)"
+
+family=ubuntu
+
+# This is an internally used mechanism for the daily kernel builds. It
+# creates packages whose ABI is suffixed with a minimal representation of
+# the current git HEAD sha. If .git/HEAD is not present, then it uses the
+# uuidgen program,
+#
+# AUTOBUILD can also be used by anyone wanting to build a custom kernel
+# image, or rebuild the entire set of Ubuntu packages using custom patches
+# or configs.
+AUTOBUILD=
+
+ifneq ($(AUTOBUILD),)
+skipabi		= true
+skipmodule	= true
+skipretpoline	= true
+skipdbg		= true
+gitver=$(shell if test -f .git/HEAD; then cat .git/HEAD; else uuidgen; fi)
+gitverpre=$(shell echo $(gitver) | cut -b -3)
+gitverpost=$(shell echo $(gitver) | cut -b 38-40)
+abi_suffix = -$(gitverpre)$(gitverpost)
+endif
+
+ifneq ($(NOKERNLOG),)
+ubuntu_log_opts += --no-kern-log
+endif
+ifneq ($(PRINTSHAS),)
+ubuntu_log_opts += --print-shas
+endif
+
+# Get the kernels own extra version to be added to the release signature.
+raw_kernelversion=$(shell make kernelversion)
+
+#
+# full_build -- are we doing a full buildd style build
+#
+ifeq ($(wildcard /CurrentlyBuilding),)
+full_build?=false
+else
+full_build?=true
+endif
+
+#
+# The debug packages are ginormous, so you probably want to skip
+# building them (as a developer).
+#
+ifeq ($(full_build),false)
+skipdbg=true
+endif
+
+abinum		:= $(shell echo $(revision) | sed -r -e 's/([^\+~]*)\.[^\.]+(~.*)?(\+.*)?$$/\1/')$(abi_suffix)
+prev_abinum	:= $(shell echo $(prev_revision) | sed -r -e 's/([^\+~]*)\.[^\.]+(~.*)?(\+.*)?$$/\1/')$(abi_suffix)
+abi_release	:= $(release)-$(abinum)
+
+uploadnum	:= $(shell echo $(revision) | sed -r -e 's/[^\+~]*\.([^\.~]+(~.*)?(\+.*)?$$)/\1/')
+ifneq ($(full_build),false)
+  uploadnum	:= $(uploadnum)-Ubuntu
+endif
+
+# XXX: linux-libc-dev got bumped to -803.N inadvertantly by a ti-omap4 upload
+#      shift our version higher for this package only.  Ensure this only
+#      occurs for the v2.6.35 kernel so that we do not propogate this into
+#      any other series.
+raw_uploadnum	:= $(shell echo $(revision) | sed -e 's/.*\.//')
+libc_dev_version :=
+ifeq ($(DEBIAN),debian.master)
+ifeq ($(release),2.6.35)
+libc_dev_version := -v$(release)-$(shell expr "$(abinum)" + 1000).$(raw_uploadnum)
+endif
+endif
+
+DEB_HOST_MULTIARCH = $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)
+DEB_HOST_GNU_TYPE  = $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
+DEB_BUILD_GNU_TYPE = $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
+DEB_HOST_ARCH = $(shell dpkg-architecture -qDEB_HOST_ARCH)
+DEB_BUILD_ARCH = $(shell dpkg-architecture -qDEB_BUILD_ARCH)
+
+#
+# Detect invocations of the form 'fakeroot debian/rules binary arch=armhf'
+# within an x86'en schroot. This only gets you part of the way since the
+# packaging phase fails, but you can at least compile the kernel quickly.
+#
+arch := $(DEB_HOST_ARCH)
+ifneq ($(arch),$(DEB_HOST_ARCH))
+	CROSS_COMPILE ?= $(shell dpkg-architecture -a$(arch) -qDEB_HOST_GNU_TYPE -f 2>/dev/null)-
+endif
+
+#
+# Detect invocations of the form 'dpkg-buildpackage -B -aarmhf' within
+# an x86'en schroot. This is the only way to build all of the packages
+# (except for tools).
+#
+ifneq ($(DEB_BUILD_GNU_TYPE),$(DEB_HOST_GNU_TYPE))
+	CROSS_COMPILE ?= $(DEB_HOST_GNU_TYPE)-
+endif
+
+abidir		:= $(CURDIR)/$(DEBIAN)/abi/$(release)-$(revision)/$(arch)
+commonconfdir	:= $(CURDIR)/$(DEBIAN)/config
+archconfdir	:= $(CURDIR)/$(DEBIAN)/config/$(arch)
+sharedconfdir	:= $(CURDIR)/debian.master/config
+builddir	:= $(CURDIR)/debian/build
+stampdir	:= $(CURDIR)/debian/stamps
+
+#
+# The binary package name always starts with linux-image-$KVER-$ABI.$UPLOAD_NUM. There
+# are places that you'll find linux-image hard coded, but I guess thats OK since the
+# assumption that the binary package always starts with linux-image will never change.
+#
+bin_pkg_name_signed=linux-image-$(abi_release)
+bin_pkg_name_unsigned=linux-image-unsigned-$(abi_release)
+mods_pkg_name=linux-modules-$(abi_release)
+mods_extra_pkg_name=linux-modules-extra-$(abi_release)
+bldinfo_pkg_name=linux-buildinfo-$(abi_release)
+hdrs_pkg_name=linux-headers-$(abi_release)
+indep_hdrs_pkg_name=$(src_pkg_name)-headers-$(abi_release)
+
+#
+# The generation of content in the doc package depends on both 'AUTOBUILD=' and
+# 'do_doc_package_content=true'. There are usually build errors during the development
+# cycle, so its OK to leave 'do_doc_package_content=false' until those build
+# failures get sorted out. Finally, the doc package doesn't really need to be built
+# for developer testing (its kind of slow), so only do it if on a buildd.
+ifneq ($(filter --,$(variants)),)
+do_doc_package=true
+else
+do_doc_package=false
+endif
+do_doc_package_content=true
+ifeq ($(full_build),false)
+do_doc_package_content=false
+endif
+doc_pkg_name=$(src_pkg_name)-doc
+
+#
+# Similarly with the linux-source package, you need not build it as a developer. Its
+# somewhat I/O intensive and utterly useless.
+#
+do_source_package=true
+do_source_package_content=true
+ifeq ($(full_build),false)
+do_source_package_content=false
+endif
+
+# linux-libc-dev may not be needed, default to building it only for the
+# primary variant
+ifneq ($(filter --,$(variants)),)
+do_libc_dev_package=true
+else
+do_libc_dev_package=false
+endif
+
+# common headers normally is built as an indep package, but may be arch
+do_common_headers_indep=true
+
+# add a 'full source' mode
+do_full_source=false
+
+# Add an option to enable special drivers which should only be build when
+# explicitly enabled.
+do_odm_drivers=false
+
+# build tools
+ifneq ($(wildcard $(CURDIR)/tools),)
+	ifeq ($(do_tools),)
+		ifneq ($(DEB_BUILD_GNU_TYPE),$(DEB_HOST_GNU_TYPE))
+			do_tools=false
+		endif
+	endif
+	do_tools?=true
+else
+	do_tools?=false
+endif
+tools_pkg_name=$(src_pkg_name)-tools-$(abi_release)
+tools_common_pkg_name=$(src_pkg_name)-tools-common
+tools_flavour_pkg_name=linux-tools-$(abi_release)
+cloud_pkg_name=$(src_pkg_name)-cloud-tools-$(abi_release)
+cloud_common_pkg_name=$(src_pkg_name)-cloud-tools-common
+cloud_flavour_pkg_name=linux-cloud-tools-$(abi_release)
+hosttools_pkg_name=$(src_pkg_name)-tools-host
+
+# The general flavour specific image package.
+do_flavour_image_package=true
+
+# The general flavour specific header package.
+do_flavour_header_package=true
+
+# DTBs
+do_dtbs=false
+
+# Support parallel=<n> in DEB_BUILD_OPTIONS (see #209008)
+#
+# These 2 environment variables set the -j value of the kernel build. For example,
+# CONCURRENCY_LEVEL=16 fakeroot $(DEBIAN)/rules binary-debs
+# or
+# DEB_BUILD_OPTIONS=parallel=16 fakeroot $(DEBIAN)/rules binary-debs
+#
+# The default is to use the number of CPUs.
+#
+COMMA=,
+DEB_BUILD_OPTIONS_PARA = $(subst parallel=,,$(filter parallel=%,$(subst $(COMMA), ,$(DEB_BUILD_OPTIONS))))
+ifneq (,$(DEB_BUILD_OPTIONS_PARA))
+  CONCURRENCY_LEVEL := $(DEB_BUILD_OPTIONS_PARA)
+endif
+
+ifeq ($(CONCURRENCY_LEVEL),)
+  # Check the environment
+  CONCURRENCY_LEVEL := $(shell echo $$CONCURRENCY_LEVEL)
+  # No? Then build with the number of CPUs on the host.
+  ifeq ($(CONCURRENCY_LEVEL),)
+      CONCURRENCY_LEVEL := $(shell expr `getconf _NPROCESSORS_ONLN` \* 1)
+  endif
+  # Oh hell, give 'em one
+  ifeq ($(CONCURRENCY_LEVEL),)
+    CONCURRENCY_LEVEL := 1
+  endif
+endif
+
+conc_level		= -j$(CONCURRENCY_LEVEL)
+
+# target_flavour is filled in for each step
+kmake = make ARCH=$(build_arch) \
+	CROSS_COMPILE=$(CROSS_COMPILE) \
+	KERNELVERSION=$(abi_release)-$(target_flavour) \
+	CONFIG_DEBUG_SECTION_MISMATCH=y \
+	KBUILD_BUILD_VERSION="$(uploadnum)" \
+	LOCALVERSION= localver-extra= \
+	CFLAGS_MODULE="-DPKG_ABI=$(abinum)"
+ifneq ($(LOCAL_ENV_CC),)
+kmake += CC="$(LOCAL_ENV_CC)" DISTCC_HOSTS="$(LOCAL_ENV_DISTCC_HOSTS)"
+endif
+
+# Locking is required in parallel builds to prevent loss of contents
+# of the debian/files.
+lockme_file = $(CURDIR)/debian/.LOCK
+lockme_cmd = flock -w 60
+lockme = $(lockme_cmd) $(lockme_file)
+
+# Don't fail if a link already exists.
+LN = ln -sf
+
+# Checks if a var is overriden by the custom rules. Called with var and
+# flavour as arguments.
+custom_override = \
+ $(shell if [ -n "$($(1)_$(2))" ]; then echo "$($(1)_$(2))"; else echo "$($(1))"; fi)
+
+# selftests that Ubuntu cares about
+ubuntu_selftests = breakpoints bpf cpu-hotplug efivarfs memfd memory-hotplug mount net ptrace seccomp timers powerpc user ftrace
--- linux-xilinx-zynqmp-5.4.0.orig/debian/rules.d/1-maintainer.mk
+++ linux-xilinx-zynqmp-5.4.0/debian/rules.d/1-maintainer.mk
@@ -0,0 +1,198 @@
+# The following targets are for the maintainer only! do not run if you don't
+# know what they do.
+
+.PHONY: printenv updateconfigs migrateconfigs printchanges insertchanges startnewrelease diffupstream help updateportsconfigs editportsconfigs autoreconstruct finalchecks
+
+help:
+	@echo "These are the targets in addition to the normal $(DEBIAN) ones:"
+	@echo
+	@echo "  printenv        : Print some variables used in the build"
+	@echo
+	@echo "  updateconfigs        : Update core arch configs"
+	@echo
+	@echo "  editconfigs          : Update core arch configs interractively"
+	@echo "  migrateconfigs       : Automatically import old configs into annotations"
+	@echo "  genconfigs           : Generate core arch configs in CONFIGS/*"
+	@echo
+	@echo "  updateportsconfigs   : Update ports arch configs"
+	@echo
+	@echo "  editportsconfigs     : Update ports arch configs interactivly"
+	@echo "  genportconfigs       : Generate ports arch configs in CONFIGS/*"
+	@echo
+	@echo "  printchanges    : Print the current changelog entries (from git)"
+	@echo
+	@echo "  insertchanges   : Insert current changelog entries (from git)"
+	@echo
+	@echo "  startnewrelease : Start a new changelog set"
+	@echo
+	@echo "  diffupstream    : Diff stock kernel code against upstream (git)"
+	@echo
+	@echo "  compileselftests : Only compile the selftests listed on ubuntu_selftests variable"
+	@echo
+	@echo "  runselftests    : Run the selftests listed on ubuntu_selftests variable"
+	@echo
+	@echo "  help            : If you are kernel hacking, you need the professional"
+	@echo "                    version of this"
+	@echo
+	@echo "Environment variables:"
+	@echo
+	@echo "  NOKERNLOG       : Do not add upstream kernel commits to changelog"
+	@echo "  CONCURRENCY_LEVEL=X"
+	@echo "                  : Use -jX for kernel compile"
+	@echo "  PRINTSHAS       : Include SHAs for commits in changelog"
+
+printdebian:
+	@echo "$(DEBIAN)"
+
+updateconfigs defaultconfigs editconfigs genconfigs dumpconfigs:
+	dh_testdir;
+ifneq ($(wildcard $(DEBIAN)/config/config.common.ubuntu),)
+	$(SHELL) $(DROOT)/scripts/misc/old-kernelconfig $@ "$(do_enforce_all)"
+else
+	kmake='$(kmake)' skip_checks=$(do_skip_checks) conc_level=$(conc_level) \
+		$(SHELL) $(DROOT)/scripts/misc/kernelconfig $@
+	@rm -rf build
+endif
+
+migrateconfigs:
+ifneq ($(wildcard $(DEBIAN)/config/config.common.ubuntu),)
+	dh_testdir
+	conc_level=$(conc_level) $(SHELL) $(DROOT)/scripts/misc/old-kernelconfig genconfigs
+	rm -rf build
+	mkdir build
+	mv $(DEBIAN)/config/annotations build/.annotations
+	mv $(DEBIAN)/config/README.rst build/.README.rst 2>/dev/null || true
+	rm -rf $(DEBIAN)/config
+	mkdir -p $(DEBIAN)/config
+	debian/scripts/misc/migrate-annotations < build/.annotations > $(DEBIAN)/config/annotations
+	mv build/.README.rst $(DEBIAN)/config/README.rst 2>/dev/null || true
+	rm -rf build
+	kmake='$(kmake)' conc_level=$(conc_level) $(SHELL) $(DROOT)/scripts/misc/kernelconfig updateconfigs
+endif
+
+updateportsconfigs defaultportsconfigs editportsconfigs genportsconfigs askconfigs:
+	dh_testdir;
+	$(SHELL) $(DROOT)/scripts/misc/kernelconfig $@ ports
+	rm -rf build
+
+printenv:
+	dh_testdir
+	@echo "src package name  = $(src_pkg_name)"
+	@echo "series            = $(series)"
+	@echo "release           = $(release)"
+	@echo "revisions         = $(revisions)"
+	@echo "revision          = $(revision)"
+	@echo "uploadnum         = $(uploadnum)"
+	@echo "prev_revisions    = $(prev_revisions)"
+	@echo "prev_revision     = $(prev_revision)"
+	@echo "abinum            = $(abinum)"
+	@echo "upstream_tag      = $(upstream_tag)"
+	@echo "gitver            = $(gitver)"
+	@echo "variants          = $(variants)"
+	@echo "flavours          = $(flavours)"
+	@echo "skipabi           = $(skipabi)"
+	@echo "skipmodule        = $(skipmodule)"
+	@echo "skipdbg           = $(skipdbg)"
+	@echo "ubuntu_log_opts   = $(ubuntu_log_opts)"
+	@echo "CONCURRENCY_LEVEL = $(CONCURRENCY_LEVEL)"
+	@echo "ubuntu_selftests  = $(ubuntu_selftests)"
+	@echo "bin package name  = $(bin_pkg_name)"
+	@echo "hdr package name  = $(hdrs_pkg_name)"
+	@echo "doc package name  = $(doc_pkg_name)"
+	@echo "do_doc_package            = $(do_doc_package)"
+	@echo "do_doc_package_content    = $(do_doc_package_content)"
+	@echo "do_source_package         = $(do_source_package)"
+	@echo "do_source_package_content = $(do_source_package_content)"
+	@echo "do_libc_dev_package       = $(do_libc_dev_package)"
+	@echo "do_flavour_image_package  = $(do_flavour_image_package)"
+	@echo "do_flavour_header_package = $(do_flavour_header_package)"
+	@echo "do_common_headers_indep   = $(do_common_headers_indep)"
+	@echo "do_full_source            = $(do_full_source)"
+	@echo "do_odm_drivers            = $(do_odm_drivers)"
+	@echo "do_tools                  = $(do_tools)"
+	@echo "do_any_tools              = $(do_any_tools)"
+	@echo "do_linux_tools            = $(do_linux_tools)"
+	@echo " do_tools_cpupower         = $(do_tools_cpupower)"
+	@echo " do_tools_perf             = $(do_tools_perf)"
+	@echo " do_tools_bpftool          = $(do_tools_bpftool)"
+	@echo " do_tools_x86              = $(do_tools_x86)"
+	@echo " do_tools_host             = $(do_tools_host)"
+	@echo "do_cloud_tools            = $(do_cloud_tools)"
+	@echo " do_tools_hyperv           = $(do_tools_hyperv)"
+	@echo "any_signed                = $(any_signed)"
+	@echo " uefi_signed               = $(uefi_signed)"
+	@echo " opal_signed               = $(opal_signed)"
+	@echo " sipl_signed               = $(sipl_signed)"
+	@echo "full_build                = $(full_build)"
+	@echo "libc_dev_version          = $(libc_dev_version)"
+	@echo "DEB_HOST_GNU_TYPE         = $(DEB_HOST_GNU_TYPE)"
+	@echo "DEB_BUILD_GNU_TYPE        = $(DEB_BUILD_GNU_TYPE)"
+	@echo "DEB_HOST_ARCH             = $(DEB_HOST_ARCH)"
+	@echo "DEB_BUILD_ARCH            = $(DEB_BUILD_ARCH)"
+	@echo "arch                      = $(arch)"
+	@echo "kmake                     = $(kmake)"
+
+printchanges:
+	@baseCommit=$$(git log --pretty=format:'%H %s' | \
+		gawk '/UBUNTU: '".*Ubuntu-.*`echo $(prev_fullver) | sed 's/+/\\\\+/'`"'(~.*)?$$/ { print $$1; exit }'); \
+	if [ -z "$$baseCommit" ]; then \
+		echo "WARNING: couldn't find a commit for the previous version. Using the lastest one." >&2; \
+		baseCommit=$$(git log --pretty=format:'%H %s' | \
+			gawk '/UBUNTU:\s*Ubuntu-.*$$/ { print $$1; exit }'); \
+	fi; \
+	git log "$$baseCommit"..HEAD | \
+	$(DROOT)/scripts/misc/git-ubuntu-log $(ubuntu_log_opts)
+
+insertchanges: autoreconstruct finalchecks
+	@perl -w -f $(DROOT)/scripts/misc/insert-changes.pl $(DROOT) $(DEBIAN) 
+
+autoreconstruct:
+	# No need for reconstruct for -rc kernels since we don't upload an
+	# orig tarball, so just remove it.
+	if grep -q "^EXTRAVERSION = -rc[0-9]\+$$" Makefile; then \
+		echo "exit 0" >$(DEBIAN)/reconstruct; \
+	else \
+		$(DROOT)/scripts/misc/gen-auto-reconstruct $(upstream_tag) $(DEBIAN)/reconstruct $(DROOT)/source/options; \
+	fi
+
+finalchecks: debian/control
+	$(DROOT)/scripts/misc/final-checks "$(DEBIAN)" "$(prev_fullver)"
+
+diffupstream:
+	@git diff-tree -p refs/remotes/linux-2.6/master..HEAD $(shell ls | grep -vE '^(ubuntu|$(DEBIAN)|\.git.*)')
+
+startnewrelease:
+	dh_testdir
+	@[ -f "$(DEBIAN)/etc/update.conf" ] && . "$(DEBIAN)/etc/update.conf"; \
+	if [ -n "$$BACKPORT_SUFFIX" ]; then \
+		ver="$$(dpkg-parsechangelog -l"$$DEBIAN_MASTER/changelog" -SVersion)$${BACKPORT_SUFFIX}.1"; \
+		prev_ver="$$(dpkg-parsechangelog -l"$(DEBIAN)/changelog" -SVersion)"; \
+		if [ "$${ver%.*}" = "$${prev_ver%.*}" ]; then \
+			ver="$${ver%.*}.$$(( $${prev_ver##*.} +1 ))"; \
+		fi; \
+	else \
+		ver="$(release)-$$(echo "$(revision)" | \
+			perl -ne 'if (/^(\d*)\.(\d*)(.*)?$$/) { printf("%d.%d%s\n", $$1 + 1, $$2 +1, $$3) }')"; \
+	fi; \
+	now="$(shell date -R)"; \
+	echo "Creating new changelog set for $$ver..."; \
+	echo -e "$(src_pkg_name) ($$ver) UNRELEASED; urgency=medium\n" > $(DEBIAN)/changelog.new; \
+	echo "  CHANGELOG: Do not edit directly. Autogenerated at release." >> \
+		$(DEBIAN)/changelog.new; \
+	echo "  CHANGELOG: Use the printchanges target to see the curent changes." \
+		>> $(DEBIAN)/changelog.new; \
+	echo "  CHANGELOG: Use the insertchanges target to create the final log." \
+		>> $(DEBIAN)/changelog.new; \
+	echo -e "\n -- $$DEBFULLNAME <$$DEBEMAIL>  $$now\n" >> \
+		$(DEBIAN)/changelog.new ; \
+	cat $(DEBIAN)/changelog >> $(DEBIAN)/changelog.new; \
+	mv $(DEBIAN)/changelog.new $(DEBIAN)/changelog
+
+compileselftests:
+	# a loop is needed here to fail on errors
+	for test in $(ubuntu_selftests); do \
+		$(kmake) -C tools/testing/selftests TARGETS="$$test"; \
+	done;
+
+runselftests:
+	$(kmake) -C tools/testing/selftests TARGETS="$(ubuntu_selftests)" run_tests
--- linux-xilinx-zynqmp-5.4.0.orig/debian/rules.d/2-binary-arch.mk
+++ linux-xilinx-zynqmp-5.4.0/debian/rules.d/2-binary-arch.mk
@@ -0,0 +1,824 @@
+# We don't want make removing intermediary stamps
+.SECONDARY :
+
+# Prepare the out-of-tree build directory
+ifeq ($(do_full_source),true)
+build_cd = cd $(builddir)/build-$*; #
+build_O  =
+else
+build_cd =
+build_O  = O=$(builddir)/build-$*
+endif
+
+# Typically supplied from the arch makefile, e.g., debian.master/control.d/armhf.mk
+ifneq ($(gcc),)
+kmake += CC=$(CROSS_COMPILE)$(gcc)
+endif
+
+shlibdeps_opts = $(if $(CROSS_COMPILE),-- -l$(CROSS_COMPILE:%-=/usr/%)/lib)
+
+debian/scripts/fix-filenames: debian/scripts/fix-filenames.c
+	$(CC) -o $@ $^
+
+$(stampdir)/stamp-prepare-%: config-prepare-check-%
+	@echo Debug: $@
+	@touch $@
+$(stampdir)/stamp-prepare-tree-%: target_flavour = $*
+$(stampdir)/stamp-prepare-tree-%: debian/scripts/fix-filenames
+	@echo Debug: $@
+	install -d $(builddir)/build-$*
+	touch $(builddir)/build-$*/ubuntu-build
+	[ "$(do_full_source)" != 'true' ] && true || \
+		rsync -a --exclude debian --exclude debian.master --exclude $(DEBIAN) * $(builddir)/build-$*
+	if [ -e $(commonconfdir)/config.common.ubuntu ]; then \
+		cat $(commonconfdir)/config.common.ubuntu $(archconfdir)/config.common.$(arch) $(archconfdir)/config.flavour.$(target_flavour) > $(builddir)/build-$*/.config; \
+	else \
+		python3 debian/scripts/misc/annotations --export --arch $(arch) --flavour $(target_flavour) | sed -e 's/.*CONFIG_VERSION_SIGNATURE.*/CONFIG_VERSION_SIGNATURE="Ubuntu $(release)-$(revision)-$* $(raw_kernelversion)"/' > $(builddir)/build-$*/.config; \
+	fi
+	sed -i 's/.*CONFIG_VERSION_SIGNATURE.*/CONFIG_VERSION_SIGNATURE="Ubuntu $(release)-$(revision)-$* $(raw_kernelversion)"/' $(builddir)/build-$*/.config
+	[ "$(do_odm_drivers)" = 'true' ] && true || \
+		sed -ie 's/.*CONFIG_UBUNTU_ODM_DRIVERS.*/# CONFIG_UBUNTU_ODM_DRIVERS is not set/' \
+		    $(builddir)/build-$*/.config
+	find $(builddir)/build-$* -name "*.ko" | xargs rm -f
+	$(build_cd) $(kmake) $(build_O) -j1 syncconfig prepare scripts
+	touch $@
+
+# Used by developers as a shortcut to prepare a tree for compilation.
+prepare-%: $(stampdir)/stamp-prepare-%
+	@echo Debug: $@
+# Used by developers to allow efficient pre-building without fakeroot.
+build-%: $(stampdir)/stamp-build-%
+	@echo Debug: $@
+
+# Do the actual build, including image and modules
+$(stampdir)/stamp-build-%: target_flavour = $*
+$(stampdir)/stamp-build-%: bldimg = $(call custom_override,build_image,$*)
+$(stampdir)/stamp-build-%: $(stampdir)/stamp-prepare-%
+	@echo Debug: $@ build_image $(build_image) bldimg $(bldimg)
+	$(build_cd) $(kmake) $(build_O) $(conc_level) $(bldimg) modules $(if $(filter true,$(do_dtbs)),dtbs)
+
+	@touch $@
+
+define build_dkms_sign =
+	$(shell set -x; if grep -q CONFIG_MODULE_SIG=y $(1)/.config; then
+			echo $(1)/scripts/sign-file $(MODHASHALGO) $(MODSECKEY) $(MODPUBKEY);
+		else
+			echo "-";
+		fi
+	)
+endef
+define build_dkms =
+	CROSS_COMPILE=$(CROSS_COMPILE) $(SHELL) $(DROOT)/scripts/dkms-build $(dkms_dir) $(abi_release)-$* '$(call build_dkms_sign,$(builddir)/build-$*)' $(1) $(2) $(3) $(4) $(5)
+endef
+
+# nvidia_build_payload 450 450 450_450.102.04-0ubuntu0.20.04.1
+# nvidia_build_payload 450-server 450srv 50.102.04-0ubuntu0.20.04.1
+define nvidia_build_payload =
+	$(call build_dkms, $(bldinfo_pkg_name)-$*, $(pkgdir_bldinfo)/usr/lib/linux/$(abi_release)-$*/signatures, "", nvidia-$(2), pool/restricted/n/nvidia-graphics-drivers-$(1)/nvidia-kernel-source-$(1)_$(3)_$(arch).deb pool/restricted/n/nvidia-graphics-drivers-$(1)/nvidia-dkms-$(1)_$(3)_$(arch).deb)
+endef
+# nvidia_build 450
+# nvidia_build 450-server
+define nvidia_build =
+	$(call nvidia_build_payload,$(1),$(shell echo $(1) | sed -e 's/-server/srv/'),$(shell awk '/^nvidia-graphics-drivers-$(1) / {print($$2);}' $(DEBIAN)/dkms-versions))
+
+endef
+
+define install_control =
+	for which in $(3);							\
+	do									\
+		template="$(DROOT)/templates/$(2).$$which.in";			\
+		script="$(DROOT)/$(1).$$which";					\
+		sed -e 's/@abiname@/$(abi_release)/g'				\
+		    -e 's/@localversion@/-$*/g'					\
+		    -e 's/@image-stem@/$(instfile)/g'				\
+			<"$$template" >"$$script";				\
+	done
+endef
+
+# Ensure the directory prefix is exactly 100 characters long so pathnames are the
+# exact same length in any binary files produced by the builds.  These will be
+# commonised later.
+dkms_20d=....................
+dkms_100d=$(dkms_20d)$(dkms_20d)$(dkms_20d)$(dkms_20d)$(dkms_20d)
+dkms_100c=$(shell echo '$(dkms_100d)' | sed -e 's/\./_/g')
+define dkms_dir_prefix =
+$(shell echo $(1)/$(dkms_100c) | \
+	sed -e 's/\($(dkms_100d)\).*/\1/' -e 's/^\(.*\)....$$/\1dkms/')
+endef
+
+# Install the finished build
+install-%: pkgdir_bin = $(CURDIR)/debian/$(bin_pkg_name)-$*
+install-%: pkgdir = $(CURDIR)/debian/$(mods_pkg_name)-$*
+install-%: pkgdir_ex = $(CURDIR)/debian/$(mods_extra_pkg_name)-$*
+install-%: pkgdir_bldinfo = $(CURDIR)/debian/$(bldinfo_pkg_name)-$*
+install-%: bindoc = $(pkgdir)/usr/share/doc/$(bin_pkg_name)-$*
+install-%: dbgpkgdir = $(CURDIR)/debian/$(bin_pkg_name)-$*-dbgsym
+install-%: signingv = $(CURDIR)/debian/$(bin_pkg_name)-signing/$(release)-$(revision)
+install-%: toolspkgdir = $(CURDIR)/debian/$(tools_flavour_pkg_name)-$*
+install-%: cloudpkgdir = $(CURDIR)/debian/$(cloud_flavour_pkg_name)-$*
+install-%: basepkg = $(hdrs_pkg_name)
+install-%: indeppkg = $(indep_hdrs_pkg_name)
+install-%: kernfile = $(call custom_override,kernel_file,$*)
+install-%: instfile = $(call custom_override,install_file,$*)
+install-%: hdrdir = $(CURDIR)/debian/$(basepkg)-$*/usr/src/$(basepkg)-$*
+install-%: target_flavour = $*
+install-%: MODHASHALGO=sha512
+install-%: MODSECKEY=$(builddir)/build-$*/certs/signing_key.pem
+install-%: MODPUBKEY=$(builddir)/build-$*/certs/signing_key.x509
+install-%: build_dir=$(builddir)/build-$*
+install-%: dkms_dir=$(call dkms_dir_prefix,$(builddir)/build-$*)
+install-%: enable_zfs = $(call custom_override,do_zfs,$*)
+install-%: dbgpkgdir_zfs = $(if $(filter true,$(skipdbg)),"",$(dbgpkgdir)/usr/lib/debug/lib/modules/$(abi_release)-$*/kernel)
+install-%: $(stampdir)/stamp-build-% install-headers
+	@echo Debug: $@ kernel_file $(kernel_file) kernfile $(kernfile) install_file $(install_file) instfile $(instfile)
+	dh_testdir
+	dh_testroot
+	dh_prep -p$(bin_pkg_name)-$*
+	dh_prep -p$(mods_pkg_name)-$*
+	dh_prep -p$(hdrs_pkg_name)-$*
+ifneq ($(skipdbg),true)
+	dh_prep -p$(bin_pkg_name)-$*-dbgsym
+endif
+
+	# The main image
+	# compress_file logic required because not all architectures
+	# generate a zImage automatically out of the box
+ifeq ($(compress_file),)
+	install -m600 -D $(builddir)/build-$*/$(kernfile) \
+		$(pkgdir_bin)/boot/$(instfile)-$(abi_release)-$*
+else
+	install -d $(pkgdir_bin)/boot
+	gzip -c9v $(builddir)/build-$*/$(kernfile) > \
+		$(pkgdir_bin)/boot/$(instfile)-$(abi_release)-$*
+	chmod 600 $(pkgdir_bin)/boot/$(instfile)-$(abi_release)-$*
+endif
+
+ifeq ($(uefi_signed),true)
+	install -d $(signingv)
+	# gzipped kernel images must be decompressed for signing
+	if [[ "$(kernfile)" =~ \.gz$$ ]]; then \
+		< $(pkgdir_bin)/boot/$(instfile)-$(abi_release)-$* \
+			gunzip -cv > $(signingv)/$(instfile)-$(abi_release)-$*.efi; \
+		cp -p --attributes-only $(pkgdir_bin)/boot/$(instfile)-$(abi_release)-$* \
+			$(signingv)/$(instfile)-$(abi_release)-$*.efi; \
+		echo "GZIP=1" >> $(signingv)/$(instfile)-$(abi_release)-$*.efi.vars; \
+	else \
+		cp -p $(pkgdir_bin)/boot/$(instfile)-$(abi_release)-$* \
+			$(signingv)/$(instfile)-$(abi_release)-$*.efi; \
+	fi
+endif
+ifeq ($(opal_signed),true)
+	install -d $(signingv)
+	cp -p $(pkgdir_bin)/boot/$(instfile)-$(abi_release)-$* \
+		$(signingv)/$(instfile)-$(abi_release)-$*.opal;
+endif
+ifeq ($(sipl_signed),true)
+	install -d $(signingv)
+	cp -p $(pkgdir_bin)/boot/$(instfile)-$(abi_release)-$* \
+		$(signingv)/$(instfile)-$(abi_release)-$*.sipl;
+endif
+
+	install -d $(pkgdir)/boot
+	install -m644 $(builddir)/build-$*/.config \
+		$(pkgdir)/boot/config-$(abi_release)-$*
+	install -m600 $(builddir)/build-$*/System.map \
+		$(pkgdir)/boot/System.map-$(abi_release)-$*
+	if [ "$(filter true,$(do_dtbs))" ]; then \
+		$(build_cd) $(kmake) $(build_O) $(conc_level) dtbs_install \
+			INSTALL_DTBS_PATH=$(pkgdir)/lib/firmware/$(abi_release)-$*/device-tree; \
+		( cd $(pkgdir)/lib/firmware/$(abi_release)-$*/ && find device-tree -print ) | \
+		while read dtb_file; do \
+			echo "$$dtb_file ?" >> $(DEBIAN)/d-i/firmware/$(arch)/kernel-image; \
+		done; \
+	fi
+ifeq ($(no_dumpfile),)
+	makedumpfile -g $(pkgdir)/boot/vmcoreinfo-$(abi_release)-$* \
+		-x $(builddir)/build-$*/vmlinux
+	chmod 0600 $(pkgdir)/boot/vmcoreinfo-$(abi_release)-$*
+endif
+
+	$(build_cd) $(kmake) $(build_O) $(conc_level) modules_install $(vdso) \
+		INSTALL_MOD_STRIP=1 INSTALL_MOD_PATH=$(pkgdir)/ \
+		INSTALL_FW_PATH=$(pkgdir)/lib/firmware/$(abi_release)-$*
+
+	#
+	# Build module blacklists:
+	#  - blacklist all watchdog drivers (LP:1432837)
+	#
+	install -d $(pkgdir)/lib/modprobe.d
+	echo "# Kernel supplied blacklist for $(src_pkg_name) $(abi_release)-$* $(arch)" \
+		>$(pkgdir)/lib/modprobe.d/blacklist_$(src_pkg_name)_$(abi_release)-$*.conf
+	for conf in $(arch)-$* $(arch) common.conf; do \
+		if [ -f $(DEBIAN)/modprobe.d/$$conf ]; then \
+			echo "# modprobe.d/$$conf"; \
+			cat $(DEBIAN)/modprobe.d/$$conf; \
+		fi; \
+	done >>$(pkgdir)/lib/modprobe.d/blacklist_$(src_pkg_name)_$(abi_release)-$*.conf
+	echo "# Autogenerated watchdog blacklist" \
+		>>$(pkgdir)/lib/modprobe.d/blacklist_$(src_pkg_name)_$(abi_release)-$*.conf
+	ls -1 $(pkgdir)/lib/modules/$(abi_release)-$*/kernel/drivers/watchdog/ | \
+		grep -v '^bcm2835_wdt$$' | \
+		sed -e 's/^/blacklist /' -e 's/.ko$$//' | \
+		sort -u \
+		>>$(pkgdir)/lib/modprobe.d/blacklist_$(src_pkg_name)_$(abi_release)-$*.conf
+
+ifeq ($(do_extras_package),true)
+	#
+	# Remove all modules not in the inclusion list.
+	#
+	if [ -f $(DEBIAN)/control.d/$(target_flavour).inclusion-list ] ; then \
+		/sbin/depmod -v -b $(pkgdir) $(abi_release)-$* | \
+			sed -e "s@$(pkgdir)/lib/modules/$(abi_release)-$*/kernel/@@g" | \
+			awk '{ print $$1 " " $$NF}' >$(build_dir)/module-inclusion.depmap; \
+		mkdir -p $(pkgdir_ex)/lib/modules/$(abi_release)-$*; \
+		mv $(pkgdir)/lib/modules/$(abi_release)-$*/kernel \
+			$(pkgdir_ex)/lib/modules/$(abi_release)-$*/kernel; \
+		$(SHELL) $(DROOT)/scripts/module-inclusion --master \
+			$(pkgdir_ex)/lib/modules/$(abi_release)-$*/kernel \
+			$(pkgdir)/lib/modules/$(abi_release)-$*/kernel \
+			$(DEBIAN)/control.d/$(target_flavour).inclusion-list \
+			$(build_dir)/module-inclusion.depmap 2>&1 | \
+				tee $(target_flavour).inclusion-list.log; \
+		/sbin/depmod -b $(pkgdir) -ea -F $(pkgdir)/boot/System.map-$(abi_release)-$* \
+			$(abi_release)-$* 2>&1 |tee $(target_flavour).depmod.log; \
+		if [ `grep -c 'unknown symbol' $(target_flavour).depmod.log` -gt 0 ]; then \
+			echo "EE: Unresolved module dependencies in base package!"; \
+			exit 1; \
+		fi \
+	fi
+endif
+
+ifeq ($(no_dumpfile),)
+	makedumpfile -g $(pkgdir)/boot/vmcoreinfo-$(abi_release)-$* \
+		-x $(builddir)/build-$*/vmlinux
+	chmod 0600 $(pkgdir)/boot/vmcoreinfo-$(abi_release)-$*
+endif
+	rm -f $(pkgdir)/lib/modules/$(abi_release)-$*/build
+	rm -f $(pkgdir)/lib/modules/$(abi_release)-$*/source
+
+	# Some initramfs-tools specific modules
+	install -d $(pkgdir)/lib/modules/$(abi_release)-$*/initrd
+	if [ -f $(pkgdir)/lib/modules/$(abi_release)-$*/kernel/drivers/video/vesafb.ko ]; then\
+	  $(LN) $(pkgdir)/lib/modules/$(abi_release)-$*/kernel/drivers/video/vesafb.ko \
+		$(pkgdir)/lib/modules/$(abi_release)-$*/initrd/; \
+	fi
+
+	echo "interest linux-update-$(abi_release)-$*" >"$(DROOT)/$(bin_pkg_name)-$*.triggers"
+	install -d $(pkgdir_bin)/usr/lib/linux/triggers
+	$(call install_control,$(bin_pkg_name)-$*,image,postinst postrm preinst prerm)
+	install -d $(pkgdir)/usr/lib/linux/triggers
+	$(call install_control,$(mods_pkg_name)-$*,extra,postinst postrm)
+ifeq ($(do_extras_package),true)
+	# Install the postinit/postrm scripts in the extras package.
+	if [ -f $(DEBIAN)/control.d/$(target_flavour).inclusion-list ] ; then	\
+		install -d $(pkgdir_ex)/usr/lib/linux/triggers; \
+		$(call install_control,$(mods_extra_pkg_name)-$*,extra,postinst postrm); \
+	fi
+endif
+
+	# Install the full changelog.
+ifeq ($(do_doc_package),true)
+	install -d $(bindoc)
+	cat $(DEBIAN)/changelog $(DEBIAN)/changelog.historical | \
+		gzip -9 >$(bindoc)/changelog.Debian.old.gz
+	chmod 644 $(bindoc)/changelog.Debian.old.gz
+endif
+
+ifneq ($(skipsub),true)
+	for sub in $($(*)_sub); do					\
+		if ! (TO=$$sub FROM=$* ABI_RELEASE=$(abi_release) $(SHELL)		\
+			$(DROOT)/scripts/sub-flavour); then exit 1; fi;		\
+		/sbin/depmod -b debian/$(bin_pkg_name)-$$sub		\
+			-ea -F debian/$(bin_pkg_name)-$$sub/boot/System.map-$(abi_release)-$* \
+			$(abi_release)-$*;					\
+		$(call install_control,$(bin_pkg_name)--$$sub,image,postinst postrm preinst prerm); \
+	done
+endif
+
+ifneq ($(skipdbg),true)
+	# Debug image is simple
+	install -m644 -D $(builddir)/build-$*/vmlinux \
+		$(dbgpkgdir)/usr/lib/debug/boot/vmlinux-$(abi_release)-$*
+	$(build_cd) $(kmake) $(build_O) modules_install $(vdso) \
+		INSTALL_MOD_PATH=$(dbgpkgdir)/usr/lib/debug
+	# Add .gnu_debuglink sections only after all/DKMS modules are built.
+	rm -f $(dbgpkgdir)/usr/lib/debug/lib/modules/$(abi_release)-$*/build
+	rm -f $(dbgpkgdir)/usr/lib/debug/lib/modules/$(abi_release)-$*/source
+	rm -f $(dbgpkgdir)/usr/lib/debug/lib/modules/$(abi_release)-$*/modules.*
+	rm -fr $(dbgpkgdir)/usr/lib/debug/lib/firmware
+endif
+
+	# The flavour specific headers image
+	# TODO: Would be nice if we didn't have to dupe the original builddir
+	install -d -m755 $(hdrdir)
+	cat $(builddir)/build-$*/.config | \
+		sed -e 's/.*CONFIG_DEBUG_INFO=.*/# CONFIG_DEBUG_INFO is not set/g' > \
+		$(hdrdir)/.config
+	chmod 644 $(hdrdir)/.config
+	$(kmake) O=$(hdrdir) -j1 syncconfig prepare scripts
+	# We'll symlink this stuff
+	rm -f $(hdrdir)/Makefile
+	rm -rf $(hdrdir)/include2 $(hdrdir)/source
+	# We do not need the retpoline information.
+	find $(hdrdir) -name \*.o.ur-\* | xargs rm -f
+	# Copy over the compilation version.
+	cp "$(builddir)/build-$*/include/generated/compile.h" \
+		"$(hdrdir)/include/generated/compile.h"
+	# Add UTS_UBUNTU_RELEASE_ABI since UTS_RELEASE is difficult to parse.
+	echo "#define UTS_UBUNTU_RELEASE_ABI $(abinum)" >> $(hdrdir)/include/generated/utsrelease.h
+	# powerpc kernel arch seems to need some .o files for external module linking. Add them in.
+ifeq ($(build_arch),powerpc)
+	mkdir -p $(hdrdir)/arch/powerpc/lib
+	cp $(builddir)/build-$*/arch/powerpc/lib/*.o $(hdrdir)/arch/powerpc/lib
+endif
+	# Copy over the new retpoline extractor.
+	cp scripts/ubuntu-retpoline-extract-one $(hdrdir)/scripts
+	# Script to symlink everything up
+	$(SHELL) $(DROOT)/scripts/link-headers "$(hdrdir)" "$(indeppkg)" "$*"
+	# The build symlink
+	install -d debian/$(basepkg)-$*/lib/modules/$(abi_release)-$*
+	$(LN) /usr/src/$(basepkg)-$* \
+		debian/$(basepkg)-$*/lib/modules/$(abi_release)-$*/build
+	# And finally the symvers
+	install -m644 $(builddir)/build-$*/Module.symvers \
+		$(hdrdir)/Module.symvers
+
+	# Now the header scripts
+	$(call install_control,$(hdrs_pkg_name)-$*,headers,postinst)
+
+	# At the end of the package prep, call the tests
+	DPKG_ARCH="$(arch)" KERN_ARCH="$(build_arch)" FLAVOUR="$*"	\
+	 VERSION="$(abi_release)" REVISION="$(revision)"		\
+	 PREV_REVISION="$(prev_revision)" ABI_NUM="$(abinum)"		\
+	 PREV_ABI_NUM="$(prev_abinum)" BUILD_DIR="$(builddir)/build-$*"	\
+	 INSTALL_DIR="$(pkgdir)" SOURCE_DIR="$(CURDIR)"			\
+	 run-parts -v $(DROOT)/tests-build
+
+	#
+	# Remove files which are generated at installation by postinst,
+	# except for modules.order and modules.builtin
+	# 
+	# NOTE: need to keep this list in sync with postrm
+	#
+	mkdir $(pkgdir)/lib/modules/$(abi_release)-$*/_
+	mv $(pkgdir)/lib/modules/$(abi_release)-$*/modules.order \
+		$(pkgdir)/lib/modules/$(abi_release)-$*/_
+	if [ -f $(pkgdir)/lib/modules/$(abi_release)-$*/modules.builtin ] ; then \
+	    mv $(pkgdir)/lib/modules/$(abi_release)-$*/modules.builtin \
+		$(pkgdir)/lib/modules/$(abi_release)-$*/_; \
+	fi
+	if [ -f $(pkgdir)/lib/modules/$(abi_release)-$*/modules.builtin.modinfo ] ; then \
+	    mv $(pkgdir)/lib/modules/$(abi_release)-$*/modules.builtin.modinfo \
+		$(pkgdir)/lib/modules/$(abi_release)-$*/_; \
+	fi
+	rm -f $(pkgdir)/lib/modules/$(abi_release)-$*/modules.*
+	mv $(pkgdir)/lib/modules/$(abi_release)-$*/_/* \
+		$(pkgdir)/lib/modules/$(abi_release)-$*
+	rmdir $(pkgdir)/lib/modules/$(abi_release)-$*/_
+
+ifeq ($(do_linux_tools),true)
+	# Create the linux-tools tool links
+	install -d $(toolspkgdir)/usr/lib/linux-tools/$(abi_release)-$*
+ifeq ($(do_tools_usbip),true)
+	$(LN) ../../$(src_pkg_name)-tools-$(abi_release)/usbip $(toolspkgdir)/usr/lib/linux-tools/$(abi_release)-$*
+	$(LN) ../../$(src_pkg_name)-tools-$(abi_release)/usbipd $(toolspkgdir)/usr/lib/linux-tools/$(abi_release)-$*
+endif
+ifeq ($(do_tools_acpidbg),true)
+	$(LN) ../../$(src_pkg_name)-tools-$(abi_release)/acpidbg $(toolspkgdir)/usr/lib/linux-tools/$(abi_release)-$*
+endif
+ifeq ($(do_tools_cpupower),true)
+	$(LN) ../../$(src_pkg_name)-tools-$(abi_release)/cpupower $(toolspkgdir)/usr/lib/linux-tools/$(abi_release)-$*
+endif
+ifeq ($(do_tools_perf),true)
+	$(LN) ../../$(src_pkg_name)-tools-$(abi_release)/perf $(toolspkgdir)/usr/lib/linux-tools/$(abi_release)-$*
+ifeq ($(do_tools_perf_jvmti),true)
+	$(LN) ../../$(src_pkg_name)-tools-$(abi_release)/libperf-jvmti.so $(toolspkgdir)/usr/lib/linux-tools/$(abi_release)-$*
+endif
+endif
+ifeq ($(do_tools_bpftool),true)
+	$(LN) ../../$(src_pkg_name)-tools-$(abi_release)/bpftool $(toolspkgdir)/usr/lib/linux-tools/$(abi_release)-$*
+endif
+ifeq ($(do_tools_x86),true)
+	$(LN) ../../$(src_pkg_name)-tools-$(abi_release)/x86_energy_perf_policy $(toolspkgdir)/usr/lib/linux-tools/$(abi_release)-$*
+	$(LN) ../../$(src_pkg_name)-tools-$(abi_release)/turbostat $(toolspkgdir)/usr/lib/linux-tools/$(abi_release)-$*
+endif
+endif
+ifeq ($(do_cloud_tools),true)
+ifeq ($(do_tools_hyperv),true)
+	# Create the linux-hyperv tool links
+	install -d $(cloudpkgdir)/usr/lib/linux-tools/$(abi_release)-$*
+	$(LN) ../../$(src_pkg_name)-tools-$(abi_release)/hv_kvp_daemon $(cloudpkgdir)/usr/lib/linux-tools/$(abi_release)-$*
+	$(LN) ../../$(src_pkg_name)-tools-$(abi_release)/hv_vss_daemon $(cloudpkgdir)/usr/lib/linux-tools/$(abi_release)-$*
+	$(LN) ../../$(src_pkg_name)-tools-$(abi_release)/hv_fcopy_daemon $(cloudpkgdir)/usr/lib/linux-tools/$(abi_release)-$*
+	$(LN) ../../$(src_pkg_name)-tools-$(abi_release)/lsvmbus $(cloudpkgdir)/usr/lib/linux-tools/$(abi_release)-$*
+endif
+endif
+
+	# Build a temporary "installed headers" directory.
+	install -d $(dkms_dir) $(dkms_dir)/headers $(dkms_dir)/build $(dkms_dir)/source
+	cp -rp "$(hdrdir)" "$(indep_hdrdir)" "$(dkms_dir)/headers"
+
+	$(if $(filter true,$(enable_zfs)),$(call build_dkms, $(mods_pkg_name)-$*, $(pkgdir)/lib/modules/$(abi_release)-$*/kernel, $(dbgpkgdir_zfs), zfs, pool/universe/z/zfs-linux/zfs-dkms_$(dkms_zfs_linux_version)_all.deb))
+
+	$(if $(filter true,$(do_dkms_wireguard)),$(call build_dkms, $(mods_pkg_name)-$*, $(pkgdir)/lib/modules/$(abi_release)-$*/kernel, "", wireguard, pool/universe/w/wireguard-linux-compat/wireguard-dkms_$(dkms_wireguard_version)_all.deb))
+
+ifeq ($(do_dkms_nvidia),true)
+	$(foreach series,$(nvidia_desktop_series),$(call nvidia_build,$(series)))
+endif
+ifeq ($(do_dkms_nvidia_server),true)
+	$(foreach series,$(nvidia_server_series),$(call nvidia_build,$(series)))
+endif
+
+ifeq ($(do_extras_package),true)
+	$(if $(filter true,$(do_dkms_vbox)),$(call build_dkms, $(mods_pkg_name)-$*, $(pkgdir)/lib/modules/$(abi_release)-$*/kernel, "", virtualbox-guest, pool/multiverse/v/virtualbox/virtualbox-guest-dkms_$(dkms_vbox_guest_version)_all.deb))
+endif
+
+ifneq ($(skipdbg),true)
+	# Add .gnu_debuglink sections to each stripped .ko
+	# pointing to unstripped verson
+	find $(pkgdir) \
+	  $(if $(filter true,$(do_extras_package)),$(pkgdir_ex)) \
+	  -name '*.ko' | while read path_module ; do \
+		module="/lib/modules/$${path_module#*/lib/modules/}"; \
+		if [[ -f "$(dbgpkgdir)/usr/lib/debug/$$module" ]] ; then \
+			while IFS= read -r -d '' signature < <(tail -c 28 "$$path_module"); do \
+				break; \
+			done; \
+			$(CROSS_COMPILE)objcopy \
+				--add-gnu-debuglink=$(dbgpkgdir)/usr/lib/debug/$$module \
+				$$path_module; \
+			if grep -q CONFIG_MODULE_SIG=y $(builddir)/build-$*/.config && \
+			   [ "$$signature" = $$'~Module signature appended~\n' ]; then \
+				$(builddir)/build-$*/scripts/sign-file $(MODHASHALGO) \
+					$(MODSECKEY) \
+					$(MODPUBKEY) \
+					$$path_module; \
+			fi; \
+		else \
+			echo "WARNING: Missing debug symbols for module '$$module'."; \
+		fi; \
+	done
+endif
+
+	# Build the final ABI information.
+	install -d $(abidir)
+	sed -e 's/^\(.\+\)[[:space:]]\+\(.\+\)[[:space:]]\(.\+\)$$/\3 \2 \1/'	\
+		$(builddir)/build-$*/Module.symvers | sort > $(abidir)/$*
+
+	# Build the final ABI modules information.
+	find $(pkgdir_bin) $(pkgdir) $(pkgdir_ex) -name \*.ko | \
+		sed -e 's/.*\/\([^\/]*\)\.ko/\1/' | sort > $(abidir)/$*.modules
+
+	# Build the final ABI firmware information.
+	find $(pkgdir_bin) $(pkgdir) $(pkgdir_ex) -name \*.ko | \
+	while read ko; do \
+		/sbin/modinfo $$ko | grep ^firmware || true; \
+	done | sort -u >$(abidir)/$*.fwinfo
+
+	# Build the final ABI compiler information.
+	ko=$$(find $(pkgdir_bin) $(pkgdir) $(pkgdir_ex) -name \*.ko | head -1); \
+	readelf -p .comment "$$ko" | gawk ' \
+		($$1 == "[") { \
+			printf("%s", $$3); \
+			for (n=4; n<=NF; n++) { \
+				printf(" %s", $$n); \
+			} \
+			print "" \
+		}' | sort -u >$(abidir)/$*.compiler
+
+	# Build the final ABI retpoline information.
+	if grep -q CONFIG_RETPOLINE=y $(builddir)/build-$*/.config; then \
+		echo "# retpoline v1.0" >$(abidir)/$*.retpoline; \
+		$(SHELL) $(DROOT)/scripts/retpoline-extract $(builddir)/build-$* $(CURDIR) | \
+			sort >>$(abidir)/$*.retpoline; \
+	else \
+		echo "# RETPOLINE NOT ENABLED" >$(abidir)/$*.retpoline; \
+	fi
+
+	# Build the buildinfo package content.
+	install -d $(pkgdir_bldinfo)/usr/lib/linux/$(abi_release)-$*
+	install -m644 $(builddir)/build-$*/.config \
+		$(pkgdir_bldinfo)/usr/lib/linux/$(abi_release)-$*/config
+	install -m644 $(abidir)/$* \
+		$(pkgdir_bldinfo)/usr/lib/linux/$(abi_release)-$*/abi
+	install -m644 $(abidir)/$*.modules \
+		$(pkgdir_bldinfo)/usr/lib/linux/$(abi_release)-$*/modules
+	install -m644 $(abidir)/$*.fwinfo \
+		$(pkgdir_bldinfo)/usr/lib/linux/$(abi_release)-$*/fwinfo
+	install -m644 $(abidir)/$*.retpoline \
+		$(pkgdir_bldinfo)/usr/lib/linux/$(abi_release)-$*/retpoline
+	install -m644 $(abidir)/$*.compiler \
+		$(pkgdir_bldinfo)/usr/lib/linux/$(abi_release)-$*/compiler
+	install -m644 $(DROOT)/canonical-certs.pem $(pkgdir_bldinfo)/usr/lib/linux/$(abi_release)-$*/canonical-certs.pem
+	install -m644 $(DROOT)/canonical-revoked-certs.pem $(pkgdir_bldinfo)/usr/lib/linux/$(abi_release)-$*/canonical-revoked-certs.pem
+
+headers_tmp := $(CURDIR)/debian/tmp-headers
+headers_dir := $(CURDIR)/debian/linux-libc-dev
+
+hmake := $(MAKE) -C $(CURDIR) O=$(headers_tmp) \
+	KERNELVERSION=$(abi_release) INSTALL_HDR_PATH=$(headers_tmp)/install \
+	SHELL="$(SHELL)" ARCH=$(header_arch)
+
+install-arch-headers:
+	@echo Debug: $@
+	dh_testdir
+	dh_testroot
+ifeq ($(do_libc_dev_package),true)
+	dh_prep -plinux-libc-dev
+endif
+
+	rm -rf $(headers_tmp)
+	install -d $(headers_tmp) $(headers_dir)/usr/include/
+
+	$(hmake) $(defconfig)
+	mv $(headers_tmp)/.config $(headers_tmp)/.config.old
+	sed -e 's/^# \(CONFIG_MODVERSIONS\) is not set$$/\1=y/' \
+	  -e 's/.*CONFIG_LOCALVERSION_AUTO.*/# CONFIG_LOCALVERSION_AUTO is not set/' \
+	  $(headers_tmp)/.config.old > $(headers_tmp)/.config
+	$(hmake) syncconfig
+	$(hmake) headers_install
+
+	( cd $(headers_tmp)/install/include/ && \
+		find . -name '.' -o -name '.*' -prune -o -print | \
+                cpio -pvd --preserve-modification-time \
+			$(headers_dir)/usr/include/ )
+	mkdir $(headers_dir)/usr/include/$(DEB_HOST_MULTIARCH)
+	mv $(headers_dir)/usr/include/asm $(headers_dir)/usr/include/$(DEB_HOST_MULTIARCH)/
+
+	rm -rf $(headers_tmp)
+
+define dh_all
+	dh_installchangelogs -p$(1)
+	dh_installdocs -p$(1)
+	dh_compress -p$(1)
+	dh_fixperms -p$(1) -X/boot/
+	dh_shlibdeps -p$(1) $(shlibdeps_opts)
+	dh_installdeb -p$(1)
+	dh_installdebconf -p$(1)
+	$(lockme) dh_gencontrol -p$(1) -- -Vlinux:rprovides='$(rprovides)'
+	dh_md5sums -p$(1)
+	dh_builddeb -p$(1)
+endef
+define newline
+
+
+endef
+define dh_all_inline
+        $(subst ${newline},; \${newline},$(call dh_all,$(1)))
+endef
+
+binary-arch-headers: install-arch-headers
+	@echo Debug: $@
+	dh_testdir
+	dh_testroot
+ifeq ($(do_libc_dev_package),true)
+ifneq ($(DEBIAN),debian.master)
+	echo "non-master branch building linux-libc-dev, aborting"
+	exit 1
+endif
+	$(call dh_all,linux-libc-dev)
+endif
+
+binary-%: pkgimg = $(bin_pkg_name)-$*
+binary-%: pkgimg_mods = $(mods_pkg_name)-$*
+binary-%: pkgimg_ex = $(mods_extra_pkg_name)-$*
+binary-%: pkgdir_ex = $(CURDIR)/debian/$(extra_pkg_name)-$*
+binary-%: pkgbldinfo = $(bldinfo_pkg_name)-$*
+binary-%: pkghdr = $(hdrs_pkg_name)-$*
+binary-%: dbgpkg = $(bin_pkg_name)-$*-dbgsym
+binary-%: dbgpkgdir = $(CURDIR)/debian/$(bin_pkg_name)-$*-dbgsym
+binary-%: pkgtools = $(tools_flavour_pkg_name)-$*
+binary-%: pkgcloud = $(cloud_flavour_pkg_name)-$*
+binary-%: rprovides = $(if $(filter true,$(call custom_override,do_zfs,$*)),spl-modules$(comma) spl-dkms$(comma) zfs-modules$(comma) zfs-dkms$(comma))
+binary-%: rprovides += $(if $(filter true,$(call custom_override,do_dkms_vbox,$*)),virtualbox-guest-dkms$(comma))
+binary-%: target_flavour = $*
+binary-%: checks-%
+	@echo Debug: $@
+	dh_testdir
+	dh_testroot
+
+	$(call dh_all,$(pkgimg))
+	$(call dh_all,$(pkgimg_mods))
+
+ifeq ($(do_extras_package),true)
+  ifeq ($(ship_extras_package),false)
+	# If $(ship_extras_package) is explicitly set to false, then do not
+	# construct the linux-image-extra package; instead just log all of the
+	# "extra" modules which were pointlessly built yet won't be shipped.
+	find $(pkgdir_ex) -name '*.ko' | sort \
+		| sed 's|^$(pkgdir_ex)/|NOT-SHIPPED |' \
+		| tee -a $(target_flavour).not-shipped.log;
+  else
+	if [ -f $(DEBIAN)/control.d/$(target_flavour).inclusion-list ] ; then \
+		$(call dh_all_inline,$(pkgimg_ex)); \
+	fi
+  endif
+endif
+
+	$(call dh_all,$(pkgbldinfo))
+	$(call dh_all,$(pkghdr))
+
+ifneq ($(skipsub),true)
+	@set -e; for sub in $($(*)_sub); do		\
+		pkg=$(bin_pkg_name)-$$sub;		\
+		$(call dh_all_inline,$$pkg);		\
+	done
+endif
+
+ifneq ($(skipdbg),true)
+	$(call dh_all,$(dbgpkg))
+
+	# Hokay...here's where we do a little twiddling...
+	# Renaming the debug package prevents it from getting into
+	# the primary archive, and therefore prevents this very large
+	# package from being mirrored. It is instead, through some
+	# archive admin hackery, copied to http://ddebs.ubuntu.com.
+	#
+	mv ../$(dbgpkg)_$(release)-$(revision)_$(arch).deb \
+		../$(dbgpkg)_$(release)-$(revision)_$(arch).ddeb
+	set -e; \
+	( \
+		$(lockme_cmd) 9 || exit 1; \
+		if grep -qs '^Build-Debug-Symbols: yes$$' /CurrentlyBuilding; then \
+			sed -i '/^$(dbgpkg)_/s/\.deb /.ddeb /' debian/files; \
+		else \
+			grep -v '^$(dbgpkg)_.*$$' debian/files > debian/files.new; \
+			mv debian/files.new debian/files; \
+		fi; \
+	) 9>$(lockme_file)
+	# Now, the package wont get into the archive, but it will get put
+	# into the debug system.
+endif
+
+ifeq ($(do_linux_tools),true)
+	$(call dh_all,$(pkgtools))
+endif
+ifeq ($(do_cloud_tools),true)
+	$(call dh_all,$(pkgcloud))
+endif
+
+ifneq ($(full_build),false)
+	# Clean out this flavours build directory.
+	rm -rf $(builddir)/build-$*
+	# Clean out the debugging package source directory.
+	rm -rf $(dbgpkgdir)
+endif
+
+#
+# per-architecture packages
+#
+builddirpa = $(builddir)/tools-perarch
+
+$(stampdir)/stamp-prepare-perarch:
+	@echo Debug: $@
+ifeq ($(do_any_tools),true)
+	rm -rf $(builddirpa)
+	install -d $(builddirpa)
+	rsync -a --exclude debian --exclude debian.master --exclude $(DEBIAN) --exclude .git -a ./ $(builddirpa)/
+endif
+	touch $@
+
+$(stampdir)/stamp-build-perarch: $(stampdir)/stamp-prepare-perarch install-arch-headers
+	@echo Debug: $@
+ifeq ($(do_linux_tools),true)
+ifeq ($(do_tools_usbip),true)
+	chmod 755 $(builddirpa)/tools/usb/usbip/autogen.sh
+	cd $(builddirpa)/tools/usb/usbip && ./autogen.sh
+	chmod 755 $(builddirpa)/tools/usb/usbip/configure
+	cd $(builddirpa)/tools/usb/usbip && ./configure --prefix=$(builddirpa)/tools/usb/usbip/bin
+	cd $(builddirpa)/tools/usb/usbip && make install CFLAGS="-g -O2 -static" CROSS_COMPILE=$(CROSS_COMPILE)
+endif
+ifeq ($(do_tools_acpidbg),true)
+	cd $(builddirpa)/tools/power/acpi && make clean && make CFLAGS="-g -O2 -static -I$(builddirpa)/include" CROSS_COMPILE=$(CROSS_COMPILE) acpidbg
+endif
+ifeq ($(do_tools_cpupower),true)
+	# Allow for multiple installed versions of cpupower and libcpupower.so:
+	# Override LIB_MIN in order to to generate a versioned .so named
+	# libcpupower.so.$(abi_release) and link cpupower with that.
+	make -C $(builddirpa)/tools/power/cpupower \
+		CROSS_COMPILE=$(CROSS_COMPILE) \
+		CROSS=$(CROSS_COMPILE) \
+		LIB_MIN=$(abi_release) CPUFREQ_BENCH=false
+endif
+ifeq ($(do_tools_perf),true)
+	cd $(builddirpa) && $(kmake) $(defconfig)
+	mv $(builddirpa)/.config $(builddirpa)/.config.old
+	sed -e 's/^# \(CONFIG_MODVERSIONS\) is not set$$/\1=y/' \
+	  -e 's/.*CONFIG_LOCALVERSION_AUTO.*/# CONFIG_LOCALVERSION_AUTO is not set/' \
+	  $(builddirpa)/.config.old > $(builddirpa)/.config
+	cd $(builddirpa) && $(kmake) syncconfig
+	cd $(builddirpa) && $(kmake) prepare
+	cd $(builddirpa)/tools/perf && \
+		$(kmake) prefix=/usr HAVE_NO_LIBBFD=1 HAVE_CPLUS_DEMANGLE_SUPPORT=1 CROSS_COMPILE=$(CROSS_COMPILE) NO_LIBPYTHON=1 NO_LIBPERL=1
+endif
+ifeq ($(do_tools_bpftool),true)
+	$(kmake) CROSS_COMPILE=$(CROSS_COMPILE) -C $(builddirpa)/tools/bpf/bpftool
+endif
+ifeq ($(do_tools_x86),true)
+	cd $(builddirpa)/tools/power/x86/x86_energy_perf_policy && make CROSS_COMPILE=$(CROSS_COMPILE)
+	cd $(builddirpa)/tools/power/x86/turbostat && make CROSS_COMPILE=$(CROSS_COMPILE)
+endif
+endif
+ifeq ($(do_cloud_tools),true)
+ifeq ($(do_tools_hyperv),true)
+	cd $(builddirpa)/tools/hv && make CFLAGS="-I$(headers_dir)/usr/include -I$(headers_dir)/usr/include/$(DEB_HOST_MULTIARCH)" CROSS_COMPILE=$(CROSS_COMPILE) hv_kvp_daemon hv_vss_daemon hv_fcopy_daemon
+endif
+endif
+	@touch $@
+
+install-perarch: toolspkgdir = $(CURDIR)/debian/$(tools_pkg_name)
+install-perarch: cloudpkgdir = $(CURDIR)/debian/$(cloud_pkg_name)
+install-perarch: $(stampdir)/stamp-build-perarch
+	@echo Debug: $@
+	# Add the tools.
+ifeq ($(do_linux_tools),true)
+	install -d $(toolspkgdir)/usr/lib
+	install -d $(toolspkgdir)/usr/lib/$(src_pkg_name)-tools-$(abi_release)
+ifeq ($(do_tools_usbip),true)
+	install -m755 $(builddirpa)/tools/usb/usbip/bin/sbin/usbip \
+		$(toolspkgdir)/usr/lib/$(src_pkg_name)-tools-$(abi_release)
+	install -m755 $(builddirpa)/tools/usb/usbip/bin/sbin/usbipd \
+		$(toolspkgdir)/usr/lib/$(src_pkg_name)-tools-$(abi_release)
+endif
+ifeq ($(do_tools_acpidbg),true)
+	install -m755 $(builddirpa)/tools/power/acpi/acpidbg \
+		$(toolspkgdir)/usr/lib/$(src_pkg_name)-tools-$(abi_release)
+endif
+ifeq ($(do_tools_cpupower),true)
+	install -m755 $(builddirpa)/tools/power/cpupower/cpupower \
+		$(toolspkgdir)/usr/lib/$(src_pkg_name)-tools-$(abi_release)
+	# Install only the full versioned libcpupower.so.$(abi_release), not
+	# the usual symlinks to it.
+	install -m644 $(builddirpa)/tools/power/cpupower/libcpupower.so.$(abi_release) \
+		$(toolspkgdir)/usr/lib/
+endif
+ifeq ($(do_tools_perf),true)
+	install -m755 $(builddirpa)/tools/perf/perf $(toolspkgdir)/usr/lib/$(src_pkg_name)-tools-$(abi_release)
+ifeq ($(do_tools_perf_jvmti),true)
+	install -m755 $(builddirpa)/tools/perf/libperf-jvmti.so $(toolspkgdir)/usr/lib/$(src_pkg_name)-tools-$(abi_release)
+endif
+endif
+ifeq ($(do_tools_bpftool),true)
+	install -m755 $(builddirpa)/tools/bpf/bpftool/bpftool $(toolspkgdir)/usr/lib/$(src_pkg_name)-tools-$(abi_release)
+endif
+ifeq ($(do_tools_x86),true)
+	install -m755 $(builddirpa)/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy \
+		$(toolspkgdir)/usr/lib/$(src_pkg_name)-tools-$(abi_release)
+	install -m755 $(builddirpa)/tools/power/x86/turbostat/turbostat \
+		$(toolspkgdir)/usr/lib/$(src_pkg_name)-tools-$(abi_release)
+endif
+endif
+ifeq ($(do_cloud_tools),true)
+ifeq ($(do_tools_hyperv),true)
+	install -d $(cloudpkgdir)/usr/lib
+	install -d $(cloudpkgdir)/usr/lib/$(src_pkg_name)-tools-$(abi_release)
+	install -m755 $(builddirpa)/tools/hv/hv_kvp_daemon \
+		$(cloudpkgdir)/usr/lib/$(src_pkg_name)-tools-$(abi_release)
+	install -m755 $(builddirpa)/tools/hv/hv_vss_daemon \
+		$(cloudpkgdir)/usr/lib/$(src_pkg_name)-tools-$(abi_release)
+	install -m755 $(builddirpa)/tools/hv/hv_fcopy_daemon \
+		$(cloudpkgdir)/usr/lib/$(src_pkg_name)-tools-$(abi_release)
+	install -m755 $(builddirpa)/tools/hv/lsvmbus \
+		$(cloudpkgdir)/usr/lib/$(src_pkg_name)-tools-$(abi_release)
+endif
+endif
+
+binary-perarch: toolspkg = $(tools_pkg_name)
+binary-perarch: cloudpkg = $(cloud_pkg_name)
+binary-perarch: install-perarch
+	@echo Debug: $@
+ifeq ($(do_linux_tools),true)
+	$(call dh_all,$(toolspkg))
+endif
+ifeq ($(do_cloud_tools),true)
+	$(call dh_all,$(cloudpkg))
+endif
+
+binary-debs: signing = $(CURDIR)/debian/$(bin_pkg_name)-signing
+binary-debs: signingv = $(CURDIR)/debian/$(bin_pkg_name)-signing/$(release)-$(revision)
+binary-debs: signing_tar = $(src_pkg_name)_$(release)-$(revision)_$(arch).tar.gz
+binary-debs: binary-perarch $(addprefix binary-,$(flavours))
+	@echo Debug: $@
+ifeq ($(any_signed),true)
+	install -d $(signingv)/control
+	{ echo "tarball"; } >$(signingv)/control/options
+	cd $(signing) && tar czvf ../../../$(signing_tar) .
+	dpkg-distaddfile $(signing_tar) raw-signing -
+endif
+
+build-arch-deps-$(do_flavour_image_package) += $(addprefix $(stampdir)/stamp-build-,$(flavours))
+build-arch: $(build-arch-deps-true)
+	@echo Debug: $@
+
+ifeq ($(AUTOBUILD),)
+binary-arch-deps-$(do_flavour_image_package) += binary-udebs
+else
+binary-arch-deps-$(do_flavour_image_package) = binary-debs
+endif
+binary-arch-deps-$(do_libc_dev_package) += binary-arch-headers
+ifneq ($(do_common_headers_indep),true)
+binary-arch-deps-$(do_flavour_header_package) += binary-headers
+endif
+binary-arch: $(binary-arch-deps-true)
+	@echo Debug: $@
+
--- linux-xilinx-zynqmp-5.4.0.orig/debian/rules.d/3-binary-indep.mk
+++ linux-xilinx-zynqmp-5.4.0/debian/rules.d/3-binary-indep.mk
@@ -0,0 +1,220 @@
+build-indep:
+	@echo Debug: $@
+
+# The binary-indep dependency chain is:
+#
+# install-headers <- install-doc <- install-source <- install-tools <- install-indep <- binary-indep
+# install-headers <- binary-headers
+#
+indep_hdrpkg = $(indep_hdrs_pkg_name)
+indep_hdrdir = $(CURDIR)/debian/$(indep_hdrpkg)/usr/src/$(indep_hdrpkg)
+install-headers: prepare-indep
+	@echo Debug: $@
+	dh_testdir
+	dh_testroot
+
+ifeq ($(do_flavour_header_package),true)
+	install -d $(indep_hdrdir)
+	find . -path './debian' -prune -o -path './$(DEBIAN)' -prune \
+	  -o -path './include/*' -prune \
+	  -o -path './scripts/*' -prune -o -type f \
+	  \( -name 'Makefile*' -o -name 'Kconfig*' -o -name 'Kbuild*' -o \
+	     -name '*.sh' -o -name '*.pl' -o -name '*.lds' \) \
+	  -print | cpio -pd --preserve-modification-time $(indep_hdrdir)
+	cp -a scripts include $(indep_hdrdir)
+	(find arch -name include -type d -print | \
+		xargs -n1 -i: find : -type f) | \
+		cpio -pd --preserve-modification-time $(indep_hdrdir)
+endif
+
+docpkg = $(doc_pkg_name)
+docdir = $(CURDIR)/debian/$(docpkg)/usr/share/doc/$(docpkg)
+install-doc: prepare-indep
+	@echo Debug: $@
+ifeq ($(do_doc_package),true)
+	dh_testdir
+	dh_testroot
+
+	install -d $(docdir)
+ifeq ($(do_doc_package_content),true)
+	# First the html docs. We skip these for autobuilds
+	if [ -z "$(AUTOBUILD)" ]; then \
+		install -d $(docdir)/$(doc_pkg_name)-tmp; \
+		$(kmake) O=$(docdir)/$(doc_pkg_name)-tmp htmldocs; \
+		install -d $(docdir)/html; \
+		rsync -aL $(docdir)/$(doc_pkg_name)-tmp/Documentation/output/ \
+			$(docdir)/html/; \
+		rm -rf $(docdir)/$(doc_pkg_name)-tmp; \
+	fi
+endif
+	# Copy the rest
+	cp -a Documentation/* $(docdir)
+	find $(docdir) -name .gitignore | xargs rm -f
+endif
+
+srcpkg = linux-source-$(release)
+srcdir = $(CURDIR)/debian/$(srcpkg)/usr/src/$(srcpkg)
+balldir = $(CURDIR)/debian/$(srcpkg)/usr/src/$(srcpkg)/$(srcpkg)
+install-source: prepare-indep
+	@echo Debug: $@
+ifeq ($(do_source_package),true)
+
+	install -d $(srcdir)
+ifeq ($(do_source_package_content),true)
+	find . -path './debian' -prune -o -path './$(DEBIAN)' -prune -o \
+		-path './.*' -prune -o -print | \
+		cpio -pd --preserve-modification-time $(balldir)
+	(cd $(srcdir); tar cf - $(srcpkg)) | bzip2 -9c > \
+		$(srcdir)/$(srcpkg).tar.bz2
+	rm -rf $(balldir)
+	find './debian' './$(DEBIAN)' \
+		-path './debian/linux-*' -prune -o \
+		-path './debian/$(src_pkg_name)-*' -prune -o \
+		-path './debian/build' -prune -o \
+		-path './debian/files' -prune -o \
+		-path './debian/stamps' -prune -o \
+		-path './debian/tmp' -prune -o \
+		-print | \
+		cpio -pd --preserve-modification-time $(srcdir)
+	$(LN) $(srcpkg)/$(srcpkg).tar.bz2 $(srcdir)/..
+endif
+endif
+
+install-tools: toolspkg = $(tools_common_pkg_name)
+install-tools: toolsbin = $(CURDIR)/debian/$(toolspkg)/usr/bin
+install-tools: toolssbin = $(CURDIR)/debian/$(toolspkg)/usr/sbin
+install-tools: toolsman = $(CURDIR)/debian/$(toolspkg)/usr/share/man
+install-tools: toolsbashcomp = $(CURDIR)/debian/$(toolspkg)/usr/share/bash-completion/completions
+install-tools: hosttoolspkg = $(hosttools_pkg_name)
+install-tools: hosttoolsbin = $(CURDIR)/debian/$(hosttoolspkg)/usr/bin
+install-tools: hosttoolsman = $(CURDIR)/debian/$(hosttoolspkg)/usr/share/man
+install-tools: cloudpkg = $(cloud_common_pkg_name)
+install-tools: cloudbin = $(CURDIR)/debian/$(cloudpkg)/usr/bin
+install-tools: cloudsbin = $(CURDIR)/debian/$(cloudpkg)/usr/sbin
+install-tools: cloudman = $(CURDIR)/debian/$(cloudpkg)/usr/share/man
+install-tools: prepare-indep $(stampdir)/stamp-build-perarch
+	@echo Debug: $@
+
+ifeq ($(do_tools_common),true)
+	rm -rf $(builddir)/tools
+	install -d $(builddir)/tools
+	for i in *; do $(LN) $(CURDIR)/$$i $(builddir)/tools/; done
+	rm $(builddir)/tools/tools
+	rsync -a tools/ $(builddir)/tools/tools/
+
+	install -d $(toolsbin)
+	install -d $(toolssbin)
+	install -d $(toolsman)/man1
+	install -d $(toolsman)/man8
+	install -d $(toolsbashcomp)
+
+	install -m755 debian/tools/generic $(toolsbin)/usbip
+	install -m755 debian/tools/generic $(toolsbin)/usbipd
+	install -m644 $(CURDIR)/tools/usb/usbip/doc/*.8 $(toolsman)/man8/
+
+	install -m755 debian/tools/generic $(toolsbin)/cpupower
+	install -m644 $(CURDIR)/tools/power/cpupower/man/*.1 $(toolsman)/man1/
+
+	install -m755 debian/tools/generic $(toolsbin)/perf
+
+	install -m755 debian/tools/generic $(toolssbin)/bpftool
+	make -C $(builddir)/tools/tools/bpf/bpftool doc
+	install -m644 $(builddir)/tools/tools/bpf/bpftool/Documentation/*.8 \
+		$(toolsman)/man8
+	install -m644 $(builddir)/tools/tools/bpf/bpftool/bash-completion/bpftool \
+		$(toolsbashcomp)
+
+	install -m755 debian/tools/generic $(toolsbin)/x86_energy_perf_policy
+	install -m755 debian/tools/generic $(toolsbin)/turbostat
+
+	cd $(builddir)/tools/tools/perf && make man
+	install -m644 $(builddir)/tools/tools/perf/Documentation/*.1 \
+		$(toolsman)/man1
+
+	install -m644 $(CURDIR)/tools/power/x86/x86_energy_perf_policy/*.8 $(toolsman)/man8
+	install -m644 $(CURDIR)/tools/power/x86/turbostat/*.8 $(toolsman)/man8
+
+ifeq ($(do_cloud_tools),true)
+ifeq ($(do_tools_hyperv),true)
+	install -d $(cloudsbin)
+	install -m755 debian/tools/generic $(cloudsbin)/hv_kvp_daemon
+	install -m755 debian/tools/generic $(cloudsbin)/hv_vss_daemon
+	install -m755 debian/tools/generic $(cloudsbin)/hv_fcopy_daemon
+	install -m755 debian/tools/generic $(cloudsbin)/lsvmbus
+	install -m755 debian/cloud-tools/hv_get_dhcp_info $(cloudsbin)
+	install -m755 debian/cloud-tools/hv_get_dns_info $(cloudsbin)
+	install -m755 debian/cloud-tools/hv_set_ifconfig $(cloudsbin)
+
+	install -d $(cloudman)/man8
+	install -m644 $(CURDIR)/tools/hv/*.8 $(cloudman)/man8
+endif
+endif
+
+ifeq ($(do_tools_acpidbg),true)
+	install -m755 debian/tools/generic $(toolsbin)/acpidbg
+endif
+
+endif
+
+ifeq ($(do_tools_host),true)
+	install -d $(hosttoolsbin)
+	install -d $(hosttoolsman)/man1
+
+	install -m 755 $(CURDIR)/tools/kvm/kvm_stat/kvm_stat $(hosttoolsbin)/
+
+	cd $(builddir)/tools/tools/kvm/kvm_stat && make man
+	install -m644 $(builddir)/tools/tools/kvm/kvm_stat/*.1 \
+		$(hosttoolsman)/man1
+endif
+
+prepare-indep:
+	@echo Debug: $@
+	dh_prep -i
+
+install-indep: install-headers install-doc install-source install-tools
+	@echo Debug: $@
+
+# This is just to make it easy to call manually. Normally done in
+# binary-indep target during builds.
+binary-headers: prepare-indep install-headers
+	@echo Debug: $@
+	dh_installchangelogs -p$(indep_hdrpkg)
+	dh_installdocs -p$(indep_hdrpkg)
+	dh_compress -p$(indep_hdrpkg)
+	dh_fixperms -p$(indep_hdrpkg)
+	dh_installdeb -p$(indep_hdrpkg)
+	$(lockme) dh_gencontrol -p$(indep_hdrpkg)
+	dh_md5sums -p$(indep_hdrpkg)
+	dh_builddeb -p$(indep_hdrpkg)
+
+binary-indep: cloudpkg = $(cloud_common_pkg_name)
+binary-indep: install-indep
+	@echo Debug: $@
+	dh_installchangelogs -i
+	dh_installdocs -i
+	dh_compress -i
+	dh_fixperms -i
+ifeq ($(do_tools_common),true)
+ifeq ($(do_cloud_tools),true)
+ifeq ($(do_tools_hyperv),true)
+	dh_installinit -p$(cloudpkg) -n --name hv-kvp-daemon
+	dh_installinit -p$(cloudpkg) -n --name hv-vss-daemon
+	dh_installinit -p$(cloudpkg) -n --name hv-fcopy-daemon
+	dh_installudev -p$(cloudpkg) -n --name hv-kvp-daemon
+	dh_installudev -p$(cloudpkg) -n --name hv-vss-daemon
+	dh_installudev -p$(cloudpkg) -n --name hv-fcopy-daemon
+	dh_systemd_enable -p$(cloudpkg)
+	dh_installinit -p$(cloudpkg) -o --name hv-kvp-daemon
+	dh_installinit -p$(cloudpkg) -o --name hv-vss-daemon
+	dh_installinit -p$(cloudpkg) -o --name hv-fcopy-daemon
+	dh_systemd_start -p$(cloudpkg)
+endif
+	# Keep intel_sgx service disabled by default, so add it after dh_systemd_enable
+	# and dh_systemd_start are called:
+	dh_installinit -p$(cloudpkg) --no-start --no-enable --name intel-sgx-load-module
+endif
+endif
+	dh_installdeb -i
+	$(lockme) dh_gencontrol -i
+	dh_md5sums -i
+	dh_builddeb -i
--- linux-xilinx-zynqmp-5.4.0.orig/debian/rules.d/4-checks.mk
+++ linux-xilinx-zynqmp-5.4.0/debian/rules.d/4-checks.mk
@@ -0,0 +1,14 @@
+checks-%: install-%
+	@echo Debug: $@
+
+# Check the config against the known options list.
+config-prepare-check-%: $(stampdir)/stamp-prepare-tree-%
+	@echo Debug: $@
+	if [ -e $(commonconfdir)/config.common.ubuntu ]; then \
+		perl -f $(DROOT)/scripts/config-check \
+			$(builddir)/build-$*/.config "$(arch)" "$*" "$(commonconfdir)" \
+			"$(skipconfig)" "$(do_enforce_all)"; \
+	else \
+		python3 $(DROOT)/scripts/misc/annotations -f $(commonconfdir)/annotations \
+			--arch $(arch) --flavour $* --check $(builddir)/build-$*/.config; \
+	fi
--- linux-xilinx-zynqmp-5.4.0.orig/debian/rules.d/5-udebs.mk
+++ linux-xilinx-zynqmp-5.4.0/debian/rules.d/5-udebs.mk
@@ -0,0 +1,79 @@
+# Do udebs if not disabled in the arch-specific makefile
+binary-udebs: binary-debs
+	@echo Debug: $@
+ifeq ($(disable_d_i),)
+	@$(MAKE) --no-print-directory -f $(DROOT)/rules DEBIAN=$(DEBIAN) \
+		do-binary-udebs
+endif
+
+do-binary-udebs: linux_udeb_name=$(shell if echo $(src_pkg_name)|egrep -q '(linux-lts|linux-hwe)'; then echo $(src_pkg_name); else echo linux; fi)
+do-binary-udebs: debian/control
+	@echo Debug: $@
+	dh_testdir
+	dh_testroot
+
+	# unpack the kernels into a temporary directory
+	mkdir -p debian/d-i-${arch}
+
+	imagelist=$$(cat $(CURDIR)/$(DEBIAN)/d-i/kernel-versions | grep ^${arch} | gawk '{print $$3}') && \
+	for f in $$imagelist; do \
+	  i=$(release)-$(abinum)-$$f; \
+          for f in \
+		../linux-image-$$i\_$(release)-$(revision)_${arch}.deb \
+		../linux-image-unsigned-$$i\_$(release)-$(revision)_${arch}.deb \
+		../linux-modules-$$i\_$(release)-$(revision)_${arch}.deb \
+		../linux-modules-extra-$$i\_$(release)-$(revision)_${arch}.deb; \
+	  do \
+		  [ -f $$f ] && dpkg -x $$f debian/d-i-${arch}; \
+	  done; \
+	  /sbin/depmod -b debian/d-i-${arch} $$i; \
+	done
+
+	# kernel-wedge will error if no modules unless this is touched
+	touch $(DEBIAN)/d-i/no-modules
+
+	touch $(CURDIR)/$(DEBIAN)/d-i/ignore-dups
+	export KW_DEFCONFIG_DIR=$(CURDIR)/$(DEBIAN)/d-i && \
+	export KW_CONFIG_DIR=$(CURDIR)/$(DEBIAN)/d-i && \
+	export SOURCEDIR=$(CURDIR)/debian/d-i-${arch} && \
+	  kernel-wedge install-files $(release)-$(abinum) && \
+	  kernel-wedge check
+
+        # Build just the udebs
+	dilist=$$(dh_listpackages -s | grep "\-di$$") && \
+	[ -z "$dilist" ] || \
+	for i in $$dilist; do \
+	  dh_fixperms -p$$i; \
+	  $(lockme) dh_gencontrol -p$$i; \
+	  dh_builddeb -p$$i; \
+	done
+	
+	# Generate the meta-udeb dependancy lists.
+	@gawk '										\
+		/^Package:/ {								\
+			package=$$2; flavour=""; parch="" }				\
+		(/Package-Type: udeb/ && package !~ /^$(linux_udeb_name)-udebs-/) {      \
+			match(package, "'$(release)'-'$(abinum)'-(.*)-di", bits);       \
+			flavour = bits[1];						\
+		}									\
+		(/^Architecture:/ && $$0 " " ~ / '$(arch)'/) {				\
+			parch=$$0;							\
+		}									\
+		(flavour != "" && parch != "") {					\
+			udebs[flavour] = udebs[flavour] package ", ";			\
+			flavour=""; parch="";						\
+		}                                                      			\
+		END {                                                  			\
+			for (flavour in udebs) {					\
+				package="$(linux_udeb_name)-udebs-" flavour;		\
+				file="debian/" package ".substvars";			\
+				print("udeb:Depends=" udebs[flavour]) > file;		\
+				metas="'$(builddir)'/udeb-meta-packages";		\
+				print(package) >metas					\
+			}								\
+		}									\
+	' <$(CURDIR)/debian/control
+	@while read i; do \
+		$(lockme) dh_gencontrol -p$$i; \
+		dh_builddeb -p$$i; \
+	done <$(builddir)/udeb-meta-packages
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/config-check
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/config-check
@@ -0,0 +1,163 @@
+#!/usr/bin/perl
+#
+# check-config -- check the current config for issues
+#
+use strict;
+use File::Basename;
+use File::Spec;
+
+my $P = 'check-config';
+
+my $test = -1;
+if ($ARGV[0] eq '--test') {
+	$test = $ARGV[1] + 0;
+} elsif ($#ARGV != 5) {
+	die "Usage: $P <config> <arch> <flavour> <commonconfig> <warn-only> <enforce-all>\n";
+}
+
+my ($configfile, $arch, $flavour, $commonconfig, $warn_only, $enforce_all) = @ARGV;
+
+my %values = ();
+
+# If we are in overridden then still perform the checks and emit the messages
+# but do not return failure.  Those items marked FATAL will alway trigger
+# failure.
+my $fail_exit = 1;
+$fail_exit = 0 if ($warn_only eq 'true' || $warn_only eq '1');
+my $exit_val = 0;
+
+$enforce_all = 0 if $enforce_all eq "no" or $enforce_all eq "false";
+
+# Load up the current configuration values -- FATAL if this fails
+print "$P: $configfile: loading config\n";
+open(CONFIG, "<$configfile") || die "$P: $configfile: open failed -- $! -- aborting\n";
+while (<CONFIG>) {
+	# Pull out values.
+	/^#*\s*(CONFIG_\w+)[\s=](.*)$/ or next;
+	if ($2 eq 'is not set') {
+		$values{$1} = 'n';
+	} else {
+		$values{$1} = $2;
+	}
+}
+close(CONFIG);
+
+sub read_annotations {
+    my ($filename) = @_;
+    my %annot;
+    my $form = 1;
+    my ($config, $value, $options);
+
+    # Keep track of the configs that shouldn't be appended because
+    # they were include_annot from another annotations file.
+    # That's a hash of undefs, aka a set.
+    my %noappend;
+
+    print "$P: $filename loading annotations\n";
+    open(my $fd, "<$filename") ||
+	die "$P: $filename: open failed -- $! -- aborting\n";
+    while (<$fd>) {
+	if (/^# FORMAT: (\S+)/) {
+	    die "$P: $1: unknown annotations format\n" if ($1 < 2 || $1 > 4);
+	    $form = $1;
+	}
+
+	# Format #3 and #4 add the include directive on top of format #2:
+	if ($form >= 3 && /^\s*include(\s|$)/) {
+	    # Include quoted or unquoted files:
+	    if (/^\s*include\s+"(.*)"\s*$/ || /^\s*include\s+(.*)$/) {
+		# The include is relative to the current file
+		my $include_filename = File::Spec->join(dirname($filename), $1);
+		# Append the include files
+		my %include_annot = read_annotations($include_filename);
+		%annot = ( %annot, %include_annot );
+		# And marked them to not be appended:
+		my %included_noappend;
+		# Discard the values and keep only the keys
+		@included_noappend{keys %include_annot} = ();
+		%noappend = ( %noappend, %included_noappend );
+		next;
+	    } else {
+		die "$P: Invalid include: $_";
+	    }
+	}
+
+	/^#/ && next;
+	chomp;
+	/^$/ && next;
+	/^CONFIG_/ || next;
+
+	if ($form == 1) {
+	    ($config, $value, $options) = split(' ', $_, 3);
+	} elsif ($form >= 2) {
+	    ($config, $options) = split(' ', $_, 2);
+	}
+
+	if (exists $noappend{$config}) {
+	    delete $annot{$config};
+	    delete $noappend{$config};
+	}
+	$annot{$config} = $annot{$config} . ' ' . $options;
+    }
+    close($fd);
+    return %annot;
+}
+
+# ANNOTATIONS: check any annotations marked for enforcement
+my $annotations = "$commonconfig/annotations";
+my %annot = read_annotations($annotations);
+
+my $pass = 0;
+my $total = 0;
+my ($config, $value, $options, $option, $check, $policy);
+for $config (keys %annot) {
+	$check = $enforce_all;
+	$options = $annot{$config};
+
+	$policy = undef;
+	while ($options =~ /\s*([^\s<]+)<(.*?)?>/g) {
+		($option, $value) = ($1, $2);
+
+		if ($option eq 'mark' && $value eq 'ENFORCED') {
+			$check = 1;
+
+		} elsif ($option eq 'policy') {
+			if ($value =~ /^{/) {
+				$value =~ s/:/=>/g;
+				$policy = eval($value);
+				warn "$config: $@" if ($@);
+			} else {
+				$policy = undef;
+			}
+		}
+	}
+	if ($check == 1 && !defined($policy)) {
+		print "$P: INVALID POLICY (use policy<{...}>) $config$options\n";
+		$total++;
+		$check = 0;
+	}
+	if ($check) {
+		# CONFIG_VERSION_SIGNATURE is dynamically set during the build
+		next if ($config eq "CONFIG_VERSION_SIGNATURE");
+		my $is = '-';
+		$is = $values{$config} if (defined $values{$config});
+
+		my $value = '-';
+		for my $which ("$arch-$flavour", "$arch-*", "*-$flavour", "$arch", "*") {
+			if (defined $policy->{$which}) {
+				$value = $policy->{$which};
+				last;
+			}
+		}
+		if ($is eq $value) {
+			$pass++;
+		} else {
+			print "$P: FAIL ($is != $value): $config$options\n";
+			$exit_val = $fail_exit;
+		}
+		$total++;
+	}
+}
+
+print "$P: $pass/$total checks passed -- exit $exit_val\n";
+exit $exit_val;
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/control-create
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/control-create
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+. debian/debian.env
+
+vars=$1
+any_signed=$2
+
+. $vars
+
+[ "$provides" != '' ] && provides="$provides, "
+
+if [ "$is_sub" = "" ]; then
+	flavour=$(basename $vars | sed 's/.*\.//')
+	stub="${DEBIAN}/control.d/flavour-control.stub debian/control.d/flavour-buildinfo.stub"
+	if [ "$any_signed" = 'true' ]; then
+		sign_me_pkg="-unsigned"
+		sign_me_txt=" unsigned"
+		sign_peer_pkg=""
+	else
+		sign_me_pkg=""
+		sign_me_txt=""
+		sign_peer_pkg="-unsigned"
+	fi
+else
+	flavour=$(basename $vars .vars)
+	stub=${DEBIAN}/sub-flavours/control.stub
+fi
+
+cat $stub | grep -v '^#' | sed \
+	-e "s#FLAVOUR#$flavour#g"		\
+	-e "s#DESC#$desc#g"			\
+	-e "s#ARCH#$arch#g"			\
+	-e "s#SUPPORTED#$supported#g"		\
+	-e "s#TARGET#$target#g"			\
+	-e "s#BOOTLOADER#$bootloader#g" 	\
+	-e "s#=PROVIDES=#$provides#g"		\
+	-e "s#=CONFLICTS=#$conflicts#g"		\
+	-e "s#=SIGN-ME-PKG=#$sign_me_pkg#g"	\
+	-e "s#=SIGN-ME-TXT=#$sign_me_txt#g"	\
+	-e "s#=SIGN-PEER-PKG=#$sign_peer_pkg#g"
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/dkms-build
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/dkms-build
@@ -0,0 +1,261 @@
+#!/bin/sh
+set -e
+
+dkms_dir="$1"
+abi_flavour="$2"
+sign="$3"
+pkgname="$4"
+pkgdir="$5"
+dbgpkgdir="$6"
+package="$7"
+shift 7
+
+here=$(dirname "$(readlink -f "${0}")")
+
+srcdir=$(pwd)
+cd "$dkms_dir" || exit 1
+
+built_using_record()
+{
+	local subst="$1"
+	local built_using="$2"
+	if [ ! -f "$subst" ]; then
+		touch "$subst"
+	fi
+	if ! grep -q -s "^linux:BuiltUsing=" "$subst"; then
+		echo "linux:BuiltUsing=" >>"$subst"
+	fi
+	sed -i -e "s/^\(linux:BuiltUsing=.*\)/\1$built_using, /" "$subst"
+}
+
+# ABI: returns present in $? and located path in lpackage_path when found.
+package_present()
+{
+	for lpackage_path in "$1"_*.deb
+	do
+		break
+	done
+	[ -f "$lpackage_path" ]
+}
+
+# Download and extract the DKMS package -- note there may be more
+# than one package to install.
+for package_path in "$@"
+do
+	package_file=$(basename "$package_path")
+	echo "II: dkms-build downloading $package ($package_file)"
+	rpackage=$( echo "$package_path" | sed -e 's@.*/@@' -e 's@_.*@@' )
+	lpackage=$( echo "$rpackage" | sed -e 's@=.*@@' )
+
+	while true
+	do
+		if package_present "$lpackage"; then
+			break
+		fi
+		case "$package_path" in
+		pool/*)
+			# Attempt download from the launchpad librarian first.
+			"$here/file-downloader" "https://launchpad.net/ubuntu/+archive/primary/+files/$package_file" || true
+			if package_present "$lpackage"; then
+				break
+			fi
+
+			# Download from the available pools.
+			for pool in $( grep -h '^deb ' /etc/apt/sources.list /etc/apt/sources.list.d/*.list | awk '{print $2}' | sort -u )
+			do
+				if package_present "$lpackage"; then
+					break
+				fi
+				url="$pool/$package_path"
+				"$here/file-downloader" "$url" && break || true
+				# No components in PPAs.
+				url=$(echo "$url" | sed -e 's@/pool/[^/]*/@/pool/main/@')
+				"$here/file-downloader" "$url" && break || true
+			done
+			;;
+		http*:*)
+			"$here/file-downloader" "$package_path"
+			;;
+		*/*)
+			cp -p "$package_path" .
+			;;
+		*)
+			apt-get download "$rpackage"
+			;;
+		esac
+		break
+	done
+	if ! package_present "$lpackage"; then
+		echo "EE: $lpackage not found"
+		exit 1
+	fi
+
+	dpkg -x "$lpackage"_*.deb "$package"
+
+	lversion=$( echo "$lpackage_path" | sed -e 's@.*/@@' -e 's@_[^_]*$@@' -e 's@.*_@@')
+	#built_using_record "$srcdir/debian/$pkgname.substvars" "$built_using$lpackage (= $lversion)"
+done
+
+# Pick out the package/version from the dkms.conf.
+for dkms_conf in "$package/usr/src"/*/"dkms.conf"
+do
+	break
+done
+
+# It seems some packages have a # in the name which works fine if the
+# package is installed directly, but not so much if we build it out
+# of the normal location.
+sed -i -e '/^PACKAGE_NAME=/ s/#//g' "$dkms_conf"
+
+# Run any dkms-package specfic configuration steps
+dkms_config_specific="$srcdir/$0-configure--$package"
+dkms_config_generic=$(echo "$dkms_config_specific" | sed -e 's/-[0-9][0-9]*$/-N/')
+for dkms_config in "$dkms_config_specific" "$dkms_config_generic"
+do
+	if [ -z "$dkms_config" -o ! -e "$dkms_config" ]; then
+		continue
+	fi
+	echo "II: dkms-build-configure $(basename "$dkms_config") found, executing"
+	"$dkms_config" \
+		"$srcdir" \
+		"$dkms_conf" \
+		"$dkms_dir" \
+		"$abi_flavour" \
+		"$sign" \
+		"$pkgname" \
+		"$pkgdir" \
+		"$dbgpkgdir" \
+		"$package" \
+		"$@" || exit 1
+	break
+done
+
+cat - <<'EOF' >>"$dkms_conf"
+POST_BUILD="ubuntu-save-objects ${dkms_tree}/${PACKAGE_NAME}/${PACKAGE_VERSION}/build ${dkms_tree}/${PACKAGE_NAME}/${PACKAGE_VERSION}/objects $POST_BUILD"
+EOF
+ubuntu_script="$(dirname "$dkms_conf")/ubuntu-save-objects"
+cat - <<'EOF' >"$ubuntu_script"
+#!/bin/sh
+from="$1"
+to="$2"
+script="$3"
+shift 2
+
+# Copy the objects.
+echo "II: copying objects to '$to'"
+mkdir -p "$to"
+(cd "$from" && find -name \*.o -o -name \*.o.ur-\* | cpio -Lpd "$to")
+
+# Call the original post_install script if there is one.
+[ "$script" = '' ] && exit 0
+
+shift
+exec "$(dirname "$0")/$script" "$@"
+EOF
+chmod +x "$ubuntu_script"
+dkms_package=$( sed -ne 's/PACKAGE_NAME="\(.*\)"/\1/p' "$dkms_conf" )
+dkms_version=$( sed -ne 's/PACKAGE_VERSION="\(.*\)"/\1/p' "$dkms_conf" )
+
+# Build the DKMS binaries.
+echo "II: dkms-build building $package"
+fakeroot=""
+[ $(id -u) -ne 0 ] && fakeroot="/usr/bin/fakeroot"
+rc=0
+$fakeroot /usr/sbin/dkms build --no-prepare-kernel --no-clean-kernel \
+	-k "$abi_flavour" \
+	--sourcetree "$dkms_dir/source" \
+	--dkmstree "$dkms_dir/build" \
+	--kernelsourcedir "$dkms_dir/headers/linux-headers-$abi_flavour" \
+	"$dkms_conf" || rc=1
+
+# Find the log and add it to our own.
+for log in "$dkms_dir/build/$dkms_package/$dkms_version/$abi_flavour"/*/"log/make.log" "$dkms_dir/build/$dkms_package/$dkms_version/build/make.log"
+do
+	[ -f "$log" ] && break
+done
+sed -e "s@$dkms_dir@<<DKMSDIR>>@g" <"$log"
+
+# If this build failed then exit here.
+[ "$rc" != 0 ] && exit "$rc"
+
+# Install the modules with debug symbols we possibly built,
+# and strip the original modules for the next install step.
+if [ -n "$dbgpkgdir" ]; then
+	dbgpkgdir="$dbgpkgdir/$package"
+	echo "II: dkms-build installing $package into $dbgpkgdir (debug symbols)"
+	install -d "$dbgpkgdir"
+	find "$dkms_dir/build/$dkms_package/$dkms_version/$abi_version" -name \*.ko |
+	while read module; do
+		vmodule=$( basename "$module" )
+
+		# Check for '.debug_info' section in order to copy module.
+		# Useful if debug symbols are requested but not built for
+		# any reason (including not yet supported by DKMS package).
+		# Strip module just in case even if section isn't present.
+		if ${CROSS_COMPILE}objdump -h -j '.debug_info' "$module" >/dev/null 2>&1
+		then
+			echo "copying $vmodule"
+			cp "$module" "$dbgpkgdir"
+		else
+			echo "ignoring $vmodule (missing debug symbols)"
+		fi
+
+		# Just 'strip -g' as '/usr/sbin/dkms' does.
+		echo "stripping $vmodule"
+		strip -g "$module"
+	done
+fi
+
+# Install and optionally sign the modules we have built.
+pkgdir="$pkgdir/$package"
+echo "II: dkms-build installing $package into $pkgdir"
+install -d "$pkgdir"
+find "$dkms_dir/build/$dkms_package/$dkms_version/$abi_version" -name \*.ko |
+while read module; do
+	vmodule=$( basename "$module" )
+	case "$sign" in
+	--*)
+		echo "copying $vmodule"
+		cp "$module" "$pkgdir"
+		;;
+	*)
+		echo "signing $vmodule"
+		$sign "$module" "$pkgdir/$vmodule"
+		;;
+	esac
+done
+
+find "$dkms_dir/build/$dkms_package/$dkms_version/objects" -name \*.o -print | \
+while read object
+do
+	"$srcdir/debian/scripts/fix-filenames" "$object" "$dkms_dir"
+done
+
+# Finally see if there is a dkms-package specific post processor present.  Hand
+# it the original source directory, destination package directory, the objects
+# as squirreled away, and the log in case it is useful.  Finally pass a formed
+# signing command line in case we need to do that.
+dkms_build_specific="$srcdir/$0--$package"
+dkms_build_generic=$(echo "$dkms_build_specific" | sed -n -e 's/-[0-9][0-9]*[a-z]*$/-N/p')
+for dkms_build in "$dkms_build_specific" "$dkms_build_generic"
+do
+	if [ -z "$dkms_build" -o ! -e "$dkms_build" ]; then
+		continue
+	fi
+	echo "II: dkms-build override $(basename "$dkms_build") found, executing"
+	"$dkms_build" \
+		"$srcdir" \
+		"$dkms_dir/build/$dkms_package/$dkms_version/objects" \
+		"$log" \
+		"$dkms_dir" \
+		"$abi_flavour" \
+		"$sign" \
+		"$pkgname" \
+		"$pkgdir" \
+		"$dbgpkgdir" \
+		"$package" \
+		"$@" || exit 1
+	break
+done
+
+echo "II: dkms-build build $package complete"
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/dkms-build--nvidia-N
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/dkms-build--nvidia-N
@@ -0,0 +1,113 @@
+#!/bin/sh
+set -e
+
+srcdir="$1"
+objects="$2"
+log="$3"
+shift 3
+
+dkms_dir="$1"
+abi_flavour="$2"
+sign="$3"
+pkgname="$4"
+pkgdir="$5"
+dbgpkgdir="$6"
+package="$7"
+shift 7
+
+build="$( dirname "$objects" )/build"
+
+# Copy over the objects ready for reconstruction.  The objects copy contains
+# the *.o files and the *.o-ur* retpoline files to allow the kernel to track
+# any retpoline sequences therein.  For our purposes we only want the *.o
+# files, elide the rest.
+mkdir -p "$pkgdir/bits/scripts"
+(
+	gcc_variant1=$(gcc --version | head -1 | sed -e 's/^gcc/GCC:/')
+	gcc_variant2=$(gcc --version | head -1 | sed -e 's/^\(gcc\) \((.*)\) \(.*\)$/\1 version \3 \2/')
+	cd "$objects" || exit 1
+	find -name \*.o | \
+	while read file
+	do
+		cp --parents "$file" "$pkgdir/bits"
+		"$srcdir/debian/scripts/fix-filenames" "$pkgdir/bits/$file" "$gcc_variant1"
+		"$srcdir/debian/scripts/fix-filenames" "$pkgdir/bits/$file" "$gcc_variant2"
+	done
+)
+
+# Install the support files we need.
+echo "II: copying support files ..."
+for lds_src in \
+	"$dkms_dir/headers/linux-headers-$abi_flavour/scripts/module.lds" \
+	"/usr/src/linux-headers-$abi_flavour/scripts/module.lds" \
+	"$dkms_dir/headers/linux-headers-$abi_flavour/scripts/module-common.lds" \
+	"/usr/src/linux-headers-$abi_flavour/scripts/module-common.lds"
+do
+	[ ! -f "$lds_src" ] && continue
+	echo "II: copying support files ... found $lds_src"
+	cp "$lds_src" "$pkgdir/bits/scripts"
+	break
+done
+
+# Build helper scripts.
+cat - <<'EOL' >"$pkgdir/bits/BUILD"
+[ "$1" = "unsigned" ] && { signed_only=:; shift; }
+[ "$1" = "nocheck" ] && { check_only=:; shift; }
+EOL
+grep /usr/bin/ld.bfd "$log" | grep -v scripts/genksyms/genksyms | sed -e "s@$build/@@g" >>"$pkgdir/bits/BUILD"
+sed -e 's/.*-o  *\([^ ]*\) .*/rm -f \1/g' <"$pkgdir/bits/BUILD" >"$pkgdir/bits/CLEAN"
+
+# As the builds contain the absolute filenames as used.  Use RECONSTRUCT to
+# rebuild the .ko's, sign them, pull off the signatures and then finally clean
+# up again.
+(
+	cd "$pkgdir/bits" || exit 1
+
+	# Add checksum check.
+	echo "\$check_only sha256sum -c SHA256SUMS || exit 1" >>"$pkgdir/bits/BUILD"
+
+	# Add .ko handling to the CLEAN/BUILD dance.
+	for ko in "$pkgdir"/*.ko
+	do
+		ko=$(basename "$ko")
+		echo "\$signed_only cat '$ko' '$ko.sig' >'../$ko'" >>"$pkgdir/bits/BUILD"
+		echo "\$signed_only rm -f '$ko'" >>"$pkgdir/bits/BUILD"
+		echo "rm -f '../$ko'" >>"$pkgdir/bits/CLEAN"
+	done
+
+	# Clear out anything we are not going to distribute and build unsigned .kos.
+	sh ./CLEAN
+	sh ./BUILD unsigned nocheck
+
+	if [ "$sign" = "--custom" ]; then
+		# We are building for and archive custom signing upload.  Keep everything.
+		:
+	elif [ "$sign" = "--lrm" ]; then
+		# We are in the LRM build; grab sha256 checksums and clean up.
+		sha256sum -b *.ko >"SHA256SUMS"
+		sh ./CLEAN
+
+	else
+		# We are in the main kernel, put the .kos together as we will
+		# on the users machine, sign them, and keep just the signature.
+		: >"SHA256SUMS"
+		for ko in *.ko
+		do
+			echo "detached-signature $ko"
+			$sign "$ko" "$ko.signed"
+			length=$( stat --format %s "$ko" )
+			dd if="$ko.signed" of="$ko.sig" bs=1 skip="$length" 2>/dev/null
+
+			rm -f "$ko.signed"
+			# Keep a checksum of the pre-signed object so we can check it is
+			# built correctly in LRM.
+			sha256sum -b "$ko" >>"SHA256SUMS"
+		done
+
+		# Clean out anything which not a signature.
+		mv "$pkgdir/bits/"*.sig "$pkgdir"
+		mv "$pkgdir/bits/SHA256SUMS" "$pkgdir"
+		find "$pkgdir" -name \*.sig -prune -o -name SHA256SUMS -prune -o -type f -print | xargs rm -f
+		find "$pkgdir" -depth -type d -print | xargs rmdir --ignore-fail-on-non-empty
+	fi
+) || exit "$?"
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/dkms-build--virtualbox-guest
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/dkms-build--virtualbox-guest
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+srcdir="$1"
+objects="$2"
+log="$3"
+shift 3
+
+dkms_dir="$1"
+abi_flavour="$2"
+sign="$3"
+pkgname="$4"
+pkgdir="$5"
+dbgpkgdir="$6"
+package="$7"
+shift 7
+
+# We want to ship the vboxvideo.ko from the upstream staging tree, so
+# remove the one built via dkms.
+rm -f "$pkgdir/vboxvideo.ko"
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/dkms-build-configure--zfs
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/dkms-build-configure--zfs
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+srcdir="$1"
+dkms_conf="$2"
+shift 2
+
+dkms_dir="$1"
+abi_flavour="$2"
+sign="$3"
+pkgname="$4"
+pkgdir="$5"
+dbgpkgdir="$6"
+package="$7"
+shift 7
+
+# ZFS debug symbols are enabled in dkms.conf via PACKAGE_CONFIG file.
+if [ -n "$dbgpkgdir" ]; then
+	echo "enable zfs debug symbols"
+	pkg_cfg="$(dirname "$dkms_conf")/pkg_cfg"
+	echo 'ZFS_DKMS_ENABLE_DEBUGINFO=yes' >"$pkg_cfg"
+	echo 'ZFS_DKMS_DISABLE_STRIP=yes'   >>"$pkg_cfg"
+	sed -i "s,^\(PACKAGE_CONFIG=\).*,\1$pkg_cfg," $dkms_conf
+fi
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/file-downloader
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/file-downloader
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+if [ "$#" -ne 1 ]; then
+	echo "Usage: $0 <url>" 1>&2
+	exit 1
+fi
+url="$1"
+
+to=$(basename "$url")
+
+count=0
+what='fetching'
+while :
+do
+	if [ "$count" -eq 20 ]; then
+		echo "EE: excessive redirects" 1>&2
+		exit 1
+	fi
+	count=$(($count+1))
+
+	echo "II: $what $url"
+
+	curl --silent --fail --show-error "$url" -o "$to" -D "$to.hdr" || exit 1
+	redirect=$(awk '/^Location: / {gsub(/^[[:space:]]+|[[:space:]]+$/,"",$2); print $2;}' "$to.hdr")
+	[ -z "$redirect" ] && break
+	what='  following'
+
+	url=$(echo "$redirect" | sed -e 's@https://launchpadlibrarian.net/@http://launchpadlibrarian.net/@')
+	if [ "$redirect" != "$url" ]; then
+		echo "II:   fixing $redirect"
+	fi
+done
+
+exit 0
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/fix-filenames.c
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/fix-filenames.c
@@ -0,0 +1,80 @@
+/*
+ * fix-filenames: find a specified pathname prefix and remove it from
+ *                C strings.
+ *
+ * Copyright (C) 2018 Canonical Ltd.
+ * Author: Andy Whitcroft <apw@canonical.com>
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+int
+main(int argc, char *argv[])
+{
+	int rc;
+	char *in_name;
+	char *prefix;
+	int prefix_len;
+	int in_fd;
+	struct stat in_info;
+	char *in;
+	off_t size;
+	int length;
+
+	if (argc != 3) {
+		fprintf(stderr, "Usage: %s <file> <prefix>\n", argv[0]);
+		exit(1);
+	}
+	in_name    = argv[1];
+	prefix     = argv[2];
+	prefix_len = strlen(prefix);
+
+	in_fd = open(in_name, O_RDWR);
+	if (in_fd < 0) {
+		perror("open input failed");
+		exit(1);
+	}
+
+	rc = fstat(in_fd, &in_info);
+	if (rc < 0) {
+		perror("fstat input failed");
+		exit(1);
+	}
+	size = in_info.st_size;
+
+	in = mmap((void *)0, size, PROT_READ|PROT_WRITE, MAP_SHARED, in_fd, (off_t)0);
+	if (!in) {
+		perror("mmap failed");
+		exit(1);
+	}
+
+	for (; size > 0; size--, in++) {
+		if (*in != *prefix)
+			continue;
+		if (strncmp(in, prefix, prefix_len) != 0)
+			continue;
+		/* In the case of an exact match there there is nothing to move. */
+		if (in[prefix_len] == '\0')
+			length = 0;
+		/* If this is a filename, strip the leading slash. */
+		else if (in[prefix_len] == '/')
+			length = strlen(in + prefix_len + 1) + 1;
+		/* Otherwise just keep the suffix. */
+		else
+			length = strlen(in + prefix_len) + 1;
+
+		/*
+		 * Copy the suffix portion down to the start and clear
+		 * the remainder of the space to 0.
+		 */
+		memmove(in, in + prefix_len + 1, length);
+		memset(in + length, '\0', prefix_len);
+	}
+}
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/link-headers
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/link-headers
@@ -0,0 +1,42 @@
+#!/bin/bash -e
+
+. debian/debian.env
+
+hdrdir="$1"
+symdir="$2"
+flavour="$3"
+
+echo "Symlinking and copying headers for $flavour..."
+
+excludes="( -path ./debian -prune -o -path ./${DEBIAN} -prune -o -path ./.git ) -prune -o"
+
+(
+find . $excludes  -type f \
+	\( -name 'Makefile*' -o -name 'Kconfig*' -o -name 'Kbuild*' -o \
+	-name '*.sh' -o -name '*.pl' -o -name '*.lds' \) -print
+find ./include ./scripts -name .gitignore -prune -o -type f -print
+find ./include -mindepth 1 -maxdepth 1 $excludes -type d -print
+) | (
+while read file; do
+	dir=$file
+	lastdir=$file
+
+	if [ -e "$hdrdir/$file" -o -L "$hdrdir/$file" ]; then
+		continue
+	fi
+
+	while [ ! -e "$hdrdir/$dir" -a ! -L "$hdrdir/$dir" ]; do
+		lastdir=$dir
+		dir=`dirname $dir`
+	done
+	# If the last item to exist is a symlink we assume all is good
+	if [ ! -L "$hdrdir/$dir" ]; then
+		# Turns things like "./foo" into "../"
+		deref="`echo -n $lastdir | sed -e 's/^\.//' -e's,/[^/]*,../,g'`"
+		item="`echo -n $lastdir | sed -e 's/^\.\///'`"
+		ln -s $deref$symdir/$item $hdrdir/$item
+	fi
+done
+)
+
+exit
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/misc/annotations
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/misc/annotations
@@ -0,0 +1,35 @@
+#!/usr/bin/env python3
+# -*- mode: python -*-
+
+# This file is not installed; it's just to run annotations from inside a source
+# distribution without installing it in the system.
+
+import sys
+
+# Prevent generating .pyc files on import
+#
+# We may end up adding these files to our git repos by mistake, so simply
+# prevent generating them in advance.
+#
+# There's a tiny performance penalty with this, because python needs to
+# re-generate the bytecode on-the-fly every time the script is executed, but
+# this overhead is absolutely negligible compared the rest of the kernel build
+# time.
+sys.dont_write_bytecode = True
+
+import os  # noqa: E402 Import not at top of file
+
+from kconfig import run  # noqa: E402 Import not at top of file
+
+
+# Update PATH to make sure that annotations can be executed directly from the
+# source directory.
+def update_path():
+    script_dir = os.path.dirname(os.path.abspath(__file__))
+    current_path = os.environ.get("PATH", "")
+    new_path = f"{script_dir}:{current_path}"
+    os.environ["PATH"] = new_path
+
+
+update_path()
+exit(run.main())
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/misc/arch-has-odm-enabled.sh
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/misc/arch-has-odm-enabled.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+# Evaluate whether arch ($1) will be built with do_odm_drivers set to true.
+set -e
+
+if [ "$1" = "" ]; then
+	# This would be set doing the actual kernel build
+	if [ "$KBUILD_VERBOSE" = "" ]; then
+		return 1
+	fi
+	case $ARCH in
+	x86)	ARCH=amd64;;
+	*)	;;
+	esac
+else
+	ARCH=$1
+fi
+
+TOPDIR=$(dirname $0)/../../..
+. $TOPDIR/debian/debian.env
+RULESDIR=$TOPDIR/$DEBIAN/rules.d
+
+do_odm_drivers=false
+for f in $ARCH.mk hooks.mk; do
+	eval $(cat $RULESDIR/$f | sed -n -e '/do_odm_drivers/s/ \+//gp')
+done
+if [ "$do_odm_drivers" != "true" ]; then
+	return 1
+fi
+
+return 0
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/misc/final-checks
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/misc/final-checks
@@ -0,0 +1,52 @@
+#!/bin/bash
+
+debian="$1"
+abi="$2"
+abi=${abi%~*}
+
+. "$debian/etc/kernelconfig"
+archs=$( awk '/^Architecture:/ { $1=""; for (i=1; i<=NF; i++) { if ($i != "all") { print $i }}}' debian/control | sort -u)
+
+fail=0
+
+failure()
+{
+	echo "EE: $@" 1>&2
+	fail=1
+}
+
+if [ -e $debian/config/config.common.ubuntu ]; then
+    if [ -d debian/certs ]; then
+        if ! grep -q '^CONFIG_SYSTEM_TRUSTED_KEYS="debian/canonical-certs.pem"$' $debian/config/config.common.ubuntu; then
+	    failure "'CONFIG_SYSTEM_TRUSTED_KEYS="debian/canonical-certs.pem"' is required"
+        fi
+    fi
+
+    if [ -d debian/revoked-certs ]; then
+        if ! grep -q '^CONFIG_SYSTEM_REVOCATION_KEYS="debian/canonical-revoked-certs.pem"$' $debian/config/config.common.ubuntu; then
+	    failure "'CONFIG_SYSTEM_REVOCATION_KEYS="debian/canonical-revoked-certs.pem"' is required"
+        fi
+    fi
+fi
+
+for arch in $archs
+do
+	image_pkg=$(awk -F '\\s*=\\s*' '$1 == "do_flavour_image_package" { print $2 }' $debian/rules.d/$arch.mk)
+	if [ "$image_pkg" = "false" ]; then
+		continue
+	fi
+	if [ ! -f "$debian/rules.d/$arch.mk" ]; then
+		continue
+	fi
+	flavours=$(
+		awk '/^\s*flavours\s*=/{
+			sub(/^\s*flavours\s*=\s*/, "");
+			print
+		}' "$debian/rules.d/$arch.mk")
+	for flavour in $flavours
+	do
+		flavour=$(echo "$flavour" | sed -e 's@.*/config.flavour.@@')
+	done
+done
+
+exit "$fail"
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/misc/find-missing-sauce.sh
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/misc/find-missing-sauce.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+#
+# Find the 'UBUNTU: SAUCE:' patches that have been dropped from
+# the previous release.
+#
+PREV_REL=artful
+PREV_REPO=git://kernel.ubuntu.com/ubuntu/ubuntu-${PREV_REL}.git
+
+git fetch ${PREV_REPO} master-next
+git log --pretty=oneline FETCH_HEAD|grep SAUCE|while read c m;do echo $m;done |sort > $$.prev-rel
+git log --pretty=oneline |grep SAUCE|while read c m;do echo $m;done |sort > $$.curr-rel
+
+diff -u $$.prev-rel $$.curr-rel |grep "^-"
+rm -f $$.prev-rel $$.curr-rel
+
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/misc/find-obsolete-firmware
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/misc/find-obsolete-firmware
@@ -0,0 +1,91 @@
+#!/bin/bash
+#
+# Find all duplicate or obsolete firmware that is being carried
+# in the kernel firmware directory. Compare these files against
+# the linux-firmware package for the approriate release. For example,
+# assuming this is raring, then compare the kernel firmware files
+# against the raring branch of linux-firmware.
+#
+# Example: $0 ~/ubuntu/linux-firmware-raring
+
+USEAGE="$0 LINUX-FIRMWARE"
+
+. debian/debian.env
+
+NFWINFO="`find $DEBIAN -name fwinfo|wc -l`"
+if [ ! "$NFWINFO" = "1" ]
+then
+	echo Your repo is hosed. There can only be one fwinfo file.
+	find $DEBIAN -name fwinfo
+	exit 1
+fi
+
+FWINFO="`pwd`/`find $DEBIAN -name fwinfo`"
+
+if [ "$1" = "" ]
+then
+	echo $USEAGE
+	exit 1
+fi
+FW="$1"
+
+if [ ! -f $FW/WHENCE ]
+then
+	echo Bogus linux-firmware directory
+	exit 1
+fi
+if ! egrep -q "^firmware:" $FWINFO
+then
+	echo Bogus firmware info file
+	exit 1
+fi
+
+#
+# Prepare the tree and make firmware.
+#
+TEE="tee -a"
+LO=`pwd`/firmware.txt
+LF=`pwd`/lib/firmware
+rm -rf debian/build $LF $LO
+fakeroot debian/rules clean prepare-generic
+cp debian/build/build-generic/.config .
+mkdir -p $LF
+make firmware_install INSTALL_MOD_PATH=`pwd`
+
+(cd $LF
+find . -type f | while read f
+do
+	BN="`basename $f`"
+
+	if ! grep -q $BN $FWINFO
+	then
+		echo "Unused firmware: $f" | $TEE $LO
+	else
+		if [ -f $FW/$f ]
+		then
+			if ! cmp $FW/$f $f
+			then
+				echo "$f differs" | $TEE $LO
+			else
+				echo "$f is duplicated" | $TEE $LO
+			fi
+		else
+			echo "$f does not exist in $FW" | $TEE $LO
+		fi
+	fi
+done)
+
+#
+# Check for firmware files referenced by the kernel
+# that do not exist in either location.
+#
+cat $FWINFO | while read fwi f
+do
+	if [ -s lib/firmware/$f ] || [ -s $FW/$f ]
+	then
+		continue
+	else
+		echo "Missing firmware $f" | $TEE $LO
+	fi
+done
+
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/misc/fw-to-ihex.sh
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/misc/fw-to-ihex.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+F=$1
+if [ "$F" = "" ]
+then
+	echo You must supply a firmware file.
+	exit 1
+fi
+
+echo "unsigned char d[] = {" > $F.c
+hexdump -v -e '"\t" 8/1 "0x%02x, " "\n"' $F >> $F.c
+echo "};" >> $F.c
+sed -i 's/0x .*$//' $F.c
+
+O="`dirname $F`/`basename $F`.o"
+gcc -o $O -c $F.c
+objcopy -Oihex $F.o $F.ihex
+
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/misc/gen-auto-reconstruct
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/misc/gen-auto-reconstruct
@@ -0,0 +1,89 @@
+#!/bin/bash
+
+if [ "$#" -ne 3 ]; then
+	echo "Usage: $0 <orig tag>|<base release> <reconstruct> <options>" 1>&2
+	exit 1
+fi
+tag="$1"
+reconstruct="$2"
+options="$3"
+
+case "$tag" in
+v*)	;;
+*)	tag="v${tag%.*}" ;;
+esac
+
+# Validate the tag.
+count=$( git tag -l "$tag" | wc -l )
+if [ "$count" != 1 ]; then
+	echo "$0: $tag: tag invalid" 1>&2
+	exit 1
+fi
+
+#git ls-tree -r --full-tree HEAD | grep ^120 | \
+#while read mode type blobid name
+
+(
+	# Identify all new symlinks since the proffered tag.
+	echo "# Recreate any symlinks created since the orig."
+	git diff "$tag.." --raw --no-renames | awk '(/^:000000 120000/ && $5 == "A") { print $NF }' | \
+	while read name
+	do
+		link=$( readlink "$name" )
+
+		echo "[ ! -L '$name' ] && ln -sf '$link' '$name'"
+	done
+
+	# Identify files with execute permissions added since the proffered tag.
+	git diff "$tag.." --raw --no-renames | awk -F '[: \t]' '{print $2, $3, $NF }' | \
+	while IFS=" " read old new name
+	do
+		old=$( printf "0%s" $old )
+		new=$( printf "0%s" $new )
+		changed=$(( (old ^ new) & 0111 ))
+		if [ "$changed" -ne 0 ]; then
+			added=$(( new & 0111 ))
+			if [ "$added" -ne 0 ]; then
+				echo "chmod +x '$name'"
+                       elif [ "$new" -ne 0 ]; then
+				echo "chmod -x '$name'"
+			fi
+		fi
+	done
+
+       # Identify all removed files since the proffered tag.
+	echo "# Remove any files deleted from the orig."
+	git diff "$tag.." --raw --no-renames | awk '(/^:/ && $5 == "D") { print $NF }' | \
+	while read name
+	do
+		echo "rm -f '$name'"
+	done
+
+	# All done, make sure this does not complete in error.
+	echo "exit 0"
+) >"$reconstruct"
+
+(
+	# Identify all new symlinks since the proffered tag.
+	echo "# Ignore any symlinks created since the orig which are rebuilt by reconstruct."
+	git diff "$tag.." --raw --no-renames | awk '(/^:000000 120000/ && $5 == "A") { print $NF }' | \
+	while read name
+	do
+		echo "extend-diff-ignore=^$name\$"
+	done
+) >"$options.update"
+
+
+head='^## autoreconstruct -- begin$'
+foot='^## autoreconstruct -- end$'
+sed -i -e "
+	/$head/,/$foot/{
+		/$head/{
+			p;
+			r $options.update
+		};
+		/$foot/p;
+		d
+	}
+" "$options"
+rm -f "$options.update"
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/misc/get-firmware
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/misc/get-firmware
@@ -0,0 +1,62 @@
+#!/bin/bash
+#
+# Find all files in linux-firmware that are new or different since the previous release
+# and copy them into the kernel firmware directory. You should only do this on the
+# backport branch since it would be redundant on the released kernel. It assumed you've
+# unpacked linux-firmware from each release into separate directories.
+#
+# Example: $0 ~/ubuntu/linux-firmware-precise ~/ubuntu/linux-firmware-quantal
+
+if [ "$1" = "" ] || [ "$2" = "" ] || [ ! -f $1/WHENCE ] || [ ! -f $2/WHENCE ]
+then
+	echo You must supply 2 firmware directories.
+	exit 1
+fi
+
+if [ ! -f debian/debian.env ]
+then
+	echo You must run this script from the root of the repo
+	exit 1
+fi
+. debian/debian.env
+
+NFWINFO="`find $DEBIAN -name fwinfo|wc -l`"
+if [ ! "$NFWINFO" = "1" ]
+then
+	echo Your repo is hosed. There can only be one fwinfo file.
+	find $DEBIAN -name fwinfo
+	exit 1
+fi
+
+FWINFO="`pwd`/`find $DEBIAN -name fwinfo`"
+
+CDIR=`pwd`
+OFW=$1
+NFW=$2
+
+cd $NFW
+#
+# Find all files in $NFW that are new or different from $1
+#
+(find . -type f | egrep -v "debian|git|LICEN|WHEN|READ|Make|configure" | sed 's;\./;;' | \
+while read f
+do
+	if grep -q $f $FWINFO
+	then
+		if [ ! -f $OFW/$f ]
+		then
+			echo $f
+		elif ! cmp $f $OFW/$f > /dev/null
+		then
+			echo $f
+		fi
+	fi
+done) |\
+while read f
+do
+	mkdir -p $CDIR/firmware/`dirname $f`
+	if [ ! -f $CDIR/firmware/`dirname $f`/`basename $f`.ihex ]
+	then
+		cp -v $f $CDIR/firmware/`dirname $f`
+	fi
+done
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/misc/git-ubuntu-log
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/misc/git-ubuntu-log
@@ -0,0 +1,163 @@
+#!/usr/bin/env python3
+
+import codecs
+import json
+import sys
+import textwrap
+import urllib.request
+
+sys.stdin = codecs.getreader("utf-8")(sys.stdin.detach())
+sys.stdout = codecs.getwriter("utf-8")(sys.stdout.detach())
+
+entries = []
+
+
+def add_entry(entry):
+    global tracking_bug
+
+    if entry and "ignore" not in entry:
+        combo = []
+        for bug in set(entry.get("bugs", [])):
+            combo.append(bug)
+        for cve in set(entry.get("cves", [])):
+            combo.append(cve)
+        combo = sorted(combo)
+
+        if len(combo) == 0:
+            if entry.get("subject", "").startswith("UBUNTU"):
+                combo = "__packaging__"
+            else:
+                combo = "__mainline__"
+        else:
+            if entry.get("subject", "") == "UBUNTU: link-to-tracker: update tracking bug":
+                tracking_bug = combo
+            if combo not in keys:
+                keys.append(combo)
+
+        entry["key"] = combo
+        entries.append(entry)
+
+
+# Suck up the git log output and extract the information we need.
+keys = []
+tracking_bug = None
+entry = None
+subject_wait = False
+for line in sys.stdin:
+    if line.startswith("commit "):
+        add_entry(entry)
+        entry = {}
+        subject_wait = True
+
+    elif line.startswith("Author: "):
+        bits = line.strip().split(maxsplit=1)
+        entry["author"] = bits[1]
+
+    elif subject_wait and line.startswith("    "):
+        subject_wait = False
+        entry["subject"] = line.strip()
+
+    elif line.startswith("    BugLink: "):
+        bits = line.strip().split(maxsplit=2)
+        if len(bits) > 2:
+            # There is text after the URL, so use that (after stripping the
+            # enclosing characters)
+            entry.setdefault("bugs", []).append(bits[2][1:-1])
+        elif "launchpad.net" in bits[1]:
+            # Extract the bug number from the launchpad URL
+            bits = bits[1].split("/")
+            entry.setdefault("bugs", []).append(bits[-1])
+
+    elif line.startswith("    CVE-"):
+        entry.setdefault("cves", []).append(line.strip())
+
+    elif line.startswith("    Ignore:"):
+        entry["ignore"] = True
+
+    elif line.startswith("    Properties:"):
+        for prop in line.strip().split()[1:]:
+            if prop in ("ignore", "no-changelog"):
+                entry["ignore"] = True
+
+add_entry(entry)
+
+entries.reverse()
+
+# Go through the entries and clear out authors for upstream commits.
+for entry in entries:
+    if entry["subject"].startswith("UBUNTU:"):
+        entry["subject"] = entry["subject"][7:].strip()
+    else:
+        del entry["author"]
+
+# Lump everything without a bug at the bottom.
+keys.append("__packaging__")
+keys.append("__mainline__")
+
+# Ensure we list the tracking bug updates first.
+if tracking_bug is not None:
+    keys.remove(tracking_bug)
+    keys.insert(0, tracking_bug)
+
+emit_nl = False
+for key in keys:
+    if key == "__packaging__":
+        title_set = ["Miscellaneous Ubuntu changes"]
+    elif key == "__mainline__":
+        title_set = ["Miscellaneous upstream changes"]
+    else:
+        title_set = []
+        for bug in key:
+            if bug.startswith("CVE-"):
+                title_set.append(bug)
+            elif bug.isdigit():
+                # Assume that it is an LP bug number if 'bug' contains only digits
+                bug_info = None
+
+                try:
+                    # urllib.request.urlcleanup()
+                    request = urllib.request.Request("https://api.launchpad.net/devel/bugs/" + bug)
+                    request.add_header("Cache-Control", "no-cache")
+                    with urllib.request.urlopen(request) as response:
+                        data = response.read()
+                        bug_info = json.loads(data.decode("utf-8"))
+
+                    title = bug_info["title"]
+                    if "description" in bug_info:
+                        for line in bug_info["description"].split("\n"):
+                            if line.startswith("Kernel-Description:"):
+                                title = line.split(" ", 1)[1]
+
+                except urllib.error.HTTPError:
+                    title = "INVALID or PRIVATE BUG"
+
+                title += " (LP###" + bug + ")"
+                title_set.append(title)
+            else:
+                # Finally treat 'bug' itself as the title
+                title_set.append(bug)
+
+    emit_title = True
+    for entry in entries:
+        if entry["key"] != key:
+            continue
+
+        if emit_title:
+            if emit_nl:
+                print("")
+            emit_nl = True
+
+            title_lines = textwrap.wrap("#// ".join(title_set), 76)
+            print("  * " + title_lines[0].replace("LP###", "LP: #").replace("#//", " //"))
+            for line in title_lines[1:]:
+                line = line.replace("LP###", "LP: #").replace("#//", " //")
+                print("    " + line)
+
+            emit_title = False
+
+        if key != tracking_bug or (key == tracking_bug and entry["subject"] != "link-to-tracker: update tracking bug"):
+            title_lines = textwrap.wrap(entry["subject"], 76)
+            print("    - " + title_lines[0])
+            for line in title_lines[1:]:
+                line = line.replace("LP###", "LP: #")
+                print("      " + line)
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/misc/insert-changes.pl
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/misc/insert-changes.pl
@@ -0,0 +1,43 @@
+#!/usr/bin/perl -w
+
+my $debian;
+$droot = $ARGV[0] if (defined $ARGV[0]);
+$droot = 'debian' if (!defined $droot);
+$debian = $ARGV[1] if (defined $ARGV[1]);
+$debian = 'debian.master' if (!defined $debian);
+
+system("make -s -f $droot/rules printchanges > $debian/changes");
+
+open(CHANGELOG, "< $debian/changelog") or die "Cannot open changelog";
+open(CHANGES, "< $debian/changes") or die "Cannot open new changes";
+open(NEW, "> $debian/changelog.new") or die "Cannot open new changelog";
+
+$printed = 0;
+my $skip_newline = 0;
+
+while (<CHANGELOG>) {
+	if (/^  CHANGELOG: /) {
+		next if $printed;
+
+		$skip_newline = 1;
+		while (<CHANGES>) {
+			$skip_newline = 0;
+			print NEW;
+		}
+
+		$printed = 1;
+	} else {
+		if (/^$/ && $skip_newline == 1) {
+			$skip_newline = 0;
+			next;
+		}
+		print NEW;
+	}
+}
+
+close(NEW);
+close(CHANGES);
+close(CHANGELOG);
+
+rename("$debian/changelog.new", "$debian/changelog");
+unlink("$debian/changes");
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/misc/insert-mainline-changes
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/misc/insert-mainline-changes
@@ -0,0 +1,42 @@
+#!/usr/bin/perl
+
+if ($#ARGV != 2) {
+	warn "Usage: $0 <changelog> <to> <range>\n";
+	die  "       $0 debian.master/changelog v3.2.3 v3.2.2..v3.2.3\n";
+}
+my ($changelog, $to, $range) = @ARGV;
+
+my @changes = ();
+
+push(@changes, "\n");
+push(@changes, "  [ Upstream Kernel Changes ]\n\n");
+push(@changes, "  * rebase to $to\n");
+
+open(LOG, "git log '$range'|") || die "$0: git log failed: - $!\n";
+while (<LOG>) {
+	if (m@BugLink: .*launchpad.net/.*/([0-9]+)\s$@) {
+		push(@changes, "    - LP: #$1\n");
+	}
+}
+close(LOG);
+
+open(CHANGELOG, "< $changelog") or die "Cannot open changelog";
+open(NEW, "> $changelog.new") or die "Cannot open new changelog";
+
+$printed = 3;
+while (<CHANGELOG>) {
+	if (/^  CHANGELOG: /) {
+		$printed--;
+		print NEW;
+		if ($printed == 0) {
+			print NEW @changes;
+		}
+		next;
+	}
+	print NEW;
+}
+
+close(NEW);
+close(CHANGELOG);
+
+rename("$changelog.new", "$changelog");
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/misc/insert-ubuntu-changes
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/misc/insert-ubuntu-changes
@@ -0,0 +1,83 @@
+#!/usr/bin/perl
+
+if ($#ARGV != 2 && $#ARGV != 3) {
+	die "Usage: $0 <changelog> <stop at> <start at> [<source changelog>]\n";
+}
+if ($#ARGV == 2) {
+	push(@ARGV, "debian.master/changelog")
+}
+my ($changelog, $end, $start, $source_changelog) = @ARGV;
+
+$end =~ s/^\D+//;
+$start =~ s/^\D+//;
+
+sub version_cmp($$) {
+	my @a = split(/[\.-]+/, $_[0]);
+	my @b = split(/[\.-]+/, $_[1]);
+	for (my $i = 1;; $i++) {
+		if (!defined $a[$i]) {
+			if (!defined $b[$i]) {
+				return 0;
+			}
+			return -1;
+		}
+		if (!defined $b[$i]) {
+			return 1;
+		}
+		if ($a[$i] < $b[$i]) {
+			return -1;
+		}
+		if ($a[$i] > $b[$i]) {
+			return 1;
+		}
+	}
+}
+
+my @changes = ();
+my $output = 0;
+open(CHG, "<$source_changelog") ||
+	open(CHG, "<debian/changelog") ||
+	die "$0: debian/changelog: open failed - $!\n";
+while (<CHG>) {
+	if (/^\S+\s+\((.*)\)/) {
+		if (version_cmp($1, $end) <= 0) {
+			last;
+		}
+		if ($1 eq $start) {
+			$output = 1;
+		}
+		if ($output) {
+			push(@changes, "\n  [ Ubuntu: $1 ]\n\n");
+			next;
+		}
+	}
+	next if ($output == 0);
+
+	next if (/^\s*$/);
+	next if (/^\s--/);
+	next if (/^\s\s[^\*\s]/);
+
+	push(@changes, $_);
+}
+close(CHG);
+
+open(CHANGELOG, "< $changelog") or die "Cannot open changelog";
+open(NEW, "> $changelog.new") or die "Cannot open new changelog";
+
+$printed = 3;
+while (<CHANGELOG>) {
+	if (/^  CHANGELOG: /) {
+		$printed--;
+		print NEW;
+		if ($printed == 0) {
+			print NEW @changes;
+		}
+		next;
+	}
+	print NEW;
+}
+
+close(NEW);
+close(CHANGELOG);
+
+rename("$changelog.new", "$changelog");
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/misc/kconfig/annotations.py
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/misc/kconfig/annotations.py
@@ -0,0 +1,521 @@
+# -*- mode: python -*-
+# python module to manage Ubuntu kernel .config and annotations
+# Copyright © 2022 Canonical Ltd.
+
+import json
+import re
+import shutil
+import tempfile
+from abc import abstractmethod
+from ast import literal_eval
+from os.path import abspath, dirname
+
+from kconfig.version import ANNOTATIONS_FORMAT_VERSION
+
+
+class Config:
+    def __init__(self, fname, do_include=True):
+        """
+        Basic configuration file object
+        """
+        self.fname = fname
+        self.config = {}
+        self.do_include = do_include
+
+        raw_data = self._load(fname)
+        self._parse(raw_data)
+
+    @staticmethod
+    def _load(fname: str) -> str:
+        with open(fname, "rt", encoding="utf-8") as fd:
+            data = fd.read()
+        return data.rstrip()
+
+    def __str__(self):
+        """Return a JSON representation of the config"""
+        return json.dumps(self.config, indent=4)
+
+    @abstractmethod
+    def _parse(self, data: str):
+        pass
+
+
+class KConfig(Config):
+    """
+    Parse a .config file, individual config options can be accessed via
+    .config[<CONFIG_OPTION>]
+    """
+
+    def _parse(self, data: str):
+        self.config = {}
+        for line in data.splitlines():
+            m = re.match(r"^# (CONFIG_.*) is not set$", line)
+            if m:
+                self.config[m.group(1)] = literal_eval("'n'")
+                continue
+            m = re.match(r"^(CONFIG_[A-Za-z0-9_]+)=(.*)$", line)
+            if m:
+                self.config[m.group(1)] = literal_eval("'" + m.group(2) + "'")
+                continue
+
+
+class Annotation(Config):
+    """
+    Parse body of annotations file
+    """
+
+    def __init__(self, fname, do_include=True, do_json=False):
+        self.do_json = do_json
+        super().__init__(fname, do_include=True)
+
+    def _parse_body(self, data: str, parent=True):
+        for line in data.splitlines():
+            # Replace tabs with spaces, squeeze multiple into singles and
+            # remove leading and trailing spaces
+            line = line.replace("\t", " ")
+            line = re.sub(r" +", " ", line)
+            line = line.strip()
+
+            # Ignore empty lines
+            if not line:
+                continue
+
+            # Catpure flavors of included files
+            if line.startswith("# FLAVOUR: "):
+                self.include_flavour += line.split(" ")[2:]
+                continue
+
+            # Ignore comments
+            if line.startswith("#"):
+                continue
+
+            # Handle includes (recursively)
+            m = re.match(r'^include\s+"?([^"]*)"?', line)
+            if m:
+                if parent:
+                    self.include.append(m.group(1))
+                if self.do_include:
+                    include_fname = dirname(abspath(self.fname)) + "/" + m.group(1)
+                    include_data = self._load(include_fname)
+                    self._parse_body(include_data, parent=False)
+                continue
+
+            # Handle policy and note lines
+            if re.match(r".* (policy|note)<", line):
+                try:
+                    conf = line.split(" ")[0]
+                    if conf in self.config:
+                        entry = self.config[conf]
+                    else:
+                        entry = {"policy": {}}
+
+                    match = False
+                    m = re.match(r".* policy<(.*?)>", line)
+                    if m:
+                        match = True
+                        # Update the previous entry considering potential overrides:
+                        #  - if the new entry is adding a rule for a new
+                        #    arch/flavour, simply add that
+                        #  - if the new entry is overriding a previous
+                        #    arch-flavour item, then overwrite that item
+                        #  - if the new entry is overriding a whole arch, then
+                        #    remove all the previous flavour rules of that arch
+                        new_entry = literal_eval(m.group(1))
+                        for key in new_entry:
+                            if key in self.arch:
+                                for flavour_key in list(entry["policy"].keys()):
+                                    if flavour_key.startswith(key):
+                                        del entry["policy"][flavour_key]
+                                entry["policy"][key] = new_entry[key]
+                            else:
+                                entry["policy"][key] = new_entry[key]
+
+                    m = re.match(r".* note<(.*?)>", line)
+                    if m:
+                        entry["oneline"] = match
+                        match = True
+                        entry["note"] = "'" + m.group(1).replace("'", "") + "'"
+
+                    if not match:
+                        raise SyntaxError("syntax error")
+                    self.config[conf] = entry
+                except Exception as e:
+                    raise SyntaxError(str(e) + f", line = {line}") from e
+                continue
+
+            # Invalid line
+            raise SyntaxError(f"invalid line: {line}")
+
+    def _legacy_parse(self, data: str):
+        """
+        Parse main annotations file, individual config options can be accessed
+        via self.config[<CONFIG_OPTION>]
+        """
+        self.config = {}
+        self.arch = []
+        self.flavour = []
+        self.flavour_dep = {}
+        self.include = []
+        self.header = ""
+        self.include_flavour = []
+
+        # Parse header (only main header will considered, headers in includes
+        # will be treated as comments)
+        for line in data.splitlines():
+            if re.match(r"^#.*", line):
+                m = re.match(r"^# ARCH: (.*)", line)
+                if m:
+                    self.arch = list(m.group(1).split(" "))
+                m = re.match(r"^# FLAVOUR: (.*)", line)
+                if m:
+                    self.flavour = list(m.group(1).split(" "))
+                m = re.match(r"^# FLAVOUR_DEP: (.*)", line)
+                if m:
+                    self.flavour_dep = literal_eval(m.group(1))
+                self.header += line + "\n"
+            else:
+                break
+
+        # Return an error if architectures are not defined
+        if not self.arch:
+            raise SyntaxError("ARCH not defined in annotations")
+        # Return an error if flavours are not defined
+        if not self.flavour:
+            raise SyntaxError("FLAVOUR not defined in annotations")
+
+        # Parse body
+        self._parse_body(data)
+
+        # Sanity check: Verify that all FLAVOUR_DEP flavors are valid
+        if self.do_include:
+            for src, tgt in self.flavour_dep.items():
+                if src not in self.flavour:
+                    raise SyntaxError(f"Invalid source flavour in FLAVOUR_DEP: {src}")
+                if tgt not in self.include_flavour:
+                    raise SyntaxError(f"Invalid target flavour in FLAVOUR_DEP: {tgt}")
+
+    def _json_parse(self, data, is_included=False):
+        data = json.loads(data)
+
+        # Check if version is supported
+        version = data["attributes"]["_version"]
+        if version > ANNOTATIONS_FORMAT_VERSION:
+            raise SyntaxError(f"annotations format version {version} not supported")
+
+        # Check for top-level annotations vs imported annotations
+        if not is_included:
+            self.config = data["config"]
+            self.arch = data["attributes"]["arch"]
+            self.flavour = data["attributes"]["flavour"]
+            self.flavour_dep = data["attributes"]["flavour_dep"]
+            self.include = data["attributes"]["include"]
+            self.include_flavour = []
+        else:
+            # We are procesing an imported annotations, so merge all the
+            # configs and attributes.
+            try:
+                self.config = data["config"] | self.config
+            except TypeError:
+                self.config = {**self.config, **data["config"]}
+            self.arch = list(set(self.arch) | set(data["attributes"]["arch"]))
+            self.flavour = list(set(self.flavour) | set(data["attributes"]["flavour"]))
+            self.include_flavour = list(set(self.include_flavour) | set(data["attributes"]["flavour"]))
+            self.flavour_dep = self.flavour_dep | data["attributes"]["flavour_dep"]
+
+        # Handle recursive inclusions
+        if self.do_include:
+            for f in data["attributes"]["include"]:
+                include_fname = dirname(abspath(self.fname)) + "/" + f
+                data = self._load(include_fname)
+                self._json_parse(data, is_included=True)
+
+    def _parse(self, data: str):
+        if self.do_json:
+            self._json_parse(data, is_included=False)
+        else:
+            self._legacy_parse(data)
+
+    def _remove_entry(self, config: str):
+        if self.config[config]:
+            del self.config[config]
+
+    def remove(self, config: str, arch: str = None, flavour: str = None):
+        if config not in self.config:
+            return
+        if arch is not None:
+            if flavour is not None:
+                flavour = f"{arch}-{flavour}"
+            else:
+                flavour = arch
+            del self.config[config]["policy"][flavour]
+            if not self.config[config]["policy"]:
+                self._remove_entry(config)
+        else:
+            self._remove_entry(config)
+
+    def set(
+        self,
+        config: str,
+        arch: str = None,
+        flavour: str = None,
+        value: str = None,
+        note: str = None,
+    ):
+        if value is not None:
+            if config not in self.config:
+                self.config[config] = {"policy": {}}
+            if arch is not None:
+                if flavour is not None:
+                    flavour = f"{arch}-{flavour}"
+                else:
+                    flavour = arch
+                self.config[config]["policy"][flavour] = value
+            else:
+                for a in self.arch:
+                    self.config[config]["policy"][a] = value
+        if note is not None:
+            self.config[config]["note"] = "'" + note.replace("'", "") + "'"
+
+    def update(self, c: KConfig, arch: str, flavour: str = None, configs: list = None):
+        """Merge configs from a Kconfig object into Annotation object"""
+
+        # Determine if we need to import all configs or a single config
+        if not configs:
+            configs = c.config.keys()
+            try:
+                configs |= self.search_config(arch=arch, flavour=flavour).keys()
+            except TypeError:
+                configs = {
+                    **configs,
+                    **self.search_config(arch=arch, flavour=flavour).keys(),
+                }
+
+        # Import configs from the Kconfig object into Annotations
+        flavour_arg = flavour
+        if flavour is not None:
+            flavour = arch + f"-{flavour}"
+        else:
+            flavour = arch
+        for conf in configs:
+            if conf in c.config:
+                val = c.config[conf]
+            else:
+                val = "-"
+            if conf in self.config:
+                if "policy" in self.config[conf]:
+                    # Add a TODO if a config with a note is changing and print
+                    # a warning
+                    old_val = self.search_config(config=conf, arch=arch, flavour=flavour_arg)
+                    if old_val:
+                        old_val = old_val[conf]
+                    if val != old_val and "note" in self.config[conf]:
+                        self.config[conf]["note"] = "TODO: update note"
+                        print(f"WARNING: {conf} changed from {old_val} to {val}, updating note")
+                    self.config[conf]["policy"][flavour] = val
+                else:
+                    self.config[conf]["policy"] = {flavour: val}
+            else:
+                self.config[conf] = {"policy": {flavour: val}}
+
+    def _compact(self):
+        # Try to remove redundant settings: if the config value of a flavour is
+        # the same as the one of the main arch simply drop it.
+        for conf in self.config.copy():
+            if "policy" not in self.config[conf]:
+                continue
+            for flavour in self.flavour:
+                if flavour not in self.config[conf]["policy"]:
+                    continue
+                m = re.match(r"^(.*?)-(.*)$", flavour)
+                if not m:
+                    continue
+                arch = m.group(1)
+                if arch in self.config[conf]["policy"]:
+                    if self.config[conf]["policy"][flavour] == self.config[conf]["policy"][arch]:
+                        del self.config[conf]["policy"][flavour]
+                        continue
+                if flavour not in self.flavour_dep:
+                    continue
+                generic = self.flavour_dep[flavour]
+                if generic in self.config[conf]["policy"]:
+                    if self.config[conf]["policy"][flavour] == self.config[conf]["policy"][generic]:
+                        del self.config[conf]["policy"][flavour]
+                        continue
+            # Remove rules for flavours / arches that are not supported (not
+            # listed in the annotations header).
+            for flavour in self.config[conf]["policy"].copy():
+                if flavour not in list(set(self.arch + self.flavour)):
+                    del self.config[conf]["policy"][flavour]
+            # Remove configs that are all undefined across all arches/flavours
+            # (unless we have includes)
+            if not self.include:
+                if "policy" in self.config[conf]:
+                    if list(set(self.config[conf]["policy"].values())) == ["-"]:
+                        self.config[conf]["policy"] = {}
+            # Drop empty rules
+            if not self.config[conf]["policy"]:
+                del self.config[conf]
+            else:
+                # Compact same value across all flavour within the same arch
+                for arch in self.arch:
+                    arch_flavours = [i for i in self.flavour if i.startswith(arch)]
+                    value = None
+                    for flavour in arch_flavours:
+                        if flavour not in self.config[conf]["policy"]:
+                            break
+                        if value is None:
+                            value = self.config[conf]["policy"][flavour]
+                        elif value != self.config[conf]["policy"][flavour]:
+                            break
+                    else:
+                        for flavour in arch_flavours:
+                            del self.config[conf]["policy"][flavour]
+                        self.config[conf]["policy"][arch] = value
+        # After the first round of compaction we may end up having configs that
+        # are undefined across all arches, so do another round of compaction to
+        # drop these settings that are not needed anymore
+        # (unless we have includes).
+        if not self.include:
+            for conf in self.config.copy():
+                # Remove configs that are all undefined across all arches/flavours
+                if "policy" in self.config[conf]:
+                    if list(set(self.config[conf]["policy"].values())) == ["-"]:
+                        self.config[conf]["policy"] = {}
+                # Drop empty rules
+                if not self.config[conf]["policy"]:
+                    del self.config[conf]
+
+    @staticmethod
+    def _sorted(config):
+        """Sort configs alphabetically but return configs with a note first"""
+        w_note = []
+        wo_note = []
+        for c in sorted(config):
+            if "note" in config[c]:
+                w_note.append(c)
+            else:
+                wo_note.append(c)
+        return w_note + wo_note
+
+    def save(self, fname: str):
+        """Save annotations data to the annotation file"""
+        # Compact annotations structure
+        self._compact()
+
+        # Save annotations to disk
+        with tempfile.NamedTemporaryFile(mode="w+t", delete=False) as tmp:
+            # Write header
+            tmp.write(self.header + "\n")
+
+            # Write includes
+            for i in self.include:
+                tmp.write(f'include "{i}"\n')
+            if self.include:
+                tmp.write("\n")
+
+            # Write config annotations and notes
+            tmp.flush()
+            shutil.copy(tmp.name, fname)
+            tmp_a = Annotation(fname)
+
+            # Only save local differences (preserve includes)
+            marker = False
+            for conf in self._sorted(self.config):
+                new_val = self.config[conf]
+                if "policy" not in new_val:
+                    continue
+
+                # If new_val is a subset of old_val, skip it unless there are
+                # new notes that are different than the old ones.
+                old_val = tmp_a.config.get(conf)
+                if old_val and "policy" in old_val:
+                    try:
+                        can_skip = old_val["policy"] == old_val["policy"] | new_val["policy"]
+                    except TypeError:
+                        can_skip = old_val["policy"] == {
+                            **old_val["policy"],
+                            **new_val["policy"],
+                        }
+                    if can_skip:
+                        if "note" not in new_val:
+                            continue
+                        if "note" in old_val and "note" in new_val:
+                            if old_val["note"] == new_val["note"]:
+                                continue
+
+                # Write out the policy (and note) line(s)
+                val = dict(sorted(new_val["policy"].items()))
+                line = f"{conf: <47} policy<{val}>"
+                if "note" in new_val:
+                    val = new_val["note"]
+                    if new_val.get("oneline", False):
+                        # Single line
+                        line += f" note<{val}>"
+                    else:
+                        # Separate policy and note lines,
+                        # followed by an empty line
+                        line += f"\n{conf: <47} note<{val}>\n"
+                elif not marker:
+                    # Write out a marker indicating the start of annotations
+                    # without notes
+                    tmp.write("\n# ---- Annotations without notes ----\n\n")
+                    marker = True
+                tmp.write(line + "\n")
+
+            # Replace annotations with the updated version
+            tmp.flush()
+            shutil.move(tmp.name, fname)
+
+    def search_config(self, config: str = None, arch: str = None, flavour: str = None) -> dict:
+        """Return config value of a specific config option or architecture"""
+        if flavour is None:
+            flavour = "generic"
+        flavour = f"{arch}-{flavour}"
+        if flavour in self.flavour_dep:
+            generic = self.flavour_dep[flavour]
+        else:
+            generic = flavour
+        if config is None and arch is None:
+            # Get all config options for all architectures
+            return self.config
+        if config is None and arch is not None:
+            # Get config options of a specific architecture
+            ret = {}
+            for c, val in self.config.items():
+                if "policy" not in val:
+                    continue
+                if flavour in val["policy"]:
+                    ret[c] = val["policy"][flavour]
+                elif generic != flavour and generic in val["policy"]:
+                    ret[c] = val["policy"][generic]
+                elif arch in val["policy"]:
+                    ret[c] = val["policy"][arch]
+            return ret
+        if config is not None and arch is None:
+            # Get a specific config option for all architectures
+            return self.config[config] if config in self.config else None
+        if config is not None and arch is not None:
+            # Get a specific config option for a specific architecture
+            if config in self.config:
+                if "policy" in self.config[config]:
+                    if flavour in self.config[config]["policy"]:
+                        return {config: self.config[config]["policy"][flavour]}
+                    if generic != flavour and generic in self.config[config]["policy"]:
+                        return {config: self.config[config]["policy"][generic]}
+                    if arch in self.config[config]["policy"]:
+                        return {config: self.config[config]["policy"][arch]}
+        return None
+
+    @staticmethod
+    def to_config(data: dict) -> str:
+        """Convert annotations data to .config format"""
+        s = ""
+        for c in data:
+            v = data[c]
+            if v == "n":
+                s += f"# {c} is not set\n"
+            elif v == "-":
+                pass
+            else:
+                s += f"{c}={v}\n"
+        return s.rstrip()
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/misc/kconfig/run.py
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/misc/kconfig/run.py
@@ -0,0 +1,375 @@
+# -*- mode: python -*-
+# Manage Ubuntu kernel .config and annotations
+# Copyright © 2022 Canonical Ltd.
+
+import argparse
+import json
+import os
+import sys
+from signal import SIG_DFL, SIGPIPE, signal
+
+try:
+    from argcomplete import autocomplete
+except ModuleNotFoundError:
+    # Allow to run this program also when argcomplete is not available
+    def autocomplete(_unused):
+        pass
+
+
+from kconfig.annotations import Annotation, KConfig  # noqa: E402 Import not at top of file
+from kconfig.utils import arg_fail, autodetect_annotations  # noqa: E402 Import not at top of file
+from kconfig.version import ANNOTATIONS_FORMAT_VERSION, VERSION  # noqa: E402 Import not at top of file
+
+SKIP_CONFIGS = (
+    # CONFIG_VERSION_SIGNATURE is dynamically set during the build
+    "CONFIG_VERSION_SIGNATURE",
+    # Allow to use a different versions of toolchain tools
+    "CONFIG_GCC_VERSION",
+    "CONFIG_CC_VERSION_TEXT",
+    "CONFIG_AS_VERSION",
+    "CONFIG_LD_VERSION",
+    "CONFIG_LLD_VERSION",
+    "CONFIG_CLANG_VERSION",
+    "CONFIG_PAHOLE_VERSION",
+    "CONFIG_RUSTC_VERSION_TEXT",
+    "CONFIG_BINDGEN_VERSION_TEXT",
+)
+
+
+def removeprefix(data, prefix):
+    if data[: len(prefix)] == prefix:
+        data = data[len(prefix) :]
+    return data
+
+
+def make_parser():
+    parser = argparse.ArgumentParser(
+        description="Manage Ubuntu kernel .config and annotations",
+    )
+    parser.add_argument("--version", "-v", action="version", version=f"%(prog)s {VERSION}")
+
+    parser.add_argument(
+        "--file",
+        "-f",
+        action="store",
+        help="Pass annotations or .config file to be parsed",
+    )
+    parser.add_argument("--arch", "-a", action="store", help="Select architecture")
+    parser.add_argument("--flavour", "-l", action="store", help='Select flavour (default is "generic")')
+    parser.add_argument("--config", "-c", action="store", help="Select a specific config option")
+    parser.add_argument("--query", "-q", action="store_true", help="Query annotations")
+    parser.add_argument(
+        "--note",
+        "-n",
+        action="store",
+        help="Write a specific note to a config option in annotations",
+    )
+    parser.add_argument(
+        "--autocomplete",
+        action="store_true",
+        help="Enable config bash autocomplete: `source <(annotations --autocomplete)`",
+    )
+    parser.add_argument(
+        "--source",
+        "-t",
+        action="store_true",
+        help="Jump to a config definition in the kernel source code",
+    )
+    parser.add_argument(
+        "--no-include",
+        action="store_true",
+        help="Do not process included annotations (stop at the main file)",
+    )
+    parser.add_argument(
+        "--json",
+        action="store_true",
+        help="Try to parse annotations file in pure JSON format",
+    )
+
+    ga = parser.add_argument_group(title="Action").add_mutually_exclusive_group(required=False)
+    ga.add_argument(
+        "--write",
+        "-w",
+        action="store",
+        metavar="VALUE",
+        dest="value",
+        help="Set a specific config value in annotations (use 'null' to remove)",
+    )
+    ga.add_argument(
+        "--export",
+        "-e",
+        action="store_true",
+        help="Convert annotations to .config format",
+    )
+    ga.add_argument(
+        "--import",
+        "-i",
+        action="store",
+        metavar="FILE",
+        dest="import_file",
+        help="Import a full .config for a specific arch and flavour into annotations",
+    )
+    ga.add_argument(
+        "--update",
+        "-u",
+        action="store",
+        metavar="FILE",
+        dest="update_file",
+        help="Import a partial .config into annotations (only resync configs specified in FILE)",
+    )
+    ga.add_argument(
+        "--check",
+        "-k",
+        action="store",
+        metavar="FILE",
+        dest="check_file",
+        help="Validate kernel .config with annotations",
+    )
+    return parser
+
+
+_ARGPARSER = make_parser()
+
+
+def export_result(data):
+    # Dump metadata / attributes first
+    out = '{\n  "attributes": {\n'
+    for key, value in sorted(data["attributes"].items()):
+        out += f'     "{key}": {json.dumps(value)},\n'
+    out = out.rstrip(",\n")
+    out += "\n  },"
+    print(out)
+
+    configs_with_note = {key: value for key, value in data["config"].items() if "note" in value}
+    configs_without_note = {key: value for key, value in data["config"].items() if "note" not in value}
+
+    # Dump configs, sorted alphabetically, showing items with a note first
+    out = '  "config": {\n'
+    for key in sorted(configs_with_note) + sorted(configs_without_note):
+        policy = data["config"][key]["policy"]
+        if "note" in data["config"][key]:
+            note = data["config"][key]["note"]
+            out += f'    "{key}": {{"policy": {json.dumps(policy)}, "note": {json.dumps(note)}}},\n'
+        else:
+            out += f'    "{key}": {{"policy": {json.dumps(policy)}}},\n'
+    out = out.rstrip(",\n")
+    out += "\n  }\n}"
+    print(out)
+
+
+def print_result(config, data):
+    if data is not None and config is not None and config not in data:
+        data = {config: data}
+    print(json.dumps(data, sort_keys=True, indent=2))
+
+
+def do_query(args):
+    if args.arch is None and args.flavour is not None:
+        arg_fail(_ARGPARSER, "error: --flavour requires --arch")
+    a = Annotation(args.file, do_include=(not args.no_include), do_json=args.json)
+    res = a.search_config(config=args.config, arch=args.arch, flavour=args.flavour)
+    # If no arguments are specified dump the whole annotations structure
+    if args.config is None and args.arch is None and args.flavour is None:
+        res = {
+            "attributes": {
+                "arch": a.arch,
+                "flavour": a.flavour,
+                "flavour_dep": a.flavour_dep,
+                "include": a.include,
+                "_version": ANNOTATIONS_FORMAT_VERSION,
+            },
+            "config": res,
+        }
+        export_result(res)
+    else:
+        print_result(args.config, res)
+
+
+def do_autocomplete(args):
+    a = Annotation(args.file)
+    res = (removeprefix(c, "CONFIG_") for c in a.search_config())
+    res_str = " ".join(res)
+    print(f'complete -W "{res_str}" annotations')
+
+
+def do_source(args):
+    if args.config is None:
+        arg_fail(_ARGPARSER, "error: --source requires --config")
+    if not os.path.exists("tags"):
+        print("tags not found in the current directory, try: `make tags`")
+        sys.exit(1)
+    os.system(f"vim -t {args.config}")
+
+
+def do_note(args):
+    if args.config is None:
+        arg_fail(_ARGPARSER, "error: --note requires --config")
+
+    # Set the note in annotations
+    a = Annotation(args.file)
+    a.set(args.config, note=args.note)
+
+    # Save back to annotations
+    a.save(args.file)
+
+    # Query and print back the value
+    a = Annotation(args.file)
+    res = a.search_config(config=args.config)
+    print_result(args.config, res)
+
+
+def do_write(args):
+    if args.config is None:
+        arg_fail(_ARGPARSER, "error: --write requires --config")
+
+    # Set the value in annotations ('null' means remove)
+    a = Annotation(args.file)
+    if args.value == "null":
+        a.remove(args.config, arch=args.arch, flavour=args.flavour)
+    else:
+        a.set(
+            args.config,
+            arch=args.arch,
+            flavour=args.flavour,
+            value=args.value,
+            note=args.note,
+        )
+
+    # Save back to annotations
+    a.save(args.file)
+
+    # Query and print back the value
+    a = Annotation(args.file)
+    res = a.search_config(config=args.config)
+    print_result(args.config, res)
+
+
+def do_export(args):
+    if args.arch is None:
+        arg_fail(_ARGPARSER, "error: --export requires --arch")
+    a = Annotation(args.file)
+    conf = a.search_config(config=args.config, arch=args.arch, flavour=args.flavour)
+    if conf:
+        print(a.to_config(conf))
+
+
+def do_import(args):
+    if args.arch is None:
+        arg_fail(_ARGPARSER, "error: --arch is required with --import")
+    if args.flavour is None:
+        arg_fail(_ARGPARSER, "error: --flavour is required with --import")
+    if args.config is not None:
+        arg_fail(_ARGPARSER, "error: --config cannot be used with --import (try --update)")
+
+    # Merge with the current annotations
+    a = Annotation(args.file)
+    c = KConfig(args.import_file)
+    a.update(c, arch=args.arch, flavour=args.flavour)
+
+    # Save back to annotations
+    a.save(args.file)
+
+
+def do_update(args):
+    if args.arch is None:
+        arg_fail(_ARGPARSER, "error: --arch is required with --update")
+
+    # Merge with the current annotations
+    a = Annotation(args.file)
+    c = KConfig(args.update_file)
+    if args.config is None:
+        configs = list(set(c.config.keys()) - set(SKIP_CONFIGS))
+    if configs:
+        a.update(c, arch=args.arch, flavour=args.flavour, configs=configs)
+
+    # Save back to annotations
+    a.save(args.file)
+
+
+def do_check(args):
+    # Determine arch and flavour
+    if args.arch is None:
+        arg_fail(_ARGPARSER, "error: --arch is required with --check")
+
+    print(f"check-config: loading annotations from {args.file}")
+    total = good = ret = 0
+
+    # Load annotations settings
+    a = Annotation(args.file)
+    a_configs = a.search_config(arch=args.arch, flavour=args.flavour).keys()
+
+    # Parse target .config
+    c = KConfig(args.check_file)
+    c_configs = c.config.keys()
+
+    # Validate .config against annotations
+    for conf in sorted(a_configs | c_configs):
+        if conf in SKIP_CONFIGS:
+            continue
+        entry = a.search_config(config=conf, arch=args.arch, flavour=args.flavour)
+        expected = entry[conf] if entry else "-"
+        value = c.config[conf] if conf in c.config else "-"
+        if value != expected:
+            policy = a.config[conf] if conf in a.config else "undefined"
+            if "policy" in policy:
+                policy = f"policy<{policy['policy']}>"
+            print(f"check-config: {conf} changed from {expected} to {value}: {policy})")
+            ret = 1
+        else:
+            good += 1
+        total += 1
+
+    num = total - good
+    if ret:
+        if os.path.exists(".git"):
+            print(f"check-config: {num} config options have been changed, review them with `git diff`")
+        else:
+            print(f"check-config: {num} config options have changed")
+    else:
+        print("check-config: all good")
+    sys.exit(ret)
+
+
+def main():
+    # Prevent broken pipe errors when showing output in pipe to other tools
+    # (less for example)
+    signal(SIGPIPE, SIG_DFL)
+
+    # Main annotations program
+    autocomplete(_ARGPARSER)
+    args = _ARGPARSER.parse_args()
+
+    if args.file is None:
+        args.file = autodetect_annotations()
+        if args.file is None:
+            arg_fail(
+                _ARGPARSER,
+                "error: could not determine DEBDIR, try using: --file/-f",
+                show_usage=False,
+            )
+
+    if args.config and not args.config.startswith("CONFIG_"):
+        args.config = "CONFIG_" + args.config
+
+    if args.value:
+        do_write(args)
+    elif args.note:
+        do_note(args)
+    elif args.export:
+        do_export(args)
+    elif args.import_file:
+        do_import(args)
+    elif args.update_file:
+        do_update(args)
+    elif args.check_file:
+        do_check(args)
+    elif args.autocomplete:
+        do_autocomplete(args)
+    elif args.source:
+        do_source(args)
+    else:
+        do_query(args)
+
+
+if __name__ == "__main__":
+    main()
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/misc/kconfig/utils.py
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/misc/kconfig/utils.py
@@ -0,0 +1,20 @@
+# -*- mode: python -*-
+# Misc helpers for Kconfig and annotations
+# Copyright © 2023 Canonical Ltd.
+
+import sys
+
+
+def autodetect_annotations():
+    try:
+        with open("debian/debian.env", "rt", encoding="utf-8") as fd:
+            return fd.read().rstrip().split("=")[1] + "/config/annotations"
+    except (FileNotFoundError, IndexError):
+        return None
+
+
+def arg_fail(parser, message, show_usage=True):
+    print(message)
+    if show_usage:
+        parser.print_usage()
+    sys.exit(1)
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/misc/kconfig/version.py
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/misc/kconfig/version.py
@@ -0,0 +1,10 @@
+# -*- mode: python -*-
+# version of annotations module
+# Copyright © 2022 Canonical Ltd.
+
+VERSION = "0.1"
+
+ANNOTATIONS_FORMAT_VERSION = 5
+
+if __name__ == "__main__":
+    print(VERSION)
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/misc/kernel-wedge-arch.pl
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/misc/kernel-wedge-arch.pl
@@ -0,0 +1,26 @@
+#!/usr/bin/perl
+#
+# kernel-wedge-arch.pl -- select only specifiers for the supplied arch.
+#
+use strict;
+
+require Dpkg::Control;
+require Dpkg::Deps;
+
+my $fh = \*STDIN;
+
+my @entries;
+
+my $wanted = $ARGV[0];
+
+my $entry;
+while (!eof($fh)) {
+	$entry = Dpkg::Control->new();
+	$entry->parse($fh, '???');
+
+	if ($entry->{'Architecture'} eq $wanted) {
+		print("\n" . $entry);
+	}
+}
+
+close($fh);
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/misc/kernelconfig
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/misc/kernelconfig
@@ -0,0 +1,178 @@
+#!/bin/bash -u
+#
+# Manage kernel config annotations
+#
+# Supported environment variales:
+#   conc_level  : Concurrency level for upstream make (-jX)
+#   skip_checks : Skip config checks if set to 'true'
+#   gcc         : Default gcc to use (mandatory)
+#
+
+function cleanup()
+{
+	rm -rf build "${TMP_DIR}"
+}
+
+# We have to be in the top level Ubuntu kernel source directory
+if ! [ -e debian/debian.env ] ; then
+	echo "ERROR: This is not an Ubuntu kernel source directory" >&2
+	exit 1
+fi
+
+if [ -z "${gcc:-}" ] ; then
+	gcc=gcc
+fi
+
+if [ ${#} -ne 1 ] ; then
+	echo "Usage: $0 updateconfigs|defaultconfigs|genconfigs|editconfigs"
+	exit 2
+fi
+
+mode=${1}
+
+case "${mode}" in
+	updateconfigs)  target="syncconfig" ;;
+	defaultconfigs) target="olddefconfig" ;;
+	genconfigs)     target="oldconfig" ;;
+	editconfigs)    ;;  # Target is set later based on user input
+	*) echo "ERROR: Invalid mode: ${1}" >&2
+	   exit 1 ;;
+esac
+
+. debian/debian.env
+
+annotations_file=${DEBIAN}/config/annotations
+warning_partial=()
+
+TMP_DIR=$(mktemp -d)
+trap cleanup EXIT
+
+# Use annotations to generate configs
+FLAVOURS=$(sed -ne 's/^# FLAVOUR: //p' "${annotations_file}")
+
+for arch_flavour in ${FLAVOURS} ; do
+	arch=${arch_flavour%%-*}
+	flavour=${arch_flavour#*-}
+	tmp_conf_file=${TMP_DIR}/${arch}-config.flavour.${flavour}
+
+	# Map debian archs to kernel archs
+	case "${arch}" in
+		amd64)   kern_arch="x86_64" ;;
+		arm64)   kern_arch="arm64" ;;
+		armhf)   kern_arch="arm" ;;
+		i386)    kern_arch="i386" ;;
+		ppc64el) kern_arch="powerpc" ;;
+		riscv64) kern_arch="riscv" ;;
+		s390x)   kern_arch="s390" ;;
+		*)       echo "WARNING: Unsupported architecture: ${arch}"
+		         warning_partial+=("${arch}")
+		         continue ;;
+	esac
+
+	# Determine cross toolchain to use for Kconfig compiler tests
+	cross_compile="$(dpkg-architecture -qDEB_HOST_GNU_TYPE -a"${arch}" 2>/dev/null)-"
+
+	# Arch-specific compiler, if any
+	arch_gcc=$(cat <<EOF | make -s -f - all
+include ${DEBIAN}/rules.d/${arch}.mk
+all:
+	@echo \$(if \$(gcc),\$(gcc),${gcc})
+EOF
+			)
+	gcc_path=$(which "${cross_compile}${arch_gcc}" || true)
+	if [ -z "${gcc_path}" ] ; then
+		echo "WARNING: ${cross_compile}${arch_gcc} not installed"
+		warning_partial+=("${arch}")
+		continue
+	fi
+
+	if [ "${mode}" = "editconfigs" ] ; then
+		while true ; do
+			echo -n "Do you want to edit configs for ${arch}-${flavour}? [Y/n] "
+			read -r choice
+			case "${choice,,}" in
+				y|"") target="menuconfig" ; break ;;
+				n)    target="syncconfig" ; break ;;
+			esac
+		done
+	fi
+
+	rm -rf build
+	mkdir build
+
+	# Generate .config from annotations
+	python3 debian/scripts/misc/annotations -f "${annotations_file}" \
+			--arch "${arch}" --flavour "${flavour}" --export > build/.config
+
+	# Environment variables for 'make *config'
+	env=(ARCH="${kern_arch}"
+		 DEB_ARCH="${arch}"
+		 CROSS_COMPILE="${cross_compile}"
+		 CC="${gcc_path}")
+
+	# Concurrency level
+	if [ -n "${conc_level:-}" ] ; then
+		env+=("${conc_level}")
+	fi
+
+	# Call config target
+	echo
+	echo "* Run ${target} on ${arch}/${flavour} ..."
+	${kmake} O=build "${env[@]}" "${target}"
+
+	# Move config for further processing
+	mv build/.config "${tmp_conf_file}"
+done
+
+rc=0
+
+if [ "${skip_checks:-}" = "true" ] ; then
+	echo
+	echo "Skipping config-check (skip_checks=${skip_checks}) ..."
+else
+	echo
+	echo "Running config-check for all configurations ..."
+	fail=0
+	for arch_flavour in ${FLAVOURS} ; do
+		arch=${arch_flavour%%-*}
+		flavour=${arch_flavour#*-}
+		tmp_conf_file=${TMP_DIR}/${arch}-config.flavour.${flavour}
+
+		echo
+		echo "* Run config-check for ${arch}-${flavour} ..."
+		python3 debian/scripts/misc/annotations -f "${annotations_file}" \
+				--arch "${arch}" --flavour "${flavour}" --check "${tmp_conf_file}" || \
+			fail=$((fail + 1))
+	done
+
+	if [ ${fail} -gt 0 ] ; then
+		rc=1
+		echo "ERROR: ${fail} config-check failures detected" >&2
+	fi
+fi
+
+if [ ${#warning_partial[@]} -gt 0 ] ; then
+	rc=1
+	echo "ERROR: Config operation not applied to all architectures (skipped ${warning_partial[*]})" >&2
+fi
+
+# Recreate the annotations file
+if [ "${mode}" = "genconfigs" ] ; then
+	rm -rf CONFIGS
+	mv "${TMP_DIR}" CONFIGS
+else
+	echo
+	echo "Importing all configurations ..."
+	echo
+	for arch_flavour in ${FLAVOURS} ; do
+		arch=${arch_flavour%%-*}
+		flavour=${arch_flavour#*-}
+		tmp_conf_file=${TMP_DIR}/${arch}-config.flavour.${flavour}
+
+		echo "* Import configs for ${arch}-${flavour} ..."
+		python3 debian/scripts/misc/annotations -f "${annotations_file}" \
+				--arch "${arch}" --flavour "${flavour}" --import "${tmp_conf_file}"
+	done
+fi
+
+exit "${rc}"
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/misc/migrate-annotations
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/misc/migrate-annotations
@@ -0,0 +1,35 @@
+#!/bin/bash
+
+. debian/debian.env
+
+# We have to be in the top level kernel source directory
+if [ ! -f MAINTAINERS ] || [ ! -f Makefile ]; then
+	echo "This does not appear to be the kernel source directory." 1>&2
+	exit 1
+fi
+
+. ${DEBIAN}/etc/kernelconfig
+
+ARCH=$(echo $archs | tr " " "\n" | sort -u)
+FLAVOUR=$(for arch in ${ARCH}; do
+	flavours=$(sed -ne 's/^flavours\s*=\s*\(.*\)$/\1/p' ${DEBIAN}/rules.d/${arch}.mk)
+	for flavour in ${flavours}; do
+		echo ${arch}-${flavour}
+	done
+done | tr " " "\n" | sort -u)
+
+while read line; do
+	(echo $line | grep -q '^#') || break
+done
+
+cat << EOF
+# Menu: HEADER
+# FORMAT: 4
+# ARCH: $(echo ${ARCH})
+# FLAVOUR: $(echo ${FLAVOUR})
+
+EOF
+
+while read line; do
+	echo ${line}
+done
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/misc/old-kernelconfig
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/misc/old-kernelconfig
@@ -0,0 +1,207 @@
+#!/bin/bash
+
+. debian/debian.env
+
+# Script to merge all configs and run 'make syncconfig' on it to wade out bad juju.
+# Then split the configs into distro-commmon and flavour-specific parts
+
+# We have to be in the top level kernel source directory
+if [ ! -f MAINTAINERS ] || [ ! -f Makefile ]; then
+	echo "This does not appear to be the kernel source directory." 1>&2
+	exit 1
+fi
+
+mode=${1:?"Usage: $0 (oldconfig|editconfig) [do_enforce_all]"}
+do_enforce_all=${2:-0}
+yes=0
+case "$mode" in
+    update*configs)  mode='syncconfig' ;;
+    default*configs) mode='oldconfig'; yes=1 ;;
+    edit*configs)    ;; # All is good
+    gen*configs)     mode='genconfigs' ;; # All is good
+    dump*configs)    mode='config'; yes=1 ;;
+    *) echo "$0 called with invalid mode" 1>&2
+       exit 1 ;;
+esac
+kerneldir="`pwd`"
+confdir="$kerneldir/${DEBIAN}/config"
+variant="$2"
+
+. $DEBIAN/etc/kernelconfig
+
+bindir="`pwd`/${DROOT}/scripts/misc"
+common_conf="$confdir/config.common.$family"
+tmpdir=`mktemp -d`
+mkdir "$tmpdir/CONFIGS"
+
+if [ "$mode" = "genconfigs" ]; then
+	keep=1
+	mode="oldconfig"
+	test -d CONFIGS || mkdir CONFIGS
+fi
+
+warning_partial=
+
+for arch in $archs; do
+	rm -rf build
+	mkdir build
+
+	# Map debian archs to kernel archs
+	case "$arch" in
+		ppc64|ppc64el)	kernarch="powerpc"	;;
+		amd64)		kernarch="x86_64"	;;
+		lpia)		kernarch="x86" 		;;
+		sparc)		kernarch="sparc64"	;;
+		armel|armhf)	kernarch="arm"		;;
+		s390x)		kernarch="s390"		;;
+		riscv64)	kernarch="riscv"	;;
+		*)		kernarch="$arch"	;;
+	esac
+
+	# Determine cross toolchain to use for Kconfig compiler tests
+	cross_compile=""
+	deb_build_arch=$(dpkg-architecture -qDEB_BUILD_ARCH -a$arch 2>/dev/null)
+	deb_host_arch=$(dpkg-architecture -qDEB_HOST_ARCH -a$arch 2>/dev/null)
+	[ $deb_build_arch != $deb_host_arch ] && cross_compile="$(dpkg-architecture -qDEB_HOST_GNU_TYPE -a$arch 2>/dev/null)-"
+
+	# Environment variables for 'make *config'. We omit CROSS_COMPILE
+	# for i386 since it is no longer supported after 19.04, however
+	# we maintain the configs for hwe.
+	modify_config=true
+	env="ARCH=$kernarch DEB_ARCH=$arch"
+	compiler_path=$(which "${cross_compile}gcc" || true)
+	if [ "$compiler_path" != '' ]; then
+		env="$env CROSS_COMPILE=$cross_compile"
+	else
+		echo "WARNING: ${cross_compile}gcc not installed"
+		modify_config=
+		warning_partial="$warning_partial $arch"
+	fi
+
+	archconfdir=$confdir/$arch
+	flavourconfigs=$(cd $archconfdir && ls config.flavour.*)
+
+	# Merge configs
+	# We merge config.common.ubuntu + config.common.<arch> +
+	# config.flavour.<flavour>
+
+	for config in $flavourconfigs; do
+		fullconf="$tmpdir/$arch-$config-full"
+		case $config in
+		*)
+			: >"$fullconf"
+			if [ -f $common_conf ]; then
+				cat $common_conf >> "$fullconf"
+			fi
+			if [ -f $archconfdir/config.common.$arch ]; then
+				cat $archconfdir/config.common.$arch >> "$fullconf"
+			fi
+			cat "$archconfdir/$config" >>"$fullconf"
+			if [ -f $confdir/OVERRIDES ]; then
+				cat $confdir/OVERRIDES >> "$fullconf"
+			fi
+			;;
+		esac
+	done
+
+	for config in $flavourconfigs; do
+		if [ -f $archconfdir/$config ]; then
+			fullconf="$tmpdir/$arch-$config-full"
+			cat "$fullconf" > build/.config
+			# Call oldconfig or menuconfig
+			if [ "$modify_config" ]; then
+				case "$mode" in
+				    editconfigs)
+					# Interactively edit config parameters
+					while : ; do
+						echo -n "Do you want to edit config: $arch/$config? [Y/n] "
+						read choice
+						case "$choice" in
+						y* | Y* | "" )
+							make O=`pwd`/build $env menuconfig
+							break ;;
+						n* | N* )
+							# 'syncconfig' prevents
+							# errors for '-' options set
+							# in common config fragments
+							make O=`pwd`/build $env syncconfig
+							break ;;
+						*)
+							echo "Entry not valid"
+						esac
+					done
+					;;
+				    *)
+					echo "* Run $mode (yes=$yes) on $arch/$config ..."
+					if [ "$yes" -eq 1 ]; then
+						yes "" | make O=`pwd`/build $env "$mode"
+					else
+						make O=`pwd`/build $env "$mode"
+					fi ;;
+				esac
+			fi
+			cat build/.config > $archconfdir/$config
+			[ "$modify_config" ] && cat build/.config >"$tmpdir/CONFIGS/$arch-$config"
+			if [ "$keep" = "1" ]; then
+				cat build/.config > CONFIGS/$arch-$config
+			fi
+		else
+			echo "!! Config not found $archconfdir/$config..."
+		fi
+	done
+
+	echo "Running splitconfig.pl for $arch"
+	echo
+
+	# Can we make this more robust by avoiding $tmpdir completely?
+	# This approach was used for now because I didn't want to change
+	# splitconfig.pl
+	(cd $archconfdir; $bindir/splitconfig.pl config.flavour.*; mv config.common \
+	 config.common.$arch; cp config.common.$arch $tmpdir)
+done
+
+rm -f $common_conf
+
+# Now run splitconfig.pl on all the config.common.<arch> copied to
+# $tmpdir
+(cd $tmpdir; $bindir/splitconfig.pl *)
+(
+	cd $confdir;
+	rm -f *-full
+	grep -v 'is UNMERGABLE' <$tmpdir/config.common >$common_conf
+	for arch in $archs; do
+		grep -v 'is UNMERGABLE' <$tmpdir/config.common.$arch \
+			>$arch/config.common.$arch
+	done
+)
+
+echo ""
+echo "Running config-check for all configurations ..."
+echo ""
+fail=0
+for arch in $archs; do
+	archconfdir=$confdir/$arch
+	flavourconfigs=$(cd $archconfdir && ls config.flavour.*)
+	for config in $flavourconfigs; do
+		flavour="${config##*.}"
+		if [ -f $archconfdir/$config ]; then
+			fullconf="$tmpdir/CONFIGS/$arch-$config"
+			[ ! -f "$fullconf" ] && continue
+			"$bindir/../config-check" "$fullconf" "$arch" "$flavour" "$confdir" "0" "$do_enforce_all" || let "fail=$fail+1"
+		fi
+	done
+done
+
+if [ "$fail" != 0 ]; then
+	echo ""
+	echo "*** ERROR: $fail config-check failures detected"
+	echo ""
+fi
+
+rm -rf build
+
+if [ "$warning_partial" ]; then
+	echo ""
+	echo "WARNING: configuration operation applied only to a subset of architectures (skipped$warning_partial)" 1>&2
+	echo ""
+fi
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/misc/retag
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/misc/retag
@@ -0,0 +1,34 @@
+#!/usr/bin/perl -w
+
+open(TAGS, "git tag -l |") or die "Could not get list of tags";
+@tags = <TAGS>;
+close(TAGS);
+
+open(LOGS, "git log --pretty=short |") or die "ERROR: Calling git log";
+my $commit = "";
+
+while (<LOGS>) {
+	my $origtag;
+
+	if (m|^commit (.*)$|) {
+		$commit = $1;
+		next;
+	}
+
+	m|\s*UBUNTU: (Ubuntu-2\.6\..*)| or next;
+
+	$tag = $1;
+
+	($origtag) = grep(/^$tag.orig$/, @tags);
+
+	if (!defined($origtag)) {
+		print "I: Adding original tag for $tag\n";
+		system("git tag -m $tag $tag.orig $tag");
+	}
+
+	print "I: Tagging $tag => $commit\n";
+
+	system("git tag -f -m $tag $tag $commit");
+}
+
+close(LOGS);
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/misc/splitconfig.pl
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/misc/splitconfig.pl
@@ -0,0 +1,107 @@
+#!/usr/bin/perl -w
+
+%allconfigs = ();
+%common = ();
+
+print "Reading config's ...\n";
+
+for $config (@ARGV) {
+	# Only config.*
+	next if $config !~ /^config\..*/;
+	# Nothing that is disabled, or remnant
+	next if $config =~ /.*\.(default|disabled|stub)$/;
+
+	%{$allconfigs{$config}} = ();
+
+	print "  processing $config ... ";
+
+	open(CONFIG, "< $config");
+
+	while (<CONFIG>) {
+		# Skip comments
+		/^#*\s*CONFIG_(\w+)[\s=](.*)$/ or next;
+
+		${$allconfigs{$config}}{$1} = $2;
+
+		$common{$1} = $2;
+	}
+
+	close(CONFIG);
+
+	print "done.\n";
+}
+
+print "\n";
+
+print "Merging lists ... \n";
+
+# %options - pointer to flavour config inside the allconfigs array
+for $config (keys(%allconfigs)) {
+	my %options = %{$allconfigs{$config}};
+
+	print "   processing $config ... ";
+
+	for $key (keys(%common)) {
+		next if not defined $common{$key};
+
+		# If we don't have the common option, then it isn't
+		# common. If we do have that option, it must have the same
+		# value.  EXCEPT where this file does not have a value at all
+		# which may safely be merged with any other value; the value
+		# will be elided during recombination of the parts.
+		if (!defined($options{$key})) {
+			# Its ok really ... let it merge
+		} elsif (not defined($options{$key})) {
+			undef $common{$key};
+		} elsif ($common{$key} ne $options{$key}) {
+			undef $common{$key};
+		}
+	}
+
+	print "done.\n";
+}
+
+print "\n";
+
+print "Creating common config ... ";
+
+open(COMMON, "> config.common");
+print COMMON "#\n# Common config options automatically generated by splitconfig.pl\n#\n";
+
+for $key (sort(keys(%common))) {
+	if (not defined $common{$key}) {
+		print COMMON "# CONFIG_$key is UNMERGABLE\n";
+	} elsif ($common{$key} eq "is not set") {
+		print COMMON "# CONFIG_$key is not set\n";
+	} else {
+		print COMMON "CONFIG_$key=$common{$key}\n";
+	}
+}
+close(COMMON);
+
+print "done.\n\n";
+
+print "Creating stub configs ...\n";
+
+for $config (keys(%allconfigs)) {
+	my %options = %{$allconfigs{$config}};
+
+	print "  processing $config ... ";
+
+	open(STUB, "> $config");
+	print STUB "#\n# Config options for $config automatically generated by splitconfig.pl\n#\n";
+
+	for $key (sort(keys(%options))) {
+		next if defined $common{$key};
+
+		if ($options{$key} =~ /^is /) {
+			print STUB "# CONFIG_$key $options{$key}\n";
+		} else {
+			print STUB "CONFIG_$key=$options{$key}\n";
+		}
+	}
+
+	close(STUB);
+
+	print "done.\n";
+}
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/misc/tristate.sh
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/misc/tristate.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+#
+# Find config variables that might be able to transition from =y to =m
+#
+# Example: debian/scripts/misc/tristate.sh debian.master/config/config.common.ubuntu
+#
+
+KC=Kconfig.tmp
+rm -f ${KC}
+find .|grep Kconfig | while read f
+do
+	cat $f >> ${KC}
+done
+
+grep =y $1 | sed -e 's/CONFIG_//' -e 's/=y//' | while read c
+do
+	cat <<EOF > tristate.awk
+BEGIN { tristate=0; }
+/^config ${c}\$/ { tristate=1; next; }
+/tristate/ { if (tristate == 1) printf("CONFIG_%s=m\n","${c}"); next; }
+{ if (tristate == 1) exit; }
+EOF
+
+	gawk -f tristate.awk ${KC}
+done
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/misc/update-aufs.sh
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/misc/update-aufs.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+
+AUFS=aufs4-standalone
+
+#
+# Before you run this be sure you've removed or reverted the 'UBUNTU: SAUCE: AUFS" patch.
+#
+#
+# Make sure the current working directory is at the top of the
+# linux tree.
+#
+if ! grep PATCHLEVEL Makefile
+then
+	echo "You must run this script from the top of the linux tree"
+	exit 1
+fi
+
+clean=0
+if [ "$#" = 1 ]; then
+	AUFS="$1"
+else
+	clean=1
+	rm -rf ${AUFS}
+	git clone https://github.com/sfjro/aufs5-standalone.git ${AUFS}
+	(cd ${AUFS}; git checkout -b aufs5.x-rcN remotes/origin/aufs5.x-rcN)
+fi
+
+cp ${AUFS}/include/uapi/linux/aufs_type.h include/uapi/linux
+rsync -av ${AUFS}/fs/ fs/
+rsync -av ${AUFS}/Documentation/ Documentation/
+
+PATCHES="${PATCHES} aufs5-kbuild.patch"
+PATCHES="${PATCHES} aufs5-base.patch"
+PATCHES="${PATCHES} aufs5-mmap.patch"
+PATCHES="${PATCHES} aufs5-standalone.patch"
+PATCHES="${PATCHES} aufs5-loopback.patch"
+#PATCHES="${PATCHES} vfs-ino.patch"
+PATCHES="${PATCHES} tmpfs-idr.patch"
+
+for i in ${PATCHES}
+do
+	patch -p1 < ${AUFS}/$i
+done
+
+[ "$clean" = 1 ] && rm -rf ${AUFS}
+git add mm/prfile.c
+git add -u
+find . -name "*.orig" | xargs rm
+find . |grep aufs | xargs git add
+git commit -s -m"UBUNTU: SAUCE: AUFS"
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/module-inclusion
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/module-inclusion
@@ -0,0 +1,104 @@
+#!/bin/bash
+
+#
+# Build a new directory of modules based on an inclusion list.
+# The includsion list format must be a bash regular expression.
+#
+# usage: $0 ROOT INCLUSION_LIST
+# example: $0 \
+#       debian/build/build-virtual-ALL debian/build/build-virtual \
+#	debian.master/control.d/virtual.inclusion-list \
+#	virtual.depmap
+master=0
+if [ "$1" = "--master" ]; then
+	master=1
+	shift
+fi
+
+ROOT=$1
+NROOT=$2
+ILIST=$3
+DEPMAP=$4
+
+tmp="/tmp/module-inclusion.$$"
+
+#
+# Prep a destination directory.
+#
+mkdir -p ${NROOT}
+
+{
+	# Copy over the framework into the master package.
+	if  [ "$master" -eq 1 ]; then
+		(cd ${ROOT}; find . ! -name "*.ko" -type f)
+	fi
+
+	# Copy over modules by name or pattern.
+	while read -r i
+	do
+		#
+		# 'find' blurts a warning if it cannot find any ko files.
+		#
+		case "$i" in
+		\!*)
+			(cd ${ROOT}; ${i#!} || true)
+			;;
+		*\**)
+			(cd ${ROOT}; eval find "${i}" -name "*.ko" || true)
+			;;
+		*)
+			echo "$i"
+			;;
+		esac
+	done <"${ILIST}"
+} >"$tmp"
+
+# Copy over the listed modules.
+while read i
+do
+	# If this is already moved over, all is good.
+	if [ -f "${NROOT}/$i" ]; then
+		:
+
+	# If present in the source, moved it over.
+	elif [ -f "${ROOT}/$i" ]; then
+		mkdir -p "${NROOT}/`dirname $i`"
+		mv "${ROOT}/$i" "${NROOT}/$i"
+
+	# Otherwise, it is missing.
+	else
+		echo "Warning: Could not find ${ROOT}/$i" 1>&2
+	fi
+done <"$tmp"
+
+# Copy over any dependancies, note if those are missing
+# we know they are in a pre-requisite package as they must
+# have existed at depmap generation time, and can only have
+# moved into a package.
+let n=0 || true
+while [ -s "$tmp" ]
+do
+	let n="$n+1" || true
+	[ "$n" = "20" ] && break || true
+
+	echo "NOTE: pass $n: dependency scan" 1>&2
+
+	while read i
+	do
+		grep "^$i " "$DEPMAP" | \
+		while read m d
+		do
+			if [ -f "${ROOT}/$d" ]; then
+				echo "NOTE: pass $n: ${i} pulls in ${d}" 1>&2
+				echo "$d"
+				mkdir -p "${NROOT}/`dirname $d`"
+				mv "${ROOT}/$d" "${NROOT}/$d"
+			fi
+		done
+	done <"$tmp" >"$tmp.new"
+	mv -f "$tmp.new" "$tmp"
+done
+
+rm -f "$tmp"
+
+exit 0
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/retpoline-extract
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/retpoline-extract
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+cd "$1" || exit 1
+
+# Find all valid retpoline information, collate the detected and
+# safe information together.  Join the result to find the detected
+# but non-safe elements.  These are our concern.
+ur_detected=$(mktemp --tmpdir "retpoline-check-XXXXXX.ur-detected")
+ur_safe=$(mktemp --tmpdir "retpoline-check-XXXXXX.ur-safe")
+
+find "." -path './drivers/firmware/efi/libstub' -prune -o \
+	 -path './arch/x86/boot' -prune -o \
+	 -path './arch/x86/purgatory' -prune -o \
+	 -name \*.ur-detected -print0 | xargs -0 cat | \
+	sed -e "s@^$1@@" -e "s@ $2/@ @" -e "s@^/@@" | \
+	sort -k 1b,1 >"$ur_detected"
+find "." -name \*.ur-safe -print0 | xargs -0 cat | \
+	sed -e "s@^$1@@" -e "s@^/@@" | \
+	sort -k 1b,1 >"$ur_safe"
+
+join -v 1 -j 1 "$ur_detected" "$ur_safe" | sed -s 's/[^ ]*  *//'
+
+rm -f "$ur_detected" "$ur_safe"
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/retpoline-extract-one
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/retpoline-extract-one
@@ -0,0 +1,270 @@
+#!/bin/bash
+
+exec </dev/null
+
+object="$1"
+src="$2"
+bit16="$3"
+
+SECTION=".discard.retpoline_safe"
+
+# Form an associative lookup for the symbol numbers in the ELF symbol table.
+# Uses 8 character 0 expanded hexadecimal key for ease of consumption.
+__symbolmap_init()
+{
+	readelf -W --syms "$1" |
+		awk '($4 == "SECTION" && $1 ~ /^[0-9]*:/) { printf("%08x %08x\n", int($1), int($7)); }' | \
+	while read symbol_num section_num
+	do
+		echo "symbolmap_$symbol_num='$section_num'"
+	done
+}
+symbolmap_init()
+{
+	eval $(__symbolmap_init "$1")
+}
+symbolmap()
+{
+	eval RET="\$symbolmap_$1"
+	if [ "$RET" = '' ]; then
+		echo "symbolmap: $1: invalid section" 1>&2
+		exit 1
+	fi
+}
+
+# Form an associative lookup for the section numbers in the ELF symbol table.
+# Uses 8 character 0 expanded hexadecimal key for ease of consumption.
+__sectionmap_init()
+{
+	readelf -W --headers "$1" | \
+		awk '
+						{ sub("\\[", ""); sub("\\]", ""); }
+                        ($1 ~ /^[0-9][0-9]*/)   { printf("%08x %s %s %s\n", int($1), $2, $3, $4); }
+		' | \
+	{
+		while read section_num section_name section_type section_vma
+		do
+			echo "sectionmap_$section_num='$section_name'"
+			echo "sectionvma_$section_num='$section_vma'"
+			case "$section_type" in
+			REL|RELA) section_relocation="$section_type" ;;
+			esac
+		done
+		echo "section_relocation='$section_relocation'"
+	}
+}
+sectionmap_init()
+{
+	eval $(__sectionmap_init "$1")
+}
+sectionmap()
+{
+	eval RET="\$sectionmap_$1"
+	if [ "$RET" = '' ]; then
+		echo "sectionmap: $1: invalid section" 1>&2
+		exit 1
+	fi
+}
+sectionvma()
+{
+	eval RET="\$sectionvma_$1"
+	if [ "$RET" = '' ]; then
+		echo "sectionvma: $1: invalid section" 1>&2
+		exit 1
+	fi
+}
+
+# Read and parse the hex-dump output.
+hex="[0-9a-f]"
+hex_8="$hex$hex$hex$hex$hex$hex$hex$hex"
+hexspc="[0-9a-f ]"
+hexspc_8="$hexspc$hexspc$hexspc$hexspc$hexspc$hexspc$hexspc$hexspc"
+
+raw32()
+{
+	readelf --hex-dump "$2" "$1" 2>/dev/null |
+	sed \
+		-e '/^Hex/d' -e '/^$/d' -e '/^ *NOTE/d' \
+		-e 's/  *[^ ][^ ]*  *\('"$hex_8"'\) \('"$hexspc_8"'\) \('"$hexspc_8"'\) \('"$hexspc_8"'\) .*/\1 \2 \3 \4 /' \
+		-e 's/\('"$hex$hex"'\)\('"$hex$hex"'\)\('"$hex$hex"'\)\('"$hex$hex"'\) /\4\3\2\1 /g' \
+		-e 's/ $//g' -e 's/ /\n/g'
+}
+#-e 's/\([^ ][^ ][^ ][^ ][^ ][^ ][^ ][^ ]\) \([^ ][^ ][^ ][^ ][^ ][^ ][^ ][^ ]\) /\2\1 /g' \
+
+rela()
+{
+	#file="$(basename "$1")"
+	file="$1"
+
+	# Read relocation information for a 64bit binary.  Each relocation entry
+	# is 3 long longs so we collect 6 quads here.  Note that the dump is in
+	# listed in increasing byte order not withstanding the quad split.
+	#
+	# The record says to take the value of <symbol> add <symbol offset> and
+	# shove that into <write offset> in the segment of the <symbol>.
+	#
+	# Format:
+	#  <write offset>	64 bits
+	#  <symbol number>	32 bits
+	#  <relocation type>	32 bits
+	#  <symbol offset>	64 bits
+	raw32 "$1" ".rela$SECTION" | \
+	{
+		a1=''; a2=''; a3=''; a4=''; a5=''
+		while read a6
+		do
+			[ "$a1" = '' ] && { a1="$a6"; continue; }
+			[ "$a2" = '' ] && { a2="$a6"; continue; }
+			[ "$a3" = '' ] && { a3="$a6"; continue; }
+			[ "$a4" = '' ] && { a4="$a6"; continue; }
+			[ "$a5" = '' ] && { a5="$a6"; continue; }
+
+			#echo ">$a1< >$a2< >$a3< >$a4< >$a5< >$a6<" 1>&2
+			#echo "type<$a3> symbol<$a4> offset<$a2$a1> addr<$a6a5>" 1>&2
+
+			symbolmap "$a4"; section_num="$RET"
+			#echo "section_num<$section_num>" 1>&2
+
+			sectionmap "$section_num"; section="$RET"
+			sectionvma "$section_num"; vma="$RET"
+			#echo "section<$section> vma<$vma>" 1>&2
+
+			# Adjust the segment addressing by the segment offset.
+			printf -v addr "%u" "0x$a6$a5"
+			printf -v vma "%u" "0x$vma"
+			let offset="$addr + $vma"
+			printf -v offset "%x" "$offset"
+
+			echo "$file-$section-$offset"
+
+			a1=''; a2=''; a3=''; a4=''; a5=''
+		done
+	} | sed -e 's/-00*\([0-9a-f]\)/-\1/'
+}
+
+# Form an associative lookup for the raw contents for an ELF section.
+# Uses 8 character 0 expanded hexadecimal key for ease of consumption.
+contentmap_init()
+{
+	raw32 "$1" "$2" >"$tmp"
+	let offset=0
+	while read value
+	do
+		printf -v offset_hex "%08x" $offset
+		eval contentmap_$offset_hex=\'$value\'
+
+		let offset="$offset + 4"
+	done <"$tmp"
+	rm -f "$tmp"
+}
+contentmap()
+{
+	eval RET="\$contentmap_$1"
+	if [ "$RET" = '' ]; then
+		echo "contentmap: $1: invalid offset" 1>&2
+		exit 1
+	fi
+}
+
+rel()
+{
+	# Load up the current contents of the $SECTION segment
+	# as the offsets (see below) are recorded there and we will need
+	# those to calculate the actuall address.
+	contentmap_init "$1" "$SECTION"
+
+	#file="$(basename "$1")"
+	file="$1"
+
+	# Read relocation information for a 32bit binary.  Each relocation entry
+	# is 3 longs so we collect 3 quads here.  Note that the dump is in
+	# listed in increasing byte order not withstanding the quad split.
+	#
+	# The record says to take the value of <symbol> and add that to the
+	# existing contents of <write offset> in the segment of the <symbol>.
+	#
+	# Format:
+	#  <write offset>	32 bits
+	#  <symbol number>	24 bits
+	#  <relocation type>	 8 bits
+	raw32 "$1" ".rel$SECTION" | \
+	{
+		a1=''
+		while read a2
+		do
+			[ "$a1" = '' ] && { a1="$a2"; continue; }
+
+			#echo ">$a1< >$a2<"
+			contentmap "$a1"; offset="$RET"
+			symbolmap "00${a2%??}"; section_num="$RET"
+
+			sectionmap "$section_num"; section="$RET"
+			sectionvma "$section_num"; vma="$RET"
+			#echo ">$a1< >$a2< >$offset< >$section<"
+
+			echo "$file-$section-$offset"
+
+			a1=''
+		done
+	} | sed -e 's/-00*\([0-9a-f]\)/-\1/'
+}
+
+tmp=$(mktemp --tmpdir "retpoline-extract-XXXXXX")
+
+disassemble()
+{
+	local object="$1"
+	local src="$2"
+	local options="$3"
+	local selector="$4"
+
+	objdump $options --disassemble --no-show-raw-insn "$object" | \
+	awk -F' ' '
+		BEGIN				{ file="'"$object"'"; src="'"$src"'"; }
+		/Disassembly of section/        { segment=$4; sub(":", "", segment); }
+		/^[0-9a-f][0-9a-f]* <.*>:/      { tag=$0; sub(".*<", "", tag); sub(">.*", "", tag); }
+		$0 ~ /(call|jmp)q?  *\*0x[0-9a-f]*\(%rip\)/ {
+			next
+		}
+		$0 ~ /(call|jmp)q?  *\*.*%/ {
+			sub(":", "", $1);
+			if ('"$selector"') {
+				offset=$1
+				$1=tag
+				print(file "-" segment "-" offset " " src " " segment " " $0);
+			}
+		}
+	'
+}
+
+# Accumulate potentially vunerable indirect call/jmp sequences.  We do this
+# by examining the raw disassembly for affected forms, recording the location
+# of each.
+case "$bit16" in
+'')	disassemble "$object" "$src" '' 'segment != ".init.text"' ;;
+*)	disassemble "$object" "$src" '--disassembler-options=i8086' 'segment != ".init.text" && segment != ".text32" && segment != ".text64"'
+	disassemble "$object" "$src" '--disassembler-options=i386' 'segment == ".text32"'
+	disassemble "$object" "$src" '--disassembler-options=x86-64' 'segment == ".text64"'
+	;;
+esac | sort -k 1b,1 >"$object.ur-detected"
+[ ! -s "$object.ur-detected" ] && rm -f "$object.ur-detected"
+
+# Load up the symbol table and section mappings.
+symbolmap_init "$object"
+sectionmap_init "$object"
+
+# Accumulate annotated safe indirect call/jmp sequences.  We do this by examining
+# the $SECTION sections (and their associated relocation information),
+# each entry represents the address of an instruction which has been marked
+# as ok.
+case "$section_relocation" in
+REL)	rel "$object" ;;
+RELA)	rela "$object" ;;
+esac | sort -k 1b,1 >"$object.ur-safe"
+[ ! -s "$object.ur-safe" ] && rm -f "$object.ur-safe"
+
+# We will perform the below join on the summarised and sorted fragments
+# formed above.  This is performed in retpoline-check.
+#join -v 1 -j 1 "$tmp.extracted" "$tmp.safe" | sed -s 's/[^ ]*  *//'
+
+rm -f "$tmp"
--- linux-xilinx-zynqmp-5.4.0.orig/debian/scripts/sub-flavour
+++ linux-xilinx-zynqmp-5.4.0/debian/scripts/sub-flavour
@@ -0,0 +1,69 @@
+#!/bin/bash
+
+. debian/debian.env
+
+echo "SUB_PROCESS $FROM => $TO"
+
+export from_pkg="linux-image-$ABI_RELEASE-$FROM"
+export to_pkg="linux-image-$ABI_RELEASE-$TO"
+
+from_moddir="debian/$from_pkg/lib/modules/$ABI_RELEASE-$FROM"
+to_moddir="debian/$to_pkg/lib/modules/$ABI_RELEASE-$FROM"
+
+install -d "debian/$to_pkg/boot"
+install -m644 debian/$from_pkg/boot/config-$ABI_RELEASE-$FROM \
+	debian/$to_pkg/boot/
+install -m600 debian/$from_pkg/boot/{vmlinuz,System.map}-$ABI_RELEASE-$FROM \
+	debian/$to_pkg/boot/
+
+#
+# Print some warnings if there are files in the sub-flavours list
+# that do not actually exist.
+#
+cat ${DEBIAN}/sub-flavours/$TO.list | while read line
+do
+(
+	cd debian/$from_pkg/lib/modules/$ABI_RELEASE-$FROM/kernel;
+	#
+	# If its a wildcard, then check that there are files that match.
+	#
+	if echo "$line" | grep '\*' > /dev/null
+	then
+		if [ `eval find "$line" -name '*.ko' 2>/dev/null|wc -l` -lt 1 ]
+		then
+			echo SUB_INST Warning - No files in $line
+		fi
+	#
+	# Else it should be a single file reference.
+	#
+	elif [ ! -f "$line" ]
+	then
+		echo SUB_INST Warning - could not find "$line"
+	fi
+)
+done
+
+cat ${DEBIAN}/sub-flavours/$TO.list | while read line; do
+	(
+	cd debian/$from_pkg/lib/modules/$ABI_RELEASE-$FROM/kernel;
+	if echo "$line" | grep '\*' > /dev/null
+	then
+		eval find "$line" -name '*.ko' 2>/dev/null || true
+	elif [ -f "$line" ]
+	then
+		echo "$line"
+	fi
+	);
+done | while read mod; do
+	echo "SUB_INST checking: $mod"
+	fromdir="/lib/modules/$ABI_RELEASE-$FROM/"
+	egrep "^($fromdir)?kernel/$mod:" \
+		$from_moddir/modules.dep | sed -e "s|^$fromdir||" -e 's/://' -e 's/ /\n/g' | \
+	while read m; do
+		m="${fromdir}$m"
+		test -f debian/$to_pkg/$m && continue
+		echo "SUB_INST installing: $m"
+		install -D -m644 debian/$from_pkg/$m \
+			debian/$to_pkg/$m
+	done
+done
--- linux-xilinx-zynqmp-5.4.0.orig/debian/snapcraft.mk
+++ linux-xilinx-zynqmp-5.4.0/debian/snapcraft.mk
@@ -0,0 +1,15 @@
+ifeq ($(ARCH),)
+  arch := $(shell uname -m | sed -e s/i.86/i386/ -e s/x86_64/amd64/ \
+            -e s/arm.*/armhf/ -e s/s390/s390x/ -e s/ppc.*/powerpc/ \
+            -e s/aarch64.*/arm64/ )
+else ifeq ($(ARCH),arm)
+  arch := armhf
+else
+  arch := $(ARCH)
+endif
+config:
+	if [ -e debian/config/config.common.ubuntu ]; then \
+	    cat debian.$(branch)/config/config.common.ubuntu debian.$(branch)/config/$(arch)/config.common.$(arch) debian.$(branch)/config/$(arch)/config.flavour.$(flavour) >.config; \
+	else \
+	    python3 debian/scripts/misc/annotations --export --arch $(arch) --flavour $(flavour) >.config; \
+	fi
--- linux-xilinx-zynqmp-5.4.0.orig/debian/source/format
+++ linux-xilinx-zynqmp-5.4.0/debian/source/format
@@ -0,0 +1 @@
+1.0
--- linux-xilinx-zynqmp-5.4.0.orig/debian/source/options
+++ linux-xilinx-zynqmp-5.4.0/debian/source/options
@@ -0,0 +1,8 @@
+# Ignore vbox symlinks, we will regenerate these at clean (LP:1426113)
+## autoreconstruct -- begin
+# Ignore any symlinks created since the orig which are rebuilt by reconstruct.
+## autoreconstruct -- end
+
+# force "dpkg-source -I -i" behavior
+diff-ignore
+tar-ignore
--- linux-xilinx-zynqmp-5.4.0.orig/debian/stamps/keep-dir
+++ linux-xilinx-zynqmp-5.4.0/debian/stamps/keep-dir
@@ -0,0 +1 @@
+Place holder
--- linux-xilinx-zynqmp-5.4.0.orig/debian/templates/extra.postinst.in
+++ linux-xilinx-zynqmp-5.4.0/debian/templates/extra.postinst.in
@@ -0,0 +1,20 @@
+#!/bin/sh
+set -e
+
+version=@abiname@@localversion@
+image_path=/boot/@image-stem@-$version
+
+if [ "$1" != configure ]; then
+    exit 0
+fi
+
+depmod -a -F /boot/System.map-$version $version || true
+if [ -d /etc/kernel/postinst.d ]; then
+    cat - >/usr/lib/linux/triggers/$version <<EOF
+DEB_MAINT_PARAMS="$*" run-parts --report --exit-on-error --arg=$version \
+	    --arg="$image_path" /etc/kernel/postinst.d
+EOF
+    dpkg-trigger --no-await linux-update-$version
+fi
+
+exit 0
--- linux-xilinx-zynqmp-5.4.0.orig/debian/templates/extra.postrm.in
+++ linux-xilinx-zynqmp-5.4.0/debian/templates/extra.postrm.in
@@ -0,0 +1,31 @@
+#!/bin/sh
+set -e
+
+version=@abiname@@localversion@
+image_path=/boot/@image-stem@-$version
+
+if [ "$1" != remove ]; then
+    exit 0
+fi
+
+depmod -a -F /boot/System.map-$version $version 2>/dev/null || true
+#
+# We should be rebuilding the initramfs here on removal to pare down the
+# initramfs if it contains any of the objects we just removed.  But people
+# commonly remove kernels in order to free space in /boot, and rebuilding the
+# initramfs now risks ENOSPC when we are trying to make space.  The files we
+# leave lying about could be confusing, but we trade that against safety on
+# removal.
+#
+#if [ -d /etc/kernel/postinst.d ]; then
+#    # We want to behave as if linux-image (without us) was installed, therefore
+#    # we do not want the postinst support to know we are being removed, claim
+#    # this is an installation event.
+#    cat - >/usr/lib/linux/triggers/$version <<EOF
+#DEB_MAINT_PARAMS="configure" run-parts --report --exit-on-error --arg=$version \
+#	--arg="$image_path" /etc/kernel/postinst.d
+#EOF
+#    dpkg-trigger --no-await linux-update-$version
+#fi
+
+exit 0
--- linux-xilinx-zynqmp-5.4.0.orig/debian/templates/headers.postinst.in
+++ linux-xilinx-zynqmp-5.4.0/debian/templates/headers.postinst.in
@@ -0,0 +1,15 @@
+#!/bin/sh
+set -e
+
+version=@abiname@@localversion@
+
+if [ "$1" != configure ]; then
+    exit 0
+fi
+
+if [ -d /etc/kernel/header_postinst.d ]; then
+    DEB_MAINT_PARAMS="$*" run-parts --report --exit-on-error --arg=$version \
+		/etc/kernel/header_postinst.d
+fi
+
+exit 0
--- linux-xilinx-zynqmp-5.4.0.orig/debian/templates/image.postinst.in
+++ linux-xilinx-zynqmp-5.4.0/debian/templates/image.postinst.in
@@ -0,0 +1,62 @@
+#!/bin/sh
+set -e
+
+version=@abiname@@localversion@
+image_path=/boot/@image-stem@-$version
+
+#
+# When we install linux-image we have to run kernel postinst.d support to
+# generate the initramfs, create links etc.  Should it have an associated
+# linux-image-extra package and we install that we also need to run kernel
+# postinst.d, to regenerate the initramfs.  If we are installing both at the
+# same time, we necessarily trigger kernel postinst.d twice. As this includes
+# rebuilding the initramfs and reconfiguring the boot loader this is very time
+# consuming.
+#
+# Similarly for removal when we remove the linux-image-extra package we need to
+# run kernel postinst.d handling in order to pare down the initramfs to
+# linux-image contents only.  When we remove the linux-image need to remove the
+# now redundant initramfs.  If we are removing both at the same time, then
+# we will rebuilt the initramfs and then immediatly remove it.
+#
+# Switches to using a trigger against the linux-image package for all
+# postinst.d and postrm.d handling.  On installation postinst.d gets triggered
+# twice once by linux-image and once by linux-image-extra.  As triggers are
+# non-cumulative we will only run this processing once.  When removing both
+# packages we will trigger postinst.d from linux-image-extra and then in
+# linux-image postrm.d we effectivly ignore the pending trigger and simply run
+# the postrm.d.  This prevents us from rebuilding the initramfs.
+#
+if [ "$1" = triggered ]; then
+    trigger=/usr/lib/linux/triggers/$version
+    if [ -f "$trigger" ]; then
+	sh "$trigger"
+	rm -f "$trigger"
+    fi
+    exit 0
+fi
+
+if [ "$1" != configure ]; then
+    exit 0
+fi
+
+depmod $version
+
+if [ -f /lib/modules/$version/.fresh-install ]; then
+    change=install
+else
+    change=upgrade
+fi
+linux-update-symlinks $change $version $image_path
+rm -f /lib/modules/$version/.fresh-install
+
+if [ -d /etc/kernel/postinst.d ]; then
+    mkdir -p /usr/lib/linux/triggers
+    cat - >/usr/lib/linux/triggers/$version <<EOF
+DEB_MAINT_PARAMS="$*" run-parts --report --exit-on-error --arg=$version \
+      --arg=$image_path /etc/kernel/postinst.d
+EOF
+    dpkg-trigger --no-await linux-update-$version
+fi
+
+exit 0
--- linux-xilinx-zynqmp-5.4.0.orig/debian/templates/image.postrm.in
+++ linux-xilinx-zynqmp-5.4.0/debian/templates/image.postrm.in
@@ -0,0 +1,40 @@
+#!/bin/sh
+set -e
+
+version=@abiname@@localversion@
+image_path=/boot/@image-stem@-$version
+
+rm -f /lib/modules/$version/.fresh-install
+
+if [ "$1" != upgrade ] && command -v linux-update-symlinks >/dev/null; then
+    linux-update-symlinks remove $version $image_path
+fi
+
+if [ -d /etc/kernel/postrm.d ]; then
+    # We cannot trigger ourselves as at the end of this we will no longer
+    # exist and can no longer respond to the trigger.  The trigger would
+    # then become lost.  Therefore we clear any pending trigger and apply
+    # postrm directly.
+    if [ -f /usr/lib/linux/triggers/$version ]; then
+	echo "$0 ... removing pending trigger"
+	rm -f /usr/lib/linux/triggers/$version
+    fi
+    DEB_MAINT_PARAMS="$*" run-parts --report --exit-on-error --arg=$version \
+	      --arg=$image_path /etc/kernel/postrm.d
+fi
+
+if [ "$1" = purge ]; then
+    for extra_file in modules.dep modules.isapnpmap modules.pcimap \
+                      modules.usbmap modules.parportmap \
+                      modules.generic_string modules.ieee1394map \
+                      modules.ieee1394map modules.pnpbiosmap \
+                      modules.alias modules.ccwmap modules.inputmap \
+                      modules.symbols modules.ofmap \
+                      modules.seriomap modules.\*.bin \
+		      modules.softdep modules.devname; do
+	eval rm -f /lib/modules/$version/$extra_file
+    done
+    rmdir /lib/modules/$version || true
+fi
+
+exit 0
--- linux-xilinx-zynqmp-5.4.0.orig/debian/templates/image.preinst.in
+++ linux-xilinx-zynqmp-5.4.0/debian/templates/image.preinst.in
@@ -0,0 +1,22 @@
+#!/bin/sh
+set -e
+
+version=@abiname@@localversion@
+image_path=/boot/@image-stem@-$version
+
+if [ "$1" = abort-upgrade ]; then
+    exit 0
+fi
+
+if [ "$1" = install ]; then
+    # Create a flag file for postinst
+    mkdir -p /lib/modules/$version
+    touch /lib/modules/$version/.fresh-install
+fi
+
+if [ -d /etc/kernel/preinst.d ]; then
+    DEB_MAINT_PARAMS="$*" run-parts --report --exit-on-error --arg=$version \
+	      --arg=$image_path /etc/kernel/preinst.d
+fi
+
+exit 0
--- linux-xilinx-zynqmp-5.4.0.orig/debian/templates/image.prerm.in
+++ linux-xilinx-zynqmp-5.4.0/debian/templates/image.prerm.in
@@ -0,0 +1,18 @@
+#!/bin/sh
+set -e
+
+version=@abiname@@localversion@
+image_path=/boot/@image-stem@-$version
+
+if [ "$1" != remove ]; then
+    exit 0
+fi
+
+linux-check-removal $version
+
+if [ -d /etc/kernel/prerm.d ]; then
+    DEB_MAINT_PARAMS="$*" run-parts --report --exit-on-error --arg=$version \
+	      --arg=$image_path /etc/kernel/prerm.d
+fi
+
+exit 0
--- linux-xilinx-zynqmp-5.4.0.orig/debian/tests-build/README
+++ linux-xilinx-zynqmp-5.4.0/debian/tests-build/README
@@ -0,0 +1,21 @@
+Scripts placed in this directory get called one at a time by run-parts(8).
+The scripts are expected to perform some sort of sanity checks on the
+finished build. Scripts will be called once for each flavour.
+
+Some environment variables are exported to make life a little easier:
+
+DPKG_ARCH     : The dpkg architecture (e.g. "amd64")
+KERN_ARCH     : The kernel architecture (e.g. "x86_64")
+FLAVOUR       : The specific flavour for this run (e.g. "generic")
+VERSION       : The full version of this build (e.g. 2.6.22-1)
+REVISION      : The exact revision of this build (e.g. 1.3)
+PREV_REVISION : The revision prior to this one
+ABI_NUM       : The specific ABI number for this build (e.g. 2)
+PREV_ABI_NUM  : The previous ABI number. Can be the same as ABI_NUM.
+BUILD_DIR     : The directory where this build took place
+INSTALL_DIR   : The directory where the package is prepared
+SOURCE_DIR    : Where the main kernel source is
+
+Scripts are expected to have a zero exit status when no problems occur,
+and non-zero when an error occurs that should stop the build. Scripts
+should print whatever info they deem needed to deduce the problem.
--- linux-xilinx-zynqmp-5.4.0.orig/debian/tests-build/check-aliases
+++ linux-xilinx-zynqmp-5.4.0/debian/tests-build/check-aliases
@@ -0,0 +1,24 @@
+#!/usr/bin/perl -w
+
+my %map;
+
+print "Checking for dupe aliases in $ENV{'FLAVOUR'}...\n";
+
+$aliases =
+  "$ENV{'INSTALL_DIR'}/lib/modules/$ENV{'VERSION'}-$ENV{'FLAVOUR'}/modules.alias";
+
+open(ALIASES, "< $aliases") or die "Could not open $aliases";
+
+while (<ALIASES>) {
+	chomp;
+	my ($junk, $alias, $module) = split;
+
+	if (defined($map{$alias})) {
+		printf("%s %20s / %-20s : %s \n", ("$map{$alias}" eq "$module")
+			? "INT" : "   ", $map{$alias}, $module, $alias);
+	} else {
+		$map{$alias} = $module;
+	}
+}
+
+exit(0);
--- linux-xilinx-zynqmp-5.4.0.orig/debian/tests/control
+++ linux-xilinx-zynqmp-5.4.0/debian/tests/control
@@ -0,0 +1,7 @@
+Tests: rebuild
+Depends: @builddeps@, fakeroot
+Restrictions: allow-stderr, skippable
+
+Tests: ubuntu-regression-suite
+Depends: build-essential, gcc-multilib [amd64 armhf i386], gdb, git, python2 | python, bzr
+Restrictions: allow-stderr, isolation-machine, breaks-testbed, skippable
--- linux-xilinx-zynqmp-5.4.0.orig/debian/tests/rebuild
+++ linux-xilinx-zynqmp-5.4.0/debian/tests/rebuild
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+# If we are triggering for just linux or linux-meta we know we have
+# just built the kernel and there is no point in repeating that
+# build, it just wastes time.  (LP: #1498862)
+build_needed=0
+for trigger in ${ADT_TEST_TRIGGERS:-force}
+do
+	case "$trigger" in
+	linux/*|linux-lts-*/*|linux-meta*/*|linux-oem*/*|fakeroot/*|gdb/*|git/*|bzr/*|gcc-multilib/*)	;;
+	*)						build_needed=1 ;;
+	esac
+done
+if [ "$build_needed" -eq 0 ]; then
+	echo "rebuild: short circuiting build for '${ADT_TEST_TRIGGERS}'"
+	exit 77
+fi
+
+set -e
+dpkg-buildpackage -rfakeroot -us -uc -b -Pautopkgtest
--- linux-xilinx-zynqmp-5.4.0.orig/debian/tests/ubuntu-regression-suite
+++ linux-xilinx-zynqmp-5.4.0/debian/tests/ubuntu-regression-suite
@@ -0,0 +1,45 @@
+#!/bin/sh
+set -e
+
+# Only run regression-suite on kernels we can boot in canonistack
+source=`dpkg-parsechangelog -SSource`
+case $source in
+    linux|linux-hwe*|linux-kvm|linux-oem)
+	;;
+    *)
+	echo "ubuntu-regression-suite is pointless, if one cannot boot the kernel"
+	exit 77
+	;;
+esac
+
+# Only run regression-suite if we were requested to
+have_meta=0
+for trigger in ${ADT_TEST_TRIGGERS}
+do
+    case "$trigger" in
+	linux-meta/*|linux-meta-*/*)
+	    have_meta=1
+	    ;;
+    esac
+done
+if [ -n "$ADT_TEST_TRIGGERS" ] && [ "$have_meta" -eq 0 ]; then
+    echo "ubuntu-regression-suite is not requested, as there is no linux-meta trigger"
+    exit 77
+fi
+
+sver=`dpkg-parsechangelog -SVersion`
+read x rver x </proc/version_signature
+
+flavour=${rver#*-*-}
+rver=${rver%-$flavour}
+
+echo "Source Package Version: $sver"
+echo "Running Kernel Version: $rver"
+
+if [ "$sver" != "$rver" ]; then
+    echo "ERROR: running version does not match source package" 1>&2
+    exit 1
+fi
+
+git clone --depth=1 git://git.launchpad.net/~canonical-kernel-team/+git/kernel-testing
+kernel-testing/run-dep8-tests
--- linux-xilinx-zynqmp-5.4.0.orig/debian/tools/generic
+++ linux-xilinx-zynqmp-5.4.0/debian/tools/generic
@@ -0,0 +1,60 @@
+#!/bin/bash
+full_version=`uname -r`
+
+# First check for a fully qualified version.
+this="/usr/lib/linux-tools/$full_version/`basename $0`"
+if [ -f "$this" ]; then
+	exec "$this" "$@"
+fi
+
+# Removing flavour from version i.e. generic or server.
+flavour_abi=${full_version#*-}
+flavour=${flavour_abi#*-}
+version=${full_version%-$flavour}
+this="$0_$version"
+if [ -f "$this" ]; then
+	exec "$this" "$@"
+fi
+
+# Before saucy kernels we had no flavour linkage.
+if dpkg --compare-versions "$version" lt "3.11.0"; then
+	flavour=''
+else
+	flavour="-$flavour"
+fi
+# Hint at the cloud tools if they exist (trusty and later)
+if dpkg --compare-versions "$version" ge "3.13.0"; then
+	cld=""
+else
+	cld=":"
+fi
+# Work out if this is an LTS backport or not.
+codename=`lsb_release -cs`
+case "$codename" in
+precise)	base='3.2.0-9999' ;;
+trusty)		base='3.13.0-9999' ;;
+*)		base='' ;;
+esac
+std=""
+lts=":"
+if [ "$base" != "" ]; then
+	if dpkg --compare-versions "$version" gt "$base"; then
+		std=":"
+		lts=""
+	fi
+fi
+
+# Give them a hint as to what to install.
+		echo "WARNING: `basename $0` not found for kernel $version" >&2
+		echo "" >&2
+		echo "  You may need to install the following packages for this specific kernel:" >&2
+		echo "    linux-tools-$version$flavour" >&2
+$cld		echo "    linux-cloud-tools-$version$flavour" >&2
+		echo "" >&2
+		echo "  You may also want to install one of the following packages to keep up to date:" >&2
+$std		echo "    linux-tools$flavour" >&2
+$std $cld	echo "    linux-cloud-tools$flavour" >&2
+$lts		echo "    linux-tools$flavour-lts-<series>" >&2
+$lts $cld	echo "    linux-cloud-tools$flavour-lts-<series>" >&2
+
+exit 2
--- linux-xilinx-zynqmp-5.4.0.orig/debian/vbox-modules.ignore
+++ linux-xilinx-zynqmp-5.4.0/debian/vbox-modules.ignore
@@ -0,0 +1,2 @@
+vboxguest
+vboxsf
--- linux-xilinx-zynqmp-5.4.0.orig/debian/wireguard-modules.ignore
+++ linux-xilinx-zynqmp-5.4.0/debian/wireguard-modules.ignore
@@ -0,0 +1 @@
+wireguard
--- linux-xilinx-zynqmp-5.4.0.orig/debian/zfs-modules.ignore
+++ linux-xilinx-zynqmp-5.4.0/debian/zfs-modules.ignore
@@ -0,0 +1,10 @@
+icp
+spl
+splat
+zavl
+zcommon
+zfs
+zlua
+znvpair
+zpios
+zunicode
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/Makefile
@@ -58,14 +58,9 @@
 # iommu/ comes before gpu as gpu are using iommu controllers
 obj-y				+= iommu/
 
-# gpu/ comes after char for AGP vs DRM startup and after iommu
-obj-y				+= gpu/
 
 obj-$(CONFIG_CONNECTOR)		+= connector/
 
-# i810fb and intelfb depend on char/agp/
-obj-$(CONFIG_FB_I810)           += video/fbdev/i810/
-obj-$(CONFIG_FB_INTEL)          += video/fbdev/intelfb/
 
 obj-$(CONFIG_PARPORT)		+= parport/
 obj-$(CONFIG_NVM)		+= lightnvm/
@@ -79,6 +74,12 @@
 obj-y				+= scsi/
 obj-y				+= nvme/
 obj-$(CONFIG_ATA)		+= ata/
+
+# gpu/ comes after char for AGP vs DRM startup and after iommu
+obj-y				+= gpu/
+# i810fb and intelfb depend on char/agp/
+obj-$(CONFIG_FB_I810)           += video/fbdev/i810/
+obj-$(CONFIG_FB_INTEL)          += video/fbdev/intelfb/
 obj-$(CONFIG_TARGET_CORE)	+= target/
 obj-$(CONFIG_MTD)		+= mtd/
 obj-$(CONFIG_SPI)		+= spi/
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/Makefile
@@ -8,6 +8,11 @@
 #
 # ACPI Boot-Time Table Parsing
 #
+ifeq ($(CONFIG_ACPI_CUSTOM_DSDT),y)
+tables.o: $(src)/../../include/$(subst $\",,$(CONFIG_ACPI_CUSTOM_DSDT_FILE)) ;
+
+endif
+
 obj-$(CONFIG_ACPI)		+= tables.o
 obj-$(CONFIG_X86)		+= blacklist.o
 
@@ -48,7 +53,7 @@
 acpi-$(CONFIG_ARM_AMBA)	+= acpi_amba.o
 acpi-y				+= power.o
 acpi-y				+= event.o
-acpi-$(CONFIG_ACPI_REDUCED_HARDWARE_ONLY) += evged.o
+acpi-y				+= evged.o
 acpi-y				+= sysfs.o
 acpi-y				+= property.o
 acpi-$(CONFIG_X86)		+= acpi_cmos_rtc.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpi_amba.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpi_amba.c
@@ -76,6 +76,7 @@
 		case IORESOURCE_MEM:
 			if (!address_found) {
 				dev->res = *rentry->res;
+				dev->res.name = dev_name(&dev->dev);
 				address_found = true;
 			}
 			break;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpi_configfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpi_configfs.c
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/configfs.h>
 #include <linux/acpi.h>
+#include <linux/security.h>
 
 #include "acpica/accommon.h"
 #include "acpica/actables.h"
@@ -28,7 +29,10 @@
 {
 	const struct acpi_table_header *header = data;
 	struct acpi_table *table;
-	int ret;
+	int ret = security_locked_down(LOCKDOWN_ACPI_TABLES);
+
+	if (ret)
+		return ret;
 
 	table = container_of(cfg, struct acpi_table, cfg);
 
@@ -263,7 +267,12 @@
 
 	acpi_table_group = configfs_register_default_group(root, "table",
 							   &acpi_tables_type);
-	return PTR_ERR_OR_ZERO(acpi_table_group);
+	if (IS_ERR(acpi_table_group)) {
+		configfs_unregister_subsystem(&acpi_configfs);
+		return PTR_ERR(acpi_table_group);
+	}
+
+	return 0;
 }
 module_init(acpi_configfs_init);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpi_dbg.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpi_dbg.c
@@ -749,6 +749,9 @@
 {
 	int ret;
 
+	if (acpi_disabled)
+		return -ENODEV;
+
 	/* Initialize AML IO interface */
 	mutex_init(&acpi_aml_io.lock);
 	init_waitqueue_head(&acpi_aml_io.wait);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpi_extlog.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpi_extlog.c
@@ -12,6 +12,7 @@
 #include <linux/ratelimit.h>
 #include <linux/edac.h>
 #include <linux/ras.h>
+#include <acpi/ghes.h>
 #include <asm/cpu.h>
 #include <asm/mce.h>
 
@@ -140,8 +141,8 @@
 	int	cpu = mce->extcpu;
 	struct acpi_hest_generic_status *estatus, *tmp;
 	struct acpi_hest_generic_data *gdata;
-	const guid_t *fru_id = &guid_null;
-	char *fru_text = "";
+	const guid_t *fru_id;
+	char *fru_text;
 	guid_t *sec_type;
 	static u32 err_seq;
 
@@ -162,17 +163,23 @@
 
 	/* log event via trace */
 	err_seq++;
-	gdata = (struct acpi_hest_generic_data *)(tmp + 1);
-	if (gdata->validation_bits & CPER_SEC_VALID_FRU_ID)
-		fru_id = (guid_t *)gdata->fru_id;
-	if (gdata->validation_bits & CPER_SEC_VALID_FRU_TEXT)
-		fru_text = gdata->fru_text;
-	sec_type = (guid_t *)gdata->section_type;
-	if (guid_equal(sec_type, &CPER_SEC_PLATFORM_MEM)) {
-		struct cper_sec_mem_err *mem = (void *)(gdata + 1);
-		if (gdata->error_data_length >= sizeof(*mem))
-			trace_extlog_mem_event(mem, err_seq, fru_id, fru_text,
-					       (u8)gdata->error_severity);
+	apei_estatus_for_each_section(tmp, gdata) {
+		if (gdata->validation_bits & CPER_SEC_VALID_FRU_ID)
+			fru_id = (guid_t *)gdata->fru_id;
+		else
+			fru_id = &guid_null;
+		if (gdata->validation_bits & CPER_SEC_VALID_FRU_TEXT)
+			fru_text = gdata->fru_text;
+		else
+			fru_text = "";
+		sec_type = (guid_t *)gdata->section_type;
+		if (guid_equal(sec_type, &CPER_SEC_PLATFORM_MEM)) {
+			struct cper_sec_mem_err *mem = (void *)(gdata + 1);
+
+			if (gdata->error_data_length >= sizeof(*mem))
+				trace_extlog_mem_event(mem, err_seq, fru_id, fru_text,
+						       (u8)gdata->error_severity);
+		}
 	}
 
 out:
@@ -223,9 +230,9 @@
 	u64 cap;
 	int rc;
 
-	rdmsrl(MSR_IA32_MCG_CAP, cap);
-
-	if (!(cap & MCG_ELOG_P) || !extlog_get_l1addr())
+	if (rdmsrl_safe(MSR_IA32_MCG_CAP, &cap) ||
+	    !(cap & MCG_ELOG_P) ||
+	    !extlog_get_l1addr())
 		return -ENODEV;
 
 	if (edac_get_report_status() == EDAC_REPORTING_FORCE) {
@@ -309,9 +316,10 @@
 {
 	edac_set_report_status(old_edac_report_status);
 	mce_unregister_decode_chain(&extlog_mce_dec);
-	((struct extlog_l1_head *)extlog_l1_addr)->flags &= ~FLAG_OS_OPTIN;
-	if (extlog_l1_addr)
+	if (extlog_l1_addr) {
+		((struct extlog_l1_head *)extlog_l1_addr)->flags &= ~FLAG_OS_OPTIN;
 		acpi_os_unmap_iomem(extlog_l1_addr, l1_size);
+	}
 	if (elog_addr)
 		acpi_os_unmap_iomem(elog_addr, elog_size);
 	release_mem_region(elog_base, elog_size);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpi_lpit.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpi_lpit.c
@@ -98,7 +98,7 @@
 				 struct acpi_lpit_native *lpit_native)
 {
 	info->frequency = lpit_native->counter_frequency ?
-				lpit_native->counter_frequency : tsc_khz * 1000;
+				lpit_native->counter_frequency : mul_u32_u32(tsc_khz, 1000U);
 	if (!info->frequency)
 		info->frequency = 1;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpi_lpss.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpi_lpss.c
@@ -10,6 +10,7 @@
 #include <linux/acpi.h>
 #include <linux/clkdev.h>
 #include <linux/clk-provider.h>
+#include <linux/dmi.h>
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/mutex.h>
@@ -400,6 +401,9 @@
 	if (!lpss_clk_dev)
 		lpt_register_clock_device();
 
+	if (IS_ERR(lpss_clk_dev))
+		return PTR_ERR(lpss_clk_dev);
+
 	clk_data = platform_get_drvdata(lpss_clk_dev);
 	if (!clk_data)
 		return -ENODEV;
@@ -463,6 +467,18 @@
 	const char *consumer_hid;
 	const char *consumer_uid;
 	u32 flags;
+	const struct dmi_system_id *dep_missing_ids;
+};
+
+/* Please keep this list sorted alphabetically by vendor and model */
+static const struct dmi_system_id i2c1_dep_missing_dmi_ids[] = {
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "T200TA"),
+		},
+	},
+	{}
 };
 
 /*
@@ -473,9 +489,17 @@
  * the supplier is not enumerated until after the consumer is probed.
  */
 static const struct lpss_device_links lpss_device_links[] = {
+	/* CHT External sdcard slot controller depends on PMIC I2C ctrl */
 	{"808622C1", "7", "80860F14", "3", DL_FLAG_PM_RUNTIME},
+	/* CHT iGPU depends on PMIC I2C controller */
 	{"808622C1", "7", "LNXVIDEO", NULL, DL_FLAG_PM_RUNTIME},
+	/* BYT iGPU depends on the Embedded Controller I2C controller (UID 1) */
+	{"80860F41", "1", "LNXVIDEO", NULL, DL_FLAG_PM_RUNTIME,
+	 i2c1_dep_missing_dmi_ids},
+	/* BYT CR iGPU depends on PMIC I2C controller (UID 5 on CR) */
 	{"80860F41", "5", "LNXVIDEO", NULL, DL_FLAG_PM_RUNTIME},
+	/* BYT iGPU depends on PMIC I2C controller (UID 7 on non CR) */
+	{"80860F41", "7", "LNXVIDEO", NULL, DL_FLAG_PM_RUNTIME},
 };
 
 static bool hid_uid_match(struct acpi_device *adev,
@@ -570,7 +594,8 @@
 	if (!dev2)
 		return;
 
-	if (acpi_lpss_dep(ACPI_COMPANION(dev2), ACPI_HANDLE(dev1)))
+	if ((link->dep_missing_ids && dmi_check_system(link->dep_missing_ids))
+	    || acpi_lpss_dep(ACPI_COMPANION(dev2), ACPI_HANDLE(dev1)))
 		device_link_add(dev2, dev1, link->flags);
 
 	put_device(dev2);
@@ -585,7 +610,8 @@
 	if (!dev2)
 		return;
 
-	if (acpi_lpss_dep(ACPI_COMPANION(dev1), ACPI_HANDLE(dev2)))
+	if ((link->dep_missing_ids && dmi_check_system(link->dep_missing_ids))
+	    || acpi_lpss_dep(ACPI_COMPANION(dev1), ACPI_HANDLE(dev2)))
 		device_link_add(dev1, dev2, link->flags);
 
 	put_device(dev2);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpi_pad.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpi_pad.c
@@ -88,7 +88,7 @@
 	cpumask_var_t tmp;
 	int cpu;
 	unsigned long min_weight = -1;
-	unsigned long uninitialized_var(preferred_cpu);
+	unsigned long preferred_cpu;
 
 	if (!alloc_cpumask_var(&tmp, GFP_KERNEL))
 		return;
@@ -128,8 +128,11 @@
 static void exit_round_robin(unsigned int tsk_index)
 {
 	struct cpumask *pad_busy_cpus = to_cpumask(pad_busy_cpus_bits);
-	cpumask_clear_cpu(tsk_in_cpu[tsk_index], pad_busy_cpus);
-	tsk_in_cpu[tsk_index] = -1;
+
+	if (tsk_in_cpu[tsk_index] != -1) {
+		cpumask_clear_cpu(tsk_in_cpu[tsk_index], pad_busy_cpus);
+		tsk_in_cpu[tsk_index] = -1;
+	}
 }
 
 static unsigned int idle_pct = 5; /* percentage */
@@ -262,7 +265,7 @@
 	return ps_tsk_num;
 }
 
-static ssize_t acpi_pad_rrtime_store(struct device *dev,
+static ssize_t rrtime_store(struct device *dev,
 	struct device_attribute *attr, const char *buf, size_t count)
 {
 	unsigned long num;
@@ -276,16 +279,14 @@
 	return count;
 }
 
-static ssize_t acpi_pad_rrtime_show(struct device *dev,
+static ssize_t rrtime_show(struct device *dev,
 	struct device_attribute *attr, char *buf)
 {
 	return scnprintf(buf, PAGE_SIZE, "%d\n", round_robin_time);
 }
-static DEVICE_ATTR(rrtime, S_IRUGO|S_IWUSR,
-	acpi_pad_rrtime_show,
-	acpi_pad_rrtime_store);
+static DEVICE_ATTR_RW(rrtime);
 
-static ssize_t acpi_pad_idlepct_store(struct device *dev,
+static ssize_t idlepct_store(struct device *dev,
 	struct device_attribute *attr, const char *buf, size_t count)
 {
 	unsigned long num;
@@ -299,16 +300,14 @@
 	return count;
 }
 
-static ssize_t acpi_pad_idlepct_show(struct device *dev,
+static ssize_t idlepct_show(struct device *dev,
 	struct device_attribute *attr, char *buf)
 {
 	return scnprintf(buf, PAGE_SIZE, "%d\n", idle_pct);
 }
-static DEVICE_ATTR(idlepct, S_IRUGO|S_IWUSR,
-	acpi_pad_idlepct_show,
-	acpi_pad_idlepct_store);
+static DEVICE_ATTR_RW(idlepct);
 
-static ssize_t acpi_pad_idlecpus_store(struct device *dev,
+static ssize_t idlecpus_store(struct device *dev,
 	struct device_attribute *attr, const char *buf, size_t count)
 {
 	unsigned long num;
@@ -320,16 +319,14 @@
 	return count;
 }
 
-static ssize_t acpi_pad_idlecpus_show(struct device *dev,
+static ssize_t idlecpus_show(struct device *dev,
 	struct device_attribute *attr, char *buf)
 {
 	return cpumap_print_to_pagebuf(false, buf,
 				       to_cpumask(pad_busy_cpus_bits));
 }
 
-static DEVICE_ATTR(idlecpus, S_IRUGO|S_IWUSR,
-	acpi_pad_idlecpus_show,
-	acpi_pad_idlecpus_store);
+static DEVICE_ATTR_RW(idlecpus);
 
 static int acpi_pad_add_sysfs(struct acpi_device *device)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpi_platform.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpi_platform.c
@@ -31,6 +31,44 @@
 	{"", 0},
 };
 
+static struct platform_device *acpi_platform_device_find_by_companion(struct acpi_device *adev)
+{
+	struct device *dev;
+
+	dev = bus_find_device_by_acpi_dev(&platform_bus_type, adev);
+	return dev ? to_platform_device(dev) : NULL;
+}
+
+static int acpi_platform_device_remove_notify(struct notifier_block *nb,
+					      unsigned long value, void *arg)
+{
+	struct acpi_device *adev = arg;
+	struct platform_device *pdev;
+
+	switch (value) {
+	case ACPI_RECONFIG_DEVICE_ADD:
+		/* Nothing to do here */
+		break;
+	case ACPI_RECONFIG_DEVICE_REMOVE:
+		if (!acpi_device_enumerated(adev))
+			break;
+
+		pdev = acpi_platform_device_find_by_companion(adev);
+		if (!pdev)
+			break;
+
+		platform_device_unregister(pdev);
+		put_device(&pdev->dev);
+		break;
+	}
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block acpi_platform_notifier = {
+	.notifier_call = acpi_platform_device_remove_notify,
+};
+
 static void acpi_platform_fill_resource(struct acpi_device *adev,
 	const struct resource *src, struct resource *dest)
 {
@@ -130,3 +168,8 @@
 	return pdev;
 }
 EXPORT_SYMBOL_GPL(acpi_create_platform_device);
+
+void __init acpi_platform_init(void)
+{
+	acpi_reconfig_notifier_register(&acpi_platform_notifier);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpi_pnp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpi_pnp.c
@@ -317,6 +317,9 @@
 {
 	int i;
 
+	if (strlen(idstr) != strlen(list_id))
+		return false;
+
 	if (memcmp(idstr, list_id, 3))
 		return false;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpi_processor.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpi_processor.c
@@ -388,7 +388,7 @@
 
 	result = acpi_processor_get_info(device);
 	if (result) /* Processor is not physically present or unavailable */
-		return 0;
+		goto err_clear_driver_data;
 
 	BUG_ON(pr->id >= nr_cpu_ids);
 
@@ -403,7 +403,7 @@
 			"BIOS reported wrong ACPI id %d for the processor\n",
 			pr->id);
 		/* Give up, but do not abort the namespace scan. */
-		goto err;
+		goto err_clear_driver_data;
 	}
 	/*
 	 * processor_device_array is not cleared on errors to allow buggy BIOS
@@ -415,12 +415,12 @@
 	dev = get_cpu_device(pr->id);
 	if (!dev) {
 		result = -ENODEV;
-		goto err;
+		goto err_clear_per_cpu;
 	}
 
 	result = acpi_bind_one(dev, device);
 	if (result)
-		goto err;
+		goto err_clear_per_cpu;
 
 	pr->dev = dev;
 
@@ -431,10 +431,11 @@
 	dev_err(dev, "Processor driver could not be attached\n");
 	acpi_unbind_one(dev);
 
- err:
-	free_cpumask_var(pr->throttling.shared_cpu_map);
-	device->driver_data = NULL;
+ err_clear_per_cpu:
 	per_cpu(processors, pr->id) = NULL;
+ err_clear_driver_data:
+	device->driver_data = NULL;
+	free_cpumask_var(pr->throttling.shared_cpu_map);
  err_free_pr:
 	kfree(pr);
 	return result;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpi_tad.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpi_tad.c
@@ -237,7 +237,7 @@
 		       rt.tz, rt.daylight);
 }
 
-static DEVICE_ATTR(time, S_IRUSR | S_IWUSR, time_show, time_store);
+static DEVICE_ATTR_RW(time);
 
 static struct attribute *acpi_tad_time_attrs[] = {
 	&dev_attr_time.attr,
@@ -446,7 +446,7 @@
 	return acpi_tad_alarm_read(dev, buf, ACPI_TAD_AC_TIMER);
 }
 
-static DEVICE_ATTR(ac_alarm, S_IRUSR | S_IWUSR, ac_alarm_show, ac_alarm_store);
+static DEVICE_ATTR_RW(ac_alarm);
 
 static ssize_t ac_policy_store(struct device *dev, struct device_attribute *attr,
 			       const char *buf, size_t count)
@@ -462,7 +462,7 @@
 	return acpi_tad_policy_read(dev, buf, ACPI_TAD_AC_TIMER);
 }
 
-static DEVICE_ATTR(ac_policy, S_IRUSR | S_IWUSR, ac_policy_show, ac_policy_store);
+static DEVICE_ATTR_RW(ac_policy);
 
 static ssize_t ac_status_store(struct device *dev, struct device_attribute *attr,
 			       const char *buf, size_t count)
@@ -478,7 +478,7 @@
 	return acpi_tad_status_read(dev, buf, ACPI_TAD_AC_TIMER);
 }
 
-static DEVICE_ATTR(ac_status, S_IRUSR | S_IWUSR, ac_status_show, ac_status_store);
+static DEVICE_ATTR_RW(ac_status);
 
 static struct attribute *acpi_tad_attrs[] = {
 	&dev_attr_caps.attr,
@@ -505,7 +505,7 @@
 	return acpi_tad_alarm_read(dev, buf, ACPI_TAD_DC_TIMER);
 }
 
-static DEVICE_ATTR(dc_alarm, S_IRUSR | S_IWUSR, dc_alarm_show, dc_alarm_store);
+static DEVICE_ATTR_RW(dc_alarm);
 
 static ssize_t dc_policy_store(struct device *dev, struct device_attribute *attr,
 			       const char *buf, size_t count)
@@ -521,7 +521,7 @@
 	return acpi_tad_policy_read(dev, buf, ACPI_TAD_DC_TIMER);
 }
 
-static DEVICE_ATTR(dc_policy, S_IRUSR | S_IWUSR, dc_policy_show, dc_policy_store);
+static DEVICE_ATTR_RW(dc_policy);
 
 static ssize_t dc_status_store(struct device *dev, struct device_attribute *attr,
 			       const char *buf, size_t count)
@@ -537,7 +537,7 @@
 	return acpi_tad_status_read(dev, buf, ACPI_TAD_DC_TIMER);
 }
 
-static DEVICE_ATTR(dc_status, S_IRUSR | S_IWUSR, dc_status_show, dc_status_store);
+static DEVICE_ATTR_RW(dc_status);
 
 static struct attribute *acpi_tad_dc_attrs[] = {
 	&dev_attr_dc_alarm.attr,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpi_video.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpi_video.c
@@ -498,6 +498,22 @@
 		DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE R830"),
 		},
 	},
+	{
+	 .callback = video_disable_backlight_sysfs_if,
+	 .ident = "Toshiba Satellite Z830",
+	 .matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE Z830"),
+		},
+	},
+	{
+	 .callback = video_disable_backlight_sysfs_if,
+	 .ident = "Toshiba Portege Z830",
+	 .matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE Z830"),
+		},
+	},
 	/*
 	 * Some machine's _DOD IDs don't have bit 31(Device ID Scheme) set
 	 * but the IDs actually follow the Device ID Scheme.
@@ -543,6 +559,24 @@
 		DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V131"),
 		},
 	},
+	{
+	 .callback = video_set_report_key_events,
+	 .driver_data = (void *)((uintptr_t)REPORT_BRIGHTNESS_KEY_EVENTS),
+	 .ident = "Dell Vostro 3350",
+	 .matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+		DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3350"),
+		},
+	},
+	{
+	 .callback = video_set_report_key_events,
+	 .driver_data = (void *)((uintptr_t)REPORT_BRIGHTNESS_KEY_EVENTS),
+	 .ident = "COLORFUL X15 AT 23",
+	 .matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "COLORFUL"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "X15 AT 23"),
+		},
+	},
 	/*
 	 * Some machines change the brightness themselves when a brightness
 	 * hotkey gets pressed, despite us telling them not to. In this case
@@ -1759,12 +1793,12 @@
 		return;
 	count++;
 
-	acpi_get_parent(device->dev->handle, &acpi_parent);
-
-	pdev = acpi_get_pci_dev(acpi_parent);
-	if (pdev) {
-		parent = &pdev->dev;
-		pci_dev_put(pdev);
+	if (ACPI_SUCCESS(acpi_get_parent(device->dev->handle, &acpi_parent))) {
+		pdev = acpi_get_pci_dev(acpi_parent);
+		if (pdev) {
+			parent = &pdev->dev;
+			pci_dev_put(pdev);
+		}
 	}
 
 	memset(&props, 0, sizeof(struct backlight_properties));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpi_watchdog.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpi_watchdog.c
@@ -55,12 +55,14 @@
 }
 #endif
 
+static bool acpi_no_watchdog;
+
 static const struct acpi_table_wdat *acpi_watchdog_get_wdat(void)
 {
 	const struct acpi_table_wdat *wdat = NULL;
 	acpi_status status;
 
-	if (acpi_disabled)
+	if (acpi_disabled || acpi_no_watchdog)
 		return NULL;
 
 	status = acpi_get_table(ACPI_SIG_WDAT, 0,
@@ -88,6 +90,14 @@
 }
 EXPORT_SYMBOL_GPL(acpi_has_watchdog);
 
+/* ACPI watchdog can be disabled on boot command line */
+static int __init disable_acpi_watchdog(char *str)
+{
+	acpi_no_watchdog = true;
+	return 1;
+}
+__setup("acpi_no_watchdog", disable_acpi_watchdog);
+
 void __init acpi_watchdog_init(void)
 {
 	const struct acpi_wdat_entry *entries;
@@ -126,12 +136,11 @@
 		gas = &entries[i].register_region;
 
 		res.start = gas->address;
+		res.end = res.start + ACPI_ACCESS_BYTE_WIDTH(gas->access_width) - 1;
 		if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
 			res.flags = IORESOURCE_MEM;
-			res.end = res.start + ALIGN(gas->access_width, 4) - 1;
 		} else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
 			res.flags = IORESOURCE_IO;
-			res.end = res.start + gas->access_width - 1;
 		} else {
 			pr_warn("Unsupported address space: %u\n",
 				gas->space_id);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpica/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpica/Makefile
@@ -3,8 +3,9 @@
 # Makefile for ACPICA Core interpreter
 #
 
-ccflags-y			:= -Os -D_LINUX -DBUILDING_ACPICA
+ccflags-y			:= -D_LINUX -DBUILDING_ACPICA
 ccflags-$(CONFIG_ACPI_DEBUG)	+= -DACPI_DEBUG_OUTPUT
+CFLAGS_tbfind.o 		+= $(call cc-disable-warning, stringop-truncation)
 
 # use acpi.o to put all files here into acpi.o modparam namespace
 obj-y	+= acpi.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpica/acglobal.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpica/acglobal.h
@@ -220,6 +220,8 @@
     acpi_gbl_bit_register_info[ACPI_NUM_BITREG];
 ACPI_GLOBAL(u8, acpi_gbl_sleep_type_a);
 ACPI_GLOBAL(u8, acpi_gbl_sleep_type_b);
+ACPI_GLOBAL(u8, acpi_gbl_sleep_type_a_s0);
+ACPI_GLOBAL(u8, acpi_gbl_sleep_type_b_s0);
 
 /*****************************************************************************
  *
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpica/achware.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpica/achware.h
@@ -101,6 +101,8 @@
 
 acpi_status acpi_hw_enable_all_wakeup_gpes(void);
 
+u8 acpi_hw_check_all_gpes(acpi_handle gpe_skip_device, u32 gpe_skip_number);
+
 acpi_status
 acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
 				 struct acpi_gpe_block_info *gpe_block,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpica/acnamesp.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpica/acnamesp.h
@@ -256,6 +256,8 @@
 acpi_ns_build_normalized_path(struct acpi_namespace_node *node,
 			      char *full_path, u32 path_size, u8 no_trailing);
 
+void acpi_ns_normalize_pathname(char *original_path);
+
 char *acpi_ns_get_normalized_pathname(struct acpi_namespace_node *node,
 				      u8 no_trailing);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpica/acobject.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpica/acobject.h
@@ -283,6 +283,7 @@
 	acpi_adr_space_handler handler;
 	struct acpi_namespace_node *node;	/* Parent device */
 	void *context;
+	acpi_mutex context_mutex;
 	acpi_adr_space_setup setup;
 	union acpi_operand_object *region_list;	/* Regions using this handler */
 	union acpi_operand_object *next;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpica/dbconvert.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpica/dbconvert.c
@@ -170,6 +170,8 @@
 	elements =
 	    ACPI_ALLOCATE_ZEROED(DB_DEFAULT_PKG_ELEMENTS *
 				 sizeof(union acpi_object));
+	if (!elements)
+		return (AE_NO_MEMORY);
 
 	this = string;
 	for (i = 0; i < (DB_DEFAULT_PKG_ELEMENTS - 1); i++) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpica/dbinput.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpica/dbinput.c
@@ -464,16 +464,14 @@
 		return (NULL);
 	}
 
-	/* Remove any spaces at the beginning */
+	/* Remove any spaces at the beginning, ignore blank lines */
 
-	if (*string == ' ') {
-		while (*string && (*string == ' ')) {
-			string++;
-		}
+	while (*string && isspace(*string)) {
+		string++;
+	}
 
-		if (!(*string)) {
-			return (NULL);
-		}
+	if (!(*string)) {
+		return (NULL);
 	}
 
 	switch (*string) {
@@ -551,7 +549,7 @@
 
 		/* Find end of token */
 
-		while (*string && (*string != ' ')) {
+		while (*string && !isspace(*string)) {
 			string++;
 		}
 		break;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpica/dbnames.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpica/dbnames.c
@@ -571,6 +571,9 @@
 		object_info =
 		    ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_object_info));
 
+		if (!object_info)
+			return (AE_NO_MEMORY);
+
 		/* Walk the namespace from the root */
 
 		(void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpica/dsfield.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpica/dsfield.c
@@ -244,7 +244,7 @@
  * FUNCTION:    acpi_ds_get_field_names
  *
  * PARAMETERS:  info            - create_field info structure
- *  `           walk_state      - Current method state
+ *              walk_state      - Current method state
  *              arg             - First parser arg for the field name list
  *
  * RETURN:      Status
@@ -518,13 +518,20 @@
 	info.region_node = region_node;
 
 	status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
+	if (ACPI_FAILURE(status)) {
+		return_ACPI_STATUS(status);
+	}
+
 	if (info.region_node->object->region.space_id ==
-	    ACPI_ADR_SPACE_PLATFORM_COMM
-	    && !(region_node->object->field.internal_pcc_buffer =
-		 ACPI_ALLOCATE_ZEROED(info.region_node->object->region.
-				      length))) {
-		return_ACPI_STATUS(AE_NO_MEMORY);
+	    ACPI_ADR_SPACE_PLATFORM_COMM) {
+		region_node->object->field.internal_pcc_buffer =
+		    ACPI_ALLOCATE_ZEROED(info.region_node->object->region.
+					 length);
+		if (!region_node->object->field.internal_pcc_buffer) {
+			return_ACPI_STATUS(AE_NO_MEMORY);
+		}
 	}
+
 	return_ACPI_STATUS(status);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpica/dsmethod.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpica/dsmethod.c
@@ -517,7 +517,7 @@
 	info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
 	if (!info) {
 		status = AE_NO_MEMORY;
-		goto cleanup;
+		goto pop_walk_state;
 	}
 
 	info->parameters = &this_walk_state->operands[0];
@@ -529,7 +529,7 @@
 
 	ACPI_FREE(info);
 	if (ACPI_FAILURE(status)) {
-		goto cleanup;
+		goto pop_walk_state;
 	}
 
 	next_walk_state->method_nesting_depth =
@@ -575,6 +575,12 @@
 
 	return_ACPI_STATUS(status);
 
+pop_walk_state:
+
+	/* On error, pop the walk state to be deleted from thread */
+
+	acpi_ds_pop_walk_state(thread);
+
 cleanup:
 
 	/* On error, we must terminate the method properly */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpica/dswexec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpica/dswexec.c
@@ -16,6 +16,9 @@
 #include "acinterp.h"
 #include "acnamesp.h"
 #include "acdebug.h"
+#ifdef ACPI_EXEC_APP
+#include "aecommon.h"
+#endif
 
 #define _COMPONENT          ACPI_DISPATCHER
 ACPI_MODULE_NAME("dswexec")
@@ -329,6 +332,10 @@
 	u32 op_class;
 	union acpi_parse_object *next_op;
 	union acpi_parse_object *first_arg;
+#ifdef ACPI_EXEC_APP
+	char *namepath;
+	union acpi_operand_object *obj_desc;
+#endif
 
 	ACPI_FUNCTION_TRACE_PTR(ds_exec_end_op, walk_state);
 
@@ -537,6 +544,32 @@
 
 			status =
 			    acpi_ds_eval_buffer_field_operands(walk_state, op);
+			if (ACPI_FAILURE(status)) {
+				break;
+			}
+#ifdef ACPI_EXEC_APP
+			/*
+			 * acpi_exec support for namespace initialization file (initialize
+			 * buffer_fields in this code.)
+			 */
+			namepath =
+			    acpi_ns_get_external_pathname(op->common.node);
+			status = ae_lookup_init_file_entry(namepath, &obj_desc);
+			if (ACPI_SUCCESS(status)) {
+				status =
+				    acpi_ex_write_data_to_field(obj_desc,
+								op->common.
+								node->object,
+								NULL);
+				if ACPI_FAILURE
+					(status) {
+					ACPI_EXCEPTION((AE_INFO, status,
+							"While writing to buffer field"));
+					}
+			}
+			ACPI_FREE(namepath);
+			status = AE_OK;
+#endif
 			break;
 
 		case AML_TYPE_CREATE_OBJECT:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpica/dswload.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpica/dswload.c
@@ -14,7 +14,6 @@
 #include "acdispat.h"
 #include "acinterp.h"
 #include "acnamesp.h"
-
 #ifdef ACPI_ASL_COMPILER
 #include "acdisasm.h"
 #endif
@@ -399,7 +398,6 @@
 	union acpi_parse_object *op;
 	acpi_object_type object_type;
 	acpi_status status = AE_OK;
-
 #ifdef ACPI_ASL_COMPILER
 	u8 param_count;
 #endif
@@ -410,6 +408,27 @@
 	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,
 			  walk_state));
 
+	/*
+	 * Disassembler: handle create field operators here.
+	 *
+	 * create_buffer_field is a deferred op that is typically processed in load
+	 * pass 2. However, disassembly of control method contents walk the parse
+	 * tree with ACPI_PARSE_LOAD_PASS1 and AML_CREATE operators are processed
+	 * in a later walk. This is a problem when there is a control method that
+	 * has the same name as the AML_CREATE object. In this case, any use of the
+	 * name segment will be detected as a method call rather than a reference
+	 * to a buffer field.
+	 *
+	 * This earlier creation during disassembly solves this issue by inserting
+	 * the named object in the ACPI namespace so that references to this name
+	 * would be a name string rather than a method call.
+	 */
+	if ((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) &&
+	    (walk_state->op_info->flags & AML_CREATE)) {
+		status = acpi_ds_create_buffer_field(op, walk_state);
+		return_ACPI_STATUS(status);
+	}
+
 	/* We are only interested in opcodes that have an associated name */
 
 	if (!(walk_state->op_info->flags & (AML_NAMED | AML_FIELD))) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpica/dswload2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpica/dswload2.c
@@ -15,6 +15,9 @@
 #include "acinterp.h"
 #include "acnamesp.h"
 #include "acevents.h"
+#ifdef ACPI_EXEC_APP
+#include "aecommon.h"
+#endif
 
 #define _COMPONENT          ACPI_DISPATCHER
 ACPI_MODULE_NAME("dswload2")
@@ -373,6 +376,10 @@
 	struct acpi_namespace_node *new_node;
 	u32 i;
 	u8 region_space;
+#ifdef ACPI_EXEC_APP
+	union acpi_operand_object *obj_desc;
+	char *namepath;
+#endif
 
 	ACPI_FUNCTION_TRACE(ds_load2_end_op);
 
@@ -466,6 +473,11 @@
 		 * be evaluated later during the execution phase
 		 */
 		status = acpi_ds_create_buffer_field(op, walk_state);
+		if (ACPI_FAILURE(status)) {
+			ACPI_EXCEPTION((AE_INFO, status,
+					"CreateBufferField failure"));
+			goto cleanup;
+			}
 		break;
 
 	case AML_TYPE_NAMED_FIELD:
@@ -604,6 +616,29 @@
 		case AML_NAME_OP:
 
 			status = acpi_ds_create_node(walk_state, node, op);
+			if (ACPI_FAILURE(status)) {
+				goto cleanup;
+			}
+#ifdef ACPI_EXEC_APP
+			/*
+			 * acpi_exec support for namespace initialization file (initialize
+			 * Name opcodes in this code.)
+			 */
+			namepath = acpi_ns_get_external_pathname(node);
+			status = ae_lookup_init_file_entry(namepath, &obj_desc);
+			if (ACPI_SUCCESS(status)) {
+
+				/* Detach any existing object, attach new object */
+
+				if (node->object) {
+					acpi_ns_detach_object(node);
+				}
+				acpi_ns_attach_object(node, obj_desc,
+						      obj_desc->common.type);
+			}
+			ACPI_FREE(namepath);
+			status = AE_OK;
+#endif
 			break;
 
 		case AML_METHOD_OP:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpica/dswstate.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpica/dswstate.c
@@ -576,9 +576,14 @@
 	ACPI_FUNCTION_TRACE(ds_init_aml_walk);
 
 	walk_state->parser_state.aml =
-	    walk_state->parser_state.aml_start = aml_start;
-	walk_state->parser_state.aml_end =
-	    walk_state->parser_state.pkg_end = aml_start + aml_length;
+	    walk_state->parser_state.aml_start =
+	    walk_state->parser_state.aml_end =
+	    walk_state->parser_state.pkg_end = aml_start;
+	/* Avoid undefined behavior: applying zero offset to null pointer */
+	if (aml_length != 0) {
+		walk_state->parser_state.aml_end += aml_length;
+		walk_state->parser_state.pkg_end += aml_length;
+	}
 
 	/* The next_op of the next_walk will be the beginning of the method */
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpica/evevent.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpica/evevent.c
@@ -265,4 +265,49 @@
 		 handler) (acpi_gbl_fixed_event_handlers[event].context));
 }
 
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_any_fixed_event_status_set
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      TRUE or FALSE
+ *
+ * DESCRIPTION: Checks the PM status register for active fixed events
+ *
+ ******************************************************************************/
+
+u32 acpi_any_fixed_event_status_set(void)
+{
+	acpi_status status;
+	u32 in_status;
+	u32 in_enable;
+	u32 i;
+
+	status = acpi_hw_register_read(ACPI_REGISTER_PM1_ENABLE, &in_enable);
+	if (ACPI_FAILURE(status)) {
+		return (FALSE);
+	}
+
+	status = acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS, &in_status);
+	if (ACPI_FAILURE(status)) {
+		return (FALSE);
+	}
+
+	/*
+	 * Check for all possible Fixed Events and dispatch those that are active
+	 */
+	for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
+
+		/* Both the status and enable bits must be on for this event */
+
+		if ((in_status & acpi_gbl_fixed_event_info[i].status_bit_mask) &&
+		    (in_enable & acpi_gbl_fixed_event_info[i].enable_bit_mask)) {
+			return (TRUE);
+		}
+	}
+
+	return (FALSE);
+}
+
 #endif				/* !ACPI_REDUCED_HARDWARE */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpica/evhandler.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpica/evhandler.c
@@ -489,6 +489,13 @@
 
 	/* Init handler obj */
 
+	status =
+	    acpi_os_create_mutex(&handler_obj->address_space.context_mutex);
+	if (ACPI_FAILURE(status)) {
+		acpi_ut_remove_reference(handler_obj);
+		goto unlock_and_exit;
+	}
+
 	handler_obj->address_space.space_id = (u8)space_id;
 	handler_obj->address_space.handler_flags = flags;
 	handler_obj->address_space.region_list = NULL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpica/evregion.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpica/evregion.c
@@ -111,6 +111,8 @@
 	union acpi_operand_object *region_obj2;
 	void *region_context = NULL;
 	struct acpi_connection_info *context;
+	acpi_mutex context_mutex;
+	u8 context_locked;
 	acpi_physical_address address;
 
 	ACPI_FUNCTION_TRACE(ev_address_space_dispatch);
@@ -135,6 +137,8 @@
 	}
 
 	context = handler_desc->address_space.context;
+	context_mutex = handler_desc->address_space.context_mutex;
+	context_locked = FALSE;
 
 	/*
 	 * It may be the case that the region has never been initialized.
@@ -203,6 +207,23 @@
 	handler = handler_desc->address_space.handler;
 	address = (region_obj->region.address + region_offset);
 
+	ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+			  "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
+			  &region_obj->region.handler->address_space, handler,
+			  ACPI_FORMAT_UINT64(address),
+			  acpi_ut_get_region_name(region_obj->region.
+						  space_id)));
+
+	if (!(handler_desc->address_space.handler_flags &
+	      ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
+		/*
+		 * For handlers other than the default (supplied) handlers, we must
+		 * exit the interpreter because the handler *might* block -- we don't
+		 * know what it will do, so we can't hold the lock on the interpreter.
+		 */
+		acpi_ex_exit_interpreter();
+	}
+
 	/*
 	 * Special handling for generic_serial_bus and general_purpose_io:
 	 * There are three extra parameters that must be passed to the
@@ -211,6 +232,11 @@
 	 *   2) Length of the above buffer
 	 *   3) Actual access length from the access_as() op
 	 *
+	 * Since we pass these extra parameters via the context, which is
+	 * shared between threads, we must lock the context to avoid these
+	 * parameters being changed from another thread before the handler
+	 * has completed running.
+	 *
 	 * In addition, for general_purpose_io, the Address and bit_width fields
 	 * are defined as follows:
 	 *   1) Address is the pin number index of the field (bit offset from
@@ -220,6 +246,14 @@
 	if ((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) &&
 	    context && field_obj) {
 
+		status =
+		    acpi_os_acquire_mutex(context_mutex, ACPI_WAIT_FOREVER);
+		if (ACPI_FAILURE(status)) {
+			goto re_enter_interpreter;
+		}
+
+		context_locked = TRUE;
+
 		/* Get the Connection (resource_template) buffer */
 
 		context->connection = field_obj->field.resource_buffer;
@@ -229,6 +263,14 @@
 	if ((region_obj->region.space_id == ACPI_ADR_SPACE_GPIO) &&
 	    context && field_obj) {
 
+		status =
+		    acpi_os_acquire_mutex(context_mutex, ACPI_WAIT_FOREVER);
+		if (ACPI_FAILURE(status)) {
+			goto re_enter_interpreter;
+		}
+
+		context_locked = TRUE;
+
 		/* Get the Connection (resource_template) buffer */
 
 		context->connection = field_obj->field.resource_buffer;
@@ -238,28 +280,15 @@
 		bit_width = field_obj->field.bit_length;
 	}
 
-	ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
-			  "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
-			  &region_obj->region.handler->address_space, handler,
-			  ACPI_FORMAT_UINT64(address),
-			  acpi_ut_get_region_name(region_obj->region.
-						  space_id)));
-
-	if (!(handler_desc->address_space.handler_flags &
-	      ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
-		/*
-		 * For handlers other than the default (supplied) handlers, we must
-		 * exit the interpreter because the handler *might* block -- we don't
-		 * know what it will do, so we can't hold the lock on the interpreter.
-		 */
-		acpi_ex_exit_interpreter();
-	}
-
 	/* Call the handler */
 
 	status = handler(function, address, bit_width, value, context,
 			 region_obj2->extra.region_context);
 
+	if (context_locked) {
+		acpi_os_release_mutex(context_mutex);
+	}
+
 	if (ACPI_FAILURE(status)) {
 		ACPI_EXCEPTION((AE_INFO, status, "Returned by Handler for [%s]",
 				acpi_ut_get_region_name(region_obj->region.
@@ -276,6 +305,7 @@
 		}
 	}
 
+re_enter_interpreter:
 	if (!(handler_desc->address_space.handler_flags &
 	      ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
 		/*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpica/evxfgpe.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpica/evxfgpe.c
@@ -795,6 +795,45 @@
 
 ACPI_EXPORT_SYMBOL(acpi_enable_all_wakeup_gpes)
 
+/******************************************************************************
+ *
+ * FUNCTION:    acpi_any_gpe_status_set
+ *
+ * PARAMETERS:  gpe_skip_number      - Number of the GPE to skip
+ *
+ * RETURN:      Whether or not the status bit is set for any GPE
+ *
+ * DESCRIPTION: Check the status bits of all enabled GPEs, except for the one
+ *              represented by the "skip" argument, and return TRUE if any of
+ *              them is set or FALSE otherwise.
+ *
+ ******************************************************************************/
+u32 acpi_any_gpe_status_set(u32 gpe_skip_number)
+{
+	acpi_status status;
+	acpi_handle gpe_device;
+	u8 ret;
+
+	ACPI_FUNCTION_TRACE(acpi_any_gpe_status_set);
+
+	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+	if (ACPI_FAILURE(status)) {
+		return (FALSE);
+	}
+
+	status = acpi_get_gpe_device(gpe_skip_number, &gpe_device);
+	if (ACPI_FAILURE(status)) {
+		gpe_device = NULL;
+	}
+
+	ret = acpi_hw_check_all_gpes(gpe_device, gpe_skip_number);
+	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
+
+	return (ret);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_any_gpe_status_set)
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_install_gpe_block
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpica/exfield.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpica/exfield.c
@@ -320,12 +320,7 @@
 		       obj_desc->field.base_byte_offset,
 		       source_desc->buffer.pointer, data_length);
 
-		if ((obj_desc->field.region_obj->region.address ==
-		     PCC_MASTER_SUBSPACE
-		     && MASTER_SUBSPACE_COMMAND(obj_desc->field.
-						base_byte_offset))
-		    || GENERIC_SUBSPACE_COMMAND(obj_desc->field.
-						base_byte_offset)) {
+		if (MASTER_SUBSPACE_COMMAND(obj_desc->field.base_byte_offset)) {
 
 			/* Perform the write */
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpica/exoparg1.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpica/exoparg1.c
@@ -1007,7 +1007,8 @@
 						    (walk_state, return_desc,
 						     &temp_desc);
 						if (ACPI_FAILURE(status)) {
-							goto cleanup;
+							return_ACPI_STATUS
+							    (status);
 						}
 
 						return_desc = temp_desc;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpica/exprep.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpica/exprep.c
@@ -437,6 +437,9 @@
 
 		if (info->connection_node) {
 			second_desc = info->connection_node->object;
+			if (second_desc == NULL) {
+				break;
+			}
 			if (!(second_desc->common.flags & AOPOBJ_DATA_VALID)) {
 				status =
 				    acpi_ds_get_buffer_arguments(second_desc);
@@ -473,10 +476,6 @@
 				    (u8)access_byte_width;
 			}
 		}
-		/* An additional reference for the container */
-
-		acpi_ut_add_reference(obj_desc->field.region_obj);
-
 		ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
 				  "RegionField: BitOff %X, Off %X, Gran %X, Region %p\n",
 				  obj_desc->field.start_field_bit_offset,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpica/exregion.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpica/exregion.c
@@ -43,7 +43,6 @@
 	struct acpi_mem_space_context *mem_info = region_context;
 	u32 length;
 	acpi_size map_length;
-	acpi_size page_boundary_map_length;
 #ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
 	u32 remainder;
 #endif
@@ -120,26 +119,8 @@
 		map_length = (acpi_size)
 		    ((mem_info->address + mem_info->length) - address);
 
-		/*
-		 * If mapping the entire remaining portion of the region will cross
-		 * a page boundary, just map up to the page boundary, do not cross.
-		 * On some systems, crossing a page boundary while mapping regions
-		 * can cause warnings if the pages have different attributes
-		 * due to resource management.
-		 *
-		 * This has the added benefit of constraining a single mapping to
-		 * one page, which is similar to the original code that used a 4k
-		 * maximum window.
-		 */
-		page_boundary_map_length = (acpi_size)
-		    (ACPI_ROUND_UP(address, ACPI_DEFAULT_PAGE_SIZE) - address);
-		if (page_boundary_map_length == 0) {
-			page_boundary_map_length = ACPI_DEFAULT_PAGE_SIZE;
-		}
-
-		if (map_length > page_boundary_map_length) {
-			map_length = page_boundary_map_length;
-		}
+		if (map_length > ACPI_DEFAULT_PAGE_SIZE)
+			map_length = ACPI_DEFAULT_PAGE_SIZE;
 
 		/* Create a new mapping starting at the address given */
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpica/hwesleep.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpica/hwesleep.c
@@ -104,7 +104,9 @@
 
 	/* Flush caches, as per ACPI specification */
 
-	ACPI_FLUSH_CPU_CACHE();
+	if (sleep_state < ACPI_STATE_S4) {
+		ACPI_FLUSH_CPU_CACHE();
+	}
 
 	status = acpi_os_enter_sleep(sleep_state, sleep_control, 0);
 	if (status == AE_CTRL_TERMINATE) {
@@ -147,17 +149,13 @@
 
 acpi_status acpi_hw_extended_wake_prep(u8 sleep_state)
 {
-	acpi_status status;
 	u8 sleep_type_value;
 
 	ACPI_FUNCTION_TRACE(hw_extended_wake_prep);
 
-	status = acpi_get_sleep_type_data(ACPI_STATE_S0,
-					  &acpi_gbl_sleep_type_a,
-					  &acpi_gbl_sleep_type_b);
-	if (ACPI_SUCCESS(status)) {
+	if (acpi_gbl_sleep_type_a_s0 != ACPI_SLEEP_TYPE_INVALID) {
 		sleep_type_value =
-		    ((acpi_gbl_sleep_type_a << ACPI_X_SLEEP_TYPE_POSITION) &
+		    ((acpi_gbl_sleep_type_a_s0 << ACPI_X_SLEEP_TYPE_POSITION) &
 		     ACPI_X_SLEEP_TYPE_MASK);
 
 		(void)acpi_write((u64)(sleep_type_value | ACPI_X_SLEEP_ENABLE),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpica/hwgpe.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpica/hwgpe.c
@@ -444,6 +444,65 @@
 	return (AE_OK);
 }
 
+struct acpi_gpe_block_status_context {
+	struct acpi_gpe_register_info *gpe_skip_register_info;
+	u8 gpe_skip_mask;
+	u8 retval;
+};
+
+/******************************************************************************
+ *
+ * FUNCTION:    acpi_hw_get_gpe_block_status
+ *
+ * PARAMETERS:  gpe_xrupt_info      - GPE Interrupt info
+ *              gpe_block           - Gpe Block info
+ *              context             - GPE list walk context data
+ *
+ * RETURN:      Success
+ *
+ * DESCRIPTION: Produce a combined GPE status bits mask for the given block.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_hw_get_gpe_block_status(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
+			     struct acpi_gpe_block_info *gpe_block,
+			     void *context)
+{
+	struct acpi_gpe_block_status_context *c = context;
+	struct acpi_gpe_register_info *gpe_register_info;
+	u64 in_enable, in_status;
+	acpi_status status;
+	u8 ret_mask;
+	u32 i;
+
+	/* Examine each GPE Register within the block */
+
+	for (i = 0; i < gpe_block->register_count; i++) {
+		gpe_register_info = &gpe_block->register_info[i];
+
+		status = acpi_hw_read(&in_enable,
+				      &gpe_register_info->enable_address);
+		if (ACPI_FAILURE(status)) {
+			continue;
+		}
+
+		status = acpi_hw_read(&in_status,
+				      &gpe_register_info->status_address);
+		if (ACPI_FAILURE(status)) {
+			continue;
+		}
+
+		ret_mask = in_enable & in_status;
+		if (ret_mask && c->gpe_skip_register_info == gpe_register_info) {
+			ret_mask &= ~c->gpe_skip_mask;
+		}
+		c->retval |= ret_mask;
+	}
+
+	return (AE_OK);
+}
+
 /******************************************************************************
  *
  * FUNCTION:    acpi_hw_disable_all_gpes
@@ -510,4 +569,45 @@
 	return_ACPI_STATUS(status);
 }
 
+/******************************************************************************
+ *
+ * FUNCTION:    acpi_hw_check_all_gpes
+ *
+ * PARAMETERS:  gpe_skip_device      - GPE devoce of the GPE to skip
+ *              gpe_skip_number      - Number of the GPE to skip
+ *
+ * RETURN:      Combined status of all GPEs
+ *
+ * DESCRIPTION: Check all enabled GPEs in all GPE blocks, except for the one
+ *              represented by the "skip" arguments, and return TRUE if the
+ *              status bit is set for at least one of them of FALSE otherwise.
+ *
+ ******************************************************************************/
+
+u8 acpi_hw_check_all_gpes(acpi_handle gpe_skip_device, u32 gpe_skip_number)
+{
+	struct acpi_gpe_block_status_context context = {
+		.gpe_skip_register_info = NULL,
+		.retval = 0,
+	};
+	struct acpi_gpe_event_info *gpe_event_info;
+	acpi_cpu_flags flags;
+
+	ACPI_FUNCTION_TRACE(acpi_hw_check_all_gpes);
+
+	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
+
+	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_skip_device,
+						    gpe_skip_number);
+	if (gpe_event_info) {
+		context.gpe_skip_register_info = gpe_event_info->register_info;
+		context.gpe_skip_mask = acpi_hw_get_gpe_register_bit(gpe_event_info);
+	}
+
+	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
+
+	(void)acpi_ev_walk_gpe_list(acpi_hw_get_gpe_block_status, &context);
+	return (context.retval != 0);
+}
+
 #endif				/* !ACPI_REDUCED_HARDWARE */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpica/hwsleep.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpica/hwsleep.c
@@ -110,7 +110,9 @@
 
 	/* Flush caches, as per ACPI specification */
 
-	ACPI_FLUSH_CPU_CACHE();
+	if (sleep_state < ACPI_STATE_S4) {
+		ACPI_FLUSH_CPU_CACHE();
+	}
 
 	status = acpi_os_enter_sleep(sleep_state, pm1a_control, pm1b_control);
 	if (status == AE_CTRL_TERMINATE) {
@@ -179,7 +181,7 @@
 
 acpi_status acpi_hw_legacy_wake_prep(u8 sleep_state)
 {
-	acpi_status status;
+	acpi_status status = AE_OK;
 	struct acpi_bit_register_info *sleep_type_reg_info;
 	struct acpi_bit_register_info *sleep_enable_reg_info;
 	u32 pm1a_control;
@@ -192,10 +194,7 @@
 	 * This is unclear from the ACPI Spec, but it is required
 	 * by some machines.
 	 */
-	status = acpi_get_sleep_type_data(ACPI_STATE_S0,
-					  &acpi_gbl_sleep_type_a,
-					  &acpi_gbl_sleep_type_b);
-	if (ACPI_SUCCESS(status)) {
+	if (acpi_gbl_sleep_type_a_s0 != ACPI_SLEEP_TYPE_INVALID) {
 		sleep_type_reg_info =
 		    acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE);
 		sleep_enable_reg_info =
@@ -216,9 +215,9 @@
 
 			/* Insert the SLP_TYP bits */
 
-			pm1a_control |= (acpi_gbl_sleep_type_a <<
+			pm1a_control |= (acpi_gbl_sleep_type_a_s0 <<
 					 sleep_type_reg_info->bit_position);
-			pm1b_control |= (acpi_gbl_sleep_type_b <<
+			pm1b_control |= (acpi_gbl_sleep_type_b_s0 <<
 					 sleep_type_reg_info->bit_position);
 
 			/* Write the control registers and ignore any errors */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpica/hwvalid.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpica/hwvalid.c
@@ -23,8 +23,8 @@
  *
  * The table is used to implement the Microsoft port access rules that
  * first appeared in Windows XP. Some ports are always illegal, and some
- * ports are only illegal if the BIOS calls _OSI with a win_XP string or
- * later (meaning that the BIOS itelf is post-XP.)
+ * ports are only illegal if the BIOS calls _OSI with nothing newer than
+ * the specific _OSI strings.
  *
  * This provides ACPICA with the desired port protections and
  * Microsoft compatibility.
@@ -145,7 +145,8 @@
 
 			/* Port illegality may depend on the _OSI calls made by the BIOS */
 
-			if (acpi_gbl_osi_data >= port_info->osi_dependency) {
+			if (port_info->osi_dependency == ACPI_ALWAYS_ILLEGAL ||
+			    acpi_gbl_osi_data == port_info->osi_dependency) {
 				ACPI_DEBUG_PRINT((ACPI_DB_VALUES,
 						  "Denied AML access to port 0x%8.8X%8.8X/%X (%s 0x%.4X-0x%.4X)\n",
 						  ACPI_FORMAT_UINT64(address),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpica/hwxfsleep.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpica/hwxfsleep.c
@@ -162,8 +162,6 @@
 		return_ACPI_STATUS(status);
 	}
 
-	ACPI_FLUSH_CPU_CACHE();
-
 	status = acpi_hw_write_port(acpi_gbl_FADT.smi_command,
 				    (u32)acpi_gbl_FADT.s4_bios_request, 8);
 
@@ -214,6 +212,13 @@
 		return_ACPI_STATUS(status);
 	}
 
+	status = acpi_get_sleep_type_data(ACPI_STATE_S0,
+					  &acpi_gbl_sleep_type_a_s0,
+					  &acpi_gbl_sleep_type_b_s0);
+	if (ACPI_FAILURE(status)) {
+		acpi_gbl_sleep_type_a_s0 = ACPI_SLEEP_TYPE_INVALID;
+	}
+
 	/* Execute the _PTS method (Prepare To Sleep) */
 
 	arg_list.count = 1;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpica/nsaccess.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpica/nsaccess.c
@@ -99,13 +99,12 @@
 		 * just create and link the new node(s) here.
 		 */
 		new_node =
-		    ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_namespace_node));
+		    acpi_ns_create_node(*ACPI_CAST_PTR(u32, init_val->name));
 		if (!new_node) {
 			status = AE_NO_MEMORY;
 			goto unlock_and_exit;
 		}
 
-		ACPI_COPY_NAMESEG(new_node->name.ascii, init_val->name);
 		new_node->descriptor_type = ACPI_DESC_TYPE_NAMED;
 		new_node->type = init_val->type;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpica/nsnames.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpica/nsnames.c
@@ -13,9 +13,6 @@
 #define _COMPONENT          ACPI_NAMESPACE
 ACPI_MODULE_NAME("nsnames")
 
-/* Local Prototypes */
-static void acpi_ns_normalize_pathname(char *original_path);
-
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ns_get_external_pathname
@@ -30,7 +27,6 @@
  *              for error and debug statements.
  *
  ******************************************************************************/
-
 char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node)
 {
 	char *name_buffer;
@@ -411,7 +407,7 @@
  *
  ******************************************************************************/
 
-static void acpi_ns_normalize_pathname(char *original_path)
+void acpi_ns_normalize_pathname(char *original_path)
 {
 	char *input_path = original_path;
 	char *new_path_buffer;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpica/nsrepair.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpica/nsrepair.c
@@ -181,8 +181,9 @@
 	 * Try to fix if there was no return object. Warning if failed to fix.
 	 */
 	if (!return_object) {
-		if (expected_btypes && (!(expected_btypes & ACPI_RTYPE_NONE))) {
-			if (package_index != ACPI_NOT_PACKAGE_ELEMENT) {
+		if (expected_btypes) {
+			if (!(expected_btypes & ACPI_RTYPE_NONE) &&
+			    package_index != ACPI_NOT_PACKAGE_ELEMENT) {
 				ACPI_WARN_PREDEFINED((AE_INFO,
 						      info->full_pathname,
 						      ACPI_WARN_ALWAYS,
@@ -196,14 +197,15 @@
 				if (ACPI_SUCCESS(status)) {
 					return (AE_OK);	/* Repair was successful */
 				}
-			} else {
+			}
+
+			if (expected_btypes != ACPI_RTYPE_NONE) {
 				ACPI_WARN_PREDEFINED((AE_INFO,
 						      info->full_pathname,
 						      ACPI_WARN_ALWAYS,
 						      "Missing expected return value"));
+				return (AE_AML_NO_RETURN_VALUE);
 			}
-
-			return (AE_AML_NO_RETURN_VALUE);
 		}
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpica/nswalk.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpica/nswalk.c
@@ -169,6 +169,9 @@
 
 	if (start_node == ACPI_ROOT_OBJECT) {
 		start_node = acpi_gbl_root_node;
+		if (!start_node) {
+			return_ACPI_STATUS(AE_NO_NAMESPACE);
+		}
 	}
 
 	/* Null child means "get first node" */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpica/psargs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpica/psargs.c
@@ -25,6 +25,8 @@
 static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
 						       *parser_state);
 
+static void acpi_ps_free_field_list(union acpi_parse_object *start);
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ps_get_next_package_length
@@ -685,6 +687,39 @@
 
 /*******************************************************************************
  *
+ * FUNCTION:    acpi_ps_free_field_list
+ *
+ * PARAMETERS:  start               - First Op in field list
+ *
+ * RETURN:      None.
+ *
+ * DESCRIPTION: Free all Op objects inside a field list.
+ *
+ ******************************************************************************/
+
+static void acpi_ps_free_field_list(union acpi_parse_object *start)
+{
+	union acpi_parse_object *cur = start;
+	union acpi_parse_object *next;
+	union acpi_parse_object *arg;
+
+	while (cur) {
+		next = cur->common.next;
+
+		/* AML_INT_CONNECTION_OP can have a single argument */
+
+		arg = acpi_ps_get_arg(cur, 0);
+		if (arg) {
+			acpi_ps_free_op(arg);
+		}
+
+		acpi_ps_free_op(cur);
+		cur = next;
+	}
+}
+
+/*******************************************************************************
+ *
  * FUNCTION:    acpi_ps_get_next_arg
  *
  * PARAMETERS:  walk_state          - Current state
@@ -751,6 +786,10 @@
 			while (parser_state->aml < parser_state->pkg_end) {
 				field = acpi_ps_get_next_field(parser_state);
 				if (!field) {
+					if (arg) {
+						acpi_ps_free_field_list(arg);
+					}
+
 					return_ACPI_STATUS(AE_NO_MEMORY);
 				}
 
@@ -820,6 +859,10 @@
 			    acpi_ps_get_next_namepath(walk_state, parser_state,
 						      arg,
 						      ACPI_NOT_METHOD_CALL);
+			if (ACPI_FAILURE(status)) {
+				acpi_ps_free_op(arg);
+				return_ACPI_STATUS(status);
+			}
 		} else {
 			/* Single complex argument, nothing returned */
 
@@ -854,6 +897,10 @@
 			    acpi_ps_get_next_namepath(walk_state, parser_state,
 						      arg,
 						      ACPI_POSSIBLE_METHOD_CALL);
+			if (ACPI_FAILURE(status)) {
+				acpi_ps_free_op(arg);
+				return_ACPI_STATUS(status);
+			}
 
 			if (arg->common.aml_opcode == AML_INT_METHODCALL_OP) {
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpica/psopcode.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpica/psopcode.c
@@ -603,7 +603,7 @@
 
 /* 7E */ ACPI_OP("Timer", ARGP_TIMER_OP, ARGI_TIMER_OP, ACPI_TYPE_ANY,
 			 AML_CLASS_EXECUTE, AML_TYPE_EXEC_0A_0T_1R,
-			 AML_FLAGS_EXEC_0A_0T_1R),
+			 AML_FLAGS_EXEC_0A_0T_1R | AML_NO_OPERAND_RESOLVE),
 
 /* ACPI 5.0 opcodes */
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpica/utcopy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpica/utcopy.c
@@ -916,13 +916,6 @@
 	status = acpi_ut_walk_package_tree(source_obj, dest_obj,
 					   acpi_ut_copy_ielement_to_ielement,
 					   walk_state);
-	if (ACPI_FAILURE(status)) {
-
-		/* On failure, delete the destination package object */
-
-		acpi_ut_remove_reference(dest_obj);
-	}
-
 	return_ACPI_STATUS(status);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/acpica/utdelete.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/acpica/utdelete.c
@@ -285,6 +285,14 @@
 		}
 		break;
 
+	case ACPI_TYPE_LOCAL_ADDRESS_HANDLER:
+
+		ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+				  "***** Address handler %p\n", object));
+
+		acpi_os_delete_mutex(object->address_space.context_mutex);
+		break;
+
 	default:
 
 		break;
@@ -414,6 +422,7 @@
 			ACPI_WARNING((AE_INFO,
 				      "Obj %p, Reference Count is already zero, cannot decrement\n",
 				      object));
+			return;
 		}
 
 		ACPI_DEBUG_PRINT_RAW((ACPI_DB_ALLOCATIONS,
@@ -452,13 +461,13 @@
  *
  * FUNCTION:    acpi_ut_update_object_reference
  *
- * PARAMETERS:  object              - Increment ref count for this object
- *                                    and all sub-objects
+ * PARAMETERS:  object              - Increment or decrement the ref count for
+ *                                    this object and all sub-objects
  *              action              - Either REF_INCREMENT or REF_DECREMENT
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Increment the object reference count
+ * DESCRIPTION: Increment or decrement the object reference count
  *
  * Object references are incremented when:
  * 1) An object is attached to a Node (namespace object)
@@ -492,7 +501,7 @@
 		}
 
 		/*
-		 * All sub-objects must have their reference count incremented
+		 * All sub-objects must have their reference count updated
 		 * also. Different object types have different subobjects.
 		 */
 		switch (object->common.type) {
@@ -559,6 +568,7 @@
 					break;
 				}
 			}
+
 			next_object = NULL;
 			break;
 
@@ -567,11 +577,6 @@
 			next_object = object->buffer_field.buffer_obj;
 			break;
 
-		case ACPI_TYPE_LOCAL_REGION_FIELD:
-
-			next_object = object->field.region_obj;
-			break;
-
 		case ACPI_TYPE_LOCAL_BANK_FIELD:
 
 			next_object = object->bank_field.bank_obj;
@@ -612,6 +617,7 @@
 			}
 			break;
 
+		case ACPI_TYPE_LOCAL_REGION_FIELD:
 		case ACPI_TYPE_REGION:
 		default:
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/apei/bert.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/apei/bert.c
@@ -30,14 +30,25 @@
 #undef pr_fmt
 #define pr_fmt(fmt) "BERT: " fmt
 
+#define ACPI_BERT_PRINT_MAX_RECORDS 5
+#define ACPI_BERT_PRINT_MAX_LEN 1024
+
 static int bert_disable;
 
+/*
+ * Print "all" the error records in the BERT table, but avoid huge spam to
+ * the console if the BIOS included oversize records, or too many records.
+ * Skipping some records here does not lose anything because the full
+ * data is available to user tools in:
+ *	/sys/firmware/acpi/tables/data/BERT
+ */
 static void __init bert_print_all(struct acpi_bert_region *region,
 				  unsigned int region_len)
 {
 	struct acpi_hest_generic_status *estatus =
 		(struct acpi_hest_generic_status *)region;
 	int remain = region_len;
+	int printed = 0, skipped = 0;
 	u32 estatus_len;
 
 	while (remain >= sizeof(struct acpi_bert_region)) {
@@ -45,21 +56,26 @@
 		if (remain < estatus_len) {
 			pr_err(FW_BUG "Truncated status block (length: %u).\n",
 			       estatus_len);
-			return;
+			break;
 		}
 
 		/* No more error records. */
 		if (!estatus->block_status)
-			return;
+			break;
 
 		if (cper_estatus_check(estatus)) {
 			pr_err(FW_BUG "Invalid error record.\n");
-			return;
+			break;
 		}
 
-		pr_info_once("Error records from previous boot:\n");
-
-		cper_estatus_print(KERN_INFO HW_ERR, estatus);
+		if (estatus_len < ACPI_BERT_PRINT_MAX_LEN &&
+		    printed < ACPI_BERT_PRINT_MAX_RECORDS) {
+			pr_info_once("Error records from previous boot:\n");
+			cper_estatus_print(KERN_INFO HW_ERR, estatus);
+			printed++;
+		} else {
+			skipped++;
+		}
 
 		/*
 		 * Because the boot error source is "one-time polled" type,
@@ -71,13 +87,16 @@
 		estatus = (void *)estatus + estatus_len;
 		remain -= estatus_len;
 	}
+
+	if (skipped)
+		pr_info(HW_ERR "Skipped %d error records\n", skipped);
 }
 
 static int __init setup_bert_disable(char *str)
 {
 	bert_disable = 1;
 
-	return 0;
+	return 1;
 }
 __setup("bert_disable", setup_bert_disable);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/apei/erst.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/apei/erst.c
@@ -891,7 +891,7 @@
 static int __init setup_erst_disable(char *str)
 {
 	erst_disable = 1;
-	return 0;
+	return 1;
 }
 
 __setup("erst_disable", setup_erst_disable);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/apei/ghes.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/apei/ghes.c
@@ -128,8 +128,6 @@
 static struct ghes_estatus_cache *ghes_estatus_caches[GHES_ESTATUS_CACHES_SIZE];
 static atomic_t ghes_estatus_cache_alloced;
 
-static int ghes_panic_timeout __read_mostly = 30;
-
 static void __iomem *ghes_map(u64 pfn, enum fixed_addresses fixmap_idx)
 {
 	phys_addr_t paddr;
@@ -171,7 +169,7 @@
 	 * New allocation must be visible in all pgd before it can be found by
 	 * an NMI allocating from the pool.
 	 */
-	vmalloc_sync_all();
+	vmalloc_sync_mappings();
 
 	rc = gen_pool_add(ghes_estatus_pool, addr, PAGE_ALIGN(len), -1);
 	if (rc)
@@ -707,14 +705,16 @@
 			 struct acpi_hest_generic_status *estatus,
 			 u64 buf_paddr, enum fixed_addresses fixmap_idx)
 {
+	const char *msg = GHES_PFX "Fatal hardware error";
+
 	__ghes_print_estatus(KERN_EMERG, ghes->generic, estatus);
 
 	ghes_clear_estatus(ghes, estatus, buf_paddr, fixmap_idx);
 
-	/* reboot to log the error! */
 	if (!panic_timeout)
-		panic_timeout = ghes_panic_timeout;
-	panic("Fatal hardware error!");
+		pr_emerg("%s but panic disabled\n", msg);
+
+	panic(msg);
 }
 
 static int ghes_proc(struct ghes *ghes)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/apei/hest.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/apei/hest.c
@@ -219,7 +219,7 @@
 static int __init setup_hest_disable(char *str)
 {
 	hest_disable = HEST_DISABLED;
-	return 0;
+	return 1;
 }
 
 __setup("hest_disable", setup_hest_disable);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/arm64/gtdt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/arm64/gtdt.c
@@ -36,7 +36,7 @@
 
 static struct acpi_gtdt_descriptor acpi_gtdt_desc __initdata;
 
-static inline void *next_platform_timer(void *platform_timer)
+static inline __init void *next_platform_timer(void *platform_timer)
 {
 	struct acpi_gtdt_header *gh = platform_timer;
 
@@ -283,7 +283,7 @@
 		if (frame->virt_irq > 0)
 			acpi_unregister_gsi(gtdt_frame->virtual_timer_interrupt);
 		frame->virt_irq = 0;
-	} while (i-- >= 0 && gtdt_frame--);
+	} while (i-- > 0 && gtdt_frame--);
 
 	return -EINVAL;
 }
@@ -329,7 +329,7 @@
 					int index)
 {
 	struct platform_device *pdev;
-	int irq = map_gt_gsi(wd->timer_interrupt, wd->timer_flags);
+	int irq;
 
 	/*
 	 * According to SBSA specification the size of refresh and control
@@ -338,7 +338,7 @@
 	struct resource res[] = {
 		DEFINE_RES_MEM(wd->control_frame_address, SZ_4K),
 		DEFINE_RES_MEM(wd->refresh_frame_address, SZ_4K),
-		DEFINE_RES_IRQ(irq),
+		{},
 	};
 	int nr_res = ARRAY_SIZE(res);
 
@@ -348,10 +348,11 @@
 
 	if (!(wd->refresh_frame_address && wd->control_frame_address)) {
 		pr_err(FW_BUG "failed to get the Watchdog base address.\n");
-		acpi_unregister_gsi(wd->timer_interrupt);
 		return -EINVAL;
 	}
 
+	irq = map_gt_gsi(wd->timer_interrupt, wd->timer_flags);
+	res[2] = (struct resource)DEFINE_RES_IRQ(irq);
 	if (irq <= 0) {
 		pr_warn("failed to map the Watchdog interrupt.\n");
 		nr_res--;
@@ -364,7 +365,8 @@
 	 */
 	pdev = platform_device_register_simple("sbsa-gwdt", index, res, nr_res);
 	if (IS_ERR(pdev)) {
-		acpi_unregister_gsi(wd->timer_interrupt);
+		if (irq > 0)
+			acpi_unregister_gsi(wd->timer_interrupt);
 		return PTR_ERR(pdev);
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/arm64/iort.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/arm64/iort.c
@@ -361,6 +361,7 @@
 static int iort_get_id_mapping_index(struct acpi_iort_node *node)
 {
 	struct acpi_iort_smmu_v3 *smmu;
+	struct acpi_iort_pmcg *pmcg;
 
 	switch (node->type) {
 	case ACPI_IORT_NODE_SMMU_V3:
@@ -388,6 +389,10 @@
 
 		return smmu->id_mapping_index;
 	case ACPI_IORT_NODE_PMCG:
+		pmcg = (struct acpi_iort_pmcg *)node->node_data;
+		if (pmcg->overflow_gsiv || node->mapping_count == 0)
+			return -EINVAL;
+
 		return 0;
 	default:
 		return -EINVAL;
@@ -498,7 +503,6 @@
 		node = iort_get_iort_node(dev->fwnode);
 		if (node)
 			return node;
-
 		/*
 		 * if not, then it should be a platform device defined in
 		 * DSDT/SSDT (with Named Component node in IORT)
@@ -517,22 +521,22 @@
 }
 
 /**
- * iort_msi_map_rid() - Map a MSI requester ID for a device
+ * iort_msi_map_id() - Map a MSI input ID for a device
  * @dev: The device for which the mapping is to be done.
- * @req_id: The device requester ID.
+ * @input_id: The device input ID.
  *
- * Returns: mapped MSI RID on success, input requester ID otherwise
+ * Returns: mapped MSI ID on success, input ID otherwise
  */
-u32 iort_msi_map_rid(struct device *dev, u32 req_id)
+u32 iort_msi_map_id(struct device *dev, u32 input_id)
 {
 	struct acpi_iort_node *node;
 	u32 dev_id;
 
 	node = iort_find_dev_node(dev);
 	if (!node)
-		return req_id;
+		return input_id;
 
-	iort_node_map_id(node, req_id, &dev_id, IORT_MSI_TYPE);
+	iort_node_map_id(node, input_id, &dev_id, IORT_MSI_TYPE);
 	return dev_id;
 }
 
@@ -589,13 +593,13 @@
 /**
  * iort_dev_find_its_id() - Find the ITS identifier for a device
  * @dev: The device.
- * @req_id: Device's requester ID
+ * @id: Device's ID
  * @idx: Index of the ITS identifier list.
  * @its_id: ITS identifier.
  *
  * Returns: 0 on success, appropriate error value otherwise
  */
-static int iort_dev_find_its_id(struct device *dev, u32 req_id,
+static int iort_dev_find_its_id(struct device *dev, u32 id,
 				unsigned int idx, int *its_id)
 {
 	struct acpi_iort_its_group *its;
@@ -605,7 +609,7 @@
 	if (!node)
 		return -ENXIO;
 
-	node = iort_node_map_id(node, req_id, NULL, IORT_MSI_TYPE);
+	node = iort_node_map_id(node, id, NULL, IORT_MSI_TYPE);
 	if (!node)
 		return -ENXIO;
 
@@ -628,19 +632,20 @@
  *
  * Returns: the MSI domain for this device, NULL otherwise
  */
-struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id)
+struct irq_domain *iort_get_device_domain(struct device *dev, u32 id,
+					  enum irq_domain_bus_token bus_token)
 {
 	struct fwnode_handle *handle;
 	int its_id;
 
-	if (iort_dev_find_its_id(dev, req_id, 0, &its_id))
+	if (iort_dev_find_its_id(dev, id, 0, &its_id))
 		return NULL;
 
 	handle = iort_find_domain_token(its_id);
 	if (!handle)
 		return NULL;
 
-	return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI);
+	return irq_find_matching_fwnode(handle, bus_token);
 }
 
 static void iort_set_device_domain(struct device *dev,
@@ -1368,9 +1373,17 @@
 	res[0].start = pmcg->page0_base_address;
 	res[0].end = pmcg->page0_base_address + SZ_4K - 1;
 	res[0].flags = IORESOURCE_MEM;
-	res[1].start = pmcg->page1_base_address;
-	res[1].end = pmcg->page1_base_address + SZ_4K - 1;
-	res[1].flags = IORESOURCE_MEM;
+	/*
+	 * The initial version in DEN0049C lacked a way to describe register
+	 * page 1, which makes it broken for most PMCG implementations; in
+	 * that case, just let the driver fail gracefully if it expects to
+	 * find a second memory resource.
+	 */
+	if (node->revision > 0) {
+		res[1].start = pmcg->page1_base_address;
+		res[1].end = pmcg->page1_base_address + SZ_4K - 1;
+		res[1].flags = IORESOURCE_MEM;
+	}
 
 	if (pmcg->overflow_gsiv)
 		acpi_iort_register_irq(pmcg->overflow_gsiv, "overflow",
@@ -1380,7 +1393,10 @@
 static struct acpi_platform_list pmcg_plat_info[] __initdata = {
 	/* HiSilicon Hip08 Platform */
 	{"HISI  ", "HIP08   ", 0, ACPI_SIG_IORT, greater_than_or_equal,
-	 "Erratum #162001800", IORT_SMMU_V3_PMCG_HISI_HIP08},
+	 "Erratum #162001800, Erratum #162001900", IORT_SMMU_V3_PMCG_HISI_HIP08},
+	/* HiSilicon Hip09 Platform */
+	{"HISI  ", "HIP09   ", 0, ACPI_SIG_IORT, greater_than_or_equal,
+	 "Erratum #162001900", IORT_SMMU_V3_PMCG_HISI_HIP09},
 	{ }
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/battery.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/battery.c
@@ -38,6 +38,8 @@
 #define PREFIX "ACPI: "
 
 #define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF
+#define ACPI_BATTERY_CAPACITY_VALID(capacity) \
+	((capacity) != 0 && (capacity) != ACPI_BATTERY_VALUE_UNKNOWN)
 
 #define ACPI_BATTERY_DEVICE_NAME	"Battery"
 
@@ -63,6 +65,7 @@
 static int battery_notification_delay_ms;
 static int battery_ac_is_broken;
 static int battery_check_pmic = 1;
+static int battery_quirk_notcharging;
 static unsigned int cache_time = 1000;
 module_param(cache_time, uint, 0644);
 MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
@@ -74,6 +77,10 @@
 
 static const struct acpi_device_id battery_device_ids[] = {
 	{"PNP0C0A", 0},
+
+	/* Microsoft Surface Go 3 */
+	{"MSHW0146", 0},
+
 	{"", 0},
 };
 
@@ -183,7 +190,7 @@
 		return 1;
 
 	/* fallback to using design values for broken batteries */
-	if (battery->design_capacity == battery->capacity_now)
+	if (battery->design_capacity <= battery->capacity_now)
 		return 1;
 
 	/* we don't do any sort of metric based on percentages */
@@ -192,7 +199,8 @@
 
 static bool acpi_battery_is_degraded(struct acpi_battery *battery)
 {
-	return battery->full_charge_capacity && battery->design_capacity &&
+	return ACPI_BATTERY_CAPACITY_VALID(battery->full_charge_capacity) &&
+		ACPI_BATTERY_CAPACITY_VALID(battery->design_capacity) &&
 		battery->full_charge_capacity < battery->design_capacity;
 }
 
@@ -214,7 +222,7 @@
 				     enum power_supply_property psp,
 				     union power_supply_propval *val)
 {
-	int ret = 0;
+	int full_capacity = ACPI_BATTERY_VALUE_UNKNOWN, ret = 0;
 	struct acpi_battery *battery = to_acpi_battery(psy);
 
 	if (acpi_battery_present(battery)) {
@@ -230,6 +238,8 @@
 			val->intval = POWER_SUPPLY_STATUS_CHARGING;
 		else if (acpi_battery_is_charged(battery))
 			val->intval = POWER_SUPPLY_STATUS_FULL;
+		else if (battery_quirk_notcharging)
+			val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
 		else
 			val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
 		break;
@@ -263,14 +273,14 @@
 		break;
 	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
 	case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
-		if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
+		if (!ACPI_BATTERY_CAPACITY_VALID(battery->design_capacity))
 			ret = -ENODEV;
 		else
 			val->intval = battery->design_capacity * 1000;
 		break;
 	case POWER_SUPPLY_PROP_CHARGE_FULL:
 	case POWER_SUPPLY_PROP_ENERGY_FULL:
-		if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
+		if (!ACPI_BATTERY_CAPACITY_VALID(battery->full_charge_capacity))
 			ret = -ENODEV;
 		else
 			val->intval = battery->full_charge_capacity * 1000;
@@ -283,11 +293,17 @@
 			val->intval = battery->capacity_now * 1000;
 		break;
 	case POWER_SUPPLY_PROP_CAPACITY:
-		if (battery->capacity_now && battery->full_charge_capacity)
-			val->intval = battery->capacity_now * 100/
-					battery->full_charge_capacity;
+		if (ACPI_BATTERY_CAPACITY_VALID(battery->full_charge_capacity))
+			full_capacity = battery->full_charge_capacity;
+		else if (ACPI_BATTERY_CAPACITY_VALID(battery->design_capacity))
+			full_capacity = battery->design_capacity;
+
+		if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN ||
+		    full_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
+			ret = -ENODEV;
 		else
-			val->intval = 0;
+			val->intval = battery->capacity_now * 100/
+					full_capacity;
 		break;
 	case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
 		if (battery->state & ACPI_BATTERY_STATE_CRITICAL)
@@ -333,6 +349,20 @@
 	POWER_SUPPLY_PROP_SERIAL_NUMBER,
 };
 
+static enum power_supply_property charge_battery_full_cap_broken_props[] = {
+	POWER_SUPPLY_PROP_STATUS,
+	POWER_SUPPLY_PROP_PRESENT,
+	POWER_SUPPLY_PROP_TECHNOLOGY,
+	POWER_SUPPLY_PROP_CYCLE_COUNT,
+	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+	POWER_SUPPLY_PROP_VOLTAGE_NOW,
+	POWER_SUPPLY_PROP_CURRENT_NOW,
+	POWER_SUPPLY_PROP_CHARGE_NOW,
+	POWER_SUPPLY_PROP_MODEL_NAME,
+	POWER_SUPPLY_PROP_MANUFACTURER,
+	POWER_SUPPLY_PROP_SERIAL_NUMBER,
+};
+
 static enum power_supply_property energy_battery_props[] = {
 	POWER_SUPPLY_PROP_STATUS,
 	POWER_SUPPLY_PROP_PRESENT,
@@ -435,7 +465,7 @@
 			u8 *ptr = (u8 *)battery + offsets[i].offset;
 			if (element->type == ACPI_TYPE_STRING ||
 			    element->type == ACPI_TYPE_BUFFER)
-				strncpy(ptr, element->string.pointer, 32);
+				strscpy(ptr, element->string.pointer, 32);
 			else if (element->type == ACPI_TYPE_INTEGER) {
 				strncpy(ptr, (u8 *)&element->integer.value,
 					sizeof(u64));
@@ -651,12 +681,18 @@
 	return count;
 }
 
-static const struct device_attribute alarm_attr = {
+static struct device_attribute alarm_attr = {
 	.attr = {.name = "alarm", .mode = 0644},
 	.show = acpi_battery_alarm_show,
 	.store = acpi_battery_alarm_store,
 };
 
+static struct attribute *acpi_battery_attrs[] = {
+	&alarm_attr.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(acpi_battery);
+
 /*
  * The Battery Hooking API
  *
@@ -670,27 +706,34 @@
 static LIST_HEAD(battery_hook_list);
 static DEFINE_MUTEX(hook_mutex);
 
-static void __battery_hook_unregister(struct acpi_battery_hook *hook, int lock)
+static void battery_hook_unregister_unlocked(struct acpi_battery_hook *hook)
 {
 	struct acpi_battery *battery;
+
 	/*
 	 * In order to remove a hook, we first need to
 	 * de-register all the batteries that are registered.
 	 */
-	if (lock)
-		mutex_lock(&hook_mutex);
 	list_for_each_entry(battery, &acpi_battery_list, list) {
 		hook->remove_battery(battery->bat);
 	}
-	list_del(&hook->list);
-	if (lock)
-		mutex_unlock(&hook_mutex);
+	list_del_init(&hook->list);
+
 	pr_info("extension unregistered: %s\n", hook->name);
 }
 
 void battery_hook_unregister(struct acpi_battery_hook *hook)
 {
-	__battery_hook_unregister(hook, 1);
+	mutex_lock(&hook_mutex);
+	/*
+	 * Ignore already unregistered battery hooks. This might happen
+	 * if a battery hook was previously unloaded due to an error when
+	 * adding a new battery.
+	 */
+	if (!list_empty(&hook->list))
+		battery_hook_unregister_unlocked(hook);
+
+	mutex_unlock(&hook_mutex);
 }
 EXPORT_SYMBOL_GPL(battery_hook_unregister);
 
@@ -699,7 +742,6 @@
 	struct acpi_battery *battery;
 
 	mutex_lock(&hook_mutex);
-	INIT_LIST_HEAD(&hook->list);
 	list_add(&hook->list, &battery_hook_list);
 	/*
 	 * Now that the driver is registered, we need
@@ -716,7 +758,7 @@
 			 * hooks.
 			 */
 			pr_err("extension failed to load: %s", hook->name);
-			__battery_hook_unregister(hook, 0);
+			battery_hook_unregister_unlocked(hook);
 			goto end;
 		}
 	}
@@ -753,7 +795,7 @@
 			 */
 			pr_err("error in extension, unloading: %s",
 					hook_node->name);
-			__battery_hook_unregister(hook_node, 0);
+			battery_hook_unregister_unlocked(hook_node);
 		}
 	}
 	mutex_unlock(&hook_mutex);
@@ -786,28 +828,45 @@
 	 * need to remove the hooks.
 	 */
 	list_for_each_entry_safe(hook, ptr, &battery_hook_list, list) {
-		__battery_hook_unregister(hook, 1);
+		battery_hook_unregister(hook);
 	}
 	mutex_destroy(&hook_mutex);
 }
 
 static int sysfs_add_battery(struct acpi_battery *battery)
 {
-	struct power_supply_config psy_cfg = { .drv_data = battery, };
+	struct power_supply_config psy_cfg = {
+		.drv_data = battery,
+		.attr_grp = acpi_battery_groups,
+	};
+	bool full_cap_broken = false;
+
+	if (!ACPI_BATTERY_CAPACITY_VALID(battery->full_charge_capacity) &&
+	    !ACPI_BATTERY_CAPACITY_VALID(battery->design_capacity))
+		full_cap_broken = true;
 
 	if (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) {
-		battery->bat_desc.properties = charge_battery_props;
-		battery->bat_desc.num_properties =
-			ARRAY_SIZE(charge_battery_props);
-	} else if (battery->full_charge_capacity == 0) {
-		battery->bat_desc.properties =
-			energy_battery_full_cap_broken_props;
-		battery->bat_desc.num_properties =
-			ARRAY_SIZE(energy_battery_full_cap_broken_props);
+		if (full_cap_broken) {
+			battery->bat_desc.properties =
+			    charge_battery_full_cap_broken_props;
+			battery->bat_desc.num_properties =
+			    ARRAY_SIZE(charge_battery_full_cap_broken_props);
+		} else {
+			battery->bat_desc.properties = charge_battery_props;
+			battery->bat_desc.num_properties =
+			    ARRAY_SIZE(charge_battery_props);
+		}
 	} else {
-		battery->bat_desc.properties = energy_battery_props;
-		battery->bat_desc.num_properties =
-			ARRAY_SIZE(energy_battery_props);
+		if (full_cap_broken) {
+			battery->bat_desc.properties =
+			    energy_battery_full_cap_broken_props;
+			battery->bat_desc.num_properties =
+			    ARRAY_SIZE(energy_battery_full_cap_broken_props);
+		} else {
+			battery->bat_desc.properties = energy_battery_props;
+			battery->bat_desc.num_properties =
+			    ARRAY_SIZE(energy_battery_props);
+		}
 	}
 
 	battery->bat_desc.name = acpi_device_bid(battery->device);
@@ -824,7 +883,7 @@
 		return result;
 	}
 	battery_hook_add_battery(battery);
-	return device_create_file(&battery->bat->dev, &alarm_attr);
+	return 0;
 }
 
 static void sysfs_remove_battery(struct acpi_battery *battery)
@@ -835,7 +894,6 @@
 		return;
 	}
 	battery_hook_remove_battery(battery);
-	device_remove_file(&battery->bat->dev, &alarm_attr);
 	power_supply_unregister(battery->bat);
 	battery->bat = NULL;
 	mutex_unlock(&battery->sysfs_lock);
@@ -1300,6 +1358,12 @@
 	return 0;
 }
 
+static int __init battery_quirk_not_charging(const struct dmi_system_id *d)
+{
+	battery_quirk_notcharging = 1;
+	return 0;
+}
+
 static const struct dmi_system_id bat_dmi_table[] __initconst = {
 	{
 		/* NEC LZ750/LS */
@@ -1344,6 +1408,27 @@
 		  DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"),
 		},
 	},
+	{
+		/*
+		 * On Lenovo ThinkPads the BIOS specification defines
+		 * a state when the bits for charging and discharging
+		 * are both set to 0. That state is "Not Charging".
+		 */
+		.callback = battery_quirk_not_charging,
+		.ident = "Lenovo ThinkPad",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad"),
+		},
+	},
+	{
+		/* Microsoft Surface Go 3 */
+		.callback = battery_notification_delay_quirk,
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Surface Go 3"),
+		},
+	},
 	{},
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/bgrt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/bgrt.c
@@ -15,40 +15,19 @@
 static void *bgrt_image;
 static struct kobject *bgrt_kobj;
 
-static ssize_t show_version(struct device *dev,
-			    struct device_attribute *attr, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab.version);
-}
-static DEVICE_ATTR(version, S_IRUGO, show_version, NULL);
-
-static ssize_t show_status(struct device *dev,
-			   struct device_attribute *attr, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab.status);
-}
-static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
-
-static ssize_t show_type(struct device *dev,
-			 struct device_attribute *attr, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab.image_type);
-}
-static DEVICE_ATTR(type, S_IRUGO, show_type, NULL);
-
-static ssize_t show_xoffset(struct device *dev,
-			    struct device_attribute *attr, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab.image_offset_x);
-}
-static DEVICE_ATTR(xoffset, S_IRUGO, show_xoffset, NULL);
-
-static ssize_t show_yoffset(struct device *dev,
-			    struct device_attribute *attr, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab.image_offset_y);
-}
-static DEVICE_ATTR(yoffset, S_IRUGO, show_yoffset, NULL);
+#define BGRT_SHOW(_name, _member) \
+	static ssize_t _name##_show(struct kobject *kobj,			\
+				    struct kobj_attribute *attr, char *buf)	\
+	{									\
+		return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab._member);	\
+	}									\
+	struct kobj_attribute bgrt_attr_##_name = __ATTR_RO(_name)
+
+BGRT_SHOW(version, version);
+BGRT_SHOW(status, status);
+BGRT_SHOW(type, image_type);
+BGRT_SHOW(xoffset, image_offset_x);
+BGRT_SHOW(yoffset, image_offset_y);
 
 static ssize_t image_read(struct file *file, struct kobject *kobj,
 	       struct bin_attribute *attr, char *buf, loff_t off, size_t count)
@@ -60,11 +39,11 @@
 static BIN_ATTR_RO(image, 0);	/* size gets filled in later */
 
 static struct attribute *bgrt_attributes[] = {
-	&dev_attr_version.attr,
-	&dev_attr_status.attr,
-	&dev_attr_type.attr,
-	&dev_attr_xoffset.attr,
-	&dev_attr_yoffset.attr,
+	&bgrt_attr_version.attr,
+	&bgrt_attr_status.attr,
+	&bgrt_attr_type.attr,
+	&bgrt_attr_xoffset.attr,
+	&bgrt_attr_yoffset.attr,
 	NULL,
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/bus.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/bus.c
@@ -153,7 +153,7 @@
 {
 	acpi_status status;
 
-	if (!*data)
+	if (!data)
 		return -EINVAL;
 
 	status = acpi_get_data(handle, acpi_bus_private_data_handler, data);
@@ -1240,6 +1240,7 @@
 
 	result = acpi_bus_init();
 	if (result) {
+		kobject_put(acpi_kobj);
 		disable_acpi();
 		return result;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/button.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/button.c
@@ -78,6 +78,50 @@
 			DMI_MATCH(DMI_BIOS_VERSION, "BYT70A.YNCHENG.WIN.007"),
 		},
 	},
+	{
+		/*
+		 * Medion Akoya E2215T, notification of the LID device only
+		 * happens on close, not on open and _LID always returns closed.
+		 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "E2215T"),
+		},
+		.driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_OPEN,
+	},
+	{
+		/*
+		 * Medion Akoya E2228T, notification of the LID device only
+		 * happens on close, not on open and _LID always returns closed.
+		 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "E2228T"),
+		},
+		.driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_OPEN,
+	},
+	{
+		/*
+		 * Razer Blade Stealth 13 late 2019, notification of the LID device
+		 * only happens on close, not on open and _LID always returns closed.
+		 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Razer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Razer Blade Stealth 13 Late 2019"),
+		},
+		.driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_OPEN,
+	},
+	{
+		/*
+		 * Samsung galaxybook2 ,initial _LID device notification returns
+		 * lid closed.
+		 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "750XED"),
+		},
+		.driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_OPEN,
+	},
 	{}
 };
 
@@ -114,6 +158,7 @@
 	int last_state;
 	ktime_t last_time;
 	bool suspended;
+	bool lid_state_initialized;
 };
 
 static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
@@ -369,6 +414,8 @@
 
 static void acpi_lid_initialize_state(struct acpi_device *device)
 {
+	struct acpi_button *button = acpi_driver_data(device);
+
 	switch (lid_init_state) {
 	case ACPI_BUTTON_LID_INIT_OPEN:
 		(void)acpi_lid_notify_state(device, 1);
@@ -380,13 +427,14 @@
 	default:
 		break;
 	}
+
+	button->lid_state_initialized = true;
 }
 
 static void acpi_button_notify(struct acpi_device *device, u32 event)
 {
 	struct acpi_button *button = acpi_driver_data(device);
 	struct input_dev *input;
-	int users;
 
 	switch (event) {
 	case ACPI_FIXED_HARDWARE_EVENT:
@@ -395,10 +443,7 @@
 	case ACPI_BUTTON_NOTIFY_STATUS:
 		input = button->input;
 		if (button->type == ACPI_BUTTON_TYPE_LID) {
-			mutex_lock(&button->input->mutex);
-			users = button->input->users;
-			mutex_unlock(&button->input->mutex);
-			if (users)
+			if (button->lid_state_initialized)
 				acpi_lid_update_state(device, true);
 		} else {
 			int keycode;
@@ -443,7 +488,7 @@
 	struct acpi_button *button = acpi_driver_data(device);
 
 	button->suspended = false;
-	if (button->type == ACPI_BUTTON_TYPE_LID && button->input->users) {
+	if (button->type == ACPI_BUTTON_TYPE_LID) {
 		button->last_state = !!acpi_lid_evaluate_state(device);
 		button->last_time = ktime_get();
 		acpi_lid_initialize_state(device);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/cppc_acpi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/cppc_acpi.c
@@ -118,23 +118,15 @@
  */
 #define NUM_RETRIES 500ULL
 
-struct cppc_attr {
-	struct attribute attr;
-	ssize_t (*show)(struct kobject *kobj,
-			struct attribute *attr, char *buf);
-	ssize_t (*store)(struct kobject *kobj,
-			struct attribute *attr, const char *c, ssize_t count);
-};
-
 #define define_one_cppc_ro(_name)		\
-static struct cppc_attr _name =			\
+static struct kobj_attribute _name =		\
 __ATTR(_name, 0444, show_##_name, NULL)
 
 #define to_cpc_desc(a) container_of(a, struct cpc_desc, kobj)
 
 #define show_cppc_data(access_fn, struct_name, member_name)		\
 	static ssize_t show_##member_name(struct kobject *kobj,		\
-					struct attribute *attr,	char *buf) \
+				struct kobj_attribute *attr, char *buf)	\
 	{								\
 		struct cpc_desc *cpc_ptr = to_cpc_desc(kobj);		\
 		struct struct_name st_name = {0};			\
@@ -160,7 +152,7 @@
 show_cppc_data(cppc_get_perf_ctrs, cppc_perf_fb_ctrs, wraparound_time);
 
 static ssize_t show_feedback_ctrs(struct kobject *kobj,
-		struct attribute *attr, char *buf)
+		struct kobj_attribute *attr, char *buf)
 {
 	struct cpc_desc *cpc_ptr = to_cpc_desc(kobj);
 	struct cppc_perf_fb_ctrs fb_ctrs = {0};
@@ -634,33 +626,6 @@
 	return 0;
 }
 
-/* Check if CPPC revision + num_ent combination is supported */
-static bool is_cppc_supported(int revision, int num_ent)
-{
-	int expected_num_ent;
-
-	switch (revision) {
-	case CPPC_V2_REV:
-		expected_num_ent = CPPC_V2_NUM_ENT;
-		break;
-	case CPPC_V3_REV:
-		expected_num_ent = CPPC_V3_NUM_ENT;
-		break;
-	default:
-		pr_debug("Firmware exports unsupported CPPC revision: %d\n",
-			revision);
-		return false;
-	}
-
-	if (expected_num_ent != num_ent) {
-		pr_debug("Firmware exports %d entries. Expected: %d for CPPC rev:%d\n",
-			num_ent, expected_num_ent, revision);
-		return false;
-	}
-
-	return true;
-}
-
 /*
  * An example CPC table looks like the following.
  *
@@ -746,12 +711,16 @@
 	cpc_obj = &out_obj->package.elements[0];
 	if (cpc_obj->type == ACPI_TYPE_INTEGER)	{
 		num_ent = cpc_obj->integer.value;
+		if (num_ent <= 1) {
+			pr_debug("Unexpected _CPC NumEntries value (%d) for CPU:%d\n",
+				 num_ent, pr->id);
+			goto out_free;
+		}
 	} else {
 		pr_debug("Unexpected entry type(%d) for NumEntries\n",
 				cpc_obj->type);
 		goto out_free;
 	}
-	cpc_ptr->num_entries = num_ent;
 
 	/* Second entry should be revision. */
 	cpc_obj = &out_obj->package.elements[1];
@@ -762,10 +731,32 @@
 				cpc_obj->type);
 		goto out_free;
 	}
-	cpc_ptr->version = cpc_rev;
 
-	if (!is_cppc_supported(cpc_rev, num_ent))
+	if (cpc_rev < CPPC_V2_REV) {
+		pr_debug("Unsupported _CPC Revision (%d) for CPU:%d\n", cpc_rev,
+			 pr->id);
+		goto out_free;
+	}
+
+	/*
+	 * Disregard _CPC if the number of entries in the return pachage is not
+	 * as expected, but support future revisions being proper supersets of
+	 * the v3 and only causing more entries to be returned by _CPC.
+	 */
+	if ((cpc_rev == CPPC_V2_REV && num_ent != CPPC_V2_NUM_ENT) ||
+	    (cpc_rev == CPPC_V3_REV && num_ent != CPPC_V3_NUM_ENT) ||
+	    (cpc_rev > CPPC_V3_REV && num_ent <= CPPC_V3_NUM_ENT)) {
+		pr_debug("Unexpected number of _CPC return package entries (%d) for CPU:%d\n",
+			 num_ent, pr->id);
 		goto out_free;
+	}
+	if (cpc_rev > CPPC_V3_REV) {
+		num_ent = CPPC_V3_NUM_ENT;
+		cpc_rev = CPPC_V3_REV;
+	}
+
+	cpc_ptr->num_entries = num_ent;
+	cpc_ptr->version = cpc_rev;
 
 	/* Iterate through remaining entries in _CPC */
 	for (i = 2; i < num_ent; i++) {
@@ -865,6 +856,7 @@
 			"acpi_cppc");
 	if (ret) {
 		per_cpu(cpc_desc_ptr, pr->id) = NULL;
+		kobject_put(&cpc_ptr->kobj);
 		goto out_free;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/custom_method.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/custom_method.c
@@ -44,6 +44,8 @@
 				   sizeof(struct acpi_table_header)))
 			return -EFAULT;
 		uncopied_bytes = max_size = table.length;
+		/* make sure the buf is not allocated */
+		kfree(buf);
 		buf = kzalloc(max_size, GFP_KERNEL);
 		if (!buf)
 			return -ENOMEM;
@@ -57,6 +59,7 @@
 	    (*ppos + count < count) ||
 	    (count > uncopied_bytes)) {
 		kfree(buf);
+		buf = NULL;
 		return -EINVAL;
 	}
 
@@ -78,7 +81,6 @@
 		add_taint(TAINT_OVERRIDDEN_ACPI_TABLE, LOCKDEP_NOW_UNRELIABLE);
 	}
 
-	kfree(buf);
 	return count;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/device_pm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/device_pm.c
@@ -186,7 +186,7 @@
 		 * possibly drop references to the power resources in use.
 		 */
 		state = ACPI_STATE_D3_HOT;
-		/* If _PR3 is not available, use D3hot as the target state. */
+		/* If D3cold is not supported, use D3hot as the target state. */
 		if (!device->power.states[ACPI_STATE_D3_COLD].flags.valid)
 			target_state = state;
 	} else if (!device->power.states[state].flags.valid) {
@@ -273,13 +273,13 @@
  end:
 	if (result) {
 		dev_warn(&device->dev, "Failed to change power state to %s\n",
-			 acpi_power_state_string(state));
+			 acpi_power_state_string(target_state));
 	} else {
 		device->power.state = target_state;
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 				  "Device [%s] transitioned to %s\n",
 				  device->pnp.bus_id,
-				  acpi_power_state_string(state)));
+				  acpi_power_state_string(target_state)));
 	}
 
 	return result;
@@ -749,7 +749,7 @@
 static DEFINE_MUTEX(acpi_wakeup_lock);
 
 static int __acpi_device_wakeup_enable(struct acpi_device *adev,
-				       u32 target_state, int max_count)
+				       u32 target_state)
 {
 	struct acpi_device_wakeup *wakeup = &adev->wakeup;
 	acpi_status status;
@@ -757,15 +757,26 @@
 
 	mutex_lock(&acpi_wakeup_lock);
 
-	if (wakeup->enable_count >= max_count)
-		goto out;
-
+	/*
+	 * If the device wakeup power is already enabled, disable it and enable
+	 * it again in case it depends on the configuration of subordinate
+	 * devices and the conditions have changed since it was enabled last
+	 * time.
+	 */
 	if (wakeup->enable_count > 0)
-		goto inc;
+		acpi_disable_wakeup_device_power(adev);
 
 	error = acpi_enable_wakeup_device_power(adev, target_state);
-	if (error)
+	if (error) {
+		if (wakeup->enable_count > 0) {
+			acpi_disable_gpe(wakeup->gpe_device, wakeup->gpe_number);
+			wakeup->enable_count = 0;
+		}
 		goto out;
+	}
+
+	if (wakeup->enable_count > 0)
+		goto inc;
 
 	status = acpi_enable_gpe(wakeup->gpe_device, wakeup->gpe_number);
 	if (ACPI_FAILURE(status)) {
@@ -778,7 +789,10 @@
 			  (unsigned int)wakeup->gpe_number);
 
 inc:
-	wakeup->enable_count++;
+	if (wakeup->enable_count < INT_MAX)
+		wakeup->enable_count++;
+	else
+		acpi_handle_info(adev->handle, "Wakeup enable count out of bounds!\n");
 
 out:
 	mutex_unlock(&acpi_wakeup_lock);
@@ -799,7 +813,7 @@
  */
 static int acpi_device_wakeup_enable(struct acpi_device *adev, u32 target_state)
 {
-	return __acpi_device_wakeup_enable(adev, target_state, 1);
+	return __acpi_device_wakeup_enable(adev, target_state);
 }
 
 /**
@@ -829,8 +843,12 @@
 	mutex_unlock(&acpi_wakeup_lock);
 }
 
-static int __acpi_pm_set_device_wakeup(struct device *dev, bool enable,
-				       int max_count)
+/**
+ * acpi_pm_set_device_wakeup - Enable/disable remote wakeup for given device.
+ * @dev: Device to enable/disable to generate wakeup events.
+ * @enable: Whether to enable or disable the wakeup functionality.
+ */
+int acpi_pm_set_device_wakeup(struct device *dev, bool enable)
 {
 	struct acpi_device *adev;
 	int error;
@@ -850,37 +868,15 @@
 		return 0;
 	}
 
-	error = __acpi_device_wakeup_enable(adev, acpi_target_system_state(),
-					    max_count);
+	error = __acpi_device_wakeup_enable(adev, acpi_target_system_state());
 	if (!error)
 		dev_dbg(dev, "Wakeup enabled by ACPI\n");
 
 	return error;
 }
-
-/**
- * acpi_pm_set_device_wakeup - Enable/disable remote wakeup for given device.
- * @dev: Device to enable/disable to generate wakeup events.
- * @enable: Whether to enable or disable the wakeup functionality.
- */
-int acpi_pm_set_device_wakeup(struct device *dev, bool enable)
-{
-	return __acpi_pm_set_device_wakeup(dev, enable, 1);
-}
 EXPORT_SYMBOL_GPL(acpi_pm_set_device_wakeup);
 
 /**
- * acpi_pm_set_bridge_wakeup - Enable/disable remote wakeup for given bridge.
- * @dev: Bridge device to enable/disable to generate wakeup events.
- * @enable: Whether to enable or disable the wakeup functionality.
- */
-int acpi_pm_set_bridge_wakeup(struct device *dev, bool enable)
-{
-	return __acpi_pm_set_device_wakeup(dev, enable, INT_MAX);
-}
-EXPORT_SYMBOL_GPL(acpi_pm_set_bridge_wakeup);
-
-/**
  * acpi_dev_pm_low_power - Put ACPI device into a low-power state.
  * @dev: Device to put into a low-power state.
  * @adev: ACPI device node corresponding to @dev.
@@ -1314,9 +1310,19 @@
  */
 int acpi_dev_pm_attach(struct device *dev, bool power_on)
 {
+	/*
+	 * Skip devices whose ACPI companions match the device IDs below,
+	 * because they require special power management handling incompatible
+	 * with the generic ACPI PM domain.
+	 */
+	static const struct acpi_device_id special_pm_ids[] = {
+		{"PNP0C0B", }, /* Generic ACPI fan */
+		{"INT3404", }, /* Fan */
+		{}
+	};
 	struct acpi_device *adev = ACPI_COMPANION(dev);
 
-	if (!adev)
+	if (!adev || !acpi_match_device_ids(adev, special_pm_ids))
 		return 0;
 
 	/*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/device_sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/device_sysfs.c
@@ -156,8 +156,8 @@
 		return 0;
 
 	len = snprintf(modalias, size, "acpi:");
-	if (len <= 0)
-		return len;
+	if (len >= size)
+		return -ENOMEM;
 
 	size -= len;
 
@@ -210,8 +210,10 @@
 	len = snprintf(modalias, size, "of:N%sT", (char *)buf.pointer);
 	ACPI_FREE(buf.pointer);
 
-	if (len <= 0)
-		return len;
+	if (len >= size)
+		return -ENOMEM;
+
+	size -= len;
 
 	of_compatible = acpi_dev->data.of_compatible;
 	if (of_compatible->type == ACPI_TYPE_PACKAGE) {
@@ -251,20 +253,12 @@
 	if (add_uevent_var(env, "MODALIAS="))
 		return -ENOMEM;
 
-	len = create_pnp_modalias(adev, &env->buf[env->buflen - 1],
-				  sizeof(env->buf) - env->buflen);
-	if (len < 0)
-		return len;
-
-	env->buflen += len;
-	if (!adev->data.of_compatible)
-		return 0;
-
-	if (len > 0 && add_uevent_var(env, "MODALIAS="))
-		return -ENOMEM;
-
-	len = create_of_modalias(adev, &env->buf[env->buflen - 1],
-				 sizeof(env->buf) - env->buflen);
+	if (adev->data.of_compatible)
+		len = create_of_modalias(adev, &env->buf[env->buflen - 1],
+					 sizeof(env->buf) - env->buflen);
+	else
+		len = create_pnp_modalias(adev, &env->buf[env->buflen - 1],
+					  sizeof(env->buf) - env->buflen);
 	if (len < 0)
 		return len;
 
@@ -333,11 +327,11 @@
 EXPORT_SYMBOL_GPL(acpi_device_modalias);
 
 static ssize_t
-acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
+modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	return __acpi_device_modalias(to_acpi_device(dev), buf, 1024);
 }
-static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL);
+static DEVICE_ATTR_RO(modalias);
 
 static ssize_t real_power_state_show(struct device *dev,
 				     struct device_attribute *attr, char *buf)
@@ -366,8 +360,8 @@
 static DEVICE_ATTR_RO(power_state);
 
 static ssize_t
-acpi_eject_store(struct device *d, struct device_attribute *attr,
-		const char *buf, size_t count)
+eject_store(struct device *d, struct device_attribute *attr,
+	    const char *buf, size_t count)
 {
 	struct acpi_device *acpi_device = to_acpi_device(d);
 	acpi_object_type not_used;
@@ -395,28 +389,28 @@
 	return status == AE_NO_MEMORY ? -ENOMEM : -EAGAIN;
 }
 
-static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store);
+static DEVICE_ATTR_WO(eject);
 
 static ssize_t
-acpi_device_hid_show(struct device *dev, struct device_attribute *attr, char *buf)
+hid_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct acpi_device *acpi_dev = to_acpi_device(dev);
 
 	return sprintf(buf, "%s\n", acpi_device_hid(acpi_dev));
 }
-static DEVICE_ATTR(hid, 0444, acpi_device_hid_show, NULL);
+static DEVICE_ATTR_RO(hid);
 
-static ssize_t acpi_device_uid_show(struct device *dev,
-				    struct device_attribute *attr, char *buf)
+static ssize_t uid_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
 {
 	struct acpi_device *acpi_dev = to_acpi_device(dev);
 
 	return sprintf(buf, "%s\n", acpi_dev->pnp.unique_id);
 }
-static DEVICE_ATTR(uid, 0444, acpi_device_uid_show, NULL);
+static DEVICE_ATTR_RO(uid);
 
-static ssize_t acpi_device_adr_show(struct device *dev,
-				    struct device_attribute *attr, char *buf)
+static ssize_t adr_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
 {
 	struct acpi_device *acpi_dev = to_acpi_device(dev);
 
@@ -425,16 +419,16 @@
 	else
 		return sprintf(buf, "0x%08llx\n", acpi_dev->pnp.bus_address);
 }
-static DEVICE_ATTR(adr, 0444, acpi_device_adr_show, NULL);
+static DEVICE_ATTR_RO(adr);
 
-static ssize_t acpi_device_path_show(struct device *dev,
-				     struct device_attribute *attr, char *buf)
+static ssize_t path_show(struct device *dev,
+			 struct device_attribute *attr, char *buf)
 {
 	struct acpi_device *acpi_dev = to_acpi_device(dev);
 
 	return acpi_object_path(acpi_dev->handle, buf);
 }
-static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL);
+static DEVICE_ATTR_RO(path);
 
 /* sysfs file that shows description text from the ACPI _STR method */
 static ssize_t description_show(struct device *dev,
@@ -454,7 +448,7 @@
 		(wchar_t *)acpi_dev->pnp.str_obj->buffer.pointer,
 		acpi_dev->pnp.str_obj->buffer.length,
 		UTF16_LITTLE_ENDIAN, buf,
-		PAGE_SIZE);
+		PAGE_SIZE - 1);
 
 	buf[result++] = '\n';
 
@@ -463,8 +457,8 @@
 static DEVICE_ATTR_RO(description);
 
 static ssize_t
-acpi_device_sun_show(struct device *dev, struct device_attribute *attr,
-		     char *buf) {
+sun_show(struct device *dev, struct device_attribute *attr,
+	 char *buf) {
 	struct acpi_device *acpi_dev = to_acpi_device(dev);
 	acpi_status status;
 	unsigned long long sun;
@@ -475,11 +469,11 @@
 
 	return sprintf(buf, "%llu\n", sun);
 }
-static DEVICE_ATTR(sun, 0444, acpi_device_sun_show, NULL);
+static DEVICE_ATTR_RO(sun);
 
 static ssize_t
-acpi_device_hrv_show(struct device *dev, struct device_attribute *attr,
-		     char *buf) {
+hrv_show(struct device *dev, struct device_attribute *attr,
+	 char *buf) {
 	struct acpi_device *acpi_dev = to_acpi_device(dev);
 	acpi_status status;
 	unsigned long long hrv;
@@ -490,7 +484,7 @@
 
 	return sprintf(buf, "%llu\n", hrv);
 }
-static DEVICE_ATTR(hrv, 0444, acpi_device_hrv_show, NULL);
+static DEVICE_ATTR_RO(hrv);
 
 static ssize_t status_show(struct device *dev, struct device_attribute *attr,
 				char *buf) {
@@ -539,8 +533,9 @@
 	 * If device has _STR, 'description' file is created
 	 */
 	if (acpi_has_method(dev->handle, "_STR")) {
-		status = acpi_evaluate_object(dev->handle, "_STR",
-					NULL, &buffer);
+		status = acpi_evaluate_object_typed(dev->handle, "_STR",
+						    NULL, &buffer,
+						    ACPI_TYPE_BUFFER);
 		if (ACPI_FAILURE(status))
 			buffer.pointer = NULL;
 		dev->pnp.str_obj = buffer.pointer;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/dock.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/dock.c
@@ -485,7 +485,7 @@
 /*
  * show_docked - read method for "docked" file in sysfs
  */
-static ssize_t show_docked(struct device *dev,
+static ssize_t docked_show(struct device *dev,
 			   struct device_attribute *attr, char *buf)
 {
 	struct dock_station *dock_station = dev->platform_data;
@@ -494,25 +494,25 @@
 	acpi_bus_get_device(dock_station->handle, &adev);
 	return snprintf(buf, PAGE_SIZE, "%u\n", acpi_device_enumerated(adev));
 }
-static DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL);
+static DEVICE_ATTR_RO(docked);
 
 /*
  * show_flags - read method for flags file in sysfs
  */
-static ssize_t show_flags(struct device *dev,
+static ssize_t flags_show(struct device *dev,
 			  struct device_attribute *attr, char *buf)
 {
 	struct dock_station *dock_station = dev->platform_data;
 	return snprintf(buf, PAGE_SIZE, "%d\n", dock_station->flags);
 
 }
-static DEVICE_ATTR(flags, S_IRUGO, show_flags, NULL);
+static DEVICE_ATTR_RO(flags);
 
 /*
  * write_undock - write method for "undock" file in sysfs
  */
-static ssize_t write_undock(struct device *dev, struct device_attribute *attr,
-			   const char *buf, size_t count)
+static ssize_t undock_store(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t count)
 {
 	int ret;
 	struct dock_station *dock_station = dev->platform_data;
@@ -526,13 +526,13 @@
 	acpi_scan_lock_release();
 	return ret ? ret: count;
 }
-static DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock);
+static DEVICE_ATTR_WO(undock);
 
 /*
  * show_dock_uid - read method for "uid" file in sysfs
  */
-static ssize_t show_dock_uid(struct device *dev,
-			     struct device_attribute *attr, char *buf)
+static ssize_t uid_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
 {
 	unsigned long long lbuf;
 	struct dock_station *dock_station = dev->platform_data;
@@ -543,10 +543,10 @@
 
 	return snprintf(buf, PAGE_SIZE, "%llx\n", lbuf);
 }
-static DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL);
+static DEVICE_ATTR_RO(uid);
 
-static ssize_t show_dock_type(struct device *dev,
-		struct device_attribute *attr, char *buf)
+static ssize_t type_show(struct device *dev,
+			 struct device_attribute *attr, char *buf)
 {
 	struct dock_station *dock_station = dev->platform_data;
 	char *type;
@@ -562,7 +562,7 @@
 
 	return snprintf(buf, PAGE_SIZE, "%s\n", type);
 }
-static DEVICE_ATTR(type, S_IRUGO, show_dock_type, NULL);
+static DEVICE_ATTR_RO(type);
 
 static struct attribute *dock_attributes[] = {
 	&dev_attr_docked.attr,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/ec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/ec.c
@@ -95,12 +95,12 @@
 	EC_FLAGS_QUERY_ENABLED,		/* Query is enabled */
 	EC_FLAGS_QUERY_PENDING,		/* Query is pending */
 	EC_FLAGS_QUERY_GUARDING,	/* Guard for SCI_EVT check */
-	EC_FLAGS_GPE_HANDLER_INSTALLED,	/* GPE handler installed */
+	EC_FLAGS_EVENT_HANDLER_INSTALLED,	/* Event handler installed */
 	EC_FLAGS_EC_HANDLER_INSTALLED,	/* OpReg handler installed */
-	EC_FLAGS_EVT_HANDLER_INSTALLED, /* _Qxx handlers installed */
+	EC_FLAGS_QUERY_METHODS_INSTALLED, /* _Qxx handlers installed */
 	EC_FLAGS_STARTED,		/* Driver is started */
 	EC_FLAGS_STOPPED,		/* Driver is stopped */
-	EC_FLAGS_GPE_MASKED,		/* GPE masked */
+	EC_FLAGS_EVENTS_MASKED,		/* Events masked */
 };
 
 #define ACPI_EC_COMMAND_POLL		0x01 /* Available for command byte */
@@ -167,6 +167,7 @@
 	struct transaction transaction;
 	struct work_struct work;
 	struct acpi_ec_query_handler *handler;
+	struct acpi_ec *ec;
 };
 
 static int acpi_ec_query(struct acpi_ec *ec, u8 *data);
@@ -179,6 +180,7 @@
 
 static struct acpi_ec *boot_ec;
 static bool boot_ec_is_ecdt = false;
+static struct workqueue_struct *ec_wq;
 static struct workqueue_struct *ec_query_wq;
 
 static int EC_FLAGS_QUERY_HANDSHAKE; /* Needs QR_EC issued when SCI_EVT set */
@@ -397,8 +399,8 @@
 static void acpi_ec_submit_request(struct acpi_ec *ec)
 {
 	ec->reference_count++;
-	if (test_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags) &&
-	    ec->reference_count == 1)
+	if (test_bit(EC_FLAGS_EVENT_HANDLER_INSTALLED, &ec->flags) &&
+	    ec->gpe >= 0 && ec->reference_count == 1)
 		acpi_ec_enable_gpe(ec, true);
 }
 
@@ -407,28 +409,36 @@
 	bool flushed = false;
 
 	ec->reference_count--;
-	if (test_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags) &&
-	    ec->reference_count == 0)
+	if (test_bit(EC_FLAGS_EVENT_HANDLER_INSTALLED, &ec->flags) &&
+	    ec->gpe >= 0 && ec->reference_count == 0)
 		acpi_ec_disable_gpe(ec, true);
 	flushed = acpi_ec_flushed(ec);
 	if (flushed)
 		wake_up(&ec->wait);
 }
 
-static void acpi_ec_mask_gpe(struct acpi_ec *ec)
+static void acpi_ec_mask_events(struct acpi_ec *ec)
 {
-	if (!test_bit(EC_FLAGS_GPE_MASKED, &ec->flags)) {
-		acpi_ec_disable_gpe(ec, false);
+	if (!test_bit(EC_FLAGS_EVENTS_MASKED, &ec->flags)) {
+		if (ec->gpe >= 0)
+			acpi_ec_disable_gpe(ec, false);
+		else
+			disable_irq_nosync(ec->irq);
+
 		ec_dbg_drv("Polling enabled");
-		set_bit(EC_FLAGS_GPE_MASKED, &ec->flags);
+		set_bit(EC_FLAGS_EVENTS_MASKED, &ec->flags);
 	}
 }
 
-static void acpi_ec_unmask_gpe(struct acpi_ec *ec)
+static void acpi_ec_unmask_events(struct acpi_ec *ec)
 {
-	if (test_bit(EC_FLAGS_GPE_MASKED, &ec->flags)) {
-		clear_bit(EC_FLAGS_GPE_MASKED, &ec->flags);
-		acpi_ec_enable_gpe(ec, false);
+	if (test_bit(EC_FLAGS_EVENTS_MASKED, &ec->flags)) {
+		clear_bit(EC_FLAGS_EVENTS_MASKED, &ec->flags);
+		if (ec->gpe >= 0)
+			acpi_ec_enable_gpe(ec, false);
+		else
+			enable_irq(ec->irq);
+
 		ec_dbg_drv("Polling disabled");
 	}
 }
@@ -454,14 +464,15 @@
 
 static void acpi_ec_submit_query(struct acpi_ec *ec)
 {
-	acpi_ec_mask_gpe(ec);
+	acpi_ec_mask_events(ec);
 	if (!acpi_ec_event_enabled(ec))
 		return;
 	if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) {
 		ec_dbg_evt("Command(%s) submitted/blocked",
 			   acpi_ec_cmd_string(ACPI_EC_COMMAND_QUERY));
 		ec->nr_pending_queries++;
-		schedule_work(&ec->work);
+		ec->events_in_progress++;
+		queue_work(ec_wq, &ec->work);
 	}
 }
 
@@ -470,7 +481,7 @@
 	if (test_and_clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags))
 		ec_dbg_evt("Command(%s) unblocked",
 			   acpi_ec_cmd_string(ACPI_EC_COMMAND_QUERY));
-	acpi_ec_unmask_gpe(ec);
+	acpi_ec_unmask_events(ec);
 }
 
 static inline void __acpi_ec_enable_event(struct acpi_ec *ec)
@@ -525,26 +536,10 @@
 }
 
 #ifdef CONFIG_PM_SLEEP
-static bool acpi_ec_query_flushed(struct acpi_ec *ec)
+static void __acpi_ec_flush_work(void)
 {
-	bool flushed;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ec->lock, flags);
-	flushed = !ec->nr_pending_queries;
-	spin_unlock_irqrestore(&ec->lock, flags);
-	return flushed;
-}
-
-static void __acpi_ec_flush_event(struct acpi_ec *ec)
-{
-	/*
-	 * When ec_freeze_events is true, we need to flush events in
-	 * the proper position before entering the noirq stage.
-	 */
-	wait_event(ec->wait, acpi_ec_query_flushed(ec));
-	if (ec_query_wq)
-		flush_workqueue(ec_query_wq);
+	flush_workqueue(ec_wq); /* flush ec->work */
+	flush_workqueue(ec_query_wq); /* flush queries */
 }
 
 static void acpi_ec_disable_event(struct acpi_ec *ec)
@@ -554,15 +549,21 @@
 	spin_lock_irqsave(&ec->lock, flags);
 	__acpi_ec_disable_event(ec);
 	spin_unlock_irqrestore(&ec->lock, flags);
-	__acpi_ec_flush_event(ec);
+
+	/*
+	 * When ec_freeze_events is true, we need to flush events in
+	 * the proper position before entering the noirq stage.
+	 */
+	__acpi_ec_flush_work();
 }
 
 void acpi_ec_flush_work(void)
 {
-	if (first_ec)
-		__acpi_ec_flush_event(first_ec);
+	/* Without ec_wq there is nothing to flush. */
+	if (!ec_wq)
+		return;
 
-	flush_scheduled_work();
+	__acpi_ec_flush_work();
 }
 #endif /* CONFIG_PM_SLEEP */
 
@@ -648,7 +649,9 @@
 	 * ensure a hardware STS 0->1 change after this clearing can always
 	 * trigger a GPE interrupt.
 	 */
-	acpi_ec_clear_gpe(ec);
+	if (ec->gpe >= 0)
+		acpi_ec_clear_gpe(ec);
+
 	status = acpi_ec_read_status(ec);
 	t = ec->curr;
 	/*
@@ -717,7 +720,7 @@
 				++t->irq_count;
 			/* Allow triggering on 0 threshold */
 			if (t->irq_count == ec_storm_threshold)
-				acpi_ec_mask_gpe(ec);
+				acpi_ec_mask_events(ec);
 		}
 	}
 out:
@@ -797,6 +800,9 @@
 	unsigned long tmp;
 	int ret = 0;
 
+	if (t->rdata)
+		memset(t->rdata, 0, t->rlen);
+
 	/* start transaction */
 	spin_lock_irqsave(&ec->lock, tmp);
 	/* Enable GPE for command processing (IBF=0/OBF=1) */
@@ -815,7 +821,7 @@
 
 	spin_lock_irqsave(&ec->lock, tmp);
 	if (t->irq_count == ec_storm_threshold)
-		acpi_ec_unmask_gpe(ec);
+		acpi_ec_unmask_events(ec);
 	ec_dbg_req("Command(%s) stopped", acpi_ec_cmd_string(t->command));
 	ec->curr = NULL;
 	/* Disable GPE for command processing (IBF=0/OBF=1) */
@@ -833,8 +839,6 @@
 
 	if (!ec || (!t) || (t->wlen && !t->wdata) || (t->rlen && !t->rdata))
 		return -EINVAL;
-	if (t->rdata)
-		memset(t->rdata, 0, t->rlen);
 
 	mutex_lock(&ec->mutex);
 	if (ec->global_lock) {
@@ -861,7 +865,7 @@
 				.wdata = NULL, .rdata = &d,
 				.wlen = 0, .rlen = 1};
 
-	return acpi_ec_transaction(ec, &t);
+	return acpi_ec_transaction_unlocked(ec, &t);
 }
 
 static int acpi_ec_burst_disable(struct acpi_ec *ec)
@@ -871,7 +875,7 @@
 				.wlen = 0, .rlen = 0};
 
 	return (acpi_ec_read_status(ec) & ACPI_EC_FLAG_BURST) ?
-				acpi_ec_transaction(ec, &t) : 0;
+				acpi_ec_transaction_unlocked(ec, &t) : 0;
 }
 
 static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 *data)
@@ -887,6 +891,19 @@
 	return result;
 }
 
+static int acpi_ec_read_unlocked(struct acpi_ec *ec, u8 address, u8 *data)
+{
+	int result;
+	u8 d;
+	struct transaction t = {.command = ACPI_EC_COMMAND_READ,
+				.wdata = &address, .rdata = &d,
+				.wlen = 1, .rlen = 1};
+
+	result = acpi_ec_transaction_unlocked(ec, &t);
+	*data = d;
+	return result;
+}
+
 static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data)
 {
 	u8 wdata[2] = { address, data };
@@ -897,6 +914,16 @@
 	return acpi_ec_transaction(ec, &t);
 }
 
+static int acpi_ec_write_unlocked(struct acpi_ec *ec, u8 address, u8 data)
+{
+	u8 wdata[2] = { address, data };
+	struct transaction t = {.command = ACPI_EC_COMMAND_WRITE,
+				.wdata = wdata, .rdata = NULL,
+				.wlen = 2, .rlen = 0};
+
+	return acpi_ec_transaction_unlocked(ec, &t);
+}
+
 int ec_read(u8 addr, u8 *val)
 {
 	int err;
@@ -1053,28 +1080,20 @@
                                 Event Management
    -------------------------------------------------------------------------- */
 static struct acpi_ec_query_handler *
-acpi_ec_get_query_handler(struct acpi_ec_query_handler *handler)
-{
-	if (handler)
-		kref_get(&handler->kref);
-	return handler;
-}
-
-static struct acpi_ec_query_handler *
 acpi_ec_get_query_handler_by_value(struct acpi_ec *ec, u8 value)
 {
 	struct acpi_ec_query_handler *handler;
-	bool found = false;
 
 	mutex_lock(&ec->mutex);
 	list_for_each_entry(handler, &ec->list, node) {
 		if (value == handler->query_bit) {
-			found = true;
-			break;
+			kref_get(&handler->kref);
+			mutex_unlock(&ec->mutex);
+			return handler;
 		}
 	}
 	mutex_unlock(&ec->mutex);
-	return found ? acpi_ec_get_query_handler(handler) : NULL;
+	return NULL;
 }
 
 static void acpi_ec_query_handler_release(struct kref *kref)
@@ -1133,10 +1152,11 @@
 void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit)
 {
 	acpi_ec_remove_query_handlers(ec, false, query_bit);
+	flush_workqueue(ec_query_wq);
 }
 EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler);
 
-static struct acpi_ec_query *acpi_ec_create_query(u8 *pval)
+static struct acpi_ec_query *acpi_ec_create_query(struct acpi_ec *ec, u8 *pval)
 {
 	struct acpi_ec_query *q;
 	struct transaction *t;
@@ -1144,11 +1164,13 @@
 	q = kzalloc(sizeof (struct acpi_ec_query), GFP_KERNEL);
 	if (!q)
 		return NULL;
+
 	INIT_WORK(&q->work, acpi_ec_event_processor);
 	t = &q->transaction;
 	t->command = ACPI_EC_COMMAND_QUERY;
 	t->rdata = pval;
 	t->rlen = 1;
+	q->ec = ec;
 	return q;
 }
 
@@ -1165,13 +1187,21 @@
 {
 	struct acpi_ec_query *q = container_of(work, struct acpi_ec_query, work);
 	struct acpi_ec_query_handler *handler = q->handler;
+	struct acpi_ec *ec = q->ec;
 
 	ec_dbg_evt("Query(0x%02x) started", handler->query_bit);
+
 	if (handler->func)
 		handler->func(handler->data);
 	else if (handler->handle)
 		acpi_evaluate_object(handler->handle, NULL, NULL, NULL);
+
 	ec_dbg_evt("Query(0x%02x) stopped", handler->query_bit);
+
+	spin_lock_irq(&ec->lock);
+	ec->queries_in_progress--;
+	spin_unlock_irq(&ec->lock);
+
 	acpi_ec_delete_query(q);
 }
 
@@ -1181,7 +1211,7 @@
 	int result;
 	struct acpi_ec_query *q;
 
-	q = acpi_ec_create_query(&value);
+	q = acpi_ec_create_query(ec, &value);
 	if (!q)
 		return -ENOMEM;
 
@@ -1203,19 +1233,20 @@
 	}
 
 	/*
-	 * It is reported that _Qxx are evaluated in a parallel way on
-	 * Windows:
+	 * It is reported that _Qxx are evaluated in a parallel way on Windows:
 	 * https://bugzilla.kernel.org/show_bug.cgi?id=94411
 	 *
-	 * Put this log entry before schedule_work() in order to make
-	 * it appearing before any other log entries occurred during the
-	 * work queue execution.
+	 * Put this log entry before queue_work() to make it appear in the log
+	 * before any other messages emitted during workqueue handling.
 	 */
 	ec_dbg_evt("Query(0x%02x) scheduled", value);
-	if (!queue_work(ec_query_wq, &q->work)) {
-		ec_dbg_evt("Query(0x%02x) overlapped", value);
-		result = -EBUSY;
-	}
+
+	spin_lock_irq(&ec->lock);
+
+	ec->queries_in_progress++;
+	queue_work(ec_query_wq, &q->work);
+
+	spin_unlock_irq(&ec->lock);
 
 err_exit:
 	if (result)
@@ -1273,20 +1304,34 @@
 	ec_dbg_evt("Event stopped");
 
 	acpi_ec_check_event(ec);
+
+	spin_lock_irqsave(&ec->lock, flags);
+	ec->events_in_progress--;
+	spin_unlock_irqrestore(&ec->lock, flags);
 }
 
-static u32 acpi_ec_gpe_handler(acpi_handle gpe_device,
-	u32 gpe_number, void *data)
+static void acpi_ec_handle_interrupt(struct acpi_ec *ec)
 {
 	unsigned long flags;
-	struct acpi_ec *ec = data;
 
 	spin_lock_irqsave(&ec->lock, flags);
 	advance_transaction(ec);
 	spin_unlock_irqrestore(&ec->lock, flags);
+}
+
+static u32 acpi_ec_gpe_handler(acpi_handle gpe_device,
+			       u32 gpe_number, void *data)
+{
+	acpi_ec_handle_interrupt(data);
 	return ACPI_INTERRUPT_HANDLED;
 }
 
+static irqreturn_t acpi_ec_irq_handler(int irq, void *data)
+{
+	acpi_ec_handle_interrupt(data);
+	return IRQ_HANDLED;
+}
+
 /* --------------------------------------------------------------------------
  *                           Address Space Management
  * -------------------------------------------------------------------------- */
@@ -1299,6 +1344,7 @@
 	struct acpi_ec *ec = handler_context;
 	int result = 0, i, bytes = bits / 8;
 	u8 *value = (u8 *)value64;
+	u32 glk;
 
 	if ((address > 0xFF) || !value || !handler_context)
 		return AE_BAD_PARAMETER;
@@ -1306,17 +1352,38 @@
 	if (function != ACPI_READ && function != ACPI_WRITE)
 		return AE_BAD_PARAMETER;
 
+	mutex_lock(&ec->mutex);
+
+	if (ec->global_lock) {
+		acpi_status status;
+
+		status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk);
+		if (ACPI_FAILURE(status)) {
+			result = -ENODEV;
+			goto unlock;
+		}
+	}
+
 	if (ec->busy_polling || bits > 8)
 		acpi_ec_burst_enable(ec);
 
-	for (i = 0; i < bytes; ++i, ++address, ++value)
+	for (i = 0; i < bytes; ++i, ++address, ++value) {
 		result = (function == ACPI_READ) ?
-			acpi_ec_read(ec, address, value) :
-			acpi_ec_write(ec, address, *value);
+			acpi_ec_read_unlocked(ec, address, value) :
+			acpi_ec_write_unlocked(ec, address, *value);
+		if (result < 0)
+			break;
+	}
 
 	if (ec->busy_polling || bits > 8)
 		acpi_ec_burst_disable(ec);
 
+	if (ec->global_lock)
+		acpi_release_global_lock(glk);
+
+unlock:
+	mutex_unlock(&ec->mutex);
+
 	switch (result) {
 	case -EINVAL:
 		return AE_BAD_PARAMETER;
@@ -1324,8 +1391,10 @@
 		return AE_NOT_FOUND;
 	case -ETIME:
 		return AE_TIME;
-	default:
+	case 0:
 		return AE_OK;
+	default:
+		return AE_ERROR;
 	}
 }
 
@@ -1359,6 +1428,8 @@
 	ec->timestamp = jiffies;
 	ec->busy_polling = true;
 	ec->polling_guard = 0;
+	ec->gpe = -1;
+	ec->irq = -1;
 	return ec;
 }
 
@@ -1406,9 +1477,13 @@
 		/* Get GPE bit assignment (EC events). */
 		/* TODO: Add support for _GPE returning a package */
 		status = acpi_evaluate_integer(handle, "_GPE", NULL, &tmp);
-		if (ACPI_FAILURE(status))
-			return status;
-		ec->gpe = tmp;
+		if (ACPI_SUCCESS(status))
+			ec->gpe = tmp;
+
+		/*
+		 * Errors are non-fatal, allowing for ACPI Reduced Hardware
+		 * platforms which use GpioInt instead of GPE.
+		 */
 	}
 	/* Use the global lock for all EC transactions? */
 	tmp = 0;
@@ -1418,12 +1493,45 @@
 	return AE_CTRL_TERMINATE;
 }
 
-/*
- * Note: This function returns an error code only when the address space
- *       handler is not installed, which means "not able to handle
- *       transactions".
+static bool install_gpe_event_handler(struct acpi_ec *ec)
+{
+	acpi_status status;
+
+	status = acpi_install_gpe_raw_handler(NULL, ec->gpe,
+					      ACPI_GPE_EDGE_TRIGGERED,
+					      &acpi_ec_gpe_handler, ec);
+	if (ACPI_FAILURE(status))
+		return false;
+
+	if (test_bit(EC_FLAGS_STARTED, &ec->flags) && ec->reference_count >= 1)
+		acpi_ec_enable_gpe(ec, true);
+
+	return true;
+}
+
+static bool install_gpio_irq_event_handler(struct acpi_ec *ec)
+{
+	return request_irq(ec->irq, acpi_ec_irq_handler, IRQF_SHARED,
+			   "ACPI EC", ec) >= 0;
+}
+
+/**
+ * ec_install_handlers - Install service callbacks and register query methods.
+ * @ec: Target EC.
+ * @device: ACPI device object corresponding to @ec.
+ *
+ * Install a handler for the EC address space type unless it has been installed
+ * already.  If @device is not NULL, also look for EC query methods in the
+ * namespace and register them, and install an event (either GPE or GPIO IRQ)
+ * handler for the EC, if possible.
+ *
+ * Return:
+ * -ENODEV if the address space handler cannot be installed, which means
+ *  "unable to handle transactions",
+ * -EPROBE_DEFER if GPIO IRQ acquisition needs to be deferred,
+ * or 0 (success) otherwise.
  */
-static int ec_install_handlers(struct acpi_ec *ec, bool handle_events)
+static int ec_install_handlers(struct acpi_ec *ec, struct acpi_device *device)
 {
 	acpi_status status;
 
@@ -1453,28 +1561,45 @@
 		set_bit(EC_FLAGS_EC_HANDLER_INSTALLED, &ec->flags);
 	}
 
-	if (!handle_events)
+	if (!device)
 		return 0;
 
-	if (!test_bit(EC_FLAGS_EVT_HANDLER_INSTALLED, &ec->flags)) {
+	if (ec->gpe < 0) {
+		/* ACPI reduced hardware platforms use a GpioInt from _CRS. */
+		int irq = acpi_dev_gpio_irq_get(device, 0);
+		/*
+		 * Bail out right away for deferred probing or complete the
+		 * initialization regardless of any other errors.
+		 */
+		if (irq == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+		else if (irq >= 0)
+			ec->irq = irq;
+	}
+
+	if (!test_bit(EC_FLAGS_QUERY_METHODS_INSTALLED, &ec->flags)) {
 		/* Find and register all query methods */
 		acpi_walk_namespace(ACPI_TYPE_METHOD, ec->handle, 1,
 				    acpi_ec_register_query_methods,
 				    NULL, ec, NULL);
-		set_bit(EC_FLAGS_EVT_HANDLER_INSTALLED, &ec->flags);
+		set_bit(EC_FLAGS_QUERY_METHODS_INSTALLED, &ec->flags);
 	}
-	if (!test_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags)) {
-		status = acpi_install_gpe_raw_handler(NULL, ec->gpe,
-					  ACPI_GPE_EDGE_TRIGGERED,
-					  &acpi_ec_gpe_handler, ec);
-		/* This is not fatal as we can poll EC events */
-		if (ACPI_SUCCESS(status)) {
-			set_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags);
+	if (!test_bit(EC_FLAGS_EVENT_HANDLER_INSTALLED, &ec->flags)) {
+		bool ready = false;
+
+		if (ec->gpe >= 0)
+			ready = install_gpe_event_handler(ec);
+		else if (ec->irq >= 0)
+			ready = install_gpio_irq_event_handler(ec);
+
+		if (ready) {
+			set_bit(EC_FLAGS_EVENT_HANDLER_INSTALLED, &ec->flags);
 			acpi_ec_leave_noirq(ec);
-			if (test_bit(EC_FLAGS_STARTED, &ec->flags) &&
-			    ec->reference_count >= 1)
-				acpi_ec_enable_gpe(ec, true);
 		}
+		/*
+		 * Failures to install an event handler are not fatal, because
+		 * the EC can be polled for events.
+		 */
 	}
 	/* EC is fully operational, allow queries */
 	acpi_ec_enable_event(ec);
@@ -1504,23 +1629,28 @@
 	 */
 	acpi_ec_stop(ec, false);
 
-	if (test_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags)) {
-		if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe,
-					&acpi_ec_gpe_handler)))
+	if (test_bit(EC_FLAGS_EVENT_HANDLER_INSTALLED, &ec->flags)) {
+		if (ec->gpe >= 0 &&
+		    ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe,
+				 &acpi_ec_gpe_handler)))
 			pr_err("failed to remove gpe handler\n");
-		clear_bit(EC_FLAGS_GPE_HANDLER_INSTALLED, &ec->flags);
+
+		if (ec->irq >= 0)
+			free_irq(ec->irq, ec);
+
+		clear_bit(EC_FLAGS_EVENT_HANDLER_INSTALLED, &ec->flags);
 	}
-	if (test_bit(EC_FLAGS_EVT_HANDLER_INSTALLED, &ec->flags)) {
+	if (test_bit(EC_FLAGS_QUERY_METHODS_INSTALLED, &ec->flags)) {
 		acpi_ec_remove_query_handlers(ec, true, 0);
-		clear_bit(EC_FLAGS_EVT_HANDLER_INSTALLED, &ec->flags);
+		clear_bit(EC_FLAGS_QUERY_METHODS_INSTALLED, &ec->flags);
 	}
 }
 
-static int acpi_ec_setup(struct acpi_ec *ec, bool handle_events)
+static int acpi_ec_setup(struct acpi_ec *ec, struct acpi_device *device)
 {
 	int ret;
 
-	ret = ec_install_handlers(ec, handle_events);
+	ret = ec_install_handlers(ec, device);
 	if (ret)
 		return ret;
 
@@ -1531,8 +1661,8 @@
 	}
 
 	acpi_handle_info(ec->handle,
-			 "GPE=0x%x, EC_CMD/EC_SC=0x%lx, EC_DATA=0x%lx\n",
-			 ec->gpe, ec->command_addr, ec->data_addr);
+			 "GPE=0x%x, IRQ=%d, EC_CMD/EC_SC=0x%lx, EC_DATA=0x%lx\n",
+			 ec->gpe, ec->irq, ec->command_addr, ec->data_addr);
 	return ret;
 }
 
@@ -1577,7 +1707,7 @@
 		status = ec_parse_device(device->handle, 0, ec, NULL);
 		if (status != AE_CTRL_TERMINATE) {
 			ret = -EINVAL;
-			goto err_alloc;
+			goto err;
 		}
 
 		if (boot_ec && ec->command_addr == boot_ec->command_addr &&
@@ -1596,9 +1726,9 @@
 		}
 	}
 
-	ret = acpi_ec_setup(ec, true);
+	ret = acpi_ec_setup(ec, device);
 	if (ret)
-		goto err_query;
+		goto err;
 
 	if (ec == boot_ec)
 		acpi_handle_info(boot_ec->handle,
@@ -1619,12 +1749,10 @@
 	acpi_handle_debug(ec->handle, "enumerated.\n");
 	return 0;
 
-err_query:
-	if (ec != boot_ec)
-		acpi_ec_remove_query_handlers(ec, true, 0);
-err_alloc:
+err:
 	if (ec != boot_ec)
 		acpi_ec_free(ec);
+
 	return ret;
 }
 
@@ -1716,7 +1844,7 @@
 	 * At this point, the GPE is not fully initialized, so do not to
 	 * handle the events.
 	 */
-	ret = acpi_ec_setup(ec, false);
+	ret = acpi_ec_setup(ec, NULL);
 	if (ret) {
 		acpi_ec_free(ec);
 		return;
@@ -1843,6 +1971,22 @@
 	DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
 	DMI_MATCH(DMI_PRODUCT_NAME, "GL702VMK"),}, NULL},
 	{
+	ec_honor_ecdt_gpe, "ASUSTeK COMPUTER INC. X505BA", {
+	DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+	DMI_MATCH(DMI_PRODUCT_NAME, "X505BA"),}, NULL},
+	{
+	ec_honor_ecdt_gpe, "ASUSTeK COMPUTER INC. X505BP", {
+	DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+	DMI_MATCH(DMI_PRODUCT_NAME, "X505BP"),}, NULL},
+	{
+	ec_honor_ecdt_gpe, "ASUSTeK COMPUTER INC. X542BA", {
+	DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+	DMI_MATCH(DMI_PRODUCT_NAME, "X542BA"),}, NULL},
+	{
+	ec_honor_ecdt_gpe, "ASUSTeK COMPUTER INC. X542BP", {
+	DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+	DMI_MATCH(DMI_PRODUCT_NAME, "X542BP"),}, NULL},
+	{
 	ec_honor_ecdt_gpe, "ASUS X550VXK", {
 	DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
 	DMI_MATCH(DMI_PRODUCT_NAME, "X550VXK"),}, NULL},
@@ -1889,14 +2033,21 @@
 		ec->command_addr = ecdt_ptr->control.address;
 		ec->data_addr = ecdt_ptr->data.address;
 	}
-	ec->gpe = ecdt_ptr->gpe;
+
+	/*
+	 * Ignore the GPE value on Reduced Hardware platforms.
+	 * Some products have this set to an erroneous value.
+	 */
+	if (!acpi_gbl_reduced_hardware)
+		ec->gpe = ecdt_ptr->gpe;
+
 	ec->handle = ACPI_ROOT_OBJECT;
 
 	/*
 	 * At this point, the namespace is not initialized, so do not find
 	 * the namespace objects, or handle the events.
 	 */
-	ret = acpi_ec_setup(ec, false);
+	ret = acpi_ec_setup(ec, NULL);
 	if (ret) {
 		acpi_ec_free(ec);
 		return;
@@ -1928,7 +2079,7 @@
 	 * masked at the low level without side effects.
 	 */
 	if (ec_no_wakeup && test_bit(EC_FLAGS_STARTED, &ec->flags) &&
-	    ec->reference_count >= 1)
+	    ec->gpe >= 0 && ec->reference_count >= 1)
 		acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_DISABLE);
 
 	acpi_ec_enter_noirq(ec);
@@ -1943,7 +2094,7 @@
 	acpi_ec_leave_noirq(ec);
 
 	if (ec_no_wakeup && test_bit(EC_FLAGS_STARTED, &ec->flags) &&
-	    ec->reference_count >= 1)
+	    ec->gpe >= 0 && ec->reference_count >= 1)
 		acpi_set_gpe(NULL, ec->gpe, ACPI_GPE_ENABLE);
 
 	return 0;
@@ -1973,16 +2124,41 @@
 
 bool acpi_ec_dispatch_gpe(void)
 {
+	bool work_in_progress;
 	u32 ret;
 
 	if (!first_ec)
-		return false;
+		return acpi_any_gpe_status_set(U32_MAX);
 
+	/*
+	 * Report wakeup if the status bit is set for any enabled GPE other
+	 * than the EC one.
+	 */
+	if (acpi_any_gpe_status_set(first_ec->gpe))
+		return true;
+
+	/*
+	 * Dispatch the EC GPE in-band, but do not report wakeup in any case
+	 * to allow the caller to process events properly after that.
+	 */
 	ret = acpi_dispatch_gpe(NULL, first_ec->gpe);
-	if (ret == ACPI_INTERRUPT_HANDLED) {
+	if (ret == ACPI_INTERRUPT_HANDLED)
 		pm_pr_dbg("EC GPE dispatched\n");
-		return true;
-	}
+
+	/* Drain EC work. */
+	do {
+		acpi_ec_flush_work();
+
+		pm_pr_dbg("ACPI EC work flushed\n");
+
+		spin_lock_irq(&first_ec->lock);
+
+		work_in_progress = first_ec->events_in_progress +
+			first_ec->queries_in_progress > 0;
+
+		spin_unlock_irq(&first_ec->lock);
+	} while (work_in_progress && !pm_wakeup_pending());
+
 	return false;
 }
 #endif /* CONFIG_PM_SLEEP */
@@ -2042,25 +2218,33 @@
 	.drv.pm = &acpi_ec_pm,
 };
 
-static inline int acpi_ec_query_init(void)
+static void acpi_ec_destroy_workqueues(void)
 {
-	if (!ec_query_wq) {
-		ec_query_wq = alloc_workqueue("kec_query", 0,
-					      ec_max_queries);
-		if (!ec_query_wq)
-			return -ENODEV;
+	if (ec_wq) {
+		destroy_workqueue(ec_wq);
+		ec_wq = NULL;
 	}
-	return 0;
-}
-
-static inline void acpi_ec_query_exit(void)
-{
 	if (ec_query_wq) {
 		destroy_workqueue(ec_query_wq);
 		ec_query_wq = NULL;
 	}
 }
 
+static int acpi_ec_init_workqueues(void)
+{
+	if (!ec_wq)
+		ec_wq = alloc_ordered_workqueue("kec", 0);
+
+	if (!ec_query_wq)
+		ec_query_wq = alloc_workqueue("kec_query", 0, ec_max_queries);
+
+	if (!ec_wq || !ec_query_wq) {
+		acpi_ec_destroy_workqueues();
+		return -ENODEV;
+	}
+	return 0;
+}
+
 static const struct dmi_system_id acpi_ec_no_wakeup[] = {
 	{
 		.ident = "Thinkpad X1 Carbon 6th",
@@ -2070,13 +2254,6 @@
 		},
 	},
 	{
-		.ident = "ThinkPad X1 Carbon 6th",
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-			DMI_MATCH(DMI_PRODUCT_FAMILY, "ThinkPad X1 Carbon 6th"),
-		},
-	},
-	{
 		.ident = "ThinkPad X1 Yoga 3rd",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
@@ -2091,8 +2268,7 @@
 	int result;
 	int ecdt_fail, dsdt_fail;
 
-	/* register workqueue for _Qxx evaluations */
-	result = acpi_ec_query_init();
+	result = acpi_ec_init_workqueues();
 	if (result)
 		return result;
 
@@ -2123,6 +2299,6 @@
 {
 
 	acpi_bus_unregister_driver(&acpi_ec_driver);
-	acpi_ec_query_exit();
+	acpi_ec_destroy_workqueues();
 }
 #endif	/* 0 */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/evged.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/evged.c
@@ -79,6 +79,8 @@
 	struct resource r;
 	struct acpi_resource_irq *p = &ares->data.irq;
 	struct acpi_resource_extended_irq *pext = &ares->data.extended_irq;
+	char ev_name[5];
+	u8 trigger;
 
 	if (ares->type == ACPI_RESOURCE_TYPE_END_TAG)
 		return AE_OK;
@@ -87,14 +89,28 @@
 		dev_err(dev, "unable to parse IRQ resource\n");
 		return AE_ERROR;
 	}
-	if (ares->type == ACPI_RESOURCE_TYPE_IRQ)
+	if (ares->type == ACPI_RESOURCE_TYPE_IRQ) {
 		gsi = p->interrupts[0];
-	else
+		trigger = p->triggering;
+	} else {
 		gsi = pext->interrupts[0];
+		trigger = pext->triggering;
+	}
 
 	irq = r.start;
 
-	if (ACPI_FAILURE(acpi_get_handle(handle, "_EVT", &evt_handle))) {
+	switch (gsi) {
+	case 0 ... 255:
+		sprintf(ev_name, "_%c%02X",
+			trigger == ACPI_EDGE_SENSITIVE ? 'E' : 'L', gsi);
+
+		if (ACPI_SUCCESS(acpi_get_handle(handle, ev_name, &evt_handle)))
+			break;
+		/* fall through */
+	default:
+		if (ACPI_SUCCESS(acpi_get_handle(handle, "_EVT", &evt_handle)))
+			break;
+
 		dev_err(dev, "cannot locate _EVT method\n");
 		return AE_ERROR;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/hmat/hmat.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/hmat/hmat.c
@@ -403,7 +403,8 @@
 		pr_info("HMAT: Memory Flags:%04x Processor Domain:%d Memory Domain:%d\n",
 			p->flags, p->processor_PD, p->memory_PD);
 
-	if (p->flags & ACPI_HMAT_MEMORY_PD_VALID && hmat_revision == 1) {
+	if ((hmat_revision == 1 && p->flags & ACPI_HMAT_MEMORY_PD_VALID) ||
+	    hmat_revision > 1) {
 		target = find_mem_target(p->memory_PD);
 		if (!target) {
 			pr_debug("HMAT: Memory Domain missing from SRAT\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/internal.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/internal.h
@@ -9,6 +9,8 @@
 #ifndef _ACPI_INTERNAL_H_
 #define _ACPI_INTERNAL_H_
 
+#include <linux/idr.h>
+
 #define PREFIX "ACPI: "
 
 int early_acpi_osi_init(void);
@@ -96,9 +98,11 @@
 
 extern struct list_head acpi_bus_id_list;
 
+#define ACPI_MAX_DEVICE_INSTANCES	4096
+
 struct acpi_device_bus_id {
-	char bus_id[15];
-	unsigned int instance_no;
+	const char *bus_id;
+	struct ida instance_ida;
 	struct list_head node;
 };
 
@@ -165,7 +169,8 @@
    -------------------------------------------------------------------------- */
 struct acpi_ec {
 	acpi_handle handle;
-	u32 gpe;
+	int gpe;
+	int irq;
 	unsigned long command_addr;
 	unsigned long data_addr;
 	bool global_lock;
@@ -179,6 +184,8 @@
 	struct work_struct work;
 	unsigned long timestamp;
 	unsigned long nr_pending_queries;
+	unsigned int events_in_progress;
+	unsigned int queries_in_progress;
 	bool busy_polling;
 	unsigned int polling_guard;
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/irq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/irq.c
@@ -52,6 +52,7 @@
 		      int polarity)
 {
 	struct irq_fwspec fwspec;
+	unsigned int irq;
 
 	if (WARN_ON(!acpi_gsi_domain_id)) {
 		pr_warn("GSI: No registered irqchip, giving up\n");
@@ -63,7 +64,11 @@
 	fwspec.param[1] = acpi_dev_get_irq_type(trigger, polarity);
 	fwspec.param_count = 2;
 
-	return irq_create_fwspec_mapping(&fwspec);
+	irq = irq_create_fwspec_mapping(&fwspec);
+	if (!irq)
+		return -EINVAL;
+
+	return irq;
 }
 EXPORT_SYMBOL_GPL(acpi_register_gsi);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/nfit/core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/nfit/core.c
@@ -360,7 +360,7 @@
 
 static u8 nfit_dsm_revid(unsigned family, unsigned func)
 {
-	static const u8 revid_table[NVDIMM_FAMILY_MAX+1][32] = {
+	static const u8 revid_table[NVDIMM_FAMILY_MAX+1][NVDIMM_CMD_MAX+1] = {
 		[NVDIMM_FAMILY_INTEL] = {
 			[NVDIMM_INTEL_GET_MODES] = 2,
 			[NVDIMM_INTEL_GET_FWINFO] = 2,
@@ -386,7 +386,7 @@
 
 	if (family > NVDIMM_FAMILY_MAX)
 		return 0;
-	if (func > 31)
+	if (func > NVDIMM_CMD_MAX)
 		return 0;
 	id = revid_table[family][func];
 	if (id == 0)
@@ -454,8 +454,13 @@
 	if (cmd_rc)
 		*cmd_rc = -EINVAL;
 
-	if (cmd == ND_CMD_CALL)
+	if (cmd == ND_CMD_CALL) {
+		if (!buf || buf_len < sizeof(*call_pkg))
+			return -EINVAL;
+
 		call_pkg = buf;
+	}
+
 	func = cmd_to_func(nfit_mem, cmd, call_pkg);
 	if (func < 0)
 		return func;
@@ -492,7 +497,8 @@
 	 * Check for a valid command.  For ND_CMD_CALL, we also have to
 	 * make sure that the DSM function is supported.
 	 */
-	if (cmd == ND_CMD_CALL && !test_bit(func, &dsm_mask))
+	if (cmd == ND_CMD_CALL &&
+	    (func > NVDIMM_CMD_MAX || !test_bit(func, &dsm_mask)))
 		return -ENOTTY;
 	else if (!test_bit(cmd, &cmd_mask))
 		return -ENOTTY;
@@ -1552,7 +1558,7 @@
 					le16_to_cpu(nfit_dcr->dcr->code));
 			break;
 		}
-		if (rc != ENXIO)
+		if (rc != -ENXIO)
 			break;
 	}
 	mutex_unlock(&acpi_desc->init_mutex);
@@ -2972,6 +2978,9 @@
 		struct acpi_nfit_memory_map *memdev = nfit_memdev->memdev;
 		struct nd_mapping_desc *mapping;
 
+		/* range index 0 == unmapped in SPA or invalid-SPA */
+		if (memdev->range_index == 0 || spa->range_index == 0)
+			continue;
 		if (memdev->range_index != spa->range_index)
 			continue;
 		if (count >= ND_MAX_MAPPINGS) {
@@ -3499,7 +3508,8 @@
 	if (nvdimm && cmd == ND_CMD_CALL &&
 			call_pkg->nd_family == NVDIMM_FAMILY_INTEL) {
 		func = call_pkg->nd_command;
-		if ((1 << func) & NVDIMM_INTEL_SECURITY_CMDMASK)
+		if (func > NVDIMM_CMD_MAX ||
+		    (1 << func) & NVDIMM_INTEL_SECURITY_CMDMASK)
 			return -EOPNOTSUPP;
 	}
 
@@ -3594,8 +3604,8 @@
 
 	mutex_lock(&acpi_desc->init_mutex);
 	set_bit(ARS_CANCEL, &acpi_desc->scrub_flags);
-	cancel_delayed_work_sync(&acpi_desc->dwork);
 	mutex_unlock(&acpi_desc->init_mutex);
+	cancel_delayed_work_sync(&acpi_desc->dwork);
 
 	/*
 	 * Bounce the nvdimm bus lock to make sure any in-flight
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/nfit/nfit.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/nfit/nfit.h
@@ -34,6 +34,7 @@
 		| ACPI_NFIT_MEM_NOT_ARMED | ACPI_NFIT_MEM_MAP_FAILED)
 
 #define NVDIMM_FAMILY_MAX NVDIMM_FAMILY_HYPERV
+#define NVDIMM_CMD_MAX 31
 
 #define NVDIMM_STANDARD_CMDMASK \
 (1 << ND_CMD_SMART | 1 << ND_CMD_SMART_THRESHOLD | 1 << ND_CMD_DIMM_FLAGS \
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/numa.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/numa.c
@@ -31,7 +31,7 @@
 
 int pxm_to_node(int pxm)
 {
-	if (pxm < 0)
+	if (pxm < 0 || pxm >= MAX_PXM_DOMAINS || numa_off)
 		return NUMA_NO_NODE;
 	return pxm_to_node_map[pxm];
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/osi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/osi.c
@@ -468,6 +468,77 @@
 	},
 
 	/*
+	 * The following Lenovo models have a broken workaround in the
+	 * acpi_video backlight implementation to meet the Windows 8
+	 * requirement of 101 backlight levels. Reverting to pre-Win8
+	 * behavior fixes the problem.
+	 */
+	{
+	.callback = dmi_disable_osi_win8,
+	.ident = "Lenovo ThinkPad L430",
+	.matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+		     DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L430"),
+		},
+	},
+	{
+	.callback = dmi_disable_osi_win8,
+	.ident = "Lenovo ThinkPad T430",
+	.matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+		     DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T430"),
+		},
+	},
+	{
+	.callback = dmi_disable_osi_win8,
+	.ident = "Lenovo ThinkPad T430s",
+	.matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+		     DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T430s"),
+		},
+	},
+	{
+	.callback = dmi_disable_osi_win8,
+	.ident = "Lenovo ThinkPad T530",
+	.matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+		     DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T530"),
+		},
+	},
+	{
+	.callback = dmi_disable_osi_win8,
+	.ident = "Lenovo ThinkPad W530",
+	.matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+		     DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W530"),
+		},
+	},
+	{
+	.callback = dmi_disable_osi_win8,
+	.ident = "Lenovo ThinkPad X1 Carbon",
+	.matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+		     DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X1 Carbon"),
+		},
+	},
+	{
+	.callback = dmi_disable_osi_win8,
+	.ident = "Lenovo ThinkPad X230",
+	.matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+		     DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X230"),
+		},
+	},
+	{
+	.callback = dmi_disable_osi_win8,
+	.ident = "Lenovo ThinkPad Edge E330",
+	.matches = {
+		     DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+		     DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad Edge E330"),
+		},
+	},
+
+	/*
 	 * BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
 	 * Linux ignores it, except for the machines enumerated below.
 	 */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/osl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/osl.c
@@ -374,19 +374,21 @@
 }
 EXPORT_SYMBOL_GPL(acpi_os_map_memory);
 
-static void acpi_os_drop_map_ref(struct acpi_ioremap *map)
+/* Must be called with mutex_lock(&acpi_ioremap_lock) */
+static unsigned long acpi_os_drop_map_ref(struct acpi_ioremap *map)
 {
-	if (!--map->refcount)
+	unsigned long refcount = --map->refcount;
+
+	if (!refcount)
 		list_del_rcu(&map->list);
+	return refcount;
 }
 
 static void acpi_os_map_cleanup(struct acpi_ioremap *map)
 {
-	if (!map->refcount) {
-		synchronize_rcu_expedited();
-		acpi_unmap(map->phys, map->virt);
-		kfree(map);
-	}
+	synchronize_rcu_expedited();
+	acpi_unmap(map->phys, map->virt);
+	kfree(map);
 }
 
 /**
@@ -406,6 +408,7 @@
 void __ref acpi_os_unmap_iomem(void __iomem *virt, acpi_size size)
 {
 	struct acpi_ioremap *map;
+	unsigned long refcount;
 
 	if (!acpi_permanent_mmap) {
 		__acpi_unmap_table(virt, size);
@@ -419,10 +422,11 @@
 		WARN(true, PREFIX "%s: bad address %p\n", __func__, virt);
 		return;
 	}
-	acpi_os_drop_map_ref(map);
+	refcount = acpi_os_drop_map_ref(map);
 	mutex_unlock(&acpi_ioremap_lock);
 
-	acpi_os_map_cleanup(map);
+	if (!refcount)
+		acpi_os_map_cleanup(map);
 }
 EXPORT_SYMBOL_GPL(acpi_os_unmap_iomem);
 
@@ -457,6 +461,7 @@
 {
 	u64 addr;
 	struct acpi_ioremap *map;
+	unsigned long refcount;
 
 	if (gas->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
 		return;
@@ -472,10 +477,11 @@
 		mutex_unlock(&acpi_ioremap_lock);
 		return;
 	}
-	acpi_os_drop_map_ref(map);
+	refcount = acpi_os_drop_map_ref(map);
 	mutex_unlock(&acpi_ioremap_lock);
 
-	acpi_os_map_cleanup(map);
+	if (!refcount)
+		acpi_os_map_cleanup(map);
 }
 EXPORT_SYMBOL(acpi_os_unmap_generic_address);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/pci_mcfg.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/pci_mcfg.c
@@ -41,6 +41,8 @@
 static struct mcfg_fixup mcfg_quirks[] = {
 /*	{ OEM_ID, OEM_TABLE_ID, REV, SEGMENT, BUS_RANGE, ops, cfgres }, */
 
+#ifdef CONFIG_ARM64
+
 #define AL_ECAM(table_id, rev, seg, ops) \
 	{ "AMAZON", table_id, rev, seg, MCFG_BUS_ANY, ops }
 
@@ -142,6 +144,27 @@
 	XGENE_V2_ECAM_MCFG(4, 0),
 	XGENE_V2_ECAM_MCFG(4, 1),
 	XGENE_V2_ECAM_MCFG(4, 2),
+
+#define ALTRA_ECAM_QUIRK(rev, seg) \
+	{ "Ampere", "Altra   ", rev, seg, MCFG_BUS_ANY, &pci_32b_read_ops }
+
+	ALTRA_ECAM_QUIRK(1, 0),
+	ALTRA_ECAM_QUIRK(1, 1),
+	ALTRA_ECAM_QUIRK(1, 2),
+	ALTRA_ECAM_QUIRK(1, 3),
+	ALTRA_ECAM_QUIRK(1, 4),
+	ALTRA_ECAM_QUIRK(1, 5),
+	ALTRA_ECAM_QUIRK(1, 6),
+	ALTRA_ECAM_QUIRK(1, 7),
+	ALTRA_ECAM_QUIRK(1, 8),
+	ALTRA_ECAM_QUIRK(1, 9),
+	ALTRA_ECAM_QUIRK(1, 10),
+	ALTRA_ECAM_QUIRK(1, 11),
+	ALTRA_ECAM_QUIRK(1, 12),
+	ALTRA_ECAM_QUIRK(1, 13),
+	ALTRA_ECAM_QUIRK(1, 14),
+	ALTRA_ECAM_QUIRK(1, 15),
+#endif /* ARM64 */
 };
 
 static char mcfg_oem_id[ACPI_OEM_ID_SIZE];
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/pmic/intel_pmic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/pmic/intel_pmic.c
@@ -211,31 +211,36 @@
 		void *handler_context, void *region_context)
 {
 	struct intel_pmic_opregion *opregion = region_context;
-	int result = 0;
+	int result = -EINVAL;
 
-	switch (address) {
-	case 0:
-		return AE_OK;
-	case 1:
-		opregion->ctx.addr |= (*value64 & 0xff) << 8;
-		return AE_OK;
-	case 2:
-		opregion->ctx.addr |= *value64 & 0xff;
-		return AE_OK;
-	case 3:
-		opregion->ctx.val = *value64 & 0xff;
-		return AE_OK;
-	case 4:
-		if (*value64) {
-			result = regmap_write(opregion->regmap, opregion->ctx.addr,
-					      opregion->ctx.val);
-		} else {
-			result = regmap_read(opregion->regmap, opregion->ctx.addr,
-					     &opregion->ctx.val);
-			if (result == 0)
-				*value64 = opregion->ctx.val;
+	if (function == ACPI_WRITE) {
+		switch (address) {
+		case 0:
+			return AE_OK;
+		case 1:
+			opregion->ctx.addr |= (*value64 & 0xff) << 8;
+			return AE_OK;
+		case 2:
+			opregion->ctx.addr |= *value64 & 0xff;
+			return AE_OK;
+		case 3:
+			opregion->ctx.val = *value64 & 0xff;
+			return AE_OK;
+		case 4:
+			if (*value64) {
+				result = regmap_write(opregion->regmap, opregion->ctx.addr,
+						      opregion->ctx.val);
+			} else {
+				result = regmap_read(opregion->regmap, opregion->ctx.addr,
+						     &opregion->ctx.val);
+			}
+			opregion->ctx.addr = 0;
 		}
-		memset(&opregion->ctx, 0x00, sizeof(opregion->ctx));
+	}
+
+	if (function == ACPI_READ && address == 3) {
+		*value64 = opregion->ctx.val;
+		return AE_OK;
 	}
 
 	if (result < 0) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/pmic/tps68470_pmic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/pmic/tps68470_pmic.c
@@ -376,10 +376,8 @@
 	struct tps68470_pmic_opregion *opregion;
 	acpi_status status;
 
-	if (!dev || !tps68470_regmap) {
-		dev_warn(dev, "dev or regmap is NULL\n");
-		return -EINVAL;
-	}
+	if (!tps68470_regmap)
+		return dev_err_probe(dev, -EINVAL, "regmap is missing\n");
 
 	if (!handle) {
 		dev_warn(dev, "acpi handle is NULL\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/power.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/power.c
@@ -888,15 +888,16 @@
 	kfree(resource);
 }
 
-static ssize_t acpi_power_in_use_show(struct device *dev,
-				      struct device_attribute *attr,
-				      char *buf) {
+static ssize_t resource_in_use_show(struct device *dev,
+				    struct device_attribute *attr,
+				    char *buf)
+{
 	struct acpi_power_resource *resource;
 
 	resource = to_power_resource(to_acpi_device(dev));
 	return sprintf(buf, "%u\n", !!resource->ref_count);
 }
-static DEVICE_ATTR(resource_in_use, 0444, acpi_power_in_use_show, NULL);
+static DEVICE_ATTR_RO(resource_in_use);
 
 static void acpi_power_sysfs_remove(struct acpi_device *device)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/processor_idle.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/processor_idle.c
@@ -540,10 +540,33 @@
 	return;
 }
 
+static void acpi_cst_latency_sort(struct acpi_processor_cx *states, size_t length)
+{
+	int i, j, k;
+
+	for (i = 1; i < length; i++) {
+		if (!states[i].valid)
+			continue;
+
+		for (j = i - 1, k = i; j >= 0; j--) {
+			if (!states[j].valid)
+				continue;
+
+			if (states[j].latency > states[k].latency)
+				swap(states[j].latency, states[k].latency);
+
+			k = j;
+		}
+	}
+}
+
 static int acpi_processor_power_verify(struct acpi_processor *pr)
 {
 	unsigned int i;
 	unsigned int working = 0;
+	unsigned int last_latency = 0;
+	unsigned int last_type = 0;
+	bool buggy_latency = false;
 
 	pr->power.timer_broadcast_on_state = INT_MAX;
 
@@ -567,12 +590,21 @@
 		}
 		if (!cx->valid)
 			continue;
+		if (cx->type >= last_type && cx->latency < last_latency)
+			buggy_latency = true;
+		last_latency = cx->latency;
+		last_type = cx->type;
 
 		lapic_timer_check_state(i, pr, cx);
 		tsc_check_state(cx->type);
 		working++;
 	}
 
+	if (buggy_latency) {
+		pr_notice("FW issue: working around C-state latencies out of order\n");
+		acpi_cst_latency_sort(&pr->power.states[1], max_cstate);
+	}
+
 	lapic_timer_propagate_broadcast(pr);
 
 	return (working);
@@ -642,6 +674,36 @@
 	return bm_status;
 }
 
+static void wait_for_freeze(void)
+{
+#ifdef	CONFIG_X86
+	/* No delay is needed if we are in guest */
+	if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
+		return;
+	/*
+	 * Modern (>=Nehalem) Intel systems use ACPI via intel_idle,
+	 * not this code.  Assume that any Intel systems using this
+	 * are ancient and may need the dummy wait.  This also assumes
+	 * that the motivating chipset issue was Intel-only.
+	 */
+	if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
+		return;
+#endif
+	/*
+	 * Dummy wait op - must do something useless after P_LVL2 read
+	 * because chipsets cannot guarantee that STPCLK# signal gets
+	 * asserted in time to freeze execution properly
+	 *
+	 * This workaround has been in place since the original ACPI
+	 * implementation was merged, circa 2002.
+	 *
+	 * If a profile is pointing to this instruction, please first
+	 * consider moving your system to a more modern idle
+	 * mechanism.
+	 */
+	inl(acpi_gbl_FADT.xpm_timer_block.address);
+}
+
 /**
  * acpi_idle_do_entry - enter idle state using the appropriate method
  * @cx: cstate data
@@ -658,10 +720,7 @@
 	} else {
 		/* IO port based C-state */
 		inb(cx->address);
-		/* Dummy wait op - must do something useless after P_LVL2 read
-		   because chipsets cannot guarantee that STPCLK# signal
-		   gets asserted in time to freeze execution properly. */
-		inl(acpi_gbl_FADT.xpm_timer_block.address);
+		wait_for_freeze();
 	}
 }
 
@@ -682,8 +741,7 @@
 			safe_halt();
 		else if (cx->entry_method == ACPI_CSTATE_SYSTEMIO) {
 			inb(cx->address);
-			/* See comment in acpi_idle_do_entry() */
-			inl(acpi_gbl_FADT.xpm_timer_block.address);
+			wait_for_freeze();
 		} else
 			return -ENODEV;
 	}
@@ -1161,6 +1219,11 @@
 	return 0;
 }
 
+int __weak acpi_processor_ffh_lpi_probe(unsigned int cpu)
+{
+	return -EOPNOTSUPP;
+}
+
 static int acpi_processor_get_lpi_info(struct acpi_processor *pr)
 {
 	int ret, i;
@@ -1169,6 +1232,11 @@
 	struct acpi_device *d = NULL;
 	struct acpi_lpi_states_array info[2], *tmp, *prev, *curr;
 
+	/* make sure our architecture has support */
+	ret = acpi_processor_ffh_lpi_probe(pr->id);
+	if (ret == -EOPNOTSUPP)
+		return ret;
+
 	if (!osc_pc_lpi_support_confirmed)
 		return -EOPNOTSUPP;
 
@@ -1220,11 +1288,6 @@
 	return 0;
 }
 
-int __weak acpi_processor_ffh_lpi_probe(unsigned int cpu)
-{
-	return -ENODEV;
-}
-
 int __weak acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi)
 {
 	return -ENODEV;
@@ -1486,6 +1549,8 @@
 		acpi_processor_registered--;
 		if (acpi_processor_registered == 0)
 			cpuidle_unregister_driver(&acpi_idle_driver);
+
+		kfree(dev);
 	}
 
 	pr->flags.power_setup_done = 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/processor_perflib.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/processor_perflib.c
@@ -56,6 +56,8 @@
 {
 	acpi_status status = 0;
 	unsigned long long ppc = 0;
+	s32 qos_value;
+	int index;
 	int ret;
 
 	if (!pr)
@@ -75,17 +77,30 @@
 		return -ENODEV;
 	}
 
+	index = ppc;
+
+	if (pr->performance_platform_limit == index ||
+	    ppc >= pr->performance->state_count)
+		return 0;
+
 	pr_debug("CPU %d: _PPC is %d - frequency %s limited\n", pr->id,
-		       (int)ppc, ppc ? "" : "not");
+		 index, index ? "is" : "is not");
 
-	pr->performance_platform_limit = (int)ppc;
+	pr->performance_platform_limit = index;
 
-	if (ppc >= pr->performance->state_count ||
-	    unlikely(!freq_qos_request_active(&pr->perflib_req)))
+	if (unlikely(!freq_qos_request_active(&pr->perflib_req)))
 		return 0;
 
-	ret = freq_qos_update_request(&pr->perflib_req,
-			pr->performance->states[ppc].core_frequency * 1000);
+	/*
+	 * If _PPC returns 0, it means that all of the available states can be
+	 * used ("no limit").
+	 */
+	if (index == 0)
+		qos_value = FREQ_QOS_MAX_DEFAULT_VALUE;
+	else
+		qos_value = pr->performance->states[index].core_frequency * 1000;
+
+	ret = freq_qos_update_request(&pr->perflib_req, qos_value);
 	if (ret < 0) {
 		pr_warn("Failed to update perflib freq constraint: CPU%d (%d)\n",
 			pr->id, ret);
@@ -168,9 +183,16 @@
 		if (!pr)
 			continue;
 
+		/*
+		 * Reset performance_platform_limit in case there is a stale
+		 * value in it, so as to make it match the "no limit" QoS value
+		 * below.
+		 */
+		pr->performance_platform_limit = 0;
+
 		ret = freq_qos_add_request(&policy->constraints,
-					   &pr->perflib_req,
-					   FREQ_QOS_MAX, INT_MAX);
+					   &pr->perflib_req, FREQ_QOS_MAX,
+					   FREQ_QOS_MAX_DEFAULT_VALUE);
 		if (ret < 0)
 			pr_err("Failed to add freq constraint for CPU%d (%d)\n",
 			       cpu, ret);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/processor_thermal.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/processor_thermal.c
@@ -150,7 +150,7 @@
 	unsigned int cpu;
 
 	for_each_cpu(cpu, policy->related_cpus) {
-		struct acpi_processor *pr = per_cpu(processors, policy->cpu);
+		struct acpi_processor *pr = per_cpu(processors, cpu);
 
 		if (pr)
 			freq_qos_remove_request(&pr->thermal_req);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/processor_throttling.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/processor_throttling.c
@@ -897,13 +897,6 @@
 	return pr->throttling.acpi_processor_get_throttling(pr);
 }
 
-static int call_on_cpu(int cpu, long (*fn)(void *), void *arg, bool direct)
-{
-	if (direct || (is_percpu_thread() && cpu == smp_processor_id()))
-		return fn(arg);
-	return work_on_cpu(cpu, fn, arg);
-}
-
 static int acpi_processor_get_throttling(struct acpi_processor *pr)
 {
 	if (!pr)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/property.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/property.c
@@ -152,10 +152,10 @@
 	return acpi_nondev_subnode_data_ok(handle, link, list, parent);
 }
 
-static int acpi_add_nondev_subnodes(acpi_handle scope,
-				    const union acpi_object *links,
-				    struct list_head *list,
-				    struct fwnode_handle *parent)
+static bool acpi_add_nondev_subnodes(acpi_handle scope,
+				     const union acpi_object *links,
+				     struct list_head *list,
+				     struct fwnode_handle *parent)
 {
 	bool ret = false;
 	int i;
@@ -430,6 +430,16 @@
 		acpi_extract_apple_properties(adev);
 }
 
+static void acpi_free_device_properties(struct list_head *list)
+{
+	struct acpi_device_properties *props, *tmp;
+
+	list_for_each_entry_safe(props, tmp, list, list) {
+		list_del(&props->list);
+		kfree(props);
+	}
+}
+
 static void acpi_destroy_nondev_subnodes(struct list_head *list)
 {
 	struct acpi_data_node *dn, *next;
@@ -442,22 +452,18 @@
 		wait_for_completion(&dn->kobj_done);
 		list_del(&dn->sibling);
 		ACPI_FREE((void *)dn->data.pointer);
+		acpi_free_device_properties(&dn->data.properties);
 		kfree(dn);
 	}
 }
 
 void acpi_free_properties(struct acpi_device *adev)
 {
-	struct acpi_device_properties *props, *tmp;
-
 	acpi_destroy_nondev_subnodes(&adev->data.subnodes);
 	ACPI_FREE((void *)adev->data.pointer);
 	adev->data.of_compatible = NULL;
 	adev->data.pointer = NULL;
-	list_for_each_entry_safe(props, tmp, &adev->data.properties, list) {
-		list_del(&props->list);
-		kfree(props);
-	}
+	acpi_free_device_properties(&adev->data.properties);
 }
 
 /**
@@ -640,6 +646,7 @@
  * @index: Index of the reference to return
  * @num_args: Maximum number of arguments after each reference
  * @args: Location to store the returned reference with optional arguments
+ *	  (may be NULL)
  *
  * Find property with @name, verifify that it is a package containing at least
  * one object reference and if so, store the ACPI device object pointer to the
@@ -692,12 +699,15 @@
 	 */
 	if (obj->type == ACPI_TYPE_LOCAL_REFERENCE) {
 		if (index)
-			return -EINVAL;
+			return -ENOENT;
 
 		ret = acpi_bus_get_device(obj->reference.handle, &device);
 		if (ret)
 			return ret == -ENODEV ? -EINVAL : ret;
 
+		if (!args)
+			return 0;
+
 		args->fwnode = acpi_fwnode_handle(device);
 		args->nargs = 0;
 		return 0;
@@ -794,9 +804,6 @@
 	const union acpi_object *obj;
 	int ret;
 
-	if (!val)
-		return -EINVAL;
-
 	if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64) {
 		ret = acpi_data_get_property(data, propname, ACPI_TYPE_INTEGER, &obj);
 		if (ret)
@@ -806,28 +813,43 @@
 		case DEV_PROP_U8:
 			if (obj->integer.value > U8_MAX)
 				return -EOVERFLOW;
-			*(u8 *)val = obj->integer.value;
+
+			if (val)
+				*(u8 *)val = obj->integer.value;
+
 			break;
 		case DEV_PROP_U16:
 			if (obj->integer.value > U16_MAX)
 				return -EOVERFLOW;
-			*(u16 *)val = obj->integer.value;
+
+			if (val)
+				*(u16 *)val = obj->integer.value;
+
 			break;
 		case DEV_PROP_U32:
 			if (obj->integer.value > U32_MAX)
 				return -EOVERFLOW;
-			*(u32 *)val = obj->integer.value;
+
+			if (val)
+				*(u32 *)val = obj->integer.value;
+
 			break;
 		default:
-			*(u64 *)val = obj->integer.value;
+			if (val)
+				*(u64 *)val = obj->integer.value;
+
 			break;
 		}
+
+		if (!val)
+			return 1;
 	} else if (proptype == DEV_PROP_STRING) {
 		ret = acpi_data_get_property(data, propname, ACPI_TYPE_STRING, &obj);
 		if (ret)
 			return ret;
 
-		*(char **)val = obj->string.pointer;
+		if (val)
+			*(char **)val = obj->string.pointer;
 
 		return 1;
 	} else {
@@ -841,7 +863,7 @@
 {
 	int ret;
 
-	if (!adev)
+	if (!adev || !val)
 		return -EINVAL;
 
 	ret = acpi_data_prop_read_single(&adev->data, propname, proptype, val);
@@ -935,10 +957,20 @@
 	const union acpi_object *items;
 	int ret;
 
-	if (val && nval == 1) {
+	if (nval == 1 || !val) {
 		ret = acpi_data_prop_read_single(data, propname, proptype, val);
-		if (ret >= 0)
+		/*
+		 * The overflow error means that the property is there and it is
+		 * single-value, but its type does not match, so return.
+		 */
+		if (ret >= 0 || ret == -EOVERFLOW)
 			return ret;
+
+		/*
+		 * Reading this property as a single-value one failed, but its
+		 * value may still be represented as one-element array, so
+		 * continue.
+		 */
 	}
 
 	ret = acpi_data_get_property_array(data, propname, ACPI_TYPE_ANY, &obj);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/resource.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/resource.c
@@ -16,6 +16,7 @@
 #include <linux/ioport.h>
 #include <linux/slab.h>
 #include <linux/irq.h>
+#include <linux/dmi.h>
 
 #ifdef CONFIG_X86
 #define valid_IRQ(i) (((i) != 0) && ((i) != 2))
@@ -249,6 +250,9 @@
 	switch (addr->resource_type) {
 	case ACPI_MEMORY_RANGE:
 		acpi_dev_memresource_flags(res, len, wp);
+
+		if (addr->info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
+			res->flags |= IORESOURCE_PREFETCH;
 		break;
 	case ACPI_IO_RANGE:
 		acpi_dev_ioresource_flags(res, len, iodec,
@@ -264,9 +268,6 @@
 	if (addr->producer_consumer == ACPI_PRODUCER)
 		res->flags |= IORESOURCE_WINDOW;
 
-	if (addr->info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
-		res->flags |= IORESOURCE_PREFETCH;
-
 	return !(res->flags & IORESOURCE_DISABLED);
 }
 
@@ -380,21 +381,220 @@
 }
 EXPORT_SYMBOL_GPL(acpi_dev_get_irq_type);
 
-static void acpi_dev_irqresource_disabled(struct resource *res, u32 gsi)
+static const struct dmi_system_id medion_laptop[] = {
+	{
+		.ident = "MEDION P15651",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
+			DMI_MATCH(DMI_BOARD_NAME, "M15T"),
+		},
+	},
+	{
+		.ident = "MEDION S17405",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
+			DMI_MATCH(DMI_BOARD_NAME, "M17T"),
+		},
+	},
+	{ }
+};
+
+static const struct dmi_system_id asus_laptop[] = {
+	{
+		.ident = "Asus Vivobook K3402ZA",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_BOARD_NAME, "K3402ZA"),
+		},
+	},
+	{
+		.ident = "Asus Vivobook K3502ZA",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_BOARD_NAME, "K3502ZA"),
+		},
+	},
+	{
+		.ident = "Asus Vivobook S5402ZA",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_BOARD_NAME, "S5402ZA"),
+		},
+	},
+	{
+		.ident = "Asus Vivobook S5602ZA",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_BOARD_NAME, "S5602ZA"),
+		},
+	},
+	{
+		.ident = "Asus ExpertBook B1402CBA",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_BOARD_NAME, "B1402CBA"),
+		},
+	},
+	{
+		.ident = "Asus ExpertBook B1502CBA",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_BOARD_NAME, "B1502CBA"),
+		},
+	},
+	{
+		.ident = "Asus ExpertBook B2402CBA",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_BOARD_NAME, "B2402CBA"),
+		},
+	},
+	{
+		/* Asus Vivobook X1404VAP */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_BOARD_NAME, "X1404VAP"),
+		},
+	},
+	{
+		/* Asus Vivobook X1504VAP */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_BOARD_NAME, "X1504VAP"),
+		},
+	},
+	{
+		/* Asus Vivobook X1704VAP */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_BOARD_NAME, "X1704VAP"),
+		},
+	},
+	{
+		/* TongFang GMxXGxx/TUXEDO Polaris 15 Gen5 AMD */
+		.matches = {
+			DMI_MATCH(DMI_BOARD_NAME, "GMxXGxx"),
+		},
+	},
+	{
+		/* Asus ExpertBook B1402CVA */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_BOARD_NAME, "B1402CVA"),
+		},
+	},
+	{
+		/* TongFang GMxXGxX/TUXEDO Polaris 15 Gen5 AMD */
+		.matches = {
+			DMI_MATCH(DMI_BOARD_NAME, "GMxXGxX"),
+		},
+	},
+	{
+		/* TongFang GMxXGxx sold as Eluktronics Inc. RP-15 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Eluktronics Inc."),
+			DMI_MATCH(DMI_BOARD_NAME, "RP-15"),
+		},
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Eluktronics Inc."),
+			DMI_MATCH(DMI_BOARD_NAME, "MECH-17"),
+		},
+	},
+	{
+		/* TongFang GM6XGxX/TUXEDO Stellaris 16 Gen5 AMD */
+		.matches = {
+			DMI_MATCH(DMI_BOARD_NAME, "GM6XGxX"),
+		},
+	},
+	{
+		.ident = "Asus ExpertBook B2502",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_BOARD_NAME, "B2502CBA"),
+		},
+	},
+	{
+		/* TongFang GXxHRXx/TUXEDO InfinityBook Pro Gen9 AMD */
+		.matches = {
+			DMI_MATCH(DMI_BOARD_NAME, "GXxHRXx"),
+		},
+	},
+	{
+		/* Asus ExpertBook B2502CVA */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_BOARD_NAME, "B2502CVA"),
+		},
+	},
+	{
+		/* TongFang GMxHGxx/TUXEDO Stellaris Slim Gen1 AMD */
+		.matches = {
+			DMI_MATCH(DMI_BOARD_NAME, "GMxHGxx"),
+		},
+	},
+	{
+		/* LG Electronics 16T90SP */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"),
+			DMI_MATCH(DMI_BOARD_NAME, "16T90SP"),
+		},
+	},
+	{
+		/*
+		 * TongFang GM5HG0A in case of the SKIKK Vanaheim relabel the
+		 * board-name is changed, so check OEM strings instead. Note
+		 * OEM string matches are always exact matches.
+		 * https://bugzilla.kernel.org/show_bug.cgi?id=219614
+		 */
+		.matches = {
+			DMI_EXACT_MATCH(DMI_OEM_STRING, "GM5HG0A"),
+		},
+	},
+	{ }
+};
+
+struct irq_override_cmp {
+	const struct dmi_system_id *system;
+	unsigned char irq;
+	unsigned char triggering;
+	unsigned char polarity;
+	unsigned char shareable;
+};
+
+static const struct irq_override_cmp skip_override_table[] = {
+	{ medion_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0 },
+	{ asus_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0 },
+};
+
+static bool acpi_dev_irq_override(u32 gsi, u8 triggering, u8 polarity,
+				  u8 shareable)
 {
-	res->start = gsi;
-	res->end = gsi;
-	res->flags = IORESOURCE_IRQ | IORESOURCE_DISABLED | IORESOURCE_UNSET;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(skip_override_table); i++) {
+		const struct irq_override_cmp *entry = &skip_override_table[i];
+
+		if (dmi_check_system(entry->system) &&
+		    entry->irq == gsi &&
+		    entry->triggering == triggering &&
+		    entry->polarity == polarity &&
+		    entry->shareable == shareable)
+			return false;
+	}
+
+	return true;
 }
 
 static void acpi_dev_get_irqresource(struct resource *res, u32 gsi,
 				     u8 triggering, u8 polarity, u8 shareable,
-				     bool legacy)
+				     bool check_override)
 {
 	int irq, p, t;
 
 	if (!valid_IRQ(gsi)) {
-		acpi_dev_irqresource_disabled(res, gsi);
+		irqresource_disabled(res, gsi);
 		return;
 	}
 
@@ -408,7 +608,9 @@
 	 * using extended IRQ descriptors we take the IRQ configuration
 	 * from _CRS directly.
 	 */
-	if (legacy && !acpi_get_override_irq(gsi, &t, &p)) {
+	if (check_override &&
+	    acpi_dev_irq_override(gsi, triggering, polarity, shareable) &&
+	    !acpi_get_override_irq(gsi, &t, &p)) {
 		u8 trig = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
 		u8 pol = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
 
@@ -426,7 +628,7 @@
 		res->start = irq;
 		res->end = irq;
 	} else {
-		acpi_dev_irqresource_disabled(res, gsi);
+		irqresource_disabled(res, gsi);
 	}
 }
 
@@ -463,7 +665,7 @@
 		 */
 		irq = &ares->data.irq;
 		if (index >= irq->interrupt_count) {
-			acpi_dev_irqresource_disabled(res, 0);
+			irqresource_disabled(res, 0);
 			return false;
 		}
 		acpi_dev_get_irqresource(res, irq->interrupts[index],
@@ -473,7 +675,7 @@
 	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
 		ext_irq = &ares->data.extended_irq;
 		if (index >= ext_irq->interrupt_count) {
-			acpi_dev_irqresource_disabled(res, 0);
+			irqresource_disabled(res, 0);
 			return false;
 		}
 		if (is_gsi(ext_irq))
@@ -481,7 +683,7 @@
 					 ext_irq->triggering, ext_irq->polarity,
 					 ext_irq->shareable, false);
 		else
-			acpi_dev_irqresource_disabled(res, 0);
+			irqresource_disabled(res, 0);
 		break;
 	default:
 		res->flags = 0;
@@ -541,7 +743,7 @@
 		ret = c->preproc(ares, c->preproc_data);
 		if (ret < 0) {
 			c->error = ret;
-			return AE_CTRL_TERMINATE;
+			return AE_ABORT_METHOD;
 		} else if (ret > 0) {
 			return AE_OK;
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/sbs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/sbs.c
@@ -80,7 +80,6 @@
 	u16 spec;
 	u8 id;
 	u8 present:1;
-	u8 have_sysfs_alarm:1;
 };
 
 #define to_acpi_battery(x) power_supply_get_drvdata(x)
@@ -465,12 +464,18 @@
 	return count;
 }
 
-static const struct device_attribute alarm_attr = {
+static struct device_attribute alarm_attr = {
 	.attr = {.name = "alarm", .mode = 0644},
 	.show = acpi_battery_alarm_show,
 	.store = acpi_battery_alarm_store,
 };
 
+static struct attribute *acpi_battery_attrs[] = {
+	&alarm_attr.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(acpi_battery);
+
 /* --------------------------------------------------------------------------
                                  Driver Interface
    -------------------------------------------------------------------------- */
@@ -512,7 +517,10 @@
 static int acpi_battery_add(struct acpi_sbs *sbs, int id)
 {
 	struct acpi_battery *battery = &sbs->battery[id];
-	struct power_supply_config psy_cfg = { .drv_data = battery, };
+	struct power_supply_config psy_cfg = {
+		.drv_data = battery,
+		.attr_grp = acpi_battery_groups,
+	};
 	int result;
 
 	battery->id = id;
@@ -542,10 +550,6 @@
 		goto end;
 	}
 
-	result = device_create_file(&battery->bat->dev, &alarm_attr);
-	if (result)
-		goto end;
-	battery->have_sysfs_alarm = 1;
       end:
 	printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n",
 	       ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
@@ -557,11 +561,8 @@
 {
 	struct acpi_battery *battery = &sbs->battery[id];
 
-	if (battery->bat) {
-		if (battery->have_sysfs_alarm)
-			device_remove_file(&battery->bat->dev, &alarm_attr);
+	if (battery->bat)
 		power_supply_unregister(battery->bat);
-	}
 }
 
 static int acpi_charger_add(struct acpi_sbs *sbs)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/scan.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/scan.c
@@ -322,18 +322,14 @@
 		 * again).
 		 */
 		if (adev->handler) {
-			dev_warn(&adev->dev, "Already enumerated\n");
-			return -EALREADY;
+			dev_dbg(&adev->dev, "Already enumerated\n");
+			return 0;
 		}
 		error = acpi_bus_scan(adev->handle);
 		if (error) {
 			dev_warn(&adev->dev, "Namespace scan failure\n");
 			return error;
 		}
-		if (!adev->handler) {
-			dev_warn(&adev->dev, "Enumeration failure\n");
-			error = -ENODEV;
-		}
 	} else {
 		error = acpi_scan_device_not_present(adev);
 	}
@@ -483,10 +479,10 @@
 	list_for_each_entry(acpi_device_bus_id, &acpi_bus_id_list, node)
 		if (!strcmp(acpi_device_bus_id->bus_id,
 			    acpi_device_hid(device))) {
-			if (acpi_device_bus_id->instance_no > 0)
-				acpi_device_bus_id->instance_no--;
-			else {
+			ida_simple_remove(&acpi_device_bus_id->instance_ida, device->pnp.instance_no);
+			if (ida_is_empty(&acpi_device_bus_id->instance_ida)) {
 				list_del(&acpi_device_bus_id->node);
+				kfree_const(acpi_device_bus_id->bus_id);
 				kfree(acpi_device_bus_id);
 			}
 			break;
@@ -586,6 +582,8 @@
 	if (!device)
 		return -EINVAL;
 
+	*device = NULL;
+
 	status = acpi_get_data_full(handle, acpi_scan_drop_device,
 				    (void **)device, callback);
 	if (ACPI_FAILURE(status) || !*device) {
@@ -621,12 +619,38 @@
 	put_device(&adev->dev);
 }
 
+static struct acpi_device_bus_id *acpi_device_bus_id_match(const char *dev_id)
+{
+	struct acpi_device_bus_id *acpi_device_bus_id;
+
+	/* Find suitable bus_id and instance number in acpi_bus_id_list. */
+	list_for_each_entry(acpi_device_bus_id, &acpi_bus_id_list, node) {
+		if (!strcmp(acpi_device_bus_id->bus_id, dev_id))
+			return acpi_device_bus_id;
+	}
+	return NULL;
+}
+
+static int acpi_device_set_name(struct acpi_device *device,
+				struct acpi_device_bus_id *acpi_device_bus_id)
+{
+	struct ida *instance_ida = &acpi_device_bus_id->instance_ida;
+	int result;
+
+	result = ida_simple_get(instance_ida, 0, ACPI_MAX_DEVICE_INSTANCES, GFP_KERNEL);
+	if (result < 0)
+		return result;
+
+	device->pnp.instance_no = result;
+	dev_set_name(&device->dev, "%s:%02x", acpi_device_bus_id->bus_id, result);
+	return 0;
+}
+
 int acpi_device_add(struct acpi_device *device,
 		    void (*release)(struct device *))
 {
+	struct acpi_device_bus_id *acpi_device_bus_id;
 	int result;
-	struct acpi_device_bus_id *acpi_device_bus_id, *new_bus_id;
-	int found = 0;
 
 	if (device->handle) {
 		acpi_status status;
@@ -652,34 +676,39 @@
 	INIT_LIST_HEAD(&device->del_list);
 	mutex_init(&device->physical_node_lock);
 
-	new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL);
-	if (!new_bus_id) {
-		pr_err(PREFIX "Memory allocation error\n");
-		result = -ENOMEM;
-		goto err_detach;
-	}
-
 	mutex_lock(&acpi_device_lock);
-	/*
-	 * Find suitable bus_id and instance number in acpi_bus_id_list
-	 * If failed, create one and link it into acpi_bus_id_list
-	 */
-	list_for_each_entry(acpi_device_bus_id, &acpi_bus_id_list, node) {
-		if (!strcmp(acpi_device_bus_id->bus_id,
-			    acpi_device_hid(device))) {
-			acpi_device_bus_id->instance_no++;
-			found = 1;
-			kfree(new_bus_id);
-			break;
+
+	acpi_device_bus_id = acpi_device_bus_id_match(acpi_device_hid(device));
+	if (acpi_device_bus_id) {
+		result = acpi_device_set_name(device, acpi_device_bus_id);
+		if (result)
+			goto err_unlock;
+	} else {
+		acpi_device_bus_id = kzalloc(sizeof(*acpi_device_bus_id),
+					     GFP_KERNEL);
+		if (!acpi_device_bus_id) {
+			result = -ENOMEM;
+			goto err_unlock;
+		}
+		acpi_device_bus_id->bus_id =
+			kstrdup_const(acpi_device_hid(device), GFP_KERNEL);
+		if (!acpi_device_bus_id->bus_id) {
+			kfree(acpi_device_bus_id);
+			result = -ENOMEM;
+			goto err_unlock;
+		}
+
+		ida_init(&acpi_device_bus_id->instance_ida);
+
+		result = acpi_device_set_name(device, acpi_device_bus_id);
+		if (result) {
+			kfree_const(acpi_device_bus_id->bus_id);
+			kfree(acpi_device_bus_id);
+			goto err_unlock;
 		}
-	}
-	if (!found) {
-		acpi_device_bus_id = new_bus_id;
-		strcpy(acpi_device_bus_id->bus_id, acpi_device_hid(device));
-		acpi_device_bus_id->instance_no = 0;
+
 		list_add_tail(&acpi_device_bus_id->node, &acpi_bus_id_list);
 	}
-	dev_set_name(&device->dev, "%s:%02x", acpi_device_bus_id->bus_id, acpi_device_bus_id->instance_no);
 
 	if (device->parent)
 		list_add_tail(&device->node, &device->parent->children);
@@ -710,9 +739,10 @@
 	if (device->parent)
 		list_del(&device->node);
 	list_del(&device->wakeup_list);
+
+ err_unlock:
 	mutex_unlock(&acpi_device_lock);
 
- err_detach:
 	acpi_detach_data(device->handle, acpi_scan_drop_device);
 	return result;
 }
@@ -919,12 +949,9 @@
 
 		if (buffer.length && package
 		    && package->type == ACPI_TYPE_PACKAGE
-		    && package->package.count) {
-			int err = acpi_extract_power_resources(package, 0,
-							       &ps->resources);
-			if (!err)
-				device->power.flags.power_resources = 1;
-		}
+		    && package->package.count)
+			acpi_extract_power_resources(package, 0, &ps->resources);
+
 		ACPI_FREE(buffer.pointer);
 	}
 
@@ -971,14 +998,27 @@
 		acpi_bus_init_power_state(device, i);
 
 	INIT_LIST_HEAD(&device->power.states[ACPI_STATE_D3_COLD].resources);
-	if (!list_empty(&device->power.states[ACPI_STATE_D3_HOT].resources))
-		device->power.states[ACPI_STATE_D3_COLD].flags.valid = 1;
 
-	/* Set defaults for D0 and D3hot states (always valid) */
+	/* Set the defaults for D0 and D3hot (always supported). */
 	device->power.states[ACPI_STATE_D0].flags.valid = 1;
 	device->power.states[ACPI_STATE_D0].power = 100;
 	device->power.states[ACPI_STATE_D3_HOT].flags.valid = 1;
 
+	/*
+	 * Use power resources only if the D0 list of them is populated, because
+	 * some platforms may provide _PR3 only to indicate D3cold support and
+	 * in those cases the power resources list returned by it may be bogus.
+	 */
+	if (!list_empty(&device->power.states[ACPI_STATE_D0].resources)) {
+		device->power.flags.power_resources = 1;
+		/*
+		 * D3cold is supported if the D3hot list of power resources is
+		 * not empty.
+		 */
+		if (!list_empty(&device->power.states[ACPI_STATE_D3_HOT].resources))
+			device->power.states[ACPI_STATE_D3_COLD].flags.valid = 1;
+	}
+
 	if (acpi_bus_init_power(device))
 		device->flags.power_manageable = 0;
 }
@@ -1533,6 +1573,7 @@
 {
 	struct list_head resource_list;
 	bool is_serial_bus_slave = false;
+	static const struct acpi_device_id ignore_serial_bus_ids[] = {
 	/*
 	 * These devices have multiple I2cSerialBus resources and an i2c-client
 	 * must be instantiated for each, each with its own i2c_device_id.
@@ -1541,11 +1582,18 @@
 	 * drivers/platform/x86/i2c-multi-instantiate.c driver, which knows
 	 * which i2c_device_id to use for each resource.
 	 */
-	static const struct acpi_device_id i2c_multi_instantiate_ids[] = {
 		{"BSG1160", },
 		{"BSG2150", },
 		{"INT33FE", },
 		{"INT3515", },
+	/*
+	 * HIDs of device with an UartSerialBusV2 resource for which userspace
+	 * expects a regular tty cdev to be created (instead of the in kernel
+	 * serdev) and which have a kernel driver which expects a platform_dev
+	 * such as the rfkill-gpio driver.
+	 */
+		{"BCM4752", },
+		{"LNV4752", },
 		{}
 	};
 
@@ -1559,8 +1607,7 @@
 	     fwnode_property_present(&device->fwnode, "baud")))
 		return true;
 
-	/* Instantiate a pdev for the i2c-multi-instantiate drv to bind to */
-	if (!acpi_match_device_ids(device, i2c_multi_instantiate_ids))
+	if (!acpi_match_device_ids(device, ignore_serial_bus_ids))
 		return false;
 
 	INIT_LIST_HEAD(&resource_list);
@@ -2174,6 +2221,7 @@
 	acpi_pci_root_init();
 	acpi_pci_link_init();
 	acpi_processor_init();
+	acpi_platform_init();
 	acpi_lpss_init();
 	acpi_apd_init();
 	acpi_cmos_rtc_init();
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/sleep.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/sleep.c
@@ -361,6 +361,14 @@
 		DMI_MATCH(DMI_PRODUCT_NAME, "80E3"),
 		},
 	},
+	{
+	.callback = init_nvs_save_s3,
+	.ident = "Lenovo G40-45",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "80E1"),
+		},
+	},
 	/*
 	 * ThinkPad X1 Tablet(2016) cannot do suspend-to-idle using
 	 * the Low Power S0 Idle firmware interface (see
@@ -977,23 +985,38 @@
 	return 0;
 }
 
-static void acpi_s2idle_wake(void)
+static bool acpi_s2idle_wake(void)
 {
-	/*
-	 * If IRQD_WAKEUP_ARMED is set for the SCI at this point, the SCI has
-	 * not triggered while suspended, so bail out.
-	 */
-	if (!acpi_sci_irq_valid() ||
-	    irqd_is_wakeup_armed(irq_get_irq_data(acpi_sci_irq)))
-		return;
+	if (!acpi_sci_irq_valid())
+		return pm_wakeup_pending();
+
+	while (pm_wakeup_pending()) {
+		/*
+		 * If IRQD_WAKEUP_ARMED is set for the SCI at this point, the
+		 * SCI has not triggered while suspended, so bail out (the
+		 * wakeup is pending anyway and the SCI is not the source of
+		 * it).
+		 */
+		if (irqd_is_wakeup_armed(irq_get_irq_data(acpi_sci_irq)))
+			return true;
+
+		/*
+		 * If the status bit of any enabled fixed event is set, the
+		 * wakeup is regarded as valid.
+		 */
+		if (acpi_any_fixed_event_status_set())
+			return true;
+
+		/* Check wakeups from drivers sharing the SCI. */
+		if (acpi_check_wakeup_handlers())
+			return true;
+
+		/* Check non-EC GPE wakeups and dispatch the EC GPE. */
+		if (acpi_ec_dispatch_gpe())
+			return true;
 
-	/*
-	 * If there are EC events to process, the wakeup may be a spurious one
-	 * coming from the EC.
-	 */
-	if (acpi_ec_dispatch_gpe()) {
 		/*
-		 * Cancel the wakeup and process all pending events in case
+		 * Cancel the SCI wakeup and process all pending events in case
 		 * there are any wakeup ones in there.
 		 *
 		 * Note that if any non-EC GPEs are active at this point, the
@@ -1001,16 +1024,22 @@
 		 * should be missed by canceling the wakeup here.
 		 */
 		pm_system_cancel_wakeup();
+		acpi_os_wait_events_complete();
+
 		/*
-		 * The EC driver uses the system workqueue and an additional
-		 * special one, so those need to be flushed too.
+		 * The SCI is in the "suspended" state now and it cannot produce
+		 * new wakeup events till the rearming below, so if any of them
+		 * are pending here, they must be resulting from the processing
+		 * of EC events above or coming from somewhere else.
 		 */
-		acpi_os_wait_events_complete(); /* synchronize EC GPE processing */
-		acpi_ec_flush_work();
-		acpi_os_wait_events_complete(); /* synchronize Notify handling */
+		if (pm_wakeup_pending())
+			return true;
 
+		pm_wakeup_clear(acpi_sci_irq);
 		rearm_wake_irq(acpi_sci_irq);
 	}
+
+	return false;
 }
 
 static void acpi_s2idle_restore_early(void)
@@ -1024,6 +1053,14 @@
 
 static void acpi_s2idle_restore(void)
 {
+	/*
+	 * Drain pending events before restoring the working-state configuration
+	 * of GPEs.
+	 */
+	acpi_os_wait_events_complete(); /* synchronize GPE processing */
+	acpi_ec_flush_work(); /* flush the EC driver's workqueues */
+	acpi_os_wait_events_complete(); /* synchronize Notify handling */
+
 	s2idle_wakeup = false;
 
 	acpi_enable_all_runtime_gpes();
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/sleep.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/sleep.h
@@ -2,6 +2,7 @@
 
 extern void acpi_enable_wakeup_devices(u8 sleep_state);
 extern void acpi_disable_wakeup_devices(u8 sleep_state);
+extern bool acpi_check_wakeup_handlers(void);
 
 extern struct list_head acpi_wakeup_device_list;
 extern struct mutex acpi_device_lock;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/sysfs.c
@@ -439,18 +439,29 @@
 {
 	struct acpi_data_attr *data_attr;
 	void __iomem *base;
-	ssize_t rc;
+	ssize_t size;
 
 	data_attr = container_of(bin_attr, struct acpi_data_attr, attr);
+	size = data_attr->attr.size;
 
-	base = acpi_os_map_memory(data_attr->addr, data_attr->attr.size);
+	if (offset < 0)
+		return -EINVAL;
+
+	if (offset >= size)
+		return 0;
+
+	if (count > size - offset)
+		count = size - offset;
+
+	base = acpi_os_map_iomem(data_attr->addr, size);
 	if (!base)
 		return -ENOMEM;
-	rc = memory_read_from_buffer(buf, count, &offset, base,
-				     data_attr->attr.size);
-	acpi_os_unmap_memory(base, data_attr->attr.size);
 
-	return rc;
+	memcpy_fromio(buf, base + offset, count);
+
+	acpi_os_unmap_iomem(base, size);
+
+	return count;
 }
 
 static int acpi_bert_data_init(void *th, struct acpi_data_attr *data_attr)
@@ -819,14 +830,14 @@
  * interface:
  *   echo unmask > /sys/firmware/acpi/interrupts/gpe00
  */
-#define ACPI_MASKABLE_GPE_MAX	0xFF
+#define ACPI_MASKABLE_GPE_MAX	0x100
 static DECLARE_BITMAP(acpi_masked_gpes_map, ACPI_MASKABLE_GPE_MAX) __initdata;
 
 static int __init acpi_gpe_set_masked_gpes(char *val)
 {
 	u8 gpe;
 
-	if (kstrtou8(val, 0, &gpe) || gpe > ACPI_MASKABLE_GPE_MAX)
+	if (kstrtou8(val, 0, &gpe))
 		return -EINVAL;
 	set_bit(gpe, acpi_masked_gpes_map);
 
@@ -838,7 +849,7 @@
 {
 	acpi_handle handle;
 	acpi_status status;
-	u8 gpe;
+	u16 gpe;
 
 	for_each_set_bit(gpe, acpi_masked_gpes_map, ACPI_MASKABLE_GPE_MAX) {
 		status = acpi_get_gpe_device(gpe, &handle);
@@ -938,13 +949,13 @@
 }
 
 static ssize_t
-acpi_show_profile(struct device *dev, struct device_attribute *attr,
+acpi_show_profile(struct kobject *kobj, struct kobj_attribute *attr,
 		  char *buf)
 {
 	return sprintf(buf, "%d\n", acpi_gbl_FADT.preferred_profile);
 }
 
-static const struct device_attribute pm_profile_attr =
+static const struct kobj_attribute pm_profile_attr =
 	__ATTR(pm_profile, S_IRUGO, acpi_show_profile, NULL);
 
 static ssize_t hotplug_enabled_show(struct kobject *kobj,
@@ -993,8 +1004,10 @@
 
 	error = kobject_init_and_add(&hotplug->kobj,
 		&acpi_hotplug_profile_ktype, hotplug_kobj, "%s", name);
-	if (error)
+	if (error) {
+		kobject_put(&hotplug->kobj);
 		goto err_out;
+	}
 
 	kobject_uevent(&hotplug->kobj, KOBJ_ADD);
 	return;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/tables.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/tables.c
@@ -791,7 +791,7 @@
 }
 
 /*
- * acpi_table_init()
+ * acpi_locate_initial_tables()
  *
  * find RSDP, find and checksum SDT/XSDT.
  * checksum all tables, print SDT/XSDT
@@ -799,7 +799,7 @@
  * result: sdt_entry[] is initialized
  */
 
-int __init acpi_table_init(void)
+int __init acpi_locate_initial_tables(void)
 {
 	acpi_status status;
 
@@ -814,9 +814,45 @@
 	status = acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0);
 	if (ACPI_FAILURE(status))
 		return -EINVAL;
-	acpi_table_initrd_scan();
 
+	return 0;
+}
+
+void __init acpi_reserve_initial_tables(void)
+{
+	int i;
+
+	for (i = 0; i < ACPI_MAX_TABLES; i++) {
+		struct acpi_table_desc *table_desc = &initial_tables[i];
+		u64 start = table_desc->address;
+		u64 size = table_desc->length;
+
+		if (!start || !size)
+			break;
+
+		pr_info("Reserving %4s table memory at [mem 0x%llx-0x%llx]\n",
+			table_desc->signature.ascii, start, start + size - 1);
+
+		memblock_reserve(start, size);
+	}
+}
+
+void __init acpi_table_init_complete(void)
+{
+	acpi_table_initrd_scan();
 	check_multiple_madt();
+}
+
+int __init acpi_table_init(void)
+{
+	int ret;
+
+	ret = acpi_locate_initial_tables();
+	if (ret)
+		return ret;
+
+	acpi_table_init_complete();
+
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/thermal.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/thermal.c
@@ -174,6 +174,8 @@
 	int tz_enabled;
 	int kelvin_offset;
 	struct work_struct thermal_check_work;
+	struct mutex thermal_check_lock;
+	refcount_t thermal_check_count;
 };
 
 /* --------------------------------------------------------------------------
@@ -494,17 +496,6 @@
 	return 0;
 }
 
-static void acpi_thermal_check(void *data)
-{
-	struct acpi_thermal *tz = data;
-
-	if (!tz->tz_enabled)
-		return;
-
-	thermal_zone_device_update(tz->thermal_zone,
-				   THERMAL_EVENT_UNSPECIFIED);
-}
-
 /* sys I/F for generic thermal sysfs support */
 
 static int thermal_get_temp(struct thermal_zone_device *thermal, int *temp)
@@ -538,6 +529,8 @@
 	return 0;
 }
 
+static void acpi_thermal_check_fn(struct work_struct *work);
+
 static int thermal_set_mode(struct thermal_zone_device *thermal,
 				enum thermal_device_mode mode)
 {
@@ -563,7 +556,7 @@
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 			"%s kernel ACPI thermal control\n",
 			tz->tz_enabled ? "Enable" : "Disable"));
-		acpi_thermal_check(tz);
+		acpi_thermal_check_fn(&tz->thermal_check_work);
 	}
 	return 0;
 }
@@ -932,6 +925,12 @@
                                  Driver Interface
    -------------------------------------------------------------------------- */
 
+static void acpi_queue_thermal_check(struct acpi_thermal *tz)
+{
+	if (!work_pending(&tz->thermal_check_work))
+		queue_work(acpi_thermal_pm_queue, &tz->thermal_check_work);
+}
+
 static void acpi_thermal_notify(struct acpi_device *device, u32 event)
 {
 	struct acpi_thermal *tz = acpi_driver_data(device);
@@ -942,17 +941,17 @@
 
 	switch (event) {
 	case ACPI_THERMAL_NOTIFY_TEMPERATURE:
-		acpi_thermal_check(tz);
+		acpi_queue_thermal_check(tz);
 		break;
 	case ACPI_THERMAL_NOTIFY_THRESHOLDS:
 		acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_THRESHOLDS);
-		acpi_thermal_check(tz);
+		acpi_queue_thermal_check(tz);
 		acpi_bus_generate_netlink_event(device->pnp.device_class,
 						  dev_name(&device->dev), event, 0);
 		break;
 	case ACPI_THERMAL_NOTIFY_DEVICES:
 		acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_DEVICES);
-		acpi_thermal_check(tz);
+		acpi_queue_thermal_check(tz);
 		acpi_bus_generate_netlink_event(device->pnp.device_class,
 						  dev_name(&device->dev), event, 0);
 		break;
@@ -1052,7 +1051,27 @@
 {
 	struct acpi_thermal *tz = container_of(work, struct acpi_thermal,
 					       thermal_check_work);
-	acpi_thermal_check(tz);
+
+	if (!tz->tz_enabled)
+		return;
+	/*
+	 * In general, it is not sufficient to check the pending bit, because
+	 * subsequent instances of this function may be queued after one of them
+	 * has started running (e.g. if _TMP sleeps).  Avoid bailing out if just
+	 * one of them is running, though, because it may have done the actual
+	 * check some time ago, so allow at least one of them to block on the
+	 * mutex while another one is running the update.
+	 */
+	if (!refcount_dec_not_one(&tz->thermal_check_count))
+		return;
+
+	mutex_lock(&tz->thermal_check_lock);
+
+	thermal_zone_device_update(tz->thermal_zone, THERMAL_EVENT_UNSPECIFIED);
+
+	refcount_inc(&tz->thermal_check_count);
+
+	mutex_unlock(&tz->thermal_check_lock);
 }
 
 static int acpi_thermal_add(struct acpi_device *device)
@@ -1084,6 +1103,8 @@
 	if (result)
 		goto free_memory;
 
+	refcount_set(&tz->thermal_check_count, 3);
+	mutex_init(&tz->thermal_check_lock);
 	INIT_WORK(&tz->thermal_check_work, acpi_thermal_check_fn);
 
 	pr_info(PREFIX "%s [%s] (%ld C)\n", acpi_device_name(device),
@@ -1132,8 +1153,6 @@
 		return -EINVAL;
 
 	for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
-		if (!(&tz->trips.active[i]))
-			break;
 		if (!tz->trips.active[i].flags.valid)
 			break;
 		tz->trips.active[i].flags.enabled = 1;
@@ -1149,7 +1168,7 @@
 		tz->state.active |= tz->trips.active[i].flags.enabled;
 	}
 
-	queue_work(acpi_thermal_pm_queue, &tz->thermal_check_work);
+	acpi_queue_thermal_check(tz);
 
 	return AE_OK;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/video_detect.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/video_detect.c
@@ -143,6 +143,14 @@
 	},
 	{
 	.callback = video_detect_force_vendor,
+	.ident = "GIGABYTE GB-BXBT-2807",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "GB-BXBT-2807"),
+		},
+	},
+	{
+	.callback = video_detect_force_vendor,
 	.ident = "Sony VPCEH3U1E",
 	.matches = {
 		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
@@ -282,6 +290,15 @@
 		DMI_MATCH(DMI_PRODUCT_NAME, "530U4E/540U4E"),
 		},
 	},
+	/* https://bugs.launchpad.net/bugs/1894667 */
+	{
+	 .callback = video_detect_force_video,
+	 .ident = "HP 635 Notebook",
+	 .matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "HP 635 Notebook PC"),
+		},
+	},
 
 	/* Non win8 machines which need native backlight nevertheless */
 	{
@@ -294,12 +311,37 @@
 		},
 	},
 	{
+	 /* https://bugzilla.suse.com/show_bug.cgi?id=1208724 */
+	 .callback = video_detect_force_native,
+	 /* Lenovo Ideapad Z470 */
+	 .matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+		DMI_MATCH(DMI_PRODUCT_VERSION, "IdeaPad Z470"),
+		},
+	},
+	{
 	 /* https://bugzilla.redhat.com/show_bug.cgi?id=1187004 */
 	 .callback = video_detect_force_native,
 	 .ident = "Lenovo Ideapad Z570",
 	 .matches = {
 		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-		DMI_MATCH(DMI_PRODUCT_NAME, "102434U"),
+		DMI_MATCH(DMI_PRODUCT_VERSION, "Ideapad Z570"),
+		},
+	},
+	{
+	 .callback = video_detect_force_native,
+	 .ident = "Lenovo E41-25",
+	 .matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "81FS"),
+		},
+	},
+	{
+	 .callback = video_detect_force_native,
+	 .ident = "Lenovo E41-45",
+	 .matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "82BK"),
 		},
 	},
 	{
@@ -337,6 +379,184 @@
 		},
 	},
 	{
+	 .callback = video_detect_force_native,
+	 .ident = "Acer Aspire 5738z",
+	 .matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5738"),
+		DMI_MATCH(DMI_BOARD_NAME, "JV50"),
+		},
+	},
+	{
+	 /* https://bugzilla.kernel.org/show_bug.cgi?id=207835 */
+	 .callback = video_detect_force_native,
+	 .ident = "Acer TravelMate 5735Z",
+	 .matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 5735Z"),
+		DMI_MATCH(DMI_BOARD_NAME, "BA51_MV"),
+		},
+	},
+	/*
+	 * Clevo NL5xRU and NL5xNU/TUXEDO Aura 15 Gen1 and Gen2 have both a
+	 * working native and video interface. However the default detection
+	 * mechanism first registers the video interface before unregistering
+	 * it again and switching to the native interface during boot. This
+	 * results in a dangling SBIOS request for backlight change for some
+	 * reason, causing the backlight to switch to ~2% once per boot on the
+	 * first power cord connect or disconnect event. Setting the native
+	 * interface explicitly circumvents this buggy behaviour, by avoiding
+	 * the unregistering process.
+	 */
+	{
+	.callback = video_detect_force_native,
+	.ident = "Clevo NL5xRU",
+	.matches = {
+		DMI_MATCH(DMI_BOARD_NAME, "NL5xRU"),
+		},
+	},
+	{
+	.callback = video_detect_force_native,
+	.ident = "Clevo NL5xRU",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
+		DMI_MATCH(DMI_BOARD_NAME, "AURA1501"),
+		},
+	},
+	{
+	.callback = video_detect_force_native,
+	.ident = "Clevo NL5xRU",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
+		DMI_MATCH(DMI_BOARD_NAME, "EDUBOOK1502"),
+		},
+	},
+	{
+	.callback = video_detect_force_native,
+	.ident = "Clevo NL5xNU",
+	.matches = {
+		DMI_MATCH(DMI_BOARD_NAME, "NL5xNU"),
+		},
+	},
+	/*
+	 * The TongFang PF5PU1G, PF4NU1F, PF5NU1G, and PF5LUXG/TUXEDO BA15 Gen10,
+	 * Pulse 14/15 Gen1, and Pulse 15 Gen2 have the same problem as the Clevo
+	 * NL5xRU and NL5xNU/TUXEDO Aura 15 Gen1 and Gen2. See the description
+	 * above.
+	 */
+	{
+	.callback = video_detect_force_native,
+	.ident = "TongFang PF5PU1G",
+	.matches = {
+		DMI_MATCH(DMI_BOARD_NAME, "PF5PU1G"),
+		},
+	},
+	{
+	.callback = video_detect_force_native,
+	.ident = "TongFang PF4NU1F",
+	.matches = {
+		DMI_MATCH(DMI_BOARD_NAME, "PF4NU1F"),
+		},
+	},
+	{
+	.callback = video_detect_force_native,
+	.ident = "TongFang PF4NU1F",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
+		DMI_MATCH(DMI_BOARD_NAME, "PULSE1401"),
+		},
+	},
+	{
+	.callback = video_detect_force_native,
+	.ident = "TongFang PF5NU1G",
+	.matches = {
+		DMI_MATCH(DMI_BOARD_NAME, "PF5NU1G"),
+		},
+	},
+	{
+	.callback = video_detect_force_native,
+	.ident = "TongFang PF5NU1G",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
+		DMI_MATCH(DMI_BOARD_NAME, "PULSE1501"),
+		},
+	},
+	{
+	.callback = video_detect_force_native,
+	.ident = "TongFang PF5LUXG",
+	.matches = {
+		DMI_MATCH(DMI_BOARD_NAME, "PF5LUXG"),
+		},
+	},
+	/*
+	 * More Tongfang devices with the same issue as the Clevo NL5xRU and
+	 * NL5xNU/TUXEDO Aura 15 Gen1 and Gen2. See the description above.
+	 */
+	{
+	.callback = video_detect_force_native,
+	.ident = "TongFang GKxNRxx",
+	.matches = {
+		DMI_MATCH(DMI_BOARD_NAME, "GKxNRxx"),
+		},
+	},
+	{
+	.callback = video_detect_force_native,
+	.ident = "TongFang GKxNRxx",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
+		DMI_MATCH(DMI_BOARD_NAME, "POLARIS1501A1650TI"),
+		},
+	},
+	{
+	.callback = video_detect_force_native,
+	.ident = "TongFang GKxNRxx",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
+		DMI_MATCH(DMI_BOARD_NAME, "POLARIS1501A2060"),
+		},
+	},
+	{
+	.callback = video_detect_force_native,
+	.ident = "TongFang GKxNRxx",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
+		DMI_MATCH(DMI_BOARD_NAME, "POLARIS1701A1650TI"),
+		},
+	},
+	{
+	.callback = video_detect_force_native,
+	.ident = "TongFang GKxNRxx",
+	.matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"),
+		DMI_MATCH(DMI_BOARD_NAME, "POLARIS1701A2060"),
+		},
+	},
+	{
+	.callback = video_detect_force_native,
+	.ident = "TongFang GMxNGxx",
+	.matches = {
+		DMI_MATCH(DMI_BOARD_NAME, "GMxNGxx"),
+		},
+	},
+	{
+	.callback = video_detect_force_native,
+	.ident = "TongFang GMxZGxx",
+	.matches = {
+		DMI_MATCH(DMI_BOARD_NAME, "GMxZGxx"),
+		},
+	},
+	{
+	.callback = video_detect_force_native,
+	.ident = "TongFang GMxRGxx",
+	.matches = {
+		DMI_MATCH(DMI_BOARD_NAME, "GMxRGxx"),
+		},
+	},
+	/*
+	 * Desktops which falsely report a backlight and which our heuristics
+	 * for this do not catch.
+	 */
+	{
 	 .callback = video_detect_force_none,
 	 .ident = "Dell OptiPlex 9020M",
 	 .matches = {
@@ -344,6 +564,14 @@
 		DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 9020M"),
 		},
 	},
+	{
+	 .callback = video_detect_force_none,
+	 .ident = "MSI MS-7721",
+	 .matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "MSI"),
+		DMI_MATCH(DMI_PRODUCT_NAME, "MS-7721"),
+		},
+	},
 	{ },
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/acpi/wakeup.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/acpi/wakeup.c
@@ -12,6 +12,15 @@
 #include "internal.h"
 #include "sleep.h"
 
+struct acpi_wakeup_handler {
+	struct list_head list_node;
+	bool (*wakeup)(void *context);
+	void *context;
+};
+
+static LIST_HEAD(acpi_wakeup_handler_head);
+static DEFINE_MUTEX(acpi_wakeup_handler_mutex);
+
 /*
  * We didn't lock acpi_device_lock in the file, because it invokes oops in
  * suspend/resume and isn't really required as this is called in S-state. At
@@ -96,3 +105,75 @@
 	mutex_unlock(&acpi_device_lock);
 	return 0;
 }
+
+/**
+ * acpi_register_wakeup_handler - Register wakeup handler
+ * @wake_irq: The IRQ through which the device may receive wakeups
+ * @wakeup:   Wakeup-handler to call when the SCI has triggered a wakeup
+ * @context:  Context to pass to the handler when calling it
+ *
+ * Drivers which may share an IRQ with the SCI can use this to register
+ * a handler which returns true when the device they are managing wants
+ * to trigger a wakeup.
+ */
+int acpi_register_wakeup_handler(int wake_irq, bool (*wakeup)(void *context),
+				 void *context)
+{
+	struct acpi_wakeup_handler *handler;
+
+	/*
+	 * If the device is not sharing its IRQ with the SCI, there is no
+	 * need to register the handler.
+	 */
+	if (!acpi_sci_irq_valid() || wake_irq != acpi_sci_irq)
+		return 0;
+
+	handler = kmalloc(sizeof(*handler), GFP_KERNEL);
+	if (!handler)
+		return -ENOMEM;
+
+	handler->wakeup = wakeup;
+	handler->context = context;
+
+	mutex_lock(&acpi_wakeup_handler_mutex);
+	list_add(&handler->list_node, &acpi_wakeup_handler_head);
+	mutex_unlock(&acpi_wakeup_handler_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(acpi_register_wakeup_handler);
+
+/**
+ * acpi_unregister_wakeup_handler - Unregister wakeup handler
+ * @wakeup:   Wakeup-handler passed to acpi_register_wakeup_handler()
+ * @context:  Context passed to acpi_register_wakeup_handler()
+ */
+void acpi_unregister_wakeup_handler(bool (*wakeup)(void *context),
+				    void *context)
+{
+	struct acpi_wakeup_handler *handler;
+
+	mutex_lock(&acpi_wakeup_handler_mutex);
+	list_for_each_entry(handler, &acpi_wakeup_handler_head, list_node) {
+		if (handler->wakeup == wakeup && handler->context == context) {
+			list_del(&handler->list_node);
+			kfree(handler);
+			break;
+		}
+	}
+	mutex_unlock(&acpi_wakeup_handler_mutex);
+}
+EXPORT_SYMBOL_GPL(acpi_unregister_wakeup_handler);
+
+bool acpi_check_wakeup_handlers(void)
+{
+	struct acpi_wakeup_handler *handler;
+
+	/* No need to lock, nothing else is running when we're called. */
+	list_for_each_entry(handler, &acpi_wakeup_handler_head, list_node) {
+		if (handler->wakeup(handler->context))
+			return true;
+	}
+
+	return false;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/amba/bus.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/amba/bus.c
@@ -299,10 +299,11 @@
 {
 	struct amba_device *pcdev = to_amba_device(dev);
 	struct amba_driver *drv = to_amba_driver(dev->driver);
-	int ret;
+	int ret = 0;
 
 	pm_runtime_get_sync(dev);
-	ret = drv->remove(pcdev);
+	if (drv->remove)
+		ret = drv->remove(pcdev);
 	pm_runtime_put_noidle(dev);
 
 	/* Undo the runtime PM settings in amba_probe() */
@@ -319,7 +320,9 @@
 static void amba_shutdown(struct device *dev)
 {
 	struct amba_driver *drv = to_amba_driver(dev->driver);
-	drv->shutdown(to_amba_device(dev));
+
+	if (drv->shutdown)
+		drv->shutdown(to_amba_device(dev));
 }
 
 /**
@@ -332,12 +335,13 @@
  */
 int amba_driver_register(struct amba_driver *drv)
 {
-	drv->drv.bus = &amba_bustype;
+	if (!drv->probe)
+		return -EINVAL;
 
-#define SETFN(fn)	if (drv->fn) drv->drv.fn = amba_##fn
-	SETFN(probe);
-	SETFN(remove);
-	SETFN(shutdown);
+	drv->drv.bus = &amba_bustype;
+	drv->drv.probe = amba_probe;
+	drv->drv.remove = amba_remove;
+	drv->drv.shutdown = amba_shutdown;
 
 	return driver_register(&drv->drv);
 }
@@ -360,6 +364,7 @@
 {
 	struct amba_device *d = to_amba_device(dev);
 
+	of_node_put(d->dev.of_node);
 	if (d->res.parent)
 		release_resource(&d->res);
 	kfree(d);
@@ -371,9 +376,6 @@
 	void __iomem *tmp;
 	int i, ret;
 
-	WARN_ON(dev->irq[0] == (unsigned int)-1);
-	WARN_ON(dev->irq[1] == (unsigned int)-1);
-
 	ret = request_resource(parent, &dev->res);
 	if (ret)
 		goto err_out;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/android/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/android/Kconfig
@@ -9,7 +9,7 @@
 if ANDROID
 
 config ANDROID_BINDER_IPC
-	bool "Android Binder IPC Driver"
+	tristate "Android Binder IPC Driver"
 	depends on MMU
 	default n
 	---help---
@@ -21,8 +21,8 @@
 	  between said processes.
 
 config ANDROID_BINDERFS
-	bool "Android Binderfs filesystem"
-	depends on ANDROID_BINDER_IPC
+	tristate "Android Binderfs filesystem"
+	depends on (ANDROID_BINDER_IPC=y) || (ANDROID_BINDER_IPC=m && m)
 	default n
 	---help---
 	  Binderfs is a pseudo-filesystem for the Android Binder IPC driver
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/android/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/android/Makefile
@@ -1,6 +1,10 @@
 # SPDX-License-Identifier: GPL-2.0-only
 ccflags-y += -I$(src)			# needed for trace events
 
-obj-$(CONFIG_ANDROID_BINDERFS)		+= binderfs.o
-obj-$(CONFIG_ANDROID_BINDER_IPC)	+= binder.o binder_alloc.o
-obj-$(CONFIG_ANDROID_BINDER_IPC_SELFTEST) += binder_alloc_selftest.o
+binder_linux-y := binder.o binder_alloc.o
+obj-$(CONFIG_ANDROID_BINDER_IPC) += binder_linux.o
+binder_linux-$(CONFIG_ANDROID_BINDERFS) += binderfs.o
+binder_linux-$(CONFIG_ANDROID_BINDER_IPC_SELFTEST) += binder_alloc_selftest.o
+
+# binder-$(CONFIG_ANDROID_BINDER_IPC) := binder.o binder_alloc.o
+# binder-$(CONFIG_ANDROID_BINDERFS) += binderfs.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/android/binder.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/android/binder.c
@@ -227,7 +227,7 @@
 struct binder_work {
 	struct list_head entry;
 
-	enum {
+	enum binder_work_type {
 		BINDER_WORK_TRANSACTION = 1,
 		BINDER_WORK_TRANSACTION_COMPLETE,
 		BINDER_WORK_RETURN_ERROR,
@@ -424,6 +424,9 @@
  *                        (invariant after initialized)
  * @tsk                   task_struct for group_leader of process
  *                        (invariant after initialized)
+ * @cred                  struct cred associated with the `struct file`
+ *                        in binder_open()
+ *                        (invariant after initialized)
  * @deferred_work_node:   element for binder_deferred_list
  *                        (protected by binder_deferred_lock)
  * @deferred_work:        bitmap of deferred work to perform
@@ -469,6 +472,7 @@
 	struct list_head waiting_threads;
 	int pid;
 	struct task_struct *tsk;
+	const struct cred *cred;
 	struct hlist_node deferred_work_node;
 	int deferred_work;
 	bool is_dead;
@@ -476,7 +480,7 @@
 	struct list_head todo;
 	struct binder_stats stats;
 	struct list_head delivered_death;
-	int max_threads;
+	u32 max_threads;
 	int requested_threads;
 	int requested_threads_started;
 	int tmp_ref;
@@ -836,6 +840,16 @@
 {
 	WARN_ON(!list_empty(&thread->waiting_thread_node));
 	binder_enqueue_work_ilocked(work, &thread->todo);
+
+	/* (e)poll-based threads require an explicit wakeup signal when
+	 * queuing their own work; they rely on these events to consume
+	 * messages without I/O block. Without it, threads risk waiting
+	 * indefinitely without handling the work.
+	 */
+	if (thread->looper & BINDER_LOOPER_STATE_POLL &&
+	    thread->pid == current->pid && !thread->process_todo)
+		wake_up_interruptible_sync(&thread->wait);
+
 	thread->process_todo = true;
 }
 
@@ -889,27 +903,6 @@
 	return w;
 }
 
-/**
- * binder_dequeue_work_head() - Dequeues the item at head of list
- * @proc:         binder_proc associated with list
- * @list:         list to dequeue head
- *
- * Removes the head of the list if there are items on the list
- *
- * Return: pointer dequeued binder_work, NULL if list was empty
- */
-static struct binder_work *binder_dequeue_work_head(
-					struct binder_proc *proc,
-					struct list_head *list)
-{
-	struct binder_work *w;
-
-	binder_inner_proc_lock(proc);
-	w = binder_dequeue_work_head_ilocked(list);
-	binder_inner_proc_unlock(proc);
-	return w;
-}
-
 static void
 binder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer);
 static void binder_free_thread(struct binder_thread *thread);
@@ -939,9 +932,7 @@
 static bool binder_available_for_proc_work_ilocked(struct binder_thread *thread)
 {
 	return !thread->transaction_stack &&
-		binder_worklist_empty_ilocked(&thread->todo) &&
-		(thread->looper & (BINDER_LOOPER_STATE_ENTERED |
-				   BINDER_LOOPER_STATE_REGISTERED));
+		binder_worklist_empty_ilocked(&thread->todo);
 }
 
 static void binder_wakeup_poll_threads_ilocked(struct binder_proc *proc,
@@ -1765,6 +1756,18 @@
 	}
 	ret = binder_inc_ref_olocked(ref, strong, target_list);
 	*rdata = ref->data;
+	if (ret && ref == new_ref) {
+		/*
+		 * Cleanup the failed reference here as the target
+		 * could now be dead and have already released its
+		 * references by now. Calling on the new reference
+		 * with strong=0 and a tmp_refs will not decrement
+		 * the node. The new_ref gets kfree'd below.
+		 */
+		binder_cleanup_ref_olocked(new_ref);
+		ref = NULL;
+	}
+
 	binder_proc_unlock(proc);
 	if (new_ref && ref != new_ref)
 		/*
@@ -2018,15 +2021,21 @@
 /**
  * binder_get_object() - gets object and checks for valid metadata
  * @proc:	binder_proc owning the buffer
+ * @u:		sender's user pointer to base of buffer
  * @buffer:	binder_buffer that we're parsing.
  * @offset:	offset in the @buffer at which to validate an object.
  * @object:	struct binder_object to read into
  *
- * Return:	If there's a valid metadata object at @offset in @buffer, the
+ * Copy the binder object at the given offset into @object. If @u is
+ * provided then the copy is from the sender's buffer. If not, then
+ * it is copied from the target's @buffer.
+ *
+ * Return:	If there's a valid metadata object at @offset, the
  *		size of that object. Otherwise, it returns zero. The object
  *		is read into the struct binder_object pointed to by @object.
  */
 static size_t binder_get_object(struct binder_proc *proc,
+				const void __user *u,
 				struct binder_buffer *buffer,
 				unsigned long offset,
 				struct binder_object *object)
@@ -2037,10 +2046,18 @@
 
 	read_size = min_t(size_t, sizeof(*object), buffer->data_size - offset);
 	if (offset > buffer->data_size || read_size < sizeof(*hdr) ||
-	    binder_alloc_copy_from_buffer(&proc->alloc, object, buffer,
-					  offset, read_size))
+	    !IS_ALIGNED(offset, sizeof(u32)))
 		return 0;
 
+	if (u) {
+		if (copy_from_user(object, u + offset, read_size))
+			return 0;
+	} else {
+		if (binder_alloc_copy_from_buffer(&proc->alloc, object, buffer,
+						  offset, read_size))
+			return 0;
+	}
+
 	/* Ok, now see if we read a complete object. */
 	hdr = &object->hdr;
 	switch (hdr->type) {
@@ -2112,7 +2129,7 @@
 					  b, buffer_offset,
 					  sizeof(object_offset)))
 		return NULL;
-	object_size = binder_get_object(proc, b, object_offset, object);
+	object_size = binder_get_object(proc, NULL, b, object_offset, object);
 	if (!object_size || object->hdr.type != BINDER_TYPE_PTR)
 		return NULL;
 	if (object_offsetp)
@@ -2177,7 +2194,8 @@
 		unsigned long buffer_offset;
 		struct binder_object last_object;
 		struct binder_buffer_object *last_bbo;
-		size_t object_size = binder_get_object(proc, b, last_obj_offset,
+		size_t object_size = binder_get_object(proc, NULL, b,
+						       last_obj_offset,
 						       &last_object);
 		if (object_size != sizeof(*last_bbo))
 			return false;
@@ -2260,25 +2278,25 @@
 }
 
 static void binder_transaction_buffer_release(struct binder_proc *proc,
+					      struct binder_thread *thread,
 					      struct binder_buffer *buffer,
-					      binder_size_t failed_at,
+					      binder_size_t off_end_offset,
 					      bool is_failure)
 {
 	int debug_id = buffer->debug_id;
-	binder_size_t off_start_offset, buffer_offset, off_end_offset;
+	binder_size_t off_start_offset, buffer_offset;
 
 	binder_debug(BINDER_DEBUG_TRANSACTION,
 		     "%d buffer release %d, size %zd-%zd, failed at %llx\n",
 		     proc->pid, buffer->debug_id,
 		     buffer->data_size, buffer->offsets_size,
-		     (unsigned long long)failed_at);
+		     (unsigned long long)off_end_offset);
 
 	if (buffer->target_node)
 		binder_dec_node(buffer->target_node, 1, 0);
 
 	off_start_offset = ALIGN(buffer->data_size, sizeof(void *));
-	off_end_offset = is_failure ? failed_at :
-				off_start_offset + buffer->offsets_size;
+
 	for (buffer_offset = off_start_offset; buffer_offset < off_end_offset;
 	     buffer_offset += sizeof(binder_size_t)) {
 		struct binder_object_header *hdr;
@@ -2289,7 +2307,7 @@
 		if (!binder_alloc_copy_from_buffer(&proc->alloc, &object_offset,
 						   buffer, buffer_offset,
 						   sizeof(object_offset)))
-			object_size = binder_get_object(proc, buffer,
+			object_size = binder_get_object(proc, NULL, buffer,
 							object_offset, &object);
 		if (object_size == 0) {
 			pr_err("transaction release %d bad object at offset %lld, size %zd\n",
@@ -2347,8 +2365,6 @@
 			 * file is done when the transaction is torn
 			 * down.
 			 */
-			WARN_ON(failed_at &&
-				proc->tsk == current->group_leader);
 		} break;
 		case BINDER_TYPE_PTR:
 			/*
@@ -2365,9 +2381,8 @@
 			binder_size_t fd_buf_size;
 			binder_size_t num_valid;
 
-			if (proc->tsk != current->group_leader) {
+			if (is_failure) {
 				/*
-				 * Nothing to do if running in sender context
 				 * The fd fixups have not been applied so no
 				 * fds need to be closed.
 				 */
@@ -2421,8 +2436,16 @@
 						&proc->alloc, &fd, buffer,
 						offset, sizeof(fd));
 				WARN_ON(err);
-				if (!err)
+				if (!err) {
 					binder_deferred_fd_close(fd);
+					/*
+					 * Need to make sure the thread goes
+					 * back to userspace to complete the
+					 * deferred close
+					 */
+					if (thread)
+						thread->looper_need_return = true;
+				}
 			}
 		} break;
 		default:
@@ -2433,6 +2456,21 @@
 	}
 }
 
+/* Clean up all the objects in the buffer */
+static inline void binder_release_entire_buffer(struct binder_proc *proc,
+						struct binder_thread *thread,
+						struct binder_buffer *buffer,
+						bool is_failure)
+{
+	binder_size_t off_end_offset;
+
+	off_end_offset = ALIGN(buffer->data_size, sizeof(void *));
+	off_end_offset += buffer->offsets_size;
+
+	binder_transaction_buffer_release(proc, thread, buffer,
+					  off_end_offset, is_failure);
+}
+
 static int binder_translate_binder(struct flat_binder_object *fp,
 				   struct binder_transaction *t,
 				   struct binder_thread *thread)
@@ -2457,7 +2495,7 @@
 		ret = -EINVAL;
 		goto done;
 	}
-	if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) {
+	if (security_binder_transfer_binder(proc->cred, target_proc->cred)) {
 		ret = -EPERM;
 		goto done;
 	}
@@ -2503,7 +2541,7 @@
 				  proc->pid, thread->pid, fp->handle);
 		return -EINVAL;
 	}
-	if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) {
+	if (security_binder_transfer_binder(proc->cred, target_proc->cred)) {
 		ret = -EPERM;
 		goto done;
 	}
@@ -2591,7 +2629,7 @@
 		ret = -EBADF;
 		goto err_fget;
 	}
-	ret = security_binder_transfer_file(proc->tsk, target_proc->tsk, file);
+	ret = security_binder_transfer_file(proc->cred, target_proc->cred, file);
 	if (ret < 0) {
 		ret = -EPERM;
 		goto err_security;
@@ -2622,16 +2660,266 @@
 	return ret;
 }
 
-static int binder_translate_fd_array(struct binder_fd_array_object *fda,
+/**
+ * struct binder_ptr_fixup - data to be fixed-up in target buffer
+ * @offset	offset in target buffer to fixup
+ * @skip_size	bytes to skip in copy (fixup will be written later)
+ * @fixup_data	data to write at fixup offset
+ * @node	list node
+ *
+ * This is used for the pointer fixup list (pf) which is created and consumed
+ * during binder_transaction() and is only accessed locally. No
+ * locking is necessary.
+ *
+ * The list is ordered by @offset.
+ */
+struct binder_ptr_fixup {
+	binder_size_t offset;
+	size_t skip_size;
+	binder_uintptr_t fixup_data;
+	struct list_head node;
+};
+
+/**
+ * struct binder_sg_copy - scatter-gather data to be copied
+ * @offset		offset in target buffer
+ * @sender_uaddr	user address in source buffer
+ * @length		bytes to copy
+ * @node		list node
+ *
+ * This is used for the sg copy list (sgc) which is created and consumed
+ * during binder_transaction() and is only accessed locally. No
+ * locking is necessary.
+ *
+ * The list is ordered by @offset.
+ */
+struct binder_sg_copy {
+	binder_size_t offset;
+	const void __user *sender_uaddr;
+	size_t length;
+	struct list_head node;
+};
+
+/**
+ * binder_do_deferred_txn_copies() - copy and fixup scatter-gather data
+ * @alloc:	binder_alloc associated with @buffer
+ * @buffer:	binder buffer in target process
+ * @sgc_head:	list_head of scatter-gather copy list
+ * @pf_head:	list_head of pointer fixup list
+ *
+ * Processes all elements of @sgc_head, applying fixups from @pf_head
+ * and copying the scatter-gather data from the source process' user
+ * buffer to the target's buffer. It is expected that the list creation
+ * and processing all occurs during binder_transaction() so these lists
+ * are only accessed in local context.
+ *
+ * Return: 0=success, else -errno
+ */
+static int binder_do_deferred_txn_copies(struct binder_alloc *alloc,
+					 struct binder_buffer *buffer,
+					 struct list_head *sgc_head,
+					 struct list_head *pf_head)
+{
+	int ret = 0;
+	struct binder_sg_copy *sgc, *tmpsgc;
+	struct binder_ptr_fixup *tmppf;
+	struct binder_ptr_fixup *pf =
+		list_first_entry_or_null(pf_head, struct binder_ptr_fixup,
+					 node);
+
+	list_for_each_entry_safe(sgc, tmpsgc, sgc_head, node) {
+		size_t bytes_copied = 0;
+
+		while (bytes_copied < sgc->length) {
+			size_t copy_size;
+			size_t bytes_left = sgc->length - bytes_copied;
+			size_t offset = sgc->offset + bytes_copied;
+
+			/*
+			 * We copy up to the fixup (pointed to by pf)
+			 */
+			copy_size = pf ? min(bytes_left, (size_t)pf->offset - offset)
+				       : bytes_left;
+			if (!ret && copy_size)
+				ret = binder_alloc_copy_user_to_buffer(
+						alloc, buffer,
+						offset,
+						sgc->sender_uaddr + bytes_copied,
+						copy_size);
+			bytes_copied += copy_size;
+			if (copy_size != bytes_left) {
+				BUG_ON(!pf);
+				/* we stopped at a fixup offset */
+				if (pf->skip_size) {
+					/*
+					 * we are just skipping. This is for
+					 * BINDER_TYPE_FDA where the translated
+					 * fds will be fixed up when we get
+					 * to target context.
+					 */
+					bytes_copied += pf->skip_size;
+				} else {
+					/* apply the fixup indicated by pf */
+					if (!ret)
+						ret = binder_alloc_copy_to_buffer(
+							alloc, buffer,
+							pf->offset,
+							&pf->fixup_data,
+							sizeof(pf->fixup_data));
+					bytes_copied += sizeof(pf->fixup_data);
+				}
+				list_del(&pf->node);
+				kfree(pf);
+				pf = list_first_entry_or_null(pf_head,
+						struct binder_ptr_fixup, node);
+			}
+		}
+		list_del(&sgc->node);
+		kfree(sgc);
+	}
+	list_for_each_entry_safe(pf, tmppf, pf_head, node) {
+		BUG_ON(pf->skip_size == 0);
+		list_del(&pf->node);
+		kfree(pf);
+	}
+	BUG_ON(!list_empty(sgc_head));
+
+	return ret > 0 ? -EINVAL : ret;
+}
+
+/**
+ * binder_cleanup_deferred_txn_lists() - free specified lists
+ * @sgc_head:	list_head of scatter-gather copy list
+ * @pf_head:	list_head of pointer fixup list
+ *
+ * Called to clean up @sgc_head and @pf_head if there is an
+ * error.
+ */
+static void binder_cleanup_deferred_txn_lists(struct list_head *sgc_head,
+					      struct list_head *pf_head)
+{
+	struct binder_sg_copy *sgc, *tmpsgc;
+	struct binder_ptr_fixup *pf, *tmppf;
+
+	list_for_each_entry_safe(sgc, tmpsgc, sgc_head, node) {
+		list_del(&sgc->node);
+		kfree(sgc);
+	}
+	list_for_each_entry_safe(pf, tmppf, pf_head, node) {
+		list_del(&pf->node);
+		kfree(pf);
+	}
+}
+
+/**
+ * binder_defer_copy() - queue a scatter-gather buffer for copy
+ * @sgc_head:		list_head of scatter-gather copy list
+ * @offset:		binder buffer offset in target process
+ * @sender_uaddr:	user address in source process
+ * @length:		bytes to copy
+ *
+ * Specify a scatter-gather block to be copied. The actual copy must
+ * be deferred until all the needed fixups are identified and queued.
+ * Then the copy and fixups are done together so un-translated values
+ * from the source are never visible in the target buffer.
+ *
+ * We are guaranteed that repeated calls to this function will have
+ * monotonically increasing @offset values so the list will naturally
+ * be ordered.
+ *
+ * Return: 0=success, else -errno
+ */
+static int binder_defer_copy(struct list_head *sgc_head, binder_size_t offset,
+			     const void __user *sender_uaddr, size_t length)
+{
+	struct binder_sg_copy *bc = kzalloc(sizeof(*bc), GFP_KERNEL);
+
+	if (!bc)
+		return -ENOMEM;
+
+	bc->offset = offset;
+	bc->sender_uaddr = sender_uaddr;
+	bc->length = length;
+	INIT_LIST_HEAD(&bc->node);
+
+	/*
+	 * We are guaranteed that the deferred copies are in-order
+	 * so just add to the tail.
+	 */
+	list_add_tail(&bc->node, sgc_head);
+
+	return 0;
+}
+
+/**
+ * binder_add_fixup() - queue a fixup to be applied to sg copy
+ * @pf_head:	list_head of binder ptr fixup list
+ * @offset:	binder buffer offset in target process
+ * @fixup:	bytes to be copied for fixup
+ * @skip_size:	bytes to skip when copying (fixup will be applied later)
+ *
+ * Add the specified fixup to a list ordered by @offset. When copying
+ * the scatter-gather buffers, the fixup will be copied instead of
+ * data from the source buffer. For BINDER_TYPE_FDA fixups, the fixup
+ * will be applied later (in target process context), so we just skip
+ * the bytes specified by @skip_size. If @skip_size is 0, we copy the
+ * value in @fixup.
+ *
+ * This function is called *mostly* in @offset order, but there are
+ * exceptions. Since out-of-order inserts are relatively uncommon,
+ * we insert the new element by searching backward from the tail of
+ * the list.
+ *
+ * Return: 0=success, else -errno
+ */
+static int binder_add_fixup(struct list_head *pf_head, binder_size_t offset,
+			    binder_uintptr_t fixup, size_t skip_size)
+{
+	struct binder_ptr_fixup *pf = kzalloc(sizeof(*pf), GFP_KERNEL);
+	struct binder_ptr_fixup *tmppf;
+
+	if (!pf)
+		return -ENOMEM;
+
+	pf->offset = offset;
+	pf->fixup_data = fixup;
+	pf->skip_size = skip_size;
+	INIT_LIST_HEAD(&pf->node);
+
+	/* Fixups are *mostly* added in-order, but there are some
+	 * exceptions. Look backwards through list for insertion point.
+	 */
+	list_for_each_entry_reverse(tmppf, pf_head, node) {
+		if (tmppf->offset < pf->offset) {
+			list_add(&pf->node, &tmppf->node);
+			return 0;
+		}
+	}
+	/*
+	 * if we get here, then the new offset is the lowest so
+	 * insert at the head
+	 */
+	list_add(&pf->node, pf_head);
+	return 0;
+}
+
+static int binder_translate_fd_array(struct list_head *pf_head,
+				     struct binder_fd_array_object *fda,
+				     const void __user *sender_ubuffer,
 				     struct binder_buffer_object *parent,
+				     struct binder_buffer_object *sender_uparent,
 				     struct binder_transaction *t,
 				     struct binder_thread *thread,
 				     struct binder_transaction *in_reply_to)
 {
 	binder_size_t fdi, fd_buf_size;
 	binder_size_t fda_offset;
+	const void __user *sender_ufda_base;
 	struct binder_proc *proc = thread->proc;
-	struct binder_proc *target_proc = t->to_proc;
+	int ret;
+
+	if (fda->num_fds == 0)
+		return 0;
 
 	fd_buf_size = sizeof(u32) * fda->num_fds;
 	if (fda->num_fds >= SIZE_MAX / sizeof(u32)) {
@@ -2655,29 +2943,36 @@
 	 */
 	fda_offset = (parent->buffer - (uintptr_t)t->buffer->user_data) +
 		fda->parent_offset;
-	if (!IS_ALIGNED((unsigned long)fda_offset, sizeof(u32))) {
+	sender_ufda_base = (void __user *)(uintptr_t)sender_uparent->buffer +
+				fda->parent_offset;
+
+	if (!IS_ALIGNED((unsigned long)fda_offset, sizeof(u32)) ||
+	    !IS_ALIGNED((unsigned long)sender_ufda_base, sizeof(u32))) {
 		binder_user_error("%d:%d parent offset not aligned correctly.\n",
 				  proc->pid, thread->pid);
 		return -EINVAL;
 	}
+	ret = binder_add_fixup(pf_head, fda_offset, 0, fda->num_fds * sizeof(u32));
+	if (ret)
+		return ret;
+
 	for (fdi = 0; fdi < fda->num_fds; fdi++) {
 		u32 fd;
-		int ret;
 		binder_size_t offset = fda_offset + fdi * sizeof(fd);
+		binder_size_t sender_uoffset = fdi * sizeof(fd);
 
-		ret = binder_alloc_copy_from_buffer(&target_proc->alloc,
-						    &fd, t->buffer,
-						    offset, sizeof(fd));
+		ret = copy_from_user(&fd, sender_ufda_base + sender_uoffset, sizeof(fd));
 		if (!ret)
 			ret = binder_translate_fd(fd, offset, t, thread,
 						  in_reply_to);
-		if (ret < 0)
-			return ret;
+		if (ret)
+			return ret > 0 ? -EINVAL : ret;
 	}
 	return 0;
 }
 
-static int binder_fixup_parent(struct binder_transaction *t,
+static int binder_fixup_parent(struct list_head *pf_head,
+			       struct binder_transaction *t,
 			       struct binder_thread *thread,
 			       struct binder_buffer_object *bp,
 			       binder_size_t off_start_offset,
@@ -2723,14 +3018,7 @@
 	}
 	buffer_offset = bp->parent_offset +
 			(uintptr_t)parent->buffer - (uintptr_t)b->user_data;
-	if (binder_alloc_copy_to_buffer(&target_proc->alloc, b, buffer_offset,
-					&bp->buffer, sizeof(bp->buffer))) {
-		binder_user_error("%d:%d got transaction with invalid parent offset\n",
-				  proc->pid, thread->pid);
-		return -EINVAL;
-	}
-
-	return 0;
+	return binder_add_fixup(pf_head, buffer_offset, bp->buffer, 0);
 }
 
 /**
@@ -2851,6 +3139,7 @@
 	binder_size_t off_start_offset, off_end_offset;
 	binder_size_t off_min;
 	binder_size_t sg_buf_offset, sg_buf_end_offset;
+	binder_size_t user_offset = 0;
 	struct binder_proc *target_proc = NULL;
 	struct binder_thread *target_thread = NULL;
 	struct binder_node *target_node = NULL;
@@ -2865,6 +3154,12 @@
 	int t_debug_id = atomic_inc_return(&binder_last_id);
 	char *secctx = NULL;
 	u32 secctx_sz = 0;
+	struct list_head sgc_head;
+	struct list_head pf_head;
+	const void __user *user_buffer = (const void __user *)
+				(uintptr_t)tr->data.ptr.buffer;
+	INIT_LIST_HEAD(&sgc_head);
+	INIT_LIST_HEAD(&pf_head);
 
 	e = binder_transaction_log_add(&binder_transaction_log);
 	e->debug_id = t_debug_id;
@@ -2984,8 +3279,14 @@
 			goto err_dead_binder;
 		}
 		e->to_node = target_node->debug_id;
-		if (security_binder_transaction(proc->tsk,
-						target_proc->tsk) < 0) {
+		if (WARN_ON(proc == target_proc)) {
+			return_error = BR_FAILED_REPLY;
+			return_error_param = -EINVAL;
+			return_error_line = __LINE__;
+			goto err_invalid_target_handle;
+		}
+		if (security_binder_transaction(proc->cred,
+						target_proc->cred) < 0) {
 			return_error = BR_FAILED_REPLY;
 			return_error_param = -EPERM;
 			return_error_line = __LINE__;
@@ -3111,7 +3412,7 @@
 		u32 secid;
 		size_t added_size;
 
-		security_task_getsecid(proc->tsk, &secid);
+		security_cred_getsecid(proc->cred, &secid);
 		ret = security_secid_to_secctx(secid, &secctx, &secctx_sz);
 		if (ret) {
 			return_error = BR_FAILED_REPLY;
@@ -3167,23 +3468,11 @@
 	t->buffer->debug_id = t->debug_id;
 	t->buffer->transaction = t;
 	t->buffer->target_node = target_node;
+	t->buffer->clear_on_free = !!(t->flags & TF_CLEAR_BUF);
 	trace_binder_transaction_alloc_buf(t->buffer);
 
 	if (binder_alloc_copy_user_to_buffer(
 				&target_proc->alloc,
-				t->buffer, 0,
-				(const void __user *)
-					(uintptr_t)tr->data.ptr.buffer,
-				tr->data_size)) {
-		binder_user_error("%d:%d got transaction with invalid data ptr\n",
-				proc->pid, thread->pid);
-		return_error = BR_FAILED_REPLY;
-		return_error_param = -EFAULT;
-		return_error_line = __LINE__;
-		goto err_copy_data_failed;
-	}
-	if (binder_alloc_copy_user_to_buffer(
-				&target_proc->alloc,
 				t->buffer,
 				ALIGN(tr->data_size, sizeof(void *)),
 				(const void __user *)
@@ -3226,6 +3515,7 @@
 		size_t object_size;
 		struct binder_object object;
 		binder_size_t object_offset;
+		binder_size_t copy_size;
 
 		if (binder_alloc_copy_from_buffer(&target_proc->alloc,
 						  &object_offset,
@@ -3237,8 +3527,28 @@
 			return_error_line = __LINE__;
 			goto err_bad_offset;
 		}
-		object_size = binder_get_object(target_proc, t->buffer,
-						object_offset, &object);
+
+		/*
+		 * Copy the source user buffer up to the next object
+		 * that will be processed.
+		 */
+		copy_size = object_offset - user_offset;
+		if (copy_size && (user_offset > object_offset ||
+				object_offset > tr->data_size ||
+				binder_alloc_copy_user_to_buffer(
+					&target_proc->alloc,
+					t->buffer, user_offset,
+					user_buffer + user_offset,
+					copy_size))) {
+			binder_user_error("%d:%d got transaction with invalid data ptr\n",
+					proc->pid, thread->pid);
+			return_error = BR_FAILED_REPLY;
+			return_error_param = -EFAULT;
+			return_error_line = __LINE__;
+			goto err_copy_data_failed;
+		}
+		object_size = binder_get_object(target_proc, user_buffer,
+				t->buffer, object_offset, &object);
 		if (object_size == 0 || object_offset < off_min) {
 			binder_user_error("%d:%d got transaction with invalid offset (%lld, min %lld max %lld) or object.\n",
 					  proc->pid, thread->pid,
@@ -3250,6 +3560,11 @@
 			return_error_line = __LINE__;
 			goto err_bad_offset;
 		}
+		/*
+		 * Set offset to the next buffer fragment to be
+		 * copied
+		 */
+		user_offset = object_offset + object_size;
 
 		hdr = &object.hdr;
 		off_min = object_offset + object_size;
@@ -3312,9 +3627,11 @@
 		case BINDER_TYPE_FDA: {
 			struct binder_object ptr_object;
 			binder_size_t parent_offset;
+			struct binder_object user_object;
+			size_t user_parent_size;
 			struct binder_fd_array_object *fda =
 				to_binder_fd_array_object(hdr);
-			size_t num_valid = (buffer_offset - off_start_offset) *
+			size_t num_valid = (buffer_offset - off_start_offset) /
 						sizeof(binder_size_t);
 			struct binder_buffer_object *parent =
 				binder_validate_ptr(target_proc, t->buffer,
@@ -3343,11 +3660,35 @@
 				return_error_line = __LINE__;
 				goto err_bad_parent;
 			}
-			ret = binder_translate_fd_array(fda, parent, t, thread,
-							in_reply_to);
-			if (ret < 0) {
+			/*
+			 * We need to read the user version of the parent
+			 * object to get the original user offset
+			 */
+			user_parent_size =
+				binder_get_object(proc, user_buffer, t->buffer,
+						  parent_offset, &user_object);
+			if (user_parent_size != sizeof(user_object.bbo)) {
+				binder_user_error("%d:%d invalid ptr object size: %zd vs %zd\n",
+						  proc->pid, thread->pid,
+						  user_parent_size,
+						  sizeof(user_object.bbo));
 				return_error = BR_FAILED_REPLY;
-				return_error_param = ret;
+				return_error_param = -EINVAL;
+				return_error_line = __LINE__;
+				goto err_bad_parent;
+			}
+			ret = binder_translate_fd_array(&pf_head, fda,
+							user_buffer, parent,
+							&user_object.bbo, t,
+							thread, in_reply_to);
+			if (!ret)
+				ret = binder_alloc_copy_to_buffer(&target_proc->alloc,
+								  t->buffer,
+								  object_offset,
+								  fda, sizeof(*fda));
+			if (ret) {
+				return_error = BR_FAILED_REPLY;
+				return_error_param = ret > 0 ? -EINVAL : ret;
 				return_error_line = __LINE__;
 				goto err_translate_failed;
 			}
@@ -3369,28 +3710,24 @@
 				return_error_line = __LINE__;
 				goto err_bad_offset;
 			}
-			if (binder_alloc_copy_user_to_buffer(
-						&target_proc->alloc,
-						t->buffer,
-						sg_buf_offset,
-						(const void __user *)
-							(uintptr_t)bp->buffer,
-						bp->length)) {
-				binder_user_error("%d:%d got transaction with invalid offsets ptr\n",
-						  proc->pid, thread->pid);
-				return_error_param = -EFAULT;
+			ret = binder_defer_copy(&sgc_head, sg_buf_offset,
+				(const void __user *)(uintptr_t)bp->buffer,
+				bp->length);
+			if (ret) {
 				return_error = BR_FAILED_REPLY;
+				return_error_param = ret;
 				return_error_line = __LINE__;
-				goto err_copy_data_failed;
+				goto err_translate_failed;
 			}
 			/* Fixup buffer pointer to target proc address space */
 			bp->buffer = (uintptr_t)
 				t->buffer->user_data + sg_buf_offset;
 			sg_buf_offset += ALIGN(bp->length, sizeof(u64));
 
-			num_valid = (buffer_offset - off_start_offset) *
+			num_valid = (buffer_offset - off_start_offset) /
 					sizeof(binder_size_t);
-			ret = binder_fixup_parent(t, thread, bp,
+			ret = binder_fixup_parent(&pf_head, t,
+						  thread, bp,
 						  off_start_offset,
 						  num_valid,
 						  last_fixup_obj_off,
@@ -3417,6 +3754,30 @@
 			goto err_bad_object_type;
 		}
 	}
+	/* Done processing objects, copy the rest of the buffer */
+	if (binder_alloc_copy_user_to_buffer(
+				&target_proc->alloc,
+				t->buffer, user_offset,
+				user_buffer + user_offset,
+				tr->data_size - user_offset)) {
+		binder_user_error("%d:%d got transaction with invalid data ptr\n",
+				proc->pid, thread->pid);
+		return_error = BR_FAILED_REPLY;
+		return_error_param = -EFAULT;
+		return_error_line = __LINE__;
+		goto err_copy_data_failed;
+	}
+
+	ret = binder_do_deferred_txn_copies(&target_proc->alloc, t->buffer,
+					    &sgc_head, &pf_head);
+	if (ret) {
+		binder_user_error("%d:%d got transaction with invalid offsets ptr\n",
+				  proc->pid, thread->pid);
+		return_error = BR_FAILED_REPLY;
+		return_error_param = ret;
+		return_error_line = __LINE__;
+		goto err_copy_data_failed;
+	}
 	tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
 	t->work.type = BINDER_WORK_TRANSACTION;
 
@@ -3483,9 +3844,10 @@
 err_bad_offset:
 err_bad_parent:
 err_copy_data_failed:
+	binder_cleanup_deferred_txn_lists(&sgc_head, &pf_head);
 	binder_free_txn_fixups(t);
 	trace_binder_transaction_failed_buffer_release(t->buffer);
-	binder_transaction_buffer_release(target_proc, t->buffer,
+	binder_transaction_buffer_release(target_proc, NULL, t->buffer,
 					  buffer_offset, true);
 	if (target_node)
 		binder_dec_node_tmpref(target_node);
@@ -3555,6 +3917,7 @@
  * binder_free_buf() - free the specified buffer
  * @proc:	binder proc that owns buffer
  * @buffer:	buffer to be freed
+ * @is_failure:	failed to send transaction
  *
  * If buffer for an async transaction, enqueue the next async
  * transaction from the node.
@@ -3562,7 +3925,9 @@
  * Cleanup buffer and free it.
  */
 static void
-binder_free_buf(struct binder_proc *proc, struct binder_buffer *buffer)
+binder_free_buf(struct binder_proc *proc,
+		struct binder_thread *thread,
+		struct binder_buffer *buffer, bool is_failure)
 {
 	binder_inner_proc_lock(proc);
 	if (buffer->transaction) {
@@ -3590,7 +3955,7 @@
 		binder_node_inner_unlock(buf_node);
 	}
 	trace_binder_transaction_buffer_release(buffer);
-	binder_transaction_buffer_release(proc, buffer, 0, false);
+	binder_release_entire_buffer(proc, thread, buffer, is_failure);
 	binder_alloc_free_buf(&proc->alloc, buffer);
 }
 
@@ -3637,10 +4002,17 @@
 				struct binder_node *ctx_mgr_node;
 				mutex_lock(&context->context_mgr_node_lock);
 				ctx_mgr_node = context->binder_context_mgr_node;
-				if (ctx_mgr_node)
+				if (ctx_mgr_node) {
+					if (ctx_mgr_node->proc == proc) {
+						binder_user_error("%d:%d context manager tried to acquire desc 0\n",
+								  proc->pid, thread->pid);
+						mutex_unlock(&context->context_mgr_node_lock);
+						return -EINVAL;
+					}
 					ret = binder_inc_ref_for_node(
 							proc, ctx_mgr_node,
 							strong, NULL, &rdata);
+				}
 				mutex_unlock(&context->context_mgr_node_lock);
 			}
 			if (ret)
@@ -3784,7 +4156,7 @@
 				     proc->pid, thread->pid, (u64)data_ptr,
 				     buffer->debug_id,
 				     buffer->transaction ? "active" : "finished");
-			binder_free_buf(proc, buffer);
+			binder_free_buf(proc, thread, buffer, false);
 			break;
 		}
 
@@ -4472,7 +4844,7 @@
 			buffer->transaction = NULL;
 			binder_cleanup_transaction(t, "fd fixups failed",
 						   BR_FAILED_REPLY);
-			binder_free_buf(proc, buffer);
+			binder_free_buf(proc, thread, buffer, true);
 			binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
 				     "%d:%d %stransaction %d fd fixups failed %d/%d, line %d\n",
 				     proc->pid, thread->pid,
@@ -4578,13 +4950,17 @@
 				struct list_head *list)
 {
 	struct binder_work *w;
+	enum binder_work_type wtype;
 
 	while (1) {
-		w = binder_dequeue_work_head(proc, list);
+		binder_inner_proc_lock(proc);
+		w = binder_dequeue_work_head_ilocked(list);
+		wtype = w ? w->type : 0;
+		binder_inner_proc_unlock(proc);
 		if (!w)
 			return;
 
-		switch (w->type) {
+		switch (wtype) {
 		case BINDER_WORK_TRANSACTION: {
 			struct binder_transaction *t;
 
@@ -4618,9 +4994,11 @@
 			kfree(death);
 			binder_stats_deleted(BINDER_STAT_DEATH);
 		} break;
+		case BINDER_WORK_NODE:
+			break;
 		default:
 			pr_err("unexpected work type, %d, not freed\n",
-			       w->type);
+			       wtype);
 			break;
 		}
 	}
@@ -4688,10 +5066,18 @@
 
 static void binder_free_proc(struct binder_proc *proc)
 {
+	struct binder_device *device;
+
 	BUG_ON(!list_empty(&proc->todo));
 	BUG_ON(!list_empty(&proc->delivered_death));
+	device = container_of(proc->context, struct binder_device, context);
+	if (refcount_dec_and_test(&device->ref)) {
+		kfree(proc->context->name);
+		kfree(device);
+	}
 	binder_alloc_deferred_release(&proc->alloc);
 	put_task_struct(proc->tsk);
+	put_cred(proc->cred);
 	binder_stats_deleted(BINDER_STAT_PROC);
 	kfree(proc);
 }
@@ -4768,23 +5154,20 @@
 	__release(&t->lock);
 
 	/*
-	 * If this thread used poll, make sure we remove the waitqueue
-	 * from any epoll data structures holding it with POLLFREE.
-	 * waitqueue_active() is safe to use here because we're holding
-	 * the inner lock.
+	 * If this thread used poll, make sure we remove the waitqueue from any
+	 * poll data structures holding it.
 	 */
-	if ((thread->looper & BINDER_LOOPER_STATE_POLL) &&
-	    waitqueue_active(&thread->wait)) {
-		wake_up_poll(&thread->wait, EPOLLHUP | POLLFREE);
-	}
+	if (thread->looper & BINDER_LOOPER_STATE_POLL)
+		wake_up_pollfree(&thread->wait);
 
 	binder_inner_proc_unlock(thread->proc);
 
 	/*
-	 * This is needed to avoid races between wake_up_poll() above and
-	 * and ep_remove_waitqueue() called for other reasons (eg the epoll file
-	 * descriptor being closed); ep_remove_waitqueue() holds an RCU read
-	 * lock, so we can be sure it's done after calling synchronize_rcu().
+	 * This is needed to avoid races between wake_up_pollfree() above and
+	 * someone else removing the last entry from the queue for other reasons
+	 * (e.g. ep_remove_wait_queue() being called due to an epoll file
+	 * descriptor being closed).  Such other users hold an RCU read lock, so
+	 * we can be sure they're done after we call synchronize_rcu().
 	 */
 	if (thread->looper & BINDER_LOOPER_STATE_POLL)
 		synchronize_rcu();
@@ -4805,7 +5188,7 @@
 
 	thread = binder_get_thread(proc);
 	if (!thread)
-		return POLLERR;
+		return EPOLLERR;
 
 	binder_inner_proc_lock(thread->proc);
 	thread->looper |= BINDER_LOOPER_STATE_POLL;
@@ -4902,7 +5285,7 @@
 		ret = -EBUSY;
 		goto out;
 	}
-	ret = security_binder_set_context_mgr(proc->tsk);
+	ret = security_binder_set_context_mgr(proc->cred);
 	if (ret < 0)
 		goto out;
 	if (uid_valid(context->binder_context_mgr_uid)) {
@@ -5028,7 +5411,7 @@
 			goto err;
 		break;
 	case BINDER_SET_MAX_THREADS: {
-		int max_threads;
+		u32 max_threads;
 
 		if (copy_from_user(&max_threads, ubuf,
 				   sizeof(max_threads))) {
@@ -5203,10 +5586,11 @@
 
 static int binder_open(struct inode *nodp, struct file *filp)
 {
-	struct binder_proc *proc;
+	struct binder_proc *proc, *itr;
 	struct binder_device *binder_dev;
 	struct binderfs_info *info;
 	struct dentry *binder_binderfs_dir_entry_proc = NULL;
+	bool existing_pid = false;
 
 	binder_debug(BINDER_DEBUG_OPEN_CLOSE, "%s: %d:%d\n", __func__,
 		     current->group_leader->pid, current->pid);
@@ -5218,6 +5602,7 @@
 	spin_lock_init(&proc->outer_lock);
 	get_task_struct(current->group_leader);
 	proc->tsk = current->group_leader;
+	proc->cred = get_cred(filp->f_cred);
 	INIT_LIST_HEAD(&proc->todo);
 	proc->default_priority = task_nice(current);
 	/* binderfs stashes devices in i_private */
@@ -5229,6 +5614,7 @@
 		binder_dev = container_of(filp->private_data,
 					  struct binder_device, miscdev);
 	}
+	refcount_inc(&binder_dev->ref);
 	proc->context = &binder_dev->context;
 	binder_alloc_init(&proc->alloc);
 
@@ -5239,19 +5625,24 @@
 	filp->private_data = proc;
 
 	mutex_lock(&binder_procs_lock);
+	hlist_for_each_entry(itr, &binder_procs, proc_node) {
+		if (itr->pid == proc->pid) {
+			existing_pid = true;
+			break;
+		}
+	}
 	hlist_add_head(&proc->proc_node, &binder_procs);
 	mutex_unlock(&binder_procs_lock);
 
-	if (binder_debugfs_dir_entry_proc) {
+	if (binder_debugfs_dir_entry_proc && !existing_pid) {
 		char strbuf[11];
 
 		snprintf(strbuf, sizeof(strbuf), "%u", proc->pid);
 		/*
-		 * proc debug entries are shared between contexts, so
-		 * this will fail if the process tries to open the driver
-		 * again with a different context. The priting code will
-		 * anyway print all contexts that a given PID has, so this
-		 * is not a problem.
+		 * proc debug entries are shared between contexts.
+		 * Only create for the first PID to avoid debugfs log spamming
+		 * The printing code will anyway print all contexts for a given
+		 * PID so this is not a problem.
 		 */
 		proc->debugfs_entry = debugfs_create_file(strbuf, 0444,
 			binder_debugfs_dir_entry_proc,
@@ -5259,19 +5650,16 @@
 			&proc_fops);
 	}
 
-	if (binder_binderfs_dir_entry_proc) {
+	if (binder_binderfs_dir_entry_proc && !existing_pid) {
 		char strbuf[11];
 		struct dentry *binderfs_entry;
 
 		snprintf(strbuf, sizeof(strbuf), "%u", proc->pid);
 		/*
 		 * Similar to debugfs, the process specific log file is shared
-		 * between contexts. If the file has already been created for a
-		 * process, the following binderfs_create_file() call will
-		 * fail with error code EEXIST if another context of the same
-		 * process invoked binder_open(). This is ok since same as
-		 * debugfs, the log file will contain information on all
-		 * contexts of a given PID.
+		 * between contexts. Only create for the first PID.
+		 * This is ok since same as debugfs, the log file will contain
+		 * information on all contexts of a given PID.
 		 */
 		binderfs_entry = binderfs_create_file(binder_binderfs_dir_entry_proc,
 			strbuf, &proc_fops, (void *)(unsigned long)proc->pid);
@@ -5281,10 +5669,8 @@
 			int error;
 
 			error = PTR_ERR(binderfs_entry);
-			if (error != -EEXIST) {
-				pr_warn("Unable to create file %s in binderfs (error %d)\n",
-					strbuf, error);
-			}
+			pr_warn("Unable to create file %s in binderfs (error %d)\n",
+				strbuf, error);
 		}
 	}
 
@@ -6063,6 +6449,7 @@
 	.open = binder_open,
 	.flush = binder_flush,
 	.release = binder_release,
+	.may_pollfree = true,
 };
 
 static int __init init_binder_device(const char *name)
@@ -6078,6 +6465,7 @@
 	binder_device->miscdev.minor = MISC_DYNAMIC_MINOR;
 	binder_device->miscdev.name = name;
 
+	refcount_set(&binder_device->ref, 1);
 	binder_device->context.binder_context_mgr_uid = INVALID_UID;
 	binder_device->context.name = name;
 	mutex_init(&binder_device->context.context_mgr_node_lock);
@@ -6178,13 +6566,25 @@
 
 err_alloc_device_names_failed:
 	debugfs_remove_recursive(binder_debugfs_dir_entry_root);
+	binder_alloc_shrinker_exit();
 
 	return ret;
 }
 
-device_initcall(binder_init);
+module_init(binder_init);
+/*
+ * binder will have no exit function since binderfs instances can be mounted
+ * multiple times and also in user namespaces finding and destroying them all
+ * is not feasible without introducing insane locking. Just ignoring existing
+ * instances on module unload also wouldn't work since we would loose track of
+ * what major numer was dynamically allocated and also what minor numbers are
+ * already given out. So this would get us into all kinds of issues with device
+ * number reuse. So simply don't allow unloading unless we are forced to do so.
+ */
+
+MODULE_AUTHOR("Google, Inc.");
+MODULE_DESCRIPTION("Driver for Android binder device");
+MODULE_LICENSE("GPL v2");
 
 #define CREATE_TRACE_POINTS
 #include "binder_trace.h"
-
-MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/android/binder_alloc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/android/binder_alloc.c
@@ -38,8 +38,7 @@
 };
 static uint32_t binder_alloc_debug_mask = BINDER_DEBUG_USER_ERROR;
 
-module_param_named(debug_mask, binder_alloc_debug_mask,
-		   uint, 0644);
+module_param_named(alloc_debug_mask, binder_alloc_debug_mask, uint, 0644);
 
 #define binder_alloc_debug(mask, x...) \
 	do { \
@@ -212,7 +211,7 @@
 		mm = alloc->vma_vm_mm;
 
 	if (mm) {
-		down_read(&mm->mmap_sem);
+		down_write(&mm->mmap_sem);
 		vma = alloc->vma;
 	}
 
@@ -271,14 +270,13 @@
 		/* vm_insert_page does not seem to increment the refcount */
 	}
 	if (mm) {
-		up_read(&mm->mmap_sem);
-		mmput(mm);
+		up_write(&mm->mmap_sem);
+		mmput_async(mm);
 	}
 	return 0;
 
 free_range:
-	for (page_addr = end - PAGE_SIZE; page_addr >= start;
-	     page_addr -= PAGE_SIZE) {
+	for (page_addr = end - PAGE_SIZE; 1; page_addr -= PAGE_SIZE) {
 		bool ret;
 		size_t index;
 
@@ -291,6 +289,8 @@
 		WARN_ON(!ret);
 
 		trace_binder_free_lru_end(alloc, index);
+		if (page_addr == start)
+			break;
 		continue;
 
 err_vm_insert_page_failed:
@@ -298,12 +298,13 @@
 		page->page_ptr = NULL;
 err_alloc_page_failed:
 err_page_ptr_cleared:
-		;
+		if (page_addr == start)
+			break;
 	}
 err_no_vma:
 	if (mm) {
-		up_read(&mm->mmap_sem);
-		mmput(mm);
+		up_write(&mm->mmap_sem);
+		mmput_async(mm);
 	}
 	return vma ? -ENOMEM : -ESRCH;
 }
@@ -376,17 +377,17 @@
 				alloc->pid, extra_buffers_size);
 		return ERR_PTR(-EINVAL);
 	}
-	if (is_async &&
-	    alloc->free_async_space < size + sizeof(struct binder_buffer)) {
+
+	/* Pad 0-size buffers so they get assigned unique addresses */
+	size = max(size, sizeof(void *));
+
+	if (is_async && alloc->free_async_space < size) {
 		binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,
 			     "%d: binder_alloc_buf size %zd failed, no async space left\n",
 			      alloc->pid, size);
 		return ERR_PTR(-ENOSPC);
 	}
 
-	/* Pad 0-size buffers so they get assigned unique addresses */
-	size = max(size, sizeof(void *));
-
 	while (n) {
 		buffer = rb_entry(n, struct binder_buffer, rb_node);
 		BUG_ON(!buffer->free);
@@ -486,7 +487,7 @@
 	buffer->async_transaction = is_async;
 	buffer->extra_buffers_size = extra_buffers_size;
 	if (is_async) {
-		alloc->free_async_space -= size + sizeof(struct binder_buffer);
+		alloc->free_async_space -= size;
 		binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC_ASYNC,
 			     "%d: binder_alloc_buf size %zd async free %zd\n",
 			      alloc->pid, size, alloc->free_async_space);
@@ -513,7 +514,7 @@
  * is the sum of the three given sizes (each rounded up to
  * pointer-sized boundary)
  *
- * Return:	The allocated buffer or %NULL if error
+ * Return:	The allocated buffer or %ERR_PTR(-errno) if error
  */
 struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc,
 					   size_t data_size,
@@ -611,8 +612,7 @@
 	BUG_ON(buffer->user_data > alloc->buffer + alloc->buffer_size);
 
 	if (buffer->async_transaction) {
-		alloc->free_async_space += size + sizeof(struct binder_buffer);
-
+		alloc->free_async_space += buffer_size;
 		binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC_ASYNC,
 			     "%d: binder_free_buf size %zd async free %zd\n",
 			      alloc->pid, size, alloc->free_async_space);
@@ -645,6 +645,8 @@
 	binder_insert_free_buffer(alloc, buffer);
 }
 
+static void binder_alloc_clear_buf(struct binder_alloc *alloc,
+				   struct binder_buffer *buffer);
 /**
  * binder_alloc_free_buf() - free a binder buffer
  * @alloc:	binder_alloc for this proc
@@ -655,6 +657,18 @@
 void binder_alloc_free_buf(struct binder_alloc *alloc,
 			    struct binder_buffer *buffer)
 {
+	/*
+	 * We could eliminate the call to binder_alloc_clear_buf()
+	 * from binder_alloc_deferred_release() by moving this to
+	 * binder_free_buf_locked(). However, that could
+	 * increase contention for the alloc mutex if clear_on_free
+	 * is used frequently for large buffers. The mutex is not
+	 * needed for correctness here.
+	 */
+	if (buffer->clear_on_free) {
+		binder_alloc_clear_buf(alloc, buffer);
+		buffer->clear_on_free = false;
+	}
 	mutex_lock(&alloc->mutex);
 	binder_free_buf_locked(alloc, buffer);
 	mutex_unlock(&alloc->mutex);
@@ -681,17 +695,17 @@
 	struct binder_buffer *buffer;
 
 	mutex_lock(&binder_alloc_mmap_lock);
-	if (alloc->buffer) {
+	if (alloc->buffer_size) {
 		ret = -EBUSY;
 		failure_string = "already mapped";
 		goto err_already_mapped;
 	}
+	alloc->buffer_size = min_t(unsigned long, vma->vm_end - vma->vm_start,
+				   SZ_4M);
+	mutex_unlock(&binder_alloc_mmap_lock);
 
 	alloc->buffer = (void __user *)vma->vm_start;
-	mutex_unlock(&binder_alloc_mmap_lock);
 
-	alloc->buffer_size = min_t(unsigned long, vma->vm_end - vma->vm_start,
-				   SZ_4M);
 	alloc->pages = kcalloc(alloc->buffer_size / PAGE_SIZE,
 			       sizeof(alloc->pages[0]),
 			       GFP_KERNEL);
@@ -722,8 +736,9 @@
 	kfree(alloc->pages);
 	alloc->pages = NULL;
 err_alloc_pages_failed:
-	mutex_lock(&binder_alloc_mmap_lock);
 	alloc->buffer = NULL;
+	mutex_lock(&binder_alloc_mmap_lock);
+	alloc->buffer_size = 0;
 err_already_mapped:
 	mutex_unlock(&binder_alloc_mmap_lock);
 	binder_alloc_debug(BINDER_DEBUG_USER_ERROR,
@@ -750,6 +765,10 @@
 		/* Transaction should already have been freed */
 		BUG_ON(buffer->transaction);
 
+		if (buffer->clear_on_free) {
+			binder_alloc_clear_buf(alloc, buffer);
+			buffer->clear_on_free = false;
+		}
 		binder_free_buf_locked(alloc, buffer);
 		buffers++;
 	}
@@ -841,14 +860,20 @@
 	int free = 0;
 
 	mutex_lock(&alloc->mutex);
-	for (i = 0; i < alloc->buffer_size / PAGE_SIZE; i++) {
-		page = &alloc->pages[i];
-		if (!page->page_ptr)
-			free++;
-		else if (list_empty(&page->lru))
-			active++;
-		else
-			lru++;
+	/*
+	 * Make sure the binder_alloc is fully initialized, otherwise we might
+	 * read inconsistent state.
+	 */
+	if (binder_alloc_get_vma(alloc) != NULL) {
+		for (i = 0; i < alloc->buffer_size / PAGE_SIZE; i++) {
+			page = &alloc->pages[i];
+			if (!page->page_ptr)
+				free++;
+			else if (list_empty(&page->lru))
+				active++;
+			else
+				lru++;
+		}
 	}
 	mutex_unlock(&alloc->mutex);
 	seq_printf(m, "  pages: %d:%d:%d\n", active, lru, free);
@@ -926,7 +951,9 @@
 		goto err_mmget;
 	if (!down_read_trylock(&mm->mmap_sem))
 		goto err_down_read_mmap_sem_failed;
-	vma = binder_alloc_get_vma(alloc);
+	vma = find_vma(mm, page_addr);
+	if (vma && vma != binder_alloc_get_vma(alloc))
+		goto err_invalid_vma;
 
 	list_lru_isolate(lru, item);
 	spin_unlock(lock);
@@ -939,7 +966,7 @@
 		trace_binder_unmap_user_end(alloc, index);
 	}
 	up_read(&mm->mmap_sem);
-	mmput(mm);
+	mmput_async(mm);
 
 	trace_binder_unmap_kernel_start(alloc, index);
 
@@ -952,6 +979,8 @@
 	mutex_unlock(&alloc->mutex);
 	return LRU_REMOVED_RETRY;
 
+err_invalid_vma:
+	up_read(&mm->mmap_sem);
 err_down_read_mmap_sem_failed:
 	mmput_async(mm);
 err_mmget:
@@ -1010,6 +1039,12 @@
 	return ret;
 }
 
+void binder_alloc_shrinker_exit(void)
+{
+	unregister_shrinker(&binder_shrinker);
+	list_lru_destroy(&binder_alloc_lru);
+}
+
 /**
  * check_buffer() - verify that buffer/offset is safe to access
  * @alloc: binder_alloc for this proc
@@ -1078,6 +1113,36 @@
 }
 
 /**
+ * binder_alloc_clear_buf() - zero out buffer
+ * @alloc: binder_alloc for this proc
+ * @buffer: binder buffer to be cleared
+ *
+ * memset the given buffer to 0
+ */
+static void binder_alloc_clear_buf(struct binder_alloc *alloc,
+				   struct binder_buffer *buffer)
+{
+	size_t bytes = binder_alloc_buffer_size(alloc, buffer);
+	binder_size_t buffer_offset = 0;
+
+	while (bytes) {
+		unsigned long size;
+		struct page *page;
+		pgoff_t pgoff;
+		void *kptr;
+
+		page = binder_alloc_get_page(alloc, buffer,
+					     buffer_offset, &pgoff);
+		size = min_t(size_t, bytes, PAGE_SIZE - pgoff);
+		kptr = kmap(page) + pgoff;
+		memset(kptr, 0, size);
+		kunmap(page);
+		bytes -= size;
+		buffer_offset += size;
+	}
+}
+
+/**
  * binder_alloc_copy_user_to_buffer() - copy src user to tgt user
  * @alloc: binder_alloc for this proc
  * @buffer: binder buffer to be accessed
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/android/binder_alloc.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/android/binder_alloc.h
@@ -6,6 +6,7 @@
 #ifndef _LINUX_BINDER_ALLOC_H
 #define _LINUX_BINDER_ALLOC_H
 
+#include <linux/kconfig.h>
 #include <linux/rbtree.h>
 #include <linux/list.h>
 #include <linux/mm.h>
@@ -23,6 +24,7 @@
  * @entry:              entry alloc->buffers
  * @rb_node:            node for allocated_buffers/free_buffers rb trees
  * @free:               %true if buffer is free
+ * @clear_on_free:      %true if buffer must be zeroed after use
  * @allow_user_free:    %true if user is allowed to free buffer
  * @async_transaction:  %true if buffer is in use for an async txn
  * @debug_id:           unique ID for debugging
@@ -40,9 +42,10 @@
 	struct rb_node rb_node; /* free entry by size or allocated entry */
 				/* by address */
 	unsigned free:1;
+	unsigned clear_on_free:1;
 	unsigned allow_user_free:1;
 	unsigned async_transaction:1;
-	unsigned debug_id:29;
+	unsigned debug_id:28;
 
 	struct binder_transaction *transaction;
 
@@ -105,7 +108,7 @@
 	size_t pages_high;
 };
 
-#ifdef CONFIG_ANDROID_BINDER_IPC_SELFTEST
+#if IS_ENABLED(CONFIG_ANDROID_BINDER_IPC_SELFTEST)
 void binder_selftest_alloc(struct binder_alloc *alloc);
 #else
 static inline void binder_selftest_alloc(struct binder_alloc *alloc) {}
@@ -120,6 +123,7 @@
 						  int is_async);
 extern void binder_alloc_init(struct binder_alloc *alloc);
 extern int binder_alloc_shrinker_init(void);
+extern void binder_alloc_shrinker_exit(void);
 extern void binder_alloc_vma_close(struct binder_alloc *alloc);
 extern struct binder_buffer *
 binder_alloc_prepare_to_free(struct binder_alloc *alloc,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/android/binder_internal.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/android/binder_internal.h
@@ -5,9 +5,11 @@
 
 #include <linux/export.h>
 #include <linux/fs.h>
+#include <linux/kconfig.h>
 #include <linux/list.h>
 #include <linux/miscdevice.h>
 #include <linux/mutex.h>
+#include <linux/refcount.h>
 #include <linux/stddef.h>
 #include <linux/types.h>
 #include <linux/uidgid.h>
@@ -33,6 +35,7 @@
 	struct miscdevice miscdev;
 	struct binder_context context;
 	struct inode *binderfs_inode;
+	refcount_t ref;
 };
 
 /**
@@ -73,7 +76,7 @@
 
 extern char *binder_devices_param;
 
-#ifdef CONFIG_ANDROID_BINDERFS
+#if IS_ENABLED(CONFIG_ANDROID_BINDERFS)
 extern bool is_binderfs_device(const struct inode *inode);
 extern struct dentry *binderfs_create_file(struct dentry *dir, const char *name,
 					   const struct file_operations *fops,
@@ -94,7 +97,7 @@
 static inline void binderfs_remove_file(struct dentry *dentry) {}
 #endif
 
-#ifdef CONFIG_ANDROID_BINDERFS
+#if IS_ENABLED(CONFIG_ANDROID_BINDERFS)
 extern int __init init_binderfs(void);
 #else
 static inline int __init init_binderfs(void)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/android/binderfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/android/binderfs.c
@@ -109,7 +109,7 @@
 	struct super_block *sb = ref_inode->i_sb;
 	struct binderfs_info *info = sb->s_fs_info;
 #if defined(CONFIG_IPC_NS)
-	bool use_reserve = (info->ipc_ns == &init_ipc_ns);
+	bool use_reserve = (info->ipc_ns == show_init_ipc_ns());
 #else
 	bool use_reserve = true;
 #endif
@@ -154,6 +154,7 @@
 	if (!name)
 		goto err;
 
+	refcount_set(&device->ref, 1);
 	device->binderfs_inode = inode;
 	device->context.binder_context_mgr_uid = INVALID_UID;
 	device->context.name = name;
@@ -257,8 +258,10 @@
 	ida_free(&binderfs_minors, device->miscdev.minor);
 	mutex_unlock(&binderfs_minors_mutex);
 
-	kfree(device->context.name);
-	kfree(device);
+	if (refcount_dec_and_test(&device->ref)) {
+		kfree(device->context.name);
+		kfree(device);
+	}
 }
 
 /**
@@ -405,7 +408,7 @@
 	struct dentry *root = sb->s_root;
 	struct binderfs_info *info = sb->s_fs_info;
 #if defined(CONFIG_IPC_NS)
-	bool use_reserve = (info->ipc_ns == &init_ipc_ns);
+	bool use_reserve = (info->ipc_ns == show_init_ipc_ns());
 #else
 	bool use_reserve = true;
 #endif
@@ -445,6 +448,7 @@
 	inode->i_uid = info->root_uid;
 	inode->i_gid = info->root_gid;
 
+	refcount_set(&device->ref, 1);
 	device->binderfs_inode = inode;
 	device->miscdev.minor = minor;
 
@@ -683,7 +687,7 @@
 		return -ENOMEM;
 	info = sb->s_fs_info;
 
-	info->ipc_ns = get_ipc_ns(current->nsproxy->ipc_ns);
+	info->ipc_ns = get_ipc_ns_exported(current->nsproxy->ipc_ns);
 
 	ret = binderfs_parse_mount_opts(data, &info->mount_opts);
 	if (ret)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/acard-ahci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/acard-ahci.c
@@ -56,7 +56,7 @@
 	__le32			size;	 /* bit 31 (EOT) max==0x10000 (64k) */
 };
 
-static void acard_ahci_qc_prep(struct ata_queued_cmd *qc);
+static enum ata_completion_errors acard_ahci_qc_prep(struct ata_queued_cmd *qc);
 static bool acard_ahci_qc_fill_rtf(struct ata_queued_cmd *qc);
 static int acard_ahci_port_start(struct ata_port *ap);
 static int acard_ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
@@ -210,7 +210,7 @@
 	return si;
 }
 
-static void acard_ahci_qc_prep(struct ata_queued_cmd *qc)
+static enum ata_completion_errors acard_ahci_qc_prep(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
 	struct ahci_port_priv *pp = ap->private_data;
@@ -248,6 +248,8 @@
 		opts |= AHCI_CMD_ATAPI | AHCI_CMD_PREFETCH;
 
 	ahci_fill_cmd_slot(pp, qc->hw_tag, opts);
+
+	return AC_ERR_OK;
 }
 
 static bool acard_ahci_qc_fill_rtf(struct ata_queued_cmd *qc)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/ahci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/ahci.c
@@ -48,6 +48,7 @@
 enum board_ids {
 	/* board IDs by feature in alphabetical order */
 	board_ahci,
+	board_ahci_43bit_dma,
 	board_ahci_ign_iferr,
 	board_ahci_mobile,
 	board_ahci_nomsi,
@@ -80,6 +81,8 @@
 
 static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
 static void ahci_remove_one(struct pci_dev *dev);
+static void ahci_shutdown_one(struct pci_dev *dev);
+static void ahci_intel_pcs_quirk(struct pci_dev *pdev, struct ahci_host_priv *hpriv);
 static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
 				 unsigned long deadline);
 static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class,
@@ -124,6 +127,13 @@
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_ops,
 	},
+	[board_ahci_43bit_dma] = {
+		AHCI_HFLAGS	(AHCI_HFLAG_43BIT_ONLY),
+		.flags		= AHCI_FLAG_COMMON,
+		.pio_mask	= ATA_PIO4,
+		.udma_mask	= ATA_UDMA6,
+		.port_ops	= &ahci_ops,
+	},
 	[board_ahci_ign_iferr] = {
 		AHCI_HFLAGS	(AHCI_HFLAG_IGN_IRQ_IF_ERR),
 		.flags		= AHCI_FLAG_COMMON,
@@ -236,6 +246,7 @@
 
 static const struct pci_device_id ahci_pci_tbl[] = {
 	/* Intel */
+	{ PCI_VDEVICE(INTEL, 0x06d6), board_ahci }, /* Comet Lake PCH-H RAID */
 	{ PCI_VDEVICE(INTEL, 0x2652), board_ahci }, /* ICH6 */
 	{ PCI_VDEVICE(INTEL, 0x2653), board_ahci }, /* ICH6M */
 	{ PCI_VDEVICE(INTEL, 0x27c1), board_ahci }, /* ICH7 */
@@ -392,11 +403,13 @@
 	{ PCI_VDEVICE(INTEL, 0xa252), board_ahci }, /* Lewisburg RAID*/
 	{ PCI_VDEVICE(INTEL, 0xa256), board_ahci }, /* Lewisburg RAID*/
 	{ PCI_VDEVICE(INTEL, 0xa356), board_ahci }, /* Cannon Lake PCH-H RAID */
+	{ PCI_VDEVICE(INTEL, 0x06d7), board_ahci }, /* Comet Lake-H RAID */
 	{ PCI_VDEVICE(INTEL, 0x0f22), board_ahci_mobile }, /* Bay Trail AHCI */
 	{ PCI_VDEVICE(INTEL, 0x0f23), board_ahci_mobile }, /* Bay Trail AHCI */
 	{ PCI_VDEVICE(INTEL, 0x22a3), board_ahci_mobile }, /* Cherry Tr. AHCI */
 	{ PCI_VDEVICE(INTEL, 0x5ae3), board_ahci_mobile }, /* ApolloLake AHCI */
 	{ PCI_VDEVICE(INTEL, 0x34d3), board_ahci_mobile }, /* Ice Lake LP AHCI */
+	{ PCI_VDEVICE(INTEL, 0x02d7), board_ahci_mobile }, /* Comet Lake PCH RAID */
 
 	/* JMicron 360/1/3/5/6, match class to avoid IDE function */
 	{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
@@ -418,6 +431,7 @@
 	/* AMD */
 	{ PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */
 	{ PCI_VDEVICE(AMD, 0x7900), board_ahci }, /* AMD CZ */
+	{ PCI_VDEVICE(AMD, 0x7901), board_ahci_mobile }, /* AMD Green Sardine */
 	/* AMD is using RAID class only for ahci controllers */
 	{ PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
 	  PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci },
@@ -557,11 +571,11 @@
 	{ PCI_VDEVICE(PROMISE, 0x3f20), board_ahci },	/* PDC42819 */
 	{ PCI_VDEVICE(PROMISE, 0x3781), board_ahci },   /* FastTrak TX8660 ahci-mode */
 
-	/* Asmedia */
+	/* ASMedia */
 	{ PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci },	/* ASM1060 */
 	{ PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci },	/* ASM1060 */
-	{ PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci },	/* ASM1061 */
-	{ PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci },	/* ASM1062 */
+	{ PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci_43bit_dma },	/* ASM1061 */
+	{ PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci_43bit_dma },	/* ASM1061/1062 */
 	{ PCI_VDEVICE(ASMEDIA, 0x0621), board_ahci },   /* ASM1061R */
 	{ PCI_VDEVICE(ASMEDIA, 0x0622), board_ahci },   /* ASM1062R */
 
@@ -593,6 +607,7 @@
 	.id_table		= ahci_pci_tbl,
 	.probe			= ahci_init_one,
 	.remove			= ahci_remove_one,
+	.shutdown		= ahci_shutdown_one,
 	.driver = {
 		.pm		= &ahci_pci_pm_ops,
 	},
@@ -635,6 +650,25 @@
 	ahci_save_initial_config(&pdev->dev, hpriv);
 }
 
+static int ahci_pci_reset_controller(struct ata_host *host)
+{
+	struct pci_dev *pdev = to_pci_dev(host->dev);
+	struct ahci_host_priv *hpriv = host->private_data;
+	int rc;
+
+	rc = ahci_reset_controller(host);
+	if (rc)
+		return rc;
+
+	/*
+	 * If platform firmware failed to enable ports, try to enable
+	 * them here.
+	 */
+	ahci_intel_pcs_quirk(pdev, hpriv);
+
+	return 0;
+}
+
 static void ahci_pci_init_controller(struct ata_host *host)
 {
 	struct ahci_host_priv *hpriv = host->private_data;
@@ -837,7 +871,7 @@
 	struct ata_host *host = pci_get_drvdata(pdev);
 	int rc;
 
-	rc = ahci_reset_controller(host);
+	rc = ahci_pci_reset_controller(host);
 	if (rc)
 		return rc;
 	ahci_pci_init_controller(host);
@@ -872,7 +906,7 @@
 		ahci_mcp89_apple_enable(pdev);
 
 	if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
-		rc = ahci_reset_controller(host);
+		rc = ahci_pci_reset_controller(host);
 		if (rc)
 			return rc;
 
@@ -887,11 +921,20 @@
 
 #endif /* CONFIG_PM */
 
-static int ahci_configure_dma_masks(struct pci_dev *pdev, int using_dac)
+static int ahci_configure_dma_masks(struct pci_dev *pdev,
+				    struct ahci_host_priv *hpriv)
 {
-	const int dma_bits = using_dac ? 64 : 32;
+	int dma_bits;
 	int rc;
 
+	if (hpriv->cap & HOST_CAP_64) {
+		dma_bits = 64;
+		if (hpriv->flags & AHCI_HFLAG_43BIT_ONLY)
+			dma_bits = 43;
+	} else {
+		dma_bits = 32;
+	}
+
 	/*
 	 * If the device fixup already set the dma_mask to some non-standard
 	 * value, don't extend it here. This happens on STA2X11, for example.
@@ -1473,7 +1516,7 @@
 static void ahci_remap_check(struct pci_dev *pdev, int bar,
 		struct ahci_host_priv *hpriv)
 {
-	int i, count = 0;
+	int i;
 	u32 cap;
 
 	/*
@@ -1494,13 +1537,14 @@
 			continue;
 
 		/* We've found a remapped device */
-		count++;
+		hpriv->remapped_nvme++;
 	}
 
-	if (!count)
+	if (!hpriv->remapped_nvme)
 		return;
 
-	dev_warn(&pdev->dev, "Found %d remapped NVMe devices.\n", count);
+	dev_warn(&pdev->dev, "Found %u remapped NVMe devices.\n",
+		 hpriv->remapped_nvme);
 	dev_warn(&pdev->dev,
 		 "Switch your BIOS from RAID to AHCI mode to use them.\n");
 
@@ -1620,6 +1664,18 @@
 	}
 }
 
+static ssize_t remapped_nvme_show(struct device *dev,
+				  struct device_attribute *attr,
+				  char *buf)
+{
+	struct ata_host *host = dev_get_drvdata(dev);
+	struct ahci_host_priv *hpriv = host->private_data;
+
+	return sprintf(buf, "%u\n", hpriv->remapped_nvme);
+}
+
+static DEVICE_ATTR_RO(remapped_nvme);
+
 static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	unsigned int board_id = ent->driver_data;
@@ -1720,11 +1776,20 @@
 	/* detect remapped nvme devices */
 	ahci_remap_check(pdev, ahci_pci_bar, hpriv);
 
+	sysfs_add_file_to_group(&pdev->dev.kobj,
+				&dev_attr_remapped_nvme.attr,
+				NULL);
+
 	/* must set flag prior to save config in order to take effect */
 	if (ahci_broken_devslp(pdev))
 		hpriv->flags |= AHCI_HFLAG_NO_DEVSLP;
 
 #ifdef CONFIG_ARM64
+	if (pdev->vendor == PCI_VENDOR_ID_HUAWEI &&
+	    pdev->device == 0xa235 &&
+	    pdev->revision < 0x30)
+		hpriv->flags |= AHCI_HFLAG_NO_SXS;
+
 	if (pdev->vendor == 0x177d && pdev->device == 0xa01c)
 		hpriv->irq_handler = ahci_thunderx_irq_handler;
 #endif
@@ -1732,12 +1797,6 @@
 	/* save initial config */
 	ahci_pci_save_initial_config(pdev, hpriv);
 
-	/*
-	 * If platform firmware failed to enable ports, try to enable
-	 * them here.
-	 */
-	ahci_intel_pcs_quirk(pdev, hpriv);
-
 	/* prepare host */
 	if (hpriv->cap & HOST_CAP_NCQ) {
 		pi.flags |= ATA_FLAG_NCQ;
@@ -1815,6 +1874,15 @@
 	else
 		dev_info(&pdev->dev, "SSS flag set, parallel bus scan disabled\n");
 
+	if (!(hpriv->cap & HOST_CAP_PART))
+		host->flags |= ATA_HOST_NO_PART;
+
+	if (!(hpriv->cap & HOST_CAP_SSC))
+		host->flags |= ATA_HOST_NO_SSC;
+
+	if (!(hpriv->cap2 & HOST_CAP2_SDS))
+		host->flags |= ATA_HOST_NO_DEVSLP;
+
 	if (pi.flags & ATA_FLAG_EM)
 		ahci_reset_em(host);
 
@@ -1843,11 +1911,11 @@
 	ahci_gtf_filter_workaround(host);
 
 	/* initialize adapter */
-	rc = ahci_configure_dma_masks(pdev, hpriv->cap & HOST_CAP_64);
+	rc = ahci_configure_dma_masks(pdev, hpriv);
 	if (rc)
 		return rc;
 
-	rc = ahci_reset_controller(host);
+	rc = ahci_pci_reset_controller(host);
 	if (rc)
 		return rc;
 
@@ -1864,8 +1932,16 @@
 	return 0;
 }
 
+static void ahci_shutdown_one(struct pci_dev *pdev)
+{
+	ata_pci_shutdown_one(pdev);
+}
+
 static void ahci_remove_one(struct pci_dev *pdev)
 {
+	sysfs_remove_file_from_group(&pdev->dev.kobj,
+				     &dev_attr_remapped_nvme.attr,
+				     NULL);
 	pm_runtime_get_noresume(&pdev->dev);
 	ata_pci_remove_one(pdev);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/ahci.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/ahci.h
@@ -24,6 +24,7 @@
 #include <linux/libata.h>
 #include <linux/phy/phy.h>
 #include <linux/regulator/consumer.h>
+#include <linux/bits.h>
 
 /* Enclosure Management Control */
 #define EM_CTRL_MSG_TYPE              0x000f0000
@@ -54,12 +55,12 @@
 	AHCI_PORT_PRIV_FBS_DMA_SZ	= AHCI_CMD_SLOT_SZ +
 					  AHCI_CMD_TBL_AR_SZ +
 					  (AHCI_RX_FIS_SZ * 16),
-	AHCI_IRQ_ON_SG		= (1 << 31),
-	AHCI_CMD_ATAPI		= (1 << 5),
-	AHCI_CMD_WRITE		= (1 << 6),
-	AHCI_CMD_PREFETCH	= (1 << 7),
-	AHCI_CMD_RESET		= (1 << 8),
-	AHCI_CMD_CLR_BUSY	= (1 << 10),
+	AHCI_IRQ_ON_SG		= BIT(31),
+	AHCI_CMD_ATAPI		= BIT(5),
+	AHCI_CMD_WRITE		= BIT(6),
+	AHCI_CMD_PREFETCH	= BIT(7),
+	AHCI_CMD_RESET		= BIT(8),
+	AHCI_CMD_CLR_BUSY	= BIT(10),
 
 	RX_FIS_PIO_SETUP	= 0x20,	/* offset of PIO Setup FIS data */
 	RX_FIS_D2H_REG		= 0x40,	/* offset of D2H Register FIS data */
@@ -77,37 +78,37 @@
 	HOST_CAP2		= 0x24, /* host capabilities, extended */
 
 	/* HOST_CTL bits */
-	HOST_RESET		= (1 << 0),  /* reset controller; self-clear */
-	HOST_IRQ_EN		= (1 << 1),  /* global IRQ enable */
-	HOST_MRSM		= (1 << 2),  /* MSI Revert to Single Message */
-	HOST_AHCI_EN		= (1 << 31), /* AHCI enabled */
+	HOST_RESET		= BIT(0),  /* reset controller; self-clear */
+	HOST_IRQ_EN		= BIT(1),  /* global IRQ enable */
+	HOST_MRSM		= BIT(2),  /* MSI Revert to Single Message */
+	HOST_AHCI_EN		= BIT(31), /* AHCI enabled */
 
 	/* HOST_CAP bits */
-	HOST_CAP_SXS		= (1 << 5),  /* Supports External SATA */
-	HOST_CAP_EMS		= (1 << 6),  /* Enclosure Management support */
-	HOST_CAP_CCC		= (1 << 7),  /* Command Completion Coalescing */
-	HOST_CAP_PART		= (1 << 13), /* Partial state capable */
-	HOST_CAP_SSC		= (1 << 14), /* Slumber state capable */
-	HOST_CAP_PIO_MULTI	= (1 << 15), /* PIO multiple DRQ support */
-	HOST_CAP_FBS		= (1 << 16), /* FIS-based switching support */
-	HOST_CAP_PMP		= (1 << 17), /* Port Multiplier support */
-	HOST_CAP_ONLY		= (1 << 18), /* Supports AHCI mode only */
-	HOST_CAP_CLO		= (1 << 24), /* Command List Override support */
-	HOST_CAP_LED		= (1 << 25), /* Supports activity LED */
-	HOST_CAP_ALPM		= (1 << 26), /* Aggressive Link PM support */
-	HOST_CAP_SSS		= (1 << 27), /* Staggered Spin-up */
-	HOST_CAP_MPS		= (1 << 28), /* Mechanical presence switch */
-	HOST_CAP_SNTF		= (1 << 29), /* SNotification register */
-	HOST_CAP_NCQ		= (1 << 30), /* Native Command Queueing */
-	HOST_CAP_64		= (1 << 31), /* PCI DAC (64-bit DMA) support */
+	HOST_CAP_SXS		= BIT(5),  /* Supports External SATA */
+	HOST_CAP_EMS		= BIT(6),  /* Enclosure Management support */
+	HOST_CAP_CCC		= BIT(7),  /* Command Completion Coalescing */
+	HOST_CAP_PART		= BIT(13), /* Partial state capable */
+	HOST_CAP_SSC		= BIT(14), /* Slumber state capable */
+	HOST_CAP_PIO_MULTI	= BIT(15), /* PIO multiple DRQ support */
+	HOST_CAP_FBS		= BIT(16), /* FIS-based switching support */
+	HOST_CAP_PMP		= BIT(17), /* Port Multiplier support */
+	HOST_CAP_ONLY		= BIT(18), /* Supports AHCI mode only */
+	HOST_CAP_CLO		= BIT(24), /* Command List Override support */
+	HOST_CAP_LED		= BIT(25), /* Supports activity LED */
+	HOST_CAP_ALPM		= BIT(26), /* Aggressive Link PM support */
+	HOST_CAP_SSS		= BIT(27), /* Staggered Spin-up */
+	HOST_CAP_MPS		= BIT(28), /* Mechanical presence switch */
+	HOST_CAP_SNTF		= BIT(29), /* SNotification register */
+	HOST_CAP_NCQ		= BIT(30), /* Native Command Queueing */
+	HOST_CAP_64		= BIT(31), /* PCI DAC (64-bit DMA) support */
 
 	/* HOST_CAP2 bits */
-	HOST_CAP2_BOH		= (1 << 0),  /* BIOS/OS handoff supported */
-	HOST_CAP2_NVMHCI	= (1 << 1),  /* NVMHCI supported */
-	HOST_CAP2_APST		= (1 << 2),  /* Automatic partial to slumber */
-	HOST_CAP2_SDS		= (1 << 3),  /* Support device sleep */
-	HOST_CAP2_SADM		= (1 << 4),  /* Support aggressive DevSlp */
-	HOST_CAP2_DESO		= (1 << 5),  /* DevSlp from slumber only */
+	HOST_CAP2_BOH		= BIT(0),  /* BIOS/OS handoff supported */
+	HOST_CAP2_NVMHCI	= BIT(1),  /* NVMHCI supported */
+	HOST_CAP2_APST		= BIT(2),  /* Automatic partial to slumber */
+	HOST_CAP2_SDS		= BIT(3),  /* Support device sleep */
+	HOST_CAP2_SADM		= BIT(4),  /* Support aggressive DevSlp */
+	HOST_CAP2_DESO		= BIT(5),  /* DevSlp from slumber only */
 
 	/* registers for each SATA port */
 	PORT_LST_ADDR		= 0x00, /* command list DMA addr */
@@ -129,24 +130,24 @@
 	PORT_DEVSLP		= 0x44, /* device sleep */
 
 	/* PORT_IRQ_{STAT,MASK} bits */
-	PORT_IRQ_COLD_PRES	= (1 << 31), /* cold presence detect */
-	PORT_IRQ_TF_ERR		= (1 << 30), /* task file error */
-	PORT_IRQ_HBUS_ERR	= (1 << 29), /* host bus fatal error */
-	PORT_IRQ_HBUS_DATA_ERR	= (1 << 28), /* host bus data error */
-	PORT_IRQ_IF_ERR		= (1 << 27), /* interface fatal error */
-	PORT_IRQ_IF_NONFATAL	= (1 << 26), /* interface non-fatal error */
-	PORT_IRQ_OVERFLOW	= (1 << 24), /* xfer exhausted available S/G */
-	PORT_IRQ_BAD_PMP	= (1 << 23), /* incorrect port multiplier */
-
-	PORT_IRQ_PHYRDY		= (1 << 22), /* PhyRdy changed */
-	PORT_IRQ_DEV_ILCK	= (1 << 7), /* device interlock */
-	PORT_IRQ_CONNECT	= (1 << 6), /* port connect change status */
-	PORT_IRQ_SG_DONE	= (1 << 5), /* descriptor processed */
-	PORT_IRQ_UNK_FIS	= (1 << 4), /* unknown FIS rx'd */
-	PORT_IRQ_SDB_FIS	= (1 << 3), /* Set Device Bits FIS rx'd */
-	PORT_IRQ_DMAS_FIS	= (1 << 2), /* DMA Setup FIS rx'd */
-	PORT_IRQ_PIOS_FIS	= (1 << 1), /* PIO Setup FIS rx'd */
-	PORT_IRQ_D2H_REG_FIS	= (1 << 0), /* D2H Register FIS rx'd */
+	PORT_IRQ_COLD_PRES	= BIT(31), /* cold presence detect */
+	PORT_IRQ_TF_ERR		= BIT(30), /* task file error */
+	PORT_IRQ_HBUS_ERR	= BIT(29), /* host bus fatal error */
+	PORT_IRQ_HBUS_DATA_ERR	= BIT(28), /* host bus data error */
+	PORT_IRQ_IF_ERR		= BIT(27), /* interface fatal error */
+	PORT_IRQ_IF_NONFATAL	= BIT(26), /* interface non-fatal error */
+	PORT_IRQ_OVERFLOW	= BIT(24), /* xfer exhausted available S/G */
+	PORT_IRQ_BAD_PMP	= BIT(23), /* incorrect port multiplier */
+
+	PORT_IRQ_PHYRDY		= BIT(22), /* PhyRdy changed */
+	PORT_IRQ_DEV_ILCK	= BIT(7),  /* device interlock */
+	PORT_IRQ_CONNECT	= BIT(6),  /* port connect change status */
+	PORT_IRQ_SG_DONE	= BIT(5),  /* descriptor processed */
+	PORT_IRQ_UNK_FIS	= BIT(4),  /* unknown FIS rx'd */
+	PORT_IRQ_SDB_FIS	= BIT(3),  /* Set Device Bits FIS rx'd */
+	PORT_IRQ_DMAS_FIS	= BIT(2),  /* DMA Setup FIS rx'd */
+	PORT_IRQ_PIOS_FIS	= BIT(1),  /* PIO Setup FIS rx'd */
+	PORT_IRQ_D2H_REG_FIS	= BIT(0),  /* D2H Register FIS rx'd */
 
 	PORT_IRQ_FREEZE		= PORT_IRQ_HBUS_ERR |
 				  PORT_IRQ_IF_ERR |
@@ -162,34 +163,34 @@
 				  PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS,
 
 	/* PORT_CMD bits */
-	PORT_CMD_ASP		= (1 << 27), /* Aggressive Slumber/Partial */
-	PORT_CMD_ALPE		= (1 << 26), /* Aggressive Link PM enable */
-	PORT_CMD_ATAPI		= (1 << 24), /* Device is ATAPI */
-	PORT_CMD_FBSCP		= (1 << 22), /* FBS Capable Port */
-	PORT_CMD_ESP		= (1 << 21), /* External Sata Port */
-	PORT_CMD_HPCP		= (1 << 18), /* HotPlug Capable Port */
-	PORT_CMD_PMP		= (1 << 17), /* PMP attached */
-	PORT_CMD_LIST_ON	= (1 << 15), /* cmd list DMA engine running */
-	PORT_CMD_FIS_ON		= (1 << 14), /* FIS DMA engine running */
-	PORT_CMD_FIS_RX		= (1 << 4), /* Enable FIS receive DMA engine */
-	PORT_CMD_CLO		= (1 << 3), /* Command list override */
-	PORT_CMD_POWER_ON	= (1 << 2), /* Power up device */
-	PORT_CMD_SPIN_UP	= (1 << 1), /* Spin up device */
-	PORT_CMD_START		= (1 << 0), /* Enable port DMA engine */
-
-	PORT_CMD_ICC_MASK	= (0xf << 28), /* i/f ICC state mask */
-	PORT_CMD_ICC_ACTIVE	= (0x1 << 28), /* Put i/f in active state */
-	PORT_CMD_ICC_PARTIAL	= (0x2 << 28), /* Put i/f in partial state */
-	PORT_CMD_ICC_SLUMBER	= (0x6 << 28), /* Put i/f in slumber state */
+	PORT_CMD_ASP		= BIT(27), /* Aggressive Slumber/Partial */
+	PORT_CMD_ALPE		= BIT(26), /* Aggressive Link PM enable */
+	PORT_CMD_ATAPI		= BIT(24), /* Device is ATAPI */
+	PORT_CMD_FBSCP		= BIT(22), /* FBS Capable Port */
+	PORT_CMD_ESP		= BIT(21), /* External Sata Port */
+	PORT_CMD_HPCP		= BIT(18), /* HotPlug Capable Port */
+	PORT_CMD_PMP		= BIT(17), /* PMP attached */
+	PORT_CMD_LIST_ON	= BIT(15), /* cmd list DMA engine running */
+	PORT_CMD_FIS_ON		= BIT(14), /* FIS DMA engine running */
+	PORT_CMD_FIS_RX		= BIT(4),  /* Enable FIS receive DMA engine */
+	PORT_CMD_CLO		= BIT(3),  /* Command list override */
+	PORT_CMD_POWER_ON	= BIT(2),  /* Power up device */
+	PORT_CMD_SPIN_UP	= BIT(1),  /* Spin up device */
+	PORT_CMD_START		= BIT(0),  /* Enable port DMA engine */
+
+	PORT_CMD_ICC_MASK	= (0xfu << 28), /* i/f ICC state mask */
+	PORT_CMD_ICC_ACTIVE	= (0x1u << 28), /* Put i/f in active state */
+	PORT_CMD_ICC_PARTIAL	= (0x2u << 28), /* Put i/f in partial state */
+	PORT_CMD_ICC_SLUMBER	= (0x6u << 28), /* Put i/f in slumber state */
 
 	/* PORT_FBS bits */
 	PORT_FBS_DWE_OFFSET	= 16, /* FBS device with error offset */
 	PORT_FBS_ADO_OFFSET	= 12, /* FBS active dev optimization offset */
 	PORT_FBS_DEV_OFFSET	= 8,  /* FBS device to issue offset */
 	PORT_FBS_DEV_MASK	= (0xf << PORT_FBS_DEV_OFFSET),  /* FBS.DEV */
-	PORT_FBS_SDE		= (1 << 2), /* FBS single device error */
-	PORT_FBS_DEC		= (1 << 1), /* FBS device error clear */
-	PORT_FBS_EN		= (1 << 0), /* Enable FBS */
+	PORT_FBS_SDE		= BIT(2), /* FBS single device error */
+	PORT_FBS_DEC		= BIT(1), /* FBS device error clear */
+	PORT_FBS_EN		= BIT(0), /* Enable FBS */
 
 	/* PORT_DEVSLP bits */
 	PORT_DEVSLP_DM_OFFSET	= 25,             /* DITO multiplier offset */
@@ -197,49 +198,53 @@
 	PORT_DEVSLP_DITO_OFFSET	= 15,             /* DITO offset */
 	PORT_DEVSLP_MDAT_OFFSET	= 10,             /* Minimum assertion time */
 	PORT_DEVSLP_DETO_OFFSET	= 2,              /* DevSlp exit timeout */
-	PORT_DEVSLP_DSP		= (1 << 1),       /* DevSlp present */
-	PORT_DEVSLP_ADSE	= (1 << 0),       /* Aggressive DevSlp enable */
+	PORT_DEVSLP_DSP		= BIT(1),         /* DevSlp present */
+	PORT_DEVSLP_ADSE	= BIT(0),         /* Aggressive DevSlp enable */
 
 	/* hpriv->flags bits */
 
 #define AHCI_HFLAGS(flags)		.private_data	= (void *)(flags)
 
-	AHCI_HFLAG_NO_NCQ		= (1 << 0),
-	AHCI_HFLAG_IGN_IRQ_IF_ERR	= (1 << 1), /* ignore IRQ_IF_ERR */
-	AHCI_HFLAG_IGN_SERR_INTERNAL	= (1 << 2), /* ignore SERR_INTERNAL */
-	AHCI_HFLAG_32BIT_ONLY		= (1 << 3), /* force 32bit */
-	AHCI_HFLAG_MV_PATA		= (1 << 4), /* PATA port */
-	AHCI_HFLAG_NO_MSI		= (1 << 5), /* no PCI MSI */
-	AHCI_HFLAG_NO_PMP		= (1 << 6), /* no PMP */
-	AHCI_HFLAG_SECT255		= (1 << 8), /* max 255 sectors */
-	AHCI_HFLAG_YES_NCQ		= (1 << 9), /* force NCQ cap on */
-	AHCI_HFLAG_NO_SUSPEND		= (1 << 10), /* don't suspend */
-	AHCI_HFLAG_SRST_TOUT_IS_OFFLINE	= (1 << 11), /* treat SRST timeout as
-							link offline */
-	AHCI_HFLAG_NO_SNTF		= (1 << 12), /* no sntf */
-	AHCI_HFLAG_NO_FPDMA_AA		= (1 << 13), /* no FPDMA AA */
-	AHCI_HFLAG_YES_FBS		= (1 << 14), /* force FBS cap on */
-	AHCI_HFLAG_DELAY_ENGINE		= (1 << 15), /* do not start engine on
-						        port start (wait until
-						        error-handling stage) */
-	AHCI_HFLAG_NO_DEVSLP		= (1 << 17), /* no device sleep */
-	AHCI_HFLAG_NO_FBS		= (1 << 18), /* no FBS */
+	AHCI_HFLAG_NO_NCQ		= BIT(0),
+	AHCI_HFLAG_IGN_IRQ_IF_ERR	= BIT(1), /* ignore IRQ_IF_ERR */
+	AHCI_HFLAG_IGN_SERR_INTERNAL	= BIT(2), /* ignore SERR_INTERNAL */
+	AHCI_HFLAG_32BIT_ONLY		= BIT(3), /* force 32bit */
+	AHCI_HFLAG_MV_PATA		= BIT(4), /* PATA port */
+	AHCI_HFLAG_NO_MSI		= BIT(5), /* no PCI MSI */
+	AHCI_HFLAG_NO_PMP		= BIT(6), /* no PMP */
+	AHCI_HFLAG_SECT255		= BIT(8), /* max 255 sectors */
+	AHCI_HFLAG_YES_NCQ		= BIT(9), /* force NCQ cap on */
+	AHCI_HFLAG_NO_SUSPEND		= BIT(10), /* don't suspend */
+	AHCI_HFLAG_SRST_TOUT_IS_OFFLINE	= BIT(11), /* treat SRST timeout as
+						      link offline */
+	AHCI_HFLAG_NO_SNTF		= BIT(12), /* no sntf */
+	AHCI_HFLAG_NO_FPDMA_AA		= BIT(13), /* no FPDMA AA */
+	AHCI_HFLAG_YES_FBS		= BIT(14), /* force FBS cap on */
+	AHCI_HFLAG_DELAY_ENGINE		= BIT(15), /* do not start engine on
+						      port start (wait until
+						      error-handling stage) */
+	AHCI_HFLAG_NO_DEVSLP		= BIT(17), /* no device sleep */
+	AHCI_HFLAG_NO_FBS		= BIT(18), /* no FBS */
 
 #ifdef CONFIG_PCI_MSI
-	AHCI_HFLAG_MULTI_MSI		= (1 << 20), /* per-port MSI(-X) */
+	AHCI_HFLAG_MULTI_MSI		= BIT(20), /* per-port MSI(-X) */
 #else
 	/* compile out MSI infrastructure */
 	AHCI_HFLAG_MULTI_MSI		= 0,
 #endif
-	AHCI_HFLAG_WAKE_BEFORE_STOP	= (1 << 22), /* wake before DMA stop */
-	AHCI_HFLAG_YES_ALPM		= (1 << 23), /* force ALPM cap on */
-	AHCI_HFLAG_NO_WRITE_TO_RO	= (1 << 24), /* don't write to read
-							only registers */
-	AHCI_HFLAG_IS_MOBILE		= (1 << 25), /* mobile chipset, use
-							SATA_MOBILE_LPM_POLICY
-							as default lpm_policy */
-	AHCI_HFLAG_SUSPEND_PHYS		= (1 << 26), /* handle PHYs during
-							suspend/resume */
+	AHCI_HFLAG_WAKE_BEFORE_STOP	= BIT(22), /* wake before DMA stop */
+	AHCI_HFLAG_YES_ALPM		= BIT(23), /* force ALPM cap on */
+	AHCI_HFLAG_NO_WRITE_TO_RO	= BIT(24), /* don't write to read
+						      only registers */
+	AHCI_HFLAG_IS_MOBILE            = BIT(25), /* mobile chipset, use
+						      SATA_MOBILE_LPM_POLICY
+						      as default lpm_policy */
+	AHCI_HFLAG_SUSPEND_PHYS		= BIT(26), /* handle PHYs during
+						      suspend/resume */
+	AHCI_HFLAG_IGN_NOTSUPP_POWER_ON	= BIT(27), /* ignore -EOPNOTSUPP
+						      from phy_power_on() */
+	AHCI_HFLAG_NO_SXS		= BIT(28), /* SXS not supported */
+	AHCI_HFLAG_43BIT_ONLY		= BIT(29), /* 43bit DMA addr limit */
 
 	/* ap->flags bits */
 
@@ -251,26 +256,26 @@
 	PCS_7				= 0x94, /* 7+ port PCS (Denverton) */
 
 	/* em constants */
-	EM_MAX_SLOTS			= 8,
+	EM_MAX_SLOTS			= SATA_PMP_MAX_PORTS,
 	EM_MAX_RETRY			= 5,
 
 	/* em_ctl bits */
-	EM_CTL_RST		= (1 << 9), /* Reset */
-	EM_CTL_TM		= (1 << 8), /* Transmit Message */
-	EM_CTL_MR		= (1 << 0), /* Message Received */
-	EM_CTL_ALHD		= (1 << 26), /* Activity LED */
-	EM_CTL_XMT		= (1 << 25), /* Transmit Only */
-	EM_CTL_SMB		= (1 << 24), /* Single Message Buffer */
-	EM_CTL_SGPIO		= (1 << 19), /* SGPIO messages supported */
-	EM_CTL_SES		= (1 << 18), /* SES-2 messages supported */
-	EM_CTL_SAFTE		= (1 << 17), /* SAF-TE messages supported */
-	EM_CTL_LED		= (1 << 16), /* LED messages supported */
+	EM_CTL_RST		= BIT(9), /* Reset */
+	EM_CTL_TM		= BIT(8), /* Transmit Message */
+	EM_CTL_MR		= BIT(0), /* Message Received */
+	EM_CTL_ALHD		= BIT(26), /* Activity LED */
+	EM_CTL_XMT		= BIT(25), /* Transmit Only */
+	EM_CTL_SMB		= BIT(24), /* Single Message Buffer */
+	EM_CTL_SGPIO		= BIT(19), /* SGPIO messages supported */
+	EM_CTL_SES		= BIT(18), /* SES-2 messages supported */
+	EM_CTL_SAFTE		= BIT(17), /* SAF-TE messages supported */
+	EM_CTL_LED		= BIT(16), /* LED messages supported */
 
 	/* em message type */
-	EM_MSG_TYPE_LED		= (1 << 0), /* LED */
-	EM_MSG_TYPE_SAFTE	= (1 << 1), /* SAF-TE */
-	EM_MSG_TYPE_SES2	= (1 << 2), /* SES-2 */
-	EM_MSG_TYPE_SGPIO	= (1 << 3), /* SGPIO */
+	EM_MSG_TYPE_LED		= BIT(0), /* LED */
+	EM_MSG_TYPE_SAFTE	= BIT(1), /* SAF-TE */
+	EM_MSG_TYPE_SES2	= BIT(2), /* SES-2 */
+	EM_MSG_TYPE_SGPIO	= BIT(3), /* SGPIO */
 };
 
 struct ahci_cmd_hdr {
@@ -336,6 +341,7 @@
 	u32 			em_loc; /* enclosure management location */
 	u32			em_buf_sz;	/* EM buffer size in byte */
 	u32			em_msg_type;	/* EM message type */
+	u32			remapped_nvme;	/* NVMe remapped device count */
 	bool			got_runtime_pm; /* Did we do pm_runtime_get? */
 	struct clk		*clks[AHCI_MAX_CLKS]; /* Optional */
 	struct reset_control	*rsts;		/* Optional */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/ahci_brcm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/ahci_brcm.c
@@ -76,8 +76,7 @@
 };
 
 enum brcm_ahci_quirks {
-	BRCM_AHCI_QUIRK_NO_NCQ		= BIT(0),
-	BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE	= BIT(1),
+	BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE	= BIT(0),
 };
 
 struct brcm_ahci_priv {
@@ -213,19 +212,12 @@
 			brcm_sata_phy_disable(priv, i);
 }
 
-static u32 brcm_ahci_get_portmask(struct platform_device *pdev,
+static u32 brcm_ahci_get_portmask(struct ahci_host_priv *hpriv,
 				  struct brcm_ahci_priv *priv)
 {
-	void __iomem *ahci;
-	struct resource *res;
 	u32 impl;
 
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ahci");
-	ahci = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(ahci))
-		return 0;
-
-	impl = readl(ahci + HOST_PORTS_IMPL);
+	impl = readl(hpriv->mmio + HOST_PORTS_IMPL);
 
 	if (fls(impl) > SATA_TOP_MAX_PHYS)
 		dev_warn(priv->dev, "warning: more ports than PHYs (%#x)\n",
@@ -233,9 +225,6 @@
 	else if (!impl)
 		dev_info(priv->dev, "no ports found\n");
 
-	devm_iounmap(&pdev->dev, ahci);
-	devm_release_mem_region(&pdev->dev, res->start, resource_size(res));
-
 	return impl;
 }
 
@@ -285,6 +274,13 @@
 	/* Perform the SATA PHY reset sequence */
 	brcm_sata_phy_disable(priv, ap->port_no);
 
+	/* Reset the SATA clock */
+	ahci_platform_disable_clks(hpriv);
+	msleep(10);
+
+	ahci_platform_enable_clks(hpriv);
+	msleep(10);
+
 	/* Bring the PHY back on */
 	brcm_sata_phy_enable(priv, ap->port_no);
 
@@ -347,11 +343,10 @@
 	struct ata_host *host = dev_get_drvdata(dev);
 	struct ahci_host_priv *hpriv = host->private_data;
 	struct brcm_ahci_priv *priv = hpriv->plat_data;
-	int ret;
 
-	ret = ahci_platform_suspend(dev);
 	brcm_sata_phys_disable(priv);
-	return ret;
+
+	return ahci_platform_suspend(dev);
 }
 
 static int brcm_ahci_resume(struct device *dev)
@@ -359,11 +354,50 @@
 	struct ata_host *host = dev_get_drvdata(dev);
 	struct ahci_host_priv *hpriv = host->private_data;
 	struct brcm_ahci_priv *priv = hpriv->plat_data;
+	int ret;
+
+	/* Make sure clocks are turned on before re-configuration */
+	ret = ahci_platform_enable_clks(hpriv);
+	if (ret)
+		return ret;
+
+	ret = ahci_platform_enable_regulators(hpriv);
+	if (ret)
+		goto out_disable_clks;
 
 	brcm_sata_init(priv);
 	brcm_sata_phys_enable(priv);
 	brcm_sata_alpm_init(hpriv);
-	return ahci_platform_resume(dev);
+
+	/* Since we had to enable clocks earlier on, we cannot use
+	 * ahci_platform_resume() as-is since a second call to
+	 * ahci_platform_enable_resources() would bump up the resources
+	 * (regulators, clocks, PHYs) count artificially so we copy the part
+	 * after ahci_platform_enable_resources().
+	 */
+	ret = ahci_platform_enable_phys(hpriv);
+	if (ret)
+		goto out_disable_phys;
+
+	ret = ahci_platform_resume_host(dev);
+	if (ret)
+		goto out_disable_platform_phys;
+
+	/* We resumed so update PM runtime state */
+	pm_runtime_disable(dev);
+	pm_runtime_set_active(dev);
+	pm_runtime_enable(dev);
+
+	return 0;
+
+out_disable_platform_phys:
+	ahci_platform_disable_phys(hpriv);
+out_disable_phys:
+	brcm_sata_phys_disable(priv);
+	ahci_platform_disable_regulators(hpriv);
+out_disable_clks:
+	ahci_platform_disable_clks(hpriv);
+	return ret;
 }
 #endif
 
@@ -410,44 +444,77 @@
 	if (!IS_ERR_OR_NULL(priv->rcdev))
 		reset_control_deassert(priv->rcdev);
 
-	if ((priv->version == BRCM_SATA_BCM7425) ||
-		(priv->version == BRCM_SATA_NSP)) {
-		priv->quirks |= BRCM_AHCI_QUIRK_NO_NCQ;
+	hpriv = ahci_platform_get_resources(pdev, 0);
+	if (IS_ERR(hpriv)) {
+		ret = PTR_ERR(hpriv);
+		goto out_reset;
+	}
+
+	hpriv->plat_data = priv;
+	hpriv->flags = AHCI_HFLAG_WAKE_BEFORE_STOP | AHCI_HFLAG_NO_WRITE_TO_RO;
+
+	switch (priv->version) {
+	case BRCM_SATA_BCM7425:
+		hpriv->flags |= AHCI_HFLAG_DELAY_ENGINE;
+		/* fall through */
+	case BRCM_SATA_NSP:
+		hpriv->flags |= AHCI_HFLAG_NO_NCQ;
 		priv->quirks |= BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE;
+		break;
+	default:
+		break;
 	}
 
+	ret = ahci_platform_enable_clks(hpriv);
+	if (ret)
+		goto out_reset;
+
+	ret = ahci_platform_enable_regulators(hpriv);
+	if (ret)
+		goto out_disable_clks;
+
+	/* Must be first so as to configure endianness including that
+	 * of the standard AHCI register space.
+	 */
 	brcm_sata_init(priv);
 
-	priv->port_mask = brcm_ahci_get_portmask(pdev, priv);
-	if (!priv->port_mask)
-		return -ENODEV;
+	/* Initializes priv->port_mask which is used below */
+	priv->port_mask = brcm_ahci_get_portmask(hpriv, priv);
+	if (!priv->port_mask) {
+		ret = -ENODEV;
+		goto out_disable_regulators;
+	}
 
+	/* Must be done before ahci_platform_enable_phys() */
 	brcm_sata_phys_enable(priv);
 
-	hpriv = ahci_platform_get_resources(pdev, 0);
-	if (IS_ERR(hpriv))
-		return PTR_ERR(hpriv);
-	hpriv->plat_data = priv;
-	hpriv->flags = AHCI_HFLAG_WAKE_BEFORE_STOP;
-
 	brcm_sata_alpm_init(hpriv);
 
-	ret = ahci_platform_enable_resources(hpriv);
+	ret = ahci_platform_enable_phys(hpriv);
 	if (ret)
-		return ret;
-
-	if (priv->quirks & BRCM_AHCI_QUIRK_NO_NCQ)
-		hpriv->flags |= AHCI_HFLAG_NO_NCQ;
-	hpriv->flags |= AHCI_HFLAG_NO_WRITE_TO_RO;
+		goto out_disable_phys;
 
 	ret = ahci_platform_init_host(pdev, hpriv, &ahci_brcm_port_info,
 				      &ahci_platform_sht);
 	if (ret)
-		return ret;
+		goto out_disable_platform_phys;
 
 	dev_info(dev, "Broadcom AHCI SATA3 registered\n");
 
 	return 0;
+
+out_disable_platform_phys:
+	ahci_platform_disable_phys(hpriv);
+out_disable_phys:
+	brcm_sata_phys_disable(priv);
+out_disable_regulators:
+	ahci_platform_disable_regulators(hpriv);
+out_disable_clks:
+	ahci_platform_disable_clks(hpriv);
+out_reset:
+	if (!IS_ERR_OR_NULL(priv->rcdev))
+		reset_control_assert(priv->rcdev);
+	return ret;
 }
 
 static int brcm_ahci_remove(struct platform_device *pdev)
@@ -457,12 +524,12 @@
 	struct brcm_ahci_priv *priv = hpriv->plat_data;
 	int ret;
 
+	brcm_sata_phys_disable(priv);
+
 	ret = ata_platform_remove_one(pdev);
 	if (ret)
 		return ret;
 
-	brcm_sata_phys_disable(priv);
-
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/ahci_imx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/ahci_imx.c
@@ -1239,4 +1239,4 @@
 MODULE_DESCRIPTION("Freescale i.MX AHCI SATA platform driver");
 MODULE_AUTHOR("Richard Zhu <Hong-Xing.Zhu@freescale.com>");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("ahci:imx");
+MODULE_ALIAS("platform:" DRV_NAME);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/ahci_mvebu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/ahci_mvebu.c
@@ -227,7 +227,7 @@
 
 static const struct ahci_mvebu_plat_data ahci_mvebu_armada_3700_plat_data = {
 	.plat_config = ahci_mvebu_armada_3700_config,
-	.flags = AHCI_HFLAG_SUSPEND_PHYS,
+	.flags = AHCI_HFLAG_SUSPEND_PHYS | AHCI_HFLAG_IGN_NOTSUPP_POWER_ON,
 };
 
 static const struct of_device_id ahci_mvebu_of_match[] = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/ahci_sunxi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/ahci_sunxi.c
@@ -200,7 +200,7 @@
 }
 
 static const struct ata_port_info ahci_sunxi_port_info = {
-	.flags		= AHCI_FLAG_COMMON | ATA_FLAG_NCQ,
+	.flags		= AHCI_FLAG_COMMON | ATA_FLAG_NCQ | ATA_FLAG_NO_DIPM,
 	.pio_mask	= ATA_PIO4,
 	.udma_mask	= ATA_UDMA6,
 	.port_ops	= &ahci_platform_ops,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/libahci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/libahci.c
@@ -57,7 +57,7 @@
 static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc);
 static int ahci_port_start(struct ata_port *ap);
 static void ahci_port_stop(struct ata_port *ap);
-static void ahci_qc_prep(struct ata_queued_cmd *qc);
+static enum ata_completion_errors ahci_qc_prep(struct ata_queued_cmd *qc);
 static int ahci_pmp_qc_defer(struct ata_queued_cmd *qc);
 static void ahci_freeze(struct ata_port *ap);
 static void ahci_thaw(struct ata_port *ap);
@@ -493,6 +493,11 @@
 		cap |= HOST_CAP_ALPM;
 	}
 
+	if ((cap & HOST_CAP_SXS) && (hpriv->flags & AHCI_HFLAG_NO_SXS)) {
+		dev_info(dev, "controller does not support SXS, disabling CAP_SXS\n");
+		cap &= ~HOST_CAP_SXS;
+	}
+
 	if (hpriv->force_port_map && port_map != hpriv->force_port_map) {
 		dev_info(dev, "forcing port_map 0x%x -> 0x%x\n",
 			 port_map, hpriv->force_port_map);
@@ -1194,6 +1199,26 @@
 	return sprintf(buf, "%d\n", emp->blink_policy);
 }
 
+static void ahci_port_clear_pending_irq(struct ata_port *ap)
+{
+	struct ahci_host_priv *hpriv = ap->host->private_data;
+	void __iomem *port_mmio = ahci_port_base(ap);
+	u32 tmp;
+
+	/* clear SError */
+	tmp = readl(port_mmio + PORT_SCR_ERR);
+	dev_dbg(ap->host->dev, "PORT_SCR_ERR 0x%x\n", tmp);
+	writel(tmp, port_mmio + PORT_SCR_ERR);
+
+	/* clear port IRQ */
+	tmp = readl(port_mmio + PORT_IRQ_STAT);
+	dev_dbg(ap->host->dev, "PORT_IRQ_STAT 0x%x\n", tmp);
+	if (tmp)
+		writel(tmp, port_mmio + PORT_IRQ_STAT);
+
+	writel(1 << ap->port_no, hpriv->mmio + HOST_IRQ_STAT);
+}
+
 static void ahci_port_init(struct device *dev, struct ata_port *ap,
 			   int port_no, void __iomem *mmio,
 			   void __iomem *port_mmio)
@@ -1208,18 +1233,7 @@
 	if (rc)
 		dev_warn(dev, "%s (%d)\n", emsg, rc);
 
-	/* clear SError */
-	tmp = readl(port_mmio + PORT_SCR_ERR);
-	VPRINTK("PORT_SCR_ERR 0x%x\n", tmp);
-	writel(tmp, port_mmio + PORT_SCR_ERR);
-
-	/* clear port IRQ */
-	tmp = readl(port_mmio + PORT_IRQ_STAT);
-	VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp);
-	if (tmp)
-		writel(tmp, port_mmio + PORT_IRQ_STAT);
-
-	writel(1 << port_no, mmio + HOST_IRQ_STAT);
+	ahci_port_clear_pending_irq(ap);
 
 	/* mark esata ports */
 	tmp = readl(port_mmio + PORT_CMD);
@@ -1549,6 +1563,8 @@
 	tf.command = ATA_BUSY;
 	ata_tf_to_fis(&tf, 0, 0, d2h_fis);
 
+	ahci_port_clear_pending_irq(ap);
+
 	rc = sata_link_hardreset(link, timing, deadline, online,
 				 ahci_check_ready);
 
@@ -1624,7 +1640,7 @@
 		return sata_pmp_qc_defer_cmd_switch(qc);
 }
 
-static void ahci_qc_prep(struct ata_queued_cmd *qc)
+static enum ata_completion_errors ahci_qc_prep(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
 	struct ahci_port_priv *pp = ap->private_data;
@@ -1660,6 +1676,8 @@
 		opts |= AHCI_CMD_ATAPI | AHCI_CMD_PREFETCH;
 
 	ahci_fill_cmd_slot(pp, qc->hw_tag, opts);
+
+	return AC_ERR_OK;
 }
 
 static void ahci_fbs_dec_intr(struct ata_port *ap)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/libahci_platform.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/libahci_platform.c
@@ -43,7 +43,7 @@
  * RETURNS:
  * 0 on success otherwise a negative error code
  */
-static int ahci_platform_enable_phys(struct ahci_host_priv *hpriv)
+int ahci_platform_enable_phys(struct ahci_host_priv *hpriv)
 {
 	int rc, i;
 
@@ -59,7 +59,7 @@
 		}
 
 		rc = phy_power_on(hpriv->phys[i]);
-		if (rc) {
+		if (rc && !(rc == -EOPNOTSUPP && (hpriv->flags & AHCI_HFLAG_IGN_NOTSUPP_POWER_ON))) {
 			phy_exit(hpriv->phys[i]);
 			goto disable_phys;
 		}
@@ -74,6 +74,7 @@
 	}
 	return rc;
 }
+EXPORT_SYMBOL_GPL(ahci_platform_enable_phys);
 
 /**
  * ahci_platform_disable_phys - Disable PHYs
@@ -81,7 +82,7 @@
  *
  * This function disables all PHYs found in hpriv->phys.
  */
-static void ahci_platform_disable_phys(struct ahci_host_priv *hpriv)
+void ahci_platform_disable_phys(struct ahci_host_priv *hpriv)
 {
 	int i;
 
@@ -90,6 +91,7 @@
 		phy_exit(hpriv->phys[i]);
 	}
 }
+EXPORT_SYMBOL_GPL(ahci_platform_disable_phys);
 
 /**
  * ahci_platform_enable_clks - Enable platform clocks
@@ -438,10 +440,7 @@
 	hpriv->phy_regulator = devm_regulator_get(dev, "phy");
 	if (IS_ERR(hpriv->phy_regulator)) {
 		rc = PTR_ERR(hpriv->phy_regulator);
-		if (rc == -EPROBE_DEFER)
-			goto err_out;
-		rc = 0;
-		hpriv->phy_regulator = NULL;
+		goto err_out;
 	}
 
 	if (flags & AHCI_PLATFORM_GET_RESETS) {
@@ -452,14 +451,24 @@
 		}
 	}
 
-	hpriv->nports = child_nodes = of_get_child_count(dev->of_node);
+	/*
+	 * Too many sub-nodes most likely means having something wrong with
+	 * the firmware.
+	 */
+	child_nodes = of_get_child_count(dev->of_node);
+	if (child_nodes > AHCI_MAX_PORTS) {
+		rc = -EINVAL;
+		goto err_out;
+	}
 
 	/*
 	 * If no sub-node was found, we still need to set nports to
 	 * one in order to be able to use the
 	 * ahci_platform_[en|dis]able_[phys|regulators] functions.
 	 */
-	if (!child_nodes)
+	if (child_nodes)
+		hpriv->nports = child_nodes;
+	else
 		hpriv->nports = 1;
 
 	hpriv->phys = devm_kcalloc(dev, hpriv->nports, sizeof(*hpriv->phys), GFP_KERNEL);
@@ -580,11 +589,13 @@
 	int i, irq, n_ports, rc;
 
 	irq = platform_get_irq(pdev, 0);
-	if (irq <= 0) {
+	if (irq < 0) {
 		if (irq != -EPROBE_DEFER)
 			dev_err(dev, "no irq\n");
 		return irq;
 	}
+	if (!irq)
+		return -EINVAL;
 
 	hpriv->irq = irq;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/libata-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/libata-core.c
@@ -41,7 +41,6 @@
 #include <linux/workqueue.h>
 #include <linux/scatterlist.h>
 #include <linux/io.h>
-#include <linux/async.h>
 #include <linux/log2.h>
 #include <linux/slab.h>
 #include <linux/glob.h>
@@ -2058,7 +2057,7 @@
 
 retry:
 	ata_tf_init(dev, &tf);
-	if (dev->dma_mode && ata_id_has_read_log_dma_ext(dev->id) &&
+	if (ata_dma_enabled(dev) && ata_id_has_read_log_dma_ext(dev->id) &&
 	    !(dev->horkage & ATA_HORKAGE_NO_DMA_LOG)) {
 		tf.command = ATA_CMD_READ_LOG_DMA_EXT;
 		tf.protocol = ATA_PROT_DMA;
@@ -2253,6 +2252,25 @@
 
 }
 
+static bool ata_dev_check_adapter(struct ata_device *dev,
+				  unsigned short vendor_id)
+{
+	struct pci_dev *pcidev = NULL;
+	struct device *parent_dev = NULL;
+
+	for (parent_dev = dev->tdev.parent; parent_dev != NULL;
+	     parent_dev = parent_dev->parent) {
+		if (dev_is_pci(parent_dev)) {
+			pcidev = to_pci_dev(parent_dev);
+			if (pcidev->vendor == vendor_id)
+				return true;
+			break;
+		}
+	}
+
+	return false;
+}
+
 static int ata_dev_config_ncq(struct ata_device *dev,
 			       char *desc, size_t desc_sz)
 {
@@ -2269,6 +2287,13 @@
 		snprintf(desc, desc_sz, "NCQ (not used)");
 		return 0;
 	}
+
+	if (dev->horkage & ATA_HORKAGE_NO_NCQ_ON_ATI &&
+	    ata_dev_check_adapter(dev, PCI_VENDOR_ID_ATI)) {
+		snprintf(desc, desc_sz, "NCQ (not used)");
+		return 0;
+	}
+
 	if (ap->flags & ATA_FLAG_NCQ) {
 		hdepth = min(ap->scsi_host->can_queue, ATA_MAX_QUEUE);
 		dev->flags |= ATA_DFLAG_NCQ;
@@ -3071,7 +3096,7 @@
 	 */
 	if (spd > 1)
 		mask &= (1 << (spd - 1)) - 1;
-	else
+	else if (link->sata_spd)
 		return -EINVAL;
 
 	/* were we already at the bottom? */
@@ -3956,10 +3981,23 @@
 	case ATA_LPM_MED_POWER_WITH_DIPM:
 	case ATA_LPM_MIN_POWER_WITH_PARTIAL:
 	case ATA_LPM_MIN_POWER:
-		if (ata_link_nr_enabled(link) > 0)
-			/* no restrictions on LPM transitions */
+		if (ata_link_nr_enabled(link) > 0) {
+			/* assume no restrictions on LPM transitions */
 			scontrol &= ~(0x7 << 8);
-		else {
+
+			/*
+			 * If the controller does not support partial, slumber,
+			 * or devsleep, then disallow these transitions.
+			 */
+			if (link->ap->host->flags & ATA_HOST_NO_PART)
+				scontrol |= (0x1 << 8);
+
+			if (link->ap->host->flags & ATA_HOST_NO_SSC)
+				scontrol |= (0x2 << 8);
+
+			if (link->ap->host->flags & ATA_HOST_NO_DEVSLP)
+				scontrol |= (0x4 << 8);
+		} else {
 			/* empty port, power off */
 			scontrol &= ~0xf;
 			scontrol |= (0x1 << 2);
@@ -4412,6 +4450,8 @@
 	{ "VRFDFC22048UCHC-TE*", NULL,		ATA_HORKAGE_NODMA },
 	/* Odd clown on sil3726/4726 PMPs */
 	{ "Config  Disk",	NULL,		ATA_HORKAGE_DISABLE },
+	/* Similar story with ASMedia 1092 */
+	{ "ASMT109x- Config",	NULL,		ATA_HORKAGE_DISABLE },
 
 	/* Weird ATAPI devices */
 	{ "TORiSAN DVD-ROM DRD-N216", NULL,	ATA_HORKAGE_MAX_SEC_128 },
@@ -4475,9 +4515,8 @@
 	/* https://bugzilla.kernel.org/show_bug.cgi?id=15573 */
 	{ "C300-CTFDDAC128MAG",	"0001",		ATA_HORKAGE_NONCQ, },
 
-	/* Some Sandisk SSDs lock up hard with NCQ enabled.  Reported on
-	   SD7SN6S256G and SD8SN8U256G */
-	{ "SanDisk SD[78]SN*G",	NULL,		ATA_HORKAGE_NONCQ, },
+	/* Sandisk SD7/8/9s lock up hard on large trims */
+	{ "SanDisk SD[789]*",	NULL,		ATA_HORKAGE_MAX_TRIM_128M, },
 
 	/* devices which puke on READ_NATIVE_MAX */
 	{ "HDS724040KLSA80",	"KFAOA20N",	ATA_HORKAGE_BROKEN_HPA, },
@@ -4516,6 +4555,10 @@
 	{ "PIONEER DVD-RW  DVR-212D",	NULL,	ATA_HORKAGE_NOSETXFER },
 	{ "PIONEER DVD-RW  DVR-216D",	NULL,	ATA_HORKAGE_NOSETXFER },
 
+	/* These specific Pioneer models have LPM issues */
+	{ "PIONEER BD-RW   BDR-207M",	NULL,	ATA_HORKAGE_NOLPM },
+	{ "PIONEER BD-RW   BDR-205",	NULL,	ATA_HORKAGE_NOLPM },
+
 	/* Crucial BX100 SSD 500GB has broken LPM support */
 	{ "CT500BX100SSD1",		NULL,	ATA_HORKAGE_NOLPM },
 
@@ -4554,15 +4597,25 @@
 						ATA_HORKAGE_ZERO_AFTER_TRIM, },
 	{ "Crucial_CT*MX100*",		"MU01",	ATA_HORKAGE_NO_NCQ_TRIM |
 						ATA_HORKAGE_ZERO_AFTER_TRIM, },
+	{ "Samsung SSD 840 EVO*",	NULL,	ATA_HORKAGE_NO_NCQ_TRIM |
+						ATA_HORKAGE_NO_DMA_LOG |
+						ATA_HORKAGE_ZERO_AFTER_TRIM, },
 	{ "Samsung SSD 840*",		NULL,	ATA_HORKAGE_NO_NCQ_TRIM |
 						ATA_HORKAGE_ZERO_AFTER_TRIM, },
 	{ "Samsung SSD 850*",		NULL,	ATA_HORKAGE_NO_NCQ_TRIM |
 						ATA_HORKAGE_ZERO_AFTER_TRIM, },
+	{ "Samsung SSD 860*",		NULL,	ATA_HORKAGE_NO_NCQ_TRIM |
+						ATA_HORKAGE_ZERO_AFTER_TRIM |
+						ATA_HORKAGE_NO_NCQ_ON_ATI, },
+	{ "Samsung SSD 870*",		NULL,	ATA_HORKAGE_NO_NCQ_TRIM |
+						ATA_HORKAGE_ZERO_AFTER_TRIM |
+						ATA_HORKAGE_NO_NCQ_ON_ATI, },
 	{ "FCCT*M500*",			NULL,	ATA_HORKAGE_NO_NCQ_TRIM |
 						ATA_HORKAGE_ZERO_AFTER_TRIM, },
 
 	/* devices that don't properly handle TRIM commands */
 	{ "SuperSSpeed S238*",		NULL,	ATA_HORKAGE_NOTRIM, },
+	{ "M88V29*",			NULL,	ATA_HORKAGE_NOTRIM, },
 
 	/*
 	 * As defined, the DRAT (Deterministic Read After Trim) and RZAT
@@ -4980,7 +5033,10 @@
 	return ATA_DEFER_LINK;
 }
 
-void ata_noop_qc_prep(struct ata_queued_cmd *qc) { }
+enum ata_completion_errors ata_noop_qc_prep(struct ata_queued_cmd *qc)
+{
+	return AC_ERR_OK;
+}
 
 /**
  *	ata_sg_init - Associate command with scatter-gather table.
@@ -5326,6 +5382,30 @@
 }
 
 /**
+ *	ata_qc_get_active - get bitmask of active qcs
+ *	@ap: port in question
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host lock)
+ *
+ *	RETURNS:
+ *	Bitmask of active qcs
+ */
+u64 ata_qc_get_active(struct ata_port *ap)
+{
+	u64 qc_active = ap->qc_active;
+
+	/* ATA_TAG_INTERNAL is sent to hw as tag 0 */
+	if (qc_active & (1ULL << ATA_TAG_INTERNAL)) {
+		qc_active |= (1 << 0);
+		qc_active &= ~(1ULL << ATA_TAG_INTERNAL);
+	}
+
+	return qc_active;
+}
+EXPORT_SYMBOL_GPL(ata_qc_get_active);
+
+/**
  *	ata_qc_complete_multiple - Complete multiple qcs successfully
  *	@ap: port in question
  *	@qc_active: new qc_active mask
@@ -5443,7 +5523,9 @@
 		return;
 	}
 
-	ap->ops->qc_prep(qc);
+	qc->err_mask |= ap->ops->qc_prep(qc);
+	if (unlikely(qc->err_mask))
+		goto err;
 	trace_ata_qc_issue(qc);
 	qc->err_mask |= ap->ops->qc_issue(qc);
 	if (unlikely(qc->err_mask))
@@ -5669,17 +5751,19 @@
 	struct ata_link *link;
 	unsigned long flags;
 
-	/* Previous resume operation might still be in
-	 * progress.  Wait for PM_PENDING to clear.
+	spin_lock_irqsave(ap->lock, flags);
+
+	/*
+	 * A previous PM operation might still be in progress. Wait for
+	 * ATA_PFLAG_PM_PENDING to clear.
 	 */
 	if (ap->pflags & ATA_PFLAG_PM_PENDING) {
+		spin_unlock_irqrestore(ap->lock, flags);
 		ata_port_wait_eh(ap);
-		WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING);
+		spin_lock_irqsave(ap->lock, flags);
 	}
 
-	/* request PM ops to EH */
-	spin_lock_irqsave(ap->lock, flags);
-
+	/* Request PM operation to EH */
 	ap->pm_mesg = mesg;
 	ap->pflags |= ATA_PFLAG_PM_PENDING;
 	ata_for_each_link(link, ap, HOST_FIRST) {
@@ -5691,10 +5775,8 @@
 
 	spin_unlock_irqrestore(ap->lock, flags);
 
-	if (!async) {
+	if (!async)
 		ata_port_wait_eh(ap);
-		WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING);
-	}
 }
 
 /*
@@ -5860,7 +5942,7 @@
 #endif
 
 const struct device_type ata_port_type = {
-	.name = "ata_port",
+	.name = ATA_PORT_TYPE_NAME,
 #ifdef CONFIG_PM
 	.pm = &ata_port_pm_ops,
 #endif
@@ -6059,6 +6141,9 @@
 	for (i = 0; i < host->n_ports; i++) {
 		struct ata_port *ap = host->ports[i];
 
+		if (!ap)
+			continue;
+
 		kfree(ap->pmp_link);
 		kfree(ap->slave_link);
 		kfree(ap);
@@ -6112,12 +6197,16 @@
 	if (!host)
 		return NULL;
 
-	if (!devres_open_group(dev, NULL, GFP_KERNEL))
-		goto err_free;
+	if (!devres_open_group(dev, NULL, GFP_KERNEL)) {
+		kfree(host);
+		return NULL;
+	}
 
 	dr = devres_alloc(ata_devres_release, 0, GFP_KERNEL);
-	if (!dr)
+	if (!dr) {
+		kfree(host);
 		goto err_out;
+	}
 
 	devres_add(dev, dr);
 	dev_set_drvdata(dev, host);
@@ -6145,8 +6234,6 @@
 
  err_out:
 	devres_release_group(dev, NULL);
- err_free:
-	kfree(host);
 	return NULL;
 }
 
@@ -6170,7 +6257,7 @@
 				      const struct ata_port_info * const * ppi,
 				      int n_ports)
 {
-	const struct ata_port_info *pi;
+	const struct ata_port_info *pi = &ata_dummy_port_info;
 	struct ata_host *host;
 	int i, j;
 
@@ -6178,7 +6265,7 @@
 	if (!host)
 		return NULL;
 
-	for (i = 0, j = 0, pi = NULL; i < host->n_ports; i++) {
+	for (i = 0, j = 0; i < host->n_ports; i++) {
 		struct ata_port *ap = host->ports[i];
 
 		if (ppi[j])
@@ -6367,7 +6454,7 @@
 			have_stop = 1;
 	}
 
-	if (host->ops->host_stop)
+	if (host->ops && host->ops->host_stop)
 		have_stop = 1;
 
 	if (have_stop) {
@@ -6568,7 +6655,7 @@
 	/* perform each probe asynchronously */
 	for (i = 0; i < host->n_ports; i++) {
 		struct ata_port *ap = host->ports[i];
-		async_schedule(async_port_probe, ap);
+		ap->cookie = async_schedule(async_port_probe, ap);
 	}
 
 	return 0;
@@ -6663,11 +6750,30 @@
 	if (!ap->ops->error_handler)
 		goto skip_eh;
 
-	/* tell EH we're leaving & flush EH */
+	/* Wait for any ongoing EH */
+	ata_port_wait_eh(ap);
+
+	mutex_lock(&ap->scsi_scan_mutex);
 	spin_lock_irqsave(ap->lock, flags);
+
+	/* Remove scsi devices */
+	ata_for_each_link(link, ap, HOST_FIRST) {
+		ata_for_each_dev(dev, link, ALL) {
+			if (dev->sdev) {
+				spin_unlock_irqrestore(ap->lock, flags);
+				scsi_remove_device(dev->sdev);
+				spin_lock_irqsave(ap->lock, flags);
+				dev->sdev = NULL;
+			}
+		}
+	}
+
+	/* Tell EH to disable all devices */
 	ap->pflags |= ATA_PFLAG_UNLOADING;
 	ata_port_schedule_eh(ap);
+
 	spin_unlock_irqrestore(ap->lock, flags);
+	mutex_unlock(&ap->scsi_scan_mutex);
 
 	/* wait till EH commits suicide */
 	ata_port_wait_eh(ap);
@@ -6708,8 +6814,11 @@
 {
 	int i;
 
-	for (i = 0; i < host->n_ports; i++)
+	for (i = 0; i < host->n_ports; i++) {
+		/* Ensure ata_port probe has completed */
+		async_synchronize_cookie(host->ports[i]->cookie + 1);
 		ata_port_detach(host->ports[i]);
+	}
 
 	/* the host is dead now, dissociate ACPI */
 	ata_acpi_dissociate(host);
@@ -6735,6 +6844,26 @@
 	ata_host_detach(host);
 }
 
+void ata_pci_shutdown_one(struct pci_dev *pdev)
+{
+	struct ata_host *host = pci_get_drvdata(pdev);
+	int i;
+
+	for (i = 0; i < host->n_ports; i++) {
+		struct ata_port *ap = host->ports[i];
+
+		ap->pflags |= ATA_PFLAG_FROZEN;
+
+		/* Disable port interrupts */
+		if (ap->ops->freeze)
+			ap->ops->freeze(ap);
+
+		/* Stop the port DMA engines */
+		if (ap->ops->port_stop)
+			ap->ops->port_stop(ap);
+	}
+}
+
 /* move to PCI subsystem */
 int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits)
 {
@@ -6862,6 +6991,8 @@
 		{ "ncq",	.horkage_off	= ATA_HORKAGE_NONCQ },
 		{ "noncqtrim",	.horkage_on	= ATA_HORKAGE_NO_NCQ_TRIM },
 		{ "ncqtrim",	.horkage_off	= ATA_HORKAGE_NO_NCQ_TRIM },
+		{ "noncqati",	.horkage_on	= ATA_HORKAGE_NO_NCQ_ON_ATI },
+		{ "ncqati",	.horkage_off	= ATA_HORKAGE_NO_NCQ_ON_ATI },
 		{ "dump_id",	.horkage_on	= ATA_HORKAGE_DUMP_ID },
 		{ "pio0",	.xfer_mask	= 1 << (ATA_SHIFT_PIO + 0) },
 		{ "pio1",	.xfer_mask	= 1 << (ATA_SHIFT_PIO + 1) },
@@ -7355,6 +7486,7 @@
 
 #ifdef CONFIG_PCI
 EXPORT_SYMBOL_GPL(pci_test_config_bits);
+EXPORT_SYMBOL_GPL(ata_pci_shutdown_one);
 EXPORT_SYMBOL_GPL(ata_pci_remove_one);
 #ifdef CONFIG_PM
 EXPORT_SYMBOL_GPL(ata_pci_device_do_suspend);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/libata-eh.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/libata-eh.c
@@ -97,6 +97,12 @@
 	ULONG_MAX,
 };
 
+static const unsigned long ata_eh_revalidate_timeouts[] = {
+	15000,	/* Some drives are slow to read log pages when waking-up */
+	15000,  /* combined time till here is enough even for media access */
+	ULONG_MAX,
+};
+
 static const unsigned long ata_eh_flush_timeouts[] = {
 	15000,	/* be generous with flush */
 	15000,  /* ditto */
@@ -133,6 +139,8 @@
 ata_eh_cmd_timeout_table[ATA_EH_CMD_TIMEOUT_TABLE_SIZE] = {
 	{ .commands = CMDS(ATA_CMD_ID_ATA, ATA_CMD_ID_ATAPI),
 	  .timeouts = ata_eh_identify_timeouts, },
+	{ .commands = CMDS(ATA_CMD_READ_LOG_EXT, ATA_CMD_READ_LOG_DMA_EXT),
+	  .timeouts = ata_eh_revalidate_timeouts, },
 	{ .commands = CMDS(ATA_CMD_READ_NATIVE_MAX, ATA_CMD_READ_NATIVE_MAX_EXT),
 	  .timeouts = ata_eh_other_timeouts, },
 	{ .commands = CMDS(ATA_CMD_SET_MAX, ATA_CMD_SET_MAX_EXT),
@@ -2321,6 +2329,7 @@
 		{ ATA_CMD_WRITE_QUEUED_FUA_EXT, "WRITE DMA QUEUED FUA EXT" },
 		{ ATA_CMD_FPDMA_READ,		"READ FPDMA QUEUED" },
 		{ ATA_CMD_FPDMA_WRITE,		"WRITE FPDMA QUEUED" },
+		{ ATA_CMD_NCQ_NON_DATA,		"NCQ NON-DATA" },
 		{ ATA_CMD_FPDMA_SEND,		"SEND FPDMA QUEUED" },
 		{ ATA_CMD_FPDMA_RECV,		"RECEIVE FPDMA QUEUED" },
 		{ ATA_CMD_PIO_READ,		"READ SECTOR(S)" },
@@ -2413,7 +2422,7 @@
 	struct ata_eh_context *ehc = &link->eh_context;
 	struct ata_queued_cmd *qc;
 	const char *frozen, *desc;
-	char tries_buf[6] = "";
+	char tries_buf[16] = "";
 	int tag, nr_failed = 0;
 
 	if (ehc->i.flags & ATA_EHI_QUIET)
@@ -2892,18 +2901,11 @@
 			postreset(slave, classes);
 	}
 
-	/*
-	 * Some controllers can't be frozen very well and may set spurious
-	 * error conditions during reset.  Clear accumulated error
-	 * information and re-thaw the port if frozen.  As reset is the
-	 * final recovery action and we cross check link onlineness against
-	 * device classification later, no hotplug event is lost by this.
-	 */
+	/* clear cached SError */
 	spin_lock_irqsave(link->ap->lock, flags);
-	memset(&link->eh_info, 0, sizeof(link->eh_info));
+	link->eh_info.serror = 0;
 	if (slave)
-		memset(&slave->eh_info, 0, sizeof(link->eh_info));
-	ap->pflags &= ~ATA_PFLAG_EH_PENDING;
+		slave->eh_info.serror = 0;
 	spin_unlock_irqrestore(link->ap->lock, flags);
 
 	if (ap->pflags & ATA_PFLAG_FROZEN)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/libata-pmp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/libata-pmp.c
@@ -763,6 +763,7 @@
 
 	if (dev->flags & ATA_DFLAG_DETACH) {
 		detach = 1;
+		rc = -ENODEV;
 		goto fail;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/libata-scsi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/libata-scsi.c
@@ -162,7 +162,7 @@
 	struct ata_link *link;
 	struct ata_device *dev;
 	unsigned long now;
-	unsigned int uninitialized_var(msecs);
+	unsigned int msecs;
 	int rc = 0;
 
 	ap = ata_shost_to_port(sdev->host);
@@ -2374,6 +2374,7 @@
 
 static unsigned int ata_scsiop_inq_b0(struct ata_scsi_args *args, u8 *rbuf)
 {
+	struct ata_device *dev = args->dev;
 	u16 min_io_sectors;
 
 	rbuf[1] = 0xb0;
@@ -2399,7 +2400,12 @@
 	 * with the unmap bit set.
 	 */
 	if (ata_id_has_trim(args->id)) {
-		put_unaligned_be64(65535 * ATA_MAX_TRIM_RNUM, &rbuf[36]);
+		u64 max_blocks = 65535 * ATA_MAX_TRIM_RNUM;
+
+		if (dev->horkage & ATA_HORKAGE_MAX_TRIM_128M)
+			max_blocks = 128 << (20 - SECTOR_SHIFT);
+
+		put_unaligned_be64(max_blocks, &rbuf[36]);
 		put_unaligned_be32(1, &rbuf[28]);
 	}
 
@@ -3030,18 +3036,36 @@
 	return 0;
 }
 
-static struct ata_device *ata_find_dev(struct ata_port *ap, int devno)
+static struct ata_device *ata_find_dev(struct ata_port *ap, unsigned int devno)
 {
-	if (!sata_pmp_attached(ap)) {
-		if (likely(devno >= 0 &&
-			   devno < ata_link_max_devices(&ap->link)))
+	/*
+	 * For the non-PMP case, ata_link_max_devices() returns 1 (SATA case),
+	 * or 2 (IDE master + slave case). However, the former case includes
+	 * libsas hosted devices which are numbered per scsi host, leading
+	 * to devno potentially being larger than 0 but with each struct
+	 * ata_device having its own struct ata_port and struct ata_link.
+	 * To accommodate these, ignore devno and always use device number 0.
+	 */
+	if (likely(!sata_pmp_attached(ap))) {
+		int link_max_devices = ata_link_max_devices(&ap->link);
+
+		if (link_max_devices == 1)
+			return &ap->link.device[0];
+
+		if (devno < link_max_devices)
 			return &ap->link.device[devno];
-	} else {
-		if (likely(devno >= 0 &&
-			   devno < ap->nr_pmp_links))
-			return &ap->pmp_link[devno].device[0];
+
+		return NULL;
 	}
 
+	/*
+	 * For PMP-attached devices, the device number corresponds to C
+	 * (channel) of SCSI [H:C:I:L], indicating the port pmp link
+	 * for the device.
+	 */
+	if (devno < ap->nr_pmp_links)
+		return &ap->pmp_link[devno].device[0];
+
 	return NULL;
 }
 
@@ -3158,8 +3182,19 @@
 		goto invalid_fld;
 	}
 
-	if (ata_is_ncq(tf->protocol) && (cdb[2 + cdb_offset] & 0x3) == 0)
-		tf->protocol = ATA_PROT_NCQ_NODATA;
+	if ((cdb[2 + cdb_offset] & 0x3) == 0) {
+		/*
+		 * When T_LENGTH is zero (No data is transferred), dir should
+		 * be DMA_NONE.
+		 */
+		if (scmd->sc_data_direction != DMA_NONE) {
+			fp = 2 + cdb_offset;
+			goto invalid_fld;
+		}
+
+		if (ata_is_ncq(tf->protocol))
+			tf->protocol = ATA_PROT_NCQ_NODATA;
+	}
 
 	/* enable LBA */
 	tf->flags |= ATA_TFLAG_LBA;
@@ -3978,12 +4013,13 @@
 {
 	struct scsi_cmnd *scmd = qc->scsicmd;
 	const u8 *cdb = scmd->cmnd;
-	const u8 *p;
 	u8 pg, spg;
 	unsigned six_byte, pg_len, hdr_len, bd_len;
 	int len;
 	u16 fp = (u16)-1;
 	u8 bp = 0xff;
+	u8 buffer[64];
+	const u8 *p = buffer;
 
 	VPRINTK("ENTER\n");
 
@@ -4017,12 +4053,14 @@
 	if (!scsi_sg_count(scmd) || scsi_sglist(scmd)->length < len)
 		goto invalid_param_len;
 
-	p = page_address(sg_page(scsi_sglist(scmd)));
-
 	/* Move past header and block descriptors.  */
 	if (len < hdr_len)
 		goto invalid_param_len;
 
+	if (!sg_copy_to_buffer(scsi_sglist(scmd), scsi_sg_count(scmd),
+			       buffer, sizeof(buffer)))
+		goto invalid_param_len;
+
 	if (six_byte)
 		bd_len = p[3];
 	else
@@ -4506,7 +4544,7 @@
 		break;
 
 	case MAINTENANCE_IN:
-		if (scsicmd[1] == MI_REPORT_SUPPORTED_OPERATION_CODES)
+		if ((scsicmd[1] & 0x1f) == MI_REPORT_SUPPORTED_OPERATION_CODES)
 			ata_scsi_rbuf_fill(&args, ata_scsiop_maint_in);
 		else
 			ata_scsi_set_invalid_field(dev, cmd, 1, 0xff);
@@ -4553,22 +4591,19 @@
 		 */
 		shost->max_host_blocked = 1;
 
-		rc = scsi_add_host_with_dma(ap->scsi_host,
-						&ap->tdev, ap->host->dev);
+		rc = scsi_add_host_with_dma(shost, &ap->tdev, ap->host->dev);
 		if (rc)
-			goto err_add;
+			goto err_alloc;
 	}
 
 	return 0;
 
- err_add:
-	scsi_host_put(host->ports[i]->scsi_host);
  err_alloc:
 	while (--i >= 0) {
 		struct Scsi_Host *shost = host->ports[i]->scsi_host;
 
+		/* scsi_host_put() is in ata_devres_release() */
 		scsi_remove_host(shost);
-		scsi_host_put(shost);
 	}
 	return rc;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/libata-sff.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/libata-sff.c
@@ -641,6 +641,20 @@
 }
 EXPORT_SYMBOL_GPL(ata_sff_data_xfer32);
 
+static void ata_pio_xfer(struct ata_queued_cmd *qc, struct page *page,
+		unsigned int offset, size_t xfer_size)
+{
+	bool do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
+	unsigned char *buf;
+
+	buf = kmap_atomic(page);
+	qc->ap->ops->sff_data_xfer(qc, buf + offset, xfer_size, do_write);
+	kunmap_atomic(buf);
+
+	if (!do_write && !PageSlab(page))
+		flush_dcache_page(page);
+}
+
 /**
  *	ata_pio_sector - Transfer a sector of data.
  *	@qc: Command on going
@@ -652,11 +666,9 @@
  */
 static void ata_pio_sector(struct ata_queued_cmd *qc)
 {
-	int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
 	struct ata_port *ap = qc->ap;
 	struct page *page;
 	unsigned int offset;
-	unsigned char *buf;
 
 	if (!qc->cursg) {
 		qc->curbytes = qc->nbytes;
@@ -674,13 +686,20 @@
 
 	DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
 
-	/* do the actual data transfer */
-	buf = kmap_atomic(page);
-	ap->ops->sff_data_xfer(qc, buf + offset, qc->sect_size, do_write);
-	kunmap_atomic(buf);
-
-	if (!do_write && !PageSlab(page))
-		flush_dcache_page(page);
+	/*
+	 * Split the transfer when it splits a page boundary.  Note that the
+	 * split still has to be dword aligned like all ATA data transfers.
+	 */
+	WARN_ON_ONCE(offset % 4);
+	if (offset + qc->sect_size > PAGE_SIZE) {
+		unsigned int split_len = PAGE_SIZE - offset;
+
+		ata_pio_xfer(qc, page, offset, split_len);
+		ata_pio_xfer(qc, nth_page(page, 1), 0,
+			     qc->sect_size - split_len);
+	} else {
+		ata_pio_xfer(qc, page, offset, qc->sect_size);
+	}
 
 	qc->curbytes += qc->sect_size;
 	qc->cursg_ofs += qc->sect_size;
@@ -2679,12 +2698,14 @@
  *	LOCKING:
  *	spin_lock_irqsave(host lock)
  */
-void ata_bmdma_qc_prep(struct ata_queued_cmd *qc)
+enum ata_completion_errors ata_bmdma_qc_prep(struct ata_queued_cmd *qc)
 {
 	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
-		return;
+		return AC_ERR_OK;
 
 	ata_bmdma_fill_sg(qc);
+
+	return AC_ERR_OK;
 }
 EXPORT_SYMBOL_GPL(ata_bmdma_qc_prep);
 
@@ -2697,12 +2718,14 @@
  *	LOCKING:
  *	spin_lock_irqsave(host lock)
  */
-void ata_bmdma_dumb_qc_prep(struct ata_queued_cmd *qc)
+enum ata_completion_errors ata_bmdma_dumb_qc_prep(struct ata_queued_cmd *qc)
 {
 	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
-		return;
+		return AC_ERR_OK;
 
 	ata_bmdma_fill_sg_dumb(qc);
+
+	return AC_ERR_OK;
 }
 EXPORT_SYMBOL_GPL(ata_bmdma_dumb_qc_prep);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/libata-transport.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/libata-transport.c
@@ -196,7 +196,7 @@
 	{ XFER_PIO_0,			"XFER_PIO_0" },
 	{ XFER_PIO_SLOW,		"XFER_PIO_SLOW" }
 };
-ata_bitfield_name_match(xfer,ata_xfer_names)
+ata_bitfield_name_search(xfer, ata_xfer_names)
 
 /*
  * ATA Port attributes
@@ -266,6 +266,10 @@
 	put_device(dev);
 }
 
+static const struct device_type ata_port_sas_type = {
+	.name = ATA_PORT_TYPE_NAME,
+};
+
 /** ata_tport_add - initialize a transport ATA port structure
  *
  * @parent:	parent device
@@ -283,7 +287,10 @@
 	struct device *dev = &ap->tdev;
 
 	device_initialize(dev);
-	dev->type = &ata_port_type;
+	if (ap->flags & ATA_FLAG_SAS_HOST)
+		dev->type = &ata_port_sas_type;
+	else
+		dev->type = &ata_port_type;
 
 	dev->parent = parent;
 	ata_host_get(ap->host);
@@ -317,7 +324,6 @@
  tport_err:
 	transport_destroy_device(dev);
 	put_device(dev);
-	ata_host_put(ap->host);
 	return error;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/libata.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/libata.h
@@ -30,6 +30,8 @@
 	ATA_DNXFER_QUIET	= (1 << 31),
 };
 
+#define ATA_PORT_TYPE_NAME	"ata_port"
+
 extern atomic_t ata_print_id;
 extern int atapi_passthru16;
 extern int libata_fua;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/pata_arasan_cf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/pata_arasan_cf.c
@@ -817,12 +817,19 @@
 	else
 		quirk = CF_BROKEN_UDMA; /* as it is on spear1340 */
 
-	/* if irq is 0, support only PIO */
-	acdev->irq = platform_get_irq(pdev, 0);
-	if (acdev->irq)
+	/*
+	 * If there's an error getting IRQ (or we do get IRQ0),
+	 * support only PIO
+	 */
+	ret = platform_get_irq(pdev, 0);
+	if (ret > 0) {
+		acdev->irq = ret;
 		irq_handler = arasan_cf_interrupt;
-	else
+	} else	if (ret == -EPROBE_DEFER) {
+		return ret;
+	} else	{
 		quirk |= CF_BROKEN_MWDMA | CF_BROKEN_UDMA;
+	}
 
 	acdev->pbase = res->start;
 	acdev->vbase = devm_ioremap_nocache(&pdev->dev, res->start,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/pata_ep93xx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/pata_ep93xx.c
@@ -928,7 +928,7 @@
 	/* INT[3] (IRQ_EP93XX_EXT3) line connected as pull down */
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
-		err = -ENXIO;
+		err = irq;
 		goto err_rel_gpio;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/pata_ftide010.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/pata_ftide010.c
@@ -570,6 +570,7 @@
 };
 module_platform_driver(pata_ftide010_driver);
 
+MODULE_DESCRIPTION("low level driver for Faraday Technology FTIDE010");
 MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:" DRV_NAME);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/pata_hpt37x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/pata_hpt37x.c
@@ -918,6 +918,20 @@
 	pci_write_config_byte(dev, 0x5a, irqmask);
 
 	/*
+	 * HPT371 chips physically have only one channel, the secondary one,
+	 * but the primary channel registers do exist!  Go figure...
+	 * So,  we manually disable the non-existing channel here
+	 * (if the BIOS hasn't done this already).
+	 */
+	if (dev->device == PCI_DEVICE_ID_TTI_HPT371) {
+		u8 mcr1;
+
+		pci_read_config_byte(dev, 0x50, &mcr1);
+		mcr1 &= ~0x04;
+		pci_write_config_byte(dev, 0x50, mcr1);
+	}
+
+	/*
 	 * default to pci clock. make sure MA15/16 are set to output
 	 * to prevent drives having problems with 40-pin cables. Needed
 	 * for some drives such as IBM-DTLA which will not enter ready
@@ -948,14 +962,14 @@
 
 	if ((freq >> 12) != 0xABCDE) {
 		int i;
-		u8 sr;
+		u16 sr;
 		u32 total = 0;
 
 		pr_warn("BIOS has not set timing clocks\n");
 
 		/* This is the process the HPT371 BIOS is reported to use */
 		for (i = 0; i < 128; i++) {
-			pci_read_config_byte(dev, 0x78, &sr);
+			pci_read_config_word(dev, 0x78, &sr);
 			total += sr & 0x1FF;
 			udelay(15);
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/pata_isapnp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/pata_isapnp.c
@@ -82,6 +82,9 @@
 	if (pnp_port_valid(idev, 1)) {
 		ctl_addr = devm_ioport_map(&idev->dev,
 					   pnp_port_start(idev, 1), 1);
+		if (!ctl_addr)
+			return -ENOMEM;
+
 		ap->ioaddr.altstatus_addr = ctl_addr;
 		ap->ioaddr.ctl_addr = ctl_addr;
 		ap->ops = &isapnp_port_ops;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/pata_ixp4xx_cf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/pata_ixp4xx_cf.c
@@ -135,12 +135,12 @@
 
 static int ixp4xx_pata_probe(struct platform_device *pdev)
 {
-	unsigned int irq;
 	struct resource *cs0, *cs1;
 	struct ata_host *host;
 	struct ata_port *ap;
 	struct ixp4xx_pata_data *data = dev_get_platdata(&pdev->dev);
 	int ret;
+	int irq;
 
 	cs0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	cs1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
@@ -165,8 +165,12 @@
 		return -ENOMEM;
 
 	irq = platform_get_irq(pdev, 0);
-	if (irq)
+	if (irq > 0)
 		irq_set_irq_type(irq, IRQ_TYPE_EDGE_RISING);
+	else if (irq < 0)
+		return irq;
+	else
+		return -EINVAL;
 
 	/* Setup expansion bus chip selects */
 	*data->cs0_cfg = data->cs0_bits;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/pata_legacy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/pata_legacy.c
@@ -114,8 +114,6 @@
 static struct legacy_probe probe_list[NR_HOST];
 static struct legacy_data legacy_data[NR_HOST];
 static struct ata_host *legacy_host[NR_HOST];
-static int nr_legacy_host;
-
 
 static int probe_all;		/* Set to check all ISA port ranges */
 static int ht6560a;		/* HT 6560A on primary 1, second 2, both 3 */
@@ -278,9 +276,10 @@
 	outb(inb(0x1F4) & 0x07, 0x1F4);
 
 	rt = inb(0x1F3);
-	rt &= 0x07 << (3 * adev->devno);
+	rt &= ~(0x07 << (3 * !adev->devno));
 	if (pio)
-		rt |= (1 + 3 * pio) << (3 * adev->devno);
+		rt |= (1 + 3 * pio) << (3 * !adev->devno);
+	outb(rt, 0x1F3);
 
 	udelay(100);
 	outb(inb(0x1F2) | 0x01, 0x1F2);
@@ -315,7 +314,8 @@
 			iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
 
 		if (unlikely(slop)) {
-			__le32 pad;
+			__le32 pad = 0;
+
 			if (rw == READ) {
 				pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr));
 				memcpy(buf + buflen - slop, &pad, slop);
@@ -705,7 +705,8 @@
 			ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
 
 		if (unlikely(slop)) {
-			__le32 pad;
+			__le32 pad = 0;
+
 			if (rw == WRITE) {
 				memcpy(&pad, buf + buflen - slop, slop);
 				iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
@@ -1236,9 +1237,11 @@
 {
 	int i;
 
-	for (i = 0; i < nr_legacy_host; i++) {
+	for (i = 0; i < NR_HOST; i++) {
 		struct legacy_data *ld = &legacy_data[i];
-		ata_host_detach(legacy_host[i]);
+
+		if (legacy_host[i])
+			ata_host_detach(legacy_host[i]);
 		platform_device_unregister(ld->platform_dev);
 	}
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/pata_macio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/pata_macio.c
@@ -510,7 +510,7 @@
 	return ATA_CBL_PATA40;
 }
 
-static void pata_macio_qc_prep(struct ata_queued_cmd *qc)
+static enum ata_completion_errors pata_macio_qc_prep(struct ata_queued_cmd *qc)
 {
 	unsigned int write = (qc->tf.flags & ATA_TFLAG_WRITE);
 	struct ata_port *ap = qc->ap;
@@ -523,7 +523,7 @@
 		   __func__, qc, qc->flags, write, qc->dev->devno);
 
 	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
-		return;
+		return AC_ERR_OK;
 
 	table = (struct dbdma_cmd *) priv->dma_table_cpu;
 
@@ -540,7 +540,8 @@
 
 		while (sg_len) {
 			/* table overflow should never happen */
-			BUG_ON (pi++ >= MAX_DCMDS);
+			if (WARN_ON_ONCE(pi >= MAX_DCMDS))
+				return AC_ERR_SYSTEM;
 
 			len = (sg_len < MAX_DBDMA_SEG) ? sg_len : MAX_DBDMA_SEG;
 			table->command = cpu_to_le16(write ? OUTPUT_MORE: INPUT_MORE);
@@ -552,11 +553,13 @@
 			addr += len;
 			sg_len -= len;
 			++table;
+			++pi;
 		}
 	}
 
 	/* Should never happen according to Tejun */
-	BUG_ON(!pi);
+	if (WARN_ON_ONCE(!pi))
+		return AC_ERR_SYSTEM;
 
 	/* Convert the last command to an input/output */
 	table--;
@@ -568,6 +571,8 @@
 	table->command = cpu_to_le16(DBDMA_STOP);
 
 	dev_dbgdma(priv->dev, "%s: %d DMA list entries\n", __func__, pi);
+
+	return AC_ERR_OK;
 }
 
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/pata_marvell.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/pata_marvell.c
@@ -83,6 +83,8 @@
 	switch(ap->port_no)
 	{
 	case 0:
+		if (!ap->ioaddr.bmdma_addr)
+			return ATA_CBL_PATA_UNK;
 		if (ioread8(ap->ioaddr.bmdma_addr + 1) & 1)
 			return ATA_CBL_PATA40;
 		return ATA_CBL_PATA80;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/pata_ns87415.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/pata_ns87415.c
@@ -261,7 +261,7 @@
  *	LOCKING:
  *	Inherited from caller.
  */
-void ns87560_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+static void ns87560_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
 {
 	struct ata_ioports *ioaddr = &ap->ioaddr;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/pata_octeon_cf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/pata_octeon_cf.c
@@ -888,20 +888,24 @@
 				int i;
 				res_dma = platform_get_resource(dma_dev, IORESOURCE_MEM, 0);
 				if (!res_dma) {
+					put_device(&dma_dev->dev);
 					of_node_put(dma_node);
 					return -EINVAL;
 				}
 				cf_port->dma_base = (u64)devm_ioremap_nocache(&pdev->dev, res_dma->start,
 									 resource_size(res_dma));
 				if (!cf_port->dma_base) {
+					put_device(&dma_dev->dev);
 					of_node_put(dma_node);
 					return -EINVAL;
 				}
 
-				irq_handler = octeon_cf_interrupt;
 				i = platform_get_irq(dma_dev, 0);
-				if (i > 0)
+				if (i > 0) {
 					irq = i;
+					irq_handler = octeon_cf_interrupt;
+				}
+				put_device(&dma_dev->dev);
 			}
 			of_node_put(dma_node);
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/pata_pxa.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/pata_pxa.c
@@ -44,25 +44,27 @@
 /*
  * Prepare taskfile for submission.
  */
-static void pxa_qc_prep(struct ata_queued_cmd *qc)
+static enum ata_completion_errors pxa_qc_prep(struct ata_queued_cmd *qc)
 {
 	struct pata_pxa_data *pd = qc->ap->private_data;
 	struct dma_async_tx_descriptor *tx;
 	enum dma_transfer_direction dir;
 
 	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
-		return;
+		return AC_ERR_OK;
 
 	dir = (qc->dma_dir == DMA_TO_DEVICE ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM);
 	tx = dmaengine_prep_slave_sg(pd->dma_chan, qc->sg, qc->n_elem, dir,
 				     DMA_PREP_INTERRUPT);
 	if (!tx) {
 		ata_dev_err(qc->dev, "prep_slave_sg() failed\n");
-		return;
+		return AC_ERR_OK;
 	}
 	tx->callback = pxa_ata_dma_irq;
 	tx->callback_param = pd;
 	pd->dma_cookie = dmaengine_submit(tx);
+
+	return AC_ERR_OK;
 }
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/pata_rb532_cf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/pata_rb532_cf.c
@@ -115,10 +115,12 @@
 	}
 
 	irq = platform_get_irq(pdev, 0);
-	if (irq <= 0) {
+	if (irq < 0) {
 		dev_err(&pdev->dev, "no IRQ resource found\n");
-		return -ENOENT;
+		return irq;
 	}
+	if (!irq)
+		return -EINVAL;
 
 	gpiod = devm_gpiod_get(&pdev->dev, NULL, GPIOD_IN);
 	if (IS_ERR(gpiod)) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/pdc_adma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/pdc_adma.c
@@ -116,7 +116,7 @@
 				const struct pci_device_id *ent);
 static int adma_port_start(struct ata_port *ap);
 static void adma_port_stop(struct ata_port *ap);
-static void adma_qc_prep(struct ata_queued_cmd *qc);
+static enum ata_completion_errors adma_qc_prep(struct ata_queued_cmd *qc);
 static unsigned int adma_qc_issue(struct ata_queued_cmd *qc);
 static int adma_check_atapi_dma(struct ata_queued_cmd *qc);
 static void adma_freeze(struct ata_port *ap);
@@ -295,7 +295,7 @@
 	return i;
 }
 
-static void adma_qc_prep(struct ata_queued_cmd *qc)
+static enum ata_completion_errors adma_qc_prep(struct ata_queued_cmd *qc)
 {
 	struct adma_port_priv *pp = qc->ap->private_data;
 	u8  *buf = pp->pkt;
@@ -306,7 +306,7 @@
 
 	adma_enter_reg_mode(qc->ap);
 	if (qc->tf.protocol != ATA_PROT_DMA)
-		return;
+		return AC_ERR_OK;
 
 	buf[i++] = 0;	/* Response flags */
 	buf[i++] = 0;	/* reserved */
@@ -371,6 +371,7 @@
 			printk("%s\n", obuf);
 	}
 #endif
+	return AC_ERR_OK;
 }
 
 static inline void adma_packet_start(struct ata_queued_cmd *qc)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/sata_dwc_460ex.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/sata_dwc_460ex.c
@@ -145,7 +145,11 @@
 #endif
 };
 
-#define SATA_DWC_QCMD_MAX	32
+/*
+ * Allow one extra special slot for commands and DMA management
+ * to account for libata internal commands.
+ */
+#define SATA_DWC_QCMD_MAX	(ATA_MAX_QUEUE + 1)
 
 struct sata_dwc_device_port {
 	struct sata_dwc_device	*hsdev;
@@ -1249,24 +1253,20 @@
 	irq = irq_of_parse_and_map(np, 0);
 	if (irq == NO_IRQ) {
 		dev_err(&ofdev->dev, "no SATA DMA irq\n");
-		err = -ENODEV;
-		goto error_out;
+		return -ENODEV;
 	}
 
 #ifdef CONFIG_SATA_DWC_OLD_DMA
 	if (!of_find_property(np, "dmas", NULL)) {
 		err = sata_dwc_dma_init_old(ofdev, hsdev);
 		if (err)
-			goto error_out;
+			return err;
 	}
 #endif
 
 	hsdev->phy = devm_phy_optional_get(hsdev->dev, "sata-phy");
-	if (IS_ERR(hsdev->phy)) {
-		err = PTR_ERR(hsdev->phy);
-		hsdev->phy = NULL;
-		goto error_out;
-	}
+	if (IS_ERR(hsdev->phy))
+		return PTR_ERR(hsdev->phy);
 
 	err = phy_init(hsdev->phy);
 	if (err)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/sata_fsl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/sata_fsl.c
@@ -502,7 +502,7 @@
 	return num_prde;
 }
 
-static void sata_fsl_qc_prep(struct ata_queued_cmd *qc)
+static enum ata_completion_errors sata_fsl_qc_prep(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
 	struct sata_fsl_port_priv *pp = ap->private_data;
@@ -548,6 +548,8 @@
 
 	VPRINTK("SATA FSL : xx_qc_prep, di = 0x%x, ttl = %d, num_prde = %d\n",
 		desc_info, ttl_dwords, num_prde);
+
+	return AC_ERR_OK;
 }
 
 static unsigned int sata_fsl_qc_issue(struct ata_queued_cmd *qc)
@@ -1278,7 +1280,7 @@
 				     i, ioread32(hcr_base + CC),
 				     ioread32(hcr_base + CA));
 		}
-		ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask);
+		ata_qc_complete_multiple(ap, ata_qc_get_active(ap) ^ done_mask);
 		return;
 
 	} else if ((ap->qc_active & (1ULL << ATA_TAG_INTERNAL))) {
@@ -1392,6 +1394,14 @@
 	return 0;
 }
 
+static void sata_fsl_host_stop(struct ata_host *host)
+{
+        struct sata_fsl_host_priv *host_priv = host->private_data;
+
+        iounmap(host_priv->hcr_base);
+        kfree(host_priv);
+}
+
 /*
  * scsi mid-layer and libata interface structures
  */
@@ -1424,6 +1434,8 @@
 	.port_start = sata_fsl_port_start,
 	.port_stop = sata_fsl_port_stop,
 
+	.host_stop      = sata_fsl_host_stop,
+
 	.pmp_attach = sata_fsl_pmp_attach,
 	.pmp_detach = sata_fsl_pmp_detach,
 };
@@ -1478,9 +1490,9 @@
 	host_priv->ssr_base = ssr_base;
 	host_priv->csr_base = csr_base;
 
-	irq = irq_of_parse_and_map(ofdev->dev.of_node, 0);
-	if (!irq) {
-		dev_err(&ofdev->dev, "invalid irq from platform\n");
+	irq = platform_get_irq(ofdev, 0);
+	if (irq < 0) {
+		retval = irq;
 		goto error_exit_with_cleanup;
 	}
 	host_priv->irq = irq;
@@ -1555,10 +1567,6 @@
 
 	ata_host_detach(host);
 
-	irq_dispose_mapping(host_priv->irq);
-	iounmap(host_priv->hcr_base);
-	kfree(host_priv);
-
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/sata_gemini.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/sata_gemini.c
@@ -201,7 +201,10 @@
 		pclk = sg->sata0_pclk;
 	else
 		pclk = sg->sata1_pclk;
-	clk_enable(pclk);
+	ret = clk_enable(pclk);
+	if (ret)
+		return ret;
+
 	msleep(10);
 
 	/* Do not keep clocking a bridge that is not online */
@@ -435,6 +438,7 @@
 };
 module_platform_driver(gemini_sata_driver);
 
+MODULE_DESCRIPTION("low level driver for Cortina Systems Gemini SATA bridge");
 MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:" DRV_NAME);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/sata_highbank.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/sata_highbank.c
@@ -348,6 +348,7 @@
 			phy_nodes[phy] = phy_data.np;
 			cphy_base[phy] = of_iomap(phy_nodes[phy], 0);
 			if (cphy_base[phy] == NULL) {
+				of_node_put(phy_data.np);
 				return 0;
 			}
 			phy_count += 1;
@@ -469,10 +470,12 @@
 	}
 
 	irq = platform_get_irq(pdev, 0);
-	if (irq <= 0) {
+	if (irq < 0) {
 		dev_err(dev, "no irq\n");
-		return -EINVAL;
+		return irq;
 	}
+	if (!irq)
+		return -EINVAL;
 
 	hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
 	if (!hpriv) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/sata_inic162x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/sata_inic162x.c
@@ -478,7 +478,7 @@
 	prd[-1].flags |= PRD_END;
 }
 
-static void inic_qc_prep(struct ata_queued_cmd *qc)
+static enum ata_completion_errors inic_qc_prep(struct ata_queued_cmd *qc)
 {
 	struct inic_port_priv *pp = qc->ap->private_data;
 	struct inic_pkt *pkt = pp->pkt;
@@ -538,6 +538,8 @@
 		inic_fill_sg(prd, qc);
 
 	pp->cpb_tbl[0] = pp->pkt_dma;
+
+	return AC_ERR_OK;
 }
 
 static unsigned int inic_qc_issue(struct ata_queued_cmd *qc)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/sata_mv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/sata_mv.c
@@ -592,8 +592,8 @@
 static int mv_port_start(struct ata_port *ap);
 static void mv_port_stop(struct ata_port *ap);
 static int mv_qc_defer(struct ata_queued_cmd *qc);
-static void mv_qc_prep(struct ata_queued_cmd *qc);
-static void mv_qc_prep_iie(struct ata_queued_cmd *qc);
+static enum ata_completion_errors mv_qc_prep(struct ata_queued_cmd *qc);
+static enum ata_completion_errors mv_qc_prep_iie(struct ata_queued_cmd *qc);
 static unsigned int mv_qc_issue(struct ata_queued_cmd *qc);
 static int mv_hardreset(struct ata_link *link, unsigned int *class,
 			unsigned long deadline);
@@ -783,37 +783,6 @@
 	},
 };
 
-static const struct pci_device_id mv_pci_tbl[] = {
-	{ PCI_VDEVICE(MARVELL, 0x5040), chip_504x },
-	{ PCI_VDEVICE(MARVELL, 0x5041), chip_504x },
-	{ PCI_VDEVICE(MARVELL, 0x5080), chip_5080 },
-	{ PCI_VDEVICE(MARVELL, 0x5081), chip_508x },
-	/* RocketRAID 1720/174x have different identifiers */
-	{ PCI_VDEVICE(TTI, 0x1720), chip_6042 },
-	{ PCI_VDEVICE(TTI, 0x1740), chip_6042 },
-	{ PCI_VDEVICE(TTI, 0x1742), chip_6042 },
-
-	{ PCI_VDEVICE(MARVELL, 0x6040), chip_604x },
-	{ PCI_VDEVICE(MARVELL, 0x6041), chip_604x },
-	{ PCI_VDEVICE(MARVELL, 0x6042), chip_6042 },
-	{ PCI_VDEVICE(MARVELL, 0x6080), chip_608x },
-	{ PCI_VDEVICE(MARVELL, 0x6081), chip_608x },
-
-	{ PCI_VDEVICE(ADAPTEC2, 0x0241), chip_604x },
-
-	/* Adaptec 1430SA */
-	{ PCI_VDEVICE(ADAPTEC2, 0x0243), chip_7042 },
-
-	/* Marvell 7042 support */
-	{ PCI_VDEVICE(MARVELL, 0x7042), chip_7042 },
-
-	/* Highpoint RocketRAID PCIe series */
-	{ PCI_VDEVICE(TTI, 0x2300), chip_7042 },
-	{ PCI_VDEVICE(TTI, 0x2310), chip_7042 },
-
-	{ }			/* terminate list */
-};
-
 static const struct mv_hw_ops mv5xxx_ops = {
 	.phy_errata		= mv5_phy_errata,
 	.enable_leds		= mv5_enable_leds,
@@ -2031,7 +2000,7 @@
  *      LOCKING:
  *      Inherited from caller.
  */
-static void mv_qc_prep(struct ata_queued_cmd *qc)
+static enum ata_completion_errors mv_qc_prep(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
 	struct mv_port_priv *pp = ap->private_data;
@@ -2043,15 +2012,15 @@
 	switch (tf->protocol) {
 	case ATA_PROT_DMA:
 		if (tf->command == ATA_CMD_DSM)
-			return;
+			return AC_ERR_OK;
 		/* fall-thru */
 	case ATA_PROT_NCQ:
 		break;	/* continue below */
 	case ATA_PROT_PIO:
 		mv_rw_multi_errata_sata24(qc);
-		return;
+		return AC_ERR_OK;
 	default:
-		return;
+		return AC_ERR_OK;
 	}
 
 	/* Fill in command request block
@@ -2098,12 +2067,10 @@
 		 * non-NCQ mode are: [RW] STREAM DMA and W DMA FUA EXT, none
 		 * of which are defined/used by Linux.  If we get here, this
 		 * driver needs work.
-		 *
-		 * FIXME: modify libata to give qc_prep a return value and
-		 * return error here.
 		 */
-		BUG_ON(tf->command);
-		break;
+		ata_port_err(ap, "%s: unsupported command: %.2x\n", __func__,
+				tf->command);
+		return AC_ERR_INVALID;
 	}
 	mv_crqb_pack_cmd(cw++, tf->nsect, ATA_REG_NSECT, 0);
 	mv_crqb_pack_cmd(cw++, tf->hob_lbal, ATA_REG_LBAL, 0);
@@ -2116,8 +2083,10 @@
 	mv_crqb_pack_cmd(cw++, tf->command, ATA_REG_CMD, 1);	/* last */
 
 	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
-		return;
+		return AC_ERR_OK;
 	mv_fill_sg(qc);
+
+	return AC_ERR_OK;
 }
 
 /**
@@ -2132,7 +2101,7 @@
  *      LOCKING:
  *      Inherited from caller.
  */
-static void mv_qc_prep_iie(struct ata_queued_cmd *qc)
+static enum ata_completion_errors mv_qc_prep_iie(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
 	struct mv_port_priv *pp = ap->private_data;
@@ -2143,9 +2112,9 @@
 
 	if ((tf->protocol != ATA_PROT_DMA) &&
 	    (tf->protocol != ATA_PROT_NCQ))
-		return;
+		return AC_ERR_OK;
 	if (tf->command == ATA_CMD_DSM)
-		return;  /* use bmdma for this */
+		return AC_ERR_OK;  /* use bmdma for this */
 
 	/* Fill in Gen IIE command request block */
 	if (!(tf->flags & ATA_TFLAG_WRITE))
@@ -2186,8 +2155,10 @@
 		);
 
 	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
-		return;
+		return AC_ERR_OK;
 	mv_fill_sg(qc);
+
+	return AC_ERR_OK;
 }
 
 /**
@@ -2827,7 +2798,7 @@
 	}
 
 	if (work_done) {
-		ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask);
+		ata_qc_complete_multiple(ap, ata_qc_get_active(ap) ^ done_mask);
 
 		/* Update the software queue position index in hardware */
 		writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) |
@@ -3890,8 +3861,8 @@
 		break;
 
 	default:
-		dev_err(host->dev, "BUG: invalid board index %u\n", board_idx);
-		return 1;
+		dev_alert(host->dev, "BUG: invalid board index %u\n", board_idx);
+		return -EINVAL;
 	}
 
 	hpriv->hp_flags = hp_flags;
@@ -4095,6 +4066,10 @@
 		n_ports = mv_platform_data->n_ports;
 		irq = platform_get_irq(pdev, 0);
 	}
+	if (irq < 0)
+		return irq;
+	if (!irq)
+		return -EINVAL;
 
 	host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
 	hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);
@@ -4301,6 +4276,36 @@
 static int mv_pci_device_resume(struct pci_dev *pdev);
 #endif
 
+static const struct pci_device_id mv_pci_tbl[] = {
+	{ PCI_VDEVICE(MARVELL, 0x5040), chip_504x },
+	{ PCI_VDEVICE(MARVELL, 0x5041), chip_504x },
+	{ PCI_VDEVICE(MARVELL, 0x5080), chip_5080 },
+	{ PCI_VDEVICE(MARVELL, 0x5081), chip_508x },
+	/* RocketRAID 1720/174x have different identifiers */
+	{ PCI_VDEVICE(TTI, 0x1720), chip_6042 },
+	{ PCI_VDEVICE(TTI, 0x1740), chip_6042 },
+	{ PCI_VDEVICE(TTI, 0x1742), chip_6042 },
+
+	{ PCI_VDEVICE(MARVELL, 0x6040), chip_604x },
+	{ PCI_VDEVICE(MARVELL, 0x6041), chip_604x },
+	{ PCI_VDEVICE(MARVELL, 0x6042), chip_6042 },
+	{ PCI_VDEVICE(MARVELL, 0x6080), chip_608x },
+	{ PCI_VDEVICE(MARVELL, 0x6081), chip_608x },
+
+	{ PCI_VDEVICE(ADAPTEC2, 0x0241), chip_604x },
+
+	/* Adaptec 1430SA */
+	{ PCI_VDEVICE(ADAPTEC2, 0x0243), chip_7042 },
+
+	/* Marvell 7042 support */
+	{ PCI_VDEVICE(MARVELL, 0x7042), chip_7042 },
+
+	/* Highpoint RocketRAID PCIe series */
+	{ PCI_VDEVICE(TTI, 0x2300), chip_7042 },
+	{ PCI_VDEVICE(TTI, 0x2310), chip_7042 },
+
+	{ }			/* terminate list */
+};
 
 static struct pci_driver mv_pci_driver = {
 	.name			= DRV_NAME,
@@ -4313,6 +4318,7 @@
 #endif
 
 };
+MODULE_DEVICE_TABLE(pci, mv_pci_tbl);
 
 /**
  *      mv_print_info - Dump key info to kernel log for perusal.
@@ -4485,7 +4491,6 @@
 MODULE_AUTHOR("Brett Russ");
 MODULE_DESCRIPTION("SCSI low-level driver for Marvell SATA controllers");
 MODULE_LICENSE("GPL v2");
-MODULE_DEVICE_TABLE(pci, mv_pci_tbl);
 MODULE_VERSION(DRV_VERSION);
 MODULE_ALIAS("platform:" DRV_NAME);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/sata_nv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/sata_nv.c
@@ -297,7 +297,7 @@
 static void nv_ck804_thaw(struct ata_port *ap);
 static int nv_adma_slave_config(struct scsi_device *sdev);
 static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc);
-static void nv_adma_qc_prep(struct ata_queued_cmd *qc);
+static enum ata_completion_errors nv_adma_qc_prep(struct ata_queued_cmd *qc);
 static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc);
 static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance);
 static void nv_adma_irq_clear(struct ata_port *ap);
@@ -319,7 +319,7 @@
 static void nv_swncq_error_handler(struct ata_port *ap);
 static int nv_swncq_slave_config(struct scsi_device *sdev);
 static int nv_swncq_port_start(struct ata_port *ap);
-static void nv_swncq_qc_prep(struct ata_queued_cmd *qc);
+static enum ata_completion_errors nv_swncq_qc_prep(struct ata_queued_cmd *qc);
 static void nv_swncq_fill_sg(struct ata_queued_cmd *qc);
 static unsigned int nv_swncq_qc_issue(struct ata_queued_cmd *qc);
 static void nv_swncq_irq_clear(struct ata_port *ap, u16 fis);
@@ -984,7 +984,7 @@
 					check_commands = 0;
 				check_commands &= ~(1 << pos);
 			}
-			ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask);
+			ata_qc_complete_multiple(ap, ata_qc_get_active(ap) ^ done_mask);
 		}
 	}
 
@@ -1344,7 +1344,7 @@
 	return 1;
 }
 
-static void nv_adma_qc_prep(struct ata_queued_cmd *qc)
+static enum ata_completion_errors nv_adma_qc_prep(struct ata_queued_cmd *qc)
 {
 	struct nv_adma_port_priv *pp = qc->ap->private_data;
 	struct nv_adma_cpb *cpb = &pp->cpb[qc->hw_tag];
@@ -1356,7 +1356,7 @@
 			(qc->flags & ATA_QCFLAG_DMAMAP));
 		nv_adma_register_mode(qc->ap);
 		ata_bmdma_qc_prep(qc);
-		return;
+		return AC_ERR_OK;
 	}
 
 	cpb->resp_flags = NV_CPB_RESP_DONE;
@@ -1388,6 +1388,8 @@
 	cpb->ctl_flags = ctl_flags;
 	wmb();
 	cpb->resp_flags = 0;
+
+	return AC_ERR_OK;
 }
 
 static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc)
@@ -1950,17 +1952,19 @@
 	return 0;
 }
 
-static void nv_swncq_qc_prep(struct ata_queued_cmd *qc)
+static enum ata_completion_errors nv_swncq_qc_prep(struct ata_queued_cmd *qc)
 {
 	if (qc->tf.protocol != ATA_PROT_NCQ) {
 		ata_bmdma_qc_prep(qc);
-		return;
+		return AC_ERR_OK;
 	}
 
 	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
-		return;
+		return AC_ERR_OK;
 
 	nv_swncq_fill_sg(qc);
+
+	return AC_ERR_OK;
 }
 
 static void nv_swncq_fill_sg(struct ata_queued_cmd *qc)
@@ -2096,7 +2100,7 @@
 	pp->dhfis_bits &= ~done_mask;
 	pp->dmafis_bits &= ~done_mask;
 	pp->sdbfis_bits |= done_mask;
-	ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask);
+	ata_qc_complete_multiple(ap, ata_qc_get_active(ap) ^ done_mask);
 
 	if (!ap->qc_active) {
 		DPRINTK("over\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/sata_promise.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/sata_promise.c
@@ -139,7 +139,7 @@
 static int pdc_ata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
 static int pdc_common_port_start(struct ata_port *ap);
 static int pdc_sata_port_start(struct ata_port *ap);
-static void pdc_qc_prep(struct ata_queued_cmd *qc);
+static enum ata_completion_errors pdc_qc_prep(struct ata_queued_cmd *qc);
 static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
 static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
 static int pdc_check_atapi_dma(struct ata_queued_cmd *qc);
@@ -633,7 +633,7 @@
 	prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
 }
 
-static void pdc_qc_prep(struct ata_queued_cmd *qc)
+static enum ata_completion_errors pdc_qc_prep(struct ata_queued_cmd *qc)
 {
 	struct pdc_port_priv *pp = qc->ap->private_data;
 	unsigned int i;
@@ -665,6 +665,8 @@
 	default:
 		break;
 	}
+
+	return AC_ERR_OK;
 }
 
 static int pdc_is_sataii_tx4(unsigned long flags)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/sata_qstor.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/sata_qstor.c
@@ -100,7 +100,7 @@
 static int qs_ata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
 static int qs_port_start(struct ata_port *ap);
 static void qs_host_stop(struct ata_host *host);
-static void qs_qc_prep(struct ata_queued_cmd *qc);
+static enum ata_completion_errors qs_qc_prep(struct ata_queued_cmd *qc);
 static unsigned int qs_qc_issue(struct ata_queued_cmd *qc);
 static int qs_check_atapi_dma(struct ata_queued_cmd *qc);
 static void qs_freeze(struct ata_port *ap);
@@ -260,7 +260,7 @@
 	return si;
 }
 
-static void qs_qc_prep(struct ata_queued_cmd *qc)
+static enum ata_completion_errors qs_qc_prep(struct ata_queued_cmd *qc)
 {
 	struct qs_port_priv *pp = qc->ap->private_data;
 	u8 dflags = QS_DF_PORD, *buf = pp->pkt;
@@ -272,7 +272,7 @@
 
 	qs_enter_reg_mode(qc->ap);
 	if (qc->tf.protocol != ATA_PROT_DMA)
-		return;
+		return AC_ERR_OK;
 
 	nelem = qs_fill_sg(qc);
 
@@ -295,6 +295,8 @@
 
 	/* frame information structure (FIS) */
 	ata_tf_to_fis(&qc->tf, 0, 1, &buf[32]);
+
+	return AC_ERR_OK;
 }
 
 static inline void qs_packet_start(struct ata_queued_cmd *qc)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/sata_rcar.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/sata_rcar.c
@@ -120,7 +120,7 @@
 /* Descriptor table word 0 bit (when DTA32M = 1) */
 #define SATA_RCAR_DTEND			BIT(0)
 
-#define SATA_RCAR_DMA_BOUNDARY		0x1FFFFFFEUL
+#define SATA_RCAR_DMA_BOUNDARY		0x1FFFFFFFUL
 
 /* Gen2 Physical Layer Control Registers */
 #define RCAR_GEN2_PHY_CTL1_REG		0x1704
@@ -550,12 +550,14 @@
 	prd[si - 1].addr |= cpu_to_le32(SATA_RCAR_DTEND);
 }
 
-static void sata_rcar_qc_prep(struct ata_queued_cmd *qc)
+static enum ata_completion_errors sata_rcar_qc_prep(struct ata_queued_cmd *qc)
 {
 	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
-		return;
+		return AC_ERR_OK;
 
 	sata_rcar_bmdma_fill_sg(qc);
+
+	return AC_ERR_OK;
 }
 
 static void sata_rcar_bmdma_setup(struct ata_queued_cmd *qc)
@@ -905,7 +907,7 @@
 	pm_runtime_enable(dev);
 	ret = pm_runtime_get_sync(dev);
 	if (ret < 0)
-		goto err_pm_disable;
+		goto err_pm_put;
 
 	host = ata_host_alloc(dev, 1);
 	if (!host) {
@@ -935,7 +937,6 @@
 
 err_pm_put:
 	pm_runtime_put(dev);
-err_pm_disable:
 	pm_runtime_disable(dev);
 	return ret;
 }
@@ -989,8 +990,10 @@
 	int ret;
 
 	ret = pm_runtime_get_sync(dev);
-	if (ret < 0)
+	if (ret < 0) {
+		pm_runtime_put(dev);
 		return ret;
+	}
 
 	if (priv->type == RCAR_GEN3_SATA) {
 		sata_rcar_init_module(priv);
@@ -1015,8 +1018,10 @@
 	int ret;
 
 	ret = pm_runtime_get_sync(dev);
-	if (ret < 0)
+	if (ret < 0) {
+		pm_runtime_put(dev);
 		return ret;
+	}
 
 	sata_rcar_setup_port(host);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/sata_sil.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/sata_sil.c
@@ -103,7 +103,7 @@
 static int sil_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
 static int sil_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
 static int sil_set_mode(struct ata_link *link, struct ata_device **r_failed);
-static void sil_qc_prep(struct ata_queued_cmd *qc);
+static enum ata_completion_errors sil_qc_prep(struct ata_queued_cmd *qc);
 static void sil_bmdma_setup(struct ata_queued_cmd *qc);
 static void sil_bmdma_start(struct ata_queued_cmd *qc);
 static void sil_bmdma_stop(struct ata_queued_cmd *qc);
@@ -128,7 +128,7 @@
 static const struct sil_drivelist {
 	const char *product;
 	unsigned int quirk;
-} sil_blacklist [] = {
+} sil_quirks[] = {
 	{ "ST320012AS",		SIL_QUIRK_MOD15WRITE },
 	{ "ST330013AS",		SIL_QUIRK_MOD15WRITE },
 	{ "ST340017AS",		SIL_QUIRK_MOD15WRITE },
@@ -317,12 +317,14 @@
 		last_prd->flags_len |= cpu_to_le32(ATA_PRD_EOT);
 }
 
-static void sil_qc_prep(struct ata_queued_cmd *qc)
+static enum ata_completion_errors sil_qc_prep(struct ata_queued_cmd *qc)
 {
 	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
-		return;
+		return AC_ERR_OK;
 
 	sil_fill_sg(qc);
+
+	return AC_ERR_OK;
 }
 
 static unsigned char sil_get_device_cache_line(struct pci_dev *pdev)
@@ -599,8 +601,8 @@
  *	list, and apply the fixups to only the specific
  *	devices/hosts/firmwares that need it.
  *
- *	20040111 - Seagate drives affected by the Mod15Write bug are blacklisted
- *	The Maxtor quirk is in the blacklist, but I'm keeping the original
+ *	20040111 - Seagate drives affected by the Mod15Write bug are quirked
+ *	The Maxtor quirk is in sil_quirks, but I'm keeping the original
  *	pessimistic fix for the following reasons...
  *	- There seems to be less info on it, only one device gleaned off the
  *	Windows	driver, maybe only one is affected.  More info would be greatly
@@ -619,9 +621,9 @@
 
 	ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num));
 
-	for (n = 0; sil_blacklist[n].product; n++)
-		if (!strcmp(sil_blacklist[n].product, model_num)) {
-			quirks = sil_blacklist[n].quirk;
+	for (n = 0; sil_quirks[n].product; n++)
+		if (!strcmp(sil_quirks[n].product, model_num)) {
+			quirks = sil_quirks[n].quirk;
 			break;
 		}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/sata_sil24.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/sata_sil24.c
@@ -326,7 +326,7 @@
 static int sil24_scr_read(struct ata_link *link, unsigned sc_reg, u32 *val);
 static int sil24_scr_write(struct ata_link *link, unsigned sc_reg, u32 val);
 static int sil24_qc_defer(struct ata_queued_cmd *qc);
-static void sil24_qc_prep(struct ata_queued_cmd *qc);
+static enum ata_completion_errors sil24_qc_prep(struct ata_queued_cmd *qc);
 static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc);
 static bool sil24_qc_fill_rtf(struct ata_queued_cmd *qc);
 static void sil24_pmp_attach(struct ata_port *ap);
@@ -830,7 +830,7 @@
 	return ata_std_qc_defer(qc);
 }
 
-static void sil24_qc_prep(struct ata_queued_cmd *qc)
+static enum ata_completion_errors sil24_qc_prep(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
 	struct sil24_port_priv *pp = ap->private_data;
@@ -874,6 +874,8 @@
 
 	if (qc->flags & ATA_QCFLAG_DMAMAP)
 		sil24_fill_sg(qc, sge);
+
+	return AC_ERR_OK;
 }
 
 static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ata/sata_sx4.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ata/sata_sx4.c
@@ -202,7 +202,7 @@
 static void pdc_freeze(struct ata_port *ap);
 static void pdc_thaw(struct ata_port *ap);
 static int pdc_port_start(struct ata_port *ap);
-static void pdc20621_qc_prep(struct ata_queued_cmd *qc);
+static enum ata_completion_errors pdc20621_qc_prep(struct ata_queued_cmd *qc);
 static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
 static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
 static unsigned int pdc20621_dimm_init(struct ata_host *host);
@@ -530,7 +530,7 @@
 	VPRINTK("ata pkt buf ofs %u, mmio copied\n", i);
 }
 
-static void pdc20621_qc_prep(struct ata_queued_cmd *qc)
+static enum ata_completion_errors pdc20621_qc_prep(struct ata_queued_cmd *qc)
 {
 	switch (qc->tf.protocol) {
 	case ATA_PROT_DMA:
@@ -542,6 +542,8 @@
 	default:
 		break;
 	}
+
+	return AC_ERR_OK;
 }
 
 static void __pdc20621_push_hdma(struct ata_queued_cmd *qc,
@@ -1002,8 +1004,7 @@
 
 	offset -= (idx * window_size);
 	idx++;
-	dist = ((long) (window_size - (offset + size))) >= 0 ? size :
-		(long) (window_size - offset);
+	dist = min(size, window_size - offset);
 	memcpy_fromio(psource, dimm_mmio + offset / 4, dist);
 
 	psource += dist;
@@ -1051,8 +1052,7 @@
 	readl(mmio + PDC_DIMM_WINDOW_CTLR);
 	offset -= (idx * window_size);
 	idx++;
-	dist = ((long)(s32)(window_size - (offset + size))) >= 0 ? size :
-		(long) (window_size - offset);
+	dist = min(size, window_size - offset);
 	memcpy_toio(dimm_mmio + offset / 4, psource, dist);
 	writel(0x01, mmio + PDC_GENERAL_CTLR);
 	readl(mmio + PDC_GENERAL_CTLR);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/atm/atmtcp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/atm/atmtcp.c
@@ -433,9 +433,15 @@
 		return -EMEDIUMTYPE;
 	}
 	dev_data = PRIV(dev);
-	if (!dev_data->persist) return 0;
+	if (!dev_data->persist) {
+		atm_dev_put(dev);
+		return 0;
+	}
 	dev_data->persist = 0;
-	if (PRIV(dev)->vcc) return 0;
+	if (PRIV(dev)->vcc) {
+		atm_dev_put(dev);
+		return 0;
+	}
 	kfree(dev_data);
 	atm_dev_put(dev);
 	atm_dev_deregister(dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/atm/eni.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/atm/eni.c
@@ -374,7 +374,7 @@
 		here = (eni_vcc->descr+skip) & (eni_vcc->words-1);
 		dma[j++] = (here << MID_DMA_COUNT_SHIFT) | (vcc->vci
 		    << MID_DMA_VCI_SHIFT) | MID_DT_JK;
-		j++;
+		dma[j++] = 0;
 	}
 	here = (eni_vcc->descr+size+skip) & (eni_vcc->words-1);
 	if (!eff) size += skip;
@@ -447,7 +447,7 @@
 	if (size != eff) {
 		dma[j++] = (here << MID_DMA_COUNT_SHIFT) |
 		    (vcc->vci << MID_DMA_VCI_SHIFT) | MID_DT_JK;
-		j++;
+		dma[j++] = 0;
 	}
 	if (!j || j > 2*RX_DMA_BUF) {
 		printk(KERN_CRIT DEV_LABEL "!j or j too big!!!\n");
@@ -1116,6 +1116,8 @@
 	}
 	paddr = dma_map_single(&eni_dev->pci_dev->dev,skb->data,skb->len,
 			       DMA_TO_DEVICE);
+	if (dma_mapping_error(&eni_dev->pci_dev->dev, paddr))
+		return enq_next;
 	ENI_PRV_PADDR(skb) = paddr;
 	/* prepare DMA queue entries */
 	j = 0;
@@ -2245,7 +2247,7 @@
 
 	rc = dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(32));
 	if (rc < 0)
-		goto out;
+		goto err_disable;
 
 	rc = -ENOMEM;
 	eni_dev = kmalloc(sizeof(struct eni_dev), GFP_KERNEL);
@@ -2281,7 +2283,8 @@
 	return rc;
 
 err_eni_release:
-	eni_do_release(dev);
+	dev->phy = NULL;
+	iounmap(ENI_DEV(dev)->ioaddr);
 err_unregister:
 	atm_dev_deregister(dev);
 err_free_consistent:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/atm/firestream.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/atm/firestream.c
@@ -912,6 +912,7 @@
 			}
 			if (!to) {
 				printk ("No more free channels for FS50..\n");
+				kfree(vcc);
 				return -EBUSY;
 			}
 			vcc->channo = dev->channo;
@@ -922,6 +923,7 @@
 			if (((DO_DIRECTION(rxtp) && dev->atm_vccs[vcc->channo])) ||
 			    ( DO_DIRECTION(txtp) && test_bit (vcc->channo, dev->tx_inuse))) {
 				printk ("Channel is in use for FS155.\n");
+				kfree(vcc);
 				return -EBUSY;
 			}
 		}
@@ -935,6 +937,7 @@
 			    tc, sizeof (struct fs_transmit_config));
 		if (!tc) {
 			fs_dprintk (FS_DEBUG_OPEN, "fs: can't alloc transmit_config.\n");
+			kfree(vcc);
 			return -ENOMEM;
 		}
 
@@ -995,6 +998,7 @@
 				error = make_rate (pcr, r, &tmc0, NULL);
 				if (error) {
 					kfree(tc);
+					kfree(vcc);
 					return error;
 				}
 			}
@@ -1673,6 +1677,8 @@
 	dev->hw_base = pci_resource_start(pci_dev, 0);
 
 	dev->base = ioremap(dev->hw_base, 0x1000);
+	if (!dev->base)
+		return 1;
 
 	reset_chip (dev);
   
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/atm/fore200e.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/atm/fore200e.c
@@ -1414,12 +1414,14 @@
 static void
 fore200e_close(struct atm_vcc* vcc)
 {
-    struct fore200e*        fore200e = FORE200E_DEV(vcc->dev);
     struct fore200e_vcc*    fore200e_vcc;
+    struct fore200e*        fore200e;
     struct fore200e_vc_map* vc_map;
     unsigned long           flags;
 
     ASSERT(vcc);
+    fore200e = FORE200E_DEV(vcc->dev);
+
     ASSERT((vcc->vpi >= 0) && (vcc->vpi < 1<<FORE200E_VPI_BITS));
     ASSERT((vcc->vci >= 0) && (vcc->vci < 1<<FORE200E_VCI_BITS));
 
@@ -1464,10 +1466,10 @@
 static int
 fore200e_send(struct atm_vcc *vcc, struct sk_buff *skb)
 {
-    struct fore200e*        fore200e     = FORE200E_DEV(vcc->dev);
-    struct fore200e_vcc*    fore200e_vcc = FORE200E_VCC(vcc);
+    struct fore200e*        fore200e;
+    struct fore200e_vcc*    fore200e_vcc;
     struct fore200e_vc_map* vc_map;
-    struct host_txq*        txq          = &fore200e->host_txq;
+    struct host_txq*        txq;
     struct host_txq_entry*  entry;
     struct tpd*             tpd;
     struct tpd_haddr        tpd_haddr;
@@ -1480,9 +1482,18 @@
     unsigned char*          data;
     unsigned long           flags;
 
-    ASSERT(vcc);
-    ASSERT(fore200e);
-    ASSERT(fore200e_vcc);
+    if (!vcc)
+        return -EINVAL;
+
+    fore200e = FORE200E_DEV(vcc->dev);
+    fore200e_vcc = FORE200E_VCC(vcc);
+
+    if (!fore200e)
+        return -EINVAL;
+
+    txq = &fore200e->host_txq;
+    if (!fore200e_vcc)
+        return -EINVAL;
 
     if (!test_bit(ATM_VF_READY, &vcc->flags)) {
 	DPRINTK(1, "VC %d.%d.%d not ready for tx\n", vcc->itf, vcc->vpi, vcc->vpi);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/atm/idt77105.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/atm/idt77105.c
@@ -262,7 +262,7 @@
 {
 	unsigned long flags;
 
-	if (!(dev->dev_data = kmalloc(sizeof(struct idt77105_priv),GFP_KERNEL)))
+	if (!(dev->phy_data = kmalloc(sizeof(struct idt77105_priv),GFP_KERNEL)))
 		return -ENOMEM;
 	PRIV(dev)->dev = dev;
 	spin_lock_irqsave(&idt77105_priv_lock, flags);
@@ -337,7 +337,7 @@
                 else
                     idt77105_all = walk->next;
 	        dev->phy = NULL;
-                dev->dev_data = NULL;
+                dev->phy_data = NULL;
                 kfree(walk);
                 break;
             }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/atm/idt77252.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/atm/idt77252.c
@@ -1117,8 +1117,8 @@
 	rpp->len += skb->len;
 
 	if (stat & SAR_RSQE_EPDU) {
+		unsigned int len, truesize;
 		unsigned char *l1l2;
-		unsigned int len;
 
 		l1l2 = (unsigned char *) ((unsigned long) skb->data + skb->len - 6);
 
@@ -1188,14 +1188,15 @@
 		ATM_SKB(skb)->vcc = vcc;
 		__net_timestamp(skb);
 
+		truesize = skb->truesize;
 		vcc->push(vcc, skb);
 		atomic_inc(&vcc->stats->rx);
 
-		if (skb->truesize > SAR_FB_SIZE_3)
+		if (truesize > SAR_FB_SIZE_3)
 			add_rx_skb(card, 3, SAR_FB_SIZE_3, 1);
-		else if (skb->truesize > SAR_FB_SIZE_2)
+		else if (truesize > SAR_FB_SIZE_2)
 			add_rx_skb(card, 2, SAR_FB_SIZE_2, 1);
-		else if (skb->truesize > SAR_FB_SIZE_1)
+		else if (truesize > SAR_FB_SIZE_1)
 			add_rx_skb(card, 1, SAR_FB_SIZE_1, 1);
 		else
 			add_rx_skb(card, 0, SAR_FB_SIZE_0, 1);
@@ -2914,6 +2915,7 @@
 
 				recycle_rx_pool_skb(card, &vc->rcv.rx_pool);
 			}
+			kfree(vc);
 		}
 	}
 }
@@ -2934,6 +2936,8 @@
 	vc->scq = alloc_scq(card, vc->class);
 	if (!vc->scq) {
 		printk("%s: can't get SCQ.\n", card->name);
+		kfree(card->vcs[0]);
+		card->vcs[0] = NULL;
 		return -ENOMEM;
 	}
 
@@ -2957,6 +2961,15 @@
 	return 0;
 }
 
+static void
+close_card_ubr0(struct idt77252_dev *card)
+{
+	struct vc_map *vc = card->vcs[0];
+
+	free_scq(card, vc->scq);
+	kfree(vc);
+}
+
 static int
 idt77252_dev_open(struct idt77252_dev *card)
 {
@@ -3006,6 +3019,7 @@
 	struct idt77252_dev *card = dev->dev_data;
 	u32 conf;
 
+	close_card_ubr0(card);
 	close_card_oam(card);
 
 	conf = SAR_CFG_RXPTH |	/* enable receive path           */
@@ -3606,7 +3620,7 @@
 
 	if ((err = dma_set_mask_and_coherent(&pcidev->dev, DMA_BIT_MASK(32)))) {
 		printk("idt77252: can't enable DMA for PCI device at %s\n", pci_name(pcidev));
-		return err;
+		goto err_out_disable_pdev;
 	}
 
 	card = kzalloc(sizeof(struct idt77252_dev), GFP_KERNEL);
@@ -3766,6 +3780,7 @@
 		card = idt77252_chain;
 		dev = card->atmdev;
 		idt77252_chain = card->next;
+		del_timer_sync(&card->tst_timer);
 
 		if (dev->phy->stop)
 			dev->phy->stop(dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/atm/iphase.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/atm/iphase.c
@@ -2290,19 +2290,21 @@
 static int reset_sar(struct atm_dev *dev)  
 {  
 	IADEV *iadev;  
-	int i, error = 1;  
+	int i, error;
 	unsigned int pci[64];  
 	  
 	iadev = INPH_IA_DEV(dev);  
-	for(i=0; i<64; i++)  
-	  if ((error = pci_read_config_dword(iadev->pci,  
-				i*4, &pci[i])) != PCIBIOS_SUCCESSFUL)  
-  	      return error;  
+	for (i = 0; i < 64; i++) {
+		error = pci_read_config_dword(iadev->pci, i * 4, &pci[i]);
+		if (error != PCIBIOS_SUCCESSFUL)
+			return error;
+	}
 	writel(0, iadev->reg+IPHASE5575_EXT_RESET);  
-	for(i=0; i<64; i++)  
-	  if ((error = pci_write_config_dword(iadev->pci,  
-					i*4, pci[i])) != PCIBIOS_SUCCESSFUL)  
-	    return error;  
+	for (i = 0; i < 64; i++) {
+		error = pci_write_config_dword(iadev->pci, i * 4, pci[i]);
+		if (error != PCIBIOS_SUCCESSFUL)
+			return error;
+	}
 	udelay(5);  
 	return 0;  
 }  
@@ -3295,7 +3297,7 @@
 {
 	pci_unregister_driver(&ia_driver);
 
-        del_timer(&ia_timer);
+	del_timer_sync(&ia_timer);
 }
 
 module_init(ia_module_init);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/atm/lanai.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/atm/lanai.c
@@ -2234,6 +2234,7 @@
 	conf1_write(lanai);
 #endif
 	iounmap(lanai->base);
+	lanai->base = NULL;
     error_pci:
 	pci_disable_device(lanai->pci);
     error:
@@ -2246,6 +2247,8 @@
 static void lanai_dev_close(struct atm_dev *atmdev)
 {
 	struct lanai_dev *lanai = (struct lanai_dev *) atmdev->dev_data;
+	if (lanai->base==NULL)
+		return;
 	printk(KERN_INFO DEV_LABEL "(itf %d): shutting down interface\n",
 	    lanai->number);
 	lanai_timed_poll_stop(lanai);
@@ -2555,7 +2558,7 @@
 	struct atm_dev *atmdev;
 	int result;
 
-	lanai = kmalloc(sizeof(*lanai), GFP_KERNEL);
+	lanai = kzalloc(sizeof(*lanai), GFP_KERNEL);
 	if (lanai == NULL) {
 		printk(KERN_ERR DEV_LABEL
 		       ": couldn't allocate dev_data structure!\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/atm/nicstar.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/atm/nicstar.c
@@ -297,7 +297,7 @@
 {
 	XPRINTK("nicstar: nicstar_cleanup() called.\n");
 
-	del_timer(&ns_timer);
+	del_timer_sync(&ns_timer);
 
 	pci_unregister_driver(&nicstar_driver);
 
@@ -525,6 +525,15 @@
 	/* Set the VPI/VCI MSb mask to zero so we can receive OAM cells */
 	writel(0x00000000, card->membase + VPM);
 
+	card->intcnt = 0;
+	if (request_irq
+	    (pcidev->irq, &ns_irq_handler, IRQF_SHARED, "nicstar", card) != 0) {
+		pr_err("nicstar%d: can't allocate IRQ %d.\n", i, pcidev->irq);
+		error = 9;
+		ns_init_card_error(card, error);
+		return error;
+	}
+
 	/* Initialize TSQ */
 	card->tsq.org = dma_alloc_coherent(&card->pcidev->dev,
 					   NS_TSQSIZE + NS_TSQ_ALIGNMENT,
@@ -751,15 +760,6 @@
 
 	card->efbie = 1;
 
-	card->intcnt = 0;
-	if (request_irq
-	    (pcidev->irq, &ns_irq_handler, IRQF_SHARED, "nicstar", card) != 0) {
-		printk("nicstar%d: can't allocate IRQ %d.\n", i, pcidev->irq);
-		error = 9;
-		ns_init_card_error(card, error);
-		return error;
-	}
-
 	/* Register device */
 	card->atmdev = atm_dev_register("nicstar", &card->pcidev->dev, &atm_ops,
 					-1, NULL);
@@ -837,10 +837,12 @@
 			dev_kfree_skb_any(hb);
 	}
 	if (error >= 12) {
-		kfree(card->rsq.org);
+		dma_free_coherent(&card->pcidev->dev, NS_RSQSIZE + NS_RSQ_ALIGNMENT,
+				card->rsq.org, card->rsq.dma);
 	}
 	if (error >= 11) {
-		kfree(card->tsq.org);
+		dma_free_coherent(&card->pcidev->dev, NS_TSQSIZE + NS_TSQ_ALIGNMENT,
+				card->tsq.org, card->tsq.dma);
 	}
 	if (error >= 10) {
 		free_irq(card->pcidev->irq, card);
@@ -1706,6 +1708,8 @@
 
 	if (push_scqe(card, vc, scq, &scqe, skb) != 0) {
 		atomic_inc(&vcc->stats->tx_err);
+		dma_unmap_single(&card->pcidev->dev, NS_PRV_DMA(skb), skb->len,
+				 DMA_TO_DEVICE);
 		dev_kfree_skb_any(skb);
 		return -EIO;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/atm/solos-pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/atm/solos-pci.c
@@ -449,9 +449,9 @@
 	struct sk_buff *skb;
 	unsigned int len;
 
-	spin_lock(&card->cli_queue_lock);
+	spin_lock_bh(&card->cli_queue_lock);
 	skb = skb_dequeue(&card->cli_queue[SOLOS_CHAN(atmdev)]);
-	spin_unlock(&card->cli_queue_lock);
+	spin_unlock_bh(&card->cli_queue_lock);
 	if(skb == NULL)
 		return sprintf(buf, "No data.\n");
 
@@ -956,14 +956,14 @@
 	struct pkt_hdr *header;
 
 	/* Remove any yet-to-be-transmitted packets from the pending queue */
-	spin_lock(&card->tx_queue_lock);
+	spin_lock_bh(&card->tx_queue_lock);
 	skb_queue_walk_safe(&card->tx_queue[port], skb, tmpskb) {
 		if (SKB_CB(skb)->vcc == vcc) {
 			skb_unlink(skb, &card->tx_queue[port]);
 			solos_pop(vcc, skb);
 		}
 	}
-	spin_unlock(&card->tx_queue_lock);
+	spin_unlock_bh(&card->tx_queue_lock);
 
 	skb = alloc_skb(sizeof(*header), GFP_KERNEL);
 	if (!skb) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/atm/uPD98402.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/atm/uPD98402.c
@@ -211,7 +211,7 @@
 static int uPD98402_start(struct atm_dev *dev)
 {
 	DPRINTK("phy_start\n");
-	if (!(dev->dev_data = kmalloc(sizeof(struct uPD98402_priv),GFP_KERNEL)))
+	if (!(dev->phy_data = kmalloc(sizeof(struct uPD98402_priv),GFP_KERNEL)))
 		return -ENOMEM;
 	spin_lock_init(&PRIV(dev)->lock);
 	memset(&PRIV(dev)->sonet_stats,0,sizeof(struct k_sonet_stats));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/atm/zatm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/atm/zatm.c
@@ -940,7 +940,7 @@
 	    vcc->qos.txtp.max_pcr >= ATM_OC3_PCR);
 	if (unlimited && zatm_dev->ubr != -1) zatm_vcc->shaper = zatm_dev->ubr;
 	else {
-		int uninitialized_var(pcr);
+		int pcr;
 
 		if (unlimited) vcc->qos.txtp.max_sdu = ATM_MAX_AAL5_PDU;
 		if ((zatm_vcc->shaper = alloc_shaper(vcc->dev,&pcr,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/auxdisplay/ht16k33.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/auxdisplay/ht16k33.c
@@ -117,8 +117,7 @@
 {
 	struct ht16k33_fbdev *fbdev = &priv->fbdev;
 
-	schedule_delayed_work(&fbdev->work,
-			      msecs_to_jiffies(HZ / fbdev->refresh_rate));
+	schedule_delayed_work(&fbdev->work, HZ / fbdev->refresh_rate);
 }
 
 /*
@@ -220,6 +219,15 @@
 	.check_fb	= ht16k33_bl_check_fb,
 };
 
+/*
+ * Blank events will be passed to the actual device handling the backlight when
+ * we return zero here.
+ */
+static int ht16k33_blank(int blank, struct fb_info *info)
+{
+	return 0;
+}
+
 static int ht16k33_mmap(struct fb_info *info, struct vm_area_struct *vma)
 {
 	struct ht16k33_priv *priv = info->par;
@@ -232,6 +240,7 @@
 	.owner = THIS_MODULE,
 	.fb_read = fb_sys_read,
 	.fb_write = fb_sys_write,
+	.fb_blank = ht16k33_blank,
 	.fb_fillrect = sys_fillrect,
 	.fb_copyarea = sys_copyarea,
 	.fb_imageblit = sys_imageblit,
@@ -419,6 +428,33 @@
 	if (err)
 		return err;
 
+	/* Backlight */
+	memset(&bl_props, 0, sizeof(struct backlight_properties));
+	bl_props.type = BACKLIGHT_RAW;
+	bl_props.max_brightness = MAX_BRIGHTNESS;
+
+	bl = devm_backlight_device_register(&client->dev, DRIVER_NAME"-bl",
+					    &client->dev, priv,
+					    &ht16k33_bl_ops, &bl_props);
+	if (IS_ERR(bl)) {
+		dev_err(&client->dev, "failed to register backlight\n");
+		return PTR_ERR(bl);
+	}
+
+	err = of_property_read_u32(node, "default-brightness-level",
+				   &dft_brightness);
+	if (err) {
+		dft_brightness = MAX_BRIGHTNESS;
+	} else if (dft_brightness > MAX_BRIGHTNESS) {
+		dev_warn(&client->dev,
+			 "invalid default brightness level: %u, using %u\n",
+			 dft_brightness, MAX_BRIGHTNESS);
+		dft_brightness = MAX_BRIGHTNESS;
+	}
+
+	bl->props.brightness = dft_brightness;
+	ht16k33_bl_update_status(bl);
+
 	/* Framebuffer (2 bytes per column) */
 	BUILD_BUG_ON(PAGE_SIZE < HT16K33_FB_SIZE);
 	fbdev->buffer = (unsigned char *) get_zeroed_page(GFP_KERNEL);
@@ -451,6 +487,7 @@
 	fbdev->info->screen_size = HT16K33_FB_SIZE;
 	fbdev->info->fix = ht16k33_fb_fix;
 	fbdev->info->var = ht16k33_fb_var;
+	fbdev->info->bl_dev = bl;
 	fbdev->info->pseudo_palette = NULL;
 	fbdev->info->flags = FBINFO_FLAG_DEFAULT;
 	fbdev->info->par = priv;
@@ -463,34 +500,6 @@
 	if (err)
 		goto err_fbdev_unregister;
 
-	/* Backlight */
-	memset(&bl_props, 0, sizeof(struct backlight_properties));
-	bl_props.type = BACKLIGHT_RAW;
-	bl_props.max_brightness = MAX_BRIGHTNESS;
-
-	bl = devm_backlight_device_register(&client->dev, DRIVER_NAME"-bl",
-					    &client->dev, priv,
-					    &ht16k33_bl_ops, &bl_props);
-	if (IS_ERR(bl)) {
-		dev_err(&client->dev, "failed to register backlight\n");
-		err = PTR_ERR(bl);
-		goto err_fbdev_unregister;
-	}
-
-	err = of_property_read_u32(node, "default-brightness-level",
-				   &dft_brightness);
-	if (err) {
-		dft_brightness = MAX_BRIGHTNESS;
-	} else if (dft_brightness > MAX_BRIGHTNESS) {
-		dev_warn(&client->dev,
-			 "invalid default brightness level: %u, using %u\n",
-			 dft_brightness, MAX_BRIGHTNESS);
-		dft_brightness = MAX_BRIGHTNESS;
-	}
-
-	bl->props.brightness = dft_brightness;
-	ht16k33_bl_update_status(bl);
-
 	ht16k33_fb_queue(priv);
 	return 0;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/auxdisplay/img-ascii-lcd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/auxdisplay/img-ascii-lcd.c
@@ -280,6 +280,16 @@
 	if (msg[count - 1] == '\n')
 		count--;
 
+	if (!count) {
+		/* clear the LCD */
+		devm_kfree(&ctx->pdev->dev, ctx->message);
+		ctx->message = NULL;
+		ctx->message_len = 0;
+		memset(ctx->curr, ' ', ctx->cfg->num_chars);
+		ctx->cfg->update(ctx);
+		return 0;
+	}
+
 	new_msg = devm_kmalloc(&ctx->pdev->dev, count + 1, GFP_KERNEL);
 	if (!new_msg)
 		return -ENOMEM;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/arch_topology.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/arch_topology.c
@@ -48,7 +48,7 @@
 {
 	struct cpu *cpu = container_of(dev, struct cpu, dev);
 
-	return sprintf(buf, "%lu\n", topology_get_cpu_scale(cpu->dev.id));
+	return sysfs_emit(buf, "%lu\n", topology_get_cpu_scale(cpu->dev.id));
 }
 
 static void update_topology_flags_workfn(struct work_struct *work);
@@ -270,7 +270,7 @@
 static int __init parse_core(struct device_node *core, int package_id,
 			     int core_id)
 {
-	char name[10];
+	char name[20];
 	bool leaf = true;
 	int i = 0;
 	int cpu;
@@ -317,7 +317,7 @@
 
 static int __init parse_cluster(struct device_node *cluster, int depth)
 {
-	char name[10];
+	char name[20];
 	bool leaf = true;
 	bool has_cores = false;
 	struct device_node *c;
@@ -457,7 +457,7 @@
 	for_each_online_cpu(cpu) {
 		cpu_topo = &cpu_topology[cpu];
 
-		if (cpuid_topo->llc_id == cpu_topo->llc_id) {
+		if (cpu_topo->llc_id != -1 && cpuid_topo->llc_id == cpu_topo->llc_id) {
 			cpumask_set_cpu(cpu, &cpuid_topo->llc_sibling);
 			cpumask_set_cpu(cpuid, &cpu_topo->llc_sibling);
 		}
@@ -538,4 +538,23 @@
 	else if (of_have_populated_dt() && parse_dt_topology())
 		reset_cpu_topology();
 }
+
+void store_cpu_topology(unsigned int cpuid)
+{
+	struct cpu_topology *cpuid_topo = &cpu_topology[cpuid];
+
+	if (cpuid_topo->package_id != -1)
+		goto topology_populated;
+
+	cpuid_topo->thread_id = -1;
+	cpuid_topo->core_id = cpuid;
+	cpuid_topo->package_id = cpu_to_node(cpuid);
+
+	pr_debug("CPU%u: package %d core %d thread %d\n",
+		 cpuid, cpuid_topo->package_id, cpuid_topo->core_id,
+		 cpuid_topo->thread_id);
+
+topology_populated:
+	update_siblings_masks(cpuid);
+}
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/bus.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/bus.c
@@ -103,7 +103,8 @@
 {
 	struct bus_attribute *bus_attr = to_bus_attr(attr);
 	struct subsys_private *subsys_priv = to_subsys_private(kobj);
-	ssize_t ret = 0;
+	/* return -EIO for reading a bus attribute without show() */
+	ssize_t ret = -EIO;
 
 	if (bus_attr->show)
 		ret = bus_attr->show(subsys_priv->bus, buf);
@@ -115,7 +116,8 @@
 {
 	struct bus_attribute *bus_attr = to_bus_attr(attr);
 	struct subsys_private *subsys_priv = to_subsys_private(kobj);
-	ssize_t ret = 0;
+	/* return -EIO for writing a bus attribute without store() */
+	ssize_t ret = -EIO;
 
 	if (bus_attr->store)
 		ret = bus_attr->store(subsys_priv->bus, buf, count);
@@ -620,7 +622,7 @@
 	if (drv->bus->p->drivers_autoprobe) {
 		error = driver_attach(drv);
 		if (error)
-			goto out_unregister;
+			goto out_del_list;
 	}
 	module_add_driver(drv->owner, drv);
 
@@ -647,6 +649,8 @@
 
 	return 0;
 
+out_del_list:
+	klist_del(&priv->knode_bus);
 out_unregister:
 	kobject_put(&priv->kobj);
 	/* drv->p is freed in driver_release()  */
@@ -869,6 +873,8 @@
 	bus_remove_file(bus, &bus_attr_uevent);
 bus_uevent_fail:
 	kset_unregister(&bus->p->subsys);
+	/* Above kset_unregister() will kfree @bus->p */
+	bus->p = NULL;
 out:
 	kfree(bus->p);
 	bus->p = NULL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/cacheinfo.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/cacheinfo.c
@@ -377,7 +377,7 @@
 {
 	struct cacheinfo *this_leaf = dev_get_drvdata(dev);
 
-	return sprintf(buf, "%uK\n", this_leaf->size >> 10);
+	return sysfs_emit(buf, "%uK\n", this_leaf->size >> 10);
 }
 
 static ssize_t shared_cpumap_show_func(struct device *dev, bool list, char *buf)
@@ -407,11 +407,11 @@
 
 	switch (this_leaf->type) {
 	case CACHE_TYPE_DATA:
-		return sprintf(buf, "Data\n");
+		return sysfs_emit(buf, "Data\n");
 	case CACHE_TYPE_INST:
-		return sprintf(buf, "Instruction\n");
+		return sysfs_emit(buf, "Instruction\n");
 	case CACHE_TYPE_UNIFIED:
-		return sprintf(buf, "Unified\n");
+		return sysfs_emit(buf, "Unified\n");
 	default:
 		return -EINVAL;
 	}
@@ -425,11 +425,11 @@
 	int n = 0;
 
 	if ((ci_attr & CACHE_READ_ALLOCATE) && (ci_attr & CACHE_WRITE_ALLOCATE))
-		n = sprintf(buf, "ReadWriteAllocate\n");
+		n = sysfs_emit(buf, "ReadWriteAllocate\n");
 	else if (ci_attr & CACHE_READ_ALLOCATE)
-		n = sprintf(buf, "ReadAllocate\n");
+		n = sysfs_emit(buf, "ReadAllocate\n");
 	else if (ci_attr & CACHE_WRITE_ALLOCATE)
-		n = sprintf(buf, "WriteAllocate\n");
+		n = sysfs_emit(buf, "WriteAllocate\n");
 	return n;
 }
 
@@ -441,9 +441,9 @@
 	int n = 0;
 
 	if (ci_attr & CACHE_WRITE_THROUGH)
-		n = sprintf(buf, "WriteThrough\n");
+		n = sysfs_emit(buf, "WriteThrough\n");
 	else if (ci_attr & CACHE_WRITE_BACK)
-		n = sprintf(buf, "WriteBack\n");
+		n = sysfs_emit(buf, "WriteBack\n");
 	return n;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/class.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/class.c
@@ -191,6 +191,11 @@
 	}
 	error = class_add_groups(class_get(cls), cls->class_groups);
 	class_put(cls);
+	if (error) {
+		kobject_del(&cp->subsys.kobj);
+		kfree_const(cp->subsys.kobj.name);
+		kfree(cp);
+	}
 	return error;
 }
 EXPORT_SYMBOL_GPL(__class_register);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/component.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/component.c
@@ -102,11 +102,11 @@
 	seq_printf(s, "%-40s %20s\n", "device name", "status");
 	seq_puts(s, "-------------------------------------------------------------\n");
 	for (i = 0; i < match->num; i++) {
-		struct device *d = (struct device *)match->compare[i].data;
+		struct component *component = match->compare[i].component;
 
-		seq_printf(s, "%-40s %20s\n", dev_name(d),
-			   match->compare[i].component ?
-			   "registered" : "not registered");
+		seq_printf(s, "%-40s %20s\n",
+			   component ? dev_name(component->dev) : "(unknown)",
+			   component ? (component->bound ? "bound" : "not bound") : "not registered");
 	}
 	mutex_unlock(&component_mutex);
 
@@ -257,7 +257,8 @@
 	ret = master->ops->bind(master->dev);
 	if (ret < 0) {
 		devres_release_group(master->dev, NULL);
-		dev_info(master->dev, "master bind failed: %d\n", ret);
+		if (ret != -EPROBE_DEFER)
+			dev_info(master->dev, "master bind failed: %d\n", ret);
 		return ret;
 	}
 
@@ -611,8 +612,9 @@
 		devres_release_group(component->dev, NULL);
 		devres_release_group(master->dev, NULL);
 
-		dev_err(master->dev, "failed to bind %s (ops %ps): %d\n",
-			dev_name(component->dev), component->ops, ret);
+		if (ret != -EPROBE_DEFER)
+			dev_err(master->dev, "failed to bind %s (ops %ps): %d\n",
+				dev_name(component->dev), component->ops, ret);
 	}
 
 	return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/core.c
@@ -106,6 +106,16 @@
 #endif
 #endif /* !CONFIG_SRCU */
 
+static bool device_is_ancestor(struct device *dev, struct device *target)
+{
+	while (target->parent) {
+		target = target->parent;
+		if (dev == target)
+			return true;
+	}
+	return false;
+}
+
 /**
  * device_is_dependent - Check if one device depends on another one
  * @dev: Device to check dependencies for.
@@ -119,7 +129,12 @@
 	struct device_link *link;
 	int ret;
 
-	if (dev == target)
+	/*
+	 * The "ancestors" check is needed to catch the case when the target
+	 * device has not been completely initialized yet and it is still
+	 * missing from the list of children of its parent device.
+	 */
+	if (dev == target || device_is_ancestor(dev, target))
 		return 1;
 
 	ret = device_for_each_child(dev, target, device_is_dependent);
@@ -454,8 +469,7 @@
 	dev_dbg(link->consumer, "Dropping the link to %s\n",
 		dev_name(link->supplier));
 
-	if (link->flags & DL_FLAG_PM_RUNTIME)
-		pm_runtime_drop_link(link->consumer);
+	pm_runtime_drop_link(link);
 
 	list_del_rcu(&link->s_node);
 	list_del_rcu(&link->c_node);
@@ -469,8 +483,7 @@
 	dev_info(link->consumer, "Dropping the link to %s\n",
 		 dev_name(link->supplier));
 
-	if (link->flags & DL_FLAG_PM_RUNTIME)
-		pm_runtime_drop_link(link->consumer);
+	pm_runtime_drop_link(link);
 
 	list_del(&link->s_node);
 	list_del(&link->c_node);
@@ -1014,7 +1027,7 @@
 			  char *buf)
 {
 	struct dev_ext_attribute *ea = to_ext_attr(attr);
-	return snprintf(buf, PAGE_SIZE, "%lx\n", *(unsigned long *)(ea->var));
+	return sysfs_emit(buf, "%lx\n", *(unsigned long *)(ea->var));
 }
 EXPORT_SYMBOL_GPL(device_show_ulong);
 
@@ -1044,7 +1057,7 @@
 {
 	struct dev_ext_attribute *ea = to_ext_attr(attr);
 
-	return snprintf(buf, PAGE_SIZE, "%d\n", *(int *)(ea->var));
+	return sysfs_emit(buf, "%d\n", *(int *)(ea->var));
 }
 EXPORT_SYMBOL_GPL(device_show_int);
 
@@ -1065,7 +1078,7 @@
 {
 	struct dev_ext_attribute *ea = to_ext_attr(attr);
 
-	return snprintf(buf, PAGE_SIZE, "%d\n", *(bool *)(ea->var));
+	return sysfs_emit(buf, "%d\n", *(bool *)(ea->var));
 }
 EXPORT_SYMBOL_GPL(device_show_bool);
 
@@ -1260,8 +1273,11 @@
 	if (!env)
 		return -ENOMEM;
 
+	/* Synchronize with really_probe() */
+	device_lock(dev);
 	/* let the kset specific function add its keys */
 	retval = kset->uevent_ops->uevent(kset, &dev->kobj, env);
+	device_unlock(dev);
 	if (retval)
 		goto out;
 
@@ -1297,7 +1313,7 @@
 	device_lock(dev);
 	val = !dev->offline;
 	device_unlock(dev);
-	return sprintf(buf, "%u\n", val);
+	return sysfs_emit(buf, "%u\n", val);
 }
 
 static ssize_t online_store(struct device *dev, struct device_attribute *attr,
@@ -1709,6 +1725,7 @@
 	device_pm_init(dev);
 	set_dev_node(dev, -1);
 #ifdef CONFIG_GENERIC_MSI_IRQ
+	raw_spin_lock_init(&dev->msi_lock);
 	INIT_LIST_HEAD(&dev->msi_list);
 #endif
 	INIT_LIST_HEAD(&dev->links.consumers);
@@ -2604,6 +2621,26 @@
 }
 EXPORT_SYMBOL_GPL(device_find_child_by_name);
 
+static int match_any(struct device *dev, void *unused)
+{
+	return 1;
+}
+
+/**
+ * device_find_any_child - device iterator for locating a child device, if any.
+ * @parent: parent struct device
+ *
+ * This is similar to the device_find_child() function above, but it
+ * returns a reference to a child device, if any.
+ *
+ * NOTE: you will need to drop the reference with put_device() after use.
+ */
+struct device *device_find_any_child(struct device *parent)
+{
+	return device_find_child(parent, NULL, match_any);
+}
+EXPORT_SYMBOL_GPL(device_find_any_child);
+
 int __init devices_init(void)
 {
 	devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);
@@ -3170,6 +3207,126 @@
 }
 EXPORT_SYMBOL_GPL(device_move);
 
+static int device_attrs_change_owner(struct device *dev, kuid_t kuid,
+				     kgid_t kgid)
+{
+	struct kobject *kobj = &dev->kobj;
+	struct class *class = dev->class;
+	const struct device_type *type = dev->type;
+	int error;
+
+	if (class) {
+		/*
+		 * Change the device groups of the device class for @dev to
+		 * @kuid/@kgid.
+		 */
+		error = sysfs_groups_change_owner(kobj, class->dev_groups, kuid,
+						  kgid);
+		if (error)
+			return error;
+	}
+
+	if (type) {
+		/*
+		 * Change the device groups of the device type for @dev to
+		 * @kuid/@kgid.
+		 */
+		error = sysfs_groups_change_owner(kobj, type->groups, kuid,
+						  kgid);
+		if (error)
+			return error;
+	}
+
+	/* Change the device groups of @dev to @kuid/@kgid. */
+	error = sysfs_groups_change_owner(kobj, dev->groups, kuid, kgid);
+	if (error)
+		return error;
+
+	if (device_supports_offline(dev) && !dev->offline_disabled) {
+		/* Change online device attributes of @dev to @kuid/@kgid. */
+		error = sysfs_file_change_owner(kobj, dev_attr_online.attr.name,
+						kuid, kgid);
+		if (error)
+			return error;
+	}
+
+	return 0;
+}
+
+/**
+ * device_change_owner - change the owner of an existing device.
+ * @dev: device.
+ * @kuid: new owner's kuid
+ * @kgid: new owner's kgid
+ *
+ * This changes the owner of @dev and its corresponding sysfs entries to
+ * @kuid/@kgid. This function closely mirrors how @dev was added via driver
+ * core.
+ *
+ * Returns 0 on success or error code on failure.
+ */
+int device_change_owner(struct device *dev, kuid_t kuid, kgid_t kgid)
+{
+	int error;
+	struct kobject *kobj = &dev->kobj;
+
+	dev = get_device(dev);
+	if (!dev)
+		return -EINVAL;
+
+	/*
+	 * Change the kobject and the default attributes and groups of the
+	 * ktype associated with it to @kuid/@kgid.
+	 */
+	error = sysfs_change_owner(kobj, kuid, kgid);
+	if (error)
+		goto out;
+
+	/*
+	 * Change the uevent file for @dev to the new owner. The uevent file
+	 * was created in a separate step when @dev got added and we mirror
+	 * that step here.
+	 */
+	error = sysfs_file_change_owner(kobj, dev_attr_uevent.attr.name, kuid,
+					kgid);
+	if (error)
+		goto out;
+
+	/*
+	 * Change the device groups, the device groups associated with the
+	 * device class, and the groups associated with the device type of @dev
+	 * to @kuid/@kgid.
+	 */
+	error = device_attrs_change_owner(dev, kuid, kgid);
+	if (error)
+		goto out;
+
+	error = dpm_sysfs_change_owner(dev, kuid, kgid);
+	if (error)
+		goto out;
+
+#ifdef CONFIG_BLOCK
+	if (sysfs_deprecated && dev->class == &block_class)
+		goto out;
+#endif
+
+	/*
+	 * Change the owner of the symlink located in the class directory of
+	 * the device class associated with @dev which points to the actual
+	 * directory entry for @dev to @kuid/@kgid. This ensures that the
+	 * symlink shows the same permissions as its target.
+	 */
+	error = sysfs_link_change_owner(&dev->class->p->subsys.kobj, &dev->kobj,
+					dev_name(dev), kuid, kgid);
+	if (error)
+		goto out;
+
+out:
+	put_device(dev);
+	return error;
+}
+EXPORT_SYMBOL_GPL(device_change_owner);
+
 /**
  * device_shutdown - call ->shutdown() on each device to shutdown.
  */
@@ -3385,6 +3542,50 @@
 
 #endif
 
+/**
+ * dev_err_probe - probe error check and log helper
+ * @dev: the pointer to the struct device
+ * @err: error value to test
+ * @fmt: printf-style format string
+ * @...: arguments as specified in the format string
+ *
+ * This helper implements common pattern present in probe functions for error
+ * checking: print debug or error message depending if the error value is
+ * -EPROBE_DEFER and propagate error upwards.
+ * It replaces code sequence::
+ * 	if (err != -EPROBE_DEFER)
+ * 		dev_err(dev, ...);
+ * 	else
+ * 		dev_dbg(dev, ...);
+ * 	return err;
+ *
+ * with::
+ *
+ * 	return dev_err_probe(dev, err, ...);
+ *
+ * Returns @err.
+ *
+ */
+int dev_err_probe(const struct device *dev, int err, const char *fmt, ...)
+{
+	struct va_format vaf;
+	va_list args;
+
+	va_start(args, fmt);
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	if (err != -EPROBE_DEFER)
+		dev_err(dev, "error %pe: %pV", ERR_PTR(err), &vaf);
+	else
+		dev_dbg(dev, "error %pe: %pV", ERR_PTR(err), &vaf);
+
+	va_end(args);
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(dev_err_probe);
+
 static inline bool fwnode_is_primary(struct fwnode_handle *fwnode)
 {
 	return fwnode && !IS_ERR(fwnode->secondary);
@@ -3400,9 +3601,10 @@
  */
 void set_primary_fwnode(struct device *dev, struct fwnode_handle *fwnode)
 {
-	if (fwnode) {
-		struct fwnode_handle *fn = dev->fwnode;
+	struct device *parent = dev->parent;
+	struct fwnode_handle *fn = dev->fwnode;
 
+	if (fwnode) {
 		if (fwnode_is_primary(fn))
 			fn = fn->secondary;
 
@@ -3412,8 +3614,13 @@
 		}
 		dev->fwnode = fwnode;
 	} else {
-		dev->fwnode = fwnode_is_primary(dev->fwnode) ?
-			dev->fwnode->secondary : NULL;
+		if (fwnode_is_primary(fn)) {
+			dev->fwnode = fn->secondary;
+			if (!(parent && fn == parent->fwnode))
+				fn->secondary = NULL;
+		} else {
+			dev->fwnode = NULL;
+		}
 	}
 }
 EXPORT_SYMBOL_GPL(set_primary_fwnode);
@@ -3454,6 +3661,13 @@
 }
 EXPORT_SYMBOL_GPL(device_set_of_node_from_dev);
 
+void device_set_node(struct device *dev, struct fwnode_handle *fwnode)
+{
+	dev->fwnode = fwnode;
+	dev->of_node = to_of_node(fwnode);
+}
+EXPORT_SYMBOL_GPL(device_set_node);
+
 int device_match_name(struct device *dev, const void *name)
 {
 	return sysfs_streq(dev_name(dev), name);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/cpu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/cpu.c
@@ -156,7 +156,7 @@
 	 * operation should be safe. No locking required.
 	 */
 	addr = per_cpu_ptr_to_phys(per_cpu_ptr(crash_notes, cpunum));
-	rc = sprintf(buf, "%Lx\n", addr);
+	rc = sysfs_emit(buf, "%Lx\n", addr);
 	return rc;
 }
 static DEVICE_ATTR(crash_notes, 0400, show_crash_notes, NULL);
@@ -167,7 +167,7 @@
 {
 	ssize_t rc;
 
-	rc = sprintf(buf, "%zu\n", sizeof(note_buf_t));
+	rc = sysfs_emit(buf, "%zu\n", sizeof(note_buf_t));
 	return rc;
 }
 static DEVICE_ATTR(crash_notes_size, 0400, show_crash_notes_size, NULL);
@@ -231,8 +231,7 @@
 static ssize_t print_cpus_kernel_max(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
-	int n = snprintf(buf, PAGE_SIZE-2, "%d\n", NR_CPUS - 1);
-	return n;
+	return sprintf(buf, "%d\n", NR_CPUS - 1);
 }
 static DEVICE_ATTR(kernel_max, 0444, print_cpus_kernel_max, NULL);
 
@@ -272,7 +271,7 @@
 static ssize_t print_cpus_isolated(struct device *dev,
 				  struct device_attribute *attr, char *buf)
 {
-	int n = 0, len = PAGE_SIZE-2;
+	int n;
 	cpumask_var_t isolated;
 
 	if (!alloc_cpumask_var(&isolated, GFP_KERNEL))
@@ -280,7 +279,7 @@
 
 	cpumask_andnot(isolated, cpu_possible_mask,
 		       housekeeping_cpumask(HK_FLAG_DOMAIN));
-	n = scnprintf(buf, len, "%*pbl\n", cpumask_pr_args(isolated));
+	n = sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(isolated));
 
 	free_cpumask_var(isolated);
 
@@ -292,11 +291,7 @@
 static ssize_t print_cpus_nohz_full(struct device *dev,
 				  struct device_attribute *attr, char *buf)
 {
-	int n = 0, len = PAGE_SIZE-2;
-
-	n = scnprintf(buf, len, "%*pbl\n", cpumask_pr_args(tick_nohz_full_mask));
-
-	return n;
+	return sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(tick_nohz_full_mask));
 }
 static DEVICE_ATTR(nohz_full, 0444, print_cpus_nohz_full, NULL);
 #endif
@@ -328,8 +323,8 @@
 	ssize_t n;
 	u32 i;
 
-	n = sprintf(buf, "cpu:type:" CPU_FEATURE_TYPEFMT ":feature:",
-		    CPU_FEATURE_TYPEVAL);
+	n = sysfs_emit(buf, "cpu:type:" CPU_FEATURE_TYPEFMT ":feature:",
+		       CPU_FEATURE_TYPEVAL);
 
 	for (i = 0; i < MAX_CPU_FEATURES; i++)
 		if (cpu_have_feature(i)) {
@@ -496,7 +491,8 @@
 bool cpu_is_hotpluggable(unsigned cpu)
 {
 	struct device *dev = get_cpu_device(cpu);
-	return dev && container_of(dev, struct cpu, dev)->hotpluggable;
+	return dev && container_of(dev, struct cpu, dev)->hotpluggable
+		&& tick_nohz_cpu_hotpluggable(cpu);
 }
 EXPORT_SYMBOL_GPL(cpu_is_hotpluggable);
 
@@ -521,50 +517,79 @@
 ssize_t __weak cpu_show_meltdown(struct device *dev,
 				 struct device_attribute *attr, char *buf)
 {
-	return sprintf(buf, "Not affected\n");
+	return sysfs_emit(buf, "Not affected\n");
 }
 
 ssize_t __weak cpu_show_spectre_v1(struct device *dev,
 				   struct device_attribute *attr, char *buf)
 {
-	return sprintf(buf, "Not affected\n");
+	return sysfs_emit(buf, "Not affected\n");
 }
 
 ssize_t __weak cpu_show_spectre_v2(struct device *dev,
 				   struct device_attribute *attr, char *buf)
 {
-	return sprintf(buf, "Not affected\n");
+	return sysfs_emit(buf, "Not affected\n");
 }
 
 ssize_t __weak cpu_show_spec_store_bypass(struct device *dev,
 					  struct device_attribute *attr, char *buf)
 {
-	return sprintf(buf, "Not affected\n");
+	return sysfs_emit(buf, "Not affected\n");
 }
 
 ssize_t __weak cpu_show_l1tf(struct device *dev,
 			     struct device_attribute *attr, char *buf)
 {
-	return sprintf(buf, "Not affected\n");
+	return sysfs_emit(buf, "Not affected\n");
 }
 
 ssize_t __weak cpu_show_mds(struct device *dev,
 			    struct device_attribute *attr, char *buf)
 {
-	return sprintf(buf, "Not affected\n");
+	return sysfs_emit(buf, "Not affected\n");
 }
 
 ssize_t __weak cpu_show_tsx_async_abort(struct device *dev,
 					struct device_attribute *attr,
 					char *buf)
 {
-	return sprintf(buf, "Not affected\n");
+	return sysfs_emit(buf, "Not affected\n");
 }
 
 ssize_t __weak cpu_show_itlb_multihit(struct device *dev,
 			    struct device_attribute *attr, char *buf)
 {
-	return sprintf(buf, "Not affected\n");
+	return sysfs_emit(buf, "Not affected\n");
+}
+
+ssize_t __weak cpu_show_srbds(struct device *dev,
+			      struct device_attribute *attr, char *buf)
+{
+	return sysfs_emit(buf, "Not affected\n");
+}
+
+ssize_t __weak cpu_show_mmio_stale_data(struct device *dev,
+					struct device_attribute *attr, char *buf)
+{
+	return sysfs_emit(buf, "Not affected\n");
+}
+
+ssize_t __weak cpu_show_retbleed(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	return sysfs_emit(buf, "Not affected\n");
+}
+
+ssize_t __weak cpu_show_gds(struct device *dev,
+			    struct device_attribute *attr, char *buf)
+{
+	return sysfs_emit(buf, "Not affected\n");
+}
+
+ssize_t __weak cpu_show_vmscape(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	return sysfs_emit(buf, "Not affected\n");
 }
 
 static DEVICE_ATTR(meltdown, 0444, cpu_show_meltdown, NULL);
@@ -575,6 +600,11 @@
 static DEVICE_ATTR(mds, 0444, cpu_show_mds, NULL);
 static DEVICE_ATTR(tsx_async_abort, 0444, cpu_show_tsx_async_abort, NULL);
 static DEVICE_ATTR(itlb_multihit, 0444, cpu_show_itlb_multihit, NULL);
+static DEVICE_ATTR(srbds, 0444, cpu_show_srbds, NULL);
+static DEVICE_ATTR(mmio_stale_data, 0444, cpu_show_mmio_stale_data, NULL);
+static DEVICE_ATTR(retbleed, 0444, cpu_show_retbleed, NULL);
+static DEVICE_ATTR(gather_data_sampling, 0444, cpu_show_gds, NULL);
+static DEVICE_ATTR(vmscape, 0444, cpu_show_vmscape, NULL);
 
 static struct attribute *cpu_root_vulnerabilities_attrs[] = {
 	&dev_attr_meltdown.attr,
@@ -585,6 +615,11 @@
 	&dev_attr_mds.attr,
 	&dev_attr_tsx_async_abort.attr,
 	&dev_attr_itlb_multihit.attr,
+	&dev_attr_srbds.attr,
+	&dev_attr_mmio_stale_data.attr,
+	&dev_attr_retbleed.attr,
+	&dev_attr_gather_data_sampling.attr,
+	&dev_attr_vmscape.attr,
 	NULL
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/dd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/dd.c
@@ -300,14 +300,16 @@
 
 static void deferred_probe_timeout_work_func(struct work_struct *work)
 {
-	struct device_private *private, *p;
+	struct device_private *p;
 
 	deferred_probe_timeout = 0;
 	driver_deferred_probe_trigger();
 	flush_work(&deferred_probe_work);
 
-	list_for_each_entry_safe(private, p, &deferred_probe_pending_list, deferred_probe)
-		dev_info(private->device, "deferred probe pending");
+	mutex_lock(&deferred_probe_mutex);
+	list_for_each_entry(p, &deferred_probe_pending_list, deferred_probe)
+		dev_info(p->device, "deferred probe pending\n");
+	mutex_unlock(&deferred_probe_mutex);
 }
 static DECLARE_DELAYED_WORK(deferred_probe_timeout_work, deferred_probe_timeout_work_func);
 
@@ -516,7 +518,11 @@
 	atomic_inc(&probe_count);
 	pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
 		 drv->bus->name, __func__, drv->name, dev_name(dev));
-	WARN_ON(!list_empty(&dev->devres_head));
+	if (!list_empty(&dev->devres_head)) {
+		dev_crit(dev, "Resources present before probing\n");
+		ret = -EBUSY;
+		goto done;
+	}
 
 re_probe:
 	dev->driver = drv;
@@ -636,7 +642,7 @@
 	ret = 0;
 done:
 	atomic_dec(&probe_count);
-	wake_up(&probe_waitqueue);
+	wake_up_all(&probe_waitqueue);
 	return ret;
 }
 
@@ -741,7 +747,7 @@
 			"Too long list of driver names for 'driver_async_probe'!\n");
 
 	strlcpy(async_probe_drv_names, buf, ASYNC_DRV_NAMES_MAX_LEN);
-	return 0;
+	return 1;
 }
 __setup("driver_async_probe=", save_async_options);
 
@@ -812,6 +818,11 @@
 	} else if (ret == -EPROBE_DEFER) {
 		dev_dbg(dev, "Device match requests probe deferral\n");
 		driver_deferred_probe_add(dev);
+		/*
+		 * Device can't match with a driver right now, so don't attempt
+		 * to match or bind with other drivers on the bus.
+		 */
+		return ret;
 	} else if (ret < 0) {
 		dev_dbg(dev, "Bus failed to match device: %d", ret);
 		return ret;
@@ -867,9 +878,12 @@
 static int __device_attach(struct device *dev, bool allow_async)
 {
 	int ret = 0;
+	bool async = false;
 
 	device_lock(dev);
-	if (dev->driver) {
+	if (dev->p->dead) {
+		goto out_unlock;
+	} else if (dev->driver) {
 		if (device_is_bound(dev)) {
 			ret = 1;
 			goto out_unlock;
@@ -903,7 +917,7 @@
 			 */
 			dev_dbg(dev, "scheduling asynchronous probe\n");
 			get_device(dev);
-			async_schedule_dev(__device_attach_async_helper, dev);
+			async = true;
 		} else {
 			pm_request_idle(dev);
 		}
@@ -913,6 +927,8 @@
 	}
 out_unlock:
 	device_unlock(dev);
+	if (async)
+		async_schedule_dev(__device_attach_async_helper, dev);
 	return ret;
 }
 
@@ -1026,6 +1042,7 @@
 static int __driver_attach(struct device *dev, void *data)
 {
 	struct device_driver *drv = data;
+	bool async = false;
 	int ret;
 
 	/*
@@ -1045,9 +1062,18 @@
 	} else if (ret == -EPROBE_DEFER) {
 		dev_dbg(dev, "Device match requests probe deferral\n");
 		driver_deferred_probe_add(dev);
+		/*
+		 * Driver could not match with device, but may match with
+		 * another device on the bus.
+		 */
+		return 0;
 	} else if (ret < 0) {
-		dev_dbg(dev, "Bus failed to match device: %d", ret);
-		return ret;
+		dev_dbg(dev, "Bus failed to match device: %d\n", ret);
+		/*
+		 * Driver could not match with device, but may match with
+		 * another device on the bus.
+		 */
+		return 0;
 	} /* ret > 0 means positive match */
 
 	if (driver_allows_async_probing(drv)) {
@@ -1063,9 +1089,11 @@
 		if (!dev->driver) {
 			get_device(dev);
 			dev->p->async_driver = drv;
-			async_schedule_dev(__driver_attach_async_helper, dev);
+			async = true;
 		}
 		device_unlock(dev);
+		if (async)
+			async_schedule_dev(__driver_attach_async_helper, dev);
 		return 0;
 	}
 
@@ -1099,6 +1127,8 @@
 
 	drv = dev->driver;
 	if (drv) {
+		pm_runtime_get_sync(dev);
+
 		while (device_links_busy(dev)) {
 			__device_driver_unlock(dev, parent);
 
@@ -1110,13 +1140,12 @@
 			 * have released the driver successfully while this one
 			 * was waiting, so check for that.
 			 */
-			if (dev->driver != drv)
+			if (dev->driver != drv) {
+				pm_runtime_put(dev);
 				return;
+			}
 		}
 
-		pm_runtime_get_sync(dev);
-		pm_runtime_clean_up_links(dev);
-
 		driver_sysfs_remove(dev);
 
 		if (dev->bus)
@@ -1132,8 +1161,13 @@
 			dev->bus->remove(dev);
 		else if (drv->remove)
 			drv->remove(dev);
-
-		device_links_driver_cleanup(dev);
+		/*
+		 * A concurrent invocation of the same function might
+		 * have released the driver successfully while this one
+		 * was waiting, so check for that.
+		 */
+		if (dev->driver != drv)
+			return;
 
 		devres_release_all(dev);
 		arch_teardown_dma_ops(dev);
@@ -1144,6 +1178,8 @@
 		pm_runtime_reinit(dev);
 		dev_pm_set_driver_flags(dev, 0);
 
+		device_links_driver_cleanup(dev);
+
 		klist_remove(&dev->p->knode_driver);
 		device_pm_check_callbacks(dev);
 		if (dev->bus)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/devcoredump.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/devcoredump.c
@@ -29,6 +29,47 @@
 	struct device devcd_dev;
 	void *data;
 	size_t datalen;
+	/*
+	 * Here, mutex is required to serialize the calls to del_wk work between
+	 * user/kernel space which happens when devcd is added with device_add()
+	 * and that sends uevent to user space. User space reads the uevents,
+	 * and calls to devcd_data_write() which try to modify the work which is
+	 * not even initialized/queued from devcoredump.
+	 *
+	 *
+	 *
+	 *        cpu0(X)                                 cpu1(Y)
+	 *
+	 *        dev_coredump() uevent sent to user space
+	 *        device_add()  ======================> user space process Y reads the
+	 *                                              uevents writes to devcd fd
+	 *                                              which results into writes to
+	 *
+	 *                                             devcd_data_write()
+	 *                                               mod_delayed_work()
+	 *                                                 try_to_grab_pending()
+	 *                                                   del_timer()
+	 *                                                     debug_assert_init()
+	 *       INIT_DELAYED_WORK()
+	 *       schedule_delayed_work()
+	 *
+	 *
+	 * Also, mutex alone would not be enough to avoid scheduling of
+	 * del_wk work after it get flush from a call to devcd_free()
+	 * mentioned as below.
+	 *
+	 *	disabled_store()
+	 *        devcd_free()
+	 *          mutex_lock()             devcd_data_write()
+	 *          flush_delayed_work()
+	 *          mutex_unlock()
+	 *                                   mutex_lock()
+	 *                                   mod_delayed_work()
+	 *                                   mutex_unlock()
+	 * So, delete_work flag is required.
+	 */
+	struct mutex mutex;
+	bool delete_work;
 	struct module *owner;
 	ssize_t (*read)(char *buffer, loff_t offset, size_t count,
 			void *data, size_t datalen);
@@ -88,7 +129,12 @@
 	struct device *dev = kobj_to_dev(kobj);
 	struct devcd_entry *devcd = dev_to_devcd(dev);
 
-	mod_delayed_work(system_wq, &devcd->del_wk, 0);
+	mutex_lock(&devcd->mutex);
+	if (!devcd->delete_work) {
+		devcd->delete_work = true;
+		mod_delayed_work(system_wq, &devcd->del_wk, 0);
+	}
+	mutex_unlock(&devcd->mutex);
 
 	return count;
 }
@@ -116,7 +162,12 @@
 {
 	struct devcd_entry *devcd = dev_to_devcd(dev);
 
+	mutex_lock(&devcd->mutex);
+	if (!devcd->delete_work)
+		devcd->delete_work = true;
+
 	flush_delayed_work(&devcd->del_wk);
+	mutex_unlock(&devcd->mutex);
 	return 0;
 }
 
@@ -126,6 +177,30 @@
 	return sprintf(buf, "%d\n", devcd_disabled);
 }
 
+/*
+ *
+ *	disabled_store()                                	worker()
+ *	 class_for_each_device(&devcd_class,
+ *		NULL, NULL, devcd_free)
+ *         ...
+ *         ...
+ *	   while ((dev = class_dev_iter_next(&iter))
+ *                                                             devcd_del()
+ *                                                               device_del()
+ *                                                                 put_device() <- last reference
+ *             error = fn(dev, data)                           devcd_dev_release()
+ *             devcd_free(dev, data)                           kfree(devcd)
+ *             mutex_lock(&devcd->mutex);
+ *
+ *
+ * In the above diagram, It looks like disabled_store() would be racing with parallely
+ * running devcd_del() and result in memory abort while acquiring devcd->mutex which
+ * is called after kfree of devcd memory  after dropping its last reference with
+ * put_device(). However, this will not happens as fn(dev, data) runs
+ * with its own reference to device via klist_node so it is not its last reference.
+ * so, above situation would not occur.
+ */
+
 static ssize_t disabled_store(struct class *class, struct class_attribute *attr,
 			      const char *buf, size_t count)
 {
@@ -282,13 +357,17 @@
 	devcd->read = read;
 	devcd->free = free;
 	devcd->failing_dev = get_device(dev);
+	devcd->delete_work = false;
 
+	mutex_init(&devcd->mutex);
 	device_initialize(&devcd->devcd_dev);
 
 	dev_set_name(&devcd->devcd_dev, "devcd%d",
 		     atomic_inc_return(&devcd_count));
 	devcd->devcd_dev.class = &devcd_class;
 
+	mutex_lock(&devcd->mutex);
+	dev_set_uevent_suppress(&devcd->devcd_dev, true);
 	if (device_add(&devcd->devcd_dev))
 		goto put_device;
 
@@ -300,12 +379,15 @@
 			      "devcoredump"))
 		/* nothing - symlink will be missing */;
 
+	dev_set_uevent_suppress(&devcd->devcd_dev, false);
+	kobject_uevent(&devcd->devcd_dev.kobj, KOBJ_ADD);
 	INIT_DELAYED_WORK(&devcd->del_wk, devcd_del);
 	schedule_delayed_work(&devcd->del_wk, DEVCD_TIMEOUT);
-
+	mutex_unlock(&devcd->mutex);
 	return;
  put_device:
 	put_device(&devcd->devcd_dev);
+	mutex_unlock(&devcd->mutex);
  put_module:
 	module_put(owner);
  free:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/devres.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/devres.c
@@ -561,6 +561,7 @@
 	grp->id = grp;
 	if (id)
 		grp->id = id;
+	grp->color = 0;
 
 	spin_lock_irqsave(&dev->devres_lock, flags);
 	add_dr(dev, &grp->node[0]);
@@ -1111,7 +1112,11 @@
  */
 void devm_free_percpu(struct device *dev, void __percpu *pdata)
 {
-	WARN_ON(devres_destroy(dev, devm_percpu_release, devm_percpu_match,
-			       (void *)pdata));
+	/*
+	 * Use devres_release() to prevent memory leakage as
+	 * devm_free_pages() does.
+	 */
+	WARN_ON(devres_release(dev, devm_percpu_release, devm_percpu_match,
+			       (__force void *)pdata));
 }
 EXPORT_SYMBOL_GPL(devm_free_percpu);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/devtmpfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/devtmpfs.c
@@ -25,6 +25,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/kthread.h>
+#include <linux/fs_context.h>
 #include <uapi/linux/mount.h>
 #include "base.h"
 
@@ -62,8 +63,15 @@
 		      const char *dev_name, void *data)
 {
 	struct super_block *s = mnt->mnt_sb;
+	int err;
+
 	atomic_inc(&s->s_active);
 	down_write(&s->s_umount);
+	err = reconfigure_single(s, flags, data);
+	if (err < 0) {
+		deactivate_locked_super(s);
+		return ERR_PTR(err);
+	}
 	return dget(s->s_root);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/driver.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/driver.c
@@ -30,6 +30,75 @@
 }
 
 /**
+ * driver_set_override() - Helper to set or clear driver override.
+ * @dev: Device to change
+ * @override: Address of string to change (e.g. &device->driver_override);
+ *            The contents will be freed and hold newly allocated override.
+ * @s: NUL-terminated string, new driver name to force a match, pass empty
+ *     string to clear it ("" or "\n", where the latter is only for sysfs
+ *     interface).
+ * @len: length of @s
+ *
+ * Helper to set or clear driver override in a device, intended for the cases
+ * when the driver_override field is allocated by driver/bus code.
+ *
+ * Returns: 0 on success or a negative error code on failure.
+ */
+int driver_set_override(struct device *dev, const char **override,
+			const char *s, size_t len)
+{
+	const char *new, *old;
+	char *cp;
+
+	if (!override || !s)
+		return -EINVAL;
+
+	/*
+	 * The stored value will be used in sysfs show callback (sysfs_emit()),
+	 * which has a length limit of PAGE_SIZE and adds a trailing newline.
+	 * Thus we can store one character less to avoid truncation during sysfs
+	 * show.
+	 */
+	if (len >= (PAGE_SIZE - 1))
+		return -EINVAL;
+
+	if (!len) {
+		/* Empty string passed - clear override */
+		device_lock(dev);
+		old = *override;
+		*override = NULL;
+		device_unlock(dev);
+		kfree(old);
+
+		return 0;
+	}
+
+	cp = strnchr(s, len, '\n');
+	if (cp)
+		len = cp - s;
+
+	new = kstrndup(s, len, GFP_KERNEL);
+	if (!new)
+		return -ENOMEM;
+
+	device_lock(dev);
+	old = *override;
+	if (cp != s) {
+		*override = new;
+	} else {
+		/* "\n" passed - clear override */
+		kfree(new);
+		*override = NULL;
+	}
+	device_unlock(dev);
+
+	kfree(old);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(driver_set_override);
+
+/**
  * driver_for_each_device - Iterator for devices bound to a driver.
  * @drv: Driver we're iterating.
  * @start: Device to begin with
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/firmware_loader/builtin/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/firmware_loader/builtin/Makefile
@@ -8,7 +8,8 @@
 obj-y  := $(addsuffix .gen.o, $(subst $(quote),,$(CONFIG_EXTRA_FIRMWARE)))
 
 FWNAME    = $(patsubst $(obj)/%.gen.S,%,$@)
-FWSTR     = $(subst /,_,$(subst .,_,$(subst -,_,$(FWNAME))))
+comma     := ,
+FWSTR     = $(subst $(comma),_,$(subst /,_,$(subst .,_,$(subst -,_,$(FWNAME)))))
 ASM_WORD  = $(if $(CONFIG_64BIT),.quad,.long)
 ASM_ALIGN = $(if $(CONFIG_64BIT),3,2)
 PROGBITS  = $(if $(CONFIG_ARM),%,@)progbits
@@ -16,7 +17,7 @@
 filechk_fwbin = \
 	echo "/* Generated by $(src)/Makefile */"		;\
 	echo "    .section .rodata"				;\
-	echo "    .p2align $(ASM_ALIGN)"			;\
+	echo "    .p2align 4"					;\
 	echo "_fw_$(FWSTR)_bin:"				;\
 	echo "    .incbin \"$(fwdir)/$(FWNAME)\""		;\
 	echo "_fw_end:"						;\
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/firmware_loader/fallback.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/firmware_loader/fallback.c
@@ -86,12 +86,11 @@
 {
 	/*
 	 * There is a small window in which user can write to 'loading'
-	 * between loading done and disappearance of 'loading'
+	 * between loading done/aborted and disappearance of 'loading'
 	 */
-	if (fw_sysfs_done(fw_priv))
+	if (fw_state_is_aborted(fw_priv) || fw_sysfs_done(fw_priv))
 		return;
 
-	list_del_init(&fw_priv->pending_list);
 	fw_state_aborted(fw_priv);
 }
 
@@ -216,7 +215,7 @@
 		loading = fw_sysfs_loading(fw_sysfs->fw_priv);
 	mutex_unlock(&fw_lock);
 
-	return sprintf(buf, "%d\n", loading);
+	return sysfs_emit(buf, "%d\n", loading);
 }
 
 /**
@@ -277,7 +276,6 @@
 			 * Same logic as fw_load_abort, only the DONE bit
 			 * is ignored and we set ABORT only on failure.
 			 */
-			list_del_init(&fw_priv->pending_list);
 			if (rc) {
 				fw_state_aborted(fw_priv);
 				written = rc;
@@ -512,6 +510,11 @@
 	}
 
 	mutex_lock(&fw_lock);
+	if (fw_state_is_aborted(fw_priv)) {
+		mutex_unlock(&fw_lock);
+		retval = -EINTR;
+		goto out;
+	}
 	list_add(&fw_priv->pending_list, &pending_fw_head);
 	mutex_unlock(&fw_lock);
 
@@ -525,7 +528,7 @@
 	}
 
 	retval = fw_sysfs_wait_timeout(fw_priv, timeout);
-	if (retval < 0) {
+	if (retval < 0 && retval != -ENOENT) {
 		mutex_lock(&fw_lock);
 		fw_load_abort(fw_sysfs);
 		mutex_unlock(&fw_lock);
@@ -534,11 +537,10 @@
 	if (fw_state_is_aborted(fw_priv)) {
 		if (retval == -ERESTARTSYS)
 			retval = -EINTR;
-		else
-			retval = -EAGAIN;
 	} else if (fw_priv->is_paged_buf && !fw_priv->data)
 		retval = -ENOMEM;
 
+out:
 	device_del(f_dev);
 err_put_dev:
 	put_device(f_dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/firmware_loader/firmware.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/firmware_loader/firmware.h
@@ -108,8 +108,16 @@
 
 	WRITE_ONCE(fw_st->status, status);
 
-	if (status == FW_STATUS_DONE || status == FW_STATUS_ABORTED)
+	if (status == FW_STATUS_DONE || status == FW_STATUS_ABORTED) {
+#ifdef CONFIG_FW_LOADER_USER_HELPER
+		/*
+		 * Doing this here ensures that the fw_priv is deleted from
+		 * the pending list in all abort/done paths.
+		 */
+		list_del_init(&fw_priv->pending_list);
+#endif
 		complete_all(&fw_st->completion);
+	}
 }
 
 static inline void fw_state_aborted(struct fw_priv *fw_priv)
@@ -139,10 +147,12 @@
 void fw_free_paged_buf(struct fw_priv *fw_priv);
 int fw_grow_paged_buf(struct fw_priv *fw_priv, int pages_needed);
 int fw_map_paged_buf(struct fw_priv *fw_priv);
+bool fw_is_paged_buf(struct fw_priv *fw_priv);
 #else
 static inline void fw_free_paged_buf(struct fw_priv *fw_priv) {}
 static inline int fw_grow_paged_buf(struct fw_priv *fw_priv, int pages_needed) { return -ENXIO; }
 static inline int fw_map_paged_buf(struct fw_priv *fw_priv) { return -ENXIO; }
+static inline bool fw_is_paged_buf(struct fw_priv *fw_priv) { return false; }
 #endif
 
 #endif /* __FIRMWARE_LOADER_H */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/firmware_loader/main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/firmware_loader/main.c
@@ -98,12 +98,15 @@
 extern struct builtin_fw __start_builtin_fw[];
 extern struct builtin_fw __end_builtin_fw[];
 
-static void fw_copy_to_prealloc_buf(struct firmware *fw,
+static bool fw_copy_to_prealloc_buf(struct firmware *fw,
 				    void *buf, size_t size)
 {
-	if (!buf || size < fw->size)
-		return;
+	if (!buf)
+		return true;
+	if (size < fw->size)
+		return false;
 	memcpy(buf, fw->data, fw->size);
+	return true;
 }
 
 static bool fw_get_builtin_firmware(struct firmware *fw, const char *name,
@@ -115,9 +118,7 @@
 		if (strcmp(name, b_fw->name) == 0) {
 			fw->size = b_fw->size;
 			fw->data = b_fw->data;
-			fw_copy_to_prealloc_buf(fw, buf, size);
-
-			return true;
+			return fw_copy_to_prealloc_buf(fw, buf, size);
 		}
 	}
 
@@ -252,9 +253,11 @@
 	list_del(&fw_priv->list);
 	spin_unlock(&fwc->lock);
 
-	fw_free_paged_buf(fw_priv); /* free leftover pages */
-	if (!fw_priv->allocated_size)
+	if (fw_is_paged_buf(fw_priv))
+		fw_free_paged_buf(fw_priv);
+	else if (!fw_priv->allocated_size)
 		vfree(fw_priv->data);
+
 	kfree_const(fw_priv->fw_name);
 	kfree(fw_priv);
 }
@@ -268,6 +271,11 @@
 }
 
 #ifdef CONFIG_FW_LOADER_PAGED_BUF
+bool fw_is_paged_buf(struct fw_priv *fw_priv)
+{
+	return fw_priv->is_paged_buf;
+}
+
 void fw_free_paged_buf(struct fw_priv *fw_priv)
 {
 	int i;
@@ -275,6 +283,8 @@
 	if (!fw_priv->pages)
 		return;
 
+	vunmap(fw_priv->data);
+
 	for (i = 0; i < fw_priv->nr_pages; i++)
 		__free_page(fw_priv->pages[i]);
 	kvfree(fw_priv->pages);
@@ -328,10 +338,6 @@
 	if (!fw_priv->data)
 		return -ENOMEM;
 
-	/* page table is no longer needed after mapping, let's free */
-	kvfree(fw_priv->pages);
-	fw_priv->pages = NULL;
-
 	return 0;
 }
 #endif
@@ -742,8 +748,30 @@
 		return;
 
 	fw_priv = fw->priv;
+	mutex_lock(&fw_lock);
 	if (!fw_state_is_aborted(fw_priv))
 		fw_state_aborted(fw_priv);
+	mutex_unlock(&fw_lock);
+}
+
+/*
+ * Reject firmware file names with ".." path components.
+ * There are drivers that construct firmware file names from device-supplied
+ * strings, and we don't want some device to be able to tell us "I would like to
+ * be sent my firmware from ../../../etc/shadow, please".
+ *
+ * Search for ".." surrounded by either '/' or start/end of string.
+ *
+ * This intentionally only looks at the firmware name, not at the firmware base
+ * directory or at symlink contents.
+ */
+static bool name_contains_dotdot(const char *name)
+{
+	size_t name_len = strlen(name);
+
+	return strcmp(name, "..") == 0 || strncmp(name, "../", 3) == 0 ||
+	       strstr(name, "/../") != NULL ||
+	       (name_len >= 3 && strcmp(name+name_len-3, "/..") == 0);
 }
 
 /* called from request_firmware() and request_firmware_work_func() */
@@ -753,6 +781,8 @@
 		  enum fw_opt opt_flags)
 {
 	struct firmware *fw = NULL;
+	struct cred *kern_cred = NULL;
+	const struct cred *old_cred;
 	int ret;
 
 	if (!firmware_p)
@@ -763,11 +793,31 @@
 		goto out;
 	}
 
+	if (name_contains_dotdot(name)) {
+		dev_warn(device,
+			 "Firmware load for '%s' refused, path contains '..' component\n",
+			 name);
+		ret = -EINVAL;
+		goto out;
+	}
+
 	ret = _request_firmware_prepare(&fw, name, device, buf, size,
 					opt_flags);
 	if (ret <= 0) /* error or already assigned */
 		goto out;
 
+	/*
+	 * We are about to try to access the firmware file. Because we may have been
+	 * called by a driver when serving an unrelated request from userland, we use
+	 * the kernel credentials to read the file.
+	 */
+	kern_cred = prepare_kernel_cred(NULL);
+	if (!kern_cred) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	old_cred = override_creds(kern_cred);
+
 	ret = fw_get_filesystem_firmware(device, fw->priv, "", NULL);
 #ifdef CONFIG_FW_LOADER_COMPRESS
 	if (ret == -ENOENT)
@@ -784,6 +834,9 @@
 	} else
 		ret = assign_fw(fw, device, opt_flags);
 
+	revert_creds(old_cred);
+	put_cred(kern_cred);
+
  out:
 	if (ret < 0) {
 		fw_abort_batch_reqs(fw);
@@ -809,6 +862,8 @@
  *      @name will be used as $FIRMWARE in the uevent environment and
  *      should be distinctive enough not to be confused with any other
  *      firmware image for this or any other device.
+ *	It must not contain any ".." path components - "foo/bar..bin" is
+ *	allowed, but "foo/../bar.bin" is not.
  *
  *	Caller must hold the reference count of @device.
  *
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/memory.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/memory.c
@@ -110,34 +110,17 @@
 	unsigned long phys_index;
 
 	phys_index = mem->start_section_nr / sections_per_block;
-	return sprintf(buf, "%08lx\n", phys_index);
+	return sysfs_emit(buf, "%08lx\n", phys_index);
 }
 
 /*
- * Show whether the memory block is likely to be offlineable (or is already
- * offline). Once offline, the memory block could be removed. The return
- * value does, however, not indicate that there is a way to remove the
- * memory block.
+ * Legacy interface that we cannot remove. Always indicate "removable"
+ * with CONFIG_MEMORY_HOTREMOVE - bad heuristic.
  */
 static ssize_t removable_show(struct device *dev, struct device_attribute *attr,
 			      char *buf)
 {
-	struct memory_block *mem = to_memory_block(dev);
-	unsigned long pfn;
-	int ret = 1, i;
-
-	if (mem->state != MEM_ONLINE)
-		goto out;
-
-	for (i = 0; i < sections_per_block; i++) {
-		if (!present_section_nr(mem->start_section_nr + i))
-			continue;
-		pfn = section_nr_to_pfn(mem->start_section_nr + i);
-		ret &= is_mem_section_removable(pfn, PAGES_PER_SECTION);
-	}
-
-out:
-	return sprintf(buf, "%d\n", ret);
+	return sysfs_emit(buf, "%d\n", (int)IS_ENABLED(CONFIG_MEMORY_HOTREMOVE));
 }
 
 /*
@@ -155,17 +138,17 @@
 	 */
 	switch (mem->state) {
 	case MEM_ONLINE:
-		len = sprintf(buf, "online\n");
+		len = sysfs_emit(buf, "online\n");
 		break;
 	case MEM_OFFLINE:
-		len = sprintf(buf, "offline\n");
+		len = sysfs_emit(buf, "offline\n");
 		break;
 	case MEM_GOING_OFFLINE:
-		len = sprintf(buf, "going-offline\n");
+		len = sysfs_emit(buf, "going-offline\n");
 		break;
 	default:
-		len = sprintf(buf, "ERROR-UNKNOWN-%ld\n",
-				mem->state);
+		len = sysfs_emit(buf, "ERROR-UNKNOWN-%ld\n",
+				 mem->state);
 		WARN_ON(1);
 		break;
 	}
@@ -375,7 +358,7 @@
 				struct device_attribute *attr, char *buf)
 {
 	struct memory_block *mem = to_memory_block(dev);
-	return sprintf(buf, "%d\n", mem->phys_device);
+	return sysfs_emit(buf, "%d\n", mem->phys_device);
 }
 
 #ifdef CONFIG_MEMORY_HOTREMOVE
@@ -413,7 +396,7 @@
 		 */
 		if (!test_pages_in_a_zone(start_pfn, start_pfn + nr_pages,
 					  &valid_start_pfn, &valid_end_pfn))
-			return sprintf(buf, "none\n");
+			return sysfs_emit(buf, "none\n");
 		start_pfn = valid_start_pfn;
 		strcat(buf, page_zone(pfn_to_page(start_pfn))->name);
 		goto out;
@@ -446,7 +429,7 @@
 static ssize_t block_size_bytes_show(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
-	return sprintf(buf, "%lx\n", memory_block_size_bytes());
+	return sysfs_emit(buf, "%lx\n", memory_block_size_bytes());
 }
 
 static DEVICE_ATTR_RO(block_size_bytes);
@@ -459,9 +442,9 @@
 				       struct device_attribute *attr, char *buf)
 {
 	if (memhp_auto_online)
-		return sprintf(buf, "online\n");
+		return sysfs_emit(buf, "online\n");
 	else
-		return sprintf(buf, "offline\n");
+		return sysfs_emit(buf, "offline\n");
 }
 
 static ssize_t auto_online_blocks_store(struct device *dev,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/node.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/node.c
@@ -262,21 +262,20 @@
 	if (!dev)
 		return;
 
+	device_initialize(dev);
 	dev->parent = &node->dev;
 	dev->release = node_cache_release;
 	if (dev_set_name(dev, "memory_side_cache"))
-		goto free_dev;
+		goto put_device;
 
-	if (device_register(dev))
-		goto free_name;
+	if (device_add(dev))
+		goto put_device;
 
 	pm_runtime_no_callbacks(dev);
 	node->cache_dev = dev;
 	return;
-free_name:
-	kfree_const(dev->kobj.name);
-free_dev:
-	kfree(dev);
+put_device:
+	put_device(dev);
 }
 
 /**
@@ -313,25 +312,24 @@
 		return;
 
 	dev = &info->dev;
+	device_initialize(dev);
 	dev->parent = node->cache_dev;
 	dev->release = node_cacheinfo_release;
 	dev->groups = cache_groups;
 	if (dev_set_name(dev, "index%d", cache_attrs->level))
-		goto free_cache;
+		goto put_device;
 
 	info->cache_attrs = *cache_attrs;
-	if (device_register(dev)) {
+	if (device_add(dev)) {
 		dev_warn(&node->dev, "failed to add cache level:%d\n",
 			 cache_attrs->level);
-		goto free_name;
+		goto put_device;
 	}
 	pm_runtime_no_callbacks(dev);
 	list_add_tail(&info->node, &node->cache_attrs);
 	return;
-free_name:
-	kfree_const(dev->kobj.name);
-free_cache:
-	kfree(info);
+put_device:
+	put_device(dev);
 }
 
 static void node_remove_caches(struct node *node)
@@ -370,7 +368,7 @@
 	si_meminfo_node(&i, nid);
 	sreclaimable = node_page_state(pgdat, NR_SLAB_RECLAIMABLE);
 	sunreclaimable = node_page_state(pgdat, NR_SLAB_UNRECLAIMABLE);
-	n = sprintf(buf,
+	n = sysfs_emit(buf,
 		       "Node %d MemTotal:       %8lu kB\n"
 		       "Node %d MemFree:        %8lu kB\n"
 		       "Node %d MemUsed:        %8lu kB\n"
@@ -471,19 +469,19 @@
 static ssize_t node_read_numastat(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
-	return sprintf(buf,
-		       "numa_hit %lu\n"
-		       "numa_miss %lu\n"
-		       "numa_foreign %lu\n"
-		       "interleave_hit %lu\n"
-		       "local_node %lu\n"
-		       "other_node %lu\n",
-		       sum_zone_numa_state(dev->id, NUMA_HIT),
-		       sum_zone_numa_state(dev->id, NUMA_MISS),
-		       sum_zone_numa_state(dev->id, NUMA_FOREIGN),
-		       sum_zone_numa_state(dev->id, NUMA_INTERLEAVE_HIT),
-		       sum_zone_numa_state(dev->id, NUMA_LOCAL),
-		       sum_zone_numa_state(dev->id, NUMA_OTHER));
+	return sysfs_emit(buf,
+			  "numa_hit %lu\n"
+			  "numa_miss %lu\n"
+			  "numa_foreign %lu\n"
+			  "interleave_hit %lu\n"
+			  "local_node %lu\n"
+			  "other_node %lu\n",
+			  sum_zone_numa_state(dev->id, NUMA_HIT),
+			  sum_zone_numa_state(dev->id, NUMA_MISS),
+			  sum_zone_numa_state(dev->id, NUMA_FOREIGN),
+			  sum_zone_numa_state(dev->id, NUMA_INTERLEAVE_HIT),
+			  sum_zone_numa_state(dev->id, NUMA_LOCAL),
+			  sum_zone_numa_state(dev->id, NUMA_OTHER));
 }
 static DEVICE_ATTR(numastat, S_IRUGO, node_read_numastat, NULL);
 
@@ -643,6 +641,7 @@
  */
 void unregister_node(struct node *node)
 {
+	compaction_unregister_node(node);
 	hugetlb_unregister_node(node);		/* no-op, if memoryless node */
 	node_remove_accesses(node);
 	node_remove_caches(node);
@@ -758,14 +757,36 @@
 	return pfn_to_nid(pfn);
 }
 
+static int do_register_memory_block_under_node(int nid,
+					       struct memory_block *mem_blk)
+{
+	int ret;
+
+	/*
+	 * If this memory block spans multiple nodes, we only indicate
+	 * the last processed node.
+	 */
+	mem_blk->nid = nid;
+
+	ret = sysfs_create_link_nowarn(&node_devices[nid]->dev.kobj,
+				       &mem_blk->dev.kobj,
+				       kobject_name(&mem_blk->dev.kobj));
+	if (ret)
+		return ret;
+
+	return sysfs_create_link_nowarn(&mem_blk->dev.kobj,
+				&node_devices[nid]->dev.kobj,
+				kobject_name(&node_devices[nid]->dev.kobj));
+}
+
 /* register memory section under specified node if it spans that node */
-static int register_mem_sect_under_node(struct memory_block *mem_blk,
-					 void *arg)
+static int register_mem_block_under_node_early(struct memory_block *mem_blk,
+					       void *arg)
 {
 	unsigned long memory_block_pfns = memory_block_size_bytes() / PAGE_SIZE;
 	unsigned long start_pfn = section_nr_to_pfn(mem_blk->start_section_nr);
 	unsigned long end_pfn = start_pfn + memory_block_pfns - 1;
-	int ret, nid = *(int *)arg;
+	int nid = *(int *)arg;
 	unsigned long pfn;
 
 	for (pfn = start_pfn; pfn <= end_pfn; pfn++) {
@@ -782,39 +803,34 @@
 		}
 
 		/*
-		 * We need to check if page belongs to nid only for the boot
-		 * case, during hotplug we know that all pages in the memory
-		 * block belong to the same node.
-		 */
-		if (system_state == SYSTEM_BOOTING) {
-			page_nid = get_nid_for_pfn(pfn);
-			if (page_nid < 0)
-				continue;
-			if (page_nid != nid)
-				continue;
-		}
-
-		/*
-		 * If this memory block spans multiple nodes, we only indicate
-		 * the last processed node.
+		 * We need to check if page belongs to nid only at the boot
+		 * case because node's ranges can be interleaved.
 		 */
-		mem_blk->nid = nid;
-
-		ret = sysfs_create_link_nowarn(&node_devices[nid]->dev.kobj,
-					&mem_blk->dev.kobj,
-					kobject_name(&mem_blk->dev.kobj));
-		if (ret)
-			return ret;
+		page_nid = get_nid_for_pfn(pfn);
+		if (page_nid < 0)
+			continue;
+		if (page_nid != nid)
+			continue;
 
-		return sysfs_create_link_nowarn(&mem_blk->dev.kobj,
-				&node_devices[nid]->dev.kobj,
-				kobject_name(&node_devices[nid]->dev.kobj));
+		return do_register_memory_block_under_node(nid, mem_blk);
 	}
 	/* mem section does not span the specified node */
 	return 0;
 }
 
 /*
+ * During hotplug we know that all pages in the memory block belong to the same
+ * node.
+ */
+static int register_mem_block_under_node_hotplug(struct memory_block *mem_blk,
+						 void *arg)
+{
+	int nid = *(int *)arg;
+
+	return do_register_memory_block_under_node(nid, mem_blk);
+}
+
+/*
  * Unregister a memory block device under the node it spans. Memory blocks
  * with multiple nodes cannot be offlined and therefore also never be removed.
  */
@@ -829,11 +845,19 @@
 			  kobject_name(&node_devices[mem_blk->nid]->dev.kobj));
 }
 
-int link_mem_sections(int nid, unsigned long start_pfn, unsigned long end_pfn)
+int link_mem_sections(int nid, unsigned long start_pfn, unsigned long end_pfn,
+		      enum meminit_context context)
 {
+	walk_memory_blocks_func_t func;
+
+	if (context == MEMINIT_HOTPLUG)
+		func = register_mem_block_under_node_hotplug;
+	else
+		func = register_mem_block_under_node_early;
+
 	return walk_memory_blocks(PFN_PHYS(start_pfn),
 				  PFN_PHYS(end_pfn - start_pfn), (void *)&nid,
-				  register_mem_sect_under_node);
+				  func);
 }
 
 #ifdef CONFIG_HUGETLBFS
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/platform.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/platform.c
@@ -27,6 +27,7 @@
 #include <linux/limits.h>
 #include <linux/property.h>
 #include <linux/kmemleak.h>
+#include <linux/types.h>
 
 #include "base.h"
 #include "power/power.h"
@@ -48,7 +49,7 @@
 struct resource *platform_get_resource(struct platform_device *dev,
 				       unsigned int type, unsigned int num)
 {
-	int i;
+	u32 i;
 
 	for (i = 0; i < dev->num_resources; i++) {
 		struct resource *r = &dev->resource[i];
@@ -226,7 +227,7 @@
 					      unsigned int type,
 					      const char *name)
 {
-	int i;
+	u32 i;
 
 	for (i = 0; i < dev->num_resources; i++) {
 		struct resource *r = &dev->resource[i];
@@ -334,10 +335,10 @@
 {
 	if (!pdev->dev.coherent_dma_mask)
 		pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
-	if (!pdev->dma_mask)
-		pdev->dma_mask = DMA_BIT_MASK(32);
-	if (!pdev->dev.dma_mask)
-		pdev->dev.dma_mask = &pdev->dma_mask;
+	if (!pdev->dev.dma_mask) {
+		pdev->platform_dma_mask = DMA_BIT_MASK(32);
+		pdev->dev.dma_mask = &pdev->platform_dma_mask;
+	}
 };
 
 /**
@@ -473,7 +474,8 @@
  */
 int platform_device_add(struct platform_device *pdev)
 {
-	int i, ret;
+	u32 i;
+	int ret;
 
 	if (!pdev)
 		return -EINVAL;
@@ -541,7 +543,7 @@
 		pdev->id = PLATFORM_DEVID_AUTO;
 	}
 
-	while (--i >= 0) {
+	while (i--) {
 		struct resource *r = &pdev->resource[i];
 		if (r->parent)
 			release_resource(r);
@@ -562,7 +564,7 @@
  */
 void platform_device_del(struct platform_device *pdev)
 {
-	int i;
+	u32 i;
 
 	if (!IS_ERR_OR_NULL(pdev)) {
 		device_del(&pdev->dev);
@@ -632,20 +634,8 @@
 	pdev->dev.of_node_reused = pdevinfo->of_node_reused;
 
 	if (pdevinfo->dma_mask) {
-		/*
-		 * This memory isn't freed when the device is put,
-		 * I don't have a nice idea for that though.  Conceptually
-		 * dma_mask in struct device should not be a pointer.
-		 * See http://thread.gmane.org/gmane.linux.kernel.pci/9081
-		 */
-		pdev->dev.dma_mask =
-			kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL);
-		if (!pdev->dev.dma_mask)
-			goto err;
-
-		kmemleak_ignore(pdev->dev.dma_mask);
-
-		*pdev->dev.dma_mask = pdevinfo->dma_mask;
+		pdev->platform_dma_mask = pdevinfo->dma_mask;
+		pdev->dev.dma_mask = &pdev->platform_dma_mask;
 		pdev->dev.coherent_dma_mask = pdevinfo->dma_mask;
 	}
 
@@ -670,7 +660,6 @@
 	if (ret) {
 err:
 		ACPI_COMPANION_SET(&pdev->dev, NULL);
-		kfree(pdev->dev.dma_mask);
 		platform_device_put(pdev);
 		return ERR_PTR(ret);
 	}
@@ -813,6 +802,8 @@
 	/* temporary section violation during probe() */
 	drv->probe = probe;
 	retval = code = __platform_driver_register(drv, module);
+	if (retval)
+		return retval;
 
 	/*
 	 * Fixup that section violation, being paranoid about code scanning
@@ -982,31 +973,11 @@
 				     const char *buf, size_t count)
 {
 	struct platform_device *pdev = to_platform_device(dev);
-	char *driver_override, *old, *cp;
-
-	/* We need to keep extra room for a newline */
-	if (count >= (PAGE_SIZE - 1))
-		return -EINVAL;
-
-	driver_override = kstrndup(buf, count, GFP_KERNEL);
-	if (!driver_override)
-		return -ENOMEM;
-
-	cp = strchr(driver_override, '\n');
-	if (cp)
-		*cp = '\0';
-
-	device_lock(dev);
-	old = pdev->driver_override;
-	if (strlen(driver_override)) {
-		pdev->driver_override = driver_override;
-	} else {
-		kfree(driver_override);
-		pdev->driver_override = NULL;
-	}
-	device_unlock(dev);
+	int ret;
 
-	kfree(old);
+	ret = driver_set_override(dev, &pdev->driver_override, buf, count);
+	if (ret)
+		return ret;
 
 	return count;
 }
@@ -1018,7 +989,7 @@
 	ssize_t len;
 
 	device_lock(dev);
-	len = sprintf(buf, "%s\n", pdev->driver_override);
+	len = sysfs_emit(buf, "%s\n", pdev->driver_override);
 	device_unlock(dev);
 	return len;
 }
@@ -1278,6 +1249,11 @@
 };
 EXPORT_SYMBOL_GPL(platform_bus_type);
 
+static inline int __platform_match(struct device *dev, const void *drv)
+{
+	return platform_match(dev, (struct device_driver *)drv);
+}
+
 /**
  * platform_find_device_by_driver - Find a platform device with a given
  * driver.
@@ -1288,7 +1264,7 @@
 					      const struct device_driver *drv)
 {
 	return bus_find_device(&platform_bus_type, start, drv,
-			       (void *)platform_match);
+			       __platform_match);
 }
 EXPORT_SYMBOL_GPL(platform_find_device_by_driver);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/power/domain.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/power/domain.c
@@ -263,18 +263,18 @@
 	/*
 	 * Traverse all sub-domains within the domain. This can be
 	 * done without any additional locking as the link->performance_state
-	 * field is protected by the master genpd->lock, which is already taken.
+	 * field is protected by the parent genpd->lock, which is already taken.
 	 *
 	 * Also note that link->performance_state (subdomain's performance state
-	 * requirement to master domain) is different from
-	 * link->slave->performance_state (current performance state requirement
+	 * requirement to parent domain) is different from
+	 * link->child->performance_state (current performance state requirement
 	 * of the devices/sub-domains of the subdomain) and so can have a
 	 * different value.
 	 *
 	 * Note that we also take vote from powered-off sub-domains into account
 	 * as the same is done for devices right now.
 	 */
-	list_for_each_entry(link, &genpd->master_links, master_node) {
+	list_for_each_entry(link, &genpd->parent_links, parent_node) {
 		if (link->performance_state > state)
 			state = link->performance_state;
 	}
@@ -285,40 +285,40 @@
 static int _genpd_set_performance_state(struct generic_pm_domain *genpd,
 					unsigned int state, int depth)
 {
-	struct generic_pm_domain *master;
+	struct generic_pm_domain *parent;
 	struct gpd_link *link;
-	int master_state, ret;
+	int parent_state, ret;
 
 	if (state == genpd->performance_state)
 		return 0;
 
-	/* Propagate to masters of genpd */
-	list_for_each_entry(link, &genpd->slave_links, slave_node) {
-		master = link->master;
+	/* Propagate to parents of genpd */
+	list_for_each_entry(link, &genpd->child_links, child_node) {
+		parent = link->parent;
 
-		if (!master->set_performance_state)
+		if (!parent->set_performance_state)
 			continue;
 
-		/* Find master's performance state */
+		/* Find parent's performance state */
 		ret = dev_pm_opp_xlate_performance_state(genpd->opp_table,
-							 master->opp_table,
+							 parent->opp_table,
 							 state);
 		if (unlikely(ret < 0))
 			goto err;
 
-		master_state = ret;
+		parent_state = ret;
 
-		genpd_lock_nested(master, depth + 1);
+		genpd_lock_nested(parent, depth + 1);
 
 		link->prev_performance_state = link->performance_state;
-		link->performance_state = master_state;
-		master_state = _genpd_reeval_performance_state(master,
-						master_state);
-		ret = _genpd_set_performance_state(master, master_state, depth + 1);
+		link->performance_state = parent_state;
+		parent_state = _genpd_reeval_performance_state(parent,
+						parent_state);
+		ret = _genpd_set_performance_state(parent, parent_state, depth + 1);
 		if (ret)
 			link->performance_state = link->prev_performance_state;
 
-		genpd_unlock(master);
+		genpd_unlock(parent);
 
 		if (ret)
 			goto err;
@@ -333,26 +333,26 @@
 
 err:
 	/* Encountered an error, lets rollback */
-	list_for_each_entry_continue_reverse(link, &genpd->slave_links,
-					     slave_node) {
-		master = link->master;
+	list_for_each_entry_continue_reverse(link, &genpd->child_links,
+					     child_node) {
+		parent = link->parent;
 
-		if (!master->set_performance_state)
+		if (!parent->set_performance_state)
 			continue;
 
-		genpd_lock_nested(master, depth + 1);
+		genpd_lock_nested(parent, depth + 1);
 
-		master_state = link->prev_performance_state;
-		link->performance_state = master_state;
+		parent_state = link->prev_performance_state;
+		link->performance_state = parent_state;
 
-		master_state = _genpd_reeval_performance_state(master,
-						master_state);
-		if (_genpd_set_performance_state(master, master_state, depth + 1)) {
+		parent_state = _genpd_reeval_performance_state(parent,
+						parent_state);
+		if (_genpd_set_performance_state(parent, parent_state, depth + 1)) {
 			pr_err("%s: Failed to roll back to %d performance state\n",
-			       master->name, master_state);
+			       parent->name, parent_state);
 		}
 
-		genpd_unlock(master);
+		genpd_unlock(parent);
 	}
 
 	return ret;
@@ -552,7 +552,7 @@
 
 		/*
 		 * If sd_count > 0 at this point, one of the subdomains hasn't
-		 * managed to call genpd_power_on() for the master yet after
+		 * managed to call genpd_power_on() for the parent yet after
 		 * incrementing it.  In that case genpd_power_on() will wait
 		 * for us to drop the lock, so we can call .power_off() and let
 		 * the genpd_power_on() restore power for us (this shouldn't
@@ -566,22 +566,22 @@
 	genpd->status = GPD_STATE_POWER_OFF;
 	genpd_update_accounting(genpd);
 
-	list_for_each_entry(link, &genpd->slave_links, slave_node) {
-		genpd_sd_counter_dec(link->master);
-		genpd_lock_nested(link->master, depth + 1);
-		genpd_power_off(link->master, false, depth + 1);
-		genpd_unlock(link->master);
+	list_for_each_entry(link, &genpd->child_links, child_node) {
+		genpd_sd_counter_dec(link->parent);
+		genpd_lock_nested(link->parent, depth + 1);
+		genpd_power_off(link->parent, false, depth + 1);
+		genpd_unlock(link->parent);
 	}
 
 	return 0;
 }
 
 /**
- * genpd_power_on - Restore power to a given PM domain and its masters.
+ * genpd_power_on - Restore power to a given PM domain and its parents.
  * @genpd: PM domain to power up.
  * @depth: nesting count for lockdep.
  *
- * Restore power to @genpd and all of its masters so that it is possible to
+ * Restore power to @genpd and all of its parents so that it is possible to
  * resume a device belonging to it.
  */
 static int genpd_power_on(struct generic_pm_domain *genpd, unsigned int depth)
@@ -594,20 +594,20 @@
 
 	/*
 	 * The list is guaranteed not to change while the loop below is being
-	 * executed, unless one of the masters' .power_on() callbacks fiddles
+	 * executed, unless one of the parents' .power_on() callbacks fiddles
 	 * with it.
 	 */
-	list_for_each_entry(link, &genpd->slave_links, slave_node) {
-		struct generic_pm_domain *master = link->master;
+	list_for_each_entry(link, &genpd->child_links, child_node) {
+		struct generic_pm_domain *parent = link->parent;
 
-		genpd_sd_counter_inc(master);
+		genpd_sd_counter_inc(parent);
 
-		genpd_lock_nested(master, depth + 1);
-		ret = genpd_power_on(master, depth + 1);
-		genpd_unlock(master);
+		genpd_lock_nested(parent, depth + 1);
+		ret = genpd_power_on(parent, depth + 1);
+		genpd_unlock(parent);
 
 		if (ret) {
-			genpd_sd_counter_dec(master);
+			genpd_sd_counter_dec(parent);
 			goto err;
 		}
 	}
@@ -623,12 +623,12 @@
 
  err:
 	list_for_each_entry_continue_reverse(link,
-					&genpd->slave_links,
-					slave_node) {
-		genpd_sd_counter_dec(link->master);
-		genpd_lock_nested(link->master, depth + 1);
-		genpd_power_off(link->master, false, depth + 1);
-		genpd_unlock(link->master);
+					&genpd->child_links,
+					child_node) {
+		genpd_sd_counter_dec(link->parent);
+		genpd_lock_nested(link->parent, depth + 1);
+		genpd_power_off(link->parent, false, depth + 1);
+		genpd_unlock(link->parent);
 	}
 
 	return ret;
@@ -920,7 +920,7 @@
 
 	return 0;
 }
-late_initcall(genpd_power_off_unused);
+late_initcall_sync(genpd_power_off_unused);
 
 #if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM_GENERIC_DOMAINS_OF)
 
@@ -943,13 +943,13 @@
 #ifdef CONFIG_PM_SLEEP
 
 /**
- * genpd_sync_power_off - Synchronously power off a PM domain and its masters.
+ * genpd_sync_power_off - Synchronously power off a PM domain and its parents.
  * @genpd: PM domain to power off, if possible.
  * @use_lock: use the lock.
  * @depth: nesting count for lockdep.
  *
  * Check if the given PM domain can be powered off (during system suspend or
- * hibernation) and do that if so.  Also, in that case propagate to its masters.
+ * hibernation) and do that if so.  Also, in that case propagate to its parents.
  *
  * This function is only called in "noirq" and "syscore" stages of system power
  * transitions. The "noirq" callbacks may be executed asynchronously, thus in
@@ -974,21 +974,21 @@
 
 	genpd->status = GPD_STATE_POWER_OFF;
 
-	list_for_each_entry(link, &genpd->slave_links, slave_node) {
-		genpd_sd_counter_dec(link->master);
+	list_for_each_entry(link, &genpd->child_links, child_node) {
+		genpd_sd_counter_dec(link->parent);
 
 		if (use_lock)
-			genpd_lock_nested(link->master, depth + 1);
+			genpd_lock_nested(link->parent, depth + 1);
 
-		genpd_sync_power_off(link->master, use_lock, depth + 1);
+		genpd_sync_power_off(link->parent, use_lock, depth + 1);
 
 		if (use_lock)
-			genpd_unlock(link->master);
+			genpd_unlock(link->parent);
 	}
 }
 
 /**
- * genpd_sync_power_on - Synchronously power on a PM domain and its masters.
+ * genpd_sync_power_on - Synchronously power on a PM domain and its parents.
  * @genpd: PM domain to power on.
  * @use_lock: use the lock.
  * @depth: nesting count for lockdep.
@@ -1005,16 +1005,16 @@
 	if (genpd_status_on(genpd))
 		return;
 
-	list_for_each_entry(link, &genpd->slave_links, slave_node) {
-		genpd_sd_counter_inc(link->master);
+	list_for_each_entry(link, &genpd->child_links, child_node) {
+		genpd_sd_counter_inc(link->parent);
 
 		if (use_lock)
-			genpd_lock_nested(link->master, depth + 1);
+			genpd_lock_nested(link->parent, depth + 1);
 
-		genpd_sync_power_on(link->master, use_lock, depth + 1);
+		genpd_sync_power_on(link->parent, use_lock, depth + 1);
 
 		if (use_lock)
-			genpd_unlock(link->master);
+			genpd_unlock(link->parent);
 	}
 
 	_genpd_power_on(genpd, false);
@@ -1454,12 +1454,12 @@
 	if (!genpd_is_cpu_domain(genpd))
 		return;
 
-	list_for_each_entry(link, &genpd->slave_links, slave_node) {
-		struct generic_pm_domain *master = link->master;
+	list_for_each_entry(link, &genpd->child_links, child_node) {
+		struct generic_pm_domain *parent = link->parent;
 
-		genpd_lock_nested(master, depth + 1);
-		genpd_update_cpumask(master, cpu, set, depth + 1);
-		genpd_unlock(master);
+		genpd_lock_nested(parent, depth + 1);
+		genpd_update_cpumask(parent, cpu, set, depth + 1);
+		genpd_unlock(parent);
 	}
 
 	if (set)
@@ -1647,17 +1647,17 @@
 		goto out;
 	}
 
-	list_for_each_entry(itr, &genpd->master_links, master_node) {
-		if (itr->slave == subdomain && itr->master == genpd) {
+	list_for_each_entry(itr, &genpd->parent_links, parent_node) {
+		if (itr->child == subdomain && itr->parent == genpd) {
 			ret = -EINVAL;
 			goto out;
 		}
 	}
 
-	link->master = genpd;
-	list_add_tail(&link->master_node, &genpd->master_links);
-	link->slave = subdomain;
-	list_add_tail(&link->slave_node, &subdomain->slave_links);
+	link->parent = genpd;
+	list_add_tail(&link->parent_node, &genpd->parent_links);
+	link->child = subdomain;
+	list_add_tail(&link->child_node, &subdomain->child_links);
 	if (genpd_status_on(subdomain))
 		genpd_sd_counter_inc(genpd);
 
@@ -1671,7 +1671,7 @@
 
 /**
  * pm_genpd_add_subdomain - Add a subdomain to an I/O PM domain.
- * @genpd: Master PM domain to add the subdomain to.
+ * @genpd: Leader PM domain to add the subdomain to.
  * @subdomain: Subdomain to be added.
  */
 int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
@@ -1689,7 +1689,7 @@
 
 /**
  * pm_genpd_remove_subdomain - Remove a subdomain from an I/O PM domain.
- * @genpd: Master PM domain to remove the subdomain from.
+ * @genpd: Leader PM domain to remove the subdomain from.
  * @subdomain: Subdomain to be removed.
  */
 int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
@@ -1704,19 +1704,19 @@
 	genpd_lock(subdomain);
 	genpd_lock_nested(genpd, SINGLE_DEPTH_NESTING);
 
-	if (!list_empty(&subdomain->master_links) || subdomain->device_count) {
+	if (!list_empty(&subdomain->parent_links) || subdomain->device_count) {
 		pr_warn("%s: unable to remove subdomain %s\n",
 			genpd->name, subdomain->name);
 		ret = -EBUSY;
 		goto out;
 	}
 
-	list_for_each_entry_safe(link, l, &genpd->master_links, master_node) {
-		if (link->slave != subdomain)
+	list_for_each_entry_safe(link, l, &genpd->parent_links, parent_node) {
+		if (link->child != subdomain)
 			continue;
 
-		list_del(&link->master_node);
-		list_del(&link->slave_node);
+		list_del(&link->parent_node);
+		list_del(&link->child_node);
 		kfree(link);
 		if (genpd_status_on(subdomain))
 			genpd_sd_counter_dec(genpd);
@@ -1781,8 +1781,8 @@
 	if (IS_ERR_OR_NULL(genpd))
 		return -EINVAL;
 
-	INIT_LIST_HEAD(&genpd->master_links);
-	INIT_LIST_HEAD(&genpd->slave_links);
+	INIT_LIST_HEAD(&genpd->parent_links);
+	INIT_LIST_HEAD(&genpd->child_links);
 	INIT_LIST_HEAD(&genpd->dev_list);
 	genpd_lock_init(genpd);
 	genpd->gov = gov;
@@ -1858,15 +1858,15 @@
 		return -EBUSY;
 	}
 
-	if (!list_empty(&genpd->master_links) || genpd->device_count) {
+	if (!list_empty(&genpd->parent_links) || genpd->device_count) {
 		genpd_unlock(genpd);
 		pr_err("%s: unable to remove %s\n", __func__, genpd->name);
 		return -EBUSY;
 	}
 
-	list_for_each_entry_safe(link, l, &genpd->slave_links, slave_node) {
-		list_del(&link->master_node);
-		list_del(&link->slave_node);
+	list_for_each_entry_safe(link, l, &genpd->child_links, child_node) {
+		list_del(&link->parent_node);
+		list_del(&link->child_node);
 		kfree(link);
 	}
 
@@ -2596,10 +2596,10 @@
 
 	err = of_property_read_u32(state_node, "min-residency-us", &residency);
 	if (!err)
-		genpd_state->residency_ns = 1000 * residency;
+		genpd_state->residency_ns = 1000LL * residency;
 
-	genpd_state->power_on_latency_ns = 1000 * exit_latency;
-	genpd_state->power_off_latency_ns = 1000 * entry_latency;
+	genpd_state->power_on_latency_ns = 1000LL * exit_latency;
+	genpd_state->power_off_latency_ns = 1000LL * entry_latency;
 	genpd_state->fwnode = &state_node->fwnode;
 
 	return 0;
@@ -2615,13 +2615,17 @@
 
 	ret = of_count_phandle_with_args(dn, "domain-idle-states", NULL);
 	if (ret <= 0)
-		return ret;
+		return ret == -ENOENT ? 0 : ret;
 
 	/* Loop over the phandles until all the requested entry is found */
 	of_for_each_phandle(&it, ret, dn, "domain-idle-states", NULL, 0) {
 		np = it.node;
 		if (!of_match_node(idle_state_match, np))
 			continue;
+
+		if (!of_device_is_available(np))
+			continue;
+
 		if (states) {
 			ret = genpd_parse_state(&states[i], np);
 			if (ret) {
@@ -2789,12 +2793,12 @@
 
 	/*
 	 * Modifications on the list require holding locks on both
-	 * master and slave, so we are safe.
+	 * parent and child, so we are safe.
 	 * Also genpd->name is immutable.
 	 */
-	list_for_each_entry(link, &genpd->master_links, master_node) {
-		seq_printf(s, "%s", link->slave->name);
-		if (!list_is_last(&link->master_node, &genpd->master_links))
+	list_for_each_entry(link, &genpd->parent_links, parent_node) {
+		seq_printf(s, "%s", link->child->name);
+		if (!list_is_last(&link->parent_node, &genpd->parent_links))
 			seq_puts(s, ", ");
 	}
 
@@ -2822,7 +2826,7 @@
 	struct generic_pm_domain *genpd;
 	int ret = 0;
 
-	seq_puts(s, "domain                          status          slaves\n");
+	seq_puts(s, "domain                          status          children\n");
 	seq_puts(s, "    /device                                             runtime status\n");
 	seq_puts(s, "----------------------------------------------------------------------\n");
 
@@ -2877,8 +2881,8 @@
 	if (ret)
 		return -ERESTARTSYS;
 
-	list_for_each_entry(link, &genpd->master_links, master_node)
-		seq_printf(s, "%s\n", link->slave->name);
+	list_for_each_entry(link, &genpd->parent_links, parent_node)
+		seq_printf(s, "%s\n", link->child->name);
 
 	genpd_unlock(genpd);
 	return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/power/domain_governor.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/power/domain_governor.c
@@ -135,8 +135,8 @@
 	 *
 	 * All subdomains have been powered off already at this point.
 	 */
-	list_for_each_entry(link, &genpd->master_links, master_node) {
-		struct generic_pm_domain *sd = link->slave;
+	list_for_each_entry(link, &genpd->parent_links, parent_node) {
+		struct generic_pm_domain *sd = link->child;
 		s64 sd_max_off_ns = sd->max_off_time_ns;
 
 		if (sd_max_off_ns < 0)
@@ -217,13 +217,13 @@
 	}
 
 	/*
-	 * We have to invalidate the cached results for the masters, so
+	 * We have to invalidate the cached results for the parents, so
 	 * use the observation that default_power_down_ok() is not
-	 * going to be called for any master until this instance
+	 * going to be called for any parent until this instance
 	 * returns.
 	 */
-	list_for_each_entry(link, &genpd->slave_links, slave_node)
-		link->master->max_off_time_changed = true;
+	list_for_each_entry(link, &genpd->child_links, child_node)
+		link->parent->max_off_time_changed = true;
 
 	genpd->max_off_time_ns = -1;
 	genpd->max_off_time_changed = false;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/power/main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/power/main.c
@@ -273,10 +273,38 @@
 	device_links_read_unlock(idx);
 }
 
-static void dpm_wait_for_superior(struct device *dev, bool async)
+static bool dpm_wait_for_superior(struct device *dev, bool async)
 {
-	dpm_wait(dev->parent, async);
+	struct device *parent;
+
+	/*
+	 * If the device is resumed asynchronously and the parent's callback
+	 * deletes both the device and the parent itself, the parent object may
+	 * be freed while this function is running, so avoid that by reference
+	 * counting the parent once more unless the device has been deleted
+	 * already (in which case return right away).
+	 */
+	mutex_lock(&dpm_list_mtx);
+
+	if (!device_pm_initialized(dev)) {
+		mutex_unlock(&dpm_list_mtx);
+		return false;
+	}
+
+	parent = get_device(dev->parent);
+
+	mutex_unlock(&dpm_list_mtx);
+
+	dpm_wait(parent, async);
+	put_device(parent);
+
 	dpm_wait_for_suppliers(dev, async);
+
+	/*
+	 * If the parent's callback has deleted the device, attempting to resume
+	 * it would be invalid, so avoid doing that then.
+	 */
+	return device_pm_initialized(dev);
 }
 
 static void dpm_wait_for_consumers(struct device *dev, bool async)
@@ -597,7 +625,7 @@
 						const char **info_p);
 
 /**
- * device_resume_noirq - Execute a "noirq resume" callback for given device.
+ * __device_resume_noirq - Execute a "noirq resume" callback for given device.
  * @dev: Device to handle.
  * @state: PM transition of the system being carried out.
  * @async: If true, the device is being resumed asynchronously.
@@ -605,7 +633,7 @@
  * The driver of @dev will not receive interrupts while this function is being
  * executed.
  */
-static int device_resume_noirq(struct device *dev, pm_message_t state, bool async)
+static void __device_resume_noirq(struct device *dev, pm_message_t state, bool async)
 {
 	pm_callback_t callback;
 	const char *info;
@@ -621,7 +649,8 @@
 	if (!dev->power.is_noirq_suspended)
 		goto Out;
 
-	dpm_wait_for_superior(dev, async);
+	if (!dpm_wait_for_superior(dev, async))
+		goto Out;
 
 	skip_resume = dev_pm_may_skip_resume(dev);
 
@@ -682,7 +711,13 @@
 Out:
 	complete_all(&dev->power.completion);
 	TRACE_RESUME(error);
-	return error;
+
+	if (error) {
+		suspend_stats.failed_resume_noirq++;
+		dpm_save_failed_step(SUSPEND_RESUME_NOIRQ);
+		dpm_save_failed_dev(dev_name(dev));
+		pm_dev_err(dev, state, async ? " async noirq" : " noirq", error);
+	}
 }
 
 static bool is_async(struct device *dev)
@@ -695,11 +730,15 @@
 {
 	reinit_completion(&dev->power.completion);
 
-	if (is_async(dev)) {
-		get_device(dev);
-		async_schedule(func, dev);
+	if (!is_async(dev))
+		return false;
+
+	get_device(dev);
+
+	if (async_schedule_dev_nocall(func, dev))
 		return true;
-	}
+
+	put_device(dev);
 
 	return false;
 }
@@ -707,15 +746,19 @@
 static void async_resume_noirq(void *data, async_cookie_t cookie)
 {
 	struct device *dev = (struct device *)data;
-	int error;
-
-	error = device_resume_noirq(dev, pm_transition, true);
-	if (error)
-		pm_dev_err(dev, pm_transition, " async", error);
 
+	__device_resume_noirq(dev, pm_transition, true);
 	put_device(dev);
 }
 
+static void device_resume_noirq(struct device *dev)
+{
+	if (dpm_async_fn(dev, async_resume_noirq))
+		return;
+
+	__device_resume_noirq(dev, pm_transition, false);
+}
+
 static void dpm_noirq_resume_devices(pm_message_t state)
 {
 	struct device *dev;
@@ -725,34 +768,18 @@
 	mutex_lock(&dpm_list_mtx);
 	pm_transition = state;
 
-	/*
-	 * Advanced the async threads upfront,
-	 * in case the starting of async threads is
-	 * delayed by non-async resuming devices.
-	 */
-	list_for_each_entry(dev, &dpm_noirq_list, power.entry)
-		dpm_async_fn(dev, async_resume_noirq);
-
 	while (!list_empty(&dpm_noirq_list)) {
 		dev = to_device(dpm_noirq_list.next);
 		get_device(dev);
 		list_move_tail(&dev->power.entry, &dpm_late_early_list);
+
 		mutex_unlock(&dpm_list_mtx);
 
-		if (!is_async(dev)) {
-			int error;
+		device_resume_noirq(dev);
 
-			error = device_resume_noirq(dev, state, false);
-			if (error) {
-				suspend_stats.failed_resume_noirq++;
-				dpm_save_failed_step(SUSPEND_RESUME_NOIRQ);
-				dpm_save_failed_dev(dev_name(dev));
-				pm_dev_err(dev, state, " noirq", error);
-			}
-		}
+		put_device(dev);
 
 		mutex_lock(&dpm_list_mtx);
-		put_device(dev);
 	}
 	mutex_unlock(&dpm_list_mtx);
 	async_synchronize_full();
@@ -807,14 +834,14 @@
 }
 
 /**
- * device_resume_early - Execute an "early resume" callback for given device.
+ * __device_resume_early - Execute an "early resume" callback for given device.
  * @dev: Device to handle.
  * @state: PM transition of the system being carried out.
  * @async: If true, the device is being resumed asynchronously.
  *
  * Runtime PM is disabled for @dev while this function is being executed.
  */
-static int device_resume_early(struct device *dev, pm_message_t state, bool async)
+static void __device_resume_early(struct device *dev, pm_message_t state, bool async)
 {
 	pm_callback_t callback;
 	const char *info;
@@ -829,7 +856,8 @@
 	if (!dev->power.is_late_suspended)
 		goto Out;
 
-	dpm_wait_for_superior(dev, async);
+	if (!dpm_wait_for_superior(dev, async))
+		goto Out;
 
 	callback = dpm_subsys_resume_early_cb(dev, state, &info);
 
@@ -846,21 +874,31 @@
 
 	pm_runtime_enable(dev);
 	complete_all(&dev->power.completion);
-	return error;
+
+	if (error) {
+		suspend_stats.failed_resume_early++;
+		dpm_save_failed_step(SUSPEND_RESUME_EARLY);
+		dpm_save_failed_dev(dev_name(dev));
+		pm_dev_err(dev, state, async ? " async early" : " early", error);
+	}
 }
 
 static void async_resume_early(void *data, async_cookie_t cookie)
 {
 	struct device *dev = (struct device *)data;
-	int error;
-
-	error = device_resume_early(dev, pm_transition, true);
-	if (error)
-		pm_dev_err(dev, pm_transition, " async", error);
 
+	__device_resume_early(dev, pm_transition, true);
 	put_device(dev);
 }
 
+static void device_resume_early(struct device *dev)
+{
+	if (dpm_async_fn(dev, async_resume_early))
+		return;
+
+	__device_resume_early(dev, pm_transition, false);
+}
+
 /**
  * dpm_resume_early - Execute "early resume" callbacks for all devices.
  * @state: PM transition of the system being carried out.
@@ -874,33 +912,18 @@
 	mutex_lock(&dpm_list_mtx);
 	pm_transition = state;
 
-	/*
-	 * Advanced the async threads upfront,
-	 * in case the starting of async threads is
-	 * delayed by non-async resuming devices.
-	 */
-	list_for_each_entry(dev, &dpm_late_early_list, power.entry)
-		dpm_async_fn(dev, async_resume_early);
-
 	while (!list_empty(&dpm_late_early_list)) {
 		dev = to_device(dpm_late_early_list.next);
 		get_device(dev);
 		list_move_tail(&dev->power.entry, &dpm_suspended_list);
+
 		mutex_unlock(&dpm_list_mtx);
 
-		if (!is_async(dev)) {
-			int error;
+		device_resume_early(dev);
 
-			error = device_resume_early(dev, state, false);
-			if (error) {
-				suspend_stats.failed_resume_early++;
-				dpm_save_failed_step(SUSPEND_RESUME_EARLY);
-				dpm_save_failed_dev(dev_name(dev));
-				pm_dev_err(dev, state, " early", error);
-			}
-		}
-		mutex_lock(&dpm_list_mtx);
 		put_device(dev);
+
+		mutex_lock(&dpm_list_mtx);
 	}
 	mutex_unlock(&dpm_list_mtx);
 	async_synchronize_full();
@@ -920,12 +943,12 @@
 EXPORT_SYMBOL_GPL(dpm_resume_start);
 
 /**
- * device_resume - Execute "resume" callbacks for given device.
+ * __device_resume - Execute "resume" callbacks for given device.
  * @dev: Device to handle.
  * @state: PM transition of the system being carried out.
  * @async: If true, the device is being resumed asynchronously.
  */
-static int device_resume(struct device *dev, pm_message_t state, bool async)
+static void __device_resume(struct device *dev, pm_message_t state, bool async)
 {
 	pm_callback_t callback = NULL;
 	const char *info = NULL;
@@ -938,13 +961,18 @@
 	if (dev->power.syscore)
 		goto Complete;
 
+	if (!dev->power.is_suspended)
+		goto Complete;
+
 	if (dev->power.direct_complete) {
 		/* Match the pm_runtime_disable() in __device_suspend(). */
 		pm_runtime_enable(dev);
 		goto Complete;
 	}
 
-	dpm_wait_for_superior(dev, async);
+	if (!dpm_wait_for_superior(dev, async))
+		goto Complete;
+
 	dpm_watchdog_set(&wd, dev);
 	device_lock(dev);
 
@@ -954,9 +982,6 @@
 	 */
 	dev->power.is_prepared = false;
 
-	if (!dev->power.is_suspended)
-		goto Unlock;
-
 	if (dev->pm_domain) {
 		info = "power domain ";
 		callback = pm_op(&dev->pm_domain->ops, state);
@@ -996,7 +1021,6 @@
 	error = dpm_run_callback(callback, dev, state, info);
 	dev->power.is_suspended = false;
 
- Unlock:
 	device_unlock(dev);
 	dpm_watchdog_clear(&wd);
 
@@ -1005,20 +1029,30 @@
 
 	TRACE_RESUME(error);
 
-	return error;
+	if (error) {
+		suspend_stats.failed_resume++;
+		dpm_save_failed_step(SUSPEND_RESUME);
+		dpm_save_failed_dev(dev_name(dev));
+		pm_dev_err(dev, state, async ? " async" : "", error);
+	}
 }
 
 static void async_resume(void *data, async_cookie_t cookie)
 {
 	struct device *dev = (struct device *)data;
-	int error;
 
-	error = device_resume(dev, pm_transition, true);
-	if (error)
-		pm_dev_err(dev, pm_transition, " async", error);
+	__device_resume(dev, pm_transition, true);
 	put_device(dev);
 }
 
+static void device_resume(struct device *dev)
+{
+	if (dpm_async_fn(dev, async_resume))
+		return;
+
+	__device_resume(dev, pm_transition, false);
+}
+
 /**
  * dpm_resume - Execute "resume" callbacks for non-sysdev devices.
  * @state: PM transition of the system being carried out.
@@ -1038,30 +1072,25 @@
 	pm_transition = state;
 	async_error = 0;
 
-	list_for_each_entry(dev, &dpm_suspended_list, power.entry)
-		dpm_async_fn(dev, async_resume);
-
 	while (!list_empty(&dpm_suspended_list)) {
 		dev = to_device(dpm_suspended_list.next);
+
 		get_device(dev);
-		if (!is_async(dev)) {
-			int error;
 
-			mutex_unlock(&dpm_list_mtx);
+		mutex_unlock(&dpm_list_mtx);
 
-			error = device_resume(dev, state, false);
-			if (error) {
-				suspend_stats.failed_resume++;
-				dpm_save_failed_step(SUSPEND_RESUME);
-				dpm_save_failed_dev(dev_name(dev));
-				pm_dev_err(dev, state, "", error);
-			}
+		device_resume(dev);
+
+		mutex_lock(&dpm_list_mtx);
 
-			mutex_lock(&dpm_list_mtx);
-		}
 		if (!list_empty(&dev->power.entry))
 			list_move_tail(&dev->power.entry, &dpm_prepared_list);
+
+		mutex_unlock(&dpm_list_mtx);
+
 		put_device(dev);
+
+		mutex_lock(&dpm_list_mtx);
 	}
 	mutex_unlock(&dpm_list_mtx);
 	async_synchronize_full();
@@ -1138,14 +1167,16 @@
 		get_device(dev);
 		dev->power.is_prepared = false;
 		list_move(&dev->power.entry, &list);
+
 		mutex_unlock(&dpm_list_mtx);
 
 		trace_device_pm_callback_start(dev, "", state.event);
 		device_complete(dev, state);
 		trace_device_pm_callback_end(dev, 0);
 
-		mutex_lock(&dpm_list_mtx);
 		put_device(dev);
+
+		mutex_lock(&dpm_list_mtx);
 	}
 	list_splice(&list, &dpm_list);
 	mutex_unlock(&dpm_list_mtx);
@@ -1373,17 +1404,21 @@
 		error = device_suspend_noirq(dev);
 
 		mutex_lock(&dpm_list_mtx);
+
 		if (error) {
 			pm_dev_err(dev, state, " noirq", error);
 			dpm_save_failed_dev(dev_name(dev));
-			put_device(dev);
-			break;
-		}
-		if (!list_empty(&dev->power.entry))
+		} else if (!list_empty(&dev->power.entry)) {
 			list_move(&dev->power.entry, &dpm_noirq_list);
+		}
+
+		mutex_unlock(&dpm_list_mtx);
+
 		put_device(dev);
 
-		if (async_error)
+		mutex_lock(&dpm_list_mtx);
+
+		if (error || async_error)
 			break;
 	}
 	mutex_unlock(&dpm_list_mtx);
@@ -1568,23 +1603,28 @@
 		struct device *dev = to_device(dpm_suspended_list.prev);
 
 		get_device(dev);
+
 		mutex_unlock(&dpm_list_mtx);
 
 		error = device_suspend_late(dev);
 
 		mutex_lock(&dpm_list_mtx);
+
 		if (!list_empty(&dev->power.entry))
 			list_move(&dev->power.entry, &dpm_late_early_list);
 
 		if (error) {
 			pm_dev_err(dev, state, " late", error);
 			dpm_save_failed_dev(dev_name(dev));
-			put_device(dev);
-			break;
 		}
+
+		mutex_unlock(&dpm_list_mtx);
+
 		put_device(dev);
 
-		if (async_error)
+		mutex_lock(&dpm_list_mtx);
+
+		if (error || async_error)
 			break;
 	}
 	mutex_unlock(&dpm_list_mtx);
@@ -1696,13 +1736,17 @@
 	}
 
 	/*
-	 * If a device configured to wake up the system from sleep states
-	 * has been suspended at run time and there's a resume request pending
-	 * for it, this is equivalent to the device signaling wakeup, so the
-	 * system suspend operation should be aborted.
+	 * Wait for possible runtime PM transitions of the device in progress
+	 * to complete and if there's a runtime resume request pending for it,
+	 * resume it before proceeding with invoking the system-wide suspend
+	 * callbacks for it.
+	 *
+	 * If the system-wide suspend callbacks below change the configuration
+	 * of the device, they must disable runtime PM for it or otherwise
+	 * ensure that its runtime-resume callbacks will not be confused by that
+	 * change in case they are invoked going forward.
 	 */
-	if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
-		pm_wakeup_event(dev, 0);
+	pm_runtime_barrier(dev);
 
 	if (pm_wakeup_pending()) {
 		dev->power.direct_complete = false;
@@ -1722,6 +1766,7 @@
 			pm_runtime_disable(dev);
 			if (pm_runtime_status_suspended(dev)) {
 				pm_dev_dbg(dev, state, "direct-complete ");
+				dev->power.is_suspended = true;
 				goto Complete;
 			}
 
@@ -1840,21 +1885,27 @@
 		struct device *dev = to_device(dpm_prepared_list.prev);
 
 		get_device(dev);
+
 		mutex_unlock(&dpm_list_mtx);
 
 		error = device_suspend(dev);
 
 		mutex_lock(&dpm_list_mtx);
+
 		if (error) {
 			pm_dev_err(dev, state, "", error);
 			dpm_save_failed_dev(dev_name(dev));
-			put_device(dev);
-			break;
-		}
-		if (!list_empty(&dev->power.entry))
+		} else if (!list_empty(&dev->power.entry)) {
 			list_move(&dev->power.entry, &dpm_suspended_list);
+		}
+
+		mutex_unlock(&dpm_list_mtx);
+
 		put_device(dev);
-		if (async_error)
+
+		mutex_lock(&dpm_list_mtx);
+
+		if (error || async_error)
 			break;
 	}
 	mutex_unlock(&dpm_list_mtx);
@@ -1972,10 +2023,11 @@
 	device_block_probing();
 
 	mutex_lock(&dpm_list_mtx);
-	while (!list_empty(&dpm_list)) {
+	while (!list_empty(&dpm_list) && !error) {
 		struct device *dev = to_device(dpm_list.next);
 
 		get_device(dev);
+
 		mutex_unlock(&dpm_list_mtx);
 
 		trace_device_pm_callback_start(dev, "", state.event);
@@ -1983,21 +2035,22 @@
 		trace_device_pm_callback_end(dev, error);
 
 		mutex_lock(&dpm_list_mtx);
-		if (error) {
-			if (error == -EAGAIN) {
-				put_device(dev);
-				error = 0;
-				continue;
-			}
+		if (!error) {
+			dev->power.is_prepared = true;
+			if (!list_empty(&dev->power.entry))
+				list_move_tail(&dev->power.entry, &dpm_prepared_list);
+		} else if (error == -EAGAIN) {
+			error = 0;
+		} else {
 			pr_info("Device %s not prepared for power transition: code %d\n",
 				dev_name(dev), error);
-			put_device(dev);
-			break;
 		}
-		dev->power.is_prepared = true;
-		if (!list_empty(&dev->power.entry))
-			list_move_tail(&dev->power.entry, &dpm_prepared_list);
+
+		mutex_unlock(&dpm_list_mtx);
+
 		put_device(dev);
+
+		mutex_lock(&dpm_list_mtx);
 	}
 	mutex_unlock(&dpm_list_mtx);
 	trace_suspend_resume(TPS("dpm_prepare"), state.event, false);
@@ -2085,7 +2138,9 @@
 
 void device_pm_check_callbacks(struct device *dev)
 {
-	spin_lock_irq(&dev->power.lock);
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->power.lock, flags);
 	dev->power.no_pm_callbacks =
 		(!dev->bus || (pm_ops_is_empty(dev->bus->pm) &&
 		 !dev->bus->suspend && !dev->bus->resume)) &&
@@ -2094,7 +2149,7 @@
 		(!dev->pm_domain || pm_ops_is_empty(&dev->pm_domain->ops)) &&
 		(!dev->driver || (pm_ops_is_empty(dev->driver->pm) &&
 		 !dev->driver->suspend && !dev->driver->resume));
-	spin_unlock_irq(&dev->power.lock);
+	spin_unlock_irqrestore(&dev->power.lock, flags);
 }
 
 bool dev_pm_smart_suspend_and_suspended(struct device *dev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/power/power.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/power/power.h
@@ -25,8 +25,11 @@
 
 #define WAKE_IRQ_DEDICATED_ALLOCATED	BIT(0)
 #define WAKE_IRQ_DEDICATED_MANAGED	BIT(1)
+#define WAKE_IRQ_DEDICATED_REVERSE	BIT(2)
 #define WAKE_IRQ_DEDICATED_MASK		(WAKE_IRQ_DEDICATED_ALLOCATED | \
-					 WAKE_IRQ_DEDICATED_MANAGED)
+					 WAKE_IRQ_DEDICATED_MANAGED | \
+					 WAKE_IRQ_DEDICATED_REVERSE)
+#define WAKE_IRQ_DEDICATED_ENABLED	BIT(3)
 
 struct wake_irq {
 	struct device *dev;
@@ -39,7 +42,8 @@
 extern void dev_pm_disarm_wake_irq(struct wake_irq *wirq);
 extern void dev_pm_enable_wake_irq_check(struct device *dev,
 					 bool can_change_status);
-extern void dev_pm_disable_wake_irq_check(struct device *dev);
+extern void dev_pm_disable_wake_irq_check(struct device *dev, bool cond_disable);
+extern void dev_pm_enable_wake_irq_complete(struct device *dev);
 
 #ifdef CONFIG_PM_SLEEP
 
@@ -74,6 +78,7 @@
 extern void pm_qos_sysfs_remove_flags(struct device *dev);
 extern int pm_qos_sysfs_add_latency_tolerance(struct device *dev);
 extern void pm_qos_sysfs_remove_latency_tolerance(struct device *dev);
+extern int dpm_sysfs_change_owner(struct device *dev, kuid_t kuid, kgid_t kgid);
 
 #else /* CONFIG_PM */
 
@@ -88,6 +93,8 @@
 
 static inline int dpm_sysfs_add(struct device *dev) { return 0; }
 static inline void dpm_sysfs_remove(struct device *dev) {}
+static inline int dpm_sysfs_change_owner(struct device *dev, kuid_t kuid,
+					 kgid_t kgid) { return 0; }
 
 #endif
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/power/runtime.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/power/runtime.c
@@ -291,8 +291,7 @@
 				device_links_read_lock_held()) {
 		int retval;
 
-		if (!(link->flags & DL_FLAG_PM_RUNTIME) ||
-		    READ_ONCE(link->status) == DL_STATE_SUPPLIER_UNBIND)
+		if (!(link->flags & DL_FLAG_PM_RUNTIME))
 			continue;
 
 		retval = pm_runtime_get_sync(link->supplier);
@@ -306,20 +305,38 @@
 	return 0;
 }
 
-static void rpm_put_suppliers(struct device *dev)
+static void __rpm_put_suppliers(struct device *dev, bool try_to_suspend)
 {
 	struct device_link *link;
 
 	list_for_each_entry_rcu(link, &dev->links.suppliers, c_node,
 				device_links_read_lock_held()) {
-		if (READ_ONCE(link->status) == DL_STATE_SUPPLIER_UNBIND)
-			continue;
 
 		while (refcount_dec_not_one(&link->rpm_active))
-			pm_runtime_put(link->supplier);
+			pm_runtime_put_noidle(link->supplier);
+
+		if (try_to_suspend)
+			pm_request_idle(link->supplier);
 	}
 }
 
+static void rpm_put_suppliers(struct device *dev)
+{
+	__rpm_put_suppliers(dev, true);
+}
+
+static void rpm_suspend_suppliers(struct device *dev)
+{
+	struct device_link *link;
+	int idx = device_links_read_lock();
+
+	list_for_each_entry_rcu(link, &dev->links.suppliers, c_node,
+				device_links_read_lock_held())
+		pm_request_idle(link->supplier);
+
+	device_links_read_unlock(idx);
+}
+
 /**
  * __rpm_callback - Run a given runtime PM callback for a given device.
  * @cb: Runtime PM callback to run.
@@ -347,8 +364,10 @@
 			idx = device_links_read_lock();
 
 			retval = rpm_get_suppliers(dev);
-			if (retval)
+			if (retval) {
+				rpm_put_suppliers(dev);
 				goto fail;
+			}
 
 			device_links_read_unlock(idx);
 		}
@@ -371,9 +390,9 @@
 		    || (dev->power.runtime_status == RPM_RESUMING && retval))) {
 			idx = device_links_read_lock();
 
- fail:
-			rpm_put_suppliers(dev);
+			__rpm_put_suppliers(dev, false);
 
+fail:
 			device_links_read_unlock(idx);
 		}
 
@@ -427,7 +446,10 @@
 	/* Pending requests need to be canceled. */
 	dev->power.request = RPM_REQ_NONE;
 
-	if (dev->power.no_callbacks)
+	callback = RPM_GET_CALLBACK(dev, runtime_idle);
+
+	/* If no callback assume success. */
+	if (!callback || dev->power.no_callbacks)
 		goto out;
 
 	/* Carry out an asynchronous or a synchronous idle notification. */
@@ -443,10 +465,17 @@
 
 	dev->power.idle_notification = true;
 
-	callback = RPM_GET_CALLBACK(dev, runtime_idle);
+	if (dev->power.irq_safe)
+		spin_unlock(&dev->power.lock);
+	else
+		spin_unlock_irq(&dev->power.lock);
 
-	if (callback)
-		retval = __rpm_callback(callback, dev);
+	retval = callback(dev);
+
+	if (dev->power.irq_safe)
+		spin_lock(&dev->power.lock);
+	else
+		spin_lock_irq(&dev->power.lock);
 
 	dev->power.idle_notification = false;
 	wake_up_all(&dev->power.wait_queue);
@@ -630,6 +659,8 @@
 	if (retval)
 		goto fail;
 
+	dev_pm_enable_wake_irq_complete(dev);
+
  no_callback:
 	__update_runtime_status(dev, RPM_SUSPENDED);
 	pm_runtime_deactivate_timer(dev);
@@ -647,8 +678,11 @@
 		goto out;
 	}
 
+	if (dev->power.irq_safe)
+		goto out;
+
 	/* Maybe the parent is now able to suspend. */
-	if (parent && !parent->power.ignore_children && !dev->power.irq_safe) {
+	if (parent && !parent->power.ignore_children) {
 		spin_unlock(&dev->power.lock);
 
 		spin_lock(&parent->power.lock);
@@ -657,6 +691,14 @@
 
 		spin_lock(&dev->power.lock);
 	}
+	/* Maybe the suppliers are now able to suspend. */
+	if (dev->power.links_count > 0) {
+		spin_unlock_irq(&dev->power.lock);
+
+		rpm_suspend_suppliers(dev);
+
+		spin_lock_irq(&dev->power.lock);
+	}
 
  out:
 	trace_rpm_return_int_rcuidle(dev, _THIS_IP_, retval);
@@ -664,7 +706,7 @@
 	return retval;
 
  fail:
-	dev_pm_disable_wake_irq_check(dev);
+	dev_pm_disable_wake_irq_check(dev, true);
 	__update_runtime_status(dev, RPM_ACTIVE);
 	dev->power.deferred_resume = false;
 	wake_up_all(&dev->power.wait_queue);
@@ -847,7 +889,7 @@
 
 	callback = RPM_GET_CALLBACK(dev, runtime_resume);
 
-	dev_pm_disable_wake_irq_check(dev);
+	dev_pm_disable_wake_irq_check(dev, false);
 	retval = rpm_callback(callback, dev);
 	if (retval) {
 		__update_runtime_status(dev, RPM_SUSPENDED);
@@ -1006,8 +1048,10 @@
 	int retval;
 
 	if (rpmflags & RPM_GET_PUT) {
-		if (!atomic_dec_and_test(&dev->power.usage_count))
+		if (!atomic_dec_and_test(&dev->power.usage_count)) {
+			trace_rpm_usage_rcuidle(dev, rpmflags);
 			return 0;
+		}
 	}
 
 	might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
@@ -1038,8 +1082,10 @@
 	int retval;
 
 	if (rpmflags & RPM_GET_PUT) {
-		if (!atomic_dec_and_test(&dev->power.usage_count))
+		if (!atomic_dec_and_test(&dev->power.usage_count)) {
+			trace_rpm_usage_rcuidle(dev, rpmflags);
 			return 0;
+		}
 	}
 
 	might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
@@ -1083,28 +1129,47 @@
 EXPORT_SYMBOL_GPL(__pm_runtime_resume);
 
 /**
- * pm_runtime_get_if_in_use - Conditionally bump up the device's usage counter.
+ * pm_runtime_get_if_active - Conditionally bump up the device's usage counter.
  * @dev: Device to handle.
  *
  * Return -EINVAL if runtime PM is disabled for the device.
  *
- * If that's not the case and if the device's runtime PM status is RPM_ACTIVE
- * and the runtime PM usage counter is nonzero, increment the counter and
- * return 1.  Otherwise return 0 without changing the counter.
+ * Otherwise, if the device's runtime PM status is RPM_ACTIVE and either
+ * ign_usage_count is true or the device's usage_count is non-zero, increment
+ * the counter and return 1. Otherwise return 0 without changing the counter.
+ *
+ * If ign_usage_count is true, the function can be used to prevent suspending
+ * the device when its runtime PM status is RPM_ACTIVE.
+ *
+ * If ign_usage_count is false, the function can be used to prevent suspending
+ * the device when both its runtime PM status is RPM_ACTIVE and its usage_count
+ * is non-zero.
+ *
+ * The caller is resposible for putting the device's usage count when ther
+ * return value is greater than zero.
  */
-int pm_runtime_get_if_in_use(struct device *dev)
+int pm_runtime_get_if_active(struct device *dev, bool ign_usage_count)
 {
 	unsigned long flags;
 	int retval;
 
 	spin_lock_irqsave(&dev->power.lock, flags);
-	retval = dev->power.disable_depth > 0 ? -EINVAL :
-		dev->power.runtime_status == RPM_ACTIVE
-			&& atomic_inc_not_zero(&dev->power.usage_count);
+	if (dev->power.disable_depth > 0) {
+		retval = -EINVAL;
+	} else if (dev->power.runtime_status != RPM_ACTIVE) {
+		retval = 0;
+	} else if (ign_usage_count) {
+		retval = 1;
+		atomic_inc(&dev->power.usage_count);
+	} else {
+		retval = atomic_inc_not_zero(&dev->power.usage_count);
+	}
+	trace_rpm_usage_rcuidle(dev, 0);
 	spin_unlock_irqrestore(&dev->power.lock, flags);
+
 	return retval;
 }
-EXPORT_SYMBOL_GPL(pm_runtime_get_if_in_use);
+EXPORT_SYMBOL_GPL(pm_runtime_get_if_active);
 
 /**
  * __pm_runtime_set_status - Set runtime PM status of a device.
@@ -1396,6 +1461,28 @@
 }
 EXPORT_SYMBOL_GPL(pm_runtime_enable);
 
+static void pm_runtime_disable_action(void *data)
+{
+	pm_runtime_dont_use_autosuspend(data);
+	pm_runtime_disable(data);
+}
+
+/**
+ * devm_pm_runtime_enable - devres-enabled version of pm_runtime_enable.
+ *
+ * NOTE: this will also handle calling pm_runtime_dont_use_autosuspend() for
+ * you at driver exit time if needed.
+ *
+ * @dev: Device to handle.
+ */
+int devm_pm_runtime_enable(struct device *dev)
+{
+	pm_runtime_enable(dev);
+
+	return devm_add_action_or_reset(dev, pm_runtime_disable_action, dev);
+}
+EXPORT_SYMBOL_GPL(devm_pm_runtime_enable);
+
 /**
  * pm_runtime_forbid - Block runtime PM of a device.
  * @dev: Device to handle.
@@ -1434,6 +1521,8 @@
 	dev->power.runtime_auto = true;
 	if (atomic_dec_and_test(&dev->power.usage_count))
 		rpm_idle(dev, RPM_AUTO | RPM_ASYNC);
+	else
+		trace_rpm_usage_rcuidle(dev, RPM_AUTO | RPM_ASYNC);
 
  out:
 	spin_unlock_irq(&dev->power.lock);
@@ -1501,6 +1590,8 @@
 		if (!old_use || old_delay >= 0) {
 			atomic_inc(&dev->power.usage_count);
 			rpm_resume(dev, 0);
+		} else {
+			trace_rpm_usage_rcuidle(dev, 0);
 		}
 	}
 
@@ -1580,6 +1671,7 @@
 	dev->power.request_pending = false;
 	dev->power.request = RPM_REQ_NONE;
 	dev->power.deferred_resume = false;
+	dev->power.needs_force_resume = 0;
 	INIT_WORK(&dev->power.work, pm_runtime_work);
 
 	dev->power.timer_expires = 0;
@@ -1619,42 +1711,6 @@
 }
 
 /**
- * pm_runtime_clean_up_links - Prepare links to consumers for driver removal.
- * @dev: Device whose driver is going to be removed.
- *
- * Check links from this device to any consumers and if any of them have active
- * runtime PM references to the device, drop the usage counter of the device
- * (as many times as needed).
- *
- * Links with the DL_FLAG_MANAGED flag unset are ignored.
- *
- * Since the device is guaranteed to be runtime-active at the point this is
- * called, nothing else needs to be done here.
- *
- * Moreover, this is called after device_links_busy() has returned 'false', so
- * the status of each link is guaranteed to be DL_STATE_SUPPLIER_UNBIND and
- * therefore rpm_active can't be manipulated concurrently.
- */
-void pm_runtime_clean_up_links(struct device *dev)
-{
-	struct device_link *link;
-	int idx;
-
-	idx = device_links_read_lock();
-
-	list_for_each_entry_rcu(link, &dev->links.consumers, s_node,
-				device_links_read_lock_held()) {
-		if (!(link->flags & DL_FLAG_MANAGED))
-			continue;
-
-		while (refcount_dec_not_one(&link->rpm_active))
-			pm_runtime_put_noidle(dev);
-	}
-
-	device_links_read_unlock(idx);
-}
-
-/**
  * pm_runtime_get_suppliers - Resume and reference-count supplier devices.
  * @dev: Consumer device.
  */
@@ -1669,8 +1725,8 @@
 				device_links_read_lock_held())
 		if (link->flags & DL_FLAG_PM_RUNTIME) {
 			link->supplier_preactivated = true;
-			refcount_inc(&link->rpm_active);
 			pm_runtime_get_sync(link->supplier);
+			refcount_inc(&link->rpm_active);
 		}
 
 	device_links_read_unlock(idx);
@@ -1683,6 +1739,8 @@
 void pm_runtime_put_suppliers(struct device *dev)
 {
 	struct device_link *link;
+	unsigned long flags;
+	bool put;
 	int idx;
 
 	idx = device_links_read_lock();
@@ -1691,7 +1749,11 @@
 				device_links_read_lock_held())
 		if (link->supplier_preactivated) {
 			link->supplier_preactivated = false;
-			if (refcount_dec_not_one(&link->rpm_active))
+			spin_lock_irqsave(&dev->power.lock, flags);
+			put = pm_runtime_status_suspended(dev) &&
+			      refcount_dec_not_one(&link->rpm_active);
+			spin_unlock_irqrestore(&dev->power.lock, flags);
+			if (put)
 				pm_runtime_put(link->supplier);
 		}
 
@@ -1705,7 +1767,7 @@
 	spin_unlock_irq(&dev->power.lock);
 }
 
-void pm_runtime_drop_link(struct device *dev)
+static void pm_runtime_drop_link_count(struct device *dev)
 {
 	spin_lock_irq(&dev->power.lock);
 	WARN_ON(dev->power.links_count == 0);
@@ -1713,6 +1775,25 @@
 	spin_unlock_irq(&dev->power.lock);
 }
 
+/**
+ * pm_runtime_drop_link - Prepare for device link removal.
+ * @link: Device link going away.
+ *
+ * Drop the link count of the consumer end of @link and decrement the supplier
+ * device's runtime PM usage counter as many times as needed to drop all of the
+ * PM runtime reference to it from the consumer.
+ */
+void pm_runtime_drop_link(struct device_link *link)
+{
+	if (!(link->flags & DL_FLAG_PM_RUNTIME))
+		return;
+
+	pm_runtime_drop_link_count(link->consumer);
+
+	while (refcount_dec_not_one(&link->rpm_active))
+		pm_runtime_put(link->supplier);
+}
+
 static bool pm_runtime_need_not_resume(struct device *dev)
 {
 	return atomic_read(&dev->power.usage_count) <= 1 &&
@@ -1758,10 +1839,12 @@
 	 * its parent, but set its status to RPM_SUSPENDED anyway in case this
 	 * function will be called again for it in the meantime.
 	 */
-	if (pm_runtime_need_not_resume(dev))
+	if (pm_runtime_need_not_resume(dev)) {
 		pm_runtime_set_suspended(dev);
-	else
+	} else {
 		__update_runtime_status(dev, RPM_SUSPENDED);
+		dev->power.needs_force_resume = 1;
+	}
 
 	return 0;
 
@@ -1788,7 +1871,7 @@
 	int (*callback)(struct device *);
 	int ret = 0;
 
-	if (!pm_runtime_status_suspended(dev) || pm_runtime_need_not_resume(dev))
+	if (!pm_runtime_status_suspended(dev) || !dev->power.needs_force_resume)
 		goto out;
 
 	/*
@@ -1807,6 +1890,7 @@
 
 	pm_runtime_mark_last_busy(dev);
 out:
+	dev->power.needs_force_resume = 0;
 	pm_runtime_enable(dev);
 	return ret;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/power/sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/power/sysfs.c
@@ -100,7 +100,7 @@
 static ssize_t control_show(struct device *dev, struct device_attribute *attr,
 			    char *buf)
 {
-	return sprintf(buf, "%s\n",
+	return sysfs_emit(buf, "%s\n",
 				dev->power.runtime_auto ? ctrl_auto : ctrl_on);
 }
 
@@ -126,7 +126,7 @@
 	int ret;
 	u64 tmp = pm_runtime_active_time(dev);
 	do_div(tmp, NSEC_PER_MSEC);
-	ret = sprintf(buf, "%llu\n", tmp);
+	ret = sysfs_emit(buf, "%llu\n", tmp);
 	return ret;
 }
 
@@ -138,7 +138,7 @@
 	int ret;
 	u64 tmp = pm_runtime_suspended_time(dev);
 	do_div(tmp, NSEC_PER_MSEC);
-	ret = sprintf(buf, "%llu\n", tmp);
+	ret = sysfs_emit(buf, "%llu\n", tmp);
 	return ret;
 }
 
@@ -171,7 +171,7 @@
 			return -EIO;
 		}
 	}
-	return sprintf(buf, p);
+	return sysfs_emit(buf, p);
 }
 
 static DEVICE_ATTR_RO(runtime_status);
@@ -181,7 +181,7 @@
 {
 	if (!dev->power.use_autosuspend)
 		return -EIO;
-	return sprintf(buf, "%d\n", dev->power.autosuspend_delay);
+	return sysfs_emit(buf, "%d\n", dev->power.autosuspend_delay);
 }
 
 static ssize_t autosuspend_delay_ms_store(struct device *dev,
@@ -210,11 +210,11 @@
 	s32 value = dev_pm_qos_requested_resume_latency(dev);
 
 	if (value == 0)
-		return sprintf(buf, "n/a\n");
+		return sysfs_emit(buf, "n/a\n");
 	if (value == PM_QOS_RESUME_LATENCY_NO_CONSTRAINT)
 		value = 0;
 
-	return sprintf(buf, "%d\n", value);
+	return sysfs_emit(buf, "%d\n", value);
 }
 
 static ssize_t pm_qos_resume_latency_us_store(struct device *dev,
@@ -254,11 +254,11 @@
 	s32 value = dev_pm_qos_get_user_latency_tolerance(dev);
 
 	if (value < 0)
-		return sprintf(buf, "auto\n");
+		return sysfs_emit(buf, "auto\n");
 	if (value == PM_QOS_LATENCY_ANY)
-		return sprintf(buf, "any\n");
+		return sysfs_emit(buf, "any\n");
 
-	return sprintf(buf, "%d\n", value);
+	return sysfs_emit(buf, "%d\n", value);
 }
 
 static ssize_t pm_qos_latency_tolerance_us_store(struct device *dev,
@@ -290,8 +290,8 @@
 					struct device_attribute *attr,
 					char *buf)
 {
-	return sprintf(buf, "%d\n", !!(dev_pm_qos_requested_flags(dev)
-					& PM_QOS_FLAG_NO_POWER_OFF));
+	return sysfs_emit(buf, "%d\n", !!(dev_pm_qos_requested_flags(dev)
+					  & PM_QOS_FLAG_NO_POWER_OFF));
 }
 
 static ssize_t pm_qos_no_power_off_store(struct device *dev,
@@ -319,9 +319,9 @@
 static ssize_t wakeup_show(struct device *dev, struct device_attribute *attr,
 			   char *buf)
 {
-	return sprintf(buf, "%s\n", device_can_wakeup(dev)
-		? (device_may_wakeup(dev) ? _enabled : _disabled)
-		: "");
+	return sysfs_emit(buf, "%s\n", device_can_wakeup(dev)
+			  ? (device_may_wakeup(dev) ? _enabled : _disabled)
+			  : "");
 }
 
 static ssize_t wakeup_store(struct device *dev, struct device_attribute *attr,
@@ -480,6 +480,14 @@
 	return enabled ? sprintf(buf, "%lld\n", msec) : sprintf(buf, "\n");
 }
 
+static inline int dpm_sysfs_wakeup_change_owner(struct device *dev, kuid_t kuid,
+						kgid_t kgid)
+{
+	if (dev->power.wakeup && dev->power.wakeup->dev)
+		return device_change_owner(dev->power.wakeup->dev, kuid, kgid);
+	return 0;
+}
+
 static DEVICE_ATTR_RO(wakeup_last_time_ms);
 
 #ifdef CONFIG_PM_AUTOSLEEP
@@ -501,13 +509,19 @@
 
 static DEVICE_ATTR_RO(wakeup_prevent_sleep_time_ms);
 #endif /* CONFIG_PM_AUTOSLEEP */
-#endif /* CONFIG_PM_SLEEP */
+#else /* CONFIG_PM_SLEEP */
+static inline int dpm_sysfs_wakeup_change_owner(struct device *dev, kuid_t kuid,
+						kgid_t kgid)
+{
+	return 0;
+}
+#endif
 
 #ifdef CONFIG_PM_ADVANCED_DEBUG
 static ssize_t runtime_usage_show(struct device *dev,
 				  struct device_attribute *attr, char *buf)
 {
-	return sprintf(buf, "%d\n", atomic_read(&dev->power.usage_count));
+	return sysfs_emit(buf, "%d\n", atomic_read(&dev->power.usage_count));
 }
 static DEVICE_ATTR_RO(runtime_usage);
 
@@ -515,8 +529,8 @@
 					struct device_attribute *attr,
 					char *buf)
 {
-	return sprintf(buf, "%d\n", dev->power.ignore_children ?
-		0 : atomic_read(&dev->power.child_count));
+	return sysfs_emit(buf, "%d\n", dev->power.ignore_children ?
+			  0 : atomic_read(&dev->power.child_count));
 }
 static DEVICE_ATTR_RO(runtime_active_kids);
 
@@ -524,12 +538,12 @@
 				    struct device_attribute *attr, char *buf)
 {
 	if (dev->power.disable_depth && (dev->power.runtime_auto == false))
-		return sprintf(buf, "disabled & forbidden\n");
+		return sysfs_emit(buf, "disabled & forbidden\n");
 	if (dev->power.disable_depth)
-		return sprintf(buf, "disabled\n");
+		return sysfs_emit(buf, "disabled\n");
 	if (dev->power.runtime_auto == false)
-		return sprintf(buf, "forbidden\n");
-	return sprintf(buf, "enabled\n");
+		return sysfs_emit(buf, "forbidden\n");
+	return sysfs_emit(buf, "enabled\n");
 }
 static DEVICE_ATTR_RO(runtime_enabled);
 
@@ -537,9 +551,9 @@
 static ssize_t async_show(struct device *dev, struct device_attribute *attr,
 			  char *buf)
 {
-	return sprintf(buf, "%s\n",
-			device_async_suspend_enabled(dev) ?
-				_enabled : _disabled);
+	return sysfs_emit(buf, "%s\n",
+			  device_async_suspend_enabled(dev) ?
+			  _enabled : _disabled);
 }
 
 static ssize_t async_store(struct device *dev, struct device_attribute *attr,
@@ -684,6 +698,45 @@
 	return rc;
 }
 
+int dpm_sysfs_change_owner(struct device *dev, kuid_t kuid, kgid_t kgid)
+{
+	int rc;
+
+	if (device_pm_not_required(dev))
+		return 0;
+
+	rc = sysfs_group_change_owner(&dev->kobj, &pm_attr_group, kuid, kgid);
+	if (rc)
+		return rc;
+
+	if (pm_runtime_callbacks_present(dev)) {
+		rc = sysfs_group_change_owner(
+			&dev->kobj, &pm_runtime_attr_group, kuid, kgid);
+		if (rc)
+			return rc;
+	}
+
+	if (device_can_wakeup(dev)) {
+		rc = sysfs_group_change_owner(&dev->kobj, &pm_wakeup_attr_group,
+					      kuid, kgid);
+		if (rc)
+			return rc;
+
+		rc = dpm_sysfs_wakeup_change_owner(dev, kuid, kgid);
+		if (rc)
+			return rc;
+	}
+
+	if (dev->power.set_latency_tolerance) {
+		rc = sysfs_group_change_owner(
+			&dev->kobj, &pm_qos_latency_tolerance_attr_group, kuid,
+			kgid);
+		if (rc)
+			return rc;
+	}
+	return 0;
+}
+
 int wakeup_sysfs_add(struct device *dev)
 {
 	return sysfs_merge_group(&dev->kobj, &pm_wakeup_attr_group);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/power/trace.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/power/trace.c
@@ -13,6 +13,7 @@
 #include <linux/export.h>
 #include <linux/rtc.h>
 #include <linux/suspend.h>
+#include <linux/init.h>
 
 #include <linux/mc146818rtc.h>
 
@@ -165,6 +166,9 @@
 	const char *file = *(const char **)(tracedata + 2);
 	unsigned int user_hash_value, file_hash_value;
 
+	if (!x86_platform.legacy.rtc)
+		return;
+
 	user_hash_value = user % USERHASH;
 	file_hash_value = hash_string(lineno, file, FILEHASH);
 	set_magic_time(user_hash_value, file_hash_value, dev_hash_value);
@@ -267,6 +271,9 @@
 
 static int early_resume_init(void)
 {
+	if (!x86_platform.legacy.rtc)
+		return 0;
+
 	hash_value_early_read = read_magic_time();
 	register_pm_notifier(&pm_trace_nb);
 	return 0;
@@ -277,6 +284,9 @@
 	unsigned int val = hash_value_early_read;
 	unsigned int user, file, dev;
 
+	if (!x86_platform.legacy.rtc)
+		return 0;
+
 	user = val % USERHASH;
 	val = val / USERHASH;
 	file = val % FILEHASH;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/power/wakeirq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/power/wakeirq.c
@@ -145,24 +145,7 @@
 	return IRQ_HANDLED;
 }
 
-/**
- * dev_pm_set_dedicated_wake_irq - Request a dedicated wake-up interrupt
- * @dev: Device entry
- * @irq: Device wake-up interrupt
- *
- * Unless your hardware has separate wake-up interrupts in addition
- * to the device IO interrupts, you don't need this.
- *
- * Sets up a threaded interrupt handler for a device that has
- * a dedicated wake-up interrupt in addition to the device IO
- * interrupt.
- *
- * The interrupt starts disabled, and needs to be managed for
- * the device by the bus code or the device driver using
- * dev_pm_enable_wake_irq() and dev_pm_disable_wake_irq()
- * functions.
- */
-int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
+static int __dev_pm_set_dedicated_wake_irq(struct device *dev, int irq, unsigned int flag)
 {
 	struct wake_irq *wirq;
 	int err;
@@ -200,7 +183,7 @@
 	if (err)
 		goto err_free_irq;
 
-	wirq->status = WAKE_IRQ_DEDICATED_ALLOCATED;
+	wirq->status = WAKE_IRQ_DEDICATED_ALLOCATED | flag;
 
 	return err;
 
@@ -213,9 +196,58 @@
 
 	return err;
 }
+
+
+/**
+ * dev_pm_set_dedicated_wake_irq - Request a dedicated wake-up interrupt
+ * @dev: Device entry
+ * @irq: Device wake-up interrupt
+ *
+ * Unless your hardware has separate wake-up interrupts in addition
+ * to the device IO interrupts, you don't need this.
+ *
+ * Sets up a threaded interrupt handler for a device that has
+ * a dedicated wake-up interrupt in addition to the device IO
+ * interrupt.
+ *
+ * The interrupt starts disabled, and needs to be managed for
+ * the device by the bus code or the device driver using
+ * dev_pm_enable_wake_irq*() and dev_pm_disable_wake_irq*()
+ * functions.
+ */
+int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
+{
+	return __dev_pm_set_dedicated_wake_irq(dev, irq, 0);
+}
 EXPORT_SYMBOL_GPL(dev_pm_set_dedicated_wake_irq);
 
 /**
+ * dev_pm_set_dedicated_wake_irq_reverse - Request a dedicated wake-up interrupt
+ *                                         with reverse enable ordering
+ * @dev: Device entry
+ * @irq: Device wake-up interrupt
+ *
+ * Unless your hardware has separate wake-up interrupts in addition
+ * to the device IO interrupts, you don't need this.
+ *
+ * Sets up a threaded interrupt handler for a device that has a dedicated
+ * wake-up interrupt in addition to the device IO interrupt. It sets
+ * the status of WAKE_IRQ_DEDICATED_REVERSE to tell rpm_suspend()
+ * to enable dedicated wake-up interrupt after running the runtime suspend
+ * callback for @dev.
+ *
+ * The interrupt starts disabled, and needs to be managed for
+ * the device by the bus code or the device driver using
+ * dev_pm_enable_wake_irq*() and dev_pm_disable_wake_irq*()
+ * functions.
+ */
+int dev_pm_set_dedicated_wake_irq_reverse(struct device *dev, int irq)
+{
+	return __dev_pm_set_dedicated_wake_irq(dev, irq, WAKE_IRQ_DEDICATED_REVERSE);
+}
+EXPORT_SYMBOL_GPL(dev_pm_set_dedicated_wake_irq_reverse);
+
+/**
  * dev_pm_enable_wake_irq - Enable device wake-up interrupt
  * @dev: Device
  *
@@ -285,25 +317,58 @@
 	return;
 
 enable:
-	enable_irq(wirq->irq);
+	if (!can_change_status || !(wirq->status & WAKE_IRQ_DEDICATED_REVERSE)) {
+		enable_irq(wirq->irq);
+		wirq->status |= WAKE_IRQ_DEDICATED_ENABLED;
+	}
 }
 
 /**
  * dev_pm_disable_wake_irq_check - Checks and disables wake-up interrupt
  * @dev: Device
+ * @cond_disable: if set, also check WAKE_IRQ_DEDICATED_REVERSE
  *
  * Disables wake-up interrupt conditionally based on status.
  * Should be only called from rpm_suspend() and rpm_resume() path.
  */
-void dev_pm_disable_wake_irq_check(struct device *dev)
+void dev_pm_disable_wake_irq_check(struct device *dev, bool cond_disable)
 {
 	struct wake_irq *wirq = dev->power.wakeirq;
 
 	if (!wirq || !((wirq->status & WAKE_IRQ_DEDICATED_MASK)))
 		return;
 
-	if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED)
+	if (cond_disable && (wirq->status & WAKE_IRQ_DEDICATED_REVERSE))
+		return;
+
+	if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED) {
+		wirq->status &= ~WAKE_IRQ_DEDICATED_ENABLED;
 		disable_irq_nosync(wirq->irq);
+	}
+}
+
+/**
+ * dev_pm_enable_wake_irq_complete - enable wake IRQ not enabled before
+ * @dev: Device using the wake IRQ
+ *
+ * Enable wake IRQ conditionally based on status, mainly used if want to
+ * enable wake IRQ after running ->runtime_suspend() which depends on
+ * WAKE_IRQ_DEDICATED_REVERSE.
+ *
+ * Should be only called from rpm_suspend() path.
+ */
+void dev_pm_enable_wake_irq_complete(struct device *dev)
+{
+	struct wake_irq *wirq = dev->power.wakeirq;
+
+	if (!wirq || !(wirq->status & WAKE_IRQ_DEDICATED_MASK))
+		return;
+
+	if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED &&
+	    wirq->status & WAKE_IRQ_DEDICATED_REVERSE) {
+		enable_irq(wirq->irq);
+		wirq->status |= WAKE_IRQ_DEDICATED_ENABLED;
+	}
 }
 
 /**
@@ -320,7 +385,7 @@
 
 	if (device_may_wakeup(wirq->dev)) {
 		if (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED &&
-		    !pm_runtime_status_suspended(wirq->dev))
+		    !(wirq->status & WAKE_IRQ_DEDICATED_ENABLED))
 			enable_irq(wirq->irq);
 
 		enable_irq_wake(wirq->irq);
@@ -343,7 +408,7 @@
 		disable_irq_wake(wirq->irq);
 
 		if (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED &&
-		    !pm_runtime_status_suspended(wirq->dev))
+		    !(wirq->status & WAKE_IRQ_DEDICATED_ENABLED))
 			disable_irq_nosync(wirq->irq);
 	}
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/power/wakeup.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/power/wakeup.c
@@ -31,7 +31,8 @@
 bool events_check_enabled __read_mostly;
 
 /* First wakeup IRQ seen by the kernel in the last cycle. */
-unsigned int pm_wakeup_irq __read_mostly;
+static unsigned int wakeup_irq[2] __read_mostly;
+static DEFINE_RAW_SPINLOCK(wakeup_irq_lock);
 
 /* If greater than 0 and the system is suspending, terminate the suspend. */
 static atomic_t pm_abort_suspend __read_mostly;
@@ -241,7 +242,9 @@
 {
 	if (ws) {
 		wakeup_source_remove(ws);
-		wakeup_source_sysfs_remove(ws);
+		if (ws->dev)
+			wakeup_source_sysfs_remove(ws);
+
 		wakeup_source_destroy(ws);
 	}
 }
@@ -882,19 +885,45 @@
 	atomic_dec_if_positive(&pm_abort_suspend);
 }
 
-void pm_wakeup_clear(bool reset)
+void pm_wakeup_clear(unsigned int irq_number)
 {
-	pm_wakeup_irq = 0;
-	if (reset)
+	raw_spin_lock_irq(&wakeup_irq_lock);
+
+	if (irq_number && wakeup_irq[0] == irq_number)
+		wakeup_irq[0] = wakeup_irq[1];
+	else
+		wakeup_irq[0] = 0;
+
+	wakeup_irq[1] = 0;
+
+	raw_spin_unlock_irq(&wakeup_irq_lock);
+
+	if (!irq_number)
 		atomic_set(&pm_abort_suspend, 0);
 }
 
 void pm_system_irq_wakeup(unsigned int irq_number)
 {
-	if (pm_wakeup_irq == 0) {
-		pm_wakeup_irq = irq_number;
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&wakeup_irq_lock, flags);
+
+	if (wakeup_irq[0] == 0)
+		wakeup_irq[0] = irq_number;
+	else if (wakeup_irq[1] == 0)
+		wakeup_irq[1] = irq_number;
+	else
+		irq_number = 0;
+
+	raw_spin_unlock_irqrestore(&wakeup_irq_lock, flags);
+
+	if (irq_number)
 		pm_system_wakeup();
-	}
+}
+
+unsigned int pm_wakeup_irq(void)
+{
+	return wakeup_irq[0];
 }
 
 /**
@@ -1071,6 +1100,9 @@
 		break;
 	}
 
+	if (!next_ws)
+		print_wakeup_source_stats(m, &deleted_ws);
+
 	return next_ws;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/power/wakeup_stats.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/power/wakeup_stats.c
@@ -42,7 +42,7 @@
 	ktime_t active_time =
 		ws->active ? ktime_sub(ktime_get(), ws->last_time) : 0;
 
-	return sprintf(buf, "%lld\n", ktime_to_ms(active_time));
+	return sysfs_emit(buf, "%lld\n", ktime_to_ms(active_time));
 }
 static DEVICE_ATTR_RO(active_time_ms);
 
@@ -57,7 +57,7 @@
 		active_time = ktime_sub(ktime_get(), ws->last_time);
 		total_time = ktime_add(total_time, active_time);
 	}
-	return sprintf(buf, "%lld\n", ktime_to_ms(total_time));
+	return sysfs_emit(buf, "%lld\n", ktime_to_ms(total_time));
 }
 static DEVICE_ATTR_RO(total_time_ms);
 
@@ -73,7 +73,7 @@
 		if (active_time > max_time)
 			max_time = active_time;
 	}
-	return sprintf(buf, "%lld\n", ktime_to_ms(max_time));
+	return sysfs_emit(buf, "%lld\n", ktime_to_ms(max_time));
 }
 static DEVICE_ATTR_RO(max_time_ms);
 
@@ -82,7 +82,7 @@
 {
 	struct wakeup_source *ws = dev_get_drvdata(dev);
 
-	return sprintf(buf, "%lld\n", ktime_to_ms(ws->last_time));
+	return sysfs_emit(buf, "%lld\n", ktime_to_ms(ws->last_time));
 }
 static DEVICE_ATTR_RO(last_change_ms);
 
@@ -91,7 +91,7 @@
 {
 	struct wakeup_source *ws = dev_get_drvdata(dev);
 
-	return sprintf(buf, "%s\n", ws->name);
+	return sysfs_emit(buf, "%s\n", ws->name);
 }
 static DEVICE_ATTR_RO(name);
 
@@ -106,7 +106,7 @@
 		prevent_sleep_time = ktime_add(prevent_sleep_time,
 			ktime_sub(ktime_get(), ws->start_prevent_time));
 	}
-	return sprintf(buf, "%lld\n", ktime_to_ms(prevent_sleep_time));
+	return sysfs_emit(buf, "%lld\n", ktime_to_ms(prevent_sleep_time));
 }
 static DEVICE_ATTR_RO(prevent_suspend_time_ms);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/regmap/internal.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/regmap/internal.h
@@ -104,6 +104,10 @@
 	int (*reg_write)(void *context, unsigned int reg, unsigned int val);
 	int (*reg_update_bits)(void *context, unsigned int reg,
 			       unsigned int mask, unsigned int val);
+	/* Bulk read/write */
+	int (*read)(void *context, const void *reg_buf, size_t reg_size,
+		    void *val_buf, size_t val_size);
+	int (*write)(void *context, const void *data, size_t count);
 
 	bool defer_caching;
 
@@ -259,7 +263,7 @@
 int regcache_lookup_reg(struct regmap *map, unsigned int reg);
 
 int _regmap_raw_write(struct regmap *map, unsigned int reg,
-		      const void *val, size_t val_len);
+		      const void *val, size_t val_len, bool noinc);
 
 void regmap_async_complete_cb(struct regmap_async *async, int ret);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/regmap/regcache-rbtree.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/regmap/regcache-rbtree.c
@@ -277,18 +277,18 @@
 
 	blk = krealloc(rbnode->block,
 		       blklen * map->cache_word_size,
-		       GFP_KERNEL);
+		       map->alloc_flags);
 	if (!blk)
 		return -ENOMEM;
 
+	rbnode->block = blk;
+
 	if (BITS_TO_LONGS(blklen) > BITS_TO_LONGS(rbnode->blklen)) {
 		present = krealloc(rbnode->cache_present,
 				   BITS_TO_LONGS(blklen) * sizeof(*present),
-				   GFP_KERNEL);
-		if (!present) {
-			kfree(blk);
+				   map->alloc_flags);
+		if (!present)
 			return -ENOMEM;
-		}
 
 		memset(present + BITS_TO_LONGS(rbnode->blklen), 0,
 		       (BITS_TO_LONGS(blklen) - BITS_TO_LONGS(rbnode->blklen))
@@ -305,7 +305,6 @@
 	}
 
 	/* update the rbnode block, its size and the base register */
-	rbnode->block = blk;
 	rbnode->blklen = blklen;
 	rbnode->base_reg = base_reg;
 	rbnode->cache_present = present;
@@ -321,7 +320,7 @@
 	const struct regmap_range *range;
 	int i;
 
-	rbnode = kzalloc(sizeof(*rbnode), GFP_KERNEL);
+	rbnode = kzalloc(sizeof(*rbnode), map->alloc_flags);
 	if (!rbnode)
 		return NULL;
 
@@ -347,13 +346,13 @@
 	}
 
 	rbnode->block = kmalloc_array(rbnode->blklen, map->cache_word_size,
-				      GFP_KERNEL);
+				      map->alloc_flags);
 	if (!rbnode->block)
 		goto err_free;
 
 	rbnode->cache_present = kcalloc(BITS_TO_LONGS(rbnode->blklen),
 					sizeof(*rbnode->cache_present),
-					GFP_KERNEL);
+					map->alloc_flags);
 	if (!rbnode->cache_present)
 		goto err_free_block;
 
@@ -454,7 +453,8 @@
 		if (!rbnode)
 			return -ENOMEM;
 		regcache_rbtree_set_register(map, rbnode,
-					     reg - rbnode->base_reg, value);
+					     (reg - rbnode->base_reg) / map->reg_stride,
+					     value);
 		regcache_rbtree_insert(map, &rbtree_ctx->root, rbnode);
 		rbtree_ctx->cached_rbnode = rbnode;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/regmap/regcache.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/regmap/regcache.c
@@ -343,6 +343,9 @@
 	const char *name;
 	bool bypass;
 
+	if (WARN_ON(map->cache_type == REGCACHE_NONE))
+		return -EINVAL;
+
 	BUG_ON(!map->cache_ops);
 
 	map->lock(map->lock_arg);
@@ -412,6 +415,9 @@
 	const char *name;
 	bool bypass;
 
+	if (WARN_ON(map->cache_type == REGCACHE_NONE))
+		return -EINVAL;
+
 	BUG_ON(!map->cache_ops);
 
 	map->lock(map->lock_arg);
@@ -717,7 +723,7 @@
 
 	map->cache_bypass = true;
 
-	ret = _regmap_raw_write(map, base, *data, count * val_bytes);
+	ret = _regmap_raw_write(map, base, *data, count * val_bytes, false);
 	if (ret)
 		dev_err(map->dev, "Unable to sync registers %#x-%#x. %d\n",
 			base, cur - map->reg_stride, ret);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/regmap/regmap-debugfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/regmap/regmap-debugfs.c
@@ -49,7 +49,7 @@
 		name = map->dev->driver->name;
 
 	ret = snprintf(buf, PAGE_SIZE, "%s\n", name);
-	if (ret < 0) {
+	if (ret >= PAGE_SIZE) {
 		kfree(buf);
 		return ret;
 	}
@@ -227,6 +227,9 @@
 	if (*ppos < 0 || !count)
 		return -EINVAL;
 
+	if (count > (PAGE_SIZE << (MAX_ORDER - 1)))
+		count = PAGE_SIZE << (MAX_ORDER - 1);
+
 	buf = kmalloc(count, GFP_KERNEL);
 	if (!buf)
 		return -ENOMEM;
@@ -371,6 +374,9 @@
 	if (*ppos < 0 || !count)
 		return -EINVAL;
 
+	if (count > (PAGE_SIZE << (MAX_ORDER - 1)))
+		count = PAGE_SIZE << (MAX_ORDER - 1);
+
 	buf = kmalloc(count, GFP_KERNEL);
 	if (!buf)
 		return -ENOMEM;
@@ -457,29 +463,31 @@
 {
 	struct regmap *map = container_of(file->private_data,
 					  struct regmap, cache_only);
-	ssize_t result;
-	bool was_enabled, require_sync = false;
+	bool new_val, require_sync = false;
 	int err;
 
-	map->lock(map->lock_arg);
-
-	was_enabled = map->cache_only;
+	err = kstrtobool_from_user(user_buf, count, &new_val);
+	/* Ignore malforned data like debugfs_write_file_bool() */
+	if (err)
+		return count;
+
+	err = debugfs_file_get(file->f_path.dentry);
+	if (err)
+		return err;
 
-	result = debugfs_write_file_bool(file, user_buf, count, ppos);
-	if (result < 0) {
-		map->unlock(map->lock_arg);
-		return result;
-	}
+	map->lock(map->lock_arg);
 
-	if (map->cache_only && !was_enabled) {
+	if (new_val && !map->cache_only) {
 		dev_warn(map->dev, "debugfs cache_only=Y forced\n");
 		add_taint(TAINT_USER, LOCKDEP_STILL_OK);
-	} else if (!map->cache_only && was_enabled) {
+	} else if (!new_val && map->cache_only) {
 		dev_warn(map->dev, "debugfs cache_only=N forced: syncing cache\n");
 		require_sync = true;
 	}
+	map->cache_only = new_val;
 
 	map->unlock(map->lock_arg);
+	debugfs_file_put(file->f_path.dentry);
 
 	if (require_sync) {
 		err = regcache_sync(map);
@@ -487,7 +495,7 @@
 			dev_err(map->dev, "Failed to sync cache %d\n", err);
 	}
 
-	return result;
+	return count;
 }
 
 static const struct file_operations regmap_cache_only_fops = {
@@ -502,28 +510,32 @@
 {
 	struct regmap *map = container_of(file->private_data,
 					  struct regmap, cache_bypass);
-	ssize_t result;
-	bool was_enabled;
-
-	map->lock(map->lock_arg);
+	bool new_val;
+	int err;
 
-	was_enabled = map->cache_bypass;
+	err = kstrtobool_from_user(user_buf, count, &new_val);
+	/* Ignore malforned data like debugfs_write_file_bool() */
+	if (err)
+		return count;
+
+	err = debugfs_file_get(file->f_path.dentry);
+	if (err)
+		return err;
 
-	result = debugfs_write_file_bool(file, user_buf, count, ppos);
-	if (result < 0)
-		goto out;
+	map->lock(map->lock_arg);
 
-	if (map->cache_bypass && !was_enabled) {
+	if (new_val && !map->cache_bypass) {
 		dev_warn(map->dev, "debugfs cache_bypass=Y forced\n");
 		add_taint(TAINT_USER, LOCKDEP_STILL_OK);
-	} else if (!map->cache_bypass && was_enabled) {
+	} else if (!new_val && map->cache_bypass) {
 		dev_warn(map->dev, "debugfs cache_bypass=N forced\n");
 	}
+	map->cache_bypass = new_val;
 
-out:
 	map->unlock(map->lock_arg);
+	debugfs_file_put(file->f_path.dentry);
 
-	return result;
+	return count;
 }
 
 static const struct file_operations regmap_cache_bypass_fops = {
@@ -571,8 +583,12 @@
 		devname = dev_name(map->dev);
 
 	if (name) {
-		map->debugfs_name = kasprintf(GFP_KERNEL, "%s-%s",
+		if (!map->debugfs_name) {
+			map->debugfs_name = kasprintf(GFP_KERNEL, "%s-%s",
 					      devname, name);
+			if (!map->debugfs_name)
+				return;
+		}
 		name = map->debugfs_name;
 	} else {
 		name = devname;
@@ -580,9 +596,10 @@
 
 	if (!strcmp(name, "dummy")) {
 		kfree(map->debugfs_name);
-
 		map->debugfs_name = kasprintf(GFP_KERNEL, "dummy%d",
 						dummy_index);
+		if (!map->debugfs_name)
+				return;
 		name = map->debugfs_name;
 		dummy_index++;
 	}
@@ -644,6 +661,7 @@
 		regmap_debugfs_free_dump_cache(map);
 		mutex_unlock(&map->cache_lock);
 		kfree(map->debugfs_name);
+		map->debugfs_name = NULL;
 	} else {
 		struct regmap_debugfs_node *node, *tmp;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/regmap/regmap-i2c.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/regmap/regmap-i2c.c
@@ -242,6 +242,63 @@
 static struct regmap_bus regmap_i2c_smbus_i2c_block = {
 	.write = regmap_i2c_smbus_i2c_write,
 	.read = regmap_i2c_smbus_i2c_read,
+	.max_raw_read = I2C_SMBUS_BLOCK_MAX - 1,
+	.max_raw_write = I2C_SMBUS_BLOCK_MAX - 1,
+};
+
+static int regmap_i2c_smbus_i2c_write_reg16(void *context, const void *data,
+				      size_t count)
+{
+	struct device *dev = context;
+	struct i2c_client *i2c = to_i2c_client(dev);
+
+	if (count < 2)
+		return -EINVAL;
+
+	count--;
+	return i2c_smbus_write_i2c_block_data(i2c, ((u8 *)data)[0], count,
+					      (u8 *)data + 1);
+}
+
+static int regmap_i2c_smbus_i2c_read_reg16(void *context, const void *reg,
+				     size_t reg_size, void *val,
+				     size_t val_size)
+{
+	struct device *dev = context;
+	struct i2c_client *i2c = to_i2c_client(dev);
+	int ret, count, len = val_size;
+
+	if (reg_size != 2)
+		return -EINVAL;
+
+	ret = i2c_smbus_write_byte_data(i2c, ((u16 *)reg)[0] & 0xff,
+					((u16 *)reg)[0] >> 8);
+	if (ret < 0)
+		return ret;
+
+	count = 0;
+	do {
+		/* Current Address Read */
+		ret = i2c_smbus_read_byte(i2c);
+		if (ret < 0)
+			break;
+
+		*((u8 *)val++) = ret;
+		count++;
+		len--;
+	} while (len > 0);
+
+	if (count == val_size)
+		return 0;
+	else if (ret < 0)
+		return ret;
+	else
+		return -EIO;
+}
+
+static const struct regmap_bus regmap_i2c_smbus_i2c_block_reg16 = {
+	.write = regmap_i2c_smbus_i2c_write_reg16,
+	.read = regmap_i2c_smbus_i2c_read_reg16,
 	.max_raw_read = I2C_SMBUS_BLOCK_MAX,
 	.max_raw_write = I2C_SMBUS_BLOCK_MAX,
 };
@@ -255,6 +312,10 @@
 		 i2c_check_functionality(i2c->adapter,
 					 I2C_FUNC_SMBUS_I2C_BLOCK))
 		return &regmap_i2c_smbus_i2c_block;
+	else if (config->val_bits == 8 && config->reg_bits == 16 &&
+		i2c_check_functionality(i2c->adapter,
+					I2C_FUNC_SMBUS_I2C_BLOCK))
+		return &regmap_i2c_smbus_i2c_block_reg16;
 	else if (config->val_bits == 16 && config->reg_bits == 8 &&
 		 i2c_check_functionality(i2c->adapter,
 					 I2C_FUNC_SMBUS_WORD_DATA))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/regmap/regmap-irq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/regmap/regmap-irq.c
@@ -214,6 +214,7 @@
 	struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data);
 	struct regmap *map = d->map;
 	const struct regmap_irq *irq_data = irq_to_regmap_irq(d, data->hwirq);
+	unsigned int reg = irq_data->reg_offset / map->reg_stride;
 	unsigned int mask, type;
 
 	type = irq_data->type.type_falling_val | irq_data->type.type_rising_val;
@@ -230,14 +231,14 @@
 	 * at the corresponding offset in regmap_irq_set_type().
 	 */
 	if (d->chip->type_in_mask && type)
-		mask = d->type_buf[irq_data->reg_offset / map->reg_stride];
+		mask = d->type_buf[reg] & irq_data->mask;
 	else
 		mask = irq_data->mask;
 
 	if (d->chip->clear_on_unmask)
 		d->clear_status = true;
 
-	d->mask_buf[irq_data->reg_offset / map->reg_stride] &= ~mask;
+	d->mask_buf[reg] &= ~mask;
 }
 
 static void regmap_irq_disable(struct irq_data *data)
@@ -521,12 +522,16 @@
 		return IRQ_NONE;
 }
 
+static struct lock_class_key regmap_irq_lock_class;
+static struct lock_class_key regmap_irq_request_class;
+
 static int regmap_irq_map(struct irq_domain *h, unsigned int virq,
 			  irq_hw_number_t hw)
 {
 	struct regmap_irq_chip_data *data = h->host_data;
 
 	irq_set_chip_data(virq, data);
+	irq_set_lockdep_class(virq, &regmap_irq_lock_class, &regmap_irq_request_class);
 	irq_set_chip(virq, &data->irq_chip);
 	irq_set_nested_thread(virq, 1);
 	irq_set_parent(virq, data->irq);
@@ -803,6 +808,7 @@
 	kfree(d->wake_buf);
 	kfree(d->mask_buf_def);
 	kfree(d->mask_buf);
+	kfree(d->main_status_buf);
 	kfree(d->status_buf);
 	kfree(d->status_reg_buf);
 	kfree(d);
@@ -849,6 +855,7 @@
 	kfree(d->wake_buf);
 	kfree(d->mask_buf_def);
 	kfree(d->mask_buf);
+	kfree(d->main_status_buf);
 	kfree(d->status_reg_buf);
 	kfree(d->status_buf);
 	kfree(d);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/regmap/regmap-sdw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/regmap/regmap-sdw.c
@@ -12,7 +12,7 @@
 	struct device *dev = context;
 	struct sdw_slave *slave = dev_to_sdw_dev(dev);
 
-	return sdw_write(slave, reg, val);
+	return sdw_write_no_pm(slave, reg, val);
 }
 
 static int regmap_sdw_read(void *context, unsigned int reg, unsigned int *val)
@@ -21,7 +21,7 @@
 	struct sdw_slave *slave = dev_to_sdw_dev(dev);
 	int read;
 
-	read = sdw_read(slave, reg);
+	read = sdw_read_no_pm(slave, reg);
 	if (read < 0)
 		return read;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/regmap/regmap.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/regmap/regmap.c
@@ -17,6 +17,7 @@
 #include <linux/delay.h>
 #include <linux/log2.h>
 #include <linux/hwspinlock.h>
+#include <asm/unaligned.h>
 
 #define CREATE_TRACE_POINTS
 #include "trace.h"
@@ -249,22 +250,20 @@
 
 static void regmap_format_16_be(void *buf, unsigned int val, unsigned int shift)
 {
-	__be16 *b = buf;
-
-	b[0] = cpu_to_be16(val << shift);
+	put_unaligned_be16(val << shift, buf);
 }
 
 static void regmap_format_16_le(void *buf, unsigned int val, unsigned int shift)
 {
-	__le16 *b = buf;
-
-	b[0] = cpu_to_le16(val << shift);
+	put_unaligned_le16(val << shift, buf);
 }
 
 static void regmap_format_16_native(void *buf, unsigned int val,
 				    unsigned int shift)
 {
-	*(u16 *)buf = val << shift;
+	u16 v = val << shift;
+
+	memcpy(buf, &v, sizeof(v));
 }
 
 static void regmap_format_24(void *buf, unsigned int val, unsigned int shift)
@@ -280,43 +279,39 @@
 
 static void regmap_format_32_be(void *buf, unsigned int val, unsigned int shift)
 {
-	__be32 *b = buf;
-
-	b[0] = cpu_to_be32(val << shift);
+	put_unaligned_be32(val << shift, buf);
 }
 
 static void regmap_format_32_le(void *buf, unsigned int val, unsigned int shift)
 {
-	__le32 *b = buf;
-
-	b[0] = cpu_to_le32(val << shift);
+	put_unaligned_le32(val << shift, buf);
 }
 
 static void regmap_format_32_native(void *buf, unsigned int val,
 				    unsigned int shift)
 {
-	*(u32 *)buf = val << shift;
+	u32 v = val << shift;
+
+	memcpy(buf, &v, sizeof(v));
 }
 
 #ifdef CONFIG_64BIT
 static void regmap_format_64_be(void *buf, unsigned int val, unsigned int shift)
 {
-	__be64 *b = buf;
-
-	b[0] = cpu_to_be64((u64)val << shift);
+	put_unaligned_be64((u64) val << shift, buf);
 }
 
 static void regmap_format_64_le(void *buf, unsigned int val, unsigned int shift)
 {
-	__le64 *b = buf;
-
-	b[0] = cpu_to_le64((u64)val << shift);
+	put_unaligned_le64((u64) val << shift, buf);
 }
 
 static void regmap_format_64_native(void *buf, unsigned int val,
 				    unsigned int shift)
 {
-	*(u64 *)buf = (u64)val << shift;
+	u64 v = (u64) val << shift;
+
+	memcpy(buf, &v, sizeof(v));
 }
 #endif
 
@@ -333,35 +328,34 @@
 
 static unsigned int regmap_parse_16_be(const void *buf)
 {
-	const __be16 *b = buf;
-
-	return be16_to_cpu(b[0]);
+	return get_unaligned_be16(buf);
 }
 
 static unsigned int regmap_parse_16_le(const void *buf)
 {
-	const __le16 *b = buf;
-
-	return le16_to_cpu(b[0]);
+	return get_unaligned_le16(buf);
 }
 
 static void regmap_parse_16_be_inplace(void *buf)
 {
-	__be16 *b = buf;
+	u16 v = get_unaligned_be16(buf);
 
-	b[0] = be16_to_cpu(b[0]);
+	memcpy(buf, &v, sizeof(v));
 }
 
 static void regmap_parse_16_le_inplace(void *buf)
 {
-	__le16 *b = buf;
+	u16 v = get_unaligned_le16(buf);
 
-	b[0] = le16_to_cpu(b[0]);
+	memcpy(buf, &v, sizeof(v));
 }
 
 static unsigned int regmap_parse_16_native(const void *buf)
 {
-	return *(u16 *)buf;
+	u16 v;
+
+	memcpy(&v, buf, sizeof(v));
+	return v;
 }
 
 static unsigned int regmap_parse_24(const void *buf)
@@ -376,69 +370,67 @@
 
 static unsigned int regmap_parse_32_be(const void *buf)
 {
-	const __be32 *b = buf;
-
-	return be32_to_cpu(b[0]);
+	return get_unaligned_be32(buf);
 }
 
 static unsigned int regmap_parse_32_le(const void *buf)
 {
-	const __le32 *b = buf;
-
-	return le32_to_cpu(b[0]);
+	return get_unaligned_le32(buf);
 }
 
 static void regmap_parse_32_be_inplace(void *buf)
 {
-	__be32 *b = buf;
+	u32 v = get_unaligned_be32(buf);
 
-	b[0] = be32_to_cpu(b[0]);
+	memcpy(buf, &v, sizeof(v));
 }
 
 static void regmap_parse_32_le_inplace(void *buf)
 {
-	__le32 *b = buf;
+	u32 v = get_unaligned_le32(buf);
 
-	b[0] = le32_to_cpu(b[0]);
+	memcpy(buf, &v, sizeof(v));
 }
 
 static unsigned int regmap_parse_32_native(const void *buf)
 {
-	return *(u32 *)buf;
+	u32 v;
+
+	memcpy(&v, buf, sizeof(v));
+	return v;
 }
 
 #ifdef CONFIG_64BIT
 static unsigned int regmap_parse_64_be(const void *buf)
 {
-	const __be64 *b = buf;
-
-	return be64_to_cpu(b[0]);
+	return get_unaligned_be64(buf);
 }
 
 static unsigned int regmap_parse_64_le(const void *buf)
 {
-	const __le64 *b = buf;
-
-	return le64_to_cpu(b[0]);
+	return get_unaligned_le64(buf);
 }
 
 static void regmap_parse_64_be_inplace(void *buf)
 {
-	__be64 *b = buf;
+	u64 v =  get_unaligned_be64(buf);
 
-	b[0] = be64_to_cpu(b[0]);
+	memcpy(buf, &v, sizeof(v));
 }
 
 static void regmap_parse_64_le_inplace(void *buf)
 {
-	__le64 *b = buf;
+	u64 v = get_unaligned_le64(buf);
 
-	b[0] = le64_to_cpu(b[0]);
+	memcpy(buf, &v, sizeof(v));
 }
 
 static unsigned int regmap_parse_64_native(const void *buf)
 {
-	return *(u64 *)buf;
+	u64 v;
+
+	memcpy(&v, buf, sizeof(v));
+	return v;
 }
 #endif
 
@@ -611,6 +603,17 @@
 }
 EXPORT_SYMBOL_GPL(regmap_attach_dev);
 
+static int dev_get_regmap_match(struct device *dev, void *res, void *data);
+
+static int regmap_detach_dev(struct device *dev, struct regmap *map)
+{
+	if (!dev)
+		return 0;
+
+	return devres_release(dev, dev_get_regmap_release,
+			      dev_get_regmap_match, (void *)map->name);
+}
+
 static enum regmap_endian regmap_get_reg_endian(const struct regmap_bus *bus,
 					const struct regmap_config *config)
 {
@@ -779,12 +782,15 @@
 		map->reg_stride_order = ilog2(map->reg_stride);
 	else
 		map->reg_stride_order = -1;
-	map->use_single_read = config->use_single_read || !bus || !bus->read;
-	map->use_single_write = config->use_single_write || !bus || !bus->write;
-	map->can_multi_write = config->can_multi_write && bus && bus->write;
+	map->use_single_read = config->use_single_read || !(config->read || (bus && bus->read));
+	map->use_single_write = config->use_single_write || !(config->write || (bus && bus->write));
+	map->can_multi_write = config->can_multi_write && (config->write || (bus && bus->write));
 	if (bus) {
 		map->max_raw_read = bus->max_raw_read;
 		map->max_raw_write = bus->max_raw_write;
+	} else if (config->max_raw_read && config->max_raw_write) {
+		map->max_raw_read = config->max_raw_read;
+		map->max_raw_write = config->max_raw_write;
 	}
 	map->dev = dev;
 	map->bus = bus;
@@ -818,9 +824,19 @@
 		map->read_flag_mask = bus->read_flag_mask;
 	}
 
-	if (!bus) {
+	if (config && config->read && config->write) {
+		map->reg_read  = _regmap_bus_read;
+
+		/* Bulk read/write */
+		map->read = config->read;
+		map->write = config->write;
+
+		reg_endian = REGMAP_ENDIAN_NATIVE;
+		val_endian = REGMAP_ENDIAN_NATIVE;
+	} else if (!bus) {
 		map->reg_read  = config->reg_read;
 		map->reg_write = config->reg_write;
+		map->reg_update_bits = config->reg_update_bits;
 
 		map->defer_caching = false;
 		goto skip_format_initialization;
@@ -833,10 +849,13 @@
 	} else {
 		map->reg_read  = _regmap_bus_read;
 		map->reg_update_bits = bus->reg_update_bits;
-	}
+		/* Bulk read/write */
+		map->read = bus->read;
+		map->write = bus->write;
 
-	reg_endian = regmap_get_reg_endian(bus, config);
-	val_endian = regmap_get_val_endian(dev, bus, config);
+		reg_endian = regmap_get_reg_endian(bus, config);
+		val_endian = regmap_get_val_endian(dev, bus, config);
+	}
 
 	switch (config->reg_bits + map->reg_shift) {
 	case 2:
@@ -1056,13 +1075,13 @@
 
 		/* Sanity check */
 		if (range_cfg->range_max < range_cfg->range_min) {
-			dev_err(map->dev, "Invalid range %d: %d < %d\n", i,
+			dev_err(map->dev, "Invalid range %d: %u < %u\n", i,
 				range_cfg->range_max, range_cfg->range_min);
 			goto err_range;
 		}
 
 		if (range_cfg->range_max > map->max_register) {
-			dev_err(map->dev, "Invalid range %d: %d > %d\n", i,
+			dev_err(map->dev, "Invalid range %d: %u > %u\n", i,
 				range_cfg->range_max, map->max_register);
 			goto err_range;
 		}
@@ -1339,6 +1358,7 @@
 {
 	struct regmap_async *async;
 
+	regmap_detach_dev(map->dev, map);
 	regcache_exit(map);
 	regmap_debugfs_exit(map);
 	regmap_range_exit(map);
@@ -1356,6 +1376,7 @@
 	if (map->hwlock)
 		hwspin_lock_free(map->hwlock);
 	kfree_const(map->name);
+	kfree(map->patch);
 	kfree(map);
 }
 EXPORT_SYMBOL_GPL(regmap_exit);
@@ -1370,7 +1391,7 @@
 
 	/* If the user didn't specify a name match any */
 	if (data)
-		return (*r)->name == data;
+		return (*r)->name && !strcmp((*r)->name, data);
 	else
 		return 1;
 }
@@ -1475,7 +1496,7 @@
 }
 
 static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg,
-				  const void *val, size_t val_len)
+				  const void *val, size_t val_len, bool noinc)
 {
 	struct regmap_range_node *range;
 	unsigned long flags;
@@ -1486,26 +1507,33 @@
 	size_t len;
 	int i;
 
-	WARN_ON(!map->bus);
-
-	/* Check for unwritable registers before we start */
-	for (i = 0; i < val_len / map->format.val_bytes; i++)
-		if (!regmap_writeable(map,
-				     reg + regmap_get_offset(map, i)))
-			return -EINVAL;
+	/* Check for unwritable or noinc registers in range
+	 * before we start
+	 */
+	if (!regmap_writeable_noinc(map, reg)) {
+		for (i = 0; i < val_len / map->format.val_bytes; i++) {
+			unsigned int element =
+				reg + regmap_get_offset(map, i);
+			if (!regmap_writeable(map, element) ||
+				regmap_writeable_noinc(map, element))
+				return -EINVAL;
+		}
+	}
 
 	if (!map->cache_bypass && map->format.parse_val) {
-		unsigned int ival;
+		unsigned int ival, offset;
 		int val_bytes = map->format.val_bytes;
-		for (i = 0; i < val_len / val_bytes; i++) {
-			ival = map->format.parse_val(val + (i * val_bytes));
-			ret = regcache_write(map,
-					     reg + regmap_get_offset(map, i),
-					     ival);
+
+		/* Cache the last written value for noinc writes */
+		i = noinc ? val_len - val_bytes : 0;
+		for (; i < val_len; i += val_bytes) {
+			ival = map->format.parse_val(val + i);
+			offset = noinc ? 0 : regmap_get_offset(map, i / val_bytes);
+			ret = regcache_write(map, reg + offset, ival);
 			if (ret) {
 				dev_err(map->dev,
 					"Error in caching of register: %x ret: %d\n",
-					reg + i, ret);
+					reg + offset, ret);
 				return ret;
 			}
 		}
@@ -1527,7 +1555,7 @@
 				win_residue, val_len / map->format.val_bytes);
 			ret = _regmap_raw_write_impl(map, reg, val,
 						     win_residue *
-						     map->format.val_bytes);
+						     map->format.val_bytes, noinc);
 			if (ret != 0)
 				return ret;
 
@@ -1541,7 +1569,7 @@
 			win_residue = range->window_len - win_offset;
 		}
 
-		ret = _regmap_select_page(map, &reg, range, val_num);
+		ret = _regmap_select_page(map, &reg, range, noinc ? 1 : val_num);
 		if (ret != 0)
 			return ret;
 	}
@@ -1560,7 +1588,7 @@
 		val = work_val;
 	}
 
-	if (map->async && map->bus->async_write) {
+	if (map->async && map->bus && map->bus->async_write) {
 		struct regmap_async *async;
 
 		trace_regmap_async_write_start(map, reg, val_len);
@@ -1628,11 +1656,11 @@
 	 * write.
 	 */
 	if (val == work_val)
-		ret = map->bus->write(map->bus_context, map->work_buf,
-				      map->format.reg_bytes +
-				      map->format.pad_bytes +
-				      val_len);
-	else if (map->bus->gather_write)
+		ret = map->write(map->bus_context, map->work_buf,
+				 map->format.reg_bytes +
+				 map->format.pad_bytes +
+				 val_len);
+	else if (map->bus && map->bus->gather_write)
 		ret = map->bus->gather_write(map->bus_context, map->work_buf,
 					     map->format.reg_bytes +
 					     map->format.pad_bytes,
@@ -1650,7 +1678,7 @@
 		memcpy(buf, map->work_buf, map->format.reg_bytes);
 		memcpy(buf + map->format.reg_bytes + map->format.pad_bytes,
 		       val, val_len);
-		ret = map->bus->write(map->bus_context, buf, len);
+		ret = map->write(map->bus_context, buf, len);
 
 		kfree(buf);
 	} else if (ret != 0 && !map->cache_bypass && map->format.parse_val) {
@@ -1707,7 +1735,7 @@
 	struct regmap_range_node *range;
 	struct regmap *map = context;
 
-	WARN_ON(!map->bus || !map->format.format_write);
+	WARN_ON(!map->format.format_write);
 
 	range = _regmap_range_lookup(map, reg);
 	if (range) {
@@ -1720,8 +1748,7 @@
 
 	trace_regmap_hw_write_start(map, reg, 1);
 
-	ret = map->bus->write(map->bus_context, map->work_buf,
-			      map->format.buf_size);
+	ret = map->write(map->bus_context, map->work_buf, map->format.buf_size);
 
 	trace_regmap_hw_write_done(map, reg, 1);
 
@@ -1741,7 +1768,7 @@
 {
 	struct regmap *map = context;
 
-	WARN_ON(!map->bus || !map->format.format_val);
+	WARN_ON(!map->format.format_val);
 
 	map->format.format_val(map->work_buf + map->format.reg_bytes
 			       + map->format.pad_bytes, val, 0);
@@ -1749,12 +1776,13 @@
 				      map->work_buf +
 				      map->format.reg_bytes +
 				      map->format.pad_bytes,
-				      map->format.val_bytes);
+				      map->format.val_bytes,
+				      false);
 }
 
 static inline void *_regmap_map_get_context(struct regmap *map)
 {
-	return (map->bus) ? map : map->bus_context;
+	return (map->bus || (!map->bus && map->read)) ? map : map->bus_context;
 }
 
 int _regmap_write(struct regmap *map, unsigned int reg,
@@ -1843,12 +1871,14 @@
 EXPORT_SYMBOL_GPL(regmap_write_async);
 
 int _regmap_raw_write(struct regmap *map, unsigned int reg,
-		      const void *val, size_t val_len)
+		      const void *val, size_t val_len, bool noinc)
 {
 	size_t val_bytes = map->format.val_bytes;
 	size_t val_count = val_len / val_bytes;
 	size_t chunk_count, chunk_bytes;
 	size_t chunk_regs = val_count;
+	size_t max_data = map->max_raw_write - map->format.reg_bytes -
+			map->format.pad_bytes;
 	int ret, i;
 
 	if (!val_count)
@@ -1856,15 +1886,15 @@
 
 	if (map->use_single_write)
 		chunk_regs = 1;
-	else if (map->max_raw_write && val_len > map->max_raw_write)
-		chunk_regs = map->max_raw_write / val_bytes;
+	else if (map->max_raw_write && val_len > max_data)
+		chunk_regs = max_data / val_bytes;
 
 	chunk_count = val_count / chunk_regs;
 	chunk_bytes = chunk_regs * val_bytes;
 
 	/* Write as many bytes as possible with chunk_size */
 	for (i = 0; i < chunk_count; i++) {
-		ret = _regmap_raw_write_impl(map, reg, val, chunk_bytes);
+		ret = _regmap_raw_write_impl(map, reg, val, chunk_bytes, noinc);
 		if (ret)
 			return ret;
 
@@ -1875,7 +1905,7 @@
 
 	/* Write remaining bytes */
 	if (val_len)
-		ret = _regmap_raw_write_impl(map, reg, val, val_len);
+		ret = _regmap_raw_write_impl(map, reg, val, val_len, noinc);
 
 	return ret;
 }
@@ -1908,7 +1938,7 @@
 
 	map->lock(map->lock_arg);
 
-	ret = _regmap_raw_write(map, reg, val, val_len);
+	ret = _regmap_raw_write(map, reg, val, val_len, false);
 
 	map->unlock(map->lock_arg);
 
@@ -1966,7 +1996,7 @@
 			write_len = map->max_raw_write;
 		else
 			write_len = val_len;
-		ret = _regmap_raw_write(map, reg, val, write_len);
+		ret = _regmap_raw_write(map, reg, val, write_len, true);
 		if (ret)
 			goto out_unlock;
 		val = ((u8 *)val) + write_len;
@@ -2161,7 +2191,7 @@
 	u8 = buf;
 	*u8 |= map->write_flag_mask;
 
-	ret = map->bus->write(map->bus_context, buf, len);
+	ret = map->write(map->bus_context, buf, len);
 
 	kfree(buf);
 
@@ -2443,7 +2473,7 @@
 
 	map->async = true;
 
-	ret = _regmap_raw_write(map, reg, val, val_len);
+	ret = _regmap_raw_write(map, reg, val, val_len, false);
 
 	map->async = false;
 
@@ -2454,20 +2484,18 @@
 EXPORT_SYMBOL_GPL(regmap_raw_write_async);
 
 static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
-			    unsigned int val_len)
+			    unsigned int val_len, bool noinc)
 {
 	struct regmap_range_node *range;
 	int ret;
 
-	WARN_ON(!map->bus);
-
-	if (!map->bus || !map->bus->read)
+	if (!map->read)
 		return -EINVAL;
 
 	range = _regmap_range_lookup(map, reg);
 	if (range) {
 		ret = _regmap_select_page(map, &reg, range,
-					  val_len / map->format.val_bytes);
+					  noinc ? 1 : val_len / map->format.val_bytes);
 		if (ret != 0)
 			return ret;
 	}
@@ -2477,9 +2505,9 @@
 				      map->read_flag_mask);
 	trace_regmap_hw_read_start(map, reg, val_len / map->format.val_bytes);
 
-	ret = map->bus->read(map->bus_context, map->work_buf,
-			     map->format.reg_bytes + map->format.pad_bytes,
-			     val, val_len);
+	ret = map->read(map->bus_context, map->work_buf,
+			map->format.reg_bytes + map->format.pad_bytes,
+			val, val_len);
 
 	trace_regmap_hw_read_done(map, reg, val_len / map->format.val_bytes);
 
@@ -2505,7 +2533,7 @@
 	if (!map->format.parse_val)
 		return -EINVAL;
 
-	ret = _regmap_raw_read(map, reg, work_val, map->format.val_bytes);
+	ret = _regmap_raw_read(map, reg, work_val, map->format.val_bytes, false);
 	if (ret == 0)
 		*val = map->format.parse_val(work_val);
 
@@ -2590,8 +2618,6 @@
 	unsigned int v;
 	int ret, i;
 
-	if (!map->bus)
-		return -EINVAL;
 	if (val_len % map->format.val_bytes)
 		return -EINVAL;
 	if (!IS_ALIGNED(reg, map->reg_stride))
@@ -2606,7 +2632,7 @@
 		size_t chunk_count, chunk_bytes;
 		size_t chunk_regs = val_count;
 
-		if (!map->bus->read) {
+		if (!map->read) {
 			ret = -ENOTSUPP;
 			goto out;
 		}
@@ -2621,7 +2647,7 @@
 
 		/* Read bytes that fit into whole chunks */
 		for (i = 0; i < chunk_count; i++) {
-			ret = _regmap_raw_read(map, reg, val, chunk_bytes);
+			ret = _regmap_raw_read(map, reg, val, chunk_bytes, false);
 			if (ret != 0)
 				goto out;
 
@@ -2632,7 +2658,7 @@
 
 		/* Read remaining bytes */
 		if (val_len) {
-			ret = _regmap_raw_read(map, reg, val, val_len);
+			ret = _regmap_raw_read(map, reg, val, val_len, false);
 			if (ret != 0)
 				goto out;
 		}
@@ -2666,7 +2692,7 @@
  * @val: Pointer to data buffer
  * @val_len: Length of output buffer in bytes.
  *
- * The regmap API usually assumes that bulk bus read operations will read a
+ * The regmap API usually assumes that bulk read operations will read a
  * range of registers. Some devices have certain registers for which a read
  * operation read will read from an internal FIFO.
  *
@@ -2684,10 +2710,6 @@
 	size_t read_len;
 	int ret;
 
-	if (!map->bus)
-		return -EINVAL;
-	if (!map->bus->read)
-		return -ENOTSUPP;
 	if (val_len % map->format.val_bytes)
 		return -EINVAL;
 	if (!IS_ALIGNED(reg, map->reg_stride))
@@ -2707,7 +2729,7 @@
 			read_len = map->max_raw_read;
 		else
 			read_len = val_len;
-		ret = _regmap_raw_read(map, reg, val, read_len);
+		ret = _regmap_raw_read(map, reg, val, read_len, true);
 		if (ret)
 			goto out_unlock;
 		val = ((u8 *)val) + read_len;
@@ -2801,7 +2823,7 @@
 	if (val_count == 0)
 		return -EINVAL;
 
-	if (map->bus && map->format.parse_inplace && (vol || map->cache_type == REGCACHE_NONE)) {
+	if (map->format.parse_inplace && (vol || map->cache_type == REGCACHE_NONE)) {
 		ret = regmap_raw_read(map, reg, val, val_bytes * val_count);
 		if (ret != 0)
 			return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/soc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/soc.c
@@ -76,15 +76,15 @@
 	struct soc_device *soc_dev = container_of(dev, struct soc_device, dev);
 
 	if (attr == &dev_attr_machine)
-		return sprintf(buf, "%s\n", soc_dev->attr->machine);
+		return sysfs_emit(buf, "%s\n", soc_dev->attr->machine);
 	if (attr == &dev_attr_family)
-		return sprintf(buf, "%s\n", soc_dev->attr->family);
+		return sysfs_emit(buf, "%s\n", soc_dev->attr->family);
 	if (attr == &dev_attr_revision)
-		return sprintf(buf, "%s\n", soc_dev->attr->revision);
+		return sysfs_emit(buf, "%s\n", soc_dev->attr->revision);
 	if (attr == &dev_attr_serial_number)
-		return sprintf(buf, "%s\n", soc_dev->attr->serial_number);
+		return sysfs_emit(buf, "%s\n", soc_dev->attr->serial_number);
 	if (attr == &dev_attr_soc_id)
-		return sprintf(buf, "%s\n", soc_dev->attr->soc_id);
+		return sysfs_emit(buf, "%s\n", soc_dev->attr->soc_id);
 
 	return -EINVAL;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/swnode.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/swnode.c
@@ -520,7 +520,10 @@
 {
 	struct swnode *swnode = to_swnode(fwnode);
 
-	return swnode ? (swnode->parent ? &swnode->parent->fwnode : NULL) : NULL;
+	if (!swnode || !swnode->parent)
+		return NULL;
+
+	return fwnode_handle_get(&swnode->parent->fwnode);
 }
 
 static struct fwnode_handle *
@@ -531,14 +534,18 @@
 	struct swnode *c = to_swnode(child);
 
 	if (!p || list_empty(&p->children) ||
-	    (c && list_is_last(&c->entry, &p->children)))
+	    (c && list_is_last(&c->entry, &p->children))) {
+		fwnode_handle_put(child);
 		return NULL;
+	}
 
 	if (c)
 		c = list_next_entry(c, entry);
 	else
 		c = list_first_entry(&p->children, struct swnode, entry);
-	return &c->fwnode;
+
+	fwnode_handle_put(child);
+	return fwnode_handle_get(&c->fwnode);
 }
 
 static struct fwnode_handle *
@@ -597,6 +604,9 @@
 	if (nargs > NR_FWNODE_REFERENCE_ARGS)
 		return -EINVAL;
 
+	if (!args)
+		return 0;
+
 	args->fwnode = software_node_get(refnode);
 	args->nargs = nargs;
 
@@ -676,6 +686,13 @@
 {
 	struct swnode *swnode = kobj_to_swnode(kobj);
 
+	if (swnode->parent) {
+		ida_simple_remove(&swnode->parent->child_ids, swnode->id);
+		list_del(&swnode->entry);
+	} else {
+		ida_simple_remove(&swnode_root_ids, swnode->id);
+	}
+
 	if (swnode->allocated) {
 		property_entries_free(swnode->node->properties);
 		kfree(swnode->node);
@@ -798,6 +815,9 @@
 	if (software_node_to_swnode(node))
 		return -EEXIST;
 
+	if (node->parent && !parent)
+		return -EINVAL;
+
 	return PTR_ERR_OR_ZERO(swnode_register(node, parent, 0));
 }
 EXPORT_SYMBOL_GPL(software_node_register);
@@ -841,13 +861,6 @@
 	if (!swnode)
 		return;
 
-	if (swnode->parent) {
-		ida_simple_remove(&swnode->parent->child_ids, swnode->id);
-		list_del(&swnode->entry);
-	} else {
-		ida_simple_remove(&swnode_root_ids, swnode->id);
-	}
-
 	kobject_put(&swnode->kobj);
 }
 EXPORT_SYMBOL_GPL(fwnode_remove_software_node);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/base/test/test_async_driver_probe.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/base/test/test_async_driver_probe.c
@@ -44,7 +44,8 @@
 	 * performing an async init on that node.
 	 */
 	if (dev->driver->probe_type == PROBE_PREFER_ASYNCHRONOUS) {
-		if (dev_to_node(dev) != numa_node_id()) {
+		if (IS_ENABLED(CONFIG_NUMA) &&
+		    dev_to_node(dev) != numa_node_id()) {
 			dev_warn(dev, "NUMA node mismatch %d != %d\n",
 				 dev_to_node(dev), numa_node_id());
 			atomic_inc(&warnings);
@@ -83,7 +84,7 @@
 
 	pdev = platform_device_alloc(name, id);
 	if (!pdev)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 
 	if (nid != NUMA_NO_NODE)
 		set_dev_node(&pdev->dev, nid);
@@ -145,7 +146,7 @@
 	calltime = ktime_get();
 	for_each_online_cpu(cpu) {
 		nid = cpu_to_node(cpu);
-		pdev = &sync_dev[sync_id];
+		pdev = &async_dev[async_id];
 
 		*pdev = test_platform_device_register_node("test_async_driver",
 							   async_id,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/bcma/main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/bcma/main.c
@@ -236,6 +236,7 @@
 
 void bcma_prepare_core(struct bcma_bus *bus, struct bcma_device *core)
 {
+	device_initialize(&core->dev);
 	core->dev.release = bcma_release_core_dev;
 	core->dev.bus = &bcma_bus_type;
 	dev_set_name(&core->dev, "bcma%d:%d", bus->num, core->core_index);
@@ -277,11 +278,10 @@
 {
 	int err;
 
-	err = device_register(&core->dev);
+	err = device_add(&core->dev);
 	if (err) {
 		bcma_err(bus, "Could not register dev for core 0x%03X\n",
 			 core->id.id);
-		put_device(&core->dev);
 		return;
 	}
 	core->dev_registered = true;
@@ -372,7 +372,7 @@
 	/* Now noone uses internally-handled cores, we can free them */
 	list_for_each_entry_safe(core, tmp, &bus->cores, list) {
 		list_del(&core->list);
-		kfree(core);
+		put_device(&core->dev);
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/block/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/block/Kconfig
@@ -39,6 +39,22 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called floppy.
 
+config BLK_DEV_FD_RAWCMD
+	bool "Support for raw floppy disk commands (DEPRECATED)"
+	depends on BLK_DEV_FD
+	help
+	  If you want to use actual physical floppies and expect to do
+	  special low-level hardware accesses to them (access and use
+	  non-standard formats, for example), then enable this.
+
+	  Note that the code enabled by this option is rarely used and
+	  might be unstable or insecure, and distros should not enable it.
+
+	  Note: FDRAWCMD is deprecated and will be removed from the kernel
+	  in the near future.
+
+	  If unsure, say N.
+
 config AMIGA_FLOPPY
 	tristate "Amiga floppy support"
 	depends on AMIGA
@@ -230,7 +246,7 @@
 	  dynamically allocated with the /dev/loop-control interface.
 
 config BLK_DEV_CRYPTOLOOP
-	tristate "Cryptoloop Support"
+	tristate "Cryptoloop Support (DEPRECATED)"
 	select CRYPTO
 	select CRYPTO_CBC
 	depends on BLK_DEV_LOOP
@@ -242,7 +258,7 @@
 	  WARNING: This device is not safe for journaled file systems like
 	  ext3 or Reiserfs. Please use the Device Mapper crypto module
 	  instead, which can be configured to be on-disk compatible with the
-	  cryptoloop device.
+	  cryptoloop device.  cryptoloop support will be removed in Linux 5.16.
 
 source "drivers/block/drbd/Kconfig"
 
@@ -283,15 +299,6 @@
 
 	Use device /dev/skd$N amd /dev/skd$Np$M.
 
-config BLK_DEV_SX8
-	tristate "Promise SATA SX8 support"
-	depends on PCI
-	---help---
-	  Saying Y or M here will enable support for the 
-	  Promise SATA SX8 controllers.
-
-	  Use devices /dev/sx8/$N and /dev/sx8/$Np$M.
-
 config BLK_DEV_RAM
 	tristate "RAM block device support"
 	---help---
@@ -461,6 +468,7 @@
 config BLK_DEV_RSXX
 	tristate "IBM Flash Adapter 900GB Full Height PCIe Device Driver"
 	depends on PCI
+	select CRC32
 	help
 	  Device driver for IBM's high speed PCIe SSD
 	  storage device: Flash Adapter 900GB Full Height.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/block/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/block/Makefile
@@ -26,8 +26,6 @@
 obj-$(CONFIG_BLK_DEV_CRYPTOLOOP) += cryptoloop.o
 obj-$(CONFIG_VIRTIO_BLK)	+= virtio_blk.o
 
-obj-$(CONFIG_BLK_DEV_SX8)	+= sx8.o
-
 obj-$(CONFIG_XEN_BLKDEV_FRONTEND)	+= xen-blkfront.o
 obj-$(CONFIG_XEN_BLKDEV_BACKEND)	+= xen-blkback/
 obj-$(CONFIG_BLK_DEV_DRBD)     += drbd/
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/block/aoe/aoecmd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/block/aoe/aoecmd.c
@@ -362,6 +362,7 @@
 	}
 
 	ah->cmdstat = ATA_CMD_PIO_READ | writebit | extbit;
+	dev_hold(t->ifp->nd);
 	skb->dev = t->ifp->nd;
 }
 
@@ -402,6 +403,8 @@
 		__skb_queue_head_init(&queue);
 		__skb_queue_tail(&queue, skb);
 		aoenet_xmit(&queue);
+	} else {
+		dev_put(f->t->ifp->nd);
 	}
 	return 1;
 }
@@ -420,13 +423,16 @@
 	rcu_read_lock();
 	for_each_netdev_rcu(&init_net, ifp) {
 		dev_hold(ifp);
-		if (!is_aoe_netif(ifp))
-			goto cont;
+		if (!is_aoe_netif(ifp)) {
+			dev_put(ifp);
+			continue;
+		}
 
 		skb = new_skb(sizeof *h + sizeof *ch);
 		if (skb == NULL) {
 			printk(KERN_INFO "aoe: skb alloc failure\n");
-			goto cont;
+			dev_put(ifp);
+			continue;
 		}
 		skb_put(skb, sizeof *h + sizeof *ch);
 		skb->dev = ifp;
@@ -441,9 +447,6 @@
 		h->major = cpu_to_be16(aoemajor);
 		h->minor = aoeminor;
 		h->cmd = AOECMD_CFG;
-
-cont:
-		dev_put(ifp);
 	}
 	rcu_read_unlock();
 }
@@ -484,10 +487,13 @@
 	memcpy(h->dst, t->addr, sizeof h->dst);
 	memcpy(h->src, t->ifp->nd->dev_addr, sizeof h->src);
 
+	dev_hold(t->ifp->nd);
 	skb->dev = t->ifp->nd;
 	skb = skb_clone(skb, GFP_ATOMIC);
-	if (skb == NULL)
+	if (skb == NULL) {
+		dev_put(t->ifp->nd);
 		return;
+	}
 	f->sent = ktime_get();
 	__skb_queue_head_init(&queue);
 	__skb_queue_tail(&queue, skb);
@@ -618,6 +624,8 @@
 		__skb_queue_head_init(&queue);
 		__skb_queue_tail(&queue, skb);
 		aoenet_xmit(&queue);
+	} else {
+		dev_put(f->t->ifp->nd);
 	}
 }
 
@@ -1405,6 +1413,7 @@
 	ah->cmdstat = ATA_CMD_ID_ATA;
 	ah->lba3 = 0xa0;
 
+	dev_hold(t->ifp->nd);
 	skb->dev = t->ifp->nd;
 
 	d->rttavg = RTTAVG_INIT;
@@ -1414,6 +1423,8 @@
 	skb = skb_clone(skb, GFP_ATOMIC);
 	if (skb)
 		f->sent = ktime_get();
+	else
+		dev_put(t->ifp->nd);
 
 	return skb;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/block/aoe/aoenet.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/block/aoe/aoenet.c
@@ -64,6 +64,7 @@
 			pr_warn("aoe: packet could not be sent on %s.  %s\n",
 				ifp ? ifp->name : "netif",
 				"consider increasing tx_queue_len");
+		dev_put(ifp);
 		spin_lock_irq(&txlock);
 	}
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/block/ataflop.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/block/ataflop.c
@@ -653,9 +653,6 @@
 		*p2++ = *p1++;
 }
 
-  
-  
-
 /* General Interrupt Handling */
 
 static void (*FloppyIRQHandler)( int status ) = NULL;
@@ -1225,6 +1222,7 @@
 	}
 	else {
 		/* all sectors finished */
+		finish_fdc();
 		fd_end_request_cur(BLK_STS_OK);
 	}
 	return;
@@ -1472,15 +1470,6 @@
 			ReqTrack, ReqSector, (unsigned long)ReqData ));
 }
 
-static void ataflop_commit_rqs(struct blk_mq_hw_ctx *hctx)
-{
-	spin_lock_irq(&ataflop_lock);
-	atari_disable_irq(IRQ_MFP_FDC);
-	finish_fdc();
-	atari_enable_irq(IRQ_MFP_FDC);
-	spin_unlock_irq(&ataflop_lock);
-}
-
 static blk_status_t ataflop_queue_rq(struct blk_mq_hw_ctx *hctx,
 				     const struct blk_mq_queue_data *bd)
 {
@@ -1488,6 +1477,8 @@
 	int drive = floppy - unit;
 	int type = floppy->type;
 
+	DPRINT(("Queue request: drive %d type %d last %d\n", drive, type, bd->last));
+
 	spin_lock_irq(&ataflop_lock);
 	if (fd_request) {
 		spin_unlock_irq(&ataflop_lock);
@@ -1547,8 +1538,6 @@
 	setup_req_params( drive );
 	do_fd_action( drive );
 
-	if (bd->last)
-		finish_fdc();
 	atari_enable_irq( IRQ_MFP_FDC );
 
 out:
@@ -1958,7 +1947,6 @@
 
 static const struct blk_mq_ops ataflop_mq_ops = {
 	.queue_rq = ataflop_queue_rq,
-	.commit_rqs = ataflop_commit_rqs,
 };
 
 static struct kobject *floppy_find(dev_t dev, int *part, void *data)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/block/brd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/block/brd.c
@@ -470,6 +470,25 @@
 	return kobj;
 }
 
+static inline void brd_check_and_reset_par(void)
+{
+	if (unlikely(!max_part))
+		max_part = 1;
+
+	/*
+	 * make sure 'max_part' can be divided exactly by (1U << MINORBITS),
+	 * otherwise, it is possiable to get same dev_t when adding partitions.
+	 */
+	if ((1U << MINORBITS) % max_part != 0)
+		max_part = 1UL << fls(max_part);
+
+	if (max_part > DISK_MAX_PARTS) {
+		pr_info("brd: max_part can't be larger than %d, reset max_part = %d.\n",
+			DISK_MAX_PARTS, DISK_MAX_PARTS);
+		max_part = DISK_MAX_PARTS;
+	}
+}
+
 static int __init brd_init(void)
 {
 	struct brd_device *brd, *next;
@@ -493,8 +512,7 @@
 	if (register_blkdev(RAMDISK_MAJOR, "ramdisk"))
 		return -EIO;
 
-	if (unlikely(!max_part))
-		max_part = 1;
+	brd_check_and_reset_par();
 
 	for (i = 0; i < rd_nr; i++) {
 		brd = brd_alloc(i);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/block/cryptoloop.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/block/cryptoloop.c
@@ -189,6 +189,8 @@
 
 	if (rc)
 		printk(KERN_ERR "cryptoloop: loop_register_transfer failed\n");
+	else
+		pr_warn("the cryptoloop driver has been deprecated and will be removed in in Linux 5.16\n");
 	return rc;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/block/drbd/drbd_int.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/block/drbd/drbd_int.h
@@ -1673,22 +1673,22 @@
 };
 void drbd_bcast_event(struct drbd_device *device, const struct sib_info *sib);
 
-extern void notify_resource_state(struct sk_buff *,
+extern int notify_resource_state(struct sk_buff *,
 				  unsigned int,
 				  struct drbd_resource *,
 				  struct resource_info *,
 				  enum drbd_notification_type);
-extern void notify_device_state(struct sk_buff *,
+extern int notify_device_state(struct sk_buff *,
 				unsigned int,
 				struct drbd_device *,
 				struct device_info *,
 				enum drbd_notification_type);
-extern void notify_connection_state(struct sk_buff *,
+extern int notify_connection_state(struct sk_buff *,
 				    unsigned int,
 				    struct drbd_connection *,
 				    struct connection_info *,
 				    enum drbd_notification_type);
-extern void notify_peer_device_state(struct sk_buff *,
+extern int notify_peer_device_state(struct sk_buff *,
 				     unsigned int,
 				     struct drbd_peer_device *,
 				     struct peer_device_info *,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/block/drbd/drbd_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/block/drbd/drbd_main.c
@@ -183,7 +183,7 @@
 		unsigned int set_size)
 {
 	struct drbd_request *r;
-	struct drbd_request *req = NULL;
+	struct drbd_request *req = NULL, *tmp = NULL;
 	int expect_epoch = 0;
 	int expect_size = 0;
 
@@ -237,8 +237,11 @@
 	 * to catch requests being barrier-acked "unexpectedly".
 	 * It usually should find the same req again, or some READ preceding it. */
 	list_for_each_entry(req, &connection->transfer_log, tl_requests)
-		if (req->epoch == expect_epoch)
+		if (req->epoch == expect_epoch) {
+			tmp = req;
 			break;
+		}
+	req = list_prepare_entry(tmp, &connection->transfer_log, tl_requests);
 	list_for_each_entry_safe_from(req, r, &connection->transfer_log, tl_requests) {
 		if (req->epoch != expect_epoch)
 			break;
@@ -2775,7 +2778,7 @@
 enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsigned int minor)
 {
 	struct drbd_resource *resource = adm_ctx->resource;
-	struct drbd_connection *connection;
+	struct drbd_connection *connection, *n;
 	struct drbd_device *device;
 	struct drbd_peer_device *peer_device, *tmp_peer_device;
 	struct gendisk *disk;
@@ -2903,7 +2906,7 @@
 out_idr_remove_vol:
 	idr_remove(&connection->peer_devices, vnr);
 out_idr_remove_from_resource:
-	for_each_connection(connection, resource) {
+	for_each_connection_safe(connection, n, resource) {
 		peer_device = idr_remove(&connection->peer_devices, vnr);
 		if (peer_device)
 			kref_put(&connection->kref, drbd_destroy_connection);
@@ -3506,10 +3509,12 @@
 void drbd_uuid_set_bm(struct drbd_device *device, u64 val) __must_hold(local)
 {
 	unsigned long flags;
-	if (device->ldev->md.uuid[UI_BITMAP] == 0 && val == 0)
+	spin_lock_irqsave(&device->ldev->md.uuid_lock, flags);
+	if (device->ldev->md.uuid[UI_BITMAP] == 0 && val == 0) {
+		spin_unlock_irqrestore(&device->ldev->md.uuid_lock, flags);
 		return;
+	}
 
-	spin_lock_irqsave(&device->ldev->md.uuid_lock, flags);
 	if (val == 0) {
 		drbd_uuid_move_history(device);
 		device->ldev->md.uuid[UI_HISTORY_START] = device->ldev->md.uuid[UI_BITMAP];
@@ -3706,9 +3711,8 @@
 	 * when we want to support more than
 	 * one PRO_VERSION */
 	static const char *cmdnames[] = {
+
 		[P_DATA]	        = "Data",
-		[P_WSAME]	        = "WriteSame",
-		[P_TRIM]	        = "Trim",
 		[P_DATA_REPLY]	        = "DataReply",
 		[P_RS_DATA_REPLY]	= "RSDataReply",
 		[P_BARRIER]	        = "Barrier",
@@ -3719,7 +3723,6 @@
 		[P_DATA_REQUEST]	= "DataRequest",
 		[P_RS_DATA_REQUEST]     = "RSDataRequest",
 		[P_SYNC_PARAM]	        = "SyncParam",
-		[P_SYNC_PARAM89]	= "SyncParam89",
 		[P_PROTOCOL]            = "ReportProtocol",
 		[P_UUIDS]	        = "ReportUUIDs",
 		[P_SIZES]	        = "ReportSizes",
@@ -3727,6 +3730,7 @@
 		[P_SYNC_UUID]           = "ReportSyncUUID",
 		[P_AUTH_CHALLENGE]      = "AuthChallenge",
 		[P_AUTH_RESPONSE]	= "AuthResponse",
+		[P_STATE_CHG_REQ]       = "StateChgRequest",
 		[P_PING]		= "Ping",
 		[P_PING_ACK]	        = "PingAck",
 		[P_RECV_ACK]	        = "RecvAck",
@@ -3737,24 +3741,26 @@
 		[P_NEG_DREPLY]	        = "NegDReply",
 		[P_NEG_RS_DREPLY]	= "NegRSDReply",
 		[P_BARRIER_ACK]	        = "BarrierAck",
-		[P_STATE_CHG_REQ]       = "StateChgRequest",
 		[P_STATE_CHG_REPLY]     = "StateChgReply",
 		[P_OV_REQUEST]          = "OVRequest",
 		[P_OV_REPLY]            = "OVReply",
 		[P_OV_RESULT]           = "OVResult",
 		[P_CSUM_RS_REQUEST]     = "CsumRSRequest",
 		[P_RS_IS_IN_SYNC]	= "CsumRSIsInSync",
+		[P_SYNC_PARAM89]	= "SyncParam89",
 		[P_COMPRESSED_BITMAP]   = "CBitmap",
 		[P_DELAY_PROBE]         = "DelayProbe",
 		[P_OUT_OF_SYNC]		= "OutOfSync",
-		[P_RETRY_WRITE]		= "RetryWrite",
 		[P_RS_CANCEL]		= "RSCancel",
 		[P_CONN_ST_CHG_REQ]	= "conn_st_chg_req",
 		[P_CONN_ST_CHG_REPLY]	= "conn_st_chg_reply",
 		[P_RETRY_WRITE]		= "retry_write",
 		[P_PROTOCOL_UPDATE]	= "protocol_update",
+		[P_TRIM]	        = "Trim",
 		[P_RS_THIN_REQ]         = "rs_thin_req",
 		[P_RS_DEALLOCATED]      = "rs_deallocated",
+		[P_WSAME]	        = "WriteSame",
+		[P_ZEROES]		= "Zeroes",
 
 		/* enum drbd_packet, but not commands - obsoleted flags:
 		 *	P_MAY_IGNORE
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/block/drbd/drbd_nl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/block/drbd/drbd_nl.c
@@ -791,9 +791,11 @@
 	mutex_lock(&adm_ctx.resource->adm_mutex);
 
 	if (info->genlhdr->cmd == DRBD_ADM_PRIMARY)
-		retcode = drbd_set_role(adm_ctx.device, R_PRIMARY, parms.assume_uptodate);
+		retcode = (enum drbd_ret_code)drbd_set_role(adm_ctx.device,
+						R_PRIMARY, parms.assume_uptodate);
 	else
-		retcode = drbd_set_role(adm_ctx.device, R_SECONDARY, 0);
+		retcode = (enum drbd_ret_code)drbd_set_role(adm_ctx.device,
+						R_SECONDARY, 0);
 
 	mutex_unlock(&adm_ctx.resource->adm_mutex);
 	genl_lock();
@@ -1971,7 +1973,7 @@
 	drbd_flush_workqueue(&connection->sender_work);
 
 	rv = _drbd_request_state(device, NS(disk, D_ATTACHING), CS_VERBOSE);
-	retcode = rv;  /* FIXME: Type mismatch. */
+	retcode = (enum drbd_ret_code)rv;
 	drbd_resume_io(device);
 	if (rv < SS_SUCCESS)
 		goto fail;
@@ -2696,7 +2698,8 @@
 	}
 	rcu_read_unlock();
 
-	retcode = conn_request_state(connection, NS(conn, C_UNCONNECTED), CS_VERBOSE);
+	retcode = (enum drbd_ret_code)conn_request_state(connection,
+					NS(conn, C_UNCONNECTED), CS_VERBOSE);
 
 	conn_reconfig_done(connection);
 	mutex_unlock(&adm_ctx.resource->adm_mutex);
@@ -2809,7 +2812,7 @@
 	mutex_lock(&adm_ctx.resource->adm_mutex);
 	rv = conn_try_disconnect(connection, parms.force_disconnect);
 	if (rv < SS_SUCCESS)
-		retcode = rv;  /* FIXME: Type mismatch. */
+		retcode = (enum drbd_ret_code)rv;
 	else
 		retcode = NO_ERROR;
 	mutex_unlock(&adm_ctx.resource->adm_mutex);
@@ -3423,7 +3426,7 @@
 {
 	struct nlattr *resource_filter;
 	struct drbd_resource *resource;
-	struct drbd_device *uninitialized_var(device);
+	struct drbd_device *device;
 	int minor, err, retcode;
 	struct drbd_genlmsghdr *dh;
 	struct device_info device_info;
@@ -3512,7 +3515,7 @@
 {
 	struct nlattr *resource_filter;
 	struct drbd_resource *resource = NULL, *next_resource;
-	struct drbd_connection *uninitialized_var(connection);
+	struct drbd_connection *connection;
 	int err = 0, retcode;
 	struct drbd_genlmsghdr *dh;
 	struct connection_info connection_info;
@@ -3674,7 +3677,7 @@
 {
 	struct nlattr *resource_filter;
 	struct drbd_resource *resource;
-	struct drbd_device *uninitialized_var(device);
+	struct drbd_device *device;
 	struct drbd_peer_device *peer_device = NULL;
 	int minor, err, retcode;
 	struct drbd_genlmsghdr *dh;
@@ -4630,7 +4633,7 @@
 	return drbd_notification_header_to_skb(msg, &nh, true);
 }
 
-void notify_resource_state(struct sk_buff *skb,
+int notify_resource_state(struct sk_buff *skb,
 			   unsigned int seq,
 			   struct drbd_resource *resource,
 			   struct resource_info *resource_info,
@@ -4672,16 +4675,17 @@
 		if (err && err != -ESRCH)
 			goto failed;
 	}
-	return;
+	return 0;
 
 nla_put_failure:
 	nlmsg_free(skb);
 failed:
 	drbd_err(resource, "Error %d while broadcasting event. Event seq:%u\n",
 			err, seq);
+	return err;
 }
 
-void notify_device_state(struct sk_buff *skb,
+int notify_device_state(struct sk_buff *skb,
 			 unsigned int seq,
 			 struct drbd_device *device,
 			 struct device_info *device_info,
@@ -4721,16 +4725,17 @@
 		if (err && err != -ESRCH)
 			goto failed;
 	}
-	return;
+	return 0;
 
 nla_put_failure:
 	nlmsg_free(skb);
 failed:
 	drbd_err(device, "Error %d while broadcasting event. Event seq:%u\n",
 		 err, seq);
+	return err;
 }
 
-void notify_connection_state(struct sk_buff *skb,
+int notify_connection_state(struct sk_buff *skb,
 			     unsigned int seq,
 			     struct drbd_connection *connection,
 			     struct connection_info *connection_info,
@@ -4770,16 +4775,17 @@
 		if (err && err != -ESRCH)
 			goto failed;
 	}
-	return;
+	return 0;
 
 nla_put_failure:
 	nlmsg_free(skb);
 failed:
 	drbd_err(connection, "Error %d while broadcasting event. Event seq:%u\n",
 		 err, seq);
+	return err;
 }
 
-void notify_peer_device_state(struct sk_buff *skb,
+int notify_peer_device_state(struct sk_buff *skb,
 			      unsigned int seq,
 			      struct drbd_peer_device *peer_device,
 			      struct peer_device_info *peer_device_info,
@@ -4820,13 +4826,14 @@
 		if (err && err != -ESRCH)
 			goto failed;
 	}
-	return;
+	return 0;
 
 nla_put_failure:
 	nlmsg_free(skb);
 failed:
 	drbd_err(peer_device, "Error %d while broadcasting event. Event seq:%u\n",
 		 err, seq);
+	return err;
 }
 
 void notify_helper(enum drbd_notification_type type,
@@ -4877,7 +4884,7 @@
 		 err, seq);
 }
 
-static void notify_initial_state_done(struct sk_buff *skb, unsigned int seq)
+static int notify_initial_state_done(struct sk_buff *skb, unsigned int seq)
 {
 	struct drbd_genlmsghdr *dh;
 	int err;
@@ -4891,11 +4898,12 @@
 	if (nla_put_notification_header(skb, NOTIFY_EXISTS))
 		goto nla_put_failure;
 	genlmsg_end(skb, dh);
-	return;
+	return 0;
 
 nla_put_failure:
 	nlmsg_free(skb);
 	pr_err("Error %d sending event. Event seq:%u\n", err, seq);
+	return err;
 }
 
 static void free_state_changes(struct list_head *list)
@@ -4922,6 +4930,7 @@
 	unsigned int seq = cb->args[2];
 	unsigned int n;
 	enum drbd_notification_type flags = 0;
+	int err = 0;
 
 	/* There is no need for taking notification_mutex here: it doesn't
 	   matter if the initial state events mix with later state chage
@@ -4930,32 +4939,32 @@
 
 	cb->args[5]--;
 	if (cb->args[5] == 1) {
-		notify_initial_state_done(skb, seq);
+		err = notify_initial_state_done(skb, seq);
 		goto out;
 	}
 	n = cb->args[4]++;
 	if (cb->args[4] < cb->args[3])
 		flags |= NOTIFY_CONTINUES;
 	if (n < 1) {
-		notify_resource_state_change(skb, seq, state_change->resource,
+		err = notify_resource_state_change(skb, seq, state_change->resource,
 					     NOTIFY_EXISTS | flags);
 		goto next;
 	}
 	n--;
 	if (n < state_change->n_connections) {
-		notify_connection_state_change(skb, seq, &state_change->connections[n],
+		err = notify_connection_state_change(skb, seq, &state_change->connections[n],
 					       NOTIFY_EXISTS | flags);
 		goto next;
 	}
 	n -= state_change->n_connections;
 	if (n < state_change->n_devices) {
-		notify_device_state_change(skb, seq, &state_change->devices[n],
+		err = notify_device_state_change(skb, seq, &state_change->devices[n],
 					   NOTIFY_EXISTS | flags);
 		goto next;
 	}
 	n -= state_change->n_devices;
 	if (n < state_change->n_devices * state_change->n_connections) {
-		notify_peer_device_state_change(skb, seq, &state_change->peer_devices[n],
+		err = notify_peer_device_state_change(skb, seq, &state_change->peer_devices[n],
 						NOTIFY_EXISTS | flags);
 		goto next;
 	}
@@ -4970,7 +4979,10 @@
 		cb->args[4] = 0;
 	}
 out:
-	return skb->len;
+	if (err)
+		return err;
+	else
+		return skb->len;
 }
 
 int drbd_adm_get_initial_state(struct sk_buff *skb, struct netlink_callback *cb)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/block/drbd/drbd_receiver.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/block/drbd/drbd_receiver.c
@@ -1298,7 +1298,7 @@
 	bio_set_dev(bio, device->ldev->backing_bdev);
 	bio->bi_private = octx;
 	bio->bi_end_io = one_flush_endio;
-	bio->bi_opf = REQ_OP_FLUSH | REQ_PREFLUSH;
+	bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
 
 	device->flush_jif = jiffies;
 	set_bit(FLUSH_PENDING, &device->flags);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/block/drbd/drbd_req.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/block/drbd/drbd_req.c
@@ -195,7 +195,8 @@
 void complete_master_bio(struct drbd_device *device,
 		struct bio_and_error *m)
 {
-	m->bio->bi_status = errno_to_blk_status(m->error);
+	if (unlikely(m->error))
+		m->bio->bi_status = errno_to_blk_status(m->error);
 	bio_endio(m->bio);
 	dec_ap_bio(device);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/block/drbd/drbd_state.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/block/drbd/drbd_state.c
@@ -876,7 +876,7 @@
 		  ns.disk == D_OUTDATED)
 		rv = SS_CONNECTED_OUTDATES;
 
-	else if ((ns.conn == C_VERIFY_S || ns.conn == C_VERIFY_T) &&
+	else if (nc && (ns.conn == C_VERIFY_S || ns.conn == C_VERIFY_T) &&
 		 (nc->verify_alg[0] == 0))
 		rv = SS_NO_VERIFY_ALG;
 
@@ -1537,7 +1537,7 @@
 	return rv;
 }
 
-void notify_resource_state_change(struct sk_buff *skb,
+int notify_resource_state_change(struct sk_buff *skb,
 				  unsigned int seq,
 				  struct drbd_resource_state_change *resource_state_change,
 				  enum drbd_notification_type type)
@@ -1550,10 +1550,10 @@
 		.res_susp_fen = resource_state_change->susp_fen[NEW],
 	};
 
-	notify_resource_state(skb, seq, resource, &resource_info, type);
+	return notify_resource_state(skb, seq, resource, &resource_info, type);
 }
 
-void notify_connection_state_change(struct sk_buff *skb,
+int notify_connection_state_change(struct sk_buff *skb,
 				    unsigned int seq,
 				    struct drbd_connection_state_change *connection_state_change,
 				    enum drbd_notification_type type)
@@ -1564,10 +1564,10 @@
 		.conn_role = connection_state_change->peer_role[NEW],
 	};
 
-	notify_connection_state(skb, seq, connection, &connection_info, type);
+	return notify_connection_state(skb, seq, connection, &connection_info, type);
 }
 
-void notify_device_state_change(struct sk_buff *skb,
+int notify_device_state_change(struct sk_buff *skb,
 				unsigned int seq,
 				struct drbd_device_state_change *device_state_change,
 				enum drbd_notification_type type)
@@ -1577,10 +1577,10 @@
 		.dev_disk_state = device_state_change->disk_state[NEW],
 	};
 
-	notify_device_state(skb, seq, device, &device_info, type);
+	return notify_device_state(skb, seq, device, &device_info, type);
 }
 
-void notify_peer_device_state_change(struct sk_buff *skb,
+int notify_peer_device_state_change(struct sk_buff *skb,
 				     unsigned int seq,
 				     struct drbd_peer_device_state_change *p,
 				     enum drbd_notification_type type)
@@ -1594,7 +1594,7 @@
 		.peer_resync_susp_dependency = p->resync_susp_dependency[NEW],
 	};
 
-	notify_peer_device_state(skb, seq, peer_device, &peer_device_info, type);
+	return notify_peer_device_state(skb, seq, peer_device, &peer_device_info, type);
 }
 
 static void broadcast_state_change(struct drbd_state_change *state_change)
@@ -1602,7 +1602,7 @@
 	struct drbd_resource_state_change *resource_state_change = &state_change->resource[0];
 	bool resource_state_has_changed;
 	unsigned int n_device, n_connection, n_peer_device, n_peer_devices;
-	void (*last_func)(struct sk_buff *, unsigned int, void *,
+	int (*last_func)(struct sk_buff *, unsigned int, void *,
 			  enum drbd_notification_type) = NULL;
 	void *uninitialized_var(last_arg);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/block/drbd/drbd_state_change.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/block/drbd/drbd_state_change.h
@@ -44,19 +44,19 @@
 extern void copy_old_to_new_state_change(struct drbd_state_change *);
 extern void forget_state_change(struct drbd_state_change *);
 
-extern void notify_resource_state_change(struct sk_buff *,
+extern int notify_resource_state_change(struct sk_buff *,
 					 unsigned int,
 					 struct drbd_resource_state_change *,
 					 enum drbd_notification_type type);
-extern void notify_connection_state_change(struct sk_buff *,
+extern int notify_connection_state_change(struct sk_buff *,
 					   unsigned int,
 					   struct drbd_connection_state_change *,
 					   enum drbd_notification_type type);
-extern void notify_device_state_change(struct sk_buff *,
+extern int notify_device_state_change(struct sk_buff *,
 				       unsigned int,
 				       struct drbd_device_state_change *,
 				       enum drbd_notification_type type);
-extern void notify_peer_device_state_change(struct sk_buff *,
+extern int notify_peer_device_state_change(struct sk_buff *,
 					    unsigned int,
 					    struct drbd_peer_device_state_change *,
 					    enum drbd_notification_type type);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/block/floppy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/block/floppy.c
@@ -521,8 +521,8 @@
 static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
 static DECLARE_WAIT_QUEUE_HEAD(command_done);
 
-/* Errors during formatting are counted here. */
-static int format_errors;
+/* errors encountered on the current (or last) request */
+static int floppy_errors;
 
 /* Format request descriptor. */
 static struct format_descr format_req;
@@ -542,7 +542,6 @@
 static char *floppy_track_buffer;
 static int max_buffer_sectors;
 
-static int *errors;
 typedef void (*done_f)(int);
 static const struct cont_t {
 	void (*interrupt)(void);
@@ -853,14 +852,17 @@
 /* selects the fdc and drive, and enables the fdc's input/dma. */
 static void set_fdc(int drive)
 {
+	unsigned int new_fdc = fdc;
+
 	if (drive >= 0 && drive < N_DRIVE) {
-		fdc = FDC(drive);
+		new_fdc = FDC(drive);
 		current_drive = drive;
 	}
-	if (fdc != 1 && fdc != 0) {
+	if (new_fdc >= N_FDC) {
 		pr_info("bad fdc value\n");
 		return;
 	}
+	fdc = new_fdc;
 	set_dor(fdc, ~0, 8);
 #if N_FDC > 1
 	set_dor(1 - fdc, ~8, 0);
@@ -1000,7 +1002,7 @@
 static void cancel_activity(void)
 {
 	do_floppy = NULL;
-	cancel_delayed_work_sync(&fd_timer);
+	cancel_delayed_work(&fd_timer);
 	cancel_work_sync(&floppy_work);
 }
 
@@ -1432,7 +1434,7 @@
 			if (DP->flags & FTD_MSG)
 				DPRINT("Over/Underrun - retrying\n");
 			bad = 0;
-		} else if (*errors >= DP->max_errors.reporting) {
+		} else if (floppy_errors >= DP->max_errors.reporting) {
 			print_errors();
 		}
 		if (ST2 & ST2_WC || ST2 & ST2_BC)
@@ -2052,7 +2054,7 @@
 		if (!next_valid_format())
 			return;
 	}
-	err_count = ++(*errors);
+	err_count = ++floppy_errors;
 	INFBOUND(DRWE->badness, err_count);
 	if (err_count > DP->max_errors.abort)
 		cont->done(0);
@@ -2197,9 +2199,8 @@
 		return -EINVAL;
 	}
 	format_req = *tmp_format_req;
-	format_errors = 0;
 	cont = &format_cont;
-	errors = &format_errors;
+	floppy_errors = 0;
 	ret = wait_til_done(redo_format, true);
 	if (ret == -EINTR)
 		return -EINTR;
@@ -2674,7 +2675,7 @@
 		 */
 		if (!direct ||
 		    (indirect * 2 > direct * 3 &&
-		     *errors < DP->max_errors.read_track &&
+		     floppy_errors < DP->max_errors.read_track &&
 		     ((!probing ||
 		       (DP->read_track & (1 << DRS->probed_format)))))) {
 			max_size = blk_rq_sectors(current_req);
@@ -2798,10 +2799,11 @@
 	current_req = list_first_entry_or_null(&floppy_reqs, struct request,
 					       queuelist);
 	if (current_req) {
-		current_req->error_count = 0;
+		floppy_errors = 0;
 		list_del_init(&current_req->queuelist);
+		return 1;
 	}
-	return current_req != NULL;
+	return 0;
 }
 
 static void redo_fd_request(void)
@@ -2857,7 +2859,6 @@
 		_floppy = floppy_type + DP->autodetect[DRS->probed_format];
 	} else
 		probing = 0;
-	errors = &(current_req->error_count);
 	tmp = make_raw_rw_request();
 	if (tmp < 2) {
 		request_done(tmp);
@@ -2899,17 +2900,17 @@
 		 (unsigned long long) current_req->cmd_flags))
 		return BLK_STS_IOERR;
 
-	spin_lock_irq(&floppy_lock);
-	list_add_tail(&bd->rq->queuelist, &floppy_reqs);
-	spin_unlock_irq(&floppy_lock);
-
 	if (test_and_set_bit(0, &fdc_busy)) {
 		/* fdc busy, this new request will be treated when the
 		   current one is done */
 		is_alive(__func__, "old request running");
-		return BLK_STS_OK;
+		return BLK_STS_RESOURCE;
 	}
 
+	spin_lock_irq(&floppy_lock);
+	list_add_tail(&bd->rq->queuelist, &floppy_reqs);
+	spin_unlock_irq(&floppy_lock);
+
 	command_status = FD_COMMAND_NONE;
 	__reschedule_timeout(MAXTIMEOUT, "fd_request");
 	set_fdc(0);
@@ -3009,6 +3010,8 @@
 		return "(null)";
 }
 
+#ifdef CONFIG_BLK_DEV_FD_RAWCMD
+
 /* raw commands */
 static void raw_cmd_done(int flag)
 {
@@ -3109,6 +3112,8 @@
 	}
 }
 
+#define MAX_LEN (1UL << MAX_ORDER << PAGE_SHIFT)
+
 static int raw_cmd_copyin(int cmd, void __user *param,
 				 struct floppy_raw_cmd **rcmd)
 {
@@ -3146,7 +3151,7 @@
 	ptr->resultcode = 0;
 
 	if (ptr->flags & (FD_RAW_READ | FD_RAW_WRITE)) {
-		if (ptr->length <= 0)
+		if (ptr->length <= 0 || ptr->length >= MAX_LEN)
 			return -EINVAL;
 		ptr->kernel_data = (char *)fd_dma_mem_alloc(ptr->length);
 		fallback_on_nodma_alloc(&ptr->kernel_data, ptr->length);
@@ -3218,6 +3223,35 @@
 	return ret;
 }
 
+static int floppy_raw_cmd_ioctl(int type, int drive, int cmd,
+				void __user *param)
+{
+	int ret;
+
+	pr_warn_once("Note: FDRAWCMD is deprecated and will be removed from the kernel in the near future.\n");
+
+	if (type)
+		return -EINVAL;
+	if (lock_fdc(drive))
+		return -EINTR;
+	set_floppy(drive);
+	ret = raw_cmd_ioctl(cmd, param);
+	if (ret == -EINTR)
+		return -EINTR;
+	process_fd_request();
+	return ret;
+}
+
+#else /* CONFIG_BLK_DEV_FD_RAWCMD */
+
+static int floppy_raw_cmd_ioctl(int type, int drive, int cmd,
+				void __user *param)
+{
+	return -EOPNOTSUPP;
+}
+
+#endif
+
 static int invalidate_drive(struct block_device *bdev)
 {
 	/* invalidate the buffer track to force a reread */
@@ -3405,7 +3439,6 @@
 {
 	int drive = (long)bdev->bd_disk->private_data;
 	int type = ITYPE(UDRS->fd_device);
-	int i;
 	int ret;
 	int size;
 	union inparam {
@@ -3556,16 +3589,7 @@
 		outparam = UDRWE;
 		break;
 	case FDRAWCMD:
-		if (type)
-			return -EINVAL;
-		if (lock_fdc(drive))
-			return -EINTR;
-		set_floppy(drive);
-		i = raw_cmd_ioctl(cmd, (void __user *)param);
-		if (i == -EINTR)
-			return -EINTR;
-		process_fd_request();
-		return i;
+		return floppy_raw_cmd_ioctl(type, drive, cmd, (void __user *)param);
 	case FDTWADDLE:
 		if (lock_fdc(drive))
 			return -EINTR;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/block/loop.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/block/loop.c
@@ -226,24 +226,30 @@
 	blk_mq_unfreeze_queue(lo->lo_queue);
 }
 
-static int
-figure_loop_size(struct loop_device *lo, loff_t offset, loff_t sizelimit)
+/**
+ * loop_set_size() - sets device size and notifies userspace
+ * @lo: struct loop_device to set the size for
+ * @size: new size of the loop device
+ *
+ * Callers must validate that the size passed into this function fits into
+ * a sector_t, eg using loop_validate_size()
+ */
+static void loop_set_size(struct loop_device *lo, loff_t size)
 {
-	loff_t size = get_size(offset, sizelimit, lo->lo_backing_file);
-	sector_t x = (sector_t)size;
 	struct block_device *bdev = lo->lo_device;
 
-	if (unlikely((loff_t)x != size))
-		return -EFBIG;
-	if (lo->lo_offset != offset)
-		lo->lo_offset = offset;
-	if (lo->lo_sizelimit != sizelimit)
-		lo->lo_sizelimit = sizelimit;
-	set_capacity(lo->lo_disk, x);
-	bd_set_size(bdev, (loff_t)get_capacity(bdev->bd_disk) << 9);
+	set_capacity(lo->lo_disk, size);
+	bd_set_size(bdev, size << SECTOR_SHIFT);
 	/* let user-space know about the new size */
 	kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, KOBJ_CHANGE);
-	return 0;
+}
+
+static void
+figure_loop_size(struct loop_device *lo, loff_t offset, loff_t sizelimit)
+{
+	loff_t size = get_size(offset, sizelimit, lo->lo_backing_file);
+
+	loop_set_size(lo, size);
 }
 
 static inline int
@@ -417,19 +423,22 @@
 	return ret;
 }
 
-static int lo_discard(struct loop_device *lo, struct request *rq, loff_t pos)
+static int lo_fallocate(struct loop_device *lo, struct request *rq, loff_t pos,
+			int mode)
 {
 	/*
-	 * We use punch hole to reclaim the free space used by the
-	 * image a.k.a. discard. However we do not support discard if
-	 * encryption is enabled, because it may give an attacker
-	 * useful information.
+	 * We use fallocate to manipulate the space mappings used by the image
+	 * a.k.a. discard/zerorange. However we do not support this if
+	 * encryption is enabled, because it may give an attacker useful
+	 * information.
 	 */
 	struct file *file = lo->lo_backing_file;
-	int mode = FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE;
+	struct request_queue *q = lo->lo_queue;
 	int ret;
 
-	if ((!file->f_op->fallocate) || lo->lo_encrypt_key_size) {
+	mode |= FALLOC_FL_KEEP_SIZE;
+
+	if (!blk_queue_discard(q)) {
 		ret = -EOPNOTSUPP;
 		goto out;
 	}
@@ -494,7 +503,8 @@
 		return;
 	kfree(cmd->bvec);
 	cmd->bvec = NULL;
-	blk_mq_complete_request(rq);
+	if (likely(!blk_should_fake_timeout(rq->q)))
+		blk_mq_complete_request(rq);
 }
 
 static void lo_rw_aio_complete(struct kiocb *iocb, long ret, long ret2)
@@ -596,9 +606,17 @@
 	switch (req_op(rq)) {
 	case REQ_OP_FLUSH:
 		return lo_req_flush(lo, rq);
-	case REQ_OP_DISCARD:
 	case REQ_OP_WRITE_ZEROES:
-		return lo_discard(lo, rq, pos);
+		/*
+		 * If the caller doesn't want deallocation, call zeroout to
+		 * write zeroes the range.  Otherwise, punch them out.
+		 */
+		return lo_fallocate(lo, rq, pos,
+			(rq->cmd_flags & REQ_NOUNMAP) ?
+				FALLOC_FL_ZERO_RANGE :
+				FALLOC_FL_PUNCH_HOLE);
+	case REQ_OP_DISCARD:
+		return lo_fallocate(lo, rq, pos, FALLOC_FL_PUNCH_HOLE);
 	case REQ_OP_WRITE:
 		if (lo->transfer)
 			return lo_write_transfer(lo, rq, pos);
@@ -625,6 +643,15 @@
 			lo->use_dio);
 }
 
+static struct file *loop_real_file(struct file *file)
+{
+	struct file *f = NULL;
+
+	if (file->f_path.dentry->d_sb->s_op->real_loop)
+		f = file->f_path.dentry->d_sb->s_op->real_loop(file);
+	return f;
+}
+
 static void loop_reread_partitions(struct loop_device *lo,
 				   struct block_device *bdev)
 {
@@ -678,6 +705,7 @@
 			  unsigned int arg)
 {
 	struct file	*file = NULL, *old_file;
+	struct file	*f, *virt_file = NULL, *old_virt_file;
 	int		error;
 	bool		partscan;
 
@@ -697,12 +725,19 @@
 	file = fget(arg);
 	if (!file)
 		goto out_err;
+	f = loop_real_file(file);
+	if (f) {
+		virt_file = file;
+		file = f;
+		get_file(file);
+	}
 
 	error = loop_validate_file(file, bdev);
 	if (error)
 		goto out_err;
 
 	old_file = lo->lo_backing_file;
+	old_virt_file = lo->lo_backing_virt_file;
 
 	error = -EINVAL;
 
@@ -714,6 +749,7 @@
 	blk_mq_freeze_queue(lo->lo_queue);
 	mapping_set_gfp_mask(old_file->f_mapping, lo->old_gfp_mask);
 	lo->lo_backing_file = file;
+	lo->lo_backing_virt_file = virt_file;
 	lo->old_gfp_mask = mapping_gfp_mask(file->f_mapping);
 	mapping_set_gfp_mask(file->f_mapping,
 			     lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
@@ -727,6 +763,8 @@
 	 * dependency.
 	 */
 	fput(old_file);
+	if (old_virt_file)
+		fput(old_virt_file);
 	if (partscan)
 		loop_reread_partitions(lo, bdev);
 	return 0;
@@ -735,9 +773,29 @@
 	mutex_unlock(&loop_ctl_mutex);
 	if (file)
 		fput(file);
+	if (virt_file)
+		fput(virt_file);
 	return error;
 }
 
+/*
+ * for AUFS
+ * no get/put for file.
+ */
+struct file *loop_backing_file(struct super_block *sb)
+{
+	struct file *ret;
+	struct loop_device *l;
+
+	ret = NULL;
+	if (MAJOR(sb->s_dev) == LOOP_MAJOR) {
+		l = sb->s_bdev->bd_disk->private_data;
+		ret = l->lo_backing_file;
+	}
+	return ret;
+}
+EXPORT_SYMBOL_GPL(loop_backing_file);
+
 /* loop sysfs attributes */
 
 static ssize_t loop_attr_show(struct device *dev, char *page,
@@ -783,33 +841,33 @@
 
 static ssize_t loop_attr_offset_show(struct loop_device *lo, char *buf)
 {
-	return sprintf(buf, "%llu\n", (unsigned long long)lo->lo_offset);
+	return sysfs_emit(buf, "%llu\n", (unsigned long long)lo->lo_offset);
 }
 
 static ssize_t loop_attr_sizelimit_show(struct loop_device *lo, char *buf)
 {
-	return sprintf(buf, "%llu\n", (unsigned long long)lo->lo_sizelimit);
+	return sysfs_emit(buf, "%llu\n", (unsigned long long)lo->lo_sizelimit);
 }
 
 static ssize_t loop_attr_autoclear_show(struct loop_device *lo, char *buf)
 {
 	int autoclear = (lo->lo_flags & LO_FLAGS_AUTOCLEAR);
 
-	return sprintf(buf, "%s\n", autoclear ? "1" : "0");
+	return sysfs_emit(buf, "%s\n", autoclear ? "1" : "0");
 }
 
 static ssize_t loop_attr_partscan_show(struct loop_device *lo, char *buf)
 {
 	int partscan = (lo->lo_flags & LO_FLAGS_PARTSCAN);
 
-	return sprintf(buf, "%s\n", partscan ? "1" : "0");
+	return sysfs_emit(buf, "%s\n", partscan ? "1" : "0");
 }
 
 static ssize_t loop_attr_dio_show(struct loop_device *lo, char *buf)
 {
 	int dio = (lo->lo_flags & LO_FLAGS_DIRECT_IO);
 
-	return sprintf(buf, "%s\n", dio ? "1" : "0");
+	return sysfs_emit(buf, "%s\n", dio ? "1" : "0");
 }
 
 LOOP_ATTR_RO(backing_file);
@@ -852,6 +910,23 @@
 	struct file *file = lo->lo_backing_file;
 	struct inode *inode = file->f_mapping->host;
 	struct request_queue *q = lo->lo_queue;
+	u32 granularity, max_discard_sectors;
+
+	/*
+	 * If the backing device is a block device, mirror its zeroing
+	 * capability. Set the discard sectors to the block device's zeroing
+	 * capabilities because loop discards result in blkdev_issue_zeroout(),
+	 * not blkdev_issue_discard(). This maintains consistent behavior with
+	 * file-backed loop devices: discarded regions read back as zero.
+	 */
+	if (S_ISBLK(inode->i_mode) && !lo->lo_encrypt_key_size) {
+		struct request_queue *backingq;
+
+		backingq = bdev_get_queue(inode->i_bdev);
+
+		max_discard_sectors = backingq->limits.max_write_zeroes_sectors;
+		granularity = backingq->limits.discard_granularity ?:
+			queue_physical_block_size(backingq);
 
 	/*
 	 * We use punch hole to reclaim the free space used by the
@@ -859,22 +934,27 @@
 	 * encryption is enabled, because it may give an attacker
 	 * useful information.
 	 */
-	if ((!file->f_op->fallocate) ||
-	    lo->lo_encrypt_key_size) {
+	} else if (!file->f_op->fallocate || lo->lo_encrypt_key_size) {
+		max_discard_sectors = 0;
+		granularity = 0;
+
+	} else {
+		max_discard_sectors = UINT_MAX >> 9;
+		granularity = inode->i_sb->s_blocksize;
+	}
+
+	if (max_discard_sectors) {
+		q->limits.discard_granularity = granularity;
+		blk_queue_max_discard_sectors(q, max_discard_sectors);
+		blk_queue_max_write_zeroes_sectors(q, max_discard_sectors);
+		blk_queue_flag_set(QUEUE_FLAG_DISCARD, q);
+	} else {
 		q->limits.discard_granularity = 0;
-		q->limits.discard_alignment = 0;
 		blk_queue_max_discard_sectors(q, 0);
 		blk_queue_max_write_zeroes_sectors(q, 0);
 		blk_queue_flag_clear(QUEUE_FLAG_DISCARD, q);
-		return;
 	}
-
-	q->limits.discard_granularity = inode->i_sb->s_blocksize;
 	q->limits.discard_alignment = 0;
-
-	blk_queue_max_discard_sectors(q, UINT_MAX >> 9);
-	blk_queue_max_write_zeroes_sectors(q, UINT_MAX >> 9);
-	blk_queue_flag_set(QUEUE_FLAG_DISCARD, q);
 }
 
 static void loop_unprepare_queue(struct loop_device *lo)
@@ -921,7 +1001,7 @@
 static int loop_set_fd(struct loop_device *lo, fmode_t mode,
 		       struct block_device *bdev, unsigned int arg)
 {
-	struct file	*file;
+	struct file	*file, *f, *virt_file = NULL;
 	struct inode	*inode;
 	struct address_space *mapping;
 	struct block_device *claimed_bdev = NULL;
@@ -937,6 +1017,12 @@
 	file = fget(arg);
 	if (!file)
 		goto out;
+	f = loop_real_file(file);
+	if (f) {
+		virt_file = file;
+		file = f;
+		get_file(file);
+	}
 
 	/*
 	 * If we don't hold exclusive handle for the device, upgrade to it
@@ -969,10 +1055,8 @@
 	    !file->f_op->write_iter)
 		lo_flags |= LO_FLAGS_READ_ONLY;
 
-	error = -EFBIG;
 	size = get_loop_size(lo, file);
-	if ((loff_t)(sector_t)size != size)
-		goto out_unlock;
+
 	error = loop_prepare_queue(lo);
 	if (error)
 		goto out_unlock;
@@ -985,6 +1069,7 @@
 	lo->lo_device = bdev;
 	lo->lo_flags = lo_flags;
 	lo->lo_backing_file = file;
+	lo->lo_backing_virt_file = virt_file;
 	lo->transfer = NULL;
 	lo->ioctl = NULL;
 	lo->lo_sizelimit = 0;
@@ -1006,11 +1091,8 @@
 
 	loop_update_rotational(lo);
 	loop_update_dio(lo);
-	set_capacity(lo->lo_disk, size);
-	bd_set_size(bdev, size << 9);
 	loop_sysfs_init(lo);
-	/* let user-space know about the new size */
-	kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, KOBJ_CHANGE);
+	loop_set_size(lo, size);
 
 	set_blocksize(bdev, S_ISBLK(inode->i_mode) ?
 		      block_size(inode->i_bdev) : PAGE_SIZE);
@@ -1038,6 +1120,8 @@
 		bd_abort_claiming(bdev, claimed_bdev, loop_set_fd);
 out_putf:
 	fput(file);
+	if (virt_file)
+		fput(virt_file);
 out:
 	/* This is safe: open() is still holding a reference. */
 	module_put(THIS_MODULE);
@@ -1084,6 +1168,7 @@
 static int __loop_clr_fd(struct loop_device *lo, bool release)
 {
 	struct file *filp = NULL;
+	struct file *virt_filp = lo->lo_backing_virt_file;
 	gfp_t gfp = lo->old_gfp_mask;
 	struct block_device *bdev = lo->lo_device;
 	int err = 0;
@@ -1102,11 +1187,15 @@
 		goto out_unlock;
 	}
 
+	if (test_bit(QUEUE_FLAG_WC, &lo->lo_queue->queue_flags))
+		blk_queue_write_cache(lo->lo_queue, false, false);
+
 	/* freeze request queue during the transition */
 	blk_mq_freeze_queue(lo->lo_queue);
 
 	spin_lock_irq(&lo->lo_lock);
 	lo->lo_backing_file = NULL;
+	lo->lo_backing_virt_file = NULL;
 	spin_unlock_irq(&lo->lo_lock);
 
 	loop_release_xfer(lo);
@@ -1189,6 +1278,8 @@
 	 */
 	if (filp)
 		fput(filp);
+	if (virt_filp)
+		fput(virt_filp);
 	return err;
 }
 
@@ -1224,82 +1315,50 @@
 	return __loop_clr_fd(lo, false);
 }
 
+/**
+ * loop_set_status_from_info - configure device from loop_info
+ * @lo: struct loop_device to configure
+ * @info: struct loop_info64 to configure the device with
+ *
+ * Configures the loop device parameters according to the passed
+ * in loop_info64 configuration.
+ */
 static int
-loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
+loop_set_status_from_info(struct loop_device *lo,
+			  const struct loop_info64 *info)
 {
 	int err;
 	struct loop_func_table *xfer;
 	kuid_t uid = current_uid();
-	struct block_device *bdev;
-	bool partscan = false;
-
-	err = mutex_lock_killable(&loop_ctl_mutex);
-	if (err)
-		return err;
-	if (lo->lo_encrypt_key_size &&
-	    !uid_eq(lo->lo_key_owner, uid) &&
-	    !capable(CAP_SYS_ADMIN)) {
-		err = -EPERM;
-		goto out_unlock;
-	}
-	if (lo->lo_state != Lo_bound) {
-		err = -ENXIO;
-		goto out_unlock;
-	}
-	if ((unsigned int) info->lo_encrypt_key_size > LO_KEY_SIZE) {
-		err = -EINVAL;
-		goto out_unlock;
-	}
 
-	if (lo->lo_offset != info->lo_offset ||
-	    lo->lo_sizelimit != info->lo_sizelimit) {
-		sync_blockdev(lo->lo_device);
-		kill_bdev(lo->lo_device);
-	}
-
-	/* I/O need to be drained during transfer transition */
-	blk_mq_freeze_queue(lo->lo_queue);
+	if ((unsigned int) info->lo_encrypt_key_size > LO_KEY_SIZE)
+		return -EINVAL;
 
 	err = loop_release_xfer(lo);
 	if (err)
-		goto out_unfreeze;
+		return err;
 
 	if (info->lo_encrypt_type) {
 		unsigned int type = info->lo_encrypt_type;
 
-		if (type >= MAX_LO_CRYPT) {
-			err = -EINVAL;
-			goto out_unfreeze;
-		}
+		if (type >= MAX_LO_CRYPT)
+			return -EINVAL;
 		xfer = xfer_funcs[type];
-		if (xfer == NULL) {
-			err = -EINVAL;
-			goto out_unfreeze;
-		}
+		if (xfer == NULL)
+			return -EINVAL;
 	} else
 		xfer = NULL;
 
 	err = loop_init_xfer(lo, xfer, info);
 	if (err)
-		goto out_unfreeze;
+		return err;
 
-	if (lo->lo_offset != info->lo_offset ||
-	    lo->lo_sizelimit != info->lo_sizelimit) {
-		/* kill_bdev should have truncated all the pages */
-		if (lo->lo_device->bd_inode->i_mapping->nrpages) {
-			err = -EAGAIN;
-			pr_warn("%s: loop%d (%s) has still dirty pages (nrpages=%lu)\n",
-				__func__, lo->lo_number, lo->lo_file_name,
-				lo->lo_device->bd_inode->i_mapping->nrpages);
-			goto out_unfreeze;
-		}
-		if (figure_loop_size(lo, info->lo_offset, info->lo_sizelimit)) {
-			err = -EFBIG;
-			goto out_unfreeze;
-		}
-	}
+	/* Avoid assigning overflow values */
+	if (info->lo_offset > LLONG_MAX || info->lo_sizelimit > LLONG_MAX)
+		return -EOVERFLOW;
 
-	loop_config_discard(lo);
+	lo->lo_offset = info->lo_offset;
+	lo->lo_sizelimit = info->lo_sizelimit;
 
 	memcpy(lo->lo_file_name, info->lo_file_name, LO_NAME_SIZE);
 	memcpy(lo->lo_crypt_name, info->lo_crypt_name, LO_NAME_SIZE);
@@ -1324,6 +1383,63 @@
 		lo->lo_key_owner = uid;
 	}
 
+	return 0;
+}
+
+static int
+loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
+{
+	int err;
+	struct block_device *bdev;
+	kuid_t uid = current_uid();
+	bool partscan = false;
+	bool size_changed = false;
+
+	err = mutex_lock_killable(&loop_ctl_mutex);
+	if (err)
+		return err;
+	if (lo->lo_encrypt_key_size &&
+	    !uid_eq(lo->lo_key_owner, uid) &&
+	    !capable(CAP_SYS_ADMIN)) {
+		err = -EPERM;
+		goto out_unlock;
+	}
+	if (lo->lo_state != Lo_bound) {
+		err = -ENXIO;
+		goto out_unlock;
+	}
+
+	if (lo->lo_offset != info->lo_offset ||
+	    lo->lo_sizelimit != info->lo_sizelimit) {
+		size_changed = true;
+		sync_blockdev(lo->lo_device);
+		invalidate_bdev(lo->lo_device);
+	}
+
+	/* I/O need to be drained during transfer transition */
+	blk_mq_freeze_queue(lo->lo_queue);
+
+	if (size_changed && lo->lo_device->bd_inode->i_mapping->nrpages) {
+		/* If any pages were dirtied after invalidate_bdev(), try again */
+		err = -EAGAIN;
+		pr_warn("%s: loop%d (%s) has still dirty pages (nrpages=%lu)\n",
+			__func__, lo->lo_number, lo->lo_file_name,
+			lo->lo_device->bd_inode->i_mapping->nrpages);
+		goto out_unfreeze;
+	}
+
+	err = loop_set_status_from_info(lo, info);
+	if (err)
+		goto out_unfreeze;
+
+	if (size_changed) {
+		loff_t new_size = get_size(lo->lo_offset, lo->lo_sizelimit,
+					   lo->lo_backing_file);
+		loop_set_size(lo, new_size);
+	}
+
+	loop_config_discard(lo);
+
 	/* update dio if lo_offset or transfer is changed */
 	__loop_update_dio(lo, lo->use_dio);
 
@@ -1499,7 +1615,9 @@
 	if (unlikely(lo->lo_state != Lo_bound))
 		return -ENXIO;
 
-	return figure_loop_size(lo, lo->lo_offset, lo->lo_sizelimit);
+	figure_loop_size(lo, lo->lo_offset, lo->lo_sizelimit);
+
+	return 0;
 }
 
 static int loop_set_dio(struct loop_device *lo, unsigned long arg)
@@ -1528,12 +1646,12 @@
 
 	if (lo->lo_queue->limits.logical_block_size != arg) {
 		sync_blockdev(lo->lo_device);
-		kill_bdev(lo->lo_device);
+		invalidate_bdev(lo->lo_device);
 	}
 
 	blk_mq_freeze_queue(lo->lo_queue);
 
-	/* kill_bdev should have truncated all the pages */
+	/* invalidate_bdev should have truncated all the pages */
 	if (lo->lo_queue->limits.logical_block_size != arg &&
 			lo->lo_device->bd_inode->i_mapping->nrpages) {
 		err = -EAGAIN;
@@ -1941,7 +2059,8 @@
 	/* complete non-aio request */
 	if (!cmd->use_aio || ret) {
 		cmd->ret = ret ? -EIO : 0;
-		blk_mq_complete_request(rq);
+		if (likely(!blk_should_fake_timeout(rq->q)))
+			blk_mq_complete_request(rq);
 	}
 }
 
@@ -1999,7 +2118,7 @@
 	lo->tag_set.queue_depth = 128;
 	lo->tag_set.numa_node = NUMA_NO_NODE;
 	lo->tag_set.cmd_size = sizeof(struct loop_cmd);
-	lo->tag_set.flags = BLK_MQ_F_SHOULD_MERGE;
+	lo->tag_set.flags = BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_NO_SCHED;
 	lo->tag_set.driver_data = lo;
 
 	err = blk_mq_alloc_tag_set(&lo->tag_set);
@@ -2295,6 +2414,8 @@
 
 	range = max_loop ? max_loop << part_shift : 1UL << MINORBITS;
 
+	mutex_lock(&loop_ctl_mutex);
+
 	idr_for_each(&loop_index_idr, &loop_exit_cb, NULL);
 	idr_destroy(&loop_index_idr);
 
@@ -2302,6 +2423,8 @@
 	unregister_blkdev(LOOP_MAJOR, "loop");
 
 	misc_deregister(&loop_misc);
+
+	mutex_unlock(&loop_ctl_mutex);
 }
 
 module_init(loop_init);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/block/loop.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/block/loop.h
@@ -46,7 +46,7 @@
 	int		(*ioctl)(struct loop_device *, int cmd, 
 				 unsigned long arg); 
 
-	struct file *	lo_backing_file;
+	struct file	*lo_backing_file, *lo_backing_virt_file;
 	struct block_device *lo_device;
 	void		*key_data; 
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/block/mtip32xx/mtip32xx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/block/mtip32xx/mtip32xx.c
@@ -492,7 +492,8 @@
 	struct request *req = blk_mq_rq_from_pdu(cmd);
 
 	cmd->status = status;
-	blk_mq_complete_request(req);
+	if (likely(!blk_should_fake_timeout(req->q)))
+		blk_mq_complete_request(req);
 }
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/block/nbd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/block/nbd.c
@@ -78,8 +78,7 @@
 #define NBD_RT_HAS_PID_FILE		3
 #define NBD_RT_HAS_CONFIG_REF		4
 #define NBD_RT_BOUND			5
-#define NBD_RT_DESTROY_ON_DISCONNECT	6
-#define NBD_RT_DISCONNECT_ON_CLOSE	7
+#define NBD_RT_DISCONNECT_ON_CLOSE	6
 
 #define NBD_DESTROY_ON_DISCONNECT	0
 #define NBD_DISCONNECT_REQUESTED	1
@@ -123,6 +122,12 @@
 };
 
 #define NBD_CMD_REQUEUED	1
+/*
+ * This flag will be set if nbd_queue_rq() succeed, and will be checked and
+ * cleared in completion. Both setting and clearing of the flag are protected
+ * by cmd->lock.
+ */
+#define NBD_CMD_INFLIGHT	2
 
 struct nbd_cmd {
 	struct nbd_device *nbd;
@@ -296,7 +301,7 @@
 	}
 }
 
-static void nbd_size_update(struct nbd_device *nbd)
+static void nbd_size_update(struct nbd_device *nbd, bool start)
 {
 	struct nbd_config *config = nbd->config;
 	struct block_device *bdev = bdget_disk(nbd->disk, 0);
@@ -312,7 +317,8 @@
 	if (bdev) {
 		if (bdev->bd_disk) {
 			bd_set_size(bdev, config->bytesize);
-			set_blocksize(bdev, config->blksize);
+			if (start)
+				set_blocksize(bdev, config->blksize);
 		} else
 			bdev->bd_invalidated = 1;
 		bdput(bdev);
@@ -327,7 +333,7 @@
 	config->blksize = blocksize;
 	config->bytesize = blocksize * nr_blocks;
 	if (nbd->task_recv != NULL)
-		nbd_size_update(nbd);
+		nbd_size_update(nbd, false);
 }
 
 static void nbd_complete_rq(struct request *req)
@@ -388,8 +394,14 @@
 	if (!mutex_trylock(&cmd->lock))
 		return BLK_EH_RESET_TIMER;
 
+	if (!test_bit(NBD_CMD_INFLIGHT, &cmd->flags)) {
+		mutex_unlock(&cmd->lock);
+		return BLK_EH_DONE;
+	}
+
 	if (!refcount_inc_not_zero(&nbd->config_refs)) {
 		cmd->status = BLK_STS_TIMEOUT;
+		__clear_bit(NBD_CMD_INFLIGHT, &cmd->flags);
 		mutex_unlock(&cmd->lock);
 		goto done;
 	}
@@ -445,6 +457,7 @@
 	dev_err_ratelimited(nbd_to_dev(nbd), "Connection timed out\n");
 	set_bit(NBD_RT_TIMEDOUT, &config->runtime_flags);
 	cmd->status = BLK_STS_IOERR;
+	__clear_bit(NBD_CMD_INFLIGHT, &cmd->flags);
 	mutex_unlock(&cmd->lock);
 	sock_shutdown(nbd);
 	nbd_config_put(nbd);
@@ -704,6 +717,12 @@
 	cmd = blk_mq_rq_to_pdu(req);
 
 	mutex_lock(&cmd->lock);
+	if (!test_bit(NBD_CMD_INFLIGHT, &cmd->flags)) {
+		dev_err(disk_to_dev(nbd->disk), "Suspicious reply %d (status %u flags %lu)",
+			tag, cmd->status, cmd->flags);
+		ret = -ENOENT;
+		goto out;
+	}
 	if (cmd->cmd_cookie != nbd_handle_to_cookie(handle)) {
 		dev_err(disk_to_dev(nbd->disk), "Double reply on req %p, cmd_cookie %u, handle cookie %u\n",
 			req, cmd->cmd_cookie, nbd_handle_to_cookie(handle));
@@ -773,6 +792,7 @@
 	struct nbd_device *nbd = args->nbd;
 	struct nbd_config *config = nbd->config;
 	struct nbd_cmd *cmd;
+	struct request *rq;
 
 	while (1) {
 		cmd = nbd_read_stat(nbd, args->index);
@@ -785,11 +805,21 @@
 			break;
 		}
 
-		blk_mq_complete_request(blk_mq_rq_from_pdu(cmd));
+		rq = blk_mq_rq_from_pdu(cmd);
+		if (likely(!blk_should_fake_timeout(rq->q))) {
+			bool complete;
+
+			mutex_lock(&cmd->lock);
+			complete = __test_and_clear_bit(NBD_CMD_INFLIGHT,
+							&cmd->flags);
+			mutex_unlock(&cmd->lock);
+			if (complete)
+				blk_mq_complete_request(rq);
+		}
 	}
+	nbd_config_put(nbd);
 	atomic_dec(&config->recv_threads);
 	wake_up(&config->recv_wq);
-	nbd_config_put(nbd);
 	kfree(args);
 }
 
@@ -797,7 +827,15 @@
 {
 	struct nbd_cmd *cmd = blk_mq_rq_to_pdu(req);
 
+	/* don't abort one completed request */
+	if (blk_mq_request_completed(req))
+		return true;
+
 	mutex_lock(&cmd->lock);
+	if (!__test_and_clear_bit(NBD_CMD_INFLIGHT, &cmd->flags)) {
+		mutex_unlock(&cmd->lock);
+		return true;
+	}
 	cmd->status = BLK_STS_IOERR;
 	mutex_unlock(&cmd->lock);
 
@@ -861,11 +899,15 @@
 	struct nbd_config *config = nbd->config;
 	if (!config->dead_conn_timeout)
 		return 0;
-	if (test_bit(NBD_RT_DISCONNECTED, &config->runtime_flags))
+
+	if (!wait_event_timeout(config->conn_wait,
+				test_bit(NBD_RT_DISCONNECTED,
+					 &config->runtime_flags) ||
+				atomic_read(&config->live_connections) > 0,
+				config->dead_conn_timeout))
 		return 0;
-	return wait_event_timeout(config->conn_wait,
-				  atomic_read(&config->live_connections) > 0,
-				  config->dead_conn_timeout) > 0;
+
+	return !test_bit(NBD_RT_DISCONNECTED, &config->runtime_flags);
 }
 
 static int nbd_handle_cmd(struct nbd_cmd *cmd, int index)
@@ -934,7 +976,13 @@
 	 * returns EAGAIN can be retried on a different socket.
 	 */
 	ret = nbd_send_cmd(nbd, cmd, index);
-	if (ret == -EAGAIN) {
+	/*
+	 * Access to this flag is protected by cmd->lock, thus it's safe to set
+	 * the flag after nbd_send_cmd() succeed to send request to server.
+	 */
+	if (!ret)
+		__set_bit(NBD_CMD_INFLIGHT, &cmd->flags);
+	else if (ret == -EAGAIN) {
 		dev_err_ratelimited(disk_to_dev(nbd->disk),
 				    "Request send failed, requeueing\n");
 		nbd_mark_nsock_dead(nbd, nsock, 1);
@@ -1013,6 +1061,12 @@
 	if (!sock)
 		return err;
 
+	/*
+	 * We need to make sure we don't get any errant requests while we're
+	 * reallocating the ->socks array.
+	 */
+	blk_mq_freeze_queue(nbd->disk->queue);
+
 	if (!netlink && !nbd->task_setup &&
 	    !test_bit(NBD_RT_BOUND, &config->runtime_flags))
 		nbd->task_setup = current;
@@ -1022,20 +1076,22 @@
 	     test_bit(NBD_RT_BOUND, &config->runtime_flags))) {
 		dev_err(disk_to_dev(nbd->disk),
 			"Device being setup by another task");
-		sockfd_put(sock);
-		return -EBUSY;
+		err = -EBUSY;
+		goto put_socket;
+	}
+
+	nsock = kzalloc(sizeof(*nsock), GFP_KERNEL);
+	if (!nsock) {
+		err = -ENOMEM;
+		goto put_socket;
 	}
 
 	socks = krealloc(config->socks, (config->num_connections + 1) *
 			 sizeof(struct nbd_sock *), GFP_KERNEL);
 	if (!socks) {
-		sockfd_put(sock);
-		return -ENOMEM;
-	}
-	nsock = kzalloc(sizeof(struct nbd_sock), GFP_KERNEL);
-	if (!nsock) {
-		sockfd_put(sock);
-		return -ENOMEM;
+		kfree(nsock);
+		err = -ENOMEM;
+		goto put_socket;
 	}
 
 	config->socks = socks;
@@ -1049,8 +1105,14 @@
 	nsock->cookie = 0;
 	socks[config->num_connections++] = nsock;
 	atomic_inc(&config->live_connections);
+	blk_mq_unfreeze_queue(nbd->disk->queue);
 
 	return 0;
+
+put_socket:
+	blk_mq_unfreeze_queue(nbd->disk->queue);
+	sockfd_put(sock);
+	return err;
 }
 
 static int nbd_reconnect_socket(struct nbd_device *nbd, unsigned long arg)
@@ -1264,6 +1326,16 @@
 		args = kzalloc(sizeof(*args), GFP_KERNEL);
 		if (!args) {
 			sock_shutdown(nbd);
+			/*
+			 * If num_connections is m (2 < m),
+			 * and NO.1 ~ NO.n(1 < n < m) kzallocs are successful.
+			 * But NO.(n + 1) failed. We still have n recv threads.
+			 * So, add flush_workqueue here to prevent recv threads
+			 * dropping the last config_refs and trying to destroy
+			 * the workqueue from inside the workqueue.
+			 */
+			if (i)
+				flush_workqueue(nbd->recv_workq);
 			return -ENOMEM;
 		}
 		sk_set_memalloc(config->socks[i]->sock->sk);
@@ -1277,7 +1349,7 @@
 		args->index = i;
 		queue_work(nbd->recv_workq, &args->work);
 	}
-	nbd_size_update(nbd);
+	nbd_size_update(nbd, true);
 	return error;
 }
 
@@ -1297,8 +1369,10 @@
 					 atomic_read(&config->recv_threads) == 0);
 	if (ret) {
 		sock_shutdown(nbd);
-		flush_workqueue(nbd->recv_workq);
+		nbd_clear_que(nbd);
 	}
+
+	flush_workqueue(nbd->recv_workq);
 	mutex_lock(&nbd->config_lock);
 	nbd_bdev_reset(bdev);
 	/* user requested, ignore socket errors */
@@ -1312,7 +1386,7 @@
 static void nbd_clear_sock_ioctl(struct nbd_device *nbd,
 				 struct block_device *bdev)
 {
-	sock_shutdown(nbd);
+	nbd_clear_sock(nbd);
 	__invalidate_device(bdev, true);
 	nbd_bdev_reset(bdev);
 	if (test_and_clear_bit(NBD_RT_HAS_CONFIG_REF,
@@ -1333,6 +1407,8 @@
 	nbd->tag_set.timeout = timeout * HZ;
 	if (timeout)
 		blk_queue_rq_timeout(nbd->disk->queue, timeout * HZ);
+	else
+		blk_queue_rq_timeout(nbd->disk->queue, 30 * HZ);
 }
 
 /* Must be called with config_lock held */
@@ -1423,15 +1499,20 @@
 {
 	struct nbd_config *config;
 
+	if (!try_module_get(THIS_MODULE))
+		return ERR_PTR(-ENODEV);
+
 	config = kzalloc(sizeof(struct nbd_config), GFP_NOFS);
-	if (!config)
-		return NULL;
+	if (!config) {
+		module_put(THIS_MODULE);
+		return ERR_PTR(-ENOMEM);
+	}
+
 	atomic_set(&config->recv_threads, 0);
 	init_waitqueue_head(&config->recv_wq);
 	init_waitqueue_head(&config->conn_wait);
 	config->blksize = NBD_DEF_BLKSIZE;
 	atomic_set(&config->live_connections, 0);
-	try_module_get(THIS_MODULE);
 	return config;
 }
 
@@ -1458,12 +1539,13 @@
 			mutex_unlock(&nbd->config_lock);
 			goto out;
 		}
-		config = nbd->config = nbd_alloc_config();
-		if (!config) {
-			ret = -ENOMEM;
+		config = nbd_alloc_config();
+		if (IS_ERR(config)) {
+			ret = PTR_ERR(config);
 			mutex_unlock(&nbd->config_lock);
 			goto out;
 		}
+		nbd->config = config;
 		refcount_set(&nbd->config_refs, 1);
 		refcount_inc(&nbd->refs);
 		mutex_unlock(&nbd->config_lock);
@@ -1484,6 +1566,7 @@
 	if (test_bit(NBD_RT_DISCONNECT_ON_CLOSE, &nbd->config->runtime_flags) &&
 			bdev->bd_openers == 0)
 		nbd_disconnect_and_put(nbd);
+	bdput(bdev);
 
 	nbd_config_put(nbd);
 	nbd_put(nbd);
@@ -1566,7 +1649,7 @@
 		return -EIO;
 
 	dir = debugfs_create_dir(nbd_name(nbd), nbd_dbg_dir);
-	if (!dir) {
+	if (IS_ERR(dir)) {
 		dev_err(nbd_to_dev(nbd), "Failed to create debugfs dir for '%s'\n",
 			nbd_name(nbd));
 		return -EIO;
@@ -1592,7 +1675,7 @@
 	struct dentry *dbg_dir;
 
 	dbg_dir = debugfs_create_dir("nbd", NULL);
-	if (!dbg_dir)
+	if (IS_ERR(dbg_dir))
 		return -EIO;
 
 	nbd_dbg_dir = dbg_dir;
@@ -1665,7 +1748,8 @@
 		if (err == -ENOSPC)
 			err = -EEXIST;
 	} else {
-		err = idr_alloc(&nbd_index_idr, nbd, 0, 0, GFP_KERNEL);
+		err = idr_alloc(&nbd_index_idr, nbd, 0,
+				(MINORMASK >> part_shift) + 1, GFP_KERNEL);
 		if (err >= 0)
 			index = err;
 	}
@@ -1884,13 +1968,14 @@
 		nbd_put(nbd);
 		return -EINVAL;
 	}
-	config = nbd->config = nbd_alloc_config();
-	if (!nbd->config) {
+	config = nbd_alloc_config();
+	if (IS_ERR(config)) {
 		mutex_unlock(&nbd->config_lock);
 		nbd_put(nbd);
 		printk(KERN_ERR "nbd: couldn't allocate config\n");
-		return -ENOMEM;
+		return PTR_ERR(config);
 	}
+	nbd->config = config;
 	refcount_set(&nbd->config_refs, 1);
 	set_bit(NBD_RT_BOUND, &config->runtime_flags);
 
@@ -1912,12 +1997,21 @@
 	if (info->attrs[NBD_ATTR_CLIENT_FLAGS]) {
 		u64 flags = nla_get_u64(info->attrs[NBD_ATTR_CLIENT_FLAGS]);
 		if (flags & NBD_CFLAG_DESTROY_ON_DISCONNECT) {
-			set_bit(NBD_RT_DESTROY_ON_DISCONNECT,
-				&config->runtime_flags);
-			set_bit(NBD_DESTROY_ON_DISCONNECT, &nbd->flags);
-			put_dev = true;
+			/*
+			 * We have 1 ref to keep the device around, and then 1
+			 * ref for our current operation here, which will be
+			 * inherited by the config.  If we already have
+			 * DESTROY_ON_DISCONNECT set then we know we don't have
+			 * that extra ref already held so we don't need the
+			 * put_dev.
+			 */
+			if (!test_and_set_bit(NBD_DESTROY_ON_DISCONNECT,
+					      &nbd->flags))
+				put_dev = true;
 		} else {
-			clear_bit(NBD_DESTROY_ON_DISCONNECT, &nbd->flags);
+			if (test_and_clear_bit(NBD_DESTROY_ON_DISCONNECT,
+					       &nbd->flags))
+				refcount_inc(&nbd->refs);
 		}
 		if (flags & NBD_CFLAG_DISCONNECT_ON_CLOSE) {
 			set_bit(NBD_RT_DISCONNECT_ON_CLOSE,
@@ -1973,14 +2067,21 @@
 {
 	mutex_lock(&nbd->config_lock);
 	nbd_disconnect(nbd);
-	nbd_clear_sock(nbd);
-	mutex_unlock(&nbd->config_lock);
+	sock_shutdown(nbd);
+	wake_up(&nbd->config->conn_wait);
 	/*
 	 * Make sure recv thread has finished, so it does not drop the last
 	 * config ref and try to destroy the workqueue from inside the work
-	 * queue.
+	 * queue. And this also ensure that we can safely call nbd_clear_que()
+	 * to cancel the inflight I/Os.
 	 */
-	flush_workqueue(nbd->recv_workq);
+	if (nbd->recv_workq)
+		flush_workqueue(nbd->recv_workq);
+	nbd_clear_que(nbd);
+	nbd->task_setup = NULL;
+	clear_bit(NBD_RT_BOUND, &nbd->config->runtime_flags);
+	mutex_unlock(&nbd->config_lock);
+
 	if (test_and_clear_bit(NBD_RT_HAS_CONFIG_REF,
 			       &nbd->config->runtime_flags))
 		nbd_config_put(nbd);
@@ -2088,15 +2189,13 @@
 	if (info->attrs[NBD_ATTR_CLIENT_FLAGS]) {
 		u64 flags = nla_get_u64(info->attrs[NBD_ATTR_CLIENT_FLAGS]);
 		if (flags & NBD_CFLAG_DESTROY_ON_DISCONNECT) {
-			if (!test_and_set_bit(NBD_RT_DESTROY_ON_DISCONNECT,
-					      &config->runtime_flags))
+			if (!test_and_set_bit(NBD_DESTROY_ON_DISCONNECT,
+					      &nbd->flags))
 				put_dev = true;
-			set_bit(NBD_DESTROY_ON_DISCONNECT, &nbd->flags);
 		} else {
-			if (test_and_clear_bit(NBD_RT_DESTROY_ON_DISCONNECT,
-					       &config->runtime_flags))
+			if (test_and_clear_bit(NBD_DESTROY_ON_DISCONNECT,
+					       &nbd->flags))
 				refcount_inc(&nbd->refs);
-			clear_bit(NBD_DESTROY_ON_DISCONNECT, &nbd->flags);
 		}
 
 		if (flags & NBD_CFLAG_DISCONNECT_ON_CLOSE) {
@@ -2255,6 +2354,12 @@
 	}
 
 	dev_list = nla_nest_start_noflag(reply, NBD_ATTR_DEVICE_LIST);
+	if (!dev_list) {
+		nlmsg_free(reply);
+		ret = -EMSGSIZE;
+		goto out;
+	}
+
 	if (index == -1) {
 		ret = idr_for_each(&nbd_index_idr, &status_cb, reply);
 		if (ret) {
@@ -2398,6 +2503,12 @@
 	struct nbd_device *nbd;
 	LIST_HEAD(del_list);
 
+	/*
+	 * Unregister netlink interface prior to waiting
+	 * for the completion of netlink commands.
+	 */
+	genl_unregister_family(&nbd_genl_family);
+
 	nbd_dbg_close();
 
 	mutex_lock(&nbd_index_mutex);
@@ -2407,13 +2518,15 @@
 	while (!list_empty(&del_list)) {
 		nbd = list_first_entry(&del_list, struct nbd_device, list);
 		list_del_init(&nbd->list);
+		if (refcount_read(&nbd->config_refs))
+			printk(KERN_ERR "nbd: possibly leaking nbd_config (ref %d)\n",
+					refcount_read(&nbd->config_refs));
 		if (refcount_read(&nbd->refs) != 1)
 			printk(KERN_ERR "nbd: possibly leaking a device\n");
 		nbd_put(nbd);
 	}
 
 	idr_destroy(&nbd_index_idr);
-	genl_unregister_family(&nbd_genl_family);
 	unregister_blkdev(NBD_MAJOR, "nbd");
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/block/null_blk_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/block/null_blk_main.c
@@ -579,6 +579,7 @@
 	if (tag != -1U) {
 		cmd = &nq->cmds[tag];
 		cmd->tag = tag;
+		cmd->error = BLK_STS_OK;
 		cmd->nq = nq;
 		if (nq->dev->irqmode == NULL_IRQ_TIMER) {
 			hrtimer_init(&cmd->timer, CLOCK_MONOTONIC,
@@ -1071,7 +1072,7 @@
 		len = bvec.bv_len;
 		err = null_transfer(nullb, bvec.bv_page, len, bvec.bv_offset,
 				     op_is_write(req_op(rq)), sector,
-				     req_op(rq) & REQ_FUA);
+				     rq->cmd_flags & REQ_FUA);
 		if (err) {
 			spin_unlock_irq(&nullb->lock);
 			return err;
@@ -1189,7 +1190,8 @@
 	case NULL_IRQ_SOFTIRQ:
 		switch (cmd->nq->dev->queue_mode) {
 		case NULL_Q_MQ:
-			blk_mq_complete_request(cmd->rq);
+			if (likely(!blk_should_fake_timeout(cmd->rq->q)))
+				blk_mq_complete_request(cmd->rq);
 			break;
 		case NULL_Q_BIO:
 			/*
@@ -1335,6 +1337,7 @@
 		cmd->timer.function = null_cmd_timer_expired;
 	}
 	cmd->rq = bd->rq;
+	cmd->error = BLK_STS_OK;
 	cmd->nq = nq;
 
 	blk_mq_start_request(bd->rq);
@@ -1382,7 +1385,12 @@
 
 static void null_del_dev(struct nullb *nullb)
 {
-	struct nullb_device *dev = nullb->dev;
+	struct nullb_device *dev;
+
+	if (!nullb)
+		return;
+
+	dev = nullb->dev;
 
 	ida_simple_remove(&nullb_indexes, nullb->index);
 
@@ -1704,8 +1712,13 @@
 	blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, nullb->q);
 
 	mutex_lock(&lock);
-	nullb->index = ida_simple_get(&nullb_indexes, 0, 0, GFP_KERNEL);
-	dev->index = nullb->index;
+	rv = ida_simple_get(&nullb_indexes, 0, 0, GFP_KERNEL);
+	if (rv < 0) {
+		mutex_unlock(&lock);
+		goto out_cleanup_zone;
+	}
+	nullb->index = rv;
+	dev->index = rv;
 	mutex_unlock(&lock);
 
 	blk_queue_logical_block_size(nullb->q, dev->blocksize);
@@ -1717,13 +1730,16 @@
 
 	rv = null_gendisk_register(nullb);
 	if (rv)
-		goto out_cleanup_zone;
+		goto out_ida_free;
 
 	mutex_lock(&lock);
 	list_add_tail(&nullb->list, &nullb_list);
 	mutex_unlock(&lock);
 
 	return 0;
+
+out_ida_free:
+	ida_free(&nullb_indexes, nullb->index);
 out_cleanup_zone:
 	if (dev->zoned)
 		null_zone_exit(dev);
@@ -1736,6 +1752,7 @@
 	cleanup_queues(nullb);
 out_free_nullb:
 	kfree(nullb);
+	dev->nullb = NULL;
 out:
 	return rv;
 }
@@ -1852,10 +1869,13 @@
 
 	if (g_queue_mode == NULL_Q_MQ && shared_tags)
 		blk_mq_free_tag_set(&tag_set);
+
+	mutex_destroy(&lock);
 }
 
 module_init(null_init);
 module_exit(null_exit);
 
 MODULE_AUTHOR("Jens Axboe <axboe@kernel.dk>");
+MODULE_DESCRIPTION("multi queue aware block test driver");
 MODULE_LICENSE("GPL");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/block/null_blk_zoned.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/block/null_blk_zoned.c
@@ -2,8 +2,7 @@
 #include <linux/vmalloc.h>
 #include "null_blk.h"
 
-/* zone_size in MBs to sectors. */
-#define ZONE_SIZE_SHIFT		11
+#define MB_TO_SECTS(mb) (((sector_t)mb * SZ_1M) >> SECTOR_SHIFT)
 
 static inline unsigned int null_zone_no(struct nullb_device *dev, sector_t sect)
 {
@@ -12,7 +11,7 @@
 
 int null_zone_init(struct nullb_device *dev)
 {
-	sector_t dev_size = (sector_t)dev->size * 1024 * 1024;
+	sector_t dev_capacity_sects;
 	sector_t sector = 0;
 	unsigned int i;
 
@@ -20,10 +19,17 @@
 		pr_err("zone_size must be power-of-two\n");
 		return -EINVAL;
 	}
+	if (dev->zone_size > dev->size) {
+		pr_err("Zone size larger than device capacity\n");
+		return -EINVAL;
+	}
+
+	dev_capacity_sects = MB_TO_SECTS(dev->size);
+	dev->zone_size_sects = MB_TO_SECTS(dev->zone_size);
+	dev->nr_zones = dev_capacity_sects >> ilog2(dev->zone_size_sects);
+	if (dev_capacity_sects & (dev->zone_size_sects - 1))
+		dev->nr_zones++;
 
-	dev->zone_size_sects = dev->zone_size << ZONE_SIZE_SHIFT;
-	dev->nr_zones = dev_size >>
-				(SECTOR_SHIFT + ilog2(dev->zone_size_sects));
 	dev->zones = kvmalloc_array(dev->nr_zones, sizeof(struct blk_zone),
 			GFP_KERNEL | __GFP_ZERO);
 	if (!dev->zones)
@@ -51,7 +57,10 @@
 		struct blk_zone *zone = &dev->zones[i];
 
 		zone->start = zone->wp = sector;
-		zone->len = dev->zone_size_sects;
+		if (zone->start + dev->zone_size_sects > dev_capacity_sects)
+			zone->len = dev_capacity_sects - zone->start;
+		else
+			zone->len = dev->zone_size_sects;
 		zone->type = BLK_ZONE_TYPE_SEQWRITE_REQ;
 		zone->cond = BLK_ZONE_COND_EMPTY;
 
@@ -64,6 +73,7 @@
 void null_zone_exit(struct nullb_device *dev)
 {
 	kvfree(dev->zones);
+	dev->zones = NULL;
 }
 
 int null_zone_report(struct gendisk *disk, sector_t sector,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/block/ps3disk.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/block/ps3disk.c
@@ -454,7 +454,6 @@
 	queue->queuedata = dev;
 
 	blk_queue_max_hw_sectors(queue, dev->bounce_size >> 9);
-	blk_queue_segment_boundary(queue, -1UL);
 	blk_queue_dma_alignment(queue, dev->blk_size-1);
 	blk_queue_logical_block_size(queue, dev->blk_size);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/block/rbd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/block/rbd.c
@@ -366,7 +366,7 @@
 enum rbd_lock_state {
 	RBD_LOCK_STATE_UNLOCKED,
 	RBD_LOCK_STATE_LOCKED,
-	RBD_LOCK_STATE_RELEASING,
+	RBD_LOCK_STATE_QUIESCING,
 };
 
 /* WatchNotify::ClientId */
@@ -427,7 +427,7 @@
 	struct list_head	running_list;
 	struct completion	acquire_wait;
 	int			acquire_err;
-	struct completion	releasing_wait;
+	struct completion	quiescing_wait;
 
 	spinlock_t		object_map_lock;
 	u8			*object_map;
@@ -519,7 +519,7 @@
 	lockdep_assert_held(&rbd_dev->lock_rwsem);
 
 	return rbd_dev->lock_state == RBD_LOCK_STATE_LOCKED ||
-	       rbd_dev->lock_state == RBD_LOCK_STATE_RELEASING;
+	       rbd_dev->lock_state == RBD_LOCK_STATE_QUIESCING;
 }
 
 static bool rbd_is_lock_owner(struct rbd_device *rbd_dev)
@@ -626,9 +626,8 @@
 static void rbd_dev_remove_parent(struct rbd_device *rbd_dev);
 
 static int rbd_dev_refresh(struct rbd_device *rbd_dev);
-static int rbd_dev_v2_header_onetime(struct rbd_device *rbd_dev);
-static int rbd_dev_header_info(struct rbd_device *rbd_dev);
-static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev);
+static int rbd_dev_v2_header_onetime(struct rbd_device *rbd_dev,
+				     struct rbd_image_header *header);
 static const char *rbd_dev_v2_snap_name(struct rbd_device *rbd_dev,
 					u64 snap_id);
 static int _rbd_dev_v2_snap_size(struct rbd_device *rbd_dev, u64 snap_id,
@@ -1098,15 +1097,24 @@
 	RCU_INIT_POINTER(rbd_dev->layout.pool_ns, NULL);
 }
 
+static void rbd_image_header_cleanup(struct rbd_image_header *header)
+{
+	kfree(header->object_prefix);
+	ceph_put_snap_context(header->snapc);
+	kfree(header->snap_sizes);
+	kfree(header->snap_names);
+
+	memset(header, 0, sizeof(*header));
+}
+
 /*
  * Fill an rbd image header with information from the given format 1
  * on-disk header.
  */
-static int rbd_header_from_disk(struct rbd_device *rbd_dev,
-				 struct rbd_image_header_ondisk *ondisk)
+static int rbd_header_from_disk(struct rbd_image_header *header,
+				struct rbd_image_header_ondisk *ondisk,
+				bool first_time)
 {
-	struct rbd_image_header *header = &rbd_dev->header;
-	bool first_time = header->object_prefix == NULL;
 	struct ceph_snap_context *snapc;
 	char *object_prefix = NULL;
 	char *snap_names = NULL;
@@ -1173,11 +1181,6 @@
 	if (first_time) {
 		header->object_prefix = object_prefix;
 		header->obj_order = ondisk->options.order;
-		rbd_init_layout(rbd_dev);
-	} else {
-		ceph_put_snap_context(header->snapc);
-		kfree(header->snap_names);
-		kfree(header->snap_sizes);
 	}
 
 	/* The remaining fields always get updated (when we refresh) */
@@ -1493,14 +1496,30 @@
 /*
  * Must be called after rbd_obj_calc_img_extents().
  */
-static bool rbd_obj_copyup_enabled(struct rbd_obj_request *obj_req)
+static void rbd_obj_set_copyup_enabled(struct rbd_obj_request *obj_req)
 {
-	if (!obj_req->num_img_extents ||
-	    (rbd_obj_is_entire(obj_req) &&
-	     !obj_req->img_request->snapc->num_snaps))
-		return false;
+	rbd_assert(obj_req->img_request->snapc);
 
-	return true;
+	if (obj_req->img_request->op_type == OBJ_OP_DISCARD) {
+		dout("%s %p objno %llu discard\n", __func__, obj_req,
+		     obj_req->ex.oe_objno);
+		return;
+	}
+
+	if (!obj_req->num_img_extents) {
+		dout("%s %p objno %llu not overlapping\n", __func__, obj_req,
+		     obj_req->ex.oe_objno);
+		return;
+	}
+
+	if (rbd_obj_is_entire(obj_req) &&
+	    !obj_req->img_request->snapc->num_snaps) {
+		dout("%s %p objno %llu entire\n", __func__, obj_req,
+		     obj_req->ex.oe_objno);
+		return;
+	}
+
+	obj_req->flags |= RBD_OBJ_FLAG_COPYUP_ENABLED;
 }
 
 static u64 rbd_obj_img_extents_bytes(struct rbd_obj_request *obj_req)
@@ -1599,6 +1618,7 @@
 static struct ceph_osd_request *
 rbd_obj_add_osd_request(struct rbd_obj_request *obj_req, int num_ops)
 {
+	rbd_assert(obj_req->img_request->snapc);
 	return __rbd_obj_add_osd_request(obj_req, obj_req->img_request->snapc,
 					 num_ops);
 }
@@ -1727,11 +1747,14 @@
  * Caller is responsible for filling in the list of object requests
  * that comprises the image request, and the Linux request pointer
  * (if there is one).
+ *
+ * Only snap_id is captured here, for reads.  For writes, snapshot
+ * context is captured in rbd_img_object_requests() after exclusive
+ * lock is ensured to be held.
  */
 static struct rbd_img_request *rbd_img_request_create(
 					struct rbd_device *rbd_dev,
-					enum obj_operation_type op_type,
-					struct ceph_snap_context *snapc)
+					enum obj_operation_type op_type)
 {
 	struct rbd_img_request *img_request;
 
@@ -1743,8 +1766,6 @@
 	img_request->op_type = op_type;
 	if (!rbd_img_is_write(img_request))
 		img_request->snap_id = rbd_dev->spec->snap_id;
-	else
-		img_request->snapc = snapc;
 
 	if (rbd_dev_parent_get(rbd_dev))
 		img_request_layered_set(img_request);
@@ -2087,7 +2108,7 @@
 	struct rbd_device *rbd_dev = obj_req->img_request->rbd_dev;
 	struct ceph_osd_data *osd_data;
 	u64 objno;
-	u8 state, new_state, uninitialized_var(current_state);
+	u8 state, new_state, current_state;
 	bool has_current_state;
 	void *p;
 
@@ -2389,9 +2410,6 @@
 	if (ret)
 		return ret;
 
-	if (rbd_obj_copyup_enabled(obj_req))
-		obj_req->flags |= RBD_OBJ_FLAG_COPYUP_ENABLED;
-
 	obj_req->write_state = RBD_OBJ_WRITE_START;
 	return 0;
 }
@@ -2497,8 +2515,6 @@
 	if (ret)
 		return ret;
 
-	if (rbd_obj_copyup_enabled(obj_req))
-		obj_req->flags |= RBD_OBJ_FLAG_COPYUP_ENABLED;
 	if (!obj_req->num_img_extents) {
 		obj_req->flags |= RBD_OBJ_FLAG_NOOP_FOR_NONEXISTENT;
 		if (rbd_obj_is_entire(obj_req))
@@ -2739,7 +2755,7 @@
 			       u64 off, u64 len)
 {
 	struct ceph_file_extent ex = { off, len };
-	union rbd_img_fill_iter dummy;
+	union rbd_img_fill_iter dummy = {};
 	struct rbd_img_fill_ctx fctx = {
 		.pos_type = OBJ_REQUEST_NODATA,
 		.pos = &dummy,
@@ -2935,7 +2951,7 @@
 	int ret;
 
 	child_img_req = rbd_img_request_create(img_req->rbd_dev->parent,
-					       OBJ_OP_READ, NULL);
+					       OBJ_OP_READ);
 	if (!child_img_req)
 		return -ENOMEM;
 
@@ -3439,6 +3455,7 @@
 	case RBD_OBJ_WRITE_START:
 		rbd_assert(!*result);
 
+		rbd_obj_set_copyup_enabled(obj_req);
 		if (rbd_obj_write_is_noop(obj_req))
 			return true;
 
@@ -3586,17 +3603,19 @@
 static void rbd_lock_del_request(struct rbd_img_request *img_req)
 {
 	struct rbd_device *rbd_dev = img_req->rbd_dev;
-	bool need_wakeup;
+	bool need_wakeup = false;
 
 	lockdep_assert_held(&rbd_dev->lock_rwsem);
 	spin_lock(&rbd_dev->lock_lists_lock);
-	rbd_assert(!list_empty(&img_req->lock_item));
-	list_del_init(&img_req->lock_item);
-	need_wakeup = (rbd_dev->lock_state == RBD_LOCK_STATE_RELEASING &&
-		       list_empty(&rbd_dev->running_list));
+	if (!list_empty(&img_req->lock_item)) {
+		rbd_assert(!list_empty(&rbd_dev->running_list));
+		list_del_init(&img_req->lock_item);
+		need_wakeup = (rbd_dev->lock_state == RBD_LOCK_STATE_QUIESCING &&
+			       list_empty(&rbd_dev->running_list));
+	}
 	spin_unlock(&rbd_dev->lock_lists_lock);
 	if (need_wakeup)
-		complete(&rbd_dev->releasing_wait);
+		complete(&rbd_dev->quiescing_wait);
 }
 
 static int rbd_img_exclusive_lock(struct rbd_img_request *img_req)
@@ -3609,11 +3628,6 @@
 	if (rbd_lock_add_request(img_req))
 		return 1;
 
-	if (rbd_dev->opts->exclusive) {
-		WARN_ON(1); /* lock got released? */
-		return -EROFS;
-	}
-
 	/*
 	 * Note the use of mod_delayed_work() in rbd_acquire_lock()
 	 * and cancel_delayed_work() in wake_lock_waiters().
@@ -3625,9 +3639,19 @@
 
 static void rbd_img_object_requests(struct rbd_img_request *img_req)
 {
+	struct rbd_device *rbd_dev = img_req->rbd_dev;
 	struct rbd_obj_request *obj_req;
 
 	rbd_assert(!img_req->pending.result && !img_req->pending.num_pending);
+	rbd_assert(!need_exclusive_lock(img_req) ||
+		   __rbd_is_lock_owner(rbd_dev));
+
+	if (rbd_img_is_write(img_req)) {
+		rbd_assert(!img_req->snapc);
+		down_read(&rbd_dev->header_rwsem);
+		img_req->snapc = ceph_get_snap_context(rbd_dev->header.snapc);
+		up_read(&rbd_dev->header_rwsem);
+	}
 
 	for_each_obj_request(img_req, obj_req) {
 		int result = 0;
@@ -3645,7 +3669,6 @@
 
 static bool rbd_img_advance(struct rbd_img_request *img_req, int *result)
 {
-	struct rbd_device *rbd_dev = img_req->rbd_dev;
 	int ret;
 
 again:
@@ -3666,9 +3689,6 @@
 		if (*result)
 			return true;
 
-		rbd_assert(!need_exclusive_lock(img_req) ||
-			   __rbd_is_lock_owner(rbd_dev));
-
 		rbd_img_object_requests(img_req);
 		if (!img_req->pending.num_pending) {
 			*result = img_req->pending.result;
@@ -3974,14 +3994,19 @@
 		return;
 	}
 
-	list_for_each_entry(img_req, &rbd_dev->acquiring_list, lock_item) {
+	while (!list_empty(&rbd_dev->acquiring_list)) {
+		img_req = list_first_entry(&rbd_dev->acquiring_list,
+					   struct rbd_img_request, lock_item);
 		mutex_lock(&img_req->state_mutex);
 		rbd_assert(img_req->state == RBD_IMG_EXCLUSIVE_LOCK);
+		if (!result)
+			list_move_tail(&img_req->lock_item,
+				       &rbd_dev->running_list);
+		else
+			list_del_init(&img_req->lock_item);
 		rbd_img_schedule(img_req, result);
 		mutex_unlock(&img_req->state_mutex);
 	}
-
-	list_splice_tail_init(&rbd_dev->acquiring_list, &rbd_dev->running_list);
 }
 
 static int get_lock_owner_info(struct rbd_device *rbd_dev,
@@ -4130,6 +4155,10 @@
 {
 	int ret;
 
+	ret = rbd_dev_refresh(rbd_dev);
+	if (ret)
+		return ret;
+
 	if (rbd_dev->header.features & RBD_FEATURE_OBJECT_MAP) {
 		ret = rbd_object_map_open(rbd_dev);
 		if (ret)
@@ -4239,8 +4268,6 @@
 
 static bool rbd_quiesce_lock(struct rbd_device *rbd_dev)
 {
-	bool need_wait;
-
 	dout("%s rbd_dev %p\n", __func__, rbd_dev);
 	lockdep_assert_held_write(&rbd_dev->lock_rwsem);
 
@@ -4250,16 +4277,16 @@
 	/*
 	 * Ensure that all in-flight IO is flushed.
 	 */
-	rbd_dev->lock_state = RBD_LOCK_STATE_RELEASING;
-	rbd_assert(!completion_done(&rbd_dev->releasing_wait));
-	need_wait = !list_empty(&rbd_dev->running_list);
-	downgrade_write(&rbd_dev->lock_rwsem);
-	if (need_wait)
-		wait_for_completion(&rbd_dev->releasing_wait);
-	up_read(&rbd_dev->lock_rwsem);
+	rbd_dev->lock_state = RBD_LOCK_STATE_QUIESCING;
+	rbd_assert(!completion_done(&rbd_dev->quiescing_wait));
+	if (list_empty(&rbd_dev->running_list))
+		return true;
+
+	up_write(&rbd_dev->lock_rwsem);
+	wait_for_completion(&rbd_dev->quiescing_wait);
 
 	down_write(&rbd_dev->lock_rwsem);
-	if (rbd_dev->lock_state != RBD_LOCK_STATE_RELEASING)
+	if (rbd_dev->lock_state != RBD_LOCK_STATE_QUIESCING)
 		return false;
 
 	rbd_assert(list_empty(&rbd_dev->running_list));
@@ -4342,15 +4369,11 @@
 	if (!rbd_cid_equal(&cid, &rbd_empty_cid)) {
 		down_write(&rbd_dev->lock_rwsem);
 		if (rbd_cid_equal(&cid, &rbd_dev->owner_cid)) {
-			/*
-			 * we already know that the remote client is
-			 * the owner
-			 */
-			up_write(&rbd_dev->lock_rwsem);
-			return;
+			dout("%s rbd_dev %p cid %llu-%llu == owner_cid\n",
+			     __func__, rbd_dev, cid.gid, cid.handle);
+		} else {
+			rbd_set_owner_cid(rbd_dev, &cid);
 		}
-
-		rbd_set_owner_cid(rbd_dev, &cid);
 		downgrade_write(&rbd_dev->lock_rwsem);
 	} else {
 		down_read(&rbd_dev->lock_rwsem);
@@ -4375,14 +4398,12 @@
 	if (!rbd_cid_equal(&cid, &rbd_empty_cid)) {
 		down_write(&rbd_dev->lock_rwsem);
 		if (!rbd_cid_equal(&cid, &rbd_dev->owner_cid)) {
-			dout("%s rbd_dev %p unexpected owner, cid %llu-%llu != owner_cid %llu-%llu\n",
+			dout("%s rbd_dev %p cid %llu-%llu != owner_cid %llu-%llu\n",
 			     __func__, rbd_dev, cid.gid, cid.handle,
 			     rbd_dev->owner_cid.gid, rbd_dev->owner_cid.handle);
-			up_write(&rbd_dev->lock_rwsem);
-			return;
+		} else {
+			rbd_set_owner_cid(rbd_dev, &rbd_empty_cid);
 		}
-
-		rbd_set_owner_cid(rbd_dev, &rbd_empty_cid);
 		downgrade_write(&rbd_dev->lock_rwsem);
 	} else {
 		down_read(&rbd_dev->lock_rwsem);
@@ -4636,6 +4657,10 @@
 	cancel_work_sync(&rbd_dev->unlock_work);
 }
 
+/*
+ * header_rwsem must not be held to avoid a deadlock with
+ * rbd_dev_refresh() when flushing notifies.
+ */
 static void rbd_unregister_watch(struct rbd_device *rbd_dev)
 {
 	cancel_tasks_sync(rbd_dev);
@@ -4672,6 +4697,10 @@
 			rbd_warn(rbd_dev, "failed to update lock cookie: %d",
 				 ret);
 
+		if (rbd_dev->opts->exclusive)
+			rbd_warn(rbd_dev,
+			     "temporarily releasing lock on exclusive mapping");
+
 		/*
 		 * Lock cookie cannot be updated on older OSDs, so do
 		 * a manual release and queue an acquire.
@@ -4792,7 +4821,6 @@
 	struct request *rq = blk_mq_rq_from_pdu(work);
 	struct rbd_device *rbd_dev = rq->q->queuedata;
 	struct rbd_img_request *img_request;
-	struct ceph_snap_context *snapc = NULL;
 	u64 offset = (u64)blk_rq_pos(rq) << SECTOR_SHIFT;
 	u64 length = blk_rq_bytes(rq);
 	enum obj_operation_type op_type;
@@ -4857,10 +4885,6 @@
 
 	down_read(&rbd_dev->header_rwsem);
 	mapping_size = rbd_dev->mapping.size;
-	if (op_type != OBJ_OP_READ) {
-		snapc = rbd_dev->header.snapc;
-		ceph_get_snap_context(snapc);
-	}
 	up_read(&rbd_dev->header_rwsem);
 
 	if (offset + length > mapping_size) {
@@ -4870,13 +4894,12 @@
 		goto err_rq;
 	}
 
-	img_request = rbd_img_request_create(rbd_dev, op_type, snapc);
+	img_request = rbd_img_request_create(rbd_dev, op_type);
 	if (!img_request) {
 		result = -ENOMEM;
 		goto err_rq;
 	}
 	img_request->rq = rq;
-	snapc = NULL; /* img_request consumes a ref */
 
 	dout("%s rbd_dev %p img_req %p %s %llu~%llu\n", __func__, rbd_dev,
 	     img_request, obj_op_name(op_type), offset, length);
@@ -4898,7 +4921,6 @@
 	if (result)
 		rbd_warn(rbd_dev, "%s %llx at %llx result %d",
 			 obj_op_name(op_type), length, offset, result);
-	ceph_put_snap_context(snapc);
 err:
 	blk_mq_end_request(rq, errno_to_blk_status(result));
 }
@@ -4970,7 +4992,9 @@
  * return, the rbd_dev->header field will contain up-to-date
  * information about the image.
  */
-static int rbd_dev_v1_header_info(struct rbd_device *rbd_dev)
+static int rbd_dev_v1_header_info(struct rbd_device *rbd_dev,
+				  struct rbd_image_header *header,
+				  bool first_time)
 {
 	struct rbd_image_header_ondisk *ondisk = NULL;
 	u32 snap_count = 0;
@@ -5018,7 +5042,7 @@
 		snap_count = le32_to_cpu(ondisk->snap_count);
 	} while (snap_count != want_count);
 
-	ret = rbd_header_from_disk(rbd_dev, ondisk);
+	ret = rbd_header_from_disk(header, ondisk, first_time);
 out:
 	kfree(ondisk);
 
@@ -5062,43 +5086,6 @@
 	}
 }
 
-static int rbd_dev_refresh(struct rbd_device *rbd_dev)
-{
-	u64 mapping_size;
-	int ret;
-
-	down_write(&rbd_dev->header_rwsem);
-	mapping_size = rbd_dev->mapping.size;
-
-	ret = rbd_dev_header_info(rbd_dev);
-	if (ret)
-		goto out;
-
-	/*
-	 * If there is a parent, see if it has disappeared due to the
-	 * mapped image getting flattened.
-	 */
-	if (rbd_dev->parent) {
-		ret = rbd_dev_v2_parent_info(rbd_dev);
-		if (ret)
-			goto out;
-	}
-
-	if (rbd_dev->spec->snap_id == CEPH_NOSNAP) {
-		rbd_dev->mapping.size = rbd_dev->header.image_size;
-	} else {
-		/* validate mapped snapshot's EXISTS flag */
-		rbd_exists_validate(rbd_dev);
-	}
-
-out:
-	up_write(&rbd_dev->header_rwsem);
-	if (!ret && mapping_size != rbd_dev->mapping.size)
-		rbd_dev_update_size(rbd_dev);
-
-	return ret;
-}
-
 static int rbd_init_request(struct blk_mq_tag_set *set, struct request *rq,
 		unsigned int hctx_idx, unsigned int numa_node)
 {
@@ -5276,6 +5263,9 @@
 {
 	struct rbd_device *rbd_dev = dev_to_rbd_dev(dev);
 
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
 	return sprintf(buf, "%s\n", rbd_dev->config_info);
 }
 
@@ -5387,6 +5377,9 @@
 	struct rbd_device *rbd_dev = dev_to_rbd_dev(dev);
 	int ret;
 
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
 	ret = rbd_dev_refresh(rbd_dev);
 	if (ret)
 		return ret;
@@ -5527,8 +5520,7 @@
 		module_put(THIS_MODULE);
 }
 
-static struct rbd_device *__rbd_dev_create(struct rbd_client *rbdc,
-					   struct rbd_spec *spec)
+static struct rbd_device *__rbd_dev_create(struct rbd_spec *spec)
 {
 	struct rbd_device *rbd_dev;
 
@@ -5564,7 +5556,7 @@
 	INIT_LIST_HEAD(&rbd_dev->acquiring_list);
 	INIT_LIST_HEAD(&rbd_dev->running_list);
 	init_completion(&rbd_dev->acquire_wait);
-	init_completion(&rbd_dev->releasing_wait);
+	init_completion(&rbd_dev->quiescing_wait);
 
 	spin_lock_init(&rbd_dev->object_map_lock);
 
@@ -5573,9 +5565,6 @@
 	rbd_dev->dev.parent = &rbd_root_dev;
 	device_initialize(&rbd_dev->dev);
 
-	rbd_dev->rbd_client = rbdc;
-	rbd_dev->spec = spec;
-
 	return rbd_dev;
 }
 
@@ -5588,12 +5577,10 @@
 {
 	struct rbd_device *rbd_dev;
 
-	rbd_dev = __rbd_dev_create(rbdc, spec);
+	rbd_dev = __rbd_dev_create(spec);
 	if (!rbd_dev)
 		return NULL;
 
-	rbd_dev->opts = opts;
-
 	/* get an id and fill in device name */
 	rbd_dev->dev_id = ida_simple_get(&rbd_dev_id_ida, 0,
 					 minor_to_rbd_dev_id(1 << MINORBITS),
@@ -5610,6 +5597,10 @@
 	/* we have a ref from do_rbd_add() */
 	__module_get(THIS_MODULE);
 
+	rbd_dev->rbd_client = rbdc;
+	rbd_dev->spec = spec;
+	rbd_dev->opts = opts;
+
 	dout("%s rbd_dev %p dev_id %d\n", __func__, rbd_dev, rbd_dev->dev_id);
 	return rbd_dev;
 
@@ -5664,17 +5655,12 @@
 	return 0;
 }
 
-static int rbd_dev_v2_image_size(struct rbd_device *rbd_dev)
-{
-	return _rbd_dev_v2_snap_size(rbd_dev, CEPH_NOSNAP,
-					&rbd_dev->header.obj_order,
-					&rbd_dev->header.image_size);
-}
-
-static int rbd_dev_v2_object_prefix(struct rbd_device *rbd_dev)
+static int rbd_dev_v2_object_prefix(struct rbd_device *rbd_dev,
+				    char **pobject_prefix)
 {
 	size_t size;
 	void *reply_buf;
+	char *object_prefix;
 	int ret;
 	void *p;
 
@@ -5692,16 +5678,16 @@
 		goto out;
 
 	p = reply_buf;
-	rbd_dev->header.object_prefix = ceph_extract_encoded_string(&p,
-						p + ret, NULL, GFP_NOIO);
+	object_prefix = ceph_extract_encoded_string(&p, p + ret, NULL,
+						    GFP_NOIO);
+	if (IS_ERR(object_prefix)) {
+		ret = PTR_ERR(object_prefix);
+		goto out;
+	}
 	ret = 0;
 
-	if (IS_ERR(rbd_dev->header.object_prefix)) {
-		ret = PTR_ERR(rbd_dev->header.object_prefix);
-		rbd_dev->header.object_prefix = NULL;
-	} else {
-		dout("  object_prefix = %s\n", rbd_dev->header.object_prefix);
-	}
+	*pobject_prefix = object_prefix;
+	dout("  object_prefix = %s\n", object_prefix);
 out:
 	kfree(reply_buf);
 
@@ -5746,12 +5732,6 @@
 	return 0;
 }
 
-static int rbd_dev_v2_features(struct rbd_device *rbd_dev)
-{
-	return _rbd_dev_v2_snap_features(rbd_dev, CEPH_NOSNAP,
-						&rbd_dev->header.features);
-}
-
 /*
  * These are generic image flags, but since they are used only for
  * object map, store them in rbd_dev->object_map_flags.
@@ -5788,6 +5768,14 @@
 	u64		overlap;
 };
 
+static void rbd_parent_info_cleanup(struct parent_image_info *pii)
+{
+	kfree(pii->pool_ns);
+	kfree(pii->image_id);
+
+	memset(pii, 0, sizeof(*pii));
+}
+
 /*
  * The caller is responsible for @pii.
  */
@@ -5857,6 +5845,9 @@
 	if (pii->has_overlap)
 		ceph_decode_64_safe(&p, end, pii->overlap, e_inval);
 
+	dout("%s pool_id %llu pool_ns %s image_id %s snap_id %llu has_overlap %d overlap %llu\n",
+	     __func__, pii->pool_id, pii->pool_ns, pii->image_id, pii->snap_id,
+	     pii->has_overlap, pii->overlap);
 	return 0;
 
 e_inval:
@@ -5895,14 +5886,17 @@
 	pii->has_overlap = true;
 	ceph_decode_64_safe(&p, end, pii->overlap, e_inval);
 
+	dout("%s pool_id %llu pool_ns %s image_id %s snap_id %llu has_overlap %d overlap %llu\n",
+	     __func__, pii->pool_id, pii->pool_ns, pii->image_id, pii->snap_id,
+	     pii->has_overlap, pii->overlap);
 	return 0;
 
 e_inval:
 	return -EINVAL;
 }
 
-static int get_parent_info(struct rbd_device *rbd_dev,
-			   struct parent_image_info *pii)
+static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev,
+				  struct parent_image_info *pii)
 {
 	struct page *req_page, *reply_page;
 	void *p;
@@ -5930,7 +5924,7 @@
 	return ret;
 }
 
-static int rbd_dev_v2_parent_info(struct rbd_device *rbd_dev)
+static int rbd_dev_setup_parent(struct rbd_device *rbd_dev)
 {
 	struct rbd_spec *parent_spec;
 	struct parent_image_info pii = { 0 };
@@ -5940,37 +5934,12 @@
 	if (!parent_spec)
 		return -ENOMEM;
 
-	ret = get_parent_info(rbd_dev, &pii);
+	ret = rbd_dev_v2_parent_info(rbd_dev, &pii);
 	if (ret)
 		goto out_err;
 
-	dout("%s pool_id %llu pool_ns %s image_id %s snap_id %llu has_overlap %d overlap %llu\n",
-	     __func__, pii.pool_id, pii.pool_ns, pii.image_id, pii.snap_id,
-	     pii.has_overlap, pii.overlap);
-
-	if (pii.pool_id == CEPH_NOPOOL || !pii.has_overlap) {
-		/*
-		 * Either the parent never existed, or we have
-		 * record of it but the image got flattened so it no
-		 * longer has a parent.  When the parent of a
-		 * layered image disappears we immediately set the
-		 * overlap to 0.  The effect of this is that all new
-		 * requests will be treated as if the image had no
-		 * parent.
-		 *
-		 * If !pii.has_overlap, the parent image spec is not
-		 * applicable.  It's there to avoid duplication in each
-		 * snapshot record.
-		 */
-		if (rbd_dev->parent_overlap) {
-			rbd_dev->parent_overlap = 0;
-			rbd_dev_parent_put(rbd_dev);
-			pr_info("%s: clone image has been flattened\n",
-				rbd_dev->disk->disk_name);
-		}
-
+	if (pii.pool_id == CEPH_NOPOOL || !pii.has_overlap)
 		goto out;	/* No parent?  No problem. */
-	}
 
 	/* The ceph file layout needs to fit pool id in 32 bits */
 
@@ -5982,58 +5951,46 @@
 	}
 
 	/*
-	 * The parent won't change (except when the clone is
-	 * flattened, already handled that).  So we only need to
-	 * record the parent spec we have not already done so.
+	 * The parent won't change except when the clone is flattened,
+	 * so we only need to record the parent image spec once.
 	 */
-	if (!rbd_dev->parent_spec) {
-		parent_spec->pool_id = pii.pool_id;
-		if (pii.pool_ns && *pii.pool_ns) {
-			parent_spec->pool_ns = pii.pool_ns;
-			pii.pool_ns = NULL;
-		}
-		parent_spec->image_id = pii.image_id;
-		pii.image_id = NULL;
-		parent_spec->snap_id = pii.snap_id;
-
-		rbd_dev->parent_spec = parent_spec;
-		parent_spec = NULL;	/* rbd_dev now owns this */
-	}
+	parent_spec->pool_id = pii.pool_id;
+	if (pii.pool_ns && *pii.pool_ns) {
+		parent_spec->pool_ns = pii.pool_ns;
+		pii.pool_ns = NULL;
+	}
+	parent_spec->image_id = pii.image_id;
+	pii.image_id = NULL;
+	parent_spec->snap_id = pii.snap_id;
+
+	rbd_assert(!rbd_dev->parent_spec);
+	rbd_dev->parent_spec = parent_spec;
+	parent_spec = NULL;	/* rbd_dev now owns this */
 
 	/*
-	 * We always update the parent overlap.  If it's zero we issue
-	 * a warning, as we will proceed as if there was no parent.
+	 * Record the parent overlap.  If it's zero, issue a warning as
+	 * we will proceed as if there is no parent.
 	 */
-	if (!pii.overlap) {
-		if (parent_spec) {
-			/* refresh, careful to warn just once */
-			if (rbd_dev->parent_overlap)
-				rbd_warn(rbd_dev,
-				    "clone now standalone (overlap became 0)");
-		} else {
-			/* initial probe */
-			rbd_warn(rbd_dev, "clone is standalone (overlap 0)");
-		}
-	}
+	if (!pii.overlap)
+		rbd_warn(rbd_dev, "clone is standalone (overlap 0)");
 	rbd_dev->parent_overlap = pii.overlap;
 
 out:
 	ret = 0;
 out_err:
-	kfree(pii.pool_ns);
-	kfree(pii.image_id);
+	rbd_parent_info_cleanup(&pii);
 	rbd_spec_put(parent_spec);
 	return ret;
 }
 
-static int rbd_dev_v2_striping_info(struct rbd_device *rbd_dev)
+static int rbd_dev_v2_striping_info(struct rbd_device *rbd_dev,
+				    u64 *stripe_unit, u64 *stripe_count)
 {
 	struct {
 		__le64 stripe_unit;
 		__le64 stripe_count;
 	} __attribute__ ((packed)) striping_info_buf = { 0 };
 	size_t size = sizeof (striping_info_buf);
-	void *p;
 	int ret;
 
 	ret = rbd_obj_method_sync(rbd_dev, &rbd_dev->header_oid,
@@ -6045,27 +6002,33 @@
 	if (ret < size)
 		return -ERANGE;
 
-	p = &striping_info_buf;
-	rbd_dev->header.stripe_unit = ceph_decode_64(&p);
-	rbd_dev->header.stripe_count = ceph_decode_64(&p);
+	*stripe_unit = le64_to_cpu(striping_info_buf.stripe_unit);
+	*stripe_count = le64_to_cpu(striping_info_buf.stripe_count);
+	dout("  stripe_unit = %llu stripe_count = %llu\n", *stripe_unit,
+	     *stripe_count);
+
 	return 0;
 }
 
-static int rbd_dev_v2_data_pool(struct rbd_device *rbd_dev)
+static int rbd_dev_v2_data_pool(struct rbd_device *rbd_dev, s64 *data_pool_id)
 {
-	__le64 data_pool_id;
+	__le64 data_pool_buf;
 	int ret;
 
 	ret = rbd_obj_method_sync(rbd_dev, &rbd_dev->header_oid,
 				  &rbd_dev->header_oloc, "get_data_pool",
-				  NULL, 0, &data_pool_id, sizeof(data_pool_id));
+				  NULL, 0, &data_pool_buf,
+				  sizeof(data_pool_buf));
+	dout("%s: rbd_obj_method_sync returned %d\n", __func__, ret);
 	if (ret < 0)
 		return ret;
-	if (ret < sizeof(data_pool_id))
+	if (ret < sizeof(data_pool_buf))
 		return -EBADMSG;
 
-	rbd_dev->header.data_pool_id = le64_to_cpu(data_pool_id);
-	WARN_ON(rbd_dev->header.data_pool_id == CEPH_NOPOOL);
+	*data_pool_id = le64_to_cpu(data_pool_buf);
+	dout("  data_pool_id = %lld\n", *data_pool_id);
+	WARN_ON(*data_pool_id == CEPH_NOPOOL);
+
 	return 0;
 }
 
@@ -6257,7 +6220,8 @@
 	return ret;
 }
 
-static int rbd_dev_v2_snap_context(struct rbd_device *rbd_dev)
+static int rbd_dev_v2_snap_context(struct rbd_device *rbd_dev,
+				   struct ceph_snap_context **psnapc)
 {
 	size_t size;
 	int ret;
@@ -6318,9 +6282,7 @@
 	for (i = 0; i < snap_count; i++)
 		snapc->snaps[i] = ceph_decode_64(&p);
 
-	ceph_put_snap_context(rbd_dev->header.snapc);
-	rbd_dev->header.snapc = snapc;
-
+	*psnapc = snapc;
 	dout("  snap context seq = %llu, snap_count = %u\n",
 		(unsigned long long)seq, (unsigned int)snap_count);
 out:
@@ -6369,38 +6331,42 @@
 	return snap_name;
 }
 
-static int rbd_dev_v2_header_info(struct rbd_device *rbd_dev)
+static int rbd_dev_v2_header_info(struct rbd_device *rbd_dev,
+				  struct rbd_image_header *header,
+				  bool first_time)
 {
-	bool first_time = rbd_dev->header.object_prefix == NULL;
 	int ret;
 
-	ret = rbd_dev_v2_image_size(rbd_dev);
+	ret = _rbd_dev_v2_snap_size(rbd_dev, CEPH_NOSNAP,
+				    first_time ? &header->obj_order : NULL,
+				    &header->image_size);
 	if (ret)
 		return ret;
 
 	if (first_time) {
-		ret = rbd_dev_v2_header_onetime(rbd_dev);
+		ret = rbd_dev_v2_header_onetime(rbd_dev, header);
 		if (ret)
 			return ret;
 	}
 
-	ret = rbd_dev_v2_snap_context(rbd_dev);
-	if (ret && first_time) {
-		kfree(rbd_dev->header.object_prefix);
-		rbd_dev->header.object_prefix = NULL;
-	}
+	ret = rbd_dev_v2_snap_context(rbd_dev, &header->snapc);
+	if (ret)
+		return ret;
 
-	return ret;
+	return 0;
 }
 
-static int rbd_dev_header_info(struct rbd_device *rbd_dev)
+static int rbd_dev_header_info(struct rbd_device *rbd_dev,
+			       struct rbd_image_header *header,
+			       bool first_time)
 {
 	rbd_assert(rbd_image_format_valid(rbd_dev->image_format));
+	rbd_assert(!header->object_prefix && !header->snapc);
 
 	if (rbd_dev->image_format == 1)
-		return rbd_dev_v1_header_info(rbd_dev);
+		return rbd_dev_v1_header_info(rbd_dev, header, first_time);
 
-	return rbd_dev_v2_header_info(rbd_dev);
+	return rbd_dev_v2_header_info(rbd_dev, header, first_time);
 }
 
 /*
@@ -6652,11 +6618,6 @@
 		return ret;
 	}
 
-	/*
-	 * The lock may have been released by now, unless automatic lock
-	 * transitions are disabled.
-	 */
-	rbd_assert(!rbd_dev->opts->exclusive || rbd_is_lock_owner(rbd_dev));
 	return 0;
 }
 
@@ -6750,60 +6711,49 @@
  */
 static void rbd_dev_unprobe(struct rbd_device *rbd_dev)
 {
-	struct rbd_image_header	*header;
-
 	rbd_dev_parent_put(rbd_dev);
 	rbd_object_map_free(rbd_dev);
 	rbd_dev_mapping_clear(rbd_dev);
 
 	/* Free dynamic fields from the header, then zero it out */
 
-	header = &rbd_dev->header;
-	ceph_put_snap_context(header->snapc);
-	kfree(header->snap_sizes);
-	kfree(header->snap_names);
-	kfree(header->object_prefix);
-	memset(header, 0, sizeof (*header));
+	rbd_image_header_cleanup(&rbd_dev->header);
 }
 
-static int rbd_dev_v2_header_onetime(struct rbd_device *rbd_dev)
+static int rbd_dev_v2_header_onetime(struct rbd_device *rbd_dev,
+				     struct rbd_image_header *header)
 {
 	int ret;
 
-	ret = rbd_dev_v2_object_prefix(rbd_dev);
+	ret = rbd_dev_v2_object_prefix(rbd_dev, &header->object_prefix);
 	if (ret)
-		goto out_err;
+		return ret;
 
 	/*
 	 * Get the and check features for the image.  Currently the
 	 * features are assumed to never change.
 	 */
-	ret = rbd_dev_v2_features(rbd_dev);
+	ret = _rbd_dev_v2_snap_features(rbd_dev, CEPH_NOSNAP,
+					&header->features);
 	if (ret)
-		goto out_err;
+		return ret;
 
 	/* If the image supports fancy striping, get its parameters */
 
-	if (rbd_dev->header.features & RBD_FEATURE_STRIPINGV2) {
-		ret = rbd_dev_v2_striping_info(rbd_dev);
-		if (ret < 0)
-			goto out_err;
+	if (header->features & RBD_FEATURE_STRIPINGV2) {
+		ret = rbd_dev_v2_striping_info(rbd_dev, &header->stripe_unit,
+					       &header->stripe_count);
+		if (ret)
+			return ret;
 	}
 
-	if (rbd_dev->header.features & RBD_FEATURE_DATA_POOL) {
-		ret = rbd_dev_v2_data_pool(rbd_dev);
+	if (header->features & RBD_FEATURE_DATA_POOL) {
+		ret = rbd_dev_v2_data_pool(rbd_dev, &header->data_pool_id);
 		if (ret)
-			goto out_err;
+			return ret;
 	}
 
-	rbd_init_layout(rbd_dev);
 	return 0;
-
-out_err:
-	rbd_dev->header.features = 0;
-	kfree(rbd_dev->header.object_prefix);
-	rbd_dev->header.object_prefix = NULL;
-	return ret;
 }
 
 /*
@@ -6825,7 +6775,7 @@
 		goto out_err;
 	}
 
-	parent = __rbd_dev_create(rbd_dev->rbd_client, rbd_dev->parent_spec);
+	parent = __rbd_dev_create(rbd_dev->parent_spec);
 	if (!parent) {
 		ret = -ENOMEM;
 		goto out_err;
@@ -6835,8 +6785,8 @@
 	 * Images related by parent/child relationships always share
 	 * rbd_client and spec/parent_spec, so bump their refcounts.
 	 */
-	__rbd_get_client(rbd_dev->rbd_client);
-	rbd_spec_get(rbd_dev->parent_spec);
+	parent->rbd_client = __rbd_get_client(rbd_dev->rbd_client);
+	parent->spec = rbd_spec_get(rbd_dev->parent_spec);
 
 	ret = rbd_dev_image_probe(parent, depth);
 	if (ret < 0)
@@ -6929,9 +6879,10 @@
 
 static void rbd_dev_image_release(struct rbd_device *rbd_dev)
 {
-	rbd_dev_unprobe(rbd_dev);
 	if (rbd_dev->opts)
 		rbd_unregister_watch(rbd_dev);
+
+	rbd_dev_unprobe(rbd_dev);
 	rbd_dev->image_format = 0;
 	kfree(rbd_dev->spec->image_id);
 	rbd_dev->spec->image_id = NULL;
@@ -6942,6 +6893,9 @@
  * device.  If this image is the one being mapped (i.e., not a
  * parent), initiate a watch on its header object before using that
  * object to get detailed information about the rbd image.
+ *
+ * On success, returns with header_rwsem held for write if called
+ * with @depth == 0.
  */
 static int rbd_dev_image_probe(struct rbd_device *rbd_dev, int depth)
 {
@@ -6974,9 +6928,14 @@
 		}
 	}
 
-	ret = rbd_dev_header_info(rbd_dev);
+	if (!depth)
+		down_write(&rbd_dev->header_rwsem);
+
+	ret = rbd_dev_header_info(rbd_dev, &rbd_dev->header, true);
 	if (ret)
-		goto err_out_watch;
+		goto err_out_probe;
+
+	rbd_init_layout(rbd_dev);
 
 	/*
 	 * If this image is the one being mapped, we have pool name and
@@ -7011,7 +6970,7 @@
 	}
 
 	if (rbd_dev->header.features & RBD_FEATURE_LAYERING) {
-		ret = rbd_dev_v2_parent_info(rbd_dev);
+		ret = rbd_dev_setup_parent(rbd_dev);
 		if (ret)
 			goto err_out_probe;
 	}
@@ -7025,10 +6984,11 @@
 	return 0;
 
 err_out_probe:
-	rbd_dev_unprobe(rbd_dev);
-err_out_watch:
+	if (!depth)
+		up_write(&rbd_dev->header_rwsem);
 	if (!depth)
 		rbd_unregister_watch(rbd_dev);
+	rbd_dev_unprobe(rbd_dev);
 err_out_format:
 	rbd_dev->image_format = 0;
 	kfree(rbd_dev->spec->image_id);
@@ -7036,6 +6996,112 @@
 	return ret;
 }
 
+static void rbd_dev_update_header(struct rbd_device *rbd_dev,
+				  struct rbd_image_header *header)
+{
+	rbd_assert(rbd_image_format_valid(rbd_dev->image_format));
+	rbd_assert(rbd_dev->header.object_prefix); /* !first_time */
+
+	if (rbd_dev->header.image_size != header->image_size) {
+		rbd_dev->header.image_size = header->image_size;
+
+		if (rbd_dev->spec->snap_id == CEPH_NOSNAP) {
+			rbd_dev->mapping.size = header->image_size;
+			rbd_dev_update_size(rbd_dev);
+		}
+	}
+
+	if (rbd_dev->spec->snap_id != CEPH_NOSNAP) {
+		/* validate mapped snapshot's EXISTS flag */
+		rbd_exists_validate(rbd_dev);
+	}
+
+	ceph_put_snap_context(rbd_dev->header.snapc);
+	rbd_dev->header.snapc = header->snapc;
+	header->snapc = NULL;
+
+	if (rbd_dev->image_format == 1) {
+		kfree(rbd_dev->header.snap_names);
+		rbd_dev->header.snap_names = header->snap_names;
+		header->snap_names = NULL;
+
+		kfree(rbd_dev->header.snap_sizes);
+		rbd_dev->header.snap_sizes = header->snap_sizes;
+		header->snap_sizes = NULL;
+	}
+}
+
+static void rbd_dev_update_parent(struct rbd_device *rbd_dev,
+				  struct parent_image_info *pii)
+{
+	if (pii->pool_id == CEPH_NOPOOL || !pii->has_overlap) {
+		/*
+		 * Either the parent never existed, or we have
+		 * record of it but the image got flattened so it no
+		 * longer has a parent.  When the parent of a
+		 * layered image disappears we immediately set the
+		 * overlap to 0.  The effect of this is that all new
+		 * requests will be treated as if the image had no
+		 * parent.
+		 *
+		 * If !pii.has_overlap, the parent image spec is not
+		 * applicable.  It's there to avoid duplication in each
+		 * snapshot record.
+		 */
+		if (rbd_dev->parent_overlap) {
+			rbd_dev->parent_overlap = 0;
+			rbd_dev_parent_put(rbd_dev);
+			pr_info("%s: clone has been flattened\n",
+				rbd_dev->disk->disk_name);
+		}
+	} else {
+		rbd_assert(rbd_dev->parent_spec);
+
+		/*
+		 * Update the parent overlap.  If it became zero, issue
+		 * a warning as we will proceed as if there is no parent.
+		 */
+		if (!pii->overlap && rbd_dev->parent_overlap)
+			rbd_warn(rbd_dev,
+				 "clone has become standalone (overlap 0)");
+		rbd_dev->parent_overlap = pii->overlap;
+	}
+}
+
+static int rbd_dev_refresh(struct rbd_device *rbd_dev)
+{
+	struct rbd_image_header	header = { 0 };
+	struct parent_image_info pii = { 0 };
+	int ret;
+
+	dout("%s rbd_dev %p\n", __func__, rbd_dev);
+
+	ret = rbd_dev_header_info(rbd_dev, &header, false);
+	if (ret)
+		goto out;
+
+	/*
+	 * If there is a parent, see if it has disappeared due to the
+	 * mapped image getting flattened.
+	 */
+	if (rbd_dev->parent) {
+		ret = rbd_dev_v2_parent_info(rbd_dev, &pii);
+		if (ret)
+			goto out;
+	}
+
+	down_write(&rbd_dev->header_rwsem);
+	rbd_dev_update_header(rbd_dev, &header);
+	if (rbd_dev->parent)
+		rbd_dev_update_parent(rbd_dev, &pii);
+	up_write(&rbd_dev->header_rwsem);
+
+out:
+	rbd_parent_info_cleanup(&pii);
+	rbd_image_header_cleanup(&header);
+	return ret;
+}
+
 static ssize_t do_rbd_add(struct bus_type *bus,
 			  const char *buf,
 			  size_t count)
@@ -7047,6 +7113,9 @@
 	struct rbd_client *rbdc;
 	int rc;
 
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
 	if (!try_module_get(THIS_MODULE))
 		return -ENODEV;
 
@@ -7085,12 +7154,9 @@
 		goto err_out_rbd_dev;
 	}
 
-	down_write(&rbd_dev->header_rwsem);
 	rc = rbd_dev_image_probe(rbd_dev, 0);
-	if (rc < 0) {
-		up_write(&rbd_dev->header_rwsem);
+	if (rc < 0)
 		goto err_out_rbd_dev;
-	}
 
 	/* If we are mapping a snapshot it must be marked read-only */
 	if (rbd_dev->spec->snap_id != CEPH_NOSNAP)
@@ -7199,6 +7265,9 @@
 	bool force = false;
 	int ret;
 
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
 	dev_id = -1;
 	opt_buf[0] = '\0';
 	sscanf(buf, "%d %5s", &dev_id, opt_buf);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/block/rsxx/core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/block/rsxx/core.c
@@ -165,15 +165,17 @@
 {
 	struct rsxx_cardinfo *card = file_inode(fp)->i_private;
 	char *buf;
-	ssize_t st;
+	int st;
 
 	buf = kzalloc(cnt, GFP_KERNEL);
 	if (!buf)
 		return -ENOMEM;
 
 	st = rsxx_creg_read(card, CREG_ADD_CRAM + (u32)*ppos, cnt, buf, 1);
-	if (!st)
-		st = copy_to_user(ubuf, buf, cnt);
+	if (!st) {
+		if (copy_to_user(ubuf, buf, cnt))
+			st = -EFAULT;
+	}
 	kfree(buf);
 	if (st)
 		return st;
@@ -867,6 +869,7 @@
 	card->event_wq = create_singlethread_workqueue(DRIVER_NAME"_event");
 	if (!card->event_wq) {
 		dev_err(CARD_TO_DEV(card), "Failed card event setup.\n");
+		st = -ENOMEM;
 		goto failed_event_handler;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/block/skd_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/block/skd_main.c
@@ -1417,7 +1417,8 @@
 	case SKD_CHECK_STATUS_REPORT_GOOD:
 	case SKD_CHECK_STATUS_REPORT_SMART_ALERT:
 		skreq->status = BLK_STS_OK;
-		blk_mq_complete_request(req);
+		if (likely(!blk_should_fake_timeout(req->q)))
+			blk_mq_complete_request(req);
 		break;
 
 	case SKD_CHECK_STATUS_BUSY_IMMINENT:
@@ -1440,7 +1441,8 @@
 	case SKD_CHECK_STATUS_REPORT_ERROR:
 	default:
 		skreq->status = BLK_STS_IOERR;
-		blk_mq_complete_request(req);
+		if (likely(!blk_should_fake_timeout(req->q)))
+			blk_mq_complete_request(req);
 		break;
 	}
 }
@@ -1560,7 +1562,8 @@
 		 */
 		if (likely(cmp_status == SAM_STAT_GOOD)) {
 			skreq->status = BLK_STS_OK;
-			blk_mq_complete_request(rq);
+			if (likely(!blk_should_fake_timeout(rq->q)))
+				blk_mq_complete_request(rq);
 		} else {
 			skd_resolve_req_exception(skdev, skreq, rq);
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/block/sunvdc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/block/sunvdc.c
@@ -983,6 +983,8 @@
 	print_version();
 
 	hp = mdesc_grab();
+	if (!hp)
+		return -ENODEV;
 
 	err = -ENODEV;
 	if ((vdev->dev_no << PARTITION_SHIFT) & ~(u64)MINORMASK) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/block/virtio_blk.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/block/virtio_blk.c
@@ -33,6 +33,15 @@
 } ____cacheline_aligned_in_smp;
 
 struct virtio_blk {
+	/*
+	 * This mutex must be held by anything that may run after
+	 * virtblk_remove() sets vblk->vdev to NULL.
+	 *
+	 * blk-mq, virtqueue processing, and sysfs attribute code paths are
+	 * shut down before vblk->vdev is set to NULL and therefore do not need
+	 * to hold this mutex.
+	 */
+	struct mutex vdev_mutex;
 	struct virtio_device *vdev;
 
 	/* The disk structure for the kernel. */
@@ -44,6 +53,13 @@
 	/* Process context for config space updates */
 	struct work_struct config_work;
 
+	/*
+	 * Tracks references from block_device_operations open/release and
+	 * virtio_driver probe/remove so this object can be freed once no
+	 * longer in use.
+	 */
+	refcount_t refs;
+
 	/* What host tells us, plus 2 for header & tailer. */
 	unsigned int sg_elems;
 
@@ -189,16 +205,31 @@
 	if (!range)
 		return -ENOMEM;
 
-	__rq_for_each_bio(bio, req) {
-		u64 sector = bio->bi_iter.bi_sector;
-		u32 num_sectors = bio->bi_iter.bi_size >> SECTOR_SHIFT;
-
-		range[n].flags = cpu_to_le32(flags);
-		range[n].num_sectors = cpu_to_le32(num_sectors);
-		range[n].sector = cpu_to_le64(sector);
-		n++;
+	/*
+	 * Single max discard segment means multi-range discard isn't
+	 * supported, and block layer only runs contiguity merge like
+	 * normal RW request. So we can't reply on bio for retrieving
+	 * each range info.
+	 */
+	if (queue_max_discard_segments(req->q) == 1) {
+		range[0].flags = cpu_to_le32(flags);
+		range[0].num_sectors = cpu_to_le32(blk_rq_sectors(req));
+		range[0].sector = cpu_to_le64(blk_rq_pos(req));
+		n = 1;
+	} else {
+		__rq_for_each_bio(bio, req) {
+			u64 sector = bio->bi_iter.bi_sector;
+			u32 num_sectors = bio->bi_iter.bi_size >> SECTOR_SHIFT;
+
+			range[n].flags = cpu_to_le32(flags);
+			range[n].num_sectors = cpu_to_le32(num_sectors);
+			range[n].sector = cpu_to_le64(sector);
+			n++;
+		}
 	}
 
+	WARN_ON_ONCE(n != segments);
+
 	req->special_vec.bv_page = virt_to_page(range);
 	req->special_vec.bv_offset = offset_in_page(range);
 	req->special_vec.bv_len = sizeof(*range) * segments;
@@ -241,7 +272,8 @@
 		while ((vbr = virtqueue_get_buf(vblk->vqs[qid].vq, &len)) != NULL) {
 			struct request *req = blk_mq_rq_from_pdu(vbr);
 
-			blk_mq_complete_request(req);
+			if (likely(!blk_should_fake_timeout(req->q)))
+				blk_mq_complete_request(req);
 			req_done = true;
 		}
 		if (unlikely(virtqueue_is_broken(vq)))
@@ -339,13 +371,20 @@
 		err = virtblk_add_req(vblk->vqs[qid].vq, vbr, vbr->sg, num);
 	if (err) {
 		virtqueue_kick(vblk->vqs[qid].vq);
-		blk_mq_stop_hw_queue(hctx);
+		/* Don't stop the queue if -ENOMEM: we may have failed to
+		 * bounce the buffer due to global resource outage.
+		 */
+		if (err == -ENOSPC)
+			blk_mq_stop_hw_queue(hctx);
 		spin_unlock_irqrestore(&vblk->vqs[qid].lock, flags);
-		/* Out of mem doesn't actually happen, since we fall back
-		 * to direct descriptors */
-		if (err == -ENOMEM || err == -ENOSPC)
+		switch (err) {
+		case -ENOSPC:
 			return BLK_STS_DEV_RESOURCE;
-		return BLK_STS_IOERR;
+		case -ENOMEM:
+			return BLK_STS_RESOURCE;
+		default:
+			return BLK_STS_IOERR;
+		}
 	}
 
 	if (bd->last && virtqueue_kick_prepare(vblk->vqs[qid].vq))
@@ -381,10 +420,55 @@
 	return err;
 }
 
+static void virtblk_get(struct virtio_blk *vblk)
+{
+	refcount_inc(&vblk->refs);
+}
+
+static void virtblk_put(struct virtio_blk *vblk)
+{
+	if (refcount_dec_and_test(&vblk->refs)) {
+		ida_simple_remove(&vd_index_ida, vblk->index);
+		mutex_destroy(&vblk->vdev_mutex);
+		kfree(vblk);
+	}
+}
+
+static int virtblk_open(struct block_device *bd, fmode_t mode)
+{
+	struct virtio_blk *vblk = bd->bd_disk->private_data;
+	int ret = 0;
+
+	mutex_lock(&vblk->vdev_mutex);
+
+	if (vblk->vdev)
+		virtblk_get(vblk);
+	else
+		ret = -ENXIO;
+
+	mutex_unlock(&vblk->vdev_mutex);
+	return ret;
+}
+
+static void virtblk_release(struct gendisk *disk, fmode_t mode)
+{
+	struct virtio_blk *vblk = disk->private_data;
+
+	virtblk_put(vblk);
+}
+
 /* We provide getgeo only to please some old bootloader/partitioning tools */
 static int virtblk_getgeo(struct block_device *bd, struct hd_geometry *geo)
 {
 	struct virtio_blk *vblk = bd->bd_disk->private_data;
+	int ret = 0;
+
+	mutex_lock(&vblk->vdev_mutex);
+
+	if (!vblk->vdev) {
+		ret = -ENXIO;
+		goto out;
+	}
 
 	/* see if the host passed in geometry config */
 	if (virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_GEOMETRY)) {
@@ -400,12 +484,16 @@
 		geo->sectors = 1 << 5;
 		geo->cylinders = get_capacity(bd->bd_disk) >> 11;
 	}
-	return 0;
+out:
+	mutex_unlock(&vblk->vdev_mutex);
+	return ret;
 }
 
 static const struct block_device_operations virtblk_fops = {
 	.ioctl  = virtblk_ioctl,
 	.owner  = THIS_MODULE,
+	.open = virtblk_open,
+	.release = virtblk_release,
 	.getgeo = virtblk_getgeo,
 };
 
@@ -760,6 +848,10 @@
 		goto out_free_index;
 	}
 
+	/* This reference is dropped in virtblk_remove(). */
+	refcount_set(&vblk->refs, 1);
+	mutex_init(&vblk->vdev_mutex);
+
 	vblk->vdev = vdev;
 	vblk->sg_elems = sg_elems;
 
@@ -845,9 +937,17 @@
 	err = virtio_cread_feature(vdev, VIRTIO_BLK_F_BLK_SIZE,
 				   struct virtio_blk_config, blk_size,
 				   &blk_size);
-	if (!err)
+	if (!err) {
+		err = blk_validate_block_size(blk_size);
+		if (err) {
+			dev_err(&vdev->dev,
+				"virtio_blk: invalid block size: 0x%x\n",
+				blk_size);
+			goto out_free_tags;
+		}
+
 		blk_queue_logical_block_size(q, blk_size);
-	else
+	} else
 		blk_size = queue_logical_block_size(q);
 
 	/* Use topology information if available */
@@ -877,11 +977,12 @@
 		blk_queue_io_opt(q, blk_size * opt_io_size);
 
 	if (virtio_has_feature(vdev, VIRTIO_BLK_F_DISCARD)) {
-		q->limits.discard_granularity = blk_size;
-
 		virtio_cread(vdev, struct virtio_blk_config,
 			     discard_sector_alignment, &v);
-		q->limits.discard_alignment = v ? v << SECTOR_SHIFT : 0;
+		if (v)
+			q->limits.discard_granularity = v << SECTOR_SHIFT;
+		else
+			q->limits.discard_granularity = blk_size;
 
 		virtio_cread(vdev, struct virtio_blk_config,
 			     max_discard_sectors, &v);
@@ -889,9 +990,15 @@
 
 		virtio_cread(vdev, struct virtio_blk_config, max_discard_seg,
 			     &v);
+
+		/*
+		 * max_discard_seg == 0 is out of spec but we always
+		 * handled it.
+		 */
+		if (!v)
+			v = sg_elems - 2;
 		blk_queue_max_discard_segments(q,
-					       min_not_zero(v,
-							    MAX_DISCARD_SEGMENTS));
+					       min(v, MAX_DISCARD_SEGMENTS));
 
 		blk_queue_flag_set(QUEUE_FLAG_DISCARD, q);
 	}
@@ -914,6 +1021,7 @@
 	put_disk(vblk->disk);
 out_free_vq:
 	vdev->config->del_vqs(vdev);
+	kfree(vblk->vqs);
 out_free_vblk:
 	kfree(vblk);
 out_free_index:
@@ -925,8 +1033,6 @@
 static void virtblk_remove(struct virtio_device *vdev)
 {
 	struct virtio_blk *vblk = vdev->priv;
-	int index = vblk->index;
-	int refc;
 
 	/* Make sure no work handler is accessing the device. */
 	flush_work(&vblk->config_work);
@@ -936,24 +1042,33 @@
 
 	blk_mq_free_tag_set(&vblk->tag_set);
 
+	mutex_lock(&vblk->vdev_mutex);
+
 	/* Stop all the virtqueues. */
 	vdev->config->reset(vdev);
 
-	refc = kref_read(&disk_to_dev(vblk->disk)->kobj.kref);
+	/* Virtqueues are stopped, nothing can use vblk->vdev anymore. */
+	vblk->vdev = NULL;
+
 	put_disk(vblk->disk);
 	vdev->config->del_vqs(vdev);
 	kfree(vblk->vqs);
-	kfree(vblk);
 
-	/* Only free device id if we don't have any users */
-	if (refc == 1)
-		ida_simple_remove(&vd_index_ida, index);
+	mutex_unlock(&vblk->vdev_mutex);
+
+	virtblk_put(vblk);
 }
 
 #ifdef CONFIG_PM_SLEEP
 static int virtblk_freeze(struct virtio_device *vdev)
 {
 	struct virtio_blk *vblk = vdev->priv;
+	struct request_queue *q = vblk->disk->queue;
+
+	/* Ensure no requests in virtqueues before deleting vqs. */
+	blk_mq_freeze_queue(q);
+	blk_mq_quiesce_queue_nowait(q);
+	blk_mq_unfreeze_queue(q);
 
 	/* Ensure we don't receive any more interrupts */
 	vdev->config->reset(vdev);
@@ -961,9 +1076,9 @@
 	/* Make sure no work handler is accessing the device. */
 	flush_work(&vblk->config_work);
 
-	blk_mq_quiesce_queue(vblk->disk->queue);
-
 	vdev->config->del_vqs(vdev);
+	kfree(vblk->vqs);
+
 	return 0;
 }
 
@@ -977,8 +1092,8 @@
 		return ret;
 
 	virtio_device_ready(vdev);
-
 	blk_mq_unquiesce_queue(vblk->disk->queue);
+
 	return 0;
 }
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/block/xen-blkback/blkback.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/block/xen-blkback/blkback.c
@@ -202,7 +202,7 @@
 
 #define vaddr(page) ((unsigned long)pfn_to_kaddr(page_to_pfn(page)))
 
-static int do_block_io_op(struct xen_blkif_ring *ring);
+static int do_block_io_op(struct xen_blkif_ring *ring, unsigned int *eoi_flags);
 static int dispatch_rw_block_io(struct xen_blkif_ring *ring,
 				struct blkif_request *req,
 				struct pending_req *pending_req);
@@ -615,6 +615,8 @@
 	struct xen_vbd *vbd = &blkif->vbd;
 	unsigned long timeout;
 	int ret;
+	bool do_eoi;
+	unsigned int eoi_flags = XEN_EOI_FLAG_SPURIOUS;
 
 	set_freezable();
 	while (!kthread_should_stop()) {
@@ -639,16 +641,23 @@
 		if (timeout == 0)
 			goto purge_gnt_list;
 
+		do_eoi = ring->waiting_reqs;
+
 		ring->waiting_reqs = 0;
 		smp_mb(); /* clear flag *before* checking for work */
 
-		ret = do_block_io_op(ring);
+		ret = do_block_io_op(ring, &eoi_flags);
 		if (ret > 0)
 			ring->waiting_reqs = 1;
 		if (ret == -EACCES)
 			wait_event_interruptible(ring->shutdown_wq,
 						 kthread_should_stop());
 
+		if (do_eoi && !ring->waiting_reqs) {
+			xen_irq_lateeoi(ring->irq, eoi_flags);
+			eoi_flags |= XEN_EOI_FLAG_SPURIOUS;
+		}
+
 purge_gnt_list:
 		if (blkif->vbd.feature_gnt_persistent &&
 		    time_after(jiffies, ring->next_lru)) {
@@ -841,8 +850,11 @@
 			pages[i]->page = persistent_gnt->page;
 			pages[i]->persistent_gnt = persistent_gnt;
 		} else {
-			if (get_free_page(ring, &pages[i]->page))
-				goto out_of_memory;
+			if (get_free_page(ring, &pages[i]->page)) {
+				put_free_pages(ring, pages_to_gnt, segs_to_map);
+				ret = -ENOMEM;
+				goto out;
+			}
 			addr = vaddr(pages[i]->page);
 			pages_to_gnt[segs_to_map] = pages[i]->page;
 			pages[i]->persistent_gnt = NULL;
@@ -858,10 +870,8 @@
 			break;
 	}
 
-	if (segs_to_map) {
+	if (segs_to_map)
 		ret = gnttab_map_refs(map, NULL, pages_to_gnt, segs_to_map);
-		BUG_ON(ret);
-	}
 
 	/*
 	 * Now swizzle the MFN in our domain with the MFN from the other domain
@@ -876,7 +886,7 @@
 				pr_debug("invalid buffer -- could not remap it\n");
 				put_free_pages(ring, &pages[seg_idx]->page, 1);
 				pages[seg_idx]->handle = BLKBACK_INVALID_HANDLE;
-				ret |= 1;
+				ret |= !ret;
 				goto next;
 			}
 			pages[seg_idx]->handle = map[new_map_idx].handle;
@@ -928,15 +938,18 @@
 	}
 	segs_to_map = 0;
 	last_map = map_until;
-	if (map_until != num)
+	if (!ret && map_until != num)
 		goto again;
 
-	return ret;
+out:
+	for (i = last_map; i < num; i++) {
+		/* Don't zap current batch's valid persistent grants. */
+		if(i >= map_until)
+			pages[i]->persistent_gnt = NULL;
+		pages[i]->handle = BLKBACK_INVALID_HANDLE;
+	}
 
-out_of_memory:
-	pr_alert("%s: out of memory\n", __func__);
-	put_free_pages(ring, pages_to_gnt, segs_to_map);
-	return -ENOMEM;
+	return ret;
 }
 
 static int xen_blkbk_map_seg(struct pending_req *pending_req)
@@ -1119,7 +1132,7 @@
  * and transmute  it to the block API to hand it over to the proper block disk.
  */
 static int
-__do_block_io_op(struct xen_blkif_ring *ring)
+__do_block_io_op(struct xen_blkif_ring *ring, unsigned int *eoi_flags)
 {
 	union blkif_back_rings *blk_rings = &ring->blk_rings;
 	struct blkif_request req;
@@ -1142,6 +1155,9 @@
 		if (RING_REQUEST_CONS_OVERFLOW(&blk_rings->common, rc))
 			break;
 
+		/* We've seen a request, so clear spurious eoi flag. */
+		*eoi_flags &= ~XEN_EOI_FLAG_SPURIOUS;
+
 		if (kthread_should_stop()) {
 			more_to_do = 1;
 			break;
@@ -1200,13 +1216,13 @@
 }
 
 static int
-do_block_io_op(struct xen_blkif_ring *ring)
+do_block_io_op(struct xen_blkif_ring *ring, unsigned int *eoi_flags)
 {
 	union blkif_back_rings *blk_rings = &ring->blk_rings;
 	int more_to_do;
 
 	do {
-		more_to_do = __do_block_io_op(ring);
+		more_to_do = __do_block_io_op(ring, eoi_flags);
 		if (more_to_do)
 			break;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/block/xen-blkback/common.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/block/xen-blkback/common.h
@@ -316,6 +316,7 @@
 
 	struct work_struct	free_work;
 	unsigned int 		nr_ring_pages;
+	bool			multi_ref;
 	/* All rings for this device. */
 	struct xen_blkif_ring	*rings;
 	unsigned int		nr_rings;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/block/xen-blkback/xenbus.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/block/xen-blkback/xenbus.c
@@ -171,6 +171,15 @@
 	blkif->domid = domid;
 	atomic_set(&blkif->refcnt, 1);
 	init_completion(&blkif->drain_complete);
+
+	/*
+	 * Because freeing back to the cache may be deferred, it is not
+	 * safe to unload the module (and hence destroy the cache) until
+	 * this has completed. To prevent premature unloading, take an
+	 * extra module reference here and release only when the object
+	 * has been freed back to the cache.
+	 */
+	__module_get(THIS_MODULE);
 	INIT_WORK(&blkif->free_work, xen_blkif_deferred_free);
 
 	return blkif;
@@ -220,9 +229,8 @@
 		BUG();
 	}
 
-	err = bind_interdomain_evtchn_to_irqhandler(blkif->domid, evtchn,
-						    xen_blkif_be_int, 0,
-						    "blkif-backend", ring);
+	err = bind_interdomain_evtchn_to_irqhandler_lateeoi(blkif->domid,
+			evtchn, xen_blkif_be_int, 0, "blkif-backend", ring);
 	if (err < 0) {
 		xenbus_unmap_ring_vfree(blkif->be->dev, ring->blk_ring);
 		ring->blk_rings.common.sring = NULL;
@@ -248,6 +256,7 @@
 
 		if (ring->xenblkd) {
 			kthread_stop(ring->xenblkd);
+			ring->xenblkd = NULL;
 			wake_up(&ring->shutdown_wq);
 		}
 
@@ -320,6 +329,7 @@
 
 	/* Make sure everything is drained before shutting down */
 	kmem_cache_free(xen_blkif_cachep, blkif);
+	module_put(THIS_MODULE);
 }
 
 int __init xen_blkif_interface_init(void)
@@ -634,7 +644,8 @@
 	/* setup back pointer */
 	be->blkif->be = be;
 
-	err = xenbus_watch_pathfmt(dev, &be->backend_watch, backend_changed,
+	err = xenbus_watch_pathfmt(dev, &be->backend_watch, NULL,
+				   backend_changed,
 				   "%s/%s", dev->nodename, "physical-device");
 	if (err)
 		goto fail;
@@ -938,14 +949,17 @@
 	for (i = 0; i < nr_grefs; i++) {
 		char ring_ref_name[RINGREF_NAME_LEN];
 
-		snprintf(ring_ref_name, RINGREF_NAME_LEN, "ring-ref%u", i);
+		if (blkif->multi_ref)
+			snprintf(ring_ref_name, RINGREF_NAME_LEN, "ring-ref%u", i);
+		else {
+			WARN_ON(i != 0);
+			snprintf(ring_ref_name, RINGREF_NAME_LEN, "ring-ref");
+		}
+
 		err = xenbus_scanf(XBT_NIL, dir, ring_ref_name,
 				   "%u", &ring_ref[i]);
 
 		if (err != 1) {
-			if (nr_grefs == 1)
-				break;
-
 			err = -EINVAL;
 			xenbus_dev_fatal(dev, err, "reading %s/%s",
 					 dir, ring_ref_name);
@@ -953,18 +967,6 @@
 		}
 	}
 
-	if (err != 1) {
-		WARN_ON(nr_grefs != 1);
-
-		err = xenbus_scanf(XBT_NIL, dir, "ring-ref", "%u",
-				   &ring_ref[0]);
-		if (err != 1) {
-			err = -EINVAL;
-			xenbus_dev_fatal(dev, err, "reading %s/ring-ref", dir);
-			return err;
-		}
-	}
-
 	err = -ENOMEM;
 	for (i = 0; i < nr_grefs * XEN_BLKIF_REQS_PER_PAGE; i++) {
 		req = kzalloc(sizeof(*req), GFP_KERNEL);
@@ -1068,10 +1070,15 @@
 		 blkif->nr_rings, blkif->blk_protocol, protocol,
 		 pers_grants ? "persistent grants" : "");
 
-	ring_page_order = xenbus_read_unsigned(dev->otherend,
-					       "ring-page-order", 0);
-
-	if (ring_page_order > xen_blkif_max_ring_order) {
+	err = xenbus_scanf(XBT_NIL, dev->otherend, "ring-page-order", "%u",
+			   &ring_page_order);
+	if (err != 1) {
+		blkif->nr_ring_pages = 1;
+		blkif->multi_ref = false;
+	} else if (ring_page_order <= xen_blkif_max_ring_order) {
+		blkif->nr_ring_pages = 1 << ring_page_order;
+		blkif->multi_ref = true;
+	} else {
 		err = -EINVAL;
 		xenbus_dev_fatal(dev, err,
 				 "requested ring page order %d exceed max:%d",
@@ -1080,8 +1087,6 @@
 		return err;
 	}
 
-	blkif->nr_ring_pages = 1 << ring_page_order;
-
 	if (blkif->nr_rings == 1)
 		return read_per_ring_refs(&blkif->rings[0], dev->otherend);
 	else {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/block/xen-blkfront.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/block/xen-blkfront.c
@@ -47,6 +47,7 @@
 #include <linux/bitmap.h>
 #include <linux/list.h>
 #include <linux/workqueue.h>
+#include <linux/sched/mm.h>
 
 #include <xen/xen.h>
 #include <xen/xenbus.h>
@@ -79,6 +80,7 @@
 	BLKIF_STATE_DISCONNECTED,
 	BLKIF_STATE_CONNECTED,
 	BLKIF_STATE_SUSPENDED,
+	BLKIF_STATE_ERROR,
 };
 
 struct grant {
@@ -88,6 +90,7 @@
 };
 
 enum blk_req_status {
+	REQ_PROCESSING,
 	REQ_WAITING,
 	REQ_DONE,
 	REQ_ERROR,
@@ -148,6 +151,10 @@
 module_param_named(max_ring_page_order, xen_blkif_max_ring_order, int, 0444);
 MODULE_PARM_DESC(max_ring_page_order, "Maximum order of pages to be used for the shared ring");
 
+static bool __read_mostly xen_blkif_trusted = true;
+module_param_named(trusted, xen_blkif_trusted, bool, 0644);
+MODULE_PARM_DESC(trusted, "Is the backend trusted");
+
 #define BLK_RING_SIZE(info)	\
 	__CONST_RING_SIZE(blkif, XEN_PAGE_SIZE * (info)->nr_ring_pages)
 
@@ -208,6 +215,7 @@
 	unsigned int feature_discard:1;
 	unsigned int feature_secdiscard:1;
 	unsigned int feature_persistent:1;
+	unsigned int bounce:1;
 	unsigned int discard_granularity;
 	unsigned int discard_alignment;
 	/* Number of 4KB segments handled */
@@ -297,8 +305,8 @@
 		if (!gnt_list_entry)
 			goto out_of_memory;
 
-		if (info->feature_persistent) {
-			granted_page = alloc_page(GFP_NOIO);
+		if (info->bounce) {
+			granted_page = alloc_page(GFP_NOIO | __GFP_ZERO);
 			if (!granted_page) {
 				kfree(gnt_list_entry);
 				goto out_of_memory;
@@ -317,7 +325,7 @@
 	list_for_each_entry_safe(gnt_list_entry, n,
 	                         &rinfo->grants, node) {
 		list_del(&gnt_list_entry->node);
-		if (info->feature_persistent)
+		if (info->bounce)
 			__free_page(gnt_list_entry->page);
 		kfree(gnt_list_entry);
 		i--;
@@ -363,7 +371,7 @@
 	/* Assign a gref to this page */
 	gnt_list_entry->gref = gnttab_claim_grant_reference(gref_head);
 	BUG_ON(gnt_list_entry->gref == -ENOSPC);
-	if (info->feature_persistent)
+	if (info->bounce)
 		grant_foreign_access(gnt_list_entry, info);
 	else {
 		/* Grant access to the GFN passed by the caller */
@@ -387,7 +395,7 @@
 	/* Assign a gref to this page */
 	gnt_list_entry->gref = gnttab_claim_grant_reference(gref_head);
 	BUG_ON(gnt_list_entry->gref == -ENOSPC);
-	if (!info->feature_persistent) {
+	if (!info->bounce) {
 		struct page *indirect_page;
 
 		/* Fetch a pre-allocated page to use for indirect grefs */
@@ -532,10 +540,10 @@
 
 	id = get_id_from_freelist(rinfo);
 	rinfo->shadow[id].request = req;
-	rinfo->shadow[id].status = REQ_WAITING;
+	rinfo->shadow[id].status = REQ_PROCESSING;
 	rinfo->shadow[id].associated_id = NO_ASSOCIATED_ID;
 
-	(*ring_req)->u.rw.id = id;
+	rinfo->shadow[id].req.u.rw.id = id;
 
 	return id;
 }
@@ -543,11 +551,12 @@
 static int blkif_queue_discard_req(struct request *req, struct blkfront_ring_info *rinfo)
 {
 	struct blkfront_info *info = rinfo->dev_info;
-	struct blkif_request *ring_req;
+	struct blkif_request *ring_req, *final_ring_req;
 	unsigned long id;
 
 	/* Fill out a communications ring structure. */
-	id = blkif_ring_get_request(rinfo, req, &ring_req);
+	id = blkif_ring_get_request(rinfo, req, &final_ring_req);
+	ring_req = &rinfo->shadow[id].req;
 
 	ring_req->operation = BLKIF_OP_DISCARD;
 	ring_req->u.discard.nr_sectors = blk_rq_sectors(req);
@@ -558,8 +567,9 @@
 	else
 		ring_req->u.discard.flag = 0;
 
-	/* Keep a private copy so we can reissue requests when recovering. */
-	rinfo->shadow[id].req = *ring_req;
+	/* Copy the request to the ring page. */
+	*final_ring_req = *ring_req;
+	rinfo->shadow[id].status = REQ_WAITING;
 
 	return 0;
 }
@@ -692,6 +702,7 @@
 {
 	struct blkfront_info *info = rinfo->dev_info;
 	struct blkif_request *ring_req, *extra_ring_req = NULL;
+	struct blkif_request *final_ring_req, *final_extra_ring_req = NULL;
 	unsigned long id, extra_id = NO_ASSOCIATED_ID;
 	bool require_extra_req = false;
 	int i;
@@ -699,7 +710,7 @@
 		.grant_idx = 0,
 		.segments = NULL,
 		.rinfo = rinfo,
-		.need_copy = rq_data_dir(req) && info->feature_persistent,
+		.need_copy = rq_data_dir(req) && info->bounce,
 	};
 
 	/*
@@ -736,7 +747,8 @@
 	}
 
 	/* Fill out a communications ring structure. */
-	id = blkif_ring_get_request(rinfo, req, &ring_req);
+	id = blkif_ring_get_request(rinfo, req, &final_ring_req);
+	ring_req = &rinfo->shadow[id].req;
 
 	num_sg = blk_rq_map_sg(req->q, req, rinfo->shadow[id].sg);
 	num_grant = 0;
@@ -767,7 +779,8 @@
 		ring_req->u.rw.handle = info->handle;
 		ring_req->operation = rq_data_dir(req) ?
 			BLKIF_OP_WRITE : BLKIF_OP_READ;
-		if (req_op(req) == REQ_OP_FLUSH || req->cmd_flags & REQ_FUA) {
+		if (req_op(req) == REQ_OP_FLUSH ||
+		    (req_op(req) == REQ_OP_WRITE && (req->cmd_flags & REQ_FUA))) {
 			/*
 			 * Ideally we can do an unordered flush-to-disk.
 			 * In case the backend onlysupports barriers, use that.
@@ -787,7 +800,9 @@
 		ring_req->u.rw.nr_segments = num_grant;
 		if (unlikely(require_extra_req)) {
 			extra_id = blkif_ring_get_request(rinfo, req,
-							  &extra_ring_req);
+							  &final_extra_ring_req);
+			extra_ring_req = &rinfo->shadow[extra_id].req;
+
 			/*
 			 * Only the first request contains the scatter-gather
 			 * list.
@@ -829,10 +844,13 @@
 	if (setup.segments)
 		kunmap_atomic(setup.segments);
 
-	/* Keep a private copy so we can reissue requests when recovering. */
-	rinfo->shadow[id].req = *ring_req;
-	if (unlikely(require_extra_req))
-		rinfo->shadow[extra_id].req = *extra_ring_req;
+	/* Copy request(s) to the ring page. */
+	*final_ring_req = *ring_req;
+	rinfo->shadow[id].status = REQ_WAITING;
+	if (unlikely(require_extra_req)) {
+		*final_extra_ring_req = *extra_ring_req;
+		rinfo->shadow[extra_id].status = REQ_WAITING;
+	}
 
 	if (new_persistent_gnts)
 		gnttab_free_grant_references(setup.gref_head);
@@ -935,7 +953,8 @@
 	if (info->feature_discard) {
 		blk_queue_flag_set(QUEUE_FLAG_DISCARD, rq);
 		blk_queue_max_discard_sectors(rq, get_capacity(gd));
-		rq->limits.discard_granularity = info->discard_granularity;
+		rq->limits.discard_granularity = info->discard_granularity ?:
+						 info->physical_sector_size;
 		rq->limits.discard_alignment = info->discard_alignment;
 		if (info->feature_secdiscard)
 			blk_queue_flag_set(QUEUE_FLAG_SECERASE, rq);
@@ -1013,11 +1032,12 @@
 {
 	blk_queue_write_cache(info->rq, info->feature_flush ? true : false,
 			      info->feature_fua ? true : false);
-	pr_info("blkfront: %s: %s %s %s %s %s\n",
+	pr_info("blkfront: %s: %s %s %s %s %s %s %s\n",
 		info->gd->disk_name, flush_info(info),
 		"persistent grants:", info->feature_persistent ?
 		"enabled;" : "disabled;", "indirect descriptors:",
-		info->max_indirect_segments ? "enabled;" : "disabled;");
+		info->max_indirect_segments ? "enabled;" : "disabled;",
+		"bounce buffer:", info->bounce ? "enabled" : "disabled;");
 }
 
 static int xen_translate_vdev(int vdevice, int *minor, unsigned int *offset)
@@ -1113,8 +1133,8 @@
 	if (!VDEV_IS_EXTENDED(info->vdevice)) {
 		err = xen_translate_vdev(info->vdevice, &minor, &offset);
 		if (err)
-			return err;		
- 		nr_parts = PARTS_PER_DISK;
+			return err;
+		nr_parts = PARTS_PER_DISK;
 	} else {
 		minor = BLKIF_MINOR_EXT(info->vdevice);
 		nr_parts = PARTS_PER_EXT_DISK;
@@ -1252,7 +1272,7 @@
 	if (!list_empty(&rinfo->indirect_pages)) {
 		struct page *indirect_page, *n;
 
-		BUG_ON(info->feature_persistent);
+		BUG_ON(info->bounce);
 		list_for_each_entry_safe(indirect_page, n, &rinfo->indirect_pages, lru) {
 			list_del(&indirect_page->lru);
 			__free_page(indirect_page);
@@ -1269,7 +1289,7 @@
 							  0, 0UL);
 				rinfo->persistent_gnts_c--;
 			}
-			if (info->feature_persistent)
+			if (info->bounce)
 				__free_page(persistent_gnt->page);
 			kfree(persistent_gnt);
 		}
@@ -1290,7 +1310,7 @@
 		for (j = 0; j < segs; j++) {
 			persistent_gnt = rinfo->shadow[i].grants_used[j];
 			gnttab_end_foreign_access(persistent_gnt->gref, 0, 0UL);
-			if (info->feature_persistent)
+			if (info->bounce)
 				__free_page(persistent_gnt->page);
 			kfree(persistent_gnt);
 		}
@@ -1331,7 +1351,8 @@
 			rinfo->ring_ref[i] = GRANT_INVALID_REF;
 		}
 	}
-	free_pages((unsigned long)rinfo->ring.sring, get_order(info->nr_ring_pages * XEN_PAGE_SIZE));
+	free_pages_exact(rinfo->ring.sring,
+			 info->nr_ring_pages * XEN_PAGE_SIZE);
 	rinfo->ring.sring = NULL;
 
 	if (rinfo->irq)
@@ -1405,8 +1426,8 @@
 static int blkif_get_final_status(enum blk_req_status s1,
 				  enum blk_req_status s2)
 {
-	BUG_ON(s1 == REQ_WAITING);
-	BUG_ON(s2 == REQ_WAITING);
+	BUG_ON(s1 < REQ_DONE);
+	BUG_ON(s2 < REQ_DONE);
 
 	if (s1 == REQ_ERROR || s2 == REQ_ERROR)
 		return BLKIF_RSP_ERROR;
@@ -1415,9 +1436,15 @@
 	return BLKIF_RSP_OKAY;
 }
 
-static bool blkif_completion(unsigned long *id,
-			     struct blkfront_ring_info *rinfo,
-			     struct blkif_response *bret)
+/*
+ * Return values:
+ *  1 response processed.
+ *  0 missing further responses.
+ * -1 error while processing.
+ */
+static int blkif_completion(unsigned long *id,
+			    struct blkfront_ring_info *rinfo,
+			    struct blkif_response *bret)
 {
 	int i = 0;
 	struct scatterlist *sg;
@@ -1439,8 +1466,8 @@
 		s->status = blkif_rsp_to_req_status(bret->status);
 
 		/* Wait the second response if not yet here. */
-		if (s2->status == REQ_WAITING)
-			return false;
+		if (s2->status < REQ_DONE)
+			return 0;
 
 		bret->status = blkif_get_final_status(s->status,
 						      s2->status);
@@ -1473,7 +1500,7 @@
 	data.s = s;
 	num_sg = s->num_sg;
 
-	if (bret->operation == BLKIF_OP_READ && info->feature_persistent) {
+	if (bret->operation == BLKIF_OP_READ && info->bounce) {
 		for_each_sg(s->sg, sg, num_sg, i) {
 			BUG_ON(sg->offset + sg->length > PAGE_SIZE);
 
@@ -1491,47 +1518,48 @@
 	}
 	/* Add the persistent grant into the list of free grants */
 	for (i = 0; i < num_grant; i++) {
-		if (gnttab_query_foreign_access(s->grants_used[i]->gref)) {
+		if (!gnttab_try_end_foreign_access(s->grants_used[i]->gref)) {
 			/*
 			 * If the grant is still mapped by the backend (the
 			 * backend has chosen to make this grant persistent)
 			 * we add it at the head of the list, so it will be
 			 * reused first.
 			 */
-			if (!info->feature_persistent)
-				pr_alert_ratelimited("backed has not unmapped grant: %u\n",
-						     s->grants_used[i]->gref);
+			if (!info->feature_persistent) {
+				pr_alert("backed has not unmapped grant: %u\n",
+					 s->grants_used[i]->gref);
+				return -1;
+			}
 			list_add(&s->grants_used[i]->node, &rinfo->grants);
 			rinfo->persistent_gnts_c++;
 		} else {
 			/*
-			 * If the grant is not mapped by the backend we end the
-			 * foreign access and add it to the tail of the list,
-			 * so it will not be picked again unless we run out of
-			 * persistent grants.
+			 * If the grant is not mapped by the backend we add it
+			 * to the tail of the list, so it will not be picked
+			 * again unless we run out of persistent grants.
 			 */
-			gnttab_end_foreign_access(s->grants_used[i]->gref, 0, 0UL);
 			s->grants_used[i]->gref = GRANT_INVALID_REF;
 			list_add_tail(&s->grants_used[i]->node, &rinfo->grants);
 		}
 	}
 	if (s->req.operation == BLKIF_OP_INDIRECT) {
 		for (i = 0; i < INDIRECT_GREFS(num_grant); i++) {
-			if (gnttab_query_foreign_access(s->indirect_grants[i]->gref)) {
-				if (!info->feature_persistent)
-					pr_alert_ratelimited("backed has not unmapped grant: %u\n",
-							     s->indirect_grants[i]->gref);
+			if (!gnttab_try_end_foreign_access(s->indirect_grants[i]->gref)) {
+				if (!info->feature_persistent) {
+					pr_alert("backed has not unmapped grant: %u\n",
+						 s->indirect_grants[i]->gref);
+					return -1;
+				}
 				list_add(&s->indirect_grants[i]->node, &rinfo->grants);
 				rinfo->persistent_gnts_c++;
 			} else {
 				struct page *indirect_page;
 
-				gnttab_end_foreign_access(s->indirect_grants[i]->gref, 0, 0UL);
 				/*
 				 * Add the used indirect page back to the list of
 				 * available pages for indirect grefs.
 				 */
-				if (!info->feature_persistent) {
+				if (!info->bounce) {
 					indirect_page = s->indirect_grants[i]->page;
 					list_add(&indirect_page->lru, &rinfo->indirect_pages);
 				}
@@ -1541,71 +1569,103 @@
 		}
 	}
 
-	return true;
+	return 1;
 }
 
 static irqreturn_t blkif_interrupt(int irq, void *dev_id)
 {
 	struct request *req;
-	struct blkif_response *bret;
+	struct blkif_response bret;
 	RING_IDX i, rp;
 	unsigned long flags;
 	struct blkfront_ring_info *rinfo = (struct blkfront_ring_info *)dev_id;
 	struct blkfront_info *info = rinfo->dev_info;
+	unsigned int eoiflag = XEN_EOI_FLAG_SPURIOUS;
 
-	if (unlikely(info->connected != BLKIF_STATE_CONNECTED))
+	if (unlikely(info->connected != BLKIF_STATE_CONNECTED)) {
+		xen_irq_lateeoi(irq, XEN_EOI_FLAG_SPURIOUS);
 		return IRQ_HANDLED;
+	}
 
 	spin_lock_irqsave(&rinfo->ring_lock, flags);
  again:
-	rp = rinfo->ring.sring->rsp_prod;
-	rmb(); /* Ensure we see queued responses up to 'rp'. */
+	rp = READ_ONCE(rinfo->ring.sring->rsp_prod);
+	virt_rmb(); /* Ensure we see queued responses up to 'rp'. */
+	if (RING_RESPONSE_PROD_OVERFLOW(&rinfo->ring, rp)) {
+		pr_alert("%s: illegal number of responses %u\n",
+			 info->gd->disk_name, rp - rinfo->ring.rsp_cons);
+		goto err;
+	}
 
 	for (i = rinfo->ring.rsp_cons; i != rp; i++) {
 		unsigned long id;
+		unsigned int op;
+
+		eoiflag = 0;
+
+		RING_COPY_RESPONSE(&rinfo->ring, i, &bret);
+		id = bret.id;
 
-		bret = RING_GET_RESPONSE(&rinfo->ring, i);
-		id   = bret->id;
 		/*
 		 * The backend has messed up and given us an id that we would
 		 * never have given to it (we stamp it up to BLK_RING_SIZE -
 		 * look in get_id_from_freelist.
 		 */
 		if (id >= BLK_RING_SIZE(info)) {
-			WARN(1, "%s: response to %s has incorrect id (%ld)\n",
-			     info->gd->disk_name, op_name(bret->operation), id);
-			/* We can't safely get the 'struct request' as
-			 * the id is busted. */
-			continue;
+			pr_alert("%s: response has incorrect id (%ld)\n",
+				 info->gd->disk_name, id);
+			goto err;
 		}
+		if (rinfo->shadow[id].status != REQ_WAITING) {
+			pr_alert("%s: response references no pending request\n",
+				 info->gd->disk_name);
+			goto err;
+		}
+
+		rinfo->shadow[id].status = REQ_PROCESSING;
 		req  = rinfo->shadow[id].request;
 
-		if (bret->operation != BLKIF_OP_DISCARD) {
+		op = rinfo->shadow[id].req.operation;
+		if (op == BLKIF_OP_INDIRECT)
+			op = rinfo->shadow[id].req.u.indirect.indirect_op;
+		if (bret.operation != op) {
+			pr_alert("%s: response has wrong operation (%u instead of %u)\n",
+				 info->gd->disk_name, bret.operation, op);
+			goto err;
+		}
+
+		if (bret.operation != BLKIF_OP_DISCARD) {
+			int ret;
+
 			/*
 			 * We may need to wait for an extra response if the
 			 * I/O request is split in 2
 			 */
-			if (!blkif_completion(&id, rinfo, bret))
+			ret = blkif_completion(&id, rinfo, &bret);
+			if (!ret)
 				continue;
+			if (unlikely(ret < 0))
+				goto err;
 		}
 
 		if (add_id_to_freelist(rinfo, id)) {
 			WARN(1, "%s: response to %s (id %ld) couldn't be recycled!\n",
-			     info->gd->disk_name, op_name(bret->operation), id);
+			     info->gd->disk_name, op_name(bret.operation), id);
 			continue;
 		}
 
-		if (bret->status == BLKIF_RSP_OKAY)
+		if (bret.status == BLKIF_RSP_OKAY)
 			blkif_req(req)->error = BLK_STS_OK;
 		else
 			blkif_req(req)->error = BLK_STS_IOERR;
 
-		switch (bret->operation) {
+		switch (bret.operation) {
 		case BLKIF_OP_DISCARD:
-			if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) {
+			if (unlikely(bret.status == BLKIF_RSP_EOPNOTSUPP)) {
 				struct request_queue *rq = info->rq;
-				printk(KERN_WARNING "blkfront: %s: %s op failed\n",
-					   info->gd->disk_name, op_name(bret->operation));
+
+				pr_warn_ratelimited("blkfront: %s: %s op failed\n",
+					   info->gd->disk_name, op_name(bret.operation));
 				blkif_req(req)->error = BLK_STS_NOTSUPP;
 				info->feature_discard = 0;
 				info->feature_secdiscard = 0;
@@ -1615,15 +1675,15 @@
 			break;
 		case BLKIF_OP_FLUSH_DISKCACHE:
 		case BLKIF_OP_WRITE_BARRIER:
-			if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) {
-				printk(KERN_WARNING "blkfront: %s: %s op failed\n",
-				       info->gd->disk_name, op_name(bret->operation));
+			if (unlikely(bret.status == BLKIF_RSP_EOPNOTSUPP)) {
+				pr_warn_ratelimited("blkfront: %s: %s op failed\n",
+				       info->gd->disk_name, op_name(bret.operation));
 				blkif_req(req)->error = BLK_STS_NOTSUPP;
 			}
-			if (unlikely(bret->status == BLKIF_RSP_ERROR &&
+			if (unlikely(bret.status == BLKIF_RSP_ERROR &&
 				     rinfo->shadow[id].req.u.rw.nr_segments == 0)) {
-				printk(KERN_WARNING "blkfront: %s: empty %s op failed\n",
-				       info->gd->disk_name, op_name(bret->operation));
+				pr_warn_ratelimited("blkfront: %s: empty %s op failed\n",
+				       info->gd->disk_name, op_name(bret.operation));
 				blkif_req(req)->error = BLK_STS_NOTSUPP;
 			}
 			if (unlikely(blkif_req(req)->error)) {
@@ -1636,16 +1696,18 @@
 			/* fall through */
 		case BLKIF_OP_READ:
 		case BLKIF_OP_WRITE:
-			if (unlikely(bret->status != BLKIF_RSP_OKAY))
-				dev_dbg(&info->xbdev->dev, "Bad return from blkdev data "
-					"request: %x\n", bret->status);
+			if (unlikely(bret.status != BLKIF_RSP_OKAY))
+				dev_dbg_ratelimited(&info->xbdev->dev,
+					"Bad return from blkdev data request: %#x\n",
+					bret.status);
 
 			break;
 		default:
 			BUG();
 		}
 
-		blk_mq_complete_request(req);
+		if (likely(!blk_should_fake_timeout(req->q)))
+			blk_mq_complete_request(req);
 	}
 
 	rinfo->ring.rsp_cons = i;
@@ -1662,6 +1724,18 @@
 
 	spin_unlock_irqrestore(&rinfo->ring_lock, flags);
 
+	xen_irq_lateeoi(irq, eoiflag);
+
+	return IRQ_HANDLED;
+
+ err:
+	info->connected = BLKIF_STATE_ERROR;
+
+	spin_unlock_irqrestore(&rinfo->ring_lock, flags);
+
+	/* No EOI in order to avoid further interrupts. */
+
+	pr_alert("%s disabled for further use\n", info->gd->disk_name);
 	return IRQ_HANDLED;
 }
 
@@ -1678,8 +1752,7 @@
 	for (i = 0; i < info->nr_ring_pages; i++)
 		rinfo->ring_ref[i] = GRANT_INVALID_REF;
 
-	sring = (struct blkif_sring *)__get_free_pages(GFP_NOIO | __GFP_HIGH,
-						       get_order(ring_size));
+	sring = alloc_pages_exact(ring_size, GFP_NOIO | __GFP_ZERO);
 	if (!sring) {
 		xenbus_dev_fatal(dev, -ENOMEM, "allocating shared ring");
 		return -ENOMEM;
@@ -1689,7 +1762,7 @@
 
 	err = xenbus_grant_ring(dev, rinfo->ring.sring, info->nr_ring_pages, gref);
 	if (err < 0) {
-		free_pages((unsigned long)sring, get_order(ring_size));
+		free_pages_exact(sring, ring_size);
 		rinfo->ring.sring = NULL;
 		goto fail;
 	}
@@ -1700,8 +1773,8 @@
 	if (err)
 		goto fail;
 
-	err = bind_evtchn_to_irqhandler(rinfo->evtchn, blkif_interrupt, 0,
-					"blkif", rinfo);
+	err = bind_evtchn_to_irqhandler_lateeoi(rinfo->evtchn, blkif_interrupt,
+						0, "blkif", rinfo);
 	if (err <= 0) {
 		xenbus_dev_fatal(dev, err,
 				 "bind_evtchn_to_irqhandler failed");
@@ -1782,6 +1855,10 @@
 	if (!info)
 		return -ENODEV;
 
+	/* Check if backend is trusted. */
+	info->bounce = !xen_blkif_trusted ||
+		       !xenbus_read_unsigned(dev->nodename, "trusted", 1);
+
 	max_page_order = xenbus_read_unsigned(info->xbdev->otherend,
 					      "max-ring-page-order", 0);
 	ring_page_order = min(xen_blkif_max_ring_order, max_page_order);
@@ -2168,19 +2245,12 @@
 
 static void blkfront_setup_discard(struct blkfront_info *info)
 {
-	int err;
-	unsigned int discard_granularity;
-	unsigned int discard_alignment;
-
 	info->feature_discard = 1;
-	err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
-		"discard-granularity", "%u", &discard_granularity,
-		"discard-alignment", "%u", &discard_alignment,
-		NULL);
-	if (!err) {
-		info->discard_granularity = discard_granularity;
-		info->discard_alignment = discard_alignment;
-	}
+	info->discard_granularity = xenbus_read_unsigned(info->xbdev->otherend,
+							 "discard-granularity",
+							 0);
+	info->discard_alignment = xenbus_read_unsigned(info->xbdev->otherend,
+						       "discard-alignment", 0);
 	info->feature_secdiscard =
 		!!xenbus_read_unsigned(info->xbdev->otherend, "discard-secure",
 				       0);
@@ -2188,10 +2258,12 @@
 
 static int blkfront_setup_indirect(struct blkfront_ring_info *rinfo)
 {
-	unsigned int psegs, grants;
+	unsigned int psegs, grants, memflags;
 	int err, i;
 	struct blkfront_info *info = rinfo->dev_info;
 
+	memflags = memalloc_noio_save();
+
 	if (info->max_indirect_segments == 0) {
 		if (!HAS_EXTRA_REQ)
 			grants = BLKIF_MAX_SEGMENTS_PER_REQUEST;
@@ -2213,17 +2285,18 @@
 	if (err)
 		goto out_of_memory;
 
-	if (!info->feature_persistent && info->max_indirect_segments) {
+	if (!info->bounce && info->max_indirect_segments) {
 		/*
-		 * We are using indirect descriptors but not persistent
-		 * grants, we need to allocate a set of pages that can be
+		 * We are using indirect descriptors but don't have a bounce
+		 * buffer, we need to allocate a set of pages that can be
 		 * used for mapping indirect grefs
 		 */
 		int num = INDIRECT_GREFS(grants) * BLK_RING_SIZE(info);
 
 		BUG_ON(!list_empty(&rinfo->indirect_pages));
 		for (i = 0; i < num; i++) {
-			struct page *indirect_page = alloc_page(GFP_NOIO);
+			struct page *indirect_page = alloc_page(GFP_KERNEL |
+			                                        __GFP_ZERO);
 			if (!indirect_page)
 				goto out_of_memory;
 			list_add(&indirect_page->lru, &rinfo->indirect_pages);
@@ -2234,15 +2307,15 @@
 		rinfo->shadow[i].grants_used =
 			kvcalloc(grants,
 				 sizeof(rinfo->shadow[i].grants_used[0]),
-				 GFP_NOIO);
+				 GFP_KERNEL);
 		rinfo->shadow[i].sg = kvcalloc(psegs,
 					       sizeof(rinfo->shadow[i].sg[0]),
-					       GFP_NOIO);
+					       GFP_KERNEL);
 		if (info->max_indirect_segments)
 			rinfo->shadow[i].indirect_grants =
 				kvcalloc(INDIRECT_GREFS(grants),
 					 sizeof(rinfo->shadow[i].indirect_grants[0]),
-					 GFP_NOIO);
+					 GFP_KERNEL);
 		if ((rinfo->shadow[i].grants_used == NULL) ||
 			(rinfo->shadow[i].sg == NULL) ||
 		     (info->max_indirect_segments &&
@@ -2251,6 +2324,7 @@
 		sg_init_table(rinfo->shadow[i].sg, psegs);
 	}
 
+	memalloc_noio_restore(memflags);
 
 	return 0;
 
@@ -2270,6 +2344,9 @@
 			__free_page(indirect_page);
 		}
 	}
+
+	memalloc_noio_restore(memflags);
+
 	return -ENOMEM;
 }
 
@@ -2311,6 +2388,8 @@
 	info->feature_persistent =
 		!!xenbus_read_unsigned(info->xbdev->otherend,
 				       "feature-persistent", 0);
+	if (info->feature_persistent)
+		info->bounce = true;
 
 	indirect_segments = xenbus_read_unsigned(info->xbdev->otherend,
 					"feature-max-indirect-segments", 0);
@@ -2668,11 +2747,10 @@
 		list_for_each_entry_safe(gnt_list_entry, tmp, &rinfo->grants,
 					 node) {
 			if (gnt_list_entry->gref == GRANT_INVALID_REF ||
-			    gnttab_query_foreign_access(gnt_list_entry->gref))
+			    !gnttab_try_end_foreign_access(gnt_list_entry->gref))
 				continue;
 
 			list_del(&gnt_list_entry->node);
-			gnttab_end_foreign_access(gnt_list_entry->gref, 0, 0UL);
 			rinfo->persistent_gnts_c--;
 			gnt_list_entry->gref = GRANT_INVALID_REF;
 			list_add_tail(&gnt_list_entry->node, &rinfo->grants);
@@ -2687,6 +2765,13 @@
 	struct blkfront_info *info;
 	bool need_schedule_work = false;
 
+	/*
+	 * Note that when using bounce buffers but not persistent grants
+	 * there's no need to run blkfront_delay_work because grants are
+	 * revoked in blkif_completion or else an error is reported and the
+	 * connection is closed.
+	 */
+
 	mutex_lock(&blkfront_mutex);
 
 	list_for_each_entry(info, &info_list, info_list) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/block/zram/zram_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/block/zram/zram_drv.c
@@ -495,6 +495,12 @@
 	}
 
 	nr_pages = i_size_read(inode) >> PAGE_SHIFT;
+	/* Refuse to use zero sized device (also prevents self reference) */
+	if (!nr_pages) {
+		err = -EINVAL;
+		goto out;
+	}
+
 	bitmap_sz = BITS_TO_LONGS(nr_pages) * sizeof(long);
 	bitmap = kvzalloc(bitmap_sz, GFP_KERNEL);
 	if (!bitmap) {
@@ -626,8 +632,8 @@
 	struct bio bio;
 	struct bio_vec bio_vec;
 	struct page *page;
-	ssize_t ret;
-	int mode;
+	ssize_t ret = len;
+	int mode, err;
 	unsigned long blk_idx = 0;
 
 	if (sysfs_streq(buf, "idle"))
@@ -719,12 +725,17 @@
 		 * XXX: A single page IO would be inefficient for write
 		 * but it would be not bad as starter.
 		 */
-		ret = submit_bio_wait(&bio);
-		if (ret) {
+		err = submit_bio_wait(&bio);
+		if (err) {
 			zram_slot_lock(zram, index);
 			zram_clear_flag(zram, index, ZRAM_UNDER_WB);
 			zram_clear_flag(zram, index, ZRAM_IDLE);
 			zram_slot_unlock(zram, index);
+			/*
+			 * Return last IO error unless every IO were
+			 * not suceeded.
+			 */
+			ret = err;
 			continue;
 		}
 
@@ -762,7 +773,6 @@
 
 	if (blk_idx)
 		free_block_bdev(zram, blk_idx);
-	ret = len;
 	__free_page(page);
 release_init_lock:
 	up_read(&zram->init_lock);
@@ -897,7 +907,7 @@
 			zram_test_flag(zram, index, ZRAM_HUGE) ? 'h' : '.',
 			zram_test_flag(zram, index, ZRAM_IDLE) ? 'i' : '.');
 
-		if (count < copied) {
+		if (count <= copied) {
 			zram_slot_unlock(zram, index);
 			break;
 		}
@@ -1073,7 +1083,7 @@
 			zram->limit_pages << PAGE_SHIFT,
 			max_used << PAGE_SHIFT,
 			(u64)atomic64_read(&zram->stats.same_pages),
-			pool_stats.pages_compacted,
+			atomic_long_read(&pool_stats.pages_compacted),
 			(u64)atomic64_read(&zram->stats.huge_pages));
 	up_read(&zram->init_lock);
 
@@ -2024,7 +2034,8 @@
 		return ret;
 	return scnprintf(buf, PAGE_SIZE, "%d\n", ret);
 }
-static CLASS_ATTR_RO(hot_add);
+static struct class_attribute class_attr_hot_add =
+	__ATTR(hot_add, 0400, hot_add_show, NULL);
 
 static ssize_t hot_remove_store(struct class *class,
 			struct class_attribute *attr,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/bluetooth/ath3k.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/bluetooth/ath3k.c
@@ -3,7 +3,6 @@
  * Copyright (c) 2008-2009 Atheros Communications Inc.
  */
 
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -129,7 +128,6 @@
  * for AR3012
  */
 static const struct usb_device_id ath3k_blist_tbl[] = {
-
 	/* Atheros AR3012 with sflash firmware*/
 	{ USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 },
@@ -203,7 +201,7 @@
 #define TIMEGAP_USEC_MAX	100
 
 static int ath3k_load_firmware(struct usb_device *udev,
-				const struct firmware *firmware)
+			       const struct firmware *firmware)
 {
 	u8 *send_buf;
 	int len = 0;
@@ -241,9 +239,9 @@
 		memcpy(send_buf, firmware->data + sent, size);
 
 		err = usb_bulk_msg(udev, pipe, send_buf, size,
-					&len, 3000);
+				   &len, 3000);
 
-		if (err || (len != size)) {
+		if (err || len != size) {
 			ath3k_log_failed_loading(err, len, size, count);
 			goto error;
 		}
@@ -278,7 +276,7 @@
 }
 
 static int ath3k_get_version(struct usb_device *udev,
-			struct ath3k_version *version)
+			     struct ath3k_version *version)
 {
 	int ret, pipe = 0;
 	struct ath3k_version *buf;
@@ -300,7 +298,7 @@
 }
 
 static int ath3k_load_fwfile(struct usb_device *udev,
-		const struct firmware *firmware)
+			     const struct firmware *firmware)
 {
 	u8 *send_buf;
 	int len = 0;
@@ -341,8 +339,8 @@
 		memcpy(send_buf, firmware->data + sent, size);
 
 		err = usb_bulk_msg(udev, pipe, send_buf, size,
-					&len, 3000);
-		if (err || (len != size)) {
+				   &len, 3000);
+		if (err || len != size) {
 			ath3k_log_failed_loading(err, len, size, count);
 			kfree(send_buf);
 			return err;
@@ -461,7 +459,6 @@
 	}
 
 	switch (fw_version.ref_clock) {
-
 	case ATH3K_XTAL_FREQ_26M:
 		clk_value = 26;
 		break;
@@ -477,7 +474,7 @@
 	}
 
 	snprintf(filename, ATH3K_NAME_LEN, "ar3k/ramps_0x%08x_%d%s",
-		le32_to_cpu(fw_version.rom_version), clk_value, ".dfu");
+		 le32_to_cpu(fw_version.rom_version), clk_value, ".dfu");
 
 	ret = request_firmware(&firmware, filename, &udev->dev);
 	if (ret < 0) {
@@ -492,7 +489,7 @@
 }
 
 static int ath3k_probe(struct usb_interface *intf,
-			const struct usb_device_id *id)
+		       const struct usb_device_id *id)
 {
 	const struct firmware *firmware;
 	struct usb_device *udev = interface_to_usbdev(intf);
@@ -541,10 +538,10 @@
 	if (ret < 0) {
 		if (ret == -ENOENT)
 			BT_ERR("Firmware file \"%s\" not found",
-							ATH3K_FIRMWARE);
+			       ATH3K_FIRMWARE);
 		else
 			BT_ERR("Firmware file \"%s\" request failed (err=%d)",
-							ATH3K_FIRMWARE, ret);
+			       ATH3K_FIRMWARE, ret);
 		return ret;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/bluetooth/bfusb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/bluetooth/bfusb.c
@@ -629,6 +629,9 @@
 	data->bulk_out_ep   = bulk_out_ep->desc.bEndpointAddress;
 	data->bulk_pkt_size = le16_to_cpu(bulk_out_ep->desc.wMaxPacketSize);
 
+	if (!data->bulk_pkt_size)
+		goto done;
+
 	rwlock_init(&data->lock);
 
 	data->reassembly = NULL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/bluetooth/btbcm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/bluetooth/btbcm.c
@@ -329,6 +329,7 @@
 	{ 0x410e, "BCM43341B0"	},	/* 002.001.014 */
 	{ 0x4204, "BCM2076B1"	},	/* 002.002.004 */
 	{ 0x4406, "BCM4324B3"	},	/* 002.004.006 */
+	{ 0x4606, "BCM4324B5"	},	/* 002.006.006 */
 	{ 0x6109, "BCM4335C0"	},	/* 003.001.009 */
 	{ 0x610c, "BCM4354"	},	/* 003.001.012 */
 	{ 0x2122, "BCM4343A0"	},	/* 001.001.034 */
@@ -343,6 +344,7 @@
 };
 
 static const struct bcm_subver_table bcm_usb_subver_table[] = {
+	{ 0x2105, "BCM20703A1"	},	/* 001.001.005 */
 	{ 0x210b, "BCM43142A0"	},	/* 001.001.011 */
 	{ 0x2112, "BCM4314A0"	},	/* 001.001.018 */
 	{ 0x2118, "BCM20702A0"	},	/* 001.001.024 */
@@ -440,6 +442,12 @@
 
 	set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);
 
+	/* Some devices ship with the controller default address.
+	 * Allow the bootloader to set a valid address through the
+	 * device tree.
+	 */
+	set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(btbcm_finalize);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/bluetooth/btintel.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/bluetooth/btintel.c
@@ -346,7 +346,7 @@
 		return PTR_ERR(skb);
 	}
 
-	if (skb->len != sizeof(*ver)) {
+	if (!skb || skb->len != sizeof(*ver)) {
 		bt_dev_err(hdev, "Intel version event size mismatch");
 		kfree_skb(skb);
 		return -EILSEQ;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/bluetooth/btmrvl_sdio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/bluetooth/btmrvl_sdio.c
@@ -105,13 +105,15 @@
 		} else {
 			ret = devm_request_irq(dev, cfg->irq_bt,
 					       btmrvl_wake_irq_bt,
-					       0, "bt_wake", card);
+					       IRQF_NO_AUTOEN, "bt_wake", card);
 			if (ret) {
 				dev_err(dev,
 					"Failed to request irq_bt %d (%d)\n",
 					cfg->irq_bt, ret);
 			}
-			disable_irq(cfg->irq_bt);
+
+			/* Configure wakeup (enabled by default) */
+			device_init_wakeup(dev, true);
 		}
 	}
 
@@ -328,7 +330,7 @@
 
 static const struct btmrvl_sdio_device btmrvl_sdio_sd8977 = {
 	.helper         = NULL,
-	.firmware       = "mrvl/sd8977_uapsta.bin",
+	.firmware       = "mrvl/sdsd8977_combo_v2.bin",
 	.reg            = &btmrvl_reg_8977,
 	.support_pscan_win_report = true,
 	.sd_blksz_fw_dl = 256,
@@ -346,7 +348,7 @@
 
 static const struct btmrvl_sdio_device btmrvl_sdio_sd8997 = {
 	.helper         = NULL,
-	.firmware       = "mrvl/sd8997_uapsta.bin",
+	.firmware       = "mrvl/sdsd8997_combo_v4.bin",
 	.reg            = &btmrvl_reg_8997,
 	.support_pscan_win_report = true,
 	.sd_blksz_fw_dl = 256,
@@ -1654,6 +1656,7 @@
 							MODULE_SHUTDOWN_REQ);
 				btmrvl_sdio_disable_host_int(card);
 			}
+
 			BT_DBG("unregister dev");
 			card->priv->surprise_removed = true;
 			btmrvl_sdio_unregister_dev(card);
@@ -1690,7 +1693,8 @@
 	}
 
 	/* Enable platform specific wakeup interrupt */
-	if (card->plt_wake_cfg && card->plt_wake_cfg->irq_bt >= 0) {
+	if (card->plt_wake_cfg && card->plt_wake_cfg->irq_bt >= 0 &&
+	    device_may_wakeup(dev)) {
 		card->plt_wake_cfg->wake_by_bt = false;
 		enable_irq(card->plt_wake_cfg->irq_bt);
 		enable_irq_wake(card->plt_wake_cfg->irq_bt);
@@ -1707,7 +1711,8 @@
 			BT_ERR("HS not activated, suspend failed!");
 			/* Disable platform specific wakeup interrupt */
 			if (card->plt_wake_cfg &&
-			    card->plt_wake_cfg->irq_bt >= 0) {
+			    card->plt_wake_cfg->irq_bt >= 0 &&
+			    device_may_wakeup(dev)) {
 				disable_irq_wake(card->plt_wake_cfg->irq_bt);
 				disable_irq(card->plt_wake_cfg->irq_bt);
 			}
@@ -1767,7 +1772,8 @@
 	hci_resume_dev(hcidev);
 
 	/* Disable platform specific wakeup interrupt */
-	if (card->plt_wake_cfg && card->plt_wake_cfg->irq_bt >= 0) {
+	if (card->plt_wake_cfg && card->plt_wake_cfg->irq_bt >= 0 &&
+	    device_may_wakeup(dev)) {
 		disable_irq_wake(card->plt_wake_cfg->irq_bt);
 		disable_irq(card->plt_wake_cfg->irq_bt);
 		if (card->plt_wake_cfg->wake_by_bt)
@@ -1831,6 +1837,6 @@
 MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin");
 MODULE_FIRMWARE("mrvl/sd8887_uapsta.bin");
 MODULE_FIRMWARE("mrvl/sd8897_uapsta.bin");
-MODULE_FIRMWARE("mrvl/sd8977_uapsta.bin");
+MODULE_FIRMWARE("mrvl/sdsd8977_combo_v2.bin");
 MODULE_FIRMWARE("mrvl/sd8987_uapsta.bin");
-MODULE_FIRMWARE("mrvl/sd8997_uapsta.bin");
+MODULE_FIRMWARE("mrvl/sdsd8997_combo_v4.bin");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/bluetooth/btmtksdio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/bluetooth/btmtksdio.c
@@ -684,7 +684,7 @@
 	const u8 *fw_ptr;
 	size_t fw_size;
 	int err, dlen;
-	u8 flag;
+	u8 flag, param;
 
 	err = request_firmware(&fw, fwname, &hdev->dev);
 	if (err < 0) {
@@ -692,6 +692,20 @@
 		return err;
 	}
 
+	/* Power on data RAM the firmware relies on. */
+	param = 1;
+	wmt_params.op = MTK_WMT_FUNC_CTRL;
+	wmt_params.flag = 3;
+	wmt_params.dlen = sizeof(param);
+	wmt_params.data = &param;
+	wmt_params.status = NULL;
+
+	err = mtk_hci_wmt_sync(hdev, &wmt_params);
+	if (err < 0) {
+		bt_dev_err(hdev, "Failed to power on data RAM (%d)", err);
+		goto free_fw;
+	}
+
 	fw_ptr = fw->data;
 	fw_size = fw->size;
 
@@ -966,6 +980,8 @@
 	hdev->manufacturer = 70;
 	set_bit(HCI_QUIRK_NON_PERSISTENT_SETUP, &hdev->quirks);
 
+	sdio_set_drvdata(func, bdev);
+
 	err = hci_register_dev(hdev);
 	if (err < 0) {
 		dev_err(&func->dev, "Can't register HCI device\n");
@@ -973,8 +989,6 @@
 		return err;
 	}
 
-	sdio_set_drvdata(func, bdev);
-
 	/* pm_runtime_enable would be done after the firmware is being
 	 * downloaded because the core layer probably already enables
 	 * runtime PM for this func such as the case host->caps &
@@ -1027,6 +1041,8 @@
 	if (!bdev)
 		return 0;
 
+	sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
+
 	sdio_claim_host(bdev->func);
 
 	sdio_writel(bdev->func, C_FW_OWN_REQ_SET, MTK_REG_CHLPCR, &err);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/bluetooth/btmtkuart.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/bluetooth/btmtkuart.c
@@ -158,8 +158,10 @@
 	int err;
 
 	hlen = sizeof(*hdr) + wmt_params->dlen;
-	if (hlen > 255)
-		return -EINVAL;
+	if (hlen > 255) {
+		err = -EINVAL;
+		goto err_free_skb;
+	}
 
 	hdr = (struct mtk_wmt_hdr *)&wc;
 	hdr->dir = 1;
@@ -173,7 +175,7 @@
 	err = __hci_cmd_send(hdev, 0xfc6f, hlen, &wc);
 	if (err < 0) {
 		clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state);
-		return err;
+		goto err_free_skb;
 	}
 
 	/* The vendor specific WMT commands are all answered by a vendor
@@ -190,13 +192,14 @@
 	if (err == -EINTR) {
 		bt_dev_err(hdev, "Execution of wmt command interrupted");
 		clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state);
-		return err;
+		goto err_free_skb;
 	}
 
 	if (err) {
 		bt_dev_err(hdev, "Execution of wmt command timed out");
 		clear_bit(BTMTKUART_TX_WAIT_VND_EVT, &bdev->tx_state);
-		return -ETIMEDOUT;
+		err = -ETIMEDOUT;
+		goto err_free_skb;
 	}
 
 	/* Parse and handle the return WMT event */
@@ -468,7 +471,7 @@
 	return data;
 }
 
-static int btmtkuart_recv(struct hci_dev *hdev, const u8 *data, size_t count)
+static void btmtkuart_recv(struct hci_dev *hdev, const u8 *data, size_t count)
 {
 	struct btmtkuart_dev *bdev = hci_get_drvdata(hdev);
 	const unsigned char *p_left = data, *p_h4;
@@ -507,25 +510,20 @@
 			bt_dev_err(bdev->hdev,
 				   "Frame reassembly failed (%d)", err);
 			bdev->rx_skb = NULL;
-			return err;
+			return;
 		}
 
 		sz_left -= sz_h4;
 		p_left += sz_h4;
 	}
-
-	return 0;
 }
 
 static int btmtkuart_receive_buf(struct serdev_device *serdev, const u8 *data,
 				 size_t count)
 {
 	struct btmtkuart_dev *bdev = serdev_device_get_drvdata(serdev);
-	int err;
 
-	err = btmtkuart_recv(bdev->hdev, data, count);
-	if (err < 0)
-		return err;
+	btmtkuart_recv(bdev->hdev, data, count);
 
 	bdev->hdev->stat.byte_rx += count;
 
@@ -1015,7 +1013,7 @@
 	if (btmtkuart_is_standalone(bdev)) {
 		err = clk_prepare_enable(bdev->osc);
 		if (err < 0)
-			return err;
+			goto err_hci_free_dev;
 
 		if (bdev->boot) {
 			gpiod_set_value_cansleep(bdev->boot, 1);
@@ -1028,10 +1026,8 @@
 
 		/* Power on */
 		err = regulator_enable(bdev->vcc);
-		if (err < 0) {
-			clk_disable_unprepare(bdev->osc);
-			return err;
-		}
+		if (err < 0)
+			goto err_clk_disable_unprepare;
 
 		/* Reset if the reset-gpios is available otherwise the board
 		 * -level design should be guaranteed.
@@ -1063,7 +1059,6 @@
 	err = hci_register_dev(hdev);
 	if (err < 0) {
 		dev_err(&serdev->dev, "Can't register HCI device\n");
-		hci_free_dev(hdev);
 		goto err_regulator_disable;
 	}
 
@@ -1072,6 +1067,11 @@
 err_regulator_disable:
 	if (btmtkuart_is_standalone(bdev))
 		regulator_disable(bdev->vcc);
+err_clk_disable_unprepare:
+	if (btmtkuart_is_standalone(bdev))
+		clk_disable_unprepare(bdev->osc);
+err_hci_free_dev:
+	hci_free_dev(hdev);
 
 	return err;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/bluetooth/btqcomsmd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/bluetooth/btqcomsmd.c
@@ -122,6 +122,21 @@
 	return 0;
 }
 
+static int btqcomsmd_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
+{
+	int ret;
+
+	ret = qca_set_bdaddr_rome(hdev, bdaddr);
+	if (ret)
+		return ret;
+
+	/* The firmware stops responding for a while after setting the bdaddr,
+	 * causing timeouts for subsequent commands. Sleep a bit to avoid this.
+	 */
+	usleep_range(1000, 10000);
+	return 0;
+}
+
 static int btqcomsmd_probe(struct platform_device *pdev)
 {
 	struct btqcomsmd *btq;
@@ -142,12 +157,16 @@
 
 	btq->cmd_channel = qcom_wcnss_open_channel(wcnss, "APPS_RIVA_BT_CMD",
 						   btqcomsmd_cmd_callback, btq);
-	if (IS_ERR(btq->cmd_channel))
-		return PTR_ERR(btq->cmd_channel);
+	if (IS_ERR(btq->cmd_channel)) {
+		ret = PTR_ERR(btq->cmd_channel);
+		goto destroy_acl_channel;
+	}
 
 	hdev = hci_alloc_dev();
-	if (!hdev)
-		return -ENOMEM;
+	if (!hdev) {
+		ret = -ENOMEM;
+		goto destroy_cmd_channel;
+	}
 
 	hci_set_drvdata(hdev, btq);
 	btq->hdev = hdev;
@@ -158,17 +177,24 @@
 	hdev->close = btqcomsmd_close;
 	hdev->send = btqcomsmd_send;
 	hdev->setup = btqcomsmd_setup;
-	hdev->set_bdaddr = qca_set_bdaddr_rome;
+	hdev->set_bdaddr = btqcomsmd_set_bdaddr;
 
 	ret = hci_register_dev(hdev);
-	if (ret < 0) {
-		hci_free_dev(hdev);
-		return ret;
-	}
+	if (ret < 0)
+		goto hci_free_dev;
 
 	platform_set_drvdata(pdev, btq);
 
 	return 0;
+
+hci_free_dev:
+	hci_free_dev(hdev);
+destroy_cmd_channel:
+	rpmsg_destroy_ept(btq->cmd_channel);
+destroy_acl_channel:
+	rpmsg_destroy_ept(btq->acl_channel);
+
+	return ret;
 }
 
 static int btqcomsmd_remove(struct platform_device *pdev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/bluetooth/btrtl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/bluetooth/btrtl.c
@@ -55,6 +55,7 @@
 	int fw_len;
 	u8 *cfg_data;
 	int cfg_len;
+	bool drop_fw;
 };
 
 static const struct id_table ic_id_table[] = {
@@ -130,12 +131,19 @@
 	  .cfg_name = "rtl_bt/rtl8821c_config" },
 
 	/* 8761A */
-	{ IC_MATCH_FL_LMPSUBV, RTL_ROM_LMP_8761A, 0x0,
+	{ IC_INFO(RTL_ROM_LMP_8761A, 0xa),
 	  .config_needed = false,
 	  .has_rom_version = true,
 	  .fw_name  = "rtl_bt/rtl8761a_fw.bin",
 	  .cfg_name = "rtl_bt/rtl8761a_config" },
 
+	/* 8761B */
+	{ IC_INFO(RTL_ROM_LMP_8761A, 0xb),
+	  .config_needed = false,
+	  .has_rom_version = true,
+	  .fw_name  = "rtl_bt/rtl8761b_fw.bin",
+	  .cfg_name = "rtl_bt/rtl8761b_config" },
+
 	/* 8822C with USB interface */
 	{ IC_INFO(RTL_ROM_LMP_8822B, 0xc),
 	  .config_needed = false,
@@ -255,6 +263,7 @@
 		{ RTL_ROM_LMP_8723B, 9 },	/* 8723D */
 		{ RTL_ROM_LMP_8821A, 10 },	/* 8821C */
 		{ RTL_ROM_LMP_8822B, 13 },	/* 8822C */
+		{ RTL_ROM_LMP_8761A, 14 },	/* 8761B */
 	};
 
 	min_size = sizeof(struct rtl_epatch_header) + sizeof(extension_sig) + 3;
@@ -370,11 +379,11 @@
 	 * the end.
 	 */
 	len = patch_length;
-	buf = kmemdup(btrtl_dev->fw_data + patch_offset, patch_length,
-		      GFP_KERNEL);
+	buf = kvmalloc(patch_length, GFP_KERNEL);
 	if (!buf)
 		return -ENOMEM;
 
+	memcpy(buf, btrtl_dev->fw_data + patch_offset, patch_length - 4);
 	memcpy(buf + patch_length - 4, &epatch_info->fw_version, 4);
 
 	*_buf = buf;
@@ -460,8 +469,10 @@
 	if (ret < 0)
 		return ret;
 	ret = fw->size;
-	*buff = kmemdup(fw->data, ret, GFP_KERNEL);
-	if (!*buff)
+	*buff = kvmalloc(fw->size, GFP_KERNEL);
+	if (*buff)
+		memcpy(*buff, fw->data, ret);
+	else
 		ret = -ENOMEM;
 
 	release_firmware(fw);
@@ -499,14 +510,14 @@
 		goto out;
 
 	if (btrtl_dev->cfg_len > 0) {
-		tbuff = kzalloc(ret + btrtl_dev->cfg_len, GFP_KERNEL);
+		tbuff = kvzalloc(ret + btrtl_dev->cfg_len, GFP_KERNEL);
 		if (!tbuff) {
 			ret = -ENOMEM;
 			goto out;
 		}
 
 		memcpy(tbuff, fw_data, ret);
-		kfree(fw_data);
+		kvfree(fw_data);
 
 		memcpy(tbuff + ret, btrtl_dev->cfg_data, btrtl_dev->cfg_len);
 		ret += btrtl_dev->cfg_len;
@@ -519,14 +530,14 @@
 	ret = rtl_download_firmware(hdev, fw_data, ret);
 
 out:
-	kfree(fw_data);
+	kvfree(fw_data);
 	return ret;
 }
 
 void btrtl_free(struct btrtl_device_info *btrtl_dev)
 {
-	kfree(btrtl_dev->fw_data);
-	kfree(btrtl_dev->cfg_data);
+	kvfree(btrtl_dev->fw_data);
+	kvfree(btrtl_dev->cfg_data);
 	kfree(btrtl_dev);
 }
 EXPORT_SYMBOL_GPL(btrtl_free);
@@ -541,6 +552,8 @@
 	u16 hci_rev, lmp_subver;
 	u8 hci_ver;
 	int ret;
+	u16 opcode;
+	u8 cmd[2];
 
 	btrtl_dev = kzalloc(sizeof(*btrtl_dev), GFP_KERNEL);
 	if (!btrtl_dev) {
@@ -562,6 +575,49 @@
 	hci_ver = resp->hci_ver;
 	hci_rev = le16_to_cpu(resp->hci_rev);
 	lmp_subver = le16_to_cpu(resp->lmp_subver);
+
+	if (resp->hci_ver == 0x8 && le16_to_cpu(resp->hci_rev) == 0x826c &&
+	    resp->lmp_ver == 0x8 && le16_to_cpu(resp->lmp_subver) == 0xa99e)
+		btrtl_dev->drop_fw = true;
+
+	if (btrtl_dev->drop_fw) {
+		opcode = hci_opcode_pack(0x3f, 0x66);
+		cmd[0] = opcode & 0xff;
+		cmd[1] = opcode >> 8;
+
+		skb = bt_skb_alloc(sizeof(cmd), GFP_KERNEL);
+		if (!skb)
+			goto out_free;
+
+		skb_put_data(skb, cmd, sizeof(cmd));
+		hci_skb_pkt_type(skb) = HCI_COMMAND_PKT;
+
+		hdev->send(hdev, skb);
+
+		/* Ensure the above vendor command is sent to controller and
+		 * process has done.
+		 */
+		msleep(200);
+
+		/* Read the local version again. Expect to have the vanilla
+		 * version as cold boot.
+		 */
+		skb = btrtl_read_local_version(hdev);
+		if (IS_ERR(skb)) {
+			ret = PTR_ERR(skb);
+			goto err_free;
+		}
+
+		resp = (struct hci_rp_read_local_version *)skb->data;
+		rtl_dev_info(hdev, "examining hci_ver=%02x hci_rev=%04x lmp_ver=%02x lmp_subver=%04x",
+			     resp->hci_ver, resp->hci_rev,
+			     resp->lmp_ver, resp->lmp_subver);
+
+		hci_ver = resp->hci_ver;
+		hci_rev = le16_to_cpu(resp->hci_rev);
+		lmp_subver = le16_to_cpu(resp->lmp_subver);
+	}
+out_free:
 	kfree_skb(skb);
 
 	btrtl_dev->ic_info = btrtl_match_ic(lmp_subver, hci_rev, hci_ver,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/bluetooth/btsdio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/bluetooth/btsdio.c
@@ -346,6 +346,7 @@
 	if (!data)
 		return;
 
+	cancel_work_sync(&data->work);
 	hdev = data->hdev;
 
 	sdio_set_drvdata(func, NULL);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/bluetooth/btusb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/bluetooth/btusb.c
@@ -14,6 +14,7 @@
 #include <linux/iopoll.h>
 #include <linux/of_device.h>
 #include <linux/of_irq.h>
+#include <linux/pci.h>
 #include <linux/suspend.h>
 #include <linux/gpio/consumer.h>
 #include <asm/unaligned.h>
@@ -57,6 +58,7 @@
 #define BTUSB_IFNUM_2		0x80000
 #define BTUSB_CW6622		0x100000
 #define BTUSB_MEDIATEK		0x200000
+#define BTUSB_WIDEBAND_SPEECH	0x400000
 
 static const struct usb_device_id btusb_table[] = {
 	/* Generic Bluetooth USB device */
@@ -332,20 +334,50 @@
 	{ USB_DEVICE(0x1286, 0x204e), .driver_info = BTUSB_MARVELL },
 
 	/* Intel Bluetooth devices */
-	{ USB_DEVICE(0x8087, 0x0025), .driver_info = BTUSB_INTEL_NEW },
-	{ USB_DEVICE(0x8087, 0x0026), .driver_info = BTUSB_INTEL_NEW },
-	{ USB_DEVICE(0x8087, 0x0029), .driver_info = BTUSB_INTEL_NEW },
+	{ USB_DEVICE(0x8087, 0x0025), .driver_info = BTUSB_INTEL_NEW |
+						     BTUSB_WIDEBAND_SPEECH },
+	{ USB_DEVICE(0x8087, 0x0026), .driver_info = BTUSB_INTEL_NEW |
+						     BTUSB_WIDEBAND_SPEECH },
+	{ USB_DEVICE(0x8087, 0x0029), .driver_info = BTUSB_INTEL_NEW |
+						     BTUSB_WIDEBAND_SPEECH },
 	{ USB_DEVICE(0x8087, 0x07da), .driver_info = BTUSB_CSR },
 	{ USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL },
 	{ USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL },
-	{ USB_DEVICE(0x8087, 0x0a2b), .driver_info = BTUSB_INTEL_NEW },
-	{ USB_DEVICE(0x8087, 0x0aa7), .driver_info = BTUSB_INTEL },
-	{ USB_DEVICE(0x8087, 0x0aaa), .driver_info = BTUSB_INTEL_NEW },
+	{ USB_DEVICE(0x8087, 0x0a2b), .driver_info = BTUSB_INTEL_NEW |
+						     BTUSB_WIDEBAND_SPEECH },
+	{ USB_DEVICE(0x8087, 0x0aa7), .driver_info = BTUSB_INTEL |
+						     BTUSB_WIDEBAND_SPEECH },
+	{ USB_DEVICE(0x8087, 0x0aaa), .driver_info = BTUSB_INTEL_NEW |
+						     BTUSB_WIDEBAND_SPEECH },
 
 	/* Other Intel Bluetooth devices */
 	{ USB_VENDOR_AND_INTERFACE_INFO(0x8087, 0xe0, 0x01, 0x01),
 	  .driver_info = BTUSB_IGNORE },
 
+	/* Realtek 8822CE Bluetooth devices */
+	{ USB_DEVICE(0x0bda, 0xb00c), .driver_info = BTUSB_REALTEK |
+						     BTUSB_WIDEBAND_SPEECH },
+
+	/* Realtek 8852BE Bluetooth devices */
+	{ USB_DEVICE(0x0cb8, 0xc559), .driver_info = BTUSB_REALTEK |
+						     BTUSB_WIDEBAND_SPEECH },
+	{ USB_DEVICE(0x0bda, 0x4853), .driver_info = BTUSB_REALTEK |
+						     BTUSB_WIDEBAND_SPEECH },
+	{ USB_DEVICE(0x0bda, 0x887b), .driver_info = BTUSB_REALTEK |
+						     BTUSB_WIDEBAND_SPEECH },
+	{ USB_DEVICE(0x0bda, 0xb85b), .driver_info = BTUSB_REALTEK |
+						     BTUSB_WIDEBAND_SPEECH },
+	{ USB_DEVICE(0x13d3, 0x3570), .driver_info = BTUSB_REALTEK |
+						     BTUSB_WIDEBAND_SPEECH },
+	{ USB_DEVICE(0x13d3, 0x3571), .driver_info = BTUSB_REALTEK |
+						     BTUSB_WIDEBAND_SPEECH },
+	{ USB_DEVICE(0x13d3, 0x3591), .driver_info = BTUSB_REALTEK |
+						     BTUSB_WIDEBAND_SPEECH },
+	{ USB_DEVICE(0x0489, 0xe123), .driver_info = BTUSB_REALTEK |
+						     BTUSB_WIDEBAND_SPEECH },
+	{ USB_DEVICE(0x0489, 0xe125), .driver_info = BTUSB_REALTEK |
+						     BTUSB_WIDEBAND_SPEECH },
+
 	/* Realtek Bluetooth devices */
 	{ USB_VENDOR_AND_INTERFACE_INFO(0x0bda, 0xe0, 0x01, 0x01),
 	  .driver_info = BTUSB_REALTEK },
@@ -373,6 +405,10 @@
 	{ USB_DEVICE(0x0bda, 0xb009), .driver_info = BTUSB_REALTEK },
 	{ USB_DEVICE(0x2ff8, 0xb011), .driver_info = BTUSB_REALTEK },
 
+	/* Additional Realtek 8761BU Bluetooth devices */
+	{ USB_DEVICE(0x0b05, 0x190e), .driver_info = BTUSB_REALTEK |
+	  					     BTUSB_WIDEBAND_SPEECH },
+
 	/* Additional Realtek 8821AE Bluetooth devices */
 	{ USB_DEVICE(0x0b05, 0x17dc), .driver_info = BTUSB_REALTEK },
 	{ USB_DEVICE(0x13d3, 0x3414), .driver_info = BTUSB_REALTEK },
@@ -563,13 +599,13 @@
 
 	spin_lock_irqsave(&data->rxlock, flags);
 
-	kfree_skb(data->evt_skb);
+	dev_kfree_skb_irq(data->evt_skb);
 	data->evt_skb = NULL;
 
-	kfree_skb(data->acl_skb);
+	dev_kfree_skb_irq(data->acl_skb);
 	data->acl_skb = NULL;
 
-	kfree_skb(data->sco_skb);
+	dev_kfree_skb_irq(data->sco_skb);
 	data->sco_skb = NULL;
 
 	spin_unlock_irqrestore(&data->rxlock, flags);
@@ -805,7 +841,15 @@
 	if (!urb)
 		return -ENOMEM;
 
-	size = le16_to_cpu(data->intr_ep->wMaxPacketSize);
+	if (le16_to_cpu(data->udev->descriptor.idVendor)  == 0x0a12 &&
+	    le16_to_cpu(data->udev->descriptor.idProduct) == 0x0001)
+		/* Fake CSR devices don't seem to support sort-transter */
+		size = le16_to_cpu(data->intr_ep->wMaxPacketSize);
+	else
+		/* Use maximum HCI Event size so the USB stack handles
+		 * ZPL/short-transfer automatically.
+		 */
+		size = HCI_MAX_EVENT_SIZE;
 
 	buf = kmalloc(size, mem_flags);
 	if (!buf) {
@@ -1200,7 +1244,7 @@
 	if (data->setup_on_usb) {
 		err = data->setup_on_usb(hdev);
 		if (err < 0)
-			return err;
+			goto setup_fail;
 	}
 
 	data->intf->needs_remote_wakeup = 1;
@@ -1239,6 +1283,7 @@
 
 failed:
 	clear_bit(BTUSB_INTR_RUNNING, &data->flags);
+setup_fail:
 	usb_autopm_put_interface(data->intf);
 	return err;
 }
@@ -2567,7 +2612,8 @@
 		skb = bt_skb_alloc(HCI_WMT_MAX_EVENT_SIZE, GFP_ATOMIC);
 		if (!skb) {
 			hdev->stat.err_rx++;
-			goto err_out;
+			kfree(urb->setup_packet);
+			return;
 		}
 
 		hci_skb_pkt_type(skb) = HCI_EVENT_PKT;
@@ -2584,14 +2630,21 @@
 		 * and being processed the events from there then.
 		 */
 		if (test_bit(BTUSB_TX_WAIT_VND_EVT, &data->flags)) {
-			data->evt_skb = skb_clone(skb, GFP_KERNEL);
-			if (!data->evt_skb)
-				goto err_out;
+			data->evt_skb = skb_clone(skb, GFP_ATOMIC);
+			if (!data->evt_skb) {
+				kfree_skb(skb);
+				kfree(urb->setup_packet);
+				return;
+			}
 		}
 
 		err = hci_recv_frame(hdev, skb);
-		if (err < 0)
-			goto err_free_skb;
+		if (err < 0) {
+			kfree_skb(data->evt_skb);
+			data->evt_skb = NULL;
+			kfree(urb->setup_packet);
+			return;
+		}
 
 		if (test_and_clear_bit(BTUSB_TX_WAIT_VND_EVT,
 				       &data->flags)) {
@@ -2600,11 +2653,7 @@
 			wake_up_bit(&data->flags,
 				    BTUSB_TX_WAIT_VND_EVT);
 		}
-err_out:
-		return;
-err_free_skb:
-		kfree_skb(data->evt_skb);
-		data->evt_skb = NULL;
+		kfree(urb->setup_packet);
 		return;
 	} else if (urb->status == -ENOENT) {
 		/* Avoid suspend failed when usb_kill_urb */
@@ -2625,6 +2674,7 @@
 	usb_anchor_urb(urb, &data->ctrl_anchor);
 	err = usb_submit_urb(urb, GFP_ATOMIC);
 	if (err < 0) {
+		kfree(urb->setup_packet);
 		/* -EPERM: urb is being killed;
 		 * -ENODEV: device got disconnected
 		 */
@@ -2663,6 +2713,7 @@
 	buf = kmalloc(size, GFP_KERNEL);
 	if (!buf) {
 		kfree(dr);
+		usb_free_urb(urb);
 		return -ENOMEM;
 	}
 
@@ -2698,11 +2749,6 @@
 	struct btmtk_wmt_hdr *hdr;
 	int err;
 
-	/* Submit control IN URB on demand to process the WMT event */
-	err = btusb_mtk_submit_wmt_recv_urb(hdev);
-	if (err < 0)
-		return err;
-
 	/* Send the WMT command and wait until the WMT event returns */
 	hlen = sizeof(*hdr) + wmt_params->dlen;
 	if (hlen > 255)
@@ -2724,6 +2770,11 @@
 		return err;
 	}
 
+	/* Submit control IN URB on demand to process the WMT event */
+	err = btusb_mtk_submit_wmt_recv_urb(hdev);
+	if (err < 0)
+		return err;
+
 	/* The vendor specific WMT commands are all answered by a vendor
 	 * specific event and will have the Command Status or Command
 	 * Complete as with usual HCI command flow control.
@@ -2791,7 +2842,7 @@
 	const u8 *fw_ptr;
 	size_t fw_size;
 	int err, dlen;
-	u8 flag;
+	u8 flag, param;
 
 	err = request_firmware(&fw, fwname, &hdev->dev);
 	if (err < 0) {
@@ -2799,6 +2850,20 @@
 		return err;
 	}
 
+	/* Power on data RAM the firmware relies on. */
+	param = 1;
+	wmt_params.op = BTMTK_WMT_FUNC_CTRL;
+	wmt_params.flag = 3;
+	wmt_params.dlen = sizeof(param);
+	wmt_params.data = &param;
+	wmt_params.status = NULL;
+
+	err = btusb_mtk_hci_wmt_sync(hdev, &wmt_params);
+	if (err < 0) {
+		bt_dev_err(hdev, "Failed to power on data RAM (%d)", err);
+		goto err_release_fw;
+	}
+
 	fw_ptr = fw->data;
 	fw_size = fw->size;
 
@@ -2849,7 +2914,7 @@
 	err = btusb_mtk_hci_wmt_sync(hdev, &wmt_params);
 	if (err < 0) {
 		bt_dev_err(hdev, "Failed to send wmt rst (%d)", err);
-		return err;
+		goto err_release_fw;
 	}
 
 	/* Wait a few moments for firmware activation done */
@@ -3120,6 +3185,35 @@
 	return 0;
 }
 
+#define BTUSB_EDGE_LED_COMMAND		0xfc77
+
+static void btusb_edge_set_led(struct hci_dev *hdev, bool state)
+{
+	struct sk_buff *skb;
+	u8 config_led[] = { 0x09, 0x00, 0x01, 0x01 };
+
+	if (state)
+		config_led[1] = 0x01;
+
+	skb = __hci_cmd_sync(hdev, BTUSB_EDGE_LED_COMMAND, sizeof(config_led), config_led, HCI_INIT_TIMEOUT);
+	if (IS_ERR(skb))
+		BT_ERR("%s fail to set LED (%ld)", hdev->name, PTR_ERR(skb));
+	else
+		kfree_skb(skb);
+}
+
+static int btusb_edge_post_init(struct hci_dev *hdev)
+{
+	btusb_edge_set_led(hdev, true);
+	return 0;
+}
+
+static int btusb_edge_shutdown(struct hci_dev *hdev)
+{
+	btusb_edge_set_led(hdev, false);
+	return 0;
+}
+
 static int btusb_set_bdaddr_ath3012(struct hci_dev *hdev,
 				    const bdaddr_t *bdaddr)
 {
@@ -3247,6 +3341,11 @@
 	sent += size;
 	count -= size;
 
+	/* ep2 need time to switch from function acl to function dfu,
+	 * so we add 20ms delay here.
+	 */
+	msleep(20);
+
 	while (count) {
 		size = min_t(size_t, count, QCA_DFU_PACKET_LEN);
 
@@ -3771,8 +3870,18 @@
 		set_bit(HCI_QUIRK_NON_PERSISTENT_DIAG, &hdev->quirks);
 	}
 
-	if (id->driver_info & BTUSB_MARVELL)
+	if (id->driver_info & BTUSB_MARVELL) {
+		struct pci_dev *pdev;
 		hdev->set_bdaddr = btusb_set_bdaddr_marvell;
+		pdev = pci_get_subsys(PCI_ANY_ID, PCI_ANY_ID, 0x1028, 0x0720, NULL);
+		if (!pdev)
+			pdev = pci_get_subsys(PCI_ANY_ID, PCI_ANY_ID, 0x1028, 0x0733, NULL);
+		if (pdev) {
+			pci_dev_put(pdev);
+			hdev->post_init = btusb_edge_post_init;
+			hdev->shutdown = btusb_edge_shutdown;
+		}
+	}
 
 #ifdef CONFIG_BT_HCIBTUSB_MTK
 	if (id->driver_info & BTUSB_MEDIATEK) {
@@ -3807,8 +3916,8 @@
 		btusb_check_needs_reset_resume(intf);
 	}
 
-#ifdef CONFIG_BT_HCIBTUSB_RTL
-	if (id->driver_info & BTUSB_REALTEK) {
+	if (IS_ENABLED(CONFIG_BT_HCIBTUSB_RTL) &&
+	    (id->driver_info & BTUSB_REALTEK)) {
 		hdev->setup = btrtl_setup_realtek;
 		hdev->shutdown = btrtl_shutdown_realtek;
 		hdev->cmd_timeout = btusb_rtl_cmd_timeout;
@@ -3818,8 +3927,11 @@
 		 * (DEVICE_REMOTE_WAKEUP)
 		 */
 		set_bit(BTUSB_WAKEUP_DISABLE, &data->flags);
+
+		err = usb_autopm_get_interface(intf);
+		if (err < 0)
+			goto out_free_dev;
 	}
-#endif
 
 	if (id->driver_info & BTUSB_AMP) {
 		/* AMP controllers do not support SCO packets */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/bluetooth/hci_bcm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/bluetooth/hci_bcm.c
@@ -107,6 +107,7 @@
 	u32			oper_speed;
 	int			irq;
 	bool			irq_active_low;
+	bool			irq_acquired;
 
 #ifdef CONFIG_PM
 	struct hci_uart		*hu;
@@ -319,6 +320,8 @@
 		goto unlock;
 	}
 
+	bdev->irq_acquired = true;
+
 	device_init_wakeup(bdev->dev, true);
 
 	pm_runtime_set_autosuspend_delay(bdev->dev,
@@ -487,7 +490,7 @@
 	}
 
 	if (bdev) {
-		if (IS_ENABLED(CONFIG_PM) && bdev->irq > 0) {
+		if (IS_ENABLED(CONFIG_PM) && bdev->irq_acquired) {
 			devm_free_irq(bdev->dev, bdev->irq, bdev);
 			device_init_wakeup(bdev->dev, false);
 			pm_runtime_disable(bdev->dev);
@@ -1124,7 +1127,12 @@
 		return -ENOMEM;
 
 	dev->dev = &pdev->dev;
-	dev->irq = platform_get_irq(pdev, 0);
+
+	ret = platform_get_irq(pdev, 0);
+	if (ret < 0)
+		return ret;
+
+	dev->irq = ret;
 
 	if (has_acpi_companion(&pdev->dev)) {
 		ret = bcm_acpi_probe(dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/bluetooth/hci_bcsp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/bluetooth/hci_bcsp.c
@@ -378,7 +378,7 @@
 		i++;
 
 		__skb_unlink(skb, &bcsp->unack);
-		kfree_skb(skb);
+		dev_kfree_skb_irq(skb);
 	}
 
 	if (skb_queue_empty(&bcsp->unack))
@@ -591,6 +591,7 @@
 			if (*ptr == 0xc0) {
 				BT_ERR("Short BCSP packet");
 				kfree_skb(bcsp->rx_skb);
+				bcsp->rx_skb = NULL;
 				bcsp->rx_state = BCSP_W4_PKT_START;
 				bcsp->rx_count = 0;
 			} else
@@ -606,6 +607,7 @@
 			    bcsp->rx_skb->data[2])) != bcsp->rx_skb->data[3]) {
 				BT_ERR("Error in BCSP hdr checksum");
 				kfree_skb(bcsp->rx_skb);
+				bcsp->rx_skb = NULL;
 				bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
 				bcsp->rx_count = 0;
 				continue;
@@ -630,6 +632,7 @@
 				       bscp_get_crc(bcsp));
 
 				kfree_skb(bcsp->rx_skb);
+				bcsp->rx_skb = NULL;
 				bcsp->rx_state = BCSP_W4_PKT_DELIMITER;
 				bcsp->rx_count = 0;
 				continue;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/bluetooth/hci_h5.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/bluetooth/hci_h5.c
@@ -244,6 +244,9 @@
 	skb_queue_purge(&h5->rel);
 	skb_queue_purge(&h5->unrel);
 
+	kfree_skb(h5->rx_skb);
+	h5->rx_skb = NULL;
+
 	if (h5->vnd && h5->vnd->close)
 		h5->vnd->close(h5);
 
@@ -295,7 +298,7 @@
 			break;
 
 		__skb_unlink(skb, &h5->unack);
-		kfree_skb(skb);
+		dev_kfree_skb_irq(skb);
 	}
 
 	if (skb_queue_empty(&h5->unack))
@@ -790,7 +793,7 @@
 	if (!h5)
 		return -ENOMEM;
 
-	set_bit(HCI_UART_RESET_ON_INIT, &h5->serdev_hu.flags);
+	set_bit(HCI_UART_RESET_ON_INIT, &h5->serdev_hu.hdev_flags);
 
 	h5->hu = &h5->serdev_hu;
 	h5->serdev_hu.serdev = serdev;
@@ -891,6 +894,11 @@
 	/* Give the device some time before the hci-core sends it a reset */
 	usleep_range(10000, 20000);
 
+	/* Enable controller to do both LE scan and BR/EDR inquiry
+	 * simultaneously.
+	 */
+	set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &h5->hu->hdev->quirks);
+
 out_free:
 	btrtl_free(btrtl_dev);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/bluetooth/hci_intel.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/bluetooth/hci_intel.c
@@ -1230,7 +1230,11 @@
 
 int __init intel_init(void)
 {
-	platform_driver_register(&intel_driver);
+	int err;
+
+	err = platform_driver_register(&intel_driver);
+	if (err)
+		return err;
 
 	return hci_uart_register_proto(&intel_proto);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/bluetooth/hci_ldisc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/bluetooth/hci_ldisc.c
@@ -127,10 +127,9 @@
 	if (!test_bit(HCI_UART_PROTO_READY, &hu->flags))
 		goto no_schedule;
 
-	if (test_and_set_bit(HCI_UART_SENDING, &hu->tx_state)) {
-		set_bit(HCI_UART_TX_WAKEUP, &hu->tx_state);
+	set_bit(HCI_UART_TX_WAKEUP, &hu->tx_state);
+	if (test_and_set_bit(HCI_UART_SENDING, &hu->tx_state))
 		goto no_schedule;
-	}
 
 	BT_DBG("");
 
@@ -174,10 +173,10 @@
 		kfree_skb(skb);
 	}
 
+	clear_bit(HCI_UART_SENDING, &hu->tx_state);
 	if (test_bit(HCI_UART_TX_WAKEUP, &hu->tx_state))
 		goto restart;
 
-	clear_bit(HCI_UART_SENDING, &hu->tx_state);
 	wake_up_bit(&hu->tx_state, HCI_UART_SENDING);
 }
 
@@ -480,6 +479,9 @@
 
 	BT_DBG("tty %p", tty);
 
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
 	/* Error if the tty has no write op instead of leaving an exploitable
 	 * hole
 	 */
@@ -538,6 +540,7 @@
 		clear_bit(HCI_UART_PROTO_READY, &hu->flags);
 		percpu_up_write(&hu->proto_lock);
 
+		cancel_work_sync(&hu->init_ready);
 		cancel_work_sync(&hu->write_work);
 
 		if (hdev) {
@@ -765,7 +768,8 @@
 		break;
 
 	case HCIUARTGETPROTO:
-		if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
+		if (test_bit(HCI_UART_PROTO_SET, &hu->flags) &&
+		    test_bit(HCI_UART_PROTO_READY, &hu->flags))
 			err = hu->proto->id;
 		else
 			err = -EUNATCH;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/bluetooth/hci_ll.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/bluetooth/hci_ll.c
@@ -345,7 +345,7 @@
 	default:
 		BT_ERR("illegal hcill state: %ld (losing packet)",
 		       ll->hcill_state);
-		kfree_skb(skb);
+		dev_kfree_skb_irq(skb);
 		break;
 	}
 
@@ -621,38 +621,18 @@
 
 	serdev_device_set_flow_control(serdev, true);
 
-	if (hu->oper_speed)
-		speed = hu->oper_speed;
-	else if (hu->proto->oper_speed)
-		speed = hu->proto->oper_speed;
-	else
-		speed = 0;
-
 	do {
 		/* Reset the Bluetooth device */
 		gpiod_set_value_cansleep(lldev->enable_gpio, 0);
 		msleep(5);
 		gpiod_set_value_cansleep(lldev->enable_gpio, 1);
+		msleep(500);
 		err = serdev_device_wait_for_cts(serdev, true, 200);
 		if (err) {
 			bt_dev_err(hu->hdev, "Failed to get CTS");
 			return err;
 		}
 
-		if (speed) {
-			__le32 speed_le = cpu_to_le32(speed);
-			struct sk_buff *skb;
-
-			skb = __hci_cmd_sync(hu->hdev,
-					     HCI_VS_UPDATE_UART_HCI_BAUDRATE,
-					     sizeof(speed_le), &speed_le,
-					     HCI_INIT_TIMEOUT);
-			if (!IS_ERR(skb)) {
-				kfree_skb(skb);
-				serdev_device_set_baudrate(serdev, speed);
-			}
-		}
-
 		err = download_firmware(lldev);
 		if (!err)
 			break;
@@ -677,7 +657,25 @@
 	}
 
 	/* Operational speed if any */
+	if (hu->oper_speed)
+		speed = hu->oper_speed;
+	else if (hu->proto->oper_speed)
+		speed = hu->proto->oper_speed;
+	else
+		speed = 0;
 
+	if (speed) {
+		__le32 speed_le = cpu_to_le32(speed);
+		struct sk_buff *skb;
+
+		skb = __hci_cmd_sync(hu->hdev, HCI_VS_UPDATE_UART_HCI_BAUDRATE,
+				     sizeof(speed_le), &speed_le,
+				     HCI_INIT_TIMEOUT);
+		if (!IS_ERR(skb)) {
+			kfree_skb(skb);
+			serdev_device_set_baudrate(serdev, speed);
+		}
+	}
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/bluetooth/hci_nokia.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/bluetooth/hci_nokia.c
@@ -734,7 +734,11 @@
 		return err;
 	}
 
-	clk_prepare_enable(sysclk);
+	err = clk_prepare_enable(sysclk);
+	if (err) {
+		dev_err(dev, "could not enable sysclk: %d", err);
+		return err;
+	}
 	btdev->sysclk_speed = clk_get_rate(sysclk);
 	clk_disable_unprepare(sysclk);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/bluetooth/hci_qca.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/bluetooth/hci_qca.c
@@ -816,7 +816,7 @@
 	default:
 		BT_ERR("Illegal tx state: %d (losing packet)",
 		       qca->tx_ibs_state);
-		kfree_skb(skb);
+		dev_kfree_skb_irq(skb);
 		break;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/bluetooth/hci_serdev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/bluetooth/hci_serdev.c
@@ -85,9 +85,9 @@
 			hci_uart_tx_complete(hu, hci_skb_pkt_type(skb));
 			kfree_skb(skb);
 		}
-	} while (test_bit(HCI_UART_TX_WAKEUP, &hu->tx_state));
 
-	clear_bit(HCI_UART_SENDING, &hu->tx_state);
+		clear_bit(HCI_UART_SENDING, &hu->tx_state);
+	} while (test_bit(HCI_UART_TX_WAKEUP, &hu->tx_state));
 }
 
 /* ------- Interface to HCI layer ------ */
@@ -279,6 +279,8 @@
 	if (err)
 		return err;
 
+	percpu_init_rwsem(&hu->proto_lock);
+
 	err = p->open(hu);
 	if (err)
 		goto err_open;
@@ -301,7 +303,6 @@
 
 	INIT_WORK(&hu->init_ready, hci_uart_init_work);
 	INIT_WORK(&hu->write_work, hci_uart_write_work);
-	percpu_init_rwsem(&hu->proto_lock);
 
 	/* Only when vendor specific setup callback is provided, consider
 	 * the manufacturer information valid. This avoids filling in the
@@ -357,7 +358,10 @@
 	struct hci_dev *hdev = hu->hdev;
 
 	clear_bit(HCI_UART_PROTO_READY, &hu->flags);
-	hci_unregister_dev(hdev);
+
+	cancel_work_sync(&hu->init_ready);
+	if (test_bit(HCI_UART_REGISTERED, &hu->flags))
+		hci_unregister_dev(hdev);
 	hci_free_dev(hdev);
 
 	cancel_work_sync(&hu->write_work);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/bluetooth/hci_vhci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/bluetooth/hci_vhci.c
@@ -67,7 +67,10 @@
 	struct vhci_data *data = hci_get_drvdata(hdev);
 
 	memcpy(skb_push(skb, 1), &hci_skb_pkt_type(skb), 1);
+
+	mutex_lock(&data->open_mutex);
 	skb_queue_tail(&data->readq, skb);
+	mutex_unlock(&data->open_mutex);
 
 	wake_up_interruptible(&data->read_wait);
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/bus/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/bus/Kconfig
@@ -136,12 +136,12 @@
 
 config TEGRA_ACONNECT
 	tristate "Tegra ACONNECT Bus Driver"
-	depends on ARCH_TEGRA_210_SOC
+	depends on ARCH_TEGRA
 	depends on OF && PM
-	select PM_CLK
 	help
 	  Driver for the Tegra ACONNECT bus which is used to interface with
-	  the devices inside the Audio Processing Engine (APE) for Tegra210.
+	  the devices inside the Audio Processing Engine (APE) for
+	  Tegra210 and later.
 
 config TEGRA_GMI
 	tristate "Tegra Generic Memory Interface bus driver"
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/bus/fsl-mc/fsl-mc-allocator.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/bus/fsl-mc/fsl-mc-allocator.c
@@ -292,8 +292,10 @@
 		goto error;
 
 	mc_adev = resource->data;
-	if (!mc_adev)
+	if (!mc_adev) {
+		error = -EINVAL;
 		goto error;
+	}
 
 	mc_adev->consumer_link = device_link_add(&mc_dev->dev,
 						 &mc_adev->dev,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/bus/fsl-mc/mc-io.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/bus/fsl-mc/mc-io.c
@@ -129,7 +129,12 @@
  */
 void fsl_destroy_mc_io(struct fsl_mc_io *mc_io)
 {
-	struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
+	struct fsl_mc_device *dpmcp_dev;
+
+	if (!mc_io)
+		return;
+
+	dpmcp_dev = mc_io->dpmcp_dev;
 
 	if (dpmcp_dev)
 		fsl_mc_io_unset_dpmcp(mc_io);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/bus/hisi_lpc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/bus/hisi_lpc.c
@@ -359,6 +359,26 @@
 }
 
 /*
+ * Released firmware describes the IO port max address as 0x3fff, which is
+ * the max host bus address. Fixup to a proper range. This will probably
+ * never be fixed in firmware.
+ */
+static void hisi_lpc_acpi_fixup_child_resource(struct device *hostdev,
+					       struct resource *r)
+{
+	if (r->end != 0x3fff)
+		return;
+
+	if (r->start == 0xe4)
+		r->end = 0xe4 + 0x04 - 1;
+	else if (r->start == 0x2f8)
+		r->end = 0x2f8 + 0x08 - 1;
+	else
+		dev_warn(hostdev, "unrecognised resource %pR to fixup, ignoring\n",
+			 r);
+}
+
+/*
  * hisi_lpc_acpi_set_io_res - set the resources for a child
  * @child: the device node to be updated the I/O resource
  * @hostdev: the device node associated with host controller
@@ -419,8 +439,11 @@
 		return -ENOMEM;
 	}
 	count = 0;
-	list_for_each_entry(rentry, &resource_list, node)
-		resources[count++] = *rentry->res;
+	list_for_each_entry(rentry, &resource_list, node) {
+		resources[count] = *rentry->res;
+		hisi_lpc_acpi_fixup_child_resource(hostdev, &resources[count]);
+		count++;
+	}
 
 	acpi_dev_free_resource_list(&resource_list);
 
@@ -481,13 +504,13 @@
 {
 	struct acpi_device *adev = ACPI_COMPANION(hostdev);
 	struct acpi_device *child;
+	struct platform_device *pdev;
 	int ret;
 
 	/* Only consider the children of the host */
 	list_for_each_entry(child, &adev->children, node) {
 		const char *hid = acpi_device_hid(child);
 		const struct hisi_lpc_acpi_cell *cell;
-		struct platform_device *pdev;
 		const struct resource *res;
 		bool found = false;
 		int num_res;
@@ -549,22 +572,24 @@
 
 		ret = platform_device_add_resources(pdev, res, num_res);
 		if (ret)
-			goto fail;
+			goto fail_put_device;
 
 		ret = platform_device_add_data(pdev, cell->pdata,
 					       cell->pdata_size);
 		if (ret)
-			goto fail;
+			goto fail_put_device;
 
 		ret = platform_device_add(pdev);
 		if (ret)
-			goto fail;
+			goto fail_put_device;
 
 		acpi_device_set_enumerated(child);
 	}
 
 	return 0;
 
+fail_put_device:
+	platform_device_put(pdev);
 fail:
 	hisi_lpc_acpi_remove(hostdev);
 	return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/bus/imx-weim.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/bus/imx-weim.c
@@ -192,8 +192,8 @@
 	const struct of_device_id *of_id = of_match_device(weim_id_table,
 							   &pdev->dev);
 	const struct imx_weim_devtype *devtype = of_id->data;
+	int ret = 0, have_child = 0;
 	struct device_node *child;
-	int ret, have_child = 0;
 	struct cs_timing_state ts = {};
 	u32 reg;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/bus/mips_cdmm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/bus/mips_cdmm.c
@@ -544,10 +544,8 @@
 		dev_set_name(&dev->dev, "cdmm%u-%u", cpu, id);
 		++id;
 		ret = device_register(&dev->dev);
-		if (ret) {
+		if (ret)
 			put_device(&dev->dev);
-			kfree(dev);
-		}
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/bus/moxtet.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/bus/moxtet.c
@@ -466,7 +466,7 @@
 {
 	struct moxtet *moxtet = file->private_data;
 	u8 bin[TURRIS_MOX_MAX_MODULES];
-	u8 hex[sizeof(buf) * 2 + 1];
+	u8 hex[sizeof(bin) * 2 + 1];
 	int ret, n;
 
 	ret = moxtet_spi_read(moxtet, bin);
@@ -833,6 +833,12 @@
 	return 0;
 }
 
+static const struct spi_device_id moxtet_spi_ids[] = {
+	{ "moxtet" },
+	{ },
+};
+MODULE_DEVICE_TABLE(spi, moxtet_spi_ids);
+
 static const struct of_device_id moxtet_dt_ids[] = {
 	{ .compatible = "cznic,moxtet" },
 	{},
@@ -844,6 +850,7 @@
 		.name		= "moxtet",
 		.of_match_table = moxtet_dt_ids,
 	},
+	.id_table	= moxtet_spi_ids,
 	.probe		= moxtet_probe,
 	.remove		= moxtet_remove,
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/bus/omap_l3_noc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/bus/omap_l3_noc.c
@@ -285,7 +285,7 @@
 	 */
 	l3->debug_irq = platform_get_irq(pdev, 0);
 	ret = devm_request_irq(l3->dev, l3->debug_irq, l3_interrupt_handler,
-			       0x0, "l3-dbg-irq", l3);
+			       IRQF_NO_THREAD, "l3-dbg-irq", l3);
 	if (ret) {
 		dev_err(l3->dev, "request_irq failed for %d\n",
 			l3->debug_irq);
@@ -294,7 +294,7 @@
 
 	l3->app_irq = platform_get_irq(pdev, 1);
 	ret = devm_request_irq(l3->dev, l3->app_irq, l3_interrupt_handler,
-			       0x0, "l3-app-irq", l3);
+			       IRQF_NO_THREAD, "l3-app-irq", l3);
 	if (ret)
 		dev_err(l3->dev, "request_irq failed for %d\n", l3->app_irq);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/bus/qcom-ebi2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/bus/qcom-ebi2.c
@@ -353,8 +353,10 @@
 
 		/* Figure out the chipselect */
 		ret = of_property_read_u32(child, "reg", &csindex);
-		if (ret)
+		if (ret) {
+			of_node_put(child);
 			return ret;
+		}
 
 		if (csindex > 5) {
 			dev_err(dev,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/bus/sunxi-rsb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/bus/sunxi-rsb.c
@@ -224,6 +224,8 @@
 
 	dev_dbg(&rdev->dev, "device %s registered\n", dev_name(&rdev->dev));
 
+	return rdev;
+
 err_device_add:
 	put_device(&rdev->dev);
 
@@ -266,6 +268,9 @@
 /* common code that starts a transfer */
 static int _sunxi_rsb_run_xfer(struct sunxi_rsb *rsb)
 {
+	u32 int_mask, status;
+	bool timeout;
+
 	if (readl(rsb->regs + RSB_CTRL) & RSB_CTRL_START_TRANS) {
 		dev_dbg(rsb->dev, "RSB transfer still in progress\n");
 		return -EBUSY;
@@ -273,13 +278,23 @@
 
 	reinit_completion(&rsb->complete);
 
-	writel(RSB_INTS_LOAD_BSY | RSB_INTS_TRANS_ERR | RSB_INTS_TRANS_OVER,
-	       rsb->regs + RSB_INTE);
+	int_mask = RSB_INTS_LOAD_BSY | RSB_INTS_TRANS_ERR | RSB_INTS_TRANS_OVER;
+	writel(int_mask, rsb->regs + RSB_INTE);
 	writel(RSB_CTRL_START_TRANS | RSB_CTRL_GLOBAL_INT_ENB,
 	       rsb->regs + RSB_CTRL);
 
-	if (!wait_for_completion_io_timeout(&rsb->complete,
-					    msecs_to_jiffies(100))) {
+	if (irqs_disabled()) {
+		timeout = readl_poll_timeout_atomic(rsb->regs + RSB_INTS,
+						    status, (status & int_mask),
+						    10, 100000);
+		writel(status, rsb->regs + RSB_INTS);
+	} else {
+		timeout = !wait_for_completion_io_timeout(&rsb->complete,
+							  msecs_to_jiffies(100));
+		status = rsb->status;
+	}
+
+	if (timeout) {
 		dev_dbg(rsb->dev, "RSB timeout\n");
 
 		/* abort the transfer */
@@ -291,18 +306,18 @@
 		return -ETIMEDOUT;
 	}
 
-	if (rsb->status & RSB_INTS_LOAD_BSY) {
+	if (status & RSB_INTS_LOAD_BSY) {
 		dev_dbg(rsb->dev, "RSB busy\n");
 		return -EBUSY;
 	}
 
-	if (rsb->status & RSB_INTS_TRANS_ERR) {
-		if (rsb->status & RSB_INTS_TRANS_ERR_ACK) {
+	if (status & RSB_INTS_TRANS_ERR) {
+		if (status & RSB_INTS_TRANS_ERR_ACK) {
 			dev_dbg(rsb->dev, "RSB slave nack\n");
 			return -EINVAL;
 		}
 
-		if (rsb->status & RSB_INTS_TRANS_ERR_DATA) {
+		if (status & RSB_INTS_TRANS_ERR_DATA) {
 			dev_dbg(rsb->dev, "RSB transfer data error\n");
 			return -EIO;
 		}
@@ -345,7 +360,7 @@
 	if (ret)
 		goto unlock;
 
-	*buf = readl(rsb->regs + RSB_DATA);
+	*buf = readl(rsb->regs + RSB_DATA) & GENMASK(len * 8 - 1, 0);
 
 unlock:
 	mutex_unlock(&rsb->lock);
@@ -766,7 +781,13 @@
 		return ret;
 	}
 
-	return platform_driver_register(&sunxi_rsb_driver);
+	ret = platform_driver_register(&sunxi_rsb_driver);
+	if (ret) {
+		bus_unregister(&sunxi_rsb_bus);
+		return ret;
+	}
+
+	return 0;
 }
 module_init(sunxi_rsb_init);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/bus/ti-sysc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/bus/ti-sysc.c
@@ -70,11 +70,13 @@
  * @child_needs_resume: runtime resume needed for child on resume from suspend
  * @disable_on_idle: status flag used for disabling modules with resets
  * @idle_work: work structure used to perform delayed idle on a module
- * @clk_enable_quirk: module specific clock enable quirk
- * @clk_disable_quirk: module specific clock disable quirk
+ * @pre_reset_quirk: module specific pre-reset quirk
+ * @post_reset_quirk: module specific post-reset quirk
  * @reset_done_quirk: module specific reset done quirk
  * @module_enable_quirk: module specific enable quirk
  * @module_disable_quirk: module specific disable quirk
+ * @module_unlock_quirk: module specific sysconfig unlock quirk
+ * @module_lock_quirk: module specific sysconfig lock quirk
  */
 struct sysc {
 	struct device *dev;
@@ -97,11 +99,13 @@
 	unsigned int needs_resume:1;
 	unsigned int child_needs_resume:1;
 	struct delayed_work idle_work;
-	void (*clk_enable_quirk)(struct sysc *sysc);
-	void (*clk_disable_quirk)(struct sysc *sysc);
+	void (*pre_reset_quirk)(struct sysc *sysc);
+	void (*post_reset_quirk)(struct sysc *sysc);
 	void (*reset_done_quirk)(struct sysc *sysc);
 	void (*module_enable_quirk)(struct sysc *sysc);
 	void (*module_disable_quirk)(struct sysc *sysc);
+	void (*module_unlock_quirk)(struct sysc *sysc);
+	void (*module_lock_quirk)(struct sysc *sysc);
 };
 
 static void sysc_parse_dts_quirks(struct sysc *ddata, struct device_node *np,
@@ -182,6 +186,37 @@
 	return sysc_read(ddata, offset);
 }
 
+/* Poll on reset status */
+static int sysc_wait_softreset(struct sysc *ddata)
+{
+	u32 sysc_mask, syss_done, rstval;
+	int syss_offset, error = 0;
+
+	if (ddata->cap->regbits->srst_shift < 0)
+		return 0;
+
+	syss_offset = ddata->offsets[SYSC_SYSSTATUS];
+	sysc_mask = BIT(ddata->cap->regbits->srst_shift);
+
+	if (ddata->cfg.quirks & SYSS_QUIRK_RESETDONE_INVERTED)
+		syss_done = 0;
+	else
+		syss_done = ddata->cfg.syss_mask;
+
+	if (syss_offset >= 0) {
+		error = readx_poll_timeout_atomic(sysc_read_sysstatus, ddata,
+				rstval, (rstval & ddata->cfg.syss_mask) ==
+				syss_done, 100, MAX_MODULE_SOFTRESET_WAIT);
+
+	} else if (ddata->cfg.quirks & SYSC_QUIRK_RESET_STATUS) {
+		error = readx_poll_timeout_atomic(sysc_read_sysconfig, ddata,
+				rstval, !(rstval & sysc_mask),
+				100, MAX_MODULE_SOFTRESET_WAIT);
+	}
+
+	return error;
+}
+
 static int sysc_add_named_clock_from_child(struct sysc *ddata,
 					   const char *name,
 					   const char *optfck_name)
@@ -343,6 +378,12 @@
 		return -EINVAL;
 	}
 
+	/* Always add a slot for main clocks fck and ick even if unused */
+	if (!nr_fck)
+		ddata->nr_clocks++;
+	if (!nr_ick)
+		ddata->nr_clocks++;
+
 	ddata->clocks = devm_kcalloc(ddata->dev,
 				     ddata->nr_clocks, sizeof(*ddata->clocks),
 				     GFP_KERNEL);
@@ -421,7 +462,7 @@
 	struct clk *clock;
 	int i, error;
 
-	if (!ddata->clocks)
+	if (!ddata->clocks || ddata->nr_clocks < SYSC_OPTFCK0 + 1)
 		return 0;
 
 	for (i = SYSC_OPTFCK0; i < SYSC_MAX_CLOCKS; i++) {
@@ -455,7 +496,7 @@
 	struct clk *clock;
 	int i;
 
-	if (!ddata->clocks)
+	if (!ddata->clocks || ddata->nr_clocks < SYSC_OPTFCK0 + 1)
 		return;
 
 	for (i = SYSC_OPTFCK0; i < SYSC_MAX_CLOCKS; i++) {
@@ -473,7 +514,7 @@
 {
 	struct ti_sysc_platform_data *pdata;
 
-	if (ddata->legacy_mode)
+	if (ddata->legacy_mode || (ddata->cfg.quirks & SYSC_QUIRK_CLKDM_NOAUTO))
 		return;
 
 	pdata = dev_get_platdata(ddata->dev);
@@ -485,7 +526,7 @@
 {
 	struct ti_sysc_platform_data *pdata;
 
-	if (ddata->legacy_mode)
+	if (ddata->legacy_mode || (ddata->cfg.quirks & SYSC_QUIRK_CLKDM_NOAUTO))
 		return;
 
 	pdata = dev_get_platdata(ddata->dev);
@@ -561,6 +602,51 @@
 	return 0;
 }
 
+/* Interconnect instances to probe before l4_per instances */
+static struct resource early_bus_ranges[] = {
+	/* am3/4 l4_wkup */
+	{ .start = 0x44c00000, .end = 0x44c00000 + 0x300000, },
+	/* omap4/5 and dra7 l4_cfg */
+	{ .start = 0x4a000000, .end = 0x4a000000 + 0x300000, },
+	/* omap4 l4_wkup */
+	{ .start = 0x4a300000, .end = 0x4a300000 + 0x30000,  },
+	/* omap5 and dra7 l4_wkup without dra7 dcan segment */
+	{ .start = 0x4ae00000, .end = 0x4ae00000 + 0x30000,  },
+};
+
+static atomic_t sysc_defer = ATOMIC_INIT(10);
+
+/**
+ * sysc_defer_non_critical - defer non_critical interconnect probing
+ * @ddata: device driver data
+ *
+ * We want to probe l4_cfg and l4_wkup interconnect instances before any
+ * l4_per instances as l4_per instances depend on resources on l4_cfg and
+ * l4_wkup interconnects.
+ */
+static int sysc_defer_non_critical(struct sysc *ddata)
+{
+	struct resource *res;
+	int i;
+
+	if (!atomic_read(&sysc_defer))
+		return 0;
+
+	for (i = 0; i < ARRAY_SIZE(early_bus_ranges); i++) {
+		res = &early_bus_ranges[i];
+		if (ddata->module_pa >= res->start &&
+		    ddata->module_pa <= res->end) {
+			atomic_set(&sysc_defer, 0);
+
+			return 0;
+		}
+	}
+
+	atomic_dec_if_positive(&sysc_defer);
+
+	return -EPROBE_DEFER;
+}
+
 static struct device_node *stdout_path;
 
 static void sysc_init_stdout_path(struct sysc *ddata)
@@ -785,6 +871,10 @@
 	if (error)
 		return error;
 
+	error = sysc_defer_non_critical(ddata);
+	if (error)
+		return error;
+
 	sysc_check_children(ddata);
 
 	error = sysc_parse_registers(ddata);
@@ -857,6 +947,22 @@
 		buf);
 }
 
+/**
+ * sysc_write_sysconfig - handle sysconfig quirks for register write
+ * @ddata: device driver data
+ * @value: register value
+ */
+static void sysc_write_sysconfig(struct sysc *ddata, u32 value)
+{
+	if (ddata->module_unlock_quirk)
+		ddata->module_unlock_quirk(ddata);
+
+	sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], value);
+
+	if (ddata->module_lock_quirk)
+		ddata->module_lock_quirk(ddata);
+}
+
 #define SYSC_IDLE_MASK	(SYSC_NR_IDLEMODES - 1)
 #define SYSC_CLOCACT_ICK	2
 
@@ -866,18 +972,47 @@
 	struct sysc *ddata;
 	const struct sysc_regbits *regbits;
 	u32 reg, idlemodes, best_mode;
+	int error;
 
 	ddata = dev_get_drvdata(dev);
+
+	/*
+	 * Some modules like DSS reset automatically on idle. Enable optional
+	 * reset clocks and wait for OCP softreset to complete.
+	 */
+	if (ddata->cfg.quirks & SYSC_QUIRK_OPT_CLKS_IN_RESET) {
+		error = sysc_enable_opt_clocks(ddata);
+		if (error) {
+			dev_err(ddata->dev,
+				"Optional clocks failed for enable: %i\n",
+				error);
+			return error;
+		}
+	}
+	error = sysc_wait_softreset(ddata);
+	if (error)
+		dev_warn(ddata->dev, "OCP softreset timed out\n");
+	if (ddata->cfg.quirks & SYSC_QUIRK_OPT_CLKS_IN_RESET)
+		sysc_disable_opt_clocks(ddata);
+
+	/*
+	 * Some subsystem private interconnects, like DSS top level module,
+	 * need only the automatic OCP softreset handling with no sysconfig
+	 * register bits to configure.
+	 */
 	if (ddata->offsets[SYSC_SYSCONFIG] == -ENODEV)
 		return 0;
 
 	regbits = ddata->cap->regbits;
 	reg = sysc_read(ddata, ddata->offsets[SYSC_SYSCONFIG]);
 
-	/* Set CLOCKACTIVITY, we only use it for ick */
+	/*
+	 * Set CLOCKACTIVITY, we only use it for ick. And we only configure it
+	 * based on the SYSC_QUIRK_USE_CLOCKACT flag, not based on the hardware
+	 * capabilities. See the old HWMOD_SET_DEFAULT_CLOCKACT flag.
+	 */
 	if (regbits->clkact_shift >= 0 &&
-	    (ddata->cfg.quirks & SYSC_QUIRK_USE_CLOCKACT ||
-	     ddata->cfg.sysc_val & BIT(regbits->clkact_shift)))
+	    (ddata->cfg.quirks & SYSC_QUIRK_USE_CLOCKACT))
 		reg |= SYSC_CLOCACT_ICK << regbits->clkact_shift;
 
 	/* Set SIDLE mode */
@@ -888,6 +1023,11 @@
 	if (ddata->cfg.quirks & (SYSC_QUIRK_SWSUP_SIDLE |
 				 SYSC_QUIRK_SWSUP_SIDLE_ACT)) {
 		best_mode = SYSC_IDLE_NO;
+
+		/* Clear WAKEUP */
+		if (regbits->enwkup_shift >= 0 &&
+		    ddata->cfg.sysc_val & BIT(regbits->enwkup_shift))
+			reg &= ~BIT(regbits->enwkup_shift);
 	} else {
 		best_mode = fls(ddata->cfg.sidlemodes) - 1;
 		if (best_mode > SYSC_IDLE_MASK) {
@@ -903,7 +1043,7 @@
 
 	reg &= ~(SYSC_IDLE_MASK << regbits->sidle_shift);
 	reg |= best_mode << regbits->sidle_shift;
-	sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], reg);
+	sysc_write_sysconfig(ddata, reg);
 
 set_midle:
 	/* Set MIDLE mode */
@@ -917,18 +1057,24 @@
 		return -EINVAL;
 	}
 
+	if (ddata->cfg.quirks & SYSC_QUIRK_SWSUP_MSTANDBY)
+		best_mode = SYSC_IDLE_NO;
+
 	reg &= ~(SYSC_IDLE_MASK << regbits->midle_shift);
 	reg |= best_mode << regbits->midle_shift;
-	sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], reg);
+	sysc_write_sysconfig(ddata, reg);
 
 set_autoidle:
 	/* Autoidle bit must enabled separately if available */
 	if (regbits->autoidle_shift >= 0 &&
 	    ddata->cfg.sysc_val & BIT(regbits->autoidle_shift)) {
 		reg |= 1 << regbits->autoidle_shift;
-		sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], reg);
+		sysc_write_sysconfig(ddata, reg);
 	}
 
+	/* Flush posted write */
+	sysc_read(ddata, ddata->offsets[SYSC_SYSCONFIG]);
+
 	if (ddata->module_enable_quirk)
 		ddata->module_enable_quirk(ddata);
 
@@ -978,9 +1124,13 @@
 		return ret;
 	}
 
+	if (ddata->cfg.quirks & (SYSC_QUIRK_SWSUP_MSTANDBY) ||
+	    ddata->cfg.quirks & (SYSC_QUIRK_FORCE_MSTANDBY))
+		best_mode = SYSC_IDLE_FORCE;
+
 	reg &= ~(SYSC_IDLE_MASK << regbits->midle_shift);
 	reg |= best_mode << regbits->midle_shift;
-	sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], reg);
+	sysc_write_sysconfig(ddata, reg);
 
 set_sidle:
 	/* Set SIDLE mode */
@@ -998,12 +1148,22 @@
 		}
 	}
 
+	if (ddata->cfg.quirks & SYSC_QUIRK_SWSUP_SIDLE_ACT) {
+		/* Set WAKEUP */
+		if (regbits->enwkup_shift >= 0 &&
+		    ddata->cfg.sysc_val & BIT(regbits->enwkup_shift))
+			reg |= BIT(regbits->enwkup_shift);
+	}
+
 	reg &= ~(SYSC_IDLE_MASK << regbits->sidle_shift);
 	reg |= best_mode << regbits->sidle_shift;
 	if (regbits->autoidle_shift >= 0 &&
 	    ddata->cfg.sysc_val & BIT(regbits->autoidle_shift))
 		reg |= 1 << regbits->autoidle_shift;
-	sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], reg);
+	sysc_write_sysconfig(ddata, reg);
+
+	/* Flush posted write */
+	sysc_read(ddata, ddata->offsets[SYSC_SYSCONFIG]);
 
 	return 0;
 }
@@ -1149,7 +1309,8 @@
 
 	ddata = dev_get_drvdata(dev);
 
-	if (ddata->cfg.quirks & SYSC_QUIRK_LEGACY_IDLE)
+	if (ddata->cfg.quirks &
+	    (SYSC_QUIRK_LEGACY_IDLE | SYSC_QUIRK_NO_IDLE))
 		return 0;
 
 	return pm_runtime_force_suspend(dev);
@@ -1161,7 +1322,8 @@
 
 	ddata = dev_get_drvdata(dev);
 
-	if (ddata->cfg.quirks & SYSC_QUIRK_LEGACY_IDLE)
+	if (ddata->cfg.quirks &
+	    (SYSC_QUIRK_LEGACY_IDLE | SYSC_QUIRK_NO_IDLE))
 		return 0;
 
 	return pm_runtime_force_resume(dev);
@@ -1209,33 +1371,54 @@
 		   SYSC_QUIRK_LEGACY_IDLE),
 	SYSC_QUIRK("sham", 0, 0x100, 0x110, 0x114, 0x40000c03, 0xffffffff,
 		   SYSC_QUIRK_LEGACY_IDLE),
-	SYSC_QUIRK("smartreflex", 0, -1, 0x24, -1, 0x00000000, 0xffffffff,
+	SYSC_QUIRK("smartreflex", 0, -ENODEV, 0x24, -ENODEV, 0x00000000, 0xffffffff,
 		   SYSC_QUIRK_LEGACY_IDLE),
-	SYSC_QUIRK("smartreflex", 0, -1, 0x38, -1, 0x00000000, 0xffffffff,
+	SYSC_QUIRK("smartreflex", 0, -ENODEV, 0x38, -ENODEV, 0x00000000, 0xffffffff,
 		   SYSC_QUIRK_LEGACY_IDLE),
 	SYSC_QUIRK("timer", 0, 0, 0x10, 0x14, 0x00000015, 0xffffffff,
 		   0),
 	/* Some timers on omap4 and later */
-	SYSC_QUIRK("timer", 0, 0, 0x10, -1, 0x50002100, 0xffffffff,
+	SYSC_QUIRK("timer", 0, 0, 0x10, -ENODEV, 0x50002100, 0xffffffff,
 		   0),
-	SYSC_QUIRK("timer", 0, 0, 0x10, -1, 0x4fff1301, 0xffff00ff,
+	SYSC_QUIRK("timer", 0, 0, 0x10, -ENODEV, 0x4fff1301, 0xffff00ff,
 		   0),
 	SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x00000046, 0xffffffff,
-		   SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_LEGACY_IDLE),
+		   SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE),
 	SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x00000052, 0xffffffff,
-		   SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_LEGACY_IDLE),
+		   SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE),
 	/* Uarts on omap4 and later */
 	SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x50411e03, 0xffff00ff,
 		   SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE),
 	SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x47422e03, 0xffffffff,
 		   SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE),
+	SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x47424e03, 0xffffffff,
+		   SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE),
 
 	/* Quirks that need to be set based on the module address */
-	SYSC_QUIRK("mcpdm", 0x40132000, 0, 0x10, -1, 0x50000800, 0xffffffff,
+	SYSC_QUIRK("mcpdm", 0x40132000, 0, 0x10, -ENODEV, 0x50000800, 0xffffffff,
 		   SYSC_QUIRK_EXT_OPT_CLOCK | SYSC_QUIRK_NO_RESET_ON_INIT |
 		   SYSC_QUIRK_SWSUP_SIDLE),
 
 	/* Quirks that need to be set based on detected module */
+	SYSC_QUIRK("aess", 0, 0, 0x10, -ENODEV, 0x40000000, 0xffffffff,
+		   SYSC_MODULE_QUIRK_AESS),
+	/* Errata i893 handling for dra7 dcan1 and 2 */
+	SYSC_QUIRK("dcan", 0x4ae3c000, 0x20, -ENODEV, -ENODEV, 0xa3170504, 0xffffffff,
+		   SYSC_QUIRK_CLKDM_NOAUTO),
+	SYSC_QUIRK("dcan", 0x48480000, 0x20, -ENODEV, -ENODEV, 0xa3170504, 0xffffffff,
+		   SYSC_QUIRK_CLKDM_NOAUTO),
+	SYSC_QUIRK("dss", 0x4832a000, 0, 0x10, 0x14, 0x00000020, 0xffffffff,
+		   SYSC_QUIRK_OPT_CLKS_IN_RESET),
+	SYSC_QUIRK("dss", 0x58000000, 0, -ENODEV, 0x14, 0x00000040, 0xffffffff,
+		   SYSC_QUIRK_OPT_CLKS_IN_RESET),
+	SYSC_QUIRK("dss", 0x58000000, 0, -ENODEV, 0x14, 0x00000061, 0xffffffff,
+		   SYSC_QUIRK_OPT_CLKS_IN_RESET),
+	SYSC_QUIRK("dwc3", 0x48880000, 0, 0x10, -ENODEV, 0x500a0200, 0xffffffff,
+		   SYSC_QUIRK_CLKDM_NOAUTO),
+	SYSC_QUIRK("dwc3", 0x488c0000, 0, 0x10, -ENODEV, 0x500a0200, 0xffffffff,
+		   SYSC_QUIRK_CLKDM_NOAUTO),
+	SYSC_QUIRK("hdmi", 0, 0, 0x10, -ENODEV, 0x50030200, 0xffffffff,
+		   SYSC_QUIRK_OPT_CLKS_NEEDED),
 	SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x00000006, 0xffffffff,
 		   SYSC_MODULE_QUIRK_HDQ1W),
 	SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x0000000a, 0xffffffff,
@@ -1248,9 +1431,23 @@
 		   SYSC_MODULE_QUIRK_I2C),
 	SYSC_QUIRK("i2c", 0, 0, 0x10, 0x90, 0x5040000a, 0xfffff0f0,
 		   SYSC_MODULE_QUIRK_I2C),
-	SYSC_QUIRK("gpu", 0x50000000, 0x14, -1, -1, 0x00010201, 0xffffffff, 0),
-	SYSC_QUIRK("gpu", 0x50000000, 0xfe00, 0xfe10, -1, 0x40000000 , 0xffffffff,
+	SYSC_QUIRK("gpu", 0x50000000, 0x14, -ENODEV, -ENODEV, 0x00010201, 0xffffffff, 0),
+	SYSC_QUIRK("gpu", 0x50000000, 0xfe00, 0xfe10, -ENODEV, 0x40000000 , 0xffffffff,
 		   SYSC_MODULE_QUIRK_SGX),
+	SYSC_QUIRK("rtc", 0, 0x74, 0x78, -ENODEV, 0x4eb01908, 0xffff00f0,
+		   SYSC_MODULE_QUIRK_RTC_UNLOCK),
+	SYSC_QUIRK("tptc", 0, 0, 0x10, -ENODEV, 0x40006c00, 0xffffefff,
+		   SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY),
+	SYSC_QUIRK("tptc", 0, 0, -ENODEV, -ENODEV, 0x40007c00, 0xffffffff,
+		   SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY),
+	SYSC_QUIRK("usb_host_hs", 0, 0, 0x10, 0x14, 0x50700100, 0xffffffff,
+		   SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY),
+	SYSC_QUIRK("usb_host_hs", 0, 0, 0x10, -ENODEV, 0x50700101, 0xffffffff,
+		   SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY),
+	SYSC_QUIRK("usb_otg_hs", 0, 0x400, 0x404, 0x408, 0x00000050,
+		   0xffffffff, SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY),
+	SYSC_QUIRK("usb_otg_hs", 0, 0, 0x10, -ENODEV, 0x4ea2080d, 0xffffffff,
+		   SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY),
 	SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0500, 0xfffff0f0,
 		   SYSC_MODULE_QUIRK_WDT),
 	/* Watchdog on am3 and am4 */
@@ -1258,60 +1455,66 @@
 		   SYSC_MODULE_QUIRK_WDT | SYSC_QUIRK_SWSUP_SIDLE),
 
 #ifdef DEBUG
-	SYSC_QUIRK("adc", 0, 0, 0x10, -1, 0x47300001, 0xffffffff, 0),
-	SYSC_QUIRK("atl", 0, 0, -1, -1, 0x0a070100, 0xffffffff, 0),
-	SYSC_QUIRK("aess", 0, 0, 0x10, -1, 0x40000000, 0xffffffff, 0),
-	SYSC_QUIRK("cm", 0, 0, -1, -1, 0x40000301, 0xffffffff, 0),
-	SYSC_QUIRK("control", 0, 0, 0x10, -1, 0x40000900, 0xffffffff, 0),
+	SYSC_QUIRK("adc", 0, 0, 0x10, -ENODEV, 0x47300001, 0xffffffff, 0),
+	SYSC_QUIRK("atl", 0, 0, -ENODEV, -ENODEV, 0x0a070100, 0xffffffff, 0),
+	SYSC_QUIRK("cm", 0, 0, -ENODEV, -ENODEV, 0x40000301, 0xffffffff, 0),
+	SYSC_QUIRK("control", 0, 0, 0x10, -ENODEV, 0x40000900, 0xffffffff, 0),
 	SYSC_QUIRK("cpgmac", 0, 0x1200, 0x1208, 0x1204, 0x4edb1902,
 		   0xffff00f0, 0),
-	SYSC_QUIRK("dcan", 0, 0x20, -1, -1, 0xa3170504, 0xffffffff, 0),
-	SYSC_QUIRK("dcan", 0, 0x20, -1, -1, 0x4edb1902, 0xffffffff, 0),
-	SYSC_QUIRK("dmic", 0, 0, 0x10, -1, 0x50010000, 0xffffffff, 0),
-	SYSC_QUIRK("dwc3", 0, 0, 0x10, -1, 0x500a0200, 0xffffffff, 0),
+	SYSC_QUIRK("dcan", 0, 0x20, -ENODEV, -ENODEV, 0xa3170504, 0xffffffff, 0),
+	SYSC_QUIRK("dcan", 0, 0x20, -ENODEV, -ENODEV, 0x4edb1902, 0xffffffff, 0),
+	SYSC_QUIRK("dispc", 0x4832a400, 0, 0x10, 0x14, 0x00000030, 0xffffffff, 0),
+	SYSC_QUIRK("dispc", 0x58001000, 0, 0x10, 0x14, 0x00000040, 0xffffffff, 0),
+	SYSC_QUIRK("dispc", 0x58001000, 0, 0x10, 0x14, 0x00000051, 0xffffffff, 0),
+	SYSC_QUIRK("dmic", 0, 0, 0x10, -ENODEV, 0x50010000, 0xffffffff, 0),
+	SYSC_QUIRK("dsi", 0x58004000, 0, 0x10, 0x14, 0x00000030, 0xffffffff, 0),
+	SYSC_QUIRK("dsi", 0x58005000, 0, 0x10, 0x14, 0x00000030, 0xffffffff, 0),
+	SYSC_QUIRK("dsi", 0x58005000, 0, 0x10, 0x14, 0x00000040, 0xffffffff, 0),
+	SYSC_QUIRK("dsi", 0x58009000, 0, 0x10, 0x14, 0x00000040, 0xffffffff, 0),
+	SYSC_QUIRK("dwc3", 0, 0, 0x10, -ENODEV, 0x500a0200, 0xffffffff, 0),
 	SYSC_QUIRK("d2d", 0x4a0b6000, 0, 0x10, 0x14, 0x00000010, 0xffffffff, 0),
 	SYSC_QUIRK("d2d", 0x4a0cd000, 0, 0x10, 0x14, 0x00000010, 0xffffffff, 0),
-	SYSC_QUIRK("epwmss", 0, 0, 0x4, -1, 0x47400001, 0xffffffff, 0),
-	SYSC_QUIRK("gpu", 0, 0x1fc00, 0x1fc10, -1, 0, 0, 0),
-	SYSC_QUIRK("gpu", 0, 0xfe00, 0xfe10, -1, 0x40000000 , 0xffffffff, 0),
+	SYSC_QUIRK("epwmss", 0, 0, 0x4, -ENODEV, 0x47400001, 0xffffffff, 0),
+	SYSC_QUIRK("gpu", 0, 0x1fc00, 0x1fc10, -ENODEV, 0, 0, 0),
+	SYSC_QUIRK("gpu", 0, 0xfe00, 0xfe10, -ENODEV, 0x40000000 , 0xffffffff, 0),
+	SYSC_QUIRK("hdmi", 0, 0, 0x10, -ENODEV, 0x50031d00, 0xffffffff, 0),
 	SYSC_QUIRK("hsi", 0, 0, 0x10, 0x14, 0x50043101, 0xffffffff, 0),
-	SYSC_QUIRK("iss", 0, 0, 0x10, -1, 0x40000101, 0xffffffff, 0),
-	SYSC_QUIRK("lcdc", 0, 0, 0x54, -1, 0x4f201000, 0xffffffff, 0),
-	SYSC_QUIRK("mcasp", 0, 0, 0x4, -1, 0x44306302, 0xffffffff, 0),
-	SYSC_QUIRK("mcasp", 0, 0, 0x4, -1, 0x44307b02, 0xffffffff, 0),
-	SYSC_QUIRK("mcbsp", 0, -1, 0x8c, -1, 0, 0, 0),
-	SYSC_QUIRK("mcspi", 0, 0, 0x10, -1, 0x40300a0b, 0xffff00ff, 0),
+	SYSC_QUIRK("iss", 0, 0, 0x10, -ENODEV, 0x40000101, 0xffffffff, 0),
+	SYSC_QUIRK("lcdc", 0, 0, 0x54, -ENODEV, 0x4f201000, 0xffffffff, 0),
+	SYSC_QUIRK("mcasp", 0, 0, 0x4, -ENODEV, 0x44306302, 0xffffffff, 0),
+	SYSC_QUIRK("mcasp", 0, 0, 0x4, -ENODEV, 0x44307b02, 0xffffffff, 0),
+	SYSC_QUIRK("mcbsp", 0, -ENODEV, 0x8c, -ENODEV, 0, 0, 0),
+	SYSC_QUIRK("mcspi", 0, 0, 0x10, -ENODEV, 0x40300a0b, 0xffff00ff, 0),
 	SYSC_QUIRK("mcspi", 0, 0, 0x110, 0x114, 0x40300a0b, 0xffffffff, 0),
-	SYSC_QUIRK("mailbox", 0, 0, 0x10, -1, 0x00000400, 0xffffffff, 0),
-	SYSC_QUIRK("m3", 0, 0, -1, -1, 0x5f580105, 0x0fff0f00, 0),
+	SYSC_QUIRK("mailbox", 0, 0, 0x10, -ENODEV, 0x00000400, 0xffffffff, 0),
+	SYSC_QUIRK("m3", 0, 0, -ENODEV, -ENODEV, 0x5f580105, 0x0fff0f00, 0),
 	SYSC_QUIRK("ocp2scp", 0, 0, 0x10, 0x14, 0x50060005, 0xfffffff0, 0),
-	SYSC_QUIRK("ocp2scp", 0, 0, -1, -1, 0x50060007, 0xffffffff, 0),
-	SYSC_QUIRK("padconf", 0, 0, 0x10, -1, 0x4fff0800, 0xffffffff, 0),
-	SYSC_QUIRK("padconf", 0, 0, -1, -1, 0x40001100, 0xffffffff, 0),
-	SYSC_QUIRK("prcm", 0, 0, -1, -1, 0x40000100, 0xffffffff, 0),
-	SYSC_QUIRK("prcm", 0, 0, -1, -1, 0x00004102, 0xffffffff, 0),
-	SYSC_QUIRK("prcm", 0, 0, -1, -1, 0x40000400, 0xffffffff, 0),
-	SYSC_QUIRK("scm", 0, 0, 0x10, -1, 0x40000900, 0xffffffff, 0),
-	SYSC_QUIRK("scm", 0, 0, -1, -1, 0x4e8b0100, 0xffffffff, 0),
-	SYSC_QUIRK("scm", 0, 0, -1, -1, 0x4f000100, 0xffffffff, 0),
-	SYSC_QUIRK("scm", 0, 0, -1, -1, 0x40000900, 0xffffffff, 0),
-	SYSC_QUIRK("scrm", 0, 0, -1, -1, 0x00000010, 0xffffffff, 0),
-	SYSC_QUIRK("sdio", 0, 0, 0x10, -1, 0x40202301, 0xffff0ff0, 0),
+	SYSC_QUIRK("ocp2scp", 0, 0, -ENODEV, -ENODEV, 0x50060007, 0xffffffff, 0),
+	SYSC_QUIRK("padconf", 0, 0, 0x10, -ENODEV, 0x4fff0800, 0xffffffff, 0),
+	SYSC_QUIRK("padconf", 0, 0, -ENODEV, -ENODEV, 0x40001100, 0xffffffff, 0),
+	SYSC_QUIRK("prcm", 0, 0, -ENODEV, -ENODEV, 0x40000100, 0xffffffff, 0),
+	SYSC_QUIRK("prcm", 0, 0, -ENODEV, -ENODEV, 0x00004102, 0xffffffff, 0),
+	SYSC_QUIRK("prcm", 0, 0, -ENODEV, -ENODEV, 0x40000400, 0xffffffff, 0),
+	SYSC_QUIRK("rfbi", 0x4832a800, 0, 0x10, 0x14, 0x00000010, 0xffffffff, 0),
+	SYSC_QUIRK("rfbi", 0x58002000, 0, 0x10, 0x14, 0x00000010, 0xffffffff, 0),
+	SYSC_QUIRK("scm", 0, 0, 0x10, -ENODEV, 0x40000900, 0xffffffff, 0),
+	SYSC_QUIRK("scm", 0, 0, -ENODEV, -ENODEV, 0x4e8b0100, 0xffffffff, 0),
+	SYSC_QUIRK("scm", 0, 0, -ENODEV, -ENODEV, 0x4f000100, 0xffffffff, 0),
+	SYSC_QUIRK("scm", 0, 0, -ENODEV, -ENODEV, 0x40000900, 0xffffffff, 0),
+	SYSC_QUIRK("scrm", 0, 0, -ENODEV, -ENODEV, 0x00000010, 0xffffffff, 0),
+	SYSC_QUIRK("sdio", 0, 0, 0x10, -ENODEV, 0x40202301, 0xffff0ff0, 0),
 	SYSC_QUIRK("sdio", 0, 0x2fc, 0x110, 0x114, 0x31010000, 0xffffffff, 0),
 	SYSC_QUIRK("sdma", 0, 0, 0x2c, 0x28, 0x00010900, 0xffffffff, 0),
-	SYSC_QUIRK("slimbus", 0, 0, 0x10, -1, 0x40000902, 0xffffffff, 0),
-	SYSC_QUIRK("slimbus", 0, 0, 0x10, -1, 0x40002903, 0xffffffff, 0),
-	SYSC_QUIRK("spinlock", 0, 0, 0x10, -1, 0x50020000, 0xffffffff, 0),
-	SYSC_QUIRK("rng", 0, 0x1fe0, 0x1fe4, -1, 0x00000020, 0xffffffff, 0),
-	SYSC_QUIRK("rtc", 0, 0x74, 0x78, -1, 0x4eb01908, 0xffff00f0, 0),
-	SYSC_QUIRK("timer32k", 0, 0, 0x4, -1, 0x00000060, 0xffffffff, 0),
+	SYSC_QUIRK("slimbus", 0, 0, 0x10, -ENODEV, 0x40000902, 0xffffffff, 0),
+	SYSC_QUIRK("slimbus", 0, 0, 0x10, -ENODEV, 0x40002903, 0xffffffff, 0),
+	SYSC_QUIRK("spinlock", 0, 0, 0x10, -ENODEV, 0x50020000, 0xffffffff, 0),
+	SYSC_QUIRK("rng", 0, 0x1fe0, 0x1fe4, -ENODEV, 0x00000020, 0xffffffff, 0),
+	SYSC_QUIRK("timer32k", 0, 0, 0x4, -ENODEV, 0x00000060, 0xffffffff, 0),
+	SYSC_QUIRK("tpcc", 0, 0, -ENODEV, -ENODEV, 0x40014c00, 0xffffffff, 0),
 	SYSC_QUIRK("usbhstll", 0, 0, 0x10, 0x14, 0x00000004, 0xffffffff, 0),
 	SYSC_QUIRK("usbhstll", 0, 0, 0x10, 0x14, 0x00000008, 0xffffffff, 0),
-	SYSC_QUIRK("usb_host_hs", 0, 0, 0x10, 0x14, 0x50700100, 0xffffffff, 0),
-	SYSC_QUIRK("usb_host_hs", 0, 0, 0x10, -1, 0x50700101, 0xffffffff, 0),
-	SYSC_QUIRK("usb_otg_hs", 0, 0x400, 0x404, 0x408, 0x00000050,
-		   0xffffffff, 0),
-	SYSC_QUIRK("vfpe", 0, 0, 0x104, -1, 0x4d001200, 0xffffffff, 0),
+	SYSC_QUIRK("venc", 0x58003000, 0, -ENODEV, -ENODEV, 0x00000002, 0xffffffff, 0),
+	SYSC_QUIRK("vfpe", 0, 0, 0x104, -ENODEV, 0x4d001200, 0xffffffff, 0),
 #endif
 };
 
@@ -1333,16 +1536,13 @@
 		if (q->base != ddata->module_pa)
 			continue;
 
-		if (q->rev_offset >= 0 &&
-		    q->rev_offset != ddata->offsets[SYSC_REVISION])
+		if (q->rev_offset != ddata->offsets[SYSC_REVISION])
 			continue;
 
-		if (q->sysc_offset >= 0 &&
-		    q->sysc_offset != ddata->offsets[SYSC_SYSCONFIG])
+		if (q->sysc_offset != ddata->offsets[SYSC_SYSCONFIG])
 			continue;
 
-		if (q->syss_offset >= 0 &&
-		    q->syss_offset != ddata->offsets[SYSC_SYSSTATUS])
+		if (q->syss_offset != ddata->offsets[SYSC_SYSSTATUS])
 			continue;
 
 		ddata->name = q->name;
@@ -1362,16 +1562,13 @@
 		if (q->base && q->base != ddata->module_pa)
 			continue;
 
-		if (q->rev_offset >= 0 &&
-		    q->rev_offset != ddata->offsets[SYSC_REVISION])
+		if (q->rev_offset != ddata->offsets[SYSC_REVISION])
 			continue;
 
-		if (q->sysc_offset >= 0 &&
-		    q->sysc_offset != ddata->offsets[SYSC_SYSCONFIG])
+		if (q->sysc_offset != ddata->offsets[SYSC_SYSCONFIG])
 			continue;
 
-		if (q->syss_offset >= 0 &&
-		    q->syss_offset != ddata->offsets[SYSC_SYSSTATUS])
+		if (q->syss_offset != ddata->offsets[SYSC_SYSSTATUS])
 			continue;
 
 		if (q->revision == ddata->revision ||
@@ -1384,7 +1581,7 @@
 }
 
 /* 1-wire needs module's internal clocks enabled for reset */
-static void sysc_clk_enable_quirk_hdq1w(struct sysc *ddata)
+static void sysc_pre_reset_quirk_hdq1w(struct sysc *ddata)
 {
 	int offset = 0x0c;	/* HDQ_CTRL_STATUS */
 	u16 val;
@@ -1394,7 +1591,15 @@
 	sysc_write(ddata, offset, val);
 }
 
-/* I2C needs extra enable bit toggling for reset */
+/* AESS (Audio Engine SubSystem) needs autogating set after enable */
+static void sysc_module_enable_quirk_aess(struct sysc *ddata)
+{
+	int offset = 0x7c;	/* AESS_AUTO_GATING_ENABLE */
+
+	sysc_write(ddata, offset, 1);
+}
+
+/* I2C needs to be disabled for reset */
 static void sysc_clk_quirk_i2c(struct sysc *ddata, bool enable)
 {
 	int offset;
@@ -1415,14 +1620,48 @@
 	sysc_write(ddata, offset, val);
 }
 
-static void sysc_clk_enable_quirk_i2c(struct sysc *ddata)
+static void sysc_pre_reset_quirk_i2c(struct sysc *ddata)
+{
+	sysc_clk_quirk_i2c(ddata, false);
+}
+
+static void sysc_post_reset_quirk_i2c(struct sysc *ddata)
 {
 	sysc_clk_quirk_i2c(ddata, true);
 }
 
-static void sysc_clk_disable_quirk_i2c(struct sysc *ddata)
+/* RTC on am3 and 4 needs to be unlocked and locked for sysconfig */
+static void sysc_quirk_rtc(struct sysc *ddata, bool lock)
 {
-	sysc_clk_quirk_i2c(ddata, false);
+	u32 val, kick0_val = 0, kick1_val = 0;
+	unsigned long flags;
+	int error;
+
+	if (!lock) {
+		kick0_val = 0x83e70b13;
+		kick1_val = 0x95a4f1e0;
+	}
+
+	local_irq_save(flags);
+	/* RTC_STATUS BUSY bit may stay active for 1/32768 seconds (~30 usec) */
+	error = readl_poll_timeout_atomic(ddata->module_va + 0x44, val,
+					  !(val & BIT(0)), 100, 50);
+	if (error)
+		dev_warn(ddata->dev, "rtc busy timeout\n");
+	/* Now we have ~15 microseconds to read/write various registers */
+	sysc_write(ddata, 0x6c, kick0_val);
+	sysc_write(ddata, 0x70, kick1_val);
+	local_irq_restore(flags);
+}
+
+static void sysc_module_unlock_quirk_rtc(struct sysc *ddata)
+{
+	sysc_quirk_rtc(ddata, false);
+}
+
+static void sysc_module_lock_quirk_rtc(struct sysc *ddata)
+{
+	sysc_quirk_rtc(ddata, true);
 }
 
 /* 36xx SGX needs a quirk for to bypass OCP IPG interrupt logic */
@@ -1464,14 +1703,24 @@
 		return;
 
 	if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_HDQ1W) {
-		ddata->clk_enable_quirk = sysc_clk_enable_quirk_hdq1w;
+		ddata->pre_reset_quirk = sysc_pre_reset_quirk_hdq1w;
 
 		return;
 	}
 
 	if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_I2C) {
-		ddata->clk_enable_quirk = sysc_clk_enable_quirk_i2c;
-		ddata->clk_disable_quirk = sysc_clk_disable_quirk_i2c;
+		ddata->pre_reset_quirk = sysc_pre_reset_quirk_i2c;
+		ddata->post_reset_quirk = sysc_post_reset_quirk_i2c;
+
+		return;
+	}
+
+	if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_AESS)
+		ddata->module_enable_quirk = sysc_module_enable_quirk_aess;
+
+	if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_RTC_UNLOCK) {
+		ddata->module_unlock_quirk = sysc_module_unlock_quirk_rtc;
+		ddata->module_lock_quirk = sysc_module_lock_quirk_rtc;
 
 		return;
 	}
@@ -1569,46 +1818,39 @@
  */
 static int sysc_reset(struct sysc *ddata)
 {
-	int sysc_offset, syss_offset, sysc_val, rstval, error = 0;
-	u32 sysc_mask, syss_done;
+	int sysc_offset, sysc_val, error;
+	u32 sysc_mask;
 
 	sysc_offset = ddata->offsets[SYSC_SYSCONFIG];
-	syss_offset = ddata->offsets[SYSC_SYSSTATUS];
 
-	if (ddata->legacy_mode || sysc_offset < 0 ||
+	if (ddata->legacy_mode ||
 	    ddata->cap->regbits->srst_shift < 0 ||
 	    ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT)
 		return 0;
 
 	sysc_mask = BIT(ddata->cap->regbits->srst_shift);
 
-	if (ddata->cfg.quirks & SYSS_QUIRK_RESETDONE_INVERTED)
-		syss_done = 0;
-	else
-		syss_done = ddata->cfg.syss_mask;
-
-	if (ddata->clk_disable_quirk)
-		ddata->clk_disable_quirk(ddata);
+	if (ddata->pre_reset_quirk)
+		ddata->pre_reset_quirk(ddata);
 
-	sysc_val = sysc_read_sysconfig(ddata);
-	sysc_val |= sysc_mask;
-	sysc_write(ddata, sysc_offset, sysc_val);
+	if (sysc_offset >= 0) {
+		sysc_val = sysc_read_sysconfig(ddata);
+		sysc_val |= sysc_mask;
+		sysc_write(ddata, sysc_offset, sysc_val);
+		/* Flush posted write */
+		sysc_val = sysc_read_sysconfig(ddata);
+	}
 
-	if (ddata->clk_enable_quirk)
-		ddata->clk_enable_quirk(ddata);
+	if (ddata->cfg.srst_udelay)
+		usleep_range(ddata->cfg.srst_udelay,
+			     ddata->cfg.srst_udelay * 2);
 
-	/* Poll on reset status */
-	if (syss_offset >= 0) {
-		error = readx_poll_timeout(sysc_read_sysstatus, ddata, rstval,
-					   (rstval & ddata->cfg.syss_mask) ==
-					   syss_done,
-					   100, MAX_MODULE_SOFTRESET_WAIT);
+	if (ddata->post_reset_quirk)
+		ddata->post_reset_quirk(ddata);
 
-	} else if (ddata->cfg.quirks & SYSC_QUIRK_RESET_STATUS) {
-		error = readx_poll_timeout(sysc_read_sysconfig, ddata, rstval,
-					   !(rstval & sysc_mask),
-					   100, MAX_MODULE_SOFTRESET_WAIT);
-	}
+	error = sysc_wait_softreset(ddata);
+	if (error)
+		dev_warn(ddata->dev, "OCP softreset timed out\n");
 
 	if (ddata->reset_done_quirk)
 		ddata->reset_done_quirk(ddata);
@@ -2500,7 +2742,9 @@
 	struct sysc *ddata = platform_get_drvdata(pdev);
 	int error;
 
-	cancel_delayed_work_sync(&ddata->idle_work);
+	/* Device can still be enabled, see deferred idle quirk in probe */
+	if (cancel_delayed_work_sync(&ddata->idle_work))
+		ti_sysc_idle(&ddata->idle_work.work);
 
 	error = pm_runtime_get_sync(ddata->dev);
 	if (error < 0) {
@@ -2513,7 +2757,9 @@
 
 	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
-	reset_control_assert(ddata->rsts);
+
+	if (!reset_control_status(ddata->rsts))
+		reset_control_assert(ddata->rsts);
 
 unprepare:
 	sysc_unprepare(ddata);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cdrom/cdrom.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cdrom/cdrom.c
@@ -291,7 +291,7 @@
 /* default compatibility mode */
 static bool autoclose=1;
 static bool autoeject;
-static bool lockdoor = 1;
+static bool lockdoor = 0;
 /* will we ever get to use this... sigh. */
 static bool check_media_type;
 /* automatically restart mrw format */
@@ -996,6 +996,12 @@
 	tracks->xa = 0;
 	tracks->error = 0;
 	cd_dbg(CD_COUNT_TRACKS, "entering cdrom_count_tracks\n");
+
+	if (!CDROM_CAN(CDC_PLAY_AUDIO)) {
+		tracks->error = CDS_NO_INFO;
+		return;
+	}
+
 	/* Grab the TOC header so we can see how many tracks there are */
 	ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCHDR, &header);
 	if (ret) {
@@ -1162,7 +1168,8 @@
 		ret = open_for_data(cdi);
 		if (ret)
 			goto err;
-		cdrom_mmc3_profile(cdi);
+		if (CDROM_CAN(CDC_GENERIC_PACKET))
+			cdrom_mmc3_profile(cdi);
 		if (mode & FMODE_WRITE) {
 			ret = -EROFS;
 			if (cdrom_open_write(cdi))
@@ -2882,6 +2889,9 @@
 	   it doesn't give enough information or fails. then we return
 	   the toc contents. */
 use_toc:
+	if (!CDROM_CAN(CDC_PLAY_AUDIO))
+		return -ENOSYS;
+
 	toc.cdte_format = CDROM_MSF;
 	toc.cdte_track = CDROM_LEADOUT;
 	if ((ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &toc)))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cdrom/gdrom.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cdrom/gdrom.c
@@ -740,6 +740,13 @@
 static int probe_gdrom(struct platform_device *devptr)
 {
 	int err;
+
+	/*
+	 * Ensure our "one" device is initialized properly in case of previous
+	 * usages of it
+	 */
+	memset(&gd, 0, sizeof(gd));
+
 	/* Start the device */
 	if (gdrom_execute_diagnostic() != 1) {
 		pr_warning("ATA Probe for GDROM failed\n");
@@ -828,6 +835,8 @@
 	if (gdrom_major)
 		unregister_blkdev(gdrom_major, GDROM_DEV_NAME);
 	unregister_cdrom(gd.cd_info);
+	kfree(gd.cd_info);
+	kfree(gd.toc);
 
 	return 0;
 }
@@ -843,7 +852,7 @@
 static int __init init_gdrom(void)
 {
 	int rc;
-	gd.toc = NULL;
+
 	rc = platform_driver_register(&gdrom_driver);
 	if (rc)
 		return rc;
@@ -859,8 +868,6 @@
 {
 	platform_device_unregister(pd);
 	platform_driver_unregister(&gdrom_driver);
-	kfree(gd.toc);
-	kfree(gd.cd_info);
 }
 
 module_init(init_gdrom);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/Kconfig
@@ -535,28 +535,41 @@
 	  and SSM (Silicon Secured Memory).  Intended consumers of this
 	  driver include crash and makedumpfile.
 
-endmenu
-
 config RANDOM_TRUST_CPU
-	bool "Trust the CPU manufacturer to initialize Linux's CRNG"
-	depends on X86 || S390 || PPC
-	default n
+	bool "Initialize RNG using CPU RNG instructions"
+	default y
+	depends on ARCH_RANDOM
 	help
-	Assume that CPU manufacturer (e.g., Intel or AMD for RDSEED or
-	RDRAND, IBM for the S390 and Power PC architectures) is trustworthy
-	for the purposes of initializing Linux's CRNG.  Since this is not
-	something that can be independently audited, this amounts to trusting
-	that CPU manufacturer (perhaps with the insistence or mandate
-	of a Nation State's intelligence or law enforcement agencies)
-	has not installed a hidden back door to compromise the CPU's
-	random number generation facilities. This can also be configured
-	at boot with "random.trust_cpu=on/off".
+	  Initialize the RNG using random numbers supplied by the CPU's
+	  RNG instructions (e.g. RDRAND), if supported and available. These
+	  random numbers are never used directly, but are rather hashed into
+	  the main input pool, and this happens regardless of whether or not
+	  this option is enabled. Instead, this option controls whether the
+	  they are credited and hence can initialize the RNG. Additionally,
+	  other sources of randomness are always used, regardless of this
+	  setting.  Enabling this implies trusting that the CPU can supply high
+	  quality and non-backdoored random numbers.
+
+	  Say Y here unless you have reason to mistrust your CPU or believe
+	  its RNG facilities may be faulty. This may also be configured at
+	  boot time with "random.trust_cpu=on/off".
 
 config RANDOM_TRUST_BOOTLOADER
-	bool "Trust the bootloader to initialize Linux's CRNG"
+	bool "Initialize RNG using bootloader-supplied seed"
+	default y
 	help
-	Some bootloaders can provide entropy to increase the kernel's initial
-	device randomness. Say Y here to assume the entropy provided by the
-	booloader is trustworthy so it will be added to the kernel's entropy
-	pool. Otherwise, say N here so it will be regarded as device input that
-	only mixes the entropy pool.
\ No newline at end of file
+	  Initialize the RNG using a seed supplied by the bootloader or boot
+	  environment (e.g. EFI or a bootloader-generated device tree). This
+	  seed is not used directly, but is rather hashed into the main input
+	  pool, and this happens regardless of whether or not this option is
+	  enabled. Instead, this option controls whether the seed is credited
+	  and hence can initialize the RNG. Additionally, other sources of
+	  randomness are always used, regardless of this setting. Enabling
+	  this implies trusting that the bootloader can supply high quality and
+	  non-backdoored seeds.
+
+	  Say Y here unless you have reason to mistrust your bootloader or
+	  believe its RNG facilities may be faulty. This may also be configured
+	  at boot time with "random.trust_bootloader=on/off".
+
+endmenu
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/agp/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/agp/Kconfig
@@ -125,7 +125,7 @@
 
 config AGP_PARISC
 	tristate "HP Quicksilver AGP support"
-	depends on AGP && PARISC && 64BIT
+	depends on AGP && PARISC && 64BIT && IOMMU_SBA
 	help
 	  This option gives you AGP GART support for the HP Quicksilver
 	  AGP bus adapter on HP PA-RISC machines (Ok, just on the C8000
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/agp/intel-gtt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/agp/intel-gtt.c
@@ -304,8 +304,10 @@
 	if (intel_private.needs_dmar) {
 		dma_addr = pci_map_page(intel_private.pcidev, page, 0,
 				    PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
-		if (pci_dma_mapping_error(intel_private.pcidev, dma_addr))
+		if (pci_dma_mapping_error(intel_private.pcidev, dma_addr)) {
+			__free_page(page);
 			return -EINVAL;
+		}
 
 		intel_private.scratch_page_dma = dma_addr;
 	} else
@@ -846,6 +848,7 @@
 			   unsigned int flags)
 {
 	intel_private.driver->write_entry(addr, pg, flags);
+	readl(intel_private.gtt + pg);
 	if (intel_private.driver->chipset_flush)
 		intel_private.driver->chipset_flush();
 }
@@ -871,7 +874,7 @@
 			j++;
 		}
 	}
-	wmb();
+	readl(intel_private.gtt + j - 1);
 	if (intel_private.driver->chipset_flush)
 		intel_private.driver->chipset_flush();
 }
@@ -1105,6 +1108,7 @@
 
 static void i9xx_chipset_flush(void)
 {
+	wmb();
 	if (intel_private.i9xx_flush_page)
 		writel(1, intel_private.i9xx_flush_page);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/agp/parisc-agp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/agp/parisc-agp.c
@@ -90,6 +90,9 @@
 {
 	struct _parisc_agp_info *info = &parisc_agp_info;
 
+	/* force fdc ops to be visible to IOMMU */
+	asm_io_sync();
+
 	writeq(info->gart_base | ilog2(info->gart_size), info->ioc_regs+IOC_PCOM);
 	readq(info->ioc_regs+IOC_PCOM);	/* flush */
 }
@@ -158,6 +161,7 @@
 			info->gatt[j] =
 				parisc_agp_mask_memory(agp_bridge,
 					paddr, type);
+			asm_io_fdc(&info->gatt[j]);
 		}
 	}
 
@@ -191,7 +195,16 @@
 parisc_agp_mask_memory(struct agp_bridge_data *bridge, dma_addr_t addr,
 		       int type)
 {
-	return SBA_PDIR_VALID_BIT | addr;
+	unsigned ci;			/* coherent index */
+	dma_addr_t pa;
+
+	pa = addr & IOVP_MASK;
+	asm("lci 0(%1), %0" : "=r" (ci) : "r" (phys_to_virt(pa)));
+
+	pa |= (ci >> PAGE_SHIFT) & 0xff;/* move CI (8 bits) into lowest byte */
+	pa |= SBA_PDIR_VALID_BIT;	/* set "valid" bit */
+
+	return cpu_to_le64(pa);
 }
 
 static void
@@ -281,7 +294,7 @@
         return 0;
 }
 
-static int
+static int __init
 lba_find_capability(int cap)
 {
 	struct _parisc_agp_info *info = &parisc_agp_info;
@@ -366,7 +379,7 @@
 	return error;
 }
 
-static int
+static int __init
 find_quicksilver(struct device *dev, void *data)
 {
 	struct parisc_device **lba = data;
@@ -378,11 +391,9 @@
 	return 0;
 }
 
-static int
+static int __init
 parisc_agp_init(void)
 {
-	extern struct sba_device *sba_list;
-
 	int err = -1;
 	struct parisc_device *sba = NULL, *lba = NULL;
 	struct lba_device *lbadev = NULL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/hpet.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/hpet.c
@@ -304,8 +304,13 @@
 	if (!devp->hd_ireqfreq)
 		return -EIO;
 
-	if (count < sizeof(unsigned long))
-		return -EINVAL;
+	if (in_compat_syscall()) {
+		if (count < sizeof(compat_ulong_t))
+			return -EINVAL;
+	} else {
+		if (count < sizeof(unsigned long))
+			return -EINVAL;
+	}
 
 	add_wait_queue(&devp->hd_waitqueue, &wait);
 
@@ -329,9 +334,16 @@
 		schedule();
 	}
 
-	retval = put_user(data, (unsigned long __user *)buf);
-	if (!retval)
-		retval = sizeof(unsigned long);
+	if (in_compat_syscall()) {
+		retval = put_user(data, (compat_ulong_t __user *)buf);
+		if (!retval)
+			retval = sizeof(compat_ulong_t);
+	} else {
+		retval = put_user(data, (unsigned long __user *)buf);
+		if (!retval)
+			retval = sizeof(unsigned long);
+	}
+
 out:
 	__set_current_state(TASK_RUNNING);
 	remove_wait_queue(&devp->hd_waitqueue, &wait);
@@ -686,12 +698,24 @@
 	unsigned short hi_timer;
 };
 
+/* 32-bit types would lead to different command codes which should be
+ * translated into 64-bit ones before passed to hpet_ioctl_common
+ */
+#define COMPAT_HPET_INFO       _IOR('h', 0x03, struct compat_hpet_info)
+#define COMPAT_HPET_IRQFREQ    _IOW('h', 0x6, compat_ulong_t)
+
 static long
 hpet_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	struct hpet_info info;
 	int err;
 
+	if (cmd == COMPAT_HPET_INFO)
+		cmd = HPET_INFO;
+
+	if (cmd == COMPAT_HPET_IRQFREQ)
+		cmd = HPET_IRQFREQ;
+
 	mutex_lock(&hpet_mutex);
 	err = hpet_ioctl_common(file->private_data, cmd, arg, &info);
 	mutex_unlock(&hpet_mutex);
@@ -855,7 +879,7 @@
 		return 0;
 	}
 
-	hpetp = kzalloc(struct_size(hpetp, hp_dev, hdp->hd_nirqs - 1),
+	hpetp = kzalloc(struct_size(hpetp, hp_dev, hdp->hd_nirqs),
 			GFP_KERNEL);
 
 	if (!hpetp)
@@ -984,6 +1008,8 @@
 		hdp->hd_phys_address = fixmem32->address;
 		hdp->hd_address = ioremap(fixmem32->address,
 						HPET_RANGE_SIZE);
+		if (!hdp->hd_address)
+			return AE_ERROR;
 
 		if (hpet_is_known(hdp)) {
 			iounmap(hdp->hd_address);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/hw_random/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/hw_random/Kconfig
@@ -308,6 +308,19 @@
 
 	  If unsure, say Y.
 
+config HW_RANDOM_HISI_V2
+	tristate "HiSilicon True Random Number Generator V2 support"
+	depends on HW_RANDOM && ARM64 && ACPI
+	default HW_RANDOM
+	help
+	  This driver provides kernel-side support for the True Random Number
+	  Generator V2 hardware found on HiSilicon Hi1620 SoC.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called hisi-trng-v2.
+
+	  If unsure, say Y.
+
 config HW_RANDOM_ST
 	tristate "ST Microelectronics HW Random Number Generator support"
 	depends on HW_RANDOM && ARCH_STI
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/hw_random/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/hw_random/Makefile
@@ -27,6 +27,7 @@
 obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o
 obj-$(CONFIG_HW_RANDOM_POWERNV) += powernv-rng.o
 obj-$(CONFIG_HW_RANDOM_HISI)	+= hisi-rng.o
+obj-$(CONFIG_HW_RANDOM_HISI_V2) += hisi-trng-v2.o
 obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o
 obj-$(CONFIG_HW_RANDOM_IPROC_RNG200) += iproc-rng200.o
 obj-$(CONFIG_HW_RANDOM_ST) += st-rng.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/hw_random/amd-rng.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/hw_random/amd-rng.c
@@ -142,16 +142,22 @@
 
 found:
 	err = pci_read_config_dword(pdev, 0x58, &pmbase);
-	if (err)
-		return err;
+	if (err) {
+		err = pcibios_err_to_errno(err);
+		goto put_dev;
+	}
 
 	pmbase &= 0x0000FF00;
-	if (pmbase == 0)
-		return -EIO;
+	if (pmbase == 0) {
+		err = -EIO;
+		goto put_dev;
+	}
 
 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-	if (!priv)
-		return -ENOMEM;
+	if (!priv) {
+		err = -ENOMEM;
+		goto put_dev;
+	}
 
 	if (!request_region(pmbase + PMBASE_OFFSET, PMBASE_SIZE, DRV_NAME)) {
 		dev_err(&pdev->dev, DRV_NAME " region 0x%x already in use!\n",
@@ -185,6 +191,8 @@
 	release_region(pmbase + PMBASE_OFFSET, PMBASE_SIZE);
 out:
 	kfree(priv);
+put_dev:
+	pci_dev_put(pdev);
 	return err;
 }
 
@@ -200,6 +208,8 @@
 
 	release_region(priv->pmbase + PMBASE_OFFSET, PMBASE_SIZE);
 
+	pci_dev_put(priv->pcidev);
+
 	kfree(priv);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/hw_random/atmel-rng.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/hw_random/atmel-rng.c
@@ -96,6 +96,7 @@
 
 err_register:
 	clk_disable_unprepare(trng->clk);
+	atmel_trng_disable(trng);
 	return ret;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/hw_random/core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/hw_random/core.c
@@ -15,6 +15,7 @@
 #include <linux/err.h>
 #include <linux/fs.h>
 #include <linux/hw_random.h>
+#include <linux/random.h>
 #include <linux/kernel.h>
 #include <linux/kthread.h>
 #include <linux/sched/signal.h>
@@ -23,10 +24,13 @@
 #include <linux/random.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
+#include <linux/string.h>
 #include <linux/uaccess.h>
 
 #define RNG_MODULE_NAME		"hw_random"
 
+#define RNG_BUFFER_SIZE (SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES)
+
 static struct hwrng *current_rng;
 /* the current rng has been explicitly chosen by user via sysfs */
 static int cur_rng_set_by_user;
@@ -58,7 +62,7 @@
 
 static size_t rng_buffer_size(void)
 {
-	return SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES;
+	return RNG_BUFFER_SIZE;
 }
 
 static void add_early_randomness(struct hwrng *rng)
@@ -201,6 +205,7 @@
 static ssize_t rng_dev_read(struct file *filp, char __user *buf,
 			    size_t size, loff_t *offp)
 {
+	u8 buffer[RNG_BUFFER_SIZE];
 	ssize_t ret = 0;
 	int err = 0;
 	int bytes_read, len;
@@ -228,34 +233,37 @@
 			if (bytes_read < 0) {
 				err = bytes_read;
 				goto out_unlock_reading;
+			} else if (bytes_read == 0 &&
+				   (filp->f_flags & O_NONBLOCK)) {
+				err = -EAGAIN;
+				goto out_unlock_reading;
 			}
+
 			data_avail = bytes_read;
 		}
 
-		if (!data_avail) {
-			if (filp->f_flags & O_NONBLOCK) {
-				err = -EAGAIN;
-				goto out_unlock_reading;
-			}
-		} else {
-			len = data_avail;
+		len = data_avail;
+		if (len) {
 			if (len > size)
 				len = size;
 
 			data_avail -= len;
 
-			if (copy_to_user(buf + ret, rng_buffer + data_avail,
-								len)) {
+			memcpy(buffer, rng_buffer + data_avail, len);
+		}
+		mutex_unlock(&reading_mutex);
+		put_rng(rng);
+
+		if (len) {
+			if (copy_to_user(buf + ret, buffer, len)) {
 				err = -EFAULT;
-				goto out_unlock_reading;
+				goto out;
 			}
 
 			size -= len;
 			ret += len;
 		}
 
-		mutex_unlock(&reading_mutex);
-		put_rng(rng);
 
 		if (need_resched())
 			schedule_timeout_interruptible(1);
@@ -266,6 +274,7 @@
 		}
 	}
 out:
+	memzero_explicit(buffer, sizeof(buffer));
 	return ret ? : err;
 
 out_unlock_reading:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/hw_random/exynos-trng.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/hw_random/exynos-trng.c
@@ -134,7 +134,7 @@
 		return PTR_ERR(trng->mem);
 
 	pm_runtime_enable(&pdev->dev);
-	ret = pm_runtime_get_sync(&pdev->dev);
+	ret = pm_runtime_resume_and_get(&pdev->dev);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "Could not get runtime PM.\n");
 		goto err_pm_get;
@@ -167,7 +167,7 @@
 	clk_disable_unprepare(trng->clk);
 
 err_clock:
-	pm_runtime_put_sync(&pdev->dev);
+	pm_runtime_put_noidle(&pdev->dev);
 
 err_pm_get:
 	pm_runtime_disable(&pdev->dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/hw_random/geode-rng.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/hw_random/geode-rng.c
@@ -51,10 +51,15 @@
 };
 MODULE_DEVICE_TABLE(pci, pci_tbl);
 
+struct amd_geode_priv {
+	struct pci_dev *pcidev;
+	void __iomem *membase;
+};
 
 static int geode_rng_data_read(struct hwrng *rng, u32 *data)
 {
-	void __iomem *mem = (void __iomem *)rng->priv;
+	struct amd_geode_priv *priv = (struct amd_geode_priv *)rng->priv;
+	void __iomem *mem = priv->membase;
 
 	*data = readl(mem + GEODE_RNG_DATA_REG);
 
@@ -63,7 +68,8 @@
 
 static int geode_rng_data_present(struct hwrng *rng, int wait)
 {
-	void __iomem *mem = (void __iomem *)rng->priv;
+	struct amd_geode_priv *priv = (struct amd_geode_priv *)rng->priv;
+	void __iomem *mem = priv->membase;
 	int data, i;
 
 	for (i = 0; i < 20; i++) {
@@ -90,6 +96,7 @@
 	const struct pci_device_id *ent;
 	void __iomem *mem;
 	unsigned long rng_base;
+	struct amd_geode_priv *priv;
 
 	for_each_pci_dev(pdev) {
 		ent = pci_match_id(pci_tbl, pdev);
@@ -97,17 +104,26 @@
 			goto found;
 	}
 	/* Device not found. */
-	goto out;
+	return err;
 
 found:
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		err = -ENOMEM;
+		goto put_dev;
+	}
+
 	rng_base = pci_resource_start(pdev, 0);
 	if (rng_base == 0)
-		goto out;
+		goto free_priv;
 	err = -ENOMEM;
 	mem = ioremap(rng_base, 0x58);
 	if (!mem)
-		goto out;
-	geode_rng.priv = (unsigned long)mem;
+		goto free_priv;
+
+	geode_rng.priv = (unsigned long)priv;
+	priv->membase = mem;
+	priv->pcidev = pdev;
 
 	pr_info("AMD Geode RNG detected\n");
 	err = hwrng_register(&geode_rng);
@@ -116,20 +132,26 @@
 		       err);
 		goto err_unmap;
 	}
-out:
 	return err;
 
 err_unmap:
 	iounmap(mem);
-	goto out;
+free_priv:
+	kfree(priv);
+put_dev:
+	pci_dev_put(pdev);
+	return err;
 }
 
 static void __exit mod_exit(void)
 {
-	void __iomem *mem = (void __iomem *)geode_rng.priv;
+	struct amd_geode_priv *priv;
 
+	priv = (struct amd_geode_priv *)geode_rng.priv;
 	hwrng_unregister(&geode_rng);
-	iounmap(mem);
+	iounmap(priv->membase);
+	pci_dev_put(priv->pcidev);
+	kfree(priv);
 }
 
 module_init(mod_init);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/hw_random/hisi-trng-v2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/hw_random/hisi-trng-v2.c
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2019 HiSilicon Limited. */
+
+#include <linux/acpi.h>
+#include <linux/err.h>
+#include <linux/hw_random.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/random.h>
+
+#define HISI_TRNG_REG		0x00F0
+#define HISI_TRNG_BYTES		4
+#define HISI_TRNG_QUALITY	512
+#define SLEEP_US		10
+#define TIMEOUT_US		10000
+
+struct hisi_trng {
+	void __iomem *base;
+	struct hwrng rng;
+};
+
+static int hisi_trng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
+{
+	struct hisi_trng *trng;
+	int currsize = 0;
+	u32 val = 0;
+	u32 ret;
+
+	trng = container_of(rng, struct hisi_trng, rng);
+
+	do {
+		ret = readl_poll_timeout(trng->base + HISI_TRNG_REG, val,
+					 val, SLEEP_US, TIMEOUT_US);
+		if (ret)
+			return currsize;
+
+		if (max - currsize >= HISI_TRNG_BYTES) {
+			memcpy(buf + currsize, &val, HISI_TRNG_BYTES);
+			currsize += HISI_TRNG_BYTES;
+			if (currsize == max)
+				return currsize;
+			continue;
+		}
+
+		/* copy remaining bytes */
+		memcpy(buf + currsize, &val, max - currsize);
+		currsize = max;
+	} while (currsize < max);
+
+	return currsize;
+}
+
+static int hisi_trng_probe(struct platform_device *pdev)
+{
+	struct hisi_trng *trng;
+	int ret;
+
+	trng = devm_kzalloc(&pdev->dev, sizeof(*trng), GFP_KERNEL);
+	if (!trng)
+		return -ENOMEM;
+
+	trng->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(trng->base))
+		return PTR_ERR(trng->base);
+
+	trng->rng.name = pdev->name;
+	trng->rng.read = hisi_trng_read;
+	trng->rng.quality = HISI_TRNG_QUALITY;
+
+	ret = devm_hwrng_register(&pdev->dev, &trng->rng);
+	if (ret)
+		dev_err(&pdev->dev, "failed to register hwrng!\n");
+
+	return ret;
+}
+
+static const struct acpi_device_id hisi_trng_acpi_match[] = {
+	{ "HISI02B3", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(acpi, hisi_trng_acpi_match);
+
+static struct platform_driver hisi_trng_driver = {
+	.probe		= hisi_trng_probe,
+	.driver		= {
+		.name	= "hisi-trng-v2",
+		.acpi_match_table = ACPI_PTR(hisi_trng_acpi_match),
+	},
+};
+
+module_platform_driver(hisi_trng_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Weili Qian <qianweili@huawei.com>");
+MODULE_AUTHOR("Zaibo Xu <xuzaibo@huawei.com>");
+MODULE_DESCRIPTION("HiSilicon true random number generator V2 driver");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/hw_random/imx-rngc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/hw_random/imx-rngc.c
@@ -99,14 +99,16 @@
 	cmd = readl(rngc->base + RNGC_COMMAND);
 	writel(cmd | RNGC_CMD_SELF_TEST, rngc->base + RNGC_COMMAND);
 
-	ret = wait_for_completion_timeout(&rngc->rng_op_done, RNGC_TIMEOUT);
+	ret = wait_for_completion_timeout(&rngc->rng_op_done, msecs_to_jiffies(RNGC_TIMEOUT));
 	if (!ret) {
 		imx_rngc_irq_mask_clear(rngc);
 		return -ETIMEDOUT;
 	}
 
-	if (rngc->err_reg != 0)
+	if (rngc->err_reg != 0) {
+		imx_rngc_irq_mask_clear(rngc);
 		return -EIO;
+	}
 
 	return 0;
 }
@@ -180,9 +182,7 @@
 		cmd = readl(rngc->base + RNGC_COMMAND);
 		writel(cmd | RNGC_CMD_SEED, rngc->base + RNGC_COMMAND);
 
-		ret = wait_for_completion_timeout(&rngc->rng_op_done,
-				RNGC_TIMEOUT);
-
+		ret = wait_for_completion_timeout(&rngc->rng_op_done, msecs_to_jiffies(RNGC_TIMEOUT));
 		if (!ret) {
 			imx_rngc_irq_mask_clear(rngc);
 			return -ETIMEDOUT;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/hw_random/iproc-rng200.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/hw_random/iproc-rng200.c
@@ -202,10 +202,12 @@
 		return PTR_ERR(priv->base);
 	}
 
-	priv->rng.name = "iproc-rng200",
-	priv->rng.read = iproc_rng200_read,
-	priv->rng.init = iproc_rng200_init,
-	priv->rng.cleanup = iproc_rng200_cleanup,
+	dev_set_drvdata(dev, priv);
+
+	priv->rng.name = "iproc-rng200";
+	priv->rng.read = iproc_rng200_read;
+	priv->rng.init = iproc_rng200_init;
+	priv->rng.cleanup = iproc_rng200_cleanup;
 
 	/* Register driver */
 	ret = devm_hwrng_register(dev, &priv->rng);
@@ -219,6 +221,28 @@
 	return 0;
 }
 
+static int __maybe_unused iproc_rng200_suspend(struct device *dev)
+{
+	struct iproc_rng200_dev *priv = dev_get_drvdata(dev);
+
+	iproc_rng200_cleanup(&priv->rng);
+
+	return 0;
+}
+
+static int __maybe_unused iproc_rng200_resume(struct device *dev)
+{
+	struct iproc_rng200_dev *priv =  dev_get_drvdata(dev);
+
+	iproc_rng200_init(&priv->rng);
+
+	return 0;
+}
+
+static const struct dev_pm_ops iproc_rng200_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(iproc_rng200_suspend, iproc_rng200_resume)
+};
+
 static const struct of_device_id iproc_rng200_of_match[] = {
 	{ .compatible = "brcm,bcm7211-rng200", },
 	{ .compatible = "brcm,bcm7278-rng200", },
@@ -231,6 +255,7 @@
 	.driver = {
 		.name		= "iproc-rng200",
 		.of_match_table = iproc_rng200_of_match,
+		.pm		= &iproc_rng200_pm_ops,
 	},
 	.probe		= iproc_rng200_probe,
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/hw_random/ks-sa-rng.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/hw_random/ks-sa-rng.c
@@ -208,6 +208,7 @@
 	ret = pm_runtime_get_sync(dev);
 	if (ret < 0) {
 		dev_err(dev, "Failed to enable SA power-domain\n");
+		pm_runtime_put_noidle(dev);
 		pm_runtime_disable(dev);
 		return ret;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/hw_random/mtk-rng.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/hw_random/mtk-rng.c
@@ -149,7 +149,7 @@
 	dev_set_drvdata(&pdev->dev, priv);
 	pm_runtime_set_autosuspend_delay(&pdev->dev, RNG_AUTOSUSPEND_TIMEOUT);
 	pm_runtime_use_autosuspend(&pdev->dev);
-	pm_runtime_enable(&pdev->dev);
+	devm_pm_runtime_enable(&pdev->dev);
 
 	dev_info(&pdev->dev, "registered RNG driver\n");
 
@@ -173,8 +173,13 @@
 	return mtk_rng_init(&priv->rng);
 }
 
-static UNIVERSAL_DEV_PM_OPS(mtk_rng_pm_ops, mtk_rng_runtime_suspend,
-			    mtk_rng_runtime_resume, NULL);
+static const struct dev_pm_ops mtk_rng_pm_ops = {
+	SET_RUNTIME_PM_OPS(mtk_rng_runtime_suspend,
+			   mtk_rng_runtime_resume, NULL)
+	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+				pm_runtime_force_resume)
+};
+
 #define MTK_RNG_PM_OPS (&mtk_rng_pm_ops)
 #else	/* CONFIG_PM */
 #define MTK_RNG_PM_OPS NULL
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/hw_random/omap-rng.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/hw_random/omap-rng.c
@@ -66,6 +66,13 @@
 #define OMAP4_RNG_OUTPUT_SIZE			0x8
 #define EIP76_RNG_OUTPUT_SIZE			0x10
 
+/*
+ * EIP76 RNG takes approx. 700us to produce 16 bytes of output data
+ * as per testing results. And to account for the lack of udelay()'s
+ * reliability, we keep the timeout as 1000us.
+ */
+#define RNG_DATA_FILL_TIMEOUT			100
+
 enum {
 	RNG_OUTPUT_0_REG = 0,
 	RNG_OUTPUT_1_REG,
@@ -176,7 +183,7 @@
 	if (max < priv->pdata->data_size)
 		return 0;
 
-	for (i = 0; i < 20; i++) {
+	for (i = 0; i < RNG_DATA_FILL_TIMEOUT; i++) {
 		present = priv->pdata->data_present(priv);
 		if (present || !wait)
 			break;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/hw_random/omap3-rom-rng.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/hw_random/omap3-rom-rng.c
@@ -20,6 +20,8 @@
 #include <linux/workqueue.h>
 #include <linux/clk.h>
 #include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 
 #define RNG_RESET			0x01
@@ -86,14 +88,18 @@
 
 static struct hwrng omap3_rom_rng_ops = {
 	.name		= "omap3-rom",
-	.read		= omap3_rom_rng_read,
 };
 
 static int omap3_rom_rng_probe(struct platform_device *pdev)
 {
 	int ret = 0;
 
-	pr_info("initializing\n");
+	omap3_rom_rng_ops.read = of_device_get_match_data(&pdev->dev);
+	if (!omap3_rom_rng_ops.read) {
+		dev_err(&pdev->dev, "missing rom code handler\n");
+
+		return -ENODEV;
+	}
 
 	omap3_rom_rng_call = pdev->dev.platform_data;
 	if (!omap3_rom_rng_call) {
@@ -121,13 +127,21 @@
 {
 	cancel_delayed_work_sync(&idle_work);
 	hwrng_unregister(&omap3_rom_rng_ops);
-	clk_disable_unprepare(rng_clk);
+	if (!rng_idle)
+		clk_disable_unprepare(rng_clk);
 	return 0;
 }
 
+static const struct of_device_id omap_rom_rng_match[] = {
+	{ .compatible = "nokia,n900-rom-rng", .data = omap3_rom_rng_read, },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, omap_rom_rng_match);
+
 static struct platform_driver omap3_rom_rng_driver = {
 	.driver = {
 		.name		= "omap3-rom-rng",
+		.of_match_table = omap_rom_rng_match,
 	},
 	.probe		= omap3_rom_rng_probe,
 	.remove		= omap3_rom_rng_remove,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/hw_random/st-rng.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/hw_random/st-rng.c
@@ -12,6 +12,7 @@
 #include <linux/delay.h>
 #include <linux/hw_random.h>
 #include <linux/io.h>
+#include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
@@ -41,7 +42,6 @@
 
 struct st_rng_data {
 	void __iomem	*base;
-	struct clk	*clk;
 	struct hwrng	ops;
 };
 
@@ -86,26 +86,18 @@
 	if (IS_ERR(base))
 		return PTR_ERR(base);
 
-	clk = devm_clk_get(&pdev->dev, NULL);
+	clk = devm_clk_get_enabled(&pdev->dev, NULL);
 	if (IS_ERR(clk))
 		return PTR_ERR(clk);
 
-	ret = clk_prepare_enable(clk);
-	if (ret)
-		return ret;
-
 	ddata->ops.priv	= (unsigned long)ddata;
 	ddata->ops.read	= st_rng_read;
 	ddata->ops.name	= pdev->name;
 	ddata->base	= base;
-	ddata->clk	= clk;
-
-	dev_set_drvdata(&pdev->dev, ddata);
 
 	ret = devm_hwrng_register(&pdev->dev, &ddata->ops);
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to register HW RNG\n");
-		clk_disable_unprepare(clk);
 		return ret;
 	}
 
@@ -114,16 +106,7 @@
 	return 0;
 }
 
-static int st_rng_remove(struct platform_device *pdev)
-{
-	struct st_rng_data *ddata = dev_get_drvdata(&pdev->dev);
-
-	clk_disable_unprepare(ddata->clk);
-
-	return 0;
-}
-
-static const struct of_device_id st_rng_match[] = {
+static const struct of_device_id st_rng_match[] __maybe_unused = {
 	{ .compatible = "st,rng" },
 	{},
 };
@@ -135,7 +118,6 @@
 		.of_match_table = of_match_ptr(st_rng_match),
 	},
 	.probe = st_rng_probe,
-	.remove = st_rng_remove
 };
 
 module_platform_driver(st_rng_driver);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/hw_random/timeriomem-rng.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/hw_random/timeriomem-rng.c
@@ -69,7 +69,7 @@
 		 */
 		if (retval > 0)
 			usleep_range(period_us,
-					period_us + min(1, period_us / 100));
+					period_us + max(1, period_us / 100));
 
 		*(u32 *)data = readl(priv->io_base);
 		retval += sizeof(u32);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/hw_random/virtio-rng.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/hw_random/virtio-rng.c
@@ -4,6 +4,7 @@
  *  Copyright (C) 2007, 2008 Rusty Russell IBM Corporation
  */
 
+#include <asm/barrier.h>
 #include <linux/err.h>
 #include <linux/hw_random.h>
 #include <linux/scatterlist.h>
@@ -17,71 +18,111 @@
 struct virtrng_info {
 	struct hwrng hwrng;
 	struct virtqueue *vq;
-	struct completion have_data;
 	char name[25];
-	unsigned int data_avail;
 	int index;
-	bool busy;
 	bool hwrng_register_done;
 	bool hwrng_removed;
+	/* data transfer */
+	struct completion have_data;
+	unsigned int data_avail;
+	unsigned int data_idx;
+	/* minimal size returned by rng_buffer_size() */
+#if SMP_CACHE_BYTES < 32
+	u8 data[32];
+#else
+	u8 data[SMP_CACHE_BYTES];
+#endif
 };
 
 static void random_recv_done(struct virtqueue *vq)
 {
 	struct virtrng_info *vi = vq->vdev->priv;
+	unsigned int len;
 
 	/* We can get spurious callbacks, e.g. shared IRQs + virtio_pci. */
-	if (!virtqueue_get_buf(vi->vq, &vi->data_avail))
+	if (!virtqueue_get_buf(vi->vq, &len))
 		return;
 
+	smp_store_release(&vi->data_avail, len);
 	complete(&vi->have_data);
 }
 
-/* The host will fill any buffer we give it with sweet, sweet randomness. */
-static void register_buffer(struct virtrng_info *vi, u8 *buf, size_t size)
+static void request_entropy(struct virtrng_info *vi)
 {
 	struct scatterlist sg;
 
-	sg_init_one(&sg, buf, size);
+	reinit_completion(&vi->have_data);
+	vi->data_idx = 0;
+
+	sg_init_one(&sg, vi->data, sizeof(vi->data));
 
 	/* There should always be room for one buffer. */
-	virtqueue_add_inbuf(vi->vq, &sg, 1, buf, GFP_KERNEL);
+	virtqueue_add_inbuf(vi->vq, &sg, 1, vi->data, GFP_KERNEL);
 
 	virtqueue_kick(vi->vq);
 }
 
+static unsigned int copy_data(struct virtrng_info *vi, void *buf,
+			      unsigned int size)
+{
+	size = min_t(unsigned int, size, vi->data_avail);
+	memcpy(buf, vi->data + vi->data_idx, size);
+	vi->data_idx += size;
+	vi->data_avail -= size;
+	if (vi->data_avail == 0)
+		request_entropy(vi);
+	return size;
+}
+
 static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait)
 {
 	int ret;
 	struct virtrng_info *vi = (struct virtrng_info *)rng->priv;
+	unsigned int chunk;
+	size_t read;
 
 	if (vi->hwrng_removed)
 		return -ENODEV;
 
-	if (!vi->busy) {
-		vi->busy = true;
-		reinit_completion(&vi->have_data);
-		register_buffer(vi, buf, size);
+	read = 0;
+
+	/* copy available data */
+	if (smp_load_acquire(&vi->data_avail)) {
+		chunk = copy_data(vi, buf, size);
+		size -= chunk;
+		read += chunk;
 	}
 
 	if (!wait)
-		return 0;
-
-	ret = wait_for_completion_killable(&vi->have_data);
-	if (ret < 0)
-		return ret;
+		return read;
 
-	vi->busy = false;
+	/* We have already copied available entropy,
+	 * so either size is 0 or data_avail is 0
+	 */
+	while (size != 0) {
+		/* data_avail is 0 but a request is pending */
+		ret = wait_for_completion_killable(&vi->have_data);
+		if (ret < 0)
+			return ret;
+		/* if vi->data_avail is 0, we have been interrupted
+		 * by a cleanup, but buffer stays in the queue
+		 */
+		if (vi->data_avail == 0)
+			return read;
+
+		chunk = copy_data(vi, buf + read, size);
+		size -= chunk;
+		read += chunk;
+	}
 
-	return vi->data_avail;
+	return read;
 }
 
 static void virtio_cleanup(struct hwrng *rng)
 {
 	struct virtrng_info *vi = (struct virtrng_info *)rng->priv;
 
-	if (vi->busy)
-		wait_for_completion(&vi->have_data);
+	complete(&vi->have_data);
 }
 
 static int probe_common(struct virtio_device *vdev)
@@ -117,6 +158,9 @@
 		goto err_find;
 	}
 
+	/* we always have a pending entropy request */
+	request_entropy(vi);
+
 	return 0;
 
 err_find:
@@ -132,9 +176,9 @@
 
 	vi->hwrng_removed = true;
 	vi->data_avail = 0;
+	vi->data_idx = 0;
 	complete(&vi->have_data);
 	vdev->config->reset(vdev);
-	vi->busy = false;
 	if (vi->hwrng_register_done)
 		hwrng_unregister(&vi->hwrng);
 	vdev->config->del_vqs(vdev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/ipmi/bt-bmc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/ipmi/bt-bmc.c
@@ -399,15 +399,15 @@
 	struct device *dev = &pdev->dev;
 	int rc;
 
-	bt_bmc->irq = platform_get_irq(pdev, 0);
-	if (!bt_bmc->irq)
-		return -ENODEV;
+	bt_bmc->irq = platform_get_irq_optional(pdev, 0);
+	if (bt_bmc->irq < 0)
+		return bt_bmc->irq;
 
 	rc = devm_request_irq(dev, bt_bmc->irq, bt_bmc_irq, IRQF_SHARED,
 			      DEVICE_NAME, bt_bmc);
 	if (rc < 0) {
 		dev_warn(dev, "Unable to request IRQ %d\n", bt_bmc->irq);
-		bt_bmc->irq = 0;
+		bt_bmc->irq = rc;
 		return rc;
 	}
 
@@ -479,7 +479,7 @@
 
 	bt_bmc_config_irq(bt_bmc, pdev);
 
-	if (bt_bmc->irq) {
+	if (bt_bmc->irq >= 0) {
 		dev_info(dev, "Using IRQ %d\n", bt_bmc->irq);
 	} else {
 		dev_info(dev, "No IRQ; using timer\n");
@@ -505,7 +505,7 @@
 	struct bt_bmc *bt_bmc = dev_get_drvdata(&pdev->dev);
 
 	misc_deregister(&bt_bmc->miscdev);
-	if (!bt_bmc->irq)
+	if (bt_bmc->irq < 0)
 		del_timer_sync(&bt_bmc->poll_timer);
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/ipmi/ipmb_dev_int.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/ipmi/ipmb_dev_int.c
@@ -265,7 +265,7 @@
 		break;
 
 	case I2C_SLAVE_WRITE_RECEIVED:
-		if (ipmb_dev->msg_idx >= sizeof(struct ipmb_msg))
+		if (ipmb_dev->msg_idx >= sizeof(struct ipmb_msg) - 1)
 			break;
 
 		buf[++ipmb_dev->msg_idx] = *val;
@@ -309,6 +309,9 @@
 	ipmb_dev->miscdev.name = devm_kasprintf(&client->dev, GFP_KERNEL,
 						"%s%d", "ipmb-",
 						client->adapter->nr);
+	if (!ipmb_dev->miscdev.name)
+		return -ENOMEM;
+
 	ipmb_dev->miscdev.fops = &ipmb_fops;
 	ipmb_dev->miscdev.parent = &client->dev;
 	ret = misc_register(&ipmb_dev->miscdev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/ipmi/ipmi_msghandler.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/ipmi/ipmi_msghandler.c
@@ -11,8 +11,8 @@
  * Copyright 2002 MontaVista Software Inc.
  */
 
-#define pr_fmt(fmt) "%s" fmt, "IPMI message handler: "
-#define dev_fmt pr_fmt
+#define pr_fmt(fmt) "IPMI message handler: " fmt
+#define dev_fmt(fmt) pr_fmt(fmt)
 
 #include <linux/module.h>
 #include <linux/errno.h>
@@ -33,6 +33,7 @@
 #include <linux/workqueue.h>
 #include <linux/uuid.h>
 #include <linux/nospec.h>
+#include <linux/vmalloc.h>
 
 #define IPMI_DRIVER_VERSION "39.2"
 
@@ -219,6 +220,8 @@
 	struct work_struct remove_work;
 };
 
+static struct workqueue_struct *remove_work_wq;
+
 static struct ipmi_user *acquire_ipmi_user(struct ipmi_user *user, int *index)
 	__acquires(user->release_barrier)
 {
@@ -448,6 +451,8 @@
 
 #define IPMI_IPMB_NUM_SEQ	64
 struct ipmi_smi {
+	struct module *owner;
+
 	/* What interface number are we? */
 	int intf_num;
 
@@ -1168,7 +1173,7 @@
 					      remove_work);
 
 	cleanup_srcu_struct(&user->release_barrier);
-	kfree(user);
+	vfree(user);
 }
 
 int ipmi_create_user(unsigned int          if_num,
@@ -1200,7 +1205,7 @@
 	if (rv)
 		return rv;
 
-	new_user = kmalloc(sizeof(*new_user), GFP_KERNEL);
+	new_user = vzalloc(sizeof(*new_user));
 	if (!new_user)
 		return -ENOMEM;
 
@@ -1220,6 +1225,11 @@
 	if (rv)
 		goto out_kfree;
 
+	if (!try_module_get(intf->owner)) {
+		rv = -ENODEV;
+		goto out_kfree;
+	}
+
 	/* Note that each existing user holds a refcount to the interface. */
 	kref_get(&intf->refcount);
 
@@ -1242,7 +1252,7 @@
 
 out_kfree:
 	srcu_read_unlock(&ipmi_interfaces_srcu, index);
-	kfree(new_user);
+	vfree(new_user);
 	return rv;
 }
 EXPORT_SYMBOL(ipmi_create_user);
@@ -1278,7 +1288,7 @@
 	struct ipmi_user *user = container_of(ref, struct ipmi_user, refcount);
 
 	/* SRCU cleanup must happen in task context. */
-	schedule_work(&user->remove_work);
+	queue_work(remove_work_wq, &user->remove_work);
 }
 
 static void _ipmi_destroy_user(struct ipmi_user *user)
@@ -1288,6 +1298,7 @@
 	unsigned long    flags;
 	struct cmd_rcvr  *rcvr;
 	struct cmd_rcvr  *rcvrs = NULL;
+	struct module    *owner;
 
 	if (!acquire_ipmi_user(user, &i)) {
 		/*
@@ -1348,7 +1359,9 @@
 		kfree(rcvr);
 	}
 
+	owner = intf->owner;
 	kref_put(&intf->refcount, intf_free);
+	module_put(owner);
 }
 
 int ipmi_destroy_user(struct ipmi_user *user)
@@ -2459,7 +2472,7 @@
  * been recently fetched, this will just use the cached data.  Otherwise
  * it will run a new fetch.
  *
- * Except for the first time this is called (in ipmi_register_smi()),
+ * Except for the first time this is called (in ipmi_add_smi()),
  * this will always return good data;
  */
 static int __bmc_get_device_id(struct ipmi_smi *intf, struct bmc_device *bmc,
@@ -2927,7 +2940,7 @@
 	 * with removing the device attributes while reading a device
 	 * attribute.
 	 */
-	schedule_work(&bmc->remove_work);
+	queue_work(remove_work_wq, &bmc->remove_work);
 }
 
 /*
@@ -3031,8 +3044,11 @@
 		bmc->pdev.name = "ipmi_bmc";
 
 		rv = ida_simple_get(&ipmi_bmc_ida, 0, 0, GFP_KERNEL);
-		if (rv < 0)
+		if (rv < 0) {
+			kfree(bmc);
 			goto out;
+		}
+
 		bmc->pdev.dev.driver = &ipmidriver.driver;
 		bmc->pdev.id = rv;
 		bmc->pdev.dev.release = release_bmc_device;
@@ -3196,8 +3212,8 @@
 	if (rv)
 		/* Send failed, no GUID available. */
 		bmc->dyn_guid_set = 0;
-
-	wait_event(intf->waitq, bmc->dyn_guid_set != 2);
+	else
+		wait_event(intf->waitq, bmc->dyn_guid_set != 2);
 
 	/* dyn_guid_set makes the guid data available. */
 	smp_rmb();
@@ -3377,10 +3393,11 @@
 	kref_put(&intf->refcount, intf_free);
 }
 
-int ipmi_register_smi(const struct ipmi_smi_handlers *handlers,
-		      void		       *send_info,
-		      struct device            *si_dev,
-		      unsigned char            slave_addr)
+int ipmi_add_smi(struct module         *owner,
+		 const struct ipmi_smi_handlers *handlers,
+		 void		       *send_info,
+		 struct device         *si_dev,
+		 unsigned char         slave_addr)
 {
 	int              i, j;
 	int              rv;
@@ -3406,7 +3423,7 @@
 		return rv;
 	}
 
-
+	intf->owner = owner;
 	intf->bmc = &intf->tmp_bmc;
 	INIT_LIST_HEAD(&intf->bmc->intfs);
 	mutex_init(&intf->bmc->dyn_mutex);
@@ -3514,18 +3531,22 @@
 
 	return rv;
 }
-EXPORT_SYMBOL(ipmi_register_smi);
+EXPORT_SYMBOL(ipmi_add_smi);
 
 static void deliver_smi_err_response(struct ipmi_smi *intf,
 				     struct ipmi_smi_msg *msg,
 				     unsigned char err)
 {
+	int rv;
 	msg->rsp[0] = msg->data[0] | 4;
 	msg->rsp[1] = msg->data[1];
 	msg->rsp[2] = err;
 	msg->rsp_size = 3;
-	/* It's an error, so it will never requeue, no need to check return. */
-	handle_one_recv_msg(intf, msg);
+
+	/* This will never requeue, but it may ask us to free the message. */
+	rv = handle_one_recv_msg(intf, msg);
+	if (rv == 0)
+		ipmi_free_smi_msg(msg);
 }
 
 static void cleanup_smi_msgs(struct ipmi_smi *intf)
@@ -4784,7 +4805,9 @@
 static void free_smi_msg(struct ipmi_smi_msg *msg)
 {
 	atomic_dec(&smi_msg_inuse_count);
-	kfree(msg);
+	/* Try to keep as much stuff out of the panic path as possible. */
+	if (!oops_in_progress)
+		kfree(msg);
 }
 
 struct ipmi_smi_msg *ipmi_alloc_smi_msg(void)
@@ -4803,7 +4826,9 @@
 static void free_recv_msg(struct ipmi_recv_msg *msg)
 {
 	atomic_dec(&recv_msg_inuse_count);
-	kfree(msg);
+	/* Try to keep as much stuff out of the panic path as possible. */
+	if (!oops_in_progress)
+		kfree(msg);
 }
 
 static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void)
@@ -4821,7 +4846,7 @@
 
 void ipmi_free_recv_msg(struct ipmi_recv_msg *msg)
 {
-	if (msg->user)
+	if (msg->user && !oops_in_progress)
 		kref_put(&msg->user->refcount, free_user);
 	msg->done(msg);
 }
@@ -5137,7 +5162,16 @@
 	if (initialized)
 		goto out;
 
-	init_srcu_struct(&ipmi_interfaces_srcu);
+	rv = init_srcu_struct(&ipmi_interfaces_srcu);
+	if (rv)
+		goto out;
+
+	remove_work_wq = create_singlethread_workqueue("ipmi-msghandler-remove-wq");
+	if (!remove_work_wq) {
+		pr_err("unable to create ipmi-msghandler-remove-wq workqueue");
+		rv = -ENOMEM;
+		goto out_wq;
+	}
 
 	timer_setup(&ipmi_timer, ipmi_timeout, 0);
 	mod_timer(&ipmi_timer, jiffies + IPMI_TIMEOUT_JIFFIES);
@@ -5146,6 +5180,9 @@
 
 	initialized = true;
 
+out_wq:
+	if (rv)
+		cleanup_srcu_struct(&ipmi_interfaces_srcu);
 out:
 	mutex_unlock(&ipmi_interfaces_mutex);
 	return rv;
@@ -5169,6 +5206,8 @@
 	int count;
 
 	if (initialized) {
+		destroy_workqueue(remove_work_wq);
+
 		atomic_notifier_chain_unregister(&panic_notifier_list,
 						 &panic_block);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/ipmi/ipmi_si_intf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/ipmi/ipmi_si_intf.c
@@ -1977,7 +1977,7 @@
 	/* Do this early so it's available for logs. */
 	if (!new_smi->io.dev) {
 		pr_err("IPMI interface added with no device\n");
-		rv = EIO;
+		rv = -EIO;
 		goto out_err;
 	}
 
@@ -2086,6 +2086,11 @@
 		new_smi->io.io_cleanup = NULL;
 	}
 
+	if (rv && new_smi->si_sm) {
+		kfree(new_smi->si_sm);
+		new_smi->si_sm = NULL;
+	}
+
 	return rv;
 }
 
@@ -2157,6 +2162,20 @@
 }
 module_init(init_ipmi_si);
 
+static void wait_msg_processed(struct smi_info *smi_info)
+{
+	unsigned long jiffies_now;
+	long time_diff;
+
+	while (smi_info->curr_msg || (smi_info->si_state != SI_NORMAL)) {
+		jiffies_now = jiffies;
+		time_diff = (((long)jiffies_now - (long)smi_info->last_timeout_jiffies)
+		     * SI_USEC_PER_JIFFY);
+		smi_event_handler(smi_info, time_diff);
+		schedule_timeout_uninterruptible(1);
+	}
+}
+
 static void shutdown_smi(void *send_info)
 {
 	struct smi_info *smi_info = send_info;
@@ -2191,16 +2210,13 @@
 	 * in the BMC.  Note that timers and CPU interrupts are off,
 	 * so no need for locks.
 	 */
-	while (smi_info->curr_msg || (smi_info->si_state != SI_NORMAL)) {
-		poll(smi_info);
-		schedule_timeout_uninterruptible(1);
-	}
+	wait_msg_processed(smi_info);
+
 	if (smi_info->handlers)
 		disable_si_irq(smi_info);
-	while (smi_info->curr_msg || (smi_info->si_state != SI_NORMAL)) {
-		poll(smi_info);
-		schedule_timeout_uninterruptible(1);
-	}
+
+	wait_msg_processed(smi_info);
+
 	if (smi_info->handlers)
 		smi_info->handlers->cleanup(smi_info->si_sm);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/ipmi/ipmi_si_platform.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/ipmi/ipmi_si_platform.c
@@ -194,7 +194,7 @@
 	else
 		io.slave_addr = slave_addr;
 
-	io.irq = platform_get_irq(pdev, 0);
+	io.irq = platform_get_irq_optional(pdev, 0);
 	if (io.irq > 0)
 		io.irq_setup = ipmi_std_irq_setup;
 	else
@@ -378,7 +378,7 @@
 		io.irq = tmp;
 		io.irq_setup = acpi_gpe_irq_setup;
 	} else {
-		int irq = platform_get_irq(pdev, 0);
+		int irq = platform_get_irq_optional(pdev, 0);
 
 		if (irq > 0) {
 			io.irq = irq;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/ipmi/ipmi_ssif.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/ipmi/ipmi_ssif.c
@@ -79,7 +79,8 @@
 /*
  * Timer values
  */
-#define SSIF_MSG_USEC		20000	/* 20ms between message tries. */
+#define SSIF_MSG_USEC		60000	/* 60ms between message tries (T3). */
+#define SSIF_REQ_RETRY_USEC	60000	/* 60ms between send retries (T6). */
 #define SSIF_MSG_PART_USEC	5000	/* 5ms for a message part */
 
 /* How many times to we retry sending/receiving the message. */
@@ -87,7 +88,9 @@
 #define	SSIF_RECV_RETRIES	250
 
 #define SSIF_MSG_MSEC		(SSIF_MSG_USEC / 1000)
+#define SSIF_REQ_RETRY_MSEC	(SSIF_REQ_RETRY_USEC / 1000)
 #define SSIF_MSG_JIFFIES	((SSIF_MSG_USEC * 1000) / TICK_NSEC)
+#define SSIF_REQ_RETRY_JIFFIES	((SSIF_REQ_RETRY_USEC * 1000) / TICK_NSEC)
 #define SSIF_MSG_PART_JIFFIES	((SSIF_MSG_PART_USEC * 1000) / TICK_NSEC)
 
 /*
@@ -97,7 +100,7 @@
 #define SSIF_WATCH_WATCHDOG_TIMEOUT	msecs_to_jiffies(250)
 
 enum ssif_intf_state {
-	SSIF_NORMAL,
+	SSIF_IDLE,
 	SSIF_GETTING_FLAGS,
 	SSIF_GETTING_EVENTS,
 	SSIF_CLEARING_FLAGS,
@@ -105,8 +108,8 @@
 	/* FIXME - add watchdog stuff. */
 };
 
-#define SSIF_IDLE(ssif)	 ((ssif)->ssif_state == SSIF_NORMAL \
-			  && (ssif)->curr_msg == NULL)
+#define IS_SSIF_IDLE(ssif) ((ssif)->ssif_state == SSIF_IDLE \
+			    && (ssif)->curr_msg == NULL)
 
 /*
  * Indexes into stats[] in ssif_info below.
@@ -236,6 +239,9 @@
 	bool		    got_alert;
 	bool		    waiting_alert;
 
+	/* Used to inform the timeout that it should do a resend. */
+	bool		    do_resend;
+
 	/*
 	 * If set to true, this will request events the next time the
 	 * state machine is idle.
@@ -248,12 +254,6 @@
 	 */
 	bool                req_flags;
 
-	/*
-	 * Used to perform timer operations when run-to-completion
-	 * mode is on.  This is a countdown timer.
-	 */
-	int                 rtc_us_timer;
-
 	/* Used for sending/receiving data.  +1 for the length. */
 	unsigned char data[IPMI_MAX_MSG_LENGTH + 1];
 	unsigned int  data_len;
@@ -353,9 +353,9 @@
 
 /*
  * Must be called with the message lock held.  This will release the
- * message lock.  Note that the caller will check SSIF_IDLE and start a
- * new operation, so there is no need to check for new messages to
- * start in here.
+ * message lock.  Note that the caller will check IS_SSIF_IDLE and
+ * start a new operation, so there is no need to check for new
+ * messages to start in here.
  */
 static void start_clear_flags(struct ssif_info *ssif_info, unsigned long *flags)
 {
@@ -372,7 +372,7 @@
 
 	if (start_send(ssif_info, msg, 3) != 0) {
 		/* Error, just go to normal state. */
-		ssif_info->ssif_state = SSIF_NORMAL;
+		ssif_info->ssif_state = SSIF_IDLE;
 	}
 }
 
@@ -387,7 +387,7 @@
 	mb[0] = (IPMI_NETFN_APP_REQUEST << 2);
 	mb[1] = IPMI_GET_MSG_FLAGS_CMD;
 	if (start_send(ssif_info, mb, 2) != 0)
-		ssif_info->ssif_state = SSIF_NORMAL;
+		ssif_info->ssif_state = SSIF_IDLE;
 }
 
 static void check_start_send(struct ssif_info *ssif_info, unsigned long *flags,
@@ -398,7 +398,7 @@
 
 		flags = ipmi_ssif_lock_cond(ssif_info, &oflags);
 		ssif_info->curr_msg = NULL;
-		ssif_info->ssif_state = SSIF_NORMAL;
+		ssif_info->ssif_state = SSIF_IDLE;
 		ipmi_ssif_unlock_cond(ssif_info, flags);
 		ipmi_free_smi_msg(msg);
 	}
@@ -412,7 +412,7 @@
 
 	msg = ipmi_alloc_smi_msg();
 	if (!msg) {
-		ssif_info->ssif_state = SSIF_NORMAL;
+		ssif_info->ssif_state = SSIF_IDLE;
 		ipmi_ssif_unlock_cond(ssif_info, flags);
 		return;
 	}
@@ -435,7 +435,7 @@
 
 	msg = ipmi_alloc_smi_msg();
 	if (!msg) {
-		ssif_info->ssif_state = SSIF_NORMAL;
+		ssif_info->ssif_state = SSIF_IDLE;
 		ipmi_ssif_unlock_cond(ssif_info, flags);
 		return;
 	}
@@ -453,9 +453,9 @@
 
 /*
  * Must be called with the message lock held.  This will release the
- * message lock.  Note that the caller will check SSIF_IDLE and start a
- * new operation, so there is no need to check for new messages to
- * start in here.
+ * message lock.  Note that the caller will check IS_SSIF_IDLE and
+ * start a new operation, so there is no need to check for new
+ * messages to start in here.
  */
 static void handle_flags(struct ssif_info *ssif_info, unsigned long *flags)
 {
@@ -471,7 +471,7 @@
 		/* Events available. */
 		start_event_fetch(ssif_info, flags);
 	else {
-		ssif_info->ssif_state = SSIF_NORMAL;
+		ssif_info->ssif_state = SSIF_IDLE;
 		ipmi_ssif_unlock_cond(ssif_info, flags);
 	}
 }
@@ -515,7 +515,7 @@
 	return 0;
 }
 
-static int ssif_i2c_send(struct ssif_info *ssif_info,
+static void ssif_i2c_send(struct ssif_info *ssif_info,
 			ssif_i2c_done handler,
 			int read_write, int command,
 			unsigned char *data, unsigned int size)
@@ -527,7 +527,6 @@
 	ssif_info->i2c_data = data;
 	ssif_info->i2c_size = size;
 	complete(&ssif_info->wake_thread);
-	return 0;
 }
 
 
@@ -536,40 +535,37 @@
 
 static void start_get(struct ssif_info *ssif_info)
 {
-	int rv;
-
-	ssif_info->rtc_us_timer = 0;
 	ssif_info->multi_pos = 0;
 
-	rv = ssif_i2c_send(ssif_info, msg_done_handler, I2C_SMBUS_READ,
-			  SSIF_IPMI_RESPONSE,
-			  ssif_info->recv, I2C_SMBUS_BLOCK_DATA);
-	if (rv < 0) {
-		/* request failed, just return the error. */
-		if (ssif_info->ssif_debug & SSIF_DEBUG_MSG)
-			dev_dbg(&ssif_info->client->dev,
-				"Error from i2c_non_blocking_op(5)\n");
-
-		msg_done_handler(ssif_info, -EIO, NULL, 0);
-	}
+	ssif_i2c_send(ssif_info, msg_done_handler, I2C_SMBUS_READ,
+		  SSIF_IPMI_RESPONSE,
+		  ssif_info->recv, I2C_SMBUS_BLOCK_DATA);
 }
 
+static void start_resend(struct ssif_info *ssif_info);
+
 static void retry_timeout(struct timer_list *t)
 {
 	struct ssif_info *ssif_info = from_timer(ssif_info, t, retry_timer);
 	unsigned long oflags, *flags;
-	bool waiting;
+	bool waiting, resend;
 
 	if (ssif_info->stopping)
 		return;
 
 	flags = ipmi_ssif_lock_cond(ssif_info, &oflags);
+	resend = ssif_info->do_resend;
+	ssif_info->do_resend = false;
 	waiting = ssif_info->waiting_alert;
 	ssif_info->waiting_alert = false;
 	ipmi_ssif_unlock_cond(ssif_info, flags);
 
 	if (waiting)
 		start_get(ssif_info);
+	if (resend) {
+		start_resend(ssif_info);
+		ssif_inc_stat(ssif_info, send_retries);
+	}
 }
 
 static void watch_timeout(struct timer_list *t)
@@ -584,7 +580,7 @@
 	if (ssif_info->watch_timeout) {
 		mod_timer(&ssif_info->watch_timer,
 			  jiffies + ssif_info->watch_timeout);
-		if (SSIF_IDLE(ssif_info)) {
+		if (IS_SSIF_IDLE(ssif_info)) {
 			start_flag_fetch(ssif_info, flags); /* Releases lock */
 			return;
 		}
@@ -618,14 +614,11 @@
 		start_get(ssif_info);
 }
 
-static int start_resend(struct ssif_info *ssif_info);
-
 static void msg_done_handler(struct ssif_info *ssif_info, int result,
 			     unsigned char *data, unsigned int len)
 {
 	struct ipmi_smi_msg *msg;
 	unsigned long oflags, *flags;
-	int rv;
 
 	/*
 	 * We are single-threaded here, so no need for a lock until we
@@ -639,7 +632,6 @@
 
 			flags = ipmi_ssif_lock_cond(ssif_info, &oflags);
 			ssif_info->waiting_alert = true;
-			ssif_info->rtc_us_timer = SSIF_MSG_USEC;
 			if (!ssif_info->stopping)
 				mod_timer(&ssif_info->retry_timer,
 					  jiffies + SSIF_MSG_JIFFIES);
@@ -671,17 +663,10 @@
 		ssif_info->multi_len = len;
 		ssif_info->multi_pos = 1;
 
-		rv = ssif_i2c_send(ssif_info, msg_done_handler, I2C_SMBUS_READ,
-				  SSIF_IPMI_MULTI_PART_RESPONSE_MIDDLE,
-				  ssif_info->recv, I2C_SMBUS_BLOCK_DATA);
-		if (rv < 0) {
-			if (ssif_info->ssif_debug & SSIF_DEBUG_MSG)
-				dev_dbg(&ssif_info->client->dev,
-					"Error from i2c_non_blocking_op(1)\n");
-
-			result = -EIO;
-		} else
-			return;
+		ssif_i2c_send(ssif_info, msg_done_handler, I2C_SMBUS_READ,
+			 SSIF_IPMI_MULTI_PART_RESPONSE_MIDDLE,
+			 ssif_info->recv, I2C_SMBUS_BLOCK_DATA);
+		return;
 	} else if (ssif_info->multi_pos) {
 		/* Middle of multi-part read.  Start the next transaction. */
 		int i;
@@ -743,19 +728,12 @@
 
 			ssif_info->multi_pos++;
 
-			rv = ssif_i2c_send(ssif_info, msg_done_handler,
-					   I2C_SMBUS_READ,
-					   SSIF_IPMI_MULTI_PART_RESPONSE_MIDDLE,
-					   ssif_info->recv,
-					   I2C_SMBUS_BLOCK_DATA);
-			if (rv < 0) {
-				if (ssif_info->ssif_debug & SSIF_DEBUG_MSG)
-					dev_dbg(&ssif_info->client->dev,
-						"Error from ssif_i2c_send\n");
-
-				result = -EIO;
-			} else
-				return;
+			ssif_i2c_send(ssif_info, msg_done_handler,
+				  I2C_SMBUS_READ,
+				  SSIF_IPMI_MULTI_PART_RESPONSE_MIDDLE,
+				  ssif_info->recv,
+				  I2C_SMBUS_BLOCK_DATA);
+			return;
 		}
 	}
 
@@ -775,15 +753,19 @@
 	flags = ipmi_ssif_lock_cond(ssif_info, &oflags);
 	msg = ssif_info->curr_msg;
 	if (msg) {
+		if (data) {
+			if (len > IPMI_MAX_MSG_LENGTH)
+				len = IPMI_MAX_MSG_LENGTH;
+			memcpy(msg->rsp, data, len);
+		} else {
+			len = 0;
+		}
 		msg->rsp_size = len;
-		if (msg->rsp_size > IPMI_MAX_MSG_LENGTH)
-			msg->rsp_size = IPMI_MAX_MSG_LENGTH;
-		memcpy(msg->rsp, data, msg->rsp_size);
 		ssif_info->curr_msg = NULL;
 	}
 
 	switch (ssif_info->ssif_state) {
-	case SSIF_NORMAL:
+	case SSIF_IDLE:
 		ipmi_ssif_unlock_cond(ssif_info, flags);
 		if (!msg)
 			break;
@@ -801,7 +783,7 @@
 			 * Error fetching flags, or invalid length,
 			 * just give up for now.
 			 */
-			ssif_info->ssif_state = SSIF_NORMAL;
+			ssif_info->ssif_state = SSIF_IDLE;
 			ipmi_ssif_unlock_cond(ssif_info, flags);
 			dev_warn(&ssif_info->client->dev,
 				 "Error getting flags: %d %d, %x\n",
@@ -809,9 +791,9 @@
 		} else if (data[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2
 			   || data[1] != IPMI_GET_MSG_FLAGS_CMD) {
 			/*
-			 * Don't abort here, maybe it was a queued
-			 * response to a previous command.
+			 * Recv error response, give up.
 			 */
+			ssif_info->ssif_state = SSIF_IDLE;
 			ipmi_ssif_unlock_cond(ssif_info, flags);
 			dev_warn(&ssif_info->client->dev,
 				 "Invalid response getting flags: %x %x\n",
@@ -836,11 +818,19 @@
 				 "Invalid response clearing flags: %x %x\n",
 				 data[0], data[1]);
 		}
-		ssif_info->ssif_state = SSIF_NORMAL;
+		ssif_info->ssif_state = SSIF_IDLE;
 		ipmi_ssif_unlock_cond(ssif_info, flags);
 		break;
 
 	case SSIF_GETTING_EVENTS:
+		if (!msg) {
+			/* Should never happen, but just in case. */
+			dev_warn(&ssif_info->client->dev,
+				 "No message set while getting events\n");
+			ipmi_ssif_unlock_cond(ssif_info, flags);
+			break;
+		}
+
 		if ((result < 0) || (len < 3) || (msg->rsp[2] != 0)) {
 			/* Error getting event, probably done. */
 			msg->done(msg);
@@ -865,6 +855,14 @@
 		break;
 
 	case SSIF_GETTING_MESSAGES:
+		if (!msg) {
+			/* Should never happen, but just in case. */
+			dev_warn(&ssif_info->client->dev,
+				 "No message set while getting messages\n");
+			ipmi_ssif_unlock_cond(ssif_info, flags);
+			break;
+		}
+
 		if ((result < 0) || (len < 3) || (msg->rsp[2] != 0)) {
 			/* Error getting event, probably done. */
 			msg->done(msg);
@@ -888,10 +886,17 @@
 			deliver_recv_msg(ssif_info, msg);
 		}
 		break;
+
+	default:
+		/* Should never happen, but just in case. */
+		dev_warn(&ssif_info->client->dev,
+			 "Invalid state in message done handling: %d\n",
+			 ssif_info->ssif_state);
+		ipmi_ssif_unlock_cond(ssif_info, flags);
 	}
 
 	flags = ipmi_ssif_lock_cond(ssif_info, &oflags);
-	if (SSIF_IDLE(ssif_info) && !ssif_info->stopping) {
+	if (IS_SSIF_IDLE(ssif_info) && !ssif_info->stopping) {
 		if (ssif_info->req_events)
 			start_event_fetch(ssif_info, flags);
 		else if (ssif_info->req_flags)
@@ -909,37 +914,27 @@
 static void msg_written_handler(struct ssif_info *ssif_info, int result,
 				unsigned char *data, unsigned int len)
 {
-	int rv;
-
 	/* We are single-threaded here, so no need for a lock. */
 	if (result < 0) {
 		ssif_info->retries_left--;
 		if (ssif_info->retries_left > 0) {
-			if (!start_resend(ssif_info)) {
-				ssif_inc_stat(ssif_info, send_retries);
-				return;
-			}
-			/* request failed, just return the error. */
-			ssif_inc_stat(ssif_info, send_errors);
-
-			if (ssif_info->ssif_debug & SSIF_DEBUG_MSG)
-				dev_dbg(&ssif_info->client->dev,
-					"%s: Out of retries\n", __func__);
-			msg_done_handler(ssif_info, -EIO, NULL, 0);
+			/*
+			 * Wait the retry timeout time per the spec,
+			 * then redo the send.
+			 */
+			ssif_info->do_resend = true;
+			mod_timer(&ssif_info->retry_timer,
+				  jiffies + SSIF_REQ_RETRY_JIFFIES);
 			return;
 		}
 
 		ssif_inc_stat(ssif_info, send_errors);
 
-		/*
-		 * Got an error on transmit, let the done routine
-		 * handle it.
-		 */
 		if (ssif_info->ssif_debug & SSIF_DEBUG_MSG)
 			dev_dbg(&ssif_info->client->dev,
-				"%s: Error  %d\n", __func__, result);
+				"%s: Out of retries\n", __func__);
 
-		msg_done_handler(ssif_info, result, NULL, 0);
+		msg_done_handler(ssif_info, -EIO, NULL, 0);
 		return;
 	}
 
@@ -973,18 +968,9 @@
 			ssif_info->multi_data = NULL;
 		}
 
-		rv = ssif_i2c_send(ssif_info, msg_written_handler,
-				   I2C_SMBUS_WRITE, cmd,
-				   data_to_send, I2C_SMBUS_BLOCK_DATA);
-		if (rv < 0) {
-			/* request failed, just return the error. */
-			ssif_inc_stat(ssif_info, send_errors);
-
-			if (ssif_info->ssif_debug & SSIF_DEBUG_MSG)
-				dev_dbg(&ssif_info->client->dev,
-					"Error from i2c_non_blocking_op(3)\n");
-			msg_done_handler(ssif_info, -EIO, NULL, 0);
-		}
+		ssif_i2c_send(ssif_info, msg_written_handler,
+			  I2C_SMBUS_WRITE, cmd,
+			  data_to_send, I2C_SMBUS_BLOCK_DATA);
 	} else {
 		/* Ready to request the result. */
 		unsigned long oflags, *flags;
@@ -1002,7 +988,6 @@
 			/* Wait a jiffie then request the next message */
 			ssif_info->waiting_alert = true;
 			ssif_info->retries_left = SSIF_RECV_RETRIES;
-			ssif_info->rtc_us_timer = SSIF_MSG_PART_USEC;
 			if (!ssif_info->stopping)
 				mod_timer(&ssif_info->retry_timer,
 					  jiffies + SSIF_MSG_PART_JIFFIES);
@@ -1011,9 +996,8 @@
 	}
 }
 
-static int start_resend(struct ssif_info *ssif_info)
+static void start_resend(struct ssif_info *ssif_info)
 {
-	int rv;
 	int command;
 
 	ssif_info->got_alert = false;
@@ -1035,12 +1019,8 @@
 		ssif_info->data[0] = ssif_info->data_len;
 	}
 
-	rv = ssif_i2c_send(ssif_info, msg_written_handler, I2C_SMBUS_WRITE,
-			  command, ssif_info->data, I2C_SMBUS_BLOCK_DATA);
-	if (rv && (ssif_info->ssif_debug & SSIF_DEBUG_MSG))
-		dev_dbg(&ssif_info->client->dev,
-			"Error from i2c_non_blocking_op(4)\n");
-	return rv;
+	ssif_i2c_send(ssif_info, msg_written_handler, I2C_SMBUS_WRITE,
+		   command, ssif_info->data, I2C_SMBUS_BLOCK_DATA);
 }
 
 static int start_send(struct ssif_info *ssif_info,
@@ -1055,7 +1035,8 @@
 	ssif_info->retries_left = SSIF_SEND_RETRIES;
 	memcpy(ssif_info->data + 1, data, len);
 	ssif_info->data_len = len;
-	return start_resend(ssif_info);
+	start_resend(ssif_info);
+	return 0;
 }
 
 /* Must be called with the message lock held. */
@@ -1065,7 +1046,7 @@
 	unsigned long oflags;
 
  restart:
-	if (!SSIF_IDLE(ssif_info)) {
+	if (!IS_SSIF_IDLE(ssif_info)) {
 		ipmi_ssif_unlock_cond(ssif_info, flags);
 		return;
 	}
@@ -1288,7 +1269,7 @@
 	dev_set_drvdata(&ssif_info->client->dev, NULL);
 
 	/* make sure the driver is not looking for flags any more. */
-	while (ssif_info->ssif_state != SSIF_NORMAL)
+	while (ssif_info->ssif_state != SSIF_IDLE)
 		schedule_timeout(1);
 
 	ssif_info->stopping = true;
@@ -1355,8 +1336,10 @@
 	ret = i2c_smbus_write_block_data(client, SSIF_IPMI_REQUEST, len, msg);
 	if (ret) {
 		retry_cnt--;
-		if (retry_cnt > 0)
+		if (retry_cnt > 0) {
+			msleep(SSIF_REQ_RETRY_MSEC);
 			goto retry1;
+		}
 		return -ENODEV;
 	}
 
@@ -1427,7 +1410,7 @@
 restart:
 	list_for_each_entry(info, &ssif_infos, link) {
 		if (info->binfo.addr == addr) {
-			if (info->addr_src == SI_SMBIOS)
+			if (info->addr_src == SI_SMBIOS && !info->adapter_name)
 				info->adapter_name = kstrdup(adapter_name,
 							     GFP_KERNEL);
 
@@ -1496,8 +1479,10 @@
 					 32, msg);
 	if (ret) {
 		retry_cnt--;
-		if (retry_cnt > 0)
+		if (retry_cnt > 0) {
+			msleep(SSIF_REQ_RETRY_MSEC);
 			goto retry_write;
+		}
 		dev_err(&client->dev, "Could not write multi-part start, though the BMC said it could handle it.  Just limit sends to one part.\n");
 		return ret;
 	}
@@ -1624,6 +1609,11 @@
 	info->addr_src = SI_ACPI;
 	info->client = client;
 	info->adapter_name = kstrdup(client->adapter->name, GFP_KERNEL);
+	if (!info->adapter_name) {
+		kfree(info);
+		return -ENOMEM;
+	}
+
 	info->binfo.addr = client->addr;
 	list_add_tail(&info->link, &ssif_infos);
 	return 0;
@@ -1700,6 +1690,9 @@
 		}
 	}
 
+	ssif_info->client = client;
+	i2c_set_clientdata(client, ssif_info);
+
 	rv = ssif_check_and_remove(client, ssif_info);
 	/* If rv is 0 and addr source is not SI_ACPI, continue probing */
 	if (!rv && ssif_info->addr_source == SI_ACPI) {
@@ -1720,9 +1713,6 @@
 		ipmi_addr_src_to_str(ssif_info->addr_source),
 		client->addr, client->adapter->name, slave_addr);
 
-	ssif_info->client = client;
-	i2c_set_clientdata(client, ssif_info);
-
 	/* Now check for system interface capabilities */
 	msg[0] = IPMI_NETFN_APP_REQUEST << 2;
 	msg[1] = IPMI_GET_SYSTEM_INTERFACE_CAPABILITIES_CMD;
@@ -1859,7 +1849,7 @@
 	}
 
 	spin_lock_init(&ssif_info->lock);
-	ssif_info->ssif_state = SSIF_NORMAL;
+	ssif_info->ssif_state = SSIF_IDLE;
 	timer_setup(&ssif_info->retry_timer, retry_timeout, 0);
 	timer_setup(&ssif_info->watch_timer, watch_timeout, 0);
 
@@ -1922,6 +1912,7 @@
 
 		dev_err(&ssif_info->client->dev,
 			"Unable to start IPMI SSIF: %d\n", rv);
+		i2c_set_clientdata(client, NULL);
 		kfree(ssif_info);
 	}
 	kfree(resp);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/ipmi/ipmi_watchdog.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/ipmi/ipmi_watchdog.c
@@ -337,13 +337,17 @@
 static DECLARE_COMPLETION(msg_wait);
 static void msg_free_smi(struct ipmi_smi_msg *msg)
 {
-	if (atomic_dec_and_test(&msg_tofree))
-		complete(&msg_wait);
+	if (atomic_dec_and_test(&msg_tofree)) {
+		if (!oops_in_progress)
+			complete(&msg_wait);
+	}
 }
 static void msg_free_recv(struct ipmi_recv_msg *msg)
 {
-	if (atomic_dec_and_test(&msg_tofree))
-		complete(&msg_wait);
+	if (atomic_dec_and_test(&msg_tofree)) {
+		if (!oops_in_progress)
+			complete(&msg_wait);
+	}
 }
 static struct ipmi_smi_msg smi_msg = {
 	.done = msg_free_smi
@@ -366,16 +370,18 @@
 	data[0] = 0;
 	WDOG_SET_TIMER_USE(data[0], WDOG_TIMER_USE_SMS_OS);
 
-	if ((ipmi_version_major > 1)
-	    || ((ipmi_version_major == 1) && (ipmi_version_minor >= 5))) {
-		/* This is an IPMI 1.5-only feature. */
-		data[0] |= WDOG_DONT_STOP_ON_SET;
-	} else if (ipmi_watchdog_state != WDOG_TIMEOUT_NONE) {
-		/*
-		 * In ipmi 1.0, setting the timer stops the watchdog, we
-		 * need to start it back up again.
-		 */
-		hbnow = 1;
+	if (ipmi_watchdog_state != WDOG_TIMEOUT_NONE) {
+		if ((ipmi_version_major > 1) ||
+		    ((ipmi_version_major == 1) && (ipmi_version_minor >= 5))) {
+			/* This is an IPMI 1.5-only feature. */
+			data[0] |= WDOG_DONT_STOP_ON_SET;
+		} else {
+			/*
+			 * In ipmi 1.0, setting the timer stops the watchdog, we
+			 * need to start it back up again.
+			 */
+			hbnow = 1;
+		}
 	}
 
 	data[1] = 0;
@@ -427,8 +433,10 @@
 	rv = __ipmi_set_timeout(&smi_msg,
 				&recv_msg,
 				&send_heartbeat_now);
-	if (rv)
+	if (rv) {
+		atomic_set(&msg_tofree, 0);
 		return rv;
+	}
 
 	wait_for_completion(&msg_wait);
 
@@ -490,7 +498,7 @@
 	msg.cmd = IPMI_WDOG_RESET_TIMER;
 	msg.data = NULL;
 	msg.data_len = 0;
-	atomic_add(1, &panic_done_count);
+	atomic_add(2, &panic_done_count);
 	rv = ipmi_request_supply_msgs(watchdog_user,
 				      (struct ipmi_addr *) &addr,
 				      0,
@@ -500,7 +508,7 @@
 				      &panic_halt_heartbeat_recv_msg,
 				      1);
 	if (rv)
-		atomic_sub(1, &panic_done_count);
+		atomic_sub(2, &panic_done_count);
 }
 
 static struct ipmi_smi_msg panic_halt_smi_msg = {
@@ -524,12 +532,12 @@
 	/* Wait for the messages to be free. */
 	while (atomic_read(&panic_done_count) != 0)
 		ipmi_poll_interface(watchdog_user);
-	atomic_add(1, &panic_done_count);
+	atomic_add(2, &panic_done_count);
 	rv = __ipmi_set_timeout(&panic_halt_smi_msg,
 				&panic_halt_recv_msg,
 				&send_heartbeat_now);
 	if (rv) {
-		atomic_sub(1, &panic_done_count);
+		atomic_sub(2, &panic_done_count);
 		pr_warn("Unable to extend the watchdog timeout\n");
 	} else {
 		if (send_heartbeat_now)
@@ -573,6 +581,7 @@
 				      &recv_msg,
 				      1);
 	if (rv) {
+		atomic_set(&msg_tofree, 0);
 		pr_warn("heartbeat send failure: %d\n", rv);
 		return rv;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/lp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/lp.c
@@ -713,6 +713,10 @@
 	if (copy_from_user(karg, arg, sizeof(karg)))
 		return -EFAULT;
 
+	/* sparc64 suseconds_t is 32-bit only */
+	if (IS_ENABLED(CONFIG_SPARC64) && !in_compat_syscall())
+		karg[1] >>= 32;
+
 	return lp_set_timeout(minor, karg[0], karg[1]);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/mem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/mem.c
@@ -31,11 +31,15 @@
 #include <linux/uio.h>
 #include <linux/uaccess.h>
 #include <linux/security.h>
+#include <linux/pseudo_fs.h>
+#include <uapi/linux/magic.h>
+#include <linux/mount.h>
 
 #ifdef CONFIG_IA64
 # include <linux/efi.h>
 #endif
 
+#define DEVMEM_MINOR	1
 #define DEVPORT_MINOR	4
 
 static inline unsigned long size_inside_page(unsigned long start,
@@ -805,12 +809,65 @@
 	return ret;
 }
 
+static struct inode *devmem_inode;
+
+#ifdef CONFIG_IO_STRICT_DEVMEM
+void revoke_devmem(struct resource *res)
+{
+	/* pairs with smp_store_release() in devmem_init_inode() */
+	struct inode *inode = smp_load_acquire(&devmem_inode);
+
+	/*
+	 * Check that the initialization has completed. Losing the race
+	 * is ok because it means drivers are claiming resources before
+	 * the fs_initcall level of init and prevent /dev/mem from
+	 * establishing mappings.
+	 */
+	if (!inode)
+		return;
+
+	/*
+	 * The expectation is that the driver has successfully marked
+	 * the resource busy by this point, so devmem_is_allowed()
+	 * should start returning false, however for performance this
+	 * does not iterate the entire resource range.
+	 */
+	if (devmem_is_allowed(PHYS_PFN(res->start)) &&
+	    devmem_is_allowed(PHYS_PFN(res->end))) {
+		/*
+		 * *cringe* iomem=relaxed says "go ahead, what's the
+		 * worst that can happen?"
+		 */
+		return;
+	}
+
+	unmap_mapping_range(inode->i_mapping, res->start, resource_size(res), 1);
+}
+#endif
+
 static int open_port(struct inode *inode, struct file *filp)
 {
+	int rc;
+
 	if (!capable(CAP_SYS_RAWIO))
 		return -EPERM;
 
-	return security_locked_down(LOCKDOWN_DEV_MEM);
+	rc = security_locked_down(LOCKDOWN_DEV_MEM);
+	if (rc)
+		return rc;
+
+	if (iminor(inode) != DEVMEM_MINOR)
+		return 0;
+
+	/*
+	 * Use a unified address space to have a single point to manage
+	 * revocations when drivers want to take over a /dev/mem mapped
+	 * range.
+	 */
+	inode->i_mapping = devmem_inode->i_mapping;
+	filp->f_mapping = inode->i_mapping;
+
+	return 0;
 }
 
 #define zero_lseek	null_lseek
@@ -885,7 +942,7 @@
 	fmode_t fmode;
 } devlist[] = {
 #ifdef CONFIG_DEVMEM
-	 [1] = { "mem", 0, &mem_fops, FMODE_UNSIGNED_OFFSET },
+	 [DEVMEM_MINOR] = { "mem", 0, &mem_fops, FMODE_UNSIGNED_OFFSET },
 #endif
 #ifdef CONFIG_DEVKMEM
 	 [2] = { "kmem", 0, &kmem_fops, FMODE_UNSIGNED_OFFSET },
@@ -896,8 +953,8 @@
 #endif
 	 [5] = { "zero", 0666, &zero_fops, 0 },
 	 [7] = { "full", 0666, &full_fops, 0 },
-	 [8] = { "random", 0666, &random_fops, 0 },
-	 [9] = { "urandom", 0666, &urandom_fops, 0 },
+	 [8] = { "random", 0666, &random_fops, FMODE_NOWAIT },
+	 [9] = { "urandom", 0666, &urandom_fops, FMODE_NOWAIT },
 #ifdef CONFIG_PRINTK
 	[11] = { "kmsg", 0644, &kmsg_fops, 0 },
 #endif
@@ -939,6 +996,48 @@
 
 static struct class *mem_class;
 
+static int devmem_fs_init_fs_context(struct fs_context *fc)
+{
+	return init_pseudo(fc, DEVMEM_MAGIC) ? 0 : -ENOMEM;
+}
+
+static struct file_system_type devmem_fs_type = {
+	.name		= "devmem",
+	.owner		= THIS_MODULE,
+	.init_fs_context = devmem_fs_init_fs_context,
+	.kill_sb	= kill_anon_super,
+};
+
+static int devmem_init_inode(void)
+{
+	static struct vfsmount *devmem_vfs_mount;
+	static int devmem_fs_cnt;
+	struct inode *inode;
+	int rc;
+
+	rc = simple_pin_fs(&devmem_fs_type, &devmem_vfs_mount, &devmem_fs_cnt);
+	if (rc < 0) {
+		pr_err("Cannot mount /dev/mem pseudo filesystem: %d\n", rc);
+		return rc;
+	}
+
+	inode = alloc_anon_inode(devmem_vfs_mount->mnt_sb);
+	if (IS_ERR(inode)) {
+		rc = PTR_ERR(inode);
+		pr_err("Cannot allocate inode for /dev/mem: %d\n", rc);
+		simple_release_fs(&devmem_vfs_mount, &devmem_fs_cnt);
+		return rc;
+	}
+
+	/*
+	 * Publish /dev/mem initialized.
+	 * Pairs with smp_load_acquire() in revoke_devmem().
+	 */
+	smp_store_release(&devmem_inode, inode);
+
+	return 0;
+}
+
 static int __init chr_dev_init(void)
 {
 	int minor;
@@ -960,6 +1059,8 @@
 		 */
 		if ((minor == DEVPORT_MINOR) && !arch_has_dev_port())
 			continue;
+		if ((minor == DEVMEM_MINOR) && devmem_init_inode() != 0)
+			continue;
 
 		device_create(mem_class, NULL, MKDEV(MEM_MAJOR, minor),
 			      NULL, devlist[minor].name);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/mwave/3780i.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/mwave/3780i.h
@@ -68,7 +68,7 @@
 	unsigned char ClockControl:1;	/* RW: Clock control: 0=normal, 1=stop 3780i clocks */
 	unsigned char SoftReset:1;	/* RW: Soft reset 0=normal, 1=soft reset active */
 	unsigned char ConfigMode:1;	/* RW: Configuration mode, 0=normal, 1=config mode */
-	unsigned char Reserved:5;	/* 0: Reserved */
+	unsigned short Reserved:13;	/* 0: Reserved */
 } DSP_ISA_SLAVE_CONTROL;
 
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/pcmcia/cm4000_cs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/pcmcia/cm4000_cs.c
@@ -544,6 +544,10 @@
 		io_read_num_rec_bytes(iobase, &num_bytes_read);
 		if (num_bytes_read >= 4) {
 			DEBUGP(2, dev, "NumRecBytes = %i\n", num_bytes_read);
+			if (num_bytes_read > 4) {
+				rc = -EIO;
+				goto exit_setprotocol;
+			}
 			break;
 		}
 		usleep_range(10000, 11000);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/ppdev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/ppdev.c
@@ -296,28 +296,35 @@
 	if (!port) {
 		pr_warn("%s: no associated port!\n", name);
 		rc = -ENXIO;
-		goto err;
+		goto err_free_name;
+	}
+
+	index = ida_alloc(&ida_index, GFP_KERNEL);
+	if (index < 0) {
+		pr_warn("%s: failed to get index!\n", name);
+		rc = index;
+		goto err_put_port;
 	}
 
-	index = ida_simple_get(&ida_index, 0, 0, GFP_KERNEL);
 	memset(&ppdev_cb, 0, sizeof(ppdev_cb));
 	ppdev_cb.irq_func = pp_irq;
 	ppdev_cb.flags = (pp->flags & PP_EXCL) ? PARPORT_FLAG_EXCL : 0;
 	ppdev_cb.private = pp;
 	pdev = parport_register_dev_model(port, name, &ppdev_cb, index);
-	parport_put_port(port);
 
 	if (!pdev) {
 		pr_warn("%s: failed to register device!\n", name);
 		rc = -ENXIO;
-		ida_simple_remove(&ida_index, index);
-		goto err;
+		ida_free(&ida_index, index);
+		goto err_put_port;
 	}
 
 	pp->pdev = pdev;
 	pp->index = index;
 	dev_dbg(&pdev->dev, "registered pardevice\n");
-err:
+err_put_port:
+	parport_put_port(port);
+err_free_name:
 	kfree(name);
 	return rc;
 }
@@ -619,20 +626,27 @@
 		if (copy_from_user(time32, argp, sizeof(time32)))
 			return -EFAULT;
 
+		if ((time32[0] < 0) || (time32[1] < 0))
+			return -EINVAL;
+
 		return pp_set_timeout(pp->pdev, time32[0], time32[1]);
 
 	case PPSETTIME64:
 		if (copy_from_user(time64, argp, sizeof(time64)))
 			return -EFAULT;
 
+		if ((time64[0] < 0) || (time64[1] < 0))
+			return -EINVAL;
+
+		if (IS_ENABLED(CONFIG_SPARC64) && !in_compat_syscall())
+			time64[1] >>= 32;
+
 		return pp_set_timeout(pp->pdev, time64[0], time64[1]);
 
 	case PPGETTIME32:
 		jiffies_to_timespec64(pp->pdev->timeout, &ts);
 		time32[0] = ts.tv_sec;
 		time32[1] = ts.tv_nsec / NSEC_PER_USEC;
-		if ((time32[0] < 0) || (time32[1] < 0))
-			return -EINVAL;
 
 		if (copy_to_user(argp, time32, sizeof(time32)))
 			return -EFAULT;
@@ -643,8 +657,9 @@
 		jiffies_to_timespec64(pp->pdev->timeout, &ts);
 		time64[0] = ts.tv_sec;
 		time64[1] = ts.tv_nsec / NSEC_PER_USEC;
-		if ((time64[0] < 0) || (time64[1] < 0))
-			return -EINVAL;
+
+		if (IS_ENABLED(CONFIG_SPARC64) && !in_compat_syscall())
+			time64[1] <<= 32;
 
 		if (copy_to_user(argp, time64, sizeof(time64)))
 			return -EFAULT;
@@ -754,7 +769,7 @@
 
 	if (pp->pdev) {
 		parport_unregister_device(pp->pdev);
-		ida_simple_remove(&ida_index, pp->index);
+		ida_free(&ida_index, pp->index);
 		pp->pdev = NULL;
 		pr_debug(CHRDEV "%x: unregistered pardevice\n", minor);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/random.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/random.c
@@ -1,312 +1,30 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
 /*
- * random.c -- A strong random number generator
- *
- * Copyright (C) 2017 Jason A. Donenfeld <Jason@zx2c4.com>. All
- * Rights Reserved.
- *
+ * Copyright (C) 2017-2022 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
  * Copyright Matt Mackall <mpm@selenic.com>, 2003, 2004, 2005
+ * Copyright Theodore Ts'o, 1994, 1995, 1996, 1997, 1998, 1999. All rights reserved.
  *
- * Copyright Theodore Ts'o, 1994, 1995, 1996, 1997, 1998, 1999.  All
- * rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, and the entire permission notice in its entirety,
- *    including the disclaimer of warranties.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- *    products derived from this software without specific prior
- *    written permission.
- *
- * ALTERNATIVELY, this product may be distributed under the terms of
- * the GNU General Public License, in which case the provisions of the GPL are
- * required INSTEAD OF the above restrictions.  (This clause is
- * necessary due to a potential bad interaction between the GPL and
- * the restrictions contained in a BSD-style copyright.)
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
- * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- */
-
-/*
- * (now, with legal B.S. out of the way.....)
- *
- * This routine gathers environmental noise from device drivers, etc.,
- * and returns good random numbers, suitable for cryptographic use.
- * Besides the obvious cryptographic uses, these numbers are also good
- * for seeding TCP sequence numbers, and other places where it is
- * desirable to have numbers which are not only random, but hard to
- * predict by an attacker.
- *
- * Theory of operation
- * ===================
- *
- * Computers are very predictable devices.  Hence it is extremely hard
- * to produce truly random numbers on a computer --- as opposed to
- * pseudo-random numbers, which can easily generated by using a
- * algorithm.  Unfortunately, it is very easy for attackers to guess
- * the sequence of pseudo-random number generators, and for some
- * applications this is not acceptable.  So instead, we must try to
- * gather "environmental noise" from the computer's environment, which
- * must be hard for outside attackers to observe, and use that to
- * generate random numbers.  In a Unix environment, this is best done
- * from inside the kernel.
- *
- * Sources of randomness from the environment include inter-keyboard
- * timings, inter-interrupt timings from some interrupts, and other
- * events which are both (a) non-deterministic and (b) hard for an
- * outside observer to measure.  Randomness from these sources are
- * added to an "entropy pool", which is mixed using a CRC-like function.
- * This is not cryptographically strong, but it is adequate assuming
- * the randomness is not chosen maliciously, and it is fast enough that
- * the overhead of doing it on every interrupt is very reasonable.
- * As random bytes are mixed into the entropy pool, the routines keep
- * an *estimate* of how many bits of randomness have been stored into
- * the random number generator's internal state.
- *
- * When random bytes are desired, they are obtained by taking the SHA
- * hash of the contents of the "entropy pool".  The SHA hash avoids
- * exposing the internal state of the entropy pool.  It is believed to
- * be computationally infeasible to derive any useful information
- * about the input of SHA from its output.  Even if it is possible to
- * analyze SHA in some clever way, as long as the amount of data
- * returned from the generator is less than the inherent entropy in
- * the pool, the output data is totally unpredictable.  For this
- * reason, the routine decreases its internal estimate of how many
- * bits of "true randomness" are contained in the entropy pool as it
- * outputs random numbers.
- *
- * If this estimate goes to zero, the routine can still generate
- * random numbers; however, an attacker may (at least in theory) be
- * able to infer the future output of the generator from prior
- * outputs.  This requires successful cryptanalysis of SHA, which is
- * not believed to be feasible, but there is a remote possibility.
- * Nonetheless, these numbers should be useful for the vast majority
- * of purposes.
- *
- * Exported interfaces ---- output
- * ===============================
- *
- * There are four exported interfaces; two for use within the kernel,
- * and two or use from userspace.
- *
- * Exported interfaces ---- userspace output
- * -----------------------------------------
- *
- * The userspace interfaces are two character devices /dev/random and
- * /dev/urandom.  /dev/random is suitable for use when very high
- * quality randomness is desired (for example, for key generation or
- * one-time pads), as it will only return a maximum of the number of
- * bits of randomness (as estimated by the random number generator)
- * contained in the entropy pool.
- *
- * The /dev/urandom device does not have this limit, and will return
- * as many bytes as are requested.  As more and more random bytes are
- * requested without giving time for the entropy pool to recharge,
- * this will result in random numbers that are merely cryptographically
- * strong.  For many applications, however, this is acceptable.
- *
- * Exported interfaces ---- kernel output
- * --------------------------------------
- *
- * The primary kernel interface is
- *
- * 	void get_random_bytes(void *buf, int nbytes);
- *
- * This interface will return the requested number of random bytes,
- * and place it in the requested buffer.  This is equivalent to a
- * read from /dev/urandom.
- *
- * For less critical applications, there are the functions:
- *
- * 	u32 get_random_u32()
- * 	u64 get_random_u64()
- * 	unsigned int get_random_int()
- * 	unsigned long get_random_long()
- *
- * These are produced by a cryptographic RNG seeded from get_random_bytes,
- * and so do not deplete the entropy pool as much.  These are recommended
- * for most in-kernel operations *if the result is going to be stored in
- * the kernel*.
- *
- * Specifically, the get_random_int() family do not attempt to do
- * "anti-backtracking".  If you capture the state of the kernel (e.g.
- * by snapshotting the VM), you can figure out previous get_random_int()
- * return values.  But if the value is stored in the kernel anyway,
- * this is not a problem.
- *
- * It *is* safe to expose get_random_int() output to attackers (e.g. as
- * network cookies); given outputs 1..n, it's not feasible to predict
- * outputs 0 or n+1.  The only concern is an attacker who breaks into
- * the kernel later; the get_random_int() engine is not reseeded as
- * often as the get_random_bytes() one.
- *
- * get_random_bytes() is needed for keys that need to stay secret after
- * they are erased from the kernel.  For example, any key that will
- * be wrapped and stored encrypted.  And session encryption keys: we'd
- * like to know that after the session is closed and the keys erased,
- * the plaintext is unrecoverable to someone who recorded the ciphertext.
- *
- * But for network ports/cookies, stack canaries, PRNG seeds, address
- * space layout randomization, session *authentication* keys, or other
- * applications where the sensitive data is stored in the kernel in
- * plaintext for as long as it's sensitive, the get_random_int() family
- * is just fine.
- *
- * Consider ASLR.  We want to keep the address space secret from an
- * outside attacker while the process is running, but once the address
- * space is torn down, it's of no use to an attacker any more.  And it's
- * stored in kernel data structures as long as it's alive, so worrying
- * about an attacker's ability to extrapolate it from the get_random_int()
- * CRNG is silly.
- *
- * Even some cryptographic keys are safe to generate with get_random_int().
- * In particular, keys for SipHash are generally fine.  Here, knowledge
- * of the key authorizes you to do something to a kernel object (inject
- * packets to a network connection, or flood a hash table), and the
- * key is stored with the object being protected.  Once it goes away,
- * we no longer care if anyone knows the key.
- *
- * prandom_u32()
- * -------------
- *
- * For even weaker applications, see the pseudorandom generator
- * prandom_u32(), prandom_max(), and prandom_bytes().  If the random
- * numbers aren't security-critical at all, these are *far* cheaper.
- * Useful for self-tests, random error simulation, randomized backoffs,
- * and any other application where you trust that nobody is trying to
- * maliciously mess with you by guessing the "random" numbers.
- *
- * Exported interfaces ---- input
- * ==============================
- *
- * The current exported interfaces for gathering environmental noise
- * from the devices are:
- *
- *	void add_device_randomness(const void *buf, unsigned int size);
- * 	void add_input_randomness(unsigned int type, unsigned int code,
- *                                unsigned int value);
- *	void add_interrupt_randomness(int irq, int irq_flags);
- * 	void add_disk_randomness(struct gendisk *disk);
- *
- * add_device_randomness() is for adding data to the random pool that
- * is likely to differ between two devices (or possibly even per boot).
- * This would be things like MAC addresses or serial numbers, or the
- * read-out of the RTC. This does *not* add any actual entropy to the
- * pool, but it initializes the pool to different values for devices
- * that might otherwise be identical and have very little entropy
- * available to them (particularly common in the embedded world).
- *
- * add_input_randomness() uses the input layer interrupt timing, as well as
- * the event type information from the hardware.
- *
- * add_interrupt_randomness() uses the interrupt timing as random
- * inputs to the entropy pool. Using the cycle counters and the irq source
- * as inputs, it feeds the randomness roughly once a second.
- *
- * add_disk_randomness() uses what amounts to the seek time of block
- * layer request events, on a per-disk_devt basis, as input to the
- * entropy pool. Note that high-speed solid state drives with very low
- * seek times do not make for good sources of entropy, as their seek
- * times are usually fairly consistent.
+ * This driver produces cryptographically secure pseudorandom data. It is divided
+ * into roughly six sections, each with a section header:
  *
- * All of these routines try to estimate how many bits of randomness a
- * particular randomness source.  They do this by keeping track of the
- * first and second order deltas of the event timings.
- *
- * Ensuring unpredictability at system startup
- * ============================================
- *
- * When any operating system starts up, it will go through a sequence
- * of actions that are fairly predictable by an adversary, especially
- * if the start-up does not involve interaction with a human operator.
- * This reduces the actual number of bits of unpredictability in the
- * entropy pool below the value in entropy_count.  In order to
- * counteract this effect, it helps to carry information in the
- * entropy pool across shut-downs and start-ups.  To do this, put the
- * following lines an appropriate script which is run during the boot
- * sequence:
- *
- *	echo "Initializing random number generator..."
- *	random_seed=/var/run/random-seed
- *	# Carry a random seed from start-up to start-up
- *	# Load and then save the whole entropy pool
- *	if [ -f $random_seed ]; then
- *		cat $random_seed >/dev/urandom
- *	else
- *		touch $random_seed
- *	fi
- *	chmod 600 $random_seed
- *	dd if=/dev/urandom of=$random_seed count=1 bs=512
- *
- * and the following lines in an appropriate script which is run as
- * the system is shutdown:
- *
- *	# Carry a random seed from shut-down to start-up
- *	# Save the whole entropy pool
- *	echo "Saving random seed..."
- *	random_seed=/var/run/random-seed
- *	touch $random_seed
- *	chmod 600 $random_seed
- *	dd if=/dev/urandom of=$random_seed count=1 bs=512
- *
- * For example, on most modern systems using the System V init
- * scripts, such code fragments would be found in
- * /etc/rc.d/init.d/random.  On older Linux systems, the correct script
- * location might be in /etc/rcb.d/rc.local or /etc/rc.d/rc.0.
- *
- * Effectively, these commands cause the contents of the entropy pool
- * to be saved at shut-down time and reloaded into the entropy pool at
- * start-up.  (The 'dd' in the addition to the bootup script is to
- * make sure that /etc/random-seed is different for every start-up,
- * even if the system crashes without executing rc.0.)  Even with
- * complete knowledge of the start-up activities, predicting the state
- * of the entropy pool requires knowledge of the previous history of
- * the system.
- *
- * Configuring the /dev/random driver under Linux
- * ==============================================
- *
- * The /dev/random driver under Linux uses minor numbers 8 and 9 of
- * the /dev/mem major number (#1).  So if your system does not have
- * /dev/random and /dev/urandom created already, they can be created
- * by using the commands:
- *
- * 	mknod /dev/random c 1 8
- * 	mknod /dev/urandom c 1 9
- *
- * Acknowledgements:
- * =================
- *
- * Ideas for constructing this random number generator were derived
- * from Pretty Good Privacy's random number generator, and from private
- * discussions with Phil Karn.  Colin Plumb provided a faster random
- * number generator, which speed up the mixing function of the entropy
- * pool, taken from PGPfone.  Dale Worley has also contributed many
- * useful ideas and suggestions to improve this driver.
- *
- * Any flaws in the design are solely my responsibility, and should
- * not be attributed to the Phil, Colin, or any of authors of PGP.
- *
- * Further background information on this topic may be obtained from
- * RFC 1750, "Randomness Recommendations for Security", by Donald
- * Eastlake, Steve Crocker, and Jeff Schiller.
+ *   - Initialization and readiness waiting.
+ *   - Fast key erasure RNG, the "crng".
+ *   - Entropy accumulation and extraction routines.
+ *   - Entropy collection routines.
+ *   - Userspace reader/writer interfaces.
+ *   - Sysctl interface.
+ *
+ * The high level overview is that there is one input pool, into which
+ * various pieces of data are hashed. Prior to initialization, some of that
+ * data is then "credited" as having a certain number of bits of entropy.
+ * When enough bits of entropy are available, the hash is finalized and
+ * handed as a key to a stream cipher that expands it indefinitely for
+ * various consumers. This key is periodically refreshed as the various
+ * entropy collectors, described below, add data to the input pool.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/utsname.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -325,8 +43,6 @@
 #include <linux/spinlock.h>
 #include <linux/kthread.h>
 #include <linux/percpu.h>
-#include <linux/cryptohash.h>
-#include <linux/fips.h>
 #include <linux/ptrace.h>
 #include <linux/workqueue.h>
 #include <linux/irq.h>
@@ -334,1403 +50,1085 @@
 #include <linux/syscalls.h>
 #include <linux/completion.h>
 #include <linux/uuid.h>
+#include <linux/uaccess.h>
+#include <linux/siphash.h>
+#include <linux/uio.h>
 #include <crypto/chacha.h>
-
+#include <crypto/blake2s.h>
 #include <asm/processor.h>
-#include <linux/uaccess.h>
 #include <asm/irq.h>
 #include <asm/irq_regs.h>
 #include <asm/io.h>
 
-#define CREATE_TRACE_POINTS
-#include <trace/events/random.h>
-
-/* #define ADD_INTERRUPT_BENCH */
-
-/*
- * Configuration information
- */
-#define INPUT_POOL_SHIFT	12
-#define INPUT_POOL_WORDS	(1 << (INPUT_POOL_SHIFT-5))
-#define OUTPUT_POOL_SHIFT	10
-#define OUTPUT_POOL_WORDS	(1 << (OUTPUT_POOL_SHIFT-5))
-#define SEC_XFER_SIZE		512
-#define EXTRACT_SIZE		10
-
-
-#define LONGS(x) (((x) + sizeof(unsigned long) - 1)/sizeof(unsigned long))
-
-/*
- * To allow fractional bits to be tracked, the entropy_count field is
- * denominated in units of 1/8th bits.
- *
- * 2*(ENTROPY_SHIFT + poolbitshift) must <= 31, or the multiply in
- * credit_entropy_bits() needs to be 64 bits wide.
- */
-#define ENTROPY_SHIFT 3
-#define ENTROPY_BITS(r) ((r)->entropy_count >> ENTROPY_SHIFT)
-
-/*
- * The minimum number of bits of entropy before we wake up a read on
- * /dev/random.  Should be enough to do a significant reseed.
- */
-static int random_read_wakeup_bits = 64;
-
-/*
- * If the entropy count falls under this number of bits, then we
- * should wake up processes which are selecting or polling on write
- * access to /dev/random.
- */
-static int random_write_wakeup_bits = 28 * OUTPUT_POOL_WORDS;
-
-/*
- * Originally, we used a primitive polynomial of degree .poolwords
- * over GF(2).  The taps for various sizes are defined below.  They
- * were chosen to be evenly spaced except for the last tap, which is 1
- * to get the twisting happening as fast as possible.
- *
- * For the purposes of better mixing, we use the CRC-32 polynomial as
- * well to make a (modified) twisted Generalized Feedback Shift
- * Register.  (See M. Matsumoto & Y. Kurita, 1992.  Twisted GFSR
- * generators.  ACM Transactions on Modeling and Computer Simulation
- * 2(3):179-194.  Also see M. Matsumoto & Y. Kurita, 1994.  Twisted
- * GFSR generators II.  ACM Transactions on Modeling and Computer
- * Simulation 4:254-266)
- *
- * Thanks to Colin Plumb for suggesting this.
- *
- * The mixing operation is much less sensitive than the output hash,
- * where we use SHA-1.  All that we want of mixing operation is that
- * it be a good non-cryptographic hash; i.e. it not produce collisions
- * when fed "random" data of the sort we expect to see.  As long as
- * the pool state differs for different inputs, we have preserved the
- * input entropy and done a good job.  The fact that an intelligent
- * attacker can construct inputs that will produce controlled
- * alterations to the pool's state is not important because we don't
- * consider such inputs to contribute any randomness.  The only
- * property we need with respect to them is that the attacker can't
- * increase his/her knowledge of the pool's state.  Since all
- * additions are reversible (knowing the final state and the input,
- * you can reconstruct the initial state), if an attacker has any
- * uncertainty about the initial state, he/she can only shuffle that
- * uncertainty about, but never cause any collisions (which would
- * decrease the uncertainty).
- *
- * Our mixing functions were analyzed by Lacharme, Roeck, Strubel, and
- * Videau in their paper, "The Linux Pseudorandom Number Generator
- * Revisited" (see: http://eprint.iacr.org/2012/251.pdf).  In their
- * paper, they point out that we are not using a true Twisted GFSR,
- * since Matsumoto & Kurita used a trinomial feedback polynomial (that
- * is, with only three taps, instead of the six that we are using).
- * As a result, the resulting polynomial is neither primitive nor
- * irreducible, and hence does not have a maximal period over
- * GF(2**32).  They suggest a slight change to the generator
- * polynomial which improves the resulting TGFSR polynomial to be
- * irreducible, which we have made here.
- */
-static const struct poolinfo {
-	int poolbitshift, poolwords, poolbytes, poolfracbits;
-#define S(x) ilog2(x)+5, (x), (x)*4, (x) << (ENTROPY_SHIFT+5)
-	int tap1, tap2, tap3, tap4, tap5;
-} poolinfo_table[] = {
-	/* was: x^128 + x^103 + x^76 + x^51 +x^25 + x + 1 */
-	/* x^128 + x^104 + x^76 + x^51 +x^25 + x + 1 */
-	{ S(128),	104,	76,	51,	25,	1 },
-	/* was: x^32 + x^26 + x^20 + x^14 + x^7 + x + 1 */
-	/* x^32 + x^26 + x^19 + x^14 + x^7 + x + 1 */
-	{ S(32),	26,	19,	14,	7,	1 },
-#if 0
-	/* x^2048 + x^1638 + x^1231 + x^819 + x^411 + x + 1  -- 115 */
-	{ S(2048),	1638,	1231,	819,	411,	1 },
-
-	/* x^1024 + x^817 + x^615 + x^412 + x^204 + x + 1 -- 290 */
-	{ S(1024),	817,	615,	412,	204,	1 },
-
-	/* x^1024 + x^819 + x^616 + x^410 + x^207 + x^2 + 1 -- 115 */
-	{ S(1024),	819,	616,	410,	207,	2 },
-
-	/* x^512 + x^411 + x^308 + x^208 + x^104 + x + 1 -- 225 */
-	{ S(512),	411,	308,	208,	104,	1 },
-
-	/* x^512 + x^409 + x^307 + x^206 + x^102 + x^2 + 1 -- 95 */
-	{ S(512),	409,	307,	206,	102,	2 },
-	/* x^512 + x^409 + x^309 + x^205 + x^103 + x^2 + 1 -- 95 */
-	{ S(512),	409,	309,	205,	103,	2 },
-
-	/* x^256 + x^205 + x^155 + x^101 + x^52 + x + 1 -- 125 */
-	{ S(256),	205,	155,	101,	52,	1 },
-
-	/* x^128 + x^103 + x^78 + x^51 + x^27 + x^2 + 1 -- 70 */
-	{ S(128),	103,	78,	51,	27,	2 },
-
-	/* x^64 + x^52 + x^39 + x^26 + x^14 + x + 1 -- 15 */
-	{ S(64),	52,	39,	26,	14,	1 },
-#endif
-};
+/*********************************************************************
+ *
+ * Initialization and readiness waiting.
+ *
+ * Much of the RNG infrastructure is devoted to various dependencies
+ * being able to wait until the RNG has collected enough entropy and
+ * is ready for safe consumption.
+ *
+ *********************************************************************/
 
 /*
- * Static global variables
+ * crng_init is protected by base_crng->lock, and only increases
+ * its value (from empty->early->ready).
  */
-static DECLARE_WAIT_QUEUE_HEAD(random_read_wait);
-static DECLARE_WAIT_QUEUE_HEAD(random_write_wait);
+static enum {
+	CRNG_EMPTY = 0, /* Little to no entropy collected */
+	CRNG_EARLY = 1, /* At least POOL_EARLY_BITS collected */
+	CRNG_READY = 2  /* Fully initialized with POOL_READY_BITS collected */
+} crng_init __read_mostly = CRNG_EMPTY;
+#define crng_ready() (likely(crng_init >= CRNG_READY))
+/* Various types of waiters for crng_init->CRNG_READY transition. */
+static DECLARE_WAIT_QUEUE_HEAD(crng_init_wait);
 static struct fasync_struct *fasync;
+static DEFINE_SPINLOCK(random_ready_chain_lock);
+static RAW_NOTIFIER_HEAD(random_ready_chain);
 
-static DEFINE_SPINLOCK(random_ready_list_lock);
-static LIST_HEAD(random_ready_list);
-
-struct crng_state {
-	__u32		state[16];
-	unsigned long	init_time;
-	spinlock_t	lock;
-};
-
-static struct crng_state primary_crng = {
-	.lock = __SPIN_LOCK_UNLOCKED(primary_crng.lock),
-};
-
-/*
- * crng_init =  0 --> Uninitialized
- *		1 --> Initialized
- *		2 --> Initialized from input_pool
- *
- * crng_init is protected by primary_crng->lock, and only increases
- * its value (from 0->1->2).
- */
-static int crng_init = 0;
-#define crng_ready() (likely(crng_init > 1))
-static int crng_init_cnt = 0;
-static unsigned long crng_global_init_time = 0;
-#define CRNG_INIT_CNT_THRESH (2*CHACHA_KEY_SIZE)
-static void _extract_crng(struct crng_state *crng, __u8 out[CHACHA_BLOCK_SIZE]);
-static void _crng_backtrack_protect(struct crng_state *crng,
-				    __u8 tmp[CHACHA_BLOCK_SIZE], int used);
-static void process_random_ready_list(void);
-static void _get_random_bytes(void *buf, int nbytes);
-
-static struct ratelimit_state unseeded_warning =
-	RATELIMIT_STATE_INIT("warn_unseeded_randomness", HZ, 3);
+/* Control how we warn userspace. */
 static struct ratelimit_state urandom_warning =
-	RATELIMIT_STATE_INIT("warn_urandom_randomness", HZ, 3);
-
-static int ratelimit_disable __read_mostly;
-
+	RATELIMIT_STATE_INIT_FLAGS("urandom_warning", HZ, 3, RATELIMIT_MSG_ON_RELEASE);
+static int ratelimit_disable __read_mostly =
+	IS_ENABLED(CONFIG_WARN_ALL_UNSEEDED_RANDOM);
 module_param_named(ratelimit_disable, ratelimit_disable, int, 0644);
 MODULE_PARM_DESC(ratelimit_disable, "Disable random ratelimit suppression");
 
-/**********************************************************************
- *
- * OS independent entropy store.   Here are the functions which handle
- * storing entropy in an entropy pool.
+/*
+ * Returns whether or not the input pool has been seeded and thus guaranteed
+ * to supply cryptographically secure random numbers. This applies to: the
+ * /dev/urandom device, the get_random_bytes function, and the get_random_{u32,
+ * ,u64,int,long} family of functions.
  *
- **********************************************************************/
-
-struct entropy_store;
-struct entropy_store {
-	/* read-only data: */
-	const struct poolinfo *poolinfo;
-	__u32 *pool;
-	const char *name;
-	struct entropy_store *pull;
-	struct work_struct push_work;
-
-	/* read-write data: */
-	unsigned long last_pulled;
-	spinlock_t lock;
-	unsigned short add_ptr;
-	unsigned short input_rotate;
-	int entropy_count;
-	unsigned int initialized:1;
-	unsigned int last_data_init:1;
-	__u8 last_data[EXTRACT_SIZE];
-};
-
-static ssize_t extract_entropy(struct entropy_store *r, void *buf,
-			       size_t nbytes, int min, int rsvd);
-static ssize_t _extract_entropy(struct entropy_store *r, void *buf,
-				size_t nbytes, int fips);
-
-static void crng_reseed(struct crng_state *crng, struct entropy_store *r);
-static void push_to_pool(struct work_struct *work);
-static __u32 input_pool_data[INPUT_POOL_WORDS] __latent_entropy;
-static __u32 blocking_pool_data[OUTPUT_POOL_WORDS] __latent_entropy;
-
-static struct entropy_store input_pool = {
-	.poolinfo = &poolinfo_table[0],
-	.name = "input",
-	.lock = __SPIN_LOCK_UNLOCKED(input_pool.lock),
-	.pool = input_pool_data
-};
-
-static struct entropy_store blocking_pool = {
-	.poolinfo = &poolinfo_table[1],
-	.name = "blocking",
-	.pull = &input_pool,
-	.lock = __SPIN_LOCK_UNLOCKED(blocking_pool.lock),
-	.pool = blocking_pool_data,
-	.push_work = __WORK_INITIALIZER(blocking_pool.push_work,
-					push_to_pool),
-};
+ * Returns: true if the input pool has been seeded.
+ *          false if the input pool has not been seeded.
+ */
+bool rng_is_initialized(void)
+{
+	return crng_ready();
+}
+EXPORT_SYMBOL(rng_is_initialized);
 
-static __u32 const twist_table[8] = {
-	0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
-	0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
+/* Used by wait_for_random_bytes(), and considered an entropy collector, below. */
+static void try_to_generate_entropy(void);
 
 /*
- * This function adds bytes into the entropy "pool".  It does not
- * update the entropy estimate.  The caller should call
- * credit_entropy_bits if this is appropriate.
+ * Wait for the input pool to be seeded and thus guaranteed to supply
+ * cryptographically secure random numbers. This applies to: the /dev/urandom
+ * device, the get_random_bytes function, and the get_random_{u32,u64,int,long}
+ * family of functions. Using any of these functions without first calling
+ * this function forfeits the guarantee of security.
  *
- * The pool is stirred with a primitive polynomial of the appropriate
- * degree, and then twisted.  We twist by three bits at a time because
- * it's cheap to do so and helps slightly in the expected case where
- * the entropy is concentrated in the low-order bits.
+ * Returns: 0 if the input pool has been seeded.
+ *          -ERESTARTSYS if the function was interrupted by a signal.
  */
-static void _mix_pool_bytes(struct entropy_store *r, const void *in,
-			    int nbytes)
+int wait_for_random_bytes(void)
 {
-	unsigned long i, tap1, tap2, tap3, tap4, tap5;
-	int input_rotate;
-	int wordmask = r->poolinfo->poolwords - 1;
-	const char *bytes = in;
-	__u32 w;
-
-	tap1 = r->poolinfo->tap1;
-	tap2 = r->poolinfo->tap2;
-	tap3 = r->poolinfo->tap3;
-	tap4 = r->poolinfo->tap4;
-	tap5 = r->poolinfo->tap5;
-
-	input_rotate = r->input_rotate;
-	i = r->add_ptr;
-
-	/* mix one byte at a time to simplify size handling and churn faster */
-	while (nbytes--) {
-		w = rol32(*bytes++, input_rotate);
-		i = (i - 1) & wordmask;
+	while (!crng_ready()) {
+		int ret;
 
-		/* XOR in the various taps */
-		w ^= r->pool[i];
-		w ^= r->pool[(i + tap1) & wordmask];
-		w ^= r->pool[(i + tap2) & wordmask];
-		w ^= r->pool[(i + tap3) & wordmask];
-		w ^= r->pool[(i + tap4) & wordmask];
-		w ^= r->pool[(i + tap5) & wordmask];
+		try_to_generate_entropy();
+		ret = wait_event_interruptible_timeout(crng_init_wait, crng_ready(), HZ);
+		if (ret)
+			return ret > 0 ? 0 : ret;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(wait_for_random_bytes);
 
-		/* Mix the result back in with a twist */
-		r->pool[i] = (w >> 3) ^ twist_table[w & 7];
+/*
+ * Add a callback function that will be invoked when the input
+ * pool is initialised.
+ *
+ * returns: 0 if callback is successfully added
+ *	    -EALREADY if pool is already initialised (callback not called)
+ */
+int __cold register_random_ready_notifier(struct notifier_block *nb)
+{
+	unsigned long flags;
+	int ret = -EALREADY;
 
-		/*
-		 * Normally, we add 7 bits of rotation to the pool.
-		 * At the beginning of the pool, add an extra 7 bits
-		 * rotation, so that successive passes spread the
-		 * input bits across the pool evenly.
-		 */
-		input_rotate = (input_rotate + (i ? 7 : 14)) & 31;
-	}
+	if (crng_ready())
+		return ret;
 
-	r->input_rotate = input_rotate;
-	r->add_ptr = i;
+	spin_lock_irqsave(&random_ready_chain_lock, flags);
+	if (!crng_ready())
+		ret = raw_notifier_chain_register(&random_ready_chain, nb);
+	spin_unlock_irqrestore(&random_ready_chain_lock, flags);
+	return ret;
 }
 
-static void __mix_pool_bytes(struct entropy_store *r, const void *in,
-			     int nbytes)
+/*
+ * Delete a previously registered readiness callback function.
+ */
+int __cold unregister_random_ready_notifier(struct notifier_block *nb)
 {
-	trace_mix_pool_bytes_nolock(r->name, nbytes, _RET_IP_);
-	_mix_pool_bytes(r, in, nbytes);
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&random_ready_chain_lock, flags);
+	ret = raw_notifier_chain_unregister(&random_ready_chain, nb);
+	spin_unlock_irqrestore(&random_ready_chain_lock, flags);
+	return ret;
 }
 
-static void mix_pool_bytes(struct entropy_store *r, const void *in,
-			   int nbytes)
+static void __cold process_random_ready_list(void)
 {
 	unsigned long flags;
 
-	trace_mix_pool_bytes(r->name, nbytes, _RET_IP_);
-	spin_lock_irqsave(&r->lock, flags);
-	_mix_pool_bytes(r, in, nbytes);
-	spin_unlock_irqrestore(&r->lock, flags);
+	spin_lock_irqsave(&random_ready_chain_lock, flags);
+	raw_notifier_call_chain(&random_ready_chain, 0, NULL);
+	spin_unlock_irqrestore(&random_ready_chain_lock, flags);
 }
 
-struct fast_pool {
-	__u32		pool[4];
-	unsigned long	last;
-	unsigned short	reg_idx;
-	unsigned char	count;
-};
+#define warn_unseeded_randomness() \
+	if (IS_ENABLED(CONFIG_WARN_ALL_UNSEEDED_RANDOM) && !crng_ready()) \
+		printk_deferred(KERN_NOTICE "random: %s called from %pS with crng_init=%d\n", \
+				__func__, (void *)_RET_IP_, crng_init)
 
-/*
- * This is a fast mixing routine used by the interrupt randomness
- * collector.  It's hardcoded for an 128 bit pool and assumes that any
- * locks that might be needed are taken by the caller.
- */
-static void fast_mix(struct fast_pool *f)
-{
-	__u32 a = f->pool[0],	b = f->pool[1];
-	__u32 c = f->pool[2],	d = f->pool[3];
 
-	a += b;			c += d;
-	b = rol32(b, 6);	d = rol32(d, 27);
-	d ^= a;			b ^= c;
+/*********************************************************************
+ *
+ * Fast key erasure RNG, the "crng".
+ *
+ * These functions expand entropy from the entropy extractor into
+ * long streams for external consumption using the "fast key erasure"
+ * RNG described at <https://blog.cr.yp.to/20170723-random.html>.
+ *
+ * There are a few exported interfaces for use by other drivers:
+ *
+ *	void get_random_bytes(void *buf, size_t len)
+ *	u32 get_random_u32()
+ *	u64 get_random_u64()
+ *	unsigned int get_random_int()
+ *	unsigned long get_random_long()
+ *
+ * These interfaces will return the requested number of random bytes
+ * into the given buffer or as a return value. This is equivalent to
+ * a read from /dev/urandom. The u32, u64, int, and long family of
+ * functions may be higher performance for one-off random integers,
+ * because they do a bit of buffering and do not invoke reseeding
+ * until the buffer is emptied.
+ *
+ *********************************************************************/
+
+enum {
+	CRNG_RESEED_START_INTERVAL = HZ,
+	CRNG_RESEED_INTERVAL = 60 * HZ
+};
 
-	a += b;			c += d;
-	b = rol32(b, 16);	d = rol32(d, 14);
-	d ^= a;			b ^= c;
+static struct {
+	u8 key[CHACHA_KEY_SIZE] __aligned(__alignof__(long));
+	unsigned long birth;
+	unsigned long generation;
+	spinlock_t lock;
+} base_crng = {
+	.lock = __SPIN_LOCK_UNLOCKED(base_crng.lock)
+};
 
-	a += b;			c += d;
-	b = rol32(b, 6);	d = rol32(d, 27);
-	d ^= a;			b ^= c;
+struct crng {
+	u8 key[CHACHA_KEY_SIZE];
+	unsigned long generation;
+};
 
-	a += b;			c += d;
-	b = rol32(b, 16);	d = rol32(d, 14);
-	d ^= a;			b ^= c;
+static DEFINE_PER_CPU(struct crng, crngs) = {
+	.generation = ULONG_MAX
+};
 
-	f->pool[0] = a;  f->pool[1] = b;
-	f->pool[2] = c;  f->pool[3] = d;
-	f->count++;
-}
+/* Used by crng_reseed() and crng_make_state() to extract a new seed from the input pool. */
+static void extract_entropy(void *buf, size_t len);
 
-static void process_random_ready_list(void)
+/* This extracts a new crng key from the input pool. */
+static void crng_reseed(void)
 {
 	unsigned long flags;
-	struct random_ready_callback *rdy, *tmp;
+	unsigned long next_gen;
+	u8 key[CHACHA_KEY_SIZE];
 
-	spin_lock_irqsave(&random_ready_list_lock, flags);
-	list_for_each_entry_safe(rdy, tmp, &random_ready_list, list) {
-		struct module *owner = rdy->owner;
+	extract_entropy(key, sizeof(key));
 
-		list_del_init(&rdy->list);
-		rdy->func(rdy);
-		module_put(owner);
-	}
-	spin_unlock_irqrestore(&random_ready_list_lock, flags);
+	/*
+	 * We copy the new key into the base_crng, overwriting the old one,
+	 * and update the generation counter. We avoid hitting ULONG_MAX,
+	 * because the per-cpu crngs are initialized to ULONG_MAX, so this
+	 * forces new CPUs that come online to always initialize.
+	 */
+	spin_lock_irqsave(&base_crng.lock, flags);
+	memcpy(base_crng.key, key, sizeof(base_crng.key));
+	next_gen = base_crng.generation + 1;
+	if (next_gen == ULONG_MAX)
+		++next_gen;
+	WRITE_ONCE(base_crng.generation, next_gen);
+	WRITE_ONCE(base_crng.birth, jiffies);
+	if (!crng_ready())
+		crng_init = CRNG_READY;
+	spin_unlock_irqrestore(&base_crng.lock, flags);
+	memzero_explicit(key, sizeof(key));
 }
 
 /*
- * Credit (or debit) the entropy store with n bits of entropy.
- * Use credit_entropy_bits_safe() if the value comes from userspace
- * or otherwise should be checked for extreme values.
+ * This generates a ChaCha block using the provided key, and then
+ * immediately overwites that key with half the block. It returns
+ * the resultant ChaCha state to the user, along with the second
+ * half of the block containing 32 bytes of random data that may
+ * be used; random_data_len may not be greater than 32.
+ *
+ * The returned ChaCha state contains within it a copy of the old
+ * key value, at index 4, so the state should always be zeroed out
+ * immediately after using in order to maintain forward secrecy.
+ * If the state cannot be erased in a timely manner, then it is
+ * safer to set the random_data parameter to &chacha_state[4] so
+ * that this function overwrites it before returning.
  */
-static void credit_entropy_bits(struct entropy_store *r, int nbits)
+static void crng_fast_key_erasure(u8 key[CHACHA_KEY_SIZE],
+				  u32 chacha_state[CHACHA_BLOCK_SIZE / sizeof(u32)],
+				  u8 *random_data, size_t random_data_len)
 {
-	int entropy_count, orig, has_initialized = 0;
-	const int pool_size = r->poolinfo->poolfracbits;
-	int nfrac = nbits << ENTROPY_SHIFT;
+	u8 first_block[CHACHA_BLOCK_SIZE];
 
-	if (!nbits)
-		return;
+	BUG_ON(random_data_len > 32);
 
-retry:
-	entropy_count = orig = READ_ONCE(r->entropy_count);
-	if (nfrac < 0) {
-		/* Debit */
-		entropy_count += nfrac;
-	} else {
-		/*
-		 * Credit: we have to account for the possibility of
-		 * overwriting already present entropy.	 Even in the
-		 * ideal case of pure Shannon entropy, new contributions
-		 * approach the full value asymptotically:
-		 *
-		 * entropy <- entropy + (pool_size - entropy) *
-		 *	(1 - exp(-add_entropy/pool_size))
-		 *
-		 * For add_entropy <= pool_size/2 then
-		 * (1 - exp(-add_entropy/pool_size)) >=
-		 *    (add_entropy/pool_size)*0.7869...
-		 * so we can approximate the exponential with
-		 * 3/4*add_entropy/pool_size and still be on the
-		 * safe side by adding at most pool_size/2 at a time.
-		 *
-		 * The use of pool_size-2 in the while statement is to
-		 * prevent rounding artifacts from making the loop
-		 * arbitrarily long; this limits the loop to log2(pool_size)*2
-		 * turns no matter how large nbits is.
-		 */
-		int pnfrac = nfrac;
-		const int s = r->poolinfo->poolbitshift + ENTROPY_SHIFT + 2;
-		/* The +2 corresponds to the /4 in the denominator */
-
-		do {
-			unsigned int anfrac = min(pnfrac, pool_size/2);
-			unsigned int add =
-				((pool_size - entropy_count)*anfrac*3) >> s;
-
-			entropy_count += add;
-			pnfrac -= anfrac;
-		} while (unlikely(entropy_count < pool_size-2 && pnfrac));
-	}
-
-	if (unlikely(entropy_count < 0)) {
-		pr_warn("random: negative entropy/overflow: pool %s count %d\n",
-			r->name, entropy_count);
-		WARN_ON(1);
-		entropy_count = 0;
-	} else if (entropy_count > pool_size)
-		entropy_count = pool_size;
-	if ((r == &blocking_pool) && !r->initialized &&
-	    (entropy_count >> ENTROPY_SHIFT) > 128)
-		has_initialized = 1;
-	if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
-		goto retry;
-
-	if (has_initialized) {
-		r->initialized = 1;
-		wake_up_interruptible(&random_read_wait);
-		kill_fasync(&fasync, SIGIO, POLL_IN);
-	}
+	chacha_init_consts(chacha_state);
+	memcpy(&chacha_state[4], key, CHACHA_KEY_SIZE);
+	memset(&chacha_state[12], 0, sizeof(u32) * 4);
+	chacha20_block(chacha_state, first_block);
 
-	trace_credit_entropy_bits(r->name, nbits,
-				  entropy_count >> ENTROPY_SHIFT, _RET_IP_);
-
-	if (r == &input_pool) {
-		int entropy_bits = entropy_count >> ENTROPY_SHIFT;
-		struct entropy_store *other = &blocking_pool;
-
-		if (crng_init < 2) {
-			if (entropy_bits < 128)
-				return;
-			crng_reseed(&primary_crng, r);
-			entropy_bits = r->entropy_count >> ENTROPY_SHIFT;
-		}
-
-		/* initialize the blocking pool if necessary */
-		if (entropy_bits >= random_read_wakeup_bits &&
-		    !other->initialized) {
-			schedule_work(&other->push_work);
-			return;
-		}
-
-		/* should we wake readers? */
-		if (entropy_bits >= random_read_wakeup_bits &&
-		    wq_has_sleeper(&random_read_wait)) {
-			wake_up_interruptible(&random_read_wait);
-			kill_fasync(&fasync, SIGIO, POLL_IN);
-		}
-		/* If the input pool is getting full, and the blocking
-		 * pool has room, send some entropy to the blocking
-		 * pool.
-		 */
-		if (!work_pending(&other->push_work) &&
-		    (ENTROPY_BITS(r) > 6 * r->poolinfo->poolbytes) &&
-		    (ENTROPY_BITS(other) <= 6 * other->poolinfo->poolbytes))
-			schedule_work(&other->push_work);
-	}
+	memcpy(key, first_block, CHACHA_KEY_SIZE);
+	memcpy(random_data, first_block + CHACHA_KEY_SIZE, random_data_len);
+	memzero_explicit(first_block, sizeof(first_block));
 }
 
-static int credit_entropy_bits_safe(struct entropy_store *r, int nbits)
+/*
+ * Return whether the crng seed is considered to be sufficiently old
+ * that a reseeding is needed. This happens if the last reseeding
+ * was CRNG_RESEED_INTERVAL ago, or during early boot, at an interval
+ * proportional to the uptime.
+ */
+static bool crng_has_old_seed(void)
 {
-	const int nbits_max = r->poolinfo->poolwords * 32;
+	static bool early_boot = true;
+	unsigned long interval = CRNG_RESEED_INTERVAL;
 
-	if (nbits < 0)
-		return -EINVAL;
-
-	/* Cap the value to avoid overflows */
-	nbits = min(nbits,  nbits_max);
-
-	credit_entropy_bits(r, nbits);
-	return 0;
+	if (unlikely(READ_ONCE(early_boot))) {
+		time64_t uptime = ktime_get_seconds();
+		if (uptime >= CRNG_RESEED_INTERVAL / HZ * 2)
+			WRITE_ONCE(early_boot, false);
+		else
+			interval = max_t(unsigned int, CRNG_RESEED_START_INTERVAL,
+					 (unsigned int)uptime / 2 * HZ);
+	}
+	return time_is_before_jiffies(READ_ONCE(base_crng.birth) + interval);
 }
 
-/*********************************************************************
- *
- * CRNG using CHACHA20
- *
- *********************************************************************/
-
-#define CRNG_RESEED_INTERVAL (300*HZ)
-
-static DECLARE_WAIT_QUEUE_HEAD(crng_init_wait);
-
-#ifdef CONFIG_NUMA
 /*
- * Hack to deal with crazy userspace progams when they are all trying
- * to access /dev/urandom in parallel.  The programs are almost
- * certainly doing something terribly wrong, but we'll work around
- * their brain damage.
+ * This function returns a ChaCha state that you may use for generating
+ * random data. It also returns up to 32 bytes on its own of random data
+ * that may be used; random_data_len may not be greater than 32.
  */
-static struct crng_state **crng_node_pool __read_mostly;
-#endif
+static void crng_make_state(u32 chacha_state[CHACHA_BLOCK_SIZE / sizeof(u32)],
+			    u8 *random_data, size_t random_data_len)
+{
+	unsigned long flags;
+	struct crng *crng;
 
-static void invalidate_batched_entropy(void);
-static void numa_crng_init(void);
+	BUG_ON(random_data_len > 32);
 
-static bool trust_cpu __ro_after_init = IS_ENABLED(CONFIG_RANDOM_TRUST_CPU);
-static int __init parse_trust_cpu(char *arg)
-{
-	return kstrtobool(arg, &trust_cpu);
-}
-early_param("random.trust_cpu", parse_trust_cpu);
+	/*
+	 * For the fast path, we check whether we're ready, unlocked first, and
+	 * then re-check once locked later. In the case where we're really not
+	 * ready, we do fast key erasure with the base_crng directly, extracting
+	 * when crng_init is CRNG_EMPTY.
+	 */
+	if (!crng_ready()) {
+		bool ready;
 
-static void crng_initialize(struct crng_state *crng)
-{
-	int		i;
-	int		arch_init = 1;
-	unsigned long	rv;
-
-	memcpy(&crng->state[0], "expand 32-byte k", 16);
-	if (crng == &primary_crng)
-		_extract_entropy(&input_pool, &crng->state[4],
-				 sizeof(__u32) * 12, 0);
-	else
-		_get_random_bytes(&crng->state[4], sizeof(__u32) * 12);
-	for (i = 4; i < 16; i++) {
-		if (!arch_get_random_seed_long(&rv) &&
-		    !arch_get_random_long(&rv)) {
-			rv = random_get_entropy();
-			arch_init = 0;
+		spin_lock_irqsave(&base_crng.lock, flags);
+		ready = crng_ready();
+		if (!ready) {
+			if (crng_init == CRNG_EMPTY)
+				extract_entropy(base_crng.key, sizeof(base_crng.key));
+			crng_fast_key_erasure(base_crng.key, chacha_state,
+					      random_data, random_data_len);
 		}
-		crng->state[i] ^= rv;
+		spin_unlock_irqrestore(&base_crng.lock, flags);
+		if (!ready)
+			return;
 	}
-	if (trust_cpu && arch_init && crng == &primary_crng) {
-		invalidate_batched_entropy();
-		numa_crng_init();
-		crng_init = 2;
-		pr_notice("random: crng done (trusting CPU's manufacturer)\n");
+
+	/*
+	 * If the base_crng is old enough, we reseed, which in turn bumps the
+	 * generation counter that we check below.
+	 */
+	if (unlikely(crng_has_old_seed()))
+		crng_reseed();
+
+	local_irq_save(flags);
+	crng = raw_cpu_ptr(&crngs);
+
+	/*
+	 * If our per-cpu crng is older than the base_crng, then it means
+	 * somebody reseeded the base_crng. In that case, we do fast key
+	 * erasure on the base_crng, and use its output as the new key
+	 * for our per-cpu crng. This brings us up to date with base_crng.
+	 */
+	if (unlikely(crng->generation != READ_ONCE(base_crng.generation))) {
+		spin_lock(&base_crng.lock);
+		crng_fast_key_erasure(base_crng.key, chacha_state,
+				      crng->key, sizeof(crng->key));
+		crng->generation = base_crng.generation;
+		spin_unlock(&base_crng.lock);
 	}
-	crng->init_time = jiffies - CRNG_RESEED_INTERVAL - 1;
+
+	/*
+	 * Finally, when we've made it this far, our per-cpu crng has an up
+	 * to date key, and we can do fast key erasure with it to produce
+	 * some random data and a ChaCha state for the caller. All other
+	 * branches of this function are "unlikely", so most of the time we
+	 * should wind up here immediately.
+	 */
+	crng_fast_key_erasure(crng->key, chacha_state, random_data, random_data_len);
+	local_irq_restore(flags);
 }
 
-#ifdef CONFIG_NUMA
-static void do_numa_crng_init(struct work_struct *work)
+static void _get_random_bytes(void *buf, size_t len)
 {
-	int i;
-	struct crng_state *crng;
-	struct crng_state **pool;
+	u32 chacha_state[CHACHA_BLOCK_SIZE / sizeof(u32)];
+	u8 tmp[CHACHA_BLOCK_SIZE];
+	size_t first_block_len;
 
-	pool = kcalloc(nr_node_ids, sizeof(*pool), GFP_KERNEL|__GFP_NOFAIL);
-	for_each_online_node(i) {
-		crng = kmalloc_node(sizeof(struct crng_state),
-				    GFP_KERNEL | __GFP_NOFAIL, i);
-		spin_lock_init(&crng->lock);
-		crng_initialize(crng);
-		pool[i] = crng;
-	}
-	mb();
-	if (cmpxchg(&crng_node_pool, NULL, pool)) {
-		for_each_node(i)
-			kfree(pool[i]);
-		kfree(pool);
-	}
-}
+	if (!len)
+		return;
 
-static DECLARE_WORK(numa_crng_init_work, do_numa_crng_init);
+	first_block_len = min_t(size_t, 32, len);
+	crng_make_state(chacha_state, buf, first_block_len);
+	len -= first_block_len;
+	buf += first_block_len;
+
+	while (len) {
+		if (len < CHACHA_BLOCK_SIZE) {
+			chacha20_block(chacha_state, tmp);
+			memcpy(buf, tmp, len);
+			memzero_explicit(tmp, sizeof(tmp));
+			break;
+		}
 
-static void numa_crng_init(void)
-{
-	schedule_work(&numa_crng_init_work);
+		chacha20_block(chacha_state, buf);
+		if (unlikely(chacha_state[12] == 0))
+			++chacha_state[13];
+		len -= CHACHA_BLOCK_SIZE;
+		buf += CHACHA_BLOCK_SIZE;
+	}
+
+	memzero_explicit(chacha_state, sizeof(chacha_state));
 }
-#else
-static void numa_crng_init(void) {}
-#endif
 
 /*
- * crng_fast_load() can be called by code in the interrupt service
- * path.  So we can't afford to dilly-dally.
+ * This function is the exported kernel interface.  It returns some
+ * number of good random numbers, suitable for key generation, seeding
+ * TCP sequence numbers, etc.  It does not rely on the hardware random
+ * number generator.  For random bytes direct from the hardware RNG
+ * (when available), use get_random_bytes_arch(). In order to ensure
+ * that the randomness provided by this function is okay, the function
+ * wait_for_random_bytes() should be called and return 0 at least once
+ * at any point prior.
  */
-static int crng_fast_load(const char *cp, size_t len)
+void get_random_bytes(void *buf, size_t len)
 {
-	unsigned long flags;
-	char *p;
-
-	if (!spin_trylock_irqsave(&primary_crng.lock, flags))
-		return 0;
-	if (crng_init != 0) {
-		spin_unlock_irqrestore(&primary_crng.lock, flags);
-		return 0;
-	}
-	p = (unsigned char *) &primary_crng.state[4];
-	while (len > 0 && crng_init_cnt < CRNG_INIT_CNT_THRESH) {
-		p[crng_init_cnt % CHACHA_KEY_SIZE] ^= *cp;
-		cp++; crng_init_cnt++; len--;
-	}
-	spin_unlock_irqrestore(&primary_crng.lock, flags);
-	if (crng_init_cnt >= CRNG_INIT_CNT_THRESH) {
-		invalidate_batched_entropy();
-		crng_init = 1;
-		wake_up_interruptible(&crng_init_wait);
-		pr_notice("random: fast init done\n");
-	}
-	return 1;
+	warn_unseeded_randomness();
+	_get_random_bytes(buf, len);
 }
+EXPORT_SYMBOL(get_random_bytes);
 
-/*
- * crng_slow_load() is called by add_device_randomness, which has two
- * attributes.  (1) We can't trust the buffer passed to it is
- * guaranteed to be unpredictable (so it might not have any entropy at
- * all), and (2) it doesn't have the performance constraints of
- * crng_fast_load().
- *
- * So we do something more comprehensive which is guaranteed to touch
- * all of the primary_crng's state, and which uses a LFSR with a
- * period of 255 as part of the mixing algorithm.  Finally, we do
- * *not* advance crng_init_cnt since buffer we may get may be something
- * like a fixed DMI table (for example), which might very well be
- * unique to the machine, but is otherwise unvarying.
- */
-static int crng_slow_load(const char *cp, size_t len)
+static ssize_t get_random_bytes_user(struct iov_iter *iter)
 {
-	unsigned long		flags;
-	static unsigned char	lfsr = 1;
-	unsigned char		tmp;
-	unsigned		i, max = CHACHA_KEY_SIZE;
-	const char *		src_buf = cp;
-	char *			dest_buf = (char *) &primary_crng.state[4];
+	u32 chacha_state[CHACHA_BLOCK_SIZE / sizeof(u32)];
+	u8 block[CHACHA_BLOCK_SIZE];
+	size_t ret = 0, copied;
 
-	if (!spin_trylock_irqsave(&primary_crng.lock, flags))
-		return 0;
-	if (crng_init != 0) {
-		spin_unlock_irqrestore(&primary_crng.lock, flags);
+	if (unlikely(!iov_iter_count(iter)))
 		return 0;
+
+	/*
+	 * Immediately overwrite the ChaCha key at index 4 with random
+	 * bytes, in case userspace causes copy_to_iter() below to sleep
+	 * forever, so that we still retain forward secrecy in that case.
+	 */
+	crng_make_state(chacha_state, (u8 *)&chacha_state[4], CHACHA_KEY_SIZE);
+	/*
+	 * However, if we're doing a read of len <= 32, we don't need to
+	 * use chacha_state after, so we can simply return those bytes to
+	 * the user directly.
+	 */
+	if (iov_iter_count(iter) <= CHACHA_KEY_SIZE) {
+		ret = copy_to_iter(&chacha_state[4], CHACHA_KEY_SIZE, iter);
+		goto out_zero_chacha;
 	}
-	if (len > max)
-		max = len;
 
-	for (i = 0; i < max ; i++) {
-		tmp = lfsr;
-		lfsr >>= 1;
-		if (tmp & 1)
-			lfsr ^= 0xE1;
-		tmp = dest_buf[i % CHACHA_KEY_SIZE];
-		dest_buf[i % CHACHA_KEY_SIZE] ^= src_buf[i % len] ^ lfsr;
-		lfsr += (tmp << 3) | (tmp >> 5);
-	}
-	spin_unlock_irqrestore(&primary_crng.lock, flags);
-	return 1;
-}
-
-static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
-{
-	unsigned long	flags;
-	int		i, num;
-	union {
-		__u8	block[CHACHA_BLOCK_SIZE];
-		__u32	key[8];
-	} buf;
-
-	if (r) {
-		num = extract_entropy(r, &buf, 32, 16, 0);
-		if (num == 0)
-			return;
-	} else {
-		_extract_crng(&primary_crng, buf.block);
-		_crng_backtrack_protect(&primary_crng, buf.block,
-					CHACHA_KEY_SIZE);
-	}
-	spin_lock_irqsave(&crng->lock, flags);
-	for (i = 0; i < 8; i++) {
-		unsigned long	rv;
-		if (!arch_get_random_seed_long(&rv) &&
-		    !arch_get_random_long(&rv))
-			rv = random_get_entropy();
-		crng->state[i+4] ^= buf.key[i] ^ rv;
-	}
-	memzero_explicit(&buf, sizeof(buf));
-	crng->init_time = jiffies;
-	spin_unlock_irqrestore(&crng->lock, flags);
-	if (crng == &primary_crng && crng_init < 2) {
-		invalidate_batched_entropy();
-		numa_crng_init();
-		crng_init = 2;
-		process_random_ready_list();
-		wake_up_interruptible(&crng_init_wait);
-		pr_notice("random: crng init done\n");
-		if (unseeded_warning.missed) {
-			pr_notice("random: %d get_random_xx warning(s) missed "
-				  "due to ratelimiting\n",
-				  unseeded_warning.missed);
-			unseeded_warning.missed = 0;
-		}
-		if (urandom_warning.missed) {
-			pr_notice("random: %d urandom warning(s) missed "
-				  "due to ratelimiting\n",
-				  urandom_warning.missed);
-			urandom_warning.missed = 0;
+	for (;;) {
+		chacha20_block(chacha_state, block);
+		if (unlikely(chacha_state[12] == 0))
+			++chacha_state[13];
+
+		copied = copy_to_iter(block, sizeof(block), iter);
+		ret += copied;
+		if (!iov_iter_count(iter) || copied != sizeof(block))
+			break;
+
+		BUILD_BUG_ON(PAGE_SIZE % sizeof(block) != 0);
+		if (ret % PAGE_SIZE == 0) {
+			if (signal_pending(current))
+				break;
+			cond_resched();
 		}
 	}
-}
 
-static void _extract_crng(struct crng_state *crng,
-			  __u8 out[CHACHA_BLOCK_SIZE])
-{
-	unsigned long v, flags;
-
-	if (crng_ready() &&
-	    (time_after(crng_global_init_time, crng->init_time) ||
-	     time_after(jiffies, crng->init_time + CRNG_RESEED_INTERVAL)))
-		crng_reseed(crng, crng == &primary_crng ? &input_pool : NULL);
-	spin_lock_irqsave(&crng->lock, flags);
-	if (arch_get_random_long(&v))
-		crng->state[14] ^= v;
-	chacha20_block(&crng->state[0], out);
-	if (crng->state[12] == 0)
-		crng->state[13]++;
-	spin_unlock_irqrestore(&crng->lock, flags);
-}
-
-static void extract_crng(__u8 out[CHACHA_BLOCK_SIZE])
-{
-	struct crng_state *crng = NULL;
-
-#ifdef CONFIG_NUMA
-	if (crng_node_pool)
-		crng = crng_node_pool[numa_node_id()];
-	if (crng == NULL)
-#endif
-		crng = &primary_crng;
-	_extract_crng(crng, out);
-}
+	memzero_explicit(block, sizeof(block));
+out_zero_chacha:
+	memzero_explicit(chacha_state, sizeof(chacha_state));
+	return ret ? ret : -EFAULT;
+}
+
+/*
+ * Batched entropy returns random integers. The quality of the random
+ * number is good as /dev/urandom. In order to ensure that the randomness
+ * provided by this function is okay, the function wait_for_random_bytes()
+ * should be called and return 0 at least once at any point prior.
+ */
+
+#define DEFINE_BATCHED_ENTROPY(type)						\
+struct batch_ ##type {								\
+	/*									\
+	 * We make this 1.5x a ChaCha block, so that we get the			\
+	 * remaining 32 bytes from fast key erasure, plus one full		\
+	 * block from the detached ChaCha state. We can increase		\
+	 * the size of this later if needed so long as we keep the		\
+	 * formula of (integer_blocks + 0.5) * CHACHA_BLOCK_SIZE.		\
+	 */									\
+	type entropy[CHACHA_BLOCK_SIZE * 3 / (2 * sizeof(type))];		\
+	unsigned long generation;						\
+	unsigned int position;							\
+};										\
+										\
+static DEFINE_PER_CPU(struct batch_ ##type, batched_entropy_ ##type) = {	\
+	.position = UINT_MAX							\
+};										\
+										\
+type get_random_ ##type(void)							\
+{										\
+	type ret;								\
+	unsigned long flags;							\
+	struct batch_ ##type *batch;						\
+	unsigned long next_gen;							\
+										\
+	warn_unseeded_randomness();						\
+										\
+	if  (!crng_ready()) {							\
+		_get_random_bytes(&ret, sizeof(ret));				\
+		return ret;							\
+	}									\
+										\
+	local_irq_save(flags);		\
+	batch = raw_cpu_ptr(&batched_entropy_##type);				\
+										\
+	next_gen = READ_ONCE(base_crng.generation);				\
+	if (batch->position >= ARRAY_SIZE(batch->entropy) ||			\
+	    next_gen != batch->generation) {					\
+		_get_random_bytes(batch->entropy, sizeof(batch->entropy));	\
+		batch->position = 0;						\
+		batch->generation = next_gen;					\
+	}									\
+										\
+	ret = batch->entropy[batch->position];					\
+	batch->entropy[batch->position] = 0;					\
+	++batch->position;							\
+	local_irq_restore(flags);		\
+	return ret;								\
+}										\
+EXPORT_SYMBOL(get_random_ ##type);
+
+DEFINE_BATCHED_ENTROPY(u64)
+DEFINE_BATCHED_ENTROPY(u32)
 
+#ifdef CONFIG_SMP
 /*
- * Use the leftover bytes from the CRNG block output (if there is
- * enough) to mutate the CRNG key to provide backtracking protection.
+ * This function is called when the CPU is coming up, with entry
+ * CPUHP_RANDOM_PREPARE, which comes before CPUHP_WORKQUEUE_PREP.
  */
-static void _crng_backtrack_protect(struct crng_state *crng,
-				    __u8 tmp[CHACHA_BLOCK_SIZE], int used)
+int __cold random_prepare_cpu(unsigned int cpu)
 {
-	unsigned long	flags;
-	__u32		*s, *d;
-	int		i;
-
-	used = round_up(used, sizeof(__u32));
-	if (used + CHACHA_KEY_SIZE > CHACHA_BLOCK_SIZE) {
-		extract_crng(tmp);
-		used = 0;
-	}
-	spin_lock_irqsave(&crng->lock, flags);
-	s = (__u32 *) &tmp[used];
-	d = &crng->state[4];
-	for (i=0; i < 8; i++)
-		*d++ ^= *s++;
-	spin_unlock_irqrestore(&crng->lock, flags);
+	/*
+	 * When the cpu comes back online, immediately invalidate both
+	 * the per-cpu crng and all batches, so that we serve fresh
+	 * randomness.
+	 */
+	per_cpu_ptr(&crngs, cpu)->generation = ULONG_MAX;
+	per_cpu_ptr(&batched_entropy_u32, cpu)->position = UINT_MAX;
+	per_cpu_ptr(&batched_entropy_u64, cpu)->position = UINT_MAX;
+	return 0;
 }
-
-static void crng_backtrack_protect(__u8 tmp[CHACHA_BLOCK_SIZE], int used)
-{
-	struct crng_state *crng = NULL;
-
-#ifdef CONFIG_NUMA
-	if (crng_node_pool)
-		crng = crng_node_pool[numa_node_id()];
-	if (crng == NULL)
 #endif
-		crng = &primary_crng;
-	_crng_backtrack_protect(crng, tmp, used);
-}
 
-static ssize_t extract_crng_user(void __user *buf, size_t nbytes)
+/*
+ * This function will use the architecture-specific hardware random
+ * number generator if it is available. It is not recommended for
+ * use. Use get_random_bytes() instead. It returns the number of
+ * bytes filled in.
+ */
+size_t __must_check get_random_bytes_arch(void *buf, size_t len)
 {
-	ssize_t ret = 0, i = CHACHA_BLOCK_SIZE;
-	__u8 tmp[CHACHA_BLOCK_SIZE] __aligned(4);
-	int large_request = (nbytes > 256);
+	size_t left = len;
+	u8 *p = buf;
 
-	while (nbytes) {
-		if (large_request && need_resched()) {
-			if (signal_pending(current)) {
-				if (ret == 0)
-					ret = -ERESTARTSYS;
-				break;
-			}
-			schedule();
-		}
+	while (left) {
+		unsigned long v;
+		size_t block_len = min_t(size_t, left, sizeof(unsigned long));
 
-		extract_crng(tmp);
-		i = min_t(int, nbytes, CHACHA_BLOCK_SIZE);
-		if (copy_to_user(buf, tmp, i)) {
-			ret = -EFAULT;
+		if (!arch_get_random_long(&v))
 			break;
-		}
 
-		nbytes -= i;
-		buf += i;
-		ret += i;
+		memcpy(p, &v, block_len);
+		p += block_len;
+		left -= block_len;
 	}
-	crng_backtrack_protect(tmp, i);
-
-	/* Wipe data just written to memory */
-	memzero_explicit(tmp, sizeof(tmp));
 
-	return ret;
+	return len - left;
 }
+EXPORT_SYMBOL(get_random_bytes_arch);
 
 
-/*********************************************************************
+/**********************************************************************
  *
- * Entropy input management
+ * Entropy accumulation and extraction routines.
  *
- *********************************************************************/
+ * Callers may add entropy via:
+ *
+ *     static void mix_pool_bytes(const void *buf, size_t len)
+ *
+ * After which, if added entropy should be credited:
+ *
+ *     static void credit_init_bits(size_t bits)
+ *
+ * Finally, extract entropy via:
+ *
+ *     static void extract_entropy(void *buf, size_t len)
+ *
+ **********************************************************************/
 
-/* There is one of these per entropy source */
-struct timer_rand_state {
-	cycles_t last_time;
-	long last_delta, last_delta2;
+enum {
+	POOL_BITS = BLAKE2S_HASH_SIZE * 8,
+	POOL_READY_BITS = POOL_BITS, /* When crng_init->CRNG_READY */
+	POOL_EARLY_BITS = POOL_READY_BITS / 2 /* When crng_init->CRNG_EARLY */
+};
+
+static struct {
+	struct blake2s_state hash;
+	spinlock_t lock;
+	unsigned int init_bits;
+} input_pool = {
+	.hash.h = { BLAKE2S_IV0 ^ (0x01010000 | BLAKE2S_HASH_SIZE),
+		    BLAKE2S_IV1, BLAKE2S_IV2, BLAKE2S_IV3, BLAKE2S_IV4,
+		    BLAKE2S_IV5, BLAKE2S_IV6, BLAKE2S_IV7 },
+	.hash.outlen = BLAKE2S_HASH_SIZE,
+	.lock = __SPIN_LOCK_UNLOCKED(input_pool.lock),
 };
 
-#define INIT_TIMER_RAND_STATE { INITIAL_JIFFIES, };
+static void _mix_pool_bytes(const void *buf, size_t len)
+{
+	blake2s_update(&input_pool.hash, buf, len);
+}
 
 /*
- * Add device- or boot-specific data to the input pool to help
- * initialize it.
- *
- * None of this adds any entropy; it is meant to avoid the problem of
- * the entropy pool having similar initial state across largely
- * identical devices.
+ * This function adds bytes into the input pool. It does not
+ * update the initialization bit counter; the caller should call
+ * credit_init_bits if this is appropriate.
  */
-void add_device_randomness(const void *buf, unsigned int size)
+static void mix_pool_bytes(const void *buf, size_t len)
 {
-	unsigned long time = random_get_entropy() ^ jiffies;
 	unsigned long flags;
 
-	if (!crng_ready() && size)
-		crng_slow_load(buf, size);
-
-	trace_add_device_randomness(size, _RET_IP_);
 	spin_lock_irqsave(&input_pool.lock, flags);
-	_mix_pool_bytes(&input_pool, buf, size);
-	_mix_pool_bytes(&input_pool, &time, sizeof(time));
+	_mix_pool_bytes(buf, len);
 	spin_unlock_irqrestore(&input_pool.lock, flags);
 }
-EXPORT_SYMBOL(add_device_randomness);
-
-static struct timer_rand_state input_timer_state = INIT_TIMER_RAND_STATE;
 
 /*
- * This function adds entropy to the entropy "pool" by using timing
- * delays.  It uses the timer_rand_state structure to make an estimate
- * of how many bits of entropy this call has added to the pool.
- *
- * The number "num" is also added to the pool - it should somehow describe
- * the type of event which just happened.  This is currently 0-255 for
- * keyboard scan codes, and 256 upwards for interrupts.
- *
+ * This is an HKDF-like construction for using the hashed collected entropy
+ * as a PRF key, that's then expanded block-by-block.
  */
-static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
+static void extract_entropy(void *buf, size_t len)
 {
-	struct entropy_store	*r;
+	unsigned long flags;
+	u8 seed[BLAKE2S_HASH_SIZE], next_key[BLAKE2S_HASH_SIZE];
 	struct {
-		long jiffies;
-		unsigned cycles;
-		unsigned num;
-	} sample;
-	long delta, delta2, delta3;
-
-	sample.jiffies = jiffies;
-	sample.cycles = random_get_entropy();
-	sample.num = num;
-	r = &input_pool;
-	mix_pool_bytes(r, &sample, sizeof(sample));
-
-	/*
-	 * Calculate number of bits of randomness we probably added.
-	 * We take into account the first, second and third-order deltas
-	 * in order to make our estimate.
-	 */
-	delta = sample.jiffies - state->last_time;
-	state->last_time = sample.jiffies;
+		unsigned long rdseed[32 / sizeof(long)];
+		size_t counter;
+	} block;
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(block.rdseed); ++i) {
+		if (!arch_get_random_seed_long(&block.rdseed[i]) &&
+		    !arch_get_random_long(&block.rdseed[i]))
+			block.rdseed[i] = random_get_entropy();
+	}
 
-	delta2 = delta - state->last_delta;
-	state->last_delta = delta;
+	spin_lock_irqsave(&input_pool.lock, flags);
 
-	delta3 = delta2 - state->last_delta2;
-	state->last_delta2 = delta2;
+	/* seed = HASHPRF(last_key, entropy_input) */
+	blake2s_final(&input_pool.hash, seed);
 
-	if (delta < 0)
-		delta = -delta;
-	if (delta2 < 0)
-		delta2 = -delta2;
-	if (delta3 < 0)
-		delta3 = -delta3;
-	if (delta > delta2)
-		delta = delta2;
-	if (delta > delta3)
-		delta = delta3;
-
-	/*
-	 * delta is now minimum absolute delta.
-	 * Round down by 1 bit on general principles,
-	 * and limit entropy entimate to 12 bits.
-	 */
-	credit_entropy_bits(r, min_t(int, fls(delta>>1), 11));
-}
+	/* next_key = HASHPRF(seed, RDSEED || 0) */
+	block.counter = 0;
+	blake2s(next_key, (u8 *)&block, seed, sizeof(next_key), sizeof(block), sizeof(seed));
+	blake2s_init_key(&input_pool.hash, BLAKE2S_HASH_SIZE, next_key, sizeof(next_key));
 
-void add_input_randomness(unsigned int type, unsigned int code,
-				 unsigned int value)
-{
-	static unsigned char last_value;
+	spin_unlock_irqrestore(&input_pool.lock, flags);
+	memzero_explicit(next_key, sizeof(next_key));
 
-	/* ignore autorepeat and the like */
-	if (value == last_value)
-		return;
+	while (len) {
+		i = min_t(size_t, len, BLAKE2S_HASH_SIZE);
+		/* output = HASHPRF(seed, RDSEED || ++counter) */
+		++block.counter;
+		blake2s(buf, (u8 *)&block, seed, i, sizeof(block), sizeof(seed));
+		len -= i;
+		buf += i;
+	}
 
-	last_value = value;
-	add_timer_randomness(&input_timer_state,
-			     (type << 4) ^ code ^ (code >> 4) ^ value);
-	trace_add_input_randomness(ENTROPY_BITS(&input_pool));
+	memzero_explicit(seed, sizeof(seed));
+	memzero_explicit(&block, sizeof(block));
 }
-EXPORT_SYMBOL_GPL(add_input_randomness);
-
-static DEFINE_PER_CPU(struct fast_pool, irq_randomness);
-
-#ifdef ADD_INTERRUPT_BENCH
-static unsigned long avg_cycles, avg_deviation;
 
-#define AVG_SHIFT 8     /* Exponential average factor k=1/256 */
-#define FIXED_1_2 (1 << (AVG_SHIFT-1))
+#define credit_init_bits(bits) if (!crng_ready()) _credit_init_bits(bits)
 
-static void add_interrupt_bench(cycles_t start)
+static void __cold _credit_init_bits(size_t bits)
 {
-        long delta = random_get_entropy() - start;
-
-        /* Use a weighted moving average */
-        delta = delta - ((avg_cycles + FIXED_1_2) >> AVG_SHIFT);
-        avg_cycles += delta;
-        /* And average deviation */
-        delta = abs(delta) - ((avg_deviation + FIXED_1_2) >> AVG_SHIFT);
-        avg_deviation += delta;
-}
-#else
-#define add_interrupt_bench(x)
-#endif
-
-static __u32 get_reg(struct fast_pool *f, struct pt_regs *regs)
-{
-	__u32 *ptr = (__u32 *) regs;
-	unsigned int idx;
-
-	if (regs == NULL)
-		return 0;
-	idx = READ_ONCE(f->reg_idx);
-	if (idx >= sizeof(struct pt_regs) / sizeof(__u32))
-		idx = 0;
-	ptr += idx++;
-	WRITE_ONCE(f->reg_idx, idx);
-	return *ptr;
-}
-
-void add_interrupt_randomness(int irq, int irq_flags)
-{
-	struct entropy_store	*r;
-	struct fast_pool	*fast_pool = this_cpu_ptr(&irq_randomness);
-	struct pt_regs		*regs = get_irq_regs();
-	unsigned long		now = jiffies;
-	cycles_t		cycles = random_get_entropy();
-	__u32			c_high, j_high;
-	__u64			ip;
-	unsigned long		seed;
-	int			credit = 0;
-
-	if (cycles == 0)
-		cycles = get_reg(fast_pool, regs);
-	c_high = (sizeof(cycles) > 4) ? cycles >> 32 : 0;
-	j_high = (sizeof(now) > 4) ? now >> 32 : 0;
-	fast_pool->pool[0] ^= cycles ^ j_high ^ irq;
-	fast_pool->pool[1] ^= now ^ c_high;
-	ip = regs ? instruction_pointer(regs) : _RET_IP_;
-	fast_pool->pool[2] ^= ip;
-	fast_pool->pool[3] ^= (sizeof(ip) > 4) ? ip >> 32 :
-		get_reg(fast_pool, regs);
-
-	fast_mix(fast_pool);
-	add_interrupt_bench(cycles);
-
-	if (unlikely(crng_init == 0)) {
-		if ((fast_pool->count >= 64) &&
-		    crng_fast_load((char *) fast_pool->pool,
-				   sizeof(fast_pool->pool))) {
-			fast_pool->count = 0;
-			fast_pool->last = now;
-		}
-		return;
-	}
+	unsigned int new, orig, add;
+	unsigned long flags;
 
-	if ((fast_pool->count < 64) &&
-	    !time_after(now, fast_pool->last + HZ))
+	if (!bits)
 		return;
 
-	r = &input_pool;
-	if (!spin_trylock(&r->lock))
-		return;
+	add = min_t(size_t, bits, POOL_BITS);
 
-	fast_pool->last = now;
-	__mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool));
+	do {
+		orig = READ_ONCE(input_pool.init_bits);
+		new = min_t(unsigned int, POOL_BITS, orig + add);
+	} while (cmpxchg(&input_pool.init_bits, orig, new) != orig);
 
-	/*
-	 * If we have architectural seed generator, produce a seed and
-	 * add it to the pool.  For the sake of paranoia don't let the
-	 * architectural seed generator dominate the input from the
-	 * interrupt noise.
-	 */
-	if (arch_get_random_seed_long(&seed)) {
-		__mix_pool_bytes(r, &seed, sizeof(seed));
-		credit = 1;
+	if (orig < POOL_READY_BITS && new >= POOL_READY_BITS) {
+		crng_reseed(); /* Sets crng_init to CRNG_READY under base_crng.lock. */
+		process_random_ready_list();
+		wake_up_interruptible(&crng_init_wait);
+		kill_fasync(&fasync, SIGIO, POLL_IN);
+		pr_notice("crng init done\n");
+		if (urandom_warning.missed)
+			pr_notice("%d urandom warning(s) missed due to ratelimiting\n",
+				  urandom_warning.missed);
+	} else if (orig < POOL_EARLY_BITS && new >= POOL_EARLY_BITS) {
+		spin_lock_irqsave(&base_crng.lock, flags);
+		/* Check if crng_init is CRNG_EMPTY, to avoid race with crng_reseed(). */
+		if (crng_init == CRNG_EMPTY) {
+			extract_entropy(base_crng.key, sizeof(base_crng.key));
+			crng_init = CRNG_EARLY;
+		}
+		spin_unlock_irqrestore(&base_crng.lock, flags);
 	}
-	spin_unlock(&r->lock);
-
-	fast_pool->count = 0;
-
-	/* award one bit for the contents of the fast pool */
-	credit_entropy_bits(r, credit + 1);
 }
-EXPORT_SYMBOL_GPL(add_interrupt_randomness);
 
-#ifdef CONFIG_BLOCK
-void add_disk_randomness(struct gendisk *disk)
-{
-	if (!disk || !disk->random)
-		return;
-	/* first major is 1, so we get >= 0x200 here */
-	add_timer_randomness(disk->random, 0x100 + disk_devt(disk));
-	trace_add_disk_randomness(disk_devt(disk), ENTROPY_BITS(&input_pool));
-}
-EXPORT_SYMBOL_GPL(add_disk_randomness);
-#endif
 
-/*********************************************************************
+/**********************************************************************
  *
- * Entropy extraction routines
+ * Entropy collection routines.
  *
- *********************************************************************/
-
-/*
- * This utility inline function is responsible for transferring entropy
- * from the primary pool to the secondary extraction pool. We make
- * sure we pull enough for a 'catastrophic reseed'.
- */
-static void _xfer_secondary_pool(struct entropy_store *r, size_t nbytes);
-static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
-{
-	if (!r->pull ||
-	    r->entropy_count >= (nbytes << (ENTROPY_SHIFT + 3)) ||
-	    r->entropy_count > r->poolinfo->poolfracbits)
-		return;
+ * The following exported functions are used for pushing entropy into
+ * the above entropy accumulation routines:
+ *
+ *	void add_device_randomness(const void *buf, size_t len);
+ *	void add_hwgenerator_randomness(const void *buf, size_t len, size_t entropy);
+ *	void add_bootloader_randomness(const void *buf, size_t len);
+ *	void add_interrupt_randomness(int irq);
+ *	void add_input_randomness(unsigned int type, unsigned int code, unsigned int value);
+ *	void add_disk_randomness(struct gendisk *disk);
+ *
+ * add_device_randomness() adds data to the input pool that
+ * is likely to differ between two devices (or possibly even per boot).
+ * This would be things like MAC addresses or serial numbers, or the
+ * read-out of the RTC. This does *not* credit any actual entropy to
+ * the pool, but it initializes the pool to different values for devices
+ * that might otherwise be identical and have very little entropy
+ * available to them (particularly common in the embedded world).
+ *
+ * add_hwgenerator_randomness() is for true hardware RNGs, and will credit
+ * entropy as specified by the caller. If the entropy pool is full it will
+ * block until more entropy is needed.
+ *
+ * add_bootloader_randomness() is called by bootloader drivers, such as EFI
+ * and device tree, and credits its input depending on whether or not the
+ * configuration option CONFIG_RANDOM_TRUST_BOOTLOADER is set.
+ *
+ * add_interrupt_randomness() uses the interrupt timing as random
+ * inputs to the entropy pool. Using the cycle counters and the irq source
+ * as inputs, it feeds the input pool roughly once a second or after 64
+ * interrupts, crediting 1 bit of entropy for whichever comes first.
+ *
+ * add_input_randomness() uses the input layer interrupt timing, as well
+ * as the event type information from the hardware.
+ *
+ * add_disk_randomness() uses what amounts to the seek time of block
+ * layer request events, on a per-disk_devt basis, as input to the
+ * entropy pool. Note that high-speed solid state drives with very low
+ * seek times do not make for good sources of entropy, as their seek
+ * times are usually fairly consistent.
+ *
+ * The last two routines try to estimate how many bits of entropy
+ * to credit. They do this by keeping track of the first and second
+ * order deltas of the event timings.
+ *
+ **********************************************************************/
 
-	_xfer_secondary_pool(r, nbytes);
+static bool trust_cpu __initdata = IS_ENABLED(CONFIG_RANDOM_TRUST_CPU);
+static bool trust_bootloader __initdata = IS_ENABLED(CONFIG_RANDOM_TRUST_BOOTLOADER);
+static int __init parse_trust_cpu(char *arg)
+{
+	return kstrtobool(arg, &trust_cpu);
 }
+static int __init parse_trust_bootloader(char *arg)
+{
+	return kstrtobool(arg, &trust_bootloader);
+}
+early_param("random.trust_cpu", parse_trust_cpu);
+early_param("random.trust_bootloader", parse_trust_bootloader);
 
-static void _xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
+/*
+ * The first collection of entropy occurs at system boot while interrupts
+ * are still turned off. Here we push in latent entropy, RDSEED, a timestamp,
+ * utsname(), and the command line. Depending on the above configuration knob,
+ * RDSEED may be considered sufficient for initialization. Note that much
+ * earlier setup may already have pushed entropy into the input pool by the
+ * time we get here.
+ */
+int __init random_init(const char *command_line)
 {
-	__u32	tmp[OUTPUT_POOL_WORDS];
+	ktime_t now = ktime_get_real();
+	unsigned int i, arch_bits;
+	unsigned long entropy;
 
-	int bytes = nbytes;
+#if defined(LATENT_ENTROPY_PLUGIN)
+	static const u8 compiletime_seed[BLAKE2S_BLOCK_SIZE] __initconst __latent_entropy;
+	_mix_pool_bytes(compiletime_seed, sizeof(compiletime_seed));
+#endif
 
-	/* pull at least as much as a wakeup */
-	bytes = max_t(int, bytes, random_read_wakeup_bits / 8);
-	/* but never more than the buffer size */
-	bytes = min_t(int, bytes, sizeof(tmp));
+	for (i = 0, arch_bits = BLAKE2S_BLOCK_SIZE * 8;
+	     i < BLAKE2S_BLOCK_SIZE; i += sizeof(entropy)) {
+		if (!arch_get_random_seed_long_early(&entropy) &&
+		    !arch_get_random_long_early(&entropy)) {
+			entropy = random_get_entropy();
+			arch_bits -= sizeof(entropy) * 8;
+		}
+		_mix_pool_bytes(&entropy, sizeof(entropy));
+	}
+	_mix_pool_bytes(&now, sizeof(now));
+	_mix_pool_bytes(utsname(), sizeof(*(utsname())));
+	_mix_pool_bytes(command_line, strlen(command_line));
+	add_latent_entropy();
+
+	if (crng_ready())
+		crng_reseed();
+	else if (trust_cpu)
+		_credit_init_bits(arch_bits);
 
-	trace_xfer_secondary_pool(r->name, bytes * 8, nbytes * 8,
-				  ENTROPY_BITS(r), ENTROPY_BITS(r->pull));
-	bytes = extract_entropy(r->pull, tmp, bytes,
-				random_read_wakeup_bits / 8, 0);
-	mix_pool_bytes(r, tmp, bytes);
-	credit_entropy_bits(r, bytes*8);
+	return 0;
 }
 
 /*
- * Used as a workqueue function so that when the input pool is getting
- * full, we can "spill over" some entropy to the output pools.  That
- * way the output pools can store some of the excess entropy instead
- * of letting it go to waste.
+ * Add device- or boot-specific data to the input pool to help
+ * initialize it.
+ *
+ * None of this adds any entropy; it is meant to avoid the problem of
+ * the entropy pool having similar initial state across largely
+ * identical devices.
  */
-static void push_to_pool(struct work_struct *work)
+void add_device_randomness(const void *buf, size_t len)
 {
-	struct entropy_store *r = container_of(work, struct entropy_store,
-					      push_work);
-	BUG_ON(!r);
-	_xfer_secondary_pool(r, random_read_wakeup_bits/8);
-	trace_push_to_pool(r->name, r->entropy_count >> ENTROPY_SHIFT,
-			   r->pull->entropy_count >> ENTROPY_SHIFT);
+	unsigned long entropy = random_get_entropy();
+	unsigned long flags;
+
+	spin_lock_irqsave(&input_pool.lock, flags);
+	_mix_pool_bytes(&entropy, sizeof(entropy));
+	_mix_pool_bytes(buf, len);
+	spin_unlock_irqrestore(&input_pool.lock, flags);
 }
+EXPORT_SYMBOL(add_device_randomness);
 
 /*
- * This function decides how many bytes to actually take from the
- * given pool, and also debits the entropy count accordingly.
+ * Interface for in-kernel drivers of true hardware RNGs.
+ * Those devices may produce endless random bits and will be throttled
+ * when our pool is full.
  */
-static size_t account(struct entropy_store *r, size_t nbytes, int min,
-		      int reserved)
+void add_hwgenerator_randomness(const void *buf, size_t len, size_t entropy)
 {
-	int entropy_count, orig, have_bytes;
-	size_t ibytes, nfrac;
-
-	BUG_ON(r->entropy_count > r->poolinfo->poolfracbits);
+	mix_pool_bytes(buf, len);
+	credit_init_bits(entropy);
 
-	/* Can we pull enough? */
-retry:
-	entropy_count = orig = READ_ONCE(r->entropy_count);
-	ibytes = nbytes;
-	/* never pull more than available */
-	have_bytes = entropy_count >> (ENTROPY_SHIFT + 3);
+	/*
+	 * Throttle writing to once every CRNG_RESEED_INTERVAL, unless
+	 * we're not yet initialized.
+	 */
+	if (!kthread_should_stop() && crng_ready())
+		schedule_timeout_interruptible(CRNG_RESEED_INTERVAL);
+}
+EXPORT_SYMBOL_GPL(add_hwgenerator_randomness);
 
-	if ((have_bytes -= reserved) < 0)
-		have_bytes = 0;
-	ibytes = min_t(size_t, ibytes, have_bytes);
-	if (ibytes < min)
-		ibytes = 0;
+/*
+ * Handle random seed passed by bootloader, and credit it if
+ * CONFIG_RANDOM_TRUST_BOOTLOADER is set.
+ */
+void __init add_bootloader_randomness(const void *buf, size_t len)
+{
+	mix_pool_bytes(buf, len);
+	if (trust_bootloader)
+		credit_init_bits(len * 8);
+}
 
-	if (unlikely(entropy_count < 0)) {
-		pr_warn("random: negative entropy count: pool %s count %d\n",
-			r->name, entropy_count);
-		WARN_ON(1);
-		entropy_count = 0;
-	}
-	nfrac = ibytes << (ENTROPY_SHIFT + 3);
-	if ((size_t) entropy_count > nfrac)
-		entropy_count -= nfrac;
-	else
-		entropy_count = 0;
+struct fast_pool {
+	unsigned long pool[4];
+	unsigned long last;
+	unsigned int count;
+	struct timer_list mix;
+};
 
-	if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
-		goto retry;
+static void mix_interrupt_randomness(struct timer_list *work);
 
-	trace_debit_entropy(r->name, 8 * ibytes);
-	if (ibytes &&
-	    (r->entropy_count >> ENTROPY_SHIFT) < random_write_wakeup_bits) {
-		wake_up_interruptible(&random_write_wait);
-		kill_fasync(&fasync, SIGIO, POLL_OUT);
-	}
+static DEFINE_PER_CPU(struct fast_pool, irq_randomness) = {
+#ifdef CONFIG_64BIT
+#define FASTMIX_PERM SIPHASH_PERMUTATION
+	.pool = { SIPHASH_CONST_0, SIPHASH_CONST_1, SIPHASH_CONST_2, SIPHASH_CONST_3 },
+#else
+#define FASTMIX_PERM HSIPHASH_PERMUTATION
+	.pool = { HSIPHASH_CONST_0, HSIPHASH_CONST_1, HSIPHASH_CONST_2, HSIPHASH_CONST_3 },
+#endif
+	.mix = __TIMER_INITIALIZER(mix_interrupt_randomness, 0)
+};
 
-	return ibytes;
+/*
+ * This is [Half]SipHash-1-x, starting from an empty key. Because
+ * the key is fixed, it assumes that its inputs are non-malicious,
+ * and therefore this has no security on its own. s represents the
+ * four-word SipHash state, while v represents a two-word input.
+ */
+static void fast_mix(unsigned long s[4], unsigned long v1, unsigned long v2)
+{
+	s[3] ^= v1;
+	FASTMIX_PERM(s[0], s[1], s[2], s[3]);
+	s[0] ^= v1;
+	s[3] ^= v2;
+	FASTMIX_PERM(s[0], s[1], s[2], s[3]);
+	s[0] ^= v2;
 }
 
+#ifdef CONFIG_SMP
 /*
- * This function does the actual extraction for extract_entropy and
- * extract_entropy_user.
- *
- * Note: we assume that .poolwords is a multiple of 16 words.
+ * This function is called when the CPU has just come online, with
+ * entry CPUHP_AP_RANDOM_ONLINE, just after CPUHP_AP_WORKQUEUE_ONLINE.
  */
-static void extract_buf(struct entropy_store *r, __u8 *out)
+int __cold random_online_cpu(unsigned int cpu)
 {
-	int i;
-	union {
-		__u32 w[5];
-		unsigned long l[LONGS(20)];
-	} hash;
-	__u32 workspace[SHA_WORKSPACE_WORDS];
-	unsigned long flags;
-
 	/*
-	 * If we have an architectural hardware random number
-	 * generator, use it for SHA's initial vector
+	 * During CPU shutdown and before CPU onlining, add_interrupt_
+	 * randomness() may schedule mix_interrupt_randomness(), and
+	 * set the MIX_INFLIGHT flag. However, because the worker can
+	 * be scheduled on a different CPU during this period, that
+	 * flag will never be cleared. For that reason, we zero out
+	 * the flag here, which runs just after workqueues are onlined
+	 * for the CPU again. This also has the effect of setting the
+	 * irq randomness count to zero so that new accumulated irqs
+	 * are fresh.
 	 */
-	sha_init(hash.w);
-	for (i = 0; i < LONGS(20); i++) {
-		unsigned long v;
-		if (!arch_get_random_long(&v))
-			break;
-		hash.l[i] = v;
-	}
-
-	/* Generate a hash across the pool, 16 words (512 bits) at a time */
-	spin_lock_irqsave(&r->lock, flags);
-	for (i = 0; i < r->poolinfo->poolwords; i += 16)
-		sha_transform(hash.w, (__u8 *)(r->pool + i), workspace);
+	per_cpu_ptr(&irq_randomness, cpu)->count = 0;
+	return 0;
+}
+#endif
 
+static void mix_interrupt_randomness(struct timer_list *work)
+{
+	struct fast_pool *fast_pool = container_of(work, struct fast_pool, mix);
 	/*
-	 * We mix the hash back into the pool to prevent backtracking
-	 * attacks (where the attacker knows the state of the pool
-	 * plus the current outputs, and attempts to find previous
-	 * ouputs), unless the hash function can be inverted. By
-	 * mixing at least a SHA1 worth of hash data back, we make
-	 * brute-forcing the feedback as hard as brute-forcing the
-	 * hash.
+	 * The size of the copied stack pool is explicitly 2 longs so that we
+	 * only ever ingest half of the siphash output each time, retaining
+	 * the other half as the next "key" that carries over. The entropy is
+	 * supposed to be sufficiently dispersed between bits so on average
+	 * we don't wind up "losing" some.
 	 */
-	__mix_pool_bytes(r, hash.w, sizeof(hash.w));
-	spin_unlock_irqrestore(&r->lock, flags);
+	unsigned long pool[2];
+	unsigned int count;
 
-	memzero_explicit(workspace, sizeof(workspace));
+	/* Check to see if we're running on the wrong CPU due to hotplug. */
+	local_irq_disable();
+	if (fast_pool != this_cpu_ptr(&irq_randomness)) {
+		local_irq_enable();
+		return;
+	}
 
 	/*
-	 * In case the hash function has some recognizable output
-	 * pattern, we fold it in half. Thus, we always feed back
-	 * twice as much data as we output.
+	 * Copy the pool to the stack so that the mixer always has a
+	 * consistent view, before we reenable irqs again.
 	 */
-	hash.w[0] ^= hash.w[3];
-	hash.w[1] ^= hash.w[4];
-	hash.w[2] ^= rol32(hash.w[2], 16);
+	memcpy(pool, fast_pool->pool, sizeof(pool));
+	count = fast_pool->count;
+	fast_pool->count = 0;
+	fast_pool->last = jiffies;
+	local_irq_enable();
+
+	mix_pool_bytes(pool, sizeof(pool));
+	credit_init_bits(clamp_t(unsigned int, (count & U16_MAX) / 64, 1, sizeof(pool) * 8));
 
-	memcpy(out, &hash, EXTRACT_SIZE);
-	memzero_explicit(&hash, sizeof(hash));
+	memzero_explicit(pool, sizeof(pool));
 }
 
-static ssize_t _extract_entropy(struct entropy_store *r, void *buf,
-				size_t nbytes, int fips)
+void add_interrupt_randomness(int irq)
 {
-	ssize_t ret = 0, i;
-	__u8 tmp[EXTRACT_SIZE];
-	unsigned long flags;
+	enum { MIX_INFLIGHT = 1U << 31 };
+	unsigned long entropy = random_get_entropy();
+	struct fast_pool *fast_pool = this_cpu_ptr(&irq_randomness);
+	struct pt_regs *regs = get_irq_regs();
+	unsigned int new_count;
 
-	while (nbytes) {
-		extract_buf(r, tmp);
+	fast_mix(fast_pool->pool, entropy,
+		 (regs ? instruction_pointer(regs) : _RET_IP_) ^ swab(irq));
+	new_count = ++fast_pool->count;
 
-		if (fips) {
-			spin_lock_irqsave(&r->lock, flags);
-			if (!memcmp(tmp, r->last_data, EXTRACT_SIZE))
-				panic("Hardware RNG duplicated output!\n");
-			memcpy(r->last_data, tmp, EXTRACT_SIZE);
-			spin_unlock_irqrestore(&r->lock, flags);
-		}
-		i = min_t(int, nbytes, EXTRACT_SIZE);
-		memcpy(buf, tmp, i);
-		nbytes -= i;
-		buf += i;
-		ret += i;
-	}
+	if (new_count & MIX_INFLIGHT)
+		return;
 
-	/* Wipe data just returned from memory */
-	memzero_explicit(tmp, sizeof(tmp));
+	if (new_count < 1024 && !time_is_before_jiffies(fast_pool->last + HZ))
+		return;
 
-	return ret;
+	fast_pool->count |= MIX_INFLIGHT;
+	if (!timer_pending(&fast_pool->mix)) {
+		fast_pool->mix.expires = jiffies;
+		add_timer_on(&fast_pool->mix, raw_smp_processor_id());
+	}
 }
+EXPORT_SYMBOL_GPL(add_interrupt_randomness);
+
+/* There is one of these per entropy source */
+struct timer_rand_state {
+	unsigned long last_time;
+	long last_delta, last_delta2;
+};
 
 /*
- * This function extracts randomness from the "entropy pool", and
- * returns it in a buffer.
- *
- * The min parameter specifies the minimum amount we can pull before
- * failing to avoid races that defeat catastrophic reseeding while the
- * reserved parameter indicates how much entropy we must leave in the
- * pool after each pull to avoid starving other readers.
+ * This function adds entropy to the entropy "pool" by using timing
+ * delays. It uses the timer_rand_state structure to make an estimate
+ * of how many bits of entropy this call has added to the pool. The
+ * value "num" is also added to the pool; it should somehow describe
+ * the type of event that just happened.
  */
-static ssize_t extract_entropy(struct entropy_store *r, void *buf,
-				 size_t nbytes, int min, int reserved)
+static void add_timer_randomness(struct timer_rand_state *state, unsigned int num)
 {
-	__u8 tmp[EXTRACT_SIZE];
-	unsigned long flags;
+	unsigned long entropy = random_get_entropy(), now = jiffies, flags;
+	long delta, delta2, delta3;
+	unsigned int bits;
 
-	/* if last_data isn't primed, we need EXTRACT_SIZE extra bytes */
-	if (fips_enabled) {
-		spin_lock_irqsave(&r->lock, flags);
-		if (!r->last_data_init) {
-			r->last_data_init = 1;
-			spin_unlock_irqrestore(&r->lock, flags);
-			trace_extract_entropy(r->name, EXTRACT_SIZE,
-					      ENTROPY_BITS(r), _RET_IP_);
-			xfer_secondary_pool(r, EXTRACT_SIZE);
-			extract_buf(r, tmp);
-			spin_lock_irqsave(&r->lock, flags);
-			memcpy(r->last_data, tmp, EXTRACT_SIZE);
-		}
-		spin_unlock_irqrestore(&r->lock, flags);
+	/*
+	 * If we're in a hard IRQ, add_interrupt_randomness() will be called
+	 * sometime after, so mix into the fast pool.
+	 */
+	if (in_irq()) {
+		fast_mix(this_cpu_ptr(&irq_randomness)->pool, entropy, num);
+	} else {
+		spin_lock_irqsave(&input_pool.lock, flags);
+		_mix_pool_bytes(&entropy, sizeof(entropy));
+		_mix_pool_bytes(&num, sizeof(num));
+		spin_unlock_irqrestore(&input_pool.lock, flags);
 	}
 
-	trace_extract_entropy(r->name, nbytes, ENTROPY_BITS(r), _RET_IP_);
-	xfer_secondary_pool(r, nbytes);
-	nbytes = account(r, nbytes, min, reserved);
-
-	return _extract_entropy(r, buf, nbytes, fips_enabled);
-}
-
-/*
- * This function extracts randomness from the "entropy pool", and
- * returns it in a userspace buffer.
- */
-static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
-				    size_t nbytes)
-{
-	ssize_t ret = 0, i;
-	__u8 tmp[EXTRACT_SIZE];
-	int large_request = (nbytes > 256);
+	if (crng_ready())
+		return;
 
-	trace_extract_entropy_user(r->name, nbytes, ENTROPY_BITS(r), _RET_IP_);
-	if (!r->initialized && r->pull) {
-		xfer_secondary_pool(r, ENTROPY_BITS(r->pull)/8);
-		if (!r->initialized)
-			return 0;
-	}
-	xfer_secondary_pool(r, nbytes);
-	nbytes = account(r, nbytes, 0, 0);
+	/*
+	 * Calculate number of bits of randomness we probably added.
+	 * We take into account the first, second and third-order deltas
+	 * in order to make our estimate.
+	 */
+	delta = now - READ_ONCE(state->last_time);
+	WRITE_ONCE(state->last_time, now);
 
-	while (nbytes) {
-		if (large_request && need_resched()) {
-			if (signal_pending(current)) {
-				if (ret == 0)
-					ret = -ERESTARTSYS;
-				break;
-			}
-			schedule();
-		}
+	delta2 = delta - READ_ONCE(state->last_delta);
+	WRITE_ONCE(state->last_delta, delta);
 
-		extract_buf(r, tmp);
-		i = min_t(int, nbytes, EXTRACT_SIZE);
-		if (copy_to_user(buf, tmp, i)) {
-			ret = -EFAULT;
-			break;
-		}
+	delta3 = delta2 - READ_ONCE(state->last_delta2);
+	WRITE_ONCE(state->last_delta2, delta2);
 
-		nbytes -= i;
-		buf += i;
-		ret += i;
-	}
+	if (delta < 0)
+		delta = -delta;
+	if (delta2 < 0)
+		delta2 = -delta2;
+	if (delta3 < 0)
+		delta3 = -delta3;
+	if (delta > delta2)
+		delta = delta2;
+	if (delta > delta3)
+		delta = delta3;
 
-	/* Wipe data just returned from memory */
-	memzero_explicit(tmp, sizeof(tmp));
+	/*
+	 * delta is now minimum absolute delta. Round down by 1 bit
+	 * on general principles, and limit entropy estimate to 11 bits.
+	 */
+	bits = min(fls(delta >> 1), 11);
 
-	return ret;
+	/*
+	 * As mentioned above, if we're in a hard IRQ, add_interrupt_randomness()
+	 * will run after this, which uses a different crediting scheme of 1 bit
+	 * per every 64 interrupts. In order to let that function do accounting
+	 * close to the one in this function, we credit a full 64/64 bit per bit,
+	 * and then subtract one to account for the extra one added.
+	 */
+	if (in_irq())
+		this_cpu_ptr(&irq_randomness)->count += max(1u, bits * 64) - 1;
+	else
+		_credit_init_bits(bits);
 }
 
-#define warn_unseeded_randomness(previous) \
-	_warn_unseeded_randomness(__func__, (void *) _RET_IP_, (previous))
-
-static void _warn_unseeded_randomness(const char *func_name, void *caller,
-				      void **previous)
+void add_input_randomness(unsigned int type, unsigned int code, unsigned int value)
 {
-#ifdef CONFIG_WARN_ALL_UNSEEDED_RANDOM
-	const bool print_once = false;
-#else
-	static bool print_once __read_mostly;
-#endif
+	static unsigned char last_value;
+	static struct timer_rand_state input_timer_state = { INITIAL_JIFFIES };
 
-	if (print_once ||
-	    crng_ready() ||
-	    (previous && (caller == READ_ONCE(*previous))))
+	/* Ignore autorepeat and the like. */
+	if (value == last_value)
 		return;
-	WRITE_ONCE(*previous, caller);
-#ifndef CONFIG_WARN_ALL_UNSEEDED_RANDOM
-	print_once = true;
-#endif
-	if (__ratelimit(&unseeded_warning))
-		pr_notice("random: %s called from %pS with crng_init=%d\n",
-			  func_name, caller, crng_init);
+
+	last_value = value;
+	add_timer_randomness(&input_timer_state,
+			     (type << 4) ^ code ^ (code >> 4) ^ value);
 }
+EXPORT_SYMBOL_GPL(add_input_randomness);
 
-/*
- * This function is the exported kernel interface.  It returns some
- * number of good random numbers, suitable for key generation, seeding
- * TCP sequence numbers, etc.  It does not rely on the hardware random
- * number generator.  For random bytes direct from the hardware RNG
- * (when available), use get_random_bytes_arch(). In order to ensure
- * that the randomness provided by this function is okay, the function
- * wait_for_random_bytes() should be called and return 0 at least once
- * at any point prior.
- */
-static void _get_random_bytes(void *buf, int nbytes)
+#ifdef CONFIG_BLOCK
+void add_disk_randomness(struct gendisk *disk)
 {
-	__u8 tmp[CHACHA_BLOCK_SIZE] __aligned(4);
-
-	trace_get_random_bytes(nbytes, _RET_IP_);
-
-	while (nbytes >= CHACHA_BLOCK_SIZE) {
-		extract_crng(buf);
-		buf += CHACHA_BLOCK_SIZE;
-		nbytes -= CHACHA_BLOCK_SIZE;
-	}
-
-	if (nbytes > 0) {
-		extract_crng(tmp);
-		memcpy(buf, tmp, nbytes);
-		crng_backtrack_protect(tmp, nbytes);
-	} else
-		crng_backtrack_protect(tmp, CHACHA_BLOCK_SIZE);
-	memzero_explicit(tmp, sizeof(tmp));
+	if (!disk || !disk->random)
+		return;
+	/* First major is 1, so we get >= 0x200 here. */
+	add_timer_randomness(disk->random, 0x100 + disk_devt(disk));
 }
+EXPORT_SYMBOL_GPL(add_disk_randomness);
 
-void get_random_bytes(void *buf, int nbytes)
+void __cold rand_initialize_disk(struct gendisk *disk)
 {
-	static void *previous;
+	struct timer_rand_state *state;
 
-	warn_unseeded_randomness(&previous);
-	_get_random_bytes(buf, nbytes);
+	/*
+	 * If kzalloc returns null, we just won't use that entropy
+	 * source.
+	 */
+	state = kzalloc(sizeof(struct timer_rand_state), GFP_KERNEL);
+	if (state) {
+		state->last_time = INITIAL_JIFFIES;
+		disk->random = state;
+	}
 }
-EXPORT_SYMBOL(get_random_bytes);
-
+#endif
 
 /*
  * Each time the timer fires, we expect that we got an unpredictable
@@ -1745,371 +1143,181 @@
  *
  * So the re-arming always happens in the entropy loop itself.
  */
-static void entropy_timer(struct timer_list *t)
+static void __cold entropy_timer(struct timer_list *t)
 {
-	credit_entropy_bits(&input_pool, 1);
+	credit_init_bits(1);
 }
 
 /*
  * If we have an actual cycle counter, see if we can
  * generate enough entropy with timing noise
  */
-static void try_to_generate_entropy(void)
+static void __cold try_to_generate_entropy(void)
 {
 	struct {
-		unsigned long now;
+		unsigned long entropy;
 		struct timer_list timer;
 	} stack;
 
-	stack.now = random_get_entropy();
+	stack.entropy = random_get_entropy();
 
 	/* Slow counter - or none. Don't even bother */
-	if (stack.now == random_get_entropy())
+	if (stack.entropy == random_get_entropy())
 		return;
 
 	timer_setup_on_stack(&stack.timer, entropy_timer, 0);
-	while (!crng_ready()) {
+	while (!crng_ready() && !signal_pending(current)) {
 		if (!timer_pending(&stack.timer))
-			mod_timer(&stack.timer, jiffies+1);
-		mix_pool_bytes(&input_pool, &stack.now, sizeof(stack.now));
+			mod_timer(&stack.timer, jiffies + 1);
+		mix_pool_bytes(&stack.entropy, sizeof(stack.entropy));
 		schedule();
-		stack.now = random_get_entropy();
+		stack.entropy = random_get_entropy();
 	}
 
 	del_timer_sync(&stack.timer);
 	destroy_timer_on_stack(&stack.timer);
-	mix_pool_bytes(&input_pool, &stack.now, sizeof(stack.now));
+	mix_pool_bytes(&stack.entropy, sizeof(stack.entropy));
 }
 
-/*
- * Wait for the urandom pool to be seeded and thus guaranteed to supply
- * cryptographically secure random numbers. This applies to: the /dev/urandom
- * device, the get_random_bytes function, and the get_random_{u32,u64,int,long}
- * family of functions. Using any of these functions without first calling
- * this function forfeits the guarantee of security.
- *
- * Returns: 0 if the urandom pool has been seeded.
- *          -ERESTARTSYS if the function was interrupted by a signal.
- */
-int wait_for_random_bytes(void)
-{
-	if (likely(crng_ready()))
-		return 0;
-
-	do {
-		int ret;
-		ret = wait_event_interruptible_timeout(crng_init_wait, crng_ready(), HZ);
-		if (ret)
-			return ret > 0 ? 0 : ret;
-
-		try_to_generate_entropy();
-	} while (!crng_ready());
 
-	return 0;
-}
-EXPORT_SYMBOL(wait_for_random_bytes);
-
-/*
- * Returns whether or not the urandom pool has been seeded and thus guaranteed
- * to supply cryptographically secure random numbers. This applies to: the
- * /dev/urandom device, the get_random_bytes function, and the get_random_{u32,
- * ,u64,int,long} family of functions.
+/**********************************************************************
  *
- * Returns: true if the urandom pool has been seeded.
- *          false if the urandom pool has not been seeded.
- */
-bool rng_is_initialized(void)
-{
-	return crng_ready();
-}
-EXPORT_SYMBOL(rng_is_initialized);
-
-/*
- * Add a callback function that will be invoked when the nonblocking
- * pool is initialised.
+ * Userspace reader/writer interfaces.
  *
- * returns: 0 if callback is successfully added
- *	    -EALREADY if pool is already initialised (callback not called)
- *	    -ENOENT if module for callback is not alive
- */
-int add_random_ready_callback(struct random_ready_callback *rdy)
-{
-	struct module *owner;
-	unsigned long flags;
-	int err = -EALREADY;
-
-	if (crng_ready())
-		return err;
-
-	owner = rdy->owner;
-	if (!try_module_get(owner))
-		return -ENOENT;
-
-	spin_lock_irqsave(&random_ready_list_lock, flags);
-	if (crng_ready())
-		goto out;
-
-	owner = NULL;
-
-	list_add(&rdy->list, &random_ready_list);
-	err = 0;
-
-out:
-	spin_unlock_irqrestore(&random_ready_list_lock, flags);
-
-	module_put(owner);
-
-	return err;
-}
-EXPORT_SYMBOL(add_random_ready_callback);
-
-/*
- * Delete a previously registered readiness callback function.
- */
-void del_random_ready_callback(struct random_ready_callback *rdy)
-{
-	unsigned long flags;
-	struct module *owner = NULL;
-
-	spin_lock_irqsave(&random_ready_list_lock, flags);
-	if (!list_empty(&rdy->list)) {
-		list_del_init(&rdy->list);
-		owner = rdy->owner;
-	}
-	spin_unlock_irqrestore(&random_ready_list_lock, flags);
-
-	module_put(owner);
-}
-EXPORT_SYMBOL(del_random_ready_callback);
-
-/*
- * This function will use the architecture-specific hardware random
- * number generator if it is available.  The arch-specific hw RNG will
- * almost certainly be faster than what we can do in software, but it
- * is impossible to verify that it is implemented securely (as
- * opposed, to, say, the AES encryption of a sequence number using a
- * key known by the NSA).  So it's useful if we need the speed, but
- * only if we're willing to trust the hardware manufacturer not to
- * have put in a back door.
+ * getrandom(2) is the primary modern interface into the RNG and should
+ * be used in preference to anything else.
  *
- * Return number of bytes filled in.
- */
-int __must_check get_random_bytes_arch(void *buf, int nbytes)
-{
-	int left = nbytes;
-	char *p = buf;
-
-	trace_get_random_bytes_arch(left, _RET_IP_);
-	while (left) {
-		unsigned long v;
-		int chunk = min_t(int, left, sizeof(unsigned long));
-
-		if (!arch_get_random_long(&v))
-			break;
-
-		memcpy(p, &v, chunk);
-		p += chunk;
-		left -= chunk;
-	}
-
-	return nbytes - left;
-}
-EXPORT_SYMBOL(get_random_bytes_arch);
-
-/*
- * init_std_data - initialize pool with system data
+ * Reading from /dev/random has the same functionality as calling
+ * getrandom(2) with flags=0. In earlier versions, however, it had
+ * vastly different semantics and should therefore be avoided, to
+ * prevent backwards compatibility issues.
  *
- * @r: pool to initialize
+ * Reading from /dev/urandom has the same functionality as calling
+ * getrandom(2) with flags=GRND_INSECURE. Because it does not block
+ * waiting for the RNG to be ready, it should not be used.
  *
- * This function clears the pool's entropy count and mixes some system
- * data into the pool to prepare it for use. The pool is not cleared
- * as that can only decrease the entropy in the pool.
- */
-static void __init init_std_data(struct entropy_store *r)
+ * Writing to either /dev/random or /dev/urandom adds entropy to
+ * the input pool but does not credit it.
+ *
+ * Polling on /dev/random indicates when the RNG is initialized, on
+ * the read side, and when it wants new entropy, on the write side.
+ *
+ * Both /dev/random and /dev/urandom have the same set of ioctls for
+ * adding entropy, getting the entropy count, zeroing the count, and
+ * reseeding the crng.
+ *
+ **********************************************************************/
+
+SYSCALL_DEFINE3(getrandom, char __user *, ubuf, size_t, len, unsigned int, flags)
 {
-	int i;
-	ktime_t now = ktime_get_real();
-	unsigned long rv;
+	struct iov_iter iter;
+	struct iovec iov;
+	int ret;
 
-	r->last_pulled = jiffies;
-	mix_pool_bytes(r, &now, sizeof(now));
-	for (i = r->poolinfo->poolbytes; i > 0; i -= sizeof(rv)) {
-		if (!arch_get_random_seed_long(&rv) &&
-		    !arch_get_random_long(&rv))
-			rv = random_get_entropy();
-		mix_pool_bytes(r, &rv, sizeof(rv));
-	}
-	mix_pool_bytes(r, utsname(), sizeof(*(utsname())));
-}
+	if (flags & ~(GRND_NONBLOCK | GRND_RANDOM | GRND_INSECURE))
+		return -EINVAL;
 
-/*
- * Note that setup_arch() may call add_device_randomness()
- * long before we get here. This allows seeding of the pools
- * with some platform dependent data very early in the boot
- * process. But it limits our options here. We must use
- * statically allocated structures that already have all
- * initializations complete at compile time. We should also
- * take care not to overwrite the precious per platform data
- * we were given.
- */
-int __init rand_initialize(void)
-{
-	init_std_data(&input_pool);
-	init_std_data(&blocking_pool);
-	crng_initialize(&primary_crng);
-	crng_global_init_time = jiffies;
-	if (ratelimit_disable) {
-		urandom_warning.interval = 0;
-		unseeded_warning.interval = 0;
+	/*
+	 * Requesting insecure and blocking randomness at the same time makes
+	 * no sense.
+	 */
+	if ((flags & (GRND_INSECURE | GRND_RANDOM)) == (GRND_INSECURE | GRND_RANDOM))
+		return -EINVAL;
+
+	if (!crng_ready() && !(flags & GRND_INSECURE)) {
+		if (flags & GRND_NONBLOCK)
+			return -EAGAIN;
+		ret = wait_for_random_bytes();
+		if (unlikely(ret))
+			return ret;
 	}
-	return 0;
+
+	ret = import_single_range(READ, ubuf, len, &iov, &iter);
+	if (unlikely(ret))
+		return ret;
+	return get_random_bytes_user(&iter);
 }
 
-#ifdef CONFIG_BLOCK
-void rand_initialize_disk(struct gendisk *disk)
+static __poll_t random_poll(struct file *file, poll_table *wait)
 {
-	struct timer_rand_state *state;
-
-	/*
-	 * If kzalloc returns null, we just won't use that entropy
-	 * source.
-	 */
-	state = kzalloc(sizeof(struct timer_rand_state), GFP_KERNEL);
-	if (state) {
-		state->last_time = INITIAL_JIFFIES;
-		disk->random = state;
-	}
+	poll_wait(file, &crng_init_wait, wait);
+	return crng_ready() ? EPOLLIN | EPOLLRDNORM : EPOLLOUT | EPOLLWRNORM;
 }
-#endif
 
-static ssize_t
-_random_read(int nonblock, char __user *buf, size_t nbytes)
+static ssize_t write_pool_user(struct iov_iter *iter)
 {
-	ssize_t n;
+	u8 block[BLAKE2S_BLOCK_SIZE];
+	ssize_t ret = 0;
+	size_t copied;
 
-	if (nbytes == 0)
+	if (unlikely(!iov_iter_count(iter)))
 		return 0;
 
-	nbytes = min_t(size_t, nbytes, SEC_XFER_SIZE);
-	while (1) {
-		n = extract_entropy_user(&blocking_pool, buf, nbytes);
-		if (n < 0)
-			return n;
-		trace_random_read(n*8, (nbytes-n)*8,
-				  ENTROPY_BITS(&blocking_pool),
-				  ENTROPY_BITS(&input_pool));
-		if (n > 0)
-			return n;
-
-		/* Pool is (near) empty.  Maybe wait and retry. */
-		if (nonblock)
-			return -EAGAIN;
+	for (;;) {
+		copied = copy_from_iter(block, sizeof(block), iter);
+		ret += copied;
+		mix_pool_bytes(block, copied);
+		if (!iov_iter_count(iter) || copied != sizeof(block))
+			break;
 
-		wait_event_interruptible(random_read_wait,
-		    blocking_pool.initialized &&
-		    (ENTROPY_BITS(&input_pool) >= random_read_wakeup_bits));
-		if (signal_pending(current))
-			return -ERESTARTSYS;
+		BUILD_BUG_ON(PAGE_SIZE % sizeof(block) != 0);
+		if (ret % PAGE_SIZE == 0) {
+			if (signal_pending(current))
+				break;
+			cond_resched();
+		}
 	}
-}
-
-static ssize_t
-random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
-{
-	return _random_read(file->f_flags & O_NONBLOCK, buf, nbytes);
-}
-
-static ssize_t
-urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
-{
-	unsigned long flags;
-	static int maxwarn = 10;
-	int ret;
 
-	if (!crng_ready() && maxwarn > 0) {
-		maxwarn--;
-		if (__ratelimit(&urandom_warning))
-			printk(KERN_NOTICE "random: %s: uninitialized "
-			       "urandom read (%zd bytes read)\n",
-			       current->comm, nbytes);
-		spin_lock_irqsave(&primary_crng.lock, flags);
-		crng_init_cnt = 0;
-		spin_unlock_irqrestore(&primary_crng.lock, flags);
-	}
-	nbytes = min_t(size_t, nbytes, INT_MAX >> (ENTROPY_SHIFT + 3));
-	ret = extract_crng_user(buf, nbytes);
-	trace_urandom_read(8 * nbytes, 0, ENTROPY_BITS(&input_pool));
-	return ret;
+	memzero_explicit(block, sizeof(block));
+	return ret ? ret : -EFAULT;
 }
 
-static __poll_t
-random_poll(struct file *file, poll_table * wait)
+static ssize_t random_write_iter(struct kiocb *kiocb, struct iov_iter *iter)
 {
-	__poll_t mask;
-
-	poll_wait(file, &random_read_wait, wait);
-	poll_wait(file, &random_write_wait, wait);
-	mask = 0;
-	if (ENTROPY_BITS(&input_pool) >= random_read_wakeup_bits)
-		mask |= EPOLLIN | EPOLLRDNORM;
-	if (ENTROPY_BITS(&input_pool) < random_write_wakeup_bits)
-		mask |= EPOLLOUT | EPOLLWRNORM;
-	return mask;
+	return write_pool_user(iter);
 }
 
-static int
-write_pool(struct entropy_store *r, const char __user *buffer, size_t count)
+static ssize_t urandom_read_iter(struct kiocb *kiocb, struct iov_iter *iter)
 {
-	size_t bytes;
-	__u32 t, buf[16];
-	const char __user *p = buffer;
-
-	while (count > 0) {
-		int b, i = 0;
-
-		bytes = min(count, sizeof(buf));
-		if (copy_from_user(&buf, p, bytes))
-			return -EFAULT;
+	static int maxwarn = 10;
 
-		for (b = bytes ; b > 0 ; b -= sizeof(__u32), i++) {
-			if (!arch_get_random_int(&t))
-				break;
-			buf[i] ^= t;
+	if (!crng_ready()) {
+		if (!ratelimit_disable && maxwarn <= 0)
+			++urandom_warning.missed;
+		else if (ratelimit_disable || __ratelimit(&urandom_warning)) {
+			--maxwarn;
+			pr_notice("%s: uninitialized urandom read (%zu bytes read)\n",
+				  current->comm, iov_iter_count(iter));
 		}
-
-		count -= bytes;
-		p += bytes;
-
-		mix_pool_bytes(r, buf, bytes);
-		cond_resched();
 	}
 
-	return 0;
+	return get_random_bytes_user(iter);
 }
 
-static ssize_t random_write(struct file *file, const char __user *buffer,
-			    size_t count, loff_t *ppos)
+static ssize_t random_read_iter(struct kiocb *kiocb, struct iov_iter *iter)
 {
-	size_t ret;
+	int ret;
 
-	ret = write_pool(&input_pool, buffer, count);
-	if (ret)
-		return ret;
+	if (!crng_ready() &&
+	    ((kiocb->ki_flags & IOCB_NOWAIT) ||
+	     (kiocb->ki_filp->f_flags & O_NONBLOCK)))
+		return -EAGAIN;
 
-	return (ssize_t)count;
+	ret = wait_for_random_bytes();
+	if (ret != 0)
+		return ret;
+	return get_random_bytes_user(iter);
 }
 
 static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
 {
-	int size, ent_count;
 	int __user *p = (int __user *)arg;
-	int retval;
+	int ent_count;
 
 	switch (cmd) {
 	case RNDGETENTCNT:
-		/* inherently racy, no point locking */
-		ent_count = ENTROPY_BITS(&input_pool);
-		if (put_user(ent_count, p))
+		/* Inherently racy, no point locking. */
+		if (put_user(input_pool.init_bits, p))
 			return -EFAULT;
 		return 0;
 	case RNDADDTOENTCNT:
@@ -2117,39 +1325,48 @@
 			return -EPERM;
 		if (get_user(ent_count, p))
 			return -EFAULT;
-		return credit_entropy_bits_safe(&input_pool, ent_count);
-	case RNDADDENTROPY:
+		if (ent_count < 0)
+			return -EINVAL;
+		credit_init_bits(ent_count);
+		return 0;
+	case RNDADDENTROPY: {
+		struct iov_iter iter;
+		struct iovec iov;
+		ssize_t ret;
+		int len;
+
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
 		if (get_user(ent_count, p++))
 			return -EFAULT;
 		if (ent_count < 0)
 			return -EINVAL;
-		if (get_user(size, p++))
+		if (get_user(len, p++))
 			return -EFAULT;
-		retval = write_pool(&input_pool, (const char __user *)p,
-				    size);
-		if (retval < 0)
-			return retval;
-		return credit_entropy_bits_safe(&input_pool, ent_count);
+		ret = import_single_range(WRITE, p, len, &iov, &iter);
+		if (unlikely(ret))
+			return ret;
+		ret = write_pool_user(&iter);
+		if (unlikely(ret < 0))
+			return ret;
+		/* Since we're crediting, enforce that it was all written into the pool. */
+		if (unlikely(ret != len))
+			return -EFAULT;
+		credit_init_bits(ent_count);
+		return 0;
+	}
 	case RNDZAPENTCNT:
 	case RNDCLEARPOOL:
-		/*
-		 * Clear the entropy pool counters. We no longer clear
-		 * the entropy pool, as that's silly.
-		 */
+		/* No longer has any effect. */
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
-		input_pool.entropy_count = 0;
-		blocking_pool.entropy_count = 0;
 		return 0;
 	case RNDRESEEDCRNG:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
-		if (crng_init < 2)
+		if (!crng_ready())
 			return -ENODATA;
-		crng_reseed(&primary_crng, NULL);
-		crng_global_init_time = jiffies - 1;
+		crng_reseed();
 		return 0;
 	default:
 		return -EINVAL;
@@ -2162,49 +1379,56 @@
 }
 
 const struct file_operations random_fops = {
-	.read  = random_read,
-	.write = random_write,
-	.poll  = random_poll,
+	.read_iter = random_read_iter,
+	.write_iter = random_write_iter,
+	.poll = random_poll,
 	.unlocked_ioctl = random_ioctl,
+	.compat_ioctl = compat_ptr_ioctl,
 	.fasync = random_fasync,
 	.llseek = noop_llseek,
+	.splice_read = generic_file_splice_read,
+	.splice_write = iter_file_splice_write,
 };
 
 const struct file_operations urandom_fops = {
-	.read  = urandom_read,
-	.write = random_write,
+	.read_iter = urandom_read_iter,
+	.write_iter = random_write_iter,
 	.unlocked_ioctl = random_ioctl,
+	.compat_ioctl = compat_ptr_ioctl,
 	.fasync = random_fasync,
 	.llseek = noop_llseek,
+	.splice_read = generic_file_splice_read,
+	.splice_write = iter_file_splice_write,
 };
 
-SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count,
-		unsigned int, flags)
-{
-	int ret;
-
-	if (flags & ~(GRND_NONBLOCK|GRND_RANDOM))
-		return -EINVAL;
-
-	if (count > INT_MAX)
-		count = INT_MAX;
-
-	if (flags & GRND_RANDOM)
-		return _random_read(flags & GRND_NONBLOCK, buf, count);
-
-	if (!crng_ready()) {
-		if (flags & GRND_NONBLOCK)
-			return -EAGAIN;
-		ret = wait_for_random_bytes();
-		if (unlikely(ret))
-			return ret;
-	}
-	return urandom_read(NULL, buf, count, NULL);
-}
 
 /********************************************************************
  *
- * Sysctl interface
+ * Sysctl interface.
+ *
+ * These are partly unused legacy knobs with dummy values to not break
+ * userspace and partly still useful things. They are usually accessible
+ * in /proc/sys/kernel/random/ and are as follows:
+ *
+ * - boot_id - a UUID representing the current boot.
+ *
+ * - uuid - a random UUID, different each time the file is read.
+ *
+ * - poolsize - the number of bits of entropy that the input pool can
+ *   hold, tied to the POOL_BITS constant.
+ *
+ * - entropy_avail - the number of bits of entropy currently in the
+ *   input pool. Always <= poolsize.
+ *
+ * - write_wakeup_threshold - the amount of entropy in the input pool
+ *   below which write polls to /dev/random will unblock, requesting
+ *   more entropy, tied to the POOL_READY_BITS constant. It is writable
+ *   to avoid breaking old userspaces, but writing to it does not
+ *   change any behavior of the RNG.
+ *
+ * - urandom_min_reseed_secs - fixed to the value CRNG_RESEED_INTERVAL.
+ *   It is writable to avoid breaking old userspaces, but writing
+ *   to it does not change any behavior of the RNG.
  *
  ********************************************************************/
 
@@ -2212,26 +1436,28 @@
 
 #include <linux/sysctl.h>
 
-static int min_read_thresh = 8, min_write_thresh;
-static int max_read_thresh = OUTPUT_POOL_WORDS * 32;
-static int max_write_thresh = INPUT_POOL_WORDS * 32;
-static int random_min_urandom_seed = 60;
-static char sysctl_bootid[16];
+static int sysctl_random_min_urandom_seed = CRNG_RESEED_INTERVAL / HZ;
+static int sysctl_random_write_wakeup_bits = POOL_READY_BITS;
+static int sysctl_poolsize = POOL_BITS;
+static u8 sysctl_bootid[UUID_SIZE];
 
 /*
  * This function is used to return both the bootid UUID, and random
- * UUID.  The difference is in whether table->data is NULL; if it is,
+ * UUID. The difference is in whether table->data is NULL; if it is,
  * then a new UUID is generated and returned to the user.
- *
- * If the user accesses this via the proc interface, the UUID will be
- * returned as an ASCII string in the standard UUID format; if via the
- * sysctl system call, as 16 bytes of binary data.
  */
-static int proc_do_uuid(struct ctl_table *table, int write,
-			void __user *buffer, size_t *lenp, loff_t *ppos)
+static int proc_do_uuid(struct ctl_table *table, int write, void __user *buf,
+			size_t *lenp, loff_t *ppos)
 {
-	struct ctl_table fake_table;
-	unsigned char buf[64], tmp_uuid[16], *uuid;
+	u8 tmp_uuid[UUID_SIZE], *uuid;
+	char uuid_string[UUID_STRING_LEN + 1];
+	struct ctl_table fake_table = {
+		.data = uuid_string,
+		.maxlen = UUID_STRING_LEN
+	};
+
+	if (write)
+		return -EPERM;
 
 	uuid = table->data;
 	if (!uuid) {
@@ -2246,32 +1472,17 @@
 		spin_unlock(&bootid_spinlock);
 	}
 
-	sprintf(buf, "%pU", uuid);
-
-	fake_table.data = buf;
-	fake_table.maxlen = sizeof(buf);
-
-	return proc_dostring(&fake_table, write, buffer, lenp, ppos);
+	snprintf(uuid_string, sizeof(uuid_string), "%pU", uuid);
+	return proc_dostring(&fake_table, 0, buf, lenp, ppos);
 }
 
-/*
- * Return entropy available scaled to integral bits
- */
-static int proc_do_entropy(struct ctl_table *table, int write,
-			   void __user *buffer, size_t *lenp, loff_t *ppos)
+/* The same as proc_dointvec, but writes don't change anything. */
+static int proc_do_rointvec(struct ctl_table *table, int write, void __user *buf,
+			    size_t *lenp, loff_t *ppos)
 {
-	struct ctl_table fake_table;
-	int entropy_count;
-
-	entropy_count = *(int *)table->data >> ENTROPY_SHIFT;
-
-	fake_table.data = &entropy_count;
-	fake_table.maxlen = sizeof(entropy_count);
-
-	return proc_dointvec(&fake_table, write, buffer, lenp, ppos);
+	return write ? 0 : proc_dointvec(table, 0, buf, lenp, ppos);
 }
 
-static int sysctl_poolsize = INPUT_POOL_WORDS * 32;
 extern struct ctl_table random_table[];
 struct ctl_table random_table[] = {
 	{
@@ -2283,239 +1494,36 @@
 	},
 	{
 		.procname	= "entropy_avail",
+		.data		= &input_pool.init_bits,
 		.maxlen		= sizeof(int),
 		.mode		= 0444,
-		.proc_handler	= proc_do_entropy,
-		.data		= &input_pool.entropy_count,
-	},
-	{
-		.procname	= "read_wakeup_threshold",
-		.data		= &random_read_wakeup_bits,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= proc_dointvec_minmax,
-		.extra1		= &min_read_thresh,
-		.extra2		= &max_read_thresh,
+		.proc_handler	= proc_dointvec,
 	},
 	{
 		.procname	= "write_wakeup_threshold",
-		.data		= &random_write_wakeup_bits,
+		.data		= &sysctl_random_write_wakeup_bits,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec_minmax,
-		.extra1		= &min_write_thresh,
-		.extra2		= &max_write_thresh,
+		.proc_handler	= proc_do_rointvec,
 	},
 	{
 		.procname	= "urandom_min_reseed_secs",
-		.data		= &random_min_urandom_seed,
+		.data		= &sysctl_random_min_urandom_seed,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec,
+		.proc_handler	= proc_do_rointvec,
 	},
 	{
 		.procname	= "boot_id",
 		.data		= &sysctl_bootid,
-		.maxlen		= 16,
 		.mode		= 0444,
 		.proc_handler	= proc_do_uuid,
 	},
 	{
 		.procname	= "uuid",
-		.maxlen		= 16,
 		.mode		= 0444,
 		.proc_handler	= proc_do_uuid,
 	},
-#ifdef ADD_INTERRUPT_BENCH
-	{
-		.procname	= "add_interrupt_avg_cycles",
-		.data		= &avg_cycles,
-		.maxlen		= sizeof(avg_cycles),
-		.mode		= 0444,
-		.proc_handler	= proc_doulongvec_minmax,
-	},
-	{
-		.procname	= "add_interrupt_avg_deviation",
-		.data		= &avg_deviation,
-		.maxlen		= sizeof(avg_deviation),
-		.mode		= 0444,
-		.proc_handler	= proc_doulongvec_minmax,
-	},
-#endif
 	{ }
 };
-#endif 	/* CONFIG_SYSCTL */
-
-struct batched_entropy {
-	union {
-		u64 entropy_u64[CHACHA_BLOCK_SIZE / sizeof(u64)];
-		u32 entropy_u32[CHACHA_BLOCK_SIZE / sizeof(u32)];
-	};
-	unsigned int position;
-	spinlock_t batch_lock;
-};
-
-/*
- * Get a random word for internal kernel use only. The quality of the random
- * number is either as good as RDRAND or as good as /dev/urandom, with the
- * goal of being quite fast and not depleting entropy. In order to ensure
- * that the randomness provided by this function is okay, the function
- * wait_for_random_bytes() should be called and return 0 at least once
- * at any point prior.
- */
-static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u64) = {
-	.batch_lock	= __SPIN_LOCK_UNLOCKED(batched_entropy_u64.lock),
-};
-
-u64 get_random_u64(void)
-{
-	u64 ret;
-	unsigned long flags;
-	struct batched_entropy *batch;
-	static void *previous;
-
-#if BITS_PER_LONG == 64
-	if (arch_get_random_long((unsigned long *)&ret))
-		return ret;
-#else
-	if (arch_get_random_long((unsigned long *)&ret) &&
-	    arch_get_random_long((unsigned long *)&ret + 1))
-	    return ret;
-#endif
-
-	warn_unseeded_randomness(&previous);
-
-	batch = raw_cpu_ptr(&batched_entropy_u64);
-	spin_lock_irqsave(&batch->batch_lock, flags);
-	if (batch->position % ARRAY_SIZE(batch->entropy_u64) == 0) {
-		extract_crng((u8 *)batch->entropy_u64);
-		batch->position = 0;
-	}
-	ret = batch->entropy_u64[batch->position++];
-	spin_unlock_irqrestore(&batch->batch_lock, flags);
-	return ret;
-}
-EXPORT_SYMBOL(get_random_u64);
-
-static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u32) = {
-	.batch_lock	= __SPIN_LOCK_UNLOCKED(batched_entropy_u32.lock),
-};
-u32 get_random_u32(void)
-{
-	u32 ret;
-	unsigned long flags;
-	struct batched_entropy *batch;
-	static void *previous;
-
-	if (arch_get_random_int(&ret))
-		return ret;
-
-	warn_unseeded_randomness(&previous);
-
-	batch = raw_cpu_ptr(&batched_entropy_u32);
-	spin_lock_irqsave(&batch->batch_lock, flags);
-	if (batch->position % ARRAY_SIZE(batch->entropy_u32) == 0) {
-		extract_crng((u8 *)batch->entropy_u32);
-		batch->position = 0;
-	}
-	ret = batch->entropy_u32[batch->position++];
-	spin_unlock_irqrestore(&batch->batch_lock, flags);
-	return ret;
-}
-EXPORT_SYMBOL(get_random_u32);
-
-/* It's important to invalidate all potential batched entropy that might
- * be stored before the crng is initialized, which we can do lazily by
- * simply resetting the counter to zero so that it's re-extracted on the
- * next usage. */
-static void invalidate_batched_entropy(void)
-{
-	int cpu;
-	unsigned long flags;
-
-	for_each_possible_cpu (cpu) {
-		struct batched_entropy *batched_entropy;
-
-		batched_entropy = per_cpu_ptr(&batched_entropy_u32, cpu);
-		spin_lock_irqsave(&batched_entropy->batch_lock, flags);
-		batched_entropy->position = 0;
-		spin_unlock(&batched_entropy->batch_lock);
-
-		batched_entropy = per_cpu_ptr(&batched_entropy_u64, cpu);
-		spin_lock(&batched_entropy->batch_lock);
-		batched_entropy->position = 0;
-		spin_unlock_irqrestore(&batched_entropy->batch_lock, flags);
-	}
-}
-
-/**
- * randomize_page - Generate a random, page aligned address
- * @start:	The smallest acceptable address the caller will take.
- * @range:	The size of the area, starting at @start, within which the
- *		random address must fall.
- *
- * If @start + @range would overflow, @range is capped.
- *
- * NOTE: Historical use of randomize_range, which this replaces, presumed that
- * @start was already page aligned.  We now align it regardless.
- *
- * Return: A page aligned address within [start, start + range).  On error,
- * @start is returned.
- */
-unsigned long
-randomize_page(unsigned long start, unsigned long range)
-{
-	if (!PAGE_ALIGNED(start)) {
-		range -= PAGE_ALIGN(start) - start;
-		start = PAGE_ALIGN(start);
-	}
-
-	if (start > ULONG_MAX - range)
-		range = ULONG_MAX - start;
-
-	range >>= PAGE_SHIFT;
-
-	if (range == 0)
-		return start;
-
-	return start + (get_random_long() % range << PAGE_SHIFT);
-}
-
-/* Interface for in-kernel drivers of true hardware RNGs.
- * Those devices may produce endless random bits and will be throttled
- * when our pool is full.
- */
-void add_hwgenerator_randomness(const char *buffer, size_t count,
-				size_t entropy)
-{
-	struct entropy_store *poolp = &input_pool;
-
-	if (unlikely(crng_init == 0)) {
-		crng_fast_load(buffer, count);
-		return;
-	}
-
-	/* Suspend writing if we're above the trickle threshold.
-	 * We'll be woken up again once below random_write_wakeup_thresh,
-	 * or when the calling thread is about to terminate.
-	 */
-	wait_event_interruptible(random_write_wait, kthread_should_stop() ||
-			ENTROPY_BITS(&input_pool) <= random_write_wakeup_bits);
-	mix_pool_bytes(poolp, buffer, count);
-	credit_entropy_bits(poolp, entropy);
-}
-EXPORT_SYMBOL_GPL(add_hwgenerator_randomness);
-
-/* Handle random seed passed by bootloader.
- * If the seed is trustworthy, it would be regarded as hardware RNGs. Otherwise
- * it would be regarded as device data.
- * The decision is controlled by CONFIG_RANDOM_TRUST_BOOTLOADER.
- */
-void add_bootloader_randomness(const void *buf, unsigned int size)
-{
-	if (IS_ENABLED(CONFIG_RANDOM_TRUST_BOOTLOADER))
-		add_hwgenerator_randomness(buf, size, size * 8);
-	else
-		add_device_randomness(buf, size);
-}
-EXPORT_SYMBOL_GPL(add_bootloader_randomness);
+#endif	/* CONFIG_SYSCTL */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/tlclk.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/tlclk.c
@@ -777,17 +777,21 @@
 {
 	int ret;
 
+	telclk_interrupt = (inb(TLCLK_REG7) & 0x0f);
+
+	alarm_events = kzalloc( sizeof(struct tlclk_alarms), GFP_KERNEL);
+	if (!alarm_events) {
+		ret = -ENOMEM;
+		goto out1;
+	}
+
 	ret = register_chrdev(tlclk_major, "telco_clock", &tlclk_fops);
 	if (ret < 0) {
 		printk(KERN_ERR "tlclk: can't get major %d.\n", tlclk_major);
+		kfree(alarm_events);
 		return ret;
 	}
 	tlclk_major = ret;
-	alarm_events = kzalloc( sizeof(struct tlclk_alarms), GFP_KERNEL);
-	if (!alarm_events) {
-		ret = -ENOMEM;
-		goto out1;
-	}
 
 	/* Read telecom clock IRQ number (Set by BIOS) */
 	if (!request_region(TLCLK_BASE, 8, "telco_clock")) {
@@ -796,7 +800,6 @@
 		ret = -EBUSY;
 		goto out2;
 	}
-	telclk_interrupt = (inb(TLCLK_REG7) & 0x0f);
 
 	if (0x0F == telclk_interrupt ) { /* not MCPBL0010 ? */
 		printk(KERN_ERR "telclk_interrupt = 0x%x non-mcpbl0010 hw.\n",
@@ -837,8 +840,8 @@
 	release_region(TLCLK_BASE, 8);
 out2:
 	kfree(alarm_events);
-out1:
 	unregister_chrdev(tlclk_major, "telco_clock");
+out1:
 	return ret;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/tpm/eventlog/common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/tpm/eventlog/common.c
@@ -47,6 +47,8 @@
 	if (!err) {
 		seq = file->private_data;
 		seq->private = chip;
+	} else {
+		put_device(&chip->dev);
 	}
 
 	return err;
@@ -99,20 +101,20 @@
  *
  * If an event log is found then the securityfs files are setup to
  * export it to userspace, otherwise nothing is done.
- *
- * Returns -ENODEV if the firmware has no event log or securityfs is not
- * supported.
  */
-int tpm_bios_log_setup(struct tpm_chip *chip)
+void tpm_bios_log_setup(struct tpm_chip *chip)
 {
 	const char *name = dev_name(&chip->dev);
 	unsigned int cnt;
 	int log_version;
 	int rc = 0;
 
+	if (chip->flags & TPM_CHIP_FLAG_VIRTUAL)
+		return;
+
 	rc = tpm_read_log(chip);
 	if (rc < 0)
-		return rc;
+		return;
 	log_version = rc;
 
 	cnt = 0;
@@ -158,13 +160,12 @@
 		cnt++;
 	}
 
-	return 0;
+	return;
 
 err:
-	rc = PTR_ERR(chip->bios_dir[cnt]);
 	chip->bios_dir[cnt] = NULL;
 	tpm_bios_log_teardown(chip);
-	return rc;
+	return;
 }
 
 void tpm_bios_log_teardown(struct tpm_chip *chip)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/tpm/eventlog/efi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/tpm/eventlog/efi.c
@@ -17,6 +17,7 @@
 {
 
 	struct efi_tcg2_final_events_table *final_tbl = NULL;
+	int final_events_log_size = efi_tpm_final_log_size;
 	struct linux_efi_tpm_eventlog *log_tbl;
 	struct tpm_bios_log *log;
 	u32 log_size;
@@ -41,6 +42,11 @@
 	log_size = log_tbl->size;
 	memunmap(log_tbl);
 
+	if (!log_size) {
+		pr_warn("UEFI TPM log area empty\n");
+		return -EIO;
+	}
+
 	log_tbl = memremap(efi.tpm_log, sizeof(*log_tbl) + log_size,
 			   MEMREMAP_WB);
 	if (!log_tbl) {
@@ -61,12 +67,12 @@
 	ret = tpm_log_version;
 
 	if (efi.tpm_final_log == EFI_INVALID_TABLE_ADDR ||
-	    efi_tpm_final_log_size == 0 ||
+	    final_events_log_size == 0 ||
 	    tpm_log_version != EFI_TCG2_EVENT_LOG_FORMAT_TCG_2)
 		goto out;
 
 	final_tbl = memremap(efi.tpm_final_log,
-			     sizeof(*final_tbl) + efi_tpm_final_log_size,
+			     sizeof(*final_tbl) + final_events_log_size,
 			     MEMREMAP_WB);
 	if (!final_tbl) {
 		pr_err("Could not map UEFI TPM final log\n");
@@ -75,10 +81,18 @@
 		goto out;
 	}
 
-	efi_tpm_final_log_size -= log_tbl->final_events_preboot_size;
+	/*
+	 * The 'final events log' size excludes the 'final events preboot log'
+	 * at its beginning.
+	 */
+	final_events_log_size -= log_tbl->final_events_preboot_size;
 
+	/*
+	 * Allocate memory for the 'combined log' where we will append the
+	 * 'final events log' to.
+	 */
 	tmp = krealloc(log->bios_event_log,
-		       log_size + efi_tpm_final_log_size,
+		       log_size + final_events_log_size,
 		       GFP_KERNEL);
 	if (!tmp) {
 		kfree(log->bios_event_log);
@@ -89,15 +103,19 @@
 	log->bios_event_log = tmp;
 
 	/*
-	 * Copy any of the final events log that didn't also end up in the
-	 * main log. Events can be logged in both if events are generated
+	 * Append any of the 'final events log' that didn't also end up in the
+	 * 'main log'. Events can be logged in both if events are generated
 	 * between GetEventLog() and ExitBootServices().
 	 */
 	memcpy((void *)log->bios_event_log + log_size,
 	       final_tbl->events + log_tbl->final_events_preboot_size,
-	       efi_tpm_final_log_size);
+	       final_events_log_size);
+	/*
+	 * The size of the 'combined log' is the size of the 'main log' plus
+	 * the size of the 'final events log'.
+	 */
 	log->bios_event_log_end = log->bios_event_log +
-		log_size + efi_tpm_final_log_size;
+		log_size + final_events_log_size;
 
 out:
 	memunmap(final_tbl);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/tpm/eventlog/tpm1.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/tpm/eventlog/tpm1.c
@@ -115,6 +115,7 @@
 	u32 converted_event_size;
 	u32 converted_event_type;
 
+	(*pos)++;
 	converted_event_size = do_endian_conversion(event->event_size);
 
 	v += sizeof(struct tcpa_event) + converted_event_size;
@@ -132,7 +133,6 @@
 	    ((v + sizeof(struct tcpa_event) + converted_event_size) > limit))
 		return NULL;
 
-	(*pos)++;
 	return v;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/tpm/eventlog/tpm2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/tpm/eventlog/tpm2.c
@@ -94,6 +94,7 @@
 	size_t event_size;
 	void *marker;
 
+	(*pos)++;
 	event_header = log->bios_event_log;
 
 	if (v == SEQ_START_TOKEN) {
@@ -118,7 +119,6 @@
 	if (((v + event_size) >= limit) || (event_size == 0))
 		return NULL;
 
-	(*pos)++;
 	return v;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/tpm/tpm-chip.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/tpm/tpm-chip.c
@@ -274,14 +274,6 @@
 	kfree(chip);
 }
 
-static void tpm_devs_release(struct device *dev)
-{
-	struct tpm_chip *chip = container_of(dev, struct tpm_chip, devs);
-
-	/* release the master device reference */
-	put_device(&chip->dev);
-}
-
 /**
  * tpm_class_shutdown() - prepare the TPM device for loss of power.
  * @dev: device to which the chip is associated.
@@ -344,7 +336,6 @@
 	chip->dev_num = rc;
 
 	device_initialize(&chip->dev);
-	device_initialize(&chip->devs);
 
 	chip->dev.class = tpm_class;
 	chip->dev.class->shutdown_pre = tpm_class_shutdown;
@@ -352,47 +343,23 @@
 	chip->dev.parent = pdev;
 	chip->dev.groups = chip->groups;
 
-	chip->devs.parent = pdev;
-	chip->devs.class = tpmrm_class;
-	chip->devs.release = tpm_devs_release;
-	/* get extra reference on main device to hold on
-	 * behalf of devs.  This holds the chip structure
-	 * while cdevs is in use.  The corresponding put
-	 * is in the tpm_devs_release (TPM2 only)
-	 */
-	if (chip->flags & TPM_CHIP_FLAG_TPM2)
-		get_device(&chip->dev);
-
 	if (chip->dev_num == 0)
 		chip->dev.devt = MKDEV(MISC_MAJOR, TPM_MINOR);
 	else
 		chip->dev.devt = MKDEV(MAJOR(tpm_devt), chip->dev_num);
 
-	chip->devs.devt =
-		MKDEV(MAJOR(tpm_devt), chip->dev_num + TPM_NUM_DEVICES);
-
 	rc = dev_set_name(&chip->dev, "tpm%d", chip->dev_num);
 	if (rc)
 		goto out;
-	rc = dev_set_name(&chip->devs, "tpmrm%d", chip->dev_num);
-	if (rc)
-		goto out;
 
 	if (!pdev)
 		chip->flags |= TPM_CHIP_FLAG_VIRTUAL;
 
 	cdev_init(&chip->cdev, &tpm_fops);
-	cdev_init(&chip->cdevs, &tpmrm_fops);
 	chip->cdev.owner = THIS_MODULE;
-	chip->cdevs.owner = THIS_MODULE;
 
-	chip->work_space.context_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
-	if (!chip->work_space.context_buf) {
-		rc = -ENOMEM;
-		goto out;
-	}
-	chip->work_space.session_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
-	if (!chip->work_space.session_buf) {
+	rc = tpm2_init_space(&chip->work_space, TPM2_SPACE_BUFFER_SIZE);
+	if (rc) {
 		rc = -ENOMEM;
 		goto out;
 	}
@@ -401,7 +368,6 @@
 	return chip;
 
 out:
-	put_device(&chip->devs);
 	put_device(&chip->dev);
 	return ERR_PTR(rc);
 }
@@ -450,14 +416,9 @@
 	}
 
 	if (chip->flags & TPM_CHIP_FLAG_TPM2) {
-		rc = cdev_device_add(&chip->cdevs, &chip->devs);
-		if (rc) {
-			dev_err(&chip->devs,
-				"unable to cdev_device_add() %s, major %d, minor %d, err=%d\n",
-				dev_name(&chip->devs), MAJOR(chip->devs.devt),
-				MINOR(chip->devs.devt), rc);
-			return rc;
-		}
+		rc = tpm_devs_add(chip);
+		if (rc)
+			goto err_del_cdev;
 	}
 
 	/* Make the chip available. */
@@ -465,6 +426,10 @@
 	idr_replace(&dev_nums_idr, chip, chip->dev_num);
 	mutex_unlock(&idr_lock);
 
+	return 0;
+
+err_del_cdev:
+	cdev_device_del(&chip->cdev, &chip->dev);
 	return rc;
 }
 
@@ -596,9 +561,7 @@
 
 	tpm_sysfs_add_device(chip);
 
-	rc = tpm_bios_log_setup(chip);
-	if (rc != 0 && rc != -ENODEV)
-		return rc;
+	tpm_bios_log_setup(chip);
 
 	tpm_add_ppi(chip);
 
@@ -648,7 +611,7 @@
 		hwrng_unregister(&chip->hwrng);
 	tpm_bios_log_teardown(chip);
 	if (chip->flags & TPM_CHIP_FLAG_TPM2)
-		cdev_device_del(&chip->cdevs, &chip->devs);
+		tpm_devs_remove(chip);
 	tpm_del_char_device(chip);
 }
 EXPORT_SYMBOL_GPL(tpm_chip_unregister);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/tpm/tpm-dev-common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/tpm/tpm-dev-common.c
@@ -48,6 +48,8 @@
 
 	if (!ret)
 		ret = tpm2_commit_space(chip, space, buf, &len);
+	else
+		tpm2_flush_space(chip);
 
 out_rc:
 	return ret ? ret : len;
@@ -61,13 +63,26 @@
 
 	mutex_lock(&priv->buffer_mutex);
 	priv->command_enqueued = false;
+	ret = tpm_try_get_ops(priv->chip);
+	if (ret) {
+		priv->response_length = ret;
+		goto out;
+	}
+
 	ret = tpm_dev_transmit(priv->chip, priv->space, priv->data_buffer,
 			       sizeof(priv->data_buffer));
 	tpm_put_ops(priv->chip);
-	if (ret > 0) {
+
+	/*
+	 * If ret is > 0 then tpm_dev_transmit returned the size of the
+	 * response. If ret is < 0 then tpm_dev_transmit failed and
+	 * returned an error code.
+	 */
+	if (ret != 0) {
 		priv->response_length = ret;
 		mod_timer(&priv->user_read_timer, jiffies + (120 * HZ));
 	}
+out:
 	mutex_unlock(&priv->buffer_mutex);
 	wake_up_interruptible(&priv->async_wait);
 }
@@ -123,7 +138,7 @@
 		priv->response_read = true;
 
 		ret_size = min_t(ssize_t, size, priv->response_length);
-		if (!ret_size) {
+		if (ret_size <= 0) {
 			priv->response_length = 0;
 			goto out;
 		}
@@ -143,7 +158,7 @@
 out:
 	if (!priv->response_length) {
 		*off = 0;
-		del_singleshot_timer_sync(&priv->user_read_timer);
+		del_timer_sync(&priv->user_read_timer);
 		flush_work(&priv->timeout_work);
 	}
 	mutex_unlock(&priv->buffer_mutex);
@@ -182,15 +197,6 @@
 		goto out;
 	}
 
-	/* atomic tpm command send and result receive. We only hold the ops
-	 * lock during this period so that the tpm can be unregistered even if
-	 * the char dev is held open.
-	 */
-	if (tpm_try_get_ops(priv->chip)) {
-		ret = -EPIPE;
-		goto out;
-	}
-
 	priv->response_length = 0;
 	priv->response_read = false;
 	*off = 0;
@@ -208,6 +214,15 @@
 		return size;
 	}
 
+	/* atomic tpm command send and result receive. We only hold the ops
+	 * lock during this period so that the tpm can be unregistered even if
+	 * the char dev is held open.
+	 */
+	if (tpm_try_get_ops(priv->chip)) {
+		ret = -EPIPE;
+		goto out;
+	}
+
 	ret = tpm_dev_transmit(priv->chip, priv->space, priv->data_buffer,
 			       sizeof(priv->data_buffer));
 	tpm_put_ops(priv->chip);
@@ -250,7 +265,7 @@
 void tpm_common_release(struct file *file, struct file_priv *priv)
 {
 	flush_work(&priv->async_work);
-	del_singleshot_timer_sync(&priv->user_read_timer);
+	del_timer_sync(&priv->user_read_timer);
 	flush_work(&priv->timeout_work);
 	file->private_data = NULL;
 	priv->response_length = 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/tpm/tpm-dev.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/tpm/tpm-dev.h
@@ -14,7 +14,7 @@
 	struct work_struct timeout_work;
 	struct work_struct async_work;
 	wait_queue_head_t async_wait;
-	size_t response_length;
+	ssize_t response_length;
 	bool response_read;
 	bool command_enqueued;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/tpm/tpm-interface.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/tpm/tpm-interface.c
@@ -322,7 +322,7 @@
 
 	for (i = 0; i < chip->nr_allocated_banks; i++) {
 		if (digests[i].alg_id != chip->allocated_banks[i].alg_id) {
-			rc = EINVAL;
+			rc = -EINVAL;
 			goto out;
 		}
 	}
@@ -396,13 +396,14 @@
 	if (chip->flags & TPM_CHIP_FLAG_ALWAYS_POWERED)
 		return 0;
 
-	if (!tpm_chip_start(chip)) {
+	rc = tpm_try_get_ops(chip);
+	if (!rc) {
 		if (chip->flags & TPM_CHIP_FLAG_TPM2)
 			tpm2_shutdown(chip, TPM2_SU_STATE);
 		else
 			rc = tpm1_pm_suspend(chip, tpm_suspend_pcr);
 
-		tpm_chip_stop(chip);
+		tpm_put_ops(chip);
 	}
 
 	return rc;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/tpm/tpm.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/tpm/tpm.h
@@ -177,6 +177,9 @@
 
 #define TPM_TAG_RQU_COMMAND 193
 
+/* TPM2 specific constants. */
+#define TPM2_SPACE_BUFFER_SIZE		16384 /* 16 kB */
+
 struct	stclear_flags_t {
 	__be16	tag;
 	u8	deactivated;
@@ -456,15 +459,17 @@
 unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
 int tpm2_probe(struct tpm_chip *chip);
 int tpm2_find_cc(struct tpm_chip *chip, u32 cc);
-int tpm2_init_space(struct tpm_space *space);
+int tpm2_init_space(struct tpm_space *space, unsigned int buf_size);
 void tpm2_del_space(struct tpm_chip *chip, struct tpm_space *space);
 void tpm2_flush_space(struct tpm_chip *chip);
 int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space, u8 *cmd,
 		       size_t cmdsiz);
 int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space, void *buf,
 		      size_t *bufsiz);
+int tpm_devs_add(struct tpm_chip *chip);
+void tpm_devs_remove(struct tpm_chip *chip);
 
-int tpm_bios_log_setup(struct tpm_chip *chip);
+void tpm_bios_log_setup(struct tpm_chip *chip);
 void tpm_bios_log_teardown(struct tpm_chip *chip);
 int tpm_dev_common_init(void);
 void tpm_dev_common_exit(void);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/tpm/tpm2-cmd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/tpm/tpm2-cmd.c
@@ -706,7 +706,16 @@
 	if (!rc) {
 		out = (struct tpm2_get_cap_out *)
 			&buf.data[TPM_HEADER_SIZE];
-		*value = be32_to_cpu(out->value);
+		/*
+		 * To prevent failing boot up of some systems, Infineon TPM2.0
+		 * returns SUCCESS on TPM2_Startup in field upgrade mode. Also
+		 * the TPM2_Getcapability command returns a zero length list
+		 * in field upgrade mode.
+		 */
+		if (be32_to_cpu(out->property_cnt) > 0)
+			*value = be32_to_cpu(out->value);
+		else
+			rc = -ENODATA;
 	}
 	tpm_buf_destroy(&buf);
 	return rc;
@@ -831,6 +840,8 @@
 		return 0;
 	}
 
+	bank->crypto_id = HASH_ALGO__LAST;
+
 	return tpm2_pcr_read(chip, 0, &digest, &bank->digest_size);
 }
 
@@ -939,6 +950,10 @@
 
 	chip->cc_attrs_tbl = devm_kcalloc(&chip->dev, 4, nr_commands,
 					  GFP_KERNEL);
+	if (!chip->cc_attrs_tbl) {
+		rc = -ENOMEM;
+		goto out;
+	}
 
 	rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY);
 	if (rc)
@@ -956,6 +971,7 @@
 
 	if (nr_commands !=
 	    be32_to_cpup((__be32 *)&buf.data[TPM_HEADER_SIZE + 5])) {
+		rc = -EFAULT;
 		tpm_buf_destroy(&buf);
 		goto out;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/tpm/tpm2-space.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/tpm/tpm2-space.c
@@ -38,29 +38,32 @@
 	}
 }
 
-int tpm2_init_space(struct tpm_space *space)
+int tpm2_init_space(struct tpm_space *space, unsigned int buf_size)
 {
-	space->context_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
+	space->context_buf = kzalloc(buf_size, GFP_KERNEL);
 	if (!space->context_buf)
 		return -ENOMEM;
 
-	space->session_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
+	space->session_buf = kzalloc(buf_size, GFP_KERNEL);
 	if (space->session_buf == NULL) {
 		kfree(space->context_buf);
+		/* Prevent caller getting a dangling pointer. */
+		space->context_buf = NULL;
 		return -ENOMEM;
 	}
 
+	space->buf_size = buf_size;
 	return 0;
 }
 
 void tpm2_del_space(struct tpm_chip *chip, struct tpm_space *space)
 {
-	mutex_lock(&chip->tpm_mutex);
-	if (!tpm_chip_start(chip)) {
+
+	if (tpm_try_get_ops(chip) == 0) {
 		tpm2_flush_sessions(chip, space);
-		tpm_chip_stop(chip);
+		tpm_put_ops(chip);
 	}
-	mutex_unlock(&chip->tpm_mutex);
+
 	kfree(space->context_buf);
 	kfree(space->session_buf);
 }
@@ -163,6 +166,9 @@
 	struct tpm_space *space = &chip->work_space;
 	int i;
 
+	if (!space)
+		return;
+
 	for (i = 0; i < ARRAY_SIZE(space->context_tbl); i++)
 		if (space->context_tbl[i] && ~space->context_tbl[i])
 			tpm2_flush_context(chip, space->context_tbl[i]);
@@ -311,8 +317,10 @@
 	       sizeof(space->context_tbl));
 	memcpy(&chip->work_space.session_tbl, &space->session_tbl,
 	       sizeof(space->session_tbl));
-	memcpy(chip->work_space.context_buf, space->context_buf, PAGE_SIZE);
-	memcpy(chip->work_space.session_buf, space->session_buf, PAGE_SIZE);
+	memcpy(chip->work_space.context_buf, space->context_buf,
+	       space->buf_size);
+	memcpy(chip->work_space.session_buf, space->session_buf,
+	       space->buf_size);
 
 	rc = tpm2_load_space(chip);
 	if (rc) {
@@ -450,6 +458,9 @@
 	if (be32_to_cpu(data->capability) != TPM2_CAP_HANDLES)
 		return 0;
 
+	if (be32_to_cpu(data->count) > (UINT_MAX - TPM_HEADER_SIZE - 9) / 4)
+		return -EFAULT;
+
 	if (len != TPM_HEADER_SIZE + 9 + 4 * be32_to_cpu(data->count))
 		return -EFAULT;
 
@@ -492,7 +503,7 @@
 			continue;
 
 		rc = tpm2_save_context(chip, space->context_tbl[i],
-				       space->context_buf, PAGE_SIZE,
+				       space->context_buf, space->buf_size,
 				       &offset);
 		if (rc == -ENOENT) {
 			space->context_tbl[i] = 0;
@@ -509,9 +520,8 @@
 			continue;
 
 		rc = tpm2_save_context(chip, space->session_tbl[i],
-				       space->session_buf, PAGE_SIZE,
+				       space->session_buf, space->buf_size,
 				       &offset);
-
 		if (rc == -ENOENT) {
 			/* handle error saving session, just forget it */
 			space->session_tbl[i] = 0;
@@ -557,11 +567,78 @@
 	       sizeof(space->context_tbl));
 	memcpy(&space->session_tbl, &chip->work_space.session_tbl,
 	       sizeof(space->session_tbl));
-	memcpy(space->context_buf, chip->work_space.context_buf, PAGE_SIZE);
-	memcpy(space->session_buf, chip->work_space.session_buf, PAGE_SIZE);
+	memcpy(space->context_buf, chip->work_space.context_buf,
+	       space->buf_size);
+	memcpy(space->session_buf, chip->work_space.session_buf,
+	       space->buf_size);
 
 	return 0;
 out:
 	dev_err(&chip->dev, "%s: error %d\n", __func__, rc);
 	return rc;
 }
+
+/*
+ * Put the reference to the main device.
+ */
+static void tpm_devs_release(struct device *dev)
+{
+	struct tpm_chip *chip = container_of(dev, struct tpm_chip, devs);
+
+	/* release the master device reference */
+	put_device(&chip->dev);
+}
+
+/*
+ * Remove the device file for exposed TPM spaces and release the device
+ * reference. This may also release the reference to the master device.
+ */
+void tpm_devs_remove(struct tpm_chip *chip)
+{
+	cdev_device_del(&chip->cdevs, &chip->devs);
+	put_device(&chip->devs);
+}
+
+/*
+ * Add a device file to expose TPM spaces. Also take a reference to the
+ * main device.
+ */
+int tpm_devs_add(struct tpm_chip *chip)
+{
+	int rc;
+
+	device_initialize(&chip->devs);
+	chip->devs.parent = chip->dev.parent;
+	chip->devs.class = tpmrm_class;
+
+	/*
+	 * Get extra reference on main device to hold on behalf of devs.
+	 * This holds the chip structure while cdevs is in use. The
+	 * corresponding put is in the tpm_devs_release.
+	 */
+	get_device(&chip->dev);
+	chip->devs.release = tpm_devs_release;
+	chip->devs.devt = MKDEV(MAJOR(tpm_devt), chip->dev_num + TPM_NUM_DEVICES);
+	cdev_init(&chip->cdevs, &tpmrm_fops);
+	chip->cdevs.owner = THIS_MODULE;
+
+	rc = dev_set_name(&chip->devs, "tpmrm%d", chip->dev_num);
+	if (rc)
+		goto err_put_devs;
+
+	rc = cdev_device_add(&chip->cdevs, &chip->devs);
+	if (rc) {
+		dev_err(&chip->devs,
+			"unable to cdev_device_add() %s, major %d, minor %d, err=%d\n",
+			dev_name(&chip->devs), MAJOR(chip->devs.devt),
+			MINOR(chip->devs.devt), rc);
+		goto err_put_devs;
+	}
+
+	return 0;
+
+err_put_devs:
+	put_device(&chip->devs);
+
+	return rc;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/tpm/tpm_crb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/tpm/tpm_crb.c
@@ -22,6 +22,7 @@
 #include "tpm.h"
 
 #define ACPI_SIG_TPM2 "TPM2"
+#define TPM_CRB_MAX_RESOURCES 3
 
 static const guid_t crb_acpi_start_guid =
 	GUID_INIT(0x6BBF6CAB, 0x5463, 0x4714,
@@ -91,7 +92,6 @@
 struct crb_priv {
 	u32 sm;
 	const char *hid;
-	void __iomem *iobase;
 	struct crb_regs_head __iomem *regs_h;
 	struct crb_regs_tail __iomem *regs_t;
 	u8 __iomem *cmd;
@@ -252,7 +252,7 @@
 	iowrite32(CRB_LOC_CTRL_RELINQUISH, &priv->regs_h->loc_ctrl);
 	if (!crb_wait_for_reg_32(&priv->regs_h->loc_state, mask, value,
 				 TPM2_TIMEOUT_C)) {
-		dev_warn(dev, "TPM_LOC_STATE_x.requestAccess timed out\n");
+		dev_warn(dev, "TPM_LOC_STATE_x.Relinquish timed out\n");
 		return -ETIME;
 	}
 
@@ -434,21 +434,27 @@
 
 static int crb_check_resource(struct acpi_resource *ares, void *data)
 {
-	struct resource *io_res = data;
+	struct resource *iores_array = data;
 	struct resource_win win;
 	struct resource *res = &(win.res);
+	int i;
 
 	if (acpi_dev_resource_memory(ares, res) ||
 	    acpi_dev_resource_address_space(ares, &win)) {
-		*io_res = *res;
-		io_res->name = NULL;
+		for (i = 0; i < TPM_CRB_MAX_RESOURCES + 1; ++i) {
+			if (resource_type(iores_array + i) != IORESOURCE_MEM) {
+				iores_array[i] = *res;
+				iores_array[i].name = NULL;
+				break;
+			}
+		}
 	}
 
 	return 1;
 }
 
-static void __iomem *crb_map_res(struct device *dev, struct crb_priv *priv,
-				 struct resource *io_res, u64 start, u32 size)
+static void __iomem *crb_map_res(struct device *dev, struct resource *iores,
+				 void __iomem **iobase_ptr, u64 start, u32 size)
 {
 	struct resource new_res = {
 		.start	= start,
@@ -460,10 +466,16 @@
 	if (start != new_res.start)
 		return (void __iomem *) ERR_PTR(-EINVAL);
 
-	if (!resource_contains(io_res, &new_res))
+	if (!iores)
 		return devm_ioremap_resource(dev, &new_res);
 
-	return priv->iobase + (new_res.start - io_res->start);
+	if (!*iobase_ptr) {
+		*iobase_ptr = devm_ioremap_resource(dev, iores);
+		if (IS_ERR(*iobase_ptr))
+			return *iobase_ptr;
+	}
+
+	return *iobase_ptr + (new_res.start - iores->start);
 }
 
 /*
@@ -490,9 +502,13 @@
 static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
 		      struct acpi_table_tpm2 *buf)
 {
-	struct list_head resources;
-	struct resource io_res;
+	struct list_head acpi_resource_list;
+	struct resource iores_array[TPM_CRB_MAX_RESOURCES + 1] = { {0} };
+	void __iomem *iobase_array[TPM_CRB_MAX_RESOURCES] = {NULL};
 	struct device *dev = &device->dev;
+	struct resource *iores;
+	void __iomem **iobase_ptr;
+	int i;
 	u32 pa_high, pa_low;
 	u64 cmd_pa;
 	u32 cmd_size;
@@ -501,21 +517,41 @@
 	u32 rsp_size;
 	int ret;
 
-	INIT_LIST_HEAD(&resources);
-	ret = acpi_dev_get_resources(device, &resources, crb_check_resource,
-				     &io_res);
+	INIT_LIST_HEAD(&acpi_resource_list);
+	ret = acpi_dev_get_resources(device, &acpi_resource_list,
+				     crb_check_resource, iores_array);
 	if (ret < 0)
 		return ret;
-	acpi_dev_free_resource_list(&resources);
+	acpi_dev_free_resource_list(&acpi_resource_list);
 
-	if (resource_type(&io_res) != IORESOURCE_MEM) {
+	if (resource_type(iores_array) != IORESOURCE_MEM) {
 		dev_err(dev, FW_BUG "TPM2 ACPI table does not define a memory resource\n");
 		return -EINVAL;
+	} else if (resource_type(iores_array + TPM_CRB_MAX_RESOURCES) ==
+		IORESOURCE_MEM) {
+		dev_warn(dev, "TPM2 ACPI table defines too many memory resources\n");
+		memset(iores_array + TPM_CRB_MAX_RESOURCES,
+		       0, sizeof(*iores_array));
+		iores_array[TPM_CRB_MAX_RESOURCES].flags = 0;
+	}
+
+	iores = NULL;
+	iobase_ptr = NULL;
+	for (i = 0; resource_type(iores_array + i) == IORESOURCE_MEM; ++i) {
+		if (buf->control_address >= iores_array[i].start &&
+		    buf->control_address + sizeof(struct crb_regs_tail) - 1 <=
+		    iores_array[i].end) {
+			iores = iores_array + i;
+			iobase_ptr = iobase_array + i;
+			break;
+		}
 	}
 
-	priv->iobase = devm_ioremap_resource(dev, &io_res);
-	if (IS_ERR(priv->iobase))
-		return PTR_ERR(priv->iobase);
+	priv->regs_t = crb_map_res(dev, iores, iobase_ptr, buf->control_address,
+				   sizeof(struct crb_regs_tail));
+
+	if (IS_ERR(priv->regs_t))
+		return PTR_ERR(priv->regs_t);
 
 	/* The ACPI IO region starts at the head area and continues to include
 	 * the control area, as one nice sane region except for some older
@@ -523,9 +559,10 @@
 	 */
 	if ((priv->sm == ACPI_TPM2_COMMAND_BUFFER) ||
 	    (priv->sm == ACPI_TPM2_MEMORY_MAPPED)) {
-		if (buf->control_address == io_res.start +
+		if (iores &&
+		    buf->control_address == iores->start +
 		    sizeof(*priv->regs_h))
-			priv->regs_h = priv->iobase;
+			priv->regs_h = *iobase_ptr;
 		else
 			dev_warn(dev, FW_BUG "Bad ACPI memory layout");
 	}
@@ -534,13 +571,6 @@
 	if (ret)
 		return ret;
 
-	priv->regs_t = crb_map_res(dev, priv, &io_res, buf->control_address,
-				   sizeof(struct crb_regs_tail));
-	if (IS_ERR(priv->regs_t)) {
-		ret = PTR_ERR(priv->regs_t);
-		goto out_relinquish_locality;
-	}
-
 	/*
 	 * PTT HW bug w/a: wake up the device to access
 	 * possibly not retained registers.
@@ -552,13 +582,26 @@
 	pa_high = ioread32(&priv->regs_t->ctrl_cmd_pa_high);
 	pa_low  = ioread32(&priv->regs_t->ctrl_cmd_pa_low);
 	cmd_pa = ((u64)pa_high << 32) | pa_low;
-	cmd_size = crb_fixup_cmd_size(dev, &io_res, cmd_pa,
-				      ioread32(&priv->regs_t->ctrl_cmd_size));
+	cmd_size = ioread32(&priv->regs_t->ctrl_cmd_size);
+
+	iores = NULL;
+	iobase_ptr = NULL;
+	for (i = 0; iores_array[i].end; ++i) {
+		if (cmd_pa >= iores_array[i].start &&
+		    cmd_pa <= iores_array[i].end) {
+			iores = iores_array + i;
+			iobase_ptr = iobase_array + i;
+			break;
+		}
+	}
+
+	if (iores)
+		cmd_size = crb_fixup_cmd_size(dev, iores, cmd_pa, cmd_size);
 
 	dev_dbg(dev, "cmd_hi = %X cmd_low = %X cmd_size %X\n",
 		pa_high, pa_low, cmd_size);
 
-	priv->cmd = crb_map_res(dev, priv, &io_res, cmd_pa, cmd_size);
+	priv->cmd = crb_map_res(dev, iores, iobase_ptr,	cmd_pa, cmd_size);
 	if (IS_ERR(priv->cmd)) {
 		ret = PTR_ERR(priv->cmd);
 		goto out;
@@ -566,11 +609,25 @@
 
 	memcpy_fromio(&__rsp_pa, &priv->regs_t->ctrl_rsp_pa, 8);
 	rsp_pa = le64_to_cpu(__rsp_pa);
-	rsp_size = crb_fixup_cmd_size(dev, &io_res, rsp_pa,
-				      ioread32(&priv->regs_t->ctrl_rsp_size));
+	rsp_size = ioread32(&priv->regs_t->ctrl_rsp_size);
+
+	iores = NULL;
+	iobase_ptr = NULL;
+	for (i = 0; resource_type(iores_array + i) == IORESOURCE_MEM; ++i) {
+		if (rsp_pa >= iores_array[i].start &&
+		    rsp_pa <= iores_array[i].end) {
+			iores = iores_array + i;
+			iobase_ptr = iobase_array + i;
+			break;
+		}
+	}
+
+	if (iores)
+		rsp_size = crb_fixup_cmd_size(dev, iores, rsp_pa, rsp_size);
 
 	if (cmd_pa != rsp_pa) {
-		priv->rsp = crb_map_res(dev, priv, &io_res, rsp_pa, rsp_size);
+		priv->rsp = crb_map_res(dev, iores, iobase_ptr,
+					rsp_pa, rsp_size);
 		ret = PTR_ERR_OR_ZERO(priv->rsp);
 		goto out;
 	}
@@ -619,12 +676,16 @@
 
 	/* Should the FIFO driver handle this? */
 	sm = buf->start_method;
-	if (sm == ACPI_TPM2_MEMORY_MAPPED)
-		return -ENODEV;
+	if (sm == ACPI_TPM2_MEMORY_MAPPED) {
+		rc = -ENODEV;
+		goto out;
+	}
 
 	priv = devm_kzalloc(dev, sizeof(struct crb_priv), GFP_KERNEL);
-	if (!priv)
-		return -ENOMEM;
+	if (!priv) {
+		rc = -ENOMEM;
+		goto out;
+	}
 
 	if (sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC) {
 		if (buf->header.length < (sizeof(*buf) + sizeof(*crb_smc))) {
@@ -632,7 +693,8 @@
 				FW_BUG "TPM2 ACPI table has wrong size %u for start method type %d\n",
 				buf->header.length,
 				ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC);
-			return -EINVAL;
+			rc = -EINVAL;
+			goto out;
 		}
 		crb_smc = ACPI_ADD_PTR(struct tpm2_crb_smc, buf, sizeof(*buf));
 		priv->smc_func_id = crb_smc->smc_func_id;
@@ -643,17 +705,23 @@
 
 	rc = crb_map_io(device, priv, buf);
 	if (rc)
-		return rc;
+		goto out;
 
 	chip = tpmm_chip_alloc(dev, &tpm_crb);
-	if (IS_ERR(chip))
-		return PTR_ERR(chip);
+	if (IS_ERR(chip)) {
+		rc = PTR_ERR(chip);
+		goto out;
+	}
 
 	dev_set_drvdata(&chip->dev, priv);
 	chip->acpi_dev_handle = device->handle;
 	chip->flags = TPM_CHIP_FLAG_TPM2;
 
-	return tpm_chip_register(chip);
+	rc = tpm_chip_register(chip);
+
+out:
+	acpi_put_table((struct acpi_table_header *)buf);
+	return rc;
 }
 
 static int crb_acpi_remove(struct acpi_device *device)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/tpm/tpm_ftpm_tee.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/tpm/tpm_ftpm_tee.c
@@ -32,7 +32,7 @@
 		  0x82, 0xCB, 0x34, 0x3F, 0xB7, 0xF3, 0x78, 0x96);
 
 /**
- * ftpm_tee_tpm_op_recv - retrieve fTPM response.
+ * ftpm_tee_tpm_op_recv() - retrieve fTPM response.
  * @chip:	the tpm_chip description as specified in driver/char/tpm/tpm.h.
  * @buf:	the buffer to store data.
  * @count:	the number of bytes to read.
@@ -61,7 +61,7 @@
 }
 
 /**
- * ftpm_tee_tpm_op_send - send TPM commands through the TEE shared memory.
+ * ftpm_tee_tpm_op_send() - send TPM commands through the TEE shared memory.
  * @chip:	the tpm_chip description as specified in driver/char/tpm/tpm.h
  * @buf:	the buffer to send.
  * @len:	the number of bytes to send.
@@ -208,7 +208,7 @@
 }
 
 /**
- * ftpm_tee_probe - initialize the fTPM
+ * ftpm_tee_probe() - initialize the fTPM
  * @pdev: the platform_device description.
  *
  * Return:
@@ -255,11 +255,11 @@
 	pvt_data->session = sess_arg.session;
 
 	/* Allocate dynamic shared memory with fTPM TA */
-	pvt_data->shm = tee_shm_alloc(pvt_data->ctx,
-				      MAX_COMMAND_SIZE + MAX_RESPONSE_SIZE,
-				      TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
+	pvt_data->shm = tee_shm_alloc_kernel_buf(pvt_data->ctx,
+						 MAX_COMMAND_SIZE +
+						 MAX_RESPONSE_SIZE);
 	if (IS_ERR(pvt_data->shm)) {
-		dev_err(dev, "%s: tee_shm_alloc failed\n", __func__);
+		dev_err(dev, "%s: tee_shm_alloc_kernel_buf failed\n", __func__);
 		rc = -ENOMEM;
 		goto out_shm_alloc;
 	}
@@ -298,7 +298,7 @@
 }
 
 /**
- * ftpm_tee_remove - remove the TPM device
+ * ftpm_tee_remove() - remove the TPM device
  * @pdev: the platform_device description.
  *
  * Return:
@@ -328,6 +328,19 @@
 	return 0;
 }
 
+/**
+ * ftpm_tee_shutdown() - shutdown the TPM device
+ * @pdev: the platform_device description.
+ */
+static void ftpm_tee_shutdown(struct platform_device *pdev)
+{
+	struct ftpm_tee_private *pvt_data = dev_get_drvdata(&pdev->dev);
+
+	tee_shm_free(pvt_data->shm);
+	tee_client_close_session(pvt_data->ctx, pvt_data->session);
+	tee_client_close_context(pvt_data->ctx);
+}
+
 static const struct of_device_id of_ftpm_tee_ids[] = {
 	{ .compatible = "microsoft,ftpm" },
 	{ }
@@ -341,6 +354,7 @@
 	},
 	.probe = ftpm_tee_probe,
 	.remove = ftpm_tee_remove,
+	.shutdown = ftpm_tee_shutdown,
 };
 
 module_platform_driver(ftpm_tee_driver);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/tpm/tpm_ibmvtpm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/tpm/tpm_ibmvtpm.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (C) 2012 IBM Corporation
+ * Copyright (C) 2012-2020 IBM Corporation
  *
  * Author: Ashley Lai <ashleydlai@gmail.com>
  *
@@ -134,6 +134,64 @@
 }
 
 /**
+ * ibmvtpm_crq_send_init - Send a CRQ initialize message
+ * @ibmvtpm:	vtpm device struct
+ *
+ * Return:
+ *	0 on success.
+ *	Non-zero on failure.
+ */
+static int ibmvtpm_crq_send_init(struct ibmvtpm_dev *ibmvtpm)
+{
+	int rc;
+
+	rc = ibmvtpm_send_crq_word(ibmvtpm->vdev, INIT_CRQ_CMD);
+	if (rc != H_SUCCESS)
+		dev_err(ibmvtpm->dev,
+			"%s failed rc=%d\n", __func__, rc);
+
+	return rc;
+}
+
+/**
+ * tpm_ibmvtpm_resume - Resume from suspend
+ *
+ * @dev:	device struct
+ *
+ * Return: Always 0.
+ */
+static int tpm_ibmvtpm_resume(struct device *dev)
+{
+	struct tpm_chip *chip = dev_get_drvdata(dev);
+	struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev);
+	int rc = 0;
+
+	do {
+		if (rc)
+			msleep(100);
+		rc = plpar_hcall_norets(H_ENABLE_CRQ,
+					ibmvtpm->vdev->unit_address);
+	} while (rc == H_IN_PROGRESS || rc == H_BUSY || H_IS_LONG_BUSY(rc));
+
+	if (rc) {
+		dev_err(dev, "Error enabling ibmvtpm rc=%d\n", rc);
+		return rc;
+	}
+
+	rc = vio_enable_interrupts(ibmvtpm->vdev);
+	if (rc) {
+		dev_err(dev, "Error vio_enable_interrupts rc=%d\n", rc);
+		return rc;
+	}
+
+	rc = ibmvtpm_crq_send_init(ibmvtpm);
+	if (rc)
+		dev_err(dev, "Error send_init rc=%d\n", rc);
+
+	return rc;
+}
+
+/**
  * tpm_ibmvtpm_send() - Send a TPM command
  * @chip:	tpm chip struct
  * @buf:	buffer contains data to send
@@ -146,6 +204,7 @@
 static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
 {
 	struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev);
+	bool retry = true;
 	int rc, sig;
 
 	if (!ibmvtpm->rtce_buf) {
@@ -179,18 +238,27 @@
 	 */
 	ibmvtpm->tpm_processing_cmd = true;
 
+again:
 	rc = ibmvtpm_send_crq(ibmvtpm->vdev,
 			IBMVTPM_VALID_CMD, VTPM_TPM_COMMAND,
 			count, ibmvtpm->rtce_dma_handle);
 	if (rc != H_SUCCESS) {
+		/*
+		 * H_CLOSED can be returned after LPM resume.  Call
+		 * tpm_ibmvtpm_resume() to re-enable the CRQ then retry
+		 * ibmvtpm_send_crq() once before failing.
+		 */
+		if (rc == H_CLOSED && retry) {
+			tpm_ibmvtpm_resume(ibmvtpm->dev);
+			retry = false;
+			goto again;
+		}
 		dev_err(ibmvtpm->dev, "tpm_ibmvtpm_send failed rc=%d\n", rc);
-		rc = 0;
 		ibmvtpm->tpm_processing_cmd = false;
-	} else
-		rc = 0;
+	}
 
 	spin_unlock(&ibmvtpm->rtce_lock);
-	return rc;
+	return 0;
 }
 
 static void tpm_ibmvtpm_cancel(struct tpm_chip *chip)
@@ -269,26 +337,6 @@
 }
 
 /**
- * ibmvtpm_crq_send_init - Send a CRQ initialize message
- * @ibmvtpm:	vtpm device struct
- *
- * Return:
- *	0 on success.
- *	Non-zero on failure.
- */
-static int ibmvtpm_crq_send_init(struct ibmvtpm_dev *ibmvtpm)
-{
-	int rc;
-
-	rc = ibmvtpm_send_crq_word(ibmvtpm->vdev, INIT_CRQ_CMD);
-	if (rc != H_SUCCESS)
-		dev_err(ibmvtpm->dev,
-			"ibmvtpm_crq_send_init failed rc=%d\n", rc);
-
-	return rc;
-}
-
-/**
  * tpm_ibmvtpm_remove - ibm vtpm remove entry point
  * @vdev:	vio device struct
  *
@@ -400,44 +448,6 @@
 				  ibmvtpm->crq_dma_handle, CRQ_RES_BUF_SIZE);
 }
 
-/**
- * tpm_ibmvtpm_resume - Resume from suspend
- *
- * @dev:	device struct
- *
- * Return: Always 0.
- */
-static int tpm_ibmvtpm_resume(struct device *dev)
-{
-	struct tpm_chip *chip = dev_get_drvdata(dev);
-	struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev);
-	int rc = 0;
-
-	do {
-		if (rc)
-			msleep(100);
-		rc = plpar_hcall_norets(H_ENABLE_CRQ,
-					ibmvtpm->vdev->unit_address);
-	} while (rc == H_IN_PROGRESS || rc == H_BUSY || H_IS_LONG_BUSY(rc));
-
-	if (rc) {
-		dev_err(dev, "Error enabling ibmvtpm rc=%d\n", rc);
-		return rc;
-	}
-
-	rc = vio_enable_interrupts(ibmvtpm->vdev);
-	if (rc) {
-		dev_err(dev, "Error vio_enable_interrupts rc=%d\n", rc);
-		return rc;
-	}
-
-	rc = ibmvtpm_crq_send_init(ibmvtpm);
-	if (rc)
-		dev_err(dev, "Error send_init rc=%d\n", rc);
-
-	return rc;
-}
-
 static bool tpm_ibmvtpm_req_canceled(struct tpm_chip *chip, u8 status)
 {
 	return (status == 0);
@@ -571,6 +581,7 @@
 	 */
 	while ((crq = ibmvtpm_crq_get_next(ibmvtpm)) != NULL) {
 		ibmvtpm_crq_process(crq, ibmvtpm);
+		wake_up_interruptible(&ibmvtpm->crq_queue.wq);
 		crq->valid = 0;
 		smp_wmb();
 	}
@@ -618,6 +629,7 @@
 	}
 
 	crq_q->num_entry = CRQ_RES_BUF_SIZE / sizeof(*crq_q->crq_addr);
+	init_waitqueue_head(&crq_q->wq);
 	ibmvtpm->crq_dma_handle = dma_map_single(dev, crq_q->crq_addr,
 						 CRQ_RES_BUF_SIZE,
 						 DMA_BIDIRECTIONAL);
@@ -670,6 +682,14 @@
 	if (rc)
 		goto init_irq_cleanup;
 
+	if (!wait_event_timeout(ibmvtpm->crq_queue.wq,
+				ibmvtpm->rtce_buf != NULL,
+				HZ)) {
+		rc = -ENODEV;
+		dev_err(dev, "CRQ response timed out\n");
+		goto init_irq_cleanup;
+	}
+
 	return tpm_chip_register(chip);
 init_irq_cleanup:
 	do {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/tpm/tpm_ibmvtpm.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/tpm/tpm_ibmvtpm.h
@@ -26,6 +26,7 @@
 	struct ibmvtpm_crq *crq_addr;
 	u32 index;
 	u32 num_entry;
+	wait_queue_head_t wq;
 };
 
 struct ibmvtpm_dev {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/tpm/tpm_tis.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/tpm/tpm_tis.c
@@ -27,6 +27,7 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/kernel.h>
+#include <linux/dmi.h>
 #include "tpm.h"
 #include "tpm_tis_core.h"
 
@@ -49,8 +50,8 @@
 	return container_of(data, struct tpm_tis_tcg_phy, priv);
 }
 
-static bool interrupts = true;
-module_param(interrupts, bool, 0444);
+static int interrupts = -1;
+module_param(interrupts, int, 0444);
 MODULE_PARM_DESC(interrupts, "Enable interrupts");
 
 static bool itpm;
@@ -63,6 +64,44 @@
 MODULE_PARM_DESC(force, "Force device probe rather than using ACPI entry");
 #endif
 
+static int tpm_tis_disable_irq(const struct dmi_system_id *d)
+{
+	if (interrupts == -1) {
+		pr_notice("tpm_tis: %s detected: disabling interrupts.\n", d->ident);
+		interrupts = 0;
+	}
+
+	return 0;
+}
+
+static const struct dmi_system_id tpm_tis_dmi_table[] = {
+	{
+		.callback = tpm_tis_disable_irq,
+		.ident = "ThinkPad T490s",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T490s"),
+		},
+	},
+	{
+		.callback = tpm_tis_disable_irq,
+		.ident = "ThinkStation P360 Tiny",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkStation P360 Tiny"),
+		},
+	},
+	{
+		.callback = tpm_tis_disable_irq,
+		.ident = "ThinkPad L490",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L490"),
+		},
+	},
+	{}
+};
+
 #if defined(CONFIG_PNP) && defined(CONFIG_ACPI)
 static int has_hid(struct acpi_device *dev, const char *hid)
 {
@@ -102,6 +141,7 @@
 	const struct acpi_device_id *aid = acpi_match_device(tpm_acpi_tbl, dev);
 	struct acpi_table_tpm2 *tbl;
 	acpi_status st;
+	int ret = 0;
 
 	if (!aid || aid->driver_data != DEVICE_IS_TPM2)
 		return 0;
@@ -109,8 +149,7 @@
 	/* If the ACPI TPM2 signature is matched then a global ACPI_SIG_TPM2
 	 * table is mandatory
 	 */
-	st =
-	    acpi_get_table(ACPI_SIG_TPM2, 1, (struct acpi_table_header **)&tbl);
+	st = acpi_get_table(ACPI_SIG_TPM2, 1, (struct acpi_table_header **)&tbl);
 	if (ACPI_FAILURE(st) || tbl->header.length < sizeof(*tbl)) {
 		dev_err(dev, FW_BUG "failed to get TPM2 ACPI table\n");
 		return -EINVAL;
@@ -118,9 +157,10 @@
 
 	/* The tpm2_crb driver handles this device */
 	if (tbl->start_method != ACPI_TPM2_MEMORY_MAPPED)
-		return -ENODEV;
+		ret = -ENODEV;
 
-	return 0;
+	acpi_put_table((struct acpi_table_header *)tbl);
+	return ret;
 }
 #else
 static int check_acpi_tpm2(struct device *dev)
@@ -192,6 +232,8 @@
 	int irq = -1;
 	int rc;
 
+	dmi_check_system(tpm_tis_dmi_table);
+
 	rc = check_acpi_tpm2(dev);
 	if (rc)
 		return rc;
@@ -286,7 +328,7 @@
 	}
 	tpm_info.res = *res;
 
-	tpm_info.irq = platform_get_irq(pdev, 0);
+	tpm_info.irq = platform_get_irq_optional(pdev, 0);
 	if (tpm_info.irq <= 0) {
 		if (pdev != force_pdev)
 			tpm_info.irq = -1;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/tpm/tpm_tis_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/tpm/tpm_tis_core.c
@@ -125,7 +125,8 @@
 	if (rc < 0)
 		return false;
 
-	if ((access & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
+	if ((access & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID
+		       | TPM_ACCESS_REQUEST_USE)) ==
 	    (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) {
 		priv->locality = l;
 		return true;
@@ -134,58 +135,13 @@
 	return false;
 }
 
-static bool locality_inactive(struct tpm_chip *chip, int l)
-{
-	struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
-	int rc;
-	u8 access;
-
-	rc = tpm_tis_read8(priv, TPM_ACCESS(l), &access);
-	if (rc < 0)
-		return false;
-
-	if ((access & (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY))
-	    == TPM_ACCESS_VALID)
-		return true;
-
-	return false;
-}
-
 static int release_locality(struct tpm_chip *chip, int l)
 {
 	struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
-	unsigned long stop, timeout;
-	long rc;
 
 	tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_ACTIVE_LOCALITY);
 
-	stop = jiffies + chip->timeout_a;
-
-	if (chip->flags & TPM_CHIP_FLAG_IRQ) {
-again:
-		timeout = stop - jiffies;
-		if ((long)timeout <= 0)
-			return -1;
-
-		rc = wait_event_interruptible_timeout(priv->int_queue,
-						      (locality_inactive(chip, l)),
-						      timeout);
-
-		if (rc > 0)
-			return 0;
-
-		if (rc == -ERESTARTSYS && freezing(current)) {
-			clear_thread_flag(TIF_SIGPENDING);
-			goto again;
-		}
-	} else {
-		do {
-			if (locality_inactive(chip, l))
-				return 0;
-			tpm_msleep(TPM_TIMEOUT);
-		} while (time_before(jiffies, stop));
-	}
-	return -1;
+	return 0;
 }
 
 static int request_locality(struct tpm_chip *chip, int l)
@@ -310,6 +266,7 @@
 	int size = 0;
 	int status;
 	u32 expected;
+	int rc;
 
 	if (count < TPM_HEADER_SIZE) {
 		size = -EIO;
@@ -329,8 +286,13 @@
 		goto out;
 	}
 
-	size += recv_data(chip, &buf[TPM_HEADER_SIZE],
-			  expected - TPM_HEADER_SIZE);
+	rc = recv_data(chip, &buf[TPM_HEADER_SIZE],
+		       expected - TPM_HEADER_SIZE);
+	if (rc < 0) {
+		size = rc;
+		goto out;
+	}
+	size += rc;
 	if (size < expected) {
 		dev_err(&chip->dev, "Unable to read remainder of result\n");
 		size = -ETIME;
@@ -433,6 +395,9 @@
 	u32 intmask;
 	int rc;
 
+	if (priv->irq == 0)
+		return;
+
 	rc = tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &intmask);
 	if (rc < 0)
 		intmask = 0;
@@ -456,10 +421,17 @@
 	int rc;
 	u32 ordinal;
 	unsigned long dur;
+	unsigned int try;
 
-	rc = tpm_tis_send_data(chip, buf, len);
-	if (rc < 0)
-		return rc;
+	for (try = 0; try < TPM_RETRY; try++) {
+		rc = tpm_tis_send_data(chip, buf, len);
+		if (rc >= 0)
+			/* Data transfer done successfully */
+			break;
+		else if (rc != -EIO)
+			/* Data transfer failed, not recoverable */
+			return rc;
+	}
 
 	/* go and do it */
 	rc = tpm_tis_write8(priv, TPM_STS(priv->locality), TPM_STS_GO);
@@ -654,17 +626,23 @@
 	return IRQ_HANDLED;
 }
 
-static int tpm_tis_gen_interrupt(struct tpm_chip *chip)
+static void tpm_tis_gen_interrupt(struct tpm_chip *chip)
 {
 	const char *desc = "attempting to generate an interrupt";
 	u32 cap2;
 	cap_t cap;
+	int ret;
+
+	ret = request_locality(chip, 0);
+	if (ret < 0)
+		return;
 
 	if (chip->flags & TPM_CHIP_FLAG_TPM2)
-		return tpm2_get_tpm_pt(chip, 0x100, &cap2, desc);
+		ret = tpm2_get_tpm_pt(chip, 0x100, &cap2, desc);
 	else
-		return tpm1_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, desc,
-				  0);
+		ret = tpm1_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, desc, 0);
+
+	release_locality(chip, 0);
 }
 
 /* Register the IRQ and issue a command that will cause an interrupt. If an
@@ -694,42 +672,37 @@
 
 	rc = tpm_tis_write8(priv, TPM_INT_VECTOR(priv->locality), irq);
 	if (rc < 0)
-		return rc;
+		goto restore_irqs;
 
 	rc = tpm_tis_read32(priv, TPM_INT_STATUS(priv->locality), &int_status);
 	if (rc < 0)
-		return rc;
+		goto restore_irqs;
 
 	/* Clear all existing */
 	rc = tpm_tis_write32(priv, TPM_INT_STATUS(priv->locality), int_status);
 	if (rc < 0)
-		return rc;
-
+		goto restore_irqs;
 	/* Turn on */
 	rc = tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality),
 			     intmask | TPM_GLOBAL_INT_ENABLE);
 	if (rc < 0)
-		return rc;
+		goto restore_irqs;
 
 	priv->irq_tested = false;
 
 	/* Generate an interrupt by having the core call through to
 	 * tpm_tis_send
 	 */
-	rc = tpm_tis_gen_interrupt(chip);
-	if (rc < 0)
-		return rc;
+	tpm_tis_gen_interrupt(chip);
 
+restore_irqs:
 	/* tpm_tis_send will either confirm the interrupt is working or it
 	 * will call disable_irq which undoes all of the above.
 	 */
 	if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) {
-		rc = tpm_tis_write8(priv, original_int_vec,
-				TPM_INT_VECTOR(priv->locality));
-		if (rc < 0)
-			return rc;
-
-		return 1;
+		tpm_tis_write8(priv, original_int_vec,
+			       TPM_INT_VECTOR(priv->locality));
+		return -1;
 	}
 
 	return 0;
@@ -910,7 +883,15 @@
 	intmask |= TPM_INTF_CMD_READY_INT | TPM_INTF_LOCALITY_CHANGE_INT |
 		   TPM_INTF_DATA_AVAIL_INT | TPM_INTF_STS_VALID_INT;
 	intmask &= ~TPM_GLOBAL_INT_ENABLE;
+
+	rc = request_locality(chip, 0);
+	if (rc < 0) {
+		rc = -ENODEV;
+		goto out_err;
+	}
+
 	tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask);
+	release_locality(chip, 0);
 
 	rc = tpm_chip_start(chip);
 	if (rc)
@@ -970,28 +951,38 @@
 	init_waitqueue_head(&priv->read_queue);
 	init_waitqueue_head(&priv->int_queue);
 	if (irq != -1) {
-		/* Before doing irq testing issue a command to the TPM in polling mode
+		/*
+		 * Before doing irq testing issue a command to the TPM in polling mode
 		 * to make sure it works. May as well use that command to set the
 		 * proper timeouts for the driver.
 		 */
-		if (tpm_get_timeouts(chip)) {
+
+		rc = request_locality(chip, 0);
+		if (rc < 0)
+			goto out_err;
+
+		rc = tpm_get_timeouts(chip);
+
+		release_locality(chip, 0);
+
+		if (rc) {
 			dev_err(dev, "Could not get TPM timeouts and durations\n");
 			rc = -ENODEV;
 			goto out_err;
 		}
 
-		tpm_chip_start(chip);
-		chip->flags |= TPM_CHIP_FLAG_IRQ;
 		if (irq) {
 			tpm_tis_probe_irq_single(chip, intmask, IRQF_SHARED,
 						 irq);
-			if (!(chip->flags & TPM_CHIP_FLAG_IRQ))
+			if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) {
 				dev_err(&chip->dev, FW_BUG
 					"TPM interrupt not working, polling instead\n");
+
+				disable_interrupts(chip);
+			}
 		} else {
 			tpm_tis_probe_irq(chip, intmask);
 		}
-		tpm_chip_stop(chip);
 	}
 
 	rc = tpm_chip_register(chip);
@@ -1003,7 +994,7 @@
 
 	return 0;
 out_err:
-	if ((chip->ops != NULL) && (chip->ops->clk_enable != NULL))
+	if (chip->ops->clk_enable != NULL)
 		chip->ops->clk_enable(chip, false);
 
 	tpm_tis_remove(chip);
@@ -1058,12 +1049,20 @@
 	if (ret)
 		return ret;
 
-	/* TPM 1.2 requires self-test on resume. This function actually returns
+	/*
+	 * TPM 1.2 requires self-test on resume. This function actually returns
 	 * an error code but for unknown reason it isn't handled.
 	 */
-	if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
+	if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) {
+		ret = request_locality(chip, 0);
+		if (ret < 0)
+			return ret;
+
 		tpm1_do_selftest(chip);
 
+		release_locality(chip, 0);
+	}
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(tpm_tis_resume);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/tpm/tpm_vtpm_proxy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/tpm/tpm_vtpm_proxy.c
@@ -693,37 +693,21 @@
 	.fops = &vtpmx_fops,
 };
 
-static int vtpmx_init(void)
-{
-	return misc_register(&vtpmx_miscdev);
-}
-
-static void vtpmx_cleanup(void)
-{
-	misc_deregister(&vtpmx_miscdev);
-}
-
 static int __init vtpm_module_init(void)
 {
 	int rc;
 
-	rc = vtpmx_init();
-	if (rc) {
-		pr_err("couldn't create vtpmx device\n");
-		return rc;
-	}
-
 	workqueue = create_workqueue("tpm-vtpm");
 	if (!workqueue) {
 		pr_err("couldn't create workqueue\n");
-		rc = -ENOMEM;
-		goto err_vtpmx_cleanup;
+		return -ENOMEM;
 	}
 
-	return 0;
-
-err_vtpmx_cleanup:
-	vtpmx_cleanup();
+	rc = misc_register(&vtpmx_miscdev);
+	if (rc) {
+		pr_err("couldn't create vtpmx device\n");
+		destroy_workqueue(workqueue);
+	}
 
 	return rc;
 }
@@ -731,7 +715,7 @@
 static void __exit vtpm_module_exit(void)
 {
 	destroy_workqueue(workqueue);
-	vtpmx_cleanup();
+	misc_deregister(&vtpmx_miscdev);
 }
 
 module_init(vtpm_module_init);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/tpm/tpmrm-dev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/tpm/tpmrm-dev.c
@@ -21,7 +21,7 @@
 	if (priv == NULL)
 		return -ENOMEM;
 
-	rc = tpm2_init_space(&priv->space);
+	rc = tpm2_init_space(&priv->space, TPM2_SPACE_BUFFER_SIZE);
 	if (rc) {
 		kfree(priv);
 		return -ENOMEM;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/ttyprintk.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/ttyprintk.c
@@ -15,10 +15,11 @@
 #include <linux/serial.h>
 #include <linux/tty.h>
 #include <linux/module.h>
+#include <linux/spinlock.h>
 
 struct ttyprintk_port {
 	struct tty_port port;
-	struct mutex port_write_mutex;
+	spinlock_t spinlock;
 };
 
 static struct ttyprintk_port tpk_port;
@@ -99,11 +100,12 @@
 static void tpk_close(struct tty_struct *tty, struct file *filp)
 {
 	struct ttyprintk_port *tpkp = tty->driver_data;
+	unsigned long flags;
 
-	mutex_lock(&tpkp->port_write_mutex);
+	spin_lock_irqsave(&tpkp->spinlock, flags);
 	/* flush tpk_printk buffer */
 	tpk_printk(NULL, 0);
-	mutex_unlock(&tpkp->port_write_mutex);
+	spin_unlock_irqrestore(&tpkp->spinlock, flags);
 
 	tty_port_close(&tpkp->port, tty, filp);
 }
@@ -115,13 +117,14 @@
 		const unsigned char *buf, int count)
 {
 	struct ttyprintk_port *tpkp = tty->driver_data;
+	unsigned long flags;
 	int ret;
 
 
 	/* exclusive use of tpk_printk within this tty */
-	mutex_lock(&tpkp->port_write_mutex);
+	spin_lock_irqsave(&tpkp->spinlock, flags);
 	ret = tpk_printk(buf, count);
-	mutex_unlock(&tpkp->port_write_mutex);
+	spin_unlock_irqrestore(&tpkp->spinlock, flags);
 
 	return ret;
 }
@@ -155,12 +158,23 @@
 	return 0;
 }
 
+/*
+ * TTY operations hangup function.
+ */
+static void tpk_hangup(struct tty_struct *tty)
+{
+	struct ttyprintk_port *tpkp = tty->driver_data;
+
+	tty_port_hangup(&tpkp->port);
+}
+
 static const struct tty_operations ttyprintk_ops = {
 	.open = tpk_open,
 	.close = tpk_close,
 	.write = tpk_write,
 	.write_room = tpk_write_room,
 	.ioctl = tpk_ioctl,
+	.hangup = tpk_hangup,
 };
 
 static const struct tty_port_operations null_ops = { };
@@ -171,7 +185,7 @@
 {
 	int ret = -ENOMEM;
 
-	mutex_init(&tpk_port.port_write_mutex);
+	spin_lock_init(&tpk_port.spinlock);
 
 	ttyprintk_driver = tty_alloc_driver(1,
 			TTY_DRIVER_RESET_TERMIOS |
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/char/virtio_console.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/char/virtio_console.c
@@ -435,12 +435,12 @@
 		/*
 		 * Allocate DMA memory from ancestor. When a virtio
 		 * device is created by remoteproc, the DMA memory is
-		 * associated with the grandparent device:
-		 * vdev => rproc => platform-dev.
+		 * associated with the parent device:
+		 * virtioY => remoteprocX#vdevYbuffer.
 		 */
-		if (!vdev->dev.parent || !vdev->dev.parent->parent)
+		buf->dev = vdev->dev.parent;
+		if (!buf->dev)
 			goto free_buf;
-		buf->dev = vdev->dev.parent->parent;
 
 		/* Increase device refcnt to avoid freeing it */
 		get_device(buf->dev);
@@ -475,7 +475,7 @@
 
 	buf = virtqueue_get_buf(port->in_vq, &len);
 	if (buf) {
-		buf->len = len;
+		buf->len = min_t(size_t, len, buf->size);
 		buf->offset = 0;
 		port->stats.bytes_received += len;
 	}
@@ -1714,7 +1714,7 @@
 	while ((buf = virtqueue_get_buf(vq, &len))) {
 		spin_unlock(&portdev->c_ivq_lock);
 
-		buf->len = len;
+		buf->len = min_t(size_t, len, buf->size);
 		buf->offset = 0;
 
 		handle_control_message(vq->vdev, portdev, buf);
@@ -1961,6 +1961,13 @@
 	list_del(&portdev->list);
 	spin_unlock_irq(&pdrvdata_lock);
 
+	/* Device is going away, exit any polling for buffers */
+	virtio_break_device(vdev);
+	if (use_multiport(portdev))
+		flush_work(&portdev->control_work);
+	else
+		flush_work(&portdev->config_work);
+
 	/* Disable interrupts for vqs */
 	vdev->config->reset(vdev);
 	/* Finish up work that's lined up */
@@ -2044,25 +2051,27 @@
 		multiport = true;
 	}
 
-	err = init_vqs(portdev);
-	if (err < 0) {
-		dev_err(&vdev->dev, "Error %d initializing vqs\n", err);
-		goto free_chrdev;
-	}
-
 	spin_lock_init(&portdev->ports_lock);
 	INIT_LIST_HEAD(&portdev->ports);
 	INIT_LIST_HEAD(&portdev->list);
 
-	virtio_device_ready(portdev->vdev);
-
 	INIT_WORK(&portdev->config_work, &config_work_handler);
 	INIT_WORK(&portdev->control_work, &control_work_handler);
 
 	if (multiport) {
 		spin_lock_init(&portdev->c_ivq_lock);
 		spin_lock_init(&portdev->c_ovq_lock);
+	}
 
+	err = init_vqs(portdev);
+	if (err < 0) {
+		dev_err(&vdev->dev, "Error %d initializing vqs\n", err);
+		goto free_chrdev;
+	}
+
+	virtio_device_ready(portdev->vdev);
+
+	if (multiport) {
 		err = fill_queue(portdev->c_ivq, &portdev->c_ivq_lock);
 		if (err < 0) {
 			dev_err(&vdev->dev,
@@ -2118,6 +2127,7 @@
 	{ VIRTIO_ID_CONSOLE, VIRTIO_DEV_ANY_ID },
 	{ 0 },
 };
+MODULE_DEVICE_TABLE(virtio, id_table);
 
 static unsigned int features[] = {
 	VIRTIO_CONSOLE_F_SIZE,
@@ -2130,6 +2140,7 @@
 #endif
 	{ 0 },
 };
+MODULE_DEVICE_TABLE(virtio, rproc_serial_id_table);
 
 static unsigned int rproc_serial_features[] = {
 };
@@ -2232,7 +2243,7 @@
 	.remove =	virtcons_remove,
 };
 
-static int __init init(void)
+static int __init virtio_console_init(void)
 {
 	int err;
 
@@ -2269,7 +2280,7 @@
 	return err;
 }
 
-static void __exit fini(void)
+static void __exit virtio_console_fini(void)
 {
 	reclaim_dma_bufs();
 
@@ -2279,9 +2290,8 @@
 	class_destroy(pdrvdata.class);
 	debugfs_remove_recursive(pdrvdata.debugfs_dir);
 }
-module_init(init);
-module_exit(fini);
+module_init(virtio_console_init);
+module_exit(virtio_console_fini);
 
-MODULE_DEVICE_TABLE(virtio, id_table);
 MODULE_DESCRIPTION("Virtio console driver");
 MODULE_LICENSE("GPL");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/Kconfig
@@ -63,7 +63,7 @@
 config COMMON_CLK_HI655X
 	tristate "Clock driver for Hi655x" if EXPERT
 	depends on (MFD_HI655X_PMIC || COMPILE_TEST)
-	depends on REGMAP
+	select REGMAP
 	default MFD_HI655X_PMIC
 	---help---
 	  This driver supports the hi655x PMIC clock. This
@@ -136,6 +136,39 @@
 	  This driver supports Silicon Labs 570/571/598/599 programmable
 	  clock generators.
 
+config COMMON_CLK_SI5324
+	tristate "Clock driver for SiLabs 5324 and compatible devices"
+	depends on I2C
+	depends on OF
+	select REGMAP_I2C
+	help
+	---help--
+	  This driver supports Silicon Labs 5324/5319/5328 programmable
+	  clock generators. Dynamic programming of the oscillator is done
+	  via I2C.
+
+config COMMON_CLK_IDT8T49N24X
+	tristate "Clock driver for IDT 8T49N24x"
+	depends on I2C
+	depends on OF
+	select REGMAP_I2C
+	help
+	---help---
+	  This driver supports the IDT 8T49N24x universal frequency translator
+	  product family.  The only chip in the family that is currently
+	  supported is the 8T49N241. The driver supports setting the rate for
+	  all four outputs on the chip and automatically calculating/setting
+	  the appropriate VCO value.
+
+	  The driver can read a full register map from the DT,
+	  and will use that register map to initialize the attached part
+	  (via I2C) when the system boots. Any configuration not supported
+	  by the common clock framework must be done via the full register
+	  map, including optimized settings.
+
+	  All outputs are currently assumed to be LVDS, unless overridden
+	  in the full register map in the DT.
+
 config COMMON_CLK_CDCE706
 	tristate "Clock driver for TI CDCE706 clock synthesizer"
 	depends on I2C
@@ -302,9 +335,25 @@
 config COMMON_CLK_FIXED_MMIO
 	bool "Clock driver for Memory Mapped Fixed values"
 	depends on COMMON_CLK && OF
+	depends on HAS_IOMEM
 	help
 	  Support for Memory Mapped IO Fixed clocks
 
+config COMMON_CLK_XLNX_CLKWZRD
+	tristate "Xilinx Clocking Wizard"
+	depends on COMMON_CLK && OF
+	help
+	  Support for the Xilinx Clocking Wizard IP core clock generator.
+
+config COMMON_CLK_XLNX_CLKWZRD_V
+	tristate "Xilinx Versal Clocking Wizard"
+	depends on COMMON_CLK && OF
+	help
+	  Support for the Versal Xilinx Clocking Wizard IP core clock generator.
+	  Adds support for Versal clocking wizard 1.0 and compatible.
+	  This driver supports the Xilinx clocking wizard programmable clock
+	  synthesizer. The number of output is configurable in the design.
+
 source "drivers/clk/actions/Kconfig"
 source "drivers/clk/analogbits/Kconfig"
 source "drivers/clk/bcm/Kconfig"
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/Makefile
@@ -58,6 +58,8 @@
 obj-$(CONFIG_COMMON_CLK_STM32F)		+= clk-stm32f4.o
 obj-$(CONFIG_COMMON_CLK_STM32H7)	+= clk-stm32h7.o
 obj-$(CONFIG_COMMON_CLK_STM32MP157)	+= clk-stm32mp1.o
+clk-si5324drv-y				:= si5324drv.o clk-si5324.o
+obj-$(CONFIG_COMMON_CLK_SI5324)		+= clk-si5324drv.o
 obj-$(CONFIG_ARCH_TANGO)		+= clk-tango4.o
 obj-$(CONFIG_CLK_TWL6040)		+= clk-twl6040.o
 obj-$(CONFIG_ARCH_U300)			+= clk-u300.o
@@ -65,6 +67,8 @@
 obj-$(CONFIG_COMMON_CLK_VC5)		+= clk-versaclock5.o
 obj-$(CONFIG_COMMON_CLK_WM831X)		+= clk-wm831x.o
 obj-$(CONFIG_COMMON_CLK_XGENE)		+= clk-xgene.o
+obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD)	+= clk-xlnx-clock-wizard.o
+obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD_V)	+= clk-xlnx-clock-wizard-v.o
 
 # please keep this section sorted lexicographically by directory path name
 obj-y					+= actions/
@@ -77,6 +81,7 @@
 obj-$(CONFIG_ARCH_DAVINCI)		+= davinci/
 obj-$(CONFIG_H8300)			+= h8300/
 obj-$(CONFIG_ARCH_HISI)			+= hisilicon/
+obj-$(CONFIG_COMMON_CLK_IDT8T49N24X)	+= idt/
 obj-y					+= imgtec/
 obj-y					+= imx/
 obj-y					+= ingenic/
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/actions/owl-s500.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/actions/owl-s500.c
@@ -125,8 +125,7 @@
 	{ 12, 1, 13 }, { 13, 1, 14 }, { 14, 1, 15 }, { 15, 1, 16 },
 	{ 16, 1, 17 }, { 17, 1, 18 }, { 18, 1, 19 }, { 19, 1, 20 },
 	{ 20, 1, 21 }, { 21, 1, 22 }, { 22, 1, 23 }, { 23, 1, 24 },
-	{ 24, 1, 25 }, { 25, 1, 26 }, { 26, 1, 27 }, { 27, 1, 28 },
-	{ 28, 1, 29 }, { 29, 1, 30 }, { 30, 1, 31 }, { 31, 1, 32 },
+	{ 24, 1, 25 },
 
 	/* bit8: /128 */
 	{ 256, 1, 1 * 128 }, { 257, 1, 2 * 128 }, { 258, 1, 3 * 128 }, { 259, 1, 4 * 128 },
@@ -135,14 +134,20 @@
 	{ 268, 1, 13 * 128 }, { 269, 1, 14 * 128 }, { 270, 1, 15 * 128 }, { 271, 1, 16 * 128 },
 	{ 272, 1, 17 * 128 }, { 273, 1, 18 * 128 }, { 274, 1, 19 * 128 }, { 275, 1, 20 * 128 },
 	{ 276, 1, 21 * 128 }, { 277, 1, 22 * 128 }, { 278, 1, 23 * 128 }, { 279, 1, 24 * 128 },
-	{ 280, 1, 25 * 128 }, { 281, 1, 26 * 128 }, { 282, 1, 27 * 128 }, { 283, 1, 28 * 128 },
-	{ 284, 1, 29 * 128 }, { 285, 1, 30 * 128 }, { 286, 1, 31 * 128 }, { 287, 1, 32 * 128 },
+	{ 280, 1, 25 * 128 },
 	{ 0, 0, 0 },
 };
 
-static struct clk_factor_table bisp_factor_table[] = {
-	{ 0, 1, 1 }, { 1, 1, 2 }, { 2, 1, 3 }, { 3, 1, 4 },
-	{ 4, 1, 5 }, { 5, 1, 6 }, { 6, 1, 7 }, { 7, 1, 8 },
+static struct clk_factor_table de_factor_table[] = {
+	{ 0, 1, 1 }, { 1, 2, 3 }, { 2, 1, 2 }, { 3, 2, 5 },
+	{ 4, 1, 3 }, { 5, 1, 4 }, { 6, 1, 6 }, { 7, 1, 8 },
+	{ 8, 1, 12 },
+	{ 0, 0, 0 },
+};
+
+static struct clk_factor_table hde_factor_table[] = {
+	{ 0, 1, 1 }, { 1, 2, 3 }, { 2, 1, 2 }, { 3, 2, 5 },
+	{ 4, 1, 3 }, { 5, 1, 4 }, { 6, 1, 6 }, { 7, 1, 8 },
 	{ 0, 0, 0 },
 };
 
@@ -156,6 +161,13 @@
 	{ 0, 0 },
 };
 
+static struct clk_div_table std12rate_div_table[] = {
+	{ 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 4 },
+	{ 4, 5 }, { 5, 6 }, { 6, 7 }, { 7, 8 },
+	{ 8, 9 }, { 9, 10 }, { 10, 11 }, { 11, 12 },
+	{ 0, 0 },
+};
+
 static struct clk_div_table i2s_div_table[] = {
 	{ 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 4 },
 	{ 4, 6 }, { 5, 8 }, { 6, 12 }, { 7, 16 },
@@ -183,44 +195,44 @@
 static OWL_GATE(hdmi_clk, "hdmi_clk", "hosc", CMU_DEVCLKEN1, 3, 0, 0);
 
 /* divider clocks */
-static OWL_DIVIDER(h_clk, "h_clk", "ahbprevdiv_clk", CMU_BUSCLK1, 12, 2, NULL, 0, 0);
+static OWL_DIVIDER(h_clk, "h_clk", "ahbprediv_clk", CMU_BUSCLK1, 12, 2, NULL, 0, 0);
 static OWL_DIVIDER(rmii_ref_clk, "rmii_ref_clk", "ethernet_pll_clk", CMU_ETHERNETPLL, 1, 1, rmii_ref_div_table, 0, 0);
 
 /* factor clocks */
 static OWL_FACTOR(ahb_clk, "ahb_clk", "h_clk", CMU_BUSCLK1, 2, 2, ahb_factor_table, 0, 0);
-static OWL_FACTOR(de1_clk, "de_clk1", "de_clk", CMU_DECLK, 0, 3, bisp_factor_table, 0, 0);
-static OWL_FACTOR(de2_clk, "de_clk2", "de_clk", CMU_DECLK, 4, 3, bisp_factor_table, 0, 0);
+static OWL_FACTOR(de1_clk, "de_clk1", "de_clk", CMU_DECLK, 0, 4, de_factor_table, 0, 0);
+static OWL_FACTOR(de2_clk, "de_clk2", "de_clk", CMU_DECLK, 4, 4, de_factor_table, 0, 0);
 
 /* composite clocks */
 static OWL_COMP_FACTOR(vce_clk, "vce_clk", hde_clk_mux_p,
 			OWL_MUX_HW(CMU_VCECLK, 4, 2),
 			OWL_GATE_HW(CMU_DEVCLKEN0, 26, 0),
-			OWL_FACTOR_HW(CMU_VCECLK, 0, 3, 0, bisp_factor_table),
+			OWL_FACTOR_HW(CMU_VCECLK, 0, 3, 0, hde_factor_table),
 			0);
 
 static OWL_COMP_FACTOR(vde_clk, "vde_clk", hde_clk_mux_p,
 			OWL_MUX_HW(CMU_VDECLK, 4, 2),
 			OWL_GATE_HW(CMU_DEVCLKEN0, 25, 0),
-			OWL_FACTOR_HW(CMU_VDECLK, 0, 3, 0, bisp_factor_table),
+			OWL_FACTOR_HW(CMU_VDECLK, 0, 3, 0, hde_factor_table),
 			0);
 
-static OWL_COMP_FACTOR(bisp_clk, "bisp_clk", bisp_clk_mux_p,
+static OWL_COMP_DIV(bisp_clk, "bisp_clk", bisp_clk_mux_p,
 			OWL_MUX_HW(CMU_BISPCLK, 4, 1),
 			OWL_GATE_HW(CMU_DEVCLKEN0, 14, 0),
-			OWL_FACTOR_HW(CMU_BISPCLK, 0, 3, 0, bisp_factor_table),
+			OWL_DIVIDER_HW(CMU_BISPCLK, 0, 4, 0, std12rate_div_table),
 			0);
 
-static OWL_COMP_FACTOR(sensor0_clk, "sensor0_clk", sensor_clk_mux_p,
+static OWL_COMP_DIV(sensor0_clk, "sensor0_clk", sensor_clk_mux_p,
 			OWL_MUX_HW(CMU_SENSORCLK, 4, 1),
 			OWL_GATE_HW(CMU_DEVCLKEN0, 14, 0),
-			OWL_FACTOR_HW(CMU_SENSORCLK, 0, 3, 0, bisp_factor_table),
-			CLK_IGNORE_UNUSED);
+			OWL_DIVIDER_HW(CMU_SENSORCLK, 0, 4, 0, std12rate_div_table),
+			0);
 
-static OWL_COMP_FACTOR(sensor1_clk, "sensor1_clk", sensor_clk_mux_p,
+static OWL_COMP_DIV(sensor1_clk, "sensor1_clk", sensor_clk_mux_p,
 			OWL_MUX_HW(CMU_SENSORCLK, 4, 1),
 			OWL_GATE_HW(CMU_DEVCLKEN0, 14, 0),
-			OWL_FACTOR_HW(CMU_SENSORCLK, 8, 3, 0, bisp_factor_table),
-			CLK_IGNORE_UNUSED);
+			OWL_DIVIDER_HW(CMU_SENSORCLK, 8, 4, 0, std12rate_div_table),
+			0);
 
 static OWL_COMP_FACTOR(sd0_clk, "sd0_clk", sd_clk_mux_p,
 			OWL_MUX_HW(CMU_SD0CLK, 9, 1),
@@ -300,7 +312,7 @@
 static OWL_COMP_DIV(uart0_clk, "uart0_clk", uart_clk_mux_p,
 			OWL_MUX_HW(CMU_UART0CLK, 16, 1),
 			OWL_GATE_HW(CMU_DEVCLKEN1, 6, 0),
-			OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL),
+			OWL_DIVIDER_HW(CMU_UART0CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL),
 			CLK_IGNORE_UNUSED);
 
 static OWL_COMP_DIV(uart1_clk, "uart1_clk", uart_clk_mux_p,
@@ -312,31 +324,31 @@
 static OWL_COMP_DIV(uart2_clk, "uart2_clk", uart_clk_mux_p,
 			OWL_MUX_HW(CMU_UART2CLK, 16, 1),
 			OWL_GATE_HW(CMU_DEVCLKEN1, 8, 0),
-			OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL),
+			OWL_DIVIDER_HW(CMU_UART2CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL),
 			CLK_IGNORE_UNUSED);
 
 static OWL_COMP_DIV(uart3_clk, "uart3_clk", uart_clk_mux_p,
 			OWL_MUX_HW(CMU_UART3CLK, 16, 1),
 			OWL_GATE_HW(CMU_DEVCLKEN1, 19, 0),
-			OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL),
+			OWL_DIVIDER_HW(CMU_UART3CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL),
 			CLK_IGNORE_UNUSED);
 
 static OWL_COMP_DIV(uart4_clk, "uart4_clk", uart_clk_mux_p,
 			OWL_MUX_HW(CMU_UART4CLK, 16, 1),
 			OWL_GATE_HW(CMU_DEVCLKEN1, 20, 0),
-			OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL),
+			OWL_DIVIDER_HW(CMU_UART4CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL),
 			CLK_IGNORE_UNUSED);
 
 static OWL_COMP_DIV(uart5_clk, "uart5_clk", uart_clk_mux_p,
 			OWL_MUX_HW(CMU_UART5CLK, 16, 1),
 			OWL_GATE_HW(CMU_DEVCLKEN1, 21, 0),
-			OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL),
+			OWL_DIVIDER_HW(CMU_UART5CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL),
 			CLK_IGNORE_UNUSED);
 
 static OWL_COMP_DIV(uart6_clk, "uart6_clk", uart_clk_mux_p,
 			OWL_MUX_HW(CMU_UART6CLK, 16, 1),
 			OWL_GATE_HW(CMU_DEVCLKEN1, 18, 0),
-			OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL),
+			OWL_DIVIDER_HW(CMU_UART6CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL),
 			CLK_IGNORE_UNUSED);
 
 static OWL_COMP_DIV(i2srx_clk, "i2srx_clk", i2s_clk_mux_p,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/actions/owl-s700.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/actions/owl-s700.c
@@ -162,6 +162,7 @@
 
 static struct clk_div_table rmii_div_table[] = {
 	{0, 4},   {1, 10},
+	{0, 0}
 };
 
 /* divider clocks */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/actions/owl-s900.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/actions/owl-s900.c
@@ -140,7 +140,7 @@
 
 static struct clk_div_table usb3_mac_div_table[] = {
 	{ 1, 2 }, { 2, 3 }, { 3, 4 },
-	{ 0, 8 },
+	{ 0, 0 }
 };
 
 static struct clk_div_table i2s_div_table[] = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/analogbits/wrpll-cln28hpc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/analogbits/wrpll-cln28hpc.c
@@ -287,7 +287,7 @@
 			vco = vco_pre * f;
 		}
 
-		delta = abs(target_rate - vco);
+		delta = abs(target_vco_rate - vco);
 		if (delta < best_delta) {
 			best_delta = delta;
 			best_r = r;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/at91/at91sam9260.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/at91/at91sam9260.c
@@ -348,7 +348,7 @@
 		return;
 	mainxtal_name = of_clk_get_parent_name(np, i);
 
-	regmap = syscon_node_to_regmap(np);
+	regmap = device_node_to_regmap(np);
 	if (IS_ERR(regmap))
 		return;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/at91/at91sam9rl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/at91/at91sam9rl.c
@@ -83,7 +83,7 @@
 		return;
 	mainxtal_name = of_clk_get_parent_name(np, i);
 
-	regmap = syscon_node_to_regmap(np);
+	regmap = device_node_to_regmap(np);
 	if (IS_ERR(regmap))
 		return;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/at91/at91sam9x5.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/at91/at91sam9x5.c
@@ -146,7 +146,7 @@
 		return;
 	mainxtal_name = of_clk_get_parent_name(np, i);
 
-	regmap = syscon_node_to_regmap(np);
+	regmap = device_node_to_regmap(np);
 	if (IS_ERR(regmap))
 		return;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/at91/clk-generated.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/at91/clk-generated.c
@@ -18,8 +18,6 @@
 
 #define GENERATED_MAX_DIV	255
 
-#define GCK_INDEX_DT_AUDIO_PLL	5
-
 struct clk_generated {
 	struct clk_hw hw;
 	struct regmap *regmap;
@@ -29,7 +27,7 @@
 	u32 gckdiv;
 	const struct clk_pcr_layout *layout;
 	u8 parent_id;
-	bool audio_pll_allowed;
+	int chg_pid;
 };
 
 #define to_clk_generated(hw) \
@@ -107,9 +105,13 @@
 		tmp_rate = parent_rate;
 	else
 		tmp_rate = parent_rate / div;
+
+	if (tmp_rate < req->min_rate || tmp_rate > req->max_rate)
+		return;
+
 	tmp_diff = abs(req->rate - tmp_rate);
 
-	if (*best_diff < 0 || *best_diff > tmp_diff) {
+	if (*best_diff < 0 || *best_diff >= tmp_diff) {
 		*best_rate = tmp_rate;
 		*best_diff = tmp_diff;
 		req->best_parent_rate = parent_rate;
@@ -129,7 +131,16 @@
 	int i;
 	u32 div;
 
-	for (i = 0; i < clk_hw_get_num_parents(hw) - 1; i++) {
+	/* do not look for a rate that is outside of our range */
+	if (gck->range.max && req->rate > gck->range.max)
+		req->rate = gck->range.max;
+	if (gck->range.min && req->rate < gck->range.min)
+		req->rate = gck->range.min;
+
+	for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
+		if (gck->chg_pid == i)
+			continue;
+
 		parent = clk_hw_get_parent_by_index(hw, i);
 		if (!parent)
 			continue;
@@ -161,10 +172,10 @@
 	 * that the only clks able to modify gck rate are those of audio IPs.
 	 */
 
-	if (!gck->audio_pll_allowed)
+	if (gck->chg_pid < 0)
 		goto end;
 
-	parent = clk_hw_get_parent_by_index(hw, GCK_INDEX_DT_AUDIO_PLL);
+	parent = clk_hw_get_parent_by_index(hw, gck->chg_pid);
 	if (!parent)
 		goto end;
 
@@ -271,8 +282,8 @@
 at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
 			    const struct clk_pcr_layout *layout,
 			    const char *name, const char **parent_names,
-			    u8 num_parents, u8 id, bool pll_audio,
-			    const struct clk_range *range)
+			    u8 num_parents, u8 id,
+			    const struct clk_range *range, int chg_pid)
 {
 	struct clk_generated *gck;
 	struct clk_init_data init;
@@ -287,15 +298,16 @@
 	init.ops = &generated_ops;
 	init.parent_names = parent_names;
 	init.num_parents = num_parents;
-	init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
-		CLK_SET_RATE_PARENT;
+	init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
+	if (chg_pid >= 0)
+		init.flags |= CLK_SET_RATE_PARENT;
 
 	gck->id = id;
 	gck->hw.init = &init;
 	gck->regmap = regmap;
 	gck->lock = lock;
 	gck->range = *range;
-	gck->audio_pll_allowed = pll_audio;
+	gck->chg_pid = chg_pid;
 	gck->layout = layout;
 
 	clk_generated_startup(gck);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/at91/clk-main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/at91/clk-main.c
@@ -437,12 +437,17 @@
 		return -EINVAL;
 
 	regmap_read(regmap, AT91_CKGR_MOR, &tmp);
-	tmp &= ~MOR_KEY_MASK;
 
 	if (index && !(tmp & AT91_PMC_MOSCSEL))
-		regmap_write(regmap, AT91_CKGR_MOR, tmp | AT91_PMC_MOSCSEL);
+		tmp = AT91_PMC_MOSCSEL;
 	else if (!index && (tmp & AT91_PMC_MOSCSEL))
-		regmap_write(regmap, AT91_CKGR_MOR, tmp & ~AT91_PMC_MOSCSEL);
+		tmp = 0;
+	else
+		return 0;
+
+	regmap_update_bits(regmap, AT91_CKGR_MOR,
+			   AT91_PMC_MOSCSEL | MOR_KEY_MASK,
+			   tmp | AT91_PMC_KEY);
 
 	while (!clk_sam9x5_main_ready(regmap))
 		cpu_relax();
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/at91/clk-usb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/at91/clk-usb.c
@@ -75,6 +75,9 @@
 			tmp_parent_rate = req->rate * div;
 			tmp_parent_rate = clk_hw_round_rate(parent,
 							   tmp_parent_rate);
+			if (!tmp_parent_rate)
+				continue;
+
 			tmp_rate = DIV_ROUND_CLOSEST(tmp_parent_rate, div);
 			if (tmp_rate < req->rate)
 				tmp_diff = req->rate - tmp_rate;
@@ -211,7 +214,7 @@
 
 	usb->hw.init = &init;
 	usb->regmap = regmap;
-	usb->usbs_mask = SAM9X5_USBS_MASK;
+	usb->usbs_mask = usbs_mask;
 
 	hw = &usb->hw;
 	ret = clk_hw_register(NULL, &usb->hw);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/at91/dt-compat.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/at91/dt-compat.c
@@ -22,6 +22,8 @@
 
 #define SYSTEM_MAX_ID		31
 
+#define GCK_INDEX_DT_AUDIO_PLL	5
+
 #ifdef CONFIG_HAVE_AT91_AUDIO_PLL
 static void __init of_sama5d2_clk_audio_pll_frac_setup(struct device_node *np)
 {
@@ -135,7 +137,7 @@
 		return;
 
 	for_each_child_of_node(np, gcknp) {
-		bool pll_audio = false;
+		int chg_pid = INT_MIN;
 
 		if (of_property_read_u32(gcknp, "reg", &id))
 			continue;
@@ -152,12 +154,12 @@
 		if (of_device_is_compatible(np, "atmel,sama5d2-clk-generated") &&
 		    (id == GCK_ID_I2S0 || id == GCK_ID_I2S1 ||
 		     id == GCK_ID_CLASSD))
-			pll_audio = true;
+			chg_pid = GCK_INDEX_DT_AUDIO_PLL;
 
 		hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
 						 &dt_pcr_layout, name,
 						 parent_names, num_parents,
-						 id, pll_audio, &range);
+						 id, &range, chg_pid);
 		if (IS_ERR(hw))
 			continue;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/at91/pmc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/at91/pmc.c
@@ -275,7 +275,12 @@
 
 	np = of_find_matching_node(NULL, sama5d2_pmc_dt_ids);
 
-	pmcreg = syscon_node_to_regmap(np);
+	if (!of_device_is_available(np)) {
+		of_node_put(np);
+		return -ENODEV;
+	}
+
+	pmcreg = device_node_to_regmap(np);
 	if (IS_ERR(pmcreg))
 		return PTR_ERR(pmcreg);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/at91/pmc.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/at91/pmc.h
@@ -118,8 +118,8 @@
 at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
 			    const struct clk_pcr_layout *layout,
 			    const char *name, const char **parent_names,
-			    u8 num_parents, u8 id, bool pll_audio,
-			    const struct clk_range *range);
+			    u8 num_parents, u8 id,
+			    const struct clk_range *range, int chg_pid);
 
 struct clk_hw * __init
 at91_clk_register_h32mx(struct regmap *regmap, const char *name,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/at91/sam9x60.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/at91/sam9x60.c
@@ -47,6 +47,7 @@
 	.pres_shift = 8,
 	.css_mask = 0x1f,
 	.have_slck_mck = 0,
+	.is_pres_direct = 1,
 };
 
 static const struct clk_pcr_layout sam9x60_pcr_layout = {
@@ -123,7 +124,6 @@
 	char *n;
 	u8 id;
 	struct clk_range r;
-	bool pll;
 } sam9x60_gck[] = {
 	{ .n = "flex0_gclk",  .id = 5, },
 	{ .n = "flex1_gclk",  .id = 6, },
@@ -143,11 +143,9 @@
 	{ .n = "sdmmc1_gclk", .id = 26, .r = { .min = 0, .max = 105000000 }, },
 	{ .n = "flex11_gclk", .id = 32, },
 	{ .n = "flex12_gclk", .id = 33, },
-	{ .n = "i2s_gclk",    .id = 34, .r = { .min = 0, .max = 105000000 },
-		.pll = true, },
+	{ .n = "i2s_gclk",    .id = 34, .r = { .min = 0, .max = 105000000 }, },
 	{ .n = "pit64b_gclk", .id = 37, },
-	{ .n = "classd_gclk", .id = 42, .r = { .min = 0, .max = 100000000 },
-		.pll = true, },
+	{ .n = "classd_gclk", .id = 42, .r = { .min = 0, .max = 100000000 }, },
 	{ .n = "tcb1_gclk",   .id = 45, },
 	{ .n = "dbgu_gclk",   .id = 47, },
 };
@@ -161,7 +159,6 @@
 	struct regmap *regmap;
 	struct clk_hw *hw;
 	int i;
-	bool bypass;
 
 	i = of_property_match_string(np, "clock-names", "td_slck");
 	if (i < 0)
@@ -196,10 +193,7 @@
 	if (IS_ERR(hw))
 		goto err_free;
 
-	bypass = of_property_read_bool(np, "atmel,osc-bypass");
-
-	hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
-					bypass);
+	hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, 0);
 	if (IS_ERR(hw))
 		goto err_free;
 
@@ -236,9 +230,8 @@
 
 	parent_names[0] = "pllack";
 	parent_names[1] = "upllck";
-	parent_names[2] = "mainck";
-	parent_names[3] = "mainck";
-	hw = sam9x60_clk_register_usb(regmap, "usbck", parent_names, 4);
+	parent_names[2] = "main_osc";
+	hw = sam9x60_clk_register_usb(regmap, "usbck", parent_names, 3);
 	if (IS_ERR(hw))
 		goto err_free;
 
@@ -289,8 +282,7 @@
 						 sam9x60_gck[i].n,
 						 parent_names, 6,
 						 sam9x60_gck[i].id,
-						 sam9x60_gck[i].pll,
-						 &sam9x60_gck[i].r);
+						 &sam9x60_gck[i].r, INT_MIN);
 		if (IS_ERR(hw))
 			goto err_free;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/at91/sama5d2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/at91/sama5d2.c
@@ -115,21 +115,20 @@
 	char *n;
 	u8 id;
 	struct clk_range r;
-	bool pll;
+	int chg_pid;
 } sama5d2_gck[] = {
-	{ .n = "sdmmc0_gclk", .id = 31, },
-	{ .n = "sdmmc1_gclk", .id = 32, },
-	{ .n = "tcb0_gclk",   .id = 35, .r = { .min = 0, .max = 83000000 }, },
-	{ .n = "tcb1_gclk",   .id = 36, .r = { .min = 0, .max = 83000000 }, },
-	{ .n = "pwm_gclk",    .id = 38, .r = { .min = 0, .max = 83000000 }, },
-	{ .n = "isc_gclk",    .id = 46, },
-	{ .n = "pdmic_gclk",  .id = 48, },
-	{ .n = "i2s0_gclk",   .id = 54, .pll = true },
-	{ .n = "i2s1_gclk",   .id = 55, .pll = true },
-	{ .n = "can0_gclk",   .id = 56, .r = { .min = 0, .max = 80000000 }, },
-	{ .n = "can1_gclk",   .id = 57, .r = { .min = 0, .max = 80000000 }, },
-	{ .n = "classd_gclk", .id = 59, .r = { .min = 0, .max = 100000000 },
-	  .pll = true },
+	{ .n = "sdmmc0_gclk", .id = 31, .chg_pid = INT_MIN, },
+	{ .n = "sdmmc1_gclk", .id = 32, .chg_pid = INT_MIN, },
+	{ .n = "tcb0_gclk",   .id = 35, .chg_pid = INT_MIN, .r = { .min = 0, .max = 83000000 }, },
+	{ .n = "tcb1_gclk",   .id = 36, .chg_pid = INT_MIN, .r = { .min = 0, .max = 83000000 }, },
+	{ .n = "pwm_gclk",    .id = 38, .chg_pid = INT_MIN, .r = { .min = 0, .max = 83000000 }, },
+	{ .n = "isc_gclk",    .id = 46, .chg_pid = INT_MIN, },
+	{ .n = "pdmic_gclk",  .id = 48, .chg_pid = INT_MIN, },
+	{ .n = "i2s0_gclk",   .id = 54, .chg_pid = 5, },
+	{ .n = "i2s1_gclk",   .id = 55, .chg_pid = 5, },
+	{ .n = "can0_gclk",   .id = 56, .chg_pid = INT_MIN, .r = { .min = 0, .max = 80000000 }, },
+	{ .n = "can1_gclk",   .id = 57, .chg_pid = INT_MIN, .r = { .min = 0, .max = 80000000 }, },
+	{ .n = "classd_gclk", .id = 59, .chg_pid = 5, .r = { .min = 0, .max = 100000000 }, },
 };
 
 static const struct clk_programmable_layout sama5d2_programmable_layout = {
@@ -162,7 +161,7 @@
 		return;
 	mainxtal_name = of_clk_get_parent_name(np, i);
 
-	regmap = syscon_node_to_regmap(np);
+	regmap = device_node_to_regmap(np);
 	if (IS_ERR(regmap))
 		return;
 
@@ -317,8 +316,8 @@
 						 sama5d2_gck[i].n,
 						 parent_names, 6,
 						 sama5d2_gck[i].id,
-						 sama5d2_gck[i].pll,
-						 &sama5d2_gck[i].r);
+						 &sama5d2_gck[i].r,
+						 sama5d2_gck[i].chg_pid);
 		if (IS_ERR(hw))
 			goto err_free;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/at91/sama5d4.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/at91/sama5d4.c
@@ -136,7 +136,7 @@
 		return;
 	mainxtal_name = of_clk_get_parent_name(np, i);
 
-	regmap = syscon_node_to_regmap(np);
+	regmap = device_node_to_regmap(np);
 	if (IS_ERR(regmap))
 		return;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/bcm/clk-bcm2835.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/bcm/clk-bcm2835.c
@@ -314,6 +314,7 @@
 	struct device *dev;
 	void __iomem *regs;
 	spinlock_t regs_lock; /* spinlock for all clocks */
+	unsigned int soc;
 
 	/*
 	 * Real names of cprman clock parents looked up through
@@ -525,6 +526,20 @@
 		A2W_PLL_CTRL_PRST_DISABLE;
 }
 
+static u32 bcm2835_pll_get_prediv_mask(struct bcm2835_cprman *cprman,
+				       const struct bcm2835_pll_data *data)
+{
+	/*
+	 * On BCM2711 there isn't a pre-divisor available in the PLL feedback
+	 * loop. Bits 13:14 of ANA1 (PLLA,PLLB,PLLC,PLLD) have been re-purposed
+	 * for to for VCO RANGE bits.
+	 */
+	if (cprman->soc & SOC_BCM2711)
+		return 0;
+
+	return data->ana->fb_prediv_mask;
+}
+
 static void bcm2835_pll_choose_ndiv_and_fdiv(unsigned long rate,
 					     unsigned long parent_rate,
 					     u32 *ndiv, u32 *fdiv)
@@ -582,7 +597,7 @@
 	ndiv = (a2wctrl & A2W_PLL_CTRL_NDIV_MASK) >> A2W_PLL_CTRL_NDIV_SHIFT;
 	pdiv = (a2wctrl & A2W_PLL_CTRL_PDIV_MASK) >> A2W_PLL_CTRL_PDIV_SHIFT;
 	using_prediv = cprman_read(cprman, data->ana_reg_base + 4) &
-		data->ana->fb_prediv_mask;
+		       bcm2835_pll_get_prediv_mask(cprman, data);
 
 	if (using_prediv) {
 		ndiv *= 2;
@@ -665,6 +680,7 @@
 	struct bcm2835_pll *pll = container_of(hw, struct bcm2835_pll, hw);
 	struct bcm2835_cprman *cprman = pll->cprman;
 	const struct bcm2835_pll_data *data = pll->data;
+	u32 prediv_mask = bcm2835_pll_get_prediv_mask(cprman, data);
 	bool was_using_prediv, use_fb_prediv, do_ana_setup_first;
 	u32 ndiv, fdiv, a2w_ctl;
 	u32 ana[4];
@@ -682,7 +698,7 @@
 	for (i = 3; i >= 0; i--)
 		ana[i] = cprman_read(cprman, data->ana_reg_base + i * 4);
 
-	was_using_prediv = ana[1] & data->ana->fb_prediv_mask;
+	was_using_prediv = ana[1] & prediv_mask;
 
 	ana[0] &= ~data->ana->mask0;
 	ana[0] |= data->ana->set0;
@@ -692,10 +708,10 @@
 	ana[3] |= data->ana->set3;
 
 	if (was_using_prediv && !use_fb_prediv) {
-		ana[1] &= ~data->ana->fb_prediv_mask;
+		ana[1] &= ~prediv_mask;
 		do_ana_setup_first = true;
 	} else if (!was_using_prediv && use_fb_prediv) {
-		ana[1] |= data->ana->fb_prediv_mask;
+		ana[1] |= prediv_mask;
 		do_ana_setup_first = false;
 	} else {
 		do_ana_setup_first = true;
@@ -916,8 +932,7 @@
 
 static u32 bcm2835_clock_choose_div(struct clk_hw *hw,
 				    unsigned long rate,
-				    unsigned long parent_rate,
-				    bool round_up)
+				    unsigned long parent_rate)
 {
 	struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
 	const struct bcm2835_clock_data *data = clock->data;
@@ -929,10 +944,6 @@
 
 	rem = do_div(temp, rate);
 	div = temp;
-
-	/* Round up and mask off the unused bits */
-	if (round_up && ((div & unused_frac_mask) != 0 || rem != 0))
-		div += unused_frac_mask + 1;
 	div &= ~unused_frac_mask;
 
 	/* different clamping limits apply for a mash clock */
@@ -956,9 +967,9 @@
 	return div;
 }
 
-static long bcm2835_clock_rate_from_divisor(struct bcm2835_clock *clock,
-					    unsigned long parent_rate,
-					    u32 div)
+static unsigned long bcm2835_clock_rate_from_divisor(struct bcm2835_clock *clock,
+						     unsigned long parent_rate,
+						     u32 div)
 {
 	const struct bcm2835_clock_data *data = clock->data;
 	u64 temp;
@@ -1063,7 +1074,7 @@
 	struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
 	struct bcm2835_cprman *cprman = clock->cprman;
 	const struct bcm2835_clock_data *data = clock->data;
-	u32 div = bcm2835_clock_choose_div(hw, rate, parent_rate, false);
+	u32 div = bcm2835_clock_choose_div(hw, rate, parent_rate);
 	u32 ctl;
 
 	spin_lock(&cprman->regs_lock);
@@ -1114,7 +1125,7 @@
 
 	if (!(BIT(parent_idx) & data->set_rate_parent)) {
 		*prate = clk_hw_get_rate(parent);
-		*div = bcm2835_clock_choose_div(hw, rate, *prate, true);
+		*div = bcm2835_clock_choose_div(hw, rate, *prate);
 
 		*avgrate = bcm2835_clock_rate_from_divisor(clock, *prate, *div);
 
@@ -1200,7 +1211,7 @@
 		rate = bcm2835_clock_choose_div_and_prate(hw, i, req->rate,
 							  &div, &prate,
 							  &avgrate);
-		if (rate > best_rate && rate <= req->rate) {
+		if (abs(req->rate - rate) < abs(req->rate - best_rate)) {
 			best_parent = parent;
 			best_prate = prate;
 			best_rate = rate;
@@ -1320,8 +1331,10 @@
 	pll->hw.init = &init;
 
 	ret = devm_clk_hw_register(cprman->dev, &pll->hw);
-	if (ret)
+	if (ret) {
+		kfree(pll);
 		return NULL;
+	}
 	return &pll->hw;
 }
 
@@ -1448,13 +1461,13 @@
 	return &clock->hw;
 }
 
-static struct clk *bcm2835_register_gate(struct bcm2835_cprman *cprman,
+static struct clk_hw *bcm2835_register_gate(struct bcm2835_cprman *cprman,
 					 const struct bcm2835_gate_data *data)
 {
-	return clk_register_gate(cprman->dev, data->name, data->parent,
-				 CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE,
-				 cprman->regs + data->ctl_reg,
-				 CM_GATE_BIT, 0, &cprman->regs_lock);
+	return clk_hw_register_gate(cprman->dev, data->name, data->parent,
+				    CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE,
+				    cprman->regs + data->ctl_reg,
+				    CM_GATE_BIT, 0, &cprman->regs_lock);
 }
 
 typedef struct clk_hw *(*bcm2835_clk_register)(struct bcm2835_cprman *cprman,
@@ -1743,7 +1756,7 @@
 		.load_mask = CM_PLLC_LOADPER,
 		.hold_mask = CM_PLLC_HOLDPER,
 		.fixed_divider = 1,
-		.flags = CLK_SET_RATE_PARENT),
+		.flags = CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
 
 	/*
 	 * PLLD is the display PLL, used to drive DSI display panels.
@@ -2234,6 +2247,7 @@
 	platform_set_drvdata(pdev, cprman);
 
 	cprman->onecell.num = asize;
+	cprman->soc = pdata->soc;
 	hws = cprman->onecell.hws;
 
 	for (i = 0; i < asize; i++) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/bcm/clk-bcm53573-ilp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/bcm/clk-bcm53573-ilp.c
@@ -112,7 +112,7 @@
 		goto err_free_ilp;
 	}
 
-	ilp->regmap = syscon_node_to_regmap(of_get_parent(np));
+	ilp->regmap = syscon_node_to_regmap(np->parent);
 	if (IS_ERR(ilp->regmap)) {
 		err = PTR_ERR(ilp->regmap);
 		goto err_free_ilp;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/bcm/clk-bcm63xx-gate.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/bcm/clk-bcm63xx-gate.c
@@ -155,6 +155,7 @@
 
 	for (entry = table; entry->name; entry++)
 		maxbit = max_t(u8, maxbit, entry->bit);
+	maxbit++;
 
 	hw = devm_kzalloc(&pdev->dev, struct_size(hw, data.hws, maxbit),
 			  GFP_KERNEL);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/bcm/clk-iproc-pll.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/bcm/clk-iproc-pll.c
@@ -736,6 +736,7 @@
 	const char *parent_name;
 	struct iproc_clk *iclk_array;
 	struct clk_hw_onecell_data *clk_data;
+	const char *clk_name;
 
 	if (WARN_ON(!pll_ctrl) || WARN_ON(!clk_ctrl))
 		return;
@@ -783,7 +784,12 @@
 	iclk = &iclk_array[0];
 	iclk->pll = pll;
 
-	init.name = node->name;
+	ret = of_property_read_string_index(node, "clock-output-names",
+					    0, &clk_name);
+	if (WARN_ON(ret))
+		goto err_pll_register;
+
+	init.name = clk_name;
 	init.ops = &iproc_pll_ops;
 	init.flags = 0;
 	parent_name = of_clk_get_parent_name(node, 0);
@@ -803,13 +809,11 @@
 		goto err_pll_register;
 
 	clk_data->hws[0] = &iclk->hw;
+	parent_name = clk_name;
 
 	/* now initialize and register all leaf clocks */
 	for (i = 1; i < num_clks; i++) {
-		const char *clk_name;
-
 		memset(&init, 0, sizeof(init));
-		parent_name = node->name;
 
 		ret = of_property_read_string_index(node, "clock-output-names",
 						    i, &clk_name);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/bcm/clk-raspberrypi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/bcm/clk-raspberrypi.c
@@ -113,7 +113,7 @@
 					 RPI_FIRMWARE_ARM_CLK_ID,
 					 &val);
 	if (ret)
-		return ret;
+		return 0;
 
 	return val * RPI_FIRMWARE_PLLB_ARM_DIV_RATE;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/berlin/bg2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/berlin/bg2.c
@@ -500,12 +500,15 @@
 	int n, ret;
 
 	clk_data = kzalloc(struct_size(clk_data, hws, MAX_CLKS), GFP_KERNEL);
-	if (!clk_data)
+	if (!clk_data) {
+		of_node_put(parent_np);
 		return;
+	}
 	clk_data->num = MAX_CLKS;
 	hws = clk_data->hws;
 
 	gbase = of_iomap(parent_np, 0);
+	of_node_put(parent_np);
 	if (!gbase)
 		return;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/berlin/bg2q.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/berlin/bg2q.c
@@ -286,19 +286,23 @@
 	int n, ret;
 
 	clk_data = kzalloc(struct_size(clk_data, hws, MAX_CLKS), GFP_KERNEL);
-	if (!clk_data)
+	if (!clk_data) {
+		of_node_put(parent_np);
 		return;
+	}
 	clk_data->num = MAX_CLKS;
 	hws = clk_data->hws;
 
 	gbase = of_iomap(parent_np, 0);
 	if (!gbase) {
+		of_node_put(parent_np);
 		pr_err("%pOF: Unable to map global base\n", np);
 		return;
 	}
 
 	/* BG2Q CPU PLL is not part of global registers */
 	cpupll_base = of_iomap(parent_np, 1);
+	of_node_put(parent_np);
 	if (!cpupll_base) {
 		pr_err("%pOF: Unable to map cpupll base\n", np);
 		iounmap(gbase);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/clk-ast2600.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/clk-ast2600.c
@@ -17,7 +17,8 @@
 
 #define ASPEED_G6_NUM_CLKS		67
 
-#define ASPEED_G6_SILICON_REV		0x004
+#define ASPEED_G6_SILICON_REV		0x014
+#define CHIP_REVISION_ID			GENMASK(23, 16)
 
 #define ASPEED_G6_RESET_CTRL		0x040
 #define ASPEED_G6_RESET_CTRL2		0x050
@@ -47,6 +48,8 @@
 static struct clk_hw_onecell_data *aspeed_g6_clk_data;
 
 static void __iomem *scu_g6_base;
+/* AST2600 revision: A0, A1, A2, etc */
+static u8 soc_rev;
 
 /*
  * Clocks marked with CLK_IS_CRITICAL:
@@ -57,10 +60,10 @@
 static const struct aspeed_gate_data aspeed_g6_gates[] = {
 	/*				    clk rst  name		parent	 flags */
 	[ASPEED_CLK_GATE_MCLK]		= {  0, -1, "mclk-gate",	"mpll",	 CLK_IS_CRITICAL }, /* SDRAM */
-	[ASPEED_CLK_GATE_ECLK]		= {  1, -1, "eclk-gate",	"eclk",	 0 },	/* Video Engine */
+	[ASPEED_CLK_GATE_ECLK]		= {  1,  6, "eclk-gate",	"eclk",	 0 },	/* Video Engine */
 	[ASPEED_CLK_GATE_GCLK]		= {  2,  7, "gclk-gate",	NULL,	 0 },	/* 2D engine */
 	/* vclk parent - dclk/d1clk/hclk/mclk */
-	[ASPEED_CLK_GATE_VCLK]		= {  3,  6, "vclk-gate",	NULL,	 0 },	/* Video Capture */
+	[ASPEED_CLK_GATE_VCLK]		= {  3, -1, "vclk-gate",	NULL,	 0 },	/* Video Capture */
 	[ASPEED_CLK_GATE_BCLK]		= {  4,  8, "bclk-gate",	"bclk",	 0 }, /* PCIe/PCI */
 	/* From dpll */
 	[ASPEED_CLK_GATE_DCLK]		= {  5, -1, "dclk-gate",	NULL,	 CLK_IS_CRITICAL }, /* DAC */
@@ -130,6 +133,18 @@
 	{ 0 }
 };
 
+static const struct clk_div_table ast2600_emmc_extclk_div_table[] = {
+	{ 0x0, 2 },
+	{ 0x1, 4 },
+	{ 0x2, 6 },
+	{ 0x3, 8 },
+	{ 0x4, 10 },
+	{ 0x5, 12 },
+	{ 0x6, 14 },
+	{ 0x7, 16 },
+	{ 0 }
+};
+
 static const struct clk_div_table ast2600_mac_div_table[] = {
 	{ 0x0, 4 },
 	{ 0x1, 4 },
@@ -178,17 +193,32 @@
 {
 	unsigned int mult, div;
 
-	if (val & BIT(20)) {
-		/* Pass through mode */
-		mult = div = 1;
+	if (soc_rev >= 2) {
+		if (val & BIT(24)) {
+			/* Pass through mode */
+			mult = div = 1;
+		} else {
+			/* F = 25Mhz * [(m + 1) / (n + 1)] / (p + 1) */
+			u32 m = val & 0x1fff;
+			u32 n = (val >> 13) & 0x3f;
+			u32 p = (val >> 19) & 0xf;
+
+			mult = (m + 1);
+			div = (n + 1) * (p + 1);
+		}
 	} else {
-		/* F = 25Mhz * (2-od) * [(m + 2) / (n + 1)] */
-		u32 m = (val >> 5) & 0x3f;
-		u32 od = (val >> 4) & 0x1;
-		u32 n = val & 0xf;
-
-		mult = (2 - od) * (m + 2);
-		div = n + 1;
+		if (val & BIT(20)) {
+			/* Pass through mode */
+			mult = div = 1;
+		} else {
+			/* F = 25Mhz * (2-od) * [(m + 2) / (n + 1)] */
+			u32 m = (val >> 5) & 0x3f;
+			u32 od = (val >> 4) & 0x1;
+			u32 n = val & 0xf;
+
+			mult = (2 - od) * (m + 2);
+			div = n + 1;
+		}
 	}
 	return clk_hw_register_fixed_factor(NULL, name, "clkin", 0,
 			mult, div);
@@ -389,6 +419,11 @@
 	return hw;
 }
 
+static const char *const emmc_extclk_parent_names[] = {
+	"emmc_extclk_hpll_in",
+	"mpll",
+};
+
 static const char * const vclk_parent_names[] = {
 	"dpll",
 	"d1pll",
@@ -458,16 +493,32 @@
 		return PTR_ERR(hw);
 	aspeed_g6_clk_data->hws[ASPEED_CLK_UARTX] = hw;
 
-	/* EMMC ext clock divider */
-	hw = clk_hw_register_gate(dev, "emmc_extclk_gate", "hpll", 0,
-			scu_g6_base + ASPEED_G6_CLK_SELECTION1, 15, 0,
-			&aspeed_g6_clk_lock);
+	/* EMMC ext clock */
+	hw = clk_hw_register_fixed_factor(dev, "emmc_extclk_hpll_in", "hpll",
+					  0, 1, 2);
 	if (IS_ERR(hw))
 		return PTR_ERR(hw);
-	hw = clk_hw_register_divider_table(dev, "emmc_extclk", "emmc_extclk_gate", 0,
-			scu_g6_base + ASPEED_G6_CLK_SELECTION1, 12, 3, 0,
-			ast2600_div_table,
-			&aspeed_g6_clk_lock);
+
+	hw = clk_hw_register_mux(dev, "emmc_extclk_mux",
+				 emmc_extclk_parent_names,
+				 ARRAY_SIZE(emmc_extclk_parent_names), 0,
+				 scu_g6_base + ASPEED_G6_CLK_SELECTION1, 11, 1,
+				 0, &aspeed_g6_clk_lock);
+	if (IS_ERR(hw))
+		return PTR_ERR(hw);
+
+	hw = clk_hw_register_gate(dev, "emmc_extclk_gate", "emmc_extclk_mux",
+				  0, scu_g6_base + ASPEED_G6_CLK_SELECTION1,
+				  15, 0, &aspeed_g6_clk_lock);
+	if (IS_ERR(hw))
+		return PTR_ERR(hw);
+
+	hw = clk_hw_register_divider_table(dev, "emmc_extclk",
+					   "emmc_extclk_gate", 0,
+					   scu_g6_base +
+						ASPEED_G6_CLK_SELECTION1, 12,
+					   3, 0, ast2600_emmc_extclk_div_table,
+					   &aspeed_g6_clk_lock);
 	if (IS_ERR(hw))
 		return PTR_ERR(hw);
 	aspeed_g6_clk_data->hws[ASPEED_CLK_EMMC] = hw;
@@ -528,7 +579,7 @@
 	regmap_write(map, 0x308, 0x12000); /* 3x3 = 9 */
 
 	/* P-Bus (BCLK) clock divider */
-	hw = clk_hw_register_divider_table(dev, "bclk", "hpll", 0,
+	hw = clk_hw_register_divider_table(dev, "bclk", "epll", 0,
 			scu_g6_base + ASPEED_G6_CLK_SELECTION1, 20, 3, 0,
 			ast2600_div_table,
 			&aspeed_g6_clk_lock);
@@ -599,14 +650,22 @@
 	2, 2, 3, 5,
 };
 
-static const u32 ast2600_a1_axi_ahb_div_table[] = {
-	4, 6, 2, 4,
+static const u32 ast2600_a1_axi_ahb_div0_tbl[] = {
+	3, 2, 3, 4,
+};
+
+static const u32 ast2600_a1_axi_ahb_div1_tbl[] = {
+	3, 4, 6, 8,
+};
+
+static const u32 ast2600_a1_axi_ahb200_tbl[] = {
+	3, 4, 3, 4, 2, 2, 2, 2,
 };
 
 static void __init aspeed_g6_cc(struct regmap *map)
 {
 	struct clk_hw *hw;
-	u32 val, div, chip_id, axi_div, ahb_div;
+	u32 val, div, divbits, axi_div, ahb_div;
 
 	clk_hw_register_fixed_rate(NULL, "clkin", NULL, 0, 25000000);
 
@@ -636,11 +695,21 @@
 	else
 		axi_div = 2;
 
-	regmap_read(map, ASPEED_G6_SILICON_REV, &chip_id);
-	if (chip_id & BIT(16))
-		ahb_div = ast2600_a1_axi_ahb_div_table[(val >> 11) & 0x3];
-	else
+	divbits = (val >> 11) & 0x3;
+	if (soc_rev >= 1) {
+		if (!divbits) {
+			ahb_div = ast2600_a1_axi_ahb200_tbl[(val >> 8) & 0x3];
+			if (val & BIT(16))
+				ahb_div *= 2;
+		} else {
+			if (val & BIT(16))
+				ahb_div = ast2600_a1_axi_ahb_div1_tbl[divbits];
+			else
+				ahb_div = ast2600_a1_axi_ahb_div0_tbl[divbits];
+		}
+	} else {
 		ahb_div = ast2600_a0_axi_ahb_div_table[(val >> 11) & 0x3];
+	}
 
 	hw = clk_hw_register_fixed_factor(NULL, "ahb", "hpll", 0, 1, axi_div * ahb_div);
 	aspeed_g6_clk_data->hws[ASPEED_CLK_AHB] = hw;
@@ -672,6 +741,8 @@
 	if (!scu_g6_base)
 		return;
 
+	soc_rev = (readl(scu_g6_base + ASPEED_G6_SILICON_REV) & CHIP_REVISION_ID) >> 16;
+
 	aspeed_g6_clk_data = kzalloc(struct_size(aspeed_g6_clk_data, hws,
 				      ASPEED_G6_NUM_CLKS), GFP_KERNEL);
 	if (!aspeed_g6_clk_data)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/clk-axi-clkgen.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/clk-axi-clkgen.c
@@ -7,6 +7,7 @@
  */
 
 #include <linux/platform_device.h>
+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/slab.h>
 #include <linux/io.h>
@@ -412,7 +413,7 @@
 	struct clk_init_data init;
 	const char *parent_names[2];
 	const char *clk_name;
-	struct resource *mem;
+	struct clk *axi_clk;
 	unsigned int i;
 	int ret;
 
@@ -427,14 +428,29 @@
 	if (!axi_clkgen)
 		return -ENOMEM;
 
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	axi_clkgen->base = devm_ioremap_resource(&pdev->dev, mem);
+	axi_clkgen->base = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(axi_clkgen->base))
 		return PTR_ERR(axi_clkgen->base);
 
 	init.num_parents = of_clk_get_parent_count(pdev->dev.of_node);
-	if (init.num_parents < 1 || init.num_parents > 2)
-		return -EINVAL;
+
+	axi_clk = devm_clk_get_enabled(&pdev->dev, "s_axi_aclk");
+	if (!IS_ERR(axi_clk)) {
+		if (init.num_parents < 2 || init.num_parents > 3)
+			return -EINVAL;
+
+		init.num_parents -= 1;
+	} else {
+		/*
+		 * Legacy... So that old DTs which do not have clock-names still
+		 * work. In this case we don't explicitly enable the AXI bus
+		 * clock.
+		 */
+		if (PTR_ERR(axi_clk) != -ENOENT)
+			return PTR_ERR(axi_clk);
+		if (init.num_parents < 1 || init.num_parents > 2)
+			return -EINVAL;
+	}
 
 	for (i = 0; i < init.num_parents; i++) {
 		parent_names[i] = of_clk_get_parent_name(pdev->dev.of_node, i);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/clk-cdce925.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/clk-cdce925.c
@@ -705,6 +705,10 @@
 	for (i = 0; i < data->chip_info->num_plls; ++i) {
 		pll_clk_name[i] = kasprintf(GFP_KERNEL, "%pOFn.pll%d",
 			client->dev.of_node, i);
+		if (!pll_clk_name[i]) {
+			err = -ENOMEM;
+			goto error;
+		}
 		init.name = pll_clk_name[i];
 		data->pll[i].chip = data;
 		data->pll[i].hw.init = &init;
@@ -746,6 +750,10 @@
 	init.num_parents = 1;
 	init.parent_names = &parent_name; /* Mux Y1 to input */
 	init.name = kasprintf(GFP_KERNEL, "%pOFn.Y1", client->dev.of_node);
+	if (!init.name) {
+		err = -ENOMEM;
+		goto error;
+	}
 	data->clk[0].chip = data;
 	data->clk[0].hw.init = &init;
 	data->clk[0].index = 0;
@@ -764,6 +772,10 @@
 	for (i = 1; i < data->chip_info->num_outputs; ++i) {
 		init.name = kasprintf(GFP_KERNEL, "%pOFn.Y%d",
 			client->dev.of_node, i+1);
+		if (!init.name) {
+			err = -ENOMEM;
+			goto error;
+		}
 		data->clk[i].chip = data;
 		data->clk[i].hw.init = &init;
 		data->clk[i].index = i;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/clk-clps711x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/clk-clps711x.c
@@ -28,11 +28,13 @@
 	{ .val = 1, .div = 8, },
 	{ .val = 2, .div = 2, },
 	{ .val = 3, .div = 1, },
+	{ /* sentinel */ }
 };
 
 static const struct clk_div_table timer_div_table[] = {
 	{ .val = 0, .div = 256, },
 	{ .val = 1, .div = 1, },
+	{ /* sentinel */ }
 };
 
 struct clps711x_clk {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/clk-conf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/clk-conf.c
@@ -33,9 +33,12 @@
 			else
 				return rc;
 		}
-		if (clkspec.np == node && !clk_supplier)
+		if (clkspec.np == node && !clk_supplier) {
+			of_node_put(clkspec.np);
 			return 0;
+		}
 		pclk = of_clk_get_from_provider(&clkspec);
+		of_node_put(clkspec.np);
 		if (IS_ERR(pclk)) {
 			if (PTR_ERR(pclk) != -EPROBE_DEFER)
 				pr_warn("clk: couldn't get parent clock %d for %pOF\n",
@@ -48,10 +51,12 @@
 		if (rc < 0)
 			goto err;
 		if (clkspec.np == node && !clk_supplier) {
+			of_node_put(clkspec.np);
 			rc = 0;
 			goto err;
 		}
 		clk = of_clk_get_from_provider(&clkspec);
+		of_node_put(clkspec.np);
 		if (IS_ERR(clk)) {
 			if (PTR_ERR(clk) != -EPROBE_DEFER)
 				pr_warn("clk: couldn't get assigned clock %d for %pOF\n",
@@ -93,10 +98,13 @@
 				else
 					return rc;
 			}
-			if (clkspec.np == node && !clk_supplier)
+			if (clkspec.np == node && !clk_supplier) {
+				of_node_put(clkspec.np);
 				return 0;
+			}
 
 			clk = of_clk_get_from_provider(&clkspec);
+			of_node_put(clkspec.np);
 			if (IS_ERR(clk)) {
 				if (PTR_ERR(clk) != -EPROBE_DEFER)
 					pr_warn("clk: couldn't get clock %d for %pOF\n",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/clk-devres.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/clk-devres.c
@@ -4,42 +4,101 @@
 #include <linux/export.h>
 #include <linux/gfp.h>
 
+struct devm_clk_state {
+	struct clk *clk;
+	void (*exit)(struct clk *clk);
+};
+
 static void devm_clk_release(struct device *dev, void *res)
 {
-	clk_put(*(struct clk **)res);
+	struct devm_clk_state *state = res;
+
+	if (state->exit)
+		state->exit(state->clk);
+
+	clk_put(state->clk);
 }
 
-struct clk *devm_clk_get(struct device *dev, const char *id)
+static struct clk *__devm_clk_get(struct device *dev, const char *id,
+				  struct clk *(*get)(struct device *dev, const char *id),
+				  int (*init)(struct clk *clk),
+				  void (*exit)(struct clk *clk))
 {
-	struct clk **ptr, *clk;
+	struct devm_clk_state *state;
+	struct clk *clk;
+	int ret;
 
-	ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL);
-	if (!ptr)
+	state = devres_alloc(devm_clk_release, sizeof(*state), GFP_KERNEL);
+	if (!state)
 		return ERR_PTR(-ENOMEM);
 
-	clk = clk_get(dev, id);
-	if (!IS_ERR(clk)) {
-		*ptr = clk;
-		devres_add(dev, ptr);
-	} else {
-		devres_free(ptr);
+	clk = get(dev, id);
+	if (IS_ERR(clk)) {
+		ret = PTR_ERR(clk);
+		goto err_clk_get;
+	}
+
+	if (init) {
+		ret = init(clk);
+		if (ret)
+			goto err_clk_init;
 	}
 
+	state->clk = clk;
+	state->exit = exit;
+
+	devres_add(dev, state);
+
 	return clk;
+
+err_clk_init:
+
+	clk_put(clk);
+err_clk_get:
+
+	devres_free(state);
+	return ERR_PTR(ret);
+}
+
+struct clk *devm_clk_get(struct device *dev, const char *id)
+{
+	return __devm_clk_get(dev, id, clk_get, NULL, NULL);
 }
 EXPORT_SYMBOL(devm_clk_get);
 
-struct clk *devm_clk_get_optional(struct device *dev, const char *id)
+struct clk *devm_clk_get_prepared(struct device *dev, const char *id)
 {
-	struct clk *clk = devm_clk_get(dev, id);
+	return __devm_clk_get(dev, id, clk_get, clk_prepare, clk_unprepare);
+}
+EXPORT_SYMBOL_GPL(devm_clk_get_prepared);
 
-	if (clk == ERR_PTR(-ENOENT))
-		return NULL;
+struct clk *devm_clk_get_enabled(struct device *dev, const char *id)
+{
+	return __devm_clk_get(dev, id, clk_get,
+			      clk_prepare_enable, clk_disable_unprepare);
+}
+EXPORT_SYMBOL_GPL(devm_clk_get_enabled);
 
-	return clk;
+struct clk *devm_clk_get_optional(struct device *dev, const char *id)
+{
+	return __devm_clk_get(dev, id, clk_get_optional, NULL, NULL);
 }
 EXPORT_SYMBOL(devm_clk_get_optional);
 
+struct clk *devm_clk_get_optional_prepared(struct device *dev, const char *id)
+{
+	return __devm_clk_get(dev, id, clk_get_optional,
+			      clk_prepare, clk_unprepare);
+}
+EXPORT_SYMBOL_GPL(devm_clk_get_optional_prepared);
+
+struct clk *devm_clk_get_optional_enabled(struct device *dev, const char *id)
+{
+	return __devm_clk_get(dev, id, clk_get_optional,
+			      clk_prepare_enable, clk_disable_unprepare);
+}
+EXPORT_SYMBOL_GPL(devm_clk_get_optional_enabled);
+
 struct clk_bulk_devres {
 	struct clk_bulk_data *clks;
 	int num_clks;
@@ -92,13 +151,20 @@
 }
 EXPORT_SYMBOL_GPL(devm_clk_bulk_get_optional);
 
+static void devm_clk_bulk_release_all(struct device *dev, void *res)
+{
+	struct clk_bulk_devres *devres = res;
+
+	clk_bulk_put_all(devres->num_clks, devres->clks);
+}
+
 int __must_check devm_clk_bulk_get_all(struct device *dev,
 				       struct clk_bulk_data **clks)
 {
 	struct clk_bulk_devres *devres;
 	int ret;
 
-	devres = devres_alloc(devm_clk_bulk_release,
+	devres = devres_alloc(devm_clk_bulk_release_all,
 			      sizeof(*devres), GFP_KERNEL);
 	if (!devres)
 		return -ENOMEM;
@@ -139,18 +205,19 @@
 struct clk *devm_get_clk_from_child(struct device *dev,
 				    struct device_node *np, const char *con_id)
 {
-	struct clk **ptr, *clk;
+	struct devm_clk_state *state;
+	struct clk *clk;
 
-	ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL);
-	if (!ptr)
+	state = devres_alloc(devm_clk_release, sizeof(*state), GFP_KERNEL);
+	if (!state)
 		return ERR_PTR(-ENOMEM);
 
 	clk = of_clk_get_by_name(np, con_id);
 	if (!IS_ERR(clk)) {
-		*ptr = clk;
-		devres_add(dev, ptr);
+		state->clk = clk;
+		devres_add(dev, state);
 	} else {
-		devres_free(ptr);
+		devres_free(state);
 	}
 
 	return clk;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/clk-gate.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/clk-gate.c
@@ -56,7 +56,7 @@
 {
 	struct clk_gate *gate = to_clk_gate(hw);
 	int set = gate->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
-	unsigned long uninitialized_var(flags);
+	unsigned long flags;
 	u32 reg;
 
 	set ^= enable;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/clk-gpio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/clk-gpio.c
@@ -280,7 +280,7 @@
 	else
 		clk = clk_register_gpio_gate(&pdev->dev, node->name,
 				parent_names ?  parent_names[0] : NULL, gpiod,
-				0);
+				CLK_SET_RATE_PARENT);
 	if (IS_ERR(clk))
 		return PTR_ERR(clk);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/clk-npcm7xx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/clk-npcm7xx.c
@@ -647,7 +647,7 @@
 	return;
 
 npcm7xx_init_fail:
-	kfree(npcm7xx_clk_data->hws);
+	kfree(npcm7xx_clk_data);
 npcm7xx_init_np_err:
 	iounmap(clk_base);
 npcm7xx_init_error:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/clk-oxnas.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/clk-oxnas.c
@@ -207,7 +207,7 @@
 
 static int oxnas_stdclk_probe(struct platform_device *pdev)
 {
-	struct device_node *np = pdev->dev.of_node;
+	struct device_node *np = pdev->dev.of_node, *parent_np;
 	const struct oxnas_stdclk_data *data;
 	const struct of_device_id *id;
 	struct regmap *regmap;
@@ -219,7 +219,9 @@
 		return -ENODEV;
 	data = id->data;
 
-	regmap = syscon_node_to_regmap(of_get_parent(np));
+	parent_np = of_get_parent(np);
+	regmap = syscon_node_to_regmap(parent_np);
+	of_node_put(parent_np);
 	if (IS_ERR(regmap)) {
 		dev_err(&pdev->dev, "failed to have parent regmap\n");
 		return PTR_ERR(regmap);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/clk-s2mps11.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/clk-s2mps11.c
@@ -195,6 +195,7 @@
 	return ret;
 
 err_reg:
+	of_node_put(s2mps11_clks[0].clk_np);
 	while (--i >= 0)
 		clkdev_drop(s2mps11_clks[i].lookup);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/clk-scmi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/clk-scmi.c
@@ -103,6 +103,8 @@
 static int scmi_clk_ops_init(struct device *dev, struct scmi_clk *sclk)
 {
 	int ret;
+	unsigned long min_rate, max_rate;
+
 	struct clk_init_data init = {
 		.flags = CLK_GET_RATE_NOCACHE,
 		.num_parents = 0,
@@ -112,9 +114,23 @@
 
 	sclk->hw.init = &init;
 	ret = devm_clk_hw_register(dev, &sclk->hw);
-	if (!ret)
-		clk_hw_set_rate_range(&sclk->hw, sclk->info->range.min_rate,
-				      sclk->info->range.max_rate);
+	if (ret)
+		return ret;
+
+	if (sclk->info->rate_discrete) {
+		int num_rates = sclk->info->list.num_rates;
+
+		if (num_rates <= 0)
+			return -EINVAL;
+
+		min_rate = sclk->info->list.rates[0];
+		max_rate = sclk->info->list.rates[num_rates - 1];
+	} else {
+		min_rate = sclk->info->range.min_rate;
+		max_rate = sclk->info->range.max_rate;
+	}
+
+	clk_hw_set_rate_range(&sclk->hw, min_rate, max_rate);
 	return ret;
 }
 
@@ -154,6 +170,7 @@
 		sclk->info = handle->clk_ops->info_get(handle, idx);
 		if (!sclk->info) {
 			dev_dbg(dev, "invalid clock info for idx %d\n", idx);
+			devm_kfree(dev, sclk);
 			continue;
 		}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/clk-si5324.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/clk-si5324.c
@@ -0,0 +1,1227 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * clk-si5324.c - Si5324 clock driver
+ *
+ * Copyright (C) 2017-2018 Xilinx, Inc.
+ *
+ * Author:	Venkateshwar Rao G <vgannava.xilinx.com>
+ *		Leon Woestenberg <leon@sidebranch.com>
+ */
+
+#include <asm/div64.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/rational.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include "clk-si5324.h"
+#include "si5324.h"
+#include "si5324drv.h"
+
+struct si5324_driver_data;
+
+/**
+ * struct si5324_parameters - si5324 core parameters
+ *
+ * @n1_hs_min:		Minimum high-speed n1 output divider
+ * @n1_hs_max:		Maximum high-speed n1 output divider
+ * @n1_hs:		n1 high-speed output divider
+ * @nc1_ls_min:		Minimum low-speed clkout1 output divider
+ * @nc1_ls_max:		Maximum low-speed clkout1 output divider
+ * @nc1_ls:		Clkout1 low-speed output divider
+ * @nc2_ls_min:		Minimum low-speed clkout2 output divider
+ * @nc2_ls_max:		Maximum low-speed clkout2 output divider
+ * @nc2_ls:		Clkout2 low-speed output divider
+ * @n2_hs:		High-speed feedback divider
+ * @n2_ls_min:		Minimum low-speed feedback divider
+ * @n2_ls_max:		Maximum low-speed feedback divider
+ * @n2_ls:		Low-speed feedback divider
+ * @n31_min:		Minimum input divider for clk1
+ * @n31_max:		Maximum input divider for clk1
+ * @n31:		Input divider for clk1
+ * @n32_min:		Minimum input divider for clk2
+ * @n32_max:		Maximum input divider for clk2
+ * @n32:		Input divider for clk2
+ * @fin:		Input frequency
+ * @fout:		Output frequency
+ * @fosc:		Osc frequency
+ * @best_delta_fout:	Delta out frequency
+ * @best_fout:		Best output frequency
+ * @best_n1_hs:		Best high speed output divider
+ * @best_nc1_ls:	Best low speed clkout1 divider
+ * @best_n2_hs:		Best high speed feedback divider
+ * @best_n2_ls:		Best low speed feedback divider
+ * @best_n3:		Best input clock divider
+ * @valid: Validility
+ */
+struct si5324_parameters {
+	u32 n1_hs_min;
+	u32 n1_hs_max;
+	u32 n1_hs;
+	u32 nc1_ls_min;
+	u32 nc1_ls_max;
+	u32 nc1_ls;
+	u32 nc2_ls_min;
+	u32 nc2_ls_max;
+	u32 nc2_ls;
+	u32 n2_hs;
+	u32 n2_ls_min;
+	u32 n2_ls_max;
+	u32 n2_ls;
+	u32 n31_min;
+	u32 n31_max;
+	u32 n31;
+	u32 n32_min;
+	u32 n32_max;
+	u32 n32;
+	u64 fin;
+	u64 fout;
+	u64 fosc;
+	u64 best_delta_fout;
+	u64 best_fout;
+	u32 best_n1_hs;
+	u32 best_nc1_ls;
+	u32 best_n2_hs;
+	u32 best_n2_ls;
+	u32 best_n3;
+	int valid;
+};
+
+/**
+ * struct si5324_hw_data - Clock parameters
+ *
+ * @hw:		Handle between common and hardware-specific interfaces
+ * @drvdata:	Driver private data
+ * @num:	Differential pair clock number
+ */
+struct si5324_hw_data {
+	struct clk_hw hw;
+	struct si5324_driver_data *drvdata;
+	unsigned char num;
+};
+
+/**
+ * struct si5324_driver_data - Driver parameters
+ * @client:		I2C client pointer
+ * @regmap:		Device's regmap
+ * @onecell:		Clock onecell data
+ * @params:		Device parameters
+ * @pxtal:		Clock
+ * @pxtal_name:		Clock name
+ * @xtal:		Reference clock
+ * @pclkin1:		Clock in 1
+ * @pclkin1_name:	Clock in 1 name
+ * @clkin1:		Differential input clock 1
+ * @pclkin2:		Clock in 2
+ * @pclkin2_name:	Clock in 2 name
+ * @clkin2:		Differential input clock 2
+ * @pll:		Pll clock
+ * @clkout:		Output clock
+ * @rate_clkout0:	Clock out 0 rate
+ * @rate_clkout1:	Clock out 1 rate
+ */
+struct si5324_driver_data {
+	struct i2c_client		*client;
+	struct regmap			*regmap;
+	struct clk_onecell_data		onecell;
+	struct si5324_parameters	params;
+	struct clk			*pxtal;
+	const char			*pxtal_name;
+	struct clk_hw			xtal;
+	struct clk			*pclkin1;
+	const char			*pclkin1_name;
+	struct clk_hw			clkin1;
+	struct clk			*pclkin2;
+	const char			*pclkin2_name;
+	struct clk_hw			clkin2;
+	struct si5324_hw_data		pll;
+	struct si5324_hw_data		*clkout;
+	unsigned long			rate_clkout0;
+	unsigned long			rate_clkout1;
+};
+
+static const char * const si5324_input_names[] = {
+	"xtal", "clkin1", "clkin2"
+};
+
+static const char * const si5324_pll_name = "pll";
+
+static const char * const si5324_clkout_names[] = {
+	"clk0", "clk1"
+};
+
+enum si53xx_variant {
+	si5319,
+	si5324,
+	si5328
+};
+
+static const char * const si53xx_variant_name[] = {
+	"si5319", "si5324", "si5328"
+};
+
+/**
+ * si5324_reg_read - Read a single si5324 register.
+ *
+ * @drvdata:	Device to read from.
+ * @reg:	Register to read.
+ *
+ * This function reads data from a single register
+ *
+ * Return:	Data of the register on success, error number on failure
+ */
+static inline int
+si5324_reg_read(struct si5324_driver_data *drvdata, u8 reg)
+{
+	u32 val;
+	int ret;
+
+	ret = regmap_read(drvdata->regmap, reg, &val);
+	if (ret < 0) {
+		dev_err(&drvdata->client->dev,
+			"unable to read from reg%02x\n", reg);
+		return ret;
+	}
+
+	return (u8)val;
+}
+
+/**
+ * si5324_bulk_read - Read multiple si5324 registers
+ *
+ * @drvdata:	Device to read from
+ * @reg:	First register to be read from
+ * @count:	Number of registers
+ * @buf:	Pointer to store read value
+ *
+ * This function reads from multiple registers which are in
+ * sequential order
+ *
+ * Return:	Number of bytes read
+ */
+static inline int si5324_bulk_read(struct si5324_driver_data *drvdata,
+				   u8 reg, u8 count, u8 *buf)
+{
+	return regmap_bulk_read(drvdata->regmap, reg, buf, count);
+}
+
+/**
+ * si5324_reg_write - Write a single si5324 register.
+ *
+ * @drvdata:	Device to write to.
+ * @reg:	Register to write to.
+ * @val:	Value to write.
+ *
+ * This function writes into a single register
+ *
+ * Return:	Zero on success, a negative error number on failure.
+ *
+ */
+static inline int si5324_reg_write(struct si5324_driver_data *drvdata,
+				   u8 reg, u8 val)
+{
+	int ret = regmap_write(drvdata->regmap, reg, val);
+
+	dev_dbg(&drvdata->client->dev, "%s 0x%02x @%02d\n", __func__,
+		(int)val, (int)reg);
+	return ret;
+}
+
+/**
+ * si5324_bulk_write - Write into multiple si5324 registers
+ *
+ * @drvdata:	Device to write to
+ * @reg:	First register
+ * @count:	Number of registers
+ * @buf:	Block of data to be written
+ *
+ * This function writes into multiple registers.
+ *
+ * Return:	Zero on success, a negative error number on failure.
+ */
+static inline int si5324_bulk_write(struct si5324_driver_data *drvdata,
+				    u8 reg, u8 count, const u8 *buf)
+{
+	return regmap_raw_write(drvdata->regmap, reg, buf, count);
+}
+
+/**
+ * si5324_set_bits - Set the value of a bitfield in a si5324 register
+ *
+ * @drvdata:	Device to write to.
+ * @reg:	Register to write to.
+ * @mask:	Mask of bits to set.
+ * @val:	Value to set (unshifted)
+ *
+ * This function set particular bits in register
+ *
+ * Return:	Zero on success, a negative error number on failure.
+ */
+static inline int si5324_set_bits(struct si5324_driver_data *drvdata,
+				  u8 reg, u8 mask, u8 val)
+{
+	return regmap_update_bits(drvdata->regmap, reg, mask, val);
+}
+
+/**
+ * si5324_bulk_scatter_write - Write into multiple si5324 registers
+ *
+ * @drvdata:	Device to write to
+ * @count:	Number of registers
+ * @buf:	Register and data to write
+ *
+ * This function writes into multiple registers which are need not
+ * to be in sequential order.
+ *
+ * Return:	Number of bytes written
+ */
+static inline int
+si5324_bulk_scatter_write(struct si5324_driver_data *drvdata,
+			  u8 count, const u8 *buf)
+{
+	int i;
+	int ret = 0;
+
+	for (i = 0; i < count; i++) {
+		ret = si5324_reg_write(drvdata, buf[i * 2], buf[i * 2 + 1]);
+		if (ret)
+			return ret;
+	}
+	return ret;
+}
+
+/**
+ * si5324_initialize - Initializes si5324 device
+ *
+ * @drvdata:	Device instance
+ *
+ * This function initializes si5324 with the following settings
+ * Keep reset asserted for 20ms
+ * 1. freerun mode
+ * 2. Disable output clocks during calibration
+ * 3. Clock selection mode : default value, manual
+ * 4. output signal format : LVDS for clkout1, disable clkout2
+ * 5. CS_CA pin in ignored
+ * 6. Set lock time to 13.3ms
+ * 7. Enables the fastlock.
+ *
+ * Return:	Zero on success, negative number on failure.
+ */
+static int si5324_initialize(struct si5324_driver_data *drvdata)
+{
+	int ret = 0;
+
+	si5324_set_bits(drvdata, SI5324_RESET_CALIB,
+			SI5324_RST_ALL, SI5324_RST_ALL);
+	msleep(SI5324_RESET_DELAY_MS);
+	si5324_set_bits(drvdata, SI5324_RESET_CALIB, SI5324_RST_ALL, 0);
+	msleep(SI5324_RESET_DELAY_MS);
+
+	ret = si5324_reg_read(drvdata, SI5324_CONTROL);
+	if (ret < 0)
+		return ret;
+
+	si5324_reg_write(drvdata, SI5324_CONTROL,
+			 (ret | SI5324_CONTROL_FREE_RUN));
+
+	ret = si5324_reg_read(drvdata, SI5324_CKSEL);
+	if (ret < 0)
+		return ret;
+
+	si5324_reg_write(drvdata, SI5324_CKSEL, (ret | SI5324_CKSEL_SQL_ICAL));
+	si5324_reg_write(drvdata, SI3324_AUTOSEL, SI5324_AUTOSEL_DEF);
+	si5324_reg_write(drvdata, SI5324_OUTPUT_SIGFMT,
+			 SI5324_OUTPUT_SF1_DEFAULT);
+
+	ret = si5324_reg_read(drvdata, SI5324_DSBL_CLKOUT);
+	if (ret < 0)
+		return ret;
+
+	si5324_reg_write(drvdata, SI5324_DSBL_CLKOUT,
+			 (ret | SI5324_DSBL_CLKOUT2));
+	ret = si5324_reg_read(drvdata, SI5324_POWERDOWN);
+	if (ret < 0)
+		return ret;
+
+	si5324_reg_write(drvdata, SI5324_POWERDOWN, (ret | SI5324_PD_CK2));
+	si5324_reg_write(drvdata, SI5324_FOS_LOCKT, SI5324_FOS_DEFAULT);
+
+	ret = si5324_reg_read(drvdata, SI5324_CK_ACTV_SEL);
+	if (ret < 0)
+		return ret;
+
+	si5324_reg_write(drvdata, SI5324_CK_ACTV_SEL, SI5324_CK_DEFAULT);
+	ret = si5324_reg_read(drvdata, SI5324_FASTLOCK);
+	if (ret < 0)
+		return ret;
+
+	si5324_reg_write(drvdata, SI5324_FASTLOCK, (ret | SI5324_FASTLOCK_EN));
+	return 0;
+}
+
+/**
+ * si5324_read_parameters - Reads clock divider parameters
+ *
+ * @drvdata:	Device to read from
+ *
+ * This function reads the clock divider parameters into driver structure.
+ *
+ * Following table gives the buffer index, register number and
+ * register name with bit fields
+ * 0 25 N1_HS[2:0]
+ * 6 31 NC1_LS[19:16]
+ * 7 32 NC1_LS[15:8]
+ * 8 33 NC1_LS[7:0]
+ * 9 34 NC2_LS[19:16]
+ * 10 35 NC2_LS[15:8]
+ * 11 36 NC2_LS[7:0]
+ * 15 40 N2_HS[2:0] N2_LS[19:16]
+ * 16 41 N2_LS[15:8]
+ * 17 42 N2_LS[7:0]
+ * 18 43 N31[18:16]
+ * 19 44 N31[15:8]
+ * 20 45 N31[7:0]
+ * 21 46 N32[18:16]
+ * 22 47 N32[15:8]
+ * 23 48 N32[7:0]
+ */
+static void si5324_read_parameters(struct si5324_driver_data *drvdata)
+{
+	u8 buf[SI5324_PARAM_LEN];
+
+	si5324_bulk_read(drvdata, SI5324_N1_HS, SI5324_N1_PARAM_LEN, &buf[0]);
+	si5324_bulk_read(drvdata, SI5324_NC1_LS_H, SI5324_NC_PARAM_LEN,
+			 &buf[6]);
+	si5324_bulk_read(drvdata, SI5324_N2_HS_LS_H, SI5324_N2_PARAM_LEN,
+			 &buf[15]);
+
+	drvdata->params.n1_hs = (buf[0] >> SI5324_N1_HS_VAL_SHIFT);
+	drvdata->params.n1_hs += 4;
+
+	drvdata->params.nc1_ls = ((buf[6] & SI5324_DIV_LS_MASK) <<
+				  SI5324_HSHIFT) | (buf[7] << SI5324_LSHIFT) |
+				  buf[8];
+	drvdata->params.nc1_ls += 1;
+	drvdata->params.nc2_ls = ((buf[9] & SI5324_DIV_LS_MASK) <<
+				  SI5324_HSHIFT) | (buf[10] << SI5324_LSHIFT) |
+				  buf[11];
+	drvdata->params.nc2_ls += 1;
+	drvdata->params.n2_ls = ((buf[15] & SI5324_DIV_LS_MASK) <<
+				 SI5324_HSHIFT) | (buf[16] << SI5324_LSHIFT) |
+				 buf[17];
+	drvdata->params.n2_ls += 1;
+	drvdata->params.n2_hs = buf[15] >> SI5324_N2_HS_LS_H_VAL_SHIFT;
+	drvdata->params.n2_hs += 4;
+	drvdata->params.n31 = ((buf[18] & SI5324_DIV_LS_MASK) <<
+				SI5324_HSHIFT) | (buf[19] << SI5324_LSHIFT) |
+				buf[20];
+	drvdata->params.n31 += 1;
+	drvdata->params.n32 = ((buf[21] & SI5324_DIV_LS_MASK) <<
+				SI5324_HSHIFT) | (buf[22] << SI5324_LSHIFT) |
+				buf[23];
+	drvdata->params.n32 += 1;
+	drvdata->params.valid = 1;
+}
+
+static bool si5324_regmap_is_volatile(struct device *dev, unsigned int reg)
+{
+	return true;
+}
+
+/**
+ * si5324_regmap_is_readable - Checks the register is readable or not
+ *
+ * @dev:	Registered device
+ * @reg:	Register offset
+ *
+ * Checks the register is readable or not.
+ *
+ * Return:	True if the register is reabdle, False if it is not readable.
+ */
+static bool si5324_regmap_is_readable(struct device *dev, unsigned int reg)
+{
+	if ((reg > SI5324_POWERDOWN && reg < SI5324_FOS_LOCKT) ||
+	    (reg > SI5324_N1_HS && reg < SI5324_NC1_LS_H) ||
+	    (reg > SI5324_NC2_LS_L && reg < SI5324_N2_HS_LS_H) ||
+	    (reg > SI5324_N32_CLKIN_L && reg < SI5324_FOS_CLKIN_RATE) ||
+	    (reg > SI5324_FOS_CLKIN_RATE && reg < SI5324_PLL_ACTV_CLK) ||
+	    reg > SI5324_SKEW2)
+		return false;
+
+	return true;
+}
+
+/**
+ * si5324_regmap_is_writable - Checks the register is writable or not
+ *
+ * @dev:	Registered device
+ * @reg:	Register offset
+ *
+ * Checks the register is writable or not.
+ *
+ * Return:	True if the register is writeable, False if it's not writeable.
+ */
+static bool si5324_regmap_is_writeable(struct device *dev, unsigned int reg)
+{
+	if ((reg > SI5324_POWERDOWN && reg < SI5324_FOS_LOCKT) ||
+	    (reg > SI5324_N1_HS && reg < SI5324_NC1_LS_H) ||
+	    (reg > SI5324_NC2_LS_L && reg < SI5324_N2_HS_LS_H) ||
+	    (reg > SI5324_N32_CLKIN_L && reg < SI5324_FOS_CLKIN_RATE) ||
+	    (reg > SI5324_FOS_CLKIN_RATE && reg < SI5324_PLL_ACTV_CLK) ||
+	    reg > SI5324_SKEW2 ||
+	    (reg >= SI5324_PLL_ACTV_CLK && reg <= SI5324_CLKIN_LOL_STATUS) ||
+	    (reg >= SI5324_PARTNO_H && reg <= SI5324_PARTNO_L))
+		return false;
+
+	return true;
+}
+
+static const struct regmap_config si5324_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.cache_type = REGCACHE_RBTREE,
+	.max_register = 144,
+	.writeable_reg = si5324_regmap_is_writeable,
+	.readable_reg = si5324_regmap_is_readable,
+	.volatile_reg = si5324_regmap_is_volatile,
+};
+
+static int si5324_xtal_prepare(struct clk_hw *hw)
+{
+	return 0;
+}
+
+static void si5324_xtal_unprepare(struct clk_hw *hw)
+{
+}
+
+static const struct clk_ops si5324_xtal_ops = {
+	.prepare = si5324_xtal_prepare,
+	.unprepare = si5324_xtal_unprepare,
+};
+
+/**
+ * si5324_clkin_prepare - Prepare the clkin
+ *
+ * @hw:		Handle between common and hardware-specific interfaces
+ *
+ * This function enables the particular clk
+ *
+ * Return:	Zero on success, a negative error number on failure.
+ */
+static int si5324_clkin_prepare(struct clk_hw *hw)
+{
+	int ret = 0;
+	struct si5324_driver_data *drvdata;
+	struct si5324_hw_data *hwdata =
+		container_of(hw, struct si5324_hw_data, hw);
+
+	if (hwdata->num == SI5324_CLKIN1) {
+		drvdata = container_of(hw, struct si5324_driver_data, clkin1);
+		ret = si5324_set_bits(drvdata, SI5324_CONTROL,
+				      SI5324_CONTROL_FREE_RUN, 0);
+		ret = si5324_set_bits(drvdata, SI5324_POWERDOWN, SI5324_PD_CK1 |
+				      SI5324_PD_CK2, SI5324_PD_CK2);
+	} else if (hwdata->num == SI5324_CLKIN2) {
+		drvdata = container_of(hw, struct si5324_driver_data, clkin2);
+		ret = si5324_set_bits(drvdata, SI5324_CONTROL,
+				      SI5324_CONTROL_FREE_RUN, 0);
+		ret = si5324_set_bits(drvdata, SI5324_POWERDOWN, SI5324_PD_CK1 |
+				      SI5324_PD_CK2, SI5324_PD_CK1);
+	}
+
+	return ret;
+}
+
+/**
+ * si5324_clkin_unprepare - Unprepare the clkin
+ *
+ * @hw:		Clock hardware
+ *
+ * This function enables the particular clk.
+ */
+static void si5324_clkin_unprepare(struct clk_hw *hw)
+{
+	struct si5324_driver_data *drvdata;
+	struct si5324_hw_data *hwdata =
+		container_of(hw, struct si5324_hw_data, hw);
+
+	if (hwdata->num == SI5324_CLKIN1) {
+		drvdata = container_of(hw, struct si5324_driver_data, clkin1);
+		si5324_set_bits(drvdata, SI5324_POWERDOWN,
+				SI5324_PD_CK1 | SI5324_PD_CK2, SI5324_PD_CK1);
+	} else if (hwdata->num == SI5324_CLKIN2) {
+		drvdata = container_of(hw, struct si5324_driver_data, clkin2);
+		si5324_set_bits(drvdata, SI5324_POWERDOWN,
+				SI5324_PD_CK1 | SI5324_PD_CK2, SI5324_PD_CK1);
+	}
+}
+
+static unsigned long si5324_clkin_recalc_rate(struct clk_hw *hw,
+					      unsigned long parent_rate)
+{
+	return 0;
+}
+
+static const struct clk_ops si5324_clkin_ops = {
+	.prepare = si5324_clkin_prepare,
+	.unprepare = si5324_clkin_unprepare,
+	.recalc_rate = si5324_clkin_recalc_rate,
+};
+
+static int si5324_pll_reparent(struct si5324_driver_data *drvdata,
+			       int num, enum si5324_pll_src parent)
+{
+	if (parent == SI5324_PLL_SRC_XTAL) {
+		si5324_set_bits(drvdata, SI5324_CONTROL,
+				SI5324_CONTROL_FREE_RUN,
+				SI5324_CONTROL_FREE_RUN);
+		si5324_set_bits(drvdata, SI5324_POWERDOWN,
+				SI5324_PD_CK1 | SI5324_PD_CK2, SI5324_PD_CK1);
+		si5324_set_bits(drvdata, SI5324_CKSEL,
+				SI5324_CK_SEL << SI5324_CKSEL_SHIFT,
+				1 << SI5324_CKSEL_SHIFT);
+	} else if (parent == SI5324_PLL_SRC_CLKIN1) {
+		si5324_set_bits(drvdata, SI5324_CONTROL,
+				SI5324_CONTROL_FREE_RUN, 0);
+		si5324_set_bits(drvdata, SI5324_POWERDOWN,
+				SI5324_PD_CK1 | SI5324_PD_CK2, SI5324_PD_CK2);
+		si5324_set_bits(drvdata, SI5324_CKSEL,
+				SI5324_CK_SEL << SI5324_CKSEL_SHIFT, 0);
+	} else if (parent == SI5324_PLL_SRC_CLKIN2) {
+		si5324_set_bits(drvdata, SI5324_CONTROL,
+				SI5324_CONTROL_FREE_RUN, 0);
+		si5324_set_bits(drvdata, SI5324_POWERDOWN,
+				SI5324_PD_CK1 | SI5324_PD_CK2, SI5324_PD_CK1);
+		si5324_set_bits(drvdata, SI5324_CKSEL,
+				SI5324_CK_SEL << SI5324_CKSEL_SHIFT,
+				1 << SI5324_CKSEL_SHIFT);
+	}
+
+	return 0;
+}
+
+static unsigned char si5324_pll_get_parent(struct clk_hw *hw)
+{
+	return 0;
+}
+
+/**
+ * si5324_pll_set_parent - Set parent of clock
+ *
+ * @hw:		Handle between common and hardware-specific interfaces
+ * @index:	Parent index
+ *
+ * This function sets the paraent of clock.
+ *
+ * Return:	0 on success, negative error number on failure
+ */
+static int si5324_pll_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct si5324_hw_data *hwdata =
+		container_of(hw, struct si5324_hw_data, hw);
+	enum si5324_pll_src parent;
+
+	if (index == SI5324_SRC_XTAL)
+		parent = SI5324_PLL_SRC_XTAL;
+	else if (index == SI5324_SRC_CLKIN1)
+		parent = SI5324_PLL_SRC_CLKIN1;
+	else if (index == SI5324_SRC_CLKIN2)
+		parent = SI5324_PLL_SRC_CLKIN2;
+	else
+		return -EINVAL;
+
+	return si5324_pll_reparent(hwdata->drvdata, hwdata->num, parent);
+}
+
+/**
+ * si5324_pll_recalc_rate - Recalculate clock frequency
+ *
+ * @hw:			Handle between common and hardware-specific interfaces
+ * @parent_rate:	Clock frequency of parent clock
+ *
+ * This function recalculate clock frequency.
+ *
+ * Return:		Current clock frequency
+ */
+static unsigned long si5324_pll_recalc_rate(struct clk_hw *hw,
+					    unsigned long parent_rate)
+{
+	unsigned long rate;
+	struct si5324_hw_data *hwdata =
+		container_of(hw, struct si5324_hw_data, hw);
+
+	if (!hwdata->drvdata->params.valid)
+		si5324_read_parameters(hwdata->drvdata);
+	WARN_ON(!hwdata->drvdata->params.valid);
+
+	rate = parent_rate * hwdata->drvdata->params.n2_ls *
+		hwdata->drvdata->params.n2_hs;
+
+	dev_dbg(&hwdata->drvdata->client->dev,
+		"%s - %s: n2_ls = %u, n2_hs = %u, parent_rate = %lu, rate = %lu\n",
+		__func__, clk_hw_get_name(hw),
+		hwdata->drvdata->params.n2_ls, hwdata->drvdata->params.n2_hs,
+		parent_rate, (unsigned long)rate);
+
+	return rate;
+}
+
+static long si5324_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+				  unsigned long *parent_rate)
+{
+	return rate;
+}
+
+static int si5324_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+			       unsigned long parent_rate)
+{
+	return 0;
+}
+
+static const struct clk_ops si5324_pll_ops = {
+	.set_parent = si5324_pll_set_parent,
+	.get_parent = si5324_pll_get_parent,
+	.recalc_rate = si5324_pll_recalc_rate,
+	.round_rate = si5324_pll_round_rate,
+	.set_rate = si5324_pll_set_rate,
+};
+
+static int si5324_clkout_set_drive_strength(
+	struct si5324_driver_data *drvdata, int num,
+	enum si5324_drive_strength drive)
+{
+	return 0;
+}
+
+static int si5324_clkout_prepare(struct clk_hw *hw)
+{
+	return 0;
+}
+
+static void si5324_clkout_unprepare(struct clk_hw *hw)
+{
+}
+
+static unsigned long si5324_clkout_recalc_rate(struct clk_hw *hw,
+					       unsigned long parent_rate)
+{
+	unsigned long rate;
+
+	struct si5324_hw_data *hwdata =
+		container_of(hw, struct si5324_hw_data, hw);
+
+	rate = hwdata->drvdata->rate_clkout0;
+
+	return rate;
+}
+
+/**
+ * si5324_clkout_round_rate - selects the closest value to requested one.
+ *
+ * @hw:			Handle between common and hardware-specific interfaces
+ * @rate:		Clock rate
+ * @parent_rate:	Parent clock rate
+ *
+ * This function selects the rate closest to the requested one.
+ *
+ * Return:		Clock rate on success, negative error number on failure
+ */
+static long si5324_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
+				     unsigned long *parent_rate)
+{
+	u32 ncn_ls, n2_ls, n3n, actual_rate;
+	u8 n1_hs, n2_hs, bwsel;
+	int ret;
+
+	ret = si5324_calcfreqsettings(SI5324_REF_CLOCK, rate, &actual_rate,
+				      &n1_hs, &ncn_ls, &n2_hs, &n2_ls, &n3n,
+				      &bwsel);
+	if (ret < 0)
+		return ret;
+
+	return actual_rate;
+}
+
+static int si5324_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
+				  unsigned long parent_rate)
+{
+	struct si5324_hw_data *hwdata =
+		container_of(hw, struct si5324_hw_data, hw);
+
+	u32 ncn_ls, n2_ls, n3n, actual_rate;
+	u8 n1_hs, n2_hs, bwsel, buf[SI5324_OUT_REGS * 2];
+	int i, ret, rc;
+
+	ret = si5324_calcfreqsettings(SI5324_REF_CLOCK, rate, &actual_rate,
+				      &n1_hs, &ncn_ls, &n2_hs, &n2_ls, &n3n,
+				      &bwsel);
+	if (ret < 0)
+		return ret;
+
+	hwdata->drvdata->rate_clkout0 = rate;
+	i = 0;
+
+	/* Enable Free running mode */
+	buf[i] = SI5324_CONTROL;
+	buf[i + 1] = SI5324_FREE_RUN_EN;
+	i += 2;
+
+	/* Loop bandwidth */
+	buf[i] = SI5324_BWSEL;
+	buf[i + 1] = (bwsel << SI5324_BWSEL_SHIFT) | SI5324_BWSEL_DEF_VAL;
+	i += 2;
+
+	/* Enable reference clock 2 in free running mode */
+	buf[i] = SI5324_POWERDOWN;
+	/* Enable input clock 2, Disable input clock 1 */
+	buf[i + 1] = SI5324_PD_CK1_DIS;
+	i += 2;
+
+	/* N1_HS */
+	buf[i] = SI5324_N1_HS;
+	buf[i + 1] = n1_hs << SI5324_N1_HS_VAL_SHIFT;
+	i += 2;
+
+	/* NC1_LS */
+	buf[i] = SI5324_NC1_LS_H;
+	buf[i + 1] = (u8)((ncn_ls & 0x000F0000) >> 16);
+	buf[i + 2] = SI5324_NC1_LS_M;
+	buf[i + 3] = (u8)((ncn_ls & 0x0000FF00) >> 8);
+	buf[i + 4] = SI5324_NC1_LS_L;
+	buf[i + 5] = (u8)(ncn_ls & 0x000000FF);
+	i += 6;
+
+	/* N2_HS and N2_LS */
+	buf[i] = SI5324_N2_HS_LS_H;
+	buf[i + 1] = (n2_hs << SI5324_N2_HS_LS_H_VAL_SHIFT);
+	buf[i + 1] |= (u8)((n2_ls & 0x000F0000) >> 16);
+	buf[i + 2] = SI5324_N2_LS_H;
+	buf[i + 3] = (u8)((n2_ls & 0x0000FF00) >> 8);
+	buf[i + 4] = SI5324_N2_LS_L;
+	buf[i + 5] = (u8)(n2_ls & 0x000000FF);
+	i += 6;
+
+	/* N32 (CLKIN2 or XTAL in FREERUNNING mode) */
+	buf[i] = SI5324_N32_CLKIN_H;
+	buf[i + 2] = SI5324_N32_CLKIN_M;
+	buf[i + 4] = SI5324_N32_CLKIN_L;
+	buf[i + 1] = (u8)((n3n & 0x00070000) >> 16);
+	buf[i + 3] = (u8)((n3n & 0x0000FF00) >> 8);
+	buf[i + 5] = (u8)(n3n & 0x000000FF);
+	i += 6;
+
+	/* Start calibration */
+	buf[i] = SI5324_RESET_CALIB;
+	buf[i + 1] = SI5324_CALIB_EN;
+	i += 2;
+
+	hwdata->drvdata->params.valid = 0;
+	rc = si5324_bulk_scatter_write(hwdata->drvdata, SI5324_OUT_REGS, buf);
+
+	return rc;
+}
+
+static const struct clk_ops si5324_clkout_ops = {
+	.prepare = si5324_clkout_prepare,
+	.unprepare = si5324_clkout_unprepare,
+	.recalc_rate = si5324_clkout_recalc_rate,
+	.round_rate = si5324_clkout_round_rate,
+	.set_rate = si5324_clkout_set_rate,
+};
+
+static const struct of_device_id si5324_dt_ids[] = {
+	{ .compatible = "silabs,si5319" },
+	{ .compatible = "silabs,si5324" },
+	{ .compatible = "silabs,si5328" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, si5324_dt_ids);
+
+static int si5324_dt_parse(struct i2c_client *client)
+{
+	struct device_node *child, *np = client->dev.of_node;
+	struct si5324_platform_data *pdata;
+	struct property *prop;
+	const __be32 *p;
+	int num = 0;
+	u32 val;
+
+	if (!np)
+		return 0;
+
+	pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+
+	/*
+	 * property silabs,pll-source : <num src>, [<..>]
+	 * allow to selectively set pll source
+	 */
+	of_property_for_each_u32(np, "silabs,pll-source", prop, p, num) {
+		if (num >= 1) {
+			dev_err(&client->dev,
+				"invalid pll %d on pll-source prop\n", num);
+			return -EINVAL;
+		}
+		p = of_prop_next_u32(prop, p, &val);
+		if (!p) {
+			dev_err(&client->dev,
+				"missing pll-source for pll %d\n", num);
+			return -EINVAL;
+		}
+
+		switch (val) {
+		case 0:
+			dev_dbg(&client->dev, "using xtal as parent for pll\n");
+			pdata->pll_src = SI5324_PLL_SRC_XTAL;
+			break;
+		case 1:
+			dev_dbg(&client->dev,
+				"using clkin1 as parent for pll\n");
+			pdata->pll_src = SI5324_PLL_SRC_CLKIN1;
+			break;
+		case 2:
+			dev_dbg(&client->dev,
+				"using clkin2 as parent for pll\n");
+			pdata->pll_src = SI5324_PLL_SRC_CLKIN2;
+			break;
+		default:
+			dev_err(&client->dev,
+				"invalid parent %d for pll %d\n", val, num);
+			return -EINVAL;
+		}
+	}
+	/* per clkout properties */
+	for_each_child_of_node(np, child) {
+		if (of_property_read_u32(child, "reg", &num)) {
+			dev_err(&client->dev, "missing reg property of %s\n",
+				child->name);
+			goto put_child;
+		}
+
+		if (num >= 2) {
+			dev_err(&client->dev, "invalid clkout %d\n", num);
+			goto put_child;
+		}
+
+		if (!of_property_read_u32(child, "silabs,drive-strength",
+					  &val)) {
+			switch (val) {
+			case SI5324_DRIVE_2MA:
+			case SI5324_DRIVE_4MA:
+			case SI5324_DRIVE_6MA:
+			case SI5324_DRIVE_8MA:
+				pdata->clkout[num].drive = val;
+				break;
+			default:
+				dev_err(&client->dev,
+					"invalid drive strength %d for clkout %d\n",
+					val, num);
+				goto put_child;
+			}
+		}
+
+		if (!of_property_read_u32(child, "clock-frequency", &val)) {
+			dev_dbg(&client->dev, "clock-frequency = %u\n", val);
+			pdata->clkout[num].rate = val;
+		} else {
+			dev_err(&client->dev,
+				"missing clock-frequency property of %s\n",
+				child->name);
+			goto put_child;
+		}
+	}
+	client->dev.platform_data = pdata;
+
+	return 0;
+put_child:
+	of_node_put(child);
+	return -EINVAL;
+}
+
+static u8 instance;
+
+static int si5324_i2c_probe(struct i2c_client *client,
+			    const struct i2c_device_id *id)
+{
+	struct si5324_platform_data *pdata;
+	struct si5324_driver_data *drvdata;
+	struct clk_init_data init;
+	struct clk *clk;
+	const char *parent_names[3];
+	char inst_names[NUM_NAME_IDS][MAX_NAME_LEN];
+	u8 num_parents, num_clocks;
+	int ret, n;
+	enum si53xx_variant variant = id->driver_data;
+
+	if (variant > si5328) {
+		dev_err(&client->dev, "si53xx device not present\n");
+		return -ENODEV;
+	}
+
+	dev_info(&client->dev, "%s probed\n", si53xx_variant_name[variant]);
+	ret = si5324_dt_parse(client);
+	if (ret)
+		return ret;
+
+	pdata = client->dev.platform_data;
+	if (!pdata)
+		return -EINVAL;
+
+	drvdata = devm_kzalloc(&client->dev, sizeof(*drvdata), GFP_KERNEL);
+	if (!drvdata)
+		return -ENOMEM;
+
+	drvdata->client = client;
+	drvdata->pxtal = devm_clk_get(&client->dev, "xtal");
+	drvdata->pclkin1 = devm_clk_get(&client->dev, "clkin1");
+	drvdata->pclkin2 = devm_clk_get(&client->dev, "clkin2");
+
+	if (PTR_ERR(drvdata->pxtal) == -EPROBE_DEFER ||
+	    PTR_ERR(drvdata->pclkin1) == -EPROBE_DEFER ||
+	    PTR_ERR(drvdata->pclkin2) == -EPROBE_DEFER)
+		return -EPROBE_DEFER;
+
+	drvdata->regmap = devm_regmap_init_i2c(client, &si5324_regmap_config);
+	if (IS_ERR(drvdata->regmap)) {
+		dev_err(&client->dev, "failed to allocate register map\n");
+		return PTR_ERR(drvdata->regmap);
+	}
+
+	i2c_set_clientdata(client, drvdata);
+	si5324_initialize(drvdata);
+
+	/* setup input clock configuration */
+	ret = si5324_pll_reparent(drvdata, 0, pdata->pll_src);
+	if (ret) {
+		dev_err(&client->dev,
+			"failed to reparent pll to %d\n",
+			pdata->pll_src);
+		return ret;
+	}
+
+	for (n = 0; n < SI5324_MAX_CLKOUTS; n++) {
+		ret = si5324_clkout_set_drive_strength(drvdata, n,
+						       pdata->clkout[n].drive);
+		if (ret) {
+			dev_err(&client->dev,
+				"failed set drive strength of clkout%d to %d\n",
+				n, pdata->clkout[n].drive);
+			return ret;
+		}
+	}
+
+	if (!IS_ERR(drvdata->pxtal))
+		clk_prepare_enable(drvdata->pxtal);
+	if (!IS_ERR(drvdata->pclkin1))
+		clk_prepare_enable(drvdata->pclkin1);
+	if (!IS_ERR(drvdata->pclkin2))
+		clk_prepare_enable(drvdata->pclkin2);
+
+	/* create instance names by appending instance id */
+	for (n = 0; n < SI5324_SRC_CLKS; n++) {
+		sprintf(inst_names[n], "%s_%d", si5324_input_names[n],
+			instance);
+	}
+	sprintf(inst_names[3], "%s_%d", si5324_pll_name, instance);
+	for (n = 0; n < SI5324_MAX_CLKOUTS; n++) {
+		sprintf(inst_names[n + 4], "%s_%d", si5324_clkout_names[n],
+			instance);
+	}
+
+	/* register xtal input clock gate */
+	memset(&init, 0, sizeof(init));
+	init.name = inst_names[0];
+	init.ops = &si5324_xtal_ops;
+	init.flags = 0;
+
+	if (!IS_ERR(drvdata->pxtal)) {
+		drvdata->pxtal_name = __clk_get_name(drvdata->pxtal);
+		init.parent_names = &drvdata->pxtal_name;
+		init.num_parents = 1;
+	}
+	drvdata->xtal.init = &init;
+
+	clk = devm_clk_register(&client->dev, &drvdata->xtal);
+	if (IS_ERR(clk)) {
+		dev_err(&client->dev, "unable to register %s\n", init.name);
+		ret = PTR_ERR(clk);
+		goto err_clk;
+	}
+
+	/* register clkin1 input clock gate */
+	memset(&init, 0, sizeof(init));
+	init.name = inst_names[1];
+	init.ops = &si5324_clkin_ops;
+	if (!IS_ERR(drvdata->pclkin1)) {
+		drvdata->pclkin1_name = __clk_get_name(drvdata->pclkin1);
+		init.parent_names = &drvdata->pclkin1_name;
+		init.num_parents = 1;
+	}
+
+	drvdata->clkin1.init = &init;
+	clk = devm_clk_register(&client->dev, &drvdata->clkin1);
+	if (IS_ERR(clk)) {
+		dev_err(&client->dev, "unable to register %s\n",
+			init.name);
+		ret = PTR_ERR(clk);
+		goto err_clk;
+	}
+
+	/* register clkin2 input clock gate */
+	memset(&init, 0, sizeof(init));
+	init.name = inst_names[2];
+	init.ops = &si5324_clkin_ops;
+	if (!IS_ERR(drvdata->pclkin2)) {
+		drvdata->pclkin2_name = __clk_get_name(drvdata->pclkin2);
+		init.parent_names = &drvdata->pclkin2_name;
+		init.num_parents = 1;
+	}
+
+	drvdata->clkin2.init = &init;
+	clk = devm_clk_register(&client->dev, &drvdata->clkin2);
+	if (IS_ERR(clk)) {
+		dev_err(&client->dev, "unable to register %s\n",
+			init.name);
+		ret = PTR_ERR(clk);
+		goto err_clk;
+	}
+
+	/* Si5324 allows to mux xtal or clkin1 or clkin2 to PLL input */
+	num_parents = SI5324_SRC_CLKS;
+	parent_names[0] = inst_names[0];
+	parent_names[1] = inst_names[1];
+	parent_names[2] = inst_names[2];
+
+	/* register PLL */
+	drvdata->pll.drvdata = drvdata;
+	drvdata->pll.hw.init = &init;
+	memset(&init, 0, sizeof(init));
+	init.name = inst_names[3];
+	init.ops = &si5324_pll_ops;
+	init.flags = 0;
+	init.flags |= CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE;
+	init.parent_names = parent_names;
+	init.num_parents = num_parents;
+
+	clk = devm_clk_register(&client->dev, &drvdata->pll.hw);
+	if (IS_ERR(clk)) {
+		dev_err(&client->dev, "unable to register %s\n", init.name);
+		ret = PTR_ERR(clk);
+		goto err_clk;
+	}
+
+	/* register clk out divider */
+	num_clocks = 2;
+	num_parents = 1;
+	parent_names[0] = inst_names[3];
+
+	drvdata->clkout = devm_kzalloc(&client->dev, num_clocks *
+				       sizeof(*drvdata->clkout), GFP_KERNEL);
+
+	drvdata->onecell.clk_num = num_clocks;
+	drvdata->onecell.clks = devm_kzalloc(&client->dev,
+					     num_clocks *
+					     sizeof(*drvdata->onecell.clks),
+					     GFP_KERNEL);
+
+	if (WARN_ON(!drvdata->clkout) || !drvdata->onecell.clks) {
+		ret = -ENOMEM;
+		goto err_clk;
+	}
+
+	for (n = 0; n < num_clocks; n++) {
+		drvdata->clkout[n].num = n;
+		drvdata->clkout[n].drvdata = drvdata;
+		drvdata->clkout[n].hw.init = &init;
+		memset(&init, 0, sizeof(init));
+		init.name = inst_names[4 + n];
+		init.ops = &si5324_clkout_ops;
+		init.flags = 0;
+		init.flags |= CLK_SET_RATE_PARENT;
+		init.parent_names = parent_names;
+		init.num_parents = num_parents;
+
+		clk = devm_clk_register(&client->dev, &drvdata->clkout[n].hw);
+		if (IS_ERR(clk)) {
+			dev_err(&client->dev, "unable to register %s\n",
+				init.name);
+			ret = PTR_ERR(clk);
+			goto err_clk;
+		}
+		/* refer to output clock in onecell */
+		drvdata->onecell.clks[n] = clk;
+
+		/* set initial clkout rate */
+		if (pdata->clkout[n].rate != 0) {
+			int ret;
+
+			ret = clk_set_rate(clk, pdata->clkout[n].rate);
+			if (ret != 0) {
+				dev_err(&client->dev, "Cannot set rate : %d\n",
+					ret);
+			}
+		}
+	}
+
+	ret = of_clk_add_provider(client->dev.of_node, of_clk_src_onecell_get,
+				  &drvdata->onecell);
+	if (ret) {
+		dev_err(&client->dev, "unable to add clk provider\n");
+		goto err_clk;
+	}
+
+	dev_info(&client->dev, "%s probe successful\n",
+		 si53xx_variant_name[variant]);
+	instance++;
+	return 0;
+
+err_clk:
+	if (!IS_ERR(drvdata->pxtal))
+		clk_disable_unprepare(drvdata->pxtal);
+	if (!IS_ERR(drvdata->pclkin1))
+		clk_disable_unprepare(drvdata->pclkin1);
+	if (!IS_ERR(drvdata->pclkin2))
+		clk_disable_unprepare(drvdata->pclkin2);
+
+	return ret;
+}
+
+static int si5324_i2c_remove(struct i2c_client *client)
+{
+	of_clk_del_provider(client->dev.of_node);
+	return 0;
+}
+
+static const struct i2c_device_id si5324_i2c_ids[] = {
+	{ "si5319", si5319 },
+	{ "si5324", si5324 },
+	{ "si5328", si5328 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, si5324_i2c_ids);
+
+static struct i2c_driver si5324_driver = {
+	.driver = {
+		.name = "si5324",
+		.of_match_table = of_match_ptr(si5324_dt_ids),
+	},
+	.probe = si5324_i2c_probe,
+	.remove = si5324_i2c_remove,
+	.id_table = si5324_i2c_ids,
+};
+module_i2c_driver(si5324_driver);
+
+MODULE_AUTHOR("Venkateshwar Rao G <vgannava@xilinx.com>");
+MODULE_DESCRIPTION("Silicon Labs 5319/5324/5328 clock driver");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/clk-si5324.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/clk-si5324.h
@@ -0,0 +1,140 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Si5324 clock driver
+ *
+ * Copyright (C) 2017-2018 Xilinx, Inc.
+ *
+ * Authors:	Leon Woestenberg <leon@sidebranch.com>
+ *		Venkateshwar Rao <vgannava@xilinx.com>
+ */
+
+#ifndef _CLK_SI5324_H_
+#define _CLK_SI5324_H_
+
+#define SI5324_BUS_BASE_ADDR		0x68
+
+#define SI5324_CONTROL			0
+#define SI5324_CONTROL_FREE_RUN		BIT(6)
+#define SI5324_FREE_RUN_EN		0x54
+
+#define SI5324_INCK_PRIOR		1
+#define SI5324_INCK_PRIOR_1_MASK	0xC
+#define SI5324_INCK_PRIOI_2_MASK	0x3
+
+#define SI5324_BWSEL			2
+#define SI5324_BWSEL_MASK		0xF0
+#define SI5324_BWSEL_SHIFT		4
+#define SI5324_BWSEL_DEF_VAL		2
+
+#define SI5324_CKSEL			3
+#define SI5324_CKSEL_SQL_ICAL		BIT(4)
+#define SI5324_CKSEL_SHIFT		6
+#define SI5324_CK_SEL			3
+
+#define SI3324_AUTOSEL			4
+#define SI5324_AUTOSEL_DEF		0x12
+
+#define SI5324_ICMOS			5
+#define SI5324_OUTPUT_SIGFMT		6
+#define SI5324_OUTPUT_SF1_DEFAULT	0xF
+#define SI5324_REFFRE_FOS		7
+#define SI5324_HLOG			8
+#define SI5324_AVG_HIST			9
+#define SI5324_DSBL_CLKOUT		10
+#define SI5324_DSBL_CLKOUT2		BIT(3)
+#define SI5324_POWERDOWN		11
+#define SI5324_PD_CK1			BIT(0)
+#define SI5324_PD_CK2			BIT(1)
+#define SI5324_PD_CK1_DIS		0x41
+#define SI5324_PD_CK2_DIS		0x42
+#define SI5324_FOS_LOCKT		19
+#define SI5324_FOS_DEFAULT		0x23
+#define SI5324_CK_ACTV_SEL		21
+#define SI5324_CK_DEFAULT		0xFC
+#define SI5324_CK_ACTV			BIT(1)
+#define SI5324_CK_SELPIN		BIT(1)
+#define SI5324_LOS_MSK			23
+#define SI5324_FOS_L0L_MASK		24
+
+/* output clock dividers */
+#define SI5324_N1_HS			25
+#define SI5324_N1_HS_VAL_SHIFT		5
+#define SI5324_HSHIFT			16
+#define SI5324_LSHIFT			8
+#define SI5324_NC1_LS_H			31
+#define SI5324_NC1_LS_M			32
+#define SI5324_NC1_LS_L			33
+#define SI5324_DIV_LS_MASK		0x0F
+#define SI5324_DIV_HS_MASK		0xF0
+#define SI5324_NC2_LS_H			34
+#define SI5324_NC2_LS_M			35
+#define SI5324_NC2_LS_L			36
+
+#define SI5324_N2_HS_LS_H		40
+#define SI5324_N2_HS_LS_H_VAL_SHIFT	5
+#define SI5324_N2_LS_H			41
+#define SI5324_N2_LS_L			42
+#define SI5324_N31_CLKIN_H		43
+#define SI5324_N31_CLKIN_M		44
+#define SI5324_N31_CLKIN_L		45
+#define SI5324_N32_CLKIN_H		46
+#define SI5324_N32_CLKIN_M		47
+#define SI5324_N32_CLKIN_L		48
+#define SI5324_FOS_CLKIN_RATE		55
+#define SI5324_PLL_ACTV_CLK		128
+#define SI5324_LOS_STATUS		129
+#define SI5324_CLKIN_LOL_STATUS		130
+#define SI5324_LOS_FLG			131
+#define SI5324_FOS_FLG			132
+#define SI5324_PARTNO_H			134
+#define SI5324_PARTNO_L			135
+
+#define SI5324_RESET_CALIB		136
+#define SI5324_RST_ALL			BIT(7)
+#define SI5324_CALIB_EN			BIT(6)
+
+#define SI5324_FASTLOCK			137
+#define SI5324_FASTLOCK_EN		BIT(0)
+#define SI5324_LOS1_LOS2_EN		138
+#define SI5324_SKEW1			142
+#define SI5324_SKEW2			143
+
+/* selects 2kHz to 710 MHz */
+#define SI5324_CLKIN_MIN_FREQ		2000
+#define SI5324_CLKIN_MAX_FREQ		(710 * 1000 * 1000)
+
+/* generates 2kHz to 945 MHz */
+#define SI5324_CLKOUT_MIN_FREQ		2000
+#define SI5324_CLKOUT_MAX_FREQ		(945 * 1000 * 1000)
+
+/* The following constants define the limits of the divider settings. */
+#define SI5324_N1_HS_MIN		6
+#define SI5324_N1_HS_MAX		11
+#define SI5324_NC_LS_MIN		1
+#define SI5324_NC_LS_MAX		0x100000
+#define SI5324_N2_HS_MIN		4
+#define SI5324_N2_HS_MAX		11
+#define SI5324_N2_LS_MIN		2
+#define SI5324_N2_LS_MAX		0x100000
+#define SI5324_N3_MIN			1
+#define SI5324_N3_MAX			0x080000
+
+#define SI5324_SRC_XTAL			0
+#define SI5324_SRC_CLKIN1		1
+#define SI5324_SRC_CLKIN2		2
+#define SI5324_SRC_CLKS			3
+
+#define SI5324_CLKIN1			0
+#define SI5324_CLKIN2			1
+#define SI5324_MAX_CLKOUTS		2
+#define NUM_NAME_IDS			6 /* 3 clkin, 1 pll, 2 clkout */
+#define MAX_NAME_LEN			11
+#define SI5324_PARAM_LEN		24
+#define SI5324_NC_PARAM_LEN		6
+#define SI5324_OUT_REGS			14
+#define SI5324_N1_PARAM_LEN		1
+#define SI5324_N2_PARAM_LEN		9
+#define SI5324_REF_CLOCK		114285000UL
+#define SI5324_RESET_DELAY_MS		20
+
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/clk-si5341.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/clk-si5341.c
@@ -16,6 +16,8 @@
 #include <linux/slab.h>
 #include <asm/unaligned.h>
 
+#define SI5341_NUM_INPUTS 4
+
 #define SI5341_MAX_NUM_OUTPUTS 10
 #define SI5340_MAX_NUM_OUTPUTS 4
 
@@ -56,8 +58,8 @@
 	struct i2c_client *i2c_client;
 	struct clk_si5341_synth synth[SI5341_NUM_SYNTH];
 	struct clk_si5341_output clk[SI5341_MAX_NUM_OUTPUTS];
-	struct clk *pxtal;
-	const char *pxtal_name;
+	struct clk *input_clk[SI5341_NUM_INPUTS];
+	const char *input_clk_name[SI5341_NUM_INPUTS];
 	const u16 *reg_output_offset;
 	const u16 *reg_rdiv_offset;
 	u64 freq_vco; /* 13500–14256 MHz */
@@ -78,10 +80,25 @@
 #define SI5341_DEVICE_REV	0x0005
 #define SI5341_STATUS		0x000C
 #define SI5341_SOFT_RST		0x001C
+#define SI5341_IN_SEL		0x0021
+#define SI5341_XAXB_CFG		0x090E
+#define SI5341_IN_EN		0x0949
+#define SI5341_INX_TO_PFD_EN	0x094A
+
+/* Input selection */
+#define SI5341_IN_SEL_MASK	0x06
+#define SI5341_IN_SEL_SHIFT	1
+#define SI5341_IN_SEL_REGCTRL	0x01
+#define SI5341_INX_TO_PFD_SHIFT	4
+
+/* XTAL config bits */
+#define SI5341_XAXB_CFG_EXTCLK_EN	BIT(0)
+#define SI5341_XAXB_CFG_PDNB		BIT(1)
 
 /* Input dividers (48-bit) */
 #define SI5341_IN_PDIV(x)	(0x0208 + ((x) * 10))
 #define SI5341_IN_PSET(x)	(0x020E + ((x) * 10))
+#define SI5341_PX_UPD		0x0230
 
 /* PLL configuration */
 #define SI5341_PLL_M_NUM	0x0235
@@ -120,6 +137,10 @@
 	u8 value;
 };
 
+static const char * const si5341_input_clock_names[] = {
+	"in0", "in1", "in2", "xtal"
+};
+
 /* Output configuration registers 0..9 are not quite logically organized */
 static const u16 si5341_reg_output_offset[] = {
 	0x0108,
@@ -304,6 +325,8 @@
 	{ 0x094A, 0x00 }, /* INx_TO_PFD_EN (disabled) */
 	{ 0x0A02, 0x00 }, /* Not in datasheet */
 	{ 0x0B44, 0x0F }, /* PDIV_ENB (datasheet does not mention what it is) */
+	{ 0x0B57, 0x10 }, /* VCO_RESET_CALCODE (not described in datasheet) */
+	{ 0x0B58, 0x05 }, /* VCO_RESET_CALCODE (not described in datasheet) */
 };
 
 /* Read and interpret a 44-bit followed by a 32-bit value in the regmap */
@@ -390,7 +413,112 @@
 	return (unsigned long)res;
 }
 
+static int si5341_clk_get_selected_input(struct clk_si5341 *data)
+{
+	int err;
+	u32 val;
+
+	err = regmap_read(data->regmap, SI5341_IN_SEL, &val);
+	if (err < 0)
+		return err;
+
+	return (val & SI5341_IN_SEL_MASK) >> SI5341_IN_SEL_SHIFT;
+}
+
+static u8 si5341_clk_get_parent(struct clk_hw *hw)
+{
+	struct clk_si5341 *data = to_clk_si5341(hw);
+	int res = si5341_clk_get_selected_input(data);
+
+	if (res < 0)
+		return 0; /* Apparently we cannot report errors */
+
+	return res;
+}
+
+static int si5341_clk_reparent(struct clk_si5341 *data, u8 index)
+{
+	int err;
+	u8 val;
+
+	val = (index << SI5341_IN_SEL_SHIFT) & SI5341_IN_SEL_MASK;
+	/* Enable register-based input selection */
+	val |= SI5341_IN_SEL_REGCTRL;
+
+	err = regmap_update_bits(data->regmap,
+		SI5341_IN_SEL, SI5341_IN_SEL_REGCTRL | SI5341_IN_SEL_MASK, val);
+	if (err < 0)
+		return err;
+
+	if (index < 3) {
+		/* Enable input buffer for selected input */
+		err = regmap_update_bits(data->regmap,
+				SI5341_IN_EN, 0x07, BIT(index));
+		if (err < 0)
+			return err;
+
+		/* Enables the input to phase detector */
+		err = regmap_update_bits(data->regmap, SI5341_INX_TO_PFD_EN,
+				0x7 << SI5341_INX_TO_PFD_SHIFT,
+				BIT(index + SI5341_INX_TO_PFD_SHIFT));
+		if (err < 0)
+			return err;
+
+		/* Power down XTAL oscillator and buffer */
+		err = regmap_update_bits(data->regmap, SI5341_XAXB_CFG,
+				SI5341_XAXB_CFG_PDNB, 0);
+		if (err < 0)
+			return err;
+
+		/*
+		 * Set the P divider to "1". There's no explanation in the
+		 * datasheet of these registers, but the clockbuilder software
+		 * programs a "1" when the input is being used.
+		 */
+		err = regmap_write(data->regmap, SI5341_IN_PDIV(index), 1);
+		if (err < 0)
+			return err;
+
+		err = regmap_write(data->regmap, SI5341_IN_PSET(index), 1);
+		if (err < 0)
+			return err;
+
+		/* Set update PDIV bit */
+		err = regmap_write(data->regmap, SI5341_PX_UPD, BIT(index));
+		if (err < 0)
+			return err;
+	} else {
+		/* Disable all input buffers */
+		err = regmap_update_bits(data->regmap, SI5341_IN_EN, 0x07, 0);
+		if (err < 0)
+			return err;
+
+		/* Disable input to phase detector */
+		err = regmap_update_bits(data->regmap, SI5341_INX_TO_PFD_EN,
+				0x7 << SI5341_INX_TO_PFD_SHIFT, 0);
+		if (err < 0)
+			return err;
+
+		/* Power up XTAL oscillator and buffer */
+		err = regmap_update_bits(data->regmap, SI5341_XAXB_CFG,
+				SI5341_XAXB_CFG_PDNB, SI5341_XAXB_CFG_PDNB);
+		if (err < 0)
+			return err;
+	}
+
+	return 0;
+}
+
+static int si5341_clk_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct clk_si5341 *data = to_clk_si5341(hw);
+
+	return si5341_clk_reparent(data, index);
+}
+
 static const struct clk_ops si5341_clk_ops = {
+	.set_parent = si5341_clk_set_parent,
+	.get_parent = si5341_clk_get_parent,
 	.recalc_rate = si5341_clk_recalc_rate,
 };
 
@@ -482,6 +610,9 @@
 			SI5341_SYNTH_N_NUM(synth->index), &n_num, &n_den);
 	if (err < 0)
 		return err;
+	/* Check for bogus/uninitialized settings */
+	if (!n_num || !n_den)
+		return 0;
 
 	/*
 	 * n_num and n_den are shifted left as much as possible, so to prevent
@@ -633,6 +764,15 @@
 	u32 r_divider;
 	u8 r[3];
 
+	err = regmap_read(output->data->regmap,
+			SI5341_OUT_CONFIG(output), &val);
+	if (err < 0)
+		return err;
+
+	/* If SI5341_OUT_CFG_RDIV_FORCE2 is set, r_divider is 2 */
+	if (val & SI5341_OUT_CFG_RDIV_FORCE2)
+		return parent_rate / 2;
+
 	err = regmap_bulk_read(output->data->regmap,
 			SI5341_OUT_R_REG(output), r, 3);
 	if (err < 0)
@@ -649,13 +789,6 @@
 	r_divider += 1;
 	r_divider <<= 1;
 
-	err = regmap_read(output->data->regmap,
-			SI5341_OUT_CONFIG(output), &val);
-	if (err < 0)
-		return err;
-
-	if (val & SI5341_OUT_CFG_RDIV_FORCE2)
-		r_divider = 2;
 
 	return parent_rate / r_divider;
 }
@@ -665,6 +798,9 @@
 {
 	unsigned long r;
 
+	if (!rate)
+		return 0;
+
 	r = *parent_rate >> 1;
 
 	/* If rate is an even divisor, no changes to parent required */
@@ -693,11 +829,16 @@
 		unsigned long parent_rate)
 {
 	struct clk_si5341_output *output = to_clk_si5341_output(hw);
-	/* Frequency divider is (r_div + 1) * 2 */
-	u32 r_div = (parent_rate / rate) >> 1;
+	u32 r_div;
 	int err;
 	u8 r[3];
 
+	if (!rate)
+		return -EINVAL;
+
+	/* Frequency divider is (r_div + 1) * 2 */
+	r_div = (parent_rate / rate) >> 1;
+
 	if (r_div <= 1)
 		r_div = 0;
 	else if (r_div >= BIT(24))
@@ -717,10 +858,8 @@
 	r[0] = r_div ? (r_div & 0xff) : 1;
 	r[1] = (r_div >> 8) & 0xff;
 	r[2] = (r_div >> 16) & 0xff;
-	err = regmap_bulk_write(output->data->regmap,
+	return regmap_bulk_write(output->data->regmap,
 			SI5341_OUT_R_REG(output), r, 3);
-
-	return 0;
 }
 
 static int si5341_output_reparent(struct clk_si5341_output *output, u8 index)
@@ -924,7 +1063,7 @@
 	{ 0x0B25, 0x00 },
 	{ 0x0502, 0x01 },
 	{ 0x0505, 0x03 },
-	{ 0x0957, 0x1F },
+	{ 0x0957, 0x17 },
 	{ 0x0B4E, 0x1A },
 };
 
@@ -985,7 +1124,8 @@
 	regmap_reg_range(0x000C, 0x0012), /* Status */
 	regmap_reg_range(0x001C, 0x001E), /* reset, finc/fdec */
 	regmap_reg_range(0x00E2, 0x00FE), /* NVM, interrupts, device ready */
-	/* Update bits for synth config */
+	/* Update bits for P divider and synth config */
+	regmap_reg_range(SI5341_PX_UPD, SI5341_PX_UPD),
 	regmap_reg_range(SI5341_SYNTH_N_UPD(0), SI5341_SYNTH_N_UPD(0)),
 	regmap_reg_range(SI5341_SYNTH_N_UPD(1), SI5341_SYNTH_N_UPD(1)),
 	regmap_reg_range(SI5341_SYNTH_N_UPD(2), SI5341_SYNTH_N_UPD(2)),
@@ -1122,6 +1262,7 @@
 	struct device_node *np = data->i2c_client->dev.of_node;
 	u32 m_num = 0;
 	u32 m_den = 0;
+	int sel;
 
 	if (of_property_read_u32(np, "silabs,pll-m-num", &m_num)) {
 		dev_err(&data->i2c_client->dev,
@@ -1135,7 +1276,11 @@
 	if (!m_num || !m_den) {
 		dev_err(&data->i2c_client->dev,
 			"PLL configuration invalid, assume 14GHz\n");
-		m_den = clk_get_rate(data->pxtal) / 10;
+		sel = si5341_clk_get_selected_input(data);
+		if (sel < 0)
+			return sel;
+
+		m_den = clk_get_rate(data->input_clk[sel]) / 10;
 		m_num = 1400000000;
 	}
 
@@ -1143,11 +1288,52 @@
 			SI5341_PLL_M_NUM, m_num, m_den);
 }
 
+static int si5341_clk_select_active_input(struct clk_si5341 *data)
+{
+	int res;
+	int err;
+	int i;
+
+	res = si5341_clk_get_selected_input(data);
+	if (res < 0)
+		return res;
+
+	/* If the current register setting is invalid, pick the first input */
+	if (!data->input_clk[res]) {
+		dev_dbg(&data->i2c_client->dev,
+			"Input %d not connected, rerouting\n", res);
+		res = -ENODEV;
+		for (i = 0; i < SI5341_NUM_INPUTS; ++i) {
+			if (data->input_clk[i]) {
+				res = i;
+				break;
+			}
+		}
+		if (res < 0) {
+			dev_err(&data->i2c_client->dev,
+				"No clock input available\n");
+			return res;
+		}
+	}
+
+	/* Make sure the selected clock is also enabled and routed */
+	err = si5341_clk_reparent(data, res);
+	if (err < 0)
+		return err;
+
+	err = clk_prepare_enable(data->input_clk[res]);
+	if (err < 0)
+		return err;
+
+	return res;
+}
+
 static int si5341_probe(struct i2c_client *client,
 		const struct i2c_device_id *id)
 {
 	struct clk_si5341 *data;
 	struct clk_init_data init;
+	struct clk *input;
 	const char *root_clock_name;
 	const char *synth_clock_names[SI5341_NUM_SYNTH];
 	int err;
@@ -1161,12 +1347,16 @@
 
 	data->i2c_client = client;
 
-	data->pxtal = devm_clk_get(&client->dev, "xtal");
-	if (IS_ERR(data->pxtal)) {
-		if (PTR_ERR(data->pxtal) == -EPROBE_DEFER)
-			return -EPROBE_DEFER;
-
-		dev_err(&client->dev, "Missing xtal clock input\n");
+	for (i = 0; i < SI5341_NUM_INPUTS; ++i) {
+		input = devm_clk_get(&client->dev, si5341_input_clock_names[i]);
+		if (IS_ERR(input)) {
+			if (PTR_ERR(input) == -EPROBE_DEFER)
+				return -EPROBE_DEFER;
+			data->input_clk_name[i] = si5341_input_clock_names[i];
+		} else {
+			data->input_clk[i] = input;
+			data->input_clk_name[i] = __clk_get_name(input);
+		}
 	}
 
 	err = si5341_dt_parse_dt(client, config);
@@ -1188,9 +1378,6 @@
 	if (err < 0)
 		return err;
 
-	/* "Activate" the xtal (usually a fixed clock) */
-	clk_prepare_enable(data->pxtal);
-
 	if (of_property_read_bool(client->dev.of_node, "silabs,reprogram")) {
 		initialization_required = true;
 	} else {
@@ -1223,7 +1410,14 @@
 					ARRAY_SIZE(si5341_reg_defaults));
 		if (err < 0)
 			return err;
+	}
 
+	/* Input must be up and running at this point */
+	err = si5341_clk_select_active_input(data);
+	if (err < 0)
+		return err;
+
+	if (initialization_required) {
 		/* PLL configuration is required */
 		err = si5341_initialize_pll(data);
 		if (err < 0)
@@ -1231,9 +1425,8 @@
 	}
 
 	/* Register the PLL */
-	data->pxtal_name = __clk_get_name(data->pxtal);
-	init.parent_names = &data->pxtal_name;
-	init.num_parents = 1; /* For now, only XTAL input supported */
+	init.parent_names = data->input_clk_name;
+	init.num_parents = SI5341_NUM_INPUTS;
 	init.ops = &si5341_clk_ops;
 	init.flags = 0;
 	data->hw.init = &init;
@@ -1290,7 +1483,7 @@
 			clk_prepare(data->clk[i].hw.clk);
 	}
 
-	err = of_clk_add_hw_provider(client->dev.of_node, of_clk_si5341_get,
+	err = devm_of_clk_add_hw_provider(&client->dev, of_clk_si5341_get,
 			data);
 	if (err) {
 		dev_err(&client->dev, "unable to add clk provider\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/clk-stm32f4.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/clk-stm32f4.c
@@ -129,7 +129,6 @@
 	{ STM32F4_RCC_APB2ENR, 20,	"spi5",		"apb2_div" },
 	{ STM32F4_RCC_APB2ENR, 21,	"spi6",		"apb2_div" },
 	{ STM32F4_RCC_APB2ENR, 22,	"sai1",		"apb2_div" },
-	{ STM32F4_RCC_APB2ENR, 26,	"ltdc",		"apb2_div" },
 };
 
 static const struct stm32f4_gate_data stm32f469_gates[] __initconst = {
@@ -211,7 +210,6 @@
 	{ STM32F4_RCC_APB2ENR, 20,	"spi5",		"apb2_div" },
 	{ STM32F4_RCC_APB2ENR, 21,	"spi6",		"apb2_div" },
 	{ STM32F4_RCC_APB2ENR, 22,	"sai1",		"apb2_div" },
-	{ STM32F4_RCC_APB2ENR, 26,	"ltdc",		"apb2_div" },
 };
 
 static const struct stm32f4_gate_data stm32f746_gates[] __initconst = {
@@ -286,7 +284,6 @@
 	{ STM32F4_RCC_APB2ENR, 21,	"spi6",		"apb2_div" },
 	{ STM32F4_RCC_APB2ENR, 22,	"sai1",		"apb2_div" },
 	{ STM32F4_RCC_APB2ENR, 23,	"sai2",		"apb2_div" },
-	{ STM32F4_RCC_APB2ENR, 26,	"ltdc",		"apb2_div" },
 };
 
 static const struct stm32f4_gate_data stm32f769_gates[] __initconst = {
@@ -364,7 +361,6 @@
 	{ STM32F4_RCC_APB2ENR, 21,	"spi6",		"apb2_div" },
 	{ STM32F4_RCC_APB2ENR, 22,	"sai1",		"apb2_div" },
 	{ STM32F4_RCC_APB2ENR, 23,	"sai2",		"apb2_div" },
-	{ STM32F4_RCC_APB2ENR, 26,	"ltdc",		"apb2_div" },
 	{ STM32F4_RCC_APB2ENR, 30,	"mdio",		"apb2_div" },
 };
 
@@ -526,7 +522,7 @@
 
 struct stm32f4_pll_post_div_data {
 	int idx;
-	u8 pll_num;
+	int pll_idx;
 	const char *name;
 	const char *parent;
 	u8 flag;
@@ -557,13 +553,13 @@
 
 #define MAX_POST_DIV 3
 static const struct stm32f4_pll_post_div_data  post_div_data[MAX_POST_DIV] = {
-	{ CLK_I2SQ_PDIV, PLL_I2S, "plli2s-q-div", "plli2s-q",
+	{ CLK_I2SQ_PDIV, PLL_VCO_I2S, "plli2s-q-div", "plli2s-q",
 		CLK_SET_RATE_PARENT, STM32F4_RCC_DCKCFGR, 0, 5, 0, NULL},
 
-	{ CLK_SAIQ_PDIV, PLL_SAI, "pllsai-q-div", "pllsai-q",
+	{ CLK_SAIQ_PDIV, PLL_VCO_SAI, "pllsai-q-div", "pllsai-q",
 		CLK_SET_RATE_PARENT, STM32F4_RCC_DCKCFGR, 8, 5, 0, NULL },
 
-	{ NO_IDX, PLL_SAI, "pllsai-r-div", "pllsai-r", CLK_SET_RATE_PARENT,
+	{ NO_IDX, PLL_VCO_SAI, "pllsai-r-div", "pllsai-r", CLK_SET_RATE_PARENT,
 		STM32F4_RCC_DCKCFGR, 16, 2, 0, post_divr_table },
 };
 
@@ -1774,7 +1770,7 @@
 				post_div->width,
 				post_div->flag_div,
 				post_div->div_table,
-				clks[post_div->pll_num],
+				clks[post_div->pll_idx],
 				&stm32f4_clk_lock);
 
 		if (post_div->idx != NO_IDX)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/clk-xlnx-clock-wizard-v.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/clk-xlnx-clock-wizard-v.c
@@ -0,0 +1,513 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx 'Clocking Wizard' driver
+ *
+ *  Copyright (C) 2020 Xilinx
+ *
+ *  Shubhrajyoti Datta <shubhrajyoti.datta@xilinx.com>
+ */
+
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/module.h>
+#include <linux/err.h>
+
+#define WZRD_NUM_OUTPUTS	7
+#define WZRD_ACLK_MAX_FREQ	250000000UL
+
+#define WZRD_CLK_CFG_REG(n)	(0x330 + 4 * (n))
+
+#define WZRD_CLKFBOUT_FRAC_EN	BIT(1)
+
+#define WZRD_CLKFBOUT_L_SHIFT	0
+#define WZRD_CLKFBOUT_H_SHIFT	8
+#define WZRD_CLKFBOUT_L_MASK	(0xff << WZRD_CLKFBOUT_L_SHIFT)
+#define WZRD_CLKFBOUT_H_MASK	(0xff << WZRD_CLKFBOUT_H_SHIFT)
+#define WZRD_CLKFBOUT_FRAC_SHIFT	16
+#define WZRD_CLKFBOUT_FRAC_MASK		(0x3f)
+#define WZRD_DIVCLK_DIVIDE_SHIFT	0
+#define WZRD_DIVCLK_DIVIDE_MASK		(0xff << WZRD_DIVCLK_DIVIDE_SHIFT)
+#define WZRD_CLKOUT_DIVIDE_SHIFT	0
+#define WZRD_CLKOUT_DIVIDE_WIDTH	8
+#define WZRD_CLKOUT_DIVIDE_MASK		(0xff << WZRD_DIVCLK_DIVIDE_SHIFT)
+#define WZRD_CLKOUT_FRAC_SHIFT		8
+#define WZRD_CLKOUT_FRAC_MASK		0x3ff
+
+#define WZRD_DR_MAX_INT_DIV_VALUE	32767
+#define WZRD_DR_NUM_RETRIES		10000
+#define WZRD_DR_STATUS_REG_OFFSET	0x04
+#define WZRD_DR_LOCK_BIT_MASK		0x00000001
+#define WZRD_DR_INIT_REG_OFFSET		0x14
+#define WZRD_DR_DIV_TO_PHASE_OFFSET	4
+#define WZRD_DR_BEGIN_DYNA_RECONF	0x03
+
+/* Get the mask from width */
+#define div_mask(width)			((1 << (width)) - 1)
+
+/* Extract divider instance from clock hardware instance */
+#define to_clk_wzrd_divider(_hw) container_of(_hw, struct clk_wzrd_divider, hw)
+
+enum clk_wzrd_int_clks {
+	wzrd_clk_mul,
+	wzrd_clk_mul_div,
+	wzrd_clk_mul_frac,
+	wzrd_clk_int_max
+};
+
+/**
+ * struct clk_wzrd - Clock wizard private data structure
+ *
+ * @clk_data:		Clock data
+ * @nb:			Notifier block
+ * @base:		Memory base
+ * @clk_in1:		Handle to input clock 'clk_in1'
+ * @axi_clk:		Handle to input clock 's_axi_aclk'
+ * @clks_internal:	Internal clocks
+ * @clkout:		Output clocks
+ * @suspended:		Flag indicating power state of the device
+ * @is_versal:		Flag indicating if it versal device
+ */
+struct clk_wzrd {
+	struct clk_onecell_data clk_data;
+	struct notifier_block nb;
+	void __iomem *base;
+	struct clk *clk_in1;
+	struct clk *axi_clk;
+	struct clk *clks_internal[wzrd_clk_int_max];
+	struct clk *clkout[WZRD_NUM_OUTPUTS];
+	bool suspended;
+	bool is_versal;
+};
+
+/**
+ * struct clk_wzrd_divider - clock divider specific to clk_wzrd
+ *
+ * @hw:		handle between common and hardware-specific interfaces
+ * @base:	base address of register containing the divider
+ * @offset:	offset address of register containing the divider
+ * @shift:	shift to the divider bit field
+ * @width:	width of the divider bit field
+ * @flags:	clk_wzrd divider flags
+ * @table:	array of value/divider pairs, last entry should have div = 0
+ * @lock:	register lock
+ */
+struct clk_wzrd_divider {
+	struct clk_hw hw;
+	void __iomem *base;
+	u16 offset;
+	u8 shift;
+	u8 width;
+	u8 flags;
+	const struct clk_div_table *table;
+	spinlock_t *lock;  /* divider lock */
+};
+
+#define to_clk_wzrd(_nb) container_of(_nb, struct clk_wzrd, nb)
+
+/* spin lock variable for clk_wzrd */
+static DEFINE_SPINLOCK(clkwzrd_lock);
+
+static unsigned long clk_wzrd_recalc_rate(struct clk_hw *hw,
+					  unsigned long parent_rate)
+{
+	struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw);
+	void __iomem *div_addr =
+			(void __iomem *)((u64)divider->base + divider->offset);
+	unsigned int vall, valh;
+	u32 div;
+	u32 p5en, edge, prediv2;
+	u32 all;
+
+	edge = !!(readl(div_addr) & BIT(8));
+	p5en = !!(readl(div_addr) & BIT(13));
+	prediv2 = !!(readl(div_addr) & BIT(11));
+	vall = readl(div_addr + 4) & 0xff;
+	valh = readl(div_addr + 4) >> 8;
+	all = valh + vall + edge;
+	if (!all)
+		all = 1;
+	div = (prediv2 + 1) * (all + (prediv2 * p5en) / 2);
+	return  DIV_ROUND_UP_ULL((u64)parent_rate, div);
+}
+
+static int clk_wzrd_dynamic_reconfig(struct clk_hw *hw, unsigned long rate,
+				     unsigned long parent_rate)
+{
+	int err = 0;
+	u16 retries;
+	u32 value;
+	unsigned long flags = 0;
+	u32 regh, edged;
+	u32 p5en, p5fedge;
+	u32 regval, regval1;
+	struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw);
+	void __iomem *div_addr =
+			(void __iomem *)((u64)divider->base + divider->offset);
+	if (divider->lock)
+		spin_lock_irqsave(divider->lock, flags);
+	else
+		__acquire(divider->lock);
+
+	value = DIV_ROUND_CLOSEST(parent_rate, rate);
+	regh = (value / 4);
+	regh = regh * 2;
+	regval = regh | (regh << 8);
+	regval1 = readl(div_addr);
+	regval1 = regval1 &  ~(BIT(8) | BIT(13) | BIT(15));
+	if (value % 4 > 1) {
+		edged = 1;
+		regval1 |= (edged << 8);
+	}
+	p5fedge = value % 2;
+	p5en = value % 2;
+	regval1 = regval1 | p5en << 13 | p5fedge << 15;
+	writel(regval1, div_addr);
+	regval = regh | regh << 8;
+	writel(regval, div_addr + 4);
+	/* Check status register */
+	retries = WZRD_DR_NUM_RETRIES;
+	while (retries--) {
+		if (readl(divider->base + WZRD_DR_STATUS_REG_OFFSET) &
+							WZRD_DR_LOCK_BIT_MASK)
+			break;
+	}
+
+	if (retries == 0) {
+		err = -ETIMEDOUT;
+		goto err_reconfig;
+	}
+
+	/* Initiate reconfiguration */
+	writel(WZRD_DR_BEGIN_DYNA_RECONF,
+	       divider->base + WZRD_DR_INIT_REG_OFFSET);
+
+	/* Check status register */
+	retries = WZRD_DR_NUM_RETRIES;
+	while (retries--) {
+		if (readl(divider->base + WZRD_DR_STATUS_REG_OFFSET) &
+							WZRD_DR_LOCK_BIT_MASK)
+			break;
+	}
+
+	if (retries == 0) {
+		pr_err("NOT LOCKED\n");
+		err = -ETIMEDOUT;
+	}
+
+err_reconfig:
+	if (divider->lock)
+		spin_unlock_irqrestore(divider->lock, flags);
+	else
+		__release(divider->lock);
+
+	return err;
+}
+
+static long clk_wzrd_round_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long *prate)
+{
+	u8 div;
+
+	/*
+	 * since we donot change parent rate we just round rate to closest
+	 * achievable
+	 */
+	div = DIV_ROUND_CLOSEST(*prate, rate);
+
+	return (*prate / div);
+}
+
+static const struct clk_ops clk_wzrd_clk_divider_ops = {
+	.round_rate = clk_wzrd_round_rate,
+	.set_rate = clk_wzrd_dynamic_reconfig,
+	.recalc_rate = clk_wzrd_recalc_rate,
+};
+
+static struct clk *clk_wzrd_register_divider(struct device *dev,
+					     const char *name,
+					     const char *parent_name,
+					     unsigned long flags,
+					     void __iomem *base, u16 offset,
+					     u8 shift, u8 width,
+					     u8 clk_divider_flags,
+					     const struct clk_div_table *table,
+					     spinlock_t *lock)
+{
+	struct clk_wzrd_divider *div;
+	struct clk_hw *hw;
+	struct clk_init_data init;
+	int ret;
+
+	if (clk_divider_flags & CLK_DIVIDER_HIWORD_MASK) {
+		if (width + shift > 16) {
+			pr_warn("divider value exceeds LOWORD field\n");
+			return ERR_PTR(-EINVAL);
+		}
+	}
+
+	/* allocate the divider */
+	div = kzalloc(sizeof(*div), GFP_KERNEL);
+	if (!div)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	if (clk_divider_flags & CLK_DIVIDER_READ_ONLY)
+		init.ops = &clk_divider_ro_ops;
+	else
+		init.ops = &clk_wzrd_clk_divider_ops;
+	init.flags = flags;
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+
+	/* struct clk_divider assignments */
+	div->base = base;
+	div->offset = offset;
+	div->shift = shift;
+	div->width = width;
+	div->flags = clk_divider_flags;
+	div->lock = lock;
+	div->hw.init = &init;
+	div->table = table;
+
+	/* register the clock */
+	hw = &div->hw;
+	ret = clk_hw_register(dev, hw);
+	if (ret) {
+		kfree(div);
+		hw = ERR_PTR(ret);
+	}
+
+	return hw->clk;
+}
+
+static int __maybe_unused clk_wzrd_suspend(struct device *dev)
+{
+	struct clk_wzrd *clk_wzrd = dev_get_drvdata(dev);
+
+	clk_disable_unprepare(clk_wzrd->axi_clk);
+	clk_wzrd->suspended = true;
+
+	return 0;
+}
+
+static int __maybe_unused clk_wzrd_resume(struct device *dev)
+{
+	int ret;
+	struct clk_wzrd *clk_wzrd = dev_get_drvdata(dev);
+
+	ret = clk_prepare_enable(clk_wzrd->axi_clk);
+	if (ret) {
+		dev_err(dev, "unable to enable s_axi_aclk\n");
+		return ret;
+	}
+
+	clk_wzrd->suspended = false;
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(clk_wzrd_dev_pm_ops, clk_wzrd_suspend,
+			 clk_wzrd_resume);
+
+static int clk_wzrd_probe(struct platform_device *pdev)
+{
+	int i, ret;
+	u32 regl, regh, edge, mult;
+	u32 regld, reghd, edged, div;
+	unsigned long rate;
+	const char *clk_name;
+	struct clk_wzrd *clk_wzrd;
+	struct resource *mem;
+	int outputs;
+	struct device_node *np = pdev->dev.of_node;
+
+	clk_wzrd = devm_kzalloc(&pdev->dev, sizeof(*clk_wzrd), GFP_KERNEL);
+	if (!clk_wzrd)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, clk_wzrd);
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	clk_wzrd->base = devm_ioremap_resource(&pdev->dev, mem);
+	if (IS_ERR(clk_wzrd->base))
+		return PTR_ERR(clk_wzrd->base);
+
+	clk_wzrd->clk_in1 = devm_clk_get(&pdev->dev, "clk_in1");
+	if (IS_ERR(clk_wzrd->clk_in1)) {
+		if (clk_wzrd->clk_in1 != ERR_PTR(-EPROBE_DEFER))
+			dev_err(&pdev->dev, "clk_in1 not found\n");
+		return PTR_ERR(clk_wzrd->clk_in1);
+	}
+
+	clk_wzrd->axi_clk = devm_clk_get(&pdev->dev, "s_axi_aclk");
+	if (IS_ERR(clk_wzrd->axi_clk)) {
+		if (clk_wzrd->axi_clk != ERR_PTR(-EPROBE_DEFER))
+			dev_err(&pdev->dev, "s_axi_aclk not found\n");
+		return PTR_ERR(clk_wzrd->axi_clk);
+	}
+	ret = clk_prepare_enable(clk_wzrd->axi_clk);
+	if (ret) {
+		dev_err(&pdev->dev, "enabling s_axi_aclk failed\n");
+		return ret;
+	}
+	rate = clk_get_rate(clk_wzrd->axi_clk);
+	if (rate > WZRD_ACLK_MAX_FREQ) {
+		dev_err(&pdev->dev, "s_axi_aclk frequency (%lu) too high\n",
+			rate);
+		ret = -EINVAL;
+		goto err_disable_clk;
+	}
+
+	/* register multiplier */
+	edge = !!(readl(clk_wzrd->base + WZRD_CLK_CFG_REG(0)) & BIT(8));
+	regl = (readl(clk_wzrd->base + WZRD_CLK_CFG_REG(1)) &
+		     WZRD_CLKFBOUT_L_MASK) >> WZRD_CLKFBOUT_L_SHIFT;
+	regh = (readl(clk_wzrd->base + WZRD_CLK_CFG_REG(1)) &
+		     WZRD_CLKFBOUT_H_MASK) >> WZRD_CLKFBOUT_H_SHIFT;
+	mult = (regl  + regh + edge);
+	if (!mult)
+		mult = 1;
+	mult = mult * 64;
+
+	regl = readl(clk_wzrd->base + WZRD_CLK_CFG_REG(51)) &
+		     WZRD_CLKFBOUT_FRAC_EN;
+	if (!regl) {
+		regl = readl(clk_wzrd->base + WZRD_CLK_CFG_REG(48)) &
+			WZRD_CLKFBOUT_FRAC_MASK;
+		mult = mult + regl;
+	}
+
+	clk_name = kasprintf(GFP_KERNEL, "%s_mul", dev_name(&pdev->dev));
+	if (!clk_name) {
+		ret = -ENOMEM;
+		goto err_disable_clk;
+	}
+	clk_wzrd->clks_internal[wzrd_clk_mul] = clk_register_fixed_factor
+			(&pdev->dev, clk_name,
+			 __clk_get_name(clk_wzrd->clk_in1),
+			0, mult, 64);
+	kfree(clk_name);
+	if (IS_ERR(clk_wzrd->clks_internal[wzrd_clk_mul])) {
+		dev_err(&pdev->dev, "unable to register fixed-factor clock\n");
+		ret = PTR_ERR(clk_wzrd->clks_internal[wzrd_clk_mul]);
+		goto err_disable_clk;
+	}
+
+	outputs = of_property_count_strings(np, "clock-output-names");
+	clk_name = kasprintf(GFP_KERNEL, "%s_mul_div", dev_name(&pdev->dev));
+	if (!clk_name) {
+		ret = -ENOMEM;
+		goto err_rm_int_clk;
+	}
+
+	/* register div */
+	edged = !!(readl(clk_wzrd->base + WZRD_CLK_CFG_REG(20)) &
+		     BIT(10));
+	regld = (readl(clk_wzrd->base + WZRD_CLK_CFG_REG(21)) &
+		     WZRD_CLKFBOUT_L_MASK) >> WZRD_CLKFBOUT_L_SHIFT;
+	reghd = (readl(clk_wzrd->base + WZRD_CLK_CFG_REG(21)) &
+		     WZRD_CLKFBOUT_H_MASK) >> WZRD_CLKFBOUT_H_SHIFT;
+	div = (regld  + reghd + edged);
+	if (!div)
+		div = 1;
+	clk_wzrd->clks_internal[wzrd_clk_mul_div] = clk_register_fixed_factor
+			(&pdev->dev, clk_name,
+			 __clk_get_name(clk_wzrd->clks_internal[wzrd_clk_mul]),
+			0, 1, div);
+	if (IS_ERR(clk_wzrd->clks_internal[wzrd_clk_mul_div])) {
+		dev_err(&pdev->dev, "unable to register divider clock\n");
+		ret = PTR_ERR(clk_wzrd->clks_internal[wzrd_clk_mul_div]);
+		goto err_rm_int_clk;
+	}
+
+	/* register div per output */
+	for (i = outputs - 1; i >= 0 ; i--) {
+		const char *clkout_name;
+
+		if (of_property_read_string_index(np, "clock-output-names", i,
+						  &clkout_name)) {
+			dev_err(&pdev->dev,
+				"clock output name not specified\n");
+			ret = -EINVAL;
+			goto err_rm_int_clks;
+		}
+
+		clk_wzrd->clkout[i] = clk_wzrd_register_divider
+				(&pdev->dev, clkout_name,
+				clk_name, 0,
+				clk_wzrd->base, (WZRD_CLK_CFG_REG(3) + i * 8),
+				WZRD_CLKOUT_DIVIDE_SHIFT,
+				WZRD_CLKOUT_DIVIDE_WIDTH,
+				CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
+				NULL, &clkwzrd_lock);
+		if (IS_ERR(clk_wzrd->clkout[i])) {
+			int j;
+
+			for (j = i + 1; j < outputs; j++)
+				clk_unregister(clk_wzrd->clkout[j]);
+			dev_err(&pdev->dev,
+				"unable to register divider clock\n");
+			ret = PTR_ERR(clk_wzrd->clkout[i]);
+			goto err_rm_int_clks;
+		}
+	}
+
+	kfree(clk_name);
+
+	clk_wzrd->clk_data.clks = clk_wzrd->clkout;
+	clk_wzrd->clk_data.clk_num = ARRAY_SIZE(clk_wzrd->clkout);
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_wzrd->clk_data);
+
+	return 0;
+
+err_rm_int_clks:
+	clk_unregister(clk_wzrd->clks_internal[1]);
+err_rm_int_clk:
+	kfree(clk_name);
+	clk_unregister(clk_wzrd->clks_internal[0]);
+err_disable_clk:
+	clk_disable_unprepare(clk_wzrd->axi_clk);
+
+	return ret;
+}
+
+static int clk_wzrd_remove(struct platform_device *pdev)
+{
+	int i;
+	struct clk_wzrd *clk_wzrd = platform_get_drvdata(pdev);
+
+	of_clk_del_provider(pdev->dev.of_node);
+
+	for (i = 0; i < WZRD_NUM_OUTPUTS; i++)
+		clk_unregister(clk_wzrd->clkout[i]);
+	for (i = 0; i < wzrd_clk_int_max; i++)
+		clk_unregister(clk_wzrd->clks_internal[i]);
+
+	clk_disable_unprepare(clk_wzrd->axi_clk);
+
+	return 0;
+}
+
+static const struct of_device_id clk_wzrd_ids[] = {
+	{ .compatible = "xlnx,clk-wizard-1.0" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, clk_wzrd_ids);
+
+static struct platform_driver clk_wzrd_driver = {
+	.driver = {
+		.name = "clk-wizard",
+		.of_match_table = clk_wzrd_ids,
+		.pm = &clk_wzrd_dev_pm_ops,
+	},
+	.probe = clk_wzrd_probe,
+	.remove = clk_wzrd_remove,
+};
+module_platform_driver(clk_wzrd_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Shubhrajyoti Datta <shubhrajyoti.datta@xilinx.com>");
+MODULE_DESCRIPTION("Driver for the Versal Clocking Wizard IP core");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/clk-xlnx-clock-wizard.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/clk-xlnx-clock-wizard.c
@@ -0,0 +1,978 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx 'Clocking Wizard' driver
+ *
+ *  Copyright (C) 2013 - 2014 Xilinx
+ *
+ *  Sören Brinkmann <soren.brinkmann@xilinx.com>
+ */
+
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/module.h>
+#include <linux/err.h>
+
+#define WZRD_NUM_OUTPUTS	7
+#define WZRD_ACLK_MAX_FREQ	250000000UL
+
+#define WZRD_CLK_CFG_REG(n)	(0x200 + 4 * (n))
+
+#define WZRD_CLKOUT0_FRAC_EN	BIT(18)
+#define WZRD_CLKFBOUT_FRAC_EN	BIT(26)
+
+#define WZRD_CLKFBOUT_MULT_SHIFT	8
+#define WZRD_CLKFBOUT_MULT_MASK		(0xff << WZRD_CLKFBOUT_MULT_SHIFT)
+#define WZRD_CLKFBOUT_FRAC_SHIFT	16
+#define WZRD_CLKFBOUT_FRAC_MASK		(0x3ff << WZRD_CLKFBOUT_FRAC_SHIFT)
+#define WZRD_DIVCLK_DIVIDE_SHIFT	0
+#define WZRD_DIVCLK_DIVIDE_MASK		(0xff << WZRD_DIVCLK_DIVIDE_SHIFT)
+#define WZRD_CLKOUT_DIVIDE_SHIFT	0
+#define WZRD_CLKOUT_DIVIDE_WIDTH	8
+#define WZRD_CLKOUT_DIVIDE_MASK		(0xff << WZRD_DIVCLK_DIVIDE_SHIFT)
+#define WZRD_CLKOUT_FRAC_SHIFT		8
+#define WZRD_CLKOUT_FRAC_MASK		0x3ff
+
+#define WZRD_DR_MAX_INT_DIV_VALUE	255
+#define WZRD_DR_NUM_RETRIES		10000
+#define WZRD_DR_STATUS_REG_OFFSET	0x04
+#define WZRD_DR_LOCK_BIT_MASK		0x00000001
+#define WZRD_DR_INIT_REG_OFFSET		0x25C
+#define WZRD_DR_DIV_TO_PHASE_OFFSET	4
+#define WZRD_DR_BEGIN_DYNA_RECONF	0x03
+
+/* Multiplier limits, from UG572 Table 3-4 for Ultrascale+ */
+#define CLKFBOUT_MULT_F_MIN		2000U
+#define CLKFBOUT_MULT_F_MAX		128000U
+
+/* Divider limits, from UG572 Table 3-4 for Ultrascale+ */
+#define DIVCLK_DIVIDE_MIN		1U
+#define DIVCLK_DIVIDE_MAX		106U
+
+/* Get the mask from width */
+#define div_mask(width)			((1 << (width)) - 1)
+
+/* Extract divider instance from clock hardware instance */
+#define to_clk_wzrd_divider(_hw) container_of(_hw, struct clk_wzrd_divider, hw)
+
+/*
+ *         MMCM Block Diagram
+ *
+ *         +----------------+  +-----------------+
+ * input ->| vco_clk_div_hw |->| vco_clk_mul_hw  |--+
+ * rate    | (int divide)   |  | (frac multiply) |  |
+ *         +----------------+  +-----------------+  |
+ *                                                  |
+ *      +--------------------------------VCO-rate---+
+ *      |
+ *      |  +----------------+
+ *      +->| clkout[0]      |-> output0 rate
+ *      |  | (frac divide)  |
+ *      |  +----------------+
+ *      |
+ *      |  +----------------+
+ *      +->| clkout[1]      |-> output1 rate
+ *      |  | (int divide)   |
+ *      |  +----------------+
+ *      |
+ *     ...
+ *      |
+ *      |  +----------------+
+ *      +->| clkout[1]      |-> output6 rate
+ *         | (int divide)   |
+ *         +----------------+
+ *
+ * struct clk_wzrd - Clock wizard private data structure
+ *
+ * @clk_data:		Clock data
+ * @nb:			Notifier block
+ * @base:		Memory base
+ * @clk_in1:		Handle to input clock 'clk_in1'
+ * @axi_clk:		Handle to input clock 's_axi_aclk'
+ * @clkout:		Output clocks
+ * @speed_grade:	Speed grade of the device
+ * @suspended:		Flag indicating power state of the device
+ * @lock		lock pointer
+ * @vco_clk:		hw Voltage Controlled Oscilator clock
+ */
+struct clk_wzrd {
+	struct clk_onecell_data clk_data;
+	struct notifier_block nb;
+	void __iomem *base;
+	struct clk *clk_in1;
+	struct clk *axi_clk;
+	struct clk *clkout[WZRD_NUM_OUTPUTS];
+	unsigned int speed_grade;
+	bool suspended;
+	spinlock_t *lock;
+	struct clk_hw vco_clk_div_hw;
+	struct clk_hw vco_clk_mul_hw;
+};
+
+/**
+ * struct clk_wzrd_divider - clock divider specific to clk_wzrd
+ *
+ * @hw:		handle between common and hardware-specific interfaces
+ * @base:	base address of register containing the divider
+ * @offset:	offset address of register containing the divider
+ * @shift:	shift to the divider bit field
+ * @width:	width of the divider bit field
+ * @flags:	clk_wzrd divider flags
+ * @table:	array of value/divider pairs, last entry should have div = 0
+ * @lock:	register lock
+ */
+struct clk_wzrd_divider {
+	struct clk_hw hw;
+	void __iomem *base;
+	u16 offset;
+	u8 shift;
+	u8 width;
+	u8 flags;
+	const struct clk_div_table *table;
+	spinlock_t *lock;  /* divider lock */
+};
+
+#define to_clk_wzrd(_nb) container_of(_nb, struct clk_wzrd, nb)
+
+/* maximum frequencies for input/output clocks per speed grade */
+static const unsigned long clk_wzrd_max_freq[] = {
+	800000000UL,
+	933000000UL,
+	1066000000UL
+};
+
+/* spin lock variable for clk_wzrd */
+static DEFINE_SPINLOCK(clkwzrd_lock);
+
+static unsigned long clk_wzrd_recalc_rate(struct clk_hw *hw,
+					  unsigned long parent_rate)
+{
+	struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw);
+	void __iomem *div_addr =
+			(void __iomem *)(divider->base + divider->offset);
+	unsigned int val;
+
+	val = readl(div_addr) >> divider->shift;
+	val &= div_mask(divider->width);
+
+	return divider_recalc_rate(hw, parent_rate, val, divider->table,
+			divider->flags, divider->width);
+}
+
+static int clk_wzrd_dynamic_reconfig(struct clk_hw *hw, unsigned long rate,
+				     unsigned long parent_rate)
+{
+	int err = 0;
+	u16 retries;
+	u32 value;
+	unsigned long flags = 0;
+	struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw);
+	void __iomem *div_addr =
+			(void __iomem *)(divider->base + divider->offset);
+
+	if (divider->lock)
+		spin_lock_irqsave(divider->lock, flags);
+	else
+		__acquire(divider->lock);
+
+	value = DIV_ROUND_CLOSEST(parent_rate, rate);
+
+	/* Cap the value to max */
+	if (value > WZRD_DR_MAX_INT_DIV_VALUE)
+		value = WZRD_DR_MAX_INT_DIV_VALUE;
+
+	/* Set divisor and clear phase offset */
+	writel(value, div_addr);
+	writel(0x00, div_addr + WZRD_DR_DIV_TO_PHASE_OFFSET);
+
+	/* Check status register */
+	retries = WZRD_DR_NUM_RETRIES;
+	while (retries--) {
+		if (readl(divider->base + WZRD_DR_STATUS_REG_OFFSET) &
+							WZRD_DR_LOCK_BIT_MASK)
+			break;
+	}
+
+	if (retries == 0) {
+		err = -ETIMEDOUT;
+		goto err_reconfig;
+	}
+
+	/* Initiate reconfiguration */
+	writel(WZRD_DR_BEGIN_DYNA_RECONF,
+	       divider->base + WZRD_DR_INIT_REG_OFFSET);
+
+	/* Check status register */
+	retries = WZRD_DR_NUM_RETRIES;
+	while (retries--) {
+		if (readl(divider->base + WZRD_DR_STATUS_REG_OFFSET) &
+							WZRD_DR_LOCK_BIT_MASK)
+			break;
+	}
+
+	if (retries == 0)
+		err = -ETIMEDOUT;
+
+err_reconfig:
+	if (divider->lock)
+		spin_unlock_irqrestore(divider->lock, flags);
+	else
+		__release(divider->lock);
+
+	return err;
+}
+
+static long clk_wzrd_round_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long *prate)
+{
+	u8 div;
+
+	/*
+	 * since we donot change parent rate we just round rate to closest
+	 * achievable
+	 */
+	div = DIV_ROUND_CLOSEST(*prate, rate);
+
+	return (*prate / div);
+}
+
+static const struct clk_ops clk_wzrd_clk_divider_ops = {
+	.round_rate = clk_wzrd_round_rate,
+	.set_rate = clk_wzrd_dynamic_reconfig,
+	.recalc_rate = clk_wzrd_recalc_rate,
+};
+
+static unsigned long clk_wzrd_recalc_ratef(struct clk_hw *hw,
+					   unsigned long parent_rate)
+{
+	unsigned int val;
+	u32 div, frac;
+	struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw);
+	void __iomem *div_addr =
+			(void __iomem *)((u64)divider->base + divider->offset);
+
+	val = readl(div_addr);
+	div = val & div_mask(divider->width);
+	frac = (val >> WZRD_CLKOUT_FRAC_SHIFT) & WZRD_CLKOUT_FRAC_MASK;
+
+	return ((parent_rate * 1000) / ((div * 1000) + frac));
+}
+
+static int clk_wzrd_dynamic_reconfig_f(struct clk_hw *hw, unsigned long rate,
+				       unsigned long parent_rate)
+{
+	int err = 0;
+	u16 retries;
+	u32 value, pre;
+	unsigned long flags = 0;
+	unsigned long rate_div, f, clockout0_div;
+	struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw);
+	void __iomem *div_addr =
+			(void __iomem *)((u64)divider->base + divider->offset);
+
+	if (divider->lock)
+		spin_lock_irqsave(divider->lock, flags);
+	else
+		__acquire(divider->lock);
+
+	rate_div = ((parent_rate * 1000) / rate);
+	clockout0_div = rate_div / 1000;
+
+	pre = DIV_ROUND_CLOSEST((parent_rate * 1000), rate);
+	f = (u32)(pre - (clockout0_div * 1000));
+	f = f & WZRD_CLKOUT_FRAC_MASK;
+
+	value = ((f << WZRD_CLKOUT_DIVIDE_WIDTH) | (clockout0_div &
+			WZRD_CLKOUT_DIVIDE_MASK));
+
+	/* Set divisor and clear phase offset */
+	writel(value, div_addr);
+	writel(0x0, div_addr + WZRD_DR_DIV_TO_PHASE_OFFSET);
+
+	/* Check status register */
+	retries = WZRD_DR_NUM_RETRIES;
+	while (retries--) {
+		if (readl(divider->base + WZRD_DR_STATUS_REG_OFFSET) &
+							WZRD_DR_LOCK_BIT_MASK)
+			break;
+	}
+
+	if (!retries) {
+		err = -ETIMEDOUT;
+		goto err_reconfig;
+	}
+
+	/* Initiate reconfiguration */
+	writel(WZRD_DR_BEGIN_DYNA_RECONF,
+	       divider->base + WZRD_DR_INIT_REG_OFFSET);
+
+	/* Check status register */
+	retries = WZRD_DR_NUM_RETRIES;
+	while (retries--) {
+		if (readl(divider->base + WZRD_DR_STATUS_REG_OFFSET) &
+							WZRD_DR_LOCK_BIT_MASK)
+			break;
+	}
+
+	if (!retries)
+		err = -ETIMEDOUT;
+
+err_reconfig:
+	if (divider->lock)
+		spin_unlock_irqrestore(divider->lock, flags);
+	else
+		__release(divider->lock);
+
+	return err;
+}
+
+static long clk_wzrd_round_rate_f(struct clk_hw *hw, unsigned long rate,
+				  unsigned long *prate)
+{
+	return rate;
+}
+
+static const struct clk_ops clk_wzrd_clk_divider_ops_f = {
+	.round_rate = clk_wzrd_round_rate_f,
+	.set_rate = clk_wzrd_dynamic_reconfig_f,
+	.recalc_rate = clk_wzrd_recalc_ratef,
+};
+
+static unsigned long clk_wzrd_vco_mul_recalc_rate_f(struct clk_hw *hw,
+					       unsigned long parent_rate)
+{
+	u32 clk_cfg_reg0;
+	u32 clkfbout_mult, clkfbout_frac;
+	u64 rate;
+
+	struct clk_wzrd *clk_wzrd = container_of(hw,
+						 struct clk_wzrd,
+						 vco_clk_mul_hw);
+
+	clk_cfg_reg0 = readl(clk_wzrd->base + WZRD_CLK_CFG_REG(0));
+	clkfbout_mult = (clk_cfg_reg0 & WZRD_CLKFBOUT_MULT_MASK) >>
+			 WZRD_CLKFBOUT_MULT_SHIFT;
+	clkfbout_frac = (clk_cfg_reg0 & WZRD_CLKFBOUT_FRAC_MASK) >>
+			 WZRD_CLKFBOUT_FRAC_SHIFT;
+
+	rate = parent_rate *
+	       (clkfbout_mult * 1000 + clkfbout_frac) / /* multiplier x1000 */
+	       1000;
+
+	return (unsigned long)rate;
+}
+
+static int clk_wzrd_vco_mul_dynamic_reconfig_f(struct clk_hw *hw,
+					   unsigned long rate,
+					   unsigned long parent_rate)
+{
+	int err = 0;
+	u16 retries;
+	unsigned long flags = 0;
+	u32 clk_cfg_reg0, value;
+	u32 divclk_divide, clkfbout_mult, clkfbout_frac;
+	unsigned int new_mult;
+
+	struct clk_wzrd *clk_wzrd = container_of(hw,
+						 struct clk_wzrd,
+						 vco_clk_mul_hw);
+
+	/* The 8*125 give the x1000 that is needed */
+	new_mult = (rate * 8 / parent_rate) * 125;
+	new_mult = clamp(new_mult, CLKFBOUT_MULT_F_MIN, CLKFBOUT_MULT_F_MAX);
+
+	clkfbout_mult = new_mult / 1000;
+	clkfbout_frac = new_mult % 1000;
+
+	/* Read divclk_divide so it can be left unchanged */
+	clk_cfg_reg0 = readl(clk_wzrd->base + WZRD_CLK_CFG_REG(0));
+	divclk_divide = (clk_cfg_reg0 & WZRD_DIVCLK_DIVIDE_MASK) >>
+			 WZRD_DIVCLK_DIVIDE_SHIFT;
+
+	value = clkfbout_frac << WZRD_CLKFBOUT_FRAC_SHIFT |
+		 clkfbout_mult << WZRD_CLKFBOUT_MULT_SHIFT |
+		 divclk_divide << WZRD_DIVCLK_DIVIDE_SHIFT;
+
+	if (clk_wzrd->lock)
+		spin_lock_irqsave(clk_wzrd->lock, flags);
+	else
+		__acquire(clk_wzrd->lock);
+
+	/* Write the configuration out */
+	writel(value, clk_wzrd->base + WZRD_CLK_CFG_REG(0));
+
+	/* Check status register */
+	retries = WZRD_DR_NUM_RETRIES;
+	while (retries--) {
+		if (readl(clk_wzrd->base + WZRD_DR_STATUS_REG_OFFSET) &
+							WZRD_DR_LOCK_BIT_MASK)
+			break;
+	}
+
+	if (!retries) {
+		err = -ETIMEDOUT;
+		goto err_reconfig;
+	}
+
+	/* Initiate reconfiguration */
+	writel(WZRD_DR_BEGIN_DYNA_RECONF,
+	       clk_wzrd->base + WZRD_DR_INIT_REG_OFFSET);
+
+	/* Check status register */
+	retries = WZRD_DR_NUM_RETRIES;
+	while (retries--) {
+		if (readl(clk_wzrd->base + WZRD_DR_STATUS_REG_OFFSET) &
+							WZRD_DR_LOCK_BIT_MASK)
+			break;
+	}
+
+	if (!retries)
+		err = -ETIMEDOUT;
+
+err_reconfig:
+	if (clk_wzrd->lock)
+		spin_unlock_irqrestore(clk_wzrd->lock, flags);
+	else
+		__release(clk_wzrd->lock);
+
+	return err;
+}
+
+static long clk_wzrd_vco_mul_round_rate_f(struct clk_hw *hw, unsigned long rate,
+				      unsigned long *prate)
+{
+	return rate;
+}
+
+static const struct clk_ops clk_wzrd_vco_mul_ops_f = {
+	.round_rate = clk_wzrd_vco_mul_round_rate_f,
+	.set_rate = clk_wzrd_vco_mul_dynamic_reconfig_f,
+	.recalc_rate = clk_wzrd_vco_mul_recalc_rate_f,
+};
+
+static unsigned long clk_wzrd_vco_div_recalc_rate(struct clk_hw *hw,
+					       unsigned long parent_rate)
+{
+	u32 clk_cfg_reg0;
+	u32 divclk_divide;
+	u64 rate;
+
+	struct clk_wzrd *clk_wzrd = container_of(hw,
+						 struct clk_wzrd,
+						 vco_clk_div_hw);
+
+	clk_cfg_reg0 = readl(clk_wzrd->base + WZRD_CLK_CFG_REG(0));
+	divclk_divide = (clk_cfg_reg0 & WZRD_DIVCLK_DIVIDE_MASK) >>
+			 WZRD_DIVCLK_DIVIDE_SHIFT;
+
+	rate = parent_rate / divclk_divide;
+
+	return (unsigned long)rate;
+}
+
+static int clk_wzrd_vco_div_dynamic_reconfig(struct clk_hw *hw,
+					   unsigned long rate,
+					   unsigned long parent_rate)
+{
+	int err = 0;
+	u16 retries;
+	unsigned long flags = 0;
+	u32 clk_cfg_reg0, value;
+	u32 divclk_divide, clkfbout_mult, clkfbout_frac;
+
+	struct clk_wzrd *clk_wzrd = container_of(hw,
+						 struct clk_wzrd,
+						 vco_clk_div_hw);
+
+	divclk_divide = DIV_ROUND_CLOSEST(parent_rate, rate);
+
+	divclk_divide = clamp(divclk_divide,
+			      DIVCLK_DIVIDE_MIN,
+			      DIVCLK_DIVIDE_MAX);
+
+	/*
+	 * Read clkfbout_mult and clkfbout_frac
+	 * so they can be left unchanged
+	 */
+	clk_cfg_reg0 = readl(clk_wzrd->base + WZRD_CLK_CFG_REG(0));
+	clkfbout_mult = (clk_cfg_reg0 & WZRD_CLKFBOUT_MULT_MASK) >>
+			 WZRD_CLKFBOUT_MULT_SHIFT;
+	clkfbout_frac = (clk_cfg_reg0 & WZRD_CLKFBOUT_FRAC_MASK) >>
+			 WZRD_CLKFBOUT_FRAC_SHIFT;
+
+	value = clkfbout_frac << WZRD_CLKFBOUT_FRAC_SHIFT |
+		 clkfbout_mult << WZRD_CLKFBOUT_MULT_SHIFT |
+		 divclk_divide << WZRD_DIVCLK_DIVIDE_SHIFT;
+
+	if (clk_wzrd->lock)
+		spin_lock_irqsave(clk_wzrd->lock, flags);
+	else
+		__acquire(clk_wzrd->lock);
+
+	/* Write the configuration out */
+	writel(value, clk_wzrd->base + WZRD_CLK_CFG_REG(0));
+
+	/* Check status register */
+	retries = WZRD_DR_NUM_RETRIES;
+	while (retries--) {
+		if (readl(clk_wzrd->base + WZRD_DR_STATUS_REG_OFFSET) &
+							WZRD_DR_LOCK_BIT_MASK)
+			break;
+	}
+
+	if (!retries) {
+		err = -ETIMEDOUT;
+		goto err_reconfig;
+	}
+
+	/* Initiate reconfiguration */
+	writel(WZRD_DR_BEGIN_DYNA_RECONF,
+	       clk_wzrd->base + WZRD_DR_INIT_REG_OFFSET);
+
+	/* Check status register */
+	retries = WZRD_DR_NUM_RETRIES;
+	while (retries--) {
+		if (readl(clk_wzrd->base + WZRD_DR_STATUS_REG_OFFSET) &
+							WZRD_DR_LOCK_BIT_MASK)
+			break;
+	}
+
+	if (!retries)
+		err = -ETIMEDOUT;
+
+err_reconfig:
+	if (clk_wzrd->lock)
+		spin_unlock_irqrestore(clk_wzrd->lock, flags);
+	else
+		__release(clk_wzrd->lock);
+
+	return err;
+}
+
+static long clk_wzrd_vco_div_round_rate(struct clk_hw *hw, unsigned long rate,
+				      unsigned long *prate)
+{
+	return rate;
+}
+
+static const struct clk_ops clk_wzrd_vco_div_ops = {
+	.round_rate = clk_wzrd_vco_div_round_rate,
+	.set_rate = clk_wzrd_vco_div_dynamic_reconfig,
+	.recalc_rate = clk_wzrd_vco_div_recalc_rate,
+};
+
+static struct clk *clk_wzrd_register_divf(struct device *dev,
+					  const char *name,
+					  const char *parent_name,
+					  unsigned long flags,
+					  void __iomem *base, u16 offset,
+					  u8 shift, u8 width,
+					  u8 clk_divider_flags,
+					  const struct clk_div_table *table,
+					  spinlock_t *lock)
+{
+	struct clk_wzrd_divider *div;
+	struct clk_hw *hw;
+	struct clk_init_data init;
+	int ret;
+
+	if (clk_divider_flags & CLK_DIVIDER_HIWORD_MASK) {
+		if (width + shift > 16) {
+			pr_warn("divider value exceeds LOWORD field\n");
+			return ERR_PTR(-EINVAL);
+		}
+	}
+
+	/* allocate the divider */
+	div = kzalloc(sizeof(*div), GFP_KERNEL);
+	if (!div)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+
+	if (clk_divider_flags & CLK_DIVIDER_READ_ONLY)
+		init.ops = &clk_divider_ro_ops;
+	else
+		init.ops = &clk_wzrd_clk_divider_ops_f;
+
+	init.flags = flags;
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+
+	/* struct clk_divider assignments */
+	div->base = base;
+	div->offset = offset;
+	div->shift = shift;
+	div->width = width;
+	div->flags = clk_divider_flags;
+	div->lock = lock;
+	div->hw.init = &init;
+	div->table = table;
+
+	/* register the clock */
+	hw = &div->hw;
+	ret = clk_hw_register(dev, hw);
+	if (ret) {
+		kfree(div);
+		return ERR_PTR(ret);
+	}
+
+	return hw->clk;
+}
+
+static struct clk *clk_wzrd_register_divider(struct device *dev,
+					     const char *name,
+					     const char *parent_name,
+					     unsigned long flags,
+					     void __iomem *base, u16 offset,
+					     u8 shift, u8 width,
+					     u8 clk_divider_flags,
+					     const struct clk_div_table *table,
+					     spinlock_t *lock)
+{
+	struct clk_wzrd_divider *div;
+	struct clk_hw *hw;
+	struct clk_init_data init;
+	int ret;
+
+	if (clk_divider_flags & CLK_DIVIDER_HIWORD_MASK) {
+		if (width + shift > 16) {
+			pr_warn("divider value exceeds LOWORD field\n");
+			return ERR_PTR(-EINVAL);
+		}
+	}
+
+	/* allocate the divider */
+	div = kzalloc(sizeof(*div), GFP_KERNEL);
+	if (!div)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	if (clk_divider_flags & CLK_DIVIDER_READ_ONLY)
+		init.ops = &clk_divider_ro_ops;
+	else
+		init.ops = &clk_wzrd_clk_divider_ops;
+	init.flags = flags;
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+
+	/* struct clk_divider assignments */
+	div->base = base;
+	div->offset = offset;
+	div->shift = shift;
+	div->width = width;
+	div->flags = clk_divider_flags;
+	div->lock = lock;
+	div->hw.init = &init;
+	div->table = table;
+
+	/* register the clock */
+	hw = &div->hw;
+	ret = clk_hw_register(dev, hw);
+	if (ret) {
+		kfree(div);
+		hw = ERR_PTR(ret);
+	}
+
+	return hw->clk;
+}
+
+static int clk_wzrd_clk_notifier(struct notifier_block *nb, unsigned long event,
+				 void *data)
+{
+	unsigned long max;
+	struct clk_notifier_data *ndata = data;
+	struct clk_wzrd *clk_wzrd = to_clk_wzrd(nb);
+
+	if (clk_wzrd->suspended)
+		return NOTIFY_OK;
+
+	if (ndata->clk == clk_wzrd->clk_in1)
+		max = clk_wzrd_max_freq[clk_wzrd->speed_grade - 1];
+	else if (ndata->clk == clk_wzrd->axi_clk)
+		max = WZRD_ACLK_MAX_FREQ;
+	else
+		return NOTIFY_DONE;	/* should never happen */
+
+	switch (event) {
+	case PRE_RATE_CHANGE:
+		if (ndata->new_rate > max)
+			return NOTIFY_BAD;
+		return NOTIFY_OK;
+	case POST_RATE_CHANGE:
+	case ABORT_RATE_CHANGE:
+	default:
+		return NOTIFY_DONE;
+	}
+}
+
+static int __maybe_unused clk_wzrd_suspend(struct device *dev)
+{
+	struct clk_wzrd *clk_wzrd = dev_get_drvdata(dev);
+
+	clk_disable_unprepare(clk_wzrd->axi_clk);
+	clk_wzrd->suspended = true;
+
+	return 0;
+}
+
+static int __maybe_unused clk_wzrd_resume(struct device *dev)
+{
+	int ret;
+	struct clk_wzrd *clk_wzrd = dev_get_drvdata(dev);
+
+	ret = clk_prepare_enable(clk_wzrd->axi_clk);
+	if (ret) {
+		dev_err(dev, "unable to enable s_axi_aclk\n");
+		return ret;
+	}
+
+	clk_wzrd->suspended = false;
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(clk_wzrd_dev_pm_ops, clk_wzrd_suspend,
+			 clk_wzrd_resume);
+
+static int clk_wzrd_probe(struct platform_device *pdev)
+{
+	int i, ret;
+	unsigned long rate;
+	struct clk_wzrd *clk_wzrd;
+	struct resource *mem;
+	int outputs;
+	unsigned long flags = 0;
+	struct device_node *np = pdev->dev.of_node;
+
+	const char *clk_in_name = NULL;
+	const char *clk_vco_div_name = NULL, *clk_vco_mul_name = NULL;
+	struct clk_init_data init;
+
+	clk_wzrd = devm_kzalloc(&pdev->dev, sizeof(*clk_wzrd), GFP_KERNEL);
+	if (!clk_wzrd)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, clk_wzrd);
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	clk_wzrd->base = devm_ioremap_resource(&pdev->dev, mem);
+	if (IS_ERR(clk_wzrd->base))
+		return PTR_ERR(clk_wzrd->base);
+
+	clk_wzrd->lock = &clkwzrd_lock;
+
+	ret = of_property_read_u32(np, "speed-grade", &clk_wzrd->speed_grade);
+	if (!ret) {
+		if (clk_wzrd->speed_grade < 1 || clk_wzrd->speed_grade > 3) {
+			dev_warn(&pdev->dev, "invalid speed grade '%d'\n",
+				 clk_wzrd->speed_grade);
+			clk_wzrd->speed_grade = 0;
+		}
+	}
+
+	clk_wzrd->clk_in1 = devm_clk_get(&pdev->dev, "clk_in1");
+	if (IS_ERR(clk_wzrd->clk_in1)) {
+		if (clk_wzrd->clk_in1 != ERR_PTR(-EPROBE_DEFER))
+			dev_err(&pdev->dev, "clk_in1 not found\n");
+		return PTR_ERR(clk_wzrd->clk_in1);
+	}
+
+	clk_wzrd->axi_clk = devm_clk_get(&pdev->dev, "s_axi_aclk");
+	if (IS_ERR(clk_wzrd->axi_clk)) {
+		if (clk_wzrd->axi_clk != ERR_PTR(-EPROBE_DEFER))
+			dev_err(&pdev->dev, "s_axi_aclk not found\n");
+		return PTR_ERR(clk_wzrd->axi_clk);
+	}
+	ret = clk_prepare_enable(clk_wzrd->axi_clk);
+	if (ret) {
+		dev_err(&pdev->dev, "enabling s_axi_aclk failed\n");
+		return ret;
+	}
+	rate = clk_get_rate(clk_wzrd->axi_clk);
+	if (rate > WZRD_ACLK_MAX_FREQ) {
+		dev_err(&pdev->dev, "s_axi_aclk frequency (%lu) too high\n",
+			rate);
+		ret = -EINVAL;
+		goto err_disable_clk;
+	}
+
+	ret = clk_prepare_enable(clk_wzrd->clk_in1);
+	if (ret) {
+		dev_err(&pdev->dev, "enabling clk_in1 failed\n");
+		return ret;
+	}
+
+	/* Only allow the parent rate to be set if there is a single output */
+	outputs = of_property_count_strings(np, "clock-output-names");
+	if (outputs == 1)
+		flags = CLK_SET_RATE_PARENT;
+
+	/* Write the divider clock name */
+	clk_vco_div_name = kasprintf(GFP_KERNEL, "%s_div",
+				     dev_name(&pdev->dev));
+
+	if (!clk_vco_div_name) {
+		ret = -ENOMEM;
+		goto err_disable_clk;
+	}
+
+	/* Write the multiplier clock name */
+	clk_vco_mul_name = kasprintf(GFP_KERNEL, "%s_mul",
+				     dev_name(&pdev->dev));
+	if (!clk_vco_mul_name) {
+		ret = -ENOMEM;
+		kfree(clk_vco_div_name);
+		goto err_disable_clk;
+	}
+
+	/* setup and register the VCO divider clock */
+	init.name = clk_vco_div_name;
+	init.ops = &clk_wzrd_vco_div_ops;
+	clk_in_name = __clk_get_name(clk_wzrd->clk_in1);
+	dev_info(&pdev->dev, "clk_in_name: %s\n", clk_in_name);
+	init.parent_names = &clk_in_name;
+	init.num_parents = 1;
+	init.flags = 0;
+
+	clk_wzrd->vco_clk_div_hw.init = &init;
+	ret = clk_hw_register(&pdev->dev, &clk_wzrd->vco_clk_div_hw);
+	if (ret)
+		goto err_disable_clk_free_names;
+
+	/* setup and register the VCO multiplier clock */
+	init.name = clk_vco_mul_name;
+	init.ops = &clk_wzrd_vco_mul_ops_f;
+	init.parent_names = &clk_vco_div_name;
+	init.num_parents = 1;
+	/* needs CLK_SET_RATE_PARENT if set above */
+	init.flags = flags;
+
+	clk_wzrd->vco_clk_mul_hw.init = &init;
+	ret = clk_hw_register(&pdev->dev, &clk_wzrd->vco_clk_mul_hw);
+	if (ret)
+		goto err_rm_hw_div_clk;
+
+	/* register div per output */
+	for (i = outputs - 1; i >= 0 ; i--) {
+		const char *clkout_name;
+
+		if (of_property_read_string_index(np, "clock-output-names", i,
+						  &clkout_name)) {
+			dev_err(&pdev->dev,
+				"clock output name not specified\n");
+			ret = -EINVAL;
+			goto err_rm_hw_clks;
+		}
+		if (!i)
+			clk_wzrd->clkout[i] = clk_wzrd_register_divf
+				(&pdev->dev, clkout_name,
+				clk_vco_mul_name, flags,
+				clk_wzrd->base, (WZRD_CLK_CFG_REG(2) + i * 12),
+				WZRD_CLKOUT_DIVIDE_SHIFT,
+				WZRD_CLKOUT_DIVIDE_WIDTH,
+				CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
+				NULL, &clkwzrd_lock);
+		else
+			clk_wzrd->clkout[i] = clk_wzrd_register_divider
+				(&pdev->dev, clkout_name,
+				clk_vco_mul_name, 0,
+				clk_wzrd->base, (WZRD_CLK_CFG_REG(2) + i * 12),
+				WZRD_CLKOUT_DIVIDE_SHIFT,
+				WZRD_CLKOUT_DIVIDE_WIDTH,
+				CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
+				NULL, &clkwzrd_lock);
+		if (IS_ERR(clk_wzrd->clkout[i])) {
+			int j;
+
+			for (j = i + 1; j < outputs; j++)
+				clk_unregister(clk_wzrd->clkout[j]);
+			dev_err(&pdev->dev,
+				"unable to register divider clock\n");
+			ret = PTR_ERR(clk_wzrd->clkout[i]);
+			goto err_rm_hw_clks;
+		}
+	}
+
+	kfree(clk_vco_div_name);
+	kfree(clk_vco_mul_name);
+
+	clk_wzrd->clk_data.clks = clk_wzrd->clkout;
+	clk_wzrd->clk_data.clk_num = ARRAY_SIZE(clk_wzrd->clkout);
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_wzrd->clk_data);
+
+	if (clk_wzrd->speed_grade) {
+		clk_wzrd->nb.notifier_call = clk_wzrd_clk_notifier;
+
+		ret = clk_notifier_register(clk_wzrd->clk_in1,
+					    &clk_wzrd->nb);
+		if (ret)
+			dev_warn(&pdev->dev,
+				 "unable to register clock notifier\n");
+
+		ret = clk_notifier_register(clk_wzrd->axi_clk, &clk_wzrd->nb);
+		if (ret)
+			dev_warn(&pdev->dev,
+				 "unable to register clock notifier\n");
+	}
+
+	return 0;
+
+err_rm_hw_clks:
+	clk_unregister(clk_wzrd->vco_clk_mul_hw.clk);
+err_rm_hw_div_clk:
+	clk_unregister(clk_wzrd->vco_clk_div_hw.clk);
+err_disable_clk_free_names:
+	kfree(clk_vco_div_name);
+	kfree(clk_vco_mul_name);
+err_disable_clk:
+	clk_disable_unprepare(clk_wzrd->axi_clk);
+
+	return ret;
+}
+
+static int clk_wzrd_remove(struct platform_device *pdev)
+{
+	int i;
+	struct clk_wzrd *clk_wzrd = platform_get_drvdata(pdev);
+
+	of_clk_del_provider(pdev->dev.of_node);
+
+	for (i = 0; i < WZRD_NUM_OUTPUTS; i++)
+		clk_unregister(clk_wzrd->clkout[i]);
+
+	clk_unregister(clk_wzrd->vco_clk_div_hw.clk);
+	clk_unregister(clk_wzrd->vco_clk_mul_hw.clk);
+
+	if (clk_wzrd->speed_grade) {
+		clk_notifier_unregister(clk_wzrd->axi_clk, &clk_wzrd->nb);
+		clk_notifier_unregister(clk_wzrd->clk_in1, &clk_wzrd->nb);
+	}
+
+	clk_disable_unprepare(clk_wzrd->axi_clk);
+
+	return 0;
+}
+
+static const struct of_device_id clk_wzrd_ids[] = {
+	{ .compatible = "xlnx,clocking-wizard" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, clk_wzrd_ids);
+
+static struct platform_driver clk_wzrd_driver = {
+	.driver = {
+		.name = "clk-wizard",
+		.of_match_table = clk_wzrd_ids,
+		.pm = &clk_wzrd_dev_pm_ops,
+	},
+	.probe = clk_wzrd_probe,
+	.remove = clk_wzrd_remove,
+};
+module_platform_driver(clk_wzrd_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Soeren Brinkmann <soren.brinkmann@xilinx.com");
+MODULE_DESCRIPTION("Driver for the Xilinx Clocking Wizard IP core");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/clk.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/clk.c
@@ -37,7 +37,11 @@
 static HLIST_HEAD(clk_orphan_list);
 static LIST_HEAD(clk_notifier_list);
 
-static struct hlist_head *all_lists[] = {
+/* List of registered clks that use runtime PM */
+static HLIST_HEAD(clk_rpm_list);
+static DEFINE_MUTEX(clk_rpm_list_lock);
+
+static const struct hlist_head *all_lists[] = {
 	&clk_root_list,
 	&clk_orphan_list,
 	NULL,
@@ -59,6 +63,7 @@
 	struct clk_hw		*hw;
 	struct module		*owner;
 	struct device		*dev;
+	struct hlist_node	rpm_node;
 	struct device_node	*of_node;
 	struct clk_core		*parent;
 	struct clk_parent_map	*parents;
@@ -114,7 +119,11 @@
 		return 0;
 
 	ret = pm_runtime_get_sync(core->dev);
-	return ret < 0 ? ret : 0;
+	if (ret < 0) {
+		pm_runtime_put_noidle(core->dev);
+		return ret;
+	}
+	return 0;
 }
 
 static void clk_pm_runtime_put(struct clk_core *core)
@@ -125,6 +134,89 @@
 	pm_runtime_put_sync(core->dev);
 }
 
+/**
+ * clk_pm_runtime_get_all() - Runtime "get" all clk provider devices
+ *
+ * Call clk_pm_runtime_get() on all runtime PM enabled clks in the clk tree so
+ * that disabling unused clks avoids a deadlock where a device is runtime PM
+ * resuming/suspending and the runtime PM callback is trying to grab the
+ * prepare_lock for something like clk_prepare_enable() while
+ * clk_disable_unused_subtree() holds the prepare_lock and is trying to runtime
+ * PM resume/suspend the device as well.
+ *
+ * Context: Acquires the 'clk_rpm_list_lock' and returns with the lock held on
+ * success. Otherwise the lock is released on failure.
+ *
+ * Return: 0 on success, negative errno otherwise.
+ */
+static int clk_pm_runtime_get_all(void)
+{
+	int ret;
+	struct clk_core *core, *failed;
+
+	/*
+	 * Grab the list lock to prevent any new clks from being registered
+	 * or unregistered until clk_pm_runtime_put_all().
+	 */
+	mutex_lock(&clk_rpm_list_lock);
+
+	/*
+	 * Runtime PM "get" all the devices that are needed for the clks
+	 * currently registered. Do this without holding the prepare_lock, to
+	 * avoid the deadlock.
+	 */
+	hlist_for_each_entry(core, &clk_rpm_list, rpm_node) {
+		ret = clk_pm_runtime_get(core);
+		if (ret) {
+			failed = core;
+			pr_err("clk: Failed to runtime PM get '%s' for clk '%s'\n",
+			       dev_name(failed->dev), failed->name);
+			goto err;
+		}
+	}
+
+	return 0;
+
+err:
+	hlist_for_each_entry(core, &clk_rpm_list, rpm_node) {
+		if (core == failed)
+			break;
+
+		clk_pm_runtime_put(core);
+	}
+	mutex_unlock(&clk_rpm_list_lock);
+
+	return ret;
+}
+
+/**
+ * clk_pm_runtime_put_all() - Runtime "put" all clk provider devices
+ *
+ * Put the runtime PM references taken in clk_pm_runtime_get_all() and release
+ * the 'clk_rpm_list_lock'.
+ */
+static void clk_pm_runtime_put_all(void)
+{
+	struct clk_core *core;
+
+	hlist_for_each_entry(core, &clk_rpm_list, rpm_node)
+		clk_pm_runtime_put(core);
+	mutex_unlock(&clk_rpm_list_lock);
+}
+
+static void clk_pm_runtime_init(struct clk_core *core)
+{
+	struct device *dev = core->dev;
+
+	if (dev && pm_runtime_enabled(dev)) {
+		core->rpm_enabled = true;
+
+		mutex_lock(&clk_rpm_list_lock);
+		hlist_add_head(&core->rpm_node, &clk_rpm_list);
+		mutex_unlock(&clk_rpm_list_lock);
+	}
+}
+
 /***           locking             ***/
 static void clk_prepare_lock(void)
 {
@@ -247,6 +339,17 @@
 		}
 	}
 
+	/*
+	 * This could be called with the enable lock held, or from atomic
+	 * context. If the parent isn't enabled already, we can't do
+	 * anything here. We can also assume this clock isn't enabled.
+	 */
+	if ((core->flags & CLK_OPS_PARENT_ENABLE) && core->parent)
+		if (!clk_core_is_enabled(core->parent)) {
+			ret = false;
+			goto done;
+		}
+
 	ret = core->ops->is_enabled(core->hw);
 done:
 	if (core->rpm_enabled)
@@ -410,6 +513,9 @@
 	if (IS_ERR(hw))
 		return ERR_CAST(hw);
 
+	if (!hw)
+		return NULL;
+
 	return hw->core;
 }
 
@@ -633,6 +739,24 @@
 		*max_rate = min(*max_rate, clk_user->max_rate);
 }
 
+static bool clk_core_check_boundaries(struct clk_core *core,
+				      unsigned long min_rate,
+				      unsigned long max_rate)
+{
+	struct clk *user;
+
+	lockdep_assert_held(&prepare_lock);
+
+	if (min_rate > core->max_rate || max_rate < core->min_rate)
+		return false;
+
+	hlist_for_each_entry(user, &core->clks, clks_node)
+		if (min_rate > user->max_rate || max_rate < user->min_rate)
+			return false;
+
+	return true;
+}
+
 void clk_hw_set_rate_range(struct clk_hw *hw, unsigned long min_rate,
 			   unsigned long max_rate)
 {
@@ -802,6 +926,25 @@
 }
 EXPORT_SYMBOL_GPL(clk_rate_exclusive_get);
 
+static void devm_clk_rate_exclusive_put(void *data)
+{
+	struct clk *clk = data;
+
+	clk_rate_exclusive_put(clk);
+}
+
+int devm_clk_rate_exclusive_get(struct device *dev, struct clk *clk)
+{
+	int ret;
+
+	ret = clk_rate_exclusive_get(clk);
+	if (ret)
+		return ret;
+
+	return devm_add_action_or_reset(dev, devm_clk_rate_exclusive_put, clk);
+}
+EXPORT_SYMBOL_GPL(devm_clk_rate_exclusive_get);
+
 static void clk_core_unprepare(struct clk_core *core)
 {
 	lockdep_assert_held(&prepare_lock);
@@ -830,10 +973,9 @@
 	if (core->ops->unprepare)
 		core->ops->unprepare(core->hw);
 
-	clk_pm_runtime_put(core);
-
 	trace_clk_unprepare_complete(core);
 	clk_core_unprepare(core->parent);
+	clk_pm_runtime_put(core);
 }
 
 static void clk_core_unprepare_lock(struct clk_core *core)
@@ -1202,9 +1344,6 @@
 	if (core->flags & CLK_IGNORE_UNUSED)
 		return;
 
-	if (clk_pm_runtime_get(core))
-		return;
-
 	if (clk_core_is_prepared(core)) {
 		trace_clk_unprepare(core);
 		if (core->ops->unprepare_unused)
@@ -1213,8 +1352,6 @@
 			core->ops->unprepare(core->hw);
 		trace_clk_unprepare_complete(core);
 	}
-
-	clk_pm_runtime_put(core);
 }
 
 static void clk_disable_unused_subtree(struct clk_core *core)
@@ -1230,9 +1367,6 @@
 	if (core->flags & CLK_OPS_PARENT_ENABLE)
 		clk_core_prepare_enable(core->parent);
 
-	if (clk_pm_runtime_get(core))
-		goto unprepare_out;
-
 	flags = clk_enable_lock();
 
 	if (core->enable_count)
@@ -1257,8 +1391,6 @@
 
 unlock_out:
 	clk_enable_unlock(flags);
-	clk_pm_runtime_put(core);
-unprepare_out:
 	if (core->flags & CLK_OPS_PARENT_ENABLE)
 		clk_core_disable_unprepare(core->parent);
 }
@@ -1274,12 +1406,22 @@
 static int clk_disable_unused(void)
 {
 	struct clk_core *core;
+	int ret;
 
 	if (clk_ignore_unused) {
 		pr_warn("clk: Not disabling unused clocks\n");
 		return 0;
 	}
 
+	pr_info("clk: Disabling unused clocks\n");
+
+	ret = clk_pm_runtime_get_all();
+	if (ret)
+		return ret;
+	/*
+	 * Grab the prepare lock to keep the clk topology stable while iterating
+	 * over clks.
+	 */
 	clk_prepare_lock();
 
 	hlist_for_each_entry(core, &clk_root_list, child_node)
@@ -1296,6 +1438,8 @@
 
 	clk_prepare_unlock();
 
+	clk_pm_runtime_put_all();
+
 	return 0;
 }
 late_initcall_sync(clk_disable_unused);
@@ -2302,6 +2446,11 @@
 	clk->min_rate = min;
 	clk->max_rate = max;
 
+	if (!clk_core_check_boundaries(clk->core, min, max)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
 	rate = clk_core_get_rate_nolock(clk->core);
 	if (rate < min || rate > max) {
 		/*
@@ -2330,6 +2479,7 @@
 		}
 	}
 
+out:
 	if (clk->exclusive_count)
 		clk_core_rate_protect(clk->core);
 
@@ -2642,12 +2792,14 @@
 {
 	int ret;
 
-	clk_prepare_lock();
+	lockdep_assert_held(&prepare_lock);
+	if (!core->ops->get_phase)
+		return 0;
+
 	/* Always try to update cached phase if possible */
-	if (core->ops->get_phase)
-		core->phase = core->ops->get_phase(core->hw);
-	ret = core->phase;
-	clk_prepare_unlock();
+	ret = core->ops->get_phase(core->hw);
+	if (ret >= 0)
+		core->phase = ret;
 
 	return ret;
 }
@@ -2661,10 +2813,16 @@
  */
 int clk_get_phase(struct clk *clk)
 {
+	int ret;
+
 	if (!clk)
 		return 0;
 
-	return clk_core_get_phase(clk->core);
+	clk_prepare_lock();
+	ret = clk_core_get_phase(clk->core);
+	clk_prepare_unlock();
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(clk_get_phase);
 
@@ -2878,13 +3036,21 @@
 static void clk_summary_show_one(struct seq_file *s, struct clk_core *c,
 				 int level)
 {
-	seq_printf(s, "%*s%-*s %7d %8d %8d %11lu %10lu %5d %6d\n",
+	int phase;
+
+	seq_printf(s, "%*s%-*s %7d %8d %8d %11lu %10lu ",
 		   level * 3 + 1, "",
 		   30 - level * 3, c->name,
 		   c->enable_count, c->prepare_count, c->protect_count,
-		   clk_core_get_rate(c), clk_core_get_accuracy(c),
-		   clk_core_get_phase(c),
-		   clk_core_get_scaled_duty_cycle(c, 100000));
+		   clk_core_get_rate(c), clk_core_get_accuracy(c));
+
+	phase = clk_core_get_phase(c);
+	if (phase >= 0)
+		seq_printf(s, "%5d", phase);
+	else
+		seq_puts(s, "-----");
+
+	seq_printf(s, " %6d\n", clk_core_get_scaled_duty_cycle(c, 100000));
 }
 
 static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c,
@@ -2921,6 +3087,7 @@
 
 static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level)
 {
+	int phase;
 	unsigned long min_rate, max_rate;
 
 	clk_core_get_boundaries(c, &min_rate, &max_rate);
@@ -2934,7 +3101,9 @@
 	seq_printf(s, "\"min_rate\": %lu,", min_rate);
 	seq_printf(s, "\"max_rate\": %lu,", max_rate);
 	seq_printf(s, "\"accuracy\": %lu,", clk_core_get_accuracy(c));
-	seq_printf(s, "\"phase\": %d,", clk_core_get_phase(c));
+	phase = clk_core_get_phase(c);
+	if (phase >= 0)
+		seq_printf(s, "\"phase\": %d,", phase);
 	seq_printf(s, "\"duty_cycle\": %u",
 		   clk_core_get_scaled_duty_cycle(c, 100000));
 }
@@ -3023,6 +3192,7 @@
 				 unsigned int i, char terminator)
 {
 	struct clk_core *parent;
+	const char *name = NULL;
 
 	/*
 	 * Go through the following options to fetch a parent's name.
@@ -3037,18 +3207,20 @@
 	 * registered (yet).
 	 */
 	parent = clk_core_get_parent_by_index(core, i);
-	if (parent)
+	if (parent) {
 		seq_puts(s, parent->name);
-	else if (core->parents[i].name)
+	} else if (core->parents[i].name) {
 		seq_puts(s, core->parents[i].name);
-	else if (core->parents[i].fw_name)
+	} else if (core->parents[i].fw_name) {
 		seq_printf(s, "<%s>(fw)", core->parents[i].fw_name);
-	else if (core->parents[i].index >= 0)
-		seq_puts(s,
-			 of_clk_get_parent_name(core->of_node,
-						core->parents[i].index));
-	else
-		seq_puts(s, "(missing)");
+	} else {
+		if (core->parents[i].index >= 0)
+			name = of_clk_get_parent_name(core->of_node, core->parents[i].index);
+		if (!name)
+			name = "(missing)";
+
+		seq_puts(s, name);
+	}
 
 	seq_putc(s, terminator);
 }
@@ -3231,6 +3403,47 @@
 }
 #endif
 
+static void clk_core_reparent_orphans_nolock(void)
+{
+	struct clk_core *orphan;
+	struct hlist_node *tmp2;
+
+	/*
+	 * walk the list of orphan clocks and reparent any that newly finds a
+	 * parent.
+	 */
+	hlist_for_each_entry_safe(orphan, tmp2, &clk_orphan_list, child_node) {
+		struct clk_core *parent = __clk_init_parent(orphan);
+
+		/*
+		 * We need to use __clk_set_parent_before() and _after() to
+		 * to properly migrate any prepare/enable count of the orphan
+		 * clock. This is important for CLK_IS_CRITICAL clocks, which
+		 * are enabled during init but might not have a parent yet.
+		 */
+		if (parent) {
+			/* update the clk tree topology */
+			__clk_set_parent_before(orphan, parent);
+			__clk_set_parent_after(orphan, parent, NULL);
+			__clk_recalc_accuracies(orphan);
+			__clk_recalc_rates(orphan, 0);
+
+			/*
+			 * __clk_init_parent() will set the initial req_rate to
+			 * 0 if the clock doesn't have clk_ops::recalc_rate and
+			 * is an orphan when it's registered.
+			 *
+			 * 'req_rate' is used by clk_set_rate_range() and
+			 * clk_put() to trigger a clk_set_rate() call whenever
+			 * the boundaries are modified. Let's make sure
+			 * 'req_rate' is set to something non-zero so that
+			 * clk_set_rate_range() doesn't drop the frequency.
+			 */
+			orphan->req_rate = orphan->rate;
+		}
+	}
+}
+
 /**
  * __clk_core_init - initialize the data structures in a struct clk_core
  * @core:	clk_core being initialized
@@ -3241,8 +3454,6 @@
 static int __clk_core_init(struct clk_core *core)
 {
 	int ret;
-	struct clk_core *orphan;
-	struct hlist_node *tmp2;
 	unsigned long rate;
 
 	if (!core)
@@ -3250,6 +3461,14 @@
 
 	clk_prepare_lock();
 
+	/*
+	 * Set hw->core after grabbing the prepare_lock to synchronize with
+	 * callers of clk_core_fill_parent_index() where we treat hw->core
+	 * being NULL as the clk not being registered yet. This is crucial so
+	 * that clks aren't parented until their parent is fully registered.
+	 */
+	core->hw->core = core;
+
 	ret = clk_pm_runtime_get(core);
 	if (ret)
 		goto unlock;
@@ -3294,6 +3513,21 @@
 		goto out;
 	}
 
+	/*
+	 * optional platform-specific magic
+	 *
+	 * The .init callback is not used by any of the basic clock types, but
+	 * exists for weird hardware that must perform initialization magic.
+	 * Please consider other ways of solving initialization problems before
+	 * using this callback, as its use is discouraged.
+	 *
+	 * If it exist, this callback should called before any other callback of
+	 * the clock
+	 */
+	if (core->ops->init)
+		core->ops->init(core->hw);
+
+
 	core->parent = __clk_init_parent(core);
 
 	/*
@@ -3319,17 +3553,6 @@
 	}
 
 	/*
-	 * optional platform-specific magic
-	 *
-	 * The .init callback is not used by any of the basic clock types, but
-	 * exists for weird hardware that must perform initialization magic.
-	 * Please consider other ways of solving initialization problems before
-	 * using this callback, as its use is discouraged.
-	 */
-	if (core->ops->init)
-		core->ops->init(core->hw);
-
-	/*
 	 * Set clk's accuracy.  The preferred method is to use
 	 * .recalc_accuracy. For simple clocks and lazy developers the default
 	 * fallback is to use the parent's accuracy.  If a clock doesn't have a
@@ -3345,14 +3568,11 @@
 		core->accuracy = 0;
 
 	/*
-	 * Set clk's phase.
+	 * Set clk's phase by clk_core_get_phase() caching the phase.
 	 * Since a phase is by definition relative to its parent, just
 	 * query the current clock phase, or just assume it's in phase.
 	 */
-	if (core->ops->get_phase)
-		core->phase = core->ops->get_phase(core->hw);
-	else
-		core->phase = 0;
+	clk_core_get_phase(core);
 
 	/*
 	 * Set clk's duty cycle.
@@ -3382,39 +3602,28 @@
 	if (core->flags & CLK_IS_CRITICAL) {
 		unsigned long flags;
 
-		clk_core_prepare(core);
+		ret = clk_core_prepare(core);
+		if (ret)
+			goto out;
 
 		flags = clk_enable_lock();
-		clk_core_enable(core);
+		ret = clk_core_enable(core);
 		clk_enable_unlock(flags);
-	}
-
-	/*
-	 * walk the list of orphan clocks and reparent any that newly finds a
-	 * parent.
-	 */
-	hlist_for_each_entry_safe(orphan, tmp2, &clk_orphan_list, child_node) {
-		struct clk_core *parent = __clk_init_parent(orphan);
-
-		/*
-		 * We need to use __clk_set_parent_before() and _after() to
-		 * to properly migrate any prepare/enable count of the orphan
-		 * clock. This is important for CLK_IS_CRITICAL clocks, which
-		 * are enabled during init but might not have a parent yet.
-		 */
-		if (parent) {
-			/* update the clk tree topology */
-			__clk_set_parent_before(orphan, parent);
-			__clk_set_parent_after(orphan, parent, NULL);
-			__clk_recalc_accuracies(orphan);
-			__clk_recalc_rates(orphan, 0);
+		if (ret) {
+			clk_core_unprepare(core);
+			goto out;
 		}
 	}
 
-	kref_init(&core->ref);
+	clk_core_reparent_orphans_nolock();
 out:
 	clk_pm_runtime_put(core);
 unlock:
+	if (ret) {
+		hlist_del_init(&core->child_node);
+		core->hw->core = NULL;
+	}
+
 	clk_prepare_unlock();
 
 	if (!ret)
@@ -3616,6 +3825,22 @@
 	kfree(core->parents);
 }
 
+/* Free memory allocated for a struct clk_core */
+static void __clk_release(struct kref *ref)
+{
+	struct clk_core *core = container_of(ref, struct clk_core, ref);
+
+	if (core->rpm_enabled) {
+		mutex_lock(&clk_rpm_list_lock);
+		hlist_del(&core->rpm_node);
+		mutex_unlock(&clk_rpm_list_lock);
+	}
+
+	clk_core_free_parent_map(core);
+	kfree_const(core->name);
+	kfree(core);
+}
+
 static struct clk *
 __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
 {
@@ -3636,6 +3861,8 @@
 		goto fail_out;
 	}
 
+	kref_init(&core->ref);
+
 	core->name = kstrdup_const(init->name, GFP_KERNEL);
 	if (!core->name) {
 		ret = -ENOMEM;
@@ -3648,9 +3875,8 @@
 	}
 	core->ops = init->ops;
 
-	if (dev && pm_runtime_enabled(dev))
-		core->rpm_enabled = true;
 	core->dev = dev;
+	clk_pm_runtime_init(core);
 	core->of_node = np;
 	if (dev && dev->driver)
 		core->owner = dev->driver->owner;
@@ -3659,7 +3885,6 @@
 	core->num_parents = init->num_parents;
 	core->min_rate = 0;
 	core->max_rate = ULONG_MAX;
-	hw->core = core;
 
 	ret = clk_core_populate_parent_map(core, init);
 	if (ret)
@@ -3677,7 +3902,7 @@
 		goto fail_create_clk;
 	}
 
-	clk_core_link_consumer(hw->core, hw->clk);
+	clk_core_link_consumer(core, hw->clk);
 
 	ret = __clk_core_init(core);
 	if (!ret)
@@ -3691,17 +3916,37 @@
 	hw->clk = NULL;
 
 fail_create_clk:
-	clk_core_free_parent_map(core);
 fail_parents:
 fail_ops:
-	kfree_const(core->name);
 fail_name:
-	kfree(core);
+	kref_put(&core->ref, __clk_release);
 fail_out:
 	return ERR_PTR(ret);
 }
 
 /**
+ * dev_or_parent_of_node() - Get device node of @dev or @dev's parent
+ * @dev: Device to get device node of
+ *
+ * Return: device node pointer of @dev, or the device node pointer of
+ * @dev->parent if dev doesn't have a device node, or NULL if neither
+ * @dev or @dev->parent have a device node.
+ */
+static struct device_node *dev_or_parent_of_node(struct device *dev)
+{
+	struct device_node *np;
+
+	if (!dev)
+		return NULL;
+
+	np = dev_of_node(dev);
+	if (!np)
+		np = dev_of_node(dev->parent);
+
+	return np;
+}
+
+/**
  * clk_register - allocate a new clock, register it and return an opaque cookie
  * @dev: device that is registering this clock
  * @hw: link to hardware-specific clock data
@@ -3716,7 +3961,7 @@
  */
 struct clk *clk_register(struct device *dev, struct clk_hw *hw)
 {
-	return __clk_register(dev, dev_of_node(dev), hw);
+	return __clk_register(dev, dev_or_parent_of_node(dev), hw);
 }
 EXPORT_SYMBOL_GPL(clk_register);
 
@@ -3732,7 +3977,8 @@
  */
 int clk_hw_register(struct device *dev, struct clk_hw *hw)
 {
-	return PTR_ERR_OR_ZERO(__clk_register(dev, dev_of_node(dev), hw));
+	return PTR_ERR_OR_ZERO(__clk_register(dev, dev_or_parent_of_node(dev),
+			       hw));
 }
 EXPORT_SYMBOL_GPL(clk_hw_register);
 
@@ -3753,18 +3999,6 @@
 }
 EXPORT_SYMBOL_GPL(of_clk_hw_register);
 
-/* Free memory allocated for a clock. */
-static void __clk_release(struct kref *ref)
-{
-	struct clk_core *core = container_of(ref, struct clk_core, ref);
-
-	lockdep_assert_held(&prepare_lock);
-
-	clk_core_free_parent_map(core);
-	kfree_const(core->name);
-	kfree(core);
-}
-
 /*
  * Empty clk_ops for unregistered clocks. These are used temporarily
  * after clk_unregister() was called on a clock and until last clock
@@ -3817,7 +4051,7 @@
 /* Remove this clk from all parent caches */
 static void clk_core_evict_parent_cache(struct clk_core *core)
 {
-	struct hlist_head **lists;
+	const struct hlist_head **lists;
 	struct clk_core *root;
 
 	lockdep_assert_held(&prepare_lock);
@@ -3846,7 +4080,8 @@
 	if (clk->core->ops == &clk_nodrv_ops) {
 		pr_err("%s: unregistered clock: %s\n", __func__,
 		       clk->core->name);
-		goto unlock;
+		clk_prepare_unlock();
+		return;
 	}
 	/*
 	 * Assign empty clock ops for consumers that might still hold
@@ -3877,10 +4112,10 @@
 	if (clk->core->protect_count)
 		pr_warn("%s: unregistering protected clock: %s\n",
 					__func__, clk->core->name);
+	clk_prepare_unlock();
 
 	kref_put(&clk->core->ref, __clk_release);
-unlock:
-	clk_prepare_unlock();
+	free_clk(clk);
 }
 EXPORT_SYMBOL_GPL(clk_unregister);
 
@@ -4042,13 +4277,11 @@
 	    clk->max_rate < clk->core->req_rate)
 		clk_core_set_rate_nolock(clk->core, clk->core->req_rate);
 
-	owner = clk->core->owner;
-	kref_put(&clk->core->ref, __clk_release);
-
 	clk_prepare_unlock();
 
+	owner = clk->core->owner;
+	kref_put(&clk->core->ref, __clk_release);
 	module_put(owner);
-
 	free_clk(clk);
 }
 
@@ -4087,20 +4320,19 @@
 	/* search the list of notifiers for this clk */
 	list_for_each_entry(cn, &clk_notifier_list, node)
 		if (cn->clk == clk)
-			break;
+			goto found;
 
 	/* if clk wasn't in the notifier list, allocate new clk_notifier */
-	if (cn->clk != clk) {
-		cn = kzalloc(sizeof(*cn), GFP_KERNEL);
-		if (!cn)
-			goto out;
+	cn = kzalloc(sizeof(*cn), GFP_KERNEL);
+	if (!cn)
+		goto out;
 
-		cn->clk = clk;
-		srcu_init_notifier_head(&cn->notifier_head);
+	cn->clk = clk;
+	srcu_init_notifier_head(&cn->notifier_head);
 
-		list_add(&cn->node, &clk_notifier_list);
-	}
+	list_add(&cn->node, &clk_notifier_list);
 
+found:
 	ret = srcu_notifier_chain_register(&cn->notifier_head, nb);
 
 	clk->core->notifier_count++;
@@ -4125,32 +4357,28 @@
  */
 int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb)
 {
-	struct clk_notifier *cn = NULL;
-	int ret = -EINVAL;
+	struct clk_notifier *cn;
+	int ret = -ENOENT;
 
 	if (!clk || !nb)
 		return -EINVAL;
 
 	clk_prepare_lock();
 
-	list_for_each_entry(cn, &clk_notifier_list, node)
-		if (cn->clk == clk)
-			break;
-
-	if (cn->clk == clk) {
-		ret = srcu_notifier_chain_unregister(&cn->notifier_head, nb);
+	list_for_each_entry(cn, &clk_notifier_list, node) {
+		if (cn->clk == clk) {
+			ret = srcu_notifier_chain_unregister(&cn->notifier_head, nb);
 
-		clk->core->notifier_count--;
+			clk->core->notifier_count--;
 
-		/* XXX the notifier code should handle this better */
-		if (!cn->notifier_head.head) {
-			srcu_cleanup_notifier_head(&cn->notifier_head);
-			list_del(&cn->node);
-			kfree(cn);
+			/* XXX the notifier code should handle this better */
+			if (!cn->notifier_head.head) {
+				srcu_cleanup_notifier_head(&cn->notifier_head);
+				list_del(&cn->node);
+				kfree(cn);
+			}
+			break;
 		}
-
-	} else {
-		ret = -ENOENT;
 	}
 
 	clk_prepare_unlock();
@@ -4160,6 +4388,13 @@
 EXPORT_SYMBOL_GPL(clk_notifier_unregister);
 
 #ifdef CONFIG_OF
+static void clk_core_reparent_orphans(void)
+{
+	clk_prepare_lock();
+	clk_core_reparent_orphans_nolock();
+	clk_prepare_unlock();
+}
+
 /**
  * struct of_clk_provider - Clock provider registration structure
  * @link: Entry in global list of clock providers
@@ -4255,6 +4490,8 @@
 	mutex_unlock(&of_clk_mutex);
 	pr_debug("Added clock from %pOF\n", np);
 
+	clk_core_reparent_orphans();
+
 	ret = of_clk_set_defaults(np, true);
 	if (ret < 0)
 		of_clk_del_provider(np);
@@ -4290,6 +4527,8 @@
 	mutex_unlock(&of_clk_mutex);
 	pr_debug("Added clk_hw provider from %pOF\n", np);
 
+	clk_core_reparent_orphans();
+
 	ret = of_clk_set_defaults(np, true);
 	if (ret < 0)
 		of_clk_del_provider(np);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/davinci/da8xx-cfgchip.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/davinci/da8xx-cfgchip.c
@@ -505,7 +505,7 @@
 	const char * const parent_names[] = { "usb_refclkin", "pll0_auxclk" };
 	struct clk *fck_clk;
 	struct da8xx_usb0_clk48 *usb0;
-	struct clk_init_data init;
+	struct clk_init_data init = {};
 	int ret;
 
 	fck_clk = devm_clk_get(dev, "fck");
@@ -579,7 +579,7 @@
 {
 	const char * const parent_names[] = { "usb0_clk48", "usb_refclkin" };
 	struct da8xx_usb1_clk48 *usb1;
-	struct clk_init_data init;
+	struct clk_init_data init = {};
 	int ret;
 
 	usb1 = devm_kzalloc(dev, sizeof(*usb1), GFP_KERNEL);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/davinci/pll.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/davinci/pll.c
@@ -491,7 +491,7 @@
 		parent_name = postdiv_name;
 	}
 
-	pllen = kzalloc(sizeof(*pllout), GFP_KERNEL);
+	pllen = kzalloc(sizeof(*pllen), GFP_KERNEL);
 	if (!pllen) {
 		ret = -ENOMEM;
 		goto err_unregister_postdiv;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/hisilicon/clk-hi3519.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/hisilicon/clk-hi3519.c
@@ -130,7 +130,7 @@
 	of_clk_del_provider(pdev->dev.of_node);
 
 	hisi_clk_unregister_gate(hi3519_gate_clks,
-				ARRAY_SIZE(hi3519_mux_clks),
+				ARRAY_SIZE(hi3519_gate_clks),
 				crg->clk_data);
 	hisi_clk_unregister_mux(hi3519_mux_clks,
 				ARRAY_SIZE(hi3519_mux_clks),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/hisilicon/clk-hi3620.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/hisilicon/clk-hi3620.c
@@ -467,8 +467,10 @@
 		return;
 
 	clk_data->clks = kcalloc(num, sizeof(*clk_data->clks), GFP_KERNEL);
-	if (!clk_data->clks)
+	if (!clk_data->clks) {
+		kfree(clk_data);
 		return;
+	}
 
 	for (i = 0; i < num; i++) {
 		struct hisi_mmc_clock *mmc_clk = &hi3620_mmc_clks[i];
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/hisilicon/clk-hi6220.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/hisilicon/clk-hi6220.c
@@ -86,7 +86,8 @@
 	hisi_clk_register_gate_sep(hi6220_separated_gate_clks_ao,
 				ARRAY_SIZE(hi6220_separated_gate_clks_ao), clk_data_ao);
 }
-CLK_OF_DECLARE(hi6220_clk_ao, "hisilicon,hi6220-aoctrl", hi6220_clk_ao_init);
+/* Allow reset driver to probe as well */
+CLK_OF_DECLARE_DRIVER(hi6220_clk_ao, "hisilicon,hi6220-aoctrl", hi6220_clk_ao_init);
 
 
 /* clocks in sysctrl */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/idt/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/idt/Makefile
@@ -0,0 +1,3 @@
+obj-y += clk-idt8t49n24x-core.o
+obj-y += clk-idt8t49n24x-debugfs.o
+obj-y += clk-idt8t49n24x.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/idt/clk-idt8t49n24x-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/idt/clk-idt8t49n24x-core.c
@@ -0,0 +1,933 @@
+// SPDX-License-Identifier: GPL-2.0
+/* clk-idt8t49n24x-core.c - Program 8T49N24x settings via I2C (common code)
+ *
+ * Copyright (C) 2018, Integrated Device Technology, Inc. <david.cater@idt.com>
+ *
+ * See https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html
+ * This program is distributed "AS IS" and  WITHOUT ANY WARRANTY;
+ * including the implied warranties of MERCHANTABILITY, FITNESS FOR
+ * A PARTICULAR PURPOSE, or NON-INFRINGEMENT.
+ */
+
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+
+#include "clk-idt8t49n24x-core.h"
+
+/*
+ * In Timing Commander, Q0 is changed from 25MHz to Q0 75MHz, the following
+ * changes occur:
+ *
+ * 2 bytes change in EEPROM data string.
+ *
+ * DSM_INT R0025[0],R0026[7:0] : 35 => 30
+ * NS2_Q0 R0040[7:0],R0041[7:0] : 14 => 4
+ *
+ * In EEPROM
+ * 1. R0026
+ * 2. R0041
+ *
+ * Note that VCO_Frequency (metadata) also changed (3500 =>3000).
+ * This reflects a change to DSM_INT.
+ *
+ * Note that the Timing Commander code has workarounds in the workflow scripts
+ * to handle dividers for the 8T49N241 (because the development of that GUI
+ * predates chip override functionality). That affects NS1_Qx (x in 1-3)
+ * and NS2_Qx. NS1_Qx contains the upper bits of NS_Qx, and NS2_Qx contains
+ * the lower bits. That is NOT the case for Q0, though. In that case NS1_Q0
+ * is the 1st stage output divider (/5, /6, /4) and NS2_Q0 is the 16-bit
+ * second stage (with actual divide being twice the value stored in the
+ * register).
+ *
+ * NS1_Q0 R003F[1:0]
+ */
+
+#define IDT24x_VCO_MIN			2999997000u
+#define IDT24x_VCO_MAX			4000004000u
+#define IDT24x_VCO_OPT			3500000000u
+#define IDT24x_MIN_INT_DIVIDER		6
+#define IDT24x_MIN_NS1			4
+#define IDT24x_MAX_NS1			6
+
+static u8 q0_ns1_options[3] = { 5, 6, 4 };
+
+/**
+ * bits_to_shift - num bits to shift given specified mask
+ * @mask:	32-bit word input to count zero bits on right
+ *
+ * Given a bit mask indicating where a value will be stored in
+ * a register, return the number of bits you need to shift the value
+ * before ORing it into the register value.
+ *
+ * Return: number of bits to shift
+ */
+int bits_to_shift(unsigned int mask)
+{
+	/* the number of zero bits on the right */
+	unsigned int c = 32;
+
+	mask &= ~mask + 1;
+	if (mask)
+		c--;
+	if (mask & 0x0000FFFF)
+		c -= 16;
+	if (mask & 0x00FF00FF)
+		c -= 8;
+	if (mask & 0x0F0F0F0F)
+		c -= 4;
+	if (mask & 0x33333333)
+		c -= 2;
+	if (mask & 0x55555555)
+		c -= 1;
+	return c;
+}
+
+/*
+ * TODO: Consider replacing this with regmap_multi_reg_write, which
+ * supports introducing a delay after each write. Experiment to see if
+ * the writes succeed consistently when using that API.
+ */
+static int regmap_bulk_write_with_retry(
+	struct regmap *map, unsigned int offset, u8 val[],
+	int val_count, int max_attempts)
+{
+	int err = 0;
+	int count = 1;
+
+	do {
+		err = regmap_bulk_write(map, offset, val, val_count);
+		if (err == 0)
+			return 0;
+
+		usleep_range(100, 200);
+	} while (count++ <= max_attempts);
+	return err;
+}
+
+static int regmap_write_with_retry(
+	struct regmap *map, unsigned int offset, unsigned int val,
+	int max_attempts)
+{
+	int err = 0;
+	int count = 1;
+
+	do {
+		err = regmap_write(map, offset, val);
+		if (err == 0)
+			return 0;
+		usleep_range(100, 200);
+	} while (count++ <= max_attempts);
+	return err;
+}
+
+/*
+ * TODO: Consider using regmap_multi_reg_write instead. Explore
+ * use of regmap to configure WRITE_BLOCK_SIZE, and using the delay
+ * mechanism in regmap_multi_reg_write instead of retrying multiple
+ * times (regmap_bulk_write_with_retry).
+ */
+int i2cwritebulk(
+	struct i2c_client *client, struct regmap *map,
+	unsigned int reg, u8 val[], size_t val_count)
+{
+	char dbg[128];
+	u8 block[WRITE_BLOCK_SIZE];
+	unsigned int block_offset = reg;
+	int x;
+	int err = 0;
+	int currentOffset = 0;
+
+	dev_dbg(&client->dev, "I2C->0x%04x : [hex] . First byte: %02x, Second byte: %02x",
+		reg, reg >> 8, reg & 0xFF);
+	dbg[0] = 0;
+
+	for (x = 0; x < val_count; x++) {
+		char data[4];
+
+		block[currentOffset++] = val[x];
+		sprintf(data, "%02x ", val[x]);
+		strcat(dbg, data);
+		if (x > 0 && (x + 1) % WRITE_BLOCK_SIZE == 0) {
+			dev_dbg(&client->dev, "%s", dbg);
+			dbg[0] = '\0';
+			sprintf(dbg,
+				"(loop) calling regmap_bulk_write @ 0x%04x [%d bytes]",
+				block_offset, WRITE_BLOCK_SIZE);
+			dev_dbg(&client->dev, "%s", dbg);
+			dbg[0] = '\0';
+			err = regmap_bulk_write_with_retry(
+				map, block_offset, block, WRITE_BLOCK_SIZE, 5);
+			if (err != 0)
+				break;
+			block_offset += WRITE_BLOCK_SIZE;
+			currentOffset = 0;
+		}
+	}
+	if (err == 0 && currentOffset > 0) {
+		dev_dbg(&client->dev, "%s", dbg);
+		dev_dbg(&client->dev, "(final) calling regmap_bulk_write @ 0x%04x [%d bytes]",
+			block_offset, currentOffset);
+		err = regmap_bulk_write_with_retry(
+			map, block_offset, block, currentOffset, 5);
+	}
+
+	return err;
+}
+
+static int i2cwrite(
+	struct i2c_client *client, struct regmap *map,
+	unsigned int reg, unsigned int val)
+{
+	int err;
+
+	dev_dbg(&client->dev, "I2C->0x%x : [hex] %x", reg, val);
+	err = regmap_write_with_retry(map, reg, val, 5);
+	usleep_range(100, 200);
+	return err;
+}
+
+static int i2cwritewithmask(
+	struct i2c_client *client, struct regmap *map, unsigned int reg,
+	u8 val, u8 original, u8 mask)
+{
+	return i2cwrite(client, map, reg,
+		((val << bits_to_shift(mask)) & mask) | (original & ~mask));
+}
+
+int idt24x_get_offsets(
+	u8 output_num,
+	struct clk_register_offsets *offsets)
+{
+	switch (output_num) {
+	case 0:
+		offsets->oe_offset = IDT24x_REG_OUTEN;
+		offsets->oe_mask = IDT24x_REG_OUTEN0_MASK;
+		offsets->dis_mask = IDT24x_REG_Q0_DIS_MASK;
+		offsets->ns1_offset = IDT24x_REG_NS1_Q0;
+		offsets->ns1_offset_mask = IDT24x_REG_NS1_Q0_MASK;
+		offsets->ns2_15_8_offset = IDT24x_REG_NS2_Q0_15_8;
+		offsets->ns2_7_0_offset = IDT24x_REG_NS2_Q0_7_0;
+		break;
+	case 1:
+		offsets->oe_offset = IDT24x_REG_OUTEN;
+		offsets->oe_mask = IDT24x_REG_OUTEN1_MASK;
+		offsets->dis_mask = IDT24x_REG_Q1_DIS_MASK;
+		offsets->n_17_16_offset = IDT24x_REG_N_Q1_17_16;
+		offsets->n_17_16_mask = IDT24x_REG_N_Q1_17_16_MASK;
+		offsets->n_15_8_offset = IDT24x_REG_N_Q1_15_8;
+		offsets->n_7_0_offset = IDT24x_REG_N_Q1_7_0;
+		offsets->nfrac_27_24_offset = IDT24x_REG_NFRAC_Q1_27_24;
+		offsets->nfrac_27_24_mask =
+			IDT24x_REG_NFRAC_Q1_27_24_MASK;
+		offsets->nfrac_23_16_offset = IDT24x_REG_NFRAC_Q1_23_16;
+		offsets->nfrac_15_8_offset = IDT24x_REG_NFRAC_Q1_15_8;
+		offsets->nfrac_7_0_offset = IDT24x_REG_NFRAC_Q1_7_0;
+		break;
+	case 2:
+		offsets->oe_offset = IDT24x_REG_OUTEN;
+		offsets->oe_mask = IDT24x_REG_OUTEN2_MASK;
+		offsets->dis_mask = IDT24x_REG_Q2_DIS_MASK;
+		offsets->n_17_16_offset = IDT24x_REG_N_Q2_17_16;
+		offsets->n_17_16_mask = IDT24x_REG_N_Q2_17_16_MASK;
+		offsets->n_15_8_offset = IDT24x_REG_N_Q2_15_8;
+		offsets->n_7_0_offset = IDT24x_REG_N_Q2_7_0;
+		offsets->nfrac_27_24_offset = IDT24x_REG_NFRAC_Q2_27_24;
+		offsets->nfrac_27_24_mask =
+			IDT24x_REG_NFRAC_Q2_27_24_MASK;
+		offsets->nfrac_23_16_offset = IDT24x_REG_NFRAC_Q2_23_16;
+		offsets->nfrac_15_8_offset = IDT24x_REG_NFRAC_Q2_15_8;
+		offsets->nfrac_7_0_offset = IDT24x_REG_NFRAC_Q2_7_0;
+		break;
+	case 3:
+		offsets->oe_offset = IDT24x_REG_OUTEN;
+		offsets->oe_mask = IDT24x_REG_OUTEN3_MASK;
+		offsets->dis_mask = IDT24x_REG_Q3_DIS_MASK;
+		offsets->n_17_16_offset = IDT24x_REG_N_Q3_17_16;
+		offsets->n_17_16_mask = IDT24x_REG_N_Q3_17_16_MASK;
+		offsets->n_15_8_offset = IDT24x_REG_N_Q3_15_8;
+		offsets->n_7_0_offset = IDT24x_REG_N_Q3_7_0;
+		offsets->nfrac_27_24_offset = IDT24x_REG_NFRAC_Q3_27_24;
+		offsets->nfrac_27_24_mask =
+			IDT24x_REG_NFRAC_Q3_27_24_MASK;
+		offsets->nfrac_23_16_offset = IDT24x_REG_NFRAC_Q3_23_16;
+		offsets->nfrac_15_8_offset = IDT24x_REG_NFRAC_Q3_15_8;
+		offsets->nfrac_7_0_offset = IDT24x_REG_NFRAC_Q3_7_0;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/**
+ * idt24x_calc_div_q0 - Calculate dividers and VCO freq to generate
+ *		the specified Q0 frequency.
+ * @chip:	Device data structure. contains all requested frequencies
+ *		for all outputs.
+ *
+ * The actual output divider is ns1 * ns2 * 2. fOutput = fVCO / (ns1 * ns2 * 2)
+ *
+ * The options for ns1 (when the source is the VCO) are 4,5,6. ns2 is a
+ * 16-bit value.
+ *
+ * chip->divs: structure for specifying ns1/ns2 values. If 0 after this
+ * function, Q0 is not requested
+ *
+ * Return: 0 on success, negative errno otherwise.
+ */
+static int idt24x_calc_div_q0(struct clk_idt24x_chip *chip)
+{
+	u8 x;
+	u32 min_div, max_div, best_vco = 0;
+	u16 min_ns2, max_ns2;
+	bool is_lower_vco = false;
+
+	chip->divs.ns1_q0 = 0;
+	chip->divs.ns2_q0 = 0;
+
+	if (chip->clk[0].requested == 0)
+		return 0;
+
+	min_div = div64_u64(
+		(u64)IDT24x_VCO_MIN, chip->clk[0].requested * 2) * 2;
+	max_div = div64_u64(
+		(u64)IDT24x_VCO_MAX, chip->clk[0].requested * 2) * 2;
+
+	dev_dbg(&chip->i2c_client->dev,
+		"%s. requested: %u, min_div: %u, max_div: %u",
+		__func__, chip->clk[0].requested, min_div, max_div);
+
+	min_ns2 = div64_u64((u64)min_div, IDT24x_MAX_NS1 * 2);
+	max_ns2 = div64_u64((u64)max_div, IDT24x_MIN_NS1 * 2);
+
+	dev_dbg(&chip->i2c_client->dev,
+		"%s. min_ns2: %u, max_ns2: %u", __func__, min_ns2, max_ns2);
+
+	for (x = 0; x < ARRAY_SIZE(q0_ns1_options); x++) {
+		u16 y = min_ns2;
+
+		while (y <= max_ns2) {
+			u32 actual_div = q0_ns1_options[x] * y * 2;
+			u32 current_vco = actual_div *
+				chip->clk[0].requested;
+
+			if (current_vco < IDT24x_VCO_MIN)
+				dev_dbg(&chip->i2c_client->dev,
+					"%s. ignore div: (ns1=%u * ns2=%u * 2 * %u) == %u < %u",
+					__func__, q0_ns1_options[x], y,
+					chip->clk[0].requested,
+					current_vco, IDT24x_VCO_MIN);
+			else if (current_vco > IDT24x_VCO_MAX) {
+				dev_dbg(&chip->i2c_client->dev,
+					"%s. ignore div: (ns1=%u * ns2=%u * 2 * %u) == %u > %u. EXIT LOOP.",
+					__func__, q0_ns1_options[x], y,
+					chip->clk[0].requested,
+					current_vco, IDT24x_VCO_MAX);
+				y = max_ns2;
+			} else {
+				bool use = false;
+
+				dev_dbg(&chip->i2c_client->dev,
+					"%s. contender: (ns1=%u * ns2=%u * 2 * %u) == %u [in range]",
+					__func__, q0_ns1_options[x], y,
+					chip->clk[0].requested,
+					current_vco);
+				if (current_vco <= IDT24x_VCO_OPT) {
+					if (current_vco > best_vco ||
+					    !is_lower_vco) {
+						is_lower_vco = true;
+						use = true;
+					}
+				} else if (!is_lower_vco &&
+					   current_vco > best_vco)
+					use = true;
+				if (use) {
+					chip->divs.ns1_q0 = x;
+					chip->divs.ns2_q0 = y;
+					best_vco = current_vco;
+				}
+			}
+			y++;
+		}
+	}
+
+	dev_dbg(&chip->i2c_client->dev,
+		"%s. best: (ns1=%u [/%u] * ns2=%u * 2 * %u) == %u",
+		__func__, chip->divs.ns1_q0, q0_ns1_options[chip->divs.ns1_q0],
+		chip->divs.ns2_q0, chip->clk[0].requested, best_vco);
+	return 0;
+}
+
+/**
+ * idt24x_calc_divs - Calculate dividers to generate the specified frequency.
+ * @chip:	Device data structure. contains all requested frequencies
+ *		for all outputs.
+ *
+ * Calculate the clock dividers (dsmint, dsmfrac for vco; ns1/ns2 for q0,
+ * n/nfrac for q1-3) for a given target frequency.
+ *
+ * Return: 0 on success, negative errno otherwise.
+ */
+static int idt24x_calc_divs(struct clk_idt24x_chip *chip)
+{
+	u32 vco = 0;
+	int result;
+
+	result = idt24x_calc_div_q0(chip);
+	if (result < 0)
+		return result;
+
+	dev_dbg(&chip->i2c_client->dev,
+		"%s: after idt24x_calc_div_q0. ns1: %u [/%u], ns2: %u",
+		__func__, chip->divs.ns1_q0, q0_ns1_options[chip->divs.ns1_q0],
+		chip->divs.ns2_q0);
+
+	chip->divs.dsmint = 0;
+	chip->divs.dsmfrac = 0;
+
+	if (chip->clk[0].requested > 0) {
+		/* Q0 is in use and is governing the actual VCO freq */
+		vco = q0_ns1_options[chip->divs.ns1_q0] * chip->divs.ns2_q0 *
+			2 * chip->clk[0].requested;
+	} else {
+		u32 freq = 0;
+		u32 walk;
+		u32 min_div, max_div;
+		bool is_lower_vco = false;
+
+		/*
+		 * Q0 is not in use. Use the first requested (fractional)
+		 * output frequency as the one controlling the VCO.
+		 */
+		for (walk = 1; walk < NUM_OUTPUTS; walk++) {
+			if (chip->clk[walk].requested != 0) {
+				freq = chip->clk[walk].requested;
+				break;
+			}
+		}
+
+		if (freq == 0) {
+			dev_err(&chip->i2c_client->dev,
+				"%s: NO FREQUENCIES SPECIFIED", __func__);
+			return -EINVAL;
+		}
+
+		/*
+		 * First, determine the min/max div for the output frequency.
+		 */
+		min_div = IDT24x_MIN_INT_DIVIDER;
+		max_div = div64_u64((u64)IDT24x_VCO_MAX, freq * 2) * 2;
+
+		dev_dbg(&chip->i2c_client->dev,
+			"%s: calc_divs for fractional output. freq: %u, min_div: %u, max_div: %u",
+			__func__, freq, min_div, max_div);
+
+		walk = min_div;
+
+		while (walk <= max_div) {
+			u32 current_vco = freq * walk;
+
+			dev_dbg(&chip->i2c_client->dev,
+				"%s: calc_divs for fractional output. walk: %u, freq: %u, vco: %u",
+				__func__, walk, freq, vco);
+			if (current_vco >= IDT24x_VCO_MIN &&
+			    vco <= IDT24x_VCO_MAX) {
+				if (current_vco <= IDT24x_VCO_OPT) {
+					if (current_vco > vco ||
+					    !is_lower_vco) {
+						is_lower_vco = true;
+						vco = current_vco;
+					}
+				} else if (!is_lower_vco && current_vco > vco) {
+					vco = current_vco;
+				}
+			}
+			/* Divider must be even. */
+			walk += 2;
+		}
+	}
+
+	if (vco != 0) {
+		u32 pfd;
+		u64 rem;
+		int x;
+
+		/* Setup dividers for outputs with fractional dividers. */
+		for (x = 1; x < NUM_OUTPUTS; x++) {
+			if (chip->clk[x].requested != 0) {
+				/*
+				 * The value written to the chip is half
+				 * the calculated divider.
+				 */
+				chip->divs.nint[x - 1] = div64_u64_rem(
+					(u64)vco,
+					chip->clk[x].requested * 2,
+					&rem);
+				chip->divs.nfrac[x - 1] = div64_u64(
+					rem * 1 << 28,
+					chip->clk[x].requested * 2);
+				dev_dbg(&chip->i2c_client->dev,
+					"%s: div to get Q%i freq %u from vco %u: int part: %u, rem: %llu, frac part: %u",
+					__func__, x,
+					chip->clk[x].requested,
+					vco, chip->divs.nint[x - 1], rem,
+					chip->divs.nfrac[x - 1]);
+			}
+		}
+
+		/* Calculate freq for pfd */
+		pfd = chip->input_clk_freq * (chip->doubler_disabled ? 1 : 2);
+
+		/*
+		 * Calculate dsmint & dsmfrac:
+		 * -----------------------------
+		 * dsm = float(vco)/float(pfd)
+		 * dsmfrac = dsm-floor(dsm) * 2^21
+		 * rem = vco % pfd
+		 * therefore:
+		 * dsmfrac = (rem * 2^21)/pfd
+		 */
+		chip->divs.dsmint = div64_u64_rem(vco, pfd, &rem);
+		chip->divs.dsmfrac = div64_u64(rem * 1 << 21, pfd);
+
+		dev_dbg(&chip->i2c_client->dev,
+			"%s: vco: %u, pfd: %u, dsmint: %u, dsmfrac: %u, rem: %llu",
+			__func__, vco, pfd, chip->divs.dsmint,
+			chip->divs.dsmfrac, rem);
+	} else {
+		dev_err(&chip->i2c_client->dev,
+			"%s: no integer divider in range found. NOT SUPPORTED.",
+			__func__);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/**
+ * idt24x_enable_output - Enable/disable a particular output
+ * @chip:	Device data structure
+ * @output:	Output to enable/disable
+ * @enable:	Enable (true/false)
+ *
+ * Return: passes on regmap_write return value.
+ */
+static int idt24x_enable_output(
+	struct clk_idt24x_chip *chip, u8 output, bool enable)
+{
+	struct clk_register_offsets offsets;
+	int err;
+	struct i2c_client *client = chip->i2c_client;
+
+	/*
+	 * When an output is enabled, enable it in the original
+	 * data read from the chip and cached. Otherwise it may be
+	 * accidentally	turned off when another output is enabled.
+	 *
+	 * E.g., the driver starts with all outputs off in reg_out_en_x.
+	 * Q1 is enabled with the appropriate mask. Q2 is then enabled,
+	 * which results in Q1 being turned back off (because Q1 was off
+	 * in reg_out_en_x).
+	 */
+
+	err = idt24x_get_offsets(output, &offsets);
+	if (err) {
+		dev_err(&client->dev,
+			"%s: error calling idt24x_get_offsets for %d: %i",
+			__func__, output, err);
+		return err;
+	}
+
+	dev_dbg(&client->dev,
+		"%s: q%u enable? %d. reg_out_en_x before: 0x%x, reg_out_mode_0_1 before: 0x%x, reg_out_mode_2_3 before: 0x%x, reg_qx_dis before: 0x%x",
+		__func__, output, enable, chip->reg_out_en_x,
+		chip->reg_out_mode_0_1, chip->reg_out_mode_2_3,
+		chip->reg_qx_dis);
+
+	chip->reg_out_en_x = chip->reg_out_en_x & ~offsets.oe_mask;
+	if (enable)
+		chip->reg_out_en_x |= (1 << bits_to_shift(offsets.oe_mask));
+
+	chip->reg_qx_dis = chip->reg_qx_dis & ~offsets.dis_mask;
+	dev_dbg(&client->dev,
+		"%s: q%u enable? %d. reg_qx_dis mask: 0x%x, before checking enable: 0x%x",
+		__func__, output, enable, offsets.dis_mask,
+		chip->reg_qx_dis);
+	if (!enable)
+		chip->reg_qx_dis |= (1 << bits_to_shift(offsets.dis_mask));
+
+	dev_dbg(&client->dev,
+		"%s: q%u enable? %d. reg_out_en_x after: 0x%x, reg_qx_dis after: 0x%x",
+		__func__, output, enable, chip->reg_out_en_x,
+		chip->reg_qx_dis);
+
+	err = i2cwrite(
+		client, chip->regmap, IDT24x_REG_OUTEN, chip->reg_out_en_x);
+	if (err) {
+		dev_err(&client->dev,
+			"%s: error setting IDT24x_REG_OUTEN: %i",
+			__func__, err);
+		return err;
+	}
+
+	err = i2cwrite(
+		client, chip->regmap, IDT24x_REG_OUTMODE0_1,
+		chip->reg_out_mode_0_1);
+	if (err) {
+		dev_err(&client->dev,
+			"%s: error setting IDT24x_REG_OUTMODE0_1: %i",
+			__func__, err);
+		return err;
+	}
+
+	err = i2cwrite(
+		client, chip->regmap, IDT24x_REG_OUTMODE2_3,
+		chip->reg_out_mode_2_3);
+	if (err) {
+		dev_err(&client->dev,
+			"%s: error setting IDT24x_REG_OUTMODE2_3: %i",
+			__func__, err);
+		return err;
+	}
+
+	err = i2cwrite(
+		client, chip->regmap, IDT24x_REG_Q_DIS, chip->reg_qx_dis);
+	if (err) {
+		dev_err(&client->dev,
+			"%s: error setting IDT24x_REG_Q_DIS: %i",
+			__func__, err);
+		return err;
+	}
+
+	return 0;
+}
+
+/**
+ * idt24x_update_device - write registers to the chip
+ * @chip:	Device data structure
+ *
+ * Write all values to hardware that we	have calculated.
+ *
+ * Return: passes on regmap_bulk_write return value.
+ */
+static int idt24x_update_device(struct clk_idt24x_chip *chip)
+{
+	int err;
+	struct i2c_client *client = chip->i2c_client;
+	int x = -1;
+
+	dev_dbg(&client->dev,
+		"%s: setting DSM_INT_8 (val %u @ %u)",
+		__func__, chip->divs.dsmint >> 8,
+		IDT24x_REG_DSM_INT_8);
+	err = i2cwritewithmask(
+		client, chip->regmap, IDT24x_REG_DSM_INT_8,
+		(chip->divs.dsmint >> 8) & IDT24x_REG_DSM_INT_8_MASK,
+		chip->reg_dsm_int_8, IDT24x_REG_DSM_INT_8_MASK);
+	if (err) {
+		dev_err(&client->dev,
+			"%s: error setting IDT24x_REG_DSM_INT_8: %i",
+			__func__, err);
+		return err;
+	}
+
+	dev_dbg(&client->dev,
+		"%s: setting DSM_INT_7_0 (val %u @ 0x%x)",
+		__func__, chip->divs.dsmint & 0xFF,
+		IDT24x_REG_DSM_INT_7_0);
+	err = i2cwrite(
+		client, chip->regmap, IDT24x_REG_DSM_INT_7_0,
+		chip->divs.dsmint & 0xFF);
+	if (err) {
+		dev_err(&client->dev,
+			"%s: error setting IDT24x_REG_DSM_INT_7_0: %i",
+			__func__, err);
+		return err;
+	}
+
+	dev_dbg(&client->dev,
+		"%s: setting IDT24x_REG_DSMFRAC_20_16 (val %u @ 0x%x)",
+		__func__, chip->divs.dsmfrac >> 16,
+		IDT24x_REG_DSMFRAC_20_16);
+	err = i2cwritewithmask(
+		client, chip->regmap, IDT24x_REG_DSMFRAC_20_16,
+		(chip->divs.dsmfrac >> 16) & IDT24x_REG_DSMFRAC_20_16_MASK,
+		chip->reg_dsm_int_8, IDT24x_REG_DSMFRAC_20_16_MASK);
+	if (err) {
+		dev_err(&client->dev,
+			"%s: error setting IDT24x_REG_DSMFRAC_20_16: %i",
+			__func__, err);
+		return err;
+	}
+
+	dev_dbg(&client->dev,
+		"%s: setting IDT24x_REG_DSMFRAC_15_8 (val %u @ 0x%x)",
+		__func__, (chip->divs.dsmfrac >> 8) & 0xFF,
+		IDT24x_REG_DSMFRAC_15_8);
+	err = i2cwrite(
+		client, chip->regmap, IDT24x_REG_DSMFRAC_15_8,
+		(chip->divs.dsmfrac >> 8) & 0xFF);
+	if (err) {
+		dev_err(&client->dev,
+			"%s: error setting IDT24x_REG_DSMFRAC_15_8: %i",
+			__func__, err);
+		return err;
+	}
+
+	dev_dbg(&client->dev,
+		"%s: setting IDT24x_REG_DSMFRAC_7_0 (val %u @ 0x%x)",
+		__func__, chip->divs.dsmfrac & 0xFF,
+		IDT24x_REG_DSMFRAC_7_0);
+	err = i2cwrite(
+		client, chip->regmap, IDT24x_REG_DSMFRAC_7_0,
+		chip->divs.dsmfrac & 0xFF);
+	if (err) {
+		dev_err(&client->dev,
+			"%s: error setting IDT24x_REG_DSMFRAC_7_0: %i",
+			__func__, err);
+		return err;
+	}
+
+	dev_dbg(&client->dev,
+		"%s: setting IDT24x_REG_NS1_Q0 (val %u @ 0x%x)",
+		__func__, chip->divs.ns1_q0, IDT24x_REG_NS1_Q0);
+	err = i2cwritewithmask(
+		client, chip->regmap, IDT24x_REG_NS1_Q0,
+		chip->divs.ns1_q0 & IDT24x_REG_NS1_Q0_MASK,
+		chip->reg_ns1_q0, IDT24x_REG_NS1_Q0_MASK);
+	if (err) {
+		dev_err(&client->dev,
+			"%s: error setting IDT24x_REG_NS1_Q0: %i",
+			__func__, err);
+		return err;
+	}
+
+	dev_dbg(&client->dev,
+		"%s: setting IDT24x_REG_NS2_Q0_15_8 (val %u @ 0x%x)",
+		__func__, (chip->divs.ns2_q0 >> 8) & 0xFF,
+		IDT24x_REG_NS2_Q0_15_8);
+	err = i2cwrite(
+		client, chip->regmap, IDT24x_REG_NS2_Q0_15_8,
+		(chip->divs.ns2_q0 >> 8) & 0xFF);
+	if (err) {
+		dev_err(&client->dev,
+			"%s: error setting IDT24x_REG_NS2_Q0_15_8: %i",
+			__func__, err);
+		return err;
+	}
+
+	dev_dbg(&client->dev,
+		"%s: setting IDT24x_REG_NS2_Q0_7_0 (val %u @ 0x%x)",
+		__func__, chip->divs.ns2_q0 & 0xFF,
+		IDT24x_REG_NS2_Q0_7_0);
+	err = i2cwrite(
+		client, chip->regmap, IDT24x_REG_NS2_Q0_7_0,
+		chip->divs.ns2_q0 & 0xFF);
+	if (err) {
+		dev_err(&client->dev,
+			"%s: error setting IDT24x_REG_NS2_Q0_7_0: %i",
+			__func__, err);
+		return err;
+	}
+
+	dev_dbg(&client->dev,
+		"%s: calling idt24x_enable_output for Q0. requestedFreq: %u",
+		__func__, chip->clk[0].requested);
+	idt24x_enable_output(chip, 0, chip->clk[0].requested != 0);
+
+	dev_dbg(&client->dev,
+		"%s: writing values for q1-q3", __func__);
+	for (x = 1; x < NUM_OUTPUTS; x++) {
+		struct clk_register_offsets offsets;
+
+		if (chip->clk[x].requested != 0) {
+			dev_dbg(&client->dev,
+				"%s: calling idt24x_get_offsets for %u",
+				__func__, x);
+			err = idt24x_get_offsets(x, &offsets);
+			if (err) {
+				dev_err(&client->dev,
+					"%s: error calling idt24x_get_offsets: %i",
+					__func__, err);
+				return err;
+			}
+
+			dev_dbg(&client->dev,
+				"%s: (q%u, nint: %u, nfrac: %u)",
+				__func__, x, chip->divs.nint[x - 1],
+				chip->divs.nfrac[x - 1]);
+
+			dev_dbg(&client->dev,
+				"%s: setting n_17_16_offset (q%u, val %u @ 0x%x)",
+				__func__, x,
+				chip->divs.nint[x - 1] >> 16,
+				offsets.n_17_16_offset);
+			err = i2cwritewithmask(
+				client, chip->regmap, offsets.n_17_16_offset,
+				(chip->divs.nint[x - 1] >> 16) &
+					offsets.n_17_16_mask,
+				chip->reg_n_qx_17_16[x - 1],
+				offsets.n_17_16_mask);
+			if (err) {
+				dev_err(&client->dev,
+					"%s: error setting n_17_16_offset: %i",
+					__func__, err);
+				return err;
+			}
+
+			dev_dbg(&client->dev,
+				"%s: setting n_15_8_offset (q%u, val %u @ 0x%x)",
+				__func__, x,
+				(chip->divs.nint[x - 1] >> 8) & 0xFF,
+				offsets.n_15_8_offset);
+			err = i2cwrite(
+				client, chip->regmap, offsets.n_15_8_offset,
+				(chip->divs.nint[x - 1] >> 8) & 0xFF);
+			if (err) {
+				dev_err(&client->dev,
+					"%s: error setting n_15_8_offset: %i",
+					__func__, err);
+				return err;
+			}
+
+			dev_dbg(&client->dev,
+				"%s: setting n_7_0_offset (q%u, val %u @ 0x%x)",
+				__func__, x,
+				chip->divs.nint[x - 1] & 0xFF,
+				offsets.n_7_0_offset);
+			err = i2cwrite(
+				client, chip->regmap, offsets.n_7_0_offset,
+				chip->divs.nint[x - 1] & 0xFF);
+			if (err) {
+				dev_err(&client->dev,
+					"%s: error setting n_7_0_offset: %i",
+					__func__, err);
+				return err;
+			}
+
+			dev_dbg(&client->dev,
+				"%s: setting nfrac_27_24_offset (q%u, val %u @ 0x%x)",
+				__func__, x,
+				(chip->divs.nfrac[x - 1] >> 24),
+				offsets.nfrac_27_24_offset);
+			err = i2cwritewithmask(
+				client, chip->regmap,
+				offsets.nfrac_27_24_offset,
+				(chip->divs.nfrac[x - 1] >> 24) &
+					offsets.nfrac_27_24_mask,
+				chip->reg_nfrac_qx_27_24[x - 1],
+				offsets.nfrac_27_24_mask);
+			if (err) {
+				dev_err(&client->dev,
+					"%s: error setting nfrac_27_24_offset: %i",
+					__func__, err);
+				return err;
+			}
+
+			dev_dbg(&client->dev,
+				"%s: setting nfrac_23_16_offset (q%u, val %u @ 0x%x)",
+				__func__, x,
+				(chip->divs.nfrac[x - 1] >> 16) & 0xFF,
+				offsets.nfrac_23_16_offset);
+			err = i2cwrite(
+				client, chip->regmap,
+				offsets.nfrac_23_16_offset,
+				(chip->divs.nfrac[x - 1] >> 16) & 0xFF);
+			if (err) {
+				dev_err(&client->dev,
+					"%s: error setting nfrac_23_16_offset: %i",
+					__func__, err);
+				return err;
+			}
+
+			dev_dbg(&client->dev,
+				"%s: setting nfrac_15_8_offset (q%u, val %u @ 0x%x)",
+				__func__, x,
+				(chip->divs.nfrac[x - 1] >> 8) & 0xFF,
+				offsets.nfrac_15_8_offset);
+			err = i2cwrite(
+				client, chip->regmap,
+				offsets.nfrac_15_8_offset,
+				(chip->divs.nfrac[x - 1] >> 8) & 0xFF);
+			if (err) {
+				dev_err(&client->dev,
+					"%s: error setting nfrac_15_8_offset: %i",
+					__func__, err);
+				return err;
+			}
+
+			dev_dbg(&client->dev,
+				"%s: setting nfrac_7_0_offset (q%u, val %u @ 0x%x)",
+				__func__, x,
+				chip->divs.nfrac[x - 1] & 0xFF,
+				offsets.nfrac_7_0_offset);
+			err = i2cwrite(
+				client, chip->regmap, offsets.nfrac_7_0_offset,
+				chip->divs.nfrac[x - 1] & 0xFF);
+			if (err) {
+				dev_err(&client->dev,
+					"%s: error setting nfrac_7_0_offset: %i",
+					__func__, err);
+				return err;
+			}
+		}
+		idt24x_enable_output(chip, x,
+				     chip->clk[x].requested != 0);
+		chip->clk[x].actual = chip->clk[x].requested;
+	}
+	return 0;
+}
+
+/**
+ * idt24x_set_frequency - Adjust output frequency on the attached chip.
+ * @chip:	Device data structure, including all requested frequencies.
+ *
+ * Return: 0 on success.
+ */
+int idt24x_set_frequency(struct clk_idt24x_chip *chip)
+{
+	int err;
+	struct i2c_client *client = chip->i2c_client;
+	int x;
+	bool all_disabled = true;
+
+	for (x = 0; x < NUM_OUTPUTS; x++) {
+		if (chip->clk[x].requested == 0) {
+			idt24x_enable_output(chip, x, false);
+			chip->clk[x].actual = 0;
+		} else {
+			all_disabled = false;
+		}
+	}
+
+	if (all_disabled)
+		/*
+		 * no requested frequencies, so nothing else to calculate
+		 * or write to the chip. If the consumer wants to disable
+		 * all outputs, they can request 0 for all frequencies.
+		 */
+		return 0;
+
+	if (chip->input_clk_freq == 0) {
+		dev_err(&client->dev,
+			"%s: no input frequency; can't continue.", __func__);
+		return -EINVAL;
+	}
+
+	err = idt24x_calc_divs(chip);
+	if (err) {
+		dev_err(&client->dev,
+			"%s: error calling idt24x_calc_divs: %i",
+			__func__, err);
+		return err;
+	}
+
+	err = idt24x_update_device(chip);
+	if (err) {
+		dev_err(&client->dev,
+			"%s: error updating the device: %i",
+			__func__, err);
+		return err;
+	}
+
+	return 0;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/idt/clk-idt8t49n24x-core.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/idt/clk-idt8t49n24x-core.h
@@ -0,0 +1,272 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* clk-idt8t49n24x-core.h - Program 8T49N24x settings via I2C (common code)
+ *
+ * Copyright (C) 2018, Integrated Device Technology, Inc. <david.cater@idt.com>
+ *
+ * See https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html
+ * This program is distributed "AS IS" and  WITHOUT ANY WARRANTY;
+ * including the implied warranties of MERCHANTABILITY, FITNESS FOR
+ * A PARTICULAR PURPOSE, or NON-INFRINGEMENT.
+ */
+
+#ifndef __IDT_CLK_IDT8T49N24X_CORE_H_
+#define __IDT_CLK_IDT8T49N24X_CORE_H_
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+
+/*
+ * The configurations in the settings file have 0x317 registers (last offset
+ * is 0x316).
+ */
+#define NUM_CONFIG_REGISTERS	0x317
+#define NUM_INPUTS		2
+#define NUM_OUTPUTS		4
+#define DEBUGFS_BUFFER_LENGTH	200
+#define WRITE_BLOCK_SIZE	32
+
+/* Non output-specific registers */
+#define IDT24x_REG_DBL_DIS		0x6C
+#define IDT24x_REG_DBL_DIS_MASK		0x01
+#define IDT24x_REG_DSM_INT_8		0x25
+#define IDT24x_REG_DSM_INT_8_MASK	0x01
+#define IDT24x_REG_DSM_INT_7_0		0x26
+#define IDT24x_REG_DSMFRAC_20_16	0x28
+#define IDT24x_REG_DSMFRAC_20_16_MASK	0x1F
+#define IDT24x_REG_DSMFRAC_15_8		0x29
+#define IDT24x_REG_DSMFRAC_7_0		0x2A
+#define IDT24x_REG_OUTEN		0x39
+#define IDT24x_REG_OUTMODE0_1		0x3E
+#define IDT24x_REG_OUTMODE2_3		0x3D
+#define IDT24x_REG_Q_DIS		0x6F
+
+/* Q0 */
+#define IDT24x_REG_OUTEN0_MASK		0x01
+#define IDT24x_REG_OUTMODE0_MASK	0x0E
+#define IDT24x_REG_Q0_DIS_MASK		0x01
+#define IDT24x_REG_NS1_Q0		0x3F
+#define IDT24x_REG_NS1_Q0_MASK		0x03
+#define IDT24x_REG_NS2_Q0_15_8		0x40
+#define IDT24x_REG_NS2_Q0_7_0		0x41
+
+/* Q1 */
+#define IDT24x_REG_OUTEN1_MASK		0x02
+#define IDT24x_REG_OUTMODE1_MASK	0xE0
+#define IDT24x_REG_Q1_DIS_MASK		0x02
+#define IDT24x_REG_N_Q1_17_16		0x42
+#define IDT24x_REG_N_Q1_17_16_MASK	0x03
+#define IDT24x_REG_N_Q1_15_8		0x43
+#define IDT24x_REG_N_Q1_7_0		0x44
+#define IDT24x_REG_NFRAC_Q1_27_24	0x57
+#define IDT24x_REG_NFRAC_Q1_27_24_MASK	0x0F
+#define IDT24x_REG_NFRAC_Q1_23_16	0x58
+#define IDT24x_REG_NFRAC_Q1_15_8	0x59
+#define IDT24x_REG_NFRAC_Q1_7_0		0x5A
+
+/* Q2 */
+#define IDT24x_REG_OUTEN2_MASK		0x04
+#define IDT24x_REG_OUTMODE2_MASK	0x0E
+#define IDT24x_REG_Q2_DIS_MASK		0x04
+#define IDT24x_REG_N_Q2_17_16		0x45
+#define IDT24x_REG_N_Q2_17_16_MASK	0x03
+#define IDT24x_REG_N_Q2_15_8		0x46
+#define IDT24x_REG_N_Q2_7_0		0x47
+#define IDT24x_REG_NFRAC_Q2_27_24	0x5B
+#define IDT24x_REG_NFRAC_Q2_27_24_MASK	0x0F
+#define IDT24x_REG_NFRAC_Q2_23_16	0x5C
+#define IDT24x_REG_NFRAC_Q2_15_8	0x5D
+#define IDT24x_REG_NFRAC_Q2_7_0		0x5E
+
+/* Q3 */
+#define IDT24x_REG_OUTEN3_MASK		0x08
+#define IDT24x_REG_OUTMODE3_MASK	0xE0
+#define IDT24x_REG_Q3_DIS_MASK		0x08
+#define IDT24x_REG_N_Q3_17_16		0x48
+#define IDT24x_REG_N_Q3_17_16_MASK	0x03
+#define IDT24x_REG_N_Q3_15_8		0x49
+#define IDT24x_REG_N_Q3_7_0		0x4A
+#define IDT24x_REG_NFRAC_Q3_27_24	0x5F
+#define IDT24x_REG_NFRAC_Q3_27_24_MASK	0x0F
+#define IDT24x_REG_NFRAC_Q3_23_16	0x60
+#define IDT24x_REG_NFRAC_Q3_15_8	0x61
+#define IDT24x_REG_NFRAC_Q3_7_0		0x62
+
+/**
+ * struct idt24x_output - device output information
+ * @hw:		hw registration info for this specific output clcok. This gets
+ *		passed as an argument to CCF api calls (e.g., set_rate).
+ *		container_of can then be used to get the reference to this
+ *		struct.
+ * @chip:	store a reference to the parent device structure. container_of
+ *		cannot be used to get to the parent device structure from
+ *		idt24x_output, because clk_idt24x_chip contains an array of
+ *		output structs (for future enhancements to support devices
+ *		with different numbers of output clocks).
+ * @index:	identifies output on the chip; used in debug statements
+ * @requested:	requested output clock frequency (in Hz)
+ * @actual:	actual output clock frequency (in Hz). Will only be set after
+ *		successful update of the device.
+ * @debug_freq:	stores value for debugfs file. Use this instead of requested
+ *		struct var because debugfs expects u64, not u32.
+ */
+struct idt24x_output {
+	struct clk_hw hw;
+	struct clk_idt24x_chip *chip;
+	u8 index;
+	u32 requested;
+	u32 actual;
+	u64 debug_freq;
+};
+
+/**
+ * struct idt24x_dividers - output dividers
+ * @dsmint:	int component of feedback divider for VCO (2-stage divider)
+ * @dsmfrac:	fractional component of feedback divider for VCO
+ * @ns1_q0:	ns1 divider component for Q0
+ * @ns2_q0:	ns2 divider component for Q0
+ * @nint:	int divider component for Q1-3
+ * @nfrac:	fractional divider component for Q1-3
+ */
+struct idt24x_dividers {
+	u16 dsmint;
+	u32 dsmfrac;
+
+	u8 ns1_q0;
+	u16 ns2_q0;
+
+	u32 nint[3];
+	u32 nfrac[3];
+};
+
+/**
+ * struct clk_idt24x_chip - device info for chip
+ * @regmap:		register map used to perform i2c writes to the chip
+ * @i2c_client:		i2c_client struct passed to probe
+ * @min_freq:		min frequency for this chip
+ * @max_freq:		max frequency for this chip
+ * @settings:		filled in if full register map is specified in the DT
+ * @has_settings:	true if settings array is valid
+ * @input_clk:		ptr to input clock specified in DT
+ * @input_clk_num:	which input clock was specified. 0-based. A value of
+ *			NUM_INPUTS indicates that a XTAL is used as the input.
+ * @input_clk_nb:	notification support (if input clk changes)
+ * @input_clk_freq:	current freq of input_clk
+ * @doubler_disabled:	whether input doubler is enabled. This value is read
+ *			from the hw on probe (in case it is set in @settings).
+ * @clk:		array of outputs. One entry per output supported by the
+ *			chip. Frequencies requested via the ccf api will be
+ *			recorded in this array.
+ * @reg_dsm_int_8:	record current value from hw to avoid modifying
+ *			when writing register values
+ * @reg_dsm_frac_20_16:	record current value
+ * @reg_out_en_x:	record current value
+ * @reg_out_mode_0_1:	record current value
+ * @reg_out_mode_2_3:	record current value
+ * @reg_qx_dis:		record current value
+ * @reg_ns1_q0:		record current value
+ * @reg_n_qx_17_16:	record current value
+ * @reg_nfrac_qx_27_24:	record current value
+ * @divs:		output divider values for all outputs
+ * @debugfs_dirroot:	debugfs support
+ * @debugfs_fileaction:	debugfs support
+ * @debugfs_filei2c:	debugfs support
+ * @debugfs_map:	debugfs support
+ * @dbg_cache:		debugfs support
+ * @debugfs_fileqfreq:	debugfs support
+ */
+struct clk_idt24x_chip {
+	struct regmap *regmap;
+	struct i2c_client *i2c_client;
+
+	u32 min_freq;
+	u32 max_freq;
+
+	u8 settings[NUM_CONFIG_REGISTERS];
+
+	bool has_settings;
+
+	struct clk *input_clk;
+	int input_clk_num;
+	struct notifier_block input_clk_nb;
+	u32 input_clk_freq;
+
+	bool doubler_disabled;
+
+	struct idt24x_output clk[NUM_OUTPUTS];
+
+	unsigned int reg_dsm_int_8;
+	unsigned int reg_dsm_frac_20_16;
+	unsigned int reg_out_en_x;
+	unsigned int reg_out_mode_0_1;
+	unsigned int reg_out_mode_2_3;
+	unsigned int reg_qx_dis;
+	unsigned int reg_ns1_q0;
+	unsigned int reg_n_qx_17_16[3];
+	unsigned int reg_nfrac_qx_27_24[3];
+
+	struct idt24x_dividers divs;
+
+	struct dentry *debugfs_dirroot, *debugfs_fileaction, *debugfs_filei2c,
+		*debugfs_map;
+	char dbg_cache[DEBUGFS_BUFFER_LENGTH];
+	struct dentry *debugfs_fileqfreq[4];
+};
+
+#define to_idt24x_output(_hw) \
+	container_of(_hw, struct idt24x_output, hw)
+#define to_clk_idt24x_from_client(_client) \
+	container_of(_client, struct clk_idt24x_chip, i2c_client)
+#define to_clk_idt24x_from_nb(_nb) \
+	container_of(_nb, struct clk_idt24x_chip, input_clk_nb)
+
+/**
+ * struct clk_register_offsets - register offsets for current context
+ * @oe_offset:		offset for current output enable and mode
+ * @oe_mask:		mask for current output enable
+ * @dis_mask:		mask for current output disable
+ * @n_17_16_offset:	offset for current output int divider (bits 17:16)
+ * @n_17_16_mask:	mask for current output int divider (bits 17:16)
+ * @n_15_8_offset:	offset for current output int divider (bits 15:8)
+ * @n_7_0_offset:	offset for current output int divider (bits 7:0)
+ * @nfrac_27_24_offset:	offset for current output frac divider (bits 27:24)
+ * @nfrac_27_24_mask:	mask for current output frac divider (bits 27:24)
+ * @nfrac_23_16_offset:	offset for current output frac divider (bits 23:16)
+ * @nfrac_15_8_offset:	offset for current output frac divider (bits 15:8)
+ * @nfrac_7_0_offset:	offset for current output frac divider (bits 7:0)
+ * @ns1_offset:		offset for stage 1 div for output Q0
+ * @ns1_offset_mask:	mask for stage 1 div for output Q0
+ * @ns2_15_8_offset:	offset for stage 2 div for output Q0 (bits 15:8)
+ * @ns2_7_0_offset:	offset for stage 2 div for output Q0 (bits 7:0)
+ */
+struct clk_register_offsets {
+	u16 oe_offset;
+	u8 oe_mask;
+	u8 dis_mask;
+
+	u16 n_17_16_offset;
+	u8 n_17_16_mask;
+	u16 n_15_8_offset;
+	u16 n_7_0_offset;
+	u16 nfrac_27_24_offset;
+	u8 nfrac_27_24_mask;
+	u16 nfrac_23_16_offset;
+	u16 nfrac_15_8_offset;
+	u16 nfrac_7_0_offset;
+
+	u16 ns1_offset;
+	u8 ns1_offset_mask;
+	u16 ns2_15_8_offset;
+	u16 ns2_7_0_offset;
+};
+
+int bits_to_shift(unsigned int mask);
+int i2cwritebulk(
+	struct i2c_client *client, struct regmap *map,
+	unsigned int reg, u8 val[], size_t val_count);
+int idt24x_get_offsets(
+	u8 output_num,
+	struct clk_register_offsets *offsets);
+int idt24x_set_frequency(struct clk_idt24x_chip *chip);
+
+#endif /* __IDT_CLK_IDT8T49N24X_CORE_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/idt/clk-idt8t49n24x-debugfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/idt/clk-idt8t49n24x-debugfs.c
@@ -0,0 +1,382 @@
+// SPDX-License-Identifier: GPL-2.0
+/* clk-idt8t49n24x-debugfs.c - Debugfs support for 8T49N24x
+ *
+ * Copyright (C) 2018, Integrated Device Technology, Inc. <david.cater@idt.com>
+ *
+ * See https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html
+ * This program is distributed "AS IS" and  WITHOUT ANY WARRANTY;
+ * including the implied warranties of MERCHANTABILITY, FITNESS FOR
+ * A PARTICULAR PURPOSE, or NON-INFRINGEMENT.
+ */
+
+#include <linux/debugfs.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#include "clk-idt8t49n24x-debugfs.h"
+
+static struct clk_idt24x_chip *idt24x_chip_fordebugfs;
+
+static int idt24x_read_all_settings(
+	struct clk_idt24x_chip *chip, char *output_buffer, int count)
+{
+	u8 settings[NUM_CONFIG_REGISTERS];
+	int err = 0;
+	int x;
+
+	err = regmap_bulk_read(
+		chip->regmap, 0x0, settings, NUM_CONFIG_REGISTERS);
+	if (!err) {
+		output_buffer[0] = '\0';
+		for (x = 0; x < ARRAY_SIZE(settings); x++) {
+			char dbg[4];
+
+			if ((strlen(output_buffer) + 4) > count)
+				return -EINVAL;
+			sprintf(dbg, "%02x ", settings[x]);
+			strcat(output_buffer, dbg);
+		}
+	}
+	return err;
+}
+
+/**
+ * idt24x_debugfs_writer_action - Write handler for the "action" debugfs file.
+ * @fp:			file pointer
+ * @user_buffer:	buffer of text written to file
+ * @count:		size of text in buffer
+ * @position:		pass in current position, return new position
+ *
+ * Return: result of call to simple_write_to_buffer
+ *
+ * Use the "action" file as a trigger for setting all requested
+ * rates. The driver doesn't get any notification when the files
+ * representing the Qx outputs are written to, so something else is
+ * needed to notify the driver that the device should be udpated.
+ *
+ * It doesn't matter what you write to the action debugs file. When the
+ * handler is called, the device will be updated.
+ */
+static ssize_t idt24x_debugfs_writer_action(
+	struct file *fp, const char __user *user_buffer,
+	size_t count, loff_t *position)
+{
+	int err = 0;
+	int x;
+	u32 freq;
+	bool needs_update = true;
+	struct i2c_client *client = idt24x_chip_fordebugfs->i2c_client;
+
+	if (count > DEBUGFS_BUFFER_LENGTH)
+		return -EINVAL;
+
+	for (x = 0; x < NUM_OUTPUTS; x++) {
+		freq = idt24x_chip_fordebugfs->clk[x].debug_freq;
+		if (freq) {
+			needs_update = false;
+			dev_dbg(&client->dev,
+				"%s: calling clk_set_rate with debug frequency for Q%i",
+				__func__, x);
+			err = clk_set_rate(
+				idt24x_chip_fordebugfs->clk[x].hw.clk, freq);
+			if (err) {
+				dev_err(&client->dev,
+					"error calling clk_set_rate for Q%i (%i)\n",
+					x, err);
+			}
+		} else {
+			needs_update = true;
+			idt24x_chip_fordebugfs->clk[x].requested = 0;
+			dev_dbg(&client->dev,
+				"%s: debug frequency for Q%i not set; make sure clock is disabled",
+				__func__, x);
+		}
+	}
+
+	if (needs_update) {
+		dev_dbg(&client->dev,
+			"%s: calling idt24x_set_frequency to ensure any clocks that should be disabled are turned off.",
+			__func__);
+		err = idt24x_set_frequency(idt24x_chip_fordebugfs);
+		if (err) {
+			dev_err(&idt24x_chip_fordebugfs->i2c_client->dev,
+				"%s: error calling idt24x_set_frequency (%i)\n",
+				__func__, err);
+			return err;
+		}
+	}
+
+	return simple_write_to_buffer(
+		idt24x_chip_fordebugfs->dbg_cache, DEBUGFS_BUFFER_LENGTH,
+		position, user_buffer, count);
+}
+
+/**
+ * idt24x_debugfs_reader_action - Read the "action" debugfs file.
+ * @fp:			file pointer
+ * @user_buffer:	buffer of text written to file
+ * @count:		size of text in buffer
+ * @position:		pass in current position, return new position
+ *
+ * Return: whatever was last written to the "action" debugfs file.
+ */
+static ssize_t idt24x_debugfs_reader_action(
+	struct file *fp, char __user *user_buffer, size_t count,
+	loff_t *position)
+{
+	return simple_read_from_buffer(
+		user_buffer, count, position, idt24x_chip_fordebugfs->dbg_cache,
+		DEBUGFS_BUFFER_LENGTH);
+}
+
+/**
+ * idt24x_debugfs_reader_map - display the current registers on the device
+ * @fp:			file pointer
+ * @user_buffer:	buffer of text written to file
+ * @count:		size of text in buffer
+ * @position:		pass in current position, return new position
+ *
+ * Reads the current register map from the attached chip via I2C and
+ * returns it.
+ *
+ * Return: result of call to simple_read_from_buffer
+ */
+static ssize_t idt24x_debugfs_reader_map(
+	struct file *fp, char __user *user_buffer, size_t count,
+	loff_t *position)
+{
+	int err = 0;
+	char *buf = kzalloc(5000, GFP_KERNEL);
+
+	dev_dbg(&idt24x_chip_fordebugfs->i2c_client->dev,
+		"calling idt24x_read_all_settings (count: %zu)\n", count);
+	err = idt24x_read_all_settings(idt24x_chip_fordebugfs, buf, 5000);
+	if (err) {
+		dev_err(&idt24x_chip_fordebugfs->i2c_client->dev,
+			"error calling idt24x_read_all_settings (%i)\n", err);
+		return 0;
+	}
+	/* TMGCDR-1456. We're returning 1 byte too few. */
+	err = simple_read_from_buffer(
+		user_buffer, count, position, buf, strlen(buf));
+	kfree(buf);
+	return err;
+}
+
+/**
+ * idt24x_handle_i2c_debug_token - process "token" written to the i2c file
+ * @dev:	pointer to device structure
+ * @token:	pointer to current char being examined
+ * @reg:	pass in current register, or return register from token.
+ * @val:	resulting array of bytes being parsed
+ * @nextbyte:	position in val array to store next byte
+ *
+ * Utility function to operate on the current "token" (from within a
+ * space-delimited string) written to the i2c debugfs file. It will
+ * either be a register offset or a byte to be added to the val array.
+ * If it is added to the val array, auto-increment nextbyte.
+ *
+ * Return:	0 for success
+ */
+static int idt24x_handle_i2c_debug_token(
+	const struct device *dev, char *token, unsigned int *reg,
+	u8 val[], u16 *nextbyte)
+{
+	int err = 0;
+
+	dev_dbg(dev, "got token (%s)\n", token);
+	if (*reg == -1) {
+		err = kstrtouint(token, 16, reg);
+		if (!err)
+			dev_dbg(dev, "hex register address == 0x%x\n", *reg);
+	} else {
+		u8 temp;
+
+		err = kstrtou8(token, 16, &temp);
+		if (!err) {
+			dev_dbg(dev, "data byte == 0x%x\n", temp);
+			val[*nextbyte] = temp;
+			*nextbyte += 1;
+		}
+	}
+	if (err == -ERANGE)
+		dev_err(dev, "ERANGE error when parsing data\n");
+	else if (err == -EINVAL)
+		dev_err(dev, "EINVAL error when parsing data\n");
+	else if (err)
+		dev_err(dev, "error when parsing data: %i\n", err);
+	return err;
+}
+
+/**
+ * idt24x_debugfs_writer_i2c - debugfs handler for i2c file
+ * @fp:			file pointer
+ * @user_buffer:	buffer of text written to file
+ * @count:		size of text in buffer
+ * @position:		pass in current position, return new position
+ *
+ * Handler for the "i2c" debugfs file. Write to this file to write bytes
+ * via I2C to a particular offset.
+ *
+ * Usage: echo 006c 01 02 0D FF > i2c
+ *
+ * First 4 chars are the 2-byte i2c register offset. Then follow that
+ * with a sequence of 2-char bytes in hex format that you want to write
+ * starting at that offset.
+ *
+ * Return: result of simple_write_to_buffer
+ */
+static ssize_t idt24x_debugfs_writer_i2c(struct file *fp,
+					 const char __user *user_buffer,
+					 size_t count, loff_t *position)
+{
+	int err = 0;
+	int x = 0;
+	int start = 0;
+	ssize_t written;
+	unsigned int reg = -1;
+	u8 val[WRITE_BLOCK_SIZE];
+	u16 nextbyte = 0;
+	char token[16];
+
+	if (count > DEBUGFS_BUFFER_LENGTH)
+		return -EINVAL;
+
+	written = simple_write_to_buffer(
+		idt24x_chip_fordebugfs->dbg_cache, DEBUGFS_BUFFER_LENGTH,
+		position, user_buffer, count);
+	if (written != count) {
+		dev_dbg(&idt24x_chip_fordebugfs->i2c_client->dev,
+			"write count != expected count");
+		return written;
+	}
+
+	for (x = 0; x < count; x++) {
+		token[x - start] = idt24x_chip_fordebugfs->dbg_cache[x];
+		if (idt24x_chip_fordebugfs->dbg_cache[x] == ' ') {
+			token[x - start] = '\0';
+			err = idt24x_handle_i2c_debug_token(
+				&idt24x_chip_fordebugfs->i2c_client->dev,
+				token, &reg, val, &nextbyte);
+			if (err)
+				break;
+			start = x + 1;
+		}
+	}
+
+	/* handle the last token */
+	if (!err) {
+		token[count - start] = '\0';
+		err = idt24x_handle_i2c_debug_token(
+			&idt24x_chip_fordebugfs->i2c_client->dev, token, &reg,
+			val, &nextbyte);
+	}
+
+	if (!err && reg != -1 && nextbyte > 0) {
+		err = i2cwritebulk(
+			idt24x_chip_fordebugfs->i2c_client,
+			idt24x_chip_fordebugfs->regmap,
+			reg, val, nextbyte);
+		if (err) {
+			dev_err(&idt24x_chip_fordebugfs->i2c_client->dev,
+				"error writing data chip (%i)\n", err);
+			return err;
+		}
+		dev_dbg(&idt24x_chip_fordebugfs->i2c_client->dev,
+			"successfully wrote i2c data to chip");
+	}
+
+	return written;
+}
+
+static const struct file_operations idt24x_fops_debug_action = {
+	.read = idt24x_debugfs_reader_action,
+	.write = idt24x_debugfs_writer_action,
+};
+
+static const struct file_operations idt24x_fops_debug_map = {
+	.read = idt24x_debugfs_reader_map
+};
+
+static const struct file_operations idt24x_fops_debug_i2c = {
+	.write = idt24x_debugfs_writer_i2c,
+};
+
+/**
+ * idt24x_expose_via_debugfs - Set up all debugfs files
+ * @client:	pointer to i2c_client structure
+ * @chip:	Device data structure
+ *
+ * Sets up all debugfs files to use for debugging the driver.
+ * Return: error code. 0 if success or debugfs doesn't appear to be enabled.
+ */
+int idt24x_expose_via_debugfs(struct i2c_client *client,
+			      struct clk_idt24x_chip *chip)
+{
+	int output_num;
+
+	/*
+	 * create root directory in /sys/kernel/debugfs
+	 */
+	chip->debugfs_dirroot = debugfs_create_dir("idt24x", NULL);
+	if (!chip->debugfs_dirroot) {
+		/* debugfs probably not enabled. Don't fail the probe. */
+		return 0;
+	}
+
+	/*
+	 * create files in the root directory. This requires read and
+	 * write file operations
+	 */
+	chip->debugfs_fileaction = debugfs_create_file(
+		"action", 0644, chip->debugfs_dirroot, NULL,
+		&idt24x_fops_debug_action);
+	if (!chip->debugfs_fileaction) {
+		dev_err(&client->dev,
+			"%s: error creating action file", __func__);
+		return (-ENODEV);
+	}
+
+	chip->debugfs_map = debugfs_create_file(
+		"map", 0444, chip->debugfs_dirroot, NULL,
+		&idt24x_fops_debug_map);
+	if (!chip->debugfs_map) {
+		dev_err(&client->dev,
+			"%s: error creating map file", __func__);
+		return (-ENODEV);
+	}
+
+	for (output_num = 0; output_num < NUM_OUTPUTS; output_num++) {
+		char name[5];
+
+		sprintf(name, "q%d", output_num);
+		chip->debugfs_fileqfreq[output_num] = debugfs_create_u64(
+			name, 0644, chip->debugfs_dirroot,
+			&chip->clk[output_num].debug_freq);
+		if (!chip->debugfs_fileqfreq[output_num]) {
+			dev_err(&client->dev,
+				"%s: error creating %s debugfs file",
+				__func__, name);
+			return (-ENODEV);
+		}
+	}
+
+	chip->debugfs_filei2c = debugfs_create_file(
+		"i2c", 0644, chip->debugfs_dirroot, NULL,
+		&idt24x_fops_debug_i2c);
+	if (!chip->debugfs_filei2c) {
+		dev_err(&client->dev,
+			"%s: error creating i2c file", __func__);
+		return (-ENODEV);
+	}
+
+	dev_dbg(&client->dev, "%s: success", __func__);
+	idt24x_chip_fordebugfs = chip;
+	return 0;
+}
+
+void idt24x_cleanup_debugfs(struct clk_idt24x_chip *chip)
+{
+	debugfs_remove_recursive(chip->debugfs_dirroot);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/idt/clk-idt8t49n24x-debugfs.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/idt/clk-idt8t49n24x-debugfs.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* clk-idt8t49n24x-debugfs.h - Debugfs support for 8T49N24x
+ *
+ * Copyright (C) 2018, Integrated Device Technology, Inc. <david.cater@idt.com>
+ *
+ * See https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html
+ * This program is distributed "AS IS" and  WITHOUT ANY WARRANTY;
+ * including the implied warranties of MERCHANTABILITY, FITNESS FOR
+ * A PARTICULAR PURPOSE, or NON-INFRINGEMENT.
+ */
+
+#ifndef __IDT_CLK_IDT8T49N24X_DEBUGFS_H_
+#define __IDT_CLK_IDT8T49N24X_DEBUGFS_H_
+
+#include "clk-idt8t49n24x-core.h"
+
+int idt24x_expose_via_debugfs(struct i2c_client *client,
+			      struct clk_idt24x_chip *chip);
+void idt24x_cleanup_debugfs(struct clk_idt24x_chip *chip);
+
+#endif /* __IDT_CLK_IDT8T49N24X_DEBUGFS_H_*/
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/idt/clk-idt8t49n24x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/idt/clk-idt8t49n24x.c
@@ -0,0 +1,641 @@
+// SPDX-License-Identifier: GPL-2.0
+/* clk-idt8t49n24x.c - Program 8T49N24x settings via I2C.
+ *
+ * Copyright (C) 2018, Integrated Device Technology, Inc. <david.cater@idt.com>
+ *
+ * See https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html
+ * This program is distributed "AS IS" and  WITHOUT ANY WARRANTY;
+ * including the implied warranties of MERCHANTABILITY, FITNESS FOR
+ * A PARTICULAR PURPOSE, or NON-INFRINGEMENT.
+ */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "clk-idt8t49n24x-core.h"
+#include "clk-idt8t49n24x-debugfs.h"
+
+#define OUTPUTMODE_HIGHZ	0
+#define OUTPUTMODE_LVDS		2
+#define IDT24x_MIN_FREQ		1000000L
+#define IDT24x_MAX_FREQ		300000000L
+#define DRV_NAME		"idt8t49n24x"
+
+enum clk_idt24x_variant {
+	idt24x
+};
+
+static u32 mask_and_shift(u32 value, u8 mask)
+{
+	value &= mask;
+	return value >> bits_to_shift(mask);
+}
+
+/**
+ * idt24x_set_output_mode - Set the mode for a particular clock
+ * output in the register.
+ * @reg:	The current register value before setting the mode.
+ * @mask:	The bitmask identifying where in the register the
+ *		output mode is stored.
+ * @mode:	The mode to set.
+ *
+ * Return: the new register value with the specified mode bits set.
+ */
+static int idt24x_set_output_mode(u32 reg, u8 mask, u8 mode)
+{
+	if (((reg & mask) >> bits_to_shift(mask)) == OUTPUTMODE_HIGHZ) {
+		reg = reg & ~mask;
+		reg |= (OUTPUTMODE_LVDS << bits_to_shift(mask));
+	}
+	return reg;
+}
+
+/**
+ * idt24x_read_from_hw - Get the current values on the hw
+ * @chip:	Device data structure
+ *
+ * Return: 0 on success, negative errno otherwise.
+ */
+static int idt24x_read_from_hw(struct clk_idt24x_chip *chip)
+{
+	int err;
+	struct i2c_client *client = chip->i2c_client;
+	u32 tmp, tmp2;
+	u8 output;
+
+	err = regmap_read(chip->regmap, IDT24x_REG_DSM_INT_8,
+			  &chip->reg_dsm_int_8);
+	if (err) {
+		dev_err(&client->dev,
+			"%s: error reading IDT24x_REG_DSM_INT_8: %i",
+			__func__, err);
+		return err;
+	}
+	dev_dbg(&client->dev, "%s: reg_dsm_int_8: 0x%x",
+		__func__, chip->reg_dsm_int_8);
+
+	err = regmap_read(chip->regmap, IDT24x_REG_DSMFRAC_20_16_MASK,
+			  &chip->reg_dsm_frac_20_16);
+	if (err) {
+		dev_err(&client->dev,
+			"%s: error reading IDT24x_REG_DSMFRAC_20_16_MASK: %i",
+			__func__, err);
+		return err;
+	}
+	dev_dbg(&client->dev, "%s: reg_dsm_frac_20_16: 0x%x",
+		__func__, chip->reg_dsm_frac_20_16);
+
+	err = regmap_read(chip->regmap, IDT24x_REG_OUTEN, &chip->reg_out_en_x);
+	if (err) {
+		dev_err(&client->dev,
+			"%s: error reading IDT24x_REG_OUTEN: %i",
+			__func__, err);
+		return err;
+	}
+	dev_dbg(&client->dev, "%s: reg_out_en_x: 0x%x",
+		__func__, chip->reg_out_en_x);
+
+	err = regmap_read(chip->regmap, IDT24x_REG_OUTMODE0_1, &tmp);
+	if (err) {
+		dev_err(&client->dev,
+			"%s: error reading IDT24x_REG_OUTMODE0_1: %i",
+			__func__, err);
+		return err;
+	}
+
+	tmp2 = idt24x_set_output_mode(
+		tmp, IDT24x_REG_OUTMODE0_MASK, OUTPUTMODE_LVDS);
+	tmp2 = idt24x_set_output_mode(
+		tmp2, IDT24x_REG_OUTMODE1_MASK, OUTPUTMODE_LVDS);
+	dev_dbg(&client->dev,
+		"%s: reg_out_mode_0_1 original: 0x%x. After setting OUT0/1 to LVDS if necessary: 0x%x",
+		__func__, tmp, tmp2);
+	chip->reg_out_mode_0_1 = tmp2;
+
+	err = regmap_read(chip->regmap, IDT24x_REG_OUTMODE2_3, &tmp);
+	if (err) {
+		dev_err(&client->dev,
+			"%s: error reading IDT24x_REG_OUTMODE2_3: %i",
+			__func__, err);
+		return err;
+	}
+
+	tmp2 = idt24x_set_output_mode(
+		tmp, IDT24x_REG_OUTMODE2_MASK, OUTPUTMODE_LVDS);
+	tmp2 = idt24x_set_output_mode(
+		tmp2, IDT24x_REG_OUTMODE3_MASK, OUTPUTMODE_LVDS);
+	dev_dbg(&client->dev,
+		"%s: reg_out_mode_2_3 original: 0x%x. After setting OUT2/3 to LVDS if necessary: 0x%x",
+		__func__, tmp, tmp2);
+	chip->reg_out_mode_2_3 = tmp2;
+
+	err = regmap_read(chip->regmap, IDT24x_REG_Q_DIS, &chip->reg_qx_dis);
+	if (err) {
+		dev_err(&client->dev,
+			"%s: error reading IDT24x_REG_Q_DIS: %i",
+			__func__, err);
+		return err;
+	}
+	dev_dbg(&client->dev, "%s: reg_qx_dis: 0x%x",
+		__func__, chip->reg_qx_dis);
+
+	err = regmap_read(chip->regmap, IDT24x_REG_NS1_Q0, &chip->reg_ns1_q0);
+	if (err) {
+		dev_err(&client->dev,
+			"%s: error reading IDT24x_REG_NS1_Q0: %i",
+			__func__, err);
+		return err;
+	}
+	dev_dbg(&client->dev, "%s: reg_ns1_q0: 0x%x",
+		__func__, chip->reg_ns1_q0);
+
+	for (output = 1; output <= 3; output++) {
+		struct clk_register_offsets offsets;
+
+		err = idt24x_get_offsets(output, &offsets);
+		if (err) {
+			dev_err(&client->dev,
+				"%s: error calling idt24x_get_offsets: %i",
+				__func__, err);
+			return err;
+		}
+
+		err = regmap_read(chip->regmap, offsets.n_17_16_offset,
+				  &chip->reg_n_qx_17_16[output - 1]);
+		if (err) {
+			dev_err(&client->dev,
+				"%s: error reading n_17_16_offset for output %d (offset: 0x%x): %i",
+				__func__, output, offsets.n_17_16_offset, err);
+			return err;
+		}
+		dev_dbg(&client->dev,
+			"%s: reg_n_qx_17_16[Q%u]: 0x%x",
+			__func__, output, chip->reg_n_qx_17_16[output - 1]);
+
+		err = regmap_read(chip->regmap, offsets.nfrac_27_24_offset,
+				  &chip->reg_nfrac_qx_27_24[output - 1]);
+		if (err) {
+			dev_err(&client->dev,
+				"%s: error reading nfrac_27_24_offset for output %d (offset: 0x%x): %i",
+				__func__, output,
+				offsets.nfrac_27_24_offset, err);
+			return err;
+		}
+		dev_dbg(&client->dev,
+			"%s: reg_nfrac_qx_27_24[Q%u]: 0x%x",
+			__func__, output,
+			chip->reg_nfrac_qx_27_24[output - 1]);
+	}
+
+	dev_info(&client->dev,
+		 "%s: initial values read from chip successfully",
+		 __func__);
+
+	/* Also read DBL_DIS to determine whether the doubler is disabled. */
+	err = regmap_read(chip->regmap, IDT24x_REG_DBL_DIS, &tmp);
+	if (err) {
+		dev_err(&client->dev,
+			"%s: error reading IDT24x_REG_DBL_DIS: %i",
+			__func__, err);
+		return err;
+	}
+	chip->doubler_disabled = mask_and_shift(tmp, IDT24x_REG_DBL_DIS_MASK);
+	dev_dbg(&client->dev, "%s: doubler_disabled: %d",
+		__func__, chip->doubler_disabled);
+
+	return 0;
+}
+
+/**
+ * idt24x_set_rate - Sets the specified output clock to the specified rate.
+ * @hw:		clk_hw struct that identifies the specific output clock.
+ * @rate:	the rate (in Hz) for the specified clock.
+ * @parent_rate:(not sure) the rate for a parent signal (e.g.,
+ *		the VCO feeding the output)
+ *
+ * This function will call idt24_set_frequency, which means it will
+ * calculate divider for all requested outputs and update the attached
+ * device (issue I2C commands to update the registers).
+ *
+ * Return: 0 on success.
+ */
+static int idt24x_set_rate(struct clk_hw *hw, unsigned long rate,
+			   unsigned long parent_rate)
+{
+	int err = 0;
+
+	/*
+	 * hw->clk is the pointer to the specific output clock the user is
+	 * requesting. We use hw to get back to the output structure for
+	 * the output clock. Set the requested rate in the output structure.
+	 * Note that container_of cannot be used to find the device structure
+	 * (clk_idt24x_chip) from clk_hw, because clk_idt24x_chip has an array
+	 * of idt24x_output structs. That is why it is necessary to use
+	 * output->chip to access the device structure.
+	 */
+	struct idt24x_output *output = to_idt24x_output(hw);
+	struct i2c_client *client = output->chip->i2c_client;
+
+	if (rate < output->chip->min_freq || rate > output->chip->max_freq) {
+		dev_err(&client->dev,
+			"requested frequency (%luHz) is out of range\n", rate);
+		return -EINVAL;
+	}
+
+	/*
+	 * Set the requested frequency in the output data structure, and then
+	 * call idt24x_set_frequency. idt24x_set_frequency considers all
+	 * requested frequencies when deciding on a vco frequency and
+	 * calculating dividers.
+	 */
+	output->requested = rate;
+
+	/*
+	 * Also set in the memory location used by the debugfs file
+	 * that exposes the output clock frequency. That allows querying
+	 * the current rate via debugfs.
+	 */
+	output->debug_freq = rate;
+
+	dev_info(&client->dev,
+		 "%s. calling idt24x_set_frequency for Q%u. rate: %lu",
+		 __func__, output->index, rate);
+	err = idt24x_set_frequency(output->chip);
+
+	if (err != 0)
+		dev_err(&client->dev, "error calling set_frequency: %d", err);
+
+	return err;
+}
+
+/**
+ * idt24x_round_rate - get valid rate that is closest to the requested rate
+ * @hw:		clk_hw struct that identifies the specific output clock.
+ * @rate:	the rate (in Hz) for the specified clock.
+ * @parent_rate:(not sure) the rate for a parent signal (e.g., the VCO
+ *		feeding the output). This is an i/o param.
+ *		If the driver supports a parent clock for the output (e.g.,
+ *		the VCO(?), then set this param to indicate what the rate of
+ *		the parent would be (e.g., the VCO frequency) if the rounded
+ *		rate is used.
+ *
+ * Returns the closest rate to the requested rate actually supported by the
+ * chip.
+ *
+ * Return: adjusted rate
+ */
+static long idt24x_round_rate(struct clk_hw *hw, unsigned long rate,
+			      unsigned long *parent_rate)
+{
+	/*
+	 * The chip has fractional output dividers, so assume it
+	 * can provide the requested rate.
+	 *
+	 * TODO: figure out the closest rate that chip can support
+	 * within a low error threshold and return that rate.
+	 */
+	return rate;
+}
+
+/**
+ * idt24x_recalc_rate - return the frequency being provided by the clock.
+ * @hw:			clk_hw struct that identifies the specific output clock.
+ * @parent_rate:	(not sure) the rate for a parent signal (e.g., the
+ *			VCO feeding the output)
+ *
+ * This API appears to be used to read the current values from the hardware
+ * and report the frequency being provided by the clock. Without this function,
+ * the clock will be initialized to 0 by default. The OS appears to be
+ * calling this to find out what the current value of the clock is at
+ * startup, so it can determine when .set_rate is actually changing the
+ * frequency.
+ *
+ * Return: the frequency of the specified clock.
+ */
+static unsigned long idt24x_recalc_rate(struct clk_hw *hw,
+					unsigned long parent_rate)
+{
+	struct idt24x_output *output = to_idt24x_output(hw);
+
+	return output->requested;
+}
+
+/*
+ * Note that .prepare and .unprepare appear to be used more in Gates.
+ * They do not appear to be necessary for this device.
+ * Instead, update the device when .set_rate is called.
+ */
+static const struct clk_ops idt24x_clk_ops = {
+	.recalc_rate = idt24x_recalc_rate,
+	.round_rate = idt24x_round_rate,
+	.set_rate = idt24x_set_rate,
+};
+
+static bool idt24x_regmap_is_volatile(struct device *dev, unsigned int reg)
+{
+	return false;
+}
+
+static bool idt24x_regmap_is_writeable(struct device *dev, unsigned int reg)
+{
+	return true;
+}
+
+static const struct regmap_config idt24x_regmap_config = {
+	.reg_bits = 16,
+	.val_bits = 8,
+	.cache_type = REGCACHE_RBTREE,
+	.max_register = 0xffff,
+	.writeable_reg = idt24x_regmap_is_writeable,
+	.volatile_reg = idt24x_regmap_is_volatile,
+};
+
+/**
+ * idt24x_clk_notifier_cb - Clock rate change callback
+ * @nb:		Pointer to notifier block
+ * @event:	Notification reason
+ * @data:	Pointer to notification data object
+ *
+ * This function is called when the input clock frequency changes.
+ * The callback checks whether a valid bus frequency can be generated after the
+ * change. If so, the change is acknowledged, otherwise the change is aborted.
+ * New dividers are written to the HW in the pre- or post change notification
+ * depending on the scaling direction.
+ *
+ * Return:	NOTIFY_STOP if the rate change should be aborted, NOTIFY_OK
+ *		to acknowledge the change, NOTIFY_DONE if the notification is
+ *		considered irrelevant.
+ */
+static int idt24x_clk_notifier_cb(struct notifier_block *nb,
+				  unsigned long event, void *data)
+{
+	struct clk_notifier_data *ndata = data;
+	struct clk_idt24x_chip *chip = to_clk_idt24x_from_nb(nb);
+	int err = 0;
+
+	dev_info(&chip->i2c_client->dev,
+		 "%s: input frequency changed: %lu Hz. event: %lu",
+		 __func__, ndata->new_rate, event);
+
+	switch (event) {
+	case PRE_RATE_CHANGE: {
+		dev_dbg(&chip->i2c_client->dev, "PRE_RATE_CHANGE\n");
+		return NOTIFY_OK;
+	}
+	case POST_RATE_CHANGE:
+		chip->input_clk_freq = ndata->new_rate;
+		/*
+		 * Can't call clock API clk_set_rate here; I believe
+		 * it will be ignored if the rate is the same as we
+		 * set previously. Need to call our internal function.
+		 */
+		dev_dbg(&chip->i2c_client->dev,
+			"POST_RATE_CHANGE. Calling idt24x_set_frequency\n");
+		err = idt24x_set_frequency(chip);
+		if (err)
+			dev_err(&chip->i2c_client->dev,
+				"error calling idt24x_set_frequency (%i)\n",
+				err);
+		return NOTIFY_OK;
+	case ABORT_RATE_CHANGE:
+		return NOTIFY_OK;
+	default:
+		return NOTIFY_DONE;
+	}
+}
+
+static struct clk_hw *of_clk_idt24x_get(
+	struct of_phandle_args *clkspec, void *_data)
+{
+	struct clk_idt24x_chip *chip = _data;
+	unsigned int idx = clkspec->args[0];
+
+	if (idx >= ARRAY_SIZE(chip->clk)) {
+		pr_err("%s: invalid index %u\n", __func__, idx);
+		return ERR_PTR(-EINVAL);
+	}
+
+	return &chip->clk[idx].hw;
+}
+
+/**
+ * idt24x_probe - main entry point for ccf driver
+ * @client:	pointer to i2c_client structure
+ * @id:		pointer to i2c_device_id structure
+ *
+ * Main entry point function that gets called to initialize the driver.
+ *
+ * Return: 0 for success.
+ */
+static int idt24x_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct clk_idt24x_chip *chip;
+	struct clk_init_data init;
+
+	int err = 0;
+	int x;
+	char buf[6];
+
+	dev_info(&client->dev, "%s", __func__);
+	chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
+	if (!chip)
+		return -ENOMEM;
+
+	init.ops = &idt24x_clk_ops;
+	init.flags = 0;
+	init.num_parents = 0;
+	chip->i2c_client = client;
+
+	chip->min_freq = IDT24x_MIN_FREQ;
+	chip->max_freq = IDT24x_MAX_FREQ;
+
+	for (x = 0; x < NUM_INPUTS + 1; x++) {
+		char name[12];
+
+		sprintf(name, x == NUM_INPUTS ? "input-xtal" : "input-clk%i",
+			x);
+		dev_dbg(&client->dev, "attempting to get %s", name);
+		chip->input_clk = devm_clk_get(&client->dev, name);
+		if (IS_ERR(chip->input_clk)) {
+			err = PTR_ERR(chip->input_clk);
+			/*
+			 * TODO: Handle EPROBE_DEFER error, which indicates
+			 * that the input_clk isn't available now but may be
+			 * later when the appropriate module is loaded.
+			 */
+		} else {
+			err = 0;
+			chip->input_clk_num = x;
+			break;
+		}
+	}
+
+	if (err) {
+		dev_err(&client->dev, "Unable to get input clock (%u).", err);
+		chip->input_clk = NULL;
+		return err;
+	}
+
+	chip->input_clk_freq = clk_get_rate(chip->input_clk);
+	dev_dbg(&client->dev, "Got input-freq from input-clk in device tree: %uHz",
+		chip->input_clk_freq);
+
+	chip->input_clk_nb.notifier_call = idt24x_clk_notifier_cb;
+	if (clk_notifier_register(chip->input_clk, &chip->input_clk_nb))
+		dev_warn(&client->dev,
+			 "Unable to register clock notifier for input_clk.");
+
+	dev_dbg(&client->dev, "%s: about to read settings: %zu",
+		__func__, ARRAY_SIZE(chip->settings));
+
+	err = of_property_read_u8_array(
+		client->dev.of_node, "settings", chip->settings,
+		ARRAY_SIZE(chip->settings));
+	if (!err) {
+		dev_dbg(&client->dev, "settings property specified in DT");
+		chip->has_settings = true;
+	} else {
+		if (err == -EOVERFLOW) {
+			dev_alert(&client->dev,
+				  "EOVERFLOW error trying to read the settings. ARRAY_SIZE: %zu",
+				  ARRAY_SIZE(chip->settings));
+			return err;
+		}
+		dev_dbg(&client->dev,
+			"settings property not specified in DT (or there was an error that can be ignored: %i). The settings property is optional.",
+			err);
+	}
+
+	/*
+	 * Requested output frequencies cannot be specified in the DT.
+	 * Either a consumer needs to use the clock API to request the rate,
+	 * or use debugfs to set the rate from user space. Use clock-names in
+	 * DT to specify the output clock.
+	 */
+
+	chip->regmap = devm_regmap_init_i2c(client, &idt24x_regmap_config);
+	if (IS_ERR(chip->regmap)) {
+		dev_err(&client->dev, "failed to allocate register map\n");
+		return PTR_ERR(chip->regmap);
+	}
+
+	dev_dbg(&client->dev, "%s: call i2c_set_clientdata", __func__);
+	i2c_set_clientdata(client, chip);
+
+	if (chip->has_settings) {
+		/*
+		 * A raw settings array was specified in the DT. Write the
+		 * settings to the device immediately.
+		 */
+		err = i2cwritebulk(
+			chip->i2c_client, chip->regmap, 0, chip->settings,
+			ARRAY_SIZE(chip->settings));
+		if (err) {
+			dev_err(&client->dev,
+				"error writing all settings to chip (%i)\n",
+				err);
+			return err;
+		}
+		dev_dbg(&client->dev, "successfully wrote full settings array");
+	}
+
+	/*
+	 * Whether or not settings were written to the device, read all
+	 * current values from the hw.
+	 */
+	dev_dbg(&client->dev, "read from HW");
+	err = idt24x_read_from_hw(chip);
+	if (err) {
+		dev_err(&client->dev,
+			"failed calling idt24x_read_from_hw (%i)\n", err);
+		return err;
+	}
+
+	/* Create all 4 clocks */
+	for (x = 0; x < NUM_OUTPUTS; x++) {
+		init.name = kasprintf(
+			GFP_KERNEL, "%s.Q%i", client->dev.of_node->name, x);
+		chip->clk[x].chip = chip;
+		chip->clk[x].hw.init = &init;
+		chip->clk[x].index = x;
+		err = devm_clk_hw_register(&client->dev, &chip->clk[x].hw);
+		kfree(init.name); /* clock framework made a copy of the name */
+		if (err) {
+			dev_err(&client->dev, "clock registration failed\n");
+			return err;
+		}
+		dev_dbg(&client->dev, "successfully registered Q%i", x);
+	}
+
+	if (err) {
+		dev_err(&client->dev, "clock registration failed\n");
+		return err;
+	}
+
+	err = of_clk_add_hw_provider(
+		client->dev.of_node, of_clk_idt24x_get, chip);
+	if (err) {
+		dev_err(&client->dev, "unable to add clk provider\n");
+		return err;
+	}
+
+	err = idt24x_expose_via_debugfs(client, chip);
+	if (err) {
+		dev_err(&client->dev,
+			"error calling idt24x_expose_via_debugfs: %i\n", err);
+		return err;
+	}
+
+	if (chip->input_clk_num == NUM_INPUTS)
+		sprintf(buf, "XTAL");
+	else
+		sprintf(buf, "CLK%i", chip->input_clk_num);
+	dev_info(&client->dev, "probe success. input freq: %uHz (%s), settings string? %s\n",
+		 chip->input_clk_freq, buf,
+		 chip->has_settings ? "true" : "false");
+	return 0;
+}
+
+static int idt24x_remove(struct i2c_client *client)
+{
+	struct clk_idt24x_chip *chip = to_clk_idt24x_from_client(&client);
+
+	dev_info(&client->dev, "%s", __func__);
+	of_clk_del_provider(client->dev.of_node);
+	idt24x_cleanup_debugfs(chip);
+
+	if (!chip->input_clk)
+		clk_notifier_unregister(
+			chip->input_clk, &chip->input_clk_nb);
+	return 0;
+}
+
+static const struct i2c_device_id idt24x_id[] = {
+	{ "idt8t49n24x", idt24x },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, idt24x_id);
+
+static const struct of_device_id idt24x_of_match[] = {
+	{ .compatible = "idt,idt8t49n241" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, idt24x_of_match);
+
+static struct i2c_driver idt24x_driver = {
+	.driver = {
+		.name = DRV_NAME,
+		.of_match_table = idt24x_of_match,
+	},
+	.probe = idt24x_probe,
+	.remove = idt24x_remove,
+	.id_table = idt24x_id,
+};
+
+module_i2c_driver(idt24x_driver);
+
+MODULE_DESCRIPTION("8T49N24x ccf driver");
+MODULE_AUTHOR("David Cater <david.cater@idt.com>");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/imx/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/imx/Kconfig
@@ -30,5 +30,6 @@
 	bool "IMX8QXP SCU Clock"
 	depends on ARCH_MXC && IMX_SCU && ARM64
 	select MXC_CLK_SCU
+	select MXC_CLK
 	help
 	  Build the driver for IMX8QXP SCU based clocks.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/imx/clk-composite-8m.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/imx/clk-composite-8m.c
@@ -95,7 +95,7 @@
 	int prediv_value;
 	int div_value;
 	int ret;
-	u32 val;
+	u32 orig, val;
 
 	ret = imx8m_clk_composite_compute_dividers(rate, parent_rate,
 						&prediv_value, &div_value);
@@ -104,13 +104,15 @@
 
 	spin_lock_irqsave(divider->lock, flags);
 
-	val = readl(divider->reg);
-	val &= ~((clk_div_mask(divider->width) << divider->shift) |
-			(clk_div_mask(PCG_DIV_WIDTH) << PCG_DIV_SHIFT));
+	orig = readl(divider->reg);
+	val = orig & ~((clk_div_mask(divider->width) << divider->shift) |
+		       (clk_div_mask(PCG_DIV_WIDTH) << PCG_DIV_SHIFT));
 
 	val |= (u32)(prediv_value  - 1) << divider->shift;
 	val |= (u32)(div_value - 1) << PCG_DIV_SHIFT;
-	writel(val, divider->reg);
+
+	if (val != orig)
+		writel(val, divider->reg);
 
 	spin_unlock_irqrestore(divider->lock, flags);
 
@@ -142,6 +144,7 @@
 	mux->reg = reg;
 	mux->shift = PCG_PCS_SHIFT;
 	mux->mask = PCG_PCS_MASK;
+	mux->lock = &imx_ccm_lock;
 
 	div = kzalloc(sizeof(*div), GFP_KERNEL);
 	if (!div)
@@ -161,6 +164,7 @@
 	gate_hw = &gate->hw;
 	gate->reg = reg;
 	gate->bit_idx = PCG_CGC_SHIFT;
+	gate->lock = &imx_ccm_lock;
 
 	hw = clk_hw_register_composite(NULL, name, parent_names, num_parents,
 			mux_hw, &clk_mux_ops, div_hw,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/imx/clk-imx6sx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/imx/clk-imx6sx.c
@@ -287,13 +287,13 @@
 	hws[IMX6SX_CLK_SSI3_SEL]           = imx_clk_hw_mux("ssi3_sel",         base + 0x1c,  14,     2,      ssi_sels,          ARRAY_SIZE(ssi_sels));
 	hws[IMX6SX_CLK_SSI2_SEL]           = imx_clk_hw_mux("ssi2_sel",         base + 0x1c,  12,     2,      ssi_sels,          ARRAY_SIZE(ssi_sels));
 	hws[IMX6SX_CLK_SSI1_SEL]           = imx_clk_hw_mux("ssi1_sel",         base + 0x1c,  10,     2,      ssi_sels,          ARRAY_SIZE(ssi_sels));
-	hws[IMX6SX_CLK_QSPI1_SEL]          = imx_clk_hw_mux_flags("qspi1_sel", base + 0x1c,  7, 3, qspi1_sels, ARRAY_SIZE(qspi1_sels), CLK_SET_RATE_PARENT);
+	hws[IMX6SX_CLK_QSPI1_SEL]          = imx_clk_hw_mux("qspi1_sel",        base + 0x1c,  7,      3,      qspi1_sels,        ARRAY_SIZE(qspi1_sels));
 	hws[IMX6SX_CLK_PERCLK_SEL]         = imx_clk_hw_mux("perclk_sel",       base + 0x1c,  6,      1,      perclk_sels,       ARRAY_SIZE(perclk_sels));
 	hws[IMX6SX_CLK_VID_SEL]            = imx_clk_hw_mux("vid_sel",          base + 0x20,  21,     3,      vid_sels,          ARRAY_SIZE(vid_sels));
 	hws[IMX6SX_CLK_ESAI_SEL]           = imx_clk_hw_mux("esai_sel",         base + 0x20,  19,     2,      audio_sels,        ARRAY_SIZE(audio_sels));
 	hws[IMX6SX_CLK_CAN_SEL]            = imx_clk_hw_mux("can_sel",          base + 0x20,  8,      2,      can_sels,          ARRAY_SIZE(can_sels));
 	hws[IMX6SX_CLK_UART_SEL]           = imx_clk_hw_mux("uart_sel",         base + 0x24,  6,      1,      uart_sels,         ARRAY_SIZE(uart_sels));
-	hws[IMX6SX_CLK_QSPI2_SEL]          = imx_clk_hw_mux_flags("qspi2_sel", base + 0x2c, 15, 3, qspi2_sels, ARRAY_SIZE(qspi2_sels), CLK_SET_RATE_PARENT);
+	hws[IMX6SX_CLK_QSPI2_SEL]          = imx_clk_hw_mux("qspi2_sel",        base + 0x2c,  15,     3,      qspi2_sels,        ARRAY_SIZE(qspi2_sels));
 	hws[IMX6SX_CLK_SPDIF_SEL]          = imx_clk_hw_mux("spdif_sel",        base + 0x30,  20,     2,      audio_sels,        ARRAY_SIZE(audio_sels));
 	hws[IMX6SX_CLK_AUDIO_SEL]          = imx_clk_hw_mux("audio_sel",        base + 0x30,  7,      2,      audio_sels,        ARRAY_SIZE(audio_sels));
 	hws[IMX6SX_CLK_ENET_PRE_SEL]       = imx_clk_hw_mux("enet_pre_sel",     base + 0x34,  15,     3,      enet_pre_sels,     ARRAY_SIZE(enet_pre_sels));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/imx/clk-imx6ul.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/imx/clk-imx6ul.c
@@ -161,7 +161,6 @@
 	hws[IMX6UL_PLL5_BYPASS] = imx_clk_hw_mux_flags("pll5_bypass", base + 0xa0, 16, 1, pll5_bypass_sels, ARRAY_SIZE(pll5_bypass_sels), CLK_SET_RATE_PARENT);
 	hws[IMX6UL_PLL6_BYPASS] = imx_clk_hw_mux_flags("pll6_bypass", base + 0xe0, 16, 1, pll6_bypass_sels, ARRAY_SIZE(pll6_bypass_sels), CLK_SET_RATE_PARENT);
 	hws[IMX6UL_PLL7_BYPASS] = imx_clk_hw_mux_flags("pll7_bypass", base + 0x20, 16, 1, pll7_bypass_sels, ARRAY_SIZE(pll7_bypass_sels), CLK_SET_RATE_PARENT);
-	hws[IMX6UL_CLK_CSI_SEL] = imx_clk_hw_mux_flags("csi_sel", base + 0x3c, 9, 2, csi_sels, ARRAY_SIZE(csi_sels), CLK_SET_RATE_PARENT);
 
 	/* Do not bypass PLLs initially */
 	clk_set_parent(hws[IMX6UL_PLL1_BYPASS]->clk, hws[IMX6UL_CLK_PLL1]->clk);
@@ -270,6 +269,7 @@
 	hws[IMX6UL_CLK_ECSPI_SEL]	  = imx_clk_hw_mux("ecspi_sel",	base + 0x38, 18, 1, ecspi_sels, ARRAY_SIZE(ecspi_sels));
 	hws[IMX6UL_CLK_LCDIF_PRE_SEL]	  = imx_clk_hw_mux_flags("lcdif_pre_sel", base + 0x38, 15, 3, lcdif_pre_sels, ARRAY_SIZE(lcdif_pre_sels), CLK_SET_RATE_PARENT);
 	hws[IMX6UL_CLK_LCDIF_SEL]	  = imx_clk_hw_mux("lcdif_sel",	base + 0x38, 9, 3, lcdif_sels, ARRAY_SIZE(lcdif_sels));
+	hws[IMX6UL_CLK_CSI_SEL]		  = imx_clk_hw_mux("csi_sel", base + 0x3c, 9, 2, csi_sels, ARRAY_SIZE(csi_sels));
 
 	hws[IMX6UL_CLK_LDB_DI0_DIV_SEL]  = imx_clk_hw_mux("ldb_di0", base + 0x20, 10, 1, ldb_di0_div_sels, ARRAY_SIZE(ldb_di0_div_sels));
 	hws[IMX6UL_CLK_LDB_DI1_DIV_SEL]  = imx_clk_hw_mux("ldb_di1", base + 0x20, 11, 1, ldb_di1_div_sels, ARRAY_SIZE(ldb_di1_div_sels));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/imx/clk-imx7d.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/imx/clk-imx7d.c
@@ -859,7 +859,6 @@
 	hws[IMX7D_WDOG4_ROOT_CLK] = imx_clk_hw_gate4("wdog4_root_clk", "wdog_post_div", base + 0x49f0, 0);
 	hws[IMX7D_KPP_ROOT_CLK] = imx_clk_hw_gate4("kpp_root_clk", "ipg_root_clk", base + 0x4aa0, 0);
 	hws[IMX7D_CSI_MCLK_ROOT_CLK] = imx_clk_hw_gate4("csi_mclk_root_clk", "csi_mclk_post_div", base + 0x4490, 0);
-	hws[IMX7D_AUDIO_MCLK_ROOT_CLK] = imx_clk_hw_gate4("audio_mclk_root_clk", "audio_mclk_post_div", base + 0x4790, 0);
 	hws[IMX7D_WRCLK_ROOT_CLK] = imx_clk_hw_gate4("wrclk_root_clk", "wrclk_post_div", base + 0x47a0, 0);
 	hws[IMX7D_USB_CTRL_CLK] = imx_clk_hw_gate4("usb_ctrl_clk", "ahb_root_clk", base + 0x4680, 0);
 	hws[IMX7D_USB_PHY1_CLK] = imx_clk_hw_gate4("usb_phy1_clk", "pll_usb1_main_clk", base + 0x46a0, 0);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/imx/clk-imx7ulp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/imx/clk-imx7ulp.c
@@ -24,8 +24,8 @@
 static const char * const spll_sels[]		= { "spll", "spll_pfd_sel", };
 static const char * const apll_pfd_sels[]	= { "apll_pfd0", "apll_pfd1", "apll_pfd2", "apll_pfd3", };
 static const char * const apll_sels[]		= { "apll", "apll_pfd_sel", };
-static const char * const scs_sels[]		= { "dummy", "sosc", "sirc", "firc", "dummy", "apll_sel", "spll_sel", "upll", };
-static const char * const ddr_sels[]		= { "apll_pfd_sel", "upll", };
+static const char * const scs_sels[]		= { "dummy", "sosc", "sirc", "firc", "dummy", "apll_sel", "spll_sel", "dummy", };
+static const char * const ddr_sels[]		= { "apll_pfd_sel", "dummy", "dummy", "dummy", };
 static const char * const nic_sels[]		= { "firc", "ddr_clk", };
 static const char * const periph_plat_sels[]	= { "dummy", "nic1_bus_clk", "nic1_clk", "ddr_clk", "apll_pfd2", "apll_pfd1", "apll_pfd0", "upll", };
 static const char * const periph_bus_sels[]	= { "dummy", "sosc_bus_clk", "mpll", "firc_bus_clk", "rosc", "nic1_bus_clk", "nic1_clk", "spll_bus_clk", };
@@ -40,6 +40,7 @@
 	{ .val = 5, .div = 16, },
 	{ .val = 6, .div = 32, },
 	{ .val = 7, .div = 64, },
+	{ /* sentinel */ },
 };
 
 static const int pcc2_uart_clk_ids[] __initconst = {
@@ -118,7 +119,7 @@
 	clks[IMX7ULP_CLK_SYS_SEL]	= imx_clk_hw_mux2("scs_sel", base + 0x14, 24, 4, scs_sels, ARRAY_SIZE(scs_sels));
 	clks[IMX7ULP_CLK_HSRUN_SYS_SEL] = imx_clk_hw_mux2("hsrun_scs_sel", base + 0x1c, 24, 4, scs_sels, ARRAY_SIZE(scs_sels));
 	clks[IMX7ULP_CLK_NIC_SEL]	= imx_clk_hw_mux2("nic_sel", base + 0x40, 28, 1, nic_sels, ARRAY_SIZE(nic_sels));
-	clks[IMX7ULP_CLK_DDR_SEL]	= imx_clk_hw_mux_flags("ddr_sel", base + 0x30, 24, 1, ddr_sels, ARRAY_SIZE(ddr_sels), CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE);
+	clks[IMX7ULP_CLK_DDR_SEL]	= imx_clk_hw_mux_flags("ddr_sel", base + 0x30, 24, 2, ddr_sels, ARRAY_SIZE(ddr_sels), CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE);
 
 	clks[IMX7ULP_CLK_CORE_DIV]	= imx_clk_hw_divider_flags("divcore",	"scs_sel",  base + 0x14, 16, 4, CLK_SET_RATE_PARENT);
 	clks[IMX7ULP_CLK_HSRUN_CORE_DIV] = imx_clk_hw_divider_flags("hsrun_divcore", "hsrun_scs_sel", base + 0x1c, 16, 4, CLK_SET_RATE_PARENT);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/imx/clk-imx8mm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/imx/clk-imx8mm.c
@@ -26,73 +26,6 @@
 static u32 share_count_pdm;
 static u32 share_count_nand;
 
-static const struct imx_pll14xx_rate_table imx8mm_pll1416x_tbl[] = {
-	PLL_1416X_RATE(1800000000U, 225, 3, 0),
-	PLL_1416X_RATE(1600000000U, 200, 3, 0),
-	PLL_1416X_RATE(1200000000U, 300, 3, 1),
-	PLL_1416X_RATE(1000000000U, 250, 3, 1),
-	PLL_1416X_RATE(800000000U,  200, 3, 1),
-	PLL_1416X_RATE(750000000U,  250, 2, 2),
-	PLL_1416X_RATE(700000000U,  350, 3, 2),
-	PLL_1416X_RATE(600000000U,  300, 3, 2),
-};
-
-static const struct imx_pll14xx_rate_table imx8mm_audiopll_tbl[] = {
-	PLL_1443X_RATE(393216000U, 262, 2, 3, 9437),
-	PLL_1443X_RATE(361267200U, 361, 3, 3, 17511),
-};
-
-static const struct imx_pll14xx_rate_table imx8mm_videopll_tbl[] = {
-	PLL_1443X_RATE(650000000U, 325, 3, 2, 0),
-	PLL_1443X_RATE(594000000U, 198, 2, 2, 0),
-};
-
-static const struct imx_pll14xx_rate_table imx8mm_drampll_tbl[] = {
-	PLL_1443X_RATE(650000000U, 325, 3, 2, 0),
-};
-
-static struct imx_pll14xx_clk imx8mm_audio_pll = {
-		.type = PLL_1443X,
-		.rate_table = imx8mm_audiopll_tbl,
-		.rate_count = ARRAY_SIZE(imx8mm_audiopll_tbl),
-};
-
-static struct imx_pll14xx_clk imx8mm_video_pll = {
-		.type = PLL_1443X,
-		.rate_table = imx8mm_videopll_tbl,
-		.rate_count = ARRAY_SIZE(imx8mm_videopll_tbl),
-};
-
-static struct imx_pll14xx_clk imx8mm_dram_pll = {
-		.type = PLL_1443X,
-		.rate_table = imx8mm_drampll_tbl,
-		.rate_count = ARRAY_SIZE(imx8mm_drampll_tbl),
-};
-
-static struct imx_pll14xx_clk imx8mm_arm_pll = {
-		.type = PLL_1416X,
-		.rate_table = imx8mm_pll1416x_tbl,
-		.rate_count = ARRAY_SIZE(imx8mm_pll1416x_tbl),
-};
-
-static struct imx_pll14xx_clk imx8mm_gpu_pll = {
-		.type = PLL_1416X,
-		.rate_table = imx8mm_pll1416x_tbl,
-		.rate_count = ARRAY_SIZE(imx8mm_pll1416x_tbl),
-};
-
-static struct imx_pll14xx_clk imx8mm_vpu_pll = {
-		.type = PLL_1416X,
-		.rate_table = imx8mm_pll1416x_tbl,
-		.rate_count = ARRAY_SIZE(imx8mm_pll1416x_tbl),
-};
-
-static struct imx_pll14xx_clk imx8mm_sys_pll = {
-		.type = PLL_1416X,
-		.rate_table = imx8mm_pll1416x_tbl,
-		.rate_count = ARRAY_SIZE(imx8mm_pll1416x_tbl),
-};
-
 static const char *pll_ref_sels[] = { "osc_24m", "dummy", "dummy", "dummy", };
 static const char *audio_pll1_bypass_sels[] = {"audio_pll1", "audio_pll1_ref_sel", };
 static const char *audio_pll2_bypass_sels[] = {"audio_pll2", "audio_pll2_ref_sel", };
@@ -396,16 +329,16 @@
 	clks[IMX8MM_SYS_PLL2_REF_SEL] = imx_clk_mux("sys_pll2_ref_sel", base + 0x104, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
 	clks[IMX8MM_SYS_PLL3_REF_SEL] = imx_clk_mux("sys_pll3_ref_sel", base + 0x114, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
 
-	clks[IMX8MM_AUDIO_PLL1] = imx_clk_pll14xx("audio_pll1", "audio_pll1_ref_sel", base, &imx8mm_audio_pll);
-	clks[IMX8MM_AUDIO_PLL2] = imx_clk_pll14xx("audio_pll2", "audio_pll2_ref_sel", base + 0x14, &imx8mm_audio_pll);
-	clks[IMX8MM_VIDEO_PLL1] = imx_clk_pll14xx("video_pll1", "video_pll1_ref_sel", base + 0x28, &imx8mm_video_pll);
-	clks[IMX8MM_DRAM_PLL] = imx_clk_pll14xx("dram_pll", "dram_pll_ref_sel", base + 0x50, &imx8mm_dram_pll);
-	clks[IMX8MM_GPU_PLL] = imx_clk_pll14xx("gpu_pll", "gpu_pll_ref_sel", base + 0x64, &imx8mm_gpu_pll);
-	clks[IMX8MM_VPU_PLL] = imx_clk_pll14xx("vpu_pll", "vpu_pll_ref_sel", base + 0x74, &imx8mm_vpu_pll);
-	clks[IMX8MM_ARM_PLL] = imx_clk_pll14xx("arm_pll", "arm_pll_ref_sel", base + 0x84, &imx8mm_arm_pll);
-	clks[IMX8MM_SYS_PLL1] = imx_clk_pll14xx("sys_pll1", "sys_pll1_ref_sel", base + 0x94, &imx8mm_sys_pll);
-	clks[IMX8MM_SYS_PLL2] = imx_clk_pll14xx("sys_pll2", "sys_pll2_ref_sel", base + 0x104, &imx8mm_sys_pll);
-	clks[IMX8MM_SYS_PLL3] = imx_clk_pll14xx("sys_pll3", "sys_pll3_ref_sel", base + 0x114, &imx8mm_sys_pll);
+	clks[IMX8MM_AUDIO_PLL1] = imx_clk_pll14xx("audio_pll1", "audio_pll1_ref_sel", base, &imx_1443x_pll);
+	clks[IMX8MM_AUDIO_PLL2] = imx_clk_pll14xx("audio_pll2", "audio_pll2_ref_sel", base + 0x14, &imx_1443x_pll);
+	clks[IMX8MM_VIDEO_PLL1] = imx_clk_pll14xx("video_pll1", "video_pll1_ref_sel", base + 0x28, &imx_1443x_pll);
+	clks[IMX8MM_DRAM_PLL] = imx_clk_pll14xx("dram_pll", "dram_pll_ref_sel", base + 0x50, &imx_1443x_pll);
+	clks[IMX8MM_GPU_PLL] = imx_clk_pll14xx("gpu_pll", "gpu_pll_ref_sel", base + 0x64, &imx_1416x_pll);
+	clks[IMX8MM_VPU_PLL] = imx_clk_pll14xx("vpu_pll", "vpu_pll_ref_sel", base + 0x74, &imx_1416x_pll);
+	clks[IMX8MM_ARM_PLL] = imx_clk_pll14xx("arm_pll", "arm_pll_ref_sel", base + 0x84, &imx_1416x_pll);
+	clks[IMX8MM_SYS_PLL1] = imx_clk_pll14xx("sys_pll1", "sys_pll1_ref_sel", base + 0x94, &imx_1416x_pll);
+	clks[IMX8MM_SYS_PLL2] = imx_clk_pll14xx("sys_pll2", "sys_pll2_ref_sel", base + 0x104, &imx_1416x_pll);
+	clks[IMX8MM_SYS_PLL3] = imx_clk_pll14xx("sys_pll3", "sys_pll3_ref_sel", base + 0x114, &imx_1416x_pll);
 
 	/* PLL bypass out */
 	clks[IMX8MM_AUDIO_PLL1_BYPASS] = imx_clk_mux_flags("audio_pll1_bypass", base, 16, 1, audio_pll1_bypass_sels, ARRAY_SIZE(audio_pll1_bypass_sels), CLK_SET_RATE_PARENT);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/imx/clk-imx8mn.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/imx/clk-imx8mn.c
@@ -189,27 +189,27 @@
 						      "sys_pll3_out", "clk_ext4", };
 
 static const char * const imx8mn_sai2_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
-						"video_pll1_out", "sys_pll1_133m", "osc_hdmi",
+						"video_pll1_out", "sys_pll1_133m", "dummy",
 						"clk_ext3", "clk_ext4", };
 
 static const char * const imx8mn_sai3_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
-						"video_pll1_out", "sys_pll1_133m", "osc_hdmi",
+						"video_pll1_out", "sys_pll1_133m", "dummy",
 						"clk_ext3", "clk_ext4", };
 
 static const char * const imx8mn_sai5_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
-						"video_pll1_out", "sys_pll1_133m", "osc_hdmi",
+						"video_pll1_out", "sys_pll1_133m", "dummy",
 						"clk_ext2", "clk_ext3", };
 
 static const char * const imx8mn_sai6_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
-						"video_pll1_out", "sys_pll1_133m", "osc_hdmi",
+						"video_pll1_out", "sys_pll1_133m", "dummy",
 						"clk_ext3", "clk_ext4", };
 
 static const char * const imx8mn_sai7_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
-						"video_pll1_out", "sys_pll1_133m", "osc_hdmi",
+						"video_pll1_out", "sys_pll1_133m", "dummy",
 						"clk_ext3", "clk_ext4", };
 
 static const char * const imx8mn_spdif1_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
-						  "video_pll1_out", "sys_pll1_133m", "osc_hdmi",
+						  "video_pll1_out", "sys_pll1_133m", "dummy",
 						  "clk_ext2", "clk_ext3", };
 
 static const char * const imx8mn_enet_ref_sels[] = {"osc_24m", "sys_pll2_125m", "sys_pll2_50m",
@@ -358,9 +358,9 @@
 
 static const char * const imx8mn_dram_core_sels[] = {"dram_pll_out", "dram_alt_root", };
 
-static const char * const imx8mn_clko1_sels[] = {"osc_24m", "sys_pll1_800m", "osc_27m",
-						 "sys_pll1_200m", "audio_pll2_out", "vpu_pll",
-						 "sys_pll1_80m", };
+static const char * const imx8mn_clko1_sels[] = {"osc_24m", "sys_pll1_800m", "dummy",
+						 "sys_pll1_200m", "audio_pll2_out", "sys_pll2_500m",
+						 "dummy", "sys_pll1_80m", };
 static const char * const imx8mn_clko2_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_400m",
 						 "sys_pll2_166m", "sys_pll3_out", "audio_pll1_out",
 						 "video_pll1_out", "osc_32k", };
@@ -582,7 +582,7 @@
 	clks[IMX8MN_CLK_UART2_ROOT] = imx_clk_gate4("uart2_root_clk", "uart2", base + 0x44a0, 0);
 	clks[IMX8MN_CLK_UART3_ROOT] = imx_clk_gate4("uart3_root_clk", "uart3", base + 0x44b0, 0);
 	clks[IMX8MN_CLK_UART4_ROOT] = imx_clk_gate4("uart4_root_clk", "uart4", base + 0x44c0, 0);
-	clks[IMX8MN_CLK_USB1_CTRL_ROOT] = imx_clk_gate4("usb1_ctrl_root_clk", "usb_core_ref", base + 0x44d0, 0);
+	clks[IMX8MN_CLK_USB1_CTRL_ROOT] = imx_clk_gate4("usb1_ctrl_root_clk", "usb_bus", base + 0x44d0, 0);
 	clks[IMX8MN_CLK_GPU_CORE_ROOT] = imx_clk_gate4("gpu_core_root_clk", "gpu_core_div", base + 0x44f0, 0);
 	clks[IMX8MN_CLK_USDHC1_ROOT] = imx_clk_gate4("usdhc1_root_clk", "usdhc1", base + 0x4510, 0);
 	clks[IMX8MN_CLK_USDHC2_ROOT] = imx_clk_gate4("usdhc2_root_clk", "usdhc2", base + 0x4520, 0);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/imx/clk-imx8mq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/imx/clk-imx8mq.c
@@ -157,10 +157,10 @@
 					 "audio_pll2_out", "sys1_pll_266m", "sys3_pll_out", "sys1_pll_100m", };
 
 static const char * const imx8mq_usdhc1_sels[] = {"osc_25m", "sys1_pll_400m", "sys1_pll_800m", "sys2_pll_500m",
-					 "audio_pll2_out", "sys1_pll_266m", "sys3_pll_out", "sys1_pll_100m", };
+					 "sys3_pll_out", "sys1_pll_266m", "audio_pll2_out", "sys1_pll_100m", };
 
 static const char * const imx8mq_usdhc2_sels[] = {"osc_25m", "sys1_pll_400m", "sys1_pll_800m", "sys2_pll_500m",
-					 "audio_pll2_out", "sys1_pll_266m", "sys3_pll_out", "sys1_pll_100m", };
+					 "sys3_pll_out", "sys1_pll_266m", "audio_pll2_out", "sys1_pll_100m", };
 
 static const char * const imx8mq_i2c1_sels[] = {"osc_25m", "sys1_pll_160m", "sys2_pll_50m", "sys3_pll_out", "audio_pll1_out",
 					 "video_pll1_out", "audio_pll2_out", "sys1_pll_133m", };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/imx/clk-pfdv2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/imx/clk-pfdv2.c
@@ -139,6 +139,12 @@
 	u32 val;
 	u8 frac;
 
+	if (!rate)
+		return -EINVAL;
+
+	/* PFD can NOT change rate without gating */
+	WARN_ON(clk_pfdv2_is_enabled(hw));
+
 	tmp = tmp * 18 + rate / 2;
 	do_div(tmp, rate);
 	frac = tmp;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/imx/clk-pll14xx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/imx/clk-pll14xx.c
@@ -41,6 +41,36 @@
 
 #define to_clk_pll14xx(_hw) container_of(_hw, struct clk_pll14xx, hw)
 
+const struct imx_pll14xx_rate_table imx_pll1416x_tbl[] = {
+	PLL_1416X_RATE(1800000000U, 225, 3, 0),
+	PLL_1416X_RATE(1600000000U, 200, 3, 0),
+	PLL_1416X_RATE(1200000000U, 300, 3, 1),
+	PLL_1416X_RATE(1000000000U, 250, 3, 1),
+	PLL_1416X_RATE(800000000U,  200, 3, 1),
+	PLL_1416X_RATE(750000000U,  250, 2, 2),
+	PLL_1416X_RATE(700000000U,  350, 3, 2),
+	PLL_1416X_RATE(600000000U,  300, 3, 2),
+};
+
+const struct imx_pll14xx_rate_table imx_pll1443x_tbl[] = {
+	PLL_1443X_RATE(650000000U, 325, 3, 2, 0),
+	PLL_1443X_RATE(594000000U, 198, 2, 2, 0),
+	PLL_1443X_RATE(393216000U, 262, 2, 3, 9437),
+	PLL_1443X_RATE(361267200U, 361, 3, 3, 17511),
+};
+
+struct imx_pll14xx_clk imx_1443x_pll = {
+	.type = PLL_1443X,
+	.rate_table = imx_pll1443x_tbl,
+	.rate_count = ARRAY_SIZE(imx_pll1443x_tbl),
+};
+
+struct imx_pll14xx_clk imx_1416x_pll = {
+	.type = PLL_1416X,
+	.rate_table = imx_pll1416x_tbl,
+	.rate_count = ARRAY_SIZE(imx_pll1416x_tbl),
+};
+
 static const struct imx_pll14xx_rate_table *imx_get_pll_settings(
 		struct clk_pll14xx *pll, unsigned long rate)
 {
@@ -112,48 +142,22 @@
 	return fvco;
 }
 
-static inline bool clk_pll1416x_mp_change(const struct imx_pll14xx_rate_table *rate,
+static inline bool clk_pll14xx_mp_change(const struct imx_pll14xx_rate_table *rate,
 					  u32 pll_div)
 {
 	u32 old_mdiv, old_pdiv;
 
-	old_mdiv = (pll_div >> MDIV_SHIFT) & MDIV_MASK;
-	old_pdiv = (pll_div >> PDIV_SHIFT) & PDIV_MASK;
+	old_mdiv = (pll_div & MDIV_MASK) >> MDIV_SHIFT;
+	old_pdiv = (pll_div & PDIV_MASK) >> PDIV_SHIFT;
 
 	return rate->mdiv != old_mdiv || rate->pdiv != old_pdiv;
 }
 
-static inline bool clk_pll1443x_mpk_change(const struct imx_pll14xx_rate_table *rate,
-					  u32 pll_div_ctl0, u32 pll_div_ctl1)
-{
-	u32 old_mdiv, old_pdiv, old_kdiv;
-
-	old_mdiv = (pll_div_ctl0 >> MDIV_SHIFT) & MDIV_MASK;
-	old_pdiv = (pll_div_ctl0 >> PDIV_SHIFT) & PDIV_MASK;
-	old_kdiv = (pll_div_ctl1 >> KDIV_SHIFT) & KDIV_MASK;
-
-	return rate->mdiv != old_mdiv || rate->pdiv != old_pdiv ||
-		rate->kdiv != old_kdiv;
-}
-
-static inline bool clk_pll1443x_mp_change(const struct imx_pll14xx_rate_table *rate,
-					  u32 pll_div_ctl0, u32 pll_div_ctl1)
-{
-	u32 old_mdiv, old_pdiv, old_kdiv;
-
-	old_mdiv = (pll_div_ctl0 >> MDIV_SHIFT) & MDIV_MASK;
-	old_pdiv = (pll_div_ctl0 >> PDIV_SHIFT) & PDIV_MASK;
-	old_kdiv = (pll_div_ctl1 >> KDIV_SHIFT) & KDIV_MASK;
-
-	return rate->mdiv != old_mdiv || rate->pdiv != old_pdiv ||
-		rate->kdiv != old_kdiv;
-}
-
 static int clk_pll14xx_wait_lock(struct clk_pll14xx *pll)
 {
 	u32 val;
 
-	return readl_poll_timeout(pll->base, val, val & LOCK_TIMEOUT_US, 0,
+	return readl_poll_timeout(pll->base, val, val & LOCK_STATUS, 0,
 			LOCK_TIMEOUT_US);
 }
 
@@ -174,7 +178,7 @@
 
 	tmp = readl_relaxed(pll->base + 4);
 
-	if (!clk_pll1416x_mp_change(rate, tmp)) {
+	if (!clk_pll14xx_mp_change(rate, tmp)) {
 		tmp &= ~(SDIV_MASK) << SDIV_SHIFT;
 		tmp |= rate->sdiv << SDIV_SHIFT;
 		writel_relaxed(tmp, pll->base + 4);
@@ -239,13 +243,15 @@
 	}
 
 	tmp = readl_relaxed(pll->base + 4);
-	div_val = readl_relaxed(pll->base + 8);
 
-	if (!clk_pll1443x_mpk_change(rate, tmp, div_val)) {
+	if (!clk_pll14xx_mp_change(rate, tmp)) {
 		tmp &= ~(SDIV_MASK) << SDIV_SHIFT;
 		tmp |= rate->sdiv << SDIV_SHIFT;
 		writel_relaxed(tmp, pll->base + 4);
 
+		tmp = rate->kdiv << KDIV_SHIFT;
+		writel_relaxed(tmp, pll->base + 8);
+
 		return 0;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/imx/clk-scu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/imx/clk-scu.c
@@ -43,12 +43,12 @@
 	__le32 rate;
 	__le16 resource;
 	u8 clk;
-} __packed;
+} __packed __aligned(4);
 
 struct req_get_clock_rate {
 	__le16 resource;
 	u8 clk;
-} __packed;
+} __packed __aligned(4);
 
 struct resp_get_clock_rate {
 	__le32 rate;
@@ -84,7 +84,7 @@
 		struct req_get_clock_parent {
 			__le16 resource;
 			u8 clk;
-		} __packed req;
+		} __packed __aligned(4) req;
 		struct resp_get_clock_parent {
 			u8 parent;
 		} resp;
@@ -121,7 +121,7 @@
 	u8 clk;
 	u8 enable;
 	u8 autog;
-} __packed;
+} __packed __aligned(4);
 
 static inline struct clk_scu *to_clk_scu(struct clk_hw *hw)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/imx/clk.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/imx/clk.h
@@ -50,49 +50,52 @@
 	int flags;
 };
 
+extern struct imx_pll14xx_clk imx_1416x_pll;
+extern struct imx_pll14xx_clk imx_1443x_pll;
+
 #define imx_clk_cpu(name, parent_name, div, mux, pll, step) \
-	imx_clk_hw_cpu(name, parent_name, div, mux, pll, step)->clk
+	to_clk(imx_clk_hw_cpu(name, parent_name, div, mux, pll, step))
 
 #define clk_register_gate2(dev, name, parent_name, flags, reg, bit_idx, \
 				cgr_val, clk_gate_flags, lock, share_count) \
-	clk_hw_register_gate2(dev, name, parent_name, flags, reg, bit_idx, \
-				cgr_val, clk_gate_flags, lock, share_count)->clk
+	to_clk(clk_hw_register_gate2(dev, name, parent_name, flags, reg, bit_idx, \
+				cgr_val, clk_gate_flags, lock, share_count))
 
 #define imx_clk_pllv3(type, name, parent_name, base, div_mask) \
-	imx_clk_hw_pllv3(type, name, parent_name, base, div_mask)->clk
+	to_clk(imx_clk_hw_pllv3(type, name, parent_name, base, div_mask))
 
 #define imx_clk_pfd(name, parent_name, reg, idx) \
-	imx_clk_hw_pfd(name, parent_name, reg, idx)->clk
+	to_clk(imx_clk_hw_pfd(name, parent_name, reg, idx))
 
 #define imx_clk_gate_exclusive(name, parent, reg, shift, exclusive_mask) \
-	imx_clk_hw_gate_exclusive(name, parent, reg, shift, exclusive_mask)->clk
+	to_clk(imx_clk_hw_gate_exclusive(name, parent, reg, shift, exclusive_mask))
 
 #define imx_clk_fixed_factor(name, parent, mult, div) \
-	imx_clk_hw_fixed_factor(name, parent, mult, div)->clk
+	to_clk(imx_clk_hw_fixed_factor(name, parent, mult, div))
 
 #define imx_clk_divider2(name, parent, reg, shift, width) \
-	imx_clk_hw_divider2(name, parent, reg, shift, width)->clk
+	to_clk(imx_clk_hw_divider2(name, parent, reg, shift, width))
 
 #define imx_clk_gate_dis(name, parent, reg, shift) \
-	imx_clk_hw_gate_dis(name, parent, reg, shift)->clk
+	to_clk(imx_clk_hw_gate_dis(name, parent, reg, shift))
 
 #define imx_clk_gate2(name, parent, reg, shift) \
-	imx_clk_hw_gate2(name, parent, reg, shift)->clk
+	to_clk(imx_clk_hw_gate2(name, parent, reg, shift))
 
 #define imx_clk_gate2_flags(name, parent, reg, shift, flags) \
-	imx_clk_hw_gate2_flags(name, parent, reg, shift, flags)->clk
+	to_clk(imx_clk_hw_gate2_flags(name, parent, reg, shift, flags))
 
 #define imx_clk_gate2_shared2(name, parent, reg, shift, share_count) \
-	imx_clk_hw_gate2_shared2(name, parent, reg, shift, share_count)->clk
+	to_clk(imx_clk_hw_gate2_shared2(name, parent, reg, shift, share_count))
 
 #define imx_clk_gate3(name, parent, reg, shift) \
-	imx_clk_hw_gate3(name, parent, reg, shift)->clk
+	to_clk(imx_clk_hw_gate3(name, parent, reg, shift))
 
 #define imx_clk_gate4(name, parent, reg, shift) \
-	imx_clk_hw_gate4(name, parent, reg, shift)->clk
+	to_clk(imx_clk_hw_gate4(name, parent, reg, shift))
 
 #define imx_clk_mux(name, reg, shift, width, parents, num_parents) \
-	imx_clk_hw_mux(name, reg, shift, width, parents, num_parents)->clk
+	to_clk(imx_clk_hw_mux(name, reg, shift, width, parents, num_parents))
 
 struct clk *imx_clk_pll14xx(const char *name, const char *parent_name,
 		 void __iomem *base, const struct imx_pll14xx_clk *pll_clk);
@@ -195,6 +198,13 @@
 			      u8 shift, u8 width, const char * const *parents,
 			      int num_parents, void (*fixup)(u32 *val));
 
+static inline struct clk *to_clk(struct clk_hw *hw)
+{
+	if (IS_ERR_OR_NULL(hw))
+		return ERR_CAST(hw);
+	return hw->clk;
+}
+
 static inline struct clk *imx_clk_fixed(const char *name, int rate)
 {
 	return clk_register_fixed_rate(NULL, name, NULL, 0, rate);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/ingenic/cgu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/ingenic/cgu.c
@@ -393,15 +393,21 @@
 ingenic_clk_calc_hw_div(const struct ingenic_cgu_clk_info *clk_info,
 			unsigned int div)
 {
-	unsigned int i;
+	unsigned int i, best_i = 0, best = (unsigned int)-1;
 
 	for (i = 0; i < (1 << clk_info->div.bits)
 				&& clk_info->div.div_table[i]; i++) {
-		if (clk_info->div.div_table[i] >= div)
-			return i;
+		if (clk_info->div.div_table[i] >= div &&
+		    clk_info->div.div_table[i] < best) {
+			best = clk_info->div.div_table[i];
+			best_i = i;
+
+			if (div == best)
+				break;
+		}
 	}
 
-	return i - 1;
+	return best_i;
 }
 
 static unsigned
@@ -420,15 +426,15 @@
 	}
 
 	/* Impose hardware constraints */
-	div = min_t(unsigned, div, 1 << clk_info->div.bits);
-	div = max_t(unsigned, div, 1);
+	div = clamp_t(unsigned int, div, clk_info->div.div,
+		      clk_info->div.div << clk_info->div.bits);
 
 	/*
 	 * If the divider value itself must be divided before being written to
 	 * the divider register, we must ensure we don't have any bits set that
 	 * would be lost as a result of doing so.
 	 */
-	div /= clk_info->div.div;
+	div = DIV_ROUND_UP(div, clk_info->div.div);
 	div *= clk_info->div.div;
 
 	return div;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/ingenic/jz4725b-cgu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/ingenic/jz4725b-cgu.c
@@ -135,11 +135,10 @@
 	},
 
 	[JZ4725B_CLK_I2S] = {
-		"i2s", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
+		"i2s", CGU_CLK_MUX | CGU_CLK_DIV,
 		.parents = { JZ4725B_CLK_EXT, JZ4725B_CLK_PLL_HALF, -1, -1 },
 		.mux = { CGU_REG_CPCCR, 31, 1 },
 		.div = { CGU_REG_I2SCDR, 0, 1, 9, -1, -1, -1 },
-		.gate = { CGU_REG_CLKGR, 6 },
 	},
 
 	[JZ4725B_CLK_SPI] = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/ingenic/jz4770-cgu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/ingenic/jz4770-cgu.c
@@ -432,8 +432,10 @@
 
 	cgu = ingenic_cgu_new(jz4770_cgu_clocks,
 			      ARRAY_SIZE(jz4770_cgu_clocks), np);
-	if (!cgu)
+	if (!cgu) {
 		pr_err("%s: failed to initialise CGU\n", __func__);
+		return;
+	}
 
 	retval = ingenic_cgu_register_clocks(cgu);
 	if (retval)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/ingenic/tcu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/ingenic/tcu.c
@@ -100,15 +100,11 @@
 	bool enabled = false;
 
 	/*
-	 * If the SoC has no global TCU clock, we must ungate the channel's
-	 * clock to be able to access its registers.
-	 * If we have a TCU clock, it will be enabled automatically as it has
-	 * been attached to the regmap.
+	 * According to the programming manual, a timer channel's registers can
+	 * only be accessed when the channel's stop bit is clear.
 	 */
-	if (!tcu->clk) {
-		enabled = !!ingenic_tcu_is_enabled(hw);
-		regmap_write(tcu->map, TCU_REG_TSCR, BIT(info->gate_bit));
-	}
+	enabled = !!ingenic_tcu_is_enabled(hw);
+	regmap_write(tcu->map, TCU_REG_TSCR, BIT(info->gate_bit));
 
 	return enabled;
 }
@@ -119,8 +115,7 @@
 	const struct ingenic_tcu_clk_info *info = tcu_clk->info;
 	struct ingenic_tcu *tcu = tcu_clk->tcu;
 
-	if (!tcu->clk)
-		regmap_write(tcu->map, TCU_REG_TSSR, BIT(info->gate_bit));
+	regmap_write(tcu->map, TCU_REG_TSSR, BIT(info->gate_bit));
 }
 
 static u8 ingenic_tcu_get_parent(struct clk_hw *hw)
@@ -189,7 +184,7 @@
 	u8 prescale;
 
 	if (req_rate > rate)
-		return -EINVAL;
+		return rate;
 
 	prescale = ingenic_tcu_get_prescale(rate, req_rate);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/keystone/pll.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/keystone/pll.c
@@ -209,7 +209,7 @@
 	}
 
 	clk = clk_register_pll(NULL, node->name, parent_name, pll_data);
-	if (clk) {
+	if (!IS_ERR_OR_NULL(clk)) {
 		of_clk_add_provider(node, of_clk_src_simple_get, clk);
 		return;
 	}
@@ -281,12 +281,13 @@
 
 	clk = clk_register_divider(NULL, clk_name, parent_name, 0, reg, shift,
 				 mask, 0, NULL);
-	if (clk) {
-		of_clk_add_provider(node, of_clk_src_simple_get, clk);
-	} else {
+	if (IS_ERR(clk)) {
 		pr_err("%s: error registering divider %s\n", __func__, clk_name);
 		iounmap(reg);
+		return;
 	}
+
+	of_clk_add_provider(node, of_clk_src_simple_get, clk);
 }
 CLK_OF_DECLARE(pll_divider_clock, "ti,keystone,pll-divider-clock", of_pll_div_clk_init);
 
@@ -328,10 +329,12 @@
 	clk = clk_register_mux(NULL, clk_name, (const char **)&parents,
 				ARRAY_SIZE(parents) , 0, reg, shift, mask,
 				0, NULL);
-	if (clk)
-		of_clk_add_provider(node, of_clk_src_simple_get, clk);
-	else
+	if (IS_ERR(clk)) {
 		pr_err("%s: error registering mux %s\n", __func__, clk_name);
+		return;
+	}
+
+	of_clk_add_provider(node, of_clk_src_simple_get, clk);
 }
 CLK_OF_DECLARE(pll_mux_clock, "ti,keystone,pll-mux-clock", of_pll_mux_clk_init);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/keystone/sci-clk.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/keystone/sci-clk.c
@@ -287,6 +287,8 @@
 
 	name = kasprintf(GFP_KERNEL, "clk:%d:%d", sci_clk->dev_id,
 			 sci_clk->clk_id);
+	if (!name)
+		return -ENOMEM;
 
 	init.name = name;
 
@@ -522,7 +524,7 @@
 		np = of_find_node_with_property(np, *clk_name);
 		if (!np) {
 			clk_name++;
-			break;
+			continue;
 		}
 
 		if (!of_device_is_available(np))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/loongson1/clk-loongson1c.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/loongson1/clk-loongson1c.c
@@ -37,6 +37,7 @@
 	[1] = { .val = 1, .div = 4 },
 	[2] = { .val = 2, .div = 3 },
 	[3] = { .val = 3, .div = 3 },
+	[4] = { /* sentinel */ }
 };
 
 void __init ls1x_clk_init(void)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/mediatek/clk-mt2701.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/mediatek/clk-mt2701.c
@@ -675,6 +675,8 @@
 		return PTR_ERR(base);
 
 	clk_data = mtk_alloc_clk_data(CLK_TOP_NR);
+	if (!clk_data)
+		return -ENOMEM;
 
 	mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks),
 								clk_data);
@@ -742,6 +744,8 @@
 
 	if (!infra_clk_data) {
 		infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
+		if (!infra_clk_data)
+			return;
 
 		for (i = 0; i < CLK_INFRA_NR; i++)
 			infra_clk_data->clks[i] = ERR_PTR(-EPROBE_DEFER);
@@ -768,6 +772,8 @@
 
 	if (!infra_clk_data) {
 		infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
+		if (!infra_clk_data)
+			return -ENOMEM;
 	} else {
 		for (i = 0; i < CLK_INFRA_NR; i++) {
 			if (infra_clk_data->clks[i] == ERR_PTR(-EPROBE_DEFER))
@@ -896,6 +902,8 @@
 		return PTR_ERR(base);
 
 	clk_data = mtk_alloc_clk_data(CLK_PERI_NR);
+	if (!clk_data)
+		return -ENOMEM;
 
 	mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks),
 						clk_data);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/mediatek/clk-mt6779.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/mediatek/clk-mt6779.c
@@ -919,6 +919,8 @@
 		    "pwm_sel", 19),
 	GATE_INFRA0(CLK_INFRA_PWM, "infra_pwm",
 		    "pwm_sel", 21),
+	GATE_INFRA0(CLK_INFRA_UART0, "infra_uart0",
+		    "uart_sel", 22),
 	GATE_INFRA0(CLK_INFRA_UART1, "infra_uart1",
 		    "uart_sel", 23),
 	GATE_INFRA0(CLK_INFRA_UART2, "infra_uart2",
@@ -1214,6 +1216,8 @@
 	struct device_node *node = pdev->dev.of_node;
 
 	clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
+	if (!clk_data)
+		return -ENOMEM;
 
 	mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
 
@@ -1235,6 +1239,8 @@
 		return PTR_ERR(base);
 
 	clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
+	if (!clk_data)
+		return -ENOMEM;
 
 	mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks),
 				    clk_data);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/mediatek/clk-mt6797.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/mediatek/clk-mt6797.c
@@ -392,6 +392,8 @@
 		return PTR_ERR(base);
 
 	clk_data = mtk_alloc_clk_data(CLK_TOP_NR);
+	if (!clk_data)
+		return -ENOMEM;
 
 	mtk_clk_register_factors(top_fixed_divs, ARRAY_SIZE(top_fixed_divs),
 				 clk_data);
@@ -564,6 +566,8 @@
 
 	if (!infra_clk_data) {
 		infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
+		if (!infra_clk_data)
+			return;
 
 		for (i = 0; i < CLK_INFRA_NR; i++)
 			infra_clk_data->clks[i] = ERR_PTR(-EPROBE_DEFER);
@@ -588,6 +592,8 @@
 
 	if (!infra_clk_data) {
 		infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
+		if (!infra_clk_data)
+			return -ENOMEM;
 	} else {
 		for (i = 0; i < CLK_INFRA_NR; i++) {
 			if (infra_clk_data->clks[i] == ERR_PTR(-EPROBE_DEFER))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/mediatek/clk-mt7629-eth.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/mediatek/clk-mt7629-eth.c
@@ -83,6 +83,8 @@
 	int r;
 
 	clk_data = mtk_alloc_clk_data(CLK_ETH_NR_CLK);
+	if (!clk_data)
+		return -ENOMEM;
 
 	mtk_clk_register_gates(node, eth_clks, CLK_ETH_NR_CLK, clk_data);
 
@@ -105,6 +107,8 @@
 	int r;
 
 	clk_data = mtk_alloc_clk_data(CLK_SGMII_NR_CLK);
+	if (!clk_data)
+		return -ENOMEM;
 
 	mtk_clk_register_gates(node, sgmii_clks[id++], CLK_SGMII_NR_CLK,
 			       clk_data);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/mediatek/clk-mt7629.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/mediatek/clk-mt7629.c
@@ -581,6 +581,8 @@
 		return PTR_ERR(base);
 
 	clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
+	if (!clk_data)
+		return -ENOMEM;
 
 	mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks),
 				    clk_data);
@@ -605,6 +607,8 @@
 	int r;
 
 	clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
+	if (!clk_data)
+		return -ENOMEM;
 
 	mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
 			       clk_data);
@@ -633,6 +637,8 @@
 		return PTR_ERR(base);
 
 	clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK);
+	if (!clk_data)
+		return -ENOMEM;
 
 	mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks),
 			       clk_data);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/mediatek/clk-mt8183-mfgcfg.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/mediatek/clk-mt8183-mfgcfg.c
@@ -18,9 +18,9 @@
 	.sta_ofs = 0x0,
 };
 
-#define GATE_MFG(_id, _name, _parent, _shift)			\
-	GATE_MTK(_id, _name, _parent, &mfg_cg_regs, _shift,	\
-		&mtk_clk_gate_ops_setclr)
+#define GATE_MFG(_id, _name, _parent, _shift)				\
+	GATE_MTK_FLAGS(_id, _name, _parent, &mfg_cg_regs, _shift,	\
+		       &mtk_clk_gate_ops_setclr, CLK_SET_RATE_PARENT)
 
 static const struct mtk_gate mfg_clks[] = {
 	GATE_MFG(CLK_MFG_BG3D, "mfg_bg3d", "mfg_sel", 0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/mediatek/clk-mux.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/mediatek/clk-mux.c
@@ -160,7 +160,7 @@
 				 spinlock_t *lock)
 {
 	struct mtk_clk_mux *clk_mux;
-	struct clk_init_data init;
+	struct clk_init_data init = {};
 	struct clk *clk;
 
 	clk_mux = kzalloc(sizeof(*clk_mux), GFP_KERNEL);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/mediatek/reset.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/mediatek/reset.c
@@ -25,7 +25,7 @@
 	struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev);
 	unsigned int reg = data->regofs + ((id / 32) << 4);
 
-	return regmap_write(data->regmap, reg, 1);
+	return regmap_write(data->regmap, reg, BIT(id % 32));
 }
 
 static int mtk_reset_deassert_set_clr(struct reset_controller_dev *rcdev,
@@ -34,7 +34,7 @@
 	struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev);
 	unsigned int reg = data->regofs + ((id / 32) << 4) + 0x4;
 
-	return regmap_write(data->regmap, reg, 1);
+	return regmap_write(data->regmap, reg, BIT(id % 32));
 }
 
 static int mtk_reset_assert(struct reset_controller_dev *rcdev,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/meson/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/meson/Kconfig
@@ -103,6 +103,7 @@
 	select COMMON_CLK_MESON_AO_CLKC
 	select COMMON_CLK_MESON_EE_CLKC
 	select COMMON_CLK_MESON_CPU_DYNDIV
+	select COMMON_CLK_MESON_VID_PLL_DIV
 	select MFD_SYSCON
 	help
 	  Support for the clock controller on Amlogic S905D2, S905X2 and S905Y2
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/meson/axg-audio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/meson/axg-audio.c
@@ -1001,7 +1001,7 @@
 	.reg_bits	= 32,
 	.val_bits	= 32,
 	.reg_stride	= 4,
-	.max_register	= AUDIO_CLK_PDMIN_CTRL1,
+	.max_register	= AUDIO_CLK_SPDIFOUT_B_CTRL,
 };
 
 struct audioclk_data {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/meson/clk-pll.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/meson/clk-pll.c
@@ -77,6 +77,15 @@
 	unsigned int m, n, frac;
 
 	n = meson_parm_read(clk->map, &pll->n);
+
+	/*
+	 * On some HW, N is set to zero on init. This value is invalid as
+	 * it would result in a division by zero. The rate can't be
+	 * calculated in this case
+	 */
+	if (n == 0)
+		return 0;
+
 	m = meson_parm_read(clk->map, &pll->m);
 
 	frac = MESON_PARM_APPLICABLE(&pll->frac) ?
@@ -354,13 +363,14 @@
 {
 	struct clk_regmap *clk = to_clk_regmap(hw);
 	struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
-	unsigned int enabled, m, n, frac = 0, ret;
+	unsigned int enabled, m, n, frac = 0;
 	unsigned long old_rate;
+	int ret;
 
 	if (parent_rate == 0 || rate == 0)
 		return -EINVAL;
 
-	old_rate = rate;
+	old_rate = clk_hw_get_rate(hw);
 
 	ret = meson_clk_get_pll_settings(rate, parent_rate, &m, &n, pll);
 	if (ret)
@@ -382,7 +392,8 @@
 	if (!enabled)
 		return 0;
 
-	if (meson_clk_pll_enable(hw)) {
+	ret = meson_clk_pll_enable(hw);
+	if (ret) {
 		pr_warn("%s: pll did not lock, trying to restore old rate %lu\n",
 			__func__, old_rate);
 		/*
@@ -394,7 +405,7 @@
 		meson_clk_pll_set_rate(hw, old_rate, parent_rate);
 	}
 
-	return 0;
+	return ret;
 }
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/meson/g12a.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/meson/g12a.c
@@ -298,6 +298,17 @@
 			&g12a_fclk_div2_div.hw
 		},
 		.num_parents = 1,
+		/*
+		 * Similar to fclk_div3, it seems that this clock is used by
+		 * the resident firmware and is required by the platform to
+		 * operate correctly.
+		 * Until the following condition are met, we need this clock to
+		 * be marked as critical:
+		 * a) Mark the clock used by a firmware resource, if possible
+		 * b) CCF has a clock hand-off mechanism to make the sure the
+		 *    clock stays on until the proper driver comes along
+		 */
+		.flags = CLK_IS_CRITICAL,
 	},
 };
 
@@ -1124,8 +1135,18 @@
 	.hw.init = &(struct clk_init_data) {
 		.name = "cpu_clk_div16_en",
 		.ops = &clk_regmap_gate_ro_ops,
-		.parent_hws = (const struct clk_hw *[]) {
-			&g12a_cpu_clk.hw
+		.parent_data = &(const struct clk_parent_data) {
+			/*
+			 * Note:
+			 * G12A and G12B have different cpu clocks (with
+			 * different struct clk_hw). We fallback to the global
+			 * naming string mechanism so this clock picks
+			 * up the appropriate one. Same goes for the other
+			 * clock using cpu cluster A clock output and present
+			 * on both G12 variant.
+			 */
+			.name = "cpu_clk",
+			.index = -1,
 		},
 		.num_parents = 1,
 		/*
@@ -1190,7 +1211,10 @@
 	.hw.init = &(struct clk_init_data){
 		.name = "cpu_clk_apb_div",
 		.ops = &clk_regmap_divider_ro_ops,
-		.parent_hws = (const struct clk_hw *[]) { &g12a_cpu_clk.hw },
+		.parent_data = &(const struct clk_parent_data) {
+			.name = "cpu_clk",
+			.index = -1,
+		},
 		.num_parents = 1,
 	},
 };
@@ -1224,7 +1248,10 @@
 	.hw.init = &(struct clk_init_data){
 		.name = "cpu_clk_atb_div",
 		.ops = &clk_regmap_divider_ro_ops,
-		.parent_hws = (const struct clk_hw *[]) { &g12a_cpu_clk.hw },
+		.parent_data = &(const struct clk_parent_data) {
+			.name = "cpu_clk",
+			.index = -1,
+		},
 		.num_parents = 1,
 	},
 };
@@ -1258,7 +1285,10 @@
 	.hw.init = &(struct clk_init_data){
 		.name = "cpu_clk_axi_div",
 		.ops = &clk_regmap_divider_ro_ops,
-		.parent_hws = (const struct clk_hw *[]) { &g12a_cpu_clk.hw },
+		.parent_data = &(const struct clk_parent_data) {
+			.name = "cpu_clk",
+			.index = -1,
+		},
 		.num_parents = 1,
 	},
 };
@@ -1293,13 +1323,6 @@
 		.name = "cpu_clk_trace_div",
 		.ops = &clk_regmap_divider_ro_ops,
 		.parent_data = &(const struct clk_parent_data) {
-			/*
-			 * Note:
-			 * G12A and G12B have different cpu_clks (with
-			 * different struct clk_hw). We fallback to the global
-			 * naming string mechanism so cpu_clk_trace_div picks
-			 * up the appropriate one.
-			 */
 			.name = "cpu_clk",
 			.index = -1,
 		},
@@ -1591,7 +1614,7 @@
 };
 
 static const struct pll_mult_range g12a_gp0_pll_mult_range = {
-	.min = 55,
+	.min = 125,
 	.max = 255,
 };
 
@@ -3887,7 +3910,7 @@
 static MESON_GATE(g12a_hiu_reg,			HHI_GCLK_MPEG0,	19);
 static MESON_GATE(g12a_mipi_dsi_phy,		HHI_GCLK_MPEG0,	20);
 static MESON_GATE(g12a_assist_misc,		HHI_GCLK_MPEG0,	23);
-static MESON_GATE(g12a_emmc_a,			HHI_GCLK_MPEG0,	4);
+static MESON_GATE(g12a_emmc_a,			HHI_GCLK_MPEG0,	24);
 static MESON_GATE(g12a_emmc_b,			HHI_GCLK_MPEG0,	25);
 static MESON_GATE(g12a_emmc_c,			HHI_GCLK_MPEG0,	26);
 static MESON_GATE(g12a_audio_codec,		HHI_GCLK_MPEG0,	28);
@@ -4692,6 +4715,7 @@
 	&g12a_bt656,
 	&g12a_usb1_to_ddr,
 	&g12a_mmc_pclk,
+	&g12a_uart2,
 	&g12a_vpu_intr,
 	&g12a_gic,
 	&g12a_sd_emmc_a_clk0,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/meson/gxbb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/meson/gxbb.c
@@ -719,6 +719,35 @@
 			.width   = 14,
 		},
 		.sdm_en = {
+			.reg_off = HHI_MPLL_CNTL,
+			.shift   = 25,
+			.width	 = 1,
+		},
+		.n2 = {
+			.reg_off = HHI_MPLL_CNTL7,
+			.shift   = 16,
+			.width   = 9,
+		},
+		.lock = &meson_clk_lock,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "mpll0_div",
+		.ops = &meson_clk_mpll_ops,
+		.parent_hws = (const struct clk_hw *[]) {
+			&gxbb_mpll_prediv.hw
+		},
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap gxl_mpll0_div = {
+	.data = &(struct meson_clk_mpll_data){
+		.sdm = {
+			.reg_off = HHI_MPLL_CNTL7,
+			.shift   = 0,
+			.width   = 14,
+		},
+		.sdm_en = {
 			.reg_off = HHI_MPLL_CNTL7,
 			.shift   = 15,
 			.width	 = 1,
@@ -748,7 +777,16 @@
 	.hw.init = &(struct clk_init_data){
 		.name = "mpll0",
 		.ops = &clk_regmap_gate_ops,
-		.parent_hws = (const struct clk_hw *[]) { &gxbb_mpll0_div.hw },
+		.parent_data = &(const struct clk_parent_data) {
+			/*
+			 * Note:
+			 * GXL and GXBB have different SDM_EN registers. We
+			 * fallback to the global naming string mechanism so
+			 * mpll0_div picks up the appropriate one.
+			 */
+			.name = "mpll0_div",
+			.index = -1,
+		},
 		.num_parents = 1,
 		.flags = CLK_SET_RATE_PARENT,
 	},
@@ -1227,14 +1265,13 @@
 	},
 };
 
+/*
+ * This table skips a clock named 'cts_slow_oscin' in the documentation
+ * This clock does not exist yet in this controller or the AO one
+ */
+static u32 gxbb_32k_clk_parents_val_table[] = { 0, 2, 3 };
 static const struct clk_parent_data gxbb_32k_clk_parent_data[] = {
 	{ .fw_name = "xtal", },
-	/*
-	 * FIXME: This clock is provided by the ao clock controller but the
-	 * clock is not yet part of the binding of this controller, so string
-	 * name must be use to set this parent.
-	 */
-	{ .name = "cts_slow_oscin", .index = -1 },
 	{ .hw = &gxbb_fclk_div3.hw },
 	{ .hw = &gxbb_fclk_div5.hw },
 };
@@ -1244,6 +1281,7 @@
 		.offset = HHI_32K_CLK_CNTL,
 		.mask = 0x3,
 		.shift = 16,
+		.table = gxbb_32k_clk_parents_val_table,
 		},
 	.hw.init = &(struct clk_init_data){
 		.name = "32k_clk_sel",
@@ -1267,7 +1305,7 @@
 			&gxbb_32k_clk_sel.hw
 		},
 		.num_parents = 1,
-		.flags = CLK_SET_RATE_PARENT | CLK_DIVIDER_ROUND_CLOSEST,
+		.flags = CLK_SET_RATE_PARENT,
 	},
 };
 
@@ -3036,7 +3074,7 @@
 		[CLKID_VAPB_1]		    = &gxbb_vapb_1.hw,
 		[CLKID_VAPB_SEL]	    = &gxbb_vapb_sel.hw,
 		[CLKID_VAPB]		    = &gxbb_vapb.hw,
-		[CLKID_MPLL0_DIV]	    = &gxbb_mpll0_div.hw,
+		[CLKID_MPLL0_DIV]	    = &gxl_mpll0_div.hw,
 		[CLKID_MPLL1_DIV]	    = &gxbb_mpll1_div.hw,
 		[CLKID_MPLL2_DIV]	    = &gxbb_mpll2_div.hw,
 		[CLKID_MPLL_PREDIV]	    = &gxbb_mpll_prediv.hw,
@@ -3430,7 +3468,7 @@
 	&gxbb_mpll0,
 	&gxbb_mpll1,
 	&gxbb_mpll2,
-	&gxbb_mpll0_div,
+	&gxl_mpll0_div,
 	&gxbb_mpll1_div,
 	&gxbb_mpll2_div,
 	&gxbb_cts_amclk_div,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/meson/meson-aoclk.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/meson/meson-aoclk.c
@@ -36,6 +36,7 @@
 	struct meson_aoclk_reset_controller *rstc;
 	struct meson_aoclk_data *data;
 	struct device *dev = &pdev->dev;
+	struct device_node *np;
 	struct regmap *regmap;
 	int ret, clkid;
 
@@ -47,7 +48,9 @@
 	if (!rstc)
 		return -ENOMEM;
 
-	regmap = syscon_node_to_regmap(of_get_parent(dev->of_node));
+	np = of_get_parent(dev->of_node);
+	regmap = syscon_node_to_regmap(np);
+	of_node_put(np);
 	if (IS_ERR(regmap)) {
 		dev_err(dev, "failed to get regmap\n");
 		return PTR_ERR(regmap);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/meson/meson-eeclk.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/meson/meson-eeclk.c
@@ -17,6 +17,7 @@
 {
 	const struct meson_eeclkc_data *data;
 	struct device *dev = &pdev->dev;
+	struct device_node *np;
 	struct regmap *map;
 	int ret, i;
 
@@ -25,7 +26,9 @@
 		return -EINVAL;
 
 	/* Get the hhi system controller node */
-	map = syscon_node_to_regmap(of_get_parent(dev->of_node));
+	np = of_get_parent(dev->of_node);
+	map = syscon_node_to_regmap(np);
+	of_node_put(np);
 	if (IS_ERR(map)) {
 		dev_err(dev,
 			"failed to get HHI regmap\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/meson/meson8b.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/meson/meson8b.c
@@ -1071,7 +1071,7 @@
 		 * Meson8m2: vid2_pll
 		 */
 		.parent_hws = (const struct clk_hw *[]) {
-			&meson8b_hdmi_pll_dco.hw
+			&meson8b_hdmi_pll_lvds_out.hw
 		},
 		.num_parents = 1,
 		.flags = CLK_SET_RATE_PARENT,
@@ -1207,7 +1207,7 @@
 
 static struct clk_regmap meson8b_vclk_div1_gate = {
 	.data = &(struct clk_regmap_gate_data){
-		.offset = HHI_VID_CLK_DIV,
+		.offset = HHI_VID_CLK_CNTL,
 		.bit_idx = 0,
 	},
 	.hw.init = &(struct clk_init_data){
@@ -1237,7 +1237,7 @@
 
 static struct clk_regmap meson8b_vclk_div2_div_gate = {
 	.data = &(struct clk_regmap_gate_data){
-		.offset = HHI_VID_CLK_DIV,
+		.offset = HHI_VID_CLK_CNTL,
 		.bit_idx = 1,
 	},
 	.hw.init = &(struct clk_init_data){
@@ -1267,7 +1267,7 @@
 
 static struct clk_regmap meson8b_vclk_div4_div_gate = {
 	.data = &(struct clk_regmap_gate_data){
-		.offset = HHI_VID_CLK_DIV,
+		.offset = HHI_VID_CLK_CNTL,
 		.bit_idx = 2,
 	},
 	.hw.init = &(struct clk_init_data){
@@ -1297,7 +1297,7 @@
 
 static struct clk_regmap meson8b_vclk_div6_div_gate = {
 	.data = &(struct clk_regmap_gate_data){
-		.offset = HHI_VID_CLK_DIV,
+		.offset = HHI_VID_CLK_CNTL,
 		.bit_idx = 3,
 	},
 	.hw.init = &(struct clk_init_data){
@@ -1327,7 +1327,7 @@
 
 static struct clk_regmap meson8b_vclk_div12_div_gate = {
 	.data = &(struct clk_regmap_gate_data){
-		.offset = HHI_VID_CLK_DIV,
+		.offset = HHI_VID_CLK_CNTL,
 		.bit_idx = 4,
 	},
 	.hw.init = &(struct clk_init_data){
@@ -1764,8 +1764,11 @@
 
 /*
  * The MALI IP is clocked by two identical clocks (mali_0 and mali_1)
- * muxed by a glitch-free switch on Meson8b and Meson8m2. Meson8 only
- * has mali_0 and no glitch-free mux.
+ * muxed by a glitch-free switch on Meson8b and Meson8m2. The CCF can
+ * actually manage this glitch-free mux because it does top-to-bottom
+ * updates the each clock tree and switches to the "inactive" one when
+ * CLK_SET_RATE_GATE is set.
+ * Meson8 only has mali_0 and no glitch-free mux.
  */
 static const struct clk_hw *meson8b_mali_0_1_parent_hws[] = {
 	&meson8b_xtal.hw,
@@ -1830,7 +1833,7 @@
 			&meson8b_mali_0_div.hw
 		},
 		.num_parents = 1,
-		.flags = CLK_SET_RATE_PARENT,
+		.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
 	},
 };
 
@@ -1885,7 +1888,7 @@
 			&meson8b_mali_1_div.hw
 		},
 		.num_parents = 1,
-		.flags = CLK_SET_RATE_PARENT,
+		.flags = CLK_SET_RATE_GATE | CLK_SET_RATE_PARENT,
 	},
 };
 
@@ -1907,6 +1910,13 @@
 	},
 };
 
+static const struct reg_sequence meson8m2_gp_pll_init_regs[] = {
+	{ .reg = HHI_GP_PLL_CNTL2,	.def = 0x59c88000 },
+	{ .reg = HHI_GP_PLL_CNTL3,	.def = 0xca463823 },
+	{ .reg = HHI_GP_PLL_CNTL4,	.def = 0x0286a027 },
+	{ .reg = HHI_GP_PLL_CNTL5,	.def = 0x00003000 },
+};
+
 static const struct pll_params_table meson8m2_gp_pll_params_table[] = {
 	PLL_PARAMS(182, 3),
 	{ /* sentinel */ },
@@ -1940,6 +1950,8 @@
 			.width   = 1,
 		},
 		.table = meson8m2_gp_pll_params_table,
+		.init_regs = meson8m2_gp_pll_init_regs,
+		.init_count = ARRAY_SIZE(meson8m2_gp_pll_init_regs),
 	},
 	.hw.init = &(struct clk_init_data){
 		.name = "gp_pll_dco",
@@ -3488,54 +3500,87 @@
 static const struct meson8b_clk_reset_line {
 	u32 reg;
 	u8 bit_idx;
+	bool active_low;
 } meson8b_clk_reset_bits[] = {
 	[CLKC_RESET_L2_CACHE_SOFT_RESET] = {
-		.reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 30
+		.reg = HHI_SYS_CPU_CLK_CNTL0,
+		.bit_idx = 30,
+		.active_low = false,
 	},
 	[CLKC_RESET_AXI_64_TO_128_BRIDGE_A5_SOFT_RESET] = {
-		.reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 29
+		.reg = HHI_SYS_CPU_CLK_CNTL0,
+		.bit_idx = 29,
+		.active_low = false,
 	},
 	[CLKC_RESET_SCU_SOFT_RESET] = {
-		.reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 28
+		.reg = HHI_SYS_CPU_CLK_CNTL0,
+		.bit_idx = 28,
+		.active_low = false,
 	},
 	[CLKC_RESET_CPU3_SOFT_RESET] = {
-		.reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 27
+		.reg = HHI_SYS_CPU_CLK_CNTL0,
+		.bit_idx = 27,
+		.active_low = false,
 	},
 	[CLKC_RESET_CPU2_SOFT_RESET] = {
-		.reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 26
+		.reg = HHI_SYS_CPU_CLK_CNTL0,
+		.bit_idx = 26,
+		.active_low = false,
 	},
 	[CLKC_RESET_CPU1_SOFT_RESET] = {
-		.reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 25
+		.reg = HHI_SYS_CPU_CLK_CNTL0,
+		.bit_idx = 25,
+		.active_low = false,
 	},
 	[CLKC_RESET_CPU0_SOFT_RESET] = {
-		.reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 24
+		.reg = HHI_SYS_CPU_CLK_CNTL0,
+		.bit_idx = 24,
+		.active_low = false,
 	},
 	[CLKC_RESET_A5_GLOBAL_RESET] = {
-		.reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 18
+		.reg = HHI_SYS_CPU_CLK_CNTL0,
+		.bit_idx = 18,
+		.active_low = false,
 	},
 	[CLKC_RESET_A5_AXI_SOFT_RESET] = {
-		.reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 17
+		.reg = HHI_SYS_CPU_CLK_CNTL0,
+		.bit_idx = 17,
+		.active_low = false,
 	},
 	[CLKC_RESET_A5_ABP_SOFT_RESET] = {
-		.reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 16
+		.reg = HHI_SYS_CPU_CLK_CNTL0,
+		.bit_idx = 16,
+		.active_low = false,
 	},
 	[CLKC_RESET_AXI_64_TO_128_BRIDGE_MMC_SOFT_RESET] = {
-		.reg = HHI_SYS_CPU_CLK_CNTL1, .bit_idx = 30
+		.reg = HHI_SYS_CPU_CLK_CNTL1,
+		.bit_idx = 30,
+		.active_low = false,
 	},
 	[CLKC_RESET_VID_CLK_CNTL_SOFT_RESET] = {
-		.reg = HHI_VID_CLK_CNTL, .bit_idx = 15
+		.reg = HHI_VID_CLK_CNTL,
+		.bit_idx = 15,
+		.active_low = false,
 	},
 	[CLKC_RESET_VID_DIVIDER_CNTL_SOFT_RESET_POST] = {
-		.reg = HHI_VID_DIVIDER_CNTL, .bit_idx = 7
+		.reg = HHI_VID_DIVIDER_CNTL,
+		.bit_idx = 7,
+		.active_low = false,
 	},
 	[CLKC_RESET_VID_DIVIDER_CNTL_SOFT_RESET_PRE] = {
-		.reg = HHI_VID_DIVIDER_CNTL, .bit_idx = 3
+		.reg = HHI_VID_DIVIDER_CNTL,
+		.bit_idx = 3,
+		.active_low = false,
 	},
 	[CLKC_RESET_VID_DIVIDER_CNTL_RESET_N_POST] = {
-		.reg = HHI_VID_DIVIDER_CNTL, .bit_idx = 1
+		.reg = HHI_VID_DIVIDER_CNTL,
+		.bit_idx = 1,
+		.active_low = true,
 	},
 	[CLKC_RESET_VID_DIVIDER_CNTL_RESET_N_PRE] = {
-		.reg = HHI_VID_DIVIDER_CNTL, .bit_idx = 0
+		.reg = HHI_VID_DIVIDER_CNTL,
+		.bit_idx = 0,
+		.active_low = true,
 	},
 };
 
@@ -3544,22 +3589,22 @@
 {
 	struct meson8b_clk_reset *meson8b_clk_reset =
 		container_of(rcdev, struct meson8b_clk_reset, reset);
-	unsigned long flags;
 	const struct meson8b_clk_reset_line *reset;
+	unsigned int value = 0;
+	unsigned long flags;
 
 	if (id >= ARRAY_SIZE(meson8b_clk_reset_bits))
 		return -EINVAL;
 
 	reset = &meson8b_clk_reset_bits[id];
 
+	if (assert != reset->active_low)
+		value = BIT(reset->bit_idx);
+
 	spin_lock_irqsave(&meson_clk_lock, flags);
 
-	if (assert)
-		regmap_update_bits(meson8b_clk_reset->regmap, reset->reg,
-				   BIT(reset->bit_idx), BIT(reset->bit_idx));
-	else
-		regmap_update_bits(meson8b_clk_reset->regmap, reset->reg,
-				   BIT(reset->bit_idx), 0);
+	regmap_update_bits(meson8b_clk_reset->regmap, reset->reg,
+			   BIT(reset->bit_idx), value);
 
 	spin_unlock_irqrestore(&meson_clk_lock, flags);
 
@@ -3639,13 +3684,16 @@
 			struct clk_hw_onecell_data *clk_hw_onecell_data)
 {
 	struct meson8b_clk_reset *rstc;
+	struct device_node *parent_np;
 	const char *notifier_clk_name;
 	struct clk *notifier_clk;
 	void __iomem *clk_base;
 	struct regmap *map;
 	int i, ret;
 
-	map = syscon_node_to_regmap(of_get_parent(np));
+	parent_np = of_get_parent(np);
+	map = syscon_node_to_regmap(parent_np);
+	of_node_put(parent_np);
 	if (IS_ERR(map)) {
 		pr_info("failed to get HHI regmap - Trying obsolete regs\n");
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/meson/meson8b.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/meson/meson8b.h
@@ -20,6 +20,10 @@
  * [0] http://dn.odroid.com/S805/Datasheet/S805_Datasheet%20V0.8%2020150126.pdf
  */
 #define HHI_GP_PLL_CNTL			0x40  /* 0x10 offset in data sheet */
+#define HHI_GP_PLL_CNTL2		0x44  /* 0x11 offset in data sheet */
+#define HHI_GP_PLL_CNTL3		0x48  /* 0x12 offset in data sheet */
+#define HHI_GP_PLL_CNTL4		0x4C  /* 0x13 offset in data sheet */
+#define HHI_GP_PLL_CNTL5		0x50  /* 0x14 offset in data sheet */
 #define HHI_VIID_CLK_DIV		0x128 /* 0x4a offset in data sheet */
 #define HHI_VIID_CLK_CNTL		0x12c /* 0x4b offset in data sheet */
 #define HHI_GCLK_MPEG0			0x140 /* 0x50 offset in data sheet */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/mmp/clk-of-mmp2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/mmp/clk-of-mmp2.c
@@ -134,7 +134,7 @@
 static const char *ssp_parent_names[] = {"vctcxo_4", "vctcxo_2", "vctcxo", "pll1_16"};
 
 static DEFINE_SPINLOCK(timer_lock);
-static const char *timer_parent_names[] = {"clk32", "vctcxo_2", "vctcxo_4", "vctcxo"};
+static const char *timer_parent_names[] = {"clk32", "vctcxo_4", "vctcxo_2", "vctcxo"};
 
 static DEFINE_SPINLOCK(reset_lock);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/mmp/clk-of-pxa168.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/mmp/clk-of-pxa168.c
@@ -258,18 +258,21 @@
 	pxa_unit->mpmu_base = of_iomap(np, 0);
 	if (!pxa_unit->mpmu_base) {
 		pr_err("failed to map mpmu registers\n");
+		kfree(pxa_unit);
 		return;
 	}
 
 	pxa_unit->apmu_base = of_iomap(np, 1);
 	if (!pxa_unit->apmu_base) {
 		pr_err("failed to map apmu registers\n");
+		kfree(pxa_unit);
 		return;
 	}
 
 	pxa_unit->apbc_base = of_iomap(np, 2);
 	if (!pxa_unit->apbc_base) {
 		pr_err("failed to map apbc registers\n");
+		kfree(pxa_unit);
 		return;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/mvebu/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/mvebu/Kconfig
@@ -42,6 +42,7 @@
 
 config ARMADA_AP_CPU_CLK
 	bool
+	select ARMADA_AP_CP_HELPER
 
 config ARMADA_CP110_SYSCON
 	bool
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/mvebu/ap-cpu-clk.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/mvebu/ap-cpu-clk.c
@@ -256,12 +256,15 @@
 		int cpu, err;
 
 		err = of_property_read_u32(dn, "reg", &cpu);
-		if (WARN_ON(err))
+		if (WARN_ON(err)) {
+			of_node_put(dn);
 			return err;
+		}
 
 		/* If cpu2 or cpu3 is enabled */
 		if (cpu & APN806_CLUSTER_NUM_MASK) {
 			nclusters = 2;
+			of_node_put(dn);
 			break;
 		}
 	}
@@ -288,8 +291,10 @@
 		int cpu, err;
 
 		err = of_property_read_u32(dn, "reg", &cpu);
-		if (WARN_ON(err))
+		if (WARN_ON(err)) {
+			of_node_put(dn);
 			return err;
+		}
 
 		cluster_index = cpu & APN806_CLUSTER_NUM_MASK;
 		cluster_index >>= APN806_CLUSTER_NUM_OFFSET;
@@ -301,6 +306,7 @@
 		parent = of_clk_get(np, cluster_index);
 		if (IS_ERR(parent)) {
 			dev_err(dev, "Could not get the clock parent\n");
+			of_node_put(dn);
 			return -EINVAL;
 		}
 		parent_name =  __clk_get_name(parent);
@@ -319,8 +325,10 @@
 		init.parent_names = &parent_name;
 
 		ret = devm_clk_hw_register(dev, &ap_cpu_clk[cluster_index].hw);
-		if (ret)
+		if (ret) {
+			of_node_put(dn);
 			return ret;
+		}
 		ap_cpu_data->hws[cluster_index] = &ap_cpu_clk[cluster_index].hw;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/mvebu/armada-37xx-periph.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/mvebu/armada-37xx-periph.c
@@ -84,6 +84,7 @@
 	void __iomem *reg_div;
 	u8 shift_div;
 	struct regmap *nb_pm_base;
+	unsigned long l1_expiration;
 };
 
 #define to_clk_double_div(_hw) container_of(_hw, struct clk_double_div, hw)
@@ -438,33 +439,6 @@
 	return val;
 }
 
-static int clk_pm_cpu_set_parent(struct clk_hw *hw, u8 index)
-{
-	struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
-	struct regmap *base = pm_cpu->nb_pm_base;
-	int load_level;
-
-	/*
-	 * We set the clock parent only if the DVFS is available but
-	 * not enabled.
-	 */
-	if (IS_ERR(base) || armada_3700_pm_dvfs_is_enabled(base))
-		return -EINVAL;
-
-	/* Set the parent clock for all the load level */
-	for (load_level = 0; load_level < LOAD_LEVEL_NR; load_level++) {
-		unsigned int reg, mask,  val,
-			offset = ARMADA_37XX_NB_TBG_SEL_OFF;
-
-		armada_3700_pm_dvfs_update_regs(load_level, &reg, &offset);
-
-		val = index << offset;
-		mask = ARMADA_37XX_NB_TBG_SEL_MASK << offset;
-		regmap_update_bits(base, reg, mask, val);
-	}
-	return 0;
-}
-
 static unsigned long clk_pm_cpu_recalc_rate(struct clk_hw *hw,
 					    unsigned long parent_rate)
 {
@@ -512,8 +486,10 @@
 }
 
 /*
- * Switching the CPU from the L2 or L3 frequencies (300 and 200 Mhz
- * respectively) to L0 frequency (1.2 Ghz) requires a significant
+ * Workaround when base CPU frequnecy is 1000 or 1200 MHz
+ *
+ * Switching the CPU from the L2 or L3 frequencies (250/300 or 200 MHz
+ * respectively) to L0 frequency (1/1.2 GHz) requires a significant
  * amount of time to let VDD stabilize to the appropriate
  * voltage. This amount of time is large enough that it cannot be
  * covered by the hardware countdown register. Due to this, the CPU
@@ -523,26 +499,56 @@
  * To work around this problem, we prevent switching directly from the
  * L2/L3 frequencies to the L0 frequency, and instead switch to the L1
  * frequency in-between. The sequence therefore becomes:
- * 1. First switch from L2/L3(200/300MHz) to L1(600MHZ)
+ * 1. First switch from L2/L3 (200/250/300 MHz) to L1 (500/600 MHz)
  * 2. Sleep 20ms for stabling VDD voltage
- * 3. Then switch from L1(600MHZ) to L0(1200Mhz).
+ * 3. Then switch from L1 (500/600 MHz) to L0 (1000/1200 MHz).
  */
-static void clk_pm_cpu_set_rate_wa(unsigned long rate, struct regmap *base)
+static void clk_pm_cpu_set_rate_wa(struct clk_pm_cpu *pm_cpu,
+				   unsigned int new_level, unsigned long rate,
+				   struct regmap *base)
 {
 	unsigned int cur_level;
 
-	if (rate != 1200 * 1000 * 1000)
-		return;
-
 	regmap_read(base, ARMADA_37XX_NB_CPU_LOAD, &cur_level);
 	cur_level &= ARMADA_37XX_NB_CPU_LOAD_MASK;
-	if (cur_level <= ARMADA_37XX_DVFS_LOAD_1)
+
+	if (cur_level == new_level)
+		return;
+
+	/*
+	 * System wants to go to L1 on its own. If we are going from L2/L3,
+	 * remember when 20ms will expire. If from L0, set the value so that
+	 * next switch to L0 won't have to wait.
+	 */
+	if (new_level == ARMADA_37XX_DVFS_LOAD_1) {
+		if (cur_level == ARMADA_37XX_DVFS_LOAD_0)
+			pm_cpu->l1_expiration = jiffies;
+		else
+			pm_cpu->l1_expiration = jiffies + msecs_to_jiffies(20);
 		return;
+	}
+
+	/*
+	 * If we are setting to L2/L3, just invalidate L1 expiration time,
+	 * sleeping is not needed.
+	 */
+	if (rate < 1000*1000*1000)
+		goto invalidate_l1_exp;
+
+	/*
+	 * We are going to L0 with rate >= 1GHz. Check whether we have been at
+	 * L1 for long enough time. If not, go to L1 for 20ms.
+	 */
+	if (pm_cpu->l1_expiration && jiffies >= pm_cpu->l1_expiration)
+		goto invalidate_l1_exp;
 
 	regmap_update_bits(base, ARMADA_37XX_NB_CPU_LOAD,
 			   ARMADA_37XX_NB_CPU_LOAD_MASK,
 			   ARMADA_37XX_DVFS_LOAD_1);
 	msleep(20);
+
+invalidate_l1_exp:
+	pm_cpu->l1_expiration = 0;
 }
 
 static int clk_pm_cpu_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -576,7 +582,9 @@
 			reg = ARMADA_37XX_NB_CPU_LOAD;
 			mask = ARMADA_37XX_NB_CPU_LOAD_MASK;
 
-			clk_pm_cpu_set_rate_wa(rate, base);
+			/* Apply workaround when base CPU frequency is 1000 or 1200 MHz */
+			if (parent_rate >= 1000*1000*1000)
+				clk_pm_cpu_set_rate_wa(pm_cpu, load_level, rate, base);
 
 			regmap_update_bits(base, reg, mask, load_level);
 
@@ -590,7 +598,6 @@
 
 static const struct clk_ops clk_pm_cpu_ops = {
 	.get_parent = clk_pm_cpu_get_parent,
-	.set_parent = clk_pm_cpu_set_parent,
 	.round_rate = clk_pm_cpu_round_rate,
 	.set_rate = clk_pm_cpu_set_rate,
 	.recalc_rate = clk_pm_cpu_recalc_rate,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/mvebu/armada-37xx-xtal.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/mvebu/armada-37xx-xtal.c
@@ -13,8 +13,8 @@
 #include <linux/platform_device.h>
 #include <linux/regmap.h>
 
-#define NB_GPIO1_LATCH	0xC
-#define XTAL_MODE	    BIT(31)
+#define NB_GPIO1_LATCH	0x8
+#define XTAL_MODE	    BIT(9)
 
 static int armada_3700_xtal_clock_probe(struct platform_device *pdev)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/mvebu/kirkwood.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/mvebu/kirkwood.c
@@ -265,6 +265,7 @@
 static const struct clk_muxing_soc_desc kirkwood_mux_desc[] __initconst = {
 	{ "powersave", powersave_parents, ARRAY_SIZE(powersave_parents),
 		11, 1, 0 },
+	{ }
 };
 
 static struct clk *clk_muxing_get_src(
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/pxa/clk-pxa27x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/pxa/clk-pxa27x.c
@@ -459,6 +459,7 @@
 };
 static struct dummy_clk dummy_clks[] __initdata = {
 	DUMMY_CLK(NULL, "pxa27x-gpio", "osc_32_768khz"),
+	DUMMY_CLK(NULL, "pxa-rtc", "osc_32_768khz"),
 	DUMMY_CLK(NULL, "sa1100-rtc", "osc_32_768khz"),
 	DUMMY_CLK("UARTCLK", "pxa2xx-ir", "STUART"),
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/qcom/a53-pll.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/qcom/a53-pll.c
@@ -93,6 +93,7 @@
 	{ .compatible = "qcom,msm8916-a53pll" },
 	{ }
 };
+MODULE_DEVICE_TABLE(of, qcom_a53pll_match_table);
 
 static struct platform_driver qcom_a53pll_driver = {
 	.probe = qcom_a53pll_probe,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/qcom/camcc-sdm845.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/qcom/camcc-sdm845.c
@@ -1521,6 +1521,8 @@
 	},
 };
 
+static struct gdsc titan_top_gdsc;
+
 static struct gdsc bps_gdsc = {
 	.gdscr = 0x6004,
 	.pd = {
@@ -1554,6 +1556,7 @@
 		.name = "ife_0_gdsc",
 	},
 	.flags = POLL_CFG_GDSCR,
+	.parent = &titan_top_gdsc.pd,
 	.pwrsts = PWRSTS_OFF_ON,
 };
 
@@ -1563,6 +1566,7 @@
 		.name = "ife_1_gdsc",
 	},
 	.flags = POLL_CFG_GDSCR,
+	.parent = &titan_top_gdsc.pd,
 	.pwrsts = PWRSTS_OFF_ON,
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/qcom/clk-alpha-pll.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/qcom/clk-alpha-pll.c
@@ -38,7 +38,7 @@
 
 #define PLL_USER_CTL(p)		((p)->offset + (p)->regs[PLL_OFF_USER_CTL])
 # define PLL_POST_DIV_SHIFT	8
-# define PLL_POST_DIV_MASK(p)	GENMASK((p)->width, 0)
+# define PLL_POST_DIV_MASK(p)	GENMASK((p)->width - 1, 0)
 # define PLL_ALPHA_EN		BIT(24)
 # define PLL_ALPHA_MODE		BIT(25)
 # define PLL_VCO_SHIFT		20
@@ -55,7 +55,6 @@
 #define PLL_STATUS(p)		((p)->offset + (p)->regs[PLL_OFF_STATUS])
 #define PLL_OPMODE(p)		((p)->offset + (p)->regs[PLL_OFF_OPMODE])
 #define PLL_FRAC(p)		((p)->offset + (p)->regs[PLL_OFF_FRAC])
-#define PLL_CAL_VAL(p)		((p)->offset + (p)->regs[PLL_OFF_CAL_VAL])
 
 const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = {
 	[CLK_ALPHA_PLL_TYPE_DEFAULT] =  {
@@ -114,7 +113,6 @@
 		[PLL_OFF_STATUS] = 0x30,
 		[PLL_OFF_OPMODE] = 0x38,
 		[PLL_OFF_ALPHA_VAL] = 0x40,
-		[PLL_OFF_CAL_VAL] = 0x44,
 	},
 };
 EXPORT_SYMBOL_GPL(clk_alpha_pll_regs);
@@ -238,6 +236,8 @@
 	mask |= config->pre_div_mask;
 	mask |= config->post_div_mask;
 	mask |= config->vco_mask;
+	mask |= config->alpha_en_mask;
+	mask |= config->alpha_mode_mask;
 
 	regmap_update_bits(regmap, PLL_USER_CTL(pll), mask, val);
 
@@ -1259,8 +1259,8 @@
 	}
 
 	return regmap_update_bits(regmap, PLL_USER_CTL(pll),
-				  PLL_POST_DIV_MASK(pll) << PLL_POST_DIV_SHIFT,
-				  val << PLL_POST_DIV_SHIFT);
+				  PLL_POST_DIV_MASK(pll) << pll->post_div_shift,
+				  val << pll->post_div_shift);
 }
 
 const struct clk_ops clk_trion_pll_postdiv_ops = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/qcom/clk-krait.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/qcom/clk-krait.c
@@ -32,11 +32,16 @@
 		regval |= (sel & mux->mask) << (mux->shift + LPL_SHIFT);
 	}
 	krait_set_l2_indirect_reg(mux->offset, regval);
-	spin_unlock_irqrestore(&krait_clock_reg_lock, flags);
 
 	/* Wait for switch to complete. */
 	mb();
 	udelay(1);
+
+	/*
+	 * Unlock now to make sure the mux register is not
+	 * modified while switching to the new parent.
+	 */
+	spin_unlock_irqrestore(&krait_clock_reg_lock, flags);
 }
 
 static int krait_mux_set_parent(struct clk_hw *hw, u8 index)
@@ -93,6 +98,8 @@
 
 	if (d->lpl)
 		mask = mask << (d->shift + LPL_SHIFT) | mask << d->shift;
+	else
+		mask <<= d->shift;
 
 	spin_lock_irqsave(&krait_clock_reg_lock, flags);
 	val = krait_get_l2_indirect_reg(d->offset);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/qcom/clk-rcg2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/qcom/clk-rcg2.c
@@ -146,17 +146,11 @@
 static unsigned long
 calc_rate(unsigned long rate, u32 m, u32 n, u32 mode, u32 hid_div)
 {
-	if (hid_div) {
-		rate *= 2;
-		rate /= hid_div + 1;
-	}
+	if (hid_div)
+		rate = mult_frac(rate, 2, hid_div + 1);
 
-	if (mode) {
-		u64 tmp = rate;
-		tmp *= m;
-		do_div(tmp, n);
-		rate = tmp;
-	}
+	if (mode)
+		rate = mult_frac(rate, m, n);
 
 	return rate;
 }
@@ -217,9 +211,14 @@
 
 	clk_flags = clk_hw_get_flags(hw);
 	p = clk_hw_get_parent_by_index(hw, index);
+	if (!p)
+		return -EINVAL;
+
 	if (clk_flags & CLK_SET_RATE_PARENT) {
 		rate = f->freq;
 		if (f->pre_div) {
+			if (!rate)
+				rate = req->rate;
 			rate /= 2;
 			rate *= f->pre_div + 1;
 		}
@@ -258,7 +257,7 @@
 
 static int __clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f)
 {
-	u32 cfg, mask;
+	u32 cfg, mask, d_val, not2d_val, n_minus_m;
 	struct clk_hw *hw = &rcg->clkr.hw;
 	int ret, index = qcom_find_src_index(hw, rcg->parent_map, f->src);
 
@@ -277,8 +276,17 @@
 		if (ret)
 			return ret;
 
+		/* Calculate 2d value */
+		d_val = f->n;
+
+		n_minus_m = f->n - f->m;
+		n_minus_m *= 2;
+
+		d_val = clamp_t(u32, d_val, f->m, n_minus_m);
+		not2d_val = ~d_val & mask;
+
 		ret = regmap_update_bits(rcg->clkr.regmap,
-				RCG_D_OFFSET(rcg), mask, ~f->n);
+				RCG_D_OFFSET(rcg), mask, not2d_val);
 		if (ret)
 			return ret;
 	}
@@ -633,6 +641,7 @@
 	{ 2, 9 },
 	{ 4, 9 },
 	{ 1, 1 },
+	{ 2, 3 },
 	{ }
 };
 
@@ -950,7 +959,7 @@
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
 	struct clk_hw *p;
 	unsigned long prate = 0;
-	u32 val, mask, cfg, mode;
+	u32 val, mask, cfg, mode, src;
 	int i, num_parents;
 
 	regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + SE_PERF_DFSR(l), &cfg);
@@ -960,12 +969,12 @@
 	if (cfg & mask)
 		f->pre_div = cfg & mask;
 
-	cfg &= CFG_SRC_SEL_MASK;
-	cfg >>= CFG_SRC_SEL_SHIFT;
+	src = cfg & CFG_SRC_SEL_MASK;
+	src >>= CFG_SRC_SEL_SHIFT;
 
 	num_parents = clk_hw_get_num_parents(hw);
 	for (i = 0; i < num_parents; i++) {
-		if (cfg == rcg->parent_map[i].cfg) {
+		if (src == rcg->parent_map[i].cfg) {
 			f->src = rcg->parent_map[i].src;
 			p = clk_hw_get_parent_by_index(&rcg->clkr.hw, i);
 			prate = clk_hw_get_rate(p);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/qcom/clk-regmap-mux.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/qcom/clk-regmap-mux.c
@@ -28,7 +28,7 @@
 	val &= mask;
 
 	if (mux->parent_map)
-		return qcom_find_src_index(hw, mux->parent_map, val);
+		return qcom_find_cfg_index(hw, mux->parent_map, val);
 
 	return val;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/qcom/clk-rpmh.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/qcom/clk-rpmh.c
@@ -143,12 +143,22 @@
 		!= (c->aggr_state & BIT(state));
 }
 
+static int clk_rpmh_send(struct clk_rpmh *c, enum rpmh_state state,
+			 struct tcs_cmd *cmd, bool wait)
+{
+	if (wait)
+		return rpmh_write(c->dev, state, cmd, 1);
+
+	return rpmh_write_async(c->dev, state, cmd, 1);
+}
+
 static int clk_rpmh_send_aggregate_command(struct clk_rpmh *c)
 {
 	struct tcs_cmd cmd = { 0 };
 	u32 cmd_state, on_val;
 	enum rpmh_state state = RPMH_SLEEP_STATE;
 	int ret;
+	bool wait;
 
 	cmd.addr = c->res_addr;
 	cmd_state = c->aggr_state;
@@ -159,7 +169,8 @@
 			if (cmd_state & BIT(state))
 				cmd.data = on_val;
 
-			ret = rpmh_write_async(c->dev, state, &cmd, 1);
+			wait = cmd_state && state == RPMH_ACTIVE_ONLY_STATE;
+			ret = clk_rpmh_send(c, state, &cmd, wait);
 			if (ret) {
 				dev_err(c->dev, "set %s state of %s failed: (%d)\n",
 					!state ? "sleep" :
@@ -248,38 +259,35 @@
 {
 	struct tcs_cmd cmd = { 0 };
 	u32 cmd_state;
-	int ret;
+	int ret = 0;
 
 	mutex_lock(&rpmh_clk_lock);
-
-	cmd_state = 0;
 	if (enable) {
 		cmd_state = 1;
 		if (c->aggr_state)
 			cmd_state = c->aggr_state;
+	} else {
+		cmd_state = 0;
 	}
 
-	if (c->last_sent_aggr_state == cmd_state) {
-		mutex_unlock(&rpmh_clk_lock);
-		return 0;
-	}
-
-	cmd.addr = c->res_addr;
-	cmd.data = BCM_TCS_CMD(1, enable, 0, cmd_state);
+	cmd_state = min(cmd_state, BCM_TCS_CMD_VOTE_MASK);
 
-	ret = rpmh_write_async(c->dev, RPMH_ACTIVE_ONLY_STATE, &cmd, 1);
-	if (ret) {
-		dev_err(c->dev, "set active state of %s failed: (%d)\n",
-			c->res_name, ret);
-		mutex_unlock(&rpmh_clk_lock);
-		return ret;
+	if (c->last_sent_aggr_state != cmd_state) {
+		cmd.addr = c->res_addr;
+		cmd.data = BCM_TCS_CMD(1, enable, 0, cmd_state);
+
+		ret = clk_rpmh_send(c, RPMH_ACTIVE_ONLY_STATE, &cmd, enable);
+		if (ret) {
+			dev_err(c->dev, "set active state of %s failed: (%d)\n",
+				c->res_name, ret);
+		} else {
+			c->last_sent_aggr_state = cmd_state;
+		}
 	}
 
-	c->last_sent_aggr_state = cmd_state;
-
 	mutex_unlock(&rpmh_clk_lock);
 
-	return 0;
+	return ret;
 }
 
 static int clk_rpmh_bcm_prepare(struct clk_hw *hw)
@@ -323,7 +331,7 @@
 {
 	struct clk_rpmh *c = to_clk_rpmh(hw);
 
-	return c->aggr_state * c->unit;
+	return (unsigned long)c->aggr_state * c->unit;
 }
 
 static const struct clk_ops clk_rpmh_bcm_ops = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/qcom/clk-smd-rpm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/qcom/clk-smd-rpm.c
@@ -648,6 +648,8 @@
 };
 
 /* msm8998 */
+DEFINE_CLK_SMD_RPM(msm8998, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0);
+DEFINE_CLK_SMD_RPM(msm8998, pcnoc_clk, pcnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0);
 DEFINE_CLK_SMD_RPM(msm8998, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1);
 DEFINE_CLK_SMD_RPM(msm8998, cnoc_clk, cnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 2);
 DEFINE_CLK_SMD_RPM(msm8998, ce1_clk, ce1_a_clk, QCOM_SMD_RPM_CE_CLK, 0);
@@ -670,6 +672,10 @@
 DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8998, rf_clk3, rf_clk3_a, 6);
 DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8998, rf_clk3_pin, rf_clk3_a_pin, 6);
 static struct clk_smd_rpm *msm8998_clks[] = {
+	[RPM_SMD_BIMC_CLK] = &msm8998_bimc_clk,
+	[RPM_SMD_BIMC_A_CLK] = &msm8998_bimc_a_clk,
+	[RPM_SMD_PCNOC_CLK] = &msm8998_pcnoc_clk,
+	[RPM_SMD_PCNOC_A_CLK] = &msm8998_pcnoc_a_clk,
 	[RPM_SMD_SNOC_CLK] = &msm8998_snoc_clk,
 	[RPM_SMD_SNOC_A_CLK] = &msm8998_snoc_a_clk,
 	[RPM_SMD_CNOC_CLK] = &msm8998_cnoc_clk,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/qcom/common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/qcom/common.c
@@ -29,6 +29,9 @@
 	if (!f)
 		return NULL;
 
+	if (!f->freq)
+		return f;
+
 	for (; f->freq; f++)
 		if (rate <= f->freq)
 			return f;
@@ -66,6 +69,18 @@
 }
 EXPORT_SYMBOL_GPL(qcom_find_src_index);
 
+int qcom_find_cfg_index(struct clk_hw *hw, const struct parent_map *map, u8 cfg)
+{
+	int i, num_parents = clk_hw_get_num_parents(hw);
+
+	for (i = 0; i < num_parents; i++)
+		if (cfg == map[i].cfg)
+			return i;
+
+	return -ENOENT;
+}
+EXPORT_SYMBOL_GPL(qcom_find_cfg_index);
+
 struct regmap *
 qcom_cc_map(struct platform_device *pdev, const struct qcom_cc_desc *desc)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/qcom/common.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/qcom/common.h
@@ -49,6 +49,8 @@
 qcom_pll_set_fsm_mode(struct regmap *m, u32 reg, u8 bias_count, u8 lock_count);
 extern int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map,
 			       u8 src);
+extern int qcom_find_cfg_index(struct clk_hw *hw, const struct parent_map *map,
+			       u8 cfg);
 
 extern int qcom_cc_register_board_clk(struct device *dev, const char *path,
 				      const char *name, unsigned long rate);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/qcom/dispcc-sdm845.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/qcom/dispcc-sdm845.c
@@ -569,6 +569,8 @@
 
 static struct gdsc mdss_gdsc = {
 	.gdscr = 0x3000,
+	.en_few_wait_val = 0x6,
+	.en_rest_wait_val = 0x5,
 	.pd = {
 		.name = "mdss_gdsc",
 	},
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/qcom/gcc-ipq8074.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/qcom/gcc-ipq8074.c
@@ -423,7 +423,6 @@
 		},
 		.num_parents = 1,
 		.ops = &clk_fixed_factor_ops,
-		.flags = CLK_SET_RATE_PARENT,
 	},
 };
 
@@ -470,7 +469,6 @@
 		},
 		.num_parents = 1,
 		.ops = &clk_alpha_pll_postdiv_ro_ops,
-		.flags = CLK_SET_RATE_PARENT,
 	},
 };
 
@@ -503,7 +501,6 @@
 		},
 		.num_parents = 1,
 		.ops = &clk_alpha_pll_postdiv_ro_ops,
-		.flags = CLK_SET_RATE_PARENT,
 	},
 };
 
@@ -537,7 +534,6 @@
 		},
 		.num_parents = 1,
 		.ops = &clk_alpha_pll_postdiv_ro_ops,
-		.flags = CLK_SET_RATE_PARENT,
 	},
 };
 
@@ -551,7 +547,6 @@
 		},
 		.num_parents = 1,
 		.ops = &clk_fixed_factor_ops,
-		.flags = CLK_SET_RATE_PARENT,
 	},
 };
 
@@ -616,7 +611,6 @@
 		},
 		.num_parents = 1,
 		.ops = &clk_alpha_pll_postdiv_ro_ops,
-		.flags = CLK_SET_RATE_PARENT,
 	},
 };
 
@@ -667,6 +661,7 @@
 			},
 			.num_parents = 1,
 			.ops = &clk_branch2_ops,
+			.flags = CLK_IS_CRITICAL,
 		},
 	},
 };
@@ -977,6 +972,7 @@
 
 static const struct freq_tbl ftbl_pcie_aux_clk_src[] = {
 	F(19200000, P_XO, 1, 0, 0),
+	{ }
 };
 
 static struct clk_rcg2 pcie0_aux_clk_src = {
@@ -1074,7 +1070,7 @@
 		.name = "sdcc1_apps_clk_src",
 		.parent_names = gcc_xo_gpll0_gpll2_gpll0_out_main_div2,
 		.num_parents = 4,
-		.ops = &clk_rcg2_ops,
+		.ops = &clk_rcg2_floor_ops,
 	},
 };
 
@@ -1082,6 +1078,7 @@
 	F(19200000, P_XO, 1, 0, 0),
 	F(160000000, P_GPLL0, 5, 0, 0),
 	F(308570000, P_GPLL6, 3.5, 0, 0),
+	{ }
 };
 
 static struct clk_rcg2 sdcc1_ice_core_clk_src = {
@@ -1788,8 +1785,10 @@
 static const struct freq_tbl ftbl_nss_port5_rx_clk_src[] = {
 	F(19200000, P_XO, 1, 0, 0),
 	F(25000000, P_UNIPHY1_RX, 12.5, 0, 0),
+	F(25000000, P_UNIPHY0_RX, 5, 0, 0),
 	F(78125000, P_UNIPHY1_RX, 4, 0, 0),
 	F(125000000, P_UNIPHY1_RX, 2.5, 0, 0),
+	F(125000000, P_UNIPHY0_RX, 1, 0, 0),
 	F(156250000, P_UNIPHY1_RX, 2, 0, 0),
 	F(312500000, P_UNIPHY1_RX, 1, 0, 0),
 	{ }
@@ -1828,8 +1827,10 @@
 static const struct freq_tbl ftbl_nss_port5_tx_clk_src[] = {
 	F(19200000, P_XO, 1, 0, 0),
 	F(25000000, P_UNIPHY1_TX, 12.5, 0, 0),
+	F(25000000, P_UNIPHY0_TX, 5, 0, 0),
 	F(78125000, P_UNIPHY1_TX, 4, 0, 0),
 	F(125000000, P_UNIPHY1_TX, 2.5, 0, 0),
+	F(125000000, P_UNIPHY0_TX, 1, 0, 0),
 	F(156250000, P_UNIPHY1_TX, 2, 0, 0),
 	F(312500000, P_UNIPHY1_TX, 1, 0, 0),
 	{ }
@@ -1867,8 +1868,10 @@
 
 static const struct freq_tbl ftbl_nss_port6_rx_clk_src[] = {
 	F(19200000, P_XO, 1, 0, 0),
+	F(25000000, P_UNIPHY2_RX, 5, 0, 0),
 	F(25000000, P_UNIPHY2_RX, 12.5, 0, 0),
 	F(78125000, P_UNIPHY2_RX, 4, 0, 0),
+	F(125000000, P_UNIPHY2_RX, 1, 0, 0),
 	F(125000000, P_UNIPHY2_RX, 2.5, 0, 0),
 	F(156250000, P_UNIPHY2_RX, 2, 0, 0),
 	F(312500000, P_UNIPHY2_RX, 1, 0, 0),
@@ -1907,8 +1910,10 @@
 
 static const struct freq_tbl ftbl_nss_port6_tx_clk_src[] = {
 	F(19200000, P_XO, 1, 0, 0),
+	F(25000000, P_UNIPHY2_TX, 5, 0, 0),
 	F(25000000, P_UNIPHY2_TX, 12.5, 0, 0),
 	F(78125000, P_UNIPHY2_TX, 4, 0, 0),
+	F(125000000, P_UNIPHY2_TX, 1, 0, 0),
 	F(125000000, P_UNIPHY2_TX, 2.5, 0, 0),
 	F(156250000, P_UNIPHY2_TX, 2, 0, 0),
 	F(312500000, P_UNIPHY2_TX, 1, 0, 0),
@@ -3346,6 +3351,7 @@
 
 static struct clk_branch gcc_ubi0_ahb_clk = {
 	.halt_reg = 0x6820c,
+	.halt_check = BRANCH_HALT_DELAY,
 	.clkr = {
 		.enable_reg = 0x6820c,
 		.enable_mask = BIT(0),
@@ -3363,6 +3369,7 @@
 
 static struct clk_branch gcc_ubi0_axi_clk = {
 	.halt_reg = 0x68200,
+	.halt_check = BRANCH_HALT_DELAY,
 	.clkr = {
 		.enable_reg = 0x68200,
 		.enable_mask = BIT(0),
@@ -3380,6 +3387,7 @@
 
 static struct clk_branch gcc_ubi0_nc_axi_clk = {
 	.halt_reg = 0x68204,
+	.halt_check = BRANCH_HALT_DELAY,
 	.clkr = {
 		.enable_reg = 0x68204,
 		.enable_mask = BIT(0),
@@ -3397,6 +3405,7 @@
 
 static struct clk_branch gcc_ubi0_core_clk = {
 	.halt_reg = 0x68210,
+	.halt_check = BRANCH_HALT_DELAY,
 	.clkr = {
 		.enable_reg = 0x68210,
 		.enable_mask = BIT(0),
@@ -3414,6 +3423,7 @@
 
 static struct clk_branch gcc_ubi0_mpt_clk = {
 	.halt_reg = 0x68208,
+	.halt_check = BRANCH_HALT_DELAY,
 	.clkr = {
 		.enable_reg = 0x68208,
 		.enable_mask = BIT(0),
@@ -3431,6 +3441,7 @@
 
 static struct clk_branch gcc_ubi1_ahb_clk = {
 	.halt_reg = 0x6822c,
+	.halt_check = BRANCH_HALT_DELAY,
 	.clkr = {
 		.enable_reg = 0x6822c,
 		.enable_mask = BIT(0),
@@ -3448,6 +3459,7 @@
 
 static struct clk_branch gcc_ubi1_axi_clk = {
 	.halt_reg = 0x68220,
+	.halt_check = BRANCH_HALT_DELAY,
 	.clkr = {
 		.enable_reg = 0x68220,
 		.enable_mask = BIT(0),
@@ -3465,6 +3477,7 @@
 
 static struct clk_branch gcc_ubi1_nc_axi_clk = {
 	.halt_reg = 0x68224,
+	.halt_check = BRANCH_HALT_DELAY,
 	.clkr = {
 		.enable_reg = 0x68224,
 		.enable_mask = BIT(0),
@@ -3482,6 +3495,7 @@
 
 static struct clk_branch gcc_ubi1_core_clk = {
 	.halt_reg = 0x68230,
+	.halt_check = BRANCH_HALT_DELAY,
 	.clkr = {
 		.enable_reg = 0x68230,
 		.enable_mask = BIT(0),
@@ -3499,6 +3513,7 @@
 
 static struct clk_branch gcc_ubi1_mpt_clk = {
 	.halt_reg = 0x68228,
+	.halt_check = BRANCH_HALT_DELAY,
 	.clkr = {
 		.enable_reg = 0x68228,
 		.enable_mask = BIT(0),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/qcom/gcc-mdm9615.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/qcom/gcc-mdm9615.c
@@ -58,7 +58,7 @@
 	.enable_mask = BIT(0),
 	.hw.init = &(struct clk_init_data){
 		.name = "pll0_vote",
-		.parent_names = (const char *[]){ "pll8" },
+		.parent_names = (const char *[]){ "pll0" },
 		.num_parents = 1,
 		.ops = &clk_pll_vote_ops,
 	},
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/qcom/gcc-msm8916.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/qcom/gcc-msm8916.c
@@ -260,7 +260,7 @@
 	.l_reg = 0x21004,
 	.m_reg = 0x21008,
 	.n_reg = 0x2100c,
-	.config_reg = 0x21014,
+	.config_reg = 0x21010,
 	.mode_reg = 0x21000,
 	.status_reg = 0x2101c,
 	.status_bit = 17,
@@ -287,7 +287,7 @@
 	.l_reg = 0x20004,
 	.m_reg = 0x20008,
 	.n_reg = 0x2000c,
-	.config_reg = 0x20014,
+	.config_reg = 0x20010,
 	.mode_reg = 0x20000,
 	.status_reg = 0x2001c,
 	.status_bit = 17,
@@ -314,7 +314,7 @@
 	.l_reg = 0x4a004,
 	.m_reg = 0x4a008,
 	.n_reg = 0x4a00c,
-	.config_reg = 0x4a014,
+	.config_reg = 0x4a010,
 	.mode_reg = 0x4a000,
 	.status_reg = 0x4a01c,
 	.status_bit = 17,
@@ -341,7 +341,7 @@
 	.l_reg = 0x23004,
 	.m_reg = 0x23008,
 	.n_reg = 0x2300c,
-	.config_reg = 0x23014,
+	.config_reg = 0x23010,
 	.mode_reg = 0x23000,
 	.status_reg = 0x2301c,
 	.status_bit = 17,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/qcom/gcc-msm8994.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/qcom/gcc-msm8994.c
@@ -107,6 +107,7 @@
 
 static struct clk_alpha_pll_postdiv gpll4 = {
 	.offset = 0x1dc0,
+	.width = 4,
 	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
 	.clkr.hw.init = &(struct clk_init_data)
 	{
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/qcom/gcc-msm8996.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/qcom/gcc-msm8996.c
@@ -2937,20 +2937,6 @@
 	},
 };
 
-static struct clk_branch gcc_aggre1_pnoc_ahb_clk = {
-	.halt_reg = 0x82014,
-	.clkr = {
-		.enable_reg = 0x82014,
-		.enable_mask = BIT(0),
-		.hw.init = &(struct clk_init_data){
-			.name = "gcc_aggre1_pnoc_ahb_clk",
-			.parent_names = (const char *[]){ "periph_noc_clk_src" },
-			.num_parents = 1,
-			.ops = &clk_branch2_ops,
-		},
-	},
-};
-
 static struct clk_branch gcc_aggre2_ufs_axi_clk = {
 	.halt_reg = 0x83014,
 	.clkr = {
@@ -3453,7 +3439,6 @@
 	[GCC_AGGRE0_CNOC_AHB_CLK] = &gcc_aggre0_cnoc_ahb_clk.clkr,
 	[GCC_SMMU_AGGRE0_AXI_CLK] = &gcc_smmu_aggre0_axi_clk.clkr,
 	[GCC_SMMU_AGGRE0_AHB_CLK] = &gcc_smmu_aggre0_ahb_clk.clkr,
-	[GCC_AGGRE1_PNOC_AHB_CLK] = &gcc_aggre1_pnoc_ahb_clk.clkr,
 	[GCC_AGGRE2_UFS_AXI_CLK] = &gcc_aggre2_ufs_axi_clk.clkr,
 	[GCC_AGGRE2_USB3_AXI_CLK] = &gcc_aggre2_usb3_axi_clk.clkr,
 	[GCC_QSPI_AHB_CLK] = &gcc_qspi_ahb_clk.clkr,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/qcom/gcc-msm8998.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/qcom/gcc-msm8998.c
@@ -135,7 +135,7 @@
 
 static struct clk_alpha_pll gpll0 = {
 	.offset = 0x0,
-	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
 	.vco_table = fabia_vco,
 	.num_vco = ARRAY_SIZE(fabia_vco),
 	.clkr = {
@@ -145,58 +145,58 @@
 			.name = "gpll0",
 			.parent_names = (const char *[]){ "xo" },
 			.num_parents = 1,
-			.ops = &clk_alpha_pll_ops,
+			.ops = &clk_alpha_pll_fixed_fabia_ops,
 		}
 	},
 };
 
 static struct clk_alpha_pll_postdiv gpll0_out_even = {
 	.offset = 0x0,
-	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gpll0_out_even",
 		.parent_names = (const char *[]){ "gpll0" },
 		.num_parents = 1,
-		.ops = &clk_alpha_pll_postdiv_ops,
+		.ops = &clk_alpha_pll_postdiv_fabia_ops,
 	},
 };
 
 static struct clk_alpha_pll_postdiv gpll0_out_main = {
 	.offset = 0x0,
-	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gpll0_out_main",
 		.parent_names = (const char *[]){ "gpll0" },
 		.num_parents = 1,
-		.ops = &clk_alpha_pll_postdiv_ops,
+		.ops = &clk_alpha_pll_postdiv_fabia_ops,
 	},
 };
 
 static struct clk_alpha_pll_postdiv gpll0_out_odd = {
 	.offset = 0x0,
-	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gpll0_out_odd",
 		.parent_names = (const char *[]){ "gpll0" },
 		.num_parents = 1,
-		.ops = &clk_alpha_pll_postdiv_ops,
+		.ops = &clk_alpha_pll_postdiv_fabia_ops,
 	},
 };
 
 static struct clk_alpha_pll_postdiv gpll0_out_test = {
 	.offset = 0x0,
-	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gpll0_out_test",
 		.parent_names = (const char *[]){ "gpll0" },
 		.num_parents = 1,
-		.ops = &clk_alpha_pll_postdiv_ops,
+		.ops = &clk_alpha_pll_postdiv_fabia_ops,
 	},
 };
 
 static struct clk_alpha_pll gpll1 = {
 	.offset = 0x1000,
-	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
 	.vco_table = fabia_vco,
 	.num_vco = ARRAY_SIZE(fabia_vco),
 	.clkr = {
@@ -206,58 +206,58 @@
 			.name = "gpll1",
 			.parent_names = (const char *[]){ "xo" },
 			.num_parents = 1,
-			.ops = &clk_alpha_pll_ops,
+			.ops = &clk_alpha_pll_fixed_fabia_ops,
 		}
 	},
 };
 
 static struct clk_alpha_pll_postdiv gpll1_out_even = {
 	.offset = 0x1000,
-	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gpll1_out_even",
 		.parent_names = (const char *[]){ "gpll1" },
 		.num_parents = 1,
-		.ops = &clk_alpha_pll_postdiv_ops,
+		.ops = &clk_alpha_pll_postdiv_fabia_ops,
 	},
 };
 
 static struct clk_alpha_pll_postdiv gpll1_out_main = {
 	.offset = 0x1000,
-	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gpll1_out_main",
 		.parent_names = (const char *[]){ "gpll1" },
 		.num_parents = 1,
-		.ops = &clk_alpha_pll_postdiv_ops,
+		.ops = &clk_alpha_pll_postdiv_fabia_ops,
 	},
 };
 
 static struct clk_alpha_pll_postdiv gpll1_out_odd = {
 	.offset = 0x1000,
-	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gpll1_out_odd",
 		.parent_names = (const char *[]){ "gpll1" },
 		.num_parents = 1,
-		.ops = &clk_alpha_pll_postdiv_ops,
+		.ops = &clk_alpha_pll_postdiv_fabia_ops,
 	},
 };
 
 static struct clk_alpha_pll_postdiv gpll1_out_test = {
 	.offset = 0x1000,
-	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gpll1_out_test",
 		.parent_names = (const char *[]){ "gpll1" },
 		.num_parents = 1,
-		.ops = &clk_alpha_pll_postdiv_ops,
+		.ops = &clk_alpha_pll_postdiv_fabia_ops,
 	},
 };
 
 static struct clk_alpha_pll gpll2 = {
 	.offset = 0x2000,
-	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
 	.vco_table = fabia_vco,
 	.num_vco = ARRAY_SIZE(fabia_vco),
 	.clkr = {
@@ -267,58 +267,58 @@
 			.name = "gpll2",
 			.parent_names = (const char *[]){ "xo" },
 			.num_parents = 1,
-			.ops = &clk_alpha_pll_ops,
+			.ops = &clk_alpha_pll_fixed_fabia_ops,
 		}
 	},
 };
 
 static struct clk_alpha_pll_postdiv gpll2_out_even = {
 	.offset = 0x2000,
-	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gpll2_out_even",
 		.parent_names = (const char *[]){ "gpll2" },
 		.num_parents = 1,
-		.ops = &clk_alpha_pll_postdiv_ops,
+		.ops = &clk_alpha_pll_postdiv_fabia_ops,
 	},
 };
 
 static struct clk_alpha_pll_postdiv gpll2_out_main = {
 	.offset = 0x2000,
-	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gpll2_out_main",
 		.parent_names = (const char *[]){ "gpll2" },
 		.num_parents = 1,
-		.ops = &clk_alpha_pll_postdiv_ops,
+		.ops = &clk_alpha_pll_postdiv_fabia_ops,
 	},
 };
 
 static struct clk_alpha_pll_postdiv gpll2_out_odd = {
 	.offset = 0x2000,
-	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gpll2_out_odd",
 		.parent_names = (const char *[]){ "gpll2" },
 		.num_parents = 1,
-		.ops = &clk_alpha_pll_postdiv_ops,
+		.ops = &clk_alpha_pll_postdiv_fabia_ops,
 	},
 };
 
 static struct clk_alpha_pll_postdiv gpll2_out_test = {
 	.offset = 0x2000,
-	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gpll2_out_test",
 		.parent_names = (const char *[]){ "gpll2" },
 		.num_parents = 1,
-		.ops = &clk_alpha_pll_postdiv_ops,
+		.ops = &clk_alpha_pll_postdiv_fabia_ops,
 	},
 };
 
 static struct clk_alpha_pll gpll3 = {
 	.offset = 0x3000,
-	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
 	.vco_table = fabia_vco,
 	.num_vco = ARRAY_SIZE(fabia_vco),
 	.clkr = {
@@ -328,58 +328,58 @@
 			.name = "gpll3",
 			.parent_names = (const char *[]){ "xo" },
 			.num_parents = 1,
-			.ops = &clk_alpha_pll_ops,
+			.ops = &clk_alpha_pll_fixed_fabia_ops,
 		}
 	},
 };
 
 static struct clk_alpha_pll_postdiv gpll3_out_even = {
 	.offset = 0x3000,
-	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gpll3_out_even",
 		.parent_names = (const char *[]){ "gpll3" },
 		.num_parents = 1,
-		.ops = &clk_alpha_pll_postdiv_ops,
+		.ops = &clk_alpha_pll_postdiv_fabia_ops,
 	},
 };
 
 static struct clk_alpha_pll_postdiv gpll3_out_main = {
 	.offset = 0x3000,
-	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gpll3_out_main",
 		.parent_names = (const char *[]){ "gpll3" },
 		.num_parents = 1,
-		.ops = &clk_alpha_pll_postdiv_ops,
+		.ops = &clk_alpha_pll_postdiv_fabia_ops,
 	},
 };
 
 static struct clk_alpha_pll_postdiv gpll3_out_odd = {
 	.offset = 0x3000,
-	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gpll3_out_odd",
 		.parent_names = (const char *[]){ "gpll3" },
 		.num_parents = 1,
-		.ops = &clk_alpha_pll_postdiv_ops,
+		.ops = &clk_alpha_pll_postdiv_fabia_ops,
 	},
 };
 
 static struct clk_alpha_pll_postdiv gpll3_out_test = {
 	.offset = 0x3000,
-	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gpll3_out_test",
 		.parent_names = (const char *[]){ "gpll3" },
 		.num_parents = 1,
-		.ops = &clk_alpha_pll_postdiv_ops,
+		.ops = &clk_alpha_pll_postdiv_fabia_ops,
 	},
 };
 
 static struct clk_alpha_pll gpll4 = {
 	.offset = 0x77000,
-	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
 	.vco_table = fabia_vco,
 	.num_vco = ARRAY_SIZE(fabia_vco),
 	.clkr = {
@@ -389,52 +389,52 @@
 			.name = "gpll4",
 			.parent_names = (const char *[]){ "xo" },
 			.num_parents = 1,
-			.ops = &clk_alpha_pll_ops,
+			.ops = &clk_alpha_pll_fixed_fabia_ops,
 		}
 	},
 };
 
 static struct clk_alpha_pll_postdiv gpll4_out_even = {
 	.offset = 0x77000,
-	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gpll4_out_even",
 		.parent_names = (const char *[]){ "gpll4" },
 		.num_parents = 1,
-		.ops = &clk_alpha_pll_postdiv_ops,
+		.ops = &clk_alpha_pll_postdiv_fabia_ops,
 	},
 };
 
 static struct clk_alpha_pll_postdiv gpll4_out_main = {
 	.offset = 0x77000,
-	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gpll4_out_main",
 		.parent_names = (const char *[]){ "gpll4" },
 		.num_parents = 1,
-		.ops = &clk_alpha_pll_postdiv_ops,
+		.ops = &clk_alpha_pll_postdiv_fabia_ops,
 	},
 };
 
 static struct clk_alpha_pll_postdiv gpll4_out_odd = {
 	.offset = 0x77000,
-	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gpll4_out_odd",
 		.parent_names = (const char *[]){ "gpll4" },
 		.num_parents = 1,
-		.ops = &clk_alpha_pll_postdiv_ops,
+		.ops = &clk_alpha_pll_postdiv_fabia_ops,
 	},
 };
 
 static struct clk_alpha_pll_postdiv gpll4_out_test = {
 	.offset = 0x77000,
-	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
+	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gpll4_out_test",
 		.parent_names = (const char *[]){ "gpll4" },
 		.num_parents = 1,
-		.ops = &clk_alpha_pll_postdiv_ops,
+		.ops = &clk_alpha_pll_postdiv_fabia_ops,
 	},
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/qcom/gcc-qcs404.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/qcom/gcc-qcs404.c
@@ -25,11 +25,9 @@
 	P_CORE_BI_PLL_TEST_SE,
 	P_DSI0_PHY_PLL_OUT_BYTECLK,
 	P_DSI0_PHY_PLL_OUT_DSICLK,
-	P_GPLL0_OUT_AUX,
 	P_GPLL0_OUT_MAIN,
 	P_GPLL1_OUT_MAIN,
 	P_GPLL3_OUT_MAIN,
-	P_GPLL4_OUT_AUX,
 	P_GPLL4_OUT_MAIN,
 	P_GPLL6_OUT_AUX,
 	P_HDMI_PHY_PLL_CLK,
@@ -109,28 +107,24 @@
 static const struct parent_map gcc_parent_map_5[] = {
 	{ P_XO, 0 },
 	{ P_DSI0_PHY_PLL_OUT_BYTECLK, 1 },
-	{ P_GPLL0_OUT_AUX, 2 },
 	{ P_CORE_BI_PLL_TEST_SE, 7 },
 };
 
 static const char * const gcc_parent_names_5[] = {
 	"cxo",
-	"dsi0pll_byteclk_src",
-	"gpll0_out_aux",
+	"dsi0pllbyte",
 	"core_bi_pll_test_se",
 };
 
 static const struct parent_map gcc_parent_map_6[] = {
 	{ P_XO, 0 },
 	{ P_DSI0_PHY_PLL_OUT_BYTECLK, 2 },
-	{ P_GPLL0_OUT_AUX, 3 },
 	{ P_CORE_BI_PLL_TEST_SE, 7 },
 };
 
 static const char * const gcc_parent_names_6[] = {
 	"cxo",
-	"dsi0_phy_pll_out_byteclk",
-	"gpll0_out_aux",
+	"dsi0pllbyte",
 	"core_bi_pll_test_se",
 };
 
@@ -139,7 +133,6 @@
 	{ P_GPLL0_OUT_MAIN, 1 },
 	{ P_GPLL3_OUT_MAIN, 2 },
 	{ P_GPLL6_OUT_AUX, 3 },
-	{ P_GPLL4_OUT_AUX, 4 },
 	{ P_CORE_BI_PLL_TEST_SE, 7 },
 };
 
@@ -148,7 +141,6 @@
 	"gpll0_out_main",
 	"gpll3_out_main",
 	"gpll6_out_aux",
-	"gpll4_out_aux",
 	"core_bi_pll_test_se",
 };
 
@@ -175,7 +167,7 @@
 static const char * const gcc_parent_names_9[] = {
 	"cxo",
 	"gpll0_out_main",
-	"dsi0_phy_pll_out_dsiclk",
+	"dsi0pll",
 	"gpll6_out_aux",
 	"core_bi_pll_test_se",
 };
@@ -207,14 +199,12 @@
 static const struct parent_map gcc_parent_map_12[] = {
 	{ P_XO, 0 },
 	{ P_DSI0_PHY_PLL_OUT_DSICLK, 1 },
-	{ P_GPLL0_OUT_AUX, 2 },
 	{ P_CORE_BI_PLL_TEST_SE, 7 },
 };
 
 static const char * const gcc_parent_names_12[] = {
 	"cxo",
-	"dsi0pll_pclk_src",
-	"gpll0_out_aux",
+	"dsi0pll",
 	"core_bi_pll_test_se",
 };
 
@@ -237,40 +227,34 @@
 static const struct parent_map gcc_parent_map_14[] = {
 	{ P_XO, 0 },
 	{ P_GPLL0_OUT_MAIN, 1 },
-	{ P_GPLL4_OUT_AUX, 2 },
 	{ P_CORE_BI_PLL_TEST_SE, 7 },
 };
 
 static const char * const gcc_parent_names_14[] = {
 	"cxo",
 	"gpll0_out_main",
-	"gpll4_out_aux",
 	"core_bi_pll_test_se",
 };
 
 static const struct parent_map gcc_parent_map_15[] = {
 	{ P_XO, 0 },
-	{ P_GPLL0_OUT_AUX, 2 },
 	{ P_CORE_BI_PLL_TEST_SE, 7 },
 };
 
 static const char * const gcc_parent_names_15[] = {
 	"cxo",
-	"gpll0_out_aux",
 	"core_bi_pll_test_se",
 };
 
 static const struct parent_map gcc_parent_map_16[] = {
 	{ P_XO, 0 },
 	{ P_GPLL0_OUT_MAIN, 1 },
-	{ P_GPLL0_OUT_AUX, 2 },
 	{ P_CORE_BI_PLL_TEST_SE, 7 },
 };
 
 static const char * const gcc_parent_names_16[] = {
 	"cxo",
 	"gpll0_out_main",
-	"gpll0_out_aux",
 	"core_bi_pll_test_se",
 };
 
@@ -353,6 +337,7 @@
 /* 930MHz configuration */
 static const struct alpha_pll_config gpll3_config = {
 	.l = 48,
+	.alpha_hi = 0x70,
 	.alpha = 0x0,
 	.alpha_en_mask = BIT(24),
 	.post_div_mask = 0xf << 8,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/qcom/gcc-sdm660.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/qcom/gcc-sdm660.c
@@ -666,7 +666,7 @@
 	.cmd_rcgr = 0x48044,
 	.mnd_width = 0,
 	.hid_width = 5,
-	.parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
+	.parent_map = gcc_parent_map_xo_gpll0,
 	.freq_tbl = ftbl_hmss_rbcpr_clk_src,
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "hmss_rbcpr_clk_src",
@@ -1715,6 +1715,9 @@
 
 static struct clk_branch gcc_mss_mnoc_bimc_axi_clk = {
 	.halt_reg = 0x8a004,
+	.halt_check = BRANCH_HALT,
+	.hwcg_reg = 0x8a004,
+	.hwcg_bit = 1,
 	.clkr = {
 		.enable_reg = 0x8a004,
 		.enable_mask = BIT(0),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/qcom/gcc-sdm845.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/qcom/gcc-sdm845.c
@@ -3255,6 +3255,7 @@
 		.name = "hlos1_vote_aggre_noc_mmu_audio_tbu_gdsc",
 	},
 	.pwrsts = PWRSTS_OFF_ON,
+	.flags = VOTABLE,
 };
 
 static struct gdsc hlos1_vote_aggre_noc_mmu_pcie_tbu_gdsc = {
@@ -3263,6 +3264,7 @@
 		.name = "hlos1_vote_aggre_noc_mmu_pcie_tbu_gdsc",
 	},
 	.pwrsts = PWRSTS_OFF_ON,
+	.flags = VOTABLE,
 };
 
 static struct gdsc hlos1_vote_aggre_noc_mmu_tbu1_gdsc = {
@@ -3271,6 +3273,7 @@
 		.name = "hlos1_vote_aggre_noc_mmu_tbu1_gdsc",
 	},
 	.pwrsts = PWRSTS_OFF_ON,
+	.flags = VOTABLE,
 };
 
 static struct gdsc hlos1_vote_aggre_noc_mmu_tbu2_gdsc = {
@@ -3279,6 +3282,7 @@
 		.name = "hlos1_vote_aggre_noc_mmu_tbu2_gdsc",
 	},
 	.pwrsts = PWRSTS_OFF_ON,
+	.flags = VOTABLE,
 };
 
 static struct gdsc hlos1_vote_mmnoc_mmu_tbu_hf0_gdsc = {
@@ -3287,6 +3291,7 @@
 		.name = "hlos1_vote_mmnoc_mmu_tbu_hf0_gdsc",
 	},
 	.pwrsts = PWRSTS_OFF_ON,
+	.flags = VOTABLE,
 };
 
 static struct gdsc hlos1_vote_mmnoc_mmu_tbu_hf1_gdsc = {
@@ -3295,6 +3300,7 @@
 		.name = "hlos1_vote_mmnoc_mmu_tbu_hf1_gdsc",
 	},
 	.pwrsts = PWRSTS_OFF_ON,
+	.flags = VOTABLE,
 };
 
 static struct gdsc hlos1_vote_mmnoc_mmu_tbu_sf_gdsc = {
@@ -3303,6 +3309,7 @@
 		.name = "hlos1_vote_mmnoc_mmu_tbu_sf_gdsc",
 	},
 	.pwrsts = PWRSTS_OFF_ON,
+	.flags = VOTABLE,
 };
 
 static struct clk_regmap *gcc_sdm845_clocks[] = {
@@ -3639,3 +3646,4 @@
 MODULE_DESCRIPTION("QTI GCC SDM845 Driver");
 MODULE_LICENSE("GPL v2");
 MODULE_ALIAS("platform:gcc-sdm845");
+MODULE_SOFTDEP("pre: rpmhpd");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/qcom/gcc-sm8150.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/qcom/gcc-sm8150.c
@@ -75,8 +75,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gpll0_out_even",
 		.parent_data = &(const struct clk_parent_data){
-			.fw_name = "bi_tcxo",
-			.name = "bi_tcxo",
+			.hw = &gpll0.clkr.hw,
 		},
 		.num_parents = 1,
 		.ops = &clk_trion_pll_postdiv_ops,
@@ -251,7 +250,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_cpuss_ahb_clk_src",
 		.parent_data = gcc_parents_0,
-		.num_parents = 4,
+		.num_parents = ARRAY_SIZE(gcc_parents_0),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -274,7 +273,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_emac_ptp_clk_src",
 		.parent_data = gcc_parents_5,
-		.num_parents = 5,
+		.num_parents = ARRAY_SIZE(gcc_parents_5),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -300,7 +299,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_emac_rgmii_clk_src",
 		.parent_data = gcc_parents_5,
-		.num_parents = 5,
+		.num_parents = ARRAY_SIZE(gcc_parents_5),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -324,7 +323,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_gp1_clk_src",
 		.parent_data = gcc_parents_1,
-		.num_parents = 5,
+		.num_parents = ARRAY_SIZE(gcc_parents_1),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -339,7 +338,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_gp2_clk_src",
 		.parent_data = gcc_parents_1,
-		.num_parents = 5,
+		.num_parents = ARRAY_SIZE(gcc_parents_1),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -354,7 +353,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_gp3_clk_src",
 		.parent_data = gcc_parents_1,
-		.num_parents = 5,
+		.num_parents = ARRAY_SIZE(gcc_parents_1),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -375,7 +374,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_pcie_0_aux_clk_src",
 		.parent_data = gcc_parents_2,
-		.num_parents = 3,
+		.num_parents = ARRAY_SIZE(gcc_parents_2),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -390,7 +389,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_pcie_1_aux_clk_src",
 		.parent_data = gcc_parents_2,
-		.num_parents = 3,
+		.num_parents = ARRAY_SIZE(gcc_parents_2),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -411,7 +410,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_pcie_phy_refgen_clk_src",
 		.parent_data = gcc_parents_0,
-		.num_parents = 4,
+		.num_parents = ARRAY_SIZE(gcc_parents_0),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -433,7 +432,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_pdm2_clk_src",
 		.parent_data = gcc_parents_0,
-		.num_parents = 4,
+		.num_parents = ARRAY_SIZE(gcc_parents_0),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -456,7 +455,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_qspi_core_clk_src",
 		.parent_data = gcc_parents_0,
-		.num_parents = 4,
+		.num_parents = ARRAY_SIZE(gcc_parents_0),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -490,7 +489,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_qupv3_wrap0_s0_clk_src",
 		.parent_data = gcc_parents_0,
-		.num_parents = 4,
+		.num_parents = ARRAY_SIZE(gcc_parents_0),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -505,7 +504,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_qupv3_wrap0_s1_clk_src",
 		.parent_data = gcc_parents_0,
-		.num_parents = 4,
+		.num_parents = ARRAY_SIZE(gcc_parents_0),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -520,7 +519,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_qupv3_wrap0_s2_clk_src",
 		.parent_data = gcc_parents_0,
-		.num_parents = 4,
+		.num_parents = ARRAY_SIZE(gcc_parents_0),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -535,7 +534,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_qupv3_wrap0_s3_clk_src",
 		.parent_data = gcc_parents_0,
-		.num_parents = 4,
+		.num_parents = ARRAY_SIZE(gcc_parents_0),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -550,7 +549,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_qupv3_wrap0_s4_clk_src",
 		.parent_data = gcc_parents_0,
-		.num_parents = 4,
+		.num_parents = ARRAY_SIZE(gcc_parents_0),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -565,7 +564,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_qupv3_wrap0_s5_clk_src",
 		.parent_data = gcc_parents_0,
-		.num_parents = 4,
+		.num_parents = ARRAY_SIZE(gcc_parents_0),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -580,7 +579,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_qupv3_wrap0_s6_clk_src",
 		.parent_data = gcc_parents_0,
-		.num_parents = 4,
+		.num_parents = ARRAY_SIZE(gcc_parents_0),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -595,7 +594,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_qupv3_wrap0_s7_clk_src",
 		.parent_data = gcc_parents_0,
-		.num_parents = 4,
+		.num_parents = ARRAY_SIZE(gcc_parents_0),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -610,7 +609,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_qupv3_wrap1_s0_clk_src",
 		.parent_data = gcc_parents_0,
-		.num_parents = 4,
+		.num_parents = ARRAY_SIZE(gcc_parents_0),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -625,7 +624,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_qupv3_wrap1_s1_clk_src",
 		.parent_data = gcc_parents_0,
-		.num_parents = 4,
+		.num_parents = ARRAY_SIZE(gcc_parents_0),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -640,7 +639,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_qupv3_wrap1_s2_clk_src",
 		.parent_data = gcc_parents_0,
-		.num_parents = 4,
+		.num_parents = ARRAY_SIZE(gcc_parents_0),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -655,7 +654,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_qupv3_wrap1_s3_clk_src",
 		.parent_data = gcc_parents_0,
-		.num_parents = 4,
+		.num_parents = ARRAY_SIZE(gcc_parents_0),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -670,7 +669,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_qupv3_wrap1_s4_clk_src",
 		.parent_data = gcc_parents_0,
-		.num_parents = 4,
+		.num_parents = ARRAY_SIZE(gcc_parents_0),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -685,7 +684,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_qupv3_wrap1_s5_clk_src",
 		.parent_data = gcc_parents_0,
-		.num_parents = 4,
+		.num_parents = ARRAY_SIZE(gcc_parents_0),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -700,7 +699,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_qupv3_wrap2_s0_clk_src",
 		.parent_data = gcc_parents_0,
-		.num_parents = 4,
+		.num_parents = ARRAY_SIZE(gcc_parents_0),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -715,7 +714,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_qupv3_wrap2_s1_clk_src",
 		.parent_data = gcc_parents_0,
-		.num_parents = 4,
+		.num_parents = ARRAY_SIZE(gcc_parents_0),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -730,7 +729,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_qupv3_wrap2_s2_clk_src",
 		.parent_data = gcc_parents_0,
-		.num_parents = 4,
+		.num_parents = ARRAY_SIZE(gcc_parents_0),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -745,7 +744,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_qupv3_wrap2_s3_clk_src",
 		.parent_data = gcc_parents_0,
-		.num_parents = 4,
+		.num_parents = ARRAY_SIZE(gcc_parents_0),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -760,7 +759,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_qupv3_wrap2_s4_clk_src",
 		.parent_data = gcc_parents_0,
-		.num_parents = 4,
+		.num_parents = ARRAY_SIZE(gcc_parents_0),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -775,7 +774,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_qupv3_wrap2_s5_clk_src",
 		.parent_data = gcc_parents_0,
-		.num_parents = 4,
+		.num_parents = ARRAY_SIZE(gcc_parents_0),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -801,8 +800,8 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_sdcc2_apps_clk_src",
 		.parent_data = gcc_parents_6,
-		.num_parents = 5,
-		.flags = CLK_SET_RATE_PARENT,
+		.num_parents = ARRAY_SIZE(gcc_parents_6),
+		.flags = CLK_OPS_PARENT_ENABLE,
 		.ops = &clk_rcg2_floor_ops,
 	},
 };
@@ -826,7 +825,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_sdcc4_apps_clk_src",
 		.parent_data = gcc_parents_3,
-		.num_parents = 3,
+		.num_parents = ARRAY_SIZE(gcc_parents_3),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_floor_ops,
 	},
@@ -846,7 +845,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_tsif_ref_clk_src",
 		.parent_data = gcc_parents_7,
-		.num_parents = 5,
+		.num_parents = ARRAY_SIZE(gcc_parents_7),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -870,7 +869,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_ufs_card_axi_clk_src",
 		.parent_data = gcc_parents_0,
-		.num_parents = 4,
+		.num_parents = ARRAY_SIZE(gcc_parents_0),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -893,7 +892,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_ufs_card_ice_core_clk_src",
 		.parent_data = gcc_parents_0,
-		.num_parents = 4,
+		.num_parents = ARRAY_SIZE(gcc_parents_0),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -913,7 +912,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_ufs_card_phy_aux_clk_src",
 		.parent_data = gcc_parents_4,
-		.num_parents = 2,
+		.num_parents = ARRAY_SIZE(gcc_parents_4),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -935,7 +934,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_ufs_card_unipro_core_clk_src",
 		.parent_data = gcc_parents_0,
-		.num_parents = 4,
+		.num_parents = ARRAY_SIZE(gcc_parents_0),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -959,7 +958,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_ufs_phy_axi_clk_src",
 		.parent_data = gcc_parents_0,
-		.num_parents = 4,
+		.num_parents = ARRAY_SIZE(gcc_parents_0),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -974,7 +973,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_ufs_phy_ice_core_clk_src",
 		.parent_data = gcc_parents_0,
-		.num_parents = 4,
+		.num_parents = ARRAY_SIZE(gcc_parents_0),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -989,7 +988,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_ufs_phy_phy_aux_clk_src",
 		.parent_data = gcc_parents_4,
-		.num_parents = 2,
+		.num_parents = ARRAY_SIZE(gcc_parents_4),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -1004,7 +1003,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_ufs_phy_unipro_core_clk_src",
 		.parent_data = gcc_parents_0,
-		.num_parents = 4,
+		.num_parents = ARRAY_SIZE(gcc_parents_0),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -1028,7 +1027,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_usb30_prim_master_clk_src",
 		.parent_data = gcc_parents_0,
-		.num_parents = 4,
+		.num_parents = ARRAY_SIZE(gcc_parents_0),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -1050,7 +1049,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_usb30_prim_mock_utmi_clk_src",
 		.parent_data = gcc_parents_0,
-		.num_parents = 4,
+		.num_parents = ARRAY_SIZE(gcc_parents_0),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -1065,7 +1064,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_usb30_sec_master_clk_src",
 		.parent_data = gcc_parents_0,
-		.num_parents = 4,
+		.num_parents = ARRAY_SIZE(gcc_parents_0),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -1080,7 +1079,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_usb30_sec_mock_utmi_clk_src",
 		.parent_data = gcc_parents_0,
-		.num_parents = 4,
+		.num_parents = ARRAY_SIZE(gcc_parents_0),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -1095,7 +1094,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_usb3_prim_phy_aux_clk_src",
 		.parent_data = gcc_parents_2,
-		.num_parents = 3,
+		.num_parents = ARRAY_SIZE(gcc_parents_2),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -1110,7 +1109,7 @@
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_usb3_sec_phy_aux_clk_src",
 		.parent_data = gcc_parents_2,
-		.num_parents = 3,
+		.num_parents = ARRAY_SIZE(gcc_parents_2),
 		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 	},
@@ -1616,6 +1615,38 @@
 	},
 };
 
+static struct clk_branch gcc_gpu_gpll0_clk_src = {
+	.halt_check = BRANCH_HALT_SKIP,
+	.clkr = {
+		.enable_reg = 0x52004,
+		.enable_mask = BIT(15),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_gpu_gpll0_clk_src",
+			.parent_hws = (const struct clk_hw *[]){
+				&gpll0.clkr.hw },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_gpu_gpll0_div_clk_src = {
+	.halt_check = BRANCH_HALT_SKIP,
+	.clkr = {
+		.enable_reg = 0x52004,
+		.enable_mask = BIT(16),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_gpu_gpll0_div_clk_src",
+			.parent_hws = (const struct clk_hw *[]){
+				&gpll0_out_even.clkr.hw },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
 static struct clk_branch gcc_gpu_iref_clk = {
 	.halt_reg = 0x8c010,
 	.halt_check = BRANCH_HALT,
@@ -1698,6 +1729,38 @@
 	},
 };
 
+static struct clk_branch gcc_npu_gpll0_clk_src = {
+	.halt_check = BRANCH_HALT_SKIP,
+	.clkr = {
+		.enable_reg = 0x52004,
+		.enable_mask = BIT(18),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_npu_gpll0_clk_src",
+			.parent_hws = (const struct clk_hw *[]){
+				&gpll0.clkr.hw },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_npu_gpll0_div_clk_src = {
+	.halt_check = BRANCH_HALT_SKIP,
+	.clkr = {
+		.enable_reg = 0x52004,
+		.enable_mask = BIT(19),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_npu_gpll0_div_clk_src",
+			.parent_hws = (const struct clk_hw *[]){
+				&gpll0_out_even.clkr.hw },
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
 static struct clk_branch gcc_npu_trig_clk = {
 	.halt_reg = 0x4d00c,
 	.halt_check = BRANCH_VOTED,
@@ -2812,6 +2875,45 @@
 	},
 };
 
+/* external clocks so add BRANCH_HALT_SKIP */
+static struct clk_branch gcc_ufs_card_rx_symbol_0_clk = {
+	.halt_check = BRANCH_HALT_SKIP,
+	.clkr = {
+		.enable_reg = 0x7501c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ufs_card_rx_symbol_0_clk",
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+/* external clocks so add BRANCH_HALT_SKIP */
+static struct clk_branch gcc_ufs_card_rx_symbol_1_clk = {
+	.halt_check = BRANCH_HALT_SKIP,
+	.clkr = {
+		.enable_reg = 0x750ac,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ufs_card_rx_symbol_1_clk",
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+/* external clocks so add BRANCH_HALT_SKIP */
+static struct clk_branch gcc_ufs_card_tx_symbol_0_clk = {
+	.halt_check = BRANCH_HALT_SKIP,
+	.clkr = {
+		.enable_reg = 0x75018,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ufs_card_tx_symbol_0_clk",
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
 static struct clk_branch gcc_ufs_card_unipro_core_clk = {
 	.halt_reg = 0x75058,
 	.halt_check = BRANCH_HALT,
@@ -2992,6 +3094,45 @@
 	},
 };
 
+/* external clocks so add BRANCH_HALT_SKIP */
+static struct clk_branch gcc_ufs_phy_rx_symbol_0_clk = {
+	.halt_check = BRANCH_HALT_SKIP,
+	.clkr = {
+		.enable_reg = 0x7701c,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ufs_phy_rx_symbol_0_clk",
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+/* external clocks so add BRANCH_HALT_SKIP */
+static struct clk_branch gcc_ufs_phy_rx_symbol_1_clk = {
+	.halt_check = BRANCH_HALT_SKIP,
+	.clkr = {
+		.enable_reg = 0x770ac,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ufs_phy_rx_symbol_1_clk",
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+/* external clocks so add BRANCH_HALT_SKIP */
+static struct clk_branch gcc_ufs_phy_tx_symbol_0_clk = {
+	.halt_check = BRANCH_HALT_SKIP,
+	.clkr = {
+		.enable_reg = 0x77018,
+		.enable_mask = BIT(0),
+		.hw.init = &(struct clk_init_data){
+			.name = "gcc_ufs_phy_tx_symbol_0_clk",
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
 static struct clk_branch gcc_ufs_phy_unipro_core_clk = {
 	.halt_reg = 0x77058,
 	.halt_check = BRANCH_HALT,
@@ -3332,12 +3473,16 @@
 	[GCC_GP3_CLK] = &gcc_gp3_clk.clkr,
 	[GCC_GP3_CLK_SRC] = &gcc_gp3_clk_src.clkr,
 	[GCC_GPU_CFG_AHB_CLK] = &gcc_gpu_cfg_ahb_clk.clkr,
+	[GCC_GPU_GPLL0_CLK_SRC] = &gcc_gpu_gpll0_clk_src.clkr,
+	[GCC_GPU_GPLL0_DIV_CLK_SRC] = &gcc_gpu_gpll0_div_clk_src.clkr,
 	[GCC_GPU_IREF_CLK] = &gcc_gpu_iref_clk.clkr,
 	[GCC_GPU_MEMNOC_GFX_CLK] = &gcc_gpu_memnoc_gfx_clk.clkr,
 	[GCC_GPU_SNOC_DVM_GFX_CLK] = &gcc_gpu_snoc_dvm_gfx_clk.clkr,
 	[GCC_NPU_AT_CLK] = &gcc_npu_at_clk.clkr,
 	[GCC_NPU_AXI_CLK] = &gcc_npu_axi_clk.clkr,
 	[GCC_NPU_CFG_AHB_CLK] = &gcc_npu_cfg_ahb_clk.clkr,
+	[GCC_NPU_GPLL0_CLK_SRC] = &gcc_npu_gpll0_clk_src.clkr,
+	[GCC_NPU_GPLL0_DIV_CLK_SRC] = &gcc_npu_gpll0_div_clk_src.clkr,
 	[GCC_NPU_TRIG_CLK] = &gcc_npu_trig_clk.clkr,
 	[GCC_PCIE0_PHY_REFGEN_CLK] = &gcc_pcie0_phy_refgen_clk.clkr,
 	[GCC_PCIE1_PHY_REFGEN_CLK] = &gcc_pcie1_phy_refgen_clk.clkr,
@@ -3442,6 +3587,9 @@
 	[GCC_UFS_CARD_PHY_AUX_CLK_SRC] = &gcc_ufs_card_phy_aux_clk_src.clkr,
 	[GCC_UFS_CARD_PHY_AUX_HW_CTL_CLK] =
 		&gcc_ufs_card_phy_aux_hw_ctl_clk.clkr,
+	[GCC_UFS_CARD_RX_SYMBOL_0_CLK] = &gcc_ufs_card_rx_symbol_0_clk.clkr,
+	[GCC_UFS_CARD_RX_SYMBOL_1_CLK] = &gcc_ufs_card_rx_symbol_1_clk.clkr,
+	[GCC_UFS_CARD_TX_SYMBOL_0_CLK] = &gcc_ufs_card_tx_symbol_0_clk.clkr,
 	[GCC_UFS_CARD_UNIPRO_CORE_CLK] = &gcc_ufs_card_unipro_core_clk.clkr,
 	[GCC_UFS_CARD_UNIPRO_CORE_CLK_SRC] =
 		&gcc_ufs_card_unipro_core_clk_src.clkr,
@@ -3459,6 +3607,9 @@
 	[GCC_UFS_PHY_PHY_AUX_CLK] = &gcc_ufs_phy_phy_aux_clk.clkr,
 	[GCC_UFS_PHY_PHY_AUX_CLK_SRC] = &gcc_ufs_phy_phy_aux_clk_src.clkr,
 	[GCC_UFS_PHY_PHY_AUX_HW_CTL_CLK] = &gcc_ufs_phy_phy_aux_hw_ctl_clk.clkr,
+	[GCC_UFS_PHY_RX_SYMBOL_0_CLK] = &gcc_ufs_phy_rx_symbol_0_clk.clkr,
+	[GCC_UFS_PHY_RX_SYMBOL_1_CLK] = &gcc_ufs_phy_rx_symbol_1_clk.clkr,
+	[GCC_UFS_PHY_TX_SYMBOL_0_CLK] = &gcc_ufs_phy_tx_symbol_0_clk.clkr,
 	[GCC_UFS_PHY_UNIPRO_CORE_CLK] = &gcc_ufs_phy_unipro_core_clk.clkr,
 	[GCC_UFS_PHY_UNIPRO_CORE_CLK_SRC] =
 		&gcc_ufs_phy_unipro_core_clk_src.clkr,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/qcom/gdsc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/qcom/gdsc.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2015, 2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015, 2017-2018, 2022, The Linux Foundation. All rights reserved.
  */
 
 #include <linux/bitops.h>
@@ -31,9 +31,14 @@
 #define CFG_GDSCR_OFFSET		0x4
 
 /* Wait 2^n CXO cycles between all states. Here, n=2 (4 cycles). */
-#define EN_REST_WAIT_VAL	(0x2 << 20)
-#define EN_FEW_WAIT_VAL		(0x8 << 16)
-#define CLK_DIS_WAIT_VAL	(0x2 << 12)
+#define EN_REST_WAIT_VAL	0x2
+#define EN_FEW_WAIT_VAL		0x8
+#define CLK_DIS_WAIT_VAL	0x2
+
+/* Transition delay shifts */
+#define EN_REST_WAIT_SHIFT	20
+#define EN_FEW_WAIT_SHIFT	16
+#define CLK_DIS_WAIT_SHIFT	12
 
 #define RETAIN_MEM		BIT(14)
 #define RETAIN_PERIPH		BIT(13)
@@ -308,7 +313,18 @@
 	 */
 	mask = HW_CONTROL_MASK | SW_OVERRIDE_MASK |
 	       EN_REST_WAIT_MASK | EN_FEW_WAIT_MASK | CLK_DIS_WAIT_MASK;
-	val = EN_REST_WAIT_VAL | EN_FEW_WAIT_VAL | CLK_DIS_WAIT_VAL;
+
+	if (!sc->en_rest_wait_val)
+		sc->en_rest_wait_val = EN_REST_WAIT_VAL;
+	if (!sc->en_few_wait_val)
+		sc->en_few_wait_val = EN_FEW_WAIT_VAL;
+	if (!sc->clk_dis_wait_val)
+		sc->clk_dis_wait_val = CLK_DIS_WAIT_VAL;
+
+	val = sc->en_rest_wait_val << EN_REST_WAIT_SHIFT |
+		sc->en_few_wait_val << EN_FEW_WAIT_SHIFT |
+		sc->clk_dis_wait_val << CLK_DIS_WAIT_SHIFT;
+
 	ret = regmap_update_bits(sc->regmap, sc->gdscr, mask, val);
 	if (ret)
 		return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/qcom/gdsc.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/qcom/gdsc.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2015, 2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015, 2017-2018, 2022, The Linux Foundation. All rights reserved.
  */
 
 #ifndef __QCOM_GDSC_H__
@@ -21,6 +21,9 @@
  * @cxcs: offsets of branch registers to toggle mem/periph bits in
  * @cxc_count: number of @cxcs
  * @pwrsts: Possible powerdomain power states
+ * @en_rest_wait_val: transition delay value for receiving enr ack signal
+ * @en_few_wait_val: transition delay value for receiving enf ack signal
+ * @clk_dis_wait_val: transition delay value for halting clock
  * @resets: ids of resets associated with this gdsc
  * @reset_count: number of @resets
  * @rcdev: reset controller
@@ -34,6 +37,9 @@
 	unsigned int			clamp_io_ctrl;
 	unsigned int			*cxcs;
 	unsigned int			cxc_count;
+	unsigned int			en_rest_wait_val;
+	unsigned int			en_few_wait_val;
+	unsigned int			clk_dis_wait_val;
 	const u8			pwrsts;
 /* Powerdomain allowable state bitfields */
 #define PWRSTS_OFF		BIT(0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/qcom/gpucc-sdm845.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/qcom/gpucc-sdm845.c
@@ -22,8 +22,6 @@
 #define CX_GMU_CBCR_SLEEP_SHIFT		4
 #define CX_GMU_CBCR_WAKE_MASK		0xf
 #define CX_GMU_CBCR_WAKE_SHIFT		8
-#define CLK_DIS_WAIT_SHIFT		12
-#define CLK_DIS_WAIT_MASK		(0xf << CLK_DIS_WAIT_SHIFT)
 
 enum {
 	P_BI_TCXO,
@@ -124,6 +122,7 @@
 static struct gdsc gpu_cx_gdsc = {
 	.gdscr = 0x106c,
 	.gds_hw_ctrl = 0x1540,
+	.clk_dis_wait_val = 0x8,
 	.pd = {
 		.name = "gpu_cx_gdsc",
 	},
@@ -221,10 +220,6 @@
 	value = 0xf << CX_GMU_CBCR_WAKE_SHIFT | 0xf << CX_GMU_CBCR_SLEEP_SHIFT;
 	regmap_update_bits(regmap, 0x1098, mask, value);
 
-	/* Configure clk_dis_wait for gpu_cx_gdsc */
-	regmap_update_bits(regmap, 0x106c, CLK_DIS_WAIT_MASK,
-						8 << CLK_DIS_WAIT_SHIFT);
-
 	return qcom_cc_really_probe(pdev, &gpu_cc_sdm845_desc, regmap);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/qcom/mmcc-apq8084.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/qcom/mmcc-apq8084.c
@@ -333,6 +333,7 @@
 	F(333430000, P_MMPLL1, 3.5, 0, 0),
 	F(400000000, P_MMPLL0, 2, 0, 0),
 	F(466800000, P_MMPLL1, 2.5, 0, 0),
+	{ }
 };
 
 static struct clk_rcg2 mmss_axi_clk_src = {
@@ -357,6 +358,7 @@
 	F(150000000, P_GPLL0, 4, 0, 0),
 	F(228570000, P_MMPLL0, 3.5, 0, 0),
 	F(320000000, P_MMPLL0, 2.5, 0, 0),
+	{ }
 };
 
 static struct clk_rcg2 ocmemnoc_clk_src = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/qcom/mmcc-msm8974.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/qcom/mmcc-msm8974.c
@@ -283,6 +283,7 @@
 	F(291750000, P_MMPLL1, 4, 0, 0),
 	F(400000000, P_MMPLL0, 2, 0, 0),
 	F(466800000, P_MMPLL1, 2.5, 0, 0),
+	{ }
 };
 
 static struct clk_rcg2 mmss_axi_clk_src = {
@@ -307,6 +308,7 @@
 	F(150000000, P_GPLL0, 4, 0, 0),
 	F(291750000, P_MMPLL1, 4, 0, 0),
 	F(400000000, P_MMPLL0, 2, 0, 0),
+	{ }
 };
 
 static struct clk_rcg2 ocmemnoc_clk_src = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/qcom/reset.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/qcom/reset.c
@@ -13,14 +13,16 @@
 
 static int qcom_reset(struct reset_controller_dev *rcdev, unsigned long id)
 {
+	struct qcom_reset_controller *rst = to_qcom_reset_controller(rcdev);
+
 	rcdev->ops->assert(rcdev, id);
-	udelay(1);
+	udelay(rst->reset_map[id].udelay ?: 1); /* use 1 us as default */
 	rcdev->ops->deassert(rcdev, id);
 	return 0;
 }
 
-static int
-qcom_reset_assert(struct reset_controller_dev *rcdev, unsigned long id)
+static int qcom_reset_set_assert(struct reset_controller_dev *rcdev,
+				 unsigned long id, bool assert)
 {
 	struct qcom_reset_controller *rst;
 	const struct qcom_reset_map *map;
@@ -28,23 +30,24 @@
 
 	rst = to_qcom_reset_controller(rcdev);
 	map = &rst->reset_map[id];
-	mask = BIT(map->bit);
+	mask = map->bitmask ? map->bitmask : BIT(map->bit);
+
+	regmap_update_bits(rst->regmap, map->reg, mask, assert ? mask : 0);
+
+	/* Read back the register to ensure write completion, ignore the value */
+	regmap_read(rst->regmap, map->reg, &mask);
 
-	return regmap_update_bits(rst->regmap, map->reg, mask, mask);
+	return 0;
 }
 
-static int
-qcom_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id)
+static int qcom_reset_assert(struct reset_controller_dev *rcdev, unsigned long id)
 {
-	struct qcom_reset_controller *rst;
-	const struct qcom_reset_map *map;
-	u32 mask;
-
-	rst = to_qcom_reset_controller(rcdev);
-	map = &rst->reset_map[id];
-	mask = BIT(map->bit);
+	return qcom_reset_set_assert(rcdev, id, true);
+}
 
-	return regmap_update_bits(rst->regmap, map->reg, mask, 0);
+static int qcom_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id)
+{
+	return qcom_reset_set_assert(rcdev, id, false);
 }
 
 const struct reset_control_ops qcom_reset_ops = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/qcom/reset.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/qcom/reset.h
@@ -11,6 +11,8 @@
 struct qcom_reset_map {
 	unsigned int reg;
 	u8 bit;
+	u8 udelay;
+	u32 bitmask;
 };
 
 struct regmap;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/renesas/r7s9210-cpg-mssr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/renesas/r7s9210-cpg-mssr.c
@@ -213,7 +213,7 @@
 	.cpg_clk_register = rza2_cpg_clk_register,
 
 	/* RZ/A2 has Standby Control Registers */
-	.stbyctrl = true,
+	.reg_layout = CLK_REG_LAYOUT_RZ_A,
 };
 
 static void __init r7s9210_cpg_mssr_early_init(struct device_node *np)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/renesas/r8a77995-cpg-mssr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/renesas/r8a77995-cpg-mssr.c
@@ -75,6 +75,7 @@
 	DEF_RATE(".oco",       CLK_OCO,            8 * 1000 * 1000),
 
 	/* Core Clock Outputs */
+	DEF_FIXED("za2",       R8A77995_CLK_ZA2,   CLK_PLL0D3,     2, 1),
 	DEF_FIXED("z2",        R8A77995_CLK_Z2,    CLK_PLL0D3,     1, 1),
 	DEF_FIXED("ztr",       R8A77995_CLK_ZTR,   CLK_PLL1,       6, 1),
 	DEF_FIXED("zt",        R8A77995_CLK_ZT,    CLK_PLL1,       4, 1),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/renesas/r9a06g032-clocks.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/renesas/r9a06g032-clocks.c
@@ -55,7 +55,7 @@
 			u16 sel, g1, r1, g2, r2;
 		} dual;
 	};
-} __packed;
+};
 
 #define I_GATE(_clk, _rst, _rdy, _midle, _scon, _mirack, _mistat) \
 	{ .gate = _clk, .reset = _rst, \
@@ -286,8 +286,8 @@
 		.name = "uart_group_012",
 		.type = K_BITSEL,
 		.source = 1 + R9A06G032_DIV_UART,
-		/* R9A06G032_SYSCTRL_REG_PWRCTRL_PG1_PR2 */
-		.dual.sel = ((0xec / 4) << 5) | 24,
+		/* R9A06G032_SYSCTRL_REG_PWRCTRL_PG0_0 */
+		.dual.sel = ((0x34 / 4) << 5) | 30,
 		.dual.group = 0,
 	},
 	{
@@ -295,8 +295,8 @@
 		.name = "uart_group_34567",
 		.type = K_BITSEL,
 		.source = 1 + R9A06G032_DIV_P2_PG,
-		/* R9A06G032_SYSCTRL_REG_PWRCTRL_PG0_0 */
-		.dual.sel = ((0x34 / 4) << 5) | 30,
+		/* R9A06G032_SYSCTRL_REG_PWRCTRL_PG1_PR2 */
+		.dual.sel = ((0xec / 4) << 5) | 24,
 		.dual.group = 1,
 	},
 	D_UGATE(CLK_UART0, "clk_uart0", UART_GROUP_012, 0, 0, 0x1b2, 0x1b3, 0x1b4, 0x1b5),
@@ -386,7 +386,7 @@
 	int error;
 	int index;
 
-	while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i,
+	while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i++,
 					   &clkspec)) {
 		if (clkspec.np != pd->dev.of_node)
 			continue;
@@ -399,7 +399,6 @@
 			if (error)
 				return error;
 		}
-		i++;
 	}
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/renesas/rcar-gen3-cpg.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/renesas/rcar-gen3-cpg.c
@@ -464,7 +464,8 @@
 
 	clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
 				     &rpc->div.hw,  &clk_divider_ops,
-				     &rpc->gate.hw, &clk_gate_ops, 0);
+				     &rpc->gate.hw, &clk_gate_ops,
+				     CLK_SET_RATE_PARENT);
 	if (IS_ERR(clk)) {
 		kfree(rpc);
 		return clk;
@@ -500,7 +501,8 @@
 
 	clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
 				     &rpcd2->fixed.hw, &clk_fixed_factor_ops,
-				     &rpcd2->gate.hw, &clk_gate_ops, 0);
+				     &rpcd2->gate.hw, &clk_gate_ops,
+				     CLK_SET_RATE_PARENT);
 	if (IS_ERR(clk))
 		kfree(rpcd2);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/renesas/renesas-cpg-mssr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/renesas/renesas-cpg-mssr.c
@@ -111,12 +111,12 @@
  * @rcdev: Optional reset controller entity
  * @dev: CPG/MSSR device
  * @base: CPG/MSSR register block base address
+ * @reg_layout: CPG/MSSR register layout
  * @rmw_lock: protects RMW register accesses
  * @np: Device node in DT for this CPG/MSSR module
  * @num_core_clks: Number of Core Clocks in clks[]
  * @num_mod_clks: Number of Module Clocks in clks[]
  * @last_dt_core_clk: ID of the last Core Clock exported to DT
- * @stbyctrl: This device has Standby Control Registers
  * @notifiers: Notifier chain to save/restore clock state for system resume
  * @smstpcr_saved[].mask: Mask of SMSTPCR[] bits under our control
  * @smstpcr_saved[].val: Saved values of SMSTPCR[]
@@ -128,13 +128,13 @@
 #endif
 	struct device *dev;
 	void __iomem *base;
+	enum clk_reg_layout reg_layout;
 	spinlock_t rmw_lock;
 	struct device_node *np;
 
 	unsigned int num_core_clks;
 	unsigned int num_mod_clks;
 	unsigned int last_dt_core_clk;
-	bool stbyctrl;
 
 	struct raw_notifier_head notifiers;
 	struct {
@@ -177,7 +177,7 @@
 		enable ? "ON" : "OFF");
 	spin_lock_irqsave(&priv->rmw_lock, flags);
 
-	if (priv->stbyctrl) {
+	if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A) {
 		value = readb(priv->base + STBCR(reg));
 		if (enable)
 			value &= ~bitmask;
@@ -199,7 +199,7 @@
 
 	spin_unlock_irqrestore(&priv->rmw_lock, flags);
 
-	if (!enable || priv->stbyctrl)
+	if (!enable || priv->reg_layout == CLK_REG_LAYOUT_RZ_A)
 		return 0;
 
 	for (i = 1000; i > 0; --i) {
@@ -233,7 +233,7 @@
 	struct cpg_mssr_priv *priv = clock->priv;
 	u32 value;
 
-	if (priv->stbyctrl)
+	if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A)
 		value = readb(priv->base + STBCR(clock->index / 32));
 	else
 		value = readl(priv->base + MSTPSR(clock->index / 32));
@@ -272,7 +272,7 @@
 
 	case CPG_MOD:
 		type = "module";
-		if (priv->stbyctrl) {
+		if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A) {
 			idx = MOD_CLK_PACK_10(clkidx);
 			range_check = 7 - (clkidx % 10);
 		} else {
@@ -801,6 +801,8 @@
 	for (reg = 0; reg < ARRAY_SIZE(priv->smstpcr_saved); reg++) {
 		if (priv->smstpcr_saved[reg].mask)
 			priv->smstpcr_saved[reg].val =
+				priv->reg_layout == CLK_REG_LAYOUT_RZ_A ?
+				readb(priv->base + STBCR(reg)) :
 				readl(priv->base + SMSTPCR(reg));
 	}
 
@@ -829,7 +831,7 @@
 		if (!mask)
 			continue;
 
-		if (priv->stbyctrl)
+		if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A)
 			oldval = readb(priv->base + STBCR(reg));
 		else
 			oldval = readl(priv->base + SMSTPCR(reg));
@@ -838,7 +840,7 @@
 		if (newval == oldval)
 			continue;
 
-		if (priv->stbyctrl) {
+		if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A) {
 			writeb(newval, priv->base + STBCR(reg));
 			/* dummy read to ensure write has completed */
 			readb(priv->base + STBCR(reg));
@@ -860,8 +862,8 @@
 		}
 
 		if (!i)
-			dev_warn(dev, "Failed to enable SMSTP %p[0x%x]\n",
-				 priv->base + SMSTPCR(reg), oldval & mask);
+			dev_warn(dev, "Failed to enable SMSTP%u[0x%x]\n", reg,
+				 oldval & mask);
 	}
 
 	return 0;
@@ -905,12 +907,11 @@
 		goto out_err;
 	}
 
-	cpg_mssr_priv = priv;
 	priv->num_core_clks = info->num_total_core_clks;
 	priv->num_mod_clks = info->num_hw_mod_clks;
 	priv->last_dt_core_clk = info->last_dt_core_clk;
 	RAW_INIT_NOTIFIER_HEAD(&priv->notifiers);
-	priv->stbyctrl = info->stbyctrl;
+	priv->reg_layout = info->reg_layout;
 
 	for (i = 0; i < nclks; i++)
 		priv->clks[i] = ERR_PTR(-ENOENT);
@@ -919,6 +920,8 @@
 	if (error)
 		goto out_err;
 
+	cpg_mssr_priv = priv;
+
 	return 0;
 
 out_err:
@@ -988,7 +991,7 @@
 		return error;
 
 	/* Reset Controller not supported for Standby Control SoCs */
-	if (info->stbyctrl)
+	if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A)
 		return 0;
 
 	error = cpg_mssr_reset_controller_register(priv);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/renesas/renesas-cpg-mssr.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/renesas/renesas-cpg-mssr.h
@@ -85,6 +85,11 @@
 
 struct device_node;
 
+enum clk_reg_layout {
+	CLK_REG_LAYOUT_RCAR_GEN2_AND_GEN3 = 0,
+	CLK_REG_LAYOUT_RZ_A,
+};
+
     /**
      * SoC-specific CPG/MSSR Description
      *
@@ -105,6 +110,7 @@
      * @crit_mod_clks: Array with Module Clock IDs of critical clocks that
      *                 should not be disabled without a knowledgeable driver
      * @num_crit_mod_clks: Number of entries in crit_mod_clks[]
+     * @reg_layout: CPG/MSSR register layout from enum clk_reg_layout
      *
      * @core_pm_clks: Array with IDs of Core Clocks that are suitable for Power
      *                Management, in addition to Module Clocks
@@ -112,10 +118,6 @@
      *
      * @init: Optional callback to perform SoC-specific initialization
      * @cpg_clk_register: Optional callback to handle special Core Clock types
-     *
-     * @stbyctrl: This device has Standby Control Registers which are 8-bits
-     *            wide, no status registers (MSTPSR) and have different address
-     *            offsets.
      */
 
 struct cpg_mssr_info {
@@ -130,7 +132,7 @@
 	unsigned int num_core_clks;
 	unsigned int last_dt_core_clk;
 	unsigned int num_total_core_clks;
-	bool stbyctrl;
+	enum clk_reg_layout reg_layout;
 
 	/* Module Clocks */
 	const struct mssr_mod_clk *mod_clks;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/rockchip/clk-half-divider.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/rockchip/clk-half-divider.c
@@ -167,7 +167,7 @@
 					  unsigned long flags,
 					  spinlock_t *lock)
 {
-	struct clk *clk;
+	struct clk *clk = ERR_PTR(-ENOMEM);
 	struct clk_mux *mux = NULL;
 	struct clk_gate *gate = NULL;
 	struct clk_divider *div = NULL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/rockchip/clk-pll.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/rockchip/clk-pll.c
@@ -963,6 +963,7 @@
 	return mux_clk;
 
 err_pll:
+	kfree(pll->rate_table);
 	clk_unregister(mux_clk);
 	mux_clk = pll_clk;
 err_mux:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/rockchip/clk-rk3128.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/rockchip/clk-rk3128.c
@@ -489,7 +489,7 @@
 	GATE(HCLK_I2S_2CH, "hclk_i2s_2ch", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 2, GFLAGS),
 	GATE(0, "hclk_usb_peri", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 13, GFLAGS),
 	GATE(HCLK_HOST2, "hclk_host2", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 3, GFLAGS),
-	GATE(HCLK_OTG, "hclk_otg", "hclk_peri", 0, RK2928_CLKGATE_CON(3), 13, GFLAGS),
+	GATE(HCLK_OTG, "hclk_otg", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 13, GFLAGS),
 	GATE(0, "hclk_peri_ahb", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 14, GFLAGS),
 	GATE(HCLK_SPDIF, "hclk_spdif", "hclk_peri", 0, RK2928_CLKGATE_CON(10), 9, GFLAGS),
 	GATE(HCLK_TSP, "hclk_tsp", "hclk_peri", 0, RK2928_CLKGATE_CON(10), 12, GFLAGS),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/rockchip/clk-rk3188.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/rockchip/clk-rk3188.c
@@ -751,6 +751,7 @@
 	"pclk_peri",
 	"hclk_cpubus",
 	"hclk_vio_bus",
+	"sclk_mac_lbtest",
 };
 
 static struct rockchip_clk_provider *__init rk3188_common_clk_init(struct device_node *np)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/rockchip/clk-rk3228.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/rockchip/clk-rk3228.c
@@ -137,7 +137,7 @@
 PNAME(mux_hdmiphy_p)		= { "hdmiphy_phy", "xin24m" };
 PNAME(mux_aclk_cpu_src_p)	= { "cpll_aclk_cpu", "gpll_aclk_cpu", "hdmiphy_aclk_cpu" };
 
-PNAME(mux_pll_src_4plls_p)	= { "cpll", "gpll", "hdmiphy" "usb480m" };
+PNAME(mux_pll_src_4plls_p)	= { "cpll", "gpll", "hdmiphy", "usb480m" };
 PNAME(mux_pll_src_3plls_p)	= { "cpll", "gpll", "hdmiphy" };
 PNAME(mux_pll_src_2plls_p)	= { "cpll", "gpll" };
 PNAME(mux_sclk_hdmi_cec_p)	= { "cpll", "gpll", "xin24m" };
@@ -156,8 +156,6 @@
 PNAME(mux_i2s2_p)		= { "i2s2_src", "i2s2_frac", "xin12m" };
 PNAME(mux_sclk_spdif_p)		= { "sclk_spdif_src", "spdif_frac", "xin12m" };
 
-PNAME(mux_aclk_gpu_pre_p)	= { "cpll_gpu", "gpll_gpu", "hdmiphy_gpu", "usb480m_gpu" };
-
 PNAME(mux_uart0_p)		= { "uart0_src", "uart0_frac", "xin24m" };
 PNAME(mux_uart1_p)		= { "uart1_src", "uart1_frac", "xin24m" };
 PNAME(mux_uart2_p)		= { "uart2_src", "uart2_frac", "xin24m" };
@@ -410,7 +408,7 @@
 			RK2928_CLKSEL_CON(29), 0, 3, DFLAGS),
 	DIV(0, "sclk_vop_pre", "sclk_vop_src", 0,
 			RK2928_CLKSEL_CON(27), 8, 8, DFLAGS),
-	MUX(DCLK_VOP, "dclk_vop", mux_dclk_vop_p, 0,
+	MUX(DCLK_VOP, "dclk_vop", mux_dclk_vop_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
 			RK2928_CLKSEL_CON(27), 1, 1, MFLAGS),
 
 	FACTOR(0, "xin12m", "xin24m", 0, 1, 2),
@@ -468,16 +466,9 @@
 			RK2928_CLKSEL_CON(24), 6, 10, DFLAGS,
 			RK2928_CLKGATE_CON(2), 8, GFLAGS),
 
-	GATE(0, "cpll_gpu", "cpll", 0,
-			RK2928_CLKGATE_CON(3), 13, GFLAGS),
-	GATE(0, "gpll_gpu", "gpll", 0,
-			RK2928_CLKGATE_CON(3), 13, GFLAGS),
-	GATE(0, "hdmiphy_gpu", "hdmiphy", 0,
-			RK2928_CLKGATE_CON(3), 13, GFLAGS),
-	GATE(0, "usb480m_gpu", "usb480m", 0,
+	COMPOSITE(0, "aclk_gpu_pre", mux_pll_src_4plls_p, 0,
+			RK2928_CLKSEL_CON(34), 5, 2, MFLAGS, 0, 5, DFLAGS,
 			RK2928_CLKGATE_CON(3), 13, GFLAGS),
-	COMPOSITE_NOGATE(0, "aclk_gpu_pre", mux_aclk_gpu_pre_p, 0,
-			RK2928_CLKSEL_CON(34), 5, 2, MFLAGS, 0, 5, DFLAGS),
 
 	COMPOSITE(SCLK_SPI0, "sclk_spi0", mux_pll_src_2plls_p, 0,
 			RK2928_CLKSEL_CON(25), 8, 1, MFLAGS, 0, 7, DFLAGS,
@@ -582,8 +573,8 @@
 	GATE(0, "pclk_peri_noc", "pclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(12), 2, GFLAGS),
 
 	/* PD_GPU */
-	GATE(ACLK_GPU, "aclk_gpu", "aclk_gpu_pre", 0, RK2928_CLKGATE_CON(13), 14, GFLAGS),
-	GATE(0, "aclk_gpu_noc", "aclk_gpu_pre", 0, RK2928_CLKGATE_CON(13), 15, GFLAGS),
+	GATE(ACLK_GPU, "aclk_gpu", "aclk_gpu_pre", 0, RK2928_CLKGATE_CON(7), 14, GFLAGS),
+	GATE(0, "aclk_gpu_noc", "aclk_gpu_pre", 0, RK2928_CLKGATE_CON(7), 15, GFLAGS),
 
 	/* PD_BUS */
 	GATE(0, "sclk_initmem_mbist", "aclk_cpu", 0, RK2928_CLKGATE_CON(8), 1, GFLAGS),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/rockchip/clk-rk3328.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/rockchip/clk-rk3328.c
@@ -200,7 +200,7 @@
 				    "gpll_peri",
 				    "hdmiphy_peri" };
 PNAME(mux_ref_usb3otg_src_p)	= { "xin24m",
-				    "clk_usb3otg_ref" };
+				    "clk_ref_usb3otg_src" };
 PNAME(mux_xin24m_32k_p)		= { "xin24m",
 				    "clk_rtc32k" };
 PNAME(mux_mac2io_src_p)		= { "clk_mac2io_src",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/rockchip/clk-rk3399.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/rockchip/clk-rk3399.c
@@ -1259,7 +1259,7 @@
 			RK3399_CLKSEL_CON(56), 6, 2, MFLAGS,
 			RK3399_CLKGATE_CON(10), 7, GFLAGS),
 
-	COMPOSITE_NOGATE(SCLK_CIF_OUT, "clk_cifout", mux_clk_cif_p, 0,
+	COMPOSITE_NOGATE(SCLK_CIF_OUT, "clk_cifout", mux_clk_cif_p, CLK_SET_RATE_PARENT,
 			 RK3399_CLKSEL_CON(56), 5, 1, MFLAGS, 0, 5, DFLAGS),
 
 	/* gic */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/rockchip/clk.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/rockchip/clk.c
@@ -439,12 +439,13 @@
 				      struct rockchip_clk_branch *list,
 				      unsigned int nr_clk)
 {
-	struct clk *clk = NULL;
+	struct clk *clk;
 	unsigned int idx;
 	unsigned long flags;
 
 	for (idx = 0; idx < nr_clk; idx++, list++) {
 		flags = list->flags;
+		clk = NULL;
 
 		/* catch simple muxes */
 		switch (list->branch_type) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/samsung/clk-exynos4.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/samsung/clk-exynos4.c
@@ -927,7 +927,7 @@
 	GATE(CLK_PCIE, "pcie", "aclk133", GATE_IP_FSYS, 14, 0, 0),
 	GATE(CLK_SMMU_PCIE, "smmu_pcie", "aclk133", GATE_IP_FSYS, 18, 0, 0),
 	GATE(CLK_MODEMIF, "modemif", "aclk100", GATE_IP_PERIL, 28, 0, 0),
-	GATE(CLK_CHIPID, "chipid", "aclk100", E4210_GATE_IP_PERIR, 0, 0, 0),
+	GATE(CLK_CHIPID, "chipid", "aclk100", E4210_GATE_IP_PERIR, 0, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_SYSREG, "sysreg", "aclk100", E4210_GATE_IP_PERIR, 0,
 			CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_HDMI_CEC, "hdmi_cec", "aclk100", E4210_GATE_IP_PERIR, 11, 0,
@@ -969,7 +969,7 @@
 		0),
 	GATE(CLK_TSADC, "tsadc", "aclk133", E4X12_GATE_BUS_FSYS1, 16, 0, 0),
 	GATE(CLK_MIPI_HSI, "mipi_hsi", "aclk133", GATE_IP_FSYS, 10, 0, 0),
-	GATE(CLK_CHIPID, "chipid", "aclk100", E4X12_GATE_IP_PERIR, 0, 0, 0),
+	GATE(CLK_CHIPID, "chipid", "aclk100", E4X12_GATE_IP_PERIR, 0, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_SYSREG, "sysreg", "aclk100", E4X12_GATE_IP_PERIR, 1,
 			CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_HDMI_CEC, "hdmi_cec", "aclk100", E4X12_GATE_IP_PERIR, 11, 0,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/samsung/clk-exynos5420.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/samsung/clk-exynos5420.c
@@ -12,6 +12,7 @@
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/clk.h>
 
 #include "clk.h"
 #include "clk-cpu.h"
@@ -165,6 +166,8 @@
 	GATE_BUS_CPU,
 	GATE_SCLK_CPU,
 	CLKOUT_CMU_CPU,
+	APLL_CON0,
+	KPLL_CON0,
 	CPLL_CON0,
 	DPLL_CON0,
 	EPLL_CON0,
@@ -537,7 +540,7 @@
 
 static const struct samsung_gate_clock exynos5800_gate_clks[] __initconst = {
 	GATE(CLK_ACLK550_CAM, "aclk550_cam", "mout_user_aclk550_cam",
-				GATE_BUS_TOP, 24, 0, 0),
+				GATE_BUS_TOP, 24, CLK_IS_CRITICAL, 0),
 	GATE(CLK_ACLK432_SCALER, "aclk432_scaler", "mout_user_aclk432_scaler",
 				GATE_BUS_TOP, 27, CLK_IS_CRITICAL, 0),
 };
@@ -937,25 +940,25 @@
 	GATE(0, "aclk300_jpeg", "mout_user_aclk300_jpeg",
 			GATE_BUS_TOP, 4, CLK_IGNORE_UNUSED, 0),
 	GATE(0, "aclk333_432_isp0", "mout_user_aclk333_432_isp0",
-			GATE_BUS_TOP, 5, 0, 0),
+			GATE_BUS_TOP, 5, CLK_IS_CRITICAL, 0),
 	GATE(0, "aclk300_gscl", "mout_user_aclk300_gscl",
 			GATE_BUS_TOP, 6, CLK_IS_CRITICAL, 0),
 	GATE(0, "aclk333_432_gscl", "mout_user_aclk333_432_gscl",
 			GATE_BUS_TOP, 7, CLK_IGNORE_UNUSED, 0),
 	GATE(0, "aclk333_432_isp", "mout_user_aclk333_432_isp",
-			GATE_BUS_TOP, 8, 0, 0),
+			GATE_BUS_TOP, 8, CLK_IS_CRITICAL, 0),
 	GATE(CLK_PCLK66_GPIO, "pclk66_gpio", "mout_user_pclk66_gpio",
 			GATE_BUS_TOP, 9, CLK_IGNORE_UNUSED, 0),
 	GATE(0, "aclk66_psgen", "mout_user_aclk66_psgen",
 			GATE_BUS_TOP, 10, CLK_IGNORE_UNUSED, 0),
 	GATE(0, "aclk266_isp", "mout_user_aclk266_isp",
-			GATE_BUS_TOP, 13, 0, 0),
+			GATE_BUS_TOP, 13, CLK_IS_CRITICAL, 0),
 	GATE(0, "aclk166", "mout_user_aclk166",
 			GATE_BUS_TOP, 14, CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_ACLK333, "aclk333", "mout_user_aclk333",
 			GATE_BUS_TOP, 15, CLK_IS_CRITICAL, 0),
 	GATE(0, "aclk400_isp", "mout_user_aclk400_isp",
-			GATE_BUS_TOP, 16, 0, 0),
+			GATE_BUS_TOP, 16, CLK_IS_CRITICAL, 0),
 	GATE(0, "aclk400_mscl", "mout_user_aclk400_mscl",
 			GATE_BUS_TOP, 17, CLK_IS_CRITICAL, 0),
 	GATE(0, "aclk200_disp1", "mout_user_aclk200_disp1",
@@ -1155,8 +1158,10 @@
 			GATE_IP_GSCL1, 3, 0, 0),
 	GATE(CLK_SMMU_FIMCL1, "smmu_fimcl1", "dout_gscl_blk_333",
 			GATE_IP_GSCL1, 4, 0, 0),
-	GATE(CLK_GSCL_WA, "gscl_wa", "sclk_gscl_wa", GATE_IP_GSCL1, 12, 0, 0),
-	GATE(CLK_GSCL_WB, "gscl_wb", "sclk_gscl_wb", GATE_IP_GSCL1, 13, 0, 0),
+	GATE(CLK_GSCL_WA, "gscl_wa", "sclk_gscl_wa", GATE_IP_GSCL1, 12,
+			CLK_IS_CRITICAL, 0),
+	GATE(CLK_GSCL_WB, "gscl_wb", "sclk_gscl_wb", GATE_IP_GSCL1, 13,
+			CLK_IS_CRITICAL, 0),
 	GATE(CLK_SMMU_FIMCL3, "smmu_fimcl3,", "dout_gscl_blk_333",
 			GATE_IP_GSCL1, 16, 0, 0),
 	GATE(CLK_FIMC_LITE3, "fimc_lite3", "aclk333_432_gscl",
@@ -1628,6 +1633,13 @@
 				     exynos5x_subcmus);
 	}
 
+	/*
+	 * Keep top part of G3D clock path enabled permanently to ensure
+	 * that the internal busses get their clock regardless of the
+	 * main G3D clock enablement status.
+	 */
+	clk_prepare_enable(__clk_lookup("mout_sw_aclk_g3d"));
+
 	samsung_clk_of_add_provider(np, ctx);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/samsung/clk-exynos5433.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/samsung/clk-exynos5433.c
@@ -1706,7 +1706,8 @@
 	GATE(CLK_SCLK_PCM1, "sclk_pcm1", "sclk_pcm1_peric",
 			ENABLE_SCLK_PERIC, 7, CLK_SET_RATE_PARENT, 0),
 	GATE(CLK_SCLK_I2S1, "sclk_i2s1", "sclk_i2s1_peric",
-			ENABLE_SCLK_PERIC, 6, CLK_SET_RATE_PARENT, 0),
+			ENABLE_SCLK_PERIC, 6,
+			CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 0),
 	GATE(CLK_SCLK_SPI2, "sclk_spi2", "sclk_spi2_peric", ENABLE_SCLK_PERIC,
 			5, CLK_SET_RATE_PARENT, 0),
 	GATE(CLK_SCLK_SPI1, "sclk_spi1", "sclk_spi1_peric", ENABLE_SCLK_PERIC,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/samsung/clk-exynos7.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/samsung/clk-exynos7.c
@@ -537,8 +537,13 @@
 	GATE(CLK_ACLK_FSYS0_200, "aclk_fsys0_200", "dout_aclk_fsys0_200",
 		ENABLE_ACLK_TOP13, 28, CLK_SET_RATE_PARENT |
 		CLK_IS_CRITICAL, 0),
+	/*
+	 * This clock is required for the CMU_FSYS1 registers access, keep it
+	 * enabled permanently until proper runtime PM support is added.
+	 */
 	GATE(CLK_ACLK_FSYS1_200, "aclk_fsys1_200", "dout_aclk_fsys1_200",
-		ENABLE_ACLK_TOP13, 24, CLK_SET_RATE_PARENT, 0),
+		ENABLE_ACLK_TOP13, 24, CLK_SET_RATE_PARENT |
+		CLK_IS_CRITICAL, 0),
 
 	GATE(CLK_SCLK_PHY_FSYS1_26M, "sclk_phy_fsys1_26m",
 		"dout_sclk_phy_fsys1_26m", ENABLE_SCLK_TOP1_FSYS11,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/samsung/clk-pll.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/samsung/clk-pll.c
@@ -1390,6 +1390,7 @@
 	if (ret) {
 		pr_err("%s: failed to register pll clock %s : %d\n",
 			__func__, pll_clk->name, ret);
+		kfree(pll->rate_table);
 		kfree(pll);
 		return;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/si5324.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/si5324.h
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Si5324 clock generator platform data
+ *
+ * Copyright (C) 2017-2018 Xilinx, Inc.
+ */
+
+#ifndef __LINUX_PLATFORM_DATA_SI5324_H__
+#define __LINUX_PLATFORM_DATA_SI5324_H__
+
+/**
+ * enum si5324_pll_src - Si5324 pll clock source
+ *
+ * @SI5324_PLL_SRC_DEFAULT:	Default, do not change eeprom config
+ * @SI5324_PLL_SRC_XTAL:	Pll source clock is XTAL input
+ * @SI5324_PLL_SRC_CLKIN1:	Pll source clock is CLKIN1 input
+ * @SI5324_PLL_SRC_CLKIN2:	Pll source clock is CLKIN2 input
+ *
+ * Defines enums for clock sources.
+ */
+enum si5324_pll_src {
+	SI5324_PLL_SRC_XTAL = 0,
+	SI5324_PLL_SRC_CLKIN1 = 1,
+	SI5324_PLL_SRC_CLKIN2 = 2,
+};
+
+/**
+ * enum si5324_drive_strength - Si5324 clock output drive strength
+ *
+ * @SI5324_DRIVE_DEFAULT:	Default, do not change eeprom config
+ * @SI5324_DRIVE_2MA:		2mA clock output drive strength
+ * @SI5324_DRIVE_4MA:		4mA clock output drive strength
+ * @SI5324_DRIVE_6MA:		6mA clock output drive strength
+ * @SI5324_DRIVE_8MA:		8mA clock output drive strength
+ *
+ * Defines enums for drive strength
+ */
+enum si5324_drive_strength {
+	SI5324_DRIVE_DEFAULT = 0,
+	SI5324_DRIVE_2MA = 2,
+	SI5324_DRIVE_4MA = 4,
+	SI5324_DRIVE_6MA = 6,
+	SI5324_DRIVE_8MA = 8,
+};
+
+/**
+ * struct si5324_clkout_config - Si5324 clock output configuration
+ *
+ * @drive:	output drive strength
+ * @rate:	clkout rate
+ */
+struct si5324_clkout_config {
+	enum si5324_drive_strength drive;
+	unsigned long rate;
+};
+
+/**
+ * struct si5324_platform_data - Platform data for the Si5324 clock driver
+ *
+ * @pll_src:	Pll source clock setting
+ * @clkout:	Array of clkout configuration
+ */
+struct si5324_platform_data {
+	enum si5324_pll_src pll_src;
+	struct si5324_clkout_config clkout[2];
+};
+
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/si5324drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/si5324drv.c
@@ -0,0 +1,382 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Si5324 clock driver
+ *
+ * Copyright (C) 2017-2018 Xilinx, Inc.
+ *
+ * Author:	Venkateshwar Rao G <vgannava.xilinx.com>
+ *		Leon Woestenberg <leon@sidebranch.com>
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include "si5324drv.h"
+
+/**
+ * si5324_rate_approx - Find closest rational approximation N2_LS/N3 fraction.
+ *
+ * @f:		Holds the N2_LS/N3 fraction in 36.28 fixed point notation.
+ * @md:		Holds the maximum denominator (N3) value allowed.
+ * @num:	Store the numinator (N2_LS) found.
+ * @denom:	Store the denominator (N3) found.
+ *
+ * This function finds the closest rational approximation.
+ * It allows only n/1 solution and as a part of the calculation
+ * multiply fraction until no digits after the decimal point and
+ * continued fraction and check denominator at each step.
+ */
+void si5324_rate_approx(u64 f, u64 md, u32 *num, u32 *denom)
+{
+	u64 a, h[3] = { 0, 1, 0 }, k[3] = { 1, 0, 0 };
+	u64 x, d, m, n = 1;
+	int i = 0;
+
+	if (md <= 1) {
+		*denom = 1;
+		*num = (u32)(f >> 28);
+		return;
+	}
+
+	n <<= 28;
+	for (i = 0; i < 28; i++) {
+		if ((f & 0x1) == 0) {
+			n >>= 1;
+			f >>= 1;
+		} else {
+			break;
+		}
+	}
+	d = f;
+
+	for (i = 0; i < 64; i++) {
+		a = n ? (div64_u64(d, n)) : 0;
+		if (i && !a)
+			break;
+		x = d;
+		d = n;
+		div64_u64_rem(x, n, &m);
+		n = m;
+		x = a;
+		if (k[1] * a + k[0] >= md) {
+			x = div64_u64((md - k[0]), k[1]);
+			if (x * 2 >= a || k[1] >= md)
+				i = 65;
+			else
+				break;
+		}
+		h[2] = x * h[1] + h[0];
+		h[0] = h[1];
+		h[1] = h[2];
+		k[2] = x * k[1] + k[0];
+		k[0] = k[1];
+		k[1] = k[2];
+	}
+
+	*denom = (u32)k[1];
+	*num = (u32)h[1];
+}
+
+/**
+ * si5324_find_n2ls - Search through the possible settings for the N2_LS.
+ *
+ * @settings:	Holds the settings up till now.
+ *
+ * This function finds the best setting for N2_LS and N3n with the values
+ * for N1_HS, NCn_LS, and N2_HS.
+ *
+ * Return:	1 when the best possible result has been found, 0 on failure.
+ */
+static int si5324_find_n2ls(struct si5324_settingst *settings)
+{
+	u32 result = 0;
+	u64 f3_actual;
+	u64 fosc_actual;
+	u64 fout_actual;
+	u64 delta_fout;
+	u64 n2_ls_div_n3, mult_res;
+	u32 mult;
+
+	n2_ls_div_n3 = div64_u64(div64_u64(div64_u64(settings->fosc,
+			(settings->fin >> SI5324_FIN_FOUT_SHIFT)),
+			(u64)settings->n2_hs), (u64)2);
+
+	si5324_rate_approx(n2_ls_div_n3, settings->n31_max, &settings->n2_ls,
+				&settings->n31);
+	settings->n2_ls *= 2;
+
+	if (settings->n2_ls < settings->n2_ls_min) {
+		mult = div64_u64(settings->n2_ls_min, settings->n2_ls);
+		div64_u64_rem(settings->n2_ls_min, settings->n2_ls, &mult_res);
+		mult = mult_res ? mult + 1 : mult;
+		settings->n2_ls *= mult;
+		settings->n31 *= mult;
+	}
+
+	if (settings->n31 < settings->n31_min) {
+		mult = div64_u64(settings->n31_min, settings->n31);
+		div64_u64_rem(settings->n31_min, settings->n31, &mult_res);
+		mult = mult_res ? mult + 1 : mult;
+		settings->n2_ls *= mult;
+		settings->n31 *= mult;
+	}
+	pr_debug("Trying N2_LS = %d N3 = %d.\n", settings->n2_ls,
+		 settings->n31);
+
+	if (settings->n2_ls < settings->n2_ls_min ||
+	    settings->n2_ls > settings->n2_ls_max) {
+		pr_info("N2_LS out of range.\n");
+	} else if ((settings->n31 < settings->n31_min) ||
+		   (settings->n31 > settings->n31_max)) {
+		pr_info("N3 out of range.\n");
+	} else {
+		f3_actual = div64_u64(settings->fin, settings->n31);
+		fosc_actual = f3_actual * settings->n2_hs * settings->n2_ls;
+		fout_actual = div64_u64(fosc_actual,
+					(settings->n1_hs * settings->nc1_ls));
+		delta_fout = fout_actual - settings->fout;
+
+		if ((f3_actual < ((u64)SI5324_F3_MIN) <<
+			SI5324_FIN_FOUT_SHIFT) ||
+			(f3_actual > ((u64)SI5324_F3_MAX) <<
+			SI5324_FIN_FOUT_SHIFT)) {
+			pr_debug("F3 frequency out of range.\n");
+		} else if ((fosc_actual < ((u64)SI5324_FOSC_MIN) <<
+				SI5324_FIN_FOUT_SHIFT) ||
+				(fosc_actual > ((u64)SI5324_FOSC_MAX) <<
+				SI5324_FIN_FOUT_SHIFT)) {
+			pr_debug("Fosc frequency out of range.\n");
+		} else if ((fout_actual < ((u64)SI5324_FOUT_MIN) <<
+				SI5324_FIN_FOUT_SHIFT) ||
+				(fout_actual > ((u64)SI5324_FOUT_MAX) <<
+				SI5324_FIN_FOUT_SHIFT)) {
+			pr_debug("Fout frequency out of range.\n");
+		} else {
+			pr_debug("Found solution: fout = %dHz delta = %dHz.\n",
+				 (u32)(fout_actual >> SI5324_FIN_FOUT_SHIFT),
+				 (u32)(delta_fout >> SI5324_FIN_FOUT_SHIFT));
+			pr_debug("fosc = %dkHz f3 = %dHz.\n",
+				 (u32)((fosc_actual >> SI5324_FIN_FOUT_SHIFT) /
+				       1000),
+				 (u32)(f3_actual >> SI5324_FIN_FOUT_SHIFT));
+
+			if (((u64)abs(delta_fout)) <
+				settings->best_delta_fout) {
+				settings->best_n1_hs = settings->n1_hs;
+				settings->best_nc1_ls = settings->nc1_ls;
+				settings->best_n2_hs = settings->n2_hs;
+				settings->best_n2_ls = settings->n2_ls;
+				settings->best_n3 = settings->n31;
+				settings->best_fout = fout_actual;
+				settings->best_delta_fout = abs(delta_fout);
+				if (delta_fout == 0)
+					result = 1;
+			}
+		}
+	}
+	return result;
+}
+
+/**
+ * si5324_find_n2 - Find a valid setting for N2_HS and N2_LS.
+ *
+ * @settings:	Holds the settings up till now.
+ *
+ * This function finds a valid settings for N2_HS and N2_LS. Iterates over
+ * all possibilities of N2_HS and then performs a binary search over the
+ * N2_LS values.
+ *
+ * Return:	1 when the best possible result has been found.
+ */
+static int si5324_find_n2(struct si5324_settingst *settings)
+{
+	u32 result = 0;
+
+	for (settings->n2_hs = SI5324_N2_HS_MAX; settings->n2_hs >=
+		SI5324_N2_HS_MIN; settings->n2_hs--) {
+		pr_debug("Trying N2_HS = %d.\n", settings->n2_hs);
+		settings->n2_ls_min = (u32)(div64_u64(settings->fosc,
+					((u64)(SI5324_F3_MAX * settings->n2_hs)
+						<< SI5324_FIN_FOUT_SHIFT)));
+
+		if (settings->n2_ls_min < SI5324_N2_LS_MIN)
+			settings->n2_ls_min = SI5324_N2_LS_MIN;
+
+		settings->n2_ls_max = (u32)(div64_u64(settings->fosc,
+					((u64)(SI5324_F3_MIN *
+					settings->n2_hs) <<
+					SI5324_FIN_FOUT_SHIFT)));
+		if (settings->n2_ls_max > SI5324_N2_LS_MAX)
+			settings->n2_ls_max = SI5324_N2_LS_MAX;
+
+		result = si5324_find_n2ls(settings);
+		if (result)
+			break;
+	}
+	return result;
+}
+
+/**
+ * si5324_calc_ncls_limits - Calculates the valid range for NCn_LS.
+ *
+ * @settings:	Holds the input and output frequencies and the setting
+ * for N1_HS.
+ *
+ * This function calculates the valid range for NCn_LS with the value
+ * for the output frequency and N1_HS already set in settings.
+ *
+ * Return:	-1 when there are no valid settings, 0 otherwise.
+ */
+int si5324_calc_ncls_limits(struct si5324_settingst *settings)
+{
+	settings->nc1_ls_min = div64_u64(settings->n1_hs_min,
+					 settings->n1_hs);
+
+	if (settings->nc1_ls_min < SI5324_NC_LS_MIN)
+		settings->nc1_ls_min = SI5324_NC_LS_MIN;
+	if (settings->nc1_ls_min > 1 &&	(settings->nc1_ls_min & 0x1) == 1)
+		settings->nc1_ls_min++;
+	settings->nc1_ls_max = div64_u64(settings->n1_hs_max, settings->n1_hs);
+
+	if (settings->nc1_ls_max > SI5324_NC_LS_MAX)
+		settings->nc1_ls_max = SI5324_NC_LS_MAX;
+
+	if ((settings->nc1_ls_max & 0x1) == 1)
+		settings->nc1_ls_max--;
+	if ((settings->nc1_ls_max * settings->n1_hs < settings->n1_hs_min) ||
+	    (settings->nc1_ls_min * settings->n1_hs > settings->n1_hs_max))
+		return -1;
+
+	return 0;
+}
+
+/**
+ * si5324_find_ncls - Find a valid setting for NCn_LS
+ *
+ * @settings:	Holds the input and output frequencies, the setting for
+ * N1_HS, and the limits for NCn_LS.
+ *
+ * This function find a valid setting for NCn_LS that can deliver the correct
+ * output frequency. Assumes that the valid range is relatively small
+ * so a full search can be done (should be true for video clock frequencies).
+ *
+ * Return:	1 when the best possible result has been found.
+ */
+static int si5324_find_ncls(struct si5324_settingst *settings)
+{
+	u64 fosc_1;
+	u32 result;
+
+	fosc_1 = settings->fout * settings->n1_hs;
+	for (settings->nc1_ls = settings->nc1_ls_min;
+		settings->nc1_ls <= settings->nc1_ls_max;) {
+		settings->fosc = fosc_1 * settings->nc1_ls;
+		pr_debug("Trying NCn_LS = %d: fosc = %dkHz.\n",
+			 settings->nc1_ls,
+			 (u32)(div64_u64((settings->fosc >>
+				SI5324_FIN_FOUT_SHIFT), 1000)));
+
+		result = si5324_find_n2(settings);
+		if (result)
+			break;
+		if (settings->nc1_ls == 1)
+			settings->nc1_ls++;
+		else
+			settings->nc1_ls += 2;
+	}
+	return result;
+}
+
+/**
+ * si5324_calcfreqsettings - Calculate the frequency settings
+ *
+ * @clkinfreq:	Frequency of the input clock.
+ * @clkoutfreq:	Desired output clock frequency.
+ * @clkactual:	Actual clock frequency.
+ * @n1_hs:	Set to the value for the N1_HS register.
+ * @ncn_ls:	Set to the value for the NCn_LS register.
+ * @n2_hs:	Set to the value for the N2_HS register.
+ * @n2_ls:	Set to the value for the N2_LS register.
+ * @n3n:	Set to the value for the N3n register.
+ * @bwsel:	Set to the value for the BW_SEL register.
+ *
+ * This funciton calculates the frequency settings for the desired output
+ * frequency.
+ *
+ * Return:	SI5324_SUCCESS for success, SI5324_ERR_FREQ when the
+ * requested frequency cannot be generated.
+ */
+int si5324_calcfreqsettings(u32 clkinfreq, u32 clkoutfreq, u32 *clkactual,
+			    u8 *n1_hs, u32 *ncn_ls, u8 *n2_hs, u32 *n2_ls,
+			    u32 *n3n, u8 *bwsel)
+{
+	struct si5324_settingst settings;
+	int result;
+
+	settings.fin = (u64)clkinfreq << SI5324_FIN_FOUT_SHIFT;
+	settings.fout = (u64)clkoutfreq << SI5324_FIN_FOUT_SHIFT;
+	settings.best_delta_fout = settings.fout;
+
+	settings.n1_hs_min = (int)(div64_u64(SI5324_FOSC_MIN, clkoutfreq));
+	if (settings.n1_hs_min < SI5324_N1_HS_MIN * SI5324_NC_LS_MIN)
+		settings.n1_hs_min = SI5324_N1_HS_MIN * SI5324_NC_LS_MIN;
+
+	settings.n1_hs_max = (int)(div64_u64(SI5324_FOSC_MAX, clkoutfreq));
+	if (settings.n1_hs_max > SI5324_N1_HS_MAX * SI5324_NC_LS_MAX)
+		settings.n1_hs_max = SI5324_N1_HS_MAX * SI5324_NC_LS_MAX;
+
+	settings.n31_min = div64_u64(clkinfreq, SI5324_F3_MAX);
+	if (settings.n31_min < SI5324_N3_MIN)
+		settings.n31_min = SI5324_N3_MIN;
+
+	settings.n31_max = div64_u64(clkinfreq, SI5324_F3_MIN);
+	if (settings.n31_max > SI5324_N3_MAX)
+		settings.n31_max = SI5324_N3_MAX;
+
+	/* Find a valid oscillator frequency with the highest setting of N1_HS
+	 * possible (reduces power)
+	 */
+	for (settings.n1_hs = SI5324_N1_HS_MAX;
+		settings.n1_hs >= SI5324_N1_HS_MIN; settings.n1_hs--) {
+		pr_debug("Trying N1_HS = %d.\n", settings.n1_hs);
+
+		result = si5324_calc_ncls_limits(&settings);
+		if (result) {
+			pr_debug("No valid settings\n");
+			continue;
+		}
+		result = si5324_find_ncls(&settings);
+		if (result)
+			break;
+	}
+
+		pr_debug("Si5324: settings.best_delta_fout = %llu\n",
+			 (unsigned long long)settings.best_delta_fout);
+		pr_debug("Si5324: settings.fout = %llu\n",
+			 (unsigned long long)settings.fout);
+
+	if (settings.best_delta_fout == settings.fout) {
+		pr_debug("Si5324: No valid settings found.");
+		return SI5324_ERR_FREQ;
+	}
+		pr_debug("Si5324: Found solution: fout = %dHz.\n",
+			 (u32)(settings.best_fout >> 28));
+
+	/* Post processing: convert temporary values to actual registers */
+	*n1_hs = (u8)settings.best_n1_hs - 4;
+	*ncn_ls = settings.best_nc1_ls - 1;
+	*n2_hs = (u8)settings.best_n2_hs - 4;
+	*n2_ls = settings.best_n2_ls - 1;
+	*n3n = settings.best_n3 - 1;
+	/*
+	 * How must the bandwidth selection be determined?
+	 * Not all settings will be valid.
+	 * refclk 2, 0xA2, BWSEL_REG=1010 (?)
+	 * free running 2, 0x42, BWSEL_REG=0100 (?)
+	 */
+	*bwsel = 6;
+
+	if (clkactual)
+		*clkactual = (settings.best_fout >> SI5324_FIN_FOUT_SHIFT);
+
+	return SI5324_SUCCESS;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/si5324drv.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/si5324drv.h
@@ -0,0 +1,100 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Si5324 clock driver
+ *
+ * Copyright (C) 2017-2018 Xilinx, Inc.
+ */
+
+#ifndef SI5324DRV_H_
+#define SI5324DRV_H_
+
+#include <linux/types.h>
+
+/******************************************************************************
+ * User settable defines that depend on the specific board design.
+ * The defaults are for the Xilinx KC705 board.
+ *****************************************************************************/
+
+#define SI5324_XTAL_FREQ 114285000UL
+
+/******************************************************************************
+ * Defines independent on the specific board design. Should not be changed.
+ *****************************************************************************/
+
+#define SI5324_SUCCESS		0 /*< Operation was successful */
+#define SI5324_ERR_IIC		-1 /*< IIC error occurred */
+#define SI5324_ERR_FREQ		-2 /*< Could not calculate frequency setting */
+#define SI5324_ERR_PARM		-3 /*< Invalid parameter */
+
+#define SI5324_CLKSRC_CLK1	1 /*< Use clock input 1 */
+#define SI5324_CLKSRC_CLK2	2 /*< Use clock input 2 */
+#define SI5324_CLKSRC_XTAL	3 /*< Use crystal (free running mode) */
+
+#define SI5324_FOSC_MIN		4850000000UL /*< Min oscillator frequency */
+#define SI5324_FOSC_MAX		5670000000UL /*< Max oscillator frequency */
+#define SI5324_F3_MIN		10000 /*< Min phase detector frequency */
+#define SI5324_F3_MAX		2000000 /*< Max phase detector frequency */
+#define SI5324_FIN_MIN		2000 /*< Min input frequency */
+#define SI5324_FIN_MAX		710000000UL /*< Max input frequency */
+#define SI5324_FOUT_MIN		2000 /*< Min output frequency */
+#define SI5324_FOUT_MAX		945000000UL /*< Max output frequency */
+
+#define SI5324_N1_HS_MIN	6
+#define SI5324_N1_HS_MAX	11
+#define SI5324_NC_LS_MIN	1
+#define SI5324_NC_LS_MAX	0x100000
+#define SI5324_N2_HS_MIN	4
+#define SI5324_N2_HS_MAX	11
+#define SI5324_N2_LS_MIN	2 /* even values only */
+#define SI5324_N2_LS_MAX	0x100000
+#define SI5324_N3_MIN		1
+#define SI5324_N3_MAX		0x080000
+#define SI5324_FIN_FOUT_SHIFT	28
+
+struct si5324_settingst {
+	/* high-speed output divider */
+	u32 n1_hs_min;
+	u32 n1_hs_max;
+	u32 n1_hs;
+
+	/* low-speed output divider for clkout1 */
+	u32 nc1_ls_min;
+	u32 nc1_ls_max;
+	u32 nc1_ls;
+
+	/* low-speed output divider for clkout2 */
+	u32 nc2_ls_min;
+	u32 nc2_ls_max;
+	u32 nc2_ls;
+
+	/* high-speed feedback divider (PLL multiplier) */
+	u32 n2_hs;
+	/* low-speed feedback divider (PLL multiplier) */
+	u32 n2_ls_min;
+	u32 n2_ls_max;
+	u32 n2_ls;
+
+	/* input divider for clk1 */
+	u32 n31_min;
+	u32 n31_max;
+	u32 n31;
+
+	u64 fin;
+	u64 fout;
+	u64 fosc;
+	u64 best_delta_fout;
+	u64 best_fout;
+	u32 best_n1_hs;
+	u32 best_nc1_ls;
+	u32 best_n2_hs;
+	u32 best_n2_ls;
+	u32 best_n3;
+};
+
+int si5324_calcfreqsettings(u32 clkinfreq, u32 clkoutfreq, u32 *clkactual,
+			    u8 *n1_hs, u32 *ncn_ls, u8 *n2_hs,
+			    u32 *n2_ls, u32 *n3n, u8 *bwsel);
+void si5324_rate_approx(u64 f, u64 md, u32 *num, u32 *denom);
+int si5324_calc_ncls_limits(struct si5324_settingst *settings);
+
+#endif /* SI5324DRV_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/sifive/fu540-prci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/sifive/fu540-prci.c
@@ -586,7 +586,10 @@
 	struct __prci_data *pd;
 	int r;
 
-	pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
+	pd = devm_kzalloc(dev,
+			  struct_size(pd, hw_clks.hws,
+				      ARRAY_SIZE(__prci_init_clocks)),
+			  GFP_KERNEL);
 	if (!pd)
 		return -ENOMEM;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/sirf/clk-atlas6.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/sirf/clk-atlas6.c
@@ -135,7 +135,7 @@
 
 	for (i = pll1; i < maxclk; i++) {
 		atlas6_clks[i] = clk_register(NULL, atlas6_clk_hw_array[i]);
-		BUG_ON(!atlas6_clks[i]);
+		BUG_ON(IS_ERR(atlas6_clks[i]));
 	}
 	clk_register_clkdev(atlas6_clks[cpu], NULL, "cpu");
 	clk_register_clkdev(atlas6_clks[io],  NULL, "io");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/socfpga/clk-gate-a10.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/socfpga/clk-gate-a10.c
@@ -146,6 +146,7 @@
 		if (IS_ERR(socfpga_clk->sys_mgr_base_addr)) {
 			pr_err("%s: failed to find altr,sys-mgr regmap!\n",
 					__func__);
+			kfree(socfpga_clk);
 			return;
 		}
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/socfpga/clk-gate.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/socfpga/clk-gate.c
@@ -99,7 +99,7 @@
 		val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
 		val &= GENMASK(socfpgaclk->width - 1, 0);
 		/* Check for GPIO_DB_CLK by its offset */
-		if ((int) socfpgaclk->div_reg & SOCFPGA_GPIO_DB_CLK_OFFSET)
+		if ((uintptr_t) socfpgaclk->div_reg & SOCFPGA_GPIO_DB_CLK_OFFSET)
 			div = val + 1;
 		else
 			div = (1 << val);
@@ -174,21 +174,24 @@
 	u32 div_reg[3];
 	u32 clk_phase[2];
 	u32 fixed_div;
-	struct clk *clk;
+	struct clk_hw *hw_clk;
 	struct socfpga_gate_clk *socfpga_clk;
 	const char *clk_name = node->name;
 	const char *parent_name[SOCFPGA_MAX_PARENTS];
 	struct clk_init_data init;
 	struct clk_ops *ops;
 	int rc;
+	int err;
 
 	socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL);
 	if (WARN_ON(!socfpga_clk))
 		return;
 
 	ops = kmemdup(&gateclk_ops, sizeof(gateclk_ops), GFP_KERNEL);
-	if (WARN_ON(!ops))
+	if (WARN_ON(!ops)) {
+		kfree(socfpga_clk);
 		return;
+	}
 
 	rc = of_property_read_u32_array(node, "clk-gate", clk_gate, 2);
 	if (rc)
@@ -238,12 +241,15 @@
 	init.parent_names = parent_name;
 	socfpga_clk->hw.hw.init = &init;
 
-	clk = clk_register(NULL, &socfpga_clk->hw.hw);
-	if (WARN_ON(IS_ERR(clk))) {
+	hw_clk = &socfpga_clk->hw.hw;
+
+	err = clk_hw_register(NULL, hw_clk);
+	if (err) {
+		kfree(ops);
 		kfree(socfpga_clk);
 		return;
 	}
-	rc = of_clk_add_provider(node, of_clk_src_simple_get, clk);
+	rc = of_clk_add_provider(node, of_clk_src_simple_get, hw_clk);
 	if (WARN_ON(rc))
 		return;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/socfpga/clk-periph.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/socfpga/clk-periph.c
@@ -51,7 +51,7 @@
 	const struct clk_ops *ops)
 {
 	u32 reg;
-	struct clk *clk;
+	struct clk_hw *hw_clk;
 	struct socfpga_periph_clk *periph_clk;
 	const char *clk_name = node->name;
 	const char *parent_name[SOCFPGA_MAX_PARENTS];
@@ -94,13 +94,13 @@
 	init.parent_names = parent_name;
 
 	periph_clk->hw.hw.init = &init;
+	hw_clk = &periph_clk->hw.hw;
 
-	clk = clk_register(NULL, &periph_clk->hw.hw);
-	if (WARN_ON(IS_ERR(clk))) {
+	if (clk_hw_register(NULL, hw_clk)) {
 		kfree(periph_clk);
 		return;
 	}
-	rc = of_clk_add_provider(node, of_clk_src_simple_get, clk);
+	rc = of_clk_add_provider(node, of_clk_src_simple_get, hw_clk);
 }
 
 void __init socfpga_periph_init(struct device_node *node)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/socfpga/clk-pll-s10.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/socfpga/clk-pll-s10.c
@@ -39,7 +39,9 @@
 	/* read VCO1 reg for numerator and denominator */
 	reg = readl(socfpgaclk->hw.reg);
 	refdiv = (reg & SOCFPGA_PLL_REFDIV_MASK) >> SOCFPGA_PLL_REFDIV_SHIFT;
-	vco_freq = (unsigned long long)parent_rate / refdiv;
+
+	vco_freq = parent_rate;
+	do_div(vco_freq, refdiv);
 
 	/* Read mdiv and fdiv from the fdbck register */
 	reg = readl(socfpgaclk->hw.reg + 0x4);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/socfpga/clk-pll.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/socfpga/clk-pll.c
@@ -70,17 +70,18 @@
 	.get_parent = clk_pll_get_parent,
 };
 
-static __init struct clk *__socfpga_pll_init(struct device_node *node,
+static __init struct clk_hw *__socfpga_pll_init(struct device_node *node,
 	const struct clk_ops *ops)
 {
 	u32 reg;
-	struct clk *clk;
+	struct clk_hw *hw_clk;
 	struct socfpga_pll *pll_clk;
 	const char *clk_name = node->name;
 	const char *parent_name[SOCFPGA_MAX_PARENTS];
 	struct clk_init_data init;
 	struct device_node *clkmgr_np;
 	int rc;
+	int err;
 
 	of_property_read_u32(node, "reg", &reg);
 
@@ -108,13 +109,15 @@
 	clk_pll_ops.enable = clk_gate_ops.enable;
 	clk_pll_ops.disable = clk_gate_ops.disable;
 
-	clk = clk_register(NULL, &pll_clk->hw.hw);
-	if (WARN_ON(IS_ERR(clk))) {
+	hw_clk = &pll_clk->hw.hw;
+
+	err = clk_hw_register(NULL, hw_clk);
+	if (err) {
 		kfree(pll_clk);
-		return NULL;
+		return ERR_PTR(err);
 	}
-	rc = of_clk_add_provider(node, of_clk_src_simple_get, clk);
-	return clk;
+	rc = of_clk_add_provider(node, of_clk_src_simple_get, hw_clk);
+	return hw_clk;
 }
 
 void __init socfpga_pll_init(struct device_node *node)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/socfpga/clk-s10.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/socfpga/clk-s10.c
@@ -107,7 +107,7 @@
 	{ STRATIX10_EMAC_B_FREE_CLK, "emacb_free_clk", NULL, emacb_free_mux, ARRAY_SIZE(emacb_free_mux),
 	  0, 0, 2, 0xB0, 1},
 	{ STRATIX10_EMAC_PTP_FREE_CLK, "emac_ptp_free_clk", NULL, emac_ptp_free_mux,
-	  ARRAY_SIZE(emac_ptp_free_mux), 0, 0, 4, 0xB0, 2},
+	  ARRAY_SIZE(emac_ptp_free_mux), 0, 0, 2, 0xB0, 2},
 	{ STRATIX10_GPIO_DB_FREE_CLK, "gpio_db_free_clk", NULL, gpio_db_free_mux,
 	  ARRAY_SIZE(gpio_db_free_mux), 0, 0, 0, 0xB0, 3},
 	{ STRATIX10_SDMMC_FREE_CLK, "sdmmc_free_clk", NULL, sdmmc_free_mux,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/sprd/common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/sprd/common.c
@@ -46,7 +46,7 @@
 
 	if (of_find_property(node, "sprd,syscon", NULL)) {
 		regmap = syscon_regmap_lookup_by_phandle(node, "sprd,syscon");
-		if (IS_ERR_OR_NULL(regmap)) {
+		if (IS_ERR(regmap)) {
 			pr_err("%s: failed to get syscon regmap\n", __func__);
 			return PTR_ERR(regmap);
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/sprd/pll.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/sprd/pll.c
@@ -105,7 +105,7 @@
 
 	cfg = kcalloc(regs_num, sizeof(*cfg), GFP_KERNEL);
 	if (!cfg)
-		return -ENOMEM;
+		return parent_rate;
 
 	for (i = 0; i < regs_num; i++)
 		cfg[i] = sprd_pll_read(pll, i);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/st/clk-flexgen.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/st/clk-flexgen.c
@@ -375,6 +375,7 @@
 			break;
 		}
 
+		flex_flags &= ~CLK_IS_CRITICAL;
 		of_clk_detect_critical(np, i, &flex_flags);
 
 		/*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/st/clkgen-fsyn.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/st/clkgen-fsyn.c
@@ -943,9 +943,10 @@
 
 	clk = st_clk_register_quadfs_pll(pll_name, clk_parent_name, data,
 			reg, lock);
-	if (IS_ERR(clk))
+	if (IS_ERR(clk)) {
+		kfree(lock);
 		goto err_exit;
-	else
+	} else
 		pr_debug("%s: parent %s rate %u\n",
 			__clk_get_name(clk),
 			__clk_get_name(clk_get_parent(clk)),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
@@ -389,6 +389,7 @@
 	{ .val = 1, .div = 2 },
 	{ .val = 2, .div = 4 },
 	{ .val = 3, .div = 6 },
+	{ /* Sentinel */ },
 };
 static const char * const ths_parents[] = { "osc24M" };
 static struct ccu_div ths_clk = {
@@ -921,11 +922,26 @@
 	.num_resets	= ARRAY_SIZE(sun50i_a64_ccu_resets),
 };
 
+static struct ccu_pll_nb sun50i_a64_pll_cpu_nb = {
+	.common	= &pll_cpux_clk.common,
+	/* copy from pll_cpux_clk */
+	.enable	= BIT(31),
+	.lock	= BIT(28),
+};
+
+static struct ccu_mux_nb sun50i_a64_cpu_nb = {
+	.common		= &cpux_clk.common,
+	.cm		= &cpux_clk.mux,
+	.delay_us	= 1, /* > 8 clock cycles at 24 MHz */
+	.bypass_index	= 1, /* index of 24 MHz oscillator */
+};
+
 static int sun50i_a64_ccu_probe(struct platform_device *pdev)
 {
 	struct resource *res;
 	void __iomem *reg;
 	u32 val;
+	int ret;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	reg = devm_ioremap_resource(&pdev->dev, res);
@@ -939,7 +955,18 @@
 
 	writel(0x515, reg + SUN50I_A64_PLL_MIPI_REG);
 
-	return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_a64_ccu_desc);
+	ret = sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_a64_ccu_desc);
+	if (ret)
+		return ret;
+
+	/* Gate then ungate PLL CPU after any rate changes */
+	ccu_pll_notifier_register(&sun50i_a64_pll_cpu_nb);
+
+	/* Reparent CPU during PLL CPU rate changes */
+	ccu_mux_notifier_register(pll_cpux_clk.common.hw.clk,
+				  &sun50i_a64_cpu_nb);
+
+	return 0;
 }
 
 static const struct of_device_id sun50i_a64_ccu_ids[] = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
@@ -23,9 +23,9 @@
  */
 
 static const char * const ar100_r_apb2_parents[] = { "osc24M", "osc32k",
-					     "pll-periph0", "iosc" };
+						     "iosc", "pll-periph0" };
 static const struct ccu_mux_var_prediv ar100_r_apb2_predivs[] = {
-	{ .index = 2, .shift = 0, .width = 5 },
+	{ .index = 3, .shift = 0, .width = 5 },
 };
 
 static struct ccu_div ar100_clk = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
@@ -228,7 +228,7 @@
 static SUNXI_CCU_MP_WITH_MUX(psi_ahb1_ahb2_clk, "psi-ahb1-ahb2",
 			     psi_ahb1_ahb2_parents,
 			     0x510,
-			     0, 5,	/* M */
+			     0, 2,	/* M */
 			     8, 2,	/* P */
 			     24, 2,	/* mux */
 			     0);
@@ -237,19 +237,19 @@
 						       "psi-ahb1-ahb2",
 						       "pll-periph0" };
 static SUNXI_CCU_MP_WITH_MUX(ahb3_clk, "ahb3", ahb3_apb1_apb2_parents, 0x51c,
-			     0, 5,	/* M */
+			     0, 2,	/* M */
 			     8, 2,	/* P */
 			     24, 2,	/* mux */
 			     0);
 
 static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1", ahb3_apb1_apb2_parents, 0x520,
-			     0, 5,	/* M */
+			     0, 2,	/* M */
 			     8, 2,	/* P */
 			     24, 2,	/* mux */
 			     0);
 
 static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", ahb3_apb1_apb2_parents, 0x524,
-			     0, 5,	/* M */
+			     0, 2,	/* M */
 			     8, 2,	/* P */
 			     24, 2,	/* mux */
 			     0);
@@ -673,7 +673,7 @@
 
 	.common		= {
 		.reg		= 0xb10,
-		.features	= CCU_FEATURE_VARIABLE_PREDIV,
+		.features	= CCU_FEATURE_FIXED_PREDIV,
 		.hw.init	= CLK_HW_INIT_PARENTS("hdmi-cec",
 						      hdmi_cec_parents,
 						      &ccu_mux_ops,
@@ -1172,12 +1172,19 @@
 	SUN50I_H6_USB3_CLK_REG,
 };
 
+static struct ccu_mux_nb sun50i_h6_cpu_nb = {
+	.common		= &cpux_clk.common,
+	.cm		= &cpux_clk.mux,
+	.delay_us       = 1,
+	.bypass_index   = 0, /* index of 24 MHz oscillator */
+};
+
 static int sun50i_h6_ccu_probe(struct platform_device *pdev)
 {
 	struct resource *res;
 	void __iomem *reg;
+	int i, ret;
 	u32 val;
-	int i;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	reg = devm_ioremap_resource(&pdev->dev, res);
@@ -1231,7 +1238,15 @@
 	val |= BIT(24);
 	writel(val, reg + SUN50I_H6_HDMI_CEC_CLK_REG);
 
-	return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_h6_ccu_desc);
+	ret = sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_h6_ccu_desc);
+	if (ret)
+		return ret;
+
+	/* Reparent CPU during PLL CPUX rate changes */
+	ccu_mux_notifier_register(pll_cpux_clk.common.hw.clk,
+				  &sun50i_h6_cpu_nb);
+
+	return 0;
 }
 
 static const struct of_device_id sun50i_h6_ccu_ids[] = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
@@ -322,6 +322,7 @@
 	{ .val = 1, .div = 2 },
 	{ .val = 2, .div = 4 },
 	{ .val = 3, .div = 6 },
+	{ /* Sentinel */ },
 };
 static SUNXI_CCU_DIV_TABLE_WITH_GATE(ths_clk, "ths", "osc24M",
 				     0x074, 0, 2, ths_div_table, BIT(31), 0);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/sunxi-ng/ccu-sun8i-r.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/sunxi-ng/ccu-sun8i-r.c
@@ -51,19 +51,7 @@
 
 static CLK_FIXED_FACTOR_HW(ahb0_clk, "ahb0", &ar100_clk.common.hw, 1, 1, 0);
 
-static struct ccu_div apb0_clk = {
-	.div		= _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO),
-
-	.common		= {
-		.reg		= 0x0c,
-		.hw.init	= CLK_HW_INIT_HW("apb0",
-						 &ahb0_clk.hw,
-						 &ccu_div_ops,
-						 0),
-	},
-};
-
-static SUNXI_CCU_M(a83t_apb0_clk, "apb0", "ahb0", 0x0c, 0, 2, 0);
+static SUNXI_CCU_M(apb0_clk, "apb0", "ahb0", 0x0c, 0, 2, 0);
 
 /*
  * Define the parent as an array that can be reused to save space
@@ -127,7 +115,7 @@
 
 static struct ccu_common *sun8i_a83t_r_ccu_clks[] = {
 	&ar100_clk.common,
-	&a83t_apb0_clk.common,
+	&apb0_clk.common,
 	&apb0_pio_clk.common,
 	&apb0_ir_clk.common,
 	&apb0_timer_clk.common,
@@ -167,7 +155,7 @@
 	.hws	= {
 		[CLK_AR100]		= &ar100_clk.common.hw,
 		[CLK_AHB0]		= &ahb0_clk.hw,
-		[CLK_APB0]		= &a83t_apb0_clk.common.hw,
+		[CLK_APB0]		= &apb0_clk.common.hw,
 		[CLK_APB0_PIO]		= &apb0_pio_clk.common.hw,
 		[CLK_APB0_IR]		= &apb0_ir_clk.common.hw,
 		[CLK_APB0_TIMER]	= &apb0_timer_clk.common.hw,
@@ -282,9 +270,6 @@
 
 static void __init sun8i_a83t_r_ccu_setup(struct device_node *node)
 {
-	/* Fix apb0 bus gate parents here */
-	apb0_gate_parent[0] = &a83t_apb0_clk.common.hw;
-
 	sunxi_r_ccu_init(node, &sun8i_a83t_r_ccu_desc);
 }
 CLK_OF_DECLARE(sun8i_a83t_r_ccu, "allwinner,sun8i-a83t-r-ccu",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/sunxi-ng/ccu-sun8i-r40.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/sunxi-ng/ccu-sun8i-r40.c
@@ -761,7 +761,8 @@
 		.reg		= 0x1f0,
 		.features	= CCU_FEATURE_FIXED_PREDIV,
 		.hw.init	= CLK_HW_INIT_PARENTS("outa", out_parents,
-						      &ccu_mp_ops, 0),
+						      &ccu_mp_ops,
+						      CLK_SET_RATE_PARENT),
 	}
 };
 
@@ -779,7 +780,8 @@
 		.reg		= 0x1f4,
 		.features	= CCU_FEATURE_FIXED_PREDIV,
 		.hw.init	= CLK_HW_INIT_PARENTS("outb", out_parents,
-						      &ccu_mp_ops, 0),
+						      &ccu_mp_ops,
+						      CLK_SET_RATE_PARENT),
 	}
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
@@ -618,7 +618,7 @@
 		[CLK_MBUS]		= &mbus_clk.common.hw,
 		[CLK_MIPI_CSI]		= &mipi_csi_clk.common.hw,
 	},
-	.num	= CLK_NUMBER,
+	.num	= CLK_PLL_DDR1 + 1,
 };
 
 static struct clk_hw_onecell_data sun8i_v3_hw_clks = {
@@ -700,7 +700,7 @@
 		[CLK_MBUS]		= &mbus_clk.common.hw,
 		[CLK_MIPI_CSI]		= &mipi_csi_clk.common.hw,
 	},
-	.num	= CLK_NUMBER,
+	.num	= CLK_I2S0 + 1,
 };
 
 static struct ccu_reset_map sun8i_v3s_ccu_resets[] = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/sunxi-ng/ccu-sun8i-v3s.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/sunxi-ng/ccu-sun8i-v3s.h
@@ -51,6 +51,4 @@
 
 #define CLK_PLL_DDR1		74
 
-#define CLK_NUMBER		(CLK_I2S0 + 1)
-
 #endif /* _CCU_SUN8I_H3_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/sunxi-ng/ccu_mmc_timing.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/sunxi-ng/ccu_mmc_timing.c
@@ -43,7 +43,7 @@
 EXPORT_SYMBOL_GPL(sunxi_ccu_set_mmc_timing_mode);
 
 /**
- * sunxi_ccu_set_mmc_timing_mode: Get the current MMC clock timing mode
+ * sunxi_ccu_get_mmc_timing_mode: Get the current MMC clock timing mode
  * @clk: clock to query
  *
  * Returns 0 if the clock is in old timing mode, > 0 if it is in
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/sunxi-ng/ccu_mp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/sunxi-ng/ccu_mp.c
@@ -108,7 +108,7 @@
 	max_m = cmp->m.max ?: 1 << cmp->m.width;
 	max_p = cmp->p.max ?: 1 << ((1 << cmp->p.width) - 1);
 
-	if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) {
+	if (!clk_hw_can_set_rate_parent(&cmp->common.hw)) {
 		ccu_mp_find_best(*parent_rate, rate, max_m, max_p, &m, &p);
 		rate = *parent_rate / p / m;
 	} else {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/sunxi/clk-sun9i-mmc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/sunxi/clk-sun9i-mmc.c
@@ -109,6 +109,8 @@
 	spin_lock_init(&data->lock);
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r)
+		return -EINVAL;
 	/* one clock/reset pair per word */
 	count = DIV_ROUND_UP((resource_size(r)), SUN9I_MMC_WIDTH);
 	data->membase = devm_ioremap_resource(&pdev->dev, r);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/sunxi/clk-sunxi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/sunxi/clk-sunxi.c
@@ -90,7 +90,7 @@
 	 * Round down the frequency to the closest multiple of either
 	 * 6 or 16
 	 */
-	u32 round_freq_6 = round_down(freq_mhz, 6);
+	u32 round_freq_6 = rounddown(freq_mhz, 6);
 	u32 round_freq_16 = round_down(freq_mhz, 16);
 
 	if (round_freq_6 > round_freq_16)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/tegra/clk-bpmp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/tegra/clk-bpmp.c
@@ -159,7 +159,7 @@
 
 	err = tegra_bpmp_clk_transfer(clk->bpmp, &msg);
 	if (err < 0)
-		return err;
+		return 0;
 
 	return response.rate;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/tegra/clk-dfll.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/tegra/clk-dfll.c
@@ -1801,13 +1801,13 @@
 			    &td->reg_init_uV);
 	if (!ret) {
 		dev_err(td->dev, "couldn't get initialized voltage\n");
-		return ret;
+		return -EINVAL;
 	}
 
 	ret = read_dt_param(td, "nvidia,pwm-period-nanoseconds", &pwm_period);
 	if (!ret) {
 		dev_err(td->dev, "couldn't get PWM period\n");
-		return ret;
+		return -EINVAL;
 	}
 	td->pwm_rate = (NSEC_PER_SEC / pwm_period) * (MAX_DFLL_VOLTAGES - 1);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/tegra/clk-emc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/tegra/clk-emc.c
@@ -191,6 +191,7 @@
 
 	tegra->emc = platform_get_drvdata(pdev);
 	if (!tegra->emc) {
+		put_device(&pdev->dev);
 		pr_err("%s: cannot find EMC driver\n", __func__);
 		return NULL;
 	}
@@ -458,6 +459,7 @@
 		err = load_one_timing_from_dt(tegra, timing, child);
 		if (err) {
 			of_node_put(child);
+			kfree(tegra->timings);
 			return err;
 		}
 
@@ -509,6 +511,7 @@
 		err = load_timings_from_dt(tegra, node, node_ram_code);
 		if (err) {
 			of_node_put(node);
+			kfree(tegra);
 			return ERR_PTR(err);
 		}
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/tegra/clk-id.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/tegra/clk-id.h
@@ -233,6 +233,7 @@
 	tegra_clk_sdmmc4,
 	tegra_clk_sdmmc4_8,
 	tegra_clk_se,
+	tegra_clk_se_10,
 	tegra_clk_soc_therm,
 	tegra_clk_soc_therm_8,
 	tegra_clk_sor0,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/tegra/clk-pll.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/tegra/clk-pll.c
@@ -1089,7 +1089,8 @@
 	if (pll->lock)
 		spin_lock_irqsave(pll->lock, flags);
 
-	_clk_pll_enable(hw);
+	if (!clk_pll_is_enabled(hw))
+		_clk_pll_enable(hw);
 
 	ret = clk_pll_wait_for_lock(pll);
 	if (ret < 0)
@@ -1569,9 +1570,6 @@
 	unsigned long flags = 0;
 	unsigned long input_rate;
 
-	if (clk_pll_is_enabled(hw))
-		return 0;
-
 	input_rate = clk_hw_get_rate(clk_hw_get_parent(hw));
 
 	if (_get_table_rate(hw, &sel, pll->params->fixed_rate, input_rate))
@@ -1709,15 +1707,13 @@
 		return -EINVAL;
 	}
 
-	if (clk_pll_is_enabled(hw))
-		return 0;
-
 	input_rate = clk_hw_get_rate(__clk_get_hw(osc));
 
 	if (pll->lock)
 		spin_lock_irqsave(pll->lock, flags);
 
-	_clk_pll_enable(hw);
+	if (!clk_pll_is_enabled(hw))
+		_clk_pll_enable(hw);
 
 	ret = clk_pll_wait_for_lock(pll);
 	if (ret < 0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/tegra/clk-tegra-periph.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/tegra/clk-tegra-periph.c
@@ -636,7 +636,7 @@
 	INT8("host1x", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_HOST1X, 28, 0, tegra_clk_host1x_8),
 	INT8("host1x", mux_pllc4_out1_pllc_pllc4_out2_pllp_clkm_plla_pllc4_out0, CLK_SOURCE_HOST1X, 28, 0, tegra_clk_host1x_9),
 	INT8("se", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SE, 127, TEGRA_PERIPH_ON_APB, tegra_clk_se),
-	INT8("se", mux_pllp_pllc2_c_c3_clkm, CLK_SOURCE_SE, 127, TEGRA_PERIPH_ON_APB, tegra_clk_se),
+	INT8("se", mux_pllp_pllc2_c_c3_clkm, CLK_SOURCE_SE, 127, TEGRA_PERIPH_ON_APB, tegra_clk_se_10),
 	INT8("2d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_2D, 21, 0, tegra_clk_gr2d_8),
 	INT8("3d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_3D, 24, 0, tegra_clk_gr3d_8),
 	INT8("vic03", mux_pllm_pllc_pllp_plla_pllc2_c3_clkm, CLK_SOURCE_VIC03, 178, 0, tegra_clk_vic03),
@@ -785,7 +785,11 @@
 	GATE("ahbdma", "hclk", 33, 0, tegra_clk_ahbdma, 0),
 	GATE("apbdma", "pclk", 34, 0, tegra_clk_apbdma, 0),
 	GATE("kbc", "clk_32k", 36, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_kbc, 0),
-	GATE("fuse", "clk_m", 39, TEGRA_PERIPH_ON_APB, tegra_clk_fuse, 0),
+	/*
+	 * Critical for RAM re-repair operation, which must occur on resume
+	 * from LP1 system suspend and as part of CCPLEX cluster switching.
+	 */
+	GATE("fuse", "clk_m", 39, TEGRA_PERIPH_ON_APB, tegra_clk_fuse, CLK_IS_CRITICAL),
 	GATE("fuse_burn", "clk_m", 39, TEGRA_PERIPH_ON_APB, tegra_clk_fuse_burn, 0),
 	GATE("kfuse", "clk_m", 40, TEGRA_PERIPH_ON_APB, tegra_clk_kfuse, 0),
 	GATE("apbif", "clk_m", 107, TEGRA_PERIPH_ON_APB, tegra_clk_apbif, 0),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/tegra/clk-tegra-pmc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/tegra/clk-tegra-pmc.c
@@ -49,16 +49,16 @@
 
 static DEFINE_SPINLOCK(clk_out_lock);
 
-static const char *clk_out1_parents[] = { "clk_m", "clk_m_div2",
-	"clk_m_div4", "extern1",
+static const char *clk_out1_parents[] = { "osc", "osc_div2",
+	"osc_div4", "extern1",
 };
 
-static const char *clk_out2_parents[] = { "clk_m", "clk_m_div2",
-	"clk_m_div4", "extern2",
+static const char *clk_out2_parents[] = { "osc", "osc_div2",
+	"osc_div4", "extern2",
 };
 
-static const char *clk_out3_parents[] = { "clk_m", "clk_m_div2",
-	"clk_m_div4", "extern3",
+static const char *clk_out3_parents[] = { "osc", "osc_div2",
+	"osc_div4", "extern3",
 };
 
 static struct pmc_clk_init_data pmc_clks[] = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/tegra/clk-tegra114.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/tegra/clk-tegra114.c
@@ -1337,6 +1337,7 @@
 	}
 
 	pmc_base = of_iomap(node, 0);
+	of_node_put(node);
 	if (!pmc_base) {
 		pr_err("Can't map pmc registers\n");
 		WARN_ON(1);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/tegra/clk-tegra20.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/tegra/clk-tegra20.c
@@ -18,24 +18,24 @@
 #define MISC_CLK_ENB 0x48
 
 #define OSC_CTRL 0x50
-#define OSC_CTRL_OSC_FREQ_MASK (3<<30)
-#define OSC_CTRL_OSC_FREQ_13MHZ (0<<30)
-#define OSC_CTRL_OSC_FREQ_19_2MHZ (1<<30)
-#define OSC_CTRL_OSC_FREQ_12MHZ (2<<30)
-#define OSC_CTRL_OSC_FREQ_26MHZ (3<<30)
-#define OSC_CTRL_MASK (0x3f2 | OSC_CTRL_OSC_FREQ_MASK)
-
-#define OSC_CTRL_PLL_REF_DIV_MASK (3<<28)
-#define OSC_CTRL_PLL_REF_DIV_1		(0<<28)
-#define OSC_CTRL_PLL_REF_DIV_2		(1<<28)
-#define OSC_CTRL_PLL_REF_DIV_4		(2<<28)
+#define OSC_CTRL_OSC_FREQ_MASK (3u<<30)
+#define OSC_CTRL_OSC_FREQ_13MHZ (0u<<30)
+#define OSC_CTRL_OSC_FREQ_19_2MHZ (1u<<30)
+#define OSC_CTRL_OSC_FREQ_12MHZ (2u<<30)
+#define OSC_CTRL_OSC_FREQ_26MHZ (3u<<30)
+#define OSC_CTRL_MASK (0x3f2u | OSC_CTRL_OSC_FREQ_MASK)
+
+#define OSC_CTRL_PLL_REF_DIV_MASK	(3u<<28)
+#define OSC_CTRL_PLL_REF_DIV_1		(0u<<28)
+#define OSC_CTRL_PLL_REF_DIV_2		(1u<<28)
+#define OSC_CTRL_PLL_REF_DIV_4		(2u<<28)
 
 #define OSC_FREQ_DET 0x58
-#define OSC_FREQ_DET_TRIG (1<<31)
+#define OSC_FREQ_DET_TRIG (1u<<31)
 
 #define OSC_FREQ_DET_STATUS 0x5c
-#define OSC_FREQ_DET_BUSY (1<<31)
-#define OSC_FREQ_DET_CNT_MASK 0xFFFF
+#define OSC_FREQ_DET_BUSYu (1<<31)
+#define OSC_FREQ_DET_CNT_MASK 0xFFFFu
 
 #define TEGRA20_CLK_PERIPH_BANKS	3
 
@@ -1151,6 +1151,7 @@
 	}
 
 	pmc_base = of_iomap(node, 0);
+	of_node_put(node);
 	if (!pmc_base) {
 		pr_err("Can't map pmc registers\n");
 		BUG();
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/tegra/clk-tegra210.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/tegra/clk-tegra210.c
@@ -3523,6 +3523,7 @@
 	}
 
 	pmc_base = of_iomap(node, 0);
+	of_node_put(node);
 	if (!pmc_base) {
 		pr_err("Can't map pmc registers\n");
 		WARN_ON(1);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/tegra/clk-tegra30.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/tegra/clk-tegra30.c
@@ -1263,6 +1263,8 @@
 	{ TEGRA30_CLK_I2S3_SYNC, TEGRA30_CLK_CLK_MAX, 24000000, 0 },
 	{ TEGRA30_CLK_I2S4_SYNC, TEGRA30_CLK_CLK_MAX, 24000000, 0 },
 	{ TEGRA30_CLK_VIMCLK_SYNC, TEGRA30_CLK_CLK_MAX, 24000000, 0 },
+	{ TEGRA30_CLK_HDA, TEGRA30_CLK_PLL_P, 102000000, 0 },
+	{ TEGRA30_CLK_HDA2CODEC_2X, TEGRA30_CLK_PLL_P, 48000000, 0 },
 	/* must be the last entry */
 	{ TEGRA30_CLK_CLK_MAX, TEGRA30_CLK_CLK_MAX, 0, 0 },
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/ti/adpll.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/ti/adpll.c
@@ -194,15 +194,8 @@
 		if (err)
 			return NULL;
 	} else {
-		const char *base_name = "adpll";
-		char *buf;
-
-		buf = devm_kzalloc(d->dev, 8 + 1 + strlen(base_name) + 1 +
-				    strlen(postfix), GFP_KERNEL);
-		if (!buf)
-			return NULL;
-		sprintf(buf, "%08lx.%s.%s", d->pa, base_name, postfix);
-		name = buf;
+		name = devm_kasprintf(d->dev, GFP_KERNEL, "%08lx.adpll.%s",
+				      d->pa, postfix);
 	}
 
 	return name;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/ti/clk-33xx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/ti/clk-33xx.c
@@ -212,7 +212,7 @@
 };
 
 static const struct omap_clkctrl_reg_data am3_l4_rtc_clkctrl_regs[] __initconst = {
-	{ AM3_L4_RTC_RTC_CLKCTRL, NULL, CLKF_SW_SUP, "clk_32768_ck" },
+	{ AM3_L4_RTC_RTC_CLKCTRL, NULL, CLKF_SW_SUP, "clk-24mhz-clkctrl:0000:0" },
 	{ 0 },
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/ti/clk-43xx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/ti/clk-43xx.c
@@ -78,7 +78,7 @@
 };
 
 static const struct omap_clkctrl_reg_data am4_l4_rtc_clkctrl_regs[] __initconst = {
-	{ AM4_L4_RTC_RTC_CLKCTRL, NULL, CLKF_SW_SUP, "clk_32768_ck" },
+	{ AM4_L4_RTC_RTC_CLKCTRL, NULL, CLKF_SW_SUP, "clkdiv32k_ick" },
 	{ 0 },
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/ti/clk-7xx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/ti/clk-7xx.c
@@ -405,7 +405,7 @@
 };
 
 static const struct omap_clkctrl_reg_data dra7_gmac_clkctrl_regs[] __initconst = {
-	{ DRA7_GMAC_GMAC_CLKCTRL, dra7_gmac_bit_data, CLKF_SW_SUP, "dpll_gmac_ck" },
+	{ DRA7_GMAC_GMAC_CLKCTRL, dra7_gmac_bit_data, CLKF_SW_SUP, "gmac_main_clk" },
 	{ 0 },
 };
 
@@ -793,6 +793,7 @@
 	DT_CLK(NULL, "timer_32k_ck", "sys_32k_ck"),
 	DT_CLK(NULL, "sys_clkin_ck", "timer_sys_clk_div"),
 	DT_CLK(NULL, "sys_clkin", "sys_clkin1"),
+	DT_CLK(NULL, "timer_sys_ck", "timer_sys_clk_div"),
 	DT_CLK(NULL, "atl_dpll_clk_mux", "atl-clkctrl:0000:24"),
 	DT_CLK(NULL, "atl_gfclk_mux", "atl-clkctrl:0000:26"),
 	DT_CLK(NULL, "dcan1_sys_clk_mux", "wkupaon-clkctrl:0068:24"),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/ti/clk-dra7-atl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/ti/clk-dra7-atl.c
@@ -252,14 +252,17 @@
 		if (rc) {
 			pr_err("%s: failed to lookup atl clock %d\n", __func__,
 			       i);
-			return -EINVAL;
+			ret = -EINVAL;
+			goto pm_put;
 		}
 
 		clk = of_clk_get_from_provider(&clkspec);
+		of_node_put(clkspec.np);
 		if (IS_ERR(clk)) {
 			pr_err("%s: failed to get atl clock %d from provider\n",
 			       __func__, i);
-			return PTR_ERR(clk);
+			ret = PTR_ERR(clk);
+			goto pm_put;
 		}
 
 		cdesc = to_atl_desc(__clk_get_hw(clk));
@@ -292,8 +295,9 @@
 		if (cdesc->enabled)
 			atl_clk_enable(__clk_get_hw(clk));
 	}
-	pm_runtime_put_sync(cinfo->dev);
 
+pm_put:
+	pm_runtime_put_sync(cinfo->dev);
 	return ret;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/ti/clockdomain.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/ti/clockdomain.c
@@ -146,10 +146,12 @@
 		if (!omap2_clk_is_hw_omap(clk_hw)) {
 			pr_warn("can't setup clkdm for basic clk %s\n",
 				__clk_get_name(clk));
+			clk_put(clk);
 			continue;
 		}
 		to_clk_hw_omap(clk_hw)->clkdm_name = clkdm_name;
 		omap2_init_clk_clkdm(clk_hw);
+		clk_put(clk);
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/ti/composite.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/ti/composite.c
@@ -196,6 +196,7 @@
 		if (!cclk->comp_clks[i])
 			continue;
 		list_del(&cclk->comp_clks[i]->link);
+		kfree(cclk->comp_clks[i]->parent_names);
 		kfree(cclk->comp_clks[i]);
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/ti/fapll.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/ti/fapll.c
@@ -498,6 +498,7 @@
 {
 	struct clk_init_data *init;
 	struct fapll_synth *synth;
+	struct clk *clk = ERR_PTR(-ENOMEM);
 
 	init = kzalloc(sizeof(*init), GFP_KERNEL);
 	if (!init)
@@ -520,13 +521,19 @@
 	synth->hw.init = init;
 	synth->clk_pll = pll_clk;
 
-	return clk_register(NULL, &synth->hw);
+	clk = clk_register(NULL, &synth->hw);
+	if (IS_ERR(clk)) {
+		pr_err("failed to register clock\n");
+		goto free;
+	}
+
+	return clk;
 
 free:
 	kfree(synth);
 	kfree(init);
 
-	return ERR_PTR(-ENOMEM);
+	return clk;
 }
 
 static void __init ti_fapll_setup(struct device_node *node)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/uniphier/clk-uniphier-fixed-rate.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/uniphier/clk-uniphier-fixed-rate.c
@@ -24,6 +24,7 @@
 
 	init.name = name;
 	init.ops = &clk_fixed_rate_ops;
+	init.flags = 0;
 	init.parent_names = NULL;
 	init.num_parents = 0;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/uniphier/clk-uniphier-mux.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/uniphier/clk-uniphier-mux.c
@@ -31,10 +31,10 @@
 static u8 uniphier_clk_mux_get_parent(struct clk_hw *hw)
 {
 	struct uniphier_clk_mux *mux = to_uniphier_clk_mux(hw);
-	int num_parents = clk_hw_get_num_parents(hw);
+	unsigned int num_parents = clk_hw_get_num_parents(hw);
 	int ret;
 	unsigned int val;
-	u8 i;
+	unsigned int i;
 
 	ret = regmap_read(mux->regmap, mux->reg, &val);
 	if (ret)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/uniphier/clk-uniphier-peri.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/uniphier/clk-uniphier-peri.c
@@ -18,8 +18,8 @@
 #define UNIPHIER_PERI_CLK_FI2C(idx, ch)					\
 	UNIPHIER_CLK_GATE("i2c" #ch, (idx), "i2c", 0x24, 24 + (ch))
 
-#define UNIPHIER_PERI_CLK_SCSSI(idx)					\
-	UNIPHIER_CLK_GATE("scssi", (idx), "spi", 0x20, 17)
+#define UNIPHIER_PERI_CLK_SCSSI(idx, ch)				\
+	UNIPHIER_CLK_GATE("scssi" #ch, (idx), "spi", 0x20, 17 + (ch))
 
 #define UNIPHIER_PERI_CLK_MCSSI(idx)					\
 	UNIPHIER_CLK_GATE("mcssi", (idx), "spi", 0x24, 14)
@@ -35,7 +35,7 @@
 	UNIPHIER_PERI_CLK_I2C(6, 2),
 	UNIPHIER_PERI_CLK_I2C(7, 3),
 	UNIPHIER_PERI_CLK_I2C(8, 4),
-	UNIPHIER_PERI_CLK_SCSSI(11),
+	UNIPHIER_PERI_CLK_SCSSI(11, 0),
 	{ /* sentinel */ }
 };
 
@@ -51,7 +51,10 @@
 	UNIPHIER_PERI_CLK_FI2C(8, 4),
 	UNIPHIER_PERI_CLK_FI2C(9, 5),
 	UNIPHIER_PERI_CLK_FI2C(10, 6),
-	UNIPHIER_PERI_CLK_SCSSI(11),
-	UNIPHIER_PERI_CLK_MCSSI(12),
+	UNIPHIER_PERI_CLK_SCSSI(11, 0),
+	UNIPHIER_PERI_CLK_SCSSI(12, 1),
+	UNIPHIER_PERI_CLK_SCSSI(13, 2),
+	UNIPHIER_PERI_CLK_SCSSI(14, 3),
+	UNIPHIER_PERI_CLK_MCSSI(15),
 	{ /* sentinel */ }
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/zynq/clkc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/zynq/clkc.c
@@ -37,6 +37,7 @@
 #define SLCR_CAN_MIOCLK_CTRL		(zynq_clkc_base + 0x60)
 #define SLCR_DBG_CLK_CTRL		(zynq_clkc_base + 0x64)
 #define SLCR_PCAP_CLK_CTRL		(zynq_clkc_base + 0x68)
+#define SLCR_TOPSW_CLK_CTRL		(zynq_clkc_base + 0x6c)
 #define SLCR_FPGA0_CLK_CTRL		(zynq_clkc_base + 0x70)
 #define SLCR_621_TRUE			(zynq_clkc_base + 0xc4)
 #define SLCR_SWDT_CLK_SEL		(zynq_clkc_base + 0x204)
@@ -99,6 +100,48 @@
 static const char *const swdt_ext_clk_input_names[] __initconst = {
 	"swdt_ext_clk"};
 
+#ifdef CONFIG_SUSPEND
+static struct clk *iopll_save_parent;
+
+#define TOPSW_CLK_CTRL_DIS_MASK	BIT(0)
+
+int zynq_clk_suspend_early(void)
+{
+	int ret;
+
+	iopll_save_parent = clk_get_parent(clks[iopll]);
+
+	ret = clk_set_parent(clks[iopll], ps_clk);
+	if (ret)
+		pr_info("%s: reparent iopll failed %d\n", __func__, ret);
+
+	return 0;
+}
+
+void zynq_clk_resume_late(void)
+{
+	clk_set_parent(clks[iopll], iopll_save_parent);
+}
+
+void zynq_clk_topswitch_enable(void)
+{
+	u32 reg;
+
+	reg = readl(SLCR_TOPSW_CLK_CTRL);
+	reg &= ~TOPSW_CLK_CTRL_DIS_MASK;
+	writel(reg, SLCR_TOPSW_CLK_CTRL);
+}
+
+void zynq_clk_topswitch_disable(void)
+{
+	u32 reg;
+
+	reg = readl(SLCR_TOPSW_CLK_CTRL);
+	reg |= TOPSW_CLK_CTRL_DIS_MASK;
+	writel(reg, SLCR_TOPSW_CLK_CTRL);
+}
+#endif
+
 static void __init zynq_clk_register_fclk(enum zynq_clk fclk,
 		const char *clk_name, void __iomem *fclk_ctrl_reg,
 		const char **parents, int enable)
@@ -357,14 +400,14 @@
 				periph_parents, enable);
 	}
 
-	zynq_clk_register_periph_clk(lqspi, 0, clk_output_name[lqspi], NULL,
-			SLCR_LQSPI_CLK_CTRL, periph_parents, 0);
+	zynq_clk_register_periph_clk(lqspi, clk_max, clk_output_name[lqspi], NULL,
+				     SLCR_LQSPI_CLK_CTRL, periph_parents, 0);
 
-	zynq_clk_register_periph_clk(smc, 0, clk_output_name[smc], NULL,
-			SLCR_SMC_CLK_CTRL, periph_parents, 0);
+	zynq_clk_register_periph_clk(smc, clk_max, clk_output_name[smc], NULL,
+				     SLCR_SMC_CLK_CTRL, periph_parents, 0);
 
-	zynq_clk_register_periph_clk(pcap, 0, clk_output_name[pcap], NULL,
-			SLCR_PCAP_CLK_CTRL, periph_parents, 0);
+	zynq_clk_register_periph_clk(pcap, clk_max, clk_output_name[pcap], NULL,
+				     SLCR_PCAP_CLK_CTRL, periph_parents, 0);
 
 	zynq_clk_register_periph_clk(sdio0, sdio1, clk_output_name[sdio0],
 			clk_output_name[sdio1], SLCR_SDIO_CLK_CTRL,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/zynqmp/clk-mux-zynqmp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/zynqmp/clk-mux-zynqmp.c
@@ -49,8 +49,10 @@
 	int ret;
 	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
 
-	ret = eemi_ops->clock_getparent(clk_id, &val);
+	if (IS_ERR(eemi_ops))
+		return PTR_ERR(eemi_ops);
 
+	ret = eemi_ops->clock_getparent(clk_id, &val);
 	if (ret)
 		pr_warn_once("%s() getparent failed for clock: %s, ret = %d\n",
 			     __func__, clk_name, ret);
@@ -73,8 +75,10 @@
 	int ret;
 	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
 
-	ret = eemi_ops->clock_setparent(clk_id, index);
+	if (IS_ERR(eemi_ops))
+		return PTR_ERR(eemi_ops);
 
+	ret = eemi_ops->clock_setparent(clk_id, index);
 	if (ret)
 		pr_warn_once("%s() set parent failed for clock: %s, ret = %d\n",
 			     __func__, clk_name, ret);
@@ -85,7 +89,7 @@
 static const struct clk_ops zynqmp_clk_mux_ops = {
 	.get_parent = zynqmp_clk_mux_get_parent,
 	.set_parent = zynqmp_clk_mux_set_parent,
-	.determine_rate = __clk_mux_determine_rate,
+	.determine_rate = __clk_mux_determine_rate_closest,
 };
 
 static const struct clk_ops zynqmp_clk_mux_ro_ops = {
@@ -125,14 +129,26 @@
 	init.flags = nodes->flag;
 	init.parent_names = parents;
 	init.num_parents = num_parents;
-	mux->flags = nodes->type_flag;
+	mux->flags = 0;
+	mux->flags |= (nodes->type_flag & ZYNQMP_CLK_MUX_INDEX_ONE) ?
+		      CLK_MUX_INDEX_ONE : 0;
+	mux->flags |= (nodes->type_flag & ZYNQMP_CLK_MUX_INDEX_BIT) ?
+		      CLK_MUX_INDEX_BIT : 0;
+	mux->flags |= (nodes->type_flag & ZYNQMP_CLK_MUX_HIWORD_MASK) ?
+		      CLK_MUX_HIWORD_MASK : 0;
+	mux->flags |= (nodes->type_flag & ZYNQMP_CLK_MUX_READ_ONLY) ?
+		      CLK_MUX_READ_ONLY : 0;
+	mux->flags |= (nodes->type_flag & ZYNQMP_CLK_MUX_ROUND_CLOSEST) ?
+		      CLK_MUX_ROUND_CLOSEST : 0;
+	mux->flags |= (nodes->type_flag & ZYNQMP_CLK_MUX_BIG_ENDIAN) ?
+		      CLK_MUX_BIG_ENDIAN : 0;
 	mux->hw.init = &init;
 	mux->clk_id = clk_id;
 
 	hw = &mux->hw;
 	ret = clk_hw_register(NULL, hw);
 	if (ret) {
-		kfree(hw);
+		kfree(mux);
 		hw = ERR_PTR(ret);
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/zynqmp/clk-zynqmp.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/zynqmp/clk-zynqmp.h
@@ -10,6 +10,45 @@
 
 #include <linux/firmware/xlnx-zynqmp.h>
 
+/* Common Flags */
+/* must be gated across rate change */
+#define ZYNQMP_CLK_SET_RATE_GATE	BIT(0)
+/* must be gated across re-parent */
+#define ZYNQMP_CLK_SET_PARENT_GATE	BIT(1)
+/* propagate rate change up one level */
+#define ZYNQMP_CLK_SET_RATE_PARENT	BIT(2)
+/* do not gate even if unused */
+#define ZYNQMP_CLK_IGNORE_UNUSED	BIT(3)
+/* do not use the cached clk rate */
+#define ZYNQMP_CLK_GET_RATE_NOCACHE	BIT(6)
+/* don't re-parent on rate change */
+#define ZYNQMP_CLK_SET_RATE_NO_REPARENT	BIT(7)
+/* do not use the cached clk accuracy */
+#define ZYNQMP_CLK_GET_ACCURACY_NOCACHE	BIT(8)
+/* recalc rates after notifications */
+#define ZYNQMP_CLK_RECALC_NEW_RATES	BIT(9)
+/* clock needs to run to set rate */
+#define ZYNQMP_CLK_SET_RATE_UNGATE	BIT(10)
+/* do not gate, ever */
+#define ZYNQMP_CLK_IS_CRITICAL		BIT(11)
+
+/* Type Flags for divider clock */
+#define ZYNQMP_CLK_DIVIDER_ONE_BASED		BIT(0)
+#define ZYNQMP_CLK_DIVIDER_POWER_OF_TWO		BIT(1)
+#define ZYNQMP_CLK_DIVIDER_ALLOW_ZERO		BIT(2)
+#define ZYNQMP_CLK_DIVIDER_HIWORD_MASK		BIT(3)
+#define ZYNQMP_CLK_DIVIDER_ROUND_CLOSEST	BIT(4)
+#define ZYNQMP_CLK_DIVIDER_READ_ONLY		BIT(5)
+#define ZYNQMP_CLK_DIVIDER_MAX_AT_ZERO		BIT(6)
+
+/* Type Flags for mux clock */
+#define ZYNQMP_CLK_MUX_INDEX_ONE		BIT(0)
+#define ZYNQMP_CLK_MUX_INDEX_BIT		BIT(1)
+#define ZYNQMP_CLK_MUX_HIWORD_MASK		BIT(2)
+#define ZYNQMP_CLK_MUX_READ_ONLY		BIT(3)
+#define ZYNQMP_CLK_MUX_ROUND_CLOSEST		BIT(4)
+#define ZYNQMP_CLK_MUX_BIG_ENDIAN		BIT(5)
+
 enum topology_type {
 	TYPE_INVALID,
 	TYPE_MUX,
@@ -25,11 +64,13 @@
  * @type:	Type of topology
  * @flag:	Topology flags
  * @type_flag:	Topology type specific flag
+ * @custom_type_flag: Topology type specific custome flag
  */
 struct clock_topology {
 	u32 type;
 	u32 flag;
 	u32 type_flag;
+	u8 custom_type_flag;
 };
 
 struct clk_hw *zynqmp_clk_register_pll(const char *name, u32 clk_id,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/zynqmp/clkc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/zynqmp/clkc.c
@@ -2,7 +2,7 @@
 /*
  * Zynq UltraScale+ MPSoC clock controller
  *
- *  Copyright (C) 2016-2018 Xilinx
+ *  Copyright (C) 2016-2019 Xilinx
  *
  * Based on drivers/clk/zynq/clkc.c
  */
@@ -84,6 +84,7 @@
 
 struct topology_resp {
 #define CLK_TOPOLOGY_TYPE		GENMASK(3, 0)
+#define CLK_TOPOLOGY_CUSTOM_TYPE_FLAGS	GENMASK(7, 4)
 #define CLK_TOPOLOGY_FLAGS		GENMASK(23, 8)
 #define CLK_TOPOLOGY_TYPE_FLAGS		GENMASK(31, 24)
 	u32 topology[CLK_GET_TOPOLOGY_RESP_WORDS];
@@ -385,17 +386,41 @@
 {
 	int i;
 	u32 type;
+	u32 flag;
 
 	for (i = 0; i < ARRAY_SIZE(response->topology); i++) {
 		type = FIELD_GET(CLK_TOPOLOGY_TYPE, response->topology[i]);
 		if (type == TYPE_INVALID)
 			return END_OF_TOPOLOGY_NODE;
 		topology[*nnodes].type = type;
-		topology[*nnodes].flag = FIELD_GET(CLK_TOPOLOGY_FLAGS,
-						   response->topology[i]);
+		flag = FIELD_GET(CLK_TOPOLOGY_FLAGS, response->topology[i]);
+		topology[*nnodes].flag = 0;
+		topology[*nnodes].flag |= (flag & ZYNQMP_CLK_SET_RATE_GATE) ?
+					  CLK_SET_RATE_GATE : 0;
+		topology[*nnodes].flag |= (flag & ZYNQMP_CLK_SET_RATE_PARENT) ?
+					   CLK_SET_RATE_PARENT : 0;
+		topology[*nnodes].flag |= (flag & ZYNQMP_CLK_IGNORE_UNUSED) ?
+					  CLK_IGNORE_UNUSED : 0;
+		topology[*nnodes].flag |= (flag & ZYNQMP_CLK_GET_RATE_NOCACHE) ?
+					  CLK_GET_RATE_NOCACHE : 0;
+		topology[*nnodes].flag |= (flag &
+					   ZYNQMP_CLK_SET_RATE_NO_REPARENT) ?
+					   CLK_SET_RATE_NO_REPARENT : 0;
+		topology[*nnodes].flag |= (flag &
+					   ZYNQMP_CLK_GET_ACCURACY_NOCACHE) ?
+					   CLK_GET_ACCURACY_NOCACHE : 0;
+		topology[*nnodes].flag |= (flag & ZYNQMP_CLK_RECALC_NEW_RATES) ?
+					  CLK_RECALC_NEW_RATES : 0;
+		topology[*nnodes].flag |= (flag & ZYNQMP_CLK_SET_RATE_UNGATE) ?
+					  CLK_SET_RATE_UNGATE : 0;
+		topology[*nnodes].flag |= (flag & ZYNQMP_CLK_IS_CRITICAL) ?
+					  CLK_IS_CRITICAL : 0;
 		topology[*nnodes].type_flag =
 				FIELD_GET(CLK_TOPOLOGY_TYPE_FLAGS,
 					  response->topology[i]);
+		topology[*nnodes].custom_type_flag =
+			FIELD_GET(CLK_TOPOLOGY_CUSTOM_TYPE_FLAGS,
+				  response->topology[i]);
 		(*nnodes)++;
 	}
 
@@ -558,7 +583,7 @@
 {
 	int j;
 	u32 num_nodes, clk_dev_id;
-	char *clk_out = NULL;
+	char *clk_out[MAX_NODES];
 	struct clock_topology *nodes;
 	struct clk_hw *hw = NULL;
 
@@ -572,16 +597,16 @@
 		 * Intermediate clock names are postfixed with type of clock.
 		 */
 		if (j != (num_nodes - 1)) {
-			clk_out = kasprintf(GFP_KERNEL, "%s%s", clk_name,
+			clk_out[j] = kasprintf(GFP_KERNEL, "%s%s", clk_name,
 					    clk_type_postfix[nodes[j].type]);
 		} else {
-			clk_out = kasprintf(GFP_KERNEL, "%s", clk_name);
+			clk_out[j] = kasprintf(GFP_KERNEL, "%s", clk_name);
 		}
 
 		if (!clk_topology[nodes[j].type])
 			continue;
 
-		hw = (*clk_topology[nodes[j].type])(clk_out, clk_dev_id,
+		hw = (*clk_topology[nodes[j].type])(clk_out[j], clk_dev_id,
 						    parent_names,
 						    num_parents,
 						    &nodes[j]);
@@ -590,9 +615,12 @@
 				     __func__,  clk_dev_id, clk_name,
 				     PTR_ERR(hw));
 
-		parent_names[0] = clk_out;
+		parent_names[0] = clk_out[j];
 	}
-	kfree(clk_out);
+
+	for (j = 0; j < num_nodes; j++)
+		kfree(clk_out[j]);
+
 	return hw;
 }
 
@@ -663,6 +691,12 @@
 			continue;
 
 		clock[i].valid = FIELD_GET(CLK_ATTR_VALID, attr.attr[0]);
+
+		/* skip query for invalid clock */
+		ret = zynqmp_is_valid_clock(i);
+		if (ret != CLK_ATTR_VALID)
+			continue;
+
 		clock[i].type = FIELD_GET(CLK_ATTR_TYPE, attr.attr[0]) ?
 			CLK_TYPE_EXTERNAL : CLK_TYPE_OUTPUT;
 
@@ -676,6 +710,13 @@
 				  FIELD_PREP(CLK_ATTR_NODE_INDEX, i);
 
 		zynqmp_pm_clock_get_name(clock[i].clk_id, &name);
+
+		/*
+		 * Terminate with NULL character in case name provided by firmware
+		 * is longer and truncated due to size limit.
+		 */
+		name.name[sizeof(name.name) - 1] = '\0';
+
 		if (!strcmp(name.name, RESERVED_CLK_NAME))
 			continue;
 		strncpy(clock[i].clk_name, name.name, MAX_NAME_LEN);
@@ -728,9 +769,7 @@
 	zynqmp_register_clocks(np);
 
 	zynqmp_data->num = clock_max_idx;
-	of_clk_add_hw_provider(np, of_clk_hw_onecell_get, zynqmp_data);
-
-	return 0;
+	return of_clk_add_hw_provider(np, of_clk_hw_onecell_get, zynqmp_data);
 }
 
 static int zynqmp_clock_probe(struct platform_device *pdev)
@@ -749,6 +788,7 @@
 
 static const struct of_device_id zynqmp_clock_of_match[] = {
 	{.compatible = "xlnx,zynqmp-clk"},
+	{.compatible = "xlnx,versal-clk"},
 	{},
 };
 MODULE_DEVICE_TABLE(of, zynqmp_clock_of_match);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/zynqmp/divider.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/zynqmp/divider.c
@@ -2,7 +2,7 @@
 /*
  * Zynq UltraScale+ MPSoC Divider support
  *
- *  Copyright (C) 2016-2018 Xilinx
+ *  Copyright (C) 2016-2020 Xilinx
  *
  * Adjustable divider clock implementation
  */
@@ -25,7 +25,8 @@
 #define to_zynqmp_clk_divider(_hw)		\
 	container_of(_hw, struct zynqmp_clk_divider, hw)
 
-#define CLK_FRAC	BIT(13) /* has a fractional parent */
+#define CLK_FRAC		BIT(13) /* has a fractional parent */
+#define CUSTOM_FLAG_CLK_FRAC	BIT(0) /* has a fractional parent in custom type flag */
 
 /**
  * struct zynqmp_clk_divider - adjustable divider clock
@@ -34,19 +35,38 @@
  * @is_frac:	The divider is a fractional divider
  * @clk_id:	Id of clock
  * @div_type:	divisor type (TYPE_DIV1 or TYPE_DIV2)
+ * @max_div:	Maximum divisor value allowed
  */
 struct zynqmp_clk_divider {
 	struct clk_hw hw;
-	u8 flags;
+	u16 flags;
 	bool is_frac;
 	u32 clk_id;
 	u32 div_type;
+	u16 max_div;
 };
 
 static inline int zynqmp_divider_get_val(unsigned long parent_rate,
-					 unsigned long rate)
+					 unsigned long rate, u16 flags)
 {
-	return DIV_ROUND_CLOSEST(parent_rate, rate);
+	int up, down;
+	unsigned long up_rate, down_rate;
+
+	if (flags & CLK_DIVIDER_POWER_OF_TWO) {
+		up = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
+		down = DIV_ROUND_DOWN_ULL((u64)parent_rate, rate);
+
+		up = __roundup_pow_of_two(up);
+		down = __rounddown_pow_of_two(down);
+
+		up_rate = DIV_ROUND_UP_ULL((u64)parent_rate, up);
+		down_rate = DIV_ROUND_UP_ULL((u64)parent_rate, down);
+
+		return (rate - up_rate) <= (down_rate - rate) ? up : down;
+
+	} else {
+		return DIV_ROUND_CLOSEST(parent_rate, rate);
+	}
 }
 
 /**
@@ -78,6 +98,9 @@
 	else
 		value = div >> 16;
 
+	if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
+		value = 1 << value;
+
 	if (!value) {
 		WARN(!(divider->flags & CLK_DIVIDER_ALLOW_ZERO),
 		     "%s: Zero divisor and CLK_DIVIDER_ALLOW_ZERO not set\n",
@@ -88,6 +111,52 @@
 	return DIV_ROUND_UP_ULL(parent_rate, value);
 }
 
+static void zynqmp_get_divider2_val(struct clk_hw *hw,
+				    unsigned long rate,
+				    struct zynqmp_clk_divider *divider,
+				    u32 *bestdiv)
+{
+	int div1;
+	int div2;
+	long error = LONG_MAX;
+	unsigned long div1_prate;
+	struct clk_hw *div1_parent_hw;
+	struct zynqmp_clk_divider *pdivider;
+	struct clk_hw *div2_parent_hw = clk_hw_get_parent(hw);
+
+	if (!div2_parent_hw)
+		return;
+
+	pdivider = to_zynqmp_clk_divider(div2_parent_hw);
+	if (!pdivider)
+		return;
+
+	div1_parent_hw = clk_hw_get_parent(div2_parent_hw);
+	if (!div1_parent_hw)
+		return;
+
+	div1_prate = clk_hw_get_rate(div1_parent_hw);
+	*bestdiv = 1;
+	for (div1 = 1; div1 <= pdivider->max_div;) {
+		for (div2 = 1; div2 <= divider->max_div;) {
+			long new_error = ((div1_prate / div1) / div2) - rate;
+
+			if (abs(new_error) < abs(error)) {
+				*bestdiv = div2;
+				error = new_error;
+			}
+			if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
+				div2 = div2 << 1;
+			else
+				div2++;
+		}
+		if (pdivider->flags & CLK_DIVIDER_POWER_OF_TWO)
+			div1 = div1 << 1;
+		else
+			div1++;
+	}
+}
+
 /**
  * zynqmp_clk_divider_round_rate() - Round rate of divider clock
  * @hw:			handle between common and hardware-specific interfaces
@@ -120,13 +189,28 @@
 		else
 			bestdiv  = bestdiv >> 16;
 
+		if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
+			bestdiv = 1 << bestdiv;
+
 		return DIV_ROUND_UP_ULL((u64)*prate, bestdiv);
 	}
 
-	bestdiv = zynqmp_divider_get_val(*prate, rate);
+	bestdiv = zynqmp_divider_get_val(*prate, rate, divider->flags);
+
+	/*
+	 * In case of two divisors, compute best divider values and return
+	 * divider2 value based on compute value. div1 will  be automatically
+	 * set to optimum based on required total divider value.
+	 */
+	if (div_type == TYPE_DIV2 &&
+	    (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) {
+		zynqmp_get_divider2_val(hw, rate, divider, &bestdiv);
+	}
 
 	if ((clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) && divider->is_frac)
 		bestdiv = rate % *prate ? 1 : bestdiv;
+
+	bestdiv = min_t(u32, bestdiv, divider->max_div);
 	*prate = rate * bestdiv;
 
 	return rate;
@@ -151,7 +235,7 @@
 	int ret;
 	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
 
-	value = zynqmp_divider_get_val(parent_rate, rate);
+	value = zynqmp_divider_get_val(parent_rate, rate, divider->flags);
 	if (div_type == TYPE_DIV1) {
 		div = value & 0xFFFF;
 		div |= 0xffff << 16;
@@ -160,6 +244,9 @@
 		div |= value << 16;
 	}
 
+	if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
+		div = __ffs(div);
+
 	ret = eemi_ops->clock_setdivider(clk_id, div);
 
 	if (ret)
@@ -175,6 +262,40 @@
 	.set_rate = zynqmp_clk_divider_set_rate,
 };
 
+static const struct clk_ops zynqmp_clk_divider_ro_ops = {
+	.recalc_rate = zynqmp_clk_divider_recalc_rate,
+	.round_rate = zynqmp_clk_divider_round_rate,
+};
+
+/**
+ * zynqmp_clk_get_max_divisor() - Get maximum supported divisor from firmware.
+ * @clk_id:		Id of clock
+ * @type:		Divider type
+ *
+ * Return: Maximum divisor of a clock if query data is successful
+ *	   U16_MAX in case of query data is not success
+ */
+static u32 zynqmp_clk_get_max_divisor(u32 clk_id, u32 type)
+{
+	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
+	struct zynqmp_pm_query_data qdata = {0};
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	int ret;
+
+	qdata.qid = PM_QID_CLOCK_GET_MAX_DIVISOR;
+	qdata.arg1 = clk_id;
+	qdata.arg2 = type;
+	ret = eemi_ops->query_data(qdata, ret_payload);
+	/*
+	 * To maintain backward compatibility return maximum possible value
+	 * (0xFFFF) if query for max divisor is not successful.
+	 */
+	if (ret)
+		return U16_MAX;
+
+	return ret_payload[1];
+}
+
 /**
  * zynqmp_clk_register_divider() - Register a divider clock
  * @name:		Name of this clock
@@ -202,19 +323,43 @@
 		return ERR_PTR(-ENOMEM);
 
 	init.name = name;
-	init.ops = &zynqmp_clk_divider_ops;
+	if (nodes->type_flag & CLK_DIVIDER_READ_ONLY)
+		init.ops = &zynqmp_clk_divider_ro_ops;
+	else
+		init.ops = &zynqmp_clk_divider_ops;
 	/* CLK_FRAC is not defined in the common clk framework */
 	init.flags = nodes->flag & ~CLK_FRAC;
 	init.parent_names = parents;
 	init.num_parents = 1;
 
 	/* struct clk_divider assignments */
-	div->is_frac = !!(nodes->flag & CLK_FRAC);
-	div->flags = nodes->type_flag;
+	div->is_frac = !!((nodes->flag & CLK_FRAC) |
+			  (nodes->custom_type_flag & CUSTOM_FLAG_CLK_FRAC));
+	div->flags = 0;
+	div->flags |= (nodes->type_flag & ZYNQMP_CLK_DIVIDER_ONE_BASED) ?
+		      CLK_DIVIDER_ONE_BASED : 0;
+	div->flags |= (nodes->type_flag & ZYNQMP_CLK_DIVIDER_POWER_OF_TWO) ?
+		      CLK_DIVIDER_POWER_OF_TWO : 0;
+	div->flags |= (nodes->type_flag & ZYNQMP_CLK_DIVIDER_ALLOW_ZERO) ?
+		      CLK_DIVIDER_ALLOW_ZERO : 0;
+	div->flags |= (nodes->type_flag & ZYNQMP_CLK_DIVIDER_POWER_OF_TWO) ?
+		      CLK_DIVIDER_HIWORD_MASK : 0;
+	div->flags |= (nodes->type_flag & ZYNQMP_CLK_DIVIDER_ROUND_CLOSEST) ?
+		      CLK_DIVIDER_ROUND_CLOSEST : 0;
+	div->flags |= (nodes->type_flag & ZYNQMP_CLK_DIVIDER_READ_ONLY) ?
+		      CLK_DIVIDER_READ_ONLY : 0;
+	div->flags |= (nodes->type_flag & ZYNQMP_CLK_DIVIDER_MAX_AT_ZERO) ?
+		      CLK_DIVIDER_MAX_AT_ZERO : 0;
 	div->hw.init = &init;
 	div->clk_id = clk_id;
 	div->div_type = nodes->type;
 
+	/*
+	 * To achieve best possible rate, maximum limit of divider is required
+	 * while computation.
+	 */
+	div->max_div = zynqmp_clk_get_max_divisor(clk_id, nodes->type);
+
 	hw = &div->hw;
 	ret = clk_hw_register(NULL, hw);
 	if (ret) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clk/zynqmp/pll.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clk/zynqmp/pll.c
@@ -98,28 +98,25 @@
 				  unsigned long *prate)
 {
 	u32 fbdiv;
-	long rate_div, f;
+	u32 mult, div;
 
-	/* Enable the fractional mode if needed */
-	rate_div = (rate * FRAC_DIV) / *prate;
-	f = rate_div % FRAC_DIV;
-	zynqmp_pll_set_mode(hw, !!f);
-
-	if (zynqmp_pll_get_mode(hw) == PLL_MODE_FRAC) {
-		if (rate > PS_PLL_VCO_MAX) {
-			fbdiv = rate / PS_PLL_VCO_MAX;
-			rate = rate / (fbdiv + 1);
-		}
-		if (rate < PS_PLL_VCO_MIN) {
-			fbdiv = DIV_ROUND_UP(PS_PLL_VCO_MIN, rate);
-			rate = rate * fbdiv;
-		}
-		return rate;
+	/* Let rate fall inside the range PS_PLL_VCO_MIN ~ PS_PLL_VCO_MAX */
+	if (rate > PS_PLL_VCO_MAX) {
+		div = DIV_ROUND_UP(rate, PS_PLL_VCO_MAX);
+		rate = rate / div;
+	}
+	if (rate < PS_PLL_VCO_MIN) {
+		mult = DIV_ROUND_UP(PS_PLL_VCO_MIN, rate);
+		rate = rate * mult;
 	}
 
 	fbdiv = DIV_ROUND_CLOSEST(rate, *prate);
-	fbdiv = clamp_t(u32, fbdiv, PLL_FBDIV_MIN, PLL_FBDIV_MAX);
-	return *prate * fbdiv;
+	if (fbdiv < PLL_FBDIV_MIN || fbdiv > PLL_FBDIV_MAX) {
+		fbdiv = clamp_t(u32, fbdiv, PLL_FBDIV_MIN, PLL_FBDIV_MAX);
+		rate = *prate * fbdiv;
+	}
+
+	return rate;
 }
 
 /**
@@ -179,18 +176,23 @@
 	int ret;
 	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
 
-	if (zynqmp_pll_get_mode(hw) == PLL_MODE_FRAC) {
-		rate_div = (rate * FRAC_DIV) / parent_rate;
+	rate_div = (rate * FRAC_DIV) / parent_rate;
+	f = rate_div % FRAC_DIV;
+	zynqmp_pll_set_mode(hw, !!f);
+
+	if (f) {
 		m = rate_div / FRAC_DIV;
-		f = rate_div % FRAC_DIV;
 		m = clamp_t(u32, m, (PLL_FBDIV_MIN), (PLL_FBDIV_MAX));
 		rate = parent_rate * m;
 		frac = (parent_rate * f) / FRAC_DIV;
 
 		ret = eemi_ops->clock_setdivider(clk_id, m);
-		if (ret)
-			pr_warn_once("%s() set divider failed for %s, ret = %d\n",
-				     __func__, clk_name, ret);
+		if (ret) {
+			if (ret == -EUSERS)
+				WARN(1, "More than allowed devices are using the %s, which is forbidden\n", clk_name);
+			pr_err("%s() set divider failed for %s, ret = %d\n",
+			       __func__, clk_name, ret);
+		}
 
 		eemi_ops->ioctl(0, IOCTL_SET_PLL_FRAC_DATA, clk_id, f, NULL);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clocksource/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/clocksource/Kconfig
@@ -24,6 +24,7 @@
 
 config OMAP_DM_TIMER
 	bool
+	select TIMER_OF
 
 config CLKBLD_I8253
 	def_bool y if CLKSRC_I8253 || CLKEVT_I8253 || I8253_LOCK
@@ -79,6 +80,7 @@
 	bool "Intel XScale IXP4xx timer driver" if COMPILE_TEST
 	depends on HAS_IOMEM
 	select CLKSRC_MMIO
+	select TIMER_OF if OF
 	help
 	  Enables support for the Intel XScale IXP4xx SoC timer.
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clocksource/acpi_pm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clocksource/acpi_pm.c
@@ -229,8 +229,10 @@
 	int ret;
 
 	ret = kstrtouint(arg, 16, &base);
-	if (ret)
-		return ret;
+	if (ret) {
+		pr_warn("PMTMR: invalid 'pmtmr=' value: '%s'\n", arg);
+		return 1;
+	}
 
 	pr_info("PMTMR IOPort override: 0x%04x -> 0x%04x\n", pmtmr_ioport,
 		base);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clocksource/arm_arch_timer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clocksource/arm_arch_timer.c
@@ -69,7 +69,7 @@
 static bool arch_timer_c3stop;
 static bool arch_timer_mem_use_virtual;
 static bool arch_counter_suspend_stop;
-static bool vdso_default = true;
+static enum vdso_arch_clockmode vdso_default = VDSO_CLOCKMODE_ARCHTIMER;
 
 static cpumask_t evtstrm_available = CPU_MASK_NONE;
 static bool evtstrm_enable = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM);
@@ -348,7 +348,7 @@
 	do {								\
 		_val = read_sysreg(reg);				\
 		_retries--;						\
-	} while (((_val + 1) & GENMASK(9, 0)) <= 1 && _retries);	\
+	} while (((_val + 1) & GENMASK(8, 0)) <= 1 && _retries);	\
 									\
 	WARN_ON_ONCE(!_retries);					\
 	_val;								\
@@ -392,10 +392,10 @@
 	ctrl &= ~ARCH_TIMER_CTRL_IT_MASK;
 
 	if (access == ARCH_TIMER_PHYS_ACCESS) {
-		cval = evt + arch_counter_get_cntpct();
+		cval = evt + arch_counter_get_cntpct_stable();
 		write_sysreg(cval, cntp_cval_el0);
 	} else {
-		cval = evt + arch_counter_get_cntvct();
+		cval = evt + arch_counter_get_cntvct_stable();
 		write_sysreg(cval, cntv_cval_el0);
 	}
 
@@ -476,6 +476,14 @@
 		.set_next_event_virt = erratum_set_next_event_tval_virt,
 	},
 #endif
+#ifdef CONFIG_ARM64_ERRATUM_1418040
+	{
+		.match_type = ate_match_local_cap_id,
+		.id = (void *)ARM64_WORKAROUND_1418040,
+		.desc = "ARM erratum 1418040",
+		.disable_compat_vdso = true,
+	},
+#endif
 };
 
 typedef bool (*ate_match_fn_t)(const struct arch_timer_erratum_workaround *,
@@ -560,8 +568,11 @@
 	 * change both the default value and the vdso itself.
 	 */
 	if (wa->read_cntvct_el0) {
-		clocksource_counter.archdata.vdso_direct = false;
-		vdso_default = false;
+		clocksource_counter.archdata.clock_mode = VDSO_CLOCKMODE_NONE;
+		vdso_default = VDSO_CLOCKMODE_NONE;
+	} else if (wa->disable_compat_vdso && vdso_default != VDSO_CLOCKMODE_NONE) {
+		vdso_default = VDSO_CLOCKMODE_ARCHTIMER_NOCOMPAT;
+		clocksource_counter.archdata.clock_mode = vdso_default;
 	}
 }
 
@@ -664,8 +675,8 @@
 	return timer_handler(ARCH_TIMER_MEM_VIRT_ACCESS, evt);
 }
 
-static __always_inline int timer_shutdown(const int access,
-					  struct clock_event_device *clk)
+static __always_inline int arch_timer_shutdown(const int access,
+					       struct clock_event_device *clk)
 {
 	unsigned long ctrl;
 
@@ -678,22 +689,22 @@
 
 static int arch_timer_shutdown_virt(struct clock_event_device *clk)
 {
-	return timer_shutdown(ARCH_TIMER_VIRT_ACCESS, clk);
+	return arch_timer_shutdown(ARCH_TIMER_VIRT_ACCESS, clk);
 }
 
 static int arch_timer_shutdown_phys(struct clock_event_device *clk)
 {
-	return timer_shutdown(ARCH_TIMER_PHYS_ACCESS, clk);
+	return arch_timer_shutdown(ARCH_TIMER_PHYS_ACCESS, clk);
 }
 
 static int arch_timer_shutdown_virt_mem(struct clock_event_device *clk)
 {
-	return timer_shutdown(ARCH_TIMER_MEM_VIRT_ACCESS, clk);
+	return arch_timer_shutdown(ARCH_TIMER_MEM_VIRT_ACCESS, clk);
 }
 
 static int arch_timer_shutdown_phys_mem(struct clock_event_device *clk)
 {
-	return timer_shutdown(ARCH_TIMER_MEM_PHYS_ACCESS, clk);
+	return arch_timer_shutdown(ARCH_TIMER_MEM_PHYS_ACCESS, clk);
 }
 
 static __always_inline void set_next_event(const int access, unsigned long evt,
@@ -807,15 +818,24 @@
 
 static void arch_timer_configure_evtstream(void)
 {
-	int evt_stream_div, pos;
+	int evt_stream_div, lsb;
+
+	/*
+	 * As the event stream can at most be generated at half the frequency
+	 * of the counter, use half the frequency when computing the divider.
+	 */
+	evt_stream_div = arch_timer_rate / ARCH_TIMER_EVT_STREAM_FREQ / 2;
+
+	/*
+	 * Find the closest power of two to the divisor. If the adjacent bit
+	 * of lsb (last set bit, starts from 0) is set, then we use (lsb + 1).
+	 */
+	lsb = fls(evt_stream_div) - 1;
+	if (lsb > 0 && (evt_stream_div & BIT(lsb - 1)))
+		lsb++;
 
-	/* Find the closest power of two to the divisor */
-	evt_stream_div = arch_timer_rate / ARCH_TIMER_EVT_STREAM_FREQ;
-	pos = fls(evt_stream_div);
-	if (pos > 1 && !(evt_stream_div & (1 << (pos - 2))))
-		pos--;
 	/* enable event stream */
-	arch_timer_evtstrm_enable(min(pos, 15));
+	arch_timer_evtstrm_enable(max(0, min(lsb, 15)));
 }
 
 static void arch_counter_set_user_access(void)
@@ -979,7 +999,7 @@
 		}
 
 		arch_timer_read_counter = rd;
-		clocksource_counter.archdata.vdso_direct = vdso_default;
+		clocksource_counter.archdata.clock_mode = vdso_default;
 	} else {
 		arch_timer_read_counter = arch_counter_get_cntvct_mem;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clocksource/asm9260_timer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clocksource/asm9260_timer.c
@@ -194,6 +194,10 @@
 	}
 
 	clk = of_clk_get(np, 0);
+	if (IS_ERR(clk)) {
+		pr_err("Failed to get clk!\n");
+		return PTR_ERR(clk);
+	}
 
 	ret = clk_prepare_enable(clk);
 	if (ret) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clocksource/bcm2835_timer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clocksource/bcm2835_timer.c
@@ -121,7 +121,7 @@
 	ret = setup_irq(irq, &timer->act);
 	if (ret) {
 		pr_err("Can't set up timer IRQ\n");
-		goto err_iounmap;
+		goto err_timer_free;
 	}
 
 	clockevents_config_and_register(&timer->evt, freq, 0xf, 0xffffffff);
@@ -130,6 +130,9 @@
 
 	return 0;
 
+err_timer_free:
+	kfree(timer);
+
 err_iounmap:
 	iounmap(base);
 	return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clocksource/dw_apb_timer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clocksource/dw_apb_timer.c
@@ -222,7 +222,8 @@
 /**
  * dw_apb_clockevent_init() - use an APB timer as a clock_event_device
  *
- * @cpu:	The CPU the events will be targeted at.
+ * @cpu:	The CPU the events will be targeted at or -1 if CPU affiliation
+ *		isn't required.
  * @name:	The name used for the timer and the IRQ for it.
  * @rating:	The rating to give the timer.
  * @base:	I/O base for the timer registers.
@@ -257,7 +258,7 @@
 	dw_ced->ced.max_delta_ticks = 0x7fffffff;
 	dw_ced->ced.min_delta_ns = clockevent_delta2ns(5000, &dw_ced->ced);
 	dw_ced->ced.min_delta_ticks = 5000;
-	dw_ced->ced.cpumask = cpumask_of(cpu);
+	dw_ced->ced.cpumask = cpu < 0 ? cpu_possible_mask : cpumask_of(cpu);
 	dw_ced->ced.features = CLOCK_EVT_FEAT_PERIODIC |
 				CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_DYNIRQ;
 	dw_ced->ced.set_state_shutdown = apbt_shutdown;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clocksource/dw_apb_timer_of.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clocksource/dw_apb_timer_of.c
@@ -147,10 +147,6 @@
 static int __init dw_apb_timer_init(struct device_node *timer)
 {
 	switch (num_called) {
-	case 0:
-		pr_debug("%s: found clockevent timer\n", __func__);
-		add_clockevent(timer);
-		break;
 	case 1:
 		pr_debug("%s: found clocksource timer\n", __func__);
 		add_clocksource(timer);
@@ -161,6 +157,8 @@
 #endif
 		break;
 	default:
+		pr_debug("%s: found clockevent timer\n", __func__);
+		add_clockevent(timer);
 		break;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clocksource/h8300_timer8.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clocksource/h8300_timer8.c
@@ -169,7 +169,7 @@
 		return PTR_ERR(clk);
 	}
 
-	ret = ENXIO;
+	ret = -ENXIO;
 	base = of_iomap(node, 0);
 	if (!base) {
 		pr_err("failed to map registers for clockevent\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clocksource/hyperv_timer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clocksource/hyperv_timer.c
@@ -233,7 +233,8 @@
 
 static u64 read_hv_sched_clock_tsc(void)
 {
-	return read_hv_clock_tsc(NULL) - hv_sched_clock_offset;
+	return (read_hv_clock_tsc(NULL) - hv_sched_clock_offset) *
+		(NSEC_PER_SEC / HV_CLOCK_HZ);
 }
 
 static struct clocksource hyperv_cs_tsc = {
@@ -258,7 +259,8 @@
 
 static u64 read_hv_sched_clock_msr(void)
 {
-	return read_hv_clock_msr(NULL) - hv_sched_clock_offset;
+	return (read_hv_clock_msr(NULL) - hv_sched_clock_offset) *
+		(NSEC_PER_SEC / HV_CLOCK_HZ);
 }
 
 static struct clocksource hyperv_cs_msr = {
@@ -323,4 +325,3 @@
 	hv_sched_clock_offset = hyperv_cs->read(hyperv_cs);
 	hv_setup_sched_clock(read_hv_sched_clock_msr);
 }
-EXPORT_SYMBOL_GPL(hv_init_clocksource);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clocksource/i8253.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clocksource/i8253.c
@@ -20,13 +20,6 @@
 DEFINE_RAW_SPINLOCK(i8253_lock);
 EXPORT_SYMBOL(i8253_lock);
 
-/*
- * Handle PIT quirk in pit_shutdown() where zeroing the counter register
- * restarts the PIT, negating the shutdown. On platforms with the quirk,
- * platform specific code can set this to false.
- */
-bool i8253_clear_counter_on_shutdown __ro_after_init = true;
-
 #ifdef CONFIG_CLKSRC_I8253
 /*
  * Since the PIT overflows every tick, its not very useful
@@ -108,21 +101,47 @@
 #endif
 
 #ifdef CONFIG_CLKEVT_I8253
-static int pit_shutdown(struct clock_event_device *evt)
+void clockevent_i8253_disable(void)
 {
-	if (!clockevent_state_oneshot(evt) && !clockevent_state_periodic(evt))
-		return 0;
-
 	raw_spin_lock(&i8253_lock);
 
+	/*
+	 * Writing the MODE register should stop the counter, according to
+	 * the datasheet. This appears to work on real hardware (well, on
+	 * modern Intel and AMD boxes; I didn't dig the Pegasos out of the
+	 * shed).
+	 *
+	 * However, some virtual implementations differ, and the MODE change
+	 * doesn't have any effect until either the counter is written (KVM
+	 * in-kernel PIT) or the next interrupt (QEMU). And in those cases,
+	 * it may not stop the *count*, only the interrupts. Although in
+	 * the virt case, that probably doesn't matter, as the value of the
+	 * counter will only be calculated on demand if the guest reads it;
+	 * it's the interrupts which cause steal time.
+	 *
+	 * Hyper-V apparently has a bug where even in mode 0, the IRQ keeps
+	 * firing repeatedly if the counter is running. But it *does* do the
+	 * right thing when the MODE register is written.
+	 *
+	 * So: write the MODE and then load the counter, which ensures that
+	 * the IRQ is stopped on those buggy virt implementations. And then
+	 * write the MODE again, which is the right way to stop it.
+	 */
 	outb_p(0x30, PIT_MODE);
+	outb_p(0, PIT_CH0);
+	outb_p(0, PIT_CH0);
 
-	if (i8253_clear_counter_on_shutdown) {
-		outb_p(0, PIT_CH0);
-		outb_p(0, PIT_CH0);
-	}
+	outb_p(0x30, PIT_MODE);
 
 	raw_spin_unlock(&i8253_lock);
+}
+
+static int pit_shutdown(struct clock_event_device *evt)
+{
+	if (!clockevent_state_oneshot(evt) && !clockevent_state_periodic(evt))
+		return 0;
+
+	clockevent_i8253_disable();
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clocksource/mxs_timer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clocksource/mxs_timer.c
@@ -138,10 +138,7 @@
 
 	/* Clear pending interrupt */
 	timrot_irq_acknowledge();
-
-#ifdef DEBUG
-	pr_info("%s: changing mode to %s\n", __func__, state)
-#endif /* DEBUG */
+	pr_debug("%s: changing mode to %s\n", __func__, state);
 }
 
 static int mxs_shutdown(struct clock_event_device *evt)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clocksource/sh_cmt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clocksource/sh_cmt.c
@@ -231,6 +231,8 @@
 #define CMCNT 1 /* channel register */
 #define CMCOR 2 /* channel register */
 
+#define CMCLKE	0x1000	/* CLK Enable Register (R-Car Gen2) */
+
 static inline u32 sh_cmt_read_cmstr(struct sh_cmt_channel *ch)
 {
 	if (ch->iostart)
@@ -508,6 +510,7 @@
 static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id)
 {
 	struct sh_cmt_channel *ch = dev_id;
+	unsigned long flags;
 
 	/* clear flags */
 	sh_cmt_write_cmcsr(ch, sh_cmt_read_cmcsr(ch) &
@@ -538,6 +541,8 @@
 
 	ch->flags &= ~FLAG_SKIPEVENT;
 
+	raw_spin_lock_irqsave(&ch->lock, flags);
+
 	if (ch->flags & FLAG_REPROGRAM) {
 		ch->flags &= ~FLAG_REPROGRAM;
 		sh_cmt_clock_event_program_verify(ch, 1);
@@ -550,6 +555,8 @@
 
 	ch->flags &= ~FLAG_IRQCONTEXT;
 
+	raw_spin_unlock_irqrestore(&ch->lock, flags);
+
 	return IRQ_HANDLED;
 }
 
@@ -568,7 +575,8 @@
 	ch->flags |= flag;
 
 	/* setup timeout if no clockevent */
-	if ((flag == FLAG_CLOCKSOURCE) && (!(ch->flags & FLAG_CLOCKEVENT)))
+	if (ch->cmt->num_channels == 1 &&
+	    flag == FLAG_CLOCKSOURCE && (!(ch->flags & FLAG_CLOCKEVENT)))
 		__sh_cmt_set_next(ch, ch->max_match_value);
  out:
 	raw_spin_unlock_irqrestore(&ch->lock, flags);
@@ -604,20 +612,25 @@
 static u64 sh_cmt_clocksource_read(struct clocksource *cs)
 {
 	struct sh_cmt_channel *ch = cs_to_sh_cmt(cs);
-	unsigned long flags;
 	u32 has_wrapped;
-	u64 value;
-	u32 raw;
 
-	raw_spin_lock_irqsave(&ch->lock, flags);
-	value = ch->total_cycles;
-	raw = sh_cmt_get_counter(ch, &has_wrapped);
+	if (ch->cmt->num_channels == 1) {
+		unsigned long flags;
+		u64 value;
+		u32 raw;
 
-	if (unlikely(has_wrapped))
-		raw += ch->match_value + 1;
-	raw_spin_unlock_irqrestore(&ch->lock, flags);
+		raw_spin_lock_irqsave(&ch->lock, flags);
+		value = ch->total_cycles;
+		raw = sh_cmt_get_counter(ch, &has_wrapped);
+
+		if (unlikely(has_wrapped))
+			raw += ch->match_value + 1;
+		raw_spin_unlock_irqrestore(&ch->lock, flags);
 
-	return value + raw;
+		return value + raw;
+	}
+
+	return sh_cmt_get_counter(ch, &has_wrapped);
 }
 
 static int sh_cmt_clocksource_enable(struct clocksource *cs)
@@ -680,7 +693,7 @@
 	cs->disable = sh_cmt_clocksource_disable;
 	cs->suspend = sh_cmt_clocksource_suspend;
 	cs->resume = sh_cmt_clocksource_resume;
-	cs->mask = CLOCKSOURCE_MASK(sizeof(u64) * 8);
+	cs->mask = CLOCKSOURCE_MASK(ch->cmt->info->width);
 	cs->flags = CLOCK_SOURCE_IS_CONTINUOUS;
 
 	dev_info(&ch->cmt->pdev->dev, "ch%u: used as clock source\n",
@@ -742,12 +755,18 @@
 				   struct clock_event_device *ced)
 {
 	struct sh_cmt_channel *ch = ced_to_sh_cmt(ced);
+	unsigned long flags;
 
 	BUG_ON(!clockevent_state_oneshot(ced));
+
+	raw_spin_lock_irqsave(&ch->lock, flags);
+
 	if (likely(ch->flags & FLAG_IRQCONTEXT))
 		ch->next_match_value = delta - 1;
 	else
-		sh_cmt_set_next(ch, delta - 1);
+		__sh_cmt_set_next(ch, delta - 1);
+
+	raw_spin_unlock_irqrestore(&ch->lock, flags);
 
 	return 0;
 }
@@ -839,6 +858,7 @@
 				unsigned int hwidx, bool clockevent,
 				bool clocksource, struct sh_cmt_device *cmt)
 {
+	u32 value;
 	int ret;
 
 	/* Skip unused channels. */
@@ -868,6 +888,11 @@
 		ch->iostart = cmt->mapbase + ch->hwidx * 0x100;
 		ch->ioctrl = ch->iostart + 0x10;
 		ch->timer_bit = 0;
+
+		/* Enable the clock supply to the channel */
+		value = ioread32(cmt->mapbase + CMCLKE);
+		value |= BIT(hwidx);
+		iowrite32(value, cmt->mapbase + CMCLKE);
 		break;
 	}
 
@@ -1000,12 +1025,10 @@
 	else
 		cmt->rate = clk_get_rate(cmt->clk) / 8;
 
-	clk_disable(cmt->clk);
-
 	/* Map the memory resource(s). */
 	ret = sh_cmt_map_memory(cmt);
 	if (ret < 0)
-		goto err_clk_unprepare;
+		goto err_clk_disable;
 
 	/* Allocate and setup the channels. */
 	cmt->num_channels = hweight8(cmt->hw_channels);
@@ -1033,6 +1056,8 @@
 		mask &= ~(1 << hwidx);
 	}
 
+	clk_disable(cmt->clk);
+
 	platform_set_drvdata(pdev, cmt);
 
 	return 0;
@@ -1040,6 +1065,8 @@
 err_unmap:
 	kfree(cmt->channels);
 	iounmap(cmt->mapbase);
+err_clk_disable:
+	clk_disable(cmt->clk);
 err_clk_unprepare:
 	clk_unprepare(cmt->clk);
 err_clk_put:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clocksource/timer-atmel-tcb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clocksource/timer-atmel-tcb.c
@@ -310,6 +310,7 @@
 	writel(mck_divisor_idx			/* likely divide-by-8 */
 			| ATMEL_TC_WAVE
 			| ATMEL_TC_WAVESEL_UP		/* free-run */
+			| ATMEL_TC_ASWTRG_SET		/* TIOA0 rises at software trigger */
 			| ATMEL_TC_ACPA_SET		/* TIOA0 rises at 0 */
 			| ATMEL_TC_ACPC_CLEAR,		/* (duty cycle 50%) */
 			tcaddr + ATMEL_TC_REG(0, CMR));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clocksource/timer-cadence-ttc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clocksource/timer-cadence-ttc.c
@@ -15,6 +15,8 @@
 #include <linux/of_irq.h>
 #include <linux/slab.h>
 #include <linux/sched_clock.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
 
 /*
  * This driver configures the 2 16/32-bit count-up timers as follows:
@@ -411,10 +413,8 @@
 	ttcce->ttc.clk = clk;
 
 	err = clk_prepare_enable(ttcce->ttc.clk);
-	if (err) {
-		kfree(ttcce);
-		return err;
-	}
+	if (err)
+		goto out_kfree;
 
 	ttcce->ttc.clk_rate_change_nb.notifier_call =
 		ttc_rate_change_clockevent_cb;
@@ -424,7 +424,7 @@
 				    &ttcce->ttc.clk_rate_change_nb);
 	if (err) {
 		pr_warn("Unable to register clock notifier.\n");
-		return err;
+		goto out_kfree;
 	}
 
 	ttcce->ttc.freq = clk_get_rate(ttcce->ttc.clk);
@@ -453,24 +453,20 @@
 
 	err = request_irq(irq, ttc_clock_event_interrupt,
 			  IRQF_TIMER, ttcce->ce.name, ttcce);
-	if (err) {
-		kfree(ttcce);
-		return err;
-	}
+	if (err)
+		goto out_kfree;
 
 	clockevents_config_and_register(&ttcce->ce,
 			ttcce->ttc.freq / PRESCALE, 1, 0xfffe);
 
 	return 0;
+
+out_kfree:
+	kfree(ttcce);
+	return err;
 }
 
-/**
- * ttc_timer_init - Initialize the timer
- *
- * Initializes the timer hardware and register the clock source and clock event
- * timers with Linux kernal timer framework
- */
-static int __init ttc_timer_init(struct device_node *timer)
+static int __init ttc_timer_probe(struct platform_device *pdev)
 {
 	unsigned int irq;
 	void __iomem *timer_baseaddr;
@@ -478,6 +474,7 @@
 	static int initialized;
 	int clksel, ret;
 	u32 timer_width = 16;
+	struct device_node *timer = pdev->dev.of_node;
 
 	if (initialized)
 		return 0;
@@ -489,10 +486,10 @@
 	 * and use it. Note that the event timer uses the interrupt and it's the
 	 * 2nd TTC hence the irq_of_parse_and_map(,1)
 	 */
-	timer_baseaddr = of_iomap(timer, 0);
-	if (!timer_baseaddr) {
+	timer_baseaddr = devm_of_iomap(&pdev->dev, timer, 0, NULL);
+	if (IS_ERR(timer_baseaddr)) {
 		pr_err("ERROR: invalid timer base address\n");
-		return -ENXIO;
+		return PTR_ERR(timer_baseaddr);
 	}
 
 	irq = irq_of_parse_and_map(timer, 1);
@@ -516,20 +513,40 @@
 	clk_ce = of_clk_get(timer, clksel);
 	if (IS_ERR(clk_ce)) {
 		pr_err("ERROR: timer input clock not found\n");
-		return PTR_ERR(clk_ce);
+		ret = PTR_ERR(clk_ce);
+		goto put_clk_cs;
 	}
 
 	ret = ttc_setup_clocksource(clk_cs, timer_baseaddr, timer_width);
 	if (ret)
-		return ret;
+		goto put_clk_ce;
 
 	ret = ttc_setup_clockevent(clk_ce, timer_baseaddr + 4, irq);
 	if (ret)
-		return ret;
+		goto put_clk_ce;
 
 	pr_info("%pOFn #0 at %p, irq=%d\n", timer, timer_baseaddr, irq);
 
 	return 0;
+
+put_clk_ce:
+	clk_put(clk_ce);
+put_clk_cs:
+	clk_put(clk_cs);
+	return ret;
 }
 
-TIMER_OF_DECLARE(ttc, "cdns,ttc", ttc_timer_init);
+static const struct of_device_id ttc_timer_of_match[] = {
+	{.compatible = "cdns,ttc"},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, ttc_timer_of_match);
+
+static struct platform_driver ttc_timer_driver = {
+	.driver = {
+		.name	= "cdns_ttc_timer",
+		.of_match_table = ttc_timer_of_match,
+	},
+};
+builtin_platform_driver_probe(ttc_timer_driver, ttc_timer_probe);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clocksource/timer-davinci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clocksource/timer-davinci.c
@@ -18,7 +18,7 @@
 #include <clocksource/timer-davinci.h>
 
 #undef pr_fmt
-#define pr_fmt(fmt) "%s: " fmt "\n", __func__
+#define pr_fmt(fmt) "%s: " fmt, __func__
 
 #define DAVINCI_TIMER_REG_TIM12			0x10
 #define DAVINCI_TIMER_REG_TIM34			0x14
@@ -250,30 +250,32 @@
 
 	rv = clk_prepare_enable(clk);
 	if (rv) {
-		pr_err("Unable to prepare and enable the timer clock");
+		pr_err("Unable to prepare and enable the timer clock\n");
 		return rv;
 	}
 
 	if (!request_mem_region(timer_cfg->reg.start,
 				resource_size(&timer_cfg->reg),
 				"davinci-timer")) {
-		pr_err("Unable to request memory region");
-		return -EBUSY;
+		pr_err("Unable to request memory region\n");
+		rv = -EBUSY;
+		goto exit_clk_disable;
 	}
 
 	base = ioremap(timer_cfg->reg.start, resource_size(&timer_cfg->reg));
 	if (!base) {
-		pr_err("Unable to map the register range");
-		return -ENOMEM;
+		pr_err("Unable to map the register range\n");
+		rv = -ENOMEM;
+		goto exit_mem_region;
 	}
 
 	davinci_timer_init(base);
 	tick_rate = clk_get_rate(clk);
 
-	clockevent = kzalloc(sizeof(*clockevent), GFP_KERNEL | __GFP_NOFAIL);
+	clockevent = kzalloc(sizeof(*clockevent), GFP_KERNEL);
 	if (!clockevent) {
-		pr_err("Error allocating memory for clockevent data");
-		return -ENOMEM;
+		rv = -ENOMEM;
+		goto exit_iounmap_base;
 	}
 
 	clockevent->dev.name = "tim12";
@@ -298,14 +300,10 @@
 			 davinci_timer_irq_timer, IRQF_TIMER,
 			 "clockevent/tim12", clockevent);
 	if (rv) {
-		pr_err("Unable to request the clockevent interrupt");
-		return rv;
+		pr_err("Unable to request the clockevent interrupt\n");
+		goto exit_free_clockevent;
 	}
 
-	clockevents_config_and_register(&clockevent->dev, tick_rate,
-					DAVINCI_TIMER_MIN_DELTA,
-					DAVINCI_TIMER_MAX_DELTA);
-
 	davinci_clocksource.dev.rating = 300;
 	davinci_clocksource.dev.read = davinci_clocksource_read;
 	davinci_clocksource.dev.mask =
@@ -323,16 +321,34 @@
 		davinci_clocksource_init_tim34(base);
 	}
 
+	clockevents_config_and_register(&clockevent->dev, tick_rate,
+					DAVINCI_TIMER_MIN_DELTA,
+					DAVINCI_TIMER_MAX_DELTA);
+
 	rv = clocksource_register_hz(&davinci_clocksource.dev, tick_rate);
 	if (rv) {
-		pr_err("Unable to register clocksource");
-		return rv;
+		pr_err("Unable to register clocksource\n");
+		goto exit_free_irq;
 	}
 
 	sched_clock_register(davinci_timer_read_sched_clock,
 			     DAVINCI_TIMER_CLKSRC_BITS, tick_rate);
 
 	return 0;
+
+exit_free_irq:
+	free_irq(timer_cfg->irq[DAVINCI_TIMER_CLOCKEVENT_IRQ].start,
+			clockevent);
+exit_free_clockevent:
+	kfree(clockevent);
+exit_iounmap_base:
+	iounmap(base);
+exit_mem_region:
+	release_mem_region(timer_cfg->reg.start,
+			   resource_size(&timer_cfg->reg));
+exit_clk_disable:
+	clk_disable_unprepare(clk);
+	return rv;
 }
 
 static int __init of_davinci_timer_register(struct device_node *np)
@@ -343,20 +359,20 @@
 
 	rv = of_address_to_resource(np, 0, &timer_cfg.reg);
 	if (rv) {
-		pr_err("Unable to get the register range for timer");
+		pr_err("Unable to get the register range for timer\n");
 		return rv;
 	}
 
 	rv = of_irq_to_resource_table(np, timer_cfg.irq,
 				      DAVINCI_TIMER_NUM_IRQS);
 	if (rv != DAVINCI_TIMER_NUM_IRQS) {
-		pr_err("Unable to get the interrupts for timer");
+		pr_err("Unable to get the interrupts for timer\n");
 		return rv;
 	}
 
 	clk = of_clk_get(np, 0);
 	if (IS_ERR(clk)) {
-		pr_err("Unable to get the timer clock");
+		pr_err("Unable to get the timer clock\n");
 		return PTR_ERR(clk);
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clocksource/timer-gx6605s.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clocksource/timer-gx6605s.c
@@ -28,6 +28,7 @@
 	void __iomem *base = timer_of_base(to_timer_of(ce));
 
 	writel_relaxed(GX6605S_STATUS_CLR, base + TIMER_STATUS);
+	writel_relaxed(0, base + TIMER_INI);
 
 	ce->event_handler(ce);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clocksource/timer-imx-gpt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clocksource/timer-imx-gpt.c
@@ -460,12 +460,16 @@
 		return -ENOMEM;
 
 	imxtm->base = of_iomap(np, 0);
-	if (!imxtm->base)
-		return -ENXIO;
+	if (!imxtm->base) {
+		ret = -ENXIO;
+		goto err_kfree;
+	}
 
 	imxtm->irq = irq_of_parse_and_map(np, 0);
-	if (imxtm->irq <= 0)
-		return -EINVAL;
+	if (imxtm->irq <= 0) {
+		ret = -EINVAL;
+		goto err_kfree;
+	}
 
 	imxtm->clk_ipg = of_clk_get_by_name(np, "ipg");
 
@@ -478,11 +482,15 @@
 
 	ret = _mxc_timer_init(imxtm);
 	if (ret)
-		return ret;
+		goto err_kfree;
 
 	initialized = 1;
 
 	return 0;
+
+err_kfree:
+	kfree(imxtm);
+	return ret;
 }
 
 static int __init imx1_timer_init_dt(struct device_node *np)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clocksource/timer-imx-tpm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clocksource/timer-imx-tpm.c
@@ -83,20 +83,28 @@
 static int tpm_set_next_event(unsigned long delta,
 				struct clock_event_device *evt)
 {
-	unsigned long next, now;
+	unsigned long next, prev, now;
 
-	next = tpm_read_counter();
-	next += delta;
+	prev = tpm_read_counter();
+	next = prev + delta;
 	writel(next, timer_base + TPM_C0V);
 	now = tpm_read_counter();
 
 	/*
+	 * Need to wait CNT increase at least 1 cycle to make sure
+	 * the C0V has been updated into HW.
+	 */
+	if ((next & 0xffffffff) != readl(timer_base + TPM_C0V))
+		while (now == tpm_read_counter())
+			;
+
+	/*
 	 * NOTE: We observed in a very small probability, the bus fabric
 	 * contention between GPU and A7 may results a few cycles delay
 	 * of writing CNT registers which may cause the min_delta event got
 	 * missed, so we need add a ETIME check here in case it happened.
 	 */
-	return (int)(next - now) <= 0 ? -ETIME : 0;
+	return (now - prev) >= delta ? -ETIME : 0;
 }
 
 static int tpm_set_state_oneshot(struct clock_event_device *evt)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clocksource/timer-ixp4xx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clocksource/timer-ixp4xx.c
@@ -258,7 +258,6 @@
 	}
 	ixp4xx_timer_register(base, timer_irq, timer_freq);
 }
-EXPORT_SYMBOL_GPL(ixp4xx_timer_setup);
 
 #ifdef CONFIG_OF
 static __init int ixp4xx_of_timer_init(struct device_node *np)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clocksource/timer-of.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clocksource/timer-of.c
@@ -25,10 +25,7 @@
 
 	struct clock_event_device *clkevt = &to->clkevt;
 
-	if (of_irq->percpu)
-		free_percpu_irq(of_irq->irq, clkevt);
-	else
-		free_irq(of_irq->irq, clkevt);
+	free_irq(of_irq->irq, clkevt);
 }
 
 /**
@@ -42,9 +39,6 @@
  * - Get interrupt number by name
  * - Get interrupt number by index
  *
- * When the interrupt is per CPU, 'request_percpu_irq()' is called,
- * otherwise 'request_irq()' is used.
- *
  * Returns 0 on success, < 0 otherwise
  */
 static __init int timer_of_irq_init(struct device_node *np,
@@ -69,12 +63,9 @@
 		return -EINVAL;
 	}
 
-	ret = of_irq->percpu ?
-		request_percpu_irq(of_irq->irq, of_irq->handler,
-				   np->full_name, clkevt) :
-		request_irq(of_irq->irq, of_irq->handler,
-			    of_irq->flags ? of_irq->flags : IRQF_TIMER,
-			    np->full_name, clkevt);
+	ret = request_irq(of_irq->irq, of_irq->handler,
+			  of_irq->flags ? of_irq->flags : IRQF_TIMER,
+			  np->full_name, clkevt);
 	if (ret) {
 		pr_err("Failed to request irq %d for %pOF\n", of_irq->irq, np);
 		return ret;
@@ -157,9 +148,9 @@
 	of_base->base = of_base->name ?
 		of_io_request_and_map(np, of_base->index, of_base->name) :
 		of_iomap(np, of_base->index);
-	if (IS_ERR(of_base->base)) {
-		pr_err("Failed to iomap (%s)\n", of_base->name);
-		return PTR_ERR(of_base->base);
+	if (IS_ERR_OR_NULL(of_base->base)) {
+		pr_err("Failed to iomap (%s:%s)\n", np->name, of_base->name);
+		return of_base->base ? PTR_ERR(of_base->base) : -ENOMEM;
 	}
 
 	return 0;
@@ -192,7 +183,7 @@
 	}
 
 	if (!to->clkevt.name)
-		to->clkevt.name = np->name;
+		to->clkevt.name = np->full_name;
 
 	to->np = np;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clocksource/timer-of.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/clocksource/timer-of.h
@@ -11,7 +11,6 @@
 struct of_timer_irq {
 	int irq;
 	int index;
-	int percpu;
 	const char *name;
 	unsigned long flags;
 	irq_handler_t handler;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clocksource/timer-orion.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clocksource/timer-orion.c
@@ -149,7 +149,8 @@
 	irq = irq_of_parse_and_map(np, 1);
 	if (irq <= 0) {
 		pr_err("%pOFn: unable to parse timer1 irq\n", np);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out_unprep_clk;
 	}
 
 	rate = clk_get_rate(clk);
@@ -166,7 +167,7 @@
 				    clocksource_mmio_readl_down);
 	if (ret) {
 		pr_err("Failed to initialize mmio timer\n");
-		return ret;
+		goto out_unprep_clk;
 	}
 
 	sched_clock_register(orion_read_sched_clock, 32, rate);
@@ -175,7 +176,7 @@
 	ret = setup_irq(irq, &orion_clkevt_irq);
 	if (ret) {
 		pr_err("%pOFn: unable to setup irq\n", np);
-		return ret;
+		goto out_unprep_clk;
 	}
 
 	ticks_per_jiffy = (clk_get_rate(clk) + HZ/2) / HZ;
@@ -188,5 +189,9 @@
 	orion_delay_timer_init(rate);
 
 	return 0;
+
+out_unprep_clk:
+	clk_disable_unprepare(clk);
+	return ret;
 }
 TIMER_OF_DECLARE(orion_timer, "marvell,orion-timer", orion_timer_init);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clocksource/timer-oxnas-rps.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clocksource/timer-oxnas-rps.c
@@ -236,7 +236,7 @@
 	}
 
 	rps->irq = irq_of_parse_and_map(np, 0);
-	if (rps->irq < 0) {
+	if (!rps->irq) {
 		ret = -EINVAL;
 		goto err_iomap;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clocksource/timer-qcom.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clocksource/timer-qcom.c
@@ -233,6 +233,7 @@
 	}
 
 	if (of_property_read_u32(np, "clock-frequency", &freq)) {
+		iounmap(cpu0_base);
 		pr_err("Unknown frequency\n");
 		return -EINVAL;
 	}
@@ -243,7 +244,11 @@
 	freq /= 4;
 	writel_relaxed(DGT_CLK_CTL_DIV_4, source_base + DGT_CLK_CTL);
 
-	return msm_timer_init(freq, 32, irq, !!percpu_offset);
+	ret = msm_timer_init(freq, 32, irq, !!percpu_offset);
+	if (ret)
+		iounmap(cpu0_base);
+
+	return ret;
 }
 TIMER_OF_DECLARE(kpss_timer, "qcom,kpss-timer", msm_dt_timer_init);
 TIMER_OF_DECLARE(scss_timer, "qcom,scss-timer", msm_dt_timer_init);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clocksource/timer-riscv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clocksource/timer-riscv.c
@@ -41,7 +41,7 @@
 	return get_cycles64();
 }
 
-static u64 riscv_sched_clock(void)
+static u64 notrace riscv_sched_clock(void)
 {
 	return get_cycles64();
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/clocksource/timer-sp804.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/clocksource/timer-sp804.c
@@ -122,14 +122,14 @@
 	return IRQ_HANDLED;
 }
 
-static inline void timer_shutdown(struct clock_event_device *evt)
+static inline void evt_timer_shutdown(struct clock_event_device *evt)
 {
 	writel(0, clkevt_base + TIMER_CTRL);
 }
 
 static int sp804_shutdown(struct clock_event_device *evt)
 {
-	timer_shutdown(evt);
+	evt_timer_shutdown(evt);
 	return 0;
 }
 
@@ -138,7 +138,7 @@
 	unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE |
 			     TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE;
 
-	timer_shutdown(evt);
+	evt_timer_shutdown(evt);
 	writel(clkevt_reload, clkevt_base + TIMER_LOAD);
 	writel(ctrl, clkevt_base + TIMER_CTRL);
 	return 0;
@@ -215,6 +215,11 @@
 	struct clk *clk1, *clk2;
 	const char *name = of_get_property(np, "compatible", NULL);
 
+	if (initialized) {
+		pr_debug("%pOF: skipping further SP804 timer device\n", np);
+		return 0;
+	}
+
 	base = of_iomap(np, 0);
 	if (!base)
 		return -ENXIO;
@@ -223,11 +228,6 @@
 	writel(0, base + TIMER_CTRL);
 	writel(0, base + TIMER_2_BASE + TIMER_CTRL);
 
-	if (initialized || !of_device_is_available(np)) {
-		ret = -EINVAL;
-		goto err;
-	}
-
 	clk1 = of_clk_get(np, 0);
 	if (IS_ERR(clk1))
 		clk1 = NULL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/counter/104-quad-8.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/counter/104-quad-8.c
@@ -42,6 +42,7 @@
  * @base:		base port address of the IIO device
  */
 struct quad8_iio {
+	struct mutex lock;
 	struct counter_device counter;
 	unsigned int preset[QUAD8_NUM_COUNTERS];
 	unsigned int count_mode[QUAD8_NUM_COUNTERS];
@@ -56,10 +57,6 @@
 
 #define QUAD8_REG_CHAN_OP 0x11
 #define QUAD8_REG_INDEX_INPUT_LEVELS 0x16
-/* Borrow Toggle flip-flop */
-#define QUAD8_FLAG_BT BIT(0)
-/* Carry Toggle flip-flop */
-#define QUAD8_FLAG_CT BIT(1)
 /* Error flag */
 #define QUAD8_FLAG_E BIT(4)
 /* Up/Down flag */
@@ -96,9 +93,6 @@
 {
 	struct quad8_iio *const priv = iio_priv(indio_dev);
 	const int base_offset = priv->base + 2 * chan->channel;
-	unsigned int flags;
-	unsigned int borrow;
-	unsigned int carry;
 	int i;
 
 	switch (mask) {
@@ -109,12 +103,9 @@
 			return IIO_VAL_INT;
 		}
 
-		flags = inb(base_offset + 1);
-		borrow = flags & QUAD8_FLAG_BT;
-		carry = !!(flags & QUAD8_FLAG_CT);
+		*val = 0;
 
-		/* Borrow XOR Carry effectively doubles count range */
-		*val = (borrow ^ carry) << 24;
+		mutex_lock(&priv->lock);
 
 		/* Reset Byte Pointer; transfer Counter to Output Latch */
 		outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_CNTR_OUT,
@@ -123,6 +114,8 @@
 		for (i = 0; i < 3; i++)
 			*val |= (unsigned int)inb(base_offset) << (8 * i);
 
+		mutex_unlock(&priv->lock);
+
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_ENABLE:
 		*val = priv->ab_enable[chan->channel];
@@ -153,6 +146,8 @@
 		if ((unsigned int)val > 0xFFFFFF)
 			return -EINVAL;
 
+		mutex_lock(&priv->lock);
+
 		/* Reset Byte Pointer */
 		outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
 
@@ -176,12 +171,16 @@
 		/* Reset Error flag */
 		outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, base_offset + 1);
 
+		mutex_unlock(&priv->lock);
+
 		return 0;
 	case IIO_CHAN_INFO_ENABLE:
 		/* only boolean values accepted */
 		if (val < 0 || val > 1)
 			return -EINVAL;
 
+		mutex_lock(&priv->lock);
+
 		priv->ab_enable[chan->channel] = val;
 
 		ior_cfg = val | priv->preset_enable[chan->channel] << 1;
@@ -189,11 +188,18 @@
 		/* Load I/O control configuration */
 		outb(QUAD8_CTR_IOR | ior_cfg, base_offset + 1);
 
+		mutex_unlock(&priv->lock);
+
 		return 0;
 	case IIO_CHAN_INFO_SCALE:
+		mutex_lock(&priv->lock);
+
 		/* Quadrature scaling only available in quadrature mode */
-		if (!priv->quadrature_mode[chan->channel] && (val2 || val != 1))
+		if (!priv->quadrature_mode[chan->channel] &&
+				(val2 || val != 1)) {
+			mutex_unlock(&priv->lock);
 			return -EINVAL;
+		}
 
 		/* Only three gain states (1, 0.5, 0.25) */
 		if (val == 1 && !val2)
@@ -207,11 +213,15 @@
 				priv->quadrature_scale[chan->channel] = 2;
 				break;
 			default:
+				mutex_unlock(&priv->lock);
 				return -EINVAL;
 			}
-		else
+		else {
+			mutex_unlock(&priv->lock);
 			return -EINVAL;
+		}
 
+		mutex_unlock(&priv->lock);
 		return 0;
 	}
 
@@ -248,6 +258,8 @@
 	if (preset > 0xFFFFFF)
 		return -EINVAL;
 
+	mutex_lock(&priv->lock);
+
 	priv->preset[chan->channel] = preset;
 
 	/* Reset Byte Pointer */
@@ -257,6 +269,8 @@
 	for (i = 0; i < 3; i++)
 		outb(preset >> (8 * i), base_offset);
 
+	mutex_unlock(&priv->lock);
+
 	return len;
 }
 
@@ -286,6 +300,8 @@
 	/* Preset enable is active low in Input/Output Control register */
 	preset_enable = !preset_enable;
 
+	mutex_lock(&priv->lock);
+
 	priv->preset_enable[chan->channel] = preset_enable;
 
 	ior_cfg = priv->ab_enable[chan->channel] |
@@ -294,6 +310,8 @@
 	/* Load I/O control configuration to Input / Output Control Register */
 	outb(QUAD8_CTR_IOR | ior_cfg, base_offset);
 
+	mutex_unlock(&priv->lock);
+
 	return len;
 }
 
@@ -351,6 +369,8 @@
 	unsigned int mode_cfg = cnt_mode << 1;
 	const int base_offset = priv->base + 2 * chan->channel + 1;
 
+	mutex_lock(&priv->lock);
+
 	priv->count_mode[chan->channel] = cnt_mode;
 
 	/* Add quadrature mode configuration */
@@ -360,6 +380,8 @@
 	/* Load mode configuration to Counter Mode Register */
 	outb(QUAD8_CTR_CMR | mode_cfg, base_offset);
 
+	mutex_unlock(&priv->lock);
+
 	return 0;
 }
 
@@ -387,19 +409,26 @@
 	const struct iio_chan_spec *chan, unsigned int synchronous_mode)
 {
 	struct quad8_iio *const priv = iio_priv(indio_dev);
-	const unsigned int idr_cfg = synchronous_mode |
-		priv->index_polarity[chan->channel] << 1;
 	const int base_offset = priv->base + 2 * chan->channel + 1;
+	unsigned int idr_cfg = synchronous_mode;
+
+	mutex_lock(&priv->lock);
+
+	idr_cfg |= priv->index_polarity[chan->channel] << 1;
 
 	/* Index function must be non-synchronous in non-quadrature mode */
-	if (synchronous_mode && !priv->quadrature_mode[chan->channel])
+	if (synchronous_mode && !priv->quadrature_mode[chan->channel]) {
+		mutex_unlock(&priv->lock);
 		return -EINVAL;
+	}
 
 	priv->synchronous_mode[chan->channel] = synchronous_mode;
 
 	/* Load Index Control configuration to Index Control Register */
 	outb(QUAD8_CTR_IDR | idr_cfg, base_offset);
 
+	mutex_unlock(&priv->lock);
+
 	return 0;
 }
 
@@ -427,8 +456,12 @@
 	const struct iio_chan_spec *chan, unsigned int quadrature_mode)
 {
 	struct quad8_iio *const priv = iio_priv(indio_dev);
-	unsigned int mode_cfg = priv->count_mode[chan->channel] << 1;
 	const int base_offset = priv->base + 2 * chan->channel + 1;
+	unsigned int mode_cfg;
+
+	mutex_lock(&priv->lock);
+
+	mode_cfg = priv->count_mode[chan->channel] << 1;
 
 	if (quadrature_mode)
 		mode_cfg |= (priv->quadrature_scale[chan->channel] + 1) << 3;
@@ -446,6 +479,8 @@
 	/* Load mode configuration to Counter Mode Register */
 	outb(QUAD8_CTR_CMR | mode_cfg, base_offset);
 
+	mutex_unlock(&priv->lock);
+
 	return 0;
 }
 
@@ -473,15 +508,20 @@
 	const struct iio_chan_spec *chan, unsigned int index_polarity)
 {
 	struct quad8_iio *const priv = iio_priv(indio_dev);
-	const unsigned int idr_cfg = priv->synchronous_mode[chan->channel] |
-		index_polarity << 1;
 	const int base_offset = priv->base + 2 * chan->channel + 1;
+	unsigned int idr_cfg = index_polarity << 1;
+
+	mutex_lock(&priv->lock);
+
+	idr_cfg |= priv->synchronous_mode[chan->channel];
 
 	priv->index_polarity[chan->channel] = index_polarity;
 
 	/* Load Index Control configuration to Index Control Register */
 	outb(QUAD8_CTR_IDR | idr_cfg, base_offset);
 
+	mutex_unlock(&priv->lock);
+
 	return 0;
 }
 
@@ -585,20 +625,12 @@
 static int quad8_count_read(struct counter_device *counter,
 	struct counter_count *count, struct counter_count_read_value *val)
 {
-	const struct quad8_iio *const priv = counter->priv;
+	struct quad8_iio *const priv = counter->priv;
 	const int base_offset = priv->base + 2 * count->id;
-	unsigned int flags;
-	unsigned int borrow;
-	unsigned int carry;
-	unsigned long position;
+	unsigned long position = 0;
 	int i;
 
-	flags = inb(base_offset + 1);
-	borrow = flags & QUAD8_FLAG_BT;
-	carry = !!(flags & QUAD8_FLAG_CT);
-
-	/* Borrow XOR Carry effectively doubles count range */
-	position = (unsigned long)(borrow ^ carry) << 24;
+	mutex_lock(&priv->lock);
 
 	/* Reset Byte Pointer; transfer Counter to Output Latch */
 	outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_CNTR_OUT,
@@ -609,13 +641,15 @@
 
 	counter_count_read_value_set(val, COUNTER_COUNT_POSITION, &position);
 
+	mutex_unlock(&priv->lock);
+
 	return 0;
 }
 
 static int quad8_count_write(struct counter_device *counter,
 	struct counter_count *count, struct counter_count_write_value *val)
 {
-	const struct quad8_iio *const priv = counter->priv;
+	struct quad8_iio *const priv = counter->priv;
 	const int base_offset = priv->base + 2 * count->id;
 	int err;
 	unsigned long position;
@@ -630,6 +664,8 @@
 	if (position > 0xFFFFFF)
 		return -EINVAL;
 
+	mutex_lock(&priv->lock);
+
 	/* Reset Byte Pointer */
 	outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
 
@@ -653,6 +689,8 @@
 	/* Reset Error flag */
 	outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, base_offset + 1);
 
+	mutex_unlock(&priv->lock);
+
 	return 0;
 }
 
@@ -673,13 +711,13 @@
 static int quad8_function_get(struct counter_device *counter,
 	struct counter_count *count, size_t *function)
 {
-	const struct quad8_iio *const priv = counter->priv;
+	struct quad8_iio *const priv = counter->priv;
 	const int id = count->id;
-	const unsigned int quadrature_mode = priv->quadrature_mode[id];
-	const unsigned int scale = priv->quadrature_scale[id];
 
-	if (quadrature_mode)
-		switch (scale) {
+	mutex_lock(&priv->lock);
+
+	if (priv->quadrature_mode[id])
+		switch (priv->quadrature_scale[id]) {
 		case 0:
 			*function = QUAD8_COUNT_FUNCTION_QUADRATURE_X1;
 			break;
@@ -693,6 +731,8 @@
 	else
 		*function = QUAD8_COUNT_FUNCTION_PULSE_DIRECTION;
 
+	mutex_unlock(&priv->lock);
+
 	return 0;
 }
 
@@ -703,10 +743,15 @@
 	const int id = count->id;
 	unsigned int *const quadrature_mode = priv->quadrature_mode + id;
 	unsigned int *const scale = priv->quadrature_scale + id;
-	unsigned int mode_cfg = priv->count_mode[id] << 1;
 	unsigned int *const synchronous_mode = priv->synchronous_mode + id;
-	const unsigned int idr_cfg = priv->index_polarity[id] << 1;
 	const int base_offset = priv->base + 2 * id + 1;
+	unsigned int mode_cfg;
+	unsigned int idr_cfg;
+
+	mutex_lock(&priv->lock);
+
+	mode_cfg = priv->count_mode[id] << 1;
+	idr_cfg = priv->index_polarity[id] << 1;
 
 	if (function == QUAD8_COUNT_FUNCTION_PULSE_DIRECTION) {
 		*quadrature_mode = 0;
@@ -742,6 +787,8 @@
 	/* Load mode configuration to Counter Mode Register */
 	outb(QUAD8_CTR_CMR | mode_cfg, base_offset);
 
+	mutex_unlock(&priv->lock);
+
 	return 0;
 }
 
@@ -858,15 +905,20 @@
 {
 	struct quad8_iio *const priv = counter->priv;
 	const size_t channel_id = signal->id - 16;
-	const unsigned int idr_cfg = priv->synchronous_mode[channel_id] |
-		index_polarity << 1;
 	const int base_offset = priv->base + 2 * channel_id + 1;
+	unsigned int idr_cfg = index_polarity << 1;
+
+	mutex_lock(&priv->lock);
+
+	idr_cfg |= priv->synchronous_mode[channel_id];
 
 	priv->index_polarity[channel_id] = index_polarity;
 
 	/* Load Index Control configuration to Index Control Register */
 	outb(QUAD8_CTR_IDR | idr_cfg, base_offset);
 
+	mutex_unlock(&priv->lock);
+
 	return 0;
 }
 
@@ -893,19 +945,26 @@
 {
 	struct quad8_iio *const priv = counter->priv;
 	const size_t channel_id = signal->id - 16;
-	const unsigned int idr_cfg = synchronous_mode |
-		priv->index_polarity[channel_id] << 1;
 	const int base_offset = priv->base + 2 * channel_id + 1;
+	unsigned int idr_cfg = synchronous_mode;
+
+	mutex_lock(&priv->lock);
+
+	idr_cfg |= priv->index_polarity[channel_id] << 1;
 
 	/* Index function must be non-synchronous in non-quadrature mode */
-	if (synchronous_mode && !priv->quadrature_mode[channel_id])
+	if (synchronous_mode && !priv->quadrature_mode[channel_id]) {
+		mutex_unlock(&priv->lock);
 		return -EINVAL;
+	}
 
 	priv->synchronous_mode[channel_id] = synchronous_mode;
 
 	/* Load Index Control configuration to Index Control Register */
 	outb(QUAD8_CTR_IDR | idr_cfg, base_offset);
 
+	mutex_unlock(&priv->lock);
+
 	return 0;
 }
 
@@ -970,6 +1029,8 @@
 		break;
 	}
 
+	mutex_lock(&priv->lock);
+
 	priv->count_mode[count->id] = cnt_mode;
 
 	/* Set count mode configuration value */
@@ -982,6 +1043,8 @@
 	/* Load mode configuration to Counter Mode Register */
 	outb(QUAD8_CTR_CMR | mode_cfg, base_offset);
 
+	mutex_unlock(&priv->lock);
+
 	return 0;
 }
 
@@ -1023,6 +1086,8 @@
 	if (err)
 		return err;
 
+	mutex_lock(&priv->lock);
+
 	priv->ab_enable[count->id] = ab_enable;
 
 	ior_cfg = ab_enable | priv->preset_enable[count->id] << 1;
@@ -1030,6 +1095,8 @@
 	/* Load I/O control configuration */
 	outb(QUAD8_CTR_IOR | ior_cfg, base_offset + 1);
 
+	mutex_unlock(&priv->lock);
+
 	return len;
 }
 
@@ -1058,14 +1125,28 @@
 	return sprintf(buf, "%u\n", priv->preset[count->id]);
 }
 
+static void quad8_preset_register_set(struct quad8_iio *quad8iio, int id,
+		unsigned int preset)
+{
+	const unsigned int base_offset = quad8iio->base + 2 * id;
+	int i;
+
+	quad8iio->preset[id] = preset;
+
+	/* Reset Byte Pointer */
+	outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
+
+	/* Set Preset Register */
+	for (i = 0; i < 3; i++)
+		outb(preset >> (8 * i), base_offset);
+}
+
 static ssize_t quad8_count_preset_write(struct counter_device *counter,
 	struct counter_count *count, void *private, const char *buf, size_t len)
 {
 	struct quad8_iio *const priv = counter->priv;
-	const int base_offset = priv->base + 2 * count->id;
 	unsigned int preset;
 	int ret;
-	int i;
 
 	ret = kstrtouint(buf, 0, &preset);
 	if (ret)
@@ -1075,14 +1156,11 @@
 	if (preset > 0xFFFFFF)
 		return -EINVAL;
 
-	priv->preset[count->id] = preset;
+	mutex_lock(&priv->lock);
 
-	/* Reset Byte Pointer */
-	outb(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, base_offset + 1);
+	quad8_preset_register_set(priv, count->id, preset);
 
-	/* Set Preset Register */
-	for (i = 0; i < 3; i++)
-		outb(preset >> (8 * i), base_offset);
+	mutex_unlock(&priv->lock);
 
 	return len;
 }
@@ -1090,33 +1168,53 @@
 static ssize_t quad8_count_ceiling_read(struct counter_device *counter,
 	struct counter_count *count, void *private, char *buf)
 {
-	const struct quad8_iio *const priv = counter->priv;
+	struct quad8_iio *const priv = counter->priv;
+
+	mutex_lock(&priv->lock);
 
 	/* Range Limit and Modulo-N count modes use preset value as ceiling */
 	switch (priv->count_mode[count->id]) {
 	case 1:
 	case 3:
-		return quad8_count_preset_read(counter, count, private, buf);
+		mutex_unlock(&priv->lock);
+		return sprintf(buf, "%u\n", priv->preset[count->id]);
 	}
 
-	/* By default 0x1FFFFFF (25 bits unsigned) is maximum count */
-	return sprintf(buf, "33554431\n");
+	mutex_unlock(&priv->lock);
+
+	/* By default 0xFFFFFF (24 bits unsigned) is maximum count */
+	return sprintf(buf, "16777215\n");
 }
 
 static ssize_t quad8_count_ceiling_write(struct counter_device *counter,
 	struct counter_count *count, void *private, const char *buf, size_t len)
 {
 	struct quad8_iio *const priv = counter->priv;
+	unsigned int ceiling;
+	int ret;
+
+	ret = kstrtouint(buf, 0, &ceiling);
+	if (ret)
+		return ret;
+
+	/* Only 24-bit values are supported */
+	if (ceiling > 0xFFFFFF)
+		return -EINVAL;
+
+	mutex_lock(&priv->lock);
 
 	/* Range Limit and Modulo-N count modes use preset value as ceiling */
 	switch (priv->count_mode[count->id]) {
 	case 1:
 	case 3:
-		return quad8_count_preset_write(counter, count, private, buf,
-						len);
+		quad8_preset_register_set(priv, count->id, ceiling);
+		mutex_unlock(&priv->lock);
+		return len;
 	}
 
-	return len;
+	mutex_unlock(&priv->lock);
+
+	return -EINVAL;
 }
 
 static ssize_t quad8_count_preset_enable_read(struct counter_device *counter,
@@ -1143,6 +1241,8 @@
 	/* Preset enable is active low in Input/Output Control register */
 	preset_enable = !preset_enable;
 
+	mutex_lock(&priv->lock);
+
 	priv->preset_enable[count->id] = preset_enable;
 
 	ior_cfg = priv->ab_enable[count->id] | (unsigned int)preset_enable << 1;
@@ -1150,6 +1250,8 @@
 	/* Load I/O control configuration to Input / Output Control Register */
 	outb(QUAD8_CTR_IOR | ior_cfg, base_offset);
 
+	mutex_unlock(&priv->lock);
+
 	return len;
 }
 
@@ -1320,6 +1422,9 @@
 	quad8iio->counter.priv = quad8iio;
 	quad8iio->base = base[id];
 
+	/* Initialize mutex */
+	mutex_init(&quad8iio->lock);
+
 	/* Reset all counters and disable interrupt function */
 	outb(QUAD8_CHAN_OP_RESET_COUNTERS, base[id] + QUAD8_REG_CHAN_OP);
 	/* Set initial configuration for all counters */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/counter/stm32-lptimer-cnt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/counter/stm32-lptimer-cnt.c
@@ -58,37 +58,43 @@
 		return 0;
 	}
 
+	ret = clk_enable(priv->clk);
+	if (ret)
+		goto disable_cnt;
+
 	/* LP timer must be enabled before writing CMP & ARR */
 	ret = regmap_write(priv->regmap, STM32_LPTIM_ARR, priv->ceiling);
 	if (ret)
-		return ret;
+		goto disable_clk;
 
 	ret = regmap_write(priv->regmap, STM32_LPTIM_CMP, 0);
 	if (ret)
-		return ret;
+		goto disable_clk;
 
 	/* ensure CMP & ARR registers are properly written */
 	ret = regmap_read_poll_timeout(priv->regmap, STM32_LPTIM_ISR, val,
-				       (val & STM32_LPTIM_CMPOK_ARROK),
+				       (val & STM32_LPTIM_CMPOK_ARROK) == STM32_LPTIM_CMPOK_ARROK,
 				       100, 1000);
 	if (ret)
-		return ret;
+		goto disable_clk;
 
 	ret = regmap_write(priv->regmap, STM32_LPTIM_ICR,
 			   STM32_LPTIM_CMPOKCF_ARROKCF);
 	if (ret)
-		return ret;
+		goto disable_clk;
 
-	ret = clk_enable(priv->clk);
-	if (ret) {
-		regmap_write(priv->regmap, STM32_LPTIM_CR, 0);
-		return ret;
-	}
 	priv->enabled = true;
 
 	/* Start LP timer in continuous mode */
 	return regmap_update_bits(priv->regmap, STM32_LPTIM_CR,
 				  STM32_LPTIM_CNTSTRT, STM32_LPTIM_CNTSTRT);
+
+disable_clk:
+	clk_disable(priv->clk);
+disable_cnt:
+	regmap_write(priv->regmap, STM32_LPTIM_CR, 0);
+
+	return ret;
 }
 
 static int stm32_lptim_setup(struct stm32_lptim_cnt *priv, int enable)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/counter/stm32-timer-cnt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/counter/stm32-timer-cnt.c
@@ -24,7 +24,7 @@
 	struct counter_device counter;
 	struct regmap *regmap;
 	struct clk *clk;
-	u32 ceiling;
+	u32 max_arr;
 };
 
 /**
@@ -35,13 +35,14 @@
  * @STM32_COUNT_ENCODER_MODE_3: counts on both TI1FP1 and TI2FP2 edges
  */
 enum stm32_count_function {
-	STM32_COUNT_SLAVE_MODE_DISABLED = -1,
+	STM32_COUNT_SLAVE_MODE_DISABLED,
 	STM32_COUNT_ENCODER_MODE_1,
 	STM32_COUNT_ENCODER_MODE_2,
 	STM32_COUNT_ENCODER_MODE_3,
 };
 
 static enum counter_count_function stm32_count_functions[] = {
+	[STM32_COUNT_SLAVE_MODE_DISABLED] = COUNTER_COUNT_FUNCTION_INCREASE,
 	[STM32_COUNT_ENCODER_MODE_1] = COUNTER_COUNT_FUNCTION_QUADRATURE_X2_A,
 	[STM32_COUNT_ENCODER_MODE_2] = COUNTER_COUNT_FUNCTION_QUADRATURE_X2_B,
 	[STM32_COUNT_ENCODER_MODE_3] = COUNTER_COUNT_FUNCTION_QUADRATURE_X4,
@@ -65,14 +66,15 @@
 			     struct counter_count_write_value *val)
 {
 	struct stm32_timer_cnt *const priv = counter->priv;
-	u32 cnt;
+	u32 cnt, ceiling;
 	int err;
 
 	err = counter_count_write_value_get(&cnt, COUNTER_COUNT_POSITION, val);
 	if (err)
 		return err;
 
-	if (cnt > priv->ceiling)
+	regmap_read(priv->regmap, TIM_ARR, &ceiling);
+	if (cnt > ceiling)
 		return -EINVAL;
 
 	return regmap_write(priv->regmap, TIM_CNT, cnt);
@@ -88,6 +90,9 @@
 	regmap_read(priv->regmap, TIM_SMCR, &smcr);
 
 	switch (smcr & TIM_SMCR_SMS) {
+	case 0:
+		*function = STM32_COUNT_SLAVE_MODE_DISABLED;
+		return 0;
 	case 1:
 		*function = STM32_COUNT_ENCODER_MODE_1;
 		return 0;
@@ -97,9 +102,9 @@
 	case 3:
 		*function = STM32_COUNT_ENCODER_MODE_3;
 		return 0;
+	default:
+		return -EINVAL;
 	}
-
-	return -EINVAL;
 }
 
 static int stm32_count_function_set(struct counter_device *counter,
@@ -110,6 +115,9 @@
 	u32 cr1, sms;
 
 	switch (function) {
+	case STM32_COUNT_SLAVE_MODE_DISABLED:
+		sms = 0;
+		break;
 	case STM32_COUNT_ENCODER_MODE_1:
 		sms = 1;
 		break;
@@ -120,8 +128,7 @@
 		sms = 3;
 		break;
 	default:
-		sms = 0;
-		break;
+		return -EINVAL;
 	}
 
 	/* Store enable status */
@@ -129,10 +136,6 @@
 
 	regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0);
 
-	/* TIMx_ARR register shouldn't be buffered (ARPE=0) */
-	regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, 0);
-	regmap_write(priv->regmap, TIM_ARR, priv->ceiling);
-
 	regmap_update_bits(priv->regmap, TIM_SMCR, TIM_SMCR_SMS, sms);
 
 	/* Make sure that registers are updated */
@@ -183,11 +186,13 @@
 	if (ret)
 		return ret;
 
+	if (ceiling > priv->max_arr)
+		return -ERANGE;
+
 	/* TIMx_ARR register shouldn't be buffered (ARPE=0) */
 	regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, 0);
 	regmap_write(priv->regmap, TIM_ARR, ceiling);
 
-	priv->ceiling = ceiling;
 	return len;
 }
 
@@ -269,31 +274,36 @@
 	size_t function;
 	int err;
 
-	/* Default action mode (e.g. STM32_COUNT_SLAVE_MODE_DISABLED) */
-	*action = STM32_SYNAPSE_ACTION_NONE;
-
 	err = stm32_count_function_get(counter, count, &function);
 	if (err)
-		return 0;
+		return err;
 
 	switch (function) {
+	case STM32_COUNT_SLAVE_MODE_DISABLED:
+		/* counts on internal clock when CEN=1 */
+		*action = STM32_SYNAPSE_ACTION_NONE;
+		return 0;
 	case STM32_COUNT_ENCODER_MODE_1:
 		/* counts up/down on TI1FP1 edge depending on TI2FP2 level */
 		if (synapse->signal->id == count->synapses[0].signal->id)
 			*action = STM32_SYNAPSE_ACTION_BOTH_EDGES;
-		break;
+		else
+			*action = STM32_SYNAPSE_ACTION_NONE;
+		return 0;
 	case STM32_COUNT_ENCODER_MODE_2:
 		/* counts up/down on TI2FP2 edge depending on TI1FP1 level */
 		if (synapse->signal->id == count->synapses[1].signal->id)
 			*action = STM32_SYNAPSE_ACTION_BOTH_EDGES;
-		break;
+		else
+			*action = STM32_SYNAPSE_ACTION_NONE;
+		return 0;
 	case STM32_COUNT_ENCODER_MODE_3:
 		/* counts up/down on both TI1FP1 and TI2FP2 edges */
 		*action = STM32_SYNAPSE_ACTION_BOTH_EDGES;
-		break;
+		return 0;
+	default:
+		return -EINVAL;
 	}
-
-	return 0;
 }
 
 static const struct counter_ops stm32_timer_cnt_ops = {
@@ -354,7 +364,7 @@
 
 	priv->regmap = ddata->regmap;
 	priv->clk = ddata->clk;
-	priv->ceiling = ddata->max_arr;
+	priv->max_arr = ddata->max_arr;
 
 	priv->counter.name = dev_name(dev);
 	priv->counter.parent = dev;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpufreq/Kconfig.arm
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpufreq/Kconfig.arm
@@ -41,6 +41,7 @@
 config ARM_ARMADA_8K_CPUFREQ
 	tristate "Armada 8K CPUFreq driver"
 	depends on ARCH_MVEBU && CPUFREQ_DT
+	select ARMADA_AP_CPU_CLK
 	help
 	  This enables the CPUFreq driver support for Marvell
 	  Armada8k SOCs.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpufreq/acpi-cpufreq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpufreq/acpi-cpufreq.c
@@ -30,6 +30,7 @@
 #include <asm/msr.h>
 #include <asm/processor.h>
 #include <asm/cpufeature.h>
+#include <asm/cpu_device_id.h>
 
 MODULE_AUTHOR("Paul Diefenbaugh, Dominik Brodowski");
 MODULE_DESCRIPTION("ACPI Processor P-States Driver");
@@ -688,7 +689,8 @@
 		cpumask_copy(policy->cpus, topology_core_cpumask(cpu));
 	}
 
-	if (check_amd_hwpstate_cpu(cpu) && !acpi_pstate_strict) {
+	if (check_amd_hwpstate_cpu(cpu) && boot_cpu_data.x86 < 0x19 &&
+	    !acpi_pstate_strict) {
 		cpumask_clear(policy->cpus);
 		cpumask_set_cpu(cpu, policy->cpus);
 		cpumask_copy(data->freqdomain_cpus,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpufreq/amd_freq_sensitivity.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpufreq/amd_freq_sensitivity.c
@@ -18,6 +18,7 @@
 
 #include <asm/msr.h>
 #include <asm/cpufeature.h>
+#include <asm/cpu_device_id.h>
 
 #include "cpufreq_ondemand.h"
 
@@ -123,6 +124,8 @@
 	if (!pcidev) {
 		if (!boot_cpu_has(X86_FEATURE_PROC_FEEDBACK))
 			return -ENODEV;
+	} else {
+		pci_dev_put(pcidev);
 	}
 
 	if (rdmsrl_safe(MSR_AMD64_FREQ_SENSITIVITY_ACTUAL, &val))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpufreq/armada-37xx-cpufreq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpufreq/armada-37xx-cpufreq.c
@@ -25,6 +25,10 @@
 
 #include "cpufreq-dt.h"
 
+/* Clk register set */
+#define ARMADA_37XX_CLK_TBG_SEL		0
+#define ARMADA_37XX_CLK_TBG_SEL_CPU_OFF	22
+
 /* Power management in North Bridge register set */
 #define ARMADA_37XX_NB_L0L1	0x18
 #define ARMADA_37XX_NB_L2L3	0x1C
@@ -69,6 +73,8 @@
 #define LOAD_LEVEL_NR	4
 
 #define MIN_VOLT_MV 1000
+#define MIN_VOLT_MV_FOR_L1_1000MHZ 1108
+#define MIN_VOLT_MV_FOR_L1_1200MHZ 1155
 
 /*  AVS value for the corresponding voltage (in mV) */
 static int avs_map[] = {
@@ -96,7 +102,11 @@
 };
 
 static struct armada_37xx_dvfs armada_37xx_dvfs[] = {
-	{.cpu_freq_max = 1200*1000*1000, .divider = {1, 2, 4, 6} },
+	/*
+	 * The cpufreq scaling for 1.2 GHz variant of the SOC is currently
+	 * unstable because we do not know how to configure it properly.
+	 */
+	/* {.cpu_freq_max = 1200*1000*1000, .divider = {1, 2, 4, 6} }, */
 	{.cpu_freq_max = 1000*1000*1000, .divider = {1, 2, 4, 5} },
 	{.cpu_freq_max = 800*1000*1000,  .divider = {1, 2, 3, 4} },
 	{.cpu_freq_max = 600*1000*1000,  .divider = {2, 4, 5, 6} },
@@ -120,10 +130,15 @@
  * will be configured then the DVFS will be enabled.
  */
 static void __init armada37xx_cpufreq_dvfs_setup(struct regmap *base,
-						 struct clk *clk, u8 *divider)
+						 struct regmap *clk_base, u8 *divider)
 {
+	u32 cpu_tbg_sel;
 	int load_lvl;
-	struct clk *parent;
+
+	/* Determine to which TBG clock is CPU connected */
+	regmap_read(clk_base, ARMADA_37XX_CLK_TBG_SEL, &cpu_tbg_sel);
+	cpu_tbg_sel >>= ARMADA_37XX_CLK_TBG_SEL_CPU_OFF;
+	cpu_tbg_sel &= ARMADA_37XX_NB_TBG_SEL_MASK;
 
 	for (load_lvl = 0; load_lvl < LOAD_LEVEL_NR; load_lvl++) {
 		unsigned int reg, mask, val, offset = 0;
@@ -142,6 +157,11 @@
 		mask = (ARMADA_37XX_NB_CLK_SEL_MASK
 			<< ARMADA_37XX_NB_CLK_SEL_OFF);
 
+		/* Set TBG index, for all levels we use the same TBG */
+		val = cpu_tbg_sel << ARMADA_37XX_NB_TBG_SEL_OFF;
+		mask = (ARMADA_37XX_NB_TBG_SEL_MASK
+			<< ARMADA_37XX_NB_TBG_SEL_OFF);
+
 		/*
 		 * Set cpu divider based on the pre-computed array in
 		 * order to have balanced step.
@@ -160,14 +180,6 @@
 
 		regmap_update_bits(base, reg, mask, val);
 	}
-
-	/*
-	 * Set cpu clock source, for all the level we keep the same
-	 * clock source that the one already configured. For this one
-	 * we need to use the clock framework
-	 */
-	parent = clk_get_parent(clk);
-	clk_set_parent(clk, parent);
 }
 
 /*
@@ -202,6 +214,8 @@
  * - L2 & L3 voltage should be about 150mv smaller than L0 voltage.
  * This function calculates L1 & L2 & L3 AVS values dynamically based
  * on L0 voltage and fill all AVS values to the AVS value table.
+ * When base CPU frequency is 1000 or 1200 MHz then there is additional
+ * minimal avs value for load L1.
  */
 static void __init armada37xx_cpufreq_avs_configure(struct regmap *base,
 						struct armada_37xx_dvfs *dvfs)
@@ -233,6 +247,19 @@
 		for (load_level = 1; load_level < LOAD_LEVEL_NR; load_level++)
 			dvfs->avs[load_level] = avs_min;
 
+		/*
+		 * Set the avs values for load L0 and L1 when base CPU frequency
+		 * is 1000/1200 MHz to its typical initial values according to
+		 * the Armada 3700 Hardware Specifications.
+		 */
+		if (dvfs->cpu_freq_max >= 1000*1000*1000) {
+			if (dvfs->cpu_freq_max >= 1200*1000*1000)
+				avs_min = armada_37xx_avs_val_match(MIN_VOLT_MV_FOR_L1_1200MHZ);
+			else
+				avs_min = armada_37xx_avs_val_match(MIN_VOLT_MV_FOR_L1_1000MHZ);
+			dvfs->avs[0] = dvfs->avs[1] = avs_min;
+		}
+
 		return;
 	}
 
@@ -252,6 +279,26 @@
 	target_vm = avs_map[l0_vdd_min] - 150;
 	target_vm = target_vm > MIN_VOLT_MV ? target_vm : MIN_VOLT_MV;
 	dvfs->avs[2] = dvfs->avs[3] = armada_37xx_avs_val_match(target_vm);
+
+	/*
+	 * Fix the avs value for load L1 when base CPU frequency is 1000/1200 MHz,
+	 * otherwise the CPU gets stuck when switching from load L1 to load L0.
+	 * Also ensure that avs value for load L1 is not higher than for L0.
+	 */
+	if (dvfs->cpu_freq_max >= 1000*1000*1000) {
+		u32 avs_min_l1;
+
+		if (dvfs->cpu_freq_max >= 1200*1000*1000)
+			avs_min_l1 = armada_37xx_avs_val_match(MIN_VOLT_MV_FOR_L1_1200MHZ);
+		else
+			avs_min_l1 = armada_37xx_avs_val_match(MIN_VOLT_MV_FOR_L1_1000MHZ);
+
+		if (avs_min_l1 > dvfs->avs[0])
+			avs_min_l1 = dvfs->avs[0];
+
+		if (dvfs->avs[1] < avs_min_l1)
+			dvfs->avs[1] = avs_min_l1;
+	}
 }
 
 static void __init armada37xx_cpufreq_avs_setup(struct regmap *base,
@@ -358,11 +405,16 @@
 	struct platform_device *pdev;
 	unsigned long freq;
 	unsigned int cur_frequency, base_frequency;
-	struct regmap *nb_pm_base, *avs_base;
+	struct regmap *nb_clk_base, *nb_pm_base, *avs_base;
 	struct device *cpu_dev;
 	int load_lvl, ret;
 	struct clk *clk, *parent;
 
+	nb_clk_base =
+		syscon_regmap_lookup_by_compatible("marvell,armada-3700-periph-clock-nb");
+	if (IS_ERR(nb_clk_base))
+		return -ENODEV;
+
 	nb_pm_base =
 		syscon_regmap_lookup_by_compatible("marvell,armada-3700-nb-pm");
 
@@ -391,7 +443,7 @@
 		return -ENODEV;
 	}
 
-	clk = clk_get(cpu_dev, 0);
+	clk = clk_get(cpu_dev, NULL);
 	if (IS_ERR(clk)) {
 		dev_err(cpu_dev, "Cannot get clock for CPU0\n");
 		return PTR_ERR(clk);
@@ -421,7 +473,7 @@
 		return -EINVAL;
 	}
 
-	dvfs = armada_37xx_cpu_freq_info_get(cur_frequency);
+	dvfs = armada_37xx_cpu_freq_info_get(base_frequency);
 	if (!dvfs) {
 		clk_put(clk);
 		return -EINVAL;
@@ -439,7 +491,7 @@
 	armada37xx_cpufreq_avs_configure(avs_base, dvfs);
 	armada37xx_cpufreq_avs_setup(avs_base, dvfs);
 
-	armada37xx_cpufreq_dvfs_setup(nb_pm_base, clk, dvfs->divider);
+	armada37xx_cpufreq_dvfs_setup(nb_pm_base, nb_clk_base, dvfs->divider);
 	clk_put(clk);
 
 	for (load_lvl = ARMADA_37XX_DVFS_LOAD_0; load_lvl < LOAD_LEVEL_NR;
@@ -456,6 +508,7 @@
 	/* Now that everything is setup, enable the DVFS at hardware level */
 	armada37xx_cpufreq_enable_dvfs(nb_pm_base);
 
+	memset(&pdata, 0, sizeof(pdata));
 	pdata.suspend = armada37xx_cpufreq_suspend;
 	pdata.resume = armada37xx_cpufreq_resume;
 
@@ -472,7 +525,7 @@
 remove_opp:
 	/* clean-up the already added opp before leaving */
 	while (load_lvl-- > ARMADA_37XX_DVFS_LOAD_0) {
-		freq = cur_frequency / dvfs->divider[load_lvl];
+		freq = base_frequency / dvfs->divider[load_lvl];
 		dev_pm_opp_remove(cpu_dev, freq);
 	}
 
@@ -483,6 +536,12 @@
 /* late_initcall, to guarantee the driver is loaded after A37xx clock driver */
 late_initcall(armada37xx_cpufreq_driver_init);
 
+static const struct of_device_id __maybe_unused armada37xx_cpufreq_of_match[] = {
+	{ .compatible = "marvell,armada-3700-nb-pm" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, armada37xx_cpufreq_of_match);
+
 MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>");
 MODULE_DESCRIPTION("Armada 37xx cpufreq driver");
 MODULE_LICENSE("GPL");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpufreq/armada-8k-cpufreq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpufreq/armada-8k-cpufreq.c
@@ -204,6 +204,12 @@
 }
 module_exit(armada_8k_cpufreq_exit);
 
+static const struct of_device_id __maybe_unused armada_8k_cpufreq_of_match[] = {
+	{ .compatible = "marvell,ap806-cpu-clock" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, armada_8k_cpufreq_of_match);
+
 MODULE_AUTHOR("Gregory Clement <gregory.clement@bootlin.com>");
 MODULE_DESCRIPTION("Armada 8K cpufreq driver");
 MODULE_LICENSE("GPL");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpufreq/brcmstb-avs-cpufreq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpufreq/brcmstb-avs-cpufreq.c
@@ -410,7 +410,11 @@
 	if (ret)
 		return ERR_PTR(ret);
 
-	table = devm_kcalloc(dev, AVS_PSTATE_MAX + 1, sizeof(*table),
+	/*
+	 * We allocate space for the 5 different P-STATES AVS,
+	 * plus extra space for a terminating element.
+	 */
+	table = devm_kcalloc(dev, AVS_PSTATE_MAX + 1 + 1, sizeof(*table),
 			     GFP_KERNEL);
 	if (!table)
 		return ERR_PTR(-ENOMEM);
@@ -453,7 +457,12 @@
 static unsigned int brcm_avs_cpufreq_get(unsigned int cpu)
 {
 	struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
-	struct private_data *priv = policy->driver_data;
+	struct private_data *priv;
+
+	if (!policy)
+		return 0;
+
+	priv = policy->driver_data;
 
 	return brcm_avs_get_frequency(priv->base);
 }
@@ -566,6 +575,16 @@
 	return ret;
 }
 
+static void brcm_avs_prepare_uninit(struct platform_device *pdev)
+{
+	struct private_data *priv;
+
+	priv = platform_get_drvdata(pdev);
+
+	iounmap(priv->avs_intr_base);
+	iounmap(priv->base);
+}
+
 static int brcm_avs_cpufreq_init(struct cpufreq_policy *policy)
 {
 	struct cpufreq_frequency_table *freq_table;
@@ -701,21 +720,21 @@
 
 	brcm_avs_driver.driver_data = pdev;
 
-	return cpufreq_register_driver(&brcm_avs_driver);
+	ret = cpufreq_register_driver(&brcm_avs_driver);
+	if (ret)
+		brcm_avs_prepare_uninit(pdev);
+
+	return ret;
 }
 
 static int brcm_avs_cpufreq_remove(struct platform_device *pdev)
 {
-	struct private_data *priv;
 	int ret;
 
 	ret = cpufreq_unregister_driver(&brcm_avs_driver);
-	if (ret)
-		return ret;
+	WARN_ON(ret);
 
-	priv = platform_get_drvdata(pdev);
-	iounmap(priv->base);
-	iounmap(priv->avs_intr_base);
+	brcm_avs_prepare_uninit(pdev);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpufreq/cppc_cpufreq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpufreq/cppc_cpufreq.c
@@ -217,7 +217,7 @@
 	return ret;
 }
 
-static int cppc_verify_policy(struct cpufreq_policy *policy)
+static int cppc_verify_policy(struct cpufreq_policy_data *policy)
 {
 	cpufreq_verify_within_cpu_limits(policy);
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpufreq/cpufreq-dt-platdev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -103,6 +103,8 @@
 static const struct of_device_id blacklist[] __initconst = {
 	{ .compatible = "allwinner,sun50i-h6", },
 
+	{ .compatible = "arm,vexpress", },
+
 	{ .compatible = "calxeda,highbank", },
 	{ .compatible = "calxeda,ecx-2000", },
 
@@ -124,6 +126,7 @@
 
 	{ .compatible = "nvidia,tegra124", },
 	{ .compatible = "nvidia,tegra210", },
+	{ .compatible = "nvidia,tegra234", },
 
 	{ .compatible = "qcom,apq8096", },
 	{ .compatible = "qcom,msm8996", },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpufreq/cpufreq-nforce2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpufreq/cpufreq-nforce2.c
@@ -291,7 +291,7 @@
  * nforce2_verify - verifies a new CPUFreq policy
  * @policy: new policy
  */
-static int nforce2_verify(struct cpufreq_policy *policy)
+static int nforce2_verify(struct cpufreq_policy_data *policy)
 {
 	unsigned int fsb_pol_max;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpufreq/cpufreq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpufreq/cpufreq.c
@@ -74,6 +74,9 @@
 static int cpufreq_start_governor(struct cpufreq_policy *policy);
 static void cpufreq_stop_governor(struct cpufreq_policy *policy);
 static void cpufreq_governor_limits(struct cpufreq_policy *policy);
+static int cpufreq_set_policy(struct cpufreq_policy *policy,
+			      struct cpufreq_governor *new_gov,
+			      unsigned int new_pol);
 
 /**
  * Two notifier lists: the "policy" list is involved in the
@@ -438,8 +441,10 @@
 
 	cpufreq_notify_post_transition(policy, freqs, transition_failed);
 
+	spin_lock(&policy->transition_lock);
 	policy->transition_ongoing = false;
 	policy->transition_task = NULL;
+	spin_unlock(&policy->transition_lock);
 
 	wake_up(&policy->transition_wait);
 }
@@ -613,55 +618,51 @@
 	return NULL;
 }
 
-static int cpufreq_parse_policy(char *str_governor,
-				struct cpufreq_policy *policy)
-{
-	if (!strncasecmp(str_governor, "performance", CPUFREQ_NAME_LEN)) {
-		policy->policy = CPUFREQ_POLICY_PERFORMANCE;
-		return 0;
-	}
-	if (!strncasecmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) {
-		policy->policy = CPUFREQ_POLICY_POWERSAVE;
-		return 0;
-	}
-	return -EINVAL;
-}
-
-/**
- * cpufreq_parse_governor - parse a governor string only for has_target()
- */
-static int cpufreq_parse_governor(char *str_governor,
-				  struct cpufreq_policy *policy)
+static struct cpufreq_governor *get_governor(const char *str_governor)
 {
 	struct cpufreq_governor *t;
 
 	mutex_lock(&cpufreq_governor_mutex);
-
 	t = find_governor(str_governor);
-	if (!t) {
-		int ret;
+	if (!t)
+		goto unlock;
 
-		mutex_unlock(&cpufreq_governor_mutex);
+	if (!try_module_get(t->owner))
+		t = NULL;
 
-		ret = request_module("cpufreq_%s", str_governor);
-		if (ret)
-			return -EINVAL;
+unlock:
+	mutex_unlock(&cpufreq_governor_mutex);
 
-		mutex_lock(&cpufreq_governor_mutex);
+	return t;
+}
 
-		t = find_governor(str_governor);
-	}
-	if (t && !try_module_get(t->owner))
-		t = NULL;
+static unsigned int cpufreq_parse_policy(char *str_governor)
+{
+	if (!strncasecmp(str_governor, "performance", CPUFREQ_NAME_LEN))
+		return CPUFREQ_POLICY_PERFORMANCE;
 
-	mutex_unlock(&cpufreq_governor_mutex);
+	if (!strncasecmp(str_governor, "powersave", CPUFREQ_NAME_LEN))
+		return CPUFREQ_POLICY_POWERSAVE;
 
-	if (t) {
-		policy->governor = t;
-		return 0;
-	}
+	return CPUFREQ_POLICY_UNKNOWN;
+}
 
-	return -EINVAL;
+/**
+ * cpufreq_parse_governor - parse a governor string only for has_target()
+ * @str_governor: Governor name.
+ */
+static struct cpufreq_governor *cpufreq_parse_governor(char *str_governor)
+{
+	struct cpufreq_governor *t;
+
+	t = get_governor(str_governor);
+	if (t)
+		return t;
+
+	if (request_module("cpufreq_%s", str_governor))
+		return NULL;
+
+	return get_governor(str_governor);
 }
 
 /**
@@ -762,28 +763,33 @@
 static ssize_t store_scaling_governor(struct cpufreq_policy *policy,
 					const char *buf, size_t count)
 {
+	char str_governor[16];
 	int ret;
-	char	str_governor[16];
-	struct cpufreq_policy new_policy;
-
-	memcpy(&new_policy, policy, sizeof(*policy));
 
 	ret = sscanf(buf, "%15s", str_governor);
 	if (ret != 1)
 		return -EINVAL;
 
 	if (cpufreq_driver->setpolicy) {
-		if (cpufreq_parse_policy(str_governor, &new_policy))
+		unsigned int new_pol;
+
+		new_pol = cpufreq_parse_policy(str_governor);
+		if (!new_pol)
 			return -EINVAL;
+
+		ret = cpufreq_set_policy(policy, NULL, new_pol);
 	} else {
-		if (cpufreq_parse_governor(str_governor, &new_policy))
+		struct cpufreq_governor *new_gov;
+
+		new_gov = cpufreq_parse_governor(str_governor);
+		if (!new_gov)
 			return -EINVAL;
-	}
 
-	ret = cpufreq_set_policy(policy, &new_policy);
+		ret = cpufreq_set_policy(policy, new_gov,
+					 CPUFREQ_POLICY_UNKNOWN);
 
-	if (new_policy.governor)
-		module_put(new_policy.governor->owner);
+		module_put(new_gov->owner);
+	}
 
 	return ret ? ret : count;
 }
@@ -810,12 +816,14 @@
 		goto out;
 	}
 
+	mutex_lock(&cpufreq_governor_mutex);
 	for_each_governor(t) {
 		if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char))
 		    - (CPUFREQ_NAME_LEN + 2)))
-			goto out;
+			break;
 		i += scnprintf(&buf[i], CPUFREQ_NAME_PLEN, "%s ", t->name);
 	}
+	mutex_unlock(&cpufreq_governor_mutex);
 out:
 	i += sprintf(&buf[i], "\n");
 	return i;
@@ -933,6 +941,9 @@
 	struct freq_attr *fattr = to_attr(attr);
 	ssize_t ret;
 
+	if (!fattr->show)
+		return -EIO;
+
 	down_read(&policy->rwsem);
 	ret = fattr->show(policy, buf);
 	up_read(&policy->rwsem);
@@ -947,6 +958,9 @@
 	struct freq_attr *fattr = to_attr(attr);
 	ssize_t ret = -EINVAL;
 
+	if (!fattr->store)
+		return -EIO;
+
 	/*
 	 * cpus_read_trylock() is used here to work around a circular lock
 	 * dependency problem with respect to the cpufreq_register_driver().
@@ -983,10 +997,9 @@
 	.release	= cpufreq_sysfs_release,
 };
 
-static void add_cpu_dev_symlink(struct cpufreq_policy *policy, unsigned int cpu)
+static void add_cpu_dev_symlink(struct cpufreq_policy *policy, unsigned int cpu,
+				struct device *dev)
 {
-	struct device *dev = get_cpu_device(cpu);
-
 	if (unlikely(!dev))
 		return;
 
@@ -1044,40 +1057,47 @@
 
 static int cpufreq_init_policy(struct cpufreq_policy *policy)
 {
-	struct cpufreq_governor *gov = NULL, *def_gov = NULL;
-	struct cpufreq_policy new_policy;
-
-	memcpy(&new_policy, policy, sizeof(*policy));
-
-	def_gov = cpufreq_default_governor();
+	struct cpufreq_governor *def_gov = cpufreq_default_governor();
+	struct cpufreq_governor *gov = NULL;
+	unsigned int pol = CPUFREQ_POLICY_UNKNOWN;
+	int ret;
 
 	if (has_target()) {
-		/*
-		 * Update governor of new_policy to the governor used before
-		 * hotplug
-		 */
-		gov = find_governor(policy->last_governor);
+		/* Update policy governor to the one used before hotplug. */
+		gov = get_governor(policy->last_governor);
 		if (gov) {
 			pr_debug("Restoring governor %s for cpu %d\n",
-				policy->governor->name, policy->cpu);
-		} else {
-			if (!def_gov)
-				return -ENODATA;
+				 policy->governor->name, policy->cpu);
+		} else if (def_gov) {
 			gov = def_gov;
+			__module_get(gov->owner);
+		} else {
+			return -ENODATA;
 		}
-		new_policy.governor = gov;
 	} else {
 		/* Use the default policy if there is no last_policy. */
 		if (policy->last_policy) {
-			new_policy.policy = policy->last_policy;
-		} else {
-			if (!def_gov)
-				return -ENODATA;
-			cpufreq_parse_policy(def_gov->name, &new_policy);
+			pol = policy->last_policy;
+		} else if (def_gov) {
+			pol = cpufreq_parse_policy(def_gov->name);
+			/*
+			 * In case the default governor is neiter "performance"
+			 * nor "powersave", fall back to the initial policy
+			 * value set by the driver.
+			 */
+			if (pol == CPUFREQ_POLICY_UNKNOWN)
+				pol = policy->policy;
 		}
+		if (pol != CPUFREQ_POLICY_PERFORMANCE &&
+		    pol != CPUFREQ_POLICY_POWERSAVE)
+			return -ENODATA;
 	}
 
-	return cpufreq_set_policy(policy, &new_policy);
+	ret = cpufreq_set_policy(policy, gov, pol);
+	if (gov)
+		module_put(gov->owner);
+
+	return ret;
 }
 
 static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu)
@@ -1105,13 +1125,10 @@
 
 void refresh_frequency_limits(struct cpufreq_policy *policy)
 {
-	struct cpufreq_policy new_policy;
-
 	if (!policy_is_inactive(policy)) {
-		new_policy = *policy;
 		pr_debug("updating policy for CPU %u\n", policy->cpu);
 
-		cpufreq_set_policy(policy, &new_policy);
+		cpufreq_set_policy(policy, policy->governor, policy->policy);
 	}
 }
 EXPORT_SYMBOL(refresh_frequency_limits);
@@ -1189,6 +1206,7 @@
 	if (!zalloc_cpumask_var(&policy->real_cpus, GFP_KERNEL))
 		goto err_free_rcpumask;
 
+	init_completion(&policy->kobj_unregister);
 	ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq,
 				   cpufreq_global_kobject, "policy%u", cpu);
 	if (ret) {
@@ -1227,7 +1245,6 @@
 	init_rwsem(&policy->rwsem);
 	spin_lock_init(&policy->transition_lock);
 	init_waitqueue_head(&policy->transition_wait);
-	init_completion(&policy->kobj_unregister);
 	INIT_WORK(&policy->update, handle_update);
 
 	policy->cpu = cpu;
@@ -1345,9 +1362,14 @@
 			goto out_free_policy;
 		}
 
+		/*
+		 * The initialization has succeeded and the policy is online.
+		 * If there is a problem with its frequency table, take it
+		 * offline and drop it.
+		 */
 		ret = cpufreq_table_validate_and_sort(policy);
 		if (ret)
-			goto out_exit_policy;
+			goto out_offline_policy;
 
 		/* related_cpus should at least include policy->cpus. */
 		cpumask_copy(policy->related_cpus, policy->cpus);
@@ -1363,7 +1385,7 @@
 	if (new_policy) {
 		for_each_cpu(j, policy->related_cpus) {
 			per_cpu(cpufreq_cpu_data, j) = policy;
-			add_cpu_dev_symlink(policy, j);
+			add_cpu_dev_symlink(policy, j, get_cpu_device(j));
 		}
 
 		policy->min_freq_req = kzalloc(2 * sizeof(*policy->min_freq_req),
@@ -1373,7 +1395,7 @@
 
 		ret = freq_qos_add_request(&policy->constraints,
 					   policy->min_freq_req, FREQ_QOS_MIN,
-					   policy->min);
+					   FREQ_QOS_MIN_DEFAULT_VALUE);
 		if (ret < 0) {
 			/*
 			 * So we don't call freq_qos_remove_request() for an
@@ -1393,7 +1415,7 @@
 
 		ret = freq_qos_add_request(&policy->constraints,
 					   policy->max_freq_req, FREQ_QOS_MAX,
-					   policy->max);
+					   FREQ_QOS_MAX_DEFAULT_VALUE);
 		if (ret < 0) {
 			policy->max_freq_req = NULL;
 			goto out_destroy_policy;
@@ -1491,6 +1513,10 @@
 
 	up_write(&policy->rwsem);
 
+out_offline_policy:
+	if (cpufreq_driver->offline)
+		cpufreq_driver->offline(policy);
+
 out_exit_policy:
 	if (cpufreq_driver->exit)
 		cpufreq_driver->exit(policy);
@@ -1522,52 +1548,41 @@
 	/* Create sysfs link on CPU registration */
 	policy = per_cpu(cpufreq_cpu_data, cpu);
 	if (policy)
-		add_cpu_dev_symlink(policy, cpu);
+		add_cpu_dev_symlink(policy, cpu, dev);
 
 	return 0;
 }
 
-static int cpufreq_offline(unsigned int cpu)
+static void __cpufreq_offline(unsigned int cpu, struct cpufreq_policy *policy)
 {
-	struct cpufreq_policy *policy;
 	int ret;
 
-	pr_debug("%s: unregistering CPU %u\n", __func__, cpu);
-
-	policy = cpufreq_cpu_get_raw(cpu);
-	if (!policy) {
-		pr_debug("%s: No cpu_data found\n", __func__);
-		return 0;
-	}
-
-	down_write(&policy->rwsem);
 	if (has_target())
 		cpufreq_stop_governor(policy);
 
 	cpumask_clear_cpu(cpu, policy->cpus);
 
-	if (policy_is_inactive(policy)) {
-		if (has_target())
-			strncpy(policy->last_governor, policy->governor->name,
-				CPUFREQ_NAME_LEN);
-		else
-			policy->last_policy = policy->policy;
-	} else if (cpu == policy->cpu) {
-		/* Nominate new CPU */
-		policy->cpu = cpumask_any(policy->cpus);
-	}
-
-	/* Start governor again for active policy */
 	if (!policy_is_inactive(policy)) {
+		/* Nominate a new CPU if necessary. */
+		if (cpu == policy->cpu)
+			policy->cpu = cpumask_any(policy->cpus);
+
+		/* Start the governor again for the active policy. */
 		if (has_target()) {
 			ret = cpufreq_start_governor(policy);
 			if (ret)
 				pr_err("%s: Failed to start governor\n", __func__);
 		}
 
-		goto unlock;
+		return;
 	}
 
+	if (has_target())
+		strncpy(policy->last_governor, policy->governor->name,
+			CPUFREQ_NAME_LEN);
+	else
+		policy->last_policy = policy->policy;
+
 	if (cpufreq_thermal_control_enabled(cpufreq_driver)) {
 		cpufreq_cooling_unregister(policy->cdev);
 		policy->cdev = NULL;
@@ -1585,12 +1600,31 @@
 	 */
 	if (cpufreq_driver->offline) {
 		cpufreq_driver->offline(policy);
-	} else if (cpufreq_driver->exit) {
+		return;
+	}
+
+	if (cpufreq_driver->exit)
 		cpufreq_driver->exit(policy);
-		policy->freq_table = NULL;
+
+	policy->freq_table = NULL;
+}
+
+static int cpufreq_offline(unsigned int cpu)
+{
+	struct cpufreq_policy *policy;
+
+	pr_debug("%s: unregistering CPU %u\n", __func__, cpu);
+
+	policy = cpufreq_cpu_get_raw(cpu);
+	if (!policy) {
+		pr_debug("%s: No cpu_data found\n", __func__);
+		return 0;
 	}
 
-unlock:
+	down_write(&policy->rwsem);
+
+	__cpufreq_offline(cpu, policy);
+
 	up_write(&policy->rwsem);
 	return 0;
 }
@@ -1608,19 +1642,26 @@
 	if (!policy)
 		return;
 
+	down_write(&policy->rwsem);
+
 	if (cpu_online(cpu))
-		cpufreq_offline(cpu);
+		__cpufreq_offline(cpu, policy);
 
 	cpumask_clear_cpu(cpu, policy->real_cpus);
 	remove_cpu_dev_symlink(policy, dev);
 
-	if (cpumask_empty(policy->real_cpus)) {
-		/* We did light-weight exit earlier, do full tear down now */
-		if (cpufreq_driver->offline)
-			cpufreq_driver->exit(policy);
-
-		cpufreq_policy_free(policy);
+	if (!cpumask_empty(policy->real_cpus)) {
+		up_write(&policy->rwsem);
+		return;
 	}
+
+	/* We did light-weight exit earlier, do full tear down now */
+	if (cpufreq_driver->offline && cpufreq_driver->exit)
+		cpufreq_driver->exit(policy);
+
+	up_write(&policy->rwsem);
+
+	cpufreq_policy_free(policy);
 }
 
 /**
@@ -2355,43 +2396,46 @@
 /**
  * cpufreq_set_policy - Modify cpufreq policy parameters.
  * @policy: Policy object to modify.
- * @new_policy: New policy data.
+ * @new_gov: Policy governor pointer.
+ * @new_pol: Policy value (for drivers with built-in governors).
  *
- * Pass @new_policy to the cpufreq driver's ->verify() callback. Next, copy the
- * min and max parameters of @new_policy to @policy and either invoke the
- * driver's ->setpolicy() callback (if present) or carry out a governor update
- * for @policy.  That is, run the current governor's ->limits() callback (if the
- * governor field in @new_policy points to the same object as the one in
- * @policy) or replace the governor for @policy with the new one stored in
- * @new_policy.
+ * Invoke the cpufreq driver's ->verify() callback to sanity-check the frequency
+ * limits to be set for the policy, update @policy with the verified limits
+ * values and either invoke the driver's ->setpolicy() callback (if present) or
+ * carry out a governor update for @policy.  That is, run the current governor's
+ * ->limits() callback (if @new_gov points to the same object as the one in
+ * @policy) or replace the governor for @policy with @new_gov.
  *
  * The cpuinfo part of @policy is not updated by this function.
  */
-int cpufreq_set_policy(struct cpufreq_policy *policy,
-		       struct cpufreq_policy *new_policy)
+static int cpufreq_set_policy(struct cpufreq_policy *policy,
+			      struct cpufreq_governor *new_gov,
+			      unsigned int new_pol)
 {
+	struct cpufreq_policy_data new_data;
 	struct cpufreq_governor *old_gov;
 	int ret;
 
-	pr_debug("setting new policy for CPU %u: %u - %u kHz\n",
-		 new_policy->cpu, new_policy->min, new_policy->max);
-
-	memcpy(&new_policy->cpuinfo, &policy->cpuinfo, sizeof(policy->cpuinfo));
-
+	memcpy(&new_data.cpuinfo, &policy->cpuinfo, sizeof(policy->cpuinfo));
+	new_data.freq_table = policy->freq_table;
+	new_data.cpu = policy->cpu;
 	/*
 	 * PM QoS framework collects all the requests from users and provide us
 	 * the final aggregated value here.
 	 */
-	new_policy->min = freq_qos_read_value(&policy->constraints, FREQ_QOS_MIN);
-	new_policy->max = freq_qos_read_value(&policy->constraints, FREQ_QOS_MAX);
+	new_data.min = freq_qos_read_value(&policy->constraints, FREQ_QOS_MIN);
+	new_data.max = freq_qos_read_value(&policy->constraints, FREQ_QOS_MAX);
+
+	pr_debug("setting new policy for CPU %u: %u - %u kHz\n",
+		 new_data.cpu, new_data.min, new_data.max);
 
 	/* verify the cpu speed can be set within this limit */
-	ret = cpufreq_driver->verify(new_policy);
+	ret = cpufreq_driver->verify(&new_data);
 	if (ret)
 		return ret;
 
-	policy->min = new_policy->min;
-	policy->max = new_policy->max;
+	policy->min = new_data.min;
+	policy->max = new_data.max;
 	trace_cpu_frequency_limits(policy);
 
 	policy->cached_target_freq = UINT_MAX;
@@ -2400,12 +2444,12 @@
 		 policy->min, policy->max);
 
 	if (cpufreq_driver->setpolicy) {
-		policy->policy = new_policy->policy;
+		policy->policy = new_pol;
 		pr_debug("setting range\n");
 		return cpufreq_driver->setpolicy(policy);
 	}
 
-	if (new_policy->governor == policy->governor) {
+	if (new_gov == policy->governor) {
 		pr_debug("governor limits update\n");
 		cpufreq_governor_limits(policy);
 		return 0;
@@ -2422,7 +2466,7 @@
 	}
 
 	/* start new governor */
-	policy->governor = new_policy->governor;
+	policy->governor = new_gov;
 	ret = cpufreq_init_governor(policy);
 	if (!ret) {
 		ret = cpufreq_start_governor(policy);
@@ -2500,26 +2544,27 @@
 static int cpufreq_boost_set_sw(int state)
 {
 	struct cpufreq_policy *policy;
-	int ret = -EINVAL;
 
 	for_each_active_policy(policy) {
+		int ret;
+
 		if (!policy->freq_table)
-			continue;
+			return -ENXIO;
 
 		ret = cpufreq_frequency_table_cpuinfo(policy,
 						      policy->freq_table);
 		if (ret) {
 			pr_err("%s: Policy frequency update failed\n",
 			       __func__);
-			break;
+			return ret;
 		}
 
 		ret = freq_qos_update_request(policy->max_freq_req, policy->max);
 		if (ret < 0)
-			break;
+			return ret;
 	}
 
-	return ret;
+	return 0;
 }
 
 int cpufreq_boost_trigger_state(int state)
@@ -2610,6 +2655,20 @@
 	return 0;
 }
 
+static char cpufreq_driver_name[CPUFREQ_NAME_LEN];
+
+static int __init cpufreq_driver_setup(char *str)
+{
+	strlcpy(cpufreq_driver_name, str, CPUFREQ_NAME_LEN);
+	return 1;
+}
+
+/*
+ * Set this name to only allow one specific cpu freq driver, e.g.,
+ * cpufreq_driver=powernow-k8
+ */
+__setup("cpufreq_driver=", cpufreq_driver_setup);
+
 /**
  * cpufreq_register_driver - register a CPU Frequency driver
  * @driver_data: A struct cpufreq_driver containing the values#
@@ -2628,6 +2687,13 @@
 	if (cpufreq_disabled())
 		return -ENODEV;
 
+	/*
+	 * The cpufreq core depends heavily on the availability of device
+	 * structure, make sure they are available before proceeding further.
+	 */
+	if (!get_cpu_device(0))
+		return -EPROBE_DEFER;
+
 	if (!driver_data || !driver_data->verify || !driver_data->init ||
 	    !(driver_data->setpolicy || driver_data->target_index ||
 		    driver_data->target) ||
@@ -2637,7 +2703,13 @@
 	     (!driver_data->online != !driver_data->offline))
 		return -EINVAL;
 
-	pr_debug("trying to register driver %s\n", driver_data->name);
+	pr_debug("trying to register driver %s, cpufreq_driver=%s\n",
+		driver_data->name, cpufreq_driver_name);
+
+	if (cpufreq_driver_name[0])
+		if (!driver_data->name ||
+			strcmp(cpufreq_driver_name, driver_data->name))
+				return -EINVAL;
 
 	/* Protect against concurrent CPU online/offline. */
 	cpus_read_lock();
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpufreq/cpufreq_governor.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpufreq/cpufreq_governor.c
@@ -145,7 +145,23 @@
 		time_elapsed = update_time - j_cdbs->prev_update_time;
 		j_cdbs->prev_update_time = update_time;
 
-		idle_time = cur_idle_time - j_cdbs->prev_cpu_idle;
+		/*
+		 * cur_idle_time could be smaller than j_cdbs->prev_cpu_idle if
+		 * it's obtained from get_cpu_idle_time_jiffy() when NOHZ is
+		 * off, where idle_time is calculated by the difference between
+		 * time elapsed in jiffies and "busy time" obtained from CPU
+		 * statistics.  If a CPU is 100% busy, the time elapsed and busy
+		 * time should grow with the same amount in two consecutive
+		 * samples, but in practice there could be a tiny difference,
+		 * making the accumulated idle time decrease sometimes.  Hence,
+		 * in this case, idle_time should be regarded as 0 in order to
+		 * make the further process correct.
+		 */
+		if (cur_idle_time > j_cdbs->prev_cpu_idle)
+			idle_time = cur_idle_time - j_cdbs->prev_cpu_idle;
+		else
+			idle_time = 0;
+
 		j_cdbs->prev_cpu_idle = cur_idle_time;
 
 		if (ignore_nice) {
@@ -162,7 +178,7 @@
 			 * calls, so the previous load value can be used then.
 			 */
 			load = j_cdbs->prev_load;
-		} else if (unlikely((int)idle_time > 2 * sampling_rate &&
+		} else if (unlikely(idle_time > 2 * sampling_rate &&
 				    j_cdbs->prev_load)) {
 			/*
 			 * If the CPU had gone completely idle and a task has
@@ -189,30 +205,15 @@
 			load = j_cdbs->prev_load;
 			j_cdbs->prev_load = 0;
 		} else {
-			if (time_elapsed >= idle_time) {
+			if (time_elapsed > idle_time)
 				load = 100 * (time_elapsed - idle_time) / time_elapsed;
-			} else {
-				/*
-				 * That can happen if idle_time is returned by
-				 * get_cpu_idle_time_jiffy().  In that case
-				 * idle_time is roughly equal to the difference
-				 * between time_elapsed and "busy time" obtained
-				 * from CPU statistics.  Then, the "busy time"
-				 * can end up being greater than time_elapsed
-				 * (for example, if jiffies_64 and the CPU
-				 * statistics are updated by different CPUs),
-				 * so idle_time may in fact be negative.  That
-				 * means, though, that the CPU was busy all
-				 * the time (on the rough average) during the
-				 * last sampling interval and 100 can be
-				 * returned as the load.
-				 */
-				load = (int)idle_time < 0 ? 100 : 0;
-			}
+			else
+				load = 0;
+
 			j_cdbs->prev_load = load;
 		}
 
-		if (unlikely((int)idle_time > 2 * sampling_rate)) {
+		if (unlikely(idle_time > 2 * sampling_rate)) {
 			unsigned int periods = idle_time / sampling_rate;
 
 			if (periods < idle_periods)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpufreq/cpufreq_governor_attr_set.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpufreq/cpufreq_governor_attr_set.c
@@ -74,8 +74,8 @@
 	if (count)
 		return count;
 
-	kobject_put(&attr_set->kobj);
 	mutex_destroy(&attr_set->update_lock);
+	kobject_put(&attr_set->kobj);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(gov_attr_set_put);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpufreq/freq_table.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpufreq/freq_table.c
@@ -60,7 +60,7 @@
 		return 0;
 }
 
-int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
+int cpufreq_frequency_table_verify(struct cpufreq_policy_data *policy,
 				   struct cpufreq_frequency_table *table)
 {
 	struct cpufreq_frequency_table *pos;
@@ -100,7 +100,7 @@
  * Generic routine to verify policy & frequency table, requires driver to set
  * policy->freq_table prior to it.
  */
-int cpufreq_generic_frequency_table_verify(struct cpufreq_policy *policy)
+int cpufreq_generic_frequency_table_verify(struct cpufreq_policy_data *policy)
 {
 	if (!policy->freq_table)
 		return -ENODEV;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpufreq/gx-suspmod.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpufreq/gx-suspmod.c
@@ -328,7 +328,7 @@
  *      for the hardware supported by the driver.
  */
 
-static int cpufreq_gx_verify(struct cpufreq_policy *policy)
+static int cpufreq_gx_verify(struct cpufreq_policy_data *policy)
 {
 	unsigned int tmp_freq = 0;
 	u8 tmp1, tmp2;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpufreq/highbank-cpufreq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpufreq/highbank-cpufreq.c
@@ -101,6 +101,13 @@
 }
 module_init(hb_cpufreq_driver_init);
 
+static const struct of_device_id __maybe_unused hb_cpufreq_of_match[] = {
+	{ .compatible = "calxeda,highbank" },
+	{ .compatible = "calxeda,ecx-2000" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, hb_cpufreq_of_match);
+
 MODULE_AUTHOR("Mark Langsdorf <mark.langsdorf@calxeda.com>");
 MODULE_DESCRIPTION("Calxeda Highbank cpufreq driver");
 MODULE_LICENSE("GPL");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpufreq/imx-cpufreq-dt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpufreq/imx-cpufreq-dt.c
@@ -44,19 +44,19 @@
 	mkt_segment = (cell_value & OCOTP_CFG3_MKT_SEGMENT_MASK) >> OCOTP_CFG3_MKT_SEGMENT_SHIFT;
 
 	/*
-	 * Early samples without fuses written report "0 0" which means
-	 * consumer segment and minimum speed grading.
-	 *
-	 * According to datasheet minimum speed grading is not supported for
-	 * consumer parts so clamp to 1 to avoid warning for "no OPPs"
+	 * Early samples without fuses written report "0 0" which may NOT
+	 * match any OPP defined in DT. So clamp to minimum OPP defined in
+	 * DT to avoid warning for "no OPPs".
 	 *
 	 * Applies to i.MX8M series SoCs.
 	 */
-	if (mkt_segment == 0 && speed_grade == 0 && (
-			of_machine_is_compatible("fsl,imx8mm") ||
-			of_machine_is_compatible("fsl,imx8mn") ||
-			of_machine_is_compatible("fsl,imx8mq")))
-		speed_grade = 1;
+	if (mkt_segment == 0 && speed_grade == 0) {
+		if (of_machine_is_compatible("fsl,imx8mm") ||
+		    of_machine_is_compatible("fsl,imx8mq"))
+			speed_grade = 1;
+		if (of_machine_is_compatible("fsl,imx8mn"))
+			speed_grade = 0xb;
+	}
 
 	supported_hw[0] = BIT(speed_grade);
 	supported_hw[1] = BIT(mkt_segment);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpufreq/imx6q-cpufreq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpufreq/imx6q-cpufreq.c
@@ -210,6 +210,14 @@
 	.suspend = cpufreq_generic_suspend,
 };
 
+static void imx6x_disable_freq_in_opp(struct device *dev, unsigned long freq)
+{
+	int ret = dev_pm_opp_disable(dev, freq);
+
+	if (ret < 0 && ret != -ENODEV)
+		dev_warn(dev, "failed to disable %ldMHz OPP\n", freq / 1000000);
+}
+
 #define OCOTP_CFG3			0x440
 #define OCOTP_CFG3_SPEED_SHIFT		16
 #define OCOTP_CFG3_SPEED_1P2GHZ		0x3
@@ -245,17 +253,15 @@
 	val &= 0x3;
 
 	if (val < OCOTP_CFG3_SPEED_996MHZ)
-		if (dev_pm_opp_disable(dev, 996000000))
-			dev_warn(dev, "failed to disable 996MHz OPP\n");
+		imx6x_disable_freq_in_opp(dev, 996000000);
 
 	if (of_machine_is_compatible("fsl,imx6q") ||
 	    of_machine_is_compatible("fsl,imx6qp")) {
 		if (val != OCOTP_CFG3_SPEED_852MHZ)
-			if (dev_pm_opp_disable(dev, 852000000))
-				dev_warn(dev, "failed to disable 852MHz OPP\n");
+			imx6x_disable_freq_in_opp(dev, 852000000);
+
 		if (val != OCOTP_CFG3_SPEED_1P2GHZ)
-			if (dev_pm_opp_disable(dev, 1200000000))
-				dev_warn(dev, "failed to disable 1.2GHz OPP\n");
+			imx6x_disable_freq_in_opp(dev, 1200000000);
 	}
 	iounmap(base);
 put_node:
@@ -281,6 +287,9 @@
 
 		np = of_find_compatible_node(NULL, NULL, "fsl,imx6ul-ocotp");
 		if (!np)
+			np = of_find_compatible_node(NULL, NULL,
+						     "fsl,imx6ull-ocotp");
+		if (!np)
 			return -ENOENT;
 
 		base = of_iomap(np, 0);
@@ -305,20 +314,16 @@
 	val >>= OCOTP_CFG3_SPEED_SHIFT;
 	val &= 0x3;
 
-	if (of_machine_is_compatible("fsl,imx6ul")) {
+	if (of_machine_is_compatible("fsl,imx6ul"))
 		if (val != OCOTP_CFG3_6UL_SPEED_696MHZ)
-			if (dev_pm_opp_disable(dev, 696000000))
-				dev_warn(dev, "failed to disable 696MHz OPP\n");
-	}
+			imx6x_disable_freq_in_opp(dev, 696000000);
 
 	if (of_machine_is_compatible("fsl,imx6ull")) {
-		if (val != OCOTP_CFG3_6ULL_SPEED_792MHZ)
-			if (dev_pm_opp_disable(dev, 792000000))
-				dev_warn(dev, "failed to disable 792MHz OPP\n");
+		if (val < OCOTP_CFG3_6ULL_SPEED_792MHZ)
+			imx6x_disable_freq_in_opp(dev, 792000000);
 
 		if (val != OCOTP_CFG3_6ULL_SPEED_900MHZ)
-			if (dev_pm_opp_disable(dev, 900000000))
-				dev_warn(dev, "failed to disable 900MHz OPP\n");
+			imx6x_disable_freq_in_opp(dev, 900000000);
 	}
 
 	return ret;
@@ -378,23 +383,24 @@
 		goto put_reg;
 	}
 
+	/* Because we have added the OPPs here, we must free them */
+	free_opp = true;
+
 	if (of_machine_is_compatible("fsl,imx6ul") ||
 	    of_machine_is_compatible("fsl,imx6ull")) {
 		ret = imx6ul_opp_check_speed_grading(cpu_dev);
 		if (ret) {
 			if (ret == -EPROBE_DEFER)
-				goto put_node;
+				goto out_free_opp;
 
 			dev_err(cpu_dev, "failed to read ocotp: %d\n",
 				ret);
-			goto put_node;
+			goto out_free_opp;
 		}
 	} else {
 		imx6q_opp_check_speed_grading(cpu_dev);
 	}
 
-	/* Because we have added the OPPs here, we must free them */
-	free_opp = true;
 	num = dev_pm_opp_get_opp_count(cpu_dev);
 	if (num < 0) {
 		ret = num;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpufreq/intel_pstate.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpufreq/intel_pstate.c
@@ -442,20 +442,6 @@
 			 (u32) cpu->acpi_perf_data.states[i].control);
 	}
 
-	/*
-	 * The _PSS table doesn't contain whole turbo frequency range.
-	 * This just contains +1 MHZ above the max non turbo frequency,
-	 * with control value corresponding to max turbo ratio. But
-	 * when cpufreq set policy is called, it will call with this
-	 * max frequency, which will cause a reduced performance as
-	 * this driver uses real max turbo frequency as the max
-	 * frequency. So correct this frequency in _PSS table to
-	 * correct max turbo frequency based on the turbo state.
-	 * Also need to convert to MHz as _PSS freq is in MHz.
-	 */
-	if (!global.turbo_disabled)
-		cpu->acpi_perf_data.states[0].core_frequency =
-					policy->cpuinfo.max_freq / 1000;
 	cpu->valid_pss_table = true;
 	pr_debug("_PPC limits will be enforced\n");
 
@@ -649,11 +635,12 @@
 	mutex_lock(&intel_pstate_limits_lock);
 
 	if (boot_cpu_has(X86_FEATURE_HWP_EPP)) {
-		u64 value;
-
-		ret = rdmsrl_on_cpu(cpu_data->cpu, MSR_HWP_REQUEST, &value);
-		if (ret)
-			goto return_pref;
+		/*
+		 * Use the cached HWP Request MSR value, because the register
+		 * itself may be updated by intel_pstate_hwp_boost_up() or
+		 * intel_pstate_hwp_boost_down() at any time.
+		 */
+		u64 value = READ_ONCE(cpu_data->hwp_req_cached);
 
 		value &= ~GENMASK_ULL(31, 24);
 
@@ -661,13 +648,18 @@
 			epp = epp_values[pref_index - 1];
 
 		value |= (u64)epp << 24;
+		/*
+		 * The only other updater of hwp_req_cached in the active mode,
+		 * intel_pstate_hwp_set(), is called under the same lock as this
+		 * function, so it cannot run in parallel with the update below.
+		 */
+		WRITE_ONCE(cpu_data->hwp_req_cached, value);
 		ret = wrmsrl_on_cpu(cpu_data->cpu, MSR_HWP_REQUEST, value);
 	} else {
 		if (epp == -EINVAL)
 			epp = (pref_index - 1) << 2;
 		ret = intel_pstate_set_epb(cpu_data->cpu, epp);
 	}
-return_pref:
 	mutex_unlock(&intel_pstate_limits_lock);
 
 	return ret;
@@ -756,7 +748,7 @@
 
 	rdmsrl_on_cpu(cpu, MSR_HWP_CAPABILITIES, &cap);
 	WRITE_ONCE(all_cpu_data[cpu]->hwp_cap_cached, cap);
-	if (global.no_turbo)
+	if (global.no_turbo || global.turbo_disabled)
 		*current_max = HWP_GUARANTEED_PERF(cap);
 	else
 		*current_max = HWP_HIGHEST_PERF(cap);
@@ -1058,7 +1050,7 @@
 
 	update_turbo_state();
 	if (global.turbo_disabled) {
-		pr_warn("Turbo disabled by BIOS or unavailable on processor\n");
+		pr_notice_once("Turbo disabled by BIOS or unavailable on processor\n");
 		mutex_unlock(&intel_pstate_limits_lock);
 		mutex_unlock(&intel_pstate_driver_lock);
 		return -EPERM;
@@ -1560,20 +1552,22 @@
 static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
 {
 	cpu->pstate.min_pstate = pstate_funcs.get_min();
-	cpu->pstate.max_pstate = pstate_funcs.get_max();
 	cpu->pstate.max_pstate_physical = pstate_funcs.get_max_physical();
 	cpu->pstate.turbo_pstate = pstate_funcs.get_turbo();
 	cpu->pstate.scaling = pstate_funcs.get_scaling();
-	cpu->pstate.max_freq = cpu->pstate.max_pstate * cpu->pstate.scaling;
 
 	if (hwp_active && !hwp_mode_bdw) {
 		unsigned int phy_max, current_max;
 
 		intel_pstate_get_hwp_max(cpu->cpu, &phy_max, &current_max);
 		cpu->pstate.turbo_freq = phy_max * cpu->pstate.scaling;
+		cpu->pstate.turbo_pstate = phy_max;
+		cpu->pstate.max_pstate = HWP_GUARANTEED_PERF(READ_ONCE(cpu->hwp_cap_cached));
 	} else {
 		cpu->pstate.turbo_freq = cpu->pstate.turbo_pstate * cpu->pstate.scaling;
+		cpu->pstate.max_pstate = pstate_funcs.get_max();
 	}
+	cpu->pstate.max_freq = cpu->pstate.max_pstate * cpu->pstate.scaling;
 
 	if (pstate_funcs.get_aperf_mperf_shift)
 		cpu->aperf_mperf_shift = pstate_funcs.get_aperf_mperf_shift();
@@ -2036,8 +2030,9 @@
 			cpu->pstate.max_freq : cpu->pstate.turbo_freq;
 }
 
-static void intel_pstate_update_perf_limits(struct cpufreq_policy *policy,
-					    struct cpudata *cpu)
+static void intel_pstate_update_perf_limits(struct cpudata *cpu,
+					    unsigned int policy_min,
+					    unsigned int policy_max)
 {
 	int max_freq = intel_pstate_get_max_freq(cpu);
 	int32_t max_policy_perf, min_policy_perf;
@@ -2056,18 +2051,17 @@
 		turbo_max = cpu->pstate.turbo_pstate;
 	}
 
-	max_policy_perf = max_state * policy->max / max_freq;
-	if (policy->max == policy->min) {
+	max_policy_perf = max_state * policy_max / max_freq;
+	if (policy_max == policy_min) {
 		min_policy_perf = max_policy_perf;
 	} else {
-		min_policy_perf = max_state * policy->min / max_freq;
+		min_policy_perf = max_state * policy_min / max_freq;
 		min_policy_perf = clamp_t(int32_t, min_policy_perf,
 					  0, max_policy_perf);
 	}
 
 	pr_debug("cpu:%d max_state %d min_policy_perf:%d max_policy_perf:%d\n",
-		 policy->cpu, max_state,
-		 min_policy_perf, max_policy_perf);
+		 cpu->cpu, max_state, min_policy_perf, max_policy_perf);
 
 	/* Normalize user input to [min_perf, max_perf] */
 	if (per_cpu_limits) {
@@ -2081,7 +2075,7 @@
 		global_min = DIV_ROUND_UP(turbo_max * global.min_perf_pct, 100);
 		global_min = clamp_t(int32_t, global_min, 0, global_max);
 
-		pr_debug("cpu:%d global_min:%d global_max:%d\n", policy->cpu,
+		pr_debug("cpu:%d global_min:%d global_max:%d\n", cpu->cpu,
 			 global_min, global_max);
 
 		cpu->min_perf_ratio = max(min_policy_perf, global_min);
@@ -2094,7 +2088,7 @@
 					  cpu->max_perf_ratio);
 
 	}
-	pr_debug("cpu:%d max_perf_ratio:%d min_perf_ratio:%d\n", policy->cpu,
+	pr_debug("cpu:%d max_perf_ratio:%d min_perf_ratio:%d\n", cpu->cpu,
 		 cpu->max_perf_ratio,
 		 cpu->min_perf_ratio);
 }
@@ -2114,7 +2108,7 @@
 
 	mutex_lock(&intel_pstate_limits_lock);
 
-	intel_pstate_update_perf_limits(policy, cpu);
+	intel_pstate_update_perf_limits(cpu, policy->min, policy->max);
 
 	if (cpu->policy == CPUFREQ_POLICY_PERFORMANCE) {
 		/*
@@ -2143,8 +2137,8 @@
 	return 0;
 }
 
-static void intel_pstate_adjust_policy_max(struct cpufreq_policy *policy,
-					 struct cpudata *cpu)
+static void intel_pstate_adjust_policy_max(struct cpudata *cpu,
+					   struct cpufreq_policy_data *policy)
 {
 	if (!hwp_active &&
 	    cpu->pstate.max_pstate_physical > cpu->pstate.max_pstate &&
@@ -2155,7 +2149,7 @@
 	}
 }
 
-static int intel_pstate_verify_policy(struct cpufreq_policy *policy)
+static int intel_pstate_verify_policy(struct cpufreq_policy_data *policy)
 {
 	struct cpudata *cpu = all_cpu_data[policy->cpu];
 
@@ -2163,11 +2157,7 @@
 	cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
 				     intel_pstate_get_max_freq(cpu));
 
-	if (policy->policy != CPUFREQ_POLICY_POWERSAVE &&
-	    policy->policy != CPUFREQ_POLICY_PERFORMANCE)
-		return -EINVAL;
-
-	intel_pstate_adjust_policy_max(policy, cpu);
+	intel_pstate_adjust_policy_max(cpu, policy);
 
 	return 0;
 }
@@ -2268,7 +2258,7 @@
 	.name		= "intel_pstate",
 };
 
-static int intel_cpufreq_verify_policy(struct cpufreq_policy *policy)
+static int intel_cpufreq_verify_policy(struct cpufreq_policy_data *policy)
 {
 	struct cpudata *cpu = all_cpu_data[policy->cpu];
 
@@ -2276,9 +2266,9 @@
 	cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
 				     intel_pstate_get_max_freq(cpu));
 
-	intel_pstate_adjust_policy_max(policy, cpu);
+	intel_pstate_adjust_policy_max(cpu, policy);
 
-	intel_pstate_update_perf_limits(policy, cpu);
+	intel_pstate_update_perf_limits(cpu, policy->min, policy->max);
 
 	return 0;
 }
@@ -2530,9 +2520,15 @@
 {
 	int ret;
 
-	if (size == 3 && !strncmp(buf, "off", size))
-		return intel_pstate_driver ?
-			intel_pstate_unregister_driver() : -EINVAL;
+	if (size == 3 && !strncmp(buf, "off", size)) {
+		if (!intel_pstate_driver)
+			return -EINVAL;
+
+		if (hwp_active)
+			return -EBUSY;
+
+		return intel_pstate_unregister_driver();
+	}
 
 	if (size == 6 && !strncmp(buf, "active", size)) {
 		if (intel_pstate_driver) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpufreq/longrun.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpufreq/longrun.c
@@ -122,7 +122,7 @@
  * Validates a new CPUFreq policy. This function has to be called with
  * cpufreq_driver locked.
  */
-static int longrun_verify_policy(struct cpufreq_policy *policy)
+static int longrun_verify_policy(struct cpufreq_policy_data *policy)
 {
 	if (!policy)
 		return -EINVAL;
@@ -130,10 +130,6 @@
 	policy->cpu = 0;
 	cpufreq_verify_within_cpu_limits(policy);
 
-	if ((policy->policy != CPUFREQ_POLICY_POWERSAVE) &&
-	    (policy->policy != CPUFREQ_POLICY_PERFORMANCE))
-		return -EINVAL;
-
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpufreq/loongson1-cpufreq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpufreq/loongson1-cpufreq.c
@@ -216,6 +216,7 @@
 
 module_platform_driver(ls1x_cpufreq_platdrv);
 
+MODULE_ALIAS("platform:ls1x-cpufreq");
 MODULE_AUTHOR("Kelvin Cheung <keguang.zhang@gmail.com>");
 MODULE_DESCRIPTION("Loongson1 CPUFreq driver");
 MODULE_LICENSE("GPL");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpufreq/loongson2_cpufreq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpufreq/loongson2_cpufreq.c
@@ -167,7 +167,9 @@
 
 	ret = cpufreq_register_driver(&loongson2_cpufreq_driver);
 
-	if (!ret && !nowait) {
+	if (ret) {
+		platform_driver_unregister(&platform_driver);
+	} else if (!nowait) {
 		saved_cpu_wait = cpu_wait;
 		cpu_wait = loongson2_cpu_wait;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpufreq/mediatek-cpufreq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpufreq/mediatek-cpufreq.c
@@ -540,6 +540,7 @@
 
 	{ }
 };
+MODULE_DEVICE_TABLE(of, mtk_cpufreq_machines);
 
 static int __init mtk_cpufreq_driver_init(void)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpufreq/pcc-cpufreq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpufreq/pcc-cpufreq.c
@@ -109,7 +109,7 @@
 
 static struct pcc_cpu __percpu *pcc_cpu_info;
 
-static int pcc_cpufreq_verify(struct cpufreq_policy *policy)
+static int pcc_cpufreq_verify(struct cpufreq_policy_data *policy)
 {
 	cpufreq_verify_within_cpu_limits(policy);
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpufreq/pmac32-cpufreq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpufreq/pmac32-cpufreq.c
@@ -471,6 +471,10 @@
 	if (slew_done_gpio_np)
 		slew_done_gpio = read_gpio(slew_done_gpio_np);
 
+	of_node_put(volt_gpio_np);
+	of_node_put(freq_gpio_np);
+	of_node_put(slew_done_gpio_np);
+
 	/* If we use the frequency GPIOs, calculate the min/max speeds based
 	 * on the bus frequencies
 	 */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpufreq/powernow-k8.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpufreq/powernow-k8.c
@@ -878,9 +878,9 @@
 
 /* Take a frequency, and issue the fid/vid transition command */
 static int transition_frequency_fidvid(struct powernow_k8_data *data,
-		unsigned int index)
+		unsigned int index,
+		struct cpufreq_policy *policy)
 {
-	struct cpufreq_policy *policy;
 	u32 fid = 0;
 	u32 vid = 0;
 	int res;
@@ -912,9 +912,6 @@
 	freqs.old = find_khz_freq_from_fid(data->currfid);
 	freqs.new = find_khz_freq_from_fid(fid);
 
-	policy = cpufreq_cpu_get(smp_processor_id());
-	cpufreq_cpu_put(policy);
-
 	cpufreq_freq_transition_begin(policy, &freqs);
 	res = transition_fid_vid(data, fid, vid);
 	cpufreq_freq_transition_end(policy, &freqs, res);
@@ -969,7 +966,7 @@
 
 	powernow_k8_acpi_pst_values(data, newstate);
 
-	ret = transition_frequency_fidvid(data, newstate);
+	ret = transition_frequency_fidvid(data, newstate, pol);
 
 	if (ret) {
 		pr_err("transition frequency failed\n");
@@ -1104,7 +1101,8 @@
 
 	kfree(data->powernow_table);
 	kfree(data);
-	for_each_cpu(cpu, pol->cpus)
+	/* pol->cpus will be empty here, use related_cpus instead. */
+	for_each_cpu(cpu, pol->related_cpus)
 		per_cpu(powernow_data, cpu) = NULL;
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpufreq/powernv-cpufreq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpufreq/powernv-cpufreq.c
@@ -36,6 +36,7 @@
 #define MAX_PSTATE_SHIFT	32
 #define LPSTATE_SHIFT		48
 #define GPSTATE_SHIFT		56
+#define MAX_NR_CHIPS		32
 
 #define MAX_RAMP_DOWN_TIME				5120
 /*
@@ -884,12 +885,15 @@
 				unsigned long action, void *unused)
 {
 	int cpu;
-	struct cpufreq_policy cpu_policy;
+	struct cpufreq_policy *cpu_policy;
 
 	rebooting = true;
 	for_each_online_cpu(cpu) {
-		cpufreq_get_policy(&cpu_policy, cpu);
-		powernv_cpufreq_target_index(&cpu_policy, get_nominal_index());
+		cpu_policy = cpufreq_cpu_get(cpu);
+		if (!cpu_policy)
+			continue;
+		powernv_cpufreq_target_index(cpu_policy, get_nominal_index());
+		cpufreq_cpu_put(cpu_policy);
 	}
 
 	return NOTIFY_DONE;
@@ -902,6 +906,7 @@
 void powernv_cpufreq_work_fn(struct work_struct *work)
 {
 	struct chip *chip = container_of(work, struct chip, throttle);
+	struct cpufreq_policy *policy;
 	unsigned int cpu;
 	cpumask_t mask;
 
@@ -916,12 +921,14 @@
 	chip->restore = false;
 	for_each_cpu(cpu, &mask) {
 		int index;
-		struct cpufreq_policy policy;
 
-		cpufreq_get_policy(&policy, cpu);
-		index = cpufreq_table_find_index_c(&policy, policy.cur);
-		powernv_cpufreq_target_index(&policy, index);
-		cpumask_andnot(&mask, &mask, policy.cpus);
+		policy = cpufreq_cpu_get(cpu);
+		if (!policy)
+			continue;
+		index = cpufreq_table_find_index_c(policy, policy->cur);
+		powernv_cpufreq_target_index(policy, index);
+		cpumask_andnot(&mask, &mask, policy->cpus);
+		cpufreq_cpu_put(policy);
 	}
 out:
 	put_online_cpus();
@@ -1041,9 +1048,22 @@
 
 static int init_chip_info(void)
 {
-	unsigned int chip[256];
+	unsigned int *chip;
 	unsigned int cpu, i;
 	unsigned int prev_chip_id = UINT_MAX;
+	cpumask_t *chip_cpu_mask;
+	int ret = 0;
+
+	chip = kcalloc(num_possible_cpus(), sizeof(*chip), GFP_KERNEL);
+	if (!chip)
+		return -ENOMEM;
+
+	/* Allocate a chip cpu mask large enough to fit mask for all chips */
+	chip_cpu_mask = kcalloc(MAX_NR_CHIPS, sizeof(cpumask_t), GFP_KERNEL);
+	if (!chip_cpu_mask) {
+		ret = -ENOMEM;
+		goto free_and_return;
+	}
 
 	for_each_possible_cpu(cpu) {
 		unsigned int id = cpu_to_chip_id(cpu);
@@ -1052,25 +1072,38 @@
 			prev_chip_id = id;
 			chip[nr_chips++] = id;
 		}
+		cpumask_set_cpu(cpu, &chip_cpu_mask[nr_chips-1]);
 	}
 
 	chips = kcalloc(nr_chips, sizeof(struct chip), GFP_KERNEL);
-	if (!chips)
-		return -ENOMEM;
+	if (!chips) {
+		ret = -ENOMEM;
+		goto out_free_chip_cpu_mask;
+	}
 
 	for (i = 0; i < nr_chips; i++) {
 		chips[i].id = chip[i];
-		cpumask_copy(&chips[i].mask, cpumask_of_node(chip[i]));
+		cpumask_copy(&chips[i].mask, &chip_cpu_mask[i]);
 		INIT_WORK(&chips[i].throttle, powernv_cpufreq_work_fn);
 		for_each_cpu(cpu, &chips[i].mask)
 			per_cpu(chip_info, cpu) =  &chips[i];
 	}
 
-	return 0;
+out_free_chip_cpu_mask:
+	kfree(chip_cpu_mask);
+free_and_return:
+	kfree(chip);
+	return ret;
 }
 
 static inline void clean_chip_info(void)
 {
+	int i;
+
+	/* flush any pending work items */
+	if (chips)
+		for (i = 0; i < nr_chips; i++)
+			cancel_work_sync(&chips[i].throttle);
 	kfree(chips);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpufreq/qcom-cpufreq-nvmem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpufreq/qcom-cpufreq-nvmem.c
@@ -305,6 +305,7 @@
 	{ .compatible = "qcom,qcs404", .data = &match_data_qcs404 },
 	{},
 };
+MODULE_DEVICE_TABLE(of, qcom_cpufreq_match_list);
 
 /*
  * Since the driver depends on smem and nvmem drivers, which may
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpufreq/s3c64xx-cpufreq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpufreq/s3c64xx-cpufreq.c
@@ -25,6 +25,7 @@
 	unsigned int vddarm_max;
 };
 
+#ifdef CONFIG_REGULATOR
 static struct s3c64xx_dvfs s3c64xx_dvfs_table[] = {
 	[0] = { 1000000, 1150000 },
 	[1] = { 1050000, 1150000 },
@@ -32,6 +33,7 @@
 	[3] = { 1200000, 1350000 },
 	[4] = { 1300000, 1350000 },
 };
+#endif
 
 static struct cpufreq_frequency_table s3c64xx_freq_table[] = {
 	{ 0, 0,  66000 },
@@ -53,15 +55,16 @@
 static int s3c64xx_cpufreq_set_target(struct cpufreq_policy *policy,
 				      unsigned int index)
 {
-	struct s3c64xx_dvfs *dvfs;
-	unsigned int old_freq, new_freq;
+	unsigned int new_freq = s3c64xx_freq_table[index].frequency;
 	int ret;
 
+#ifdef CONFIG_REGULATOR
+	struct s3c64xx_dvfs *dvfs;
+	unsigned int old_freq;
+
 	old_freq = clk_get_rate(policy->clk) / 1000;
-	new_freq = s3c64xx_freq_table[index].frequency;
 	dvfs = &s3c64xx_dvfs_table[s3c64xx_freq_table[index].driver_data];
 
-#ifdef CONFIG_REGULATOR
 	if (vddarm && new_freq > old_freq) {
 		ret = regulator_set_voltage(vddarm,
 					    dvfs->vddarm_min,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpufreq/scpi-cpufreq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpufreq/scpi-cpufreq.c
@@ -239,6 +239,7 @@
 };
 module_platform_driver(scpi_cpufreq_platdrv);
 
+MODULE_ALIAS("platform:scpi-cpufreq");
 MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
 MODULE_DESCRIPTION("ARM SCPI CPUFreq interface driver");
 MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpufreq/sh-cpufreq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpufreq/sh-cpufreq.c
@@ -87,7 +87,7 @@
 	return work_on_cpu(policy->cpu, __sh_cpufreq_target, &data);
 }
 
-static int sh_cpufreq_verify(struct cpufreq_policy *policy)
+static int sh_cpufreq_verify(struct cpufreq_policy_data *policy)
 {
 	struct clk *cpuclk = &per_cpu(sh_cpuclk, policy->cpu);
 	struct cpufreq_frequency_table *freq_table;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpufreq/sti-cpufreq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpufreq/sti-cpufreq.c
@@ -141,7 +141,8 @@
 static const struct reg_field *sti_cpufreq_match(void)
 {
 	if (of_machine_is_compatible("st,stih407") ||
-	    of_machine_is_compatible("st,stih410"))
+	    of_machine_is_compatible("st,stih410") ||
+	    of_machine_is_compatible("st,stih418"))
 		return sti_stih407_dvfs_regfields;
 
 	return NULL;
@@ -258,7 +259,8 @@
 	int ret;
 
 	if ((!of_machine_is_compatible("st,stih407")) &&
-		(!of_machine_is_compatible("st,stih410")))
+		(!of_machine_is_compatible("st,stih410")) &&
+		(!of_machine_is_compatible("st,stih418")))
 		return -ENODEV;
 
 	ddata.cpu = get_cpu_device(0);
@@ -290,6 +292,13 @@
 }
 module_init(sti_cpufreq_init);
 
+static const struct of_device_id __maybe_unused sti_cpufreq_of_match[] = {
+	{ .compatible = "st,stih407" },
+	{ .compatible = "st,stih410" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, sti_cpufreq_of_match);
+
 MODULE_DESCRIPTION("STMicroelectronics CPUFreq/OPP driver");
 MODULE_AUTHOR("Ajitpal Singh <ajitpal.singh@st.com>");
 MODULE_AUTHOR("Lee Jones <lee.jones@linaro.org>");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpufreq/sun50i-cpufreq-nvmem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpufreq/sun50i-cpufreq-nvmem.c
@@ -25,7 +25,7 @@
 static struct platform_device *cpufreq_dt_pdev, *sun50i_cpufreq_pdev;
 
 /**
- * sun50i_cpufreq_get_efuse() - Parse and return efuse value present on SoC
+ * sun50i_cpufreq_get_efuse() - Determine speed grade from efuse value
  * @versions: Set to the value parsed from efuse
  *
  * Returns 0 if success.
@@ -69,21 +69,16 @@
 		return PTR_ERR(speedbin);
 
 	efuse_value = (*speedbin >> NVMEM_SHIFT) & NVMEM_MASK;
-	switch (efuse_value) {
-	case 0b0001:
-		*versions = 1;
-		break;
-	case 0b0011:
-		*versions = 2;
-		break;
-	default:
-		/*
-		 * For other situations, we treat it as bin0.
-		 * This vf table can be run for any good cpu.
-		 */
+
+	/*
+	 * We treat unexpected efuse values as if the SoC was from
+	 * the slowest bin. Expected efuse values are 1-3, slowest
+	 * to fastest.
+	 */
+	if (efuse_value >= 1 && efuse_value <= 3)
+		*versions = efuse_value - 1;
+	else
 		*versions = 0;
-		break;
-	}
 
 	kfree(speedbin);
 	return 0;
@@ -103,8 +98,10 @@
 		return -ENOMEM;
 
 	ret = sun50i_cpufreq_get_efuse(&speed);
-	if (ret)
+	if (ret) {
+		kfree(opp_tables);
 		return ret;
+	}
 
 	snprintf(name, MAX_NAME_LEN, "speed%d", speed);
 
@@ -172,6 +169,7 @@
 	{ .compatible = "allwinner,sun50i-h6" },
 	{}
 };
+MODULE_DEVICE_TABLE(of, sun50i_cpufreq_match_list);
 
 static const struct of_device_id *sun50i_cpufreq_match_node(void)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpufreq/unicore2-cpufreq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpufreq/unicore2-cpufreq.c
@@ -22,7 +22,7 @@
 /* make sure that only the "userspace" governor is run
  * -- anything else wouldn't make sense on this platform, anyway.
  */
-static int ucv2_verify_speed(struct cpufreq_policy *policy)
+static int ucv2_verify_speed(struct cpufreq_policy_data *policy)
 {
 	if (policy->cpu)
 		return -EINVAL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpuidle/cpuidle.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpuidle/cpuidle.c
@@ -148,7 +148,8 @@
 	 */
 	stop_critical_timings();
 	drv->states[index].enter_s2idle(dev, drv, index);
-	WARN_ON(!irqs_disabled());
+	if (WARN_ON_ONCE(!irqs_disabled()))
+		local_irq_disable();
 	/*
 	 * timekeeping_resume() that will be called by tick_unfreeze() for the
 	 * first CPU executing it calls functions containing RCU read-side
@@ -384,6 +385,7 @@
 			continue;
 
 		limit_ns = (u64)drv->states[i].target_residency * NSEC_PER_USEC;
+		break;
 	}
 
 	dev->poll_limit_ns = limit_ns;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpuidle/driver.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpuidle/driver.c
@@ -62,24 +62,23 @@
  * __cpuidle_set_driver - set per CPU driver variables for the given driver.
  * @drv: a valid pointer to a struct cpuidle_driver
  *
- * For each CPU in the driver's cpumask, unset the registered driver per CPU
- * to @drv.
- *
- * Returns 0 on success, -EBUSY if the CPUs have driver(s) already.
+ * Returns 0 on success, -EBUSY if any CPU in the cpumask have a driver
+ * different from drv already.
  */
 static inline int __cpuidle_set_driver(struct cpuidle_driver *drv)
 {
 	int cpu;
 
 	for_each_cpu(cpu, drv->cpumask) {
+		struct cpuidle_driver *old_drv;
 
-		if (__cpuidle_get_cpu_driver(cpu)) {
-			__cpuidle_unset_driver(drv);
+		old_drv = __cpuidle_get_cpu_driver(cpu);
+		if (old_drv && old_drv != drv)
 			return -EBUSY;
-		}
+	}
 
+	for_each_cpu(cpu, drv->cpumask)
 		per_cpu(cpuidle_drivers, cpu) = drv;
-	}
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpuidle/dt_idle_states.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpuidle/dt_idle_states.c
@@ -224,6 +224,6 @@
 	 * also be 0 on platforms with missing DT idle states or legacy DT
 	 * configuration predating the DT idle states bindings.
 	 */
-	return i;
+	return state_idx - start_idx;
 }
 EXPORT_SYMBOL_GPL(dt_init_idle_driver);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpuidle/governors/teo.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpuidle/governors/teo.c
@@ -194,7 +194,7 @@
 	 * pattern detection.
 	 */
 	cpu_data->intervals[cpu_data->interval_idx++] = measured_us;
-	if (cpu_data->interval_idx > INTERVALS)
+	if (cpu_data->interval_idx >= INTERVALS)
 		cpu_data->interval_idx = 0;
 }
 
@@ -233,8 +233,8 @@
 {
 	struct teo_cpu *cpu_data = per_cpu_ptr(&teo_cpus, dev->cpu);
 	int latency_req = cpuidle_governor_latency_req(dev->cpu);
-	unsigned int duration_us, count;
-	int max_early_idx, constraint_idx, idx, i;
+	unsigned int duration_us, hits, misses, early_hits;
+	int max_early_idx, prev_max_early_idx, constraint_idx, idx, i;
 	ktime_t delta_tick;
 
 	if (dev->last_state_idx >= 0) {
@@ -247,8 +247,11 @@
 	cpu_data->sleep_length_ns = tick_nohz_get_sleep_length(&delta_tick);
 	duration_us = ktime_to_us(cpu_data->sleep_length_ns);
 
-	count = 0;
+	hits = 0;
+	misses = 0;
+	early_hits = 0;
 	max_early_idx = -1;
+	prev_max_early_idx = -1;
 	constraint_idx = drv->state_count;
 	idx = -1;
 
@@ -258,23 +261,62 @@
 
 		if (s->disabled || su->disable) {
 			/*
-			 * If the "early hits" metric of a disabled state is
-			 * greater than the current maximum, it should be taken
-			 * into account, because it would be a mistake to select
-			 * a deeper state with lower "early hits" metric.  The
-			 * index cannot be changed to point to it, however, so
-			 * just increase the max count alone and let the index
-			 * still point to a shallower idle state.
+			 * Ignore disabled states with target residencies beyond
+			 * the anticipated idle duration.
 			 */
-			if (max_early_idx >= 0 &&
-			    count < cpu_data->states[i].early_hits)
-				count = cpu_data->states[i].early_hits;
+			if (s->target_residency > duration_us)
+				continue;
+
+			/*
+			 * This state is disabled, so the range of idle duration
+			 * values corresponding to it is covered by the current
+			 * candidate state, but still the "hits" and "misses"
+			 * metrics of the disabled state need to be used to
+			 * decide whether or not the state covering the range in
+			 * question is good enough.
+			 */
+			hits = cpu_data->states[i].hits;
+			misses = cpu_data->states[i].misses;
+
+			if (early_hits >= cpu_data->states[i].early_hits ||
+			    idx < 0)
+				continue;
+
+			/*
+			 * If the current candidate state has been the one with
+			 * the maximum "early hits" metric so far, the "early
+			 * hits" metric of the disabled state replaces the
+			 * current "early hits" count to avoid selecting a
+			 * deeper state with lower "early hits" metric.
+			 */
+			if (max_early_idx == idx) {
+				early_hits = cpu_data->states[i].early_hits;
+				continue;
+			}
+
+			/*
+			 * The current candidate state is closer to the disabled
+			 * one than the current maximum "early hits" state, so
+			 * replace the latter with it, but in case the maximum
+			 * "early hits" state index has not been set so far,
+			 * check if the current candidate state is not too
+			 * shallow for that role.
+			 */
+			if (!(tick_nohz_tick_stopped() &&
+			      drv->states[idx].target_residency < TICK_USEC)) {
+				prev_max_early_idx = max_early_idx;
+				early_hits = cpu_data->states[i].early_hits;
+				max_early_idx = idx;
+			}
 
 			continue;
 		}
 
-		if (idx < 0)
+		if (idx < 0) {
 			idx = i; /* first enabled state */
+			hits = cpu_data->states[i].hits;
+			misses = cpu_data->states[i].misses;
+		}
 
 		if (s->target_residency > duration_us)
 			break;
@@ -283,11 +325,14 @@
 			constraint_idx = i;
 
 		idx = i;
+		hits = cpu_data->states[i].hits;
+		misses = cpu_data->states[i].misses;
 
-		if (count < cpu_data->states[i].early_hits &&
+		if (early_hits < cpu_data->states[i].early_hits &&
 		    !(tick_nohz_tick_stopped() &&
 		      drv->states[i].target_residency < TICK_USEC)) {
-			count = cpu_data->states[i].early_hits;
+			prev_max_early_idx = max_early_idx;
+			early_hits = cpu_data->states[i].early_hits;
 			max_early_idx = i;
 		}
 	}
@@ -300,10 +345,19 @@
 	 * "early hits" metric, but if that cannot be determined, just use the
 	 * state selected so far.
 	 */
-	if (cpu_data->states[idx].hits <= cpu_data->states[idx].misses &&
-	    max_early_idx >= 0) {
-		idx = max_early_idx;
-		duration_us = drv->states[idx].target_residency;
+	if (hits <= misses) {
+		/*
+		 * The current candidate state is not suitable, so take the one
+		 * whose "early hits" metric is the maximum for the range of
+		 * shallower states.
+		 */
+		if (idx == max_early_idx)
+			max_early_idx = prev_max_early_idx;
+
+		if (max_early_idx >= 0) {
+			idx = max_early_idx;
+			duration_us = drv->states[idx].target_residency;
+		}
 	}
 
 	/*
@@ -316,10 +370,9 @@
 	if (idx < 0) {
 		idx = 0; /* No states enabled. Must use 0. */
 	} else if (idx > 0) {
+		unsigned int count = 0;
 		u64 sum = 0;
 
-		count = 0;
-
 		/*
 		 * Count and sum the most recent idle duration values less than
 		 * the current expected idle duration value.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/cpuidle/sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/cpuidle/sysfs.c
@@ -480,6 +480,7 @@
 		ret = kobject_init_and_add(&kobj->kobj, &ktype_state_cpuidle,
 					   &kdev->kobj, "state%d", i);
 		if (ret) {
+			kobject_put(&kobj->kobj);
 			kfree(kobj);
 			goto error_state;
 		}
@@ -611,6 +612,7 @@
 	ret = kobject_init_and_add(&kdrv->kobj, &ktype_driver_cpuidle,
 				   &kdev->kobj, "driver");
 	if (ret) {
+		kobject_put(&kdrv->kobj);
 		kfree(kdrv);
 		return ret;
 	}
@@ -698,17 +700,18 @@
 	if (!kdev)
 		return -ENOMEM;
 	kdev->dev = dev;
-	dev->kobj_dev = kdev;
 
 	init_completion(&kdev->kobj_unregister);
 
 	error = kobject_init_and_add(&kdev->kobj, &ktype_cpuidle, &cpu_dev->kobj,
 				   "cpuidle");
 	if (error) {
+		kobject_put(&kdev->kobj);
 		kfree(kdev);
 		return error;
 	}
 
+	dev->kobj_dev = kdev;
 	kobject_uevent(&kdev->kobj, KOBJ_ADD);
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/Kconfig
@@ -287,6 +287,7 @@
 	select CRYPTO_AUTHENC
 	select CRYPTO_BLKCIPHER
 	select CRYPTO_HASH
+	select CRYPTO_LIB_DES
 	select HW_RANDOM
 	depends on FSL_SOC
 	help
@@ -332,6 +333,7 @@
 	depends on PPC && 4xx
 	select CRYPTO_HASH
 	select CRYPTO_AEAD
+	select CRYPTO_AES
 	select CRYPTO_LIB_AES
 	select CRYPTO_CCM
 	select CRYPTO_CTR
@@ -489,11 +491,9 @@
 endif # if CRYPTO_DEV_UX500
 
 config CRYPTO_DEV_ATMEL_AUTHENC
-	tristate "Support for Atmel IPSEC/SSL hw accelerator"
+	bool "Support for Atmel IPSEC/SSL hw accelerator"
 	depends on ARCH_AT91 || COMPILE_TEST
-	select CRYPTO_AUTHENC
-	select CRYPTO_DEV_ATMEL_AES
-	select CRYPTO_DEV_ATMEL_SHA
+	depends on CRYPTO_DEV_ATMEL_AES
 	help
 	  Some Atmel processors can combine the AES and SHA hw accelerators
 	  to enhance support of IPSEC/SSL.
@@ -506,6 +506,8 @@
 	select CRYPTO_AES
 	select CRYPTO_AEAD
 	select CRYPTO_BLKCIPHER
+	select CRYPTO_AUTHENC if CRYPTO_DEV_ATMEL_AUTHENC
+	select CRYPTO_DEV_ATMEL_SHA if CRYPTO_DEV_ATMEL_AUTHENC
 	help
 	  Some Atmel processors have AES hw accelerator.
 	  Select this if you want to use the Atmel module for
@@ -542,6 +544,7 @@
 
 config CRYPTO_DEV_ATMEL_I2C
 	tristate
+	select BITREVERSE
 
 config CRYPTO_DEV_ATMEL_ECC
 	tristate "Support for Microchip / Atmel ECC hw accelerator"
@@ -697,6 +700,38 @@
 	  This driver interfaces with the hardware crypto accelerator.
 	  Supporting cbc/ecb chainmode, and aes/des/des3_ede cipher mode.
 
+config CRYPTO_DEV_ZYNQMP_SHA3
+	tristate "Support for Xilinx ZynqMP SHA3 hw accelerator"
+	depends on ARCH_ZYNQMP || COMPILE_TEST
+	select CRYPTO_HASH
+	help
+	  Xilinx processors have SHA384 engine used for calculation
+	  of hash. This driver interfaces with SHA3 hw accelerator.
+	  Select this if you want to use the ZynqMP module for
+	  Keccak-SHA384 algorithms.
+
+config CRYPTO_DEV_XILINX_RSA
+	tristate "Support for Xilinx ZynqMP RSA hw accelerator"
+	depends on ARCH_ZYNQMP || COMPILE_TEST
+	select CRYPTO_AES
+	select CRYPTO_BLKCIPHER
+	help
+	  Xilinx processors have RSA hw accelerator used for signature
+	  generation and verification. This driver interfaces with RSA
+	  hw accelerator. Select this if you want to use the ZynqMP module
+	  for RSA algorithms.
+
+config CRYPTO_DEV_ZYNQMP_AES
+	tristate "Support for Xilinx ZynqMP AES hw accelerator"
+	depends on ARCH_ZYNQMP || COMPILE_TEST
+	select CRYPTO_AES
+	select CRYPTO_BLKCIPHER
+	help
+	  Xilinx processors have AES-GCM engine used for symmetric key
+	  encryption and decryption. This driver interfaces with AES hw
+	  accelerator. Select this if you want to use the ZynqMP module
+	  for AES algorithms.
+
 config CRYPTO_DEV_MEDIATEK
 	tristate "MediaTek's EIP97 Cryptographic Engine driver"
 	depends on (ARM && ARCH_MEDIATEK) || COMPILE_TEST
@@ -737,7 +772,7 @@
 
 config CRYPTO_DEV_SAFEXCEL
 	tristate "Inside Secure's SafeXcel cryptographic engine driver"
-	depends on OF || PCI || COMPILE_TEST
+	depends on (OF || PCI || COMPILE_TEST) && HAS_IOMEM
 	select CRYPTO_LIB_AES
 	select CRYPTO_AUTHENC
 	select CRYPTO_BLKCIPHER
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/Makefile
@@ -47,4 +47,7 @@
 obj-$(CONFIG_CRYPTO_DEV_BCM_SPU) += bcm/
 obj-$(CONFIG_CRYPTO_DEV_SAFEXCEL) += inside-secure/
 obj-$(CONFIG_CRYPTO_DEV_ARTPEC6) += axis/
+obj-$(CONFIG_CRYPTO_DEV_ZYNQMP_AES) += zynqmp-aes.o
+obj-$(CONFIG_CRYPTO_DEV_ZYNQMP_SHA3) += zynqmp-sha.o
+obj-$(CONFIG_CRYPTO_DEV_XILINX_RSA) += zynqmp-rsa.o
 obj-y += hisilicon/
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/amcc/crypto4xx_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/amcc/crypto4xx_core.c
@@ -365,12 +365,8 @@
 		dma_alloc_coherent(dev->core_dev->device,
 			PPC4XX_SD_BUFFER_SIZE * PPC4XX_NUM_SD,
 			&dev->scatter_buffer_pa, GFP_ATOMIC);
-	if (!dev->scatter_buffer_va) {
-		dma_free_coherent(dev->core_dev->device,
-				  sizeof(struct ce_sd) * PPC4XX_NUM_SD,
-				  dev->sdr, dev->sdr_pa);
+	if (!dev->scatter_buffer_va)
 		return -ENOMEM;
-	}
 
 	for (i = 0; i < PPC4XX_NUM_SD; i++) {
 		dev->sdr[i].ptr = dev->scatter_buffer_pa +
@@ -525,7 +521,6 @@
 {
 	struct skcipher_request *req;
 	struct scatterlist *dst;
-	dma_addr_t addr;
 
 	req = skcipher_request_cast(pd_uinfo->async_req);
 
@@ -534,8 +529,8 @@
 					  req->cryptlen, req->dst);
 	} else {
 		dst = pd_uinfo->dest_va;
-		addr = dma_map_page(dev->core_dev->device, sg_page(dst),
-				    dst->offset, dst->length, DMA_FROM_DEVICE);
+		dma_unmap_page(dev->core_dev->device, pd->dest, dst->length,
+			       DMA_FROM_DEVICE);
 	}
 
 	if (pd_uinfo->sa_va->sa_command_0.bf.save_iv == SA_SAVE_IV) {
@@ -560,10 +555,9 @@
 	struct ahash_request *ahash_req;
 
 	ahash_req = ahash_request_cast(pd_uinfo->async_req);
-	ctx  = crypto_tfm_ctx(ahash_req->base.tfm);
+	ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(ahash_req));
 
-	crypto4xx_copy_digest_to_dst(ahash_req->result, pd_uinfo,
-				     crypto_tfm_ctx(ahash_req->base.tfm));
+	crypto4xx_copy_digest_to_dst(ahash_req->result, pd_uinfo, ctx);
 	crypto4xx_ret_sg_desc(dev, pd_uinfo);
 
 	if (pd_uinfo->state & PD_ENTRY_BUSY)
@@ -920,7 +914,7 @@
 	}
 
 	pd->pd_ctl.w = PD_CTL_HOST_READY |
-		((crypto_tfm_alg_type(req->tfm) == CRYPTO_ALG_TYPE_AHASH) |
+		((crypto_tfm_alg_type(req->tfm) == CRYPTO_ALG_TYPE_AHASH) ||
 		 (crypto_tfm_alg_type(req->tfm) == CRYPTO_ALG_TYPE_AEAD) ?
 			PD_CTL_HASH_FINAL : 0);
 	pd->pd_ctl_len.w = 0x00400000 | (assoclen + datalen);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/atmel-aes.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/atmel-aes.c
@@ -88,7 +88,6 @@
 struct atmel_aes_caps {
 	bool			has_dualbuff;
 	bool			has_cfb64;
-	bool			has_ctr32;
 	bool			has_gcm;
 	bool			has_xts;
 	bool			has_authenc;
@@ -145,7 +144,7 @@
 	u32			key2[AES_KEYSIZE_256 / sizeof(u32)];
 };
 
-#ifdef CONFIG_CRYPTO_DEV_ATMEL_AUTHENC
+#if IS_ENABLED(CONFIG_CRYPTO_DEV_ATMEL_AUTHENC)
 struct atmel_aes_authenc_ctx {
 	struct atmel_aes_base_ctx	base;
 	struct atmel_sha_authenc_ctx	*auth;
@@ -157,7 +156,7 @@
 	u32			lastc[AES_BLOCK_SIZE / sizeof(u32)];
 };
 
-#ifdef CONFIG_CRYPTO_DEV_ATMEL_AUTHENC
+#if IS_ENABLED(CONFIG_CRYPTO_DEV_ATMEL_AUTHENC)
 struct atmel_aes_authenc_reqctx {
 	struct atmel_aes_reqctx	base;
 
@@ -486,13 +485,36 @@
 	return (dd->flags & AES_FLAGS_ENCRYPT);
 }
 
-#ifdef CONFIG_CRYPTO_DEV_ATMEL_AUTHENC
+#if IS_ENABLED(CONFIG_CRYPTO_DEV_ATMEL_AUTHENC)
 static void atmel_aes_authenc_complete(struct atmel_aes_dev *dd, int err);
 #endif
 
+static void atmel_aes_set_iv_as_last_ciphertext_block(struct atmel_aes_dev *dd)
+{
+	struct ablkcipher_request *req = ablkcipher_request_cast(dd->areq);
+	struct atmel_aes_reqctx *rctx = ablkcipher_request_ctx(req);
+	struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req);
+	unsigned int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
+
+	if (req->nbytes < ivsize)
+		return;
+
+	if (rctx->mode & AES_FLAGS_ENCRYPT) {
+		scatterwalk_map_and_copy(req->info, req->dst,
+					 req->nbytes - ivsize, ivsize, 0);
+	} else {
+		if (req->src == req->dst)
+			memcpy(req->info, rctx->lastc, ivsize);
+		else
+			scatterwalk_map_and_copy(req->info, req->src,
+						 req->nbytes - ivsize,
+						 ivsize, 0);
+	}
+}
+
 static inline int atmel_aes_complete(struct atmel_aes_dev *dd, int err)
 {
-#ifdef CONFIG_CRYPTO_DEV_ATMEL_AUTHENC
+#if IS_ENABLED(CONFIG_CRYPTO_DEV_ATMEL_AUTHENC)
 	if (dd->ctx->is_aead)
 		atmel_aes_authenc_complete(dd, err);
 #endif
@@ -500,26 +522,8 @@
 	clk_disable(dd->iclk);
 	dd->flags &= ~AES_FLAGS_BUSY;
 
-	if (!dd->ctx->is_aead) {
-		struct ablkcipher_request *req =
-			ablkcipher_request_cast(dd->areq);
-		struct atmel_aes_reqctx *rctx = ablkcipher_request_ctx(req);
-		struct crypto_ablkcipher *ablkcipher =
-			crypto_ablkcipher_reqtfm(req);
-		int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
-
-		if (rctx->mode & AES_FLAGS_ENCRYPT) {
-			scatterwalk_map_and_copy(req->info, req->dst,
-				req->nbytes - ivsize, ivsize, 0);
-		} else {
-			if (req->src == req->dst) {
-				memcpy(req->info, rctx->lastc, ivsize);
-			} else {
-				scatterwalk_map_and_copy(req->info, req->src,
-					req->nbytes - ivsize, ivsize, 0);
-			}
-		}
-	}
+	if (!dd->ctx->is_aead)
+		atmel_aes_set_iv_as_last_ciphertext_block(dd);
 
 	if (dd->is_async)
 		dd->areq->complete(dd->areq, err);
@@ -1008,8 +1012,9 @@
 	struct atmel_aes_ctr_ctx *ctx = atmel_aes_ctr_ctx_cast(dd->ctx);
 	struct ablkcipher_request *req = ablkcipher_request_cast(dd->areq);
 	struct scatterlist *src, *dst;
-	u32 ctr, blocks;
 	size_t datalen;
+	u32 ctr;
+	u16 blocks, start, end;
 	bool use_dma, fragmented = false;
 
 	/* Check for transfer completion. */
@@ -1021,27 +1026,17 @@
 	datalen = req->nbytes - ctx->offset;
 	blocks = DIV_ROUND_UP(datalen, AES_BLOCK_SIZE);
 	ctr = be32_to_cpu(ctx->iv[3]);
-	if (dd->caps.has_ctr32) {
-		/* Check 32bit counter overflow. */
-		u32 start = ctr;
-		u32 end = start + blocks - 1;
-
-		if (end < start) {
-			ctr |= 0xffffffff;
-			datalen = AES_BLOCK_SIZE * -start;
-			fragmented = true;
-		}
-	} else {
-		/* Check 16bit counter overflow. */
-		u16 start = ctr & 0xffff;
-		u16 end = start + (u16)blocks - 1;
-
-		if (blocks >> 16 || end < start) {
-			ctr |= 0xffff;
-			datalen = AES_BLOCK_SIZE * (0x10000-start);
-			fragmented = true;
-		}
+
+	/* Check 16bit counter overflow. */
+	start = ctr & 0xffff;
+	end = start + blocks - 1;
+
+	if (blocks >> 16 || end < start) {
+		ctr |= 0xffff;
+		datalen = AES_BLOCK_SIZE * (0x10000 - start);
+		fragmented = true;
 	}
+
 	use_dma = (datalen >= ATMEL_AES_DMA_THRESHOLD);
 
 	/* Jump to offset. */
@@ -1125,10 +1120,12 @@
 	rctx->mode = mode;
 
 	if (!(mode & AES_FLAGS_ENCRYPT) && (req->src == req->dst)) {
-		int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
+		unsigned int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
 
-		scatterwalk_map_and_copy(rctx->lastc, req->src,
-			(req->nbytes - ivsize), ivsize, 0);
+		if (req->nbytes >= ivsize)
+			scatterwalk_map_and_copy(rctx->lastc, req->src,
+						 req->nbytes - ivsize,
+						 ivsize, 0);
 	}
 
 	return atmel_aes_handle_queue(dd, &req->base);
@@ -1973,7 +1970,7 @@
 	}
 };
 
-#ifdef CONFIG_CRYPTO_DEV_ATMEL_AUTHENC
+#if IS_ENABLED(CONFIG_CRYPTO_DEV_ATMEL_AUTHENC)
 /* authenc aead functions */
 
 static int atmel_aes_authenc_start(struct atmel_aes_dev *dd);
@@ -2460,7 +2457,7 @@
 {
 	int i;
 
-#ifdef CONFIG_CRYPTO_DEV_ATMEL_AUTHENC
+#if IS_ENABLED(CONFIG_CRYPTO_DEV_ATMEL_AUTHENC)
 	if (dd->caps.has_authenc)
 		for (i = 0; i < ARRAY_SIZE(aes_authenc_algs); i++)
 			crypto_unregister_aead(&aes_authenc_algs[i]);
@@ -2507,7 +2504,7 @@
 			goto err_aes_xts_alg;
 	}
 
-#ifdef CONFIG_CRYPTO_DEV_ATMEL_AUTHENC
+#if IS_ENABLED(CONFIG_CRYPTO_DEV_ATMEL_AUTHENC)
 	if (dd->caps.has_authenc) {
 		for (i = 0; i < ARRAY_SIZE(aes_authenc_algs); i++) {
 			err = crypto_register_aead(&aes_authenc_algs[i]);
@@ -2519,7 +2516,7 @@
 
 	return 0;
 
-#ifdef CONFIG_CRYPTO_DEV_ATMEL_AUTHENC
+#if IS_ENABLED(CONFIG_CRYPTO_DEV_ATMEL_AUTHENC)
 	/* i = ARRAY_SIZE(aes_authenc_algs); */
 err_aes_authenc_alg:
 	for (j = 0; j < i; j++)
@@ -2543,7 +2540,6 @@
 {
 	dd->caps.has_dualbuff = 0;
 	dd->caps.has_cfb64 = 0;
-	dd->caps.has_ctr32 = 0;
 	dd->caps.has_gcm = 0;
 	dd->caps.has_xts = 0;
 	dd->caps.has_authenc = 0;
@@ -2554,7 +2550,6 @@
 	case 0x500:
 		dd->caps.has_dualbuff = 1;
 		dd->caps.has_cfb64 = 1;
-		dd->caps.has_ctr32 = 1;
 		dd->caps.has_gcm = 1;
 		dd->caps.has_xts = 1;
 		dd->caps.has_authenc = 1;
@@ -2563,7 +2558,6 @@
 	case 0x200:
 		dd->caps.has_dualbuff = 1;
 		dd->caps.has_cfb64 = 1;
-		dd->caps.has_ctr32 = 1;
 		dd->caps.has_gcm = 1;
 		dd->caps.max_burst_size = 4;
 		break;
@@ -2709,7 +2703,7 @@
 
 	atmel_aes_get_cap(aes_dd);
 
-#ifdef CONFIG_CRYPTO_DEV_ATMEL_AUTHENC
+#if IS_ENABLED(CONFIG_CRYPTO_DEV_ATMEL_AUTHENC)
 	if (aes_dd->caps.has_authenc && !atmel_sha_authenc_is_ready()) {
 		err = -EPROBE_DEFER;
 		goto iclk_unprepare;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/atmel-authenc.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/atmel-authenc.h
@@ -12,7 +12,7 @@
 #ifndef __ATMEL_AUTHENC_H__
 #define __ATMEL_AUTHENC_H__
 
-#ifdef CONFIG_CRYPTO_DEV_ATMEL_AUTHENC
+#if IS_ENABLED(CONFIG_CRYPTO_DEV_ATMEL_AUTHENC)
 
 #include <crypto/authenc.h>
 #include <crypto/hash.h>
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/atmel-sha.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/atmel-sha.c
@@ -1918,12 +1918,7 @@
 {
 	struct atmel_sha_hmac_ctx *hmac = crypto_ahash_ctx(tfm);
 
-	if (atmel_sha_hmac_key_set(&hmac->hkey, key, keylen)) {
-		crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
-		return -EINVAL;
-	}
-
-	return 0;
+	return atmel_sha_hmac_key_set(&hmac->hkey, key, keylen);
 }
 
 static int atmel_sha_hmac_init(struct ahash_request *req)
@@ -2212,7 +2207,7 @@
 },
 };
 
-#ifdef CONFIG_CRYPTO_DEV_ATMEL_AUTHENC
+#if IS_ENABLED(CONFIG_CRYPTO_DEV_ATMEL_AUTHENC)
 /* authenc functions */
 
 static int atmel_sha_authenc_init2(struct atmel_sha_dev *dd);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/axis/artpec6_crypto.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/axis/artpec6_crypto.c
@@ -1251,7 +1251,7 @@
 
 	if (len != 16 && len != 24 && len != 32) {
 		crypto_aead_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
-		return -1;
+		return -EINVAL;
 	}
 
 	ctx->key_length = len;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/bcm/cipher.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/bcm/cipher.c
@@ -41,7 +41,7 @@
 
 /* ================= Device Structure ================== */
 
-struct device_private iproc_priv;
+struct bcm_device_private iproc_priv;
 
 /* ==================== Parameters ===================== */
 
@@ -2478,6 +2478,7 @@
 
 static int ahash_hmac_init(struct ahash_request *req)
 {
+	int ret;
 	struct iproc_reqctx_s *rctx = ahash_request_ctx(req);
 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
 	struct iproc_ctx_s *ctx = crypto_ahash_ctx(tfm);
@@ -2487,7 +2488,9 @@
 	flow_log("ahash_hmac_init()\n");
 
 	/* init the context as a hash */
-	ahash_init(req);
+	ret = ahash_init(req);
+	if (ret)
+		return ret;
 
 	if (!spu_no_incr_hash(ctx)) {
 		/* SPU-M can do incr hashing but needs sw for outer HMAC */
@@ -2937,7 +2940,6 @@
 
 	ctx->enckeylen = keylen;
 	ctx->authkeylen = 0;
-	memcpy(ctx->enckey, key, ctx->enckeylen);
 
 	switch (ctx->enckeylen) {
 	case AES_KEYSIZE_128:
@@ -2953,6 +2955,8 @@
 		goto badkey;
 	}
 
+	memcpy(ctx->enckey, key, ctx->enckeylen);
+
 	flow_log("  enckeylen:%u authkeylen:%u\n", ctx->enckeylen,
 		 ctx->authkeylen);
 	flow_dump("  enc: ", ctx->enckey, ctx->enckeylen);
@@ -3013,6 +3017,10 @@
 	struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher);
 
 	flow_log("%s\n", __func__);
+
+	if (keylen < GCM_ESP_SALT_SIZE)
+		return -EINVAL;
+
 	ctx->salt_len = GCM_ESP_SALT_SIZE;
 	ctx->salt_offset = GCM_ESP_SALT_OFFSET;
 	memcpy(ctx->salt, key + keylen - GCM_ESP_SALT_SIZE, GCM_ESP_SALT_SIZE);
@@ -3041,6 +3049,10 @@
 	struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher);
 
 	flow_log("%s\n", __func__);
+
+	if (keylen < GCM_ESP_SALT_SIZE)
+		return -EINVAL;
+
 	ctx->salt_len = GCM_ESP_SALT_SIZE;
 	ctx->salt_offset = GCM_ESP_SALT_OFFSET;
 	memcpy(ctx->salt, key + keylen - GCM_ESP_SALT_SIZE, GCM_ESP_SALT_SIZE);
@@ -3070,6 +3082,10 @@
 	struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher);
 
 	flow_log("%s\n", __func__);
+
+	if (keylen < CCM_ESP_SALT_SIZE)
+		return -EINVAL;
+
 	ctx->salt_len = CCM_ESP_SALT_SIZE;
 	ctx->salt_offset = CCM_ESP_SALT_OFFSET;
 	memcpy(ctx->salt, key + keylen - CCM_ESP_SALT_SIZE, CCM_ESP_SALT_SIZE);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/bcm/cipher.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/bcm/cipher.h
@@ -418,7 +418,7 @@
 	u32 num_chan;
 };
 
-struct device_private {
+struct bcm_device_private {
 	struct platform_device *pdev;
 
 	struct spu_hw spu;
@@ -465,6 +465,6 @@
 	struct mbox_chan **mbox;
 };
 
-extern struct device_private iproc_priv;
+extern struct bcm_device_private iproc_priv;
 
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/bcm/spu2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/bcm/spu2.c
@@ -495,7 +495,7 @@
 	if (hash_iv_len) {
 		packet_log("  Hash IV Length %u bytes\n", hash_iv_len);
 		packet_dump("  hash IV: ", ptr, hash_iv_len);
-		ptr += ciph_key_len;
+		ptr += hash_iv_len;
 	}
 
 	if (ciph_iv_len) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/bcm/util.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/bcm/util.c
@@ -348,7 +348,7 @@
 static ssize_t spu_debugfs_read(struct file *filp, char __user *ubuf,
 				size_t count, loff_t *offp)
 {
-	struct device_private *ipriv;
+	struct bcm_device_private *ipriv;
 	char *buf;
 	ssize_t ret, out_offset, out_count;
 	int i;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/caam/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/caam/Kconfig
@@ -112,6 +112,7 @@
 	select CRYPTO_AUTHENC
 	select CRYPTO_BLKCIPHER
 	select CRYPTO_DES
+	select CRYPTO_XTS
 	help
 	  Selecting this will use CAAM Queue Interface (QI) for sending
 	  & receiving crypto jobs to/from CAAM. This gives better performance
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/caam/caamalg.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/caam/caamalg.c
@@ -553,7 +553,8 @@
 		return -EINVAL;
 	}
 
-	ctx->cdata.key_virt = key;
+	memcpy(ctx->key, key, keylen);
+	ctx->cdata.key_virt = ctx->key;
 	ctx->cdata.keylen = keylen - saltlen;
 
 	return chachapoly_set_sh_desc(aead);
@@ -818,12 +819,6 @@
 	return skcipher_setkey(skcipher, key, keylen, ctx1_iv_off);
 }
 
-static int arc4_skcipher_setkey(struct crypto_skcipher *skcipher,
-				const u8 *key, unsigned int keylen)
-{
-	return skcipher_setkey(skcipher, key, keylen, 0);
-}
-
 static int des_skcipher_setkey(struct crypto_skcipher *skcipher,
 			       const u8 *key, unsigned int keylen)
 {
@@ -1810,7 +1805,7 @@
 
 	if (ivsize || mapped_dst_nents > 1)
 		sg_to_sec4_set_last(edesc->sec4_sg + dst_sg_idx +
-				    mapped_dst_nents);
+				    mapped_dst_nents - 1 + !!ivsize);
 
 	if (sec4_sg_bytes) {
 		edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
@@ -2058,21 +2053,6 @@
 		},
 		.caam.class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_ECB,
 	},
-	{
-		.skcipher = {
-			.base = {
-				.cra_name = "ecb(arc4)",
-				.cra_driver_name = "ecb-arc4-caam",
-				.cra_blocksize = ARC4_BLOCK_SIZE,
-			},
-			.setkey = arc4_skcipher_setkey,
-			.encrypt = skcipher_encrypt,
-			.decrypt = skcipher_decrypt,
-			.min_keysize = ARC4_MIN_KEY_SIZE,
-			.max_keysize = ARC4_MAX_KEY_SIZE,
-		},
-		.caam.class1_alg_type = OP_ALG_ALGSEL_ARC4 | OP_ALG_AAI_ECB,
-	},
 };
 
 static struct caam_aead_alg driver_aeads[] = {
@@ -3533,7 +3513,6 @@
 	struct caam_drv_private *priv = dev_get_drvdata(ctrldev);
 	int i = 0, err = 0;
 	u32 aes_vid, aes_inst, des_inst, md_vid, md_inst, ccha_inst, ptha_inst;
-	u32 arc4_inst;
 	unsigned int md_limit = SHA512_DIGEST_SIZE;
 	bool registered = false, gcm_support;
 
@@ -3553,8 +3532,6 @@
 			   CHA_ID_LS_DES_SHIFT;
 		aes_inst = cha_inst & CHA_ID_LS_AES_MASK;
 		md_inst = (cha_inst & CHA_ID_LS_MD_MASK) >> CHA_ID_LS_MD_SHIFT;
-		arc4_inst = (cha_inst & CHA_ID_LS_ARC4_MASK) >>
-			    CHA_ID_LS_ARC4_SHIFT;
 		ccha_inst = 0;
 		ptha_inst = 0;
 
@@ -3575,7 +3552,6 @@
 		md_inst = mdha & CHA_VER_NUM_MASK;
 		ccha_inst = rd_reg32(&priv->ctrl->vreg.ccha) & CHA_VER_NUM_MASK;
 		ptha_inst = rd_reg32(&priv->ctrl->vreg.ptha) & CHA_VER_NUM_MASK;
-		arc4_inst = rd_reg32(&priv->ctrl->vreg.afha) & CHA_VER_NUM_MASK;
 
 		gcm_support = aesa & CHA_VER_MISC_AES_GCM;
 	}
@@ -3598,10 +3574,6 @@
 		if (!aes_inst && (alg_sel == OP_ALG_ALGSEL_AES))
 				continue;
 
-		/* Skip ARC4 algorithms if not supported by device */
-		if (!arc4_inst && alg_sel == OP_ALG_ALGSEL_ARC4)
-			continue;
-
 		/*
 		 * Check support for AES modes not available
 		 * on LP devices.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/caam/caamalg_desc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/caam/caamalg_desc.c
@@ -1379,6 +1379,9 @@
 				const u32 ctx1_iv_off)
 {
 	u32 *key_jump_cmd;
+	u32 options = cdata->algtype | OP_ALG_AS_INIT | OP_ALG_ENCRYPT;
+	bool is_chacha20 = ((cdata->algtype & OP_ALG_ALGSEL_MASK) ==
+			    OP_ALG_ALGSEL_CHACHA20);
 
 	init_sh_desc(desc, HDR_SHARE_SERIAL | HDR_SAVECTX);
 	/* Skip if already shared */
@@ -1417,14 +1420,15 @@
 				      LDST_OFFSET_SHIFT));
 
 	/* Load operation */
-	append_operation(desc, cdata->algtype | OP_ALG_AS_INIT |
-			 OP_ALG_ENCRYPT);
+	if (is_chacha20)
+		options |= OP_ALG_AS_FINALIZE;
+	append_operation(desc, options);
 
 	/* Perform operation */
 	skcipher_append_src_dst(desc);
 
 	/* Store IV */
-	if (ivsize)
+	if (!is_chacha20 && ivsize)
 		append_seq_store(desc, ivsize, LDST_SRCDST_BYTE_CONTEXT |
 				 LDST_CLASS_1_CCB | (ctx1_iv_off <<
 				 LDST_OFFSET_SHIFT));
@@ -1451,6 +1455,8 @@
 				const u32 ctx1_iv_off)
 {
 	u32 *key_jump_cmd;
+	bool is_chacha20 = ((cdata->algtype & OP_ALG_ALGSEL_MASK) ==
+			    OP_ALG_ALGSEL_CHACHA20);
 
 	init_sh_desc(desc, HDR_SHARE_SERIAL | HDR_SAVECTX);
 	/* Skip if already shared */
@@ -1499,7 +1505,7 @@
 	skcipher_append_src_dst(desc);
 
 	/* Store IV */
-	if (ivsize)
+	if (!is_chacha20 && ivsize)
 		append_seq_store(desc, ivsize, LDST_SRCDST_BYTE_CONTEXT |
 				 LDST_CLASS_1_CCB | (ctx1_iv_off <<
 				 LDST_OFFSET_SHIFT));
@@ -1518,7 +1524,13 @@
  */
 void cnstr_shdsc_xts_skcipher_encap(u32 * const desc, struct alginfo *cdata)
 {
-	__be64 sector_size = cpu_to_be64(512);
+	/*
+	 * Set sector size to a big value, practically disabling
+	 * sector size segmentation in xts implementation. We cannot
+	 * take full advantage of this HW feature with existing
+	 * crypto API / dm-crypt SW architecture.
+	 */
+	__be64 sector_size = cpu_to_be64(BIT(15));
 	u32 *key_jump_cmd;
 
 	init_sh_desc(desc, HDR_SHARE_SERIAL | HDR_SAVECTX);
@@ -1571,7 +1583,13 @@
  */
 void cnstr_shdsc_xts_skcipher_decap(u32 * const desc, struct alginfo *cdata)
 {
-	__be64 sector_size = cpu_to_be64(512);
+	/*
+	 * Set sector size to a big value, practically disabling
+	 * sector size segmentation in xts implementation. We cannot
+	 * take full advantage of this HW feature with existing
+	 * crypto API / dm-crypt SW architecture.
+	 */
+	__be64 sector_size = cpu_to_be64(BIT(15));
 	u32 *key_jump_cmd;
 
 	init_sh_desc(desc, HDR_SHARE_SERIAL | HDR_SAVECTX);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/caam/caamalg_qi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/caam/caamalg_qi.c
@@ -18,6 +18,7 @@
 #include "qi.h"
 #include "jr.h"
 #include "caamalg_desc.h"
+#include <asm/unaligned.h>
 
 /*
  * crypto alg
@@ -67,6 +68,11 @@
 	struct device *qidev;
 	spinlock_t lock;	/* Protects multiple init of driver context */
 	struct caam_drv_ctx *drv_ctx[NUM_OP];
+	struct crypto_skcipher *fallback;
+};
+
+struct caam_skcipher_req_ctx {
+	struct skcipher_request fallback_req;
 };
 
 static int aead_set_sh_desc(struct crypto_aead *aead)
@@ -745,12 +751,17 @@
 	struct caam_ctx *ctx = crypto_skcipher_ctx(skcipher);
 	struct device *jrdev = ctx->jrdev;
 	int ret = 0;
+	int err;
 
 	if (keylen != 2 * AES_MIN_KEY_SIZE  && keylen != 2 * AES_MAX_KEY_SIZE) {
 		dev_err(jrdev, "key size mismatch\n");
 		goto badkey;
 	}
 
+	err = crypto_skcipher_setkey(ctx->fallback, key, keylen);
+	if (err)
+		return err;
+
 	ctx->cdata.keylen = keylen;
 	ctx->cdata.key_virt = key;
 	ctx->cdata.key_inline = true;
@@ -1395,6 +1406,14 @@
 	return edesc;
 }
 
+static inline bool xts_skcipher_ivsize(struct skcipher_request *req)
+{
+	struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req);
+	unsigned int ivsize = crypto_skcipher_ivsize(skcipher);
+
+	return !!get_unaligned((u64 *)(req->iv + (ivsize / 2)));
+}
+
 static inline int skcipher_crypt(struct skcipher_request *req, bool encrypt)
 {
 	struct skcipher_edesc *edesc;
@@ -1405,6 +1424,21 @@
 	if (!req->cryptlen)
 		return 0;
 
+	if (ctx->fallback && xts_skcipher_ivsize(req)) {
+		struct caam_skcipher_req_ctx *rctx = skcipher_request_ctx(req);
+
+		skcipher_request_set_tfm(&rctx->fallback_req, ctx->fallback);
+		skcipher_request_set_callback(&rctx->fallback_req,
+					      req->base.flags,
+					      req->base.complete,
+					      req->base.data);
+		skcipher_request_set_crypt(&rctx->fallback_req, req->src,
+					   req->dst, req->cryptlen, req->iv);
+
+		return encrypt ? crypto_skcipher_encrypt(&rctx->fallback_req) :
+				 crypto_skcipher_decrypt(&rctx->fallback_req);
+	}
+
 	if (unlikely(caam_congested))
 		return -EAGAIN;
 
@@ -1529,6 +1563,7 @@
 			.base = {
 				.cra_name = "xts(aes)",
 				.cra_driver_name = "xts-aes-caam-qi",
+				.cra_flags = CRYPTO_ALG_NEED_FALLBACK,
 				.cra_blocksize = AES_BLOCK_SIZE,
 			},
 			.setkey = xts_skcipher_setkey,
@@ -2462,9 +2497,32 @@
 	struct skcipher_alg *alg = crypto_skcipher_alg(tfm);
 	struct caam_skcipher_alg *caam_alg =
 		container_of(alg, typeof(*caam_alg), skcipher);
+	struct caam_ctx *ctx = crypto_skcipher_ctx(tfm);
+	u32 alg_aai = caam_alg->caam.class1_alg_type & OP_ALG_AAI_MASK;
+	int ret = 0;
+
+	if (alg_aai == OP_ALG_AAI_XTS) {
+		const char *tfm_name = crypto_tfm_alg_name(&tfm->base);
+		struct crypto_skcipher *fallback;
+
+		fallback = crypto_alloc_skcipher(tfm_name, 0,
+						 CRYPTO_ALG_NEED_FALLBACK);
+		if (IS_ERR(fallback)) {
+			dev_err(ctx->jrdev, "Failed to allocate %s fallback: %ld\n",
+				tfm_name, PTR_ERR(fallback));
+			return PTR_ERR(fallback);
+		}
+
+		ctx->fallback = fallback;
+		crypto_skcipher_set_reqsize(tfm, sizeof(struct caam_skcipher_req_ctx) +
+					    crypto_skcipher_reqsize(fallback));
+	}
+
+	ret = caam_init_common(ctx, &caam_alg->caam, false);
+	if (ret && ctx->fallback)
+		crypto_free_skcipher(ctx->fallback);
 
-	return caam_init_common(crypto_skcipher_ctx(tfm), &caam_alg->caam,
-				false);
+	return ret;
 }
 
 static int caam_aead_init(struct crypto_aead *tfm)
@@ -2490,7 +2548,11 @@
 
 static void caam_cra_exit(struct crypto_skcipher *tfm)
 {
-	caam_exit_common(crypto_skcipher_ctx(tfm));
+	struct caam_ctx *ctx = crypto_skcipher_ctx(tfm);
+
+	if (ctx->fallback)
+		crypto_free_skcipher(ctx->fallback);
+	caam_exit_common(ctx);
 }
 
 static void caam_aead_exit(struct crypto_aead *tfm)
@@ -2524,7 +2586,7 @@
 	alg->base.cra_module = THIS_MODULE;
 	alg->base.cra_priority = CAAM_CRA_PRIORITY;
 	alg->base.cra_ctxsize = sizeof(struct caam_ctx);
-	alg->base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY;
+	alg->base.cra_flags |= CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY;
 
 	alg->init = caam_cra_init;
 	alg->exit = caam_cra_exit;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/caam/caamalg_qi2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/caam/caamalg_qi2.c
@@ -639,7 +639,8 @@
 		return -EINVAL;
 	}
 
-	ctx->cdata.key_virt = key;
+	memcpy(ctx->key, key, keylen);
+	ctx->cdata.key_virt = ctx->key;
 	ctx->cdata.keylen = keylen - saltlen;
 
 	return chachapoly_set_sh_desc(aead);
@@ -2481,7 +2482,7 @@
 				.cra_name = "echainiv(authenc(hmac(sha256),"
 					    "cbc(des)))",
 				.cra_driver_name = "echainiv-authenc-"
-						   "hmac-sha256-cbc-desi-"
+						   "hmac-sha256-cbc-des-"
 						   "caam-qi2",
 				.cra_blocksize = DES_BLOCK_SIZE,
 			},
@@ -5421,7 +5422,7 @@
 	dpaa2_fd_set_len(&fd, dpaa2_fl_get_len(&req->fd_flt[1]));
 	dpaa2_fd_set_flc(&fd, req->flc_dma);
 
-	ppriv = this_cpu_ptr(priv->ppriv);
+	ppriv = raw_cpu_ptr(priv->ppriv);
 	for (i = 0; i < (priv->dpseci_attr.num_tx_queues << 1); i++) {
 		err = dpaa2_io_service_enqueue_fq(ppriv->dpio, ppriv->req_fqid,
 						  &fd);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/caam/caampkc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/caam/caampkc.c
@@ -225,7 +225,9 @@
 		if (len && *buff)
 			break;
 
-		sg_miter_next(&miter);
+		if (!sg_miter_next(&miter))
+			break;
+
 		buff = miter.addr;
 		len = miter.length;
 
@@ -1087,16 +1089,27 @@
 int caam_pkc_init(struct device *ctrldev)
 {
 	struct caam_drv_private *priv = dev_get_drvdata(ctrldev);
-	u32 pk_inst;
+	u32 pk_inst, pkha;
 	int err;
 	init_done = false;
 
 	/* Determine public key hardware accelerator presence. */
-	if (priv->era < 10)
+	if (priv->era < 10) {
 		pk_inst = (rd_reg32(&priv->ctrl->perfmon.cha_num_ls) &
 			   CHA_ID_LS_PK_MASK) >> CHA_ID_LS_PK_SHIFT;
-	else
-		pk_inst = rd_reg32(&priv->ctrl->vreg.pkha) & CHA_VER_NUM_MASK;
+	} else {
+		pkha = rd_reg32(&priv->ctrl->vreg.pkha);
+		pk_inst = pkha & CHA_VER_NUM_MASK;
+
+		/*
+		 * Newer CAAMs support partially disabled functionality. If this is the
+		 * case, the number is non-zero, but this bit is set to indicate that
+		 * no encryption or decryption is supported. Only signing and verifying
+		 * is supported.
+		 */
+		if (pkha & CHA_VER_MISC_PKHA_NO_CRYPT)
+			pk_inst = 0;
+	}
 
 	/* Do not register algorithms if PKHA is not present. */
 	if (!pk_inst)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/caam/compat.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/caam/compat.h
@@ -43,7 +43,6 @@
 #include <crypto/akcipher.h>
 #include <crypto/scatterwalk.h>
 #include <crypto/skcipher.h>
-#include <crypto/arc4.h>
 #include <crypto/internal/skcipher.h>
 #include <crypto/internal/hash.h>
 #include <crypto/internal/rsa.h>
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/caam/ctrl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/caam/ctrl.c
@@ -685,11 +685,9 @@
 	of_node_put(np);
 
 	if (!ctrlpriv->mc_en)
-		clrsetbits_32(&ctrl->mcr, MCFGR_AWCACHE_MASK | MCFGR_LONG_PTR,
+		clrsetbits_32(&ctrl->mcr, MCFGR_AWCACHE_MASK,
 			      MCFGR_AWCACHE_CACH | MCFGR_AWCACHE_BUFF |
-			      MCFGR_WDENABLE | MCFGR_LARGE_BURST |
-			      (sizeof(dma_addr_t) == sizeof(u64) ?
-			       MCFGR_LONG_PTR : 0));
+			      MCFGR_WDENABLE | MCFGR_LARGE_BURST);
 
 	handle_imx6_err005766(&ctrl->mcr);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/caam/regs.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/caam/regs.h
@@ -317,6 +317,9 @@
 /* CHA Miscellaneous Information - AESA_MISC specific */
 #define CHA_VER_MISC_AES_GCM	BIT(1 + CHA_VER_MISC_SHIFT)
 
+/* CHA Miscellaneous Information - PKHA_MISC specific */
+#define CHA_VER_MISC_PKHA_NO_CRYPT	BIT(7 + CHA_VER_MISC_SHIFT)
+
 /*
  * caam_perfmon - Performance Monitor/Secure Memory Status/
  *                CAAM Global Status/Component Version IDs
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/cavium/cpt/cptpf_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/cavium/cpt/cptpf_main.c
@@ -45,7 +45,7 @@
 		dev_err(dev, "Cores still busy %llx", coremask);
 		grp = cpt_read_csr64(cpt->reg_base,
 				     CPTX_PF_EXEC_BUSY(0));
-		if (timeout--)
+		if (!timeout--)
 			break;
 
 		udelay(CSR_DELAY);
@@ -254,6 +254,7 @@
 	const struct firmware *fw_entry;
 	struct device *dev = &cpt->pdev->dev;
 	struct ucode_header *ucode;
+	unsigned int code_length;
 	struct microcode *mcode;
 	int j, ret = 0;
 
@@ -264,11 +265,12 @@
 	ucode = (struct ucode_header *)fw_entry->data;
 	mcode = &cpt->mcode[cpt->next_mc_idx];
 	memcpy(mcode->version, (u8 *)fw_entry->data, CPT_UCODE_VERSION_SZ);
-	mcode->code_size = ntohl(ucode->code_length) * 2;
-	if (!mcode->code_size) {
+	code_length = ntohl(ucode->code_length);
+	if (code_length == 0 || code_length >= INT_MAX / 2) {
 		ret = -EINVAL;
 		goto fw_release;
 	}
+	mcode->code_size = code_length * 2;
 
 	mcode->is_ae = is_ae;
 	mcode->core_mask = 0ULL;
@@ -301,6 +303,8 @@
 
 	ret = do_cpt_init(cpt, mcode);
 	if (ret) {
+		dma_free_coherent(&cpt->pdev->dev, mcode->code_size,
+				  mcode->code, mcode->phys_base);
 		dev_err(dev, "do_cpt_init failed with ret: %d\n", ret);
 		goto fw_release;
 	}
@@ -393,7 +397,7 @@
 		dev_err(dev, "Cores still busy");
 		grp = cpt_read_csr64(cpt->reg_base,
 				     CPTX_PF_EXEC_BUSY(0));
-		if (timeout--)
+		if (!timeout--)
 			break;
 
 		udelay(CSR_DELAY);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/cavium/cpt/cptvf_algs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/cavium/cpt/cptvf_algs.c
@@ -200,6 +200,7 @@
 	int status;
 
 	memset(req_info, 0, sizeof(struct cpt_request_info));
+	req_info->may_sleep = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) != 0;
 	memset(fctx, 0, sizeof(struct fc_context));
 	create_input_list(req, enc, enc_iv_len);
 	create_output_list(req, enc_iv_len);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/cavium/cpt/cptvf_reqmanager.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/cavium/cpt/cptvf_reqmanager.c
@@ -133,7 +133,7 @@
 
 	/* Setup gather (input) components */
 	g_sz_bytes = ((req->incnt + 3) / 4) * sizeof(struct sglist_component);
-	info->gather_components = kzalloc(g_sz_bytes, GFP_KERNEL);
+	info->gather_components = kzalloc(g_sz_bytes, req->may_sleep ? GFP_KERNEL : GFP_ATOMIC);
 	if (!info->gather_components) {
 		ret = -ENOMEM;
 		goto  scatter_gather_clean;
@@ -150,7 +150,7 @@
 
 	/* Setup scatter (output) components */
 	s_sz_bytes = ((req->outcnt + 3) / 4) * sizeof(struct sglist_component);
-	info->scatter_components = kzalloc(s_sz_bytes, GFP_KERNEL);
+	info->scatter_components = kzalloc(s_sz_bytes, req->may_sleep ? GFP_KERNEL : GFP_ATOMIC);
 	if (!info->scatter_components) {
 		ret = -ENOMEM;
 		goto  scatter_gather_clean;
@@ -167,7 +167,7 @@
 
 	/* Create and initialize DPTR */
 	info->dlen = g_sz_bytes + s_sz_bytes + SG_LIST_HDR_SIZE;
-	info->in_buffer = kzalloc(info->dlen, GFP_KERNEL);
+	info->in_buffer = kzalloc(info->dlen, req->may_sleep ? GFP_KERNEL : GFP_ATOMIC);
 	if (!info->in_buffer) {
 		ret = -ENOMEM;
 		goto  scatter_gather_clean;
@@ -195,7 +195,7 @@
 	}
 
 	/* Create and initialize RPTR */
-	info->out_buffer = kzalloc(COMPLETION_CODE_SIZE, GFP_KERNEL);
+	info->out_buffer = kzalloc(COMPLETION_CODE_SIZE, req->may_sleep ? GFP_KERNEL : GFP_ATOMIC);
 	if (!info->out_buffer) {
 		ret = -ENOMEM;
 		goto scatter_gather_clean;
@@ -421,7 +421,7 @@
 	struct cpt_vq_command vq_cmd;
 	union cpt_inst_s cptinst;
 
-	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	info = kzalloc(sizeof(*info), req->may_sleep ? GFP_KERNEL : GFP_ATOMIC);
 	if (unlikely(!info)) {
 		dev_err(&pdev->dev, "Unable to allocate memory for info_buffer\n");
 		return -ENOMEM;
@@ -443,7 +443,7 @@
 	 * Get buffer for union cpt_res_s response
 	 * structure and its physical address
 	 */
-	info->completion_addr = kzalloc(sizeof(union cpt_res_s), GFP_KERNEL);
+	info->completion_addr = kzalloc(sizeof(union cpt_res_s), req->may_sleep ? GFP_KERNEL : GFP_ATOMIC);
 	if (unlikely(!info->completion_addr)) {
 		dev_err(&pdev->dev, "Unable to allocate memory for completion_addr\n");
 		ret = -ENOMEM;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/cavium/cpt/request_manager.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/cavium/cpt/request_manager.h
@@ -62,6 +62,8 @@
 	union ctrl_info ctrl; /* User control information */
 	struct cptvf_request req; /* Request Information (Core specific) */
 
+	bool may_sleep;
+
 	struct buf_ptr in[MAX_BUF_CNT];
 	struct buf_ptr out[MAX_BUF_CNT];
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/cavium/nitrox/nitrox_isr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/cavium/nitrox/nitrox_isr.c
@@ -306,6 +306,10 @@
 	 * Entry 192: NPS_CORE_INT_ACTIVE
 	 */
 	nr_vecs = pci_msix_vec_count(pdev);
+	if (nr_vecs < 0) {
+		dev_err(DEV(ndev), "Error in getting vec count %d\n", nr_vecs);
+		return nr_vecs;
+	}
 
 	/* Enable MSI-X */
 	ret = pci_alloc_irq_vectors(pdev, nr_vecs, nr_vecs, PCI_IRQ_MSIX);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/cavium/nitrox/nitrox_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/cavium/nitrox/nitrox_main.c
@@ -103,8 +103,7 @@
 	offset = UCD_UCODE_LOAD_BLOCK_NUM;
 	nitrox_write_csr(ndev, offset, block_num);
 
-	code_size = ucode_size;
-	code_size = roundup(code_size, 8);
+	code_size = roundup(ucode_size, 16);
 	while (code_size) {
 		data = ucode_data[i];
 		/* write 8 bytes at a time */
@@ -220,11 +219,11 @@
 
 	/* write block number and firmware length
 	 * bit:<2:0> block number
-	 * bit:3 is set SE uses 32KB microcode
-	 * bit:3 is clear SE uses 64KB microcode
+	 * bit:3 is set AE uses 32KB microcode
+	 * bit:3 is clear AE uses 64KB microcode
 	 */
 	core_2_eid_val.value = 0ULL;
-	core_2_eid_val.ucode_blk = 0;
+	core_2_eid_val.ucode_blk = 2;
 	if (ucode_size <= CNN55XX_UCD_BLOCK_SIZE)
 		core_2_eid_val.ucode_len = 1;
 	else
@@ -279,7 +278,7 @@
 
 struct nitrox_device *nitrox_get_first_device(void)
 {
-	struct nitrox_device *ndev = NULL;
+	struct nitrox_device *ndev;
 
 	mutex_lock(&devlist_lock);
 	list_for_each_entry(ndev, &ndevlist, list) {
@@ -287,7 +286,7 @@
 			break;
 	}
 	mutex_unlock(&devlist_lock);
-	if (!ndev)
+	if (&ndev->list == &ndevlist)
 		return NULL;
 
 	refcount_inc(&ndev->refcnt);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/ccp/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/ccp/Kconfig
@@ -10,10 +10,9 @@
 config CRYPTO_DEV_SP_CCP
 	bool "Cryptographic Coprocessor device"
 	default y
-	depends on CRYPTO_DEV_CCP_DD
+	depends on CRYPTO_DEV_CCP_DD && DMADEVICES
 	select HW_RANDOM
 	select DMA_ENGINE
-	select DMADEVICES
 	select CRYPTO_SHA1
 	select CRYPTO_SHA256
 	help
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/ccp/ccp-dev-v3.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/ccp/ccp-dev-v3.c
@@ -586,6 +586,7 @@
 	.setup = NULL,
 	.perform = &ccp3_actions,
 	.offset = 0,
+	.rsamax = CCP_RSA_MAX_WIDTH,
 };
 
 const struct ccp_vdata ccpv3 = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/ccp/ccp-dev.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/ccp/ccp-dev.h
@@ -469,6 +469,7 @@
 	unsigned int sg_used;
 
 	struct scatterlist *dma_sg;
+	struct scatterlist *dma_sg_head;
 	struct device *dma_dev;
 	unsigned int dma_count;
 	enum dma_data_direction dma_dir;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/ccp/ccp-dmaengine.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/ccp/ccp-dmaengine.c
@@ -342,6 +342,7 @@
 	desc->tx_desc.flags = flags;
 	desc->tx_desc.tx_submit = ccp_tx_submit;
 	desc->ccp = chan->ccp;
+	INIT_LIST_HEAD(&desc->entry);
 	INIT_LIST_HEAD(&desc->pending);
 	INIT_LIST_HEAD(&desc->active);
 	desc->status = DMA_IN_PROGRESS;
@@ -632,6 +633,36 @@
 	return 0;
 }
 
+static void ccp_dma_release(struct ccp_device *ccp)
+{
+	struct ccp_dma_chan *chan;
+	struct dma_chan *dma_chan;
+	unsigned int i;
+
+	for (i = 0; i < ccp->cmd_q_count; i++) {
+		chan = ccp->ccp_dma_chan + i;
+		dma_chan = &chan->dma_chan;
+
+		tasklet_kill(&chan->cleanup_tasklet);
+		list_del_rcu(&dma_chan->device_node);
+	}
+}
+
+static void ccp_dma_release_channels(struct ccp_device *ccp)
+{
+	struct ccp_dma_chan *chan;
+	struct dma_chan *dma_chan;
+	unsigned int i;
+
+	for (i = 0; i < ccp->cmd_q_count; i++) {
+		chan = ccp->ccp_dma_chan + i;
+		dma_chan = &chan->dma_chan;
+
+		if (dma_chan->client_count)
+			dma_release_channel(dma_chan);
+	}
+}
+
 int ccp_dmaengine_register(struct ccp_device *ccp)
 {
 	struct ccp_dma_chan *chan;
@@ -736,6 +767,7 @@
 	return 0;
 
 err_reg:
+	ccp_dma_release(ccp);
 	kmem_cache_destroy(ccp->dma_desc_cache);
 
 err_cache:
@@ -751,7 +783,9 @@
 	if (!dmaengine)
 		return;
 
+	ccp_dma_release_channels(ccp);
 	dma_async_device_unregister(dma_dev);
+	ccp_dma_release(ccp);
 
 	kmem_cache_destroy(ccp->dma_desc_cache);
 	kmem_cache_destroy(ccp->dma_cmd_cache);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/ccp/ccp-ops.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/ccp/ccp-ops.c
@@ -63,7 +63,7 @@
 static void ccp_sg_free(struct ccp_sg_workarea *wa)
 {
 	if (wa->dma_count)
-		dma_unmap_sg(wa->dma_dev, wa->dma_sg, wa->nents, wa->dma_dir);
+		dma_unmap_sg(wa->dma_dev, wa->dma_sg_head, wa->nents, wa->dma_dir);
 
 	wa->dma_count = 0;
 }
@@ -92,6 +92,7 @@
 		return 0;
 
 	wa->dma_sg = sg;
+	wa->dma_sg_head = sg;
 	wa->dma_dev = dev;
 	wa->dma_dir = dma_dir;
 	wa->dma_count = dma_map_sg(dev, sg, wa->nents, dma_dir);
@@ -104,14 +105,28 @@
 static void ccp_update_sg_workarea(struct ccp_sg_workarea *wa, unsigned int len)
 {
 	unsigned int nbytes = min_t(u64, len, wa->bytes_left);
+	unsigned int sg_combined_len = 0;
 
 	if (!wa->sg)
 		return;
 
 	wa->sg_used += nbytes;
 	wa->bytes_left -= nbytes;
-	if (wa->sg_used == wa->sg->length) {
-		wa->sg = sg_next(wa->sg);
+	if (wa->sg_used == sg_dma_len(wa->dma_sg)) {
+		/* Advance to the next DMA scatterlist entry */
+		wa->dma_sg = sg_next(wa->dma_sg);
+
+		/* In the case that the DMA mapped scatterlist has entries
+		 * that have been merged, the non-DMA mapped scatterlist
+		 * must be advanced multiple times for each merged entry.
+		 * This ensures that the current non-DMA mapped entry
+		 * corresponds to the current DMA mapped entry.
+		 */
+		do {
+			sg_combined_len += wa->sg->length;
+			wa->sg = sg_next(wa->sg);
+		} while (wa->sg_used > sg_combined_len);
+
 		wa->sg_used = 0;
 	}
 }
@@ -163,8 +178,11 @@
 
 		wa->dma.address = dma_map_single(wa->dev, wa->address, len,
 						 dir);
-		if (dma_mapping_error(wa->dev, wa->dma.address))
+		if (dma_mapping_error(wa->dev, wa->dma.address)) {
+			kfree(wa->address);
+			wa->address = NULL;
 			return -ENOMEM;
+		}
 
 		wa->dma.length = len;
 	}
@@ -299,7 +317,7 @@
 	/* Update the structures and generate the count */
 	buf_count = 0;
 	while (sg_wa->bytes_left && (buf_count < dm_wa->length)) {
-		nbytes = min(sg_wa->sg->length - sg_wa->sg_used,
+		nbytes = min(sg_dma_len(sg_wa->dma_sg) - sg_wa->sg_used,
 			     dm_wa->length - buf_count);
 		nbytes = min_t(u64, sg_wa->bytes_left, nbytes);
 
@@ -331,11 +349,11 @@
 	 * and destination. The resulting len values will always be <= UINT_MAX
 	 * because the dma length is an unsigned int.
 	 */
-	sg_src_len = sg_dma_len(src->sg_wa.sg) - src->sg_wa.sg_used;
+	sg_src_len = sg_dma_len(src->sg_wa.dma_sg) - src->sg_wa.sg_used;
 	sg_src_len = min_t(u64, src->sg_wa.bytes_left, sg_src_len);
 
 	if (dst) {
-		sg_dst_len = sg_dma_len(dst->sg_wa.sg) - dst->sg_wa.sg_used;
+		sg_dst_len = sg_dma_len(dst->sg_wa.dma_sg) - dst->sg_wa.sg_used;
 		sg_dst_len = min_t(u64, src->sg_wa.bytes_left, sg_dst_len);
 		op_len = min(sg_src_len, sg_dst_len);
 	} else {
@@ -365,7 +383,7 @@
 		/* Enough data in the sg element, but we need to
 		 * adjust for any previously copied data
 		 */
-		op->src.u.dma.address = sg_dma_address(src->sg_wa.sg);
+		op->src.u.dma.address = sg_dma_address(src->sg_wa.dma_sg);
 		op->src.u.dma.offset = src->sg_wa.sg_used;
 		op->src.u.dma.length = op_len & ~(block_size - 1);
 
@@ -386,7 +404,7 @@
 			/* Enough room in the sg element, but we need to
 			 * adjust for any previously used area
 			 */
-			op->dst.u.dma.address = sg_dma_address(dst->sg_wa.sg);
+			op->dst.u.dma.address = sg_dma_address(dst->sg_wa.dma_sg);
 			op->dst.u.dma.offset = dst->sg_wa.sg_used;
 			op->dst.u.dma.length = op->src.u.dma.length;
 		}
@@ -763,7 +781,7 @@
 				    in_place ? DMA_BIDIRECTIONAL
 					     : DMA_TO_DEVICE);
 		if (ret)
-			goto e_ctx;
+			goto e_aad;
 
 		if (in_place) {
 			dst = src;
@@ -848,7 +866,7 @@
 	op.u.aes.size = 0;
 	ret = cmd_q->ccp->vdata->perform->aes(&op);
 	if (ret)
-		goto e_dst;
+		goto e_final_wa;
 
 	if (aes->action == CCP_AES_ACTION_ENCRYPT) {
 		/* Put the ciphered tag after the ciphertext. */
@@ -858,17 +876,19 @@
 		ret = ccp_init_dm_workarea(&tag, cmd_q, authsize,
 					   DMA_BIDIRECTIONAL);
 		if (ret)
-			goto e_tag;
+			goto e_final_wa;
 		ret = ccp_set_dm_area(&tag, 0, p_tag, 0, authsize);
-		if (ret)
-			goto e_tag;
+		if (ret) {
+			ccp_dm_free(&tag);
+			goto e_final_wa;
+		}
 
 		ret = crypto_memneq(tag.address, final_wa.address,
 				    authsize) ? -EBADMSG : 0;
 		ccp_dm_free(&tag);
 	}
 
-e_tag:
+e_final_wa:
 	ccp_dm_free(&final_wa);
 
 e_dst:
@@ -1731,7 +1751,7 @@
 			break;
 		default:
 			ret = -EINVAL;
-			goto e_ctx;
+			goto e_data;
 		}
 	} else {
 		/* Stash the context */
@@ -1777,8 +1797,9 @@
 			       LSB_ITEM_SIZE);
 			break;
 		default:
+			kfree(hmac_buf);
 			ret = -EINVAL;
-			goto e_ctx;
+			goto e_data;
 		}
 
 		memset(&hmac_cmd, 0, sizeof(hmac_cmd));
@@ -2027,7 +2048,7 @@
 	dst.sg_wa.sg_used = 0;
 	for (i = 1; i <= src.sg_wa.dma_count; i++) {
 		if (!dst.sg_wa.sg ||
-		    (dst.sg_wa.sg->length < src.sg_wa.sg->length)) {
+		    (sg_dma_len(dst.sg_wa.sg) < sg_dma_len(src.sg_wa.sg))) {
 			ret = -EINVAL;
 			goto e_dst;
 		}
@@ -2053,8 +2074,8 @@
 			goto e_dst;
 		}
 
-		dst.sg_wa.sg_used += src.sg_wa.sg->length;
-		if (dst.sg_wa.sg_used == dst.sg_wa.sg->length) {
+		dst.sg_wa.sg_used += sg_dma_len(src.sg_wa.sg);
+		if (dst.sg_wa.sg_used == sg_dma_len(dst.sg_wa.sg)) {
 			dst.sg_wa.sg = sg_next(dst.sg_wa.sg);
 			dst.sg_wa.sg_used = 0;
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/ccp/psp-dev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/ccp/psp-dev.c
@@ -40,6 +40,10 @@
 module_param(psp_probe_timeout, int, 0644);
 MODULE_PARM_DESC(psp_probe_timeout, " default timeout value, in seconds, during PSP device probe");
 
+MODULE_FIRMWARE("amd/amd_sev_fam17h_model0xh.sbin"); /* 1st gen EPYC */
+MODULE_FIRMWARE("amd/amd_sev_fam17h_model3xh.sbin"); /* 2nd gen EPYC */
+MODULE_FIRMWARE("amd/amd_sev_fam19h_model0xh.sbin"); /* 3rd gen EPYC */
+
 static bool psp_dead;
 static int psp_timeout;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/ccp/sp-pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/ccp/sp-pci.c
@@ -213,7 +213,7 @@
 		if (ret) {
 			dev_err(dev, "dma_set_mask_and_coherent failed (%d)\n",
 				ret);
-			goto e_err;
+			goto free_irqs;
 		}
 	}
 
@@ -221,10 +221,12 @@
 
 	ret = sp_init(sp);
 	if (ret)
-		goto e_err;
+		goto free_irqs;
 
 	return 0;
 
+free_irqs:
+	sp_free_irqs(sp);
 e_err:
 	dev_notice(dev, "initialization failed\n");
 	return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/ccp/sp-platform.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/ccp/sp-platform.c
@@ -39,44 +39,38 @@
 	},
 };
 
-#ifdef CONFIG_ACPI
 static const struct acpi_device_id sp_acpi_match[] = {
 	{ "AMDI0C00", (kernel_ulong_t)&dev_vdata[0] },
 	{ },
 };
 MODULE_DEVICE_TABLE(acpi, sp_acpi_match);
-#endif
 
-#ifdef CONFIG_OF
 static const struct of_device_id sp_of_match[] = {
 	{ .compatible = "amd,ccp-seattle-v1a",
 	  .data = (const void *)&dev_vdata[0] },
 	{ },
 };
 MODULE_DEVICE_TABLE(of, sp_of_match);
-#endif
 
 static struct sp_dev_vdata *sp_get_of_version(struct platform_device *pdev)
 {
-#ifdef CONFIG_OF
 	const struct of_device_id *match;
 
 	match = of_match_node(sp_of_match, pdev->dev.of_node);
 	if (match && match->data)
 		return (struct sp_dev_vdata *)match->data;
-#endif
+
 	return NULL;
 }
 
 static struct sp_dev_vdata *sp_get_acpi_version(struct platform_device *pdev)
 {
-#ifdef CONFIG_ACPI
 	const struct acpi_device_id *match;
 
 	match = acpi_match_device(sp_acpi_match, &pdev->dev);
 	if (match && match->driver_data)
 		return (struct sp_dev_vdata *)match->driver_data;
-#endif
+
 	return NULL;
 }
 
@@ -222,12 +216,8 @@
 static struct platform_driver sp_platform_driver = {
 	.driver = {
 		.name = "ccp",
-#ifdef CONFIG_ACPI
 		.acpi_match_table = sp_acpi_match,
-#endif
-#ifdef CONFIG_OF
 		.of_match_table = sp_of_match,
-#endif
 	},
 	.probe = sp_platform_probe,
 	.remove = sp_platform_remove,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/ccree/cc_aead.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/ccree/cc_aead.c
@@ -237,7 +237,7 @@
 			 * revealed the decrypted message --> zero its memory.
 			 */
 			sg_zero_buffer(areq->dst, sg_nents(areq->dst),
-				       areq->cryptlen, 0);
+				       areq->cryptlen, areq->assoclen);
 			err = -EBADMSG;
 		}
 	/*ENCRYPT*/
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/ccree/cc_buffer_mgr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/ccree/cc_buffer_mgr.c
@@ -87,6 +87,8 @@
 {
 	unsigned int nents = 0;
 
+	*lbytes = 0;
+
 	while (nbytes && sg_list) {
 		nents++;
 		/* get the number of bytes in the last entry */
@@ -95,6 +97,7 @@
 				nbytes : sg_list->length;
 		sg_list = sg_next(sg_list);
 	}
+
 	dev_dbg(dev, "nents %d last bytes %d\n", nents, *lbytes);
 	return nents;
 }
@@ -290,37 +293,32 @@
 		     unsigned int nbytes, int direction, u32 *nents,
 		     u32 max_sg_nents, u32 *lbytes, u32 *mapped_nents)
 {
-	if (sg_is_last(sg)) {
-		/* One entry only case -set to DLLI */
-		if (dma_map_sg(dev, sg, 1, direction) != 1) {
-			dev_err(dev, "dma_map_sg() single buffer failed\n");
-			return -ENOMEM;
-		}
-		dev_dbg(dev, "Mapped sg: dma_address=%pad page=%p addr=%pK offset=%u length=%u\n",
-			&sg_dma_address(sg), sg_page(sg), sg_virt(sg),
-			sg->offset, sg->length);
-		*lbytes = nbytes;
-		*nents = 1;
-		*mapped_nents = 1;
-	} else {  /*sg_is_last*/
-		*nents = cc_get_sgl_nents(dev, sg, nbytes, lbytes);
-		if (*nents > max_sg_nents) {
-			*nents = 0;
-			dev_err(dev, "Too many fragments. current %d max %d\n",
-				*nents, max_sg_nents);
-			return -ENOMEM;
-		}
-		/* In case of mmu the number of mapped nents might
-		 * be changed from the original sgl nents
-		 */
-		*mapped_nents = dma_map_sg(dev, sg, *nents, direction);
-		if (*mapped_nents == 0) {
-			*nents = 0;
-			dev_err(dev, "dma_map_sg() sg buffer failed\n");
-			return -ENOMEM;
-		}
+	int ret = 0;
+
+	if (!nbytes) {
+		*mapped_nents = 0;
+		*lbytes = 0;
+		*nents = 0;
+		return 0;
 	}
 
+	*nents = cc_get_sgl_nents(dev, sg, nbytes, lbytes);
+	if (*nents > max_sg_nents) {
+		*nents = 0;
+		dev_err(dev, "Too many fragments. current %d max %d\n",
+			*nents, max_sg_nents);
+		return -ENOMEM;
+	}
+
+	ret = dma_map_sg(dev, sg, *nents, direction);
+	if (dma_mapping_error(dev, ret)) {
+		*nents = 0;
+		dev_err(dev, "dma_map_sg() sg buffer failed %d\n", ret);
+		return -ENOMEM;
+	}
+
+	*mapped_nents = ret;
+
 	return 0;
 }
 
@@ -555,11 +553,12 @@
 		sg_virt(req->src), areq_ctx->src.nents, areq_ctx->assoc.nents,
 		areq_ctx->assoclen, req->cryptlen);
 
-	dma_unmap_sg(dev, req->src, sg_nents(req->src), DMA_BIDIRECTIONAL);
+	dma_unmap_sg(dev, req->src, areq_ctx->src.mapped_nents,
+		     DMA_BIDIRECTIONAL);
 	if (req->src != req->dst) {
 		dev_dbg(dev, "Unmapping dst sgl: req->dst=%pK\n",
 			sg_virt(req->dst));
-		dma_unmap_sg(dev, req->dst, sg_nents(req->dst),
+		dma_unmap_sg(dev, req->dst, areq_ctx->dst.mapped_nents,
 			     DMA_BIDIRECTIONAL);
 	}
 	if (drvdata->coherent &&
@@ -881,7 +880,7 @@
 					    &src_last_bytes);
 	sg_index = areq_ctx->src_sgl->length;
 	//check where the data starts
-	while (sg_index <= size_to_skip) {
+	while (src_mapped_nents && (sg_index <= size_to_skip)) {
 		src_mapped_nents--;
 		offset -= areq_ctx->src_sgl->length;
 		sgl = sg_next(areq_ctx->src_sgl);
@@ -902,13 +901,17 @@
 
 	if (req->src != req->dst) {
 		size_for_map = areq_ctx->assoclen + req->cryptlen;
-		size_for_map += (direct == DRV_CRYPTO_DIRECTION_ENCRYPT) ?
-				authsize : 0;
+
+		if (direct == DRV_CRYPTO_DIRECTION_ENCRYPT)
+			size_for_map += authsize;
+		else
+			size_for_map -= authsize;
+
 		if (is_gcm4543)
 			size_for_map += crypto_aead_ivsize(tfm);
 
 		rc = cc_map_sg(dev, req->dst, size_for_map, DMA_BIDIRECTIONAL,
-			       &areq_ctx->dst.nents,
+			       &areq_ctx->dst.mapped_nents,
 			       LLI_MAX_NUM_OF_DATA_ENTRIES, &dst_last_bytes,
 			       &dst_mapped_nents);
 		if (rc)
@@ -921,7 +924,7 @@
 	offset = size_to_skip;
 
 	//check where the data starts
-	while (sg_index <= size_to_skip) {
+	while (dst_mapped_nents && sg_index <= size_to_skip) {
 		dst_mapped_nents--;
 		offset -= areq_ctx->dst_sgl->length;
 		sgl = sg_next(areq_ctx->dst_sgl);
@@ -1117,13 +1120,15 @@
 	}
 
 	size_to_map = req->cryptlen + areq_ctx->assoclen;
-	if (areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_ENCRYPT)
+	/* If we do in-place encryption, we also need the auth tag */
+	if ((areq_ctx->gen_ctx.op_type == DRV_CRYPTO_DIRECTION_ENCRYPT) &&
+	   (req->src == req->dst)) {
 		size_to_map += authsize;
-
+	}
 	if (is_gcm4543)
 		size_to_map += crypto_aead_ivsize(tfm);
 	rc = cc_map_sg(dev, req->src, size_to_map, DMA_BIDIRECTIONAL,
-		       &areq_ctx->src.nents,
+		       &areq_ctx->src.mapped_nents,
 		       (LLI_MAX_NUM_OF_ASSOC_DATA_ENTRIES +
 			LLI_MAX_NUM_OF_DATA_ENTRIES),
 		       &dummy, &mapped_nents);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/ccree/cc_buffer_mgr.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/ccree/cc_buffer_mgr.h
@@ -25,6 +25,7 @@
 
 struct cc_mlli {
 	cc_sram_addr_t sram_addr;
+	unsigned int mapped_nents;
 	unsigned int nents; //sg nents
 	unsigned int mlli_nents; //mlli nents might be different than the above
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/ccree/cc_cipher.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/ccree/cc_cipher.c
@@ -163,7 +163,6 @@
 				     skcipher_alg.base);
 	struct device *dev = drvdata_to_dev(cc_alg->drvdata);
 	unsigned int max_key_buf_size = cc_alg->skcipher_alg.max_keysize;
-	int rc = 0;
 
 	dev_dbg(dev, "Initializing context @%p for %s\n", ctx_p,
 		crypto_tfm_alg_name(tfm));
@@ -175,10 +174,19 @@
 	ctx_p->flow_mode = cc_alg->flow_mode;
 	ctx_p->drvdata = cc_alg->drvdata;
 
+	if (ctx_p->cipher_mode == DRV_CIPHER_ESSIV) {
+		/* Alloc hash tfm for essiv */
+		ctx_p->shash_tfm = crypto_alloc_shash("sha256-generic", 0, 0);
+		if (IS_ERR(ctx_p->shash_tfm)) {
+			dev_err(dev, "Error allocating hash tfm for ESSIV.\n");
+			return PTR_ERR(ctx_p->shash_tfm);
+		}
+	}
+
 	/* Allocate key buffer, cache line aligned */
 	ctx_p->user.key = kmalloc(max_key_buf_size, GFP_KERNEL);
 	if (!ctx_p->user.key)
-		return -ENOMEM;
+		goto free_shash;
 
 	dev_dbg(dev, "Allocated key buffer in context. key=@%p\n",
 		ctx_p->user.key);
@@ -190,21 +198,19 @@
 	if (dma_mapping_error(dev, ctx_p->user.key_dma_addr)) {
 		dev_err(dev, "Mapping Key %u B at va=%pK for DMA failed\n",
 			max_key_buf_size, ctx_p->user.key);
-		return -ENOMEM;
+		goto free_key;
 	}
 	dev_dbg(dev, "Mapped key %u B at va=%pK to dma=%pad\n",
 		max_key_buf_size, ctx_p->user.key, &ctx_p->user.key_dma_addr);
 
-	if (ctx_p->cipher_mode == DRV_CIPHER_ESSIV) {
-		/* Alloc hash tfm for essiv */
-		ctx_p->shash_tfm = crypto_alloc_shash("sha256-generic", 0, 0);
-		if (IS_ERR(ctx_p->shash_tfm)) {
-			dev_err(dev, "Error allocating hash tfm for ESSIV.\n");
-			return PTR_ERR(ctx_p->shash_tfm);
-		}
-	}
+	return 0;
 
-	return rc;
+free_key:
+	kfree(ctx_p->user.key);
+free_shash:
+	crypto_free_shash(ctx_p->shash_tfm);
+
+	return -ENOMEM;
 }
 
 static void cc_cipher_exit(struct crypto_tfm *tfm)
@@ -523,6 +529,7 @@
 	}
 }
 
+
 static void cc_setup_state_desc(struct crypto_tfm *tfm,
 				 struct cipher_req_ctx *req_ctx,
 				 unsigned int ivsize, unsigned int nbytes,
@@ -534,8 +541,6 @@
 	int cipher_mode = ctx_p->cipher_mode;
 	int flow_mode = ctx_p->flow_mode;
 	int direction = req_ctx->gen_ctx.op_type;
-	dma_addr_t key_dma_addr = ctx_p->user.key_dma_addr;
-	unsigned int key_len = ctx_p->keylen;
 	dma_addr_t iv_dma_addr = req_ctx->gen_ctx.iv_dma_addr;
 	unsigned int du_size = nbytes;
 
@@ -571,6 +576,47 @@
 	case DRV_CIPHER_XTS:
 	case DRV_CIPHER_ESSIV:
 	case DRV_CIPHER_BITLOCKER:
+		break;
+	default:
+		dev_err(dev, "Unsupported cipher mode (%d)\n", cipher_mode);
+	}
+}
+
+
+static void cc_setup_xex_state_desc(struct crypto_tfm *tfm,
+				 struct cipher_req_ctx *req_ctx,
+				 unsigned int ivsize, unsigned int nbytes,
+				 struct cc_hw_desc desc[],
+				 unsigned int *seq_size)
+{
+	struct cc_cipher_ctx *ctx_p = crypto_tfm_ctx(tfm);
+	struct device *dev = drvdata_to_dev(ctx_p->drvdata);
+	int cipher_mode = ctx_p->cipher_mode;
+	int flow_mode = ctx_p->flow_mode;
+	int direction = req_ctx->gen_ctx.op_type;
+	dma_addr_t key_dma_addr = ctx_p->user.key_dma_addr;
+	unsigned int key_len = ctx_p->keylen;
+	dma_addr_t iv_dma_addr = req_ctx->gen_ctx.iv_dma_addr;
+	unsigned int du_size = nbytes;
+
+	struct cc_crypto_alg *cc_alg =
+		container_of(tfm->__crt_alg, struct cc_crypto_alg,
+			     skcipher_alg.base);
+
+	if (cc_alg->data_unit)
+		du_size = cc_alg->data_unit;
+
+	switch (cipher_mode) {
+	case DRV_CIPHER_ECB:
+		break;
+	case DRV_CIPHER_CBC:
+	case DRV_CIPHER_CBC_CTS:
+	case DRV_CIPHER_CTR:
+	case DRV_CIPHER_OFB:
+		break;
+	case DRV_CIPHER_XTS:
+	case DRV_CIPHER_ESSIV:
+	case DRV_CIPHER_BITLOCKER:
 		/* load XEX key */
 		hw_desc_init(&desc[*seq_size]);
 		set_cipher_mode(&desc[*seq_size], cipher_mode);
@@ -881,12 +927,14 @@
 
 	/* STAT_PHASE_2: Create sequence */
 
-	/* Setup IV and XEX key used */
+	/* Setup state (IV)  */
 	cc_setup_state_desc(tfm, req_ctx, ivsize, nbytes, desc, &seq_len);
 	/* Setup MLLI line, if needed */
 	cc_setup_mlli_desc(tfm, req_ctx, dst, src, nbytes, req, desc, &seq_len);
 	/* Setup key */
 	cc_setup_key_desc(tfm, req_ctx, nbytes, desc, &seq_len);
+	/* Setup state (IV and XEX key)  */
+	cc_setup_xex_state_desc(tfm, req_ctx, ivsize, nbytes, desc, &seq_len);
 	/* Data processing */
 	cc_setup_flow_desc(tfm, req_ctx, dst, src, nbytes, desc, &seq_len);
 	/* Read next IV */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/ccree/cc_debugfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/ccree/cc_debugfs.c
@@ -59,7 +59,7 @@
 	cc_debugfs_dir = debugfs_create_dir("ccree", NULL);
 }
 
-void __exit cc_debugfs_global_fini(void)
+void cc_debugfs_global_fini(void)
 {
 	debugfs_remove(cc_debugfs_dir);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/ccree/cc_driver.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/ccree/cc_driver.c
@@ -653,10 +653,17 @@
 
 static int __init ccree_init(void)
 {
-	cc_hash_global_init();
+	int rc;
+
 	cc_debugfs_global_init();
 
-	return platform_driver_register(&ccree_driver);
+	rc = platform_driver_register(&ccree_driver);
+	if (rc) {
+		cc_debugfs_global_fini();
+		return rc;
+	}
+
+	return 0;
 }
 module_init(ccree_init);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/ccree/cc_driver.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/ccree/cc_driver.h
@@ -161,6 +161,7 @@
 	int std_bodies;
 	bool sec_disabled;
 	u32 comp_mask;
+	bool pm_on;
 };
 
 struct cc_crypto_alg {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/ccree/cc_hash.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/ccree/cc_hash.c
@@ -39,12 +39,19 @@
 	SHA256_H3, SHA256_H2, SHA256_H1, SHA256_H0 };
 static const u32 cc_digest_len_sha512_init[] = {
 	0x00000080, 0x00000000, 0x00000000, 0x00000000 };
-static u64 cc_sha384_init[] = {
-	SHA384_H7, SHA384_H6, SHA384_H5, SHA384_H4,
-	SHA384_H3, SHA384_H2, SHA384_H1, SHA384_H0 };
-static u64 cc_sha512_init[] = {
-	SHA512_H7, SHA512_H6, SHA512_H5, SHA512_H4,
-	SHA512_H3, SHA512_H2, SHA512_H1, SHA512_H0 };
+
+/*
+ * Due to the way the HW works, every double word in the SHA384 and SHA512
+ * larval hashes must be stored in hi/lo order
+ */
+#define hilo(x)	upper_32_bits(x), lower_32_bits(x)
+static const u32 cc_sha384_init[] = {
+	hilo(SHA384_H7), hilo(SHA384_H6), hilo(SHA384_H5), hilo(SHA384_H4),
+	hilo(SHA384_H3), hilo(SHA384_H2), hilo(SHA384_H1), hilo(SHA384_H0) };
+static const u32 cc_sha512_init[] = {
+	hilo(SHA512_H7), hilo(SHA512_H6), hilo(SHA512_H5), hilo(SHA512_H4),
+	hilo(SHA512_H3), hilo(SHA512_H2), hilo(SHA512_H1), hilo(SHA512_H0) };
+
 static const u32 cc_sm3_init[] = {
 	SM3_IVH, SM3_IVG, SM3_IVF, SM3_IVE,
 	SM3_IVD, SM3_IVC, SM3_IVB, SM3_IVA };
@@ -1948,8 +1955,8 @@
 	}
 
 	if (large_sha_supported) {
-		cc_set_sram_desc((u32 *)cc_sha384_init, sram_buff_ofs,
-				 (ARRAY_SIZE(cc_sha384_init) * 2), larval_seq,
+		cc_set_sram_desc(cc_sha384_init, sram_buff_ofs,
+				 ARRAY_SIZE(cc_sha384_init), larval_seq,
 				 &larval_seq_len);
 		rc = send_request_init(drvdata, larval_seq, larval_seq_len);
 		if (rc)
@@ -1957,8 +1964,8 @@
 		sram_buff_ofs += sizeof(cc_sha384_init);
 		larval_seq_len = 0;
 
-		cc_set_sram_desc((u32 *)cc_sha512_init, sram_buff_ofs,
-				 (ARRAY_SIZE(cc_sha512_init) * 2), larval_seq,
+		cc_set_sram_desc(cc_sha512_init, sram_buff_ofs,
+				 ARRAY_SIZE(cc_sha512_init), larval_seq,
 				 &larval_seq_len);
 		rc = send_request_init(drvdata, larval_seq, larval_seq_len);
 		if (rc)
@@ -1969,28 +1976,6 @@
 	return rc;
 }
 
-static void __init cc_swap_dwords(u32 *buf, unsigned long size)
-{
-	int i;
-	u32 tmp;
-
-	for (i = 0; i < size; i += 2) {
-		tmp = buf[i];
-		buf[i] = buf[i + 1];
-		buf[i + 1] = tmp;
-	}
-}
-
-/*
- * Due to the way the HW works we need to swap every
- * double word in the SHA384 and SHA512 larval hashes
- */
-void __init cc_hash_global_init(void)
-{
-	cc_swap_dwords((u32 *)&cc_sha384_init, (ARRAY_SIZE(cc_sha384_init) * 2));
-	cc_swap_dwords((u32 *)&cc_sha512_init, (ARRAY_SIZE(cc_sha512_init) * 2));
-}
-
 int cc_hash_alloc(struct cc_drvdata *drvdata)
 {
 	struct cc_hash_handle *hash_handle;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/ccree/cc_hash.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/ccree/cc_hash.h
@@ -104,6 +104,4 @@
  */
 cc_sram_addr_t cc_larval_digest_addr(void *drvdata, u32 mode);
 
-void cc_hash_global_init(void);
-
 #endif /*__CC_HASH_H__*/
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/ccree/cc_pm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/ccree/cc_pm.c
@@ -22,14 +22,8 @@
 int cc_pm_suspend(struct device *dev)
 {
 	struct cc_drvdata *drvdata = dev_get_drvdata(dev);
-	int rc;
 
 	dev_dbg(dev, "set HOST_POWER_DOWN_EN\n");
-	rc = cc_suspend_req_queue(drvdata);
-	if (rc) {
-		dev_err(dev, "cc_suspend_req_queue (%x)\n", rc);
-		return rc;
-	}
 	fini_cc_regs(drvdata);
 	cc_iowrite(drvdata, CC_REG(HOST_POWER_DOWN_EN), POWER_DOWN_ENABLE);
 	cc_clk_off(drvdata);
@@ -63,13 +57,6 @@
 	/* check if tee fips error occurred during power down */
 	cc_tee_handle_fips_error(drvdata);
 
-	rc = cc_resume_req_queue(drvdata);
-	if (rc) {
-		dev_err(dev, "cc_resume_req_queue (%x)\n", rc);
-		return rc;
-	}
-
-	/* must be after the queue resuming as it uses the HW queue*/
 	cc_init_hash_sram(drvdata);
 
 	return 0;
@@ -80,12 +67,10 @@
 	int rc = 0;
 	struct cc_drvdata *drvdata = dev_get_drvdata(dev);
 
-	if (cc_req_queue_suspended(drvdata))
+	if (drvdata->pm_on)
 		rc = pm_runtime_get_sync(dev);
-	else
-		pm_runtime_get_noresume(dev);
 
-	return rc;
+	return (rc == 1 ? 0 : rc);
 }
 
 int cc_pm_put_suspend(struct device *dev)
@@ -93,14 +78,11 @@
 	int rc = 0;
 	struct cc_drvdata *drvdata = dev_get_drvdata(dev);
 
-	if (!cc_req_queue_suspended(drvdata)) {
+	if (drvdata->pm_on) {
 		pm_runtime_mark_last_busy(dev);
 		rc = pm_runtime_put_autosuspend(dev);
-	} else {
-		/* Something wrong happens*/
-		dev_err(dev, "request to suspend already suspended queue");
-		rc = -EBUSY;
 	}
+
 	return rc;
 }
 
@@ -117,7 +99,7 @@
 	/* must be before the enabling to avoid resdundent suspending */
 	pm_runtime_set_autosuspend_delay(dev, CC_SUSPEND_TIMEOUT);
 	pm_runtime_use_autosuspend(dev);
-	/* activate the PM module */
+	/* set us as active - note we won't do PM ops until cc_pm_go()! */
 	return pm_runtime_set_active(dev);
 }
 
@@ -125,9 +107,11 @@
 void cc_pm_go(struct cc_drvdata *drvdata)
 {
 	pm_runtime_enable(drvdata_to_dev(drvdata));
+	drvdata->pm_on = true;
 }
 
 void cc_pm_fini(struct cc_drvdata *drvdata)
 {
 	pm_runtime_disable(drvdata_to_dev(drvdata));
+	drvdata->pm_on = false;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/ccree/cc_request_mgr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/ccree/cc_request_mgr.c
@@ -41,7 +41,6 @@
 #else
 	struct tasklet_struct comptask;
 #endif
-	bool is_runtime_suspended;
 };
 
 struct cc_bl_item {
@@ -404,6 +403,7 @@
 		spin_lock(&mgr->bl_lock);
 		list_del(&bli->list);
 		--mgr->bl_len;
+		kfree(bli);
 	}
 
 	spin_unlock(&mgr->bl_lock);
@@ -677,52 +677,3 @@
 	cc_proc_backlog(drvdata);
 	dev_dbg(dev, "Comp. handler done.\n");
 }
-
-/*
- * resume the queue configuration - no need to take the lock as this happens
- * inside the spin lock protection
- */
-#if defined(CONFIG_PM)
-int cc_resume_req_queue(struct cc_drvdata *drvdata)
-{
-	struct cc_req_mgr_handle *request_mgr_handle =
-		drvdata->request_mgr_handle;
-
-	spin_lock_bh(&request_mgr_handle->hw_lock);
-	request_mgr_handle->is_runtime_suspended = false;
-	spin_unlock_bh(&request_mgr_handle->hw_lock);
-
-	return 0;
-}
-
-/*
- * suspend the queue configuration. Since it is used for the runtime suspend
- * only verify that the queue can be suspended.
- */
-int cc_suspend_req_queue(struct cc_drvdata *drvdata)
-{
-	struct cc_req_mgr_handle *request_mgr_handle =
-						drvdata->request_mgr_handle;
-
-	/* lock the send_request */
-	spin_lock_bh(&request_mgr_handle->hw_lock);
-	if (request_mgr_handle->req_queue_head !=
-	    request_mgr_handle->req_queue_tail) {
-		spin_unlock_bh(&request_mgr_handle->hw_lock);
-		return -EBUSY;
-	}
-	request_mgr_handle->is_runtime_suspended = true;
-	spin_unlock_bh(&request_mgr_handle->hw_lock);
-
-	return 0;
-}
-
-bool cc_req_queue_suspended(struct cc_drvdata *drvdata)
-{
-	struct cc_req_mgr_handle *request_mgr_handle =
-						drvdata->request_mgr_handle;
-
-	return	request_mgr_handle->is_runtime_suspended;
-}
-
-#endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/ccree/cc_request_mgr.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/ccree/cc_request_mgr.h
@@ -40,12 +40,4 @@
 
 void cc_req_mgr_fini(struct cc_drvdata *drvdata);
 
-#if defined(CONFIG_PM)
-int cc_resume_req_queue(struct cc_drvdata *drvdata);
-
-int cc_suspend_req_queue(struct cc_drvdata *drvdata);
-
-bool cc_req_queue_suspended(struct cc_drvdata *drvdata);
-#endif
-
 #endif /*__REQUEST_MGR_H__*/
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/chelsio/chcr_algo.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/chelsio/chcr_algo.c
@@ -2480,8 +2480,9 @@
 	else
 		reqctx->b0_dma = 0;
 	if (req->src == req->dst) {
-		error = dma_map_sg(dev, req->src, sg_nents(req->src),
-				   DMA_BIDIRECTIONAL);
+		error = dma_map_sg(dev, req->src,
+				sg_nents_for_len(req->src, dst_size),
+					DMA_BIDIRECTIONAL);
 		if (!error)
 			goto err;
 	} else {
@@ -2818,7 +2819,7 @@
 	unsigned int mac_mode = CHCR_SCMD_AUTH_MODE_CBCMAC;
 	unsigned int c_id = a_ctx(tfm)->tx_chan_id;
 	unsigned int ccm_xtra;
-	unsigned char tag_offset = 0, auth_offset = 0;
+	unsigned int tag_offset = 0, auth_offset = 0;
 	unsigned int assoclen;
 
 	if (get_aead_subtype(tfm) == CRYPTO_ALG_SUB_TYPE_AEAD_RFC4309)
@@ -3194,9 +3195,6 @@
 		aeadctx->mayverify = VERIFY_SW;
 		break;
 	default:
-
-		  crypto_tfm_set_flags((struct crypto_tfm *) tfm,
-			CRYPTO_TFM_RES_BAD_KEY_LEN);
 		return -EINVAL;
 	}
 	return crypto_aead_setauthsize(aeadctx->sw_cipher, authsize);
@@ -3221,8 +3219,6 @@
 		aeadctx->mayverify = VERIFY_HW;
 		break;
 	default:
-		crypto_tfm_set_flags((struct crypto_tfm *)tfm,
-				     CRYPTO_TFM_RES_BAD_KEY_LEN);
 		return -EINVAL;
 	}
 	return crypto_aead_setauthsize(aeadctx->sw_cipher, authsize);
@@ -3263,8 +3259,6 @@
 		aeadctx->mayverify = VERIFY_HW;
 		break;
 	default:
-		crypto_tfm_set_flags((struct crypto_tfm *)tfm,
-				     CRYPTO_TFM_RES_BAD_KEY_LEN);
 		return -EINVAL;
 	}
 	return crypto_aead_setauthsize(aeadctx->sw_cipher, authsize);
@@ -3289,8 +3283,7 @@
 		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_256;
 		mk_size = CHCR_KEYCTX_MAC_KEY_SIZE_256;
 	} else {
-		crypto_tfm_set_flags((struct crypto_tfm *)aead,
-				     CRYPTO_TFM_RES_BAD_KEY_LEN);
+		crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN);
 		aeadctx->enckey_len = 0;
 		return	-EINVAL;
 	}
@@ -3328,8 +3321,7 @@
 	int error;
 
 	if (keylen < 3) {
-		crypto_tfm_set_flags((struct crypto_tfm *)aead,
-				     CRYPTO_TFM_RES_BAD_KEY_LEN);
+		crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN);
 		aeadctx->enckey_len = 0;
 		return	-EINVAL;
 	}
@@ -3379,8 +3371,7 @@
 	} else if (keylen == AES_KEYSIZE_256) {
 		ck_size = CHCR_KEYCTX_CIPHER_KEY_SIZE_256;
 	} else {
-		crypto_tfm_set_flags((struct crypto_tfm *)aead,
-				     CRYPTO_TFM_RES_BAD_KEY_LEN);
+		crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN);
 		pr_err("GCM: Invalid key length %d\n", keylen);
 		ret = -EINVAL;
 		goto out;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/chelsio/chcr_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/chelsio/chcr_core.c
@@ -125,8 +125,6 @@
 	atomic_set(&dev->inflight, 0);
 	mutex_lock(&drv_data.drv_mutex);
 	list_add_tail(&u_ctx->entry, &drv_data.inact_dev);
-	if (!drv_data.last_dev)
-		drv_data.last_dev = u_ctx;
 	mutex_unlock(&drv_data.drv_mutex);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/chelsio/chtls/chtls_cm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/chelsio/chtls/chtls_cm.c
@@ -174,7 +174,7 @@
 {
 	if (likely(skb && !skb_shared(skb) && !skb_cloned(skb))) {
 		__skb_trim(skb, 0);
-		refcount_add(2, &skb->users);
+		refcount_inc(&skb->users);
 	} else {
 		skb = alloc_skb(len, GFP_KERNEL | __GFP_NOFAIL);
 	}
@@ -577,7 +577,7 @@
 
 	while (!skb_queue_empty(&listen_ctx->synq)) {
 		struct chtls_sock *csk =
-			container_of((struct synq *)__skb_dequeue
+			container_of((struct synq *)skb_peek
 				(&listen_ctx->synq), struct chtls_sock, synq);
 		struct sock *child = csk->sk;
 
@@ -692,14 +692,13 @@
 	if (rpl->status != CPL_ERR_NONE) {
 		pr_info("Unexpected PASS_OPEN_RPL status %u for STID %u\n",
 			rpl->status, stid);
-		return CPL_RET_BUF_DONE;
+	} else {
+		cxgb4_free_stid(cdev->tids, stid, listen_ctx->lsk->sk_family);
+		sock_put(listen_ctx->lsk);
+		kfree(listen_ctx);
+		module_put(THIS_MODULE);
 	}
-	cxgb4_free_stid(cdev->tids, stid, listen_ctx->lsk->sk_family);
-	sock_put(listen_ctx->lsk);
-	kfree(listen_ctx);
-	module_put(THIS_MODULE);
-
-	return 0;
+	return CPL_RET_BUF_DONE;
 }
 
 static int chtls_close_listsrv_rpl(struct chtls_dev *cdev, struct sk_buff *skb)
@@ -716,15 +715,21 @@
 	if (rpl->status != CPL_ERR_NONE) {
 		pr_info("Unexpected CLOSE_LISTSRV_RPL status %u for STID %u\n",
 			rpl->status, stid);
-		return CPL_RET_BUF_DONE;
+	} else {
+		cxgb4_free_stid(cdev->tids, stid, listen_ctx->lsk->sk_family);
+		sock_put(listen_ctx->lsk);
+		kfree(listen_ctx);
+		module_put(THIS_MODULE);
 	}
+	return CPL_RET_BUF_DONE;
+}
 
-	cxgb4_free_stid(cdev->tids, stid, listen_ctx->lsk->sk_family);
-	sock_put(listen_ctx->lsk);
-	kfree(listen_ctx);
-	module_put(THIS_MODULE);
+static void chtls_purge_wr_queue(struct sock *sk)
+{
+	struct sk_buff *skb;
 
-	return 0;
+	while ((skb = dequeue_wr(sk)) != NULL)
+		kfree_skb(skb);
 }
 
 static void chtls_release_resources(struct sock *sk)
@@ -741,6 +746,11 @@
 	kfree_skb(csk->txdata_skb_cache);
 	csk->txdata_skb_cache = NULL;
 
+	if (csk->wr_credits != csk->wr_max_credits) {
+		chtls_purge_wr_queue(sk);
+		chtls_reset_wr_list(csk);
+	}
+
 	if (csk->l2t_entry) {
 		cxgb4_l2t_release(csk->l2t_entry);
 		csk->l2t_entry = NULL;
@@ -1011,6 +1021,7 @@
 				    const struct cpl_pass_accept_req *req,
 				    struct chtls_dev *cdev)
 {
+	struct adapter *adap = pci_get_drvdata(cdev->pdev);
 	struct inet_sock *newinet;
 	const struct iphdr *iph;
 	struct tls_context *ctx;
@@ -1020,9 +1031,10 @@
 	struct neighbour *n;
 	struct tcp_sock *tp;
 	struct sock *newsk;
+	bool found = false;
 	u16 port_id;
 	int rxq_idx;
-	int step;
+	int step, i;
 
 	iph = (const struct iphdr *)network_hdr;
 	newsk = tcp_create_openreq_child(lsk, oreq, cdev->askb);
@@ -1034,12 +1046,20 @@
 		goto free_sk;
 
 	n = dst_neigh_lookup(dst, &iph->saddr);
-	if (!n)
-		goto free_sk;
+	if (!n || !n->dev)
+		goto free_dst;
 
 	ndev = n->dev;
-	if (!ndev)
+	if (is_vlan_dev(ndev))
+		ndev = vlan_dev_real_dev(ndev);
+
+	for_each_port(adap, i)
+		if (cdev->ports[i] == ndev)
+			found = true;
+
+	if (!found)
 		goto free_dst;
+
 	port_id = cxgb4_port_idx(ndev);
 
 	csk = chtls_sock_create(cdev);
@@ -1064,6 +1084,7 @@
 	sk_setup_caps(newsk, dst);
 	ctx = tls_get_ctx(lsk);
 	newsk->sk_destruct = ctx->sk_destruct;
+	newsk->sk_prot_creator = lsk->sk_prot_creator;
 	csk->sk = newsk;
 	csk->passive_reap_next = oreq;
 	csk->tx_chan = cxgb4_port_chan(ndev);
@@ -1082,8 +1103,8 @@
 	csk->sndbuf = newsk->sk_sndbuf;
 	csk->smac_idx = ((struct port_info *)netdev_priv(ndev))->smt_idx;
 	RCV_WSCALE(tp) = select_rcv_wscale(tcp_full_space(newsk),
-					   sock_net(newsk)->
-						ipv4.sysctl_tcp_window_scaling,
+					   READ_ONCE(sock_net(newsk)->
+						     ipv4.sysctl_tcp_window_scaling),
 					   tp->window_clamp);
 	neigh_release(n);
 	inet_inherit_port(&tcp_hashinfo, lsk, newsk);
@@ -1094,6 +1115,8 @@
 free_csk:
 	chtls_sock_release(&csk->kref);
 free_dst:
+	if (n)
+		neigh_release(n);
 	dst_release(dst);
 free_sk:
 	inet_csk_prepare_forced_close(newsk);
@@ -1212,7 +1235,7 @@
 	chtls_set_req_addr(oreq, iph->daddr, iph->saddr);
 	ip_dsfield = ipv4_get_dsfield(iph);
 	if (req->tcpopt.wsf <= 14 &&
-	    sock_net(sk)->ipv4.sysctl_tcp_window_scaling) {
+	    READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_window_scaling)) {
 		inet_rsk(oreq)->wscale_ok = 1;
 		inet_rsk(oreq)->snd_wscale = req->tcpopt.wsf;
 	}
@@ -1353,7 +1376,6 @@
 	struct chtls_sock *csk = sk->sk_user_data;
 
 	local_bh_disable();
-	bh_lock_sock(sk);
 	release_tcp_port(sk); /* release the port immediately */
 
 	spin_lock(&reap_list_lock);
@@ -1362,7 +1384,6 @@
 	if (!csk->passive_reap_next)
 		schedule_work(&reap_task);
 	spin_unlock(&reap_list_lock);
-	bh_unlock_sock(sk);
 	local_bh_enable();
 }
 
@@ -1431,6 +1452,11 @@
 			sk_wake_async(sk, 0, POLL_OUT);
 
 		data = lookup_stid(cdev->tids, stid);
+		if (!data) {
+			/* listening server close */
+			kfree_skb(skb);
+			goto unlock;
+		}
 		lsk = ((struct listen_ctx *)data)->lsk;
 
 		bh_lock_sock(lsk);
@@ -1735,6 +1761,7 @@
 		else
 			sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN);
 	}
+	kfree_skb(skb);
 }
 
 static void chtls_close_con_rpl(struct sock *sk, struct sk_buff *skb)
@@ -1815,39 +1842,6 @@
 	kfree_skb(skb);
 }
 
-static void send_abort_rpl(struct sock *sk, struct sk_buff *skb,
-			   struct chtls_dev *cdev, int status, int queue)
-{
-	struct cpl_abort_req_rss *req = cplhdr(skb);
-	struct sk_buff *reply_skb;
-	struct chtls_sock *csk;
-
-	csk = rcu_dereference_sk_user_data(sk);
-
-	reply_skb = alloc_skb(sizeof(struct cpl_abort_rpl),
-			      GFP_KERNEL);
-
-	if (!reply_skb) {
-		req->status = (queue << 1);
-		send_defer_abort_rpl(cdev, skb);
-		return;
-	}
-
-	set_abort_rpl_wr(reply_skb, GET_TID(req), status);
-	kfree_skb(skb);
-
-	set_wr_txq(reply_skb, CPL_PRIORITY_DATA, queue);
-	if (csk_conn_inline(csk)) {
-		struct l2t_entry *e = csk->l2t_entry;
-
-		if (e && sk->sk_state != TCP_SYN_RECV) {
-			cxgb4_l2t_send(csk->egress_dev, reply_skb, e);
-			return;
-		}
-	}
-	cxgb4_ofld_send(cdev->lldi->ports[0], reply_skb);
-}
-
 /*
  * Add an skb to the deferred skb queue for processing from process context.
  */
@@ -1910,9 +1904,9 @@
 	queue = csk->txq_idx;
 
 	skb->sk	= NULL;
+	chtls_send_abort_rpl(child, skb, BLOG_SKB_CB(skb)->cdev,
+			     CPL_ABORT_NO_RST, queue);
 	do_abort_syn_rcv(child, lsk);
-	send_abort_rpl(child, skb, BLOG_SKB_CB(skb)->cdev,
-		       CPL_ABORT_NO_RST, queue);
 }
 
 static int abort_syn_rcv(struct sock *sk, struct sk_buff *skb)
@@ -1942,8 +1936,8 @@
 	if (!sock_owned_by_user(psk)) {
 		int queue = csk->txq_idx;
 
+		chtls_send_abort_rpl(sk, skb, cdev, CPL_ABORT_NO_RST, queue);
 		do_abort_syn_rcv(sk, psk);
-		send_abort_rpl(sk, skb, cdev, CPL_ABORT_NO_RST, queue);
 	} else {
 		skb->sk = sk;
 		BLOG_SKB_CB(skb)->backlog_rcv = bl_abort_syn_rcv;
@@ -1961,9 +1955,6 @@
 	int queue = csk->txq_idx;
 
 	if (is_neg_adv(req->status)) {
-		if (sk->sk_state == TCP_SYN_RECV)
-			chtls_set_tcb_tflag(sk, 0, 0);
-
 		kfree_skb(skb);
 		return;
 	}
@@ -1989,12 +1980,11 @@
 
 		if (sk->sk_state == TCP_SYN_RECV && !abort_syn_rcv(sk, skb))
 			return;
-
-		chtls_release_resources(sk);
-		chtls_conn_done(sk);
 	}
 
 	chtls_send_abort_rpl(sk, skb, csk->cdev, rst_status, queue);
+	chtls_release_resources(sk);
+	chtls_conn_done(sk);
 }
 
 static void chtls_abort_rpl_rss(struct sock *sk, struct sk_buff *skb)
@@ -2062,19 +2052,6 @@
 	return 0;
 }
 
-static struct sk_buff *dequeue_wr(struct sock *sk)
-{
-	struct chtls_sock *csk = rcu_dereference_sk_user_data(sk);
-	struct sk_buff *skb = csk->wr_skb_head;
-
-	if (likely(skb)) {
-	/* Don't bother clearing the tail */
-		csk->wr_skb_head = WR_SKB_CB(skb)->next_wr;
-		WR_SKB_CB(skb)->next_wr = NULL;
-	}
-	return skb;
-}
-
 static void chtls_rx_ack(struct sock *sk, struct sk_buff *skb)
 {
 	struct cpl_fw4_ack *hdr = cplhdr(skb) + RSS_HDR;
@@ -2115,7 +2092,7 @@
 
 		if (tp->snd_una != snd_una) {
 			tp->snd_una = snd_una;
-			tp->rcv_tstamp = tcp_time_stamp(tp);
+			tp->rcv_tstamp = tcp_jiffies32;
 			if (tp->snd_una == tp->snd_nxt &&
 			    !csk_flag_nochk(csk, CSK_TX_FAILOVER))
 				csk_reset_flag(csk, CSK_TX_WAIT_IDLE);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/chelsio/chtls/chtls_cm.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/chelsio/chtls/chtls_cm.h
@@ -50,9 +50,6 @@
 #define MIN_RCV_WND (24 * 1024U)
 #define LOOPBACK(x)     (((x) & htonl(0xff000000)) == htonl(0x7f000000))
 
-/* ulp_mem_io + ulptx_idata + payload + padding */
-#define MAX_IMM_ULPTX_WR_LEN (32 + 8 + 256 + 8)
-
 /* for TX: a skb must have a headroom of at least TX_HEADER_LEN bytes */
 #define TX_HEADER_LEN \
 	(sizeof(struct fw_ofld_tx_data_wr) + sizeof(struct sge_opaque_hdr))
@@ -185,6 +182,12 @@
 	kfree_skb(skb);
 }
 
+static inline void chtls_reset_wr_list(struct chtls_sock *csk)
+{
+	csk->wr_skb_head = NULL;
+	csk->wr_skb_tail = NULL;
+}
+
 static inline void enqueue_wr(struct chtls_sock *csk, struct sk_buff *skb)
 {
 	WR_SKB_CB(skb)->next_wr = NULL;
@@ -197,4 +200,19 @@
 		WR_SKB_CB(csk->wr_skb_tail)->next_wr = skb;
 	csk->wr_skb_tail = skb;
 }
+
+static inline struct sk_buff *dequeue_wr(struct sock *sk)
+{
+	struct chtls_sock *csk = rcu_dereference_sk_user_data(sk);
+	struct sk_buff *skb = NULL;
+
+	skb = csk->wr_skb_head;
+
+	if (likely(skb)) {
+	 /* Don't bother clearing the tail */
+		csk->wr_skb_head = WR_SKB_CB(skb)->next_wr;
+		WR_SKB_CB(skb)->next_wr = NULL;
+	}
+	return skb;
+}
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/chelsio/chtls/chtls_hw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/chelsio/chtls/chtls_hw.c
@@ -350,17 +350,22 @@
 	kwr->sc_imm.cmd_more = cpu_to_be32(ULPTX_CMD_V(ULP_TX_SC_IMM));
 	kwr->sc_imm.len = cpu_to_be32(klen);
 
+	lock_sock(sk);
 	/* key info */
 	kctx = (struct _key_ctx *)(kwr + 1);
 	ret = chtls_key_info(csk, kctx, keylen, optname);
 	if (ret)
 		goto out_notcb;
 
+	if (unlikely(csk_flag(sk, CSK_ABORT_SHUTDOWN)))
+		goto out_notcb;
+
 	set_wr_txq(skb, CPL_PRIORITY_DATA, csk->tlshws.txqid);
 	csk->wr_credits -= DIV_ROUND_UP(len, 16);
 	csk->wr_unacked += DIV_ROUND_UP(len, 16);
 	enqueue_wr(csk, skb);
 	cxgb4_ofld_send(csk->egress_dev, skb);
+	skb = NULL;
 
 	chtls_set_scmd(csk);
 	/* Clear quiesce for Rx key */
@@ -388,8 +393,10 @@
 		csk->tlshws.txkey = keyid;
 	}
 
+	release_sock(sk);
 	return ret;
 out_notcb:
+	release_sock(sk);
 	free_tls_keyid(sk);
 out_nokey:
 	kfree_skb(skb);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/chelsio/chtls/chtls_io.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/chelsio/chtls/chtls_io.c
@@ -682,7 +682,7 @@
 				make_tx_data_wr(sk, skb, immdlen, len,
 						credits_needed, completion);
 			tp->snd_nxt += len;
-			tp->lsndtime = tcp_time_stamp(tp);
+			tp->lsndtime = tcp_jiffies32;
 			if (completion)
 				ULP_SKB_CB(skb)->flags &= ~ULPCB_FLAG_NEED_HDR;
 		} else {
@@ -910,9 +910,9 @@
 	return (__force int)cpu_to_be16(thdr->length);
 }
 
-static int csk_mem_free(struct chtls_dev *cdev, struct sock *sk)
+static bool csk_mem_free(struct chtls_dev *cdev, struct sock *sk)
 {
-	return (cdev->max_host_sndbuf - sk->sk_wmem_queued);
+	return (cdev->max_host_sndbuf - sk->sk_wmem_queued > 0);
 }
 
 static int csk_wait_memory(struct chtls_dev *cdev,
@@ -1210,6 +1210,7 @@
 	copied = 0;
 	csk = rcu_dereference_sk_user_data(sk);
 	cdev = csk->cdev;
+	lock_sock(sk);
 	timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
 
 	err = sk_stream_wait_connect(sk, &timeo);
@@ -1437,7 +1438,7 @@
 				      csk->wr_max_credits))
 			sk->sk_write_space(sk);
 
-		if (copied >= target && !sk->sk_backlog.tail)
+		if (copied >= target && !READ_ONCE(sk->sk_backlog.tail))
 			break;
 
 		if (copied) {
@@ -1470,7 +1471,7 @@
 				break;
 			}
 		}
-		if (sk->sk_backlog.tail) {
+		if (READ_ONCE(sk->sk_backlog.tail)) {
 			release_sock(sk);
 			lock_sock(sk);
 			chtls_cleanup_rbuf(sk, copied);
@@ -1536,6 +1537,7 @@
 			tp->urg_data = 0;
 
 		if ((avail + offset) >= skb->len) {
+			struct sk_buff *next_skb;
 			if (ULP_SKB_CB(skb)->flags & ULPCB_FLAG_TLS_HDR) {
 				tp->copied_seq += skb->len;
 				hws->rcvpld = skb->hdr_len;
@@ -1545,8 +1547,10 @@
 			chtls_free_skb(sk, skb);
 			buffers_freed++;
 			hws->copied_seq = 0;
-			if (copied >= target &&
-			    !skb_peek(&sk->sk_receive_queue))
+			next_skb = skb_peek(&sk->sk_receive_queue);
+			if (copied >= target && !next_skb)
+				break;
+			if (ULP_SKB_CB(next_skb)->flags & ULPCB_FLAG_TLS_HDR)
 				break;
 		}
 	} while (len > 0);
@@ -1615,7 +1619,7 @@
 			break;
 		}
 
-		if (sk->sk_backlog.tail) {
+		if (READ_ONCE(sk->sk_backlog.tail)) {
 			/* Do not sleep, just process backlog. */
 			release_sock(sk);
 			lock_sock(sk);
@@ -1743,7 +1747,7 @@
 				      csk->wr_max_credits))
 			sk->sk_write_space(sk);
 
-		if (copied >= target && !sk->sk_backlog.tail)
+		if (copied >= target && !READ_ONCE(sk->sk_backlog.tail))
 			break;
 
 		if (copied) {
@@ -1774,7 +1778,7 @@
 			}
 		}
 
-		if (sk->sk_backlog.tail) {
+		if (READ_ONCE(sk->sk_backlog.tail)) {
 			release_sock(sk);
 			lock_sock(sk);
 			chtls_cleanup_rbuf(sk, copied);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/chelsio/chtls/chtls_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/chelsio/chtls/chtls_main.c
@@ -339,8 +339,9 @@
 	 * driver. Once driver synthesizes cpl_pass_accpet_req the skb will go
 	 * through the regular cpl_pass_accept_req processing in TOM.
 	 */
-	skb = alloc_skb(gl->tot_len + sizeof(struct cpl_pass_accept_req)
-			- pktshift, GFP_ATOMIC);
+	skb = alloc_skb(size_add(gl->tot_len,
+				 sizeof(struct cpl_pass_accept_req)) -
+			pktshift, GFP_ATOMIC);
 	if (unlikely(!skb))
 		return NULL;
 	__skb_put(skb, gl->tot_len + sizeof(struct cpl_pass_accept_req)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/geode-aes.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/geode-aes.c
@@ -10,6 +10,7 @@
 #include <linux/spinlock.h>
 #include <crypto/algapi.h>
 #include <crypto/aes.h>
+#include <crypto/internal/skcipher.h>
 
 #include <linux/io.h>
 #include <linux/delay.h>
@@ -23,12 +24,12 @@
 
 /* Write a 128 bit field (either a writable key or IV) */
 static inline void
-_writefield(u32 offset, void *value)
+_writefield(u32 offset, const void *value)
 {
 	int i;
 
 	for (i = 0; i < 4; i++)
-		iowrite32(((u32 *) value)[i], _iobase + offset + (i * 4));
+		iowrite32(((const u32 *) value)[i], _iobase + offset + (i * 4));
 }
 
 /* Read a 128 bit field (either a writable key or IV) */
@@ -42,12 +43,12 @@
 }
 
 static int
-do_crypt(void *src, void *dst, int len, u32 flags)
+do_crypt(const void *src, void *dst, u32 len, u32 flags)
 {
 	u32 status;
 	u32 counter = AES_OP_TIMEOUT;
 
-	iowrite32(virt_to_phys(src), _iobase + AES_SOURCEA_REG);
+	iowrite32(virt_to_phys((void *)src), _iobase + AES_SOURCEA_REG);
 	iowrite32(virt_to_phys(dst), _iobase + AES_DSTA_REG);
 	iowrite32(len,  _iobase + AES_LENA_REG);
 
@@ -64,16 +65,14 @@
 	return counter ? 0 : 1;
 }
 
-static unsigned int
-geode_aes_crypt(struct geode_aes_op *op)
+static void
+geode_aes_crypt(const struct geode_aes_tfm_ctx *tctx, const void *src,
+		void *dst, u32 len, u8 *iv, int mode, int dir)
 {
 	u32 flags = 0;
 	unsigned long iflags;
 	int ret;
 
-	if (op->len == 0)
-		return 0;
-
 	/* If the source and destination is the same, then
 	 * we need to turn on the coherent flags, otherwise
 	 * we don't need to worry
@@ -81,32 +80,28 @@
 
 	flags |= (AES_CTRL_DCA | AES_CTRL_SCA);
 
-	if (op->dir == AES_DIR_ENCRYPT)
+	if (dir == AES_DIR_ENCRYPT)
 		flags |= AES_CTRL_ENCRYPT;
 
 	/* Start the critical section */
 
 	spin_lock_irqsave(&lock, iflags);
 
-	if (op->mode == AES_MODE_CBC) {
+	if (mode == AES_MODE_CBC) {
 		flags |= AES_CTRL_CBC;
-		_writefield(AES_WRITEIV0_REG, op->iv);
+		_writefield(AES_WRITEIV0_REG, iv);
 	}
 
-	if (!(op->flags & AES_FLAGS_HIDDENKEY)) {
-		flags |= AES_CTRL_WRKEY;
-		_writefield(AES_WRITEKEY0_REG, op->key);
-	}
+	flags |= AES_CTRL_WRKEY;
+	_writefield(AES_WRITEKEY0_REG, tctx->key);
 
-	ret = do_crypt(op->src, op->dst, op->len, flags);
+	ret = do_crypt(src, dst, len, flags);
 	BUG_ON(ret);
 
-	if (op->mode == AES_MODE_CBC)
-		_readfield(AES_WRITEIV0_REG, op->iv);
+	if (mode == AES_MODE_CBC)
+		_readfield(AES_WRITEIV0_REG, iv);
 
 	spin_unlock_irqrestore(&lock, iflags);
-
-	return op->len;
 }
 
 /* CRYPTO-API Functions */
@@ -114,13 +109,13 @@
 static int geode_setkey_cip(struct crypto_tfm *tfm, const u8 *key,
 		unsigned int len)
 {
-	struct geode_aes_op *op = crypto_tfm_ctx(tfm);
+	struct geode_aes_tfm_ctx *tctx = crypto_tfm_ctx(tfm);
 	unsigned int ret;
 
-	op->keylen = len;
+	tctx->keylen = len;
 
 	if (len == AES_KEYSIZE_128) {
-		memcpy(op->key, key, len);
+		memcpy(tctx->key, key, len);
 		return 0;
 	}
 
@@ -133,135 +128,93 @@
 	/*
 	 * The requested key size is not supported by HW, do a fallback
 	 */
-	op->fallback.cip->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
-	op->fallback.cip->base.crt_flags |= (tfm->crt_flags & CRYPTO_TFM_REQ_MASK);
+	tctx->fallback.cip->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
+	tctx->fallback.cip->base.crt_flags |=
+		(tfm->crt_flags & CRYPTO_TFM_REQ_MASK);
 
-	ret = crypto_cipher_setkey(op->fallback.cip, key, len);
+	ret = crypto_cipher_setkey(tctx->fallback.cip, key, len);
 	if (ret) {
 		tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK;
-		tfm->crt_flags |= (op->fallback.cip->base.crt_flags & CRYPTO_TFM_RES_MASK);
+		tfm->crt_flags |= (tctx->fallback.cip->base.crt_flags &
+				   CRYPTO_TFM_RES_MASK);
 	}
 	return ret;
 }
 
-static int geode_setkey_blk(struct crypto_tfm *tfm, const u8 *key,
-		unsigned int len)
+static int geode_setkey_skcipher(struct crypto_skcipher *tfm, const u8 *key,
+				 unsigned int len)
 {
-	struct geode_aes_op *op = crypto_tfm_ctx(tfm);
+	struct geode_aes_tfm_ctx *tctx = crypto_skcipher_ctx(tfm);
 	unsigned int ret;
 
-	op->keylen = len;
+	tctx->keylen = len;
 
 	if (len == AES_KEYSIZE_128) {
-		memcpy(op->key, key, len);
+		memcpy(tctx->key, key, len);
 		return 0;
 	}
 
 	if (len != AES_KEYSIZE_192 && len != AES_KEYSIZE_256) {
 		/* not supported at all */
-		tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+		crypto_skcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
 		return -EINVAL;
 	}
 
 	/*
 	 * The requested key size is not supported by HW, do a fallback
 	 */
-	op->fallback.blk->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
-	op->fallback.blk->base.crt_flags |= (tfm->crt_flags & CRYPTO_TFM_REQ_MASK);
-
-	ret = crypto_blkcipher_setkey(op->fallback.blk, key, len);
-	if (ret) {
-		tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK;
-		tfm->crt_flags |= (op->fallback.blk->base.crt_flags & CRYPTO_TFM_RES_MASK);
-	}
-	return ret;
-}
-
-static int fallback_blk_dec(struct blkcipher_desc *desc,
-		struct scatterlist *dst, struct scatterlist *src,
-		unsigned int nbytes)
-{
-	unsigned int ret;
-	struct crypto_blkcipher *tfm;
-	struct geode_aes_op *op = crypto_blkcipher_ctx(desc->tfm);
-
-	tfm = desc->tfm;
-	desc->tfm = op->fallback.blk;
-
-	ret = crypto_blkcipher_decrypt_iv(desc, dst, src, nbytes);
-
-	desc->tfm = tfm;
-	return ret;
-}
-static int fallback_blk_enc(struct blkcipher_desc *desc,
-		struct scatterlist *dst, struct scatterlist *src,
-		unsigned int nbytes)
-{
-	unsigned int ret;
-	struct crypto_blkcipher *tfm;
-	struct geode_aes_op *op = crypto_blkcipher_ctx(desc->tfm);
-
-	tfm = desc->tfm;
-	desc->tfm = op->fallback.blk;
-
-	ret = crypto_blkcipher_encrypt_iv(desc, dst, src, nbytes);
-
-	desc->tfm = tfm;
+	crypto_skcipher_clear_flags(tctx->fallback.skcipher,
+				    CRYPTO_TFM_REQ_MASK);
+	crypto_skcipher_set_flags(tctx->fallback.skcipher,
+				  crypto_skcipher_get_flags(tfm) &
+				  CRYPTO_TFM_REQ_MASK);
+	ret = crypto_skcipher_setkey(tctx->fallback.skcipher, key, len);
+	crypto_skcipher_set_flags(tfm,
+				  crypto_skcipher_get_flags(tctx->fallback.skcipher) &
+				  CRYPTO_TFM_RES_MASK);
 	return ret;
 }
 
 static void
 geode_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
 {
-	struct geode_aes_op *op = crypto_tfm_ctx(tfm);
+	const struct geode_aes_tfm_ctx *tctx = crypto_tfm_ctx(tfm);
 
-	if (unlikely(op->keylen != AES_KEYSIZE_128)) {
-		crypto_cipher_encrypt_one(op->fallback.cip, out, in);
+	if (unlikely(tctx->keylen != AES_KEYSIZE_128)) {
+		crypto_cipher_encrypt_one(tctx->fallback.cip, out, in);
 		return;
 	}
 
-	op->src = (void *) in;
-	op->dst = (void *) out;
-	op->mode = AES_MODE_ECB;
-	op->flags = 0;
-	op->len = AES_BLOCK_SIZE;
-	op->dir = AES_DIR_ENCRYPT;
-
-	geode_aes_crypt(op);
+	geode_aes_crypt(tctx, in, out, AES_BLOCK_SIZE, NULL,
+			AES_MODE_ECB, AES_DIR_ENCRYPT);
 }
 
 
 static void
 geode_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
 {
-	struct geode_aes_op *op = crypto_tfm_ctx(tfm);
+	const struct geode_aes_tfm_ctx *tctx = crypto_tfm_ctx(tfm);
 
-	if (unlikely(op->keylen != AES_KEYSIZE_128)) {
-		crypto_cipher_decrypt_one(op->fallback.cip, out, in);
+	if (unlikely(tctx->keylen != AES_KEYSIZE_128)) {
+		crypto_cipher_decrypt_one(tctx->fallback.cip, out, in);
 		return;
 	}
 
-	op->src = (void *) in;
-	op->dst = (void *) out;
-	op->mode = AES_MODE_ECB;
-	op->flags = 0;
-	op->len = AES_BLOCK_SIZE;
-	op->dir = AES_DIR_DECRYPT;
-
-	geode_aes_crypt(op);
+	geode_aes_crypt(tctx, in, out, AES_BLOCK_SIZE, NULL,
+			AES_MODE_ECB, AES_DIR_DECRYPT);
 }
 
 static int fallback_init_cip(struct crypto_tfm *tfm)
 {
 	const char *name = crypto_tfm_alg_name(tfm);
-	struct geode_aes_op *op = crypto_tfm_ctx(tfm);
+	struct geode_aes_tfm_ctx *tctx = crypto_tfm_ctx(tfm);
 
-	op->fallback.cip = crypto_alloc_cipher(name, 0,
-					       CRYPTO_ALG_NEED_FALLBACK);
+	tctx->fallback.cip = crypto_alloc_cipher(name, 0,
+						 CRYPTO_ALG_NEED_FALLBACK);
 
-	if (IS_ERR(op->fallback.cip)) {
+	if (IS_ERR(tctx->fallback.cip)) {
 		printk(KERN_ERR "Error allocating fallback algo %s\n", name);
-		return PTR_ERR(op->fallback.cip);
+		return PTR_ERR(tctx->fallback.cip);
 	}
 
 	return 0;
@@ -269,10 +222,9 @@
 
 static void fallback_exit_cip(struct crypto_tfm *tfm)
 {
-	struct geode_aes_op *op = crypto_tfm_ctx(tfm);
+	struct geode_aes_tfm_ctx *tctx = crypto_tfm_ctx(tfm);
 
-	crypto_free_cipher(op->fallback.cip);
-	op->fallback.cip = NULL;
+	crypto_free_cipher(tctx->fallback.cip);
 }
 
 static struct crypto_alg geode_alg = {
@@ -285,7 +237,7 @@
 	.cra_init			=	fallback_init_cip,
 	.cra_exit			=	fallback_exit_cip,
 	.cra_blocksize		=	AES_BLOCK_SIZE,
-	.cra_ctxsize		=	sizeof(struct geode_aes_op),
+	.cra_ctxsize		=	sizeof(struct geode_aes_tfm_ctx),
 	.cra_module			=	THIS_MODULE,
 	.cra_u				=	{
 		.cipher	=	{
@@ -298,209 +250,126 @@
 	}
 };
 
-static int
-geode_cbc_decrypt(struct blkcipher_desc *desc,
-		  struct scatterlist *dst, struct scatterlist *src,
-		  unsigned int nbytes)
-{
-	struct geode_aes_op *op = crypto_blkcipher_ctx(desc->tfm);
-	struct blkcipher_walk walk;
-	int err, ret;
-
-	if (unlikely(op->keylen != AES_KEYSIZE_128))
-		return fallback_blk_dec(desc, dst, src, nbytes);
-
-	blkcipher_walk_init(&walk, dst, src, nbytes);
-	err = blkcipher_walk_virt(desc, &walk);
-	op->iv = walk.iv;
-
-	while ((nbytes = walk.nbytes)) {
-		op->src = walk.src.virt.addr,
-		op->dst = walk.dst.virt.addr;
-		op->mode = AES_MODE_CBC;
-		op->len = nbytes - (nbytes % AES_BLOCK_SIZE);
-		op->dir = AES_DIR_DECRYPT;
-
-		ret = geode_aes_crypt(op);
-
-		nbytes -= ret;
-		err = blkcipher_walk_done(desc, &walk, nbytes);
-	}
-
-	return err;
-}
-
-static int
-geode_cbc_encrypt(struct blkcipher_desc *desc,
-		  struct scatterlist *dst, struct scatterlist *src,
-		  unsigned int nbytes)
-{
-	struct geode_aes_op *op = crypto_blkcipher_ctx(desc->tfm);
-	struct blkcipher_walk walk;
-	int err, ret;
-
-	if (unlikely(op->keylen != AES_KEYSIZE_128))
-		return fallback_blk_enc(desc, dst, src, nbytes);
-
-	blkcipher_walk_init(&walk, dst, src, nbytes);
-	err = blkcipher_walk_virt(desc, &walk);
-	op->iv = walk.iv;
-
-	while ((nbytes = walk.nbytes)) {
-		op->src = walk.src.virt.addr,
-		op->dst = walk.dst.virt.addr;
-		op->mode = AES_MODE_CBC;
-		op->len = nbytes - (nbytes % AES_BLOCK_SIZE);
-		op->dir = AES_DIR_ENCRYPT;
-
-		ret = geode_aes_crypt(op);
-		nbytes -= ret;
-		err = blkcipher_walk_done(desc, &walk, nbytes);
-	}
-
-	return err;
-}
-
-static int fallback_init_blk(struct crypto_tfm *tfm)
+static int geode_init_skcipher(struct crypto_skcipher *tfm)
 {
-	const char *name = crypto_tfm_alg_name(tfm);
-	struct geode_aes_op *op = crypto_tfm_ctx(tfm);
-
-	op->fallback.blk = crypto_alloc_blkcipher(name, 0,
-			CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK);
+	const char *name = crypto_tfm_alg_name(&tfm->base);
+	struct geode_aes_tfm_ctx *tctx = crypto_skcipher_ctx(tfm);
 
-	if (IS_ERR(op->fallback.blk)) {
+	tctx->fallback.skcipher =
+		crypto_alloc_skcipher(name, 0, CRYPTO_ALG_NEED_FALLBACK |
+				      CRYPTO_ALG_ASYNC);
+	if (IS_ERR(tctx->fallback.skcipher)) {
 		printk(KERN_ERR "Error allocating fallback algo %s\n", name);
-		return PTR_ERR(op->fallback.blk);
+		return PTR_ERR(tctx->fallback.skcipher);
 	}
 
+	crypto_skcipher_set_reqsize(tfm, sizeof(struct skcipher_request) +
+				    crypto_skcipher_reqsize(tctx->fallback.skcipher));
 	return 0;
 }
 
-static void fallback_exit_blk(struct crypto_tfm *tfm)
+static void geode_exit_skcipher(struct crypto_skcipher *tfm)
 {
-	struct geode_aes_op *op = crypto_tfm_ctx(tfm);
+	struct geode_aes_tfm_ctx *tctx = crypto_skcipher_ctx(tfm);
 
-	crypto_free_blkcipher(op->fallback.blk);
-	op->fallback.blk = NULL;
+	crypto_free_skcipher(tctx->fallback.skcipher);
 }
 
-static struct crypto_alg geode_cbc_alg = {
-	.cra_name		=	"cbc(aes)",
-	.cra_driver_name	=	"cbc-aes-geode",
-	.cra_priority		=	400,
-	.cra_flags			=	CRYPTO_ALG_TYPE_BLKCIPHER |
-						CRYPTO_ALG_KERN_DRIVER_ONLY |
-						CRYPTO_ALG_NEED_FALLBACK,
-	.cra_init			=	fallback_init_blk,
-	.cra_exit			=	fallback_exit_blk,
-	.cra_blocksize		=	AES_BLOCK_SIZE,
-	.cra_ctxsize		=	sizeof(struct geode_aes_op),
-	.cra_alignmask		=	15,
-	.cra_type			=	&crypto_blkcipher_type,
-	.cra_module			=	THIS_MODULE,
-	.cra_u				=	{
-		.blkcipher	=	{
-			.min_keysize	=	AES_MIN_KEY_SIZE,
-			.max_keysize	=	AES_MAX_KEY_SIZE,
-			.setkey			=	geode_setkey_blk,
-			.encrypt		=	geode_cbc_encrypt,
-			.decrypt		=	geode_cbc_decrypt,
-			.ivsize			=	AES_BLOCK_SIZE,
-		}
+static int geode_skcipher_crypt(struct skcipher_request *req, int mode, int dir)
+{
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
+	const struct geode_aes_tfm_ctx *tctx = crypto_skcipher_ctx(tfm);
+	struct skcipher_walk walk;
+	unsigned int nbytes;
+	int err;
+
+	if (unlikely(tctx->keylen != AES_KEYSIZE_128)) {
+		struct skcipher_request *subreq = skcipher_request_ctx(req);
+
+		*subreq = *req;
+		skcipher_request_set_tfm(subreq, tctx->fallback.skcipher);
+		if (dir == AES_DIR_DECRYPT)
+			return crypto_skcipher_decrypt(subreq);
+		else
+			return crypto_skcipher_encrypt(subreq);
 	}
-};
 
-static int
-geode_ecb_decrypt(struct blkcipher_desc *desc,
-		  struct scatterlist *dst, struct scatterlist *src,
-		  unsigned int nbytes)
-{
-	struct geode_aes_op *op = crypto_blkcipher_ctx(desc->tfm);
-	struct blkcipher_walk walk;
-	int err, ret;
-
-	if (unlikely(op->keylen != AES_KEYSIZE_128))
-		return fallback_blk_dec(desc, dst, src, nbytes);
-
-	blkcipher_walk_init(&walk, dst, src, nbytes);
-	err = blkcipher_walk_virt(desc, &walk);
-
-	while ((nbytes = walk.nbytes)) {
-		op->src = walk.src.virt.addr,
-		op->dst = walk.dst.virt.addr;
-		op->mode = AES_MODE_ECB;
-		op->len = nbytes - (nbytes % AES_BLOCK_SIZE);
-		op->dir = AES_DIR_DECRYPT;
-
-		ret = geode_aes_crypt(op);
-		nbytes -= ret;
-		err = blkcipher_walk_done(desc, &walk, nbytes);
+	err = skcipher_walk_virt(&walk, req, false);
+
+	while ((nbytes = walk.nbytes) != 0) {
+		geode_aes_crypt(tctx, walk.src.virt.addr, walk.dst.virt.addr,
+				round_down(nbytes, AES_BLOCK_SIZE),
+				walk.iv, mode, dir);
+		err = skcipher_walk_done(&walk, nbytes % AES_BLOCK_SIZE);
 	}
 
 	return err;
 }
 
-static int
-geode_ecb_encrypt(struct blkcipher_desc *desc,
-		  struct scatterlist *dst, struct scatterlist *src,
-		  unsigned int nbytes)
-{
-	struct geode_aes_op *op = crypto_blkcipher_ctx(desc->tfm);
-	struct blkcipher_walk walk;
-	int err, ret;
-
-	if (unlikely(op->keylen != AES_KEYSIZE_128))
-		return fallback_blk_enc(desc, dst, src, nbytes);
-
-	blkcipher_walk_init(&walk, dst, src, nbytes);
-	err = blkcipher_walk_virt(desc, &walk);
-
-	while ((nbytes = walk.nbytes)) {
-		op->src = walk.src.virt.addr,
-		op->dst = walk.dst.virt.addr;
-		op->mode = AES_MODE_ECB;
-		op->len = nbytes - (nbytes % AES_BLOCK_SIZE);
-		op->dir = AES_DIR_ENCRYPT;
-
-		ret = geode_aes_crypt(op);
-		nbytes -= ret;
-		ret =  blkcipher_walk_done(desc, &walk, nbytes);
-	}
+static int geode_cbc_encrypt(struct skcipher_request *req)
+{
+	return geode_skcipher_crypt(req, AES_MODE_CBC, AES_DIR_ENCRYPT);
+}
 
-	return err;
+static int geode_cbc_decrypt(struct skcipher_request *req)
+{
+	return geode_skcipher_crypt(req, AES_MODE_CBC, AES_DIR_DECRYPT);
 }
 
-static struct crypto_alg geode_ecb_alg = {
-	.cra_name			=	"ecb(aes)",
-	.cra_driver_name	=	"ecb-aes-geode",
-	.cra_priority		=	400,
-	.cra_flags			=	CRYPTO_ALG_TYPE_BLKCIPHER |
-						CRYPTO_ALG_KERN_DRIVER_ONLY |
-						CRYPTO_ALG_NEED_FALLBACK,
-	.cra_init			=	fallback_init_blk,
-	.cra_exit			=	fallback_exit_blk,
-	.cra_blocksize		=	AES_BLOCK_SIZE,
-	.cra_ctxsize		=	sizeof(struct geode_aes_op),
-	.cra_alignmask		=	15,
-	.cra_type			=	&crypto_blkcipher_type,
-	.cra_module			=	THIS_MODULE,
-	.cra_u				=	{
-		.blkcipher	=	{
-			.min_keysize	=	AES_MIN_KEY_SIZE,
-			.max_keysize	=	AES_MAX_KEY_SIZE,
-			.setkey			=	geode_setkey_blk,
-			.encrypt		=	geode_ecb_encrypt,
-			.decrypt		=	geode_ecb_decrypt,
-		}
-	}
+static int geode_ecb_encrypt(struct skcipher_request *req)
+{
+	return geode_skcipher_crypt(req, AES_MODE_ECB, AES_DIR_ENCRYPT);
+}
+
+static int geode_ecb_decrypt(struct skcipher_request *req)
+{
+	return geode_skcipher_crypt(req, AES_MODE_ECB, AES_DIR_DECRYPT);
+}
+
+static struct skcipher_alg geode_skcipher_algs[] = {
+	{
+		.base.cra_name		= "cbc(aes)",
+		.base.cra_driver_name	= "cbc-aes-geode",
+		.base.cra_priority	= 400,
+		.base.cra_flags		= CRYPTO_ALG_KERN_DRIVER_ONLY |
+					  CRYPTO_ALG_NEED_FALLBACK,
+		.base.cra_blocksize	= AES_BLOCK_SIZE,
+		.base.cra_ctxsize	= sizeof(struct geode_aes_tfm_ctx),
+		.base.cra_alignmask	= 15,
+		.base.cra_module	= THIS_MODULE,
+		.init			= geode_init_skcipher,
+		.exit			= geode_exit_skcipher,
+		.setkey			= geode_setkey_skcipher,
+		.encrypt		= geode_cbc_encrypt,
+		.decrypt		= geode_cbc_decrypt,
+		.min_keysize		= AES_MIN_KEY_SIZE,
+		.max_keysize		= AES_MAX_KEY_SIZE,
+		.ivsize			= AES_BLOCK_SIZE,
+	}, {
+		.base.cra_name		= "ecb(aes)",
+		.base.cra_driver_name	= "ecb-aes-geode",
+		.base.cra_priority	= 400,
+		.base.cra_flags		= CRYPTO_ALG_KERN_DRIVER_ONLY |
+					  CRYPTO_ALG_NEED_FALLBACK,
+		.base.cra_blocksize	= AES_BLOCK_SIZE,
+		.base.cra_ctxsize	= sizeof(struct geode_aes_tfm_ctx),
+		.base.cra_alignmask	= 15,
+		.base.cra_module	= THIS_MODULE,
+		.init			= geode_init_skcipher,
+		.exit			= geode_exit_skcipher,
+		.setkey			= geode_setkey_skcipher,
+		.encrypt		= geode_ecb_encrypt,
+		.decrypt		= geode_ecb_decrypt,
+		.min_keysize		= AES_MIN_KEY_SIZE,
+		.max_keysize		= AES_MAX_KEY_SIZE,
+	},
 };
 
 static void geode_aes_remove(struct pci_dev *dev)
 {
 	crypto_unregister_alg(&geode_alg);
-	crypto_unregister_alg(&geode_ecb_alg);
-	crypto_unregister_alg(&geode_cbc_alg);
+	crypto_unregister_skciphers(geode_skcipher_algs,
+				    ARRAY_SIZE(geode_skcipher_algs));
 
 	pci_iounmap(dev, _iobase);
 	_iobase = NULL;
@@ -538,20 +407,14 @@
 	if (ret)
 		goto eiomap;
 
-	ret = crypto_register_alg(&geode_ecb_alg);
+	ret = crypto_register_skciphers(geode_skcipher_algs,
+					ARRAY_SIZE(geode_skcipher_algs));
 	if (ret)
 		goto ealg;
 
-	ret = crypto_register_alg(&geode_cbc_alg);
-	if (ret)
-		goto eecb;
-
 	dev_notice(&dev->dev, "GEODE AES engine enabled.\n");
 	return 0;
 
- eecb:
-	crypto_unregister_alg(&geode_ecb_alg);
-
  ealg:
 	crypto_unregister_alg(&geode_alg);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/geode-aes.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/geode-aes.h
@@ -46,21 +46,10 @@
 
 #define AES_OP_TIMEOUT    0x50000
 
-struct geode_aes_op {
-
-	void *src;
-	void *dst;
-
-	u32 mode;
-	u32 dir;
-	u32 flags;
-	int len;
-
+struct geode_aes_tfm_ctx {
 	u8 key[AES_KEYSIZE_128];
-	u8 *iv;
-
 	union {
-		struct crypto_blkcipher *blk;
+		struct crypto_skcipher *skcipher;
 		struct crypto_cipher *cip;
 	} fallback;
 	u32 keylen;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/hisilicon/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/hisilicon/Kconfig
@@ -14,26 +14,53 @@
 	  To compile this as a module, choose M here: the module
 	  will be called hisi_sec.
 
+config CRYPTO_DEV_HISI_SEC2
+	tristate "Support for HiSilicon SEC2 crypto block cipher accelerator"
+	select CRYPTO_BLKCIPHER
+	select CRYPTO_ALGAPI
+	select CRYPTO_LIB_DES
+	select CRYPTO_DEV_HISI_QM
+	select CRYPTO_AEAD
+	select CRYPTO_AUTHENC
+	select CRYPTO_HMAC
+	select CRYPTO_SHA1
+	select CRYPTO_SHA256
+	select CRYPTO_SHA512
+	depends on PCI && PCI_MSI
+	depends on ARM64 || (COMPILE_TEST && 64BIT)
+	help
+	  Support for HiSilicon SEC Engine of version 2 in crypto subsystem.
+	  It provides AES, SM4, and 3DES algorithms with ECB
+	  CBC, and XTS cipher mode, and AEAD algorithms.
+
+	  To compile this as a module, choose M here: the module
+          will be called hisi_sec2.
+
 config CRYPTO_DEV_HISI_QM
 	tristate
-	depends on ARM64 && PCI && PCI_MSI
+	depends on ARM64 || COMPILE_TEST
+	depends on PCI && PCI_MSI
+	select NEED_SG_DMA_LENGTH
 	help
 	  HiSilicon accelerator engines use a common queue management
 	  interface. Specific engine driver may use this module.
 
-config CRYPTO_HISI_SGL
-	tristate
-	depends on ARM64
-	help
-	  HiSilicon accelerator engines use a common hardware scatterlist
-	  interface for data format. Specific engine driver may use this
-	  module.
-
 config CRYPTO_DEV_HISI_ZIP
 	tristate "Support for HiSilicon ZIP accelerator"
-	depends on ARM64 && PCI && PCI_MSI
+	depends on PCI && PCI_MSI
+	depends on ARM64 || (COMPILE_TEST && 64BIT)
+	depends on !CPU_BIG_ENDIAN || COMPILE_TEST
 	select CRYPTO_DEV_HISI_QM
-	select CRYPTO_HISI_SGL
-	select SG_SPLIT
 	help
 	  Support for HiSilicon ZIP Driver
+
+config CRYPTO_DEV_HISI_HPRE
+	tristate "Support for HISI HPRE accelerator"
+	depends on PCI && PCI_MSI
+	depends on ARM64 || (COMPILE_TEST && 64BIT)
+	select CRYPTO_DEV_HISI_QM
+	select CRYPTO_DH
+	select CRYPTO_RSA
+	help
+	  Support for HiSilicon HPRE(High Performance RSA Engine)
+	  accelerator, which can accelerate RSA and DH algorithms.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/hisilicon/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/hisilicon/Makefile
@@ -1,5 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_CRYPTO_DEV_HISI_HPRE) += hpre/
 obj-$(CONFIG_CRYPTO_DEV_HISI_SEC) += sec/
-obj-$(CONFIG_CRYPTO_DEV_HISI_QM) += qm.o
-obj-$(CONFIG_CRYPTO_HISI_SGL) += sgl.o
+obj-$(CONFIG_CRYPTO_DEV_HISI_SEC2) += sec2/
+obj-$(CONFIG_CRYPTO_DEV_HISI_QM) += hisi_qm.o
+hisi_qm-objs = qm.o sgl.o
 obj-$(CONFIG_CRYPTO_DEV_HISI_ZIP) += zip/
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/hisilicon/hpre/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/hisilicon/hpre/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_CRYPTO_DEV_HISI_HPRE) += hisi_hpre.o
+hisi_hpre-objs = hpre_main.o hpre_crypto.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/hisilicon/hpre/hpre.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/hisilicon/hpre/hpre.h
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2019 HiSilicon Limited. */
+#ifndef __HISI_HPRE_H
+#define __HISI_HPRE_H
+
+#include <linux/list.h>
+#include "../qm.h"
+
+#define HPRE_SQE_SIZE			sizeof(struct hpre_sqe)
+#define HPRE_PF_DEF_Q_NUM		64
+#define HPRE_PF_DEF_Q_BASE		0
+
+enum {
+	HPRE_CLUSTER0,
+	HPRE_CLUSTER1,
+	HPRE_CLUSTER2,
+	HPRE_CLUSTER3,
+	HPRE_CLUSTERS_NUM,
+};
+
+enum hpre_ctrl_dbgfs_file {
+	HPRE_CURRENT_QM,
+	HPRE_CLEAR_ENABLE,
+	HPRE_CLUSTER_CTRL,
+	HPRE_DEBUG_FILE_NUM,
+};
+
+#define HPRE_DEBUGFS_FILE_NUM    (HPRE_DEBUG_FILE_NUM + HPRE_CLUSTERS_NUM - 1)
+
+struct hpre_debugfs_file {
+	int index;
+	enum hpre_ctrl_dbgfs_file type;
+	spinlock_t lock;
+	struct hpre_debug *debug;
+};
+
+/*
+ * One HPRE controller has one PF and multiple VFs, some global configurations
+ * which PF has need this structure.
+ * Just relevant for PF.
+ */
+struct hpre_debug {
+	struct dentry *debug_root;
+	struct hpre_debugfs_file files[HPRE_DEBUGFS_FILE_NUM];
+};
+
+struct hpre {
+	struct hisi_qm qm;
+	struct list_head list;
+	struct hpre_debug debug;
+	u32 num_vfs;
+	unsigned long status;
+};
+
+enum hpre_alg_type {
+	HPRE_ALG_NC_NCRT = 0x0,
+	HPRE_ALG_NC_CRT = 0x1,
+	HPRE_ALG_KG_STD = 0x2,
+	HPRE_ALG_KG_CRT = 0x3,
+	HPRE_ALG_DH_G2 = 0x4,
+	HPRE_ALG_DH = 0x5,
+};
+
+struct hpre_sqe {
+	__le32 dw0;
+	__u8 task_len1;
+	__u8 task_len2;
+	__u8 mrttest_num;
+	__u8 resv1;
+	__le64 key;
+	__le64 in;
+	__le64 out;
+	__le16 tag;
+	__le16 resv2;
+#define _HPRE_SQE_ALIGN_EXT	7
+	__le32 rsvd1[_HPRE_SQE_ALIGN_EXT];
+};
+
+struct hpre *hpre_find_device(int node);
+int hpre_algs_register(void);
+void hpre_algs_unregister(void);
+
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/hisilicon/hpre/hpre_crypto.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/hisilicon/hpre/hpre_crypto.c
@@ -0,0 +1,1134 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2019 HiSilicon Limited. */
+#include <crypto/akcipher.h>
+#include <crypto/dh.h>
+#include <crypto/internal/akcipher.h>
+#include <crypto/internal/kpp.h>
+#include <crypto/internal/rsa.h>
+#include <crypto/kpp.h>
+#include <crypto/scatterwalk.h>
+#include <linux/dma-mapping.h>
+#include <linux/fips.h>
+#include <linux/module.h>
+#include "hpre.h"
+
+struct hpre_ctx;
+
+#define HPRE_CRYPTO_ALG_PRI	1000
+#define HPRE_ALIGN_SZ		64
+#define HPRE_BITS_2_BYTES_SHIFT	3
+#define HPRE_RSA_512BITS_KSZ	64
+#define HPRE_RSA_1536BITS_KSZ	192
+#define HPRE_CRT_PRMS		5
+#define HPRE_CRT_Q		2
+#define HPRE_CRT_P		3
+#define HPRE_CRT_INV		4
+#define HPRE_DH_G_FLAG		0x02
+#define HPRE_TRY_SEND_TIMES	100
+#define HPRE_INVLD_REQ_ID		(-1)
+#define HPRE_DEV(ctx)		(&((ctx)->qp->qm->pdev->dev))
+
+#define HPRE_SQE_ALG_BITS	5
+#define HPRE_SQE_DONE_SHIFT	30
+#define HPRE_DH_MAX_P_SZ	512
+
+typedef void (*hpre_cb)(struct hpre_ctx *ctx, void *sqe);
+
+struct hpre_rsa_ctx {
+	/* low address: e--->n */
+	char *pubkey;
+	dma_addr_t dma_pubkey;
+
+	/* low address: d--->n */
+	char *prikey;
+	dma_addr_t dma_prikey;
+
+	/* low address: dq->dp->q->p->qinv */
+	char *crt_prikey;
+	dma_addr_t dma_crt_prikey;
+
+	struct crypto_akcipher *soft_tfm;
+};
+
+struct hpre_dh_ctx {
+	/*
+	 * If base is g we compute the public key
+	 *	ya = g^xa mod p; [RFC2631 sec 2.1.1]
+	 * else if base if the counterpart public key we
+	 * compute the shared secret
+	 *	ZZ = yb^xa mod p; [RFC2631 sec 2.1.1]
+	 */
+	char *xa_p; /* low address: d--->n, please refer to Hisilicon HPRE UM */
+	dma_addr_t dma_xa_p;
+
+	char *g; /* m */
+	dma_addr_t dma_g;
+};
+
+struct hpre_ctx {
+	struct hisi_qp *qp;
+	struct hpre_asym_request **req_list;
+	spinlock_t req_lock;
+	unsigned int key_sz;
+	bool crt_g2_mode;
+	struct idr req_idr;
+	union {
+		struct hpre_rsa_ctx rsa;
+		struct hpre_dh_ctx dh;
+	};
+};
+
+struct hpre_asym_request {
+	char *src;
+	char *dst;
+	struct hpre_sqe req;
+	struct hpre_ctx *ctx;
+	union {
+		struct akcipher_request *rsa;
+		struct kpp_request *dh;
+	} areq;
+	int err;
+	int req_id;
+	hpre_cb cb;
+};
+
+static DEFINE_MUTEX(hpre_alg_lock);
+static unsigned int hpre_active_devs;
+
+static int hpre_alloc_req_id(struct hpre_ctx *ctx)
+{
+	unsigned long flags;
+	int id;
+
+	spin_lock_irqsave(&ctx->req_lock, flags);
+	id = idr_alloc(&ctx->req_idr, NULL, 0, QM_Q_DEPTH, GFP_ATOMIC);
+	spin_unlock_irqrestore(&ctx->req_lock, flags);
+
+	return id;
+}
+
+static void hpre_free_req_id(struct hpre_ctx *ctx, int req_id)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ctx->req_lock, flags);
+	idr_remove(&ctx->req_idr, req_id);
+	spin_unlock_irqrestore(&ctx->req_lock, flags);
+}
+
+static int hpre_add_req_to_ctx(struct hpre_asym_request *hpre_req)
+{
+	struct hpre_ctx *ctx;
+	int id;
+
+	ctx = hpre_req->ctx;
+	id = hpre_alloc_req_id(ctx);
+	if (unlikely(id < 0))
+		return -EINVAL;
+
+	ctx->req_list[id] = hpre_req;
+	hpre_req->req_id = id;
+
+	return id;
+}
+
+static void hpre_rm_req_from_ctx(struct hpre_asym_request *hpre_req)
+{
+	struct hpre_ctx *ctx = hpre_req->ctx;
+	int id = hpre_req->req_id;
+
+	if (hpre_req->req_id >= 0) {
+		hpre_req->req_id = HPRE_INVLD_REQ_ID;
+		ctx->req_list[id] = NULL;
+		hpre_free_req_id(ctx, id);
+	}
+}
+
+static struct hisi_qp *hpre_get_qp_and_start(void)
+{
+	struct hisi_qp *qp;
+	struct hpre *hpre;
+	int ret;
+
+	/* find the proper hpre device, which is near the current CPU core */
+	hpre = hpre_find_device(cpu_to_node(smp_processor_id()));
+	if (!hpre) {
+		pr_err("Can not find proper hpre device!\n");
+		return ERR_PTR(-ENODEV);
+	}
+
+	qp = hisi_qm_create_qp(&hpre->qm, 0);
+	if (IS_ERR(qp)) {
+		pci_err(hpre->qm.pdev, "Can not create qp!\n");
+		return ERR_PTR(-ENODEV);
+	}
+
+	ret = hisi_qm_start_qp(qp, 0);
+	if (ret < 0) {
+		hisi_qm_release_qp(qp);
+		pci_err(hpre->qm.pdev, "Can not start qp!\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	return qp;
+}
+
+static int hpre_get_data_dma_addr(struct hpre_asym_request *hpre_req,
+				  struct scatterlist *data, unsigned int len,
+				  int is_src, dma_addr_t *tmp)
+{
+	struct hpre_ctx *ctx = hpre_req->ctx;
+	struct device *dev = HPRE_DEV(ctx);
+	enum dma_data_direction dma_dir;
+
+	if (is_src) {
+		hpre_req->src = NULL;
+		dma_dir = DMA_TO_DEVICE;
+	} else {
+		hpre_req->dst = NULL;
+		dma_dir = DMA_FROM_DEVICE;
+	}
+	*tmp = dma_map_single(dev, sg_virt(data),
+			      len, dma_dir);
+	if (unlikely(dma_mapping_error(dev, *tmp))) {
+		dev_err(dev, "dma map data err!\n");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static int hpre_prepare_dma_buf(struct hpre_asym_request *hpre_req,
+				struct scatterlist *data, unsigned int len,
+				int is_src, dma_addr_t *tmp)
+{
+	struct hpre_ctx *ctx = hpre_req->ctx;
+	struct device *dev = HPRE_DEV(ctx);
+	void *ptr;
+	int shift;
+
+	shift = ctx->key_sz - len;
+	if (unlikely(shift < 0))
+		return -EINVAL;
+
+	ptr = dma_alloc_coherent(dev, ctx->key_sz, tmp, GFP_KERNEL);
+	if (unlikely(!ptr))
+		return -ENOMEM;
+
+	if (is_src) {
+		scatterwalk_map_and_copy(ptr + shift, data, 0, len, 0);
+		hpre_req->src = ptr;
+	} else {
+		hpre_req->dst = ptr;
+	}
+
+	return 0;
+}
+
+static int hpre_hw_data_init(struct hpre_asym_request *hpre_req,
+			     struct scatterlist *data, unsigned int len,
+			     int is_src, int is_dh)
+{
+	struct hpre_sqe *msg = &hpre_req->req;
+	struct hpre_ctx *ctx = hpre_req->ctx;
+	dma_addr_t tmp = 0;
+	int ret;
+
+	/* when the data is dh's source, we should format it */
+	if ((sg_is_last(data) && len == ctx->key_sz) &&
+	    ((is_dh && !is_src) || !is_dh))
+		ret = hpre_get_data_dma_addr(hpre_req, data, len, is_src, &tmp);
+	else
+		ret = hpre_prepare_dma_buf(hpre_req, data, len,
+					  is_src, &tmp);
+	if (unlikely(ret))
+		return ret;
+
+	if (is_src)
+		msg->in = cpu_to_le64(tmp);
+	else
+		msg->out = cpu_to_le64(tmp);
+
+	return 0;
+}
+
+static void hpre_hw_data_clr_all(struct hpre_ctx *ctx,
+				 struct hpre_asym_request *req,
+				 struct scatterlist *dst,
+				 struct scatterlist *src)
+{
+	struct device *dev = HPRE_DEV(ctx);
+	struct hpre_sqe *sqe = &req->req;
+	dma_addr_t tmp;
+
+	tmp = le64_to_cpu(sqe->in);
+	if (unlikely(!tmp))
+		return;
+
+	if (src) {
+		if (req->src)
+			dma_free_coherent(dev, ctx->key_sz,
+					  req->src, tmp);
+		else
+			dma_unmap_single(dev, tmp,
+					 ctx->key_sz, DMA_TO_DEVICE);
+	}
+
+	tmp = le64_to_cpu(sqe->out);
+	if (unlikely(!tmp))
+		return;
+
+	if (req->dst) {
+		if (dst)
+			scatterwalk_map_and_copy(req->dst, dst, 0,
+						 ctx->key_sz, 1);
+		dma_free_coherent(dev, ctx->key_sz, req->dst, tmp);
+	} else {
+		dma_unmap_single(dev, tmp, ctx->key_sz, DMA_FROM_DEVICE);
+	}
+}
+
+static int hpre_alg_res_post_hf(struct hpre_ctx *ctx, struct hpre_sqe *sqe,
+				void **kreq)
+{
+	struct hpre_asym_request *req;
+	int err, id, done;
+
+#define HPRE_NO_HW_ERR		0
+#define HPRE_HW_TASK_DONE	3
+#define HREE_HW_ERR_MASK	0x7ff
+#define HREE_SQE_DONE_MASK	0x3
+	id = (int)le16_to_cpu(sqe->tag);
+	req = ctx->req_list[id];
+	hpre_rm_req_from_ctx(req);
+	*kreq = req;
+
+	err = (le32_to_cpu(sqe->dw0) >> HPRE_SQE_ALG_BITS) &
+		HREE_HW_ERR_MASK;
+
+	done = (le32_to_cpu(sqe->dw0) >> HPRE_SQE_DONE_SHIFT) &
+		HREE_SQE_DONE_MASK;
+
+	if (likely(err == HPRE_NO_HW_ERR && done == HPRE_HW_TASK_DONE))
+		return  0;
+
+	return -EINVAL;
+}
+
+static int hpre_ctx_set(struct hpre_ctx *ctx, struct hisi_qp *qp, int qlen)
+{
+	if (!ctx || !qp || qlen < 0)
+		return -EINVAL;
+
+	spin_lock_init(&ctx->req_lock);
+	ctx->qp = qp;
+
+	ctx->req_list = kcalloc(qlen, sizeof(void *), GFP_KERNEL);
+	if (!ctx->req_list)
+		return -ENOMEM;
+	ctx->key_sz = 0;
+	ctx->crt_g2_mode = false;
+	idr_init(&ctx->req_idr);
+
+	return 0;
+}
+
+static void hpre_ctx_clear(struct hpre_ctx *ctx, bool is_clear_all)
+{
+	if (is_clear_all) {
+		idr_destroy(&ctx->req_idr);
+		kfree(ctx->req_list);
+		hisi_qm_release_qp(ctx->qp);
+	}
+
+	ctx->crt_g2_mode = false;
+	ctx->key_sz = 0;
+}
+
+static void hpre_dh_cb(struct hpre_ctx *ctx, void *resp)
+{
+	struct hpre_asym_request *req;
+	struct kpp_request *areq;
+	int ret;
+
+	ret = hpre_alg_res_post_hf(ctx, resp, (void **)&req);
+	areq = req->areq.dh;
+	areq->dst_len = ctx->key_sz;
+	hpre_hw_data_clr_all(ctx, req, areq->dst, areq->src);
+	kpp_request_complete(areq, ret);
+}
+
+static void hpre_rsa_cb(struct hpre_ctx *ctx, void *resp)
+{
+	struct hpre_asym_request *req;
+	struct akcipher_request *areq;
+	int ret;
+
+	ret = hpre_alg_res_post_hf(ctx, resp, (void **)&req);
+	areq = req->areq.rsa;
+	areq->dst_len = ctx->key_sz;
+	hpre_hw_data_clr_all(ctx, req, areq->dst, areq->src);
+	akcipher_request_complete(areq, ret);
+}
+
+static void hpre_alg_cb(struct hisi_qp *qp, void *resp)
+{
+	struct hpre_ctx *ctx = qp->qp_ctx;
+	struct hpre_sqe *sqe = resp;
+
+	ctx->req_list[le16_to_cpu(sqe->tag)]->cb(ctx, resp);
+}
+
+static int hpre_ctx_init(struct hpre_ctx *ctx)
+{
+	struct hisi_qp *qp;
+
+	qp = hpre_get_qp_and_start();
+	if (IS_ERR(qp))
+		return PTR_ERR(qp);
+
+	qp->qp_ctx = ctx;
+	qp->req_cb = hpre_alg_cb;
+
+	return hpre_ctx_set(ctx, qp, QM_Q_DEPTH);
+}
+
+static int hpre_msg_request_set(struct hpre_ctx *ctx, void *req, bool is_rsa)
+{
+	struct hpre_asym_request *h_req;
+	struct hpre_sqe *msg;
+	int req_id;
+	void *tmp;
+
+	if (is_rsa) {
+		struct akcipher_request *akreq = req;
+
+		if (akreq->dst_len < ctx->key_sz) {
+			akreq->dst_len = ctx->key_sz;
+			return -EOVERFLOW;
+		}
+
+		tmp = akcipher_request_ctx(akreq);
+		h_req = PTR_ALIGN(tmp, HPRE_ALIGN_SZ);
+		h_req->cb = hpre_rsa_cb;
+		h_req->areq.rsa = akreq;
+		msg = &h_req->req;
+		memset(msg, 0, sizeof(*msg));
+	} else {
+		struct kpp_request *kreq = req;
+
+		if (kreq->dst_len < ctx->key_sz) {
+			kreq->dst_len = ctx->key_sz;
+			return -EOVERFLOW;
+		}
+
+		tmp = kpp_request_ctx(kreq);
+		h_req = PTR_ALIGN(tmp, HPRE_ALIGN_SZ);
+		h_req->cb = hpre_dh_cb;
+		h_req->areq.dh = kreq;
+		msg = &h_req->req;
+		memset(msg, 0, sizeof(*msg));
+		msg->key = cpu_to_le64((u64)ctx->dh.dma_xa_p);
+	}
+
+	msg->dw0 |= cpu_to_le32(0x1 << HPRE_SQE_DONE_SHIFT);
+	msg->task_len1 = (ctx->key_sz >> HPRE_BITS_2_BYTES_SHIFT) - 1;
+	h_req->ctx = ctx;
+
+	req_id = hpre_add_req_to_ctx(h_req);
+	if (req_id < 0)
+		return -EBUSY;
+
+	msg->tag = cpu_to_le16((u16)req_id);
+
+	return 0;
+}
+
+#ifdef CONFIG_CRYPTO_DH
+static int hpre_dh_compute_value(struct kpp_request *req)
+{
+	struct crypto_kpp *tfm = crypto_kpp_reqtfm(req);
+	struct hpre_ctx *ctx = kpp_tfm_ctx(tfm);
+	void *tmp = kpp_request_ctx(req);
+	struct hpre_asym_request *hpre_req = PTR_ALIGN(tmp, HPRE_ALIGN_SZ);
+	struct hpre_sqe *msg = &hpre_req->req;
+	int ctr = 0;
+	int ret;
+
+	ret = hpre_msg_request_set(ctx, req, false);
+	if (unlikely(ret))
+		return ret;
+
+	if (req->src) {
+		ret = hpre_hw_data_init(hpre_req, req->src, req->src_len, 1, 1);
+		if (unlikely(ret))
+			goto clear_all;
+	}
+
+	ret = hpre_hw_data_init(hpre_req, req->dst, req->dst_len, 0, 1);
+	if (unlikely(ret))
+		goto clear_all;
+
+	if (ctx->crt_g2_mode && !req->src)
+		msg->dw0 = cpu_to_le32(le32_to_cpu(msg->dw0) | HPRE_ALG_DH_G2);
+	else
+		msg->dw0 = cpu_to_le32(le32_to_cpu(msg->dw0) | HPRE_ALG_DH);
+	do {
+		ret = hisi_qp_send(ctx->qp, msg);
+	} while (ret == -EBUSY && ctr++ < HPRE_TRY_SEND_TIMES);
+
+	/* success */
+	if (likely(!ret))
+		return -EINPROGRESS;
+
+clear_all:
+	hpre_rm_req_from_ctx(hpre_req);
+	hpre_hw_data_clr_all(ctx, hpre_req, req->dst, req->src);
+
+	return ret;
+}
+
+static int hpre_is_dh_params_length_valid(unsigned int key_sz)
+{
+#define _HPRE_DH_GRP1		768
+#define _HPRE_DH_GRP2		1024
+#define _HPRE_DH_GRP5		1536
+#define _HPRE_DH_GRP14		2048
+#define _HPRE_DH_GRP15		3072
+#define _HPRE_DH_GRP16		4096
+	switch (key_sz) {
+	case _HPRE_DH_GRP1:
+	case _HPRE_DH_GRP2:
+	case _HPRE_DH_GRP5:
+	case _HPRE_DH_GRP14:
+	case _HPRE_DH_GRP15:
+	case _HPRE_DH_GRP16:
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int hpre_dh_set_params(struct hpre_ctx *ctx, struct dh *params)
+{
+	struct device *dev = HPRE_DEV(ctx);
+	unsigned int sz;
+
+	if (params->p_size > HPRE_DH_MAX_P_SZ)
+		return -EINVAL;
+
+	if (hpre_is_dh_params_length_valid(params->p_size <<
+					   HPRE_BITS_2_BYTES_SHIFT))
+		return -EINVAL;
+
+	sz = ctx->key_sz = params->p_size;
+	ctx->dh.xa_p = dma_alloc_coherent(dev, sz << 1,
+					  &ctx->dh.dma_xa_p, GFP_KERNEL);
+	if (!ctx->dh.xa_p)
+		return -ENOMEM;
+
+	memcpy(ctx->dh.xa_p + sz, params->p, sz);
+
+	/* If g equals 2 don't copy it */
+	if (params->g_size == 1 && *(char *)params->g == HPRE_DH_G_FLAG) {
+		ctx->crt_g2_mode = true;
+		return 0;
+	}
+
+	ctx->dh.g = dma_alloc_coherent(dev, sz, &ctx->dh.dma_g, GFP_KERNEL);
+	if (!ctx->dh.g) {
+		dma_free_coherent(dev, sz << 1, ctx->dh.xa_p,
+				  ctx->dh.dma_xa_p);
+		ctx->dh.xa_p = NULL;
+		return -ENOMEM;
+	}
+
+	memcpy(ctx->dh.g + (sz - params->g_size), params->g, params->g_size);
+
+	return 0;
+}
+
+static void hpre_dh_clear_ctx(struct hpre_ctx *ctx, bool is_clear_all)
+{
+	struct device *dev = HPRE_DEV(ctx);
+	unsigned int sz = ctx->key_sz;
+
+	if (is_clear_all)
+		hisi_qm_stop_qp(ctx->qp);
+
+	if (ctx->dh.g) {
+		dma_free_coherent(dev, sz, ctx->dh.g, ctx->dh.dma_g);
+		ctx->dh.g = NULL;
+	}
+
+	if (ctx->dh.xa_p) {
+		memzero_explicit(ctx->dh.xa_p, sz);
+		dma_free_coherent(dev, sz << 1, ctx->dh.xa_p,
+				  ctx->dh.dma_xa_p);
+		ctx->dh.xa_p = NULL;
+	}
+
+	hpre_ctx_clear(ctx, is_clear_all);
+}
+
+static int hpre_dh_set_secret(struct crypto_kpp *tfm, const void *buf,
+			      unsigned int len)
+{
+	struct hpre_ctx *ctx = kpp_tfm_ctx(tfm);
+	struct dh params;
+	int ret;
+
+	if (crypto_dh_decode_key(buf, len, &params) < 0)
+		return -EINVAL;
+
+	/* Free old secret if any */
+	hpre_dh_clear_ctx(ctx, false);
+
+	ret = hpre_dh_set_params(ctx, &params);
+	if (ret < 0)
+		goto err_clear_ctx;
+
+	memcpy(ctx->dh.xa_p + (ctx->key_sz - params.key_size), params.key,
+	       params.key_size);
+
+	return 0;
+
+err_clear_ctx:
+	hpre_dh_clear_ctx(ctx, false);
+	return ret;
+}
+
+static unsigned int hpre_dh_max_size(struct crypto_kpp *tfm)
+{
+	struct hpre_ctx *ctx = kpp_tfm_ctx(tfm);
+
+	return ctx->key_sz;
+}
+
+static int hpre_dh_init_tfm(struct crypto_kpp *tfm)
+{
+	struct hpre_ctx *ctx = kpp_tfm_ctx(tfm);
+
+	return hpre_ctx_init(ctx);
+}
+
+static void hpre_dh_exit_tfm(struct crypto_kpp *tfm)
+{
+	struct hpre_ctx *ctx = kpp_tfm_ctx(tfm);
+
+	hpre_dh_clear_ctx(ctx, true);
+}
+#endif
+
+static void hpre_rsa_drop_leading_zeros(const char **ptr, size_t *len)
+{
+	while (!**ptr && *len) {
+		(*ptr)++;
+		(*len)--;
+	}
+}
+
+static bool hpre_rsa_key_size_is_support(unsigned int len)
+{
+	unsigned int bits = len << HPRE_BITS_2_BYTES_SHIFT;
+
+#define _RSA_1024BITS_KEY_WDTH		1024
+#define _RSA_2048BITS_KEY_WDTH		2048
+#define _RSA_3072BITS_KEY_WDTH		3072
+#define _RSA_4096BITS_KEY_WDTH		4096
+
+	switch (bits) {
+	case _RSA_1024BITS_KEY_WDTH:
+	case _RSA_2048BITS_KEY_WDTH:
+	case _RSA_3072BITS_KEY_WDTH:
+	case _RSA_4096BITS_KEY_WDTH:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static int hpre_rsa_enc(struct akcipher_request *req)
+{
+	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+	struct hpre_ctx *ctx = akcipher_tfm_ctx(tfm);
+	void *tmp = akcipher_request_ctx(req);
+	struct hpre_asym_request *hpre_req = PTR_ALIGN(tmp, HPRE_ALIGN_SZ);
+	struct hpre_sqe *msg = &hpre_req->req;
+	int ctr = 0;
+	int ret;
+
+	/* For 512 and 1536 bits key size, use soft tfm instead */
+	if (ctx->key_sz == HPRE_RSA_512BITS_KSZ ||
+	    ctx->key_sz == HPRE_RSA_1536BITS_KSZ) {
+		akcipher_request_set_tfm(req, ctx->rsa.soft_tfm);
+		ret = crypto_akcipher_encrypt(req);
+		akcipher_request_set_tfm(req, tfm);
+		return ret;
+	}
+
+	if (unlikely(!ctx->rsa.pubkey))
+		return -EINVAL;
+
+	ret = hpre_msg_request_set(ctx, req, true);
+	if (unlikely(ret))
+		return ret;
+
+	msg->dw0 |= cpu_to_le32(HPRE_ALG_NC_NCRT);
+	msg->key = cpu_to_le64((u64)ctx->rsa.dma_pubkey);
+
+	ret = hpre_hw_data_init(hpre_req, req->src, req->src_len, 1, 0);
+	if (unlikely(ret))
+		goto clear_all;
+
+	ret = hpre_hw_data_init(hpre_req, req->dst, req->dst_len, 0, 0);
+	if (unlikely(ret))
+		goto clear_all;
+
+	do {
+		ret = hisi_qp_send(ctx->qp, msg);
+	} while (ret == -EBUSY && ctr++ < HPRE_TRY_SEND_TIMES);
+
+	/* success */
+	if (likely(!ret))
+		return -EINPROGRESS;
+
+clear_all:
+	hpre_rm_req_from_ctx(hpre_req);
+	hpre_hw_data_clr_all(ctx, hpre_req, req->dst, req->src);
+
+	return ret;
+}
+
+static int hpre_rsa_dec(struct akcipher_request *req)
+{
+	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
+	struct hpre_ctx *ctx = akcipher_tfm_ctx(tfm);
+	void *tmp = akcipher_request_ctx(req);
+	struct hpre_asym_request *hpre_req = PTR_ALIGN(tmp, HPRE_ALIGN_SZ);
+	struct hpre_sqe *msg = &hpre_req->req;
+	int ctr = 0;
+	int ret;
+
+	/* For 512 and 1536 bits key size, use soft tfm instead */
+	if (ctx->key_sz == HPRE_RSA_512BITS_KSZ ||
+	    ctx->key_sz == HPRE_RSA_1536BITS_KSZ) {
+		akcipher_request_set_tfm(req, ctx->rsa.soft_tfm);
+		ret = crypto_akcipher_decrypt(req);
+		akcipher_request_set_tfm(req, tfm);
+		return ret;
+	}
+
+	if (unlikely(!ctx->rsa.prikey))
+		return -EINVAL;
+
+	ret = hpre_msg_request_set(ctx, req, true);
+	if (unlikely(ret))
+		return ret;
+
+	if (ctx->crt_g2_mode) {
+		msg->key = cpu_to_le64((u64)ctx->rsa.dma_crt_prikey);
+		msg->dw0 = cpu_to_le32(le32_to_cpu(msg->dw0) |
+				       HPRE_ALG_NC_CRT);
+	} else {
+		msg->key = cpu_to_le64((u64)ctx->rsa.dma_prikey);
+		msg->dw0 = cpu_to_le32(le32_to_cpu(msg->dw0) |
+				       HPRE_ALG_NC_NCRT);
+	}
+
+	ret = hpre_hw_data_init(hpre_req, req->src, req->src_len, 1, 0);
+	if (unlikely(ret))
+		goto clear_all;
+
+	ret = hpre_hw_data_init(hpre_req, req->dst, req->dst_len, 0, 0);
+	if (unlikely(ret))
+		goto clear_all;
+
+	do {
+		ret = hisi_qp_send(ctx->qp, msg);
+	} while (ret == -EBUSY && ctr++ < HPRE_TRY_SEND_TIMES);
+
+	/* success */
+	if (likely(!ret))
+		return -EINPROGRESS;
+
+clear_all:
+	hpre_rm_req_from_ctx(hpre_req);
+	hpre_hw_data_clr_all(ctx, hpre_req, req->dst, req->src);
+
+	return ret;
+}
+
+static int hpre_rsa_set_n(struct hpre_ctx *ctx, const char *value,
+			  size_t vlen, bool private)
+{
+	const char *ptr = value;
+
+	hpre_rsa_drop_leading_zeros(&ptr, &vlen);
+
+	ctx->key_sz = vlen;
+
+	/* if invalid key size provided, we use software tfm */
+	if (!hpre_rsa_key_size_is_support(ctx->key_sz))
+		return 0;
+
+	ctx->rsa.pubkey = dma_alloc_coherent(HPRE_DEV(ctx), vlen << 1,
+					     &ctx->rsa.dma_pubkey,
+					     GFP_KERNEL);
+	if (!ctx->rsa.pubkey)
+		return -ENOMEM;
+
+	if (private) {
+		ctx->rsa.prikey = dma_alloc_coherent(HPRE_DEV(ctx), vlen << 1,
+						     &ctx->rsa.dma_prikey,
+						     GFP_KERNEL);
+		if (!ctx->rsa.prikey) {
+			dma_free_coherent(HPRE_DEV(ctx), vlen << 1,
+					  ctx->rsa.pubkey,
+					  ctx->rsa.dma_pubkey);
+			ctx->rsa.pubkey = NULL;
+			return -ENOMEM;
+		}
+		memcpy(ctx->rsa.prikey + vlen, ptr, vlen);
+	}
+	memcpy(ctx->rsa.pubkey + vlen, ptr, vlen);
+
+	/* Using hardware HPRE to do RSA */
+	return 1;
+}
+
+static int hpre_rsa_set_e(struct hpre_ctx *ctx, const char *value,
+			  size_t vlen)
+{
+	const char *ptr = value;
+
+	hpre_rsa_drop_leading_zeros(&ptr, &vlen);
+
+	if (!ctx->key_sz || !vlen || vlen > ctx->key_sz)
+		return -EINVAL;
+
+	memcpy(ctx->rsa.pubkey + ctx->key_sz - vlen, ptr, vlen);
+
+	return 0;
+}
+
+static int hpre_rsa_set_d(struct hpre_ctx *ctx, const char *value,
+			  size_t vlen)
+{
+	const char *ptr = value;
+
+	hpre_rsa_drop_leading_zeros(&ptr, &vlen);
+
+	if (!ctx->key_sz || !vlen || vlen > ctx->key_sz)
+		return -EINVAL;
+
+	memcpy(ctx->rsa.prikey + ctx->key_sz - vlen, ptr, vlen);
+
+	return 0;
+}
+
+static int hpre_crt_para_get(char *para, size_t para_sz,
+			     const char *raw, size_t raw_sz)
+{
+	const char *ptr = raw;
+	size_t len = raw_sz;
+
+	hpre_rsa_drop_leading_zeros(&ptr, &len);
+	if (!len || len > para_sz)
+		return -EINVAL;
+
+	memcpy(para + para_sz - len, ptr, len);
+
+	return 0;
+}
+
+static int hpre_rsa_setkey_crt(struct hpre_ctx *ctx, struct rsa_key *rsa_key)
+{
+	unsigned int hlf_ksz = ctx->key_sz >> 1;
+	struct device *dev = HPRE_DEV(ctx);
+	u64 offset;
+	int ret;
+
+	ctx->rsa.crt_prikey = dma_alloc_coherent(dev, hlf_ksz * HPRE_CRT_PRMS,
+					&ctx->rsa.dma_crt_prikey,
+					GFP_KERNEL);
+	if (!ctx->rsa.crt_prikey)
+		return -ENOMEM;
+
+	ret = hpre_crt_para_get(ctx->rsa.crt_prikey, hlf_ksz,
+				rsa_key->dq, rsa_key->dq_sz);
+	if (ret)
+		goto free_key;
+
+	offset = hlf_ksz;
+	ret = hpre_crt_para_get(ctx->rsa.crt_prikey + offset, hlf_ksz,
+				rsa_key->dp, rsa_key->dp_sz);
+	if (ret)
+		goto free_key;
+
+	offset = hlf_ksz * HPRE_CRT_Q;
+	ret = hpre_crt_para_get(ctx->rsa.crt_prikey + offset, hlf_ksz,
+				rsa_key->q, rsa_key->q_sz);
+	if (ret)
+		goto free_key;
+
+	offset = hlf_ksz * HPRE_CRT_P;
+	ret = hpre_crt_para_get(ctx->rsa.crt_prikey + offset, hlf_ksz,
+				rsa_key->p, rsa_key->p_sz);
+	if (ret)
+		goto free_key;
+
+	offset = hlf_ksz * HPRE_CRT_INV;
+	ret = hpre_crt_para_get(ctx->rsa.crt_prikey + offset, hlf_ksz,
+				rsa_key->qinv, rsa_key->qinv_sz);
+	if (ret)
+		goto free_key;
+
+	ctx->crt_g2_mode = true;
+
+	return 0;
+
+free_key:
+	offset = hlf_ksz * HPRE_CRT_PRMS;
+	memzero_explicit(ctx->rsa.crt_prikey, offset);
+	dma_free_coherent(dev, hlf_ksz * HPRE_CRT_PRMS, ctx->rsa.crt_prikey,
+			  ctx->rsa.dma_crt_prikey);
+	ctx->rsa.crt_prikey = NULL;
+	ctx->crt_g2_mode = false;
+
+	return ret;
+}
+
+/* If it is clear all, all the resources of the QP will be cleaned. */
+static void hpre_rsa_clear_ctx(struct hpre_ctx *ctx, bool is_clear_all)
+{
+	unsigned int half_key_sz = ctx->key_sz >> 1;
+	struct device *dev = HPRE_DEV(ctx);
+
+	if (is_clear_all)
+		hisi_qm_stop_qp(ctx->qp);
+
+	if (ctx->rsa.pubkey) {
+		dma_free_coherent(dev, ctx->key_sz << 1,
+				  ctx->rsa.pubkey, ctx->rsa.dma_pubkey);
+		ctx->rsa.pubkey = NULL;
+	}
+
+	if (ctx->rsa.crt_prikey) {
+		memzero_explicit(ctx->rsa.crt_prikey,
+				 half_key_sz * HPRE_CRT_PRMS);
+		dma_free_coherent(dev, half_key_sz * HPRE_CRT_PRMS,
+				  ctx->rsa.crt_prikey, ctx->rsa.dma_crt_prikey);
+		ctx->rsa.crt_prikey = NULL;
+	}
+
+	if (ctx->rsa.prikey) {
+		memzero_explicit(ctx->rsa.prikey, ctx->key_sz);
+		dma_free_coherent(dev, ctx->key_sz << 1, ctx->rsa.prikey,
+				  ctx->rsa.dma_prikey);
+		ctx->rsa.prikey = NULL;
+	}
+
+	hpre_ctx_clear(ctx, is_clear_all);
+}
+
+/*
+ * we should judge if it is CRT or not,
+ * CRT: return true,  N-CRT: return false .
+ */
+static bool hpre_is_crt_key(struct rsa_key *key)
+{
+	u16 len = key->p_sz + key->q_sz + key->dp_sz + key->dq_sz +
+		  key->qinv_sz;
+
+#define LEN_OF_NCRT_PARA	5
+
+	/* N-CRT less than 5 parameters */
+	return len > LEN_OF_NCRT_PARA;
+}
+
+static int hpre_rsa_setkey(struct hpre_ctx *ctx, const void *key,
+			   unsigned int keylen, bool private)
+{
+	struct rsa_key rsa_key;
+	int ret;
+
+	hpre_rsa_clear_ctx(ctx, false);
+
+	if (private)
+		ret = rsa_parse_priv_key(&rsa_key, key, keylen);
+	else
+		ret = rsa_parse_pub_key(&rsa_key, key, keylen);
+	if (ret < 0)
+		return ret;
+
+	ret = hpre_rsa_set_n(ctx, rsa_key.n, rsa_key.n_sz, private);
+	if (ret <= 0)
+		return ret;
+
+	if (private) {
+		ret = hpre_rsa_set_d(ctx, rsa_key.d, rsa_key.d_sz);
+		if (ret < 0)
+			goto free;
+
+		if (hpre_is_crt_key(&rsa_key)) {
+			ret = hpre_rsa_setkey_crt(ctx, &rsa_key);
+			if (ret < 0)
+				goto free;
+		}
+	}
+
+	ret = hpre_rsa_set_e(ctx, rsa_key.e, rsa_key.e_sz);
+	if (ret < 0)
+		goto free;
+
+	if ((private && !ctx->rsa.prikey) || !ctx->rsa.pubkey) {
+		ret = -EINVAL;
+		goto free;
+	}
+
+	return 0;
+
+free:
+	hpre_rsa_clear_ctx(ctx, false);
+	return ret;
+}
+
+static int hpre_rsa_setpubkey(struct crypto_akcipher *tfm, const void *key,
+			      unsigned int keylen)
+{
+	struct hpre_ctx *ctx = akcipher_tfm_ctx(tfm);
+	int ret;
+
+	ret = crypto_akcipher_set_pub_key(ctx->rsa.soft_tfm, key, keylen);
+	if (ret)
+		return ret;
+
+	return hpre_rsa_setkey(ctx, key, keylen, false);
+}
+
+static int hpre_rsa_setprivkey(struct crypto_akcipher *tfm, const void *key,
+			       unsigned int keylen)
+{
+	struct hpre_ctx *ctx = akcipher_tfm_ctx(tfm);
+	int ret;
+
+	ret = crypto_akcipher_set_priv_key(ctx->rsa.soft_tfm, key, keylen);
+	if (ret)
+		return ret;
+
+	return hpre_rsa_setkey(ctx, key, keylen, true);
+}
+
+static unsigned int hpre_rsa_max_size(struct crypto_akcipher *tfm)
+{
+	struct hpre_ctx *ctx = akcipher_tfm_ctx(tfm);
+
+	/* For 512 and 1536 bits key size, use soft tfm instead */
+	if (ctx->key_sz == HPRE_RSA_512BITS_KSZ ||
+	    ctx->key_sz == HPRE_RSA_1536BITS_KSZ)
+		return crypto_akcipher_maxsize(ctx->rsa.soft_tfm);
+
+	return ctx->key_sz;
+}
+
+static int hpre_rsa_init_tfm(struct crypto_akcipher *tfm)
+{
+	struct hpre_ctx *ctx = akcipher_tfm_ctx(tfm);
+	int ret;
+
+	ctx->rsa.soft_tfm = crypto_alloc_akcipher("rsa-generic", 0, 0);
+	if (IS_ERR(ctx->rsa.soft_tfm)) {
+		pr_err("Can not alloc_akcipher!\n");
+		return PTR_ERR(ctx->rsa.soft_tfm);
+	}
+
+	ret = hpre_ctx_init(ctx);
+	if (ret)
+		crypto_free_akcipher(ctx->rsa.soft_tfm);
+
+	return ret;
+}
+
+static void hpre_rsa_exit_tfm(struct crypto_akcipher *tfm)
+{
+	struct hpre_ctx *ctx = akcipher_tfm_ctx(tfm);
+
+	hpre_rsa_clear_ctx(ctx, true);
+	crypto_free_akcipher(ctx->rsa.soft_tfm);
+}
+
+static struct akcipher_alg rsa = {
+	.sign = hpre_rsa_dec,
+	.verify = hpre_rsa_enc,
+	.encrypt = hpre_rsa_enc,
+	.decrypt = hpre_rsa_dec,
+	.set_pub_key = hpre_rsa_setpubkey,
+	.set_priv_key = hpre_rsa_setprivkey,
+	.max_size = hpre_rsa_max_size,
+	.init = hpre_rsa_init_tfm,
+	.exit = hpre_rsa_exit_tfm,
+	.reqsize = sizeof(struct hpre_asym_request) + HPRE_ALIGN_SZ,
+	.base = {
+		.cra_ctxsize = sizeof(struct hpre_ctx),
+		.cra_priority = HPRE_CRYPTO_ALG_PRI,
+		.cra_name = "rsa",
+		.cra_driver_name = "hpre-rsa",
+		.cra_module = THIS_MODULE,
+	},
+};
+
+#ifdef CONFIG_CRYPTO_DH
+static struct kpp_alg dh = {
+	.set_secret = hpre_dh_set_secret,
+	.generate_public_key = hpre_dh_compute_value,
+	.compute_shared_secret = hpre_dh_compute_value,
+	.max_size = hpre_dh_max_size,
+	.init = hpre_dh_init_tfm,
+	.exit = hpre_dh_exit_tfm,
+	.reqsize = sizeof(struct hpre_asym_request) + HPRE_ALIGN_SZ,
+	.base = {
+		.cra_ctxsize = sizeof(struct hpre_ctx),
+		.cra_priority = HPRE_CRYPTO_ALG_PRI,
+		.cra_name = "dh",
+		.cra_driver_name = "hpre-dh",
+		.cra_module = THIS_MODULE,
+	},
+};
+#endif
+
+int hpre_algs_register(void)
+{
+	int ret = 0;
+
+	mutex_lock(&hpre_alg_lock);
+	if (++hpre_active_devs == 1) {
+		rsa.base.cra_flags = 0;
+		ret = crypto_register_akcipher(&rsa);
+		if (ret)
+			goto unlock;
+#ifdef CONFIG_CRYPTO_DH
+		ret = crypto_register_kpp(&dh);
+		if (ret) {
+			crypto_unregister_akcipher(&rsa);
+			goto unlock;
+		}
+#endif
+	}
+
+unlock:
+	mutex_unlock(&hpre_alg_lock);
+	return ret;
+}
+
+void hpre_algs_unregister(void)
+{
+	mutex_lock(&hpre_alg_lock);
+	if (--hpre_active_devs == 0) {
+		crypto_unregister_akcipher(&rsa);
+#ifdef CONFIG_CRYPTO_DH
+		crypto_unregister_kpp(&dh);
+#endif
+	}
+	mutex_unlock(&hpre_alg_lock);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/hisilicon/hpre/hpre_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/hisilicon/hpre/hpre_main.c
@@ -0,0 +1,1037 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2018-2019 HiSilicon Limited. */
+#include <linux/acpi.h>
+#include <linux/aer.h>
+#include <linux/bitops.h>
+#include <linux/debugfs.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/topology.h>
+#include "hpre.h"
+
+#define HPRE_VF_NUM			63
+#define HPRE_QUEUE_NUM_V2		1024
+#define HPRE_QM_ABNML_INT_MASK		0x100004
+#define HPRE_CTRL_CNT_CLR_CE_BIT	BIT(0)
+#define HPRE_COMM_CNT_CLR_CE		0x0
+#define HPRE_CTRL_CNT_CLR_CE		0x301000
+#define HPRE_FSM_MAX_CNT		0x301008
+#define HPRE_VFG_AXQOS			0x30100c
+#define HPRE_VFG_AXCACHE		0x301010
+#define HPRE_RDCHN_INI_CFG		0x301014
+#define HPRE_AWUSR_FP_CFG		0x301018
+#define HPRE_BD_ENDIAN			0x301020
+#define HPRE_ECC_BYPASS			0x301024
+#define HPRE_RAS_WIDTH_CFG		0x301028
+#define HPRE_POISON_BYPASS		0x30102c
+#define HPRE_BD_ARUSR_CFG		0x301030
+#define HPRE_BD_AWUSR_CFG		0x301034
+#define HPRE_TYPES_ENB			0x301038
+#define HPRE_DATA_RUSER_CFG		0x30103c
+#define HPRE_DATA_WUSER_CFG		0x301040
+#define HPRE_INT_MASK			0x301400
+#define HPRE_INT_STATUS			0x301800
+#define HPRE_CORE_INT_ENABLE		0
+#define HPRE_CORE_INT_DISABLE		0x003fffff
+#define HPRE_RAS_ECC_1BIT_TH		0x30140c
+#define HPRE_RDCHN_INI_ST		0x301a00
+#define HPRE_CLSTR_BASE			0x302000
+#define HPRE_CORE_EN_OFFSET		0x04
+#define HPRE_CORE_INI_CFG_OFFSET	0x20
+#define HPRE_CORE_INI_STATUS_OFFSET	0x80
+#define HPRE_CORE_HTBT_WARN_OFFSET	0x8c
+#define HPRE_CORE_IS_SCHD_OFFSET	0x90
+
+#define HPRE_RAS_CE_ENB			0x301410
+#define HPRE_HAC_RAS_CE_ENABLE		0x3f
+#define HPRE_RAS_NFE_ENB		0x301414
+#define HPRE_HAC_RAS_NFE_ENABLE		0x3fffc0
+#define HPRE_RAS_FE_ENB			0x301418
+#define HPRE_HAC_RAS_FE_ENABLE		0
+
+#define HPRE_CORE_ENB		(HPRE_CLSTR_BASE + HPRE_CORE_EN_OFFSET)
+#define HPRE_CORE_INI_CFG	(HPRE_CLSTR_BASE + HPRE_CORE_INI_CFG_OFFSET)
+#define HPRE_CORE_INI_STATUS (HPRE_CLSTR_BASE + HPRE_CORE_INI_STATUS_OFFSET)
+#define HPRE_HAC_ECC1_CNT		0x301a04
+#define HPRE_HAC_ECC2_CNT		0x301a08
+#define HPRE_HAC_INT_STATUS		0x301800
+#define HPRE_HAC_SOURCE_INT		0x301600
+#define MASTER_GLOBAL_CTRL_SHUTDOWN	1
+#define MASTER_TRANS_RETURN_RW		3
+#define HPRE_MASTER_TRANS_RETURN	0x300150
+#define HPRE_MASTER_GLOBAL_CTRL		0x300000
+#define HPRE_CLSTR_ADDR_INTRVL		0x1000
+#define HPRE_CLUSTER_INQURY		0x100
+#define HPRE_CLSTR_ADDR_INQRY_RSLT	0x104
+#define HPRE_TIMEOUT_ABNML_BIT		6
+#define HPRE_PASID_EN_BIT		9
+#define HPRE_REG_RD_INTVRL_US		10
+#define HPRE_REG_RD_TMOUT_US		1000
+#define HPRE_DBGFS_VAL_MAX_LEN		20
+#define HPRE_PCI_DEVICE_ID		0xa258
+#define HPRE_PCI_VF_DEVICE_ID		0xa259
+#define HPRE_ADDR(qm, offset)		((qm)->io_base + (offset))
+#define HPRE_QM_USR_CFG_MASK		0xfffffffe
+#define HPRE_QM_AXI_CFG_MASK		0xffff
+#define HPRE_QM_VFG_AX_MASK		0xff
+#define HPRE_BD_USR_MASK		0x3
+#define HPRE_CLUSTER_CORE_MASK		0xf
+
+#define HPRE_VIA_MSI_DSM		1
+
+static LIST_HEAD(hpre_list);
+static DEFINE_MUTEX(hpre_list_lock);
+static const char hpre_name[] = "hisi_hpre";
+static struct dentry *hpre_debugfs_root;
+static const struct pci_device_id hpre_dev_ids[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_HUAWEI, HPRE_PCI_DEVICE_ID) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_HUAWEI, HPRE_PCI_VF_DEVICE_ID) },
+	{ 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, hpre_dev_ids);
+
+struct hpre_hw_error {
+	u32 int_msk;
+	const char *msg;
+};
+
+static const char * const hpre_debug_file_name[] = {
+	[HPRE_CURRENT_QM]   = "current_qm",
+	[HPRE_CLEAR_ENABLE] = "rdclr_en",
+	[HPRE_CLUSTER_CTRL] = "cluster_ctrl",
+};
+
+static const struct hpre_hw_error hpre_hw_errors[] = {
+	{ .int_msk = BIT(0), .msg = "core_ecc_1bit_err_int_set" },
+	{ .int_msk = BIT(1), .msg = "core_ecc_2bit_err_int_set" },
+	{ .int_msk = BIT(2), .msg = "dat_wb_poison_int_set" },
+	{ .int_msk = BIT(3), .msg = "dat_rd_poison_int_set" },
+	{ .int_msk = BIT(4), .msg = "bd_rd_poison_int_set" },
+	{ .int_msk = BIT(5), .msg = "ooo_ecc_2bit_err_int_set" },
+	{ .int_msk = BIT(6), .msg = "cluster1_shb_timeout_int_set" },
+	{ .int_msk = BIT(7), .msg = "cluster2_shb_timeout_int_set" },
+	{ .int_msk = BIT(8), .msg = "cluster3_shb_timeout_int_set" },
+	{ .int_msk = BIT(9), .msg = "cluster4_shb_timeout_int_set" },
+	{ .int_msk = GENMASK(15, 10), .msg = "ooo_rdrsp_err_int_set" },
+	{ .int_msk = GENMASK(21, 16), .msg = "ooo_wrrsp_err_int_set" },
+	{ /* sentinel */ }
+};
+
+static const u64 hpre_cluster_offsets[] = {
+	[HPRE_CLUSTER0] =
+		HPRE_CLSTR_BASE + HPRE_CLUSTER0 * HPRE_CLSTR_ADDR_INTRVL,
+	[HPRE_CLUSTER1] =
+		HPRE_CLSTR_BASE + HPRE_CLUSTER1 * HPRE_CLSTR_ADDR_INTRVL,
+	[HPRE_CLUSTER2] =
+		HPRE_CLSTR_BASE + HPRE_CLUSTER2 * HPRE_CLSTR_ADDR_INTRVL,
+	[HPRE_CLUSTER3] =
+		HPRE_CLSTR_BASE + HPRE_CLUSTER3 * HPRE_CLSTR_ADDR_INTRVL,
+};
+
+static struct debugfs_reg32 hpre_cluster_dfx_regs[] = {
+	{"CORES_EN_STATUS          ",  HPRE_CORE_EN_OFFSET},
+	{"CORES_INI_CFG              ",  HPRE_CORE_INI_CFG_OFFSET},
+	{"CORES_INI_STATUS         ",  HPRE_CORE_INI_STATUS_OFFSET},
+	{"CORES_HTBT_WARN         ",  HPRE_CORE_HTBT_WARN_OFFSET},
+	{"CORES_IS_SCHD               ",  HPRE_CORE_IS_SCHD_OFFSET},
+};
+
+static struct debugfs_reg32 hpre_com_dfx_regs[] = {
+	{"READ_CLR_EN          ",  HPRE_CTRL_CNT_CLR_CE},
+	{"AXQOS                   ",  HPRE_VFG_AXQOS},
+	{"AWUSR_CFG              ",  HPRE_AWUSR_FP_CFG},
+	{"QM_ARUSR_MCFG1           ",  QM_ARUSER_M_CFG_1},
+	{"QM_AWUSR_MCFG1           ",  QM_AWUSER_M_CFG_1},
+	{"BD_ENDIAN               ",  HPRE_BD_ENDIAN},
+	{"ECC_CHECK_CTRL       ",  HPRE_ECC_BYPASS},
+	{"RAS_INT_WIDTH       ",  HPRE_RAS_WIDTH_CFG},
+	{"POISON_BYPASS       ",  HPRE_POISON_BYPASS},
+	{"BD_ARUSER               ",  HPRE_BD_ARUSR_CFG},
+	{"BD_AWUSER               ",  HPRE_BD_AWUSR_CFG},
+	{"DATA_ARUSER            ",  HPRE_DATA_RUSER_CFG},
+	{"DATA_AWUSER           ",  HPRE_DATA_WUSER_CFG},
+	{"INT_STATUS               ",  HPRE_INT_STATUS},
+};
+
+static int hpre_pf_q_num_set(const char *val, const struct kernel_param *kp)
+{
+	struct pci_dev *pdev;
+	u32 n, q_num;
+	u8 rev_id;
+	int ret;
+
+	if (!val)
+		return -EINVAL;
+
+	pdev = pci_get_device(PCI_VENDOR_ID_HUAWEI, HPRE_PCI_DEVICE_ID, NULL);
+	if (!pdev) {
+		q_num = HPRE_QUEUE_NUM_V2;
+		pr_info("No device found currently, suppose queue number is %d\n",
+			q_num);
+	} else {
+		rev_id = pdev->revision;
+		if (rev_id != QM_HW_V2)
+			return -EINVAL;
+
+		q_num = HPRE_QUEUE_NUM_V2;
+	}
+
+	ret = kstrtou32(val, 10, &n);
+	if (ret != 0 || n == 0 || n > q_num)
+		return -EINVAL;
+
+	return param_set_int(val, kp);
+}
+
+static const struct kernel_param_ops hpre_pf_q_num_ops = {
+	.set = hpre_pf_q_num_set,
+	.get = param_get_int,
+};
+
+static u32 hpre_pf_q_num = HPRE_PF_DEF_Q_NUM;
+module_param_cb(hpre_pf_q_num, &hpre_pf_q_num_ops, &hpre_pf_q_num, 0444);
+MODULE_PARM_DESC(hpre_pf_q_num, "Number of queues in PF of CS(1-1024)");
+
+static inline void hpre_add_to_list(struct hpre *hpre)
+{
+	mutex_lock(&hpre_list_lock);
+	list_add_tail(&hpre->list, &hpre_list);
+	mutex_unlock(&hpre_list_lock);
+}
+
+static inline void hpre_remove_from_list(struct hpre *hpre)
+{
+	mutex_lock(&hpre_list_lock);
+	list_del(&hpre->list);
+	mutex_unlock(&hpre_list_lock);
+}
+
+struct hpre *hpre_find_device(int node)
+{
+	struct hpre *hpre, *ret = NULL;
+	int min_distance = INT_MAX;
+	struct device *dev;
+	int dev_node = 0;
+
+	mutex_lock(&hpre_list_lock);
+	list_for_each_entry(hpre, &hpre_list, list) {
+		dev = &hpre->qm.pdev->dev;
+#ifdef CONFIG_NUMA
+		dev_node = dev->numa_node;
+		if (dev_node < 0)
+			dev_node = 0;
+#endif
+		if (node_distance(dev_node, node) < min_distance) {
+			ret = hpre;
+			min_distance = node_distance(dev_node, node);
+		}
+	}
+	mutex_unlock(&hpre_list_lock);
+
+	return ret;
+}
+
+static int hpre_cfg_by_dsm(struct hisi_qm *qm)
+{
+	struct device *dev = &qm->pdev->dev;
+	union acpi_object *obj;
+	guid_t guid;
+
+	if (guid_parse("b06b81ab-0134-4a45-9b0c-483447b95fa7", &guid)) {
+		dev_err(dev, "Hpre GUID failed\n");
+		return -EINVAL;
+	}
+
+	/* Switch over to MSI handling due to non-standard PCI implementation */
+	obj = acpi_evaluate_dsm(ACPI_HANDLE(dev), &guid,
+				0, HPRE_VIA_MSI_DSM, NULL);
+	if (!obj) {
+		dev_err(dev, "ACPI handle failed!\n");
+		return -EIO;
+	}
+
+	ACPI_FREE(obj);
+
+	return 0;
+}
+
+static int hpre_set_user_domain_and_cache(struct hpre *hpre)
+{
+	struct hisi_qm *qm = &hpre->qm;
+	struct device *dev = &qm->pdev->dev;
+	unsigned long offset;
+	int ret, i;
+	u32 val;
+
+	writel(HPRE_QM_USR_CFG_MASK, HPRE_ADDR(qm, QM_ARUSER_M_CFG_ENABLE));
+	writel(HPRE_QM_USR_CFG_MASK, HPRE_ADDR(qm, QM_AWUSER_M_CFG_ENABLE));
+	writel_relaxed(HPRE_QM_AXI_CFG_MASK, HPRE_ADDR(qm, QM_AXI_M_CFG));
+
+	/* disable FLR triggered by BME(bus master enable) */
+	writel(PEH_AXUSER_CFG, HPRE_ADDR(qm, QM_PEH_AXUSER_CFG));
+	writel(PEH_AXUSER_CFG_ENABLE, HPRE_ADDR(qm, QM_PEH_AXUSER_CFG_ENABLE));
+
+	/* HPRE need more time, we close this interrupt */
+	val = readl_relaxed(HPRE_ADDR(qm, HPRE_QM_ABNML_INT_MASK));
+	val |= BIT(HPRE_TIMEOUT_ABNML_BIT);
+	writel_relaxed(val, HPRE_ADDR(qm, HPRE_QM_ABNML_INT_MASK));
+
+	writel(0x1, HPRE_ADDR(qm, HPRE_TYPES_ENB));
+	writel(HPRE_QM_VFG_AX_MASK, HPRE_ADDR(qm, HPRE_VFG_AXCACHE));
+	writel(0x0, HPRE_ADDR(qm, HPRE_BD_ENDIAN));
+	writel(0x0, HPRE_ADDR(qm, HPRE_INT_MASK));
+	writel(0x0, HPRE_ADDR(qm, HPRE_RAS_ECC_1BIT_TH));
+	writel(0x0, HPRE_ADDR(qm, HPRE_POISON_BYPASS));
+	writel(0x0, HPRE_ADDR(qm, HPRE_COMM_CNT_CLR_CE));
+	writel(0x0, HPRE_ADDR(qm, HPRE_ECC_BYPASS));
+
+	writel(HPRE_BD_USR_MASK, HPRE_ADDR(qm, HPRE_BD_ARUSR_CFG));
+	writel(HPRE_BD_USR_MASK, HPRE_ADDR(qm, HPRE_BD_AWUSR_CFG));
+	writel(0x1, HPRE_ADDR(qm, HPRE_RDCHN_INI_CFG));
+	ret = readl_relaxed_poll_timeout(HPRE_ADDR(qm, HPRE_RDCHN_INI_ST), val,
+			val & BIT(0),
+			HPRE_REG_RD_INTVRL_US,
+			HPRE_REG_RD_TMOUT_US);
+	if (ret) {
+		dev_err(dev, "read rd channel timeout fail!\n");
+		return -ETIMEDOUT;
+	}
+
+	for (i = 0; i < HPRE_CLUSTERS_NUM; i++) {
+		offset = i * HPRE_CLSTR_ADDR_INTRVL;
+
+		/* clusters initiating */
+		writel(HPRE_CLUSTER_CORE_MASK,
+		       HPRE_ADDR(qm, offset + HPRE_CORE_ENB));
+		writel(0x1, HPRE_ADDR(qm, offset + HPRE_CORE_INI_CFG));
+		ret = readl_relaxed_poll_timeout(HPRE_ADDR(qm, offset +
+					HPRE_CORE_INI_STATUS), val,
+					((val & HPRE_CLUSTER_CORE_MASK) ==
+					HPRE_CLUSTER_CORE_MASK),
+					HPRE_REG_RD_INTVRL_US,
+					HPRE_REG_RD_TMOUT_US);
+		if (ret) {
+			dev_err(dev,
+				"cluster %d int st status timeout!\n", i);
+			return -ETIMEDOUT;
+		}
+	}
+
+	ret = hpre_cfg_by_dsm(qm);
+	if (ret)
+		dev_err(dev, "acpi_evaluate_dsm err.\n");
+
+	return ret;
+}
+
+static void hpre_cnt_regs_clear(struct hisi_qm *qm)
+{
+	unsigned long offset;
+	int i;
+
+	/* clear current_qm */
+	writel(0x0, qm->io_base + QM_DFX_MB_CNT_VF);
+	writel(0x0, qm->io_base + QM_DFX_DB_CNT_VF);
+
+	/* clear clusterX/cluster_ctrl */
+	for (i = 0; i < HPRE_CLUSTERS_NUM; i++) {
+		offset = HPRE_CLSTR_BASE + i * HPRE_CLSTR_ADDR_INTRVL;
+		writel(0x0, qm->io_base + offset + HPRE_CLUSTER_INQURY);
+	}
+
+	/* clear rdclr_en */
+	writel(0x0, qm->io_base + HPRE_CTRL_CNT_CLR_CE);
+
+	hisi_qm_debug_regs_clear(qm);
+}
+
+static void hpre_hw_error_disable(struct hisi_qm *qm)
+{
+	/* disable hpre hw error interrupts */
+	writel(HPRE_CORE_INT_DISABLE, qm->io_base + HPRE_INT_MASK);
+}
+
+static void hpre_hw_error_enable(struct hisi_qm *qm)
+{
+	/* enable hpre hw error interrupts */
+	writel(HPRE_CORE_INT_ENABLE, qm->io_base + HPRE_INT_MASK);
+	writel(HPRE_HAC_RAS_CE_ENABLE, qm->io_base + HPRE_RAS_CE_ENB);
+	writel(HPRE_HAC_RAS_NFE_ENABLE, qm->io_base + HPRE_RAS_NFE_ENB);
+	writel(HPRE_HAC_RAS_FE_ENABLE, qm->io_base + HPRE_RAS_FE_ENB);
+}
+
+static inline struct hisi_qm *hpre_file_to_qm(struct hpre_debugfs_file *file)
+{
+	struct hpre *hpre = container_of(file->debug, struct hpre, debug);
+
+	return &hpre->qm;
+}
+
+static u32 hpre_current_qm_read(struct hpre_debugfs_file *file)
+{
+	struct hisi_qm *qm = hpre_file_to_qm(file);
+
+	return readl(qm->io_base + QM_DFX_MB_CNT_VF);
+}
+
+static int hpre_current_qm_write(struct hpre_debugfs_file *file, u32 val)
+{
+	struct hisi_qm *qm = hpre_file_to_qm(file);
+	struct hpre_debug *debug = file->debug;
+	struct hpre *hpre = container_of(debug, struct hpre, debug);
+	u32 num_vfs = hpre->num_vfs;
+	u32 vfq_num, tmp;
+
+
+	if (val > num_vfs)
+		return -EINVAL;
+
+	/* According PF or VF Dev ID to calculation curr_qm_qp_num and store */
+	if (val == 0) {
+		qm->debug.curr_qm_qp_num = qm->qp_num;
+	} else {
+		vfq_num = (qm->ctrl_qp_num - qm->qp_num) / num_vfs;
+		if (val == num_vfs) {
+			qm->debug.curr_qm_qp_num =
+			qm->ctrl_qp_num - qm->qp_num - (num_vfs - 1) * vfq_num;
+		} else {
+			qm->debug.curr_qm_qp_num = vfq_num;
+		}
+	}
+
+	writel(val, qm->io_base + QM_DFX_MB_CNT_VF);
+	writel(val, qm->io_base + QM_DFX_DB_CNT_VF);
+
+	tmp = val |
+	      (readl(qm->io_base + QM_DFX_SQE_CNT_VF_SQN) & CURRENT_Q_MASK);
+	writel(tmp, qm->io_base + QM_DFX_SQE_CNT_VF_SQN);
+
+	tmp = val |
+	      (readl(qm->io_base + QM_DFX_CQE_CNT_VF_CQN) & CURRENT_Q_MASK);
+	writel(tmp, qm->io_base + QM_DFX_CQE_CNT_VF_CQN);
+
+	return  0;
+}
+
+static u32 hpre_clear_enable_read(struct hpre_debugfs_file *file)
+{
+	struct hisi_qm *qm = hpre_file_to_qm(file);
+
+	return readl(qm->io_base + HPRE_CTRL_CNT_CLR_CE) &
+	       HPRE_CTRL_CNT_CLR_CE_BIT;
+}
+
+static int hpre_clear_enable_write(struct hpre_debugfs_file *file, u32 val)
+{
+	struct hisi_qm *qm = hpre_file_to_qm(file);
+	u32 tmp;
+
+	if (val != 1 && val != 0)
+		return -EINVAL;
+
+	tmp = (readl(qm->io_base + HPRE_CTRL_CNT_CLR_CE) &
+	       ~HPRE_CTRL_CNT_CLR_CE_BIT) | val;
+	writel(tmp, qm->io_base + HPRE_CTRL_CNT_CLR_CE);
+
+	return  0;
+}
+
+static u32 hpre_cluster_inqry_read(struct hpre_debugfs_file *file)
+{
+	struct hisi_qm *qm = hpre_file_to_qm(file);
+	int cluster_index = file->index - HPRE_CLUSTER_CTRL;
+	unsigned long offset = HPRE_CLSTR_BASE +
+			       cluster_index * HPRE_CLSTR_ADDR_INTRVL;
+
+	return readl(qm->io_base + offset + HPRE_CLSTR_ADDR_INQRY_RSLT);
+}
+
+static int hpre_cluster_inqry_write(struct hpre_debugfs_file *file, u32 val)
+{
+	struct hisi_qm *qm = hpre_file_to_qm(file);
+	int cluster_index = file->index - HPRE_CLUSTER_CTRL;
+	unsigned long offset = HPRE_CLSTR_BASE + cluster_index *
+			       HPRE_CLSTR_ADDR_INTRVL;
+
+	writel(val, qm->io_base + offset + HPRE_CLUSTER_INQURY);
+
+	return  0;
+}
+
+static ssize_t hpre_ctrl_debug_read(struct file *filp, char __user *buf,
+			       size_t count, loff_t *pos)
+{
+	struct hpre_debugfs_file *file = filp->private_data;
+	char tbuf[HPRE_DBGFS_VAL_MAX_LEN];
+	u32 val;
+	int ret;
+
+	spin_lock_irq(&file->lock);
+	switch (file->type) {
+	case HPRE_CURRENT_QM:
+		val = hpre_current_qm_read(file);
+		break;
+	case HPRE_CLEAR_ENABLE:
+		val = hpre_clear_enable_read(file);
+		break;
+	case HPRE_CLUSTER_CTRL:
+		val = hpre_cluster_inqry_read(file);
+		break;
+	default:
+		spin_unlock_irq(&file->lock);
+		return -EINVAL;
+	}
+	spin_unlock_irq(&file->lock);
+	ret = snprintf(tbuf, HPRE_DBGFS_VAL_MAX_LEN, "%u\n", val);
+	return simple_read_from_buffer(buf, count, pos, tbuf, ret);
+}
+
+static ssize_t hpre_ctrl_debug_write(struct file *filp, const char __user *buf,
+				size_t count, loff_t *pos)
+{
+	struct hpre_debugfs_file *file = filp->private_data;
+	char tbuf[HPRE_DBGFS_VAL_MAX_LEN];
+	unsigned long val;
+	int len, ret;
+
+	if (*pos != 0)
+		return 0;
+
+	if (count >= HPRE_DBGFS_VAL_MAX_LEN)
+		return -ENOSPC;
+
+	len = simple_write_to_buffer(tbuf, HPRE_DBGFS_VAL_MAX_LEN - 1,
+				     pos, buf, count);
+	if (len < 0)
+		return len;
+
+	tbuf[len] = '\0';
+	if (kstrtoul(tbuf, 0, &val))
+		return -EFAULT;
+
+	spin_lock_irq(&file->lock);
+	switch (file->type) {
+	case HPRE_CURRENT_QM:
+		ret = hpre_current_qm_write(file, val);
+		if (ret)
+			goto err_input;
+		break;
+	case HPRE_CLEAR_ENABLE:
+		ret = hpre_clear_enable_write(file, val);
+		if (ret)
+			goto err_input;
+		break;
+	case HPRE_CLUSTER_CTRL:
+		ret = hpre_cluster_inqry_write(file, val);
+		if (ret)
+			goto err_input;
+		break;
+	default:
+		ret = -EINVAL;
+		goto err_input;
+	}
+	spin_unlock_irq(&file->lock);
+
+	return count;
+
+err_input:
+	spin_unlock_irq(&file->lock);
+	return ret;
+}
+
+static const struct file_operations hpre_ctrl_debug_fops = {
+	.owner = THIS_MODULE,
+	.open = simple_open,
+	.read = hpre_ctrl_debug_read,
+	.write = hpre_ctrl_debug_write,
+};
+
+static int hpre_create_debugfs_file(struct hpre_debug *dbg, struct dentry *dir,
+				    enum hpre_ctrl_dbgfs_file type, int indx)
+{
+	struct dentry *file_dir;
+
+	if (dir)
+		file_dir = dir;
+	else
+		file_dir = dbg->debug_root;
+
+	if (type >= HPRE_DEBUG_FILE_NUM)
+		return -EINVAL;
+
+	spin_lock_init(&dbg->files[indx].lock);
+	dbg->files[indx].debug = dbg;
+	dbg->files[indx].type = type;
+	dbg->files[indx].index = indx;
+	debugfs_create_file(hpre_debug_file_name[type], 0600, file_dir,
+			    dbg->files + indx, &hpre_ctrl_debug_fops);
+
+	return 0;
+}
+
+static int hpre_pf_comm_regs_debugfs_init(struct hpre_debug *debug)
+{
+	struct hpre *hpre = container_of(debug, struct hpre, debug);
+	struct hisi_qm *qm = &hpre->qm;
+	struct device *dev = &qm->pdev->dev;
+	struct debugfs_regset32 *regset;
+
+	regset = devm_kzalloc(dev, sizeof(*regset), GFP_KERNEL);
+	if (!regset)
+		return -ENOMEM;
+
+	regset->regs = hpre_com_dfx_regs;
+	regset->nregs = ARRAY_SIZE(hpre_com_dfx_regs);
+	regset->base = qm->io_base;
+
+	debugfs_create_regset32("regs", 0444,  debug->debug_root, regset);
+	return 0;
+}
+
+static int hpre_cluster_debugfs_init(struct hpre_debug *debug)
+{
+	struct hpre *hpre = container_of(debug, struct hpre, debug);
+	struct hisi_qm *qm = &hpre->qm;
+	struct device *dev = &qm->pdev->dev;
+	char buf[HPRE_DBGFS_VAL_MAX_LEN];
+	struct debugfs_regset32 *regset;
+	struct dentry *tmp_d;
+	int i, ret;
+
+	for (i = 0; i < HPRE_CLUSTERS_NUM; i++) {
+		ret = snprintf(buf, HPRE_DBGFS_VAL_MAX_LEN, "cluster%d", i);
+		if (ret < 0)
+			return -EINVAL;
+		tmp_d = debugfs_create_dir(buf, debug->debug_root);
+
+		regset = devm_kzalloc(dev, sizeof(*regset), GFP_KERNEL);
+		if (!regset)
+			return -ENOMEM;
+
+		regset->regs = hpre_cluster_dfx_regs;
+		regset->nregs = ARRAY_SIZE(hpre_cluster_dfx_regs);
+		regset->base = qm->io_base + hpre_cluster_offsets[i];
+
+		debugfs_create_regset32("regs", 0444, tmp_d, regset);
+		ret = hpre_create_debugfs_file(debug, tmp_d, HPRE_CLUSTER_CTRL,
+					       i + HPRE_CLUSTER_CTRL);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int hpre_ctrl_debug_init(struct hpre_debug *debug)
+{
+	int ret;
+
+	ret = hpre_create_debugfs_file(debug, NULL, HPRE_CURRENT_QM,
+				       HPRE_CURRENT_QM);
+	if (ret)
+		return ret;
+
+	ret = hpre_create_debugfs_file(debug, NULL, HPRE_CLEAR_ENABLE,
+				       HPRE_CLEAR_ENABLE);
+	if (ret)
+		return ret;
+
+	ret = hpre_pf_comm_regs_debugfs_init(debug);
+	if (ret)
+		return ret;
+
+	return hpre_cluster_debugfs_init(debug);
+}
+
+static int hpre_debugfs_init(struct hpre *hpre)
+{
+	struct hisi_qm *qm = &hpre->qm;
+	struct device *dev = &qm->pdev->dev;
+	struct dentry *dir;
+	int ret;
+
+	dir = debugfs_create_dir(dev_name(dev), hpre_debugfs_root);
+	qm->debug.debug_root = dir;
+
+	ret = hisi_qm_debug_init(qm);
+	if (ret)
+		goto failed_to_create;
+
+	if (qm->pdev->device == HPRE_PCI_DEVICE_ID) {
+		hpre->debug.debug_root = dir;
+		ret = hpre_ctrl_debug_init(&hpre->debug);
+		if (ret)
+			goto failed_to_create;
+	}
+	return 0;
+
+failed_to_create:
+	debugfs_remove_recursive(qm->debug.debug_root);
+	return ret;
+}
+
+static void hpre_debugfs_exit(struct hpre *hpre)
+{
+	struct hisi_qm *qm = &hpre->qm;
+
+	debugfs_remove_recursive(qm->debug.debug_root);
+}
+
+static int hpre_qm_pre_init(struct hisi_qm *qm, struct pci_dev *pdev)
+{
+	enum qm_hw_ver rev_id;
+
+	rev_id = hisi_qm_get_hw_version(pdev);
+	if (rev_id < 0)
+		return -ENODEV;
+
+	if (rev_id == QM_HW_V1) {
+		pci_warn(pdev, "HPRE version 1 is not supported!\n");
+		return -EINVAL;
+	}
+
+	qm->pdev = pdev;
+	qm->ver = rev_id;
+	qm->sqe_size = HPRE_SQE_SIZE;
+	qm->dev_name = hpre_name;
+	qm->fun_type = (pdev->device == HPRE_PCI_DEVICE_ID) ?
+		       QM_HW_PF : QM_HW_VF;
+	if (pdev->is_physfn) {
+		qm->qp_base = HPRE_PF_DEF_Q_BASE;
+		qm->qp_num = hpre_pf_q_num;
+	}
+	qm->use_dma_api = true;
+
+	return 0;
+}
+
+static const struct hisi_qm_err_ini hpre_err_ini = {
+	.hw_err_enable	= hpre_hw_error_enable,
+	.hw_err_disable	= hpre_hw_error_disable,
+	.err_info	= {
+		.ce		= QM_BASE_CE,
+		.nfe		= QM_BASE_NFE | QM_ACC_DO_TASK_TIMEOUT,
+		.fe		= 0,
+		.msi		= QM_DB_RANDOM_INVALID,
+	}
+};
+
+static int hpre_pf_probe_init(struct hpre *hpre)
+{
+	struct hisi_qm *qm = &hpre->qm;
+	int ret;
+
+	qm->ctrl_qp_num = HPRE_QUEUE_NUM_V2;
+
+	ret = hpre_set_user_domain_and_cache(hpre);
+	if (ret)
+		return ret;
+
+	qm->err_ini = &hpre_err_ini;
+	hisi_qm_dev_err_init(qm);
+
+	return 0;
+}
+
+static int hpre_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	struct hisi_qm *qm;
+	struct hpre *hpre;
+	int ret;
+
+	hpre = devm_kzalloc(&pdev->dev, sizeof(*hpre), GFP_KERNEL);
+	if (!hpre)
+		return -ENOMEM;
+
+	pci_set_drvdata(pdev, hpre);
+
+	qm = &hpre->qm;
+	ret = hpre_qm_pre_init(qm, pdev);
+	if (ret)
+		return ret;
+
+	ret = hisi_qm_init(qm);
+	if (ret)
+		return ret;
+
+	if (pdev->is_physfn) {
+		ret = hpre_pf_probe_init(hpre);
+		if (ret)
+			goto err_with_qm_init;
+	} else if (qm->fun_type == QM_HW_VF && qm->ver == QM_HW_V2) {
+		/* v2 starts to support get vft by mailbox */
+		ret = hisi_qm_get_vft(qm, &qm->qp_base, &qm->qp_num);
+		if (ret)
+			goto err_with_qm_init;
+	}
+
+	ret = hisi_qm_start(qm);
+	if (ret)
+		goto err_with_err_init;
+
+	ret = hpre_debugfs_init(hpre);
+	if (ret)
+		dev_warn(&pdev->dev, "init debugfs fail!\n");
+
+	hpre_add_to_list(hpre);
+
+	ret = hpre_algs_register();
+	if (ret < 0) {
+		hpre_remove_from_list(hpre);
+		pci_err(pdev, "fail to register algs to crypto!\n");
+		goto err_with_qm_start;
+	}
+	return 0;
+
+err_with_qm_start:
+	hisi_qm_stop(qm);
+
+err_with_err_init:
+	hisi_qm_dev_err_uninit(qm);
+
+err_with_qm_init:
+	hisi_qm_uninit(qm);
+
+	return ret;
+}
+
+static int hpre_vf_q_assign(struct hpre *hpre, int num_vfs)
+{
+	struct hisi_qm *qm = &hpre->qm;
+	u32 qp_num = qm->qp_num;
+	int q_num, remain_q_num, i;
+	u32 q_base = qp_num;
+	int ret;
+
+	if (!num_vfs)
+		return -EINVAL;
+
+	remain_q_num = qm->ctrl_qp_num - qp_num;
+
+	/* If remaining queues are not enough, return error. */
+	if (remain_q_num < num_vfs)
+		return -EINVAL;
+
+	q_num = remain_q_num / num_vfs;
+	for (i = 1; i <= num_vfs; i++) {
+		if (i == num_vfs)
+			q_num += remain_q_num % num_vfs;
+		ret = hisi_qm_set_vft(qm, i, q_base, (u32)q_num);
+		if (ret)
+			return ret;
+		q_base += q_num;
+	}
+
+	return 0;
+}
+
+static int hpre_clear_vft_config(struct hpre *hpre)
+{
+	struct hisi_qm *qm = &hpre->qm;
+	u32 num_vfs = hpre->num_vfs;
+	int ret;
+	u32 i;
+
+	for (i = 1; i <= num_vfs; i++) {
+		ret = hisi_qm_set_vft(qm, i, 0, 0);
+		if (ret)
+			return ret;
+	}
+	hpre->num_vfs = 0;
+
+	return 0;
+}
+
+static int hpre_sriov_enable(struct pci_dev *pdev, int max_vfs)
+{
+	struct hpre *hpre = pci_get_drvdata(pdev);
+	int pre_existing_vfs, num_vfs, ret;
+
+	pre_existing_vfs = pci_num_vf(pdev);
+	if (pre_existing_vfs) {
+		pci_err(pdev,
+			"Can't enable VF. Please disable pre-enabled VFs!\n");
+		return 0;
+	}
+
+	num_vfs = min_t(int, max_vfs, HPRE_VF_NUM);
+	ret = hpre_vf_q_assign(hpre, num_vfs);
+	if (ret) {
+		pci_err(pdev, "Can't assign queues for VF!\n");
+		return ret;
+	}
+
+	hpre->num_vfs = num_vfs;
+
+	ret = pci_enable_sriov(pdev, num_vfs);
+	if (ret) {
+		pci_err(pdev, "Can't enable VF!\n");
+		hpre_clear_vft_config(hpre);
+		return ret;
+	}
+
+	return num_vfs;
+}
+
+static int hpre_sriov_disable(struct pci_dev *pdev)
+{
+	struct hpre *hpre = pci_get_drvdata(pdev);
+
+	if (pci_vfs_assigned(pdev)) {
+		pci_err(pdev, "Failed to disable VFs while VFs are assigned!\n");
+		return -EPERM;
+	}
+
+	/* remove in hpre_pci_driver will be called to free VF resources */
+	pci_disable_sriov(pdev);
+
+	return hpre_clear_vft_config(hpre);
+}
+
+static int hpre_sriov_configure(struct pci_dev *pdev, int num_vfs)
+{
+	if (num_vfs)
+		return hpre_sriov_enable(pdev, num_vfs);
+	else
+		return hpre_sriov_disable(pdev);
+}
+
+static void hpre_remove(struct pci_dev *pdev)
+{
+	struct hpre *hpre = pci_get_drvdata(pdev);
+	struct hisi_qm *qm = &hpre->qm;
+	int ret;
+
+	hpre_algs_unregister();
+	hpre_remove_from_list(hpre);
+	if (qm->fun_type == QM_HW_PF && hpre->num_vfs != 0) {
+		ret = hpre_sriov_disable(pdev);
+		if (ret) {
+			pci_err(pdev, "Disable SRIOV fail!\n");
+			return;
+		}
+	}
+	if (qm->fun_type == QM_HW_PF) {
+		hpre_cnt_regs_clear(qm);
+		qm->debug.curr_qm_qp_num = 0;
+	}
+
+	hpre_debugfs_exit(hpre);
+	hisi_qm_stop(qm);
+	hisi_qm_dev_err_uninit(qm);
+	hisi_qm_uninit(qm);
+}
+
+static void hpre_log_hw_error(struct hpre *hpre, u32 err_sts)
+{
+	const struct hpre_hw_error *err = hpre_hw_errors;
+	struct device *dev = &hpre->qm.pdev->dev;
+
+	while (err->msg) {
+		if (err->int_msk & err_sts)
+			dev_warn(dev, "%s [error status=0x%x] found\n",
+				 err->msg, err->int_msk);
+		err++;
+	}
+}
+
+static pci_ers_result_t hpre_hw_error_handle(struct hpre *hpre)
+{
+	u32 err_sts;
+
+	/* read err sts */
+	err_sts = readl(hpre->qm.io_base + HPRE_HAC_INT_STATUS);
+	if (err_sts) {
+		hpre_log_hw_error(hpre, err_sts);
+
+		/* clear error interrupts */
+		writel(err_sts, hpre->qm.io_base + HPRE_HAC_SOURCE_INT);
+		return PCI_ERS_RESULT_NEED_RESET;
+	}
+
+	return PCI_ERS_RESULT_RECOVERED;
+}
+
+static pci_ers_result_t hpre_process_hw_error(struct pci_dev *pdev)
+{
+	struct hpre *hpre = pci_get_drvdata(pdev);
+	pci_ers_result_t qm_ret, hpre_ret;
+
+	/* log qm error */
+	qm_ret = hisi_qm_hw_error_handle(&hpre->qm);
+
+	/* log hpre error */
+	hpre_ret = hpre_hw_error_handle(hpre);
+
+	return (qm_ret == PCI_ERS_RESULT_NEED_RESET ||
+		hpre_ret == PCI_ERS_RESULT_NEED_RESET) ?
+		PCI_ERS_RESULT_NEED_RESET : PCI_ERS_RESULT_RECOVERED;
+}
+
+static pci_ers_result_t hpre_error_detected(struct pci_dev *pdev,
+					    pci_channel_state_t state)
+{
+	pci_info(pdev, "PCI error detected, state(=%d)!!\n", state);
+	if (state == pci_channel_io_perm_failure)
+		return PCI_ERS_RESULT_DISCONNECT;
+
+	return hpre_process_hw_error(pdev);
+}
+
+static const struct pci_error_handlers hpre_err_handler = {
+	.error_detected		= hpre_error_detected,
+};
+
+static struct pci_driver hpre_pci_driver = {
+	.name			= hpre_name,
+	.id_table		= hpre_dev_ids,
+	.probe			= hpre_probe,
+	.remove			= hpre_remove,
+	.sriov_configure	= hpre_sriov_configure,
+	.err_handler		= &hpre_err_handler,
+};
+
+static void hpre_register_debugfs(void)
+{
+	if (!debugfs_initialized())
+		return;
+
+	hpre_debugfs_root = debugfs_create_dir(hpre_name, NULL);
+}
+
+static void hpre_unregister_debugfs(void)
+{
+	debugfs_remove_recursive(hpre_debugfs_root);
+}
+
+static int __init hpre_init(void)
+{
+	int ret;
+
+	hpre_register_debugfs();
+
+	ret = pci_register_driver(&hpre_pci_driver);
+	if (ret) {
+		hpre_unregister_debugfs();
+		pr_err("hpre: can't register hisi hpre driver.\n");
+	}
+
+	return ret;
+}
+
+static void __exit hpre_exit(void)
+{
+	pci_unregister_driver(&hpre_pci_driver);
+	hpre_unregister_debugfs();
+}
+
+module_init(hpre_init);
+module_exit(hpre_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Zaibo Xu <xuzaibo@huawei.com>");
+MODULE_DESCRIPTION("Driver for HiSilicon HPRE accelerator");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/hisilicon/qm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/hisilicon/qm.c
@@ -59,17 +59,17 @@
 #define QM_CQ_PHASE_SHIFT		0
 #define QM_CQ_FLAG_SHIFT		1
 
-#define QM_CQE_PHASE(cqe)		((cqe)->w7 & 0x1)
+#define QM_CQE_PHASE(cqe)		(le16_to_cpu((cqe)->w7) & 0x1)
 #define QM_QC_CQE_SIZE			4
 
 /* eqc shift */
 #define QM_EQE_AEQE_SIZE		(2UL << 12)
 #define QM_EQC_PHASE_SHIFT		16
 
-#define QM_EQE_PHASE(eqe)		(((eqe)->dw0 >> 16) & 0x1)
+#define QM_EQE_PHASE(eqe)		((le32_to_cpu((eqe)->dw0) >> 16) & 0x1)
 #define QM_EQE_CQN_MASK			GENMASK(15, 0)
 
-#define QM_AEQE_PHASE(aeqe)		(((aeqe)->dw0 >> 16) & 0x1)
+#define QM_AEQE_PHASE(aeqe)		((le32_to_cpu((aeqe)->dw0) >> 16) & 0x1)
 #define QM_AEQE_TYPE_SHIFT		17
 
 #define QM_DOORBELL_CMD_SQ		0
@@ -169,17 +169,17 @@
 #define QM_MK_SQC_DW3_V2(sqe_sz) \
 	((QM_Q_DEPTH - 1) | ((u32)ilog2(sqe_sz) << QM_SQ_SQE_SIZE_SHIFT))
 
-#define INIT_QC_COMMON(qc, base, pasid) do {	\
-	(qc)->head = 0;				\
-	(qc)->tail = 0;				\
-	(qc)->base_l = lower_32_bits(base);	\
-	(qc)->base_h = upper_32_bits(base);	\
-	(qc)->dw3 = 0;				\
-	(qc)->w8 = 0;				\
-	(qc)->rsvd0 = 0;			\
-	(qc)->pasid = pasid;			\
-	(qc)->w11 = 0;				\
-	(qc)->rsvd1 = 0;			\
+#define INIT_QC_COMMON(qc, base, pasid) do {			\
+	(qc)->head = 0;						\
+	(qc)->tail = 0;						\
+	(qc)->base_l = cpu_to_le32(lower_32_bits(base));	\
+	(qc)->base_h = cpu_to_le32(upper_32_bits(base));	\
+	(qc)->dw3 = 0;						\
+	(qc)->w8 = 0;						\
+	(qc)->rsvd0 = 0;					\
+	(qc)->pasid = cpu_to_le16(pasid);			\
+	(qc)->w11 = 0;						\
+	(qc)->rsvd1 = 0;					\
 } while (0)
 
 enum vft_type {
@@ -277,6 +277,7 @@
 	int (*debug_init)(struct hisi_qm *qm);
 	void (*hw_error_init)(struct hisi_qm *qm, u32 ce, u32 nfe, u32 fe,
 			      u32 msi);
+	void (*hw_error_uninit)(struct hisi_qm *qm);
 	pci_ers_result_t (*hw_error_handle)(struct hisi_qm *qm);
 };
 
@@ -331,12 +332,18 @@
 	void __iomem *fun_base = qm->io_base + QM_MB_CMD_SEND_BASE;
 	unsigned long tmp0 = 0, tmp1 = 0;
 
+	if (!IS_ENABLED(CONFIG_ARM64)) {
+		memcpy_toio(fun_base, src, 16);
+		wmb();
+		return;
+	}
+
 	asm volatile("ldp %0, %1, %3\n"
 		     "stp %0, %1, %2\n"
 		     "dsb sy\n"
 		     : "=&r" (tmp0),
 		       "=&r" (tmp1),
-		       "+Q" (*((char *)fun_base))
+		       "+Q" (*((char __iomem *)fun_base))
 		     : "Q" (*((char *)src))
 		     : "memory");
 }
@@ -350,12 +357,12 @@
 	dev_dbg(&qm->pdev->dev, "QM mailbox request to q%u: %u-%llx\n",
 		queue, cmd, (unsigned long long)dma_addr);
 
-	mailbox.w0 = cmd |
+	mailbox.w0 = cpu_to_le16(cmd |
 		     (op ? 0x1 << QM_MB_OP_SHIFT : 0) |
-		     (0x1 << QM_MB_BUSY_SHIFT);
-	mailbox.queue_num = queue;
-	mailbox.base_l = lower_32_bits(dma_addr);
-	mailbox.base_h = upper_32_bits(dma_addr);
+		     (0x1 << QM_MB_BUSY_SHIFT));
+	mailbox.queue_num = cpu_to_le16(queue);
+	mailbox.base_l = cpu_to_le32(lower_32_bits(dma_addr));
+	mailbox.base_h = cpu_to_le32(upper_32_bits(dma_addr));
 	mailbox.rsvd = 0;
 
 	mutex_lock(&qm->mailbox_lock);
@@ -442,7 +449,7 @@
 
 static struct hisi_qp *qm_to_hisi_qp(struct hisi_qm *qm, struct qm_eqe *eqe)
 {
-	u16 cqn = eqe->dw0 & QM_EQE_CQN_MASK;
+	u16 cqn = le32_to_cpu(eqe->dw0) & QM_EQE_CQN_MASK;
 
 	return qm->qp_array[cqn];
 }
@@ -464,7 +471,8 @@
 	if (qp->req_cb) {
 		while (QM_CQE_PHASE(cqe) == qp->qp_status.cqc_phase) {
 			dma_rmb();
-			qp->req_cb(qp, qp->sqe + qm->sqe_size * cqe->sq_head);
+			qp->req_cb(qp, qp->sqe + qm->sqe_size *
+				   le16_to_cpu(cqe->sq_head));
 			qm_cq_head_update(qp);
 			cqe = qp->cqe + qp->qp_status.cq_head;
 			qm_db(qm, qp->qp_id, QM_DOORBELL_CMD_CQ,
@@ -478,17 +486,9 @@
 	}
 }
 
-static void qm_qp_work_func(struct work_struct *work)
-{
-	struct hisi_qp *qp;
-
-	qp = container_of(work, struct hisi_qp, work);
-	qm_poll_qp(qp, qp->qm);
-}
-
-static irqreturn_t qm_irq_handler(int irq, void *data)
+static void qm_work_process(struct work_struct *work)
 {
-	struct hisi_qm *qm = data;
+	struct hisi_qm *qm = container_of(work, struct hisi_qm, work);
 	struct qm_eqe *eqe = qm->eqe + qm->status.eq_head;
 	struct hisi_qp *qp;
 	int eqe_num = 0;
@@ -497,7 +497,7 @@
 		eqe_num++;
 		qp = qm_to_hisi_qp(qm, eqe);
 		if (qp)
-			queue_work(qp->wq, &qp->work);
+			qm_poll_qp(qp, qm);
 
 		if (qm->status.eq_head == QM_Q_DEPTH - 1) {
 			qm->status.eqc_phase = !qm->status.eqc_phase;
@@ -515,6 +515,17 @@
 	}
 
 	qm_db(qm, 0, QM_DOORBELL_CMD_EQ, qm->status.eq_head, 0);
+}
+
+static irqreturn_t do_qm_irq(int irq, void *data)
+{
+	struct hisi_qm *qm = (struct hisi_qm *)data;
+
+	/* the workqueue created by device driver of QM */
+	if (qm->wq)
+		queue_work(qm->wq, &qm->work);
+	else
+		schedule_work(&qm->work);
 
 	return IRQ_HANDLED;
 }
@@ -524,7 +535,7 @@
 	struct hisi_qm *qm = data;
 
 	if (readl(qm->io_base + QM_VF_EQ_INT_SOURCE))
-		return qm_irq_handler(irq, data);
+		return do_qm_irq(irq, data);
 
 	dev_err(&qm->pdev->dev, "invalid int source\n");
 	qm_db(qm, 0, QM_DOORBELL_CMD_EQ, qm->status.eq_head, 0);
@@ -542,7 +553,7 @@
 		return IRQ_NONE;
 
 	while (QM_AEQE_PHASE(aeqe) == qm->status.aeqc_phase) {
-		type = aeqe->dw0 >> QM_AEQE_TYPE_SHIFT;
+		type = le32_to_cpu(aeqe->dw0) >> QM_AEQE_TYPE_SHIFT;
 		if (type < ARRAY_SIZE(qm_fifo_overflow))
 			dev_err(&qm->pdev->dev, "%s overflow\n",
 				qm_fifo_overflow[type]);
@@ -646,7 +657,7 @@
 
 	qp_status->sq_tail = 0;
 	qp_status->cq_head = 0;
-	qp_status->cqc_phase = 1;
+	qp_status->cqc_phase = true;
 	qp_status->flags = 0;
 }
 
@@ -963,13 +974,11 @@
 
 static int qm_create_debugfs_file(struct hisi_qm *qm, enum qm_debug_file index)
 {
-	struct dentry *qm_d = qm->debug.qm_d, *tmp;
+	struct dentry *qm_d = qm->debug.qm_d;
 	struct debugfs_file *file = qm->debug.files + index;
 
-	tmp = debugfs_create_file(qm_debug_file_name[index], 0600, qm_d, file,
-				  &qm_debug_fops);
-	if (IS_ERR(tmp))
-		return -ENOENT;
+	debugfs_create_file(qm_debug_file_name[index], 0600, qm_d, file,
+			    &qm_debug_fops);
 
 	file->index = index;
 	mutex_init(&file->lock);
@@ -981,9 +990,6 @@
 static void qm_hw_error_init_v1(struct hisi_qm *qm, u32 ce, u32 nfe, u32 fe,
 				u32 msi)
 {
-	dev_info(&qm->pdev->dev,
-		 "QM v%d does not support hw error handle\n", qm->ver);
-
 	writel(QM_ABNORMAL_INT_MASK_VALUE, qm->io_base + QM_ABNORMAL_INT_MASK);
 }
 
@@ -1009,6 +1015,11 @@
 	writel(irq_unmask, qm->io_base + QM_ABNORMAL_INT_MASK);
 }
 
+static void qm_hw_error_uninit_v2(struct hisi_qm *qm)
+{
+	writel(QM_ABNORMAL_INT_MASK_VALUE, qm->io_base + QM_ABNORMAL_INT_MASK);
+}
+
 static void qm_log_hw_error(struct hisi_qm *qm, u32 error_status)
 {
 	const struct hisi_qm_hw_error *err = qm_hw_error;
@@ -1080,6 +1091,7 @@
 	.qm_db = qm_db_v2,
 	.get_irq_num = qm_get_irq_num_v2,
 	.hw_error_init = qm_hw_error_init_v2,
+	.hw_error_uninit = qm_hw_error_uninit_v2,
 	.hw_error_handle = qm_hw_error_handle_v2,
 };
 
@@ -1123,6 +1135,7 @@
 	}
 	set_bit(qp_id, qm->qp_bitmap);
 	qm->qp_array[qp_id] = qp;
+	qm->qp_in_used++;
 
 	write_unlock(&qm->qps_lock);
 
@@ -1144,20 +1157,9 @@
 
 	qp->qp_id = qp_id;
 	qp->alg_type = alg_type;
-	INIT_WORK(&qp->work, qm_qp_work_func);
-	qp->wq = alloc_workqueue("hisi_qm", WQ_UNBOUND | WQ_HIGHPRI |
-				 WQ_CPU_INTENSIVE | WQ_MEM_RECLAIM, 0);
-	if (!qp->wq) {
-		ret = -EFAULT;
-		goto err_free_qp_mem;
-	}
 
 	return qp;
 
-err_free_qp_mem:
-	if (qm->use_dma_api)
-		dma_free_coherent(dev, qp->qdma.size, qp->qdma.va,
-				  qp->qdma.dma);
 err_clear_bit:
 	write_lock(&qm->qps_lock);
 	qm->qp_array[qp_id] = NULL;
@@ -1187,6 +1189,7 @@
 	write_lock(&qm->qps_lock);
 	qm->qp_array[qp->qp_id] = NULL;
 	clear_bit(qp->qp_id, qm->qp_bitmap);
+	qm->qp_in_used--;
 	write_unlock(&qm->qps_lock);
 
 	kfree(qp);
@@ -1218,14 +1221,14 @@
 
 	INIT_QC_COMMON(sqc, qp->sqe_dma, pasid);
 	if (ver == QM_HW_V1) {
-		sqc->dw3 = QM_MK_SQC_DW3_V1(0, 0, 0, qm->sqe_size);
-		sqc->w8 = QM_Q_DEPTH - 1;
+		sqc->dw3 = cpu_to_le32(QM_MK_SQC_DW3_V1(0, 0, 0, qm->sqe_size));
+		sqc->w8 = cpu_to_le16(QM_Q_DEPTH - 1);
 	} else if (ver == QM_HW_V2) {
-		sqc->dw3 = QM_MK_SQC_DW3_V2(qm->sqe_size);
+		sqc->dw3 = cpu_to_le32(QM_MK_SQC_DW3_V2(qm->sqe_size));
 		sqc->w8 = 0; /* rand_qc */
 	}
-	sqc->cq_num = qp_id;
-	sqc->w13 = QM_MK_SQC_W13(0, 1, qp->alg_type);
+	sqc->cq_num = cpu_to_le16(qp_id);
+	sqc->w13 = cpu_to_le16(QM_MK_SQC_W13(0, 1, qp->alg_type));
 
 	ret = qm_mb(qm, QM_MB_CMD_SQC, sqc_dma, qp_id, 0);
 	dma_unmap_single(dev, sqc_dma, sizeof(struct qm_sqc), DMA_TO_DEVICE);
@@ -1245,13 +1248,13 @@
 
 	INIT_QC_COMMON(cqc, qp->cqe_dma, pasid);
 	if (ver == QM_HW_V1) {
-		cqc->dw3 = QM_MK_CQC_DW3_V1(0, 0, 0, 4);
-		cqc->w8 = QM_Q_DEPTH - 1;
+		cqc->dw3 = cpu_to_le32(QM_MK_CQC_DW3_V1(0, 0, 0, 4));
+		cqc->w8 = cpu_to_le16(QM_Q_DEPTH - 1);
 	} else if (ver == QM_HW_V2) {
-		cqc->dw3 = QM_MK_CQC_DW3_V2(4);
+		cqc->dw3 = cpu_to_le32(QM_MK_CQC_DW3_V2(4));
 		cqc->w8 = 0;
 	}
-	cqc->dw6 = 1 << QM_CQ_PHASE_SHIFT | 1 << QM_CQ_FLAG_SHIFT;
+	cqc->dw6 = cpu_to_le32(1 << QM_CQ_PHASE_SHIFT | 1 << QM_CQ_FLAG_SHIFT);
 
 	ret = qm_mb(qm, QM_MB_CMD_CQC, cqc_dma, qp_id, 0);
 	dma_unmap_single(dev, cqc_dma, sizeof(struct qm_cqc), DMA_TO_DEVICE);
@@ -1392,6 +1395,24 @@
 }
 
 /**
+ * hisi_qm_get_free_qp_num() - Get free number of qp in qm.
+ * @qm: The qm which want to get free qp.
+ *
+ * This function return free number of qp in qm.
+ */
+int hisi_qm_get_free_qp_num(struct hisi_qm *qm)
+{
+	int ret;
+
+	read_lock(&qm->qps_lock);
+	ret = qm->qp_num - qm->qp_in_used;
+	read_unlock(&qm->qps_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(hisi_qm_get_free_qp_num);
+
+/**
  * hisi_qm_init() - Initialize configures about qm.
  * @qm: The qm needing init.
  *
@@ -1454,8 +1475,10 @@
 	if (ret)
 		goto err_free_irq_vectors;
 
+	qm->qp_in_used = 0;
 	mutex_init(&qm->mailbox_lock);
 	rwlock_init(&qm->qps_lock);
+	INIT_WORK(&qm->work, qm_work_process);
 
 	dev_dbg(dev, "init qm %s with %s\n", pdev->is_physfn ? "pf" : "vf",
 		qm->use_dma_api ? "dma api" : "iommu api");
@@ -1560,8 +1583,8 @@
 
 	status->eq_head = 0;
 	status->aeq_head = 0;
-	status->eqc_phase = 1;
-	status->aeqc_phase = 1;
+	status->eqc_phase = true;
+	status->aeqc_phase = true;
 }
 
 static int qm_eq_ctx_cfg(struct hisi_qm *qm)
@@ -1585,11 +1608,11 @@
 		return -ENOMEM;
 	}
 
-	eqc->base_l = lower_32_bits(qm->eqe_dma);
-	eqc->base_h = upper_32_bits(qm->eqe_dma);
+	eqc->base_l = cpu_to_le32(lower_32_bits(qm->eqe_dma));
+	eqc->base_h = cpu_to_le32(upper_32_bits(qm->eqe_dma));
 	if (qm->ver == QM_HW_V1)
-		eqc->dw3 = QM_EQE_AEQE_SIZE;
-	eqc->dw6 = (QM_Q_DEPTH - 1) | (1 << QM_EQC_PHASE_SHIFT);
+		eqc->dw3 = cpu_to_le32(QM_EQE_AEQE_SIZE);
+	eqc->dw6 = cpu_to_le32((QM_Q_DEPTH - 1) | (1 << QM_EQC_PHASE_SHIFT));
 	ret = qm_mb(qm, QM_MB_CMD_EQC, eqc_dma, 0, 0);
 	dma_unmap_single(dev, eqc_dma, sizeof(struct qm_eqc), DMA_TO_DEVICE);
 	kfree(eqc);
@@ -1606,9 +1629,9 @@
 		return -ENOMEM;
 	}
 
-	aeqc->base_l = lower_32_bits(qm->aeqe_dma);
-	aeqc->base_h = upper_32_bits(qm->aeqe_dma);
-	aeqc->dw6 = (QM_Q_DEPTH - 1) | (1 << QM_EQC_PHASE_SHIFT);
+	aeqc->base_l = cpu_to_le32(lower_32_bits(qm->aeqe_dma));
+	aeqc->base_h = cpu_to_le32(upper_32_bits(qm->aeqe_dma));
+	aeqc->dw6 = cpu_to_le32((QM_Q_DEPTH - 1) | (1 << QM_EQC_PHASE_SHIFT));
 
 	ret = qm_mb(qm, QM_MB_CMD_AEQC, aeqc_dma, 0, 0);
 	dma_unmap_single(dev, aeqc_dma, sizeof(struct qm_aeqc), DMA_TO_DEVICE);
@@ -1780,12 +1803,10 @@
  */
 int hisi_qm_debug_init(struct hisi_qm *qm)
 {
-	struct dentry *qm_d, *qm_regs;
+	struct dentry *qm_d;
 	int i, ret;
 
 	qm_d = debugfs_create_dir("qm", qm->debug.debug_root);
-	if (IS_ERR(qm_d))
-		return -ENOENT;
 	qm->debug.qm_d = qm_d;
 
 	/* only show this in PF */
@@ -1796,12 +1817,7 @@
 				goto failed_to_create;
 			}
 
-	qm_regs = debugfs_create_file("qm_regs", 0444, qm->debug.qm_d, qm,
-				      &qm_regs_fops);
-	if (IS_ERR(qm_regs)) {
-		ret = -ENOENT;
-		goto failed_to_create;
-	}
+	debugfs_create_file("qm_regs", 0444, qm->debug.qm_d, qm, &qm_regs_fops);
 
 	return 0;
 
@@ -1840,36 +1856,28 @@
 }
 EXPORT_SYMBOL_GPL(hisi_qm_debug_regs_clear);
 
-/**
- * hisi_qm_hw_error_init() - Configure qm hardware error report method.
- * @qm: The qm which we want to configure.
- * @ce: Bit mask of correctable error configure.
- * @nfe: Bit mask of non-fatal error configure.
- * @fe: Bit mask of fatal error configure.
- * @msi: Bit mask of error reported by message signal interrupt.
- *
- * Hardware errors of qm can be reported either by RAS interrupts which will
- * be handled by UEFI and then PCIe AER or by device MSI. User can configure
- * each error to use either of above two methods. For RAS interrupts, we can
- * configure an error as one of correctable error, non-fatal error or
- * fatal error.
- *
- * Bits indicating errors can be configured to ce, nfe, fe and msi to enable
- * related report methods. Error report will be masked if related error bit
- * does not configure.
- */
-void hisi_qm_hw_error_init(struct hisi_qm *qm, u32 ce, u32 nfe, u32 fe,
-			   u32 msi)
+static void qm_hw_error_init(struct hisi_qm *qm)
 {
+	const struct hisi_qm_err_info *err_info = &qm->err_ini->err_info;
+
 	if (!qm->ops->hw_error_init) {
-		dev_err(&qm->pdev->dev, "QM version %d doesn't support hw error handling!\n",
-			qm->ver);
+		dev_err(&qm->pdev->dev, "QM doesn't support hw error handling!\n");
+		return;
+	}
+
+	qm->ops->hw_error_init(qm, err_info->ce, err_info->nfe,
+			       err_info->fe, err_info->msi);
+}
+
+static void qm_hw_error_uninit(struct hisi_qm *qm)
+{
+	if (!qm->ops->hw_error_uninit) {
+		dev_err(&qm->pdev->dev, "Unexpected QM hw error uninit!\n");
 		return;
 	}
 
-	qm->ops->hw_error_init(qm, ce, nfe, fe, msi);
+	qm->ops->hw_error_uninit(qm);
 }
-EXPORT_SYMBOL_GPL(hisi_qm_hw_error_init);
 
 /**
  * hisi_qm_hw_error_handle() - Handle qm non-fatal hardware errors.
@@ -1877,11 +1885,10 @@
  *
  * Accelerators use this function to handle qm non-fatal hardware errors.
  */
-int hisi_qm_hw_error_handle(struct hisi_qm *qm)
+pci_ers_result_t hisi_qm_hw_error_handle(struct hisi_qm *qm)
 {
 	if (!qm->ops->hw_error_handle) {
-		dev_err(&qm->pdev->dev, "QM version %d doesn't support hw error report!\n",
-			qm->ver);
+		dev_err(&qm->pdev->dev, "QM doesn't support hw error report!\n");
 		return PCI_ERS_RESULT_NONE;
 	}
 
@@ -1908,6 +1915,48 @@
 }
 EXPORT_SYMBOL_GPL(hisi_qm_get_hw_version);
 
+/**
+ * hisi_qm_dev_err_init() - Initialize device error configuration.
+ * @qm: The qm for which we want to do error initialization.
+ *
+ * Initialize QM and device error related configuration.
+ */
+void hisi_qm_dev_err_init(struct hisi_qm *qm)
+{
+	if (qm->fun_type == QM_HW_VF)
+		return;
+
+	qm_hw_error_init(qm);
+
+	if (!qm->err_ini->hw_err_enable) {
+		dev_err(&qm->pdev->dev, "Device doesn't support hw error init!\n");
+		return;
+	}
+	qm->err_ini->hw_err_enable(qm);
+}
+EXPORT_SYMBOL_GPL(hisi_qm_dev_err_init);
+
+/**
+ * hisi_qm_dev_err_uninit() - Uninitialize device error configuration.
+ * @qm: The qm for which we want to do error uninitialization.
+ *
+ * Uninitialize QM and device error related configuration.
+ */
+void hisi_qm_dev_err_uninit(struct hisi_qm *qm)
+{
+	if (qm->fun_type == QM_HW_VF)
+		return;
+
+	qm_hw_error_uninit(qm);
+
+	if (!qm->err_ini->hw_err_disable) {
+		dev_err(&qm->pdev->dev, "Unexpected device hw error uninit!\n");
+		return;
+	}
+	qm->err_ini->hw_err_disable(qm);
+}
+EXPORT_SYMBOL_GPL(hisi_qm_dev_err_uninit);
+
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Zhou Wang <wangzhou1@hisilicon.com>");
 MODULE_DESCRIPTION("HiSilicon Accelerator queue manager driver");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/hisilicon/qm.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/hisilicon/qm.h
@@ -40,6 +40,7 @@
 #define QM_AXI_M_CFG			0x1000ac
 #define AXI_M_CFG			0xffff
 #define QM_AXI_M_CFG_ENABLE		0x1000b0
+#define AM_CFG_SINGLE_PORT_MAX_TRANS	0x300014
 #define AXI_M_CFG_ENABLE		0xffffffff
 #define QM_PEH_AXUSER_CFG		0x1000cc
 #define QM_PEH_AXUSER_CFG_ENABLE	0x1000d0
@@ -75,6 +76,8 @@
 
 #define QM_Q_DEPTH			1024
 
+#define HISI_ACC_SGL_SGE_NR_MAX		255
+
 enum qp_state {
 	QP_STOP,
 };
@@ -123,6 +126,21 @@
 	unsigned long flags;
 };
 
+struct hisi_qm;
+
+struct hisi_qm_err_info {
+	u32 ce;
+	u32 nfe;
+	u32 fe;
+	u32 msi;
+};
+
+struct hisi_qm_err_ini {
+	void (*hw_err_enable)(struct hisi_qm *qm);
+	void (*hw_err_disable)(struct hisi_qm *qm);
+	struct hisi_qm_err_info err_info;
+};
+
 struct hisi_qm {
 	enum qm_hw_ver ver;
 	enum qm_fun_type fun_type;
@@ -132,6 +150,7 @@
 	u32 sqe_size;
 	u32 qp_base;
 	u32 qp_num;
+	u32 qp_in_used;
 	u32 ctrl_qp_num;
 
 	struct qm_dma qdma;
@@ -145,6 +164,7 @@
 	dma_addr_t aeqe_dma;
 
 	struct hisi_qm_status status;
+	const struct hisi_qm_err_ini *err_ini;
 
 	rwlock_t qps_lock;
 	unsigned long *qp_bitmap;
@@ -159,6 +179,8 @@
 	u32 error_mask;
 	u32 msi_mask;
 
+	struct workqueue_struct *wq;
+	struct work_struct work;
 	bool use_dma_api;
 };
 
@@ -189,8 +211,6 @@
 	struct hisi_qp_ops *hw_ops;
 	void *qp_ctx;
 	void (*req_cb)(struct hisi_qp *qp, void *data);
-	struct work_struct work;
-	struct workqueue_struct *wq;
 
 	struct hisi_qm *qm;
 };
@@ -204,12 +224,24 @@
 int hisi_qm_stop_qp(struct hisi_qp *qp);
 void hisi_qm_release_qp(struct hisi_qp *qp);
 int hisi_qp_send(struct hisi_qp *qp, const void *msg);
+int hisi_qm_get_free_qp_num(struct hisi_qm *qm);
 int hisi_qm_get_vft(struct hisi_qm *qm, u32 *base, u32 *number);
 int hisi_qm_set_vft(struct hisi_qm *qm, u32 fun_num, u32 base, u32 number);
 int hisi_qm_debug_init(struct hisi_qm *qm);
-void hisi_qm_hw_error_init(struct hisi_qm *qm, u32 ce, u32 nfe, u32 fe,
-			   u32 msi);
-int hisi_qm_hw_error_handle(struct hisi_qm *qm);
+pci_ers_result_t hisi_qm_hw_error_handle(struct hisi_qm *qm);
 enum qm_hw_ver hisi_qm_get_hw_version(struct pci_dev *pdev);
 void hisi_qm_debug_regs_clear(struct hisi_qm *qm);
+void hisi_qm_dev_err_init(struct hisi_qm *qm);
+void hisi_qm_dev_err_uninit(struct hisi_qm *qm);
+
+struct hisi_acc_sgl_pool;
+struct hisi_acc_hw_sgl *hisi_acc_sg_buf_map_to_hw_sgl(struct device *dev,
+	struct scatterlist *sgl, struct hisi_acc_sgl_pool *pool,
+	u32 index, dma_addr_t *hw_sgl_dma);
+void hisi_acc_sg_buf_unmap(struct device *dev, struct scatterlist *sgl,
+			   struct hisi_acc_hw_sgl *hw_sgl);
+struct hisi_acc_sgl_pool *hisi_acc_create_sgl_pool(struct device *dev,
+						   u32 count, u32 sge_nr);
+void hisi_acc_free_sgl_pool(struct device *dev,
+			    struct hisi_acc_sgl_pool *pool);
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/hisilicon/sec/sec_algs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/hisilicon/sec/sec_algs.c
@@ -175,7 +175,8 @@
 				     dma_addr_t *psec_sgl,
 				     struct scatterlist *sgl,
 				     int count,
-				     struct sec_dev_info *info)
+				     struct sec_dev_info *info,
+				     gfp_t gfp)
 {
 	struct sec_hw_sgl *sgl_current = NULL;
 	struct sec_hw_sgl *sgl_next;
@@ -190,7 +191,7 @@
 		sge_index = i % SEC_MAX_SGE_NUM;
 		if (sge_index == 0) {
 			sgl_next = dma_pool_zalloc(info->hw_sgl_pool,
-						   GFP_KERNEL, &sgl_next_dma);
+						   gfp, &sgl_next_dma);
 			if (!sgl_next) {
 				ret = -ENOMEM;
 				goto err_free_hw_sgls;
@@ -448,7 +449,7 @@
 		 */
 	}
 
-	mutex_lock(&ctx->queue->queuelock);
+	spin_lock_bh(&ctx->queue->queuelock);
 	/* Put the IV in place for chained cases */
 	switch (ctx->cipher_alg) {
 	case SEC_C_AES_CBC_128:
@@ -508,7 +509,7 @@
 			list_del(&backlog_req->backlog_head);
 		}
 	}
-	mutex_unlock(&ctx->queue->queuelock);
+	spin_unlock_bh(&ctx->queue->queuelock);
 
 	mutex_lock(&sec_req->lock);
 	list_del(&sec_req_el->head);
@@ -545,14 +546,14 @@
 }
 
 static int sec_alg_alloc_and_calc_split_sizes(int length, size_t **split_sizes,
-					      int *steps)
+					      int *steps, gfp_t gfp)
 {
 	size_t *sizes;
 	int i;
 
 	/* Split into suitable sized blocks */
 	*steps = roundup(length, SEC_REQ_LIMIT) / SEC_REQ_LIMIT;
-	sizes = kcalloc(*steps, sizeof(*sizes), GFP_KERNEL);
+	sizes = kcalloc(*steps, sizeof(*sizes), gfp);
 	if (!sizes)
 		return -ENOMEM;
 
@@ -568,7 +569,7 @@
 				int steps, struct scatterlist ***splits,
 				int **splits_nents,
 				int sgl_len_in,
-				struct device *dev)
+				struct device *dev, gfp_t gfp)
 {
 	int ret, count;
 
@@ -576,12 +577,12 @@
 	if (!count)
 		return -EINVAL;
 
-	*splits = kcalloc(steps, sizeof(struct scatterlist *), GFP_KERNEL);
+	*splits = kcalloc(steps, sizeof(struct scatterlist *), gfp);
 	if (!*splits) {
 		ret = -ENOMEM;
 		goto err_unmap_sg;
 	}
-	*splits_nents = kcalloc(steps, sizeof(int), GFP_KERNEL);
+	*splits_nents = kcalloc(steps, sizeof(int), gfp);
 	if (!*splits_nents) {
 		ret = -ENOMEM;
 		goto err_free_splits;
@@ -589,7 +590,7 @@
 
 	/* output the scatter list before and after this */
 	ret = sg_split(sgl, count, 0, steps, split_sizes,
-		       *splits, *splits_nents, GFP_KERNEL);
+		       *splits, *splits_nents, gfp);
 	if (ret) {
 		ret = -ENOMEM;
 		goto err_free_splits_nents;
@@ -630,13 +631,13 @@
 			   int el_size, bool different_dest,
 			   struct scatterlist *sgl_in, int n_ents_in,
 			   struct scatterlist *sgl_out, int n_ents_out,
-			   struct sec_dev_info *info)
+			   struct sec_dev_info *info, gfp_t gfp)
 {
 	struct sec_request_el *el;
 	struct sec_bd_info *req;
 	int ret;
 
-	el = kzalloc(sizeof(*el), GFP_KERNEL);
+	el = kzalloc(sizeof(*el), gfp);
 	if (!el)
 		return ERR_PTR(-ENOMEM);
 	el->el_length = el_size;
@@ -668,7 +669,7 @@
 	el->sgl_in = sgl_in;
 
 	ret = sec_alloc_and_fill_hw_sgl(&el->in, &el->dma_in, el->sgl_in,
-					n_ents_in, info);
+					n_ents_in, info, gfp);
 	if (ret)
 		goto err_free_el;
 
@@ -679,7 +680,7 @@
 		el->sgl_out = sgl_out;
 		ret = sec_alloc_and_fill_hw_sgl(&el->out, &el->dma_out,
 						el->sgl_out,
-						n_ents_out, info);
+						n_ents_out, info, gfp);
 		if (ret)
 			goto err_free_hw_sgl_in;
 
@@ -720,6 +721,7 @@
 	int *splits_out_nents = NULL;
 	struct sec_request_el *el, *temp;
 	bool split = skreq->src != skreq->dst;
+	gfp_t gfp = skreq->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : GFP_ATOMIC;
 
 	mutex_init(&sec_req->lock);
 	sec_req->req_base = &skreq->base;
@@ -728,13 +730,13 @@
 	sec_req->len_in = sg_nents(skreq->src);
 
 	ret = sec_alg_alloc_and_calc_split_sizes(skreq->cryptlen, &split_sizes,
-						 &steps);
+						 &steps, gfp);
 	if (ret)
 		return ret;
 	sec_req->num_elements = steps;
 	ret = sec_map_and_split_sg(skreq->src, split_sizes, steps, &splits_in,
 				   &splits_in_nents, sec_req->len_in,
-				   info->dev);
+				   info->dev, gfp);
 	if (ret)
 		goto err_free_split_sizes;
 
@@ -742,7 +744,7 @@
 		sec_req->len_out = sg_nents(skreq->dst);
 		ret = sec_map_and_split_sg(skreq->dst, split_sizes, steps,
 					   &splits_out, &splits_out_nents,
-					   sec_req->len_out, info->dev);
+					   sec_req->len_out, info->dev, gfp);
 		if (ret)
 			goto err_unmap_in_sg;
 	}
@@ -775,7 +777,7 @@
 					       splits_in[i], splits_in_nents[i],
 					       split ? splits_out[i] : NULL,
 					       split ? splits_out_nents[i] : 0,
-					       info);
+					       info, gfp);
 		if (IS_ERR(el)) {
 			ret = PTR_ERR(el);
 			goto err_free_elements;
@@ -796,7 +798,7 @@
 	 */
 
 	/* Grab a big lock for a long time to avoid concurrency issues */
-	mutex_lock(&queue->queuelock);
+	spin_lock_bh(&queue->queuelock);
 
 	/*
 	 * Can go on to queue if we have space in either:
@@ -812,15 +814,15 @@
 		ret = -EBUSY;
 		if ((skreq->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) {
 			list_add_tail(&sec_req->backlog_head, &ctx->backlog);
-			mutex_unlock(&queue->queuelock);
+			spin_unlock_bh(&queue->queuelock);
 			goto out;
 		}
 
-		mutex_unlock(&queue->queuelock);
+		spin_unlock_bh(&queue->queuelock);
 		goto err_free_elements;
 	}
 	ret = sec_send_request(sec_req, queue);
-	mutex_unlock(&queue->queuelock);
+	spin_unlock_bh(&queue->queuelock);
 	if (ret)
 		goto err_free_elements;
 
@@ -879,7 +881,7 @@
 	if (IS_ERR(ctx->queue))
 		return PTR_ERR(ctx->queue);
 
-	mutex_init(&ctx->queue->queuelock);
+	spin_lock_init(&ctx->queue->queuelock);
 	ctx->queue->havesoftqueue = false;
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/hisilicon/sec/sec_drv.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/hisilicon/sec/sec_drv.h
@@ -347,7 +347,7 @@
 	DECLARE_BITMAP(unprocessed, SEC_QUEUE_LEN);
 	DECLARE_KFIFO_PTR(softqueue, typeof(struct sec_request_el *));
 	bool havesoftqueue;
-	struct mutex queuelock;
+	spinlock_t queuelock;
 	void *shadow[SEC_QUEUE_LEN];
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/hisilicon/sec2/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/hisilicon/sec2/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_CRYPTO_DEV_HISI_SEC2) += hisi_sec2.o
+hisi_sec2-objs = sec_main.o sec_crypto.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/hisilicon/sec2/sec.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/hisilicon/sec2/sec.h
@@ -0,0 +1,175 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2019 HiSilicon Limited. */
+
+#ifndef __HISI_SEC_V2_H
+#define __HISI_SEC_V2_H
+
+#include <linux/list.h>
+
+#include "../qm.h"
+#include "sec_crypto.h"
+
+/* Algorithm resource per hardware SEC queue */
+struct sec_alg_res {
+	u8 *c_ivin;
+	dma_addr_t c_ivin_dma;
+	u8 *out_mac;
+	dma_addr_t out_mac_dma;
+};
+
+/* Cipher request of SEC private */
+struct sec_cipher_req {
+	struct hisi_acc_hw_sgl *c_in;
+	dma_addr_t c_in_dma;
+	struct hisi_acc_hw_sgl *c_out;
+	dma_addr_t c_out_dma;
+	struct skcipher_request *sk_req;
+	u32 c_len;
+	bool encrypt;
+};
+
+struct sec_aead_req {
+	u8 *out_mac;
+	dma_addr_t out_mac_dma;
+	struct aead_request *aead_req;
+};
+
+/* SEC request of Crypto */
+struct sec_req {
+	struct sec_sqe sec_sqe;
+	struct sec_ctx *ctx;
+	struct sec_qp_ctx *qp_ctx;
+
+	struct sec_cipher_req c_req;
+	struct sec_aead_req aead_req;
+
+	int err_type;
+	int req_id;
+
+	/* Status of the SEC request */
+	bool fake_busy;
+};
+
+/**
+ * struct sec_req_op - Operations for SEC request
+ * @buf_map: DMA map the SGL buffers of the request
+ * @buf_unmap: DMA unmap the SGL buffers of the request
+ * @bd_fill: Fill the SEC queue BD
+ * @bd_send: Send the SEC BD into the hardware queue
+ * @callback: Call back for the request
+ * @process: Main processing logic of Skcipher
+ */
+struct sec_req_op {
+	int (*buf_map)(struct sec_ctx *ctx, struct sec_req *req);
+	void (*buf_unmap)(struct sec_ctx *ctx, struct sec_req *req);
+	void (*do_transfer)(struct sec_ctx *ctx, struct sec_req *req);
+	int (*bd_fill)(struct sec_ctx *ctx, struct sec_req *req);
+	int (*bd_send)(struct sec_ctx *ctx, struct sec_req *req);
+	void (*callback)(struct sec_ctx *ctx, struct sec_req *req, int err);
+	int (*process)(struct sec_ctx *ctx, struct sec_req *req);
+};
+
+/* SEC auth context */
+struct sec_auth_ctx {
+	dma_addr_t a_key_dma;
+	u8 *a_key;
+	u8 a_key_len;
+	u8 mac_len;
+	u8 a_alg;
+	struct crypto_shash *hash_tfm;
+};
+
+/* SEC cipher context which cipher's relatives */
+struct sec_cipher_ctx {
+	u8 *c_key;
+	dma_addr_t c_key_dma;
+	sector_t iv_offset;
+	u32 c_gran_size;
+	u32 ivsize;
+	u8 c_mode;
+	u8 c_alg;
+	u8 c_key_len;
+};
+
+/* SEC queue context which defines queue's relatives */
+struct sec_qp_ctx {
+	struct hisi_qp *qp;
+	struct sec_req *req_list[QM_Q_DEPTH];
+	struct idr req_idr;
+	struct sec_alg_res res[QM_Q_DEPTH];
+	struct sec_ctx *ctx;
+	struct mutex req_lock;
+	struct hisi_acc_sgl_pool *c_in_pool;
+	struct hisi_acc_sgl_pool *c_out_pool;
+	atomic_t pending_reqs;
+};
+
+enum sec_alg_type {
+	SEC_SKCIPHER,
+	SEC_AEAD
+};
+
+/* SEC Crypto TFM context which defines queue and cipher .etc relatives */
+struct sec_ctx {
+	struct sec_qp_ctx *qp_ctx;
+	struct sec_dev *sec;
+	const struct sec_req_op *req_op;
+
+	/* Half queues for encipher, and half for decipher */
+	u32 hlf_q_num;
+
+	/* Threshold for fake busy, trigger to return -EBUSY to user */
+	u32 fake_req_limit;
+
+	/* Currrent cyclic index to select a queue for encipher */
+	atomic_t enc_qcyclic;
+
+	 /* Currrent cyclic index to select a queue for decipher */
+	atomic_t dec_qcyclic;
+
+	enum sec_alg_type alg_type;
+	struct sec_cipher_ctx c_ctx;
+	struct sec_auth_ctx a_ctx;
+};
+
+enum sec_endian {
+	SEC_LE = 0,
+	SEC_32BE,
+	SEC_64BE
+};
+
+enum sec_debug_file_index {
+	SEC_CURRENT_QM,
+	SEC_CLEAR_ENABLE,
+	SEC_DEBUG_FILE_NUM,
+};
+
+struct sec_debug_file {
+	enum sec_debug_file_index index;
+	spinlock_t lock;
+	struct hisi_qm *qm;
+};
+
+struct sec_dfx {
+	atomic64_t send_cnt;
+	atomic64_t recv_cnt;
+};
+
+struct sec_debug {
+	struct sec_dfx dfx;
+	struct sec_debug_file files[SEC_DEBUG_FILE_NUM];
+};
+
+struct sec_dev {
+	struct hisi_qm qm;
+	struct list_head list;
+	struct sec_debug debug;
+	u32 ctx_q_num;
+	u32 num_vfs;
+	unsigned long status;
+};
+
+struct sec_dev *sec_find_device(int node);
+int sec_register_to_crypto(void);
+void sec_unregister_from_crypto(void);
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/hisilicon/sec2/sec_crypto.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/hisilicon/sec2/sec_crypto.c
@@ -0,0 +1,1446 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2019 HiSilicon Limited. */
+
+#include <crypto/aes.h>
+#include <crypto/algapi.h>
+#include <crypto/authenc.h>
+#include <crypto/des.h>
+#include <crypto/hash.h>
+#include <crypto/internal/aead.h>
+#include <crypto/sha.h>
+#include <crypto/skcipher.h>
+#include <crypto/xts.h>
+#include <linux/crypto.h>
+#include <linux/dma-mapping.h>
+#include <linux/idr.h>
+
+#include "sec.h"
+#include "sec_crypto.h"
+
+#define SEC_PRIORITY		4001
+#define SEC_XTS_MIN_KEY_SIZE	(2 * AES_MIN_KEY_SIZE)
+#define SEC_XTS_MAX_KEY_SIZE	(2 * AES_MAX_KEY_SIZE)
+#define SEC_DES3_2KEY_SIZE	(2 * DES_KEY_SIZE)
+#define SEC_DES3_3KEY_SIZE	(3 * DES_KEY_SIZE)
+
+/* SEC sqe(bd) bit operational relative MACRO */
+#define SEC_DE_OFFSET		1
+#define SEC_CIPHER_OFFSET	4
+#define SEC_SCENE_OFFSET	3
+#define SEC_DST_SGL_OFFSET	2
+#define SEC_SRC_SGL_OFFSET	7
+#define SEC_CKEY_OFFSET		9
+#define SEC_CMODE_OFFSET	12
+#define SEC_AKEY_OFFSET         5
+#define SEC_AEAD_ALG_OFFSET     11
+#define SEC_AUTH_OFFSET		6
+
+#define SEC_FLAG_OFFSET		7
+#define SEC_FLAG_MASK		0x0780
+#define SEC_TYPE_MASK		0x0F
+#define SEC_DONE_MASK		0x0001
+
+#define SEC_TOTAL_IV_SZ		(SEC_IV_SIZE * QM_Q_DEPTH)
+#define SEC_SGL_SGE_NR		128
+#define SEC_CTX_DEV(ctx)	(&(ctx)->sec->qm.pdev->dev)
+#define SEC_CIPHER_AUTH		0xfe
+#define SEC_AUTH_CIPHER		0x1
+#define SEC_MAX_MAC_LEN		64
+#define SEC_TOTAL_MAC_SZ	(SEC_MAX_MAC_LEN * QM_Q_DEPTH)
+#define SEC_SQE_LEN_RATE	4
+#define SEC_SQE_CFLAG		2
+#define SEC_SQE_AEAD_FLAG	3
+#define SEC_SQE_DONE		0x1
+
+static atomic_t sec_active_devs;
+
+/* Get an en/de-cipher queue cyclically to balance load over queues of TFM */
+static inline int sec_alloc_queue_id(struct sec_ctx *ctx, struct sec_req *req)
+{
+	if (req->c_req.encrypt)
+		return (u32)atomic_inc_return(&ctx->enc_qcyclic) %
+				 ctx->hlf_q_num;
+
+	return (u32)atomic_inc_return(&ctx->dec_qcyclic) % ctx->hlf_q_num +
+				 ctx->hlf_q_num;
+}
+
+static inline void sec_free_queue_id(struct sec_ctx *ctx, struct sec_req *req)
+{
+	if (req->c_req.encrypt)
+		atomic_dec(&ctx->enc_qcyclic);
+	else
+		atomic_dec(&ctx->dec_qcyclic);
+}
+
+static int sec_alloc_req_id(struct sec_req *req, struct sec_qp_ctx *qp_ctx)
+{
+	int req_id;
+
+	mutex_lock(&qp_ctx->req_lock);
+
+	req_id = idr_alloc_cyclic(&qp_ctx->req_idr, NULL,
+				  0, QM_Q_DEPTH, GFP_ATOMIC);
+	mutex_unlock(&qp_ctx->req_lock);
+	if (unlikely(req_id < 0)) {
+		dev_err(SEC_CTX_DEV(req->ctx), "alloc req id fail!\n");
+		return req_id;
+	}
+
+	req->qp_ctx = qp_ctx;
+	qp_ctx->req_list[req_id] = req;
+	return req_id;
+}
+
+static void sec_free_req_id(struct sec_req *req)
+{
+	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
+	int req_id = req->req_id;
+
+	if (unlikely(req_id < 0 || req_id >= QM_Q_DEPTH)) {
+		dev_err(SEC_CTX_DEV(req->ctx), "free request id invalid!\n");
+		return;
+	}
+
+	qp_ctx->req_list[req_id] = NULL;
+	req->qp_ctx = NULL;
+
+	mutex_lock(&qp_ctx->req_lock);
+	idr_remove(&qp_ctx->req_idr, req_id);
+	mutex_unlock(&qp_ctx->req_lock);
+}
+
+static int sec_aead_verify(struct sec_req *req, struct sec_qp_ctx *qp_ctx)
+{
+	struct aead_request *aead_req = req->aead_req.aead_req;
+	struct crypto_aead *tfm = crypto_aead_reqtfm(aead_req);
+	u8 *mac_out = qp_ctx->res[req->req_id].out_mac;
+	size_t authsize = crypto_aead_authsize(tfm);
+	u8 *mac = mac_out + SEC_MAX_MAC_LEN;
+	struct scatterlist *sgl = aead_req->src;
+	size_t sz;
+
+	sz = sg_pcopy_to_buffer(sgl, sg_nents(sgl), mac, authsize,
+				aead_req->cryptlen + aead_req->assoclen -
+				authsize);
+	if (unlikely(sz != authsize || memcmp(mac_out, mac, sz))) {
+		dev_err(SEC_CTX_DEV(req->ctx), "aead verify failure!\n");
+		return -EBADMSG;
+	}
+
+	return 0;
+}
+
+static void sec_req_cb(struct hisi_qp *qp, void *resp)
+{
+	struct sec_qp_ctx *qp_ctx = qp->qp_ctx;
+	struct sec_sqe *bd = resp;
+	struct sec_ctx *ctx;
+	struct sec_req *req;
+	u16 done, flag;
+	int err = 0;
+	u8 type;
+
+	type = bd->type_cipher_auth & SEC_TYPE_MASK;
+	if (unlikely(type != SEC_BD_TYPE2)) {
+		pr_err("err bd type [%d]\n", type);
+		return;
+	}
+
+	req = qp_ctx->req_list[le16_to_cpu(bd->type2.tag)];
+	req->err_type = bd->type2.error_type;
+	ctx = req->ctx;
+	done = le16_to_cpu(bd->type2.done_flag) & SEC_DONE_MASK;
+	flag = (le16_to_cpu(bd->type2.done_flag) &
+		SEC_FLAG_MASK) >> SEC_FLAG_OFFSET;
+	if (unlikely(req->err_type || done != SEC_SQE_DONE ||
+	    (ctx->alg_type == SEC_SKCIPHER && flag != SEC_SQE_CFLAG) ||
+	    (ctx->alg_type == SEC_AEAD && flag != SEC_SQE_AEAD_FLAG))) {
+		dev_err(SEC_CTX_DEV(ctx),
+			"err_type[%d],done[%d],flag[%d]\n",
+			req->err_type, done, flag);
+		err = -EIO;
+	}
+
+	if (ctx->alg_type == SEC_AEAD && !req->c_req.encrypt)
+		err = sec_aead_verify(req, qp_ctx);
+
+	atomic64_inc(&ctx->sec->debug.dfx.recv_cnt);
+
+	ctx->req_op->buf_unmap(ctx, req);
+
+	ctx->req_op->callback(ctx, req, err);
+}
+
+static int sec_bd_send(struct sec_ctx *ctx, struct sec_req *req)
+{
+	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
+	int ret;
+
+	mutex_lock(&qp_ctx->req_lock);
+	ret = hisi_qp_send(qp_ctx->qp, &req->sec_sqe);
+	mutex_unlock(&qp_ctx->req_lock);
+	atomic64_inc(&ctx->sec->debug.dfx.send_cnt);
+
+	if (unlikely(ret == -EBUSY))
+		return -ENOBUFS;
+
+	if (!ret) {
+		if (req->fake_busy)
+			ret = -EBUSY;
+		else
+			ret = -EINPROGRESS;
+	}
+
+	return ret;
+}
+
+/* Get DMA memory resources */
+static int sec_alloc_civ_resource(struct device *dev, struct sec_alg_res *res)
+{
+	int i;
+
+	res->c_ivin = dma_alloc_coherent(dev, SEC_TOTAL_IV_SZ,
+					 &res->c_ivin_dma, GFP_KERNEL);
+	if (!res->c_ivin)
+		return -ENOMEM;
+
+	for (i = 1; i < QM_Q_DEPTH; i++) {
+		res[i].c_ivin_dma = res->c_ivin_dma + i * SEC_IV_SIZE;
+		res[i].c_ivin = res->c_ivin + i * SEC_IV_SIZE;
+	}
+
+	return 0;
+}
+
+static void sec_free_civ_resource(struct device *dev, struct sec_alg_res *res)
+{
+	if (res->c_ivin)
+		dma_free_coherent(dev, SEC_TOTAL_IV_SZ,
+				  res->c_ivin, res->c_ivin_dma);
+}
+
+static int sec_alloc_mac_resource(struct device *dev, struct sec_alg_res *res)
+{
+	int i;
+
+	res->out_mac = dma_alloc_coherent(dev, SEC_TOTAL_MAC_SZ << 1,
+					  &res->out_mac_dma, GFP_KERNEL);
+	if (!res->out_mac)
+		return -ENOMEM;
+
+	for (i = 1; i < QM_Q_DEPTH; i++) {
+		res[i].out_mac_dma = res->out_mac_dma +
+				     i * (SEC_MAX_MAC_LEN << 1);
+		res[i].out_mac = res->out_mac + i * (SEC_MAX_MAC_LEN << 1);
+	}
+
+	return 0;
+}
+
+static void sec_free_mac_resource(struct device *dev, struct sec_alg_res *res)
+{
+	if (res->out_mac)
+		dma_free_coherent(dev, SEC_TOTAL_MAC_SZ << 1,
+				  res->out_mac, res->out_mac_dma);
+}
+
+static int sec_alg_resource_alloc(struct sec_ctx *ctx,
+				  struct sec_qp_ctx *qp_ctx)
+{
+	struct device *dev = SEC_CTX_DEV(ctx);
+	struct sec_alg_res *res = qp_ctx->res;
+	int ret;
+
+	ret = sec_alloc_civ_resource(dev, res);
+	if (ret)
+		return ret;
+
+	if (ctx->alg_type == SEC_AEAD) {
+		ret = sec_alloc_mac_resource(dev, res);
+		if (ret)
+			goto get_fail;
+	}
+
+	return 0;
+get_fail:
+	sec_free_civ_resource(dev, res);
+
+	return ret;
+}
+
+static void sec_alg_resource_free(struct sec_ctx *ctx,
+				  struct sec_qp_ctx *qp_ctx)
+{
+	struct device *dev = SEC_CTX_DEV(ctx);
+
+	sec_free_civ_resource(dev, qp_ctx->res);
+
+	if (ctx->alg_type == SEC_AEAD)
+		sec_free_mac_resource(dev, qp_ctx->res);
+}
+
+static int sec_create_qp_ctx(struct hisi_qm *qm, struct sec_ctx *ctx,
+			     int qp_ctx_id, int alg_type)
+{
+	struct device *dev = SEC_CTX_DEV(ctx);
+	struct sec_qp_ctx *qp_ctx;
+	struct hisi_qp *qp;
+	int ret = -ENOMEM;
+
+	qp = hisi_qm_create_qp(qm, alg_type);
+	if (IS_ERR(qp))
+		return PTR_ERR(qp);
+
+	qp_ctx = &ctx->qp_ctx[qp_ctx_id];
+	qp->req_type = 0;
+	qp->qp_ctx = qp_ctx;
+	qp->req_cb = sec_req_cb;
+	qp_ctx->qp = qp;
+	qp_ctx->ctx = ctx;
+
+	mutex_init(&qp_ctx->req_lock);
+	atomic_set(&qp_ctx->pending_reqs, 0);
+	idr_init(&qp_ctx->req_idr);
+
+	qp_ctx->c_in_pool = hisi_acc_create_sgl_pool(dev, QM_Q_DEPTH,
+						     SEC_SGL_SGE_NR);
+	if (IS_ERR(qp_ctx->c_in_pool)) {
+		dev_err(dev, "fail to create sgl pool for input!\n");
+		goto err_destroy_idr;
+	}
+
+	qp_ctx->c_out_pool = hisi_acc_create_sgl_pool(dev, QM_Q_DEPTH,
+						      SEC_SGL_SGE_NR);
+	if (IS_ERR(qp_ctx->c_out_pool)) {
+		dev_err(dev, "fail to create sgl pool for output!\n");
+		goto err_free_c_in_pool;
+	}
+
+	ret = sec_alg_resource_alloc(ctx, qp_ctx);
+	if (ret)
+		goto err_free_c_out_pool;
+
+	ret = hisi_qm_start_qp(qp, 0);
+	if (ret < 0)
+		goto err_queue_free;
+
+	return 0;
+
+err_queue_free:
+	sec_alg_resource_free(ctx, qp_ctx);
+err_free_c_out_pool:
+	hisi_acc_free_sgl_pool(dev, qp_ctx->c_out_pool);
+err_free_c_in_pool:
+	hisi_acc_free_sgl_pool(dev, qp_ctx->c_in_pool);
+err_destroy_idr:
+	idr_destroy(&qp_ctx->req_idr);
+	hisi_qm_release_qp(qp);
+
+	return ret;
+}
+
+static void sec_release_qp_ctx(struct sec_ctx *ctx,
+			       struct sec_qp_ctx *qp_ctx)
+{
+	struct device *dev = SEC_CTX_DEV(ctx);
+
+	hisi_qm_stop_qp(qp_ctx->qp);
+	sec_alg_resource_free(ctx, qp_ctx);
+
+	hisi_acc_free_sgl_pool(dev, qp_ctx->c_out_pool);
+	hisi_acc_free_sgl_pool(dev, qp_ctx->c_in_pool);
+
+	idr_destroy(&qp_ctx->req_idr);
+	hisi_qm_release_qp(qp_ctx->qp);
+}
+
+static int sec_ctx_base_init(struct sec_ctx *ctx)
+{
+	struct sec_dev *sec;
+	int i, ret;
+
+	sec = sec_find_device(cpu_to_node(smp_processor_id()));
+	if (!sec) {
+		pr_err("Can not find proper Hisilicon SEC device!\n");
+		return -ENODEV;
+	}
+	ctx->sec = sec;
+	ctx->hlf_q_num = sec->ctx_q_num >> 1;
+
+	/* Half of queue depth is taken as fake requests limit in the queue. */
+	ctx->fake_req_limit = QM_Q_DEPTH >> 1;
+	ctx->qp_ctx = kcalloc(sec->ctx_q_num, sizeof(struct sec_qp_ctx),
+			      GFP_KERNEL);
+	if (!ctx->qp_ctx)
+		return -ENOMEM;
+
+	for (i = 0; i < sec->ctx_q_num; i++) {
+		ret = sec_create_qp_ctx(&sec->qm, ctx, i, 0);
+		if (ret)
+			goto err_sec_release_qp_ctx;
+	}
+
+	return 0;
+err_sec_release_qp_ctx:
+	for (i = i - 1; i >= 0; i--)
+		sec_release_qp_ctx(ctx, &ctx->qp_ctx[i]);
+
+	kfree(ctx->qp_ctx);
+	return ret;
+}
+
+static void sec_ctx_base_uninit(struct sec_ctx *ctx)
+{
+	int i;
+
+	for (i = 0; i < ctx->sec->ctx_q_num; i++)
+		sec_release_qp_ctx(ctx, &ctx->qp_ctx[i]);
+
+	kfree(ctx->qp_ctx);
+}
+
+static int sec_cipher_init(struct sec_ctx *ctx)
+{
+	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
+
+	c_ctx->c_key = dma_alloc_coherent(SEC_CTX_DEV(ctx), SEC_MAX_KEY_SIZE,
+					  &c_ctx->c_key_dma, GFP_KERNEL);
+	if (!c_ctx->c_key)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static void sec_cipher_uninit(struct sec_ctx *ctx)
+{
+	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
+
+	memzero_explicit(c_ctx->c_key, SEC_MAX_KEY_SIZE);
+	dma_free_coherent(SEC_CTX_DEV(ctx), SEC_MAX_KEY_SIZE,
+			  c_ctx->c_key, c_ctx->c_key_dma);
+}
+
+static int sec_auth_init(struct sec_ctx *ctx)
+{
+	struct sec_auth_ctx *a_ctx = &ctx->a_ctx;
+
+	a_ctx->a_key = dma_alloc_coherent(SEC_CTX_DEV(ctx), SEC_MAX_KEY_SIZE,
+					  &a_ctx->a_key_dma, GFP_KERNEL);
+	if (!a_ctx->a_key)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static void sec_auth_uninit(struct sec_ctx *ctx)
+{
+	struct sec_auth_ctx *a_ctx = &ctx->a_ctx;
+
+	memzero_explicit(a_ctx->a_key, SEC_MAX_KEY_SIZE);
+	dma_free_coherent(SEC_CTX_DEV(ctx), SEC_MAX_KEY_SIZE,
+			  a_ctx->a_key, a_ctx->a_key_dma);
+}
+
+static int sec_skcipher_init(struct crypto_skcipher *tfm)
+{
+	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
+	int ret;
+
+	ctx = crypto_skcipher_ctx(tfm);
+	ctx->alg_type = SEC_SKCIPHER;
+	crypto_skcipher_set_reqsize(tfm, sizeof(struct sec_req));
+	ctx->c_ctx.ivsize = crypto_skcipher_ivsize(tfm);
+	if (ctx->c_ctx.ivsize > SEC_IV_SIZE) {
+		dev_err(SEC_CTX_DEV(ctx), "get error skcipher iv size!\n");
+		return -EINVAL;
+	}
+
+	ret = sec_ctx_base_init(ctx);
+	if (ret)
+		return ret;
+
+	ret = sec_cipher_init(ctx);
+	if (ret)
+		goto err_cipher_init;
+
+	return 0;
+err_cipher_init:
+	sec_ctx_base_uninit(ctx);
+
+	return ret;
+}
+
+static void sec_skcipher_uninit(struct crypto_skcipher *tfm)
+{
+	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
+
+	sec_cipher_uninit(ctx);
+	sec_ctx_base_uninit(ctx);
+}
+
+static int sec_skcipher_3des_setkey(struct sec_cipher_ctx *c_ctx,
+				    const u32 keylen,
+				    const enum sec_cmode c_mode)
+{
+	switch (keylen) {
+	case SEC_DES3_2KEY_SIZE:
+		c_ctx->c_key_len = SEC_CKEY_3DES_2KEY;
+		break;
+	case SEC_DES3_3KEY_SIZE:
+		c_ctx->c_key_len = SEC_CKEY_3DES_3KEY;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int sec_skcipher_aes_sm4_setkey(struct sec_cipher_ctx *c_ctx,
+				       const u32 keylen,
+				       const enum sec_cmode c_mode)
+{
+	if (c_mode == SEC_CMODE_XTS) {
+		switch (keylen) {
+		case SEC_XTS_MIN_KEY_SIZE:
+			c_ctx->c_key_len = SEC_CKEY_128BIT;
+			break;
+		case SEC_XTS_MAX_KEY_SIZE:
+			c_ctx->c_key_len = SEC_CKEY_256BIT;
+			break;
+		default:
+			pr_err("hisi_sec2: xts mode key error!\n");
+			return -EINVAL;
+		}
+	} else {
+		switch (keylen) {
+		case AES_KEYSIZE_128:
+			c_ctx->c_key_len = SEC_CKEY_128BIT;
+			break;
+		case AES_KEYSIZE_192:
+			c_ctx->c_key_len = SEC_CKEY_192BIT;
+			break;
+		case AES_KEYSIZE_256:
+			c_ctx->c_key_len = SEC_CKEY_256BIT;
+			break;
+		default:
+			pr_err("hisi_sec2: aes key error!\n");
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static int sec_skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key,
+			       const u32 keylen, const enum sec_calg c_alg,
+			       const enum sec_cmode c_mode)
+{
+	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
+	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
+	int ret;
+
+	if (c_mode == SEC_CMODE_XTS) {
+		ret = xts_verify_key(tfm, key, keylen);
+		if (ret) {
+			dev_err(SEC_CTX_DEV(ctx), "xts mode key err!\n");
+			return ret;
+		}
+	}
+
+	c_ctx->c_alg  = c_alg;
+	c_ctx->c_mode = c_mode;
+
+	switch (c_alg) {
+	case SEC_CALG_3DES:
+		ret = sec_skcipher_3des_setkey(c_ctx, keylen, c_mode);
+		break;
+	case SEC_CALG_AES:
+	case SEC_CALG_SM4:
+		ret = sec_skcipher_aes_sm4_setkey(c_ctx, keylen, c_mode);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (ret) {
+		dev_err(SEC_CTX_DEV(ctx), "set sec key err!\n");
+		return ret;
+	}
+
+	memcpy(c_ctx->c_key, key, keylen);
+
+	return 0;
+}
+
+#define GEN_SEC_SETKEY_FUNC(name, c_alg, c_mode)			\
+static int sec_setkey_##name(struct crypto_skcipher *tfm, const u8 *key,\
+	u32 keylen)							\
+{									\
+	return sec_skcipher_setkey(tfm, key, keylen, c_alg, c_mode);	\
+}
+
+GEN_SEC_SETKEY_FUNC(aes_ecb, SEC_CALG_AES, SEC_CMODE_ECB)
+GEN_SEC_SETKEY_FUNC(aes_cbc, SEC_CALG_AES, SEC_CMODE_CBC)
+GEN_SEC_SETKEY_FUNC(aes_xts, SEC_CALG_AES, SEC_CMODE_XTS)
+
+GEN_SEC_SETKEY_FUNC(3des_ecb, SEC_CALG_3DES, SEC_CMODE_ECB)
+GEN_SEC_SETKEY_FUNC(3des_cbc, SEC_CALG_3DES, SEC_CMODE_CBC)
+
+GEN_SEC_SETKEY_FUNC(sm4_xts, SEC_CALG_SM4, SEC_CMODE_XTS)
+GEN_SEC_SETKEY_FUNC(sm4_cbc, SEC_CALG_SM4, SEC_CMODE_CBC)
+
+static int sec_cipher_map(struct device *dev, struct sec_req *req,
+			  struct scatterlist *src, struct scatterlist *dst)
+{
+	struct sec_cipher_req *c_req = &req->c_req;
+	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
+
+	c_req->c_in = hisi_acc_sg_buf_map_to_hw_sgl(dev, src,
+						    qp_ctx->c_in_pool,
+						    req->req_id,
+						    &c_req->c_in_dma);
+
+	if (IS_ERR(c_req->c_in)) {
+		dev_err(dev, "fail to dma map input sgl buffers!\n");
+		return PTR_ERR(c_req->c_in);
+	}
+
+	if (dst == src) {
+		c_req->c_out = c_req->c_in;
+		c_req->c_out_dma = c_req->c_in_dma;
+	} else {
+		c_req->c_out = hisi_acc_sg_buf_map_to_hw_sgl(dev, dst,
+							     qp_ctx->c_out_pool,
+							     req->req_id,
+							     &c_req->c_out_dma);
+
+		if (IS_ERR(c_req->c_out)) {
+			dev_err(dev, "fail to dma map output sgl buffers!\n");
+			hisi_acc_sg_buf_unmap(dev, src, c_req->c_in);
+			return PTR_ERR(c_req->c_out);
+		}
+	}
+
+	return 0;
+}
+
+static void sec_cipher_unmap(struct device *dev, struct sec_cipher_req *req,
+			     struct scatterlist *src, struct scatterlist *dst)
+{
+	if (dst != src)
+		hisi_acc_sg_buf_unmap(dev, src, req->c_in);
+
+	hisi_acc_sg_buf_unmap(dev, dst, req->c_out);
+}
+
+static int sec_skcipher_sgl_map(struct sec_ctx *ctx, struct sec_req *req)
+{
+	struct skcipher_request *sq = req->c_req.sk_req;
+
+	return sec_cipher_map(SEC_CTX_DEV(ctx), req, sq->src, sq->dst);
+}
+
+static void sec_skcipher_sgl_unmap(struct sec_ctx *ctx, struct sec_req *req)
+{
+	struct device *dev = SEC_CTX_DEV(ctx);
+	struct sec_cipher_req *c_req = &req->c_req;
+	struct skcipher_request *sk_req = c_req->sk_req;
+
+	sec_cipher_unmap(dev, c_req, sk_req->src, sk_req->dst);
+}
+
+static int sec_aead_aes_set_key(struct sec_cipher_ctx *c_ctx,
+				struct crypto_authenc_keys *keys)
+{
+	switch (keys->enckeylen) {
+	case AES_KEYSIZE_128:
+		c_ctx->c_key_len = SEC_CKEY_128BIT;
+		break;
+	case AES_KEYSIZE_192:
+		c_ctx->c_key_len = SEC_CKEY_192BIT;
+		break;
+	case AES_KEYSIZE_256:
+		c_ctx->c_key_len = SEC_CKEY_256BIT;
+		break;
+	default:
+		pr_err("hisi_sec2: aead aes key error!\n");
+		return -EINVAL;
+	}
+	memcpy(c_ctx->c_key, keys->enckey, keys->enckeylen);
+
+	return 0;
+}
+
+static int sec_aead_auth_set_key(struct sec_auth_ctx *ctx,
+				 struct crypto_authenc_keys *keys)
+{
+	struct crypto_shash *hash_tfm = ctx->hash_tfm;
+	SHASH_DESC_ON_STACK(shash, hash_tfm);
+	int blocksize, ret;
+
+	if (!keys->authkeylen) {
+		pr_err("hisi_sec2: aead auth key error!\n");
+		return -EINVAL;
+	}
+
+	blocksize = crypto_shash_blocksize(hash_tfm);
+	if (keys->authkeylen > blocksize) {
+		ret = crypto_shash_digest(shash, keys->authkey,
+					  keys->authkeylen, ctx->a_key);
+		if (ret) {
+			pr_err("hisi_sec2: aead auth digest error!\n");
+			return -EINVAL;
+		}
+		ctx->a_key_len = blocksize;
+	} else {
+		memcpy(ctx->a_key, keys->authkey, keys->authkeylen);
+		ctx->a_key_len = keys->authkeylen;
+	}
+
+	return 0;
+}
+
+static int sec_aead_setkey(struct crypto_aead *tfm, const u8 *key,
+			   const u32 keylen, const enum sec_hash_alg a_alg,
+			   const enum sec_calg c_alg,
+			   const enum sec_mac_len mac_len,
+			   const enum sec_cmode c_mode)
+{
+	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
+	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
+	struct crypto_authenc_keys keys;
+	int ret;
+
+	ctx->a_ctx.a_alg = a_alg;
+	ctx->c_ctx.c_alg = c_alg;
+	ctx->a_ctx.mac_len = mac_len;
+	c_ctx->c_mode = c_mode;
+
+	if (crypto_authenc_extractkeys(&keys, key, keylen))
+		goto bad_key;
+
+	ret = sec_aead_aes_set_key(c_ctx, &keys);
+	if (ret) {
+		dev_err(SEC_CTX_DEV(ctx), "set sec cipher key err!\n");
+		goto bad_key;
+	}
+
+	ret = sec_aead_auth_set_key(&ctx->a_ctx, &keys);
+	if (ret) {
+		dev_err(SEC_CTX_DEV(ctx), "set sec auth key err!\n");
+		goto bad_key;
+	}
+
+	return 0;
+bad_key:
+	memzero_explicit(&keys, sizeof(struct crypto_authenc_keys));
+
+	return -EINVAL;
+}
+
+
+#define GEN_SEC_AEAD_SETKEY_FUNC(name, aalg, calg, maclen, cmode)	\
+static int sec_setkey_##name(struct crypto_aead *tfm, const u8 *key,	\
+	u32 keylen)							\
+{									\
+	return sec_aead_setkey(tfm, key, keylen, aalg, calg, maclen, cmode);\
+}
+
+GEN_SEC_AEAD_SETKEY_FUNC(aes_cbc_sha1, SEC_A_HMAC_SHA1,
+			 SEC_CALG_AES, SEC_HMAC_SHA1_MAC, SEC_CMODE_CBC)
+GEN_SEC_AEAD_SETKEY_FUNC(aes_cbc_sha256, SEC_A_HMAC_SHA256,
+			 SEC_CALG_AES, SEC_HMAC_SHA256_MAC, SEC_CMODE_CBC)
+GEN_SEC_AEAD_SETKEY_FUNC(aes_cbc_sha512, SEC_A_HMAC_SHA512,
+			 SEC_CALG_AES, SEC_HMAC_SHA512_MAC, SEC_CMODE_CBC)
+
+static int sec_aead_sgl_map(struct sec_ctx *ctx, struct sec_req *req)
+{
+	struct aead_request *aq = req->aead_req.aead_req;
+
+	return sec_cipher_map(SEC_CTX_DEV(ctx), req, aq->src, aq->dst);
+}
+
+static void sec_aead_sgl_unmap(struct sec_ctx *ctx, struct sec_req *req)
+{
+	struct device *dev = SEC_CTX_DEV(ctx);
+	struct sec_cipher_req *cq = &req->c_req;
+	struct aead_request *aq = req->aead_req.aead_req;
+
+	sec_cipher_unmap(dev, cq, aq->src, aq->dst);
+}
+
+static int sec_request_transfer(struct sec_ctx *ctx, struct sec_req *req)
+{
+	int ret;
+
+	ret = ctx->req_op->buf_map(ctx, req);
+	if (unlikely(ret))
+		return ret;
+
+	ctx->req_op->do_transfer(ctx, req);
+
+	ret = ctx->req_op->bd_fill(ctx, req);
+	if (unlikely(ret))
+		goto unmap_req_buf;
+
+	return ret;
+
+unmap_req_buf:
+	ctx->req_op->buf_unmap(ctx, req);
+
+	return ret;
+}
+
+static void sec_request_untransfer(struct sec_ctx *ctx, struct sec_req *req)
+{
+	ctx->req_op->buf_unmap(ctx, req);
+}
+
+static void sec_skcipher_copy_iv(struct sec_ctx *ctx, struct sec_req *req)
+{
+	struct skcipher_request *sk_req = req->c_req.sk_req;
+	u8 *c_ivin = req->qp_ctx->res[req->req_id].c_ivin;
+
+	memcpy(c_ivin, sk_req->iv, ctx->c_ctx.ivsize);
+}
+
+static int sec_skcipher_bd_fill(struct sec_ctx *ctx, struct sec_req *req)
+{
+	struct sec_cipher_ctx *c_ctx = &ctx->c_ctx;
+	struct sec_cipher_req *c_req = &req->c_req;
+	struct sec_sqe *sec_sqe = &req->sec_sqe;
+	u8 scene, sa_type, da_type;
+	u8 bd_type, cipher;
+	u8 de = 0;
+
+	memset(sec_sqe, 0, sizeof(struct sec_sqe));
+
+	sec_sqe->type2.c_key_addr = cpu_to_le64(c_ctx->c_key_dma);
+	sec_sqe->type2.c_ivin_addr =
+		cpu_to_le64(req->qp_ctx->res[req->req_id].c_ivin_dma);
+	sec_sqe->type2.data_src_addr = cpu_to_le64(c_req->c_in_dma);
+	sec_sqe->type2.data_dst_addr = cpu_to_le64(c_req->c_out_dma);
+
+	sec_sqe->type2.icvw_kmode |= cpu_to_le16(((u16)c_ctx->c_mode) <<
+						SEC_CMODE_OFFSET);
+	sec_sqe->type2.c_alg = c_ctx->c_alg;
+	sec_sqe->type2.icvw_kmode |= cpu_to_le16(((u16)c_ctx->c_key_len) <<
+						SEC_CKEY_OFFSET);
+
+	bd_type = SEC_BD_TYPE2;
+	if (c_req->encrypt)
+		cipher = SEC_CIPHER_ENC << SEC_CIPHER_OFFSET;
+	else
+		cipher = SEC_CIPHER_DEC << SEC_CIPHER_OFFSET;
+	sec_sqe->type_cipher_auth = bd_type | cipher;
+
+	sa_type = SEC_SGL << SEC_SRC_SGL_OFFSET;
+	scene = SEC_COMM_SCENE << SEC_SCENE_OFFSET;
+	if (c_req->c_in_dma != c_req->c_out_dma)
+		de = 0x1 << SEC_DE_OFFSET;
+
+	sec_sqe->sds_sa_type = (de | scene | sa_type);
+
+	/* Just set DST address type */
+	da_type = SEC_SGL << SEC_DST_SGL_OFFSET;
+	sec_sqe->sdm_addr_type |= da_type;
+
+	sec_sqe->type2.clen_ivhlen |= cpu_to_le32(c_req->c_len);
+	sec_sqe->type2.tag = cpu_to_le16((u16)req->req_id);
+
+	return 0;
+}
+
+static void sec_update_iv(struct sec_req *req, enum sec_alg_type alg_type)
+{
+	struct aead_request *aead_req = req->aead_req.aead_req;
+	struct skcipher_request *sk_req = req->c_req.sk_req;
+	u32 iv_size = req->ctx->c_ctx.ivsize;
+	struct scatterlist *sgl;
+	unsigned int cryptlen;
+	size_t sz;
+	u8 *iv;
+
+	if (req->c_req.encrypt)
+		sgl = alg_type == SEC_SKCIPHER ? sk_req->dst : aead_req->dst;
+	else
+		sgl = alg_type == SEC_SKCIPHER ? sk_req->src : aead_req->src;
+
+	if (alg_type == SEC_SKCIPHER) {
+		iv = sk_req->iv;
+		cryptlen = sk_req->cryptlen;
+	} else {
+		iv = aead_req->iv;
+		cryptlen = aead_req->cryptlen;
+	}
+
+	sz = sg_pcopy_to_buffer(sgl, sg_nents(sgl), iv, iv_size,
+				cryptlen - iv_size);
+	if (unlikely(sz != iv_size))
+		dev_err(SEC_CTX_DEV(req->ctx), "copy output iv error!\n");
+}
+
+static void sec_skcipher_callback(struct sec_ctx *ctx, struct sec_req *req,
+				  int err)
+{
+	struct skcipher_request *sk_req = req->c_req.sk_req;
+	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
+
+	atomic_dec(&qp_ctx->pending_reqs);
+	sec_free_req_id(req);
+
+	/* IV output at encrypto of CBC mode */
+	if (!err && ctx->c_ctx.c_mode == SEC_CMODE_CBC && req->c_req.encrypt)
+		sec_update_iv(req, SEC_SKCIPHER);
+
+	if (req->fake_busy)
+		sk_req->base.complete(&sk_req->base, -EINPROGRESS);
+
+	sk_req->base.complete(&sk_req->base, err);
+}
+
+static void sec_aead_copy_iv(struct sec_ctx *ctx, struct sec_req *req)
+{
+	struct aead_request *aead_req = req->aead_req.aead_req;
+	u8 *c_ivin = req->qp_ctx->res[req->req_id].c_ivin;
+
+	memcpy(c_ivin, aead_req->iv, ctx->c_ctx.ivsize);
+}
+
+static void sec_auth_bd_fill_ex(struct sec_auth_ctx *ctx, int dir,
+			       struct sec_req *req, struct sec_sqe *sec_sqe)
+{
+	struct sec_aead_req *a_req = &req->aead_req;
+	struct sec_cipher_req *c_req = &req->c_req;
+	struct aead_request *aq = a_req->aead_req;
+
+	sec_sqe->type2.a_key_addr = cpu_to_le64(ctx->a_key_dma);
+
+	sec_sqe->type2.mac_key_alg =
+			cpu_to_le32(ctx->mac_len / SEC_SQE_LEN_RATE);
+
+	sec_sqe->type2.mac_key_alg |=
+			cpu_to_le32((u32)((ctx->a_key_len) /
+			SEC_SQE_LEN_RATE) << SEC_AKEY_OFFSET);
+
+	sec_sqe->type2.mac_key_alg |=
+			cpu_to_le32((u32)(ctx->a_alg) << SEC_AEAD_ALG_OFFSET);
+
+	sec_sqe->type_cipher_auth |= SEC_AUTH_TYPE1 << SEC_AUTH_OFFSET;
+
+	if (dir)
+		sec_sqe->sds_sa_type &= SEC_CIPHER_AUTH;
+	else
+		sec_sqe->sds_sa_type |= SEC_AUTH_CIPHER;
+
+	sec_sqe->type2.alen_ivllen = cpu_to_le32(c_req->c_len + aq->assoclen);
+
+	sec_sqe->type2.cipher_src_offset = cpu_to_le16((u16)aq->assoclen);
+
+	sec_sqe->type2.mac_addr =
+		cpu_to_le64(req->qp_ctx->res[req->req_id].out_mac_dma);
+}
+
+static int sec_aead_bd_fill(struct sec_ctx *ctx, struct sec_req *req)
+{
+	struct sec_auth_ctx *auth_ctx = &ctx->a_ctx;
+	struct sec_sqe *sec_sqe = &req->sec_sqe;
+	int ret;
+
+	ret = sec_skcipher_bd_fill(ctx, req);
+	if (unlikely(ret)) {
+		dev_err(SEC_CTX_DEV(ctx), "skcipher bd fill is error!\n");
+		return ret;
+	}
+
+	sec_auth_bd_fill_ex(auth_ctx, req->c_req.encrypt, req, sec_sqe);
+
+	return 0;
+}
+
+static void sec_aead_callback(struct sec_ctx *c, struct sec_req *req, int err)
+{
+	struct aead_request *a_req = req->aead_req.aead_req;
+	struct crypto_aead *tfm = crypto_aead_reqtfm(a_req);
+	struct sec_cipher_req *c_req = &req->c_req;
+	size_t authsize = crypto_aead_authsize(tfm);
+	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
+	size_t sz;
+
+	atomic_dec(&qp_ctx->pending_reqs);
+
+	if (!err && c->c_ctx.c_mode == SEC_CMODE_CBC && c_req->encrypt)
+		sec_update_iv(req, SEC_AEAD);
+
+	/* Copy output mac */
+	if (!err && c_req->encrypt) {
+		struct scatterlist *sgl = a_req->dst;
+
+		sz = sg_pcopy_from_buffer(sgl, sg_nents(sgl),
+					  qp_ctx->res[req->req_id].out_mac,
+					  authsize, a_req->cryptlen +
+					  a_req->assoclen);
+
+		if (unlikely(sz != authsize)) {
+			dev_err(SEC_CTX_DEV(req->ctx), "copy out mac err!\n");
+			err = -EINVAL;
+		}
+	}
+
+	sec_free_req_id(req);
+
+	if (req->fake_busy)
+		a_req->base.complete(&a_req->base, -EINPROGRESS);
+
+	a_req->base.complete(&a_req->base, err);
+}
+
+static void sec_request_uninit(struct sec_ctx *ctx, struct sec_req *req)
+{
+	struct sec_qp_ctx *qp_ctx = req->qp_ctx;
+
+	atomic_dec(&qp_ctx->pending_reqs);
+	sec_free_req_id(req);
+	sec_free_queue_id(ctx, req);
+}
+
+static int sec_request_init(struct sec_ctx *ctx, struct sec_req *req)
+{
+	struct sec_qp_ctx *qp_ctx;
+	int queue_id;
+
+	/* To load balance */
+	queue_id = sec_alloc_queue_id(ctx, req);
+	qp_ctx = &ctx->qp_ctx[queue_id];
+
+	req->req_id = sec_alloc_req_id(req, qp_ctx);
+	if (unlikely(req->req_id < 0)) {
+		sec_free_queue_id(ctx, req);
+		return req->req_id;
+	}
+
+	if (ctx->fake_req_limit <= atomic_inc_return(&qp_ctx->pending_reqs))
+		req->fake_busy = true;
+	else
+		req->fake_busy = false;
+
+	return 0;
+}
+
+static int sec_process(struct sec_ctx *ctx, struct sec_req *req)
+{
+	int ret;
+
+	ret = sec_request_init(ctx, req);
+	if (unlikely(ret))
+		return ret;
+
+	ret = sec_request_transfer(ctx, req);
+	if (unlikely(ret))
+		goto err_uninit_req;
+
+	/* Output IV as decrypto */
+	if (ctx->c_ctx.c_mode == SEC_CMODE_CBC && !req->c_req.encrypt)
+		sec_update_iv(req, ctx->alg_type);
+
+	ret = ctx->req_op->bd_send(ctx, req);
+	if (unlikely(ret != -EBUSY && ret != -EINPROGRESS)) {
+		dev_err_ratelimited(SEC_CTX_DEV(ctx), "send sec request failed!\n");
+		goto err_send_req;
+	}
+
+	return ret;
+
+err_send_req:
+	/* As failing, restore the IV from user */
+	if (ctx->c_ctx.c_mode == SEC_CMODE_CBC && !req->c_req.encrypt) {
+		if (ctx->alg_type == SEC_SKCIPHER)
+			memcpy(req->c_req.sk_req->iv,
+			       req->qp_ctx->res[req->req_id].c_ivin,
+			       ctx->c_ctx.ivsize);
+		else
+			memcpy(req->aead_req.aead_req->iv,
+			       req->qp_ctx->res[req->req_id].c_ivin,
+			       ctx->c_ctx.ivsize);
+	}
+
+	sec_request_untransfer(ctx, req);
+err_uninit_req:
+	sec_request_uninit(ctx, req);
+
+	return ret;
+}
+
+static const struct sec_req_op sec_skcipher_req_ops = {
+	.buf_map	= sec_skcipher_sgl_map,
+	.buf_unmap	= sec_skcipher_sgl_unmap,
+	.do_transfer	= sec_skcipher_copy_iv,
+	.bd_fill	= sec_skcipher_bd_fill,
+	.bd_send	= sec_bd_send,
+	.callback	= sec_skcipher_callback,
+	.process	= sec_process,
+};
+
+static const struct sec_req_op sec_aead_req_ops = {
+	.buf_map	= sec_aead_sgl_map,
+	.buf_unmap	= sec_aead_sgl_unmap,
+	.do_transfer	= sec_aead_copy_iv,
+	.bd_fill	= sec_aead_bd_fill,
+	.bd_send	= sec_bd_send,
+	.callback	= sec_aead_callback,
+	.process	= sec_process,
+};
+
+static int sec_skcipher_ctx_init(struct crypto_skcipher *tfm)
+{
+	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
+
+	ctx->req_op = &sec_skcipher_req_ops;
+
+	return sec_skcipher_init(tfm);
+}
+
+static void sec_skcipher_ctx_exit(struct crypto_skcipher *tfm)
+{
+	sec_skcipher_uninit(tfm);
+}
+
+static int sec_aead_init(struct crypto_aead *tfm)
+{
+	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
+	int ret;
+
+	crypto_aead_set_reqsize(tfm, sizeof(struct sec_req));
+	ctx->alg_type = SEC_AEAD;
+	ctx->c_ctx.ivsize = crypto_aead_ivsize(tfm);
+	if (ctx->c_ctx.ivsize > SEC_IV_SIZE) {
+		dev_err(SEC_CTX_DEV(ctx), "get error aead iv size!\n");
+		return -EINVAL;
+	}
+
+	ctx->req_op = &sec_aead_req_ops;
+	ret = sec_ctx_base_init(ctx);
+	if (ret)
+		return ret;
+
+	ret = sec_auth_init(ctx);
+	if (ret)
+		goto err_auth_init;
+
+	ret = sec_cipher_init(ctx);
+	if (ret)
+		goto err_cipher_init;
+
+	return ret;
+
+err_cipher_init:
+	sec_auth_uninit(ctx);
+err_auth_init:
+	sec_ctx_base_uninit(ctx);
+
+	return ret;
+}
+
+static void sec_aead_exit(struct crypto_aead *tfm)
+{
+	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
+
+	sec_cipher_uninit(ctx);
+	sec_auth_uninit(ctx);
+	sec_ctx_base_uninit(ctx);
+}
+
+static int sec_aead_ctx_init(struct crypto_aead *tfm, const char *hash_name)
+{
+	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
+	struct sec_auth_ctx *auth_ctx = &ctx->a_ctx;
+	int ret;
+
+	ret = sec_aead_init(tfm);
+	if (ret) {
+		pr_err("hisi_sec2: aead init error!\n");
+		return ret;
+	}
+
+	auth_ctx->hash_tfm = crypto_alloc_shash(hash_name, 0, 0);
+	if (IS_ERR(auth_ctx->hash_tfm)) {
+		dev_err(SEC_CTX_DEV(ctx), "aead alloc shash error!\n");
+		sec_aead_exit(tfm);
+		return PTR_ERR(auth_ctx->hash_tfm);
+	}
+
+	return 0;
+}
+
+static void sec_aead_ctx_exit(struct crypto_aead *tfm)
+{
+	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
+
+	crypto_free_shash(ctx->a_ctx.hash_tfm);
+	sec_aead_exit(tfm);
+}
+
+static int sec_aead_sha1_ctx_init(struct crypto_aead *tfm)
+{
+	return sec_aead_ctx_init(tfm, "sha1");
+}
+
+static int sec_aead_sha256_ctx_init(struct crypto_aead *tfm)
+{
+	return sec_aead_ctx_init(tfm, "sha256");
+}
+
+static int sec_aead_sha512_ctx_init(struct crypto_aead *tfm)
+{
+	return sec_aead_ctx_init(tfm, "sha512");
+}
+
+static int sec_skcipher_param_check(struct sec_ctx *ctx, struct sec_req *sreq)
+{
+	struct skcipher_request *sk_req = sreq->c_req.sk_req;
+	struct device *dev = SEC_CTX_DEV(ctx);
+	u8 c_alg = ctx->c_ctx.c_alg;
+
+	if (unlikely(!sk_req->src || !sk_req->dst)) {
+		dev_err(dev, "skcipher input param error!\n");
+		return -EINVAL;
+	}
+	sreq->c_req.c_len = sk_req->cryptlen;
+	if (c_alg == SEC_CALG_3DES) {
+		if (unlikely(sk_req->cryptlen & (DES3_EDE_BLOCK_SIZE - 1))) {
+			dev_err(dev, "skcipher 3des input length error!\n");
+			return -EINVAL;
+		}
+		return 0;
+	} else if (c_alg == SEC_CALG_AES || c_alg == SEC_CALG_SM4) {
+		if (unlikely(sk_req->cryptlen & (AES_BLOCK_SIZE - 1))) {
+			dev_err(dev, "skcipher aes input length error!\n");
+			return -EINVAL;
+		}
+		return 0;
+	}
+
+	dev_err(dev, "skcipher algorithm error!\n");
+	return -EINVAL;
+}
+
+static int sec_skcipher_crypto(struct skcipher_request *sk_req, bool encrypt)
+{
+	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(sk_req);
+	struct sec_req *req = skcipher_request_ctx(sk_req);
+	struct sec_ctx *ctx = crypto_skcipher_ctx(tfm);
+	int ret;
+
+	if (!sk_req->cryptlen)
+		return 0;
+
+	req->c_req.sk_req = sk_req;
+	req->c_req.encrypt = encrypt;
+	req->ctx = ctx;
+
+	ret = sec_skcipher_param_check(ctx, req);
+	if (unlikely(ret))
+		return -EINVAL;
+
+	return ctx->req_op->process(ctx, req);
+}
+
+static int sec_skcipher_encrypt(struct skcipher_request *sk_req)
+{
+	return sec_skcipher_crypto(sk_req, true);
+}
+
+static int sec_skcipher_decrypt(struct skcipher_request *sk_req)
+{
+	return sec_skcipher_crypto(sk_req, false);
+}
+
+#define SEC_SKCIPHER_GEN_ALG(sec_cra_name, sec_set_key, sec_min_key_size, \
+	sec_max_key_size, ctx_init, ctx_exit, blk_size, iv_size)\
+{\
+	.base = {\
+		.cra_name = sec_cra_name,\
+		.cra_driver_name = "hisi_sec_"sec_cra_name,\
+		.cra_priority = SEC_PRIORITY,\
+		.cra_flags = CRYPTO_ALG_ASYNC,\
+		.cra_blocksize = blk_size,\
+		.cra_ctxsize = sizeof(struct sec_ctx),\
+		.cra_module = THIS_MODULE,\
+	},\
+	.init = ctx_init,\
+	.exit = ctx_exit,\
+	.setkey = sec_set_key,\
+	.decrypt = sec_skcipher_decrypt,\
+	.encrypt = sec_skcipher_encrypt,\
+	.min_keysize = sec_min_key_size,\
+	.max_keysize = sec_max_key_size,\
+	.ivsize = iv_size,\
+},
+
+#define SEC_SKCIPHER_ALG(name, key_func, min_key_size, \
+	max_key_size, blk_size, iv_size) \
+	SEC_SKCIPHER_GEN_ALG(name, key_func, min_key_size, max_key_size, \
+	sec_skcipher_ctx_init, sec_skcipher_ctx_exit, blk_size, iv_size)
+
+static struct skcipher_alg sec_skciphers[] = {
+	SEC_SKCIPHER_ALG("ecb(aes)", sec_setkey_aes_ecb,
+			 AES_MIN_KEY_SIZE, AES_MAX_KEY_SIZE,
+			 AES_BLOCK_SIZE, 0)
+
+	SEC_SKCIPHER_ALG("cbc(aes)", sec_setkey_aes_cbc,
+			 AES_MIN_KEY_SIZE, AES_MAX_KEY_SIZE,
+			 AES_BLOCK_SIZE, AES_BLOCK_SIZE)
+
+	SEC_SKCIPHER_ALG("xts(aes)", sec_setkey_aes_xts,
+			 SEC_XTS_MIN_KEY_SIZE, SEC_XTS_MAX_KEY_SIZE,
+			 AES_BLOCK_SIZE, AES_BLOCK_SIZE)
+
+	SEC_SKCIPHER_ALG("ecb(des3_ede)", sec_setkey_3des_ecb,
+			 SEC_DES3_2KEY_SIZE, SEC_DES3_3KEY_SIZE,
+			 DES3_EDE_BLOCK_SIZE, 0)
+
+	SEC_SKCIPHER_ALG("cbc(des3_ede)", sec_setkey_3des_cbc,
+			 SEC_DES3_2KEY_SIZE, SEC_DES3_3KEY_SIZE,
+			 DES3_EDE_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE)
+
+	SEC_SKCIPHER_ALG("xts(sm4)", sec_setkey_sm4_xts,
+			 SEC_XTS_MIN_KEY_SIZE, SEC_XTS_MIN_KEY_SIZE,
+			 AES_BLOCK_SIZE, AES_BLOCK_SIZE)
+
+	SEC_SKCIPHER_ALG("cbc(sm4)", sec_setkey_sm4_cbc,
+			 AES_MIN_KEY_SIZE, AES_MIN_KEY_SIZE,
+			 AES_BLOCK_SIZE, AES_BLOCK_SIZE)
+};
+
+static int sec_aead_param_check(struct sec_ctx *ctx, struct sec_req *sreq)
+{
+	u8 c_alg = ctx->c_ctx.c_alg;
+	struct aead_request *req = sreq->aead_req.aead_req;
+	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
+	size_t authsize = crypto_aead_authsize(tfm);
+
+	if (unlikely(!req->src || !req->dst || !req->cryptlen)) {
+		dev_err(SEC_CTX_DEV(ctx), "aead input param error!\n");
+		return -EINVAL;
+	}
+
+	/* Support AES only */
+	if (unlikely(c_alg != SEC_CALG_AES)) {
+		dev_err(SEC_CTX_DEV(ctx), "aead crypto alg error!\n");
+		return -EINVAL;
+
+	}
+	if (sreq->c_req.encrypt)
+		sreq->c_req.c_len = req->cryptlen;
+	else
+		sreq->c_req.c_len = req->cryptlen - authsize;
+
+	if (unlikely(sreq->c_req.c_len & (AES_BLOCK_SIZE - 1))) {
+		dev_err(SEC_CTX_DEV(ctx), "aead crypto length error!\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int sec_aead_crypto(struct aead_request *a_req, bool encrypt)
+{
+	struct crypto_aead *tfm = crypto_aead_reqtfm(a_req);
+	struct sec_req *req = aead_request_ctx(a_req);
+	struct sec_ctx *ctx = crypto_aead_ctx(tfm);
+	int ret;
+
+	req->aead_req.aead_req = a_req;
+	req->c_req.encrypt = encrypt;
+	req->ctx = ctx;
+
+	ret = sec_aead_param_check(ctx, req);
+	if (unlikely(ret))
+		return -EINVAL;
+
+	return ctx->req_op->process(ctx, req);
+}
+
+static int sec_aead_encrypt(struct aead_request *a_req)
+{
+	return sec_aead_crypto(a_req, true);
+}
+
+static int sec_aead_decrypt(struct aead_request *a_req)
+{
+	return sec_aead_crypto(a_req, false);
+}
+
+#define SEC_AEAD_GEN_ALG(sec_cra_name, sec_set_key, ctx_init,\
+			 ctx_exit, blk_size, iv_size, max_authsize)\
+{\
+	.base = {\
+		.cra_name = sec_cra_name,\
+		.cra_driver_name = "hisi_sec_"sec_cra_name,\
+		.cra_priority = SEC_PRIORITY,\
+		.cra_flags = CRYPTO_ALG_ASYNC,\
+		.cra_blocksize = blk_size,\
+		.cra_ctxsize = sizeof(struct sec_ctx),\
+		.cra_module = THIS_MODULE,\
+	},\
+	.init = ctx_init,\
+	.exit = ctx_exit,\
+	.setkey = sec_set_key,\
+	.decrypt = sec_aead_decrypt,\
+	.encrypt = sec_aead_encrypt,\
+	.ivsize = iv_size,\
+	.maxauthsize = max_authsize,\
+}
+
+#define SEC_AEAD_ALG(algname, keyfunc, aead_init, blksize, ivsize, authsize)\
+	SEC_AEAD_GEN_ALG(algname, keyfunc, aead_init,\
+			sec_aead_ctx_exit, blksize, ivsize, authsize)
+
+static struct aead_alg sec_aeads[] = {
+	SEC_AEAD_ALG("authenc(hmac(sha1),cbc(aes))",
+		     sec_setkey_aes_cbc_sha1, sec_aead_sha1_ctx_init,
+		     AES_BLOCK_SIZE, AES_BLOCK_SIZE, SHA1_DIGEST_SIZE),
+
+	SEC_AEAD_ALG("authenc(hmac(sha256),cbc(aes))",
+		     sec_setkey_aes_cbc_sha256, sec_aead_sha256_ctx_init,
+		     AES_BLOCK_SIZE, AES_BLOCK_SIZE, SHA256_DIGEST_SIZE),
+
+	SEC_AEAD_ALG("authenc(hmac(sha512),cbc(aes))",
+		     sec_setkey_aes_cbc_sha512, sec_aead_sha512_ctx_init,
+		     AES_BLOCK_SIZE, AES_BLOCK_SIZE, SHA512_DIGEST_SIZE),
+};
+
+int sec_register_to_crypto(void)
+{
+	int ret = 0;
+
+	/* To avoid repeat register */
+	if (atomic_add_return(1, &sec_active_devs) == 1) {
+		ret = crypto_register_skciphers(sec_skciphers,
+						ARRAY_SIZE(sec_skciphers));
+		if (ret)
+			return ret;
+
+		ret = crypto_register_aeads(sec_aeads, ARRAY_SIZE(sec_aeads));
+		if (ret)
+			goto reg_aead_fail;
+	}
+
+	return ret;
+
+reg_aead_fail:
+	crypto_unregister_skciphers(sec_skciphers, ARRAY_SIZE(sec_skciphers));
+
+	return ret;
+}
+
+void sec_unregister_from_crypto(void)
+{
+	if (atomic_sub_return(1, &sec_active_devs) == 0) {
+		crypto_unregister_skciphers(sec_skciphers,
+					    ARRAY_SIZE(sec_skciphers));
+		crypto_unregister_aeads(sec_aeads, ARRAY_SIZE(sec_aeads));
+	}
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/hisilicon/sec2/sec_crypto.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/hisilicon/sec2/sec_crypto.h
@@ -0,0 +1,216 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2019 HiSilicon Limited. */
+
+#ifndef __HISI_SEC_V2_CRYPTO_H
+#define __HISI_SEC_V2_CRYPTO_H
+
+#define SEC_IV_SIZE		24
+#define SEC_MAX_KEY_SIZE	64
+#define SEC_COMM_SCENE		0
+
+enum sec_calg {
+	SEC_CALG_3DES = 0x1,
+	SEC_CALG_AES  = 0x2,
+	SEC_CALG_SM4  = 0x3,
+};
+
+enum sec_hash_alg {
+	SEC_A_HMAC_SHA1   = 0x10,
+	SEC_A_HMAC_SHA256 = 0x11,
+	SEC_A_HMAC_SHA512 = 0x15,
+};
+
+enum sec_mac_len {
+	SEC_HMAC_SHA1_MAC   = 20,
+	SEC_HMAC_SHA256_MAC = 32,
+	SEC_HMAC_SHA512_MAC = 64,
+};
+
+enum sec_cmode {
+	SEC_CMODE_ECB    = 0x0,
+	SEC_CMODE_CBC    = 0x1,
+	SEC_CMODE_CTR    = 0x4,
+	SEC_CMODE_XTS    = 0x7,
+};
+
+enum sec_ckey_type {
+	SEC_CKEY_128BIT = 0x0,
+	SEC_CKEY_192BIT = 0x1,
+	SEC_CKEY_256BIT = 0x2,
+	SEC_CKEY_3DES_3KEY = 0x1,
+	SEC_CKEY_3DES_2KEY = 0x3,
+};
+
+enum sec_bd_type {
+	SEC_BD_TYPE1 = 0x1,
+	SEC_BD_TYPE2 = 0x2,
+};
+
+enum sec_auth {
+	SEC_NO_AUTH = 0x0,
+	SEC_AUTH_TYPE1 = 0x1,
+	SEC_AUTH_TYPE2 = 0x2,
+};
+
+enum sec_cipher_dir {
+	SEC_CIPHER_ENC = 0x1,
+	SEC_CIPHER_DEC = 0x2,
+};
+
+enum sec_addr_type {
+	SEC_PBUF = 0x0,
+	SEC_SGL  = 0x1,
+	SEC_PRP  = 0x2,
+};
+
+struct sec_sqe_type2 {
+
+	/*
+	 * mac_len: 0~4 bits
+	 * a_key_len: 5~10 bits
+	 * a_alg: 11~16 bits
+	 */
+	__le32 mac_key_alg;
+
+	/*
+	 * c_icv_len: 0~5 bits
+	 * c_width: 6~8 bits
+	 * c_key_len: 9~11 bits
+	 * c_mode: 12~15 bits
+	 */
+	__le16 icvw_kmode;
+
+	/* c_alg: 0~3 bits */
+	__u8 c_alg;
+	__u8 rsvd4;
+
+	/*
+	 * a_len: 0~23 bits
+	 * iv_offset_l: 24~31 bits
+	 */
+	__le32 alen_ivllen;
+
+	/*
+	 * c_len: 0~23 bits
+	 * iv_offset_h: 24~31 bits
+	 */
+	__le32 clen_ivhlen;
+
+	__le16 auth_src_offset;
+	__le16 cipher_src_offset;
+	__le16 cs_ip_header_offset;
+	__le16 cs_udp_header_offset;
+	__le16 pass_word_len;
+	__le16 dk_len;
+	__u8 salt3;
+	__u8 salt2;
+	__u8 salt1;
+	__u8 salt0;
+
+	__le16 tag;
+	__le16 rsvd5;
+
+	/*
+	 * c_pad_type: 0~3 bits
+	 * c_pad_len: 4~11 bits
+	 * c_pad_data_type: 12~15 bits
+	 */
+	__le16 cph_pad;
+
+	/* c_pad_len_field: 0~1 bits */
+	__le16 c_pad_len_field;
+
+
+	__le64 long_a_data_len;
+	__le64 a_ivin_addr;
+	__le64 a_key_addr;
+	__le64 mac_addr;
+	__le64 c_ivin_addr;
+	__le64 c_key_addr;
+
+	__le64 data_src_addr;
+	__le64 data_dst_addr;
+
+	/*
+	 * done: 0 bit
+	 * icv: 1~3 bits
+	 * csc: 4~6 bits
+	 * flag: 7-10 bits
+	 * dif_check: 11~13 bits
+	 */
+	__le16 done_flag;
+
+	__u8 error_type;
+	__u8 warning_type;
+	__u8 mac_i3;
+	__u8 mac_i2;
+	__u8 mac_i1;
+	__u8 mac_i0;
+	__le16 check_sum_i;
+	__u8 tls_pad_len_i;
+	__u8 rsvd12;
+	__le32 counter;
+};
+
+struct sec_sqe {
+	/*
+	 * type:	0~3 bits
+	 * cipher:	4~5 bits
+	 * auth:	6~7 bit s
+	 */
+	__u8 type_cipher_auth;
+
+	/*
+	 * seq:	0 bit
+	 * de:	1~2 bits
+	 * scene:	3~6 bits
+	 * src_addr_type: ~7 bit, with sdm_addr_type 0-1 bits
+	 */
+	__u8 sds_sa_type;
+
+	/*
+	 * src_addr_type: 0~1 bits, not used now,
+	 * if support PRP, set this field, or set zero.
+	 * dst_addr_type: 2~4 bits
+	 * mac_addr_type: 5~7 bits
+	 */
+	__u8 sdm_addr_type;
+	__u8 rsvd0;
+
+	/*
+	 * nonce_len(type2): 0~3 bits
+	 * huk(type2): 4 bit
+	 * key_s(type2): 5 bit
+	 * ci_gen: 6~7 bits
+	 */
+	__u8 huk_key_ci;
+
+	/*
+	 * ai_gen: 0~1 bits
+	 * a_pad(type2): 2~3 bits
+	 * c_s(type2): 4~5 bits
+	 */
+	__u8 ai_apd_cs;
+
+	/*
+	 * rhf(type2): 0 bit
+	 * c_key_type: 1~2 bits
+	 * a_key_type: 3~4 bits
+	 * write_frame_len(type2): 5~7 bits
+	 */
+	__u8 rca_key_frm;
+
+	/*
+	 * cal_iv_addr_en(type2): 0 bit
+	 * tls_up(type2): 1 bit
+	 * inveld: 7 bit
+	 */
+	__u8 iv_tls_ld;
+
+	/* Just using type2 BD now */
+	struct sec_sqe_type2 type2;
+};
+
+int sec_register_to_crypto(void);
+void sec_unregister_from_crypto(void);
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/hisilicon/sec2/sec_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/hisilicon/sec2/sec_main.c
@@ -0,0 +1,1124 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2019 HiSilicon Limited. */
+
+#include <linux/acpi.h>
+#include <linux/aer.h>
+#include <linux/bitops.h>
+#include <linux/debugfs.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/seq_file.h>
+#include <linux/topology.h>
+
+#include "sec.h"
+
+#define SEC_VF_NUM			63
+#define SEC_QUEUE_NUM_V1		4096
+#define SEC_QUEUE_NUM_V2		1024
+#define SEC_PF_PCI_DEVICE_ID		0xa255
+#define SEC_VF_PCI_DEVICE_ID		0xa256
+
+#define SEC_BD_ERR_CHK_EN0		0xEFFFFFFF
+#define SEC_BD_ERR_CHK_EN1		0x7ffff7fd
+#define SEC_BD_ERR_CHK_EN3		0xffffbfff
+
+#define SEC_SQE_SIZE			128
+#define SEC_SQ_SIZE			(SEC_SQE_SIZE * QM_Q_DEPTH)
+#define SEC_PF_DEF_Q_NUM		256
+#define SEC_PF_DEF_Q_BASE		0
+#define SEC_CTX_Q_NUM_DEF		2
+#define SEC_CTX_Q_NUM_MAX		32
+
+#define SEC_CTRL_CNT_CLR_CE		0x301120
+#define SEC_CTRL_CNT_CLR_CE_BIT		BIT(0)
+#define SEC_ENGINE_PF_CFG_OFF		0x300000
+#define SEC_ACC_COMMON_REG_OFF		0x1000
+#define SEC_CORE_INT_SOURCE		0x301010
+#define SEC_CORE_INT_MASK		0x301000
+#define SEC_CORE_INT_STATUS		0x301008
+#define SEC_CORE_SRAM_ECC_ERR_INFO	0x301C14
+#define SEC_ECC_NUM(err)			(((err) >> 16) & 0xFF)
+#define SEC_ECC_ADDR(err)			((err) >> 0)
+#define SEC_CORE_INT_DISABLE		0x0
+#define SEC_CORE_INT_ENABLE		0x1ff
+#define SEC_CORE_INT_CLEAR		0x1ff
+#define SEC_SAA_ENABLE			0x17f
+
+#define SEC_RAS_CE_REG			0x301050
+#define SEC_RAS_FE_REG			0x301054
+#define SEC_RAS_NFE_REG			0x301058
+#define SEC_RAS_CE_ENB_MSK		0x88
+#define SEC_RAS_FE_ENB_MSK		0x0
+#define SEC_RAS_NFE_ENB_MSK		0x177
+#define SEC_RAS_DISABLE			0x0
+#define SEC_MEM_START_INIT_REG		0x0100
+#define SEC_MEM_INIT_DONE_REG		0x0104
+
+#define SEC_CONTROL_REG			0x0200
+#define SEC_TRNG_EN_SHIFT		8
+#define SEC_CLK_GATE_ENABLE		BIT(3)
+#define SEC_CLK_GATE_DISABLE		(~BIT(3))
+#define SEC_AXI_SHUTDOWN_ENABLE	BIT(12)
+#define SEC_AXI_SHUTDOWN_DISABLE	0xFFFFEFFF
+
+#define SEC_INTERFACE_USER_CTRL0_REG	0x0220
+#define SEC_INTERFACE_USER_CTRL1_REG	0x0224
+#define SEC_SAA_EN_REG					0x0270
+#define SEC_BD_ERR_CHK_EN_REG0		0x0380
+#define SEC_BD_ERR_CHK_EN_REG1		0x0384
+#define SEC_BD_ERR_CHK_EN_REG3		0x038c
+
+#define SEC_USER0_SMMU_NORMAL		(BIT(23) | BIT(15))
+#define SEC_USER1_SMMU_NORMAL		(BIT(31) | BIT(23) | BIT(15) | BIT(7))
+#define SEC_CORE_INT_STATUS_M_ECC	BIT(2)
+
+#define SEC_DELAY_10_US			10
+#define SEC_POLL_TIMEOUT_US		1000
+#define SEC_DBGFS_VAL_MAX_LEN		20
+#define SEC_SINGLE_PORT_MAX_TRANS	0x2060
+
+#define SEC_ADDR(qm, offset) ((qm)->io_base + (offset) + \
+			     SEC_ENGINE_PF_CFG_OFF + SEC_ACC_COMMON_REG_OFF)
+
+struct sec_hw_error {
+	u32 int_msk;
+	const char *msg;
+};
+
+static const char sec_name[] = "hisi_sec2";
+static struct dentry *sec_debugfs_root;
+static LIST_HEAD(sec_list);
+static DEFINE_MUTEX(sec_list_lock);
+
+static const struct sec_hw_error sec_hw_errors[] = {
+	{.int_msk = BIT(0), .msg = "sec_axi_rresp_err_rint"},
+	{.int_msk = BIT(1), .msg = "sec_axi_bresp_err_rint"},
+	{.int_msk = BIT(2), .msg = "sec_ecc_2bit_err_rint"},
+	{.int_msk = BIT(3), .msg = "sec_ecc_1bit_err_rint"},
+	{.int_msk = BIT(4), .msg = "sec_req_trng_timeout_rint"},
+	{.int_msk = BIT(5), .msg = "sec_fsm_hbeat_rint"},
+	{.int_msk = BIT(6), .msg = "sec_channel_req_rng_timeout_rint"},
+	{.int_msk = BIT(7), .msg = "sec_bd_err_rint"},
+	{.int_msk = BIT(8), .msg = "sec_chain_buff_err_rint"},
+	{ /* sentinel */ }
+};
+
+struct sec_dev *sec_find_device(int node)
+{
+#define SEC_NUMA_MAX_DISTANCE	100
+	int min_distance = SEC_NUMA_MAX_DISTANCE;
+	int dev_node = 0, free_qp_num = 0;
+	struct sec_dev *sec, *ret = NULL;
+	struct hisi_qm *qm;
+	struct device *dev;
+
+	mutex_lock(&sec_list_lock);
+	list_for_each_entry(sec, &sec_list, list) {
+		qm = &sec->qm;
+		dev = &qm->pdev->dev;
+#ifdef CONFIG_NUMA
+		dev_node = dev->numa_node;
+		if (dev_node < 0)
+			dev_node = 0;
+#endif
+		if (node_distance(dev_node, node) < min_distance) {
+			free_qp_num = hisi_qm_get_free_qp_num(qm);
+			if (free_qp_num >= sec->ctx_q_num) {
+				ret = sec;
+				min_distance = node_distance(dev_node, node);
+			}
+		}
+	}
+	mutex_unlock(&sec_list_lock);
+
+	return ret;
+}
+
+static const char * const sec_dbg_file_name[] = {
+	[SEC_CURRENT_QM] = "current_qm",
+	[SEC_CLEAR_ENABLE] = "clear_enable",
+};
+
+static struct debugfs_reg32 sec_dfx_regs[] = {
+	{"SEC_PF_ABNORMAL_INT_SOURCE    ",  0x301010},
+	{"SEC_SAA_EN                    ",  0x301270},
+	{"SEC_BD_LATENCY_MIN            ",  0x301600},
+	{"SEC_BD_LATENCY_MAX            ",  0x301608},
+	{"SEC_BD_LATENCY_AVG            ",  0x30160C},
+	{"SEC_BD_NUM_IN_SAA0            ",  0x301670},
+	{"SEC_BD_NUM_IN_SAA1            ",  0x301674},
+	{"SEC_BD_NUM_IN_SEC             ",  0x301680},
+	{"SEC_ECC_1BIT_CNT              ",  0x301C00},
+	{"SEC_ECC_1BIT_INFO             ",  0x301C04},
+	{"SEC_ECC_2BIT_CNT              ",  0x301C10},
+	{"SEC_ECC_2BIT_INFO             ",  0x301C14},
+	{"SEC_BD_SAA0                   ",  0x301C20},
+	{"SEC_BD_SAA1                   ",  0x301C24},
+	{"SEC_BD_SAA2                   ",  0x301C28},
+	{"SEC_BD_SAA3                   ",  0x301C2C},
+	{"SEC_BD_SAA4                   ",  0x301C30},
+	{"SEC_BD_SAA5                   ",  0x301C34},
+	{"SEC_BD_SAA6                   ",  0x301C38},
+	{"SEC_BD_SAA7                   ",  0x301C3C},
+	{"SEC_BD_SAA8                   ",  0x301C40},
+};
+
+static int sec_pf_q_num_set(const char *val, const struct kernel_param *kp)
+{
+	struct pci_dev *pdev;
+	u32 n, q_num;
+	u8 rev_id;
+	int ret;
+
+	if (!val)
+		return -EINVAL;
+
+	pdev = pci_get_device(PCI_VENDOR_ID_HUAWEI,
+			      SEC_PF_PCI_DEVICE_ID, NULL);
+	if (!pdev) {
+		q_num = min_t(u32, SEC_QUEUE_NUM_V1, SEC_QUEUE_NUM_V2);
+		pr_info("No device, suppose queue number is %d!\n", q_num);
+	} else {
+		rev_id = pdev->revision;
+
+		switch (rev_id) {
+		case QM_HW_V1:
+			q_num = SEC_QUEUE_NUM_V1;
+			break;
+		case QM_HW_V2:
+			q_num = SEC_QUEUE_NUM_V2;
+			break;
+		default:
+			return -EINVAL;
+		}
+	}
+
+	ret = kstrtou32(val, 10, &n);
+	if (ret || !n || n > q_num)
+		return -EINVAL;
+
+	return param_set_int(val, kp);
+}
+
+static const struct kernel_param_ops sec_pf_q_num_ops = {
+	.set = sec_pf_q_num_set,
+	.get = param_get_int,
+};
+static u32 pf_q_num = SEC_PF_DEF_Q_NUM;
+module_param_cb(pf_q_num, &sec_pf_q_num_ops, &pf_q_num, 0444);
+MODULE_PARM_DESC(pf_q_num, "Number of queues in PF(v1 0-4096, v2 0-1024)");
+
+static int sec_ctx_q_num_set(const char *val, const struct kernel_param *kp)
+{
+	u32 ctx_q_num;
+	int ret;
+
+	if (!val)
+		return -EINVAL;
+
+	ret = kstrtou32(val, 10, &ctx_q_num);
+	if (ret)
+		return -EINVAL;
+
+	if (!ctx_q_num || ctx_q_num > SEC_CTX_Q_NUM_MAX || ctx_q_num & 0x1) {
+		pr_err("ctx queue num[%u] is invalid!\n", ctx_q_num);
+		return -EINVAL;
+	}
+
+	return param_set_int(val, kp);
+}
+
+static const struct kernel_param_ops sec_ctx_q_num_ops = {
+	.set = sec_ctx_q_num_set,
+	.get = param_get_int,
+};
+static u32 ctx_q_num = SEC_CTX_Q_NUM_DEF;
+module_param_cb(ctx_q_num, &sec_ctx_q_num_ops, &ctx_q_num, 0444);
+MODULE_PARM_DESC(ctx_q_num, "Queue num in ctx (2 default, 2, 4, ..., 32)");
+
+static const struct pci_device_id sec_dev_ids[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_HUAWEI, SEC_PF_PCI_DEVICE_ID) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_HUAWEI, SEC_VF_PCI_DEVICE_ID) },
+	{ 0, }
+};
+MODULE_DEVICE_TABLE(pci, sec_dev_ids);
+
+static inline void sec_add_to_list(struct sec_dev *sec)
+{
+	mutex_lock(&sec_list_lock);
+	list_add_tail(&sec->list, &sec_list);
+	mutex_unlock(&sec_list_lock);
+}
+
+static inline void sec_remove_from_list(struct sec_dev *sec)
+{
+	mutex_lock(&sec_list_lock);
+	list_del(&sec->list);
+	mutex_unlock(&sec_list_lock);
+}
+
+static u8 sec_get_endian(struct sec_dev *sec)
+{
+	struct hisi_qm *qm = &sec->qm;
+	u32 reg;
+
+	/*
+	 * As for VF, it is a wrong way to get endian setting by
+	 * reading a register of the engine
+	 */
+	if (qm->pdev->is_virtfn) {
+		dev_err_ratelimited(&qm->pdev->dev,
+				    "cannot access a register in VF!\n");
+		return SEC_LE;
+	}
+	reg = readl_relaxed(qm->io_base + SEC_ENGINE_PF_CFG_OFF +
+			    SEC_ACC_COMMON_REG_OFF + SEC_CONTROL_REG);
+
+	/* BD little endian mode */
+	if (!(reg & BIT(0)))
+		return SEC_LE;
+
+	/* BD 32-bits big endian mode */
+	else if (!(reg & BIT(1)))
+		return SEC_32BE;
+
+	/* BD 64-bits big endian mode */
+	else
+		return SEC_64BE;
+}
+
+static int sec_engine_init(struct sec_dev *sec)
+{
+	struct hisi_qm *qm = &sec->qm;
+	int ret;
+	u32 reg;
+
+	/* disable clock gate control */
+	reg = readl_relaxed(SEC_ADDR(qm, SEC_CONTROL_REG));
+	reg &= SEC_CLK_GATE_DISABLE;
+	writel_relaxed(reg, SEC_ADDR(qm, SEC_CONTROL_REG));
+
+	writel_relaxed(0x1, SEC_ADDR(qm, SEC_MEM_START_INIT_REG));
+
+	ret = readl_relaxed_poll_timeout(SEC_ADDR(qm, SEC_MEM_INIT_DONE_REG),
+					 reg, reg & 0x1, SEC_DELAY_10_US,
+					 SEC_POLL_TIMEOUT_US);
+	if (ret) {
+		dev_err(&qm->pdev->dev, "fail to init sec mem\n");
+		return ret;
+	}
+
+	reg = readl_relaxed(SEC_ADDR(qm, SEC_CONTROL_REG));
+	reg |= (0x1 << SEC_TRNG_EN_SHIFT);
+	writel_relaxed(reg, SEC_ADDR(qm, SEC_CONTROL_REG));
+
+	reg = readl_relaxed(SEC_ADDR(qm, SEC_INTERFACE_USER_CTRL0_REG));
+	reg |= SEC_USER0_SMMU_NORMAL;
+	writel_relaxed(reg, SEC_ADDR(qm, SEC_INTERFACE_USER_CTRL0_REG));
+
+	reg = readl_relaxed(SEC_ADDR(qm, SEC_INTERFACE_USER_CTRL1_REG));
+	reg |= SEC_USER1_SMMU_NORMAL;
+	writel_relaxed(reg, SEC_ADDR(qm, SEC_INTERFACE_USER_CTRL1_REG));
+
+	writel(SEC_SINGLE_PORT_MAX_TRANS,
+	       qm->io_base + AM_CFG_SINGLE_PORT_MAX_TRANS);
+
+	writel(SEC_SAA_ENABLE, SEC_ADDR(qm, SEC_SAA_EN_REG));
+
+	/* Enable sm4 extra mode, as ctr/ecb */
+	writel_relaxed(SEC_BD_ERR_CHK_EN0,
+		       SEC_ADDR(qm, SEC_BD_ERR_CHK_EN_REG0));
+	/* Enable sm4 xts mode multiple iv */
+	writel_relaxed(SEC_BD_ERR_CHK_EN1,
+		       SEC_ADDR(qm, SEC_BD_ERR_CHK_EN_REG1));
+	writel_relaxed(SEC_BD_ERR_CHK_EN3,
+		       SEC_ADDR(qm, SEC_BD_ERR_CHK_EN_REG3));
+
+	/* config endian */
+	reg = readl_relaxed(SEC_ADDR(qm, SEC_CONTROL_REG));
+	reg |= sec_get_endian(sec);
+	writel_relaxed(reg, SEC_ADDR(qm, SEC_CONTROL_REG));
+
+	return 0;
+}
+
+static int sec_set_user_domain_and_cache(struct sec_dev *sec)
+{
+	struct hisi_qm *qm = &sec->qm;
+
+	/* qm user domain */
+	writel(AXUSER_BASE, qm->io_base + QM_ARUSER_M_CFG_1);
+	writel(ARUSER_M_CFG_ENABLE, qm->io_base + QM_ARUSER_M_CFG_ENABLE);
+	writel(AXUSER_BASE, qm->io_base + QM_AWUSER_M_CFG_1);
+	writel(AWUSER_M_CFG_ENABLE, qm->io_base + QM_AWUSER_M_CFG_ENABLE);
+	writel(WUSER_M_CFG_ENABLE, qm->io_base + QM_WUSER_M_CFG_ENABLE);
+
+	/* qm cache */
+	writel(AXI_M_CFG, qm->io_base + QM_AXI_M_CFG);
+	writel(AXI_M_CFG_ENABLE, qm->io_base + QM_AXI_M_CFG_ENABLE);
+
+	/* disable FLR triggered by BME(bus master enable) */
+	writel(PEH_AXUSER_CFG, qm->io_base + QM_PEH_AXUSER_CFG);
+	writel(PEH_AXUSER_CFG_ENABLE, qm->io_base + QM_PEH_AXUSER_CFG_ENABLE);
+
+	/* enable sqc,cqc writeback */
+	writel(SQC_CACHE_ENABLE | CQC_CACHE_ENABLE | SQC_CACHE_WB_ENABLE |
+	       CQC_CACHE_WB_ENABLE | FIELD_PREP(SQC_CACHE_WB_THRD, 1) |
+	       FIELD_PREP(CQC_CACHE_WB_THRD, 1), qm->io_base + QM_CACHE_CTL);
+
+	return sec_engine_init(sec);
+}
+
+/* sec_debug_regs_clear() - clear the sec debug regs */
+static void sec_debug_regs_clear(struct hisi_qm *qm)
+{
+	/* clear current_qm */
+	writel(0x0, qm->io_base + QM_DFX_MB_CNT_VF);
+	writel(0x0, qm->io_base + QM_DFX_DB_CNT_VF);
+
+	/* clear rdclr_en */
+	writel(0x0, qm->io_base + SEC_CTRL_CNT_CLR_CE);
+
+	hisi_qm_debug_regs_clear(qm);
+}
+
+static void sec_hw_error_enable(struct hisi_qm *qm)
+{
+	u32 val;
+
+	if (qm->ver == QM_HW_V1) {
+		writel(SEC_CORE_INT_DISABLE, qm->io_base + SEC_CORE_INT_MASK);
+		dev_info(&qm->pdev->dev, "V1 not support hw error handle\n");
+		return;
+	}
+
+	val = readl(SEC_ADDR(qm, SEC_CONTROL_REG));
+
+	/* clear SEC hw error source if having */
+	writel(SEC_CORE_INT_CLEAR, qm->io_base + SEC_CORE_INT_SOURCE);
+
+	/* enable SEC hw error interrupts */
+	writel(SEC_CORE_INT_ENABLE, qm->io_base + SEC_CORE_INT_MASK);
+
+	/* enable RAS int */
+	writel(SEC_RAS_CE_ENB_MSK, qm->io_base + SEC_RAS_CE_REG);
+	writel(SEC_RAS_FE_ENB_MSK, qm->io_base + SEC_RAS_FE_REG);
+	writel(SEC_RAS_NFE_ENB_MSK, qm->io_base + SEC_RAS_NFE_REG);
+
+	/* enable SEC block master OOO when m-bit error occur */
+	val = val | SEC_AXI_SHUTDOWN_ENABLE;
+
+	writel(val, SEC_ADDR(qm, SEC_CONTROL_REG));
+}
+
+static void sec_hw_error_disable(struct hisi_qm *qm)
+{
+	u32 val;
+
+	val = readl(SEC_ADDR(qm, SEC_CONTROL_REG));
+
+	/* disable RAS int */
+	writel(SEC_RAS_DISABLE, qm->io_base + SEC_RAS_CE_REG);
+	writel(SEC_RAS_DISABLE, qm->io_base + SEC_RAS_FE_REG);
+	writel(SEC_RAS_DISABLE, qm->io_base + SEC_RAS_NFE_REG);
+
+	/* disable SEC hw error interrupts */
+	writel(SEC_CORE_INT_DISABLE, qm->io_base + SEC_CORE_INT_MASK);
+
+	/* disable SEC block master OOO when m-bit error occur */
+	val = val & SEC_AXI_SHUTDOWN_DISABLE;
+
+	writel(val, SEC_ADDR(qm, SEC_CONTROL_REG));
+}
+
+static u32 sec_current_qm_read(struct sec_debug_file *file)
+{
+	struct hisi_qm *qm = file->qm;
+
+	return readl(qm->io_base + QM_DFX_MB_CNT_VF);
+}
+
+static int sec_current_qm_write(struct sec_debug_file *file, u32 val)
+{
+	struct hisi_qm *qm = file->qm;
+	struct sec_dev *sec = container_of(qm, struct sec_dev, qm);
+	u32 vfq_num;
+	u32 tmp;
+
+	if (val > sec->num_vfs)
+		return -EINVAL;
+
+	/* According PF or VF Dev ID to calculation curr_qm_qp_num and store */
+	if (!val) {
+		qm->debug.curr_qm_qp_num = qm->qp_num;
+	} else {
+		vfq_num = (qm->ctrl_qp_num - qm->qp_num) / sec->num_vfs;
+
+		if (val == sec->num_vfs)
+			qm->debug.curr_qm_qp_num =
+				qm->ctrl_qp_num - qm->qp_num -
+				(sec->num_vfs - 1) * vfq_num;
+		else
+			qm->debug.curr_qm_qp_num = vfq_num;
+	}
+
+	writel(val, qm->io_base + QM_DFX_MB_CNT_VF);
+	writel(val, qm->io_base + QM_DFX_DB_CNT_VF);
+
+	tmp = val |
+	      (readl(qm->io_base + QM_DFX_SQE_CNT_VF_SQN) & CURRENT_Q_MASK);
+	writel(tmp, qm->io_base + QM_DFX_SQE_CNT_VF_SQN);
+
+	tmp = val |
+	      (readl(qm->io_base + QM_DFX_CQE_CNT_VF_CQN) & CURRENT_Q_MASK);
+	writel(tmp, qm->io_base + QM_DFX_CQE_CNT_VF_CQN);
+
+	return 0;
+}
+
+static u32 sec_clear_enable_read(struct sec_debug_file *file)
+{
+	struct hisi_qm *qm = file->qm;
+
+	return readl(qm->io_base + SEC_CTRL_CNT_CLR_CE) &
+			SEC_CTRL_CNT_CLR_CE_BIT;
+}
+
+static int sec_clear_enable_write(struct sec_debug_file *file, u32 val)
+{
+	struct hisi_qm *qm = file->qm;
+	u32 tmp;
+
+	if (val != 1 && val)
+		return -EINVAL;
+
+	tmp = (readl(qm->io_base + SEC_CTRL_CNT_CLR_CE) &
+	       ~SEC_CTRL_CNT_CLR_CE_BIT) | val;
+	writel(tmp, qm->io_base + SEC_CTRL_CNT_CLR_CE);
+
+	return 0;
+}
+
+static ssize_t sec_debug_read(struct file *filp, char __user *buf,
+			       size_t count, loff_t *pos)
+{
+	struct sec_debug_file *file = filp->private_data;
+	char tbuf[SEC_DBGFS_VAL_MAX_LEN];
+	u32 val;
+	int ret;
+
+	spin_lock_irq(&file->lock);
+
+	switch (file->index) {
+	case SEC_CURRENT_QM:
+		val = sec_current_qm_read(file);
+		break;
+	case SEC_CLEAR_ENABLE:
+		val = sec_clear_enable_read(file);
+		break;
+	default:
+		spin_unlock_irq(&file->lock);
+		return -EINVAL;
+	}
+
+	spin_unlock_irq(&file->lock);
+	ret = snprintf(tbuf, SEC_DBGFS_VAL_MAX_LEN, "%u\n", val);
+
+	return simple_read_from_buffer(buf, count, pos, tbuf, ret);
+}
+
+static ssize_t sec_debug_write(struct file *filp, const char __user *buf,
+			       size_t count, loff_t *pos)
+{
+	struct sec_debug_file *file = filp->private_data;
+	char tbuf[SEC_DBGFS_VAL_MAX_LEN];
+	unsigned long val;
+	int len, ret;
+
+	if (*pos != 0)
+		return 0;
+
+	if (count >= SEC_DBGFS_VAL_MAX_LEN)
+		return -ENOSPC;
+
+	len = simple_write_to_buffer(tbuf, SEC_DBGFS_VAL_MAX_LEN - 1,
+				     pos, buf, count);
+	if (len < 0)
+		return len;
+
+	tbuf[len] = '\0';
+	if (kstrtoul(tbuf, 0, &val))
+		return -EFAULT;
+
+	spin_lock_irq(&file->lock);
+
+	switch (file->index) {
+	case SEC_CURRENT_QM:
+		ret = sec_current_qm_write(file, val);
+		if (ret)
+			goto err_input;
+		break;
+	case SEC_CLEAR_ENABLE:
+		ret = sec_clear_enable_write(file, val);
+		if (ret)
+			goto err_input;
+		break;
+	default:
+		ret = -EINVAL;
+		goto err_input;
+	}
+
+	spin_unlock_irq(&file->lock);
+
+	return count;
+
+ err_input:
+	spin_unlock_irq(&file->lock);
+	return ret;
+}
+
+static const struct file_operations sec_dbg_fops = {
+	.owner = THIS_MODULE,
+	.open = simple_open,
+	.read = sec_debug_read,
+	.write = sec_debug_write,
+};
+
+static int sec_debugfs_atomic64_get(void *data, u64 *val)
+{
+	*val = atomic64_read((atomic64_t *)data);
+	return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(sec_atomic64_ops, sec_debugfs_atomic64_get,
+			 NULL, "%lld\n");
+
+static int sec_core_debug_init(struct sec_dev *sec)
+{
+	struct hisi_qm *qm = &sec->qm;
+	struct device *dev = &qm->pdev->dev;
+	struct sec_dfx *dfx = &sec->debug.dfx;
+	struct debugfs_regset32 *regset;
+	struct dentry *tmp_d;
+
+	tmp_d = debugfs_create_dir("sec_dfx", sec->qm.debug.debug_root);
+
+	regset = devm_kzalloc(dev, sizeof(*regset), GFP_KERNEL);
+	if (!regset)
+		return -ENOENT;
+
+	regset->regs = sec_dfx_regs;
+	regset->nregs = ARRAY_SIZE(sec_dfx_regs);
+	regset->base = qm->io_base;
+
+	debugfs_create_regset32("regs", 0444, tmp_d, regset);
+
+	debugfs_create_file("send_cnt", 0444, tmp_d,
+			    &dfx->send_cnt, &sec_atomic64_ops);
+
+	debugfs_create_file("recv_cnt", 0444, tmp_d,
+			    &dfx->recv_cnt, &sec_atomic64_ops);
+
+	return 0;
+}
+
+static int sec_debug_init(struct sec_dev *sec)
+{
+	int i;
+
+	for (i = SEC_CURRENT_QM; i < SEC_DEBUG_FILE_NUM; i++) {
+		spin_lock_init(&sec->debug.files[i].lock);
+		sec->debug.files[i].index = i;
+		sec->debug.files[i].qm = &sec->qm;
+
+		debugfs_create_file(sec_dbg_file_name[i], 0600,
+				    sec->qm.debug.debug_root,
+				    sec->debug.files + i,
+				    &sec_dbg_fops);
+	}
+
+	return sec_core_debug_init(sec);
+}
+
+static int sec_debugfs_init(struct sec_dev *sec)
+{
+	struct hisi_qm *qm = &sec->qm;
+	struct device *dev = &qm->pdev->dev;
+	int ret;
+
+	qm->debug.debug_root = debugfs_create_dir(dev_name(dev),
+						  sec_debugfs_root);
+	ret = hisi_qm_debug_init(qm);
+	if (ret)
+		goto failed_to_create;
+
+	if (qm->pdev->device == SEC_PF_PCI_DEVICE_ID) {
+		ret = sec_debug_init(sec);
+		if (ret)
+			goto failed_to_create;
+	}
+
+	return 0;
+
+failed_to_create:
+	debugfs_remove_recursive(sec_debugfs_root);
+
+	return ret;
+}
+
+static void sec_debugfs_exit(struct sec_dev *sec)
+{
+	debugfs_remove_recursive(sec->qm.debug.debug_root);
+}
+
+static const struct hisi_qm_err_ini sec_err_ini = {
+	.hw_err_enable	= sec_hw_error_enable,
+	.hw_err_disable	= sec_hw_error_disable,
+	.err_info	= {
+		.ce		= QM_BASE_CE,
+		.nfe		= QM_BASE_NFE | QM_ACC_DO_TASK_TIMEOUT |
+				  QM_ACC_WB_NOT_READY_TIMEOUT,
+		.fe		= 0,
+		.msi		= QM_DB_RANDOM_INVALID,
+	}
+};
+
+static int sec_pf_probe_init(struct sec_dev *sec)
+{
+	struct hisi_qm *qm = &sec->qm;
+	int ret;
+
+	switch (qm->ver) {
+	case QM_HW_V1:
+		qm->ctrl_qp_num = SEC_QUEUE_NUM_V1;
+		break;
+
+	case QM_HW_V2:
+		qm->ctrl_qp_num = SEC_QUEUE_NUM_V2;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	qm->err_ini = &sec_err_ini;
+
+	ret = sec_set_user_domain_and_cache(sec);
+	if (ret)
+		return ret;
+
+	hisi_qm_dev_err_init(qm);
+	sec_debug_regs_clear(qm);
+
+	return 0;
+}
+
+static int sec_qm_init(struct hisi_qm *qm, struct pci_dev *pdev)
+{
+	enum qm_hw_ver rev_id;
+
+	rev_id = hisi_qm_get_hw_version(pdev);
+	if (rev_id == QM_HW_UNKNOWN)
+		return -ENODEV;
+
+	qm->pdev = pdev;
+	qm->ver = rev_id;
+
+	qm->sqe_size = SEC_SQE_SIZE;
+	qm->dev_name = sec_name;
+	qm->fun_type = (pdev->device == SEC_PF_PCI_DEVICE_ID) ?
+			QM_HW_PF : QM_HW_VF;
+	qm->use_dma_api = true;
+
+	return hisi_qm_init(qm);
+}
+
+static void sec_qm_uninit(struct hisi_qm *qm)
+{
+	hisi_qm_uninit(qm);
+}
+
+static int sec_probe_init(struct hisi_qm *qm, struct sec_dev *sec)
+{
+	int ret;
+
+	/*
+	 * WQ_HIGHPRI: SEC request must be low delayed,
+	 * so need a high priority workqueue.
+	 * WQ_UNBOUND: SEC task is likely with long
+	 * running CPU intensive workloads.
+	 */
+	qm->wq = alloc_workqueue("%s", WQ_HIGHPRI |
+		WQ_MEM_RECLAIM | WQ_UNBOUND, num_online_cpus(),
+		pci_name(qm->pdev));
+	if (!qm->wq) {
+		pci_err(qm->pdev, "fail to alloc workqueue\n");
+		return -ENOMEM;
+	}
+
+	if (qm->fun_type == QM_HW_PF) {
+		qm->qp_base = SEC_PF_DEF_Q_BASE;
+		qm->qp_num = pf_q_num;
+		qm->debug.curr_qm_qp_num = pf_q_num;
+
+		ret = sec_pf_probe_init(sec);
+		if (ret)
+			goto err_probe_uninit;
+	} else if (qm->fun_type == QM_HW_VF) {
+		/*
+		 * have no way to get qm configure in VM in v1 hardware,
+		 * so currently force PF to uses SEC_PF_DEF_Q_NUM, and force
+		 * to trigger only one VF in v1 hardware.
+		 * v2 hardware has no such problem.
+		 */
+		if (qm->ver == QM_HW_V1) {
+			qm->qp_base = SEC_PF_DEF_Q_NUM;
+			qm->qp_num = SEC_QUEUE_NUM_V1 - SEC_PF_DEF_Q_NUM;
+		} else if (qm->ver == QM_HW_V2) {
+			/* v2 starts to support get vft by mailbox */
+			ret = hisi_qm_get_vft(qm, &qm->qp_base, &qm->qp_num);
+			if (ret)
+				goto err_probe_uninit;
+		}
+	} else {
+		ret = -ENODEV;
+		goto err_probe_uninit;
+	}
+
+	return 0;
+err_probe_uninit:
+	destroy_workqueue(qm->wq);
+	return ret;
+}
+
+static void sec_probe_uninit(struct hisi_qm *qm)
+{
+	hisi_qm_dev_err_uninit(qm);
+
+	destroy_workqueue(qm->wq);
+}
+
+static int sec_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	struct sec_dev *sec;
+	struct hisi_qm *qm;
+	int ret;
+
+	sec = devm_kzalloc(&pdev->dev, sizeof(*sec), GFP_KERNEL);
+	if (!sec)
+		return -ENOMEM;
+
+	pci_set_drvdata(pdev, sec);
+
+	sec->ctx_q_num = ctx_q_num;
+
+	qm = &sec->qm;
+
+	ret = sec_qm_init(qm, pdev);
+	if (ret) {
+		pci_err(pdev, "Failed to pre init qm!\n");
+		return ret;
+	}
+
+	ret = sec_probe_init(qm, sec);
+	if (ret) {
+		pci_err(pdev, "Failed to probe!\n");
+		goto err_qm_uninit;
+	}
+
+	ret = hisi_qm_start(qm);
+	if (ret) {
+		pci_err(pdev, "Failed to start sec qm!\n");
+		goto err_probe_uninit;
+	}
+
+	ret = sec_debugfs_init(sec);
+	if (ret)
+		pci_warn(pdev, "Failed to init debugfs!\n");
+
+	sec_add_to_list(sec);
+
+	ret = sec_register_to_crypto();
+	if (ret < 0) {
+		pr_err("Failed to register driver to crypto.\n");
+		goto err_remove_from_list;
+	}
+
+	return 0;
+
+err_remove_from_list:
+	sec_remove_from_list(sec);
+	sec_debugfs_exit(sec);
+	hisi_qm_stop(qm);
+
+err_probe_uninit:
+	sec_probe_uninit(qm);
+
+err_qm_uninit:
+	sec_qm_uninit(qm);
+
+	return ret;
+}
+
+/* now we only support equal assignment */
+static int sec_vf_q_assign(struct sec_dev *sec, u32 num_vfs)
+{
+	struct hisi_qm *qm = &sec->qm;
+	u32 qp_num = qm->qp_num;
+	u32 q_base = qp_num;
+	u32 q_num, remain_q_num;
+	int i, j, ret;
+
+	if (!num_vfs)
+		return -EINVAL;
+
+	remain_q_num = qm->ctrl_qp_num - qp_num;
+	q_num = remain_q_num / num_vfs;
+
+	for (i = 1; i <= num_vfs; i++) {
+		if (i == num_vfs)
+			q_num += remain_q_num % num_vfs;
+		ret = hisi_qm_set_vft(qm, i, q_base, q_num);
+		if (ret) {
+			for (j = i; j > 0; j--)
+				hisi_qm_set_vft(qm, j, 0, 0);
+			return ret;
+		}
+		q_base += q_num;
+	}
+
+	return 0;
+}
+
+static int sec_clear_vft_config(struct sec_dev *sec)
+{
+	struct hisi_qm *qm = &sec->qm;
+	u32 num_vfs = sec->num_vfs;
+	int ret;
+	u32 i;
+
+	for (i = 1; i <= num_vfs; i++) {
+		ret = hisi_qm_set_vft(qm, i, 0, 0);
+		if (ret)
+			return ret;
+	}
+
+	sec->num_vfs = 0;
+
+	return 0;
+}
+
+static int sec_sriov_enable(struct pci_dev *pdev, int max_vfs)
+{
+	struct sec_dev *sec = pci_get_drvdata(pdev);
+	int pre_existing_vfs, ret;
+	u32 num_vfs;
+
+	pre_existing_vfs = pci_num_vf(pdev);
+
+	if (pre_existing_vfs) {
+		pci_err(pdev, "Can't enable VF. Please disable at first!\n");
+		return 0;
+	}
+
+	num_vfs = min_t(u32, max_vfs, SEC_VF_NUM);
+
+	ret = sec_vf_q_assign(sec, num_vfs);
+	if (ret) {
+		pci_err(pdev, "Can't assign queues for VF!\n");
+		return ret;
+	}
+
+	sec->num_vfs = num_vfs;
+
+	ret = pci_enable_sriov(pdev, num_vfs);
+	if (ret) {
+		pci_err(pdev, "Can't enable VF!\n");
+		sec_clear_vft_config(sec);
+		return ret;
+	}
+
+	return num_vfs;
+}
+
+static int sec_sriov_disable(struct pci_dev *pdev)
+{
+	struct sec_dev *sec = pci_get_drvdata(pdev);
+
+	if (pci_vfs_assigned(pdev)) {
+		pci_err(pdev, "Can't disable VFs while VFs are assigned!\n");
+		return -EPERM;
+	}
+
+	/* remove in sec_pci_driver will be called to free VF resources */
+	pci_disable_sriov(pdev);
+
+	return sec_clear_vft_config(sec);
+}
+
+static int sec_sriov_configure(struct pci_dev *pdev, int num_vfs)
+{
+	if (num_vfs)
+		return sec_sriov_enable(pdev, num_vfs);
+	else
+		return sec_sriov_disable(pdev);
+}
+
+static void sec_remove(struct pci_dev *pdev)
+{
+	struct sec_dev *sec = pci_get_drvdata(pdev);
+	struct hisi_qm *qm = &sec->qm;
+
+	sec_unregister_from_crypto();
+
+	sec_remove_from_list(sec);
+
+	if (qm->fun_type == QM_HW_PF && sec->num_vfs)
+		(void)sec_sriov_disable(pdev);
+
+	sec_debugfs_exit(sec);
+
+	(void)hisi_qm_stop(qm);
+
+	if (qm->fun_type == QM_HW_PF)
+		sec_debug_regs_clear(qm);
+
+	sec_probe_uninit(qm);
+
+	sec_qm_uninit(qm);
+}
+
+static void sec_log_hw_error(struct sec_dev *sec, u32 err_sts)
+{
+	const struct sec_hw_error *errs = sec_hw_errors;
+	struct device *dev = &sec->qm.pdev->dev;
+	u32 err_val;
+
+	while (errs->msg) {
+		if (errs->int_msk & err_sts) {
+			dev_err(dev, "%s [error status=0x%x] found\n",
+				errs->msg, errs->int_msk);
+
+			if (SEC_CORE_INT_STATUS_M_ECC & err_sts) {
+				err_val = readl(sec->qm.io_base +
+						SEC_CORE_SRAM_ECC_ERR_INFO);
+				dev_err(dev, "multi ecc sram num=0x%x\n",
+					SEC_ECC_NUM(err_val));
+				dev_err(dev, "multi ecc sram addr=0x%x\n",
+					SEC_ECC_ADDR(err_val));
+			}
+		}
+		errs++;
+	}
+}
+
+static pci_ers_result_t sec_hw_error_handle(struct sec_dev *sec)
+{
+	u32 err_sts;
+
+	/* read err sts */
+	err_sts = readl(sec->qm.io_base + SEC_CORE_INT_STATUS);
+	if (err_sts) {
+		sec_log_hw_error(sec, err_sts);
+
+		/* clear error interrupts */
+		writel(err_sts, sec->qm.io_base + SEC_CORE_INT_SOURCE);
+
+		return PCI_ERS_RESULT_NEED_RESET;
+	}
+
+	return PCI_ERS_RESULT_RECOVERED;
+}
+
+static pci_ers_result_t sec_process_hw_error(struct pci_dev *pdev)
+{
+	struct sec_dev *sec = pci_get_drvdata(pdev);
+	pci_ers_result_t qm_ret, sec_ret;
+
+	if (!sec) {
+		pci_err(pdev, "Can't recover error during device init\n");
+		return PCI_ERS_RESULT_NONE;
+	}
+
+	/* log qm error */
+	qm_ret = hisi_qm_hw_error_handle(&sec->qm);
+
+	/* log sec error */
+	sec_ret = sec_hw_error_handle(sec);
+
+	return (qm_ret == PCI_ERS_RESULT_NEED_RESET ||
+		sec_ret == PCI_ERS_RESULT_NEED_RESET) ?
+		PCI_ERS_RESULT_NEED_RESET : PCI_ERS_RESULT_RECOVERED;
+}
+
+static pci_ers_result_t sec_error_detected(struct pci_dev *pdev,
+					   pci_channel_state_t state)
+{
+	if (pdev->is_virtfn)
+		return PCI_ERS_RESULT_NONE;
+
+	pci_info(pdev, "PCI error detected, state(=%d)!!\n", state);
+	if (state == pci_channel_io_perm_failure)
+		return PCI_ERS_RESULT_DISCONNECT;
+
+	return sec_process_hw_error(pdev);
+}
+
+static const struct pci_error_handlers sec_err_handler = {
+	.error_detected = sec_error_detected,
+};
+
+static struct pci_driver sec_pci_driver = {
+	.name = "hisi_sec2",
+	.id_table = sec_dev_ids,
+	.probe = sec_probe,
+	.remove = sec_remove,
+	.err_handler = &sec_err_handler,
+	.sriov_configure = sec_sriov_configure,
+};
+
+static void sec_register_debugfs(void)
+{
+	if (!debugfs_initialized())
+		return;
+
+	sec_debugfs_root = debugfs_create_dir("hisi_sec2", NULL);
+}
+
+static void sec_unregister_debugfs(void)
+{
+	debugfs_remove_recursive(sec_debugfs_root);
+}
+
+static int __init sec_init(void)
+{
+	int ret;
+
+	sec_register_debugfs();
+
+	ret = pci_register_driver(&sec_pci_driver);
+	if (ret < 0) {
+		sec_unregister_debugfs();
+		pr_err("Failed to register pci driver.\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static void __exit sec_exit(void)
+{
+	pci_unregister_driver(&sec_pci_driver);
+	sec_unregister_debugfs();
+}
+
+module_init(sec_init);
+module_exit(sec_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Zaibo Xu <xuzaibo@huawei.com>");
+MODULE_AUTHOR("Longfang Liu <liulongfang@huawei.com>");
+MODULE_AUTHOR("Wei Zhang <zhangwei375@huawei.com>");
+MODULE_DESCRIPTION("Driver for HiSilicon SEC accelerator");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/hisilicon/sgl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/hisilicon/sgl.c
@@ -2,37 +2,13 @@
 /* Copyright (c) 2019 HiSilicon Limited. */
 #include <linux/dma-mapping.h>
 #include <linux/module.h>
-#include "./sgl.h"
+#include <linux/slab.h>
+#include "qm.h"
 
 #define HISI_ACC_SGL_SGE_NR_MIN		1
-#define HISI_ACC_SGL_SGE_NR_MAX		255
-#define HISI_ACC_SGL_SGE_NR_DEF		10
 #define HISI_ACC_SGL_NR_MAX		256
 #define HISI_ACC_SGL_ALIGN_SIZE		64
-
-static int acc_sgl_sge_set(const char *val, const struct kernel_param *kp)
-{
-	int ret;
-	u32 n;
-
-	if (!val)
-		return -EINVAL;
-
-	ret = kstrtou32(val, 10, &n);
-	if (ret != 0 || n > HISI_ACC_SGL_SGE_NR_MAX || n == 0)
-		return -EINVAL;
-
-	return param_set_int(val, kp);
-}
-
-static const struct kernel_param_ops acc_sgl_sge_ops = {
-	.set = acc_sgl_sge_set,
-	.get = param_get_int,
-};
-
-static u32 acc_sgl_sge_nr = HISI_ACC_SGL_SGE_NR_DEF;
-module_param_cb(acc_sgl_sge_nr, &acc_sgl_sge_ops, &acc_sgl_sge_nr, 0444);
-MODULE_PARM_DESC(acc_sgl_sge_nr, "Number of sge in sgl(1-255)");
+#define HISI_ACC_MEM_BLOCK_NR		5
 
 struct acc_hw_sge {
 	dma_addr_t buf;
@@ -55,37 +31,91 @@
 	struct acc_hw_sge sge_entries[];
 } __aligned(1);
 
+struct hisi_acc_sgl_pool {
+	struct mem_block {
+		struct hisi_acc_hw_sgl *sgl;
+		dma_addr_t sgl_dma;
+		size_t size;
+	} mem_block[HISI_ACC_MEM_BLOCK_NR];
+	u32 sgl_num_per_block;
+	u32 block_num;
+	u32 count;
+	u32 sge_nr;
+	size_t sgl_size;
+};
+
 /**
  * hisi_acc_create_sgl_pool() - Create a hw sgl pool.
  * @dev: The device which hw sgl pool belongs to.
- * @pool: Pointer of pool.
  * @count: Count of hisi_acc_hw_sgl in pool.
+ * @sge_nr: The count of sge in hw_sgl
  *
  * This function creates a hw sgl pool, after this user can get hw sgl memory
  * from it.
  */
-int hisi_acc_create_sgl_pool(struct device *dev,
-			     struct hisi_acc_sgl_pool *pool, u32 count)
+struct hisi_acc_sgl_pool *hisi_acc_create_sgl_pool(struct device *dev,
+						   u32 count, u32 sge_nr)
 {
-	u32 sgl_size;
-	u32 size;
+	u32 sgl_size, block_size, sgl_num_per_block, block_num, remain_sgl = 0;
+	struct hisi_acc_sgl_pool *pool;
+	struct mem_block *block;
+	u32 i, j;
 
-	if (!dev || !pool || !count)
-		return -EINVAL;
+	if (!dev || !count || !sge_nr || sge_nr > HISI_ACC_SGL_SGE_NR_MAX)
+		return ERR_PTR(-EINVAL);
 
-	sgl_size = sizeof(struct acc_hw_sge) * acc_sgl_sge_nr +
+	sgl_size = sizeof(struct acc_hw_sge) * sge_nr +
 		   sizeof(struct hisi_acc_hw_sgl);
-	size = sgl_size * count;
+	block_size = PAGE_SIZE * (1 << (MAX_ORDER - 1));
+	sgl_num_per_block = block_size / sgl_size;
+	block_num = count / sgl_num_per_block;
+	remain_sgl = count % sgl_num_per_block;
+
+	if ((!remain_sgl && block_num > HISI_ACC_MEM_BLOCK_NR) ||
+	    (remain_sgl > 0 && block_num > HISI_ACC_MEM_BLOCK_NR - 1))
+		return ERR_PTR(-EINVAL);
+
+	pool = kzalloc(sizeof(*pool), GFP_KERNEL);
+	if (!pool)
+		return ERR_PTR(-ENOMEM);
+	block = pool->mem_block;
+
+	for (i = 0; i < block_num; i++) {
+		block[i].sgl = dma_alloc_coherent(dev, block_size,
+						  &block[i].sgl_dma,
+						  GFP_KERNEL);
+		if (!block[i].sgl)
+			goto err_free_mem;
+
+		block[i].size = block_size;
+	}
 
-	pool->sgl = dma_alloc_coherent(dev, size, &pool->sgl_dma, GFP_KERNEL);
-	if (!pool->sgl)
-		return -ENOMEM;
+	if (remain_sgl > 0) {
+		block[i].sgl = dma_alloc_coherent(dev, remain_sgl * sgl_size,
+						  &block[i].sgl_dma,
+						  GFP_KERNEL);
+		if (!block[i].sgl)
+			goto err_free_mem;
 
-	pool->size = size;
+		block[i].size = remain_sgl * sgl_size;
+	}
+
+	pool->sgl_num_per_block = sgl_num_per_block;
+	pool->block_num = remain_sgl ? block_num + 1 : block_num;
 	pool->count = count;
 	pool->sgl_size = sgl_size;
+	pool->sge_nr = sge_nr;
+
+	return pool;
 
-	return 0;
+err_free_mem:
+	for (j = 0; j < i; j++) {
+		dma_free_coherent(dev, block_size, block[j].sgl,
+				  block[j].sgl_dma);
+		memset(block + j, 0, sizeof(*block));
+	}
+	kfree(pool);
+	return ERR_PTR(-ENOMEM);
 }
 EXPORT_SYMBOL_GPL(hisi_acc_create_sgl_pool);
 
@@ -98,38 +128,57 @@
  */
 void hisi_acc_free_sgl_pool(struct device *dev, struct hisi_acc_sgl_pool *pool)
 {
-	dma_free_coherent(dev, pool->size, pool->sgl, pool->sgl_dma);
-	memset(pool, 0, sizeof(struct hisi_acc_sgl_pool));
+	struct mem_block *block;
+	int i;
+
+	if (!dev || !pool)
+		return;
+
+	block = pool->mem_block;
+
+	for (i = 0; i < pool->block_num; i++)
+		dma_free_coherent(dev, block[i].size, block[i].sgl,
+				  block[i].sgl_dma);
+
+	kfree(pool);
 }
 EXPORT_SYMBOL_GPL(hisi_acc_free_sgl_pool);
 
-struct hisi_acc_hw_sgl *acc_get_sgl(struct hisi_acc_sgl_pool *pool, u32 index,
-				    dma_addr_t *hw_sgl_dma)
+static struct hisi_acc_hw_sgl *acc_get_sgl(struct hisi_acc_sgl_pool *pool,
+					   u32 index, dma_addr_t *hw_sgl_dma)
 {
-	if (!pool || !hw_sgl_dma || index >= pool->count || !pool->sgl)
+	struct mem_block *block;
+	u32 block_index, offset;
+
+	if (!pool || !hw_sgl_dma || index >= pool->count)
 		return ERR_PTR(-EINVAL);
 
-	*hw_sgl_dma = pool->sgl_dma + pool->sgl_size * index;
-	return (void *)pool->sgl + pool->sgl_size * index;
-}
+	block = pool->mem_block;
+	block_index = index / pool->sgl_num_per_block;
+	offset = index % pool->sgl_num_per_block;
 
-void acc_put_sgl(struct hisi_acc_sgl_pool *pool, u32 index) {}
+	*hw_sgl_dma = block[block_index].sgl_dma + pool->sgl_size * offset;
+	return (void *)block[block_index].sgl + pool->sgl_size * offset;
+}
 
 static void sg_map_to_hw_sg(struct scatterlist *sgl,
 			    struct acc_hw_sge *hw_sge)
 {
-	hw_sge->buf = sgl->dma_address;
-	hw_sge->len = sgl->dma_length;
+	hw_sge->buf = sg_dma_address(sgl);
+	hw_sge->len = cpu_to_le32(sg_dma_len(sgl));
 }
 
 static void inc_hw_sgl_sge(struct hisi_acc_hw_sgl *hw_sgl)
 {
-	hw_sgl->entry_sum_in_sgl++;
+	u16 var = le16_to_cpu(hw_sgl->entry_sum_in_sgl);
+
+	var++;
+	hw_sgl->entry_sum_in_sgl = cpu_to_le16(var);
 }
 
 static void update_hw_sgl_sum_sge(struct hisi_acc_hw_sgl *hw_sgl, u16 sum)
 {
-	hw_sgl->entry_sum_in_chain = sum;
+	hw_sgl->entry_sum_in_chain = cpu_to_le16(sum);
 }
 
 /**
@@ -153,10 +202,13 @@
 	dma_addr_t curr_sgl_dma = 0;
 	struct acc_hw_sge *curr_hw_sge;
 	struct scatterlist *sg;
-	int sg_n = sg_nents(sgl);
-	int i, ret;
+	int i, ret, sg_n;
+
+	if (!dev || !sgl || !pool || !hw_sgl_dma)
+		return ERR_PTR(-EINVAL);
 
-	if (!dev || !sgl || !pool || !hw_sgl_dma || sg_n > acc_sgl_sge_nr)
+	sg_n = sg_nents(sgl);
+	if (sg_n > pool->sge_nr)
 		return ERR_PTR(-EINVAL);
 
 	ret = dma_map_sg(dev, sgl, sg_n, DMA_BIDIRECTIONAL);
@@ -164,11 +216,12 @@
 		return ERR_PTR(-EINVAL);
 
 	curr_hw_sgl = acc_get_sgl(pool, index, &curr_sgl_dma);
-	if (!curr_hw_sgl) {
-		ret = -ENOMEM;
-		goto err_unmap_sg;
+	if (IS_ERR(curr_hw_sgl)) {
+		dma_unmap_sg(dev, sgl, sg_n, DMA_BIDIRECTIONAL);
+		return ERR_PTR(-ENOMEM);
+
 	}
-	curr_hw_sgl->entry_length_in_sgl = acc_sgl_sge_nr;
+	curr_hw_sgl->entry_length_in_sgl = cpu_to_le16(pool->sge_nr);
 	curr_hw_sge = curr_hw_sgl->sge_entries;
 
 	for_each_sg(sgl, sg, sg_n, i) {
@@ -177,14 +230,10 @@
 		curr_hw_sge++;
 	}
 
-	update_hw_sgl_sum_sge(curr_hw_sgl, acc_sgl_sge_nr);
+	update_hw_sgl_sum_sge(curr_hw_sgl, pool->sge_nr);
 	*hw_sgl_dma = curr_sgl_dma;
 
 	return curr_hw_sgl;
-
-err_unmap_sg:
-	dma_unmap_sg(dev, sgl, sg_n, DMA_BIDIRECTIONAL);
-	return ERR_PTR(ret);
 }
 EXPORT_SYMBOL_GPL(hisi_acc_sg_buf_map_to_hw_sgl);
 
@@ -201,6 +250,9 @@
 void hisi_acc_sg_buf_unmap(struct device *dev, struct scatterlist *sgl,
 			   struct hisi_acc_hw_sgl *hw_sgl)
 {
+	if (!dev || !sgl || !hw_sgl)
+		return;
+
 	dma_unmap_sg(dev, sgl, sg_nents(sgl), DMA_BIDIRECTIONAL);
 
 	hw_sgl->entry_sum_in_chain = 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/hisilicon/zip/zip.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/hisilicon/zip/zip.h
@@ -8,10 +8,13 @@
 
 #include <linux/list.h>
 #include "../qm.h"
-#include "../sgl.h"
 
 /* hisi_zip_sqe dw3 */
 #define HZIP_BD_STATUS_M			GENMASK(7, 0)
+/* hisi_zip_sqe dw7 */
+#define HZIP_IN_SGE_DATA_OFFSET_M		GENMASK(23, 0)
+/* hisi_zip_sqe dw8 */
+#define HZIP_OUT_SGE_DATA_OFFSET_M		GENMASK(23, 0)
 /* hisi_zip_sqe dw9 */
 #define HZIP_REQ_TYPE_M				GENMASK(7, 0)
 #define HZIP_ALG_TYPE_ZLIB			0x02
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/hisilicon/zip/zip_crypto.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/hisilicon/zip/zip_crypto.c
@@ -22,6 +22,7 @@
 #define HZIP_CTX_Q_NUM				2
 #define HZIP_GZIP_HEAD_BUF			256
 #define HZIP_ALG_PRIORITY			300
+#define HZIP_SGL_SGE_NR				10
 
 static const u8 zlib_head[HZIP_ZLIB_HEAD_SIZE] = {0x78, 0x9c};
 static const u8 gzip_head[HZIP_GZIP_HEAD_SIZE] = {0x1f, 0x8b, 0x08, 0x0, 0x0,
@@ -41,14 +42,12 @@
 
 #define TO_HEAD(req_type)						\
 	(((req_type) == HZIP_ALG_TYPE_ZLIB) ? zlib_head :		\
-	 ((req_type) == HZIP_ALG_TYPE_GZIP) ? gzip_head : 0)		\
+	 ((req_type) == HZIP_ALG_TYPE_GZIP) ? gzip_head : NULL)		\
 
 struct hisi_zip_req {
 	struct acomp_req *req;
-	struct scatterlist *src;
-	struct scatterlist *dst;
-	size_t slen;
-	size_t dlen;
+	int sskip;
+	int dskip;
 	struct hisi_acc_hw_sgl *hw_src;
 	struct hisi_acc_hw_sgl *hw_dst;
 	dma_addr_t dma_src;
@@ -67,7 +66,7 @@
 	struct hisi_qp *qp;
 	struct hisi_zip_sqe zip_sqe;
 	struct hisi_zip_req_q req_q;
-	struct hisi_acc_sgl_pool sgl_pool;
+	struct hisi_acc_sgl_pool *sgl_pool;
 	struct hisi_zip *zip_dev;
 	struct hisi_zip_ctx *ctx;
 };
@@ -78,6 +77,30 @@
 	struct hisi_zip_qp_ctx qp_ctx[HZIP_CTX_Q_NUM];
 };
 
+static int sgl_sge_nr_set(const char *val, const struct kernel_param *kp)
+{
+	int ret;
+	u16 n;
+
+	if (!val)
+		return -EINVAL;
+
+	ret = kstrtou16(val, 10, &n);
+	if (ret || n == 0 || n > HISI_ACC_SGL_SGE_NR_MAX)
+		return -EINVAL;
+
+	return param_set_int(val, kp);
+}
+
+static const struct kernel_param_ops sgl_sge_nr_ops = {
+	.set = sgl_sge_nr_set,
+	.get = param_get_int,
+};
+
+static u16 sgl_sge_nr = HZIP_SGL_SGE_NR;
+module_param_cb(sgl_sge_nr, &sgl_sge_nr_ops, &sgl_sge_nr, 0444);
+MODULE_PARM_DESC(sgl_sge_nr, "Number of sge in sgl(1-255)");
+
 static void hisi_zip_config_buf_type(struct hisi_zip_sqe *sqe, u8 buf_type)
 {
 	u32 val;
@@ -94,13 +117,15 @@
 
 static void hisi_zip_fill_sqe(struct hisi_zip_sqe *sqe, u8 req_type,
 			      dma_addr_t s_addr, dma_addr_t d_addr, u32 slen,
-			      u32 dlen)
+			      u32 dlen, int sskip, int dskip)
 {
 	memset(sqe, 0, sizeof(struct hisi_zip_sqe));
 
-	sqe->input_data_length = slen;
+	sqe->input_data_length = slen - sskip;
+	sqe->dw7 = FIELD_PREP(HZIP_IN_SGE_DATA_OFFSET_M, sskip);
+	sqe->dw8 = FIELD_PREP(HZIP_OUT_SGE_DATA_OFFSET_M, dskip);
 	sqe->dw9 = FIELD_PREP(HZIP_REQ_TYPE_M, req_type);
-	sqe->dest_avail_out = dlen;
+	sqe->dest_avail_out = dlen - dskip;
 	sqe->source_addr_l = lower_32_bits(s_addr);
 	sqe->source_addr_h = upper_32_bits(s_addr);
 	sqe->dest_addr_l = lower_32_bits(d_addr);
@@ -265,14 +290,15 @@
 static int hisi_zip_create_sgl_pool(struct hisi_zip_ctx *ctx)
 {
 	struct hisi_zip_qp_ctx *tmp;
-	int i, ret;
+	struct device *dev;
+	int i;
 
 	for (i = 0; i < HZIP_CTX_Q_NUM; i++) {
 		tmp = &ctx->qp_ctx[i];
-		ret = hisi_acc_create_sgl_pool(&tmp->qp->qm->pdev->dev,
-					       &tmp->sgl_pool,
-					       QM_Q_DEPTH << 1);
-		if (ret < 0) {
+		dev = &tmp->qp->qm->pdev->dev;
+		tmp->sgl_pool = hisi_acc_create_sgl_pool(dev, QM_Q_DEPTH << 1,
+							 sgl_sge_nr);
+		if (IS_ERR(tmp->sgl_pool)) {
 			if (i == 1)
 				goto err_free_sgl_pool0;
 			return -ENOMEM;
@@ -283,7 +309,7 @@
 
 err_free_sgl_pool0:
 	hisi_acc_free_sgl_pool(&ctx->qp_ctx[QPC_COMP].qp->qm->pdev->dev,
-			       &ctx->qp_ctx[QPC_COMP].sgl_pool);
+			       ctx->qp_ctx[QPC_COMP].sgl_pool);
 	return -ENOMEM;
 }
 
@@ -293,7 +319,7 @@
 
 	for (i = 0; i < HZIP_CTX_Q_NUM; i++)
 		hisi_acc_free_sgl_pool(&ctx->qp_ctx[i].qp->qm->pdev->dev,
-				       &ctx->qp_ctx[i].sgl_pool);
+				       ctx->qp_ctx[i].sgl_pool);
 }
 
 static void hisi_zip_remove_req(struct hisi_zip_qp_ctx *qp_ctx,
@@ -301,11 +327,6 @@
 {
 	struct hisi_zip_req_q *req_q = &qp_ctx->req_q;
 
-	if (qp_ctx->qp->alg_type == HZIP_ALG_TYPE_COMP)
-		kfree(req->dst);
-	else
-		kfree(req->src);
-
 	write_lock(&req_q->req_lock);
 	clear_bit(req->req_id, req_q->req_bitmap);
 	memset(req, 0, sizeof(struct hisi_zip_req));
@@ -333,8 +354,8 @@
 	}
 	dlen = sqe->produced;
 
-	hisi_acc_sg_buf_unmap(dev, req->src, req->hw_src);
-	hisi_acc_sg_buf_unmap(dev, req->dst, req->hw_dst);
+	hisi_acc_sg_buf_unmap(dev, acomp_req->src, req->hw_src);
+	hisi_acc_sg_buf_unmap(dev, acomp_req->dst, req->hw_dst);
 
 	head_size = (qp->alg_type == 0) ? TO_HEAD_SIZE(qp->req_type) : 0;
 	acomp_req->dlen = dlen + head_size;
@@ -428,20 +449,6 @@
 	}
 }
 
-static int get_sg_skip_bytes(struct scatterlist *sgl, size_t bytes,
-			     size_t remains, struct scatterlist **out)
-{
-#define SPLIT_NUM 2
-	size_t split_sizes[SPLIT_NUM];
-	int out_mapped_nents[SPLIT_NUM];
-
-	split_sizes[0] = bytes;
-	split_sizes[1] = remains;
-
-	return sg_split(sgl, 0, 0, SPLIT_NUM, split_sizes, out,
-			out_mapped_nents, GFP_KERNEL);
-}
-
 static struct hisi_zip_req *hisi_zip_create_req(struct acomp_req *req,
 						struct hisi_zip_qp_ctx *qp_ctx,
 						size_t head_size, bool is_comp)
@@ -449,31 +456,7 @@
 	struct hisi_zip_req_q *req_q = &qp_ctx->req_q;
 	struct hisi_zip_req *q = req_q->q;
 	struct hisi_zip_req *req_cache;
-	struct scatterlist *out[2];
-	struct scatterlist *sgl;
-	size_t len;
-	int ret, req_id;
-
-	/*
-	 * remove/add zlib/gzip head, as hardware operations do not include
-	 * comp head. so split req->src to get sgl without heads in acomp, or
-	 * add comp head to req->dst ahead of that hardware output compressed
-	 * data in sgl splited from req->dst without comp head.
-	 */
-	if (is_comp) {
-		sgl = req->dst;
-		len = req->dlen - head_size;
-	} else {
-		sgl = req->src;
-		len = req->slen - head_size;
-	}
-
-	ret = get_sg_skip_bytes(sgl, head_size, len, out);
-	if (ret)
-		return ERR_PTR(ret);
-
-	/* sgl for comp head is useless, so free it now */
-	kfree(out[0]);
+	int req_id;
 
 	write_lock(&req_q->req_lock);
 
@@ -481,7 +464,6 @@
 	if (req_id >= req_q->size) {
 		write_unlock(&req_q->req_lock);
 		dev_dbg(&qp_ctx->qp->qm->pdev->dev, "req cache is full!\n");
-		kfree(out[1]);
 		return ERR_PTR(-EBUSY);
 	}
 	set_bit(req_id, req_q->req_bitmap);
@@ -489,16 +471,13 @@
 	req_cache = q + req_id;
 	req_cache->req_id = req_id;
 	req_cache->req = req;
+
 	if (is_comp) {
-		req_cache->src = req->src;
-		req_cache->dst = out[1];
-		req_cache->slen = req->slen;
-		req_cache->dlen = req->dlen - head_size;
+		req_cache->sskip = 0;
+		req_cache->dskip = head_size;
 	} else {
-		req_cache->src = out[1];
-		req_cache->dst = req->dst;
-		req_cache->slen = req->slen - head_size;
-		req_cache->dlen = req->dlen;
+		req_cache->sskip = head_size;
+		req_cache->dskip = 0;
 	}
 
 	write_unlock(&req_q->req_lock);
@@ -510,23 +489,24 @@
 			    struct hisi_zip_qp_ctx *qp_ctx)
 {
 	struct hisi_zip_sqe *zip_sqe = &qp_ctx->zip_sqe;
+	struct acomp_req *a_req = req->req;
 	struct hisi_qp *qp = qp_ctx->qp;
 	struct device *dev = &qp->qm->pdev->dev;
-	struct hisi_acc_sgl_pool *pool = &qp_ctx->sgl_pool;
+	struct hisi_acc_sgl_pool *pool = qp_ctx->sgl_pool;
 	dma_addr_t input;
 	dma_addr_t output;
 	int ret;
 
-	if (!req->src || !req->slen || !req->dst || !req->dlen)
+	if (!a_req->src || !a_req->slen || !a_req->dst || !a_req->dlen)
 		return -EINVAL;
 
-	req->hw_src = hisi_acc_sg_buf_map_to_hw_sgl(dev, req->src, pool,
+	req->hw_src = hisi_acc_sg_buf_map_to_hw_sgl(dev, a_req->src, pool,
 						    req->req_id << 1, &input);
 	if (IS_ERR(req->hw_src))
 		return PTR_ERR(req->hw_src);
 	req->dma_src = input;
 
-	req->hw_dst = hisi_acc_sg_buf_map_to_hw_sgl(dev, req->dst, pool,
+	req->hw_dst = hisi_acc_sg_buf_map_to_hw_sgl(dev, a_req->dst, pool,
 						    (req->req_id << 1) + 1,
 						    &output);
 	if (IS_ERR(req->hw_dst)) {
@@ -535,8 +515,8 @@
 	}
 	req->dma_dst = output;
 
-	hisi_zip_fill_sqe(zip_sqe, qp->req_type, input, output, req->slen,
-			  req->dlen);
+	hisi_zip_fill_sqe(zip_sqe, qp->req_type, input, output, a_req->slen,
+			  a_req->dlen, req->sskip, req->dskip);
 	hisi_zip_config_buf_type(zip_sqe, HZIP_SGL);
 	hisi_zip_config_tag(zip_sqe, req->req_id);
 
@@ -548,9 +528,9 @@
 	return -EINPROGRESS;
 
 err_unmap_output:
-	hisi_acc_sg_buf_unmap(dev, req->dst, req->hw_dst);
+	hisi_acc_sg_buf_unmap(dev, a_req->dst, req->hw_dst);
 err_unmap_input:
-	hisi_acc_sg_buf_unmap(dev, req->src, req->hw_src);
+	hisi_acc_sg_buf_unmap(dev, a_req->src, req->hw_src);
 	return ret;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/hisilicon/zip/zip_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/hisilicon/zip/zip_main.c
@@ -60,13 +60,13 @@
 #define HZIP_CORE_DEBUG_DECOMP_5	0x309000
 
 #define HZIP_CORE_INT_SOURCE		0x3010A0
-#define HZIP_CORE_INT_MASK		0x3010A4
+#define HZIP_CORE_INT_MASK_REG		0x3010A4
 #define HZIP_CORE_INT_STATUS		0x3010AC
 #define HZIP_CORE_INT_STATUS_M_ECC	BIT(1)
 #define HZIP_CORE_SRAM_ECC_ERR_INFO	0x301148
 #define SRAM_ECC_ERR_NUM_SHIFT		16
 #define SRAM_ECC_ERR_ADDR_SHIFT		24
-#define HZIP_CORE_INT_DISABLE		0x000007FF
+#define HZIP_CORE_INT_MASK_ALL		GENMASK(10, 0)
 #define HZIP_COMP_CORE_NUM		2
 #define HZIP_DECOMP_CORE_NUM		6
 #define HZIP_CORE_NUM			(HZIP_COMP_CORE_NUM + \
@@ -79,47 +79,80 @@
 #define HZIP_SOFT_CTRL_CNT_CLR_CE	0x301000
 #define SOFT_CTRL_CNT_CLR_CE_BIT	BIT(0)
 
-#define HZIP_NUMA_DISTANCE		100
 #define HZIP_BUF_SIZE			22
 
 static const char hisi_zip_name[] = "hisi_zip";
 static struct dentry *hzip_debugfs_root;
-LIST_HEAD(hisi_zip_list);
-DEFINE_MUTEX(hisi_zip_list_lock);
+static LIST_HEAD(hisi_zip_list);
+static DEFINE_MUTEX(hisi_zip_list_lock);
 
-#ifdef CONFIG_NUMA
-static struct hisi_zip *find_zip_device_numa(int node)
+struct hisi_zip_resource {
+	struct hisi_zip *hzip;
+	int distance;
+	struct list_head list;
+};
+
+static void free_list(struct list_head *head)
 {
-	struct hisi_zip *zip = NULL;
-	struct hisi_zip *hisi_zip;
-	int min_distance = HZIP_NUMA_DISTANCE;
-	struct device *dev;
+	struct hisi_zip_resource *res, *tmp;
 
-	list_for_each_entry(hisi_zip, &hisi_zip_list, list) {
-		dev = &hisi_zip->qm.pdev->dev;
-		if (node_distance(dev->numa_node, node) < min_distance) {
-			zip = hisi_zip;
-			min_distance = node_distance(dev->numa_node, node);
-		}
+	list_for_each_entry_safe(res, tmp, head, list) {
+		list_del(&res->list);
+		kfree(res);
 	}
-
-	return zip;
 }
-#endif
 
 struct hisi_zip *find_zip_device(int node)
 {
-	struct hisi_zip *zip = NULL;
+	struct hisi_zip_resource *res, *tmp;
+	struct hisi_zip *ret = NULL;
+	struct hisi_zip *hisi_zip;
+	struct list_head *n;
+	struct device *dev;
+	LIST_HEAD(head);
 
 	mutex_lock(&hisi_zip_list_lock);
-#ifdef CONFIG_NUMA
-	zip = find_zip_device_numa(node);
-#else
-	zip = list_first_entry(&hisi_zip_list, struct hisi_zip, list);
-#endif
+
+	if (IS_ENABLED(CONFIG_NUMA)) {
+		list_for_each_entry(hisi_zip, &hisi_zip_list, list) {
+			res = kzalloc(sizeof(*res), GFP_KERNEL);
+			if (!res)
+				goto err;
+
+			dev = &hisi_zip->qm.pdev->dev;
+			res->hzip = hisi_zip;
+			res->distance = node_distance(dev_to_node(dev), node);
+
+			n = &head;
+			list_for_each_entry(tmp, &head, list) {
+				if (res->distance < tmp->distance) {
+					n = &tmp->list;
+					break;
+				}
+			}
+			list_add_tail(&res->list, n);
+		}
+
+		list_for_each_entry(tmp, &head, list) {
+			if (hisi_qm_get_free_qp_num(&tmp->hzip->qm)) {
+				ret = tmp->hzip;
+				break;
+			}
+		}
+
+		free_list(&head);
+	} else {
+		ret = list_first_entry(&hisi_zip_list, struct hisi_zip, list);
+	}
+
 	mutex_unlock(&hisi_zip_list_lock);
 
-	return zip;
+	return ret;
+
+err:
+	free_list(&head);
+	mutex_unlock(&hisi_zip_list_lock);
+	return NULL;
 }
 
 struct hisi_zip_hw_error {
@@ -267,6 +300,10 @@
 static int uacce_mode;
 module_param(uacce_mode, int, 0);
 
+static u32 vfs_num;
+module_param(vfs_num, uint, 0444);
+MODULE_PARM_DESC(vfs_num, "Number of VFs to enable(1-63)");
+
 static const struct pci_device_id hisi_zip_dev_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_HUAWEI, PCI_DEVICE_ID_ZIP_PF) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_HUAWEI, PCI_DEVICE_ID_ZIP_VF) },
@@ -329,28 +366,26 @@
 	       FIELD_PREP(CQC_CACHE_WB_THRD, 1), base + QM_CACHE_CTL);
 }
 
-static void hisi_zip_hw_error_set_state(struct hisi_zip *hisi_zip, bool state)
+static void hisi_zip_hw_error_enable(struct hisi_qm *qm)
 {
-	struct hisi_qm *qm = &hisi_zip->qm;
-
 	if (qm->ver == QM_HW_V1) {
-		writel(HZIP_CORE_INT_DISABLE, qm->io_base + HZIP_CORE_INT_MASK);
-		dev_info(&qm->pdev->dev, "ZIP v%d does not support hw error handle\n",
-			 qm->ver);
+		writel(HZIP_CORE_INT_MASK_ALL,
+		       qm->io_base + HZIP_CORE_INT_MASK_REG);
+		dev_info(&qm->pdev->dev, "Does not support hw error handle\n");
 		return;
 	}
 
-	if (state) {
-		/* clear ZIP hw error source if having */
-		writel(HZIP_CORE_INT_DISABLE, hisi_zip->qm.io_base +
-					      HZIP_CORE_INT_SOURCE);
-		/* enable ZIP hw error interrupts */
-		writel(0, hisi_zip->qm.io_base + HZIP_CORE_INT_MASK);
-	} else {
-		/* disable ZIP hw error interrupts */
-		writel(HZIP_CORE_INT_DISABLE,
-		       hisi_zip->qm.io_base + HZIP_CORE_INT_MASK);
-	}
+	/* clear ZIP hw error source if having */
+	writel(HZIP_CORE_INT_MASK_ALL, qm->io_base + HZIP_CORE_INT_SOURCE);
+
+	/* enable ZIP hw error interrupts */
+	writel(0, qm->io_base + HZIP_CORE_INT_MASK_REG);
+}
+
+static void hisi_zip_hw_error_disable(struct hisi_qm *qm)
+{
+	/* disable ZIP hw error interrupts */
+	writel(HZIP_CORE_INT_MASK_ALL, qm->io_base + HZIP_CORE_INT_MASK_REG);
 }
 
 static inline struct hisi_qm *file_to_qm(struct ctrl_debug_file *file)
@@ -511,7 +546,7 @@
 	struct hisi_qm *qm = &hisi_zip->qm;
 	struct device *dev = &qm->pdev->dev;
 	struct debugfs_regset32 *regset;
-	struct dentry *tmp_d, *tmp;
+	struct dentry *tmp_d;
 	char buf[HZIP_BUF_SIZE];
 	int i;
 
@@ -521,10 +556,6 @@
 		else
 			sprintf(buf, "decomp_core%d", i - HZIP_COMP_CORE_NUM);
 
-		tmp_d = debugfs_create_dir(buf, ctrl->debug_root);
-		if (!tmp_d)
-			return -ENOENT;
-
 		regset = devm_kzalloc(dev, sizeof(*regset), GFP_KERNEL);
 		if (!regset)
 			return -ENOENT;
@@ -533,9 +564,8 @@
 		regset->nregs = ARRAY_SIZE(hzip_dfx_regs);
 		regset->base = qm->io_base + core_offsets[i];
 
-		tmp = debugfs_create_regset32("regs", 0444, tmp_d, regset);
-		if (!tmp)
-			return -ENOENT;
+		tmp_d = debugfs_create_dir(buf, ctrl->debug_root);
+		debugfs_create_regset32("regs", 0444, tmp_d, regset);
 	}
 
 	return 0;
@@ -543,7 +573,6 @@
 
 static int hisi_zip_ctrl_debug_init(struct hisi_zip_ctrl *ctrl)
 {
-	struct dentry *tmp;
 	int i;
 
 	for (i = HZIP_CURRENT_QM; i < HZIP_DEBUG_FILE_NUM; i++) {
@@ -551,11 +580,9 @@
 		ctrl->files[i].ctrl = ctrl;
 		ctrl->files[i].index = i;
 
-		tmp = debugfs_create_file(ctrl_debug_file_name[i], 0600,
-					  ctrl->debug_root, ctrl->files + i,
-					  &ctrl_debug_fops);
-		if (!tmp)
-			return -ENOENT;
+		debugfs_create_file(ctrl_debug_file_name[i], 0600,
+				    ctrl->debug_root, ctrl->files + i,
+				    &ctrl_debug_fops);
 	}
 
 	return hisi_zip_core_debug_init(ctrl);
@@ -569,8 +596,6 @@
 	int ret;
 
 	dev_d = debugfs_create_dir(dev_name(dev), hzip_debugfs_root);
-	if (!dev_d)
-		return -ENOENT;
 
 	qm->debug.debug_root = dev_d;
 	ret = hisi_qm_debug_init(qm);
@@ -612,13 +637,16 @@
 		hisi_zip_debug_regs_clear(hisi_zip);
 }
 
-static void hisi_zip_hw_error_init(struct hisi_zip *hisi_zip)
-{
-	hisi_qm_hw_error_init(&hisi_zip->qm, QM_BASE_CE,
-			      QM_BASE_NFE | QM_ACC_WB_NOT_READY_TIMEOUT, 0,
-			      QM_DB_RANDOM_INVALID);
-	hisi_zip_hw_error_set_state(hisi_zip, true);
-}
+static const struct hisi_qm_err_ini hisi_zip_err_ini = {
+	.hw_err_enable	= hisi_zip_hw_error_enable,
+	.hw_err_disable	= hisi_zip_hw_error_disable,
+	.err_info	= {
+		.ce		= QM_BASE_CE,
+		.nfe		= QM_BASE_NFE | QM_ACC_WB_NOT_READY_TIMEOUT,
+		.fe		= 0,
+		.msi		= QM_DB_RANDOM_INVALID,
+	}
+};
 
 static int hisi_zip_pf_probe_init(struct hisi_zip *hisi_zip)
 {
@@ -645,97 +673,15 @@
 		return -EINVAL;
 	}
 
+	qm->err_ini = &hisi_zip_err_ini;
+
 	hisi_zip_set_user_domain_and_cache(hisi_zip);
-	hisi_zip_hw_error_init(hisi_zip);
+	hisi_qm_dev_err_init(qm);
 	hisi_zip_debug_regs_clear(hisi_zip);
 
 	return 0;
 }
 
-static int hisi_zip_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-	struct hisi_zip *hisi_zip;
-	enum qm_hw_ver rev_id;
-	struct hisi_qm *qm;
-	int ret;
-
-	rev_id = hisi_qm_get_hw_version(pdev);
-	if (rev_id == QM_HW_UNKNOWN)
-		return -EINVAL;
-
-	hisi_zip = devm_kzalloc(&pdev->dev, sizeof(*hisi_zip), GFP_KERNEL);
-	if (!hisi_zip)
-		return -ENOMEM;
-	pci_set_drvdata(pdev, hisi_zip);
-
-	qm = &hisi_zip->qm;
-	qm->pdev = pdev;
-	qm->ver = rev_id;
-
-	qm->sqe_size = HZIP_SQE_SIZE;
-	qm->dev_name = hisi_zip_name;
-	qm->fun_type = (pdev->device == PCI_DEVICE_ID_ZIP_PF) ? QM_HW_PF :
-								QM_HW_VF;
-	switch (uacce_mode) {
-	case 0:
-		qm->use_dma_api = true;
-		break;
-	case 1:
-		qm->use_dma_api = false;
-		break;
-	case 2:
-		qm->use_dma_api = true;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	ret = hisi_qm_init(qm);
-	if (ret) {
-		dev_err(&pdev->dev, "Failed to init qm!\n");
-		return ret;
-	}
-
-	if (qm->fun_type == QM_HW_PF) {
-		ret = hisi_zip_pf_probe_init(hisi_zip);
-		if (ret)
-			return ret;
-
-		qm->qp_base = HZIP_PF_DEF_Q_BASE;
-		qm->qp_num = pf_q_num;
-	} else if (qm->fun_type == QM_HW_VF) {
-		/*
-		 * have no way to get qm configure in VM in v1 hardware,
-		 * so currently force PF to uses HZIP_PF_DEF_Q_NUM, and force
-		 * to trigger only one VF in v1 hardware.
-		 *
-		 * v2 hardware has no such problem.
-		 */
-		if (qm->ver == QM_HW_V1) {
-			qm->qp_base = HZIP_PF_DEF_Q_NUM;
-			qm->qp_num = HZIP_QUEUE_NUM_V1 - HZIP_PF_DEF_Q_NUM;
-		} else if (qm->ver == QM_HW_V2)
-			/* v2 starts to support get vft by mailbox */
-			hisi_qm_get_vft(qm, &qm->qp_base, &qm->qp_num);
-	}
-
-	ret = hisi_qm_start(qm);
-	if (ret)
-		goto err_qm_uninit;
-
-	ret = hisi_zip_debugfs_init(hisi_zip);
-	if (ret)
-		dev_err(&pdev->dev, "Failed to init debugfs (%d)!\n", ret);
-
-	hisi_zip_add_to_list(hisi_zip);
-
-	return 0;
-
-err_qm_uninit:
-	hisi_qm_uninit(qm);
-	return ret;
-}
-
 /* Currently we only support equal assignment */
 static int hisi_zip_vf_q_assign(struct hisi_zip *hisi_zip, int num_vfs)
 {
@@ -832,6 +778,100 @@
 	return hisi_zip_clear_vft_config(hisi_zip);
 }
 
+static int hisi_zip_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	struct hisi_zip *hisi_zip;
+	enum qm_hw_ver rev_id;
+	struct hisi_qm *qm;
+	int ret;
+
+	rev_id = hisi_qm_get_hw_version(pdev);
+	if (rev_id == QM_HW_UNKNOWN)
+		return -EINVAL;
+
+	hisi_zip = devm_kzalloc(&pdev->dev, sizeof(*hisi_zip), GFP_KERNEL);
+	if (!hisi_zip)
+		return -ENOMEM;
+	pci_set_drvdata(pdev, hisi_zip);
+
+	qm = &hisi_zip->qm;
+	qm->pdev = pdev;
+	qm->ver = rev_id;
+
+	qm->sqe_size = HZIP_SQE_SIZE;
+	qm->dev_name = hisi_zip_name;
+	qm->fun_type = (pdev->device == PCI_DEVICE_ID_ZIP_PF) ? QM_HW_PF :
+								QM_HW_VF;
+	switch (uacce_mode) {
+	case 0:
+		qm->use_dma_api = true;
+		break;
+	case 1:
+		qm->use_dma_api = false;
+		break;
+	case 2:
+		qm->use_dma_api = true;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = hisi_qm_init(qm);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to init qm!\n");
+		return ret;
+	}
+
+	if (qm->fun_type == QM_HW_PF) {
+		ret = hisi_zip_pf_probe_init(hisi_zip);
+		if (ret)
+			return ret;
+
+		qm->qp_base = HZIP_PF_DEF_Q_BASE;
+		qm->qp_num = pf_q_num;
+	} else if (qm->fun_type == QM_HW_VF) {
+		/*
+		 * have no way to get qm configure in VM in v1 hardware,
+		 * so currently force PF to uses HZIP_PF_DEF_Q_NUM, and force
+		 * to trigger only one VF in v1 hardware.
+		 *
+		 * v2 hardware has no such problem.
+		 */
+		if (qm->ver == QM_HW_V1) {
+			qm->qp_base = HZIP_PF_DEF_Q_NUM;
+			qm->qp_num = HZIP_QUEUE_NUM_V1 - HZIP_PF_DEF_Q_NUM;
+		} else if (qm->ver == QM_HW_V2)
+			/* v2 starts to support get vft by mailbox */
+			hisi_qm_get_vft(qm, &qm->qp_base, &qm->qp_num);
+	}
+
+	ret = hisi_qm_start(qm);
+	if (ret)
+		goto err_qm_uninit;
+
+	ret = hisi_zip_debugfs_init(hisi_zip);
+	if (ret)
+		dev_err(&pdev->dev, "Failed to init debugfs (%d)!\n", ret);
+
+	hisi_zip_add_to_list(hisi_zip);
+
+	if (qm->fun_type == QM_HW_PF && vfs_num > 0) {
+		ret = hisi_zip_sriov_enable(pdev, vfs_num);
+		if (ret < 0)
+			goto err_remove_from_list;
+	}
+
+	return 0;
+
+err_remove_from_list:
+	hisi_zip_remove_from_list(hisi_zip);
+	hisi_zip_debugfs_exit(hisi_zip);
+	hisi_qm_stop(qm);
+err_qm_uninit:
+	hisi_qm_uninit(qm);
+	return ret;
+}
+
 static int hisi_zip_sriov_configure(struct pci_dev *pdev, int num_vfs)
 {
 	if (num_vfs == 0)
@@ -851,9 +891,7 @@
 	hisi_zip_debugfs_exit(hisi_zip);
 	hisi_qm_stop(qm);
 
-	if (qm->fun_type == QM_HW_PF)
-		hisi_zip_hw_error_set_state(hisi_zip, false);
-
+	hisi_qm_dev_err_uninit(qm);
 	hisi_qm_uninit(qm);
 	hisi_zip_remove_from_list(hisi_zip);
 }
@@ -945,7 +983,7 @@
 	.probe			= hisi_zip_probe,
 	.remove			= hisi_zip_remove,
 	.sriov_configure	= IS_ENABLED(CONFIG_PCI_IOV) ?
-					hisi_zip_sriov_configure : 0,
+					hisi_zip_sriov_configure : NULL,
 	.err_handler		= &hisi_zip_err_handler,
 };
 
@@ -955,8 +993,6 @@
 		return;
 
 	hzip_debugfs_root = debugfs_create_dir("hisi_zip", NULL);
-	if (IS_ERR_OR_NULL(hzip_debugfs_root))
-		hzip_debugfs_root = NULL;
 }
 
 static void hisi_zip_unregister_debugfs(void)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/img-hash.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/img-hash.c
@@ -356,12 +356,16 @@
 static void img_hash_dma_task(unsigned long d)
 {
 	struct img_hash_dev *hdev = (struct img_hash_dev *)d;
-	struct img_hash_request_ctx *ctx = ahash_request_ctx(hdev->req);
+	struct img_hash_request_ctx *ctx;
 	u8 *addr;
 	size_t nbytes, bleft, wsend, len, tbc;
 	struct scatterlist tsg;
 
-	if (!hdev->req || !ctx->sg)
+	if (!hdev->req)
+		return;
+
+	ctx = ahash_request_ctx(hdev->req);
+	if (!ctx->sg)
 		return;
 
 	addr = sg_virt(ctx->sg);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/inside-secure/safexcel.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/inside-secure/safexcel.c
@@ -221,9 +221,9 @@
 	/* Step #3: Determine log2 of hash table size */
 	cs_ht_sz = __fls(asize - cs_rc_max) - 2;
 	/* Step #4: determine current size of hash table in dwords */
-	cs_ht_wc = 16<<cs_ht_sz; /* dwords, not admin words */
+	cs_ht_wc = 16 << cs_ht_sz; /* dwords, not admin words */
 	/* Step #5: add back excess words and see if we can fit more records */
-	cs_rc_max = min_t(uint, cs_rc_abs_max, asize - (cs_ht_wc >> 4));
+	cs_rc_max = min_t(uint, cs_rc_abs_max, asize - (cs_ht_wc >> 2));
 
 	/* Clear the cache RAMs */
 	eip197_trc_cache_clear(priv, cs_rc_max, cs_ht_wc);
@@ -1090,11 +1090,12 @@
 
 static int safexcel_request_ring_irq(void *pdev, int irqid,
 				     int is_pci_dev,
+				     int ring_id,
 				     irq_handler_t handler,
 				     irq_handler_t threaded_handler,
 				     struct safexcel_ring_irq_data *ring_irq_priv)
 {
-	int ret, irq;
+	int ret, irq, cpu;
 	struct device *dev;
 
 	if (IS_ENABLED(CONFIG_PCI) && is_pci_dev) {
@@ -1120,6 +1121,8 @@
 				irq_name, irq);
 			return irq;
 		}
+	} else {
+		return -ENXIO;
 	}
 
 	ret = devm_request_threaded_irq(dev, irq, handler,
@@ -1130,6 +1133,10 @@
 		return ret;
 	}
 
+	/* Set affinity */
+	cpu = cpumask_local_spread(ring_id, NUMA_NO_NODE);
+	irq_set_affinity_hint(irq, get_cpu_mask(cpu));
+
 	return irq;
 }
 
@@ -1460,19 +1467,23 @@
 						     &priv->ring[i].rdr);
 		if (ret) {
 			dev_err(dev, "Failed to initialize rings\n");
-			return ret;
+			goto err_cleanup_rings;
 		}
 
 		priv->ring[i].rdr_req = devm_kcalloc(dev,
 			EIP197_DEFAULT_RING_SIZE,
-			sizeof(priv->ring[i].rdr_req),
+			sizeof(*priv->ring[i].rdr_req),
 			GFP_KERNEL);
-		if (!priv->ring[i].rdr_req)
-			return -ENOMEM;
+		if (!priv->ring[i].rdr_req) {
+			ret = -ENOMEM;
+			goto err_cleanup_rings;
+		}
 
 		ring_irq = devm_kzalloc(dev, sizeof(*ring_irq), GFP_KERNEL);
-		if (!ring_irq)
-			return -ENOMEM;
+		if (!ring_irq) {
+			ret = -ENOMEM;
+			goto err_cleanup_rings;
+		}
 
 		ring_irq->priv = priv;
 		ring_irq->ring = i;
@@ -1480,14 +1491,17 @@
 		irq = safexcel_request_ring_irq(pdev,
 						EIP197_IRQ_NUMBER(i, is_pci_dev),
 						is_pci_dev,
+						i,
 						safexcel_irq_ring,
 						safexcel_irq_ring_thread,
 						ring_irq);
 		if (irq < 0) {
 			dev_err(dev, "Failed to get IRQ ID for ring %d\n", i);
-			return irq;
+			ret = irq;
+			goto err_cleanup_rings;
 		}
 
+		priv->ring[i].irq = irq;
 		priv->ring[i].work_data.priv = priv;
 		priv->ring[i].work_data.ring = i;
 		INIT_WORK(&priv->ring[i].work_data.work,
@@ -1496,8 +1510,10 @@
 		snprintf(wq_name, 9, "wq_ring%d", i);
 		priv->ring[i].workqueue =
 			create_singlethread_workqueue(wq_name);
-		if (!priv->ring[i].workqueue)
-			return -ENOMEM;
+		if (!priv->ring[i].workqueue) {
+			ret = -ENOMEM;
+			goto err_cleanup_rings;
+		}
 
 		priv->ring[i].requests = 0;
 		priv->ring[i].busy = false;
@@ -1514,16 +1530,26 @@
 	ret = safexcel_hw_init(priv);
 	if (ret) {
 		dev_err(dev, "HW init failed (%d)\n", ret);
-		return ret;
+		goto err_cleanup_rings;
 	}
 
 	ret = safexcel_register_algorithms(priv);
 	if (ret) {
 		dev_err(dev, "Failed to register algorithms (%d)\n", ret);
-		return ret;
+		goto err_cleanup_rings;
 	}
 
 	return 0;
+
+err_cleanup_rings:
+	for (i = 0; i < priv->config.rings; i++) {
+		if (priv->ring[i].irq)
+			irq_set_affinity_hint(priv->ring[i].irq, NULL);
+		if (priv->ring[i].workqueue)
+			destroy_workqueue(priv->ring[i].workqueue);
+	}
+
+	return ret;
 }
 
 static void safexcel_hw_reset_rings(struct safexcel_crypto_priv *priv)
@@ -1625,8 +1651,10 @@
 
 	clk_disable_unprepare(priv->clk);
 
-	for (i = 0; i < priv->config.rings; i++)
+	for (i = 0; i < priv->config.rings; i++) {
+		irq_set_affinity_hint(priv->ring[i].irq, NULL);
 		destroy_workqueue(priv->ring[i].workqueue);
+	}
 
 	return 0;
 }
@@ -1656,6 +1684,8 @@
 	{},
 };
 
+MODULE_DEVICE_TABLE(of, safexcel_of_match_table);
+
 static struct platform_driver  crypto_safexcel = {
 	.probe		= safexcel_probe,
 	.remove		= safexcel_remove,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/inside-secure/safexcel.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/inside-secure/safexcel.h
@@ -640,6 +640,9 @@
 	 */
 	struct crypto_async_request *req;
 	struct crypto_async_request *backlog;
+
+	/* irq of this ring */
+	int irq;
 };
 
 /* EIP integration context flags */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/ixp4xx_crypto.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/ixp4xx_crypto.c
@@ -329,7 +329,7 @@
 
 		buf1 = buf->next;
 		phys1 = buf->phys_next;
-		dma_unmap_single(dev, buf->phys_next, buf->buf_len, buf->dir);
+		dma_unmap_single(dev, buf->phys_addr, buf->buf_len, buf->dir);
 		dma_pool_free(buffer_pool, buf, phys);
 		buf = buf1;
 		phys = phys1;
@@ -527,7 +527,7 @@
 
 	if (crypt_virt) {
 		dma_free_coherent(dev,
-			NPE_QLEN_TOTAL * sizeof( struct crypt_ctl),
+			NPE_QLEN * sizeof(struct crypt_ctl),
 			crypt_virt, crypt_phys);
 	}
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/marvell/cipher.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/marvell/cipher.c
@@ -287,7 +287,7 @@
 static int mv_cesa_des3_ede_setkey(struct crypto_skcipher *cipher,
 				   const u8 *key, unsigned int len)
 {
-	struct mv_cesa_des_ctx *ctx = crypto_skcipher_ctx(cipher);
+	struct mv_cesa_des3_ctx *ctx = crypto_skcipher_ctx(cipher);
 	int err;
 
 	err = verify_skcipher_des3_key(cipher, key);
@@ -610,7 +610,6 @@
 	.decrypt = mv_cesa_ecb_des3_ede_decrypt,
 	.min_keysize = DES3_EDE_KEY_SIZE,
 	.max_keysize = DES3_EDE_KEY_SIZE,
-	.ivsize = DES3_EDE_BLOCK_SIZE,
 	.base = {
 		.cra_name = "ecb(des3_ede)",
 		.cra_driver_name = "mv-ecb-des3-ede",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/mediatek/mtk-platform.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/mediatek/mtk-platform.c
@@ -442,7 +442,7 @@
 static int mtk_desc_ring_alloc(struct mtk_cryp *cryp)
 {
 	struct mtk_ring **ring = cryp->ring;
-	int i, err = ENOMEM;
+	int i;
 
 	for (i = 0; i < MTK_RING_MAX; i++) {
 		ring[i] = kzalloc(sizeof(**ring), GFP_KERNEL);
@@ -469,14 +469,14 @@
 	return 0;
 
 err_cleanup:
-	for (; i--; ) {
+	do {
 		dma_free_coherent(cryp->dev, MTK_DESC_RING_SZ,
 				  ring[i]->res_base, ring[i]->res_dma);
 		dma_free_coherent(cryp->dev, MTK_DESC_RING_SZ,
 				  ring[i]->cmd_base, ring[i]->cmd_dma);
 		kfree(ring[i]);
-	}
-	return err;
+	} while (i--);
+	return -ENOMEM;
 }
 
 static int mtk_crypto_probe(struct platform_device *pdev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/mxs-dcp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/mxs-dcp.c
@@ -20,6 +20,7 @@
 #include <crypto/sha.h>
 #include <crypto/internal/hash.h>
 #include <crypto/internal/skcipher.h>
+#include <crypto/scatterwalk.h>
 
 #define DCP_MAX_CHANS	4
 #define DCP_BUF_SZ	PAGE_SIZE
@@ -167,15 +168,19 @@
 
 static int mxs_dcp_start_dma(struct dcp_async_ctx *actx)
 {
+	int dma_err;
 	struct dcp *sdcp = global_sdcp;
 	const int chan = actx->chan;
 	uint32_t stat;
 	unsigned long ret;
 	struct dcp_dma_desc *desc = &sdcp->coh->desc[actx->chan];
-
 	dma_addr_t desc_phys = dma_map_single(sdcp->dev, desc, sizeof(*desc),
 					      DMA_TO_DEVICE);
 
+	dma_err = dma_mapping_error(sdcp->dev, desc_phys);
+	if (dma_err)
+		return dma_err;
+
 	reinit_completion(&sdcp->completion[chan]);
 
 	/* Clear status register. */
@@ -213,18 +218,29 @@
 static int mxs_dcp_run_aes(struct dcp_async_ctx *actx,
 			   struct ablkcipher_request *req, int init)
 {
+	dma_addr_t key_phys, src_phys, dst_phys;
 	struct dcp *sdcp = global_sdcp;
 	struct dcp_dma_desc *desc = &sdcp->coh->desc[actx->chan];
 	struct dcp_aes_req_ctx *rctx = ablkcipher_request_ctx(req);
 	int ret;
 
-	dma_addr_t key_phys = dma_map_single(sdcp->dev, sdcp->coh->aes_key,
-					     2 * AES_KEYSIZE_128,
-					     DMA_TO_DEVICE);
-	dma_addr_t src_phys = dma_map_single(sdcp->dev, sdcp->coh->aes_in_buf,
-					     DCP_BUF_SZ, DMA_TO_DEVICE);
-	dma_addr_t dst_phys = dma_map_single(sdcp->dev, sdcp->coh->aes_out_buf,
-					     DCP_BUF_SZ, DMA_FROM_DEVICE);
+	key_phys = dma_map_single(sdcp->dev, sdcp->coh->aes_key,
+				  2 * AES_KEYSIZE_128, DMA_TO_DEVICE);
+	ret = dma_mapping_error(sdcp->dev, key_phys);
+	if (ret)
+		return ret;
+
+	src_phys = dma_map_single(sdcp->dev, sdcp->coh->aes_in_buf,
+				  DCP_BUF_SZ, DMA_TO_DEVICE);
+	ret = dma_mapping_error(sdcp->dev, src_phys);
+	if (ret)
+		goto err_src;
+
+	dst_phys = dma_map_single(sdcp->dev, sdcp->coh->aes_out_buf,
+				  DCP_BUF_SZ, DMA_FROM_DEVICE);
+	ret = dma_mapping_error(sdcp->dev, dst_phys);
+	if (ret)
+		goto err_dst;
 
 	if (actx->fill % AES_BLOCK_SIZE) {
 		dev_err(sdcp->dev, "Invalid block size!\n");
@@ -262,10 +278,12 @@
 	ret = mxs_dcp_start_dma(actx);
 
 aes_done_run:
+	dma_unmap_single(sdcp->dev, dst_phys, DCP_BUF_SZ, DMA_FROM_DEVICE);
+err_dst:
+	dma_unmap_single(sdcp->dev, src_phys, DCP_BUF_SZ, DMA_TO_DEVICE);
+err_src:
 	dma_unmap_single(sdcp->dev, key_phys, 2 * AES_KEYSIZE_128,
 			 DMA_TO_DEVICE);
-	dma_unmap_single(sdcp->dev, src_phys, DCP_BUF_SZ, DMA_TO_DEVICE);
-	dma_unmap_single(sdcp->dev, dst_phys, DCP_BUF_SZ, DMA_FROM_DEVICE);
 
 	return ret;
 }
@@ -280,21 +298,20 @@
 
 	struct scatterlist *dst = req->dst;
 	struct scatterlist *src = req->src;
-	const int nents = sg_nents(req->src);
+	int dst_nents = sg_nents(dst);
 
 	const int out_off = DCP_BUF_SZ;
 	uint8_t *in_buf = sdcp->coh->aes_in_buf;
 	uint8_t *out_buf = sdcp->coh->aes_out_buf;
 
-	uint8_t *out_tmp, *src_buf, *dst_buf = NULL;
 	uint32_t dst_off = 0;
+	uint8_t *src_buf = NULL;
 	uint32_t last_out_len = 0;
 
 	uint8_t *key = sdcp->coh->aes_key;
 
 	int ret = 0;
-	int split = 0;
-	unsigned int i, len, clen, rem = 0, tlen = 0;
+	unsigned int i, len, clen, tlen = 0;
 	int init = 0;
 	bool limit_hit = false;
 
@@ -312,7 +329,7 @@
 		memset(key + AES_KEYSIZE_128, 0, AES_KEYSIZE_128);
 	}
 
-	for_each_sg(req->src, src, nents, i) {
+	for_each_sg(req->src, src, sg_nents(req->src), i) {
 		src_buf = sg_virt(src);
 		len = sg_dma_len(src);
 		tlen += len;
@@ -337,34 +354,17 @@
 			 * submit the buffer.
 			 */
 			if (actx->fill == out_off || sg_is_last(src) ||
-				limit_hit) {
+			    limit_hit) {
 				ret = mxs_dcp_run_aes(actx, req, init);
 				if (ret)
 					return ret;
 				init = 0;
 
-				out_tmp = out_buf;
+				sg_pcopy_from_buffer(dst, dst_nents, out_buf,
+						     actx->fill, dst_off);
+				dst_off += actx->fill;
 				last_out_len = actx->fill;
-				while (dst && actx->fill) {
-					if (!split) {
-						dst_buf = sg_virt(dst);
-						dst_off = 0;
-					}
-					rem = min(sg_dma_len(dst) - dst_off,
-						  actx->fill);
-
-					memcpy(dst_buf + dst_off, out_tmp, rem);
-					out_tmp += rem;
-					dst_off += rem;
-					actx->fill -= rem;
-
-					if (dst_off == sg_dma_len(dst)) {
-						dst = sg_next(dst);
-						split = 0;
-					} else {
-						split = 1;
-					}
-				}
+				actx->fill = 0;
 			}
 		} while (len);
 
@@ -564,6 +564,10 @@
 	dma_addr_t buf_phys = dma_map_single(sdcp->dev, sdcp->coh->sha_in_buf,
 					     DCP_BUF_SZ, DMA_TO_DEVICE);
 
+	ret = dma_mapping_error(sdcp->dev, buf_phys);
+	if (ret)
+		return ret;
+
 	/* Fill in the DMA descriptor. */
 	desc->control0 = MXS_DCP_CONTROL0_DECR_SEMAPHORE |
 		    MXS_DCP_CONTROL0_INTERRUPT |
@@ -596,6 +600,10 @@
 	if (rctx->fini) {
 		digest_phys = dma_map_single(sdcp->dev, sdcp->coh->sha_out_buf,
 					     DCP_SHA_PAY_SZ, DMA_FROM_DEVICE);
+		ret = dma_mapping_error(sdcp->dev, digest_phys);
+		if (ret)
+			goto done_run;
+
 		desc->control0 |= MXS_DCP_CONTROL0_HASH_TERM;
 		desc->payload = digest_phys;
 	}
@@ -621,49 +629,46 @@
 	struct dcp_async_ctx *actx = crypto_ahash_ctx(tfm);
 	struct dcp_sha_req_ctx *rctx = ahash_request_ctx(req);
 	struct hash_alg_common *halg = crypto_hash_alg_common(tfm);
-	const int nents = sg_nents(req->src);
 
 	uint8_t *in_buf = sdcp->coh->sha_in_buf;
 	uint8_t *out_buf = sdcp->coh->sha_out_buf;
 
-	uint8_t *src_buf;
-
 	struct scatterlist *src;
 
-	unsigned int i, len, clen;
+	unsigned int i, len, clen, oft = 0;
 	int ret;
 
 	int fin = rctx->fini;
 	if (fin)
 		rctx->fini = 0;
 
-	for_each_sg(req->src, src, nents, i) {
-		src_buf = sg_virt(src);
-		len = sg_dma_len(src);
+	src = req->src;
+	len = req->nbytes;
 
-		do {
-			if (actx->fill + len > DCP_BUF_SZ)
-				clen = DCP_BUF_SZ - actx->fill;
-			else
-				clen = len;
+	while (len) {
+		if (actx->fill + len > DCP_BUF_SZ)
+			clen = DCP_BUF_SZ - actx->fill;
+		else
+			clen = len;
 
-			memcpy(in_buf + actx->fill, src_buf, clen);
-			len -= clen;
-			src_buf += clen;
-			actx->fill += clen;
+		scatterwalk_map_and_copy(in_buf + actx->fill, src, oft, clen,
+					 0);
 
-			/*
-			 * If we filled the buffer and still have some
-			 * more data, submit the buffer.
-			 */
-			if (len && actx->fill == DCP_BUF_SZ) {
-				ret = mxs_dcp_run_sha(req);
-				if (ret)
-					return ret;
-				actx->fill = 0;
-				rctx->init = 0;
-			}
-		} while (len);
+		len -= clen;
+		oft += clen;
+		actx->fill += clen;
+
+		/*
+		 * If we filled the buffer and still have some
+		 * more data, submit the buffer.
+		 */
+		if (len && actx->fill == DCP_BUF_SZ) {
+			ret = mxs_dcp_run_sha(req);
+			if (ret)
+				return ret;
+			actx->fill = 0;
+			rctx->init = 0;
+		}
 	}
 
 	if (fin) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/n2_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/n2_core.c
@@ -1278,6 +1278,7 @@
 	const u32	*hash_init;
 	u8		hw_op_hashsz;
 	u8		digest_size;
+	u8		statesize;
 	u8		block_size;
 	u8		auth_type;
 	u8		hmac_type;
@@ -1309,6 +1310,7 @@
 	  .hmac_type	= AUTH_TYPE_HMAC_MD5,
 	  .hw_op_hashsz	= MD5_DIGEST_SIZE,
 	  .digest_size	= MD5_DIGEST_SIZE,
+	  .statesize	= sizeof(struct md5_state),
 	  .block_size	= MD5_HMAC_BLOCK_SIZE },
 	{ .name		= "sha1",
 	  .hash_zero	= sha1_zero_message_hash,
@@ -1317,6 +1319,7 @@
 	  .hmac_type	= AUTH_TYPE_HMAC_SHA1,
 	  .hw_op_hashsz	= SHA1_DIGEST_SIZE,
 	  .digest_size	= SHA1_DIGEST_SIZE,
+	  .statesize	= sizeof(struct sha1_state),
 	  .block_size	= SHA1_BLOCK_SIZE },
 	{ .name		= "sha256",
 	  .hash_zero	= sha256_zero_message_hash,
@@ -1325,6 +1328,7 @@
 	  .hmac_type	= AUTH_TYPE_HMAC_SHA256,
 	  .hw_op_hashsz	= SHA256_DIGEST_SIZE,
 	  .digest_size	= SHA256_DIGEST_SIZE,
+	  .statesize	= sizeof(struct sha256_state),
 	  .block_size	= SHA256_BLOCK_SIZE },
 	{ .name		= "sha224",
 	  .hash_zero	= sha224_zero_message_hash,
@@ -1333,6 +1337,7 @@
 	  .hmac_type	= AUTH_TYPE_RESERVED,
 	  .hw_op_hashsz	= SHA256_DIGEST_SIZE,
 	  .digest_size	= SHA224_DIGEST_SIZE,
+	  .statesize	= sizeof(struct sha256_state),
 	  .block_size	= SHA224_BLOCK_SIZE },
 };
 #define NUM_HASH_TMPLS ARRAY_SIZE(hash_tmpls)
@@ -1474,6 +1479,7 @@
 
 	halg = &ahash->halg;
 	halg->digestsize = tmpl->digest_size;
+	halg->statesize = tmpl->statesize;
 
 	base = &halg->base;
 	snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, "%s", tmpl->name);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/nx/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/nx/Makefile
@@ -1,7 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_CRYPTO_DEV_NX_ENCRYPT) += nx-crypto.o
 nx-crypto-objs := nx.o \
-		  nx_debugfs.o \
 		  nx-aes-cbc.o \
 		  nx-aes-ecb.o \
 		  nx-aes-gcm.o \
@@ -11,6 +10,7 @@
 		  nx-sha256.o \
 		  nx-sha512.o
 
+nx-crypto-$(CONFIG_DEBUG_FS) += nx_debugfs.o
 obj-$(CONFIG_CRYPTO_DEV_NX_COMPRESS_PSERIES) += nx-compress-pseries.o nx-compress.o
 obj-$(CONFIG_CRYPTO_DEV_NX_COMPRESS_POWERNV) += nx-compress-powernv.o nx-compress.o
 nx-compress-objs := nx-842.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/nx/nx-842-pseries.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/nx/nx-842-pseries.c
@@ -538,13 +538,15 @@
  * The status field indicates if the device is enabled when the status
  * is 'okay'.  Otherwise the device driver will be disabled.
  *
- * @prop - struct property point containing the maxsyncop for the update
+ * @devdata: struct nx842_devdata to use for dev_info
+ * @prop: struct property point containing the maxsyncop for the update
  *
  * Returns:
  *  0 - Device is available
  *  -ENODEV - Device is not available
  */
-static int nx842_OF_upd_status(struct property *prop)
+static int nx842_OF_upd_status(struct nx842_devdata *devdata,
+			       struct property *prop)
 {
 	const char *status = (const char *)prop->value;
 
@@ -758,7 +760,7 @@
 		goto out;
 
 	/* Perform property updates */
-	ret = nx842_OF_upd_status(status);
+	ret = nx842_OF_upd_status(new_devdata, status);
 	if (ret)
 		goto error_out;
 
@@ -1071,6 +1073,7 @@
 	{"ibm,compression-v1", "ibm,compression"},
 	{"", ""},
 };
+MODULE_DEVICE_TABLE(vio, nx842_vio_driver_ids);
 
 static struct vio_driver nx842_vio_driver = {
 	.name = KBUILD_MODNAME,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/nx/nx.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/nx/nx.h
@@ -169,8 +169,8 @@
 void nx_debugfs_init(struct nx_crypto_driver *);
 void nx_debugfs_fini(struct nx_crypto_driver *);
 #else
-#define NX_DEBUGFS_INIT(drv)	(0)
-#define NX_DEBUGFS_FINI(drv)	(0)
+#define NX_DEBUGFS_INIT(drv)	do {} while (0)
+#define NX_DEBUGFS_FINI(drv)	do {} while (0)
 #endif
 
 #define NX_PAGE_NUM(x)		((u64)(x) & 0xfffffffffffff000ULL)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/omap-aes.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/omap-aes.c
@@ -103,7 +103,7 @@
 		dd->err = 0;
 	}
 
-	err = pm_runtime_get_sync(dd->dev);
+	err = pm_runtime_resume_and_get(dd->dev);
 	if (err < 0) {
 		dev_err(dd->dev, "failed to get sync: %d\n", err);
 		return err;
@@ -1153,11 +1153,11 @@
 	pm_runtime_set_autosuspend_delay(dev, DEFAULT_AUTOSUSPEND_DELAY);
 
 	pm_runtime_enable(dev);
-	err = pm_runtime_get_sync(dev);
+	err = pm_runtime_resume_and_get(dev);
 	if (err < 0) {
 		dev_err(dev, "%s: failed to get_sync(%d)\n",
 			__func__, err);
-		goto err_res;
+		goto err_pm_disable;
 	}
 
 	omap_aes_dma_stop(dd);
@@ -1267,6 +1267,7 @@
 	omap_aes_dma_cleanup(dd);
 err_irq:
 	tasklet_kill(&dd->done_task);
+err_pm_disable:
 	pm_runtime_disable(dev);
 err_res:
 	dd = NULL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/omap-sham.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/omap-sham.c
@@ -165,8 +165,6 @@
 };
 
 struct omap_sham_ctx {
-	struct omap_sham_dev	*dd;
-
 	unsigned long		flags;
 
 	/* fallback stuff */
@@ -366,7 +364,7 @@
 {
 	int err;
 
-	err = pm_runtime_get_sync(dd->dev);
+	err = pm_runtime_resume_and_get(dd->dev);
 	if (err < 0) {
 		dev_err(dd->dev, "failed to get sync: %d\n", err);
 		return err;
@@ -455,6 +453,9 @@
 	struct omap_sham_reqctx *ctx = ahash_request_ctx(dd->req);
 	u32 val, mask;
 
+	if (likely(ctx->digcnt))
+		omap_sham_write(dd, SHA_REG_DIGCNT(dd), ctx->digcnt);
+
 	/*
 	 * Setting ALGO_CONST only for the first iteration and
 	 * CLOSE_HASH only for the last one. Note that flags mode bits
@@ -918,27 +919,35 @@
 	return 0;
 }
 
+struct omap_sham_dev *omap_sham_find_dev(struct omap_sham_reqctx *ctx)
+{
+	struct omap_sham_dev *dd;
+
+	if (ctx->dd)
+		return ctx->dd;
+
+	spin_lock_bh(&sham.lock);
+	dd = list_first_entry(&sham.dev_list, struct omap_sham_dev, list);
+	list_move_tail(&dd->list, &sham.dev_list);
+	ctx->dd = dd;
+	spin_unlock_bh(&sham.lock);
+
+	return dd;
+}
+
 static int omap_sham_init(struct ahash_request *req)
 {
 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
 	struct omap_sham_ctx *tctx = crypto_ahash_ctx(tfm);
 	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
-	struct omap_sham_dev *dd = NULL, *tmp;
+	struct omap_sham_dev *dd;
 	int bs = 0;
 
-	spin_lock_bh(&sham.lock);
-	if (!tctx->dd) {
-		list_for_each_entry(tmp, &sham.dev_list, list) {
-			dd = tmp;
-			break;
-		}
-		tctx->dd = dd;
-	} else {
-		dd = tctx->dd;
-	}
-	spin_unlock_bh(&sham.lock);
+	ctx->dd = NULL;
 
-	ctx->dd = dd;
+	dd = omap_sham_find_dev(ctx);
+	if (!dd)
+		return -ENODEV;
 
 	ctx->flags = 0;
 
@@ -1187,8 +1196,7 @@
 static int omap_sham_enqueue(struct ahash_request *req, unsigned int op)
 {
 	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
-	struct omap_sham_ctx *tctx = crypto_tfm_ctx(req->base.tfm);
-	struct omap_sham_dev *dd = tctx->dd;
+	struct omap_sham_dev *dd = ctx->dd;
 
 	ctx->op = op;
 
@@ -1198,7 +1206,7 @@
 static int omap_sham_update(struct ahash_request *req)
 {
 	struct omap_sham_reqctx *ctx = ahash_request_ctx(req);
-	struct omap_sham_dev *dd = ctx->dd;
+	struct omap_sham_dev *dd = omap_sham_find_dev(ctx);
 
 	if (!req->nbytes)
 		return 0;
@@ -1302,21 +1310,8 @@
 	struct omap_sham_hmac_ctx *bctx = tctx->base;
 	int bs = crypto_shash_blocksize(bctx->shash);
 	int ds = crypto_shash_digestsize(bctx->shash);
-	struct omap_sham_dev *dd = NULL, *tmp;
 	int err, i;
 
-	spin_lock_bh(&sham.lock);
-	if (!tctx->dd) {
-		list_for_each_entry(tmp, &sham.dev_list, list) {
-			dd = tmp;
-			break;
-		}
-		tctx->dd = dd;
-	} else {
-		dd = tctx->dd;
-	}
-	spin_unlock_bh(&sham.lock);
-
 	err = crypto_shash_setkey(tctx->fallback, key, keylen);
 	if (err)
 		return err;
@@ -1334,7 +1329,7 @@
 
 	memset(bctx->ipad + keylen, 0, bs - keylen);
 
-	if (!test_bit(FLAGS_AUTO_XOR, &dd->flags)) {
+	if (!test_bit(FLAGS_AUTO_XOR, &sham.flags)) {
 		memcpy(bctx->opad, bctx->ipad, bs);
 
 		for (i = 0; i < bs; i++) {
@@ -1739,7 +1734,7 @@
 		if (test_and_clear_bit(FLAGS_OUTPUT_READY, &dd->flags))
 			goto finish;
 	} else if (test_bit(FLAGS_DMA_READY, &dd->flags)) {
-		if (test_and_clear_bit(FLAGS_DMA_ACTIVE, &dd->flags)) {
+		if (test_bit(FLAGS_DMA_ACTIVE, &dd->flags)) {
 			omap_sham_update_dma_stop(dd);
 			if (dd->err) {
 				err = dd->err;
@@ -2136,6 +2131,7 @@
 	}
 
 	dd->flags |= dd->pdata->flags;
+	sham.flags |= dd->pdata->flags;
 
 	pm_runtime_use_autosuspend(dev);
 	pm_runtime_set_autosuspend_delay(dev, DEFAULT_AUTOSUSPEND_DELAY);
@@ -2145,7 +2141,7 @@
 	pm_runtime_enable(dev);
 	pm_runtime_irq_safe(dev);
 
-	err = pm_runtime_get_sync(dev);
+	err = pm_runtime_resume_and_get(dev);
 	if (err < 0) {
 		dev_err(dev, "failed to get sync: %d\n", err);
 		goto err_pm;
@@ -2163,6 +2159,9 @@
 	spin_unlock(&sham.lock);
 
 	for (i = 0; i < dd->pdata->algs_info_size; i++) {
+		if (dd->pdata->algs_info[i].registered)
+			break;
+
 		for (j = 0; j < dd->pdata->algs_info[i].size; j++) {
 			struct ahash_alg *alg;
 
@@ -2214,9 +2213,11 @@
 	list_del(&dd->list);
 	spin_unlock(&sham.lock);
 	for (i = dd->pdata->algs_info_size - 1; i >= 0; i--)
-		for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--)
+		for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--) {
 			crypto_unregister_ahash(
 					&dd->pdata->algs_info[i].algs_list[j]);
+			dd->pdata->algs_info[i].registered--;
+		}
 	tasklet_kill(&dd->done_task);
 	pm_runtime_disable(&pdev->dev);
 
@@ -2235,7 +2236,7 @@
 
 static int omap_sham_resume(struct device *dev)
 {
-	int err = pm_runtime_get_sync(dev);
+	int err = pm_runtime_resume_and_get(dev);
 	if (err < 0) {
 		dev_err(dev, "failed to get sync: %d\n", err);
 		return err;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/picoxcell_crypto.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/picoxcell_crypto.c
@@ -1613,6 +1613,11 @@
 MODULE_DEVICE_TABLE(of, spacc_of_id_table);
 #endif /* CONFIG_OF */
 
+static void spacc_tasklet_kill(void *data)
+{
+	tasklet_kill(data);
+}
+
 static int spacc_probe(struct platform_device *pdev)
 {
 	int i, err, ret;
@@ -1655,6 +1660,14 @@
 		return -ENXIO;
 	}
 
+	tasklet_init(&engine->complete, spacc_spacc_complete,
+		     (unsigned long)engine);
+
+	ret = devm_add_action(&pdev->dev, spacc_tasklet_kill,
+			      &engine->complete);
+	if (ret)
+		return ret;
+
 	if (devm_request_irq(&pdev->dev, irq->start, spacc_spacc_irq, 0,
 			     engine->name, engine)) {
 		dev_err(engine->dev, "failed to request IRQ\n");
@@ -1684,11 +1697,6 @@
 		goto err_clk_put;
 	}
 
-	ret = device_create_file(&pdev->dev, &dev_attr_stat_irq_thresh);
-	if (ret)
-		goto err_clk_disable;
-
-
 	/*
 	 * Use an IRQ threshold of 50% as a default. This seems to be a
 	 * reasonable trade off of latency against throughput but can be
@@ -1696,6 +1704,10 @@
 	 */
 	engine->stat_irq_thresh = (engine->fifo_sz / 2);
 
+	ret = device_create_file(&pdev->dev, &dev_attr_stat_irq_thresh);
+	if (ret)
+		goto err_clk_disable;
+
 	/*
 	 * Configure the interrupts. We only use the STAT_CNT interrupt as we
 	 * only submit a new packet for processing when we complete another in
@@ -1712,8 +1724,6 @@
 	INIT_LIST_HEAD(&engine->completed);
 	INIT_LIST_HEAD(&engine->in_progress);
 	engine->in_flight = 0;
-	tasklet_init(&engine->complete, spacc_spacc_complete,
-		     (unsigned long)engine);
 
 	platform_set_drvdata(pdev, engine);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/qat/qat_c3xxxvf/adf_c3xxxvf_hw_data.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/qat/qat_c3xxxvf/adf_c3xxxvf_hw_data.c
@@ -123,10 +123,10 @@
 	hw_data->enable_error_correction = adf_vf_void_noop;
 	hw_data->init_admin_comms = adf_vf_int_noop;
 	hw_data->exit_admin_comms = adf_vf_void_noop;
-	hw_data->send_admin_init = adf_vf2pf_init;
+	hw_data->send_admin_init = adf_vf2pf_notify_init;
 	hw_data->init_arb = adf_vf_int_noop;
 	hw_data->exit_arb = adf_vf_void_noop;
-	hw_data->disable_iov = adf_vf2pf_shutdown;
+	hw_data->disable_iov = adf_vf2pf_notify_shutdown;
 	hw_data->get_accel_mask = get_accel_mask;
 	hw_data->get_ae_mask = get_ae_mask;
 	hw_data->get_num_accels = get_num_accels;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/qat/qat_c3xxxvf/adf_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/qat/qat_c3xxxvf/adf_drv.c
@@ -233,12 +233,12 @@
 	if (ret)
 		goto out_err_free_reg;
 
-	set_bit(ADF_STATUS_PF_RUNNING, &accel_dev->status);
-
 	ret = adf_dev_init(accel_dev);
 	if (ret)
 		goto out_err_dev_shutdown;
 
+	set_bit(ADF_STATUS_PF_RUNNING, &accel_dev->status);
+
 	ret = adf_dev_start(accel_dev);
 	if (ret)
 		goto out_err_dev_stop;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/qat/qat_c62xvf/adf_c62xvf_hw_data.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/qat/qat_c62xvf/adf_c62xvf_hw_data.c
@@ -123,10 +123,10 @@
 	hw_data->enable_error_correction = adf_vf_void_noop;
 	hw_data->init_admin_comms = adf_vf_int_noop;
 	hw_data->exit_admin_comms = adf_vf_void_noop;
-	hw_data->send_admin_init = adf_vf2pf_init;
+	hw_data->send_admin_init = adf_vf2pf_notify_init;
 	hw_data->init_arb = adf_vf_int_noop;
 	hw_data->exit_arb = adf_vf_void_noop;
-	hw_data->disable_iov = adf_vf2pf_shutdown;
+	hw_data->disable_iov = adf_vf2pf_notify_shutdown;
 	hw_data->get_accel_mask = get_accel_mask;
 	hw_data->get_ae_mask = get_ae_mask;
 	hw_data->get_num_accels = get_num_accels;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/qat/qat_c62xvf/adf_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/qat/qat_c62xvf/adf_drv.c
@@ -233,12 +233,12 @@
 	if (ret)
 		goto out_err_free_reg;
 
-	set_bit(ADF_STATUS_PF_RUNNING, &accel_dev->status);
-
 	ret = adf_dev_init(accel_dev);
 	if (ret)
 		goto out_err_dev_shutdown;
 
+	set_bit(ADF_STATUS_PF_RUNNING, &accel_dev->status);
+
 	ret = adf_dev_start(accel_dev);
 	if (ret)
 		goto out_err_dev_stop;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/qat/qat_common/adf_aer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/qat/qat_common/adf_aer.c
@@ -139,7 +139,8 @@
 	if (adf_dev_init(accel_dev) || adf_dev_start(accel_dev)) {
 		/* The device hanged and we can't restart it so stop here */
 		dev_err(&GET_DEV(accel_dev), "Restart device failed\n");
-		kfree(reset_data);
+		if (reset_data->mode == ADF_DEV_RESET_ASYNC)
+			kfree(reset_data);
 		WARN(1, "QAT: device restart failed. Device is unusable\n");
 		return;
 	}
@@ -147,10 +148,10 @@
 	clear_bit(ADF_STATUS_RESTARTING, &accel_dev->status);
 
 	/* The dev is back alive. Notify the caller if in sync mode */
-	if (reset_data->mode == ADF_DEV_RESET_SYNC)
-		complete(&reset_data->compl);
-	else
+	if (reset_data->mode == ADF_DEV_RESET_ASYNC)
 		kfree(reset_data);
+	else
+		complete(&reset_data->compl);
 }
 
 static int adf_dev_aer_schedule_reset(struct adf_accel_dev *accel_dev,
@@ -182,6 +183,7 @@
 		if (!timeout) {
 			dev_err(&GET_DEV(accel_dev),
 				"Reset device timeout expired\n");
+			cancel_work_sync(&reset_data->reset_work);
 			ret = -EFAULT;
 		}
 		kfree(reset_data);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/qat/qat_common/adf_common_drv.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/qat/qat_common/adf_common_drv.h
@@ -239,8 +239,8 @@
 void adf_enable_pf2vf_interrupts(struct adf_accel_dev *accel_dev);
 void adf_disable_pf2vf_interrupts(struct adf_accel_dev *accel_dev);
 
-int adf_vf2pf_init(struct adf_accel_dev *accel_dev);
-void adf_vf2pf_shutdown(struct adf_accel_dev *accel_dev);
+int adf_vf2pf_notify_init(struct adf_accel_dev *accel_dev);
+void adf_vf2pf_notify_shutdown(struct adf_accel_dev *accel_dev);
 int adf_init_pf_wq(void);
 void adf_exit_pf_wq(void);
 int adf_init_vf_wq(void);
@@ -263,12 +263,12 @@
 {
 }
 
-static inline int adf_vf2pf_init(struct adf_accel_dev *accel_dev)
+static inline int adf_vf2pf_notify_init(struct adf_accel_dev *accel_dev)
 {
 	return 0;
 }
 
-static inline void adf_vf2pf_shutdown(struct adf_accel_dev *accel_dev)
+static inline void adf_vf2pf_notify_shutdown(struct adf_accel_dev *accel_dev)
 {
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/qat/qat_common/adf_init.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/qat/qat_common/adf_init.c
@@ -105,6 +105,7 @@
 	struct service_hndl *service;
 	struct list_head *list_itr;
 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
+	int ret;
 
 	if (!hw_data) {
 		dev_err(&GET_DEV(accel_dev),
@@ -171,9 +172,9 @@
 	}
 
 	hw_data->enable_error_correction(accel_dev);
-	hw_data->enable_vf2pf_comms(accel_dev);
+	ret = hw_data->enable_vf2pf_comms(accel_dev);
 
-	return 0;
+	return ret;
 }
 EXPORT_SYMBOL_GPL(adf_dev_init);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/qat/qat_common/adf_isr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/qat/qat_common/adf_isr.c
@@ -59,6 +59,8 @@
 #include "adf_transport_access_macros.h"
 #include "adf_transport_internal.h"
 
+#define ADF_MAX_NUM_VFS	32
+
 static int adf_enable_msix(struct adf_accel_dev *accel_dev)
 {
 	struct adf_accel_pci *pci_dev_info = &accel_dev->accel_pci_dev;
@@ -111,7 +113,7 @@
 		struct adf_bar *pmisc =
 			&GET_BARS(accel_dev)[hw_data->get_misc_bar_id(hw_data)];
 		void __iomem *pmisc_bar_addr = pmisc->virt_addr;
-		u32 vf_mask;
+		unsigned long vf_mask;
 
 		/* Get the interrupt sources triggered by VFs */
 		vf_mask = ((ADF_CSR_RD(pmisc_bar_addr, ADF_ERRSOU5) &
@@ -132,8 +134,7 @@
 			 * unless the VF is malicious and is attempting to
 			 * flood the host OS with VF2PF interrupts.
 			 */
-			for_each_set_bit(i, (const unsigned long *)&vf_mask,
-					 (sizeof(vf_mask) * BITS_PER_BYTE)) {
+			for_each_set_bit(i, &vf_mask, ADF_MAX_NUM_VFS) {
 				vf_info = accel_dev->pf.vf_info + i;
 
 				if (!__ratelimit(&vf_info->vf2pf_ratelimit)) {
@@ -330,19 +331,32 @@
 
 	ret = adf_isr_alloc_msix_entry_table(accel_dev);
 	if (ret)
-		return ret;
-	if (adf_enable_msix(accel_dev))
 		goto err_out;
 
-	if (adf_setup_bh(accel_dev))
-		goto err_out;
+	ret = adf_enable_msix(accel_dev);
+	if (ret)
+		goto err_free_msix_table;
 
-	if (adf_request_irqs(accel_dev))
-		goto err_out;
+	ret = adf_setup_bh(accel_dev);
+	if (ret)
+		goto err_disable_msix;
+
+	ret = adf_request_irqs(accel_dev);
+	if (ret)
+		goto err_cleanup_bh;
 
 	return 0;
+
+err_cleanup_bh:
+	adf_cleanup_bh(accel_dev);
+
+err_disable_msix:
+	adf_disable_msix(&accel_dev->accel_pci_dev);
+
+err_free_msix_table:
+	adf_isr_free_msix_entry_table(accel_dev);
+
 err_out:
-	adf_isr_resource_free(accel_dev);
-	return -EFAULT;
+	return ret;
 }
 EXPORT_SYMBOL_GPL(adf_isr_resource_alloc);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/qat/qat_common/adf_pf2vf_msg.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/qat/qat_common/adf_pf2vf_msg.c
@@ -195,6 +195,13 @@
 		val = ADF_CSR_RD(pmisc_bar_addr, pf2vf_offset);
 	} while ((val & int_bit) && (count++ < ADF_IOV_MSG_ACK_MAX_RETRY));
 
+	if (val != msg) {
+		dev_dbg(&GET_DEV(accel_dev),
+			"Collision - PFVF CSR overwritten by remote function\n");
+		ret = -EIO;
+		goto out;
+	}
+
 	if (val & int_bit) {
 		dev_dbg(&GET_DEV(accel_dev), "ACK not received from remote\n");
 		val &= ~int_bit;
@@ -231,7 +238,6 @@
 
 	return ret;
 }
-EXPORT_SYMBOL_GPL(adf_iov_putmsg);
 
 void adf_vf2pf_req_hndl(struct adf_accel_vf_info *vf_info)
 {
@@ -244,6 +250,11 @@
 
 	/* Read message from the VF */
 	msg = ADF_CSR_RD(pmisc_addr, hw_data->get_pf2vf_offset(vf_nr));
+	if (!(msg & ADF_VF2PF_INT)) {
+		dev_info(&GET_DEV(accel_dev),
+			 "Spurious VF2PF interrupt, msg %X. Ignored\n", msg);
+		goto out;
+	}
 
 	/* To ACK, clear the VF2PFINT bit */
 	msg &= ~ADF_VF2PF_INT;
@@ -327,6 +338,7 @@
 	if (resp && adf_iov_putmsg(accel_dev, resp, vf_nr))
 		dev_err(&GET_DEV(accel_dev), "Failed to send response to VF\n");
 
+out:
 	/* re-enable interrupt on PF from this VF */
 	adf_enable_vf2pf_interrupts(accel_dev, (1 << vf_nr));
 	return;
@@ -361,6 +373,8 @@
 	msg |= ADF_PFVF_COMPATIBILITY_VERSION << ADF_VF2PF_COMPAT_VER_REQ_SHIFT;
 	BUILD_BUG_ON(ADF_PFVF_COMPATIBILITY_VERSION > 255);
 
+	reinit_completion(&accel_dev->vf.iov_msg_completion);
+
 	/* Send request from VF to PF */
 	ret = adf_iov_putmsg(accel_dev, msg, 0);
 	if (ret) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/qat/qat_common/adf_transport.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/qat/qat_common/adf_transport.c
@@ -197,6 +197,7 @@
 		dev_err(&GET_DEV(accel_dev), "Ring address not aligned\n");
 		dma_free_coherent(&GET_DEV(accel_dev), ring_size_bytes,
 				  ring->base_addr, ring->dma_addr);
+		ring->base_addr = NULL;
 		return -EFAULT;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/qat/qat_common/adf_vf2pf_msg.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/qat/qat_common/adf_vf2pf_msg.c
@@ -49,14 +49,14 @@
 #include "adf_pf2vf_msg.h"
 
 /**
- * adf_vf2pf_init() - send init msg to PF
+ * adf_vf2pf_notify_init() - send init msg to PF
  * @accel_dev:  Pointer to acceleration VF device.
  *
  * Function sends an init messge from the VF to a PF
  *
  * Return: 0 on success, error code otherwise.
  */
-int adf_vf2pf_init(struct adf_accel_dev *accel_dev)
+int adf_vf2pf_notify_init(struct adf_accel_dev *accel_dev)
 {
 	u32 msg = (ADF_VF2PF_MSGORIGIN_SYSTEM |
 		(ADF_VF2PF_MSGTYPE_INIT << ADF_VF2PF_MSGTYPE_SHIFT));
@@ -69,17 +69,17 @@
 	set_bit(ADF_STATUS_PF_RUNNING, &accel_dev->status);
 	return 0;
 }
-EXPORT_SYMBOL_GPL(adf_vf2pf_init);
+EXPORT_SYMBOL_GPL(adf_vf2pf_notify_init);
 
 /**
- * adf_vf2pf_shutdown() - send shutdown msg to PF
+ * adf_vf2pf_notify_shutdown() - send shutdown msg to PF
  * @accel_dev:  Pointer to acceleration VF device.
  *
  * Function sends a shutdown messge from the VF to a PF
  *
  * Return: void
  */
-void adf_vf2pf_shutdown(struct adf_accel_dev *accel_dev)
+void adf_vf2pf_notify_shutdown(struct adf_accel_dev *accel_dev)
 {
 	u32 msg = (ADF_VF2PF_MSGORIGIN_SYSTEM |
 	    (ADF_VF2PF_MSGTYPE_SHUTDOWN << ADF_VF2PF_MSGTYPE_SHIFT));
@@ -89,4 +89,4 @@
 			dev_err(&GET_DEV(accel_dev),
 				"Failed to send Shutdown event to PF\n");
 }
-EXPORT_SYMBOL_GPL(adf_vf2pf_shutdown);
+EXPORT_SYMBOL_GPL(adf_vf2pf_notify_shutdown);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/qat/qat_common/adf_vf_isr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/qat/qat_common/adf_vf_isr.c
@@ -123,6 +123,11 @@
 
 	/* Read the message from PF */
 	msg = ADF_CSR_RD(pmisc_bar_addr, hw_data->get_pf2vf_offset(0));
+	if (!(msg & ADF_PF2VF_INT)) {
+		dev_info(&GET_DEV(accel_dev),
+			 "Spurious PF2VF interrupt, msg %X. Ignored\n", msg);
+		goto out;
+	}
 
 	if (!(msg & ADF_PF2VF_MSGORIGIN_SYSTEM))
 		/* Ignore legacy non-system (non-kernel) PF2VF messages */
@@ -171,6 +176,7 @@
 	msg &= ~ADF_PF2VF_INT;
 	ADF_CSR_WR(pmisc_bar_addr, hw_data->get_pf2vf_offset(0), msg);
 
+out:
 	/* Re-enable PF2VF interrupts */
 	adf_enable_pf2vf_interrupts(accel_dev);
 	return;
@@ -203,6 +209,7 @@
 	struct adf_bar *pmisc =
 			&GET_BARS(accel_dev)[hw_data->get_misc_bar_id(hw_data)];
 	void __iomem *pmisc_bar_addr = pmisc->virt_addr;
+	bool handled = false;
 	u32 v_int;
 
 	/* Read VF INT source CSR to determine the source of VF interrupt */
@@ -215,7 +222,7 @@
 
 		/* Schedule tasklet to handle interrupt BH */
 		tasklet_hi_schedule(&accel_dev->vf.pf2vf_bh_tasklet);
-		return IRQ_HANDLED;
+		handled = true;
 	}
 
 	/* Check bundle interrupt */
@@ -227,10 +234,10 @@
 		WRITE_CSR_INT_FLAG_AND_COL(bank->csr_addr, bank->bank_number,
 					   0);
 		tasklet_hi_schedule(&bank->resp_handler);
-		return IRQ_HANDLED;
+		handled = true;
 	}
 
-	return IRQ_NONE;
+	return handled ? IRQ_HANDLED : IRQ_NONE;
 }
 
 static int adf_request_msi_irq(struct adf_accel_dev *accel_dev)
@@ -304,17 +311,26 @@
 		goto err_out;
 
 	if (adf_setup_pf2vf_bh(accel_dev))
-		goto err_out;
+		goto err_disable_msi;
 
 	if (adf_setup_bh(accel_dev))
-		goto err_out;
+		goto err_cleanup_pf2vf_bh;
 
 	if (adf_request_msi_irq(accel_dev))
-		goto err_out;
+		goto err_cleanup_bh;
 
 	return 0;
+
+err_cleanup_bh:
+	adf_cleanup_bh(accel_dev);
+
+err_cleanup_pf2vf_bh:
+	adf_cleanup_pf2vf_bh(accel_dev);
+
+err_disable_msi:
+	adf_disable_msi(accel_dev);
+
 err_out:
-	adf_vf_isr_resource_free(accel_dev);
 	return -EFAULT;
 }
 EXPORT_SYMBOL_GPL(adf_vf_isr_resource_alloc);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/qat/qat_common/qat_algs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/qat/qat_common/qat_algs.c
@@ -715,7 +715,7 @@
 	struct qat_alg_buf_list *bufl;
 	struct qat_alg_buf_list *buflout = NULL;
 	dma_addr_t blp;
-	dma_addr_t bloutp = 0;
+	dma_addr_t bloutp;
 	struct scatterlist *sg;
 	size_t sz_out, sz = struct_size(bufl, bufers, n + 1);
 
@@ -727,6 +727,9 @@
 	if (unlikely(!bufl))
 		return -ENOMEM;
 
+	for_each_sg(sgl, sg, n, i)
+		bufl->bufers[i].addr = DMA_MAPPING_ERROR;
+
 	blp = dma_map_single(dev, bufl, sz, DMA_TO_DEVICE);
 	if (unlikely(dma_mapping_error(dev, blp)))
 		goto err_in;
@@ -760,10 +763,14 @@
 				       dev_to_node(&GET_DEV(inst->accel_dev)));
 		if (unlikely(!buflout))
 			goto err_in;
+
+		bufers = buflout->bufers;
+		for_each_sg(sglout, sg, n, i)
+			bufers[i].addr = DMA_MAPPING_ERROR;
+
 		bloutp = dma_map_single(dev, buflout, sz_out, DMA_TO_DEVICE);
 		if (unlikely(dma_mapping_error(dev, bloutp)))
 			goto err_out;
-		bufers = buflout->bufers;
 		for_each_sg(sglout, sg, n, i) {
 			int y = sg_nctr;
 
@@ -873,6 +880,11 @@
 	struct icp_qat_fw_la_bulk_req *msg;
 	int digst_size = crypto_aead_authsize(aead_tfm);
 	int ret, ctr = 0;
+	u32 cipher_len;
+
+	cipher_len = areq->cryptlen - digst_size;
+	if (cipher_len % AES_BLOCK_SIZE != 0)
+		return -EINVAL;
 
 	ret = qat_alg_sgl_to_bufl(ctx->inst, areq->src, areq->dst, qat_req);
 	if (unlikely(ret))
@@ -887,7 +899,7 @@
 	qat_req->req.comn_mid.src_data_addr = qat_req->buf.blp;
 	qat_req->req.comn_mid.dest_data_addr = qat_req->buf.bloutp;
 	cipher_param = (void *)&qat_req->req.serv_specif_rqpars;
-	cipher_param->cipher_length = areq->cryptlen - digst_size;
+	cipher_param->cipher_length = cipher_len;
 	cipher_param->cipher_offset = areq->assoclen;
 	memcpy(cipher_param->u.cipher_IV_array, areq->iv, AES_BLOCK_SIZE);
 	auth_param = (void *)((uint8_t *)cipher_param + sizeof(*cipher_param));
@@ -916,6 +928,9 @@
 	uint8_t *iv = areq->iv;
 	int ret, ctr = 0;
 
+	if (areq->cryptlen % AES_BLOCK_SIZE != 0)
+		return -EINVAL;
+
 	ret = qat_alg_sgl_to_bufl(ctx->inst, areq->src, areq->dst, qat_req);
 	if (unlikely(ret))
 		return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/qat/qat_common/qat_crypto.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/qat/qat_common/qat_crypto.c
@@ -170,6 +170,14 @@
 		goto err;
 	if (adf_cfg_section_add(accel_dev, "Accelerator0"))
 		goto err;
+
+	/* Temporarily set the number of crypto instances to zero to avoid
+	 * registering the crypto algorithms.
+	 * This will be removed when the algorithms will support the
+	 * CRYPTO_TFM_REQ_MAY_BACKLOG flag
+	 */
+	instances = 0;
+
 	for (i = 0; i < instances; i++) {
 		val = i;
 		snprintf(key, sizeof(key), ADF_CY "%d" ADF_RING_BANK_NUM, i);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/qat/qat_common/qat_hal.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/qat/qat_common/qat_hal.c
@@ -1189,7 +1189,7 @@
 	unsigned short mask;
 	unsigned short dr_offset = 0x10;
 
-	status = ctx_enables = qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES);
+	ctx_enables = qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES);
 	if (CE_INUSE_CONTEXTS & ctx_enables) {
 		if (ctx & 0x1) {
 			pr_err("QAT: bad 4-ctx mode,ctx=0x%x\n", ctx);
@@ -1256,7 +1256,11 @@
 		pr_err("QAT: bad xfrAddr=0x%x\n", xfr_addr);
 		return -EINVAL;
 	}
-	qat_hal_rd_rel_reg(handle, ae, ctx, ICP_GPB_REL, gprnum, &gprval);
+	status = qat_hal_rd_rel_reg(handle, ae, ctx, ICP_GPB_REL, gprnum, &gprval);
+	if (status) {
+		pr_err("QAT: failed to read register");
+		return status;
+	}
 	gpr_addr = qat_hal_get_reg_addr(ICP_GPB_REL, gprnum);
 	data16low = 0xffff & data;
 	data16hi = 0xffff & (data >> 0x10);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/qat/qat_common/qat_uclo.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/qat/qat_common/qat_uclo.c
@@ -332,13 +332,18 @@
 	}
 	return 0;
 out_err:
+	/* Do not free the list head unless we allocated it. */
+	tail_old = tail_old->next;
+	if (flag) {
+		kfree(*init_tab_base);
+		*init_tab_base = NULL;
+	}
+
 	while (tail_old) {
 		mem_init = tail_old->next;
 		kfree(tail_old);
 		tail_old = mem_init;
 	}
-	if (flag)
-		kfree(*init_tab_base);
 	return -ENOMEM;
 }
 
@@ -380,7 +385,6 @@
 	return 0;
 }
 
-#define ICP_DH895XCC_PESRAM_BAR_SIZE 0x80000
 static int qat_uclo_init_ae_memory(struct icp_qat_fw_loader_handle *handle,
 				   struct icp_qat_uof_initmem *init_mem)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/qat/qat_dh895xccvf/adf_dh895xccvf_hw_data.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/qat/qat_dh895xccvf/adf_dh895xccvf_hw_data.c
@@ -123,10 +123,10 @@
 	hw_data->enable_error_correction = adf_vf_void_noop;
 	hw_data->init_admin_comms = adf_vf_int_noop;
 	hw_data->exit_admin_comms = adf_vf_void_noop;
-	hw_data->send_admin_init = adf_vf2pf_init;
+	hw_data->send_admin_init = adf_vf2pf_notify_init;
 	hw_data->init_arb = adf_vf_int_noop;
 	hw_data->exit_arb = adf_vf_void_noop;
-	hw_data->disable_iov = adf_vf2pf_shutdown;
+	hw_data->disable_iov = adf_vf2pf_notify_shutdown;
 	hw_data->get_accel_mask = get_accel_mask;
 	hw_data->get_ae_mask = get_ae_mask;
 	hw_data->get_num_accels = get_num_accels;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/qat/qat_dh895xccvf/adf_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/qat/qat_dh895xccvf/adf_drv.c
@@ -233,12 +233,12 @@
 	if (ret)
 		goto out_err_free_reg;
 
-	set_bit(ADF_STATUS_PF_RUNNING, &accel_dev->status);
-
 	ret = adf_dev_init(accel_dev);
 	if (ret)
 		goto out_err_dev_shutdown;
 
+	set_bit(ADF_STATUS_PF_RUNNING, &accel_dev->status);
+
 	ret = adf_dev_start(accel_dev);
 	if (ret)
 		goto out_err_dev_stop;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/qce/core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/qce/core.c
@@ -40,16 +40,19 @@
 static int qce_register_algs(struct qce_device *qce)
 {
 	const struct qce_algo_ops *ops;
-	int i, ret = -ENODEV;
+	int i, j, ret = -ENODEV;
 
 	for (i = 0; i < ARRAY_SIZE(qce_ops); i++) {
 		ops = qce_ops[i];
 		ret = ops->register_algs(qce);
-		if (ret)
-			break;
+		if (ret) {
+			for (j = i - 1; j >= 0; j--)
+				ops->unregister_algs(qce);
+			return ret;
+		}
 	}
 
-	return ret;
+	return 0;
 }
 
 static int qce_handle_request(struct crypto_async_request *async_req)
@@ -214,7 +217,7 @@
 
 	ret = qce_check_version(qce);
 	if (ret)
-		goto err_clks;
+		goto err_dma;
 
 	spin_lock_init(&qce->lock);
 	tasklet_init(&qce->done_tasklet, qce_tasklet_req_done,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/qce/sha.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/qce/sha.c
@@ -512,8 +512,8 @@
 
 	ret = crypto_register_ahash(alg);
 	if (ret) {
-		kfree(tmpl);
 		dev_err(qce->dev, "%s registration failed\n", base->cra_name);
+		kfree(tmpl);
 		return ret;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/qcom-rng.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/qcom-rng.c
@@ -7,6 +7,7 @@
 #include <linux/acpi.h>
 #include <linux/clk.h>
 #include <linux/crypto.h>
+#include <linux/iopoll.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
@@ -42,16 +43,19 @@
 {
 	unsigned int currsize = 0;
 	u32 val;
+	int ret;
 
 	/* read random data from hardware */
 	do {
-		val = readl_relaxed(rng->base + PRNG_STATUS);
-		if (!(val & PRNG_STATUS_DATA_AVAIL))
-			break;
+		ret = readl_poll_timeout(rng->base + PRNG_STATUS, val,
+					 val & PRNG_STATUS_DATA_AVAIL,
+					 200, 10000);
+		if (ret)
+			return ret;
 
 		val = readl_relaxed(rng->base + PRNG_DATA_OUT);
 		if (!val)
-			break;
+			return -EINVAL;
 
 		if ((max - currsize) >= WORD_SZ) {
 			memcpy(data, &val, WORD_SZ);
@@ -64,7 +68,7 @@
 		}
 	} while (currsize < max);
 
-	return currsize;
+	return 0;
 }
 
 static int qcom_rng_generate(struct crypto_rng *tfm,
@@ -86,7 +90,7 @@
 	mutex_unlock(&rng->lock);
 	clk_disable_unprepare(rng->clk);
 
-	return 0;
+	return ret;
 }
 
 static int qcom_rng_seed(struct crypto_rng *tfm, const u8 *seed,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/s5p-sss.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/s5p-sss.c
@@ -2208,6 +2208,8 @@
 
 	variant = find_s5p_sss_version(pdev);
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -EINVAL;
 
 	/*
 	 * Note: HASH and PRNG uses the same registers in secss, avoid
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/sahara.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/sahara.c
@@ -43,7 +43,6 @@
 #define FLAGS_MODE_MASK		0x000f
 #define FLAGS_ENCRYPT		BIT(0)
 #define FLAGS_CBC		BIT(1)
-#define FLAGS_NEW_KEY		BIT(3)
 
 #define SAHARA_HDR_BASE			0x00800000
 #define SAHARA_HDR_SKHA_ALG_AES	0
@@ -141,8 +140,6 @@
 };
 
 struct sahara_ctx {
-	unsigned long flags;
-
 	/* AES-specific context */
 	int keylen;
 	u8 key[AES_KEYSIZE_128];
@@ -445,27 +442,24 @@
 	int ret;
 	int i, j;
 	int idx = 0;
+	u32 len;
 
-	/* Copy new key if necessary */
-	if (ctx->flags & FLAGS_NEW_KEY) {
-		memcpy(dev->key_base, ctx->key, ctx->keylen);
-		ctx->flags &= ~FLAGS_NEW_KEY;
-
-		if (dev->flags & FLAGS_CBC) {
-			dev->hw_desc[idx]->len1 = AES_BLOCK_SIZE;
-			dev->hw_desc[idx]->p1 = dev->iv_phys_base;
-		} else {
-			dev->hw_desc[idx]->len1 = 0;
-			dev->hw_desc[idx]->p1 = 0;
-		}
-		dev->hw_desc[idx]->len2 = ctx->keylen;
-		dev->hw_desc[idx]->p2 = dev->key_phys_base;
-		dev->hw_desc[idx]->next = dev->hw_phys_desc[1];
-
-		dev->hw_desc[idx]->hdr = sahara_aes_key_hdr(dev);
+	memcpy(dev->key_base, ctx->key, ctx->keylen);
 
-		idx++;
+	if (dev->flags & FLAGS_CBC) {
+		dev->hw_desc[idx]->len1 = AES_BLOCK_SIZE;
+		dev->hw_desc[idx]->p1 = dev->iv_phys_base;
+	} else {
+		dev->hw_desc[idx]->len1 = 0;
+		dev->hw_desc[idx]->p1 = 0;
 	}
+	dev->hw_desc[idx]->len2 = ctx->keylen;
+	dev->hw_desc[idx]->p2 = dev->key_phys_base;
+	dev->hw_desc[idx]->next = dev->hw_phys_desc[1];
+	dev->hw_desc[idx]->hdr = sahara_aes_key_hdr(dev);
+
+	idx++;
+
 
 	dev->nb_in_sg = sg_nents_for_len(dev->in_sg, dev->total);
 	if (dev->nb_in_sg < 0) {
@@ -487,24 +481,27 @@
 			 DMA_TO_DEVICE);
 	if (ret != dev->nb_in_sg) {
 		dev_err(dev->device, "couldn't map in sg\n");
-		goto unmap_in;
+		return -EINVAL;
 	}
+
 	ret = dma_map_sg(dev->device, dev->out_sg, dev->nb_out_sg,
 			 DMA_FROM_DEVICE);
 	if (ret != dev->nb_out_sg) {
 		dev_err(dev->device, "couldn't map out sg\n");
-		goto unmap_out;
+		goto unmap_in;
 	}
 
 	/* Create input links */
 	dev->hw_desc[idx]->p1 = dev->hw_phys_link[0];
 	sg = dev->in_sg;
+	len = dev->total;
 	for (i = 0; i < dev->nb_in_sg; i++) {
-		dev->hw_link[i]->len = sg->length;
+		dev->hw_link[i]->len = min(len, sg->length);
 		dev->hw_link[i]->p = sg->dma_address;
 		if (i == (dev->nb_in_sg - 1)) {
 			dev->hw_link[i]->next = 0;
 		} else {
+			len -= min(len, sg->length);
 			dev->hw_link[i]->next = dev->hw_phys_link[i + 1];
 			sg = sg_next(sg);
 		}
@@ -513,12 +510,14 @@
 	/* Create output links */
 	dev->hw_desc[idx]->p2 = dev->hw_phys_link[i];
 	sg = dev->out_sg;
+	len = dev->total;
 	for (j = i; j < dev->nb_out_sg + i; j++) {
-		dev->hw_link[j]->len = sg->length;
+		dev->hw_link[j]->len = min(len, sg->length);
 		dev->hw_link[j]->p = sg->dma_address;
 		if (j == (dev->nb_out_sg + i - 1)) {
 			dev->hw_link[j]->next = 0;
 		} else {
+			len -= min(len, sg->length);
 			dev->hw_link[j]->next = dev->hw_phys_link[j + 1];
 			sg = sg_next(sg);
 		}
@@ -537,9 +536,6 @@
 
 	return 0;
 
-unmap_out:
-	dma_unmap_sg(dev->device, dev->out_sg, dev->nb_out_sg,
-		DMA_FROM_DEVICE);
 unmap_in:
 	dma_unmap_sg(dev->device, dev->in_sg, dev->nb_in_sg,
 		DMA_TO_DEVICE);
@@ -584,16 +580,17 @@
 
 	timeout = wait_for_completion_timeout(&dev->dma_completion,
 				msecs_to_jiffies(SAHARA_TIMEOUT_MS));
-	if (!timeout) {
-		dev_err(dev->device, "AES timeout\n");
-		return -ETIMEDOUT;
-	}
 
 	dma_unmap_sg(dev->device, dev->out_sg, dev->nb_out_sg,
 		DMA_FROM_DEVICE);
 	dma_unmap_sg(dev->device, dev->in_sg, dev->nb_in_sg,
 		DMA_TO_DEVICE);
 
+	if (!timeout) {
+		dev_err(dev->device, "AES timeout\n");
+		return -ETIMEDOUT;
+	}
+
 	return 0;
 }
 
@@ -608,7 +605,6 @@
 	/* SAHARA only supports 128bit keys */
 	if (keylen == AES_KEYSIZE_128) {
 		memcpy(ctx->key, key, keylen);
-		ctx->flags |= FLAGS_NEW_KEY;
 		return 0;
 	}
 
@@ -796,6 +792,7 @@
 				       int start)
 {
 	struct scatterlist *sg;
+	unsigned int len;
 	unsigned int i;
 	int ret;
 
@@ -817,12 +814,14 @@
 	if (!ret)
 		return -EFAULT;
 
+	len = rctx->total;
 	for (i = start; i < dev->nb_in_sg + start; i++) {
-		dev->hw_link[i]->len = sg->length;
+		dev->hw_link[i]->len = min(len, sg->length);
 		dev->hw_link[i]->p = sg->dma_address;
 		if (i == (dev->nb_in_sg + start - 1)) {
 			dev->hw_link[i]->next = 0;
 		} else {
+			len -= min(len, sg->length);
 			dev->hw_link[i]->next = dev->hw_phys_link[i + 1];
 			sg = sg_next(sg);
 		}
@@ -903,24 +902,6 @@
 	return 0;
 }
 
-static int sahara_walk_and_recalc(struct scatterlist *sg, unsigned int nbytes)
-{
-	if (!sg || !sg->length)
-		return nbytes;
-
-	while (nbytes && sg) {
-		if (nbytes <= sg->length) {
-			sg->length = nbytes;
-			sg_mark_end(sg);
-			break;
-		}
-		nbytes -= sg->length;
-		sg = sg_next(sg);
-	}
-
-	return nbytes;
-}
-
 static int sahara_sha_prepare_request(struct ahash_request *req)
 {
 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
@@ -957,36 +938,20 @@
 					hash_later, 0);
 	}
 
-	/* nbytes should now be multiple of blocksize */
-	req->nbytes = req->nbytes - hash_later;
-
-	sahara_walk_and_recalc(req->src, req->nbytes);
-
+	rctx->total = len - hash_later;
 	/* have data from previous operation and current */
 	if (rctx->buf_cnt && req->nbytes) {
 		sg_init_table(rctx->in_sg_chain, 2);
 		sg_set_buf(rctx->in_sg_chain, rctx->rembuf, rctx->buf_cnt);
-
 		sg_chain(rctx->in_sg_chain, 2, req->src);
-
-		rctx->total = req->nbytes + rctx->buf_cnt;
 		rctx->in_sg = rctx->in_sg_chain;
-
-		req->src = rctx->in_sg_chain;
 	/* only data from previous operation */
 	} else if (rctx->buf_cnt) {
-		if (req->src)
-			rctx->in_sg = req->src;
-		else
-			rctx->in_sg = rctx->in_sg_chain;
-		/* buf was copied into rembuf above */
+		rctx->in_sg = rctx->in_sg_chain;
 		sg_init_one(rctx->in_sg, rctx->rembuf, rctx->buf_cnt);
-		rctx->total = rctx->buf_cnt;
 	/* no data from previous operation */
 	} else {
 		rctx->in_sg = req->src;
-		rctx->total = req->nbytes;
-		req->src = rctx->in_sg;
 	}
 
 	/* on next call, we only have the remaining data in the buffer */
@@ -1007,7 +972,10 @@
 		return ret;
 
 	if (rctx->first) {
-		sahara_sha_hw_data_descriptor_create(dev, rctx, req, 0);
+		ret = sahara_sha_hw_data_descriptor_create(dev, rctx, req, 0);
+		if (ret)
+			return ret;
+
 		dev->hw_desc[0]->next = 0;
 		rctx->first = 0;
 	} else {
@@ -1015,7 +983,10 @@
 
 		sahara_sha_hw_context_descriptor_create(dev, rctx, req, 0);
 		dev->hw_desc[0]->next = dev->hw_phys_desc[1];
-		sahara_sha_hw_data_descriptor_create(dev, rctx, req, 1);
+		ret = sahara_sha_hw_data_descriptor_create(dev, rctx, req, 1);
+		if (ret)
+			return ret;
+
 		dev->hw_desc[1]->next = 0;
 	}
 
@@ -1028,18 +999,19 @@
 
 	timeout = wait_for_completion_timeout(&dev->dma_completion,
 				msecs_to_jiffies(SAHARA_TIMEOUT_MS));
-	if (!timeout) {
-		dev_err(dev->device, "SHA timeout\n");
-		return -ETIMEDOUT;
-	}
 
 	if (rctx->sg_in_idx)
 		dma_unmap_sg(dev->device, dev->in_sg, dev->nb_in_sg,
 			     DMA_TO_DEVICE);
 
+	if (!timeout) {
+		dev_err(dev->device, "SHA timeout\n");
+		return -ETIMEDOUT;
+	}
+
 	memcpy(rctx->context, dev->context_base, rctx->context_size);
 
-	if (req->result)
+	if (req->result && rctx->last)
 		memcpy(req->result, rctx->context, rctx->digest_size);
 
 	return 0;
@@ -1183,8 +1155,7 @@
 static int sahara_sha_cra_init(struct crypto_tfm *tfm)
 {
 	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
-				 sizeof(struct sahara_sha_reqctx) +
-				 SHA_BUFFER_LEN + SHA256_BLOCK_SIZE);
+				 sizeof(struct sahara_sha_reqctx));
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/stm32/stm32-crc32.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/stm32/stm32-crc32.c
@@ -28,8 +28,10 @@
 
 /* Registers values */
 #define CRC_CR_RESET            BIT(0)
-#define CRC_CR_REVERSE          (BIT(7) | BIT(6) | BIT(5))
-#define CRC_INIT_DEFAULT        0xFFFFFFFF
+#define CRC_CR_REV_IN_WORD      (BIT(6) | BIT(5))
+#define CRC_CR_REV_IN_BYTE      BIT(5)
+#define CRC_CR_REV_OUT          BIT(7)
+#define CRC32C_INIT_DEFAULT     0xFFFFFFFF
 
 #define CRC_AUTOSUSPEND_DELAY	50
 
@@ -38,8 +40,6 @@
 	struct device    *dev;
 	void __iomem     *regs;
 	struct clk       *clk;
-	u8               pending_data[sizeof(u32)];
-	size_t           nb_pending_bytes;
 };
 
 struct stm32_crc_list {
@@ -59,14 +59,13 @@
 
 struct stm32_crc_desc_ctx {
 	u32    partial; /* crc32c: partial in first 4 bytes of that struct */
-	struct stm32_crc *crc;
 };
 
 static int stm32_crc32_cra_init(struct crypto_tfm *tfm)
 {
 	struct stm32_crc_ctx *mctx = crypto_tfm_ctx(tfm);
 
-	mctx->key = CRC_INIT_DEFAULT;
+	mctx->key = 0;
 	mctx->poly = CRC32_POLY_LE;
 	return 0;
 }
@@ -75,7 +74,7 @@
 {
 	struct stm32_crc_ctx *mctx = crypto_tfm_ctx(tfm);
 
-	mctx->key = CRC_INIT_DEFAULT;
+	mctx->key = CRC32C_INIT_DEFAULT;
 	mctx->poly = CRC32C_POLY_LE;
 	return 0;
 }
@@ -94,32 +93,42 @@
 	return 0;
 }
 
+static struct stm32_crc *stm32_crc_get_next_crc(void)
+{
+	struct stm32_crc *crc;
+
+	spin_lock_bh(&crc_list.lock);
+	crc = list_first_entry_or_null(&crc_list.dev_list, struct stm32_crc, list);
+	if (crc)
+		list_move_tail(&crc->list, &crc_list.dev_list);
+	spin_unlock_bh(&crc_list.lock);
+
+	return crc;
+}
+
 static int stm32_crc_init(struct shash_desc *desc)
 {
 	struct stm32_crc_desc_ctx *ctx = shash_desc_ctx(desc);
 	struct stm32_crc_ctx *mctx = crypto_shash_ctx(desc->tfm);
 	struct stm32_crc *crc;
 
-	spin_lock_bh(&crc_list.lock);
-	list_for_each_entry(crc, &crc_list.dev_list, list) {
-		ctx->crc = crc;
-		break;
-	}
-	spin_unlock_bh(&crc_list.lock);
+	crc = stm32_crc_get_next_crc();
+	if (!crc)
+		return -ENODEV;
 
-	pm_runtime_get_sync(ctx->crc->dev);
+	pm_runtime_get_sync(crc->dev);
 
 	/* Reset, set key, poly and configure in bit reverse mode */
-	writel_relaxed(bitrev32(mctx->key), ctx->crc->regs + CRC_INIT);
-	writel_relaxed(bitrev32(mctx->poly), ctx->crc->regs + CRC_POL);
-	writel_relaxed(CRC_CR_RESET | CRC_CR_REVERSE, ctx->crc->regs + CRC_CR);
+	writel_relaxed(bitrev32(mctx->key), crc->regs + CRC_INIT);
+	writel_relaxed(bitrev32(mctx->poly), crc->regs + CRC_POL);
+	writel_relaxed(CRC_CR_RESET | CRC_CR_REV_IN_WORD | CRC_CR_REV_OUT,
+		       crc->regs + CRC_CR);
 
 	/* Store partial result */
-	ctx->partial = readl_relaxed(ctx->crc->regs + CRC_DR);
-	ctx->crc->nb_pending_bytes = 0;
+	ctx->partial = readl_relaxed(crc->regs + CRC_DR);
 
-	pm_runtime_mark_last_busy(ctx->crc->dev);
-	pm_runtime_put_autosuspend(ctx->crc->dev);
+	pm_runtime_mark_last_busy(crc->dev);
+	pm_runtime_put_autosuspend(crc->dev);
 
 	return 0;
 }
@@ -128,31 +137,49 @@
 			    unsigned int length)
 {
 	struct stm32_crc_desc_ctx *ctx = shash_desc_ctx(desc);
-	struct stm32_crc *crc = ctx->crc;
-	u32 *d32;
-	unsigned int i;
+	struct stm32_crc_ctx *mctx = crypto_shash_ctx(desc->tfm);
+	struct stm32_crc *crc;
+
+	crc = stm32_crc_get_next_crc();
+	if (!crc)
+		return -ENODEV;
 
 	pm_runtime_get_sync(crc->dev);
 
-	if (unlikely(crc->nb_pending_bytes)) {
-		while (crc->nb_pending_bytes != sizeof(u32) && length) {
-			/* Fill in pending data */
-			crc->pending_data[crc->nb_pending_bytes++] = *(d8++);
+	/*
+	 * Restore previously calculated CRC for this context as init value
+	 * Restore polynomial configuration
+	 * Configure in register for word input data,
+	 * Configure out register in reversed bit mode data.
+	 */
+	writel_relaxed(bitrev32(ctx->partial), crc->regs + CRC_INIT);
+	writel_relaxed(bitrev32(mctx->poly), crc->regs + CRC_POL);
+	writel_relaxed(CRC_CR_RESET | CRC_CR_REV_IN_WORD | CRC_CR_REV_OUT,
+		       crc->regs + CRC_CR);
+
+	if (d8 != PTR_ALIGN(d8, sizeof(u32))) {
+		/* Configure for byte data */
+		writel_relaxed(CRC_CR_REV_IN_BYTE | CRC_CR_REV_OUT,
+			       crc->regs + CRC_CR);
+		while (d8 != PTR_ALIGN(d8, sizeof(u32)) && length) {
+			writeb_relaxed(*d8++, crc->regs + CRC_DR);
 			length--;
 		}
-
-		if (crc->nb_pending_bytes == sizeof(u32)) {
-			/* Process completed pending data */
-			writel_relaxed(*(u32 *)crc->pending_data,
-				       crc->regs + CRC_DR);
-			crc->nb_pending_bytes = 0;
-		}
+		/* Configure for word data */
+		writel_relaxed(CRC_CR_REV_IN_WORD | CRC_CR_REV_OUT,
+			       crc->regs + CRC_CR);
 	}
 
-	d32 = (u32 *)d8;
-	for (i = 0; i < length >> 2; i++)
-		/* Process 32 bits data */
-		writel_relaxed(*(d32++), crc->regs + CRC_DR);
+	for (; length >= sizeof(u32); d8 += sizeof(u32), length -= sizeof(u32))
+		writel_relaxed(*((u32 *)d8), crc->regs + CRC_DR);
+
+	if (length) {
+		/* Configure for byte data */
+		writel_relaxed(CRC_CR_REV_IN_BYTE | CRC_CR_REV_OUT,
+			       crc->regs + CRC_CR);
+		while (length--)
+			writeb_relaxed(*d8++, crc->regs + CRC_DR);
+	}
 
 	/* Store partial result */
 	ctx->partial = readl_relaxed(crc->regs + CRC_DR);
@@ -160,22 +187,6 @@
 	pm_runtime_mark_last_busy(crc->dev);
 	pm_runtime_put_autosuspend(crc->dev);
 
-	/* Check for pending data (non 32 bits) */
-	length &= 3;
-	if (likely(!length))
-		return 0;
-
-	if ((crc->nb_pending_bytes + length) >= sizeof(u32)) {
-		/* Shall not happen */
-		dev_err(crc->dev, "Pending data overflow\n");
-		return -EINVAL;
-	}
-
-	d8 = (const u8 *)d32;
-	for (i = 0; i < length; i++)
-		/* Store pending data */
-		crc->pending_data[crc->nb_pending_bytes++] = *(d8++);
-
 	return 0;
 }
 
@@ -204,6 +215,8 @@
 	return stm32_crc_init(desc) ?: stm32_crc_finup(desc, data, length, out);
 }
 
+static unsigned int refcnt;
+static DEFINE_MUTEX(refcnt_lock);
 static struct shash_alg algs[] = {
 	/* CRC-32 */
 	{
@@ -217,7 +230,7 @@
 		.digestsize     = CHKSUM_DIGEST_SIZE,
 		.base           = {
 			.cra_name               = "crc32",
-			.cra_driver_name        = DRIVER_NAME,
+			.cra_driver_name        = "stm32-crc32-crc32",
 			.cra_priority           = 200,
 			.cra_flags		= CRYPTO_ALG_OPTIONAL_KEY,
 			.cra_blocksize          = CHKSUM_BLOCK_SIZE,
@@ -239,7 +252,7 @@
 		.digestsize     = CHKSUM_DIGEST_SIZE,
 		.base           = {
 			.cra_name               = "crc32c",
-			.cra_driver_name        = DRIVER_NAME,
+			.cra_driver_name        = "stm32-crc32-crc32c",
 			.cra_priority           = 200,
 			.cra_flags		= CRYPTO_ALG_OPTIONAL_KEY,
 			.cra_blocksize          = CHKSUM_BLOCK_SIZE,
@@ -294,12 +307,18 @@
 	list_add(&crc->list, &crc_list.dev_list);
 	spin_unlock(&crc_list.lock);
 
-	ret = crypto_register_shashes(algs, ARRAY_SIZE(algs));
-	if (ret) {
-		dev_err(dev, "Failed to register\n");
-		clk_disable_unprepare(crc->clk);
-		return ret;
+	mutex_lock(&refcnt_lock);
+	if (!refcnt) {
+		ret = crypto_register_shashes(algs, ARRAY_SIZE(algs));
+		if (ret) {
+			mutex_unlock(&refcnt_lock);
+			dev_err(dev, "Failed to register\n");
+			clk_disable_unprepare(crc->clk);
+			return ret;
+		}
 	}
+	refcnt++;
+	mutex_unlock(&refcnt_lock);
 
 	dev_info(dev, "Initialized\n");
 
@@ -313,14 +332,19 @@
 	struct stm32_crc *crc = platform_get_drvdata(pdev);
 	int ret = pm_runtime_get_sync(crc->dev);
 
-	if (ret < 0)
+	if (ret < 0) {
+		pm_runtime_put_noidle(crc->dev);
 		return ret;
+	}
 
 	spin_lock(&crc_list.lock);
 	list_del(&crc->list);
 	spin_unlock(&crc_list.lock);
 
-	crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
+	mutex_lock(&refcnt_lock);
+	if (!--refcnt)
+		crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
+	mutex_unlock(&refcnt_lock);
 
 	pm_runtime_disable(crc->dev);
 	pm_runtime_put_noidle(crc->dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/stm32/stm32-cryp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/stm32/stm32-cryp.c
@@ -537,7 +537,7 @@
 	int ret;
 	u32 cfg, hw_mode;
 
-	pm_runtime_get_sync(cryp->dev);
+	pm_runtime_resume_and_get(cryp->dev);
 
 	/* Disable interrupt */
 	stm32_cryp_write(cryp, CRYP_IMSCR, 0);
@@ -639,7 +639,7 @@
 		/* Phase 4 : output tag */
 		err = stm32_cryp_read_auth_tag(cryp);
 
-	if (!err && (!(is_gcm(cryp) || is_ccm(cryp))))
+	if (!err && (!(is_gcm(cryp) || is_ccm(cryp) || is_ecb(cryp))))
 		stm32_cryp_get_iv(cryp);
 
 	if (cryp->sgs_copied) {
@@ -669,8 +669,6 @@
 	else
 		crypto_finalize_ablkcipher_request(cryp->engine, cryp->req,
 						   err);
-
-	memset(cryp->ctx->key, 0, cryp->ctx->keylen);
 }
 
 static int stm32_cryp_cpu_start(struct stm32_cryp *cryp)
@@ -2038,8 +2036,6 @@
 
 	pm_runtime_disable(dev);
 	pm_runtime_put_noidle(dev);
-	pm_runtime_disable(dev);
-	pm_runtime_put_noidle(dev);
 
 	clk_disable_unprepare(cryp->clk);
 
@@ -2054,7 +2050,7 @@
 	if (!cryp)
 		return -ENODEV;
 
-	ret = pm_runtime_get_sync(cryp->dev);
+	ret = pm_runtime_resume_and_get(cryp->dev);
 	if (ret < 0)
 		return ret;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/stm32/stm32-hash.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/stm32/stm32-hash.c
@@ -562,9 +562,9 @@
 	}
 
 	for_each_sg(rctx->sg, tsg, rctx->nents, i) {
+		sg[0] = *tsg;
 		len = sg->length;
 
-		sg[0] = *tsg;
 		if (sg_is_last(sg)) {
 			if (hdev->dma_mode == 1) {
 				len = (ALIGN(sg->length, 16) - 16);
@@ -810,7 +810,7 @@
 static int stm32_hash_hw_init(struct stm32_hash_dev *hdev,
 			      struct stm32_hash_request_ctx *rctx)
 {
-	pm_runtime_get_sync(hdev->dev);
+	pm_runtime_resume_and_get(hdev->dev);
 
 	if (!(HASH_FLAGS_INIT & hdev->flags)) {
 		stm32_hash_write(hdev, HASH_CR, HASH_CR_INIT);
@@ -959,7 +959,7 @@
 	u32 *preg;
 	unsigned int i;
 
-	pm_runtime_get_sync(hdev->dev);
+	pm_runtime_resume_and_get(hdev->dev);
 
 	while ((stm32_hash_read(hdev, HASH_SR) & HASH_SR_BUSY))
 		cpu_relax();
@@ -997,7 +997,7 @@
 
 	preg = rctx->hw_context;
 
-	pm_runtime_get_sync(hdev->dev);
+	pm_runtime_resume_and_get(hdev->dev);
 
 	stm32_hash_write(hdev, HASH_IMR, *preg++);
 	stm32_hash_write(hdev, HASH_STR, *preg++);
@@ -1554,8 +1554,6 @@
 		return -ENODEV;
 
 	ret = pm_runtime_get_sync(hdev->dev);
-	if (ret < 0)
-		return ret;
 
 	stm32_hash_unregister_algs(hdev);
 
@@ -1571,7 +1569,8 @@
 	pm_runtime_disable(hdev->dev);
 	pm_runtime_put_noidle(hdev->dev);
 
-	clk_disable_unprepare(hdev->clk);
+	if (ret >= 0)
+		clk_disable_unprepare(hdev->clk);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c
@@ -30,6 +30,8 @@
 	unsigned int ileft = areq->cryptlen;
 	unsigned int oleft = areq->cryptlen;
 	unsigned int todo;
+	unsigned long pi = 0, po = 0; /* progress for in and out */
+	bool miter_err;
 	struct sg_mapping_iter mi, mo;
 	unsigned int oi, oo; /* offset for in and out */
 	unsigned long flags;
@@ -44,59 +46,74 @@
 
 	spin_lock_irqsave(&ss->slock, flags);
 
-	for (i = 0; i < op->keylen; i += 4)
-		writel(*(op->key + i / 4), ss->base + SS_KEY0 + i);
+	for (i = 0; i < op->keylen / 4; i++)
+		writesl(ss->base + SS_KEY0 + i * 4, &op->key[i], 1);
 
 	if (areq->iv) {
 		for (i = 0; i < 4 && i < ivsize / 4; i++) {
 			v = *(u32 *)(areq->iv + i * 4);
-			writel(v, ss->base + SS_IV0 + i * 4);
+			writesl(ss->base + SS_IV0 + i * 4, &v, 1);
 		}
 	}
 	writel(mode, ss->base + SS_CTL);
 
-	sg_miter_start(&mi, areq->src, sg_nents(areq->src),
-		       SG_MITER_FROM_SG | SG_MITER_ATOMIC);
-	sg_miter_start(&mo, areq->dst, sg_nents(areq->dst),
-		       SG_MITER_TO_SG | SG_MITER_ATOMIC);
-	sg_miter_next(&mi);
-	sg_miter_next(&mo);
-	if (!mi.addr || !mo.addr) {
-		dev_err_ratelimited(ss->dev, "ERROR: sg_miter return null\n");
-		err = -EINVAL;
-		goto release_ss;
-	}
 
 	ileft = areq->cryptlen / 4;
 	oleft = areq->cryptlen / 4;
 	oi = 0;
 	oo = 0;
 	do {
-		todo = min3(rx_cnt, ileft, (mi.length - oi) / 4);
-		if (todo) {
-			ileft -= todo;
-			writesl(ss->base + SS_RXFIFO, mi.addr + oi, todo);
-			oi += todo * 4;
-		}
-		if (oi == mi.length) {
-			sg_miter_next(&mi);
-			oi = 0;
+		if (ileft) {
+			sg_miter_start(&mi, areq->src, sg_nents(areq->src),
+					SG_MITER_FROM_SG | SG_MITER_ATOMIC);
+			if (pi)
+				sg_miter_skip(&mi, pi);
+			miter_err = sg_miter_next(&mi);
+			if (!miter_err || !mi.addr) {
+				dev_err_ratelimited(ss->dev, "ERROR: sg_miter return null\n");
+				err = -EINVAL;
+				goto release_ss;
+			}
+			todo = min(rx_cnt, ileft);
+			todo = min_t(size_t, todo, (mi.length - oi) / 4);
+			if (todo) {
+				ileft -= todo;
+				writesl(ss->base + SS_RXFIFO, mi.addr + oi, todo);
+				oi += todo * 4;
+			}
+			if (oi == mi.length) {
+				pi += mi.length;
+				oi = 0;
+			}
+			sg_miter_stop(&mi);
 		}
 
 		spaces = readl(ss->base + SS_FCSR);
 		rx_cnt = SS_RXFIFO_SPACES(spaces);
 		tx_cnt = SS_TXFIFO_SPACES(spaces);
 
-		todo = min3(tx_cnt, oleft, (mo.length - oo) / 4);
+		sg_miter_start(&mo, areq->dst, sg_nents(areq->dst),
+			       SG_MITER_TO_SG | SG_MITER_ATOMIC);
+		if (po)
+			sg_miter_skip(&mo, po);
+		miter_err = sg_miter_next(&mo);
+		if (!miter_err || !mo.addr) {
+			dev_err_ratelimited(ss->dev, "ERROR: sg_miter return null\n");
+			err = -EINVAL;
+			goto release_ss;
+		}
+		todo = min(tx_cnt, oleft);
+		todo = min_t(size_t, todo, (mo.length - oo) / 4);
 		if (todo) {
 			oleft -= todo;
 			readsl(ss->base + SS_TXFIFO, mo.addr + oo, todo);
 			oo += todo * 4;
 		}
 		if (oo == mo.length) {
-			sg_miter_next(&mo);
 			oo = 0;
+			po += mo.length;
 		}
+		sg_miter_stop(&mo);
 	} while (oleft);
 
 	if (areq->iv) {
@@ -107,8 +124,6 @@
 	}
 
 release_ss:
-	sg_miter_stop(&mi);
-	sg_miter_stop(&mo);
 	writel(0, ss->base + SS_CTL);
 	spin_unlock_irqrestore(&ss->slock, flags);
 	return err;
@@ -162,12 +177,14 @@
 	unsigned int oleft = areq->cryptlen;
 	unsigned int todo;
 	struct sg_mapping_iter mi, mo;
+	unsigned long pi = 0, po = 0; /* progress for in and out */
+	bool miter_err;
 	unsigned int oi, oo;	/* offset for in and out */
 	unsigned int ob = 0;	/* offset in buf */
 	unsigned int obo = 0;	/* offset in bufo*/
 	unsigned int obl = 0;	/* length of data in bufo */
 	unsigned long flags;
-	bool need_fallback;
+	bool need_fallback = false;
 
 	if (!areq->cryptlen)
 		return 0;
@@ -186,12 +203,12 @@
 	 * we can use the SS optimized function
 	 */
 	while (in_sg && no_chunk == 1) {
-		if (in_sg->length % 4)
+		if ((in_sg->length | in_sg->offset) & 3u)
 			no_chunk = 0;
 		in_sg = sg_next(in_sg);
 	}
 	while (out_sg && no_chunk == 1) {
-		if (out_sg->length % 4)
+		if ((out_sg->length | out_sg->offset) & 3u)
 			no_chunk = 0;
 		out_sg = sg_next(out_sg);
 	}
@@ -204,28 +221,17 @@
 
 	spin_lock_irqsave(&ss->slock, flags);
 
-	for (i = 0; i < op->keylen; i += 4)
-		writel(*(op->key + i / 4), ss->base + SS_KEY0 + i);
+	for (i = 0; i < op->keylen / 4; i++)
+		writesl(ss->base + SS_KEY0 + i * 4, &op->key[i], 1);
 
 	if (areq->iv) {
 		for (i = 0; i < 4 && i < ivsize / 4; i++) {
 			v = *(u32 *)(areq->iv + i * 4);
-			writel(v, ss->base + SS_IV0 + i * 4);
+			writesl(ss->base + SS_IV0 + i * 4, &v, 1);
 		}
 	}
 	writel(mode, ss->base + SS_CTL);
 
-	sg_miter_start(&mi, areq->src, sg_nents(areq->src),
-		       SG_MITER_FROM_SG | SG_MITER_ATOMIC);
-	sg_miter_start(&mo, areq->dst, sg_nents(areq->dst),
-		       SG_MITER_TO_SG | SG_MITER_ATOMIC);
-	sg_miter_next(&mi);
-	sg_miter_next(&mo);
-	if (!mi.addr || !mo.addr) {
-		dev_err_ratelimited(ss->dev, "ERROR: sg_miter return null\n");
-		err = -EINVAL;
-		goto release_ss;
-	}
 	ileft = areq->cryptlen;
 	oleft = areq->cryptlen;
 	oi = 0;
@@ -233,13 +239,22 @@
 
 	while (oleft) {
 		if (ileft) {
-			char buf[4 * SS_RX_MAX];/* buffer for linearize SG src */
-
+			sg_miter_start(&mi, areq->src, sg_nents(areq->src),
+				       SG_MITER_FROM_SG | SG_MITER_ATOMIC);
+			if (pi)
+				sg_miter_skip(&mi, pi);
+			miter_err = sg_miter_next(&mi);
+			if (!miter_err || !mi.addr) {
+				dev_err_ratelimited(ss->dev, "ERROR: sg_miter return null\n");
+				err = -EINVAL;
+				goto release_ss;
+			}
 			/*
 			 * todo is the number of consecutive 4byte word that we
 			 * can read from current SG
 			 */
-			todo = min3(rx_cnt, ileft / 4, (mi.length - oi) / 4);
+			todo = min(rx_cnt, ileft / 4);
+			todo = min_t(size_t, todo, (mi.length - oi) / 4);
 			if (todo && !ob) {
 				writesl(ss->base + SS_RXFIFO, mi.addr + oi,
 					todo);
@@ -253,52 +268,59 @@
 				 * we need to be able to write all buf in one
 				 * pass, so it is why we min() with rx_cnt
 				 */
-				todo = min3(rx_cnt * 4 - ob, ileft,
-					    mi.length - oi);
-				memcpy(buf + ob, mi.addr + oi, todo);
+				todo = min(rx_cnt * 4 - ob, ileft);
+				todo = min_t(size_t, todo, mi.length - oi);
+				memcpy(ss->buf + ob, mi.addr + oi, todo);
 				ileft -= todo;
 				oi += todo;
 				ob += todo;
 				if (!(ob % 4)) {
-					writesl(ss->base + SS_RXFIFO, buf,
+					writesl(ss->base + SS_RXFIFO, ss->buf,
 						ob / 4);
 					ob = 0;
 				}
 			}
 			if (oi == mi.length) {
-				sg_miter_next(&mi);
+				pi += mi.length;
 				oi = 0;
 			}
+			sg_miter_stop(&mi);
 		}
 
 		spaces = readl(ss->base + SS_FCSR);
 		rx_cnt = SS_RXFIFO_SPACES(spaces);
 		tx_cnt = SS_TXFIFO_SPACES(spaces);
-		dev_dbg(ss->dev, "%x %u/%u %u/%u cnt=%u %u/%u %u/%u cnt=%u %u\n",
-			mode,
-			oi, mi.length, ileft, areq->cryptlen, rx_cnt,
-			oo, mo.length, oleft, areq->cryptlen, tx_cnt, ob);
 
 		if (!tx_cnt)
 			continue;
+		sg_miter_start(&mo, areq->dst, sg_nents(areq->dst),
+			       SG_MITER_TO_SG | SG_MITER_ATOMIC);
+		if (po)
+			sg_miter_skip(&mo, po);
+		miter_err = sg_miter_next(&mo);
+		if (!miter_err || !mo.addr) {
+			dev_err_ratelimited(ss->dev, "ERROR: sg_miter return null\n");
+			err = -EINVAL;
+			goto release_ss;
+		}
 		/* todo in 4bytes word */
-		todo = min3(tx_cnt, oleft / 4, (mo.length - oo) / 4);
+		todo = min(tx_cnt, oleft / 4);
+		todo = min_t(size_t, todo, (mo.length - oo) / 4);
+
 		if (todo) {
 			readsl(ss->base + SS_TXFIFO, mo.addr + oo, todo);
 			oleft -= todo * 4;
 			oo += todo * 4;
 			if (oo == mo.length) {
-				sg_miter_next(&mo);
+				po += mo.length;
 				oo = 0;
 			}
 		} else {
-			char bufo[4 * SS_TX_MAX]; /* buffer for linearize SG dst */
-
 			/*
 			 * read obl bytes in bufo, we read at maximum for
 			 * emptying the device
 			 */
-			readsl(ss->base + SS_TXFIFO, bufo, tx_cnt);
+			readsl(ss->base + SS_TXFIFO, ss->bufo, tx_cnt);
 			obl = tx_cnt * 4;
 			obo = 0;
 			do {
@@ -308,18 +330,21 @@
 				 * no more than remaining buffer
 				 * no need to test against oleft
 				 */
-				todo = min(mo.length - oo, obl - obo);
-				memcpy(mo.addr + oo, bufo + obo, todo);
+				todo = min_t(size_t,
+					     mo.length - oo, obl - obo);
+				memcpy(mo.addr + oo, ss->bufo + obo, todo);
 				oleft -= todo;
 				obo += todo;
 				oo += todo;
 				if (oo == mo.length) {
+					po += mo.length;
 					sg_miter_next(&mo);
 					oo = 0;
 				}
 			} while (obo < obl);
 			/* bufo must be fully used here */
 		}
+		sg_miter_stop(&mo);
 	}
 	if (areq->iv) {
 		for (i = 0; i < 4 && i < ivsize / 4; i++) {
@@ -329,8 +354,6 @@
 	}
 
 release_ss:
-	sg_miter_stop(&mi);
-	sg_miter_stop(&mo);
 	writel(0, ss->base + SS_CTL);
 	spin_unlock_irqrestore(&ss->slock, flags);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/sunxi-ss/sun4i-ss-hash.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/sunxi-ss/sun4i-ss-hash.c
@@ -175,7 +175,7 @@
 	 */
 	unsigned int i = 0, end, fill, min_fill, nwait, nbw = 0, j = 0, todo;
 	unsigned int in_i = 0;
-	u32 spaces, rx_cnt = SS_RX_DEFAULT, bf[32] = {0}, wb = 0, v, ivmode = 0;
+	u32 spaces, rx_cnt = SS_RX_DEFAULT, bf[32] = {0}, v, ivmode = 0;
 	struct sun4i_req_ctx *op = ahash_request_ctx(areq);
 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
 	struct sun4i_tfm_ctx *tfmctx = crypto_ahash_ctx(tfm);
@@ -184,6 +184,7 @@
 	struct sg_mapping_iter mi;
 	int in_r, err = 0;
 	size_t copied = 0;
+	__le32 wb = 0;
 
 	dev_dbg(ss->dev, "%s %s bc=%llu len=%u mode=%x wl=%u h0=%0x",
 		__func__, crypto_tfm_alg_name(areq->base.tfm),
@@ -272,8 +273,8 @@
 			 */
 			while (op->len < 64 && i < end) {
 				/* how many bytes we can read from current SG */
-				in_r = min3(mi.length - in_i, end - i,
-					    64 - op->len);
+				in_r = min(end - i, 64 - op->len);
+				in_r = min_t(size_t, mi.length - in_i, in_r);
 				memcpy(op->buf + op->len, mi.addr + in_i, in_r);
 				op->len += in_r;
 				i += in_r;
@@ -293,8 +294,8 @@
 		}
 		if (mi.length - in_i > 3 && i < end) {
 			/* how many bytes we can read from current SG */
-			in_r = min3(mi.length - in_i, areq->nbytes - i,
-				    ((mi.length - in_i) / 4) * 4);
+			in_r = min_t(size_t, mi.length - in_i, areq->nbytes - i);
+			in_r = min_t(size_t, ((mi.length - in_i) / 4) * 4, in_r);
 			/* how many bytes we can write in the device*/
 			todo = min3((u32)(end - i) / 4, rx_cnt, (u32)in_r / 4);
 			writesl(ss->base + SS_RXFIFO, mi.addr + in_i, todo);
@@ -320,8 +321,8 @@
 	if ((areq->nbytes - i) < 64) {
 		while (i < areq->nbytes && in_i < mi.length && op->len < 64) {
 			/* how many bytes we can read from current SG */
-			in_r = min3(mi.length - in_i, areq->nbytes - i,
-				    64 - op->len);
+			in_r = min(areq->nbytes - i, 64 - op->len);
+			in_r = min_t(size_t, mi.length - in_i, in_r);
 			memcpy(op->buf + op->len, mi.addr + in_i, in_r);
 			op->len += in_r;
 			i += in_r;
@@ -395,7 +396,7 @@
 
 		nbw = op->len - 4 * nwait;
 		if (nbw) {
-			wb = *(u32 *)(op->buf + nwait * 4);
+			wb = cpu_to_le32(*(u32 *)(op->buf + nwait * 4));
 			wb &= GENMASK((nbw * 8) - 1, 0);
 
 			op->byte_count += nbw;
@@ -404,7 +405,7 @@
 
 	/* write the remaining bytes of the nbw buffer */
 	wb |= ((1 << 7) << (nbw * 8));
-	bf[j++] = wb;
+	bf[j++] = le32_to_cpu(wb);
 
 	/*
 	 * number of space to pad to obtain 64o minus 8(size) minus 4 (final 1)
@@ -423,13 +424,13 @@
 
 	/* write the length of data */
 	if (op->mode == SS_OP_SHA1) {
-		__be64 bits = cpu_to_be64(op->byte_count << 3);
-		bf[j++] = lower_32_bits(bits);
-		bf[j++] = upper_32_bits(bits);
+		__be64 *bits = (__be64 *)&bf[j];
+		*bits = cpu_to_be64(op->byte_count << 3);
+		j += 2;
 	} else {
-		__le64 bits = op->byte_count << 3;
-		bf[j++] = lower_32_bits(bits);
-		bf[j++] = upper_32_bits(bits);
+		__le64 *bits = (__le64 *)&bf[j];
+		*bits = cpu_to_le64(op->byte_count << 3);
+		j += 2;
 	}
 	writesl(ss->base + SS_RXFIFO, bf, j);
 
@@ -471,7 +472,7 @@
 		}
 	} else {
 		for (i = 0; i < 4; i++) {
-			v = readl(ss->base + SS_MD0 + i * 4);
+			v = cpu_to_le32(readl(ss->base + SS_MD0 + i * 4));
 			memcpy(areq->result + i * 4, &v, 4);
 		}
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/sunxi-ss/sun4i-ss.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/sunxi-ss/sun4i-ss.h
@@ -138,6 +138,8 @@
 	struct reset_control *reset;
 	struct device *dev;
 	struct resource *res;
+	char buf[4 * SS_RX_MAX];/* buffer for linearize SG src */
+	char bufo[4 * SS_TX_MAX]; /* buffer for linearize SG dst */
 	spinlock_t slock; /* control the use of the device */
 #ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG
 	u32 seed[SS_SEED_LEN / BITS_PER_LONG];
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/talitos.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/talitos.c
@@ -460,7 +460,7 @@
 /*
  * locate current (offending) descriptor
  */
-static u32 current_desc_hdr(struct device *dev, int ch)
+static __be32 current_desc_hdr(struct device *dev, int ch)
 {
 	struct talitos_private *priv = dev_get_drvdata(dev);
 	int tail, iter;
@@ -478,7 +478,7 @@
 
 	iter = tail;
 	while (priv->chan[ch].fifo[iter].dma_desc != cur_desc &&
-	       priv->chan[ch].fifo[iter].desc->next_desc != cur_desc) {
+	       priv->chan[ch].fifo[iter].desc->next_desc != cpu_to_be32(cur_desc)) {
 		iter = (iter + 1) & (priv->fifo_len - 1);
 		if (iter == tail) {
 			dev_err(dev, "couldn't locate current descriptor\n");
@@ -486,7 +486,7 @@
 		}
 	}
 
-	if (priv->chan[ch].fifo[iter].desc->next_desc == cur_desc) {
+	if (priv->chan[ch].fifo[iter].desc->next_desc == cpu_to_be32(cur_desc)) {
 		struct talitos_edesc *edesc;
 
 		edesc = container_of(priv->chan[ch].fifo[iter].desc,
@@ -501,13 +501,13 @@
 /*
  * user diagnostics; report root cause of error based on execution unit status
  */
-static void report_eu_error(struct device *dev, int ch, u32 desc_hdr)
+static void report_eu_error(struct device *dev, int ch, __be32 desc_hdr)
 {
 	struct talitos_private *priv = dev_get_drvdata(dev);
 	int i;
 
 	if (!desc_hdr)
-		desc_hdr = in_be32(priv->chan[ch].reg + TALITOS_DESCBUF);
+		desc_hdr = cpu_to_be32(in_be32(priv->chan[ch].reg + TALITOS_DESCBUF));
 
 	switch (desc_hdr & DESC_HDR_SEL0_MASK) {
 	case DESC_HDR_SEL0_AFEU:
@@ -1097,11 +1097,12 @@
  */
 static int sg_to_link_tbl_offset(struct scatterlist *sg, int sg_count,
 				 unsigned int offset, int datalen, int elen,
-				 struct talitos_ptr *link_tbl_ptr)
+				 struct talitos_ptr *link_tbl_ptr, int align)
 {
 	int n_sg = elen ? sg_count + 1 : sg_count;
 	int count = 0;
 	int cryptlen = datalen + elen;
+	int padding = ALIGN(cryptlen, align) - cryptlen;
 
 	while (cryptlen && sg && n_sg--) {
 		unsigned int len = sg_dma_len(sg);
@@ -1125,7 +1126,7 @@
 			offset += datalen;
 		}
 		to_talitos_ptr(link_tbl_ptr + count,
-			       sg_dma_address(sg) + offset, len, 0);
+			       sg_dma_address(sg) + offset, sg_next(sg) ? len : len + padding, 0);
 		to_talitos_ptr_ext_set(link_tbl_ptr + count, 0, 0);
 		count++;
 		cryptlen -= len;
@@ -1148,10 +1149,11 @@
 			      unsigned int len, struct talitos_edesc *edesc,
 			      struct talitos_ptr *ptr, int sg_count,
 			      unsigned int offset, int tbl_off, int elen,
-			      bool force)
+			      bool force, int align)
 {
 	struct talitos_private *priv = dev_get_drvdata(dev);
 	bool is_sec1 = has_ftr_sec1(priv);
+	int aligned_len = ALIGN(len, align);
 
 	if (!src) {
 		to_talitos_ptr(ptr, 0, 0, is_sec1);
@@ -1159,22 +1161,22 @@
 	}
 	to_talitos_ptr_ext_set(ptr, elen, is_sec1);
 	if (sg_count == 1 && !force) {
-		to_talitos_ptr(ptr, sg_dma_address(src) + offset, len, is_sec1);
+		to_talitos_ptr(ptr, sg_dma_address(src) + offset, aligned_len, is_sec1);
 		return sg_count;
 	}
 	if (is_sec1) {
-		to_talitos_ptr(ptr, edesc->dma_link_tbl + offset, len, is_sec1);
+		to_talitos_ptr(ptr, edesc->dma_link_tbl + offset, aligned_len, is_sec1);
 		return sg_count;
 	}
 	sg_count = sg_to_link_tbl_offset(src, sg_count, offset, len, elen,
-					 &edesc->link_tbl[tbl_off]);
+					 &edesc->link_tbl[tbl_off], align);
 	if (sg_count == 1 && !force) {
 		/* Only one segment now, so no link tbl needed*/
 		copy_talitos_ptr(ptr, &edesc->link_tbl[tbl_off], is_sec1);
 		return sg_count;
 	}
 	to_talitos_ptr(ptr, edesc->dma_link_tbl +
-			    tbl_off * sizeof(struct talitos_ptr), len, is_sec1);
+			    tbl_off * sizeof(struct talitos_ptr), aligned_len, is_sec1);
 	to_talitos_ptr_ext_or(ptr, DESC_PTR_LNKTBL_JUMP, is_sec1);
 
 	return sg_count;
@@ -1186,7 +1188,7 @@
 			  unsigned int offset, int tbl_off)
 {
 	return talitos_sg_map_ext(dev, src, len, edesc, ptr, sg_count, offset,
-				  tbl_off, 0, false);
+				  tbl_off, 0, false, 1);
 }
 
 /*
@@ -1255,7 +1257,7 @@
 
 	ret = talitos_sg_map_ext(dev, areq->src, cryptlen, edesc, &desc->ptr[4],
 				 sg_count, areq->assoclen, tbl_off, elen,
-				 false);
+				 false, 1);
 
 	if (ret > 1) {
 		tbl_off += ret;
@@ -1275,7 +1277,7 @@
 		elen = 0;
 	ret = talitos_sg_map_ext(dev, areq->dst, cryptlen, edesc, &desc->ptr[5],
 				 sg_count, areq->assoclen, tbl_off, elen,
-				 is_ipsec_esp && !encrypt);
+				 is_ipsec_esp && !encrypt, 1);
 	tbl_off += ret;
 
 	if (!encrypt && is_ipsec_esp) {
@@ -1583,6 +1585,8 @@
 	bool sync_needed = false;
 	struct talitos_private *priv = dev_get_drvdata(dev);
 	bool is_sec1 = has_ftr_sec1(priv);
+	bool is_ctr = (desc->hdr & DESC_HDR_SEL0_MASK) == DESC_HDR_SEL0_AESU &&
+		      (desc->hdr & DESC_HDR_MODE0_AESU_MASK) == DESC_HDR_MODE0_AESU_CTR;
 
 	/* first DWORD empty */
 
@@ -1603,8 +1607,8 @@
 	/*
 	 * cipher in
 	 */
-	sg_count = talitos_sg_map(dev, areq->src, cryptlen, edesc,
-				  &desc->ptr[3], sg_count, 0, 0);
+	sg_count = talitos_sg_map_ext(dev, areq->src, cryptlen, edesc, &desc->ptr[3],
+				      sg_count, 0, 0, 0, false, is_ctr ? 16 : 1);
 	if (sg_count > 1)
 		sync_needed = true;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/talitos.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/talitos.h
@@ -344,6 +344,7 @@
 
 /* primary execution unit mode (MODE0) and derivatives */
 #define	DESC_HDR_MODE0_ENCRYPT		cpu_to_be32(0x00100000)
+#define	DESC_HDR_MODE0_AESU_MASK	cpu_to_be32(0x00600000)
 #define	DESC_HDR_MODE0_AESU_CBC		cpu_to_be32(0x00200000)
 #define	DESC_HDR_MODE0_AESU_CTR		cpu_to_be32(0x00600000)
 #define	DESC_HDR_MODE0_DEU_CBC		cpu_to_be32(0x00400000)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/ux500/hash/hash_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/ux500/hash/hash_core.c
@@ -1009,6 +1009,7 @@
 			goto out;
 		}
 	} else if (req->nbytes == 0 && ctx->keylen > 0) {
+		ret = -EPERM;
 		dev_err(device_data->dev, "%s: Empty message with keylength > 0, NOT supported\n",
 			__func__);
 		goto out;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/virtio/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/virtio/Kconfig
@@ -5,7 +5,6 @@
 	select CRYPTO_AEAD
 	select CRYPTO_BLKCIPHER
 	select CRYPTO_ENGINE
-	default m
 	help
 	  This driver provides support for virtio crypto device. If you
 	  choose 'M' here, this module will be called virtio_crypto.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/virtio/virtio_crypto_algs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/virtio/virtio_crypto_algs.c
@@ -105,8 +105,6 @@
 		*alg = VIRTIO_CRYPTO_CIPHER_AES_CBC;
 		break;
 	default:
-		pr_err("virtio_crypto: Unsupported key length: %d\n",
-			key_len);
 		return -EINVAL;
 	}
 	return 0;
@@ -355,13 +353,18 @@
 	int err;
 	unsigned long flags;
 	struct scatterlist outhdr, iv_sg, status_sg, **sgs;
-	int i;
 	u64 dst_len;
 	unsigned int num_out = 0, num_in = 0;
 	int sg_total;
 	uint8_t *iv;
+	struct scatterlist *sg;
 
 	src_nents = sg_nents_for_len(req->src, req->nbytes);
+	if (src_nents < 0) {
+		pr_err("Invalid number of src SG.\n");
+		return src_nents;
+	}
+
 	dst_nents = sg_nents(req->dst);
 
 	pr_debug("virtio_crypto: Number of sgs (src_nents: %d, dst_nents: %d)\n",
@@ -407,6 +410,7 @@
 		goto free;
 	}
 
+	dst_len = min_t(unsigned int, req->nbytes, dst_len);
 	pr_debug("virtio_crypto: src_len: %u, dst_len: %llu\n",
 			req->nbytes, dst_len);
 
@@ -437,17 +441,22 @@
 		goto free;
 	}
 	memcpy(iv, req->info, ivsize);
+	if (!vc_sym_req->encrypt)
+		scatterwalk_map_and_copy(req->info, req->src,
+					 req->nbytes - AES_BLOCK_SIZE,
+					 AES_BLOCK_SIZE, 0);
+
 	sg_init_one(&iv_sg, iv, ivsize);
 	sgs[num_out++] = &iv_sg;
 	vc_sym_req->iv = iv;
 
 	/* Source data */
-	for (i = 0; i < src_nents; i++)
-		sgs[num_out++] = &req->src[i];
+	for (sg = req->src; src_nents; sg = sg_next(sg), src_nents--)
+		sgs[num_out++] = sg;
 
 	/* Destination data */
-	for (i = 0; i < dst_nents; i++)
-		sgs[num_out + num_in++] = &req->dst[i];
+	for (sg = req->dst; sg; sg = sg_next(sg))
+		sgs[num_out + num_in++] = sg;
 
 	/* Status */
 	sg_init_one(&status_sg, &vc_req->status, sizeof(vc_req->status));
@@ -484,6 +493,11 @@
 	/* Use the first data virtqueue as default */
 	struct data_queue *data_vq = &vcrypto->data_vq[0];
 
+	if (!req->nbytes)
+		return 0;
+	if (req->nbytes % AES_BLOCK_SIZE)
+		return -EINVAL;
+
 	vc_req->dataq = data_vq;
 	vc_req->alg_cb = virtio_crypto_dataq_sym_callback;
 	vc_sym_req->ablkcipher_ctx = ctx;
@@ -504,6 +518,11 @@
 	/* Use the first data virtqueue as default */
 	struct data_queue *data_vq = &vcrypto->data_vq[0];
 
+	if (!req->nbytes)
+		return 0;
+	if (req->nbytes % AES_BLOCK_SIZE)
+		return -EINVAL;
+
 	vc_req->dataq = data_vq;
 	vc_req->alg_cb = virtio_crypto_dataq_sym_callback;
 	vc_sym_req->ablkcipher_ctx = ctx;
@@ -563,10 +582,15 @@
 	struct ablkcipher_request *req,
 	int err)
 {
-	crypto_finalize_ablkcipher_request(vc_sym_req->base.dataq->engine,
-					   req, err);
+	if (vc_sym_req->encrypt)
+		scatterwalk_map_and_copy(req->info, req->dst,
+					 req->nbytes - AES_BLOCK_SIZE,
+					 AES_BLOCK_SIZE, 0);
 	kzfree(vc_sym_req->iv);
 	virtcrypto_clear_request(&vc_sym_req->base);
+
+	crypto_finalize_ablkcipher_request(vc_sym_req->base.dataq->engine,
+					   req, err);
 }
 
 static struct virtio_crypto_algo virtio_crypto_algs[] = { {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/virtio/virtio_crypto_common.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/virtio/virtio_crypto_common.h
@@ -10,6 +10,7 @@
 #include <linux/virtio.h>
 #include <linux/crypto.h>
 #include <linux/spinlock.h>
+#include <linux/interrupt.h>
 #include <crypto/aead.h>
 #include <crypto/aes.h>
 #include <crypto/engine.h>
@@ -27,6 +28,7 @@
 	char name[32];
 
 	struct crypto_engine *engine;
+	struct tasklet_struct done_task;
 };
 
 struct virtio_crypto {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/virtio/virtio_crypto_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/virtio/virtio_crypto_core.c
@@ -22,27 +22,28 @@
 	}
 }
 
-static void virtcrypto_dataq_callback(struct virtqueue *vq)
+static void virtcrypto_done_task(unsigned long data)
 {
-	struct virtio_crypto *vcrypto = vq->vdev->priv;
+	struct data_queue *data_vq = (struct data_queue *)data;
+	struct virtqueue *vq = data_vq->vq;
 	struct virtio_crypto_request *vc_req;
-	unsigned long flags;
 	unsigned int len;
-	unsigned int qid = vq->index;
 
-	spin_lock_irqsave(&vcrypto->data_vq[qid].lock, flags);
 	do {
 		virtqueue_disable_cb(vq);
 		while ((vc_req = virtqueue_get_buf(vq, &len)) != NULL) {
-			spin_unlock_irqrestore(
-				&vcrypto->data_vq[qid].lock, flags);
 			if (vc_req->alg_cb)
 				vc_req->alg_cb(vc_req, len);
-			spin_lock_irqsave(
-				&vcrypto->data_vq[qid].lock, flags);
 		}
 	} while (!virtqueue_enable_cb(vq));
-	spin_unlock_irqrestore(&vcrypto->data_vq[qid].lock, flags);
+}
+
+static void virtcrypto_dataq_callback(struct virtqueue *vq)
+{
+	struct virtio_crypto *vcrypto = vq->vdev->priv;
+	struct data_queue *dq = &vcrypto->data_vq[vq->index];
+
+	tasklet_schedule(&dq->done_task);
 }
 
 static int virtcrypto_find_vqs(struct virtio_crypto *vi)
@@ -99,6 +100,8 @@
 			ret = -ENOMEM;
 			goto err_engine;
 		}
+		tasklet_init(&vi->data_vq[i].done_task, virtcrypto_done_task,
+				(unsigned long)&vi->data_vq[i]);
 	}
 
 	kfree(names);
@@ -431,11 +434,14 @@
 static void virtcrypto_remove(struct virtio_device *vdev)
 {
 	struct virtio_crypto *vcrypto = vdev->priv;
+	int i;
 
 	dev_info(&vdev->dev, "Start virtcrypto_remove.\n");
 
 	if (virtcrypto_dev_started(vcrypto))
 		virtcrypto_dev_stop(vcrypto);
+	for (i = 0; i < vcrypto->max_data_queues; i++)
+		tasklet_kill(&vcrypto->data_vq[i].done_task);
 	vdev->config->reset(vdev);
 	virtcrypto_free_unused_reqs(vcrypto);
 	virtcrypto_clear_crypto_engines(vcrypto);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/vmx/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/vmx/Kconfig
@@ -2,7 +2,11 @@
 config CRYPTO_DEV_VMX_ENCRYPT
 	tristate "Encryption acceleration support on P8 CPU"
 	depends on CRYPTO_DEV_VMX
+	select CRYPTO_AES
+	select CRYPTO_CBC
+	select CRYPTO_CTR
 	select CRYPTO_GHASH
+	select CRYPTO_XTS
 	default m
 	help
 	  Support for VMX cryptographic acceleration instructions on Power8 CPU.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/vmx/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/vmx/Makefile
@@ -3,13 +3,13 @@
 vmx-crypto-objs := vmx.o aesp8-ppc.o ghashp8-ppc.o aes.o aes_cbc.o aes_ctr.o aes_xts.o ghash.o
 
 ifeq ($(CONFIG_CPU_LITTLE_ENDIAN),y)
-TARGET := linux-ppc64le
+override flavour := linux-ppc64le
 else
-TARGET := linux-ppc64
+override flavour := linux-ppc64
 endif
 
 quiet_cmd_perl = PERL $@
-      cmd_perl = $(PERL) $(<) $(TARGET) > $(@)
+      cmd_perl = $(PERL) $(<) $(flavour) > $(@)
 
 targets += aesp8-ppc.S ghashp8-ppc.S
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/vmx/aes_xts.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/vmx/aes_xts.c
@@ -84,6 +84,9 @@
 	u8 tweak[AES_BLOCK_SIZE];
 	int ret;
 
+	if (req->cryptlen < AES_BLOCK_SIZE)
+		return -EINVAL;
+
 	if (!crypto_simd_usable() || (req->cryptlen % XTS_BLOCK_SIZE) != 0) {
 		struct skcipher_request *subreq = skcipher_request_ctx(req);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/zynqmp-aes.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/zynqmp-aes.c
@@ -0,0 +1,336 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx ZynqMP AES Driver.
+ * Copyright (c) 2018 Xilinx Inc.
+ */
+
+#include <crypto/aes.h>
+#include <crypto/scatterwalk.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/scatterlist.h>
+#include <linux/spinlock.h>
+#include <linux/firmware/xlnx-zynqmp.h>
+
+#define ZYNQMP_AES_QUEUE_LENGTH			1
+#define ZYNQMP_AES_IV_SIZE			12
+#define ZYNQMP_AES_GCM_SIZE			16
+#define ZYNQMP_AES_KEY_SIZE			32
+
+#define ZYNQMP_AES_DECRYPT			0
+#define ZYNQMP_AES_ENCRYPT			1
+
+#define ZYNQMP_AES_KUP_KEY			0
+
+#define ZYNQMP_AES_GCM_TAG_MISMATCH_ERR		0x01
+#define ZYNQMP_AES_SIZE_ERR			0x06
+#define ZYNQMP_AES_WRONG_KEY_SRC_ERR		0x13
+#define ZYNQMP_AES_PUF_NOT_PROGRAMMED		0xE300
+
+#define ZYNQMP_AES_BLOCKSIZE			0x04
+
+struct zynqmp_aes_dev {
+	struct list_head list;
+	struct device *dev;
+	/* the lock protects queue and dev list */
+	spinlock_t lock;
+	struct crypto_queue queue;
+};
+
+struct zynqmp_aes_op {
+	struct zynqmp_aes_dev *dd;
+	void *src;
+	void *dst;
+	int len;
+	u8 key[ZYNQMP_AES_KEY_SIZE];
+	u8 *iv;
+	u32 keylen;
+	u32 keytype;
+};
+
+struct zynqmp_aes_data {
+	u64 src;
+	u64 iv;
+	u64 key;
+	u64 dst;
+	u64 size;
+	u64 optype;
+	u64 keysrc;
+};
+
+struct zynqmp_aes_drv {
+	struct list_head dev_list;
+	/* the lock protects dev list */
+	spinlock_t lock;
+};
+
+static struct zynqmp_aes_drv zynqmp_aes = {
+	.dev_list = LIST_HEAD_INIT(zynqmp_aes.dev_list),
+	.lock = __SPIN_LOCK_UNLOCKED(zynqmp_aes.lock),
+};
+
+static const struct zynqmp_eemi_ops *eemi_ops;
+
+static struct zynqmp_aes_dev *zynqmp_aes_find_dev(struct zynqmp_aes_op *ctx)
+{
+	struct zynqmp_aes_dev *aes_dd = NULL;
+	struct zynqmp_aes_dev *tmp;
+
+	spin_lock_bh(&zynqmp_aes.lock);
+	if (!ctx->dd) {
+		list_for_each_entry(tmp, &zynqmp_aes.dev_list, list) {
+			aes_dd = tmp;
+			break;
+		}
+		ctx->dd = aes_dd;
+	} else {
+		aes_dd = ctx->dd;
+	}
+	spin_unlock_bh(&zynqmp_aes.lock);
+
+	return aes_dd;
+}
+
+static int zynqmp_setkey_blk(struct crypto_tfm *tfm, const u8 *key,
+			     unsigned int len)
+{
+	struct zynqmp_aes_op *op = crypto_tfm_ctx(tfm);
+
+	op->keylen = len;
+	memcpy(op->key, key, len);
+
+	return 0;
+}
+
+static int zynqmp_setkeytype(struct crypto_tfm *tfm, const u8 *keytype,
+			     unsigned int len)
+{
+	struct zynqmp_aes_op *op = crypto_tfm_ctx(tfm);
+
+	op->keytype = (u32)(*keytype);
+
+	return 0;
+}
+
+static int zynqmp_aes_xcrypt(struct blkcipher_desc *desc,
+			     struct scatterlist *dst,
+			     struct scatterlist *src,
+			     unsigned int nbytes,
+			     unsigned int flags)
+{
+	struct zynqmp_aes_op *op = crypto_blkcipher_ctx(desc->tfm);
+	struct zynqmp_aes_dev *dd = zynqmp_aes_find_dev(op);
+	int err, ret, copy_bytes, src_data = 0, dst_data = 0;
+	dma_addr_t dma_addr, dma_addr_buf;
+	struct zynqmp_aes_data *abuf;
+	struct blkcipher_walk walk;
+	unsigned int data_size;
+	size_t dma_size;
+	char *kbuf;
+
+	if (!eemi_ops->aes)
+		return -ENOTSUPP;
+
+	if (op->keytype == ZYNQMP_AES_KUP_KEY)
+		dma_size = nbytes + ZYNQMP_AES_KEY_SIZE
+			+ ZYNQMP_AES_IV_SIZE;
+	else
+		dma_size = nbytes + ZYNQMP_AES_IV_SIZE;
+
+	kbuf = dma_alloc_coherent(dd->dev, dma_size, &dma_addr, GFP_KERNEL);
+	if (!kbuf)
+		return -ENOMEM;
+
+	abuf = dma_alloc_coherent(dd->dev, sizeof(struct zynqmp_aes_data),
+				  &dma_addr_buf, GFP_KERNEL);
+	if (!abuf) {
+		dma_free_coherent(dd->dev, dma_size, kbuf, dma_addr);
+		return -ENOMEM;
+	}
+
+	data_size = nbytes;
+	blkcipher_walk_init(&walk, dst, src, data_size);
+	err = blkcipher_walk_virt(desc, &walk);
+	op->iv = walk.iv;
+
+	while ((nbytes = walk.nbytes)) {
+		op->src = walk.src.virt.addr;
+		memcpy(kbuf + src_data, op->src, nbytes);
+		src_data = src_data + nbytes;
+		nbytes &= (ZYNQMP_AES_BLOCKSIZE - 1);
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+	memcpy(kbuf + data_size, op->iv, ZYNQMP_AES_IV_SIZE);
+	abuf->src = dma_addr;
+	abuf->dst = dma_addr;
+	abuf->iv = abuf->src + data_size;
+	abuf->size = data_size - ZYNQMP_AES_GCM_SIZE;
+	abuf->optype = flags;
+	abuf->keysrc = op->keytype;
+
+	if (op->keytype == ZYNQMP_AES_KUP_KEY) {
+		memcpy(kbuf + data_size + ZYNQMP_AES_IV_SIZE,
+		       op->key, ZYNQMP_AES_KEY_SIZE);
+
+		abuf->key = abuf->src + data_size + ZYNQMP_AES_IV_SIZE;
+	} else {
+		abuf->key = 0;
+	}
+	eemi_ops->aes(dma_addr_buf, &ret);
+
+	if (ret != 0) {
+		switch (ret) {
+		case ZYNQMP_AES_GCM_TAG_MISMATCH_ERR:
+			dev_err(dd->dev, "ERROR: Gcm Tag mismatch\n\r");
+			break;
+		case ZYNQMP_AES_SIZE_ERR:
+			dev_err(dd->dev, "ERROR : Non word aligned data\n\r");
+			break;
+		case ZYNQMP_AES_WRONG_KEY_SRC_ERR:
+			dev_err(dd->dev, "ERROR: Wrong KeySrc, enable secure mode\n\r");
+			break;
+		case ZYNQMP_AES_PUF_NOT_PROGRAMMED:
+			dev_err(dd->dev, "ERROR: PUF is not registered\r\n");
+			break;
+		default:
+			dev_err(dd->dev, "ERROR: Invalid");
+			break;
+		}
+		goto END;
+	}
+	if (flags)
+		copy_bytes = data_size;
+	else
+		copy_bytes = data_size - ZYNQMP_AES_GCM_SIZE;
+
+	blkcipher_walk_init(&walk, dst, src, copy_bytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	while ((nbytes = walk.nbytes)) {
+		memcpy(walk.dst.virt.addr, kbuf + dst_data, nbytes);
+		dst_data = dst_data + nbytes;
+		nbytes &= (ZYNQMP_AES_BLOCKSIZE - 1);
+		err = blkcipher_walk_done(desc, &walk, nbytes);
+	}
+END:
+	dma_free_coherent(dd->dev, dma_size, kbuf, dma_addr);
+	dma_free_coherent(dd->dev, sizeof(struct zynqmp_aes_data),
+			  abuf, dma_addr_buf);
+	return err;
+}
+
+static int zynqmp_aes_decrypt(struct blkcipher_desc *desc,
+			      struct scatterlist *dst,
+			      struct scatterlist *src,
+			      unsigned int nbytes)
+{
+	return zynqmp_aes_xcrypt(desc, dst, src, nbytes, ZYNQMP_AES_DECRYPT);
+}
+
+static int zynqmp_aes_encrypt(struct blkcipher_desc *desc,
+			      struct scatterlist *dst,
+			      struct scatterlist *src,
+			      unsigned int nbytes)
+{
+	return zynqmp_aes_xcrypt(desc, dst, src, nbytes, ZYNQMP_AES_ENCRYPT);
+}
+
+static struct crypto_alg zynqmp_alg = {
+	.cra_name		=	"xilinx-zynqmp-aes",
+	.cra_driver_name	=	"zynqmp-aes",
+	.cra_priority		=	400,
+	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER |
+					CRYPTO_ALG_KERN_DRIVER_ONLY,
+	.cra_blocksize		=	ZYNQMP_AES_BLOCKSIZE,
+	.cra_ctxsize		=	sizeof(struct zynqmp_aes_op),
+	.cra_alignmask		=	15,
+	.cra_type		=	&crypto_blkcipher_type,
+	.cra_module		=	THIS_MODULE,
+	.cra_u			=	{
+	.blkcipher	=	{
+			.min_keysize	=	0,
+			.max_keysize	=	ZYNQMP_AES_KEY_SIZE,
+			.setkey		=	zynqmp_setkey_blk,
+			.setkeytype	=	zynqmp_setkeytype,
+			.encrypt	=	zynqmp_aes_encrypt,
+			.decrypt	=	zynqmp_aes_decrypt,
+			.ivsize		=	ZYNQMP_AES_IV_SIZE,
+		}
+	}
+};
+
+static const struct of_device_id zynqmp_aes_dt_ids[] = {
+	{ .compatible = "xlnx,zynqmp-aes" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, zynqmp_aes_dt_ids);
+
+static int zynqmp_aes_probe(struct platform_device *pdev)
+{
+	struct zynqmp_aes_dev *aes_dd;
+	struct device *dev = &pdev->dev;
+	int ret;
+
+	eemi_ops = zynqmp_pm_get_eemi_ops();
+	if (IS_ERR(eemi_ops))
+		return PTR_ERR(eemi_ops);
+
+	aes_dd = devm_kzalloc(dev, sizeof(*aes_dd), GFP_KERNEL);
+	if (!aes_dd)
+		return -ENOMEM;
+
+	aes_dd->dev = dev;
+	platform_set_drvdata(pdev, aes_dd);
+
+	ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
+	if (ret < 0) {
+		dev_err(dev, "no usable DMA configuration");
+		return ret;
+	}
+
+	INIT_LIST_HEAD(&aes_dd->list);
+	crypto_init_queue(&aes_dd->queue, ZYNQMP_AES_QUEUE_LENGTH);
+	list_add_tail(&aes_dd->list, &zynqmp_aes.dev_list);
+
+	ret = crypto_register_alg(&zynqmp_alg);
+	if (ret)
+		goto err_algs;
+
+	dev_info(dev, "AES Successfully Registered\n");
+	return 0;
+
+err_algs:
+	list_del(&aes_dd->list);
+	dev_err(dev, "initialization failed.\n");
+
+	return ret;
+}
+
+static int zynqmp_aes_remove(struct platform_device *pdev)
+{
+	struct zynqmp_aes_dev *aes_dd;
+
+	aes_dd = platform_get_drvdata(pdev);
+	if (!aes_dd)
+		return -ENODEV;
+	list_del(&aes_dd->list);
+	crypto_unregister_alg(&zynqmp_alg);
+	return 0;
+}
+
+static struct platform_driver xilinx_aes_driver = {
+	.probe = zynqmp_aes_probe,
+	.remove = zynqmp_aes_remove,
+	.driver = {
+		.name = "zynqmp_aes",
+		.of_match_table = of_match_ptr(zynqmp_aes_dt_ids),
+	},
+};
+
+module_platform_driver(xilinx_aes_driver);
+
+MODULE_DESCRIPTION("Xilinx ZynqMP AES hw acceleration support.");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Nava kishore Manne <nava.manne@xilinx.com>");
+MODULE_AUTHOR("Kalyani Akula <kalyani.akula@xilinx.com>");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/zynqmp-rsa.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/zynqmp-rsa.c
@@ -0,0 +1,238 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017 Xilinx, Inc.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/crypto.h>
+#include <linux/spinlock.h>
+#include <crypto/algapi.h>
+#include <crypto/aes.h>
+#include <linux/io.h>
+#include <linux/device.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/scatterlist.h>
+#include <crypto/scatterwalk.h>
+#include <linux/firmware/xlnx-zynqmp.h>
+
+#define ZYNQMP_RSA_QUEUE_LENGTH	1
+#define ZYNQMP_RSA_MAX_KEY_SIZE	1024
+#define ZYNQMP_RSA_BLOCKSIZE	64
+
+struct zynqmp_rsa_dev;
+
+struct zynqmp_rsa_op {
+	struct zynqmp_rsa_dev    *dd;
+	void *src;
+	void *dst;
+	int len;
+	u8 key[ZYNQMP_RSA_MAX_KEY_SIZE];
+	u8 *iv;
+	u32 keylen;
+};
+
+struct zynqmp_rsa_dev {
+	struct list_head        list;
+	struct device           *dev;
+	/* the lock protects queue and dev list*/
+	spinlock_t              lock;
+	struct crypto_queue     queue;
+};
+
+struct zynqmp_rsa_drv {
+	struct list_head        dev_list;
+	/* the lock protects queue and dev list*/
+	spinlock_t              lock;
+};
+
+static struct zynqmp_rsa_drv zynqmp_rsa = {
+	.dev_list = LIST_HEAD_INIT(zynqmp_rsa.dev_list),
+	.lock = __SPIN_LOCK_UNLOCKED(zynqmp_rsa.lock),
+};
+
+static const struct zynqmp_eemi_ops *eemi_ops;
+
+static struct zynqmp_rsa_dev *zynqmp_rsa_find_dev(struct zynqmp_rsa_op *ctx)
+{
+	struct zynqmp_rsa_dev *rsa_dd = NULL;
+	struct zynqmp_rsa_dev *tmp;
+
+	spin_lock_bh(&zynqmp_rsa.lock);
+	if (!ctx->dd) {
+		list_for_each_entry(tmp, &zynqmp_rsa.dev_list, list) {
+			rsa_dd = tmp;
+			break;
+		}
+		ctx->dd = rsa_dd;
+	} else {
+		rsa_dd = ctx->dd;
+	}
+	spin_unlock_bh(&zynqmp_rsa.lock);
+
+	return rsa_dd;
+}
+
+static int zynqmp_setkey_blk(struct crypto_tfm *tfm, const u8 *key,
+			     unsigned int len)
+{
+	struct zynqmp_rsa_op *op = crypto_tfm_ctx(tfm);
+
+	op->keylen = len;
+	memcpy(op->key, key, len);
+	return 0;
+}
+
+static int zynqmp_rsa_xcrypt(struct blkcipher_desc *desc,
+			     struct scatterlist *dst, struct scatterlist *src,
+			     unsigned int nbytes, unsigned int flags)
+{
+	struct zynqmp_rsa_op *op = crypto_blkcipher_ctx(desc->tfm);
+	struct zynqmp_rsa_dev *dd = zynqmp_rsa_find_dev(op);
+	int err, datasize, src_data = 0, dst_data = 0;
+	struct blkcipher_walk walk;
+	char *kbuf;
+	size_t dma_size;
+	dma_addr_t dma_addr;
+
+	if (!eemi_ops->rsa)
+		return -ENOTSUPP;
+
+	dma_size = nbytes + op->keylen;
+	kbuf = dma_alloc_coherent(dd->dev, dma_size, &dma_addr, GFP_KERNEL);
+	if (!kbuf)
+		return -ENOMEM;
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	while ((datasize = walk.nbytes)) {
+		op->src = walk.src.virt.addr;
+		memcpy(kbuf + src_data, op->src, datasize);
+		src_data = src_data + datasize;
+		err = blkcipher_walk_done(desc, &walk, 0);
+	}
+	memcpy(kbuf + nbytes, op->key, op->keylen);
+	eemi_ops->rsa(dma_addr, nbytes, flags);
+
+	blkcipher_walk_init(&walk, dst, src, nbytes);
+	err = blkcipher_walk_virt(desc, &walk);
+
+	while ((datasize = walk.nbytes)) {
+		memcpy(walk.dst.virt.addr, kbuf + dst_data, datasize);
+		dst_data = dst_data + datasize;
+		err = blkcipher_walk_done(desc, &walk, 0);
+	}
+	dma_free_coherent(dd->dev, dma_size, kbuf, dma_addr);
+	return err;
+}
+
+static int
+zynqmp_rsa_decrypt(struct blkcipher_desc *desc,
+		   struct scatterlist *dst, struct scatterlist *src,
+		   unsigned int nbytes)
+{
+	return zynqmp_rsa_xcrypt(desc, dst, src, nbytes, 0);
+}
+
+static int
+zynqmp_rsa_encrypt(struct blkcipher_desc *desc,
+		   struct scatterlist *dst, struct scatterlist *src,
+		   unsigned int nbytes)
+{
+	return zynqmp_rsa_xcrypt(desc, dst, src, nbytes, 1);
+}
+
+static struct crypto_alg zynqmp_alg = {
+	.cra_name		=	"xilinx-zynqmp-rsa",
+	.cra_driver_name	=	"zynqmp-rsa",
+	.cra_priority		=	400,
+	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER |
+					CRYPTO_ALG_KERN_DRIVER_ONLY,
+	.cra_blocksize		=	ZYNQMP_RSA_BLOCKSIZE,
+	.cra_ctxsize		=	sizeof(struct zynqmp_rsa_op),
+	.cra_alignmask		=	15,
+	.cra_type		=	&crypto_blkcipher_type,
+	.cra_module		=	THIS_MODULE,
+	.cra_u			=	{
+	.blkcipher = {
+			.min_keysize	=	0,
+			.max_keysize	=	ZYNQMP_RSA_MAX_KEY_SIZE,
+			.setkey		=	zynqmp_setkey_blk,
+			.encrypt	=	zynqmp_rsa_encrypt,
+			.decrypt	=	zynqmp_rsa_decrypt,
+			.ivsize		=	1,
+		}
+	}
+};
+
+static const struct of_device_id zynqmp_rsa_dt_ids[] = {
+	{ .compatible = "xlnx,zynqmp-rsa" },
+	{ /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, zynqmp_rsa_dt_ids);
+
+static int zynqmp_rsa_probe(struct platform_device *pdev)
+{
+	struct zynqmp_rsa_dev *rsa_dd;
+	struct device *dev = &pdev->dev;
+	int ret;
+
+	eemi_ops = zynqmp_pm_get_eemi_ops();
+	if (IS_ERR(eemi_ops))
+		return PTR_ERR(eemi_ops);
+
+	rsa_dd = devm_kzalloc(&pdev->dev, sizeof(*rsa_dd), GFP_KERNEL);
+	if (!rsa_dd)
+		return -ENOMEM;
+
+	rsa_dd->dev = dev;
+	platform_set_drvdata(pdev, rsa_dd);
+
+	ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+	if (ret < 0)
+		dev_err(dev, "no usable DMA configuration");
+
+	INIT_LIST_HEAD(&rsa_dd->list);
+	spin_lock_init(&rsa_dd->lock);
+	crypto_init_queue(&rsa_dd->queue, ZYNQMP_RSA_QUEUE_LENGTH);
+	spin_lock(&zynqmp_rsa.lock);
+	list_add_tail(&rsa_dd->list, &zynqmp_rsa.dev_list);
+	spin_unlock(&zynqmp_rsa.lock);
+
+	ret = crypto_register_alg(&zynqmp_alg);
+	if (ret)
+		goto err_algs;
+
+	return 0;
+
+err_algs:
+	spin_lock(&zynqmp_rsa.lock);
+	list_del(&rsa_dd->list);
+	spin_unlock(&zynqmp_rsa.lock);
+	dev_err(dev, "initialization failed.\n");
+	return ret;
+}
+
+static int zynqmp_rsa_remove(struct platform_device *pdev)
+{
+	crypto_unregister_alg(&zynqmp_alg);
+	return 0;
+}
+
+static struct platform_driver xilinx_rsa_driver = {
+	.probe = zynqmp_rsa_probe,
+	.remove = zynqmp_rsa_remove,
+	.driver = {
+		.name = "zynqmp_rsa",
+		.of_match_table = of_match_ptr(zynqmp_rsa_dt_ids),
+	},
+};
+
+module_platform_driver(xilinx_rsa_driver);
+
+MODULE_DESCRIPTION("ZynqMP RSA hw acceleration support.");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Nava kishore Manne <navam@xilinx.com>");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/crypto/zynqmp-sha.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/crypto/zynqmp-sha.c
@@ -0,0 +1,317 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2017 Xilinx, Inc.
+ */
+
+#include <asm/cacheflush.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
+#include <linux/of_device.h>
+#include <linux/crypto.h>
+#include <linux/cryptohash.h>
+#include <crypto/scatterwalk.h>
+#include <crypto/algapi.h>
+#include <crypto/sha.h>
+#include <crypto/hash.h>
+#include <crypto/internal/hash.h>
+#include <linux/firmware/xlnx-zynqmp.h>
+#include <linux/mutex.h>
+
+#define ZYNQMP_SHA3_INIT	1
+#define ZYNQMP_SHA3_UPDATE	2
+#define ZYNQMP_SHA3_FINAL	4
+
+#define ZYNQMP_SHA_QUEUE_LENGTH	1
+
+static const struct zynqmp_eemi_ops *eemi_ops;
+struct zynqmp_sha_dev;
+
+/*
+ * .statesize = sizeof(struct zynqmp_sha_reqctx) must be <= PAGE_SIZE / 8 as
+ * tested by the ahash_prepare_alg() function.
+ */
+struct zynqmp_sha_reqctx {
+	struct zynqmp_sha_dev	*dd;
+	unsigned long		flags;
+};
+
+struct zynqmp_sha_ctx {
+	struct zynqmp_sha_dev	*dd;
+	unsigned long		flags;
+};
+
+struct zynqmp_sha_dev {
+	struct list_head	list;
+	struct device		*dev;
+	/* the lock protects queue and dev list*/
+	spinlock_t		lock;
+	int			err;
+
+	unsigned long		flags;
+	struct crypto_queue	queue;
+	struct ahash_request	*req;
+};
+
+struct zynqmp_sha_drv {
+	struct list_head	dev_list;
+	/* the lock protects queue and dev list*/
+	spinlock_t		lock;
+	/* the hw_engine_mutex makes the driver thread-safe */
+	struct mutex		hw_engine_mutex;
+};
+
+static struct zynqmp_sha_drv zynqmp_sha = {
+	.dev_list = LIST_HEAD_INIT(zynqmp_sha.dev_list),
+	.lock = __SPIN_LOCK_UNLOCKED(zynqmp_sha.lock),
+};
+
+static int zynqmp_sha_init(struct ahash_request *req)
+{
+	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+	struct zynqmp_sha_ctx *tctx = crypto_ahash_ctx(tfm);
+	struct zynqmp_sha_reqctx *ctx = ahash_request_ctx(req);
+	struct zynqmp_sha_dev *dd = NULL;
+	struct zynqmp_sha_dev *tmp;
+	int ret;
+
+	if (!eemi_ops->sha_hash)
+		return -ENOTSUPP;
+
+	spin_lock_bh(&zynqmp_sha.lock);
+	if (!tctx->dd) {
+		list_for_each_entry(tmp, &zynqmp_sha.dev_list, list) {
+			dd = tmp;
+			break;
+		}
+		tctx->dd = dd;
+	} else {
+		dd = tctx->dd;
+	}
+	spin_unlock_bh(&zynqmp_sha.lock);
+
+	ctx->dd = dd;
+	dev_dbg(dd->dev, "init: digest size: %d\n",
+		crypto_ahash_digestsize(tfm));
+
+	ret = mutex_lock_interruptible(&zynqmp_sha.hw_engine_mutex);
+	if (ret)
+		goto end;
+
+	ret = eemi_ops->sha_hash(0, 0, ZYNQMP_SHA3_INIT);
+
+end:
+	return ret;
+}
+
+static int zynqmp_sha_update(struct ahash_request *req)
+{
+	struct zynqmp_sha_ctx *tctx = crypto_tfm_ctx(req->base.tfm);
+	struct zynqmp_sha_dev *dd = tctx->dd;
+	char *kbuf;
+	size_t dma_size = req->nbytes;
+	dma_addr_t dma_addr;
+	int ret;
+
+	if (!req->nbytes)
+		return 0;
+
+	if (!eemi_ops->sha_hash)
+		return -ENOTSUPP;
+
+	kbuf = dma_alloc_coherent(dd->dev, dma_size, &dma_addr, GFP_KERNEL);
+	if (!kbuf)
+		return -ENOMEM;
+
+	scatterwalk_map_and_copy(kbuf, req->src, 0, req->nbytes, 0);
+	 __flush_cache_user_range((unsigned long)kbuf,
+				  (unsigned long)kbuf + dma_size);
+	ret = eemi_ops->sha_hash(dma_addr, req->nbytes, ZYNQMP_SHA3_UPDATE);
+	if (ret) {
+		mutex_unlock(&zynqmp_sha.hw_engine_mutex);
+		goto end;
+	}
+
+	dma_free_coherent(dd->dev, dma_size, kbuf, dma_addr);
+
+end:
+	return ret;
+}
+
+static int zynqmp_sha_final(struct ahash_request *req)
+{
+	struct zynqmp_sha_ctx *tctx = crypto_tfm_ctx(req->base.tfm);
+	struct zynqmp_sha_dev *dd = tctx->dd;
+	char *kbuf;
+	size_t dma_size = SHA384_DIGEST_SIZE;
+	dma_addr_t dma_addr;
+	int ret;
+
+	if (!eemi_ops->sha_hash)
+		return -ENOTSUPP;
+
+	kbuf = dma_alloc_coherent(dd->dev, dma_size, &dma_addr, GFP_KERNEL);
+	if (!kbuf)
+		return -ENOMEM;
+
+	ret = eemi_ops->sha_hash(dma_addr, dma_size, ZYNQMP_SHA3_FINAL);
+	memcpy(req->result, kbuf, 48);
+	dma_free_coherent(dd->dev, dma_size, kbuf, dma_addr);
+
+	mutex_unlock(&zynqmp_sha.hw_engine_mutex);
+	return ret;
+}
+
+static int zynqmp_sha_finup(struct ahash_request *req)
+{
+	zynqmp_sha_update(req);
+	zynqmp_sha_final(req);
+
+	return 0;
+}
+
+static int zynqmp_sha_digest(struct ahash_request *req)
+{
+	zynqmp_sha_init(req);
+	zynqmp_sha_update(req);
+	zynqmp_sha_final(req);
+
+	return 0;
+}
+
+static int zynqmp_sha_export(struct ahash_request *req, void *out)
+{
+	const struct zynqmp_sha_reqctx *ctx = ahash_request_ctx(req);
+
+	memcpy(out, ctx, sizeof(*ctx));
+	return 0;
+}
+
+static int zynqmp_sha_import(struct ahash_request *req, const void *in)
+{
+	struct zynqmp_sha_reqctx *ctx = ahash_request_ctx(req);
+
+	memcpy(ctx, in, sizeof(*ctx));
+	return 0;
+}
+
+static int zynqmp_sha_cra_init(struct crypto_tfm *tfm)
+{
+	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
+				 sizeof(struct zynqmp_sha_reqctx));
+
+	return 0;
+}
+
+static struct ahash_alg sha3_alg = {
+	.init		= zynqmp_sha_init,
+	.update		= zynqmp_sha_update,
+	.final		= zynqmp_sha_final,
+	.finup		= zynqmp_sha_finup,
+	.digest		= zynqmp_sha_digest,
+	.export		= zynqmp_sha_export,
+	.import		= zynqmp_sha_import,
+	.halg = {
+		.digestsize	= SHA384_DIGEST_SIZE,
+		.statesize	= sizeof(struct sha256_state),
+		.base	= {
+			.cra_name		= "xilinx-keccak-384",
+			.cra_driver_name	= "zynqmp-keccak-384",
+			.cra_priority		= 300,
+			.cra_flags		= CRYPTO_ALG_ASYNC,
+			.cra_blocksize		= SHA384_BLOCK_SIZE,
+			.cra_ctxsize		= sizeof(struct zynqmp_sha_ctx),
+			.cra_alignmask		= 0,
+			.cra_module		= THIS_MODULE,
+			.cra_init		= zynqmp_sha_cra_init,
+		}
+	}
+};
+
+static const struct of_device_id zynqmp_sha_dt_ids[] = {
+	{ .compatible = "xlnx,zynqmp-keccak-384" },
+	{ /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, zynqmp_sha_dt_ids);
+
+static int zynqmp_sha_probe(struct platform_device *pdev)
+{
+	struct zynqmp_sha_dev *sha_dd;
+	struct device *dev = &pdev->dev;
+	int err;
+
+	eemi_ops = zynqmp_pm_get_eemi_ops();
+	if (IS_ERR(eemi_ops))
+		return PTR_ERR(eemi_ops);
+
+	sha_dd = devm_kzalloc(&pdev->dev, sizeof(*sha_dd), GFP_KERNEL);
+	if (!sha_dd)
+		return -ENOMEM;
+
+	sha_dd->dev = dev;
+	platform_set_drvdata(pdev, sha_dd);
+	INIT_LIST_HEAD(&sha_dd->list);
+	spin_lock_init(&sha_dd->lock);
+	mutex_init(&zynqmp_sha.hw_engine_mutex);
+	crypto_init_queue(&sha_dd->queue, ZYNQMP_SHA_QUEUE_LENGTH);
+	spin_lock(&zynqmp_sha.lock);
+	list_add_tail(&sha_dd->list, &zynqmp_sha.dev_list);
+	spin_unlock(&zynqmp_sha.lock);
+
+	err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+	if (err < 0)
+		dev_err(dev, "no usable DMA configuration");
+
+	err = crypto_register_ahash(&sha3_alg);
+	if (err)
+		goto err_algs;
+
+	return 0;
+
+err_algs:
+	spin_lock(&zynqmp_sha.lock);
+	list_del(&sha_dd->list);
+	spin_unlock(&zynqmp_sha.lock);
+	dev_err(dev, "initialization failed.\n");
+
+	return err;
+}
+
+static int zynqmp_sha_remove(struct platform_device *pdev)
+{
+	static struct zynqmp_sha_dev *sha_dd;
+
+	sha_dd = platform_get_drvdata(pdev);
+
+	if (!sha_dd)
+		return -ENODEV;
+
+	spin_lock(&zynqmp_sha.lock);
+	list_del(&sha_dd->list);
+	spin_unlock(&zynqmp_sha.lock);
+
+	crypto_unregister_ahash(&sha3_alg);
+
+	return 0;
+}
+
+static struct platform_driver zynqmp_sha_driver = {
+	.probe		= zynqmp_sha_probe,
+	.remove		= zynqmp_sha_remove,
+	.driver		= {
+		.name	= "zynqmp-keccak-384",
+		.of_match_table	= of_match_ptr(zynqmp_sha_dt_ids),
+	},
+};
+
+module_platform_driver(zynqmp_sha_driver);
+
+MODULE_DESCRIPTION("ZynqMP SHA3 hw acceleration support.");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Nava kishore Manne <navam@xilinx.com>");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dax/bus.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dax/bus.c
@@ -227,7 +227,7 @@
 
 struct dax_region *alloc_dax_region(struct device *parent, int region_id,
 		struct resource *res, int target_node, unsigned int align,
-		unsigned long pfn_flags)
+		unsigned long long pfn_flags)
 {
 	struct dax_region *dax_region;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dax/bus.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/dax/bus.h
@@ -11,7 +11,7 @@
 void dax_region_put(struct dax_region *dax_region);
 struct dax_region *alloc_dax_region(struct device *parent, int region_id,
 		struct resource *res, int target_node, unsigned int align,
-		unsigned long flags);
+		unsigned long long flags);
 
 enum dev_dax_subsys {
 	DEV_DAX_BUS,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dax/dax-private.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/dax/dax-private.h
@@ -32,7 +32,7 @@
 	struct device *dev;
 	unsigned int align;
 	struct resource res;
-	unsigned long pfn_flags;
+	unsigned long long pfn_flags;
 };
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dax/kmem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dax/kmem.c
@@ -22,6 +22,7 @@
 	resource_size_t kmem_size;
 	resource_size_t kmem_end;
 	struct resource *new_res;
+	const char *new_res_name;
 	int numa_node;
 	int rc;
 
@@ -48,11 +49,16 @@
 	kmem_size &= ~(memory_block_size_bytes() - 1);
 	kmem_end = kmem_start + kmem_size;
 
-	/* Region is permanently reserved.  Hot-remove not yet implemented. */
-	new_res = request_mem_region(kmem_start, kmem_size, dev_name(dev));
+	new_res_name = kstrdup(dev_name(dev), GFP_KERNEL);
+	if (!new_res_name)
+		return -ENOMEM;
+
+	/* Region is permanently reserved if hotremove fails. */
+	new_res = request_mem_region(kmem_start, kmem_size, new_res_name);
 	if (!new_res) {
 		dev_warn(dev, "could not reserve region [%pa-%pa]\n",
 			 &kmem_start, &kmem_end);
+		kfree(new_res_name);
 		return -EBUSY;
 	}
 
@@ -63,12 +69,12 @@
 	 * unknown to us that will break add_memory() below.
 	 */
 	new_res->flags = IORESOURCE_SYSTEM_RAM;
-	new_res->name = dev_name(dev);
 
 	rc = add_memory(numa_node, new_res->start, resource_size(new_res));
 	if (rc) {
 		release_resource(new_res);
 		kfree(new_res);
+		kfree(new_res_name);
 		return rc;
 	}
 	dev_dax->dax_kmem_res = new_res;
@@ -83,6 +89,7 @@
 	struct resource *res = dev_dax->dax_kmem_res;
 	resource_size_t kmem_start = res->start;
 	resource_size_t kmem_size = resource_size(res);
+	const char *res_name = res->name;
 	int rc;
 
 	/*
@@ -102,6 +109,7 @@
 	/* Release and free dax resources */
 	release_resource(res);
 	kfree(res);
+	kfree(res_name);
 	dev_dax->dax_kmem_res = NULL;
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dax/super.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dax/super.c
@@ -318,11 +318,15 @@
 bool dax_supported(struct dax_device *dax_dev, struct block_device *bdev,
 		int blocksize, sector_t start, sector_t len)
 {
+	if (!dax_dev)
+		return false;
+
 	if (!dax_alive(dax_dev))
 		return false;
 
 	return dax_dev->ops->dax_supported(dax_dev, bdev, blocksize, start, len);
 }
+EXPORT_SYMBOL_GPL(dax_supported);
 
 size_t dax_copy_from_iter(struct dax_device *dax_dev, pgoff_t pgoff, void *addr,
 		size_t bytes, struct iov_iter *i)
@@ -687,6 +691,7 @@
 static void dax_fs_exit(void)
 {
 	kern_unmount(dax_mnt);
+	rcu_barrier();
 	kmem_cache_destroy(dax_cache);
 }
 
@@ -716,6 +721,7 @@
 
 static void __exit dax_core_exit(void)
 {
+	dax_bus_exit();
 	unregister_chrdev_region(dax_devt, MINORMASK+1);
 	ida_destroy(&dax_minor_ida);
 	dax_fs_exit();
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/devfreq/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/devfreq/Kconfig
@@ -99,6 +99,7 @@
 		ARCH_TEGRA_210_SOC || \
 		COMPILE_TEST
 	select PM_OPP
+	depends on COMMON_CLK
 	help
 	  This adds the DEVFREQ driver for the Tegra family of SoCs.
 	  It reads ACTMON counters of memory controllers and adjusts the
@@ -117,7 +118,8 @@
 
 config ARM_RK3399_DMC_DEVFREQ
 	tristate "ARM RK3399 DMC DEVFREQ Driver"
-	depends on ARCH_ROCKCHIP
+	depends on (ARCH_ROCKCHIP && HAVE_ARM_SMCCC) || \
+		(COMPILE_TEST && HAVE_ARM_SMCCC)
 	select DEVFREQ_EVENT_ROCKCHIP_DFI
 	select DEVFREQ_GOV_SIMPLE_ONDEMAND
 	select PM_DEVFREQ_EVENT
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/devfreq/devfreq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/devfreq/devfreq.c
@@ -160,6 +160,7 @@
 	int lev, prev_lev, ret = 0;
 	unsigned long cur_time;
 
+	lockdep_assert_held(&devfreq->lock);
 	cur_time = jiffies;
 
 	/* Immediately exit if previous_freq is not initialized yet. */
@@ -318,7 +319,7 @@
 	devfreq->previous_freq = new_freq;
 
 	if (devfreq->suspend_freq)
-		devfreq->resume_freq = cur_freq;
+		devfreq->resume_freq = new_freq;
 
 	return err;
 }
@@ -550,26 +551,30 @@
 				 void *devp)
 {
 	struct devfreq *devfreq = container_of(nb, struct devfreq, nb);
-	int ret;
+	int err = -EINVAL;
 
 	mutex_lock(&devfreq->lock);
 
 	devfreq->scaling_min_freq = find_available_min_freq(devfreq);
-	if (!devfreq->scaling_min_freq) {
-		mutex_unlock(&devfreq->lock);
-		return -EINVAL;
-	}
+	if (!devfreq->scaling_min_freq)
+		goto out;
 
 	devfreq->scaling_max_freq = find_available_max_freq(devfreq);
 	if (!devfreq->scaling_max_freq) {
-		mutex_unlock(&devfreq->lock);
-		return -EINVAL;
+		devfreq->scaling_max_freq = ULONG_MAX;
+		goto out;
 	}
 
-	ret = update_devfreq(devfreq);
+	err = update_devfreq(devfreq);
+
+out:
 	mutex_unlock(&devfreq->lock);
+	if (err)
+		dev_err(devfreq->dev.parent,
+			"failed to update frequency from OPP notifier (%d)\n",
+			err);
 
-	return ret;
+	return NOTIFY_OK;
 }
 
 /**
@@ -583,11 +588,6 @@
 	struct devfreq *devfreq = to_devfreq(dev);
 
 	mutex_lock(&devfreq_list_lock);
-	if (IS_ERR(find_device_devfreq(devfreq->dev.parent))) {
-		mutex_unlock(&devfreq_list_lock);
-		dev_warn(&devfreq->dev, "releasing devfreq which doesn't exist\n");
-		return;
-	}
 	list_del(&devfreq->node);
 	mutex_unlock(&devfreq_list_lock);
 
@@ -595,6 +595,7 @@
 		devfreq->profile->exit(devfreq->dev.parent);
 
 	mutex_destroy(&devfreq->lock);
+	srcu_cleanup_notifier_head(&devfreq->transition_notifier_list);
 	kfree(devfreq);
 }
 
@@ -603,8 +604,7 @@
  * @dev:	the device to add devfreq feature.
  * @profile:	device-specific profile to run devfreq.
  * @governor_name:	name of the policy to choose frequency.
- * @data:	private data for the governor. The devfreq framework does not
- *		touch this value.
+ * @data:	devfreq driver pass to governors, governor should not change it.
  */
 struct devfreq *devfreq_add_device(struct device *dev,
 				   struct devfreq_dev_profile *profile,
@@ -613,7 +613,6 @@
 {
 	struct devfreq *devfreq;
 	struct devfreq_governor *governor;
-	static atomic_t devfreq_no = ATOMIC_INIT(-1);
 	int err = 0;
 
 	if (!dev || !profile || !governor_name) {
@@ -642,6 +641,7 @@
 	devfreq->dev.parent = dev;
 	devfreq->dev.class = devfreq_class;
 	devfreq->dev.release = devfreq_dev_release;
+	INIT_LIST_HEAD(&devfreq->node);
 	devfreq->profile = profile;
 	strncpy(devfreq->governor_name, governor_name, DEVFREQ_NAME_LEN);
 	devfreq->previous_freq = profile->initial_freq;
@@ -676,8 +676,7 @@
 	devfreq->suspend_freq = dev_pm_opp_get_suspend_opp_freq(dev);
 	atomic_set(&devfreq->suspend_count, 0);
 
-	dev_set_name(&devfreq->dev, "devfreq%d",
-				atomic_inc_return(&devfreq_no));
+	dev_set_name(&devfreq->dev, "%s", dev_name(dev));
 	err = device_register(&devfreq->dev);
 	if (err) {
 		mutex_unlock(&devfreq->lock);
@@ -789,8 +788,7 @@
  * @dev:	the device to add devfreq feature.
  * @profile:	device-specific profile to run devfreq.
  * @governor_name:	name of the policy to choose frequency.
- * @data:	private data for the governor. The devfreq framework does not
- *		touch this value.
+ * @data:	 devfreq driver pass to governors, governor should not change it.
  *
  * This function manages automatically the memory of devfreq device using device
  * resource management and simplify the free operation for memory of devfreq
@@ -903,7 +901,9 @@
 	}
 
 	if (devfreq->suspend_freq) {
+		mutex_lock(&devfreq->lock);
 		ret = devfreq_set_target(devfreq, devfreq->suspend_freq, 0);
+		mutex_unlock(&devfreq->lock);
 		if (ret)
 			return ret;
 	}
@@ -931,7 +931,9 @@
 		return 0;
 
 	if (devfreq->resume_freq) {
+		mutex_lock(&devfreq->lock);
 		ret = devfreq_set_target(devfreq, devfreq->resume_freq, 0);
+		mutex_unlock(&devfreq->lock);
 		if (ret)
 			return ret;
 	}
@@ -1111,6 +1113,14 @@
 }
 EXPORT_SYMBOL(devfreq_remove_governor);
 
+static ssize_t name_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct devfreq *devfreq = to_devfreq(dev);
+	return sprintf(buf, "%s\n", dev_name(devfreq->dev.parent));
+}
+static DEVICE_ATTR_RO(name);
+
 static ssize_t governor_show(struct device *dev,
 			     struct device_attribute *attr, char *buf)
 {
@@ -1195,7 +1205,7 @@
 	 * The devfreq with immutable governor (e.g., passive) shows
 	 * only own governor.
 	 */
-	if (df->governor->immutable) {
+	if (df->governor && df->governor->immutable) {
 		count = scnprintf(&buf[count], DEVFREQ_NAME_LEN,
 				  "%s ", df->governor_name);
 	/*
@@ -1393,47 +1403,75 @@
 			       struct device_attribute *attr, char *buf)
 {
 	struct devfreq *devfreq = to_devfreq(dev);
-	ssize_t len;
+	ssize_t len = 0;
 	int i, j;
 	unsigned int max_state = devfreq->profile->max_state;
 
+	if (max_state == 0)
+		return scnprintf(buf, PAGE_SIZE, "Not Supported.\n");
+
+	mutex_lock(&devfreq->lock);
 	if (!devfreq->stop_polling &&
-			devfreq_update_status(devfreq, devfreq->previous_freq))
+			devfreq_update_status(devfreq, devfreq->previous_freq)) {
+		mutex_unlock(&devfreq->lock);
 		return 0;
-	if (max_state == 0)
-		return sprintf(buf, "Not Supported.\n");
+	}
+	mutex_unlock(&devfreq->lock);
 
-	len = sprintf(buf, "     From  :   To\n");
-	len += sprintf(buf + len, "           :");
-	for (i = 0; i < max_state; i++)
-		len += sprintf(buf + len, "%10lu",
-				devfreq->profile->freq_table[i]);
+	len += scnprintf(buf + len, PAGE_SIZE - len, "     From  :   To\n");
+	len += scnprintf(buf + len, PAGE_SIZE - len, "           :");
+	for (i = 0; i < max_state; i++) {
+		if (len >= PAGE_SIZE - 1)
+			break;
+		len += scnprintf(buf + len, PAGE_SIZE - len, "%10lu",
+				 devfreq->profile->freq_table[i]);
+	}
+	if (len >= PAGE_SIZE - 1)
+		return PAGE_SIZE - 1;
 
-	len += sprintf(buf + len, "   time(ms)\n");
+	len += scnprintf(buf + len, PAGE_SIZE - len, "   time(ms)\n");
 
 	for (i = 0; i < max_state; i++) {
+		if (len >= PAGE_SIZE - 1)
+			break;
 		if (devfreq->profile->freq_table[i]
 					== devfreq->previous_freq) {
-			len += sprintf(buf + len, "*");
+			len += scnprintf(buf + len, PAGE_SIZE - len, "*");
 		} else {
-			len += sprintf(buf + len, " ");
+			len += scnprintf(buf + len, PAGE_SIZE - len, " ");
 		}
-		len += sprintf(buf + len, "%10lu:",
-				devfreq->profile->freq_table[i]);
-		for (j = 0; j < max_state; j++)
-			len += sprintf(buf + len, "%10u",
-				devfreq->trans_table[(i * max_state) + j]);
-		len += sprintf(buf + len, "%10u\n",
-			jiffies_to_msecs(devfreq->time_in_state[i]));
+		if (len >= PAGE_SIZE - 1)
+			break;
+
+		len += scnprintf(buf + len, PAGE_SIZE - len, "%10lu:",
+				 devfreq->profile->freq_table[i]);
+		for (j = 0; j < max_state; j++) {
+			if (len >= PAGE_SIZE - 1)
+				break;
+			len += scnprintf(buf + len, PAGE_SIZE - len, "%10u",
+					 devfreq->trans_table[(i * max_state) + j]);
+		}
+		if (len >= PAGE_SIZE - 1)
+			break;
+		len += scnprintf(buf + len, PAGE_SIZE - len, "%10u\n",
+				 jiffies_to_msecs(devfreq->time_in_state[i]));
+	}
+
+	if (len < PAGE_SIZE - 1)
+		len += scnprintf(buf + len, PAGE_SIZE - len, "Total transition : %u\n",
+				 devfreq->total_trans);
+
+	if (len >= PAGE_SIZE - 1) {
+		pr_warn_once("devfreq transition table exceeds PAGE_SIZE. Disabling\n");
+		return -EFBIG;
 	}
 
-	len += sprintf(buf + len, "Total transition : %u\n",
-					devfreq->total_trans);
 	return len;
 }
 static DEVICE_ATTR_RO(trans_stat);
 
 static struct attribute *devfreq_attrs[] = {
+	&dev_attr_name.attr,
 	&dev_attr_governor.attr,
 	&dev_attr_available_governors.attr,
 	&dev_attr_cur_freq.attr,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/devfreq/event/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/devfreq/event/Kconfig
@@ -34,7 +34,7 @@
 
 config DEVFREQ_EVENT_ROCKCHIP_DFI
 	tristate "ROCKCHIP DFI DEVFREQ event Driver"
-	depends on ARCH_ROCKCHIP
+	depends on ARCH_ROCKCHIP || COMPILE_TEST
 	help
 	  This add the devfreq-event driver for Rockchip SoC. It provides DFI
 	  (DDR Monitor Module) driver to count ddr load.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/devfreq/event/exynos-ppmu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/devfreq/event/exynos-ppmu.c
@@ -101,17 +101,22 @@
 	PPMU_EVENT(dmc1_1),
 };
 
-static int exynos_ppmu_find_ppmu_id(struct devfreq_event_dev *edev)
+static int __exynos_ppmu_find_ppmu_id(const char *edev_name)
 {
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(ppmu_events); i++)
-		if (!strcmp(edev->desc->name, ppmu_events[i].name))
+		if (!strcmp(edev_name, ppmu_events[i].name))
 			return ppmu_events[i].id;
 
 	return -EINVAL;
 }
 
+static int exynos_ppmu_find_ppmu_id(struct devfreq_event_dev *edev)
+{
+	return __exynos_ppmu_find_ppmu_id(edev->desc->name);
+}
+
 /*
  * The devfreq-event ops structure for PPMU v1.1
  */
@@ -509,15 +514,19 @@
 
 	count = of_get_child_count(events_np);
 	desc = devm_kcalloc(dev, count, sizeof(*desc), GFP_KERNEL);
-	if (!desc)
+	if (!desc) {
+		of_node_put(events_np);
 		return -ENOMEM;
+	}
 	info->num_events = count;
 
 	of_id = of_match_device(exynos_ppmu_id_match, dev);
 	if (of_id)
 		info->ppmu_type = (enum exynos_ppmu_type)of_id->data;
-	else
+	else {
+		of_node_put(events_np);
 		return -EINVAL;
+	}
 
 	j = 0;
 	for_each_child_of_node(events_np, node) {
@@ -556,13 +565,11 @@
 			 * use default if not.
 			 */
 			if (info->ppmu_type == EXYNOS_TYPE_PPMU_V2) {
-				struct devfreq_event_dev edev;
 				int id;
 				/* Not all registers take the same value for
 				 * read+write data count.
 				 */
-				edev.desc = &desc[j];
-				id = exynos_ppmu_find_ppmu_id(&edev);
+				id = __exynos_ppmu_find_ppmu_id(desc[j].name);
 
 				switch (id) {
 				case PPMU_PMNCNT0:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/devfreq/governor_userspace.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/devfreq/governor_userspace.c
@@ -21,7 +21,7 @@
 
 static int devfreq_userspace_func(struct devfreq *df, unsigned long *freq)
 {
-	struct userspace_data *data = df->data;
+	struct userspace_data *data = df->governor_data;
 
 	if (data->valid)
 		*freq = data->user_frequency;
@@ -40,7 +40,7 @@
 	int err = 0;
 
 	mutex_lock(&devfreq->lock);
-	data = devfreq->data;
+	data = devfreq->governor_data;
 
 	sscanf(buf, "%lu", &wanted);
 	data->user_frequency = wanted;
@@ -60,7 +60,7 @@
 	int err = 0;
 
 	mutex_lock(&devfreq->lock);
-	data = devfreq->data;
+	data = devfreq->governor_data;
 
 	if (data->valid)
 		err = sprintf(buf, "%lu\n", data->user_frequency);
@@ -91,7 +91,7 @@
 		goto out;
 	}
 	data->valid = false;
-	devfreq->data = data;
+	devfreq->governor_data = data;
 
 	err = sysfs_create_group(&devfreq->dev.kobj, &dev_attr_group);
 out:
@@ -107,8 +107,8 @@
 	if (devfreq->dev.kobj.sd)
 		sysfs_remove_group(&devfreq->dev.kobj, &dev_attr_group);
 
-	kfree(devfreq->data);
-	devfreq->data = NULL;
+	kfree(devfreq->governor_data);
+	devfreq->governor_data = NULL;
 }
 
 static int devfreq_userspace_handler(struct devfreq *devfreq,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/devfreq/rk3399_dmc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/devfreq/rk3399_dmc.c
@@ -95,18 +95,20 @@
 
 	mutex_lock(&dmcfreq->lock);
 
-	if (target_rate >= dmcfreq->odt_dis_freq)
-		odt_enable = true;
-
-	/*
-	 * This makes a SMC call to the TF-A to set the DDR PD (power-down)
-	 * timings and to enable or disable the ODT (on-die termination)
-	 * resistors.
-	 */
-	arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, dmcfreq->odt_pd_arg0,
-		      dmcfreq->odt_pd_arg1,
-		      ROCKCHIP_SIP_CONFIG_DRAM_SET_ODT_PD,
-		      odt_enable, 0, 0, 0, &res);
+	if (dmcfreq->regmap_pmu) {
+		if (target_rate >= dmcfreq->odt_dis_freq)
+			odt_enable = true;
+
+		/*
+		 * This makes a SMC call to the TF-A to set the DDR PD
+		 * (power-down) timings and to enable or disable the
+		 * ODT (on-die termination) resistors.
+		 */
+		arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, dmcfreq->odt_pd_arg0,
+			      dmcfreq->odt_pd_arg1,
+			      ROCKCHIP_SIP_CONFIG_DRAM_SET_ODT_PD,
+			      odt_enable, 0, 0, 0, &res);
+	}
 
 	/*
 	 * If frequency scaling from low to high, adjust voltage first.
@@ -364,16 +366,21 @@
 			if (res.a0) {
 				dev_err(dev, "Failed to set dram param: %ld\n",
 					res.a0);
-				return -EINVAL;
+				ret = -EINVAL;
+				goto err_edev;
 			}
 		}
 	}
 
 	node = of_parse_phandle(np, "rockchip,pmu", 0);
-	if (node) {
-		data->regmap_pmu = syscon_node_to_regmap(node);
-		if (IS_ERR(data->regmap_pmu))
-			return PTR_ERR(data->regmap_pmu);
+	if (!node)
+		goto no_pmu;
+
+	data->regmap_pmu = syscon_node_to_regmap(node);
+	of_node_put(node);
+	if (IS_ERR(data->regmap_pmu)) {
+		ret = PTR_ERR(data->regmap_pmu);
+		goto err_edev;
 	}
 
 	regmap_read(data->regmap_pmu, RK3399_PMUGRF_OS_REG2, &val);
@@ -391,9 +398,11 @@
 		data->odt_dis_freq = data->timing.lpddr4_odt_dis_freq;
 		break;
 	default:
-		return -EINVAL;
+		ret = -EINVAL;
+		goto err_edev;
 	};
 
+no_pmu:
 	arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, 0, 0,
 		      ROCKCHIP_SIP_CONFIG_DRAM_INIT,
 		      0, 0, 0, 0, &res);
@@ -425,7 +434,8 @@
 	 */
 	if (dev_pm_opp_of_add_table(dev)) {
 		dev_err(dev, "Invalid operating-points in device tree.\n");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto err_edev;
 	}
 
 	of_property_read_u32(np, "upthreshold",
@@ -465,6 +475,9 @@
 
 err_free_opp:
 	dev_pm_opp_of_remove_table(&pdev->dev);
+err_edev:
+	devfreq_event_disable_edev(data->edev);
+
 	return ret;
 }
 
@@ -472,6 +485,8 @@
 {
 	struct rk3399_dmcfreq *dmcfreq = dev_get_drvdata(&pdev->dev);
 
+	devfreq_event_disable_edev(dmcfreq->edev);
+
 	/*
 	 * Before remove the opp table we need to unregister the opp notifier.
 	 */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/devfreq/tegra30-devfreq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/devfreq/tegra30-devfreq.c
@@ -68,6 +68,8 @@
 
 #define KHZ							1000
 
+#define KHZ_MAX						(ULONG_MAX / KHZ)
+
 /* Assume that the bus is saturated if the utilization is 25% */
 #define BUS_SATURATION_RATIO					25
 
@@ -169,7 +171,7 @@
 };
 
 static struct tegra_actmon_emc_ratio actmon_emc_ratios[] = {
-	{ 1400000, ULONG_MAX },
+	{ 1400000,    KHZ_MAX },
 	{ 1200000,    750000 },
 	{ 1100000,    600000 },
 	{ 1000000,    500000 },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dio/dio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dio/dio.c
@@ -110,6 +110,12 @@
 
 #endif /* CONFIG_DIO_CONSTANTS */
 
+static void dio_dev_release(struct device *dev)
+{
+	struct dio_dev *ddev = container_of(dev, typeof(struct dio_dev), dev);
+	kfree(ddev);
+}
+
 int __init dio_find(int deviceid)
 {
 	/* Called to find a DIO device before the full bus scan has run.
@@ -222,6 +228,7 @@
 		dev->bus = &dio_bus;
 		dev->dev.parent = &dio_bus.dev;
 		dev->dev.bus = &dio_bus_type;
+		dev->dev.release = dio_dev_release;
 		dev->scode = scode;
 		dev->resource.start = pa;
 		dev->resource.end = pa + DIO_SIZE(scode, va);
@@ -249,6 +256,7 @@
 		if (error) {
 			pr_err("DIO: Error registering device %s\n",
 			       dev->name);
+			put_device(&dev->dev);
 			continue;
 		}
 		error = dio_create_sysfs_dev_files(dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma-buf/dma-buf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma-buf/dma-buf.c
@@ -45,46 +45,22 @@
 	size_t ret = 0;
 
 	dmabuf = dentry->d_fsdata;
-	mutex_lock(&dmabuf->lock);
+	spin_lock(&dmabuf->name_lock);
 	if (dmabuf->name)
 		ret = strlcpy(name, dmabuf->name, DMA_BUF_NAME_LEN);
-	mutex_unlock(&dmabuf->lock);
+	spin_unlock(&dmabuf->name_lock);
 
 	return dynamic_dname(dentry, buffer, buflen, "/%s:%s",
 			     dentry->d_name.name, ret > 0 ? name : "");
 }
 
-static const struct dentry_operations dma_buf_dentry_ops = {
-	.d_dname = dmabuffs_dname,
-};
-
-static struct vfsmount *dma_buf_mnt;
-
-static int dma_buf_fs_init_context(struct fs_context *fc)
-{
-	struct pseudo_fs_context *ctx;
-
-	ctx = init_pseudo(fc, DMA_BUF_MAGIC);
-	if (!ctx)
-		return -ENOMEM;
-	ctx->dops = &dma_buf_dentry_ops;
-	return 0;
-}
-
-static struct file_system_type dma_buf_fs_type = {
-	.name = "dmabuf",
-	.init_fs_context = dma_buf_fs_init_context,
-	.kill_sb = kill_anon_super,
-};
-
-static int dma_buf_release(struct inode *inode, struct file *file)
+static void dma_buf_release(struct dentry *dentry)
 {
 	struct dma_buf *dmabuf;
 
-	if (!is_dma_buf_file(file))
-		return -EINVAL;
-
-	dmabuf = file->private_data;
+	dmabuf = dentry->d_fsdata;
+	if (unlikely(!dmabuf))
+		return;
 
 	BUG_ON(dmabuf->vmapping_counter);
 
@@ -100,18 +76,55 @@
 
 	dmabuf->ops->release(dmabuf);
 
-	mutex_lock(&db_list.lock);
-	list_del(&dmabuf->list_node);
-	mutex_unlock(&db_list.lock);
-
 	if (dmabuf->resv == (struct dma_resv *)&dmabuf[1])
 		dma_resv_fini(dmabuf->resv);
 
+	WARN_ON(!list_empty(&dmabuf->attachments));
 	module_put(dmabuf->owner);
+	kfree(dmabuf->name);
 	kfree(dmabuf);
+}
+
+static int dma_buf_file_release(struct inode *inode, struct file *file)
+{
+	struct dma_buf *dmabuf;
+
+	if (!is_dma_buf_file(file))
+		return -EINVAL;
+
+	dmabuf = file->private_data;
+
+	mutex_lock(&db_list.lock);
+	list_del(&dmabuf->list_node);
+	mutex_unlock(&db_list.lock);
+
 	return 0;
 }
 
+static const struct dentry_operations dma_buf_dentry_ops = {
+	.d_dname = dmabuffs_dname,
+	.d_release = dma_buf_release,
+};
+
+static struct vfsmount *dma_buf_mnt;
+
+static int dma_buf_fs_init_context(struct fs_context *fc)
+{
+	struct pseudo_fs_context *ctx;
+
+	ctx = init_pseudo(fc, DMA_BUF_MAGIC);
+	if (!ctx)
+		return -ENOMEM;
+	ctx->dops = &dma_buf_dentry_ops;
+	return 0;
+}
+
+static struct file_system_type dma_buf_fs_type = {
+	.name = "dmabuf",
+	.init_fs_context = dma_buf_fs_init_context,
+	.kill_sb = kill_anon_super,
+};
+
 static int dma_buf_mmap_internal(struct file *file, struct vm_area_struct *vma)
 {
 	struct dma_buf *dmabuf;
@@ -340,8 +353,10 @@
 		kfree(name);
 		goto out_unlock;
 	}
+	spin_lock(&dmabuf->name_lock);
 	kfree(dmabuf->name);
 	dmabuf->name = name;
+	spin_unlock(&dmabuf->name_lock);
 
 out_unlock:
 	mutex_unlock(&dmabuf->lock);
@@ -387,7 +402,8 @@
 
 		return ret;
 
-	case DMA_BUF_SET_NAME:
+	case DMA_BUF_SET_NAME_A:
+	case DMA_BUF_SET_NAME_B:
 		return dma_buf_set_name(dmabuf, (const char __user *)arg);
 
 	default:
@@ -403,14 +419,14 @@
 	/* Don't count the temporary reference taken inside procfs seq_show */
 	seq_printf(m, "count:\t%ld\n", file_count(dmabuf->file) - 1);
 	seq_printf(m, "exp_name:\t%s\n", dmabuf->exp_name);
-	mutex_lock(&dmabuf->lock);
+	spin_lock(&dmabuf->name_lock);
 	if (dmabuf->name)
 		seq_printf(m, "name:\t%s\n", dmabuf->name);
-	mutex_unlock(&dmabuf->lock);
+	spin_unlock(&dmabuf->name_lock);
 }
 
 static const struct file_operations dma_buf_fops = {
-	.release	= dma_buf_release,
+	.release	= dma_buf_file_release,
 	.mmap		= dma_buf_mmap_internal,
 	.llseek		= dma_buf_llseek,
 	.poll		= dma_buf_poll,
@@ -539,6 +555,7 @@
 	dmabuf->size = exp_info->size;
 	dmabuf->exp_name = exp_info->exp_name;
 	dmabuf->owner = exp_info->owner;
+	spin_lock_init(&dmabuf->name_lock);
 	init_waitqueue_head(&dmabuf->poll);
 	dmabuf->cb_excl.poll = dmabuf->cb_shared.poll = &dmabuf->poll;
 	dmabuf->cb_excl.active = dmabuf->cb_shared.active = 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma-buf/dma-fence-array.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma-buf/dma-fence-array.c
@@ -103,8 +103,38 @@
 static bool dma_fence_array_signaled(struct dma_fence *fence)
 {
 	struct dma_fence_array *array = to_dma_fence_array(fence);
+	int num_pending;
+	unsigned int i;
 
-	return atomic_read(&array->num_pending) <= 0;
+	/*
+	 * We need to read num_pending before checking the enable_signal bit
+	 * to avoid racing with the enable_signaling() implementation, which
+	 * might decrement the counter, and cause a partial check.
+	 * atomic_read_acquire() pairs with atomic_dec_and_test() in
+	 * dma_fence_array_enable_signaling()
+	 *
+	 * The !--num_pending check is here to account for the any_signaled case
+	 * if we race with enable_signaling(), that means the !num_pending check
+	 * in the is_signalling_enabled branch might be outdated (num_pending
+	 * might have been decremented), but that's fine. The user will get the
+	 * right value when testing again later.
+	 */
+	num_pending = atomic_read_acquire(&array->num_pending);
+	if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &array->base.flags)) {
+		if (num_pending <= 0)
+			goto signal;
+		return false;
+	}
+
+	for (i = 0; i < array->num_fences; ++i) {
+		if (dma_fence_is_signaled(array->fences[i]) && !--num_pending)
+			goto signal;
+	}
+	return false;
+
+signal:
+	dma_fence_array_clear_pending_error(array);
+	return true;
 }
 
 static void dma_fence_array_release(struct dma_fence *fence)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma-buf/dma-fence.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma-buf/dma-fence.c
@@ -273,6 +273,30 @@
 }
 EXPORT_SYMBOL(dma_fence_free);
 
+static bool __dma_fence_enable_signaling(struct dma_fence *fence)
+{
+	bool was_set;
+
+	lockdep_assert_held(fence->lock);
+
+	was_set = test_and_set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT,
+				   &fence->flags);
+
+	if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
+		return false;
+
+	if (!was_set && fence->ops->enable_signaling) {
+		trace_dma_fence_enable_signal(fence);
+
+		if (!fence->ops->enable_signaling(fence)) {
+			dma_fence_signal_locked(fence);
+			return false;
+		}
+	}
+
+	return true;
+}
+
 /**
  * dma_fence_enable_sw_signaling - enable signaling on fence
  * @fence: the fence to enable
@@ -285,19 +309,12 @@
 {
 	unsigned long flags;
 
-	if (!test_and_set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT,
-			      &fence->flags) &&
-	    !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags) &&
-	    fence->ops->enable_signaling) {
-		trace_dma_fence_enable_signal(fence);
-
-		spin_lock_irqsave(fence->lock, flags);
-
-		if (!fence->ops->enable_signaling(fence))
-			dma_fence_signal_locked(fence);
+	if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
+		return;
 
-		spin_unlock_irqrestore(fence->lock, flags);
-	}
+	spin_lock_irqsave(fence->lock, flags);
+	__dma_fence_enable_signaling(fence);
+	spin_unlock_irqrestore(fence->lock, flags);
 }
 EXPORT_SYMBOL(dma_fence_enable_sw_signaling);
 
@@ -331,7 +348,6 @@
 {
 	unsigned long flags;
 	int ret = 0;
-	bool was_set;
 
 	if (WARN_ON(!fence || !func))
 		return -EINVAL;
@@ -343,25 +359,14 @@
 
 	spin_lock_irqsave(fence->lock, flags);
 
-	was_set = test_and_set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT,
-				   &fence->flags);
-
-	if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
-		ret = -ENOENT;
-	else if (!was_set && fence->ops->enable_signaling) {
-		trace_dma_fence_enable_signal(fence);
-
-		if (!fence->ops->enable_signaling(fence)) {
-			dma_fence_signal_locked(fence);
-			ret = -ENOENT;
-		}
-	}
-
-	if (!ret) {
+	if (__dma_fence_enable_signaling(fence)) {
 		cb->func = func;
 		list_add_tail(&cb->node, &fence->cb_list);
-	} else
+	} else {
 		INIT_LIST_HEAD(&cb->node);
+		ret = -ENOENT;
+	}
+
 	spin_unlock_irqrestore(fence->lock, flags);
 
 	return ret;
@@ -461,7 +466,6 @@
 	struct default_wait_cb cb;
 	unsigned long flags;
 	signed long ret = timeout ? timeout : 1;
-	bool was_set;
 
 	if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
 		return ret;
@@ -473,21 +477,9 @@
 		goto out;
 	}
 
-	was_set = test_and_set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT,
-				   &fence->flags);
-
-	if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))
+	if (!__dma_fence_enable_signaling(fence))
 		goto out;
 
-	if (!was_set && fence->ops->enable_signaling) {
-		trace_dma_fence_enable_signal(fence);
-
-		if (!fence->ops->enable_signaling(fence)) {
-			dma_fence_signal_locked(fence);
-			goto out;
-		}
-	}
-
 	if (!timeout) {
 		ret = 0;
 		goto out;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma-buf/dma-resv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma-buf/dma-resv.c
@@ -161,7 +161,7 @@
 			max = max(old->shared_count + num_fences,
 				  old->shared_max * 2);
 	} else {
-		max = 4;
+		max = max(4ul, roundup_pow_of_two(num_fences));
 	}
 
 	new = dma_resv_list_alloc(max);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma-buf/sw_sync.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma-buf/sw_sync.c
@@ -191,6 +191,7 @@
  */
 static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc)
 {
+	LIST_HEAD(signalled);
 	struct sync_pt *pt, *next;
 
 	trace_sync_timeline(obj);
@@ -203,21 +204,20 @@
 		if (!timeline_fence_signaled(&pt->base))
 			break;
 
-		list_del_init(&pt->link);
+		dma_fence_get(&pt->base);
+
+		list_move_tail(&pt->link, &signalled);
 		rb_erase(&pt->node, &obj->pt_tree);
 
-		/*
-		 * A signal callback may release the last reference to this
-		 * fence, causing it to be freed. That operation has to be
-		 * last to avoid a use after free inside this loop, and must
-		 * be after we remove the fence from the timeline in order to
-		 * prevent deadlocking on timeline->lock inside
-		 * timeline_fence_release().
-		 */
 		dma_fence_signal_locked(&pt->base);
 	}
 
 	spin_unlock_irq(&obj->lock);
+
+	list_for_each_entry_safe(pt, next, &signalled, link) {
+		list_del_init(&pt->link);
+		dma_fence_put(&pt->base);
+	}
 }
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma-buf/sync_debug.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma-buf/sync_debug.c
@@ -110,12 +110,12 @@
 
 	seq_printf(s, "%s: %d\n", obj->name, obj->value);
 
-	spin_lock_irq(&obj->lock);
+	spin_lock(&obj->lock); /* Caller already disabled IRQ. */
 	list_for_each(pos, &obj->pt_list) {
 		struct sync_pt *pt = container_of(pos, struct sync_pt, link);
 		sync_print_fence(s, &pt->base, false);
 	}
-	spin_unlock_irq(&obj->lock);
+	spin_unlock(&obj->lock);
 }
 
 static void sync_print_sync_file(struct seq_file *s,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma-buf/sync_file.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma-buf/sync_file.c
@@ -211,8 +211,8 @@
 					 struct sync_file *b)
 {
 	struct sync_file *sync_file;
-	struct dma_fence **fences, **nfences, **a_fences, **b_fences;
-	int i, i_a, i_b, num_fences, a_num_fences, b_num_fences;
+	struct dma_fence **fences = NULL, **nfences, **a_fences, **b_fences;
+	int i = 0, i_a, i_b, num_fences, a_num_fences, b_num_fences;
 
 	sync_file = sync_file_alloc();
 	if (!sync_file)
@@ -221,7 +221,7 @@
 	a_fences = get_fences(a, &a_num_fences);
 	b_fences = get_fences(b, &b_num_fences);
 	if (a_num_fences > INT_MAX - b_num_fences)
-		return NULL;
+		goto err;
 
 	num_fences = a_num_fences + b_num_fences;
 
@@ -236,7 +236,7 @@
 	 * If a sync_file can only be created with sync_file_merge
 	 * and sync_file_create, this is a reasonable assumption.
 	 */
-	for (i = i_a = i_b = 0; i_a < a_num_fences && i_b < b_num_fences; ) {
+	for (i_a = i_b = 0; i_a < a_num_fences && i_b < b_num_fences; ) {
 		struct dma_fence *pt_a = a_fences[i_a];
 		struct dma_fence *pt_b = b_fences[i_b];
 
@@ -278,15 +278,16 @@
 		fences = nfences;
 	}
 
-	if (sync_file_set_fence(sync_file, fences, i) < 0) {
-		kfree(fences);
+	if (sync_file_set_fence(sync_file, fences, i) < 0)
 		goto err;
-	}
 
 	strlcpy(sync_file->user_name, name, sizeof(sync_file->user_name));
 	return sync_file;
 
 err:
+	while (i)
+		dma_fence_put(fences[--i]);
+	kfree(fences);
 	fput(sync_file->file);
 	return NULL;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma-buf/udmabuf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma-buf/udmabuf.c
@@ -24,8 +24,11 @@
 {
 	struct vm_area_struct *vma = vmf->vma;
 	struct udmabuf *ubuf = vma->vm_private_data;
+	pgoff_t pgoff = vmf->pgoff;
 
-	vmf->page = ubuf->pages[vmf->pgoff];
+	if (pgoff >= ubuf->pagecount)
+		return VM_FAULT_SIGBUS;
+	vmf->page = ubuf->pages[pgoff];
 	get_page(vmf->page);
 	return 0;
 }
@@ -117,7 +120,7 @@
 };
 
 #define SEALS_WANTED (F_SEAL_SHRINK)
-#define SEALS_DENIED (F_SEAL_WRITE)
+#define SEALS_DENIED (F_SEAL_WRITE|F_SEAL_FUTURE_WRITE)
 
 static long udmabuf_create(const struct udmabuf_create_list *head,
 			   const struct udmabuf_create_item *list)
@@ -145,6 +148,10 @@
 		if (ubuf->pagecount > pglimit)
 			goto err;
 	}
+
+	if (!ubuf->pagecount)
+		goto err;
+
 	ubuf->pages = kmalloc_array(ubuf->pagecount, sizeof(*ubuf->pages),
 				    GFP_KERNEL);
 	if (!ubuf->pages) {
@@ -280,7 +287,23 @@
 
 static int __init udmabuf_dev_init(void)
 {
-	return misc_register(&udmabuf_misc);
+	int ret;
+
+	ret = misc_register(&udmabuf_misc);
+	if (ret < 0) {
+		pr_err("Could not initialize udmabuf device\n");
+		return ret;
+	}
+
+	ret = dma_coerce_mask_and_coherent(udmabuf_misc.this_device,
+					   DMA_BIT_MASK(64));
+	if (ret < 0) {
+		pr_err("Could not setup DMA mask for udmabuf device\n");
+		misc_deregister(&udmabuf_misc);
+		return ret;
+	}
+
+	return 0;
 }
 
 static void __exit udmabuf_dev_exit(void)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/Kconfig
@@ -59,6 +59,7 @@
 #devices
 config ALTERA_MSGDMA
 	tristate "Altera / Intel mSGDMA Engine"
+	depends on HAS_IOMEM
 	select DMA_ENGINE
 	help
 	  Enable support for Altera / Intel mSGDMA controller.
@@ -207,6 +208,7 @@
 config FSL_EDMA
 	tristate "Freescale eDMA engine support"
 	depends on OF
+	depends on HAS_IOMEM
 	select DMA_ENGINE
 	select DMA_VIRTUAL_CHANNELS
 	help
@@ -239,6 +241,14 @@
           the capability to offload memcpy, xor and pq computation
 	  for raid5/6.
 
+config HISI_DMA
+	tristate "HiSilicon DMA Engine support"
+	depends on ARM64 || (COMPILE_TEST && PCI_MSI)
+	select DMA_ENGINE
+	select DMA_VIRTUAL_CHANNELS
+	help
+	  Support HiSilicon Kunpeng DMA engine.
+
 config IMG_MDC_DMA
 	tristate "IMG MDC support"
 	depends on MIPS || COMPILE_TEST
@@ -267,6 +277,7 @@
 
 config INTEL_IDMA64
 	tristate "Intel integrated DMA 64-bit support"
+	depends on HAS_IOMEM
 	select DMA_ENGINE
 	select DMA_VIRTUAL_CHANNELS
 	help
@@ -275,7 +286,7 @@
 
 config INTEL_IOATDMA
 	tristate "Intel I/OAT DMA support"
-	depends on PCI && X86_64
+	depends on PCI && X86_64 && !UML
 	select DMA_ENGINE
 	select DMA_ENGINE_RAID
 	select DCA
@@ -579,16 +590,16 @@
 
 config TEGRA210_ADMA
 	tristate "NVIDIA Tegra210 ADMA support"
-	depends on (ARCH_TEGRA_210_SOC || COMPILE_TEST)
+	depends on (ARCH_TEGRA || COMPILE_TEST)
 	select DMA_ENGINE
 	select DMA_VIRTUAL_CHANNELS
 	help
-	  Support for the NVIDIA Tegra210 ADMA controller driver. The
-	  DMA controller has multiple DMA channels and is used to service
-	  various audio clients in the Tegra210 audio processing engine
-	  (APE). This DMA controller transfers data from memory to
-	  peripheral and vice versa. It does not support memory to
-	  memory data transfer.
+	  Support for the NVIDIA Tegra210/Tegra186/Tegra194/Tegra234 ADMA
+	  controller driver. The DMA controller has multiple DMA channels
+	  and is used to service various audio clients in the Tegra210
+	  audio processing engine (APE). This DMA controller transfers
+	  data from memory to peripheral and vice versa. It does not
+	  support memory to memory data transfer.
 
 config TIMB_DMA
 	tristate "Timberdale FPGA DMA support"
@@ -635,6 +646,10 @@
 	  destination address.
 	  AXI DMA engine provides high-bandwidth one dimensional direct
 	  memory access between memory and AXI4-Stream target peripherals.
+	  AXI MCDMA engine provides high-bandwidth direct memory access
+	  between memory and AXI4-Stream target peripherals. It provides
+	  the scatter gather interface with multiple channels independent
+	  configuration support.
 
 config XILINX_ZYNQMP_DMA
 	tristate "Xilinx ZynqMP DMA Engine"
@@ -643,6 +658,18 @@
 	help
 	  Enable support for Xilinx ZynqMP DMA controller.
 
+config XILINX_PS_PCIE_DMA
+	tristate "Xilinx PS PCIe DMA support"
+	depends on (PCI && X86_64 || ARM64)
+	select DMA_ENGINE
+	help
+	  Enable support for the Xilinx PS PCIe DMA engine present
+	  in recent Xilinx ZynqMP chipsets.
+
+	  Say Y here if you have such a chipset.
+
+	  If unsure, say N.
+
 config ZX_DMA
 	tristate "ZTE ZX DMA support"
 	depends on ARCH_ZX || COMPILE_TEST
@@ -669,6 +696,8 @@
 
 source "drivers/dma/ti/Kconfig"
 
+source "drivers/dma/xilinx/Kconfig"
+
 # clients
 comment "DMA Clients"
 	depends on DMA_ENGINE
@@ -695,4 +724,18 @@
 config DMA_ENGINE_RAID
 	bool
 
+config XILINX_DMATEST
+	tristate "DMA Test client for AXI DMA and MCDMA"
+	depends on XILINX_DMA
+	help
+	  Simple DMA test client. Say N unless you're debugging a
+	  DMA Device driver.
+
+config XILINX_VDMATEST
+	tristate "DMA Test client for VDMA"
+	depends on XILINX_DMA
+	help
+	  Simple xilinx VDMA test client. Say N unless you're debugging a
+	  DMA Device driver.
+
 endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/Makefile
@@ -35,6 +35,7 @@
 obj-$(CONFIG_MCF_EDMA) += mcf-edma.o fsl-edma-common.o
 obj-$(CONFIG_FSL_QDMA) += fsl-qdma.o
 obj-$(CONFIG_FSL_RAID) += fsl_raid.o
+obj-$(CONFIG_HISI_DMA) += hisi_dma.o
 obj-$(CONFIG_HSU_DMA) += hsu/
 obj-$(CONFIG_IMG_MDC_DMA) += img-mdc-dma.o
 obj-$(CONFIG_IMX_DMA) += imx-dma.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/acpi-dma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/acpi-dma.c
@@ -70,10 +70,14 @@
 
 	si = (const struct acpi_csrt_shared_info *)&grp[1];
 
-	/* Match device by MMIO and IRQ */
+	/* Match device by MMIO */
 	if (si->mmio_base_low != lower_32_bits(mem) ||
-	    si->mmio_base_high != upper_32_bits(mem) ||
-	    si->gsi_interrupt != irq)
+	    si->mmio_base_high != upper_32_bits(mem))
+		return 0;
+
+	/* Match device by Linux vIRQ */
+	ret = acpi_register_gsi(NULL, si->gsi_interrupt, si->interrupt_mode, si->interrupt_polarity);
+	if (ret != irq)
 		return 0;
 
 	dev_dbg(&adev->dev, "matches with %.4s%04X (rev %u)\n",
@@ -135,11 +139,13 @@
 		if (ret < 0) {
 			dev_warn(&adev->dev,
 				 "error in parsing resource group\n");
-			return;
+			break;
 		}
 
 		grp = (struct acpi_csrt_group *)((void *)grp + grp->length);
 	}
+
+	acpi_put_table((struct acpi_table_header *)csrt);
 }
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/at_hdmac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/at_hdmac.c
@@ -246,6 +246,8 @@
 		       ATC_SPIP_BOUNDARY(first->boundary));
 	channel_writel(atchan, DPIP, ATC_DPIP_HOLE(first->dst_hole) |
 		       ATC_DPIP_BOUNDARY(first->boundary));
+	/* Don't allow CPU to reorder channel enable. */
+	wmb();
 	dma_writel(atdma, CHER, atchan->mask);
 
 	vdbg_dump_regs(atchan);
@@ -306,7 +308,8 @@
 	struct at_desc *desc_first = atc_first_active(atchan);
 	struct at_desc *desc;
 	int ret;
-	u32 ctrla, dscr, trials;
+	u32 ctrla, dscr;
+	unsigned int i;
 
 	/*
 	 * If the cookie doesn't match to the currently running transfer then
@@ -376,7 +379,7 @@
 		dscr = channel_readl(atchan, DSCR);
 		rmb(); /* ensure DSCR is read before CTRLA */
 		ctrla = channel_readl(atchan, CTRLA);
-		for (trials = 0; trials < ATC_MAX_DSCR_TRIALS; ++trials) {
+		for (i = 0; i < ATC_MAX_DSCR_TRIALS; ++i) {
 			u32 new_dscr;
 
 			rmb(); /* ensure DSCR is read after CTRLA */
@@ -402,7 +405,7 @@
 			rmb(); /* ensure DSCR is read before CTRLA */
 			ctrla = channel_readl(atchan, CTRLA);
 		}
-		if (unlikely(trials >= ATC_MAX_DSCR_TRIALS))
+		if (unlikely(i == ATC_MAX_DSCR_TRIALS))
 			return -ETIMEDOUT;
 
 		/* for the first descriptor we can be more accurate */
@@ -550,10 +553,6 @@
 	bad_desc = atc_first_active(atchan);
 	list_del_init(&bad_desc->desc_node);
 
-	/* As we are stopped, take advantage to push queued descriptors
-	 * in active_list */
-	list_splice_init(&atchan->queue, atchan->active_list.prev);
-
 	/* Try to restart the controller */
 	if (!list_empty(&atchan->active_list))
 		atc_dostart(atchan, atc_first_active(atchan));
@@ -674,19 +673,11 @@
 	spin_lock_irqsave(&atchan->lock, flags);
 	cookie = dma_cookie_assign(tx);
 
-	if (list_empty(&atchan->active_list)) {
-		dev_vdbg(chan2dev(tx->chan), "tx_submit: started %u\n",
-				desc->txd.cookie);
-		atc_dostart(atchan, desc);
-		list_add_tail(&desc->desc_node, &atchan->active_list);
-	} else {
-		dev_vdbg(chan2dev(tx->chan), "tx_submit: queued %u\n",
-				desc->txd.cookie);
-		list_add_tail(&desc->desc_node, &atchan->queue);
-	}
-
+	list_add_tail(&desc->desc_node, &atchan->queue);
 	spin_unlock_irqrestore(&atchan->lock, flags);
 
+	dev_vdbg(chan2dev(tx->chan), "tx_submit: queued %u\n",
+		 desc->txd.cookie);
 	return cookie;
 }
 
@@ -1667,13 +1658,17 @@
 		return NULL;
 
 	dmac_pdev = of_find_device_by_node(dma_spec->np);
+	if (!dmac_pdev)
+		return NULL;
 
 	dma_cap_zero(mask);
 	dma_cap_set(DMA_SLAVE, mask);
 
-	atslave = kzalloc(sizeof(*atslave), GFP_KERNEL);
-	if (!atslave)
+	atslave = kmalloc(sizeof(*atslave), GFP_KERNEL);
+	if (!atslave) {
+		put_device(&dmac_pdev->dev);
 		return NULL;
+	}
 
 	atslave->cfg = ATC_DST_H2SEL_HW | ATC_SRC_H2SEL_HW;
 	/*
@@ -1702,8 +1697,11 @@
 	atslave->dma_dev = &dmac_pdev->dev;
 
 	chan = dma_request_channel(mask, at_dma_filter, atslave);
-	if (!chan)
+	if (!chan) {
+		put_device(&dmac_pdev->dev);
+		kfree(atslave);
 		return NULL;
+	}
 
 	atchan = to_at_dma_chan(chan);
 	atchan->per_if = dma_spec->args[0] & 0xff;
@@ -1950,7 +1948,11 @@
 	  dma_has_cap(DMA_SLAVE, atdma->dma_common.cap_mask)  ? "slave " : "",
 	  plat_dat->nr_channels);
 
-	dma_async_device_register(&atdma->dma_common);
+	err = dma_async_device_register(&atdma->dma_common);
+	if (err) {
+		dev_err(&pdev->dev, "Unable to register: %d.\n", err);
+		goto err_dma_async_device_register;
+	}
 
 	/*
 	 * Do not return an error if the dmac node is not present in order to
@@ -1970,6 +1972,7 @@
 
 err_of_dma_controller_register:
 	dma_async_device_unregister(&atdma->dma_common);
+err_dma_async_device_register:
 	dma_pool_destroy(atdma->memset_pool);
 err_memset_pool_create:
 	dma_pool_destroy(atdma->dma_desc_pool);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/at_hdmac_regs.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/at_hdmac_regs.h
@@ -164,13 +164,13 @@
 /* LLI == Linked List Item; aka DMA buffer descriptor */
 struct at_lli {
 	/* values that are not changed by hardware */
-	dma_addr_t	saddr;
-	dma_addr_t	daddr;
+	u32 saddr;
+	u32 daddr;
 	/* value that may get written back: */
-	u32		ctrla;
+	u32 ctrla;
 	/* more values that are not changed by hardware */
-	u32		ctrlb;
-	dma_addr_t	dscr;	/* chain to next lli */
+	u32 ctrlb;
+	u32 dscr;	/* chain to next lli */
 };
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/at_xdmac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/at_xdmac.c
@@ -89,6 +89,7 @@
 #define		AT_XDMAC_CNDC_NDE		(0x1 << 0)		/* Channel x Next Descriptor Enable */
 #define		AT_XDMAC_CNDC_NDSUP		(0x1 << 1)		/* Channel x Next Descriptor Source Update */
 #define		AT_XDMAC_CNDC_NDDUP		(0x1 << 2)		/* Channel x Next Descriptor Destination Update */
+#define		AT_XDMAC_CNDC_NDVIEW_MASK	GENMASK(28, 27)
 #define		AT_XDMAC_CNDC_NDVIEW_NDV0	(0x0 << 3)		/* Channel x Next Descriptor View 0 */
 #define		AT_XDMAC_CNDC_NDVIEW_NDV1	(0x1 << 3)		/* Channel x Next Descriptor View 1 */
 #define		AT_XDMAC_CNDC_NDVIEW_NDV2	(0x2 << 3)		/* Channel x Next Descriptor View 2 */
@@ -145,7 +146,7 @@
 #define		AT_XDMAC_CC_WRIP	(0x1 << 23)	/* Write in Progress (read only) */
 #define			AT_XDMAC_CC_WRIP_DONE		(0x0 << 23)
 #define			AT_XDMAC_CC_WRIP_IN_PROGRESS	(0x1 << 23)
-#define		AT_XDMAC_CC_PERID(i)	(0x7f & (i) << 24)	/* Channel Peripheral Identifier */
+#define		AT_XDMAC_CC_PERID(i)	((0x7f & (i)) << 24)	/* Channel Peripheral Identifier */
 #define AT_XDMAC_CDS_MSP	0x2C	/* Channel Data Stride Memory Set Pattern */
 #define AT_XDMAC_CSUS		0x30	/* Channel Source Microblock Stride */
 #define AT_XDMAC_CDUS		0x34	/* Channel Destination Microblock Stride */
@@ -211,6 +212,7 @@
 	int			irq;
 	struct clk		*clk;
 	u32			save_gim;
+	u32			save_gs;
 	struct dma_pool		*at_xdmac_desc_pool;
 	struct at_xdmac_chan	chan[0];
 };
@@ -220,15 +222,15 @@
 
 /* Linked List Descriptor */
 struct at_xdmac_lld {
-	dma_addr_t	mbr_nda;	/* Next Descriptor Member */
-	u32		mbr_ubc;	/* Microblock Control Member */
-	dma_addr_t	mbr_sa;		/* Source Address Member */
-	dma_addr_t	mbr_da;		/* Destination Address Member */
-	u32		mbr_cfg;	/* Configuration Register */
-	u32		mbr_bc;		/* Block Control Register */
-	u32		mbr_ds;		/* Data Stride Register */
-	u32		mbr_sus;	/* Source Microblock Stride Register */
-	u32		mbr_dus;	/* Destination Microblock Stride Register */
+	u32 mbr_nda;	/* Next Descriptor Member */
+	u32 mbr_ubc;	/* Microblock Control Member */
+	u32 mbr_sa;	/* Source Address Member */
+	u32 mbr_da;	/* Destination Address Member */
+	u32 mbr_cfg;	/* Configuration Register */
+	u32 mbr_bc;	/* Block Control Register */
+	u32 mbr_ds;	/* Data Stride Register */
+	u32 mbr_sus;	/* Source Microblock Stride Register */
+	u32 mbr_dus;	/* Destination Microblock Stride Register */
 };
 
 /* 64-bit alignment needed to update CNDA and CUBC registers in an atomic way. */
@@ -338,9 +340,6 @@
 
 	dev_vdbg(chan2dev(&atchan->chan), "%s: desc 0x%p\n", __func__, first);
 
-	if (at_xdmac_chan_is_enabled(atchan))
-		return;
-
 	/* Set transfer as active to not try to start it again. */
 	first->active_xfer = true;
 
@@ -356,7 +355,8 @@
 	 */
 	if (at_xdmac_chan_is_cyclic(atchan))
 		reg = AT_XDMAC_CNDC_NDVIEW_NDV1;
-	else if (first->lld.mbr_ubc & AT_XDMAC_MBR_UBC_NDV3)
+	else if ((first->lld.mbr_ubc &
+		  AT_XDMAC_CNDC_NDVIEW_MASK) == AT_XDMAC_MBR_UBC_NDV3)
 		reg = AT_XDMAC_CNDC_NDVIEW_NDV3;
 	else
 		reg = AT_XDMAC_CNDC_NDVIEW_NDV2;
@@ -427,13 +427,12 @@
 	spin_lock_irqsave(&atchan->lock, irqflags);
 	cookie = dma_cookie_assign(tx);
 
+	list_add_tail(&desc->xfer_node, &atchan->xfers_list);
+	spin_unlock_irqrestore(&atchan->lock, irqflags);
+
 	dev_vdbg(chan2dev(tx->chan), "%s: atchan 0x%p, add desc 0x%p to xfers_list\n",
 		 __func__, atchan, desc);
-	list_add_tail(&desc->xfer_node, &atchan->xfers_list);
-	if (list_is_singular(&atchan->xfers_list))
-		at_xdmac_start_xfer(atchan, desc);
 
-	spin_unlock_irqrestore(&atchan->lock, irqflags);
 	return cookie;
 }
 
@@ -1215,6 +1214,8 @@
 		return NULL;
 
 	desc = at_xdmac_memset_create_desc(chan, atchan, dest, len, value);
+	if (!desc)
+		return NULL;
 	list_add_tail(&desc->desc_node, &desc->descs_list);
 
 	desc->tx_dma_desc.cookie = -EBUSY;
@@ -1392,7 +1393,7 @@
 {
 	struct at_xdmac_chan	*atchan = to_at_xdmac_chan(chan);
 	struct at_xdmac		*atxdmac = to_at_xdmac(atchan->chan.device);
-	struct at_xdmac_desc	*desc, *_desc;
+	struct at_xdmac_desc	*desc, *_desc, *iter;
 	struct list_head	*descs_list;
 	enum dma_status		ret;
 	int			residue, retry;
@@ -1507,11 +1508,13 @@
 	 * microblock.
 	 */
 	descs_list = &desc->descs_list;
-	list_for_each_entry_safe(desc, _desc, descs_list, desc_node) {
-		dwidth = at_xdmac_get_dwidth(desc->lld.mbr_cfg);
-		residue -= (desc->lld.mbr_ubc & 0xffffff) << dwidth;
-		if ((desc->lld.mbr_nda & 0xfffffffc) == cur_nda)
+	list_for_each_entry_safe(iter, _desc, descs_list, desc_node) {
+		dwidth = at_xdmac_get_dwidth(iter->lld.mbr_cfg);
+		residue -= (iter->lld.mbr_ubc & 0xffffff) << dwidth;
+		if ((iter->lld.mbr_nda & 0xfffffffc) == cur_nda) {
+			desc = iter;
 			break;
+		}
 	}
 	residue += cur_ubc << dwidth;
 
@@ -1568,14 +1571,17 @@
 	struct at_xdmac_desc		*desc;
 	struct dma_async_tx_descriptor	*txd;
 
-	if (!list_empty(&atchan->xfers_list)) {
-		desc = list_first_entry(&atchan->xfers_list,
-					struct at_xdmac_desc, xfer_node);
-		txd = &desc->tx_dma_desc;
-
-		if (txd->flags & DMA_PREP_INTERRUPT)
-			dmaengine_desc_get_callback_invoke(txd, NULL);
+	spin_lock_irq(&atchan->lock);
+	if (list_empty(&atchan->xfers_list)) {
+		spin_unlock_irq(&atchan->lock);
+		return;
 	}
+	desc = list_first_entry(&atchan->xfers_list, struct at_xdmac_desc,
+				xfer_node);
+	spin_unlock_irq(&atchan->lock);
+	txd = &desc->tx_dma_desc;
+	if (txd->flags & DMA_PREP_INTERRUPT)
+		dmaengine_desc_get_callback_invoke(txd, NULL);
 }
 
 static void at_xdmac_handle_error(struct at_xdmac_chan *atchan)
@@ -1725,11 +1731,13 @@
 static void at_xdmac_issue_pending(struct dma_chan *chan)
 {
 	struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan);
+	unsigned long flags;
 
 	dev_dbg(chan2dev(&atchan->chan), "%s\n", __func__);
 
-	if (!at_xdmac_chan_is_cyclic(atchan))
-		at_xdmac_advance_work(atchan);
+	spin_lock_irqsave(&atchan->lock, flags);
+	at_xdmac_advance_work(atchan);
+	spin_unlock_irqrestore(&atchan->lock, flags);
 
 	return;
 }
@@ -1843,6 +1851,11 @@
 	for (i = 0; i < init_nr_desc_per_channel; i++) {
 		desc = at_xdmac_alloc_desc(chan, GFP_ATOMIC);
 		if (!desc) {
+			if (i == 0) {
+				dev_warn(chan2dev(chan),
+					 "can't allocate any descriptors\n");
+				return -EIO;
+			}
 			dev_warn(chan2dev(chan),
 				"only %d descriptors have been allocated\n", i);
 			break;
@@ -1912,6 +1925,7 @@
 		}
 	}
 	atxdmac->save_gim = at_xdmac_read(atxdmac, AT_XDMAC_GIM);
+	atxdmac->save_gs = at_xdmac_read(atxdmac, AT_XDMAC_GS);
 
 	at_xdmac_off(atxdmac);
 	clk_disable_unprepare(atxdmac->clk);
@@ -1948,7 +1962,8 @@
 			at_xdmac_chan_write(atchan, AT_XDMAC_CNDC, atchan->save_cndc);
 			at_xdmac_chan_write(atchan, AT_XDMAC_CIE, atchan->save_cim);
 			wmb();
-			at_xdmac_write(atxdmac, AT_XDMAC_GE, atchan->mask);
+			if (atxdmac->save_gs & atchan->mask)
+				at_xdmac_write(atxdmac, AT_XDMAC_GE, atchan->mask);
 		}
 	}
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/coh901318.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/coh901318.c
@@ -1947,8 +1947,6 @@
 		return;
 	}
 
-	spin_lock(&cohc->lock);
-
 	/*
 	 * When we reach this point, at least one queue item
 	 * should have been moved over from cohc->queue to
@@ -1969,8 +1967,6 @@
 	if (coh901318_queue_start(cohc) == NULL)
 		cohc->busy = 0;
 
-	spin_unlock(&cohc->lock);
-
 	/*
 	 * This tasklet will remove items from cohc->active
 	 * and thus terminates them.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/dma-axi-dmac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/dma-axi-dmac.c
@@ -830,6 +830,7 @@
 	struct dma_device *dma_dev;
 	struct axi_dmac *dmac;
 	struct resource *res;
+	struct regmap *regmap;
 	int ret;
 
 	dmac = devm_kzalloc(&pdev->dev, sizeof(*dmac), GFP_KERNEL);
@@ -921,10 +922,17 @@
 
 	platform_set_drvdata(pdev, dmac);
 
-	devm_regmap_init_mmio(&pdev->dev, dmac->base, &axi_dmac_regmap_config);
+	regmap = devm_regmap_init_mmio(&pdev->dev, dmac->base,
+		 &axi_dmac_regmap_config);
+	if (IS_ERR(regmap)) {
+		ret = PTR_ERR(regmap);
+		goto err_free_irq;
+	}
 
 	return 0;
 
+err_free_irq:
+	free_irq(dmac->irq, dmac);
 err_unregister_of:
 	of_dma_controller_free(pdev->dev.of_node);
 err_unregister_device:
@@ -939,8 +947,8 @@
 {
 	struct axi_dmac *dmac = platform_get_drvdata(pdev);
 
-	of_dma_controller_free(pdev->dev.of_node);
 	free_irq(dmac->irq, dmac);
+	of_dma_controller_free(pdev->dev.of_node);
 	tasklet_kill(&dmac->chan.vchan.task);
 	dma_async_device_unregister(&dmac->dma_dev);
 	clk_disable_unprepare(dmac->clk);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/dma-jz4780.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/dma-jz4780.c
@@ -639,11 +639,11 @@
 	unsigned long flags;
 	unsigned long residue = 0;
 
+	spin_lock_irqsave(&jzchan->vchan.lock, flags);
+
 	status = dma_cookie_status(chan, cookie, txstate);
 	if ((status == DMA_COMPLETE) || (txstate == NULL))
-		return status;
-
-	spin_lock_irqsave(&jzchan->vchan.lock, flags);
+		goto out_unlock_irqrestore;
 
 	vdesc = vchan_find_desc(&jzchan->vchan, cookie);
 	if (vdesc) {
@@ -660,6 +660,7 @@
 	    && jzchan->desc->status & (JZ_DMA_DCS_AR | JZ_DMA_DCS_HLT))
 		status = DMA_ERROR;
 
+out_unlock_irqrestore:
 	spin_unlock_irqrestore(&jzchan->vchan.lock, flags);
 	return status;
 }
@@ -885,24 +886,11 @@
 		return -EINVAL;
 	}
 
-	ret = platform_get_irq(pdev, 0);
-	if (ret < 0)
-		return ret;
-
-	jzdma->irq = ret;
-
-	ret = request_irq(jzdma->irq, jz4780_dma_irq_handler, 0, dev_name(dev),
-			  jzdma);
-	if (ret) {
-		dev_err(dev, "failed to request IRQ %u!\n", jzdma->irq);
-		return ret;
-	}
-
 	jzdma->clk = devm_clk_get(dev, NULL);
 	if (IS_ERR(jzdma->clk)) {
 		dev_err(dev, "failed to get clock\n");
 		ret = PTR_ERR(jzdma->clk);
-		goto err_free_irq;
+		return ret;
 	}
 
 	clk_prepare_enable(jzdma->clk);
@@ -955,10 +943,23 @@
 		jzchan->vchan.desc_free = jz4780_dma_desc_free;
 	}
 
+	ret = platform_get_irq(pdev, 0);
+	if (ret < 0)
+		goto err_disable_clk;
+
+	jzdma->irq = ret;
+
+	ret = request_irq(jzdma->irq, jz4780_dma_irq_handler, 0, dev_name(dev),
+			  jzdma);
+	if (ret) {
+		dev_err(dev, "failed to request IRQ %u!\n", jzdma->irq);
+		goto err_disable_clk;
+	}
+
 	ret = dmaenginem_async_device_register(dd);
 	if (ret) {
 		dev_err(dev, "failed to register device\n");
-		goto err_disable_clk;
+		goto err_free_irq;
 	}
 
 	/* Register with OF DMA helpers. */
@@ -966,17 +967,17 @@
 					 jzdma);
 	if (ret) {
 		dev_err(dev, "failed to register OF DMA controller\n");
-		goto err_disable_clk;
+		goto err_free_irq;
 	}
 
 	dev_info(dev, "JZ4780 DMA controller initialised\n");
 	return 0;
 
-err_disable_clk:
-	clk_disable_unprepare(jzdma->clk);
-
 err_free_irq:
 	free_irq(jzdma->irq, jzdma);
+
+err_disable_clk:
+	clk_disable_unprepare(jzdma->clk);
 	return ret;
 }
 
@@ -1004,7 +1005,8 @@
 static const struct jz4780_dma_soc_data jz4725b_dma_soc_data = {
 	.nb_channels = 6,
 	.transfer_ord_max = 5,
-	.flags = JZ_SOC_DATA_PER_CHAN_PM | JZ_SOC_DATA_NO_DCKES_DCKEC,
+	.flags = JZ_SOC_DATA_PER_CHAN_PM | JZ_SOC_DATA_NO_DCKES_DCKEC |
+		 JZ_SOC_DATA_BREAK_LINKS,
 };
 
 static const struct jz4780_dma_soc_data jz4770_dma_soc_data = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/dmaengine.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/dmaengine.c
@@ -179,7 +179,7 @@
 
 static struct module *dma_chan_to_owner(struct dma_chan *chan)
 {
-	return chan->device->dev->driver->owner;
+	return chan->device->owner;
 }
 
 /**
@@ -212,7 +212,8 @@
 	/* The channel is already in use, update client count */
 	if (chan->client_count) {
 		__module_get(owner);
-		goto out;
+		chan->client_count++;
+		return 0;
 	}
 
 	if (!try_module_get(owner))
@@ -225,11 +226,11 @@
 			goto err_out;
 	}
 
+	chan->client_count++;
+
 	if (!dma_has_cap(DMA_PRIVATE, chan->device->cap_mask))
 		balance_ref_count(chan);
 
-out:
-	chan->client_count++;
 	return 0;
 
 err_out:
@@ -919,6 +920,8 @@
 		return -EIO;
 	}
 
+	device->owner = device->dev->driver->owner;
+
 	if (dma_has_cap(DMA_MEMCPY, device->cap_mask) && !device->device_prep_dma_memcpy) {
 		dev_err(device->dev,
 			"Device claims capability %s, but op is not defined\n",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/dmaengine.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/dmaengine.h
@@ -168,7 +168,7 @@
 static inline bool
 dmaengine_desc_callback_valid(struct dmaengine_desc_callback *cb)
 {
-	return (cb->callback) ? true : false;
+	return cb->callback || cb->callback_result;
 }
 
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/dmatest.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/dmatest.c
@@ -240,7 +240,7 @@
 		struct dmatest_thread *thread;
 
 		list_for_each_entry(thread, &dtc->threads, node) {
-			if (!thread->done)
+			if (!thread->done && !thread->pending)
 				return true;
 		}
 	}
@@ -662,8 +662,8 @@
 		flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
 
 	ktime = ktime_get();
-	while (!kthread_should_stop()
-	       && !(params->iterations && total_tests >= params->iterations)) {
+	while (!(kthread_should_stop() ||
+	       (params->iterations && total_tests >= params->iterations))) {
 		struct dma_async_tx_descriptor *tx = NULL;
 		struct dmaengine_unmap_data *um;
 		dma_addr_t *dsts;
@@ -1166,10 +1166,13 @@
 		mutex_unlock(&info->lock);
 		return ret;
 	} else if (dmatest_run) {
-		if (is_threaded_test_pending(info))
-			start_threaded_tests(info);
-		else
-			pr_info("Could not start test, no channels configured\n");
+		if (!is_threaded_test_pending(info)) {
+			pr_info("No channels configured, continue with any\n");
+			if (!is_threaded_test_run(info))
+				stop_threaded_test(info);
+			add_threaded_test(info);
+		}
+		start_threaded_tests(info);
 	} else {
 		stop_threaded_test(info);
 	}
@@ -1215,15 +1218,14 @@
 	add_threaded_test(info);
 
 	/* Check if channel was added successfully */
-	dtc = list_last_entry(&info->channels, struct dmatest_chan, node);
-
-	if (dtc->chan) {
+	if (!list_empty(&info->channels)) {
 		/*
 		 * if new channel was not successfully added, revert the
 		 * "test_channel" string to the name of the last successfully
 		 * added channel. exception for when users issues empty string
 		 * to channel parameter.
 		 */
+		dtc = list_last_entry(&info->channels, struct dmatest_chan, node);
 		if ((strcmp(dma_chan_name(dtc->chan), strim(test_channel)) != 0)
 		    && (strcmp("", strim(test_channel)) != 0)) {
 			ret = -EINVAL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
@@ -551,6 +551,11 @@
 
 	/* The bad descriptor currently is in the head of vc list */
 	vd = vchan_next_desc(&chan->vc);
+	if (!vd) {
+		dev_err(chan2dev(chan), "BUG: %s, IRQ with no descriptors\n",
+			axi_chan_name(chan));
+		goto out;
+	}
 	/* Remove the completed descriptor from issued list */
 	list_del(&vd->node);
 
@@ -565,6 +570,7 @@
 	/* Try to restart the controller */
 	axi_chan_start_first_queued(chan);
 
+out:
 	spin_unlock_irqrestore(&chan->vc.lock, flags);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/dw-edma/dw-edma-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/dw-edma/dw-edma-core.c
@@ -85,12 +85,12 @@
 
 	if (desc->chunk) {
 		/* Create and add new element into the linked list */
-		desc->chunks_alloc++;
-		list_add_tail(&chunk->list, &desc->chunk->list);
 		if (!dw_edma_alloc_burst(chunk)) {
 			kfree(chunk);
 			return NULL;
 		}
+		desc->chunks_alloc++;
+		list_add_tail(&chunk->list, &desc->chunk->list);
 	} else {
 		/* List head */
 		chunk->burst = NULL;
@@ -165,7 +165,7 @@
 	dw_edma_free_desc(vd2dw_edma_desc(vdesc));
 }
 
-static void dw_edma_start_transfer(struct dw_edma_chan *chan)
+static int dw_edma_start_transfer(struct dw_edma_chan *chan)
 {
 	struct dw_edma_chunk *child;
 	struct dw_edma_desc *desc;
@@ -173,16 +173,16 @@
 
 	vd = vchan_next_desc(&chan->vc);
 	if (!vd)
-		return;
+		return 0;
 
 	desc = vd2dw_edma_desc(vd);
 	if (!desc)
-		return;
+		return 0;
 
 	child = list_first_entry_or_null(&desc->chunk->list,
 					 struct dw_edma_chunk, list);
 	if (!child)
-		return;
+		return 0;
 
 	dw_edma_v0_core_start(child, !desc->xfer_sz);
 	desc->xfer_sz += child->ll_region.sz;
@@ -190,6 +190,8 @@
 	list_del(&child->list);
 	kfree(child);
 	desc->chunks_alloc--;
+
+	return 1;
 }
 
 static int dw_edma_device_config(struct dma_chan *dchan,
@@ -273,9 +275,12 @@
 	struct dw_edma_chan *chan = dchan2dw_edma_chan(dchan);
 	unsigned long flags;
 
+	if (!chan->configured)
+		return;
+
 	spin_lock_irqsave(&chan->vc.lock, flags);
-	if (chan->configured && chan->request == EDMA_REQ_NONE &&
-	    chan->status == EDMA_ST_IDLE && vchan_issue_pending(&chan->vc)) {
+	if (vchan_issue_pending(&chan->vc) && chan->request == EDMA_REQ_NONE &&
+	    chan->status == EDMA_ST_IDLE) {
 		chan->status = EDMA_ST_BUSY;
 		dw_edma_start_transfer(chan);
 	}
@@ -391,7 +396,7 @@
 			if (xfer->cyclic) {
 				burst->dar = xfer->xfer.cyclic.paddr;
 			} else {
-				burst->dar = sg_dma_address(sg);
+				burst->dar = dst_addr;
 				/* Unlike the typical assumption by other
 				 * drivers/IPs the peripheral memory isn't
 				 * a FIFO memory, in this case, it's a
@@ -399,14 +404,13 @@
 				 * and destination addresses are increased
 				 * by the same portion (data length)
 				 */
-				src_addr += sg_dma_len(sg);
 			}
 		} else {
 			burst->dar = dst_addr;
 			if (xfer->cyclic) {
 				burst->sar = xfer->xfer.cyclic.paddr;
 			} else {
-				burst->sar = sg_dma_address(sg);
+				burst->sar = src_addr;
 				/* Unlike the typical assumption by other
 				 * drivers/IPs the peripheral memory isn't
 				 * a FIFO memory, in this case, it's a
@@ -414,12 +418,14 @@
 				 * and destination addresses are increased
 				 * by the same portion (data length)
 				 */
-				dst_addr += sg_dma_len(sg);
 			}
 		}
 
-		if (!xfer->cyclic)
+		if (!xfer->cyclic) {
+			src_addr += sg_dma_len(sg);
+			dst_addr += sg_dma_len(sg);
 			sg = sg_next(sg);
+		}
 	}
 
 	return vchan_tx_prep(&chan->vc, &desc->vd, xfer->flags);
@@ -482,14 +488,14 @@
 		switch (chan->request) {
 		case EDMA_REQ_NONE:
 			desc = vd2dw_edma_desc(vd);
-			if (desc->chunks_alloc) {
-				chan->status = EDMA_ST_BUSY;
-				dw_edma_start_transfer(chan);
-			} else {
+			if (!desc->chunks_alloc) {
 				list_del(&vd->node);
 				vchan_cookie_complete(vd);
-				chan->status = EDMA_ST_IDLE;
 			}
+
+			/* Continue transferring if there are remaining chunks or issued requests.
+			 */
+			chan->status = dw_edma_start_transfer(chan) ? EDMA_ST_BUSY : EDMA_ST_IDLE;
 			break;
 
 		case EDMA_REQ_STOP:
@@ -909,22 +915,21 @@
 	/* Power management */
 	pm_runtime_disable(dev);
 
+	/* Deregister eDMA device */
+	dma_async_device_unregister(&dw->wr_edma);
 	list_for_each_entry_safe(chan, _chan, &dw->wr_edma.channels,
 				 vc.chan.device_node) {
-		list_del(&chan->vc.chan.device_node);
 		tasklet_kill(&chan->vc.task);
+		list_del(&chan->vc.chan.device_node);
 	}
 
+	dma_async_device_unregister(&dw->rd_edma);
 	list_for_each_entry_safe(chan, _chan, &dw->rd_edma.channels,
 				 vc.chan.device_node) {
-		list_del(&chan->vc.chan.device_node);
 		tasklet_kill(&chan->vc.task);
+		list_del(&chan->vc.chan.device_node);
 	}
 
-	/* Deregister eDMA device */
-	dma_async_device_unregister(&dw->wr_edma);
-	dma_async_device_unregister(&dw->rd_edma);
-
 	/* Turn debugfs off */
 	dw_edma_v0_core_debugfs_off();
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/dw/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/dw/Kconfig
@@ -10,6 +10,7 @@
 
 config DW_DMAC
 	tristate "Synopsys DesignWare AHB DMA platform driver"
+	depends on HAS_IOMEM
 	select DW_DMAC_CORE
 	help
 	  Support the Synopsys DesignWare AHB DMA controller. This
@@ -18,6 +19,7 @@
 config DW_DMAC_PCI
 	tristate "Synopsys DesignWare AHB DMA PCI driver"
 	depends on PCI
+	depends on HAS_IOMEM
 	select DW_DMAC_CORE
 	help
 	  Support the Synopsys DesignWare AHB DMA controller on the
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/dw/core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/dw/core.c
@@ -118,16 +118,11 @@
 {
 	struct dw_dma *dw = to_dw_dma(dwc->chan.device);
 
-	if (test_bit(DW_DMA_IS_INITIALIZED, &dwc->flags))
-		return;
-
 	dw->initialize_chan(dwc);
 
 	/* Enable interrupts */
 	channel_set_bit(dw, MASK.XFER, dwc->mask);
 	channel_set_bit(dw, MASK.ERROR, dwc->mask);
-
-	set_bit(DW_DMA_IS_INITIALIZED, &dwc->flags);
 }
 
 /*----------------------------------------------------------------------*/
@@ -777,6 +772,10 @@
 	if (dws->dma_dev != chan->device->dev)
 		return false;
 
+	/* permit channels in accordance with the channels mask */
+	if (dws->channels && !(dws->channels & dwc->mask))
+		return false;
+
 	/* We have to copy data since dws can be temporary storage */
 	memcpy(&dwc->dws, dws, sizeof(struct dw_dma_slave));
 
@@ -954,8 +953,6 @@
 
 void do_dw_dma_off(struct dw_dma *dw)
 {
-	unsigned int i;
-
 	dma_writel(dw, CFG, 0);
 
 	channel_clear_bit(dw, MASK.XFER, dw->all_chan_mask);
@@ -966,9 +963,6 @@
 
 	while (dma_readl(dw, CFG) & DW_CFG_DMA_EN)
 		cpu_relax();
-
-	for (i = 0; i < dw->dma.chancnt; i++)
-		clear_bit(DW_DMA_IS_INITIALIZED, &dw->chan[i].flags);
 }
 
 void do_dw_dma_on(struct dw_dma *dw)
@@ -1032,8 +1026,6 @@
 	/* Clear custom channel configuration */
 	memset(&dwc->dws, 0, sizeof(struct dw_dma_slave));
 
-	clear_bit(DW_DMA_IS_INITIALIZED, &dwc->flags);
-
 	/* Disable interrupts */
 	channel_clear_bit(dw, MASK.XFER, dwc->mask);
 	channel_clear_bit(dw, MASK.BLOCK, dwc->mask);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/dw/dw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/dw/dw.c
@@ -14,7 +14,7 @@
 static void dw_dma_initialize_chan(struct dw_dma_chan *dwc)
 {
 	struct dw_dma *dw = to_dw_dma(dwc->chan.device);
-	u32 cfghi = DWC_CFGH_FIFO_MODE;
+	u32 cfghi = is_slave_direction(dwc->direction) ? 0 : DWC_CFGH_FIFO_MODE;
 	u32 cfglo = DWC_CFGL_CH_PRIOR(dwc->priority);
 	bool hs_polarity = dwc->dws.hs_polarity;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/dw/of.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/dw/of.c
@@ -22,18 +22,21 @@
 	};
 	dma_cap_mask_t cap;
 
-	if (dma_spec->args_count != 3)
+	if (dma_spec->args_count < 3 || dma_spec->args_count > 4)
 		return NULL;
 
 	slave.src_id = dma_spec->args[0];
 	slave.dst_id = dma_spec->args[0];
 	slave.m_master = dma_spec->args[1];
 	slave.p_master = dma_spec->args[2];
+	if (dma_spec->args_count >= 4)
+		slave.channels = dma_spec->args[3];
 
 	if (WARN_ON(slave.src_id >= DW_DMA_MAX_NR_REQUESTS ||
 		    slave.dst_id >= DW_DMA_MAX_NR_REQUESTS ||
 		    slave.m_master >= dw->pdata->nr_masters ||
-		    slave.p_master >= dw->pdata->nr_masters))
+		    slave.p_master >= dw->pdata->nr_masters ||
+		    slave.channels >= BIT(dw->pdata->nr_channels)))
 		return NULL;
 
 	dma_cap_zero(cap);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/dw/platform.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/dw/platform.c
@@ -66,7 +66,7 @@
 
 	data->chip = chip;
 
-	chip->clk = devm_clk_get(chip->dev, "hclk");
+	chip->clk = devm_clk_get_optional(chip->dev, "hclk");
 	if (IS_ERR(chip->clk))
 		return PTR_ERR(chip->clk);
 	err = clk_prepare_enable(chip->clk);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/fsl-edma-common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/fsl-edma-common.c
@@ -347,26 +347,28 @@
 	/*
 	 * TCD parameters are stored in struct fsl_edma_hw_tcd in little
 	 * endian format. However, we need to load the TCD registers in
-	 * big- or little-endian obeying the eDMA engine model endian.
+	 * big- or little-endian obeying the eDMA engine model endian,
+	 * and this is performed from specific edma_write functions
 	 */
 	edma_writew(edma, 0,  &regs->tcd[ch].csr);
-	edma_writel(edma, le32_to_cpu(tcd->saddr), &regs->tcd[ch].saddr);
-	edma_writel(edma, le32_to_cpu(tcd->daddr), &regs->tcd[ch].daddr);
 
-	edma_writew(edma, le16_to_cpu(tcd->attr), &regs->tcd[ch].attr);
-	edma_writew(edma, le16_to_cpu(tcd->soff), &regs->tcd[ch].soff);
+	edma_writel(edma, (s32)tcd->saddr, &regs->tcd[ch].saddr);
+	edma_writel(edma, (s32)tcd->daddr, &regs->tcd[ch].daddr);
 
-	edma_writel(edma, le32_to_cpu(tcd->nbytes), &regs->tcd[ch].nbytes);
-	edma_writel(edma, le32_to_cpu(tcd->slast), &regs->tcd[ch].slast);
+	edma_writew(edma, (s16)tcd->attr, &regs->tcd[ch].attr);
+	edma_writew(edma, tcd->soff, &regs->tcd[ch].soff);
 
-	edma_writew(edma, le16_to_cpu(tcd->citer), &regs->tcd[ch].citer);
-	edma_writew(edma, le16_to_cpu(tcd->biter), &regs->tcd[ch].biter);
-	edma_writew(edma, le16_to_cpu(tcd->doff), &regs->tcd[ch].doff);
+	edma_writel(edma, (s32)tcd->nbytes, &regs->tcd[ch].nbytes);
+	edma_writel(edma, (s32)tcd->slast, &regs->tcd[ch].slast);
 
-	edma_writel(edma, le32_to_cpu(tcd->dlast_sga),
+	edma_writew(edma, (s16)tcd->citer, &regs->tcd[ch].citer);
+	edma_writew(edma, (s16)tcd->biter, &regs->tcd[ch].biter);
+	edma_writew(edma, (s16)tcd->doff, &regs->tcd[ch].doff);
+
+	edma_writel(edma, (s32)tcd->dlast_sga,
 			&regs->tcd[ch].dlast_sga);
 
-	edma_writew(edma, le16_to_cpu(tcd->csr), &regs->tcd[ch].csr);
+	edma_writew(edma, (s16)tcd->csr, &regs->tcd[ch].csr);
 }
 
 static inline
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/fsl-edma-common.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/fsl-edma-common.h
@@ -33,7 +33,7 @@
 #define EDMA_TCD_ATTR_DSIZE_16BIT	BIT(0)
 #define EDMA_TCD_ATTR_DSIZE_32BIT	BIT(1)
 #define EDMA_TCD_ATTR_DSIZE_64BIT	(BIT(0) | BIT(1))
-#define EDMA_TCD_ATTR_DSIZE_32BYTE	(BIT(3) | BIT(0))
+#define EDMA_TCD_ATTR_DSIZE_32BYTE	(BIT(2) | BIT(0))
 #define EDMA_TCD_ATTR_SSIZE_8BIT	0
 #define EDMA_TCD_ATTR_SSIZE_16BIT	(EDMA_TCD_ATTR_DSIZE_16BIT << 8)
 #define EDMA_TCD_ATTR_SSIZE_32BIT	(EDMA_TCD_ATTR_DSIZE_32BIT << 8)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/fsl-edma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/fsl-edma.c
@@ -45,6 +45,13 @@
 			fsl_chan = &fsl_edma->chans[ch];
 
 			spin_lock(&fsl_chan->vchan.lock);
+
+			if (!fsl_chan->edesc) {
+				/* terminate_all called before */
+				spin_unlock(&fsl_chan->vchan.lock);
+				continue;
+			}
+
 			if (!fsl_chan->edesc->iscyclic) {
 				list_del(&fsl_chan->edesc->vdesc.node);
 				vchan_cookie_complete(&fsl_chan->edesc->vdesc);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/fsl-qdma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/fsl-qdma.c
@@ -109,6 +109,7 @@
 #define FSL_QDMA_CMD_WTHROTL_OFFSET	20
 #define FSL_QDMA_CMD_DSEN_OFFSET	19
 #define FSL_QDMA_CMD_LWC_OFFSET		16
+#define FSL_QDMA_CMD_PF			BIT(17)
 
 /* Field definition for Descriptor offset */
 #define QDMA_CCDF_STATUS		20
@@ -304,7 +305,7 @@
 
 	vchan_dma_desc_free_list(&fsl_chan->vchan, &head);
 
-	if (!fsl_queue->comp_pool && !fsl_queue->comp_pool)
+	if (!fsl_queue->comp_pool && !fsl_queue->desc_pool)
 		return;
 
 	list_for_each_entry_safe(comp_temp, _comp_temp,
@@ -372,7 +373,8 @@
 	qdma_csgf_set_f(csgf_dest, len);
 	/* Descriptor Buffer */
 	cmd = cpu_to_le32(FSL_QDMA_CMD_RWTTYPE <<
-			  FSL_QDMA_CMD_RWTTYPE_OFFSET);
+			  FSL_QDMA_CMD_RWTTYPE_OFFSET) |
+			  FSL_QDMA_CMD_PF;
 	sdf->data = QDMA_SDDF_CMD(cmd);
 
 	cmd = cpu_to_le32(FSL_QDMA_CMD_RWTTYPE <<
@@ -502,11 +504,11 @@
 			queue_temp = queue_head + i + (j * queue_num);
 
 			queue_temp->cq =
-			dma_alloc_coherent(&pdev->dev,
-					   sizeof(struct fsl_qdma_format) *
-					   queue_size[i],
-					   &queue_temp->bus_addr,
-					   GFP_KERNEL);
+			dmam_alloc_coherent(&pdev->dev,
+					    sizeof(struct fsl_qdma_format) *
+					    queue_size[i],
+					    &queue_temp->bus_addr,
+					    GFP_KERNEL);
 			if (!queue_temp->cq)
 				return NULL;
 			queue_temp->block_base = fsl_qdma->block_base +
@@ -551,11 +553,11 @@
 	/*
 	 * Buffer for queue command
 	 */
-	status_head->cq = dma_alloc_coherent(&pdev->dev,
-					     sizeof(struct fsl_qdma_format) *
-					     status_size,
-					     &status_head->bus_addr,
-					     GFP_KERNEL);
+	status_head->cq = dmam_alloc_coherent(&pdev->dev,
+					      sizeof(struct fsl_qdma_format) *
+					      status_size,
+					      &status_head->bus_addr,
+					      GFP_KERNEL);
 	if (!status_head->cq) {
 		devm_kfree(&pdev->dev, status_head);
 		return NULL;
@@ -754,7 +756,7 @@
 	int i;
 	int cpu;
 	int ret;
-	char irq_name[20];
+	char irq_name[32];
 
 	fsl_qdma->error_irq =
 		platform_get_irq_byname(pdev, "qdma-error");
@@ -1150,11 +1152,10 @@
 	if (!fsl_qdma->queue)
 		return -ENOMEM;
 
-	ret = fsl_qdma_irq_init(pdev, fsl_qdma);
-	if (ret)
-		return ret;
-
 	fsl_qdma->irq_base = platform_get_irq_byname(pdev, "qdma-queue0");
+	if (fsl_qdma->irq_base < 0)
+		return fsl_qdma->irq_base;
+
 	fsl_qdma->feature = of_property_read_bool(np, "big-endian");
 	INIT_LIST_HEAD(&fsl_qdma->dma_dev.channels);
 
@@ -1181,20 +1182,27 @@
 	fsl_qdma->dma_dev.device_synchronize = fsl_qdma_synchronize;
 	fsl_qdma->dma_dev.device_terminate_all = fsl_qdma_terminate_all;
 
-	dma_set_mask(&pdev->dev, DMA_BIT_MASK(40));
+	ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(40));
+	if (ret) {
+		dev_err(&pdev->dev, "dma_set_mask failure.\n");
+		return ret;
+	}
 
 	platform_set_drvdata(pdev, fsl_qdma);
 
-	ret = dma_async_device_register(&fsl_qdma->dma_dev);
+	ret = fsl_qdma_reg_init(fsl_qdma);
 	if (ret) {
-		dev_err(&pdev->dev,
-			"Can't register NXP Layerscape qDMA engine.\n");
+		dev_err(&pdev->dev, "Can't Initialize the qDMA engine.\n");
 		return ret;
 	}
 
-	ret = fsl_qdma_reg_init(fsl_qdma);
+	ret = fsl_qdma_irq_init(pdev, fsl_qdma);
+	if (ret)
+		return ret;
+
+	ret = dma_async_device_register(&fsl_qdma->dma_dev);
 	if (ret) {
-		dev_err(&pdev->dev, "Can't Initialize the qDMA engine.\n");
+		dev_err(&pdev->dev, "Can't register NXP Layerscape qDMA engine.\n");
 		return ret;
 	}
 
@@ -1214,8 +1222,6 @@
 
 static int fsl_qdma_remove(struct platform_device *pdev)
 {
-	int i;
-	struct fsl_qdma_queue *status;
 	struct device_node *np = pdev->dev.of_node;
 	struct fsl_qdma_engine *fsl_qdma = platform_get_drvdata(pdev);
 
@@ -1224,11 +1230,6 @@
 	of_dma_controller_free(np);
 	dma_async_device_unregister(&fsl_qdma->dma_dev);
 
-	for (i = 0; i < fsl_qdma->block_number; i++) {
-		status = fsl_qdma->status[i];
-		dma_free_coherent(&pdev->dev, sizeof(struct fsl_qdma_format) *
-				status->n_cq, status->cq, status->bus_addr);
-	}
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/fsldma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/fsldma.c
@@ -1214,6 +1214,7 @@
 {
 	struct fsldma_device *fdev;
 	struct device_node *child;
+	unsigned int i;
 	int err;
 
 	fdev = kzalloc(sizeof(*fdev), GFP_KERNEL);
@@ -1292,6 +1293,10 @@
 	return 0;
 
 out_free_fdev:
+	for (i = 0; i < FSL_DMA_MAX_CHANS_PER_DEVICE; i++) {
+		if (fdev->chan[i])
+			fsl_dma_chan_remove(fdev->chan[i]);
+	}
 	irq_dispose_mapping(fdev->irq);
 	iounmap(fdev->regs);
 out_free:
@@ -1314,6 +1319,7 @@
 		if (fdev->chan[i])
 			fsl_dma_chan_remove(fdev->chan[i]);
 	}
+	irq_dispose_mapping(fdev->irq);
 
 	iounmap(fdev->regs);
 	kfree(fdev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/fsldma.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/fsldma.h
@@ -205,10 +205,10 @@
 #else
 static u64 fsl_ioread64(const u64 __iomem *addr)
 {
-	u32 fsl_addr = lower_32_bits(addr);
-	u64 fsl_addr_hi = (u64)in_le32((u32 *)(fsl_addr + 1)) << 32;
+	u32 val_lo = in_le32((u32 __iomem *)addr);
+	u32 val_hi = in_le32((u32 __iomem *)addr + 1);
 
-	return fsl_addr_hi | in_le32((u32 *)fsl_addr);
+	return ((u64)val_hi << 32) + val_lo;
 }
 
 static void fsl_iowrite64(u64 val, u64 __iomem *addr)
@@ -219,10 +219,10 @@
 
 static u64 fsl_ioread64be(const u64 __iomem *addr)
 {
-	u32 fsl_addr = lower_32_bits(addr);
-	u64 fsl_addr_hi = (u64)in_be32((u32 *)fsl_addr) << 32;
+	u32 val_hi = in_be32((u32 __iomem *)addr);
+	u32 val_lo = in_be32((u32 __iomem *)addr + 1);
 
-	return fsl_addr_hi | in_be32((u32 *)(fsl_addr + 1));
+	return ((u64)val_hi << 32) + val_lo;
 }
 
 static void fsl_iowrite64be(u64 val, u64 __iomem *addr)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/hisi_dma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/hisi_dma.c
@@ -0,0 +1,611 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2019 HiSilicon Limited. */
+#include <linux/bitfield.h>
+#include <linux/dmaengine.h>
+#include <linux/init.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include "virt-dma.h"
+
+#define HISI_DMA_SQ_BASE_L		0x0
+#define HISI_DMA_SQ_BASE_H		0x4
+#define HISI_DMA_SQ_DEPTH		0x8
+#define HISI_DMA_SQ_TAIL_PTR		0xc
+#define HISI_DMA_CQ_BASE_L		0x10
+#define HISI_DMA_CQ_BASE_H		0x14
+#define HISI_DMA_CQ_DEPTH		0x18
+#define HISI_DMA_CQ_HEAD_PTR		0x1c
+#define HISI_DMA_CTRL0			0x20
+#define HISI_DMA_CTRL0_QUEUE_EN_S	0
+#define HISI_DMA_CTRL0_QUEUE_PAUSE_S	4
+#define HISI_DMA_CTRL1			0x24
+#define HISI_DMA_CTRL1_QUEUE_RESET_S	0
+#define HISI_DMA_Q_FSM_STS		0x30
+#define HISI_DMA_FSM_STS_MASK		GENMASK(3, 0)
+#define HISI_DMA_INT_STS		0x40
+#define HISI_DMA_INT_STS_MASK		GENMASK(12, 0)
+#define HISI_DMA_INT_MSK		0x44
+#define HISI_DMA_MODE			0x217c
+#define HISI_DMA_OFFSET			0x100
+
+#define HISI_DMA_MSI_NUM		30
+#define HISI_DMA_CHAN_NUM		30
+#define HISI_DMA_Q_DEPTH_VAL		1024
+
+#define PCI_BAR_2			2
+
+enum hisi_dma_mode {
+	EP = 0,
+	RC,
+};
+
+enum hisi_dma_chan_status {
+	DISABLE = -1,
+	IDLE = 0,
+	RUN,
+	CPL,
+	PAUSE,
+	HALT,
+	ABORT,
+	WAIT,
+	BUFFCLR,
+};
+
+struct hisi_dma_sqe {
+	__le32 dw0;
+#define OPCODE_MASK			GENMASK(3, 0)
+#define OPCODE_SMALL_PACKAGE		0x1
+#define OPCODE_M2M			0x4
+#define LOCAL_IRQ_EN			BIT(8)
+#define ATTR_SRC_MASK			GENMASK(14, 12)
+	__le32 dw1;
+	__le32 dw2;
+#define ATTR_DST_MASK			GENMASK(26, 24)
+	__le32 length;
+	__le64 src_addr;
+	__le64 dst_addr;
+};
+
+struct hisi_dma_cqe {
+	__le32 rsv0;
+	__le32 rsv1;
+	__le16 sq_head;
+	__le16 rsv2;
+	__le16 rsv3;
+	__le16 w0;
+#define STATUS_MASK			GENMASK(15, 1)
+#define STATUS_SUCC			0x0
+#define VALID_BIT			BIT(0)
+};
+
+struct hisi_dma_desc {
+	struct virt_dma_desc vd;
+	struct hisi_dma_sqe sqe;
+};
+
+struct hisi_dma_chan {
+	struct virt_dma_chan vc;
+	struct hisi_dma_dev *hdma_dev;
+	struct hisi_dma_sqe *sq;
+	struct hisi_dma_cqe *cq;
+	dma_addr_t sq_dma;
+	dma_addr_t cq_dma;
+	u32 sq_tail;
+	u32 cq_head;
+	u32 qp_num;
+	enum hisi_dma_chan_status status;
+	struct hisi_dma_desc *desc;
+};
+
+struct hisi_dma_dev {
+	struct pci_dev *pdev;
+	void __iomem *base;
+	struct dma_device dma_dev;
+	u32 chan_num;
+	u32 chan_depth;
+	struct hisi_dma_chan chan[];
+};
+
+static inline struct hisi_dma_chan *to_hisi_dma_chan(struct dma_chan *c)
+{
+	return container_of(c, struct hisi_dma_chan, vc.chan);
+}
+
+static inline struct hisi_dma_desc *to_hisi_dma_desc(struct virt_dma_desc *vd)
+{
+	return container_of(vd, struct hisi_dma_desc, vd);
+}
+
+static inline void hisi_dma_chan_write(void __iomem *base, u32 reg, u32 index,
+				       u32 val)
+{
+	writel_relaxed(val, base + reg + index * HISI_DMA_OFFSET);
+}
+
+static inline void hisi_dma_update_bit(void __iomem *addr, u32 pos, bool val)
+{
+	u32 tmp;
+
+	tmp = readl_relaxed(addr);
+	tmp = val ? tmp | BIT(pos) : tmp & ~BIT(pos);
+	writel_relaxed(tmp, addr);
+}
+
+static void hisi_dma_free_irq_vectors(void *data)
+{
+	pci_free_irq_vectors(data);
+}
+
+static void hisi_dma_pause_dma(struct hisi_dma_dev *hdma_dev, u32 index,
+			       bool pause)
+{
+	void __iomem *addr = hdma_dev->base + HISI_DMA_CTRL0 + index *
+			     HISI_DMA_OFFSET;
+
+	hisi_dma_update_bit(addr, HISI_DMA_CTRL0_QUEUE_PAUSE_S, pause);
+}
+
+static void hisi_dma_enable_dma(struct hisi_dma_dev *hdma_dev, u32 index,
+				bool enable)
+{
+	void __iomem *addr = hdma_dev->base + HISI_DMA_CTRL0 + index *
+			     HISI_DMA_OFFSET;
+
+	hisi_dma_update_bit(addr, HISI_DMA_CTRL0_QUEUE_EN_S, enable);
+}
+
+static void hisi_dma_mask_irq(struct hisi_dma_dev *hdma_dev, u32 qp_index)
+{
+	hisi_dma_chan_write(hdma_dev->base, HISI_DMA_INT_MSK, qp_index,
+			    HISI_DMA_INT_STS_MASK);
+}
+
+static void hisi_dma_unmask_irq(struct hisi_dma_dev *hdma_dev, u32 qp_index)
+{
+	void __iomem *base = hdma_dev->base;
+
+	hisi_dma_chan_write(base, HISI_DMA_INT_STS, qp_index,
+			    HISI_DMA_INT_STS_MASK);
+	hisi_dma_chan_write(base, HISI_DMA_INT_MSK, qp_index, 0);
+}
+
+static void hisi_dma_do_reset(struct hisi_dma_dev *hdma_dev, u32 index)
+{
+	void __iomem *addr = hdma_dev->base + HISI_DMA_CTRL1 + index *
+			     HISI_DMA_OFFSET;
+
+	hisi_dma_update_bit(addr, HISI_DMA_CTRL1_QUEUE_RESET_S, 1);
+}
+
+static void hisi_dma_reset_qp_point(struct hisi_dma_dev *hdma_dev, u32 index)
+{
+	hisi_dma_chan_write(hdma_dev->base, HISI_DMA_SQ_TAIL_PTR, index, 0);
+	hisi_dma_chan_write(hdma_dev->base, HISI_DMA_CQ_HEAD_PTR, index, 0);
+}
+
+static void hisi_dma_reset_hw_chan(struct hisi_dma_chan *chan)
+{
+	struct hisi_dma_dev *hdma_dev = chan->hdma_dev;
+	u32 index = chan->qp_num, tmp;
+	int ret;
+
+	hisi_dma_pause_dma(hdma_dev, index, true);
+	hisi_dma_enable_dma(hdma_dev, index, false);
+	hisi_dma_mask_irq(hdma_dev, index);
+
+	ret = readl_relaxed_poll_timeout(hdma_dev->base +
+		HISI_DMA_Q_FSM_STS + index * HISI_DMA_OFFSET, tmp,
+		FIELD_GET(HISI_DMA_FSM_STS_MASK, tmp) != RUN, 10, 1000);
+	if (ret) {
+		dev_err(&hdma_dev->pdev->dev, "disable channel timeout!\n");
+		WARN_ON(1);
+	}
+
+	hisi_dma_do_reset(hdma_dev, index);
+	hisi_dma_reset_qp_point(hdma_dev, index);
+	hisi_dma_pause_dma(hdma_dev, index, false);
+	hisi_dma_enable_dma(hdma_dev, index, true);
+	hisi_dma_unmask_irq(hdma_dev, index);
+
+	ret = readl_relaxed_poll_timeout(hdma_dev->base +
+		HISI_DMA_Q_FSM_STS + index * HISI_DMA_OFFSET, tmp,
+		FIELD_GET(HISI_DMA_FSM_STS_MASK, tmp) == IDLE, 10, 1000);
+	if (ret) {
+		dev_err(&hdma_dev->pdev->dev, "reset channel timeout!\n");
+		WARN_ON(1);
+	}
+}
+
+static void hisi_dma_free_chan_resources(struct dma_chan *c)
+{
+	struct hisi_dma_chan *chan = to_hisi_dma_chan(c);
+	struct hisi_dma_dev *hdma_dev = chan->hdma_dev;
+
+	hisi_dma_reset_hw_chan(chan);
+	vchan_free_chan_resources(&chan->vc);
+
+	memset(chan->sq, 0, sizeof(struct hisi_dma_sqe) * hdma_dev->chan_depth);
+	memset(chan->cq, 0, sizeof(struct hisi_dma_cqe) * hdma_dev->chan_depth);
+	chan->sq_tail = 0;
+	chan->cq_head = 0;
+	chan->status = DISABLE;
+}
+
+static void hisi_dma_desc_free(struct virt_dma_desc *vd)
+{
+	kfree(to_hisi_dma_desc(vd));
+}
+
+static struct dma_async_tx_descriptor *
+hisi_dma_prep_dma_memcpy(struct dma_chan *c, dma_addr_t dst, dma_addr_t src,
+			 size_t len, unsigned long flags)
+{
+	struct hisi_dma_chan *chan = to_hisi_dma_chan(c);
+	struct hisi_dma_desc *desc;
+
+	desc = kzalloc(sizeof(*desc), GFP_NOWAIT);
+	if (!desc)
+		return NULL;
+
+	desc->sqe.length = cpu_to_le32(len);
+	desc->sqe.src_addr = cpu_to_le64(src);
+	desc->sqe.dst_addr = cpu_to_le64(dst);
+
+	return vchan_tx_prep(&chan->vc, &desc->vd, flags);
+}
+
+static enum dma_status
+hisi_dma_tx_status(struct dma_chan *c, dma_cookie_t cookie,
+		   struct dma_tx_state *txstate)
+{
+	return dma_cookie_status(c, cookie, txstate);
+}
+
+static void hisi_dma_start_transfer(struct hisi_dma_chan *chan)
+{
+	struct hisi_dma_sqe *sqe = chan->sq + chan->sq_tail;
+	struct hisi_dma_dev *hdma_dev = chan->hdma_dev;
+	struct hisi_dma_desc *desc;
+	struct virt_dma_desc *vd;
+
+	vd = vchan_next_desc(&chan->vc);
+	if (!vd) {
+		dev_err(&hdma_dev->pdev->dev, "no issued task!\n");
+		chan->desc = NULL;
+		return;
+	}
+	list_del(&vd->node);
+	desc = to_hisi_dma_desc(vd);
+	chan->desc = desc;
+
+	memcpy(sqe, &desc->sqe, sizeof(struct hisi_dma_sqe));
+
+	/* update other field in sqe */
+	sqe->dw0 = cpu_to_le32(FIELD_PREP(OPCODE_MASK, OPCODE_M2M));
+	sqe->dw0 |= cpu_to_le32(LOCAL_IRQ_EN);
+
+	/* make sure data has been updated in sqe */
+	wmb();
+
+	/* update sq tail, point to new sqe position */
+	chan->sq_tail = (chan->sq_tail + 1) % hdma_dev->chan_depth;
+
+	/* update sq_tail to trigger a new task */
+	hisi_dma_chan_write(hdma_dev->base, HISI_DMA_SQ_TAIL_PTR, chan->qp_num,
+			    chan->sq_tail);
+}
+
+static void hisi_dma_issue_pending(struct dma_chan *c)
+{
+	struct hisi_dma_chan *chan = to_hisi_dma_chan(c);
+	unsigned long flags;
+
+	spin_lock_irqsave(&chan->vc.lock, flags);
+
+	if (vchan_issue_pending(&chan->vc))
+		hisi_dma_start_transfer(chan);
+
+	spin_unlock_irqrestore(&chan->vc.lock, flags);
+}
+
+static int hisi_dma_terminate_all(struct dma_chan *c)
+{
+	struct hisi_dma_chan *chan = to_hisi_dma_chan(c);
+	unsigned long flags;
+	LIST_HEAD(head);
+
+	spin_lock_irqsave(&chan->vc.lock, flags);
+
+	hisi_dma_pause_dma(chan->hdma_dev, chan->qp_num, true);
+	if (chan->desc) {
+		vchan_terminate_vdesc(&chan->desc->vd);
+		chan->desc = NULL;
+	}
+
+	vchan_get_all_descriptors(&chan->vc, &head);
+
+	spin_unlock_irqrestore(&chan->vc.lock, flags);
+
+	vchan_dma_desc_free_list(&chan->vc, &head);
+	hisi_dma_pause_dma(chan->hdma_dev, chan->qp_num, false);
+
+	return 0;
+}
+
+static void hisi_dma_synchronize(struct dma_chan *c)
+{
+	struct hisi_dma_chan *chan = to_hisi_dma_chan(c);
+
+	vchan_synchronize(&chan->vc);
+}
+
+static int hisi_dma_alloc_qps_mem(struct hisi_dma_dev *hdma_dev)
+{
+	size_t sq_size = sizeof(struct hisi_dma_sqe) * hdma_dev->chan_depth;
+	size_t cq_size = sizeof(struct hisi_dma_cqe) * hdma_dev->chan_depth;
+	struct device *dev = &hdma_dev->pdev->dev;
+	struct hisi_dma_chan *chan;
+	int i;
+
+	for (i = 0; i < hdma_dev->chan_num; i++) {
+		chan = &hdma_dev->chan[i];
+		chan->sq = dmam_alloc_coherent(dev, sq_size, &chan->sq_dma,
+					       GFP_KERNEL);
+		if (!chan->sq)
+			return -ENOMEM;
+
+		chan->cq = dmam_alloc_coherent(dev, cq_size, &chan->cq_dma,
+					       GFP_KERNEL);
+		if (!chan->cq)
+			return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void hisi_dma_init_hw_qp(struct hisi_dma_dev *hdma_dev, u32 index)
+{
+	struct hisi_dma_chan *chan = &hdma_dev->chan[index];
+	u32 hw_depth = hdma_dev->chan_depth - 1;
+	void __iomem *base = hdma_dev->base;
+
+	/* set sq, cq base */
+	hisi_dma_chan_write(base, HISI_DMA_SQ_BASE_L, index,
+			    lower_32_bits(chan->sq_dma));
+	hisi_dma_chan_write(base, HISI_DMA_SQ_BASE_H, index,
+			    upper_32_bits(chan->sq_dma));
+	hisi_dma_chan_write(base, HISI_DMA_CQ_BASE_L, index,
+			    lower_32_bits(chan->cq_dma));
+	hisi_dma_chan_write(base, HISI_DMA_CQ_BASE_H, index,
+			    upper_32_bits(chan->cq_dma));
+
+	/* set sq, cq depth */
+	hisi_dma_chan_write(base, HISI_DMA_SQ_DEPTH, index, hw_depth);
+	hisi_dma_chan_write(base, HISI_DMA_CQ_DEPTH, index, hw_depth);
+
+	/* init sq tail and cq head */
+	hisi_dma_chan_write(base, HISI_DMA_SQ_TAIL_PTR, index, 0);
+	hisi_dma_chan_write(base, HISI_DMA_CQ_HEAD_PTR, index, 0);
+}
+
+static void hisi_dma_enable_qp(struct hisi_dma_dev *hdma_dev, u32 qp_index)
+{
+	hisi_dma_init_hw_qp(hdma_dev, qp_index);
+	hisi_dma_unmask_irq(hdma_dev, qp_index);
+	hisi_dma_enable_dma(hdma_dev, qp_index, true);
+}
+
+static void hisi_dma_disable_qp(struct hisi_dma_dev *hdma_dev, u32 qp_index)
+{
+	hisi_dma_reset_hw_chan(&hdma_dev->chan[qp_index]);
+}
+
+static void hisi_dma_enable_qps(struct hisi_dma_dev *hdma_dev)
+{
+	int i;
+
+	for (i = 0; i < hdma_dev->chan_num; i++) {
+		hdma_dev->chan[i].qp_num = i;
+		hdma_dev->chan[i].hdma_dev = hdma_dev;
+		hdma_dev->chan[i].vc.desc_free = hisi_dma_desc_free;
+		vchan_init(&hdma_dev->chan[i].vc, &hdma_dev->dma_dev);
+		hisi_dma_enable_qp(hdma_dev, i);
+	}
+}
+
+static void hisi_dma_disable_qps(struct hisi_dma_dev *hdma_dev)
+{
+	int i;
+
+	for (i = 0; i < hdma_dev->chan_num; i++) {
+		hisi_dma_disable_qp(hdma_dev, i);
+		tasklet_kill(&hdma_dev->chan[i].vc.task);
+	}
+}
+
+static irqreturn_t hisi_dma_irq(int irq, void *data)
+{
+	struct hisi_dma_chan *chan = data;
+	struct hisi_dma_dev *hdma_dev = chan->hdma_dev;
+	struct hisi_dma_desc *desc;
+	struct hisi_dma_cqe *cqe;
+	unsigned long flags;
+
+	spin_lock_irqsave(&chan->vc.lock, flags);
+
+	desc = chan->desc;
+	cqe = chan->cq + chan->cq_head;
+	if (desc) {
+		if (FIELD_GET(STATUS_MASK, cqe->w0) == STATUS_SUCC) {
+			chan->cq_head = (chan->cq_head + 1) %
+					hdma_dev->chan_depth;
+			hisi_dma_chan_write(hdma_dev->base,
+					    HISI_DMA_CQ_HEAD_PTR, chan->qp_num,
+					    chan->cq_head);
+			vchan_cookie_complete(&desc->vd);
+		} else {
+			dev_err(&hdma_dev->pdev->dev, "task error!\n");
+		}
+
+		chan->desc = NULL;
+	}
+
+	spin_unlock_irqrestore(&chan->vc.lock, flags);
+
+	return IRQ_HANDLED;
+}
+
+static int hisi_dma_request_qps_irq(struct hisi_dma_dev *hdma_dev)
+{
+	struct pci_dev *pdev = hdma_dev->pdev;
+	int i, ret;
+
+	for (i = 0; i < hdma_dev->chan_num; i++) {
+		ret = devm_request_irq(&pdev->dev, pci_irq_vector(pdev, i),
+				       hisi_dma_irq, IRQF_SHARED, "hisi_dma",
+				       &hdma_dev->chan[i]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+/* This function enables all hw channels in a device */
+static int hisi_dma_enable_hw_channels(struct hisi_dma_dev *hdma_dev)
+{
+	int ret;
+
+	ret = hisi_dma_alloc_qps_mem(hdma_dev);
+	if (ret) {
+		dev_err(&hdma_dev->pdev->dev, "fail to allocate qp memory!\n");
+		return ret;
+	}
+
+	ret = hisi_dma_request_qps_irq(hdma_dev);
+	if (ret) {
+		dev_err(&hdma_dev->pdev->dev, "fail to request qp irq!\n");
+		return ret;
+	}
+
+	hisi_dma_enable_qps(hdma_dev);
+
+	return 0;
+}
+
+static void hisi_dma_disable_hw_channels(void *data)
+{
+	hisi_dma_disable_qps(data);
+}
+
+static void hisi_dma_set_mode(struct hisi_dma_dev *hdma_dev,
+			      enum hisi_dma_mode mode)
+{
+	writel_relaxed(mode == RC ? 1 : 0, hdma_dev->base + HISI_DMA_MODE);
+}
+
+static int hisi_dma_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	struct device *dev = &pdev->dev;
+	struct hisi_dma_dev *hdma_dev;
+	struct dma_device *dma_dev;
+	size_t dev_size;
+	int ret;
+
+	ret = pcim_enable_device(pdev);
+	if (ret) {
+		dev_err(dev, "failed to enable device mem!\n");
+		return ret;
+	}
+
+	ret = pcim_iomap_regions(pdev, 1 << PCI_BAR_2, pci_name(pdev));
+	if (ret) {
+		dev_err(dev, "failed to remap I/O region!\n");
+		return ret;
+	}
+
+	ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
+	if (ret)
+		return ret;
+
+	ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
+	if (ret)
+		return ret;
+
+	dev_size = sizeof(struct hisi_dma_chan) * HISI_DMA_CHAN_NUM +
+		   sizeof(*hdma_dev);
+	hdma_dev = devm_kzalloc(dev, dev_size, GFP_KERNEL);
+	if (!hdma_dev)
+		return -EINVAL;
+
+	hdma_dev->base = pcim_iomap_table(pdev)[PCI_BAR_2];
+	hdma_dev->pdev = pdev;
+	hdma_dev->chan_num = HISI_DMA_CHAN_NUM;
+	hdma_dev->chan_depth = HISI_DMA_Q_DEPTH_VAL;
+
+	pci_set_drvdata(pdev, hdma_dev);
+	pci_set_master(pdev);
+
+	ret = pci_alloc_irq_vectors(pdev, HISI_DMA_MSI_NUM, HISI_DMA_MSI_NUM,
+				    PCI_IRQ_MSI);
+	if (ret < 0) {
+		dev_err(dev, "Failed to allocate MSI vectors!\n");
+		return ret;
+	}
+
+	ret = devm_add_action_or_reset(dev, hisi_dma_free_irq_vectors, pdev);
+	if (ret)
+		return ret;
+
+	dma_dev = &hdma_dev->dma_dev;
+	dma_cap_set(DMA_MEMCPY, dma_dev->cap_mask);
+	dma_dev->device_free_chan_resources = hisi_dma_free_chan_resources;
+	dma_dev->device_prep_dma_memcpy = hisi_dma_prep_dma_memcpy;
+	dma_dev->device_tx_status = hisi_dma_tx_status;
+	dma_dev->device_issue_pending = hisi_dma_issue_pending;
+	dma_dev->device_terminate_all = hisi_dma_terminate_all;
+	dma_dev->device_synchronize = hisi_dma_synchronize;
+	dma_dev->directions = BIT(DMA_MEM_TO_MEM);
+	dma_dev->dev = dev;
+	INIT_LIST_HEAD(&dma_dev->channels);
+
+	hisi_dma_set_mode(hdma_dev, RC);
+
+	ret = hisi_dma_enable_hw_channels(hdma_dev);
+	if (ret < 0) {
+		dev_err(dev, "failed to enable hw channel!\n");
+		return ret;
+	}
+
+	ret = devm_add_action_or_reset(dev, hisi_dma_disable_hw_channels,
+				       hdma_dev);
+	if (ret)
+		return ret;
+
+	ret = dmaenginem_async_device_register(dma_dev);
+	if (ret < 0)
+		dev_err(dev, "failed to register device!\n");
+
+	return ret;
+}
+
+static const struct pci_device_id hisi_dma_pci_tbl[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_HUAWEI, 0xa122) },
+	{ 0, }
+};
+
+static struct pci_driver hisi_dma_pci_driver = {
+	.name		= "hisi_dma",
+	.id_table	= hisi_dma_pci_tbl,
+	.probe		= hisi_dma_probe,
+};
+
+module_pci_driver(hisi_dma_pci_driver);
+
+MODULE_AUTHOR("Zhou Wang <wangzhou1@hisilicon.com>");
+MODULE_AUTHOR("Zhenfa Qiu <qiuzhenfa@hisilicon.com>");
+MODULE_DESCRIPTION("HiSilicon Kunpeng DMA controller driver");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(pci, hisi_dma_pci_tbl);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/hsu/pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/hsu/pci.c
@@ -26,22 +26,12 @@
 static irqreturn_t hsu_pci_irq(int irq, void *dev)
 {
 	struct hsu_dma_chip *chip = dev;
-	struct pci_dev *pdev = to_pci_dev(chip->dev);
 	u32 dmaisr;
 	u32 status;
 	unsigned short i;
 	int ret = 0;
 	int err;
 
-	/*
-	 * On Intel Tangier B0 and Anniedale the interrupt line, disregarding
-	 * to have different numbers, is shared between HSU DMA and UART IPs.
-	 * Thus on such SoCs we are expecting that IRQ handler is called in
-	 * UART driver only.
-	 */
-	if (pdev->device == PCI_DEVICE_ID_INTEL_MRFLD_HSU_DMA)
-		return IRQ_HANDLED;
-
 	dmaisr = readl(chip->regs + HSU_PCI_DMAISR);
 	for (i = 0; i < chip->hsu->nr_channels; i++) {
 		if (dmaisr & 0x1) {
@@ -105,6 +95,17 @@
 	if (ret)
 		goto err_register_irq;
 
+	/*
+	 * On Intel Tangier B0 and Anniedale the interrupt line, disregarding
+	 * to have different numbers, is shared between HSU DMA and UART IPs.
+	 * Thus on such SoCs we are expecting that IRQ handler is called in
+	 * UART driver only. Instead of handling the spurious interrupt
+	 * from HSU DMA here and waste CPU time and delay HSU UART interrupt
+	 * handling, disable the interrupt entirely.
+	 */
+	if (pdev->device == PCI_DEVICE_ID_INTEL_MRFLD_HSU_DMA)
+		disable_irq_nosync(chip->irq);
+
 	pci_set_drvdata(pdev, chip);
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/idma64.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/idma64.c
@@ -167,6 +167,10 @@
 	u32 status_err;
 	unsigned short i;
 
+	/* Since IRQ may be shared, check if DMA controller is powered on */
+	if (status == GENMASK(31, 0))
+		return IRQ_NONE;
+
 	dev_vdbg(idma64->dma.dev, "%s: status=%#x\n", __func__, status);
 
 	/* Check if we have any interrupt from the DMA controller */
@@ -590,7 +594,9 @@
 
 	idma64->dma.dev = chip->sysdev;
 
-	dma_set_max_seg_size(idma64->dma.dev, IDMA64C_CTLH_BLOCK_TS_MASK);
+	ret = dma_set_max_seg_size(idma64->dma.dev, IDMA64C_CTLH_BLOCK_TS_MASK);
+	if (ret)
+		return ret;
 
 	ret = dma_async_device_register(&idma64->dma);
 	if (ret)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/imx-dma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/imx-dma.c
@@ -832,6 +832,8 @@
 		dma_length += sg_dma_len(sg);
 	}
 
+	imxdma_config_write(chan, &imxdmac->config, direction);
+
 	switch (imxdmac->word_size) {
 	case DMA_SLAVE_BUSWIDTH_4_BYTES:
 		if (sg_dma_len(sgl) & 3 || sgl->dma_address & 3)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/imx-sdma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/imx-sdma.c
@@ -377,7 +377,6 @@
 	unsigned long			watermark_level;
 	u32				shp_addr, per_addr;
 	enum dma_status			status;
-	bool				context_loaded;
 	struct imx_dma_data		data;
 	struct work_struct		terminate_worker;
 };
@@ -988,9 +987,6 @@
 	int ret;
 	unsigned long flags;
 
-	if (sdmac->context_loaded)
-		return 0;
-
 	if (sdmac->direction == DMA_DEV_TO_MEM)
 		load_address = sdmac->pc_from_device;
 	else if (sdmac->direction == DMA_DEV_TO_DEV)
@@ -1033,8 +1029,6 @@
 
 	spin_unlock_irqrestore(&sdma->channel_0_lock, flags);
 
-	sdmac->context_loaded = true;
-
 	return ret;
 }
 
@@ -1074,7 +1068,6 @@
 	sdmac->desc = NULL;
 	spin_unlock_irqrestore(&sdmac->vc.lock, flags);
 	vchan_dma_desc_free_list(&sdmac->vc, &head);
-	sdmac->context_loaded = false;
 }
 
 static int sdma_disable_channel_async(struct dma_chan *chan)
@@ -1141,7 +1134,6 @@
 static int sdma_config_channel(struct dma_chan *chan)
 {
 	struct sdma_channel *sdmac = to_sdma_chan(chan);
-	int ret;
 
 	sdma_disable_channel(chan);
 
@@ -1181,9 +1173,7 @@
 		sdmac->watermark_level = 0; /* FIXME: M3_BASE_ADDRESS */
 	}
 
-	ret = sdma_load_context(sdmac);
-
-	return ret;
+	return 0;
 }
 
 static int sdma_set_channel_priority(struct sdma_channel *sdmac,
@@ -1328,7 +1318,7 @@
 
 	sdma_channel_synchronize(chan);
 
-	if (sdmac->event_id0)
+	if (sdmac->event_id0 >= 0)
 		sdma_event_disable(sdmac, sdmac->event_id0);
 	if (sdmac->event_id1)
 		sdma_event_disable(sdmac, sdmac->event_id1);
@@ -1370,10 +1360,12 @@
 		sdma_config_ownership(sdmac, false, true, false);
 
 	if (sdma_load_context(sdmac))
-		goto err_desc_out;
+		goto err_bd_out;
 
 	return desc;
 
+err_bd_out:
+	sdma_free_bd(desc);
 err_desc_out:
 	kfree(desc);
 err_out:
@@ -1628,7 +1620,7 @@
 	memcpy(&sdmac->slave_config, dmaengine_cfg, sizeof(*dmaengine_cfg));
 
 	/* Set ENBLn earlier to make sure dma request triggered after that */
-	if (sdmac->event_id0) {
+	if (sdmac->event_id0 >= 0) {
 		if (sdmac->event_id0 >= sdmac->sdma->drvdata->num_events)
 			return -EINVAL;
 		sdma_event_enable(sdmac, sdmac->event_id0);
@@ -1794,7 +1786,7 @@
 	u32 reg, val, shift, num_map, i;
 	int ret = 0;
 
-	if (IS_ERR(np) || IS_ERR(gpr_np))
+	if (IS_ERR(np) || !gpr_np)
 		goto out;
 
 	event_remap = of_find_property(np, propname, NULL);
@@ -1842,7 +1834,7 @@
 	}
 
 out:
-	if (!IS_ERR(gpr_np))
+	if (gpr_np)
 		of_node_put(gpr_np);
 
 	return ret;
@@ -2218,7 +2210,7 @@
 #if IS_ENABLED(CONFIG_SOC_IMX6Q)
 MODULE_FIRMWARE("imx/sdma/sdma-imx6q.bin");
 #endif
-#if IS_ENABLED(CONFIG_SOC_IMX7D)
+#if IS_ENABLED(CONFIG_SOC_IMX7D) || IS_ENABLED(CONFIG_SOC_IMX8M)
 MODULE_FIRMWARE("imx/sdma/sdma-imx7d.bin");
 #endif
 MODULE_LICENSE("GPL");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/ioat/dma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/ioat/dma.c
@@ -26,6 +26,18 @@
 
 #include "../dmaengine.h"
 
+int completion_timeout = 200;
+module_param(completion_timeout, int, 0644);
+MODULE_PARM_DESC(completion_timeout,
+		"set ioat completion timeout [msec] (default 200 [msec])");
+int idle_timeout = 2000;
+module_param(idle_timeout, int, 0644);
+MODULE_PARM_DESC(idle_timeout,
+		"set ioat idel timeout [msec] (default 2000 [msec])");
+
+#define IDLE_TIMEOUT msecs_to_jiffies(idle_timeout)
+#define COMPLETION_TIMEOUT msecs_to_jiffies(completion_timeout)
+
 static char *chanerr_str[] = {
 	"DMA Transfer Source Address Error",
 	"DMA Transfer Destination Address Error",
@@ -377,10 +389,11 @@
 
 		descs->virt = dma_alloc_coherent(to_dev(ioat_chan),
 						 SZ_2M, &descs->hw, flags);
-		if (!descs->virt && (i > 0)) {
+		if (!descs->virt) {
 			int idx;
 
 			for (idx = 0; idx < i; idx++) {
+				descs = &ioat_chan->descs[idx];
 				dma_free_coherent(to_dev(ioat_chan), SZ_2M,
 						  descs->virt, descs->hw);
 				descs->virt = NULL;
@@ -640,7 +653,7 @@
 	if (active - i == 0) {
 		dev_dbg(to_dev(ioat_chan), "%s: cancel completion timeout\n",
 			__func__);
-		mod_timer(&ioat_chan->timer, jiffies + IDLE_TIMEOUT);
+		mod_timer_pending(&ioat_chan->timer, jiffies + IDLE_TIMEOUT);
 	}
 
 	/* microsecond delay by sysfs variable  per pending descriptor */
@@ -666,7 +679,7 @@
 
 		if (chanerr &
 		    (IOAT_CHANERR_HANDLE_MASK | IOAT_CHANERR_RECOVER_MASK)) {
-			mod_timer(&ioat_chan->timer, jiffies + IDLE_TIMEOUT);
+			mod_timer_pending(&ioat_chan->timer, jiffies + IDLE_TIMEOUT);
 			ioat_eh(ioat_chan);
 		}
 	}
@@ -863,7 +876,7 @@
 	}
 
 	if (test_and_clear_bit(IOAT_CHAN_ACTIVE, &ioat_chan->state))
-		mod_timer(&ioat_chan->timer, jiffies + IDLE_TIMEOUT);
+		mod_timer_pending(&ioat_chan->timer, jiffies + IDLE_TIMEOUT);
 }
 
 void ioat_timer_event(struct timer_list *t)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/ioat/dma.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/ioat/dma.h
@@ -99,8 +99,6 @@
 	#define IOAT_RUN 5
 	#define IOAT_CHAN_ACTIVE 6
 	struct timer_list timer;
-	#define COMPLETION_TIMEOUT msecs_to_jiffies(100)
-	#define IDLE_TIMEOUT msecs_to_jiffies(2000)
 	#define RESET_DELAY msecs_to_jiffies(100)
 	struct ioatdma_device *ioat_dma;
 	dma_addr_t completion_dma;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/ioat/init.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/ioat/init.c
@@ -1446,6 +1446,7 @@
 static void __exit ioat_exit_module(void)
 {
 	pci_unregister_driver(&ioat_pci_driver);
+	kmem_cache_destroy(ioat_sed_cache);
 	kmem_cache_destroy(ioat_cache);
 }
 module_exit(ioat_exit_module);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/k3dma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/k3dma.c
@@ -229,9 +229,11 @@
 			c = p->vchan;
 			if (c && (tc1 & BIT(i))) {
 				spin_lock_irqsave(&c->vc.lock, flags);
-				vchan_cookie_complete(&p->ds_run->vd);
-				p->ds_done = p->ds_run;
-				p->ds_run = NULL;
+				if (p->ds_run != NULL) {
+					vchan_cookie_complete(&p->ds_run->vd);
+					p->ds_done = p->ds_run;
+					p->ds_run = NULL;
+				}
 				spin_unlock_irqrestore(&c->vc.lock, flags);
 			}
 			if (c && (tc2 & BIT(i))) {
@@ -271,6 +273,10 @@
 	if (BIT(c->phy->idx) & k3_dma_get_chan_stat(d))
 		return -EAGAIN;
 
+	/* Avoid losing track of  ds_run if a transaction is in flight */
+	if (c->phy->ds_run)
+		return -EAGAIN;
+
 	if (vd) {
 		struct k3_dma_desc_sw *ds =
 			container_of(vd, struct k3_dma_desc_sw, vd);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/mcf-edma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/mcf-edma.c
@@ -35,6 +35,13 @@
 			mcf_chan = &mcf_edma->chans[ch];
 
 			spin_lock(&mcf_chan->vchan.lock);
+
+			if (!mcf_chan->edesc) {
+				/* terminate_all called before */
+				spin_unlock(&mcf_chan->vchan.lock);
+				continue;
+			}
+
 			if (!mcf_chan->edesc->iscyclic) {
 				list_del(&mcf_chan->edesc->vdesc.node);
 				vchan_cookie_complete(&mcf_chan->edesc->vdesc);
@@ -184,7 +191,13 @@
 		return -EINVAL;
 	}
 
-	chans = pdata->dma_channels;
+	if (!pdata->dma_channels) {
+		dev_info(&pdev->dev, "setting default channel number to 64");
+		chans = 64;
+	} else {
+		chans = pdata->dma_channels;
+	}
+
 	len = sizeof(*mcf_edma) + sizeof(*mcf_chan) * chans;
 	mcf_edma = devm_kzalloc(&pdev->dev, len, GFP_KERNEL);
 	if (!mcf_edma)
@@ -196,11 +209,6 @@
 	mcf_edma->drvdata = &mcf_data;
 	mcf_edma->big_endian = 1;
 
-	if (!mcf_edma->n_chans) {
-		dev_info(&pdev->dev, "setting default channel number to 64");
-		mcf_edma->n_chans = 64;
-	}
-
 	mutex_init(&mcf_edma->fsl_edma_mutex);
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/mediatek/mtk-hsdma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/mediatek/mtk-hsdma.c
@@ -997,7 +997,7 @@
 	if (err) {
 		dev_err(&pdev->dev,
 			"request_irq failed with err %d\n", err);
-		goto err_unregister;
+		goto err_free;
 	}
 
 	platform_set_drvdata(pdev, hsdma);
@@ -1006,6 +1006,9 @@
 
 	return 0;
 
+err_free:
+	mtk_hsdma_hw_deinit(hsdma);
+	of_dma_controller_free(pdev->dev.of_node);
 err_unregister:
 	dma_async_device_unregister(dd);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/mediatek/mtk-uart-apdma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/mediatek/mtk-uart-apdma.c
@@ -131,10 +131,7 @@
 
 static void mtk_uart_apdma_desc_free(struct virt_dma_desc *vd)
 {
-	struct dma_chan *chan = vd->tx.chan;
-	struct mtk_chan *c = to_mtk_uart_apdma_chan(chan);
-
-	kfree(c->desc);
+	kfree(container_of(vd, struct mtk_uart_apdma_desc, vd));
 }
 
 static void mtk_uart_apdma_start_tx(struct mtk_chan *c)
@@ -207,14 +204,9 @@
 
 static void mtk_uart_apdma_tx_handler(struct mtk_chan *c)
 {
-	struct mtk_uart_apdma_desc *d = c->desc;
-
 	mtk_uart_apdma_write(c, VFF_INT_FLAG, VFF_TX_INT_CLR_B);
 	mtk_uart_apdma_write(c, VFF_INT_EN, VFF_INT_EN_CLR_B);
 	mtk_uart_apdma_write(c, VFF_EN, VFF_EN_CLR_B);
-
-	list_del(&d->vd.node);
-	vchan_cookie_complete(&d->vd);
 }
 
 static void mtk_uart_apdma_rx_handler(struct mtk_chan *c)
@@ -245,9 +237,17 @@
 
 	c->rx_status = d->avail_len - cnt;
 	mtk_uart_apdma_write(c, VFF_RPT, wg);
+}
+
+static void mtk_uart_apdma_chan_complete_handler(struct mtk_chan *c)
+{
+	struct mtk_uart_apdma_desc *d = c->desc;
 
-	list_del(&d->vd.node);
-	vchan_cookie_complete(&d->vd);
+	if (d) {
+		list_del(&d->vd.node);
+		vchan_cookie_complete(&d->vd);
+		c->desc = NULL;
+	}
 }
 
 static irqreturn_t mtk_uart_apdma_irq_handler(int irq, void *dev_id)
@@ -261,6 +261,7 @@
 		mtk_uart_apdma_rx_handler(c);
 	else if (c->dir == DMA_MEM_TO_DEV)
 		mtk_uart_apdma_tx_handler(c);
+	mtk_uart_apdma_chan_complete_handler(c);
 	spin_unlock_irqrestore(&c->vc.lock, flags);
 
 	return IRQ_HANDLED;
@@ -273,7 +274,7 @@
 	unsigned int status;
 	int ret;
 
-	ret = pm_runtime_get_sync(mtkd->ddev.dev);
+	ret = pm_runtime_resume_and_get(mtkd->ddev.dev);
 	if (ret < 0) {
 		pm_runtime_put_noidle(chan->device->dev);
 		return ret;
@@ -287,18 +288,21 @@
 	ret = readx_poll_timeout(readl, c->base + VFF_EN,
 			  status, !status, 10, 100);
 	if (ret)
-		return ret;
+		goto err_pm;
 
 	ret = request_irq(c->irq, mtk_uart_apdma_irq_handler,
 			  IRQF_TRIGGER_NONE, KBUILD_MODNAME, chan);
 	if (ret < 0) {
 		dev_err(chan->device->dev, "Can't request dma IRQ\n");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto err_pm;
 	}
 
 	if (mtkd->support_33bits)
 		mtk_uart_apdma_write(c, VFF_4G_SUPPORT, VFF_4G_SUPPORT_CLR_B);
 
+err_pm:
+	pm_runtime_put_noidle(mtkd->ddev.dev);
 	return ret;
 }
 
@@ -348,7 +352,7 @@
 		return NULL;
 
 	/* Now allocate and setup the descriptor */
-	d = kzalloc(sizeof(*d), GFP_ATOMIC);
+	d = kzalloc(sizeof(*d), GFP_NOWAIT);
 	if (!d)
 		return NULL;
 
@@ -366,7 +370,7 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&c->vc.lock, flags);
-	if (vchan_issue_pending(&c->vc)) {
+	if (vchan_issue_pending(&c->vc) && !c->desc) {
 		vd = vchan_next_desc(&c->vc);
 		c->desc = to_mtk_uart_apdma_desc(&vd->tx);
 
@@ -446,9 +450,8 @@
 	mtk_uart_apdma_write(c, VFF_EN, VFF_EN_CLR_B);
 	mtk_uart_apdma_write(c, VFF_INT_EN, VFF_INT_EN_CLR_B);
 
-	synchronize_irq(c->irq);
-
 	spin_unlock_irqrestore(&c->vc.lock, flags);
+	synchronize_irq(c->irq);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/mmp_pdma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/mmp_pdma.c
@@ -728,12 +728,6 @@
 
 	chan->dir = direction;
 	chan->dev_addr = addr;
-	/* FIXME: drivers should be ported over to use the filter
-	 * function. Once that's done, the following two lines can
-	 * be removed.
-	 */
-	if (cfg->slave_id)
-		chan->drcmr = cfg->slave_id;
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/mmp_tdma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/mmp_tdma.c
@@ -363,6 +363,8 @@
 		gen_pool_free(gpool, (unsigned long)tdmac->desc_arr,
 				size);
 	tdmac->desc_arr = NULL;
+	if (tdmac->status == DMA_ERROR)
+		tdmac->status = DMA_COMPLETE;
 
 	return;
 }
@@ -443,7 +445,8 @@
 	if (!desc)
 		goto err_out;
 
-	mmp_tdma_config_write(chan, direction, &tdmac->slave_config);
+	if (mmp_tdma_config_write(chan, direction, &tdmac->slave_config))
+		goto err_out;
 
 	while (buf < buf_len) {
 		desc = &tdmac->desc_arr[i];
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/mv_xor.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/mv_xor.c
@@ -1394,6 +1394,7 @@
 			irq = irq_of_parse_and_map(np, 0);
 			if (!irq) {
 				ret = -ENODEV;
+				of_node_put(np);
 				goto err_channel_add;
 			}
 
@@ -1402,6 +1403,7 @@
 			if (IS_ERR(chan)) {
 				ret = PTR_ERR(chan);
 				irq_dispose_mapping(irq);
+				of_node_put(np);
 				goto err_channel_add;
 			}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/mv_xor_v2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/mv_xor_v2.c
@@ -751,7 +751,7 @@
 
 	xor_dev->clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(xor_dev->clk) && PTR_ERR(xor_dev->clk) == -EPROBE_DEFER) {
-		ret = EPROBE_DEFER;
+		ret = -EPROBE_DEFER;
 		goto disable_reg_clk;
 	}
 	if (!IS_ERR(xor_dev->clk)) {
@@ -766,8 +766,10 @@
 		goto disable_clk;
 
 	msi_desc = first_msi_entry(&pdev->dev);
-	if (!msi_desc)
+	if (!msi_desc) {
+		ret = -ENODEV;
 		goto free_msi_irqs;
+	}
 	xor_dev->msi_desc = msi_desc;
 
 	ret = devm_request_irq(&pdev->dev, msi_desc->irq,
@@ -893,6 +895,7 @@
 	tasklet_kill(&xor_dev->irq_tasklet);
 
 	clk_disable_unprepare(xor_dev->clk);
+	clk_disable_unprepare(xor_dev->reg_clk);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/of-dma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/of-dma.c
@@ -65,18 +65,23 @@
 		return NULL;
 
 	ofdma_target = of_dma_find_controller(&dma_spec_target);
-	if (!ofdma_target)
-		return NULL;
+	if (!ofdma_target) {
+		ofdma->dma_router->route_free(ofdma->dma_router->dev,
+					      route_data);
+		chan = ERR_PTR(-EPROBE_DEFER);
+		goto err;
+	}
 
 	chan = ofdma_target->of_dma_xlate(&dma_spec_target, ofdma_target);
-	if (chan) {
-		chan->router = ofdma->dma_router;
-		chan->route_data = route_data;
-	} else {
+	if (IS_ERR_OR_NULL(chan)) {
 		ofdma->dma_router->route_free(ofdma->dma_router->dev,
 					      route_data);
+	} else {
+		chan->router = ofdma->dma_router;
+		chan->route_data = route_data;
 	}
 
+err:
 	/*
 	 * Need to put the node back since the ofdma->of_dma_route_allocate
 	 * has taken it for generating the new, translated dma_spec
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/owl-dma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/owl-dma.c
@@ -175,13 +175,11 @@
  * @id: physical index to this channel
  * @base: virtual memory base for the dma channel
  * @vchan: the virtual channel currently being served by this physical channel
- * @lock: a lock to use when altering an instance of this struct
  */
 struct owl_dma_pchan {
 	u32			id;
 	void __iomem		*base;
 	struct owl_dma_vchan	*vchan;
-	spinlock_t		lock;
 };
 
 /**
@@ -240,7 +238,7 @@
 	else
 		regval &= ~val;
 
-	writel(val, pchan->base + reg);
+	writel(regval, pchan->base + reg);
 }
 
 static void pchan_writel(struct owl_dma_pchan *pchan, u32 reg, u32 data)
@@ -264,7 +262,7 @@
 	else
 		regval &= ~val;
 
-	writel(val, od->base + reg);
+	writel(regval, od->base + reg);
 }
 
 static void dma_writel(struct owl_dma *od, u32 reg, u32 data)
@@ -437,14 +435,14 @@
 	for (i = 0; i < od->nr_pchans; i++) {
 		pchan = &od->pchans[i];
 
-		spin_lock_irqsave(&pchan->lock, flags);
+		spin_lock_irqsave(&od->lock, flags);
 		if (!pchan->vchan) {
 			pchan->vchan = vchan;
-			spin_unlock_irqrestore(&pchan->lock, flags);
+			spin_unlock_irqrestore(&od->lock, flags);
 			break;
 		}
 
-		spin_unlock_irqrestore(&pchan->lock, flags);
+		spin_unlock_irqrestore(&od->lock, flags);
 	}
 
 	return pchan;
@@ -1203,6 +1201,7 @@
 	owl_dma_free(od);
 
 	clk_disable_unprepare(od->clk);
+	dma_pool_destroy(od->lli_pool);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/pch_dma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/pch_dma.c
@@ -865,6 +865,7 @@
 	}
 
 	pci_set_master(pdev);
+	pd->dma.dev = &pdev->dev;
 
 	err = request_irq(pdev->irq, pd_irq, IRQF_SHARED, DRV_NAME, pd);
 	if (err) {
@@ -880,7 +881,6 @@
 		goto err_free_irq;
 	}
 
-	pd->dma.dev = &pdev->dev;
 
 	INIT_LIST_HEAD(&pd->dma.channels);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/pl330.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/pl330.c
@@ -403,6 +403,12 @@
 	 */
 	BUSY,
 	/*
+	 * Pause was called while descriptor was BUSY. Due to hardware
+	 * limitations, only termination is possible for descriptors
+	 * that have been paused.
+	 */
+	PAUSED,
+	/*
 	 * Sitting on the channel work_list but xfer done
 	 * by PL330 core
 	 */
@@ -1048,7 +1054,7 @@
 	return true;
 }
 
-static bool _start(struct pl330_thread *thrd)
+static bool pl330_start_thread(struct pl330_thread *thrd)
 {
 	switch (_state(thrd)) {
 	case PL330_STATE_FAULT_COMPLETING:
@@ -1696,7 +1702,7 @@
 			thrd->req_running = -1;
 
 			/* Get going again ASAP */
-			_start(thrd);
+			pl330_start_thread(thrd);
 
 			/* For now, just make a list of callbacks to be done */
 			list_add_tail(&descdone->rqd, &pl330->req_done);
@@ -2035,7 +2041,7 @@
 	list_for_each_entry(desc, &pch->work_list, node) {
 
 		/* If already submitted */
-		if (desc->status == BUSY)
+		if (desc->status == BUSY || desc->status == PAUSED)
 			continue;
 
 		ret = pl330_submit_req(pch->thread, desc);
@@ -2083,7 +2089,7 @@
 	} else {
 		/* Make sure the PL330 Channel thread is active */
 		spin_lock(&pch->thread->dmac->lock);
-		_start(pch->thread);
+		pl330_start_thread(pch->thread);
 		spin_unlock(&pch->thread->dmac->lock);
 	}
 
@@ -2101,7 +2107,7 @@
 			if (power_down) {
 				pch->active = true;
 				spin_lock(&pch->thread->dmac->lock);
-				_start(pch->thread);
+				pl330_start_thread(pch->thread);
 				spin_unlock(&pch->thread->dmac->lock);
 				power_down = false;
 			}
@@ -2322,6 +2328,7 @@
 {
 	struct dma_pl330_chan *pch = to_pchan(chan);
 	struct pl330_dmac *pl330 = pch->dmac;
+	struct dma_pl330_desc *desc;
 	unsigned long flags;
 
 	pm_runtime_get_sync(pl330->ddma.dev);
@@ -2331,6 +2338,10 @@
 	_stop(pch->thread);
 	spin_unlock(&pl330->lock);
 
+	list_for_each_entry(desc, &pch->work_list, node) {
+		if (desc->status == BUSY)
+			desc->status = PAUSED;
+	}
 	spin_unlock_irqrestore(&pch->lock, flags);
 	pm_runtime_mark_last_busy(pl330->ddma.dev);
 	pm_runtime_put_autosuspend(pl330->ddma.dev);
@@ -2421,7 +2432,7 @@
 		else if (running && desc == running)
 			transferred =
 				pl330_get_current_xferred_count(pch, desc);
-		else if (desc->status == BUSY)
+		else if (desc->status == BUSY || desc->status == PAUSED)
 			/*
 			 * Busy but not running means either just enqueued,
 			 * or finished and not yet marked done
@@ -2438,6 +2449,9 @@
 			case DONE:
 				ret = DMA_COMPLETE;
 				break;
+			case PAUSED:
+				ret = DMA_PAUSED;
+				break;
 			case PREP:
 			case BUSY:
 				ret = DMA_IN_PROGRESS;
@@ -2585,7 +2599,7 @@
 
 	/* If the DMAC pool is empty, alloc new */
 	if (!desc) {
-		DEFINE_SPINLOCK(lock);
+		static DEFINE_SPINLOCK(lock);
 		LIST_HEAD(pool);
 
 		if (!add_desc(&pool, &lock, GFP_ATOMIC, 1))
@@ -2690,13 +2704,15 @@
 	for (i = 0; i < len / period_len; i++) {
 		desc = pl330_get_desc(pch);
 		if (!desc) {
+			unsigned long iflags;
+
 			dev_err(pch->dmac->ddma.dev, "%s:%d Unable to fetch desc\n",
 				__func__, __LINE__);
 
 			if (!first)
 				return NULL;
 
-			spin_lock_irqsave(&pl330->pool_lock, flags);
+			spin_lock_irqsave(&pl330->pool_lock, iflags);
 
 			while (!list_empty(&first->node)) {
 				desc = list_entry(first->node.next,
@@ -2706,7 +2722,7 @@
 
 			list_move_tail(&first->node, &pl330->desc_pool);
 
-			spin_unlock_irqrestore(&pl330->pool_lock, flags);
+			spin_unlock_irqrestore(&pl330->pool_lock, iflags);
 
 			return NULL;
 		}
@@ -2788,14 +2804,14 @@
 	while (burst != (1 << desc->rqcfg.brst_size))
 		desc->rqcfg.brst_size++;
 
+	desc->rqcfg.brst_len = get_burst_len(desc, len);
 	/*
 	 * If burst size is smaller than bus width then make sure we only
 	 * transfer one at a time to avoid a burst stradling an MFIFO entry.
 	 */
-	if (desc->rqcfg.brst_size * 8 < pl330->pcfg.data_bus_width)
+	if (burst * 8 < pl330->pcfg.data_bus_width)
 		desc->rqcfg.brst_len = 1;
 
-	desc->rqcfg.brst_len = get_burst_len(desc, len);
 	desc->bytes_requested = len;
 
 	desc->txd.flags = flags;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/pxa_dma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/pxa_dma.c
@@ -723,7 +723,6 @@
 	dma_addr_t dma;
 	struct pxad_desc_sw *sw_desc = to_pxad_sw_desc(vd);
 
-	BUG_ON(sw_desc->nb_desc == 0);
 	for (i = sw_desc->nb_desc - 1; i >= 0; i--) {
 		if (i > 0)
 			dma = sw_desc->hw_desc[i - 1]->ddadr;
@@ -911,13 +910,6 @@
 		*dcmd |= PXA_DCMD_BURST16;
 	else if (maxburst == 32)
 		*dcmd |= PXA_DCMD_BURST32;
-
-	/* FIXME: drivers should be ported over to use the filter
-	 * function. Once that's done, the following two lines can
-	 * be removed.
-	 */
-	if (chan->cfg.slave_id)
-		chan->drcmr = chan->cfg.slave_id;
 }
 
 static struct dma_async_tx_descriptor *
@@ -1256,14 +1248,14 @@
 		return -ENOMEM;
 
 	for (i = 0; i < nb_phy_chans; i++)
-		if (platform_get_irq(op, i) > 0)
+		if (platform_get_irq_optional(op, i) > 0)
 			nr_irq++;
 
 	for (i = 0; i < nb_phy_chans; i++) {
 		phy = &pdev->phys[i];
 		phy->base = pdev->base;
 		phy->idx = i;
-		irq = platform_get_irq(op, i);
+		irq = platform_get_irq_optional(op, i);
 		if ((nr_irq > 1) && (irq > 0))
 			ret = devm_request_irq(&op->dev, irq,
 					       pxad_chan_handler,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/qcom/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/qcom/Kconfig
@@ -10,6 +10,7 @@
 
 config QCOM_HIDMA_MGMT
 	tristate "Qualcomm Technologies HIDMA Management support"
+	depends on HAS_IOMEM
 	select DMA_ENGINE
 	help
 	  Enable support for the Qualcomm Technologies HIDMA Management.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/qcom/hidma_mgmt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/qcom/hidma_mgmt.c
@@ -418,8 +418,23 @@
 		hidma_mgmt_of_populate_channels(child);
 	}
 #endif
-	return platform_driver_register(&hidma_mgmt_driver);
+	/*
+	 * We do not check for return value here, as it is assumed that
+	 * platform_driver_register must not fail. The reason for this is that
+	 * the (potential) hidma_mgmt_of_populate_channels calls above are not
+	 * cleaned up if it does fail, and to do this work is quite
+	 * complicated. In particular, various calls of of_address_to_resource,
+	 * of_irq_to_resource, platform_device_register_full, of_dma_configure,
+	 * and of_msi_configure which then call other functions and so on, must
+	 * be cleaned up - this is not a trivial exercise.
+	 *
+	 * Currently, this module is not intended to be unloaded, and there is
+	 * no module_exit function defined which does the needed cleanup. For
+	 * this reason, we have to assume success here.
+	 */
+	platform_driver_register(&hidma_mgmt_driver);
 
+	return 0;
 }
 module_init(hidma_mgmt_init);
 MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/sh/rcar-dmac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/sh/rcar-dmac.c
@@ -1824,8 +1824,13 @@
 	dmac->dev = &pdev->dev;
 	platform_set_drvdata(pdev, dmac);
 	dmac->dev->dma_parms = &dmac->parms;
-	dma_set_max_seg_size(dmac->dev, RCAR_DMATCR_MASK);
-	dma_set_mask_and_coherent(dmac->dev, DMA_BIT_MASK(40));
+	ret = dma_set_max_seg_size(dmac->dev, RCAR_DMATCR_MASK);
+	if (ret)
+		return ret;
+
+	ret = dma_set_mask_and_coherent(dmac->dev, DMA_BIT_MASK(40));
+	if (ret)
+		return ret;
 
 	ret = rcar_dmac_parse_of(&pdev->dev, dmac);
 	if (ret < 0)
@@ -1855,7 +1860,7 @@
 
 	/* Enable runtime PM and initialize the device. */
 	pm_runtime_enable(&pdev->dev);
-	ret = pm_runtime_get_sync(&pdev->dev);
+	ret = pm_runtime_resume_and_get(&pdev->dev);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "runtime PM get sync failed (%d)\n", ret);
 		return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/sh/shdma.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/sh/shdma.h
@@ -25,7 +25,7 @@
 	const struct sh_dmae_slave_config *config; /* Slave DMA configuration */
 	int xmit_shift;			/* log_2(bytes_per_xfer) */
 	void __iomem *base;
-	char dev_id[16];		/* unique name per DMAC of channel */
+	char dev_id[32];		/* unique name per DMAC of channel */
 	int pm_error;
 	dma_addr_t slave_addr;
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/sh/usb-dmac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/sh/usb-dmac.c
@@ -586,6 +586,8 @@
 		desc->residue = usb_dmac_get_current_residue(chan, desc,
 							desc->sg_index - 1);
 		desc->done_cookie = desc->vd.tx.cookie;
+		desc->vd.tx_result.result = DMA_TRANS_NOERROR;
+		desc->vd.tx_result.residue = desc->residue;
 		vchan_cookie_complete(&desc->vd);
 
 		/* Restart the next transfer if this driver has a next desc */
@@ -853,8 +855,8 @@
 
 error:
 	of_dma_controller_free(pdev->dev.of_node);
-	pm_runtime_put(&pdev->dev);
 error_pm:
+	pm_runtime_put(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 	return ret;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/sprd-dma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/sprd-dma.c
@@ -1201,11 +1201,8 @@
 {
 	struct sprd_dma_dev *sdev = platform_get_drvdata(pdev);
 	struct sprd_dma_chn *c, *cn;
-	int ret;
 
-	ret = pm_runtime_get_sync(&pdev->dev);
-	if (ret < 0)
-		return ret;
+	pm_runtime_get_sync(&pdev->dev);
 
 	/* explicitly free the irq */
 	if (sdev->irq > 0)
@@ -1230,6 +1227,7 @@
 	{ .compatible = "sprd,sc9860-dma", },
 	{},
 };
+MODULE_DEVICE_TABLE(of, sprd_dma_match);
 
 static int __maybe_unused sprd_dma_runtime_suspend(struct device *dev)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/st_fdma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/st_fdma.c
@@ -873,4 +873,4 @@
 MODULE_DESCRIPTION("STMicroelectronics FDMA engine driver");
 MODULE_AUTHOR("Ludovic.barre <Ludovic.barre@st.com>");
 MODULE_AUTHOR("Peter Griffin <peter.griffin@linaro.org>");
-MODULE_ALIAS("platform: " DRIVER_NAME);
+MODULE_ALIAS("platform:" DRIVER_NAME);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/ste_dma40.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/ste_dma40.c
@@ -3599,6 +3599,10 @@
 	spin_lock_init(&base->lcla_pool.lock);
 
 	base->irq = platform_get_irq(pdev, 0);
+	if (base->irq < 0) {
+		ret = base->irq;
+		goto destroy_cache;
+	}
 
 	ret = request_irq(base->irq, d40_handle_interrupt, 0, D40_NAME, base);
 	if (ret) {
@@ -3678,6 +3682,9 @@
 
 	kfree(base->lcla_pool.base_unaligned);
 
+	if (base->lcpa_base)
+		iounmap(base->lcpa_base);
+
 	if (base->phy_lcpa)
 		release_mem_region(base->phy_lcpa,
 				   base->lcpa_size);
@@ -3693,6 +3700,7 @@
 		regulator_disable(base->lcpa_regulator);
 		regulator_put(base->lcpa_regulator);
 	}
+	pm_runtime_disable(base->dev);
 
 	kfree(base->lcla_pool.alloc_map);
 	kfree(base->lookup_log_chans);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/stm32-dma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/stm32-dma.c
@@ -488,8 +488,10 @@
 
 	spin_lock_irqsave(&chan->vchan.lock, flags);
 
-	if (chan->busy) {
-		stm32_dma_stop(chan);
+	if (chan->desc) {
+		vchan_terminate_vdesc(&chan->desc->vdesc);
+		if (chan->busy)
+			stm32_dma_stop(chan);
 		chan->desc = NULL;
 	}
 
@@ -545,6 +547,8 @@
 		if (!vdesc)
 			return;
 
+		list_del(&vdesc->node);
+
 		chan->desc = to_stm32_dma_desc(vdesc);
 		chan->next_sg = 0;
 	}
@@ -622,7 +626,6 @@
 		} else {
 			chan->busy = false;
 			if (chan->next_sg == chan->desc->num_sgs) {
-				list_del(&chan->desc->vdesc.node);
 				vchan_cookie_complete(&chan->desc->vdesc);
 				chan->desc = NULL;
 			}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/stm32-mdma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/stm32-mdma.c
@@ -40,7 +40,6 @@
 					 STM32_MDMA_SHIFT(mask))
 
 #define STM32_MDMA_GISR0		0x0000 /* MDMA Int Status Reg 1 */
-#define STM32_MDMA_GISR1		0x0004 /* MDMA Int Status Reg 2 */
 
 /* MDMA Channel x interrupt/status register */
 #define STM32_MDMA_CISR(x)		(0x40 + 0x40 * (x)) /* x = 0..62 */
@@ -184,7 +183,7 @@
 #define STM32_MDMA_CTBR(x)		(0x68 + 0x40 * (x))
 #define STM32_MDMA_CTBR_DBUS		BIT(17)
 #define STM32_MDMA_CTBR_SBUS		BIT(16)
-#define STM32_MDMA_CTBR_TSEL_MASK	GENMASK(7, 0)
+#define STM32_MDMA_CTBR_TSEL_MASK	GENMASK(5, 0)
 #define STM32_MDMA_CTBR_TSEL(n)		STM32_MDMA_SET(n, \
 						      STM32_MDMA_CTBR_TSEL_MASK)
 
@@ -196,7 +195,7 @@
 
 #define STM32_MDMA_MAX_BUF_LEN		128
 #define STM32_MDMA_MAX_BLOCK_LEN	65536
-#define STM32_MDMA_MAX_CHANNELS		63
+#define STM32_MDMA_MAX_CHANNELS		32
 #define STM32_MDMA_MAX_REQUESTS		256
 #define STM32_MDMA_MAX_BURST		128
 #define STM32_MDMA_VERY_HIGH_PRIORITY	0x11
@@ -511,7 +510,7 @@
 	src_maxburst = chan->dma_config.src_maxburst;
 	dst_maxburst = chan->dma_config.dst_maxburst;
 
-	ccr = stm32_mdma_read(dmadev, STM32_MDMA_CCR(chan->id));
+	ccr = stm32_mdma_read(dmadev, STM32_MDMA_CCR(chan->id)) & ~STM32_MDMA_CCR_EN;
 	ctcr = stm32_mdma_read(dmadev, STM32_MDMA_CTCR(chan->id));
 	ctbr = stm32_mdma_read(dmadev, STM32_MDMA_CTBR(chan->id));
 
@@ -939,7 +938,7 @@
 	if (!desc)
 		return NULL;
 
-	ccr = stm32_mdma_read(dmadev, STM32_MDMA_CCR(chan->id));
+	ccr = stm32_mdma_read(dmadev, STM32_MDMA_CCR(chan->id)) & ~STM32_MDMA_CCR_EN;
 	ctcr = stm32_mdma_read(dmadev, STM32_MDMA_CTCR(chan->id));
 	ctbr = stm32_mdma_read(dmadev, STM32_MDMA_CTBR(chan->id));
 	cbndtr = stm32_mdma_read(dmadev, STM32_MDMA_CBNDTR(chan->id));
@@ -1127,6 +1126,8 @@
 		return;
 	}
 
+	list_del(&vdesc->node);
+
 	chan->desc = to_stm32_mdma_desc(vdesc);
 	hwdesc = chan->desc->node[0].hwdesc;
 	chan->curr_hwdesc = 0;
@@ -1206,6 +1207,10 @@
 	unsigned long flags;
 	u32 status, reg;
 
+	/* Transfer can be terminated */
+	if (!chan->desc || (stm32_mdma_read(dmadev, STM32_MDMA_CCR(chan->id)) & STM32_MDMA_CCR_EN))
+		return -EPERM;
+
 	hwdesc = chan->desc->node[chan->curr_hwdesc].hwdesc;
 
 	spin_lock_irqsave(&chan->vchan.lock, flags);
@@ -1242,8 +1247,10 @@
 	LIST_HEAD(head);
 
 	spin_lock_irqsave(&chan->vchan.lock, flags);
-	if (chan->busy) {
-		stm32_mdma_stop(chan);
+	if (chan->desc) {
+		vchan_terminate_vdesc(&chan->desc->vdesc);
+		if (chan->busy)
+			stm32_mdma_stop(chan);
 		chan->desc = NULL;
 	}
 	vchan_get_all_descriptors(&chan->vchan, &head);
@@ -1331,7 +1338,6 @@
 
 static void stm32_mdma_xfer_end(struct stm32_mdma_chan *chan)
 {
-	list_del(&chan->desc->vdesc.node);
 	vchan_cookie_complete(&chan->desc->vdesc);
 	chan->desc = NULL;
 	chan->busy = false;
@@ -1348,21 +1354,11 @@
 
 	/* Find out which channel generates the interrupt */
 	status = readl_relaxed(dmadev->base + STM32_MDMA_GISR0);
-	if (status) {
-		id = __ffs(status);
-	} else {
-		status = readl_relaxed(dmadev->base + STM32_MDMA_GISR1);
-		if (!status) {
-			dev_dbg(mdma2dev(dmadev), "spurious it\n");
-			return IRQ_NONE;
-		}
-		id = __ffs(status);
-		/*
-		 * As GISR0 provides status for channel id from 0 to 31,
-		 * so GISR1 provides status for channel id from 32 to 62
-		 */
-		id += 32;
+	if (!status) {
+		dev_dbg(mdma2dev(dmadev), "spurious it\n");
+		return IRQ_NONE;
 	}
+	id = __ffs(status);
 
 	chan = &dmadev->chan[id];
 	if (!chan) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/tegra20-apb-dma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/tegra20-apb-dma.c
@@ -281,7 +281,7 @@
 
 	/* Do not allocate if desc are waiting for ack */
 	list_for_each_entry(dma_desc, &tdc->free_dma_desc, node) {
-		if (async_tx_test_ack(&dma_desc->txd)) {
+		if (async_tx_test_ack(&dma_desc->txd) && !dma_desc->cb_count) {
 			list_del(&dma_desc->node);
 			spin_unlock_irqrestore(&tdc->lock, flags);
 			dma_desc->txd.flags = 0;
@@ -756,10 +756,6 @@
 	bool was_busy;
 
 	spin_lock_irqsave(&tdc->lock, flags);
-	if (list_empty(&tdc->pending_sg_req)) {
-		spin_unlock_irqrestore(&tdc->lock, flags);
-		return 0;
-	}
 
 	if (!tdc->busy)
 		goto skip_dma_stop;
@@ -1291,8 +1287,7 @@
 
 	dev_dbg(tdc2dev(tdc), "Freeing channel %d\n", tdc->id);
 
-	if (tdc->busy)
-		tegra_dma_terminate_all(dc);
+	tegra_dma_terminate_all(dc);
 
 	spin_lock_irqsave(&tdc->lock, flags);
 	list_splice_init(&tdc->pending_sg_req, &sg_req_list);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/tegra210-adma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/tegra210-adma.c
@@ -224,7 +224,7 @@
 	int ret;
 
 	/* Clear any interrupts */
-	tdma_write(tdma, tdma->cdata->global_int_clear, 0x1);
+	tdma_write(tdma, tdma->cdata->ch_base_offset + tdma->cdata->global_int_clear, 0x1);
 
 	/* Assert soft reset */
 	tdma_write(tdma, ADMA_GLOBAL_SOFT_RESET, 0x1);
@@ -658,6 +658,7 @@
 
 	ret = pm_runtime_get_sync(tdc2dev(tdc));
 	if (ret < 0) {
+		pm_runtime_put_noidle(tdc2dev(tdc));
 		free_irq(tdc->irq, tdc);
 		return ret;
 	}
@@ -869,8 +870,10 @@
 	pm_runtime_enable(&pdev->dev);
 
 	ret = pm_runtime_get_sync(&pdev->dev);
-	if (ret < 0)
+	if (ret < 0) {
+		pm_runtime_put_noidle(&pdev->dev);
 		goto rpm_disable;
+	}
 
 	ret = tegra_adma_init(tdma);
 	if (ret)
@@ -900,7 +903,7 @@
 	ret = dma_async_device_register(&tdma->dma_dev);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "ADMA registration failed: %d\n", ret);
-		goto irq_dispose;
+		goto rpm_put;
 	}
 
 	ret = of_dma_controller_register(pdev->dev.of_node,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/ti/dma-crossbar.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/ti/dma-crossbar.c
@@ -247,6 +247,7 @@
 	if (dma_spec->args[0] >= xbar->xbar_requests) {
 		dev_err(&pdev->dev, "Invalid XBAR request number: %d\n",
 			dma_spec->args[0]);
+		put_device(&pdev->dev);
 		return ERR_PTR(-EINVAL);
 	}
 
@@ -254,12 +255,14 @@
 	dma_spec->np = of_parse_phandle(ofdma->of_node, "dma-masters", 0);
 	if (!dma_spec->np) {
 		dev_err(&pdev->dev, "Can't get DMA master\n");
+		put_device(&pdev->dev);
 		return ERR_PTR(-EINVAL);
 	}
 
 	map = kzalloc(sizeof(*map), GFP_KERNEL);
 	if (!map) {
 		of_node_put(dma_spec->np);
+		put_device(&pdev->dev);
 		return ERR_PTR(-ENOMEM);
 	}
 
@@ -270,6 +273,8 @@
 		mutex_unlock(&xbar->mutex);
 		dev_err(&pdev->dev, "Run out of free DMA requests\n");
 		kfree(map);
+		of_node_put(dma_spec->np);
+		put_device(&pdev->dev);
 		return ERR_PTR(-ENOMEM);
 	}
 	set_bit(map->xbar_out, xbar->dma_inuse);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/ti/edma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/ti/edma.c
@@ -217,7 +217,6 @@
 struct edma_cc;
 
 struct edma_tc {
-	struct device_node		*node;
 	u16				id;
 };
 
@@ -2361,7 +2360,7 @@
 	if (irq < 0 && node)
 		irq = irq_of_parse_and_map(node, 0);
 
-	if (irq >= 0) {
+	if (irq > 0) {
 		irq_name = devm_kasprintf(dev, GFP_KERNEL, "%s_ccint",
 					  dev_name(dev));
 		ret = devm_request_irq(dev, irq, dma_irq_handler, 0, irq_name,
@@ -2377,7 +2376,7 @@
 	if (irq < 0 && node)
 		irq = irq_of_parse_and_map(node, 2);
 
-	if (irq >= 0) {
+	if (irq > 0) {
 		irq_name = devm_kasprintf(dev, GFP_KERNEL, "%s_ccerrint",
 					  dev_name(dev));
 		ret = devm_request_irq(dev, irq, dma_ccerr_handler, 0, irq_name,
@@ -2403,8 +2402,10 @@
 
 		ecc->tc_list = devm_kcalloc(dev, ecc->num_tc,
 					    sizeof(*ecc->tc_list), GFP_KERNEL);
-		if (!ecc->tc_list)
-			return -ENOMEM;
+		if (!ecc->tc_list) {
+			ret = -ENOMEM;
+			goto err_reg1;
+		}
 
 		for (i = 0;; i++) {
 			ret = of_parse_phandle_with_fixed_args(node, "ti,tptcs",
@@ -2412,13 +2413,13 @@
 			if (ret || i == ecc->num_tc)
 				break;
 
-			ecc->tc_list[i].node = tc_args.np;
 			ecc->tc_list[i].id = i;
 			queue_priority_mapping[i][1] = tc_args.args[0];
 			if (queue_priority_mapping[i][1] > lowest_priority) {
 				lowest_priority = queue_priority_mapping[i][1];
 				info->default_queue = i;
 			}
+			of_node_put(tc_args.np);
 		}
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/virt-dma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/virt-dma.c
@@ -104,9 +104,8 @@
 		dmaengine_desc_get_callback(&vd->tx, &cb);
 
 		list_del(&vd->node);
-		vchan_vdesc_fini(vd);
-
 		dmaengine_desc_callback_invoke(&cb, &vd->tx_result);
+		vchan_vdesc_fini(vd);
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/xilinx/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/xilinx/Kconfig
@@ -0,0 +1,47 @@
+#
+# XILINX DMA Engines configuration
+#
+
+menuconfig XILINX_DMA_ENGINES
+	bool "Xilinx DMA Engines"
+	help
+	  Enable support for the Xilinx DMA controllers. It supports three DMA
+	  engines: Axi Central DMA (memory to memory transfer), Axi DMA (memory and
+	  device transfer), and Axi VDMA (memory and video device transfer).
+
+if XILINX_DMA_ENGINES
+
+config XILINX_DPDMA
+	tristate "Xilinx DPDMA Engine"
+	select DMA_ENGINE
+	help
+	  Enable support for Xilinx DisplayPort DMA.
+
+config XILINX_DPDMA_DEBUG_FS
+	bool "Xilinx DPDMA debugfs"
+	depends on DEBUG_FS && XILINX_DPDMA
+	help
+	  Enable the debugfs code for DPDMA driver. The debugfs code
+	  enables debugging or testing related features. It exposes some
+	  low level controls to the user space to help testing automation,
+	  as well as can enable additional diagnostic or statistical
+	  information.
+
+config XILINX_PS_PCIE_DMA_TEST
+	tristate "Xilinx PS PCIe DMA test client"
+	depends on XILINX_PS_PCIE_DMA
+	help
+	  Enable support for the test client of Xilinx PS PCIe DMA engine
+	  in recent Xilinx ZynqMP chipsets.
+
+	  Say Y here if you have such a chipset.
+
+	  If unsure, say N.
+
+endif # XILINX_DMA_ENGINES
+
+config XILINX_FRMBUF
+	tristate "Xilinx Framebuffer"
+	select DMA_ENGINE
+	help
+	 Enable support for Xilinx Framebuffer DMA.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/xilinx/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/xilinx/Makefile
@@ -1,3 +1,10 @@
 # SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_XILINX_DMATEST) += axidmatest.o
+obj-$(CONFIG_XILINX_VDMATEST) += vdmatest.o
+obj-$(CONFIG_XILINX_DPDMA) += xilinx_dpdma.o
 obj-$(CONFIG_XILINX_DMA) += xilinx_dma.o
 obj-$(CONFIG_XILINX_ZYNQMP_DMA) += zynqmp_dma.o
+xilinx_ps_pcie_dma-objs := xilinx_ps_pcie_main.o xilinx_ps_pcie_platform.o
+obj-$(CONFIG_XILINX_PS_PCIE_DMA) += xilinx_ps_pcie_dma.o
+obj-$(CONFIG_XILINX_PS_PCIE_DMA_TEST) += xilinx_ps_pcie_dma_client.o
+obj-$(CONFIG_XILINX_FRMBUF) += xilinx_frmbuf.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/xilinx/axidmatest.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/xilinx/axidmatest.c
@@ -0,0 +1,698 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * XILINX AXI DMA and MCDMA Engine test module
+ *
+ * Copyright (C) 2010 Xilinx, Inc. All rights reserved.
+ *
+ * Based on Atmel DMA Test Client
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/delay.h>
+#include <linux/dmaengine.h>
+#include <linux/init.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/of_dma.h>
+#include <linux/platform_device.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+#include <linux/sched/task.h>
+#include <linux/dma/xilinx_dma.h>
+
+static unsigned int test_buf_size = 16384;
+module_param(test_buf_size, uint, 0444);
+MODULE_PARM_DESC(test_buf_size, "Size of the memcpy test buffer");
+
+static unsigned int iterations = 5;
+module_param(iterations, uint, 0444);
+MODULE_PARM_DESC(iterations,
+		 "Iterations before stopping test (default: infinite)");
+
+/*
+ * Initialization patterns. All bytes in the source buffer has bit 7
+ * set, all bytes in the destination buffer has bit 7 cleared.
+ *
+ * Bit 6 is set for all bytes which are to be copied by the DMA
+ * engine. Bit 5 is set for all bytes which are to be overwritten by
+ * the DMA engine.
+ *
+ * The remaining bits are the inverse of a counter which increments by
+ * one for each byte address.
+ */
+#define PATTERN_SRC		0x80
+#define PATTERN_DST		0x00
+#define PATTERN_COPY		0x40
+#define PATTERN_OVERWRITE	0x20
+#define PATTERN_COUNT_MASK	0x1f
+
+#define XILINX_DMATEST_BD_CNT	11
+
+struct dmatest_slave_thread {
+	struct list_head node;
+	struct task_struct *task;
+	struct dma_chan *tx_chan;
+	struct dma_chan *rx_chan;
+	u8 **srcs;
+	u8 **dsts;
+	enum dma_transaction_type type;
+	bool done;
+};
+
+struct dmatest_chan {
+	struct list_head node;
+	struct dma_chan *chan;
+	struct list_head threads;
+};
+
+/*
+ * These are protected by dma_list_mutex since they're only used by
+ * the DMA filter function callback
+ */
+static DECLARE_WAIT_QUEUE_HEAD(thread_wait);
+static LIST_HEAD(dmatest_channels);
+static unsigned int nr_channels;
+
+static unsigned long long dmatest_persec(s64 runtime, unsigned int val)
+{
+	unsigned long long per_sec = 1000000;
+
+	if (runtime <= 0)
+		return 0;
+
+	/* drop precision until runtime is 32-bits */
+	while (runtime > UINT_MAX) {
+		runtime >>= 1;
+		per_sec <<= 1;
+	}
+
+	per_sec *= val;
+	do_div(per_sec, runtime);
+	return per_sec;
+}
+
+static unsigned long long dmatest_KBs(s64 runtime, unsigned long long len)
+{
+	return dmatest_persec(runtime, len >> 10);
+}
+
+static bool is_threaded_test_run(struct dmatest_chan *tx_dtc,
+				 struct dmatest_chan *rx_dtc)
+{
+	struct dmatest_slave_thread *thread;
+	int ret = false;
+
+	list_for_each_entry(thread, &tx_dtc->threads, node) {
+		if (!thread->done)
+			ret = true;
+	}
+
+	list_for_each_entry(thread, &rx_dtc->threads, node) {
+		if (!thread->done)
+			ret = true;
+	}
+	return ret;
+}
+
+static unsigned long dmatest_random(void)
+{
+	unsigned long buf;
+
+	get_random_bytes(&buf, sizeof(buf));
+	return buf;
+}
+
+static void dmatest_init_srcs(u8 **bufs, unsigned int start, unsigned int len)
+{
+	unsigned int i;
+	u8 *buf;
+
+	for (; (buf = *bufs); bufs++) {
+		for (i = 0; i < start; i++)
+			buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK);
+		for ( ; i < start + len; i++)
+			buf[i] = PATTERN_SRC | PATTERN_COPY
+				| (~i & PATTERN_COUNT_MASK);
+		for ( ; i < test_buf_size; i++)
+			buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK);
+	}
+}
+
+static void dmatest_init_dsts(u8 **bufs, unsigned int start, unsigned int len)
+{
+	unsigned int i;
+	u8 *buf;
+
+	for (; (buf = *bufs); bufs++) {
+		for (i = 0; i < start; i++)
+			buf[i] = PATTERN_DST | (~i & PATTERN_COUNT_MASK);
+		for ( ; i < start + len; i++)
+			buf[i] = PATTERN_DST | PATTERN_OVERWRITE
+				| (~i & PATTERN_COUNT_MASK);
+		for ( ; i < test_buf_size; i++)
+			buf[i] = PATTERN_DST | (~i & PATTERN_COUNT_MASK);
+	}
+}
+
+static void dmatest_mismatch(u8 actual, u8 pattern, unsigned int index,
+			     unsigned int counter, bool is_srcbuf)
+{
+	u8 diff = actual ^ pattern;
+	u8 expected = pattern | (~counter & PATTERN_COUNT_MASK);
+	const char *thread_name = current->comm;
+
+	if (is_srcbuf)
+		pr_warn("%s: srcbuf[0x%x] overwritten! Expected %02x, got %02x\n",
+			thread_name, index, expected, actual);
+	else if ((pattern & PATTERN_COPY) &&
+		 (diff & (PATTERN_COPY | PATTERN_OVERWRITE)))
+		pr_warn("%s: dstbuf[0x%x] not copied! Expected %02x, got %02x\n",
+			thread_name, index, expected, actual);
+	else if (diff & PATTERN_SRC)
+		pr_warn("%s: dstbuf[0x%x] was copied! Expected %02x, got %02x\n",
+			thread_name, index, expected, actual);
+	else
+		pr_warn("%s: dstbuf[0x%x] mismatch! Expected %02x, got %02x\n",
+			thread_name, index, expected, actual);
+}
+
+static unsigned int dmatest_verify(u8 **bufs, unsigned int start,
+				   unsigned int end, unsigned int counter,
+				   u8 pattern, bool is_srcbuf)
+{
+	unsigned int i;
+	unsigned int error_count = 0;
+	u8 actual;
+	u8 expected;
+	u8 *buf;
+	unsigned int counter_orig = counter;
+
+	for (; (buf = *bufs); bufs++) {
+		counter = counter_orig;
+		for (i = start; i < end; i++) {
+			actual = buf[i];
+			expected = pattern | (~counter & PATTERN_COUNT_MASK);
+			if (actual != expected) {
+				if (error_count < 32)
+					dmatest_mismatch(actual, pattern, i,
+							 counter, is_srcbuf);
+				error_count++;
+			}
+			counter++;
+		}
+	}
+
+	if (error_count > 32)
+		pr_warn("%s: %u errors suppressed\n",
+			current->comm, error_count - 32);
+
+	return error_count;
+}
+
+static void dmatest_slave_tx_callback(void *completion)
+{
+	complete(completion);
+}
+
+static void dmatest_slave_rx_callback(void *completion)
+{
+	complete(completion);
+}
+
+/* Function for slave transfers
+ * Each thread requires 2 channels, one for transmit, and one for receive
+ */
+static int dmatest_slave_func(void *data)
+{
+	struct dmatest_slave_thread	*thread = data;
+	struct dma_chan *tx_chan;
+	struct dma_chan *rx_chan;
+	const char *thread_name;
+	unsigned int src_off, dst_off, len;
+	unsigned int error_count;
+	unsigned int failed_tests = 0;
+	unsigned int total_tests = 0;
+	dma_cookie_t tx_cookie;
+	dma_cookie_t rx_cookie;
+	enum dma_status status;
+	enum dma_ctrl_flags flags;
+	int ret;
+	int src_cnt;
+	int dst_cnt;
+	int bd_cnt = XILINX_DMATEST_BD_CNT;
+	int i;
+
+	ktime_t	ktime, start, diff;
+	ktime_t	filltime = 0;
+	ktime_t	comparetime = 0;
+	s64 runtime = 0;
+	unsigned long long total_len = 0;
+	thread_name = current->comm;
+	ret = -ENOMEM;
+
+
+	/* Ensure that all previous reads are complete */
+	smp_rmb();
+	tx_chan = thread->tx_chan;
+	rx_chan = thread->rx_chan;
+	dst_cnt = bd_cnt;
+	src_cnt = bd_cnt;
+
+	thread->srcs = kcalloc(src_cnt + 1, sizeof(u8 *), GFP_KERNEL);
+	if (!thread->srcs)
+		goto err_srcs;
+	for (i = 0; i < src_cnt; i++) {
+		thread->srcs[i] = kmalloc(test_buf_size, GFP_KERNEL);
+		if (!thread->srcs[i])
+			goto err_srcbuf;
+	}
+	thread->srcs[i] = NULL;
+
+	thread->dsts = kcalloc(dst_cnt + 1, sizeof(u8 *), GFP_KERNEL);
+	if (!thread->dsts)
+		goto err_dsts;
+	for (i = 0; i < dst_cnt; i++) {
+		thread->dsts[i] = kmalloc(test_buf_size, GFP_KERNEL);
+		if (!thread->dsts[i])
+			goto err_dstbuf;
+	}
+	thread->dsts[i] = NULL;
+
+	set_user_nice(current, 10);
+
+	flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
+
+	ktime = ktime_get();
+	while (!kthread_should_stop() &&
+	       !(iterations && total_tests >= iterations)) {
+		struct dma_device *tx_dev = tx_chan->device;
+		struct dma_device *rx_dev = rx_chan->device;
+		struct dma_async_tx_descriptor *txd = NULL;
+		struct dma_async_tx_descriptor *rxd = NULL;
+		dma_addr_t dma_srcs[XILINX_DMATEST_BD_CNT];
+		dma_addr_t dma_dsts[XILINX_DMATEST_BD_CNT];
+		struct completion rx_cmp;
+		struct completion tx_cmp;
+		unsigned long rx_tmo =
+				msecs_to_jiffies(300000); /* RX takes longer */
+		unsigned long tx_tmo = msecs_to_jiffies(30000);
+		u8 align = 0;
+		struct scatterlist tx_sg[XILINX_DMATEST_BD_CNT];
+		struct scatterlist rx_sg[XILINX_DMATEST_BD_CNT];
+
+		total_tests++;
+
+		/* honor larger alignment restrictions */
+		align = tx_dev->copy_align;
+		if (rx_dev->copy_align > align)
+			align = rx_dev->copy_align;
+
+		if (1 << align > test_buf_size) {
+			pr_err("%u-byte buffer too small for %d-byte alignment\n",
+			       test_buf_size, 1 << align);
+			break;
+		}
+
+		len = dmatest_random() % test_buf_size + 1;
+		len = (len >> align) << align;
+		if (!len)
+			len = 1 << align;
+		total_len += len;
+		src_off = dmatest_random() % (test_buf_size - len + 1);
+		dst_off = dmatest_random() % (test_buf_size - len + 1);
+
+		src_off = (src_off >> align) << align;
+		dst_off = (dst_off >> align) << align;
+
+		start = ktime_get();
+		dmatest_init_srcs(thread->srcs, src_off, len);
+		dmatest_init_dsts(thread->dsts, dst_off, len);
+		diff = ktime_sub(ktime_get(), start);
+		filltime = ktime_add(filltime, diff);
+
+		for (i = 0; i < src_cnt; i++) {
+			u8 *buf = thread->srcs[i] + src_off;
+
+			dma_srcs[i] = dma_map_single(tx_dev->dev, buf, len,
+						     DMA_MEM_TO_DEV);
+		}
+
+		for (i = 0; i < dst_cnt; i++) {
+			dma_dsts[i] = dma_map_single(rx_dev->dev,
+						     thread->dsts[i],
+						     test_buf_size,
+						     DMA_BIDIRECTIONAL);
+		}
+
+		sg_init_table(tx_sg, bd_cnt);
+		sg_init_table(rx_sg, bd_cnt);
+
+		for (i = 0; i < bd_cnt; i++) {
+			sg_dma_address(&tx_sg[i]) = dma_srcs[i];
+			sg_dma_address(&rx_sg[i]) = dma_dsts[i] + dst_off;
+
+			sg_dma_len(&tx_sg[i]) = len;
+			sg_dma_len(&rx_sg[i]) = len;
+		}
+
+		rxd = rx_dev->device_prep_slave_sg(rx_chan, rx_sg, bd_cnt,
+				DMA_DEV_TO_MEM, flags, NULL);
+
+		txd = tx_dev->device_prep_slave_sg(tx_chan, tx_sg, bd_cnt,
+				DMA_MEM_TO_DEV, flags, NULL);
+
+		if (!rxd || !txd) {
+			for (i = 0; i < src_cnt; i++)
+				dma_unmap_single(tx_dev->dev, dma_srcs[i], len,
+						 DMA_MEM_TO_DEV);
+			for (i = 0; i < dst_cnt; i++)
+				dma_unmap_single(rx_dev->dev, dma_dsts[i],
+						 test_buf_size,
+						 DMA_BIDIRECTIONAL);
+			pr_warn("%s: #%u: prep error with src_off=0x%x ",
+				thread_name, total_tests - 1, src_off);
+			pr_warn("dst_off=0x%x len=0x%x\n",
+				dst_off, len);
+			msleep(100);
+			failed_tests++;
+			continue;
+		}
+
+		init_completion(&rx_cmp);
+		rxd->callback = dmatest_slave_rx_callback;
+		rxd->callback_param = &rx_cmp;
+		rx_cookie = rxd->tx_submit(rxd);
+
+		init_completion(&tx_cmp);
+		txd->callback = dmatest_slave_tx_callback;
+		txd->callback_param = &tx_cmp;
+		tx_cookie = txd->tx_submit(txd);
+
+		if (dma_submit_error(rx_cookie) ||
+		    dma_submit_error(tx_cookie)) {
+			pr_warn("%s: #%u: submit error %d/%d with src_off=0x%x ",
+				thread_name, total_tests - 1,
+				rx_cookie, tx_cookie, src_off);
+			pr_warn("dst_off=0x%x len=0x%x\n",
+				dst_off, len);
+			msleep(100);
+			failed_tests++;
+			continue;
+		}
+		dma_async_issue_pending(rx_chan);
+		dma_async_issue_pending(tx_chan);
+
+		tx_tmo = wait_for_completion_timeout(&tx_cmp, tx_tmo);
+
+		status = dma_async_is_tx_complete(tx_chan, tx_cookie,
+						  NULL, NULL);
+
+		if (tx_tmo == 0) {
+			pr_warn("%s: #%u: tx test timed out\n",
+				thread_name, total_tests - 1);
+			failed_tests++;
+			continue;
+		} else if (status != DMA_COMPLETE) {
+			pr_warn("%s: #%u: tx got completion callback, ",
+				thread_name, total_tests - 1);
+			pr_warn("but status is \'%s\'\n",
+				status == DMA_ERROR ? "error" :
+				"in progress");
+			failed_tests++;
+			continue;
+		}
+
+		rx_tmo = wait_for_completion_timeout(&rx_cmp, rx_tmo);
+		status = dma_async_is_tx_complete(rx_chan, rx_cookie,
+						  NULL, NULL);
+
+		if (rx_tmo == 0) {
+			pr_warn("%s: #%u: rx test timed out\n",
+				thread_name, total_tests - 1);
+			failed_tests++;
+			continue;
+		} else if (status != DMA_COMPLETE) {
+			pr_warn("%s: #%u: rx got completion callback, ",
+				thread_name, total_tests - 1);
+			pr_warn("but status is \'%s\'\n",
+				status == DMA_ERROR ? "error" :
+				"in progress");
+			failed_tests++;
+			continue;
+		}
+
+		/* Unmap by myself */
+		for (i = 0; i < dst_cnt; i++)
+			dma_unmap_single(rx_dev->dev, dma_dsts[i],
+					 test_buf_size, DMA_BIDIRECTIONAL);
+
+		error_count = 0;
+		start = ktime_get();
+		pr_debug("%s: verifying source buffer...\n", thread_name);
+		error_count += dmatest_verify(thread->srcs, 0, src_off,
+				0, PATTERN_SRC, true);
+		error_count += dmatest_verify(thread->srcs, src_off,
+				src_off + len, src_off,
+				PATTERN_SRC | PATTERN_COPY, true);
+		error_count += dmatest_verify(thread->srcs, src_off + len,
+				test_buf_size, src_off + len,
+				PATTERN_SRC, true);
+
+		pr_debug("%s: verifying dest buffer...\n",
+			 thread->task->comm);
+		error_count += dmatest_verify(thread->dsts, 0, dst_off,
+				0, PATTERN_DST, false);
+		error_count += dmatest_verify(thread->dsts, dst_off,
+				dst_off + len, src_off,
+				PATTERN_SRC | PATTERN_COPY, false);
+		error_count += dmatest_verify(thread->dsts, dst_off + len,
+				test_buf_size, dst_off + len,
+				PATTERN_DST, false);
+		diff = ktime_sub(ktime_get(), start);
+		comparetime = ktime_add(comparetime, diff);
+
+		if (error_count) {
+			pr_warn("%s: #%u: %u errors with ",
+				thread_name, total_tests - 1, error_count);
+			pr_warn("src_off=0x%x dst_off=0x%x len=0x%x\n",
+				src_off, dst_off, len);
+			failed_tests++;
+		} else {
+			pr_debug("%s: #%u: No errors with ",
+				 thread_name, total_tests - 1);
+			pr_debug("src_off=0x%x dst_off=0x%x len=0x%x\n",
+				 src_off, dst_off, len);
+		}
+	}
+
+	ktime = ktime_sub(ktime_get(), ktime);
+	ktime = ktime_sub(ktime, comparetime);
+	ktime = ktime_sub(ktime, filltime);
+	runtime = ktime_to_us(ktime);
+
+	ret = 0;
+	for (i = 0; thread->dsts[i]; i++)
+		kfree(thread->dsts[i]);
+err_dstbuf:
+	kfree(thread->dsts);
+err_dsts:
+	for (i = 0; thread->srcs[i]; i++)
+		kfree(thread->srcs[i]);
+err_srcbuf:
+	kfree(thread->srcs);
+err_srcs:
+	pr_notice("%s: terminating after %u tests, %u failures %llu iops %llu KB/s (status %d)\n",
+		  thread_name, total_tests, failed_tests,
+		  dmatest_persec(runtime, total_tests),
+		  dmatest_KBs(runtime, total_len), ret);
+
+	thread->done = true;
+	wake_up(&thread_wait);
+
+	return ret;
+}
+
+static void dmatest_cleanup_channel(struct dmatest_chan *dtc)
+{
+	struct dmatest_slave_thread *thread;
+	struct dmatest_slave_thread *_thread;
+	int ret;
+
+	list_for_each_entry_safe(thread, _thread, &dtc->threads, node) {
+		ret = kthread_stop(thread->task);
+		pr_debug("dmatest: thread %s exited with status %d\n",
+			 thread->task->comm, ret);
+		list_del(&thread->node);
+		put_task_struct(thread->task);
+		kfree(thread);
+	}
+	kfree(dtc);
+}
+
+static int dmatest_add_slave_threads(struct dmatest_chan *tx_dtc,
+				     struct dmatest_chan *rx_dtc)
+{
+	struct dmatest_slave_thread *thread;
+	struct dma_chan *tx_chan = tx_dtc->chan;
+	struct dma_chan *rx_chan = rx_dtc->chan;
+	int ret;
+
+	thread = kzalloc(sizeof(struct dmatest_slave_thread), GFP_KERNEL);
+	if (!thread) {
+		pr_warn("dmatest: No memory for slave thread %s-%s\n",
+			dma_chan_name(tx_chan), dma_chan_name(rx_chan));
+	}
+
+	thread->tx_chan = tx_chan;
+	thread->rx_chan = rx_chan;
+	thread->type = (enum dma_transaction_type)DMA_SLAVE;
+
+	/* Ensure that all previous writes are complete */
+	smp_wmb();
+	thread->task = kthread_run(dmatest_slave_func, thread, "%s-%s",
+				   dma_chan_name(tx_chan),
+				   dma_chan_name(rx_chan));
+	ret = PTR_ERR(thread->task);
+	if (IS_ERR(thread->task)) {
+		pr_warn("dmatest: Failed to run thread %s-%s\n",
+			dma_chan_name(tx_chan), dma_chan_name(rx_chan));
+		kfree(thread);
+		return ret;
+	}
+
+	/* srcbuf and dstbuf are allocated by the thread itself */
+	get_task_struct(thread->task);
+	list_add_tail(&thread->node, &tx_dtc->threads);
+
+	/* Added one thread with 2 channels */
+	return 1;
+}
+
+static int dmatest_add_slave_channels(struct dma_chan *tx_chan,
+				      struct dma_chan *rx_chan)
+{
+	struct dmatest_chan *tx_dtc;
+	struct dmatest_chan *rx_dtc;
+	unsigned int thread_count = 0;
+
+	tx_dtc = kmalloc(sizeof(struct dmatest_chan), GFP_KERNEL);
+	if (!tx_dtc) {
+		pr_warn("dmatest: No memory for tx %s\n",
+			dma_chan_name(tx_chan));
+		return -ENOMEM;
+	}
+
+	rx_dtc = kmalloc(sizeof(struct dmatest_chan), GFP_KERNEL);
+	if (!rx_dtc) {
+		pr_warn("dmatest: No memory for rx %s\n",
+			dma_chan_name(rx_chan));
+		return -ENOMEM;
+	}
+
+	tx_dtc->chan = tx_chan;
+	rx_dtc->chan = rx_chan;
+	INIT_LIST_HEAD(&tx_dtc->threads);
+	INIT_LIST_HEAD(&rx_dtc->threads);
+
+	dmatest_add_slave_threads(tx_dtc, rx_dtc);
+	thread_count += 1;
+
+	pr_info("dmatest: Started %u threads using %s %s\n",
+		thread_count, dma_chan_name(tx_chan), dma_chan_name(rx_chan));
+
+	list_add_tail(&tx_dtc->node, &dmatest_channels);
+	list_add_tail(&rx_dtc->node, &dmatest_channels);
+	nr_channels += 2;
+
+	if (iterations)
+		wait_event(thread_wait, !is_threaded_test_run(tx_dtc, rx_dtc));
+
+	return 0;
+}
+
+static int xilinx_axidmatest_probe(struct platform_device *pdev)
+{
+	struct dma_chan *chan, *rx_chan;
+	int err;
+
+	chan = dma_request_chan(&pdev->dev, "axidma0");
+	if (IS_ERR(chan)) {
+		err = PTR_ERR(chan);
+		if (err != -EPROBE_DEFER)
+			pr_err("xilinx_dmatest: No Tx channel\n");
+		return err;
+	}
+
+	rx_chan = dma_request_chan(&pdev->dev, "axidma1");
+	if (IS_ERR(rx_chan)) {
+		err = PTR_ERR(rx_chan);
+		if (err != -EPROBE_DEFER)
+			pr_err("xilinx_dmatest: No Rx channel\n");
+		goto free_tx;
+	}
+
+	err = dmatest_add_slave_channels(chan, rx_chan);
+	if (err) {
+		pr_err("xilinx_dmatest: Unable to add channels\n");
+		goto free_rx;
+	}
+
+	return 0;
+
+free_rx:
+	dma_release_channel(rx_chan);
+free_tx:
+	dma_release_channel(chan);
+
+	return err;
+}
+
+static int xilinx_axidmatest_remove(struct platform_device *pdev)
+{
+	struct dmatest_chan *dtc, *_dtc;
+	struct dma_chan *chan;
+
+	list_for_each_entry_safe(dtc, _dtc, &dmatest_channels, node) {
+		list_del(&dtc->node);
+		chan = dtc->chan;
+		dmatest_cleanup_channel(dtc);
+		pr_info("xilinx_dmatest: dropped channel %s\n",
+			dma_chan_name(chan));
+		dmaengine_terminate_all(chan);
+		dma_release_channel(chan);
+	}
+	return 0;
+}
+
+static const struct of_device_id xilinx_axidmatest_of_ids[] = {
+	{ .compatible = "xlnx,axi-dma-test-1.00.a",},
+	{}
+};
+
+static struct platform_driver xilinx_axidmatest_driver = {
+	.driver = {
+		.name = "xilinx_axidmatest",
+		.of_match_table = xilinx_axidmatest_of_ids,
+	},
+	.probe = xilinx_axidmatest_probe,
+	.remove = xilinx_axidmatest_remove,
+};
+
+static int __init axidma_init(void)
+{
+	return platform_driver_register(&xilinx_axidmatest_driver);
+}
+late_initcall(axidma_init);
+
+static void __exit axidma_exit(void)
+{
+	platform_driver_unregister(&xilinx_axidmatest_driver);
+}
+module_exit(axidma_exit)
+
+MODULE_AUTHOR("Xilinx, Inc.");
+MODULE_DESCRIPTION("Xilinx AXI DMA Test Client");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/xilinx/vdmatest.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/xilinx/vdmatest.c
@@ -0,0 +1,663 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * XILINX VDMA Engine test client driver
+ *
+ * Copyright (C) 2010-2014 Xilinx, Inc. All rights reserved.
+ *
+ * Based on Atmel DMA Test Client
+ *
+ * Description:
+ * This is a simple Xilinx VDMA test client for AXI VDMA driver.
+ * This test assumes both the channels of VDMA are enabled in the
+ * hardware design and configured in back-to-back connection. Test
+ * starts by pumping the data onto one channel (MM2S) and then
+ * compares the data that is received on the other channel (S2MM).
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/dma/xilinx_dma.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/of_dma.h>
+#include <linux/platform_device.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+#include <linux/sched/task.h>
+#include <linux/wait.h>
+
+static unsigned int test_buf_size = 64;
+module_param(test_buf_size, uint, 0444);
+MODULE_PARM_DESC(test_buf_size, "Size of the memcpy test buffer");
+
+static unsigned int iterations = 1;
+module_param(iterations, uint, 0444);
+MODULE_PARM_DESC(iterations,
+		"Iterations before stopping test (default: infinite)");
+
+static unsigned int hsize = 64;
+module_param(hsize, uint, 0444);
+MODULE_PARM_DESC(hsize, "Horizontal size in bytes");
+
+static unsigned int vsize = 32;
+module_param(vsize, uint, 0444);
+MODULE_PARM_DESC(vsize, "Vertical size in bytes");
+
+/*
+ * Initialization patterns. All bytes in the source buffer has bit 7
+ * set, all bytes in the destination buffer has bit 7 cleared.
+ *
+ * Bit 6 is set for all bytes which are to be copied by the DMA
+ * engine. Bit 5 is set for all bytes which are to be overwritten by
+ * the DMA engine.
+ *
+ * The remaining bits are the inverse of a counter which increments by
+ * one for each byte address.
+ */
+#define PATTERN_SRC		0x80
+#define PATTERN_DST		0x00
+#define PATTERN_COPY		0x40
+#define PATTERN_OVERWRITE	0x20
+#define PATTERN_COUNT_MASK	0x1f
+
+/* Maximum number of frame buffers */
+#define MAX_NUM_FRAMES	32
+
+/**
+ * struct vdmatest_slave_thread - VDMA test thread
+ * @node: Thread node
+ * @task: Task structure pointer
+ * @tx_chan: Tx channel pointer
+ * @rx_chan: Rx Channel pointer
+ * @srcs: Source buffer
+ * @dsts: Destination buffer
+ * @type: DMA transaction type
+ */
+struct xilinx_vdmatest_slave_thread {
+	struct list_head node;
+	struct task_struct *task;
+	struct dma_chan *tx_chan;
+	struct dma_chan *rx_chan;
+	u8 **srcs;
+	u8 **dsts;
+	enum dma_transaction_type type;
+	bool done;
+};
+
+/**
+ * struct vdmatest_chan - VDMA Test channel
+ * @node: Channel node
+ * @chan: DMA channel pointer
+ * @threads: List of VDMA test threads
+ */
+struct xilinx_vdmatest_chan {
+	struct list_head node;
+	struct dma_chan *chan;
+	struct list_head threads;
+};
+
+/* Global variables */
+static DECLARE_WAIT_QUEUE_HEAD(thread_wait);
+static LIST_HEAD(xilinx_vdmatest_channels);
+static unsigned int nr_channels;
+static unsigned int frm_cnt;
+static dma_addr_t dma_srcs[MAX_NUM_FRAMES];
+static dma_addr_t dma_dsts[MAX_NUM_FRAMES];
+static struct dma_interleaved_template xt;
+
+static bool is_threaded_test_run(struct xilinx_vdmatest_chan *tx_dtc,
+					struct xilinx_vdmatest_chan *rx_dtc)
+{
+	struct xilinx_vdmatest_slave_thread *thread;
+	int ret = false;
+
+	list_for_each_entry(thread, &tx_dtc->threads, node) {
+		if (!thread->done)
+			ret = true;
+	}
+
+	list_for_each_entry(thread, &rx_dtc->threads, node) {
+		if (!thread->done)
+			ret = true;
+	}
+	return ret;
+}
+
+static void xilinx_vdmatest_init_srcs(u8 **bufs, unsigned int start,
+					unsigned int len)
+{
+	unsigned int i;
+	u8 *buf;
+
+	for (; (buf = *bufs); bufs++) {
+		for (i = 0; i < start; i++)
+			buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK);
+		for (; i < start + len; i++)
+			buf[i] = PATTERN_SRC | PATTERN_COPY
+				| (~i & PATTERN_COUNT_MASK);
+		for (; i < test_buf_size; i++)
+			buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK);
+		buf++;
+	}
+}
+
+static void xilinx_vdmatest_init_dsts(u8 **bufs, unsigned int start,
+					unsigned int len)
+{
+	unsigned int i;
+	u8 *buf;
+
+	for (; (buf = *bufs); bufs++) {
+		for (i = 0; i < start; i++)
+			buf[i] = PATTERN_DST | (~i & PATTERN_COUNT_MASK);
+		for (; i < start + len; i++)
+			buf[i] = PATTERN_DST | PATTERN_OVERWRITE
+				| (~i & PATTERN_COUNT_MASK);
+		for (; i < test_buf_size; i++)
+			buf[i] = PATTERN_DST | (~i & PATTERN_COUNT_MASK);
+	}
+}
+
+static void xilinx_vdmatest_mismatch(u8 actual, u8 pattern, unsigned int index,
+		unsigned int counter, bool is_srcbuf)
+{
+	u8 diff = actual ^ pattern;
+	u8 expected = pattern | (~counter & PATTERN_COUNT_MASK);
+	const char *thread_name = current->comm;
+
+	if (is_srcbuf)
+		pr_warn(
+		"%s: srcbuf[0x%x] overwritten! Expected %02x, got %02x\n",
+				thread_name, index, expected, actual);
+	else if ((pattern & PATTERN_COPY)
+			&& (diff & (PATTERN_COPY | PATTERN_OVERWRITE)))
+		pr_warn(
+		"%s: dstbuf[0x%x] not copied! Expected %02x, got %02x\n",
+				thread_name, index, expected, actual);
+	else if (diff & PATTERN_SRC)
+		pr_warn(
+		"%s: dstbuf[0x%x] was copied! Expected %02x, got %02x\n",
+				thread_name, index, expected, actual);
+	else
+		pr_warn(
+		"%s: dstbuf[0x%x] mismatch! Expected %02x, got %02x\n",
+				thread_name, index, expected, actual);
+}
+
+static unsigned int xilinx_vdmatest_verify(u8 **bufs, unsigned int start,
+		unsigned int end, unsigned int counter, u8 pattern,
+		bool is_srcbuf)
+{
+	unsigned int i, error_count = 0;
+	u8 actual, expected, *buf;
+	unsigned int counter_orig = counter;
+
+	for (; (buf = *bufs); bufs++) {
+		counter = counter_orig;
+		for (i = start; i < end; i++) {
+			actual = buf[i];
+			expected = pattern | (~counter & PATTERN_COUNT_MASK);
+			if (actual != expected) {
+				if (error_count < 32)
+					xilinx_vdmatest_mismatch(actual,
+							pattern, i,
+							counter, is_srcbuf);
+				error_count++;
+			}
+			counter++;
+		}
+	}
+
+	if (error_count > 32)
+		pr_warn("%s: %u errors suppressed\n",
+			current->comm, error_count - 32);
+
+	return error_count;
+}
+
+static void xilinx_vdmatest_slave_tx_callback(void *completion)
+{
+	pr_debug("Got tx callback\n");
+	complete(completion);
+}
+
+static void xilinx_vdmatest_slave_rx_callback(void *completion)
+{
+	pr_debug("Got rx callback\n");
+	complete(completion);
+}
+
+/*
+ * Function for slave transfers
+ * Each thread requires 2 channels, one for transmit, and one for receive
+ */
+static int xilinx_vdmatest_slave_func(void *data)
+{
+	struct xilinx_vdmatest_slave_thread *thread = data;
+	struct dma_chan *tx_chan, *rx_chan;
+	const char *thread_name;
+	unsigned int len, error_count;
+	unsigned int failed_tests = 0, total_tests = 0;
+	dma_cookie_t tx_cookie = 0, rx_cookie = 0;
+	enum dma_status status;
+	enum dma_ctrl_flags flags;
+	int ret = -ENOMEM, i;
+	struct xilinx_vdma_config config;
+
+	thread_name = current->comm;
+
+	/* Limit testing scope here */
+	test_buf_size = hsize * vsize;
+
+	/* This barrier ensures 'thread' is initialized and
+	 * we get valid DMA channels
+	 */
+	smp_rmb();
+	tx_chan = thread->tx_chan;
+	rx_chan = thread->rx_chan;
+
+	thread->srcs = kcalloc(frm_cnt+1, sizeof(u8 *), GFP_KERNEL);
+	if (!thread->srcs)
+		goto err_srcs;
+	for (i = 0; i < frm_cnt; i++) {
+		thread->srcs[i] = kmalloc(test_buf_size, GFP_KERNEL);
+		if (!thread->srcs[i])
+			goto err_srcbuf;
+	}
+
+	thread->dsts = kcalloc(frm_cnt+1, sizeof(u8 *), GFP_KERNEL);
+	if (!thread->dsts)
+		goto err_dsts;
+	for (i = 0; i < frm_cnt; i++) {
+		thread->dsts[i] = kmalloc(test_buf_size, GFP_KERNEL);
+		if (!thread->dsts[i])
+			goto err_dstbuf;
+	}
+
+	set_user_nice(current, 10);
+
+	flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
+
+	while (!kthread_should_stop()
+		&& !(iterations && total_tests >= iterations)) {
+		struct dma_device *tx_dev = tx_chan->device;
+		struct dma_device *rx_dev = rx_chan->device;
+		struct dma_async_tx_descriptor *txd = NULL;
+		struct dma_async_tx_descriptor *rxd = NULL;
+		struct completion rx_cmp, tx_cmp;
+		unsigned long rx_tmo =
+				msecs_to_jiffies(30000); /* RX takes longer */
+		unsigned long tx_tmo = msecs_to_jiffies(30000);
+		u8 align = 0;
+
+		total_tests++;
+
+		/* honor larger alignment restrictions */
+		align = tx_dev->copy_align;
+		if (rx_dev->copy_align > align)
+			align = rx_dev->copy_align;
+
+		if (1 << align > test_buf_size) {
+			pr_err("%u-byte buffer too small for %d-byte alignment\n",
+			       test_buf_size, 1 << align);
+			break;
+		}
+
+		len = test_buf_size;
+		xilinx_vdmatest_init_srcs(thread->srcs, 0, len);
+		xilinx_vdmatest_init_dsts(thread->dsts, 0, len);
+
+		/* Zero out configuration */
+		memset(&config, 0, sizeof(struct xilinx_vdma_config));
+
+		/* Set up hardware configuration information */
+		config.frm_cnt_en = 1;
+		config.coalesc = frm_cnt * 10;
+		config.park = 1;
+		xilinx_vdma_channel_set_config(tx_chan, &config);
+
+		xilinx_vdma_channel_set_config(rx_chan, &config);
+
+		for (i = 0; i < frm_cnt; i++) {
+			dma_dsts[i] = dma_map_single(rx_dev->dev,
+							thread->dsts[i],
+							test_buf_size,
+							DMA_DEV_TO_MEM);
+
+			if (dma_mapping_error(rx_dev->dev, dma_dsts[i])) {
+				failed_tests++;
+				continue;
+			}
+			xt.dst_start = dma_dsts[i];
+			xt.dir = DMA_DEV_TO_MEM;
+			xt.numf = vsize;
+			xt.sgl[0].size = hsize;
+			xt.sgl[0].icg = 0;
+			xt.frame_size = 1;
+			rxd = rx_dev->device_prep_interleaved_dma(rx_chan,
+								  &xt, flags);
+			rx_cookie = rxd->tx_submit(rxd);
+		}
+
+		for (i = 0; i < frm_cnt; i++) {
+			u8 *buf = thread->srcs[i];
+
+			dma_srcs[i] = dma_map_single(tx_dev->dev, buf, len,
+							DMA_MEM_TO_DEV);
+
+			if (dma_mapping_error(tx_dev->dev, dma_srcs[i])) {
+				failed_tests++;
+				continue;
+			}
+			xt.src_start = dma_srcs[i];
+			xt.dir = DMA_MEM_TO_DEV;
+			xt.numf = vsize;
+			xt.sgl[0].size = hsize;
+			xt.sgl[0].icg = 0;
+			xt.frame_size = 1;
+			txd = tx_dev->device_prep_interleaved_dma(tx_chan,
+								  &xt, flags);
+			tx_cookie = txd->tx_submit(txd);
+		}
+
+		if (!rxd || !txd) {
+			for (i = 0; i < frm_cnt; i++)
+				dma_unmap_single(tx_dev->dev, dma_srcs[i], len,
+						DMA_MEM_TO_DEV);
+			for (i = 0; i < frm_cnt; i++)
+				dma_unmap_single(rx_dev->dev, dma_dsts[i],
+						test_buf_size,
+						DMA_DEV_TO_MEM);
+			pr_warn("%s: #%u: prep error with len=0x%x ",
+					thread_name, total_tests - 1, len);
+			msleep(100);
+			failed_tests++;
+			continue;
+		}
+
+		init_completion(&rx_cmp);
+		rxd->callback = xilinx_vdmatest_slave_rx_callback;
+		rxd->callback_param = &rx_cmp;
+
+		init_completion(&tx_cmp);
+		txd->callback = xilinx_vdmatest_slave_tx_callback;
+		txd->callback_param = &tx_cmp;
+
+		if (dma_submit_error(rx_cookie) ||
+				dma_submit_error(tx_cookie)) {
+			pr_warn("%s: #%u: submit error %d/%d with len=0x%x ",
+					thread_name, total_tests - 1,
+					rx_cookie, tx_cookie, len);
+			msleep(100);
+			failed_tests++;
+			continue;
+		}
+		dma_async_issue_pending(tx_chan);
+		dma_async_issue_pending(rx_chan);
+
+		tx_tmo = wait_for_completion_timeout(&tx_cmp, tx_tmo);
+
+		status = dma_async_is_tx_complete(tx_chan, tx_cookie,
+							NULL, NULL);
+
+		if (tx_tmo == 0) {
+			pr_warn("%s: #%u: tx test timed out\n",
+					thread_name, total_tests - 1);
+			failed_tests++;
+			continue;
+		} else if (status != DMA_COMPLETE) {
+			pr_warn(
+			"%s: #%u: tx got completion callback, ",
+				   thread_name, total_tests - 1);
+			pr_warn("but status is \'%s\'\n",
+				   status == DMA_ERROR ? "error" :
+							"in progress");
+			failed_tests++;
+			continue;
+		}
+
+		rx_tmo = wait_for_completion_timeout(&rx_cmp, rx_tmo);
+		status = dma_async_is_tx_complete(rx_chan, rx_cookie,
+							NULL, NULL);
+
+		if (rx_tmo == 0) {
+			pr_warn("%s: #%u: rx test timed out\n",
+					thread_name, total_tests - 1);
+			failed_tests++;
+			continue;
+		} else if (status != DMA_COMPLETE) {
+			pr_warn(
+			"%s: #%u: rx got completion callback, ",
+					thread_name, total_tests - 1);
+			pr_warn("but status is \'%s\'\n",
+					status == DMA_ERROR ? "error" :
+							"in progress");
+			failed_tests++;
+			continue;
+		}
+
+		/* Unmap by myself */
+		for (i = 0; i < frm_cnt; i++)
+			dma_unmap_single(rx_dev->dev, dma_dsts[i],
+					 test_buf_size, DMA_DEV_TO_MEM);
+
+		error_count = 0;
+
+		pr_debug("%s: verifying source buffer...\n", thread_name);
+		error_count += xilinx_vdmatest_verify(thread->srcs, 0, 0,
+				0, PATTERN_SRC, true);
+		error_count += xilinx_vdmatest_verify(thread->srcs, 0,
+				len, 0, PATTERN_SRC | PATTERN_COPY, true);
+		error_count += xilinx_vdmatest_verify(thread->srcs, len,
+				test_buf_size, len, PATTERN_SRC, true);
+
+		pr_debug("%s: verifying dest buffer...\n",
+				thread->task->comm);
+		error_count += xilinx_vdmatest_verify(thread->dsts, 0, 0,
+				0, PATTERN_DST, false);
+		error_count += xilinx_vdmatest_verify(thread->dsts, 0,
+				len, 0, PATTERN_SRC | PATTERN_COPY, false);
+		error_count += xilinx_vdmatest_verify(thread->dsts, len,
+				test_buf_size, len, PATTERN_DST, false);
+
+		if (error_count) {
+			pr_warn("%s: #%u: %u errors with len=0x%x\n",
+				thread_name, total_tests - 1, error_count, len);
+			failed_tests++;
+		} else {
+			pr_debug("%s: #%u: No errors with len=0x%x\n",
+				thread_name, total_tests - 1, len);
+		}
+	}
+
+	ret = 0;
+	for (i = 0; thread->dsts[i]; i++)
+		kfree(thread->dsts[i]);
+err_dstbuf:
+	kfree(thread->dsts);
+err_dsts:
+	for (i = 0; thread->srcs[i]; i++)
+		kfree(thread->srcs[i]);
+err_srcbuf:
+	kfree(thread->srcs);
+err_srcs:
+	pr_notice("%s: terminating after %u tests, %u failures (status %d)\n",
+			thread_name, total_tests, failed_tests, ret);
+
+	thread->done = true;
+	wake_up(&thread_wait);
+
+	return ret;
+}
+
+static void xilinx_vdmatest_cleanup_channel(struct xilinx_vdmatest_chan *dtc)
+{
+	struct xilinx_vdmatest_slave_thread *thread, *_thread;
+	int ret;
+
+	list_for_each_entry_safe(thread, _thread,
+				&dtc->threads, node) {
+		ret = kthread_stop(thread->task);
+		pr_info("xilinx_vdmatest: thread %s exited with status %d\n",
+				thread->task->comm, ret);
+		list_del(&thread->node);
+		put_task_struct(thread->task);
+		kfree(thread);
+	}
+	kfree(dtc);
+}
+
+static int
+xilinx_vdmatest_add_slave_threads(struct xilinx_vdmatest_chan *tx_dtc,
+					struct xilinx_vdmatest_chan *rx_dtc)
+{
+	struct xilinx_vdmatest_slave_thread *thread;
+	struct dma_chan *tx_chan = tx_dtc->chan;
+	struct dma_chan *rx_chan = rx_dtc->chan;
+
+	thread = kzalloc(sizeof(struct xilinx_vdmatest_slave_thread),
+			GFP_KERNEL);
+	if (!thread)
+		pr_warn("xilinx_vdmatest: No memory for slave thread %s-%s\n",
+			   dma_chan_name(tx_chan), dma_chan_name(rx_chan));
+
+	thread->tx_chan = tx_chan;
+	thread->rx_chan = rx_chan;
+	thread->type = (enum dma_transaction_type)DMA_SLAVE;
+
+	/* This barrier ensures the DMA channels in the 'thread'
+	 * are initialized
+	 */
+	smp_wmb();
+	thread->task = kthread_run(xilinx_vdmatest_slave_func, thread, "%s-%s",
+		dma_chan_name(tx_chan), dma_chan_name(rx_chan));
+	if (IS_ERR(thread->task)) {
+		pr_warn("xilinx_vdmatest: Failed to run thread %s-%s\n",
+				dma_chan_name(tx_chan), dma_chan_name(rx_chan));
+		kfree(thread);
+		return PTR_ERR(thread->task);
+	}
+
+	get_task_struct(thread->task);
+	list_add_tail(&thread->node, &tx_dtc->threads);
+
+	/* Added one thread with 2 channels */
+	return 1;
+}
+
+static int xilinx_vdmatest_add_slave_channels(struct dma_chan *tx_chan,
+					struct dma_chan *rx_chan)
+{
+	struct xilinx_vdmatest_chan *tx_dtc, *rx_dtc;
+	unsigned int thread_count = 0;
+
+	tx_dtc = kmalloc(sizeof(struct xilinx_vdmatest_chan), GFP_KERNEL);
+	if (!tx_dtc)
+		return -ENOMEM;
+
+	rx_dtc = kmalloc(sizeof(struct xilinx_vdmatest_chan), GFP_KERNEL);
+	if (!rx_dtc)
+		return -ENOMEM;
+
+	tx_dtc->chan = tx_chan;
+	rx_dtc->chan = rx_chan;
+	INIT_LIST_HEAD(&tx_dtc->threads);
+	INIT_LIST_HEAD(&rx_dtc->threads);
+
+	xilinx_vdmatest_add_slave_threads(tx_dtc, rx_dtc);
+	thread_count += 1;
+
+	pr_info("xilinx_vdmatest: Started %u threads using %s %s\n",
+		thread_count, dma_chan_name(tx_chan), dma_chan_name(rx_chan));
+
+	list_add_tail(&tx_dtc->node, &xilinx_vdmatest_channels);
+	list_add_tail(&rx_dtc->node, &xilinx_vdmatest_channels);
+	nr_channels += 2;
+
+	if (iterations)
+		wait_event(thread_wait, !is_threaded_test_run(tx_dtc, rx_dtc));
+
+	return 0;
+}
+
+static int xilinx_vdmatest_probe(struct platform_device *pdev)
+{
+	struct dma_chan *chan, *rx_chan;
+	int err;
+
+	err = of_property_read_u32(pdev->dev.of_node,
+					"xlnx,num-fstores", &frm_cnt);
+	if (err < 0) {
+		pr_err("xilinx_vdmatest: missing xlnx,num-fstores property\n");
+		return err;
+	}
+
+	chan = dma_request_slave_channel(&pdev->dev, "vdma0");
+	if (IS_ERR(chan)) {
+		pr_err("xilinx_vdmatest: No Tx channel\n");
+		return PTR_ERR(chan);
+	}
+
+	rx_chan = dma_request_slave_channel(&pdev->dev, "vdma1");
+	if (IS_ERR(rx_chan)) {
+		err = PTR_ERR(rx_chan);
+		pr_err("xilinx_vdmatest: No Rx channel\n");
+		goto free_tx;
+	}
+
+	err = xilinx_vdmatest_add_slave_channels(chan, rx_chan);
+	if (err) {
+		pr_err("xilinx_vdmatest: Unable to add channels\n");
+		goto free_rx;
+	}
+	return 0;
+
+free_rx:
+	dma_release_channel(rx_chan);
+free_tx:
+	dma_release_channel(chan);
+
+	return err;
+}
+
+static int xilinx_vdmatest_remove(struct platform_device *pdev)
+{
+	struct xilinx_vdmatest_chan *dtc, *_dtc;
+	struct dma_chan *chan;
+
+	list_for_each_entry_safe(dtc, _dtc, &xilinx_vdmatest_channels, node) {
+		list_del(&dtc->node);
+		chan = dtc->chan;
+		xilinx_vdmatest_cleanup_channel(dtc);
+		pr_info("xilinx_vdmatest: dropped channel %s\n",
+			dma_chan_name(chan));
+		dmaengine_terminate_async(chan);
+		dma_release_channel(chan);
+	}
+	return 0;
+}
+
+static const struct of_device_id xilinx_vdmatest_of_ids[] = {
+	{ .compatible = "xlnx,axi-vdma-test-1.00.a",},
+	{}
+};
+
+static struct platform_driver xilinx_vdmatest_driver = {
+	.driver = {
+		.name = "xilinx_vdmatest",
+		.owner = THIS_MODULE,
+		.of_match_table = xilinx_vdmatest_of_ids,
+	},
+	.probe = xilinx_vdmatest_probe,
+	.remove = xilinx_vdmatest_remove,
+};
+
+module_platform_driver(xilinx_vdmatest_driver);
+
+MODULE_AUTHOR("Xilinx, Inc.");
+MODULE_DESCRIPTION("Xilinx AXI VDMA Test Client");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/xilinx/xilinx_dma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/xilinx/xilinx_dma.c
@@ -25,6 +25,12 @@
  * The AXI CDMA, is a soft IP, which provides high-bandwidth Direct Memory
  * Access (DMA) between a memory-mapped source address and a memory-mapped
  * destination address.
+ *
+ * The AXI Multichannel Direct Memory Access (AXI MCDMA) core is a soft
+ * Xilinx IP that provides high-bandwidth direct memory access between
+ * memory and AXI4-Stream target peripherals. It provides scatter gather
+ * (SG) interface with multiple channels independent configuration support.
+ *
  */
 
 #include <linux/bitops.h>
@@ -119,7 +125,9 @@
 #define XILINX_VDMA_ENABLE_VERTICAL_FLIP	BIT(0)
 
 /* HW specific definitions */
-#define XILINX_DMA_MAX_CHANS_PER_DEVICE	0x20
+#define XILINX_MCDMA_MAX_CHANS_PER_DEVICE	0x20
+#define XILINX_DMA_MAX_CHANS_PER_DEVICE		0x2
+#define XILINX_CDMA_MAX_CHANS_PER_DEVICE	0x1
 
 #define XILINX_DMA_DMAXR_ALL_IRQ_MASK	\
 		(XILINX_DMA_DMASR_FRM_CNT_IRQ | \
@@ -173,18 +181,6 @@
 #define XILINX_DMA_NUM_DESCS		255
 #define XILINX_DMA_NUM_APP_WORDS	5
 
-/* Multi-Channel DMA Descriptor offsets*/
-#define XILINX_DMA_MCRX_CDESC(x)	(0x40 + (x-1) * 0x20)
-#define XILINX_DMA_MCRX_TDESC(x)	(0x48 + (x-1) * 0x20)
-
-/* Multi-Channel DMA Masks/Shifts */
-#define XILINX_DMA_BD_HSIZE_MASK	GENMASK(15, 0)
-#define XILINX_DMA_BD_STRIDE_MASK	GENMASK(15, 0)
-#define XILINX_DMA_BD_VSIZE_MASK	GENMASK(31, 19)
-#define XILINX_DMA_BD_TDEST_MASK	GENMASK(4, 0)
-#define XILINX_DMA_BD_STRIDE_SHIFT	0
-#define XILINX_DMA_BD_VSIZE_SHIFT	19
-
 /* AXI CDMA Specific Registers/Offsets */
 #define XILINX_CDMA_REG_SRCADDR		0x18
 #define XILINX_CDMA_REG_DSTADDR		0x20
@@ -194,6 +190,31 @@
 
 #define xilinx_prep_dma_addr_t(addr)	\
 	((dma_addr_t)((u64)addr##_##msb << 32 | (addr)))
+
+/* AXI MCDMA Specific Registers/Offsets */
+#define XILINX_MCDMA_MM2S_CTRL_OFFSET		0x0000
+#define XILINX_MCDMA_S2MM_CTRL_OFFSET		0x0500
+#define XILINX_MCDMA_CHEN_OFFSET		0x0008
+#define XILINX_MCDMA_CH_ERR_OFFSET		0x0010
+#define XILINX_MCDMA_RXINT_SER_OFFSET		0x0020
+#define XILINX_MCDMA_TXINT_SER_OFFSET		0x0028
+#define XILINX_MCDMA_CHAN_CR_OFFSET(x)		(0x40 + (x) * 0x40)
+#define XILINX_MCDMA_CHAN_SR_OFFSET(x)		(0x44 + (x) * 0x40)
+#define XILINX_MCDMA_CHAN_CDESC_OFFSET(x)	(0x48 + (x) * 0x40)
+#define XILINX_MCDMA_CHAN_TDESC_OFFSET(x)	(0x50 + (x) * 0x40)
+
+/* AXI MCDMA Specific Masks/Shifts */
+#define XILINX_MCDMA_COALESCE_SHIFT		16
+#define XILINX_MCDMA_COALESCE_MAX		24
+#define XILINX_MCDMA_IRQ_ALL_MASK		GENMASK(7, 5)
+#define XILINX_MCDMA_COALESCE_MASK		GENMASK(23, 16)
+#define XILINX_MCDMA_CR_RUNSTOP_MASK		BIT(0)
+#define XILINX_MCDMA_IRQ_IOC_MASK		BIT(5)
+#define XILINX_MCDMA_IRQ_DELAY_MASK		BIT(6)
+#define XILINX_MCDMA_IRQ_ERR_MASK		BIT(7)
+#define XILINX_MCDMA_BD_EOP			BIT(30)
+#define XILINX_MCDMA_BD_SOP			BIT(31)
+
 /**
  * struct xilinx_vdma_desc_hw - Hardware Descriptor
  * @next_desc: Next Descriptor Pointer @0x00
@@ -221,8 +242,8 @@
  * @next_desc_msb: MSB of Next Descriptor Pointer @0x04
  * @buf_addr: Buffer address @0x08
  * @buf_addr_msb: MSB of Buffer address @0x0C
- * @mcdma_control: Control field for mcdma @0x10
- * @vsize_stride: Vsize and Stride field for mcdma @0x14
+ * @reserved1: Reserved @0x10
+ * @reserved2: Reserved @0x14
  * @control: Control field @0x18
  * @status: Status field @0x1C
  * @app: APP Fields @0x20 - 0x30
@@ -232,10 +253,34 @@
 	u32 next_desc_msb;
 	u32 buf_addr;
 	u32 buf_addr_msb;
-	u32 mcdma_control;
-	u32 vsize_stride;
+	u32 reserved1;
+	u32 reserved2;
+	u32 control;
+	u32 status;
+	u32 app[XILINX_DMA_NUM_APP_WORDS];
+} __aligned(64);
+
+/**
+ * struct xilinx_aximcdma_desc_hw - Hardware Descriptor for AXI MCDMA
+ * @next_desc: Next Descriptor Pointer @0x00
+ * @next_desc_msb: MSB of Next Descriptor Pointer @0x04
+ * @buf_addr: Buffer address @0x08
+ * @buf_addr_msb: MSB of Buffer address @0x0C
+ * @rsvd: Reserved field @0x10
+ * @control: Control Information field @0x14
+ * @status: Status field @0x18
+ * @sideband_status: Status of sideband signals @0x1C
+ * @app: APP Fields @0x20 - 0x30
+ */
+struct xilinx_aximcdma_desc_hw {
+	u32 next_desc;
+	u32 next_desc_msb;
+	u32 buf_addr;
+	u32 buf_addr_msb;
+	u32 rsvd;
 	u32 control;
 	u32 status;
+	u32 sideband_status;
 	u32 app[XILINX_DMA_NUM_APP_WORDS];
 } __aligned(64);
 
@@ -286,6 +331,18 @@
 } __aligned(64);
 
 /**
+ * struct xilinx_aximcdma_tx_segment - Descriptor segment
+ * @hw: Hardware descriptor
+ * @node: Node in the descriptor segments list
+ * @phys: Physical address of segment
+ */
+struct xilinx_aximcdma_tx_segment {
+	struct xilinx_aximcdma_desc_hw hw;
+	struct list_head node;
+	dma_addr_t phys;
+} __aligned(64);
+
+/**
  * struct xilinx_cdma_tx_segment - Descriptor segment
  * @hw: Hardware descriptor
  * @node: Node in the descriptor segments list
@@ -303,12 +360,16 @@
  * @segments: TX segments list
  * @node: Node in the channel descriptors list
  * @cyclic: Check for cyclic transfers.
+ * @err: Whether the descriptor has an error.
+ * @residue: Residue of the completed descriptor
  */
 struct xilinx_dma_tx_descriptor {
 	struct dma_async_tx_descriptor async_tx;
 	struct list_head segments;
 	struct list_head node;
 	bool cyclic;
+	bool err;
+	u32 residue;
 };
 
 /**
@@ -333,14 +394,15 @@
  * @genlock: Support genlock mode
  * @err: Channel has errors
  * @idle: Check for channel idle
+ * @terminating: Check for channel being synchronized by user
  * @tasklet: Cleanup work after irq
  * @config: Device configuration info
  * @flush_on_fsync: Flush on Frame sync
  * @desc_pendingcount: Descriptor pending count
  * @ext_addr: Indicates 64 bit addressing is supported by dma channel
  * @desc_submitcount: Descriptor h/w submitted count
- * @residue: Residue for AXI DMA
  * @seg_v: Statically allocated segments base
+ * @seg_mv: Statically allocated segments base for MCDMA
  * @seg_p: Physical allocated segments base
  * @cyclic_seg_v: Statically allocated segment base for cyclic transfers
  * @cyclic_seg_p: Physical allocated segments base for cyclic dma
@@ -370,14 +432,15 @@
 	bool genlock;
 	bool err;
 	bool idle;
+	bool terminating;
 	struct tasklet_struct tasklet;
 	struct xilinx_vdma_config config;
 	bool flush_on_fsync;
 	u32 desc_pendingcount;
 	bool ext_addr;
 	u32 desc_submitcount;
-	u32 residue;
 	struct xilinx_axidma_tx_segment *seg_v;
+	struct xilinx_aximcdma_tx_segment *seg_mv;
 	dma_addr_t seg_p;
 	struct xilinx_axidma_tx_segment *cyclic_seg_v;
 	dma_addr_t cyclic_seg_p;
@@ -393,12 +456,14 @@
  * @XDMA_TYPE_AXIDMA: Axi dma ip.
  * @XDMA_TYPE_CDMA: Axi cdma ip.
  * @XDMA_TYPE_VDMA: Axi vdma ip.
+ * @XDMA_TYPE_AXIMCDMA: Axi MCDMA ip.
  *
  */
 enum xdma_ip_type {
 	XDMA_TYPE_AXIDMA = 0,
 	XDMA_TYPE_CDMA,
 	XDMA_TYPE_VDMA,
+	XDMA_TYPE_AXIMCDMA
 };
 
 struct xilinx_dma_config {
@@ -406,6 +471,8 @@
 	int (*clk_init)(struct platform_device *pdev, struct clk **axi_clk,
 			struct clk **tx_clk, struct clk **txs_clk,
 			struct clk **rx_clk, struct clk **rxs_clk);
+	irqreturn_t (*irq_handler)(int irq, void *data);
+	const int max_channels;
 };
 
 /**
@@ -414,7 +481,6 @@
  * @dev: Device Structure
  * @common: DMA device structure
  * @chan: Driver specific DMA channel
- * @mcdma: Specifies whether Multi-Channel is present or not
  * @flush_on_fsync: Flush on frame sync
  * @ext_addr: Indicates 64 bit addressing is supported by dma device
  * @pdev: Platform device structure pointer
@@ -424,16 +490,15 @@
  * @txs_clk: DMA mm2s stream clock
  * @rx_clk: DMA s2mm clock
  * @rxs_clk: DMA s2mm stream clock
- * @nr_channels: Number of channels DMA device supports
- * @chan_id: DMA channel identifier
+ * @s2mm_chan_id: DMA s2mm channel identifier
+ * @mm2s_chan_id: DMA mm2s channel identifier
  * @max_buffer_len: Max buffer length
  */
 struct xilinx_dma_device {
 	void __iomem *regs;
 	struct device *dev;
 	struct dma_device common;
-	struct xilinx_dma_chan *chan[XILINX_DMA_MAX_CHANS_PER_DEVICE];
-	bool mcdma;
+	struct xilinx_dma_chan *chan[XILINX_MCDMA_MAX_CHANS_PER_DEVICE];
 	u32 flush_on_fsync;
 	bool ext_addr;
 	struct platform_device  *pdev;
@@ -443,8 +508,8 @@
 	struct clk *txs_clk;
 	struct clk *rx_clk;
 	struct clk *rxs_clk;
-	u32 nr_channels;
-	u32 chan_id;
+	u32 s2mm_chan_id;
+	u32 mm2s_chan_id;
 	u32 max_buffer_len;
 };
 
@@ -454,8 +519,8 @@
 #define to_dma_tx_descriptor(tx) \
 	container_of(tx, struct xilinx_dma_tx_descriptor, async_tx)
 #define xilinx_dma_poll_timeout(chan, reg, val, cond, delay_us, timeout_us) \
-	readl_poll_timeout(chan->xdev->regs + chan->ctrl_offset + reg, val, \
-			   cond, delay_us, timeout_us)
+	readl_poll_timeout_atomic(chan->xdev->regs + chan->ctrl_offset + reg, \
+				  val, cond, delay_us, timeout_us)
 
 /* IO accessors */
 static inline u32 dma_read(struct xilinx_dma_chan *chan, u32 reg)
@@ -546,6 +611,18 @@
 	}
 }
 
+static inline void xilinx_aximcdma_buf(struct xilinx_dma_chan *chan,
+				       struct xilinx_aximcdma_desc_hw *hw,
+				       dma_addr_t buf_addr, size_t sg_used)
+{
+	if (chan->ext_addr) {
+		hw->buf_addr = lower_32_bits(buf_addr + sg_used);
+		hw->buf_addr_msb = upper_32_bits(buf_addr + sg_used);
+	} else {
+		hw->buf_addr = buf_addr + sg_used;
+	}
+}
+
 /* -----------------------------------------------------------------------------
  * Descriptors and segments alloc and free
  */
@@ -613,6 +690,33 @@
 	}
 	spin_unlock_irqrestore(&chan->lock, flags);
 
+	if (!segment)
+		dev_dbg(chan->dev, "Could not find free tx segment\n");
+
+	return segment;
+}
+
+/**
+ * xilinx_aximcdma_alloc_tx_segment - Allocate transaction segment
+ * @chan: Driver specific DMA channel
+ *
+ * Return: The allocated segment on success and NULL on failure.
+ */
+static struct xilinx_aximcdma_tx_segment *
+xilinx_aximcdma_alloc_tx_segment(struct xilinx_dma_chan *chan)
+{
+	struct xilinx_aximcdma_tx_segment *segment = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&chan->lock, flags);
+	if (!list_empty(&chan->free_seg_list)) {
+		segment = list_first_entry(&chan->free_seg_list,
+					   struct xilinx_aximcdma_tx_segment,
+					   node);
+		list_del(&segment->node);
+	}
+	spin_unlock_irqrestore(&chan->lock, flags);
+
 	return segment;
 }
 
@@ -627,6 +731,17 @@
 	hw->next_desc_msb = next_desc_msb;
 }
 
+static void xilinx_mcdma_clean_hw_desc(struct xilinx_aximcdma_desc_hw *hw)
+{
+	u32 next_desc = hw->next_desc;
+	u32 next_desc_msb = hw->next_desc_msb;
+
+	memset(hw, 0, sizeof(struct xilinx_aximcdma_desc_hw));
+
+	hw->next_desc = next_desc;
+	hw->next_desc_msb = next_desc_msb;
+}
+
 /**
  * xilinx_dma_free_tx_segment - Free transaction segment
  * @chan: Driver specific DMA channel
@@ -641,6 +756,20 @@
 }
 
 /**
+ * xilinx_mcdma_free_tx_segment - Free transaction segment
+ * @chan: Driver specific DMA channel
+ * @segment: DMA transaction segment
+ */
+static void xilinx_mcdma_free_tx_segment(struct xilinx_dma_chan *chan,
+					 struct xilinx_aximcdma_tx_segment *
+					 segment)
+{
+	xilinx_mcdma_clean_hw_desc(&segment->hw);
+
+	list_add_tail(&segment->node, &chan->free_seg_list);
+}
+
+/**
  * xilinx_cdma_free_tx_segment - Free transaction segment
  * @chan: Driver specific DMA channel
  * @segment: DMA transaction segment
@@ -694,6 +823,7 @@
 	struct xilinx_vdma_tx_segment *segment, *next;
 	struct xilinx_cdma_tx_segment *cdma_segment, *cdma_next;
 	struct xilinx_axidma_tx_segment *axidma_segment, *axidma_next;
+	struct xilinx_aximcdma_tx_segment *aximcdma_segment, *aximcdma_next;
 
 	if (!desc)
 		return;
@@ -709,12 +839,18 @@
 			list_del(&cdma_segment->node);
 			xilinx_cdma_free_tx_segment(chan, cdma_segment);
 		}
-	} else {
+	} else if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
 		list_for_each_entry_safe(axidma_segment, axidma_next,
 					 &desc->segments, node) {
 			list_del(&axidma_segment->node);
 			xilinx_dma_free_tx_segment(chan, axidma_segment);
 		}
+	} else {
+		list_for_each_entry_safe(aximcdma_segment, aximcdma_next,
+					 &desc->segments, node) {
+			list_del(&aximcdma_segment->node);
+			xilinx_mcdma_free_tx_segment(chan, aximcdma_segment);
+		}
 	}
 
 	kfree(desc);
@@ -783,10 +919,73 @@
 				  chan->cyclic_seg_v, chan->cyclic_seg_p);
 	}
 
-	if (chan->xdev->dma_config->dmatype != XDMA_TYPE_AXIDMA) {
+	if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIMCDMA) {
+		spin_lock_irqsave(&chan->lock, flags);
+		INIT_LIST_HEAD(&chan->free_seg_list);
+		spin_unlock_irqrestore(&chan->lock, flags);
+
+		/* Free memory that is allocated for BD */
+		dma_free_coherent(chan->dev, sizeof(*chan->seg_mv) *
+				  XILINX_DMA_NUM_DESCS, chan->seg_mv,
+				  chan->seg_p);
+	}
+
+	if (chan->xdev->dma_config->dmatype != XDMA_TYPE_AXIDMA &&
+	    chan->xdev->dma_config->dmatype != XDMA_TYPE_AXIMCDMA) {
 		dma_pool_destroy(chan->desc_pool);
 		chan->desc_pool = NULL;
 	}
+
+}
+
+/**
+ * xilinx_dma_get_residue - Compute residue for a given descriptor
+ * @chan: Driver specific dma channel
+ * @desc: dma transaction descriptor
+ *
+ * Return: The number of residue bytes for the descriptor.
+ */
+static u32 xilinx_dma_get_residue(struct xilinx_dma_chan *chan,
+				  struct xilinx_dma_tx_descriptor *desc)
+{
+	struct xilinx_cdma_tx_segment *cdma_seg;
+	struct xilinx_axidma_tx_segment *axidma_seg;
+	struct xilinx_aximcdma_tx_segment *aximcdma_seg;
+	struct xilinx_cdma_desc_hw *cdma_hw;
+	struct xilinx_axidma_desc_hw *axidma_hw;
+	struct xilinx_aximcdma_desc_hw *aximcdma_hw;
+	struct list_head *entry;
+	u32 residue = 0;
+
+	list_for_each(entry, &desc->segments) {
+		if (chan->xdev->dma_config->dmatype == XDMA_TYPE_CDMA) {
+			cdma_seg = list_entry(entry,
+					      struct xilinx_cdma_tx_segment,
+					      node);
+			cdma_hw = &cdma_seg->hw;
+			residue += (cdma_hw->control - cdma_hw->status) &
+				   chan->xdev->max_buffer_len;
+		} else if (chan->xdev->dma_config->dmatype ==
+			   XDMA_TYPE_AXIDMA) {
+			axidma_seg = list_entry(entry,
+						struct xilinx_axidma_tx_segment,
+						node);
+			axidma_hw = &axidma_seg->hw;
+			residue += (axidma_hw->control - axidma_hw->status) &
+				   chan->xdev->max_buffer_len;
+		} else {
+			aximcdma_seg =
+				list_entry(entry,
+					   struct xilinx_aximcdma_tx_segment,
+					   node);
+			aximcdma_hw = &aximcdma_seg->hw;
+			residue +=
+				(aximcdma_hw->control - aximcdma_hw->status) &
+				chan->xdev->max_buffer_len;
+		}
+	}
+
+	return residue;
 }
 
 /**
@@ -823,7 +1022,7 @@
 	spin_lock_irqsave(&chan->lock, flags);
 
 	list_for_each_entry_safe(desc, next, &chan->done_list, node) {
-		struct dmaengine_desc_callback cb;
+		struct dmaengine_result result;
 
 		if (desc->cyclic) {
 			xilinx_dma_chan_handle_cyclic(chan, desc, &flags);
@@ -833,17 +1032,32 @@
 		/* Remove from the list of running transactions */
 		list_del(&desc->node);
 
-		/* Run the link descriptor callback function */
-		dmaengine_desc_get_callback(&desc->async_tx, &cb);
-		if (dmaengine_desc_callback_valid(&cb)) {
-			spin_unlock_irqrestore(&chan->lock, flags);
-			dmaengine_desc_callback_invoke(&cb, NULL);
-			spin_lock_irqsave(&chan->lock, flags);
+		if (unlikely(desc->err)) {
+			if (chan->direction == DMA_DEV_TO_MEM)
+				result.result = DMA_TRANS_READ_FAILED;
+			else
+				result.result = DMA_TRANS_WRITE_FAILED;
+		} else {
+			result.result = DMA_TRANS_NOERROR;
 		}
 
+		result.residue = desc->residue;
+
+		/* Run the link descriptor callback function */
+		spin_unlock_irqrestore(&chan->lock, flags);
+		dmaengine_desc_get_callback_invoke(&desc->async_tx, &result);
+		spin_lock_irqsave(&chan->lock, flags);
+
 		/* Run any dependencies, then free the descriptor */
 		dma_run_dependencies(&desc->async_tx);
 		xilinx_dma_free_tx_descriptor(chan, desc);
+
+		/*
+		 * While we ran a callback the user called a terminate function,
+		 * which takes care of cleaning up any remaining descriptors
+		 */
+		if (chan->terminating)
+			break;
 	}
 
 	spin_unlock_irqrestore(&chan->lock, flags);
@@ -922,6 +1136,30 @@
 			list_add_tail(&chan->seg_v[i].node,
 				      &chan->free_seg_list);
 		}
+	} else if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIMCDMA) {
+		/* Allocate the buffer descriptors. */
+		chan->seg_mv = dma_alloc_coherent(chan->dev,
+						  sizeof(*chan->seg_mv) *
+						  XILINX_DMA_NUM_DESCS,
+						  &chan->seg_p, GFP_KERNEL);
+		if (!chan->seg_mv) {
+			dev_err(chan->dev,
+				"unable to allocate channel %d descriptors\n",
+				chan->id);
+			return -ENOMEM;
+		}
+		for (i = 0; i < XILINX_DMA_NUM_DESCS; i++) {
+			chan->seg_mv[i].hw.next_desc =
+			lower_32_bits(chan->seg_p + sizeof(*chan->seg_mv) *
+				((i + 1) % XILINX_DMA_NUM_DESCS));
+			chan->seg_mv[i].hw.next_desc_msb =
+			upper_32_bits(chan->seg_p + sizeof(*chan->seg_mv) *
+				((i + 1) % XILINX_DMA_NUM_DESCS));
+			chan->seg_mv[i].phys = chan->seg_p +
+				sizeof(*chan->seg_mv) * i;
+			list_add_tail(&chan->seg_mv[i].node,
+				      &chan->free_seg_list);
+		}
 	} else if (chan->xdev->dma_config->dmatype == XDMA_TYPE_CDMA) {
 		chan->desc_pool = dma_pool_create("xilinx_cdma_desc_pool",
 				   chan->dev,
@@ -937,7 +1175,8 @@
 	}
 
 	if (!chan->desc_pool &&
-	    (chan->xdev->dma_config->dmatype != XDMA_TYPE_AXIDMA)) {
+	    ((chan->xdev->dma_config->dmatype != XDMA_TYPE_AXIDMA) &&
+		chan->xdev->dma_config->dmatype != XDMA_TYPE_AXIMCDMA)) {
 		dev_err(chan->dev,
 			"unable to allocate channel %d descriptor pool\n",
 			chan->id);
@@ -1003,8 +1242,6 @@
 {
 	struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
 	struct xilinx_dma_tx_descriptor *desc;
-	struct xilinx_axidma_tx_segment *segment;
-	struct xilinx_axidma_desc_hw *hw;
 	enum dma_status ret;
 	unsigned long flags;
 	u32 residue = 0;
@@ -1013,23 +1250,20 @@
 	if (ret == DMA_COMPLETE || !txstate)
 		return ret;
 
-	if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
-		spin_lock_irqsave(&chan->lock, flags);
-
+	spin_lock_irqsave(&chan->lock, flags);
+	if (!list_empty(&chan->active_list)) {
 		desc = list_last_entry(&chan->active_list,
 				       struct xilinx_dma_tx_descriptor, node);
-		if (chan->has_sg) {
-			list_for_each_entry(segment, &desc->segments, node) {
-				hw = &segment->hw;
-				residue += (hw->control - hw->status) &
-					   chan->xdev->max_buffer_len;
-			}
-		}
-		spin_unlock_irqrestore(&chan->lock, flags);
-
-		chan->residue = residue;
-		dma_set_residue(txstate, chan->residue);
+		/*
+		 * VDMA and simple mode do not support residue reporting, so the
+		 * residue field will always be 0.
+		 */
+		if (chan->has_sg && chan->xdev->dma_config->dmatype != XDMA_TYPE_VDMA)
+			residue = xilinx_dma_get_residue(chan, desc);
 	}
+	spin_unlock_irqrestore(&chan->lock, flags);
+
+	dma_set_residue(txstate, residue);
 
 	return ret;
 }
@@ -1301,53 +1535,23 @@
 		dma_ctrl_write(chan, XILINX_DMA_REG_DMACR, reg);
 	}
 
-	if (chan->has_sg && !chan->xdev->mcdma)
+	if (chan->has_sg)
 		xilinx_write(chan, XILINX_DMA_REG_CURDESC,
 			     head_desc->async_tx.phys);
 
-	if (chan->has_sg && chan->xdev->mcdma) {
-		if (chan->direction == DMA_MEM_TO_DEV) {
-			dma_ctrl_write(chan, XILINX_DMA_REG_CURDESC,
-				       head_desc->async_tx.phys);
-		} else {
-			if (!chan->tdest) {
-				dma_ctrl_write(chan, XILINX_DMA_REG_CURDESC,
-				       head_desc->async_tx.phys);
-			} else {
-				dma_ctrl_write(chan,
-					XILINX_DMA_MCRX_CDESC(chan->tdest),
-				       head_desc->async_tx.phys);
-			}
-		}
-	}
-
 	xilinx_dma_start(chan);
 
 	if (chan->err)
 		return;
 
 	/* Start the transfer */
-	if (chan->has_sg && !chan->xdev->mcdma) {
+	if (chan->has_sg) {
 		if (chan->cyclic)
 			xilinx_write(chan, XILINX_DMA_REG_TAILDESC,
 				     chan->cyclic_seg_v->phys);
 		else
 			xilinx_write(chan, XILINX_DMA_REG_TAILDESC,
 				     tail_segment->phys);
-	} else if (chan->has_sg && chan->xdev->mcdma) {
-		if (chan->direction == DMA_MEM_TO_DEV) {
-			dma_ctrl_write(chan, XILINX_DMA_REG_TAILDESC,
-			       tail_segment->phys);
-		} else {
-			if (!chan->tdest) {
-				dma_ctrl_write(chan, XILINX_DMA_REG_TAILDESC,
-					       tail_segment->phys);
-			} else {
-				dma_ctrl_write(chan,
-					XILINX_DMA_MCRX_TDESC(chan->tdest),
-					tail_segment->phys);
-			}
-		}
 	} else {
 		struct xilinx_axidma_tx_segment *segment;
 		struct xilinx_axidma_desc_hw *hw;
@@ -1371,6 +1575,76 @@
 }
 
 /**
+ * xilinx_mcdma_start_transfer - Starts MCDMA transfer
+ * @chan: Driver specific channel struct pointer
+ */
+static void xilinx_mcdma_start_transfer(struct xilinx_dma_chan *chan)
+{
+	struct xilinx_dma_tx_descriptor *head_desc, *tail_desc;
+	struct xilinx_aximcdma_tx_segment *tail_segment;
+	u32 reg;
+
+	/*
+	 * lock has been held by calling functions, so we don't need it
+	 * to take it here again.
+	 */
+
+	if (chan->err)
+		return;
+
+	if (!chan->idle)
+		return;
+
+	if (list_empty(&chan->pending_list))
+		return;
+
+	head_desc = list_first_entry(&chan->pending_list,
+				     struct xilinx_dma_tx_descriptor, node);
+	tail_desc = list_last_entry(&chan->pending_list,
+				    struct xilinx_dma_tx_descriptor, node);
+	tail_segment = list_last_entry(&tail_desc->segments,
+				       struct xilinx_aximcdma_tx_segment, node);
+
+	reg = dma_ctrl_read(chan, XILINX_MCDMA_CHAN_CR_OFFSET(chan->tdest));
+
+	if (chan->desc_pendingcount <= XILINX_MCDMA_COALESCE_MAX) {
+		reg &= ~XILINX_MCDMA_COALESCE_MASK;
+		reg |= chan->desc_pendingcount <<
+			XILINX_MCDMA_COALESCE_SHIFT;
+	}
+
+	reg |= XILINX_MCDMA_IRQ_ALL_MASK;
+	dma_ctrl_write(chan, XILINX_MCDMA_CHAN_CR_OFFSET(chan->tdest), reg);
+
+	/* Program current descriptor */
+	xilinx_write(chan, XILINX_MCDMA_CHAN_CDESC_OFFSET(chan->tdest),
+		     head_desc->async_tx.phys);
+
+	/* Program channel enable register */
+	reg = dma_ctrl_read(chan, XILINX_MCDMA_CHEN_OFFSET);
+	reg |= BIT(chan->tdest);
+	dma_ctrl_write(chan, XILINX_MCDMA_CHEN_OFFSET, reg);
+
+	/* Start the fetch of BDs for the channel */
+	reg = dma_ctrl_read(chan, XILINX_MCDMA_CHAN_CR_OFFSET(chan->tdest));
+	reg |= XILINX_MCDMA_CR_RUNSTOP_MASK;
+	dma_ctrl_write(chan, XILINX_MCDMA_CHAN_CR_OFFSET(chan->tdest), reg);
+
+	xilinx_dma_start(chan);
+
+	if (chan->err)
+		return;
+
+	/* Start the transfer */
+	xilinx_write(chan, XILINX_MCDMA_CHAN_TDESC_OFFSET(chan->tdest),
+		     tail_segment->phys);
+
+	list_splice_tail_init(&chan->pending_list, &chan->active_list);
+	chan->desc_pendingcount = 0;
+	chan->idle = false;
+}
+
+/**
  * xilinx_dma_issue_pending - Issue pending transactions
  * @dchan: DMA channel
  */
@@ -1399,6 +1673,13 @@
 		return;
 
 	list_for_each_entry_safe(desc, next, &chan->active_list, node) {
+		if (chan->has_sg && chan->xdev->dma_config->dmatype !=
+		    XDMA_TYPE_VDMA)
+			desc->residue = xilinx_dma_get_residue(chan, desc);
+		else
+			desc->residue = 0;
+		desc->err = chan->err;
+
 		list_del(&desc->node);
 		if (!desc->cyclic)
 			dma_cookie_complete(&desc->async_tx);
@@ -1433,6 +1714,7 @@
 
 	chan->err = false;
 	chan->idle = true;
+	chan->desc_pendingcount = 0;
 	chan->desc_submitcount = 0;
 
 	return err;
@@ -1461,6 +1743,74 @@
 }
 
 /**
+ * xilinx_mcdma_irq_handler - MCDMA Interrupt handler
+ * @irq: IRQ number
+ * @data: Pointer to the Xilinx MCDMA channel structure
+ *
+ * Return: IRQ_HANDLED/IRQ_NONE
+ */
+static irqreturn_t xilinx_mcdma_irq_handler(int irq, void *data)
+{
+	struct xilinx_dma_chan *chan = data;
+	u32 status, ser_offset, chan_sermask, chan_offset = 0, chan_id;
+
+	if (chan->direction == DMA_DEV_TO_MEM)
+		ser_offset = XILINX_MCDMA_RXINT_SER_OFFSET;
+	else
+		ser_offset = XILINX_MCDMA_TXINT_SER_OFFSET;
+
+	/* Read the channel id raising the interrupt*/
+	chan_sermask = dma_ctrl_read(chan, ser_offset);
+	chan_id = ffs(chan_sermask);
+
+	if (!chan_id)
+		return IRQ_NONE;
+
+	if (chan->direction == DMA_DEV_TO_MEM)
+		chan_offset = chan->xdev->dma_config->max_channels / 2;
+
+	chan_offset = chan_offset + (chan_id - 1);
+	chan = chan->xdev->chan[chan_offset];
+	/* Read the status and ack the interrupts. */
+	status = dma_ctrl_read(chan, XILINX_MCDMA_CHAN_SR_OFFSET(chan->tdest));
+	if (!(status & XILINX_MCDMA_IRQ_ALL_MASK))
+		return IRQ_NONE;
+
+	dma_ctrl_write(chan, XILINX_MCDMA_CHAN_SR_OFFSET(chan->tdest),
+		       status & XILINX_MCDMA_IRQ_ALL_MASK);
+
+	if (status & XILINX_MCDMA_IRQ_ERR_MASK) {
+		dev_err(chan->dev, "Channel %p has errors %x cdr %x tdr %x\n",
+			chan,
+			dma_ctrl_read(chan, XILINX_MCDMA_CH_ERR_OFFSET),
+			dma_ctrl_read(chan, XILINX_MCDMA_CHAN_CDESC_OFFSET
+				      (chan->tdest)),
+			dma_ctrl_read(chan, XILINX_MCDMA_CHAN_TDESC_OFFSET
+				      (chan->tdest)));
+		chan->err = true;
+	}
+
+	if (status & XILINX_MCDMA_IRQ_DELAY_MASK) {
+		/*
+		 * Device takes too long to do the transfer when user requires
+		 * responsiveness.
+		 */
+		dev_dbg(chan->dev, "Inter-packet latency too long\n");
+	}
+
+	if (status & XILINX_MCDMA_IRQ_IOC_MASK) {
+		spin_lock(&chan->lock);
+		xilinx_dma_complete_descriptor(chan);
+		chan->idle = true;
+		chan->start_transfer(chan);
+		spin_unlock(&chan->lock);
+	}
+
+	tasklet_schedule(&chan->tasklet);
+	return IRQ_HANDLED;
+}
+
+/**
  * xilinx_dma_irq_handler - DMA Interrupt handler
  * @irq: IRQ number
  * @data: Pointer to the Xilinx DMA channel structure
@@ -1535,6 +1885,7 @@
 	struct xilinx_vdma_tx_segment *tail_segment;
 	struct xilinx_dma_tx_descriptor *tail_desc;
 	struct xilinx_axidma_tx_segment *axidma_tail_segment;
+	struct xilinx_aximcdma_tx_segment *aximcdma_tail_segment;
 	struct xilinx_cdma_tx_segment *cdma_tail_segment;
 
 	if (list_empty(&chan->pending_list))
@@ -1556,11 +1907,17 @@
 						struct xilinx_cdma_tx_segment,
 						node);
 		cdma_tail_segment->hw.next_desc = (u32)desc->async_tx.phys;
-	} else {
+	} else if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
 		axidma_tail_segment = list_last_entry(&tail_desc->segments,
 					       struct xilinx_axidma_tx_segment,
 					       node);
 		axidma_tail_segment->hw.next_desc = (u32)desc->async_tx.phys;
+	} else {
+		aximcdma_tail_segment =
+			list_last_entry(&tail_desc->segments,
+					struct xilinx_aximcdma_tx_segment,
+					node);
+		aximcdma_tail_segment->hw.next_desc = (u32)desc->async_tx.phys;
 	}
 
 	/*
@@ -1617,6 +1974,8 @@
 	if (desc->cyclic)
 		chan->cyclic = true;
 
+	chan->terminating = false;
+
 	spin_unlock_irqrestore(&chan->lock, flags);
 
 	return cookie;
@@ -1967,31 +2326,32 @@
 }
 
 /**
- * xilinx_dma_prep_interleaved - prepare a descriptor for a
- *	DMA_SLAVE transaction
+ * xilinx_mcdma_prep_slave_sg - prepare descriptors for a DMA_SLAVE transaction
  * @dchan: DMA channel
- * @xt: Interleaved template pointer
+ * @sgl: scatterlist to transfer to/from
+ * @sg_len: number of entries in @scatterlist
+ * @direction: DMA direction
  * @flags: transfer ack flags
+ * @context: APP words of the descriptor
  *
  * Return: Async transaction descriptor on success and NULL on failure
  */
 static struct dma_async_tx_descriptor *
-xilinx_dma_prep_interleaved(struct dma_chan *dchan,
-				 struct dma_interleaved_template *xt,
-				 unsigned long flags)
+xilinx_mcdma_prep_slave_sg(struct dma_chan *dchan, struct scatterlist *sgl,
+			   unsigned int sg_len,
+			   enum dma_transfer_direction direction,
+			   unsigned long flags, void *context)
 {
 	struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
 	struct xilinx_dma_tx_descriptor *desc;
-	struct xilinx_axidma_tx_segment *segment;
-	struct xilinx_axidma_desc_hw *hw;
-
-	if (!is_slave_direction(xt->dir))
-		return NULL;
-
-	if (!xt->numf || !xt->sgl[0].size)
-		return NULL;
+	struct xilinx_aximcdma_tx_segment *segment = NULL;
+	u32 *app_w = (u32 *)context;
+	struct scatterlist *sg;
+	size_t copy;
+	size_t sg_used;
+	unsigned int i;
 
-	if (xt->frame_size != 1)
+	if (!is_slave_direction(direction))
 		return NULL;
 
 	/* Allocate a transaction descriptor. */
@@ -1999,54 +2359,67 @@
 	if (!desc)
 		return NULL;
 
-	chan->direction = xt->dir;
 	dma_async_tx_descriptor_init(&desc->async_tx, &chan->common);
 	desc->async_tx.tx_submit = xilinx_dma_tx_submit;
 
-	/* Get a free segment */
-	segment = xilinx_axidma_alloc_tx_segment(chan);
-	if (!segment)
-		goto error;
+	/* Build transactions using information in the scatter gather list */
+	for_each_sg(sgl, sg, sg_len, i) {
+		sg_used = 0;
 
-	hw = &segment->hw;
+		/* Loop until the entire scatterlist entry is used */
+		while (sg_used < sg_dma_len(sg)) {
+			struct xilinx_aximcdma_desc_hw *hw;
 
-	/* Fill in the descriptor */
-	if (xt->dir != DMA_MEM_TO_DEV)
-		hw->buf_addr = xt->dst_start;
-	else
-		hw->buf_addr = xt->src_start;
+			/* Get a free segment */
+			segment = xilinx_aximcdma_alloc_tx_segment(chan);
+			if (!segment)
+				goto error;
 
-	hw->mcdma_control = chan->tdest & XILINX_DMA_BD_TDEST_MASK;
-	hw->vsize_stride = (xt->numf << XILINX_DMA_BD_VSIZE_SHIFT) &
-			    XILINX_DMA_BD_VSIZE_MASK;
-	hw->vsize_stride |= (xt->sgl[0].icg + xt->sgl[0].size) &
-			    XILINX_DMA_BD_STRIDE_MASK;
-	hw->control = xt->sgl[0].size & XILINX_DMA_BD_HSIZE_MASK;
+			/*
+			 * Calculate the maximum number of bytes to transfer,
+			 * making sure it is less than the hw limit
+			 */
+			copy = min_t(size_t, sg_dma_len(sg) - sg_used,
+				     chan->xdev->max_buffer_len);
+			hw = &segment->hw;
 
-	/*
-	 * Insert the segment into the descriptor segments
-	 * list.
-	 */
-	list_add_tail(&segment->node, &desc->segments);
+			/* Fill in the descriptor */
+			xilinx_aximcdma_buf(chan, hw, sg_dma_address(sg),
+					    sg_used);
+			hw->control = copy;
 
+			if (chan->direction == DMA_MEM_TO_DEV && app_w) {
+				memcpy(hw->app, app_w, sizeof(u32) *
+				       XILINX_DMA_NUM_APP_WORDS);
+			}
+
+			sg_used += copy;
+			/*
+			 * Insert the segment into the descriptor segments
+			 * list.
+			 */
+			list_add_tail(&segment->node, &desc->segments);
+		}
+	}
 
 	segment = list_first_entry(&desc->segments,
-				   struct xilinx_axidma_tx_segment, node);
+				   struct xilinx_aximcdma_tx_segment, node);
 	desc->async_tx.phys = segment->phys;
 
 	/* For the last DMA_MEM_TO_DEV transfer, set EOP */
-	if (xt->dir == DMA_MEM_TO_DEV) {
-		segment->hw.control |= XILINX_DMA_BD_SOP;
+	if (chan->direction == DMA_MEM_TO_DEV) {
+		segment->hw.control |= XILINX_MCDMA_BD_SOP;
 		segment = list_last_entry(&desc->segments,
-					  struct xilinx_axidma_tx_segment,
+					  struct xilinx_aximcdma_tx_segment,
 					  node);
-		segment->hw.control |= XILINX_DMA_BD_EOP;
+		segment->hw.control |= XILINX_MCDMA_BD_EOP;
 	}
 
 	return &desc->async_tx;
 
 error:
 	xilinx_dma_free_tx_descriptor(chan, desc);
+
 	return NULL;
 }
 
@@ -2062,17 +2435,19 @@
 	u32 reg;
 	int err;
 
-	if (chan->cyclic)
-		xilinx_dma_chan_reset(chan);
-
-	err = chan->stop_transfer(chan);
-	if (err) {
-		dev_err(chan->dev, "Cannot stop channel %p: %x\n",
-			chan, dma_ctrl_read(chan, XILINX_DMA_REG_DMASR));
-		chan->err = true;
+	if (!chan->cyclic) {
+		err = chan->stop_transfer(chan);
+		if (err) {
+			dev_err(chan->dev, "Cannot stop channel %p: %x\n",
+				chan, dma_ctrl_read(chan,
+				XILINX_DMA_REG_DMASR));
+			chan->err = true;
+		}
 	}
 
+	xilinx_dma_chan_reset(chan);
 	/* Remove and free all of the descriptors in the lists */
+	chan->terminating = true;
 	xilinx_dma_free_descriptors(chan);
 	chan->idle = true;
 
@@ -2194,7 +2569,9 @@
 	*axi_clk = devm_clk_get(&pdev->dev, "s_axi_lite_aclk");
 	if (IS_ERR(*axi_clk)) {
 		err = PTR_ERR(*axi_clk);
-		dev_err(&pdev->dev, "failed to get axi_aclk (%d)\n", err);
+		if (err != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "failed to get axi_aclk (%d)\n",
+				err);
 		return err;
 	}
 
@@ -2259,14 +2636,18 @@
 	*axi_clk = devm_clk_get(&pdev->dev, "s_axi_lite_aclk");
 	if (IS_ERR(*axi_clk)) {
 		err = PTR_ERR(*axi_clk);
-		dev_err(&pdev->dev, "failed to get axi_clk (%d)\n", err);
+		if (err != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "failed to get axi_clk (%d)\n",
+				err);
 		return err;
 	}
 
 	*dev_clk = devm_clk_get(&pdev->dev, "m_axi_aclk");
 	if (IS_ERR(*dev_clk)) {
 		err = PTR_ERR(*dev_clk);
-		dev_err(&pdev->dev, "failed to get dev_clk (%d)\n", err);
+		if (err != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "failed to get dev_clk (%d)\n",
+				err);
 		return err;
 	}
 
@@ -2299,7 +2680,9 @@
 	*axi_clk = devm_clk_get(&pdev->dev, "s_axi_lite_aclk");
 	if (IS_ERR(*axi_clk)) {
 		err = PTR_ERR(*axi_clk);
-		dev_err(&pdev->dev, "failed to get axi_aclk (%d)\n", err);
+		if (err != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "failed to get axi_aclk (%d)\n",
+				err);
 		return err;
 	}
 
@@ -2321,7 +2704,8 @@
 
 	err = clk_prepare_enable(*axi_clk);
 	if (err) {
-		dev_err(&pdev->dev, "failed to enable axi_clk (%d)\n", err);
+		dev_err(&pdev->dev, "failed to enable axi_clk (%d)\n",
+			err);
 		return err;
 	}
 
@@ -2379,12 +2763,11 @@
  *
  * @xdev: Driver specific device structure
  * @node: Device node
- * @chan_id: DMA Channel id
  *
  * Return: '0' on success and failure value on error
  */
 static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev,
-				  struct device_node *node, int chan_id)
+				  struct device_node *node)
 {
 	struct xilinx_dma_chan *chan;
 	bool has_dre = false;
@@ -2430,14 +2813,14 @@
 		has_dre = false;
 
 	if (!has_dre)
-		xdev->common.copy_align = fls(width - 1);
+		xdev->common.copy_align = (enum dmaengine_alignment)fls(width - 1);
 
 	if (of_device_is_compatible(node, "xlnx,axi-vdma-mm2s-channel") ||
 	    of_device_is_compatible(node, "xlnx,axi-dma-mm2s-channel") ||
 	    of_device_is_compatible(node, "xlnx,axi-cdma-channel")) {
 		chan->direction = DMA_MEM_TO_DEV;
-		chan->id = chan_id;
-		chan->tdest = chan_id;
+		chan->id = xdev->mm2s_chan_id++;
+		chan->tdest = chan->id;
 
 		chan->ctrl_offset = XILINX_DMA_MM2S_CTRL_OFFSET;
 		if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
@@ -2453,8 +2836,8 @@
 		   of_device_is_compatible(node,
 					   "xlnx,axi-dma-s2mm-channel")) {
 		chan->direction = DMA_DEV_TO_MEM;
-		chan->id = chan_id;
-		chan->tdest = chan_id - xdev->nr_channels;
+		chan->id = xdev->s2mm_chan_id++;
+		chan->tdest = chan->id - xdev->dma_config->max_channels / 2;
 		chan->has_vflip = of_property_read_bool(node,
 					"xlnx,enable-vert-flip");
 		if (chan->has_vflip) {
@@ -2463,7 +2846,11 @@
 				XILINX_VDMA_ENABLE_VERTICAL_FLIP;
 		}
 
-		chan->ctrl_offset = XILINX_DMA_S2MM_CTRL_OFFSET;
+		if (xdev->dma_config->dmatype == XDMA_TYPE_AXIMCDMA)
+			chan->ctrl_offset = XILINX_MCDMA_S2MM_CTRL_OFFSET;
+		else
+			chan->ctrl_offset = XILINX_DMA_S2MM_CTRL_OFFSET;
+
 		if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
 			chan->desc_offset = XILINX_VDMA_S2MM_DESC_OFFSET;
 			chan->config.park = 1;
@@ -2478,9 +2865,9 @@
 	}
 
 	/* Request the interrupt */
-	chan->irq = irq_of_parse_and_map(node, 0);
-	err = request_irq(chan->irq, xilinx_dma_irq_handler, IRQF_SHARED,
-			  "xilinx-dma-controller", chan);
+	chan->irq = irq_of_parse_and_map(node, chan->tdest);
+	err = request_irq(chan->irq, xdev->dma_config->irq_handler,
+			  IRQF_SHARED, "xilinx-dma-controller", chan);
 	if (err) {
 		dev_err(xdev->dev, "unable to request IRQ %d\n", chan->irq);
 		return err;
@@ -2489,6 +2876,9 @@
 	if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
 		chan->start_transfer = xilinx_dma_start_transfer;
 		chan->stop_transfer = xilinx_dma_stop_transfer;
+	} else if (xdev->dma_config->dmatype == XDMA_TYPE_AXIMCDMA) {
+		chan->start_transfer = xilinx_mcdma_start_transfer;
+		chan->stop_transfer = xilinx_dma_stop_transfer;
 	} else if (xdev->dma_config->dmatype == XDMA_TYPE_CDMA) {
 		chan->start_transfer = xilinx_cdma_start_transfer;
 		chan->stop_transfer = xilinx_cdma_stop_transfer;
@@ -2497,10 +2887,11 @@
 		chan->stop_transfer = xilinx_dma_stop_transfer;
 	}
 
-	/* check if SG is enabled (only for AXIDMA and CDMA) */
+	/* check if SG is enabled (only for AXIDMA, AXIMCDMA, and CDMA) */
 	if (xdev->dma_config->dmatype != XDMA_TYPE_VDMA) {
-		if (dma_ctrl_read(chan, XILINX_DMA_REG_DMASR) &
-		    XILINX_DMA_DMASR_SG_MASK)
+		if (xdev->dma_config->dmatype == XDMA_TYPE_AXIMCDMA ||
+		    dma_ctrl_read(chan, XILINX_DMA_REG_DMASR) &
+			    XILINX_DMA_DMASR_SG_MASK)
 			chan->has_sg = true;
 		dev_dbg(chan->dev, "ch %d: SG %s\n", chan->id,
 			chan->has_sg ? "enabled" : "disabled");
@@ -2545,13 +2936,11 @@
 	int ret, i, nr_channels = 1;
 
 	ret = of_property_read_u32(node, "dma-channels", &nr_channels);
-	if ((ret < 0) && xdev->mcdma)
+	if (xdev->dma_config->dmatype == XDMA_TYPE_AXIMCDMA && ret < 0)
 		dev_warn(xdev->dev, "missing dma-channels property\n");
 
 	for (i = 0; i < nr_channels; i++)
-		xilinx_dma_chan_probe(xdev, node, xdev->chan_id++);
-
-	xdev->nr_channels += nr_channels;
+		xilinx_dma_chan_probe(xdev, node);
 
 	return 0;
 }
@@ -2569,7 +2958,7 @@
 	struct xilinx_dma_device *xdev = ofdma->of_dma_data;
 	int chan_id = dma_spec->args[0];
 
-	if (chan_id >= xdev->nr_channels || !xdev->chan[chan_id])
+	if (chan_id >= xdev->dma_config->max_channels || !xdev->chan[chan_id])
 		return NULL;
 
 	return dma_get_slave_channel(&xdev->chan[chan_id]->common);
@@ -2578,22 +2967,35 @@
 static const struct xilinx_dma_config axidma_config = {
 	.dmatype = XDMA_TYPE_AXIDMA,
 	.clk_init = axidma_clk_init,
+	.irq_handler = xilinx_dma_irq_handler,
+	.max_channels = XILINX_DMA_MAX_CHANS_PER_DEVICE,
 };
 
+static const struct xilinx_dma_config aximcdma_config = {
+	.dmatype = XDMA_TYPE_AXIMCDMA,
+	.clk_init = axidma_clk_init,
+	.irq_handler = xilinx_mcdma_irq_handler,
+	.max_channels = XILINX_MCDMA_MAX_CHANS_PER_DEVICE,
+};
 static const struct xilinx_dma_config axicdma_config = {
 	.dmatype = XDMA_TYPE_CDMA,
 	.clk_init = axicdma_clk_init,
+	.irq_handler = xilinx_dma_irq_handler,
+	.max_channels = XILINX_CDMA_MAX_CHANS_PER_DEVICE,
 };
 
 static const struct xilinx_dma_config axivdma_config = {
 	.dmatype = XDMA_TYPE_VDMA,
 	.clk_init = axivdma_clk_init,
+	.irq_handler = xilinx_dma_irq_handler,
+	.max_channels = XILINX_DMA_MAX_CHANS_PER_DEVICE,
 };
 
 static const struct of_device_id xilinx_dma_of_ids[] = {
 	{ .compatible = "xlnx,axi-dma-1.00.a", .data = &axidma_config },
 	{ .compatible = "xlnx,axi-cdma-1.00.a", .data = &axicdma_config },
 	{ .compatible = "xlnx,axi-vdma-1.00.a", .data = &axivdma_config },
+	{ .compatible = "xlnx,axi-mcdma-1.00.a", .data = &aximcdma_config },
 	{}
 };
 MODULE_DEVICE_TABLE(of, xilinx_dma_of_ids);
@@ -2612,7 +3014,6 @@
 	struct device_node *node = pdev->dev.of_node;
 	struct xilinx_dma_device *xdev;
 	struct device_node *child, *np = pdev->dev.of_node;
-	struct resource *io;
 	u32 num_frames, addr_width, len_width;
 	int i, err;
 
@@ -2638,16 +3039,17 @@
 		return err;
 
 	/* Request and map I/O memory */
-	io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	xdev->regs = devm_ioremap_resource(&pdev->dev, io);
-	if (IS_ERR(xdev->regs))
-		return PTR_ERR(xdev->regs);
-
+	xdev->regs = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(xdev->regs)) {
+		err = PTR_ERR(xdev->regs);
+		goto disable_clks;
+	}
 	/* Retrieve the DMA engine properties from the device tree */
 	xdev->max_buffer_len = GENMASK(XILINX_DMA_MAX_TRANS_LEN_MAX - 1, 0);
+	xdev->s2mm_chan_id = xdev->dma_config->max_channels / 2;
 
-	if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
-		xdev->mcdma = of_property_read_bool(node, "xlnx,mcdma");
+	if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA ||
+	    xdev->dma_config->dmatype == XDMA_TYPE_AXIMCDMA) {
 		if (!of_property_read_u32(node, "xlnx,sg-length-width",
 					  &len_width)) {
 			if (len_width < XILINX_DMA_MAX_TRANS_LEN_MIN ||
@@ -2669,7 +3071,7 @@
 		if (err < 0) {
 			dev_err(xdev->dev,
 				"missing xlnx,num-fstores property\n");
-			return err;
+			goto disable_clks;
 		}
 
 		err = of_property_read_u32(node, "xlnx,flush-fsync",
@@ -2689,7 +3091,11 @@
 		xdev->ext_addr = false;
 
 	/* Set the dma mask bits */
-	dma_set_mask(xdev->dev, DMA_BIT_MASK(addr_width));
+	err = dma_set_mask_and_coherent(xdev->dev, DMA_BIT_MASK(addr_width));
+	if (err < 0) {
+		dev_err(xdev->dev, "DMA mask error %d\n", err);
+		goto disable_clks;
+	}
 
 	/* Initialize the DMA engine */
 	xdev->common.dev = &pdev->dev;
@@ -2712,14 +3118,17 @@
 		xdev->common.device_prep_slave_sg = xilinx_dma_prep_slave_sg;
 		xdev->common.device_prep_dma_cyclic =
 					  xilinx_dma_prep_dma_cyclic;
-		xdev->common.device_prep_interleaved_dma =
-					xilinx_dma_prep_interleaved;
-		/* Residue calculation is supported by only AXI DMA */
+		/* Residue calculation is supported by only AXI DMA and CDMA */
 		xdev->common.residue_granularity =
 					  DMA_RESIDUE_GRANULARITY_SEGMENT;
 	} else if (xdev->dma_config->dmatype == XDMA_TYPE_CDMA) {
 		dma_cap_set(DMA_MEMCPY, xdev->common.cap_mask);
 		xdev->common.device_prep_dma_memcpy = xilinx_cdma_prep_memcpy;
+		/* Residue calculation is supported by only AXI DMA and CDMA */
+		xdev->common.residue_granularity =
+					  DMA_RESIDUE_GRANULARITY_SEGMENT;
+	} else if (xdev->dma_config->dmatype == XDMA_TYPE_AXIMCDMA) {
+		xdev->common.device_prep_slave_sg = xilinx_mcdma_prep_slave_sg;
 	} else {
 		xdev->common.device_prep_interleaved_dma =
 				xilinx_vdma_dma_prep_interleaved;
@@ -2730,18 +3139,24 @@
 	/* Initialize the channels */
 	for_each_child_of_node(node, child) {
 		err = xilinx_dma_child_probe(xdev, child);
-		if (err < 0)
-			goto disable_clks;
+		if (err < 0) {
+			of_node_put(child);
+			goto error;
+		}
 	}
 
 	if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
-		for (i = 0; i < xdev->nr_channels; i++)
+		for (i = 0; i < xdev->dma_config->max_channels; i++)
 			if (xdev->chan[i])
 				xdev->chan[i]->num_frms = num_frames;
 	}
 
 	/* Register the DMA engine with the core */
-	dma_async_device_register(&xdev->common);
+	err = dma_async_device_register(&xdev->common);
+	if (err) {
+		dev_err(xdev->dev, "failed to register the dma device\n");
+		goto error;
+	}
 
 	err = of_dma_controller_register(node, of_dma_xilinx_xlate,
 					 xdev);
@@ -2755,17 +3170,19 @@
 		dev_info(&pdev->dev, "Xilinx AXI DMA Engine Driver Probed!!\n");
 	else if (xdev->dma_config->dmatype == XDMA_TYPE_CDMA)
 		dev_info(&pdev->dev, "Xilinx AXI CDMA Engine Driver Probed!!\n");
+	else if (xdev->dma_config->dmatype == XDMA_TYPE_AXIMCDMA)
+		dev_info(&pdev->dev, "Xilinx AXI MCDMA Engine Driver Probed!!\n");
 	else
 		dev_info(&pdev->dev, "Xilinx AXI VDMA Engine Driver Probed!!\n");
 
 	return 0;
 
-disable_clks:
-	xdma_disable_allclks(xdev);
 error:
-	for (i = 0; i < xdev->nr_channels; i++)
+	for (i = 0; i < xdev->dma_config->max_channels; i++)
 		if (xdev->chan[i])
 			xilinx_dma_chan_remove(xdev->chan[i]);
+disable_clks:
+	xdma_disable_allclks(xdev);
 
 	return err;
 }
@@ -2785,7 +3202,7 @@
 
 	dma_async_device_unregister(&xdev->common);
 
-	for (i = 0; i < xdev->nr_channels; i++)
+	for (i = 0; i < xdev->dma_config->max_channels; i++)
 		if (xdev->chan[i])
 			xilinx_dma_chan_remove(xdev->chan[i]);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/xilinx/xilinx_dpdma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/xilinx/xilinx_dpdma.c
@@ -0,0 +1,2324 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx ZynqMP DPDMA Engine driver
+ *
+ *  Copyright (C) 2015 - 2018 Xilinx, Inc.
+ *
+ *  Author: Hyun Woo Kwon <hyun.kwon@xilinx.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dmaengine.h>
+#include <linux/dmapool.h>
+#include <linux/gfp.h>
+#include <linux/interrupt.h>
+#include <linux/irqreturn.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_dma.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <linux/wait.h>
+
+#include "../dmaengine.h"
+
+/* DPDMA registers */
+#define XILINX_DPDMA_ERR_CTRL				0x0
+#define XILINX_DPDMA_ISR				0x4
+#define XILINX_DPDMA_IMR				0x8
+#define XILINX_DPDMA_IEN				0xc
+#define XILINX_DPDMA_IDS				0x10
+#define XILINX_DPDMA_INTR_DESC_DONE_MASK		(0x3f << 0)
+#define XILINX_DPDMA_INTR_DESC_DONE_SHIFT		0
+#define XILINX_DPDMA_INTR_NO_OSTAND_MASK		(0x3f << 6)
+#define XILINX_DPDMA_INTR_NO_OSTAND_SHIFT		6
+#define XILINX_DPDMA_INTR_AXI_ERR_MASK			(0x3f << 12)
+#define XILINX_DPDMA_INTR_AXI_ERR_SHIFT			12
+#define XILINX_DPDMA_INTR_DESC_ERR_MASK			(0x3f << 18)
+#define XILINX_DPDMA_INTR_DESC_ERR_SHIFT		16
+#define XILINX_DPDMA_INTR_WR_CMD_FIFO_FULL		BIT(24)
+#define XILINX_DPDMA_INTR_WR_DATA_FIFO_FULL		BIT(25)
+#define XILINX_DPDMA_INTR_AXI_4K_CROSS			BIT(26)
+#define XILINX_DPDMA_INTR_VSYNC				BIT(27)
+#define XILINX_DPDMA_INTR_CHAN_ERR_MASK			0x41000
+#define XILINX_DPDMA_INTR_CHAN_ERR			0xfff000
+#define XILINX_DPDMA_INTR_GLOBAL_ERR			0x7000000
+#define XILINX_DPDMA_INTR_ERR_ALL			0x7fff000
+#define XILINX_DPDMA_INTR_CHAN_MASK			0x41041
+#define XILINX_DPDMA_INTR_GLOBAL_MASK			0xf000000
+#define XILINX_DPDMA_INTR_ALL				0xfffffff
+#define XILINX_DPDMA_EISR				0x14
+#define XILINX_DPDMA_EIMR				0x18
+#define XILINX_DPDMA_EIEN				0x1c
+#define XILINX_DPDMA_EIDS				0x20
+#define XILINX_DPDMA_EINTR_INV_APB			BIT(0)
+#define XILINX_DPDMA_EINTR_RD_AXI_ERR_MASK		(0x3f << 1)
+#define XILINX_DPDMA_EINTR_RD_AXI_ERR_SHIFT		1
+#define XILINX_DPDMA_EINTR_PRE_ERR_MASK			(0x3f << 7)
+#define XILINX_DPDMA_EINTR_PRE_ERR_SHIFT		7
+#define XILINX_DPDMA_EINTR_CRC_ERR_MASK			(0x3f << 13)
+#define XILINX_DPDMA_EINTR_CRC_ERR_SHIFT		13
+#define XILINX_DPDMA_EINTR_WR_AXI_ERR_MASK		(0x3f << 19)
+#define XILINX_DPDMA_EINTR_WR_AXI_ERR_SHIFT		19
+#define XILINX_DPDMA_EINTR_DESC_DONE_ERR_MASK		(0x3f << 25)
+#define XILINX_DPDMA_EINTR_DESC_DONE_ERR_SHIFT		25
+#define XILINX_DPDMA_EINTR_RD_CMD_FIFO_FULL		BIT(32)
+#define XILINX_DPDMA_EINTR_CHAN_ERR_MASK		0x2082082
+#define XILINX_DPDMA_EINTR_CHAN_ERR			0x7ffffffe
+#define XILINX_DPDMA_EINTR_GLOBAL_ERR			0x80000001
+#define XILINX_DPDMA_EINTR_ALL				0xffffffff
+#define XILINX_DPDMA_CNTL				0x100
+#define XILINX_DPDMA_GBL				0x104
+#define XILINX_DPDMA_GBL_TRIG_SHIFT			0
+#define XILINX_DPDMA_GBL_RETRIG_SHIFT			6
+#define XILINX_DPDMA_ALC0_CNTL				0x108
+#define XILINX_DPDMA_ALC0_STATUS			0x10c
+#define XILINX_DPDMA_ALC0_MAX				0x110
+#define XILINX_DPDMA_ALC0_MIN				0x114
+#define XILINX_DPDMA_ALC0_ACC				0x118
+#define XILINX_DPDMA_ALC0_ACC_TRAN			0x11c
+#define XILINX_DPDMA_ALC1_CNTL				0x120
+#define XILINX_DPDMA_ALC1_STATUS			0x124
+#define XILINX_DPDMA_ALC1_MAX				0x128
+#define XILINX_DPDMA_ALC1_MIN				0x12c
+#define XILINX_DPDMA_ALC1_ACC				0x130
+#define XILINX_DPDMA_ALC1_ACC_TRAN			0x134
+
+/* Channel register */
+#define XILINX_DPDMA_CH_BASE				0x200
+#define XILINX_DPDMA_CH_OFFSET				0x100
+#define XILINX_DPDMA_CH_DESC_START_ADDRE		0x0
+#define XILINX_DPDMA_CH_DESC_START_ADDR			0x4
+#define XILINX_DPDMA_CH_DESC_NEXT_ADDRE			0x8
+#define XILINX_DPDMA_CH_DESC_NEXT_ADDR			0xc
+#define XILINX_DPDMA_CH_PYLD_CUR_ADDRE			0x10
+#define XILINX_DPDMA_CH_PYLD_CUR_ADDR			0x14
+#define XILINX_DPDMA_CH_CNTL				0x18
+#define XILINX_DPDMA_CH_CNTL_ENABLE			BIT(0)
+#define XILINX_DPDMA_CH_CNTL_PAUSE			BIT(1)
+#define XILINX_DPDMA_CH_CNTL_QOS_DSCR_WR_SHIFT		2
+#define XILINX_DPDMA_CH_CNTL_QOS_DSCR_RD_SHIFT		6
+#define XILINX_DPDMA_CH_CNTL_QOS_DATA_RD_SHIFT		10
+#define XILINX_DPDMA_CH_CNTL_QOS_VID_CLASS		11
+#define XILINX_DPDMA_CH_STATUS				0x1c
+#define XILINX_DPDMA_CH_STATUS_OTRAN_CNT_MASK		(0xf << 21)
+#define XILINX_DPDMA_CH_STATUS_OTRAN_CNT_SHIFT		21
+#define XILINX_DPDMA_CH_VDO				0x20
+#define XILINX_DPDMA_CH_PYLD_SZ				0x24
+#define XILINX_DPDMA_CH_DESC_ID				0x28
+
+/* DPDMA descriptor fields */
+#define XILINX_DPDMA_DESC_CONTROL_PREEMBLE		(0xa5)
+#define XILINX_DPDMA_DESC_CONTROL_COMPLETE_INTR		BIT(8)
+#define XILINX_DPDMA_DESC_CONTROL_DESC_UPDATE		BIT(9)
+#define XILINX_DPDMA_DESC_CONTROL_IGNORE_DONE		BIT(10)
+#define XILINX_DPDMA_DESC_CONTROL_FRAG_MODE		BIT(18)
+#define XILINX_DPDMA_DESC_CONTROL_LAST			BIT(19)
+#define XILINX_DPDMA_DESC_CONTROL_ENABLE_CRC		BIT(20)
+#define XILINX_DPDMA_DESC_CONTROL_LAST_OF_FRAME		BIT(21)
+#define XILINX_DPDMA_DESC_ID_MASK			(0xffff << 0)
+#define XILINX_DPDMA_DESC_ID_SHIFT			(0)
+#define XILINX_DPDMA_DESC_HSIZE_STRIDE_HSIZE_MASK	(0x3ffff << 0)
+#define XILINX_DPDMA_DESC_HSIZE_STRIDE_HSIZE_SHIFT	(0)
+#define XILINX_DPDMA_DESC_HSIZE_STRIDE_STRIDE_MASK	(0x3fff << 18)
+#define XILINX_DPDMA_DESC_HSIZE_STRIDE_STRIDE_SHIFT	(18)
+#define XILINX_DPDMA_DESC_ADDR_EXT_ADDR_MASK		(0xfff)
+#define XILINX_DPDMA_DESC_ADDR_EXT_ADDR_SHIFT		(16)
+
+#define XILINX_DPDMA_ALIGN_BYTES			256
+#define XILINX_DPDMA_LINESIZE_ALIGN_BITS		128
+
+#define XILINX_DPDMA_NUM_CHAN				6
+#define XILINX_DPDMA_PAGE_MASK				((1 << 12) - 1)
+#define XILINX_DPDMA_PAGE_SHIFT				12
+
+/**
+ * struct xilinx_dpdma_hw_desc - DPDMA hardware descriptor
+ * @control: control configuration field
+ * @desc_id: descriptor ID
+ * @xfer_size: transfer size
+ * @hsize_stride: horizontal size and stride
+ * @timestamp_lsb: LSB of time stamp
+ * @timestamp_msb: MSB of time stamp
+ * @addr_ext: upper 16 bit of 48 bit address (next_desc and src_addr)
+ * @next_desc: next descriptor 32 bit address
+ * @src_addr: payload source address (lower 32 bit of 1st 4KB page)
+ * @addr_ext_23: upper 16 bit of 48 bit address (src_addr2 and src_addr3)
+ * @addr_ext_45: upper 16 bit of 48 bit address (src_addr4 and src_addr5)
+ * @src_addr2: payload source address (lower 32 bit of 2nd 4KB page)
+ * @src_addr3: payload source address (lower 32 bit of 3rd 4KB page)
+ * @src_addr4: payload source address (lower 32 bit of 4th 4KB page)
+ * @src_addr5: payload source address (lower 32 bit of 5th 4KB page)
+ * @crc: descriptor CRC
+ */
+struct xilinx_dpdma_hw_desc {
+	u32 control;
+	u32 desc_id;
+	u32 xfer_size;
+	u32 hsize_stride;
+	u32 timestamp_lsb;
+	u32 timestamp_msb;
+	u32 addr_ext;
+	u32 next_desc;
+	u32 src_addr;
+	u32 addr_ext_23;
+	u32 addr_ext_45;
+	u32 src_addr2;
+	u32 src_addr3;
+	u32 src_addr4;
+	u32 src_addr5;
+	u32 crc;
+} __aligned(XILINX_DPDMA_ALIGN_BYTES);
+
+/**
+ * struct xilinx_dpdma_sw_desc - DPDMA software descriptor
+ * @hw: DPDMA hardware descriptor
+ * @node: list node for software descriptors
+ * @phys: physical address of the software descriptor
+ */
+struct xilinx_dpdma_sw_desc {
+	struct xilinx_dpdma_hw_desc hw;
+	struct list_head node;
+	dma_addr_t phys;
+};
+
+/**
+ * enum xilinx_dpdma_tx_desc_status - DPDMA tx descriptor status
+ * @PREPARED: descriptor is prepared for transaction
+ * @ACTIVE: transaction is (being) done successfully
+ * @ERRORED: descriptor generates some errors
+ */
+enum xilinx_dpdma_tx_desc_status {
+	PREPARED,
+	ACTIVE,
+	ERRORED
+};
+
+/**
+ * struct xilinx_dpdma_tx_desc - DPDMA transaction descriptor
+ * @async_tx: DMA async transaction descriptor
+ * @descriptors: list of software descriptors
+ * @node: list node for transaction descriptors
+ * @status: tx descriptor status
+ * @done_cnt: number of complete notification to deliver
+ */
+struct xilinx_dpdma_tx_desc {
+	struct dma_async_tx_descriptor async_tx;
+	struct list_head descriptors;
+	struct list_head node;
+	enum xilinx_dpdma_tx_desc_status status;
+	unsigned int done_cnt;
+};
+
+/**
+ * enum xilinx_dpdma_chan_id - DPDMA channel ID
+ * @VIDEO0: video 1st channel
+ * @VIDEO1: video 2nd channel for multi plane yuv formats
+ * @VIDEO2: video 3rd channel for multi plane yuv formats
+ * @GRAPHICS: graphics channel
+ * @AUDIO0: 1st audio channel
+ * @AUDIO1: 2nd audio channel
+ */
+enum xilinx_dpdma_chan_id {
+	VIDEO0,
+	VIDEO1,
+	VIDEO2,
+	GRAPHICS,
+	AUDIO0,
+	AUDIO1
+};
+
+/**
+ * enum xilinx_dpdma_chan_status - DPDMA channel status
+ * @IDLE: idle state
+ * @STREAMING: actively streaming state
+ */
+enum xilinx_dpdma_chan_status {
+	IDLE,
+	STREAMING
+};
+
+/*
+ * DPDMA descriptor placement
+ * --------------------------
+ * DPDMA descritpor life time is described with following placements:
+ *
+ * allocated_desc -> submitted_desc -> pending_desc -> active_desc -> done_list
+ *
+ * Transition is triggered as following:
+ *
+ * -> allocated_desc : a descriptor allocation
+ * allocated_desc -> submitted_desc: a descriptor submission
+ * submitted_desc -> pending_desc: request to issue pending a descriptor
+ * pending_desc -> active_desc: VSYNC intr when a desc is scheduled to DPDMA
+ * active_desc -> done_list: VSYNC intr when DPDMA switches to a new desc
+ */
+
+/**
+ * struct xilinx_dpdma_chan - DPDMA channel
+ * @common: generic dma channel structure
+ * @reg: register base address
+ * @id: channel ID
+ * @wait_to_stop: queue to wait for outstanding transacitons before stopping
+ * @status: channel status
+ * @first_frame: flag for the first frame of stream
+ * @video_group: flag if multi-channel operation is needed for video channels
+ * @lock: lock to access struct xilinx_dpdma_chan
+ * @desc_pool: descriptor allocation pool
+ * @done_task: done IRQ bottom half handler
+ * @err_task: error IRQ bottom half handler
+ * @allocated_desc: allocated descriptor
+ * @submitted_desc: submitted descriptor
+ * @pending_desc: pending descriptor to be scheduled in next period
+ * @active_desc: descriptor that the DPDMA channel is active on
+ * @done_list: done descriptor list
+ * @xdev: DPDMA device
+ */
+struct xilinx_dpdma_chan {
+	struct dma_chan common;
+	void __iomem *reg;
+	enum xilinx_dpdma_chan_id id;
+
+	wait_queue_head_t wait_to_stop;
+	enum xilinx_dpdma_chan_status status;
+	bool first_frame;
+	bool video_group;
+
+	spinlock_t lock; /* lock to access struct xilinx_dpdma_chan */
+	struct dma_pool *desc_pool;
+	struct tasklet_struct done_task;
+	struct tasklet_struct err_task;
+
+	struct xilinx_dpdma_tx_desc *allocated_desc;
+	struct xilinx_dpdma_tx_desc *submitted_desc;
+	struct xilinx_dpdma_tx_desc *pending_desc;
+	struct xilinx_dpdma_tx_desc *active_desc;
+	struct list_head done_list;
+
+	struct xilinx_dpdma_device *xdev;
+};
+
+/**
+ * struct xilinx_dpdma_device - DPDMA device
+ * @common: generic dma device structure
+ * @reg: register base address
+ * @dev: generic device structure
+ * @axi_clk: axi clock
+ * @chan: DPDMA channels
+ * @ext_addr: flag for 64 bit system (48 bit addressing)
+ * @desc_addr: descriptor addressing callback (32 bit vs 64 bit)
+ */
+struct xilinx_dpdma_device {
+	struct dma_device common;
+	void __iomem *reg;
+	struct device *dev;
+
+	struct clk *axi_clk;
+	struct xilinx_dpdma_chan *chan[XILINX_DPDMA_NUM_CHAN];
+
+	bool ext_addr;
+	void (*desc_addr)(struct xilinx_dpdma_sw_desc *sw_desc,
+			  struct xilinx_dpdma_sw_desc *prev,
+			  dma_addr_t dma_addr[], unsigned int num_src_addr);
+};
+
+#ifdef CONFIG_XILINX_DPDMA_DEBUG_FS
+#define XILINX_DPDMA_DEBUGFS_READ_MAX_SIZE	32
+#define XILINX_DPDMA_DEBUGFS_UINT16_MAX_STR	"65535"
+#define IN_RANGE(x, min, max) ({		\
+		typeof(x) _x = (x);		\
+		_x >= (min) && _x <= (max); })
+
+/* Match xilinx_dpdma_testcases vs dpdma_debugfs_reqs[] entry */
+enum xilinx_dpdma_testcases {
+	DPDMA_TC_INTR_DONE,
+	DPDMA_TC_NONE
+};
+
+struct xilinx_dpdma_debugfs {
+	enum xilinx_dpdma_testcases testcase;
+	u16 xilinx_dpdma_intr_done_count;
+	enum xilinx_dpdma_chan_id chan_id;
+};
+
+static struct xilinx_dpdma_debugfs dpdma_debugfs;
+struct xilinx_dpdma_debugfs_request {
+	const char *req;
+	enum xilinx_dpdma_testcases tc;
+	ssize_t (*read_handler)(char **kern_buff);
+	ssize_t (*write_handler)(char **cmd);
+};
+
+static void xilinx_dpdma_debugfs_intr_done_count_incr(int chan_id)
+{
+	if (chan_id == dpdma_debugfs.chan_id)
+		dpdma_debugfs.xilinx_dpdma_intr_done_count++;
+}
+
+static s64 xilinx_dpdma_debugfs_argument_value(char *arg)
+{
+	s64 value;
+
+	if (!arg)
+		return -1;
+
+	if (!kstrtos64(arg, 0, &value))
+		return value;
+
+	return -1;
+}
+
+static ssize_t
+xilinx_dpdma_debugfs_desc_done_intr_write(char **dpdma_test_arg)
+{
+	char *arg;
+	char *arg_chan_id;
+	s64 id;
+
+	arg = strsep(dpdma_test_arg, " ");
+	if (strncasecmp(arg, "start", 5) != 0)
+		return -EINVAL;
+
+	arg_chan_id = strsep(dpdma_test_arg, " ");
+	id = xilinx_dpdma_debugfs_argument_value(arg_chan_id);
+
+	if (id < 0 || !IN_RANGE(id, VIDEO0, AUDIO1))
+		return -EINVAL;
+
+	dpdma_debugfs.testcase = DPDMA_TC_INTR_DONE;
+	dpdma_debugfs.xilinx_dpdma_intr_done_count = 0;
+	dpdma_debugfs.chan_id = id;
+
+	return 0;
+}
+
+static ssize_t xilinx_dpdma_debugfs_desc_done_intr_read(char **kern_buff)
+{
+	size_t out_str_len;
+
+	dpdma_debugfs.testcase = DPDMA_TC_NONE;
+
+	out_str_len = strlen(XILINX_DPDMA_DEBUGFS_UINT16_MAX_STR);
+	out_str_len = min_t(size_t, XILINX_DPDMA_DEBUGFS_READ_MAX_SIZE,
+			    out_str_len);
+	snprintf(*kern_buff, out_str_len, "%d",
+		 dpdma_debugfs.xilinx_dpdma_intr_done_count);
+
+	return 0;
+}
+
+/* Match xilinx_dpdma_testcases vs dpdma_debugfs_reqs[] entry */
+struct xilinx_dpdma_debugfs_request dpdma_debugfs_reqs[] = {
+	{"DESCRIPTOR_DONE_INTR", DPDMA_TC_INTR_DONE,
+			xilinx_dpdma_debugfs_desc_done_intr_read,
+			xilinx_dpdma_debugfs_desc_done_intr_write},
+};
+
+static ssize_t xilinx_dpdma_debugfs_write(struct file *f, const char __user
+					       *buf, size_t size, loff_t *pos)
+{
+	char *kern_buff, *kern_buff_start;
+	char *dpdma_test_req;
+	int ret;
+	int i;
+
+	if (*pos != 0 || size <= 0)
+		return -EINVAL;
+
+	/* Supporting single instance of test as of now*/
+	if (dpdma_debugfs.testcase != DPDMA_TC_NONE)
+		return -EBUSY;
+
+	kern_buff = kzalloc(size, GFP_KERNEL);
+	if (!kern_buff)
+		return -ENOMEM;
+	kern_buff_start = kern_buff;
+
+	ret = strncpy_from_user(kern_buff, buf, size);
+	if (ret < 0) {
+		kfree(kern_buff_start);
+		return ret;
+	}
+
+	/* Read the testcase name from a user request */
+	dpdma_test_req = strsep(&kern_buff, " ");
+
+	for (i = 0; i < ARRAY_SIZE(dpdma_debugfs_reqs); i++) {
+		if (!strcasecmp(dpdma_test_req, dpdma_debugfs_reqs[i].req)) {
+			if (!dpdma_debugfs_reqs[i].write_handler(&kern_buff)) {
+				kfree(kern_buff_start);
+				return size;
+			}
+			break;
+		}
+	}
+	kfree(kern_buff_start);
+	return -EINVAL;
+}
+
+static ssize_t xilinx_dpdma_debugfs_read(struct file *f, char __user *buf,
+					 size_t size, loff_t *pos)
+{
+	char *kern_buff = NULL;
+	size_t kern_buff_len, out_str_len;
+	enum xilinx_dpdma_testcases tc;
+	int ret;
+
+	if (size <= 0)
+		return -EINVAL;
+
+	if (*pos != 0)
+		return 0;
+
+	kern_buff = kzalloc(XILINX_DPDMA_DEBUGFS_READ_MAX_SIZE, GFP_KERNEL);
+	if (!kern_buff) {
+		dpdma_debugfs.testcase = DPDMA_TC_NONE;
+		return -ENOMEM;
+	}
+
+	tc = dpdma_debugfs.testcase;
+	if (tc == DPDMA_TC_NONE) {
+		out_str_len = strlen("No testcase executed");
+		out_str_len = min_t(size_t, XILINX_DPDMA_DEBUGFS_READ_MAX_SIZE,
+				    out_str_len);
+		snprintf(kern_buff, out_str_len, "%s", "No testcase executed");
+	} else {
+		ret = dpdma_debugfs_reqs[tc].read_handler(&kern_buff);
+		if (ret) {
+			kfree(kern_buff);
+			return ret;
+		}
+	}
+
+	kern_buff_len = strlen(kern_buff);
+	size = min(size, kern_buff_len);
+
+	ret = copy_to_user(buf, kern_buff, size);
+
+	kfree(kern_buff);
+	if (ret)
+		return ret;
+
+	*pos = size + 1;
+	return size;
+}
+
+static const struct file_operations fops_xilinx_dpdma_dbgfs = {
+	.owner = THIS_MODULE,
+	.read = xilinx_dpdma_debugfs_read,
+	.write = xilinx_dpdma_debugfs_write,
+};
+
+static int xilinx_dpdma_debugfs_init(struct device *dev)
+{
+	int err;
+	struct dentry *xilinx_dpdma_debugfs_dir, *xilinx_dpdma_debugfs_file;
+
+	dpdma_debugfs.testcase = DPDMA_TC_NONE;
+
+	xilinx_dpdma_debugfs_dir = debugfs_create_dir("dpdma", NULL);
+	if (!xilinx_dpdma_debugfs_dir) {
+		dev_err(dev, "debugfs_create_dir failed\n");
+		return -ENODEV;
+	}
+
+	xilinx_dpdma_debugfs_file =
+		debugfs_create_file("testcase", 0444,
+				    xilinx_dpdma_debugfs_dir, NULL,
+				    &fops_xilinx_dpdma_dbgfs);
+	if (!xilinx_dpdma_debugfs_file) {
+		dev_err(dev, "debugfs_create_file testcase failed\n");
+		err = -ENODEV;
+		goto err_dbgfs;
+	}
+	return 0;
+
+err_dbgfs:
+	debugfs_remove_recursive(xilinx_dpdma_debugfs_dir);
+	xilinx_dpdma_debugfs_dir = NULL;
+	return err;
+}
+
+#else
+static int xilinx_dpdma_debugfs_init(struct device *dev)
+{
+	return 0;
+}
+
+static void xilinx_dpdma_debugfs_intr_done_count_incr(int chan_id)
+{
+}
+#endif /* CONFIG_XILINX_DPDMA_DEBUG_FS */
+
+#define to_dpdma_tx_desc(tx) \
+	container_of(tx, struct xilinx_dpdma_tx_desc, async_tx)
+
+#define to_xilinx_chan(chan) \
+	container_of(chan, struct xilinx_dpdma_chan, common)
+
+/* IO operations */
+
+static inline u32 dpdma_read(void __iomem *base, u32 offset)
+{
+	return ioread32(base + offset);
+}
+
+static inline void dpdma_write(void __iomem *base, u32 offset, u32 val)
+{
+	iowrite32(val, base + offset);
+}
+
+static inline void dpdma_clr(void __iomem *base, u32 offset, u32 clr)
+{
+	dpdma_write(base, offset, dpdma_read(base, offset) & ~clr);
+}
+
+static inline void dpdma_set(void __iomem *base, u32 offset, u32 set)
+{
+	dpdma_write(base, offset, dpdma_read(base, offset) | set);
+}
+
+/* Xilinx DPDMA descriptor operations */
+
+/**
+ * xilinx_dpdma_sw_desc_next_32 - Set 32 bit address of a next sw descriptor
+ * @sw_desc: current software descriptor
+ * @next: next descriptor
+ *
+ * Update the current sw descriptor @sw_desc with 32 bit address of the next
+ * descriptor @next.
+ */
+static inline void
+xilinx_dpdma_sw_desc_next_32(struct xilinx_dpdma_sw_desc *sw_desc,
+			     struct xilinx_dpdma_sw_desc *next)
+{
+	sw_desc->hw.next_desc = next->phys;
+}
+
+/**
+ * xilinx_dpdma_sw_desc_addr_32 - Update the sw descriptor with 32 bit address
+ * @sw_desc: software descriptor
+ * @prev: previous descriptor
+ * @dma_addr: array of dma addresses
+ * @num_src_addr: number of addresses in @dma_addr
+ *
+ * Update the descriptor @sw_desc with 32 bit address.
+ */
+static void xilinx_dpdma_sw_desc_addr_32(struct xilinx_dpdma_sw_desc *sw_desc,
+					 struct xilinx_dpdma_sw_desc *prev,
+					 dma_addr_t dma_addr[],
+					 unsigned int num_src_addr)
+{
+	struct xilinx_dpdma_hw_desc *hw_desc = &sw_desc->hw;
+	unsigned int i;
+
+	hw_desc->src_addr = dma_addr[0];
+
+	if (prev)
+		xilinx_dpdma_sw_desc_next_32(prev, sw_desc);
+
+	for (i = 1; i < num_src_addr; i++) {
+		u32 *addr = &hw_desc->src_addr2;
+		u32 frag_addr;
+
+		frag_addr = dma_addr[i];
+		addr[i - 1] = frag_addr;
+	}
+}
+
+/**
+ * xilinx_dpdma_sw_desc_next_64 - Set 64 bit address of a next sw descriptor
+ * @sw_desc: current software descriptor
+ * @next: next descriptor
+ *
+ * Update the current sw descriptor @sw_desc with 64 bit address of the next
+ * descriptor @next.
+ */
+static inline void
+xilinx_dpdma_sw_desc_next_64(struct xilinx_dpdma_sw_desc *sw_desc,
+			     struct xilinx_dpdma_sw_desc *next)
+{
+	sw_desc->hw.next_desc = lower_32_bits(next->phys);
+	sw_desc->hw.addr_ext |= upper_32_bits(next->phys) &
+				XILINX_DPDMA_DESC_ADDR_EXT_ADDR_MASK;
+}
+
+/**
+ * xilinx_dpdma_sw_desc_addr_64 - Update the sw descriptor with 64 bit address
+ * @sw_desc: software descriptor
+ * @prev: previous descriptor
+ * @dma_addr: array of dma addresses
+ * @num_src_addr: number of addresses in @dma_addr
+ *
+ * Update the descriptor @sw_desc with 64 bit address.
+ */
+static void xilinx_dpdma_sw_desc_addr_64(struct xilinx_dpdma_sw_desc *sw_desc,
+					 struct xilinx_dpdma_sw_desc *prev,
+					 dma_addr_t dma_addr[],
+					 unsigned int num_src_addr)
+{
+	struct xilinx_dpdma_hw_desc *hw_desc = &sw_desc->hw;
+	unsigned int i;
+	u32 src_addr_extn;
+
+	hw_desc->src_addr = lower_32_bits(dma_addr[0]);
+	src_addr_extn = upper_32_bits(dma_addr[0]) &
+			XILINX_DPDMA_DESC_ADDR_EXT_ADDR_MASK;
+	hw_desc->addr_ext |= (src_addr_extn <<
+			      XILINX_DPDMA_DESC_ADDR_EXT_ADDR_SHIFT);
+
+	if (prev)
+		xilinx_dpdma_sw_desc_next_64(prev, sw_desc);
+
+	for (i = 1; i < num_src_addr; i++) {
+		u32 *addr = &hw_desc->src_addr2;
+		u32 *addr_ext = &hw_desc->addr_ext_23;
+		u64 frag_addr;
+
+		frag_addr = dma_addr[i];
+		addr[i] = (u32)frag_addr;
+
+		frag_addr >>= 32;
+		frag_addr &= XILINX_DPDMA_DESC_ADDR_EXT_ADDR_MASK;
+		frag_addr <<= XILINX_DPDMA_DESC_ADDR_EXT_ADDR_SHIFT * (i % 2);
+		addr_ext[i / 2] = frag_addr;
+	}
+}
+
+/* Xilinx DPDMA channel descriptor operations */
+
+/**
+ * xilinx_dpdma_chan_alloc_sw_desc - Allocate a software descriptor
+ * @chan: DPDMA channel
+ *
+ * Allocate a software descriptor from the channel's descriptor pool.
+ *
+ * Return: a software descriptor or NULL.
+ */
+static struct xilinx_dpdma_sw_desc *
+xilinx_dpdma_chan_alloc_sw_desc(struct xilinx_dpdma_chan *chan)
+{
+	struct xilinx_dpdma_sw_desc *sw_desc;
+	dma_addr_t phys;
+
+	sw_desc = dma_pool_zalloc(chan->desc_pool, GFP_ATOMIC, &phys);
+	if (!sw_desc)
+		return NULL;
+
+	sw_desc->phys = phys;
+
+	return sw_desc;
+}
+
+/**
+ * xilinx_dpdma_chan_free_sw_desc - Free a software descriptor
+ * @chan: DPDMA channel
+ * @sw_desc: software descriptor to free
+ *
+ * Free a software descriptor from the channel's descriptor pool.
+ */
+static void
+xilinx_dpdma_chan_free_sw_desc(struct xilinx_dpdma_chan *chan,
+			       struct xilinx_dpdma_sw_desc *sw_desc)
+{
+	dma_pool_free(chan->desc_pool, sw_desc, sw_desc->phys);
+}
+
+/**
+ * xilinx_dpdma_chan_dump_tx_desc - Dump a tx descriptor
+ * @chan: DPDMA channel
+ * @tx_desc: tx descriptor to dump
+ *
+ * Dump contents of a tx descriptor
+ */
+static void xilinx_dpdma_chan_dump_tx_desc(struct xilinx_dpdma_chan *chan,
+					   struct xilinx_dpdma_tx_desc *tx_desc)
+{
+	struct xilinx_dpdma_sw_desc *sw_desc;
+	struct device *dev = chan->xdev->dev;
+	unsigned int i = 0;
+
+	dev_dbg(dev, "------- TX descriptor dump start -------\n");
+	dev_dbg(dev, "------- channel ID = %d -------\n", chan->id);
+
+	list_for_each_entry(sw_desc, &tx_desc->descriptors, node) {
+		struct xilinx_dpdma_hw_desc *hw_desc = &sw_desc->hw;
+
+		dev_dbg(dev, "------- HW descriptor %d -------\n", i++);
+		dev_dbg(dev, "descriptor phys: %pad\n", &sw_desc->phys);
+		dev_dbg(dev, "control: 0x%08x\n", hw_desc->control);
+		dev_dbg(dev, "desc_id: 0x%08x\n", hw_desc->desc_id);
+		dev_dbg(dev, "xfer_size: 0x%08x\n", hw_desc->xfer_size);
+		dev_dbg(dev, "hsize_stride: 0x%08x\n", hw_desc->hsize_stride);
+		dev_dbg(dev, "timestamp_lsb: 0x%08x\n", hw_desc->timestamp_lsb);
+		dev_dbg(dev, "timestamp_msb: 0x%08x\n", hw_desc->timestamp_msb);
+		dev_dbg(dev, "addr_ext: 0x%08x\n", hw_desc->addr_ext);
+		dev_dbg(dev, "next_desc: 0x%08x\n", hw_desc->next_desc);
+		dev_dbg(dev, "src_addr: 0x%08x\n", hw_desc->src_addr);
+		dev_dbg(dev, "addr_ext_23: 0x%08x\n", hw_desc->addr_ext_23);
+		dev_dbg(dev, "addr_ext_45: 0x%08x\n", hw_desc->addr_ext_45);
+		dev_dbg(dev, "src_addr2: 0x%08x\n", hw_desc->src_addr2);
+		dev_dbg(dev, "src_addr3: 0x%08x\n", hw_desc->src_addr3);
+		dev_dbg(dev, "src_addr4: 0x%08x\n", hw_desc->src_addr4);
+		dev_dbg(dev, "src_addr5: 0x%08x\n", hw_desc->src_addr5);
+		dev_dbg(dev, "crc: 0x%08x\n", hw_desc->crc);
+	}
+
+	dev_dbg(dev, "------- TX descriptor dump end -------\n");
+}
+
+/**
+ * xilinx_dpdma_chan_alloc_tx_desc - Allocate a transaction descriptor
+ * @chan: DPDMA channel
+ *
+ * Allocate a tx descriptor.
+ *
+ * Return: a tx descriptor or NULL.
+ */
+static struct xilinx_dpdma_tx_desc *
+xilinx_dpdma_chan_alloc_tx_desc(struct xilinx_dpdma_chan *chan)
+{
+	struct xilinx_dpdma_tx_desc *tx_desc;
+
+	tx_desc = kzalloc(sizeof(*tx_desc), GFP_ATOMIC);
+	if (!tx_desc)
+		return NULL;
+
+	INIT_LIST_HEAD(&tx_desc->descriptors);
+	tx_desc->status = PREPARED;
+
+	return tx_desc;
+}
+
+/**
+ * xilinx_dpdma_chan_free_tx_desc - Free a transaction descriptor
+ * @chan: DPDMA channel
+ * @tx_desc: tx descriptor
+ *
+ * Free the tx descriptor @tx_desc including its software descriptors.
+ */
+static void
+xilinx_dpdma_chan_free_tx_desc(struct xilinx_dpdma_chan *chan,
+			       struct xilinx_dpdma_tx_desc *tx_desc)
+{
+	struct xilinx_dpdma_sw_desc *sw_desc, *next;
+
+	if (!tx_desc)
+		return;
+
+	list_for_each_entry_safe(sw_desc, next, &tx_desc->descriptors, node) {
+		list_del(&sw_desc->node);
+		xilinx_dpdma_chan_free_sw_desc(chan, sw_desc);
+	}
+
+	kfree(tx_desc);
+}
+
+/**
+ * xilinx_dpdma_chan_submit_tx_desc - Submit a transaction descriptor
+ * @chan: DPDMA channel
+ * @tx_desc: tx descriptor
+ *
+ * Submit the tx descriptor @tx_desc to the channel @chan.
+ *
+ * Return: a cookie assigned to the tx descriptor
+ */
+static dma_cookie_t
+xilinx_dpdma_chan_submit_tx_desc(struct xilinx_dpdma_chan *chan,
+				 struct xilinx_dpdma_tx_desc *tx_desc)
+{
+	struct xilinx_dpdma_sw_desc *sw_desc;
+	dma_cookie_t cookie;
+	unsigned long flags;
+
+	spin_lock_irqsave(&chan->lock, flags);
+
+	if (chan->submitted_desc) {
+		cookie = chan->submitted_desc->async_tx.cookie;
+		goto out_unlock;
+	}
+
+	cookie = dma_cookie_assign(&tx_desc->async_tx);
+
+	/* Assign the cookie to descriptors in this transaction */
+	/* Only 16 bit will be used, but it should be enough */
+	list_for_each_entry(sw_desc, &tx_desc->descriptors, node)
+		sw_desc->hw.desc_id = cookie;
+
+	if (tx_desc != chan->allocated_desc)
+		dev_err(chan->xdev->dev, "desc != allocated_desc\n");
+	else
+		chan->allocated_desc = NULL;
+	chan->submitted_desc = tx_desc;
+
+	if (chan->id == VIDEO1 || chan->id == VIDEO2) {
+		chan->video_group = true;
+		chan->xdev->chan[VIDEO0]->video_group = true;
+	}
+
+out_unlock:
+	spin_unlock_irqrestore(&chan->lock, flags);
+
+	return cookie;
+}
+
+/**
+ * xilinx_dpdma_chan_free_desc_list - Free a descriptor list
+ * @chan: DPDMA channel
+ * @list: tx descriptor list
+ *
+ * Free tx descriptors in the list @list.
+ */
+static void xilinx_dpdma_chan_free_desc_list(struct xilinx_dpdma_chan *chan,
+					     struct list_head *list)
+{
+	struct xilinx_dpdma_tx_desc *tx_desc, *next;
+
+	list_for_each_entry_safe(tx_desc, next, list, node) {
+		list_del(&tx_desc->node);
+		xilinx_dpdma_chan_free_tx_desc(chan, tx_desc);
+	}
+}
+
+/**
+ * xilinx_dpdma_chan_free_all_desc - Free all descriptors of the channel
+ * @chan: DPDMA channel
+ *
+ * Free all descriptors associated with the channel. The channel should be
+ * disabled before this function is called, otherwise, this function may
+ * result in misbehavior of the system due to remaining outstanding
+ * transactions.
+ */
+static void xilinx_dpdma_chan_free_all_desc(struct xilinx_dpdma_chan *chan)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&chan->lock, flags);
+
+	dev_dbg(chan->xdev->dev, "chan->status = %s\n",
+		chan->status == STREAMING ? "STREAMING" : "IDLE");
+
+	xilinx_dpdma_chan_free_tx_desc(chan, chan->allocated_desc);
+	chan->allocated_desc = NULL;
+	xilinx_dpdma_chan_free_tx_desc(chan, chan->submitted_desc);
+	chan->submitted_desc = NULL;
+	xilinx_dpdma_chan_free_tx_desc(chan, chan->pending_desc);
+	chan->pending_desc = NULL;
+	xilinx_dpdma_chan_free_tx_desc(chan, chan->active_desc);
+	chan->active_desc = NULL;
+	xilinx_dpdma_chan_free_desc_list(chan, &chan->done_list);
+
+	spin_unlock_irqrestore(&chan->lock, flags);
+}
+
+/**
+ * xilinx_dpdma_chan_cleanup_desc - Clean up descriptors
+ * @chan: DPDMA channel
+ *
+ * Trigger the complete callbacks of descriptors with finished transactions.
+ * Free descriptors which are no longer in use.
+ */
+static void xilinx_dpdma_chan_cleanup_desc(struct xilinx_dpdma_chan *chan)
+{
+	struct xilinx_dpdma_tx_desc *desc;
+	dma_async_tx_callback callback;
+	void *callback_param;
+	unsigned long flags;
+	unsigned int cnt, i;
+
+	spin_lock_irqsave(&chan->lock, flags);
+
+	while (!list_empty(&chan->done_list)) {
+		desc = list_first_entry(&chan->done_list,
+					struct xilinx_dpdma_tx_desc, node);
+		list_del(&desc->node);
+
+		cnt = desc->done_cnt;
+		desc->done_cnt = 0;
+		callback = desc->async_tx.callback;
+		callback_param = desc->async_tx.callback_param;
+		if (callback) {
+			spin_unlock_irqrestore(&chan->lock, flags);
+			for (i = 0; i < cnt; i++)
+				callback(callback_param);
+			spin_lock_irqsave(&chan->lock, flags);
+		}
+
+		xilinx_dpdma_chan_free_tx_desc(chan, desc);
+	}
+
+	if (chan->active_desc) {
+		cnt = chan->active_desc->done_cnt;
+		chan->active_desc->done_cnt = 0;
+		callback = chan->active_desc->async_tx.callback;
+		callback_param = chan->active_desc->async_tx.callback_param;
+		if (callback) {
+			spin_unlock_irqrestore(&chan->lock, flags);
+			for (i = 0; i < cnt; i++)
+				callback(callback_param);
+			spin_lock_irqsave(&chan->lock, flags);
+		}
+	}
+
+	spin_unlock_irqrestore(&chan->lock, flags);
+}
+
+/**
+ * xilinx_dpdma_chan_desc_active - Set the descriptor as active
+ * @chan: DPDMA channel
+ *
+ * Make the pending descriptor @chan->pending_desc as active. This function
+ * should be called when the channel starts operating on the pending descriptor.
+ */
+static void xilinx_dpdma_chan_desc_active(struct xilinx_dpdma_chan *chan)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&chan->lock, flags);
+
+	if (!chan->pending_desc)
+		goto out_unlock;
+
+	if (chan->active_desc)
+		list_add_tail(&chan->active_desc->node, &chan->done_list);
+
+	chan->active_desc = chan->pending_desc;
+	chan->pending_desc = NULL;
+
+out_unlock:
+	spin_unlock_irqrestore(&chan->lock, flags);
+}
+
+/**
+ * xilinx_dpdma_chan_desc_done_intr - Mark the current descriptor as 'done'
+ * @chan: DPDMA channel
+ *
+ * Mark the current active descriptor @chan->active_desc as 'done'. This
+ * function should be called to mark completion of the currently active
+ * descriptor.
+ */
+static void xilinx_dpdma_chan_desc_done_intr(struct xilinx_dpdma_chan *chan)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&chan->lock, flags);
+
+	xilinx_dpdma_debugfs_intr_done_count_incr(chan->id);
+
+	if (!chan->active_desc) {
+		dev_dbg(chan->xdev->dev, "done intr with no active desc\n");
+		goto out_unlock;
+	}
+
+	chan->active_desc->done_cnt++;
+	if (chan->active_desc->status ==  PREPARED) {
+		dma_cookie_complete(&chan->active_desc->async_tx);
+		chan->active_desc->status = ACTIVE;
+	}
+
+out_unlock:
+	spin_unlock_irqrestore(&chan->lock, flags);
+	tasklet_schedule(&chan->done_task);
+}
+
+/**
+ * xilinx_dpdma_chan_prep_slave_sg - Prepare a scatter-gather dma descriptor
+ * @chan: DPDMA channel
+ * @sgl: scatter-gather list
+ *
+ * Prepare a tx descriptor incudling internal software/hardware descriptors
+ * for the given scatter-gather transaction.
+ *
+ * Return: A dma async tx descriptor on success, or NULL.
+ */
+static struct dma_async_tx_descriptor *
+xilinx_dpdma_chan_prep_slave_sg(struct xilinx_dpdma_chan *chan,
+				struct scatterlist *sgl)
+{
+	struct xilinx_dpdma_tx_desc *tx_desc;
+	struct xilinx_dpdma_sw_desc *sw_desc, *last = NULL;
+	struct scatterlist *iter = sgl;
+	u32 line_size = 0;
+
+	if (chan->allocated_desc)
+		return &chan->allocated_desc->async_tx;
+
+	tx_desc = xilinx_dpdma_chan_alloc_tx_desc(chan);
+	if (!tx_desc)
+		return NULL;
+
+	while (!sg_is_chain(iter))
+		line_size += sg_dma_len(iter++);
+
+	while (sgl) {
+		struct xilinx_dpdma_hw_desc *hw_desc;
+		dma_addr_t dma_addr[4];
+		unsigned int num_pages = 0;
+
+		sw_desc = xilinx_dpdma_chan_alloc_sw_desc(chan);
+		if (!sw_desc)
+			goto error;
+
+		while (!sg_is_chain(sgl) && !sg_is_last(sgl)) {
+			dma_addr[num_pages] = sg_dma_address(sgl++);
+			if (!IS_ALIGNED(dma_addr[num_pages++],
+					XILINX_DPDMA_ALIGN_BYTES)) {
+				dev_err(chan->xdev->dev,
+					"buffer should be aligned at %d B\n",
+					XILINX_DPDMA_ALIGN_BYTES);
+				goto error;
+			}
+		}
+
+		chan->xdev->desc_addr(sw_desc, last, dma_addr, num_pages);
+		hw_desc = &sw_desc->hw;
+		hw_desc->xfer_size = line_size;
+		hw_desc->hsize_stride =
+			line_size << XILINX_DPDMA_DESC_HSIZE_STRIDE_HSIZE_SHIFT;
+		hw_desc->control |= XILINX_DPDMA_DESC_CONTROL_PREEMBLE;
+		hw_desc->control |= XILINX_DPDMA_DESC_CONTROL_FRAG_MODE;
+		hw_desc->control |= XILINX_DPDMA_DESC_CONTROL_IGNORE_DONE;
+
+		list_add_tail(&sw_desc->node, &tx_desc->descriptors);
+		last = sw_desc;
+		if (sg_is_last(sgl))
+			break;
+		sgl = sg_chain_ptr(sgl);
+	}
+
+	sw_desc = list_first_entry(&tx_desc->descriptors,
+				   struct xilinx_dpdma_sw_desc, node);
+	if (chan->xdev->ext_addr)
+		xilinx_dpdma_sw_desc_next_64(last, sw_desc);
+	else
+		xilinx_dpdma_sw_desc_next_32(last, sw_desc);
+	last->hw.control |= XILINX_DPDMA_DESC_CONTROL_COMPLETE_INTR;
+	last->hw.control |= XILINX_DPDMA_DESC_CONTROL_LAST_OF_FRAME;
+
+	chan->allocated_desc = tx_desc;
+
+	return &tx_desc->async_tx;
+
+error:
+	xilinx_dpdma_chan_free_tx_desc(chan, tx_desc);
+
+	return NULL;
+}
+
+/**
+ * xilinx_dpdma_chan_prep_cyclic - Prepare a cyclic dma descriptor
+ * @chan: DPDMA channel
+ * @buf_addr: buffer address
+ * @buf_len: buffer length
+ * @period_len: number of periods
+ *
+ * Prepare a tx descriptor incudling internal software/hardware descriptors
+ * for the given cyclic transaction.
+ *
+ * Return: A dma async tx descriptor on success, or NULL.
+ */
+static struct dma_async_tx_descriptor *
+xilinx_dpdma_chan_prep_cyclic(struct xilinx_dpdma_chan *chan,
+			      dma_addr_t buf_addr, size_t buf_len,
+			      size_t period_len)
+{
+	struct xilinx_dpdma_tx_desc *tx_desc;
+	struct xilinx_dpdma_sw_desc *sw_desc, *last = NULL;
+	unsigned int periods = buf_len / period_len;
+	unsigned int i;
+
+	if (chan->allocated_desc)
+		return &chan->allocated_desc->async_tx;
+
+	tx_desc = xilinx_dpdma_chan_alloc_tx_desc(chan);
+	if (!tx_desc)
+		return NULL;
+
+	for (i = 0; i < periods; i++) {
+		struct xilinx_dpdma_hw_desc *hw_desc;
+
+		if (!IS_ALIGNED(buf_addr, XILINX_DPDMA_ALIGN_BYTES)) {
+			dev_err(chan->xdev->dev,
+				"buffer should be aligned at %d B\n",
+				XILINX_DPDMA_ALIGN_BYTES);
+			goto error;
+		}
+
+		sw_desc = xilinx_dpdma_chan_alloc_sw_desc(chan);
+		if (!sw_desc)
+			goto error;
+
+		chan->xdev->desc_addr(sw_desc, last, &buf_addr, 1);
+		hw_desc = &sw_desc->hw;
+		hw_desc->xfer_size = period_len;
+		hw_desc->hsize_stride =
+			period_len <<
+			XILINX_DPDMA_DESC_HSIZE_STRIDE_HSIZE_SHIFT;
+		hw_desc->hsize_stride |=
+			period_len <<
+			XILINX_DPDMA_DESC_HSIZE_STRIDE_STRIDE_SHIFT;
+		hw_desc->control |= XILINX_DPDMA_DESC_CONTROL_PREEMBLE;
+		hw_desc->control |= XILINX_DPDMA_DESC_CONTROL_IGNORE_DONE;
+		hw_desc->control |= XILINX_DPDMA_DESC_CONTROL_COMPLETE_INTR;
+
+		list_add_tail(&sw_desc->node, &tx_desc->descriptors);
+
+		buf_addr += period_len;
+		last = sw_desc;
+	}
+
+	sw_desc = list_first_entry(&tx_desc->descriptors,
+				   struct xilinx_dpdma_sw_desc, node);
+	if (chan->xdev->ext_addr)
+		xilinx_dpdma_sw_desc_next_64(last, sw_desc);
+	else
+		xilinx_dpdma_sw_desc_next_32(last, sw_desc);
+	last->hw.control |= XILINX_DPDMA_DESC_CONTROL_LAST_OF_FRAME;
+
+	chan->allocated_desc = tx_desc;
+
+	return &tx_desc->async_tx;
+
+error:
+	xilinx_dpdma_chan_free_tx_desc(chan, tx_desc);
+
+	return NULL;
+}
+
+/**
+ * xilinx_dpdma_chan_prep_interleaved - Prepare a interleaved dma descriptor
+ * @chan: DPDMA channel
+ * @xt: dma interleaved template
+ *
+ * Prepare a tx descriptor incudling internal software/hardware descriptors
+ * based on @xt.
+ *
+ * Return: A dma async tx descriptor on success, or NULL.
+ */
+static struct dma_async_tx_descriptor *
+xilinx_dpdma_chan_prep_interleaved(struct xilinx_dpdma_chan *chan,
+				   struct dma_interleaved_template *xt)
+{
+	struct xilinx_dpdma_tx_desc *tx_desc;
+	struct xilinx_dpdma_sw_desc *sw_desc;
+	struct xilinx_dpdma_hw_desc *hw_desc;
+	size_t hsize = xt->sgl[0].size;
+	size_t stride = hsize + xt->sgl[0].icg;
+
+	if (!IS_ALIGNED(xt->src_start, XILINX_DPDMA_ALIGN_BYTES)) {
+		dev_err(chan->xdev->dev, "buffer should be aligned at %d B\n",
+			XILINX_DPDMA_ALIGN_BYTES);
+		return NULL;
+	}
+
+	if (chan->allocated_desc)
+		return &chan->allocated_desc->async_tx;
+
+	tx_desc = xilinx_dpdma_chan_alloc_tx_desc(chan);
+	if (!tx_desc)
+		return NULL;
+
+	sw_desc = xilinx_dpdma_chan_alloc_sw_desc(chan);
+	if (!sw_desc)
+		goto error;
+
+	chan->xdev->desc_addr(sw_desc, sw_desc, &xt->src_start, 1);
+	hw_desc = &sw_desc->hw;
+	hsize = ALIGN(hsize, XILINX_DPDMA_LINESIZE_ALIGN_BITS / 8);
+	hw_desc->xfer_size = hsize * xt->numf;
+	hw_desc->hsize_stride = hsize <<
+				XILINX_DPDMA_DESC_HSIZE_STRIDE_HSIZE_SHIFT;
+	hw_desc->hsize_stride |= (stride / 16) <<
+				 XILINX_DPDMA_DESC_HSIZE_STRIDE_STRIDE_SHIFT;
+	hw_desc->control |= XILINX_DPDMA_DESC_CONTROL_PREEMBLE;
+	hw_desc->control |= XILINX_DPDMA_DESC_CONTROL_COMPLETE_INTR;
+	hw_desc->control |= XILINX_DPDMA_DESC_CONTROL_IGNORE_DONE;
+	hw_desc->control |= XILINX_DPDMA_DESC_CONTROL_LAST_OF_FRAME;
+
+	list_add_tail(&sw_desc->node, &tx_desc->descriptors);
+	chan->allocated_desc = tx_desc;
+
+	return &tx_desc->async_tx;
+
+error:
+	xilinx_dpdma_chan_free_tx_desc(chan, tx_desc);
+
+	return NULL;
+}
+
+/* Xilinx DPDMA channel operations */
+
+/**
+ * xilinx_dpdma_chan_enable - Enable the channel
+ * @chan: DPDMA channel
+ *
+ * Enable the channel and its interrupts. Set the QoS values for video class.
+ */
+static inline void xilinx_dpdma_chan_enable(struct xilinx_dpdma_chan *chan)
+{
+	u32 reg;
+
+	reg = XILINX_DPDMA_INTR_CHAN_MASK << chan->id;
+	reg |= XILINX_DPDMA_INTR_GLOBAL_MASK;
+	dpdma_write(chan->xdev->reg, XILINX_DPDMA_IEN, reg);
+	reg = XILINX_DPDMA_EINTR_CHAN_ERR_MASK << chan->id;
+	reg |= XILINX_DPDMA_INTR_GLOBAL_ERR;
+	dpdma_write(chan->xdev->reg, XILINX_DPDMA_EIEN, reg);
+
+	reg = XILINX_DPDMA_CH_CNTL_ENABLE;
+	reg |= XILINX_DPDMA_CH_CNTL_QOS_VID_CLASS <<
+	       XILINX_DPDMA_CH_CNTL_QOS_DSCR_WR_SHIFT;
+	reg |= XILINX_DPDMA_CH_CNTL_QOS_VID_CLASS <<
+	       XILINX_DPDMA_CH_CNTL_QOS_DSCR_RD_SHIFT;
+	reg |= XILINX_DPDMA_CH_CNTL_QOS_VID_CLASS <<
+	       XILINX_DPDMA_CH_CNTL_QOS_DATA_RD_SHIFT;
+	dpdma_set(chan->reg, XILINX_DPDMA_CH_CNTL, reg);
+}
+
+/**
+ * xilinx_dpdma_chan_disable - Disable the channel
+ * @chan: DPDMA channel
+ *
+ * Disable the channel and its interrupts.
+ */
+static inline void xilinx_dpdma_chan_disable(struct xilinx_dpdma_chan *chan)
+{
+	u32 reg;
+
+	reg = XILINX_DPDMA_INTR_CHAN_MASK << chan->id;
+	dpdma_write(chan->xdev->reg, XILINX_DPDMA_IEN, reg);
+	reg = XILINX_DPDMA_EINTR_CHAN_ERR_MASK << chan->id;
+	dpdma_write(chan->xdev->reg, XILINX_DPDMA_EIEN, reg);
+
+	dpdma_clr(chan->reg, XILINX_DPDMA_CH_CNTL, XILINX_DPDMA_CH_CNTL_ENABLE);
+}
+
+/**
+ * xilinx_dpdma_chan_pause - Pause the channel
+ * @chan: DPDMA channel
+ *
+ * Pause the channel.
+ */
+static inline void xilinx_dpdma_chan_pause(struct xilinx_dpdma_chan *chan)
+{
+	dpdma_set(chan->reg, XILINX_DPDMA_CH_CNTL, XILINX_DPDMA_CH_CNTL_PAUSE);
+}
+
+/**
+ * xilinx_dpdma_chan_unpause - Unpause the channel
+ * @chan: DPDMA channel
+ *
+ * Unpause the channel.
+ */
+static inline void xilinx_dpdma_chan_unpause(struct xilinx_dpdma_chan *chan)
+{
+	dpdma_clr(chan->reg, XILINX_DPDMA_CH_CNTL, XILINX_DPDMA_CH_CNTL_PAUSE);
+}
+
+static u32
+xilinx_dpdma_chan_video_group_ready(struct xilinx_dpdma_chan *chan)
+{
+	struct xilinx_dpdma_device *xdev = chan->xdev;
+	u32 i = 0, ret = 0;
+
+	for (i = VIDEO0; i < GRAPHICS; i++) {
+		if (xdev->chan[i]->video_group &&
+		    xdev->chan[i]->status != STREAMING)
+			return 0;
+
+		if (xdev->chan[i]->video_group)
+			ret |= BIT(i);
+	}
+
+	return ret;
+}
+
+/**
+ * xilinx_dpdma_chan_issue_pending - Issue the pending descriptor
+ * @chan: DPDMA channel
+ *
+ * Issue the first pending descriptor from @chan->submitted_desc. If the channel
+ * is already streaming, the channel is re-triggered with the pending
+ * descriptor.
+ */
+static void xilinx_dpdma_chan_issue_pending(struct xilinx_dpdma_chan *chan)
+{
+	struct xilinx_dpdma_device *xdev = chan->xdev;
+	struct xilinx_dpdma_sw_desc *sw_desc;
+	unsigned long flags;
+	u32 reg, channels;
+
+	spin_lock_irqsave(&chan->lock, flags);
+
+	if (!chan->submitted_desc || chan->pending_desc)
+		goto out_unlock;
+
+	chan->pending_desc = chan->submitted_desc;
+	chan->submitted_desc = NULL;
+
+	sw_desc = list_first_entry(&chan->pending_desc->descriptors,
+				   struct xilinx_dpdma_sw_desc, node);
+	dpdma_write(chan->reg, XILINX_DPDMA_CH_DESC_START_ADDR,
+		    (u32)sw_desc->phys);
+	if (xdev->ext_addr)
+		dpdma_write(chan->reg, XILINX_DPDMA_CH_DESC_START_ADDRE,
+			    ((u64)sw_desc->phys >> 32) &
+			    XILINX_DPDMA_DESC_ADDR_EXT_ADDR_MASK);
+
+	if (chan->first_frame) {
+		chan->first_frame = false;
+		if (chan->video_group) {
+			channels = xilinx_dpdma_chan_video_group_ready(chan);
+			if (!channels)
+				goto out_unlock;
+			reg = channels << XILINX_DPDMA_GBL_TRIG_SHIFT;
+		} else {
+			reg = 1 << (XILINX_DPDMA_GBL_TRIG_SHIFT + chan->id);
+		}
+	} else {
+		if (chan->video_group) {
+			channels = xilinx_dpdma_chan_video_group_ready(chan);
+			if (!channels)
+				goto out_unlock;
+			reg = channels << XILINX_DPDMA_GBL_RETRIG_SHIFT;
+		} else {
+			reg = 1 << (XILINX_DPDMA_GBL_RETRIG_SHIFT + chan->id);
+		}
+	}
+
+	dpdma_write(xdev->reg, XILINX_DPDMA_GBL, reg);
+
+out_unlock:
+	spin_unlock_irqrestore(&chan->lock, flags);
+}
+
+/**
+ * xilinx_dpdma_chan_start - Start the channel
+ * @chan: DPDMA channel
+ *
+ * Start the channel by enabling interrupts and triggering the channel.
+ * If the channel is enabled already or there's no pending descriptor, this
+ * function won't do anything on the channel.
+ */
+static void xilinx_dpdma_chan_start(struct xilinx_dpdma_chan *chan)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&chan->lock, flags);
+
+	if (!chan->submitted_desc || chan->status == STREAMING)
+		goto out_unlock;
+
+	xilinx_dpdma_chan_unpause(chan);
+	xilinx_dpdma_chan_enable(chan);
+	chan->first_frame = true;
+	chan->status = STREAMING;
+
+out_unlock:
+	spin_unlock_irqrestore(&chan->lock, flags);
+}
+
+/**
+ * xilinx_dpdma_chan_ostand - Number of outstanding transactions
+ * @chan: DPDMA channel
+ *
+ * Read and return the number of outstanding transactions from register.
+ *
+ * Return: Number of outstanding transactions from the status register.
+ */
+static inline u32 xilinx_dpdma_chan_ostand(struct xilinx_dpdma_chan *chan)
+{
+	return dpdma_read(chan->reg, XILINX_DPDMA_CH_STATUS) >>
+	       XILINX_DPDMA_CH_STATUS_OTRAN_CNT_SHIFT &
+	       XILINX_DPDMA_CH_STATUS_OTRAN_CNT_MASK;
+}
+
+/**
+ * xilinx_dpdma_chan_no_ostand - Notify no outstanding transaction event
+ * @chan: DPDMA channel
+ *
+ * Notify waiters for no outstanding event, so waiters can stop the channel
+ * safely. This function is supposed to be called when 'no outstanding'
+ * interrupt is generated. The 'no outstanding' interrupt is disabled and
+ * should be re-enabled when this event is handled. If the channel status
+ * register still shows some number of outstanding transactions, the interrupt
+ * remains enabled.
+ *
+ * Return: 0 on success. On failure, -EWOULDBLOCK if there's still outstanding
+ * transaction(s).
+ */
+static int xilinx_dpdma_chan_notify_no_ostand(struct xilinx_dpdma_chan *chan)
+{
+	u32 cnt;
+
+	cnt = xilinx_dpdma_chan_ostand(chan);
+	if (cnt) {
+		dev_dbg(chan->xdev->dev, "%d outstanding transactions\n", cnt);
+		return -EWOULDBLOCK;
+	}
+
+	/* Disable 'no outstanding' interrupt */
+	dpdma_write(chan->xdev->reg, XILINX_DPDMA_IDS,
+		    1 << (XILINX_DPDMA_INTR_NO_OSTAND_SHIFT + chan->id));
+	wake_up(&chan->wait_to_stop);
+
+	return 0;
+}
+
+/**
+ * xilinx_dpdma_chan_wait_no_ostand - Wait for the no outstanding intr
+ * @chan: DPDMA channel
+ *
+ * Wait for the no outstanding transaction interrupt. This functions can sleep
+ * for 50ms.
+ *
+ * Return: 0 on success. On failure, -ETIMEOUT for time out, or the error code
+ * from wait_event_interruptible_timeout().
+ */
+static int xilinx_dpdma_chan_wait_no_ostand(struct xilinx_dpdma_chan *chan)
+{
+	int ret;
+
+	/* Wait for a no outstanding transaction interrupt upto 50msec */
+	ret = wait_event_interruptible_timeout(chan->wait_to_stop,
+					       !xilinx_dpdma_chan_ostand(chan),
+					       msecs_to_jiffies(50));
+	if (ret > 0) {
+		dpdma_write(chan->xdev->reg, XILINX_DPDMA_IEN,
+			    1 <<
+			    (XILINX_DPDMA_INTR_NO_OSTAND_SHIFT + chan->id));
+		return 0;
+	}
+
+	dev_err(chan->xdev->dev, "not ready to stop: %d trans\n",
+		xilinx_dpdma_chan_ostand(chan));
+
+	if (ret == 0)
+		return -ETIMEDOUT;
+
+	return ret;
+}
+
+/**
+ * xilinx_dpdma_chan_poll_no_ostand - Poll the outstanding transaction status
+ * @chan: DPDMA channel
+ *
+ * Poll the outstanding transaction status, and return when there's no
+ * outstanding transaction. This functions can be used in the interrupt context
+ * or where the atomicity is required. Calling thread may wait more than 50ms.
+ *
+ * Return: 0 on success, or -ETIMEDOUT.
+ */
+static int xilinx_dpdma_chan_poll_no_ostand(struct xilinx_dpdma_chan *chan)
+{
+	u32 cnt, loop = 50000;
+
+	/* Poll at least for 50ms (20 fps). */
+	do {
+		cnt = xilinx_dpdma_chan_ostand(chan);
+		udelay(1);
+	} while (loop-- > 0 && cnt);
+
+	if (loop) {
+		dpdma_write(chan->xdev->reg, XILINX_DPDMA_IEN,
+			    1 <<
+			    (XILINX_DPDMA_INTR_NO_OSTAND_SHIFT + chan->id));
+		return 0;
+	}
+
+	dev_err(chan->xdev->dev, "not ready to stop: %d trans\n",
+		xilinx_dpdma_chan_ostand(chan));
+
+	return -ETIMEDOUT;
+}
+
+/**
+ * xilinx_dpdma_chan_stop - Stop the channel
+ * @chan: DPDMA channel
+ * @poll: flag whether to poll or wait
+ *
+ * Stop the channel with the following sequence: 1. Pause, 2. Wait (sleep) for
+ * no outstanding transaction interrupt, 3. Disable the channel.
+ *
+ * Return: 0 on success, or an error from xilinx_dpdma_chan_poll/wait_ostand().
+ */
+static int xilinx_dpdma_chan_stop(struct xilinx_dpdma_chan *chan, bool poll)
+{
+	unsigned long flags;
+	bool ret;
+
+	xilinx_dpdma_chan_pause(chan);
+	if (poll)
+		ret = xilinx_dpdma_chan_poll_no_ostand(chan);
+	else
+		ret = xilinx_dpdma_chan_wait_no_ostand(chan);
+	if (ret)
+		return ret;
+
+	spin_lock_irqsave(&chan->lock, flags);
+	xilinx_dpdma_chan_disable(chan);
+	chan->status = IDLE;
+	spin_unlock_irqrestore(&chan->lock, flags);
+
+	return 0;
+}
+
+/**
+ * xilinx_dpdma_chan_alloc_resources - Allocate resources for the channel
+ * @chan: DPDMA channel
+ *
+ * Allocate a descriptor pool for the channel.
+ *
+ * Return: 0 on success, or -ENOMEM if failed to allocate a pool.
+ */
+static int xilinx_dpdma_chan_alloc_resources(struct xilinx_dpdma_chan *chan)
+{
+	chan->desc_pool = dma_pool_create(dev_name(chan->xdev->dev),
+				chan->xdev->dev,
+				sizeof(struct xilinx_dpdma_sw_desc),
+				__alignof__(struct xilinx_dpdma_sw_desc), 0);
+	if (!chan->desc_pool) {
+		dev_err(chan->xdev->dev,
+			"failed to allocate a descriptor pool\n");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+/**
+ * xilinx_dpdma_chan_free_resources - Free all resources for the channel
+ * @chan: DPDMA channel
+ *
+ * Free all descriptors and the descriptor pool for the channel.
+ */
+static void xilinx_dpdma_chan_free_resources(struct xilinx_dpdma_chan *chan)
+{
+	xilinx_dpdma_chan_free_all_desc(chan);
+	dma_pool_destroy(chan->desc_pool);
+	chan->desc_pool = NULL;
+}
+
+/**
+ * xilinx_dpdma_chan_terminate_all - Terminate the channel and descriptors
+ * @chan: DPDMA channel
+ *
+ * Stop the channel and free all associated descriptors. Poll the no outstanding
+ * transaction interrupt as this can be called from an atomic context.
+ *
+ * Return: 0 on success, or the error code from xilinx_dpdma_chan_stop().
+ */
+static int xilinx_dpdma_chan_terminate_all(struct xilinx_dpdma_chan *chan)
+{
+	struct xilinx_dpdma_device *xdev = chan->xdev;
+	int ret;
+	unsigned int i;
+
+	if (chan->video_group) {
+		for (i = VIDEO0; i < GRAPHICS; i++) {
+			if (xdev->chan[i]->video_group &&
+			    xdev->chan[i]->status == STREAMING) {
+				xilinx_dpdma_chan_pause(xdev->chan[i]);
+				xdev->chan[i]->video_group = false;
+			}
+		}
+	}
+
+	ret = xilinx_dpdma_chan_stop(chan, true);
+	if (ret)
+		return ret;
+
+	xilinx_dpdma_chan_free_all_desc(chan);
+
+	return 0;
+}
+
+/**
+ * xilinx_dpdma_chan_synchronize - Synchronize all outgoing transfer
+ * @chan: DPDMA channel
+ *
+ * Stop the channel and free all associated descriptors. As this can't be
+ * called in an atomic context, sleep-wait for no outstanding transaction
+ * interrupt. Then kill all related tasklets.
+ *
+ * Return: 0 on success, or the error code from xilinx_dpdma_chan_stop().
+ */
+static int xilinx_dpdma_chan_synchronize(struct xilinx_dpdma_chan *chan)
+{
+	struct xilinx_dpdma_device *xdev = chan->xdev;
+	int ret;
+	unsigned int i;
+
+	if (chan->video_group) {
+		for (i = VIDEO0; i < GRAPHICS; i++) {
+			if (xdev->chan[i]->video_group &&
+			    xdev->chan[i]->status == STREAMING) {
+				xilinx_dpdma_chan_pause(xdev->chan[i]);
+				xdev->chan[i]->video_group = false;
+			}
+		}
+	}
+
+	ret = xilinx_dpdma_chan_stop(chan, false);
+	if (ret)
+		return ret;
+
+	tasklet_kill(&chan->err_task);
+	tasklet_kill(&chan->done_task);
+	xilinx_dpdma_chan_free_all_desc(chan);
+
+	return 0;
+}
+
+/**
+ * xilinx_dpdma_chan_err - Detect any channel error
+ * @chan: DPDMA channel
+ * @isr: masked Interrupt Status Register
+ * @eisr: Error Interrupt Status Register
+ *
+ * Return: true if any channel error occurs, or false otherwise.
+ */
+static bool
+xilinx_dpdma_chan_err(struct xilinx_dpdma_chan *chan, u32 isr, u32 eisr)
+{
+	if (!chan)
+		return false;
+
+	if (chan->status == STREAMING &&
+	    ((isr & (XILINX_DPDMA_INTR_CHAN_ERR_MASK << chan->id)) ||
+	    (eisr & (XILINX_DPDMA_EINTR_CHAN_ERR_MASK << chan->id))))
+		return true;
+
+	return false;
+}
+
+/**
+ * xilinx_dpdma_chan_handle_err - DPDMA channel error handling
+ * @chan: DPDMA channel
+ *
+ * This function is called when any channel error or any global error occurs.
+ * The function disables the paused channel by errors and determines
+ * if the current active descriptor can be rescheduled depending on
+ * the descriptor status.
+ */
+static void xilinx_dpdma_chan_handle_err(struct xilinx_dpdma_chan *chan)
+{
+	struct xilinx_dpdma_device *xdev = chan->xdev;
+	struct device *dev = xdev->dev;
+	unsigned long flags;
+
+	spin_lock_irqsave(&chan->lock, flags);
+
+	dev_dbg(dev, "cur desc addr = 0x%04x%08x\n",
+		dpdma_read(chan->reg, XILINX_DPDMA_CH_DESC_START_ADDRE),
+		dpdma_read(chan->reg, XILINX_DPDMA_CH_DESC_START_ADDR));
+	dev_dbg(dev, "cur payload addr = 0x%04x%08x\n",
+		dpdma_read(chan->reg, XILINX_DPDMA_CH_PYLD_CUR_ADDRE),
+		dpdma_read(chan->reg, XILINX_DPDMA_CH_PYLD_CUR_ADDR));
+
+	xilinx_dpdma_chan_disable(chan);
+	chan->status = IDLE;
+
+	if (!chan->active_desc)
+		goto out_unlock;
+
+	xilinx_dpdma_chan_dump_tx_desc(chan, chan->active_desc);
+
+	switch (chan->active_desc->status) {
+	case ERRORED:
+		dev_dbg(dev, "repeated error on desc\n");
+		/* fall-through */
+	case ACTIVE:
+		/* fall-through */
+	case PREPARED:
+		/* Reschedule if there's no new descriptor */
+		if (!chan->pending_desc && !chan->submitted_desc) {
+			chan->active_desc->status = ERRORED;
+			chan->submitted_desc = chan->active_desc;
+		} else {
+			xilinx_dpdma_chan_free_tx_desc(chan, chan->active_desc);
+		}
+		break;
+	}
+	chan->active_desc = NULL;
+
+out_unlock:
+	spin_unlock_irqrestore(&chan->lock, flags);
+}
+
+/* DMA tx descriptor */
+
+static dma_cookie_t xilinx_dpdma_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+	struct xilinx_dpdma_chan *chan = to_xilinx_chan(tx->chan);
+	struct xilinx_dpdma_tx_desc *tx_desc = to_dpdma_tx_desc(tx);
+
+	return xilinx_dpdma_chan_submit_tx_desc(chan, tx_desc);
+}
+
+/* DMA channel operations */
+
+static struct dma_async_tx_descriptor *
+xilinx_dpdma_prep_slave_sg(struct dma_chan *dchan, struct scatterlist *sgl,
+			   unsigned int sg_len,
+			   enum dma_transfer_direction direction,
+			   unsigned long flags, void *context)
+{
+	struct xilinx_dpdma_chan *chan = to_xilinx_chan(dchan);
+	struct dma_async_tx_descriptor *async_tx;
+
+	if (direction != DMA_MEM_TO_DEV)
+		return NULL;
+
+	if (!sgl || sg_len < 2)
+		return NULL;
+
+	async_tx = xilinx_dpdma_chan_prep_slave_sg(chan, sgl);
+	if (!async_tx)
+		return NULL;
+
+	dma_async_tx_descriptor_init(async_tx, dchan);
+	async_tx->tx_submit = xilinx_dpdma_tx_submit;
+	async_tx->flags = flags;
+	async_tx_ack(async_tx);
+
+	return async_tx;
+}
+
+static struct dma_async_tx_descriptor *
+xilinx_dpdma_prep_dma_cyclic(struct dma_chan *dchan, dma_addr_t buf_addr,
+			     size_t buf_len, size_t period_len,
+			     enum dma_transfer_direction direction,
+			     unsigned long flags)
+{
+	struct xilinx_dpdma_chan *chan = to_xilinx_chan(dchan);
+	struct dma_async_tx_descriptor *async_tx;
+
+	if (direction != DMA_MEM_TO_DEV)
+		return NULL;
+
+	if (buf_len % period_len)
+		return NULL;
+
+	async_tx = xilinx_dpdma_chan_prep_cyclic(chan, buf_addr, buf_len,
+						 period_len);
+	if (!async_tx)
+		return NULL;
+
+	dma_async_tx_descriptor_init(async_tx, dchan);
+	async_tx->tx_submit = xilinx_dpdma_tx_submit;
+	async_tx->flags = flags;
+	async_tx_ack(async_tx);
+
+	return async_tx;
+}
+
+static struct dma_async_tx_descriptor *
+xilinx_dpdma_prep_interleaved_dma(struct dma_chan *dchan,
+				  struct dma_interleaved_template *xt,
+				  unsigned long flags)
+{
+	struct xilinx_dpdma_chan *chan = to_xilinx_chan(dchan);
+	struct dma_async_tx_descriptor *async_tx;
+
+	if (xt->dir != DMA_MEM_TO_DEV)
+		return NULL;
+
+	if (!xt->numf || !xt->sgl[0].size)
+		return NULL;
+
+	async_tx = xilinx_dpdma_chan_prep_interleaved(chan, xt);
+	if (!async_tx)
+		return NULL;
+
+	dma_async_tx_descriptor_init(async_tx, dchan);
+	async_tx->tx_submit = xilinx_dpdma_tx_submit;
+	async_tx->flags = flags;
+	async_tx_ack(async_tx);
+
+	return async_tx;
+}
+
+static int xilinx_dpdma_alloc_chan_resources(struct dma_chan *dchan)
+{
+	struct xilinx_dpdma_chan *chan = to_xilinx_chan(dchan);
+
+	dma_cookie_init(dchan);
+
+	return xilinx_dpdma_chan_alloc_resources(chan);
+}
+
+static void xilinx_dpdma_free_chan_resources(struct dma_chan *dchan)
+{
+	struct xilinx_dpdma_chan *chan = to_xilinx_chan(dchan);
+
+	xilinx_dpdma_chan_free_resources(chan);
+}
+
+static enum dma_status xilinx_dpdma_tx_status(struct dma_chan *dchan,
+					      dma_cookie_t cookie,
+					      struct dma_tx_state *txstate)
+{
+	return dma_cookie_status(dchan, cookie, txstate);
+}
+
+static void xilinx_dpdma_issue_pending(struct dma_chan *dchan)
+{
+	struct xilinx_dpdma_chan *chan = to_xilinx_chan(dchan);
+
+	xilinx_dpdma_chan_start(chan);
+	xilinx_dpdma_chan_issue_pending(chan);
+}
+
+static int xilinx_dpdma_config(struct dma_chan *dchan,
+			       struct dma_slave_config *config)
+{
+	if (config->direction != DMA_MEM_TO_DEV)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int xilinx_dpdma_pause(struct dma_chan *dchan)
+{
+	xilinx_dpdma_chan_pause(to_xilinx_chan(dchan));
+
+	return 0;
+}
+
+static int xilinx_dpdma_resume(struct dma_chan *dchan)
+{
+	xilinx_dpdma_chan_unpause(to_xilinx_chan(dchan));
+
+	return 0;
+}
+
+static int xilinx_dpdma_terminate_all(struct dma_chan *dchan)
+{
+	return xilinx_dpdma_chan_terminate_all(to_xilinx_chan(dchan));
+}
+
+static void xilinx_dpdma_synchronize(struct dma_chan *dchan)
+{
+	xilinx_dpdma_chan_synchronize(to_xilinx_chan(dchan));
+}
+
+/* Xilinx DPDMA device operations */
+
+/**
+ * xilinx_dpdma_err - Detect any global error
+ * @isr: Interrupt Status Register
+ * @eisr: Error Interrupt Status Register
+ *
+ * Return: True if any global error occurs, or false otherwise.
+ */
+static bool xilinx_dpdma_err(u32 isr, u32 eisr)
+{
+	if ((isr & XILINX_DPDMA_INTR_GLOBAL_ERR ||
+	     eisr & XILINX_DPDMA_EINTR_GLOBAL_ERR))
+		return true;
+
+	return false;
+}
+
+/**
+ * xilinx_dpdma_handle_err_intr - Handle DPDMA error interrupt
+ * @xdev: DPDMA device
+ * @isr: masked Interrupt Status Register
+ * @eisr: Error Interrupt Status Register
+ *
+ * Handle if any error occurs based on @isr and @eisr. This function disables
+ * corresponding error interrupts, and those should be re-enabled once handling
+ * is done.
+ */
+static void xilinx_dpdma_handle_err_intr(struct xilinx_dpdma_device *xdev,
+					 u32 isr, u32 eisr)
+{
+	bool err = xilinx_dpdma_err(isr, eisr);
+	unsigned int i;
+
+	dev_dbg_ratelimited(xdev->dev,
+			    "error intr: isr = 0x%08x, eisr = 0x%08x\n",
+			    isr, eisr);
+
+	/* Disable channel error interrupts until errors are handled. */
+	dpdma_write(xdev->reg, XILINX_DPDMA_IDS,
+		    isr & ~XILINX_DPDMA_INTR_GLOBAL_ERR);
+	dpdma_write(xdev->reg, XILINX_DPDMA_EIDS,
+		    eisr & ~XILINX_DPDMA_EINTR_GLOBAL_ERR);
+
+	for (i = 0; i < XILINX_DPDMA_NUM_CHAN; i++)
+		if (err || xilinx_dpdma_chan_err(xdev->chan[i], isr, eisr))
+			tasklet_schedule(&xdev->chan[i]->err_task);
+}
+
+/**
+ * xilinx_dpdma_handle_vsync_intr - Handle the VSYNC interrupt
+ * @xdev: DPDMA device
+ *
+ * Handle the VSYNC event. At this point, the current frame becomes active,
+ * which means the DPDMA actually starts fetching, and the next frame can be
+ * scheduled.
+ */
+static void xilinx_dpdma_handle_vsync_intr(struct xilinx_dpdma_device *xdev)
+{
+	unsigned int i;
+
+	for (i = 0; i < XILINX_DPDMA_NUM_CHAN; i++) {
+		if (xdev->chan[i] &&
+		    xdev->chan[i]->status == STREAMING) {
+			xilinx_dpdma_chan_desc_active(xdev->chan[i]);
+			xilinx_dpdma_chan_issue_pending(xdev->chan[i]);
+		}
+	}
+}
+
+/**
+ * xilinx_dpdma_enable_intr - Enable interrupts
+ * @xdev: DPDMA device
+ *
+ * Enable interrupts.
+ */
+static void xilinx_dpdma_enable_intr(struct xilinx_dpdma_device *xdev)
+{
+	dpdma_write(xdev->reg, XILINX_DPDMA_IEN, XILINX_DPDMA_INTR_ALL);
+	dpdma_write(xdev->reg, XILINX_DPDMA_EIEN, XILINX_DPDMA_EINTR_ALL);
+}
+
+/**
+ * xilinx_dpdma_disable_intr - Disable interrupts
+ * @xdev: DPDMA device
+ *
+ * Disable interrupts.
+ */
+static void xilinx_dpdma_disable_intr(struct xilinx_dpdma_device *xdev)
+{
+	dpdma_write(xdev->reg, XILINX_DPDMA_IDS, XILINX_DPDMA_INTR_ERR_ALL);
+	dpdma_write(xdev->reg, XILINX_DPDMA_EIDS, XILINX_DPDMA_EINTR_ALL);
+}
+
+/* Interrupt handling operations*/
+
+/**
+ * xilinx_dpdma_chan_err_task - Per channel tasklet for error handling
+ * @data: tasklet data to be casted to DPDMA channel structure
+ *
+ * Per channel error handling tasklet. This function waits for the outstanding
+ * transaction to complete and triggers error handling. After error handling,
+ * re-enable channel error interrupts, and restart the channel if needed.
+ */
+static void xilinx_dpdma_chan_err_task(unsigned long data)
+{
+	struct xilinx_dpdma_chan *chan = (struct xilinx_dpdma_chan *)data;
+	struct xilinx_dpdma_device *xdev = chan->xdev;
+
+	/* Proceed error handling even when polling fails. */
+	xilinx_dpdma_chan_poll_no_ostand(chan);
+
+	xilinx_dpdma_chan_handle_err(chan);
+
+	dpdma_write(xdev->reg, XILINX_DPDMA_IEN,
+		    XILINX_DPDMA_INTR_CHAN_ERR_MASK << chan->id);
+	dpdma_write(xdev->reg, XILINX_DPDMA_EIEN,
+		    XILINX_DPDMA_EINTR_CHAN_ERR_MASK << chan->id);
+
+	xilinx_dpdma_chan_start(chan);
+	xilinx_dpdma_chan_issue_pending(chan);
+}
+
+/**
+ * xilinx_dpdma_chan_done_task - Per channel tasklet for done interrupt handling
+ * @data: tasklet data to be casted to DPDMA channel structure
+ *
+ * Per channel done interrupt handling tasklet.
+ */
+static void xilinx_dpdma_chan_done_task(unsigned long data)
+{
+	struct xilinx_dpdma_chan *chan = (struct xilinx_dpdma_chan *)data;
+
+	xilinx_dpdma_chan_cleanup_desc(chan);
+}
+
+static irqreturn_t xilinx_dpdma_irq_handler(int irq, void *data)
+{
+	struct xilinx_dpdma_device *xdev = data;
+	u32 status, error, i;
+	unsigned long masked;
+
+	status = dpdma_read(xdev->reg, XILINX_DPDMA_ISR);
+	error = dpdma_read(xdev->reg, XILINX_DPDMA_EISR);
+	if (!status && !error)
+		return IRQ_NONE;
+
+	dpdma_write(xdev->reg, XILINX_DPDMA_ISR, status);
+	dpdma_write(xdev->reg, XILINX_DPDMA_EISR, error);
+
+	if (status & XILINX_DPDMA_INTR_VSYNC)
+		xilinx_dpdma_handle_vsync_intr(xdev);
+
+	masked = (status & XILINX_DPDMA_INTR_DESC_DONE_MASK) >>
+		 XILINX_DPDMA_INTR_DESC_DONE_SHIFT;
+	if (masked)
+		for_each_set_bit(i, &masked, XILINX_DPDMA_NUM_CHAN)
+			xilinx_dpdma_chan_desc_done_intr(xdev->chan[i]);
+
+	masked = (status & XILINX_DPDMA_INTR_NO_OSTAND_MASK) >>
+		 XILINX_DPDMA_INTR_NO_OSTAND_SHIFT;
+	if (masked)
+		for_each_set_bit(i, &masked, XILINX_DPDMA_NUM_CHAN)
+			xilinx_dpdma_chan_notify_no_ostand(xdev->chan[i]);
+
+	masked = status & XILINX_DPDMA_INTR_ERR_ALL;
+	if (masked || error)
+		xilinx_dpdma_handle_err_intr(xdev, masked, error);
+
+	return IRQ_HANDLED;
+}
+
+/* Initialization operations */
+
+static struct xilinx_dpdma_chan *
+xilinx_dpdma_chan_probe(struct device_node *node,
+			struct xilinx_dpdma_device *xdev)
+{
+	struct xilinx_dpdma_chan *chan;
+
+	chan = devm_kzalloc(xdev->dev, sizeof(*chan), GFP_KERNEL);
+	if (!chan)
+		return ERR_PTR(-ENOMEM);
+
+	if (of_device_is_compatible(node, "xlnx,video0")) {
+		chan->id = VIDEO0;
+	} else if (of_device_is_compatible(node, "xlnx,video1")) {
+		chan->id = VIDEO1;
+	} else if (of_device_is_compatible(node, "xlnx,video2")) {
+		chan->id = VIDEO2;
+	} else if (of_device_is_compatible(node, "xlnx,graphics")) {
+		chan->id = GRAPHICS;
+	} else if (of_device_is_compatible(node, "xlnx,audio0")) {
+		chan->id = AUDIO0;
+	} else if (of_device_is_compatible(node, "xlnx,audio1")) {
+		chan->id = AUDIO1;
+	} else {
+		dev_err(xdev->dev, "invalid channel compatible string in DT\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	chan->reg = xdev->reg + XILINX_DPDMA_CH_BASE + XILINX_DPDMA_CH_OFFSET *
+		    chan->id;
+	chan->status = IDLE;
+
+	spin_lock_init(&chan->lock);
+	INIT_LIST_HEAD(&chan->done_list);
+	init_waitqueue_head(&chan->wait_to_stop);
+
+	tasklet_init(&chan->done_task, xilinx_dpdma_chan_done_task,
+		     (unsigned long)chan);
+	tasklet_init(&chan->err_task, xilinx_dpdma_chan_err_task,
+		     (unsigned long)chan);
+
+	chan->common.device = &xdev->common;
+	chan->xdev = xdev;
+
+	list_add_tail(&chan->common.device_node, &xdev->common.channels);
+	xdev->chan[chan->id] = chan;
+
+	return chan;
+}
+
+static void xilinx_dpdma_chan_remove(struct xilinx_dpdma_chan *chan)
+{
+	tasklet_kill(&chan->err_task);
+	tasklet_kill(&chan->done_task);
+	list_del(&chan->common.device_node);
+}
+
+static struct dma_chan *of_dma_xilinx_xlate(struct of_phandle_args *dma_spec,
+					    struct of_dma *ofdma)
+{
+	struct xilinx_dpdma_device *xdev = ofdma->of_dma_data;
+	uint32_t chan_id = dma_spec->args[0];
+
+	if (chan_id >= XILINX_DPDMA_NUM_CHAN)
+		return NULL;
+
+	if (!xdev->chan[chan_id])
+		return NULL;
+
+	return dma_get_slave_channel(&xdev->chan[chan_id]->common);
+}
+
+static int xilinx_dpdma_probe(struct platform_device *pdev)
+{
+	struct xilinx_dpdma_device *xdev;
+	struct xilinx_dpdma_chan *chan;
+	struct dma_device *ddev;
+	struct resource *res;
+	struct device_node *node, *child;
+	u32 i;
+	int irq, ret;
+
+	xdev = devm_kzalloc(&pdev->dev, sizeof(*xdev), GFP_KERNEL);
+	if (!xdev)
+		return -ENOMEM;
+
+	xdev->dev = &pdev->dev;
+	ddev = &xdev->common;
+	ddev->dev = &pdev->dev;
+	node = xdev->dev->of_node;
+
+	xdev->axi_clk = devm_clk_get(xdev->dev, "axi_clk");
+	if (IS_ERR(xdev->axi_clk))
+		return PTR_ERR(xdev->axi_clk);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	xdev->reg = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(xdev->reg))
+		return PTR_ERR(xdev->reg);
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(xdev->dev, "failed to get platform irq\n");
+		return irq;
+	}
+
+	ret = devm_request_irq(xdev->dev, irq, xilinx_dpdma_irq_handler,
+			       IRQF_SHARED, dev_name(xdev->dev), xdev);
+	if (ret) {
+		dev_err(xdev->dev, "failed to request IRQ\n");
+		return ret;
+	}
+
+	INIT_LIST_HEAD(&xdev->common.channels);
+	dma_cap_set(DMA_SLAVE, ddev->cap_mask);
+	dma_cap_set(DMA_PRIVATE, ddev->cap_mask);
+	dma_cap_set(DMA_CYCLIC, ddev->cap_mask);
+	dma_cap_set(DMA_INTERLEAVE, ddev->cap_mask);
+	ddev->copy_align = fls(XILINX_DPDMA_ALIGN_BYTES - 1);
+
+	ddev->device_alloc_chan_resources = xilinx_dpdma_alloc_chan_resources;
+	ddev->device_free_chan_resources = xilinx_dpdma_free_chan_resources;
+	ddev->device_prep_slave_sg = xilinx_dpdma_prep_slave_sg;
+	ddev->device_prep_dma_cyclic = xilinx_dpdma_prep_dma_cyclic;
+	ddev->device_prep_interleaved_dma = xilinx_dpdma_prep_interleaved_dma;
+	ddev->device_tx_status = xilinx_dpdma_tx_status;
+	ddev->device_issue_pending = xilinx_dpdma_issue_pending;
+	ddev->device_config = xilinx_dpdma_config;
+	ddev->device_pause = xilinx_dpdma_pause;
+	ddev->device_resume = xilinx_dpdma_resume;
+	ddev->device_terminate_all = xilinx_dpdma_terminate_all;
+	ddev->device_synchronize = xilinx_dpdma_synchronize;
+	ddev->src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_UNDEFINED);
+	ddev->directions = BIT(DMA_MEM_TO_DEV);
+	ddev->residue_granularity = DMA_RESIDUE_GRANULARITY_DESCRIPTOR;
+
+	for_each_child_of_node(node, child) {
+		chan = xilinx_dpdma_chan_probe(child, xdev);
+		if (IS_ERR(chan)) {
+			dev_err(xdev->dev, "failed to probe a channel\n");
+			ret = PTR_ERR(chan);
+			goto error;
+		}
+	}
+
+	xdev->ext_addr = sizeof(dma_addr_t) > 4;
+	if (xdev->ext_addr)
+		xdev->desc_addr = xilinx_dpdma_sw_desc_addr_64;
+	else
+		xdev->desc_addr = xilinx_dpdma_sw_desc_addr_32;
+
+	ret = clk_prepare_enable(xdev->axi_clk);
+	if (ret) {
+		dev_err(xdev->dev, "failed to enable the axi clock\n");
+		goto error;
+	}
+
+	ret = dma_async_device_register(ddev);
+	if (ret) {
+		dev_err(xdev->dev, "failed to register the dma device\n");
+		goto error_dma_async;
+	}
+
+	ret = of_dma_controller_register(xdev->dev->of_node,
+					 of_dma_xilinx_xlate, ddev);
+	if (ret) {
+		dev_err(xdev->dev, "failed to register DMA to DT DMA helper\n");
+		goto error_of_dma;
+	}
+
+	xilinx_dpdma_enable_intr(xdev);
+
+	xilinx_dpdma_debugfs_init(&pdev->dev);
+
+	dev_info(&pdev->dev, "Xilinx DPDMA engine is probed\n");
+
+	return 0;
+
+error_of_dma:
+	dma_async_device_unregister(ddev);
+error_dma_async:
+	clk_disable_unprepare(xdev->axi_clk);
+error:
+	for (i = 0; i < XILINX_DPDMA_NUM_CHAN; i++)
+		if (xdev->chan[i])
+			xilinx_dpdma_chan_remove(xdev->chan[i]);
+
+	return ret;
+}
+
+static int xilinx_dpdma_remove(struct platform_device *pdev)
+{
+	struct xilinx_dpdma_device *xdev;
+	unsigned int i;
+
+	xdev = platform_get_drvdata(pdev);
+
+	xilinx_dpdma_disable_intr(xdev);
+	of_dma_controller_free(pdev->dev.of_node);
+	dma_async_device_unregister(&xdev->common);
+	clk_disable_unprepare(xdev->axi_clk);
+
+	for (i = 0; i < XILINX_DPDMA_NUM_CHAN; i++)
+		if (xdev->chan[i])
+			xilinx_dpdma_chan_remove(xdev->chan[i]);
+
+	return 0;
+}
+
+static const struct of_device_id xilinx_dpdma_of_match[] = {
+	{ .compatible = "xlnx,dpdma",},
+	{ /* end of table */ },
+};
+MODULE_DEVICE_TABLE(of, xilinx_dpdma_of_match);
+
+static struct platform_driver xilinx_dpdma_driver = {
+	.probe			= xilinx_dpdma_probe,
+	.remove			= xilinx_dpdma_remove,
+	.driver			= {
+		.name		= "xilinx-dpdma",
+		.of_match_table	= xilinx_dpdma_of_match,
+	},
+};
+
+module_platform_driver(xilinx_dpdma_driver);
+
+MODULE_AUTHOR("Xilinx, Inc.");
+MODULE_DESCRIPTION("Xilinx DPDMA driver");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/xilinx/xilinx_frmbuf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/xilinx/xilinx_frmbuf.c
@@ -0,0 +1,1711 @@
+/*
+ * DMAEngine driver for Xilinx Framebuffer IP
+ *
+ * Copyright (C) 2016,2017 Xilinx, Inc. All rights reserved.
+ *
+ * Authors: Radhey Shyam Pandey <radheys@xilinx.com>
+ *          John Nichols <jnichol@xilinx.com>
+ *          Jeffrey Mouroux <jmouroux@xilinx.com>
+ *
+ * Based on the Freescale DMA driver.
+ *
+ * Description:
+ * The AXI Framebuffer core is a soft Xilinx IP core that
+ * provides high-bandwidth direct memory access between memory
+ * and AXI4-Stream.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/dma/xilinx_frmbuf.h>
+#include <linux/dmapool.h>
+#include <linux/gpio/consumer.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_dma.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+
+#include <drm/drm_fourcc.h>
+
+#include "../dmaengine.h"
+
+/* Register/Descriptor Offsets */
+#define XILINX_FRMBUF_CTRL_OFFSET		0x00
+#define XILINX_FRMBUF_GIE_OFFSET		0x04
+#define XILINX_FRMBUF_IE_OFFSET			0x08
+#define XILINX_FRMBUF_ISR_OFFSET		0x0c
+#define XILINX_FRMBUF_WIDTH_OFFSET		0x10
+#define XILINX_FRMBUF_HEIGHT_OFFSET		0x18
+#define XILINX_FRMBUF_STRIDE_OFFSET		0x20
+#define XILINX_FRMBUF_FMT_OFFSET		0x28
+#define XILINX_FRMBUF_ADDR_OFFSET		0x30
+#define XILINX_FRMBUF_ADDR2_OFFSET		0x3c
+#define XILINX_FRMBUF_FID_OFFSET		0x48
+
+/* Control Registers */
+#define XILINX_FRMBUF_CTRL_AP_START		BIT(0)
+#define XILINX_FRMBUF_CTRL_AP_DONE		BIT(1)
+#define XILINX_FRMBUF_CTRL_AP_IDLE		BIT(2)
+#define XILINX_FRMBUF_CTRL_AP_READY		BIT(3)
+#define XILINX_FRMBUF_CTRL_FLUSH		BIT(5)
+#define XILINX_FRMBUF_CTRL_FLUSH_DONE		BIT(6)
+#define XILINX_FRMBUF_CTRL_AUTO_RESTART		BIT(7)
+#define XILINX_FRMBUF_GIE_EN			BIT(0)
+
+/* Interrupt Status and Control */
+#define XILINX_FRMBUF_IE_AP_DONE		BIT(0)
+#define XILINX_FRMBUF_IE_AP_READY		BIT(1)
+
+#define XILINX_FRMBUF_ISR_AP_DONE_IRQ		BIT(0)
+#define XILINX_FRMBUF_ISR_AP_READY_IRQ		BIT(1)
+
+#define XILINX_FRMBUF_ISR_ALL_IRQ_MASK	\
+		(XILINX_FRMBUF_ISR_AP_DONE_IRQ | \
+		XILINX_FRMBUF_ISR_AP_READY_IRQ)
+
+/* Video Format Register Settings */
+#define XILINX_FRMBUF_FMT_RGBX8			10
+#define XILINX_FRMBUF_FMT_YUVX8			11
+#define XILINX_FRMBUF_FMT_YUYV8			12
+#define XILINX_FRMBUF_FMT_RGBA8			13
+#define XILINX_FRMBUF_FMT_YUVA8			14
+#define XILINX_FRMBUF_FMT_RGBX10		15
+#define XILINX_FRMBUF_FMT_YUVX10		16
+#define XILINX_FRMBUF_FMT_Y_UV8			18
+#define XILINX_FRMBUF_FMT_Y_UV8_420		19
+#define XILINX_FRMBUF_FMT_RGB8			20
+#define XILINX_FRMBUF_FMT_YUV8			21
+#define XILINX_FRMBUF_FMT_Y_UV10		22
+#define XILINX_FRMBUF_FMT_Y_UV10_420		23
+#define XILINX_FRMBUF_FMT_Y8			24
+#define XILINX_FRMBUF_FMT_Y10			25
+#define XILINX_FRMBUF_FMT_BGRA8			26
+#define XILINX_FRMBUF_FMT_BGRX8			27
+#define XILINX_FRMBUF_FMT_UYVY8			28
+#define XILINX_FRMBUF_FMT_BGR8			29
+#define XILINX_FRMBUF_FMT_RGBX12		30
+#define XILINX_FRMBUF_FMT_RGB16			35
+
+/* FID Register */
+#define XILINX_FRMBUF_FID_MASK			BIT(0)
+
+#define XILINX_FRMBUF_ALIGN_MUL			8
+
+#define WAIT_FOR_FLUSH_DONE			25
+
+/* Pixels per clock property flag */
+#define XILINX_PPC_PROP				BIT(0)
+#define XILINX_FLUSH_PROP			BIT(1)
+#define XILINX_FID_PROP				BIT(2)
+#define XILINX_CLK_PROP				BIT(3)
+
+#define XILINX_FRMBUF_MAX_HEIGHT		(4320)
+#define XILINX_FRMBUF_MIN_HEIGHT		(64)
+#define XILINX_FRMBUF_MAX_WIDTH			(8192)
+#define XILINX_FRMBUF_MIN_WIDTH			(64)
+
+/**
+ * struct xilinx_frmbuf_desc_hw - Hardware Descriptor
+ * @luma_plane_addr: Luma or packed plane buffer address
+ * @chroma_plane_addr: Chroma plane buffer address
+ * @vsize: Vertical Size
+ * @hsize: Horizontal Size
+ * @stride: Number of bytes between the first
+ *	    pixels of each horizontal line
+ */
+struct xilinx_frmbuf_desc_hw {
+	dma_addr_t luma_plane_addr;
+	dma_addr_t chroma_plane_addr;
+	u32 vsize;
+	u32 hsize;
+	u32 stride;
+};
+
+/**
+ * struct xilinx_frmbuf_tx_descriptor - Per Transaction structure
+ * @async_tx: Async transaction descriptor
+ * @hw: Hardware descriptor
+ * @node: Node in the channel descriptors list
+ * @fid: Field ID of buffer
+ * @earlycb: Whether the callback should be called when in staged state
+ */
+struct xilinx_frmbuf_tx_descriptor {
+	struct dma_async_tx_descriptor async_tx;
+	struct xilinx_frmbuf_desc_hw hw;
+	struct list_head node;
+	u32 fid;
+	u32 earlycb;
+};
+
+/**
+ * struct xilinx_frmbuf_chan - Driver specific dma channel structure
+ * @xdev: Driver specific device structure
+ * @lock: Descriptor operation lock
+ * @chan_node: Member of a list of framebuffer channel instances
+ * @pending_list: Descriptors waiting
+ * @done_list: Complete descriptors
+ * @staged_desc: Next buffer to be programmed
+ * @active_desc: Currently active buffer being read/written to
+ * @common: DMA common channel
+ * @dev: The dma device
+ * @write_addr: callback that will write dma addresses to IP (32 or 64 bit)
+ * @irq: Channel IRQ
+ * @direction: Transfer direction
+ * @idle: Channel idle state
+ * @tasklet: Cleanup work after irq
+ * @vid_fmt: Reference to currently assigned video format description
+ * @hw_fid: FID enabled in hardware flag
+ * @mode: Select operation mode
+ */
+struct xilinx_frmbuf_chan {
+	struct xilinx_frmbuf_device *xdev;
+	/* Descriptor operation lock */
+	spinlock_t lock;
+	struct list_head chan_node;
+	struct list_head pending_list;
+	struct list_head done_list;
+	struct xilinx_frmbuf_tx_descriptor *staged_desc;
+	struct xilinx_frmbuf_tx_descriptor *active_desc;
+	struct dma_chan common;
+	struct device *dev;
+	void (*write_addr)(struct xilinx_frmbuf_chan *chan, u32 reg,
+			   dma_addr_t value);
+	int irq;
+	enum dma_transfer_direction direction;
+	bool idle;
+	struct tasklet_struct tasklet;
+	const struct xilinx_frmbuf_format_desc *vid_fmt;
+	bool hw_fid;
+	enum operation_mode mode;
+};
+
+/**
+ * struct xilinx_frmbuf_format_desc - lookup table to match fourcc to format
+ * @dts_name: Device tree name for this entry.
+ * @id: Format ID
+ * @bpw: Bits of pixel data + padding in a 32-bit word (luma plane for semi-pl)
+ * @ppw: Number of pixels represented in a 32-bit word (luma plane for semi-pl)
+ * @num_planes: Expected number of plane buffers in framebuffer for this format
+ * @drm_fmt: DRM video framework equivalent fourcc code
+ * @v4l2_fmt: Video 4 Linux framework equivalent fourcc code
+ * @fmt_bitmask: Flag identifying this format in device-specific "enabled"
+ *	bitmap
+ */
+struct xilinx_frmbuf_format_desc {
+	const char *dts_name;
+	u32 id;
+	u32 bpw;
+	u32 ppw;
+	u32 num_planes;
+	u32 drm_fmt;
+	u32 v4l2_fmt;
+	u32 fmt_bitmask;
+};
+
+static LIST_HEAD(frmbuf_chan_list);
+static DEFINE_MUTEX(frmbuf_chan_list_lock);
+
+static const struct xilinx_frmbuf_format_desc xilinx_frmbuf_formats[] = {
+	{
+		.dts_name = "xbgr8888",
+		.id = XILINX_FRMBUF_FMT_RGBX8,
+		.bpw = 32,
+		.ppw = 1,
+		.num_planes = 1,
+		.drm_fmt = DRM_FORMAT_XBGR8888,
+		.v4l2_fmt = V4L2_PIX_FMT_BGRX32,
+		.fmt_bitmask = BIT(0),
+	},
+	{
+		.dts_name = "xbgr2101010",
+		.id = XILINX_FRMBUF_FMT_RGBX10,
+		.bpw = 32,
+		.ppw = 1,
+		.num_planes = 1,
+		.drm_fmt = DRM_FORMAT_XBGR2101010,
+		.v4l2_fmt = V4L2_PIX_FMT_XBGR30,
+		.fmt_bitmask = BIT(1),
+	},
+	{
+		.dts_name = "xrgb8888",
+		.id = XILINX_FRMBUF_FMT_BGRX8,
+		.bpw = 32,
+		.ppw = 1,
+		.num_planes = 1,
+		.drm_fmt = DRM_FORMAT_XRGB8888,
+		.v4l2_fmt = V4L2_PIX_FMT_XBGR32,
+		.fmt_bitmask = BIT(2),
+	},
+	{
+		.dts_name = "xvuy8888",
+		.id = XILINX_FRMBUF_FMT_YUVX8,
+		.bpw = 32,
+		.ppw = 1,
+		.num_planes = 1,
+		.drm_fmt = DRM_FORMAT_XVUY8888,
+		.v4l2_fmt = V4L2_PIX_FMT_XVUY32,
+		.fmt_bitmask = BIT(5),
+	},
+	{
+		.dts_name = "vuy888",
+		.id = XILINX_FRMBUF_FMT_YUV8,
+		.bpw = 24,
+		.ppw = 1,
+		.num_planes = 1,
+		.drm_fmt = DRM_FORMAT_VUY888,
+		.v4l2_fmt = V4L2_PIX_FMT_VUY24,
+		.fmt_bitmask = BIT(6),
+	},
+	{
+		.dts_name = "yuvx2101010",
+		.id = XILINX_FRMBUF_FMT_YUVX10,
+		.bpw = 32,
+		.ppw = 1,
+		.num_planes = 1,
+		.drm_fmt = DRM_FORMAT_XVUY2101010,
+		.v4l2_fmt = V4L2_PIX_FMT_XVUY10,
+		.fmt_bitmask = BIT(7),
+	},
+	{
+		.dts_name = "yuyv",
+		.id = XILINX_FRMBUF_FMT_YUYV8,
+		.bpw = 32,
+		.ppw = 2,
+		.num_planes = 1,
+		.drm_fmt = DRM_FORMAT_YUYV,
+		.v4l2_fmt = V4L2_PIX_FMT_YUYV,
+		.fmt_bitmask = BIT(8),
+	},
+	{
+		.dts_name = "uyvy",
+		.id = XILINX_FRMBUF_FMT_UYVY8,
+		.bpw = 32,
+		.ppw = 2,
+		.num_planes = 1,
+		.drm_fmt = DRM_FORMAT_UYVY,
+		.v4l2_fmt = V4L2_PIX_FMT_UYVY,
+		.fmt_bitmask = BIT(9),
+	},
+	{
+		.dts_name = "nv16",
+		.id = XILINX_FRMBUF_FMT_Y_UV8,
+		.bpw = 32,
+		.ppw = 4,
+		.num_planes = 2,
+		.drm_fmt = DRM_FORMAT_NV16,
+		.v4l2_fmt = V4L2_PIX_FMT_NV16M,
+		.fmt_bitmask = BIT(11),
+	},
+	{
+		.dts_name = "nv16",
+		.id = XILINX_FRMBUF_FMT_Y_UV8,
+		.bpw = 32,
+		.ppw = 4,
+		.num_planes = 2,
+		.drm_fmt = 0,
+		.v4l2_fmt = V4L2_PIX_FMT_NV16,
+		.fmt_bitmask = BIT(11),
+	},
+	{
+		.dts_name = "nv12",
+		.id = XILINX_FRMBUF_FMT_Y_UV8_420,
+		.bpw = 32,
+		.ppw = 4,
+		.num_planes = 2,
+		.drm_fmt = DRM_FORMAT_NV12,
+		.v4l2_fmt = V4L2_PIX_FMT_NV12M,
+		.fmt_bitmask = BIT(12),
+	},
+	{
+		.dts_name = "nv12",
+		.id = XILINX_FRMBUF_FMT_Y_UV8_420,
+		.bpw = 32,
+		.ppw = 4,
+		.num_planes = 2,
+		.drm_fmt = 0,
+		.v4l2_fmt = V4L2_PIX_FMT_NV12,
+		.fmt_bitmask = BIT(12),
+	},
+	{
+		.dts_name = "xv15",
+		.id = XILINX_FRMBUF_FMT_Y_UV10_420,
+		.bpw = 32,
+		.ppw = 3,
+		.num_planes = 2,
+		.drm_fmt = DRM_FORMAT_XV15,
+		.v4l2_fmt = V4L2_PIX_FMT_XV15M,
+		.fmt_bitmask = BIT(13),
+	},
+	{
+		.dts_name = "xv15",
+		.id = XILINX_FRMBUF_FMT_Y_UV10_420,
+		.bpw = 32,
+		.ppw = 3,
+		.num_planes = 2,
+		.drm_fmt = 0,
+		.v4l2_fmt = V4L2_PIX_FMT_XV15,
+		.fmt_bitmask = BIT(13),
+	},
+	{
+		.dts_name = "xv20",
+		.id = XILINX_FRMBUF_FMT_Y_UV10,
+		.bpw = 32,
+		.ppw = 3,
+		.num_planes = 2,
+		.drm_fmt = DRM_FORMAT_XV20,
+		.v4l2_fmt = V4L2_PIX_FMT_XV20M,
+		.fmt_bitmask = BIT(14),
+	},
+	{
+		.dts_name = "xv20",
+		.id = XILINX_FRMBUF_FMT_Y_UV10,
+		.bpw = 32,
+		.ppw = 3,
+		.num_planes = 2,
+		.drm_fmt = 0,
+		.v4l2_fmt = V4L2_PIX_FMT_XV20,
+		.fmt_bitmask = BIT(14),
+	},
+	{
+		.dts_name = "bgr888",
+		.id = XILINX_FRMBUF_FMT_RGB8,
+		.bpw = 24,
+		.ppw = 1,
+		.num_planes = 1,
+		.drm_fmt = DRM_FORMAT_BGR888,
+		.v4l2_fmt = V4L2_PIX_FMT_RGB24,
+		.fmt_bitmask = BIT(15),
+	},
+	{
+		.dts_name = "y8",
+		.id = XILINX_FRMBUF_FMT_Y8,
+		.bpw = 32,
+		.ppw = 4,
+		.num_planes = 1,
+		.drm_fmt = DRM_FORMAT_Y8,
+		.v4l2_fmt = V4L2_PIX_FMT_GREY,
+		.fmt_bitmask = BIT(16),
+	},
+	{
+		.dts_name = "y10",
+		.id = XILINX_FRMBUF_FMT_Y10,
+		.bpw = 32,
+		.ppw = 3,
+		.num_planes = 1,
+		.drm_fmt = DRM_FORMAT_Y10,
+		.v4l2_fmt = V4L2_PIX_FMT_XY10,
+		.fmt_bitmask = BIT(17),
+	},
+	{
+		.dts_name = "rgb888",
+		.id = XILINX_FRMBUF_FMT_BGR8,
+		.bpw = 24,
+		.ppw = 1,
+		.num_planes = 1,
+		.drm_fmt = DRM_FORMAT_RGB888,
+		.v4l2_fmt = V4L2_PIX_FMT_BGR24,
+		.fmt_bitmask = BIT(18),
+	},
+	{
+		.dts_name = "abgr8888",
+		.id = XILINX_FRMBUF_FMT_RGBA8,
+		.bpw = 32,
+		.ppw = 1,
+		.num_planes = 1,
+		.drm_fmt = DRM_FORMAT_ABGR8888,
+		.v4l2_fmt = 0,
+		.fmt_bitmask = BIT(19),
+	},
+	{
+		.dts_name = "argb8888",
+		.id = XILINX_FRMBUF_FMT_BGRA8,
+		.bpw = 32,
+		.ppw = 1,
+		.num_planes = 1,
+		.drm_fmt = DRM_FORMAT_ARGB8888,
+		.v4l2_fmt = 0,
+		.fmt_bitmask = BIT(20),
+	},
+	{
+		.dts_name = "avuy8888",
+		.id = XILINX_FRMBUF_FMT_YUVA8,
+		.bpw = 32,
+		.ppw = 1,
+		.num_planes = 1,
+		.drm_fmt = DRM_FORMAT_AVUY,
+		.v4l2_fmt = 0,
+		.fmt_bitmask = BIT(21),
+	},
+	{
+		.dts_name = "xbgr4121212",
+		.id = XILINX_FRMBUF_FMT_RGBX12,
+		.bpw = 40,
+		.ppw = 1,
+		.num_planes = 1,
+		.v4l2_fmt = V4L2_PIX_FMT_XBGR40,
+		.fmt_bitmask = BIT(22),
+	},
+	{
+		.dts_name = "rgb16",
+		.id = XILINX_FRMBUF_FMT_RGB16,
+		.bpw = 48,
+		.ppw = 1,
+		.num_planes = 1,
+		.v4l2_fmt = V4L2_PIX_FMT_BGR48,
+		.fmt_bitmask = BIT(23),
+	},
+};
+
+/**
+ * struct xilinx_frmbuf_feature - dt or IP property structure
+ * @direction: dma transfer mode and direction
+ * @flags: Bitmask of properties enabled in IP or dt
+ */
+struct xilinx_frmbuf_feature {
+	enum dma_transfer_direction direction;
+	u32 flags;
+};
+
+/**
+ * struct xilinx_frmbuf_device - dma device structure
+ * @regs: I/O mapped base address
+ * @dev: Device Structure
+ * @common: DMA device structure
+ * @chan: Driver specific dma channel
+ * @rst_gpio: GPIO reset
+ * @enabled_vid_fmts: Bitmask of video formats enabled in hardware
+ * @drm_memory_fmts: Array of supported DRM fourcc codes
+ * @drm_fmt_cnt: Count of supported DRM fourcc codes
+ * @v4l2_memory_fmts: Array of supported V4L2 fourcc codes
+ * @v4l2_fmt_cnt: Count of supported V4L2 fourcc codes
+ * @cfg: Pointer to Framebuffer Feature config struct
+ * @max_width: Maximum pixel width supported in IP.
+ * @max_height: Maximum number of lines supported in IP.
+ * @ap_clk: Video core clock
+ */
+struct xilinx_frmbuf_device {
+	void __iomem *regs;
+	struct device *dev;
+	struct dma_device common;
+	struct xilinx_frmbuf_chan chan;
+	struct gpio_desc *rst_gpio;
+	u32 enabled_vid_fmts;
+	u32 drm_memory_fmts[ARRAY_SIZE(xilinx_frmbuf_formats)];
+	u32 drm_fmt_cnt;
+	u32 v4l2_memory_fmts[ARRAY_SIZE(xilinx_frmbuf_formats)];
+	u32 v4l2_fmt_cnt;
+	const struct xilinx_frmbuf_feature *cfg;
+	u32 max_width;
+	u32 max_height;
+	struct clk *ap_clk;
+};
+
+static const struct xilinx_frmbuf_feature xlnx_fbwr_cfg_v20 = {
+	.direction = DMA_DEV_TO_MEM,
+};
+
+static const struct xilinx_frmbuf_feature xlnx_fbwr_cfg_v21 = {
+	.direction = DMA_DEV_TO_MEM,
+	.flags = XILINX_PPC_PROP | XILINX_FLUSH_PROP
+		| XILINX_FID_PROP | XILINX_CLK_PROP,
+};
+
+static const struct xilinx_frmbuf_feature xlnx_fbrd_cfg_v20 = {
+	.direction = DMA_MEM_TO_DEV,
+};
+
+static const struct xilinx_frmbuf_feature xlnx_fbrd_cfg_v21 = {
+	.direction = DMA_MEM_TO_DEV,
+	.flags = XILINX_PPC_PROP | XILINX_FLUSH_PROP
+		| XILINX_FID_PROP | XILINX_CLK_PROP,
+};
+
+static const struct of_device_id xilinx_frmbuf_of_ids[] = {
+	{ .compatible = "xlnx,axi-frmbuf-wr-v2",
+		.data = (void *)&xlnx_fbwr_cfg_v20},
+	{ .compatible = "xlnx,axi-frmbuf-wr-v2.1",
+		.data = (void *)&xlnx_fbwr_cfg_v21},
+	{ .compatible = "xlnx,axi-frmbuf-rd-v2",
+		.data = (void *)&xlnx_fbrd_cfg_v20},
+	{ .compatible = "xlnx,axi-frmbuf-rd-v2.1",
+		.data = (void *)&xlnx_fbrd_cfg_v21},
+	{/* end of list */}
+};
+
+/******************************PROTOTYPES*************************************/
+#define to_xilinx_chan(chan) \
+	container_of(chan, struct xilinx_frmbuf_chan, common)
+#define to_dma_tx_descriptor(tx) \
+	container_of(tx, struct xilinx_frmbuf_tx_descriptor, async_tx)
+
+static inline u32 frmbuf_read(struct xilinx_frmbuf_chan *chan, u32 reg)
+{
+	return ioread32(chan->xdev->regs + reg);
+}
+
+static inline void frmbuf_write(struct xilinx_frmbuf_chan *chan, u32 reg,
+				u32 value)
+{
+	iowrite32(value, chan->xdev->regs + reg);
+}
+
+static inline void frmbuf_writeq(struct xilinx_frmbuf_chan *chan, u32 reg,
+				 u64 value)
+{
+	iowrite32(lower_32_bits(value), chan->xdev->regs + reg);
+	iowrite32(upper_32_bits(value), chan->xdev->regs + reg + 4);
+}
+
+static void writeq_addr(struct xilinx_frmbuf_chan *chan, u32 reg,
+			dma_addr_t addr)
+{
+	frmbuf_writeq(chan, reg, (u64)addr);
+}
+
+static void write_addr(struct xilinx_frmbuf_chan *chan, u32 reg,
+		       dma_addr_t addr)
+{
+	frmbuf_write(chan, reg, addr);
+}
+
+static inline void frmbuf_clr(struct xilinx_frmbuf_chan *chan, u32 reg,
+			      u32 clr)
+{
+	frmbuf_write(chan, reg, frmbuf_read(chan, reg) & ~clr);
+}
+
+static inline void frmbuf_set(struct xilinx_frmbuf_chan *chan, u32 reg,
+			      u32 set)
+{
+	frmbuf_write(chan, reg, frmbuf_read(chan, reg) | set);
+}
+
+static void frmbuf_init_format_array(struct xilinx_frmbuf_device *xdev)
+{
+	u32 i, cnt;
+
+	for (i = 0; i < ARRAY_SIZE(xilinx_frmbuf_formats); i++) {
+		if (!(xdev->enabled_vid_fmts &
+		      xilinx_frmbuf_formats[i].fmt_bitmask))
+			continue;
+
+		if (xilinx_frmbuf_formats[i].drm_fmt) {
+			cnt = xdev->drm_fmt_cnt++;
+			xdev->drm_memory_fmts[cnt] =
+				xilinx_frmbuf_formats[i].drm_fmt;
+		}
+
+		if (xilinx_frmbuf_formats[i].v4l2_fmt) {
+			cnt = xdev->v4l2_fmt_cnt++;
+			xdev->v4l2_memory_fmts[cnt] =
+				xilinx_frmbuf_formats[i].v4l2_fmt;
+		}
+	}
+}
+
+static struct xilinx_frmbuf_chan *frmbuf_find_chan(struct dma_chan *chan)
+{
+	struct xilinx_frmbuf_chan *xil_chan;
+	bool found_xchan = false;
+
+	mutex_lock(&frmbuf_chan_list_lock);
+	list_for_each_entry(xil_chan, &frmbuf_chan_list, chan_node) {
+		if (chan == &xil_chan->common) {
+			found_xchan = true;
+			break;
+		}
+	}
+	mutex_unlock(&frmbuf_chan_list_lock);
+
+	if (!found_xchan) {
+		dev_dbg(chan->device->dev,
+			"dma chan not a Video Framebuffer channel instance\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	return xil_chan;
+}
+
+static struct xilinx_frmbuf_device *frmbuf_find_dev(struct dma_chan *chan)
+{
+	struct xilinx_frmbuf_chan *xchan, *temp;
+	struct xilinx_frmbuf_device *xdev;
+	bool is_frmbuf_chan = false;
+
+	list_for_each_entry_safe(xchan, temp, &frmbuf_chan_list, chan_node) {
+		if (chan == &xchan->common)
+			is_frmbuf_chan = true;
+	}
+
+	if (!is_frmbuf_chan)
+		return ERR_PTR(-ENODEV);
+
+	xchan = to_xilinx_chan(chan);
+	xdev = container_of(xchan, struct xilinx_frmbuf_device, chan);
+
+	return xdev;
+}
+
+static int frmbuf_verify_format(struct dma_chan *chan, u32 fourcc, u32 type)
+{
+	struct xilinx_frmbuf_chan *xil_chan = to_xilinx_chan(chan);
+	u32 i, sz = ARRAY_SIZE(xilinx_frmbuf_formats);
+
+	for (i = 0; i < sz; i++) {
+		if ((type == XDMA_DRM &&
+		     fourcc != xilinx_frmbuf_formats[i].drm_fmt) ||
+		   (type == XDMA_V4L2 &&
+		    fourcc != xilinx_frmbuf_formats[i].v4l2_fmt))
+			continue;
+
+		if (!(xilinx_frmbuf_formats[i].fmt_bitmask &
+		      xil_chan->xdev->enabled_vid_fmts))
+			return -EINVAL;
+
+		/*
+		 * The Alpha color formats are supported in Framebuffer Read
+		 * IP only as corresponding DRM formats.
+		 */
+		if (type == XDMA_DRM &&
+		    (xilinx_frmbuf_formats[i].drm_fmt == DRM_FORMAT_ABGR8888 ||
+		     xilinx_frmbuf_formats[i].drm_fmt == DRM_FORMAT_ARGB8888 ||
+		     xilinx_frmbuf_formats[i].drm_fmt == DRM_FORMAT_AVUY) &&
+		    xil_chan->direction != DMA_MEM_TO_DEV)
+			return -EINVAL;
+
+		xil_chan->vid_fmt = &xilinx_frmbuf_formats[i];
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static void xilinx_xdma_set_config(struct dma_chan *chan, u32 fourcc, u32 type)
+{
+	struct xilinx_frmbuf_chan *xil_chan;
+	int ret;
+
+	xil_chan = frmbuf_find_chan(chan);
+	if (IS_ERR(xil_chan))
+		return;
+	ret = frmbuf_verify_format(chan, fourcc, type);
+	if (ret == -EINVAL) {
+		dev_err(chan->device->dev,
+			"Framebuffer not configured for fourcc 0x%x\n",
+			fourcc);
+		return;
+	}
+}
+
+void xilinx_xdma_set_mode(struct dma_chan *chan, enum operation_mode
+			  mode)
+{
+	struct xilinx_frmbuf_chan *xil_chan;
+
+	xil_chan = frmbuf_find_chan(chan);
+	if (IS_ERR(xil_chan))
+		return;
+
+	xil_chan->mode = mode;
+
+	return;
+
+} EXPORT_SYMBOL_GPL(xilinx_xdma_set_mode);
+
+void xilinx_xdma_drm_config(struct dma_chan *chan, u32 drm_fourcc)
+{
+	xilinx_xdma_set_config(chan, drm_fourcc, XDMA_DRM);
+
+} EXPORT_SYMBOL_GPL(xilinx_xdma_drm_config);
+
+void xilinx_xdma_v4l2_config(struct dma_chan *chan, u32 v4l2_fourcc)
+{
+	xilinx_xdma_set_config(chan, v4l2_fourcc, XDMA_V4L2);
+
+} EXPORT_SYMBOL_GPL(xilinx_xdma_v4l2_config);
+
+int xilinx_xdma_get_drm_vid_fmts(struct dma_chan *chan, u32 *fmt_cnt,
+				 u32 **fmts)
+{
+	struct xilinx_frmbuf_device *xdev;
+
+	xdev = frmbuf_find_dev(chan);
+
+	if (IS_ERR(xdev))
+		return PTR_ERR(xdev);
+
+	*fmt_cnt = xdev->drm_fmt_cnt;
+	*fmts = xdev->drm_memory_fmts;
+
+	return 0;
+}
+EXPORT_SYMBOL(xilinx_xdma_get_drm_vid_fmts);
+
+int xilinx_xdma_get_v4l2_vid_fmts(struct dma_chan *chan, u32 *fmt_cnt,
+				  u32 **fmts)
+{
+	struct xilinx_frmbuf_device *xdev;
+
+	xdev = frmbuf_find_dev(chan);
+
+	if (IS_ERR(xdev))
+		return PTR_ERR(xdev);
+
+	*fmt_cnt = xdev->v4l2_fmt_cnt;
+	*fmts = xdev->v4l2_memory_fmts;
+
+	return 0;
+}
+EXPORT_SYMBOL(xilinx_xdma_get_v4l2_vid_fmts);
+
+int xilinx_xdma_get_fid(struct dma_chan *chan,
+			struct dma_async_tx_descriptor *async_tx, u32 *fid)
+{
+	struct xilinx_frmbuf_device *xdev;
+	struct xilinx_frmbuf_tx_descriptor *desc;
+
+	xdev = frmbuf_find_dev(chan);
+	if (IS_ERR(xdev))
+		return PTR_ERR(xdev);
+
+	if (!async_tx || !fid)
+		return -EINVAL;
+
+	if (xdev->chan.direction != DMA_DEV_TO_MEM)
+		return -EINVAL;
+
+	desc = to_dma_tx_descriptor(async_tx);
+	if (!desc)
+		return -EINVAL;
+
+	*fid = desc->fid;
+	return 0;
+}
+EXPORT_SYMBOL(xilinx_xdma_get_fid);
+
+int xilinx_xdma_set_fid(struct dma_chan *chan,
+			struct dma_async_tx_descriptor *async_tx, u32 fid)
+{
+	struct xilinx_frmbuf_device *xdev;
+	struct xilinx_frmbuf_tx_descriptor *desc;
+
+	if (fid > 1 || !async_tx)
+		return -EINVAL;
+
+	xdev = frmbuf_find_dev(chan);
+	if (IS_ERR(xdev))
+		return PTR_ERR(xdev);
+
+	if (xdev->chan.direction != DMA_MEM_TO_DEV)
+		return -EINVAL;
+
+	desc = to_dma_tx_descriptor(async_tx);
+	if (!desc)
+		return -EINVAL;
+
+	desc->fid = fid;
+	return 0;
+}
+EXPORT_SYMBOL(xilinx_xdma_set_fid);
+
+int xilinx_xdma_get_earlycb(struct dma_chan *chan,
+			    struct dma_async_tx_descriptor *async_tx,
+			    u32 *earlycb)
+{
+	struct xilinx_frmbuf_device *xdev;
+	struct xilinx_frmbuf_tx_descriptor *desc;
+
+	xdev = frmbuf_find_dev(chan);
+	if (IS_ERR(xdev))
+		return PTR_ERR(xdev);
+
+	if (!async_tx || !earlycb)
+		return -EINVAL;
+
+	desc = to_dma_tx_descriptor(async_tx);
+	if (!desc)
+		return -EINVAL;
+
+	*earlycb = desc->earlycb;
+	return 0;
+}
+EXPORT_SYMBOL(xilinx_xdma_get_earlycb);
+
+int xilinx_xdma_set_earlycb(struct dma_chan *chan,
+			    struct dma_async_tx_descriptor *async_tx,
+			    u32 earlycb)
+{
+	struct xilinx_frmbuf_device *xdev;
+	struct xilinx_frmbuf_tx_descriptor *desc;
+
+	if (!async_tx)
+		return -EINVAL;
+
+	xdev = frmbuf_find_dev(chan);
+	if (IS_ERR(xdev))
+		return PTR_ERR(xdev);
+
+	desc = to_dma_tx_descriptor(async_tx);
+	if (!desc)
+		return -EINVAL;
+
+	desc->earlycb = earlycb;
+	return 0;
+}
+EXPORT_SYMBOL(xilinx_xdma_set_earlycb);
+
+/**
+ * of_dma_xilinx_xlate - Translation function
+ * @dma_spec: Pointer to DMA specifier as found in the device tree
+ * @ofdma: Pointer to DMA controller data
+ *
+ * Return: DMA channel pointer on success or error code on error
+ */
+static struct dma_chan *of_dma_xilinx_xlate(struct of_phandle_args *dma_spec,
+					    struct of_dma *ofdma)
+{
+	struct xilinx_frmbuf_device *xdev = ofdma->of_dma_data;
+
+	return dma_get_slave_channel(&xdev->chan.common);
+}
+
+/* -----------------------------------------------------------------------------
+ * Descriptors alloc and free
+ */
+
+/**
+ * xilinx_frmbuf_tx_descriptor - Allocate transaction descriptor
+ * @chan: Driver specific dma channel
+ *
+ * Return: The allocated descriptor on success and NULL on failure.
+ */
+static struct xilinx_frmbuf_tx_descriptor *
+xilinx_frmbuf_alloc_tx_descriptor(struct xilinx_frmbuf_chan *chan)
+{
+	struct xilinx_frmbuf_tx_descriptor *desc;
+
+	desc = kzalloc(sizeof(*desc), GFP_KERNEL);
+	if (!desc)
+		return NULL;
+
+	return desc;
+}
+
+/**
+ * xilinx_frmbuf_free_desc_list - Free descriptors list
+ * @chan: Driver specific dma channel
+ * @list: List to parse and delete the descriptor
+ */
+static void xilinx_frmbuf_free_desc_list(struct xilinx_frmbuf_chan *chan,
+					 struct list_head *list)
+{
+	struct xilinx_frmbuf_tx_descriptor *desc, *next;
+
+	list_for_each_entry_safe(desc, next, list, node) {
+		list_del(&desc->node);
+		kfree(desc);
+	}
+}
+
+/**
+ * xilinx_frmbuf_free_descriptors - Free channel descriptors
+ * @chan: Driver specific dma channel
+ */
+static void xilinx_frmbuf_free_descriptors(struct xilinx_frmbuf_chan *chan)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&chan->lock, flags);
+
+	xilinx_frmbuf_free_desc_list(chan, &chan->pending_list);
+	xilinx_frmbuf_free_desc_list(chan, &chan->done_list);
+	kfree(chan->active_desc);
+	kfree(chan->staged_desc);
+
+	chan->staged_desc = NULL;
+	chan->active_desc = NULL;
+	INIT_LIST_HEAD(&chan->pending_list);
+	INIT_LIST_HEAD(&chan->done_list);
+
+	spin_unlock_irqrestore(&chan->lock, flags);
+}
+
+/**
+ * xilinx_frmbuf_free_chan_resources - Free channel resources
+ * @dchan: DMA channel
+ */
+static void xilinx_frmbuf_free_chan_resources(struct dma_chan *dchan)
+{
+	struct xilinx_frmbuf_chan *chan = to_xilinx_chan(dchan);
+
+	xilinx_frmbuf_free_descriptors(chan);
+}
+
+/**
+ * xilinx_frmbuf_chan_desc_cleanup - Clean channel descriptors
+ * @chan: Driver specific dma channel
+ */
+static void xilinx_frmbuf_chan_desc_cleanup(struct xilinx_frmbuf_chan *chan)
+{
+	struct xilinx_frmbuf_tx_descriptor *desc, *next;
+	unsigned long flags;
+
+	spin_lock_irqsave(&chan->lock, flags);
+
+	list_for_each_entry_safe(desc, next, &chan->done_list, node) {
+		dma_async_tx_callback callback;
+		void *callback_param;
+
+		list_del(&desc->node);
+
+		/* Run the link descriptor callback function */
+		callback = desc->async_tx.callback;
+		callback_param = desc->async_tx.callback_param;
+		if (callback) {
+			spin_unlock_irqrestore(&chan->lock, flags);
+			callback(callback_param);
+			spin_lock_irqsave(&chan->lock, flags);
+		}
+
+		/* Run any dependencies, then free the descriptor */
+		dma_run_dependencies(&desc->async_tx);
+		kfree(desc);
+	}
+
+	spin_unlock_irqrestore(&chan->lock, flags);
+}
+
+/**
+ * xilinx_frmbuf_do_tasklet - Schedule completion tasklet
+ * @data: Pointer to the Xilinx frmbuf channel structure
+ */
+static void xilinx_frmbuf_do_tasklet(unsigned long data)
+{
+	struct xilinx_frmbuf_chan *chan = (struct xilinx_frmbuf_chan *)data;
+
+	xilinx_frmbuf_chan_desc_cleanup(chan);
+}
+
+/**
+ * xilinx_frmbuf_alloc_chan_resources - Allocate channel resources
+ * @dchan: DMA channel
+ *
+ * Return: '0' on success and failure value on error
+ */
+static int xilinx_frmbuf_alloc_chan_resources(struct dma_chan *dchan)
+{
+	dma_cookie_init(dchan);
+
+	return 0;
+}
+
+/**
+ * xilinx_frmbuf_tx_status - Get frmbuf transaction status
+ * @dchan: DMA channel
+ * @cookie: Transaction identifier
+ * @txstate: Transaction state
+ *
+ * Return: fmrbuf transaction status
+ */
+static enum dma_status xilinx_frmbuf_tx_status(struct dma_chan *dchan,
+					       dma_cookie_t cookie,
+					       struct dma_tx_state *txstate)
+{
+	return dma_cookie_status(dchan, cookie, txstate);
+}
+
+/**
+ * xilinx_frmbuf_halt - Halt frmbuf channel
+ * @chan: Driver specific dma channel
+ */
+static void xilinx_frmbuf_halt(struct xilinx_frmbuf_chan *chan)
+{
+	frmbuf_clr(chan, XILINX_FRMBUF_CTRL_OFFSET,
+			XILINX_FRMBUF_CTRL_AP_START |
+			chan->mode);
+	chan->idle = true;
+}
+
+/**
+ * xilinx_frmbuf_start - Start dma channel
+ * @chan: Driver specific dma channel
+ */
+static void xilinx_frmbuf_start(struct xilinx_frmbuf_chan *chan)
+{
+	frmbuf_set(chan, XILINX_FRMBUF_CTRL_OFFSET,
+			XILINX_FRMBUF_CTRL_AP_START |
+			chan->mode);
+	chan->idle = false;
+}
+
+/**
+ * xilinx_frmbuf_complete_descriptor - Mark the active descriptor as complete
+ * This function is invoked with spinlock held
+ * @chan : xilinx frmbuf channel
+ *
+ * CONTEXT: hardirq
+ */
+static void xilinx_frmbuf_complete_descriptor(struct xilinx_frmbuf_chan *chan)
+{
+	struct xilinx_frmbuf_tx_descriptor *desc = chan->active_desc;
+
+	/*
+	 * In case of frame buffer write, read the fid register
+	 * and associate it with descriptor
+	 */
+	if (chan->direction == DMA_DEV_TO_MEM && chan->hw_fid)
+		desc->fid = frmbuf_read(chan, XILINX_FRMBUF_FID_OFFSET) &
+			    XILINX_FRMBUF_FID_MASK;
+
+	dma_cookie_complete(&desc->async_tx);
+	list_add_tail(&desc->node, &chan->done_list);
+}
+
+/**
+ * xilinx_frmbuf_start_transfer - Starts frmbuf transfer
+ * @chan: Driver specific channel struct pointer
+ */
+static void xilinx_frmbuf_start_transfer(struct xilinx_frmbuf_chan *chan)
+{
+	struct xilinx_frmbuf_tx_descriptor *desc;
+
+	if (!chan->idle)
+		return;
+
+	if (chan->staged_desc) {
+		chan->active_desc = chan->staged_desc;
+		chan->staged_desc = NULL;
+	}
+
+	if (list_empty(&chan->pending_list))
+		return;
+
+	desc = list_first_entry(&chan->pending_list,
+				struct xilinx_frmbuf_tx_descriptor,
+				node);
+
+	if (desc->earlycb == EARLY_CALLBACK_START_DESC) {
+		dma_async_tx_callback callback;
+		void *callback_param;
+
+		callback = desc->async_tx.callback;
+		callback_param = desc->async_tx.callback_param;
+		if (callback) {
+			callback(callback_param);
+			desc->async_tx.callback = NULL;
+			chan->active_desc = desc;
+		}
+	}
+
+	/* Start the transfer */
+	chan->write_addr(chan, XILINX_FRMBUF_ADDR_OFFSET,
+			 desc->hw.luma_plane_addr);
+	chan->write_addr(chan, XILINX_FRMBUF_ADDR2_OFFSET,
+			 desc->hw.chroma_plane_addr);
+
+	/* HW expects these parameters to be same for one transaction */
+	frmbuf_write(chan, XILINX_FRMBUF_WIDTH_OFFSET, desc->hw.hsize);
+	frmbuf_write(chan, XILINX_FRMBUF_STRIDE_OFFSET, desc->hw.stride);
+	frmbuf_write(chan, XILINX_FRMBUF_HEIGHT_OFFSET, desc->hw.vsize);
+	frmbuf_write(chan, XILINX_FRMBUF_FMT_OFFSET, chan->vid_fmt->id);
+
+	/* If it is framebuffer read IP set the FID */
+	if (chan->direction == DMA_MEM_TO_DEV && chan->hw_fid)
+		frmbuf_write(chan, XILINX_FRMBUF_FID_OFFSET, desc->fid);
+
+	/* Start the hardware */
+	xilinx_frmbuf_start(chan);
+	list_del(&desc->node);
+
+	/* No staging descriptor required when auto restart is disabled */
+	if (chan->mode == AUTO_RESTART)
+		chan->staged_desc = desc;
+	else
+		chan->active_desc = desc;
+}
+
+/**
+ * xilinx_frmbuf_issue_pending - Issue pending transactions
+ * @dchan: DMA channel
+ */
+static void xilinx_frmbuf_issue_pending(struct dma_chan *dchan)
+{
+	struct xilinx_frmbuf_chan *chan = to_xilinx_chan(dchan);
+	unsigned long flags;
+
+	spin_lock_irqsave(&chan->lock, flags);
+	xilinx_frmbuf_start_transfer(chan);
+	spin_unlock_irqrestore(&chan->lock, flags);
+}
+
+/**
+ * xilinx_frmbuf_reset - Reset frmbuf channel
+ * @chan: Driver specific dma channel
+ */
+static void xilinx_frmbuf_reset(struct xilinx_frmbuf_chan *chan)
+{
+	/* reset ip */
+	gpiod_set_value(chan->xdev->rst_gpio, 1);
+	udelay(1);
+	gpiod_set_value(chan->xdev->rst_gpio, 0);
+}
+
+/**
+ * xilinx_frmbuf_chan_reset - Reset frmbuf channel and enable interrupts
+ * @chan: Driver specific frmbuf channel
+ */
+static void xilinx_frmbuf_chan_reset(struct xilinx_frmbuf_chan *chan)
+{
+	xilinx_frmbuf_reset(chan);
+	frmbuf_write(chan, XILINX_FRMBUF_IE_OFFSET, XILINX_FRMBUF_IE_AP_DONE);
+	frmbuf_write(chan, XILINX_FRMBUF_GIE_OFFSET, XILINX_FRMBUF_GIE_EN);
+}
+
+/**
+ * xilinx_frmbuf_irq_handler - frmbuf Interrupt handler
+ * @irq: IRQ number
+ * @data: Pointer to the Xilinx frmbuf channel structure
+ *
+ * Return: IRQ_HANDLED/IRQ_NONE
+ */
+static irqreturn_t xilinx_frmbuf_irq_handler(int irq, void *data)
+{
+	struct xilinx_frmbuf_chan *chan = data;
+	u32 status;
+	dma_async_tx_callback callback = NULL;
+	void *callback_param;
+	struct xilinx_frmbuf_tx_descriptor *desc;
+
+	status = frmbuf_read(chan, XILINX_FRMBUF_ISR_OFFSET);
+	if (!(status & XILINX_FRMBUF_ISR_ALL_IRQ_MASK))
+		return IRQ_NONE;
+
+	frmbuf_write(chan, XILINX_FRMBUF_ISR_OFFSET,
+		     status & XILINX_FRMBUF_ISR_ALL_IRQ_MASK);
+
+	/* Check if callback function needs to be called early */
+	desc = chan->staged_desc;
+	if (desc && desc->earlycb == EARLY_CALLBACK) {
+		callback = desc->async_tx.callback;
+		callback_param = desc->async_tx.callback_param;
+		if (callback) {
+			callback(callback_param);
+			desc->async_tx.callback = NULL;
+		}
+	}
+
+	if (status & XILINX_FRMBUF_ISR_AP_DONE_IRQ) {
+		spin_lock(&chan->lock);
+		chan->idle = true;
+		if (chan->active_desc) {
+			xilinx_frmbuf_complete_descriptor(chan);
+			chan->active_desc = NULL;
+		}
+		xilinx_frmbuf_start_transfer(chan);
+		spin_unlock(&chan->lock);
+	}
+
+	tasklet_schedule(&chan->tasklet);
+	return IRQ_HANDLED;
+}
+
+/**
+ * xilinx_frmbuf_tx_submit - Submit DMA transaction
+ * @tx: Async transaction descriptor
+ *
+ * Return: cookie value on success and failure value on error
+ */
+static dma_cookie_t xilinx_frmbuf_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+	struct xilinx_frmbuf_tx_descriptor *desc = to_dma_tx_descriptor(tx);
+	struct xilinx_frmbuf_chan *chan = to_xilinx_chan(tx->chan);
+	dma_cookie_t cookie;
+	unsigned long flags;
+
+	spin_lock_irqsave(&chan->lock, flags);
+	cookie = dma_cookie_assign(tx);
+	list_add_tail(&desc->node, &chan->pending_list);
+	spin_unlock_irqrestore(&chan->lock, flags);
+
+	return cookie;
+}
+
+/**
+ * xilinx_frmbuf_dma_prep_interleaved - prepare a descriptor for a
+ *	DMA_SLAVE transaction
+ * @dchan: DMA channel
+ * @xt: Interleaved template pointer
+ * @flags: transfer ack flags
+ *
+ * Return: Async transaction descriptor on success and NULL on failure
+ */
+static struct dma_async_tx_descriptor *
+xilinx_frmbuf_dma_prep_interleaved(struct dma_chan *dchan,
+				   struct dma_interleaved_template *xt,
+				   unsigned long flags)
+{
+	struct xilinx_frmbuf_chan *chan = to_xilinx_chan(dchan);
+	struct xilinx_frmbuf_tx_descriptor *desc;
+	struct xilinx_frmbuf_desc_hw *hw;
+	u32 vsize, hsize;
+
+	if (chan->direction != xt->dir || !chan->vid_fmt)
+		goto error;
+
+	if (!xt->numf || !xt->sgl[0].size)
+		goto error;
+
+	if (xt->frame_size != chan->vid_fmt->num_planes)
+		goto error;
+
+	vsize = xt->numf;
+	hsize = (xt->sgl[0].size * chan->vid_fmt->ppw * 8) /
+		 chan->vid_fmt->bpw;
+	/* hsize calc should not have resulted in an odd number */
+	if (hsize & 1)
+		hsize++;
+
+	if (vsize > chan->xdev->max_height || hsize > chan->xdev->max_width) {
+		dev_dbg(chan->xdev->dev,
+			"vsize %d max vsize %d hsize %d max hsize %d\n",
+			vsize, chan->xdev->max_height, hsize,
+			chan->xdev->max_width);
+		dev_err(chan->xdev->dev, "Requested size not supported!\n");
+		goto error;
+	}
+
+	desc = xilinx_frmbuf_alloc_tx_descriptor(chan);
+	if (!desc)
+		return NULL;
+
+	dma_async_tx_descriptor_init(&desc->async_tx, &chan->common);
+	desc->async_tx.tx_submit = xilinx_frmbuf_tx_submit;
+	async_tx_ack(&desc->async_tx);
+
+	hw = &desc->hw;
+	hw->vsize = xt->numf;
+	hw->stride = xt->sgl[0].icg + xt->sgl[0].size;
+	hw->hsize = (xt->sgl[0].size * chan->vid_fmt->ppw * 8) /
+		     chan->vid_fmt->bpw;
+
+	/* hsize calc should not have resulted in an odd number */
+	if (hw->hsize & 1)
+		hw->hsize++;
+
+	if (chan->direction == DMA_MEM_TO_DEV) {
+		hw->luma_plane_addr = xt->src_start;
+		if (xt->frame_size == 2)
+			hw->chroma_plane_addr =
+				xt->src_start +
+				xt->numf * hw->stride +
+				xt->sgl[0].src_icg;
+	} else {
+		hw->luma_plane_addr = xt->dst_start;
+		if (xt->frame_size == 2)
+			hw->chroma_plane_addr =
+				xt->dst_start +
+				xt->numf * hw->stride +
+				xt->sgl[0].dst_icg;
+	}
+
+	return &desc->async_tx;
+
+error:
+	dev_err(chan->xdev->dev,
+		"Invalid dma template or missing dma video fmt config\n");
+	return NULL;
+}
+
+/**
+ * xilinx_frmbuf_terminate_all - Halt the channel and free descriptors
+ * @dchan: Driver specific dma channel pointer
+ *
+ * Return: 0
+ */
+static int xilinx_frmbuf_terminate_all(struct dma_chan *dchan)
+{
+	struct xilinx_frmbuf_chan *chan = to_xilinx_chan(dchan);
+
+	xilinx_frmbuf_halt(chan);
+	xilinx_frmbuf_free_descriptors(chan);
+	/* worst case frame-to-frame boundary; ensure frame output complete */
+	msleep(50);
+
+	if (chan->xdev->cfg->flags & XILINX_FLUSH_PROP) {
+		u8 count;
+
+		/*
+		 * Flush the framebuffer FIFO and
+		 * wait for max 50ms for flush done
+		 */
+		frmbuf_set(chan, XILINX_FRMBUF_CTRL_OFFSET,
+			   XILINX_FRMBUF_CTRL_FLUSH);
+		for (count = WAIT_FOR_FLUSH_DONE; count > 0; count--) {
+			if (frmbuf_read(chan, XILINX_FRMBUF_CTRL_OFFSET) &
+					XILINX_FRMBUF_CTRL_FLUSH_DONE)
+				break;
+			usleep_range(2000, 2100);
+		}
+
+		if (!count)
+			dev_err(chan->xdev->dev, "Framebuffer Flush not done!\n");
+	}
+
+	xilinx_frmbuf_chan_reset(chan);
+
+	return 0;
+}
+
+/**
+ * xilinx_frmbuf_synchronize - kill tasklet to stop further descr processing
+ * @dchan: Driver specific dma channel pointer
+ */
+static void xilinx_frmbuf_synchronize(struct dma_chan *dchan)
+{
+	struct xilinx_frmbuf_chan *chan = to_xilinx_chan(dchan);
+
+	tasklet_kill(&chan->tasklet);
+}
+
+/* -----------------------------------------------------------------------------
+ * Probe and remove
+ */
+
+/**
+ * xilinx_frmbuf_chan_remove - Per Channel remove function
+ * @chan: Driver specific dma channel
+ */
+static void xilinx_frmbuf_chan_remove(struct xilinx_frmbuf_chan *chan)
+{
+	/* Disable all interrupts */
+	frmbuf_clr(chan, XILINX_FRMBUF_IE_OFFSET,
+		   XILINX_FRMBUF_ISR_ALL_IRQ_MASK);
+
+	tasklet_kill(&chan->tasklet);
+	list_del(&chan->common.device_node);
+
+	mutex_lock(&frmbuf_chan_list_lock);
+	list_del(&chan->chan_node);
+	mutex_unlock(&frmbuf_chan_list_lock);
+}
+
+/**
+ * xilinx_frmbuf_chan_probe - Per Channel Probing
+ * It get channel features from the device tree entry and
+ * initialize special channel handling routines
+ *
+ * @xdev: Driver specific device structure
+ * @node: Device node
+ *
+ * Return: '0' on success and failure value on error
+ */
+static int xilinx_frmbuf_chan_probe(struct xilinx_frmbuf_device *xdev,
+				    struct device_node *node)
+{
+	struct xilinx_frmbuf_chan *chan;
+	int err;
+	u32 dma_addr_size = 0;
+
+	chan = &xdev->chan;
+
+	chan->dev = xdev->dev;
+	chan->xdev = xdev;
+	chan->idle = true;
+	chan->mode = AUTO_RESTART;
+
+	err = of_property_read_u32(node, "xlnx,dma-addr-width",
+				   &dma_addr_size);
+	if (err || (dma_addr_size != 32 && dma_addr_size != 64)) {
+		dev_err(xdev->dev, "missing or invalid addr width dts prop\n");
+		return err;
+	}
+
+	if (dma_addr_size == 64 && sizeof(dma_addr_t) == sizeof(u64))
+		chan->write_addr = writeq_addr;
+	else
+		chan->write_addr = write_addr;
+
+	if (xdev->cfg->flags & XILINX_FID_PROP)
+		chan->hw_fid = of_property_read_bool(node, "xlnx,fid");
+
+	spin_lock_init(&chan->lock);
+	INIT_LIST_HEAD(&chan->pending_list);
+	INIT_LIST_HEAD(&chan->done_list);
+
+	chan->irq = irq_of_parse_and_map(node, 0);
+	err = devm_request_irq(xdev->dev, chan->irq, xilinx_frmbuf_irq_handler,
+			       IRQF_SHARED, "xilinx_framebuffer", chan);
+
+	if (err) {
+		dev_err(xdev->dev, "unable to request IRQ %d\n", chan->irq);
+		return err;
+	}
+
+	tasklet_init(&chan->tasklet, xilinx_frmbuf_do_tasklet,
+		     (unsigned long)chan);
+
+	/*
+	 * Initialize the DMA channel and add it to the DMA engine channels
+	 * list.
+	 */
+	chan->common.device = &xdev->common;
+
+	list_add_tail(&chan->common.device_node, &xdev->common.channels);
+
+	mutex_lock(&frmbuf_chan_list_lock);
+	list_add_tail(&chan->chan_node, &frmbuf_chan_list);
+	mutex_unlock(&frmbuf_chan_list_lock);
+
+	xilinx_frmbuf_chan_reset(chan);
+
+	return 0;
+}
+
+/**
+ * xilinx_frmbuf_probe - Driver probe function
+ * @pdev: Pointer to the platform_device structure
+ *
+ * Return: '0' on success and failure value on error
+ */
+static int xilinx_frmbuf_probe(struct platform_device *pdev)
+{
+	struct device_node *node = pdev->dev.of_node;
+	struct xilinx_frmbuf_device *xdev;
+	struct resource *io;
+	enum dma_transfer_direction dma_dir;
+	const struct of_device_id *match;
+	int err;
+	u32 i, j, align, ppc;
+	int hw_vid_fmt_cnt;
+	const char *vid_fmts[ARRAY_SIZE(xilinx_frmbuf_formats)];
+
+	xdev = devm_kzalloc(&pdev->dev, sizeof(*xdev), GFP_KERNEL);
+	if (!xdev)
+		return -ENOMEM;
+
+	xdev->dev = &pdev->dev;
+
+	match = of_match_node(xilinx_frmbuf_of_ids, node);
+	if (!match)
+		return -ENODEV;
+
+	xdev->cfg = match->data;
+
+	dma_dir = (enum dma_transfer_direction)xdev->cfg->direction;
+
+	if (xdev->cfg->flags & XILINX_CLK_PROP) {
+		xdev->ap_clk = devm_clk_get(xdev->dev, "ap_clk");
+		if (IS_ERR(xdev->ap_clk)) {
+			err = PTR_ERR(xdev->ap_clk);
+			dev_err(xdev->dev, "failed to get ap_clk (%d)\n", err);
+			return err;
+		}
+	} else {
+		dev_info(xdev->dev, "assuming clock is enabled!\n");
+	}
+
+	xdev->rst_gpio = devm_gpiod_get(&pdev->dev, "reset",
+					GPIOD_OUT_HIGH);
+	if (IS_ERR(xdev->rst_gpio)) {
+		err = PTR_ERR(xdev->rst_gpio);
+		if (err == -EPROBE_DEFER)
+			dev_info(&pdev->dev,
+				 "Probe deferred due to GPIO reset defer\n");
+		else
+			dev_err(&pdev->dev,
+				"Unable to locate reset property in dt\n");
+		return err;
+	}
+
+	gpiod_set_value_cansleep(xdev->rst_gpio, 0x0);
+
+	io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	xdev->regs = devm_ioremap_resource(&pdev->dev, io);
+	if (IS_ERR(xdev->regs))
+		return PTR_ERR(xdev->regs);
+
+	err = of_property_read_u32(node, "xlnx,max-height", &xdev->max_height);
+	if (err < 0) {
+		dev_err(xdev->dev, "xlnx,max-height is missing!");
+		return -EINVAL;
+	} else if (xdev->max_height > XILINX_FRMBUF_MAX_HEIGHT ||
+		   xdev->max_height < XILINX_FRMBUF_MIN_HEIGHT) {
+		dev_err(&pdev->dev, "Invalid height in dt");
+		return -EINVAL;
+	}
+
+	err = of_property_read_u32(node, "xlnx,max-width", &xdev->max_width);
+	if (err < 0) {
+		dev_err(xdev->dev, "xlnx,max-width is missing!");
+		return -EINVAL;
+	} else if (xdev->max_width > XILINX_FRMBUF_MAX_WIDTH ||
+		   xdev->max_width < XILINX_FRMBUF_MIN_WIDTH) {
+		dev_err(&pdev->dev, "Invalid width in dt");
+		return -EINVAL;
+	}
+
+	/* Initialize the DMA engine */
+	if (xdev->cfg->flags & XILINX_PPC_PROP) {
+		err = of_property_read_u32(node, "xlnx,pixels-per-clock", &ppc);
+		if (err || (ppc != 1 && ppc != 2 && ppc != 4 && ppc != 8)) {
+			dev_err(&pdev->dev, "missing or invalid pixels per clock dts prop\n");
+			return err;
+		}
+
+		err = of_property_read_u32(node, "xlnx,dma-align", &align);
+		if (err)
+			align = ppc * XILINX_FRMBUF_ALIGN_MUL;
+
+		if (align < (ppc * XILINX_FRMBUF_ALIGN_MUL) ||
+		    ffs(align) != fls(align)) {
+			dev_err(&pdev->dev, "invalid dma align dts prop\n");
+			return -EINVAL;
+		}
+	} else {
+		align = 16;
+	}
+
+	xdev->common.copy_align = (enum dmaengine_alignment)(fls(align) - 1);
+	xdev->common.dev = &pdev->dev;
+
+	if (xdev->cfg->flags & XILINX_CLK_PROP) {
+		err = clk_prepare_enable(xdev->ap_clk);
+		if (err) {
+			dev_err(&pdev->dev, " failed to enable ap_clk (%d)\n",
+				err);
+			return err;
+		}
+	}
+
+	INIT_LIST_HEAD(&xdev->common.channels);
+	dma_cap_set(DMA_SLAVE, xdev->common.cap_mask);
+	dma_cap_set(DMA_PRIVATE, xdev->common.cap_mask);
+
+	/* Initialize the channels */
+	err = xilinx_frmbuf_chan_probe(xdev, node);
+	if (err < 0)
+		goto disable_clk;
+
+	xdev->chan.direction = dma_dir;
+
+	if (xdev->chan.direction == DMA_DEV_TO_MEM) {
+		xdev->common.directions = BIT(DMA_DEV_TO_MEM);
+		dev_info(&pdev->dev, "Xilinx AXI frmbuf DMA_DEV_TO_MEM\n");
+	} else if (xdev->chan.direction == DMA_MEM_TO_DEV) {
+		xdev->common.directions = BIT(DMA_MEM_TO_DEV);
+		dev_info(&pdev->dev, "Xilinx AXI frmbuf DMA_MEM_TO_DEV\n");
+	} else {
+		err = -EINVAL;
+		goto remove_chan;
+	}
+
+	/* read supported video formats and update internal table */
+	hw_vid_fmt_cnt = of_property_count_strings(node, "xlnx,vid-formats");
+
+	err = of_property_read_string_array(node, "xlnx,vid-formats",
+					    vid_fmts, hw_vid_fmt_cnt);
+	if (err < 0) {
+		dev_err(&pdev->dev,
+			"Missing or invalid xlnx,vid-formats dts prop\n");
+		goto remove_chan;
+	}
+
+	for (i = 0; i < hw_vid_fmt_cnt; i++) {
+		const char *vid_fmt_name = vid_fmts[i];
+
+		for (j = 0; j < ARRAY_SIZE(xilinx_frmbuf_formats); j++) {
+			const char *dts_name =
+				xilinx_frmbuf_formats[j].dts_name;
+
+			if (strcmp(vid_fmt_name, dts_name))
+				continue;
+
+			xdev->enabled_vid_fmts |=
+				xilinx_frmbuf_formats[j].fmt_bitmask;
+		}
+	}
+
+	/* Determine supported vid framework formats */
+	frmbuf_init_format_array(xdev);
+
+	xdev->common.device_alloc_chan_resources =
+				xilinx_frmbuf_alloc_chan_resources;
+	xdev->common.device_free_chan_resources =
+				xilinx_frmbuf_free_chan_resources;
+	xdev->common.device_prep_interleaved_dma =
+				xilinx_frmbuf_dma_prep_interleaved;
+	xdev->common.device_terminate_all = xilinx_frmbuf_terminate_all;
+	xdev->common.device_synchronize = xilinx_frmbuf_synchronize;
+	xdev->common.device_tx_status = xilinx_frmbuf_tx_status;
+	xdev->common.device_issue_pending = xilinx_frmbuf_issue_pending;
+
+	platform_set_drvdata(pdev, xdev);
+
+	/* Register the DMA engine with the core */
+	dma_async_device_register(&xdev->common);
+
+	err = of_dma_controller_register(node, of_dma_xilinx_xlate, xdev);
+	if (err < 0) {
+		dev_err(&pdev->dev, "Unable to register DMA to DT\n");
+		goto error;
+	}
+
+	dev_info(&pdev->dev, "Xilinx AXI FrameBuffer Engine Driver Probed!!\n");
+
+	return 0;
+error:
+	dma_async_device_unregister(&xdev->common);
+remove_chan:
+	xilinx_frmbuf_chan_remove(&xdev->chan);
+disable_clk:
+	clk_disable_unprepare(xdev->ap_clk);
+	return err;
+}
+
+/**
+ * xilinx_frmbuf_remove - Driver remove function
+ * @pdev: Pointer to the platform_device structure
+ *
+ * Return: Always '0'
+ */
+static int xilinx_frmbuf_remove(struct platform_device *pdev)
+{
+	struct xilinx_frmbuf_device *xdev = platform_get_drvdata(pdev);
+
+	of_dma_controller_free(pdev->dev.of_node);
+
+	dma_async_device_unregister(&xdev->common);
+	xilinx_frmbuf_chan_remove(&xdev->chan);
+	clk_disable_unprepare(xdev->ap_clk);
+
+	return 0;
+}
+
+MODULE_DEVICE_TABLE(of, xilinx_frmbuf_of_ids);
+
+static struct platform_driver xilinx_frmbuf_driver = {
+	.driver = {
+		.name = "xilinx-frmbuf",
+		.of_match_table = xilinx_frmbuf_of_ids,
+	},
+	.probe = xilinx_frmbuf_probe,
+	.remove = xilinx_frmbuf_remove,
+};
+
+module_platform_driver(xilinx_frmbuf_driver);
+
+MODULE_AUTHOR("Xilinx, Inc.");
+MODULE_DESCRIPTION("Xilinx Framebuffer driver");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/xilinx/xilinx_ps_pcie.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/xilinx/xilinx_ps_pcie.h
@@ -0,0 +1,44 @@
+/*
+ * Xilinx PS PCIe DMA Engine platform header file
+ *
+ * Copyright (C) 2010-2017 Xilinx, Inc. All rights reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation
+ */
+
+#ifndef __XILINX_PS_PCIE_H
+#define __XILINX_PS_PCIE_H
+
+#include <linux/delay.h>
+#include <linux/dma-direction.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/irqreturn.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mempool.h>
+#include <linux/of.h>
+#include <linux/pci.h>
+#include <linux/property.h>
+#include <linux/platform_device.h>
+#include <linux/timer.h>
+#include <linux/dma/xilinx_ps_pcie_dma.h>
+
+/**
+ * dma_platform_driver_register - This will be invoked by module init
+ *
+ * Return: returns status of platform_driver_register
+ */
+int dma_platform_driver_register(void);
+/**
+ * dma_platform_driver_unregister - This will be invoked by module exit
+ *
+ * Return: returns void after unregustering platform driver
+ */
+void dma_platform_driver_unregister(void);
+
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/xilinx/xilinx_ps_pcie_dma_client.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/xilinx/xilinx_ps_pcie_dma_client.c
@@ -0,0 +1,1402 @@
+/*
+ * XILINX PS PCIe DMA Engine test module
+ *
+ * Copyright (C) 2017 Xilinx, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/cdev.h>
+#include <linux/dma-direction.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/kdev_t.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci_ids.h>
+#include <linux/pagemap.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/dma/xilinx_ps_pcie_dma.h>
+
+#include "../dmaengine.h"
+
+#define DRV_MODULE_NAME		"ps_pcie_dma_client"
+
+#define DMA_SCRATCH0_REG_OFFSET   (0x50)
+#define DMA_SCRATCH1_REG_OFFSET   (0x54)
+#define DMA_AXI_INTR_ASSRT_REG_OFFSET   (0x74)
+
+#define DMA_SW_INTR_ASSRT_BIT      BIT(3)
+
+#define DMA_BAR_NUMBER 0
+
+#define CHAR_DRIVER_NAME               "ps_pcie_dmachan"
+
+#define PIO_CHAR_DRIVER_NAME           "ps_pcie_pio"
+#define EP_TRANSLATION_CHECK            0xCCCCCCCC
+
+#define PIO_MEMORY_BAR_NUMBER            2
+
+#define XPIO_CLIENT_MAGIC 'P'
+#define IOCTL_EP_CHECK_TRANSLATION     _IO(XPIO_CLIENT_MAGIC, 0x01)
+
+#define XPS_PCIE_DMA_CLIENT_MAGIC 'S'
+
+#define IGET_ASYNC_TRANSFERINFO   _IO(XPS_PCIE_DMA_CLIENT_MAGIC, 0x01)
+#define ISET_ASYNC_TRANSFERINFO   _IO(XPS_PCIE_DMA_CLIENT_MAGIC, 0x02)
+
+#define DMA_TRANSACTION_SUCCESSFUL 1
+#define DMA_TRANSACTION_FAILURE    0
+
+#define MAX_LIST 1024
+
+struct dma_transfer_info {
+	char __user *buff_address;
+	unsigned int buff_size;
+	loff_t    offset;
+	enum dma_data_direction direction;
+};
+
+struct buff_info {
+	bool status;
+	unsigned int buff_size;
+	char __user *buff_address;
+};
+
+struct usrbuff_info {
+	struct buff_info buff_list[MAX_LIST];
+	unsigned int expected;
+};
+
+enum pio_status {
+	PIO_SUPPORTED = 0,
+	PIO_NOT_SUPPORTED
+};
+
+enum dma_transfer_mode {
+	MEMORY_MAPPED = 0,
+	STREAMING
+};
+
+struct dma_deviceproperties {
+	u16     pci_vendorid;
+	u16     pci_deviceid;
+	u16     board_number;
+	enum pio_status pio_transfers;
+	enum dma_transfer_mode mode;
+	enum dma_data_direction direction[MAX_ALLOWED_CHANNELS_IN_HW];
+};
+
+struct xlnx_completed_info {
+	struct list_head clist;
+	struct buff_info buffer;
+};
+
+struct xlnx_ps_pcie_dma_client_channel {
+	struct device *dev;
+	struct dma_chan *chan;
+	struct ps_pcie_dma_channel_match match;
+	enum dma_data_direction direction;
+	enum dma_transfer_mode mode;
+	struct xlnx_completed_info completed;
+	spinlock_t channel_lock; /* Lock to serialize transfers on channel */
+};
+
+struct xlnx_ps_pcie_dma_client_device {
+	struct dma_deviceproperties *properties;
+
+	struct xlnx_ps_pcie_dma_client_channel
+		pcie_dma_chan[MAX_ALLOWED_CHANNELS_IN_HW];
+
+	dev_t char_device;
+	struct cdev xps_pcie_chardev;
+	struct device *chardev[MAX_ALLOWED_CHANNELS_IN_HW];
+
+	dev_t pio_char_device;
+	struct cdev xpio_char_dev;
+	struct device *xpio_char_device;
+	struct mutex  pio_chardev_mutex; /* Exclusive access to ioctl */
+	struct completion trans_cmpltn;
+	u32 pio_translation_size;
+
+	struct list_head dev_node;
+};
+
+struct xlnx_ps_pcie_dma_asynchronous_transaction {
+	dma_cookie_t cookie;
+	struct page **cache_pages;
+	unsigned int num_pages;
+	struct sg_table *sg;
+	struct xlnx_ps_pcie_dma_client_channel *chan;
+	struct xlnx_completed_info *buffer_info;
+	struct dma_async_tx_descriptor **txd;
+};
+
+static struct class *g_ps_pcie_dma_client_class; /* global device class */
+static struct list_head g_ps_pcie_dma_client_list;
+
+/*
+ * Keep adding to this list to interact with multiple DMA devices
+ */
+static struct dma_deviceproperties g_dma_deviceproperties_list[] = {
+		{
+			.pci_vendorid = PCI_VENDOR_ID_XILINX,
+			.pci_deviceid = ZYNQMP_DMA_DEVID,
+			.board_number = 0,
+			.pio_transfers = PIO_SUPPORTED,
+			.mode          = MEMORY_MAPPED,
+			/* Make sure the channel direction is same
+			 * as what is configured in DMA device
+			 */
+			.direction = {DMA_TO_DEVICE, DMA_FROM_DEVICE,
+					DMA_TO_DEVICE, DMA_FROM_DEVICE}
+		}
+};
+
+/**
+ * ps_pcie_dma_sync_transfer_cbk - Callback handler for Synchronous transfers.
+ * Handles both S2C and C2S transfer call backs.
+ * Indicates to blocked applications that DMA transfers are complete
+ *
+ * @data: Callback parameter
+ *
+ * Return: void
+ */
+static void ps_pcie_dma_sync_transfer_cbk(void *data)
+{
+	struct completion *compl = (struct completion *)data;
+
+	if (compl)
+		complete(compl);
+}
+
+/**
+ * initiate_sync_transfer - Programs both Source Q
+ * and Destination Q of channel after setting up sg lists and transaction
+ * specific data. This functions waits until transaction completion is notified
+ *
+ * @channel: Pointer to the PS PCIe DMA channel structure
+ * @buffer: User land virtual address containing data to be sent or received
+ * @length: Length of user land buffer
+ * @f_offset: AXI domain address to which data pointed by user buffer has to
+ *	      be sent/received from
+ * @direction: Transfer of data direction
+ *
+ * Return: 0 on success and non zero value for failure
+ */
+static ssize_t initiate_sync_transfer(
+			struct xlnx_ps_pcie_dma_client_channel *channel,
+			const char __user *buffer, size_t length,
+			loff_t *f_offset, enum dma_data_direction direction)
+{
+	int offset;
+	unsigned int alloc_pages;
+	unsigned long first, last, nents = 1;
+	struct page **cache_pages;
+	struct dma_chan *chan = NULL;
+	struct dma_device *device;
+	struct dma_async_tx_descriptor **txd = NULL;
+	dma_cookie_t cookie = 0;
+	enum dma_ctrl_flags flags = 0;
+	int err;
+	struct sg_table *sg;
+	enum dma_transfer_direction d_direction;
+	int i;
+	struct completion *cmpl_ptr;
+	enum dma_status status;
+	struct scatterlist *selem;
+	size_t elem_len = 0;
+
+	chan = channel->chan;
+	device = chan->device;
+
+	offset = offset_in_page(buffer);
+	first = ((unsigned long)buffer & PAGE_MASK) >> PAGE_SHIFT;
+	last = (((unsigned long)buffer + length - 1) & PAGE_MASK) >>
+		PAGE_SHIFT;
+	alloc_pages = (last - first) + 1;
+
+	cache_pages = devm_kzalloc(channel->dev,
+				   (alloc_pages * (sizeof(struct page *))),
+				   GFP_ATOMIC);
+	if (!cache_pages) {
+		dev_err(channel->dev,
+			"Unable to allocate memory for page table holder\n");
+		err = PTR_ERR(cache_pages);
+		goto err_out_cachepages_alloc;
+	}
+
+	err = get_user_pages_fast((unsigned long)buffer, alloc_pages,
+				  !(direction), cache_pages);
+	if (err <= 0) {
+		dev_err(channel->dev, "Unable to pin user pages\n");
+		err = PTR_ERR(cache_pages);
+		goto err_out_pin_pages;
+	} else if (err < alloc_pages) {
+		dev_err(channel->dev, "Only pinned few user pages %d\n", err);
+		err = PTR_ERR(cache_pages);
+		for (i = 0; i < err; i++)
+			put_page(cache_pages[i]);
+		goto err_out_pin_pages;
+	}
+
+	sg = devm_kzalloc(channel->dev, sizeof(struct sg_table), GFP_ATOMIC);
+	if (!sg) {
+		err = PTR_ERR(sg);
+		goto err_out_alloc_sg_table;
+	}
+
+	err = sg_alloc_table_from_pages(sg, cache_pages, alloc_pages, offset,
+					length, GFP_ATOMIC);
+	if (err < 0) {
+		dev_err(channel->dev, "Unable to create sg table\n");
+		goto err_out_sg_to_sgl;
+	}
+
+	err = dma_map_sg(channel->dev, sg->sgl, sg->nents, direction);
+	if (err == 0) {
+		dev_err(channel->dev, "Unable to map buffer to sg table\n");
+		err = PTR_ERR(sg);
+		goto err_out_dma_map_sg;
+	}
+
+	cmpl_ptr = devm_kzalloc(channel->dev, sizeof(struct completion),
+				GFP_ATOMIC);
+	if (!cmpl_ptr) {
+		err = PTR_ERR(cmpl_ptr);
+		goto err_out_cmpl_ptr;
+	}
+
+	init_completion(cmpl_ptr);
+
+	if (channel->mode == MEMORY_MAPPED)
+		nents = sg->nents;
+
+	txd = devm_kzalloc(channel->dev, sizeof(*txd)
+					* nents, GFP_ATOMIC);
+	if (!txd) {
+		err = PTR_ERR(txd);
+		goto err_out_cmpl_ptr;
+	}
+
+	if (channel->mode == MEMORY_MAPPED) {
+		for (i = 0, selem = (sg->sgl); i < sg->nents; i++,
+		     selem = sg_next(selem)) {
+			if ((i + 1) == sg->nents)
+				flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK;
+
+			if (direction == DMA_TO_DEVICE) {
+				txd[i] = device->device_prep_dma_memcpy(chan,
+					(dma_addr_t)(*f_offset) + elem_len,
+					selem->dma_address, selem->length,
+					flags);
+			} else {
+				txd[i] = device->device_prep_dma_memcpy(chan,
+					selem->dma_address,
+					(dma_addr_t)(*f_offset) + elem_len,
+					selem->length, flags);
+			}
+
+			elem_len += selem->length;
+
+			if (!txd[i]) {
+				err = PTR_ERR(txd[i]);
+				goto err_out_no_prep_sg_async_desc;
+			}
+		}
+	} else {
+		if (direction == DMA_TO_DEVICE)
+			d_direction = DMA_MEM_TO_DEV;
+		else
+			d_direction = DMA_DEV_TO_MEM;
+
+		flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
+
+		txd[0] = device->device_prep_slave_sg(chan, sg->sgl, sg->nents,
+						   d_direction, flags, NULL);
+		if (!txd[0]) {
+			err = PTR_ERR(txd[0]);
+			goto err_out_no_slave_sg_async_descriptor;
+		}
+	}
+
+	if (channel->mode == MEMORY_MAPPED) {
+		for (i = 0; i < sg->nents; i++) {
+			if ((i + 1) == sg->nents) {
+				txd[i]->callback =
+					ps_pcie_dma_sync_transfer_cbk;
+				txd[i]->callback_param = cmpl_ptr;
+			}
+
+			cookie = txd[i]->tx_submit(txd[i]);
+			if (dma_submit_error(cookie)) {
+				err = (int)cookie;
+				dev_err(channel->dev,
+					"Unable to submit transaction\n");
+				goto free_transaction;
+			}
+		}
+	} else {
+		txd[0]->callback = ps_pcie_dma_sync_transfer_cbk;
+		txd[0]->callback_param = cmpl_ptr;
+
+		cookie = txd[0]->tx_submit(txd[0]);
+		if (dma_submit_error(cookie)) {
+			err = (int)cookie;
+			dev_err(channel->dev,
+				"Unable to submit transaction\n");
+			goto free_transaction;
+		}
+	}
+
+	dma_async_issue_pending(chan);
+
+	wait_for_completion_killable(cmpl_ptr);
+
+	status = dmaengine_tx_status(chan, cookie, NULL);
+	if (status == DMA_COMPLETE)
+		err = length;
+	else
+		err = -1;
+
+	dma_unmap_sg(channel->dev, sg->sgl, sg->nents, direction);
+	devm_kfree(channel->dev, cmpl_ptr);
+	devm_kfree(channel->dev, txd);
+	sg_free_table(sg);
+	devm_kfree(channel->dev, sg);
+	for (i = 0; i < alloc_pages; i++)
+		put_page(cache_pages[i]);
+	devm_kfree(channel->dev, cache_pages);
+
+	return (ssize_t)err;
+
+free_transaction:
+err_out_no_prep_sg_async_desc:
+err_out_no_slave_sg_async_descriptor:
+	devm_kfree(channel->dev, cmpl_ptr);
+	devm_kfree(channel->dev, txd);
+err_out_cmpl_ptr:
+	dma_unmap_sg(channel->dev, sg->sgl, sg->nents, direction);
+err_out_dma_map_sg:
+	sg_free_table(sg);
+err_out_sg_to_sgl:
+	devm_kfree(channel->dev, sg);
+err_out_alloc_sg_table:
+	for (i = 0; i < alloc_pages; i++)
+		put_page(cache_pages[i]);
+err_out_pin_pages:
+	devm_kfree(channel->dev, cache_pages);
+err_out_cachepages_alloc:
+
+	return (ssize_t)err;
+}
+
+static ssize_t
+ps_pcie_dma_read(struct file *file,
+		 char __user *buffer,
+		 size_t length,
+		 loff_t *f_offset)
+{
+	struct xlnx_ps_pcie_dma_client_channel *chan;
+	ssize_t ret;
+
+	chan = file->private_data;
+
+	if (chan->direction != DMA_FROM_DEVICE) {
+		dev_err(chan->dev, "Invalid data direction for channel\n");
+		ret = -EINVAL;
+		goto c2s_err_direction;
+	}
+
+	ret = initiate_sync_transfer(chan, buffer, length, f_offset,
+				     DMA_FROM_DEVICE);
+
+	if (ret != length)
+		dev_dbg(chan->dev, "Read synchronous transfer unsuccessful\n");
+
+c2s_err_direction:
+	return ret;
+}
+
+static ssize_t
+ps_pcie_dma_write(struct file *file,
+		  const char __user *buffer,
+		  size_t length,
+		  loff_t *f_offset)
+{
+	struct xlnx_ps_pcie_dma_client_channel *chan;
+	ssize_t ret;
+
+	chan =   file->private_data;
+
+	if (chan->direction != DMA_TO_DEVICE) {
+		dev_err(chan->dev,
+			"Invalid data direction for channel\n");
+		ret = -EINVAL;
+		goto s2c_err_direction;
+	}
+
+	ret = initiate_sync_transfer(chan, buffer, length, f_offset,
+				     DMA_TO_DEVICE);
+
+	if (ret != length)
+		dev_dbg(chan->dev, "Write synchronous transfer unsuccessful\n");
+
+s2c_err_direction:
+	return ret;
+}
+
+static int ps_pcie_dma_open(struct inode *in, struct file *file)
+{
+	struct xlnx_ps_pcie_dma_client_device *xdev;
+	int minor_num = iminor(in);
+
+	xdev = container_of(in->i_cdev,
+			    struct xlnx_ps_pcie_dma_client_device,
+			    xps_pcie_chardev);
+
+	file->private_data = &xdev->pcie_dma_chan[minor_num];
+
+	return 0;
+}
+
+static int ps_pcie_dma_release(struct inode *in, struct file *filp)
+{
+	return 0;
+}
+
+static int update_completed_info(struct xlnx_ps_pcie_dma_client_channel *chan,
+				 struct usrbuff_info *usr_buff)
+{
+	int retval = 0;
+	unsigned int expected, count = 0;
+	struct xlnx_completed_info *entry;
+	struct xlnx_completed_info *next;
+
+	if (list_empty(&chan->completed.clist))
+		goto update_expected;
+
+	if (copy_from_user((void *)&expected,
+			   (void __user *)&usr_buff->expected,
+			   sizeof(unsigned int)) != 0) {
+		pr_err("Expected count copy failure\n");
+		retval = -ENXIO;
+		return retval;
+	}
+
+	if (expected > MAX_LIST) {
+		retval = -ENXIO;
+		return retval;
+	}
+
+	list_for_each_entry_safe(entry, next, &chan->completed.clist, clist) {
+		if (copy_to_user((void __user *)(usr_buff->buff_list + count),
+				 (void *)&entry->buffer,
+				 sizeof(struct buff_info)) != 0) {
+			pr_err("update user completed count copy failed\n");
+			retval = -ENXIO;
+			break;
+		}
+		count++;
+		spin_lock(&chan->channel_lock);
+		list_del(&entry->clist);
+		spin_unlock(&chan->channel_lock);
+		devm_kfree(chan->dev, entry);
+		if (count == expected)
+			break;
+	}
+
+update_expected:
+	if (copy_to_user((void __user *)&usr_buff->expected, (void *)&count,
+			 (sizeof(unsigned int))) != 0) {
+		pr_err("update user expected count copy failure\n");
+		retval = -ENXIO;
+	}
+
+	return retval;
+}
+
+/**
+ * ps_pcie_dma_async_transfer_cbk - Callback handler for Asynchronous transfers.
+ * Handles both S2C and C2S transfer call backs. Stores transaction information
+ * in a list for a user application to poll for this information
+ *
+ * @data: Callback parameter
+ *
+ * Return: void
+ */
+static void ps_pcie_dma_async_transfer_cbk(void *data)
+{
+	struct xlnx_ps_pcie_dma_asynchronous_transaction *trans =
+		(struct xlnx_ps_pcie_dma_asynchronous_transaction *)data;
+	enum dma_status status;
+	struct dma_tx_state state;
+	unsigned int i;
+
+	dma_unmap_sg(trans->chan->dev, trans->sg->sgl, trans->sg->nents,
+		     trans->chan->direction);
+	sg_free_table(trans->sg);
+	devm_kfree(trans->chan->dev, trans->sg);
+	devm_kfree(trans->chan->dev, trans->txd);
+	for (i = 0; i < trans->num_pages; i++)
+		put_page(trans->cache_pages[i]);
+	devm_kfree(trans->chan->dev, trans->cache_pages);
+
+	status = dmaengine_tx_status(trans->chan->chan, trans->cookie, &state);
+
+	if (status == DMA_COMPLETE)
+		trans->buffer_info->buffer.status = DMA_TRANSACTION_SUCCESSFUL;
+	else
+		trans->buffer_info->buffer.status = DMA_TRANSACTION_SUCCESSFUL;
+
+	spin_lock(&trans->chan->channel_lock);
+	list_add_tail(&trans->buffer_info->clist,
+		      &trans->chan->completed.clist);
+	spin_unlock(&trans->chan->channel_lock);
+	devm_kfree(trans->chan->dev, trans);
+}
+
+/**
+ * initiate_async_transfer - Programs both Source Q
+ * and Destination Q of channel after setting up sg lists and transaction
+ * specific data. This functions returns after setting up transfer
+ *
+ * @channel: Pointer to the PS PCIe DMA channel structure
+ * @buffer: User land virtual address containing data to be sent or received
+ * @length: Length of user land buffer
+ * @f_offset: AXI domain address to which data pointed by user buffer has to
+ *	      be sent/received from
+ * @direction: Transfer of data direction
+ *
+ * Return: 0 on success and non zero value for failure
+ */
+static int initiate_async_transfer(
+		struct xlnx_ps_pcie_dma_client_channel *channel,
+		char __user *buffer, size_t length, loff_t *f_offset,
+		enum dma_data_direction direction)
+{
+	int offset;
+	unsigned int alloc_pages;
+	unsigned long first, last, nents = 1;
+	struct page **cache_pages;
+	struct dma_chan *chan = NULL;
+	struct dma_device *device;
+	struct dma_async_tx_descriptor **txd = NULL;
+	dma_cookie_t cookie;
+	enum dma_ctrl_flags flags = 0;
+	struct xlnx_ps_pcie_dma_asynchronous_transaction *trans;
+	int err;
+	struct sg_table *sg;
+	enum dma_transfer_direction d_direction;
+	int i;
+	struct scatterlist *selem;
+	size_t elem_len = 0;
+
+	chan = channel->chan;
+	device = chan->device;
+
+	offset = offset_in_page(buffer);
+	first = ((unsigned long)buffer & PAGE_MASK) >> PAGE_SHIFT;
+	last = (((unsigned long)buffer + length - 1) & PAGE_MASK) >>
+		PAGE_SHIFT;
+	alloc_pages = (last - first) + 1;
+
+	cache_pages = devm_kzalloc(channel->dev,
+				   (alloc_pages * (sizeof(struct page *))),
+				   GFP_ATOMIC);
+	if (!cache_pages) {
+		err = PTR_ERR(cache_pages);
+		goto err_out_cachepages_alloc;
+	}
+
+	err = get_user_pages_fast((unsigned long)buffer, alloc_pages,
+				  !(direction), cache_pages);
+	if (err <= 0) {
+		dev_err(channel->dev, "Unable to pin user pages\n");
+		err = PTR_ERR(cache_pages);
+		goto err_out_pin_pages;
+	} else if (err < alloc_pages) {
+		dev_err(channel->dev, "Only pinned few user pages %d\n", err);
+		err = PTR_ERR(cache_pages);
+		for (i = 0; i < err; i++)
+			put_page(cache_pages[i]);
+		goto err_out_pin_pages;
+	}
+
+	sg = devm_kzalloc(channel->dev, sizeof(struct sg_table), GFP_ATOMIC);
+	if (!sg) {
+		err = PTR_ERR(sg);
+		goto err_out_alloc_sg_table;
+	}
+
+	err = sg_alloc_table_from_pages(sg, cache_pages, alloc_pages, offset,
+					length, GFP_ATOMIC);
+	if (err < 0) {
+		dev_err(channel->dev, "Unable to create sg table\n");
+		goto err_out_sg_to_sgl;
+	}
+
+	err = dma_map_sg(channel->dev, sg->sgl, sg->nents, direction);
+	if (err == 0) {
+		dev_err(channel->dev,
+			"Unable to map user buffer to sg table\n");
+		err = PTR_ERR(sg);
+		goto err_out_dma_map_sg;
+	}
+
+	trans = devm_kzalloc(channel->dev, sizeof(*trans), GFP_ATOMIC);
+	if (!trans) {
+		err = PTR_ERR(trans);
+		goto err_out_trans_ptr;
+	}
+
+	trans->buffer_info = devm_kzalloc(channel->dev,
+					  sizeof(struct xlnx_completed_info),
+					  GFP_ATOMIC);
+
+	if (!trans->buffer_info) {
+		err = PTR_ERR(trans->buffer_info);
+		goto err_out_no_completion_info;
+	}
+
+	if (channel->mode == MEMORY_MAPPED)
+		nents = sg->nents;
+
+	txd = devm_kzalloc(channel->dev,
+			   sizeof(*txd) * nents, GFP_ATOMIC);
+	if (!txd) {
+		err = PTR_ERR(txd);
+		goto err_out_no_completion_info;
+	}
+
+	trans->txd = txd;
+
+	if (channel->mode == MEMORY_MAPPED) {
+		for (i = 0, selem = (sg->sgl); i < sg->nents; i++,
+		     selem = sg_next(selem)) {
+			if ((i + 1) == sg->nents)
+				flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK;
+
+			if (direction == DMA_TO_DEVICE) {
+				txd[i] = device->device_prep_dma_memcpy(chan,
+					(dma_addr_t)(*f_offset) + elem_len,
+					selem->dma_address, selem->length,
+					flags);
+			} else {
+				txd[i] = device->device_prep_dma_memcpy(chan,
+					selem->dma_address,
+					(dma_addr_t)(*f_offset) + elem_len,
+					selem->length, flags);
+			}
+
+			elem_len += selem->length;
+
+			if (!txd[i]) {
+				err = PTR_ERR(txd[i]);
+				goto err_out_no_prep_sg_async_desc;
+			}
+		}
+	} else {
+		if (direction == DMA_TO_DEVICE)
+			d_direction = DMA_MEM_TO_DEV;
+		else
+			d_direction = DMA_DEV_TO_MEM;
+
+		flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
+
+		txd[0] = device->device_prep_slave_sg(chan, sg->sgl, sg->nents,
+						   d_direction, flags, NULL);
+		if (!txd[0]) {
+			err = PTR_ERR(txd[0]);
+			goto err_out_no_slave_sg_async_descriptor;
+		}
+	}
+
+	trans->buffer_info->buffer.buff_address = buffer;
+	trans->buffer_info->buffer.buff_size = length;
+	trans->cache_pages = cache_pages;
+	trans->num_pages   = alloc_pages;
+	trans->chan = channel;
+	trans->sg = sg;
+
+	if (channel->mode == MEMORY_MAPPED) {
+		for (i = 0; i < sg->nents; i++) {
+			cookie = txd[i]->tx_submit(txd[i]);
+			if (dma_submit_error(cookie)) {
+				err = (int)cookie;
+				dev_err(channel->dev,
+					"Unable to submit transaction\n");
+				goto free_transaction;
+			}
+
+			if ((i + 1) == sg->nents) {
+				txd[i]->callback =
+					ps_pcie_dma_async_transfer_cbk;
+				txd[i]->callback_param = trans;
+				trans->cookie = cookie;
+			}
+		}
+
+	} else {
+		txd[0]->callback = ps_pcie_dma_async_transfer_cbk;
+		txd[0]->callback_param = trans;
+
+		cookie = txd[0]->tx_submit(txd[0]);
+		if (dma_submit_error(cookie)) {
+			err = (int)cookie;
+			dev_err(channel->dev,
+				"Unable to submit transaction\n");
+			goto free_transaction;
+		}
+
+		trans->cookie = cookie;
+	}
+
+	dma_async_issue_pending(chan);
+
+	return length;
+
+free_transaction:
+err_out_no_prep_sg_async_desc:
+err_out_no_slave_sg_async_descriptor:
+	devm_kfree(channel->dev, trans->buffer_info);
+	devm_kfree(channel->dev, txd);
+err_out_no_completion_info:
+	devm_kfree(channel->dev, trans);
+err_out_trans_ptr:
+	dma_unmap_sg(channel->dev, sg->sgl, sg->nents, direction);
+err_out_dma_map_sg:
+	sg_free_table(sg);
+err_out_sg_to_sgl:
+	devm_kfree(channel->dev, sg);
+err_out_alloc_sg_table:
+	for (i = 0; i < alloc_pages; i++)
+		put_page(cache_pages[i]);
+err_out_pin_pages:
+	devm_kfree(channel->dev, cache_pages);
+err_out_cachepages_alloc:
+
+	return err;
+}
+
+static long ps_pcie_dma_ioctl(struct file *filp, unsigned int cmd,
+			      unsigned long arg)
+{
+	int retval = 0;
+	struct xlnx_ps_pcie_dma_client_channel *chan;
+	struct dma_transfer_info transfer_info;
+
+	if (_IOC_TYPE(cmd) != XPS_PCIE_DMA_CLIENT_MAGIC)
+		return -ENOTTY;
+
+	chan = filp->private_data;
+
+	switch (cmd) {
+	case ISET_ASYNC_TRANSFERINFO:
+		if (copy_from_user((void *)&transfer_info,
+				   (void __user *)arg,
+				   sizeof(struct dma_transfer_info)) != 0) {
+			pr_err("Copy from user asynchronous params\n");
+			retval = -ENXIO;
+			return retval;
+		}
+		if (transfer_info.direction != chan->direction) {
+			retval = -EINVAL;
+			return retval;
+		}
+		retval = initiate_async_transfer(chan,
+						 transfer_info.buff_address,
+						 transfer_info.buff_size,
+						 &transfer_info.offset,
+						 transfer_info.direction);
+		break;
+	case IGET_ASYNC_TRANSFERINFO:
+		retval = update_completed_info(chan,
+					       (struct usrbuff_info *)arg);
+		break;
+	default:
+		pr_err("Unsupported ioctl command received\n");
+		retval = -1;
+	}
+
+	return (long)retval;
+}
+
+static const struct file_operations ps_pcie_dma_comm_fops = {
+	.owner		= THIS_MODULE,
+	.read		= ps_pcie_dma_read,
+	.write		= ps_pcie_dma_write,
+	.unlocked_ioctl = ps_pcie_dma_ioctl,
+	.open		= ps_pcie_dma_open,
+	.release	= ps_pcie_dma_release,
+};
+
+static void pio_sw_intr_cbk(void *data)
+{
+	struct completion *compl = (struct completion *)data;
+
+	if (compl)
+		complete(compl);
+}
+
+static long pio_ioctl(struct file *filp, unsigned int cmd,
+		      unsigned long arg)
+{
+	char *bar_memory = NULL;
+	u32 translation_size = 0;
+	long err = 0;
+	struct dma_async_tx_descriptor *intr_txd = NULL;
+	dma_cookie_t cookie;
+	struct dma_chan *chan = NULL;
+	struct dma_device *device;
+	enum dma_ctrl_flags flags;
+	struct xlnx_ps_pcie_dma_client_device *xdev;
+	struct ps_pcie_dma_channel_match *xlnx_match;
+	struct BAR_PARAMS *barinfo;
+
+	xdev = filp->private_data;
+	chan = xdev->pcie_dma_chan[0].chan;
+	device = chan->device;
+	flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
+
+	xlnx_match =
+		(struct ps_pcie_dma_channel_match *)chan->private;
+
+	barinfo = ((struct BAR_PARAMS *)(xlnx_match->bar_params) +
+			DMA_BAR_NUMBER);
+	bar_memory = (__force char *)barinfo->BAR_VIRT_ADDR;
+
+	xdev = filp->private_data;
+
+	switch (cmd) {
+	case IOCTL_EP_CHECK_TRANSLATION:
+
+		mutex_lock(&xdev->pio_chardev_mutex);
+		reinit_completion(&xdev->trans_cmpltn);
+
+		intr_txd = device->device_prep_dma_interrupt(chan, flags);
+		if (!intr_txd) {
+			err = -EAGAIN;
+			mutex_unlock(&xdev->pio_chardev_mutex);
+			return err;
+		}
+
+		intr_txd->callback       = pio_sw_intr_cbk;
+		intr_txd->callback_param = &xdev->trans_cmpltn;
+
+		cookie = intr_txd->tx_submit(intr_txd);
+		if (dma_submit_error(cookie)) {
+			err =  cookie;
+			pr_err("Unable to submit interrupt transaction\n");
+			mutex_unlock(&xdev->pio_chardev_mutex);
+			return err;
+		}
+
+		dma_async_issue_pending(chan);
+
+		iowrite32(EP_TRANSLATION_CHECK, (void __iomem *)(bar_memory +
+						DMA_SCRATCH0_REG_OFFSET));
+		iowrite32(DMA_SW_INTR_ASSRT_BIT, (void __iomem *)(bar_memory +
+						DMA_AXI_INTR_ASSRT_REG_OFFSET));
+
+		wait_for_completion_interruptible(&xdev->trans_cmpltn);
+		translation_size = ioread32((void __iomem *)bar_memory +
+					    DMA_SCRATCH1_REG_OFFSET);
+		if (translation_size > 0)
+			xdev->pio_translation_size = translation_size;
+		else
+			err = -EAGAIN;
+		iowrite32(0, (void __iomem *)(bar_memory +
+					    DMA_SCRATCH1_REG_OFFSET));
+		mutex_unlock(&xdev->pio_chardev_mutex);
+		break;
+
+	default:
+		err = -EINVAL;
+	}
+	return err;
+}
+
+static ssize_t
+pio_read(struct file *file, char __user *buffer, size_t length,
+	 loff_t *f_offset)
+{
+	char *bar_memory = NULL;
+	struct xlnx_ps_pcie_dma_client_device *xdev;
+	struct ps_pcie_dma_channel_match *xlnx_match;
+	ssize_t num_bytes = 0;
+	struct BAR_PARAMS *barinfo;
+
+	xdev = file->private_data;
+	xlnx_match = (struct ps_pcie_dma_channel_match *)
+				xdev->pcie_dma_chan[0].chan->private;
+
+	barinfo = ((struct BAR_PARAMS *)(xlnx_match->bar_params) +
+			PIO_MEMORY_BAR_NUMBER);
+	bar_memory = (__force char *)barinfo->BAR_VIRT_ADDR;
+
+	if (length > xdev->pio_translation_size) {
+		pr_err("Error! Invalid buffer length supplied at PIO read\n");
+		num_bytes = -1;
+		return num_bytes;
+	}
+
+	if ((length + *f_offset)
+			> xdev->pio_translation_size) {
+		pr_err("Error! Invalid buffer offset supplied at PIO read\n");
+		num_bytes = -1;
+		return num_bytes;
+	}
+
+	bar_memory += *f_offset;
+
+	num_bytes = copy_to_user(buffer, bar_memory, length);
+	if (num_bytes != 0) {
+		pr_err("Error! copy_to_user failed at PIO read\n");
+		num_bytes = length - num_bytes;
+	} else {
+		num_bytes = length;
+	}
+
+	return num_bytes;
+}
+
+static ssize_t
+pio_write(struct file *file, const char __user *buffer,
+	  size_t length, loff_t *f_offset)
+{
+	char *bar_memory = NULL;
+	struct xlnx_ps_pcie_dma_client_device *xdev;
+	struct ps_pcie_dma_channel_match *xlnx_match;
+	ssize_t num_bytes = 0;
+	struct BAR_PARAMS *barinfo;
+
+	xdev = file->private_data;
+	xlnx_match = (struct ps_pcie_dma_channel_match *)
+			xdev->pcie_dma_chan[0].chan->private;
+
+	barinfo = ((struct BAR_PARAMS *)(xlnx_match->bar_params) +
+			PIO_MEMORY_BAR_NUMBER);
+	bar_memory = (__force char *)barinfo->BAR_VIRT_ADDR;
+
+	if (length > xdev->pio_translation_size) {
+		pr_err("Error! Invalid buffer length supplied at PIO write\n");
+		num_bytes = -1;
+		return num_bytes;
+	}
+
+	if ((length + *f_offset)
+			> xdev->pio_translation_size) {
+		pr_err("Error! Invalid buffer offset supplied at PIO write\n");
+		num_bytes = -1;
+		return num_bytes;
+	}
+
+	bar_memory += *f_offset;
+
+	num_bytes = copy_from_user(bar_memory, buffer, length);
+
+	if (num_bytes != 0) {
+		pr_err("Error! copy_from_user failed at PIO write\n");
+		num_bytes = length - num_bytes;
+	} else {
+		num_bytes = length;
+	}
+
+	return num_bytes;
+}
+
+static int pio_open(struct inode *in, struct file *file)
+{
+	struct xlnx_ps_pcie_dma_client_device *xdev;
+
+	xdev = container_of(in->i_cdev,
+			    struct xlnx_ps_pcie_dma_client_device,
+			    xpio_char_dev);
+
+	file->private_data = xdev;
+
+	return 0;
+}
+
+static int pio_release(struct inode *in, struct file *filp)
+{
+	return 0;
+}
+
+static const struct file_operations ps_pcie_pio_fops = {
+	.owner		= THIS_MODULE,
+	.read		= pio_read,
+	.write          = pio_write,
+	.unlocked_ioctl = pio_ioctl,
+	.open		= pio_open,
+	.release	= pio_release,
+};
+
+static void destroy_char_iface_for_pio(
+		struct xlnx_ps_pcie_dma_client_device *xdev)
+{
+	device_destroy(g_ps_pcie_dma_client_class,
+		       MKDEV(MAJOR(xdev->pio_char_device), 0));
+	cdev_del(&xdev->xpio_char_dev);
+	unregister_chrdev_region(xdev->pio_char_device, 1);
+}
+
+static void destroy_char_iface_for_dma(
+		struct xlnx_ps_pcie_dma_client_device *xdev)
+{
+	int i;
+	struct xlnx_completed_info *entry, *next;
+
+	for (i = 0; i < MAX_ALLOWED_CHANNELS_IN_HW; i++) {
+		list_for_each_entry_safe(entry, next,
+					 &xdev->pcie_dma_chan[i].completed.clist,
+					 clist) {
+			spin_lock(&xdev->pcie_dma_chan[i].channel_lock);
+			list_del(&entry->clist);
+			spin_unlock(&xdev->pcie_dma_chan[i].channel_lock);
+			kfree(entry);
+		}
+		device_destroy(g_ps_pcie_dma_client_class,
+			       MKDEV(MAJOR(xdev->char_device), i));
+	}
+	cdev_del(&xdev->xps_pcie_chardev);
+	unregister_chrdev_region(xdev->char_device, MAX_ALLOWED_CHANNELS_IN_HW);
+}
+
+static void delete_char_dev_interfaces(
+	struct xlnx_ps_pcie_dma_client_device *xdev)
+{
+	destroy_char_iface_for_dma(xdev);
+	if (xdev->properties->pio_transfers == PIO_SUPPORTED)
+		destroy_char_iface_for_pio(xdev);
+}
+
+static void release_dma_channels(struct xlnx_ps_pcie_dma_client_device *xdev)
+{
+	int i;
+
+	for (i = 0; i < MAX_ALLOWED_CHANNELS_IN_HW; i++)
+		dma_release_channel(xdev->pcie_dma_chan[i].chan);
+}
+
+static void delete_char_devices(void)
+{
+	struct xlnx_ps_pcie_dma_client_device *entry, *next;
+
+	list_for_each_entry_safe(entry, next, &g_ps_pcie_dma_client_list,
+				 dev_node) {
+		list_del(&entry->dev_node);
+		delete_char_dev_interfaces(entry);
+		release_dma_channels(entry);
+		kfree(entry);
+	}
+}
+
+static bool ps_pcie_dma_filter(struct dma_chan *chan, void *param)
+{
+	struct ps_pcie_dma_channel_match *client_match =
+		(struct ps_pcie_dma_channel_match *)param;
+
+	struct ps_pcie_dma_channel_match *dma_channel_match =
+		(struct ps_pcie_dma_channel_match *)chan->private;
+
+	if (client_match && dma_channel_match) {
+		if (client_match->pci_vendorid != 0 &&
+		    dma_channel_match->pci_vendorid != 0) {
+			if (client_match->pci_vendorid == dma_channel_match->pci_vendorid) {
+				if (client_match->pci_deviceid == dma_channel_match->pci_deviceid &&
+				    client_match->channel_number == dma_channel_match->channel_number &&
+				    client_match->direction == dma_channel_match->direction) {
+					return true;
+				}
+			}
+		}
+	}
+	return false;
+}
+
+static int acquire_dma_channels(struct xlnx_ps_pcie_dma_client_device *xdev)
+{
+	int err;
+	int i;
+	dma_cap_mask_t mask;
+	struct ps_pcie_dma_channel_match *match;
+
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE | DMA_PRIVATE, mask);
+
+	for (i = 0; i < MAX_ALLOWED_CHANNELS_IN_HW; i++) {
+		match = &xdev->pcie_dma_chan[i].match;
+		match->board_number = xdev->properties->board_number;
+		match->pci_deviceid = xdev->properties->pci_deviceid;
+		match->pci_vendorid = xdev->properties->pci_vendorid;
+		match->channel_number = i;
+		match->direction = xdev->properties->direction[i];
+
+		xdev->pcie_dma_chan[i].chan =
+			dma_request_channel(mask, ps_pcie_dma_filter, match);
+
+		if (!xdev->pcie_dma_chan[i].chan) {
+			pr_err("Error channel handle %d board %d channel\n",
+			       match->board_number,
+			       match->channel_number);
+			err = -EINVAL;
+			goto err_out_no_channels;
+		}
+		xdev->pcie_dma_chan[i].dev =
+				xdev->pcie_dma_chan[i].chan->device->dev;
+		xdev->pcie_dma_chan[i].direction =
+				xdev->properties->direction[i];
+		xdev->pcie_dma_chan[i].mode =
+				xdev->properties->mode;
+		INIT_LIST_HEAD(&xdev->pcie_dma_chan[i].completed.clist);
+		spin_lock_init(&xdev->pcie_dma_chan[i].channel_lock);
+	}
+
+	return 0;
+
+err_out_no_channels:
+	while (i > 0) {
+		i--;
+		dma_release_channel(xdev->pcie_dma_chan[i].chan);
+	}
+	return err;
+}
+
+static int create_char_dev_iface_for_dma_device(
+		struct xlnx_ps_pcie_dma_client_device *xdev)
+{
+	int err = 0;
+	int i;
+
+	WARN_ON(!xdev);
+
+	err = alloc_chrdev_region(&xdev->char_device, 0,
+				  MAX_ALLOWED_CHANNELS_IN_HW,
+				  CHAR_DRIVER_NAME);
+	if (err < 0) {
+		pr_err("Unable to allocate char device region\n");
+		return err;
+	}
+
+	xdev->xps_pcie_chardev.owner = THIS_MODULE;
+	cdev_init(&xdev->xps_pcie_chardev, &ps_pcie_dma_comm_fops);
+	xdev->xps_pcie_chardev.dev = xdev->char_device;
+
+	err = cdev_add(&xdev->xps_pcie_chardev, xdev->char_device,
+		       MAX_ALLOWED_CHANNELS_IN_HW);
+	if (err < 0) {
+		pr_err("PS PCIe DMA unable to add cdev\n");
+		goto err_out_cdev_add;
+	}
+
+	for (i = 0; i < MAX_ALLOWED_CHANNELS_IN_HW; i++) {
+		xdev->chardev[i] =
+			device_create(g_ps_pcie_dma_client_class,
+				      xdev->pcie_dma_chan[i].dev,
+				      MKDEV(MAJOR(xdev->char_device), i),
+				      xdev,
+				      "%s%d_%d", CHAR_DRIVER_NAME,
+				      i, xdev->properties->board_number);
+
+		if (!xdev->chardev[i]) {
+			err = PTR_ERR(xdev->chardev[i]);
+			pr_err(
+			"PS PCIe DMA Unable to create device %d\n", i);
+			goto err_out_dev_create;
+		}
+	}
+
+	return 0;
+
+err_out_dev_create:
+	while (--i >= 0) {
+		device_destroy(g_ps_pcie_dma_client_class,
+			       MKDEV(MAJOR(xdev->char_device), i));
+	}
+	cdev_del(&xdev->xps_pcie_chardev);
+err_out_cdev_add:
+	unregister_chrdev_region(xdev->char_device, MAX_ALLOWED_CHANNELS_IN_HW);
+	return err;
+}
+
+static int create_char_dev_iface_for_pio(
+		struct xlnx_ps_pcie_dma_client_device *xdev)
+{
+	int err;
+
+	err = alloc_chrdev_region(&xdev->pio_char_device, 0, 1,
+				  PIO_CHAR_DRIVER_NAME);
+	if (err < 0) {
+		pr_err("Unable to allocate pio character device region\n");
+		return err;
+	}
+
+	xdev->xpio_char_dev.owner = THIS_MODULE;
+	cdev_init(&xdev->xpio_char_dev, &ps_pcie_pio_fops);
+	xdev->xpio_char_dev.dev = xdev->pio_char_device;
+
+	err = cdev_add(&xdev->xpio_char_dev, xdev->pio_char_device, 1);
+	if (err < 0) {
+		pr_err("PS PCIe DMA unable to add cdev for pio\n");
+		goto err_out_pio_cdev_add;
+	}
+
+	xdev->xpio_char_device =
+		device_create(g_ps_pcie_dma_client_class,
+			      xdev->pcie_dma_chan[0].dev,
+			      MKDEV(MAJOR(xdev->pio_char_device), 0),
+			      xdev, "%s_%d", PIO_CHAR_DRIVER_NAME,
+			      xdev->properties->board_number);
+
+	if (!xdev->xpio_char_device) {
+		err = PTR_ERR(xdev->xpio_char_device);
+		pr_err("PS PCIe DMA Unable to create pio device\n");
+		goto err_out_pio_dev_create;
+	}
+
+	mutex_init(&xdev->pio_chardev_mutex);
+	xdev->pio_translation_size = 0;
+	init_completion(&xdev->trans_cmpltn);
+
+	return 0;
+
+err_out_pio_dev_create:
+	cdev_del(&xdev->xpio_char_dev);
+err_out_pio_cdev_add:
+	unregister_chrdev_region(xdev->pio_char_device, 1);
+	return err;
+}
+
+static int create_char_dev_interfaces(
+	struct xlnx_ps_pcie_dma_client_device *xdev)
+{
+	int err;
+
+	err = create_char_dev_iface_for_dma_device(xdev);
+
+	if (err != 0) {
+		pr_err("Unable to create char dev dma iface %d\n",
+		       xdev->properties->pci_deviceid);
+		goto no_char_iface_for_dma;
+	}
+
+	if (xdev->properties->pio_transfers == PIO_SUPPORTED) {
+		err = create_char_dev_iface_for_pio(xdev);
+		if (err != 0) {
+			pr_err("Unable to create char dev pio iface %d\n",
+			       xdev->properties->pci_deviceid);
+			goto no_char_iface_for_pio;
+		}
+	}
+
+	return 0;
+
+no_char_iface_for_pio:
+	destroy_char_iface_for_dma(xdev);
+no_char_iface_for_dma:
+	return err;
+}
+
+static int setup_char_devices(u16 dev_prop_index)
+{
+	struct xlnx_ps_pcie_dma_client_device *xdev;
+	int err;
+	int i;
+
+	xdev = kzalloc(sizeof(*xdev), GFP_KERNEL);
+	if (!xdev) {
+		err = -ENOMEM;
+		return err;
+	}
+
+	xdev->properties = &g_dma_deviceproperties_list[dev_prop_index];
+
+	err = acquire_dma_channels(xdev);
+	if (err != 0) {
+		pr_err("Unable to acquire dma channels %d\n",
+		       dev_prop_index);
+		goto err_no_dma_channels;
+	}
+
+	err = create_char_dev_interfaces(xdev);
+	if (err != 0) {
+		pr_err("Unable to create char dev interfaces %d\n",
+		       dev_prop_index);
+		goto err_no_char_dev_ifaces;
+	}
+
+	list_add_tail(&xdev->dev_node, &g_ps_pcie_dma_client_list);
+
+	return 0;
+
+err_no_char_dev_ifaces:
+	for (i = 0; i < MAX_ALLOWED_CHANNELS_IN_HW; i++)
+		dma_release_channel(xdev->pcie_dma_chan[i].chan);
+err_no_dma_channels:
+	kfree(xdev);
+	return err;
+}
+
+/**
+ * ps_pcie_dma_client_init - Driver init function
+ *
+ * Return: 0 on success. Non zero on failure
+ */
+static int __init ps_pcie_dma_client_init(void)
+{
+	int err;
+	int i;
+	size_t num_dma_dev_properties;
+
+	INIT_LIST_HEAD(&g_ps_pcie_dma_client_list);
+
+	g_ps_pcie_dma_client_class = class_create(THIS_MODULE, DRV_MODULE_NAME);
+	if (IS_ERR(g_ps_pcie_dma_client_class)) {
+		pr_err("%s failed to create class\n", DRV_MODULE_NAME);
+		return PTR_ERR(g_ps_pcie_dma_client_class);
+	}
+
+	num_dma_dev_properties = ARRAY_SIZE(g_dma_deviceproperties_list);
+	for (i = 0; i < num_dma_dev_properties; i++) {
+		err = setup_char_devices(i);
+		if (err) {
+			pr_err("Error creating char devices for %d\n", i);
+			goto err_no_char_devices;
+		}
+	}
+
+	pr_info("PS PCIe DMA Client Driver Init successful\n");
+	return 0;
+
+err_no_char_devices:
+	delete_char_devices();
+
+	if (g_ps_pcie_dma_client_class)
+		class_destroy(g_ps_pcie_dma_client_class);
+	return err;
+}
+late_initcall(ps_pcie_dma_client_init);
+
+/**
+ * ps_pcie_dma_client_exit - Driver exit function
+ *
+ */
+static void __exit ps_pcie_dma_client_exit(void)
+{
+	delete_char_devices();
+
+	if (g_ps_pcie_dma_client_class)
+		class_destroy(g_ps_pcie_dma_client_class);
+}
+
+module_exit(ps_pcie_dma_client_exit);
+
+MODULE_AUTHOR("Xilinx Inc");
+MODULE_DESCRIPTION("Xilinx PS PCIe DMA client Driver");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/xilinx/xilinx_ps_pcie_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/xilinx/xilinx_ps_pcie_main.c
@@ -0,0 +1,200 @@
+/*
+ * XILINX PS PCIe driver
+ *
+ * Copyright (C) 2017 Xilinx, Inc. All rights reserved.
+ *
+ * Description
+ * PS PCIe DMA is memory mapped DMA used to execute PS to PL transfers
+ * on ZynqMP UltraScale+ Devices.
+ * This PCIe driver creates a platform device with specific platform
+ * info enabling creation of DMA device corresponding to the channel
+ * information provided in the properties
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation
+ */
+
+#include "xilinx_ps_pcie.h"
+#include "../dmaengine.h"
+
+#define DRV_MODULE_NAME		  "ps_pcie_dma"
+
+static int ps_pcie_dma_probe(struct pci_dev *pdev,
+			     const struct pci_device_id *ent);
+static void ps_pcie_dma_remove(struct pci_dev *pdev);
+
+static u32 channel_properties_pcie_axi[] = {
+	(u32)(PCIE_AXI_DIRECTION), (u32)(NUMBER_OF_BUFFER_DESCRIPTORS),
+	(u32)(DEFAULT_DMA_QUEUES), (u32)(CHANNEL_COAELSE_COUNT),
+	(u32)(CHANNEL_POLL_TIMER_FREQUENCY) };
+
+static u32 channel_properties_axi_pcie[] = {
+	(u32)(AXI_PCIE_DIRECTION), (u32)(NUMBER_OF_BUFFER_DESCRIPTORS),
+	(u32)(DEFAULT_DMA_QUEUES), (u32)(CHANNEL_COAELSE_COUNT),
+	(u32)(CHANNEL_POLL_TIMER_FREQUENCY) };
+
+static struct property_entry generic_pcie_ep_property[] = {
+	PROPERTY_ENTRY_U32("numchannels", (u32)MAX_NUMBER_OF_CHANNELS),
+	PROPERTY_ENTRY_U32_ARRAY("ps_pcie_channel0",
+				 channel_properties_pcie_axi),
+	PROPERTY_ENTRY_U32_ARRAY("ps_pcie_channel1",
+				 channel_properties_axi_pcie),
+	PROPERTY_ENTRY_U32_ARRAY("ps_pcie_channel2",
+				 channel_properties_pcie_axi),
+	PROPERTY_ENTRY_U32_ARRAY("ps_pcie_channel3",
+				 channel_properties_axi_pcie),
+	{ },
+};
+
+static const struct platform_device_info xlnx_std_platform_dev_info = {
+	.name           = XLNX_PLATFORM_DRIVER_NAME,
+	.properties     = generic_pcie_ep_property,
+};
+
+/**
+ * ps_pcie_dma_probe - Driver probe function
+ * @pdev: Pointer to the pci_dev structure
+ * @ent: pci device id
+ *
+ * Return: '0' on success and failure value on error
+ */
+static int ps_pcie_dma_probe(struct pci_dev *pdev,
+			     const struct pci_device_id *ent)
+{
+	int err;
+	struct platform_device *platform_dev;
+	struct platform_device_info platform_dev_info;
+
+	dev_info(&pdev->dev, "PS PCIe DMA Driver probe\n");
+
+	err = pcim_enable_device(pdev);
+	if (err) {
+		dev_err(&pdev->dev, "Cannot enable PCI device, aborting\n");
+		return err;
+	}
+
+	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
+	if (err) {
+		dev_info(&pdev->dev, "Cannot set 64 bit DMA mask\n");
+		err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+		if (err) {
+			dev_err(&pdev->dev, "DMA mask set error\n");
+			return err;
+		}
+	}
+
+	err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
+	if (err) {
+		dev_info(&pdev->dev, "Cannot set 64 bit consistent DMA mask\n");
+		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+		if (err) {
+			dev_err(&pdev->dev, "Cannot set consistent DMA mask\n");
+			return err;
+		}
+	}
+
+	pci_set_master(pdev);
+
+	/* For Root DMA platform device will be created through device tree */
+	if (pdev->vendor == PCI_VENDOR_ID_XILINX &&
+	    pdev->device == ZYNQMP_RC_DMA_DEVID)
+		return 0;
+
+	memcpy(&platform_dev_info, &xlnx_std_platform_dev_info,
+	       sizeof(xlnx_std_platform_dev_info));
+
+	/* Do device specific channel configuration changes to
+	 * platform_dev_info.properties if required
+	 * More information on channel properties can be found
+	 * at Documentation/devicetree/bindings/dma/xilinx/ps-pcie-dma.txt
+	 */
+
+	platform_dev_info.parent = &pdev->dev;
+	platform_dev_info.data = &pdev;
+	platform_dev_info.size_data = sizeof(struct pci_dev **);
+
+	platform_dev = platform_device_register_full(&platform_dev_info);
+	if (IS_ERR(platform_dev)) {
+		dev_err(&pdev->dev,
+			"Cannot create platform device, aborting\n");
+		return PTR_ERR(platform_dev);
+	}
+
+	pci_set_drvdata(pdev, platform_dev);
+
+	dev_info(&pdev->dev, "PS PCIe DMA driver successfully probed\n");
+
+	return 0;
+}
+
+static struct pci_device_id ps_pcie_dma_tbl[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_XILINX, ZYNQMP_DMA_DEVID) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_XILINX, ZYNQMP_RC_DMA_DEVID) },
+	{ }
+};
+
+static struct pci_driver ps_pcie_dma_driver = {
+	.name     = DRV_MODULE_NAME,
+	.id_table = ps_pcie_dma_tbl,
+	.probe    = ps_pcie_dma_probe,
+	.remove   = ps_pcie_dma_remove,
+};
+
+/**
+ * ps_pcie_init - Driver init function
+ *
+ * Return: 0 on success. Non zero on failure
+ */
+static int __init ps_pcie_init(void)
+{
+	int ret;
+
+	pr_info("%s init()\n", DRV_MODULE_NAME);
+
+	ret = pci_register_driver(&ps_pcie_dma_driver);
+	if (ret)
+		return ret;
+
+	ret = dma_platform_driver_register();
+	if (ret)
+		pci_unregister_driver(&ps_pcie_dma_driver);
+
+	return ret;
+}
+
+/**
+ * ps_pcie_dma_remove - Driver remove function
+ * @pdev: Pointer to the pci_dev structure
+ *
+ * Return: void
+ */
+static void ps_pcie_dma_remove(struct pci_dev *pdev)
+{
+	struct platform_device *platform_dev;
+
+	platform_dev = (struct platform_device *)pci_get_drvdata(pdev);
+
+	if (platform_dev)
+		platform_device_unregister(platform_dev);
+}
+
+/**
+ * ps_pcie_exit - Driver exit function
+ *
+ * Return: void
+ */
+static void __exit ps_pcie_exit(void)
+{
+	pr_info("%s exit()\n", DRV_MODULE_NAME);
+
+	dma_platform_driver_unregister();
+	pci_unregister_driver(&ps_pcie_dma_driver);
+}
+
+module_init(ps_pcie_init);
+module_exit(ps_pcie_exit);
+
+MODULE_AUTHOR("Xilinx Inc");
+MODULE_DESCRIPTION("Xilinx PS PCIe DMA Driver");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/xilinx/xilinx_ps_pcie_platform.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/xilinx/xilinx_ps_pcie_platform.c
@@ -0,0 +1,3170 @@
+/*
+ * XILINX PS PCIe DMA driver
+ *
+ * Copyright (C) 2017 Xilinx, Inc. All rights reserved.
+ *
+ * Description
+ * PS PCIe DMA is memory mapped DMA used to execute PS to PL transfers
+ * on ZynqMP UltraScale+ Devices
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation
+ */
+
+#include "xilinx_ps_pcie.h"
+#include "../dmaengine.h"
+
+#define PLATFORM_DRIVER_NAME		  "ps_pcie_pform_dma"
+#define MAX_BARS 6
+
+#define DMA_BAR_NUMBER 0
+
+#define MIN_SW_INTR_TRANSACTIONS       2
+
+#define CHANNEL_PROPERTY_LENGTH 50
+#define WORKQ_NAME_SIZE		100
+#define INTR_HANDLR_NAME_SIZE   100
+
+#define PS_PCIE_DMA_IRQ_NOSHARE    0
+
+#define MAX_COALESCE_COUNT     255
+
+#define DMA_CHANNEL_REGS_SIZE 0x80
+
+#define DMA_SRCQPTRLO_REG_OFFSET  (0x00) /* Source Q pointer Lo */
+#define DMA_SRCQPTRHI_REG_OFFSET  (0x04) /* Source Q pointer Hi */
+#define DMA_SRCQSZ_REG_OFFSET     (0x08) /* Source Q size */
+#define DMA_SRCQLMT_REG_OFFSET    (0x0C) /* Source Q limit */
+#define DMA_DSTQPTRLO_REG_OFFSET  (0x10) /* Destination Q pointer Lo */
+#define DMA_DSTQPTRHI_REG_OFFSET  (0x14) /* Destination Q pointer Hi */
+#define DMA_DSTQSZ_REG_OFFSET     (0x18) /* Destination Q size */
+#define DMA_DSTQLMT_REG_OFFSET    (0x1C) /* Destination Q limit */
+#define DMA_SSTAQPTRLO_REG_OFFSET (0x20) /* Source Status Q pointer Lo */
+#define DMA_SSTAQPTRHI_REG_OFFSET (0x24) /* Source Status Q pointer Hi */
+#define DMA_SSTAQSZ_REG_OFFSET    (0x28) /* Source Status Q size */
+#define DMA_SSTAQLMT_REG_OFFSET   (0x2C) /* Source Status Q limit */
+#define DMA_DSTAQPTRLO_REG_OFFSET (0x30) /* Destination Status Q pointer Lo */
+#define DMA_DSTAQPTRHI_REG_OFFSET (0x34) /* Destination Status Q pointer Hi */
+#define DMA_DSTAQSZ_REG_OFFSET    (0x38) /* Destination Status Q size */
+#define DMA_DSTAQLMT_REG_OFFSET   (0x3C) /* Destination Status Q limit */
+#define DMA_SRCQNXT_REG_OFFSET    (0x40) /* Source Q next */
+#define DMA_DSTQNXT_REG_OFFSET    (0x44) /* Destination Q next */
+#define DMA_SSTAQNXT_REG_OFFSET   (0x48) /* Source Status Q next */
+#define DMA_DSTAQNXT_REG_OFFSET   (0x4C) /* Destination Status Q next */
+#define DMA_SCRATCH0_REG_OFFSET   (0x50) /* Scratch pad register 0 */
+
+#define DMA_PCIE_INTR_CNTRL_REG_OFFSET  (0x60) /* DMA PCIe intr control reg */
+#define DMA_PCIE_INTR_STATUS_REG_OFFSET (0x64) /* DMA PCIe intr status reg */
+#define DMA_AXI_INTR_CNTRL_REG_OFFSET   (0x68) /* DMA AXI intr control reg */
+#define DMA_AXI_INTR_STATUS_REG_OFFSET  (0x6C) /* DMA AXI intr status reg */
+#define DMA_PCIE_INTR_ASSRT_REG_OFFSET  (0x70) /* PCIe intr assert reg */
+#define DMA_AXI_INTR_ASSRT_REG_OFFSET   (0x74) /* AXI intr assert register */
+#define DMA_CNTRL_REG_OFFSET            (0x78) /* DMA control register */
+#define DMA_STATUS_REG_OFFSET           (0x7C) /* DMA status register */
+
+#define DMA_CNTRL_RST_BIT               BIT(1)
+#define DMA_CNTRL_64BIT_STAQ_ELEMSZ_BIT BIT(2)
+#define DMA_CNTRL_ENABL_BIT             BIT(0)
+#define DMA_STATUS_DMA_PRES_BIT         BIT(15)
+#define DMA_STATUS_DMA_RUNNING_BIT      BIT(0)
+#define DMA_QPTRLO_QLOCAXI_BIT          BIT(0)
+#define DMA_QPTRLO_Q_ENABLE_BIT         BIT(1)
+#define DMA_INTSTATUS_DMAERR_BIT        BIT(1)
+#define DMA_INTSTATUS_SGLINTR_BIT       BIT(2)
+#define DMA_INTSTATUS_SWINTR_BIT        BIT(3)
+#define DMA_INTCNTRL_ENABLINTR_BIT      BIT(0)
+#define DMA_INTCNTRL_DMAERRINTR_BIT     BIT(1)
+#define DMA_INTCNTRL_DMASGINTR_BIT      BIT(2)
+#define DMA_SW_INTR_ASSRT_BIT           BIT(3)
+
+#define SOURCE_CONTROL_BD_BYTE_COUNT_MASK       GENMASK(23, 0)
+#define SOURCE_CONTROL_BD_LOC_AXI		BIT(24)
+#define SOURCE_CONTROL_BD_EOP_BIT               BIT(25)
+#define SOURCE_CONTROL_BD_INTR_BIT              BIT(26)
+#define SOURCE_CONTROL_BACK_TO_BACK_PACK_BIT    BIT(25)
+#define SOURCE_CONTROL_ATTRIBUTES_MASK          GENMASK(31, 28)
+#define SRC_CTL_ATTRIB_BIT_SHIFT                (29)
+
+#define STA_BD_COMPLETED_BIT            BIT(0)
+#define STA_BD_SOURCE_ERROR_BIT         BIT(1)
+#define STA_BD_DESTINATION_ERROR_BIT    BIT(2)
+#define STA_BD_INTERNAL_ERROR_BIT       BIT(3)
+#define STA_BD_UPPER_STATUS_NONZERO_BIT BIT(31)
+#define STA_BD_BYTE_COUNT_MASK          GENMASK(30, 4)
+
+#define STA_BD_BYTE_COUNT_SHIFT         4
+
+#define DMA_INTCNTRL_SGCOLSCCNT_BIT_SHIFT (16)
+
+#define DMA_SRC_Q_LOW_BIT_SHIFT   GENMASK(5, 0)
+
+#define MAX_TRANSFER_LENGTH       0x1000000
+
+#define AXI_ATTRIBUTE       0x3
+#define PCI_ATTRIBUTE       0x2
+
+#define ROOTDMA_Q_READ_ATTRIBUTE 0x8
+
+/*
+ * User Id programmed into Source Q will be copied into Status Q of Destination
+ */
+#define DEFAULT_UID 1
+
+/*
+ * DMA channel registers
+ */
+struct DMA_ENGINE_REGISTERS {
+	u32 src_q_low;          /* 0x00 */
+	u32 src_q_high;         /* 0x04 */
+	u32 src_q_size;         /* 0x08 */
+	u32 src_q_limit;        /* 0x0C */
+	u32 dst_q_low;          /* 0x10 */
+	u32 dst_q_high;         /* 0x14 */
+	u32 dst_q_size;         /* 0x18 */
+	u32 dst_q_limit;        /* 0x1c */
+	u32 stas_q_low;         /* 0x20 */
+	u32 stas_q_high;        /* 0x24 */
+	u32 stas_q_size;        /* 0x28 */
+	u32 stas_q_limit;       /* 0x2C */
+	u32 stad_q_low;         /* 0x30 */
+	u32 stad_q_high;        /* 0x34 */
+	u32 stad_q_size;        /* 0x38 */
+	u32 stad_q_limit;       /* 0x3C */
+	u32 src_q_next;         /* 0x40 */
+	u32 dst_q_next;         /* 0x44 */
+	u32 stas_q_next;        /* 0x48 */
+	u32 stad_q_next;        /* 0x4C */
+	u32 scrathc0;           /* 0x50 */
+	u32 scrathc1;           /* 0x54 */
+	u32 scrathc2;           /* 0x58 */
+	u32 scrathc3;           /* 0x5C */
+	u32 pcie_intr_cntrl;    /* 0x60 */
+	u32 pcie_intr_status;   /* 0x64 */
+	u32 axi_intr_cntrl;     /* 0x68 */
+	u32 axi_intr_status;    /* 0x6C */
+	u32 pcie_intr_assert;   /* 0x70 */
+	u32 axi_intr_assert;    /* 0x74 */
+	u32 dma_channel_ctrl;   /* 0x78 */
+	u32 dma_channel_status; /* 0x7C */
+} __attribute__((__packed__));
+
+/**
+ * struct SOURCE_DMA_DESCRIPTOR - Source Hardware Descriptor
+ * @system_address: 64 bit buffer physical address
+ * @control_byte_count: Byte count/buffer length and control flags
+ * @user_handle: User handle gets copied to status q on completion
+ * @user_id: User id gets copied to status q of destination
+ */
+struct SOURCE_DMA_DESCRIPTOR {
+	u64 system_address;
+	u32 control_byte_count;
+	u16 user_handle;
+	u16 user_id;
+} __attribute__((__packed__));
+
+/**
+ * struct DEST_DMA_DESCRIPTOR - Destination Hardware Descriptor
+ * @system_address: 64 bit buffer physical address
+ * @control_byte_count: Byte count/buffer length and control flags
+ * @user_handle: User handle gets copied to status q on completion
+ * @reserved: Reserved field
+ */
+struct DEST_DMA_DESCRIPTOR {
+	u64 system_address;
+	u32 control_byte_count;
+	u16 user_handle;
+	u16 reserved;
+} __attribute__((__packed__));
+
+/**
+ * struct STATUS_DMA_DESCRIPTOR - Status Hardware Descriptor
+ * @status_flag_byte_count: Byte count/buffer length and status flags
+ * @user_handle: User handle gets copied from src/dstq on completion
+ * @user_id: User id gets copied from srcq
+ */
+struct STATUS_DMA_DESCRIPTOR {
+	u32 status_flag_byte_count;
+	u16 user_handle;
+	u16 user_id;
+} __attribute__((__packed__));
+
+enum PACKET_CONTEXT_AVAILABILITY {
+	FREE = 0,    /*Packet transfer Parameter context is free.*/
+	IN_USE       /*Packet transfer Parameter context is in use.*/
+};
+
+struct ps_pcie_transfer_elements {
+	struct list_head node;
+	dma_addr_t src_pa;
+	dma_addr_t dst_pa;
+	u32 transfer_bytes;
+};
+
+struct  ps_pcie_tx_segment {
+	struct list_head node;
+	struct dma_async_tx_descriptor async_tx;
+	struct list_head transfer_nodes;
+	u32 src_elements;
+	u32 dst_elements;
+	u32 total_transfer_bytes;
+};
+
+struct ps_pcie_intr_segment {
+	struct list_head node;
+	struct dma_async_tx_descriptor async_intr_tx;
+};
+
+/*
+ * The context structure stored for each DMA transaction
+ * This structure is maintained separately for Src Q and Destination Q
+ * @availability_status: Indicates whether packet context is available
+ * @idx_sop: Indicates starting index of buffer descriptor for a transfer
+ * @idx_eop: Indicates ending index of buffer descriptor for a transfer
+ * @sgl: Indicates either src or dst sglist for the transaction
+ */
+struct PACKET_TRANSFER_PARAMS {
+	enum PACKET_CONTEXT_AVAILABILITY availability_status;
+	u16 idx_sop;
+	u16 idx_eop;
+	struct ps_pcie_tx_segment *seg;
+};
+
+enum CHANNEL_STATE {
+	CHANNEL_RESOURCE_UNALLOCATED = 0, /*  Channel resources not allocated */
+	CHANNEL_UNAVIALBLE,               /*  Channel inactive */
+	CHANNEL_AVAILABLE,                /*  Channel available for transfers */
+	CHANNEL_ERROR                     /*  Channel encountered errors */
+};
+
+enum BUFFER_LOCATION {
+	BUFFER_LOC_PCI = 0,
+	BUFFER_LOC_AXI,
+	BUFFER_LOC_INVALID
+};
+
+enum dev_channel_properties {
+	DMA_CHANNEL_DIRECTION = 0,
+	NUM_DESCRIPTORS,
+	NUM_QUEUES,
+	COALESE_COUNT,
+	POLL_TIMER_FREQUENCY
+};
+
+/*
+ * struct ps_pcie_dma_chan - Driver specific DMA channel structure
+ * @xdev: Driver specific device structure
+ * @dev: The dma device
+ * @common:  DMA common channel
+ * @chan_base: Pointer to Channel registers
+ * @channel_number: DMA channel number in the device
+ * @num_queues: Number of queues per channel.
+ *		It should be four for memory mapped case and
+ *		two for Streaming case
+ * @direction: Transfer direction
+ * @state: Indicates channel state
+ * @channel_lock: Spin lock to be used before changing channel state
+ * @cookie_lock: Spin lock to be used before assigning cookie for a transaction
+ * @coalesce_count: Indicates number of packet transfers before interrupts
+ * @poll_timer_freq:Indicates frequency of polling for completed transactions
+ * @poll_timer: Timer to poll dma buffer descriptors if coalesce count is > 0
+ * @src_avail_descriptors: Available sgl source descriptors
+ * @src_desc_lock: Lock for synchronizing src_avail_descriptors
+ * @dst_avail_descriptors: Available sgl destination descriptors
+ * @dst_desc_lock: Lock for synchronizing
+ *		dst_avail_descriptors
+ * @src_sgl_bd_pa: Physical address of Source SGL buffer Descriptors
+ * @psrc_sgl_bd: Virtual address of Source SGL buffer Descriptors
+ * @src_sgl_freeidx: Holds index of Source SGL buffer descriptor to be filled
+ * @sglDestinationQLock:Lock to serialize Destination Q updates
+ * @dst_sgl_bd_pa: Physical address of Dst SGL buffer Descriptors
+ * @pdst_sgl_bd: Virtual address of Dst SGL buffer Descriptors
+ * @dst_sgl_freeidx: Holds index of Destination SGL
+ * @src_sta_bd_pa: Physical address of StatusQ buffer Descriptors
+ * @psrc_sta_bd: Virtual address of Src StatusQ buffer Descriptors
+ * @src_staprobe_idx: Holds index of Status Q to be examined for SrcQ updates
+ * @src_sta_hw_probe_idx: Holds index of maximum limit of Status Q for hardware
+ * @dst_sta_bd_pa: Physical address of Dst StatusQ buffer Descriptor
+ * @pdst_sta_bd: Virtual address of Dst Status Q buffer Descriptors
+ * @dst_staprobe_idx: Holds index of Status Q to be examined for updates
+ * @dst_sta_hw_probe_idx: Holds index of max limit of Dst Status Q for hardware
+ * @@read_attribute: Describes the attributes of buffer in srcq
+ * @@write_attribute: Describes the attributes of buffer in dstq
+ * @@intr_status_offset: Register offset to be cheked on receiving interrupt
+ * @@intr_status_offset: Register offset to be used to control interrupts
+ * @ppkt_ctx_srcq: Virtual address of packet context to Src Q updates
+ * @idx_ctx_srcq_head: Holds index of packet context to be filled for Source Q
+ * @idx_ctx_srcq_tail: Holds index of packet context to be examined for Source Q
+ * @ppkt_ctx_dstq: Virtual address of packet context to Dst Q updates
+ * @idx_ctx_dstq_head: Holds index of packet context to be filled for Dst Q
+ * @idx_ctx_dstq_tail: Holds index of packet context to be examined for Dst Q
+ * @pending_list_lock: Lock to be taken before updating pending transfers list
+ * @pending_list: List of transactions submitted to channel
+ * @active_list_lock: Lock to be taken before transferring transactions from
+ *			pending list to active list which will be subsequently
+ *				submitted to hardware
+ * @active_list: List of transactions that will be submitted to hardware
+ * @pending_interrupts_lock: Lock to be taken before updating pending Intr list
+ * @pending_interrupts_list: List of interrupt transactions submitted to channel
+ * @active_interrupts_lock: Lock to be taken before transferring transactions
+ *			from pending interrupt list to active interrupt list
+ * @active_interrupts_list: List of interrupt transactions that are active
+ * @transactions_pool: Mem pool to allocate dma transactions quickly
+ * @intr_transactions_pool: Mem pool to allocate interrupt transactions quickly
+ * @sw_intrs_wrkq: Work Q which performs handling of software intrs
+ * @handle_sw_intrs:Work function handling software interrupts
+ * @maintenance_workq: Work Q to perform maintenance tasks during stop or error
+ * @handle_chan_reset: Work that invokes channel reset function
+ * @handle_chan_shutdown: Work that invokes channel shutdown function
+ * @handle_chan_terminate: Work that invokes channel transactions termination
+ * @chan_shutdown_complt: Completion variable which says shutdown is done
+ * @chan_terminate_complete: Completion variable which says terminate is done
+ * @primary_desc_cleanup: Work Q which performs work related to sgl handling
+ * @handle_primary_desc_cleanup: Work that invokes src Q, dst Q cleanup
+ *				and programming
+ * @chan_programming: Work Q which performs work related to channel programming
+ * @handle_chan_programming: Work that invokes channel programming function
+ * @srcq_desc_cleanup: Work Q which performs src Q descriptor cleanup
+ * @handle_srcq_desc_cleanup: Work function handling Src Q completions
+ * @dstq_desc_cleanup: Work Q which performs dst Q descriptor cleanup
+ * @handle_dstq_desc_cleanup: Work function handling Dst Q completions
+ * @srcq_work_complete: Src Q Work completion variable for primary work
+ * @dstq_work_complete: Dst Q Work completion variable for primary work
+ */
+struct ps_pcie_dma_chan {
+	struct xlnx_pcie_dma_device *xdev;
+	struct device *dev;
+
+	struct dma_chan common;
+
+	struct DMA_ENGINE_REGISTERS *chan_base;
+	u16 channel_number;
+
+	u32 num_queues;
+	enum dma_data_direction direction;
+	enum BUFFER_LOCATION srcq_buffer_location;
+	enum BUFFER_LOCATION dstq_buffer_location;
+
+	u32 total_descriptors;
+
+	enum CHANNEL_STATE state;
+	spinlock_t channel_lock; /* For changing channel state */
+
+	spinlock_t cookie_lock;  /* For acquiring cookie from dma framework*/
+
+	u32 coalesce_count;
+	u32 poll_timer_freq;
+
+	struct timer_list poll_timer;
+
+	u32 src_avail_descriptors;
+	spinlock_t src_desc_lock; /* For handling srcq available descriptors */
+
+	u32 dst_avail_descriptors;
+	spinlock_t dst_desc_lock; /* For handling dstq available descriptors */
+
+	dma_addr_t src_sgl_bd_pa;
+	struct SOURCE_DMA_DESCRIPTOR *psrc_sgl_bd;
+	u32 src_sgl_freeidx;
+
+	dma_addr_t dst_sgl_bd_pa;
+	struct DEST_DMA_DESCRIPTOR *pdst_sgl_bd;
+	u32 dst_sgl_freeidx;
+
+	dma_addr_t src_sta_bd_pa;
+	struct STATUS_DMA_DESCRIPTOR *psrc_sta_bd;
+	u32 src_staprobe_idx;
+	u32 src_sta_hw_probe_idx;
+
+	dma_addr_t dst_sta_bd_pa;
+	struct STATUS_DMA_DESCRIPTOR *pdst_sta_bd;
+	u32 dst_staprobe_idx;
+	u32 dst_sta_hw_probe_idx;
+
+	u32 read_attribute;
+	u32 write_attribute;
+
+	u32 intr_status_offset;
+	u32 intr_control_offset;
+
+	struct PACKET_TRANSFER_PARAMS *ppkt_ctx_srcq;
+	u16 idx_ctx_srcq_head;
+	u16 idx_ctx_srcq_tail;
+
+	struct PACKET_TRANSFER_PARAMS *ppkt_ctx_dstq;
+	u16 idx_ctx_dstq_head;
+	u16 idx_ctx_dstq_tail;
+
+	spinlock_t  pending_list_lock; /* For handling dma pending_list */
+	struct list_head pending_list;
+	spinlock_t  active_list_lock; /* For handling dma active_list */
+	struct list_head active_list;
+
+	spinlock_t pending_interrupts_lock; /* For dma pending interrupts list*/
+	struct list_head pending_interrupts_list;
+	spinlock_t active_interrupts_lock;  /* For dma active interrupts list*/
+	struct list_head active_interrupts_list;
+
+	mempool_t *transactions_pool;
+	mempool_t *tx_elements_pool;
+	mempool_t *intr_transactions_pool;
+
+	struct workqueue_struct *sw_intrs_wrkq;
+	struct work_struct handle_sw_intrs;
+
+	struct workqueue_struct *maintenance_workq;
+	struct work_struct handle_chan_reset;
+	struct work_struct handle_chan_shutdown;
+	struct work_struct handle_chan_terminate;
+
+	struct completion chan_shutdown_complt;
+	struct completion chan_terminate_complete;
+
+	struct workqueue_struct *primary_desc_cleanup;
+	struct work_struct handle_primary_desc_cleanup;
+
+	struct workqueue_struct *chan_programming;
+	struct work_struct handle_chan_programming;
+
+	struct workqueue_struct *srcq_desc_cleanup;
+	struct work_struct handle_srcq_desc_cleanup;
+	struct completion srcq_work_complete;
+
+	struct workqueue_struct *dstq_desc_cleanup;
+	struct work_struct handle_dstq_desc_cleanup;
+	struct completion dstq_work_complete;
+};
+
+/*
+ * struct xlnx_pcie_dma_device - Driver specific platform device structure
+ * @is_rootdma: Indicates whether the dma instance is root port dma
+ * @dma_buf_ext_addr: Indicates whether target system is 32 bit or 64 bit
+ * @bar_mask: Indicates available pcie bars
+ * @board_number: Count value of platform device
+ * @dev: Device structure pointer for pcie device
+ * @channels: Pointer to device DMA channels structure
+ * @common: DMA device structure
+ * @num_channels: Number of channels active for the device
+ * @reg_base: Base address of first DMA channel of the device
+ * @irq_vecs: Number of irq vectors allocated to pci device
+ * @pci_dev: Parent pci device which created this platform device
+ * @bar_info: PCIe bar related information
+ * @platform_irq_vec: Platform irq vector number for root dma
+ * @rootdma_vendor: PCI Vendor id for root dma
+ * @rootdma_device: PCI Device id for root dma
+ */
+struct xlnx_pcie_dma_device {
+	bool is_rootdma;
+	bool dma_buf_ext_addr;
+	u32 bar_mask;
+	u16 board_number;
+	struct device *dev;
+	struct ps_pcie_dma_chan *channels;
+	struct dma_device common;
+	int num_channels;
+	int irq_vecs;
+	void __iomem *reg_base;
+	struct pci_dev *pci_dev;
+	struct BAR_PARAMS bar_info[MAX_BARS];
+	int platform_irq_vec;
+	u16 rootdma_vendor;
+	u16 rootdma_device;
+};
+
+#define to_xilinx_chan(chan) \
+	container_of(chan, struct ps_pcie_dma_chan, common)
+#define to_ps_pcie_dma_tx_descriptor(tx) \
+	container_of(tx, struct ps_pcie_tx_segment, async_tx)
+#define to_ps_pcie_dma_tx_intr_descriptor(tx) \
+	container_of(tx, struct ps_pcie_intr_segment, async_intr_tx)
+
+/* Function Protypes */
+static u32 ps_pcie_dma_read(struct ps_pcie_dma_chan *chan, u32 reg);
+static void ps_pcie_dma_write(struct ps_pcie_dma_chan *chan, u32 reg,
+			      u32 value);
+static void ps_pcie_dma_clr_mask(struct ps_pcie_dma_chan *chan, u32 reg,
+				 u32 mask);
+static void ps_pcie_dma_set_mask(struct ps_pcie_dma_chan *chan, u32 reg,
+				 u32 mask);
+static int irq_setup(struct xlnx_pcie_dma_device *xdev);
+static int platform_irq_setup(struct xlnx_pcie_dma_device *xdev);
+static int chan_intr_setup(struct xlnx_pcie_dma_device *xdev);
+static int device_intr_setup(struct xlnx_pcie_dma_device *xdev);
+static int irq_probe(struct xlnx_pcie_dma_device *xdev);
+static int ps_pcie_check_intr_status(struct ps_pcie_dma_chan *chan);
+static irqreturn_t ps_pcie_dma_dev_intr_handler(int irq, void *data);
+static irqreturn_t ps_pcie_dma_chan_intr_handler(int irq, void *data);
+static int init_hw_components(struct ps_pcie_dma_chan *chan);
+static int init_sw_components(struct ps_pcie_dma_chan *chan);
+static void update_channel_read_attribute(struct ps_pcie_dma_chan *chan);
+static void update_channel_write_attribute(struct ps_pcie_dma_chan *chan);
+static void ps_pcie_chan_reset(struct ps_pcie_dma_chan *chan);
+static void poll_completed_transactions(struct timer_list *t);
+static bool check_descriptors_for_two_queues(struct ps_pcie_dma_chan *chan,
+					     struct ps_pcie_tx_segment *seg);
+static bool check_descriptors_for_all_queues(struct ps_pcie_dma_chan *chan,
+					     struct ps_pcie_tx_segment *seg);
+static bool check_descriptor_availability(struct ps_pcie_dma_chan *chan,
+					  struct ps_pcie_tx_segment *seg);
+static void handle_error(struct ps_pcie_dma_chan *chan);
+static void xlnx_ps_pcie_update_srcq(struct ps_pcie_dma_chan *chan,
+				     struct ps_pcie_tx_segment *seg);
+static void xlnx_ps_pcie_update_dstq(struct ps_pcie_dma_chan *chan,
+				     struct ps_pcie_tx_segment *seg);
+static void ps_pcie_chan_program_work(struct work_struct *work);
+static void dst_cleanup_work(struct work_struct *work);
+static void src_cleanup_work(struct work_struct *work);
+static void ps_pcie_chan_primary_work(struct work_struct *work);
+static int probe_channel_properties(struct platform_device *platform_dev,
+				    struct xlnx_pcie_dma_device *xdev,
+				    u16 channel_number);
+static void xlnx_ps_pcie_destroy_mempool(struct ps_pcie_dma_chan *chan);
+static void xlnx_ps_pcie_free_worker_queues(struct ps_pcie_dma_chan *chan);
+static void xlnx_ps_pcie_free_pkt_ctxts(struct ps_pcie_dma_chan *chan);
+static void xlnx_ps_pcie_free_descriptors(struct ps_pcie_dma_chan *chan);
+static int xlnx_ps_pcie_channel_activate(struct ps_pcie_dma_chan *chan);
+static void xlnx_ps_pcie_channel_quiesce(struct ps_pcie_dma_chan *chan);
+static void ivk_cbk_for_pending(struct ps_pcie_dma_chan *chan);
+static void xlnx_ps_pcie_reset_channel(struct ps_pcie_dma_chan *chan);
+static void xlnx_ps_pcie_free_poll_timer(struct ps_pcie_dma_chan *chan);
+static int xlnx_ps_pcie_alloc_poll_timer(struct ps_pcie_dma_chan *chan);
+static void terminate_transactions_work(struct work_struct *work);
+static void chan_shutdown_work(struct work_struct *work);
+static void chan_reset_work(struct work_struct *work);
+static int xlnx_ps_pcie_alloc_worker_threads(struct ps_pcie_dma_chan *chan);
+static int xlnx_ps_pcie_alloc_mempool(struct ps_pcie_dma_chan *chan);
+static int xlnx_ps_pcie_alloc_pkt_contexts(struct ps_pcie_dma_chan *chan);
+static int dma_alloc_descriptors_two_queues(struct ps_pcie_dma_chan *chan);
+static int dma_alloc_decriptors_all_queues(struct ps_pcie_dma_chan *chan);
+static void xlnx_ps_pcie_dma_free_chan_resources(struct dma_chan *dchan);
+static int xlnx_ps_pcie_dma_alloc_chan_resources(struct dma_chan *dchan);
+static dma_cookie_t xilinx_dma_tx_submit(struct dma_async_tx_descriptor *tx);
+static dma_cookie_t xilinx_intr_tx_submit(struct dma_async_tx_descriptor *tx);
+static struct dma_async_tx_descriptor *
+xlnx_ps_pcie_dma_prep_memcpy(struct dma_chan *channel, dma_addr_t dma_dst,
+			     dma_addr_t dma_src, size_t len,
+			     unsigned long flags);
+static struct dma_async_tx_descriptor *xlnx_ps_pcie_dma_prep_slave_sg(
+		struct dma_chan *channel, struct scatterlist *sgl,
+		unsigned int sg_len, enum dma_transfer_direction direction,
+		unsigned long flags, void *context);
+static struct dma_async_tx_descriptor *xlnx_ps_pcie_dma_prep_interrupt(
+		struct dma_chan *channel, unsigned long flags);
+static void xlnx_ps_pcie_dma_issue_pending(struct dma_chan *channel);
+static int xlnx_ps_pcie_dma_terminate_all(struct dma_chan *channel);
+static int read_rootdma_config(struct platform_device *platform_dev,
+			       struct xlnx_pcie_dma_device *xdev);
+static int read_epdma_config(struct platform_device *platform_dev,
+			     struct xlnx_pcie_dma_device *xdev);
+static int xlnx_pcie_dma_driver_probe(struct platform_device *platform_dev);
+static int xlnx_pcie_dma_driver_remove(struct platform_device *platform_dev);
+
+/* IO accessors */
+static inline u32 ps_pcie_dma_read(struct ps_pcie_dma_chan *chan, u32 reg)
+{
+	return ioread32((void __iomem *)((char *)(chan->chan_base) + reg));
+}
+
+static inline void ps_pcie_dma_write(struct ps_pcie_dma_chan *chan, u32 reg,
+				     u32 value)
+{
+	iowrite32(value, (void __iomem *)((char *)(chan->chan_base) + reg));
+}
+
+static inline void ps_pcie_dma_clr_mask(struct ps_pcie_dma_chan *chan, u32 reg,
+					u32 mask)
+{
+	ps_pcie_dma_write(chan, reg, ps_pcie_dma_read(chan, reg) & ~mask);
+}
+
+static inline void ps_pcie_dma_set_mask(struct ps_pcie_dma_chan *chan, u32 reg,
+					u32 mask)
+{
+	ps_pcie_dma_write(chan, reg, ps_pcie_dma_read(chan, reg) | mask);
+}
+
+/**
+ * ps_pcie_dma_dev_intr_handler - This will be invoked for MSI/Legacy interrupts
+ *
+ * @irq: IRQ number
+ * @data: Pointer to the PS PCIe DMA channel structure
+ *
+ * Return: IRQ_HANDLED/IRQ_NONE
+ */
+static irqreturn_t ps_pcie_dma_dev_intr_handler(int irq, void *data)
+{
+	struct xlnx_pcie_dma_device *xdev =
+		(struct xlnx_pcie_dma_device *)data;
+	struct ps_pcie_dma_chan *chan = NULL;
+	int i;
+	int err = -1;
+	int ret = -1;
+
+	for (i = 0; i < xdev->num_channels; i++) {
+		chan = &xdev->channels[i];
+		err = ps_pcie_check_intr_status(chan);
+		if (err == 0)
+			ret = 0;
+	}
+
+	return (ret == 0) ? IRQ_HANDLED : IRQ_NONE;
+}
+
+/**
+ * ps_pcie_dma_chan_intr_handler - This will be invoked for MSI-X interrupts
+ *
+ * @irq: IRQ number
+ * @data: Pointer to the PS PCIe DMA channel structure
+ *
+ * Return: IRQ_HANDLED
+ */
+static irqreturn_t ps_pcie_dma_chan_intr_handler(int irq, void *data)
+{
+	struct ps_pcie_dma_chan *chan = (struct ps_pcie_dma_chan *)data;
+
+	ps_pcie_check_intr_status(chan);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * chan_intr_setup - Requests Interrupt handler for individual channels
+ *
+ * @xdev: Driver specific data for device
+ *
+ * Return: 0 on success and non zero value on failure.
+ */
+static int chan_intr_setup(struct xlnx_pcie_dma_device *xdev)
+{
+	struct ps_pcie_dma_chan *chan;
+	int i;
+	int err = 0;
+
+	for (i = 0; i < xdev->num_channels; i++) {
+		chan = &xdev->channels[i];
+		err = devm_request_irq(xdev->dev,
+				       pci_irq_vector(xdev->pci_dev, i),
+				       ps_pcie_dma_chan_intr_handler,
+				       PS_PCIE_DMA_IRQ_NOSHARE,
+				       "PS PCIe DMA Chan Intr handler", chan);
+		if (err) {
+			dev_err(xdev->dev,
+				"Irq %d for chan %d error %d\n",
+				pci_irq_vector(xdev->pci_dev, i),
+				chan->channel_number, err);
+			break;
+		}
+	}
+
+	if (err) {
+		while (--i >= 0) {
+			chan = &xdev->channels[i];
+			devm_free_irq(xdev->dev,
+				      pci_irq_vector(xdev->pci_dev, i), chan);
+		}
+	}
+
+	return err;
+}
+
+/**
+ * device_intr_setup - Requests interrupt handler for DMA device
+ *
+ * @xdev: Driver specific data for device
+ *
+ * Return: 0 on success and non zero value on failure.
+ */
+static int device_intr_setup(struct xlnx_pcie_dma_device *xdev)
+{
+	int err;
+	unsigned long intr_flags = IRQF_SHARED;
+
+	if (xdev->pci_dev->msix_enabled || xdev->pci_dev->msi_enabled)
+		intr_flags = PS_PCIE_DMA_IRQ_NOSHARE;
+
+	err = devm_request_irq(xdev->dev,
+			       pci_irq_vector(xdev->pci_dev, 0),
+			       ps_pcie_dma_dev_intr_handler,
+			       intr_flags,
+			       "PS PCIe DMA Intr Handler", xdev);
+	if (err)
+		dev_err(xdev->dev, "Couldn't request irq %d\n",
+			pci_irq_vector(xdev->pci_dev, 0));
+
+	return err;
+}
+
+/**
+ * irq_setup - Requests interrupts based on the interrupt type detected
+ *
+ * @xdev: Driver specific data for device
+ *
+ * Return: 0 on success and non zero value on failure.
+ */
+static int irq_setup(struct xlnx_pcie_dma_device *xdev)
+{
+	int err;
+
+	if (xdev->irq_vecs == xdev->num_channels)
+		err = chan_intr_setup(xdev);
+	else
+		err = device_intr_setup(xdev);
+
+	return err;
+}
+
+static int platform_irq_setup(struct xlnx_pcie_dma_device *xdev)
+{
+	int err;
+
+	err = devm_request_irq(xdev->dev,
+			       xdev->platform_irq_vec,
+			       ps_pcie_dma_dev_intr_handler,
+			       IRQF_SHARED,
+			       "PS PCIe Root DMA Handler", xdev);
+	if (err)
+		dev_err(xdev->dev, "Couldn't request irq %d\n",
+			xdev->platform_irq_vec);
+
+	return err;
+}
+
+/**
+ * irq_probe - Checks which interrupt types can be serviced by hardware
+ *
+ * @xdev: Driver specific data for device
+ *
+ * Return: Number of interrupt vectors when successful or -ENOSPC on failure
+ */
+static int irq_probe(struct xlnx_pcie_dma_device *xdev)
+{
+	struct pci_dev *pdev;
+
+	pdev = xdev->pci_dev;
+
+	xdev->irq_vecs = pci_alloc_irq_vectors(pdev, 1, xdev->num_channels,
+					       PCI_IRQ_ALL_TYPES);
+	return xdev->irq_vecs;
+}
+
+/**
+ * ps_pcie_check_intr_status - Checks channel interrupt status
+ *
+ * @chan: Pointer to the PS PCIe DMA channel structure
+ *
+ * Return: 0 if interrupt is pending on channel
+ *		   -1 if no interrupt is pending on channel
+ */
+static int ps_pcie_check_intr_status(struct ps_pcie_dma_chan *chan)
+{
+	int err = -1;
+	u32 status;
+
+	if (chan->state != CHANNEL_AVAILABLE)
+		return err;
+
+	status = ps_pcie_dma_read(chan, chan->intr_status_offset);
+
+	if (status & DMA_INTSTATUS_SGLINTR_BIT) {
+		if (chan->primary_desc_cleanup) {
+			queue_work(chan->primary_desc_cleanup,
+				   &chan->handle_primary_desc_cleanup);
+		}
+		/* Clearing Persistent bit */
+		ps_pcie_dma_set_mask(chan, chan->intr_status_offset,
+				     DMA_INTSTATUS_SGLINTR_BIT);
+		err = 0;
+	}
+
+	if (status & DMA_INTSTATUS_SWINTR_BIT) {
+		if (chan->sw_intrs_wrkq)
+			queue_work(chan->sw_intrs_wrkq, &chan->handle_sw_intrs);
+		/* Clearing Persistent bit */
+		ps_pcie_dma_set_mask(chan, chan->intr_status_offset,
+				     DMA_INTSTATUS_SWINTR_BIT);
+		err = 0;
+	}
+
+	if (status & DMA_INTSTATUS_DMAERR_BIT) {
+		dev_err(chan->dev,
+			"DMA Channel %d ControlStatus Reg: 0x%x",
+			chan->channel_number, status);
+		dev_err(chan->dev,
+			"Chn %d SrcQLmt = %d SrcQSz = %d SrcQNxt = %d",
+			chan->channel_number,
+			chan->chan_base->src_q_limit,
+			chan->chan_base->src_q_size,
+			chan->chan_base->src_q_next);
+		dev_err(chan->dev,
+			"Chn %d SrcStaLmt = %d SrcStaSz = %d SrcStaNxt = %d",
+			chan->channel_number,
+			chan->chan_base->stas_q_limit,
+			chan->chan_base->stas_q_size,
+			chan->chan_base->stas_q_next);
+		dev_err(chan->dev,
+			"Chn %d DstQLmt = %d DstQSz = %d DstQNxt = %d",
+			chan->channel_number,
+			chan->chan_base->dst_q_limit,
+			chan->chan_base->dst_q_size,
+			chan->chan_base->dst_q_next);
+		dev_err(chan->dev,
+			"Chan %d DstStaLmt = %d DstStaSz = %d DstStaNxt = %d",
+			chan->channel_number,
+			chan->chan_base->stad_q_limit,
+			chan->chan_base->stad_q_size,
+			chan->chan_base->stad_q_next);
+		/* Clearing Persistent bit */
+		ps_pcie_dma_set_mask(chan, chan->intr_status_offset,
+				     DMA_INTSTATUS_DMAERR_BIT);
+
+		handle_error(chan);
+
+		err = 0;
+	}
+
+	return err;
+}
+
+static int init_hw_components(struct ps_pcie_dma_chan *chan)
+{
+	if (chan->psrc_sgl_bd && chan->psrc_sta_bd) {
+		/*  Programming SourceQ and StatusQ bd addresses */
+		chan->chan_base->src_q_next = 0;
+		chan->chan_base->src_q_high =
+			upper_32_bits(chan->src_sgl_bd_pa);
+		chan->chan_base->src_q_size = chan->total_descriptors;
+		chan->chan_base->src_q_limit = 0;
+		if (chan->xdev->is_rootdma) {
+			chan->chan_base->src_q_low = ROOTDMA_Q_READ_ATTRIBUTE
+						     | DMA_QPTRLO_QLOCAXI_BIT;
+		} else {
+			chan->chan_base->src_q_low = 0;
+		}
+		chan->chan_base->src_q_low |=
+			(lower_32_bits((chan->src_sgl_bd_pa))
+			 & ~(DMA_SRC_Q_LOW_BIT_SHIFT))
+			| DMA_QPTRLO_Q_ENABLE_BIT;
+
+		chan->chan_base->stas_q_next = 0;
+		chan->chan_base->stas_q_high =
+			upper_32_bits(chan->src_sta_bd_pa);
+		chan->chan_base->stas_q_size = chan->total_descriptors;
+		chan->chan_base->stas_q_limit = chan->total_descriptors - 1;
+		if (chan->xdev->is_rootdma) {
+			chan->chan_base->stas_q_low = ROOTDMA_Q_READ_ATTRIBUTE
+						      | DMA_QPTRLO_QLOCAXI_BIT;
+		} else {
+			chan->chan_base->stas_q_low = 0;
+		}
+		chan->chan_base->stas_q_low |=
+			(lower_32_bits(chan->src_sta_bd_pa)
+			 & ~(DMA_SRC_Q_LOW_BIT_SHIFT))
+			| DMA_QPTRLO_Q_ENABLE_BIT;
+	}
+
+	if (chan->pdst_sgl_bd && chan->pdst_sta_bd) {
+		/*  Programming DestinationQ and StatusQ buffer descriptors */
+		chan->chan_base->dst_q_next = 0;
+		chan->chan_base->dst_q_high =
+			upper_32_bits(chan->dst_sgl_bd_pa);
+		chan->chan_base->dst_q_size = chan->total_descriptors;
+		chan->chan_base->dst_q_limit = 0;
+		if (chan->xdev->is_rootdma) {
+			chan->chan_base->dst_q_low = ROOTDMA_Q_READ_ATTRIBUTE
+						     | DMA_QPTRLO_QLOCAXI_BIT;
+		} else {
+			chan->chan_base->dst_q_low = 0;
+		}
+		chan->chan_base->dst_q_low |=
+			(lower_32_bits(chan->dst_sgl_bd_pa)
+			 & ~(DMA_SRC_Q_LOW_BIT_SHIFT))
+			| DMA_QPTRLO_Q_ENABLE_BIT;
+
+		chan->chan_base->stad_q_next = 0;
+		chan->chan_base->stad_q_high =
+			upper_32_bits(chan->dst_sta_bd_pa);
+		chan->chan_base->stad_q_size = chan->total_descriptors;
+		chan->chan_base->stad_q_limit = chan->total_descriptors - 1;
+		if (chan->xdev->is_rootdma) {
+			chan->chan_base->stad_q_low = ROOTDMA_Q_READ_ATTRIBUTE
+						      | DMA_QPTRLO_QLOCAXI_BIT;
+		} else {
+			chan->chan_base->stad_q_low = 0;
+		}
+		chan->chan_base->stad_q_low |=
+			(lower_32_bits(chan->dst_sta_bd_pa)
+			 & ~(DMA_SRC_Q_LOW_BIT_SHIFT))
+			| DMA_QPTRLO_Q_ENABLE_BIT;
+	}
+
+	return 0;
+}
+
+static void update_channel_read_attribute(struct ps_pcie_dma_chan *chan)
+{
+	if (chan->xdev->is_rootdma) {
+		/* For Root DMA, Host Memory and Buffer Descriptors
+		 * will be on AXI side
+		 */
+		if (chan->srcq_buffer_location == BUFFER_LOC_PCI) {
+			chan->read_attribute = (AXI_ATTRIBUTE <<
+						SRC_CTL_ATTRIB_BIT_SHIFT) |
+						SOURCE_CONTROL_BD_LOC_AXI;
+		} else if (chan->srcq_buffer_location == BUFFER_LOC_AXI) {
+			chan->read_attribute = AXI_ATTRIBUTE <<
+					       SRC_CTL_ATTRIB_BIT_SHIFT;
+		}
+	} else {
+		if (chan->srcq_buffer_location == BUFFER_LOC_PCI) {
+			chan->read_attribute = PCI_ATTRIBUTE <<
+					       SRC_CTL_ATTRIB_BIT_SHIFT;
+		} else if (chan->srcq_buffer_location == BUFFER_LOC_AXI) {
+			chan->read_attribute = (AXI_ATTRIBUTE <<
+						SRC_CTL_ATTRIB_BIT_SHIFT) |
+						SOURCE_CONTROL_BD_LOC_AXI;
+		}
+	}
+}
+
+static void update_channel_write_attribute(struct ps_pcie_dma_chan *chan)
+{
+	if (chan->xdev->is_rootdma) {
+		/* For Root DMA, Host Memory and Buffer Descriptors
+		 * will be on AXI side
+		 */
+		if (chan->dstq_buffer_location == BUFFER_LOC_PCI) {
+			chan->write_attribute = (AXI_ATTRIBUTE <<
+						 SRC_CTL_ATTRIB_BIT_SHIFT) |
+						SOURCE_CONTROL_BD_LOC_AXI;
+		} else if (chan->srcq_buffer_location == BUFFER_LOC_AXI) {
+			chan->write_attribute = AXI_ATTRIBUTE <<
+						SRC_CTL_ATTRIB_BIT_SHIFT;
+		}
+	} else {
+		if (chan->dstq_buffer_location == BUFFER_LOC_PCI) {
+			chan->write_attribute = PCI_ATTRIBUTE <<
+						SRC_CTL_ATTRIB_BIT_SHIFT;
+		} else if (chan->dstq_buffer_location == BUFFER_LOC_AXI) {
+			chan->write_attribute = (AXI_ATTRIBUTE <<
+						 SRC_CTL_ATTRIB_BIT_SHIFT) |
+						SOURCE_CONTROL_BD_LOC_AXI;
+		}
+	}
+	chan->write_attribute |= SOURCE_CONTROL_BACK_TO_BACK_PACK_BIT;
+}
+
+static int init_sw_components(struct ps_pcie_dma_chan *chan)
+{
+	if (chan->ppkt_ctx_srcq && chan->psrc_sgl_bd &&
+	    chan->psrc_sta_bd) {
+		memset(chan->ppkt_ctx_srcq, 0,
+		       sizeof(struct PACKET_TRANSFER_PARAMS)
+		       * chan->total_descriptors);
+
+		memset(chan->psrc_sgl_bd, 0,
+		       sizeof(struct SOURCE_DMA_DESCRIPTOR)
+		       * chan->total_descriptors);
+
+		memset(chan->psrc_sta_bd, 0,
+		       sizeof(struct STATUS_DMA_DESCRIPTOR)
+		       * chan->total_descriptors);
+
+		chan->src_avail_descriptors = chan->total_descriptors;
+
+		chan->src_sgl_freeidx = 0;
+		chan->src_staprobe_idx = 0;
+		chan->src_sta_hw_probe_idx = chan->total_descriptors - 1;
+		chan->idx_ctx_srcq_head = 0;
+		chan->idx_ctx_srcq_tail = 0;
+	}
+
+	if (chan->ppkt_ctx_dstq && chan->pdst_sgl_bd &&
+	    chan->pdst_sta_bd) {
+		memset(chan->ppkt_ctx_dstq, 0,
+		       sizeof(struct PACKET_TRANSFER_PARAMS)
+		       * chan->total_descriptors);
+
+		memset(chan->pdst_sgl_bd, 0,
+		       sizeof(struct DEST_DMA_DESCRIPTOR)
+		       * chan->total_descriptors);
+
+		memset(chan->pdst_sta_bd, 0,
+		       sizeof(struct STATUS_DMA_DESCRIPTOR)
+		       * chan->total_descriptors);
+
+		chan->dst_avail_descriptors = chan->total_descriptors;
+
+		chan->dst_sgl_freeidx = 0;
+		chan->dst_staprobe_idx = 0;
+		chan->dst_sta_hw_probe_idx = chan->total_descriptors - 1;
+		chan->idx_ctx_dstq_head = 0;
+		chan->idx_ctx_dstq_tail = 0;
+	}
+
+	return 0;
+}
+
+/**
+ * ps_pcie_chan_reset - Resets channel, by programming relevant registers
+ *
+ * @chan: PS PCIe DMA channel information holder
+ * Return: void
+ */
+static void ps_pcie_chan_reset(struct ps_pcie_dma_chan *chan)
+{
+	/* Enable channel reset */
+	ps_pcie_dma_set_mask(chan, DMA_CNTRL_REG_OFFSET, DMA_CNTRL_RST_BIT);
+
+	mdelay(10);
+
+	/* Disable channel reset */
+	ps_pcie_dma_clr_mask(chan, DMA_CNTRL_REG_OFFSET, DMA_CNTRL_RST_BIT);
+}
+
+/**
+ * poll_completed_transactions - Function invoked by poll timer
+ *
+ * @t: Pointer to timer triggering this callback
+ * Return: void
+ */
+static void poll_completed_transactions(struct timer_list *t)
+{
+	struct ps_pcie_dma_chan *chan = from_timer(chan, t, poll_timer);
+
+	if (chan->state == CHANNEL_AVAILABLE) {
+		queue_work(chan->primary_desc_cleanup,
+			   &chan->handle_primary_desc_cleanup);
+	}
+
+	mod_timer(&chan->poll_timer, jiffies + chan->poll_timer_freq);
+}
+
+static bool check_descriptors_for_two_queues(struct ps_pcie_dma_chan *chan,
+					     struct ps_pcie_tx_segment *seg)
+{
+	if (seg->src_elements) {
+		if (chan->src_avail_descriptors >=
+		    seg->src_elements) {
+			return true;
+		}
+	} else if (seg->dst_elements) {
+		if (chan->dst_avail_descriptors >=
+		    seg->dst_elements) {
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static bool check_descriptors_for_all_queues(struct ps_pcie_dma_chan *chan,
+					     struct ps_pcie_tx_segment *seg)
+{
+	if (chan->src_avail_descriptors >=
+		seg->src_elements &&
+	    chan->dst_avail_descriptors >=
+		seg->dst_elements) {
+		return true;
+	}
+
+	return false;
+}
+
+static bool check_descriptor_availability(struct ps_pcie_dma_chan *chan,
+					  struct ps_pcie_tx_segment *seg)
+{
+	if (chan->num_queues == DEFAULT_DMA_QUEUES)
+		return check_descriptors_for_all_queues(chan, seg);
+	else
+		return check_descriptors_for_two_queues(chan, seg);
+}
+
+static void handle_error(struct ps_pcie_dma_chan *chan)
+{
+	if (chan->state != CHANNEL_AVAILABLE)
+		return;
+
+	spin_lock(&chan->channel_lock);
+	chan->state = CHANNEL_ERROR;
+	spin_unlock(&chan->channel_lock);
+
+	if (chan->maintenance_workq)
+		queue_work(chan->maintenance_workq, &chan->handle_chan_reset);
+}
+
+static void xlnx_ps_pcie_update_srcq(struct ps_pcie_dma_chan *chan,
+				     struct ps_pcie_tx_segment *seg)
+{
+	struct SOURCE_DMA_DESCRIPTOR *pdesc;
+	struct PACKET_TRANSFER_PARAMS *pkt_ctx = NULL;
+	struct ps_pcie_transfer_elements *ele = NULL;
+	u32 i = 0;
+
+	pkt_ctx = chan->ppkt_ctx_srcq + chan->idx_ctx_srcq_head;
+	if (pkt_ctx->availability_status == IN_USE) {
+		dev_err(chan->dev,
+			"src pkt context not avail for channel %d\n",
+			chan->channel_number);
+		handle_error(chan);
+		return;
+	}
+
+	pkt_ctx->availability_status = IN_USE;
+
+	if (chan->srcq_buffer_location == BUFFER_LOC_PCI)
+		pkt_ctx->seg = seg;
+
+	/*  Get the address of the next available DMA Descriptor */
+	pdesc = chan->psrc_sgl_bd + chan->src_sgl_freeidx;
+	pkt_ctx->idx_sop = chan->src_sgl_freeidx;
+
+	/* Build transactions using information in the scatter gather list */
+	list_for_each_entry(ele, &seg->transfer_nodes, node) {
+		if (chan->xdev->dma_buf_ext_addr) {
+			pdesc->system_address =
+				(u64)ele->src_pa;
+		} else {
+			pdesc->system_address =
+				(u32)ele->src_pa;
+		}
+
+		pdesc->control_byte_count = (ele->transfer_bytes &
+					    SOURCE_CONTROL_BD_BYTE_COUNT_MASK) |
+					    chan->read_attribute;
+
+		pdesc->user_handle = chan->idx_ctx_srcq_head;
+		pdesc->user_id = DEFAULT_UID;
+		/* Check if this is last descriptor */
+		if (i == (seg->src_elements - 1)) {
+			pkt_ctx->idx_eop = chan->src_sgl_freeidx;
+			pdesc->control_byte_count |= SOURCE_CONTROL_BD_EOP_BIT;
+			if ((seg->async_tx.flags & DMA_PREP_INTERRUPT) ==
+						   DMA_PREP_INTERRUPT) {
+				pdesc->control_byte_count |=
+					SOURCE_CONTROL_BD_INTR_BIT;
+			}
+		}
+		chan->src_sgl_freeidx++;
+		if (chan->src_sgl_freeidx == chan->total_descriptors)
+			chan->src_sgl_freeidx = 0;
+		pdesc = chan->psrc_sgl_bd + chan->src_sgl_freeidx;
+		spin_lock(&chan->src_desc_lock);
+		chan->src_avail_descriptors--;
+		spin_unlock(&chan->src_desc_lock);
+		i++;
+	}
+
+	chan->chan_base->src_q_limit = chan->src_sgl_freeidx;
+	chan->idx_ctx_srcq_head++;
+	if (chan->idx_ctx_srcq_head == chan->total_descriptors)
+		chan->idx_ctx_srcq_head = 0;
+}
+
+static void xlnx_ps_pcie_update_dstq(struct ps_pcie_dma_chan *chan,
+				     struct ps_pcie_tx_segment *seg)
+{
+	struct DEST_DMA_DESCRIPTOR *pdesc;
+	struct PACKET_TRANSFER_PARAMS *pkt_ctx = NULL;
+	struct ps_pcie_transfer_elements *ele = NULL;
+	u32 i = 0;
+
+	pkt_ctx = chan->ppkt_ctx_dstq + chan->idx_ctx_dstq_head;
+	if (pkt_ctx->availability_status == IN_USE) {
+		dev_err(chan->dev,
+			"dst pkt context not avail for channel %d\n",
+			chan->channel_number);
+		handle_error(chan);
+
+		return;
+	}
+
+	pkt_ctx->availability_status = IN_USE;
+
+	if (chan->dstq_buffer_location == BUFFER_LOC_PCI)
+		pkt_ctx->seg = seg;
+
+	pdesc = chan->pdst_sgl_bd + chan->dst_sgl_freeidx;
+	pkt_ctx->idx_sop = chan->dst_sgl_freeidx;
+
+	/* Build transactions using information in the scatter gather list */
+	list_for_each_entry(ele, &seg->transfer_nodes, node) {
+		if (chan->xdev->dma_buf_ext_addr) {
+			pdesc->system_address =
+				(u64)ele->dst_pa;
+		} else {
+			pdesc->system_address =
+				(u32)ele->dst_pa;
+		}
+		pdesc->control_byte_count = (ele->transfer_bytes &
+					SOURCE_CONTROL_BD_BYTE_COUNT_MASK) |
+						chan->write_attribute;
+
+		pdesc->user_handle = chan->idx_ctx_dstq_head;
+		/* Check if this is last descriptor */
+		if (i == (seg->dst_elements - 1))
+			pkt_ctx->idx_eop = chan->dst_sgl_freeidx;
+		chan->dst_sgl_freeidx++;
+		if (chan->dst_sgl_freeidx == chan->total_descriptors)
+			chan->dst_sgl_freeidx = 0;
+		pdesc = chan->pdst_sgl_bd + chan->dst_sgl_freeidx;
+		spin_lock(&chan->dst_desc_lock);
+		chan->dst_avail_descriptors--;
+		spin_unlock(&chan->dst_desc_lock);
+		i++;
+	}
+
+	chan->chan_base->dst_q_limit = chan->dst_sgl_freeidx;
+	chan->idx_ctx_dstq_head++;
+	if (chan->idx_ctx_dstq_head == chan->total_descriptors)
+		chan->idx_ctx_dstq_head = 0;
+}
+
+static void ps_pcie_chan_program_work(struct work_struct *work)
+{
+	struct ps_pcie_dma_chan *chan =
+		(struct ps_pcie_dma_chan *)container_of(work,
+				struct ps_pcie_dma_chan,
+				handle_chan_programming);
+	struct ps_pcie_tx_segment *seg = NULL;
+
+	while (chan->state == CHANNEL_AVAILABLE) {
+		spin_lock(&chan->active_list_lock);
+		seg = list_first_entry_or_null(&chan->active_list,
+					       struct ps_pcie_tx_segment, node);
+		spin_unlock(&chan->active_list_lock);
+
+		if (!seg)
+			break;
+
+		if (check_descriptor_availability(chan, seg) == false)
+			break;
+
+		spin_lock(&chan->active_list_lock);
+		list_del(&seg->node);
+		spin_unlock(&chan->active_list_lock);
+
+		if (seg->src_elements)
+			xlnx_ps_pcie_update_srcq(chan, seg);
+
+		if (seg->dst_elements)
+			xlnx_ps_pcie_update_dstq(chan, seg);
+	}
+}
+
+/**
+ * dst_cleanup_work - Goes through all completed elements in status Q
+ * and invokes callbacks for the concerned DMA transaction.
+ *
+ * @work: Work associated with the task
+ *
+ * Return: void
+ */
+static void dst_cleanup_work(struct work_struct *work)
+{
+	struct ps_pcie_dma_chan *chan =
+		(struct ps_pcie_dma_chan *)container_of(work,
+			struct ps_pcie_dma_chan, handle_dstq_desc_cleanup);
+
+	struct STATUS_DMA_DESCRIPTOR *psta_bd;
+	struct DEST_DMA_DESCRIPTOR *pdst_bd;
+	struct PACKET_TRANSFER_PARAMS *ppkt_ctx;
+	struct dmaengine_result rslt;
+	u32 completed_bytes;
+	u32 dstq_desc_idx;
+	struct ps_pcie_transfer_elements *ele, *ele_nxt;
+
+	psta_bd = chan->pdst_sta_bd + chan->dst_staprobe_idx;
+
+	while (psta_bd->status_flag_byte_count & STA_BD_COMPLETED_BIT) {
+		if (psta_bd->status_flag_byte_count &
+				STA_BD_DESTINATION_ERROR_BIT) {
+			dev_err(chan->dev,
+				"Dst Sts Elmnt %d chan %d has Destination Err",
+				chan->dst_staprobe_idx + 1,
+				chan->channel_number);
+			handle_error(chan);
+			break;
+		}
+		if (psta_bd->status_flag_byte_count & STA_BD_SOURCE_ERROR_BIT) {
+			dev_err(chan->dev,
+				"Dst Sts Elmnt %d chan %d has Source Error",
+				chan->dst_staprobe_idx + 1,
+				chan->channel_number);
+			handle_error(chan);
+			break;
+		}
+		if (psta_bd->status_flag_byte_count &
+				STA_BD_INTERNAL_ERROR_BIT) {
+			dev_err(chan->dev,
+				"Dst Sts Elmnt %d chan %d has Internal Error",
+				chan->dst_staprobe_idx + 1,
+				chan->channel_number);
+			handle_error(chan);
+			break;
+		}
+		/* we are using 64 bit USER field. */
+		if ((psta_bd->status_flag_byte_count &
+					STA_BD_UPPER_STATUS_NONZERO_BIT) == 0) {
+			dev_err(chan->dev,
+				"Dst Sts Elmnt %d for chan %d has NON ZERO",
+				chan->dst_staprobe_idx + 1,
+				chan->channel_number);
+			handle_error(chan);
+			break;
+		}
+
+		chan->idx_ctx_dstq_tail = psta_bd->user_handle;
+		ppkt_ctx = chan->ppkt_ctx_dstq + chan->idx_ctx_dstq_tail;
+		completed_bytes = (psta_bd->status_flag_byte_count &
+					STA_BD_BYTE_COUNT_MASK) >>
+						STA_BD_BYTE_COUNT_SHIFT;
+
+		memset(psta_bd, 0, sizeof(struct STATUS_DMA_DESCRIPTOR));
+
+		chan->dst_staprobe_idx++;
+
+		if (chan->dst_staprobe_idx == chan->total_descriptors)
+			chan->dst_staprobe_idx = 0;
+
+		chan->dst_sta_hw_probe_idx++;
+
+		if (chan->dst_sta_hw_probe_idx == chan->total_descriptors)
+			chan->dst_sta_hw_probe_idx = 0;
+
+		chan->chan_base->stad_q_limit = chan->dst_sta_hw_probe_idx;
+
+		psta_bd = chan->pdst_sta_bd + chan->dst_staprobe_idx;
+
+		dstq_desc_idx = ppkt_ctx->idx_sop;
+
+		do {
+			pdst_bd = chan->pdst_sgl_bd + dstq_desc_idx;
+			memset(pdst_bd, 0,
+			       sizeof(struct DEST_DMA_DESCRIPTOR));
+
+			spin_lock(&chan->dst_desc_lock);
+			chan->dst_avail_descriptors++;
+			spin_unlock(&chan->dst_desc_lock);
+
+			if (dstq_desc_idx == ppkt_ctx->idx_eop)
+				break;
+
+			dstq_desc_idx++;
+
+			if (dstq_desc_idx == chan->total_descriptors)
+				dstq_desc_idx = 0;
+
+		} while (1);
+
+		/* Invoking callback */
+		if (ppkt_ctx->seg) {
+			spin_lock(&chan->cookie_lock);
+			dma_cookie_complete(&ppkt_ctx->seg->async_tx);
+			spin_unlock(&chan->cookie_lock);
+			rslt.result = DMA_TRANS_NOERROR;
+			rslt.residue = ppkt_ctx->seg->total_transfer_bytes -
+					completed_bytes;
+			dmaengine_desc_get_callback_invoke(&ppkt_ctx->seg->async_tx,
+							   &rslt);
+			list_for_each_entry_safe(ele, ele_nxt,
+						 &ppkt_ctx->seg->transfer_nodes,
+						 node) {
+				list_del(&ele->node);
+				mempool_free(ele, chan->tx_elements_pool);
+			}
+			mempool_free(ppkt_ctx->seg, chan->transactions_pool);
+		}
+		memset(ppkt_ctx, 0, sizeof(struct PACKET_TRANSFER_PARAMS));
+	}
+
+	complete(&chan->dstq_work_complete);
+}
+
+/**
+ * src_cleanup_work - Goes through all completed elements in status Q and
+ * invokes callbacks for the concerned DMA transaction.
+ *
+ * @work: Work associated with the task
+ *
+ * Return: void
+ */
+static void src_cleanup_work(struct work_struct *work)
+{
+	struct ps_pcie_dma_chan *chan =
+		(struct ps_pcie_dma_chan *)container_of(
+		work, struct ps_pcie_dma_chan, handle_srcq_desc_cleanup);
+
+	struct STATUS_DMA_DESCRIPTOR *psta_bd;
+	struct SOURCE_DMA_DESCRIPTOR *psrc_bd;
+	struct PACKET_TRANSFER_PARAMS *ppkt_ctx;
+	struct dmaengine_result rslt;
+	u32 completed_bytes;
+	u32 srcq_desc_idx;
+	struct ps_pcie_transfer_elements *ele, *ele_nxt;
+
+	psta_bd = chan->psrc_sta_bd + chan->src_staprobe_idx;
+
+	while (psta_bd->status_flag_byte_count & STA_BD_COMPLETED_BIT) {
+		if (psta_bd->status_flag_byte_count &
+				STA_BD_DESTINATION_ERROR_BIT) {
+			dev_err(chan->dev,
+				"Src Sts Elmnt %d chan %d has Dst Error",
+				chan->src_staprobe_idx + 1,
+				chan->channel_number);
+			handle_error(chan);
+			break;
+		}
+		if (psta_bd->status_flag_byte_count & STA_BD_SOURCE_ERROR_BIT) {
+			dev_err(chan->dev,
+				"Src Sts Elmnt %d chan %d has Source Error",
+				chan->src_staprobe_idx + 1,
+				chan->channel_number);
+			handle_error(chan);
+			break;
+		}
+		if (psta_bd->status_flag_byte_count &
+				STA_BD_INTERNAL_ERROR_BIT) {
+			dev_err(chan->dev,
+				"Src Sts Elmnt %d chan %d has Internal Error",
+				chan->src_staprobe_idx + 1,
+				chan->channel_number);
+			handle_error(chan);
+			break;
+		}
+		if ((psta_bd->status_flag_byte_count
+				& STA_BD_UPPER_STATUS_NONZERO_BIT) == 0) {
+			dev_err(chan->dev,
+				"Src Sts Elmnt %d chan %d has NonZero",
+				chan->src_staprobe_idx + 1,
+				chan->channel_number);
+			handle_error(chan);
+			break;
+		}
+		chan->idx_ctx_srcq_tail = psta_bd->user_handle;
+		ppkt_ctx = chan->ppkt_ctx_srcq + chan->idx_ctx_srcq_tail;
+		completed_bytes = (psta_bd->status_flag_byte_count
+					& STA_BD_BYTE_COUNT_MASK) >>
+						STA_BD_BYTE_COUNT_SHIFT;
+
+		memset(psta_bd, 0, sizeof(struct STATUS_DMA_DESCRIPTOR));
+
+		chan->src_staprobe_idx++;
+
+		if (chan->src_staprobe_idx == chan->total_descriptors)
+			chan->src_staprobe_idx = 0;
+
+		chan->src_sta_hw_probe_idx++;
+
+		if (chan->src_sta_hw_probe_idx == chan->total_descriptors)
+			chan->src_sta_hw_probe_idx = 0;
+
+		chan->chan_base->stas_q_limit = chan->src_sta_hw_probe_idx;
+
+		psta_bd = chan->psrc_sta_bd + chan->src_staprobe_idx;
+
+		srcq_desc_idx = ppkt_ctx->idx_sop;
+
+		do {
+			psrc_bd = chan->psrc_sgl_bd + srcq_desc_idx;
+			memset(psrc_bd, 0,
+			       sizeof(struct SOURCE_DMA_DESCRIPTOR));
+
+			spin_lock(&chan->src_desc_lock);
+			chan->src_avail_descriptors++;
+			spin_unlock(&chan->src_desc_lock);
+
+			if (srcq_desc_idx == ppkt_ctx->idx_eop)
+				break;
+			srcq_desc_idx++;
+
+			if (srcq_desc_idx == chan->total_descriptors)
+				srcq_desc_idx = 0;
+
+		} while (1);
+
+		/* Invoking callback */
+		if (ppkt_ctx->seg) {
+			spin_lock(&chan->cookie_lock);
+			dma_cookie_complete(&ppkt_ctx->seg->async_tx);
+			spin_unlock(&chan->cookie_lock);
+			rslt.result = DMA_TRANS_NOERROR;
+			rslt.residue = ppkt_ctx->seg->total_transfer_bytes -
+					completed_bytes;
+			dmaengine_desc_get_callback_invoke(&ppkt_ctx->seg->async_tx,
+							   &rslt);
+			list_for_each_entry_safe(ele, ele_nxt,
+						 &ppkt_ctx->seg->transfer_nodes,
+						 node) {
+				list_del(&ele->node);
+				mempool_free(ele, chan->tx_elements_pool);
+			}
+			mempool_free(ppkt_ctx->seg, chan->transactions_pool);
+		}
+		memset(ppkt_ctx, 0, sizeof(struct PACKET_TRANSFER_PARAMS));
+	}
+
+	complete(&chan->srcq_work_complete);
+}
+
+/**
+ * ps_pcie_chan_primary_work - Masks out interrupts, invokes source Q and
+ * destination Q processing. Waits for source Q and destination Q processing
+ * and re enables interrupts. Same work is invoked by timer if coalesce count
+ * is greater than zero and interrupts are not invoked before the timeout period
+ *
+ * @work: Work associated with the task
+ *
+ * Return: void
+ */
+static void ps_pcie_chan_primary_work(struct work_struct *work)
+{
+	struct ps_pcie_dma_chan *chan =
+		(struct ps_pcie_dma_chan *)container_of(
+				work, struct ps_pcie_dma_chan,
+				handle_primary_desc_cleanup);
+
+	/* Disable interrupts for Channel */
+	ps_pcie_dma_clr_mask(chan, chan->intr_control_offset,
+			     DMA_INTCNTRL_ENABLINTR_BIT);
+
+	if (chan->psrc_sgl_bd) {
+		reinit_completion(&chan->srcq_work_complete);
+		if (chan->srcq_desc_cleanup)
+			queue_work(chan->srcq_desc_cleanup,
+				   &chan->handle_srcq_desc_cleanup);
+	}
+	if (chan->pdst_sgl_bd) {
+		reinit_completion(&chan->dstq_work_complete);
+		if (chan->dstq_desc_cleanup)
+			queue_work(chan->dstq_desc_cleanup,
+				   &chan->handle_dstq_desc_cleanup);
+	}
+
+	if (chan->psrc_sgl_bd)
+		wait_for_completion_interruptible(&chan->srcq_work_complete);
+	if (chan->pdst_sgl_bd)
+		wait_for_completion_interruptible(&chan->dstq_work_complete);
+
+	/* Enable interrupts for channel */
+	ps_pcie_dma_set_mask(chan, chan->intr_control_offset,
+			     DMA_INTCNTRL_ENABLINTR_BIT);
+
+	if (chan->chan_programming) {
+		queue_work(chan->chan_programming,
+			   &chan->handle_chan_programming);
+	}
+
+	if (chan->coalesce_count > 0 && chan->poll_timer.function)
+		mod_timer(&chan->poll_timer, jiffies + chan->poll_timer_freq);
+}
+
+static int read_rootdma_config(struct platform_device *platform_dev,
+			       struct xlnx_pcie_dma_device *xdev)
+{
+	int err;
+	struct resource *r;
+
+	err = dma_set_mask(&platform_dev->dev, DMA_BIT_MASK(64));
+	if (err) {
+		dev_info(&platform_dev->dev, "Cannot set 64 bit DMA mask\n");
+		err = dma_set_mask(&platform_dev->dev, DMA_BIT_MASK(32));
+		if (err) {
+			dev_err(&platform_dev->dev, "DMA mask set error\n");
+			return err;
+		}
+	}
+
+	err = dma_set_coherent_mask(&platform_dev->dev, DMA_BIT_MASK(64));
+	if (err) {
+		dev_info(&platform_dev->dev, "Cannot set 64 bit consistent DMA mask\n");
+		err = dma_set_coherent_mask(&platform_dev->dev,
+					    DMA_BIT_MASK(32));
+		if (err) {
+			dev_err(&platform_dev->dev, "Cannot set consistent DMA mask\n");
+			return err;
+		}
+	}
+
+	r = platform_get_resource_byname(platform_dev, IORESOURCE_MEM,
+					 "ps_pcie_regbase");
+	if (!r) {
+		dev_err(&platform_dev->dev,
+			"Unable to find memory resource for root dma\n");
+		return PTR_ERR(r);
+	}
+
+	xdev->reg_base = devm_ioremap_resource(&platform_dev->dev, r);
+	if (IS_ERR(xdev->reg_base)) {
+		dev_err(&platform_dev->dev, "ioresource error for root dma\n");
+		return PTR_ERR(xdev->reg_base);
+	}
+
+	xdev->platform_irq_vec =
+		platform_get_irq_byname(platform_dev,
+					"ps_pcie_rootdma_intr");
+	if (xdev->platform_irq_vec < 0) {
+		dev_err(&platform_dev->dev,
+			"Unable to get interrupt number for root dma\n");
+		return xdev->platform_irq_vec;
+	}
+
+	err = device_property_read_u16(&platform_dev->dev, "dma_vendorid",
+				       &xdev->rootdma_vendor);
+	if (err) {
+		dev_err(&platform_dev->dev,
+			"Unable to find RootDMA PCI Vendor Id\n");
+		return err;
+	}
+
+	err = device_property_read_u16(&platform_dev->dev, "dma_deviceid",
+				       &xdev->rootdma_device);
+	if (err) {
+		dev_err(&platform_dev->dev,
+			"Unable to find RootDMA PCI Device Id\n");
+		return err;
+	}
+
+	xdev->common.dev = xdev->dev;
+
+	return 0;
+}
+
+static int read_epdma_config(struct platform_device *platform_dev,
+			     struct xlnx_pcie_dma_device *xdev)
+{
+	int err;
+	struct pci_dev *pdev;
+	u16 i;
+	void __iomem * const *pci_iomap;
+	unsigned long pci_bar_length;
+
+	pdev = *((struct pci_dev **)(platform_dev->dev.platform_data));
+	xdev->pci_dev = pdev;
+
+	for (i = 0; i < MAX_BARS; i++) {
+		if (pci_resource_len(pdev, i) == 0)
+			continue;
+		xdev->bar_mask = xdev->bar_mask | (1 << (i));
+	}
+
+	err = pcim_iomap_regions(pdev, xdev->bar_mask, PLATFORM_DRIVER_NAME);
+	if (err) {
+		dev_err(&pdev->dev, "Cannot request PCI regions, aborting\n");
+		return err;
+	}
+
+	pci_iomap = pcim_iomap_table(pdev);
+	if (!pci_iomap) {
+		err = -ENOMEM;
+		return err;
+	}
+
+	for (i = 0; i < MAX_BARS; i++) {
+		pci_bar_length = pci_resource_len(pdev, i);
+		if (pci_bar_length == 0) {
+			xdev->bar_info[i].BAR_LENGTH = 0;
+			xdev->bar_info[i].BAR_PHYS_ADDR = 0;
+			xdev->bar_info[i].BAR_VIRT_ADDR = NULL;
+		} else {
+			xdev->bar_info[i].BAR_LENGTH =
+				pci_bar_length;
+			xdev->bar_info[i].BAR_PHYS_ADDR =
+				pci_resource_start(pdev, i);
+			xdev->bar_info[i].BAR_VIRT_ADDR =
+				(void *)pci_iomap[i];
+		}
+	}
+
+	xdev->reg_base = pci_iomap[DMA_BAR_NUMBER];
+
+	err = irq_probe(xdev);
+	if (err < 0) {
+		dev_err(&pdev->dev, "Cannot probe irq lines for device %d\n",
+			platform_dev->id);
+		return err;
+	}
+
+	xdev->common.dev = &pdev->dev;
+
+	return 0;
+}
+
+static int probe_channel_properties(struct platform_device *platform_dev,
+				    struct xlnx_pcie_dma_device *xdev,
+				    u16 channel_number)
+{
+	int i;
+	char propertyname[CHANNEL_PROPERTY_LENGTH];
+	int numvals, ret;
+	u32 *val;
+	struct ps_pcie_dma_chan *channel;
+	struct ps_pcie_dma_channel_match *xlnx_match;
+
+	snprintf(propertyname, CHANNEL_PROPERTY_LENGTH,
+		 "ps_pcie_channel%d", channel_number);
+
+	channel = &xdev->channels[channel_number];
+
+	spin_lock_init(&channel->channel_lock);
+	spin_lock_init(&channel->cookie_lock);
+
+	INIT_LIST_HEAD(&channel->pending_list);
+	spin_lock_init(&channel->pending_list_lock);
+
+	INIT_LIST_HEAD(&channel->active_list);
+	spin_lock_init(&channel->active_list_lock);
+
+	spin_lock_init(&channel->src_desc_lock);
+	spin_lock_init(&channel->dst_desc_lock);
+
+	INIT_LIST_HEAD(&channel->pending_interrupts_list);
+	spin_lock_init(&channel->pending_interrupts_lock);
+
+	INIT_LIST_HEAD(&channel->active_interrupts_list);
+	spin_lock_init(&channel->active_interrupts_lock);
+
+	init_completion(&channel->srcq_work_complete);
+	init_completion(&channel->dstq_work_complete);
+	init_completion(&channel->chan_shutdown_complt);
+	init_completion(&channel->chan_terminate_complete);
+
+	if (device_property_present(&platform_dev->dev, propertyname)) {
+		numvals = device_property_read_u32_array(&platform_dev->dev,
+							 propertyname, NULL, 0);
+
+		if (numvals < 0)
+			return numvals;
+
+		val = devm_kzalloc(&platform_dev->dev, sizeof(u32) * numvals,
+				   GFP_KERNEL);
+
+		if (!val)
+			return -ENOMEM;
+
+		ret = device_property_read_u32_array(&platform_dev->dev,
+						     propertyname, val,
+						     numvals);
+		if (ret < 0) {
+			dev_err(&platform_dev->dev,
+				"Unable to read property %s\n", propertyname);
+			return ret;
+		}
+
+		for (i = 0; i < numvals; i++) {
+			switch (i) {
+			case DMA_CHANNEL_DIRECTION:
+				channel->direction =
+					(val[DMA_CHANNEL_DIRECTION] ==
+						PCIE_AXI_DIRECTION) ?
+						DMA_TO_DEVICE : DMA_FROM_DEVICE;
+				break;
+			case NUM_DESCRIPTORS:
+				channel->total_descriptors =
+						val[NUM_DESCRIPTORS];
+				if (channel->total_descriptors >
+					MAX_DESCRIPTORS) {
+					dev_info(&platform_dev->dev,
+						 "Descriptors > alowd max\n");
+					channel->total_descriptors =
+							MAX_DESCRIPTORS;
+				}
+				break;
+			case NUM_QUEUES:
+				channel->num_queues = val[NUM_QUEUES];
+				switch (channel->num_queues) {
+				case DEFAULT_DMA_QUEUES:
+						break;
+				case TWO_DMA_QUEUES:
+						break;
+				default:
+				dev_info(&platform_dev->dev,
+					 "Incorrect Q number for dma chan\n");
+				channel->num_queues = DEFAULT_DMA_QUEUES;
+				}
+				break;
+			case COALESE_COUNT:
+				channel->coalesce_count = val[COALESE_COUNT];
+
+				if (channel->coalesce_count >
+					MAX_COALESCE_COUNT) {
+					dev_info(&platform_dev->dev,
+						 "Invalid coalesce Count\n");
+					channel->coalesce_count =
+						MAX_COALESCE_COUNT;
+				}
+				break;
+			case POLL_TIMER_FREQUENCY:
+				channel->poll_timer_freq =
+					val[POLL_TIMER_FREQUENCY];
+				break;
+			default:
+				dev_err(&platform_dev->dev,
+					"Check order of channel properties!\n");
+			}
+		}
+	} else {
+		dev_err(&platform_dev->dev,
+			"Property %s not present. Invalid configuration!\n",
+				propertyname);
+		return -ENOTSUPP;
+	}
+
+	if (channel->direction == DMA_TO_DEVICE) {
+		if (channel->num_queues == DEFAULT_DMA_QUEUES) {
+			channel->srcq_buffer_location = BUFFER_LOC_PCI;
+			channel->dstq_buffer_location = BUFFER_LOC_AXI;
+		} else {
+			channel->srcq_buffer_location = BUFFER_LOC_PCI;
+			channel->dstq_buffer_location = BUFFER_LOC_INVALID;
+		}
+	} else {
+		if (channel->num_queues == DEFAULT_DMA_QUEUES) {
+			channel->srcq_buffer_location = BUFFER_LOC_AXI;
+			channel->dstq_buffer_location = BUFFER_LOC_PCI;
+		} else {
+			channel->srcq_buffer_location = BUFFER_LOC_INVALID;
+			channel->dstq_buffer_location = BUFFER_LOC_PCI;
+		}
+	}
+
+	channel->xdev = xdev;
+	channel->channel_number = channel_number;
+
+	if (xdev->is_rootdma) {
+		channel->dev = xdev->dev;
+		channel->intr_status_offset = DMA_AXI_INTR_STATUS_REG_OFFSET;
+		channel->intr_control_offset = DMA_AXI_INTR_CNTRL_REG_OFFSET;
+	} else {
+		channel->dev = &xdev->pci_dev->dev;
+		channel->intr_status_offset = DMA_PCIE_INTR_STATUS_REG_OFFSET;
+		channel->intr_control_offset = DMA_PCIE_INTR_CNTRL_REG_OFFSET;
+	}
+
+	channel->chan_base =
+	(struct DMA_ENGINE_REGISTERS *)((__force char *)(xdev->reg_base) +
+				 (channel_number * DMA_CHANNEL_REGS_SIZE));
+
+	if ((channel->chan_base->dma_channel_status &
+				DMA_STATUS_DMA_PRES_BIT) == 0) {
+		dev_err(&platform_dev->dev,
+			"Hardware reports channel not present\n");
+		return -ENOTSUPP;
+	}
+
+	update_channel_read_attribute(channel);
+	update_channel_write_attribute(channel);
+
+	xlnx_match = devm_kzalloc(&platform_dev->dev,
+				  sizeof(struct ps_pcie_dma_channel_match),
+				  GFP_KERNEL);
+
+	if (!xlnx_match)
+		return -ENOMEM;
+
+	if (xdev->is_rootdma) {
+		xlnx_match->pci_vendorid = xdev->rootdma_vendor;
+		xlnx_match->pci_deviceid = xdev->rootdma_device;
+	} else {
+		xlnx_match->pci_vendorid = xdev->pci_dev->vendor;
+		xlnx_match->pci_deviceid = xdev->pci_dev->device;
+		xlnx_match->bar_params = xdev->bar_info;
+	}
+
+	xlnx_match->board_number = xdev->board_number;
+	xlnx_match->channel_number = channel_number;
+	xlnx_match->direction = xdev->channels[channel_number].direction;
+
+	channel->common.private = (void *)xlnx_match;
+
+	channel->common.device = &xdev->common;
+	list_add_tail(&channel->common.device_node, &xdev->common.channels);
+
+	return 0;
+}
+
+static void xlnx_ps_pcie_destroy_mempool(struct ps_pcie_dma_chan *chan)
+{
+	mempool_destroy(chan->transactions_pool);
+
+	mempool_destroy(chan->tx_elements_pool);
+
+	mempool_destroy(chan->intr_transactions_pool);
+}
+
+static void xlnx_ps_pcie_free_worker_queues(struct ps_pcie_dma_chan *chan)
+{
+	if (chan->maintenance_workq)
+		destroy_workqueue(chan->maintenance_workq);
+
+	if (chan->sw_intrs_wrkq)
+		destroy_workqueue(chan->sw_intrs_wrkq);
+
+	if (chan->srcq_desc_cleanup)
+		destroy_workqueue(chan->srcq_desc_cleanup);
+
+	if (chan->dstq_desc_cleanup)
+		destroy_workqueue(chan->dstq_desc_cleanup);
+
+	if (chan->chan_programming)
+		destroy_workqueue(chan->chan_programming);
+
+	if (chan->primary_desc_cleanup)
+		destroy_workqueue(chan->primary_desc_cleanup);
+}
+
+static void xlnx_ps_pcie_free_pkt_ctxts(struct ps_pcie_dma_chan *chan)
+{
+	kfree(chan->ppkt_ctx_srcq);
+
+	kfree(chan->ppkt_ctx_dstq);
+}
+
+static void xlnx_ps_pcie_free_descriptors(struct ps_pcie_dma_chan *chan)
+{
+	ssize_t size;
+
+	if (chan->psrc_sgl_bd) {
+		size = chan->total_descriptors *
+			sizeof(struct SOURCE_DMA_DESCRIPTOR);
+		dma_free_coherent(chan->dev, size, chan->psrc_sgl_bd,
+				  chan->src_sgl_bd_pa);
+	}
+
+	if (chan->pdst_sgl_bd) {
+		size = chan->total_descriptors *
+			sizeof(struct DEST_DMA_DESCRIPTOR);
+		dma_free_coherent(chan->dev, size, chan->pdst_sgl_bd,
+				  chan->dst_sgl_bd_pa);
+	}
+
+	if (chan->psrc_sta_bd) {
+		size = chan->total_descriptors *
+			sizeof(struct STATUS_DMA_DESCRIPTOR);
+		dma_free_coherent(chan->dev, size, chan->psrc_sta_bd,
+				  chan->src_sta_bd_pa);
+	}
+
+	if (chan->pdst_sta_bd) {
+		size = chan->total_descriptors *
+			sizeof(struct STATUS_DMA_DESCRIPTOR);
+		dma_free_coherent(chan->dev, size, chan->pdst_sta_bd,
+				  chan->dst_sta_bd_pa);
+	}
+}
+
+static int xlnx_ps_pcie_channel_activate(struct ps_pcie_dma_chan *chan)
+{
+	u32 reg = chan->coalesce_count;
+
+	reg = reg << DMA_INTCNTRL_SGCOLSCCNT_BIT_SHIFT;
+
+	/* Enable Interrupts for channel */
+	ps_pcie_dma_set_mask(chan, chan->intr_control_offset,
+			     reg | DMA_INTCNTRL_ENABLINTR_BIT |
+			     DMA_INTCNTRL_DMAERRINTR_BIT |
+			     DMA_INTCNTRL_DMASGINTR_BIT);
+
+	/* Enable DMA */
+	ps_pcie_dma_set_mask(chan, DMA_CNTRL_REG_OFFSET,
+			     DMA_CNTRL_ENABL_BIT |
+			     DMA_CNTRL_64BIT_STAQ_ELEMSZ_BIT);
+
+	spin_lock(&chan->channel_lock);
+	chan->state = CHANNEL_AVAILABLE;
+	spin_unlock(&chan->channel_lock);
+
+	/* Activate timer if required */
+	if (chan->coalesce_count > 0 && !chan->poll_timer.function)
+		xlnx_ps_pcie_alloc_poll_timer(chan);
+
+	return 0;
+}
+
+static void xlnx_ps_pcie_channel_quiesce(struct ps_pcie_dma_chan *chan)
+{
+	/* Disable interrupts for Channel */
+	ps_pcie_dma_clr_mask(chan, chan->intr_control_offset,
+			     DMA_INTCNTRL_ENABLINTR_BIT);
+
+	/* Delete timer if it is created */
+	if (chan->coalesce_count > 0 && !chan->poll_timer.function)
+		xlnx_ps_pcie_free_poll_timer(chan);
+
+	/* Flush descriptor cleaning work queues */
+	if (chan->primary_desc_cleanup)
+		flush_workqueue(chan->primary_desc_cleanup);
+
+	/* Flush channel programming work queue */
+	if (chan->chan_programming)
+		flush_workqueue(chan->chan_programming);
+
+	/*  Clear the persistent bits */
+	ps_pcie_dma_set_mask(chan, chan->intr_status_offset,
+			     DMA_INTSTATUS_DMAERR_BIT |
+			     DMA_INTSTATUS_SGLINTR_BIT |
+			     DMA_INTSTATUS_SWINTR_BIT);
+
+	/* Disable DMA channel */
+	ps_pcie_dma_clr_mask(chan, DMA_CNTRL_REG_OFFSET, DMA_CNTRL_ENABL_BIT);
+
+	spin_lock(&chan->channel_lock);
+	chan->state = CHANNEL_UNAVIALBLE;
+	spin_unlock(&chan->channel_lock);
+}
+
+static void ivk_cbk_intr_seg(struct ps_pcie_intr_segment *intr_seg,
+			     struct ps_pcie_dma_chan *chan,
+			     enum dmaengine_tx_result result)
+{
+	struct dmaengine_result rslt;
+
+	rslt.result = result;
+	rslt.residue = 0;
+
+	spin_lock(&chan->cookie_lock);
+	dma_cookie_complete(&intr_seg->async_intr_tx);
+	spin_unlock(&chan->cookie_lock);
+
+	dmaengine_desc_get_callback_invoke(&intr_seg->async_intr_tx, &rslt);
+}
+
+static void ivk_cbk_seg(struct ps_pcie_tx_segment *seg,
+			struct ps_pcie_dma_chan *chan,
+			enum dmaengine_tx_result result)
+{
+	struct dmaengine_result rslt, *prslt;
+
+	spin_lock(&chan->cookie_lock);
+	dma_cookie_complete(&seg->async_tx);
+	spin_unlock(&chan->cookie_lock);
+
+	rslt.result = result;
+	if (seg->src_elements &&
+	    chan->srcq_buffer_location == BUFFER_LOC_PCI) {
+		rslt.residue = seg->total_transfer_bytes;
+		prslt = &rslt;
+	} else if (seg->dst_elements &&
+		   chan->dstq_buffer_location == BUFFER_LOC_PCI) {
+		rslt.residue = seg->total_transfer_bytes;
+		prslt = &rslt;
+	} else {
+		prslt = NULL;
+	}
+
+	dmaengine_desc_get_callback_invoke(&seg->async_tx, prslt);
+}
+
+static void ivk_cbk_ctx(struct PACKET_TRANSFER_PARAMS *ppkt_ctxt,
+			struct ps_pcie_dma_chan *chan,
+			enum dmaengine_tx_result result)
+{
+	if (ppkt_ctxt->availability_status == IN_USE) {
+		if (ppkt_ctxt->seg) {
+			ivk_cbk_seg(ppkt_ctxt->seg, chan, result);
+			mempool_free(ppkt_ctxt->seg,
+				     chan->transactions_pool);
+		}
+	}
+}
+
+static void ivk_cbk_for_pending(struct ps_pcie_dma_chan *chan)
+{
+	int i;
+	struct PACKET_TRANSFER_PARAMS *ppkt_ctxt;
+	struct ps_pcie_tx_segment *seg, *seg_nxt;
+	struct ps_pcie_intr_segment *intr_seg, *intr_seg_next;
+	struct ps_pcie_transfer_elements *ele, *ele_nxt;
+
+	if (chan->ppkt_ctx_srcq) {
+		if (chan->idx_ctx_srcq_tail != chan->idx_ctx_srcq_head) {
+			i = chan->idx_ctx_srcq_tail;
+			while (i != chan->idx_ctx_srcq_head) {
+				ppkt_ctxt = chan->ppkt_ctx_srcq + i;
+				ivk_cbk_ctx(ppkt_ctxt, chan,
+					    DMA_TRANS_READ_FAILED);
+				memset(ppkt_ctxt, 0,
+				       sizeof(struct PACKET_TRANSFER_PARAMS));
+				i++;
+				if (i == chan->total_descriptors)
+					i = 0;
+			}
+		}
+	}
+
+	if (chan->ppkt_ctx_dstq) {
+		if (chan->idx_ctx_dstq_tail != chan->idx_ctx_dstq_head) {
+			i = chan->idx_ctx_dstq_tail;
+			while (i != chan->idx_ctx_dstq_head) {
+				ppkt_ctxt = chan->ppkt_ctx_dstq + i;
+				ivk_cbk_ctx(ppkt_ctxt, chan,
+					    DMA_TRANS_WRITE_FAILED);
+				memset(ppkt_ctxt, 0,
+				       sizeof(struct PACKET_TRANSFER_PARAMS));
+				i++;
+				if (i == chan->total_descriptors)
+					i = 0;
+			}
+		}
+	}
+
+	list_for_each_entry_safe(seg, seg_nxt, &chan->active_list, node) {
+		ivk_cbk_seg(seg, chan, DMA_TRANS_ABORTED);
+		spin_lock(&chan->active_list_lock);
+		list_del(&seg->node);
+		spin_unlock(&chan->active_list_lock);
+		list_for_each_entry_safe(ele, ele_nxt,
+					 &seg->transfer_nodes, node) {
+			list_del(&ele->node);
+			mempool_free(ele, chan->tx_elements_pool);
+		}
+		mempool_free(seg, chan->transactions_pool);
+	}
+
+	list_for_each_entry_safe(seg, seg_nxt, &chan->pending_list, node) {
+		ivk_cbk_seg(seg, chan, DMA_TRANS_ABORTED);
+		spin_lock(&chan->pending_list_lock);
+		list_del(&seg->node);
+		spin_unlock(&chan->pending_list_lock);
+		list_for_each_entry_safe(ele, ele_nxt,
+					 &seg->transfer_nodes, node) {
+			list_del(&ele->node);
+			mempool_free(ele, chan->tx_elements_pool);
+		}
+		mempool_free(seg, chan->transactions_pool);
+	}
+
+	list_for_each_entry_safe(intr_seg, intr_seg_next,
+				 &chan->active_interrupts_list, node) {
+		ivk_cbk_intr_seg(intr_seg, chan, DMA_TRANS_ABORTED);
+		spin_lock(&chan->active_interrupts_lock);
+		list_del(&intr_seg->node);
+		spin_unlock(&chan->active_interrupts_lock);
+		mempool_free(intr_seg, chan->intr_transactions_pool);
+	}
+
+	list_for_each_entry_safe(intr_seg, intr_seg_next,
+				 &chan->pending_interrupts_list, node) {
+		ivk_cbk_intr_seg(intr_seg, chan, DMA_TRANS_ABORTED);
+		spin_lock(&chan->pending_interrupts_lock);
+		list_del(&intr_seg->node);
+		spin_unlock(&chan->pending_interrupts_lock);
+		mempool_free(intr_seg, chan->intr_transactions_pool);
+	}
+}
+
+static void xlnx_ps_pcie_reset_channel(struct ps_pcie_dma_chan *chan)
+{
+	xlnx_ps_pcie_channel_quiesce(chan);
+
+	ivk_cbk_for_pending(chan);
+
+	ps_pcie_chan_reset(chan);
+
+	init_sw_components(chan);
+	init_hw_components(chan);
+
+	xlnx_ps_pcie_channel_activate(chan);
+}
+
+static void xlnx_ps_pcie_free_poll_timer(struct ps_pcie_dma_chan *chan)
+{
+	if (chan->poll_timer.function) {
+		del_timer_sync(&chan->poll_timer);
+		chan->poll_timer.function = NULL;
+	}
+}
+
+static int xlnx_ps_pcie_alloc_poll_timer(struct ps_pcie_dma_chan *chan)
+{
+	timer_setup(&chan->poll_timer, poll_completed_transactions, 0);
+	chan->poll_timer.expires = jiffies + chan->poll_timer_freq;
+
+	add_timer(&chan->poll_timer);
+
+	return 0;
+}
+
+static void terminate_transactions_work(struct work_struct *work)
+{
+	struct ps_pcie_dma_chan *chan =
+		(struct ps_pcie_dma_chan *)container_of(work,
+			struct ps_pcie_dma_chan, handle_chan_terminate);
+
+	xlnx_ps_pcie_channel_quiesce(chan);
+	ivk_cbk_for_pending(chan);
+	xlnx_ps_pcie_channel_activate(chan);
+
+	complete(&chan->chan_terminate_complete);
+}
+
+static void chan_shutdown_work(struct work_struct *work)
+{
+	struct ps_pcie_dma_chan *chan =
+		(struct ps_pcie_dma_chan *)container_of(work,
+				struct ps_pcie_dma_chan, handle_chan_shutdown);
+
+	xlnx_ps_pcie_channel_quiesce(chan);
+
+	complete(&chan->chan_shutdown_complt);
+}
+
+static void chan_reset_work(struct work_struct *work)
+{
+	struct ps_pcie_dma_chan *chan =
+		(struct ps_pcie_dma_chan *)container_of(work,
+				struct ps_pcie_dma_chan, handle_chan_reset);
+
+	xlnx_ps_pcie_reset_channel(chan);
+}
+
+static void sw_intr_work(struct work_struct *work)
+{
+	struct ps_pcie_dma_chan *chan =
+		(struct ps_pcie_dma_chan *)container_of(work,
+				struct ps_pcie_dma_chan, handle_sw_intrs);
+	struct ps_pcie_intr_segment *intr_seg, *intr_seg_next;
+
+	list_for_each_entry_safe(intr_seg, intr_seg_next,
+				 &chan->active_interrupts_list, node) {
+		spin_lock(&chan->cookie_lock);
+		dma_cookie_complete(&intr_seg->async_intr_tx);
+		spin_unlock(&chan->cookie_lock);
+		dmaengine_desc_get_callback_invoke(&intr_seg->async_intr_tx,
+						   NULL);
+		spin_lock(&chan->active_interrupts_lock);
+		list_del(&intr_seg->node);
+		spin_unlock(&chan->active_interrupts_lock);
+	}
+}
+
+static int xlnx_ps_pcie_alloc_worker_threads(struct ps_pcie_dma_chan *chan)
+{
+	char wq_name[WORKQ_NAME_SIZE];
+
+	snprintf(wq_name, WORKQ_NAME_SIZE,
+		 "PS PCIe channel %d descriptor programming wq",
+		 chan->channel_number);
+	chan->chan_programming =
+		create_singlethread_workqueue((const char *)wq_name);
+	if (!chan->chan_programming) {
+		dev_err(chan->dev,
+			"Unable to create programming wq for chan %d",
+			chan->channel_number);
+		goto err_no_desc_program_wq;
+	} else {
+		INIT_WORK(&chan->handle_chan_programming,
+			  ps_pcie_chan_program_work);
+	}
+	memset(wq_name, 0, WORKQ_NAME_SIZE);
+
+	snprintf(wq_name, WORKQ_NAME_SIZE,
+		 "PS PCIe channel %d primary cleanup wq", chan->channel_number);
+	chan->primary_desc_cleanup =
+		create_singlethread_workqueue((const char *)wq_name);
+	if (!chan->primary_desc_cleanup) {
+		dev_err(chan->dev,
+			"Unable to create primary cleanup wq for channel %d",
+			chan->channel_number);
+		goto err_no_primary_clean_wq;
+	} else {
+		INIT_WORK(&chan->handle_primary_desc_cleanup,
+			  ps_pcie_chan_primary_work);
+	}
+	memset(wq_name, 0, WORKQ_NAME_SIZE);
+
+	snprintf(wq_name, WORKQ_NAME_SIZE,
+		 "PS PCIe channel %d maintenance works wq",
+		 chan->channel_number);
+	chan->maintenance_workq =
+		create_singlethread_workqueue((const char *)wq_name);
+	if (!chan->maintenance_workq) {
+		dev_err(chan->dev,
+			"Unable to create maintenance wq for channel %d",
+			chan->channel_number);
+		goto err_no_maintenance_wq;
+	} else {
+		INIT_WORK(&chan->handle_chan_reset, chan_reset_work);
+		INIT_WORK(&chan->handle_chan_shutdown, chan_shutdown_work);
+		INIT_WORK(&chan->handle_chan_terminate,
+			  terminate_transactions_work);
+	}
+	memset(wq_name, 0, WORKQ_NAME_SIZE);
+
+	snprintf(wq_name, WORKQ_NAME_SIZE,
+		 "PS PCIe channel %d software Interrupts wq",
+		 chan->channel_number);
+	chan->sw_intrs_wrkq =
+		create_singlethread_workqueue((const char *)wq_name);
+	if (!chan->sw_intrs_wrkq) {
+		dev_err(chan->dev,
+			"Unable to create sw interrupts wq for channel %d",
+			chan->channel_number);
+		goto err_no_sw_intrs_wq;
+	} else {
+		INIT_WORK(&chan->handle_sw_intrs, sw_intr_work);
+	}
+	memset(wq_name, 0, WORKQ_NAME_SIZE);
+
+	if (chan->psrc_sgl_bd) {
+		snprintf(wq_name, WORKQ_NAME_SIZE,
+			 "PS PCIe channel %d srcq handling wq",
+			 chan->channel_number);
+		chan->srcq_desc_cleanup =
+			create_singlethread_workqueue((const char *)wq_name);
+		if (!chan->srcq_desc_cleanup) {
+			dev_err(chan->dev,
+				"Unable to create src q completion wq chan %d",
+				chan->channel_number);
+			goto err_no_src_q_completion_wq;
+		} else {
+			INIT_WORK(&chan->handle_srcq_desc_cleanup,
+				  src_cleanup_work);
+		}
+		memset(wq_name, 0, WORKQ_NAME_SIZE);
+	}
+
+	if (chan->pdst_sgl_bd) {
+		snprintf(wq_name, WORKQ_NAME_SIZE,
+			 "PS PCIe channel %d dstq handling wq",
+			 chan->channel_number);
+		chan->dstq_desc_cleanup =
+			create_singlethread_workqueue((const char *)wq_name);
+		if (!chan->dstq_desc_cleanup) {
+			dev_err(chan->dev,
+				"Unable to create dst q completion wq chan %d",
+				chan->channel_number);
+			goto err_no_dst_q_completion_wq;
+		} else {
+			INIT_WORK(&chan->handle_dstq_desc_cleanup,
+				  dst_cleanup_work);
+		}
+		memset(wq_name, 0, WORKQ_NAME_SIZE);
+	}
+
+	return 0;
+err_no_dst_q_completion_wq:
+	if (chan->srcq_desc_cleanup)
+		destroy_workqueue(chan->srcq_desc_cleanup);
+err_no_src_q_completion_wq:
+	if (chan->sw_intrs_wrkq)
+		destroy_workqueue(chan->sw_intrs_wrkq);
+err_no_sw_intrs_wq:
+	if (chan->maintenance_workq)
+		destroy_workqueue(chan->maintenance_workq);
+err_no_maintenance_wq:
+	if (chan->primary_desc_cleanup)
+		destroy_workqueue(chan->primary_desc_cleanup);
+err_no_primary_clean_wq:
+	if (chan->chan_programming)
+		destroy_workqueue(chan->chan_programming);
+err_no_desc_program_wq:
+	return -ENOMEM;
+}
+
+static int xlnx_ps_pcie_alloc_mempool(struct ps_pcie_dma_chan *chan)
+{
+	chan->transactions_pool =
+		mempool_create_kmalloc_pool(chan->total_descriptors,
+					    sizeof(struct ps_pcie_tx_segment));
+
+	if (!chan->transactions_pool)
+		goto no_transactions_pool;
+
+	chan->tx_elements_pool =
+		mempool_create_kmalloc_pool(chan->total_descriptors,
+					    sizeof(struct ps_pcie_transfer_elements));
+
+	if (!chan->tx_elements_pool)
+		goto no_tx_elements_pool;
+
+	chan->intr_transactions_pool =
+	mempool_create_kmalloc_pool(MIN_SW_INTR_TRANSACTIONS,
+				    sizeof(struct ps_pcie_intr_segment));
+
+	if (!chan->intr_transactions_pool)
+		goto no_intr_transactions_pool;
+
+	return 0;
+
+no_intr_transactions_pool:
+	mempool_destroy(chan->tx_elements_pool);
+no_tx_elements_pool:
+	mempool_destroy(chan->transactions_pool);
+no_transactions_pool:
+	return -ENOMEM;
+}
+
+static int xlnx_ps_pcie_alloc_pkt_contexts(struct ps_pcie_dma_chan *chan)
+{
+	if (chan->psrc_sgl_bd) {
+		chan->ppkt_ctx_srcq =
+			kcalloc(chan->total_descriptors,
+				sizeof(struct PACKET_TRANSFER_PARAMS),
+				GFP_KERNEL);
+		if (!chan->ppkt_ctx_srcq) {
+			dev_err(chan->dev,
+				"Src pkt cxt allocation for chan %d failed\n",
+				chan->channel_number);
+			goto err_no_src_pkt_ctx;
+		}
+	}
+
+	if (chan->pdst_sgl_bd) {
+		chan->ppkt_ctx_dstq =
+			kcalloc(chan->total_descriptors,
+				sizeof(struct PACKET_TRANSFER_PARAMS),
+				GFP_KERNEL);
+		if (!chan->ppkt_ctx_dstq) {
+			dev_err(chan->dev,
+				"Dst pkt cxt for chan %d failed\n",
+				chan->channel_number);
+			goto err_no_dst_pkt_ctx;
+		}
+	}
+
+	return 0;
+
+err_no_dst_pkt_ctx:
+	kfree(chan->ppkt_ctx_srcq);
+
+err_no_src_pkt_ctx:
+	return -ENOMEM;
+}
+
+static int dma_alloc_descriptors_two_queues(struct ps_pcie_dma_chan *chan)
+{
+	size_t size;
+
+	void *sgl_base;
+	void *sta_base;
+	dma_addr_t phy_addr_sglbase;
+	dma_addr_t phy_addr_stabase;
+
+	size = chan->total_descriptors *
+		sizeof(struct SOURCE_DMA_DESCRIPTOR);
+
+	sgl_base = dma_alloc_coherent(chan->dev, size, &phy_addr_sglbase,
+				      GFP_KERNEL);
+
+	if (!sgl_base) {
+		dev_err(chan->dev,
+			"Sgl bds in two channel mode for chan %d failed\n",
+			chan->channel_number);
+		goto err_no_sgl_bds;
+	}
+
+	size = chan->total_descriptors * sizeof(struct STATUS_DMA_DESCRIPTOR);
+	sta_base = dma_alloc_coherent(chan->dev, size, &phy_addr_stabase,
+				      GFP_KERNEL);
+
+	if (!sta_base) {
+		dev_err(chan->dev,
+			"Sta bds in two channel mode for chan %d failed\n",
+			chan->channel_number);
+		goto err_no_sta_bds;
+	}
+
+	if (chan->direction == DMA_TO_DEVICE) {
+		chan->psrc_sgl_bd = sgl_base;
+		chan->src_sgl_bd_pa = phy_addr_sglbase;
+
+		chan->psrc_sta_bd = sta_base;
+		chan->src_sta_bd_pa = phy_addr_stabase;
+
+		chan->pdst_sgl_bd = NULL;
+		chan->dst_sgl_bd_pa = 0;
+
+		chan->pdst_sta_bd = NULL;
+		chan->dst_sta_bd_pa = 0;
+
+	} else if (chan->direction == DMA_FROM_DEVICE) {
+		chan->psrc_sgl_bd = NULL;
+		chan->src_sgl_bd_pa = 0;
+
+		chan->psrc_sta_bd = NULL;
+		chan->src_sta_bd_pa = 0;
+
+		chan->pdst_sgl_bd = sgl_base;
+		chan->dst_sgl_bd_pa = phy_addr_sglbase;
+
+		chan->pdst_sta_bd = sta_base;
+		chan->dst_sta_bd_pa = phy_addr_stabase;
+
+	} else {
+		dev_err(chan->dev,
+			"%d %s() Unsupported channel direction\n",
+			__LINE__, __func__);
+		goto unsupported_channel_direction;
+	}
+
+	return 0;
+
+unsupported_channel_direction:
+	size = chan->total_descriptors *
+		sizeof(struct STATUS_DMA_DESCRIPTOR);
+	dma_free_coherent(chan->dev, size, sta_base, phy_addr_stabase);
+err_no_sta_bds:
+	size = chan->total_descriptors *
+		sizeof(struct SOURCE_DMA_DESCRIPTOR);
+	dma_free_coherent(chan->dev, size, sgl_base, phy_addr_sglbase);
+err_no_sgl_bds:
+
+	return -ENOMEM;
+}
+
+static int dma_alloc_decriptors_all_queues(struct ps_pcie_dma_chan *chan)
+{
+	size_t size;
+
+	size = chan->total_descriptors *
+		sizeof(struct SOURCE_DMA_DESCRIPTOR);
+	chan->psrc_sgl_bd =
+		dma_alloc_coherent(chan->dev, size, &chan->src_sgl_bd_pa,
+				   GFP_KERNEL);
+
+	if (!chan->psrc_sgl_bd) {
+		dev_err(chan->dev,
+			"Alloc fail src q buffer descriptors for chan %d\n",
+			chan->channel_number);
+		goto err_no_src_sgl_descriptors;
+	}
+
+	size = chan->total_descriptors * sizeof(struct DEST_DMA_DESCRIPTOR);
+	chan->pdst_sgl_bd =
+		dma_alloc_coherent(chan->dev, size, &chan->dst_sgl_bd_pa,
+				   GFP_KERNEL);
+
+	if (!chan->pdst_sgl_bd) {
+		dev_err(chan->dev,
+			"Alloc fail dst q buffer descriptors for chan %d\n",
+			chan->channel_number);
+		goto err_no_dst_sgl_descriptors;
+	}
+
+	size = chan->total_descriptors * sizeof(struct STATUS_DMA_DESCRIPTOR);
+	chan->psrc_sta_bd =
+		dma_alloc_coherent(chan->dev, size, &chan->src_sta_bd_pa,
+				   GFP_KERNEL);
+
+	if (!chan->psrc_sta_bd) {
+		dev_err(chan->dev,
+			"Unable to allocate src q status bds for chan %d\n",
+			chan->channel_number);
+		goto err_no_src_sta_descriptors;
+	}
+
+	chan->pdst_sta_bd =
+		dma_alloc_coherent(chan->dev, size, &chan->dst_sta_bd_pa,
+				   GFP_KERNEL);
+
+	if (!chan->pdst_sta_bd) {
+		dev_err(chan->dev,
+			"Unable to allocate Dst q status bds for chan %d\n",
+			chan->channel_number);
+		goto err_no_dst_sta_descriptors;
+	}
+
+	return 0;
+
+err_no_dst_sta_descriptors:
+	size = chan->total_descriptors *
+		sizeof(struct STATUS_DMA_DESCRIPTOR);
+	dma_free_coherent(chan->dev, size, chan->psrc_sta_bd,
+			  chan->src_sta_bd_pa);
+err_no_src_sta_descriptors:
+	size = chan->total_descriptors *
+		sizeof(struct DEST_DMA_DESCRIPTOR);
+	dma_free_coherent(chan->dev, size, chan->pdst_sgl_bd,
+			  chan->dst_sgl_bd_pa);
+err_no_dst_sgl_descriptors:
+	size = chan->total_descriptors *
+		sizeof(struct SOURCE_DMA_DESCRIPTOR);
+	dma_free_coherent(chan->dev, size, chan->psrc_sgl_bd,
+			  chan->src_sgl_bd_pa);
+
+err_no_src_sgl_descriptors:
+	return -ENOMEM;
+}
+
+static void xlnx_ps_pcie_dma_free_chan_resources(struct dma_chan *dchan)
+{
+	struct ps_pcie_dma_chan *chan;
+
+	if (!dchan)
+		return;
+
+	chan = to_xilinx_chan(dchan);
+
+	if (chan->state == CHANNEL_RESOURCE_UNALLOCATED)
+		return;
+
+	if (chan->maintenance_workq) {
+		if (completion_done(&chan->chan_shutdown_complt))
+			reinit_completion(&chan->chan_shutdown_complt);
+		queue_work(chan->maintenance_workq,
+			   &chan->handle_chan_shutdown);
+		wait_for_completion_interruptible(&chan->chan_shutdown_complt);
+
+		xlnx_ps_pcie_free_worker_queues(chan);
+		xlnx_ps_pcie_free_pkt_ctxts(chan);
+		xlnx_ps_pcie_destroy_mempool(chan);
+		xlnx_ps_pcie_free_descriptors(chan);
+
+		spin_lock(&chan->channel_lock);
+		chan->state = CHANNEL_RESOURCE_UNALLOCATED;
+		spin_unlock(&chan->channel_lock);
+	}
+}
+
+static int xlnx_ps_pcie_dma_alloc_chan_resources(struct dma_chan *dchan)
+{
+	struct ps_pcie_dma_chan *chan;
+
+	if (!dchan)
+		return PTR_ERR(dchan);
+
+	chan = to_xilinx_chan(dchan);
+
+	if (chan->state != CHANNEL_RESOURCE_UNALLOCATED)
+		return 0;
+
+	if (chan->num_queues == DEFAULT_DMA_QUEUES) {
+		if (dma_alloc_decriptors_all_queues(chan) != 0) {
+			dev_err(chan->dev,
+				"Alloc fail bds for channel %d\n",
+				chan->channel_number);
+			goto err_no_descriptors;
+		}
+	} else if (chan->num_queues == TWO_DMA_QUEUES) {
+		if (dma_alloc_descriptors_two_queues(chan) != 0) {
+			dev_err(chan->dev,
+				"Alloc fail bds for two queues of channel %d\n",
+			chan->channel_number);
+			goto err_no_descriptors;
+		}
+	}
+
+	if (xlnx_ps_pcie_alloc_mempool(chan) != 0) {
+		dev_err(chan->dev,
+			"Unable to allocate memory pool for channel %d\n",
+			chan->channel_number);
+		goto err_no_mempools;
+	}
+
+	if (xlnx_ps_pcie_alloc_pkt_contexts(chan) != 0) {
+		dev_err(chan->dev,
+			"Unable to allocate packet contexts for channel %d\n",
+			chan->channel_number);
+		goto err_no_pkt_ctxts;
+	}
+
+	if (xlnx_ps_pcie_alloc_worker_threads(chan) != 0) {
+		dev_err(chan->dev,
+			"Unable to allocate worker queues for channel %d\n",
+			chan->channel_number);
+		goto err_no_worker_queues;
+	}
+
+	xlnx_ps_pcie_reset_channel(chan);
+
+	dma_cookie_init(dchan);
+
+	return 0;
+
+err_no_worker_queues:
+	xlnx_ps_pcie_free_pkt_ctxts(chan);
+err_no_pkt_ctxts:
+	xlnx_ps_pcie_destroy_mempool(chan);
+err_no_mempools:
+	xlnx_ps_pcie_free_descriptors(chan);
+err_no_descriptors:
+	return -ENOMEM;
+}
+
+static dma_cookie_t xilinx_intr_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+	struct ps_pcie_intr_segment *intr_seg =
+		to_ps_pcie_dma_tx_intr_descriptor(tx);
+	struct ps_pcie_dma_chan *chan = to_xilinx_chan(tx->chan);
+	dma_cookie_t cookie;
+
+	if (chan->state != CHANNEL_AVAILABLE)
+		return -EINVAL;
+
+	spin_lock(&chan->cookie_lock);
+	cookie = dma_cookie_assign(tx);
+	spin_unlock(&chan->cookie_lock);
+
+	spin_lock(&chan->pending_interrupts_lock);
+	list_add_tail(&intr_seg->node, &chan->pending_interrupts_list);
+	spin_unlock(&chan->pending_interrupts_lock);
+
+	return cookie;
+}
+
+static dma_cookie_t xilinx_dma_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+	struct ps_pcie_tx_segment *seg = to_ps_pcie_dma_tx_descriptor(tx);
+	struct ps_pcie_dma_chan *chan = to_xilinx_chan(tx->chan);
+	dma_cookie_t cookie;
+
+	if (chan->state != CHANNEL_AVAILABLE)
+		return -EINVAL;
+
+	spin_lock(&chan->cookie_lock);
+	cookie = dma_cookie_assign(tx);
+	spin_unlock(&chan->cookie_lock);
+
+	spin_lock(&chan->pending_list_lock);
+	list_add_tail(&seg->node, &chan->pending_list);
+	spin_unlock(&chan->pending_list_lock);
+
+	return cookie;
+}
+
+/**
+ * xlnx_ps_pcie_dma_prep_memcpy - prepare descriptors for a memcpy transaction
+ * @channel: DMA channel
+ * @dma_dst: destination address
+ * @dma_src: source address
+ * @len: transfer length
+ * @flags: transfer ack flags
+ *
+ * Return: Async transaction descriptor on success and NULL on failure
+ */
+static struct dma_async_tx_descriptor *
+xlnx_ps_pcie_dma_prep_memcpy(struct dma_chan *channel, dma_addr_t dma_dst,
+			     dma_addr_t dma_src, size_t len,
+			     unsigned long flags)
+{
+	struct ps_pcie_dma_chan *chan = to_xilinx_chan(channel);
+	struct ps_pcie_tx_segment *seg = NULL;
+	struct ps_pcie_transfer_elements *ele = NULL;
+	struct ps_pcie_transfer_elements *ele_nxt = NULL;
+	u32 i;
+
+	if (chan->state != CHANNEL_AVAILABLE)
+		return NULL;
+
+	if (chan->num_queues != DEFAULT_DMA_QUEUES) {
+		dev_err(chan->dev, "Only prep_slave_sg for channel %d\n",
+			chan->channel_number);
+		return NULL;
+	}
+
+	seg = mempool_alloc(chan->transactions_pool, GFP_ATOMIC);
+	if (!seg) {
+		dev_err(chan->dev, "Tx segment alloc for channel %d\n",
+			chan->channel_number);
+		return NULL;
+	}
+
+	memset(seg, 0, sizeof(*seg));
+	INIT_LIST_HEAD(&seg->transfer_nodes);
+
+	for (i = 0; i < len / MAX_TRANSFER_LENGTH; i++) {
+		ele = mempool_alloc(chan->tx_elements_pool, GFP_ATOMIC);
+		if (!ele) {
+			dev_err(chan->dev, "Tx element %d for channel %d\n",
+				i, chan->channel_number);
+			goto err_elements_prep_memcpy;
+		}
+		ele->src_pa = dma_src + (i * MAX_TRANSFER_LENGTH);
+		ele->dst_pa = dma_dst + (i * MAX_TRANSFER_LENGTH);
+		ele->transfer_bytes = MAX_TRANSFER_LENGTH;
+		list_add_tail(&ele->node, &seg->transfer_nodes);
+		seg->src_elements++;
+		seg->dst_elements++;
+		seg->total_transfer_bytes += ele->transfer_bytes;
+		ele = NULL;
+	}
+
+	if (len % MAX_TRANSFER_LENGTH) {
+		ele = mempool_alloc(chan->tx_elements_pool, GFP_ATOMIC);
+		if (!ele) {
+			dev_err(chan->dev, "Tx element %d for channel %d\n",
+				i, chan->channel_number);
+			goto err_elements_prep_memcpy;
+		}
+		ele->src_pa = dma_src + (i * MAX_TRANSFER_LENGTH);
+		ele->dst_pa = dma_dst + (i * MAX_TRANSFER_LENGTH);
+		ele->transfer_bytes = len % MAX_TRANSFER_LENGTH;
+		list_add_tail(&ele->node, &seg->transfer_nodes);
+		seg->src_elements++;
+		seg->dst_elements++;
+		seg->total_transfer_bytes += ele->transfer_bytes;
+	}
+
+	if (seg->src_elements > chan->total_descriptors) {
+		dev_err(chan->dev, "Insufficient descriptors in channel %d for dma transaction\n",
+			chan->channel_number);
+		goto err_elements_prep_memcpy;
+	}
+
+	dma_async_tx_descriptor_init(&seg->async_tx, &chan->common);
+	seg->async_tx.flags = flags;
+	async_tx_ack(&seg->async_tx);
+	seg->async_tx.tx_submit = xilinx_dma_tx_submit;
+
+	return &seg->async_tx;
+
+err_elements_prep_memcpy:
+	list_for_each_entry_safe(ele, ele_nxt, &seg->transfer_nodes, node) {
+		list_del(&ele->node);
+		mempool_free(ele, chan->tx_elements_pool);
+	}
+	mempool_free(seg, chan->transactions_pool);
+	return NULL;
+}
+
+static struct dma_async_tx_descriptor *xlnx_ps_pcie_dma_prep_slave_sg(
+		struct dma_chan *channel, struct scatterlist *sgl,
+		unsigned int sg_len, enum dma_transfer_direction direction,
+		unsigned long flags, void *context)
+{
+	struct ps_pcie_dma_chan *chan = to_xilinx_chan(channel);
+	struct ps_pcie_tx_segment *seg = NULL;
+	struct scatterlist *sgl_ptr;
+	struct ps_pcie_transfer_elements *ele = NULL;
+	struct ps_pcie_transfer_elements *ele_nxt = NULL;
+	u32 i, j;
+
+	if (chan->state != CHANNEL_AVAILABLE)
+		return NULL;
+
+	if (!(is_slave_direction(direction)))
+		return NULL;
+
+	if (!sgl || sg_len == 0)
+		return NULL;
+
+	if (chan->num_queues != TWO_DMA_QUEUES) {
+		dev_err(chan->dev, "Only prep_dma_memcpy is supported channel %d\n",
+			chan->channel_number);
+		return NULL;
+	}
+
+	seg = mempool_alloc(chan->transactions_pool, GFP_ATOMIC);
+	if (!seg) {
+		dev_err(chan->dev, "Unable to allocate tx segment channel %d\n",
+			chan->channel_number);
+		return NULL;
+	}
+
+	memset(seg, 0, sizeof(*seg));
+
+	for_each_sg(sgl, sgl_ptr, sg_len, j) {
+		for (i = 0; i < sg_dma_len(sgl_ptr) / MAX_TRANSFER_LENGTH; i++) {
+			ele = mempool_alloc(chan->tx_elements_pool, GFP_ATOMIC);
+			if (!ele) {
+				dev_err(chan->dev, "Tx element %d for channel %d\n",
+					i, chan->channel_number);
+				goto err_elements_prep_slave_sg;
+			}
+			if (chan->direction == DMA_TO_DEVICE) {
+				ele->src_pa = sg_dma_address(sgl_ptr) +
+						(i * MAX_TRANSFER_LENGTH);
+				seg->src_elements++;
+			} else {
+				ele->dst_pa = sg_dma_address(sgl_ptr) +
+						(i * MAX_TRANSFER_LENGTH);
+				seg->dst_elements++;
+			}
+			ele->transfer_bytes = MAX_TRANSFER_LENGTH;
+			list_add_tail(&ele->node, &seg->transfer_nodes);
+			seg->total_transfer_bytes += ele->transfer_bytes;
+			ele = NULL;
+		}
+		if (sg_dma_len(sgl_ptr) % MAX_TRANSFER_LENGTH) {
+			ele = mempool_alloc(chan->tx_elements_pool, GFP_ATOMIC);
+			if (!ele) {
+				dev_err(chan->dev, "Tx element %d for channel %d\n",
+					i, chan->channel_number);
+				goto err_elements_prep_slave_sg;
+			}
+			if (chan->direction == DMA_TO_DEVICE) {
+				ele->src_pa = sg_dma_address(sgl_ptr) +
+						(i * MAX_TRANSFER_LENGTH);
+				seg->src_elements++;
+			} else {
+				ele->dst_pa = sg_dma_address(sgl_ptr) +
+						(i * MAX_TRANSFER_LENGTH);
+				seg->dst_elements++;
+			}
+			ele->transfer_bytes = sg_dma_len(sgl_ptr) %
+						MAX_TRANSFER_LENGTH;
+			list_add_tail(&ele->node, &seg->transfer_nodes);
+			seg->total_transfer_bytes += ele->transfer_bytes;
+		}
+	}
+
+	if (max(seg->src_elements, seg->dst_elements) >
+		chan->total_descriptors) {
+		dev_err(chan->dev, "Insufficient descriptors in channel %d for dma transaction\n",
+			chan->channel_number);
+		goto err_elements_prep_slave_sg;
+	}
+
+	dma_async_tx_descriptor_init(&seg->async_tx, &chan->common);
+	seg->async_tx.flags = flags;
+	async_tx_ack(&seg->async_tx);
+	seg->async_tx.tx_submit = xilinx_dma_tx_submit;
+
+	return &seg->async_tx;
+
+err_elements_prep_slave_sg:
+	list_for_each_entry_safe(ele, ele_nxt, &seg->transfer_nodes, node) {
+		list_del(&ele->node);
+		mempool_free(ele, chan->tx_elements_pool);
+	}
+	mempool_free(seg, chan->transactions_pool);
+	return NULL;
+}
+
+static void xlnx_ps_pcie_dma_issue_pending(struct dma_chan *channel)
+{
+	struct ps_pcie_dma_chan *chan;
+
+	if (!channel)
+		return;
+
+	chan = to_xilinx_chan(channel);
+
+	if (!list_empty(&chan->pending_list)) {
+		spin_lock(&chan->pending_list_lock);
+		spin_lock(&chan->active_list_lock);
+		list_splice_tail_init(&chan->pending_list,
+				      &chan->active_list);
+		spin_unlock(&chan->active_list_lock);
+		spin_unlock(&chan->pending_list_lock);
+	}
+
+	if (!list_empty(&chan->pending_interrupts_list)) {
+		spin_lock(&chan->pending_interrupts_lock);
+		spin_lock(&chan->active_interrupts_lock);
+		list_splice_tail_init(&chan->pending_interrupts_list,
+				      &chan->active_interrupts_list);
+		spin_unlock(&chan->active_interrupts_lock);
+		spin_unlock(&chan->pending_interrupts_lock);
+	}
+
+	if (chan->chan_programming)
+		queue_work(chan->chan_programming,
+			   &chan->handle_chan_programming);
+}
+
+static int xlnx_ps_pcie_dma_terminate_all(struct dma_chan *channel)
+{
+	struct ps_pcie_dma_chan *chan;
+
+	if (!channel)
+		return PTR_ERR(channel);
+
+	chan = to_xilinx_chan(channel);
+
+	if (chan->state != CHANNEL_AVAILABLE)
+		return 1;
+
+	if (chan->maintenance_workq) {
+		if (completion_done(&chan->chan_terminate_complete))
+			reinit_completion(&chan->chan_terminate_complete);
+		queue_work(chan->maintenance_workq,
+			   &chan->handle_chan_terminate);
+		wait_for_completion_interruptible(
+			   &chan->chan_terminate_complete);
+	}
+
+	return 0;
+}
+
+static struct dma_async_tx_descriptor *xlnx_ps_pcie_dma_prep_interrupt(
+		struct dma_chan *channel, unsigned long flags)
+{
+	struct ps_pcie_dma_chan *chan;
+	struct ps_pcie_intr_segment *intr_segment = NULL;
+
+	if (!channel)
+		return NULL;
+
+	chan = to_xilinx_chan(channel);
+
+	if (chan->state != CHANNEL_AVAILABLE)
+		return NULL;
+
+	intr_segment = mempool_alloc(chan->intr_transactions_pool, GFP_ATOMIC);
+
+	memset(intr_segment, 0, sizeof(*intr_segment));
+
+	dma_async_tx_descriptor_init(&intr_segment->async_intr_tx,
+				     &chan->common);
+	intr_segment->async_intr_tx.flags = flags;
+	async_tx_ack(&intr_segment->async_intr_tx);
+	intr_segment->async_intr_tx.tx_submit = xilinx_intr_tx_submit;
+
+	return &intr_segment->async_intr_tx;
+}
+
+static int xlnx_pcie_dma_driver_probe(struct platform_device *platform_dev)
+{
+	int err, i;
+	struct xlnx_pcie_dma_device *xdev;
+	static u16 board_number;
+
+	xdev = devm_kzalloc(&platform_dev->dev,
+			    sizeof(struct xlnx_pcie_dma_device), GFP_KERNEL);
+
+	if (!xdev)
+		return -ENOMEM;
+
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+	xdev->dma_buf_ext_addr = true;
+#else
+	xdev->dma_buf_ext_addr = false;
+#endif
+
+	xdev->is_rootdma = device_property_read_bool(&platform_dev->dev,
+						     "rootdma");
+
+	xdev->dev = &platform_dev->dev;
+	xdev->board_number = board_number;
+
+	err = device_property_read_u32(&platform_dev->dev, "numchannels",
+				       &xdev->num_channels);
+	if (err) {
+		dev_err(&platform_dev->dev,
+			"Unable to find numchannels property\n");
+		goto platform_driver_probe_return;
+	}
+
+	if (xdev->num_channels == 0 || xdev->num_channels >
+		MAX_ALLOWED_CHANNELS_IN_HW) {
+		dev_warn(&platform_dev->dev,
+			 "Invalid xlnx-num_channels property value\n");
+		xdev->num_channels = MAX_ALLOWED_CHANNELS_IN_HW;
+	}
+
+	xdev->channels =
+	(struct ps_pcie_dma_chan *)devm_kzalloc(&platform_dev->dev,
+						sizeof(struct ps_pcie_dma_chan)
+							* xdev->num_channels,
+						GFP_KERNEL);
+	if (!xdev->channels) {
+		err = -ENOMEM;
+		goto platform_driver_probe_return;
+	}
+
+	if (xdev->is_rootdma)
+		err = read_rootdma_config(platform_dev, xdev);
+	else
+		err = read_epdma_config(platform_dev, xdev);
+
+	if (err) {
+		dev_err(&platform_dev->dev,
+			"Unable to initialize dma configuration\n");
+		goto platform_driver_probe_return;
+	}
+
+	/* Initialize the DMA engine */
+	INIT_LIST_HEAD(&xdev->common.channels);
+
+	dma_cap_set(DMA_SLAVE, xdev->common.cap_mask);
+	dma_cap_set(DMA_PRIVATE, xdev->common.cap_mask);
+	dma_cap_set(DMA_INTERRUPT, xdev->common.cap_mask);
+	dma_cap_set(DMA_MEMCPY, xdev->common.cap_mask);
+
+	xdev->common.src_addr_widths = DMA_SLAVE_BUSWIDTH_UNDEFINED;
+	xdev->common.dst_addr_widths = DMA_SLAVE_BUSWIDTH_UNDEFINED;
+	xdev->common.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
+	xdev->common.device_alloc_chan_resources =
+		xlnx_ps_pcie_dma_alloc_chan_resources;
+	xdev->common.device_free_chan_resources =
+		xlnx_ps_pcie_dma_free_chan_resources;
+	xdev->common.device_terminate_all = xlnx_ps_pcie_dma_terminate_all;
+	xdev->common.device_tx_status =  dma_cookie_status;
+	xdev->common.device_issue_pending = xlnx_ps_pcie_dma_issue_pending;
+	xdev->common.device_prep_dma_interrupt =
+		xlnx_ps_pcie_dma_prep_interrupt;
+	xdev->common.device_prep_dma_memcpy = xlnx_ps_pcie_dma_prep_memcpy;
+	xdev->common.device_prep_slave_sg = xlnx_ps_pcie_dma_prep_slave_sg;
+	xdev->common.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT;
+
+	for (i = 0; i < xdev->num_channels; i++) {
+		err = probe_channel_properties(platform_dev, xdev, i);
+
+		if (err != 0) {
+			dev_err(xdev->dev,
+				"Unable to read channel properties\n");
+			goto platform_driver_probe_return;
+		}
+	}
+
+	if (xdev->is_rootdma)
+		err = platform_irq_setup(xdev);
+	else
+		err = irq_setup(xdev);
+	if (err) {
+		dev_err(xdev->dev, "Cannot request irq lines for device %d\n",
+			xdev->board_number);
+		goto platform_driver_probe_return;
+	}
+
+	err = dma_async_device_register(&xdev->common);
+	if (err) {
+		dev_err(xdev->dev,
+			"Unable to register board %d with dma framework\n",
+			xdev->board_number);
+		goto platform_driver_probe_return;
+	}
+
+	platform_set_drvdata(platform_dev, xdev);
+
+	board_number++;
+
+	dev_info(&platform_dev->dev, "PS PCIe Platform driver probed\n");
+	return 0;
+
+platform_driver_probe_return:
+	return err;
+}
+
+static int xlnx_pcie_dma_driver_remove(struct platform_device *platform_dev)
+{
+	struct xlnx_pcie_dma_device *xdev =
+		platform_get_drvdata(platform_dev);
+	int i;
+
+	for (i = 0; i < xdev->num_channels; i++)
+		xlnx_ps_pcie_dma_free_chan_resources(&xdev->channels[i].common);
+
+	dma_async_device_unregister(&xdev->common);
+
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id xlnx_pcie_root_dma_of_ids[] = {
+	{ .compatible = "xlnx,ps_pcie_dma-1.00.a", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, xlnx_pcie_root_dma_of_ids);
+#endif
+
+static struct platform_driver xlnx_pcie_dma_driver = {
+	.driver = {
+		.name = XLNX_PLATFORM_DRIVER_NAME,
+		.of_match_table = of_match_ptr(xlnx_pcie_root_dma_of_ids),
+		.owner = THIS_MODULE,
+	},
+	.probe =  xlnx_pcie_dma_driver_probe,
+	.remove = xlnx_pcie_dma_driver_remove,
+};
+
+int dma_platform_driver_register(void)
+{
+	return platform_driver_register(&xlnx_pcie_dma_driver);
+}
+
+void dma_platform_driver_unregister(void)
+{
+	platform_driver_unregister(&xlnx_pcie_dma_driver);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/dma/xilinx/zynqmp_dma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/dma/xilinx/zynqmp_dma.c
@@ -123,10 +123,12 @@
 /* Max transfer size per descriptor */
 #define ZYNQMP_DMA_MAX_TRANS_LEN	0x40000000
 
+/* Max burst lengths */
+#define ZYNQMP_DMA_MAX_DST_BURST_LEN    32768U
+#define ZYNQMP_DMA_MAX_SRC_BURST_LEN    32768U
+
 /* Reset values for data attributes */
 #define ZYNQMP_DMA_AXCACHE_VAL		0xF
-#define ZYNQMP_DMA_ARLEN_RST_VAL	0xF
-#define ZYNQMP_DMA_AWLEN_RST_VAL	0xF
 
 #define ZYNQMP_DMA_SRC_ISSUE_RST_VAL	0x1F
 
@@ -230,7 +232,7 @@
 	bool is_dmacoherent;
 	struct tasklet_struct tasklet;
 	bool idle;
-	u32 desc_size;
+	size_t desc_size;
 	bool err;
 	u32 bus_width;
 	u32 src_burst_len;
@@ -451,6 +453,7 @@
 
 	list_for_each_entry_safe(desc, next, list, node)
 		zynqmp_dma_free_descriptor(chan, desc);
+	INIT_LIST_HEAD(list);
 }
 
 /**
@@ -465,7 +468,7 @@
 	struct zynqmp_dma_desc_sw *desc;
 	int i, ret;
 
-	ret = pm_runtime_get_sync(chan->dev);
+	ret = pm_runtime_resume_and_get(chan->dev);
 	if (ret < 0)
 		return ret;
 
@@ -487,7 +490,8 @@
 	}
 
 	chan->desc_pool_v = dma_alloc_coherent(chan->dev,
-					       (2 * chan->desc_size * ZYNQMP_DMA_NUM_DESCS),
+					       (2 * ZYNQMP_DMA_DESC_SIZE(chan) *
+					       ZYNQMP_DMA_NUM_DESCS),
 					       &chan->desc_pool_p, GFP_KERNEL);
 	if (!chan->desc_pool_v)
 		return -ENOMEM;
@@ -534,17 +538,19 @@
 
 static void zynqmp_dma_config(struct zynqmp_dma_chan *chan)
 {
-	u32 val;
+	u32 val, burst_val;
 
 	val = readl(chan->regs + ZYNQMP_DMA_CTRL0);
 	val |= ZYNQMP_DMA_POINT_TYPE_SG;
 	writel(val, chan->regs + ZYNQMP_DMA_CTRL0);
 
 	val = readl(chan->regs + ZYNQMP_DMA_DATA_ATTR);
+	burst_val = __ilog2_u32(chan->src_burst_len);
 	val = (val & ~ZYNQMP_DMA_ARLEN) |
-		(chan->src_burst_len << ZYNQMP_DMA_ARLEN_OFST);
+		((burst_val << ZYNQMP_DMA_ARLEN_OFST) & ZYNQMP_DMA_ARLEN);
+	burst_val = __ilog2_u32(chan->dst_burst_len);
 	val = (val & ~ZYNQMP_DMA_AWLEN) |
-		(chan->dst_burst_len << ZYNQMP_DMA_AWLEN_OFST);
+		((burst_val << ZYNQMP_DMA_AWLEN_OFST) & ZYNQMP_DMA_AWLEN);
 	writel(val, chan->regs + ZYNQMP_DMA_DATA_ATTR);
 }
 
@@ -560,8 +566,10 @@
 {
 	struct zynqmp_dma_chan *chan = to_chan(dchan);
 
-	chan->src_burst_len = config->src_maxburst;
-	chan->dst_burst_len = config->dst_maxburst;
+	chan->src_burst_len = clamp(config->src_maxburst, 1U,
+		ZYNQMP_DMA_MAX_SRC_BURST_LEN);
+	chan->dst_burst_len = clamp(config->dst_maxburst, 1U,
+		ZYNQMP_DMA_MAX_DST_BURST_LEN);
 
 	return 0;
 }
@@ -887,8 +895,8 @@
 		return PTR_ERR(chan->regs);
 
 	chan->bus_width = ZYNQMP_DMA_BUS_WIDTH_64;
-	chan->dst_burst_len = ZYNQMP_DMA_AWLEN_RST_VAL;
-	chan->src_burst_len = ZYNQMP_DMA_ARLEN_RST_VAL;
+	chan->dst_burst_len = ZYNQMP_DMA_MAX_DST_BURST_LEN;
+	chan->src_burst_len = ZYNQMP_DMA_MAX_SRC_BURST_LEN;
 	err = of_property_read_u32(node, "xlnx,bus-width", &chan->bus_width);
 	if (err < 0) {
 		dev_err(&pdev->dev, "missing xlnx,bus-width property\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/Kconfig
@@ -334,6 +334,13 @@
 	  a companion chip to the PowerPC 970 family of
 	  processors.
 
+config EDAC_PL310_L2
+	tristate "Pl310 L2 Cache Controller"
+	depends on ARM
+	help
+	  Support for parity error detection on L2 cache controller
+	  data and tag ram memory
+
 config EDAC_HIGHBANK_MC
 	tristate "Highbank Memory Controller"
 	depends on ARCH_HIGHBANK
@@ -480,6 +487,13 @@
 	  Support for error detection and correction on the Synopsys DDR
 	  memory controller.
 
+config EDAC_ZYNQMP_OCM
+	tristate "Xilinx ZynqMP OCM Controller"
+	depends on ARCH_ZYNQMP
+	help
+	  Support for error detection and correction on the xilinx ZynqMP OCM
+	  controller.
+
 config EDAC_XGENE
 	tristate "APM X-Gene SoC"
 	depends on (ARM64 || COMPILE_TEST)
@@ -487,6 +501,14 @@
 	  Support for error detection and correction on the
 	  APM X-Gene family of SOCs.
 
+config EDAC_CORTEX_ARM64
+	tristate "ARM Cortex A57/A53"
+	default y if !CPU_IDLE
+	depends on !CPU_IDLE && ARM64
+	help
+	  Support for error detection and correction on the
+	  ARM Cortex A57 and A53.
+
 config EDAC_TI
 	tristate "Texas Instruments DDR3 ECC Controller"
 	depends on ARCH_KEYSTONE || SOC_DRA7XX
@@ -524,4 +546,15 @@
 	  Support for error detection and correction on the
 	  Mellanox BlueField SoCs.
 
+config EDAC_XILINX_DDR
+	tristate "Xilinx Versal DDR Memory Controller"
+	depends on ARCH_ZYNQMP
+	help
+	  Support for error detection and correction on the Xilinx Versal DDR
+	  memory controller.
+
+	  Report both Single Bit Errors (CE) and Double Bit Errors (UE).
+	  Support injecting both Correctable and UnCorrectable errors for debug
+	  purpose using sysfs entries.
+
 endif # EDAC
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/Makefile
@@ -57,11 +57,13 @@
 layerscape_edac_mod-y			:= fsl_ddr_edac.o layerscape_edac.o
 obj-$(CONFIG_EDAC_LAYERSCAPE)		+= layerscape_edac_mod.o
 
-skx_edac-y				:= skx_common.o skx_base.o
-obj-$(CONFIG_EDAC_SKX)			+= skx_edac.o
+skx_edac_common-y			:= skx_common.o
 
-i10nm_edac-y				:= skx_common.o i10nm_base.o
-obj-$(CONFIG_EDAC_I10NM)		+= i10nm_edac.o
+skx_edac-y				:= skx_base.o
+obj-$(CONFIG_EDAC_SKX)			+= skx_edac.o skx_edac_common.o
+
+i10nm_edac-y				:= i10nm_base.o
+obj-$(CONFIG_EDAC_I10NM)		+= i10nm_edac.o skx_edac_common.o
 
 obj-$(CONFIG_EDAC_MV64X60)		+= mv64x60_edac.o
 obj-$(CONFIG_EDAC_CELL)			+= cell_edac.o
@@ -79,11 +81,15 @@
 obj-$(CONFIG_EDAC_THUNDERX)		+= thunderx_edac.o
 
 obj-$(CONFIG_EDAC_ALTERA)		+= altera_edac.o
+obj-$(CONFIG_EDAC_PL310_L2)		+= pl310_edac_l2.o
 obj-$(CONFIG_EDAC_SIFIVE)		+= sifive_edac.o
 obj-$(CONFIG_EDAC_ARMADA_XP)		+= armada_xp_edac.o
 obj-$(CONFIG_EDAC_SYNOPSYS)		+= synopsys_edac.o
 obj-$(CONFIG_EDAC_XGENE)		+= xgene_edac.o
+obj-$(CONFIG_EDAC_CORTEX_ARM64)		+= cortex_arm64_edac.o
+obj-$(CONFIG_EDAC_ZYNQMP_OCM)		+= zynqmp_ocm_edac.o
 obj-$(CONFIG_EDAC_TI)			+= ti_edac.o
 obj-$(CONFIG_EDAC_QCOM)			+= qcom_edac.o
 obj-$(CONFIG_EDAC_ASPEED)		+= aspeed_edac.o
 obj-$(CONFIG_EDAC_BLUEFIELD)		+= bluefield_edac.o
+obj-$(CONFIG_EDAC_XILINX_DDR)		+= xilinx_ddrmc_edac.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/altera_edac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/altera_edac.c
@@ -349,7 +349,7 @@
 	if (irq < 0) {
 		edac_printk(KERN_ERR, EDAC_MC,
 			    "No irq %d in DT\n", irq);
-		return -ENODEV;
+		return irq;
 	}
 
 	/* Arria10 has a 2nd IRQ */
@@ -560,6 +560,7 @@
 	.reg_write = s10_protected_reg_write,
 	.use_single_read = true,
 	.use_single_write = true,
+	.fast_io = true,
 };
 
 /************** </Stratix10 EDAC Memory Controller Functions> ***********/
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/amd64_edac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/amd64_edac.c
@@ -22,6 +22,9 @@
 /* Number of Unified Memory Controllers */
 static u8 num_umcs;
 
+/* Device for the PCI component */
+static struct device *pci_ctl_dev;
+
 /*
  * Valid scrub rates for the K8 hardware memory scrubber. We map the scrubbing
  * bandwidth to a valid bit pattern. The 'set' operation finds the 'matching-
@@ -215,7 +218,7 @@
 
 	scrubval = scrubrates[i].scrubval;
 
-	if (pvt->fam == 0x17 || pvt->fam == 0x18) {
+	if (pvt->umc) {
 		__f17h_set_scrubval(pvt, scrubval);
 	} else if (pvt->fam == 0x15 && pvt->model == 0x60) {
 		f15h_select_dct(pvt, 0);
@@ -257,18 +260,7 @@
 	int i, retval = -EINVAL;
 	u32 scrubval = 0;
 
-	switch (pvt->fam) {
-	case 0x15:
-		/* Erratum #505 */
-		if (pvt->model < 0x10)
-			f15h_select_dct(pvt, 0);
-
-		if (pvt->model == 0x60)
-			amd64_read_pci_cfg(pvt->F2, F15H_M60H_SCRCTRL, &scrubval);
-		break;
-
-	case 0x17:
-	case 0x18:
+	if (pvt->umc) {
 		amd64_read_pci_cfg(pvt->F6, F17H_SCR_BASE_ADDR, &scrubval);
 		if (scrubval & BIT(0)) {
 			amd64_read_pci_cfg(pvt->F6, F17H_SCR_LIMIT_ADDR, &scrubval);
@@ -277,11 +269,17 @@
 		} else {
 			scrubval = 0;
 		}
-		break;
+	} else if (pvt->fam == 0x15) {
+		/* Erratum #505 */
+		if (pvt->model < 0x10)
+			f15h_select_dct(pvt, 0);
 
-	default:
+		if (pvt->model == 0x60)
+			amd64_read_pci_cfg(pvt->F2, F15H_M60H_SCRCTRL, &scrubval);
+		else
+			amd64_read_pci_cfg(pvt->F3, SCRCTRL, &scrubval);
+	} else {
 		amd64_read_pci_cfg(pvt->F3, SCRCTRL, &scrubval);
-		break;
 	}
 
 	scrubval = scrubval & 0x001F;
@@ -792,12 +790,14 @@
 #define CS_ODD_PRIMARY		BIT(1)
 #define CS_EVEN_SECONDARY	BIT(2)
 #define CS_ODD_SECONDARY	BIT(3)
+#define CS_3R_INTERLEAVE	BIT(4)
 
 #define CS_EVEN			(CS_EVEN_PRIMARY | CS_EVEN_SECONDARY)
 #define CS_ODD			(CS_ODD_PRIMARY | CS_ODD_SECONDARY)
 
 static int f17_get_cs_mode(int dimm, u8 ctrl, struct amd64_pvt *pvt)
 {
+	u8 base, count = 0;
 	int cs_mode = 0;
 
 	if (csrow_enabled(2 * dimm, ctrl, pvt))
@@ -810,6 +810,20 @@
 	if (csrow_sec_enabled(2 * dimm + 1, ctrl, pvt))
 		cs_mode |= CS_ODD_SECONDARY;
 
+	/*
+	 * 3 Rank inteleaving support.
+	 * There should be only three bases enabled and their two masks should
+	 * be equal.
+	 */
+	for_each_chip_select(base, ctrl, pvt)
+		count += csrow_enabled(base, ctrl, pvt);
+
+	if (count == 3 &&
+	    pvt->csels[ctrl].csmasks[0] == pvt->csels[ctrl].csmasks[1]) {
+		edac_dbg(1, "3R interleaving in use.\n");
+		cs_mode |= CS_3R_INTERLEAVE;
+	}
+
 	return cs_mode;
 }
 
@@ -1056,6 +1070,16 @@
 {
 	u32 dram_ctrl, dcsm;
 
+	if (pvt->umc) {
+		if ((pvt->umc[0].dimm_cfg | pvt->umc[1].dimm_cfg) & BIT(5))
+			pvt->dram_type = MEM_LRDDR4;
+		else if ((pvt->umc[0].dimm_cfg | pvt->umc[1].dimm_cfg) & BIT(4))
+			pvt->dram_type = MEM_RDDR4;
+		else
+			pvt->dram_type = MEM_DDR4;
+		return;
+	}
+
 	switch (pvt->fam) {
 	case 0xf:
 		if (pvt->ext_model >= K8_REV_F)
@@ -1101,16 +1125,6 @@
 	case 0x16:
 		goto ddr3;
 
-	case 0x17:
-	case 0x18:
-		if ((pvt->umc[0].dimm_cfg | pvt->umc[1].dimm_cfg) & BIT(5))
-			pvt->dram_type = MEM_LRDDR4;
-		else if ((pvt->umc[0].dimm_cfg | pvt->umc[1].dimm_cfg) & BIT(4))
-			pvt->dram_type = MEM_RDDR4;
-		else
-			pvt->dram_type = MEM_DDR4;
-		return;
-
 	default:
 		WARN(1, KERN_ERR "%s: Family??? 0x%x\n", __func__, pvt->fam);
 		pvt->dram_type = MEM_EMPTY;
@@ -1618,10 +1632,14 @@
 	 *
 	 * The MSB is the number of bits in the full mask because BIT[0] is
 	 * always 0.
+	 *
+	 * In the special 3 Rank interleaving case, a single bit is flipped
+	 * without swapping with the most significant bit. This can be handled
+	 * by keeping the MSB where it is and ignoring the single zero bit.
 	 */
 	msb = fls(addr_mask_orig) - 1;
 	weight = hweight_long(addr_mask_orig);
-	num_zero_bits = msb - weight;
+	num_zero_bits = msb - weight - !!(cs_mode & CS_3R_INTERLEAVE);
 
 	/* Take the number of zero bits off from the top of the mask. */
 	addr_mask_deinterleaved = GENMASK_ULL(msb - num_zero_bits, 1);
@@ -2317,6 +2335,15 @@
 			.dbam_to_cs		= f17_addr_mask_to_cs_size,
 		}
 	},
+	[F17_M60H_CPUS] = {
+		.ctl_name = "F17h_M60h",
+		.f0_id = PCI_DEVICE_ID_AMD_17H_M60H_DF_F0,
+		.f6_id = PCI_DEVICE_ID_AMD_17H_M60H_DF_F6,
+		.ops = {
+			.early_channel_count	= f17_early_channel_count,
+			.dbam_to_cs		= f17_addr_mask_to_cs_size,
+		}
+	},
 	[F17_M70H_CPUS] = {
 		.ctl_name = "F17h_M70h",
 		.f0_id = PCI_DEVICE_ID_AMD_17H_M70H_DF_F0,
@@ -2326,6 +2353,15 @@
 			.dbam_to_cs		= f17_addr_mask_to_cs_size,
 		}
 	},
+	[F19_CPUS] = {
+		.ctl_name = "F19h",
+		.f0_id = PCI_DEVICE_ID_AMD_19H_DF_F0,
+		.f6_id = PCI_DEVICE_ID_AMD_19H_DF_F6,
+		.ops = {
+			.early_channel_count	= f17_early_channel_count,
+			.dbam_to_cs		= f17_addr_mask_to_cs_size,
+		}
+	},
 };
 
 /*
@@ -2661,6 +2697,9 @@
 			return -ENODEV;
 		}
 
+		if (!pci_ctl_dev)
+			pci_ctl_dev = &pvt->F0->dev;
+
 		edac_dbg(1, "F0: %s\n", pci_name(pvt->F0));
 		edac_dbg(1, "F3: %s\n", pci_name(pvt->F3));
 		edac_dbg(1, "F6: %s\n", pci_name(pvt->F6));
@@ -2685,6 +2724,9 @@
 		return -ENODEV;
 	}
 
+	if (!pci_ctl_dev)
+		pci_ctl_dev = &pvt->F2->dev;
+
 	edac_dbg(1, "F1: %s\n", pci_name(pvt->F1));
 	edac_dbg(1, "F2: %s\n", pci_name(pvt->F2));
 	edac_dbg(1, "F3: %s\n", pci_name(pvt->F3));
@@ -2936,6 +2978,7 @@
 			dimm->mtype = pvt->dram_type;
 			dimm->edac_mode = edac_mode;
 			dimm->dtype = dev_type;
+			dimm->grain = 64;
 		}
 	}
 
@@ -3012,6 +3055,7 @@
 			dimm = csrow->channels[j]->dimm;
 			dimm->mtype = pvt->dram_type;
 			dimm->edac_mode = edac_mode;
+			dimm->grain = 64;
 		}
 	}
 
@@ -3364,6 +3408,10 @@
 			fam_type = &family_types[F17_M30H_CPUS];
 			pvt->ops = &family_types[F17_M30H_CPUS].ops;
 			break;
+		} else if (pvt->model >= 0x60 && pvt->model <= 0x6f) {
+			fam_type = &family_types[F17_M60H_CPUS];
+			pvt->ops = &family_types[F17_M60H_CPUS].ops;
+			break;
 		} else if (pvt->model >= 0x70 && pvt->model <= 0x7f) {
 			fam_type = &family_types[F17_M70H_CPUS];
 			pvt->ops = &family_types[F17_M70H_CPUS].ops;
@@ -3378,6 +3426,12 @@
 			family_types[F17_CPUS].ctl_name = "F18h";
 		break;
 
+	case 0x19:
+		fam_type	= &family_types[F19_CPUS];
+		pvt->ops	= &family_types[F19_CPUS].ops;
+		family_types[F19_CPUS].ctl_name = "F19h";
+		break;
+
 	default:
 		amd64_err("Unsupported family!\n");
 		return NULL;
@@ -3609,21 +3663,10 @@
 
 static void setup_pci_device(void)
 {
-	struct mem_ctl_info *mci;
-	struct amd64_pvt *pvt;
-
 	if (pci_ctl)
 		return;
 
-	mci = edac_mc_find(0);
-	if (!mci)
-		return;
-
-	pvt = mci->pvt_info;
-	if (pvt->umc)
-		pci_ctl = edac_pci_create_generic_ctl(&pvt->F0->dev, EDAC_MOD_STR);
-	else
-		pci_ctl = edac_pci_create_generic_ctl(&pvt->F2->dev, EDAC_MOD_STR);
+	pci_ctl = edac_pci_create_generic_ctl(pci_ctl_dev, EDAC_MOD_STR);
 	if (!pci_ctl) {
 		pr_warn("%s(): Unable to create PCI control\n", __func__);
 		pr_warn("%s(): PCI error report via EDAC not set\n", __func__);
@@ -3637,6 +3680,7 @@
 	{ X86_VENDOR_AMD, 0x16, X86_MODEL_ANY,	X86_FEATURE_ANY, 0 },
 	{ X86_VENDOR_AMD, 0x17, X86_MODEL_ANY,	X86_FEATURE_ANY, 0 },
 	{ X86_VENDOR_HYGON, 0x18, X86_MODEL_ANY, X86_FEATURE_ANY, 0 },
+	{ X86_VENDOR_AMD, 0x19, X86_MODEL_ANY,	X86_FEATURE_ANY, 0 },
 	{ }
 };
 MODULE_DEVICE_TABLE(x86cpu, amd64_cpuids);
@@ -3706,6 +3750,8 @@
 	return 0;
 
 err_pci:
+	pci_ctl_dev = NULL;
+
 	msrs_free(msrs);
 	msrs = NULL;
 
@@ -3737,6 +3783,8 @@
 	kfree(ecc_stngs);
 	ecc_stngs = NULL;
 
+	pci_ctl_dev = NULL;
+
 	msrs_free(msrs);
 	msrs = NULL;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/amd64_edac.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/amd64_edac.h
@@ -120,8 +120,12 @@
 #define PCI_DEVICE_ID_AMD_17H_M10H_DF_F6 0x15ee
 #define PCI_DEVICE_ID_AMD_17H_M30H_DF_F0 0x1490
 #define PCI_DEVICE_ID_AMD_17H_M30H_DF_F6 0x1496
+#define PCI_DEVICE_ID_AMD_17H_M60H_DF_F0 0x1448
+#define PCI_DEVICE_ID_AMD_17H_M60H_DF_F6 0x144e
 #define PCI_DEVICE_ID_AMD_17H_M70H_DF_F0 0x1440
 #define PCI_DEVICE_ID_AMD_17H_M70H_DF_F6 0x1446
+#define PCI_DEVICE_ID_AMD_19H_DF_F0	0x1650
+#define PCI_DEVICE_ID_AMD_19H_DF_F6	0x1656
 
 /*
  * Function 1 - Address Map
@@ -291,7 +295,9 @@
 	F17_CPUS,
 	F17_M10H_CPUS,
 	F17_M30H_CPUS,
+	F17_M60H_CPUS,
 	F17_M70H_CPUS,
+	F19_CPUS,
 	NUM_FAMILIES,
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/armada_xp_edac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/armada_xp_edac.c
@@ -178,7 +178,7 @@
 				     "details unavailable (multiple errors)");
 	if (cnt_dbe)
 		edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci,
-				     cnt_sbe, /* error count */
+				     cnt_dbe, /* error count */
 				     0, 0, 0, /* pfn, offset, syndrome */
 				     -1, -1, -1, /* top, mid, low layer */
 				     mci->ctl_name,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/aspeed_edac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/aspeed_edac.c
@@ -209,8 +209,8 @@
 	/* register interrupt handler */
 	irq = platform_get_irq(pdev, 0);
 	dev_dbg(&pdev->dev, "got irq %d\n", irq);
-	if (!irq)
-		return -ENODEV;
+	if (irq < 0)
+		return irq;
 
 	rc = devm_request_irq(&pdev->dev, irq, mcr_isr, IRQF_TRIGGER_HIGH,
 			      DRV_NAME, ctx);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/bluefield_edac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/bluefield_edac.c
@@ -180,7 +180,7 @@
 static void bluefield_edac_init_dimms(struct mem_ctl_info *mci)
 {
 	struct bluefield_edac_priv *priv = mci->pvt_info;
-	int mem_ctrl_idx = mci->mc_idx;
+	u64 mem_ctrl_idx = mci->mc_idx;
 	struct dimm_info *dimm;
 	u64 smc_info, smc_arg;
 	int is_empty = 1, i;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/cortex_arm64_edac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/cortex_arm64_edac.c
@@ -0,0 +1,470 @@
+/*
+ * Cortex A57 and A53 EDAC
+ *
+ * Copyright (c) 2015, Advanced Micro Devices
+ * Author: Brijesh Singh <brijeshkumar.singh@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <ras/ras_event.h>
+
+#include "edac_module.h"
+
+#define DRV_NAME			"cortex_edac"
+
+#define CPUMERRSR_EL1_INDEX(x, y)	((x) & (y))
+#define CPUMERRSR_EL1_BANK_WAY(x, y)	(((x) >> 18) & (y))
+#define CPUMERRSR_EL1_RAMID(x)		(((x) >> 24) & 0x7f)
+#define CPUMERRSR_EL1_VALID(x)		((x) & (1 << 31))
+#define CPUMERRSR_EL1_REPEAT(x)		(((x) >> 32) & 0x7f)
+#define CPUMERRSR_EL1_OTHER(x)		(((x) >> 40) & 0xff)
+#define CPUMERRSR_EL1_FATAL(x)		((x) & (1UL << 63))
+#define L1_I_TAG_RAM			0x00
+#define L1_I_DATA_RAM			0x01
+#define L1_D_TAG_RAM			0x08
+#define L1_D_DATA_RAM			0x09
+#define L1_D_DIRTY_RAM			0x14
+#define TLB_RAM				0x18
+
+#define L2MERRSR_EL1_CPUID_WAY(x)	(((x) >> 18) & 0xf)
+#define L2MERRSR_EL1_RAMID(x)		(((x) >> 24) & 0x7f)
+#define L2MERRSR_EL1_VALID(x)		((x) & (1 << 31))
+#define L2MERRSR_EL1_REPEAT(x)		(((x) >> 32) & 0xff)
+#define L2MERRSR_EL1_OTHER(x)		(((x) >> 40) & 0xff)
+#define L2MERRSR_EL1_FATAL(x)		((x) & (1UL << 63))
+#define L2_TAG_RAM			0x10
+#define L2_DATA_RAM			0x11
+#define L2_SNOOP_RAM			0x12
+#define L2_DIRTY_RAM			0x14
+#define L2_INCLUSION_PF_RAM		0x18
+
+#define L1_CACHE			0
+#define L2_CACHE			1
+
+#define EDAC_MOD_STR			DRV_NAME
+
+/* Error injectin macros*/
+#define L1_DCACHE_ERRINJ_ENABLE		(1 << 6)
+#define L1_DCACHE_ERRINJ_DISABLE	(~(1 << 6))
+#define L2_DCACHE_ERRINJ_ENABLE		(1 << 29)
+#define L2_DCACHE_ERRINJ_DISABLE	(~(1 << 29))
+#define L2_ECC_PROTECTION		(1 << 22)
+
+static int poll_msec = 100;
+
+struct cortex_arm64_edac {
+	struct edac_device_ctl_info *edac_ctl;
+};
+
+static inline u64 read_cpumerrsr_el1(void)
+{
+	u64 val;
+
+	asm volatile("mrs %0, s3_1_c15_c2_2" : "=r" (val));
+	return val;
+}
+
+static inline void write_cpumerrsr_el1(u64 val)
+{
+	asm volatile("msr s3_1_c15_c2_2, %0" :: "r" (val));
+}
+
+static inline u64 read_l2merrsr_el1(void)
+{
+	u64 val;
+
+	asm volatile("mrs %0, s3_1_c15_c2_3" : "=r" (val));
+	return val;
+}
+
+static inline void write_l2merrsr_el1(u64 val)
+{
+	asm volatile("msr s3_1_c15_c2_3, %0" :: "r" (val));
+}
+
+static inline void cortexa53_edac_busy_on_inst(void)
+{
+	asm volatile("isb sy");
+}
+
+static inline void cortexa53_edac_busy_on_data(void)
+{
+	asm volatile("dsb sy");
+}
+
+static inline void write_l2actrl_el1(u64 val)
+{
+	asm volatile("msr s3_1_c15_c0_0, %0" :: "r" (val));
+	cortexa53_edac_busy_on_inst();
+}
+
+static inline u64 read_l2actrl_el1(void)
+{
+	u64 val;
+
+	asm volatile("mrs %0, s3_1_c15_c0_0" : "=r" (val));
+	return val;
+}
+
+static inline u64 read_l2ctlr_el1(void)
+{
+	u64 rval;
+
+	asm volatile("mrs %0,  S3_1_C11_C0_2" : "=r" (rval));
+	return rval;
+
+}
+
+static inline u64 read_l1actrl_el1(void)
+{
+	u64 rval;
+
+	asm volatile("mrs %0,  S3_1_C15_C2_0" : "=r" (rval));
+	return rval;
+}
+
+static inline void write_l1actrl_el1(u64 val)
+{
+	asm volatile("msr S3_1_C15_C2_0, %0" :: "r" (val));
+}
+
+static void parse_cpumerrsr(void *arg)
+{
+	int cpu, partnum, way;
+	unsigned int index = 0;
+	u64 val = read_cpumerrsr_el1();
+	int repeat_err, other_err;
+
+	/* we do not support fatal error handling so far */
+	if (CPUMERRSR_EL1_FATAL(val))
+		return;
+
+	/* check if we have valid error before continuing */
+	if (!CPUMERRSR_EL1_VALID(val))
+		return;
+
+	cpu = smp_processor_id();
+	partnum = read_cpuid_part_number();
+	repeat_err = CPUMERRSR_EL1_REPEAT(val);
+	other_err = CPUMERRSR_EL1_OTHER(val);
+
+	/* way/bank and index address bit ranges are different between
+	 * A57 and A53 */
+	if (partnum == ARM_CPU_PART_CORTEX_A57) {
+		index = CPUMERRSR_EL1_INDEX(val, 0x1ffff);
+		way = CPUMERRSR_EL1_BANK_WAY(val, 0x1f);
+	} else {
+		index = CPUMERRSR_EL1_INDEX(val, 0xfff);
+		way = CPUMERRSR_EL1_BANK_WAY(val, 0x7);
+	}
+
+	edac_printk(KERN_CRIT, EDAC_MOD_STR, "CPU%d L1 error detected!\n", cpu);
+	edac_printk(KERN_CRIT, EDAC_MOD_STR, "index=%#x, RAMID=", index);
+
+	switch (CPUMERRSR_EL1_RAMID(val)) {
+	case L1_I_TAG_RAM:
+		pr_cont("'L1-I Tag RAM' (way %d)", way);
+		break;
+	case L1_I_DATA_RAM:
+		pr_cont("'L1-I Data RAM' (bank %d)", way);
+		break;
+	case L1_D_TAG_RAM:
+		pr_cont("'L1-D Tag RAM' (way %d)", way);
+		break;
+	case L1_D_DATA_RAM:
+		pr_cont("'L1-D Data RAM' (bank %d)", way);
+		break;
+	case L1_D_DIRTY_RAM:
+		pr_cont("'L1 Dirty RAM'");
+		break;
+	case TLB_RAM:
+		pr_cont("'TLB RAM'");
+		break;
+	default:
+		pr_cont("'unknown'");
+		break;
+	}
+
+	pr_cont(", repeat=%d, other=%d (CPUMERRSR_EL1=%#llx)\n", repeat_err,
+		other_err, val);
+
+	trace_mc_event(HW_EVENT_ERR_CORRECTED, "L1 non-fatal error",
+		       "", repeat_err, 0, 0, 0, -1, index, 0, 0, DRV_NAME);
+	write_cpumerrsr_el1(0);
+}
+
+static void a57_parse_l2merrsr_way(u8 ramid, u8 val)
+{
+	switch (ramid) {
+	case L2_TAG_RAM:
+	case L2_DATA_RAM:
+	case L2_DIRTY_RAM:
+		pr_cont("(cpu%d tag, way %d)", val / 2, val % 2);
+		break;
+	case L2_SNOOP_RAM:
+		pr_cont("(cpu%d tag, way %d)", (val & 0x6) >> 1,
+			(val & 0x1));
+		break;
+	}
+}
+
+static void a53_parse_l2merrsr_way(u8 ramid, u8 val)
+{
+	switch (ramid) {
+	case L2_TAG_RAM:
+		pr_cont("(way %d)", val);
+	case L2_DATA_RAM:
+		pr_cont("(bank %d)", val);
+		break;
+	case L2_SNOOP_RAM:
+		pr_cont("(cpu%d tag, way %d)", val / 2, val % 4);
+		break;
+	}
+}
+
+static void parse_l2merrsr(void *arg)
+{
+	int cpu, partnum;
+	unsigned int index;
+	int repeat_err, other_err;
+	u64 val = read_l2merrsr_el1();
+
+	/* we do not support fatal error handling so far */
+	if (L2MERRSR_EL1_FATAL(val))
+		return;
+
+	/* check if we have valid error before continuing */
+	if (!L2MERRSR_EL1_VALID(val))
+		return;
+
+	cpu = smp_processor_id();
+	partnum = read_cpuid_part_number();
+	repeat_err = L2MERRSR_EL1_REPEAT(val);
+	other_err = L2MERRSR_EL1_OTHER(val);
+
+	/* index address range is different between A57 and A53 */
+	if (partnum == ARM_CPU_PART_CORTEX_A57)
+		index = val & 0x1ffff;
+	else
+		index = (val >> 3) & 0x3fff;
+
+	edac_printk(KERN_CRIT, EDAC_MOD_STR, "CPU%d L2 error detected!\n", cpu);
+	edac_printk(KERN_CRIT, EDAC_MOD_STR, "index=%#x RAMID=", index);
+
+	switch (L2MERRSR_EL1_RAMID(val)) {
+	case L2_TAG_RAM:
+		pr_cont("'L2 Tag RAM'");
+		break;
+	case L2_DATA_RAM:
+		pr_cont("'L2 Data RAM'");
+		break;
+	case L2_SNOOP_RAM:
+		pr_cont("'L2 Snoop tag RAM'");
+		break;
+	case L2_DIRTY_RAM:
+		pr_cont("'L2 Dirty RAM'");
+		break;
+	case L2_INCLUSION_PF_RAM:
+		pr_cont("'L2 inclusion PF RAM'");
+		break;
+	default:
+		pr_cont("unknown");
+		break;
+	}
+
+	/* cpuid/way bit description is different between A57 and A53 */
+	if (partnum == ARM_CPU_PART_CORTEX_A57)
+		a57_parse_l2merrsr_way(L2MERRSR_EL1_RAMID(val),
+				       L2MERRSR_EL1_CPUID_WAY(val));
+	else
+		a53_parse_l2merrsr_way(L2MERRSR_EL1_RAMID(val),
+				       L2MERRSR_EL1_CPUID_WAY(val));
+
+	pr_cont(", repeat=%d, other=%d (L2MERRSR_EL1=%#llx)\n", repeat_err,
+		other_err, val);
+	trace_mc_event(HW_EVENT_ERR_CORRECTED, "L2 non-fatal error",
+		       "", repeat_err, 0, 0, 0, -1, index, 0, 0, DRV_NAME);
+	write_l2merrsr_el1(0);
+}
+
+static void cortex_arm64_edac_check(struct edac_device_ctl_info *edac_ctl)
+{
+	int cpu;
+	struct cpumask cluster_mask, old_mask;
+
+	cpumask_clear(&cluster_mask);
+	cpumask_clear(&old_mask);
+
+	get_online_cpus();
+	for_each_online_cpu(cpu) {
+		/* Check CPU L1 error */
+		smp_call_function_single(cpu, parse_cpumerrsr, NULL, 0);
+		cpumask_copy(&cluster_mask, topology_core_cpumask(cpu));
+		if (cpumask_equal(&cluster_mask, &old_mask))
+			continue;
+		cpumask_copy(&old_mask, &cluster_mask);
+		/* Check CPU L2 error */
+		smp_call_function_any(&cluster_mask, parse_l2merrsr, NULL, 0);
+	}
+	put_online_cpus();
+}
+
+static ssize_t cortexa53_edac_inject_L2_show(struct edac_device_ctl_info
+							*dci, char *data)
+{
+	return sprintf(data, "L2ACTLR_EL1: [0x%llx]\n\r", read_l2actrl_el1());
+}
+
+static ssize_t cortexa53_edac_inject_L2_store(
+		struct edac_device_ctl_info *dci, const char *data,
+		size_t count)
+{
+	u64 l2actrl, l2ecc;
+
+	if (!data)
+		return -EFAULT;
+
+	l2ecc = read_l2ctlr_el1();
+	if ((l2ecc & L2_ECC_PROTECTION)) {
+		l2actrl = read_l2actrl_el1();
+		l2actrl = l2actrl | L2_DCACHE_ERRINJ_ENABLE;
+		write_l2actrl_el1(l2actrl);
+		cortexa53_edac_busy_on_inst();
+	} else {
+		edac_printk(KERN_CRIT, EDAC_MOD_STR, "L2 ECC not enabled\n");
+	}
+
+	return count;
+}
+
+static ssize_t cortexa53_edac_inject_L1_show(struct edac_device_ctl_info
+							*dci, char *data)
+{
+	return sprintf(data, "L1CTLR_EL1: [0x%llx]\n\r", read_l1actrl_el1());
+}
+
+static ssize_t cortexa53_edac_inject_L1_store(
+		struct edac_device_ctl_info *dci, const char *data,
+		size_t count)
+{
+	u64 l1actrl;
+
+	if (!data)
+		return -EFAULT;
+
+	l1actrl = read_l1actrl_el1();
+	l1actrl |= L1_DCACHE_ERRINJ_ENABLE;
+	write_l1actrl_el1(l1actrl);
+	cortexa53_edac_busy_on_inst();
+
+	return count;
+}
+
+static struct edac_dev_sysfs_attribute cortexa53_edac_sysfs_attributes[] = {
+	{
+		.attr = {
+			.name = "inject_L2_Cache_Error",
+			.mode = (S_IRUGO | S_IWUSR)
+		},
+		.show = cortexa53_edac_inject_L2_show,
+		.store = cortexa53_edac_inject_L2_store},
+	{
+		.attr = {
+			.name = "inject_L1_Cache_Error",
+			.mode = (S_IRUGO | S_IWUSR)
+		},
+		.show = cortexa53_edac_inject_L1_show,
+		.store = cortexa53_edac_inject_L1_store},
+
+	/* End of list */
+	{
+		.attr = {.name = NULL}
+	}
+};
+
+static void cortexa53_set_edac_sysfs_attributes(struct edac_device_ctl_info
+						*edac_dev)
+{
+	edac_dev->sysfs_attributes = cortexa53_edac_sysfs_attributes;
+}
+
+static int cortex_arm64_edac_probe(struct platform_device *pdev)
+{
+	int rc;
+	struct cortex_arm64_edac *drv;
+	struct device *dev = &pdev->dev;
+
+	drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL);
+	if (!drv)
+		return -ENOMEM;
+
+	/* Only POLL mode is supported */
+	edac_op_state = EDAC_OPSTATE_POLL;
+
+	drv->edac_ctl = edac_device_alloc_ctl_info(0, "cpu_cache", 1, "L", 2,
+						   0, NULL, 0,
+						   edac_device_alloc_index());
+	if (IS_ERR(drv->edac_ctl))
+		return -ENOMEM;
+
+	drv->edac_ctl->poll_msec = poll_msec;
+	drv->edac_ctl->edac_check = cortex_arm64_edac_check;
+	drv->edac_ctl->dev = dev;
+	drv->edac_ctl->mod_name = dev_name(dev);
+	drv->edac_ctl->dev_name = dev_name(dev);
+	drv->edac_ctl->ctl_name = "cache_err";
+	platform_set_drvdata(pdev, drv);
+
+	cortexa53_set_edac_sysfs_attributes(drv->edac_ctl);
+
+	rc = edac_device_add_device(drv->edac_ctl);
+	if (rc)
+		edac_device_free_ctl_info(drv->edac_ctl);
+
+	return rc;
+}
+
+static int cortex_arm64_edac_remove(struct platform_device *pdev)
+{
+	struct cortex_arm64_edac *drv = dev_get_drvdata(&pdev->dev);
+	struct edac_device_ctl_info *edac_ctl = drv->edac_ctl;
+
+	edac_device_del_device(edac_ctl->dev);
+	edac_device_free_ctl_info(edac_ctl);
+
+	return 0;
+}
+
+static const struct of_device_id cortex_arm64_edac_of_match[] = {
+	{ .compatible = "arm,cortex-a57-edac" },
+	{ .compatible = "arm,cortex-a53-edac" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, cortex_arm64_edac_of_match);
+
+static struct platform_driver cortex_arm64_edac_driver = {
+	.probe = cortex_arm64_edac_probe,
+	.remove = cortex_arm64_edac_remove,
+	.driver = {
+		.name = DRV_NAME,
+		.of_match_table = cortex_arm64_edac_of_match,
+	},
+};
+module_platform_driver(cortex_arm64_edac_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Brijesh Singh <brijeshkumar.singh@amd.com>");
+MODULE_DESCRIPTION("Cortex A57 and A53 EDAC driver");
+module_param(poll_msec, int, 0444);
+MODULE_PARM_DESC(poll_msec, "EDAC monitor poll interval in msec");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/edac_device.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/edac_device.c
@@ -34,6 +34,9 @@
 static DEFINE_MUTEX(device_ctls_mutex);
 static LIST_HEAD(edac_device_list);
 
+/* Default workqueue processing interval on this instance, in msecs */
+#define DEFAULT_POLL_INTERVAL 1000
+
 #ifdef CONFIG_EDAC_DEBUG
 static void edac_device_dump_device(struct edac_device_ctl_info *edac_dev)
 {
@@ -366,7 +369,7 @@
 	 * whole one second to save timers firing all over the period
 	 * between integral seconds
 	 */
-	if (edac_dev->poll_msec == 1000)
+	if (edac_dev->poll_msec == DEFAULT_POLL_INTERVAL)
 		edac_queue_work(&edac_dev->work, round_jiffies_relative(edac_dev->delay));
 	else
 		edac_queue_work(&edac_dev->work, edac_dev->delay);
@@ -396,7 +399,7 @@
 	 * timers firing on sub-second basis, while they are happy
 	 * to fire together on the 1 second exactly
 	 */
-	if (edac_dev->poll_msec == 1000)
+	if (edac_dev->poll_msec == DEFAULT_POLL_INTERVAL)
 		edac_queue_work(&edac_dev->work, round_jiffies_relative(edac_dev->delay));
 	else
 		edac_queue_work(&edac_dev->work, edac_dev->delay);
@@ -424,17 +427,16 @@
  *	Then restart the workq on the new delay
  */
 void edac_device_reset_delay_period(struct edac_device_ctl_info *edac_dev,
-					unsigned long value)
+				    unsigned long msec)
 {
-	unsigned long jiffs = msecs_to_jiffies(value);
-
-	if (value == 1000)
-		jiffs = round_jiffies_relative(value);
-
-	edac_dev->poll_msec = value;
-	edac_dev->delay	    = jiffs;
+	edac_dev->poll_msec = msec;
+	edac_dev->delay	    = msecs_to_jiffies(msec);
 
-	edac_mod_work(&edac_dev->work, jiffs);
+	/* See comment in edac_device_workq_setup() above */
+	if (edac_dev->poll_msec == DEFAULT_POLL_INTERVAL)
+		edac_mod_work(&edac_dev->work, round_jiffies_relative(edac_dev->delay));
+	else
+		edac_mod_work(&edac_dev->work, edac_dev->delay);
 }
 
 int edac_device_alloc_index(void)
@@ -473,11 +475,7 @@
 		/* This instance is NOW RUNNING */
 		edac_dev->op_state = OP_RUNNING_POLL;
 
-		/*
-		 * enable workq processing on this instance,
-		 * default = 1000 msec
-		 */
-		edac_device_workq_setup(edac_dev, 1000);
+		edac_device_workq_setup(edac_dev, edac_dev->poll_msec ?: DEFAULT_POLL_INTERVAL);
 	} else {
 		edac_dev->op_state = OP_RUNNING_INTERRUPT;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/edac_device_sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/edac_device_sysfs.c
@@ -275,6 +275,7 @@
 
 	/* Error exit stack */
 err_kobj_reg:
+	kobject_put(&edac_dev->kobj);
 	module_put(edac_dev->owner);
 
 err_out:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/edac_mc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/edac_mc.c
@@ -263,7 +263,7 @@
 	else
 		return (char *)ptr;
 
-	r = (unsigned long)p % align;
+	r = (unsigned long)ptr % align;
 
 	if (r == 0)
 		return (char *)ptr;
@@ -503,16 +503,10 @@
 {
 	edac_dbg(1, "\n");
 
-	/* If we're not yet registered with sysfs free only what was allocated
-	 * in edac_mc_alloc().
-	 */
-	if (!device_is_registered(&mci->dev)) {
-		_edac_mc_free(mci);
-		return;
-	}
+	if (device_is_registered(&mci->dev))
+		edac_unregister_sysfs(mci);
 
-	/* the mci instance is freed here, when the sysfs object is dropped */
-	edac_unregister_sysfs(mci);
+	_edac_mc_free(mci);
 }
 EXPORT_SYMBOL_GPL(edac_mc_free);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/edac_mc_sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/edac_mc_sysfs.c
@@ -276,10 +276,7 @@
 
 static void csrow_attr_release(struct device *dev)
 {
-	struct csrow_info *csrow = container_of(dev, struct csrow_info, dev);
-
-	edac_dbg(1, "device %s released\n", dev_name(dev));
-	kfree(csrow);
+	/* release device with _edac_mc_free() */
 }
 
 static const struct device_type csrow_attr_type = {
@@ -447,8 +444,7 @@
 		csrow = mci->csrows[i];
 		if (!nr_pages_per_csrow(csrow))
 			continue;
-
-		device_del(&mci->csrows[i]->dev);
+		device_unregister(&mci->csrows[i]->dev);
 	}
 
 	return err;
@@ -620,10 +616,7 @@
 
 static void dimm_attr_release(struct device *dev)
 {
-	struct dimm_info *dimm = container_of(dev, struct dimm_info, dev);
-
-	edac_dbg(1, "device %s released\n", dev_name(dev));
-	kfree(dimm);
+	/* release device with _edac_mc_free() */
 }
 
 static const struct device_type dimm_attr_type = {
@@ -906,10 +899,7 @@
 
 static void mci_attr_release(struct device *dev)
 {
-	struct mem_ctl_info *mci = container_of(dev, struct mem_ctl_info, dev);
-
-	edac_dbg(1, "device %s released\n", dev_name(dev));
-	kfree(mci);
+	/* release device with _edac_mc_free() */
 }
 
 static const struct device_type mci_attr_type = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/edac_module.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/edac_module.h
@@ -57,7 +57,7 @@
 bool edac_mod_work(struct delayed_work *work, unsigned long delay);
 
 extern void edac_device_reset_delay_period(struct edac_device_ctl_info
-					   *edac_dev, unsigned long value);
+					   *edac_dev, unsigned long msec);
 extern void edac_mc_reset_delay_period(unsigned long value);
 
 extern void *edac_align_ptr(void **p, unsigned size, int n_elems);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/edac_pci_sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/edac_pci_sysfs.c
@@ -386,7 +386,7 @@
 
 	/* Error unwind statck */
 kobject_init_and_add_fail:
-	kfree(edac_pci_top_main_kobj);
+	kobject_put(edac_pci_top_main_kobj);
 
 kzalloc_fail:
 	module_put(THIS_MODULE);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/fsl_ddr_edac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/fsl_ddr_edac.c
@@ -331,21 +331,25 @@
 	 * TODO: Add support for 32-bit wide buses
 	 */
 	if ((err_detect & DDR_EDE_SBE) && (bus_width == 64)) {
+		u64 cap = (u64)cap_high << 32 | cap_low;
+		u32 s = syndrome;
+
 		sbe_ecc_decode(cap_high, cap_low, syndrome,
 				&bad_data_bit, &bad_ecc_bit);
 
-		if (bad_data_bit != -1)
-			fsl_mc_printk(mci, KERN_ERR,
-				"Faulty Data bit: %d\n", bad_data_bit);
-		if (bad_ecc_bit != -1)
-			fsl_mc_printk(mci, KERN_ERR,
-				"Faulty ECC bit: %d\n", bad_ecc_bit);
+		if (bad_data_bit >= 0) {
+			fsl_mc_printk(mci, KERN_ERR, "Faulty Data bit: %d\n", bad_data_bit);
+			cap ^= 1ULL << bad_data_bit;
+		}
+
+		if (bad_ecc_bit >= 0) {
+			fsl_mc_printk(mci, KERN_ERR, "Faulty ECC bit: %d\n", bad_ecc_bit);
+			s ^= 1 << bad_ecc_bit;
+		}
 
 		fsl_mc_printk(mci, KERN_ERR,
 			"Expected Data / ECC:\t%#8.8x_%08x / %#2.2x\n",
-			cap_high ^ (1 << (bad_data_bit - 32)),
-			cap_low ^ (1 << bad_data_bit),
-			syndrome ^ (1 << bad_ecc_bit));
+			upper_32_bits(cap), lower_32_bits(cap), s);
 	}
 
 	fsl_mc_printk(mci, KERN_ERR,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/ghes_edac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/ghes_edac.c
@@ -26,9 +26,18 @@
 	char msg[80];
 };
 
-static atomic_t ghes_init = ATOMIC_INIT(0);
+static refcount_t ghes_refcount = REFCOUNT_INIT(0);
+
+/*
+ * Access to ghes_pvt must be protected by ghes_lock. The spinlock
+ * also provides the necessary (implicit) memory barrier for the SMP
+ * case to make the pointer visible on another CPU.
+ */
 static struct ghes_edac_pvt *ghes_pvt;
 
+/* GHES registration mutex */
+static DEFINE_MUTEX(ghes_reg_mutex);
+
 /*
  * Sync with other, potentially concurrent callers of
  * ghes_edac_report_mem_error(). We don't know what the
@@ -79,9 +88,8 @@
 		(*num_dimm)++;
 }
 
-static int get_dimm_smbios_index(u16 handle)
+static int get_dimm_smbios_index(struct mem_ctl_info *mci, u16 handle)
 {
-	struct mem_ctl_info *mci = ghes_pvt->mci;
 	int i;
 
 	for (i = 0; i < mci->tot_dimms; i++) {
@@ -198,14 +206,11 @@
 	enum hw_event_mc_err_type type;
 	struct edac_raw_error_desc *e;
 	struct mem_ctl_info *mci;
-	struct ghes_edac_pvt *pvt = ghes_pvt;
+	struct ghes_edac_pvt *pvt;
 	unsigned long flags;
 	char *p;
 	u8 grain_bits;
 
-	if (!pvt)
-		return;
-
 	/*
 	 * We can do the locking below because GHES defers error processing
 	 * from NMI to IRQ context. Whenever that changes, we'd at least
@@ -216,12 +221,17 @@
 
 	spin_lock_irqsave(&ghes_lock, flags);
 
+	pvt = ghes_pvt;
+	if (!pvt)
+		goto unlock;
+
 	mci = pvt->mci;
 	e = &mci->error_desc;
 
 	/* Cleans the error report buffer */
 	memset(e, 0, sizeof (*e));
 	e->error_count = 1;
+	e->grain = 1;
 	strcpy(e->label, "unknown label");
 	e->msg = pvt->msg;
 	e->other_detail = pvt->other_detail;
@@ -317,7 +327,7 @@
 
 	/* Error grain */
 	if (mem_err->validation_bits & CPER_MEM_VALID_PA_MASK)
-		e->grain = ~(mem_err->physical_addr_mask & ~PAGE_MASK);
+		e->grain = ~mem_err->physical_addr_mask + 1;
 
 	/* Memory error location, mapped on e->location */
 	p = e->location;
@@ -348,7 +358,7 @@
 			p += sprintf(p, "DIMM DMI handle: 0x%.4x ",
 				     mem_err->mem_dev_handle);
 
-		index = get_dimm_smbios_index(mem_err->mem_dev_handle);
+		index = get_dimm_smbios_index(mci, mem_err->mem_dev_handle);
 		if (index >= 0) {
 			e->top_layer = index;
 			e->enable_per_layer_report = true;
@@ -433,8 +443,13 @@
 	if (p > pvt->other_detail)
 		*(p - 1) = '\0';
 
+	/* Sanity-check driver-supplied grain value. */
+	if (WARN_ON_ONCE(!e->grain))
+		e->grain = 1;
+
+	grain_bits = fls_long(e->grain - 1);
+
 	/* Generate the trace event */
-	grain_bits = fls_long(e->grain);
 	snprintf(pvt->detail_location, sizeof(pvt->detail_location),
 		 "APEI location: %s %s", e->location, e->other_detail);
 	trace_mc_event(type, e->msg, e->label, e->error_count,
@@ -443,6 +458,8 @@
 		       grain_bits, e->syndrome, pvt->detail_location);
 
 	edac_raw_mc_handle_error(type, mci, e);
+
+unlock:
 	spin_unlock_irqrestore(&ghes_lock, flags);
 }
 
@@ -457,10 +474,12 @@
 int ghes_edac_register(struct ghes *ghes, struct device *dev)
 {
 	bool fake = false;
-	int rc, num_dimm = 0;
+	int rc = 0, num_dimm = 0;
 	struct mem_ctl_info *mci;
+	struct ghes_edac_pvt *pvt;
 	struct edac_mc_layer layers[1];
 	struct ghes_edac_dimm_fill dimm_fill;
+	unsigned long flags;
 	int idx = -1;
 
 	if (IS_ENABLED(CONFIG_X86)) {
@@ -469,14 +488,18 @@
 		if (!force_load && idx < 0)
 			return -ENODEV;
 	} else {
+		force_load = true;
 		idx = 0;
 	}
 
+	/* finish another registration/unregistration instance first */
+	mutex_lock(&ghes_reg_mutex);
+
 	/*
 	 * We have only one logical memory controller to which all DIMMs belong.
 	 */
-	if (atomic_inc_return(&ghes_init) > 1)
-		return 0;
+	if (refcount_inc_not_zero(&ghes_refcount))
+		goto unlock;
 
 	/* Get the number of DIMMs */
 	dmi_walk(ghes_edac_count_dimms, &num_dimm);
@@ -494,12 +517,13 @@
 	mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, sizeof(struct ghes_edac_pvt));
 	if (!mci) {
 		pr_info("Can't allocate memory for EDAC data\n");
-		return -ENOMEM;
+		rc = -ENOMEM;
+		goto unlock;
 	}
 
-	ghes_pvt	= mci->pvt_info;
-	ghes_pvt->ghes	= ghes;
-	ghes_pvt->mci	= mci;
+	pvt		= mci->pvt_info;
+	pvt->ghes	= ghes;
+	pvt->mci	= mci;
 
 	mci->pdev = dev;
 	mci->mtype_cap = MEM_FLAG_EMPTY;
@@ -541,23 +565,51 @@
 	if (rc < 0) {
 		pr_info("Can't register at EDAC core\n");
 		edac_mc_free(mci);
-		return -ENODEV;
+		rc = -ENODEV;
+		goto unlock;
 	}
-	return 0;
+
+	spin_lock_irqsave(&ghes_lock, flags);
+	ghes_pvt = pvt;
+	spin_unlock_irqrestore(&ghes_lock, flags);
+
+	/* only set on success */
+	refcount_set(&ghes_refcount, 1);
+
+unlock:
+	mutex_unlock(&ghes_reg_mutex);
+
+	return rc;
 }
 
 void ghes_edac_unregister(struct ghes *ghes)
 {
 	struct mem_ctl_info *mci;
+	unsigned long flags;
 
-	if (!ghes_pvt)
+	if (!force_load)
 		return;
 
-	if (atomic_dec_return(&ghes_init))
-		return;
+	mutex_lock(&ghes_reg_mutex);
 
-	mci = ghes_pvt->mci;
+	if (!refcount_dec_and_test(&ghes_refcount))
+		goto unlock;
+
+	/*
+	 * Wait for the irq handler being finished.
+	 */
+	spin_lock_irqsave(&ghes_lock, flags);
+	mci = ghes_pvt ? ghes_pvt->mci : NULL;
 	ghes_pvt = NULL;
-	edac_mc_del_mc(mci->pdev);
-	edac_mc_free(mci);
+	spin_unlock_irqrestore(&ghes_lock, flags);
+
+	if (!mci)
+		goto unlock;
+
+	mci = edac_mc_del_mc(mci->pdev);
+	if (mci)
+		edac_mc_free(mci);
+
+unlock:
+	mutex_unlock(&ghes_reg_mutex);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/highbank_mc_edac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/highbank_mc_edac.c
@@ -174,8 +174,10 @@
 	drvdata = mci->pvt_info;
 	platform_set_drvdata(pdev, mci);
 
-	if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL))
-		return -ENOMEM;
+	if (!devres_open_group(&pdev->dev, NULL, GFP_KERNEL)) {
+		res = -ENOMEM;
+		goto free;
+	}
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!r) {
@@ -243,6 +245,7 @@
 	edac_mc_del_mc(&pdev->dev);
 err:
 	devres_release_group(&pdev->dev, NULL);
+free:
 	edac_mc_free(mci);
 	return res;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/i10nm_base.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/i10nm_base.c
@@ -6,6 +6,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/io.h>
 #include <asm/cpu_device_id.h>
 #include <asm/intel-family.h>
 #include <asm/mce.h>
@@ -19,14 +20,16 @@
 #define i10nm_printk(level, fmt, arg...)	\
 	edac_printk(level, "i10nm", fmt, ##arg)
 
-#define I10NM_GET_SCK_BAR(d, reg)		\
+#define I10NM_GET_SCK_BAR(d, reg)	\
 	pci_read_config_dword((d)->uracu, 0xd0, &(reg))
 #define I10NM_GET_IMC_BAR(d, i, reg)	\
 	pci_read_config_dword((d)->uracu, 0xd8 + (i) * 4, &(reg))
 #define I10NM_GET_DIMMMTR(m, i, j)	\
-	(*(u32 *)((m)->mbase + 0x2080c + (i) * 0x4000 + (j) * 4))
-#define I10NM_GET_MCDDRTCFG(m, i, j)	\
-	(*(u32 *)((m)->mbase + 0x20970 + (i) * 0x4000 + (j) * 4))
+	readl((m)->mbase + 0x2080c + (i) * 0x4000 + (j) * 4)
+#define I10NM_GET_MCDDRTCFG(m, i)	\
+	readl((m)->mbase + 0x20970 + (i) * 0x4000)
+#define I10NM_GET_MCMTR(m, i)		\
+	readl((m)->mbase + 0x20ef8 + (i) * 0x4000)
 
 #define I10NM_GET_SCK_MMIO_BASE(reg)	(GET_BITFIELD(reg, 0, 28) << 23)
 #define I10NM_GET_IMC_MMIO_OFFSET(reg)	(GET_BITFIELD(reg, 0, 10) << 12)
@@ -50,11 +53,10 @@
 	if (unlikely(pci_enable_device(pdev) < 0)) {
 		edac_dbg(2, "Failed to enable device %02x:%02x.%x\n",
 			 bus, dev, fun);
+		pci_dev_put(pdev);
 		return NULL;
 	}
 
-	pci_dev_get(pdev);
-
 	return pdev;
 }
 
@@ -134,7 +136,7 @@
 {
 	u32 mcmtr;
 
-	mcmtr = *(u32 *)(imc->mbase + 0x20ef8 + chan * 0x4000);
+	mcmtr = I10NM_GET_MCMTR(imc, chan);
 	edac_dbg(1, "ch%d mcmtr reg %x\n", chan, mcmtr);
 
 	return !!GET_BITFIELD(mcmtr, 2, 2);
@@ -153,16 +155,16 @@
 			continue;
 
 		ndimms = 0;
+		mcddrtcfg = I10NM_GET_MCDDRTCFG(imc, i);
 		for (j = 0; j < I10NM_NUM_DIMMS; j++) {
 			dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms,
 					     mci->n_layers, i, j, 0);
 			mtr = I10NM_GET_DIMMMTR(imc, i, j);
-			mcddrtcfg = I10NM_GET_MCDDRTCFG(imc, i, j);
 			edac_dbg(1, "dimmmtr 0x%x mcddrtcfg 0x%x (mc%d ch%d dimm%d)\n",
 				 mtr, mcddrtcfg, imc->mc, i, j);
 
 			if (IS_DIMM_PRESENT(mtr))
-				ndimms += skx_get_dimm_info(mtr, 0, dimm,
+				ndimms += skx_get_dimm_info(mtr, 0, 0, dimm,
 							    imc, i, j);
 			else if (IS_NVDIMM_PRESENT(mcddrtcfg, j))
 				ndimms += skx_get_nvdimm_info(dimm, imc, i, j,
@@ -246,6 +248,9 @@
 	if (owner && strncmp(owner, EDAC_MOD_STR, sizeof(EDAC_MOD_STR)))
 		return -EBUSY;
 
+	if (cpu_feature_enabled(X86_FEATURE_HYPERVISOR))
+		return -ENODEV;
+
 	id = x86_match_cpu(i10nm_cpuids);
 	if (!id)
 		return -ENODEV;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/i5100_edac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/i5100_edac.c
@@ -1074,16 +1074,15 @@
 				    PCI_DEVICE_ID_INTEL_5100_19, 0);
 	if (!einj) {
 		ret = -ENODEV;
-		goto bail_einj;
+		goto bail_mc_free;
 	}
 
 	rc = pci_enable_device(einj);
 	if (rc < 0) {
 		ret = rc;
-		goto bail_disable_einj;
+		goto bail_einj;
 	}
 
-
 	mci->pdev = &pdev->dev;
 
 	priv = mci->pvt_info;
@@ -1149,14 +1148,14 @@
 bail_scrub:
 	priv->scrub_enable = 0;
 	cancel_delayed_work_sync(&(priv->i5100_scrubbing));
-	edac_mc_free(mci);
-
-bail_disable_einj:
 	pci_disable_device(einj);
 
 bail_einj:
 	pci_dev_put(einj);
 
+bail_mc_free:
+	edac_mc_free(mci);
+
 bail_disable_ch1:
 	pci_disable_device(ch1mm);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/i7core_edac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/i7core_edac.c
@@ -1711,9 +1711,9 @@
 	if (uncorrected_error) {
 		core_err_cnt = 1;
 		if (ripv)
-			tp_event = HW_EVENT_ERR_FATAL;
-		else
 			tp_event = HW_EVENT_ERR_UNCORRECTED;
+		else
+			tp_event = HW_EVENT_ERR_FATAL;
 	} else {
 		tp_event = HW_EVENT_ERR_CORRECTED;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/ie31200_edac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/ie31200_edac.c
@@ -83,8 +83,6 @@
 	 (((did) & PCI_DEVICE_ID_INTEL_IE31200_HB_CFL_MASK) ==                 \
 	  PCI_DEVICE_ID_INTEL_IE31200_HB_CFL_MASK))
 
-#define IE31200_DIMMS			4
-#define IE31200_RANKS			8
 #define IE31200_RANKS_PER_CHANNEL	4
 #define IE31200_DIMMS_PER_CHANNEL	2
 #define IE31200_CHANNELS		2
@@ -156,6 +154,7 @@
 #define IE31200_MAD_DIMM_0_OFFSET		0x5004
 #define IE31200_MAD_DIMM_0_OFFSET_SKL		0x500C
 #define IE31200_MAD_DIMM_SIZE			GENMASK_ULL(7, 0)
+#define IE31200_MAD_DIMM_SIZE_SKL		GENMASK_ULL(5, 0)
 #define IE31200_MAD_DIMM_A_RANK			BIT(17)
 #define IE31200_MAD_DIMM_A_RANK_SHIFT		17
 #define IE31200_MAD_DIMM_A_RANK_SKL		BIT(10)
@@ -170,6 +169,8 @@
 	(n << (28 + (2 * skl) - PAGE_SHIFT))
 
 static int nr_channels;
+static struct pci_dev *mci_pdev;
+static int ie31200_registered = 1;
 
 struct ie31200_priv {
 	void __iomem *window;
@@ -368,7 +369,7 @@
 static void __skl_populate_dimm_info(struct dimm_data *dd, u32 addr_decode,
 				     int chan)
 {
-	dd->size = (addr_decode >> (chan << 4)) & IE31200_MAD_DIMM_SIZE;
+	dd->size = (addr_decode >> (chan << 4)) & IE31200_MAD_DIMM_SIZE_SKL;
 	dd->dual_rank = (addr_decode & (IE31200_MAD_DIMM_A_RANK_SKL << (chan << 4))) ? 1 : 0;
 	dd->x16_width = ((addr_decode & (IE31200_MAD_DIMM_A_WIDTH_SKL << (chan << 4))) >>
 				(IE31200_MAD_DIMM_A_WIDTH_SKL_SHIFT + (chan << 4)));
@@ -417,7 +418,7 @@
 
 	nr_channels = how_many_channels(pdev);
 	layers[0].type = EDAC_MC_LAYER_CHIP_SELECT;
-	layers[0].size = IE31200_DIMMS;
+	layers[0].size = IE31200_RANKS_PER_CHANNEL;
 	layers[0].is_virt_csrow = true;
 	layers[1].type = EDAC_MC_LAYER_CHANNEL;
 	layers[1].size = nr_channels;
@@ -541,12 +542,16 @@
 static int ie31200_init_one(struct pci_dev *pdev,
 			    const struct pci_device_id *ent)
 {
-	edac_dbg(0, "MC:\n");
+	int rc;
 
+	edac_dbg(0, "MC:\n");
 	if (pci_enable_device(pdev) < 0)
 		return -EIO;
+	rc = ie31200_probe1(pdev, ent->driver_data);
+	if (rc == 0 && !mci_pdev)
+		mci_pdev = pci_dev_get(pdev);
 
-	return ie31200_probe1(pdev, ent->driver_data);
+	return rc;
 }
 
 static void ie31200_remove_one(struct pci_dev *pdev)
@@ -555,6 +560,8 @@
 	struct ie31200_priv *priv;
 
 	edac_dbg(0, "\n");
+	pci_dev_put(mci_pdev);
+	mci_pdev = NULL;
 	mci = edac_mc_del_mc(&pdev->dev);
 	if (!mci)
 		return;
@@ -596,17 +603,55 @@
 
 static int __init ie31200_init(void)
 {
+	int pci_rc, i;
+
 	edac_dbg(3, "MC:\n");
 	/* Ensure that the OPSTATE is set correctly for POLL or NMI */
 	opstate_init();
 
-	return pci_register_driver(&ie31200_driver);
+	pci_rc = pci_register_driver(&ie31200_driver);
+	if (pci_rc < 0)
+		return pci_rc;
+
+	if (!mci_pdev) {
+		ie31200_registered = 0;
+		for (i = 0; ie31200_pci_tbl[i].vendor != 0; i++) {
+			mci_pdev = pci_get_device(ie31200_pci_tbl[i].vendor,
+						  ie31200_pci_tbl[i].device,
+						  NULL);
+			if (mci_pdev)
+				break;
+		}
+
+		if (!mci_pdev) {
+			edac_dbg(0, "ie31200 pci_get_device fail\n");
+			pci_rc = -ENODEV;
+			goto fail0;
+		}
+
+		pci_rc = ie31200_init_one(mci_pdev, &ie31200_pci_tbl[i]);
+		if (pci_rc < 0) {
+			edac_dbg(0, "ie31200 init fail\n");
+			pci_rc = -ENODEV;
+			goto fail1;
+		}
+	}
+
+	return 0;
+fail1:
+	pci_dev_put(mci_pdev);
+fail0:
+	pci_unregister_driver(&ie31200_driver);
+
+	return pci_rc;
 }
 
 static void __exit ie31200_exit(void)
 {
 	edac_dbg(3, "MC:\n");
 	pci_unregister_driver(&ie31200_driver);
+	if (!ie31200_registered)
+		ie31200_remove_one(mci_pdev);
 }
 
 module_init(ie31200_init);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/mce_amd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/mce_amd.c
@@ -175,6 +175,33 @@
 	"L2 Fill Data error",
 };
 
+static const char * const smca_ls2_mce_desc[] = {
+	"An ECC error was detected on a data cache read by a probe or victimization",
+	"An ECC error or L2 poison was detected on a data cache read by a load",
+	"An ECC error was detected on a data cache read-modify-write by a store",
+	"An ECC error or poison bit mismatch was detected on a tag read by a probe or victimization",
+	"An ECC error or poison bit mismatch was detected on a tag read by a load",
+	"An ECC error or poison bit mismatch was detected on a tag read by a store",
+	"An ECC error was detected on an EMEM read by a load",
+	"An ECC error was detected on an EMEM read-modify-write by a store",
+	"A parity error was detected in an L1 TLB entry by any access",
+	"A parity error was detected in an L2 TLB entry by any access",
+	"A parity error was detected in a PWC entry by any access",
+	"A parity error was detected in an STQ entry by any access",
+	"A parity error was detected in an LDQ entry by any access",
+	"A parity error was detected in a MAB entry by any access",
+	"A parity error was detected in an SCB entry state field by any access",
+	"A parity error was detected in an SCB entry address field by any access",
+	"A parity error was detected in an SCB entry data field by any access",
+	"A parity error was detected in a WCB entry by any access",
+	"A poisoned line was detected in an SCB entry by any access",
+	"A SystemReadDataError error was reported on read data returned from L2 for a load",
+	"A SystemReadDataError error was reported on read data returned from L2 for an SCB store",
+	"A SystemReadDataError error was reported on read data returned from L2 for a WCB store",
+	"A hardware assertion error was reported",
+	"A parity error was detected in an STLF, SCB EMEM entry or SRB store data by any access",
+};
+
 static const char * const smca_if_mce_desc[] = {
 	"Op Cache Microtag Probe Port Parity Error",
 	"IC Microtag or Full Tag Multi-hit Error",
@@ -378,6 +405,7 @@
 
 static struct smca_mce_desc smca_mce_descs[] = {
 	[SMCA_LS]	= { smca_ls_mce_desc,	ARRAY_SIZE(smca_ls_mce_desc)	},
+	[SMCA_LS_V2]	= { smca_ls2_mce_desc,	ARRAY_SIZE(smca_ls2_mce_desc)	},
 	[SMCA_IF]	= { smca_if_mce_desc,	ARRAY_SIZE(smca_if_mce_desc)	},
 	[SMCA_L2_CACHE]	= { smca_l2_mce_desc,	ARRAY_SIZE(smca_l2_mce_desc)	},
 	[SMCA_DE]	= { smca_de_mce_desc,	ARRAY_SIZE(smca_de_mce_desc)	},
@@ -975,7 +1003,7 @@
 	}
 
 	if (bank_type == SMCA_UMC && xec == 0 && decode_dram_ecc)
-		decode_dram_ecc(cpu_to_node(m->extcpu), m);
+		decode_dram_ecc(topology_die_id(m->extcpu), m);
 }
 
 static inline void amd_decode_err_code(u16 ec)
@@ -1161,6 +1189,11 @@
 	if (!fam_ops)
 		return -ENOMEM;
 
+	if (boot_cpu_has(X86_FEATURE_SMCA)) {
+		xec_mask = 0x3f;
+		goto out;
+	}
+
 	switch (c->x86) {
 	case 0xf:
 		fam_ops->mc0_mce = k8_mc0_mce;
@@ -1209,11 +1242,8 @@
 
 	case 0x17:
 	case 0x18:
-		xec_mask = 0x3f;
-		if (!boot_cpu_has(X86_FEATURE_SMCA)) {
-			printk(KERN_WARNING "Decoding supported only on Scalable MCA processors.\n");
-			goto err_out;
-		}
+		pr_warn("Decoding supported only on Scalable MCA processors.\n");
+		goto err_out;
 		break;
 
 	default:
@@ -1221,6 +1251,7 @@
 		goto err_out;
 	}
 
+out:
 	pr_info("MCE: In-kernel MCE decoding enabled.\n");
 
 	mce_register_decode_chain(&amd_mce_dec_nb);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/pl310_edac_l2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/pl310_edac_l2.c
@@ -0,0 +1,233 @@
+/*
+ * Pl310 L2 Cache EDAC Driver
+ *
+ * Copyright (C) 2013-2014 Xilinx, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/edac.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <asm/hardware/cache-l2x0.h>
+#include "edac_module.h"
+
+/* Auxilary control register definitions */
+#define L2X0_AUX_CTRL_PARITY_MASK	BIT(21)
+
+/* Interrupt imask/status/clear register definitions */
+#define L2X0_INTR_PARRD_MASK	0x4
+#define L2X0_INTR_PARRT_MASK	0x2
+
+/**
+ * struct pl310_edac_l2_priv - Zynq L2 cache controller private instance data
+ * @base:		Base address of the controller
+ * @irq:		Interrupt number
+ */
+struct pl310_edac_l2_priv {
+	void __iomem *base;
+	int irq;
+};
+
+/**
+ * pl310_edac_l2_parityerr_check - Check controller staus for parity errors
+ * @dci:	Pointer to the edac device controller instance
+ *
+ * This routine is used to check and post parity errors
+ */
+static void pl310_edac_l2_parityerr_check(struct edac_device_ctl_info *dci)
+{
+	struct pl310_edac_l2_priv *priv = dci->pvt_info;
+	u32 regval;
+
+	regval = readl(priv->base + L2X0_RAW_INTR_STAT);
+	if (regval & L2X0_INTR_PARRD_MASK) {
+		/* Data parity error will be reported as correctable error */
+		writel(L2X0_INTR_PARRD_MASK, priv->base + L2X0_INTR_CLEAR);
+		edac_device_handle_ce(dci, 0, 0, dci->ctl_name);
+	}
+	if (regval & L2X0_INTR_PARRT_MASK) {
+		/* tag parity error will be reported as uncorrectable error */
+		writel(L2X0_INTR_PARRT_MASK, priv->base + L2X0_INTR_CLEAR);
+		edac_device_handle_ue(dci, 0, 0, dci->ctl_name);
+	}
+}
+
+/**
+ * pl310_edac_l2_int_handler - ISR fucntion for l2cahe controller
+ * @irq:	Irq Number
+ * @device:	Pointer to the edac device controller instance
+ *
+ * This routine is triggered whenever there is parity error detected
+ *
+ * Return: Always returns IRQ_HANDLED
+ */
+static irqreturn_t pl310_edac_l2_int_handler(int irq, void *device)
+{
+	pl310_edac_l2_parityerr_check((struct edac_device_ctl_info *)device);
+	return IRQ_HANDLED;
+}
+
+/**
+ * pl310_edac_l2_poll_handler - Poll the status reg for parity errors
+ * @dci:	Pointer to the edac device controller instance
+ *
+ * This routine is used to check and post parity errors and is called by
+ * the EDAC polling thread
+ */
+static void pl310_edac_l2_poll_handler(struct edac_device_ctl_info *dci)
+{
+	pl310_edac_l2_parityerr_check(dci);
+}
+
+/**
+ * pl310_edac_l2_get_paritystate - check the parity enable/disable status
+ * @base:	Pointer to the contoller base address
+ *
+ * This routine returns the parity enable/diable status for the controller
+ *
+ * Return: true/false -  parity enabled/disabled.
+ */
+static bool pl310_edac_l2_get_paritystate(void __iomem *base)
+{
+	u32 regval;
+
+	regval = readl(base + L2X0_AUX_CTRL);
+	if (regval & L2X0_AUX_CTRL_PARITY_MASK)
+		return true;
+
+	return false;
+}
+
+/**
+ * pl310_edac_l2_probe - Check controller and bind driver
+ * @pdev:	Pointer to the platform_device struct
+ *
+ * This routine probes a specific arm,pl310-cache instance for binding
+ * with the driver.
+ *
+ * Return: 0 if the controller instance was successfully bound to the
+ * driver; otherwise, < 0 on error.
+ */
+static int pl310_edac_l2_probe(struct platform_device *pdev)
+{
+	struct edac_device_ctl_info *dci;
+	struct pl310_edac_l2_priv *priv;
+	int rc;
+	struct resource *res;
+	void __iomem *baseaddr;
+	u32 regval;
+
+	/* Get the data from the platform device */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	baseaddr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(baseaddr))
+		return PTR_ERR(baseaddr);
+
+	/* Check for the ecc enable status */
+	if (pl310_edac_l2_get_paritystate(baseaddr) == false) {
+		dev_err(&pdev->dev, "parity check not enabled\n");
+		return -ENXIO;
+	}
+
+	dci = edac_device_alloc_ctl_info(sizeof(*priv), "l2cache",
+					 1, "L", 1, 1, NULL, 0,
+					 edac_device_alloc_index());
+	if (IS_ERR(dci))
+		return PTR_ERR(dci);
+
+	priv = dci->pvt_info;
+	priv->base = baseaddr;
+	dci->dev = &pdev->dev;
+	dci->mod_name = "pl310_edac_l2";
+	dci->ctl_name = "pl310_l2_controller";
+	dci->dev_name = dev_name(&pdev->dev);
+
+	priv->irq = platform_get_irq(pdev, 0);
+	rc = devm_request_irq(&pdev->dev, priv->irq,
+				pl310_edac_l2_int_handler,
+				0, dev_name(&pdev->dev), (void *)dci);
+	if (rc < 0) {
+		dci->edac_check = pl310_edac_l2_poll_handler;
+		edac_op_state = EDAC_OPSTATE_POLL;
+	}
+
+	rc = edac_device_add_device(dci);
+	if (rc) {
+		dev_err(&pdev->dev, "failed to register with EDAC core\n");
+		goto del_edac_device;
+	}
+
+	if (edac_op_state != EDAC_OPSTATE_POLL) {
+		regval = readl(priv->base+L2X0_INTR_MASK);
+		regval |= (L2X0_INTR_PARRD_MASK | L2X0_INTR_PARRT_MASK);
+		writel(regval, priv->base+L2X0_INTR_MASK);
+	}
+
+	return rc;
+
+del_edac_device:
+	edac_device_del_device(&pdev->dev);
+	edac_device_free_ctl_info(dci);
+
+	return rc;
+}
+
+/**
+ * pl310_edac_l2_remove - Unbind driver from controller
+ * @pdev:	Pointer to the platform_device struct
+ *
+ * This routine unbinds the EDAC device controller instance associated
+ * with the specified arm,pl310-cache controller described by the
+ * OpenFirmware device tree node passed as a parameter.
+ *
+ * Return: Always returns 0
+ */
+static int pl310_edac_l2_remove(struct platform_device *pdev)
+{
+	struct edac_device_ctl_info *dci = platform_get_drvdata(pdev);
+	struct pl310_edac_l2_priv *priv = dci->pvt_info;
+	u32 regval;
+
+	if (edac_op_state != EDAC_OPSTATE_POLL) {
+		regval = readl(priv->base+L2X0_INTR_MASK);
+		regval &= ~(L2X0_INTR_PARRD_MASK | L2X0_INTR_PARRT_MASK);
+		writel(regval, priv->base+L2X0_INTR_MASK);
+	}
+
+	edac_device_del_device(&pdev->dev);
+	edac_device_free_ctl_info(dci);
+
+	return 0;
+}
+
+/* Device tree node type and compatible tuples this driver can match on */
+static const struct of_device_id pl310_edac_l2_match[] = {
+	{ .compatible = "arm,pl310-cache", },
+	{ /* end of table */ }
+};
+
+MODULE_DEVICE_TABLE(of, pl310_edac_l2_match);
+
+static struct platform_driver pl310_edac_l2_driver = {
+	.driver = {
+		 .name = "pl310-edac-l2",
+		 .of_match_table = pl310_edac_l2_match,
+	},
+	.probe = pl310_edac_l2_probe,
+	.remove = pl310_edac_l2_remove,
+};
+
+module_platform_driver(pl310_edac_l2_driver);
+
+MODULE_AUTHOR("Xilinx Inc.");
+MODULE_DESCRIPTION("pl310 L2 EDAC driver");
+MODULE_LICENSE("GPL");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/pnd2_edac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/pnd2_edac.c
@@ -1155,7 +1155,7 @@
 	u32 optypenum = GET_BITFIELD(m->status, 4, 6);
 	int rc;
 
-	tp_event = uc_err ? (ripv ? HW_EVENT_ERR_FATAL : HW_EVENT_ERR_UNCORRECTED) :
+	tp_event = uc_err ? (ripv ? HW_EVENT_ERR_UNCORRECTED : HW_EVENT_ERR_FATAL) :
 						 HW_EVENT_ERR_CORRECTED;
 
 	/*
@@ -1555,6 +1555,9 @@
 	if (owner && strncmp(owner, EDAC_MOD_STR, sizeof(EDAC_MOD_STR)))
 		return -EBUSY;
 
+	if (cpu_feature_enabled(X86_FEATURE_HYPERVISOR))
+		return -ENODEV;
+
 	id = x86_match_cpu(pnd2_cpuids);
 	if (!id)
 		return -ENODEV;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/qcom_edac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/qcom_edac.c
@@ -252,7 +252,7 @@
 static int
 dump_syn_reg(struct edac_device_ctl_info *edev_ctl, int err_type, u32 bank)
 {
-	struct llcc_drv_data *drv = edev_ctl->pvt_info;
+	struct llcc_drv_data *drv = edev_ctl->dev->platform_data;
 	int ret;
 
 	ret = dump_syn_reg_values(drv, bank, err_type);
@@ -289,7 +289,7 @@
 llcc_ecc_irq_handler(int irq, void *edev_ctl)
 {
 	struct edac_device_ctl_info *edac_dev_ctl = edev_ctl;
-	struct llcc_drv_data *drv = edac_dev_ctl->pvt_info;
+	struct llcc_drv_data *drv = edac_dev_ctl->dev->platform_data;
 	irqreturn_t irq_rc = IRQ_NONE;
 	u32 drp_error, trp_error, i;
 	int ret;
@@ -358,7 +358,6 @@
 	edev_ctl->dev_name = dev_name(dev);
 	edev_ctl->ctl_name = "llcc";
 	edev_ctl->panic_on_ue = LLCC_ERP_PANIC_ON_UE;
-	edev_ctl->pvt_info = llcc_driv_data;
 
 	rc = edac_device_add_device(edev_ctl);
 	if (rc)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/sb_edac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/sb_edac.c
@@ -254,18 +254,20 @@
  * FIXME: Implement the error count reads directly
  */
 
-static const u32 correrrcnt[] = {
-	0x104, 0x108, 0x10c, 0x110,
-};
-
 #define RANK_ODD_OV(reg)		GET_BITFIELD(reg, 31, 31)
 #define RANK_ODD_ERR_CNT(reg)		GET_BITFIELD(reg, 16, 30)
 #define RANK_EVEN_OV(reg)		GET_BITFIELD(reg, 15, 15)
 #define RANK_EVEN_ERR_CNT(reg)		GET_BITFIELD(reg,  0, 14)
 
+#if 0 /* Currently unused*/
+static const u32 correrrcnt[] = {
+	0x104, 0x108, 0x10c, 0x110,
+};
+
 static const u32 correrrthrsld[] = {
 	0x11c, 0x120, 0x124, 0x128,
 };
+#endif
 
 #define RANK_ODD_ERR_THRSLD(reg)	GET_BITFIELD(reg, 16, 30)
 #define RANK_EVEN_ERR_THRSLD(reg)	GET_BITFIELD(reg,  0, 14)
@@ -1053,7 +1055,7 @@
 	pci_read_config_dword(pvt->info.pci_vtd, HASWELL_TOHM_1, &reg);
 	rc = ((reg << 6) | rc) << 26;
 
-	return rc | 0x1ffffff;
+	return rc | 0x3ffffff;
 }
 
 static u64 knl_get_tolm(struct sbridge_pvt *pvt)
@@ -1340,7 +1342,7 @@
  */
 static int knl_get_dimm_capacity(struct sbridge_pvt *pvt, u64 *mc_sizes)
 {
-	u64 sad_base, sad_size, sad_limit = 0;
+	u64 sad_base, sad_limit = 0;
 	u64 tad_base, tad_size, tad_limit, tad_deadspace, tad_livespace;
 	int sad_rule = 0;
 	int tad_rule = 0;
@@ -1427,7 +1429,6 @@
 		edram_only = KNL_EDRAM_ONLY(dram_rule);
 
 		sad_limit = pvt->info.sad_limit(dram_rule)+1;
-		sad_size = sad_limit - sad_base;
 
 		pci_read_config_dword(pvt->pci_sad0,
 			pvt->info.interleave_list[sad_rule], &interleave_reg);
@@ -2952,7 +2953,7 @@
 	struct mem_ctl_info *new_mci;
 	struct sbridge_pvt *pvt = mci->pvt_info;
 	enum hw_event_mc_err_type tp_event;
-	char *type, *optype, msg[256];
+	char *optype, msg[256];
 	bool ripv = GET_BITFIELD(m->mcgstatus, 0, 0);
 	bool overflow = GET_BITFIELD(m->status, 62, 62);
 	bool uncorrected_error = GET_BITFIELD(m->status, 61, 61);
@@ -2981,14 +2982,11 @@
 	if (uncorrected_error) {
 		core_err_cnt = 1;
 		if (ripv) {
-			type = "FATAL";
-			tp_event = HW_EVENT_ERR_FATAL;
-		} else {
-			type = "NON_FATAL";
 			tp_event = HW_EVENT_ERR_UNCORRECTED;
+		} else {
+			tp_event = HW_EVENT_ERR_FATAL;
 		}
 	} else {
-		type = "CORRECTED";
 		tp_event = HW_EVENT_ERR_CORRECTED;
 	}
 
@@ -3200,7 +3198,6 @@
 static void sbridge_unregister_mci(struct sbridge_dev *sbridge_dev)
 {
 	struct mem_ctl_info *mci = sbridge_dev->mci;
-	struct sbridge_pvt *pvt;
 
 	if (unlikely(!mci || !mci->pvt_info)) {
 		edac_dbg(0, "MC: dev = %p\n", &sbridge_dev->pdev[0]->dev);
@@ -3209,8 +3206,6 @@
 		return;
 	}
 
-	pvt = mci->pvt_info;
-
 	edac_dbg(0, "MC: mci = %p, dev = %p\n",
 		 mci, &sbridge_dev->pdev[0]->dev);
 
@@ -3517,6 +3512,9 @@
 	if (owner && strncmp(owner, EDAC_MOD_STR, sizeof(EDAC_MOD_STR)))
 		return -EBUSY;
 
+	if (cpu_feature_enabled(X86_FEATURE_HYPERVISOR))
+		return -ENODEV;
+
 	id = x86_match_cpu(sbridge_cpuids);
 	if (!id)
 		return -ENODEV;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/sifive_edac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/sifive_edac.c
@@ -54,8 +54,8 @@
 	p->dci = edac_device_alloc_ctl_info(0, "sifive_ecc", 1, "sifive_ecc",
 					    1, 1, NULL, 0,
 					    edac_device_alloc_index());
-	if (IS_ERR(p->dci))
-		return PTR_ERR(p->dci);
+	if (!p->dci)
+		return -ENOMEM;
 
 	p->dci->dev = &pdev->dev;
 	p->dci->mod_name = "Sifive ECC Manager";
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/skx_base.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/skx_base.c
@@ -46,7 +46,8 @@
 }
 
 enum munittype {
-	CHAN0, CHAN1, CHAN2, SAD_ALL, UTIL_ALL, SAD
+	CHAN0, CHAN1, CHAN2, SAD_ALL, UTIL_ALL, SAD,
+	ERRCHAN0, ERRCHAN1, ERRCHAN2,
 };
 
 struct munit {
@@ -68,6 +69,9 @@
 	{ 0x2040, { PCI_DEVFN(10, 0), PCI_DEVFN(12, 0) }, 2, 2, CHAN0 },
 	{ 0x2044, { PCI_DEVFN(10, 4), PCI_DEVFN(12, 4) }, 2, 2, CHAN1 },
 	{ 0x2048, { PCI_DEVFN(11, 0), PCI_DEVFN(13, 0) }, 2, 2, CHAN2 },
+	{ 0x2043, { PCI_DEVFN(10, 3), PCI_DEVFN(12, 3) }, 2, 2, ERRCHAN0 },
+	{ 0x2047, { PCI_DEVFN(10, 7), PCI_DEVFN(12, 7) }, 2, 2, ERRCHAN1 },
+	{ 0x204b, { PCI_DEVFN(11, 3), PCI_DEVFN(13, 3) }, 2, 2, ERRCHAN2 },
 	{ 0x208e, { }, 1, 0, SAD },
 	{ }
 };
@@ -104,10 +108,18 @@
 		}
 
 		switch (m->mtype) {
-		case CHAN0: case CHAN1: case CHAN2:
+		case CHAN0:
+		case CHAN1:
+		case CHAN2:
 			pci_dev_get(pdev);
 			d->imc[i].chan[m->mtype].cdev = pdev;
 			break;
+		case ERRCHAN0:
+		case ERRCHAN1:
+		case ERRCHAN2:
+			pci_dev_get(pdev);
+			d->imc[i].chan[m->mtype - ERRCHAN0].edev = pdev;
+			break;
 		case SAD_ALL:
 			pci_dev_get(pdev);
 			d->sad_all = pdev;
@@ -151,27 +163,23 @@
 };
 MODULE_DEVICE_TABLE(x86cpu, skx_cpuids);
 
-#define SKX_GET_MTMTR(dev, reg) \
-	pci_read_config_dword((dev), 0x87c, &(reg))
-
-static bool skx_check_ecc(struct pci_dev *pdev)
+static bool skx_check_ecc(u32 mcmtr)
 {
-	u32 mtmtr;
-
-	SKX_GET_MTMTR(pdev, mtmtr);
-
-	return !!GET_BITFIELD(mtmtr, 2, 2);
+	return !!GET_BITFIELD(mcmtr, 2, 2);
 }
 
 static int skx_get_dimm_config(struct mem_ctl_info *mci)
 {
 	struct skx_pvt *pvt = mci->pvt_info;
+	u32 mtr, mcmtr, amap, mcddrtcfg;
 	struct skx_imc *imc = pvt->imc;
-	u32 mtr, amap, mcddrtcfg;
 	struct dimm_info *dimm;
 	int i, j;
 	int ndimms;
 
+	/* Only the mcmtr on the first channel is effective */
+	pci_read_config_dword(imc->chan[0].cdev, 0x87c, &mcmtr);
+
 	for (i = 0; i < SKX_NUM_CHANNELS; i++) {
 		ndimms = 0;
 		pci_read_config_dword(imc->chan[i].cdev, 0x8C, &amap);
@@ -182,14 +190,14 @@
 			pci_read_config_dword(imc->chan[i].cdev,
 					      0x80 + 4 * j, &mtr);
 			if (IS_DIMM_PRESENT(mtr)) {
-				ndimms += skx_get_dimm_info(mtr, amap, dimm, imc, i, j);
+				ndimms += skx_get_dimm_info(mtr, mcmtr, amap, dimm, imc, i, j);
 			} else if (IS_NVDIMM_PRESENT(mcddrtcfg, j)) {
 				ndimms += skx_get_nvdimm_info(dimm, imc, i, j,
 							      EDAC_MOD_STR);
 				nvdimm_count++;
 			}
 		}
-		if (ndimms && !skx_check_ecc(imc->chan[0].cdev)) {
+		if (ndimms && !skx_check_ecc(mcmtr)) {
 			skx_printk(KERN_ERR, "ECC is disabled on imc %d\n", imc->mc);
 			return -ENODEV;
 		}
@@ -216,6 +224,39 @@
 #define SKX_ILV_REMOTE(tgt)	(((tgt) & 8) == 0)
 #define SKX_ILV_TARGET(tgt)	((tgt) & 7)
 
+static void skx_show_retry_rd_err_log(struct decoded_addr *res,
+				      char *msg, int len)
+{
+	u32 log0, log1, log2, log3, log4;
+	u32 corr0, corr1, corr2, corr3;
+	struct pci_dev *edev;
+	int n;
+
+	edev = res->dev->imc[res->imc].chan[res->channel].edev;
+
+	pci_read_config_dword(edev, 0x154, &log0);
+	pci_read_config_dword(edev, 0x148, &log1);
+	pci_read_config_dword(edev, 0x150, &log2);
+	pci_read_config_dword(edev, 0x15c, &log3);
+	pci_read_config_dword(edev, 0x114, &log4);
+
+	n = snprintf(msg, len, " retry_rd_err_log[%.8x %.8x %.8x %.8x %.8x]",
+		     log0, log1, log2, log3, log4);
+
+	pci_read_config_dword(edev, 0x104, &corr0);
+	pci_read_config_dword(edev, 0x108, &corr1);
+	pci_read_config_dword(edev, 0x10c, &corr2);
+	pci_read_config_dword(edev, 0x110, &corr3);
+
+	if (len - n > 0)
+		snprintf(msg + n, len - n,
+			 " correrrcnt[%.4x %.4x %.4x %.4x %.4x %.4x %.4x %.4x]",
+			 corr0 & 0xffff, corr0 >> 16,
+			 corr1 & 0xffff, corr1 >> 16,
+			 corr2 & 0xffff, corr2 >> 16,
+			 corr3 & 0xffff, corr3 >> 16);
+}
+
 static bool skx_sad_decode(struct decoded_addr *res)
 {
 	struct skx_dev *d = list_first_entry(skx_edac_list, typeof(*d), list);
@@ -463,7 +504,7 @@
 }
 
 static u8 skx_close_row[] = {
-	15, 16, 17, 18, 20, 21, 22, 28, 10, 11, 12, 13, 29, 30, 31, 32, 33
+	15, 16, 17, 18, 20, 21, 22, 28, 10, 11, 12, 13, 29, 30, 31, 32, 33, 34
 };
 
 static u8 skx_close_column[] = {
@@ -471,7 +512,7 @@
 };
 
 static u8 skx_open_row[] = {
-	14, 15, 16, 20, 28, 21, 22, 23, 24, 25, 26, 27, 29, 30, 31, 32, 33
+	14, 15, 16, 20, 28, 21, 22, 23, 24, 25, 26, 27, 29, 30, 31, 32, 33, 34
 };
 
 static u8 skx_open_column[] = {
@@ -609,6 +650,9 @@
 	if (owner && strncmp(owner, EDAC_MOD_STR, sizeof(EDAC_MOD_STR)))
 		return -EBUSY;
 
+	if (cpu_feature_enabled(X86_FEATURE_HYPERVISOR))
+		return -ENODEV;
+
 	id = x86_match_cpu(skx_cpuids);
 	if (!id)
 		return -ENODEV;
@@ -659,7 +703,7 @@
 		}
 	}
 
-	skx_set_decode(skx_decode);
+	skx_set_decode(skx_decode, skx_show_retry_rd_err_log);
 
 	if (nvdimm_count && skx_adxl_get() == -ENODEV)
 		skx_printk(KERN_NOTICE, "Only decoding DDR4 address!\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/skx_common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/skx_common.c
@@ -23,10 +23,13 @@
 #include "skx_common.h"
 
 static const char * const component_names[] = {
-	[INDEX_SOCKET]	= "ProcessorSocketId",
-	[INDEX_MEMCTRL]	= "MemoryControllerId",
-	[INDEX_CHANNEL]	= "ChannelId",
-	[INDEX_DIMM]	= "DimmSlotId",
+	[INDEX_SOCKET]		= "ProcessorSocketId",
+	[INDEX_MEMCTRL]		= "MemoryControllerId",
+	[INDEX_CHANNEL]		= "ChannelId",
+	[INDEX_DIMM]		= "DimmSlotId",
+	[INDEX_NM_MEMCTRL]	= "NmMemoryControllerId",
+	[INDEX_NM_CHANNEL]	= "NmChannelId",
+	[INDEX_NM_DIMM]		= "NmDimmSlotId",
 };
 
 static int component_indices[ARRAY_SIZE(component_names)];
@@ -34,13 +37,16 @@
 static const char * const *adxl_component_names;
 static u64 *adxl_values;
 static char *adxl_msg;
+static unsigned long adxl_nm_bitmap;
 
 static char skx_msg[MSG_SIZE];
 static skx_decode_f skx_decode;
+static skx_show_retry_log_f skx_show_retry_rd_err_log;
 static u64 skx_tolm, skx_tohm;
 static LIST_HEAD(dev_edac_list);
+static bool skx_mem_cfg_2lm;
 
-int __init skx_adxl_get(void)
+int skx_adxl_get(void)
 {
 	const char * const *names;
 	int i, j;
@@ -55,14 +61,25 @@
 		for (j = 0; names[j]; j++) {
 			if (!strcmp(component_names[i], names[j])) {
 				component_indices[i] = j;
+
+				if (i >= INDEX_NM_FIRST)
+					adxl_nm_bitmap |= 1 << i;
+
 				break;
 			}
 		}
 
-		if (!names[j])
+		if (!names[j] && i < INDEX_NM_FIRST)
 			goto err;
 	}
 
+	if (skx_mem_cfg_2lm) {
+		if (!adxl_nm_bitmap)
+			skx_printk(KERN_NOTICE, "Not enough ADXL components for 2-level memory.\n");
+		else
+			edac_dbg(2, "adxl_nm_bitmap: 0x%lx\n", adxl_nm_bitmap);
+	}
+
 	adxl_component_names = names;
 	while (*names++)
 		adxl_component_count++;
@@ -91,15 +108,18 @@
 
 	return -ENODEV;
 }
+EXPORT_SYMBOL_GPL(skx_adxl_get);
 
-void __exit skx_adxl_put(void)
+void skx_adxl_put(void)
 {
 	kfree(adxl_values);
 	kfree(adxl_msg);
 }
+EXPORT_SYMBOL_GPL(skx_adxl_put);
 
-static bool skx_adxl_decode(struct decoded_addr *res)
+static bool skx_adxl_decode(struct decoded_addr *res, bool error_in_1st_level_mem)
 {
+	struct skx_dev *d;
 	int i, len = 0;
 
 	if (res->addr >= skx_tohm || (res->addr >= skx_tolm &&
@@ -114,9 +134,36 @@
 	}
 
 	res->socket  = (int)adxl_values[component_indices[INDEX_SOCKET]];
-	res->imc     = (int)adxl_values[component_indices[INDEX_MEMCTRL]];
-	res->channel = (int)adxl_values[component_indices[INDEX_CHANNEL]];
-	res->dimm    = (int)adxl_values[component_indices[INDEX_DIMM]];
+	if (error_in_1st_level_mem) {
+		res->imc     = (adxl_nm_bitmap & BIT_NM_MEMCTRL) ?
+			       (int)adxl_values[component_indices[INDEX_NM_MEMCTRL]] : -1;
+		res->channel = (adxl_nm_bitmap & BIT_NM_CHANNEL) ?
+			       (int)adxl_values[component_indices[INDEX_NM_CHANNEL]] : -1;
+		res->dimm    = (adxl_nm_bitmap & BIT_NM_DIMM) ?
+			       (int)adxl_values[component_indices[INDEX_NM_DIMM]] : -1;
+	} else {
+		res->imc     = (int)adxl_values[component_indices[INDEX_MEMCTRL]];
+		res->channel = (int)adxl_values[component_indices[INDEX_CHANNEL]];
+		res->dimm    = (int)adxl_values[component_indices[INDEX_DIMM]];
+	}
+
+	if (res->imc > NUM_IMC - 1 || res->imc < 0) {
+		skx_printk(KERN_ERR, "Bad imc %d\n", res->imc);
+		return false;
+	}
+
+	list_for_each_entry(d, &dev_edac_list, list) {
+		if (d->imc[0].src_id == res->socket) {
+			res->dev = d;
+			break;
+		}
+	}
+
+	if (!res->dev) {
+		skx_printk(KERN_ERR, "No device for src_id %d imc %d\n",
+			   res->socket, res->imc);
+		return false;
+	}
 
 	for (i = 0; i < adxl_component_count; i++) {
 		if (adxl_values[i] == ~0x0ull)
@@ -131,10 +178,18 @@
 	return true;
 }
 
-void skx_set_decode(skx_decode_f decode)
+void skx_set_mem_cfg(bool mem_cfg_2lm)
+{
+	skx_mem_cfg_2lm = mem_cfg_2lm;
+}
+EXPORT_SYMBOL_GPL(skx_set_mem_cfg);
+
+void skx_set_decode(skx_decode_f decode, skx_show_retry_log_f show_retry_log)
 {
 	skx_decode = decode;
+	skx_show_retry_rd_err_log = show_retry_log;
 }
+EXPORT_SYMBOL_GPL(skx_set_decode);
 
 int skx_get_src_id(struct skx_dev *d, int off, u8 *id)
 {
@@ -148,6 +203,7 @@
 	*id = GET_BITFIELD(reg, 12, 14);
 	return 0;
 }
+EXPORT_SYMBOL_GPL(skx_get_src_id);
 
 int skx_get_node_id(struct skx_dev *d, u8 *id)
 {
@@ -161,6 +217,7 @@
 	*id = GET_BITFIELD(reg, 0, 2);
 	return 0;
 }
+EXPORT_SYMBOL_GPL(skx_get_node_id);
 
 static int get_width(u32 mtr)
 {
@@ -227,6 +284,7 @@
 		*list = &dev_edac_list;
 	return ndev;
 }
+EXPORT_SYMBOL_GPL(skx_get_all_bus_mappings);
 
 int skx_get_hi_lo(unsigned int did, int off[], u64 *tolm, u64 *tohm)
 {
@@ -235,7 +293,7 @@
 
 	pdev = pci_get_device(PCI_VENDOR_ID_INTEL, did, NULL);
 	if (!pdev) {
-		skx_printk(KERN_ERR, "Can't get tolm/tohm\n");
+		edac_dbg(2, "Can't get tolm/tohm\n");
 		return -ENODEV;
 	}
 
@@ -266,6 +324,7 @@
 	pci_dev_put(pdev);
 	return -ENODEV;
 }
+EXPORT_SYMBOL_GPL(skx_get_hi_lo);
 
 static int skx_get_dimm_attr(u32 reg, int lobit, int hibit, int add,
 			     int minval, int maxval, const char *name)
@@ -283,7 +342,7 @@
 #define numrow(reg)	skx_get_dimm_attr(reg, 2, 4, 12, 1, 6, "rows")
 #define numcol(reg)	skx_get_dimm_attr(reg, 0, 1, 10, 0, 2, "cols")
 
-int skx_get_dimm_info(u32 mtr, u32 amap, struct dimm_info *dimm,
+int skx_get_dimm_info(u32 mtr, u32 mcmtr, u32 amap, struct dimm_info *dimm,
 		      struct skx_imc *imc, int chan, int dimmno)
 {
 	int  banks = 16, ranks, rows, cols, npages;
@@ -303,8 +362,8 @@
 		 imc->mc, chan, dimmno, size, npages,
 		 banks, 1 << ranks, rows, cols);
 
-	imc->chan[chan].dimms[dimmno].close_pg = GET_BITFIELD(mtr, 0, 0);
-	imc->chan[chan].dimms[dimmno].bank_xor_enable = GET_BITFIELD(mtr, 9, 9);
+	imc->chan[chan].dimms[dimmno].close_pg = GET_BITFIELD(mcmtr, 0, 0);
+	imc->chan[chan].dimms[dimmno].bank_xor_enable = GET_BITFIELD(mcmtr, 9, 9);
 	imc->chan[chan].dimms[dimmno].fine_grain_bank = GET_BITFIELD(amap, 0, 0);
 	imc->chan[chan].dimms[dimmno].rowbits = rows;
 	imc->chan[chan].dimms[dimmno].colbits = cols;
@@ -319,6 +378,7 @@
 
 	return 1;
 }
+EXPORT_SYMBOL_GPL(skx_get_dimm_info);
 
 int skx_get_nvdimm_info(struct dimm_info *dimm, struct skx_imc *imc,
 			int chan, int dimmno, const char *mod_str)
@@ -367,6 +427,7 @@
 
 	return (size == 0 || size == ~0ull) ? 0 : 1;
 }
+EXPORT_SYMBOL_GPL(skx_get_nvdimm_info);
 
 int skx_register_mci(struct skx_imc *imc, struct pci_dev *pdev,
 		     const char *ctl_name, const char *mod_str,
@@ -434,6 +495,7 @@
 	imc->mci = NULL;
 	return rc;
 }
+EXPORT_SYMBOL_GPL(skx_register_mci);
 
 static void skx_unregister_mci(struct skx_imc *imc)
 {
@@ -452,34 +514,17 @@
 	edac_mc_free(mci);
 }
 
-static struct mem_ctl_info *get_mci(int src_id, int lmc)
-{
-	struct skx_dev *d;
-
-	if (lmc > NUM_IMC - 1) {
-		skx_printk(KERN_ERR, "Bad lmc %d\n", lmc);
-		return NULL;
-	}
-
-	list_for_each_entry(d, &dev_edac_list, list) {
-		if (d->imc[0].src_id == src_id)
-			return d->imc[lmc].mci;
-	}
-
-	skx_printk(KERN_ERR, "No mci for src_id %d lmc %d\n", src_id, lmc);
-	return NULL;
-}
-
 static void skx_mce_output_error(struct mem_ctl_info *mci,
 				 const struct mce *m,
 				 struct decoded_addr *res)
 {
 	enum hw_event_mc_err_type tp_event;
-	char *type, *optype;
+	char *optype;
 	bool ripv = GET_BITFIELD(m->mcgstatus, 0, 0);
 	bool overflow = GET_BITFIELD(m->status, 62, 62);
 	bool uncorrected_error = GET_BITFIELD(m->status, 61, 61);
 	bool recoverable;
+	int len;
 	u32 core_err_cnt = GET_BITFIELD(m->status, 38, 52);
 	u32 mscod = GET_BITFIELD(m->status, 16, 31);
 	u32 errcode = GET_BITFIELD(m->status, 0, 15);
@@ -490,14 +535,11 @@
 	if (uncorrected_error) {
 		core_err_cnt = 1;
 		if (ripv) {
-			type = "FATAL";
-			tp_event = HW_EVENT_ERR_FATAL;
-		} else {
-			type = "NON_FATAL";
 			tp_event = HW_EVENT_ERR_UNCORRECTED;
+		} else {
+			tp_event = HW_EVENT_ERR_FATAL;
 		}
 	} else {
-		type = "CORRECTED";
 		tp_event = HW_EVENT_ERR_CORRECTED;
 	}
 
@@ -539,12 +581,12 @@
 		}
 	}
 	if (adxl_component_count) {
-		snprintf(skx_msg, MSG_SIZE, "%s%s err_code:0x%04x:0x%04x %s",
+		len = snprintf(skx_msg, MSG_SIZE, "%s%s err_code:0x%04x:0x%04x %s",
 			 overflow ? " OVERFLOW" : "",
 			 (uncorrected_error && recoverable) ? " recoverable" : "",
 			 mscod, errcode, adxl_msg);
 	} else {
-		snprintf(skx_msg, MSG_SIZE,
+		len = snprintf(skx_msg, MSG_SIZE,
 			 "%s%s err_code:0x%04x:0x%04x socket:%d imc:%d rank:%d bg:%d ba:%d row:0x%x col:0x%x",
 			 overflow ? " OVERFLOW" : "",
 			 (uncorrected_error && recoverable) ? " recoverable" : "",
@@ -553,6 +595,9 @@
 			 res->bank_group, res->bank_address, res->row, res->column);
 	}
 
+	if (skx_show_retry_rd_err_log)
+		skx_show_retry_rd_err_log(res, skx_msg + len, MSG_SIZE - len);
+
 	edac_dbg(0, "%s\n", skx_msg);
 
 	/* Call the helper to output message */
@@ -562,6 +607,21 @@
 			     optype, skx_msg);
 }
 
+static bool skx_error_in_1st_level_mem(const struct mce *m)
+{
+	u32 errcode;
+
+	if (!skx_mem_cfg_2lm)
+		return false;
+
+	errcode = GET_BITFIELD(m->status, 0, 15);
+
+	if ((errcode & 0xef80) != 0x280)
+		return false;
+
+	return true;
+}
+
 int skx_mce_check_error(struct notifier_block *nb, unsigned long val,
 			void *data)
 {
@@ -581,17 +641,14 @@
 	res.addr = mce->addr;
 
 	if (adxl_component_count) {
-		if (!skx_adxl_decode(&res))
+		if (!skx_adxl_decode(&res, skx_error_in_1st_level_mem(mce)))
 			return NOTIFY_DONE;
-
-		mci = get_mci(res.socket, res.imc);
-	} else {
-		if (!skx_decode || !skx_decode(&res))
-			return NOTIFY_DONE;
-
-		mci = res.dev->imc[res.imc].mci;
+	} else if (!skx_decode || !skx_decode(&res)) {
+		return NOTIFY_DONE;
 	}
 
+	mci = res.dev->imc[res.imc].mci;
+
 	if (!mci)
 		return NOTIFY_DONE;
 
@@ -617,6 +674,7 @@
 
 	return NOTIFY_DONE;
 }
+EXPORT_SYMBOL_GPL(skx_mce_check_error);
 
 void skx_remove(void)
 {
@@ -652,3 +710,8 @@
 		kfree(d);
 	}
 }
+EXPORT_SYMBOL_GPL(skx_remove);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Tony Luck");
+MODULE_DESCRIPTION("MC Driver for Intel server processors");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/skx_common.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/skx_common.h
@@ -9,6 +9,8 @@
 #ifndef _SKX_COMM_EDAC_H
 #define _SKX_COMM_EDAC_H
 
+#include <linux/bits.h>
+
 #define MSG_SIZE		1024
 
 /*
@@ -64,6 +66,7 @@
 		u8 src_id, node_id;
 		struct skx_channel {
 			struct pci_dev	*cdev;
+			struct pci_dev	*edev;
 			struct skx_dimm {
 				u8 close_pg;
 				u8 bank_xor_enable;
@@ -89,9 +92,17 @@
 	INDEX_MEMCTRL,
 	INDEX_CHANNEL,
 	INDEX_DIMM,
+	INDEX_NM_FIRST,
+	INDEX_NM_MEMCTRL = INDEX_NM_FIRST,
+	INDEX_NM_CHANNEL,
+	INDEX_NM_DIMM,
 	INDEX_MAX
 };
 
+#define BIT_NM_MEMCTRL	BIT_ULL(INDEX_NM_MEMCTRL)
+#define BIT_NM_CHANNEL	BIT_ULL(INDEX_NM_CHANNEL)
+#define BIT_NM_DIMM	BIT_ULL(INDEX_NM_DIMM)
+
 struct decoded_addr {
 	struct skx_dev *dev;
 	u64	addr;
@@ -113,10 +124,12 @@
 
 typedef int (*get_dimm_config_f)(struct mem_ctl_info *mci);
 typedef bool (*skx_decode_f)(struct decoded_addr *res);
+typedef void (*skx_show_retry_log_f)(struct decoded_addr *res, char *msg, int len);
 
-int __init skx_adxl_get(void);
-void __exit skx_adxl_put(void);
-void skx_set_decode(skx_decode_f decode);
+int skx_adxl_get(void);
+void skx_adxl_put(void);
+void skx_set_decode(skx_decode_f decode, skx_show_retry_log_f show_retry_log);
+void skx_set_mem_cfg(bool mem_cfg_2lm);
 
 int skx_get_src_id(struct skx_dev *d, int off, u8 *id);
 int skx_get_node_id(struct skx_dev *d, u8 *id);
@@ -126,7 +139,7 @@
 
 int skx_get_hi_lo(unsigned int did, int off[], u64 *tolm, u64 *tohm);
 
-int skx_get_dimm_info(u32 mtr, u32 amap, struct dimm_info *dimm,
+int skx_get_dimm_info(u32 mtr, u32 mcmtr, u32 amap, struct dimm_info *dimm,
 		      struct skx_imc *imc, int chan, int dimmno);
 
 int skx_get_nvdimm_info(struct dimm_info *dimm, struct skx_imc *imc,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/synopsys_edac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/synopsys_edac.c
@@ -163,6 +163,11 @@
 #define ECC_STAT_CECNT_SHIFT		8
 #define ECC_STAT_BITNUM_MASK		0x7F
 
+/* ECC error count register definitions */
+#define ECC_ERRCNT_UECNT_MASK		0xFFFF0000
+#define ECC_ERRCNT_UECNT_SHIFT		16
+#define ECC_ERRCNT_CECNT_MASK		0xFFFF
+
 /* DDR QOS Interrupt register definitions */
 #define DDR_QOS_IRQ_STAT_OFST		0x20200
 #define DDR_QOSUE_MASK			0x4
@@ -418,15 +423,16 @@
 	base = priv->baseaddr;
 	p = &priv->stat;
 
+	regval = readl(base + ECC_ERRCNT_OFST);
+	p->ce_cnt = regval & ECC_ERRCNT_CECNT_MASK;
+	p->ue_cnt = (regval & ECC_ERRCNT_UECNT_MASK) >> ECC_ERRCNT_UECNT_SHIFT;
+	if (!p->ce_cnt)
+		goto ue_err;
+
 	regval = readl(base + ECC_STAT_OFST);
 	if (!regval)
 		return 1;
 
-	p->ce_cnt = (regval & ECC_STAT_CECNT_MASK) >> ECC_STAT_CECNT_SHIFT;
-	p->ue_cnt = (regval & ECC_STAT_UECNT_MASK) >> ECC_STAT_UECNT_SHIFT;
-	if (!p->ce_cnt)
-		goto ue_err;
-
 	p->ceinfo.bitpos = (regval & ECC_STAT_BITNUM_MASK);
 
 	regval = readl(base + ECC_CEADDR0_OFST);
@@ -479,20 +485,14 @@
 		pinf = &p->ceinfo;
 		if (!priv->p_data->quirks) {
 			snprintf(priv->message, SYNPS_EDAC_MSG_SIZE,
-				 "DDR ECC error type:%s Row %d Bank %d Col %d ",
-				  "CE", pinf->row, pinf->bank, pinf->col);
-			snprintf(priv->message, SYNPS_EDAC_MSG_SIZE,
-				 "Bit Position: %d Data: 0x%08x\n",
+				 "DDR ECC error type:%s Row %d Bank %d Col %d Bit Position: %d Data: 0x%08x",
+				 "CE", pinf->row, pinf->bank, pinf->col,
 				 pinf->bitpos, pinf->data);
 		} else {
 			snprintf(priv->message, SYNPS_EDAC_MSG_SIZE,
-				 "DDR ECC error type:%s Row %d Bank %d Col %d ",
-				  "CE", pinf->row, pinf->bank, pinf->col);
-			snprintf(priv->message, SYNPS_EDAC_MSG_SIZE,
-				 "BankGroup Number %d Block Number %d ",
-				 pinf->bankgrpnr, pinf->blknr);
-			snprintf(priv->message, SYNPS_EDAC_MSG_SIZE,
-				 "Bit Position: %d Data: 0x%08x\n",
+				 "DDR ECC error type:%s Row %d Bank %d Col %d BankGroup Number %d Block Number %d Bit Position: %d Data: 0x%08x",
+				 "CE", pinf->row, pinf->bank, pinf->col,
+				 pinf->bankgrpnr, pinf->blknr,
 				 pinf->bitpos, pinf->data);
 		}
 
@@ -509,10 +509,8 @@
 				"UE", pinf->row, pinf->bank, pinf->col);
 		} else {
 			snprintf(priv->message, SYNPS_EDAC_MSG_SIZE,
-				 "DDR ECC error type :%s Row %d Bank %d Col %d ",
-				 "UE", pinf->row, pinf->bank, pinf->col);
-			snprintf(priv->message, SYNPS_EDAC_MSG_SIZE,
-				 "BankGroup Number %d Block Number %d",
+				 "DDR ECC error type :%s Row %d Bank %d Col %d BankGroup Number %d Block Number %d",
+				 "UE", pinf->row, pinf->bank, pinf->col,
 				 pinf->bankgrpnr, pinf->blknr);
 		}
 
@@ -790,7 +788,7 @@
 
 		for (j = 0; j < csi->nr_channels; j++) {
 			dimm		= csi->channels[j]->dimm;
-			dimm->edac_mode	= EDAC_FLAG_SECDED;
+			dimm->edac_mode	= EDAC_SECDED;
 			dimm->mtype	= p_data->get_mtype(priv->baseaddr);
 			dimm->nr_pages	= (size >> PAGE_SHIFT) / csi->nr_channels;
 			dimm->grain	= SYNPS_EDAC_ERR_GRAIN;
@@ -1359,8 +1357,7 @@
 		}
 	}
 
-	if (of_device_is_compatible(pdev->dev.of_node,
-				    "xlnx,zynqmp-ddrc-2.40a"))
+	if (priv->p_data->quirks & DDR_ECC_INTR_SUPPORT)
 		setup_address_map(priv);
 #endif
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/thunderx_edac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/thunderx_edac.c
@@ -1133,7 +1133,7 @@
 		decode_register(other, OCX_OTHER_SIZE,
 				ocx_com_errors, ctx->reg_com_int);
 
-		strncat(msg, other, OCX_MESSAGE_SIZE);
+		strlcat(msg, other, OCX_MESSAGE_SIZE);
 
 		for (lane = 0; lane < OCX_RX_LANES; lane++)
 			if (ctx->reg_com_int & BIT(lane)) {
@@ -1142,12 +1142,12 @@
 					 lane, ctx->reg_lane_int[lane],
 					 lane, ctx->reg_lane_stat11[lane]);
 
-				strncat(msg, other, OCX_MESSAGE_SIZE);
+				strlcat(msg, other, OCX_MESSAGE_SIZE);
 
 				decode_register(other, OCX_OTHER_SIZE,
 						ocx_lane_errors,
 						ctx->reg_lane_int[lane]);
-				strncat(msg, other, OCX_MESSAGE_SIZE);
+				strlcat(msg, other, OCX_MESSAGE_SIZE);
 			}
 
 		if (ctx->reg_com_int & OCX_COM_INT_CE)
@@ -1217,7 +1217,7 @@
 		decode_register(other, OCX_OTHER_SIZE,
 				ocx_com_link_errors, ctx->reg_com_link_int);
 
-		strncat(msg, other, OCX_MESSAGE_SIZE);
+		strlcat(msg, other, OCX_MESSAGE_SIZE);
 
 		if (ctx->reg_com_link_int & OCX_COM_LINK_INT_UE)
 			edac_device_handle_ue(ocx->edac_dev, 0, 0, msg);
@@ -1896,7 +1896,7 @@
 
 		decode_register(other, L2C_OTHER_SIZE, l2_errors, ctx->reg_int);
 
-		strncat(msg, other, L2C_MESSAGE_SIZE);
+		strlcat(msg, other, L2C_MESSAGE_SIZE);
 
 		if (ctx->reg_int & mask_ue)
 			edac_device_handle_ue(l2c->edac_dev, 0, 0, msg);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/ti_edac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/ti_edac.c
@@ -197,6 +197,7 @@
 	{ .compatible = "ti,emif-dra7xx", .data = (void *)EMIF_TYPE_DRA7 },
 	{},
 };
+MODULE_DEVICE_TABLE(of, ti_edac_of_match);
 
 static int _emif_get_id(struct device_node *node)
 {
@@ -278,7 +279,8 @@
 
 	/* add EMIF ECC error handler */
 	error_irq = platform_get_irq(pdev, 0);
-	if (!error_irq) {
+	if (error_irq < 0) {
+		ret = error_irq;
 		edac_printk(KERN_ERR, EDAC_MOD_NAME,
 			    "EMIF irq number not defined.\n");
 		goto err;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/xgene_edac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/xgene_edac.c
@@ -1922,7 +1922,7 @@
 			irq = platform_get_irq(pdev, i);
 			if (irq < 0) {
 				dev_err(&pdev->dev, "No IRQ resource\n");
-				rc = -EINVAL;
+				rc = irq;
 				goto out_err;
 			}
 			rc = devm_request_irq(&pdev->dev, irq,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/xilinx_ddrmc_edac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/xilinx_ddrmc_edac.c
@@ -0,0 +1,1202 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 Xilinx, Inc.
+ */
+
+#include <linux/edac.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/sizes.h>
+
+#include "edac_module.h"
+
+/* Granularity of reported error in bytes */
+#define XDDR_EDAC_ERR_GRAIN			1
+
+#define XDDR_EDAC_MSG_SIZE			256
+
+#define XDDR_PCSR_OFFSET			0xC
+#define XDDR_ISR_OFFSET				0x14
+#define XDDR_IRQ_EN_OFFSET			0x20
+#define XDDR_IRQ_DIS_OFFSET			0x24
+#define XDDR_IRQ_CE_MASK			GENMASK(18, 15)
+#define XDDR_IRQ_UE_MASK			GENMASK(14, 11)
+
+#define XDDR_REG_CONFIG0_OFFSET			0x258
+#define XDDR_REG_CONFIG0_BUS_WIDTH_MASK		GENMASK(19, 18)
+#define XDDR_REG_CONFIG0_BUS_WIDTH_SHIFT	18
+#define XDDR_REG_CONFIG0_NUM_CHANS_MASK		BIT(17)
+#define XDDR_REG_CONFIG0_NUM_CHANS_SHIFT	17
+#define XDDR_REG_CONFIG0_NUM_RANKS_MASK		GENMASK(15, 14)
+#define XDDR_REG_CONFIG0_NUM_RANKS_SHIFT	14
+#define XDDR_REG_CONFIG0_SIZE_MASK		GENMASK(10, 8)
+#define XDDR_REG_CONFIG0_SIZE_SHIFT		8
+
+#define XDDR_REG_PINOUT_OFFSET			0x25C
+#define XDDR_REG_PINOUT_ECC_EN_MASK		GENMASK(7, 5)
+
+#define ECCW0_FLIP_CTRL				0x109C
+#define ECCW0_FLIP0_OFFSET			0x10A0
+#define ECCW1_FLIP_CTRL				0x10AC
+#define ECCW1_FLIP0_OFFSET			0x10B0
+#define ECCR0_CERR_STAT_OFFSET			0x10BC
+#define ECCR0_CE_ADDR_LO_OFFSET			0x10C0
+#define ECCR0_CE_ADDR_LO_OFFSET			0x10C0
+#define ECCR0_CE_ADDR_HI_OFFSET			0x10C4
+#define ECCR0_CE_DATA_LO_OFFSET			0x10C8
+#define ECCR0_CE_DATA_HI_OFFSET			0x10CC
+#define ECCR0_CE_DATA_PAR_OFFSET		0x10D0
+
+#define ECCR0_UERR_STAT_OFFSET			0x10D4
+#define ECCR0_UE_ADDR_LO_OFFSET			0x10D8
+#define ECCR0_UE_ADDR_HI_OFFSET			0x10DC
+#define ECCR0_UE_DATA_LO_OFFSET			0x10E0
+#define ECCR0_UE_DATA_HI_OFFSET			0x10E4
+#define ECCR0_UE_DATA_PAR_OFFSET		0x10E8
+
+#define ECCR1_CERR_STAT_OFFSET			0x10F4
+#define ECCR1_CE_ADDR_LO_OFFSET			0x10F8
+#define ECCR1_CE_ADDR_HI_OFFSET			0x10FC
+#define ECCR1_CE_DATA_LO_OFFSET			0x1100
+#define ECCR1_CE_DATA_HI_OFFSET			0x110C
+#define ECCR1_CE_DATA_PAR_OFFSET		0x1108
+
+#define ECCR1_UERR_STAT_OFFSET			0x110C
+#define ECCR1_UE_ADDR_LO_OFFSET			0x1110
+#define ECCR1_UE_ADDR_HI_OFFSET			0x1114
+#define ECCR1_UE_DATA_LO_OFFSET			0x1118
+#define ECCR1_UE_DATA_HI_OFFSET			0x111C
+#define ECCR1_UE_DATA_PAR_OFFSET		0x1120
+
+#define XDDR_NOC_REG_ADEC4_OFFSET		0x44
+#define RANK_0_MASK				GENMASK(5, 0)
+#define RANK_1_MASK				GENMASK(11, 6)
+#define RANK_1_SHIFT				6
+#define LRANK_0_MASK				GENMASK(17, 12)
+#define LRANK_0_SHIFT				12
+#define LRANK_1_MASK				GENMASK(23, 18)
+#define LRANK_1_SHIFT				18
+#define LRANK_2_MASK				GENMASK(29, 24)
+#define LRANK_2_SHIFT				24
+
+#define XDDR_NOC_REG_ADEC5_OFFSET		0x48
+#define ROW_0_MASK				GENMASK(5, 0)
+#define ROW_1_MASK				GENMASK(11, 6)
+#define ROW_1_SHIFT				6
+#define ROW_2_MASK				GENMASK(17, 12)
+#define ROW_2_SHIFT				12
+#define ROW_3_MASK				GENMASK(23, 18)
+#define ROW_3_SHIFT				18
+#define ROW_4_MASK				GENMASK(29, 24)
+#define ROW_4_SHIFT				24
+
+#define XDDR_NOC_REG_ADEC6_OFFSET		0x4C
+#define ROW_5_MASK				GENMASK(5, 0)
+#define ROW_6_MASK				GENMASK(11, 6)
+#define ROW_6_SHIFT				6
+#define ROW_7_MASK				GENMASK(17, 12)
+#define ROW_7_SHIFT				12
+#define ROW_8_MASK				GENMASK(23, 18)
+#define ROW_8_SHIFT				18
+#define ROW_9_MASK				GENMASK(29, 24)
+#define ROW_9_SHIFT				24
+
+#define XDDR_NOC_REG_ADEC7_OFFSET		0x50
+#define ROW_10_MASK				GENMASK(5, 0)
+#define ROW_11_MASK				GENMASK(11, 6)
+#define ROW_11_SHIFT				6
+#define ROW_12_MASK				GENMASK(17, 12)
+#define ROW_12_SHIFT				12
+#define ROW_13_MASK				GENMASK(23, 18)
+#define ROW_13_SHIFT				18
+#define ROW_14_MASK				GENMASK(29, 24)
+#define ROW_14_SHIFT				24
+
+#define XDDR_NOC_REG_ADEC8_OFFSET		0x54
+#define ROW_15_MASK				GENMASK(5, 0)
+#define ROW_16_MASK				GENMASK(11, 6)
+#define ROW_16_SHIFT				6
+#define ROW_17_MASK				GENMASK(17, 12)
+#define ROW_17_SHIFT				12
+#define ROW_18_MASK				GENMASK(23, 18)
+#define ROW_18_SHIFT				18
+#define COL_0_MASK				GENMASK(29, 24)
+#define COL_0_SHIFT				24
+
+#define XDDR_NOC_REG_ADEC9_OFFSET		0x58
+#define COL_1_MASK				GENMASK(5, 0)
+#define COL_2_MASK				GENMASK(11, 6)
+#define COL_2_SHIFT				6
+#define COL_3_MASK				GENMASK(17, 12)
+#define COL_3_SHIFT				12
+#define COL_4_MASK				GENMASK(23, 18)
+#define COL_4_SHIFT				18
+#define COL_5_MASK				GENMASK(29, 24)
+#define COL_5_SHIFT				24
+
+#define XDDR_NOC_REG_ADEC10_OFFSET		0x5C
+#define COL_6_MASK				GENMASK(5, 0)
+#define COL_7_MASK				GENMASK(11, 6)
+#define COL_7_SHIFT				6
+#define COL_8_MASK				GENMASK(17, 12)
+#define COL_8_SHIFT				12
+#define COL_9_MASK				GENMASK(23, 18)
+#define COL_9_SHIFT				18
+#define BANK_0_MASK				GENMASK(29, 24)
+#define BANK_0_SHIFT				24
+
+#define XDDR_NOC_REG_ADEC11_OFFSET		0x60
+#define BANK_1_MASK				GENMASK(5, 0)
+#define GRP_0_MASK				GENMASK(11, 6)
+#define GRP_0_SHIFT				6
+#define GRP_1_MASK				GENMASK(17, 12)
+#define GRP_1_SHIFT				12
+#define CH_0_MASK				GENMASK(23, 18)
+#define CH_0_SHIFT				18
+
+#define XDDR_NOC_REG_ADEC12_OFFSET		0x71C
+#define XDDR_NOC_REG_ADEC13_OFFSET		0x720
+
+#define XDDR_NOC_REG_ADEC14_OFFSET		0x724
+#define XDDR_NOC_ROW_MATCH_MASK			GENMASK(17, 0)
+#define XDDR_NOC_COL_MATCH_MASK			GENMASK(27, 18)
+#define XDDR_NOC_COL_MATCH_SHIFT		18
+#define XDDR_NOC_BANK_MATCH_MASK		GENMASK(29, 28)
+#define XDDR_NOC_BANK_MATCH_SHIFT		28
+#define XDDR_NOC_GRP_MATCH_MASK			GENMASK(31, 30)
+#define XDDR_NOC_GRP_MATCH_SHIFT		30
+
+#define XDDR_NOC_REG_ADEC15_OFFSET		0x728
+#define XDDR_NOC_RANK_MATCH_MASK		GENMASK(1, 0)
+#define XDDR_NOC_LRANK_MATCH_MASK		GENMASK(4, 2)
+#define XDDR_NOC_LRANK_MATCH_SHIFT		2
+#define XDDR_NOC_CH_MATCH_MASK			BIT(5)
+#define XDDR_NOC_CH_MATCH_SHIFT			5
+#define XDDR_NOC_MOD_SEL_MASK			BIT(6)
+#define XDDR_NOC_MATCH_EN_MASK			BIT(8)
+
+#define ECCR_UE_CE_ADDR_LO_BP_MASK		GENMASK(2, 0)
+#define ECCR_UE_CE_ADDR_LO_LRANK_MASK		GENMASK(5, 3)
+#define ECCR_UE_CE_ADDR_LO_LRANK_SHIFT		3
+#define ECCR_UE_CE_ADDR_LO_RANK_MASK		GENMASK(7, 6)
+#define ECCR_UE_CE_ADDR_LO_RANK_SHIFT		6
+#define ECCR_UE_CE_ADDR_LO_GRP_MASK		GENMASK(9, 8)
+#define ECCR_UE_CE_ADDR_LO_GRP_SHIFT		8
+#define ECCR_UE_CE_ADDR_LO_BANK_MASK		GENMASK(11, 10)
+#define ECCR_UE_CE_ADDR_LO_BANK_SHIFT		10
+#define ECCR_UE_CE_ADDR_LO_COL_MASK		GENMASK(21, 12)
+#define ECCR_UE_CE_ADDR_LO_COL_SHIFT		12
+#define ECCR_UE_CE_ADDR_LO_ROW_MASK		GENMASK(31, 22)
+#define ECCR_UE_CE_ADDR_LO_ROW_SHIFT		22
+#define ECCR_UE_CE_ADDR_HI_ROW_MASK		GENMASK(7, 0)
+#define ECCR_UE_CE_ADDR_HI_ROW_SHIFT		10
+
+#define XDDR_EDAC_NR_CSROWS			1
+#define XDDR_EDAC_NR_CHANS			1
+
+#define XDDR_BUS_WIDTH_64			0
+#define XDDR_BUS_WIDTH_32			1
+#define XDDR_BUS_WIDTH_16			2
+
+#define ECC_CEPOISON_MASK			0x1
+#define ECC_UEPOISON_MASK			0x3
+
+#define XDDR_MAX_ROW_CNT			18
+#define XDDR_MAX_COL_CNT			10
+#define XDDR_MAX_RANK_CNT			2
+#define XDDR_MAX_LRANK_CNT			3
+#define XDDR_MAX_BANK_CNT			2
+#define XDDR_MAX_GRP_CNT			2
+
+#define PCSR_UNLOCK_VAL				0xF9E8D7C6
+#define XDDR_ERR_TYPE_CE			0
+#define XDDR_ERR_TYPE_UE			1
+
+#define XILINX_DRAM_SIZE_4G			0
+#define XILINX_DRAM_SIZE_6G			1
+#define XILINX_DRAM_SIZE_8G			2
+#define XILINX_DRAM_SIZE_12G			3
+#define XILINX_DRAM_SIZE_16G			4
+#define XILINX_DRAM_SIZE_32G			5
+
+/**
+ * struct xddr_ecc_error_info - ECC error log information.
+ * @rank:		Rank number.
+ * @lrank:		Logical Rank number.
+ * @row:		Row number.
+ * @col:		Column number.
+ * @bank:		Bank number.
+ * @group:		Group number.
+ * @burstpos:		Burst position.
+ */
+struct xddr_ecc_error_info {
+	u32 rank;
+	u32 lrank;
+	u32 row;
+	u32 col;
+	u32 bank;
+	u32 group;
+	u32 burstpos;
+};
+
+/**
+ * struct xddr_ecc_status - ECC status information to report.
+ * @ceinfo:	Correctable error log information.
+ * @ueinfo:	Uncorrectable error log information.
+ * @channel:	Channel number.
+ * @error_type:	Error type information.
+ */
+struct xddr_ecc_status {
+	struct xddr_ecc_error_info ceinfo[2];
+	struct xddr_ecc_error_info ueinfo[2];
+	u32 channel;
+	u8 error_type;
+};
+
+/**
+ * struct xddr_edac_priv - DDR memory controller private instance data.
+ * @ddrmc_baseaddr:	Base address of the DDR controller.
+ * @ddrmc_noc_baseaddr:	Base address of the DDRMC NOC.
+ * @message:		Buffer for framing the event specific info.
+ * @mc_id:		Memory controller ID.
+ * @ce_cnt:		Correctable error count.
+ * @ue_cnt:		UnCorrectable error count.
+ * @stat:		ECC status information.
+ * @lrank_bit:		Bit shifts for lrank bit.
+ * @rank_bit:		Bit shifts for rank bit.
+ * @row_bit:		Bit shifts for row bit.
+ * @col_bit:		Bit shifts for column bit.
+ * @bank_bit:		Bit shifts for bank bit.
+ * @grp_bit:		Bit shifts for group bit.
+ * @ch_bit:		Bit shifts for channel bit.
+ * @err_inject_addr:	Data poison address.
+ */
+struct xddr_edac_priv {
+	void __iomem *ddrmc_baseaddr;
+	void __iomem *ddrmc_noc_baseaddr;
+	char message[XDDR_EDAC_MSG_SIZE];
+	u32 mc_id;
+	u32 ce_cnt;
+	u32 ue_cnt;
+	struct xddr_ecc_status stat;
+	u32 lrank_bit[3];
+	u32 rank_bit[2];
+	u32 row_bit[18];
+	u32 col_bit[10];
+	u32 bank_bit[2];
+	u32 grp_bit[2];
+	u32 ch_bit;
+#ifdef CONFIG_EDAC_DEBUG
+	u64 err_inject_addr;
+#endif
+};
+
+/**
+ * xddr_get_error_info - Get the current ECC error info.
+ * @priv:	DDR memory controller private instance data.
+ *
+ * Return: one if there is no error otherwise returns zero.
+ */
+static int xddr_get_error_info(struct xddr_edac_priv *priv)
+{
+	struct xddr_ecc_status *p;
+	u32 eccr0_ceval, eccr1_ceval, eccr0_ueval, eccr1_ueval, regval;
+	void __iomem *ddrmc_base;
+
+	ddrmc_base = priv->ddrmc_baseaddr;
+	p = &priv->stat;
+
+	eccr0_ceval = readl(ddrmc_base + ECCR0_CERR_STAT_OFFSET);
+	eccr1_ceval = readl(ddrmc_base + ECCR1_CERR_STAT_OFFSET);
+	eccr0_ueval = readl(ddrmc_base + ECCR0_UERR_STAT_OFFSET);
+	eccr1_ueval = readl(ddrmc_base + ECCR1_UERR_STAT_OFFSET);
+
+	if (!eccr0_ceval && !eccr1_ceval && !eccr0_ueval && !eccr1_ueval)
+		return 1;
+	else if (!eccr0_ceval && !eccr1_ceval)
+		goto ue_err;
+	else if (!eccr0_ceval)
+		p->channel = 1;
+	else
+		p->channel = 0;
+
+	p->error_type = XDDR_ERR_TYPE_CE;
+	regval = readl(ddrmc_base + ECCR0_CE_ADDR_LO_OFFSET);
+	p->ceinfo[0].burstpos = (regval & ECCR_UE_CE_ADDR_LO_BP_MASK);
+	p->ceinfo[0].lrank = (regval & ECCR_UE_CE_ADDR_LO_LRANK_MASK) >>
+					ECCR_UE_CE_ADDR_LO_LRANK_SHIFT;
+	p->ceinfo[0].rank = (regval & ECCR_UE_CE_ADDR_LO_RANK_MASK) >>
+					ECCR_UE_CE_ADDR_LO_RANK_SHIFT;
+	p->ceinfo[0].group = (regval & ECCR_UE_CE_ADDR_LO_GRP_MASK) >>
+					ECCR_UE_CE_ADDR_LO_GRP_SHIFT;
+	p->ceinfo[0].bank = (regval & ECCR_UE_CE_ADDR_LO_BANK_MASK) >>
+					ECCR_UE_CE_ADDR_LO_BANK_SHIFT;
+	p->ceinfo[0].col = (regval & ECCR_UE_CE_ADDR_LO_COL_MASK) >>
+					ECCR_UE_CE_ADDR_LO_COL_SHIFT;
+	p->ceinfo[0].row = (regval & ECCR_UE_CE_ADDR_LO_ROW_MASK) >>
+					ECCR_UE_CE_ADDR_LO_ROW_SHIFT;
+	regval = readl(ddrmc_base + ECCR0_CE_ADDR_HI_OFFSET);
+	p->ceinfo[0].row |= ((regval & ECCR_UE_CE_ADDR_HI_ROW_MASK) <<
+					ECCR_UE_CE_ADDR_HI_ROW_SHIFT);
+
+	edac_dbg(2, "ERR DATA LOW: 0x%08X ERR DATA HIGH: 0x%08X ERR DATA PARITY: 0x%08X\n",
+		 readl(ddrmc_base + ECCR0_CE_DATA_LO_OFFSET),
+		 readl(ddrmc_base + ECCR0_CE_DATA_HI_OFFSET),
+		 readl(ddrmc_base + ECCR0_CE_DATA_PAR_OFFSET));
+
+	regval = readl(ddrmc_base + ECCR1_CE_ADDR_LO_OFFSET);
+	p->ceinfo[1].burstpos = (regval & ECCR_UE_CE_ADDR_LO_BP_MASK);
+	p->ceinfo[1].lrank = (regval & ECCR_UE_CE_ADDR_LO_LRANK_MASK) >>
+					ECCR_UE_CE_ADDR_LO_LRANK_SHIFT;
+	p->ceinfo[1].rank = (regval & ECCR_UE_CE_ADDR_LO_RANK_MASK) >>
+					ECCR_UE_CE_ADDR_LO_RANK_SHIFT;
+	p->ceinfo[1].group = (regval & ECCR_UE_CE_ADDR_LO_GRP_MASK) >>
+					ECCR_UE_CE_ADDR_LO_GRP_SHIFT;
+	p->ceinfo[1].bank = (regval & ECCR_UE_CE_ADDR_LO_BANK_MASK) >>
+					ECCR_UE_CE_ADDR_LO_BANK_SHIFT;
+	p->ceinfo[1].col = (regval & ECCR_UE_CE_ADDR_LO_COL_MASK) >>
+					ECCR_UE_CE_ADDR_LO_COL_SHIFT;
+	p->ceinfo[1].row = (regval & ECCR_UE_CE_ADDR_LO_ROW_MASK) >>
+					ECCR_UE_CE_ADDR_LO_ROW_SHIFT;
+	regval = readl(ddrmc_base + ECCR1_CE_ADDR_HI_OFFSET);
+	p->ceinfo[1].row |= ((regval & ECCR_UE_CE_ADDR_HI_ROW_MASK) <<
+					ECCR_UE_CE_ADDR_HI_ROW_SHIFT);
+
+	edac_dbg(2, "ERR DATA LOW: 0x%08X ERR DATA HIGH: 0x%08X ERR DATA PARITY: 0x%08X\n",
+		 readl(ddrmc_base + ECCR1_CE_DATA_LO_OFFSET),
+		 readl(ddrmc_base + ECCR1_CE_DATA_HI_OFFSET),
+		 readl(ddrmc_base + ECCR1_CE_DATA_PAR_OFFSET));
+ue_err:
+	if (!eccr0_ueval && !eccr1_ueval)
+		goto out;
+	else if (!eccr0_ueval)
+		p->channel = 1;
+	else
+		p->channel = 0;
+
+	p->error_type = XDDR_ERR_TYPE_UE;
+	regval = readl(ddrmc_base + ECCR0_UE_ADDR_LO_OFFSET);
+	p->ueinfo[0].burstpos = (regval & ECCR_UE_CE_ADDR_LO_BP_MASK);
+	p->ueinfo[0].lrank = (regval & ECCR_UE_CE_ADDR_LO_LRANK_MASK) >>
+					ECCR_UE_CE_ADDR_LO_LRANK_SHIFT;
+	p->ueinfo[0].rank = (regval & ECCR_UE_CE_ADDR_LO_RANK_MASK) >>
+					ECCR_UE_CE_ADDR_LO_RANK_SHIFT;
+	p->ueinfo[0].group = (regval & ECCR_UE_CE_ADDR_LO_GRP_MASK) >>
+					ECCR_UE_CE_ADDR_LO_GRP_SHIFT;
+	p->ueinfo[0].bank = (regval & ECCR_UE_CE_ADDR_LO_BANK_MASK) >>
+					ECCR_UE_CE_ADDR_LO_BANK_SHIFT;
+	p->ueinfo[0].col = (regval & ECCR_UE_CE_ADDR_LO_COL_MASK) >>
+					ECCR_UE_CE_ADDR_LO_COL_SHIFT;
+	p->ueinfo[0].row = (regval & ECCR_UE_CE_ADDR_LO_ROW_MASK) >>
+					ECCR_UE_CE_ADDR_LO_ROW_SHIFT;
+	regval = readl(ddrmc_base + ECCR0_UE_ADDR_HI_OFFSET);
+	p->ueinfo[0].row |= ((regval & ECCR_UE_CE_ADDR_HI_ROW_MASK) <<
+					ECCR_UE_CE_ADDR_HI_ROW_SHIFT);
+
+	edac_dbg(2, "ERR DATA LOW: 0x%08X ERR DATA HIGH: 0x%08X ERR DATA PARITY: 0x%08X\n",
+		 readl(ddrmc_base + ECCR0_UE_DATA_LO_OFFSET),
+		 readl(ddrmc_base + ECCR0_UE_DATA_HI_OFFSET),
+		 readl(ddrmc_base + ECCR0_UE_DATA_PAR_OFFSET));
+
+	regval = readl(ddrmc_base + ECCR1_UE_ADDR_LO_OFFSET);
+	p->ueinfo[1].burstpos = (regval & ECCR_UE_CE_ADDR_LO_BP_MASK);
+	p->ueinfo[1].lrank = (regval & ECCR_UE_CE_ADDR_LO_LRANK_MASK) >>
+					ECCR_UE_CE_ADDR_LO_LRANK_SHIFT;
+	p->ueinfo[1].rank = (regval & ECCR_UE_CE_ADDR_LO_RANK_MASK) >>
+					ECCR_UE_CE_ADDR_LO_RANK_SHIFT;
+	p->ueinfo[1].group = (regval & ECCR_UE_CE_ADDR_LO_GRP_MASK) >>
+					ECCR_UE_CE_ADDR_LO_GRP_SHIFT;
+	p->ueinfo[1].bank = (regval & ECCR_UE_CE_ADDR_LO_BANK_MASK) >>
+					ECCR_UE_CE_ADDR_LO_BANK_SHIFT;
+	p->ueinfo[1].col = (regval & ECCR_UE_CE_ADDR_LO_COL_MASK) >>
+					ECCR_UE_CE_ADDR_LO_COL_SHIFT;
+	p->ueinfo[1].row = (regval & ECCR_UE_CE_ADDR_LO_ROW_MASK) >>
+					ECCR_UE_CE_ADDR_LO_ROW_SHIFT;
+	regval = readl(ddrmc_base + ECCR1_UE_ADDR_HI_OFFSET);
+	p->ueinfo[1].row |= ((regval & ECCR_UE_CE_ADDR_HI_ROW_MASK) <<
+					ECCR_UE_CE_ADDR_HI_ROW_SHIFT);
+
+	edac_dbg(2, "ERR DATA LOW: 0x%08X ERR DATA HIGH: 0x%08X ERR DATA PARITY: 0x%08X\n",
+		 readl(ddrmc_base + ECCR1_UE_DATA_LO_OFFSET),
+		 readl(ddrmc_base + ECCR1_UE_DATA_HI_OFFSET),
+		 readl(ddrmc_base + ECCR1_UE_DATA_PAR_OFFSET));
+
+out:
+	/* Unlock the PCSR registers */
+	writel(PCSR_UNLOCK_VAL, ddrmc_base + XDDR_PCSR_OFFSET);
+
+	writel(0, ddrmc_base + ECCR0_CERR_STAT_OFFSET);
+	writel(0, ddrmc_base + ECCR1_CERR_STAT_OFFSET);
+	writel(0, ddrmc_base + ECCR0_UERR_STAT_OFFSET);
+	writel(0, ddrmc_base + ECCR1_UERR_STAT_OFFSET);
+
+	/* Lock the PCSR registers */
+	writel(1, ddrmc_base + XDDR_PCSR_OFFSET);
+
+	return 0;
+}
+
+/**
+ * xddr_convert_to_physical - Convert to physical address.
+ * @priv:	DDR memory controller private instance data.
+ * @pinf:	ECC error info structure.
+ *
+ * Return: Physical address of the DDR memory.
+ */
+static ulong xddr_convert_to_physical(struct xddr_edac_priv *priv,
+				      struct xddr_ecc_error_info pinf)
+{
+	ulong err_addr = 0;
+	u32 index;
+
+	for (index = 0; index < XDDR_MAX_ROW_CNT; index++) {
+		err_addr |= (pinf.row & BIT(0)) << priv->row_bit[index];
+		pinf.row >>= 1;
+	}
+
+	for (index = 0; index < XDDR_MAX_COL_CNT; index++) {
+		err_addr |= (pinf.col & BIT(0)) << priv->col_bit[index];
+		pinf.col >>= 1;
+	}
+
+	for (index = 0; index < XDDR_MAX_BANK_CNT; index++) {
+		err_addr |= (pinf.bank & BIT(0)) << priv->bank_bit[index];
+		pinf.bank >>= 1;
+	}
+
+	for (index = 0; index < XDDR_MAX_GRP_CNT; index++) {
+		err_addr |= (pinf.group & BIT(0)) << priv->grp_bit[index];
+		pinf.group >>= 1;
+	}
+
+	for (index = 0; index < XDDR_MAX_RANK_CNT; index++) {
+		err_addr |= (pinf.rank & BIT(0)) << priv->rank_bit[index];
+		pinf.rank >>= 1;
+	}
+
+	for (index = 0; index < XDDR_MAX_LRANK_CNT; index++) {
+		err_addr |= (pinf.lrank & BIT(0)) << priv->lrank_bit[index];
+		pinf.lrank >>= 1;
+	}
+
+	err_addr |= (priv->stat.channel & BIT(0)) << priv->ch_bit;
+
+	return err_addr;
+}
+
+/**
+ * xddr_handle_error - Handle Correctable and Uncorrectable errors.
+ * @mci:	EDAC memory controller instance.
+ * @stat:	ECC status structure.
+ *
+ * Handles ECC correctable and uncorrectable errors.
+ */
+static void xddr_handle_error(struct mem_ctl_info *mci,
+			      struct xddr_ecc_status *stat)
+{
+	struct xddr_edac_priv *priv = mci->pvt_info;
+	struct xddr_ecc_error_info pinf;
+
+	if (stat->error_type == XDDR_ERR_TYPE_CE) {
+		priv->ce_cnt++;
+		pinf = stat->ceinfo[stat->channel];
+		snprintf(priv->message, XDDR_EDAC_MSG_SIZE,
+			 "Error type:%s MC ID: %d Addr at %lx Burst Pos: %d\n",
+			 "CE", priv->mc_id,
+			 xddr_convert_to_physical(priv, pinf), pinf.burstpos);
+
+		edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci,
+				     priv->ce_cnt, 0, 0, 0, 0, 0, -1,
+				     priv->message, "");
+	}
+
+	if (stat->error_type == XDDR_ERR_TYPE_UE) {
+		priv->ue_cnt++;
+		pinf = stat->ueinfo[stat->channel];
+		snprintf(priv->message, XDDR_EDAC_MSG_SIZE,
+			 "Error type:%s MC ID: %d Addr at %lx Burst Pos: %d\n",
+			 "UE", priv->mc_id,
+			 xddr_convert_to_physical(priv, pinf), pinf.burstpos);
+
+		edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci,
+				     priv->ue_cnt, 0, 0, 0, 0, 0, -1,
+				     priv->message, "");
+	}
+
+	memset(stat, 0, sizeof(*stat));
+}
+
+/**
+ * xddr_intr_handler - Interrupt Handler for ECC interrupts.
+ * @irq:	IRQ number
+ * @dev_id:	Device ID
+ *
+ * Return: IRQ_NONE, if interrupt not set or IRQ_HANDLED otherwise.
+ */
+static irqreturn_t xddr_intr_handler(int irq, void *dev_id)
+{
+	struct mem_ctl_info *mci = dev_id;
+	struct xddr_edac_priv *priv;
+	int status, regval;
+
+	priv = mci->pvt_info;
+	regval = readl(priv->ddrmc_baseaddr + XDDR_ISR_OFFSET);
+	regval &= (XDDR_IRQ_CE_MASK | XDDR_IRQ_UE_MASK);
+	if (!regval)
+		return IRQ_NONE;
+
+	/* Unlock the PCSR registers */
+	writel(PCSR_UNLOCK_VAL, priv->ddrmc_baseaddr + XDDR_PCSR_OFFSET);
+
+	/* Clear the ISR */
+	writel(regval, priv->ddrmc_baseaddr + XDDR_ISR_OFFSET);
+
+	/* Lock the PCSR registers */
+	writel(1, priv->ddrmc_baseaddr + XDDR_PCSR_OFFSET);
+
+	status = xddr_get_error_info(priv);
+	if (status)
+		return IRQ_NONE;
+
+	xddr_handle_error(mci, &priv->stat);
+
+	edac_dbg(3, "Total error count CE %d UE %d\n",
+		 priv->ce_cnt, priv->ue_cnt);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * xddr_get_dtype - Return the controller memory width.
+ * @base:	DDR memory controller base address.
+ *
+ * Get the EDAC device type width appropriate for the controller
+ * configuration.
+ *
+ * Return: a device type width enumeration.
+ */
+static enum dev_type xddr_get_dwidth(const void __iomem *base)
+{
+	enum dev_type dt;
+	u32 regval;
+
+	regval = readl(base + XDDR_REG_CONFIG0_OFFSET);
+	regval = (regval & XDDR_REG_CONFIG0_BUS_WIDTH_MASK) >>
+				XDDR_REG_CONFIG0_BUS_WIDTH_SHIFT;
+	switch (regval) {
+	case XDDR_BUS_WIDTH_16:
+		dt = DEV_X2;
+		break;
+	case XDDR_BUS_WIDTH_32:
+		dt = DEV_X4;
+		break;
+	case XDDR_BUS_WIDTH_64:
+		dt = DEV_X8;
+		break;
+	default:
+		dt = DEV_UNKNOWN;
+	}
+
+	return dt;
+}
+
+/**
+ * xddr_get_ecc_state - Return the controller ECC enable/disable status.
+ * @base:	DDR memory controller base address.
+ *
+ * Get the ECC enable/disable status for the controller.
+ *
+ * Return: a ECC status boolean i.e true/false - enabled/disabled.
+ */
+static bool xddr_get_ecc_state(void __iomem *base)
+{
+	enum dev_type dt;
+	u32 ecctype;
+
+	dt = xddr_get_dwidth(base);
+	if (dt == DEV_UNKNOWN)
+		return false;
+
+	ecctype = readl(base + XDDR_REG_PINOUT_OFFSET);
+	ecctype &= XDDR_REG_PINOUT_ECC_EN_MASK;
+	if (ecctype)
+		return true;
+
+	return false;
+}
+
+/**
+ * xddr_get_memsize - Get the size of the attached memory device.
+ * @priv:	DDR memory controller private instance data.
+ *
+ * Return: the memory size in bytes.
+ */
+static u64 xddr_get_memsize(struct xddr_edac_priv *priv)
+{
+	u64 size;
+	u32 regval;
+
+	regval = readl(priv->ddrmc_baseaddr + XDDR_REG_CONFIG0_OFFSET) &
+				XDDR_REG_CONFIG0_SIZE_MASK;
+	regval >>= XDDR_REG_CONFIG0_SIZE_SHIFT;
+	switch (regval) {
+	case XILINX_DRAM_SIZE_4G:
+		size = (4U * SZ_1G);
+		break;
+	case XILINX_DRAM_SIZE_6G:
+		size = (6U * SZ_1G);
+		break;
+	case XILINX_DRAM_SIZE_8G:
+		size = (8U * SZ_1G);
+		break;
+	case XILINX_DRAM_SIZE_12G:
+		size = (12U * SZ_1G);
+		break;
+	case XILINX_DRAM_SIZE_16G:
+		size = (16U * SZ_1G);
+		break;
+	case XILINX_DRAM_SIZE_32G:
+		size = (32U * SZ_1G);
+		break;
+	default:
+		/* Invalid configuration */
+		size = 0;
+		break;
+	}
+
+	return size;
+}
+
+/**
+ * xddr_init_csrows - Initialize the csrow data.
+ * @mci:	EDAC memory controller instance.
+ *
+ * Initialize the chip select rows associated with the EDAC memory
+ * controller instance.
+ */
+static void xddr_init_csrows(struct mem_ctl_info *mci)
+{
+	struct xddr_edac_priv *priv = mci->pvt_info;
+	struct csrow_info *csi;
+	struct dimm_info *dimm;
+	u32 row;
+	int ch;
+	unsigned long size;
+
+	size = xddr_get_memsize(priv);
+	for (row = 0; row < mci->nr_csrows; row++) {
+		csi = mci->csrows[row];
+		for (ch = 0; ch < csi->nr_channels; ch++) {
+			dimm = csi->channels[ch]->dimm;
+			dimm->edac_mode	= EDAC_SECDED;
+			dimm->mtype = MEM_DDR4;
+			dimm->nr_pages = (size >> PAGE_SHIFT) /
+						csi->nr_channels;
+			dimm->grain = XDDR_EDAC_ERR_GRAIN;
+			dimm->dtype = xddr_get_dwidth(priv->ddrmc_baseaddr);
+		}
+	}
+}
+
+/**
+ * xddr_mc_init - Initialize one driver instance.
+ * @mci:	EDAC memory controller instance.
+ * @pdev:	platform device.
+ *
+ * Perform initialization of the EDAC memory controller instance and
+ * related driver-private data associated with the memory controller the
+ * instance is bound to.
+ */
+static void xddr_mc_init(struct mem_ctl_info *mci, struct platform_device *pdev)
+{
+	mci->pdev = &pdev->dev;
+	platform_set_drvdata(pdev, mci);
+
+	/* Initialize controller capabilities and configuration */
+	mci->mtype_cap = MEM_FLAG_DDR4;
+	mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
+	mci->scrub_cap = SCRUB_HW_SRC;
+	mci->scrub_mode = SCRUB_NONE;
+
+	mci->edac_cap = EDAC_FLAG_SECDED;
+	mci->ctl_name = "xlnx_ddr_controller";
+	mci->dev_name = dev_name(&pdev->dev);
+	mci->mod_name = "xlnx_edac";
+
+	edac_op_state = EDAC_OPSTATE_INT;
+
+	xddr_init_csrows(mci);
+}
+
+static void xddr_enable_intr(struct xddr_edac_priv *priv)
+{
+	/* Unlock the PCSR registers */
+	writel(PCSR_UNLOCK_VAL, priv->ddrmc_baseaddr + XDDR_PCSR_OFFSET);
+
+	/* Enable UE/CE Interrupts */
+	writel(XDDR_IRQ_CE_MASK | XDDR_IRQ_UE_MASK,
+	       priv->ddrmc_baseaddr + XDDR_IRQ_EN_OFFSET);
+
+	/* Lock the PCSR registers */
+	writel(1, priv->ddrmc_baseaddr + XDDR_PCSR_OFFSET);
+}
+
+static void xddr_disable_intr(struct xddr_edac_priv *priv)
+{
+	/* Unlock the PCSR registers */
+	writel(PCSR_UNLOCK_VAL, priv->ddrmc_baseaddr + XDDR_PCSR_OFFSET);
+
+	/* Disable UE/CE Interrupts */
+	writel(XDDR_IRQ_CE_MASK | XDDR_IRQ_UE_MASK,
+	       priv->ddrmc_baseaddr + XDDR_IRQ_DIS_OFFSET);
+
+	/* Lock the PCSR registers */
+	writel(1, priv->ddrmc_baseaddr + XDDR_PCSR_OFFSET);
+}
+
+static int xddr_setup_irq(struct mem_ctl_info *mci,
+			  struct platform_device *pdev)
+{
+	struct xddr_edac_priv *priv = mci->pvt_info;
+	int ret, irq;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		edac_printk(KERN_ERR, EDAC_MC,
+			    "No IRQ %d in DT\n", irq);
+		return irq;
+	}
+
+	ret = devm_request_irq(&pdev->dev, irq, xddr_intr_handler,
+			       IRQF_SHARED, dev_name(&pdev->dev), mci);
+	if (ret < 0) {
+		edac_printk(KERN_ERR, EDAC_MC, "Failed to request IRQ\n");
+		return ret;
+	}
+
+	xddr_enable_intr(priv);
+
+	return 0;
+}
+
+#ifdef CONFIG_EDAC_DEBUG
+#define to_mci(k) container_of(k, struct mem_ctl_info, dev)
+
+/**
+ * ddr_poison_setup - Update poison registers.
+ * @priv:	DDR memory controller private instance data.
+ *
+ * Update poison registers as per DDR mapping.
+ * Return: none.
+ */
+static void xddr_poison_setup(struct xddr_edac_priv *priv)
+{
+	u32 col = 0, row = 0, bank = 0, grp = 0, rank = 0, lrank = 0, ch = 0;
+	u32 index, regval;
+
+	for (index = 0; index < XDDR_MAX_ROW_CNT; index++) {
+		row |= (((priv->err_inject_addr >> priv->row_bit[index]) &
+						BIT(0)) << index);
+	}
+
+	for (index = 0; index < XDDR_MAX_COL_CNT; index++) {
+		col |= (((priv->err_inject_addr >> priv->col_bit[index]) &
+						BIT(0)) << index);
+	}
+
+	for (index = 0; index < XDDR_MAX_BANK_CNT; index++) {
+		bank |= (((priv->err_inject_addr >> priv->bank_bit[index]) &
+						BIT(0)) << index);
+	}
+
+	for (index = 0; index < XDDR_MAX_GRP_CNT; index++) {
+		grp |= (((priv->err_inject_addr >> priv->grp_bit[index]) &
+						BIT(0)) << index);
+	}
+
+	for (index = 0; index < XDDR_MAX_RANK_CNT; index++) {
+		rank |= (((priv->err_inject_addr >> priv->rank_bit[index]) &
+						BIT(0)) << index);
+	}
+
+	for (index = 0; index < XDDR_MAX_LRANK_CNT; index++) {
+		lrank |= (((priv->err_inject_addr >> priv->lrank_bit[index]) &
+						BIT(0)) << index);
+	}
+
+	ch = (priv->err_inject_addr >> priv->ch_bit) & BIT(0);
+	if (ch)
+		writel(0xFF, priv->ddrmc_baseaddr + ECCW1_FLIP_CTRL);
+	else
+		writel(0xFF, priv->ddrmc_baseaddr + ECCW0_FLIP_CTRL);
+
+	writel(0, priv->ddrmc_noc_baseaddr + XDDR_NOC_REG_ADEC12_OFFSET);
+	writel(0, priv->ddrmc_noc_baseaddr + XDDR_NOC_REG_ADEC13_OFFSET);
+
+	regval = (row & XDDR_NOC_ROW_MATCH_MASK);
+	regval |= (col << XDDR_NOC_COL_MATCH_SHIFT) & XDDR_NOC_COL_MATCH_MASK;
+	regval |= (bank << XDDR_NOC_BANK_MATCH_SHIFT) &
+			XDDR_NOC_BANK_MATCH_MASK;
+	regval |= (grp << XDDR_NOC_GRP_MATCH_SHIFT) & XDDR_NOC_GRP_MATCH_MASK;
+	writel(regval, priv->ddrmc_noc_baseaddr + XDDR_NOC_REG_ADEC14_OFFSET);
+
+	regval = (rank & XDDR_NOC_RANK_MATCH_MASK);
+	regval |= (lrank << XDDR_NOC_LRANK_MATCH_SHIFT) &
+			XDDR_NOC_LRANK_MATCH_MASK;
+	regval |= (ch << XDDR_NOC_CH_MATCH_SHIFT) & XDDR_NOC_CH_MATCH_MASK;
+	regval |= (XDDR_NOC_MOD_SEL_MASK | XDDR_NOC_MATCH_EN_MASK);
+	writel(regval, priv->ddrmc_noc_baseaddr + XDDR_NOC_REG_ADEC15_OFFSET);
+}
+
+static ssize_t inject_data_error_show(struct device *dev,
+				      struct device_attribute *mattr,
+				      char *data)
+{
+	struct mem_ctl_info *mci = to_mci(dev);
+	struct xddr_edac_priv *priv = mci->pvt_info;
+
+	return sprintf(data, "Error injection Address: 0x%llx\n\r",
+			priv->err_inject_addr);
+}
+
+static ssize_t inject_data_error_store(struct device *dev,
+				       struct device_attribute *mattr,
+				       const char *data, size_t count)
+{
+	struct mem_ctl_info *mci = to_mci(dev);
+	struct xddr_edac_priv *priv = mci->pvt_info;
+
+	if (kstrtoull(data, 0, &priv->err_inject_addr))
+		return -EINVAL;
+
+	/* Unlock the PCSR registers */
+	writel(PCSR_UNLOCK_VAL, priv->ddrmc_baseaddr + XDDR_PCSR_OFFSET);
+	writel(PCSR_UNLOCK_VAL, priv->ddrmc_noc_baseaddr + XDDR_PCSR_OFFSET);
+
+	xddr_poison_setup(priv);
+
+	/* Lock the PCSR registers */
+	writel(1, priv->ddrmc_baseaddr + XDDR_PCSR_OFFSET);
+	writel(1, priv->ddrmc_noc_baseaddr + XDDR_PCSR_OFFSET);
+
+	return count;
+}
+
+static ssize_t inject_data_poison_show(struct device *dev,
+				       struct device_attribute *mattr,
+				       char *data)
+{
+	struct mem_ctl_info *mci = to_mci(dev);
+	struct xddr_edac_priv *priv = mci->pvt_info;
+	u32 regval;
+
+	regval = readl(priv->ddrmc_baseaddr + ECCW0_FLIP0_OFFSET);
+	return sprintf(data, "Data Poisoning: %s\n\r",
+			((regval & 0x3) == 1)
+			? ("Correctable Error") : ("UnCorrectable Error"));
+}
+
+static ssize_t inject_data_poison_store(struct device *dev,
+					struct device_attribute *mattr,
+					const char *data, size_t count)
+{
+	struct mem_ctl_info *mci = to_mci(dev);
+	struct xddr_edac_priv *priv = mci->pvt_info;
+
+	/* Unlock the PCSR registers */
+	writel(PCSR_UNLOCK_VAL, priv->ddrmc_baseaddr + XDDR_PCSR_OFFSET);
+
+	writel(0, priv->ddrmc_baseaddr + ECCW0_FLIP0_OFFSET);
+	writel(0, priv->ddrmc_baseaddr + ECCW1_FLIP0_OFFSET);
+	if (strncmp(data, "CE", 2) == 0) {
+		writel(ECC_CEPOISON_MASK, priv->ddrmc_baseaddr +
+		       ECCW0_FLIP0_OFFSET);
+		writel(ECC_CEPOISON_MASK, priv->ddrmc_baseaddr +
+		       ECCW1_FLIP0_OFFSET);
+	} else {
+		writel(ECC_UEPOISON_MASK, priv->ddrmc_baseaddr +
+		       ECCW0_FLIP0_OFFSET);
+		writel(ECC_UEPOISON_MASK, priv->ddrmc_baseaddr +
+		       ECCW1_FLIP0_OFFSET);
+	}
+
+	/* Lock the PCSR registers */
+	writel(1, priv->ddrmc_baseaddr + XDDR_PCSR_OFFSET);
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(inject_data_error);
+static DEVICE_ATTR_RW(inject_data_poison);
+
+static int edac_create_sysfs_attributes(struct mem_ctl_info *mci)
+{
+	int rc;
+
+	rc = device_create_file(&mci->dev, &dev_attr_inject_data_error);
+	if (rc < 0)
+		return rc;
+
+	rc = device_create_file(&mci->dev, &dev_attr_inject_data_poison);
+	if (rc < 0)
+		return rc;
+
+	return 0;
+}
+
+static void edac_remove_sysfs_attributes(struct mem_ctl_info *mci)
+{
+	device_remove_file(&mci->dev, &dev_attr_inject_data_error);
+	device_remove_file(&mci->dev, &dev_attr_inject_data_poison);
+}
+
+static void xddr_setup_row_address_map(struct xddr_edac_priv *priv)
+{
+	u32 regval;
+
+	regval = readl(priv->ddrmc_noc_baseaddr + XDDR_NOC_REG_ADEC5_OFFSET);
+	priv->row_bit[0] = regval & ROW_0_MASK;
+	priv->row_bit[1] = (regval & ROW_1_MASK) >> ROW_1_SHIFT;
+	priv->row_bit[2] = (regval & ROW_2_MASK) >> ROW_2_SHIFT;
+	priv->row_bit[3] = (regval & ROW_3_MASK) >> ROW_3_SHIFT;
+	priv->row_bit[4] = (regval & ROW_4_MASK) >> ROW_4_SHIFT;
+
+	regval = readl(priv->ddrmc_noc_baseaddr + XDDR_NOC_REG_ADEC6_OFFSET);
+	priv->row_bit[5] = regval & ROW_5_MASK;
+	priv->row_bit[6] = (regval & ROW_6_MASK) >> ROW_6_SHIFT;
+	priv->row_bit[7] = (regval & ROW_7_MASK) >> ROW_7_SHIFT;
+	priv->row_bit[8] = (regval & ROW_8_MASK) >> ROW_8_SHIFT;
+	priv->row_bit[9] = (regval & ROW_9_MASK) >> ROW_9_SHIFT;
+
+	regval = readl(priv->ddrmc_noc_baseaddr + XDDR_NOC_REG_ADEC7_OFFSET);
+	priv->row_bit[10] = regval & ROW_10_MASK;
+	priv->row_bit[11] = (regval & ROW_11_MASK) >> ROW_11_SHIFT;
+	priv->row_bit[12] = (regval & ROW_12_MASK) >> ROW_12_SHIFT;
+	priv->row_bit[13] = (regval & ROW_13_MASK) >> ROW_13_SHIFT;
+	priv->row_bit[14] = (regval & ROW_14_MASK) >> ROW_14_SHIFT;
+
+	regval = readl(priv->ddrmc_noc_baseaddr + XDDR_NOC_REG_ADEC8_OFFSET);
+
+	priv->row_bit[15] = regval & ROW_15_MASK;
+	priv->row_bit[16] = (regval & ROW_16_MASK) >> ROW_16_SHIFT;
+	priv->row_bit[17] = (regval & ROW_17_MASK) >> ROW_17_SHIFT;
+}
+
+static void xddr_setup_column_address_map(struct xddr_edac_priv *priv)
+{
+	u32 regval;
+
+	regval = readl(priv->ddrmc_noc_baseaddr + XDDR_NOC_REG_ADEC8_OFFSET);
+	priv->col_bit[0] = (regval & COL_0_MASK) >> COL_0_SHIFT;
+
+	regval = readl(priv->ddrmc_noc_baseaddr + XDDR_NOC_REG_ADEC9_OFFSET);
+	priv->col_bit[1] = (regval & COL_1_MASK);
+	priv->col_bit[2] = (regval & COL_2_MASK) >> COL_2_SHIFT;
+	priv->col_bit[3] = (regval & COL_3_MASK) >> COL_3_SHIFT;
+	priv->col_bit[4] = (regval & COL_4_MASK) >> COL_4_SHIFT;
+	priv->col_bit[5] = (regval & COL_5_MASK) >> COL_5_SHIFT;
+
+	regval = readl(priv->ddrmc_noc_baseaddr + XDDR_NOC_REG_ADEC10_OFFSET);
+	priv->col_bit[6] = (regval & COL_6_MASK);
+	priv->col_bit[7] = (regval & COL_7_MASK) >> COL_7_SHIFT;
+	priv->col_bit[8] = (regval & COL_8_MASK) >> COL_8_SHIFT;
+	priv->col_bit[9] = (regval & COL_9_MASK) >> COL_9_SHIFT;
+}
+
+static void xddr_setup_bank_grp_ch_address_map(struct xddr_edac_priv *priv)
+{
+	u32 regval;
+
+	regval = readl(priv->ddrmc_noc_baseaddr + XDDR_NOC_REG_ADEC10_OFFSET);
+	priv->bank_bit[0] = (regval & BANK_0_MASK) >> BANK_0_SHIFT;
+
+	regval = readl(priv->ddrmc_noc_baseaddr + XDDR_NOC_REG_ADEC11_OFFSET);
+	priv->bank_bit[1] = (regval & BANK_1_MASK);
+	priv->grp_bit[0] = (regval & GRP_0_MASK) >> GRP_0_SHIFT;
+	priv->grp_bit[1] = (regval & GRP_1_MASK) >> GRP_1_SHIFT;
+	priv->ch_bit = (regval & CH_0_MASK) >> CH_0_SHIFT;
+}
+
+static void xddr_setup_rank_lrank_address_map(struct xddr_edac_priv *priv)
+{
+	u32 regval;
+
+	regval = readl(priv->ddrmc_noc_baseaddr + XDDR_NOC_REG_ADEC4_OFFSET);
+	priv->rank_bit[0] = (regval & RANK_0_MASK);
+	priv->rank_bit[1] = (regval & RANK_1_MASK) >> RANK_1_SHIFT;
+	priv->lrank_bit[0] = (regval & LRANK_0_MASK) >> LRANK_0_SHIFT;
+	priv->lrank_bit[1] = (regval & LRANK_1_MASK) >> LRANK_1_SHIFT;
+	priv->lrank_bit[2] = (regval & LRANK_2_MASK) >> LRANK_2_SHIFT;
+}
+
+/**
+ * xddr_setup_address_map - Set Address Map by querying ADDRMAP registers.
+ * @priv:	DDR memory controller private instance data.
+ *
+ * Set Address Map by querying ADDRMAP registers.
+ *
+ * Return: none.
+ */
+static void xddr_setup_address_map(struct xddr_edac_priv *priv)
+{
+	xddr_setup_row_address_map(priv);
+
+	xddr_setup_column_address_map(priv);
+
+	xddr_setup_bank_grp_ch_address_map(priv);
+
+	xddr_setup_rank_lrank_address_map(priv);
+}
+#endif /* CONFIG_EDAC_DEBUG */
+
+/**
+ * xddr_mc_probe - Check controller and bind driver.
+ * @pdev:	platform device.
+ *
+ * Probe a specific controller instance for binding with the driver.
+ *
+ * Return: 0 if the controller instance was successfully bound to the
+ * driver; otherwise, < 0 on error.
+ */
+static int xddr_mc_probe(struct platform_device *pdev)
+{
+	struct edac_mc_layer layers[2];
+	struct xddr_edac_priv *priv;
+	struct mem_ctl_info *mci;
+	void __iomem *ddrmc_baseaddr, *ddrmc_noc_baseaddr;
+	struct resource *res;
+	int rc;
+	u8 num_chans, num_csrows;
+	u32 edac_mc_id, regval;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ddrmc_base");
+	ddrmc_baseaddr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(ddrmc_baseaddr))
+		return PTR_ERR(ddrmc_baseaddr);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+					   "ddrmc_noc_base");
+	ddrmc_noc_baseaddr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(ddrmc_noc_baseaddr))
+		return PTR_ERR(ddrmc_noc_baseaddr);
+
+	if (!xddr_get_ecc_state(ddrmc_baseaddr))
+		return -ENXIO;
+
+	rc = of_property_read_u32(pdev->dev.of_node, "xlnx,mc-id",
+				  &edac_mc_id);
+	if (rc)
+		return rc;
+
+	regval = readl(ddrmc_baseaddr + XDDR_REG_CONFIG0_OFFSET);
+	num_chans = (regval & XDDR_REG_CONFIG0_NUM_CHANS_MASK) >>
+			XDDR_REG_CONFIG0_NUM_CHANS_SHIFT;
+	num_chans++;
+
+	num_csrows = (regval & XDDR_REG_CONFIG0_NUM_RANKS_MASK) >>
+			XDDR_REG_CONFIG0_NUM_RANKS_SHIFT;
+	num_csrows *= 2;
+	if (!num_csrows)
+		num_csrows = 1;
+
+	layers[0].type = EDAC_MC_LAYER_CHIP_SELECT;
+	layers[0].size = num_csrows;
+	layers[0].is_virt_csrow = true;
+	layers[1].type = EDAC_MC_LAYER_CHANNEL;
+	layers[1].size = num_chans;
+	layers[1].is_virt_csrow = false;
+
+	mci = edac_mc_alloc(edac_mc_id, ARRAY_SIZE(layers), layers,
+			    sizeof(struct xddr_edac_priv));
+	if (!mci) {
+		edac_printk(KERN_ERR, EDAC_MC,
+			    "Failed memory allocation for mc instance\n");
+		return -ENOMEM;
+	}
+
+	priv = mci->pvt_info;
+	priv->ddrmc_baseaddr = ddrmc_baseaddr;
+	priv->ddrmc_noc_baseaddr = ddrmc_noc_baseaddr;
+	priv->ce_cnt = 0;
+	priv->ue_cnt = 0;
+
+	xddr_mc_init(mci, pdev);
+
+	rc = xddr_setup_irq(mci, pdev);
+	if (rc)
+		goto free_edac_mc;
+
+	rc = edac_mc_add_mc(mci);
+	if (rc) {
+		edac_printk(KERN_ERR, EDAC_MC,
+			    "Failed to register with EDAC core\n");
+		goto free_edac_mc;
+	}
+
+#ifdef CONFIG_EDAC_DEBUG
+	if (edac_create_sysfs_attributes(mci)) {
+		edac_printk(KERN_ERR, EDAC_MC,
+			    "Failed to create sysfs entries\n");
+		goto free_edac_mc;
+	}
+
+	xddr_setup_address_map(priv);
+#endif
+
+	return rc;
+
+free_edac_mc:
+	edac_mc_free(mci);
+
+	return rc;
+}
+
+/**
+ * xddr_mc_remove - Unbind driver from controller.
+ * @pdev:	Platform device.
+ *
+ * Return: Unconditionally 0
+ */
+static int xddr_mc_remove(struct platform_device *pdev)
+{
+	struct mem_ctl_info *mci = platform_get_drvdata(pdev);
+	struct xddr_edac_priv *priv = mci->pvt_info;
+
+	xddr_disable_intr(priv);
+
+#ifdef CONFIG_EDAC_DEBUG
+	edac_remove_sysfs_attributes(mci);
+#endif
+
+	edac_mc_del_mc(&pdev->dev);
+	edac_mc_free(mci);
+
+	return 0;
+}
+
+static const struct of_device_id xlnx_edac_match[] = {
+	{ .compatible = "xlnx,versal-ddrmc-edac", },
+	{
+		/* end of table */
+	}
+};
+
+MODULE_DEVICE_TABLE(of, xlnx_edac_match);
+
+static struct platform_driver xilinx_ddr_edac_mc_driver = {
+	.driver = {
+		.name = "xilinx-ddrmc-edac",
+		.of_match_table = xlnx_edac_match,
+	},
+	.probe = xddr_mc_probe,
+	.remove = xddr_mc_remove,
+};
+
+module_platform_driver(xilinx_ddr_edac_mc_driver);
+
+MODULE_AUTHOR("Xilinx Inc");
+MODULE_DESCRIPTION("Xilinx DDRMC ECC driver");
+MODULE_LICENSE("GPL");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/edac/zynqmp_ocm_edac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/edac/zynqmp_ocm_edac.c
@@ -0,0 +1,651 @@
+/*
+ * Xilinx ZynqMP OCM ECC Driver
+ * This driver is based on mpc85xx_edac.c drivers
+ *
+ * Copyright (C) 2016 Xilinx, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details
+ */
+
+#include <linux/edac.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+
+#include "edac_module.h"
+
+#define ZYNQMP_OCM_EDAC_MSG_SIZE	256
+
+#define ZYNQMP_OCM_EDAC_STRING	"zynqmp_ocm"
+#define ZYNQMP_OCM_EDAC_MOD_VER	"1"
+
+/* Controller registers */
+#define CTRL_OFST		0x0
+#define OCM_ISR_OFST		0x04
+#define OCM_IMR_OFST		0x08
+#define OCM_IEN_OFST		0x0C
+#define OCM_IDS_OFST		0x10
+
+/* ECC control register */
+#define ECC_CTRL_OFST		0x14
+
+/* Correctable error info registers */
+#define CE_FFA_OFST		0x1C
+#define CE_FFD0_OFST		0x20
+#define CE_FFD1_OFST		0x24
+#define CE_FFD2_OFST		0x28
+#define CE_FFD3_OFST		0x2C
+#define CE_FFE_OFST		0x30
+
+/* Uncorrectable error info registers */
+#define UE_FFA_OFST		0x34
+#define UE_FFD0_OFST		0x38
+#define UE_FFD1_OFST		0x3C
+#define UE_FFD2_OFST		0x40
+#define UE_FFD3_OFST		0x44
+#define UE_FFE_OFST		0x48
+
+/* ECC control register bit field definitions */
+#define ECC_CTRL_CLR_CE_ERR	0x40
+#define ECC_CTRL_CLR_UE_ERR	0x80
+
+/* Fault injection data and count registers */
+#define OCM_FID0_OFST		0x4C
+#define OCM_FID1_OFST		0x50
+#define OCM_FID2_OFST		0x54
+#define OCM_FID3_OFST		0x58
+#define OCM_FIC_OFST		0x74
+
+/* Interrupt masks */
+#define OCM_CEINTR_MASK	0x40
+#define OCM_UEINTR_MASK	0x80
+#define OCM_ECC_ENABLE_MASK	0x1
+#define OCM_FICOUNT_MASK	0x0FFFFFFF
+#define OCM_BASEVAL	0xFFFC0000
+#define EDAC_DEVICE "ZynqMP-OCM"
+#define OCM_CEUE_MASK	0xC0
+
+/**
+ * struct ecc_error_info - ECC error log information
+ * @addr:	Fault generated at this address
+ * @data0:	Generated fault data
+ * @data1:	Generated fault data
+ */
+struct ecc_error_info {
+	u32 addr;
+	u32 data0;
+	u32 data1;
+};
+
+/**
+ * struct zynqmp_ocm_ecc_status - ECC status information to report
+ * @ce_cnt:	Correctable error count
+ * @ue_cnt:	Uncorrectable error count
+ * @ceinfo:	Correctable error log information
+ * @ueinfo:	Uncorrectable error log information
+ */
+struct zynqmp_ocm_ecc_status {
+	u32 ce_cnt;
+	u32 ue_cnt;
+	struct ecc_error_info ceinfo;
+	struct ecc_error_info ueinfo;
+};
+
+/**
+ * struct zynqmp_ocm_edac_priv - DDR memory controller private instance data
+ * @baseaddr:	Base address of the DDR controller
+ * @message:	Buffer for framing the event specific info
+ * @stat:	ECC status information
+ * @p_data:	Pointer to platform data
+ * @ce_cnt:	Correctable Error count
+ * @ue_cnt:	Uncorrectable Error count
+ * @ce_bitpos:	Bit position for Correctable Error
+ * @ue_bitpos0:	First bit position for Uncorrectable Error
+ * @ue_bitpos1:	Second bit position for Uncorrectable Error
+ */
+struct zynqmp_ocm_edac_priv {
+	void __iomem *baseaddr;
+	char message[ZYNQMP_OCM_EDAC_MSG_SIZE];
+	struct zynqmp_ocm_ecc_status stat;
+	const struct zynqmp_ocm_platform_data *p_data;
+	u32 ce_cnt;
+	u32 ue_cnt;
+	u8 ce_bitpos;
+	u8 ue_bitpos0;
+	u8 ue_bitpos1;
+};
+
+/**
+ * zynqmp_ocm_edac_geterror_info - Get the current ecc error info
+ * @base:	Pointer to the base address of the ddr memory controller
+ * @p:		Pointer to the ocm ecc status structure
+ * @mask:	Status register mask value
+ *
+ * Determines there is any ecc error or not
+ *
+ */
+static void zynqmp_ocm_edac_geterror_info(void __iomem *base,
+				    struct zynqmp_ocm_ecc_status *p, int mask)
+{
+	if (mask & OCM_CEINTR_MASK) {
+		p->ce_cnt++;
+		p->ceinfo.data0 = readl(base + CE_FFD0_OFST);
+		p->ceinfo.data1 = readl(base + CE_FFD1_OFST);
+		p->ceinfo.addr = (OCM_BASEVAL | readl(base + CE_FFA_OFST));
+		writel(ECC_CTRL_CLR_CE_ERR, base + OCM_ISR_OFST);
+	} else if (mask & OCM_UEINTR_MASK) {
+		p->ue_cnt++;
+		p->ueinfo.data0 = readl(base + UE_FFD0_OFST);
+		p->ueinfo.data1 = readl(base + UE_FFD1_OFST);
+		p->ueinfo.addr = (OCM_BASEVAL | readl(base + UE_FFA_OFST));
+		writel(ECC_CTRL_CLR_UE_ERR, base + OCM_ISR_OFST);
+	}
+}
+
+/**
+ * zynqmp_ocm_edac_handle_error - Handle controller error types CE and UE
+ * @dci:	Pointer to the edac device controller instance
+ * @p:		Pointer to the ocm ecc status structure
+ *
+ * Handles the controller ECC correctable and un correctable error.
+ */
+static void zynqmp_ocm_edac_handle_error(struct edac_device_ctl_info *dci,
+				    struct zynqmp_ocm_ecc_status *p)
+{
+	struct zynqmp_ocm_edac_priv *priv = dci->pvt_info;
+	struct ecc_error_info *pinf;
+
+	if (p->ce_cnt) {
+		pinf = &p->ceinfo;
+		snprintf(priv->message, ZYNQMP_OCM_EDAC_MSG_SIZE,
+			 "\n\rOCM ECC error type :%s\n\r"
+			 "Addr: [0x%X]\n\rFault Data[31:0]: [0x%X]\n\r"
+			 "Fault Data[63:32]: [0x%X]",
+			 "CE", pinf->addr, pinf->data0, pinf->data1);
+		edac_device_handle_ce(dci, 0, 0, priv->message);
+	}
+
+	if (p->ue_cnt) {
+		pinf = &p->ueinfo;
+		snprintf(priv->message, ZYNQMP_OCM_EDAC_MSG_SIZE,
+			 "\n\rOCM ECC error type :%s\n\r"
+			 "Addr: [0x%X]\n\rFault Data[31:0]: [0x%X]\n\r"
+			 "Fault Data[63:32]: [0x%X]",
+			 "UE", pinf->addr, pinf->data0, pinf->data1);
+		edac_device_handle_ue(dci, 0, 0, priv->message);
+	}
+
+	memset(p, 0, sizeof(*p));
+}
+
+/**
+ * zynqmp_ocm_edac_intr_handler - isr routine
+ * @irq:        irq number
+ * @dev_id:     device id poniter
+ *
+ * This is the Isr routine called by edac core interrupt thread.
+ * Used to check and post ECC errors.
+ *
+ * Return: IRQ_NONE, if interrupt not set or IRQ_HANDLED otherwise
+ */
+static irqreturn_t zynqmp_ocm_edac_intr_handler(int irq, void *dev_id)
+{
+	struct edac_device_ctl_info *dci = dev_id;
+	struct zynqmp_ocm_edac_priv *priv = dci->pvt_info;
+	int regval;
+
+	regval = readl(priv->baseaddr + OCM_ISR_OFST);
+	if (!(regval & OCM_CEUE_MASK))
+		return IRQ_NONE;
+
+	zynqmp_ocm_edac_geterror_info(priv->baseaddr,
+				&priv->stat, regval);
+
+	priv->ce_cnt += priv->stat.ce_cnt;
+	priv->ue_cnt += priv->stat.ue_cnt;
+	zynqmp_ocm_edac_handle_error(dci, &priv->stat);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * zynqmp_ocm_edac_get_eccstate - Return the controller ecc status
+ * @base:	Pointer to the ddr memory controller base address
+ *
+ * Get the ECC enable/disable status for the controller
+ *
+ * Return: ecc status 0/1.
+ */
+static bool zynqmp_ocm_edac_get_eccstate(void __iomem *base)
+{
+	return readl(base + ECC_CTRL_OFST) & OCM_ECC_ENABLE_MASK;
+}
+
+static const struct of_device_id zynqmp_ocm_edac_match[] = {
+	{ .compatible = "xlnx,zynqmp-ocmc-1.0"},
+	{ /* end of table */ }
+};
+
+MODULE_DEVICE_TABLE(of, zynqmp_ocm_edac_match);
+
+/**
+ * zynqmp_ocm_edac_inject_fault_count_show - Shows fault injection count
+ * @dci:        Pointer to the edac device struct
+ * @data:       Pointer to user data
+ *
+ * Shows the fault injection count, once the counter reaches
+ * zero, it injects errors
+ * Return: Number of bytes copied.
+ */
+static ssize_t zynqmp_ocm_edac_inject_fault_count_show(
+		struct edac_device_ctl_info *dci, char *data)
+{
+	struct zynqmp_ocm_edac_priv *priv = dci->pvt_info;
+
+	return sprintf(data, "FIC: 0x%x\n\r",
+			readl(priv->baseaddr + OCM_FIC_OFST));
+}
+
+/**
+ * zynqmp_ocm_edac_inject_fault_count_store - write fi count
+ * @dci:	Pointer to the edac device struct
+ * @data:	Pointer to user data
+ * @count:	read the size bytes from buffer
+ *
+ * Update the fault injection count register, once the counter reaches
+ * zero, it injects errors
+ * Return: Number of bytes copied.
+ */
+static ssize_t zynqmp_ocm_edac_inject_fault_count_store(
+		struct edac_device_ctl_info *dci, const char *data,
+		size_t count)
+{
+	struct zynqmp_ocm_edac_priv *priv = dci->pvt_info;
+	u32 ficount;
+
+	if (!data)
+		return -EFAULT;
+
+	if (kstrtouint(data, 0, &ficount))
+		return -EINVAL;
+
+	ficount &= OCM_FICOUNT_MASK;
+	writel(ficount, priv->baseaddr + OCM_FIC_OFST);
+
+	return count;
+}
+
+/**
+ * zynqmp_ocm_edac_inject_cebitpos_show - Shows CE bit position
+ * @dci:        Pointer to the edac device struct
+ * @data:       Pointer to user data
+ *
+ * Shows the Correctable error bit position,
+ * Return: Number of bytes copied.
+ */
+static ssize_t zynqmp_ocm_edac_inject_cebitpos_show(struct edac_device_ctl_info
+							*dci, char *data)
+{
+	struct zynqmp_ocm_edac_priv *priv = dci->pvt_info;
+
+	if (priv->ce_bitpos <= 31)
+		return sprintf(data, "Fault Injection Data Reg: [0x%x]\n\r",
+			((readl(priv->baseaddr + OCM_FID0_OFST))));
+
+	return sprintf(data, "Fault Injection Data Reg: [0x%x]\n\r",
+			((readl(priv->baseaddr + OCM_FID1_OFST))));
+}
+
+/**
+ * zynqmp_ocm_edac_inject_cebitpos_store - Set CE bit postion
+ * @dci:	Pointer to the edac device struct
+ * @data:	Pointer to user data
+ * @count:	read the size bytes from buffer
+ *
+ * Set any one bit to inject CE error
+ * Return: Number of bytes copied.
+ */
+static ssize_t zynqmp_ocm_edac_inject_cebitpos_store(
+		struct edac_device_ctl_info *dci, const char *data,
+		size_t count)
+{
+	struct zynqmp_ocm_edac_priv *priv = dci->pvt_info;
+
+	if (!data)
+		return -EFAULT;
+
+	if (kstrtou8(data, 0, &priv->ce_bitpos))
+		return -EINVAL;
+
+	if (priv->ce_bitpos <= 31) {
+		writel(1 << priv->ce_bitpos, priv->baseaddr + OCM_FID0_OFST);
+		writel(0, priv->baseaddr + OCM_FID1_OFST);
+	} else if (priv->ce_bitpos >= 32 && priv->ce_bitpos <= 63) {
+		writel(1 << (priv->ce_bitpos - 32),
+				priv->baseaddr + OCM_FID1_OFST);
+		writel(0, priv->baseaddr + OCM_FID0_OFST);
+	} else {
+		edac_printk(KERN_ERR, EDAC_DEVICE,
+			"Bit number > 64 is not valid\n");
+	}
+
+	return count;
+}
+
+/**
+ * zynqmp_ocm_edac_inject_uebitpos0_show - Shows UE bit postion0
+ * @dci:        Pointer to the edac device struct
+ * @data:       Pointer to user data
+ *
+ * Shows the one of bit position for UE error
+ * Return: Number of bytes copied.
+ */
+static ssize_t zynqmp_ocm_edac_inject_uebitpos0_show(
+		struct edac_device_ctl_info *dci, char *data)
+{
+	struct zynqmp_ocm_edac_priv *priv = dci->pvt_info;
+
+	if (priv->ue_bitpos0 <= 31)
+		return sprintf(data, "Fault Injection Data Reg: [0x%x]\n\r",
+			((readl(priv->baseaddr + OCM_FID0_OFST))));
+
+	return sprintf(data, "Fault Injection Data Reg: [0x%x]\n\r",
+			((readl(priv->baseaddr + OCM_FID1_OFST))));
+}
+
+/**
+ * zynqmp_ocm_edac_inject_uebitpos0_store - set UE bit position0
+ * @dci:	Pointer to the edac device struct
+ * @data:	Pointer to user data
+ * @count:	read the size bytes from buffer
+ *
+ * Set the first bit postion for UE Error generation,we need to configure
+ * any two bitpositions to inject UE Error
+ * Return: Number of bytes copied.
+ */
+static ssize_t zynqmp_ocm_edac_inject_uebitpos0_store(
+		struct edac_device_ctl_info *dci,
+		const char *data, size_t count)
+{
+	struct zynqmp_ocm_edac_priv *priv = dci->pvt_info;
+
+	if (!data)
+		return -EFAULT;
+
+	if (kstrtou8(data, 0, &priv->ue_bitpos0))
+		return -EINVAL;
+
+	if (priv->ue_bitpos0 <= 31)
+		writel(1 << priv->ue_bitpos0, priv->baseaddr + OCM_FID0_OFST);
+	else if (priv->ue_bitpos0 >= 32 && priv->ue_bitpos0 <= 63)
+		writel(1 << (priv->ue_bitpos0 - 32),
+				priv->baseaddr + OCM_FID1_OFST);
+	else
+		edac_printk(KERN_ERR, EDAC_DEVICE,
+			"Bit position > 64 is not valid\n");
+	edac_printk(KERN_INFO, EDAC_DEVICE,
+			"Set another bit position for UE\n");
+	return count;
+}
+
+/**
+ * zynqmp_ocm_edac_inject_uebitpos1_show - Shows UE bit postion1
+ * @dci:        Pointer to the edac device struct
+ * @data:       Pointer to user data
+ *
+ * Shows the second bit postion configured for UE error
+ * Return: Number of bytes copied.
+ */
+static ssize_t zynqmp_ocm_edac_inject_uebitpos1_show(
+		struct edac_device_ctl_info *dci, char *data)
+{
+	struct zynqmp_ocm_edac_priv *priv = dci->pvt_info;
+
+	if (priv->ue_bitpos1 <= 31)
+		return sprintf(data, "Fault Injection Data Reg: [0x%x]\n\r",
+			((readl(priv->baseaddr + OCM_FID0_OFST))));
+
+	return sprintf(data, "Fault Injection Data Reg: [0x%x]\n\r",
+			((readl(priv->baseaddr + OCM_FID1_OFST))));
+
+}
+
+/**
+ * zynqmp_ocm_edac_inject_uebitposition1_store - Set UE second bit postion
+ * @dci:	Pointer to the edac device struct
+ * @data:	Pointer to user data
+ * @count:	read the size bytes from buffer
+ *
+ * Set the second bit postion for UE Error generation,we need to configure
+ * any two bitpositions to inject UE Error
+ * Return: Number of bytes copied.
+ */
+static ssize_t zynqmp_ocm_edac_inject_uebitpos1_store(
+		struct edac_device_ctl_info *dci, const char *data,
+		size_t count)
+{
+	struct zynqmp_ocm_edac_priv *priv = dci->pvt_info;
+	u32 mask;
+
+	if (!data)
+		return -EFAULT;
+
+	if (kstrtou8(data, 0, &priv->ue_bitpos1))
+		return -EINVAL;
+
+	if (priv->ue_bitpos0 == priv->ue_bitpos1) {
+		edac_printk(KERN_ERR, EDAC_DEVICE,
+				"Bit positions should not be equal\n");
+		return -EINVAL;
+	}
+
+	/* If both bit postions are referring to 32 bit data, then configure
+	 * only FID0 register or if it is 64 bit data, then configure only
+	 * FID1 register.
+	 */
+	if (priv->ue_bitpos0 <= 31 &&
+	    priv->ue_bitpos1 <= 31) {
+		mask = (1 << priv->ue_bitpos0);
+		mask |= (1 << priv->ue_bitpos1);
+		writel(mask, priv->baseaddr + OCM_FID0_OFST);
+		writel(0, priv->baseaddr + OCM_FID1_OFST);
+	} else if ((priv->ue_bitpos0 >= 32 && priv->ue_bitpos0 <= 63) &&
+			(priv->ue_bitpos1 >= 32 && priv->ue_bitpos1 <= 63)) {
+		mask = (1 << (priv->ue_bitpos0 - 32));
+		mask |= (1 << (priv->ue_bitpos1 - 32));
+		writel(mask, priv->baseaddr + OCM_FID1_OFST);
+		writel(0, priv->baseaddr + OCM_FID0_OFST);
+	}
+
+	/* If one bit position is referring a bit in 32 bit data and other in
+	 * 64 bit data, just configure FID0/FID1 based on uebitpos1.
+	 */
+	if ((priv->ue_bitpos0 <= 31) &&
+	    (priv->ue_bitpos1 >= 32 && priv->ue_bitpos1 <= 63)) {
+		writel(1 << (priv->ue_bitpos1 - 32),
+				priv->baseaddr + OCM_FID1_OFST);
+	} else if ((priv->ue_bitpos0 >= 32 && priv->ue_bitpos0 <= 63) &&
+			(priv->ue_bitpos1 <= 31)) {
+		writel(1 << priv->ue_bitpos1,
+				priv->baseaddr + OCM_FID0_OFST);
+	} else {
+		edac_printk(KERN_ERR, EDAC_DEVICE,
+			"Bit position > 64 is not valid, Valid bits:[63:0]\n");
+	}
+
+	edac_printk(KERN_INFO, EDAC_DEVICE,
+			"UE at Bit Position0: %d Bit Position1: %d\n",
+			priv->ue_bitpos0, priv->ue_bitpos1);
+	return count;
+}
+
+static struct edac_dev_sysfs_attribute zynqmp_ocm_edac_sysfs_attributes[] = {
+	{
+		.attr = {
+			.name = "inject_cebitpos",
+			.mode = (0644)
+		},
+		.show = zynqmp_ocm_edac_inject_cebitpos_show,
+		.store = zynqmp_ocm_edac_inject_cebitpos_store},
+	{
+		.attr = {
+			.name = "inject_uebitpos0",
+			.mode = (0644)
+		},
+		.show = zynqmp_ocm_edac_inject_uebitpos0_show,
+		.store = zynqmp_ocm_edac_inject_uebitpos0_store},
+	{
+		.attr = {
+			.name = "inject_uebitpos1",
+			.mode = (0644)
+		},
+		.show = zynqmp_ocm_edac_inject_uebitpos1_show,
+		.store = zynqmp_ocm_edac_inject_uebitpos1_store},
+	{
+		.attr = {
+			.name = "inject_fault_count",
+			.mode = (0644)
+		},
+		.show = zynqmp_ocm_edac_inject_fault_count_show,
+		.store = zynqmp_ocm_edac_inject_fault_count_store},
+	/* End of list */
+	{
+		.attr = {.name = NULL}
+	}
+};
+
+/**
+ * zynqmp_set_ocm_edac_sysfs_attributes - create sysfs attributes
+ * @edac_dev:	Pointer to the edac device struct
+ *
+ * Creates sysfs entires for error injection
+ * Return: None.
+ */
+static void zynqmp_set_ocm_edac_sysfs_attributes(struct edac_device_ctl_info
+						*edac_dev)
+{
+	edac_dev->sysfs_attributes = zynqmp_ocm_edac_sysfs_attributes;
+}
+
+/**
+ * zynqmp_ocm_edac_probe - Check controller and bind driver
+ * @pdev:	Pointer to the platform_device struct
+ *
+ * Probes a specific controller instance for binding with the driver.
+ *
+ * Return: 0 if the controller instance was successfully bound to the
+ * driver; otherwise, < 0 on error.
+ */
+static int zynqmp_ocm_edac_probe(struct platform_device *pdev)
+{
+	struct edac_device_ctl_info *dci;
+	struct zynqmp_ocm_edac_priv *priv;
+	int irq, status;
+	struct resource *res;
+	void __iomem *baseaddr;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	baseaddr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(baseaddr))
+		return PTR_ERR(baseaddr);
+
+	if (!zynqmp_ocm_edac_get_eccstate(baseaddr)) {
+		edac_printk(KERN_INFO, EDAC_DEVICE,
+				"ECC not enabled - Disabling EDAC driver\n");
+		return -ENXIO;
+	}
+
+	dci = edac_device_alloc_ctl_info(sizeof(*priv), ZYNQMP_OCM_EDAC_STRING,
+			1, ZYNQMP_OCM_EDAC_STRING, 1, 0, NULL, 0,
+			edac_device_alloc_index());
+	if (!dci) {
+		edac_printk(KERN_ERR, EDAC_DEVICE,
+				"Unable to allocate EDAC device\n");
+		return -ENOMEM;
+	}
+
+	priv = dci->pvt_info;
+	platform_set_drvdata(pdev, dci);
+	dci->dev = &pdev->dev;
+	priv->baseaddr = baseaddr;
+	dci->mod_name = pdev->dev.driver->name;
+	dci->ctl_name = ZYNQMP_OCM_EDAC_STRING;
+	dci->dev_name = dev_name(&pdev->dev);
+
+	zynqmp_set_ocm_edac_sysfs_attributes(dci);
+	if (edac_device_add_device(dci))
+		goto free_dev_ctl;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		edac_printk(KERN_ERR, EDAC_DEVICE,
+				"No irq %d in DT\n", irq);
+		return irq;
+	}
+
+	status = devm_request_irq(&pdev->dev, irq,
+		zynqmp_ocm_edac_intr_handler,
+		0, dev_name(&pdev->dev), dci);
+	if (status < 0) {
+		edac_printk(KERN_ERR, EDAC_DEVICE, "Failed to request Irq\n");
+		goto free_edac_dev;
+	}
+
+	writel(OCM_CEUE_MASK, priv->baseaddr + OCM_IEN_OFST);
+
+	return 0;
+
+free_edac_dev:
+	edac_device_del_device(&pdev->dev);
+free_dev_ctl:
+	edac_device_free_ctl_info(dci);
+
+	return -1;
+}
+
+/**
+ * zynqmp_ocm_edac_remove - Unbind driver from controller
+ * @pdev:	Pointer to the platform_device struct
+ *
+ * Return: Unconditionally 0
+ */
+static int zynqmp_ocm_edac_remove(struct platform_device *pdev)
+{
+	struct edac_device_ctl_info *dci = platform_get_drvdata(pdev);
+	struct zynqmp_ocm_edac_priv *priv = dci->pvt_info;
+
+	writel(OCM_CEUE_MASK, priv->baseaddr + OCM_IDS_OFST);
+	edac_device_del_device(&pdev->dev);
+	edac_device_free_ctl_info(dci);
+
+	return 0;
+}
+
+static struct platform_driver zynqmp_ocm_edac_driver = {
+	.driver = {
+		   .name = "zynqmp-ocm-edac",
+		   .of_match_table = zynqmp_ocm_edac_match,
+		   },
+	.probe = zynqmp_ocm_edac_probe,
+	.remove = zynqmp_ocm_edac_remove,
+};
+
+module_platform_driver(zynqmp_ocm_edac_driver);
+
+MODULE_AUTHOR("Xilinx Inc");
+MODULE_DESCRIPTION("ZynqMP OCM ECC driver");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/extcon/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/extcon/Kconfig
@@ -121,7 +121,8 @@
 
 config EXTCON_MAX8997
 	tristate "Maxim MAX8997 EXTCON Support"
-	depends on MFD_MAX8997 && IRQ_DOMAIN
+	depends on MFD_MAX8997
+	select IRQ_DOMAIN
 	help
 	  If you say yes here you get support for the MUIC device of
 	  Maxim MAX8997 PMIC. The MAX8997 MUIC is a USB port accessory
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/extcon/extcon-adc-jack.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/extcon/extcon-adc-jack.c
@@ -124,7 +124,7 @@
 	for (i = 0; data->adc_conditions[i].id != EXTCON_NONE; i++);
 	data->num_conditions = i;
 
-	data->chan = iio_channel_get(&pdev->dev, pdata->consumer_channel);
+	data->chan = devm_iio_channel_get(&pdev->dev, pdata->consumer_channel);
 	if (IS_ERR(data->chan))
 		return PTR_ERR(data->chan);
 
@@ -164,7 +164,6 @@
 
 	free_irq(data->irq, data);
 	cancel_work_sync(&data->handler.work);
-	iio_channel_release(data->chan);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/extcon/extcon-arizona.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/extcon/extcon-arizona.c
@@ -597,7 +597,7 @@
 	struct arizona *arizona = info->arizona;
 	int id_gpio = arizona->pdata.hpdet_id_gpio;
 	unsigned int report = EXTCON_JACK_HEADPHONE;
-	int ret, reading;
+	int ret, reading, state;
 	bool mic = false;
 
 	mutex_lock(&info->lock);
@@ -610,12 +610,11 @@
 	}
 
 	/* If the cable was removed while measuring ignore the result */
-	ret = extcon_get_state(info->edev, EXTCON_MECHANICAL);
-	if (ret < 0) {
-		dev_err(arizona->dev, "Failed to check cable state: %d\n",
-			ret);
+	state = extcon_get_state(info->edev, EXTCON_MECHANICAL);
+	if (state < 0) {
+		dev_err(arizona->dev, "Failed to check cable state: %d\n", state);
 		goto out;
-	} else if (!ret) {
+	} else if (!state) {
 		dev_dbg(arizona->dev, "Ignoring HPDET for removed cable\n");
 		goto done;
 	}
@@ -668,7 +667,7 @@
 			   ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
 
 	/* If we have a mic then reenable MICDET */
-	if (mic || info->mic)
+	if (state && (mic || info->mic))
 		arizona_start_mic(info);
 
 	if (info->hpdet_active) {
@@ -676,7 +675,9 @@
 		info->hpdet_active = false;
 	}
 
-	info->hpdet_done = true;
+	/* Do not set hp_det done when the cable has been unplugged */
+	if (state)
+		info->hpdet_done = true;
 
 out:
 	mutex_unlock(&info->lock);
@@ -1724,25 +1725,6 @@
 	bool change;
 	int ret;
 
-	ret = regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1,
-				       ARIZONA_MICD_ENA, 0,
-				       &change);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "Failed to disable micd on remove: %d\n",
-			ret);
-	} else if (change) {
-		regulator_disable(info->micvdd);
-		pm_runtime_put(info->dev);
-	}
-
-	gpiod_put(info->micd_pol_gpio);
-
-	pm_runtime_disable(&pdev->dev);
-
-	regmap_update_bits(arizona->regmap,
-			   ARIZONA_MICD_CLAMP_CONTROL,
-			   ARIZONA_MICD_CLAMP_MODE_MASK, 0);
-
 	if (info->micd_clamp) {
 		jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE;
 		jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL;
@@ -1758,10 +1740,31 @@
 	arizona_free_irq(arizona, jack_irq_rise, info);
 	arizona_free_irq(arizona, jack_irq_fall, info);
 	cancel_delayed_work_sync(&info->hpdet_work);
+	cancel_delayed_work_sync(&info->micd_detect_work);
+	cancel_delayed_work_sync(&info->micd_timeout_work);
+
+	ret = regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1,
+				       ARIZONA_MICD_ENA, 0,
+				       &change);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Failed to disable micd on remove: %d\n",
+			ret);
+	} else if (change) {
+		regulator_disable(info->micvdd);
+		pm_runtime_put(info->dev);
+	}
+
+	regmap_update_bits(arizona->regmap,
+			   ARIZONA_MICD_CLAMP_CONTROL,
+			   ARIZONA_MICD_CLAMP_MODE_MASK, 0);
 	regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,
 			   ARIZONA_JD1_ENA, 0);
 	arizona_clk32k_disable(arizona);
 
+	gpiod_put(info->micd_pol_gpio);
+
+	pm_runtime_disable(&pdev->dev);
+
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/extcon/extcon-axp288.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/extcon/extcon-axp288.c
@@ -423,9 +423,40 @@
 	/* Start charger cable type detection */
 	axp288_extcon_enable(info);
 
+	device_init_wakeup(dev, true);
+	platform_set_drvdata(pdev, info);
+
+	return 0;
+}
+
+static int __maybe_unused axp288_extcon_suspend(struct device *dev)
+{
+	struct axp288_extcon_info *info = dev_get_drvdata(dev);
+
+	if (device_may_wakeup(dev))
+		enable_irq_wake(info->irq[VBUS_RISING_IRQ]);
+
 	return 0;
 }
 
+static int __maybe_unused axp288_extcon_resume(struct device *dev)
+{
+	struct axp288_extcon_info *info = dev_get_drvdata(dev);
+
+	/*
+	 * Wakeup when a charger is connected to do charger-type
+	 * connection and generate an extcon event which makes the
+	 * axp288 charger driver set the input current limit.
+	 */
+	if (device_may_wakeup(dev))
+		disable_irq_wake(info->irq[VBUS_RISING_IRQ]);
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(axp288_extcon_pm_ops, axp288_extcon_suspend,
+			 axp288_extcon_resume);
+
 static const struct platform_device_id axp288_extcon_table[] = {
 	{ .name = "axp288_extcon" },
 	{},
@@ -437,6 +468,7 @@
 	.id_table = axp288_extcon_table,
 	.driver = {
 		.name = "axp288_extcon",
+		.pm = &axp288_extcon_pm_ops,
 	},
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/extcon/extcon-intel-cht-wc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/extcon/extcon-intel-cht-wc.c
@@ -338,6 +338,7 @@
 	struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
 	struct cht_wc_extcon_data *ext;
 	unsigned long mask = ~(CHT_WC_PWRSRC_VBUS | CHT_WC_PWRSRC_USBID_MASK);
+	int pwrsrc_sts, id;
 	int irq, ret;
 
 	irq = platform_get_irq(pdev, 0);
@@ -387,8 +388,19 @@
 		goto disable_sw_control;
 	}
 
-	/* Route D+ and D- to PMIC for initial charger detection */
-	cht_wc_extcon_set_phymux(ext, MUX_SEL_PMIC);
+	ret = regmap_read(ext->regmap, CHT_WC_PWRSRC_STS, &pwrsrc_sts);
+	if (ret) {
+		dev_err(ext->dev, "Error reading pwrsrc status: %d\n", ret);
+		goto disable_sw_control;
+	}
+
+	/*
+	 * If no USB host or device connected, route D+ and D- to PMIC for
+	 * initial charger detection
+	 */
+	id = cht_wc_extcon_get_id(ext, pwrsrc_sts);
+	if (id != INTEL_USB_ID_GND)
+		cht_wc_extcon_set_phymux(ext, MUX_SEL_PMIC);
 
 	/* Get initial state */
 	cht_wc_extcon_pwrsrc_event(ext);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/extcon/extcon-intel-mrfld.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/extcon/extcon-intel-mrfld.c
@@ -197,6 +197,7 @@
 	struct intel_soc_pmic *pmic = dev_get_drvdata(dev->parent);
 	struct regmap *regmap = pmic->regmap;
 	struct mrfld_extcon_data *data;
+	unsigned int status;
 	unsigned int id;
 	int irq, ret;
 
@@ -244,6 +245,14 @@
 	/* Get initial state */
 	mrfld_extcon_role_detect(data);
 
+	/*
+	 * Cached status value is used for cable detection, see comments
+	 * in mrfld_extcon_cable_detect(), we need to sync cached value
+	 * with a real state of the hardware.
+	 */
+	regmap_read(regmap, BCOVE_SCHGRIRQ1, &status);
+	data->status = status;
+
 	mrfld_extcon_clear(data, BCOVE_MIRQLVL1, BCOVE_LVL1_CHGR);
 	mrfld_extcon_clear(data, BCOVE_MCHGRIRQ1, BCOVE_CHGRIRQ_ALL);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/extcon/extcon-max77693.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/extcon/extcon-max77693.c
@@ -1277,4 +1277,4 @@
 MODULE_DESCRIPTION("Maxim MAX77693 Extcon driver");
 MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:extcon-max77693");
+MODULE_ALIAS("platform:max77693-muic");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/extcon/extcon-max8997.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/extcon/extcon-max8997.c
@@ -729,7 +729,7 @@
 				2, info->status);
 	if (ret) {
 		dev_err(info->dev, "failed to read MUIC register\n");
-		return ret;
+		goto err_irq;
 	}
 	cable_type = max8997_muic_get_cable_type(info,
 					   MAX8997_CABLE_GROUP_ADC, &attached);
@@ -784,3 +784,4 @@
 MODULE_DESCRIPTION("Maxim MAX8997 Extcon driver");
 MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:max8997-muic");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/extcon/extcon-ptn5150.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/extcon/extcon-ptn5150.c
@@ -127,7 +127,7 @@
 			case PTN5150_DFP_ATTACHED:
 				extcon_set_state_sync(info->edev,
 						EXTCON_USB_HOST, false);
-				gpiod_set_value(info->vbus_gpiod, 0);
+				gpiod_set_value_cansleep(info->vbus_gpiod, 0);
 				extcon_set_state_sync(info->edev, EXTCON_USB,
 						true);
 				break;
@@ -138,9 +138,9 @@
 					PTN5150_REG_CC_VBUS_DETECTION_MASK) >>
 					PTN5150_REG_CC_VBUS_DETECTION_SHIFT);
 				if (vbus)
-					gpiod_set_value(info->vbus_gpiod, 0);
+					gpiod_set_value_cansleep(info->vbus_gpiod, 0);
 				else
-					gpiod_set_value(info->vbus_gpiod, 1);
+					gpiod_set_value_cansleep(info->vbus_gpiod, 1);
 
 				extcon_set_state_sync(info->edev,
 						EXTCON_USB_HOST, true);
@@ -156,7 +156,7 @@
 					EXTCON_USB_HOST, false);
 			extcon_set_state_sync(info->edev,
 					EXTCON_USB, false);
-			gpiod_set_value(info->vbus_gpiod, 0);
+			gpiod_set_value_cansleep(info->vbus_gpiod, 0);
 		}
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/extcon/extcon-sm5502.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/extcon/extcon-sm5502.c
@@ -65,6 +65,10 @@
 /* Default value of SM5502 register to bring up MUIC device. */
 static struct reg_data sm5502_reg_data[] = {
 	{
+		.reg = SM5502_REG_RESET,
+		.val = SM5502_REG_RESET_MASK,
+		.invert = true,
+	}, {
 		.reg = SM5502_REG_CONTROL,
 		.val = SM5502_REG_CONTROL_MASK_INT_MASK,
 		.invert = false,
@@ -84,7 +88,6 @@
 			| SM5502_REG_INTM2_MHL_MASK,
 		.invert = true,
 	},
-	{ }
 };
 
 /* List of detectable cables */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/extcon/extcon-sm5502.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/extcon/extcon-sm5502.h
@@ -237,6 +237,8 @@
 #define DM_DP_SWITCH_UART			((DM_DP_CON_SWITCH_UART <<SM5502_REG_MANUAL_SW1_DP_SHIFT) \
 						| (DM_DP_CON_SWITCH_UART <<SM5502_REG_MANUAL_SW1_DM_SHIFT))
 
+#define SM5502_REG_RESET_MASK			(0x1)
+
 /* SM5502 Interrupts */
 enum sm5502_irq {
 	/* INT1 */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/extcon/extcon.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/extcon/extcon.c
@@ -196,6 +196,14 @@
  * @attr_name:		"name" sysfs entry
  * @attr_state:		"state" sysfs entry
  * @attrs:		the array pointing to attr_name and attr_state for attr_g
+ * @usb_propval:	the array of USB connector properties
+ * @chg_propval:	the array of charger connector properties
+ * @jack_propval:	the array of jack connector properties
+ * @disp_propval:	the array of display connector properties
+ * @usb_bits:		the bit array of the USB connector property capabilities
+ * @chg_bits:		the bit array of the charger connector property capabilities
+ * @jack_bits:		the bit array of the jack connector property capabilities
+ * @disp_bits:		the bit array of the display connector property capabilities
  */
 struct extcon_cable {
 	struct extcon_dev *edev;
@@ -1230,18 +1238,14 @@
 		edev->dev.type = &edev->extcon_dev_type;
 	}
 
-	ret = device_register(&edev->dev);
-	if (ret) {
-		put_device(&edev->dev);
-		goto err_dev;
-	}
-
 	spin_lock_init(&edev->lock);
-	edev->nh = devm_kcalloc(&edev->dev, edev->max_supported,
-				sizeof(*edev->nh), GFP_KERNEL);
-	if (!edev->nh) {
-		ret = -ENOMEM;
-		goto err_dev;
+	if (edev->max_supported) {
+		edev->nh = kcalloc(edev->max_supported, sizeof(*edev->nh),
+				GFP_KERNEL);
+		if (!edev->nh) {
+			ret = -ENOMEM;
+			goto err_alloc_nh;
+		}
 	}
 
 	for (index = 0; index < edev->max_supported; index++)
@@ -1252,6 +1256,12 @@
 	dev_set_drvdata(&edev->dev, edev);
 	edev->state = 0;
 
+	ret = device_register(&edev->dev);
+	if (ret) {
+		put_device(&edev->dev);
+		goto err_dev;
+	}
+
 	mutex_lock(&extcon_dev_list_lock);
 	list_add(&edev->entry, &extcon_dev_list);
 	mutex_unlock(&extcon_dev_list_lock);
@@ -1260,6 +1270,9 @@
 
 err_dev:
 	if (edev->max_supported)
+		kfree(edev->nh);
+err_alloc_nh:
+	if (edev->max_supported)
 		kfree(edev->extcon_dev_type.groups);
 err_alloc_groups:
 	if (edev->max_supported && edev->mutually_exclusive) {
@@ -1319,6 +1332,7 @@
 	if (edev->max_supported) {
 		kfree(edev->extcon_dev_type.groups);
 		kfree(edev->cables);
+		kfree(edev->nh);
 	}
 
 	put_device(&edev->dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firewire/core-card.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firewire/core-card.c
@@ -429,7 +429,23 @@
 	 */
 	card->bm_generation = generation;
 
-	if (root_device == NULL) {
+	if (card->gap_count == 0) {
+		/*
+		 * If self IDs have inconsistent gap counts, do a
+		 * bus reset ASAP. The config rom read might never
+		 * complete, so don't wait for it. However, still
+		 * send a PHY configuration packet prior to the
+		 * bus reset. The PHY configuration packet might
+		 * fail, but 1394-2008 8.4.5.2 explicitly permits
+		 * it in this case, so it should be safe to try.
+		 */
+		new_root_id = local_id;
+		/*
+		 * We must always send a bus reset if the gap count
+		 * is inconsistent, so bypass the 5-reset limit.
+		 */
+		card->bm_retries = 0;
+	} else if (root_device == NULL) {
 		/*
 		 * Either link_on is false, or we failed to read the
 		 * config rom.  In either case, pick another root.
@@ -484,7 +500,19 @@
 		fw_notice(card, "phy config: new root=%x, gap_count=%d\n",
 			  new_root_id, gap_count);
 		fw_send_phy_config(card, new_root_id, generation, gap_count);
-		reset_bus(card, true);
+		/*
+		 * Where possible, use a short bus reset to minimize
+		 * disruption to isochronous transfers. But in the event
+		 * of a gap count inconsistency, use a long bus reset.
+		 *
+		 * As noted in 1394a 8.4.6.2, nodes on a mixed 1394/1394a bus
+		 * may set different gap counts after a bus reset. On a mixed
+		 * 1394/1394a bus, a short bus reset can get doubled. Some
+		 * nodes may treat the double reset as one bus reset and others
+		 * may treat it as two, causing a gap count inconsistency
+		 * again. Using a long bus reset prevents this.
+		 */
+		reset_bus(card, card->gap_count != 0);
 		/* Will allocate broadcast channel after the reset. */
 		goto out;
 	}
@@ -668,6 +696,7 @@
 void fw_core_remove_card(struct fw_card *card)
 {
 	struct fw_card_driver dummy_driver = dummy_driver_template;
+	unsigned long flags;
 
 	card->driver->update_phy_reg(card, 4,
 				     PHY_LINK_ACTIVE | PHY_CONTENDER, 0);
@@ -682,7 +711,9 @@
 	dummy_driver.stop_iso		= card->driver->stop_iso;
 	card->driver = &dummy_driver;
 
+	spin_lock_irqsave(&card->lock, flags);
 	fw_destroy_nodes(card);
+	spin_unlock_irqrestore(&card->lock, flags);
 
 	/* Wait for all users, especially device workqueue jobs, to finish. */
 	fw_card_put(card);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firewire/core-cdev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firewire/core-cdev.c
@@ -818,8 +818,10 @@
 
 	r = container_of(resource, struct inbound_transaction_resource,
 			 resource);
-	if (is_fcp_request(r->request))
+	if (is_fcp_request(r->request)) {
+		kfree(r->data);
 		goto out;
+	}
 
 	if (a->length != fw_get_response_length(r->request)) {
 		ret = -EINVAL;
@@ -1482,6 +1484,7 @@
 {
 	struct outbound_phy_packet_event *e =
 		container_of(packet, struct outbound_phy_packet_event, p);
+	struct client *e_client;
 
 	switch (status) {
 	/* expected: */
@@ -1498,9 +1501,10 @@
 	}
 	e->phy_packet.data[0] = packet->timestamp;
 
+	e_client = e->client;
 	queue_event(e->client, &e->event, &e->phy_packet,
 		    sizeof(e->phy_packet) + e->phy_packet.length, NULL, 0);
-	client_put(e->client);
+	client_put(e_client);
 }
 
 static int ioctl_send_phy_packet(struct client *client, union ioctl_arg *arg)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firewire/core-device.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firewire/core-device.c
@@ -100,10 +100,9 @@
  * @buf:	where to put the string
  * @size:	size of @buf, in bytes
  *
- * The string is taken from a minimal ASCII text descriptor leaf after
- * the immediate entry with @key.  The string is zero-terminated.
- * An overlong string is silently truncated such that it and the
- * zero byte fit into @size.
+ * The string is taken from a minimal ASCII text descriptor leaf just after the entry with the
+ * @key. The string is zero-terminated. An overlong string is silently truncated such that it
+ * and the zero byte fit into @size.
  *
  * Returns strlen(buf) or a negative error code.
  */
@@ -719,14 +718,11 @@
 					fw_unit_attributes,
 					&unit->attribute_group);
 
-		if (device_register(&unit->device) < 0)
-			goto skip_unit;
-
 		fw_device_get(device);
-		continue;
-
-	skip_unit:
-		kfree(unit);
+		if (device_register(&unit->device) < 0) {
+			put_device(&unit->device);
+			continue;
+		}
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firewire/core-topology.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firewire/core-topology.c
@@ -374,16 +374,13 @@
 	card->bm_retries = 0;
 }
 
+/* Must be called with card->lock held */
 void fw_destroy_nodes(struct fw_card *card)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->lock, flags);
 	card->color++;
 	if (card->local_node != NULL)
 		for_each_fw_node(card, card->local_node, report_lost_node);
 	card->local_node = NULL;
-	spin_unlock_irqrestore(&card->lock, flags);
 }
 
 static void move_tree(struct fw_node *node0, struct fw_node *node1, int port)
@@ -509,6 +506,8 @@
 	struct fw_node *local_node;
 	unsigned long flags;
 
+	spin_lock_irqsave(&card->lock, flags);
+
 	/*
 	 * If the selfID buffer is not the immediate successor of the
 	 * previously processed one, we cannot reliably compare the
@@ -520,8 +519,6 @@
 		card->bm_retries = 0;
 	}
 
-	spin_lock_irqsave(&card->lock, flags);
-
 	card->broadcast_channel_allocated = card->broadcast_channel_auto_allocated;
 	card->node_id = node_id;
 	/*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firewire/core-transaction.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firewire/core-transaction.c
@@ -73,24 +73,25 @@
 static int close_transaction(struct fw_transaction *transaction,
 			     struct fw_card *card, int rcode)
 {
-	struct fw_transaction *t;
+	struct fw_transaction *t = NULL, *iter;
 	unsigned long flags;
 
 	spin_lock_irqsave(&card->lock, flags);
-	list_for_each_entry(t, &card->transaction_list, link) {
-		if (t == transaction) {
-			if (!try_cancel_split_timeout(t)) {
+	list_for_each_entry(iter, &card->transaction_list, link) {
+		if (iter == transaction) {
+			if (!try_cancel_split_timeout(iter)) {
 				spin_unlock_irqrestore(&card->lock, flags);
 				goto timed_out;
 			}
-			list_del_init(&t->link);
-			card->tlabel_mask &= ~(1ULL << t->tlabel);
+			list_del_init(&iter->link);
+			card->tlabel_mask &= ~(1ULL << iter->tlabel);
+			t = iter;
 			break;
 		}
 	}
 	spin_unlock_irqrestore(&card->lock, flags);
 
-	if (&t->link != &card->transaction_list) {
+	if (t) {
 		t->callback(card, rcode, NULL, 0, t->callback_data);
 		return 0;
 	}
@@ -935,7 +936,7 @@
 
 void fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
 {
-	struct fw_transaction *t;
+	struct fw_transaction *t = NULL, *iter;
 	unsigned long flags;
 	u32 *data;
 	size_t data_length;
@@ -947,20 +948,21 @@
 	rcode	= HEADER_GET_RCODE(p->header[1]);
 
 	spin_lock_irqsave(&card->lock, flags);
-	list_for_each_entry(t, &card->transaction_list, link) {
-		if (t->node_id == source && t->tlabel == tlabel) {
-			if (!try_cancel_split_timeout(t)) {
+	list_for_each_entry(iter, &card->transaction_list, link) {
+		if (iter->node_id == source && iter->tlabel == tlabel) {
+			if (!try_cancel_split_timeout(iter)) {
 				spin_unlock_irqrestore(&card->lock, flags);
 				goto timed_out;
 			}
-			list_del_init(&t->link);
-			card->tlabel_mask &= ~(1ULL << t->tlabel);
+			list_del_init(&iter->link);
+			card->tlabel_mask &= ~(1ULL << iter->tlabel);
+			t = iter;
 			break;
 		}
 	}
 	spin_unlock_irqrestore(&card->lock, flags);
 
-	if (&t->link == &card->transaction_list) {
+	if (!t) {
  timed_out:
 		fw_notice(card, "unsolicited response (source %x, tlabel %x)\n",
 			  source, tlabel);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firewire/net.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firewire/net.c
@@ -250,7 +250,11 @@
 	h = (struct fwnet_header *)((u8 *)hh->hh_data + HH_DATA_OFF(sizeof(*h)));
 	h->h_proto = type;
 	memcpy(h->h_dest, neigh->ha, net->addr_len);
-	hh->hh_len = FWNET_HLEN;
+
+	/* Pairs with the READ_ONCE() in neigh_resolve_output(),
+	 * neigh_hh_output() and neigh_update_hhs().
+	 */
+	smp_store_release(&hh->hh_len, FWNET_HLEN);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firewire/nosy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firewire/nosy.c
@@ -148,10 +148,12 @@
 	if (atomic_read(&buffer->size) == 0)
 		return -ENODEV;
 
-	/* FIXME: Check length <= user_length. */
+	length = buffer->head->length;
+
+	if (length > user_length)
+		return 0;
 
 	end = buffer->data + buffer->capacity;
-	length = buffer->head->length;
 
 	if (&buffer->head->data[length] < end) {
 		if (copy_to_user(data, buffer->head->data, length))
@@ -346,6 +348,7 @@
 	struct client *client = file->private_data;
 	spinlock_t *client_list_lock = &client->lynx->client_list_lock;
 	struct nosy_stats stats;
+	int ret;
 
 	switch (cmd) {
 	case NOSY_IOC_GET_STATS:
@@ -360,11 +363,15 @@
 			return 0;
 
 	case NOSY_IOC_START:
+		ret = -EBUSY;
 		spin_lock_irq(client_list_lock);
-		list_add_tail(&client->link, &client->lynx->client_list);
+		if (list_empty(&client->link)) {
+			list_add_tail(&client->link, &client->lynx->client_list);
+			ret = 0;
+		}
 		spin_unlock_irq(client_list_lock);
 
-		return 0;
+		return ret;
 
 	case NOSY_IOC_STOP:
 		spin_lock_irq(client_list_lock);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firewire/ohci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firewire/ohci.c
@@ -279,6 +279,51 @@
 #define QUIRK_TI_SLLZ059		0x20
 #define QUIRK_IR_WAKE			0x40
 
+// On PCI Express Root Complex in any type of AMD Ryzen machine, VIA VT6306/6307/6308 with Asmedia
+// ASM1083/1085 brings an inconvenience that the read accesses to 'Isochronous Cycle Timer' register
+// (at offset 0xf0 in PCI I/O space) often causes unexpected system reboot. The mechanism is not
+// clear, since the read access to the other registers is enough safe; e.g. 'Node ID' register,
+// while it is probable due to detection of any type of PCIe error.
+#define QUIRK_REBOOT_BY_CYCLE_TIMER_READ	0x80000000
+
+#if IS_ENABLED(CONFIG_X86)
+
+static bool has_reboot_by_cycle_timer_read_quirk(const struct fw_ohci *ohci)
+{
+	return !!(ohci->quirks & QUIRK_REBOOT_BY_CYCLE_TIMER_READ);
+}
+
+#define PCI_DEVICE_ID_ASMEDIA_ASM108X	0x1080
+
+static bool detect_vt630x_with_asm1083_on_amd_ryzen_machine(const struct pci_dev *pdev)
+{
+	const struct pci_dev *pcie_to_pci_bridge;
+
+	// Detect any type of AMD Ryzen machine.
+	if (!static_cpu_has(X86_FEATURE_ZEN))
+		return false;
+
+	// Detect VIA VT6306/6307/6308.
+	if (pdev->vendor != PCI_VENDOR_ID_VIA)
+		return false;
+	if (pdev->device != PCI_DEVICE_ID_VIA_VT630X)
+		return false;
+
+	// Detect Asmedia ASM1083/1085.
+	pcie_to_pci_bridge = pdev->bus->self;
+	if (pcie_to_pci_bridge->vendor != PCI_VENDOR_ID_ASMEDIA)
+		return false;
+	if (pcie_to_pci_bridge->device != PCI_DEVICE_ID_ASMEDIA_ASM108X)
+		return false;
+
+	return true;
+}
+
+#else
+#define has_reboot_by_cycle_timer_read_quirk(ohci) false
+#define detect_vt630x_with_asm1083_on_amd_ryzen_machine(pdev)	false
+#endif
+
 /* In case of multiple matches in ohci_quirks[], only the first one is used. */
 static const struct {
 	unsigned short vendor, device, revision, flags;
@@ -1099,7 +1144,7 @@
 static int context_add_buffer(struct context *ctx)
 {
 	struct descriptor_buffer *desc;
-	dma_addr_t uninitialized_var(bus_addr);
+	dma_addr_t bus_addr;
 	int offset;
 
 	/*
@@ -1289,7 +1334,7 @@
 				   struct fw_packet *packet)
 {
 	struct fw_ohci *ohci = ctx->ohci;
-	dma_addr_t d_bus, uninitialized_var(payload_bus);
+	dma_addr_t d_bus, payload_bus;
 	struct driver_data *driver_data;
 	struct descriptor *d, *last;
 	__le32 *header;
@@ -1717,6 +1762,9 @@
 	s32 diff01, diff12;
 	int i;
 
+	if (has_reboot_by_cycle_timer_read_quirk(ohci))
+		return 0;
+
 	c2 = reg_read(ohci, OHCI1394_IsochronousCycleTimer);
 
 	if (ohci->quirks & QUIRK_CYCLE_TIMER) {
@@ -2005,6 +2053,8 @@
 
 	ohci->generation = generation;
 	reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset);
+	if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS)
+		reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset);
 
 	if (ohci->quirks & QUIRK_RESET_PACKET)
 		ohci->request_generation = generation;
@@ -2071,12 +2121,14 @@
 		return IRQ_NONE;
 
 	/*
-	 * busReset and postedWriteErr must not be cleared yet
+	 * busReset and postedWriteErr events must not be cleared yet
 	 * (OHCI 1.1 clauses 7.2.3.2 and 13.2.8.1)
 	 */
 	reg_write(ohci, OHCI1394_IntEventClear,
 		  event & ~(OHCI1394_busReset | OHCI1394_postedWriteErr));
 	log_irqs(ohci, event);
+	if (event & OHCI1394_busReset)
+		reg_write(ohci, OHCI1394_IntMaskClear, OHCI1394_busReset);
 
 	if (event & OHCI1394_selfIDComplete)
 		queue_work(selfid_workqueue, &ohci->bus_reset_work);
@@ -2445,7 +2497,7 @@
 {
 	struct fw_ohci *ohci;
 	__be32 *next_config_rom;
-	dma_addr_t uninitialized_var(next_config_rom_bus);
+	dma_addr_t next_config_rom_bus;
 
 	ohci = fw_ohci(card);
 
@@ -2933,10 +2985,10 @@
 				int type, int channel, size_t header_size)
 {
 	struct fw_ohci *ohci = fw_ohci(card);
-	struct iso_context *uninitialized_var(ctx);
-	descriptor_callback_t uninitialized_var(callback);
-	u64 *uninitialized_var(channels);
-	u32 *uninitialized_var(mask), uninitialized_var(regs);
+	struct iso_context *ctx;
+	descriptor_callback_t callback;
+	u64 *channels;
+	u32 *mask, regs;
 	int index, ret = -EBUSY;
 
 	spin_lock_irq(&ohci->lock);
@@ -3619,6 +3671,9 @@
 	if (param_quirks)
 		ohci->quirks = param_quirks;
 
+	if (detect_vt630x_with_asm1083_on_amd_ryzen_machine(dev))
+		ohci->quirks |= QUIRK_REBOOT_BY_CYCLE_TIMER_READ;
+
 	/*
 	 * Because dma_alloc_coherent() allocates at least one page,
 	 * we save space by using a common buffer for the AR request/
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firewire/sbp2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firewire/sbp2.c
@@ -408,7 +408,7 @@
 			      void *payload, size_t length, void *callback_data)
 {
 	struct sbp2_logical_unit *lu = callback_data;
-	struct sbp2_orb *orb;
+	struct sbp2_orb *orb = NULL, *iter;
 	struct sbp2_status status;
 	unsigned long flags;
 
@@ -433,17 +433,18 @@
 
 	/* Lookup the orb corresponding to this status write. */
 	spin_lock_irqsave(&lu->tgt->lock, flags);
-	list_for_each_entry(orb, &lu->orb_list, link) {
+	list_for_each_entry(iter, &lu->orb_list, link) {
 		if (STATUS_GET_ORB_HIGH(status) == 0 &&
-		    STATUS_GET_ORB_LOW(status) == orb->request_bus) {
-			orb->rcode = RCODE_COMPLETE;
-			list_del(&orb->link);
+		    STATUS_GET_ORB_LOW(status) == iter->request_bus) {
+			iter->rcode = RCODE_COMPLETE;
+			list_del(&iter->link);
+			orb = iter;
 			break;
 		}
 	}
 	spin_unlock_irqrestore(&lu->tgt->lock, flags);
 
-	if (&orb->link != &lu->orb_list) {
+	if (orb) {
 		orb->callback(orb, &status);
 		kref_put(&orb->kref, free_orb); /* orb callback reference */
 	} else {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/Kconfig
@@ -170,7 +170,7 @@
 	select ISCSI_BOOT_SYSFS
 	select ISCSI_IBFT_FIND if X86
 	depends on ACPI && SCSI && SCSI_LOWLEVEL
-	default	n
+	default n
 	help
 	  This option enables support for detection and exposing of iSCSI
 	  Boot Firmware Table (iBFT) via sysfs to userspace. If you wish to
@@ -237,6 +237,7 @@
 config QCOM_SCM
 	bool
 	depends on ARM || ARM64
+	depends on HAVE_ARM_SMCCC
 	select RESET_CONTROLLER
 
 config QCOM_SCM_32
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/arm_scmi/base.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/arm_scmi/base.c
@@ -164,7 +164,7 @@
 			break;
 
 		loop_num_ret = le32_to_cpu(*num_ret);
-		if (tot_num_ret + loop_num_ret > MAX_PROTOCOLS_IMP) {
+		if (loop_num_ret > MAX_PROTOCOLS_IMP - tot_num_ret) {
 			dev_err(dev, "No. of Protocol > MAX_PROTOCOLS_IMP");
 			break;
 		}
@@ -173,6 +173,8 @@
 			protocols_imp[tot_num_ret + loop] = *(list + loop);
 
 		tot_num_ret += loop_num_ret;
+
+		scmi_reset_rx_to_maxsz(handle, t);
 	} while (loop_num_ret);
 
 	scmi_xfer_put(handle, t);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/arm_scmi/bus.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/arm_scmi/bus.c
@@ -100,6 +100,9 @@
 {
 	int retval;
 
+	if (!driver->probe)
+		return -EINVAL;
+
 	driver->driver.bus = &scmi_bus_type;
 	driver->driver.name = driver->name;
 	driver->driver.owner = owner;
@@ -135,8 +138,10 @@
 		return NULL;
 
 	id = ida_simple_get(&scmi_bus_id, 1, 0, GFP_KERNEL);
-	if (id < 0)
-		goto free_mem;
+	if (id < 0) {
+		kfree(scmi_dev);
+		return NULL;
+	}
 
 	scmi_dev->id = id;
 	scmi_dev->protocol_id = protocol;
@@ -154,8 +159,6 @@
 put_dev:
 	put_device(&scmi_dev->dev);
 	ida_simple_remove(&scmi_bus_id, id);
-free_mem:
-	kfree(scmi_dev);
 	return NULL;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/arm_scmi/clock.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/arm_scmi/clock.c
@@ -177,6 +177,8 @@
 		}
 
 		tot_rate_cnt += num_returned;
+
+		scmi_reset_rx_to_maxsz(handle, t);
 		/*
 		 * check for both returned and remaining to avoid infinite
 		 * loop due to buggy firmware
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/arm_scmi/common.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/arm_scmi/common.h
@@ -103,6 +103,8 @@
 			       struct scmi_xfer *xfer);
 int scmi_xfer_get_init(const struct scmi_handle *h, u8 msg_id, u8 prot_id,
 		       size_t tx_size, size_t rx_size, struct scmi_xfer **p);
+void scmi_reset_rx_to_maxsz(const struct scmi_handle *handle,
+			    struct scmi_xfer *xfer);
 int scmi_handle_put(const struct scmi_handle *handle);
 struct scmi_handle *scmi_handle_get(struct device *dev);
 void scmi_set_handle(struct scmi_device *scmi_dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/arm_scmi/driver.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/arm_scmi/driver.c
@@ -54,7 +54,6 @@
 	SCMI_ERR_GENERIC = -8,	/* Generic Error */
 	SCMI_ERR_HARDWARE = -9,	/* Hardware Error */
 	SCMI_ERR_PROTOCOL = -10,/* Protocol Error */
-	SCMI_ERR_MAX
 };
 
 /* List of all SCMI devices active in system */
@@ -176,8 +175,10 @@
 
 static inline int scmi_to_linux_errno(int errno)
 {
-	if (errno < SCMI_SUCCESS && errno > SCMI_ERR_MAX)
-		return scmi_linux_errmap[-errno];
+	int err_idx = -errno;
+
+	if (err_idx >= SCMI_SUCCESS && err_idx < ARRAY_SIZE(scmi_linux_errmap))
+		return scmi_linux_errmap[err_idx];
 	return -EIO;
 }
 
@@ -370,6 +371,10 @@
 
 	xfer = &minfo->xfer_block[xfer_id];
 
+	/* rx.len could be shrunk in the sync do_xfer, so reset to maxsz */
+	if (msg_type == MSG_TYPE_DELAYED_RESP)
+		xfer->rx.len = info->desc->max_msg_size;
+
 	scmi_dump_header_dbg(dev, &xfer->hdr);
 
 	scmi_fetch_response(xfer, mem);
@@ -481,6 +486,14 @@
 	return ret;
 }
 
+void scmi_reset_rx_to_maxsz(const struct scmi_handle *handle,
+			    struct scmi_xfer *xfer)
+{
+	struct scmi_info *info = handle_to_scmi_info(handle);
+
+	xfer->rx.len = info->desc->max_msg_size;
+}
+
 #define SCMI_MAX_RESPONSE_TIMEOUT	(2 * MSEC_PER_SEC)
 
 /**
@@ -502,8 +515,12 @@
 	xfer->async_done = &async_response;
 
 	ret = scmi_do_xfer(handle, xfer);
-	if (!ret && !wait_for_completion_timeout(xfer->async_done, timeout))
-		ret = -ETIMEDOUT;
+	if (!ret) {
+		if (!wait_for_completion_timeout(xfer->async_done, timeout))
+			ret = -ETIMEDOUT;
+		else if (xfer->hdr.status)
+			ret = scmi_to_linux_errno(xfer->hdr.status);
+	}
 
 	xfer->async_done = NULL;
 	return ret;
@@ -681,8 +698,9 @@
 	struct scmi_xfers_info *info = &sinfo->tx_minfo;
 
 	/* Pre-allocated messages, no more than what hdr.seq can support */
-	if (WARN_ON(desc->max_msg >= MSG_TOKEN_MAX)) {
-		dev_err(dev, "Maximum message of %d exceeds supported %ld\n",
+	if (WARN_ON(!desc->max_msg || desc->max_msg > MSG_TOKEN_MAX)) {
+		dev_err(dev,
+			"Invalid maximum messages %d, not in range [1 - %lu]\n",
 			desc->max_msg, MSG_TOKEN_MAX);
 		return -EINVAL;
 	}
@@ -719,6 +737,39 @@
 					  idx, NULL);
 }
 
+static int scmi_mailbox_chan_validate(struct device *cdev)
+{
+	int num_mb, num_sh, ret = 0;
+	struct device_node *np = cdev->of_node;
+
+	num_mb = of_count_phandle_with_args(np, "mboxes", "#mbox-cells");
+	num_sh = of_count_phandle_with_args(np, "shmem", NULL);
+	/* Bail out if mboxes and shmem descriptors are inconsistent */
+	if (num_mb <= 0 || num_sh > 2 || num_mb != num_sh) {
+		dev_warn(cdev, "Invalid channel descriptor for '%s'\n",
+			 of_node_full_name(np));
+		return -EINVAL;
+	}
+
+	if (num_sh > 1) {
+		struct device_node *np_tx, *np_rx;
+
+		np_tx = of_parse_phandle(np, "shmem", 0);
+		np_rx = of_parse_phandle(np, "shmem", 1);
+		/* SCMI Tx and Rx shared mem areas have to be distinct */
+		if (!np_tx || !np_rx || np_tx == np_rx) {
+			dev_warn(cdev, "Invalid shmem descriptor for '%s'\n",
+				 of_node_full_name(np));
+			ret = -EINVAL;
+		}
+
+		of_node_put(np_tx);
+		of_node_put(np_rx);
+	}
+
+	return ret;
+}
+
 static int scmi_mbox_chan_setup(struct scmi_info *info, struct device *dev,
 				int prot_id, bool tx)
 {
@@ -742,6 +793,10 @@
 		goto idr_alloc;
 	}
 
+	ret = scmi_mailbox_chan_validate(dev);
+	if (ret)
+		return ret;
+
 	cinfo = devm_kzalloc(info->dev, sizeof(*cinfo), GFP_KERNEL);
 	if (!cinfo)
 		return -ENOMEM;
@@ -965,7 +1020,7 @@
 
 module_platform_driver(scmi_driver);
 
-MODULE_ALIAS("platform: arm-scmi");
+MODULE_ALIAS("platform:arm-scmi");
 MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
 MODULE_DESCRIPTION("ARM SCMI protocol driver");
 MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/arm_scmi/perf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/arm_scmi/perf.c
@@ -281,6 +281,8 @@
 		}
 
 		tot_opp_cnt += num_returned;
+
+		scmi_reset_rx_to_maxsz(handle, t);
 		/*
 		 * check for both returned and remaining to avoid infinite
 		 * loop due to buggy firmware
@@ -323,7 +325,7 @@
 
 		if (db->mask)
 			val = ioread64_hi_lo(db->addr) & db->mask;
-		iowrite64_hi_lo(db->set, db->addr);
+		iowrite64_hi_lo(db->set | val, db->addr);
 	}
 #endif
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/arm_scmi/reset.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/arm_scmi/reset.c
@@ -35,9 +35,7 @@
 #define EXPLICIT_RESET_ASSERT	BIT(1)
 #define ASYNCHRONOUS_RESET	BIT(2)
 	__le32 reset_state;
-#define ARCH_RESET_TYPE		BIT(31)
-#define COLD_RESET_STATE	BIT(0)
-#define ARCH_COLD_RESET		(ARCH_RESET_TYPE | COLD_RESET_STATE)
+#define ARCH_COLD_RESET		0
 };
 
 struct reset_dom_info {
@@ -137,8 +135,12 @@
 	struct scmi_xfer *t;
 	struct scmi_msg_reset_domain_reset *dom;
 	struct scmi_reset_info *pi = handle->reset_priv;
-	struct reset_dom_info *rdom = pi->dom_info + domain;
+	struct reset_dom_info *rdom;
 
+	if (domain >= pi->num_domains)
+		return -EINVAL;
+
+	rdom = pi->dom_info + domain;
 	if (rdom->async_reset)
 		flags |= ASYNCHRONOUS_RESET;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/arm_scmi/scmi_pm_domain.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/arm_scmi/scmi_pm_domain.c
@@ -85,7 +85,10 @@
 	for (i = 0; i < num_domains; i++, scmi_pd++) {
 		u32 state;
 
-		domains[i] = &scmi_pd->genpd;
+		if (handle->power_ops->state_get(handle, i, &state)) {
+			dev_warn(dev, "failed to get state for domain %d\n", i);
+			continue;
+		}
 
 		scmi_pd->domain = i;
 		scmi_pd->handle = handle;
@@ -94,21 +97,35 @@
 		scmi_pd->genpd.power_off = scmi_pd_power_off;
 		scmi_pd->genpd.power_on = scmi_pd_power_on;
 
-		if (handle->power_ops->state_get(handle, i, &state)) {
-			dev_warn(dev, "failed to get state for domain %d\n", i);
-			continue;
-		}
-
 		pm_genpd_init(&scmi_pd->genpd, NULL,
 			      state == SCMI_POWER_STATE_GENERIC_OFF);
+
+		domains[i] = &scmi_pd->genpd;
 	}
 
 	scmi_pd_data->domains = domains;
 	scmi_pd_data->num_domains = num_domains;
 
-	of_genpd_add_provider_onecell(np, scmi_pd_data);
+	dev_set_drvdata(dev, scmi_pd_data);
 
-	return 0;
+	return of_genpd_add_provider_onecell(np, scmi_pd_data);
+}
+
+static void scmi_pm_domain_remove(struct scmi_device *sdev)
+{
+	int i;
+	struct genpd_onecell_data *scmi_pd_data;
+	struct device *dev = &sdev->dev;
+	struct device_node *np = dev->of_node;
+
+	of_genpd_del_provider(np);
+
+	scmi_pd_data = dev_get_drvdata(dev);
+	for (i = 0; i < scmi_pd_data->num_domains; i++) {
+		if (!scmi_pd_data->domains[i])
+			continue;
+		pm_genpd_remove(scmi_pd_data->domains[i]);
+	}
 }
 
 static const struct scmi_device_id scmi_id_table[] = {
@@ -120,6 +137,7 @@
 static struct scmi_driver scmi_power_domain_driver = {
 	.name = "scmi-power-domain",
 	.probe = scmi_pm_domain_probe,
+	.remove = scmi_pm_domain_remove,
 	.id_table = scmi_id_table,
 };
 module_scmi_driver(scmi_power_domain_driver);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/arm_scmi/sensors.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/arm_scmi/sensors.c
@@ -154,6 +154,8 @@
 		}
 
 		desc_index += num_returned;
+
+		scmi_reset_rx_to_maxsz(handle, t);
 		/*
 		 * check for both returned and remaining to avoid infinite
 		 * loop due to buggy firmware
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/arm_scpi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/arm_scpi.c
@@ -552,8 +552,10 @@
 
 	ret = scpi_send_message(CMD_GET_CLOCK_VALUE, &le_clk_id,
 				sizeof(le_clk_id), &rate, sizeof(rate));
+	if (ret)
+		return 0;
 
-	return ret ? ret : le32_to_cpu(rate);
+	return le32_to_cpu(rate);
 }
 
 static int scpi_clk_set_val(u16 clk_id, unsigned long rate)
@@ -625,6 +627,9 @@
 	if (ret)
 		return ERR_PTR(ret);
 
+	if (!buf.opp_count)
+		return ERR_PTR(-ENOENT);
+
 	info = kmalloc(sizeof(*info), GFP_KERNEL);
 	if (!info)
 		return ERR_PTR(-ENOMEM);
@@ -813,7 +818,7 @@
 		info->firmware_version = le32_to_cpu(caps.platform_version);
 	}
 	/* Ignore error if not implemented */
-	if (scpi_info->is_legacy && ret == -EOPNOTSUPP)
+	if (info->is_legacy && ret == -EOPNOTSUPP)
 		return 0;
 
 	return ret;
@@ -903,13 +908,14 @@
 	struct resource res;
 	struct device *dev = &pdev->dev;
 	struct device_node *np = dev->of_node;
+	struct scpi_drvinfo *scpi_drvinfo;
 
-	scpi_info = devm_kzalloc(dev, sizeof(*scpi_info), GFP_KERNEL);
-	if (!scpi_info)
+	scpi_drvinfo = devm_kzalloc(dev, sizeof(*scpi_drvinfo), GFP_KERNEL);
+	if (!scpi_drvinfo)
 		return -ENOMEM;
 
 	if (of_match_device(legacy_scpi_of_match, &pdev->dev))
-		scpi_info->is_legacy = true;
+		scpi_drvinfo->is_legacy = true;
 
 	count = of_count_phandle_with_args(np, "mboxes", "#mbox-cells");
 	if (count < 0) {
@@ -917,19 +923,19 @@
 		return -ENODEV;
 	}
 
-	scpi_info->channels = devm_kcalloc(dev, count, sizeof(struct scpi_chan),
-					   GFP_KERNEL);
-	if (!scpi_info->channels)
+	scpi_drvinfo->channels =
+		devm_kcalloc(dev, count, sizeof(struct scpi_chan), GFP_KERNEL);
+	if (!scpi_drvinfo->channels)
 		return -ENOMEM;
 
-	ret = devm_add_action(dev, scpi_free_channels, scpi_info);
+	ret = devm_add_action(dev, scpi_free_channels, scpi_drvinfo);
 	if (ret)
 		return ret;
 
-	for (; scpi_info->num_chans < count; scpi_info->num_chans++) {
+	for (; scpi_drvinfo->num_chans < count; scpi_drvinfo->num_chans++) {
 		resource_size_t size;
-		int idx = scpi_info->num_chans;
-		struct scpi_chan *pchan = scpi_info->channels + idx;
+		int idx = scpi_drvinfo->num_chans;
+		struct scpi_chan *pchan = scpi_drvinfo->channels + idx;
 		struct mbox_client *cl = &pchan->cl;
 		struct device_node *shmem = of_parse_phandle(np, "shmem", idx);
 
@@ -973,45 +979,53 @@
 		return ret;
 	}
 
-	scpi_info->commands = scpi_std_commands;
+	scpi_drvinfo->commands = scpi_std_commands;
 
-	platform_set_drvdata(pdev, scpi_info);
+	platform_set_drvdata(pdev, scpi_drvinfo);
 
-	if (scpi_info->is_legacy) {
+	if (scpi_drvinfo->is_legacy) {
 		/* Replace with legacy variants */
 		scpi_ops.clk_set_val = legacy_scpi_clk_set_val;
-		scpi_info->commands = scpi_legacy_commands;
+		scpi_drvinfo->commands = scpi_legacy_commands;
 
 		/* Fill priority bitmap */
 		for (idx = 0; idx < ARRAY_SIZE(legacy_hpriority_cmds); idx++)
 			set_bit(legacy_hpriority_cmds[idx],
-				scpi_info->cmd_priority);
+				scpi_drvinfo->cmd_priority);
 	}
 
-	ret = scpi_init_versions(scpi_info);
+	scpi_info = scpi_drvinfo;
+
+	ret = scpi_init_versions(scpi_drvinfo);
 	if (ret) {
 		dev_err(dev, "incorrect or no SCP firmware found\n");
+		scpi_info = NULL;
 		return ret;
 	}
 
-	if (scpi_info->is_legacy && !scpi_info->protocol_version &&
-	    !scpi_info->firmware_version)
+	if (scpi_drvinfo->is_legacy && !scpi_drvinfo->protocol_version &&
+	    !scpi_drvinfo->firmware_version)
 		dev_info(dev, "SCP Protocol legacy pre-1.0 firmware\n");
 	else
 		dev_info(dev, "SCP Protocol %lu.%lu Firmware %lu.%lu.%lu version\n",
 			 FIELD_GET(PROTO_REV_MAJOR_MASK,
-				   scpi_info->protocol_version),
+				   scpi_drvinfo->protocol_version),
 			 FIELD_GET(PROTO_REV_MINOR_MASK,
-				   scpi_info->protocol_version),
+				   scpi_drvinfo->protocol_version),
 			 FIELD_GET(FW_REV_MAJOR_MASK,
-				   scpi_info->firmware_version),
+				   scpi_drvinfo->firmware_version),
 			 FIELD_GET(FW_REV_MINOR_MASK,
-				   scpi_info->firmware_version),
+				   scpi_drvinfo->firmware_version),
 			 FIELD_GET(FW_REV_PATCH_MASK,
-				   scpi_info->firmware_version));
-	scpi_info->scpi_ops = &scpi_ops;
+				   scpi_drvinfo->firmware_version));
 
-	return devm_of_platform_populate(dev);
+	scpi_drvinfo->scpi_ops = &scpi_ops;
+
+	ret = devm_of_platform_populate(dev);
+	if (ret)
+		scpi_info = NULL;
+
+	return ret;
 }
 
 static const struct of_device_id scpi_of_match[] = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/arm_sdei.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/arm_sdei.c
@@ -44,6 +44,8 @@
 /* entry point from firmware to arch asm code */
 static unsigned long sdei_entry_point;
 
+static int sdei_hp_state;
+
 struct sdei_event {
 	/* These three are protected by the sdei_list_lock */
 	struct list_head	list;
@@ -305,8 +307,6 @@
 {
 	int err;
 
-	WARN_ON_ONCE(preemptible());
-
 	err = invoke_sdei_fn(SDEI_1_0_FN_SDEI_PE_MASK, 0, 0, 0, 0, 0, NULL);
 	if (err && err != -EIO) {
 		pr_warn_once("failed to mask CPU[%u]: %d\n",
@@ -319,6 +319,7 @@
 
 static void _ipi_mask_cpu(void *ignored)
 {
+	WARN_ON_ONCE(preemptible());
 	sdei_mask_local_cpu();
 }
 
@@ -326,8 +327,6 @@
 {
 	int err;
 
-	WARN_ON_ONCE(preemptible());
-
 	err = invoke_sdei_fn(SDEI_1_0_FN_SDEI_PE_UNMASK, 0, 0, 0, 0, 0, NULL);
 	if (err && err != -EIO) {
 		pr_warn_once("failed to unmask CPU[%u]: %d\n",
@@ -340,6 +339,7 @@
 
 static void _ipi_unmask_cpu(void *ignored)
 {
+	WARN_ON_ONCE(preemptible());
 	sdei_unmask_local_cpu();
 }
 
@@ -347,6 +347,8 @@
 {
 	int err;
 
+	WARN_ON_ONCE(preemptible());
+
 	err = invoke_sdei_fn(SDEI_1_0_FN_SDEI_PRIVATE_RESET, 0, 0, 0, 0, 0,
 			     NULL);
 	if (err && err != -EIO)
@@ -393,8 +395,6 @@
 	int err;
 	struct sdei_crosscall_args *arg = data;
 
-	WARN_ON_ONCE(preemptible());
-
 	err = sdei_api_event_enable(arg->event->event_num);
 
 	sdei_cross_call_return(arg, err);
@@ -412,14 +412,19 @@
 		return -ENOENT;
 	}
 
-	spin_lock(&sdei_list_lock);
-	event->reenable = true;
-	spin_unlock(&sdei_list_lock);
 
+	cpus_read_lock();
 	if (event->type == SDEI_EVENT_TYPE_SHARED)
 		err = sdei_api_event_enable(event->event_num);
 	else
 		err = sdei_do_cross_call(_local_event_enable, event);
+
+	if (!err) {
+		spin_lock(&sdei_list_lock);
+		event->reenable = true;
+		spin_unlock(&sdei_list_lock);
+	}
+	cpus_read_unlock();
 	mutex_unlock(&sdei_events_lock);
 
 	return err;
@@ -480,8 +485,6 @@
 	int err;
 	struct sdei_crosscall_args *arg = data;
 
-	WARN_ON_ONCE(preemptible());
-
 	err = sdei_api_event_unregister(arg->event->event_num);
 
 	sdei_cross_call_return(arg, err);
@@ -491,11 +494,6 @@
 {
 	lockdep_assert_held(&sdei_events_lock);
 
-	spin_lock(&sdei_list_lock);
-	event->reregister = false;
-	event->reenable = false;
-	spin_unlock(&sdei_list_lock);
-
 	if (event->type == SDEI_EVENT_TYPE_SHARED)
 		return sdei_api_event_unregister(event->event_num);
 
@@ -518,6 +516,11 @@
 			break;
 		}
 
+		spin_lock(&sdei_list_lock);
+		event->reregister = false;
+		event->reenable = false;
+		spin_unlock(&sdei_list_lock);
+
 		err = _sdei_event_unregister(event);
 		if (err)
 			break;
@@ -570,8 +573,6 @@
 	struct sdei_registered_event *reg;
 	struct sdei_crosscall_args *arg = data;
 
-	WARN_ON(preemptible());
-
 	reg = per_cpu_ptr(arg->event->private_registered, smp_processor_id());
 	err = sdei_api_event_register(arg->event->event_num, sdei_entry_point,
 				      reg, 0, 0);
@@ -585,26 +586,15 @@
 
 	lockdep_assert_held(&sdei_events_lock);
 
-	spin_lock(&sdei_list_lock);
-	event->reregister = true;
-	spin_unlock(&sdei_list_lock);
-
 	if (event->type == SDEI_EVENT_TYPE_SHARED)
 		return sdei_api_event_register(event->event_num,
 					       sdei_entry_point,
 					       event->registered,
 					       SDEI_EVENT_REGISTER_RM_ANY, 0);
 
-
 	err = sdei_do_cross_call(_local_event_register, event);
-	if (err) {
-		spin_lock(&sdei_list_lock);
-		event->reregister = false;
-		event->reenable = false;
-		spin_unlock(&sdei_list_lock);
-
+	if (err)
 		sdei_do_cross_call(_local_event_unregister, event);
-	}
 
 	return err;
 }
@@ -632,12 +622,18 @@
 			break;
 		}
 
+		cpus_read_lock();
 		err = _sdei_event_register(event);
 		if (err) {
 			sdei_event_destroy(event);
 			pr_warn("Failed to register event %u: %d\n", event_num,
 				err);
+		} else {
+			spin_lock(&sdei_list_lock);
+			event->reregister = true;
+			spin_unlock(&sdei_list_lock);
 		}
+		cpus_read_unlock();
 	} while (0);
 	mutex_unlock(&sdei_events_lock);
 
@@ -756,6 +752,8 @@
 {
 	int rv;
 
+	WARN_ON_ONCE(preemptible());
+
 	switch (action) {
 	case CPU_PM_ENTER:
 		rv = sdei_mask_local_cpu();
@@ -804,7 +802,7 @@
 	int err;
 
 	/* unregister private events */
-	cpuhp_remove_state(CPUHP_AP_ARM_SDEI_STARTING);
+	cpuhp_remove_state(sdei_hp_state);
 
 	err = sdei_unregister_shared();
 	if (err)
@@ -825,12 +823,15 @@
 		return err;
 	}
 
-	err = cpuhp_setup_state(CPUHP_AP_ARM_SDEI_STARTING, "SDEI",
+	err = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "SDEI",
 				&sdei_cpuhp_up, &sdei_cpuhp_down);
-	if (err)
+	if (err < 0) {
 		pr_warn("Failed to re-register CPU hotplug notifier...\n");
+		return err;
+	}
 
-	return err;
+	sdei_hp_state = err;
+	return 0;
 }
 
 static int sdei_device_restore(struct device *dev)
@@ -862,7 +863,7 @@
 	 * We are going to reset the interface, after this there is no point
 	 * doing work when we take CPUs offline.
 	 */
-	cpuhp_remove_state(CPUHP_AP_ARM_SDEI_STARTING);
+	cpuhp_remove_state(sdei_hp_state);
 
 	sdei_platform_reset();
 
@@ -1044,13 +1045,15 @@
 		goto remove_cpupm;
 	}
 
-	err = cpuhp_setup_state(CPUHP_AP_ARM_SDEI_STARTING, "SDEI",
+	err = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "SDEI",
 				&sdei_cpuhp_up, &sdei_cpuhp_down);
-	if (err) {
+	if (err < 0) {
 		pr_warn("Failed to register CPU hotplug notifier...\n");
 		goto remove_reboot;
 	}
 
+	sdei_hp_state = err;
+
 	return 0;
 
 remove_reboot:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/dmi-id.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/dmi-id.c
@@ -160,9 +160,14 @@
 	return 0;
 }
 
+static void dmi_dev_release(struct device *dev)
+{
+	kfree(dev);
+}
+
 static struct class dmi_class = {
 	.name = "dmi",
-	.dev_release = (void(*)(struct device *)) kfree,
+	.dev_release = dmi_dev_release,
 	.dev_uevent = dmi_dev_uevent,
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/dmi-sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/dmi-sysfs.c
@@ -603,7 +603,7 @@
 				    "%d-%d", dh->type, entry->instance);
 
 	if (*ret) {
-		kfree(entry);
+		kobject_put(&entry->kobj);
 		return;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/dmi_scan.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/dmi_scan.c
@@ -97,6 +97,17 @@
 		const struct dmi_header *dm = (const struct dmi_header *)data;
 
 		/*
+		 * If a short entry is found (less than 4 bytes), not only it
+		 * is invalid, but we cannot reliably locate the next entry.
+		 */
+		if (dm->length < sizeof(struct dmi_header)) {
+			pr_warn(FW_BUG
+				"Corrupted DMI table, offset %zd (only %d entries processed)\n",
+				data - buf, i);
+			break;
+		}
+
+		/*
 		 *  We want to know the total length (formatted area and
 		 *  strings) before decoding to make sure we won't run off the
 		 *  table in dmi_decode or dmi_string
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/efi/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/efi/Kconfig
@@ -216,6 +216,17 @@
 
 config EFI_EARLYCON
 	def_bool y
-	depends on SERIAL_EARLYCON && !ARM && !IA64
+	depends on EFI && SERIAL_EARLYCON && !ARM && !IA64
 	select FONT_SUPPORT
 	select ARCH_USE_MEMREMAP_PROT
+
+config EFI_CUSTOM_SSDT_OVERLAYS
+	bool "Load custom ACPI SSDT overlay from an EFI variable"
+	depends on EFI_VARS && ACPI
+	default ACPI_TABLE_UPGRADE
+	help
+	  Allow loading of an ACPI SSDT overlay from an EFI variable specified
+	  by a kernel command line option.
+
+	  See Documentation/admin-guide/acpi/ssdt-overlays.rst for more
+	  information.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/efi/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/efi/Makefile
@@ -24,8 +24,10 @@
 obj-$(CONFIG_EFI_BOOTLOADER_CONTROL)	+= efibc.o
 obj-$(CONFIG_EFI_TEST)			+= test/
 obj-$(CONFIG_EFI_DEV_PATH_PARSER)	+= dev-path-parser.o
+obj-$(CONFIG_EFI)			+= secureboot.o
 obj-$(CONFIG_APPLE_PROPERTIES)		+= apple-properties.o
 obj-$(CONFIG_EFI_RCI2_TABLE)		+= rci2-table.o
+obj-$(CONFIG_LOAD_UEFI_KEYS)		+= mokvar-table.o
 
 arm-obj-$(CONFIG_EFI)			:= arm-init.o arm-runtime.o
 obj-$(CONFIG_ARM)			+= $(arm-obj-y)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/efi/apple-properties.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/efi/apple-properties.c
@@ -23,7 +23,7 @@
 static int __init dump_properties_enable(char *arg)
 {
 	dump_properties = true;
-	return 0;
+	return 1;
 }
 
 __setup("dump_apple_properties", dump_properties_enable);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/efi/arm-init.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/efi/arm-init.c
@@ -17,6 +17,7 @@
 #include <linux/of_fdt.h>
 #include <linux/platform_device.h>
 #include <linux/screen_info.h>
+#include <linux/security.h>
 
 #include <asm/efi.h>
 
@@ -253,8 +254,16 @@
 		return;
 	}
 
+	efi_set_secure_boot(params.secure_boot);
+
+#ifdef CONFIG_LOCK_DOWN_IN_SECURE_BOOT
+	if (efi_enabled(EFI_SECURE_BOOT))
+		security_lock_kernel_down("EFI Secure Boot mode", LOCKDOWN_INTEGRITY_MAX);
+#endif
+
 	reserve_regions();
 	efi_esrt_init();
+	efi_mokvar_table_init();
 
 	memblock_reserve(params.mmap & PAGE_MASK,
 			 PAGE_ALIGN(params.mmap_size +
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/efi/capsule-loader.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/efi/capsule-loader.c
@@ -242,29 +242,6 @@
 }
 
 /**
- * efi_capsule_flush - called by file close or file flush
- * @file: file pointer
- * @id: not used
- *
- *	If a capsule is being partially uploaded then calling this function
- *	will be treated as upload termination and will free those completed
- *	buffer pages and -ECANCELED will be returned.
- **/
-static int efi_capsule_flush(struct file *file, fl_owner_t id)
-{
-	int ret = 0;
-	struct capsule_info *cap_info = file->private_data;
-
-	if (cap_info->index > 0) {
-		pr_err("capsule upload not complete\n");
-		efi_free_all_buff_pages(cap_info);
-		ret = -ECANCELED;
-	}
-
-	return ret;
-}
-
-/**
  * efi_capsule_release - called by file close
  * @inode: not used
  * @file: file pointer
@@ -276,6 +253,13 @@
 {
 	struct capsule_info *cap_info = file->private_data;
 
+	if (cap_info->index > 0 &&
+	    (cap_info->header.headersize == 0 ||
+	     cap_info->count < cap_info->total_size)) {
+		pr_err("capsule upload not complete\n");
+		efi_free_all_buff_pages(cap_info);
+	}
+
 	kfree(cap_info->pages);
 	kfree(cap_info->phys);
 	kfree(file->private_data);
@@ -307,7 +291,7 @@
 		return -ENOMEM;
 	}
 
-	cap_info->phys = kzalloc(sizeof(void *), GFP_KERNEL);
+	cap_info->phys = kzalloc(sizeof(phys_addr_t), GFP_KERNEL);
 	if (!cap_info->phys) {
 		kfree(cap_info->pages);
 		kfree(cap_info);
@@ -323,7 +307,6 @@
 	.owner = THIS_MODULE,
 	.open = efi_capsule_open,
 	.write = efi_capsule_write,
-	.flush = efi_capsule_flush,
 	.release = efi_capsule_release,
 	.llseek = no_llseek,
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/efi/cper.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/efi/cper.c
@@ -25,8 +25,6 @@
 #include <acpi/ghes.h>
 #include <ras/ras_event.h>
 
-static char rcd_decode_str[CPER_REC_LEN];
-
 /*
  * CPER record ID need to be unique even after reboot, because record
  * ID is used as index for ERST storage, while CPER records from
@@ -263,8 +261,7 @@
 	if (!msg || !(mem->validation_bits & CPER_MEM_VALID_MODULE_HANDLE))
 		return 0;
 
-	n = 0;
-	len = CPER_REC_LEN - 1;
+	len = CPER_REC_LEN;
 	dmi_memdev_name(mem->mem_dev_handle, &bank, &device);
 	if (bank && device)
 		n = snprintf(msg, len, "DIMM location: %s %s ", bank, device);
@@ -273,7 +270,6 @@
 			     "DIMM location: not present. DMI handle: 0x%.4x ",
 			     mem->mem_dev_handle);
 
-	msg[n] = '\0';
 	return n;
 }
 
@@ -301,6 +297,7 @@
 				struct cper_mem_err_compact *cmem)
 {
 	const char *ret = trace_seq_buffer_ptr(p);
+	char rcd_decode_str[CPER_REC_LEN];
 
 	if (cper_mem_err_location(cmem, rcd_decode_str))
 		trace_seq_printf(p, "%s", rcd_decode_str);
@@ -315,6 +312,7 @@
 	int len)
 {
 	struct cper_mem_err_compact cmem;
+	char rcd_decode_str[CPER_REC_LEN];
 
 	/* Don't trust UEFI 2.1/2.2 structure with bad validation bits */
 	if (len == sizeof(struct cper_sec_mem_err_old) &&
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/efi/earlycon.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/efi/earlycon.c
@@ -13,18 +13,58 @@
 
 #include <asm/early_ioremap.h>
 
+static const struct console *earlycon_console __initdata;
 static const struct font_desc *font;
 static u32 efi_x, efi_y;
 static u64 fb_base;
-static pgprot_t fb_prot;
+static bool fb_wb;
+static void *efi_fb;
+
+/*
+ * EFI earlycon needs to use early_memremap() to map the framebuffer.
+ * But early_memremap() is not usable for 'earlycon=efifb keep_bootcon',
+ * memremap() should be used instead. memremap() will be available after
+ * paging_init() which is earlier than initcall callbacks. Thus adding this
+ * early initcall function early_efi_map_fb() to map the whole EFI framebuffer.
+ */
+static int __init efi_earlycon_remap_fb(void)
+{
+	/* bail if there is no bootconsole or it has been disabled already */
+	if (!earlycon_console || !(earlycon_console->flags & CON_ENABLED))
+		return 0;
+
+	efi_fb = memremap(fb_base, screen_info.lfb_size,
+			  fb_wb ? MEMREMAP_WB : MEMREMAP_WC);
+
+	return efi_fb ? 0 : -ENOMEM;
+}
+early_initcall(efi_earlycon_remap_fb);
+
+static int __init efi_earlycon_unmap_fb(void)
+{
+	/* unmap the bootconsole fb unless keep_bootcon has left it enabled */
+	if (efi_fb && !(earlycon_console->flags & CON_ENABLED))
+		memunmap(efi_fb);
+	return 0;
+}
+late_initcall(efi_earlycon_unmap_fb);
 
 static __ref void *efi_earlycon_map(unsigned long start, unsigned long len)
 {
+	pgprot_t fb_prot;
+
+	if (efi_fb)
+		return efi_fb + start;
+
+	fb_prot = fb_wb ? PAGE_KERNEL : pgprot_writecombine(PAGE_KERNEL);
 	return early_memremap_prot(fb_base + start, len, pgprot_val(fb_prot));
 }
 
 static __ref void efi_earlycon_unmap(void *addr, unsigned long len)
 {
+	if (efi_fb)
+		return;
+
 	early_memunmap(addr, len);
 }
 
@@ -176,10 +216,7 @@
 	if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE)
 		fb_base |= (u64)screen_info.ext_lfb_base << 32;
 
-	if (opt && !strcmp(opt, "ram"))
-		fb_prot = PAGE_KERNEL;
-	else
-		fb_prot = pgprot_writecombine(PAGE_KERNEL);
+	fb_wb = opt && !strcmp(opt, "ram");
 
 	si = &screen_info;
 	xres = si->lfb_width;
@@ -201,6 +238,7 @@
 		efi_earlycon_scroll_up();
 
 	device->con->write = efi_earlycon_write;
+	earlycon_console = device->con;
 	return 0;
 }
 EARLYCON_DECLARE(efifb, efi_earlycon_setup);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/efi/efi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/efi/efi.c
@@ -31,6 +31,7 @@
 #include <linux/ucs2_string.h>
 #include <linux/memblock.h>
 #include <linux/security.h>
+#include <linux/bsearch.h>
 
 #include <asm/early_ioremap.h>
 
@@ -52,6 +53,9 @@
 	.rng_seed		= EFI_INVALID_TABLE_ADDR,
 	.tpm_log		= EFI_INVALID_TABLE_ADDR,
 	.tpm_final_log		= EFI_INVALID_TABLE_ADDR,
+#ifdef CONFIG_LOAD_UEFI_KEYS
+	.mokvar_table		= EFI_INVALID_TABLE_ADDR,
+#endif
 	.mem_reserve		= EFI_INVALID_TABLE_ADDR,
 };
 EXPORT_SYMBOL(efi);
@@ -217,7 +221,7 @@
 	efivars_unregister(&generic_efivars);
 }
 
-#if IS_ENABLED(CONFIG_ACPI)
+#ifdef CONFIG_EFI_CUSTOM_SSDT_OVERLAYS
 #define EFIVAR_SSDT_NAME_MAX	16
 static char efivar_ssdt[EFIVAR_SSDT_NAME_MAX] __initdata;
 static int __init efivar_ssdt_setup(char *str)
@@ -231,7 +235,7 @@
 		memcpy(efivar_ssdt, str, strlen(str));
 	else
 		pr_warn("efivar_ssdt: name too long: %s\n", str);
-	return 0;
+	return 1;
 }
 __setup("efivar_ssdt=", efivar_ssdt_setup);
 
@@ -345,7 +349,8 @@
 	efi_kobj = kobject_create_and_add("efi", firmware_kobj);
 	if (!efi_kobj) {
 		pr_err("efi: Firmware registration failed.\n");
-		return -ENOMEM;
+		error = -ENOMEM;
+		goto err_destroy_wq;
 	}
 
 	error = generic_ops_register();
@@ -381,6 +386,10 @@
 	generic_ops_unregister();
 err_put:
 	kobject_put(efi_kobj);
+err_destroy_wq:
+	if (efi_rts_wq)
+		destroy_workqueue(efi_rts_wq);
+
 	return error;
 }
 
@@ -477,6 +486,9 @@
 #ifdef CONFIG_EFI_RCI2_TABLE
 	{DELLEMC_EFI_RCI2_TABLE_GUID, NULL, &rci2_table_phys},
 #endif
+#ifdef CONFIG_LOAD_UEFI_KEYS
+	{LINUX_EFI_MOK_VARIABLE_TABLE_GUID, "MOKvar", &efi.mokvar_table},
+#endif
 	{NULL_GUID, NULL, NULL},
 };
 
@@ -544,7 +556,7 @@
 
 		seed = early_memremap(efi.rng_seed, sizeof(*seed));
 		if (seed != NULL) {
-			size = seed->size;
+			size = min(seed->size, EFI_RANDOM_SEED_SIZE);
 			early_memunmap(seed, sizeof(*seed));
 		} else {
 			pr_err("Could not map UEFI random seed!\n");
@@ -554,7 +566,7 @@
 					      sizeof(*seed) + size);
 			if (seed != NULL) {
 				pr_notice("seeding entropy pool\n");
-				add_bootloader_randomness(seed->bits, seed->size);
+				add_bootloader_randomness(seed->bits, size);
 				early_memunmap(seed, sizeof(*seed) + size);
 			} else {
 				pr_err("Could not map UEFI random seed!\n");
@@ -562,7 +574,7 @@
 		}
 	}
 
-	if (efi_enabled(EFI_MEMMAP))
+	if (!IS_ENABLED(CONFIG_X86_32) && efi_enabled(EFI_MEMMAP))
 		efi_memattr_init();
 
 	efi_tpm_eventlog_init();
@@ -688,7 +700,8 @@
 	UEFI_PARAM("MemMap Address", "linux,uefi-mmap-start", mmap),
 	UEFI_PARAM("MemMap Size", "linux,uefi-mmap-size", mmap_size),
 	UEFI_PARAM("MemMap Desc. Size", "linux,uefi-mmap-desc-size", desc_size),
-	UEFI_PARAM("MemMap Desc. Version", "linux,uefi-mmap-desc-ver", desc_ver)
+	UEFI_PARAM("MemMap Desc. Version", "linux,uefi-mmap-desc-ver", desc_ver),
+	UEFI_PARAM("Secure Boot Enabled", "linux,uefi-secure-boot", secure_boot)
 };
 
 static __initdata struct params xen_fdt_params[] = {
@@ -918,40 +931,101 @@
 }
 #endif
 
+struct efi_error_code {
+	efi_status_t status;
+	int errno;
+	const char *description;
+};
+
+static const struct efi_error_code efi_error_codes[] = {
+	{ EFI_SUCCESS, 0, "Success"},
+#if 0
+	{ EFI_LOAD_ERROR, -EPICK_AN_ERRNO, "Load Error"},
+#endif
+	{ EFI_INVALID_PARAMETER, -EINVAL, "Invalid Parameter"},
+	{ EFI_UNSUPPORTED, -ENOSYS, "Unsupported"},
+	{ EFI_BAD_BUFFER_SIZE, -ENOSPC, "Bad Buffer Size"},
+	{ EFI_BUFFER_TOO_SMALL, -ENOSPC, "Buffer Too Small"},
+	{ EFI_NOT_READY, -EAGAIN, "Not Ready"},
+	{ EFI_DEVICE_ERROR, -EIO, "Device Error"},
+	{ EFI_WRITE_PROTECTED, -EROFS, "Write Protected"},
+	{ EFI_OUT_OF_RESOURCES, -ENOMEM, "Out of Resources"},
+#if 0
+	{ EFI_VOLUME_CORRUPTED, -EPICK_AN_ERRNO, "Volume Corrupt"},
+	{ EFI_VOLUME_FULL, -EPICK_AN_ERRNO, "Volume Full"},
+	{ EFI_NO_MEDIA, -EPICK_AN_ERRNO, "No Media"},
+	{ EFI_MEDIA_CHANGED, -EPICK_AN_ERRNO, "Media changed"},
+#endif
+	{ EFI_NOT_FOUND, -ENOENT, "Not Found"},
+#if 0
+	{ EFI_ACCESS_DENIED, -EPICK_AN_ERRNO, "Access Denied"},
+	{ EFI_NO_RESPONSE, -EPICK_AN_ERRNO, "No Response"},
+	{ EFI_NO_MAPPING, -EPICK_AN_ERRNO, "No mapping"},
+	{ EFI_TIMEOUT, -EPICK_AN_ERRNO, "Time out"},
+	{ EFI_NOT_STARTED, -EPICK_AN_ERRNO, "Not started"},
+	{ EFI_ALREADY_STARTED, -EPICK_AN_ERRNO, "Already started"},
+#endif
+	{ EFI_ABORTED, -EINTR, "Aborted"},
+#if 0
+	{ EFI_ICMP_ERROR, -EPICK_AN_ERRNO, "ICMP Error"},
+	{ EFI_TFTP_ERROR, -EPICK_AN_ERRNO, "TFTP Error"},
+	{ EFI_PROTOCOL_ERROR, -EPICK_AN_ERRNO, "Protocol Error"},
+	{ EFI_INCOMPATIBLE_VERSION, -EPICK_AN_ERRNO, "Incompatible Version"},
+#endif
+	{ EFI_SECURITY_VIOLATION, -EACCES, "Security Policy Violation"},
+#if 0
+	{ EFI_CRC_ERROR, -EPICK_AN_ERRNO, "CRC Error"},
+	{ EFI_END_OF_MEDIA, -EPICK_AN_ERRNO, "End of Media"},
+	{ EFI_END_OF_FILE, -EPICK_AN_ERRNO, "End of File"},
+	{ EFI_INVALID_LANGUAGE, -EPICK_AN_ERRNO, "Invalid Languages"},
+	{ EFI_COMPROMISED_DATA, -EPICK_AN_ERRNO, "Compromised Data"},
+
+	// warnings
+	{ EFI_WARN_UNKOWN_GLYPH, -EPICK_AN_ERRNO, "Warning Unknown Glyph"},
+	{ EFI_WARN_DELETE_FAILURE, -EPICK_AN_ERRNO, "Warning Delete Failure"},
+	{ EFI_WARN_WRITE_FAILURE, -EPICK_AN_ERRNO, "Warning Write Failure"},
+	{ EFI_WARN_BUFFER_TOO_SMALL, -EPICK_AN_ERRNO, "Warning Buffer Too Small"},
+#endif
+};
+
+static int
+efi_status_cmp_bsearch(const void *key, const void *item)
+{
+	u64 status = (u64)(uintptr_t)key;
+	struct efi_error_code *code = (struct efi_error_code *)item;
+
+	if (status < code->status)
+		return -1;
+	if (status > code->status)
+		return 1;
+	return 0;
+}
+
 int efi_status_to_err(efi_status_t status)
 {
-	int err;
+	struct efi_error_code *found;
+	size_t num = sizeof(efi_error_codes) / sizeof(struct efi_error_code);
 
-	switch (status) {
-	case EFI_SUCCESS:
-		err = 0;
-		break;
-	case EFI_INVALID_PARAMETER:
-		err = -EINVAL;
-		break;
-	case EFI_OUT_OF_RESOURCES:
-		err = -ENOSPC;
-		break;
-	case EFI_DEVICE_ERROR:
-		err = -EIO;
-		break;
-	case EFI_WRITE_PROTECTED:
-		err = -EROFS;
-		break;
-	case EFI_SECURITY_VIOLATION:
-		err = -EACCES;
-		break;
-	case EFI_NOT_FOUND:
-		err = -ENOENT;
-		break;
-	case EFI_ABORTED:
-		err = -EINTR;
-		break;
-	default:
-		err = -EINVAL;
-	}
+	found = bsearch((void *)(uintptr_t)status, efi_error_codes,
+			sizeof(struct efi_error_code), num,
+			efi_status_cmp_bsearch);
+	if (!found)
+		return -EINVAL;
+	return found->errno;
+}
+
+const char *
+efi_status_to_str(efi_status_t status)
+{
+	struct efi_error_code *found;
+	size_t num = sizeof(efi_error_codes) / sizeof(struct efi_error_code);
 
-	return err;
+	found = bsearch((void *)(uintptr_t)status, efi_error_codes,
+			sizeof(struct efi_error_code), num,
+			efi_status_cmp_bsearch);
+	if (!found)
+		return "Unknown error code";
+	return found->description;
 }
 
 static DEFINE_SPINLOCK(efi_mem_reserve_persistent_lock);
@@ -970,6 +1044,35 @@
 	return 0;
 }
 
+static int efi_mem_reserve_iomem(phys_addr_t addr, u64 size)
+{
+	struct resource *res, *parent;
+	int ret;
+
+	res = kzalloc(sizeof(struct resource), GFP_ATOMIC);
+	if (!res)
+		return -ENOMEM;
+
+	res->name	= "reserved";
+	res->flags	= IORESOURCE_MEM;
+	res->start	= addr;
+	res->end	= addr + size - 1;
+
+	/* we expect a conflict with a 'System RAM' region */
+	parent = request_resource_conflict(&iomem_resource, res);
+	ret = parent ? request_resource(parent, res) : 0;
+
+	/*
+	 * Given that efi_mem_reserve_iomem() can be called at any
+	 * time, only call memblock_reserve() if the architecture
+	 * keeps the infrastructure around.
+	 */
+	if (IS_ENABLED(CONFIG_ARCH_KEEP_MEMBLOCK) && !ret)
+		memblock_reserve(addr, size);
+
+	return ret;
+}
+
 int __ref efi_mem_reserve_persistent(phys_addr_t addr, u64 size)
 {
 	struct linux_efi_memreserve *rsv;
@@ -986,16 +1089,19 @@
 	}
 
 	/* first try to find a slot in an existing linked list entry */
-	for (prsv = efi_memreserve_root->next; prsv; prsv = rsv->next) {
+	for (prsv = efi_memreserve_root->next; prsv; ) {
 		rsv = memremap(prsv, sizeof(*rsv), MEMREMAP_WB);
+		if (!rsv)
+			return -ENOMEM;
 		index = atomic_fetch_add_unless(&rsv->count, 1, rsv->size);
 		if (index < rsv->size) {
 			rsv->entry[index].base = addr;
 			rsv->entry[index].size = size;
 
 			memunmap(rsv);
-			return 0;
+			return efi_mem_reserve_iomem(addr, size);
 		}
+		prsv = rsv->next;
 		memunmap(rsv);
 	}
 
@@ -1004,6 +1110,12 @@
 	if (!rsv)
 		return -ENOMEM;
 
+	rc = efi_mem_reserve_iomem(__pa(rsv), SZ_4K);
+	if (rc) {
+		free_page((unsigned long)rsv);
+		return rc;
+	}
+
 	/*
 	 * The memremap() call above assumes that a linux_efi_memreserve entry
 	 * never crosses a page boundary, so let's ensure that this remains true
@@ -1020,7 +1132,7 @@
 	efi_memreserve_root->next = __pa(rsv);
 	spin_unlock(&efi_mem_reserve_persistent_lock);
 
-	return 0;
+	return efi_mem_reserve_iomem(addr, size);
 }
 
 static int __init efi_memreserve_root_init(void)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/efi/efivars.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/efi/efivars.c
@@ -83,13 +83,16 @@
 efivar_attr_read(struct efivar_entry *entry, char *buf)
 {
 	struct efi_variable *var = &entry->var;
+	unsigned long size = sizeof(var->Data);
 	char *str = buf;
+	int ret;
 
 	if (!entry || !buf)
 		return -EINVAL;
 
-	var->DataSize = 1024;
-	if (efivar_entry_get(entry, &var->Attributes, &var->DataSize, var->Data))
+	ret = efivar_entry_get(entry, &var->Attributes, &size, var->Data);
+	var->DataSize = size;
+	if (ret)
 		return -EIO;
 
 	if (var->Attributes & EFI_VARIABLE_NON_VOLATILE)
@@ -116,13 +119,16 @@
 efivar_size_read(struct efivar_entry *entry, char *buf)
 {
 	struct efi_variable *var = &entry->var;
+	unsigned long size = sizeof(var->Data);
 	char *str = buf;
+	int ret;
 
 	if (!entry || !buf)
 		return -EINVAL;
 
-	var->DataSize = 1024;
-	if (efivar_entry_get(entry, &var->Attributes, &var->DataSize, var->Data))
+	ret = efivar_entry_get(entry, &var->Attributes, &size, var->Data);
+	var->DataSize = size;
+	if (ret)
 		return -EIO;
 
 	str += sprintf(str, "0x%lx\n", var->DataSize);
@@ -133,12 +139,15 @@
 efivar_data_read(struct efivar_entry *entry, char *buf)
 {
 	struct efi_variable *var = &entry->var;
+	unsigned long size = sizeof(var->Data);
+	int ret;
 
 	if (!entry || !buf)
 		return -EINVAL;
 
-	var->DataSize = 1024;
-	if (efivar_entry_get(entry, &var->Attributes, &var->DataSize, var->Data))
+	ret = efivar_entry_get(entry, &var->Attributes, &size, var->Data);
+	var->DataSize = size;
+	if (ret)
 		return -EIO;
 
 	memcpy(buf, var->Data, var->DataSize);
@@ -199,6 +208,9 @@
 	u8 *data;
 	int err;
 
+	if (!entry || !buf)
+		return -EINVAL;
+
 	if (in_compat_syscall()) {
 		struct compat_efi_variable *compat;
 
@@ -250,14 +262,16 @@
 {
 	struct efi_variable *var = &entry->var;
 	struct compat_efi_variable *compat;
+	unsigned long datasize = sizeof(var->Data);
 	size_t size;
+	int ret;
 
 	if (!entry || !buf)
 		return 0;
 
-	var->DataSize = 1024;
-	if (efivar_entry_get(entry, &entry->var.Attributes,
-			     &entry->var.DataSize, entry->var.Data))
+	ret = efivar_entry_get(entry, &var->Attributes, &datasize, var->Data);
+	var->DataSize = datasize;
+	if (ret)
 		return -EIO;
 
 	if (in_compat_syscall()) {
@@ -508,8 +522,10 @@
 	ret = kobject_init_and_add(&new_var->kobj, &efivar_ktype,
 				   NULL, "%s", short_name);
 	kfree(short_name);
-	if (ret)
+	if (ret) {
+		kobject_put(&new_var->kobj);
 		return ret;
+	}
 
 	kobject_uevent(&new_var->kobj, KOBJ_ADD);
 	if (efivar_entry_add(new_var, &efivar_sysfs_list)) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/efi/esrt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/efi/esrt.c
@@ -181,7 +181,7 @@
 		rc = kobject_init_and_add(&entry->kobj, &esre1_ktype, NULL,
 					  "entry%d", entry_num);
 		if (rc) {
-			kfree(entry);
+			kobject_put(&entry->kobj);
 			return rc;
 		}
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/efi/libstub/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/efi/libstub/Makefile
@@ -28,6 +28,7 @@
 				   -D__NO_FORTIFY \
 				   $(call cc-option,-ffreestanding) \
 				   $(call cc-option,-fno-stack-protector) \
+				   $(call cc-option,-fno-addrsig) \
 				   -D__DISABLE_EXPORTS
 
 GCOV_PROFILE			:= n
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/efi/libstub/arm-stub.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/efi/libstub/arm-stub.c
@@ -189,6 +189,8 @@
 		goto fail_free_cmdline;
 	}
 
+	efi_retrieve_tpm2_eventlog(sys_table);
+
 	/* Ask the firmware to clear memory on unclean shutdown */
 	efi_enable_reset_attack_mitigation(sys_table);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -46,7 +46,7 @@
 	return __novamap;
 }
 
-#define EFI_MMAP_NR_SLACK_SLOTS	8
+#define EFI_MMAP_NR_SLACK_SLOTS	16
 
 struct file_info {
 	efi_file_handle_t *handle;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/efi/libstub/fdt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/efi/libstub/fdt.c
@@ -151,6 +151,12 @@
 		}
 	}
 
+	fdt_val32 = cpu_to_fdt32(efi_get_secureboot(sys_table));
+	status = fdt_setprop(fdt, node, "linux,uefi-secure-boot",
+			     &fdt_val32, sizeof(fdt_val32));
+	if (status)
+		goto fdt_set_fail;
+
 	/* Shrink the FDT back to its minimum size: */
 	fdt_pack(fdt);
 
@@ -291,14 +297,6 @@
 		goto fail;
 	}
 
-	/*
-	 * Now that we have done our final memory allocation (and free)
-	 * we can get the memory map key needed for exit_boot_services().
-	 */
-	status = efi_get_memory_map(sys_table, &map);
-	if (status != EFI_SUCCESS)
-		goto fail_free_new_fdt;
-
 	status = update_fdt(sys_table, (void *)fdt_addr, fdt_size,
 			    (void *)*new_fdt_addr, MAX_FDT_SIZE, cmdline_ptr,
 			    initrd_addr, initrd_size);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/efi/libstub/gop.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/efi/libstub/gop.c
@@ -84,30 +84,6 @@
 }
 
 static efi_status_t
-__gop_query32(efi_system_table_t *sys_table_arg,
-	      struct efi_graphics_output_protocol_32 *gop32,
-	      struct efi_graphics_output_mode_info **info,
-	      unsigned long *size, u64 *fb_base)
-{
-	struct efi_graphics_output_protocol_mode_32 *mode;
-	efi_graphics_output_protocol_query_mode query_mode;
-	efi_status_t status;
-	unsigned long m;
-
-	m = gop32->mode;
-	mode = (struct efi_graphics_output_protocol_mode_32 *)m;
-	query_mode = (void *)(unsigned long)gop32->query_mode;
-
-	status = __efi_call_early(query_mode, (void *)gop32, mode->mode, size,
-				  info);
-	if (status != EFI_SUCCESS)
-		return status;
-
-	*fb_base = mode->frame_buffer_base;
-	return status;
-}
-
-static efi_status_t
 setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si,
             efi_guid_t *proto, unsigned long size, void **gop_handle)
 {
@@ -119,7 +95,7 @@
 	u64 fb_base;
 	struct efi_pixel_bitmask pixel_info;
 	int pixel_format;
-	efi_status_t status = EFI_NOT_FOUND;
+	efi_status_t status;
 	u32 *handles = (u32 *)(unsigned long)gop_handle;
 	int i;
 
@@ -128,6 +104,7 @@
 
 	nr_gops = size / sizeof(u32);
 	for (i = 0; i < nr_gops; i++) {
+		struct efi_graphics_output_protocol_mode_32 *mode;
 		struct efi_graphics_output_mode_info *info = NULL;
 		efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
 		bool conout_found = false;
@@ -145,9 +122,11 @@
 		if (status == EFI_SUCCESS)
 			conout_found = true;
 
-		status = __gop_query32(sys_table_arg, gop32, &info, &size,
-				       &current_fb_base);
-		if (status == EFI_SUCCESS && (!first_gop || conout_found) &&
+		mode = (void *)(unsigned long)gop32->mode;
+		info = (void *)(unsigned long)mode->info;
+		current_fb_base = mode->frame_buffer_base;
+
+		if ((!first_gop || conout_found) &&
 		    info->pixel_format != PIXEL_BLT_ONLY) {
 			/*
 			 * Systems that use the UEFI Console Splitter may
@@ -175,7 +154,7 @@
 
 	/* Did we find any GOPs? */
 	if (!first_gop)
-		goto out;
+		return EFI_NOT_FOUND;
 
 	/* EFI framebuffer */
 	si->orig_video_isVGA = VIDEO_TYPE_EFI;
@@ -197,32 +176,8 @@
 	si->lfb_size = si->lfb_linelength * si->lfb_height;
 
 	si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS;
-out:
-	return status;
-}
-
-static efi_status_t
-__gop_query64(efi_system_table_t *sys_table_arg,
-	      struct efi_graphics_output_protocol_64 *gop64,
-	      struct efi_graphics_output_mode_info **info,
-	      unsigned long *size, u64 *fb_base)
-{
-	struct efi_graphics_output_protocol_mode_64 *mode;
-	efi_graphics_output_protocol_query_mode query_mode;
-	efi_status_t status;
-	unsigned long m;
 
-	m = gop64->mode;
-	mode = (struct efi_graphics_output_protocol_mode_64 *)m;
-	query_mode = (void *)(unsigned long)gop64->query_mode;
-
-	status = __efi_call_early(query_mode, (void *)gop64, mode->mode, size,
-				  info);
-	if (status != EFI_SUCCESS)
-		return status;
-
-	*fb_base = mode->frame_buffer_base;
-	return status;
+	return EFI_SUCCESS;
 }
 
 static efi_status_t
@@ -237,7 +192,7 @@
 	u64 fb_base;
 	struct efi_pixel_bitmask pixel_info;
 	int pixel_format;
-	efi_status_t status = EFI_NOT_FOUND;
+	efi_status_t status;
 	u64 *handles = (u64 *)(unsigned long)gop_handle;
 	int i;
 
@@ -246,6 +201,7 @@
 
 	nr_gops = size / sizeof(u64);
 	for (i = 0; i < nr_gops; i++) {
+		struct efi_graphics_output_protocol_mode_64 *mode;
 		struct efi_graphics_output_mode_info *info = NULL;
 		efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
 		bool conout_found = false;
@@ -263,9 +219,11 @@
 		if (status == EFI_SUCCESS)
 			conout_found = true;
 
-		status = __gop_query64(sys_table_arg, gop64, &info, &size,
-				       &current_fb_base);
-		if (status == EFI_SUCCESS && (!first_gop || conout_found) &&
+		mode = (void *)(unsigned long)gop64->mode;
+		info = (void *)(unsigned long)mode->info;
+		current_fb_base = mode->frame_buffer_base;
+
+		if ((!first_gop || conout_found) &&
 		    info->pixel_format != PIXEL_BLT_ONLY) {
 			/*
 			 * Systems that use the UEFI Console Splitter may
@@ -293,7 +251,7 @@
 
 	/* Did we find any GOPs? */
 	if (!first_gop)
-		goto out;
+		return EFI_NOT_FOUND;
 
 	/* EFI framebuffer */
 	si->orig_video_isVGA = VIDEO_TYPE_EFI;
@@ -315,8 +273,8 @@
 	si->lfb_size = si->lfb_linelength * si->lfb_height;
 
 	si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS;
-out:
-	return status;
+
+	return EFI_SUCCESS;
 }
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/efi/libstub/secureboot.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/efi/libstub/secureboot.c
@@ -19,7 +19,7 @@
 
 /* SHIM variables */
 static const efi_guid_t shim_guid = EFI_SHIM_LOCK_GUID;
-static const efi_char16_t shim_MokSBState_name[] = L"MokSBState";
+static const efi_char16_t shim_MokSBState_name[] = L"MokSBStateRT";
 
 #define get_efi_var(name, vendor, ...) \
 	efi_call_runtime(get_variable, \
@@ -58,8 +58,8 @@
 
 	/*
 	 * See if a user has put the shim into insecure mode. If so, and if the
-	 * variable doesn't have the runtime attribute set, we might as well
-	 * honor that.
+	 * variable doesn't have the non-volatile attribute set, we might as
+	 * well honor that.
 	 */
 	size = sizeof(moksbstate);
 	status = get_efi_var(shim_MokSBState_name, &shim_guid,
@@ -68,7 +68,7 @@
 	/* If it fails, we don't care why. Default to secure */
 	if (status != EFI_SUCCESS)
 		goto secure_boot_enabled;
-	if (!(attr & EFI_VARIABLE_RUNTIME_ACCESS) && moksbstate == 1)
+	if (!(attr & EFI_VARIABLE_NON_VOLATILE) && moksbstate == 1)
 		return efi_secureboot_mode_disabled;
 
 secure_boot_enabled:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/efi/libstub/tpm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/efi/libstub/tpm.c
@@ -64,7 +64,7 @@
 	efi_status_t status;
 	efi_physical_addr_t log_location = 0, log_last_entry = 0;
 	struct linux_efi_tpm_eventlog *log_tbl = NULL;
-	struct efi_tcg2_final_events_table *final_events_table;
+	struct efi_tcg2_final_events_table *final_events_table = NULL;
 	unsigned long first_entry_addr, last_entry_addr;
 	size_t log_size, last_entry_size;
 	efi_bool_t truncated;
@@ -140,7 +140,8 @@
 	 * Figure out whether any events have already been logged to the
 	 * final events structure, and if so how much space they take up
 	 */
-	final_events_table = get_efi_config_table(sys_table_arg,
+	if (version == EFI_TCG2_EVENT_LOG_FORMAT_TCG_2)
+		final_events_table = get_efi_config_table(sys_table_arg,
 						LINUX_EFI_TPM_FINAL_LOG_GUID);
 	if (final_events_table && final_events_table->nr_events) {
 		struct tcg_pcr_event2_head *header;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/efi/memattr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/efi/memattr.c
@@ -32,7 +32,7 @@
 		return -ENOMEM;
 	}
 
-	if (tbl->version > 1) {
+	if (tbl->version > 2) {
 		pr_warn("Unexpected EFI Memory Attributes table version %d\n",
 			tbl->version);
 		goto unmap;
@@ -66,11 +66,6 @@
 		return false;
 	}
 
-	if (!(in->attribute & (EFI_MEMORY_RO | EFI_MEMORY_XP))) {
-		pr_warn("Entry attributes invalid: RO and XP bits both cleared\n");
-		return false;
-	}
-
 	if (PAGE_SIZE > EFI_PAGE_SIZE &&
 	    (!PAGE_ALIGNED(in->phys_addr) ||
 	     !PAGE_ALIGNED(in->num_pages << EFI_PAGE_SHIFT))) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/efi/mokvar-table.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/efi/mokvar-table.c
@@ -0,0 +1,362 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * mokvar-table.c
+ *
+ * Copyright (c) 2020 Red Hat
+ * Author: Lenny Szubowicz <lszubowi@redhat.com>
+ *
+ * This module contains the kernel support for the Linux EFI Machine
+ * Owner Key (MOK) variable configuration table, which is identified by
+ * the LINUX_EFI_MOK_VARIABLE_TABLE_GUID.
+ *
+ * This EFI configuration table provides a more robust alternative to
+ * EFI volatile variables by which an EFI boot loader can pass the
+ * contents of the Machine Owner Key (MOK) certificate stores to the
+ * kernel during boot. If both the EFI MOK config table and corresponding
+ * EFI MOK variables are present, the table should be considered as
+ * more authoritative.
+ *
+ * This module includes code that validates and maps the EFI MOK table,
+ * if it's presence was detected very early in boot.
+ *
+ * Kernel interface routines are provided to walk through all the
+ * entries in the MOK config table or to search for a specific named
+ * entry.
+ *
+ * The contents of the individual named MOK config table entries are
+ * made available to user space via read-only sysfs binary files under:
+ *
+ * /sys/firmware/efi/mok-variables/
+ *
+ */
+#define pr_fmt(fmt) "mokvar: " fmt
+
+#include <linux/capability.h>
+#include <linux/efi.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/kobject.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+
+#include <asm/early_ioremap.h>
+
+/*
+ * The LINUX_EFI_MOK_VARIABLE_TABLE_GUID config table is a packed
+ * sequence of struct efi_mokvar_table_entry, one for each named
+ * MOK variable. The sequence is terminated by an entry with a
+ * completely NULL name and 0 data size.
+ *
+ * efi_mokvar_table_size is set to the computed size of the
+ * MOK config table by efi_mokvar_table_init(). This will be
+ * non-zero if and only if the table if present and has been
+ * validated by efi_mokvar_table_init().
+ */
+static size_t efi_mokvar_table_size;
+
+/*
+ * efi_mokvar_table_va is the kernel virtual address at which the
+ * EFI MOK config table has been mapped by efi_mokvar_sysfs_init().
+ */
+static struct efi_mokvar_table_entry *efi_mokvar_table_va;
+
+/*
+ * Each /sys/firmware/efi/mok-variables/ sysfs file is represented by
+ * an instance of struct efi_mokvar_sysfs_attr on efi_mokvar_sysfs_list.
+ * bin_attr.private points to the associated EFI MOK config table entry.
+ *
+ * This list is created during boot and then remains unchanged.
+ * So no synchronization is currently required to walk the list.
+ */
+struct efi_mokvar_sysfs_attr {
+	struct bin_attribute bin_attr;
+	struct list_head node;
+};
+
+static LIST_HEAD(efi_mokvar_sysfs_list);
+static struct kobject *mokvar_kobj;
+
+/*
+ * efi_mokvar_table_init() - Early boot validation of EFI MOK config table
+ *
+ * If present, validate and compute the size of the EFI MOK variable
+ * configuration table. This table may be provided by an EFI boot loader
+ * as an alternative to ordinary EFI variables, due to platform-dependent
+ * limitations. The memory occupied by this table is marked as reserved.
+ *
+ * This routine must be called before efi_free_boot_services() in order
+ * to guarantee that it can mark the table as reserved.
+ *
+ * Implicit inputs:
+ * efi.mokvar_table:	Physical address of EFI MOK variable config table
+ *			or special value that indicates no such table.
+ *
+ * Implicit outputs:
+ * efi_mokvar_table_size: Computed size of EFI MOK variable config table.
+ *			The table is considered present and valid if this
+ *			is non-zero.
+ */
+void __init efi_mokvar_table_init(void)
+{
+	efi_memory_desc_t md;
+	void *va = NULL;
+	unsigned long cur_offset = 0;
+	unsigned long offset_limit;
+	unsigned long map_size = 0;
+	unsigned long map_size_needed = 0;
+	unsigned long size;
+	struct efi_mokvar_table_entry *mokvar_entry;
+	int err;
+
+	if (!efi_enabled(EFI_MEMMAP))
+		return;
+
+	if (efi.mokvar_table == EFI_INVALID_TABLE_ADDR)
+		return;
+	/*
+	 * The EFI MOK config table must fit within a single EFI memory
+	 * descriptor range.
+	 */
+	err = efi_mem_desc_lookup(efi.mokvar_table, &md);
+	if (err) {
+		pr_warn("EFI MOKvar config table is not within the EFI memory map\n");
+		return;
+	}
+
+	offset_limit = efi_mem_desc_end(&md) - efi.mokvar_table;
+
+	/*
+	 * Validate the MOK config table. Since there is no table header
+	 * from which we could get the total size of the MOK config table,
+	 * we compute the total size as we validate each variably sized
+	 * entry, remapping as necessary.
+	 */
+	err = -EINVAL;
+	while (cur_offset + sizeof(*mokvar_entry) <= offset_limit) {
+		mokvar_entry = va + cur_offset;
+		map_size_needed = cur_offset + sizeof(*mokvar_entry);
+		if (map_size_needed > map_size) {
+			if (va)
+				early_memunmap(va, map_size);
+			/*
+			 * Map a little more than the fixed size entry
+			 * header, anticipating some data. It's safe to
+			 * do so as long as we stay within current memory
+			 * descriptor.
+			 */
+			map_size = min(map_size_needed + 2*EFI_PAGE_SIZE,
+				       offset_limit);
+			va = early_memremap(efi.mokvar_table, map_size);
+			if (!va) {
+				pr_err("Failed to map EFI MOKvar config table pa=0x%lx, size=%lu.\n",
+				       efi.mokvar_table, map_size);
+				return;
+			}
+			mokvar_entry = va + cur_offset;
+		}
+
+		/* Check for last sentinel entry */
+		if (mokvar_entry->name[0] == '\0') {
+			if (mokvar_entry->data_size != 0)
+				break;
+			err = 0;
+			break;
+		}
+
+		/* Sanity check that the name is null terminated */
+		size = strnlen(mokvar_entry->name,
+			       sizeof(mokvar_entry->name));
+		if (size >= sizeof(mokvar_entry->name))
+			break;
+
+		/* Advance to the next entry */
+		cur_offset = map_size_needed + mokvar_entry->data_size;
+	}
+
+	if (va)
+		early_memunmap(va, map_size);
+	if (err) {
+		pr_err("EFI MOKvar config table is not valid\n");
+		return;
+	}
+
+	if (md.type == EFI_BOOT_SERVICES_DATA)
+		efi_mem_reserve(efi.mokvar_table, map_size_needed);
+
+	efi_mokvar_table_size = map_size_needed;
+}
+
+/*
+ * efi_mokvar_entry_next() - Get next entry in the EFI MOK config table
+ *
+ * mokvar_entry:	Pointer to current EFI MOK config table entry
+ *			or null. Null indicates get first entry.
+ *			Passed by reference. This is updated to the
+ *			same value as the return value.
+ *
+ * Returns:		Pointer to next EFI MOK config table entry
+ *			or null, if there are no more entries.
+ *			Same value is returned in the mokvar_entry
+ *			parameter.
+ *
+ * This routine depends on the EFI MOK config table being entirely
+ * mapped with it's starting virtual address in efi_mokvar_table_va.
+ */
+struct efi_mokvar_table_entry *efi_mokvar_entry_next(
+			struct efi_mokvar_table_entry **mokvar_entry)
+{
+	struct efi_mokvar_table_entry *mokvar_cur;
+	struct efi_mokvar_table_entry *mokvar_next;
+	size_t size_cur;
+
+	mokvar_cur = *mokvar_entry;
+	*mokvar_entry = NULL;
+
+	if (efi_mokvar_table_va == NULL)
+		return NULL;
+
+	if (mokvar_cur == NULL) {
+		mokvar_next = efi_mokvar_table_va;
+	} else {
+		if (mokvar_cur->name[0] == '\0')
+			return NULL;
+		size_cur = sizeof(*mokvar_cur) + mokvar_cur->data_size;
+		mokvar_next = (void *)mokvar_cur + size_cur;
+	}
+
+	if (mokvar_next->name[0] == '\0')
+		return NULL;
+
+	*mokvar_entry = mokvar_next;
+	return mokvar_next;
+}
+
+/*
+ * efi_mokvar_entry_find() - Find EFI MOK config entry by name
+ *
+ * name:	Name of the entry to look for.
+ *
+ * Returns:	Pointer to EFI MOK config table entry if found;
+ *		null otherwise.
+ *
+ * This routine depends on the EFI MOK config table being entirely
+ * mapped with it's starting virtual address in efi_mokvar_table_va.
+ */
+struct efi_mokvar_table_entry *efi_mokvar_entry_find(const char *name)
+{
+	struct efi_mokvar_table_entry *mokvar_entry = NULL;
+
+	while (efi_mokvar_entry_next(&mokvar_entry)) {
+		if (!strncmp(name, mokvar_entry->name,
+			     sizeof(mokvar_entry->name)))
+			return mokvar_entry;
+	}
+	return NULL;
+}
+
+/*
+ * efi_mokvar_sysfs_read() - sysfs binary file read routine
+ *
+ * Returns:	Count of bytes read.
+ *
+ * Copy EFI MOK config table entry data for this mokvar sysfs binary file
+ * to the supplied buffer, starting at the specified offset into mokvar table
+ * entry data, for the specified count bytes. The copy is limited by the
+ * amount of data in this mokvar config table entry.
+ */
+static ssize_t efi_mokvar_sysfs_read(struct file *file, struct kobject *kobj,
+				 struct bin_attribute *bin_attr, char *buf,
+				 loff_t off, size_t count)
+{
+	struct efi_mokvar_table_entry *mokvar_entry = bin_attr->private;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return 0;
+
+	if (off >= mokvar_entry->data_size)
+		return 0;
+	if (count >  mokvar_entry->data_size - off)
+		count = mokvar_entry->data_size - off;
+
+	memcpy(buf, mokvar_entry->data + off, count);
+	return count;
+}
+
+/*
+ * efi_mokvar_sysfs_init() - Map EFI MOK config table and create sysfs
+ *
+ * Map the EFI MOK variable config table for run-time use by the kernel
+ * and create the sysfs entries in /sys/firmware/efi/mok-variables/
+ *
+ * This routine just returns if a valid EFI MOK variable config table
+ * was not found earlier during boot.
+ *
+ * This routine must be called during a "middle" initcall phase, i.e.
+ * after efi_mokvar_table_init() but before UEFI certs are loaded
+ * during late init.
+ *
+ * Implicit inputs:
+ * efi.mokvar_table:	Physical address of EFI MOK variable config table
+ *			or special value that indicates no such table.
+ *
+ * efi_mokvar_table_size: Computed size of EFI MOK variable config table.
+ *			The table is considered present and valid if this
+ *			is non-zero.
+ *
+ * Implicit outputs:
+ * efi_mokvar_table_va:	Start virtual address of the EFI MOK config table.
+ */
+static int __init efi_mokvar_sysfs_init(void)
+{
+	void *config_va;
+	struct efi_mokvar_table_entry *mokvar_entry = NULL;
+	struct efi_mokvar_sysfs_attr *mokvar_sysfs = NULL;
+	int err = 0;
+
+	if (efi_mokvar_table_size == 0)
+		return -ENOENT;
+
+	config_va = memremap(efi.mokvar_table, efi_mokvar_table_size,
+			     MEMREMAP_WB);
+	if (!config_va) {
+		pr_err("Failed to map EFI MOKvar config table\n");
+		return -ENOMEM;
+	}
+	efi_mokvar_table_va = config_va;
+
+	mokvar_kobj = kobject_create_and_add("mok-variables", efi_kobj);
+	if (!mokvar_kobj) {
+		pr_err("Failed to create EFI mok-variables sysfs entry\n");
+		return -ENOMEM;
+	}
+
+	while (efi_mokvar_entry_next(&mokvar_entry)) {
+		mokvar_sysfs = kzalloc(sizeof(*mokvar_sysfs), GFP_KERNEL);
+		if (!mokvar_sysfs) {
+			err = -ENOMEM;
+			break;
+		}
+
+		sysfs_bin_attr_init(&mokvar_sysfs->bin_attr);
+		mokvar_sysfs->bin_attr.private = mokvar_entry;
+		mokvar_sysfs->bin_attr.attr.name = mokvar_entry->name;
+		mokvar_sysfs->bin_attr.attr.mode = 0400;
+		mokvar_sysfs->bin_attr.size = mokvar_entry->data_size;
+		mokvar_sysfs->bin_attr.read = efi_mokvar_sysfs_read;
+
+		err = sysfs_create_bin_file(mokvar_kobj,
+					   &mokvar_sysfs->bin_attr);
+		if (err)
+			break;
+
+		list_add_tail(&mokvar_sysfs->node, &efi_mokvar_sysfs_list);
+	}
+
+	if (err) {
+		pr_err("Failed to create some EFI mok-variables sysfs entries\n");
+		kfree(mokvar_sysfs);
+	}
+	return err;
+}
+device_initcall(efi_mokvar_sysfs_init);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/efi/rci2-table.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/efi/rci2-table.c
@@ -81,6 +81,9 @@
 	struct kobject *tables_kobj;
 	int ret = -ENOMEM;
 
+	if (rci2_table_phys == EFI_INVALID_TABLE_ADDR)
+		return 0;
+
 	rci2_base = memremap(rci2_table_phys,
 			     sizeof(struct rci2_table_global_hdr),
 			     MEMREMAP_WB);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/efi/runtime-wrappers.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/efi/runtime-wrappers.c
@@ -62,6 +62,7 @@
 									\
 	if (!efi_enabled(EFI_RUNTIME_SERVICES)) {			\
 		pr_warn_once("EFI Runtime Services are disabled!\n");	\
+		efi_rts_work.status = EFI_DEVICE_ERROR;			\
 		goto exit;						\
 	}								\
 									\
@@ -414,7 +415,7 @@
 				  unsigned long data_size,
 				  efi_char16_t *data)
 {
-	if (down_interruptible(&efi_runtime_lock)) {
+	if (down_trylock(&efi_runtime_lock)) {
 		pr_warn("failed to invoke the reset_system() runtime service:\n"
 			"could not get exclusive access to the firmware\n");
 		return;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/efi/secureboot.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/efi/secureboot.c
@@ -0,0 +1,38 @@
+/* Core kernel secure boot support.
+ *
+ * Copyright (C) 2017 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/efi.h>
+#include <linux/kernel.h>
+#include <linux/printk.h>
+
+/*
+ * Decide what to do when UEFI secure boot mode is enabled.
+ */
+void __init efi_set_secure_boot(enum efi_secureboot_mode mode)
+{
+	if (efi_enabled(EFI_BOOT)) {
+		switch (mode) {
+		case efi_secureboot_mode_disabled:
+			pr_info("Secure boot disabled\n");
+			break;
+		case efi_secureboot_mode_enabled:
+			set_bit(EFI_SECURE_BOOT, &efi.flags);
+			pr_info("Secure boot enabled\n");
+			break;
+		default:
+			pr_warning("Secure boot could not be determined (mode %u)\n",
+				   mode);
+			break;
+		}
+	}
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/efi/tpm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/efi/tpm.c
@@ -16,7 +16,7 @@
 int efi_tpm_final_log_size;
 EXPORT_SYMBOL(efi_tpm_final_log_size);
 
-static int tpm2_calc_event_log_size(void *data, int count, void *size_info)
+static int __init tpm2_calc_event_log_size(void *data, int count, void *size_info)
 {
 	struct tcg_pcr_event2_head *header;
 	int event_size, size = 0;
@@ -40,7 +40,8 @@
 {
 	struct linux_efi_tpm_eventlog *log_tbl;
 	struct efi_tcg2_final_events_table *final_tbl;
-	int tbl_size;
+	unsigned int tbl_size;
+	int final_tbl_size;
 	int ret = 0;
 
 	if (efi.tpm_log == EFI_INVALID_TABLE_ADDR) {
@@ -62,8 +63,13 @@
 	tbl_size = sizeof(*log_tbl) + log_tbl->size;
 	memblock_reserve(efi.tpm_log, tbl_size);
 
-	if (efi.tpm_final_log == EFI_INVALID_TABLE_ADDR)
+	if (efi.tpm_final_log == EFI_INVALID_TABLE_ADDR) {
+		pr_info("TPM Final Events table not present\n");
 		goto out;
+	} else if (log_tbl->version != EFI_TCG2_EVENT_LOG_FORMAT_TCG_2) {
+		pr_warn(FW_BUG "TPM Final Events table invalid\n");
+		goto out;
+	}
 
 	final_tbl = early_memremap(efi.tpm_final_log, sizeof(*final_tbl));
 
@@ -75,26 +81,26 @@
 		goto out;
 	}
 
-	tbl_size = 0;
+	final_tbl_size = 0;
 	if (final_tbl->nr_events != 0) {
 		void *events = (void *)efi.tpm_final_log
 				+ sizeof(final_tbl->version)
 				+ sizeof(final_tbl->nr_events);
 
-		tbl_size = tpm2_calc_event_log_size(events,
-						    final_tbl->nr_events,
-						    log_tbl->log);
+		final_tbl_size = tpm2_calc_event_log_size(events,
+							  final_tbl->nr_events,
+							  log_tbl->log);
 	}
 
-	if (tbl_size < 0) {
+	if (final_tbl_size < 0) {
 		pr_err(FW_BUG "Failed to parse event in TPM Final Events Log\n");
 		ret = -EINVAL;
 		goto out_calc;
 	}
 
-	memblock_reserve((unsigned long)final_tbl,
-			 tbl_size + sizeof(*final_tbl));
-	efi_tpm_final_log_size = tbl_size;
+	memblock_reserve(efi.tpm_final_log,
+			 final_tbl_size + sizeof(*final_tbl));
+	efi_tpm_final_log_size = final_tbl_size;
 
 out_calc:
 	early_memunmap(final_tbl, sizeof(*final_tbl));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/efi/vars.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/efi/vars.c
@@ -427,7 +427,7 @@
 		void *data, bool duplicates, struct list_head *head)
 {
 	const struct efivar_operations *ops;
-	unsigned long variable_name_size = 1024;
+	unsigned long variable_name_size = 512;
 	efi_char16_t *variable_name;
 	efi_status_t status;
 	efi_guid_t vendor_guid;
@@ -450,12 +450,13 @@
 	}
 
 	/*
-	 * Per EFI spec, the maximum storage allocated for both
-	 * the variable name and variable data is 1024 bytes.
+	 * A small set of old UEFI implementations reject sizes
+	 * above a certain threshold, the lowest seen in the wild
+	 * is 512.
 	 */
 
 	do {
-		variable_name_size = 1024;
+		variable_name_size = 512;
 
 		status = ops->get_next_variable(&variable_name_size,
 						variable_name,
@@ -499,9 +500,13 @@
 			break;
 		case EFI_NOT_FOUND:
 			break;
+		case EFI_BUFFER_TOO_SMALL:
+			pr_warn("efivars: Variable name size exceeds maximum (%lu > 512)\n",
+				variable_name_size);
+			status = EFI_NOT_FOUND;
+			break;
 		default:
-			printk(KERN_WARNING "efivars: get_next_variable: status=%lx\n",
-				status);
+			pr_warn("efivars: get_next_variable: status=%lx\n", status);
 			status = EFI_NOT_FOUND;
 			break;
 		}
@@ -750,6 +755,7 @@
 {
 	const struct efivar_operations *ops;
 	efi_status_t status;
+	unsigned long varsize;
 
 	if (!__efivars)
 		return -EINVAL;
@@ -772,15 +778,17 @@
 		return efivar_entry_set_nonblocking(name, vendor, attributes,
 						    size, data);
 
+	varsize = size + ucs2_strsize(name, 1024);
 	if (!block) {
 		if (down_trylock(&efivars_lock))
 			return -EBUSY;
+		status = check_var_size_nonblocking(attributes, varsize);
 	} else {
 		if (down_interruptible(&efivars_lock))
 			return -EINTR;
+		status = check_var_size(attributes, varsize);
 	}
 
-	status = check_var_size(attributes, size + ucs2_strsize(name, 1024));
 	if (status != EFI_SUCCESS) {
 		up(&efivars_lock);
 		return -ENOSPC;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/google/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/google/Kconfig
@@ -3,9 +3,9 @@
 	bool "Google Firmware Drivers"
 	default n
 	help
-	  These firmware drivers are used by Google's servers.  They are
-	  only useful if you are working directly on one of their
-	  proprietary servers.  If in doubt, say "N".
+	  These firmware drivers are used by Google servers,
+	  Chromebooks and other devices using coreboot firmware.
+	  If in doubt, say "N".
 
 if GOOGLE_FIRMWARE
 
@@ -21,7 +21,7 @@
 
 config GOOGLE_COREBOOT_TABLE
 	tristate "Coreboot Table Access"
-	depends on ACPI || OF
+	depends on HAS_IOMEM && (ACPI || OF)
 	help
 	  This option enables the coreboot_table module, which provides other
 	  firmware modules access to the coreboot table. The coreboot table
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/google/coreboot_table.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/google/coreboot_table.c
@@ -152,20 +152,22 @@
 	if (!ptr)
 		return -ENOMEM;
 
-	ret = bus_register(&coreboot_bus_type);
-	if (!ret) {
-		ret = coreboot_table_populate(dev, ptr);
-		if (ret)
-			bus_unregister(&coreboot_bus_type);
-	}
+	ret = coreboot_table_populate(dev, ptr);
+
 	memunmap(ptr);
 
 	return ret;
 }
 
+static int __cb_dev_unregister(struct device *dev, void *dummy)
+{
+	device_unregister(dev);
+	return 0;
+}
+
 static int coreboot_table_remove(struct platform_device *pdev)
 {
-	bus_unregister(&coreboot_bus_type);
+	bus_for_each_dev(&coreboot_bus_type, NULL, NULL, __cb_dev_unregister);
 	return 0;
 }
 
@@ -195,6 +197,32 @@
 		.of_match_table = of_match_ptr(coreboot_of_match),
 	},
 };
-module_platform_driver(coreboot_table_driver);
+
+static int __init coreboot_table_driver_init(void)
+{
+	int ret;
+
+	ret = bus_register(&coreboot_bus_type);
+	if (ret)
+		return ret;
+
+	ret = platform_driver_register(&coreboot_table_driver);
+	if (ret) {
+		bus_unregister(&coreboot_bus_type);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void __exit coreboot_table_driver_exit(void)
+{
+	platform_driver_unregister(&coreboot_table_driver);
+	bus_unregister(&coreboot_bus_type);
+}
+
+module_init(coreboot_table_driver_init);
+module_exit(coreboot_table_driver_exit);
+
 MODULE_AUTHOR("Google, Inc.");
 MODULE_LICENSE("GPL");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/google/framebuffer-coreboot.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/google/framebuffer-coreboot.c
@@ -43,9 +43,7 @@
 		    fb->green_mask_pos     == formats[i].green.offset &&
 		    fb->green_mask_size    == formats[i].green.length &&
 		    fb->blue_mask_pos      == formats[i].blue.offset &&
-		    fb->blue_mask_size     == formats[i].blue.length &&
-		    fb->reserved_mask_pos  == formats[i].transp.offset &&
-		    fb->reserved_mask_size == formats[i].transp.length)
+		    fb->blue_mask_size     == formats[i].blue.length)
 			pdata.format = formats[i].name;
 	}
 	if (!pdata.format)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/google/gsmi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/google/gsmi.c
@@ -359,9 +359,10 @@
 		memcpy(data, gsmi_dev.data_buf->start, *data_size);
 
 		/* All variables are have the following attributes */
-		*attr = EFI_VARIABLE_NON_VOLATILE |
-			EFI_VARIABLE_BOOTSERVICE_ACCESS |
-			EFI_VARIABLE_RUNTIME_ACCESS;
+		if (attr)
+			*attr = EFI_VARIABLE_NON_VOLATILE |
+				EFI_VARIABLE_BOOTSERVICE_ACCESS |
+				EFI_VARIABLE_RUNTIME_ACCESS;
 	}
 
 	spin_unlock_irqrestore(&gsmi_dev.lock, flags);
@@ -679,6 +680,15 @@
 static int gsmi_panic_callback(struct notifier_block *nb,
 			       unsigned long reason, void *arg)
 {
+
+	/*
+	 * Panic callbacks are executed with all other CPUs stopped,
+	 * so we must not attempt to spin waiting for gsmi_dev.lock
+	 * to be released.
+	 */
+	if (spin_is_locked(&gsmi_dev.lock))
+		return NOTIFY_DONE;
+
 	gsmi_shutdown_reason(GSMI_SHUTDOWN_PANIC);
 	return NOTIFY_DONE;
 }
@@ -888,7 +898,8 @@
 	gsmi_dev.pdev = platform_device_register_full(&gsmi_dev_info);
 	if (IS_ERR(gsmi_dev.pdev)) {
 		printk(KERN_ERR "gsmi: unable to register platform device\n");
-		return PTR_ERR(gsmi_dev.pdev);
+		ret = PTR_ERR(gsmi_dev.pdev);
+		goto out_unregister;
 	}
 
 	/* SMI access needs to be serialized */
@@ -1015,6 +1026,10 @@
 	gsmi_buf_free(gsmi_dev.name_buf);
 	dma_pool_destroy(gsmi_dev.dma_pool);
 	platform_device_unregister(gsmi_dev.pdev);
+out_unregister:
+#ifdef CONFIG_PM
+	platform_driver_unregister(&gsmi_driver_info);
+#endif
 	pr_info("gsmi: failed to load: %d\n", ret);
 	return ret;
 }
@@ -1037,6 +1052,9 @@
 	gsmi_buf_free(gsmi_dev.name_buf);
 	dma_pool_destroy(gsmi_dev.dma_pool);
 	platform_device_unregister(gsmi_dev.pdev);
+#ifdef CONFIG_PM
+	platform_driver_unregister(&gsmi_driver_info);
+#endif
 }
 
 module_init(gsmi_init);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/imx/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/imx/Kconfig
@@ -13,6 +13,7 @@
 config IMX_SCU
 	bool "IMX SCU Protocol driver"
 	depends on IMX_MBOX
+	select SOC_BUS
 	help
 	  The System Controller Firmware (SCFW) is a low-level system function
 	  which runs on a dedicated Cortex-M core to provide power, clock, and
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/imx/imx-dsp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/imx/imx-dsp.c
@@ -114,7 +114,7 @@
 
 	dev_info(dev, "NXP i.MX DSP IPC initialized\n");
 
-	return devm_of_platform_populate(dev);
+	return 0;
 out:
 	kfree(chan_name);
 	for (j = 0; j < i; j++) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/imx/imx-scu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/imx/imx-scu.c
@@ -29,6 +29,7 @@
 	struct mbox_client cl;
 	struct mbox_chan *ch;
 	int idx;
+	struct completion tx_done;
 };
 
 struct imx_sc_ipc {
@@ -37,6 +38,7 @@
 	struct device *dev;
 	struct mutex lock;
 	struct completion done;
+	bool fast_ipc;
 
 	/* temporarily store the SCU msg */
 	u32 *msg;
@@ -100,12 +102,40 @@
 }
 EXPORT_SYMBOL(imx_scu_get_handle);
 
+/* Callback called when the word of a message is ack-ed, eg read by SCU */
+static void imx_scu_tx_done(struct mbox_client *cl, void *mssg, int r)
+{
+	struct imx_sc_chan *sc_chan = container_of(cl, struct imx_sc_chan, cl);
+
+	complete(&sc_chan->tx_done);
+}
+
 static void imx_scu_rx_callback(struct mbox_client *c, void *msg)
 {
 	struct imx_sc_chan *sc_chan = container_of(c, struct imx_sc_chan, cl);
 	struct imx_sc_ipc *sc_ipc = sc_chan->sc_ipc;
 	struct imx_sc_rpc_msg *hdr;
 	u32 *data = msg;
+	int i;
+
+	if (!sc_ipc->msg) {
+		dev_warn(sc_ipc->dev, "unexpected rx idx %d 0x%08x, ignore!\n",
+				sc_chan->idx, *data);
+		return;
+	}
+
+	if (sc_ipc->fast_ipc) {
+		hdr = msg;
+		sc_ipc->rx_size = hdr->size;
+		sc_ipc->msg[0] = *data++;
+
+		for (i = 1; i < sc_ipc->rx_size; i++)
+			sc_ipc->msg[i] = *data++;
+
+		complete(&sc_ipc->done);
+
+		return;
+	}
 
 	if (sc_chan->idx == 0) {
 		hdr = msg;
@@ -128,21 +158,38 @@
 
 static int imx_scu_ipc_write(struct imx_sc_ipc *sc_ipc, void *msg)
 {
-	struct imx_sc_rpc_msg *hdr = msg;
+	struct imx_sc_rpc_msg hdr = *(struct imx_sc_rpc_msg *)msg;
 	struct imx_sc_chan *sc_chan;
 	u32 *data = msg;
 	int ret;
+	int size;
 	int i;
 
 	/* Check size */
-	if (hdr->size > IMX_SC_RPC_MAX_MSG)
+	if (hdr.size > IMX_SC_RPC_MAX_MSG)
 		return -EINVAL;
 
-	dev_dbg(sc_ipc->dev, "RPC SVC %u FUNC %u SIZE %u\n", hdr->svc,
-		hdr->func, hdr->size);
+	dev_dbg(sc_ipc->dev, "RPC SVC %u FUNC %u SIZE %u\n", hdr.svc,
+		hdr.func, hdr.size);
 
-	for (i = 0; i < hdr->size; i++) {
+	size = sc_ipc->fast_ipc ? 1 : hdr.size;
+	for (i = 0; i < size; i++) {
 		sc_chan = &sc_ipc->chans[i % 4];
+
+		/*
+		 * SCU requires that all messages words are written
+		 * sequentially but linux MU driver implements multiple
+		 * independent channels for each register so ordering between
+		 * different channels must be ensured by SCU API interface.
+		 *
+		 * Wait for tx_done before every send to ensure that no
+		 * queueing happens at the mailbox channel level.
+		 */
+		if (!sc_ipc->fast_ipc) {
+			wait_for_completion(&sc_chan->tx_done);
+			reinit_completion(&sc_chan->tx_done);
+		}
+
 		ret = mbox_send_message(sc_chan->ch, &data[i]);
 		if (ret < 0)
 			return ret;
@@ -165,7 +212,8 @@
 	mutex_lock(&sc_ipc->lock);
 	reinit_completion(&sc_ipc->done);
 
-	sc_ipc->msg = msg;
+	if (have_resp)
+		sc_ipc->msg = msg;
 	sc_ipc->count = 0;
 	ret = imx_scu_ipc_write(sc_ipc, msg);
 	if (ret < 0) {
@@ -187,6 +235,7 @@
 	}
 
 out:
+	sc_ipc->msg = NULL;
 	mutex_unlock(&sc_ipc->lock);
 
 	dev_dbg(sc_ipc->dev, "RPC SVC done\n");
@@ -202,6 +251,8 @@
 	struct imx_sc_chan *sc_chan;
 	struct mbox_client *cl;
 	char *chan_name;
+	struct of_phandle_args args;
+	int num_channel;
 	int ret;
 	int i;
 
@@ -209,11 +260,21 @@
 	if (!sc_ipc)
 		return -ENOMEM;
 
-	for (i = 0; i < SCU_MU_CHAN_NUM; i++) {
-		if (i < 4)
+	ret = of_parse_phandle_with_args(pdev->dev.of_node, "mboxes",
+					 "#mbox-cells", 0, &args);
+	if (ret)
+		return ret;
+
+	sc_ipc->fast_ipc = of_device_is_compatible(args.np, "fsl,imx8-mu-scu");
+	of_node_put(args.np);
+
+	num_channel = sc_ipc->fast_ipc ? 2 : SCU_MU_CHAN_NUM;
+	for (i = 0; i < num_channel; i++) {
+		if (i < num_channel / 2)
 			chan_name = kasprintf(GFP_KERNEL, "tx%d", i);
 		else
-			chan_name = kasprintf(GFP_KERNEL, "rx%d", i - 4);
+			chan_name = kasprintf(GFP_KERNEL, "rx%d",
+					      i - num_channel / 2);
 
 		if (!chan_name)
 			return -ENOMEM;
@@ -225,14 +286,22 @@
 		cl->knows_txdone = true;
 		cl->rx_callback = imx_scu_rx_callback;
 
+		if (!sc_ipc->fast_ipc) {
+			/* Initial tx_done completion as "done" */
+			cl->tx_done = imx_scu_tx_done;
+			init_completion(&sc_chan->tx_done);
+			complete(&sc_chan->tx_done);
+		}
+
 		sc_chan->sc_ipc = sc_ipc;
-		sc_chan->idx = i % 4;
+		sc_chan->idx = i % (num_channel / 2);
 		sc_chan->ch = mbox_request_channel_byname(cl, chan_name);
 		if (IS_ERR(sc_chan->ch)) {
 			ret = PTR_ERR(sc_chan->ch);
 			if (ret != -EPROBE_DEFER)
 				dev_err(dev, "Failed to request mbox chan %s ret %d\n",
 					chan_name, ret);
+			kfree(chan_name);
 			return ret;
 		}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/imx/misc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/imx/misc.c
@@ -16,7 +16,7 @@
 	u32 ctrl;
 	u32 val;
 	u16 resource;
-} __packed;
+} __packed __aligned(4);
 
 struct imx_sc_msg_req_cpu_start {
 	struct imx_sc_rpc_msg hdr;
@@ -24,18 +24,18 @@
 	u32 address_lo;
 	u16 resource;
 	u8 enable;
-} __packed;
+} __packed __aligned(4);
 
 struct imx_sc_msg_req_misc_get_ctrl {
 	struct imx_sc_rpc_msg hdr;
 	u32 ctrl;
 	u16 resource;
-} __packed;
+} __packed __aligned(4);
 
 struct imx_sc_msg_resp_misc_get_ctrl {
 	struct imx_sc_rpc_msg hdr;
 	u32 val;
-} __packed;
+} __packed __aligned(4);
 
 /*
  * This function sets a miscellaneous control value.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/imx/scu-pd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/imx/scu-pd.c
@@ -61,7 +61,7 @@
 	struct imx_sc_rpc_msg hdr;
 	u16 resource;
 	u8 mode;
-} __packed;
+} __packed __aligned(4);
 
 #define IMX_SCU_PD_NAME_SIZE 20
 struct imx_sc_pm_domain {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/iscsi_ibft.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/iscsi_ibft.c
@@ -311,7 +311,10 @@
 		str += sprintf_ipaddr(str, nic->ip_addr);
 		break;
 	case ISCSI_BOOT_ETH_SUBNET_MASK:
-		val = cpu_to_be32(~((1 << (32-nic->subnet_mask_prefix))-1));
+		if (nic->subnet_mask_prefix > 32)
+			val = cpu_to_be32(~0);
+		else
+			val = cpu_to_be32(~((1 << (32-nic->subnet_mask_prefix))-1));
 		str += sprintf(str, "%pI4", &val);
 		break;
 	case ISCSI_BOOT_ETH_PREFIX_LEN:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/meson/meson_sm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/meson/meson_sm.c
@@ -54,8 +54,6 @@
 	void __iomem *sm_shmem_out_base;
 };
 
-static struct meson_sm_firmware fw;
-
 static u32 meson_sm_get_cmd(const struct meson_sm_chip *chip,
 			    unsigned int cmd_index)
 {
@@ -90,6 +88,7 @@
 /**
  * meson_sm_call - generic SMC32 call to the secure-monitor
  *
+ * @fw:		Pointer to secure-monitor firmware
  * @cmd_index:	Index of the SMC32 function ID
  * @ret:	Returned value
  * @arg0:	SMC32 Argument 0
@@ -100,15 +99,15 @@
  *
  * Return:	0 on success, a negative value on error
  */
-int meson_sm_call(unsigned int cmd_index, u32 *ret, u32 arg0,
-		  u32 arg1, u32 arg2, u32 arg3, u32 arg4)
+int meson_sm_call(struct meson_sm_firmware *fw, unsigned int cmd_index,
+		  u32 *ret, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
 {
 	u32 cmd, lret;
 
-	if (!fw.chip)
+	if (!fw->chip)
 		return -ENOENT;
 
-	cmd = meson_sm_get_cmd(fw.chip, cmd_index);
+	cmd = meson_sm_get_cmd(fw->chip, cmd_index);
 	if (!cmd)
 		return -EINVAL;
 
@@ -124,6 +123,7 @@
 /**
  * meson_sm_call_read - retrieve data from secure-monitor
  *
+ * @fw:		Pointer to secure-monitor firmware
  * @buffer:	Buffer to store the retrieved data
  * @bsize:	Size of the buffer
  * @cmd_index:	Index of the SMC32 function ID
@@ -137,22 +137,23 @@
  *		When 0 is returned there is no guarantee about the amount of
  *		data read and bsize bytes are copied in buffer.
  */
-int meson_sm_call_read(void *buffer, unsigned int bsize, unsigned int cmd_index,
-		       u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
+int meson_sm_call_read(struct meson_sm_firmware *fw, void *buffer,
+		       unsigned int bsize, unsigned int cmd_index, u32 arg0,
+		       u32 arg1, u32 arg2, u32 arg3, u32 arg4)
 {
 	u32 size;
 	int ret;
 
-	if (!fw.chip)
+	if (!fw->chip)
 		return -ENOENT;
 
-	if (!fw.chip->cmd_shmem_out_base)
+	if (!fw->chip->cmd_shmem_out_base)
 		return -EINVAL;
 
-	if (bsize > fw.chip->shmem_size)
+	if (bsize > fw->chip->shmem_size)
 		return -EINVAL;
 
-	if (meson_sm_call(cmd_index, &size, arg0, arg1, arg2, arg3, arg4) < 0)
+	if (meson_sm_call(fw, cmd_index, &size, arg0, arg1, arg2, arg3, arg4) < 0)
 		return -EINVAL;
 
 	if (size > bsize)
@@ -164,7 +165,7 @@
 		size = bsize;
 
 	if (buffer)
-		memcpy(buffer, fw.sm_shmem_out_base, size);
+		memcpy(buffer, fw->sm_shmem_out_base, size);
 
 	return ret;
 }
@@ -173,6 +174,7 @@
 /**
  * meson_sm_call_write - send data to secure-monitor
  *
+ * @fw:		Pointer to secure-monitor firmware
  * @buffer:	Buffer containing data to send
  * @size:	Size of the data to send
  * @cmd_index:	Index of the SMC32 function ID
@@ -184,23 +186,24 @@
  *
  * Return:	size of sent data on success, a negative value on error
  */
-int meson_sm_call_write(void *buffer, unsigned int size, unsigned int cmd_index,
-			u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
+int meson_sm_call_write(struct meson_sm_firmware *fw, void *buffer,
+			unsigned int size, unsigned int cmd_index, u32 arg0,
+			u32 arg1, u32 arg2, u32 arg3, u32 arg4)
 {
 	u32 written;
 
-	if (!fw.chip)
+	if (!fw->chip)
 		return -ENOENT;
 
-	if (size > fw.chip->shmem_size)
+	if (size > fw->chip->shmem_size)
 		return -EINVAL;
 
-	if (!fw.chip->cmd_shmem_in_base)
+	if (!fw->chip->cmd_shmem_in_base)
 		return -EINVAL;
 
-	memcpy(fw.sm_shmem_in_base, buffer, size);
+	memcpy(fw->sm_shmem_in_base, buffer, size);
 
-	if (meson_sm_call(cmd_index, &written, arg0, arg1, arg2, arg3, arg4) < 0)
+	if (meson_sm_call(fw, cmd_index, &written, arg0, arg1, arg2, arg3, arg4) < 0)
 		return -EINVAL;
 
 	if (!written)
@@ -210,6 +213,24 @@
 }
 EXPORT_SYMBOL(meson_sm_call_write);
 
+/**
+ * meson_sm_get - get pointer to meson_sm_firmware structure.
+ *
+ * @sm_node:		Pointer to the secure-monitor Device Tree node.
+ *
+ * Return:		NULL is the secure-monitor device is not ready.
+ */
+struct meson_sm_firmware *meson_sm_get(struct device_node *sm_node)
+{
+	struct platform_device *pdev = of_find_device_by_node(sm_node);
+
+	if (!pdev)
+		return NULL;
+
+	return platform_get_drvdata(pdev);
+}
+EXPORT_SYMBOL_GPL(meson_sm_get);
+
 #define SM_CHIP_ID_LENGTH	119
 #define SM_CHIP_ID_OFFSET	4
 #define SM_CHIP_ID_SIZE		12
@@ -217,14 +238,18 @@
 static ssize_t serial_show(struct device *dev, struct device_attribute *attr,
 			 char *buf)
 {
+	struct platform_device *pdev = to_platform_device(dev);
+	struct meson_sm_firmware *fw;
 	uint8_t *id_buf;
 	int ret;
 
+	fw = platform_get_drvdata(pdev);
+
 	id_buf = kmalloc(SM_CHIP_ID_LENGTH, GFP_KERNEL);
 	if (!id_buf)
 		return -ENOMEM;
 
-	ret = meson_sm_call_read(id_buf, SM_CHIP_ID_LENGTH, SM_GET_CHIP_ID,
+	ret = meson_sm_call_read(fw, id_buf, SM_CHIP_ID_LENGTH, SM_GET_CHIP_ID,
 				 0, 0, 0, 0, 0);
 	if (ret < 0) {
 		kfree(id_buf);
@@ -268,25 +293,36 @@
 
 static int __init meson_sm_probe(struct platform_device *pdev)
 {
+	struct device *dev = &pdev->dev;
 	const struct meson_sm_chip *chip;
+	struct meson_sm_firmware *fw;
 
-	chip = of_match_device(meson_sm_ids, &pdev->dev)->data;
+	fw = devm_kzalloc(dev, sizeof(*fw), GFP_KERNEL);
+	if (!fw)
+		return -ENOMEM;
+
+	chip = of_match_device(meson_sm_ids, dev)->data;
+	if (!chip)
+		return -EINVAL;
 
 	if (chip->cmd_shmem_in_base) {
-		fw.sm_shmem_in_base = meson_sm_map_shmem(chip->cmd_shmem_in_base,
-							 chip->shmem_size);
-		if (WARN_ON(!fw.sm_shmem_in_base))
+		fw->sm_shmem_in_base = meson_sm_map_shmem(chip->cmd_shmem_in_base,
+							  chip->shmem_size);
+		if (WARN_ON(!fw->sm_shmem_in_base))
 			goto out;
 	}
 
 	if (chip->cmd_shmem_out_base) {
-		fw.sm_shmem_out_base = meson_sm_map_shmem(chip->cmd_shmem_out_base,
-							  chip->shmem_size);
-		if (WARN_ON(!fw.sm_shmem_out_base))
+		fw->sm_shmem_out_base = meson_sm_map_shmem(chip->cmd_shmem_out_base,
+							   chip->shmem_size);
+		if (WARN_ON(!fw->sm_shmem_out_base))
 			goto out_in_base;
 	}
 
-	fw.chip = chip;
+	fw->chip = chip;
+
+	platform_set_drvdata(pdev, fw);
+
 	pr_info("secure-monitor enabled\n");
 
 	if (sysfs_create_group(&pdev->dev.kobj, &meson_sm_sysfs_attr_group))
@@ -295,7 +331,7 @@
 	return 0;
 
 out_in_base:
-	iounmap(fw.sm_shmem_in_base);
+	iounmap(fw->sm_shmem_in_base);
 out:
 	return -EINVAL;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/psci/psci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/psci/psci.c
@@ -57,6 +57,21 @@
 	.smccc_version = SMCCC_VERSION_1_0,
 };
 
+enum arm_smccc_conduit arm_smccc_1_1_get_conduit(void)
+{
+	if (psci_ops.smccc_version < SMCCC_VERSION_1_1)
+		return SMCCC_CONDUIT_NONE;
+
+	switch (psci_ops.conduit) {
+	case PSCI_CONDUIT_SMC:
+		return SMCCC_CONDUIT_SMC;
+	case PSCI_CONDUIT_HVC:
+		return SMCCC_CONDUIT_HVC;
+	default:
+		return SMCCC_CONDUIT_NONE;
+	}
+}
+
 typedef unsigned long (psci_fn)(unsigned long, unsigned long,
 				unsigned long, unsigned long);
 static psci_fn *invoke_psci_fn;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/psci/psci_checker.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/psci/psci_checker.c
@@ -155,10 +155,12 @@
 	if (!alloc_cpumask_var(&tmp, GFP_KERNEL))
 		return -ENOMEM;
 
-	cpu_groups = kcalloc(nb_available_cpus, sizeof(cpu_groups),
+	cpu_groups = kcalloc(nb_available_cpus, sizeof(*cpu_groups),
 			     GFP_KERNEL);
-	if (!cpu_groups)
+	if (!cpu_groups) {
+		free_cpumask_var(tmp);
 		return -ENOMEM;
+	}
 
 	cpumask_copy(tmp, cpu_online_mask);
 
@@ -167,6 +169,7 @@
 			topology_core_cpumask(cpumask_any(tmp));
 
 		if (!alloc_cpumask_var(&cpu_groups[num_groups], GFP_KERNEL)) {
+			free_cpumask_var(tmp);
 			free_cpu_groups(num_groups, &cpu_groups);
 			return -ENOMEM;
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/qcom_scm-64.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/qcom_scm-64.c
@@ -150,7 +150,7 @@
 		kfree(args_virt);
 	}
 
-	if (res->a0 < 0)
+	if ((long)res->a0 < 0)
 		return qcom_scm_remap_error(res->a0);
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/qcom_scm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/qcom_scm.c
@@ -9,7 +9,6 @@
 #include <linux/init.h>
 #include <linux/cpumask.h>
 #include <linux/export.h>
-#include <linux/dma-direct.h>
 #include <linux/dma-mapping.h>
 #include <linux/module.h>
 #include <linux/types.h>
@@ -441,8 +440,7 @@
 	struct qcom_scm_mem_map_info *mem_to_map;
 	phys_addr_t mem_to_map_phys;
 	phys_addr_t dest_phys;
-	phys_addr_t ptr_phys;
-	dma_addr_t ptr_dma;
+	dma_addr_t ptr_phys;
 	size_t mem_to_map_sz;
 	size_t dest_sz;
 	size_t src_sz;
@@ -459,10 +457,9 @@
 	ptr_sz = ALIGN(src_sz, SZ_64) + ALIGN(mem_to_map_sz, SZ_64) +
 			ALIGN(dest_sz, SZ_64);
 
-	ptr = dma_alloc_coherent(__scm->dev, ptr_sz, &ptr_dma, GFP_KERNEL);
+	ptr = dma_alloc_coherent(__scm->dev, ptr_sz, &ptr_phys, GFP_KERNEL);
 	if (!ptr)
 		return -ENOMEM;
-	ptr_phys = dma_to_phys(__scm->dev, ptr_dma);
 
 	/* Fill source vmid detail */
 	src = ptr;
@@ -490,7 +487,7 @@
 
 	ret = __qcom_scm_assign_mem(__scm->dev, mem_to_map_phys, mem_to_map_sz,
 				    ptr_phys, src_sz, dest_phys, dest_sz);
-	dma_free_coherent(__scm->dev, ptr_sz, ptr, ptr_dma);
+	dma_free_coherent(__scm->dev, ptr_sz, ptr, ptr_phys);
 	if (ret) {
 		dev_err(__scm->dev,
 			"Assign memory protection call failed %d\n", ret);
@@ -588,8 +585,7 @@
 static void qcom_scm_shutdown(struct platform_device *pdev)
 {
 	/* Clean shutdown, disable download mode to allow normal restart */
-	if (download_mode)
-		qcom_scm_set_download_mode(false);
+	qcom_scm_set_download_mode(false);
 }
 
 static const struct of_device_id qcom_scm_dt_match[] = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/qemu_fw_cfg.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/qemu_fw_cfg.c
@@ -296,15 +296,13 @@
 	return 0;
 }
 
-static ssize_t fw_cfg_showrev(struct kobject *k, struct attribute *a, char *buf)
+static ssize_t fw_cfg_showrev(struct kobject *k, struct kobj_attribute *a,
+			      char *buf)
 {
 	return sprintf(buf, "%u\n", fw_cfg_rev);
 }
 
-static const struct {
-	struct attribute attr;
-	ssize_t (*show)(struct kobject *k, struct attribute *a, char *buf);
-} fw_cfg_rev_attr = {
+static const struct kobj_attribute fw_cfg_rev_attr = {
 	.attr = { .name = "rev", .mode = S_IRUSR },
 	.show = fw_cfg_showrev,
 };
@@ -387,9 +385,7 @@
 	struct fw_cfg_sysfs_entry *entry, *next;
 
 	list_for_each_entry_safe(entry, next, &fw_cfg_entry_cache, list) {
-		/* will end up invoking fw_cfg_sysfs_cache_delist()
-		 * via each object's release() method (i.e. destructor)
-		 */
+		fw_cfg_sysfs_cache_delist(entry);
 		kobject_put(&entry->kobj);
 	}
 }
@@ -447,7 +443,6 @@
 {
 	struct fw_cfg_sysfs_entry *entry = to_entry(kobj);
 
-	fw_cfg_sysfs_cache_delist(entry);
 	kfree(entry);
 }
 
@@ -600,18 +595,18 @@
 	/* set file entry information */
 	entry->size = be32_to_cpu(f->size);
 	entry->select = be16_to_cpu(f->select);
-	memcpy(entry->name, f->name, FW_CFG_MAX_FILE_PATH);
+	strscpy(entry->name, f->name, FW_CFG_MAX_FILE_PATH);
 
 	/* register entry under "/sys/firmware/qemu_fw_cfg/by_key/" */
 	err = kobject_init_and_add(&entry->kobj, &fw_cfg_sysfs_entry_ktype,
 				   fw_cfg_sel_ko, "%d", entry->select);
 	if (err)
-		goto err_register;
+		goto err_put_entry;
 
 	/* add raw binary content access */
 	err = sysfs_create_bin_file(&entry->kobj, &fw_cfg_sysfs_attr_raw);
 	if (err)
-		goto err_add_raw;
+		goto err_del_entry;
 
 	/* try adding "/sys/firmware/qemu_fw_cfg/by_name/" symlink */
 	fw_cfg_build_symlink(fw_cfg_fname_kset, &entry->kobj, entry->name);
@@ -620,10 +615,10 @@
 	fw_cfg_sysfs_cache_enlist(entry);
 	return 0;
 
-err_add_raw:
+err_del_entry:
 	kobject_del(&entry->kobj);
-err_register:
-	kfree(entry);
+err_put_entry:
+	kobject_put(&entry->kobj);
 	return err;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/raspberrypi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/raspberrypi.c
@@ -7,7 +7,9 @@
  */
 
 #include <linux/dma-mapping.h>
+#include <linux/kref.h>
 #include <linux/mailbox_client.h>
+#include <linux/mailbox_controller.h>
 #include <linux/module.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
@@ -27,6 +29,8 @@
 	struct mbox_chan *chan; /* The property channel. */
 	struct completion c;
 	u32 enabled;
+
+	struct kref consumers;
 };
 
 static DEFINE_MUTEX(transaction_lock);
@@ -93,8 +97,8 @@
 	if (size & 3)
 		return -EINVAL;
 
-	buf = dma_alloc_coherent(fw->cl.dev, PAGE_ALIGN(size), &bus_addr,
-				 GFP_ATOMIC);
+	buf = dma_alloc_coherent(fw->chan->mbox->dev, PAGE_ALIGN(size),
+				 &bus_addr, GFP_ATOMIC);
 	if (!buf)
 		return -ENOMEM;
 
@@ -122,7 +126,7 @@
 		ret = -EINVAL;
 	}
 
-	dma_free_coherent(fw->cl.dev, PAGE_ALIGN(size), buf, bus_addr);
+	dma_free_coherent(fw->chan->mbox->dev, PAGE_ALIGN(size), buf, bus_addr);
 
 	return ret;
 }
@@ -214,12 +218,38 @@
 						-1, NULL, 0);
 }
 
+static void rpi_firmware_delete(struct kref *kref)
+{
+	struct rpi_firmware *fw = container_of(kref, struct rpi_firmware,
+					       consumers);
+
+	mbox_free_channel(fw->chan);
+	kfree(fw);
+}
+
+void rpi_firmware_put(struct rpi_firmware *fw)
+{
+	kref_put(&fw->consumers, rpi_firmware_delete);
+}
+EXPORT_SYMBOL_GPL(rpi_firmware_put);
+
+static void devm_rpi_firmware_put(void *data)
+{
+	struct rpi_firmware *fw = data;
+
+	rpi_firmware_put(fw);
+}
+
 static int rpi_firmware_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct rpi_firmware *fw;
 
-	fw = devm_kzalloc(dev, sizeof(*fw), GFP_KERNEL);
+	/*
+	 * Memory will be freed by rpi_firmware_delete() once all users have
+	 * released their firmware handles. Don't use devm_kzalloc() here.
+	 */
+	fw = kzalloc(sizeof(*fw), GFP_KERNEL);
 	if (!fw)
 		return -ENOMEM;
 
@@ -232,10 +262,12 @@
 		int ret = PTR_ERR(fw->chan);
 		if (ret != -EPROBE_DEFER)
 			dev_err(dev, "Failed to get mbox channel: %d\n", ret);
+		kfree(fw);
 		return ret;
 	}
 
 	init_completion(&fw->c);
+	kref_init(&fw->consumers);
 
 	platform_set_drvdata(pdev, fw);
 
@@ -264,7 +296,8 @@
 	rpi_hwmon = NULL;
 	platform_device_unregister(rpi_clk);
 	rpi_clk = NULL;
-	mbox_free_channel(fw->chan);
+
+	rpi_firmware_put(fw);
 
 	return 0;
 }
@@ -273,19 +306,51 @@
  * rpi_firmware_get - Get pointer to rpi_firmware structure.
  * @firmware_node:    Pointer to the firmware Device Tree node.
  *
+ * The reference to rpi_firmware has to be released with rpi_firmware_put().
+ *
  * Returns NULL is the firmware device is not ready.
  */
 struct rpi_firmware *rpi_firmware_get(struct device_node *firmware_node)
 {
 	struct platform_device *pdev = of_find_device_by_node(firmware_node);
+	struct rpi_firmware *fw;
 
 	if (!pdev)
 		return NULL;
 
-	return platform_get_drvdata(pdev);
+	fw = platform_get_drvdata(pdev);
+	if (!fw)
+		return NULL;
+
+	if (!kref_get_unless_zero(&fw->consumers))
+		return NULL;
+
+	return fw;
 }
 EXPORT_SYMBOL_GPL(rpi_firmware_get);
 
+/**
+ * devm_rpi_firmware_get - Get pointer to rpi_firmware structure.
+ * @firmware_node:    Pointer to the firmware Device Tree node.
+ *
+ * Returns NULL is the firmware device is not ready.
+ */
+struct rpi_firmware *devm_rpi_firmware_get(struct device *dev,
+					   struct device_node *firmware_node)
+{
+	struct rpi_firmware *fw;
+
+	fw = rpi_firmware_get(firmware_node);
+	if (!fw)
+		return NULL;
+
+	if (devm_add_action_or_reset(dev, devm_rpi_firmware_put, fw))
+		return NULL;
+
+	return fw;
+}
+EXPORT_SYMBOL_GPL(devm_rpi_firmware_get);
+
 static const struct of_device_id rpi_firmware_of_match[] = {
 	{ .compatible = "raspberrypi,bcm2835-firmware", },
 	{},
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/scpi_pm_domain.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/scpi_pm_domain.c
@@ -16,7 +16,6 @@
 	struct generic_pm_domain genpd;
 	struct scpi_ops *ops;
 	u32 domain;
-	char name[30];
 };
 
 /*
@@ -110,8 +109,13 @@
 
 		scpi_pd->domain = i;
 		scpi_pd->ops = scpi_ops;
-		sprintf(scpi_pd->name, "%pOFn.%d", np, i);
-		scpi_pd->genpd.name = scpi_pd->name;
+		scpi_pd->genpd.name = devm_kasprintf(dev, GFP_KERNEL,
+						     "%pOFn.%d", np, i);
+		if (!scpi_pd->genpd.name) {
+			dev_err(dev, "Failed to allocate genpd name:%pOFn.%d\n",
+				np, i);
+			continue;
+		}
 		scpi_pd->genpd.power_off = scpi_pd_power_off;
 		scpi_pd->genpd.power_on = scpi_pd_power_on;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/stratix10-svc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/stratix10-svc.c
@@ -615,8 +615,8 @@
 	end = rounddown(sh_memory->addr + sh_memory->size, PAGE_SIZE);
 	paddr = begin;
 	size = end - begin;
-	va = memremap(paddr, size, MEMREMAP_WC);
-	if (!va) {
+	va = devm_memremap(dev, paddr, size, MEMREMAP_WC);
+	if (IS_ERR(va)) {
 		dev_err(dev, "fail to remap shared memory\n");
 		return ERR_PTR(-EINVAL);
 	}
@@ -934,17 +934,17 @@
 void stratix10_svc_free_memory(struct stratix10_svc_chan *chan, void *kaddr)
 {
 	struct stratix10_svc_data_mem *pmem;
-	size_t size = 0;
 
 	list_for_each_entry(pmem, &svc_data_mem, node)
 		if (pmem->vaddr == kaddr) {
-			size = pmem->size;
-			break;
+			gen_pool_free(chan->ctrl->genpool,
+				       (unsigned long)kaddr, pmem->size);
+			pmem->vaddr = NULL;
+			list_del(&pmem->node);
+			return;
 		}
 
-	gen_pool_free(chan->ctrl->genpool, (unsigned long)kaddr, size);
-	pmem->vaddr = NULL;
-	list_del(&pmem->node);
+	list_del(&svc_data_mem);
 }
 EXPORT_SYMBOL_GPL(stratix10_svc_free_memory);
 
@@ -981,8 +981,8 @@
 		return ret;
 
 	genpool = svc_create_memory_pool(pdev, sh_memory);
-	if (!genpool)
-		return -ENOMEM;
+	if (IS_ERR(genpool))
+		return PTR_ERR(genpool);
 
 	/* allocate service controller and supporting channel */
 	controller = devm_kzalloc(dev, sizeof(*controller), GFP_KERNEL);
@@ -1026,24 +1026,32 @@
 
 	/* add svc client device(s) */
 	svc = devm_kzalloc(dev, sizeof(*svc), GFP_KERNEL);
-	if (!svc)
-		return -ENOMEM;
+	if (!svc) {
+		ret = -ENOMEM;
+		goto err_free_kfifo;
+	}
 
 	svc->stratix10_svc_rsu = platform_device_alloc(STRATIX10_RSU, 0);
 	if (!svc->stratix10_svc_rsu) {
 		dev_err(dev, "failed to allocate %s device\n", STRATIX10_RSU);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto err_free_kfifo;
 	}
 
 	ret = platform_device_add(svc->stratix10_svc_rsu);
-	if (ret) {
-		platform_device_put(svc->stratix10_svc_rsu);
-		return ret;
-	}
+	if (ret)
+		goto err_put_device;
+
 	dev_set_drvdata(dev, svc);
 
 	pr_info("Intel Service Layer Driver Initialized\n");
 
+	return 0;
+
+err_put_device:
+	platform_device_put(svc->stratix10_svc_rsu);
+err_free_kfifo:
+	kfifo_free(&controller->svc_fifo);
 	return ret;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/tegra/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/tegra/Makefile
@@ -3,6 +3,7 @@
 tegra-bpmp-$(CONFIG_ARCH_TEGRA_210_SOC)	+= bpmp-tegra210.o
 tegra-bpmp-$(CONFIG_ARCH_TEGRA_186_SOC)	+= bpmp-tegra186.o
 tegra-bpmp-$(CONFIG_ARCH_TEGRA_194_SOC)	+= bpmp-tegra186.o
+tegra-bpmp-$(CONFIG_ARCH_TEGRA_234_SOC)	+= bpmp-tegra186.o
 tegra-bpmp-$(CONFIG_DEBUG_FS)	+= bpmp-debugfs.o
 obj-$(CONFIG_TEGRA_BPMP)	+= tegra-bpmp.o
 obj-$(CONFIG_TEGRA_IVC)		+= ivc.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/tegra/bpmp-private.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/tegra/bpmp-private.h
@@ -24,7 +24,8 @@
 };
 
 #if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC) || \
-    IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC)
+    IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC) || \
+    IS_ENABLED(CONFIG_ARCH_TEGRA_234_SOC)
 extern const struct tegra_bpmp_ops tegra186_bpmp_ops;
 #endif
 #if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/tegra/bpmp-tegra210.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/tegra/bpmp-tegra210.c
@@ -210,7 +210,7 @@
 	priv->tx_irq_data = irq_get_irq_data(err);
 	if (!priv->tx_irq_data) {
 		dev_err(&pdev->dev, "failed to get IRQ data for TX IRQ\n");
-		return err;
+		return -ENOENT;
 	}
 
 	err = platform_get_irq_byname(pdev, "rx");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/tegra/bpmp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/tegra/bpmp.c
@@ -24,12 +24,6 @@
 #define MSG_RING	BIT(1)
 #define TAG_SZ		32
 
-static inline struct tegra_bpmp *
-mbox_client_to_bpmp(struct mbox_client *client)
-{
-	return container_of(client, struct tegra_bpmp, mbox.client);
-}
-
 static inline const struct tegra_bpmp_ops *
 channel_to_ops(struct tegra_bpmp_channel *channel)
 {
@@ -808,7 +802,8 @@
 };
 
 #if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC) || \
-    IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC)
+    IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC) || \
+    IS_ENABLED(CONFIG_ARCH_TEGRA_234_SOC)
 static const struct tegra_bpmp_soc tegra186_soc = {
 	.channels = {
 		.cpu_tx = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/ti_sci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/ti_sci.c
@@ -2,7 +2,7 @@
 /*
  * Texas Instruments System Control Interface Protocol Driver
  *
- * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2015-2016 Texas Instruments Incorporated - https://www.ti.com/
  *	Nishanth Menon
  */
 
@@ -179,7 +179,7 @@
 {
 	struct device *dev = &pdev->dev;
 	struct resource *res;
-	char debug_name[50] = "ti_sci_debug@";
+	char debug_name[50];
 
 	/* Debug region is optional */
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
@@ -196,10 +196,10 @@
 	/* Setup NULL termination */
 	info->debug_buffer[info->debug_region_size] = 0;
 
-	info->d = debugfs_create_file(strncat(debug_name, dev_name(dev),
-					      sizeof(debug_name) -
-					      sizeof("ti_sci_debug@")),
-				      0444, NULL, info, &ti_sci_debug_fops);
+	snprintf(debug_name, sizeof(debug_name), "ti_sci_debug@%s",
+		 dev_name(dev));
+	info->d = debugfs_create_file(debug_name, 0444, NULL, info,
+				      &ti_sci_debug_fops);
 	if (IS_ERR(info->d))
 		return PTR_ERR(info->d);
 
@@ -208,19 +208,6 @@
 	return 0;
 }
 
-/**
- * ti_sci_debugfs_destroy() - clean up log debug file
- * @pdev:	platform device pointer
- * @info:	Pointer to SCI entity information
- */
-static void ti_sci_debugfs_destroy(struct platform_device *pdev,
-				   struct ti_sci_info *info)
-{
-	if (IS_ERR(info->debug_region))
-		return;
-
-	debugfs_remove(info->d);
-}
 #else /* CONFIG_DEBUG_FS */
 static inline int ti_sci_debugfs_create(struct platform_device *dev,
 					struct ti_sci_info *info)
@@ -3527,43 +3514,12 @@
 	return ret;
 }
 
-static int ti_sci_remove(struct platform_device *pdev)
-{
-	struct ti_sci_info *info;
-	struct device *dev = &pdev->dev;
-	int ret = 0;
-
-	of_platform_depopulate(dev);
-
-	info = platform_get_drvdata(pdev);
-
-	if (info->nb.notifier_call)
-		unregister_restart_handler(&info->nb);
-
-	mutex_lock(&ti_sci_list_mutex);
-	if (info->users)
-		ret = -EBUSY;
-	else
-		list_del(&info->node);
-	mutex_unlock(&ti_sci_list_mutex);
-
-	if (!ret) {
-		ti_sci_debugfs_destroy(pdev, info);
-
-		/* Safe to free channels since no more users */
-		mbox_free_channel(info->chan_tx);
-		mbox_free_channel(info->chan_rx);
-	}
-
-	return ret;
-}
-
 static struct platform_driver ti_sci_driver = {
 	.probe = ti_sci_probe,
-	.remove = ti_sci_remove,
 	.driver = {
 		   .name = "ti-sci",
 		   .of_match_table = of_match_ptr(ti_sci_of_match),
+		   .suppress_bind_attrs = true,
 	},
 };
 module_platform_driver(ti_sci_driver);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/ti_sci.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/ti_sci.h
@@ -6,7 +6,7 @@
  * The system works in a message response protocol
  * See: http://processors.wiki.ti.com/index.php/TISCI for details
  *
- * Copyright (C)  2015-2016 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C)  2015-2016 Texas Instruments Incorporated - https://www.ti.com/
  */
 
 #ifndef __TI_SCI_H
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/turris-mox-rwtm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/turris-mox-rwtm.c
@@ -134,11 +134,14 @@
 
 static int mox_get_status(enum mbox_cmd cmd, u32 retval)
 {
-	if (MBOX_STS_CMD(retval) != cmd ||
-	    MBOX_STS_ERROR(retval) != MBOX_STS_SUCCESS)
+	if (MBOX_STS_CMD(retval) != cmd)
 		return -EIO;
 	else if (MBOX_STS_ERROR(retval) == MBOX_STS_FAIL)
 		return -(int)MBOX_STS_VALUE(retval);
+	else if (MBOX_STS_ERROR(retval) == MBOX_STS_BADCMD)
+		return -ENOSYS;
+	else if (MBOX_STS_ERROR(retval) != MBOX_STS_SUCCESS)
+		return -EIO;
 	else
 		return MBOX_STS_VALUE(retval);
 }
@@ -183,16 +186,18 @@
 	if (ret < 0)
 		return ret;
 
-	ret = wait_for_completion_timeout(&rwtm->cmd_done, HZ / 2);
-	if (ret < 0)
-		return ret;
+	if (!wait_for_completion_timeout(&rwtm->cmd_done, HZ / 2))
+		return -ETIMEDOUT;
 
 	ret = mox_get_status(MBOX_CMD_BOARD_INFO, reply->retval);
-	if (ret < 0 && ret != -ENODATA) {
-		return ret;
-	} else if (ret == -ENODATA) {
+	if (ret == -ENODATA) {
 		dev_warn(rwtm->dev,
 			 "Board does not have manufacturing information burned!\n");
+	} else if (ret == -ENOSYS) {
+		dev_notice(rwtm->dev,
+			   "Firmware does not support the BOARD_INFO command\n");
+	} else if (ret < 0) {
+		return ret;
 	} else {
 		rwtm->serial_number = reply->status[1];
 		rwtm->serial_number <<= 32;
@@ -216,15 +221,17 @@
 	if (ret < 0)
 		return ret;
 
-	ret = wait_for_completion_timeout(&rwtm->cmd_done, HZ / 2);
-	if (ret < 0)
-		return ret;
+	if (!wait_for_completion_timeout(&rwtm->cmd_done, HZ / 2))
+		return -ETIMEDOUT;
 
 	ret = mox_get_status(MBOX_CMD_ECDSA_PUB_KEY, reply->retval);
-	if (ret < 0 && ret != -ENODATA) {
-		return ret;
-	} else if (ret == -ENODATA) {
+	if (ret == -ENODATA) {
 		dev_warn(rwtm->dev, "Board has no public key burned!\n");
+	} else if (ret == -ENOSYS) {
+		dev_notice(rwtm->dev,
+			   "Firmware does not support the ECDSA_PUB_KEY command\n");
+	} else if (ret < 0) {
+		return ret;
 	} else {
 		u32 *s = reply->status;
 
@@ -238,6 +245,26 @@
 	return 0;
 }
 
+static int check_get_random_support(struct mox_rwtm *rwtm)
+{
+	struct armada_37xx_rwtm_tx_msg msg;
+	int ret;
+
+	msg.command = MBOX_CMD_GET_RANDOM;
+	msg.args[0] = 1;
+	msg.args[1] = rwtm->buf_phys;
+	msg.args[2] = 4;
+
+	ret = mbox_send_message(rwtm->mbox, &msg);
+	if (ret < 0)
+		return ret;
+
+	if (!wait_for_completion_timeout(&rwtm->cmd_done, HZ / 2))
+		return -ETIMEDOUT;
+
+	return mox_get_status(MBOX_CMD_GET_RANDOM, rwtm->reply.retval);
+}
+
 static int mox_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait)
 {
 	struct mox_rwtm *rwtm = (struct mox_rwtm *) rng->priv;
@@ -310,6 +337,7 @@
 	platform_set_drvdata(pdev, rwtm);
 
 	mutex_init(&rwtm->busy);
+	init_completion(&rwtm->cmd_done);
 
 	rwtm->mbox_client.dev = dev;
 	rwtm->mbox_client.rx_callback = mox_rwtm_rx_callback;
@@ -323,12 +351,17 @@
 		goto remove_files;
 	}
 
-	init_completion(&rwtm->cmd_done);
-
 	ret = mox_get_board_info(rwtm);
 	if (ret < 0)
 		dev_warn(dev, "Cannot read board information: %i\n", ret);
 
+	ret = check_get_random_support(rwtm);
+	if (ret < 0) {
+		dev_notice(dev,
+			   "Firmware does not support the GET_RANDOM command\n");
+		goto free_channel;
+	}
+
 	rwtm->hwrng.name = DRIVER_NAME "_hwrng";
 	rwtm->hwrng.read = mox_hwrng_read;
 	rwtm->hwrng.priv = (unsigned long) rwtm;
@@ -364,6 +397,7 @@
 
 static const struct of_device_id turris_mox_rwtm_match[] = {
 	{ .compatible = "cznic,turris-mox-rwtm", },
+	{ .compatible = "marvell,armada-3700-rwtm-firmware", },
 	{ },
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/xilinx/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/xilinx/Kconfig
@@ -21,4 +21,12 @@
 	  Say yes to enable ZynqMP firmware interface debug APIs.
 	  If in doubt, say N.
 
+config ZYNQMP_FIRMWARE_SECURE
+	bool "Enable Xilinx Zynq MPSoC secure firmware loading APIs"
+	help
+	  Firmware secure driver is used as an interface to load
+	  Authenticated and/or Encrypted firmware with single loadable
+	  partition. Say yes to enable ZynqMP secure firmware loading
+	  APIs.If in doubt, say N
+
 endmenu
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/xilinx/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/xilinx/Makefile
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 # Makefile for Xilinx firmwares
 
-obj-$(CONFIG_ZYNQMP_FIRMWARE) += zynqmp.o
+obj-$(CONFIG_ZYNQMP_FIRMWARE) += zynqmp.o zynqmp-ggs.o
 obj-$(CONFIG_ZYNQMP_FIRMWARE_DEBUG) += zynqmp-debug.o
+obj-$(CONFIG_ZYNQMP_FIRMWARE_SECURE) += zynqmp-secure.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/xilinx/zynqmp-debug.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/xilinx/zynqmp-debug.c
@@ -31,13 +31,88 @@
 
 #define PM_API(id)		 {id, #id, strlen(#id)}
 static struct pm_api_info pm_api_list[] = {
+	PM_API(PM_REQUEST_SUSPEND),
+	PM_API(PM_SELF_SUSPEND),
+	PM_API(PM_FORCE_POWERDOWN),
+	PM_API(PM_ABORT_SUSPEND),
+	PM_API(PM_REQUEST_WAKEUP),
+	PM_API(PM_SET_WAKEUP_SOURCE),
+	PM_API(PM_SYSTEM_SHUTDOWN),
+	PM_API(PM_REQUEST_NODE),
+	PM_API(PM_RELEASE_NODE),
+	PM_API(PM_SET_REQUIREMENT),
+	PM_API(PM_SET_MAX_LATENCY),
 	PM_API(PM_GET_API_VERSION),
+	PM_API(PM_SET_CONFIGURATION),
+	PM_API(PM_GET_NODE_STATUS),
+	PM_API(PM_GET_OPERATING_CHARACTERISTIC),
+	PM_API(PM_REGISTER_NOTIFIER),
+	PM_API(PM_RESET_ASSERT),
+	PM_API(PM_RESET_GET_STATUS),
+	PM_API(PM_GET_CHIPID),
+	PM_API(PM_PINCTRL_GET_FUNCTION),
+	PM_API(PM_PINCTRL_SET_FUNCTION),
+	PM_API(PM_PINCTRL_CONFIG_PARAM_GET),
+	PM_API(PM_PINCTRL_CONFIG_PARAM_SET),
+	PM_API(PM_IOCTL),
+	PM_API(PM_CLOCK_ENABLE),
+	PM_API(PM_CLOCK_DISABLE),
+	PM_API(PM_CLOCK_GETSTATE),
+	PM_API(PM_CLOCK_SETDIVIDER),
+	PM_API(PM_CLOCK_GETDIVIDER),
+	PM_API(PM_CLOCK_SETRATE),
+	PM_API(PM_CLOCK_GETRATE),
+	PM_API(PM_CLOCK_SETPARENT),
+	PM_API(PM_CLOCK_GETPARENT),
 	PM_API(PM_QUERY_DATA),
 };
 
 struct dentry *firmware_debugfs_root;
 
 /**
+ * zynqmp_pm_self_suspend - PM call for master to suspend itself
+ * @node:	Node ID of the master or subsystem
+ * @latency:	Requested maximum wakeup latency (not supported)
+ * @state:	Requested state (not supported)
+ *
+ * Return:	Returns status, either success or error+reason
+ */
+static int zynqmp_pm_self_suspend(const u32 node, const u32 latency,
+				  const u32 state)
+{
+	return zynqmp_pm_invoke_fn(PM_SELF_SUSPEND, node, latency,
+				   state, 0, NULL);
+}
+
+/**
+ * zynqmp_pm_abort_suspend - PM call to announce that a prior suspend request
+ *				is to be aborted.
+ * @reason:	Reason for the abort
+ *
+ * Return:	Returns status, either success or error+reason
+ */
+static int zynqmp_pm_abort_suspend(const enum zynqmp_pm_abort_reason reason)
+{
+	return zynqmp_pm_invoke_fn(PM_ABORT_SUSPEND, reason, 0, 0, 0, NULL);
+}
+
+/**
+ * zynqmp_pm_register_notifier - Register the PU to be notified of PM events
+ * @node:	Node ID of the slave
+ * @event:	The event to be notified about
+ * @wake:	Wake up on event
+ * @enable:	Enable or disable the notifier
+ *
+ * Return:	Returns status, either success or error+reason
+ */
+static int zynqmp_pm_register_notifier(const u32 node, const u32 event,
+				       const u32 wake, const u32 enable)
+{
+	return zynqmp_pm_invoke_fn(PM_REGISTER_NOTIFIER, node, event,
+				   wake, enable, NULL);
+}
+
+/**
  * zynqmp_pm_argument_value() - Extract argument value from a PM-API request
  * @arg:	Entered PM-API argument in string format
  *
@@ -87,6 +162,7 @@
 {
 	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
 	u32 pm_api_version;
+	u64 rate;
 	int ret;
 	struct zynqmp_pm_query_data qdata = {0};
 
@@ -96,6 +172,191 @@
 		sprintf(debugfs_buf, "PM-API Version = %d.%d\n",
 			pm_api_version >> 16, pm_api_version & 0xffff);
 		break;
+	case PM_REQUEST_SUSPEND:
+		ret = eemi_ops->request_suspend(pm_api_arg[0],
+						pm_api_arg[1] ? pm_api_arg[1] :
+						ZYNQMP_PM_REQUEST_ACK_NO,
+						pm_api_arg[2] ? pm_api_arg[2] :
+						ZYNQMP_PM_MAX_LATENCY, 0);
+		break;
+	case PM_SELF_SUSPEND:
+		ret = zynqmp_pm_self_suspend(pm_api_arg[0],
+					     pm_api_arg[1] ? pm_api_arg[1] :
+					     ZYNQMP_PM_MAX_LATENCY, 0);
+		break;
+	case PM_FORCE_POWERDOWN:
+		ret = eemi_ops->force_powerdown(pm_api_arg[0],
+						pm_api_arg[1] ? pm_api_arg[1] :
+						ZYNQMP_PM_REQUEST_ACK_NO);
+		break;
+	case PM_ABORT_SUSPEND:
+		ret = zynqmp_pm_abort_suspend(pm_api_arg[0] ? pm_api_arg[0] :
+					      ZYNQMP_PM_ABORT_REASON_UNKNOWN);
+		break;
+	case PM_REQUEST_WAKEUP:
+		ret = eemi_ops->request_wakeup(pm_api_arg[0],
+					       pm_api_arg[1], pm_api_arg[2],
+					       pm_api_arg[3] ? pm_api_arg[3] :
+					       ZYNQMP_PM_REQUEST_ACK_NO);
+		break;
+	case PM_SET_WAKEUP_SOURCE:
+		ret = eemi_ops->set_wakeup_source(pm_api_arg[0], pm_api_arg[1],
+						  pm_api_arg[2]);
+		break;
+	case PM_SYSTEM_SHUTDOWN:
+		ret = eemi_ops->system_shutdown(pm_api_arg[0], pm_api_arg[1]);
+		break;
+	case PM_REQUEST_NODE:
+		ret = eemi_ops->request_node(pm_api_arg[0],
+					     pm_api_arg[1] ? pm_api_arg[1] :
+					     ZYNQMP_PM_CAPABILITY_ACCESS,
+					     pm_api_arg[2] ? pm_api_arg[2] : 0,
+					     pm_api_arg[3] ? pm_api_arg[3] :
+					     ZYNQMP_PM_REQUEST_ACK_BLOCKING);
+		break;
+	case PM_RELEASE_NODE:
+		ret = eemi_ops->release_node(pm_api_arg[0]);
+		break;
+	case PM_SET_REQUIREMENT:
+		ret = eemi_ops->set_requirement(pm_api_arg[0],
+						pm_api_arg[1] ? pm_api_arg[1] :
+						ZYNQMP_PM_CAPABILITY_CONTEXT,
+						pm_api_arg[2] ?
+						pm_api_arg[2] : 0,
+						pm_api_arg[3] ? pm_api_arg[3] :
+						ZYNQMP_PM_REQUEST_ACK_BLOCKING);
+		break;
+	case PM_SET_MAX_LATENCY:
+		ret = eemi_ops->set_max_latency(pm_api_arg[0],
+						pm_api_arg[1] ? pm_api_arg[1] :
+						ZYNQMP_PM_MAX_LATENCY);
+		break;
+	case PM_SET_CONFIGURATION:
+		ret = eemi_ops->set_configuration(pm_api_arg[0]);
+		break;
+	case PM_GET_NODE_STATUS:
+		ret = eemi_ops->get_node_status(pm_api_arg[0],
+						&pm_api_ret[0],
+						&pm_api_ret[1],
+						&pm_api_ret[2]);
+		if (!ret)
+			sprintf(debugfs_buf,
+				"GET_NODE_STATUS:\n\tNodeId: %llu\n\tStatus: %u\n\tRequirements: %u\n\tUsage: %u\n",
+				pm_api_arg[0], pm_api_ret[0],
+				pm_api_ret[1], pm_api_ret[2]);
+		break;
+	case PM_GET_OPERATING_CHARACTERISTIC:
+		ret = eemi_ops->get_operating_characteristic(pm_api_arg[0],
+				pm_api_arg[1] ? pm_api_arg[1] :
+				ZYNQMP_PM_OPERATING_CHARACTERISTIC_POWER,
+				&pm_api_ret[0]);
+		if (!ret)
+			sprintf(debugfs_buf,
+				"GET_OPERATING_CHARACTERISTIC:\n\tNodeId: %llu\n\tType: %llu\n\tResult: %u\n",
+				pm_api_arg[0], pm_api_arg[1],
+				pm_api_ret[0]);
+		break;
+	case PM_REGISTER_NOTIFIER:
+		ret = zynqmp_pm_register_notifier(pm_api_arg[0],
+						  pm_api_arg[1] ?
+						  pm_api_arg[1] : 0,
+						  pm_api_arg[2] ?
+						  pm_api_arg[2] : 0,
+						  pm_api_arg[3] ?
+						  pm_api_arg[3] : 0);
+		break;
+	case PM_RESET_ASSERT:
+		ret = eemi_ops->reset_assert(pm_api_arg[0], pm_api_arg[1]);
+		break;
+	case PM_RESET_GET_STATUS:
+		ret = eemi_ops->reset_get_status(pm_api_arg[0], &pm_api_ret[0]);
+		if (!ret)
+			sprintf(debugfs_buf, "Reset status: %u\n",
+				pm_api_ret[0]);
+		break;
+	case PM_GET_CHIPID:
+		ret = eemi_ops->get_chipid(&pm_api_ret[0], &pm_api_ret[1]);
+		if (!ret)
+			sprintf(debugfs_buf, "Idcode: %#x, Version:%#x\n",
+				pm_api_ret[0], pm_api_ret[1]);
+		break;
+	case PM_PINCTRL_GET_FUNCTION:
+		ret = eemi_ops->pinctrl_get_function(pm_api_arg[0],
+						     &pm_api_ret[0]);
+		if (!ret)
+			sprintf(debugfs_buf,
+				"Current set function for the pin: %u\n",
+				pm_api_ret[0]);
+		break;
+	case PM_PINCTRL_SET_FUNCTION:
+		ret = eemi_ops->pinctrl_set_function(pm_api_arg[0],
+						     pm_api_arg[1]);
+		break;
+	case PM_PINCTRL_CONFIG_PARAM_GET:
+		ret = eemi_ops->pinctrl_get_config(pm_api_arg[0], pm_api_arg[1],
+						   &pm_api_ret[0]);
+		if (!ret)
+			sprintf(debugfs_buf,
+				"Pin: %llu, Param: %llu, Value: %u\n",
+				pm_api_arg[0], pm_api_arg[1],
+				pm_api_ret[0]);
+		break;
+	case PM_PINCTRL_CONFIG_PARAM_SET:
+		ret = eemi_ops->pinctrl_set_config(pm_api_arg[0],
+						   pm_api_arg[1],
+						   pm_api_arg[2]);
+		break;
+	case PM_IOCTL:
+		ret = eemi_ops->ioctl(pm_api_arg[0], pm_api_arg[1],
+				      pm_api_arg[2], pm_api_arg[3],
+				      &pm_api_ret[0]);
+		if (!ret && (pm_api_arg[1] == IOCTL_GET_RPU_OPER_MODE ||
+			     pm_api_arg[1] == IOCTL_GET_PLL_FRAC_MODE ||
+			     pm_api_arg[1] == IOCTL_GET_PLL_FRAC_DATA ||
+			     pm_api_arg[1] == IOCTL_READ_GGS ||
+			     pm_api_arg[1] == IOCTL_READ_PGGS ||
+			     pm_api_arg[1] == IOCTL_PROBE_COUNTER_READ))
+			sprintf(debugfs_buf, "IOCTL return value: %u\n",
+				pm_api_ret[1]);
+		break;
+	case PM_CLOCK_ENABLE:
+		ret = eemi_ops->clock_enable(pm_api_arg[0]);
+		break;
+	case PM_CLOCK_DISABLE:
+		ret = eemi_ops->clock_disable(pm_api_arg[0]);
+		break;
+	case PM_CLOCK_GETSTATE:
+		ret = eemi_ops->clock_getstate(pm_api_arg[0], &pm_api_ret[0]);
+		if (!ret)
+			sprintf(debugfs_buf, "Clock state: %u\n",
+				pm_api_ret[0]);
+		break;
+	case PM_CLOCK_SETDIVIDER:
+		ret = eemi_ops->clock_setdivider(pm_api_arg[0], pm_api_arg[1]);
+		break;
+	case PM_CLOCK_GETDIVIDER:
+		ret = eemi_ops->clock_getdivider(pm_api_arg[0], &pm_api_ret[0]);
+		if (!ret)
+			sprintf(debugfs_buf, "Divider Value: %d\n",
+				pm_api_ret[0]);
+		break;
+	case PM_CLOCK_SETRATE:
+		ret = eemi_ops->clock_setrate(pm_api_arg[0], pm_api_arg[1]);
+		break;
+	case PM_CLOCK_GETRATE:
+		ret = eemi_ops->clock_getrate(pm_api_arg[0], &rate);
+		if (!ret)
+			sprintf(debugfs_buf, "Clock rate :%llu\n", rate);
+		break;
+	case PM_CLOCK_SETPARENT:
+		ret = eemi_ops->clock_setparent(pm_api_arg[0], pm_api_arg[1]);
+		break;
+	case PM_CLOCK_GETPARENT:
+		ret = eemi_ops->clock_getparent(pm_api_arg[0], &pm_api_ret[0]);
+		if (!ret)
+			sprintf(debugfs_buf,
+				"Clock parent Index: %u\n", pm_api_ret[0]);
+		break;
 	case PM_QUERY_DATA:
 		qdata.qid = pm_api_arg[0];
 		qdata.arg1 = pm_api_arg[1];
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/xilinx/zynqmp-ggs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/xilinx/zynqmp-ggs.c
@@ -0,0 +1,289 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Xilinx Zynq MPSoC Firmware layer
+ *
+ *  Copyright (C) 2014-2018 Xilinx, Inc.
+ *
+ *  Jolly Shah <jollys@xilinx.com>
+ *  Rajan Vaja <rajanv@xilinx.com>
+ */
+
+#include <linux/compiler.h>
+#include <linux/of.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <linux/firmware/xlnx-zynqmp.h>
+
+static ssize_t read_register(char *buf, u32 ioctl_id, u32 reg)
+{
+	int ret;
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
+
+	if (!eemi_ops->ioctl)
+		return -EFAULT;
+
+	ret = eemi_ops->ioctl(0, ioctl_id, reg, 0, ret_payload);
+	if (ret)
+		return ret;
+
+	return sprintf(buf, "0x%x\n", ret_payload[1]);
+}
+
+static ssize_t write_register(const char *buf, size_t count, u32 read_ioctl,
+			      u32 write_ioctl, u32 reg)
+{
+	char *kern_buff, *inbuf, *tok;
+	long mask, value;
+	int ret;
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
+
+	if (!eemi_ops->ioctl)
+		return -EFAULT;
+
+	kern_buff = kzalloc(count, GFP_KERNEL);
+	if (!kern_buff)
+		return -ENOMEM;
+
+	ret = strlcpy(kern_buff, buf, count);
+	if (ret < 0) {
+		ret = -EFAULT;
+		goto err;
+	}
+
+	inbuf = kern_buff;
+
+	/* Read the write mask */
+	tok = strsep(&inbuf, " ");
+	if (!tok) {
+		ret = -EFAULT;
+		goto err;
+	}
+
+	ret = kstrtol(tok, 16, &mask);
+	if (ret) {
+		ret = -EFAULT;
+		goto err;
+	}
+
+	/* Read the write value */
+	tok = strsep(&inbuf, " ");
+	if (!tok) {
+		ret = -EFAULT;
+		goto err;
+	}
+
+	ret = kstrtol(tok, 16, &value);
+	if (ret) {
+		ret = -EFAULT;
+		goto err;
+	}
+
+	ret = eemi_ops->ioctl(0, read_ioctl, reg, 0, ret_payload);
+	if (ret) {
+		ret = -EFAULT;
+		goto err;
+	}
+	ret_payload[1] &= ~mask;
+	value &= mask;
+	value |= ret_payload[1];
+
+	ret = eemi_ops->ioctl(0, write_ioctl, reg, value, NULL);
+	if (ret)
+		ret = -EFAULT;
+
+err:
+	kfree(kern_buff);
+	if (ret)
+		return ret;
+
+	return count;
+}
+
+/**
+ * ggs_show - Show global general storage (ggs) sysfs attribute
+ * @kobj: Kobject structure
+ * @attr: Kobject attribute structure
+ * @buf: Requested available shutdown_scope attributes string
+ * @reg: Register number
+ *
+ * Return:Number of bytes printed into the buffer.
+ *
+ * Helper function for viewing a ggs register value.
+ *
+ * User-space interface for viewing the content of the ggs0 register.
+ * cat /sys/firmware/zynqmp/ggs0
+ */
+static ssize_t ggs_show(struct kobject *kobj,
+			struct kobj_attribute *attr,
+			char *buf,
+			u32 reg)
+{
+	return read_register(buf, IOCTL_READ_GGS, reg);
+}
+
+/**
+ * ggs_store - Store global general storage (ggs) sysfs attribute
+ * @kobj: Kobject structure
+ * @attr: Kobject attribute structure
+ * @buf: User entered shutdown_scope attribute string
+ * @count: Size of buf
+ * @reg: Register number
+ *
+ * Return: count argument if request succeeds, the corresponding
+ * error code otherwise
+ *
+ * Helper function for storing a ggs register value.
+ *
+ * For example, the user-space interface for storing a value to the
+ * ggs0 register:
+ * echo 0xFFFFFFFF 0x1234ABCD > /sys/firmware/zynqmp/ggs0
+ */
+static ssize_t ggs_store(struct kobject *kobj,
+			 struct kobj_attribute *attr,
+			 const char *buf,
+			 size_t count,
+			 u32 reg)
+{
+	if (!kobj || !attr || !buf || !count || reg >= GSS_NUM_REGS)
+		return -EINVAL;
+
+	return write_register(buf, count, IOCTL_READ_GGS, IOCTL_WRITE_GGS, reg);
+}
+
+/* GGS register show functions */
+#define GGS0_SHOW(N)						\
+	ssize_t ggs##N##_show(struct kobject *kobj,		\
+				struct kobj_attribute *attr,	\
+				char *buf)			\
+	{							\
+		return ggs_show(kobj, attr, buf, N);		\
+	}
+
+static GGS0_SHOW(0);
+static GGS0_SHOW(1);
+static GGS0_SHOW(2);
+static GGS0_SHOW(3);
+
+/* GGS register store function */
+#define GGS0_STORE(N)						\
+	ssize_t ggs##N##_store(struct kobject *kobj,		\
+				struct kobj_attribute *attr,	\
+				const char *buf,		\
+				size_t count)			\
+	{							\
+		return ggs_store(kobj, attr, buf, count, N);	\
+	}
+
+static GGS0_STORE(0);
+static GGS0_STORE(1);
+static GGS0_STORE(2);
+static GGS0_STORE(3);
+
+/**
+ * pggs_show - Show persistent global general storage (pggs) sysfs attribute
+ * @kobj: Kobject structure
+ * @attr: Kobject attribute structure
+ * @buf: Requested available shutdown_scope attributes string
+ * @reg: Register number
+ *
+ * Return:Number of bytes printed into the buffer.
+ *
+ * Helper function for viewing a pggs register value.
+ */
+static ssize_t pggs_show(struct kobject *kobj,
+			 struct kobj_attribute *attr,
+			 char *buf,
+			 u32 reg)
+{
+	return read_register(buf, IOCTL_READ_PGGS, reg);
+}
+
+/**
+ * pggs_store - Store persistent global general storage (pggs) sysfs attribute
+ * @kobj: Kobject structure
+ * @attr: Kobject attribute structure
+ * @buf: User entered shutdown_scope attribute string
+ * @count: Size of buf
+ * @reg: Register number
+ *
+ * Return: count argument if request succeeds, the corresponding
+ * error code otherwise
+ *
+ * Helper function for storing a pggs register value.
+ */
+static ssize_t pggs_store(struct kobject *kobj,
+			  struct kobj_attribute *attr,
+			  const char *buf,
+			  size_t count,
+			  u32 reg)
+{
+	return write_register(buf, count, IOCTL_READ_PGGS,
+			      IOCTL_WRITE_PGGS, reg);
+}
+
+#define PGGS0_SHOW(N)						\
+	ssize_t pggs##N##_show(struct kobject *kobj,		\
+				struct kobj_attribute *attr,	\
+				char *buf)			\
+	{							\
+		return pggs_show(kobj, attr, buf, N);		\
+	}
+
+#define PGGS0_STORE(N)						\
+	ssize_t pggs##N##_store(struct kobject *kobj,		\
+				   struct kobj_attribute *attr,	\
+				   const char *buf,		\
+				   size_t count)		\
+	{							\
+		return pggs_store(kobj, attr, buf, count, N);	\
+	}
+
+/* PGGS register show functions */
+static PGGS0_SHOW(0);
+static PGGS0_SHOW(1);
+static PGGS0_SHOW(2);
+static PGGS0_SHOW(3);
+
+/* PGGS register store functions */
+static PGGS0_STORE(0);
+static PGGS0_STORE(1);
+static PGGS0_STORE(2);
+static PGGS0_STORE(3);
+
+/* GGS register attributes */
+static struct kobj_attribute zynqmp_attr_ggs0 = __ATTR_RW(ggs0);
+static struct kobj_attribute zynqmp_attr_ggs1 = __ATTR_RW(ggs1);
+static struct kobj_attribute zynqmp_attr_ggs2 = __ATTR_RW(ggs2);
+static struct kobj_attribute zynqmp_attr_ggs3 = __ATTR_RW(ggs3);
+
+/* PGGS register attributes */
+static struct kobj_attribute zynqmp_attr_pggs0 = __ATTR_RW(pggs0);
+static struct kobj_attribute zynqmp_attr_pggs1 = __ATTR_RW(pggs1);
+static struct kobj_attribute zynqmp_attr_pggs2 = __ATTR_RW(pggs2);
+static struct kobj_attribute zynqmp_attr_pggs3 = __ATTR_RW(pggs3);
+
+static struct attribute *attrs[] = {
+	&zynqmp_attr_ggs0.attr,
+	&zynqmp_attr_ggs1.attr,
+	&zynqmp_attr_ggs2.attr,
+	&zynqmp_attr_ggs3.attr,
+	&zynqmp_attr_pggs0.attr,
+	&zynqmp_attr_pggs1.attr,
+	&zynqmp_attr_pggs2.attr,
+	&zynqmp_attr_pggs3.attr,
+	NULL,
+};
+
+static const struct attribute_group attr_group = {
+	.attrs = attrs,
+	NULL,
+};
+
+int zynqmp_pm_ggs_init(struct kobject *parent_kobj)
+{
+	return sysfs_create_group(parent_kobj, &attr_group);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/xilinx/zynqmp-secure.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/xilinx/zynqmp-secure.c
@@ -0,0 +1,197 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx ZynqMP SecureFw Driver.
+ * Copyright (c) 2018 Xilinx Inc.
+ */
+
+#include <asm/cacheflush.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/firmware.h>
+#include <linux/firmware/xlnx-zynqmp.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
+
+#define ZYNQMP_AES_KEY_SIZE	64
+
+static u8 key[ZYNQMP_AES_KEY_SIZE] = {0};
+static dma_addr_t dma_addr;
+static u8 *keyptr;
+static size_t dma_size;
+static char *kbuf;
+
+static const struct zynqmp_eemi_ops *eemi_ops;
+
+static ssize_t secure_load_store(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	const struct firmware *fw;
+	char image_name[NAME_MAX];
+	u64 dst, ret;
+	int len;
+
+	if (IS_ERR(eemi_ops) || !eemi_ops->secure_image)
+		return -EFAULT;
+
+	strncpy(image_name, buf, NAME_MAX);
+	len = strlen(image_name);
+	if (image_name[len - 1] == '\n')
+		image_name[len - 1] = 0;
+
+	ret = request_firmware(&fw, image_name, dev);
+	if (ret) {
+		dev_err(dev, "Error requesting firmware %s\n", image_name);
+		return ret;
+	}
+	dma_size = fw->size;
+
+	if (keyptr)
+		dma_size = fw->size + ZYNQMP_AES_KEY_SIZE;
+
+	kbuf = dma_alloc_coherent(dev, dma_size,
+				  &dma_addr, GFP_KERNEL);
+	if (!kbuf)
+		return -ENOMEM;
+
+	memcpy(kbuf, fw->data, fw->size);
+
+	if (keyptr)
+		memcpy(kbuf + fw->size, key, ZYNQMP_AES_KEY_SIZE);
+
+	/* To ensure cache coherency */
+	__flush_cache_user_range((unsigned long)kbuf,
+				 (unsigned long)kbuf + dma_size);
+	release_firmware(fw);
+
+	if (keyptr)
+		ret = eemi_ops->secure_image(dma_addr, dma_addr + fw->size,
+					     &dst);
+	else
+		ret = eemi_ops->secure_image(dma_addr, 0, &dst);
+
+	if (ret) {
+		dev_info(dev, "Failed to load secure image \r\n");
+		return ret;
+	}
+	dev_info(dev, "Verified image at 0x%llx\n", dst);
+
+	return count;
+}
+
+static ssize_t key_show(struct device *dev,
+			struct device_attribute *attr,
+			char *buf)
+{
+	return snprintf(buf, ZYNQMP_AES_KEY_SIZE + 1, "%s\n", key);
+}
+
+static ssize_t key_store(struct device *dev,
+			 struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	memcpy(key, buf, count);
+	keyptr = &key[0];
+	return count;
+}
+
+static ssize_t secure_load_done_store(struct device *dev,
+				      struct device_attribute *attr,
+				      const char *buf, size_t count)
+{
+	int ret;
+	unsigned int value;
+
+	ret = kstrtouint(buf, 10, &value);
+	if (ret)
+		return ret;
+	if (value)
+		dma_free_coherent(dev, dma_size, kbuf, dma_addr);
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(key);
+static DEVICE_ATTR_WO(secure_load);
+static DEVICE_ATTR_WO(secure_load_done);
+
+static struct attribute *securefw_attrs[] = {
+	&dev_attr_secure_load_done.attr,
+	&dev_attr_secure_load.attr,
+	&dev_attr_key.attr,
+	NULL,
+};
+
+ATTRIBUTE_GROUPS(securefw);
+
+static int securefw_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct platform_device *securefw_pdev;
+
+	eemi_ops = zynqmp_pm_get_eemi_ops();
+	if (IS_ERR(eemi_ops))
+		return PTR_ERR(eemi_ops);
+
+	securefw_pdev = pdev;
+
+	securefw_pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+
+	ret = of_dma_configure(&securefw_pdev->dev, NULL, true);
+	if (ret < 0) {
+		dev_info(&securefw_pdev->dev, "Cannot setup DMA ops\r\n");
+		return ret;
+	}
+
+	ret = sysfs_create_groups(&securefw_pdev->dev.kobj, securefw_groups);
+	if (ret)
+		return ret;
+
+	dev_info(&securefw_pdev->dev, "securefw probed\r\n");
+	return ret;
+}
+
+static int securefw_remove(struct platform_device *pdev)
+{
+	sysfs_remove_groups(&pdev->dev.kobj, securefw_groups);
+	return 0;
+}
+
+static struct platform_driver securefw_driver = {
+	.driver = {
+		.name = "securefw",
+	},
+	.probe = securefw_probe,
+	.remove = securefw_remove,
+};
+
+static struct platform_device *securefw_dev_reg;
+
+static int __init zynqmp_secure_init(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&securefw_driver);
+	if (ret)
+		return ret;
+
+	securefw_dev_reg = platform_device_register_simple("securefw", -1,
+							   NULL, 0);
+	if (IS_ERR(securefw_dev_reg)) {
+		ret = PTR_ERR(securefw_dev_reg);
+		platform_driver_unregister(&securefw_driver);
+		return ret;
+	}
+	return 0;
+}
+
+static void __exit zynqmp_secure_exit(void)
+{
+	platform_device_unregister(securefw_dev_reg);
+	platform_driver_unregister(&securefw_driver);
+}
+
+module_init(zynqmp_secure_init);
+module_exit(zynqmp_secure_exit);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/firmware/xilinx/zynqmp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/firmware/xilinx/zynqmp.c
@@ -2,7 +2,7 @@
 /*
  * Xilinx Zynq MPSoC Firmware layer
  *
- *  Copyright (C) 2014-2018 Xilinx, Inc.
+ *  Copyright (C) 2014-2020 Xilinx, Inc.
  *
  *  Michal Simek <michal.simek@xilinx.com>
  *  Davorin Mista <davorin.mista@aggios.com>
@@ -24,8 +24,13 @@
 #include <linux/firmware/xlnx-zynqmp.h>
 #include "zynqmp-debug.h"
 
+static unsigned long register_address;
+
 static const struct zynqmp_eemi_ops *eemi_ops_tbl;
 
+static bool feature_check_enabled;
+static u32 zynqmp_pm_features[PM_API_MAX];
+
 static const struct mfd_cell firmware_devs[] = {
 	{
 		.name = "zynqmp_power_controller",
@@ -44,10 +49,14 @@
 	case XST_PM_SUCCESS:
 	case XST_PM_DOUBLE_REQ:
 		return 0;
+	case XST_PM_NO_FEATURE:
+		return -ENOTSUPP;
 	case XST_PM_NO_ACCESS:
 		return -EACCES;
 	case XST_PM_ABORT_SUSPEND:
 		return -ECANCELED;
+	case XST_PM_MULT_USER:
+		return -EUSERS;
 	case XST_PM_INTERNAL:
 	case XST_PM_CONFLICT:
 	case XST_PM_INVALID_NODE:
@@ -127,6 +136,39 @@
 }
 
 /**
+ * zynqmp_pm_feature() - Check weather given feature is supported or not
+ * @api_id:		API ID to check
+ *
+ * Return: Returns status, either success or error+reason
+ */
+static int zynqmp_pm_feature(u32 api_id)
+{
+	int ret;
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	u64 smc_arg[2];
+
+	if (!feature_check_enabled)
+		return 0;
+
+	/* Return value if feature is already checked */
+	if (zynqmp_pm_features[api_id] != PM_FEATURE_UNCHECKED)
+		return zynqmp_pm_features[api_id];
+
+	smc_arg[0] = PM_SIP_SVC | PM_FEATURE_CHECK;
+	smc_arg[1] = api_id;
+
+	ret = do_fw_call(smc_arg[0], smc_arg[1], 0, ret_payload);
+	if (ret) {
+		zynqmp_pm_features[api_id] = PM_FEATURE_INVALID;
+		return PM_FEATURE_INVALID;
+	}
+
+	zynqmp_pm_features[api_id] = ret_payload[1];
+
+	return zynqmp_pm_features[api_id];
+}
+
+/**
  * zynqmp_pm_invoke_fn() - Invoke the system-level platform management layer
  *			   caller function depending on the configuration
  * @pm_api_id:		Requested PM-API call
@@ -160,6 +202,9 @@
 	 */
 	u64 smc_arg[4];
 
+	if (zynqmp_pm_feature(pm_api_id) == PM_FEATURE_INVALID)
+		return -ENOTSUPP;
+
 	smc_arg[0] = PM_SIP_SVC | pm_api_id;
 	smc_arg[1] = ((u64)arg1 << 32) | arg0;
 	smc_arg[2] = ((u64)arg3 << 32) | arg2;
@@ -461,6 +506,39 @@
 }
 
 /**
+ * versal_is_valid_ioctl() - Check whether IOCTL ID is valid or not for versal
+ * @ioctl_id:	IOCTL ID
+ *
+ * Return: 1 if IOCTL is valid else 0
+ */
+static inline int versal_is_valid_ioctl(u32 ioctl_id)
+{
+	switch (ioctl_id) {
+	case IOCTL_GET_RPU_OPER_MODE:
+	case IOCTL_SET_RPU_OPER_MODE:
+	case IOCTL_RPU_BOOT_ADDR_CONFIG:
+	case IOCTL_TCM_COMB_CONFIG:
+	case IOCTL_SET_TAPDELAY_BYPASS:
+	case IOCTL_SD_DLL_RESET:
+	case IOCTL_SET_SD_TAPDELAY:
+	case IOCTL_WRITE_GGS:
+	case IOCTL_READ_GGS:
+	case IOCTL_WRITE_PGGS:
+	case IOCTL_READ_PGGS:
+	case IOCTL_SET_BOOT_HEALTH_STATUS:
+	case IOCTL_PROBE_COUNTER_READ:
+	case IOCTL_PROBE_COUNTER_WRITE:
+	case IOCTL_USB_SET_STATE:
+	case IOCTL_OSPI_MUX_SELECT:
+	case IOCTL_GET_LAST_RESET_REASON:
+	case IOCTL_AIE_ISR_CLEAR:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+/**
  * zynqmp_is_valid_ioctl() - Check whether IOCTL ID is valid or not
  * @ioctl_id:	IOCTL ID
  *
@@ -473,6 +551,21 @@
 	case IOCTL_GET_PLL_FRAC_MODE:
 	case IOCTL_SET_PLL_FRAC_DATA:
 	case IOCTL_GET_PLL_FRAC_DATA:
+	case IOCTL_GET_RPU_OPER_MODE:
+	case IOCTL_SET_RPU_OPER_MODE:
+	case IOCTL_RPU_BOOT_ADDR_CONFIG:
+	case IOCTL_TCM_COMB_CONFIG:
+	case IOCTL_SET_TAPDELAY_BYPASS:
+	case IOCTL_SET_SGMII_MODE:
+	case IOCTL_SD_DLL_RESET:
+	case IOCTL_SET_SD_TAPDELAY:
+	case IOCTL_WRITE_GGS:
+	case IOCTL_READ_GGS:
+	case IOCTL_WRITE_PGGS:
+	case IOCTL_READ_PGGS:
+	case IOCTL_ULPI_RESET:
+	case IOCTL_SET_BOOT_HEALTH_STATUS:
+	case IOCTL_AFI:
 		return 1;
 	default:
 		return 0;
@@ -494,8 +587,13 @@
 static int zynqmp_pm_ioctl(u32 node_id, u32 ioctl_id, u32 arg1, u32 arg2,
 			   u32 *out)
 {
-	if (!zynqmp_is_valid_ioctl(ioctl_id))
-		return -EINVAL;
+	if (of_find_compatible_node(NULL, NULL, "xlnx,versal")) {
+		if (!versal_is_valid_ioctl(ioctl_id))
+			return -EINVAL;
+	} else {
+		if (!zynqmp_is_valid_ioctl(ioctl_id))
+			return -EINVAL;
+	}
 
 	return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, ioctl_id,
 				   arg1, arg2, out);
@@ -509,7 +607,7 @@
  *
  * Return: Returns status, either success or error+reason
  */
-static int zynqmp_pm_reset_assert(const enum zynqmp_pm_reset reset,
+static int zynqmp_pm_reset_assert(const u32 reset,
 				  const enum zynqmp_pm_reset_action assert_flag)
 {
 	return zynqmp_pm_invoke_fn(PM_RESET_ASSERT, reset, assert_flag,
@@ -523,8 +621,7 @@
  *
  * Return: Returns status, either success or error+reason
  */
-static int zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset,
-				      u32 *status)
+static int zynqmp_pm_reset_get_status(const u32 reset, u32 *status)
 {
 	u32 ret_payload[PAYLOAD_ARG_CNT];
 	int ret;
@@ -664,6 +761,485 @@
 				   qos, ack, NULL);
 }
 
+/**
+ * zynqmp_pm_load_pdi - Load and process pdi
+ * @src:	Source device where PDI is located
+ * @address:	Pdi src address
+ *
+ * This function provides support to load pdi from linux
+ *
+ * Return: Returns status, either success or error+reason
+ */
+static int zynqmp_pm_load_pdi(const u32 src, const u64 address)
+{
+	return zynqmp_pm_invoke_fn(PM_LOAD_PDI, src,
+				   lower_32_bits(address),
+				   upper_32_bits(address), 0, NULL);
+}
+
+/**
+ * zynqmp_pm_fpga_read - Perform the fpga configuration readback
+ * @reg_numframes: Configuration register offset (or) Number of frames to read
+ * @phys_address: Physical Address of the buffer
+ * @readback_type: Type of fpga readback operation
+ * @value: Value to read
+ *
+ * This function provides access to xilfpga library to perform
+ * fpga configuration readback.
+ *
+ * Return:	Returns status, either success or error+reason
+ */
+static int zynqmp_pm_fpga_read(const u32 reg_numframes, const u64 phys_address,
+			       u32 readback_type, u32 *value)
+{
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	int ret;
+
+	if (!value)
+		return -EINVAL;
+
+	ret = zynqmp_pm_invoke_fn(PM_FPGA_READ, reg_numframes,
+				  lower_32_bits(phys_address),
+				  upper_32_bits(phys_address), readback_type,
+				  ret_payload);
+	*value = ret_payload[1];
+
+	return ret;
+}
+
+/**
+ * zynqmp_pm_sha_hash - Access the SHA engine to calculate the hash
+ * @address:	Address of the data/ Address of output buffer where
+ *		hash should be stored.
+ * @size:	Size of the data.
+ * @flags:
+ *	BIT(0) - for initializing csudma driver and SHA3(Here address
+ *		 and size inputs can be NULL).
+ *	BIT(1) - to call Sha3_Update API which can be called multiple
+ *		 times when data is not contiguous.
+ *	BIT(2) - to get final hash of the whole updated data.
+ *		 Hash will be overwritten at provided address with
+ *		 48 bytes.
+ *
+ * Return:	Returns status, either success or error code.
+ */
+static int zynqmp_pm_sha_hash(const u64 address, const u32 size,
+			      const u32 flags)
+{
+	u32 lower_32_bits = (u32)address;
+	u32 upper_32_bits = (u32)(address >> 32);
+
+	return zynqmp_pm_invoke_fn(PM_SECURE_SHA, upper_32_bits, lower_32_bits,
+				   size, flags, NULL);
+}
+
+/**
+ * zynqmp_pm_rsa - Access RSA hardware to encrypt/decrypt the data with RSA.
+ * @address:	Address of the data
+ * @size:	Size of the data.
+ * @flags:
+ *		BIT(0) - Encryption/Decryption
+ *			 0 - RSA decryption with private key
+ *			 1 - RSA encryption with public key.
+ *
+ * Return:	Returns status, either success or error code.
+ */
+static int zynqmp_pm_rsa(const u64 address, const u32 size, const u32 flags)
+{
+	u32 lower_32_bits = (u32)address;
+	u32 upper_32_bits = (u32)(address >> 32);
+
+	return zynqmp_pm_invoke_fn(PM_SECURE_RSA, upper_32_bits, lower_32_bits,
+				   size, flags, NULL);
+}
+
+/**
+ * zynqmp_pm_aes - Access AES hardware to encrypt/decrypt the data using
+ * AES-GCM core.
+ * @address:	Address of the AesParams structure.
+ * @out:	Returned output value
+ *
+ * Return:	Returns status, either success or error code.
+ */
+static int zynqmp_pm_aes_engine(const u64 address, u32 *out)
+{
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	int ret;
+
+	if (!out)
+		return -EINVAL;
+
+	ret = zynqmp_pm_invoke_fn(PM_SECURE_AES, upper_32_bits(address),
+				  lower_32_bits(address),
+				  0, 0, ret_payload);
+	*out = ret_payload[1];
+	return ret;
+}
+
+/**
+ * zynqmp_pm_request_suspend - PM call to request for another PU or subsystem to
+ *					be suspended gracefully.
+ * @node:	Node ID of the targeted PU or subsystem
+ * @ack:	Flag to specify whether acknowledge is requested
+ * @latency:	Requested wakeup latency (not supported)
+ * @state:	Requested state (not supported)
+ *
+ * Return:	Returns status, either success or error+reason
+ */
+static int zynqmp_pm_request_suspend(const u32 node,
+				     const enum zynqmp_pm_request_ack ack,
+				     const u32 latency,
+				     const u32 state)
+{
+	return zynqmp_pm_invoke_fn(PM_REQUEST_SUSPEND, node, ack,
+				   latency, state, NULL);
+}
+
+/**
+ * zynqmp_pm_force_powerdown - PM call to request for another PU or subsystem to
+ *				be powered down forcefully
+ * @target:	Node ID of the targeted PU or subsystem
+ * @ack:	Flag to specify whether acknowledge is requested
+ *
+ * Return:	Returns status, either success or error+reason
+ */
+static int zynqmp_pm_force_powerdown(const u32 target,
+				     const enum zynqmp_pm_request_ack ack)
+{
+	return zynqmp_pm_invoke_fn(PM_FORCE_POWERDOWN, target, ack, 0, 0, NULL);
+}
+
+/**
+ * zynqmp_pm_request_wakeup - PM call to wake up selected master or subsystem
+ * @node:	Node ID of the master or subsystem
+ * @set_addr:	Specifies whether the address argument is relevant
+ * @address:	Address from which to resume when woken up
+ * @ack:	Flag to specify whether acknowledge requested
+ *
+ * Return:	Returns status, either success or error+reason
+ */
+static int zynqmp_pm_request_wakeup(const u32 node,
+				    const bool set_addr,
+				    const u64 address,
+				    const enum zynqmp_pm_request_ack ack)
+{
+	/* set_addr flag is encoded into 1st bit of address */
+	return zynqmp_pm_invoke_fn(PM_REQUEST_WAKEUP, node, address | set_addr,
+				   address >> 32, ack, NULL);
+}
+
+/**
+ * zynqmp_pm_set_wakeup_source - PM call to specify the wakeup source
+ *					while suspended
+ * @target:	Node ID of the targeted PU or subsystem
+ * @wakeup_node:Node ID of the wakeup peripheral
+ * @enable:	Enable or disable the specified peripheral as wake source
+ *
+ * Return:	Returns status, either success or error+reason
+ */
+static int zynqmp_pm_set_wakeup_source(const u32 target,
+				       const u32 wakeup_node,
+				       const u32 enable)
+{
+	return zynqmp_pm_invoke_fn(PM_SET_WAKEUP_SOURCE, target,
+				   wakeup_node, enable, 0, NULL);
+}
+
+/**
+ * zynqmp_pm_system_shutdown - PM call to request a system shutdown or restart
+ * @type:	Shutdown or restart? 0 for shutdown, 1 for restart
+ * @subtype:	Specifies which system should be restarted or shut down
+ *
+ * Return:	Returns status, either success or error+reason
+ */
+static int zynqmp_pm_system_shutdown(const u32 type, const u32 subtype)
+{
+	return zynqmp_pm_invoke_fn(PM_SYSTEM_SHUTDOWN, type, subtype,
+				   0, 0, NULL);
+}
+
+/**
+ * zynqmp_pm_set_max_latency - PM call to set wakeup latency requirements
+ * @node:	Node ID of the slave
+ * @latency:	Requested maximum wakeup latency
+ *
+ * Return:	Returns status, either success or error+reason
+ */
+static int zynqmp_pm_set_max_latency(const u32 node, const u32 latency)
+{
+	return zynqmp_pm_invoke_fn(PM_SET_MAX_LATENCY, node, latency,
+				   0, 0, NULL);
+}
+
+/**
+ * zynqmp_pm_set_configuration - PM call to set system configuration
+ * @physical_addr:	Physical 32-bit address of data structure in memory
+ *
+ * Return:		Returns status, either success or error+reason
+ */
+static int zynqmp_pm_set_configuration(const u32 physical_addr)
+{
+	return zynqmp_pm_invoke_fn(PM_SET_CONFIGURATION, physical_addr, 0,
+				   0, 0, NULL);
+}
+
+/**
+ * zynqmp_pm_get_node_status - PM call to request a node's current power state
+ * @node:		ID of the component or sub-system in question
+ * @status:		Current operating state of the requested node
+ * @requirements:	Current requirements asserted on the node,
+ *			used for slave nodes only.
+ * @usage:		Usage information, used for slave nodes only:
+ *			PM_USAGE_NO_MASTER	- No master is currently using
+ *						  the node
+ *			PM_USAGE_CURRENT_MASTER	- Only requesting master is
+ *						  currently using the node
+ *			PM_USAGE_OTHER_MASTER	- Only other masters are
+ *						  currently using the node
+ *			PM_USAGE_BOTH_MASTERS	- Both the current and at least
+ *						  one other master is currently
+ *						  using the node
+ *
+ * Return:		Returns status, either success or error+reason
+ */
+static int zynqmp_pm_get_node_status(const u32 node, u32 *const status,
+				     u32 *const requirements, u32 *const usage)
+{
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	int ret;
+
+	if (!status)
+		return -EINVAL;
+
+	ret = zynqmp_pm_invoke_fn(PM_GET_NODE_STATUS, node, 0, 0,
+				  0, ret_payload);
+	if (ret_payload[0] == XST_PM_SUCCESS) {
+		*status = ret_payload[1];
+		if (requirements)
+			*requirements = ret_payload[2];
+		if (usage)
+			*usage = ret_payload[3];
+	}
+
+	return ret;
+}
+
+/**
+ * zynqmp_pm_get_operating_characteristic - PM call to request operating
+ *						characteristic information
+ * @node:	Node ID of the slave
+ * @type:	Type of the operating characteristic requested
+ * @result:	Used to return the requsted operating characteristic
+ *
+ * Return:	Returns status, either success or error+reason
+ */
+static int zynqmp_pm_get_operating_characteristic(const u32 node,
+		const enum zynqmp_pm_opchar_type type,
+		u32 *const result)
+{
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	int ret;
+
+	if (!result)
+		return -EINVAL;
+
+	ret = zynqmp_pm_invoke_fn(PM_GET_OPERATING_CHARACTERISTIC,
+				  node, type, 0, 0, ret_payload);
+	if (ret_payload[0] == XST_PM_SUCCESS)
+		*result = ret_payload[1];
+
+	return ret;
+}
+
+/**
+ * zynqmp_pm_pinctrl_request - Request Pin from firmware
+ * @pin:	Pin number to request
+ *
+ * This function requests pin from firmware.
+ *
+ * Return:	Returns status, either success or error+reason.
+ */
+static int zynqmp_pm_pinctrl_request(const u32 pin)
+{
+	return zynqmp_pm_invoke_fn(PM_PINCTRL_REQUEST, pin, 0, 0, 0, NULL);
+}
+
+/**
+ * zynqmp_pm_pinctrl_release - Inform firmware that Pin control is released
+ * @pin:	Pin number to release
+ *
+ * This function release pin from firmware.
+ *
+ * Return:	Returns status, either success or error+reason.
+ */
+static int zynqmp_pm_pinctrl_release(const u32 pin)
+{
+	return zynqmp_pm_invoke_fn(PM_PINCTRL_RELEASE, pin, 0, 0, 0, NULL);
+}
+
+/**
+ * zynqmp_pm_pinctrl_get_function - Read function id set for the given pin
+ * @pin:	Pin number
+ * @id:		Buffer to store function ID
+ *
+ * This function provides the function currently set for the given pin.
+ *
+ * Return:	Returns status, either success or error+reason
+ */
+static int zynqmp_pm_pinctrl_get_function(const u32 pin, u32 *id)
+{
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	int ret;
+
+	if (!id)
+		return -EINVAL;
+
+	ret = zynqmp_pm_invoke_fn(PM_PINCTRL_GET_FUNCTION, pin, 0,
+				  0, 0, ret_payload);
+	*id = ret_payload[1];
+
+	return ret;
+}
+
+/**
+ * zynqmp_pm_pinctrl_set_function - Set requested function for the pin
+ * @pin:	Pin number
+ * @id:		Function ID to set
+ *
+ * This function sets requested function for the given pin.
+ *
+ * Return:	Returns status, either success or error+reason.
+ */
+static int zynqmp_pm_pinctrl_set_function(const u32 pin, const u32 id)
+{
+	return zynqmp_pm_invoke_fn(PM_PINCTRL_SET_FUNCTION, pin, id,
+				   0, 0, NULL);
+}
+
+/**
+ * zynqmp_pm_pinctrl_get_config - Get configuration parameter for the pin
+ * @pin:	Pin number
+ * @param:	Parameter to get
+ * @value:	Buffer to store parameter value
+ *
+ * This function gets requested configuration parameter for the given pin.
+ *
+ * Return:	Returns status, either success or error+reason.
+ */
+static int zynqmp_pm_pinctrl_get_config(const u32 pin, const u32 param,
+					u32 *value)
+{
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	int ret;
+
+	if (!value)
+		return -EINVAL;
+
+	ret = zynqmp_pm_invoke_fn(PM_PINCTRL_CONFIG_PARAM_GET, pin, param,
+				  0, 0, ret_payload);
+	*value = ret_payload[1];
+
+	return ret;
+}
+
+/**
+ * zynqmp_pm_pinctrl_set_config - Set configuration parameter for the pin
+ * @pin:	Pin number
+ * @param:	Parameter to set
+ * @value:	Parameter value to set
+ *
+ * This function sets requested configuration parameter for the given pin.
+ *
+ * Return:	Returns status, either success or error+reason.
+ */
+static int zynqmp_pm_pinctrl_set_config(const u32 pin, const u32 param,
+					u32 value)
+{
+	return zynqmp_pm_invoke_fn(PM_PINCTRL_CONFIG_PARAM_SET, pin,
+				   param, value, 0, NULL);
+}
+
+/**
+ * zynqmp_pm_config_reg_access - PM Config API for Config register access
+ * @register_access_id:	ID of the requested REGISTER_ACCESS
+ * @address:		Address of the register to be accessed
+ * @mask:		Mask to be written to the register
+ * @value:		Value to be written to the register
+ * @out:		Returned output value
+ *
+ * This function calls REGISTER_ACCESS to configure CSU/PMU registers.
+ *
+ * Return:	Returns status, either success or error+reason
+ */
+
+static int zynqmp_pm_config_reg_access(u32 register_access_id, u32 address,
+				       u32 mask, u32 value, u32 *out)
+{
+	return zynqmp_pm_invoke_fn(PM_REGISTER_ACCESS, register_access_id,
+				   address, mask, value, out);
+}
+
+/**
+ * zynqmp_pm_efuse_access - Provides access to efuse memory.
+ * @address:	Address of the efuse params structure
+ * @out:		Returned output value
+ *
+ * Return:	Returns status, either success or error code.
+ */
+static int zynqmp_pm_efuse_access(const u64 address, u32 *out)
+{
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	int ret;
+
+	if (!out)
+		return -EINVAL;
+
+	ret = zynqmp_pm_invoke_fn(PM_EFUSE_ACCESS, upper_32_bits(address),
+				  lower_32_bits(address), 0, 0, ret_payload);
+	*out = ret_payload[1];
+
+	return ret;
+}
+
+static int zynqmp_pm_secure_load(const u64 src_addr, u64 key_addr, u64 *dst)
+{
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	int ret_value;
+
+	if (!dst)
+		return -EINVAL;
+
+	ret_value = zynqmp_pm_invoke_fn(PM_SECURE_IMAGE,
+					lower_32_bits(src_addr),
+					upper_32_bits(src_addr),
+					lower_32_bits(key_addr),
+					upper_32_bits(key_addr),
+					ret_payload);
+	*dst = ((u64)ret_payload[1] << 32) | ret_payload[2];
+
+	return ret_value;
+}
+
+/**
+ * zynqmp_pm_get_last_reset_reason() - PM API for getting last reset reason
+ *
+ * @reset_reason:	last reset reason
+ *
+ * This function returns last reset reason
+ *
+ * Return: Returns status, either success or error+reason
+ */
+int zynqmp_pm_get_last_reset_reason(u32 *reset_reason)
+{
+	if (!reset_reason)
+		return -EINVAL;
+
+	return zynqmp_pm_invoke_fn(PM_IOCTL, 0,
+				   IOCTL_GET_LAST_RESET_REASON,
+				   0, 0, reset_reason);
+}
+EXPORT_SYMBOL_GPL(zynqmp_pm_get_last_reset_reason);
+
 static const struct zynqmp_eemi_ops eemi_ops = {
 	.get_api_version = zynqmp_pm_get_api_version,
 	.get_chipid = zynqmp_pm_get_chipid,
@@ -687,6 +1263,29 @@
 	.set_requirement = zynqmp_pm_set_requirement,
 	.fpga_load = zynqmp_pm_fpga_load,
 	.fpga_get_status = zynqmp_pm_fpga_get_status,
+	.fpga_read = zynqmp_pm_fpga_read,
+	.sha_hash = zynqmp_pm_sha_hash,
+	.rsa = zynqmp_pm_rsa,
+	.request_suspend = zynqmp_pm_request_suspend,
+	.force_powerdown = zynqmp_pm_force_powerdown,
+	.request_wakeup = zynqmp_pm_request_wakeup,
+	.set_wakeup_source = zynqmp_pm_set_wakeup_source,
+	.system_shutdown = zynqmp_pm_system_shutdown,
+	.set_max_latency = zynqmp_pm_set_max_latency,
+	.set_configuration = zynqmp_pm_set_configuration,
+	.get_node_status = zynqmp_pm_get_node_status,
+	.get_operating_characteristic = zynqmp_pm_get_operating_characteristic,
+	.pinctrl_request = zynqmp_pm_pinctrl_request,
+	.pinctrl_release = zynqmp_pm_pinctrl_release,
+	.pinctrl_get_function = zynqmp_pm_pinctrl_get_function,
+	.pinctrl_set_function = zynqmp_pm_pinctrl_set_function,
+	.pinctrl_get_config = zynqmp_pm_pinctrl_get_config,
+	.pinctrl_set_config = zynqmp_pm_pinctrl_set_config,
+	.register_access = zynqmp_pm_config_reg_access,
+	.aes = zynqmp_pm_aes_engine,
+	.efuse_access = zynqmp_pm_efuse_access,
+	.pdi_load = zynqmp_pm_load_pdi,
+	.secure_image = zynqmp_pm_secure_load,
 };
 
 /**
@@ -704,6 +1303,386 @@
 }
 EXPORT_SYMBOL_GPL(zynqmp_pm_get_eemi_ops);
 
+/**
+ * struct zynqmp_pm_shutdown_scope - Struct for shutdown scope
+ * @subtype:	Shutdown subtype
+ * @name:	Matching string for scope argument
+ *
+ * This struct encapsulates mapping between shutdown scope ID and string.
+ */
+struct zynqmp_pm_shutdown_scope {
+	const enum zynqmp_pm_shutdown_subtype subtype;
+	const char *name;
+};
+
+static struct zynqmp_pm_shutdown_scope shutdown_scopes[] = {
+	[ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM] = {
+		.subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM,
+		.name = "subsystem",
+	},
+	[ZYNQMP_PM_SHUTDOWN_SUBTYPE_PS_ONLY] = {
+		.subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_PS_ONLY,
+		.name = "ps_only",
+	},
+	[ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM] = {
+		.subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM,
+		.name = "system",
+	},
+};
+
+static struct zynqmp_pm_shutdown_scope *selected_scope =
+		&shutdown_scopes[ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM];
+
+/**
+ * zynqmp_pm_is_shutdown_scope_valid - Check if shutdown scope string is valid
+ * @scope_string:	Shutdown scope string
+ *
+ * Return:		Return pointer to matching shutdown scope struct from
+ *			array of available options in system if string is valid,
+ *			otherwise returns NULL.
+ */
+static struct zynqmp_pm_shutdown_scope*
+		zynqmp_pm_is_shutdown_scope_valid(const char *scope_string)
+{
+	int count;
+
+	for (count = 0; count < ARRAY_SIZE(shutdown_scopes); count++)
+		if (sysfs_streq(scope_string, shutdown_scopes[count].name))
+			return &shutdown_scopes[count];
+
+	return NULL;
+}
+
+/**
+ * shutdown_scope_show - Show shutdown_scope sysfs attribute
+ * @kobj:	Kobject structure
+ * @attr:	Kobject attribute structure
+ * @buf:	Requested available shutdown_scope attributes string
+ *
+ * User-space interface for viewing the available scope options for system
+ * shutdown. Scope option for next shutdown call is marked with [].
+ *
+ * Usage: cat /sys/firmware/zynqmp/shutdown_scope
+ *
+ * Return:	Number of bytes printed into the buffer.
+ */
+static ssize_t shutdown_scope_show(struct kobject *kobj,
+				   struct kobj_attribute *attr,
+				   char *buf)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(shutdown_scopes); i++) {
+		if (&shutdown_scopes[i] == selected_scope) {
+			strcat(buf, "[");
+			strcat(buf, shutdown_scopes[i].name);
+			strcat(buf, "]");
+		} else {
+			strcat(buf, shutdown_scopes[i].name);
+		}
+		strcat(buf, " ");
+	}
+	strcat(buf, "\n");
+
+	return strlen(buf);
+}
+
+/**
+ * shutdown_scope_store - Store shutdown_scope sysfs attribute
+ * @kobj:	Kobject structure
+ * @attr:	Kobject attribute structure
+ * @buf:	User entered shutdown_scope attribute string
+ * @count:	Buffer size
+ *
+ * User-space interface for setting the scope for the next system shutdown.
+ * Usage: echo <scope> > /sys/firmware/zynqmp/shutdown_scope
+ *
+ * The Linux shutdown functionality implemented via PSCI system_off does not
+ * include an option to set a scope, i.e. which parts of the system to shut
+ * down.
+ *
+ * This API function allows to set the shutdown scope for the next shutdown
+ * request by passing it to the ATF running in EL3. When the next shutdown
+ * is performed, the platform specific portion of PSCI-system_off can use
+ * the chosen shutdown scope.
+ *
+ * subsystem:	Only the APU along with all of its peripherals not used by other
+ *		processing units will be shut down. This may result in the FPD
+ *		power domain being shut down provided that no other processing
+ *		unit uses FPD peripherals or DRAM.
+ * ps_only:	The complete PS will be shut down, including the RPU, PMU, etc.
+ *		Only the PL domain (FPGA) remains untouched.
+ * system:	The complete system/device is shut down.
+ *
+ * Return:	count argument if request succeeds, the corresponding error
+ *		code otherwise
+ */
+static ssize_t shutdown_scope_store(struct kobject *kobj,
+				    struct kobj_attribute *attr,
+				    const char *buf, size_t count)
+{
+	int ret;
+	struct zynqmp_pm_shutdown_scope *scope;
+
+	scope = zynqmp_pm_is_shutdown_scope_valid(buf);
+	if (!scope)
+		return -EINVAL;
+
+	ret = zynqmp_pm_system_shutdown(ZYNQMP_PM_SHUTDOWN_TYPE_SETSCOPE_ONLY,
+					scope->subtype);
+	if (ret) {
+		pr_err("unable to set shutdown scope %s\n", buf);
+		return ret;
+	}
+
+	selected_scope = scope;
+
+	return count;
+}
+
+static struct kobj_attribute zynqmp_attr_shutdown_scope =
+						__ATTR_RW(shutdown_scope);
+
+/**
+ * health_status_store - Store health_status sysfs attribute
+ * @kobj:	Kobject structure
+ * @attr:	Kobject attribute structure
+ * @buf:	User entered health_status attribute string
+ * @count:	Buffer size
+ *
+ * User-space interface for setting the boot health status.
+ * Usage: echo <value> > /sys/firmware/zynqmp/health_status
+ *
+ * Value:
+ *	1 - Set healthy bit to 1
+ *	0 - Unset healthy bit
+ *
+ * Return:	count argument if request succeeds, the corresponding error
+ *		code otherwise
+ */
+static ssize_t health_status_store(struct kobject *kobj,
+				   struct kobj_attribute *attr,
+				   const char *buf, size_t count)
+{
+	int ret;
+	unsigned int value;
+
+	ret = kstrtouint(buf, 10, &value);
+	if (ret)
+		return ret;
+
+	ret = zynqmp_pm_ioctl(0, IOCTL_SET_BOOT_HEALTH_STATUS, value, 0, NULL);
+	if (ret) {
+		pr_err("unable to set healthy bit value to %u\n", value);
+		return ret;
+	}
+
+	return count;
+}
+
+static struct kobj_attribute zynqmp_attr_health_status =
+						__ATTR_WO(health_status);
+
+/**
+ * config_reg_store - Write config_reg sysfs attribute
+ * @kobj:	Kobject structure
+ * @attr:	Kobject attribute structure
+ * @buf:	User entered health_status attribute string
+ * @count:	Buffer size
+ *
+ * User-space interface for setting the config register.
+ *
+ * To write any CSU/PMU register
+ * echo <address> <mask> <values> > /sys/firmware/zynqmp/config_reg
+ * Usage:
+ * echo 0x345AB234 0xFFFFFFFF 0x1234ABCD > /sys/firmware/zynqmp/config_reg
+ *
+ * To Read any CSU/PMU register, write address to the variable like below
+ * echo <address> > /sys/firmware/zynqmp/config_reg
+ *
+ * Return:	count argument if request succeeds, the corresponding error
+ *		code otherwise
+ */
+static ssize_t config_reg_store(struct kobject *kobj,
+				struct kobj_attribute *attr,
+				const char *buf, size_t count)
+{
+	char *kern_buff, *inbuf, *tok;
+	unsigned long address, value, mask;
+	int ret;
+
+	kern_buff = kzalloc(count, GFP_KERNEL);
+	if (!kern_buff)
+		return -ENOMEM;
+
+	ret = strlcpy(kern_buff, buf, count);
+	if (ret < 0) {
+		ret = -EFAULT;
+		goto err;
+	}
+
+	inbuf = kern_buff;
+
+	/* Read the addess */
+	tok = strsep(&inbuf, " ");
+	if (!tok) {
+		ret = -EFAULT;
+		goto err;
+	}
+	ret = kstrtol(tok, 16, &address);
+	if (ret) {
+		ret = -EFAULT;
+		goto err;
+	}
+	/* Read the write value */
+	tok = strsep(&inbuf, " ");
+	/*
+	 * If parameter provided is only address, then its a read operation.
+	 * Store the address in a global variable and retrieve whenever
+	 * required.
+	 */
+	if (!tok) {
+		register_address = address;
+		goto err;
+	}
+	register_address = address;
+
+	ret = kstrtol(tok, 16, &mask);
+	if (ret) {
+		ret = -EFAULT;
+		goto err;
+	}
+	tok = strsep(&inbuf, " ");
+	if (!tok) {
+		ret = -EFAULT;
+		goto err;
+	}
+	ret = kstrtol(tok, 16, &value);
+	if (ret) {
+		ret = -EFAULT;
+		goto err;
+	}
+	ret = zynqmp_pm_config_reg_access(CONFIG_REG_WRITE, address,
+					  mask, value, NULL);
+	if (ret)
+		pr_err("unable to write value to %lx\n", value);
+err:
+	kfree(kern_buff);
+	if (ret)
+		return ret;
+	return count;
+}
+
+/**
+ * config_reg_show - Read config_reg sysfs attribute
+ * @kobj:	Kobject structure
+ * @attr:	Kobject attribute structure
+ * @buf:	User entered health_status attribute string
+ *
+ * User-space interface for getting the config register.
+ *
+ * To Read any CSU/PMU register, write address to the variable like below
+ * echo <address> > /sys/firmware/zynqmp/config_reg
+ *
+ * Then Read the address using below command
+ * cat /sys/firmware/zynqmp/config_reg
+ *
+ * Return: number of chars written to buf.
+ */
+static ssize_t config_reg_show(struct kobject *kobj,
+			       struct kobj_attribute *attr,
+			       char *buf)
+{
+	int ret;
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+
+	ret = zynqmp_pm_config_reg_access(CONFIG_REG_READ, register_address,
+					  0, 0, ret_payload);
+	if (ret)
+		return ret;
+
+	return sprintf(buf, "0x%x\n", ret_payload[1]);
+}
+
+static struct kobj_attribute zynqmp_attr_config_reg =
+					__ATTR_RW(config_reg);
+
+static ssize_t last_reset_reason_show(struct kobject *kobj,
+				      struct kobj_attribute *attr,
+				      char *buf)
+{
+	int ret;
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+
+	ret = zynqmp_pm_get_last_reset_reason(ret_payload);
+	if (ret)
+		return ret;
+	switch (ret_payload[1]) {
+	case PM_RESET_REASON_EXT_POR:
+		return sprintf(buf, "ext_por\n");
+	case PM_RESET_REASON_SW_POR:
+		return sprintf(buf, "sw_por\n");
+	case PM_RESET_REASON_SLR_POR:
+		return sprintf(buf, "sl_por\n");
+	case PM_RESET_REASON_ERR_POR:
+		return sprintf(buf, "err_por\n");
+	case PM_RESET_REASON_DAP_SRST:
+		return sprintf(buf, "dap_srst\n");
+	case PM_RESET_REASON_ERR_SRST:
+		return sprintf(buf, "err_srst\n");
+	case PM_RESET_REASON_SW_SRST:
+		return sprintf(buf, "sw_srst\n");
+	case PM_RESET_REASON_SLR_SRST:
+		return sprintf(buf, "slr_srst\n");
+	default:
+		return sprintf(buf, "unknown reset\n");
+	}
+}
+
+static struct kobj_attribute zynqmp_attr_last_reset_reason =
+					__ATTR_RO(last_reset_reason);
+
+static struct attribute *attrs[] = {
+	&zynqmp_attr_shutdown_scope.attr,
+	&zynqmp_attr_health_status.attr,
+	&zynqmp_attr_config_reg.attr,
+	&zynqmp_attr_last_reset_reason.attr,
+	NULL,
+};
+
+static const struct attribute_group attr_group = {
+	.attrs = attrs,
+	NULL,
+};
+
+static int zynqmp_pm_sysfs_init(void)
+{
+	struct kobject *zynqmp_kobj;
+	int ret;
+
+	zynqmp_kobj = kobject_create_and_add("zynqmp", firmware_kobj);
+	if (!zynqmp_kobj) {
+		pr_err("zynqmp: Firmware kobj add failed.\n");
+		return -ENOMEM;
+	}
+
+	ret = sysfs_create_group(zynqmp_kobj, &attr_group);
+	if (ret) {
+		pr_err("%s() sysfs creation fail with error %d\n",
+		       __func__, ret);
+		goto err;
+	}
+
+	ret = zynqmp_pm_ggs_init(zynqmp_kobj);
+	if (ret) {
+		pr_err("%s() GGS init fail with error %d\n",
+		       __func__, ret);
+		goto err;
+	}
+err:
+	return ret;
+}
+
 static int zynqmp_firmware_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -711,8 +1690,13 @@
 	int ret;
 
 	np = of_find_compatible_node(NULL, NULL, "xlnx,zynqmp");
-	if (!np)
-		return 0;
+	if (!np) {
+		np = of_find_compatible_node(NULL, NULL, "xlnx,versal");
+		if (!np)
+			return 0;
+
+		feature_check_enabled = true;
+	}
 	of_node_put(np);
 
 	ret = get_set_conduit_method(dev->of_node);
@@ -748,6 +1732,12 @@
 	/* Assign eemi_ops_table */
 	eemi_ops_tbl = &eemi_ops;
 
+	ret = zynqmp_pm_sysfs_init();
+	if (ret) {
+		pr_err("%s() sysfs init fail with error %d\n", __func__, ret);
+		return ret;
+	}
+
 	zynqmp_pm_api_debugfs_init();
 
 	ret = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, firmware_devs,
@@ -770,6 +1760,7 @@
 
 static const struct of_device_id zynqmp_firmware_of_match[] = {
 	{.compatible = "xlnx,zynqmp-firmware"},
+	{.compatible = "xlnx,versal-firmware"},
 	{},
 };
 MODULE_DEVICE_TABLE(of, zynqmp_firmware_of_match);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/fpga/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/fpga/Kconfig
@@ -12,6 +12,16 @@
 
 if FPGA
 
+config FPGA_MGR_DEBUG_FS
+	tristate "FPGA debug fs"
+	select DEBUG_FS
+	help
+	  Say Y here if you want to expose a DebugFS interface for the
+	  FPGA Manager Framework. FPGA manager DebugFS provides a user
+	  interface to read the fpga specific configuration information.
+
+	  If unsure, say N.
+
 config FPGA_MGR_SOCFPGA
 	tristate "Altera SOCFPGA FPGA Manager"
 	depends on ARCH_SOCFPGA || COMPILE_TEST
@@ -91,6 +101,24 @@
 	  FPGA manager driver support for the Altera Cyclone II FPGA
 	  present on the TS-73xx SBC boards.
 
+config FPGA_MGR_ZYNQ_AFI_FPGA
+	bool "Xilinx AFI FPGA"
+	depends on FPGA_MGR_ZYNQ_FPGA
+	help
+	  Zynq AFI driver support for writing to the AFI registers
+	  for configuring the PS_PL interface. For some of the bitstream
+	  or designs to work the PS to PL interfaces need to be configured
+	  like the data bus-width etc.
+
+config XILINX_AFI_FPGA
+	bool "Xilinx AFI FPGA"
+	depends on FPGA_MGR_ZYNQMP_FPGA || COMPILE_TEST
+	help
+	  FPGA manager driver support for writing to the AFI registers
+	  for configuring the PS_PL interface. For some of the bitstream
+	  or designs to work the PS to PL interfaces need to be configured
+	  like the datawidth etc.
+
 config FPGA_BRIDGE
 	tristate "FPGA Bridge Framework"
 	help
@@ -215,4 +243,13 @@
 	  to configure the programmable logic(PL) through PS
 	  on ZynqMP SoC.
 
+config FPGA_MGR_VERSAL_FPGA
+	tristate "Xilinx Versal FPGA"
+	depends on ARCH_ZYNQMP || COMPILE_TEST
+	help
+	  Select this option to enable FPGA manager driver support for
+	  Xilinx Versal SOC. This driver uses the versal soc firmware
+	  interface to load programmable logic(PL) images
+	  on versal soc.
+
 endif # FPGA
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/fpga/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/fpga/Makefile
@@ -17,7 +17,10 @@
 obj-$(CONFIG_FPGA_MGR_TS73XX)		+= ts73xx-fpga.o
 obj-$(CONFIG_FPGA_MGR_XILINX_SPI)	+= xilinx-spi.o
 obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA)	+= zynq-fpga.o
+obj-$(CONFIG_FPGA_MGR_ZYNQ_AFI_FPGA)	+= zynq-afi.o
 obj-$(CONFIG_FPGA_MGR_ZYNQMP_FPGA)	+= zynqmp-fpga.o
+obj-$(CONFIG_FPGA_MGR_VERSAL_FPGA)	+= versal-fpga.o
+obj-$(CONFIG_XILINX_AFI_FPGA)		+= xilinx-afi.o
 obj-$(CONFIG_ALTERA_PR_IP_CORE)         += altera-pr-ip-core.o
 obj-$(CONFIG_ALTERA_PR_IP_CORE_PLAT)    += altera-pr-ip-core-plat.o
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/fpga/altera-pr-ip-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/fpga/altera-pr-ip-core.c
@@ -108,7 +108,7 @@
 	u32 *buffer_32 = (u32 *)buf;
 	size_t i = 0;
 
-	if (count <= 0)
+	if (!count)
 		return -EINVAL;
 
 	/* Write out the complete 32-bit chunks */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/fpga/dfl-afu-dma-region.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/fpga/dfl-afu-dma-region.c
@@ -61,10 +61,10 @@
 				     region->pages);
 	if (pinned < 0) {
 		ret = pinned;
-		goto put_pages;
+		goto free_pages;
 	} else if (pinned != npages) {
 		ret = -EFAULT;
-		goto free_pages;
+		goto put_pages;
 	}
 
 	dev_dbg(dev, "%d pages pinned\n", pinned);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/fpga/dfl-afu-main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/fpga/dfl-afu-main.c
@@ -83,7 +83,8 @@
 	 * on this port and minimum soft reset pulse width has elapsed.
 	 * Driver polls port_soft_reset_ack to determine if reset done by HW.
 	 */
-	if (readq_poll_timeout(base + PORT_HDR_CTRL, v, v & PORT_CTRL_SFTRST,
+	if (readq_poll_timeout(base + PORT_HDR_CTRL, v,
+			       v & PORT_CTRL_SFTRST_ACK,
 			       RST_POLL_INVL, RST_POLL_TIMEOUT)) {
 		dev_err(&pdev->dev, "timeout, fail to reset device\n");
 		return -ETIMEDOUT;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/fpga/dfl-pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/fpga/dfl-pci.c
@@ -227,7 +227,6 @@
 {
 	struct cci_drvdata *drvdata = pci_get_drvdata(pcidev);
 	struct dfl_fpga_cdev *cdev = drvdata->cdev;
-	int ret = 0;
 
 	if (!num_vfs) {
 		/*
@@ -239,6 +238,8 @@
 		dfl_fpga_cdev_config_ports_pf(cdev);
 
 	} else {
+		int ret;
+
 		/*
 		 * before enable SRIOV, put released ports into VF access mode
 		 * first of all.
@@ -248,11 +249,13 @@
 			return ret;
 
 		ret = pci_enable_sriov(pcidev, num_vfs);
-		if (ret)
+		if (ret) {
 			dfl_fpga_cdev_config_ports_pf(cdev);
+			return ret;
+		}
 	}
 
-	return ret;
+	return num_vfs;
 }
 
 static void cci_pci_remove(struct pci_dev *pcidev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/fpga/fpga-bridge.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/fpga/fpga-bridge.c
@@ -13,6 +13,12 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 
+/* For enabling manual bridge set(enable/disable) function */
+#ifdef CONFIG_DEBUG_KERNEL
+#undef DEBUG
+#define DEBUG
+#endif
+
 static DEFINE_IDA(fpga_bridge_ida);
 static struct class *fpga_bridge_class;
 
@@ -115,7 +121,7 @@
 /**
  * fpga_bridge_get - get an exclusive reference to a fpga bridge
  * @dev:	parent device that fpga bridge was registered with
- * @info:	fpga manager info
+ * @info:	fpga image specific information
  *
  * Given a device, get an exclusive reference to a fpga bridge.
  *
@@ -304,9 +310,33 @@
 static DEVICE_ATTR_RO(name);
 static DEVICE_ATTR_RO(state);
 
+#ifdef DEBUG
+static ssize_t set_store(struct device *dev,
+			 struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	struct fpga_bridge *bridge = to_fpga_bridge(dev);
+	long enable;
+	int ret;
+
+	ret = kstrtol(buf, 16, &enable);
+	if (ret)
+		return ret;
+
+	if (bridge->br_ops && bridge->br_ops->enable_set)
+		enable = bridge->br_ops->enable_set(bridge, !!enable);
+
+	return count;
+}
+static DEVICE_ATTR_WO(set);
+#endif
+
 static struct attribute *fpga_bridge_attrs[] = {
 	&dev_attr_name.attr,
 	&dev_attr_state.attr,
+#ifdef DEBUG
+	&dev_attr_set.attr,
+#endif
 	NULL,
 };
 ATTRIBUTE_GROUPS(fpga_bridge);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/fpga/fpga-mgr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/fpga/fpga-mgr.c
@@ -8,6 +8,8 @@
  * With code from the mailing list:
  * Copyright (C) 2013 Xilinx, Inc.
  */
+#include <linux/dma-buf.h>
+#include <linux/kernel.h>
 #include <linux/firmware.h>
 #include <linux/fpga/fpga-mgr.h>
 #include <linux/idr.h>
@@ -177,6 +179,9 @@
 {
 	int ret;
 
+	if (info->flags & FPGA_MGR_USERKEY_ENCRYPTED_BITSTREAM)
+		memcpy(info->key, mgr->key, ENCRYPTED_KEY_LEN);
+
 	ret = fpga_mgr_write_init_sg(mgr, info, sgt);
 	if (ret)
 		return ret;
@@ -302,6 +307,39 @@
 	return rc;
 }
 
+static int fpga_dmabuf_load(struct fpga_manager *mgr,
+			    struct fpga_image_info *info)
+{
+	struct dma_buf_attachment *attach;
+	struct sg_table *sgt;
+	int ret;
+
+	/* create attachment for dmabuf with the user device */
+	attach = dma_buf_attach(mgr->dmabuf, &mgr->dev);
+	if (IS_ERR(attach)) {
+		pr_err("failed to attach dmabuf\n");
+		ret = PTR_ERR(attach);
+		goto fail_put;
+	}
+
+	sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
+	if (IS_ERR(sgt)) {
+		ret = PTR_ERR(sgt);
+		goto fail_detach;
+	}
+
+	info->sgt = sgt;
+	ret = fpga_mgr_buf_load_sg(mgr, info, info->sgt);
+	dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
+
+fail_detach:
+	dma_buf_detach(mgr->dmabuf, attach);
+fail_put:
+	dma_buf_put(mgr->dmabuf);
+
+	return ret;
+}
+
 /**
  * fpga_mgr_firmware_load - request firmware and load to fpga
  * @mgr:	fpga manager
@@ -328,6 +366,10 @@
 
 	mgr->state = FPGA_MGR_STATE_FIRMWARE_REQ;
 
+	/* flags indicates whether to do full or partial reconfiguration */
+	info->flags = mgr->flags;
+	memcpy(info->key, mgr->key, ENCRYPTED_KEY_LEN);
+
 	ret = request_firmware(&fw, image_name, dev);
 	if (ret) {
 		mgr->state = FPGA_MGR_STATE_FIRMWARE_REQ_ERR;
@@ -354,6 +396,8 @@
  */
 int fpga_mgr_load(struct fpga_manager *mgr, struct fpga_image_info *info)
 {
+	if (info->flags & FPGA_MGR_CONFIG_DMA_BUF)
+		return fpga_dmabuf_load(mgr, info);
 	if (info->sgt)
 		return fpga_mgr_buf_load_sg(mgr, info, info->sgt);
 	if (info->buf && info->count)
@@ -428,18 +472,105 @@
 		len += sprintf(buf + len, "reconfig IP protocol error\n");
 	if (status & FPGA_MGR_STATUS_FIFO_OVERFLOW_ERR)
 		len += sprintf(buf + len, "reconfig fifo overflow error\n");
+	if (status & FPGA_MGR_STATUS_SECURITY_ERR)
+		len += sprintf(buf + len, "reconfig security error\n");
+	if (status & FPGA_MGR_STATUS_DEVICE_INIT_ERR)
+		len += sprintf(buf + len,
+			       "initialization has not finished\n");
+	if (status & FPGA_MGR_STATUS_SIGNAL_ERR)
+		len += sprintf(buf + len, "device internal signal error\n");
+	if (status & FPGA_MGR_STATUS_HIGH_Z_STATE_ERR)
+		len += sprintf(buf + len,
+			       "all I/Os are placed in High-Z state\n");
+	if (status & FPGA_MGR_STATUS_EOS_ERR)
+		len += sprintf(buf + len,
+			       "start-up sequence has not finished\n");
+	if (status & FPGA_MGR_STATUS_FIRMWARE_REQ_ERR)
+		len += sprintf(buf + len, "firmware request error\n");
 
 	return len;
 }
 
+static ssize_t firmware_store(struct device *dev,
+			      struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	struct fpga_manager *mgr = to_fpga_manager(dev);
+	unsigned int len;
+	char image_name[NAME_MAX];
+	int ret;
+
+	/* struct with information about the FPGA image to program. */
+	struct fpga_image_info info = {0};
+
+	/* lose terminating \n */
+	strcpy(image_name, buf);
+	len = strlen(image_name);
+	if (image_name[len - 1] == '\n')
+		image_name[len - 1] = 0;
+
+	ret = fpga_mgr_firmware_load(mgr, &info, image_name);
+	if (ret)
+		return ret;
+
+	return count;
+}
+
+static ssize_t key_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct fpga_manager *mgr = to_fpga_manager(dev);
+
+	return snprintf(buf, ENCRYPTED_KEY_LEN + 1, "%s\n", mgr->key);
+}
+
+static ssize_t key_store(struct device *dev,
+			 struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	struct fpga_manager *mgr = to_fpga_manager(dev);
+
+	memcpy(mgr->key, buf, count);
+
+	return count;
+}
+
+static ssize_t flags_show(struct device *dev,
+			  struct device_attribute *attr, char *buf)
+{
+	struct fpga_manager *mgr = to_fpga_manager(dev);
+
+	return sprintf(buf, "%lx\n", mgr->flags);
+}
+
+static ssize_t flags_store(struct device *dev,
+			   struct device_attribute *attr,
+			   const char *buf, size_t count)
+{
+	struct fpga_manager *mgr = to_fpga_manager(dev);
+	int ret;
+
+	ret = kstrtol(buf, 16, &mgr->flags);
+	if (ret)
+		return ret;
+
+	return count;
+}
+
 static DEVICE_ATTR_RO(name);
 static DEVICE_ATTR_RO(state);
 static DEVICE_ATTR_RO(status);
+static DEVICE_ATTR_WO(firmware);
+static DEVICE_ATTR_RW(flags);
+static DEVICE_ATTR_RW(key);
 
 static struct attribute *fpga_mgr_attrs[] = {
 	&dev_attr_name.attr,
 	&dev_attr_state.attr,
 	&dev_attr_status.attr,
+	&dev_attr_firmware.attr,
+	&dev_attr_flags.attr,
+	&dev_attr_key.attr,
 	NULL,
 };
 ATTRIBUTE_GROUPS(fpga_mgr);
@@ -512,6 +643,104 @@
 }
 EXPORT_SYMBOL_GPL(fpga_mgr_put);
 
+#ifdef CONFIG_FPGA_MGR_DEBUG_FS
+#include <linux/debugfs.h>
+
+static int fpga_mgr_read(struct seq_file *s, void *data)
+{
+	struct fpga_manager *mgr = (struct fpga_manager *)s->private;
+	int ret = 0;
+
+	if (!mgr->mops->read)
+		return -ENOENT;
+
+	if (!mutex_trylock(&mgr->ref_mutex))
+		return -EBUSY;
+
+	if (mgr->state != FPGA_MGR_STATE_OPERATING) {
+		ret = -EPERM;
+		goto err_unlock;
+	}
+
+	/* Read the FPGA configuration data from the fabric */
+	ret = mgr->mops->read(mgr, s);
+	if (ret)
+		dev_err(&mgr->dev, "Error while reading configuration data from FPGA\n");
+
+err_unlock:
+	mutex_unlock(&mgr->ref_mutex);
+
+	return ret;
+}
+
+static int fpga_mgr_read_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, fpga_mgr_read, inode->i_private);
+}
+
+static const struct file_operations fpga_mgr_ops_image = {
+	.owner = THIS_MODULE,
+	.open = fpga_mgr_read_open,
+	.read = seq_read,
+};
+#endif
+
+static int fpga_dmabuf_fd_get(struct file *file, char __user *argp)
+{
+	struct fpga_manager *mgr =  (struct fpga_manager *)(file->private_data);
+	int buffd;
+
+	if (copy_from_user(&buffd, argp, sizeof(buffd)))
+		return -EFAULT;
+
+	mgr->dmabuf = dma_buf_get(buffd);
+	if (IS_ERR_OR_NULL(mgr->dmabuf))
+		return -EINVAL;
+
+	return 0;
+}
+
+static int fpga_device_open(struct inode *inode, struct file *file)
+{
+	struct miscdevice *miscdev = file->private_data;
+	struct fpga_manager *mgr = container_of(miscdev,
+						struct fpga_manager, miscdev);
+
+	file->private_data = mgr;
+
+	return 0;
+}
+
+static int fpga_device_release(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+static long fpga_device_ioctl(struct file *file, unsigned int cmd,
+			      unsigned long arg)
+{
+	char __user *argp = (char __user *)arg;
+	int err;
+
+	switch (cmd) {
+	case FPGA_IOCTL_LOAD_DMA_BUFF:
+		err = fpga_dmabuf_fd_get(file, argp);
+		break;
+	default:
+		err = -ENOTTY;
+	}
+
+	return err;
+}
+
+static const struct file_operations fpga_fops = {
+	.owner		= THIS_MODULE,
+	.open		= fpga_device_open,
+	.release	= fpga_device_release,
+	.unlocked_ioctl	= fpga_device_ioctl,
+	.compat_ioctl	= fpga_device_ioctl,
+};
+
 /**
  * fpga_mgr_lock - Lock FPGA manager for exclusive use
  * @mgr:	fpga manager
@@ -565,8 +794,7 @@
 	int id, ret;
 
 	if (!mops || !mops->write_complete || !mops->state ||
-	    !mops->write_init || (!mops->write && !mops->write_sg) ||
-	    (mops->write && mops->write_sg)) {
+	    !mops->write_init || (!mops->write && !mops->write_sg)) {
 		dev_err(dev, "Attempt to register without fpga_manager_ops\n");
 		return NULL;
 	}
@@ -599,10 +827,28 @@
 	mgr->dev.of_node = dev->of_node;
 	mgr->dev.id = id;
 
+	/* Make device dma capable by inheriting from parent's */
+	set_dma_ops(&mgr->dev, get_dma_ops(dev));
+	ret = dma_coerce_mask_and_coherent(&mgr->dev, dma_get_mask(dev));
+	if (ret) {
+		dev_warn(dev,
+		"Failed to set DMA mask %llx. Trying to continue... %x\n",
+		dma_get_mask(dev), ret);
+	}
+
 	ret = dev_set_name(&mgr->dev, "fpga%d", id);
 	if (ret)
 		goto error_device;
 
+	mgr->miscdev.minor = MISC_DYNAMIC_MINOR;
+	mgr->miscdev.name = kobject_name(&mgr->dev.kobj);
+	mgr->miscdev.fops = &fpga_fops;
+	ret = misc_register(&mgr->miscdev);
+	if (ret) {
+		pr_err("fpga: failed to register misc device.\n");
+		goto error_device;
+	}
+
 	return mgr;
 
 error_device:
@@ -680,6 +926,9 @@
 int fpga_mgr_register(struct fpga_manager *mgr)
 {
 	int ret;
+#ifdef CONFIG_FPGA_MGR_DEBUG_FS
+	struct dentry *d, *parent;
+#endif
 
 	/*
 	 * Initialize framework state by requesting low level driver read state
@@ -692,6 +941,26 @@
 	if (ret)
 		goto error_device;
 
+#ifdef CONFIG_FPGA_MGR_DEBUG_FS
+	mgr->dir = debugfs_create_dir("fpga", NULL);
+	if (!mgr->dir)
+		goto error_device;
+
+	parent = mgr->dir;
+	d = debugfs_create_dir(mgr->dev.kobj.name, parent);
+	if (!d) {
+		debugfs_remove_recursive(parent);
+		goto error_device;
+	}
+
+	parent = d;
+	d = debugfs_create_file("image", 0644, parent, mgr,
+				&fpga_mgr_ops_image);
+	if (!d) {
+		debugfs_remove_recursive(mgr->dir);
+		goto error_device;
+	}
+#endif
 	dev_info(&mgr->dev, "%s registered\n", mgr->name);
 
 	return 0;
@@ -713,6 +982,10 @@
 {
 	dev_info(&mgr->dev, "%s %s\n", __func__, mgr->name);
 
+#ifdef CONFIG_FPGA_MGR_DEBUG_FS
+	debugfs_remove_recursive(mgr->dir);
+#endif
+
 	/*
 	 * If the low level driver provides a method for putting fpga into
 	 * a desired state upon unregister, do it.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/fpga/machxo2-spi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/fpga/machxo2-spi.c
@@ -223,8 +223,10 @@
 		goto fail;
 
 	get_status(spi, &status);
-	if (test_bit(FAIL, &status))
+	if (test_bit(FAIL, &status)) {
+		ret = -EINVAL;
 		goto fail;
+	}
 	dump_status_reg(&status);
 
 	spi_message_init(&msg);
@@ -310,6 +312,7 @@
 	dump_status_reg(&status);
 	if (!test_bit(DONE, &status)) {
 		machxo2_cleanup(mgr);
+		ret = -EINVAL;
 		goto fail;
 	}
 
@@ -331,6 +334,7 @@
 			break;
 		if (++refreshloop == MACHXO2_MAX_REFRESH_LOOP) {
 			machxo2_cleanup(mgr);
+			ret = -EINVAL;
 			goto fail;
 		}
 	} while (1);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/fpga/of-fpga-region.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/fpga/of-fpga-region.c
@@ -228,6 +228,19 @@
 	if (of_property_read_bool(overlay, "encrypted-fpga-config"))
 		info->flags |= FPGA_MGR_ENCRYPTED_BITSTREAM;
 
+	if (of_property_read_bool(overlay, "userkey-encrypted-fpga-config"))
+		info->flags |= FPGA_MGR_USERKEY_ENCRYPTED_BITSTREAM;
+
+	if (of_property_read_bool(overlay, "ddrmem-authenticated-fpga-config"))
+		info->flags |= FPGA_MGR_DDR_MEM_AUTH_BITSTREAM;
+
+	if (of_property_read_bool(overlay,
+				  "securemem-authenticated-fpga-config"))
+		info->flags |= FPGA_MGR_SECURE_MEM_AUTH_BITSTREAM;
+
+	if (of_property_read_bool(overlay, "fpga-config-from-dmabuf"))
+		info->flags |= FPGA_MGR_CONFIG_DMA_BUF;
+
 	if (!of_property_read_string(overlay, "firmware-name",
 				     &firmware_name)) {
 		info->firmware_name = devm_kstrdup(dev, firmware_name,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/fpga/stratix10-soc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/fpga/stratix10-soc.c
@@ -218,9 +218,9 @@
 	/* Allocate buffers from the service layer's pool. */
 	for (i = 0; i < NUM_SVC_BUFS; i++) {
 		kbuf = stratix10_svc_allocate_memory(priv->chan, SVC_BUF_SIZE);
-		if (!kbuf) {
+		if (IS_ERR(kbuf)) {
 			s10_free_buffers(mgr);
-			ret = -ENOMEM;
+			ret = PTR_ERR(kbuf);
 			goto init_done;
 		}
 
@@ -476,6 +476,7 @@
 	struct s10_priv *priv = mgr->priv;
 
 	fpga_mgr_unregister(mgr);
+	fpga_mgr_free(mgr);
 	stratix10_svc_free_channel(priv->chan);
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/fpga/versal-fpga.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/fpga/versal-fpga.c
@@ -0,0 +1,170 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Xilinx, Inc.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/fpga/fpga-mgr.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/string.h>
+#include <linux/firmware/xlnx-zynqmp.h>
+
+/* Constant Definitions */
+#define PDI_SOURCE_TYPE	0xF
+
+/**
+ * struct versal_fpga_priv - Private data structure
+ * @dev:	Device data structure
+ * @flags:	flags which is used to identify the PL Image type
+ */
+struct versal_fpga_priv {
+	struct device *dev;
+	u32 flags;
+};
+
+static int versal_fpga_ops_write_init(struct fpga_manager *mgr,
+				      struct fpga_image_info *info,
+				      const char *buf, size_t size)
+{
+	struct versal_fpga_priv *priv;
+
+	priv = mgr->priv;
+	priv->flags = info->flags;
+
+	return 0;
+}
+
+static int versal_fpga_ops_write_sg(struct fpga_manager *mgr,
+				    struct sg_table *sgt)
+{
+	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
+	dma_addr_t dma_addr;
+	int ret;
+
+	if (IS_ERR_OR_NULL(eemi_ops) || !eemi_ops->fpga_load)
+		return -ENXIO;
+
+	dma_addr = sg_dma_address(sgt->sgl);
+	ret = eemi_ops->pdi_load(PDI_SOURCE_TYPE, dma_addr);
+
+	return ret;
+}
+
+static int versal_fpga_ops_write(struct fpga_manager *mgr,
+				 const char *buf, size_t size)
+{
+	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
+	struct versal_fpga_priv *priv;
+	dma_addr_t dma_addr = 0;
+	char *kbuf;
+	int ret;
+
+	if (IS_ERR(eemi_ops) || !eemi_ops->pdi_load)
+		return -ENXIO;
+
+	priv = mgr->priv;
+
+	kbuf = dma_alloc_coherent(priv->dev, size, &dma_addr, GFP_KERNEL);
+	if (!kbuf)
+		return -ENOMEM;
+
+	memcpy(kbuf, buf, size);
+
+	wmb(); /* ensure all writes are done before initiate FW call */
+
+	ret = eemi_ops->pdi_load(PDI_SOURCE_TYPE, dma_addr);
+
+	dma_free_coherent(priv->dev, size, kbuf, dma_addr);
+
+	return ret;
+}
+
+static int versal_fpga_ops_write_complete(struct fpga_manager *mgr,
+					  struct fpga_image_info *info)
+{
+	return 0;
+}
+
+static enum fpga_mgr_states versal_fpga_ops_state(struct fpga_manager *mgr)
+{
+	return FPGA_MGR_STATE_OPERATING;
+}
+
+static const struct fpga_manager_ops versal_fpga_ops = {
+	.state = versal_fpga_ops_state,
+	.write_init = versal_fpga_ops_write_init,
+	.write = versal_fpga_ops_write,
+	.write_sg = versal_fpga_ops_write_sg,
+	.write_complete = versal_fpga_ops_write_complete,
+};
+
+static int versal_fpga_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct versal_fpga_priv *priv;
+	struct fpga_manager *mgr;
+	int err, ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->dev = dev;
+	ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+	if (ret < 0) {
+		dev_err(dev, "no usable DMA configuration");
+		return ret;
+	}
+
+	mgr = devm_fpga_mgr_create(dev, "Xilinx Versal FPGA Manager",
+				   &versal_fpga_ops, priv);
+	if (!mgr)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, mgr);
+
+	err = fpga_mgr_register(mgr);
+	if (err) {
+		dev_err(dev, "unable to register FPGA manager");
+		fpga_mgr_free(mgr);
+		return err;
+	}
+
+	return 0;
+}
+
+static int versal_fpga_remove(struct platform_device *pdev)
+{
+	struct fpga_manager *mgr = platform_get_drvdata(pdev);
+
+	fpga_mgr_unregister(mgr);
+	fpga_mgr_free(mgr);
+
+	return 0;
+}
+
+static const struct of_device_id versal_fpga_of_match[] = {
+	{ .compatible = "xlnx,versal-fpga", },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, versal_fpga_of_match);
+
+static struct platform_driver versal_fpga_driver = {
+	.probe = versal_fpga_probe,
+	.remove = versal_fpga_remove,
+	.driver = {
+		.name = "versal_fpga_manager",
+		.of_match_table = of_match_ptr(versal_fpga_of_match),
+	},
+};
+
+module_platform_driver(versal_fpga_driver);
+
+MODULE_AUTHOR("Nava kishore Manne <nava.manne@xilinx.com>");
+MODULE_AUTHOR("Appana Durga Kedareswara rao <appanad.durga.rao@xilinx.com>");
+MODULE_DESCRIPTION("Xilinx Versal FPGA Manager");
+MODULE_LICENSE("GPL");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/fpga/xilinx-afi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/fpga/xilinx-afi.c
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx FPGA AFI bridge.
+ * Copyright (c) 2018 Xilinx Inc.
+ */
+
+#include <linux/err.h>
+#include <linux/firmware/xlnx-zynqmp.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+/**
+ * struct afi_fpga - AFI register description
+ * @value: value to be written to the register
+ * @regid: Register id for the register to be written
+ */
+struct afi_fpga {
+	u32 value;
+	u32 regid;
+};
+
+static int afi_fpga_probe(struct platform_device *pdev)
+{
+	struct afi_fpga *afi_fpga;
+	struct device_node *np = pdev->dev.of_node;
+	int ret;
+	int i, entries, pairs;
+	u32 reg, val;
+	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
+
+	if (IS_ERR(eemi_ops))
+		return PTR_ERR(eemi_ops);
+
+	if (!eemi_ops->ioctl)
+		return -ENOTSUPP;
+
+	afi_fpga = devm_kzalloc(&pdev->dev, sizeof(*afi_fpga), GFP_KERNEL);
+	if (!afi_fpga)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, afi_fpga);
+
+	entries = of_property_count_u32_elems(np, "config-afi");
+	if (!entries || (entries % 2)) {
+		dev_err(&pdev->dev, "Invalid number of registers\n");
+		return -EINVAL;
+	}
+	pairs = entries / 2;
+
+	for (i = 0; i < pairs; i++) {
+		ret = of_property_read_u32_index(np, "config-afi", i * 2,
+						 &reg);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to read register\n");
+			return -EINVAL;
+		}
+		ret = of_property_read_u32_index(np, "config-afi", i * 2 + 1,
+						 &val);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to read value\n");
+			return -EINVAL;
+		}
+		ret = eemi_ops->ioctl(0, IOCTL_AFI, reg, val, NULL);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "AFI register write error %d\n",
+				ret);
+			return ret;
+		}
+	}
+	return 0;
+}
+
+static const struct of_device_id afi_fpga_ids[] = {
+	{ .compatible = "xlnx,afi-fpga" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, afi_fpga_ids);
+
+static struct platform_driver afi_fpga_driver = {
+	.driver = {
+		.name = "afi-fpga",
+		.of_match_table = afi_fpga_ids,
+	},
+	.probe = afi_fpga_probe,
+};
+module_platform_driver(afi_fpga_driver);
+
+MODULE_DESCRIPTION("FPGA afi module");
+MODULE_AUTHOR("Shubhrajyoti Datta <shubhrajyoti.datta@xilinx.com>");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/fpga/xilinx-pr-decoupler.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/fpga/xilinx-pr-decoupler.c
@@ -19,10 +19,15 @@
 #define CTRL_OFFSET		0
 
 struct xlnx_pr_decoupler_data {
+	const struct xlnx_config_data *ipconfig;
 	void __iomem *io_base;
 	struct clk *clk;
 };
 
+struct xlnx_config_data {
+	char *name;
+};
+
 static inline void xlnx_pr_decoupler_write(struct xlnx_pr_decoupler_data *d,
 					   u32 offset, u32 val)
 {
@@ -76,15 +81,28 @@
 	.enable_show = xlnx_pr_decoupler_enable_show,
 };
 
+static const struct xlnx_config_data decoupler_config = {
+	.name = "Xilinx PR Decoupler",
+};
+
+static const struct xlnx_config_data shutdown_config = {
+	.name = "Xilinx DFX AXI shutdown mgr",
+};
+
 static const struct of_device_id xlnx_pr_decoupler_of_match[] = {
-	{ .compatible = "xlnx,pr-decoupler-1.00", },
-	{ .compatible = "xlnx,pr-decoupler", },
+	{ .compatible = "xlnx,pr-decoupler-1.00", .data = &decoupler_config },
+	{ .compatible = "xlnx,pr-decoupler", .data = &decoupler_config },
+	{ .compatible = "xlnx,dfx-axi-shutdown-manager-1.00",
+					.data = &shutdown_config },
+	{ .compatible = "xlnx,dfx-axi-shutdown-manager",
+					.data = &shutdown_config },
 	{},
 };
 MODULE_DEVICE_TABLE(of, xlnx_pr_decoupler_of_match);
 
 static int xlnx_pr_decoupler_probe(struct platform_device *pdev)
 {
+	struct device_node *np = pdev->dev.of_node;
 	struct xlnx_pr_decoupler_data *priv;
 	struct fpga_bridge *br;
 	int err;
@@ -94,6 +112,14 @@
 	if (!priv)
 		return -ENOMEM;
 
+	if (np) {
+		const struct of_device_id *match;
+
+		match = of_match_node(xlnx_pr_decoupler_of_match, np);
+		if (match && match->data)
+			priv->ipconfig = match->data;
+	}
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	priv->io_base = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(priv->io_base))
@@ -101,7 +127,8 @@
 
 	priv->clk = devm_clk_get(&pdev->dev, "aclk");
 	if (IS_ERR(priv->clk)) {
-		dev_err(&pdev->dev, "input clock not found\n");
+		if (PTR_ERR(priv->clk) != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "input clock not found\n");
 		return PTR_ERR(priv->clk);
 	}
 
@@ -113,7 +140,7 @@
 
 	clk_disable(priv->clk);
 
-	br = devm_fpga_bridge_create(&pdev->dev, "Xilinx PR Decoupler",
+	br = devm_fpga_bridge_create(&pdev->dev, priv->ipconfig->name,
 				     &xlnx_pr_decoupler_br_ops, priv);
 	if (!br) {
 		err = -ENOMEM;
@@ -124,7 +151,8 @@
 
 	err = fpga_bridge_register(br);
 	if (err) {
-		dev_err(&pdev->dev, "unable to register Xilinx PR Decoupler");
+		dev_err(&pdev->dev, "unable to register %s",
+			priv->ipconfig->name);
 		goto err_clk;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/fpga/zynq-afi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/fpga/zynq-afi.c
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx FPGA AFI driver.
+ * Copyright (c) 2018 Xilinx Inc.
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+/* Registers and special values for doing register-based operations */
+#define AFI_RDCHAN_CTRL_OFFSET	0x00
+#define AFI_WRCHAN_CTRL_OFFSET	0x14
+
+#define AFI_BUSWIDTH_MASK	0x01
+
+/**
+ * struct afi_fpga - AFI register description
+ * @membase:	pointer to register struct
+ * @afi_width:	AFI bus width to be written
+ */
+struct zynq_afi_fpga {
+	void __iomem	*membase;
+	u32		afi_width;
+};
+
+static int zynq_afi_fpga_probe(struct platform_device *pdev)
+{
+	struct zynq_afi_fpga *afi_fpga;
+	struct resource *res;
+	u32 reg_val;
+	u32 val;
+
+	afi_fpga = devm_kzalloc(&pdev->dev, sizeof(*afi_fpga), GFP_KERNEL);
+	if (!afi_fpga)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	afi_fpga->membase = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(afi_fpga->membase))
+		return PTR_ERR(afi_fpga->membase);
+
+	val = device_property_read_u32(&pdev->dev, "xlnx,afi-width",
+				       &afi_fpga->afi_width);
+	if (val) {
+		dev_err(&pdev->dev, "Fail to get the afi bus width\n");
+		return -EINVAL;
+	}
+
+	reg_val = readl(afi_fpga->membase + AFI_RDCHAN_CTRL_OFFSET);
+	reg_val &= ~AFI_BUSWIDTH_MASK;
+	writel(reg_val | afi_fpga->afi_width,
+	       afi_fpga->membase + AFI_RDCHAN_CTRL_OFFSET);
+	reg_val = readl(afi_fpga->membase + AFI_WRCHAN_CTRL_OFFSET);
+	reg_val &= ~AFI_BUSWIDTH_MASK;
+	writel(reg_val | afi_fpga->afi_width,
+	       afi_fpga->membase + AFI_WRCHAN_CTRL_OFFSET);
+
+	return 0;
+}
+
+static const struct of_device_id zynq_afi_fpga_ids[] = {
+	{ .compatible = "xlnx,zynq-afi-fpga" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, zynq_afi_fpga_ids);
+
+static struct platform_driver zynq_afi_fpga_driver = {
+	.driver = {
+		.name = "zynq-afi-fpga",
+		.of_match_table = zynq_afi_fpga_ids,
+	},
+	.probe = zynq_afi_fpga_probe,
+};
+module_platform_driver(zynq_afi_fpga_driver);
+
+MODULE_DESCRIPTION("ZYNQ FPGA AFI module");
+MODULE_AUTHOR("Nava kishore Manne <nava.manne@xilinx.com>");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/fpga/zynq-fpga.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/fpga/zynq-fpga.c
@@ -275,7 +275,7 @@
 
 	/* don't globally reset PL if we're doing partial reconfig */
 	if (!(info->flags & FPGA_MGR_PARTIAL_RECONFIG)) {
-		if (!zynq_fpga_has_sync(buf, count)) {
+		if (!zynq_fpga_has_sync((u8 *)buf, count)) {
 			dev_err(&mgr->dev,
 				"Invalid bitstream, could not find a sync word. Bitstream must be a byte swapped .bin file\n");
 			err = -EINVAL;
@@ -585,7 +585,8 @@
 
 	priv->clk = devm_clk_get(dev, "ref_clk");
 	if (IS_ERR(priv->clk)) {
-		dev_err(dev, "input clock not found\n");
+		if (PTR_ERR(priv->clk) != -EPROBE_DEFER)
+			dev_err(dev, "input clock not found\n");
 		return PTR_ERR(priv->clk);
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/fpga/zynqmp-fpga.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/fpga/zynqmp-fpga.c
@@ -9,20 +9,78 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/of_address.h>
+#include <linux/seq_file.h>
 #include <linux/string.h>
 #include <linux/firmware/xlnx-zynqmp.h>
 
 /* Constant Definitions */
 #define IXR_FPGA_DONE_MASK	BIT(3)
 
+#define READ_DMA_SIZE		0x200
+#define DUMMY_FRAMES_SIZE	0x64
+
+/* Error Register */
+#define IXR_FPGA_ERR_CRC_ERR		BIT(0)
+#define IXR_FPGA_ERR_SECURITY_ERR	BIT(16)
+
+/* Signal Status Register */
+#define IXR_FPGA_END_OF_STARTUP		BIT(4)
+#define IXR_FPGA_GST_CFG_B		BIT(5)
+#define IXR_FPGA_INIT_B_INTERNAL	BIT(11)
+#define IXR_FPGA_DONE_INTERNAL_SIGNAL	BIT(13)
+
+#define IXR_FPGA_CONFIG_STAT_OFFSET	7U
+#define IXR_FPGA_READ_CONFIG_TYPE	0U
+
+static bool readback_type;
+module_param(readback_type, bool, 0644);
+MODULE_PARM_DESC(readback_type,
+		 "readback_type 0-configuration register read "
+		 "1- configuration data read (default: 0)");
+
+/**
+ * struct zynqmp_configreg - Configuration register offsets
+ * @reg:	Name of the configuration register.
+ * @offset:	Register offset.
+ */
+struct zynqmp_configreg {
+	char *reg;
+	u32 offset;
+};
+
+static struct zynqmp_configreg cfgreg[] = {
+	{.reg = "CRC",		.offset = 0},
+	{.reg = "FAR",		.offset = 1},
+	{.reg = "FDRI",		.offset = 2},
+	{.reg = "FDRO",		.offset = 3},
+	{.reg = "CMD",		.offset = 4},
+	{.reg = "CTRL0",	.offset = 5},
+	{.reg = "MASK",		.offset = 6},
+	{.reg = "STAT",		.offset = 7},
+	{.reg = "LOUT",		.offset = 8},
+	{.reg = "COR0",		.offset = 9},
+	{.reg = "MFWR",		.offset = 10},
+	{.reg = "CBC",		.offset = 11},
+	{.reg = "IDCODE",	.offset = 12},
+	{.reg = "AXSS",		.offset = 13},
+	{.reg = "COR1",		.offset = 14},
+	{.reg = "WBSTR",	.offset = 16},
+	{.reg = "TIMER",	.offset = 17},
+	{.reg = "BOOTSTS",	.offset = 22},
+	{.reg = "CTRL1",	.offset = 24},
+	{}
+};
+
 /**
  * struct zynqmp_fpga_priv - Private data structure
  * @dev:	Device data structure
  * @flags:	flags which is used to identify the bitfile type
+ * @size:	Size of the Bit-stream used for readback
  */
 struct zynqmp_fpga_priv {
 	struct device *dev;
 	u32 flags;
+	u32 size;
 };
 
 static int zynqmp_fpga_ops_write_init(struct fpga_manager *mgr,
@@ -42,8 +100,9 @@
 {
 	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
 	struct zynqmp_fpga_priv *priv;
-	dma_addr_t dma_addr;
+	dma_addr_t dma_addr = 0;
 	u32 eemi_flags = 0;
+	size_t dma_size;
 	char *kbuf;
 	int ret;
 
@@ -51,21 +110,105 @@
 		return -ENXIO;
 
 	priv = mgr->priv;
+	priv->size = size;
 
-	kbuf = dma_alloc_coherent(priv->dev, size, &dma_addr, GFP_KERNEL);
+	if (priv->flags & FPGA_MGR_USERKEY_ENCRYPTED_BITSTREAM)
+		dma_size = size + ENCRYPTED_KEY_LEN;
+	else
+		dma_size = size;
+
+	kbuf = dma_alloc_coherent(priv->dev, dma_size, &dma_addr, GFP_KERNEL);
 	if (!kbuf)
 		return -ENOMEM;
 
 	memcpy(kbuf, buf, size);
 
+	if (priv->flags & FPGA_MGR_USERKEY_ENCRYPTED_BITSTREAM) {
+		eemi_flags |= XILINX_ZYNQMP_PM_FPGA_ENCRYPTION_USERKEY;
+		memcpy(kbuf + size, mgr->key, ENCRYPTED_KEY_LEN);
+	} else if (priv->flags & FPGA_MGR_ENCRYPTED_BITSTREAM) {
+		eemi_flags |= XILINX_ZYNQMP_PM_FPGA_ENCRYPTION_DEVKEY;
+	}
+
 	wmb(); /* ensure all writes are done before initiate FW call */
 
+	if (priv->flags & FPGA_MGR_DDR_MEM_AUTH_BITSTREAM)
+		eemi_flags |= XILINX_ZYNQMP_PM_FPGA_AUTHENTICATION_DDR;
+	else if (priv->flags & FPGA_MGR_SECURE_MEM_AUTH_BITSTREAM)
+		eemi_flags |= XILINX_ZYNQMP_PM_FPGA_AUTHENTICATION_OCM;
+
 	if (priv->flags & FPGA_MGR_PARTIAL_RECONFIG)
 		eemi_flags |= XILINX_ZYNQMP_PM_FPGA_PARTIAL;
 
-	ret = eemi_ops->fpga_load(dma_addr, size, eemi_flags);
+	if (priv->flags & FPGA_MGR_USERKEY_ENCRYPTED_BITSTREAM)
+		ret = eemi_ops->fpga_load(dma_addr, dma_addr + size,
+					  eemi_flags);
+	else
+		ret = eemi_ops->fpga_load(dma_addr, size, eemi_flags);
 
-	dma_free_coherent(priv->dev, size, kbuf, dma_addr);
+	dma_free_coherent(priv->dev, dma_size, kbuf, dma_addr);
+
+	return ret;
+}
+
+static unsigned long zynqmp_fpga_get_contiguous_size(struct sg_table *sgt)
+{
+	dma_addr_t expected = sg_dma_address(sgt->sgl);
+	unsigned long size = 0;
+	struct scatterlist *s;
+	unsigned int i;
+
+	for_each_sg(sgt->sgl, s, sgt->nents, i) {
+		if (sg_dma_address(s) != expected)
+			break;
+		expected = sg_dma_address(s) + sg_dma_len(s);
+		size += sg_dma_len(s);
+	}
+
+	return size;
+}
+
+static int zynqmp_fpga_ops_write_sg(struct fpga_manager *mgr,
+				    struct sg_table *sgt)
+{
+	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
+	dma_addr_t dma_addr, key_addr = 0;
+	struct zynqmp_fpga_priv *priv;
+	unsigned long contig_size;
+	u32 eemi_flags = 0;
+	char *kbuf;
+	int ret;
+
+	if (IS_ERR_OR_NULL(eemi_ops) || !eemi_ops->fpga_load)
+		return -ENXIO;
+
+	priv = mgr->priv;
+
+	dma_addr = sg_dma_address(sgt->sgl);
+	contig_size = zynqmp_fpga_get_contiguous_size(sgt);
+
+	if (priv->flags & FPGA_MGR_PARTIAL_RECONFIG)
+		eemi_flags |= XILINX_ZYNQMP_PM_FPGA_PARTIAL;
+	if (priv->flags & FPGA_MGR_USERKEY_ENCRYPTED_BITSTREAM)
+		eemi_flags |= XILINX_ZYNQMP_PM_FPGA_ENCRYPTION_USERKEY;
+	else if (priv->flags & FPGA_MGR_ENCRYPTED_BITSTREAM)
+		eemi_flags |= XILINX_ZYNQMP_PM_FPGA_ENCRYPTION_DEVKEY;
+	if (priv->flags & FPGA_MGR_DDR_MEM_AUTH_BITSTREAM)
+		eemi_flags |= XILINX_ZYNQMP_PM_FPGA_AUTHENTICATION_DDR;
+	else if (priv->flags & FPGA_MGR_SECURE_MEM_AUTH_BITSTREAM)
+		eemi_flags |= XILINX_ZYNQMP_PM_FPGA_AUTHENTICATION_OCM;
+
+	if (priv->flags & FPGA_MGR_USERKEY_ENCRYPTED_BITSTREAM) {
+		kbuf = dma_alloc_coherent(priv->dev, ENCRYPTED_KEY_LEN,
+					  &key_addr, GFP_KERNEL);
+		if (!kbuf)
+			return -ENOMEM;
+		memcpy(kbuf, mgr->key, ENCRYPTED_KEY_LEN);
+		ret = eemi_ops->fpga_load(dma_addr, key_addr, eemi_flags);
+		dma_free_coherent(priv->dev, ENCRYPTED_KEY_LEN, kbuf, key_addr);
+	} else {
+		ret = eemi_ops->fpga_load(dma_addr, contig_size, eemi_flags);
+	}
 
 	return ret;
 }
@@ -91,11 +234,138 @@
 	return FPGA_MGR_STATE_UNKNOWN;
 }
 
+static u64 zynqmp_fpga_ops_status(struct fpga_manager *mgr)
+{
+	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
+	unsigned int *buf, reg_val;
+	dma_addr_t dma_addr = 0;
+	u64 status = 0;
+	int ret;
+
+	if (IS_ERR_OR_NULL(eemi_ops) || !eemi_ops->fpga_read)
+		return FPGA_MGR_STATUS_FIRMWARE_REQ_ERR;
+
+	buf = dma_alloc_coherent(mgr->dev.parent, READ_DMA_SIZE,
+				 &dma_addr, GFP_KERNEL);
+	if (!buf)
+		return FPGA_MGR_STATUS_FIRMWARE_REQ_ERR;
+
+	ret = eemi_ops->fpga_read(IXR_FPGA_CONFIG_STAT_OFFSET, dma_addr,
+				  IXR_FPGA_READ_CONFIG_TYPE, &reg_val);
+	if (ret) {
+		status = FPGA_MGR_STATUS_FIRMWARE_REQ_ERR;
+		goto free_dmabuf;
+	}
+
+	if (reg_val & IXR_FPGA_ERR_CRC_ERR)
+		status |= FPGA_MGR_STATUS_CRC_ERR;
+	if (reg_val & IXR_FPGA_ERR_SECURITY_ERR)
+		status |= FPGA_MGR_STATUS_SECURITY_ERR;
+	if (!(reg_val & IXR_FPGA_INIT_B_INTERNAL))
+		status |= FPGA_MGR_STATUS_DEVICE_INIT_ERR;
+	if (!(reg_val & IXR_FPGA_DONE_INTERNAL_SIGNAL))
+		status |= FPGA_MGR_STATUS_SIGNAL_ERR;
+	if (!(reg_val & IXR_FPGA_GST_CFG_B))
+		status |= FPGA_MGR_STATUS_HIGH_Z_STATE_ERR;
+	if (!(reg_val & IXR_FPGA_END_OF_STARTUP))
+		status |= FPGA_MGR_STATUS_EOS_ERR;
+
+free_dmabuf:
+	dma_free_coherent(mgr->dev.parent, READ_DMA_SIZE, buf, dma_addr);
+
+	return status;
+}
+
+static int zynqmp_fpga_read_cfgreg(struct fpga_manager *mgr,
+				   struct seq_file *s)
+{
+	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
+	int ret = 0;
+	u32 val;
+	unsigned int *buf;
+	dma_addr_t dma_addr = 0;
+	struct zynqmp_configreg *p = cfgreg;
+
+	buf = dma_alloc_coherent(mgr->dev.parent, READ_DMA_SIZE,
+				 &dma_addr, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	seq_puts(s, "zynqMP FPGA Configuration register contents are\n");
+
+	while (p->reg) {
+		ret = eemi_ops->fpga_read(p->offset, dma_addr, readback_type,
+					  &val);
+		if (ret)
+			goto free_dmabuf;
+		seq_printf(s, "%s --> \t %x \t\r\n", p->reg, val);
+		p++;
+	}
+
+free_dmabuf:
+	dma_free_coherent(mgr->dev.parent, READ_DMA_SIZE, buf,
+			  dma_addr);
+
+	return ret;
+}
+
+static int zynqmp_fpga_read_cfgdata(struct fpga_manager *mgr,
+				    struct seq_file *s)
+{
+	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
+	struct zynqmp_fpga_priv *priv;
+	int ret;
+	u32 data_offset;
+	unsigned int *buf;
+	dma_addr_t dma_addr = 0;
+	size_t size;
+
+	priv = mgr->priv;
+	size = priv->size + READ_DMA_SIZE + DUMMY_FRAMES_SIZE;
+
+	buf = dma_alloc_coherent(mgr->dev.parent, size, &dma_addr,
+				 GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	seq_puts(s, "zynqMP FPGA Configuration data contents are\n");
+	ret = eemi_ops->fpga_read((priv->size + DUMMY_FRAMES_SIZE) / 4,
+				  dma_addr, readback_type, &data_offset);
+	if (ret)
+		goto free_dmabuf;
+
+	seq_write(s, &buf[data_offset], priv->size);
+
+free_dmabuf:
+	dma_free_coherent(mgr->dev.parent, size, buf, dma_addr);
+
+	return ret;
+}
+
+static int zynqmp_fpga_ops_read(struct fpga_manager *mgr, struct seq_file *s)
+{
+	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
+	int ret;
+
+	if (!eemi_ops || !eemi_ops->fpga_read)
+		return -ENXIO;
+
+	if (readback_type)
+		ret = zynqmp_fpga_read_cfgdata(mgr, s);
+	else
+		ret = zynqmp_fpga_read_cfgreg(mgr, s);
+
+	return ret;
+}
+
 static const struct fpga_manager_ops zynqmp_fpga_ops = {
 	.state = zynqmp_fpga_ops_state,
+	.status = zynqmp_fpga_ops_status,
 	.write_init = zynqmp_fpga_ops_write_init,
 	.write = zynqmp_fpga_ops_write,
+	.write_sg = zynqmp_fpga_ops_write_sg,
 	.write_complete = zynqmp_fpga_ops_write_complete,
+	.read = zynqmp_fpga_ops_read,
 };
 
 static int zynqmp_fpga_probe(struct platform_device *pdev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/fsi/fsi-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/fsi/fsi-core.c
@@ -544,6 +544,31 @@
 	return 0;
 }
 
+static unsigned long aligned_access_size(size_t offset, size_t count)
+{
+	unsigned long offset_unit, count_unit;
+
+	/* Criteria:
+	 *
+	 * 1. Access size must be less than or equal to the maximum access
+	 *    width or the highest power-of-two factor of offset
+	 * 2. Access size must be less than or equal to the amount specified by
+	 *    count
+	 *
+	 * The access width is optimal if we can calculate 1 to be strictly
+	 * equal while still satisfying 2.
+	 */
+
+	/* Find 1 by the bottom bit of offset (with a 4 byte access cap) */
+	offset_unit = BIT(__builtin_ctzl(offset | 4));
+
+	/* Find 2 by the top bit of count */
+	count_unit = BIT(8 * sizeof(unsigned long) - 1 - __builtin_clzl(count));
+
+	/* Constrain the maximum access width to the minimum of both criteria */
+	return BIT(__builtin_ctzl(offset_unit | count_unit));
+}
+
 static ssize_t fsi_slave_sysfs_raw_read(struct file *file,
 		struct kobject *kobj, struct bin_attribute *attr, char *buf,
 		loff_t off, size_t count)
@@ -559,8 +584,7 @@
 		return -EINVAL;
 
 	for (total_len = 0; total_len < count; total_len += read_len) {
-		read_len = min_t(size_t, count, 4);
-		read_len -= off & 0x3;
+		read_len = aligned_access_size(off, count - total_len);
 
 		rc = fsi_slave_read(slave, off, buf + total_len, read_len);
 		if (rc)
@@ -587,8 +611,7 @@
 		return -EINVAL;
 
 	for (total_len = 0; total_len < count; total_len += write_len) {
-		write_len = min_t(size_t, count, 4);
-		write_len -= off & 0x3;
+		write_len = aligned_access_size(off, count - total_len);
 
 		rc = fsi_slave_write(slave, off, buf + total_len, write_len);
 		if (rc)
@@ -695,7 +718,7 @@
 	rc = count;
  fail:
 	*offset = off;
-	return count;
+	return rc;
 }
 
 static ssize_t cfam_write(struct file *filep, const char __user *buf,
@@ -732,7 +755,7 @@
 	rc = count;
  fail:
 	*offset = off;
-	return count;
+	return rc;
 }
 
 static loff_t cfam_llseek(struct file *file, loff_t offset, int whence)
@@ -1248,6 +1271,9 @@
 
 	mutex_init(&master->scan_lock);
 	master->idx = ida_simple_get(&master_ida, 0, INT_MAX, GFP_KERNEL);
+	if (master->idx < 0)
+		return master->idx;
+
 	dev_set_name(&master->dev, "fsi%d", master->idx);
 
 	rc = device_register(&master->dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/fsi/fsi-master-ast-cf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/fsi/fsi-master-ast-cf.c
@@ -1438,3 +1438,4 @@
 
 module_platform_driver(fsi_master_acf);
 MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(FW_FILE_NAME);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/fsi/fsi-occ.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/fsi/fsi-occ.c
@@ -445,6 +445,7 @@
 			goto done;
 
 		if (resp->return_status == OCC_RESP_CMD_IN_PRG ||
+		    resp->return_status == OCC_RESP_CRIT_INIT ||
 		    resp->seq_no != seq_no) {
 			rc = -ETIMEDOUT;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/fsi/fsi-sbefifo.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/fsi/fsi-sbefifo.c
@@ -325,7 +325,8 @@
 static int sbefifo_request_reset(struct sbefifo *sbefifo)
 {
 	struct device *dev = &sbefifo->fsi_dev->dev;
-	u32 status, timeout;
+	unsigned long end_time;
+	u32 status;
 	int rc;
 
 	dev_dbg(dev, "Requesting FIFO reset\n");
@@ -341,7 +342,8 @@
 	}
 
 	/* Wait for it to complete */
-	for (timeout = 0; timeout < SBEFIFO_RESET_TIMEOUT; timeout++) {
+	end_time = jiffies + msecs_to_jiffies(SBEFIFO_RESET_TIMEOUT);
+	while (!time_after(jiffies, end_time)) {
 		rc = sbefifo_regr(sbefifo, SBEFIFO_UP | SBEFIFO_STS, &status);
 		if (rc) {
 			dev_err(dev, "Failed to read UP fifo status during reset"
@@ -355,7 +357,7 @@
 			return 0;
 		}
 
-		msleep(1);
+		cond_resched();
 	}
 	dev_err(dev, "FIFO reset timed out\n");
 
@@ -400,7 +402,7 @@
 	/* The FIFO already contains a reset request from the SBE ? */
 	if (down_status & SBEFIFO_STS_RESET_REQ) {
 		dev_info(dev, "Cleanup: FIFO reset request set, resetting\n");
-		rc = sbefifo_regw(sbefifo, SBEFIFO_UP, SBEFIFO_PERFORM_RESET);
+		rc = sbefifo_regw(sbefifo, SBEFIFO_DOWN, SBEFIFO_PERFORM_RESET);
 		if (rc) {
 			sbefifo->broken = true;
 			dev_err(dev, "Cleanup: Reset reg write failed, rc=%d\n", rc);
@@ -638,7 +640,7 @@
 	}
         ffdc_iov.iov_base = ffdc;
 	ffdc_iov.iov_len = SBEFIFO_MAX_FFDC_SIZE;
-        iov_iter_kvec(&ffdc_iter, WRITE, &ffdc_iov, 1, SBEFIFO_MAX_FFDC_SIZE);
+        iov_iter_kvec(&ffdc_iter, READ, &ffdc_iov, 1, SBEFIFO_MAX_FFDC_SIZE);
 	cmd[0] = cpu_to_be32(2);
 	cmd[1] = cpu_to_be32(SBEFIFO_CMD_GET_SBE_FFDC);
 	rc = sbefifo_do_command(sbefifo, cmd, 2, &ffdc_iter);
@@ -735,7 +737,7 @@
 	rbytes = (*resp_len) * sizeof(__be32);
 	resp_iov.iov_base = response;
 	resp_iov.iov_len = rbytes;
-        iov_iter_kvec(&resp_iter, WRITE, &resp_iov, 1, rbytes);
+        iov_iter_kvec(&resp_iter, READ, &resp_iov, 1, rbytes);
 
 	/* Perform the command */
 	mutex_lock(&sbefifo->lock);
@@ -815,7 +817,7 @@
 	/* Prepare iov iterator */
 	resp_iov.iov_base = buf;
 	resp_iov.iov_len = len;
-	iov_iter_init(&resp_iter, WRITE, &resp_iov, 1, len);
+	iov_iter_init(&resp_iter, READ, &resp_iov, 1, len);
 
 	/* Perform the command */
 	mutex_lock(&sbefifo->lock);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/fsi/fsi-scom.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/fsi/fsi-scom.c
@@ -38,9 +38,10 @@
 #define SCOM_STATUS_PIB_RESP_MASK	0x00007000
 #define SCOM_STATUS_PIB_RESP_SHIFT	12
 
-#define SCOM_STATUS_ANY_ERR		(SCOM_STATUS_PROTECTION | \
-					 SCOM_STATUS_PARITY |	  \
-					 SCOM_STATUS_PIB_ABORT | \
+#define SCOM_STATUS_FSI2PIB_ERROR	(SCOM_STATUS_PROTECTION |	\
+					 SCOM_STATUS_PARITY |		\
+					 SCOM_STATUS_PIB_ABORT)
+#define SCOM_STATUS_ANY_ERR		(SCOM_STATUS_FSI2PIB_ERROR |	\
 					 SCOM_STATUS_PIB_RESP_MASK)
 /* SCOM address encodings */
 #define XSCOM_ADDR_IND_FLAG		BIT_ULL(63)
@@ -240,13 +241,14 @@
 {
 	uint32_t dummy = -1;
 
-	if (status & SCOM_STATUS_PROTECTION)
-		return -EPERM;
-	if (status & SCOM_STATUS_PARITY) {
+	if (status & SCOM_STATUS_FSI2PIB_ERROR)
 		fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG, &dummy,
 				 sizeof(uint32_t));
+
+	if (status & SCOM_STATUS_PROTECTION)
+		return -EPERM;
+	if (status & SCOM_STATUS_PARITY)
 		return -EIO;
-	}
 	/* Return -EBUSY on PIB abort to force a retry */
 	if (status & SCOM_STATUS_PIB_ABORT)
 		return -EBUSY;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gnss/sirf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gnss/sirf.c
@@ -439,14 +439,18 @@
 
 	data->on_off = devm_gpiod_get_optional(dev, "sirf,onoff",
 			GPIOD_OUT_LOW);
-	if (IS_ERR(data->on_off))
+	if (IS_ERR(data->on_off)) {
+		ret = PTR_ERR(data->on_off);
 		goto err_put_device;
+	}
 
 	if (data->on_off) {
 		data->wakeup = devm_gpiod_get_optional(dev, "sirf,wakeup",
 				GPIOD_IN);
-		if (IS_ERR(data->wakeup))
+		if (IS_ERR(data->wakeup)) {
+			ret = PTR_ERR(data->wakeup);
 			goto err_put_device;
+		}
 
 		ret = regulator_enable(data->vcc);
 		if (ret)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/Kconfig
@@ -546,7 +546,6 @@
 	tristate "Cavium ThunderX/OCTEON-TX GPIO"
 	depends on ARCH_THUNDER || (64BIT && COMPILE_TEST)
 	depends on PCI_MSI
-	select GPIOLIB_IRQCHIP
 	select IRQ_DOMAIN_HIERARCHY
 	select IRQ_FASTEOI_HIERARCHY_HANDLERS
 	help
@@ -1121,6 +1120,7 @@
 config GPIO_MAX77620
 	tristate "GPIO support for PMIC MAX77620 and MAX20024"
 	depends on MFD_MAX77620
+	select GPIOLIB_IRQCHIP
 	help
 	  GPIO driver for MAX77620 and MAX20024 PMIC from Maxim Semiconductor.
 	  MAX77620 PMIC has 8 pins that can be configured as GPIOs. The
@@ -1230,8 +1230,9 @@
 	  drivers are loaded.
 
 config GPIO_TQMX86
-	tristate "TQ-Systems QTMX86 GPIO"
+	tristate "TQ-Systems TQMx86 GPIO"
 	depends on MFD_TQMX86 || COMPILE_TEST
+	depends on HAS_IOPORT_MAP
 	select GPIOLIB_IRQCHIP
 	help
 	  This driver supports GPIO on the TQMX86 IO controller.
@@ -1299,6 +1300,7 @@
 config GPIO_AMD8111
 	tristate "AMD 8111 GPIO driver"
 	depends on X86 || COMPILE_TEST
+	depends on HAS_IOPORT_MAP
 	help
 	  The AMD 8111 south bridge contains 32 GPIO pins which can be used.
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-74x164.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-74x164.c
@@ -128,8 +128,6 @@
 	if (IS_ERR(chip->gpiod_oe))
 		return PTR_ERR(chip->gpiod_oe);
 
-	gpiod_set_value_cansleep(chip->gpiod_oe, 1);
-
 	spi_set_drvdata(spi, chip);
 
 	chip->gpio_chip.label = spi->modalias;
@@ -154,6 +152,8 @@
 		goto exit_destroy;
 	}
 
+	gpiod_set_value_cansleep(chip->gpiod_oe, 1);
+
 	ret = gpiochip_add_data(&chip->gpio_chip, chip);
 	if (!ret)
 		return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-amd8111.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-amd8111.c
@@ -231,7 +231,10 @@
 		ioport_unmap(gp.pm);
 		goto out;
 	}
+	return 0;
+
 out:
+	pci_dev_put(pdev);
 	return err;
 }
 
@@ -239,6 +242,7 @@
 {
 	gpiochip_remove(&gp.chip);
 	ioport_unmap(gp.pm);
+	pci_dev_put(gp.pdev);
 }
 
 module_init(amd_gpio_init);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-arizona.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-arizona.c
@@ -64,6 +64,7 @@
 		ret = pm_runtime_get_sync(chip->parent);
 		if (ret < 0) {
 			dev_err(chip->parent, "Failed to resume: %d\n", ret);
+			pm_runtime_put_autosuspend(chip->parent);
 			return ret;
 		}
 
@@ -72,12 +73,15 @@
 		if (ret < 0) {
 			dev_err(chip->parent, "Failed to drop cache: %d\n",
 				ret);
+			pm_runtime_put_autosuspend(chip->parent);
 			return ret;
 		}
 
 		ret = regmap_read(arizona->regmap, reg, &val);
-		if (ret < 0)
+		if (ret < 0) {
+			pm_runtime_put_autosuspend(chip->parent);
 			return ret;
+		}
 
 		pm_runtime_mark_last_busy(chip->parent);
 		pm_runtime_put_autosuspend(chip->parent);
@@ -106,6 +110,7 @@
 		ret = pm_runtime_get_sync(chip->parent);
 		if (ret < 0) {
 			dev_err(chip->parent, "Failed to resume: %d\n", ret);
+			pm_runtime_put(chip->parent);
 			return ret;
 		}
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-aspeed.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-aspeed.c
@@ -53,7 +53,7 @@
 struct aspeed_gpio {
 	struct gpio_chip chip;
 	struct irq_chip irqc;
-	spinlock_t lock;
+	raw_spinlock_t lock;
 	void __iomem *base;
 	int irq;
 	const struct aspeed_gpio_config *config;
@@ -404,6 +404,8 @@
 	gpio->dcache[GPIO_BANK(offset)] = reg;
 
 	iowrite32(reg, addr);
+	/* Flush write */
+	ioread32(addr);
 }
 
 static void aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset,
@@ -413,14 +415,14 @@
 	unsigned long flags;
 	bool copro;
 
-	spin_lock_irqsave(&gpio->lock, flags);
+	raw_spin_lock_irqsave(&gpio->lock, flags);
 	copro = aspeed_gpio_copro_request(gpio, offset);
 
 	__aspeed_gpio_set(gc, offset, val);
 
 	if (copro)
 		aspeed_gpio_copro_release(gpio, offset);
-	spin_unlock_irqrestore(&gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&gpio->lock, flags);
 }
 
 static int aspeed_gpio_dir_in(struct gpio_chip *gc, unsigned int offset)
@@ -435,7 +437,7 @@
 	if (!have_input(gpio, offset))
 		return -ENOTSUPP;
 
-	spin_lock_irqsave(&gpio->lock, flags);
+	raw_spin_lock_irqsave(&gpio->lock, flags);
 
 	reg = ioread32(addr);
 	reg &= ~GPIO_BIT(offset);
@@ -445,7 +447,7 @@
 	if (copro)
 		aspeed_gpio_copro_release(gpio, offset);
 
-	spin_unlock_irqrestore(&gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&gpio->lock, flags);
 
 	return 0;
 }
@@ -463,7 +465,7 @@
 	if (!have_output(gpio, offset))
 		return -ENOTSUPP;
 
-	spin_lock_irqsave(&gpio->lock, flags);
+	raw_spin_lock_irqsave(&gpio->lock, flags);
 
 	reg = ioread32(addr);
 	reg |= GPIO_BIT(offset);
@@ -474,7 +476,7 @@
 
 	if (copro)
 		aspeed_gpio_copro_release(gpio, offset);
-	spin_unlock_irqrestore(&gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&gpio->lock, flags);
 
 	return 0;
 }
@@ -492,11 +494,11 @@
 	if (!have_output(gpio, offset))
 		return 1;
 
-	spin_lock_irqsave(&gpio->lock, flags);
+	raw_spin_lock_irqsave(&gpio->lock, flags);
 
 	val = ioread32(bank_reg(gpio, bank, reg_dir)) & GPIO_BIT(offset);
 
-	spin_unlock_irqrestore(&gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&gpio->lock, flags);
 
 	return !val;
 
@@ -540,14 +542,14 @@
 
 	status_addr = bank_reg(gpio, bank, reg_irq_status);
 
-	spin_lock_irqsave(&gpio->lock, flags);
+	raw_spin_lock_irqsave(&gpio->lock, flags);
 	copro = aspeed_gpio_copro_request(gpio, offset);
 
 	iowrite32(bit, status_addr);
 
 	if (copro)
 		aspeed_gpio_copro_release(gpio, offset);
-	spin_unlock_irqrestore(&gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&gpio->lock, flags);
 }
 
 static void aspeed_gpio_irq_set_mask(struct irq_data *d, bool set)
@@ -566,7 +568,7 @@
 
 	addr = bank_reg(gpio, bank, reg_irq_enable);
 
-	spin_lock_irqsave(&gpio->lock, flags);
+	raw_spin_lock_irqsave(&gpio->lock, flags);
 	copro = aspeed_gpio_copro_request(gpio, offset);
 
 	reg = ioread32(addr);
@@ -578,7 +580,7 @@
 
 	if (copro)
 		aspeed_gpio_copro_release(gpio, offset);
-	spin_unlock_irqrestore(&gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&gpio->lock, flags);
 }
 
 static void aspeed_gpio_irq_mask(struct irq_data *d)
@@ -630,7 +632,7 @@
 		return -EINVAL;
 	}
 
-	spin_lock_irqsave(&gpio->lock, flags);
+	raw_spin_lock_irqsave(&gpio->lock, flags);
 	copro = aspeed_gpio_copro_request(gpio, offset);
 
 	addr = bank_reg(gpio, bank, reg_irq_type0);
@@ -650,7 +652,7 @@
 
 	if (copro)
 		aspeed_gpio_copro_release(gpio, offset);
-	spin_unlock_irqrestore(&gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&gpio->lock, flags);
 
 	irq_set_handler_locked(d, handler);
 
@@ -720,7 +722,7 @@
 
 	treg = bank_reg(gpio, to_bank(offset), reg_tolerance);
 
-	spin_lock_irqsave(&gpio->lock, flags);
+	raw_spin_lock_irqsave(&gpio->lock, flags);
 	copro = aspeed_gpio_copro_request(gpio, offset);
 
 	val = readl(treg);
@@ -734,7 +736,7 @@
 
 	if (copro)
 		aspeed_gpio_copro_release(gpio, offset);
-	spin_unlock_irqrestore(&gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&gpio->lock, flags);
 
 	return 0;
 }
@@ -860,7 +862,7 @@
 		return rc;
 	}
 
-	spin_lock_irqsave(&gpio->lock, flags);
+	raw_spin_lock_irqsave(&gpio->lock, flags);
 
 	if (timer_allocation_registered(gpio, offset)) {
 		rc = unregister_allocated_timer(gpio, offset);
@@ -920,7 +922,7 @@
 	configure_timer(gpio, offset, i);
 
 out:
-	spin_unlock_irqrestore(&gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&gpio->lock, flags);
 
 	return rc;
 }
@@ -931,13 +933,13 @@
 	unsigned long flags;
 	int rc;
 
-	spin_lock_irqsave(&gpio->lock, flags);
+	raw_spin_lock_irqsave(&gpio->lock, flags);
 
 	rc = unregister_allocated_timer(gpio, offset);
 	if (!rc)
 		configure_timer(gpio, offset, 0);
 
-	spin_unlock_irqrestore(&gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&gpio->lock, flags);
 
 	return rc;
 }
@@ -967,7 +969,7 @@
 	else if (param == PIN_CONFIG_BIAS_DISABLE ||
 			param == PIN_CONFIG_BIAS_PULL_DOWN ||
 			param == PIN_CONFIG_DRIVE_STRENGTH)
-		return pinctrl_gpio_set_config(offset, config);
+		return pinctrl_gpio_set_config(chip->base + offset, config);
 	else if (param == PIN_CONFIG_DRIVE_OPEN_DRAIN ||
 			param == PIN_CONFIG_DRIVE_OPEN_SOURCE)
 		/* Return -ENOTSUPP to trigger emulation, as per datasheet */
@@ -1019,7 +1021,7 @@
 		return -EINVAL;
 	bindex = offset >> 3;
 
-	spin_lock_irqsave(&gpio->lock, flags);
+	raw_spin_lock_irqsave(&gpio->lock, flags);
 
 	/* Sanity check, this shouldn't happen */
 	if (gpio->cf_copro_bankmap[bindex] == 0xff) {
@@ -1040,7 +1042,7 @@
 	if (bit)
 		*bit = GPIO_OFFSET(offset);
  bail:
-	spin_unlock_irqrestore(&gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&gpio->lock, flags);
 	return rc;
 }
 EXPORT_SYMBOL_GPL(aspeed_gpio_copro_grab_gpio);
@@ -1064,7 +1066,7 @@
 		return -EINVAL;
 	bindex = offset >> 3;
 
-	spin_lock_irqsave(&gpio->lock, flags);
+	raw_spin_lock_irqsave(&gpio->lock, flags);
 
 	/* Sanity check, this shouldn't happen */
 	if (gpio->cf_copro_bankmap[bindex] == 0) {
@@ -1078,7 +1080,7 @@
 		aspeed_gpio_change_cmd_source(gpio, bank, bindex,
 					      GPIO_CMDSRC_ARM);
  bail:
-	spin_unlock_irqrestore(&gpio->lock, flags);
+	raw_spin_unlock_irqrestore(&gpio->lock, flags);
 	return rc;
 }
 EXPORT_SYMBOL_GPL(aspeed_gpio_copro_release_gpio);
@@ -1115,8 +1117,8 @@
 
 static const struct aspeed_bank_props ast2600_bank_props[] = {
 	/*     input	  output   */
-	{5, 0xffffffff,  0x0000ffff}, /* U/V/W/X */
-	{6, 0xffff0000,  0x0fff0000}, /* Y/Z */
+	{5, 0xffffffff,  0xffffff00}, /* U/V/W/X */
+	{6, 0x0000ffff,  0x0000ffff}, /* Y/Z */
 	{ },
 };
 
@@ -1151,13 +1153,13 @@
 	if (IS_ERR(gpio->base))
 		return PTR_ERR(gpio->base);
 
-	spin_lock_init(&gpio->lock);
+	raw_spin_lock_init(&gpio->lock);
 
 	gpio_id = of_match_node(aspeed_gpio_of_table, pdev->dev.of_node);
 	if (!gpio_id)
 		return -EINVAL;
 
-	gpio->clk = of_clk_get(pdev->dev.of_node, 0);
+	gpio->clk = devm_clk_get_enabled(&pdev->dev, NULL);
 	if (IS_ERR(gpio->clk)) {
 		dev_warn(&pdev->dev,
 				"Failed to get clock from devicetree, debouncing disabled\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-bcm-kona.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-bcm-kona.c
@@ -77,6 +77,22 @@
 struct bcm_kona_gpio_bank {
 	int id;
 	int irq;
+	/*
+	 * Used to keep track of lock/unlock operations for each GPIO in the
+	 * bank.
+	 *
+	 * All GPIOs are locked by default (see bcm_kona_gpio_reset), and the
+	 * unlock count for all GPIOs is 0 by default. Each unlock increments
+	 * the counter, and each lock decrements the counter.
+	 *
+	 * The lock function only locks the GPIO once its unlock counter is
+	 * down to 0. This is necessary because the GPIO is unlocked in two
+	 * places in this driver: once for requested GPIOs, and once for
+	 * requested IRQs. Since it is possible for a GPIO to be requested
+	 * as both a GPIO and an IRQ, we need to ensure that we don't lock it
+	 * too early.
+	 */
+	u8 gpio_unlock_count[GPIO_PER_BANK];
 	/* Used in the interrupt handler */
 	struct bcm_kona_gpio *kona_gpio;
 };
@@ -94,14 +110,24 @@
 	u32 val;
 	unsigned long flags;
 	int bank_id = GPIO_BANK(gpio);
+	int bit = GPIO_BIT(gpio);
+	struct bcm_kona_gpio_bank *bank = &kona_gpio->banks[bank_id];
 
-	raw_spin_lock_irqsave(&kona_gpio->lock, flags);
+	if (bank->gpio_unlock_count[bit] == 0) {
+		dev_err(kona_gpio->gpio_chip.parent,
+			"Unbalanced locks for GPIO %u\n", gpio);
+		return;
+	}
 
-	val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id));
-	val |= BIT(gpio);
-	bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val);
+	if (--bank->gpio_unlock_count[bit] == 0) {
+		raw_spin_lock_irqsave(&kona_gpio->lock, flags);
 
-	raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
+		val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id));
+		val |= BIT(bit);
+		bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val);
+
+		raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
+	}
 }
 
 static void bcm_kona_gpio_unlock_gpio(struct bcm_kona_gpio *kona_gpio,
@@ -110,14 +136,20 @@
 	u32 val;
 	unsigned long flags;
 	int bank_id = GPIO_BANK(gpio);
+	int bit = GPIO_BIT(gpio);
+	struct bcm_kona_gpio_bank *bank = &kona_gpio->banks[bank_id];
 
-	raw_spin_lock_irqsave(&kona_gpio->lock, flags);
+	if (bank->gpio_unlock_count[bit] == 0) {
+		raw_spin_lock_irqsave(&kona_gpio->lock, flags);
 
-	val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id));
-	val &= ~BIT(gpio);
-	bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val);
+		val = readl(kona_gpio->reg_base + GPIO_PWD_STATUS(bank_id));
+		val &= ~BIT(bit);
+		bcm_kona_gpio_write_lock_regs(kona_gpio->reg_base, bank_id, val);
 
-	raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
+		raw_spin_unlock_irqrestore(&kona_gpio->lock, flags);
+	}
+
+	++bank->gpio_unlock_count[bit];
 }
 
 static int bcm_kona_gpio_get_dir(struct gpio_chip *chip, unsigned gpio)
@@ -368,6 +400,7 @@
 
 	kona_gpio = irq_data_get_irq_chip_data(d);
 	reg_base = kona_gpio->reg_base;
+
 	raw_spin_lock_irqsave(&kona_gpio->lock, flags);
 
 	val = readl(reg_base + GPIO_INT_MASK(bank_id));
@@ -390,6 +423,7 @@
 
 	kona_gpio = irq_data_get_irq_chip_data(d);
 	reg_base = kona_gpio->reg_base;
+
 	raw_spin_lock_irqsave(&kona_gpio->lock, flags);
 
 	val = readl(reg_base + GPIO_INT_MSKCLR(bank_id));
@@ -487,15 +521,26 @@
 static int bcm_kona_gpio_irq_reqres(struct irq_data *d)
 {
 	struct bcm_kona_gpio *kona_gpio = irq_data_get_irq_chip_data(d);
+	unsigned int gpio = d->hwirq;
 
-	return gpiochip_reqres_irq(&kona_gpio->gpio_chip, d->hwirq);
+	/*
+	 * We need to unlock the GPIO before any other operations are performed
+	 * on the relevant GPIO configuration registers
+	 */
+	bcm_kona_gpio_unlock_gpio(kona_gpio, gpio);
+
+	return gpiochip_reqres_irq(&kona_gpio->gpio_chip, gpio);
 }
 
 static void bcm_kona_gpio_irq_relres(struct irq_data *d)
 {
 	struct bcm_kona_gpio *kona_gpio = irq_data_get_irq_chip_data(d);
+	unsigned int gpio = d->hwirq;
+
+	/* Once we no longer use it, lock the GPIO again */
+	bcm_kona_gpio_lock_gpio(kona_gpio, gpio);
 
-	gpiochip_relres_irq(&kona_gpio->gpio_chip, d->hwirq);
+	gpiochip_relres_irq(&kona_gpio->gpio_chip, gpio);
 }
 
 static struct irq_chip bcm_gpio_irq_chip = {
@@ -619,7 +664,7 @@
 
 	kona_gpio->reg_base = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(kona_gpio->reg_base)) {
-		ret = -ENXIO;
+		ret = PTR_ERR(kona_gpio->reg_base);
 		goto err_irq_domain;
 	}
 
@@ -629,7 +674,7 @@
 		bank->irq = platform_get_irq(pdev, i);
 		bank->kona_gpio = kona_gpio;
 		if (bank->irq < 0) {
-			dev_err(dev, "Couldn't get IRQ for bank %d", i);
+			dev_err(dev, "Couldn't get IRQ for bank %d\n", i);
 			ret = -ENOENT;
 			goto err_irq_domain;
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-cadence.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-cadence.c
@@ -278,6 +278,7 @@
 	{ .compatible = "cdns,gpio-r1p02" },
 	{ /* sentinel */ },
 };
+MODULE_DEVICE_TABLE(of, cdns_of_ids);
 
 static struct platform_driver cdns_gpio_driver = {
 	.driver = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-crystalcove.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-crystalcove.c
@@ -91,7 +91,7 @@
 		case 0x5e:
 			return GPIOPANELCTL;
 		default:
-			return -EOPNOTSUPP;
+			return -ENOTSUPP;
 		}
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-davinci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-davinci.c
@@ -227,6 +227,11 @@
 	else
 		nirq = DIV_ROUND_UP(ngpio, 16);
 
+	if (nirq > MAX_INT_PER_BANK) {
+		dev_err(dev, "Too many IRQs!\n");
+		return -EINVAL;
+	}
+
 	chips = devm_kzalloc(dev, sizeof(*chips), GFP_KERNEL);
 	if (!chips)
 		return -ENOMEM;
@@ -295,7 +300,7 @@
  * serve as EDMA event triggers.
  */
 
-static void gpio_irq_disable(struct irq_data *d)
+static void gpio_irq_mask(struct irq_data *d)
 {
 	struct davinci_gpio_regs __iomem *g = irq2regs(d);
 	uintptr_t mask = (uintptr_t)irq_data_get_irq_handler_data(d);
@@ -304,7 +309,7 @@
 	writel_relaxed(mask, &g->clr_rising);
 }
 
-static void gpio_irq_enable(struct irq_data *d)
+static void gpio_irq_unmask(struct irq_data *d)
 {
 	struct davinci_gpio_regs __iomem *g = irq2regs(d);
 	uintptr_t mask = (uintptr_t)irq_data_get_irq_handler_data(d);
@@ -330,10 +335,10 @@
 
 static struct irq_chip gpio_irqchip = {
 	.name		= "GPIO",
-	.irq_enable	= gpio_irq_enable,
-	.irq_disable	= gpio_irq_disable,
+	.irq_unmask	= gpio_irq_unmask,
+	.irq_mask	= gpio_irq_mask,
 	.irq_set_type	= gpio_irq_type,
-	.flags		= IRQCHIP_SET_TYPE_MASKED,
+	.flags		= IRQCHIP_SET_TYPE_MASKED | IRQCHIP_SKIP_SET_WAKE,
 };
 
 static void gpio_irq_handler(struct irq_desc *desc)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-dwapb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-dwapb.c
@@ -49,7 +49,9 @@
 #define GPIO_EXT_PORTC		0x58
 #define GPIO_EXT_PORTD		0x5c
 
+#define DWAPB_DRIVER_NAME	"gpio-dwapb"
 #define DWAPB_MAX_PORTS		4
+
 #define GPIO_EXT_PORT_STRIDE	0x04 /* register stride 32 bits */
 #define GPIO_SWPORT_DR_STRIDE	0x0c /* register stride 3*32 bits */
 #define GPIO_SWPORT_DDR_STRIDE	0x0c /* register stride 3*32 bits */
@@ -398,7 +400,7 @@
 		return;
 
 	err = irq_alloc_domain_generic_chips(gpio->domain, ngpio, 2,
-					     "gpio-dwapb", handle_level_irq,
+					     DWAPB_DRIVER_NAME, handle_level_irq,
 					     IRQ_NOREQUEST, 0,
 					     IRQ_GC_INIT_NESTED_LOCK);
 	if (err) {
@@ -455,7 +457,7 @@
 		 */
 		err = devm_request_irq(gpio->dev, pp->irq[0],
 				       dwapb_irq_handler_mfd,
-				       IRQF_SHARED, "gpio-dwapb-mfd", gpio);
+				       IRQF_SHARED, DWAPB_DRIVER_NAME, gpio);
 		if (err) {
 			dev_err(gpio->dev, "error requesting IRQ\n");
 			irq_domain_remove(gpio->domain);
@@ -533,26 +535,33 @@
 		dwapb_configure_irqs(gpio, port, pp);
 
 	err = gpiochip_add_data(&port->gc, port);
-	if (err)
+	if (err) {
 		dev_err(gpio->dev, "failed to register gpiochip for port%d\n",
 			port->idx);
-	else
-		port->is_registered = true;
+		return err;
+	}
 
 	/* Add GPIO-signaled ACPI event support */
-	if (pp->has_irq)
-		acpi_gpiochip_request_interrupts(&port->gc);
+	acpi_gpiochip_request_interrupts(&port->gc);
 
-	return err;
+	port->is_registered = true;
+
+	return 0;
 }
 
 static void dwapb_gpio_unregister(struct dwapb_gpio *gpio)
 {
 	unsigned int m;
 
-	for (m = 0; m < gpio->nr_ports; ++m)
-		if (gpio->ports[m].is_registered)
-			gpiochip_remove(&gpio->ports[m].gc);
+	for (m = 0; m < gpio->nr_ports; ++m) {
+		struct dwapb_gpio_port *port = &gpio->ports[m];
+
+		if (!port->is_registered)
+			continue;
+
+		acpi_gpiochip_free_interrupts(&port->gc);
+		gpiochip_remove(&port->gc);
+	}
 }
 
 static struct dwapb_platform_data *
@@ -836,7 +845,7 @@
 
 static struct platform_driver dwapb_gpio_driver = {
 	.driver		= {
-		.name	= "gpio-dwapb",
+		.name	= DWAPB_DRIVER_NAME,
 		.pm	= &dwapb_gpio_pm_ops,
 		.of_match_table = of_match_ptr(dwapb_of_match),
 		.acpi_match_table = ACPI_PTR(dwapb_acpi_match),
@@ -850,3 +859,4 @@
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Jamie Iles");
 MODULE_DESCRIPTION("Synopsys DesignWare APB GPIO driver");
+MODULE_ALIAS("platform:" DWAPB_DRIVER_NAME);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-eic-sprd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-eic-sprd.c
@@ -318,20 +318,27 @@
 		switch (flow_type) {
 		case IRQ_TYPE_LEVEL_HIGH:
 			sprd_eic_update(chip, offset, SPRD_EIC_DBNC_IEV, 1);
+			sprd_eic_update(chip, offset, SPRD_EIC_DBNC_IC, 1);
 			break;
 		case IRQ_TYPE_LEVEL_LOW:
 			sprd_eic_update(chip, offset, SPRD_EIC_DBNC_IEV, 0);
+			sprd_eic_update(chip, offset, SPRD_EIC_DBNC_IC, 1);
 			break;
 		case IRQ_TYPE_EDGE_RISING:
 		case IRQ_TYPE_EDGE_FALLING:
 		case IRQ_TYPE_EDGE_BOTH:
 			state = sprd_eic_get(chip, offset);
-			if (state)
+			if (state) {
 				sprd_eic_update(chip, offset,
 						SPRD_EIC_DBNC_IEV, 0);
-			else
+				sprd_eic_update(chip, offset,
+						SPRD_EIC_DBNC_IC, 1);
+			} else {
 				sprd_eic_update(chip, offset,
 						SPRD_EIC_DBNC_IEV, 1);
+				sprd_eic_update(chip, offset,
+						SPRD_EIC_DBNC_IC, 1);
+			}
 			break;
 		default:
 			return -ENOTSUPP;
@@ -343,20 +350,27 @@
 		switch (flow_type) {
 		case IRQ_TYPE_LEVEL_HIGH:
 			sprd_eic_update(chip, offset, SPRD_EIC_LATCH_INTPOL, 0);
+			sprd_eic_update(chip, offset, SPRD_EIC_LATCH_INTCLR, 1);
 			break;
 		case IRQ_TYPE_LEVEL_LOW:
 			sprd_eic_update(chip, offset, SPRD_EIC_LATCH_INTPOL, 1);
+			sprd_eic_update(chip, offset, SPRD_EIC_LATCH_INTCLR, 1);
 			break;
 		case IRQ_TYPE_EDGE_RISING:
 		case IRQ_TYPE_EDGE_FALLING:
 		case IRQ_TYPE_EDGE_BOTH:
 			state = sprd_eic_get(chip, offset);
-			if (state)
+			if (state) {
 				sprd_eic_update(chip, offset,
 						SPRD_EIC_LATCH_INTPOL, 0);
-			else
+				sprd_eic_update(chip, offset,
+						SPRD_EIC_LATCH_INTCLR, 1);
+			} else {
 				sprd_eic_update(chip, offset,
 						SPRD_EIC_LATCH_INTPOL, 1);
+				sprd_eic_update(chip, offset,
+						SPRD_EIC_LATCH_INTCLR, 1);
+			}
 			break;
 		default:
 			return -ENOTSUPP;
@@ -370,29 +384,34 @@
 			sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 0);
 			sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 0);
 			sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTPOL, 1);
+			sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTCLR, 1);
 			irq_set_handler_locked(data, handle_edge_irq);
 			break;
 		case IRQ_TYPE_EDGE_FALLING:
 			sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 0);
 			sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 0);
 			sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTPOL, 0);
+			sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTCLR, 1);
 			irq_set_handler_locked(data, handle_edge_irq);
 			break;
 		case IRQ_TYPE_EDGE_BOTH:
 			sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 0);
 			sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 1);
+			sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTCLR, 1);
 			irq_set_handler_locked(data, handle_edge_irq);
 			break;
 		case IRQ_TYPE_LEVEL_HIGH:
 			sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 0);
 			sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 1);
 			sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTPOL, 1);
+			sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTCLR, 1);
 			irq_set_handler_locked(data, handle_level_irq);
 			break;
 		case IRQ_TYPE_LEVEL_LOW:
 			sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 0);
 			sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 1);
 			sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTPOL, 0);
+			sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTCLR, 1);
 			irq_set_handler_locked(data, handle_level_irq);
 			break;
 		default:
@@ -405,29 +424,34 @@
 			sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTBOTH, 0);
 			sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTMODE, 0);
 			sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTPOL, 1);
+			sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTCLR, 1);
 			irq_set_handler_locked(data, handle_edge_irq);
 			break;
 		case IRQ_TYPE_EDGE_FALLING:
 			sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTBOTH, 0);
 			sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTMODE, 0);
 			sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTPOL, 0);
+			sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTCLR, 1);
 			irq_set_handler_locked(data, handle_edge_irq);
 			break;
 		case IRQ_TYPE_EDGE_BOTH:
 			sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTMODE, 0);
 			sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTBOTH, 1);
+			sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTCLR, 1);
 			irq_set_handler_locked(data, handle_edge_irq);
 			break;
 		case IRQ_TYPE_LEVEL_HIGH:
 			sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTBOTH, 0);
 			sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTMODE, 1);
 			sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTPOL, 1);
+			sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTCLR, 1);
 			irq_set_handler_locked(data, handle_level_irq);
 			break;
 		case IRQ_TYPE_LEVEL_LOW:
 			sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTBOTH, 0);
 			sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTMODE, 1);
 			sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTPOL, 0);
+			sprd_eic_update(chip, offset, SPRD_EIC_SYNC_INTCLR, 1);
 			irq_set_handler_locked(data, handle_level_irq);
 			break;
 		default:
@@ -569,6 +593,7 @@
 	const struct sprd_eic_variant_data *pdata;
 	struct gpio_irq_chip *irq;
 	struct sprd_eic *sprd_eic;
+	struct resource *res;
 	int ret, i;
 
 	pdata = of_device_get_match_data(&pdev->dev);
@@ -595,9 +620,13 @@
 		 * have one bank EIC, thus base[1] and base[2] can be
 		 * optional.
 		 */
-		sprd_eic->base[i] = devm_platform_ioremap_resource(pdev, i);
+		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+		if (!res)
+			break;
+
+		sprd_eic->base[i] = devm_ioremap_resource(&pdev->dev, res);
 		if (IS_ERR(sprd_eic->base[i]))
-			continue;
+			return PTR_ERR(sprd_eic->base[i]);
 	}
 
 	sprd_eic->chip.label = sprd_eic_label_name[sprd_eic->type];
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-ep93xx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-ep93xx.c
@@ -25,6 +25,9 @@
 /* Maximum value for gpio line identifiers */
 #define EP93XX_GPIO_LINE_MAX 63
 
+/* Number of GPIO chips in EP93XX */
+#define EP93XX_GPIO_CHIP_NUM 8
+
 /* Maximum value for irq capable line identifiers */
 #define EP93XX_GPIO_LINE_MAX_IRQ 23
 
@@ -34,74 +37,75 @@
  */
 #define EP93XX_GPIO_F_IRQ_BASE 80
 
+struct ep93xx_gpio_irq_chip {
+	struct irq_chip ic;
+	u8 irq_offset;
+	u8 int_unmasked;
+	u8 int_enabled;
+	u8 int_type1;
+	u8 int_type2;
+	u8 int_debounce;
+};
+
+struct ep93xx_gpio_chip {
+	struct gpio_chip		gc;
+	struct ep93xx_gpio_irq_chip	*eic;
+};
+
 struct ep93xx_gpio {
 	void __iomem		*base;
-	struct gpio_chip	gc[8];
+	struct ep93xx_gpio_chip	gc[EP93XX_GPIO_CHIP_NUM];
 };
 
-/*************************************************************************
- * Interrupt handling for EP93xx on-chip GPIOs
- *************************************************************************/
-static unsigned char gpio_int_unmasked[3];
-static unsigned char gpio_int_enabled[3];
-static unsigned char gpio_int_type1[3];
-static unsigned char gpio_int_type2[3];
-static unsigned char gpio_int_debounce[3];
-
-/* Port ordering is: A B F */
-static const u8 int_type1_register_offset[3]	= { 0x90, 0xac, 0x4c };
-static const u8 int_type2_register_offset[3]	= { 0x94, 0xb0, 0x50 };
-static const u8 eoi_register_offset[3]		= { 0x98, 0xb4, 0x54 };
-static const u8 int_en_register_offset[3]	= { 0x9c, 0xb8, 0x58 };
-static const u8 int_debounce_register_offset[3]	= { 0xa8, 0xc4, 0x64 };
+#define to_ep93xx_gpio_chip(x) container_of(x, struct ep93xx_gpio_chip, gc)
 
-static void ep93xx_gpio_update_int_params(struct ep93xx_gpio *epg, unsigned port)
+static struct ep93xx_gpio_irq_chip *to_ep93xx_gpio_irq_chip(struct gpio_chip *gc)
 {
-	BUG_ON(port > 2);
-
-	writeb_relaxed(0, epg->base + int_en_register_offset[port]);
+	struct ep93xx_gpio_chip *egc = to_ep93xx_gpio_chip(gc);
 
-	writeb_relaxed(gpio_int_type2[port],
-		       epg->base + int_type2_register_offset[port]);
-
-	writeb_relaxed(gpio_int_type1[port],
-		       epg->base + int_type1_register_offset[port]);
-
-	writeb(gpio_int_unmasked[port] & gpio_int_enabled[port],
-	       epg->base + int_en_register_offset[port]);
+	return egc->eic;
 }
 
-static int ep93xx_gpio_port(struct gpio_chip *gc)
-{
-	struct ep93xx_gpio *epg = gpiochip_get_data(gc);
-	int port = 0;
+/*************************************************************************
+ * Interrupt handling for EP93xx on-chip GPIOs
+ *************************************************************************/
+#define EP93XX_INT_TYPE1_OFFSET		0x00
+#define EP93XX_INT_TYPE2_OFFSET		0x04
+#define EP93XX_INT_EOI_OFFSET		0x08
+#define EP93XX_INT_EN_OFFSET		0x0c
+#define EP93XX_INT_STATUS_OFFSET	0x10
+#define EP93XX_INT_RAW_STATUS_OFFSET	0x14
+#define EP93XX_INT_DEBOUNCE_OFFSET	0x18
+
+static void ep93xx_gpio_update_int_params(struct ep93xx_gpio *epg,
+					  struct ep93xx_gpio_irq_chip *eic)
+{
+	writeb_relaxed(0, epg->base + eic->irq_offset + EP93XX_INT_EN_OFFSET);
 
-	while (port < ARRAY_SIZE(epg->gc) && gc != &epg->gc[port])
-		port++;
+	writeb_relaxed(eic->int_type2,
+		       epg->base + eic->irq_offset + EP93XX_INT_TYPE2_OFFSET);
 
-	/* This should not happen but is there as a last safeguard */
-	if (port == ARRAY_SIZE(epg->gc)) {
-		pr_crit("can't find the GPIO port\n");
-		return 0;
-	}
+	writeb_relaxed(eic->int_type1,
+		       epg->base + eic->irq_offset + EP93XX_INT_TYPE1_OFFSET);
 
-	return port;
+	writeb_relaxed(eic->int_unmasked & eic->int_enabled,
+		       epg->base + eic->irq_offset + EP93XX_INT_EN_OFFSET);
 }
 
 static void ep93xx_gpio_int_debounce(struct gpio_chip *gc,
 				     unsigned int offset, bool enable)
 {
 	struct ep93xx_gpio *epg = gpiochip_get_data(gc);
-	int port = ep93xx_gpio_port(gc);
+	struct ep93xx_gpio_irq_chip *eic = to_ep93xx_gpio_irq_chip(gc);
 	int port_mask = BIT(offset);
 
 	if (enable)
-		gpio_int_debounce[port] |= port_mask;
+		eic->int_debounce |= port_mask;
 	else
-		gpio_int_debounce[port] &= ~port_mask;
+		eic->int_debounce &= ~port_mask;
 
-	writeb(gpio_int_debounce[port],
-	       epg->base + int_debounce_register_offset[port]);
+	writeb(eic->int_debounce,
+	       epg->base + eic->irq_offset + EP93XX_INT_DEBOUNCE_OFFSET);
 }
 
 static void ep93xx_gpio_ab_irq_handler(struct irq_desc *desc)
@@ -122,12 +126,12 @@
 	 */
 	stat = readb(epg->base + EP93XX_GPIO_A_INT_STATUS);
 	for_each_set_bit(offset, &stat, 8)
-		generic_handle_irq(irq_find_mapping(epg->gc[0].irq.domain,
+		generic_handle_irq(irq_find_mapping(epg->gc[0].gc.irq.domain,
 						    offset));
 
 	stat = readb(epg->base + EP93XX_GPIO_B_INT_STATUS);
 	for_each_set_bit(offset, &stat, 8)
-		generic_handle_irq(irq_find_mapping(epg->gc[1].irq.domain,
+		generic_handle_irq(irq_find_mapping(epg->gc[1].gc.irq.domain,
 						    offset));
 
 	chained_irq_exit(irqchip, desc);
@@ -153,52 +157,52 @@
 static void ep93xx_gpio_irq_ack(struct irq_data *d)
 {
 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct ep93xx_gpio_irq_chip *eic = to_ep93xx_gpio_irq_chip(gc);
 	struct ep93xx_gpio *epg = gpiochip_get_data(gc);
-	int port = ep93xx_gpio_port(gc);
 	int port_mask = BIT(d->irq & 7);
 
 	if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) {
-		gpio_int_type2[port] ^= port_mask; /* switch edge direction */
-		ep93xx_gpio_update_int_params(epg, port);
+		eic->int_type2 ^= port_mask; /* switch edge direction */
+		ep93xx_gpio_update_int_params(epg, eic);
 	}
 
-	writeb(port_mask, epg->base + eoi_register_offset[port]);
+	writeb(port_mask, epg->base + eic->irq_offset + EP93XX_INT_EOI_OFFSET);
 }
 
 static void ep93xx_gpio_irq_mask_ack(struct irq_data *d)
 {
 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct ep93xx_gpio_irq_chip *eic = to_ep93xx_gpio_irq_chip(gc);
 	struct ep93xx_gpio *epg = gpiochip_get_data(gc);
-	int port = ep93xx_gpio_port(gc);
 	int port_mask = BIT(d->irq & 7);
 
 	if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH)
-		gpio_int_type2[port] ^= port_mask; /* switch edge direction */
+		eic->int_type2 ^= port_mask; /* switch edge direction */
 
-	gpio_int_unmasked[port] &= ~port_mask;
-	ep93xx_gpio_update_int_params(epg, port);
+	eic->int_unmasked &= ~port_mask;
+	ep93xx_gpio_update_int_params(epg, eic);
 
-	writeb(port_mask, epg->base + eoi_register_offset[port]);
+	writeb(port_mask, epg->base + eic->irq_offset + EP93XX_INT_EOI_OFFSET);
 }
 
 static void ep93xx_gpio_irq_mask(struct irq_data *d)
 {
 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct ep93xx_gpio_irq_chip *eic = to_ep93xx_gpio_irq_chip(gc);
 	struct ep93xx_gpio *epg = gpiochip_get_data(gc);
-	int port = ep93xx_gpio_port(gc);
 
-	gpio_int_unmasked[port] &= ~BIT(d->irq & 7);
-	ep93xx_gpio_update_int_params(epg, port);
+	eic->int_unmasked &= ~BIT(d->irq & 7);
+	ep93xx_gpio_update_int_params(epg, eic);
 }
 
 static void ep93xx_gpio_irq_unmask(struct irq_data *d)
 {
 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct ep93xx_gpio_irq_chip *eic = to_ep93xx_gpio_irq_chip(gc);
 	struct ep93xx_gpio *epg = gpiochip_get_data(gc);
-	int port = ep93xx_gpio_port(gc);
 
-	gpio_int_unmasked[port] |= BIT(d->irq & 7);
-	ep93xx_gpio_update_int_params(epg, port);
+	eic->int_unmasked |= BIT(d->irq & 7);
+	ep93xx_gpio_update_int_params(epg, eic);
 }
 
 /*
@@ -209,8 +213,8 @@
 static int ep93xx_gpio_irq_type(struct irq_data *d, unsigned int type)
 {
 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct ep93xx_gpio_irq_chip *eic = to_ep93xx_gpio_irq_chip(gc);
 	struct ep93xx_gpio *epg = gpiochip_get_data(gc);
-	int port = ep93xx_gpio_port(gc);
 	int offset = d->irq & 7;
 	int port_mask = BIT(offset);
 	irq_flow_handler_t handler;
@@ -219,32 +223,32 @@
 
 	switch (type) {
 	case IRQ_TYPE_EDGE_RISING:
-		gpio_int_type1[port] |= port_mask;
-		gpio_int_type2[port] |= port_mask;
+		eic->int_type1 |= port_mask;
+		eic->int_type2 |= port_mask;
 		handler = handle_edge_irq;
 		break;
 	case IRQ_TYPE_EDGE_FALLING:
-		gpio_int_type1[port] |= port_mask;
-		gpio_int_type2[port] &= ~port_mask;
+		eic->int_type1 |= port_mask;
+		eic->int_type2 &= ~port_mask;
 		handler = handle_edge_irq;
 		break;
 	case IRQ_TYPE_LEVEL_HIGH:
-		gpio_int_type1[port] &= ~port_mask;
-		gpio_int_type2[port] |= port_mask;
+		eic->int_type1 &= ~port_mask;
+		eic->int_type2 |= port_mask;
 		handler = handle_level_irq;
 		break;
 	case IRQ_TYPE_LEVEL_LOW:
-		gpio_int_type1[port] &= ~port_mask;
-		gpio_int_type2[port] &= ~port_mask;
+		eic->int_type1 &= ~port_mask;
+		eic->int_type2 &= ~port_mask;
 		handler = handle_level_irq;
 		break;
 	case IRQ_TYPE_EDGE_BOTH:
-		gpio_int_type1[port] |= port_mask;
+		eic->int_type1 |= port_mask;
 		/* set initial polarity based on current input level */
 		if (gc->get(gc, offset))
-			gpio_int_type2[port] &= ~port_mask; /* falling */
+			eic->int_type2 &= ~port_mask; /* falling */
 		else
-			gpio_int_type2[port] |= port_mask; /* rising */
+			eic->int_type2 |= port_mask; /* rising */
 		handler = handle_edge_irq;
 		break;
 	default:
@@ -253,22 +257,13 @@
 
 	irq_set_handler_locked(d, handler);
 
-	gpio_int_enabled[port] |= port_mask;
+	eic->int_enabled |= port_mask;
 
-	ep93xx_gpio_update_int_params(epg, port);
+	ep93xx_gpio_update_int_params(epg, eic);
 
 	return 0;
 }
 
-static struct irq_chip ep93xx_gpio_irq_chip = {
-	.name		= "GPIO",
-	.irq_ack	= ep93xx_gpio_irq_ack,
-	.irq_mask_ack	= ep93xx_gpio_irq_mask_ack,
-	.irq_mask	= ep93xx_gpio_irq_mask,
-	.irq_unmask	= ep93xx_gpio_irq_unmask,
-	.irq_set_type	= ep93xx_gpio_irq_type,
-};
-
 /*************************************************************************
  * gpiolib interface for EP93xx on-chip GPIOs
  *************************************************************************/
@@ -276,17 +271,19 @@
 	const char	*label;
 	int		data;
 	int		dir;
+	int		irq;
 	int		base;
 	bool		has_irq;
 	bool		has_hierarchical_irq;
 	unsigned int	irq_base;
 };
 
-#define EP93XX_GPIO_BANK(_label, _data, _dir, _base, _has_irq, _has_hier, _irq_base) \
+#define EP93XX_GPIO_BANK(_label, _data, _dir, _irq, _base, _has_irq, _has_hier, _irq_base) \
 	{							\
 		.label		= _label,			\
 		.data		= _data,			\
 		.dir		= _dir,				\
+		.irq		= _irq,				\
 		.base		= _base,			\
 		.has_irq	= _has_irq,			\
 		.has_hierarchical_irq = _has_hier,		\
@@ -295,16 +292,16 @@
 
 static struct ep93xx_gpio_bank ep93xx_gpio_banks[] = {
 	/* Bank A has 8 IRQs */
-	EP93XX_GPIO_BANK("A", 0x00, 0x10, 0, true, false, 64),
+	EP93XX_GPIO_BANK("A", 0x00, 0x10, 0x90, 0, true, false, 64),
 	/* Bank B has 8 IRQs */
-	EP93XX_GPIO_BANK("B", 0x04, 0x14, 8, true, false, 72),
-	EP93XX_GPIO_BANK("C", 0x08, 0x18, 40, false, false, 0),
-	EP93XX_GPIO_BANK("D", 0x0c, 0x1c, 24, false, false, 0),
-	EP93XX_GPIO_BANK("E", 0x20, 0x24, 32, false, false, 0),
+	EP93XX_GPIO_BANK("B", 0x04, 0x14, 0xac, 8, true, false, 72),
+	EP93XX_GPIO_BANK("C", 0x08, 0x18, 0x00, 40, false, false, 0),
+	EP93XX_GPIO_BANK("D", 0x0c, 0x1c, 0x00, 24, false, false, 0),
+	EP93XX_GPIO_BANK("E", 0x20, 0x24, 0x00, 32, false, false, 0),
 	/* Bank F has 8 IRQs */
-	EP93XX_GPIO_BANK("F", 0x30, 0x34, 16, false, true, 0),
-	EP93XX_GPIO_BANK("G", 0x38, 0x3c, 48, false, false, 0),
-	EP93XX_GPIO_BANK("H", 0x40, 0x44, 56, false, false, 0),
+	EP93XX_GPIO_BANK("F", 0x30, 0x34, 0x4c, 16, false, true, 0),
+	EP93XX_GPIO_BANK("G", 0x38, 0x3c, 0x00, 48, false, false, 0),
+	EP93XX_GPIO_BANK("H", 0x40, 0x44, 0x00, 56, false, false, 0),
 };
 
 static int ep93xx_gpio_set_config(struct gpio_chip *gc, unsigned offset,
@@ -326,13 +323,23 @@
 	return EP93XX_GPIO_F_IRQ_BASE + offset;
 }
 
-static int ep93xx_gpio_add_bank(struct gpio_chip *gc,
+static void ep93xx_init_irq_chip(struct device *dev, struct irq_chip *ic)
+{
+	ic->irq_ack = ep93xx_gpio_irq_ack;
+	ic->irq_mask_ack = ep93xx_gpio_irq_mask_ack;
+	ic->irq_mask = ep93xx_gpio_irq_mask;
+	ic->irq_unmask = ep93xx_gpio_irq_unmask;
+	ic->irq_set_type = ep93xx_gpio_irq_type;
+}
+
+static int ep93xx_gpio_add_bank(struct ep93xx_gpio_chip *egc,
 				struct platform_device *pdev,
 				struct ep93xx_gpio *epg,
 				struct ep93xx_gpio_bank *bank)
 {
 	void __iomem *data = epg->base + bank->data;
 	void __iomem *dir = epg->base + bank->dir;
+	struct gpio_chip *gc = &egc->gc;
 	struct device *dev = &pdev->dev;
 	struct gpio_irq_chip *girq;
 	int err;
@@ -346,8 +353,21 @@
 
 	girq = &gc->irq;
 	if (bank->has_irq || bank->has_hierarchical_irq) {
+		struct irq_chip *ic;
+
 		gc->set_config = ep93xx_gpio_set_config;
-		girq->chip = &ep93xx_gpio_irq_chip;
+		egc->eic = devm_kcalloc(dev, 1,
+					sizeof(*egc->eic),
+					GFP_KERNEL);
+		if (!egc->eic)
+			return -ENOMEM;
+		egc->eic->irq_offset = bank->irq;
+		ic = &egc->eic->ic;
+		ic->name = devm_kasprintf(dev, GFP_KERNEL, "gpio-irq-%s", bank->label);
+		if (!ic->name)
+			return -ENOMEM;
+		ep93xx_init_irq_chip(dev, ic);
+		girq->chip = ic;
 	}
 
 	if (bank->has_irq) {
@@ -389,7 +409,7 @@
 			gpio_irq = EP93XX_GPIO_F_IRQ_BASE + i;
 			irq_set_chip_data(gpio_irq, &epg->gc[5]);
 			irq_set_chip_and_handler(gpio_irq,
-						 &ep93xx_gpio_irq_chip,
+						 girq->chip,
 						 handle_level_irq);
 			irq_clear_status_flags(gpio_irq, IRQ_NOREQUEST);
 		}
@@ -415,7 +435,7 @@
 		return PTR_ERR(epg->base);
 
 	for (i = 0; i < ARRAY_SIZE(ep93xx_gpio_banks); i++) {
-		struct gpio_chip *gc = &epg->gc[i];
+		struct ep93xx_gpio_chip *gc = &epg->gc[i];
 		struct ep93xx_gpio_bank *bank = &ep93xx_gpio_banks[i];
 
 		if (ep93xx_gpio_add_bank(gc, pdev, epg, bank))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-exar.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-exar.c
@@ -145,8 +145,10 @@
 	mutex_init(&exar_gpio->lock);
 
 	index = ida_simple_get(&ida_index, 0, 0, GFP_KERNEL);
-	if (index < 0)
-		goto err_destroy;
+	if (index < 0) {
+		ret = index;
+		goto err_mutex_destroy;
+	}
 
 	sprintf(exar_gpio->name, "exar_gpio%d", index);
 	exar_gpio->gpio_chip.label = exar_gpio->name;
@@ -173,6 +175,7 @@
 
 err_destroy:
 	ida_simple_remove(&ida_index, index);
+err_mutex_destroy:
 	mutex_destroy(&exar_gpio->lock);
 	return ret;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-grgpio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-grgpio.c
@@ -253,17 +253,16 @@
 	lirq->irq = irq;
 	uirq = &priv->uirqs[lirq->index];
 	if (uirq->refcnt == 0) {
+		spin_unlock_irqrestore(&priv->gc.bgpio_lock, flags);
 		ret = request_irq(uirq->uirq, grgpio_irq_handler, 0,
 				  dev_name(priv->dev), priv);
 		if (ret) {
 			dev_err(priv->dev,
 				"Could not request underlying irq %d\n",
 				uirq->uirq);
-
-			spin_unlock_irqrestore(&priv->gc.bgpio_lock, flags);
-
 			return ret;
 		}
+		spin_lock_irqsave(&priv->gc.bgpio_lock, flags);
 	}
 	uirq->refcnt++;
 
@@ -309,8 +308,11 @@
 	if (index >= 0) {
 		uirq = &priv->uirqs[lirq->index];
 		uirq->refcnt--;
-		if (uirq->refcnt == 0)
+		if (uirq->refcnt == 0) {
+			spin_unlock_irqrestore(&priv->gc.bgpio_lock, flags);
 			free_irq(uirq->uirq, priv);
+			return;
+		}
 	}
 
 	spin_unlock_irqrestore(&priv->gc.bgpio_lock, flags);
@@ -326,6 +328,7 @@
 static int grgpio_probe(struct platform_device *ofdev)
 {
 	struct device_node *np = ofdev->dev.of_node;
+	struct device *dev = &ofdev->dev;
 	void  __iomem *regs;
 	struct gpio_chip *gc;
 	struct grgpio_priv *priv;
@@ -335,7 +338,7 @@
 	int size;
 	int i;
 
-	priv = devm_kzalloc(&ofdev->dev, sizeof(*priv), GFP_KERNEL);
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
 
@@ -344,29 +347,32 @@
 		return PTR_ERR(regs);
 
 	gc = &priv->gc;
-	err = bgpio_init(gc, &ofdev->dev, 4, regs + GRGPIO_DATA,
+	err = bgpio_init(gc, dev, 4, regs + GRGPIO_DATA,
 			 regs + GRGPIO_OUTPUT, NULL, regs + GRGPIO_DIR, NULL,
 			 BGPIOF_BIG_ENDIAN_BYTE_ORDER);
 	if (err) {
-		dev_err(&ofdev->dev, "bgpio_init() failed\n");
+		dev_err(dev, "bgpio_init() failed\n");
 		return err;
 	}
 
 	priv->regs = regs;
 	priv->imask = gc->read_reg(regs + GRGPIO_IMASK);
-	priv->dev = &ofdev->dev;
+	priv->dev = dev;
 
 	gc->of_node = np;
 	gc->owner = THIS_MODULE;
 	gc->to_irq = grgpio_to_irq;
-	gc->label = devm_kasprintf(&ofdev->dev, GFP_KERNEL, "%pOF", np);
+	gc->label = devm_kasprintf(dev, GFP_KERNEL, "%pOF", np);
+	if (!gc->label)
+		return -ENOMEM;
+
 	gc->base = -1;
 
 	err = of_property_read_u32(np, "nbits", &prop);
 	if (err || prop <= 0 || prop > GRGPIO_MAX_NGPIO) {
 		gc->ngpio = GRGPIO_MAX_NGPIO;
-		dev_dbg(&ofdev->dev,
-			"No or invalid nbits property: assume %d\n", gc->ngpio);
+		dev_dbg(dev, "No or invalid nbits property: assume %d\n",
+			gc->ngpio);
 	} else {
 		gc->ngpio = prop;
 	}
@@ -378,7 +384,7 @@
 	irqmap = (s32 *)of_get_property(np, "irqmap", &size);
 	if (irqmap) {
 		if (size < gc->ngpio) {
-			dev_err(&ofdev->dev,
+			dev_err(dev,
 				"irqmap shorter than ngpio (%d < %d)\n",
 				size, gc->ngpio);
 			return -EINVAL;
@@ -388,7 +394,7 @@
 						     &grgpio_irq_domain_ops,
 						     priv);
 		if (!priv->domain) {
-			dev_err(&ofdev->dev, "Could not add irq domain\n");
+			dev_err(dev, "Could not add irq domain\n");
 			return -EINVAL;
 		}
 
@@ -418,13 +424,13 @@
 
 	err = gpiochip_add_data(gc, priv);
 	if (err) {
-		dev_err(&ofdev->dev, "Could not add gpiochip\n");
+		dev_err(dev, "Could not add gpiochip\n");
 		if (priv->domain)
 			irq_domain_remove(priv->domain);
 		return err;
 	}
 
-	dev_info(&ofdev->dev, "regs=0x%p, base=%d, ngpio=%d, irqs=%s\n",
+	dev_info(dev, "regs=0x%p, base=%d, ngpio=%d, irqs=%s\n",
 		 priv->regs, gc->base, gc->ngpio, priv->domain ? "on" : "off");
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-lynxpoint.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-lynxpoint.c
@@ -164,6 +164,12 @@
 		value |= TRIG_SEL_BIT | INT_INV_BIT;
 
 	outl(value, reg);
+
+	if (type & IRQ_TYPE_EDGE_BOTH)
+		irq_set_handler_locked(d, handle_edge_irq);
+	else if (type & IRQ_TYPE_LEVEL_MASK)
+		irq_set_handler_locked(d, handle_level_irq);
+
 	spin_unlock_irqrestore(&lg->lock, flags);
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-mockup.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-mockup.c
@@ -339,7 +339,7 @@
 		priv->offset = i;
 		priv->desc = &gc->gpiodev->descs[i];
 
-		debugfs_create_file(name, 0200, chip->dbg_dir, priv,
+		debugfs_create_file(name, 0600, chip->dbg_dir, priv,
 				    &gpio_mockup_debugfs_ops);
 	}
 
@@ -497,6 +497,7 @@
 	err = platform_driver_register(&gpio_mockup_driver);
 	if (err) {
 		gpio_mockup_err("error registering platform driver\n");
+		debugfs_remove_recursive(gpio_mockup_dbg_dir);
 		return err;
 	}
 
@@ -527,6 +528,7 @@
 			gpio_mockup_err("error registering device");
 			platform_driver_unregister(&gpio_mockup_driver);
 			gpio_mockup_unregister_pdevs();
+			debugfs_remove_recursive(gpio_mockup_dbg_dir);
 			return PTR_ERR(pdev);
 		}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-mpc8xxx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-mpc8xxx.c
@@ -190,6 +190,7 @@
 
 	switch (flow_type) {
 	case IRQ_TYPE_EDGE_FALLING:
+	case IRQ_TYPE_LEVEL_LOW:
 		raw_spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
 		gc->write_reg(mpc8xxx_gc->regs + GPIO_ICR,
 			gc->read_reg(mpc8xxx_gc->regs + GPIO_ICR)
@@ -346,6 +347,7 @@
 		return -ENOMEM;
 
 	gc = &mpc8xxx_gc->gc;
+	gc->parent = &pdev->dev;
 
 	if (of_property_read_bool(np, "little-endian")) {
 		ret = bgpio_init(gc, &pdev->dev, 4,
@@ -377,7 +379,8 @@
 	 * It's assumed that only a single type of gpio controller is available
 	 * on the current machine, so overwriting global data is fine.
 	 */
-	mpc8xxx_irq_chip.irq_set_type = devtype->irq_set_type;
+	if (devtype->irq_set_type)
+		mpc8xxx_irq_chip.irq_set_type = devtype->irq_set_type;
 
 	if (devtype->gpio_dir_out)
 		gc->direction_output = devtype->gpio_dir_out;
@@ -386,6 +389,9 @@
 
 	gc->to_irq = mpc8xxx_gpio_to_irq;
 
+	if (of_device_is_compatible(np, "fsl,qoriq-gpio"))
+		gc->write_reg(mpc8xxx_gc->regs + GPIO_IBE, 0xffffffff);
+
 	ret = gpiochip_add_data(gc, mpc8xxx_gc);
 	if (ret) {
 		pr_err("%pOF: GPIO chip registration failed with status %d\n",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-mvebu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-mvebu.c
@@ -657,9 +657,8 @@
 
 	spin_lock_irqsave(&mvpwm->lock, flags);
 
-	val = (unsigned long long)
-		readl_relaxed(mvebu_pwmreg_blink_on_duration(mvpwm));
-	val *= NSEC_PER_SEC;
+	u = readl_relaxed(mvebu_pwmreg_blink_on_duration(mvpwm));
+	val = (unsigned long long) u * NSEC_PER_SEC;
 	do_div(val, mvpwm->clk_rate);
 	if (val > UINT_MAX)
 		state->duty_cycle = UINT_MAX;
@@ -668,21 +667,17 @@
 	else
 		state->duty_cycle = 1;
 
-	val = (unsigned long long)
-		readl_relaxed(mvebu_pwmreg_blink_off_duration(mvpwm));
+	val = (unsigned long long) u; /* on duration */
+	/* period = on + off duration */
+	val += readl_relaxed(mvebu_pwmreg_blink_off_duration(mvpwm));
 	val *= NSEC_PER_SEC;
 	do_div(val, mvpwm->clk_rate);
-	if (val < state->duty_cycle) {
+	if (val > UINT_MAX)
+		state->period = UINT_MAX;
+	else if (val)
+		state->period = val;
+	else
 		state->period = 1;
-	} else {
-		val -= state->duty_cycle;
-		if (val > UINT_MAX)
-			state->period = UINT_MAX;
-		else if (val)
-			state->period = val;
-		else
-			state->period = 1;
-	}
 
 	regmap_read(mvchip->regs, GPIO_BLINK_EN_OFF + mvchip->offset, &u);
 	if (u)
@@ -702,6 +697,9 @@
 	unsigned long flags;
 	unsigned int on, off;
 
+	if (state->polarity != PWM_POLARITY_NORMAL)
+		return -EINVAL;
+
 	val = (unsigned long long) mvpwm->clk_rate * state->duty_cycle;
 	do_div(val, NSEC_PER_SEC);
 	if (val > UINT_MAX)
@@ -1196,6 +1194,13 @@
 
 	devm_gpiochip_add_data(&pdev->dev, &mvchip->chip, mvchip);
 
+	/* Some MVEBU SoCs have simple PWM support for GPIO lines */
+	if (IS_ENABLED(CONFIG_PWM)) {
+		err = mvebu_pwm_probe(pdev, mvchip, id);
+		if (err)
+			return err;
+	}
+
 	/* Some gpio controllers do not provide irq support */
 	if (!have_irqs)
 		return 0;
@@ -1205,7 +1210,8 @@
 	if (!mvchip->domain) {
 		dev_err(&pdev->dev, "couldn't allocate irq domain %s (DT).\n",
 			mvchip->chip.label);
-		return -ENODEV;
+		err = -ENODEV;
+		goto err_pwm;
 	}
 
 	err = irq_alloc_domain_generic_chips(
@@ -1253,14 +1259,12 @@
 						 mvchip);
 	}
 
-	/* Some MVEBU SoCs have simple PWM support for GPIO lines */
-	if (IS_ENABLED(CONFIG_PWM))
-		return mvebu_pwm_probe(pdev, mvchip, id);
-
 	return 0;
 
 err_domain:
 	irq_domain_remove(mvchip->domain);
+err_pwm:
+	pwmchip_remove(&mvchip->mvpwm->chip);
 
 	return err;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-mxc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-mxc.c
@@ -229,7 +229,7 @@
 
 	writel(1 << gpio_idx, port->base + GPIO_ISR);
 
-	return 0;
+	return port->gc.direction_input(&port->gc, gpio_idx);
 }
 
 static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio)
@@ -411,6 +411,7 @@
 {
 	struct device_node *np = pdev->dev.of_node;
 	struct mxc_gpio_port *port;
+	int irq_count;
 	int irq_base;
 	int err;
 
@@ -426,9 +427,15 @@
 	if (IS_ERR(port->base))
 		return PTR_ERR(port->base);
 
-	port->irq_high = platform_get_irq(pdev, 1);
-	if (port->irq_high < 0)
-		port->irq_high = 0;
+	irq_count = platform_irq_count(pdev);
+	if (irq_count < 0)
+		return irq_count;
+
+	if (irq_count > 1) {
+		port->irq_high = platform_get_irq(pdev, 1);
+		if (port->irq_high < 0)
+			port->irq_high = 0;
+	}
 
 	port->irq = platform_get_irq(pdev, 0);
 	if (port->irq < 0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-omap.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-omap.c
@@ -29,6 +29,7 @@
 #define OMAP4_GPIO_DEBOUNCINGTIME_MASK 0xFF
 
 struct gpio_regs {
+	u32 sysconfig;
 	u32 irqenable1;
 	u32 irqenable2;
 	u32 wake_en;
@@ -1058,6 +1059,7 @@
 	const struct omap_gpio_reg_offs *regs = p->regs;
 	void __iomem *base = p->base;
 
+	p->context.sysconfig	= readl_relaxed(base + regs->sysconfig);
 	p->context.ctrl		= readl_relaxed(base + regs->ctrl);
 	p->context.oe		= readl_relaxed(base + regs->direction);
 	p->context.wake_en	= readl_relaxed(base + regs->wkup_en);
@@ -1077,6 +1079,7 @@
 	const struct omap_gpio_reg_offs *regs = bank->regs;
 	void __iomem *base = bank->base;
 
+	writel_relaxed(bank->context.sysconfig, base + regs->sysconfig);
 	writel_relaxed(bank->context.wake_en, base + regs->wkup_en);
 	writel_relaxed(bank->context.ctrl, base + regs->ctrl);
 	writel_relaxed(bank->context.leveldetect0, base + regs->leveldetect0);
@@ -1104,6 +1107,10 @@
 
 	bank->saved_datain = readl_relaxed(base + bank->regs->datain);
 
+	/* Save syconfig, it's runtime value can be different from init value */
+	if (bank->loses_context)
+		bank->context.sysconfig = readl_relaxed(base + bank->regs->sysconfig);
+
 	if (!bank->enabled_non_wakeup_gpios)
 		goto update_gpio_context_count;
 
@@ -1259,6 +1266,7 @@
 
 static const struct omap_gpio_reg_offs omap2_gpio_regs = {
 	.revision =		OMAP24XX_GPIO_REVISION,
+	.sysconfig =		OMAP24XX_GPIO_SYSCONFIG,
 	.direction =		OMAP24XX_GPIO_OE,
 	.datain =		OMAP24XX_GPIO_DATAIN,
 	.dataout =		OMAP24XX_GPIO_DATAOUT,
@@ -1282,6 +1290,7 @@
 
 static const struct omap_gpio_reg_offs omap4_gpio_regs = {
 	.revision =		OMAP4_GPIO_REVISION,
+	.sysconfig =		OMAP4_GPIO_SYSCONFIG,
 	.direction =		OMAP4_GPIO_OE,
 	.datain =		OMAP4_GPIO_DATAIN,
 	.dataout =		OMAP4_GPIO_DATAOUT,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-pca953x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-pca953x.c
@@ -107,6 +107,84 @@
 };
 MODULE_DEVICE_TABLE(i2c, pca953x_id);
 
+#ifdef CONFIG_GPIO_PCA953X_IRQ
+
+#include <linux/dmi.h>
+#include <linux/gpio.h>
+#include <linux/list.h>
+
+static const struct dmi_system_id pca953x_dmi_acpi_irq_info[] = {
+	{
+		/*
+		 * On Intel Galileo Gen 2 board the IRQ pin of one of
+		 * the I²C GPIO expanders, which has GpioInt() resource,
+		 * is provided as an absolute number instead of being
+		 * relative. Since first controller (gpio-sch.c) and
+		 * second (gpio-dwapb.c) are at the fixed bases, we may
+		 * safely refer to the number in the global space to get
+		 * an IRQ out of it.
+		 */
+		.matches = {
+			DMI_EXACT_MATCH(DMI_BOARD_NAME, "GalileoGen2"),
+		},
+	},
+	{}
+};
+
+#ifdef CONFIG_ACPI
+static int pca953x_acpi_get_pin(struct acpi_resource *ares, void *data)
+{
+	struct acpi_resource_gpio *agpio;
+	int *pin = data;
+
+	if (acpi_gpio_get_irq_resource(ares, &agpio))
+		*pin = agpio->pin_table[0];
+	return 1;
+}
+
+static int pca953x_acpi_find_pin(struct device *dev)
+{
+	struct acpi_device *adev = ACPI_COMPANION(dev);
+	int pin = -ENOENT, ret;
+	LIST_HEAD(r);
+
+	ret = acpi_dev_get_resources(adev, &r, pca953x_acpi_get_pin, &pin);
+	acpi_dev_free_resource_list(&r);
+	if (ret < 0)
+		return ret;
+
+	return pin;
+}
+#else
+static inline int pca953x_acpi_find_pin(struct device *dev) { return -ENXIO; }
+#endif
+
+static int pca953x_acpi_get_irq(struct device *dev)
+{
+	int pin, ret;
+
+	pin = pca953x_acpi_find_pin(dev);
+	if (pin < 0)
+		return pin;
+
+	dev_info(dev, "Applying ACPI interrupt quirk (GPIO %d)\n", pin);
+
+	if (!gpio_is_valid(pin))
+		return -EINVAL;
+
+	ret = gpio_request(pin, "pca953x interrupt");
+	if (ret)
+		return ret;
+
+	ret = gpio_to_irq(pin);
+
+	/* When pin is used as an IRQ, no need to keep it requested */
+	gpio_free(pin);
+
+	return ret;
+}
+#endif
+
 static const struct acpi_device_id pca953x_acpi_ids[] = {
 	{ "INT3491", 16 | PCA953X_TYPE | PCA_LATCH_INT, },
 	{ }
@@ -301,13 +379,31 @@
 	.reg_bits = 8,
 	.val_bits = 8,
 
+	.use_single_read = true,
+	.use_single_write = true,
+
 	.readable_reg = pca953x_readable_register,
 	.writeable_reg = pca953x_writeable_register,
 	.volatile_reg = pca953x_volatile_register,
 
 	.cache_type = REGCACHE_RBTREE,
-	/* REVISIT: should be 0x7f but some 24 bit chips use REG_ADDR_AI */
-	.max_register = 0xff,
+	.max_register = 0x7f,
+};
+
+static const struct regmap_config pca953x_ai_i2c_regmap = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.read_flag_mask = REG_ADDR_AI,
+	.write_flag_mask = REG_ADDR_AI,
+
+	.readable_reg = pca953x_readable_register,
+	.writeable_reg = pca953x_writeable_register,
+	.volatile_reg = pca953x_volatile_register,
+
+	.disable_locking = true,
+	.cache_type = REGCACHE_RBTREE,
+	.max_register = 0x7f,
 };
 
 static u8 pca953x_recalc_addr(struct pca953x_chip *chip, int reg, int off,
@@ -318,18 +414,6 @@
 	int pinctrl = (reg & PCAL_PINCTRL_MASK) << 1;
 	u8 regaddr = pinctrl | addr | (off / BANK_SZ);
 
-	/* Single byte read doesn't need AI bit set. */
-	if (!addrinc)
-		return regaddr;
-
-	/* Chips with 24 and more GPIOs always support Auto Increment */
-	if (write && NBANK(chip) > 2)
-		regaddr |= REG_ADDR_AI;
-
-	/* PCA9575 needs address-increment on multi-byte writes */
-	if (PCA_CHIP_TYPE(chip->driver_data) == PCA957X_TYPE)
-		regaddr |= REG_ADDR_AI;
-
 	return regaddr;
 }
 
@@ -502,21 +586,21 @@
 
 	mutex_lock(&chip->i2c_lock);
 
-	/* Disable pull-up/pull-down */
-	ret = regmap_write_bits(chip->regmap, pull_en_reg, bit, 0);
-	if (ret)
-		goto exit;
-
 	/* Configure pull-up/pull-down */
 	if (config == PIN_CONFIG_BIAS_PULL_UP)
 		ret = regmap_write_bits(chip->regmap, pull_sel_reg, bit, bit);
 	else if (config == PIN_CONFIG_BIAS_PULL_DOWN)
 		ret = regmap_write_bits(chip->regmap, pull_sel_reg, bit, 0);
+	else
+		ret = 0;
 	if (ret)
 		goto exit;
 
-	/* Enable pull-up/pull-down */
-	ret = regmap_write_bits(chip->regmap, pull_en_reg, bit, bit);
+	/* Disable/Enable pull-up/pull-down */
+	if (config == PIN_CONFIG_BIAS_DISABLE)
+		ret = regmap_write_bits(chip->regmap, pull_en_reg, bit, 0);
+	else
+		ret = regmap_write_bits(chip->regmap, pull_en_reg, bit, bit);
 
 exit:
 	mutex_unlock(&chip->i2c_lock);
@@ -528,9 +612,11 @@
 {
 	struct pca953x_chip *chip = gpiochip_get_data(gc);
 
-	switch (config) {
+	switch (pinconf_to_config_param(config)) {
 	case PIN_CONFIG_BIAS_PULL_UP:
+	case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:
 	case PIN_CONFIG_BIAS_PULL_DOWN:
+	case PIN_CONFIG_BIAS_DISABLE:
 		return pca953x_gpio_set_pull_up_down(chip, offset, config);
 	default:
 		return -ENOTSUPP;
@@ -770,6 +856,12 @@
 	u8 reg_direction[MAX_BANK];
 	int ret, i;
 
+	if (dmi_first_match(pca953x_dmi_acpi_irq_info)) {
+		ret = pca953x_acpi_get_irq(&client->dev);
+		if (ret > 0)
+			client->irq = ret;
+	}
+
 	if (!client->irq)
 		return 0;
 
@@ -897,6 +989,7 @@
 	int ret;
 	u32 invert = 0;
 	struct regulator *reg;
+	const struct regmap_config *regmap_config;
 
 	chip = devm_kzalloc(&client->dev,
 			sizeof(struct pca953x_chip), GFP_KERNEL);
@@ -960,7 +1053,17 @@
 
 	i2c_set_clientdata(client, chip);
 
-	chip->regmap = devm_regmap_init_i2c(client, &pca953x_i2c_regmap);
+	pca953x_setup_gpio(chip, chip->driver_data & PCA_GPIO_MASK);
+
+	if (NBANK(chip) > 2 || PCA_CHIP_TYPE(chip->driver_data) == PCA957X_TYPE) {
+		dev_info(&client->dev, "using AI\n");
+		regmap_config = &pca953x_ai_i2c_regmap;
+	} else {
+		dev_info(&client->dev, "using no AI\n");
+		regmap_config = &pca953x_i2c_regmap;
+	}
+
+	chip->regmap = devm_regmap_init_i2c(client, regmap_config);
 	if (IS_ERR(chip->regmap)) {
 		ret = PTR_ERR(chip->regmap);
 		goto err_exit;
@@ -991,7 +1094,6 @@
 	/* initialize cached registers from their original values.
 	 * we can't share this chip with another i2c master.
 	 */
-	pca953x_setup_gpio(chip, chip->driver_data & PCA_GPIO_MASK);
 
 	if (PCA_CHIP_TYPE(chip->driver_data) == PCA953X_TYPE) {
 		chip->regs = &pca953x_regs;
@@ -1096,7 +1198,9 @@
 {
 	struct pca953x_chip *chip = dev_get_drvdata(dev);
 
+	mutex_lock(&chip->i2c_lock);
 	regcache_cache_only(chip->regmap, true);
+	mutex_unlock(&chip->i2c_lock);
 
 	if (atomic_read(&chip->wakeup_path))
 		device_set_wakeup_path(dev);
@@ -1119,13 +1223,17 @@
 		}
 	}
 
+	mutex_lock(&chip->i2c_lock);
 	regcache_cache_only(chip->regmap, false);
 	regcache_mark_dirty(chip->regmap);
 	ret = pca953x_regcache_sync(dev);
-	if (ret)
+	if (ret) {
+		mutex_unlock(&chip->i2c_lock);
 		return ret;
+	}
 
 	ret = regcache_sync(chip->regmap);
+	mutex_unlock(&chip->i2c_lock);
 	if (ret) {
 		dev_err(dev, "Failed to restore register map: %d\n", ret);
 		return ret;
@@ -1175,6 +1283,7 @@
 
 	{ .compatible = "onnn,cat9554", .data = OF_953X( 8, PCA_INT), },
 	{ .compatible = "onnn,pca9654", .data = OF_953X( 8, PCA_INT), },
+	{ .compatible = "onnn,pca9655", .data = OF_953X(16, PCA_INT), },
 
 	{ .compatible = "exar,xra1202", .data = OF_953X( 8, 0), },
 	{ }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-pcf857x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-pcf857x.c
@@ -332,7 +332,7 @@
 	 * reset state.  Otherwise it flags pins to be driven low.
 	 */
 	gpio->out = ~n_latch;
-	gpio->status = gpio->out;
+	gpio->status = gpio->read(gpio->client);
 
 	status = devm_gpiochip_add_data(&client->dev, &gpio->chip, gpio);
 	if (status < 0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-pcie-idio-24.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-pcie-idio-24.c
@@ -28,6 +28,47 @@
 #include <linux/spinlock.h>
 #include <linux/types.h>
 
+/*
+ * PLX PEX8311 PCI LCS_INTCSR Interrupt Control/Status
+ *
+ * Bit: Description
+ *   0: Enable Interrupt Sources (Bit 0)
+ *   1: Enable Interrupt Sources (Bit 1)
+ *   2: Generate Internal PCI Bus Internal SERR# Interrupt
+ *   3: Mailbox Interrupt Enable
+ *   4: Power Management Interrupt Enable
+ *   5: Power Management Interrupt
+ *   6: Slave Read Local Data Parity Check Error Enable
+ *   7: Slave Read Local Data Parity Check Error Status
+ *   8: Internal PCI Wire Interrupt Enable
+ *   9: PCI Express Doorbell Interrupt Enable
+ *  10: PCI Abort Interrupt Enable
+ *  11: Local Interrupt Input Enable
+ *  12: Retry Abort Enable
+ *  13: PCI Express Doorbell Interrupt Active
+ *  14: PCI Abort Interrupt Active
+ *  15: Local Interrupt Input Active
+ *  16: Local Interrupt Output Enable
+ *  17: Local Doorbell Interrupt Enable
+ *  18: DMA Channel 0 Interrupt Enable
+ *  19: DMA Channel 1 Interrupt Enable
+ *  20: Local Doorbell Interrupt Active
+ *  21: DMA Channel 0 Interrupt Active
+ *  22: DMA Channel 1 Interrupt Active
+ *  23: Built-In Self-Test (BIST) Interrupt Active
+ *  24: Direct Master was the Bus Master during a Master or Target Abort
+ *  25: DMA Channel 0 was the Bus Master during a Master or Target Abort
+ *  26: DMA Channel 1 was the Bus Master during a Master or Target Abort
+ *  27: Target Abort after internal 256 consecutive Master Retrys
+ *  28: PCI Bus wrote data to LCS_MBOX0
+ *  29: PCI Bus wrote data to LCS_MBOX1
+ *  30: PCI Bus wrote data to LCS_MBOX2
+ *  31: PCI Bus wrote data to LCS_MBOX3
+ */
+#define PLX_PEX8311_PCI_LCS_INTCSR  0x68
+#define INTCSR_INTERNAL_PCI_WIRE    BIT(8)
+#define INTCSR_LOCAL_INPUT          BIT(11)
+
 /**
  * struct idio_24_gpio_reg - GPIO device registers structure
  * @out0_7:	Read: FET Outputs 0-7
@@ -92,6 +133,7 @@
 struct idio_24_gpio {
 	struct gpio_chip chip;
 	raw_spinlock_t lock;
+	__u8 __iomem *plx;
 	struct idio_24_gpio_reg __iomem *reg;
 	unsigned long irq_mask;
 };
@@ -360,13 +402,13 @@
 	unsigned long flags;
 	const unsigned long bit_offset = irqd_to_hwirq(data) - 24;
 	unsigned char new_irq_mask;
-	const unsigned long bank_offset = bit_offset/8 * 8;
+	const unsigned long bank_offset = bit_offset / 8;
 	unsigned char cos_enable_state;
 
 	raw_spin_lock_irqsave(&idio24gpio->lock, flags);
 
-	idio24gpio->irq_mask &= BIT(bit_offset);
-	new_irq_mask = idio24gpio->irq_mask >> bank_offset;
+	idio24gpio->irq_mask &= ~BIT(bit_offset);
+	new_irq_mask = idio24gpio->irq_mask >> bank_offset * 8;
 
 	if (!new_irq_mask) {
 		cos_enable_state = ioread8(&idio24gpio->reg->cos_enable);
@@ -389,12 +431,12 @@
 	unsigned long flags;
 	unsigned char prev_irq_mask;
 	const unsigned long bit_offset = irqd_to_hwirq(data) - 24;
-	const unsigned long bank_offset = bit_offset/8 * 8;
+	const unsigned long bank_offset = bit_offset / 8;
 	unsigned char cos_enable_state;
 
 	raw_spin_lock_irqsave(&idio24gpio->lock, flags);
 
-	prev_irq_mask = idio24gpio->irq_mask >> bank_offset;
+	prev_irq_mask = idio24gpio->irq_mask >> bank_offset * 8;
 	idio24gpio->irq_mask |= BIT(bit_offset);
 
 	if (!prev_irq_mask) {
@@ -481,6 +523,7 @@
 	struct device *const dev = &pdev->dev;
 	struct idio_24_gpio *idio24gpio;
 	int err;
+	const size_t pci_plx_bar_index = 1;
 	const size_t pci_bar_index = 2;
 	const char *const name = pci_name(pdev);
 
@@ -494,12 +537,13 @@
 		return err;
 	}
 
-	err = pcim_iomap_regions(pdev, BIT(pci_bar_index), name);
+	err = pcim_iomap_regions(pdev, BIT(pci_plx_bar_index) | BIT(pci_bar_index), name);
 	if (err) {
 		dev_err(dev, "Unable to map PCI I/O addresses (%d)\n", err);
 		return err;
 	}
 
+	idio24gpio->plx = pcim_iomap_table(pdev)[pci_plx_bar_index];
 	idio24gpio->reg = pcim_iomap_table(pdev)[pci_bar_index];
 
 	idio24gpio->chip.label = name;
@@ -520,6 +564,12 @@
 
 	/* Software board reset */
 	iowrite8(0, &idio24gpio->reg->soft_reset);
+	/*
+	 * enable PLX PEX8311 internal PCI wire interrupt and local interrupt
+	 * input
+	 */
+	iowrite8((INTCSR_INTERNAL_PCI_WIRE | INTCSR_LOCAL_INPUT) >> 8,
+		 idio24gpio->plx + PLX_PEX8311_PCI_LCS_INTCSR + 1);
 
 	err = devm_gpiochip_add_data(dev, &idio24gpio->chip, idio24gpio);
 	if (err) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-pmic-eic-sprd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-pmic-eic-sprd.c
@@ -338,6 +338,7 @@
 	pmic_eic->chip.set_config = sprd_pmic_eic_set_config;
 	pmic_eic->chip.set = sprd_pmic_eic_set;
 	pmic_eic->chip.get = sprd_pmic_eic_get;
+	pmic_eic->chip.can_sleep = true;
 
 	pmic_eic->intc.name = dev_name(&pdev->dev);
 	pmic_eic->intc.irq_mask = sprd_pmic_eic_irq_mask;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-pxa.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-pxa.c
@@ -243,6 +243,7 @@
 	switch (gpio_type) {
 	case PXA3XX_GPIO:
 	case MMP2_GPIO:
+	case MMP_GPIO:
 		return false;
 
 	default:
@@ -663,8 +664,8 @@
 	pchip->irq1 = irq1;
 
 	gpio_reg_base = devm_platform_ioremap_resource(pdev, 0);
-	if (!gpio_reg_base)
-		return -EINVAL;
+	if (IS_ERR(gpio_reg_base))
+		return PTR_ERR(gpio_reg_base);
 
 	clk = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(clk)) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-rcar.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-rcar.c
@@ -250,8 +250,10 @@
 	int error;
 
 	error = pm_runtime_get_sync(p->dev);
-	if (error < 0)
+	if (error < 0) {
+		pm_runtime_put(p->dev);
 		return error;
+	}
 
 	error = pinctrl_gpio_request(chip->base + offset);
 	if (error)
@@ -416,7 +418,12 @@
 	p->has_both_edge_trigger = info->has_both_edge_trigger;
 
 	ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, 0, &args);
-	*npins = ret == 0 ? args.args[2] : RCAR_MAX_GPIO_PER_BANK;
+	if (ret) {
+		*npins = RCAR_MAX_GPIO_PER_BANK;
+	} else {
+		*npins = args.args[2];
+		of_node_put(args.np);
+	}
 
 	if (*npins == 0 || *npins > RCAR_MAX_GPIO_PER_BANK) {
 		dev_warn(p->dev, "Invalid number of gpio lines %u, using %u\n",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-siox.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-siox.c
@@ -245,6 +245,7 @@
 	girq->chip = &ddata->ichip;
 	girq->default_type = IRQ_TYPE_NONE;
 	girq->handler = handle_level_irq;
+	girq->threaded = true;
 
 	ret = devm_gpiochip_add_data(dev, &ddata->gchip, NULL);
 	if (ret)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-sprd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-sprd.c
@@ -149,17 +149,20 @@
 		sprd_gpio_update(chip, offset, SPRD_GPIO_IS, 0);
 		sprd_gpio_update(chip, offset, SPRD_GPIO_IBE, 0);
 		sprd_gpio_update(chip, offset, SPRD_GPIO_IEV, 1);
+		sprd_gpio_update(chip, offset, SPRD_GPIO_IC, 1);
 		irq_set_handler_locked(data, handle_edge_irq);
 		break;
 	case IRQ_TYPE_EDGE_FALLING:
 		sprd_gpio_update(chip, offset, SPRD_GPIO_IS, 0);
 		sprd_gpio_update(chip, offset, SPRD_GPIO_IBE, 0);
 		sprd_gpio_update(chip, offset, SPRD_GPIO_IEV, 0);
+		sprd_gpio_update(chip, offset, SPRD_GPIO_IC, 1);
 		irq_set_handler_locked(data, handle_edge_irq);
 		break;
 	case IRQ_TYPE_EDGE_BOTH:
 		sprd_gpio_update(chip, offset, SPRD_GPIO_IS, 0);
 		sprd_gpio_update(chip, offset, SPRD_GPIO_IBE, 1);
+		sprd_gpio_update(chip, offset, SPRD_GPIO_IC, 1);
 		irq_set_handler_locked(data, handle_edge_irq);
 		break;
 	case IRQ_TYPE_LEVEL_HIGH:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-stmpe.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-stmpe.c
@@ -188,7 +188,7 @@
 		[REG_IE][CSB] = STMPE_IDX_IEGPIOR_CSB,
 		[REG_IE][MSB] = STMPE_IDX_IEGPIOR_MSB,
 	};
-	int i, j;
+	int ret, i, j;
 
 	/*
 	 * STMPE1600: to be able to get IRQ from pins,
@@ -196,8 +196,16 @@
 	 * GPSR or GPCR registers
 	 */
 	if (stmpe->partnum == STMPE1600) {
-		stmpe_reg_read(stmpe, stmpe->regs[STMPE_IDX_GPMR_LSB]);
-		stmpe_reg_read(stmpe, stmpe->regs[STMPE_IDX_GPMR_CSB]);
+		ret = stmpe_reg_read(stmpe, stmpe->regs[STMPE_IDX_GPMR_LSB]);
+		if (ret < 0) {
+			dev_err(stmpe->dev, "Failed to read GPMR_LSB: %d\n", ret);
+			goto err;
+		}
+		ret = stmpe_reg_read(stmpe, stmpe->regs[STMPE_IDX_GPMR_CSB]);
+		if (ret < 0) {
+			dev_err(stmpe->dev, "Failed to read GPMR_CSB: %d\n", ret);
+			goto err;
+		}
 	}
 
 	for (i = 0; i < CACHE_NR_REGS; i++) {
@@ -219,6 +227,7 @@
 		}
 	}
 
+err:
 	mutex_unlock(&stmpe_gpio->irq_lock);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-tb10x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-tb10x.c
@@ -195,7 +195,7 @@
 				handle_edge_irq, IRQ_NOREQUEST, IRQ_NOPROBE,
 				IRQ_GC_INIT_MASK_CACHE);
 		if (ret)
-			return ret;
+			goto err_remove_domain;
 
 		gc = tb10x_gpio->domain->gc->gc[0];
 		gc->reg_base                         = tb10x_gpio->base;
@@ -209,6 +209,10 @@
 	}
 
 	return 0;
+
+err_remove_domain:
+	irq_domain_remove(tb10x_gpio->domain);
+	return ret;
 }
 
 static int tb10x_gpio_remove(struct platform_device *pdev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-tc3589x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-tc3589x.c
@@ -209,7 +209,7 @@
 				continue;
 
 			tc3589x_gpio->oldregs[i][j] = new;
-			tc3589x_reg_write(tc3589x, regmap[i] + j * 8, new);
+			tc3589x_reg_write(tc3589x, regmap[i] + j, new);
 		}
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-tegra.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-tegra.c
@@ -365,6 +365,7 @@
 	struct tegra_gpio_info *tgi = bank->tgi;
 	unsigned int gpio = d->hwirq;
 
+	tegra_gpio_irq_mask(d);
 	gpiochip_unlock_as_irq(&tgi->gc, gpio);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-tegra186.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-tegra186.c
@@ -234,9 +234,12 @@
 	return offset + pin;
 }
 
+#define to_tegra_gpio(x) container_of((x), struct tegra_gpio, gpio)
+
 static void tegra186_irq_ack(struct irq_data *data)
 {
-	struct tegra_gpio *gpio = irq_data_get_irq_chip_data(data);
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
+	struct tegra_gpio *gpio = to_tegra_gpio(gc);
 	void __iomem *base;
 
 	base = tegra186_gpio_get_base(gpio, data->hwirq);
@@ -248,7 +251,8 @@
 
 static void tegra186_irq_mask(struct irq_data *data)
 {
-	struct tegra_gpio *gpio = irq_data_get_irq_chip_data(data);
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
+	struct tegra_gpio *gpio = to_tegra_gpio(gc);
 	void __iomem *base;
 	u32 value;
 
@@ -263,7 +267,8 @@
 
 static void tegra186_irq_unmask(struct irq_data *data)
 {
-	struct tegra_gpio *gpio = irq_data_get_irq_chip_data(data);
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
+	struct tegra_gpio *gpio = to_tegra_gpio(gc);
 	void __iomem *base;
 	u32 value;
 
@@ -278,7 +283,8 @@
 
 static int tegra186_irq_set_type(struct irq_data *data, unsigned int type)
 {
-	struct tegra_gpio *gpio = irq_data_get_irq_chip_data(data);
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
+	struct tegra_gpio *gpio = to_tegra_gpio(gc);
 	void __iomem *base;
 	u32 value;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-thunderx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-thunderx.c
@@ -53,6 +53,7 @@
 struct thunderx_gpio {
 	struct gpio_chip	chip;
 	u8 __iomem		*register_base;
+	struct irq_domain	*irqd;
 	struct msix_entry	*msix_entries;	/* per line MSI-X */
 	struct thunderx_line	*line_entries;	/* per line irq info */
 	raw_spinlock_t		lock;
@@ -282,60 +283,54 @@
 	}
 }
 
-static void thunderx_gpio_irq_ack(struct irq_data *d)
+static void thunderx_gpio_irq_ack(struct irq_data *data)
 {
-	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-	struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
+	struct thunderx_line *txline = irq_data_get_irq_chip_data(data);
 
 	writeq(GPIO_INTR_INTR,
-	       txgpio->register_base + intr_reg(irqd_to_hwirq(d)));
+	       txline->txgpio->register_base + intr_reg(txline->line));
 }
 
-static void thunderx_gpio_irq_mask(struct irq_data *d)
+static void thunderx_gpio_irq_mask(struct irq_data *data)
 {
-	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-	struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
+	struct thunderx_line *txline = irq_data_get_irq_chip_data(data);
 
 	writeq(GPIO_INTR_ENA_W1C,
-	       txgpio->register_base + intr_reg(irqd_to_hwirq(d)));
+	       txline->txgpio->register_base + intr_reg(txline->line));
 }
 
-static void thunderx_gpio_irq_mask_ack(struct irq_data *d)
+static void thunderx_gpio_irq_mask_ack(struct irq_data *data)
 {
-	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-	struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
+	struct thunderx_line *txline = irq_data_get_irq_chip_data(data);
 
 	writeq(GPIO_INTR_ENA_W1C | GPIO_INTR_INTR,
-	       txgpio->register_base + intr_reg(irqd_to_hwirq(d)));
+	       txline->txgpio->register_base + intr_reg(txline->line));
 }
 
-static void thunderx_gpio_irq_unmask(struct irq_data *d)
+static void thunderx_gpio_irq_unmask(struct irq_data *data)
 {
-	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-	struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
+	struct thunderx_line *txline = irq_data_get_irq_chip_data(data);
 
 	writeq(GPIO_INTR_ENA_W1S,
-	       txgpio->register_base + intr_reg(irqd_to_hwirq(d)));
+	       txline->txgpio->register_base + intr_reg(txline->line));
 }
 
-static int thunderx_gpio_irq_set_type(struct irq_data *d,
+static int thunderx_gpio_irq_set_type(struct irq_data *data,
 				      unsigned int flow_type)
 {
-	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-	struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
-	struct thunderx_line *txline =
-		&txgpio->line_entries[irqd_to_hwirq(d)];
+	struct thunderx_line *txline = irq_data_get_irq_chip_data(data);
+	struct thunderx_gpio *txgpio = txline->txgpio;
 	u64 bit_cfg;
 
-	irqd_set_trigger_type(d, flow_type);
+	irqd_set_trigger_type(data, flow_type);
 
 	bit_cfg = txline->fil_bits | GPIO_BIT_CFG_INT_EN;
 
 	if (flow_type & IRQ_TYPE_EDGE_BOTH) {
-		irq_set_handler_locked(d, handle_fasteoi_ack_irq);
+		irq_set_handler_locked(data, handle_fasteoi_ack_irq);
 		bit_cfg |= GPIO_BIT_CFG_INT_TYPE;
 	} else {
-		irq_set_handler_locked(d, handle_fasteoi_mask_irq);
+		irq_set_handler_locked(data, handle_fasteoi_mask_irq);
 	}
 
 	raw_spin_lock(&txgpio->lock);
@@ -364,6 +359,33 @@
 	irq_chip_disable_parent(data);
 }
 
+static int thunderx_gpio_irq_request_resources(struct irq_data *data)
+{
+	struct thunderx_line *txline = irq_data_get_irq_chip_data(data);
+	struct thunderx_gpio *txgpio = txline->txgpio;
+	int r;
+
+	r = gpiochip_lock_as_irq(&txgpio->chip, txline->line);
+	if (r)
+		return r;
+
+	r = irq_chip_request_resources_parent(data);
+	if (r)
+		gpiochip_unlock_as_irq(&txgpio->chip, txline->line);
+
+	return r;
+}
+
+static void thunderx_gpio_irq_release_resources(struct irq_data *data)
+{
+	struct thunderx_line *txline = irq_data_get_irq_chip_data(data);
+	struct thunderx_gpio *txgpio = txline->txgpio;
+
+	irq_chip_release_resources_parent(data);
+
+	gpiochip_unlock_as_irq(&txgpio->chip, txline->line);
+}
+
 /*
  * Interrupts are chained from underlying MSI-X vectors.  We have
  * these irq_chip functions to be able to handle level triggering
@@ -380,22 +402,48 @@
 	.irq_unmask		= thunderx_gpio_irq_unmask,
 	.irq_eoi		= irq_chip_eoi_parent,
 	.irq_set_affinity	= irq_chip_set_affinity_parent,
+	.irq_request_resources	= thunderx_gpio_irq_request_resources,
+	.irq_release_resources	= thunderx_gpio_irq_release_resources,
 	.irq_set_type		= thunderx_gpio_irq_set_type,
 
 	.flags			= IRQCHIP_SET_TYPE_MASKED
 };
 
-static int thunderx_gpio_child_to_parent_hwirq(struct gpio_chip *gc,
-					       unsigned int child,
-					       unsigned int child_type,
-					       unsigned int *parent,
-					       unsigned int *parent_type)
+static int thunderx_gpio_irq_translate(struct irq_domain *d,
+				       struct irq_fwspec *fwspec,
+				       irq_hw_number_t *hwirq,
+				       unsigned int *type)
+{
+	struct thunderx_gpio *txgpio = d->host_data;
+
+	if (WARN_ON(fwspec->param_count < 2))
+		return -EINVAL;
+	if (fwspec->param[0] >= txgpio->chip.ngpio)
+		return -EINVAL;
+	*hwirq = fwspec->param[0];
+	*type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
+	return 0;
+}
+
+static int thunderx_gpio_irq_alloc(struct irq_domain *d, unsigned int virq,
+				   unsigned int nr_irqs, void *arg)
 {
-	struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
+	struct thunderx_line *txline = arg;
 
-	*parent = txgpio->base_msi + (2 * child);
-	*parent_type = IRQ_TYPE_LEVEL_HIGH;
-	return 0;
+	return irq_domain_set_hwirq_and_chip(d, virq, txline->line,
+					     &thunderx_gpio_irq_chip, txline);
+}
+
+static const struct irq_domain_ops thunderx_gpio_irqd_ops = {
+	.alloc		= thunderx_gpio_irq_alloc,
+	.translate	= thunderx_gpio_irq_translate
+};
+
+static int thunderx_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
+{
+	struct thunderx_gpio *txgpio = gpiochip_get_data(chip);
+
+	return irq_find_mapping(txgpio->irqd, offset);
 }
 
 static int thunderx_gpio_probe(struct pci_dev *pdev,
@@ -405,7 +453,6 @@
 	struct device *dev = &pdev->dev;
 	struct thunderx_gpio *txgpio;
 	struct gpio_chip *chip;
-	struct gpio_irq_chip *girq;
 	int ngpio, i;
 	int err = 0;
 
@@ -450,8 +497,8 @@
 	}
 
 	txgpio->msix_entries = devm_kcalloc(dev,
-					    ngpio, sizeof(struct msix_entry),
-					    GFP_KERNEL);
+					  ngpio, sizeof(struct msix_entry),
+					  GFP_KERNEL);
 	if (!txgpio->msix_entries) {
 		err = -ENOMEM;
 		goto out;
@@ -492,6 +539,27 @@
 	if (err < 0)
 		goto out;
 
+	/*
+	 * Push GPIO specific irqdomain on hierarchy created as a side
+	 * effect of the pci_enable_msix()
+	 */
+	txgpio->irqd = irq_domain_create_hierarchy(irq_get_irq_data(txgpio->msix_entries[0].vector)->domain,
+						   0, 0, of_node_to_fwnode(dev->of_node),
+						   &thunderx_gpio_irqd_ops, txgpio);
+	if (!txgpio->irqd) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	/* Push on irq_data and the domain for each line. */
+	for (i = 0; i < ngpio; i++) {
+		err = irq_domain_push_irq(txgpio->irqd,
+					  txgpio->msix_entries[i].vector,
+					  &txgpio->line_entries[i]);
+		if (err < 0)
+			dev_err(dev, "irq_domain_push_irq: %d\n", err);
+	}
+
 	chip->label = KBUILD_MODNAME;
 	chip->parent = dev;
 	chip->owner = THIS_MODULE;
@@ -506,28 +574,11 @@
 	chip->set = thunderx_gpio_set;
 	chip->set_multiple = thunderx_gpio_set_multiple;
 	chip->set_config = thunderx_gpio_set_config;
-	girq = &chip->irq;
-	girq->chip = &thunderx_gpio_irq_chip;
-	girq->fwnode = of_node_to_fwnode(dev->of_node);
-	girq->parent_domain =
-		irq_get_irq_data(txgpio->msix_entries[0].vector)->domain;
-	girq->child_to_parent_hwirq = thunderx_gpio_child_to_parent_hwirq;
-	girq->handler = handle_bad_irq;
-	girq->default_type = IRQ_TYPE_NONE;
-
+	chip->to_irq = thunderx_gpio_to_irq;
 	err = devm_gpiochip_add_data(dev, chip, txgpio);
 	if (err)
 		goto out;
 
-	/* Push on irq_data and the domain for each line. */
-	for (i = 0; i < ngpio; i++) {
-		err = irq_domain_push_irq(chip->irq.domain,
-					  txgpio->msix_entries[i].vector,
-					  chip);
-		if (err < 0)
-			dev_err(dev, "irq_domain_push_irq: %d\n", err);
-	}
-
 	dev_info(dev, "ThunderX GPIO: %d lines with base %d.\n",
 		 ngpio, chip->base);
 	return 0;
@@ -542,10 +593,10 @@
 	struct thunderx_gpio *txgpio = pci_get_drvdata(pdev);
 
 	for (i = 0; i < txgpio->chip.ngpio; i++)
-		irq_domain_pop_irq(txgpio->chip.irq.domain,
+		irq_domain_pop_irq(txgpio->irqd,
 				   txgpio->msix_entries[i].vector);
 
-	irq_domain_remove(txgpio->chip.irq.domain);
+	irq_domain_remove(txgpio->irqd);
 
 	pci_set_drvdata(pdev, NULL);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-timberdale.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-timberdale.c
@@ -43,9 +43,10 @@
 	unsigned offset, bool enabled)
 {
 	struct timbgpio *tgpio = gpiochip_get_data(gpio);
+	unsigned long flags;
 	u32 reg;
 
-	spin_lock(&tgpio->lock);
+	spin_lock_irqsave(&tgpio->lock, flags);
 	reg = ioread32(tgpio->membase + offset);
 
 	if (enabled)
@@ -54,7 +55,7 @@
 		reg &= ~(1 << index);
 
 	iowrite32(reg, tgpio->membase + offset);
-	spin_unlock(&tgpio->lock);
+	spin_unlock_irqrestore(&tgpio->lock, flags);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-tps68470.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-tps68470.c
@@ -91,13 +91,13 @@
 	struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc);
 	struct regmap *regmap = tps68470_gpio->tps68470_regmap;
 
+	/* Set the initial value */
+	tps68470_gpio_set(gc, offset, value);
+
 	/* rest are always outputs */
 	if (offset >= TPS68470_N_REGULAR_GPIO)
 		return 0;
 
-	/* Set the initial value */
-	tps68470_gpio_set(gc, offset, value);
-
 	return regmap_update_bits(regmap, TPS68470_GPIO_CTL_REG_A(offset),
 				 TPS68470_GPIO_MODE_MASK,
 				 TPS68470_GPIO_MODE_OUT_CMOS);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-tqmx86.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-tqmx86.c
@@ -235,8 +235,8 @@
 	struct resource *res;
 	int ret, irq;
 
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0)
+	irq = platform_get_irq_optional(pdev, 0);
+	if (irq < 0 && irq != -ENXIO)
 		return irq;
 
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
@@ -275,7 +275,7 @@
 
 	pm_runtime_enable(&pdev->dev);
 
-	if (irq) {
+	if (irq > 0) {
 		struct irq_chip *irq_chip = &gpio->irq_chip;
 		u8 irq_status;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-ts4900.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-ts4900.c
@@ -1,7 +1,7 @@
 /*
  * Digital I/O driver for Technologic Systems I2C FPGA Core
  *
- * Copyright (C) 2015 Technologic Systems
+ * Copyright (C) 2015, 2018 Technologic Systems
  * Copyright (C) 2016 Savoir-Faire Linux
  *
  * This program is free software; you can redistribute it and/or
@@ -52,19 +52,33 @@
 {
 	struct ts4900_gpio_priv *priv = gpiochip_get_data(chip);
 
-	/*
-	 * This will clear the output enable bit, the other bits are
-	 * dontcare when this is cleared
+	/* Only clear the OE bit here, requires a RMW. Prevents potential issue
+	 * with OE and data getting to the physical pin at different times.
 	 */
-	return regmap_write(priv->regmap, offset, 0);
+	return regmap_update_bits(priv->regmap, offset, TS4900_GPIO_OE, 0);
 }
 
 static int ts4900_gpio_direction_output(struct gpio_chip *chip,
 					unsigned int offset, int value)
 {
 	struct ts4900_gpio_priv *priv = gpiochip_get_data(chip);
+	unsigned int reg;
 	int ret;
 
+	/* If changing from an input to an output, we need to first set the
+	 * proper data bit to what is requested and then set OE bit. This
+	 * prevents a glitch that can occur on the IO line
+	 */
+	regmap_read(priv->regmap, offset, &reg);
+	if (!(reg & TS4900_GPIO_OE)) {
+		if (value)
+			reg = TS4900_GPIO_OUT;
+		else
+			reg &= ~TS4900_GPIO_OUT;
+
+		regmap_write(priv->regmap, offset, reg);
+	}
+
 	if (value)
 		ret = regmap_write(priv->regmap, offset, TS4900_GPIO_OE |
 							 TS4900_GPIO_OUT);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-uniphier.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-uniphier.c
@@ -188,7 +188,7 @@
 
 	uniphier_gpio_reg_update(priv, UNIPHIER_GPIO_IRQ_EN, mask, 0);
 
-	return irq_chip_mask_parent(data);
+	irq_chip_mask_parent(data);
 }
 
 static void uniphier_gpio_irq_unmask(struct irq_data *data)
@@ -198,7 +198,7 @@
 
 	uniphier_gpio_reg_update(priv, UNIPHIER_GPIO_IRQ_EN, mask, mask);
 
-	return irq_chip_unmask_parent(data);
+	irq_chip_unmask_parent(data);
 }
 
 static int uniphier_gpio_irq_set_type(struct irq_data *data, unsigned int type)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-vf610.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-vf610.c
@@ -125,12 +125,16 @@
 {
 	struct vf610_gpio_port *port = gpiochip_get_data(chip);
 	unsigned long mask = BIT(gpio);
-
-	if (port->sdata && port->sdata->have_paddr)
-		vf610_gpio_writel(mask, port->gpio_base + GPIO_PDDR);
+	u32 val;
 
 	vf610_gpio_set(chip, gpio, value);
 
+	if (port->sdata && port->sdata->have_paddr) {
+		val = vf610_gpio_readl(port->gpio_base + GPIO_PDDR);
+		val |= mask;
+		vf610_gpio_writel(val, port->gpio_base + GPIO_PDDR);
+	}
+
 	return pinctrl_gpio_direction_output(chip->base + gpio);
 }
 
@@ -300,7 +304,7 @@
 	gc = &port->gc;
 	gc->of_node = np;
 	gc->parent = dev;
-	gc->label = "vf610-gpio";
+	gc->label = dev_name(dev);
 	gc->ngpio = VF610_GPIO_PER_PORT;
 	gc->base = of_alias_get_id(np, "gpio") * VF610_GPIO_PER_PORT;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-vr41xx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-vr41xx.c
@@ -217,8 +217,6 @@
 	printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n",
 	       maskl, pendl, maskh, pendh);
 
-	atomic_inc(&irq_err_count);
-
 	return -EINVAL;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-wcove.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-wcove.c
@@ -102,7 +102,7 @@
 	unsigned int reg;
 
 	if (gpio >= WCOVE_GPIO_NUM)
-		return -EOPNOTSUPP;
+		return -ENOTSUPP;
 
 	if (reg_type == CTRL_IN)
 		reg = GPIO_IN_CTRL_BASE + gpio;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-winbond.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-winbond.c
@@ -385,12 +385,13 @@
 	unsigned long *base = gpiochip_get_data(gc);
 	const struct winbond_gpio_info *info;
 	bool val;
+	int ret;
 
 	winbond_gpio_get_info(&offset, &info);
 
-	val = winbond_sio_enter(*base);
-	if (val)
-		return val;
+	ret = winbond_sio_enter(*base);
+	if (ret)
+		return ret;
 
 	winbond_sio_select_logical(*base, info->dev);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-xilinx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-xilinx.c
@@ -1,8 +1,15 @@
-// SPDX-License-Identifier: GPL-2.0-only
 /*
  * Xilinx gpio driver for xps/axi_gpio IP.
  *
  * Copyright 2008 - 2013 Xilinx, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
 #include <linux/bitops.h>
@@ -10,19 +17,32 @@
 #include <linux/errno.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
+#include <linux/of_irq.h>
 #include <linux/of_platform.h>
+#include <linux/of_gpio.h>
+#include <linux/interrupt.h>
 #include <linux/io.h>
-#include <linux/gpio/driver.h>
+#include <linux/irq.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/gpio.h>
 #include <linux/slab.h>
+#include <linux/pm_runtime.h>
+#include <linux/clk.h>
 
 /* Register Offset Definitions */
-#define XGPIO_DATA_OFFSET   (0x0)	/* Data register  */
-#define XGPIO_TRI_OFFSET    (0x4)	/* I/O direction register  */
+#define XGPIO_DATA_OFFSET	0x0 /* Data register */
+#define XGPIO_TRI_OFFSET	0x4 /* I/O direction register */
+#define XGPIO_GIER_OFFSET	0x11c /* Global Interrupt Enable */
+#define XGPIO_GIER_IE		BIT(31)
+
+#define XGPIO_IPISR_OFFSET	0x120 /* IP Interrupt Status */
+#define XGPIO_IPIER_OFFSET	0x128 /* IP Interrupt Enable */
 
 #define XGPIO_CHANNEL_OFFSET	0x8
 
 /* Read/Write access to the GPIO registers */
-#if defined(CONFIG_ARCH_ZYNQ) || defined(CONFIG_X86)
+#if defined(CONFIG_ARCH_ZYNQ) || defined(CONFIG_ARM64)
 # define xgpio_readreg(offset)		readl(offset)
 # define xgpio_writereg(offset, val)	writel(val, offset)
 #else
@@ -32,46 +52,32 @@
 
 /**
  * struct xgpio_instance - Stores information about GPIO device
- * @gc: GPIO chip
- * @regs: register block
- * @gpio_width: GPIO width for every channel
+ * @mmchip: OF GPIO chip for memory mapped banks
+ * @mmchip_dual: Pointer to the OF dual gpio chip
  * @gpio_state: GPIO state shadow register
  * @gpio_dir: GPIO direction shadow register
+ * @offset: GPIO channel offset
+ * @irq_base: GPIO channel irq base address
+ * @irq_enable: GPIO irq enable/disable bitfield
+ * @no_init: No intitialisation at probe
  * @gpio_lock: Lock used for synchronization
+ * @irq_domain: irq_domain of the controller
+ * @clk: clock resource for this driver
  */
 struct xgpio_instance {
-	struct gpio_chip gc;
-	void __iomem *regs;
-	unsigned int gpio_width[2];
-	u32 gpio_state[2];
-	u32 gpio_dir[2];
-	spinlock_t gpio_lock[2];
+	struct of_mm_gpio_chip mmchip;
+	struct of_mm_gpio_chip *mmchip_dual;
+	u32 gpio_state;
+	u32 gpio_dir;
+	u32 offset;
+	int irq_base;
+	u32 irq_enable;
+	bool no_init;
+	spinlock_t gpio_lock;
+	struct irq_domain *irq_domain;
+	struct clk *clk;
 };
 
-static inline int xgpio_index(struct xgpio_instance *chip, int gpio)
-{
-	if (gpio >= chip->gpio_width[0])
-		return 1;
-
-	return 0;
-}
-
-static inline int xgpio_regoffset(struct xgpio_instance *chip, int gpio)
-{
-	if (xgpio_index(chip, gpio))
-		return XGPIO_CHANNEL_OFFSET;
-
-	return 0;
-}
-
-static inline int xgpio_offset(struct xgpio_instance *chip, int gpio)
-{
-	if (xgpio_index(chip, gpio))
-		return gpio - chip->gpio_width[0];
-
-	return gpio;
-}
-
 /**
  * xgpio_get - Read the specified signal of the GPIO device.
  * @gc:     Pointer to gpio_chip device structure.
@@ -85,13 +91,13 @@
  */
 static int xgpio_get(struct gpio_chip *gc, unsigned int gpio)
 {
-	struct xgpio_instance *chip = gpiochip_get_data(gc);
-	u32 val;
+	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+	struct xgpio_instance *chip =
+	    container_of(mm_gc, struct xgpio_instance, mmchip);
 
-	val = xgpio_readreg(chip->regs + XGPIO_DATA_OFFSET +
-			    xgpio_regoffset(chip, gpio));
+	void __iomem *regs = mm_gc->regs + chip->offset;
 
-	return !!(val & BIT(xgpio_offset(chip, gpio)));
+	return !!(xgpio_readreg(regs + XGPIO_DATA_OFFSET) & BIT(gpio));
 }
 
 /**
@@ -106,22 +112,23 @@
 static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
 {
 	unsigned long flags;
-	struct xgpio_instance *chip = gpiochip_get_data(gc);
-	int index =  xgpio_index(chip, gpio);
-	int offset =  xgpio_offset(chip, gpio);
+	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+	struct xgpio_instance *chip =
+	    container_of(mm_gc, struct xgpio_instance, mmchip);
+	void __iomem *regs = mm_gc->regs;
 
-	spin_lock_irqsave(&chip->gpio_lock[index], flags);
+	spin_lock_irqsave(&chip->gpio_lock, flags);
 
 	/* Write to GPIO signal and set its direction to output */
 	if (val)
-		chip->gpio_state[index] |= BIT(offset);
+		chip->gpio_state |= BIT(gpio);
 	else
-		chip->gpio_state[index] &= ~BIT(offset);
+		chip->gpio_state &= ~BIT(gpio);
 
-	xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET +
-		       xgpio_regoffset(chip, gpio), chip->gpio_state[index]);
+	xgpio_writereg(regs + chip->offset + XGPIO_DATA_OFFSET,
+							 chip->gpio_state);
 
-	spin_unlock_irqrestore(&chip->gpio_lock[index], flags);
+	spin_unlock_irqrestore(&chip->gpio_lock, flags);
 }
 
 /**
@@ -137,37 +144,30 @@
 			       unsigned long *bits)
 {
 	unsigned long flags;
-	struct xgpio_instance *chip = gpiochip_get_data(gc);
-	int index = xgpio_index(chip, 0);
-	int offset, i;
+	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+	struct xgpio_instance *chip =
+	    container_of(mm_gc, struct xgpio_instance, mmchip);
+	void __iomem *regs = mm_gc->regs;
+	int i;
 
-	spin_lock_irqsave(&chip->gpio_lock[index], flags);
+	spin_lock_irqsave(&chip->gpio_lock, flags);
 
 	/* Write to GPIO signals */
 	for (i = 0; i < gc->ngpio; i++) {
 		if (*mask == 0)
 			break;
-		if (index !=  xgpio_index(chip, i)) {
-			xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET +
-				       xgpio_regoffset(chip, i),
-				       chip->gpio_state[index]);
-			spin_unlock_irqrestore(&chip->gpio_lock[index], flags);
-			index =  xgpio_index(chip, i);
-			spin_lock_irqsave(&chip->gpio_lock[index], flags);
-		}
 		if (__test_and_clear_bit(i, mask)) {
-			offset =  xgpio_offset(chip, i);
 			if (test_bit(i, bits))
-				chip->gpio_state[index] |= BIT(offset);
+				chip->gpio_state |= BIT(i);
 			else
-				chip->gpio_state[index] &= ~BIT(offset);
+				chip->gpio_state &= ~BIT(i);
 		}
 	}
 
-	xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET +
-		       xgpio_regoffset(chip, i), chip->gpio_state[index]);
+	xgpio_writereg(regs + chip->offset + XGPIO_DATA_OFFSET,
+		       chip->gpio_state);
 
-	spin_unlock_irqrestore(&chip->gpio_lock[index], flags);
+	spin_unlock_irqrestore(&chip->gpio_lock, flags);
 }
 
 /**
@@ -175,6 +175,8 @@
  * @gc:     Pointer to gpio_chip device structure.
  * @gpio:   GPIO signal number.
  *
+ * This function sets the direction of specified GPIO signal as input.
+ *
  * Return:
  * 0 - if direction of GPIO signals is set as input
  * otherwise it returns negative error value.
@@ -182,18 +184,18 @@
 static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
 {
 	unsigned long flags;
-	struct xgpio_instance *chip = gpiochip_get_data(gc);
-	int index =  xgpio_index(chip, gpio);
-	int offset =  xgpio_offset(chip, gpio);
+	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+	struct xgpio_instance *chip =
+	    container_of(mm_gc, struct xgpio_instance, mmchip);
+	void __iomem *regs = mm_gc->regs;
 
-	spin_lock_irqsave(&chip->gpio_lock[index], flags);
+	spin_lock_irqsave(&chip->gpio_lock, flags);
 
 	/* Set the GPIO bit in shadow register and set direction as input */
-	chip->gpio_dir[index] |= BIT(offset);
-	xgpio_writereg(chip->regs + XGPIO_TRI_OFFSET +
-		       xgpio_regoffset(chip, gpio), chip->gpio_dir[index]);
+	chip->gpio_dir |= BIT(gpio);
+	xgpio_writereg(regs + chip->offset + XGPIO_TRI_OFFSET, chip->gpio_dir);
 
-	spin_unlock_irqrestore(&chip->gpio_lock[index], flags);
+	spin_unlock_irqrestore(&chip->gpio_lock, flags);
 
 	return 0;
 }
@@ -213,164 +215,580 @@
 static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
 {
 	unsigned long flags;
-	struct xgpio_instance *chip = gpiochip_get_data(gc);
-	int index =  xgpio_index(chip, gpio);
-	int offset =  xgpio_offset(chip, gpio);
+	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+	struct xgpio_instance *chip =
+	    container_of(mm_gc, struct xgpio_instance, mmchip);
+	void __iomem *regs = mm_gc->regs;
 
-	spin_lock_irqsave(&chip->gpio_lock[index], flags);
+	spin_lock_irqsave(&chip->gpio_lock, flags);
 
 	/* Write state of GPIO signal */
 	if (val)
-		chip->gpio_state[index] |= BIT(offset);
+		chip->gpio_state |= BIT(gpio);
 	else
-		chip->gpio_state[index] &= ~BIT(offset);
-	xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET +
-			xgpio_regoffset(chip, gpio), chip->gpio_state[index]);
+		chip->gpio_state &= ~BIT(gpio);
+	xgpio_writereg(regs + chip->offset + XGPIO_DATA_OFFSET,
+		       chip->gpio_state);
 
 	/* Clear the GPIO bit in shadow register and set direction as output */
-	chip->gpio_dir[index] &= ~BIT(offset);
-	xgpio_writereg(chip->regs + XGPIO_TRI_OFFSET +
-			xgpio_regoffset(chip, gpio), chip->gpio_dir[index]);
+	chip->gpio_dir &= ~BIT(gpio);
+	xgpio_writereg(regs + chip->offset + XGPIO_TRI_OFFSET, chip->gpio_dir);
 
-	spin_unlock_irqrestore(&chip->gpio_lock[index], flags);
+	spin_unlock_irqrestore(&chip->gpio_lock, flags);
 
 	return 0;
 }
 
 /**
  * xgpio_save_regs - Set initial values of GPIO pins
- * @chip: Pointer to GPIO instance
+ * @mm_gc: Pointer to memory mapped GPIO chip structure
+ */
+static void xgpio_save_regs(struct of_mm_gpio_chip *mm_gc)
+{
+	struct xgpio_instance *chip =
+	    container_of(mm_gc, struct xgpio_instance, mmchip);
+	if (chip->no_init) {
+		chip->gpio_state = xgpio_readreg(mm_gc->regs +
+						 XGPIO_DATA_OFFSET);
+		chip->gpio_dir = xgpio_readreg(mm_gc->regs + XGPIO_TRI_OFFSET);
+	} else {
+		xgpio_writereg(mm_gc->regs + chip->offset + XGPIO_DATA_OFFSET,
+			       chip->gpio_state);
+		xgpio_writereg(mm_gc->regs + chip->offset + XGPIO_TRI_OFFSET,
+			       chip->gpio_dir);
+	}
+}
+
+/**
+ * xgpio_xlate - Translate gpio_spec to the GPIO number and flags
+ * @gc: Pointer to gpio_chip device structure.
+ * @gpiospec:  gpio specifier as found in the device tree
+ * @flags: A flags pointer based on binding
+ *
+ * Return:
+ * irq number otherwise -EINVAL
+ */
+static int xgpio_xlate(struct gpio_chip *gc,
+		       const struct of_phandle_args *gpiospec, u32 *flags)
+{
+	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+	struct xgpio_instance *chip = container_of(mm_gc, struct xgpio_instance,
+						   mmchip);
+	if (gc->of_gpio_n_cells == 3 && flags)
+		*flags = gpiospec->args[2];
+
+	if (gpiospec->args[1] == chip->offset)
+		return gpiospec->args[0];
+
+	return -EINVAL;
+}
+
+/**
+ * xgpio_irq_mask - Write the specified signal of the GPIO device.
+ * @irq_data: per irq and chip data passed down to chip functions
+ */
+static void xgpio_irq_mask(struct irq_data *irq_data)
+{
+	unsigned long flags;
+	struct xgpio_instance *chip = irq_data_get_irq_chip_data(irq_data);
+	struct of_mm_gpio_chip *mm_gc = &chip->mmchip;
+	u32 offset = irq_data->irq - chip->irq_base;
+	u32 temp;
+
+	pr_debug("%s: Disable %d irq, irq_enable_mask 0x%x\n",
+		__func__, offset, chip->irq_enable);
+
+	spin_lock_irqsave(&chip->gpio_lock, flags);
+
+	chip->irq_enable &= ~BIT(offset);
+
+	if (!chip->irq_enable) {
+		/* Enable per channel interrupt */
+		temp = xgpio_readreg(mm_gc->regs + XGPIO_IPIER_OFFSET);
+		temp &= chip->offset / XGPIO_CHANNEL_OFFSET + 1;
+		xgpio_writereg(mm_gc->regs + XGPIO_IPIER_OFFSET, temp);
+
+		/* Disable global interrupt if channel interrupts are unused */
+		temp = xgpio_readreg(mm_gc->regs + XGPIO_IPIER_OFFSET);
+		if (!temp)
+			xgpio_writereg(mm_gc->regs + XGPIO_GIER_OFFSET,
+				       ~XGPIO_GIER_IE);
+
+	}
+	spin_unlock_irqrestore(&chip->gpio_lock, flags);
+}
+
+/**
+ * xgpio_irq_unmask - Write the specified signal of the GPIO device.
+ * @irq_data: per irq and chip data passed down to chip functions
+ */
+static void xgpio_irq_unmask(struct irq_data *irq_data)
+{
+	unsigned long flags;
+	struct xgpio_instance *chip = irq_data_get_irq_chip_data(irq_data);
+	struct of_mm_gpio_chip *mm_gc = &chip->mmchip;
+	u32 offset = irq_data->irq - chip->irq_base;
+	u32 temp;
+
+	pr_debug("%s: Enable %d irq, irq_enable_mask 0x%x\n",
+		__func__, offset, chip->irq_enable);
+
+	/* Setup pin as input */
+	xgpio_dir_in(&mm_gc->gc, offset);
+
+	spin_lock_irqsave(&chip->gpio_lock, flags);
+
+	chip->irq_enable |= BIT(offset);
+
+	if (chip->irq_enable) {
+
+		/* Enable per channel interrupt */
+		temp = xgpio_readreg(mm_gc->regs + XGPIO_IPIER_OFFSET);
+		temp |= chip->offset / XGPIO_CHANNEL_OFFSET + 1;
+		xgpio_writereg(mm_gc->regs + XGPIO_IPIER_OFFSET, temp);
+
+		/* Enable global interrupts */
+		xgpio_writereg(mm_gc->regs + XGPIO_GIER_OFFSET, XGPIO_GIER_IE);
+	}
+
+	spin_unlock_irqrestore(&chip->gpio_lock, flags);
+}
+
+/**
+ * xgpio_set_irq_type - Write the specified signal of the GPIO device.
+ * @irq_data: Per irq and chip data passed down to chip functions
+ * @type: Interrupt type that is to be set for the gpio pin
+ *
+ * Return:
+ * 0 if interrupt type is supported otherwise otherwise -EINVAL
+ */
+static int xgpio_set_irq_type(struct irq_data *irq_data, unsigned int type)
+{
+	/* Only rising edge case is supported now */
+	if (type & IRQ_TYPE_EDGE_RISING)
+		return 0;
+
+	return -EINVAL;
+}
+
+/* irq chip descriptor */
+static struct irq_chip xgpio_irqchip = {
+	.name		= "xgpio",
+	.irq_mask	= xgpio_irq_mask,
+	.irq_unmask	= xgpio_irq_unmask,
+	.irq_set_type	= xgpio_set_irq_type,
+};
+
+/**
+ * xgpio_to_irq - Find out gpio to Linux irq mapping
+ * @gc: Pointer to gpio_chip device structure.
+ * @offset: Gpio pin offset
+ *
+ * Return:
+ * irq number otherwise -EINVAL
+ */
+static int xgpio_to_irq(struct gpio_chip *gc, unsigned int offset)
+{
+	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+	struct xgpio_instance *chip = container_of(mm_gc, struct xgpio_instance,
+						   mmchip);
+
+	return irq_find_mapping(chip->irq_domain, offset);
+}
+
+/**
+ * xgpio_irqhandler - Gpio interrupt service routine
+ * @desc: Pointer to interrupt description
  */
-static void xgpio_save_regs(struct xgpio_instance *chip)
+static void xgpio_irqhandler(struct irq_desc *desc)
 {
-	xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET,	chip->gpio_state[0]);
-	xgpio_writereg(chip->regs + XGPIO_TRI_OFFSET, chip->gpio_dir[0]);
+	unsigned int irq = irq_desc_get_irq(desc);
 
-	if (!chip->gpio_width[1])
+	struct xgpio_instance *chip = (struct xgpio_instance *)
+						irq_get_handler_data(irq);
+	struct of_mm_gpio_chip *mm_gc = &chip->mmchip;
+	struct irq_chip *irqchip = irq_desc_get_chip(desc);
+	int offset;
+	unsigned long val;
+
+	if (!chip)
 		return;
 
-	xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET + XGPIO_CHANNEL_OFFSET,
-		       chip->gpio_state[1]);
-	xgpio_writereg(chip->regs + XGPIO_TRI_OFFSET + XGPIO_CHANNEL_OFFSET,
-		       chip->gpio_dir[1]);
+	chained_irq_enter(irqchip, desc);
+
+	val = xgpio_readreg(mm_gc->regs + chip->offset);
+	/* Only rising edge is supported */
+	val &= chip->irq_enable;
+
+	for_each_set_bit(offset, &val, chip->mmchip.gc.ngpio) {
+		generic_handle_irq(chip->irq_base + offset);
+	}
+
+	xgpio_writereg(mm_gc->regs + XGPIO_IPISR_OFFSET,
+		       chip->offset / XGPIO_CHANNEL_OFFSET + 1);
+
+	chained_irq_exit(irqchip, desc);
 }
 
+static struct lock_class_key gpio_lock_class;
+static struct lock_class_key gpio_request_class;
+
 /**
- * xgpio_of_probe - Probe method for the GPIO device.
+ * xgpio_irq_setup - Allocate irq for gpio and setup appropriate functions
+ * @np: Device node of the GPIO chip
+ * @chip: Pointer to private gpio channel structure
+ *
+ * Return:
+ * 0 if success, otherwise -1
+ */
+static int xgpio_irq_setup(struct device_node *np, struct xgpio_instance *chip)
+{
+	u32 pin_num;
+	struct resource res;
+
+	int ret = of_irq_to_resource(np, 0, &res);
+
+	if (ret <= 0) {
+		pr_info("GPIO IRQ not connected\n");
+		return 0;
+	}
+
+	chip->mmchip.gc.to_irq = xgpio_to_irq;
+
+	chip->irq_base = irq_alloc_descs(-1, 1, chip->mmchip.gc.ngpio, 0);
+	if (chip->irq_base < 0) {
+		pr_err("Couldn't allocate IRQ numbers\n");
+		return -1;
+	}
+	chip->irq_domain = irq_domain_add_legacy(np, chip->mmchip.gc.ngpio,
+						 chip->irq_base, 0,
+						 &irq_domain_simple_ops, NULL);
+
+	/*
+	 * set the irq chip, handler and irq chip data for callbacks for
+	 * each pin
+	 */
+	for (pin_num = 0; pin_num < chip->mmchip.gc.ngpio; pin_num++) {
+		u32 gpio_irq = irq_find_mapping(chip->irq_domain, pin_num);
+
+		irq_set_lockdep_class(gpio_irq, &gpio_lock_class,
+				      &gpio_request_class);
+		pr_debug("IRQ Base: %d, Pin %d = IRQ %d\n",
+			chip->irq_base,	pin_num, gpio_irq);
+		irq_set_chip_and_handler(gpio_irq, &xgpio_irqchip,
+					 handle_simple_irq);
+		irq_set_chip_data(gpio_irq, (void *)chip);
+	}
+	irq_set_handler_data(res.start, (void *)chip);
+	irq_set_chained_handler(res.start, xgpio_irqhandler);
+
+	return 0;
+}
+
+static int xgpio_request(struct gpio_chip *chip, unsigned int offset)
+{
+	int ret = pm_runtime_get_sync(chip->parent);
+
+	/*
+	 * If the device is already active pm_runtime_get() will return 1 on
+	 * success, but gpio_request still needs to return 0.
+	 */
+	return ret < 0 ? ret : 0;
+}
+
+static void xgpio_free(struct gpio_chip *chip, unsigned int offset)
+{
+	pm_runtime_put(chip->parent);
+}
+
+static int __maybe_unused xgpio_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	int irq;
+	struct irq_data *data;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq <= 0) {
+		dev_dbg(dev, "failed to get IRQ\n");
+		return 0;
+	}
+
+	data = irq_get_irq_data(irq);
+	if (!irqd_is_wakeup_set(data))
+		return pm_runtime_force_suspend(dev);
+
+	return 0;
+}
+
+static int __maybe_unused xgpio_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	int irq;
+	struct irq_data *data;
+
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq <= 0) {
+		dev_dbg(dev, "failed to get IRQ\n");
+		return 0;
+	}
+
+	data = irq_get_irq_data(irq);
+	if (!irqd_is_wakeup_set(data))
+		return pm_runtime_force_resume(dev);
+
+	return 0;
+}
+
+static int __maybe_unused xgpio_runtime_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct xgpio_instance *gpio = platform_get_drvdata(pdev);
+
+	clk_disable(gpio->clk);
+
+	return 0;
+}
+
+static int __maybe_unused xgpio_runtime_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct xgpio_instance *gpio = platform_get_drvdata(pdev);
+
+	return clk_enable(gpio->clk);
+}
+
+static const struct dev_pm_ops xgpio_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(xgpio_suspend, xgpio_resume)
+	SET_RUNTIME_PM_OPS(xgpio_runtime_suspend,
+			xgpio_runtime_resume, NULL)
+};
+
+/**
+ * xgpio_remove - Remove method for the GPIO device.
  * @pdev: pointer to the platform device
  *
+ * This function remove gpiochips and frees all the allocated resources.
+ *
+ * Return: 0 always
+ */
+static int xgpio_remove(struct platform_device *pdev)
+{
+	struct xgpio_instance *chip = platform_get_drvdata(pdev);
+
+	of_mm_gpiochip_remove(&chip->mmchip);
+	if (chip->mmchip_dual)
+		of_mm_gpiochip_remove(chip->mmchip_dual);
+	if (!pm_runtime_suspended(&pdev->dev))
+		clk_disable(chip->clk);
+	clk_unprepare(chip->clk);
+	pm_runtime_disable(&pdev->dev);
+
+	return 0;
+}
+
+/**
+ * xgpio_of_probe - Probe method for the GPIO device.
+ * @pdev:       platform device instance
+ *
+ * This function probes the GPIO device in the device tree. It initializes the
+ * driver data structure.
+ *
  * Return:
  * It returns 0, if the driver is bound to the GPIO device, or
  * a negative value if there is an error.
  */
-static int xgpio_probe(struct platform_device *pdev)
+static int xgpio_of_probe(struct platform_device *pdev)
 {
-	struct xgpio_instance *chip;
-	int status = 0;
 	struct device_node *np = pdev->dev.of_node;
-	u32 is_dual;
+	struct xgpio_instance *chip, *chip_dual;
+	int status = 0;
+	const u32 *tree_info;
+	u32 ngpio = 0;
+	u32 cells = 2;
 
 	chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
 	if (!chip)
 		return -ENOMEM;
 
-	platform_set_drvdata(pdev, chip);
-
 	/* Update GPIO state shadow register with default value */
-	of_property_read_u32(np, "xlnx,dout-default", &chip->gpio_state[0]);
+	if (of_property_read_u32(np, "xlnx,dout-default", &chip->gpio_state))
+		dev_dbg(&pdev->dev, "Missing xlnx,dout-default property\n");
+
+	/* By default, all pins are inputs */
+	chip->gpio_dir = 0xFFFFFFFF;
 
 	/* Update GPIO direction shadow register with default value */
-	if (of_property_read_u32(np, "xlnx,tri-default", &chip->gpio_dir[0]))
-		chip->gpio_dir[0] = 0xFFFFFFFF;
+	if (of_property_read_u32(np, "xlnx,tri-default", &chip->gpio_dir))
+		dev_dbg(&pdev->dev, "Missing xlnx,tri-default property\n");
+
+	chip->no_init = of_property_read_bool(np, "xlnx,no-init");
+
+	/* Update cells with gpio-cells value */
+	if (of_property_read_u32(np, "#gpio-cells", &cells))
+		dev_dbg(&pdev->dev, "Missing gpio-cells property\n");
 
 	/*
 	 * Check device node and parent device node for device width
 	 * and assume default width of 32
 	 */
-	if (of_property_read_u32(np, "xlnx,gpio-width", &chip->gpio_width[0]))
-		chip->gpio_width[0] = 32;
-
-	spin_lock_init(&chip->gpio_lock[0]);
+	if (of_property_read_u32(np, "xlnx,gpio-width", &ngpio))
+		ngpio = 32;
+	chip->mmchip.gc.ngpio = (u16)ngpio;
+
+	spin_lock_init(&chip->gpio_lock);
+
+	chip->mmchip.gc.parent = &pdev->dev;
+	chip->mmchip.gc.owner = THIS_MODULE;
+	chip->mmchip.gc.of_xlate = xgpio_xlate;
+	chip->mmchip.gc.of_gpio_n_cells = cells;
+	chip->mmchip.gc.direction_input = xgpio_dir_in;
+	chip->mmchip.gc.direction_output = xgpio_dir_out;
+	chip->mmchip.gc.get = xgpio_get;
+	chip->mmchip.gc.set = xgpio_set;
+	chip->mmchip.gc.request = xgpio_request;
+	chip->mmchip.gc.free = xgpio_free;
+	chip->mmchip.gc.set_multiple = xgpio_set_multiple;
 
-	if (of_property_read_u32(np, "xlnx,is-dual", &is_dual))
-		is_dual = 0;
+	chip->mmchip.save_regs = xgpio_save_regs;
 
-	if (is_dual) {
-		/* Update GPIO state shadow register with default value */
-		of_property_read_u32(np, "xlnx,dout-default-2",
-				     &chip->gpio_state[1]);
+	platform_set_drvdata(pdev, chip);
 
-		/* Update GPIO direction shadow register with default value */
-		if (of_property_read_u32(np, "xlnx,tri-default-2",
-					 &chip->gpio_dir[1]))
-			chip->gpio_dir[1] = 0xFFFFFFFF;
+	chip->clk = devm_clk_get(&pdev->dev, "s_axi_aclk");
+	if (IS_ERR(chip->clk)) {
+		if (PTR_ERR(chip->clk) != -ENOENT) {
+			if (PTR_ERR(chip->clk) != -EPROBE_DEFER)
+				dev_err(&pdev->dev, "Input clock not found\n");
+			return PTR_ERR(chip->clk);
+		}
 
 		/*
-		 * Check device node and parent device node for device width
-		 * and assume default width of 32
+		 * Clock framework support is optional, continue on
+		 * anyways if we don't find a matching clock.
 		 */
-		if (of_property_read_u32(np, "xlnx,gpio2-width",
-					 &chip->gpio_width[1]))
-			chip->gpio_width[1] = 32;
+		chip->clk = NULL;
+	}
 
-		spin_lock_init(&chip->gpio_lock[1]);
+	status = clk_prepare_enable(chip->clk);
+	if (status < 0) {
+		dev_err(&pdev->dev, "Failed to prepare clk\n");
+		return status;
 	}
 
-	chip->gc.base = -1;
-	chip->gc.ngpio = chip->gpio_width[0] + chip->gpio_width[1];
-	chip->gc.parent = &pdev->dev;
-	chip->gc.direction_input = xgpio_dir_in;
-	chip->gc.direction_output = xgpio_dir_out;
-	chip->gc.get = xgpio_get;
-	chip->gc.set = xgpio_set;
-	chip->gc.set_multiple = xgpio_set_multiple;
+	pm_runtime_set_active(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
 
-	chip->gc.label = dev_name(&pdev->dev);
+	/* Call the OF gpio helper to setup and register the GPIO device */
+	status = of_mm_gpiochip_add(np, &chip->mmchip);
+	if (status) {
+		pr_err("%pOF: error in probe function with status %d\n",
+		       np, status);
+		goto err_unprepare_clk;
+	}
 
-	chip->regs = devm_platform_ioremap_resource(pdev, 0);
-	if (IS_ERR(chip->regs)) {
-		dev_err(&pdev->dev, "failed to ioremap memory resource\n");
-		return PTR_ERR(chip->regs);
+	status = xgpio_irq_setup(np, chip);
+	if (status) {
+		pr_err("%s: GPIO IRQ initialization failed %d\n",
+		       np->full_name, status);
+		goto err_pm_put;
 	}
 
-	xgpio_save_regs(chip);
+	pr_info("XGpio: %s: registered, base is %d\n", np->full_name,
+							chip->mmchip.gc.base);
 
-	status = devm_gpiochip_add_data(&pdev->dev, &chip->gc, chip);
-	if (status) {
-		dev_err(&pdev->dev, "failed to add GPIO chip\n");
-		return status;
+	tree_info = of_get_property(np, "xlnx,is-dual", NULL);
+	if (tree_info && be32_to_cpup(tree_info)) {
+		chip_dual = devm_kzalloc(&pdev->dev, sizeof(*chip_dual),
+					 GFP_KERNEL);
+		if (!chip_dual)
+			goto err_pm_put;
+
+		/* Add dual channel offset */
+		chip_dual->offset = XGPIO_CHANNEL_OFFSET;
+
+		/* Update GPIO state shadow register with default value */
+		of_property_read_u32(np, "xlnx,dout-default-2",
+				     &chip_dual->gpio_state);
+
+		/* By default, all pins are inputs */
+		chip_dual->gpio_dir = 0xFFFFFFFF;
+
+		/* Update GPIO direction shadow register with default value */
+		of_property_read_u32(np, "xlnx,tri-default-2",
+				     &chip_dual->gpio_dir);
+
+		/*
+		 * Check device node and parent device node for device width
+		 * and assume default width of 32
+		 */
+		if (of_property_read_u32(np, "xlnx,gpio2-width", &ngpio))
+			ngpio = 32;
+		chip_dual->mmchip.gc.ngpio = (u16)ngpio;
+
+		spin_lock_init(&chip_dual->gpio_lock);
+
+		chip_dual->mmchip.gc.parent = &pdev->dev;
+		chip_dual->mmchip.gc.owner = THIS_MODULE;
+		chip_dual->mmchip.gc.of_xlate = xgpio_xlate;
+		chip_dual->mmchip.gc.of_gpio_n_cells = cells;
+		chip_dual->mmchip.gc.direction_input = xgpio_dir_in;
+		chip_dual->mmchip.gc.direction_output = xgpio_dir_out;
+		chip_dual->mmchip.gc.get = xgpio_get;
+		chip_dual->mmchip.gc.set = xgpio_set;
+		chip_dual->mmchip.gc.request = xgpio_request;
+		chip_dual->mmchip.gc.free = xgpio_free;
+		chip_dual->mmchip.gc.set_multiple = xgpio_set_multiple;
+
+		chip_dual->mmchip.save_regs = xgpio_save_regs;
+
+		chip->mmchip_dual = &chip_dual->mmchip;
+
+		status = xgpio_irq_setup(np, chip_dual);
+		if (status) {
+			pr_err("%s: GPIO IRQ initialization failed %d\n",
+			      np->full_name, status);
+			goto err_pm_put;
+		}
+
+		/* Call the OF gpio helper to setup and register the GPIO dev */
+		status = of_mm_gpiochip_add(np, &chip_dual->mmchip);
+		if (status) {
+			pr_err("%s: error in probe function with status %d\n",
+			       np->full_name, status);
+			goto err_pm_put;
+		}
+		pr_info("XGpio: %s: dual channel registered, base is %d\n",
+			np->full_name, chip_dual->mmchip.gc.base);
 	}
 
+	pm_runtime_put(&pdev->dev);
 	return 0;
+
+err_pm_put:
+	pm_runtime_put(&pdev->dev);
+err_unprepare_clk:
+	pm_runtime_disable(&pdev->dev);
+	clk_disable_unprepare(chip->clk);
+	return status;
 }
 
 static const struct of_device_id xgpio_of_match[] = {
 	{ .compatible = "xlnx,xps-gpio-1.00.a", },
 	{ /* end of list */ },
 };
-
 MODULE_DEVICE_TABLE(of, xgpio_of_match);
 
-static struct platform_driver xgpio_plat_driver = {
-	.probe		= xgpio_probe,
-	.driver		= {
-			.name = "gpio-xilinx",
-			.of_match_table	= xgpio_of_match,
+static struct platform_driver xilinx_gpio_driver = {
+	.probe = xgpio_of_probe,
+	.remove = xgpio_remove,
+	.driver = {
+		.name = "xilinx-gpio",
+		.of_match_table = xgpio_of_match,
+		.pm = &xgpio_dev_pm_ops,
 	},
 };
 
-static int __init xgpio_init(void)
-{
-	return platform_driver_register(&xgpio_plat_driver);
-}
-
-subsys_initcall(xgpio_init);
-
-static void __exit xgpio_exit(void)
-{
-	platform_driver_unregister(&xgpio_plat_driver);
-}
-module_exit(xgpio_exit);
+module_platform_driver(xilinx_gpio_driver);
 
 MODULE_AUTHOR("Xilinx, Inc.");
 MODULE_DESCRIPTION("Xilinx GPIO driver");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-xtensa.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-xtensa.c
@@ -44,15 +44,14 @@
 	unsigned long flags;
 
 	local_irq_save(flags);
-	RSR_CPENABLE(*cpenable);
-	WSR_CPENABLE(*cpenable | BIT(XCHAL_CP_ID_XTIOP));
-
+	*cpenable = xtensa_get_sr(cpenable);
+	xtensa_set_sr(*cpenable | BIT(XCHAL_CP_ID_XTIOP), cpenable);
 	return flags;
 }
 
 static inline void disable_cp(unsigned long flags, unsigned long cpenable)
 {
-	WSR_CPENABLE(cpenable);
+	xtensa_set_sr(cpenable, cpenable);
 	local_irq_restore(flags);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpio-zynq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpio-zynq.c
@@ -10,6 +10,7 @@
 #include <linux/gpio/driver.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/spinlock.h>
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -21,6 +22,9 @@
 /* Maximum banks */
 #define ZYNQ_GPIO_MAX_BANK	4
 #define ZYNQMP_GPIO_MAX_BANK	6
+#define VERSAL_GPIO_MAX_BANK	4
+#define PMC_GPIO_MAX_BANK	5
+#define VERSAL_UNUSED_BANKS	2
 
 #define ZYNQ_GPIO_BANK0_NGPIO	32
 #define ZYNQ_GPIO_BANK1_NGPIO	22
@@ -95,6 +99,7 @@
 /* set to differentiate zynq from zynqmp, 0=zynqmp, 1=zynq */
 #define ZYNQ_GPIO_QUIRK_IS_ZYNQ	BIT(0)
 #define GPIO_QUIRK_DATA_RO_BUG	BIT(1)
+#define GPIO_QUIRK_VERSAL	BIT(2)
 
 struct gpio_regs {
 	u32 datamsw[ZYNQMP_GPIO_MAX_BANK];
@@ -116,6 +121,7 @@
  * @irq:	interrupt for the GPIO device
  * @p_data:	pointer to platform data
  * @context:	context registers
+ * @dirlock:	lock used for direction in/out synchronization
  */
 struct zynq_gpio {
 	struct gpio_chip chip;
@@ -124,6 +130,7 @@
 	int irq;
 	const struct zynq_platform_data *p_data;
 	struct gpio_regs context;
+	spinlock_t dirlock; /*lock used for direction in/out synchronization */
 };
 
 /**
@@ -196,6 +203,8 @@
 					gpio->p_data->bank_min[bank];
 			return;
 		}
+		if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL)
+			bank = bank + VERSAL_UNUSED_BANKS;
 	}
 
 	/* default */
@@ -297,6 +306,7 @@
 {
 	u32 reg;
 	unsigned int bank_num, bank_pin_num;
+	unsigned long flags;
 	struct zynq_gpio *gpio = gpiochip_get_data(chip);
 
 	zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio);
@@ -310,9 +320,11 @@
 		return -EINVAL;
 
 	/* clear the bit in direction mode reg to set the pin as input */
+	spin_lock_irqsave(&gpio->dirlock, flags);
 	reg = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
 	reg &= ~BIT(bank_pin_num);
 	writel_relaxed(reg, gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
+	spin_unlock_irqrestore(&gpio->dirlock, flags);
 
 	return 0;
 }
@@ -334,11 +346,13 @@
 {
 	u32 reg;
 	unsigned int bank_num, bank_pin_num;
+	unsigned long flags;
 	struct zynq_gpio *gpio = gpiochip_get_data(chip);
 
 	zynq_gpio_get_bank_pin(pin, &bank_num, &bank_pin_num, gpio);
 
 	/* set the GPIO pin as output */
+	spin_lock_irqsave(&gpio->dirlock, flags);
 	reg = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
 	reg |= BIT(bank_pin_num);
 	writel_relaxed(reg, gpio->base_addr + ZYNQ_GPIO_DIRM_OFFSET(bank_num));
@@ -347,6 +361,7 @@
 	reg = readl_relaxed(gpio->base_addr + ZYNQ_GPIO_OUTEN_OFFSET(bank_num));
 	reg |= BIT(bank_pin_num);
 	writel_relaxed(reg, gpio->base_addr + ZYNQ_GPIO_OUTEN_OFFSET(bank_num));
+	spin_unlock_irqrestore(&gpio->dirlock, flags);
 
 	/* set the state of the pin */
 	zynq_gpio_set_value(chip, pin, state);
@@ -556,7 +571,7 @@
 	struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
 	int ret;
 
-	ret = pm_runtime_get_sync(chip->parent);
+	ret = pm_runtime_resume_and_get(chip->parent);
 	if (ret < 0)
 		return ret;
 
@@ -644,6 +659,8 @@
 		int_enb = readl_relaxed(gpio->base_addr +
 					ZYNQ_GPIO_INTMASK_OFFSET(bank_num));
 		zynq_gpio_handle_bank_irq(gpio, bank_num, int_sts & ~int_enb);
+		if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL)
+			bank_num = bank_num + VERSAL_UNUSED_BANKS;
 	}
 
 	chained_irq_exit(irqchip, desc);
@@ -673,6 +690,8 @@
 		gpio->context.int_any[bank_num] =
 				readl_relaxed(gpio->base_addr +
 				ZYNQ_GPIO_INTANY_OFFSET(bank_num));
+		if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL)
+			bank_num = bank_num + VERSAL_UNUSED_BANKS;
 	}
 }
 
@@ -681,6 +700,8 @@
 	unsigned int bank_num;
 
 	for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++) {
+		writel_relaxed(ZYNQ_GPIO_IXR_DISABLE_ALL, gpio->base_addr +
+				ZYNQ_GPIO_INTDIS_OFFSET(bank_num));
 		writel_relaxed(gpio->context.datalsw[bank_num],
 			       gpio->base_addr +
 			       ZYNQ_GPIO_DATA_LSW_OFFSET(bank_num));
@@ -690,9 +711,6 @@
 		writel_relaxed(gpio->context.dirm[bank_num],
 			       gpio->base_addr +
 			       ZYNQ_GPIO_DIRM_OFFSET(bank_num));
-		writel_relaxed(gpio->context.int_en[bank_num],
-			       gpio->base_addr +
-			       ZYNQ_GPIO_INTEN_OFFSET(bank_num));
 		writel_relaxed(gpio->context.int_type[bank_num],
 			       gpio->base_addr +
 			       ZYNQ_GPIO_INTTYPE_OFFSET(bank_num));
@@ -702,6 +720,11 @@
 		writel_relaxed(gpio->context.int_any[bank_num],
 			       gpio->base_addr +
 			       ZYNQ_GPIO_INTANY_OFFSET(bank_num));
+		writel_relaxed(~(gpio->context.int_en[bank_num]),
+			       gpio->base_addr +
+			       ZYNQ_GPIO_INTEN_OFFSET(bank_num));
+		if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL)
+			bank_num = bank_num + VERSAL_UNUSED_BANKS;
 	}
 }
 
@@ -710,6 +733,14 @@
 	struct zynq_gpio *gpio = dev_get_drvdata(dev);
 	struct irq_data *data = irq_get_irq_data(gpio->irq);
 
+	if (!data) {
+		dev_err(dev, "irq_get_irq_data() failed\n");
+		return -EINVAL;
+	}
+
+	if (!device_may_wakeup(dev))
+		disable_irq(gpio->irq);
+
 	if (!irqd_is_wakeup_set(data)) {
 		zynq_gpio_save_context(gpio);
 		return pm_runtime_force_suspend(dev);
@@ -724,6 +755,14 @@
 	struct irq_data *data = irq_get_irq_data(gpio->irq);
 	int ret;
 
+	if (!data) {
+		dev_err(dev, "irq_get_irq_data() failed\n");
+		return -EINVAL;
+	}
+
+	if (!device_may_wakeup(dev))
+		enable_irq(gpio->irq);
+
 	if (!irqd_is_wakeup_set(data)) {
 		ret = pm_runtime_force_resume(dev);
 		zynq_gpio_restore_context(gpio);
@@ -773,6 +812,31 @@
 			   zynq_gpio_runtime_resume, NULL)
 };
 
+static const struct zynq_platform_data versal_gpio_def = {
+	.label = "versal_gpio",
+	.quirks = GPIO_QUIRK_VERSAL,
+	.ngpio = 58,
+	.max_bank = VERSAL_GPIO_MAX_BANK,
+	.bank_min[0] = 0,
+	.bank_max[0] = 25, /* 0 to 25 are connected to MIOs (26 pins) */
+	.bank_min[3] = 26,
+	.bank_max[3] = 57, /* Bank 3 is connected to FMIOs (32 pins) */
+};
+
+static const struct zynq_platform_data pmc_gpio_def = {
+	.label = "pmc_gpio",
+	.ngpio = 116,
+	.max_bank = PMC_GPIO_MAX_BANK,
+	.bank_min[0] = 0,
+	.bank_max[0] = 25, /* 0 to 25 are connected to MIOs (26 pins) */
+	.bank_min[1] = 26,
+	.bank_max[1] = 51, /* Bank 1 are connected to MIOs (26 pins) */
+	.bank_min[3] = 52,
+	.bank_max[3] = 83, /* Bank 3 is connected to EMIOs (32 pins) */
+	.bank_min[4] = 84,
+	.bank_max[4] = 115, /* Bank 4 is connected to EMIOs (32 pins) */
+};
+
 static const struct zynq_platform_data zynqmp_gpio_def = {
 	.label = "zynqmp_gpio",
 	.quirks = GPIO_QUIRK_DATA_RO_BUG,
@@ -810,6 +874,8 @@
 static const struct of_device_id zynq_gpio_of_match[] = {
 	{ .compatible = "xlnx,zynq-gpio-1.0", .data = &zynq_gpio_def },
 	{ .compatible = "xlnx,zynqmp-gpio-1.0", .data = &zynqmp_gpio_def },
+	{ .compatible = "xlnx,versal-gpio-1.0", .data = &versal_gpio_def },
+	{ .compatible = "xlnx,pmc-gpio-1.0", .data = &pmc_gpio_def },
 	{ /* end of table */ }
 };
 MODULE_DEVICE_TABLE(of, zynq_gpio_of_match);
@@ -871,7 +937,8 @@
 	/* Retrieve GPIO clock */
 	gpio->clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(gpio->clk)) {
-		dev_err(&pdev->dev, "input clock not found.\n");
+		if (PTR_ERR(gpio->clk) != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "input clock not found.\n");
 		return PTR_ERR(gpio->clk);
 	}
 	ret = clk_prepare_enable(gpio->clk);
@@ -880,16 +947,21 @@
 		return ret;
 	}
 
+	spin_lock_init(&gpio->dirlock);
+
 	pm_runtime_set_active(&pdev->dev);
 	pm_runtime_enable(&pdev->dev);
-	ret = pm_runtime_get_sync(&pdev->dev);
+	ret = pm_runtime_resume_and_get(&pdev->dev);
 	if (ret < 0)
 		goto err_pm_dis;
 
 	/* disable interrupts for all banks */
-	for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++)
+	for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++) {
 		writel_relaxed(ZYNQ_GPIO_IXR_DISABLE_ALL, gpio->base_addr +
 			       ZYNQ_GPIO_INTDIS_OFFSET(bank_num));
+		if (gpio->p_data->quirks & GPIO_QUIRK_VERSAL)
+			bank_num = bank_num + VERSAL_UNUSED_BANKS;
+	}
 
 	/* Set up the GPIO irqchip */
 	girq = &chip->irq;
@@ -914,6 +986,8 @@
 		goto err_pm_put;
 	}
 
+	irq_set_status_flags(gpio->irq, IRQ_DISABLE_UNLAZY);
+	device_init_wakeup(&pdev->dev, 1);
 	pm_runtime_put(&pdev->dev);
 
 	return 0;
@@ -936,8 +1010,11 @@
 static int zynq_gpio_remove(struct platform_device *pdev)
 {
 	struct zynq_gpio *gpio = platform_get_drvdata(pdev);
+	int ret;
 
-	pm_runtime_get_sync(&pdev->dev);
+	ret = pm_runtime_get_sync(&pdev->dev);
+	if (ret < 0)
+		dev_warn(&pdev->dev, "pm_runtime_get_sync() Failed\n");
 	gpiochip_remove(&gpio->chip);
 	clk_disable_unprepare(gpio->clk);
 	device_set_wakeup_capable(&pdev->dev, 0);
@@ -955,22 +1032,7 @@
 	.remove = zynq_gpio_remove,
 };
 
-/**
- * zynq_gpio_init - Initial driver registration call
- *
- * Return: value from platform_driver_register
- */
-static int __init zynq_gpio_init(void)
-{
-	return platform_driver_register(&zynq_gpio_driver);
-}
-postcore_initcall(zynq_gpio_init);
-
-static void __exit zynq_gpio_exit(void)
-{
-	platform_driver_unregister(&zynq_gpio_driver);
-}
-module_exit(zynq_gpio_exit);
+module_platform_driver(zynq_gpio_driver);
 
 MODULE_AUTHOR("Xilinx Inc.");
 MODULE_DESCRIPTION("Zynq GPIO driver");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpiolib-acpi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpiolib-acpi.c
@@ -26,6 +26,17 @@
 MODULE_PARM_DESC(run_edge_events_on_boot,
 		 "Run edge _AEI event-handlers at boot: 0=no, 1=yes, -1=auto");
 
+static char *ignore_wake;
+module_param(ignore_wake, charp, 0444);
+MODULE_PARM_DESC(ignore_wake,
+		 "controller@pin combos on which to ignore the ACPI wake flag "
+		 "ignore_wake=controller@pin[,controller@pin[,...]]");
+
+struct acpi_gpiolib_dmi_quirk {
+	bool no_edge_events_on_boot;
+	char *ignore_wake;
+};
+
 /**
  * struct acpi_gpio_event - ACPI GPIO event handler data
  *
@@ -163,7 +174,7 @@
 	int ret, value;
 
 	ret = request_threaded_irq(event->irq, NULL, event->handler,
-				   event->irqflags, "ACPI:Event", event);
+				   event->irqflags | IRQF_ONESHOT, "ACPI:Event", event);
 	if (ret) {
 		dev_err(acpi_gpio->chip->parent,
 			"Failed to setup interrupt handler for %d\n",
@@ -194,6 +205,57 @@
 		acpi_gpiochip_request_irq(acpi_gpio, event);
 }
 
+static bool acpi_gpio_in_ignore_list(const char *controller_in, int pin_in)
+{
+	const char *controller, *pin_str;
+	int len, pin;
+	char *endp;
+
+	controller = ignore_wake;
+	while (controller) {
+		pin_str = strchr(controller, '@');
+		if (!pin_str)
+			goto err;
+
+		len = pin_str - controller;
+		if (len == strlen(controller_in) &&
+		    strncmp(controller, controller_in, len) == 0) {
+			pin = simple_strtoul(pin_str + 1, &endp, 10);
+			if (*endp != 0 && *endp != ',')
+				goto err;
+
+			if (pin == pin_in)
+				return true;
+		}
+
+		controller = strchr(controller, ',');
+		if (controller)
+			controller++;
+	}
+
+	return false;
+err:
+	pr_err_once("Error invalid value for gpiolib_acpi.ignore_wake: %s\n",
+		    ignore_wake);
+	return false;
+}
+
+static bool acpi_gpio_irq_is_wake(struct device *parent,
+				  struct acpi_resource_gpio *agpio)
+{
+	int pin = agpio->pin_table[0];
+
+	if (agpio->wake_capable != ACPI_WAKE_CAPABLE)
+		return false;
+
+	if (acpi_gpio_in_ignore_list(dev_name(parent), pin)) {
+		dev_info(parent, "Ignoring wakeup on pin %d\n", pin);
+		return false;
+	}
+
+	return true;
+}
+
 static acpi_status acpi_gpiochip_alloc_event(struct acpi_resource *ares,
 					     void *context)
 {
@@ -213,8 +275,8 @@
 	pin = agpio->pin_table[0];
 
 	if (pin <= 255) {
-		char ev_name[5];
-		sprintf(ev_name, "_%c%02hhX",
+		char ev_name[8];
+		sprintf(ev_name, "_%c%02X",
 			agpio->triggering == ACPI_EDGE_SENSITIVE ? 'E' : 'L',
 			pin);
 		if (ACPI_SUCCESS(acpi_get_handle(handle, ev_name, &evt_handle)))
@@ -274,7 +336,7 @@
 	event->handle = evt_handle;
 	event->handler = handler;
 	event->irq = irq;
-	event->irq_is_wake = agpio->wake_capable == ACPI_WAKE_CAPABLE;
+	event->irq_is_wake = acpi_gpio_irq_is_wake(chip->parent, agpio);
 	event->pin = pin;
 	event->desc = desc;
 
@@ -891,10 +953,17 @@
 			irq_flags = acpi_dev_get_irq_type(info.triggering,
 							  info.polarity);
 
-			/* Set type if specified and different than the current one */
-			if (irq_flags != IRQ_TYPE_NONE &&
-			    irq_flags != irq_get_trigger_type(irq))
-				irq_set_irq_type(irq, irq_flags);
+			/*
+			 * If the IRQ is not already in use then set type
+			 * if specified and different than the current one.
+			 */
+			if (can_request_irq(irq, irq_flags)) {
+				if (irq_flags != IRQ_TYPE_NONE &&
+				    irq_flags != irq_get_trigger_type(irq))
+					irq_set_irq_type(irq, irq_flags);
+			} else {
+				dev_dbg(&adev->dev, "IRQ %d already in use\n", irq);
+			}
 
 			return irq;
 		}
@@ -1302,7 +1371,7 @@
 /* We must use _sync so that this runs after the first deferred_probe run */
 late_initcall_sync(acpi_gpio_handle_deferred_request_irqs);
 
-static const struct dmi_system_id run_edge_events_on_boot_blacklist[] = {
+static const struct dmi_system_id gpiolib_acpi_quirks[] = {
 	{
 		/*
 		 * The Minix Neo Z83-4 has a micro-USB-B id-pin handler for
@@ -1312,7 +1381,10 @@
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "MINIX"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "Z83-4"),
-		}
+		},
+		.driver_data = &(struct acpi_gpiolib_dmi_quirk) {
+			.no_edge_events_on_boot = true,
+		},
 	},
 	{
 		/*
@@ -1324,20 +1396,112 @@
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Wortmann_AG"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "TERRA_PAD_1061"),
-		}
+		},
+		.driver_data = &(struct acpi_gpiolib_dmi_quirk) {
+			.no_edge_events_on_boot = true,
+		},
+	},
+	{
+		/*
+		 * The Dell Venue 10 Pro 5055, with Bay Trail SoC + TI PMIC uses an
+		 * external embedded-controller connected via I2C + an ACPI GPIO
+		 * event handler on INT33FFC:02 pin 12, causing spurious wakeups.
+		 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Venue 10 Pro 5055"),
+		},
+		.driver_data = &(struct acpi_gpiolib_dmi_quirk) {
+			.ignore_wake = "INT33FC:02@12",
+		},
+	},
+	{
+		/*
+		 * HP X2 10 models with Cherry Trail SoC + TI PMIC use an
+		 * external embedded-controller connected via I2C + an ACPI GPIO
+		 * event handler on INT33FF:01 pin 0, causing spurious wakeups.
+		 * When suspending by closing the LID, the power to the USB
+		 * keyboard is turned off, causing INT0002 ACPI events to
+		 * trigger once the XHCI controller notices the keyboard is
+		 * gone. So INT0002 events cause spurious wakeups too. Ignoring
+		 * EC wakes breaks wakeup when opening the lid, the user needs
+		 * to press the power-button to wakeup the system. The
+		 * alternative is suspend simply not working, which is worse.
+		 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP x2 Detachable 10-p0XX"),
+		},
+		.driver_data = &(struct acpi_gpiolib_dmi_quirk) {
+			.ignore_wake = "INT33FF:01@0,INT0002:00@2",
+		},
+	},
+	{
+		/*
+		 * HP X2 10 models with Bay Trail SoC + AXP288 PMIC use an
+		 * external embedded-controller connected via I2C + an ACPI GPIO
+		 * event handler on INT33FC:02 pin 28, causing spurious wakeups.
+		 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"),
+			DMI_MATCH(DMI_BOARD_NAME, "815D"),
+		},
+		.driver_data = &(struct acpi_gpiolib_dmi_quirk) {
+			.ignore_wake = "INT33FC:02@28",
+		},
+	},
+	{
+		/*
+		 * HP X2 10 models with Cherry Trail SoC + AXP288 PMIC use an
+		 * external embedded-controller connected via I2C + an ACPI GPIO
+		 * event handler on INT33FF:01 pin 0, causing spurious wakeups.
+		 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"),
+			DMI_MATCH(DMI_BOARD_NAME, "813E"),
+		},
+		.driver_data = &(struct acpi_gpiolib_dmi_quirk) {
+			.ignore_wake = "INT33FF:01@0",
+		},
+	},
+	{
+		/*
+		 * Spurious wakeups from TP_ATTN# pin
+		 * Found in BIOS 0.35
+		 * https://gitlab.freedesktop.org/drm/amd/-/issues/3073
+		 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "GPD"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "G1619-04"),
+		},
+		.driver_data = &(struct acpi_gpiolib_dmi_quirk) {
+			.ignore_wake = "PNP0C50:00@8",
+		},
 	},
 	{} /* Terminating entry */
 };
 
 static int acpi_gpio_setup_params(void)
 {
+	const struct acpi_gpiolib_dmi_quirk *quirk = NULL;
+	const struct dmi_system_id *id;
+
+	id = dmi_first_match(gpiolib_acpi_quirks);
+	if (id)
+		quirk = id->driver_data;
+
 	if (run_edge_events_on_boot < 0) {
-		if (dmi_check_system(run_edge_events_on_boot_blacklist))
+		if (quirk && quirk->no_edge_events_on_boot)
 			run_edge_events_on_boot = 0;
 		else
 			run_edge_events_on_boot = 1;
 	}
 
+	if (ignore_wake == NULL && quirk && quirk->ignore_wake)
+		ignore_wake = quirk->ignore_wake;
+
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpiolib-of.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpiolib-of.c
@@ -23,6 +23,29 @@
 #include "gpiolib.h"
 #include "gpiolib-of.h"
 
+/**
+ * of_gpio_spi_cs_get_count() - special GPIO counting for SPI
+ * Some elder GPIO controllers need special quirks. Currently we handle
+ * the Freescale GPIO controller with bindings that doesn't use the
+ * established "cs-gpios" for chip selects but instead rely on
+ * "gpios" for the chip select lines. If we detect this, we redirect
+ * the counting of "cs-gpios" to count "gpios" transparent to the
+ * driver.
+ */
+int of_gpio_spi_cs_get_count(struct device *dev, const char *con_id)
+{
+	struct device_node *np = dev->of_node;
+
+	if (!IS_ENABLED(CONFIG_SPI_MASTER))
+		return 0;
+	if (!con_id || strcmp(con_id, "cs"))
+		return 0;
+	if (!of_device_is_compatible(np, "fsl,spi") &&
+	    !of_device_is_compatible(np, "aeroflexgaisler,spictrl"))
+		return 0;
+	return of_gpio_named_count(np, "gpios");
+}
+
 /*
  * This is used by external users of of_gpio_count() from <linux/of_gpio.h>
  *
@@ -35,6 +58,10 @@
 	char propname[32];
 	unsigned int i;
 
+	ret = of_gpio_spi_cs_get_count(dev, con_id);
+	if (ret > 0)
+		return ret;
+
 	for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) {
 		if (con_id)
 			snprintf(propname, sizeof(propname), "%s-%s",
@@ -119,10 +146,6 @@
 			if (of_property_read_bool(np, "cd-inverted"))
 				*flags ^= OF_GPIO_ACTIVE_LOW;
 		}
-		if (!strcmp(propname, "wp-gpios")) {
-			if (of_property_read_bool(np, "wp-inverted"))
-				*flags ^= OF_GPIO_ACTIVE_LOW;
-		}
 	}
 	/*
 	 * Some GPIO fixed regulator quirks.
@@ -711,7 +734,8 @@
 	if (mm_gc->save_regs)
 		mm_gc->save_regs(mm_gc);
 
-	mm_gc->gc.of_node = np;
+	of_node_put(mm_gc->gc.of_node);
+	mm_gc->gc.of_node = of_node_get(np);
 
 	ret = gpiochip_add_data(gc, data);
 	if (ret)
@@ -719,6 +743,7 @@
 
 	return 0;
 err2:
+	of_node_put(np);
 	iounmap(mm_gc->regs);
 err1:
 	kfree(gc->label);
@@ -760,7 +785,7 @@
 					   i, &start);
 		of_property_read_u32_index(np, "gpio-reserved-ranges",
 					   i + 1, &count);
-		if (start >= chip->ngpio || start + count >= chip->ngpio)
+		if (start >= chip->ngpio || start + count > chip->ngpio)
 			continue;
 
 		bitmap_clear(chip->valid_mask, start, count);
@@ -882,16 +907,13 @@
 	of_node_get(chip->of_node);
 
 	ret = of_gpiochip_scan_gpios(chip);
-	if (ret) {
+	if (ret)
 		of_node_put(chip->of_node);
-		gpiochip_remove_pin_ranges(chip);
-	}
 
 	return ret;
 }
 
 void of_gpiochip_remove(struct gpio_chip *chip)
 {
-	gpiochip_remove_pin_ranges(chip);
 	of_node_put(chip->of_node);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpiolib-sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpiolib-sysfs.c
@@ -457,6 +457,8 @@
 	long			gpio;
 	struct gpio_desc	*desc;
 	int			status;
+	struct gpio_chip	*gc;
+	int			offset;
 
 	status = kstrtol(buf, 0, &gpio);
 	if (status < 0)
@@ -468,6 +470,12 @@
 		pr_warn("%s: invalid GPIO %ld\n", __func__, gpio);
 		return -EINVAL;
 	}
+	gc = desc->gdev->chip;
+	offset = gpio_chip_hwgpio(desc);
+	if (!gpiochip_line_is_valid(gc, offset)) {
+		pr_warn("%s: GPIO %ld masked\n", __func__, gpio);
+		return -EINVAL;
+	}
 
 	/* No extra locking here; FLAG_SYSFS just signifies that the
 	 * request and export were done by on behalf of userspace, so
@@ -482,14 +490,17 @@
 	}
 
 	status = gpiod_set_transitory(desc, false);
-	if (!status) {
-		status = gpiod_export(desc, true);
-		if (status < 0)
-			gpiod_free(desc);
-		else
-			set_bit(FLAG_SYSFS, &desc->flags);
+	if (status) {
+		gpiod_free(desc);
+		goto done;
 	}
 
+	status = gpiod_export(desc, true);
+	if (status < 0)
+		gpiod_free(desc);
+	else
+		set_bit(FLAG_SYSFS, &desc->flags);
+
 done:
 	if (status)
 		pr_debug("%s: status %d\n", __func__, status);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/gpiolib.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/gpiolib.c
@@ -4,6 +4,7 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/nospec.h>
 #include <linux/spinlock.h>
 #include <linux/list.h>
 #include <linux/device.h>
@@ -147,7 +148,7 @@
 	if (hwnum >= gdev->ngpio)
 		return ERR_PTR(-EINVAL);
 
-	return &gdev->descs[hwnum];
+	return &gdev->descs[array_index_nospec(hwnum, gdev->ngpio)];
 }
 
 /**
@@ -220,6 +221,14 @@
 	chip = gpiod_to_chip(desc);
 	offset = gpio_chip_hwgpio(desc);
 
+	/*
+	 * Open drain emulation using input mode may incorrectly report
+	 * input here, fix that up.
+	 */
+	if (test_bit(FLAG_OPEN_DRAIN, &desc->flags) &&
+	    test_bit(FLAG_IS_OUT, &desc->flags))
+		return 0;
+
 	if (!chip->get_direction)
 		return -ENOTSUPP;
 
@@ -1444,6 +1453,7 @@
 	gpiochip_free_hogs(chip);
 	of_gpiochip_remove(chip);
 err_free_gpiochip_mask:
+	gpiochip_remove_pin_ranges(chip);
 	gpiochip_free_valid_mask(chip);
 err_remove_from_list:
 	spin_lock_irqsave(&gpio_lock, flags);
@@ -1499,8 +1509,8 @@
 	gdev->chip = NULL;
 	gpiochip_irqchip_remove(chip);
 	acpi_gpiochip_remove(chip);
-	gpiochip_remove_pin_ranges(chip);
 	of_gpiochip_remove(chip);
+	gpiochip_remove_pin_ranges(chip);
 	gpiochip_free_valid_mask(chip);
 	/*
 	 * We accept no more calls into the driver from this point, so
@@ -1915,6 +1925,7 @@
 				     parent_type);
 	chip_info(gc, "alloc_irqs_parent for %d parent hwirq %d\n",
 		  irq, parent_hwirq);
+	irq_set_lockdep_class(irq, gc->irq.lock_key, gc->irq.request_key);
 	ret = irq_domain_alloc_irqs_parent(d, irq, 1, &parent_fwspec);
 	if (ret)
 		chip_err(gc,
@@ -2136,6 +2147,16 @@
 {
 	struct irq_domain *domain = chip->irq.domain;
 
+#ifdef CONFIG_GPIOLIB_IRQCHIP
+	/*
+	 * Avoid race condition with other code, which tries to lookup
+	 * an IRQ before the irqchip has been properly registered,
+	 * i.e. while gpiochip is still being brought up.
+	 */
+	if (!chip->irq.initialized)
+		return -EPROBE_DEFER;
+#endif
+
 	if (!gpiochip_irqchip_irq_valid(chip, offset))
 		return -ENXIO;
 
@@ -2184,9 +2205,16 @@
 {
 	struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
 
+	/*
+	 * Since we override .irq_disable() we need to mimic the
+	 * behaviour of __irq_disable() in irq/chip.c.
+	 * First call .irq_disable() if it exists, else mimic the
+	 * behaviour of mask_irq() which calls .irq_mask() if
+	 * it exists.
+	 */
 	if (chip->irq.irq_disable)
 		chip->irq.irq_disable(d);
-	else
+	else if (chip->irq.chip->irq_mask)
 		chip->irq.chip->irq_mask(d);
 	gpiochip_disable_irq(chip, d->hwirq);
 }
@@ -2302,6 +2330,15 @@
 
 	gpiochip_set_irq_hooks(gpiochip);
 
+	/*
+	 * Using barrier() here to prevent compiler from reordering
+	 * gc->irq.initialized before initialization of above
+	 * GPIO chip irq members.
+	 */
+	barrier();
+
+	gpiochip->irq.initialized = true;
+
 	acpi_gpiochip_request_interrupts(gpiochip);
 
 	return 0;
@@ -3211,6 +3248,17 @@
 }
 EXPORT_SYMBOL_GPL(gpiod_is_active_low);
 
+/**
+ * gpiod_toggle_active_low - toggle whether a GPIO is active-low or not
+ * @desc: the gpio descriptor to change
+ */
+void gpiod_toggle_active_low(struct gpio_desc *desc)
+{
+	VALIDATE_DESC_VOID(desc);
+	change_bit(FLAG_ACTIVE_LOW, &desc->flags);
+}
+EXPORT_SYMBOL_GPL(gpiod_toggle_active_low);
+
 /* I/O calls are only valid after configuration completed; the relevant
  * "is this a valid GPIO" error checks should already have been done.
  *
@@ -3866,7 +3914,9 @@
 		}
 	}
 
-	if (test_bit(FLAG_IS_OUT, &desc->flags)) {
+	/* To be valid for IRQ the line needs to be input or open drain */
+	if (test_bit(FLAG_IS_OUT, &desc->flags) &&
+	    !test_bit(FLAG_OPEN_DRAIN, &desc->flags)) {
 		chip_err(chip,
 			 "%s: tried to flag a GPIO set as output for IRQ\n",
 			 __func__);
@@ -3929,7 +3979,12 @@
 
 	if (!IS_ERR(desc) &&
 	    !WARN_ON(!test_bit(FLAG_USED_AS_IRQ, &desc->flags))) {
-		WARN_ON(test_bit(FLAG_IS_OUT, &desc->flags));
+		/*
+		 * We must not be output when using IRQ UNLESS we are
+		 * open drain.
+		 */
+		WARN_ON(test_bit(FLAG_IS_OUT, &desc->flags) &&
+			!test_bit(FLAG_OPEN_DRAIN, &desc->flags));
 		set_bit(FLAG_IRQ_IS_ENABLED, &desc->flags);
 	}
 }
@@ -4320,8 +4375,9 @@
 
 		if (chip->ngpio <= p->chip_hwnum) {
 			dev_err(dev,
-				"requested GPIO %d is out of range [0..%d] for chip %s\n",
-				idx, chip->ngpio, chip->label);
+				"requested GPIO %u (%u) is out of range [0..%u] for chip %s\n",
+				idx, p->chip_hwnum, chip->ngpio - 1,
+				chip->label);
 			return ERR_PTR(-EINVAL);
 		}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpio/sgpio-aspeed.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpio/sgpio-aspeed.c
@@ -17,7 +17,17 @@
 #include <linux/spinlock.h>
 #include <linux/string.h>
 
-#define MAX_NR_SGPIO			80
+/*
+ * MAX_NR_HW_GPIO represents the number of actual hardware-supported GPIOs (ie,
+ * slots within the clocked serial GPIO data). Since each HW GPIO is both an
+ * input and an output, we provide MAX_NR_HW_GPIO * 2 lines on our gpiochip
+ * device.
+ *
+ * We use SGPIO_OUTPUT_OFFSET to define the split between the inputs and
+ * outputs; the inputs start at line 0, the outputs start at OUTPUT_OFFSET.
+ */
+#define MAX_NR_HW_SGPIO			80
+#define SGPIO_OUTPUT_OFFSET		MAX_NR_HW_SGPIO
 
 #define ASPEED_SGPIO_CTRL		0x54
 
@@ -30,8 +40,8 @@
 	struct clk *pclk;
 	spinlock_t lock;
 	void __iomem *base;
-	uint32_t dir_in[3];
 	int irq;
+	int n_sgpio;
 };
 
 struct aspeed_sgpio_bank {
@@ -107,35 +117,73 @@
 		return gpio->base + bank->irq_regs + GPIO_IRQ_STATUS;
 	default:
 		/* acturally if code runs to here, it's an error case */
-		BUG_ON(1);
+		BUG();
 	}
 }
 
-#define GPIO_BANK(x)    ((x) >> 5)
-#define GPIO_OFFSET(x)  ((x) & 0x1f)
+#define GPIO_BANK(x)    ((x % SGPIO_OUTPUT_OFFSET) >> 5)
+#define GPIO_OFFSET(x)  ((x % SGPIO_OUTPUT_OFFSET) & 0x1f)
 #define GPIO_BIT(x)     BIT(GPIO_OFFSET(x))
 
 static const struct aspeed_sgpio_bank *to_bank(unsigned int offset)
 {
-	unsigned int bank = GPIO_BANK(offset);
+	unsigned int bank;
+
+	bank = GPIO_BANK(offset);
 
 	WARN_ON(bank >= ARRAY_SIZE(aspeed_sgpio_banks));
 	return &aspeed_sgpio_banks[bank];
 }
 
+static int aspeed_sgpio_init_valid_mask(struct gpio_chip *gc,
+		unsigned long *valid_mask, unsigned int ngpios)
+{
+	struct aspeed_sgpio *sgpio = gpiochip_get_data(gc);
+	int n = sgpio->n_sgpio;
+	int c = SGPIO_OUTPUT_OFFSET - n;
+
+	WARN_ON(ngpios < MAX_NR_HW_SGPIO * 2);
+
+	/* input GPIOs in the lower range */
+	bitmap_set(valid_mask, 0, n);
+	bitmap_clear(valid_mask, n, c);
+
+	/* output GPIOS above SGPIO_OUTPUT_OFFSET */
+	bitmap_set(valid_mask, SGPIO_OUTPUT_OFFSET, n);
+	bitmap_clear(valid_mask, SGPIO_OUTPUT_OFFSET + n, c);
+
+	return 0;
+}
+
+static void aspeed_sgpio_irq_init_valid_mask(struct gpio_chip *gc,
+		unsigned long *valid_mask, unsigned int ngpios)
+{
+	struct aspeed_sgpio *sgpio = gpiochip_get_data(gc);
+	int n = sgpio->n_sgpio;
+
+	WARN_ON(ngpios < MAX_NR_HW_SGPIO * 2);
+
+	/* input GPIOs in the lower range */
+	bitmap_set(valid_mask, 0, n);
+	bitmap_clear(valid_mask, n, ngpios - n);
+}
+
+static bool aspeed_sgpio_is_input(unsigned int offset)
+{
+	return offset < SGPIO_OUTPUT_OFFSET;
+}
+
 static int aspeed_sgpio_get(struct gpio_chip *gc, unsigned int offset)
 {
 	struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
 	const struct aspeed_sgpio_bank *bank = to_bank(offset);
 	unsigned long flags;
 	enum aspeed_sgpio_reg reg;
-	bool is_input;
 	int rc = 0;
 
 	spin_lock_irqsave(&gpio->lock, flags);
 
-	is_input = gpio->dir_in[GPIO_BANK(offset)] & GPIO_BIT(offset);
-	reg = is_input ? reg_val : reg_rdata;
+	reg = aspeed_sgpio_is_input(offset) ? reg_val : reg_rdata;
 	rc = !!(ioread32(bank_reg(gpio, bank, reg)) & GPIO_BIT(offset));
 
 	spin_unlock_irqrestore(&gpio->lock, flags);
@@ -143,22 +191,31 @@
 	return rc;
 }
 
-static void sgpio_set_value(struct gpio_chip *gc, unsigned int offset, int val)
+static int sgpio_set_value(struct gpio_chip *gc, unsigned int offset, int val)
 {
 	struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
 	const struct aspeed_sgpio_bank *bank = to_bank(offset);
-	void __iomem *addr;
+	void __iomem *addr_r, *addr_w;
 	u32 reg = 0;
 
-	addr = bank_reg(gpio, bank, reg_val);
-	reg = ioread32(addr);
+	if (aspeed_sgpio_is_input(offset))
+		return -EINVAL;
+
+	/* Since this is an output, read the cached value from rdata, then
+	 * update val. */
+	addr_r = bank_reg(gpio, bank, reg_rdata);
+	addr_w = bank_reg(gpio, bank, reg_val);
+
+	reg = ioread32(addr_r);
 
 	if (val)
 		reg |= GPIO_BIT(offset);
 	else
 		reg &= ~GPIO_BIT(offset);
 
-	iowrite32(reg, addr);
+	iowrite32(reg, addr_w);
+
+	return 0;
 }
 
 static void aspeed_sgpio_set(struct gpio_chip *gc, unsigned int offset, int val)
@@ -175,43 +232,28 @@
 
 static int aspeed_sgpio_dir_in(struct gpio_chip *gc, unsigned int offset)
 {
-	struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
-	unsigned long flags;
-
-	spin_lock_irqsave(&gpio->lock, flags);
-	gpio->dir_in[GPIO_BANK(offset)] |= GPIO_BIT(offset);
-	spin_unlock_irqrestore(&gpio->lock, flags);
-
-	return 0;
+	return aspeed_sgpio_is_input(offset) ? 0 : -EINVAL;
 }
 
 static int aspeed_sgpio_dir_out(struct gpio_chip *gc, unsigned int offset, int val)
 {
 	struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
 	unsigned long flags;
+	int rc;
 
-	spin_lock_irqsave(&gpio->lock, flags);
-
-	gpio->dir_in[GPIO_BANK(offset)] &= ~GPIO_BIT(offset);
-	sgpio_set_value(gc, offset, val);
+	/* No special action is required for setting the direction; we'll
+	 * error-out in sgpio_set_value if this isn't an output GPIO */
 
+	spin_lock_irqsave(&gpio->lock, flags);
+	rc = sgpio_set_value(gc, offset, val);
 	spin_unlock_irqrestore(&gpio->lock, flags);
 
-	return 0;
+	return rc;
 }
 
 static int aspeed_sgpio_get_direction(struct gpio_chip *gc, unsigned int offset)
 {
-	int dir_status;
-	struct aspeed_sgpio *gpio = gpiochip_get_data(gc);
-	unsigned long flags;
-
-	spin_lock_irqsave(&gpio->lock, flags);
-	dir_status = gpio->dir_in[GPIO_BANK(offset)] & GPIO_BIT(offset);
-	spin_unlock_irqrestore(&gpio->lock, flags);
-
-	return dir_status;
-
+	return !!aspeed_sgpio_is_input(offset);
 }
 
 static void irqd_to_aspeed_sgpio_data(struct irq_data *d,
@@ -402,6 +444,7 @@
 
 	irq = &gpio->chip.irq;
 	irq->chip = &aspeed_sgpio_irqchip;
+	irq->init_valid_mask = aspeed_sgpio_irq_init_valid_mask;
 	irq->handler = handle_bad_irq;
 	irq->default_type = IRQ_TYPE_NONE;
 	irq->parent_handler = aspeed_sgpio_irq_handler;
@@ -409,17 +452,15 @@
 	irq->parents = &gpio->irq;
 	irq->num_parents = 1;
 
-	/* set IRQ settings and Enable Interrupt */
+	/* Apply default IRQ settings */
 	for (i = 0; i < ARRAY_SIZE(aspeed_sgpio_banks); i++) {
 		bank = &aspeed_sgpio_banks[i];
 		/* set falling or level-low irq */
 		iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_type0));
 		/* trigger type is edge */
 		iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_type1));
-		/* dual edge trigger mode. */
-		iowrite32(0xffffffff, bank_reg(gpio, bank, reg_irq_type2));
-		/* enable irq */
-		iowrite32(0xffffffff, bank_reg(gpio, bank, reg_irq_enable));
+		/* single edge trigger */
+		iowrite32(0x00000000, bank_reg(gpio, bank, reg_irq_type2));
 	}
 
 	return 0;
@@ -452,11 +493,12 @@
 	if (rc < 0) {
 		dev_err(&pdev->dev, "Could not read ngpios property\n");
 		return -EINVAL;
-	} else if (nr_gpios > MAX_NR_SGPIO) {
+	} else if (nr_gpios > MAX_NR_HW_SGPIO) {
 		dev_err(&pdev->dev, "Number of GPIOs exceeds the maximum of %d: %d\n",
-			MAX_NR_SGPIO, nr_gpios);
+			MAX_NR_HW_SGPIO, nr_gpios);
 		return -EINVAL;
 	}
+	gpio->n_sgpio = nr_gpios;
 
 	rc = of_property_read_u32(pdev->dev.of_node, "bus-frequency", &sgpio_freq);
 	if (rc < 0) {
@@ -497,7 +539,8 @@
 	spin_lock_init(&gpio->lock);
 
 	gpio->chip.parent = &pdev->dev;
-	gpio->chip.ngpio = nr_gpios;
+	gpio->chip.ngpio = MAX_NR_HW_SGPIO * 2;
+	gpio->chip.init_valid_mask = aspeed_sgpio_init_valid_mask;
 	gpio->chip.direction_input = aspeed_sgpio_dir_in;
 	gpio->chip.direction_output = aspeed_sgpio_dir_out;
 	gpio->chip.get_direction = aspeed_sgpio_get_direction;
@@ -509,9 +552,6 @@
 	gpio->chip.label = dev_name(&pdev->dev);
 	gpio->chip.base = -1;
 
-	/* set all SGPIO pins as input (1). */
-	memset(gpio->dir_in, 0xff, sizeof(gpio->dir_in));
-
 	aspeed_sgpio_setup_irqs(gpio, pdev);
 
 	rc = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/Kconfig
@@ -27,6 +27,7 @@
 config DRM_MIPI_DBI
 	tristate
 	depends on DRM
+	select DRM_KMS_HELPER
 
 config DRM_MIPI_DSI
 	bool
@@ -206,6 +207,7 @@
 config DRM_RADEON
 	tristate "ATI Radeon"
 	depends on DRM && PCI && MMU
+	depends on AGP || !AGP
 	select FW_LOADER
         select DRM_KMS_HELPER
         select DRM_TTM
@@ -318,6 +320,8 @@
 
 source "drivers/gpu/drm/sti/Kconfig"
 
+source "drivers/gpu/drm/zocl/Kconfig"
+
 source "drivers/gpu/drm/imx/Kconfig"
 
 source "drivers/gpu/drm/ingenic/Kconfig"
@@ -344,6 +348,8 @@
 
 source "drivers/gpu/drm/pl111/Kconfig"
 
+source "drivers/gpu/drm/xlnx/Kconfig"
+
 source "drivers/gpu/drm/tve200/Kconfig"
 
 source "drivers/gpu/drm/xen/Kconfig"
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/Makefile
@@ -98,6 +98,7 @@
 obj-$(CONFIG_DRM_TEGRA) += tegra/
 obj-$(CONFIG_DRM_STM) += stm/
 obj-$(CONFIG_DRM_STI) += sti/
+obj-$(CONFIG_DRM_ZOCL)	+= zocl/
 obj-$(CONFIG_DRM_IMX) += imx/
 obj-$(CONFIG_DRM_INGENIC) += ingenic/
 obj-$(CONFIG_DRM_MEDIATEK) += mediatek/
@@ -113,6 +114,7 @@
 obj-$(CONFIG_DRM_MXSFB)	+= mxsfb/
 obj-y			+= tiny/
 obj-$(CONFIG_DRM_PL111) += pl111/
+obj-$(CONFIG_DRM_XLNX)	+= xlnx/
 obj-$(CONFIG_DRM_TVE200) += tve200/
 obj-$(CONFIG_DRM_XEN) += xen/
 obj-$(CONFIG_DRM_VBOXVIDEO) += vboxvideo/
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/ObjectID.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/ObjectID.h
@@ -119,6 +119,7 @@
 #define CONNECTOR_OBJECT_ID_eDP                   0x14
 #define CONNECTOR_OBJECT_ID_MXM                   0x15
 #define CONNECTOR_OBJECT_ID_LVDS_eDP              0x16
+#define CONNECTOR_OBJECT_ID_USBC                  0x17
 
 /* deleted */
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -762,7 +762,7 @@
 	MAX_HWIP
 };
 
-#define HWIP_MAX_INSTANCE	8
+#define HWIP_MAX_INSTANCE	10
 
 struct amd_powerplay {
 	void *pp_handle;
@@ -813,6 +813,7 @@
 	uint8_t				*bios;
 	uint32_t			bios_size;
 	struct amdgpu_bo		*stolen_vga_memory;
+	struct amdgpu_bo		*discovery_memory;
 	uint32_t			bios_scratch_reg_offset;
 	uint32_t			bios_scratch[AMDGPU_BIOS_NUM_SCRATCH];
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c
@@ -163,17 +163,28 @@
 	return 0;
 }
 
-static struct device *get_mfd_cell_dev(const char *device_name, int r)
+static int acp_genpd_add_device(struct device *dev, void *data)
 {
-	char auto_dev_name[25];
-	struct device *dev;
+	struct generic_pm_domain *gpd = data;
+	int ret;
 
-	snprintf(auto_dev_name, sizeof(auto_dev_name),
-		 "%s.%d.auto", device_name, r);
-	dev = bus_find_device_by_name(&platform_bus_type, NULL, auto_dev_name);
-	dev_info(dev, "device %s added to pm domain\n", auto_dev_name);
+	ret = pm_genpd_add_device(gpd, dev);
+	if (ret)
+		dev_err(dev, "Failed to add dev to genpd %d\n", ret);
 
-	return dev;
+	return ret;
+}
+
+static int acp_genpd_remove_device(struct device *dev, void *data)
+{
+	int ret;
+
+	ret = pm_genpd_remove_device(dev);
+	if (ret)
+		dev_err(dev, "Failed to remove dev from genpd %d\n", ret);
+
+	/* Continue to remove */
+	return 0;
 }
 
 /**
@@ -184,11 +195,10 @@
  */
 static int acp_hw_init(void *handle)
 {
-	int r, i;
+	int r;
 	uint64_t acp_base;
 	u32 val = 0;
 	u32 count = 0;
-	struct device *dev;
 	struct i2s_platform_data *i2s_pdata = NULL;
 
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -344,15 +354,10 @@
 	if (r)
 		goto failure;
 
-	for (i = 0; i < ACP_DEVS ; i++) {
-		dev = get_mfd_cell_dev(adev->acp.acp_cell[i].name, i);
-		r = pm_genpd_add_device(&adev->acp.acp_genpd->gpd, dev);
-		if (r) {
-			dev_err(dev, "Failed to add dev to genpd\n");
-			goto failure;
-		}
-	}
-
+	r = device_for_each_child(adev->acp.parent, &adev->acp.acp_genpd->gpd,
+				  acp_genpd_add_device);
+	if (r)
+		goto failure;
 
 	/* Assert Soft reset of ACP */
 	val = cgs_read_register(adev->acp.cgs_device, mmACP_SOFT_RESET);
@@ -413,10 +418,8 @@
  */
 static int acp_hw_fini(void *handle)
 {
-	int i, ret;
 	u32 val = 0;
 	u32 count = 0;
-	struct device *dev;
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
 	/* return early if no ACP */
@@ -461,13 +464,8 @@
 		udelay(100);
 	}
 
-	for (i = 0; i < ACP_DEVS ; i++) {
-		dev = get_mfd_cell_dev(adev->acp.acp_cell[i].name, i);
-		ret = pm_genpd_remove_device(dev);
-		/* If removal fails, dont giveup and try rest */
-		if (ret)
-			dev_err(dev, "remove dev from genpd failed\n");
-	}
+	device_for_each_child(adev->acp.parent, NULL,
+			      acp_genpd_remove_device);
 
 	mfd_remove_devices(adev->acp.parent);
 	kfree(adev->acp.acp_res);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
@@ -85,6 +85,7 @@
 					   struct acpi_buffer *params)
 {
 	acpi_status status;
+	union acpi_object *obj;
 	union acpi_object atif_arg_elements[2];
 	struct acpi_object_list atif_arg;
 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -107,16 +108,24 @@
 
 	status = acpi_evaluate_object(atif->handle, NULL, &atif_arg,
 				      &buffer);
+	obj = (union acpi_object *)buffer.pointer;
 
-	/* Fail only if calling the method fails and ATIF is supported */
-	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+	/* Fail if calling the method fails */
+	if (ACPI_FAILURE(status)) {
 		DRM_DEBUG_DRIVER("failed to evaluate ATIF got %s\n",
 				 acpi_format_exception(status));
-		kfree(buffer.pointer);
+		kfree(obj);
 		return NULL;
 	}
 
-	return buffer.pointer;
+	if (obj->type != ACPI_TYPE_BUFFER) {
+		DRM_DEBUG_DRIVER("bad object returned from ATIF: %d\n",
+				 obj->type);
+		kfree(obj);
+		return NULL;
+	}
+
+	return obj;
 }
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_afmt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_afmt.c
@@ -100,6 +100,7 @@
 	amdgpu_afmt_calc_cts(clock, &res.cts_32khz, &res.n_32khz, 32000);
 	amdgpu_afmt_calc_cts(clock, &res.cts_44_1khz, &res.n_44_1khz, 44100);
 	amdgpu_afmt_calc_cts(clock, &res.cts_48khz, &res.n_48khz, 48000);
+	res.clock = clock;
 
 	return res;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_fence.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_fence.c
@@ -88,7 +88,7 @@
 		return NULL;
 
 	fence = container_of(f, struct amdgpu_amdkfd_fence, base);
-	if (fence && f->ops == &amdkfd_fence_ops)
+	if (f->ops == &amdkfd_fence_ops)
 		return fence;
 
 	return NULL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c
@@ -165,7 +165,7 @@
 	.get_tile_config = amdgpu_amdkfd_get_tile_config,
 };
 
-struct kfd2kgd_calls *amdgpu_amdkfd_gfx_10_0_get_functions()
+struct kfd2kgd_calls *amdgpu_amdkfd_gfx_10_0_get_functions(void)
 {
 	return (struct kfd2kgd_calls *)&kfd2kgd;
 }
@@ -644,6 +644,9 @@
 	uint32_t temp;
 	struct v10_compute_mqd *m = get_mqd(mqd);
 
+	if (amdgpu_sriov_vf(adev) && adev->in_gpu_reset)
+		return 0;
+
 #if 0
 	unsigned long flags;
 	int retry;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c
@@ -540,6 +540,9 @@
 	uint32_t temp;
 	struct v9_mqd *m = get_mqd(mqd);
 
+	if (amdgpu_sriov_vf(adev) && adev->in_gpu_reset)
+		return 0;
+
 	if (adev->in_gpu_reset)
 		return -EIO;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -55,12 +55,6 @@
 	spinlock_t mem_limit_lock;
 } kfd_mem_limit;
 
-/* Struct used for amdgpu_amdkfd_bo_validate */
-struct amdgpu_vm_parser {
-	uint32_t        domain;
-	bool            wait;
-};
-
 static const char * const domain_bit_to_string[] = {
 		"CPU",
 		"GTT",
@@ -293,11 +287,9 @@
 	return ret;
 }
 
-static int amdgpu_amdkfd_validate(void *param, struct amdgpu_bo *bo)
+static int amdgpu_amdkfd_validate_vm_bo(void *_unused, struct amdgpu_bo *bo)
 {
-	struct amdgpu_vm_parser *p = param;
-
-	return amdgpu_amdkfd_bo_validate(bo, p->domain, p->wait);
+	return amdgpu_amdkfd_bo_validate(bo, bo->allowed_domains, false);
 }
 
 /* vm_validate_pt_pd_bos - Validate page table and directory BOs
@@ -311,20 +303,15 @@
 {
 	struct amdgpu_bo *pd = vm->root.base.bo;
 	struct amdgpu_device *adev = amdgpu_ttm_adev(pd->tbo.bdev);
-	struct amdgpu_vm_parser param;
 	int ret;
 
-	param.domain = AMDGPU_GEM_DOMAIN_VRAM;
-	param.wait = false;
-
-	ret = amdgpu_vm_validate_pt_bos(adev, vm, amdgpu_amdkfd_validate,
-					&param);
+	ret = amdgpu_vm_validate_pt_bos(adev, vm, amdgpu_amdkfd_validate_vm_bo, NULL);
 	if (ret) {
 		pr_err("amdgpu: failed to validate PT BOs\n");
 		return ret;
 	}
 
-	ret = amdgpu_amdkfd_validate(&param, pd);
+	ret = amdgpu_amdkfd_validate_vm_bo(NULL, pd);
 	if (ret) {
 		pr_err("amdgpu: failed to validate PD\n");
 		return ret;
@@ -964,11 +951,15 @@
 					   struct dma_fence **ef)
 {
 	struct amdgpu_device *adev = get_amdgpu_device(kgd);
-	struct drm_file *drm_priv = filp->private_data;
-	struct amdgpu_fpriv *drv_priv = drm_priv->driver_priv;
-	struct amdgpu_vm *avm = &drv_priv->vm;
+	struct amdgpu_fpriv *drv_priv;
+	struct amdgpu_vm *avm;
 	int ret;
 
+	ret = amdgpu_file_to_fpriv(filp, &drv_priv);
+	if (ret)
+		return ret;
+	avm = &drv_priv->vm;
+
 	/* Already a compute VM? */
 	if (avm->process_info)
 		return -EINVAL;
@@ -1213,6 +1204,7 @@
 err_bo_create:
 	unreserve_mem_limit(adev, size, alloc_domain, !!sg);
 err_reserve_limit:
+	amdgpu_sync_free(&(*mem)->sync);
 	mutex_destroy(&(*mem)->lock);
 	kfree(*mem);
 err:
@@ -1247,15 +1239,15 @@
 	 * be freed anyway
 	 */
 
-	/* No more MMU notifiers */
-	amdgpu_mn_unregister(mem->bo);
-
 	/* Make sure restore workers don't access the BO any more */
 	bo_list_entry = &mem->validate_list;
 	mutex_lock(&process_info->lock);
 	list_del(&bo_list_entry->head);
 	mutex_unlock(&process_info->lock);
 
+	/* No more MMU notifiers */
+	amdgpu_mn_unregister(mem->bo);
+
 	ret = reserve_bo_and_cond_vms(mem, NULL, BO_VM_ALL, &ctx);
 	if (unlikely(ret))
 		return ret;
@@ -1288,7 +1280,7 @@
 	}
 
 	/* Free the BO*/
-	amdgpu_bo_unref(&mem->bo);
+	drm_gem_object_put_unlocked(&mem->bo->tbo.base);
 	mutex_destroy(&mem->lock);
 	kfree(mem);
 
@@ -1630,7 +1622,8 @@
 		AMDGPU_VM_PAGE_READABLE | AMDGPU_VM_PAGE_WRITEABLE |
 		AMDGPU_VM_PAGE_EXECUTABLE | AMDGPU_VM_MTYPE_NC;
 
-	(*mem)->bo = amdgpu_bo_ref(bo);
+	drm_gem_object_get(&bo->tbo.base);
+	(*mem)->bo = bo;
 	(*mem)->va = va;
 	(*mem)->domain = (bo->preferred_domains & AMDGPU_GEM_DOMAIN_VRAM) ?
 		AMDGPU_GEM_DOMAIN_VRAM : AMDGPU_GEM_DOMAIN_GTT;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
@@ -338,17 +338,9 @@
 		path_size += le16_to_cpu(path->usSize);
 
 		if (device_support & le16_to_cpu(path->usDeviceTag)) {
-			uint8_t con_obj_id, con_obj_num, con_obj_type;
-
-			con_obj_id =
+			uint8_t con_obj_id =
 			    (le16_to_cpu(path->usConnObjectId) & OBJECT_ID_MASK)
 			    >> OBJECT_ID_SHIFT;
-			con_obj_num =
-			    (le16_to_cpu(path->usConnObjectId) & ENUM_ID_MASK)
-			    >> ENUM_ID_SHIFT;
-			con_obj_type =
-			    (le16_to_cpu(path->usConnObjectId) &
-			     OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT;
 
 			/* Skip TV/CV support */
 			if ((le16_to_cpu(path->usDeviceTag) ==
@@ -373,15 +365,7 @@
 			router.ddc_valid = false;
 			router.cd_valid = false;
 			for (j = 0; j < ((le16_to_cpu(path->usSize) - 8) / 2); j++) {
-				uint8_t grph_obj_id, grph_obj_num, grph_obj_type;
-
-				grph_obj_id =
-				    (le16_to_cpu(path->usGraphicObjIds[j]) &
-				     OBJECT_ID_MASK) >> OBJECT_ID_SHIFT;
-				grph_obj_num =
-				    (le16_to_cpu(path->usGraphicObjIds[j]) &
-				     ENUM_ID_MASK) >> ENUM_ID_SHIFT;
-				grph_obj_type =
+				uint8_t grph_obj_type =
 				    (le16_to_cpu(path->usGraphicObjIds[j]) &
 				     OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT;
 
@@ -1642,6 +1626,8 @@
 										(u32)le32_to_cpu(*((u32 *)reg_data + j));
 									j++;
 								} else if ((reg_table->mc_reg_address[i].pre_reg_data & LOW_NIBBLE_MASK) == DATA_EQU_PREV) {
+									if (i == 0)
+										continue;
 									reg_table->mc_reg_table_entry[num_ranges].mc_data[i] =
 										reg_table->mc_reg_table_entry[num_ranges].mc_data[i - 1];
 								}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
@@ -150,6 +150,7 @@
 				(mode_info->atom_context->bios + data_offset);
 			switch (crev) {
 			case 11:
+			case 12:
 				mem_channel_number = igp_info->v11.umachannelnumber;
 				/* channel width is 64 */
 				return mem_channel_number * 64;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
@@ -192,30 +192,35 @@
 
 static bool amdgpu_read_platform_bios(struct amdgpu_device *adev)
 {
-	uint8_t __iomem *bios;
-	size_t size;
+	phys_addr_t rom = adev->pdev->rom;
+	size_t romlen = adev->pdev->romlen;
+	void __iomem *bios;
 
 	adev->bios = NULL;
 
-	bios = pci_platform_rom(adev->pdev, &size);
-	if (!bios) {
+	if (!rom || romlen == 0)
 		return false;
-	}
 
-	adev->bios = kzalloc(size, GFP_KERNEL);
-	if (adev->bios == NULL)
+	adev->bios = kzalloc(romlen, GFP_KERNEL);
+	if (!adev->bios)
 		return false;
 
-	memcpy_fromio(adev->bios, bios, size);
+	bios = ioremap(rom, romlen);
+	if (!bios)
+		goto free_bios;
 
-	if (!check_atom_bios(adev->bios, size)) {
-		kfree(adev->bios);
-		return false;
-	}
+	memcpy_fromio(adev->bios, bios, romlen);
+	iounmap(bios);
+
+	if (!check_atom_bios(adev->bios, romlen))
+		goto free_bios;
 
-	adev->bios_size = size;
+	adev->bios_size = romlen;
 
 	return true;
+free_bios:
+	kfree(adev->bios);
+	return false;
 }
 
 #ifdef CONFIG_ACPI
@@ -308,6 +313,7 @@
 
 	if (!found)
 		return false;
+	pci_dev_put(pdev);
 
 	adev->bios = kmalloc(size, GFP_KERNEL);
 	if (!adev->bios) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c
@@ -61,7 +61,7 @@
 
 int amdgpu_bo_list_create(struct amdgpu_device *adev, struct drm_file *filp,
 			  struct drm_amdgpu_bo_list_entry *info,
-			  unsigned num_entries, struct amdgpu_bo_list **result)
+			  size_t num_entries, struct amdgpu_bo_list **result)
 {
 	unsigned last_entry = 0, first_userptr = num_entries;
 	struct amdgpu_bo_list_entry *array;
@@ -178,6 +178,7 @@
 	}
 
 	rcu_read_unlock();
+	*result = NULL;
 	return -ENOENT;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h
@@ -60,7 +60,7 @@
 int amdgpu_bo_list_create(struct amdgpu_device *adev,
 				 struct drm_file *filp,
 				 struct drm_amdgpu_bo_list_entry *info,
-				 unsigned num_entries,
+				 size_t num_entries,
 				 struct amdgpu_bo_list **list);
 
 static inline struct amdgpu_bo_list_entry *
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c
@@ -213,6 +213,9 @@
 		struct amdgpu_firmware_info *ucode;
 
 		id = fw_type_convert(cgs_device, type);
+		if (id >= AMDGPU_UCODE_ID_MAXIMUM)
+			return -EINVAL;
+
 		ucode = &adev->firmware.ucode[id];
 		if (ucode->fw == NULL)
 			return -EINVAL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
@@ -316,8 +316,10 @@
 	if (!amdgpu_connector->edid) {
 		/* some laptops provide a hardcoded edid in rom for LCDs */
 		if (((connector->connector_type == DRM_MODE_CONNECTOR_LVDS) ||
-		     (connector->connector_type == DRM_MODE_CONNECTOR_eDP)))
+		     (connector->connector_type == DRM_MODE_CONNECTOR_eDP))) {
 			amdgpu_connector->edid = amdgpu_connector_get_hardcoded_edid(adev);
+			drm_connector_update_edid_property(connector, amdgpu_connector->edid);
+		}
 	}
 }
 
@@ -389,6 +391,9 @@
 	    native_mode->vdisplay != 0 &&
 	    native_mode->clock != 0) {
 		mode = drm_mode_duplicate(dev, native_mode);
+		if (!mode)
+			return NULL;
+
 		mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
 		drm_mode_set_name(mode);
 
@@ -403,6 +408,9 @@
 		 * simpler.
 		 */
 		mode = drm_cvt_mode(dev, native_mode->hdisplay, native_mode->vdisplay, 60, true, false, false);
+		if (!mode)
+			return NULL;
+
 		mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
 		DRM_DEBUG_KMS("Adding cvt approximation of native panel mode %s\n", mode->name);
 	}
@@ -719,8 +727,10 @@
 
 	if (!drm_kms_helper_is_poll_worker()) {
 		r = pm_runtime_get_sync(connector->dev->dev);
-		if (r < 0)
+		if (r < 0) {
+			pm_runtime_put_autosuspend(connector->dev->dev);
 			return connector_status_disconnected;
+		}
 	}
 
 	if (encoder) {
@@ -827,6 +837,7 @@
 
 	amdgpu_connector_get_edid(connector);
 	ret = amdgpu_connector_ddc_get_modes(connector);
+	amdgpu_get_native_mode(connector);
 
 	return ret;
 }
@@ -857,8 +868,10 @@
 
 	if (!drm_kms_helper_is_poll_worker()) {
 		r = pm_runtime_get_sync(connector->dev->dev);
-		if (r < 0)
+		if (r < 0) {
+			pm_runtime_put_autosuspend(connector->dev->dev);
 			return connector_status_disconnected;
+		}
 	}
 
 	encoder = amdgpu_connector_best_single_encoder(connector);
@@ -980,8 +993,10 @@
 
 	if (!drm_kms_helper_is_poll_worker()) {
 		r = pm_runtime_get_sync(connector->dev->dev);
-		if (r < 0)
+		if (r < 0) {
+			pm_runtime_put_autosuspend(connector->dev->dev);
 			return connector_status_disconnected;
+		}
 	}
 
 	if (!force && amdgpu_connector_check_hpd_status_unchanged(connector)) {
@@ -1330,8 +1345,10 @@
 
 	if (!drm_kms_helper_is_poll_worker()) {
 		r = pm_runtime_get_sync(connector->dev->dev);
-		if (r < 0)
+		if (r < 0) {
+			pm_runtime_put_autosuspend(connector->dev->dev);
 			return connector_status_disconnected;
+		}
 	}
 
 	if (!force && amdgpu_connector_check_hpd_status_unchanged(connector)) {
@@ -1631,10 +1648,12 @@
 						   adev->mode_info.dither_property,
 						   AMDGPU_FMT_DITHER_DISABLE);
 
-			if (amdgpu_audio != 0)
+			if (amdgpu_audio != 0) {
 				drm_object_attach_property(&amdgpu_connector->base.base,
 							   adev->mode_info.audio_property,
 							   AMDGPU_AUDIO_AUTO);
+				amdgpu_connector->audio = AMDGPU_AUDIO_AUTO;
+			}
 
 			subpixel_order = SubPixelHorizontalRGB;
 			connector->interlace_allowed = true;
@@ -1756,6 +1775,7 @@
 				drm_object_attach_property(&amdgpu_connector->base.base,
 							   adev->mode_info.audio_property,
 							   AMDGPU_AUDIO_AUTO);
+				amdgpu_connector->audio = AMDGPU_AUDIO_AUTO;
 			}
 			drm_object_attach_property(&amdgpu_connector->base.base,
 						   adev->mode_info.dither_property,
@@ -1809,6 +1829,7 @@
 				drm_object_attach_property(&amdgpu_connector->base.base,
 							   adev->mode_info.audio_property,
 							   AMDGPU_AUDIO_AUTO);
+				amdgpu_connector->audio = AMDGPU_AUDIO_AUTO;
 			}
 			drm_object_attach_property(&amdgpu_connector->base.base,
 						   adev->mode_info.dither_property,
@@ -1859,6 +1880,7 @@
 				drm_object_attach_property(&amdgpu_connector->base.base,
 							   adev->mode_info.audio_property,
 							   AMDGPU_AUDIO_AUTO);
+				amdgpu_connector->audio = AMDGPU_AUDIO_AUTO;
 			}
 			drm_object_attach_property(&amdgpu_connector->base.base,
 						   adev->mode_info.dither_property,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -43,7 +43,6 @@
 	struct drm_gem_object *gobj;
 	struct amdgpu_bo *bo;
 	unsigned long size;
-	int r;
 
 	gobj = drm_gem_object_lookup(p->filp, data->handle);
 	if (gobj == NULL)
@@ -58,23 +57,14 @@
 	drm_gem_object_put_unlocked(gobj);
 
 	size = amdgpu_bo_size(bo);
-	if (size != PAGE_SIZE || (data->offset + 8) > size) {
-		r = -EINVAL;
-		goto error_unref;
-	}
+	if (size != PAGE_SIZE || data->offset > (size - 8))
+		return -EINVAL;
 
-	if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm)) {
-		r = -EINVAL;
-		goto error_unref;
-	}
+	if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm))
+		return -EINVAL;
 
 	*offset = data->offset;
-
 	return 0;
-
-error_unref:
-	amdgpu_bo_unref(&bo);
-	return r;
 }
 
 static int amdgpu_cs_bo_handles_chunk(struct amdgpu_cs_parser *p,
@@ -114,7 +104,7 @@
 	int ret;
 
 	if (cs->in.num_chunks == 0)
-		return 0;
+		return -EINVAL;
 
 	chunk_array = kmalloc_array(cs->in.num_chunks, sizeof(uint64_t), GFP_KERNEL);
 	if (!chunk_array)
@@ -151,7 +141,7 @@
 	}
 
 	for (i = 0; i < p->nchunks; i++) {
-		struct drm_amdgpu_cs_chunk __user **chunk_ptr = NULL;
+		struct drm_amdgpu_cs_chunk __user *chunk_ptr = NULL;
 		struct drm_amdgpu_cs_chunk user_chunk;
 		uint32_t __user *cdata;
 
@@ -1542,6 +1532,7 @@
 		return 0;
 
 	default:
+		dma_fence_put(fence);
 		return -EINVAL;
 	}
 }
@@ -1574,15 +1565,15 @@
 			continue;
 
 		r = dma_fence_wait_timeout(fence, true, timeout);
+		if (r > 0 && fence->error)
+			r = fence->error;
+
 		dma_fence_put(fence);
 		if (r < 0)
 			return r;
 
 		if (r == 0)
 			break;
-
-		if (fence->error)
-			return fence->error;
 	}
 
 	memset(wait, 0, sizeof(*wait));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
@@ -351,7 +351,6 @@
 {
 	struct amdgpu_ctx *ctx;
 	struct amdgpu_ctx_mgr *mgr;
-	unsigned long ras_counter;
 
 	if (!fpriv)
 		return -EINVAL;
@@ -376,21 +375,6 @@
 	if (atomic_read(&ctx->guilty))
 		out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_GUILTY;
 
-	/*query ue count*/
-	ras_counter = amdgpu_ras_query_error_count(adev, false);
-	/*ras counter is monotonic increasing*/
-	if (ras_counter != ctx->ras_counter_ue) {
-		out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_RAS_UE;
-		ctx->ras_counter_ue = ras_counter;
-	}
-
-	/*query ce count*/
-	ras_counter = amdgpu_ras_query_error_count(adev, true);
-	if (ras_counter != ctx->ras_counter_ce) {
-		out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_RAS_CE;
-		ctx->ras_counter_ce = ras_counter;
-	}
-
 	mutex_unlock(&mgr->lock);
 	return 0;
 }
@@ -417,16 +401,24 @@
 
 	switch (args->in.op) {
 	case AMDGPU_CTX_OP_ALLOC_CTX:
+		if (args->in.flags)
+			return -EINVAL;
 		r = amdgpu_ctx_alloc(adev, fpriv, filp, priority, &id);
 		args->out.alloc.ctx_id = id;
 		break;
 	case AMDGPU_CTX_OP_FREE_CTX:
+		if (args->in.flags)
+			return -EINVAL;
 		r = amdgpu_ctx_free(fpriv, id);
 		break;
 	case AMDGPU_CTX_OP_QUERY_STATE:
+		if (args->in.flags)
+			return -EINVAL;
 		r = amdgpu_ctx_query(adev, fpriv, id, &args->out);
 		break;
 	case AMDGPU_CTX_OP_QUERY_STATE2:
+		if (args->in.flags)
+			return -EINVAL;
 		r = amdgpu_ctx_query2(adev, fpriv, id, &args->out);
 		break;
 	default:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
@@ -240,7 +240,7 @@
 	while (size) {
 		uint32_t value;
 
-		value = RREG32_PCIE(*pos >> 2);
+		value = RREG32_PCIE(*pos);
 		r = put_user(value, (uint32_t *)buf);
 		if (r)
 			return r;
@@ -283,7 +283,7 @@
 		if (r)
 			return r;
 
-		WREG32_PCIE(*pos >> 2, value);
+		WREG32_PCIE(*pos, value);
 
 		result += 4;
 		buf += 4;
@@ -392,6 +392,9 @@
 	ssize_t result = 0;
 	int r;
 
+	if (!adev->smc_rreg)
+		return -EOPNOTSUPP;
+
 	if (size & 0x3 || *pos & 0x3)
 		return -EINVAL;
 
@@ -431,6 +434,9 @@
 	ssize_t result = 0;
 	int r;
 
+	if (!adev->smc_wreg)
+		return -EOPNOTSUPP;
+
 	if (size & 0x3 || *pos & 0x3)
 		return -EINVAL;
 
@@ -694,11 +700,11 @@
 	ssize_t result = 0;
 	uint32_t offset, se, sh, cu, wave, simd, thread, bank, *data;
 
-	if (size & 3 || *pos & 3)
+	if (size > 4096 || size & 3 || *pos & 3)
 		return -EINVAL;
 
 	/* decode offset */
-	offset = *pos & GENMASK_ULL(11, 0);
+	offset = (*pos & GENMASK_ULL(11, 0)) >> 2;
 	se = (*pos & GENMASK_ULL(19, 12)) >> 12;
 	sh = (*pos & GENMASK_ULL(27, 20)) >> 20;
 	cu = (*pos & GENMASK_ULL(35, 28)) >> 28;
@@ -729,7 +735,7 @@
 	while (size) {
 		uint32_t value;
 
-		value = data[offset++];
+		value = data[result >> 2];
 		r = put_user(value, (uint32_t *)buf);
 		if (r) {
 			result = r;
@@ -859,6 +865,9 @@
 	struct amdgpu_device *adev = dev->dev_private;
 	int r = 0, i;
 
+	/* Avoid accidently unparking the sched thread during GPU reset */
+	mutex_lock(&adev->lock_reset);
+
 	/* hold on the scheduler */
 	for (i = 0; i < AMDGPU_MAX_RINGS; i++) {
 		struct amdgpu_ring *ring = adev->rings[i];
@@ -884,6 +893,8 @@
 		kthread_unpark(ring->sched.thread);
 	}
 
+	mutex_unlock(&adev->lock_reset);
+
 	return 0;
 }
 
@@ -985,27 +996,37 @@
 static void amdgpu_ib_preempt_mark_partial_job(struct amdgpu_ring *ring)
 {
 	struct amdgpu_job *job;
-	struct drm_sched_job *s_job;
+	struct drm_sched_job *s_job, *tmp;
 	uint32_t preempt_seq;
 	struct dma_fence *fence, **ptr;
 	struct amdgpu_fence_driver *drv = &ring->fence_drv;
 	struct drm_gpu_scheduler *sched = &ring->sched;
+	bool preempted = true;
 
 	if (ring->funcs->type != AMDGPU_RING_TYPE_GFX)
 		return;
 
 	preempt_seq = le32_to_cpu(*(drv->cpu_addr + 2));
-	if (preempt_seq <= atomic_read(&drv->last_seq))
-		return;
+	if (preempt_seq <= atomic_read(&drv->last_seq)) {
+		preempted = false;
+		goto no_preempt;
+	}
 
 	preempt_seq &= drv->num_fences_mask;
 	ptr = &drv->fences[preempt_seq];
 	fence = rcu_dereference_protected(*ptr, 1);
 
+no_preempt:
 	spin_lock(&sched->job_list_lock);
-	list_for_each_entry(s_job, &sched->ring_mirror_list, node) {
+	list_for_each_entry_safe(s_job, tmp, &sched->ring_mirror_list, node) {
+		if (dma_fence_is_signaled(&s_job->s_fence->finished)) {
+			/* remove job from ring_mirror_list */
+			list_del_init(&s_job->node);
+			sched->ops->free_job(s_job);
+			continue;
+		}
 		job = to_amdgpu_job(s_job);
-		if (job->fence == fence)
+		if (preempted && job->fence == fence)
 			/* mark the job as preempted */
 			job->preemption_status |= AMDGPU_IB_PREEMPTED;
 	}
@@ -1036,6 +1057,9 @@
 	if (!fences)
 		return -ENOMEM;
 
+	/* Avoid accidently unparking the sched thread during GPU reset */
+	mutex_lock(&adev->lock_reset);
+
 	/* stop the scheduler */
 	kthread_park(ring->sched.thread);
 
@@ -1075,6 +1099,8 @@
 	/* restart the scheduler */
 	kthread_unpark(ring->sched.thread);
 
+	mutex_unlock(&adev->lock_reset);
+
 	ttm_bo_unlock_delayed_workqueue(&adev->mman.bdev, resched);
 
 	if (fences)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -70,11 +70,9 @@
 MODULE_FIRMWARE("amdgpu/raven_gpu_info.bin");
 MODULE_FIRMWARE("amdgpu/picasso_gpu_info.bin");
 MODULE_FIRMWARE("amdgpu/raven2_gpu_info.bin");
-MODULE_FIRMWARE("amdgpu/arcturus_gpu_info.bin");
 MODULE_FIRMWARE("amdgpu/renoir_gpu_info.bin");
 MODULE_FIRMWARE("amdgpu/navi10_gpu_info.bin");
 MODULE_FIRMWARE("amdgpu/navi14_gpu_info.bin");
-MODULE_FIRMWARE("amdgpu/navi12_gpu_info.bin");
 
 #define AMDGPU_RESUME_MS		2000
 
@@ -759,10 +757,29 @@
 	u16 cmd;
 	int r;
 
+	if (!IS_ENABLED(CONFIG_PHYS_ADDR_T_64BIT))
+		return 0;
+
 	/* Bypass for VF */
 	if (amdgpu_sriov_vf(adev))
 		return 0;
 
+	/* resizing on Dell G5 SE platforms causes problems with runtime pm */
+	if ((amdgpu_runtime_pm != 0) &&
+	    adev->pdev->vendor == PCI_VENDOR_ID_ATI &&
+	    adev->pdev->device == 0x731f &&
+	    adev->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL)
+		return 0;
+
+	/* PCI_EXT_CAP_ID_VNDR extended capability is located at 0x100 */
+	if (!pci_find_ext_capability(adev->pdev, PCI_EXT_CAP_ID_VNDR))
+		DRM_WARN("System can't access extended configuration space,please check!!\n");
+
+	/* skip if the bios has already enabled large BAR */
+	if (adev->gmc.real_vram_size &&
+	    (pci_resource_len(adev->pdev, 0) >= adev->gmc.real_vram_size))
+		return 0;
+
 	/* Check if the root BUS has 64bit memory resources */
 	root = adev->pdev->bus;
 	while (root->parent)
@@ -844,6 +861,7 @@
 				return true;
 
 			fw_ver = *((uint32_t *)adev->pm.fw->data + 69);
+			release_firmware(adev->pm.fw);
 			if (fw_ver < 0x00160e00)
 				return true;
 		}
@@ -2057,11 +2075,11 @@
 	if (adev->gmc.xgmi.num_physical_nodes > 1)
 		amdgpu_xgmi_remove_device(adev);
 
-	amdgpu_amdkfd_device_fini(adev);
-
 	amdgpu_device_set_pg_state(adev, AMD_PG_STATE_UNGATE);
 	amdgpu_device_set_cg_state(adev, AMD_CG_STATE_UNGATE);
 
+	amdgpu_amdkfd_device_fini(adev);
+
 	/* need to disable SMC first */
 	for (i = 0; i < adev->num_ip_blocks; i++) {
 		if (!adev->ip_blocks[i].status.hw)
@@ -2291,7 +2309,7 @@
 		AMD_IP_BLOCK_TYPE_IH,
 	};
 
-	for (i = 0; i < ARRAY_SIZE(ip_order); i++) {
+	for (i = 0; i < adev->num_ip_blocks; i++) {
 		int j;
 		struct amdgpu_ip_block *block;
 
@@ -3070,12 +3088,12 @@
 		}
 	}
 
-	amdgpu_amdkfd_suspend(adev);
-
 	amdgpu_ras_suspend(adev);
 
 	r = amdgpu_device_ip_suspend_phase1(adev);
 
+	amdgpu_amdkfd_suspend(adev);
+
 	/* evict vram memory */
 	amdgpu_bo_evict_vram(adev);
 
@@ -3704,7 +3722,6 @@
 			r = amdgpu_ib_ring_tests(tmp_adev);
 			if (r) {
 				dev_err(tmp_adev->dev, "ib ring test failed (%d).\n", r);
-				r = amdgpu_device_ip_suspend(tmp_adev);
 				need_full_reset = true;
 				r = -EAGAIN;
 				goto end;
@@ -3890,7 +3907,7 @@
 
 		amdgpu_device_lock_adev(tmp_adev, false);
 		r = amdgpu_device_pre_asic_reset(tmp_adev,
-						 NULL,
+						 (tmp_adev == adev) ? job : NULL,
 						 &need_full_reset);
 		/*TODO Should we stop ?*/
 		if (r) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
@@ -136,7 +136,7 @@
 {
 	uint32_t *p = (uint32_t *)binary;
 	uint64_t vram_size = (uint64_t)RREG32(mmRCC_CONFIG_MEMSIZE) << 20;
-	uint64_t pos = vram_size - BINARY_MAX_SIZE;
+	uint64_t pos = vram_size - DISCOVERY_TMR_SIZE;
 	unsigned long flags;
 
 	while (pos < vram_size) {
@@ -179,7 +179,7 @@
 	uint16_t checksum;
 	int r;
 
-	adev->discovery = kzalloc(BINARY_MAX_SIZE, GFP_KERNEL);
+	adev->discovery = kzalloc(DISCOVERY_TMR_SIZE, GFP_KERNEL);
 	if (!adev->discovery)
 		return -ENOMEM;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.h
@@ -24,6 +24,8 @@
 #ifndef __AMDGPU_DISCOVERY__
 #define __AMDGPU_DISCOVERY__
 
+#define DISCOVERY_TMR_SIZE  (64 << 10)
+
 int amdgpu_discovery_init(struct amdgpu_device *adev);
 void amdgpu_discovery_fini(struct amdgpu_device *adev);
 int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
@@ -282,7 +282,7 @@
 
 	ret = pm_runtime_get_sync(dev->dev);
 	if (ret < 0)
-		return ret;
+		goto out;
 
 	ret = drm_crtc_helper_set_config(set, ctx);
 
@@ -306,6 +306,7 @@
 		adev->have_disp_power_ref = false;
 	}
 
+out:
 	/* drop the power reference we got coming in here */
 	pm_runtime_put_autosuspend(dev->dev);
 	return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -145,7 +145,7 @@
 int amdgpu_mcbp = 0;
 int amdgpu_discovery = -1;
 int amdgpu_mes = 0;
-int amdgpu_noretry = 1;
+int amdgpu_noretry;
 
 struct amdgpu_mgpu_info mgpu_info = {
 	.mutex = __MUTEX_INITIALIZER(mgpu_info.mutex),
@@ -613,7 +613,7 @@
 module_param_named(mes, amdgpu_mes, int, 0444);
 
 MODULE_PARM_DESC(noretry,
-	"Disable retry faults (0 = retry enabled, 1 = retry disabled (default))");
+	"Disable retry faults (0 = retry enabled (default), 1 = retry disabled)");
 module_param_named(noretry, amdgpu_noretry, int, 0644);
 
 #ifdef CONFIG_HSA_AMD
@@ -633,7 +633,7 @@
  * Maximum number of processes that HWS can schedule concurrently. The maximum is the
  * number of VMIDs assigned to the HWS, which is also the default.
  */
-int hws_max_conc_proc = 8;
+int hws_max_conc_proc = -1;
 module_param(hws_max_conc_proc, int, 0444);
 MODULE_PARM_DESC(hws_max_conc_proc,
 	"Max # processes HWS can execute concurrently when sched_policy=0 (0 = no concurrency, #VMIDs for KFD = Maximum(default))");
@@ -1011,6 +1011,7 @@
 	{0x1002, 0x7319, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI10},
 	{0x1002, 0x731A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI10},
 	{0x1002, 0x731B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI10},
+	{0x1002, 0x731E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI10},
 	{0x1002, 0x731F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI10},
 	/* Navi14 */
 	{0x1002, 0x7340, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI14},
@@ -1023,6 +1024,7 @@
 
 	/* Navi12 */
 	{0x1002, 0x7360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI12|AMD_EXP_HW_SUPPORT},
+	{0x1002, 0x7362, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_NAVI12|AMD_EXP_HW_SUPPORT},
 
 	{0, 0, 0}
 };
@@ -1285,11 +1287,12 @@
 	dev = file_priv->minor->dev;
 	ret = pm_runtime_get_sync(dev->dev);
 	if (ret < 0)
-		return ret;
+		goto out;
 
 	ret = drm_ioctl(filp, cmd, arg);
 
 	pm_runtime_mark_last_busy(dev->dev);
+out:
 	pm_runtime_put_autosuspend(dev->dev);
 	return ret;
 }
@@ -1420,7 +1423,7 @@
 
 static struct drm_driver kms_driver = {
 	.driver_features =
-	    DRIVER_USE_AGP | DRIVER_ATOMIC |
+	    DRIVER_ATOMIC |
 	    DRIVER_GEM |
 	    DRIVER_RENDER | DRIVER_MODESET | DRIVER_SYNCOBJ,
 	.load = amdgpu_driver_load_kms,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
@@ -133,8 +133,7 @@
 	u32 cpp;
 	u64 flags = AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
 			       AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS     |
-			       AMDGPU_GEM_CREATE_VRAM_CLEARED 	     |
-			       AMDGPU_GEM_CREATE_CPU_GTT_USWC;
+			       AMDGPU_GEM_CREATE_VRAM_CLEARED;
 
 	info = drm_get_format_info(adev->ddev, mode_cmd);
 	cpp = info->cpp[0];
@@ -147,7 +146,7 @@
 	size = mode_cmd->pitches[0] * height;
 	aligned_size = ALIGN(size, PAGE_SIZE);
 	ret = amdgpu_gem_object_create(adev, aligned_size, 0, domain, flags,
-				       ttm_bo_type_kernel, NULL, &gobj);
+				       ttm_bo_type_device, NULL, &gobj);
 	if (ret) {
 		pr_err("failed to allocate framebuffer (%d)\n", aligned_size);
 		return -ENOMEM;
@@ -290,10 +289,13 @@
 static int amdgpu_fbdev_destroy(struct drm_device *dev, struct amdgpu_fbdev *rfbdev)
 {
 	struct amdgpu_framebuffer *rfb = &rfbdev->rfb;
+	int i;
 
 	drm_fb_helper_unregister_fbi(&rfbdev->helper);
 
 	if (rfb->base.obj[0]) {
+		for (i = 0; i < rfb->base.format->num_planes; i++)
+			drm_gem_object_put(rfb->base.obj[0]);
 		amdgpufb_destroy_pinned_object(rfb->base.obj[0]);
 		rfb->base.obj[0] = NULL;
 		drm_framebuffer_unregister_private(&rfb->base);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
@@ -404,7 +404,9 @@
 		ring->fence_drv.gpu_addr = adev->uvd.inst[ring->me].gpu_addr + index;
 	}
 	amdgpu_fence_write(ring, atomic_read(&ring->fence_drv.last_seq));
-	amdgpu_irq_get(adev, irq_src, irq_type);
+
+	if (irq_src)
+		amdgpu_irq_get(adev, irq_src, irq_type);
 
 	ring->fence_drv.irq_src = irq_src;
 	ring->fence_drv.irq_type = irq_type;
@@ -539,8 +541,9 @@
 			/* no need to trigger GPU reset as we are unloading */
 			amdgpu_fence_driver_force_completion(ring);
 		}
-		amdgpu_irq_put(adev, ring->fence_drv.irq_src,
-			       ring->fence_drv.irq_type);
+		if (ring->fence_drv.irq_src)
+			amdgpu_irq_put(adev, ring->fence_drv.irq_src,
+				       ring->fence_drv.irq_type);
 		drm_sched_fini(&ring->sched);
 		del_timer_sync(&ring->fence_drv.fallback_timer);
 		for (j = 0; j <= ring->fence_drv.num_fences_mask; ++j)
@@ -576,8 +579,9 @@
 		}
 
 		/* disable the interrupt */
-		amdgpu_irq_put(adev, ring->fence_drv.irq_src,
-			       ring->fence_drv.irq_type);
+		if (ring->fence_drv.irq_src)
+			amdgpu_irq_put(adev, ring->fence_drv.irq_src,
+				       ring->fence_drv.irq_type);
 	}
 }
 
@@ -603,8 +607,9 @@
 			continue;
 
 		/* enable the interrupt */
-		amdgpu_irq_get(adev, ring->fence_drv.irq_src,
-			       ring->fence_drv.irq_type);
+		if (ring->fence_drv.irq_src)
+			amdgpu_irq_get(adev, ring->fence_drv.irq_src,
+				       ring->fence_drv.irq_type);
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
@@ -161,16 +161,17 @@
 
 	struct amdgpu_bo_list_entry vm_pd;
 	struct list_head list, duplicates;
+	struct dma_fence *fence = NULL;
 	struct ttm_validate_buffer tv;
 	struct ww_acquire_ctx ticket;
 	struct amdgpu_bo_va *bo_va;
-	int r;
+	long r;
 
 	INIT_LIST_HEAD(&list);
 	INIT_LIST_HEAD(&duplicates);
 
 	tv.bo = &bo->tbo;
-	tv.num_shared = 1;
+	tv.num_shared = 2;
 	list_add(&tv.head, &list);
 
 	amdgpu_vm_get_pd_bo(vm, &list, &vm_pd);
@@ -178,28 +179,34 @@
 	r = ttm_eu_reserve_buffers(&ticket, &list, false, &duplicates, false);
 	if (r) {
 		dev_err(adev->dev, "leaking bo va because "
-			"we fail to reserve bo (%d)\n", r);
+			"we fail to reserve bo (%ld)\n", r);
 		return;
 	}
 	bo_va = amdgpu_vm_bo_find(vm, bo);
-	if (bo_va && --bo_va->ref_count == 0) {
-		amdgpu_vm_bo_rmv(adev, bo_va);
+	if (!bo_va || --bo_va->ref_count)
+		goto out_unlock;
 
-		if (amdgpu_vm_ready(vm)) {
-			struct dma_fence *fence = NULL;
+	amdgpu_vm_bo_rmv(adev, bo_va);
+	if (!amdgpu_vm_ready(vm))
+		goto out_unlock;
 
-			r = amdgpu_vm_clear_freed(adev, vm, &fence);
-			if (unlikely(r)) {
-				dev_err(adev->dev, "failed to clear page "
-					"tables on GEM object close (%d)\n", r);
-			}
-
-			if (fence) {
-				amdgpu_bo_fence(bo, fence, true);
-				dma_fence_put(fence);
-			}
-		}
+	fence = dma_resv_get_excl(bo->tbo.base.resv);
+	if (fence) {
+		amdgpu_bo_fence(bo, fence, true);
+		fence = NULL;
 	}
+
+	r = amdgpu_vm_clear_freed(adev, vm, &fence);
+	if (r || !fence)
+		goto out_unlock;
+
+	amdgpu_bo_fence(bo, fence, true);
+	dma_fence_put(fence);
+
+out_unlock:
+	if (unlikely(r < 0))
+		dev_err(adev->dev, "failed to clear page "
+			"tables on GEM object close (%ld)\n", r);
 	ttm_eu_backoff_reservation(&ticket, &list);
 }
 
@@ -322,11 +329,9 @@
 	if (r)
 		goto release_object;
 
-	if (args->flags & AMDGPU_GEM_USERPTR_REGISTER) {
-		r = amdgpu_mn_register(bo, args->addr);
-		if (r)
-			goto release_object;
-	}
+	r = amdgpu_mn_register(bo, args->addr);
+	if (r)
+		goto release_object;
 
 	if (args->flags & AMDGPU_GEM_USERPTR_VALIDATE) {
 		r = amdgpu_ttm_tt_get_user_pages(bo, bo->tbo.ttm->pages);
@@ -554,6 +559,7 @@
 	struct ww_acquire_ctx ticket;
 	struct list_head list, duplicates;
 	uint64_t va_flags;
+	uint64_t vm_size;
 	int r = 0;
 
 	if (args->va_address < AMDGPU_VA_RESERVED_SIZE) {
@@ -574,6 +580,15 @@
 
 	args->va_address &= AMDGPU_GMC_HOLE_MASK;
 
+	vm_size = adev->vm_manager.max_pfn * AMDGPU_GPU_PAGE_SIZE;
+	vm_size -= AMDGPU_VA_RESERVED_SIZE;
+	if (args->va_address + args->map_size > vm_size) {
+		dev_dbg(&dev->pdev->dev,
+			"va_address 0x%llx is in top reserved area 0x%llx\n",
+			args->va_address + args->map_size, vm_size);
+		return -EINVAL;
+	}
+
 	if ((args->flags & ~valid_flags) && (args->flags & ~prt_flags)) {
 		dev_dbg(&dev->pdev->dev, "invalid flags combination 0x%08X\n",
 			args->flags);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
@@ -263,7 +263,7 @@
 		    * adev->gfx.mec.num_pipe_per_mec
 		    * adev->gfx.mec.num_queue_per_pipe;
 
-	while (queue_bit-- >= 0) {
+	while (--queue_bit >= 0) {
 		if (test_bit(queue_bit, adev->gfx.mec.queue_bitmap))
 			continue;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
@@ -77,6 +77,7 @@
 struct amdgpu_vmhub {
 	uint32_t	ctx0_ptb_addr_lo32;
 	uint32_t	ctx0_ptb_addr_hi32;
+	uint32_t	vm_inv_eng0_sem;
 	uint32_t	vm_inv_eng0_req;
 	uint32_t	vm_inv_eng0_ack;
 	uint32_t	vm_context0_cntl;
@@ -156,6 +157,7 @@
 	uint32_t                srbm_soft_reset;
 	bool			prt_warning;
 	uint64_t		stolen_size;
+	uint32_t		sdpif_register;
 	/* apertures */
 	u64			shared_aperture_start;
 	u64			shared_aperture_end;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c
@@ -339,7 +339,7 @@
 void
 amdgpu_i2c_router_select_ddc_port(const struct amdgpu_connector *amdgpu_connector)
 {
-	u8 val;
+	u8 val = 0;
 
 	if (!amdgpu_connector->router.ddc_valid)
 		return;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
@@ -384,6 +384,14 @@
 	int r;
 
 	entry.iv_entry = (const uint32_t *)&ih->ring[ring_index];
+
+	/*
+	 * timestamp is not supported on some legacy SOCs (cik, cz, iceland,
+	 * si and tonga), so initialize timestamp and timestamp_src to 0
+	 */
+	entry.timestamp = 0;
+	entry.timestamp_src = 0;
+
 	amdgpu_ih_decode_iv(adev, &entry);
 
 	trace_amdgpu_iv(ih - &adev->irq.ih, &entry);
@@ -469,7 +477,7 @@
 		for (j = 0; j < AMDGPU_MAX_IRQ_SRC_ID; ++j) {
 			struct amdgpu_irq_src *src = adev->irq.client[i].sources[j];
 
-			if (!src)
+			if (!src || !src->funcs || !src->funcs->set)
 				continue;
 			for (k = 0; k < src->num_types; k++)
 				amdgpu_irq_update(adev, src, k);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
@@ -36,7 +36,8 @@
 
 	memset(&ti, 0, sizeof(struct amdgpu_task_info));
 
-	if (amdgpu_ring_soft_recovery(ring, job->vmid, s_job->s_fence->parent)) {
+	if (amdgpu_gpu_recovery &&
+	    amdgpu_ring_soft_recovery(ring, job->vmid, s_job->s_fence->parent)) {
 		DRM_ERROR("ring %s timeout, but soft recovered\n",
 			  s_job->sched->name);
 		return;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -471,6 +471,7 @@
 			crtc = (struct drm_crtc *)minfo->crtcs[i];
 			if (crtc && crtc->base.id == info->mode_crtc.id) {
 				struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
+
 				ui32 = amdgpu_crtc->crtc_id;
 				found = 1;
 				break;
@@ -489,7 +490,7 @@
 		if (ret)
 			return ret;
 
-		ret = copy_to_user(out, &ip, min((size_t)size, sizeof(ip)));
+		ret = copy_to_user(out, &ip, min_t(size_t, size, sizeof(ip)));
 		return ret ? -EFAULT : 0;
 	}
 	case AMDGPU_INFO_HW_IP_COUNT: {
@@ -625,21 +626,29 @@
 				    ? -EFAULT : 0;
 	}
 	case AMDGPU_INFO_READ_MMR_REG: {
-		unsigned n, alloc_size;
+		unsigned int n, alloc_size;
 		uint32_t *regs;
-		unsigned se_num = (info->read_mmr_reg.instance >>
+		unsigned int se_num = (info->read_mmr_reg.instance >>
 				   AMDGPU_INFO_MMR_SE_INDEX_SHIFT) &
 				  AMDGPU_INFO_MMR_SE_INDEX_MASK;
-		unsigned sh_num = (info->read_mmr_reg.instance >>
+		unsigned int sh_num = (info->read_mmr_reg.instance >>
 				   AMDGPU_INFO_MMR_SH_INDEX_SHIFT) &
 				  AMDGPU_INFO_MMR_SH_INDEX_MASK;
 
 		/* set full masks if the userspace set all bits
-		 * in the bitfields */
+		 * in the bitfields
+		 */
 		if (se_num == AMDGPU_INFO_MMR_SE_INDEX_MASK)
 			se_num = 0xffffffff;
+		else if (se_num >= AMDGPU_GFX_MAX_SE)
+			return -EINVAL;
 		if (sh_num == AMDGPU_INFO_MMR_SH_INDEX_MASK)
 			sh_num = 0xffffffff;
+		else if (sh_num >= AMDGPU_GFX_MAX_SH_PER_SE)
+			return -EINVAL;
+
+		if (info->read_mmr_reg.count > 128)
+			return -EINVAL;
 
 		if (info->read_mmr_reg.count > 128)
 			return -EINVAL;
@@ -667,9 +676,10 @@
 		return n ? -EFAULT : 0;
 	}
 	case AMDGPU_INFO_DEV_INFO: {
-		struct drm_amdgpu_info_device dev_info = {};
+		struct drm_amdgpu_info_device dev_info;
 		uint64_t vm_size;
 
+		memset(&dev_info, 0, sizeof(dev_info));
 		dev_info.device_id = dev->pdev->device;
 		dev_info.chip_rev = adev->rev_id;
 		dev_info.external_rev = adev->external_rev_id;
@@ -761,7 +771,7 @@
 				    min((size_t)size, sizeof(dev_info))) ? -EFAULT : 0;
 	}
 	case AMDGPU_INFO_VCE_CLOCK_TABLE: {
-		unsigned i;
+		unsigned int i;
 		struct drm_amdgpu_info_vce_clock_table vce_clk_table = {};
 		struct amd_vce_state *vce_state;
 
@@ -975,7 +985,7 @@
 
 	r = pm_runtime_get_sync(dev->dev);
 	if (r < 0)
-		return r;
+		goto pm_put;
 
 	fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL);
 	if (unlikely(!fpriv)) {
@@ -1026,6 +1036,7 @@
 
 out_suspend:
 	pm_runtime_mark_last_busy(dev->dev);
+pm_put:
 	pm_runtime_put_autosuspend(dev->dev);
 
 	return r;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
@@ -200,7 +200,7 @@
 		c++;
 	}
 
-	BUG_ON(c >= AMDGPU_BO_MAX_PLACEMENTS);
+	BUG_ON(c > AMDGPU_BO_MAX_PLACEMENTS);
 
 	placement->num_placement = c;
 	placement->placement = places;
@@ -343,6 +343,67 @@
 }
 
 /**
+ * amdgpu_bo_create_kernel_at - create BO for kernel use at specific location
+ *
+ * @adev: amdgpu device object
+ * @offset: offset of the BO
+ * @size: size of the BO
+ * @domain: where to place it
+ * @bo_ptr:  used to initialize BOs in structures
+ * @cpu_addr: optional CPU address mapping
+ *
+ * Creates a kernel BO at a specific offset in the address space of the domain.
+ *
+ * Returns:
+ * 0 on success, negative error code otherwise.
+ */
+int amdgpu_bo_create_kernel_at(struct amdgpu_device *adev,
+			       uint64_t offset, uint64_t size, uint32_t domain,
+			       struct amdgpu_bo **bo_ptr, void **cpu_addr)
+{
+	struct ttm_operation_ctx ctx = { false, false };
+	unsigned int i;
+	int r;
+
+	offset &= PAGE_MASK;
+	size = ALIGN(size, PAGE_SIZE);
+
+	r = amdgpu_bo_create_reserved(adev, size, PAGE_SIZE, domain, bo_ptr,
+				      NULL, NULL);
+	if (r)
+		return r;
+
+	/*
+	 * Remove the original mem node and create a new one at the request
+	 * position.
+	 */
+	for (i = 0; i < (*bo_ptr)->placement.num_placement; ++i) {
+		(*bo_ptr)->placements[i].fpfn = offset >> PAGE_SHIFT;
+		(*bo_ptr)->placements[i].lpfn = (offset + size) >> PAGE_SHIFT;
+	}
+
+	ttm_bo_mem_put(&(*bo_ptr)->tbo, &(*bo_ptr)->tbo.mem);
+	r = ttm_bo_mem_space(&(*bo_ptr)->tbo, &(*bo_ptr)->placement,
+			     &(*bo_ptr)->tbo.mem, &ctx);
+	if (r)
+		goto error;
+
+	if (cpu_addr) {
+		r = amdgpu_bo_kmap(*bo_ptr, cpu_addr);
+		if (r)
+			goto error;
+	}
+
+	amdgpu_bo_unreserve(*bo_ptr);
+	return 0;
+
+error:
+	amdgpu_bo_unreserve(*bo_ptr);
+	amdgpu_bo_unref(bo_ptr);
+	return r;
+}
+
+/**
  * amdgpu_bo_free_kernel - free BO for kernel use
  *
  * @bo: amdgpu BO to free
@@ -831,6 +892,10 @@
 	if (WARN_ON_ONCE(min_offset > max_offset))
 		return -EINVAL;
 
+	/* Check domain to be pinned to against preferred domains */
+	if (bo->preferred_domains & domain)
+		domain = bo->preferred_domains & domain;
+
 	/* A shared bo cannot be migrated to VRAM */
 	if (bo->prime_shared_count) {
 		if (domain & AMDGPU_GEM_DOMAIN_GTT)
@@ -1244,7 +1309,8 @@
 	    !(abo->flags & AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE))
 		return;
 
-	dma_resv_lock(bo->base.resv, NULL);
+	if (WARN_ON_ONCE(!dma_resv_trylock(bo->base.resv)))
+		return;
 
 	r = amdgpu_fill_buffer(abo, AMDGPU_POISON, bo->base.resv, &fence);
 	if (!WARN_ON(r)) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
@@ -237,6 +237,9 @@
 			    unsigned long size, int align,
 			    u32 domain, struct amdgpu_bo **bo_ptr,
 			    u64 *gpu_addr, void **cpu_addr);
+int amdgpu_bo_create_kernel_at(struct amdgpu_device *adev,
+			       uint64_t offset, uint64_t size, uint32_t domain,
+			       struct amdgpu_bo **bo_ptr, void **cpu_addr);
 void amdgpu_bo_free_kernel(struct amdgpu_bo **bo, u64 *gpu_addr,
 			   void **cpu_addr);
 int amdgpu_bo_kmap(struct amdgpu_bo *bo, void **ptr);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
@@ -90,7 +90,8 @@
 			adev->pm.ac_power = true;
 		else
 			adev->pm.ac_power = false;
-		if (adev->powerplay.pp_funcs->enable_bapm)
+		if (adev->powerplay.pp_funcs &&
+		    adev->powerplay.pp_funcs->enable_bapm)
 			amdgpu_dpm_enable_bapm(adev, adev->pm.ac_power);
 		mutex_unlock(&adev->pm.mutex);
 	}
@@ -369,6 +370,15 @@
 	if (current_level == level)
 		return count;
 
+	if (adev->asic_type == CHIP_RAVEN) {
+		if (adev->rev_id < 8) {
+			if (current_level != AMD_DPM_FORCED_LEVEL_MANUAL && level == AMD_DPM_FORCED_LEVEL_MANUAL)
+				amdgpu_gfx_off_ctrl(adev, false);
+			else if (current_level == AMD_DPM_FORCED_LEVEL_MANUAL && level != AMD_DPM_FORCED_LEVEL_MANUAL)
+				amdgpu_gfx_off_ctrl(adev, true);
+		}
+	}
+
 	/* profile_exit setting is valid only when current mode is in profile mode */
 	if (!(current_level & (AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD |
 	    AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK |
@@ -415,8 +425,11 @@
 		ret = smu_get_power_num_states(&adev->smu, &data);
 		if (ret)
 			return ret;
-	} else if (adev->powerplay.pp_funcs->get_pp_num_states)
+	} else if (adev->powerplay.pp_funcs->get_pp_num_states) {
 		amdgpu_dpm_get_pp_num_states(adev, &data);
+	} else {
+		memset(&data, 0, sizeof(data));
+	}
 
 	buf_len = snprintf(buf, PAGE_SIZE, "states: %d\n", data.nums);
 	for (i = 0; i < data.nums; i++)
@@ -857,7 +870,7 @@
 static ssize_t amdgpu_read_mask(const char *buf, size_t count, uint32_t *mask)
 {
 	int ret;
-	long level;
+	unsigned long level;
 	char *sub_str = NULL;
 	char *tmp;
 	char buf_cpy[AMDGPU_MASK_BUF_MAX + 1];
@@ -873,8 +886,8 @@
 	while (tmp[0]) {
 		sub_str = strsep(&tmp, delimiter);
 		if (strlen(sub_str)) {
-			ret = kstrtol(sub_str, 0, &level);
-			if (ret)
+			ret = kstrtoul(sub_str, 0, &level);
+			if (ret || level > 31)
 				return -EINVAL;
 			*mask |= 1 << level;
 		} else
@@ -2088,7 +2101,7 @@
 	if (r)
 		return r;
 
-	return snprintf(buf, PAGE_SIZE, "%d\n", sclk * 10 * 1000);
+	return snprintf(buf, PAGE_SIZE, "%u\n", sclk * 10 * 1000);
 }
 
 static ssize_t amdgpu_hwmon_show_sclk_label(struct device *dev,
@@ -2118,7 +2131,7 @@
 	if (r)
 		return r;
 
-	return snprintf(buf, PAGE_SIZE, "%d\n", mclk * 10 * 1000);
+	return snprintf(buf, PAGE_SIZE, "%u\n", mclk * 10 * 1000);
 }
 
 static ssize_t amdgpu_hwmon_show_mclk_label(struct device *dev,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
@@ -65,12 +65,6 @@
 /* inject address is 52 bits */
 #define	RAS_UMC_INJECT_ADDR_LIMIT	(0x1ULL << 52)
 
-static int amdgpu_ras_reserve_vram(struct amdgpu_device *adev,
-		uint64_t offset, uint64_t size,
-		struct amdgpu_bo **bo_ptr);
-static int amdgpu_ras_release_vram(struct amdgpu_device *adev,
-		struct amdgpu_bo **bo_ptr);
-
 static ssize_t amdgpu_ras_debugfs_read(struct file *f, char __user *buf,
 					size_t size, loff_t *pos)
 {
@@ -600,6 +594,9 @@
 	if (!obj)
 		return -EINVAL;
 
+	if (!info || info->head.block == AMDGPU_RAS_BLOCK_COUNT)
+		return -EINVAL;
+
 	switch (info->head.block) {
 	case AMDGPU_RAS_BLOCK__UMC:
 		if (adev->umc.funcs->query_ras_error_count)
@@ -1056,12 +1053,15 @@
 int amdgpu_ras_interrupt_dispatch(struct amdgpu_device *adev,
 		struct ras_dispatch_if *info)
 {
-	struct ras_manager *obj = amdgpu_ras_find_obj(adev, &info->head);
-	struct ras_ih_data *data = &obj->ih_data;
+	struct ras_manager *obj;
+	struct ras_ih_data *data;
 
+	obj = amdgpu_ras_find_obj(adev, &info->head);
 	if (!obj)
 		return -EINVAL;
 
+	data = &obj->ih_data;
+
 	if (data->inuse == 0)
 		return 0;
 
@@ -1214,75 +1214,6 @@
 	atomic_set(&ras->in_recovery, 0);
 }
 
-static int amdgpu_ras_release_vram(struct amdgpu_device *adev,
-		struct amdgpu_bo **bo_ptr)
-{
-	/* no need to free it actually. */
-	amdgpu_bo_free_kernel(bo_ptr, NULL, NULL);
-	return 0;
-}
-
-/* reserve vram with size@offset */
-static int amdgpu_ras_reserve_vram(struct amdgpu_device *adev,
-		uint64_t offset, uint64_t size,
-		struct amdgpu_bo **bo_ptr)
-{
-	struct ttm_operation_ctx ctx = { false, false };
-	struct amdgpu_bo_param bp;
-	int r = 0;
-	int i;
-	struct amdgpu_bo *bo;
-
-	if (bo_ptr)
-		*bo_ptr = NULL;
-	memset(&bp, 0, sizeof(bp));
-	bp.size = size;
-	bp.byte_align = PAGE_SIZE;
-	bp.domain = AMDGPU_GEM_DOMAIN_VRAM;
-	bp.flags = AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS |
-		AMDGPU_GEM_CREATE_NO_CPU_ACCESS;
-	bp.type = ttm_bo_type_kernel;
-	bp.resv = NULL;
-
-	r = amdgpu_bo_create(adev, &bp, &bo);
-	if (r)
-		return -EINVAL;
-
-	r = amdgpu_bo_reserve(bo, false);
-	if (r)
-		goto error_reserve;
-
-	offset = ALIGN(offset, PAGE_SIZE);
-	for (i = 0; i < bo->placement.num_placement; ++i) {
-		bo->placements[i].fpfn = offset >> PAGE_SHIFT;
-		bo->placements[i].lpfn = (offset + size) >> PAGE_SHIFT;
-	}
-
-	ttm_bo_mem_put(&bo->tbo, &bo->tbo.mem);
-	r = ttm_bo_mem_space(&bo->tbo, &bo->placement, &bo->tbo.mem, &ctx);
-	if (r)
-		goto error_pin;
-
-	r = amdgpu_bo_pin_restricted(bo,
-			AMDGPU_GEM_DOMAIN_VRAM,
-			offset,
-			offset + size);
-	if (r)
-		goto error_pin;
-
-	if (bo_ptr)
-		*bo_ptr = bo;
-
-	amdgpu_bo_unreserve(bo);
-	return r;
-
-error_pin:
-	amdgpu_bo_unreserve(bo);
-error_reserve:
-	amdgpu_bo_unref(&bo);
-	return r;
-}
-
 /* alloc/realloc bps array */
 static int amdgpu_ras_realloc_eh_data_space(struct amdgpu_device *adev,
 		struct ras_err_handler_data *data, int pages)
@@ -1345,7 +1276,7 @@
 	struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
 	struct ras_err_handler_data *data;
 	uint64_t bp;
-	struct amdgpu_bo *bo;
+	struct amdgpu_bo *bo = NULL;
 	int i;
 
 	if (!con || !con->eh_data)
@@ -1359,12 +1290,14 @@
 	for (i = data->last_reserved; i < data->count; i++) {
 		bp = data->bps[i].bp;
 
-		if (amdgpu_ras_reserve_vram(adev, bp << PAGE_SHIFT,
-					PAGE_SIZE, &bo))
+		if (amdgpu_bo_create_kernel_at(adev, bp << PAGE_SHIFT, PAGE_SIZE,
+					       AMDGPU_GEM_DOMAIN_VRAM,
+					       &bo, NULL))
 			DRM_ERROR("RAS ERROR: reserve vram %llx fail\n", bp);
 
 		data->bps[i].bo = bo;
 		data->last_reserved = i + 1;
+		bo = NULL;
 	}
 out:
 	mutex_unlock(&con->recovery_lock);
@@ -1390,7 +1323,7 @@
 	for (i = data->last_reserved - 1; i >= 0; i--) {
 		bo = data->bps[i].bo;
 
-		amdgpu_ras_release_vram(adev, &bo);
+		amdgpu_bo_free_kernel(&bo, NULL, NULL);
 
 		data->bps[i].bo = bo;
 		data->last_reserved = i;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
@@ -138,7 +138,7 @@
 		return ret;
 	}
 
-	__decode_table_header_from_buff(hdr, &buff[2]);
+	__decode_table_header_from_buff(hdr, buff);
 
 	if (hdr->header == EEPROM_TABLE_HDR_VAL) {
 		control->num_recs = (hdr->tbl_size - EEPROM_TABLE_HEADER_SIZE) /
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
@@ -437,8 +437,9 @@
 					size_t size, loff_t *pos)
 {
 	struct amdgpu_ring *ring = file_inode(f)->i_private;
-	int r, i;
 	uint32_t value, result, early[3];
+	loff_t i;
+	int r;
 
 	if (*pos & 3 || size & 3)
 		return -EINVAL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_rlc.c
@@ -124,13 +124,12 @@
  */
 int amdgpu_gfx_rlc_init_csb(struct amdgpu_device *adev)
 {
-	volatile u32 *dst_ptr;
 	u32 dws;
 	int r;
 
 	/* allocate clear state block */
 	adev->gfx.rlc.clear_state_size = dws = adev->gfx.rlc.funcs->get_csb_size(adev);
-	r = amdgpu_bo_create_reserved(adev, dws * 4, PAGE_SIZE,
+	r = amdgpu_bo_create_kernel(adev, dws * 4, PAGE_SIZE,
 				      AMDGPU_GEM_DOMAIN_VRAM,
 				      &adev->gfx.rlc.clear_state_obj,
 				      &adev->gfx.rlc.clear_state_gpu_addr,
@@ -141,13 +140,6 @@
 		return r;
 	}
 
-	/* set up the cs buffer */
-	dst_ptr = adev->gfx.rlc.cs_ptr;
-	adev->gfx.rlc.funcs->get_csb_buffer(adev, dst_ptr);
-	amdgpu_bo_kunmap(adev->gfx.rlc.clear_state_obj);
-	amdgpu_bo_unpin(adev->gfx.rlc.clear_state_obj);
-	amdgpu_bo_unreserve(adev->gfx.rlc.clear_state_obj);
-
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c
@@ -58,6 +58,7 @@
 {
 	struct fd f = fdget(fd);
 	struct amdgpu_fpriv *fpriv;
+	struct amdgpu_ctx_mgr *mgr;
 	struct amdgpu_ctx *ctx;
 	uint32_t id;
 	int r;
@@ -71,8 +72,11 @@
 		return r;
 	}
 
-	idr_for_each_entry(&fpriv->ctx_mgr.ctx_handles, ctx, id)
+	mgr = &fpriv->ctx_mgr;
+	mutex_lock(&mgr->lock);
+	idr_for_each_entry(&mgr->ctx_handles, ctx, id)
 		amdgpu_ctx_priority_override(ctx, priority);
+	mutex_unlock(&mgr->lock);
 
 	fdput(f);
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
@@ -218,7 +218,8 @@
 		 */
 		fence_owner = amdgpu_sync_get_owner(f);
 		if (fence_owner == AMDGPU_FENCE_OWNER_KFD &&
-		    owner != AMDGPU_FENCE_OWNER_UNDEFINED)
+		    owner != AMDGPU_FENCE_OWNER_UNDEFINED &&
+	    owner != AMDGPU_FENCE_OWNER_KFD)
 			continue;
 
 		if (amdgpu_sync_same_dev(adev, f)) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_test.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_test.c
@@ -138,6 +138,7 @@
 		}
 
 		dma_fence_put(fence);
+		fence = NULL;
 
 		r = amdgpu_bo_kmap(vram_obj, &vram_map);
 		if (r) {
@@ -183,6 +184,7 @@
 		}
 
 		dma_fence_put(fence);
+		fence = NULL;
 
 		r = amdgpu_bo_kmap(gtt_obj[i], &gtt_map);
 		if (r) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h
@@ -21,7 +21,7 @@
  *
  */
 
-#if !defined(_AMDGPU_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+#if !defined(_AMDGPU_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
 #define _AMDGPU_TRACE_H_
 
 #include <linux/stringify.h>
@@ -170,7 +170,7 @@
 			     __field(unsigned int, context)
 			     __field(unsigned int, seqno)
 			     __field(struct dma_fence *, fence)
-			     __field(char *, ring_name)
+			     __string(ring, to_amdgpu_ring(job->base.sched)->name)
 			     __field(u32, num_ibs)
 			     ),
 
@@ -179,12 +179,12 @@
 			   __assign_str(timeline, AMDGPU_JOB_GET_TIMELINE_NAME(job))
 			   __entry->context = job->base.s_fence->finished.context;
 			   __entry->seqno = job->base.s_fence->finished.seqno;
-			   __entry->ring_name = to_amdgpu_ring(job->base.sched)->name;
+			   __assign_str(ring, to_amdgpu_ring(job->base.sched)->name)
 			   __entry->num_ibs = job->num_ibs;
 			   ),
 	    TP_printk("sched_job=%llu, timeline=%s, context=%u, seqno=%u, ring_name=%s, num_ibs=%u",
 		      __entry->sched_job_id, __get_str(timeline), __entry->context,
-		      __entry->seqno, __entry->ring_name, __entry->num_ibs)
+		      __entry->seqno, __get_str(ring), __entry->num_ibs)
 );
 
 TRACE_EVENT(amdgpu_sched_run_job,
@@ -195,7 +195,7 @@
 			     __string(timeline, AMDGPU_JOB_GET_TIMELINE_NAME(job))
 			     __field(unsigned int, context)
 			     __field(unsigned int, seqno)
-			     __field(char *, ring_name)
+			     __string(ring, to_amdgpu_ring(job->base.sched)->name)
 			     __field(u32, num_ibs)
 			     ),
 
@@ -204,12 +204,12 @@
 			   __assign_str(timeline, AMDGPU_JOB_GET_TIMELINE_NAME(job))
 			   __entry->context = job->base.s_fence->finished.context;
 			   __entry->seqno = job->base.s_fence->finished.seqno;
-			   __entry->ring_name = to_amdgpu_ring(job->base.sched)->name;
+			   __assign_str(ring, to_amdgpu_ring(job->base.sched)->name)
 			   __entry->num_ibs = job->num_ibs;
 			   ),
 	    TP_printk("sched_job=%llu, timeline=%s, context=%u, seqno=%u, ring_name=%s, num_ibs=%u",
 		      __entry->sched_job_id, __get_str(timeline), __entry->context,
-		      __entry->seqno, __entry->ring_name, __entry->num_ibs)
+		      __entry->seqno, __get_str(ring), __entry->num_ibs)
 );
 
 
@@ -468,7 +468,7 @@
 	    TP_PROTO(struct amdgpu_job *sched_job, struct dma_fence *fence),
 	    TP_ARGS(sched_job, fence),
 	    TP_STRUCT__entry(
-			     __field(const char *,name)
+			     __string(ring, sched_job->base.sched->name);
 			     __field(uint64_t, id)
 			     __field(struct dma_fence *, fence)
 			     __field(uint64_t, ctx)
@@ -476,14 +476,14 @@
 			     ),
 
 	    TP_fast_assign(
-			   __entry->name = sched_job->base.sched->name;
+			   __assign_str(ring, sched_job->base.sched->name)
 			   __entry->id = sched_job->base.id;
 			   __entry->fence = fence;
 			   __entry->ctx = fence->context;
 			   __entry->seqno = fence->seqno;
 			   ),
 	    TP_printk("job ring=%s, id=%llu, need pipe sync to fence=%p, context=%llu, seq=%u",
-		      __entry->name, __entry->id,
+		      __get_str(ring), __entry->id,
 		      __entry->fence, __entry->ctx,
 		      __entry->seqno)
 );
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -35,6 +35,7 @@
 #include <linux/hmm.h>
 #include <linux/pagemap.h>
 #include <linux/sched/task.h>
+#include <linux/sched/mm.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
 #include <linux/swap.h>
@@ -788,7 +789,7 @@
 	struct hmm_mirror *mirror = bo->mn ? &bo->mn->mirror : NULL;
 	struct ttm_tt *ttm = bo->tbo.ttm;
 	struct amdgpu_ttm_tt *gtt = (void *)ttm;
-	struct mm_struct *mm = gtt->usertask->mm;
+	struct mm_struct *mm;
 	unsigned long start = gtt->userptr;
 	struct vm_area_struct *vma;
 	struct hmm_range *range;
@@ -796,25 +797,14 @@
 	uint64_t *pfns;
 	int r = 0;
 
-	if (!mm) /* Happens during process shutdown */
-		return -ESRCH;
-
 	if (unlikely(!mirror)) {
 		DRM_DEBUG_DRIVER("Failed to get hmm_mirror\n");
-		r = -EFAULT;
-		goto out;
+		return -EFAULT;
 	}
 
-	vma = find_vma(mm, start);
-	if (unlikely(!vma || start < vma->vm_start)) {
-		r = -EFAULT;
-		goto out;
-	}
-	if (unlikely((gtt->userflags & AMDGPU_GEM_USERPTR_ANONONLY) &&
-		vma->vm_file)) {
-		r = -EPERM;
-		goto out;
-	}
+	mm = mirror->hmm->mmu_notifier.mm;
+	if (!mmget_not_zero(mm)) /* Happens during process shutdown */
+		return -ESRCH;
 
 	range = kzalloc(sizeof(*range), GFP_KERNEL);
 	if (unlikely(!range)) {
@@ -847,6 +837,17 @@
 	hmm_range_wait_until_valid(range, HMM_RANGE_DEFAULT_TIMEOUT);
 
 	down_read(&mm->mmap_sem);
+	vma = find_vma(mm, start);
+	if (unlikely(!vma || start < vma->vm_start)) {
+		r = -EFAULT;
+		goto out_unlock;
+	}
+	if (unlikely((gtt->userflags & AMDGPU_GEM_USERPTR_ANONONLY) &&
+		vma->vm_file)) {
+		r = -EPERM;
+		goto out_unlock;
+	}
+
 	r = hmm_range_fault(range, 0);
 	up_read(&mm->mmap_sem);
 
@@ -865,15 +866,19 @@
 	}
 
 	gtt->range = range;
+	mmput(mm);
 
 	return 0;
 
+out_unlock:
+	up_read(&mm->mmap_sem);
 out_free_pfns:
 	hmm_range_unregister(range);
 	kvfree(pfns);
 out_free_ranges:
 	kfree(range);
 out:
+	mmput(mm);
 	return r;
 }
 
@@ -962,6 +967,7 @@
 
 release_sg:
 	kfree(ttm->sg);
+	ttm->sg = NULL;
 	return r;
 }
 
@@ -978,7 +984,7 @@
 		DMA_BIDIRECTIONAL : DMA_TO_DEVICE;
 
 	/* double check that we don't free the table twice */
-	if (!ttm->sg->sgl)
+	if (!ttm->sg || !ttm->sg->sgl)
 		return;
 
 	/* unmap the pages mapped to the device */
@@ -1294,6 +1300,7 @@
 	if (gtt && gtt->userptr) {
 		amdgpu_ttm_tt_set_user_pages(ttm, NULL);
 		kfree(ttm->sg);
+		ttm->sg = NULL;
 		ttm->page_flags &= ~TTM_PAGE_FLAG_SG;
 		return;
 	}
@@ -1634,81 +1641,25 @@
  */
 static int amdgpu_ttm_fw_reserve_vram_init(struct amdgpu_device *adev)
 {
-	struct ttm_operation_ctx ctx = { false, false };
-	struct amdgpu_bo_param bp;
-	int r = 0;
-	int i;
-	u64 vram_size = adev->gmc.visible_vram_size;
-	u64 offset = adev->fw_vram_usage.start_offset;
-	u64 size = adev->fw_vram_usage.size;
-	struct amdgpu_bo *bo;
-
-	memset(&bp, 0, sizeof(bp));
-	bp.size = adev->fw_vram_usage.size;
-	bp.byte_align = PAGE_SIZE;
-	bp.domain = AMDGPU_GEM_DOMAIN_VRAM;
-	bp.flags = AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED |
-		AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
-	bp.type = ttm_bo_type_kernel;
-	bp.resv = NULL;
+	uint64_t vram_size = adev->gmc.visible_vram_size;
+	int r;
+
 	adev->fw_vram_usage.va = NULL;
 	adev->fw_vram_usage.reserved_bo = NULL;
 
-	if (adev->fw_vram_usage.size > 0 &&
-		adev->fw_vram_usage.size <= vram_size) {
-
-		r = amdgpu_bo_create(adev, &bp,
-				     &adev->fw_vram_usage.reserved_bo);
-		if (r)
-			goto error_create;
-
-		r = amdgpu_bo_reserve(adev->fw_vram_usage.reserved_bo, false);
-		if (r)
-			goto error_reserve;
-
-		/* remove the original mem node and create a new one at the
-		 * request position
-		 */
-		bo = adev->fw_vram_usage.reserved_bo;
-		offset = ALIGN(offset, PAGE_SIZE);
-		for (i = 0; i < bo->placement.num_placement; ++i) {
-			bo->placements[i].fpfn = offset >> PAGE_SHIFT;
-			bo->placements[i].lpfn = (offset + size) >> PAGE_SHIFT;
-		}
-
-		ttm_bo_mem_put(&bo->tbo, &bo->tbo.mem);
-		r = ttm_bo_mem_space(&bo->tbo, &bo->placement,
-				     &bo->tbo.mem, &ctx);
-		if (r)
-			goto error_pin;
-
-		r = amdgpu_bo_pin_restricted(adev->fw_vram_usage.reserved_bo,
-			AMDGPU_GEM_DOMAIN_VRAM,
-			adev->fw_vram_usage.start_offset,
-			(adev->fw_vram_usage.start_offset +
-			adev->fw_vram_usage.size));
-		if (r)
-			goto error_pin;
-		r = amdgpu_bo_kmap(adev->fw_vram_usage.reserved_bo,
-			&adev->fw_vram_usage.va);
-		if (r)
-			goto error_kmap;
-
-		amdgpu_bo_unreserve(adev->fw_vram_usage.reserved_bo);
-	}
-	return r;
+	if (adev->fw_vram_usage.size == 0 ||
+	    adev->fw_vram_usage.size > vram_size)
+		return 0;
 
-error_kmap:
-	amdgpu_bo_unpin(adev->fw_vram_usage.reserved_bo);
-error_pin:
-	amdgpu_bo_unreserve(adev->fw_vram_usage.reserved_bo);
-error_reserve:
-	amdgpu_bo_unref(&adev->fw_vram_usage.reserved_bo);
-error_create:
-	adev->fw_vram_usage.va = NULL;
-	adev->fw_vram_usage.reserved_bo = NULL;
+	return amdgpu_bo_create_kernel_at(adev,
+					  adev->fw_vram_usage.start_offset,
+					  adev->fw_vram_usage.size,
+					  AMDGPU_GEM_DOMAIN_VRAM,
+					  &adev->fw_vram_usage.reserved_bo,
+					  &adev->fw_vram_usage.va);
 	return r;
 }
+
 /**
  * amdgpu_ttm_init - Init the memory management (ttm) as well as various
  * gtt/vram related fields.
@@ -1727,6 +1678,7 @@
 
 	mutex_init(&adev->mman.gtt_window_lock);
 
+	dma_set_max_seg_size(adev->dev, UINT_MAX);
 	/* No others user of address space so set it to 0 */
 	r = ttm_bo_device_init(&adev->mman.bdev,
 			       &amdgpu_bo_driver,
@@ -1781,6 +1733,20 @@
 				    NULL, &stolen_vga_buf);
 	if (r)
 		return r;
+
+	/*
+	 * reserve one TMR (64K) memory at the top of VRAM which holds
+	 * IP Discovery data and is protected by PSP.
+	 */
+	r = amdgpu_bo_create_kernel_at(adev,
+				       adev->gmc.real_vram_size - DISCOVERY_TMR_SIZE,
+				       DISCOVERY_TMR_SIZE,
+				       AMDGPU_GEM_DOMAIN_VRAM,
+				       &adev->discovery_memory,
+				       NULL);
+	if (r)
+		return r;
+
 	DRM_INFO("amdgpu: %uM of VRAM memory ready\n",
 		 (unsigned) (adev->gmc.real_vram_size / (1024 * 1024)));
 
@@ -1845,6 +1811,9 @@
 	void *stolen_vga_buf;
 	/* return the VGA stolen memory (if any) back to VRAM */
 	amdgpu_bo_free_kernel(&adev->stolen_vga_memory, NULL, &stolen_vga_buf);
+
+	/* return the IP Discovery TMR memory back to VRAM */
+	amdgpu_bo_free_kernel(&adev->discovery_memory, NULL, NULL);
 }
 
 /**
@@ -2008,7 +1977,7 @@
 	unsigned i;
 	int r;
 
-	if (direct_submit && !ring->sched.ready) {
+	if (!direct_submit && !ring->sched.ready) {
 		DRM_ERROR("Trying to move memory with ring turned off.\n");
 		return -EINVAL;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
@@ -568,8 +568,7 @@
 
 void amdgpu_ucode_free_bo(struct amdgpu_device *adev)
 {
-	if (adev->firmware.load_type != AMDGPU_FW_LOAD_DIRECT)
-		amdgpu_bo_free_kernel(&adev->firmware.fw_buf,
+	amdgpu_bo_free_kernel(&adev->firmware.fw_buf,
 		&adev->firmware.fw_buf_mc,
 		&adev->firmware.fw_buf_ptr);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
@@ -231,7 +231,7 @@
 		if ((adev->asic_type == CHIP_POLARIS10 ||
 		     adev->asic_type == CHIP_POLARIS11) &&
 		    (adev->uvd.fw_version < FW_1_66_16))
-			DRM_ERROR("POLARIS10/11 UVD firmware version %hu.%hu is too old.\n",
+			DRM_ERROR("POLARIS10/11 UVD firmware version %u.%u is too old.\n",
 				  version_major, version_minor);
 	} else {
 		unsigned int enc_major, enc_minor, dec_minor;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
@@ -213,15 +213,15 @@
 
 	drm_sched_entity_destroy(&adev->vce.entity);
 
-	amdgpu_bo_free_kernel(&adev->vce.vcpu_bo, &adev->vce.gpu_addr,
-		(void **)&adev->vce.cpu_addr);
-
 	for (i = 0; i < adev->vce.num_rings; i++)
 		amdgpu_ring_fini(&adev->vce.ring[i]);
 
 	release_firmware(adev->vce.fw);
 	mutex_destroy(&adev->vce.idle_mutex);
 
+	amdgpu_bo_free_kernel(&adev->vce.vcpu_bo, &adev->vce.gpu_addr,
+		(void **)&adev->vce.cpu_addr);
+
 	return 0;
 }
 
@@ -715,7 +715,8 @@
 	uint32_t created = 0;
 	uint32_t allocated = 0;
 	uint32_t tmp, handle = 0;
-	uint32_t *size = &tmp;
+	uint32_t dummy = 0xffffffff;
+	uint32_t *size = &dummy;
 	unsigned idx;
 	int i, r = 0;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
@@ -55,11 +55,9 @@
 MODULE_FIRMWARE(FIRMWARE_RAVEN);
 MODULE_FIRMWARE(FIRMWARE_PICASSO);
 MODULE_FIRMWARE(FIRMWARE_RAVEN2);
-MODULE_FIRMWARE(FIRMWARE_ARCTURUS);
 MODULE_FIRMWARE(FIRMWARE_RENOIR);
 MODULE_FIRMWARE(FIRMWARE_NAVI10);
 MODULE_FIRMWARE(FIRMWARE_NAVI14);
-MODULE_FIRMWARE(FIRMWARE_NAVI12);
 
 static void amdgpu_vcn_idle_work_handler(struct work_struct *work);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h
@@ -48,6 +48,8 @@
 	uint64_t data[AMDGPU_VF_ERROR_ENTRY_SIZE];
 };
 
+enum idh_request;
+
 /**
  * struct amdgpu_virt_ops - amdgpu device virt operations
  */
@@ -56,7 +58,8 @@
 	int (*rel_full_gpu)(struct amdgpu_device *adev, bool init);
 	int (*reset_gpu)(struct amdgpu_device *adev);
 	int (*wait_reset)(struct amdgpu_device *adev);
-	void (*trans_msg)(struct amdgpu_device *adev, u32 req, u32 data1, u32 data2, u32 data3);
+	void (*trans_msg)(struct amdgpu_device *adev, enum idh_request req,
+			  u32 data1, u32 data2, u32 data3);
 	int (*get_pp_clk)(struct amdgpu_device *adev, u32 type, char *buf);
 	int (*force_dpm_level)(struct amdgpu_device *adev, u32 level);
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -1034,10 +1034,8 @@
 		id->oa_base != job->oa_base ||
 		id->oa_size != job->oa_size);
 	bool vm_flush_needed = job->vm_needs_flush;
-	bool pasid_mapping_needed = id->pasid != job->pasid ||
-		!id->pasid_mapping ||
-		!dma_fence_is_signaled(id->pasid_mapping);
 	struct dma_fence *fence = NULL;
+	bool pasid_mapping_needed = false;
 	unsigned patch_offset = 0;
 	int r;
 
@@ -1047,6 +1045,12 @@
 		pasid_mapping_needed = true;
 	}
 
+	mutex_lock(&id_mgr->lock);
+	if (id->pasid != job->pasid || !id->pasid_mapping ||
+	    !dma_fence_is_signaled(id->pasid_mapping))
+		pasid_mapping_needed = true;
+	mutex_unlock(&id_mgr->lock);
+
 	gds_switch_needed &= !!ring->funcs->emit_gds_switch;
 	vm_flush_needed &= !!ring->funcs->emit_vm_flush  &&
 			job->vm_pd_addr != AMDGPU_BO_INVALID_OFFSET;
@@ -1086,9 +1090,11 @@
 	}
 
 	if (pasid_mapping_needed) {
+		mutex_lock(&id_mgr->lock);
 		id->pasid = job->pasid;
 		dma_fence_put(id->pasid_mapping);
 		id->pasid_mapping = dma_fence_get(fence);
+		mutex_unlock(&id_mgr->lock);
 	}
 	dma_fence_put(fence);
 
@@ -2089,6 +2095,37 @@
 	trace_amdgpu_vm_bo_map(bo_va, mapping);
 }
 
+/* Validate operation parameters to prevent potential abuse */
+static int amdgpu_vm_verify_parameters(struct amdgpu_device *adev,
+					  struct amdgpu_bo *bo,
+					  uint64_t saddr,
+					  uint64_t offset,
+					  uint64_t size)
+{
+	uint64_t tmp, lpfn;
+
+	if (saddr & AMDGPU_GPU_PAGE_MASK
+	    || offset & AMDGPU_GPU_PAGE_MASK
+	    || size & AMDGPU_GPU_PAGE_MASK)
+		return -EINVAL;
+
+	if (check_add_overflow(saddr, size, &tmp)
+	    || check_add_overflow(offset, size, &tmp)
+	    || size == 0 /* which also leads to end < begin */)
+		return -EINVAL;
+
+	/* make sure object fit at this offset */
+	if (bo && offset + size > amdgpu_bo_size(bo))
+		return -EINVAL;
+
+	/* Ensure last pfn not exceed max_pfn */
+	lpfn = (saddr + size - 1) >> AMDGPU_GPU_PAGE_SHIFT;
+	if (lpfn >= adev->vm_manager.max_pfn)
+		return -EINVAL;
+
+	return 0;
+}
+
 /**
  * amdgpu_vm_bo_map - map bo inside a vm
  *
@@ -2115,20 +2152,14 @@
 	struct amdgpu_bo *bo = bo_va->base.bo;
 	struct amdgpu_vm *vm = bo_va->base.vm;
 	uint64_t eaddr;
+	int r;
 
-	/* validate the parameters */
-	if (saddr & AMDGPU_GPU_PAGE_MASK || offset & AMDGPU_GPU_PAGE_MASK ||
-	    size == 0 || size & AMDGPU_GPU_PAGE_MASK)
-		return -EINVAL;
-
-	/* make sure object fit at this offset */
-	eaddr = saddr + size - 1;
-	if (saddr >= eaddr ||
-	    (bo && offset + size > amdgpu_bo_size(bo)))
-		return -EINVAL;
+	r = amdgpu_vm_verify_parameters(adev, bo, saddr, offset, size);
+	if (r)
+		return r;
 
 	saddr /= AMDGPU_GPU_PAGE_SIZE;
-	eaddr /= AMDGPU_GPU_PAGE_SIZE;
+	eaddr = saddr + (size - 1) / AMDGPU_GPU_PAGE_SIZE;
 
 	tmp = amdgpu_vm_it_iter_first(&vm->va, saddr, eaddr);
 	if (tmp) {
@@ -2181,16 +2212,9 @@
 	uint64_t eaddr;
 	int r;
 
-	/* validate the parameters */
-	if (saddr & AMDGPU_GPU_PAGE_MASK || offset & AMDGPU_GPU_PAGE_MASK ||
-	    size == 0 || size & AMDGPU_GPU_PAGE_MASK)
-		return -EINVAL;
-
-	/* make sure object fit at this offset */
-	eaddr = saddr + size - 1;
-	if (saddr >= eaddr ||
-	    (bo && offset + size > amdgpu_bo_size(bo)))
-		return -EINVAL;
+	r = amdgpu_vm_verify_parameters(adev, bo, saddr, offset, size);
+	if (r)
+		return r;
 
 	/* Allocate all the needed memory */
 	mapping = kmalloc(sizeof(*mapping), GFP_KERNEL);
@@ -2204,7 +2228,7 @@
 	}
 
 	saddr /= AMDGPU_GPU_PAGE_SIZE;
-	eaddr /= AMDGPU_GPU_PAGE_SIZE;
+	eaddr = saddr + (size - 1) / AMDGPU_GPU_PAGE_SIZE;
 
 	mapping->start = saddr;
 	mapping->last = eaddr;
@@ -2291,10 +2315,14 @@
 	struct amdgpu_bo_va_mapping *before, *after, *tmp, *next;
 	LIST_HEAD(removed);
 	uint64_t eaddr;
+	int r;
+
+	r = amdgpu_vm_verify_parameters(adev, NULL, saddr, 0, size);
+	if (r)
+		return r;
 
-	eaddr = saddr + size - 1;
 	saddr /= AMDGPU_GPU_PAGE_SIZE;
-	eaddr /= AMDGPU_GPU_PAGE_SIZE;
+	eaddr = saddr + (size - 1) / AMDGPU_GPU_PAGE_SIZE;
 
 	/* Allocate all the needed memory */
 	before = kzalloc(sizeof(*before), GFP_KERNEL);
@@ -2327,7 +2355,7 @@
 			after->start = eaddr + 1;
 			after->last = tmp->last;
 			after->offset = tmp->offset;
-			after->offset += after->start - tmp->start;
+			after->offset += (after->start - tmp->start) << PAGE_SHIFT;
 			after->flags = tmp->flags;
 			after->bo_va = tmp->bo_va;
 			list_add(&after->list, &tmp->bo_va->invalids);
@@ -2861,10 +2889,17 @@
 	WARN_ONCE((vm->use_cpu_for_update && !amdgpu_gmc_vram_full_visible(&adev->gmc)),
 		  "CPU update of VM recommended only for large BAR system\n");
 
-	if (vm->use_cpu_for_update)
+	if (vm->use_cpu_for_update) {
+		/* Sync with last SDMA update/clear before switching to CPU */
+		r = amdgpu_bo_sync_wait(vm->root.base.bo,
+					AMDGPU_FENCE_OWNER_UNDEFINED, true);
+		if (r)
+			goto free_idr;
+
 		vm->update_funcs = &amdgpu_vm_cpu_funcs;
-	else
+	} else {
 		vm->update_funcs = &amdgpu_vm_sdma_funcs;
+	}
 	dma_fence_put(vm->last_update);
 	vm->last_update = NULL;
 
@@ -3063,6 +3098,10 @@
 	struct amdgpu_fpriv *fpriv = filp->driver_priv;
 	int r;
 
+	/* No valid flags defined yet */
+	if (args->in.flags)
+		return -EINVAL;
+
 	switch (args->in.op) {
 	case AMDGPU_VM_OP_RESERVE_VMID:
 		/* current, we only have requirement to reserve vmid from gfxhub */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
@@ -105,8 +105,8 @@
 #define AMDGPU_MMHUB_0				1
 #define AMDGPU_MMHUB_1				2
 
-/* hardcode that limit for now */
-#define AMDGPU_VA_RESERVED_SIZE			(1ULL << 20)
+/* Reserve 2MB at top/bottom of address space for kernel use */
+#define AMDGPU_VA_RESERVED_SIZE			(2ULL << 20)
 
 /* max vmids dedicated for process */
 #define AMDGPU_VM_MAX_RESERVED_VMID	1
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
@@ -311,15 +311,22 @@
 }
 
 
+/*
+ * NOTE psp_xgmi_node_info.num_hops layout is as follows:
+ * num_hops[7:6] = link type (0 = xGMI2, 1 = xGMI3, 2/3 = reserved)
+ * num_hops[5:3] = reserved
+ * num_hops[2:0] = number of hops
+ */
 int amdgpu_xgmi_get_hops_count(struct amdgpu_device *adev,
 		struct amdgpu_device *peer_adev)
 {
 	struct psp_xgmi_topology_info *top = &adev->psp.xgmi_context.top_info;
+	uint8_t num_hops_mask = 0x7;
 	int i;
 
 	for (i = 0 ; i < top->num_nodes; ++i)
 		if (top->nodes[i].node_id == peer_adev->gmc.xgmi.node_id)
-			return top->nodes[i].num_hops;
+			return top->nodes[i].num_hops & num_hops_mask;
 	return	-EINVAL;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/atom.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/atom.c
@@ -308,7 +308,7 @@
 				DEBUG("IMM 0x%02X\n", val);
 			return val;
 		}
-		return 0;
+		break;
 	case ATOM_ARG_PLL:
 		idx = U8(*ptr);
 		(*ptr)++;
@@ -744,8 +744,8 @@
 			cjiffies = jiffies;
 			if (time_after(cjiffies, ctx->last_jump_jiffies)) {
 				cjiffies -= ctx->last_jump_jiffies;
-				if ((jiffies_to_msecs(cjiffies) > 5000)) {
-					DRM_ERROR("atombios stuck in loop for more than 5secs aborting\n");
+				if ((jiffies_to_msecs(cjiffies) > 10000)) {
+					DRM_ERROR("atombios stuck in loop for more than 10secs aborting\n");
 					ctx->abort = true;
 				}
 			} else {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c
@@ -2098,23 +2098,29 @@
 					fake_edid_record = (ATOM_FAKE_EDID_PATCH_RECORD *)record;
 					if (fake_edid_record->ucFakeEDIDLength) {
 						struct edid *edid;
-						int edid_size =
-							max((int)EDID_LENGTH, (int)fake_edid_record->ucFakeEDIDLength);
-						edid = kmalloc(edid_size, GFP_KERNEL);
-						if (edid) {
-							memcpy((u8 *)edid, (u8 *)&fake_edid_record->ucFakeEDIDString[0],
-							       fake_edid_record->ucFakeEDIDLength);
+						int edid_size;
 
+						if (fake_edid_record->ucFakeEDIDLength == 128)
+							edid_size = fake_edid_record->ucFakeEDIDLength;
+						else
+							edid_size = fake_edid_record->ucFakeEDIDLength * 128;
+						edid = kmemdup(&fake_edid_record->ucFakeEDIDString[0],
+							       edid_size, GFP_KERNEL);
+						if (edid) {
 							if (drm_edid_is_valid(edid)) {
 								adev->mode_info.bios_hardcoded_edid = edid;
 								adev->mode_info.bios_hardcoded_edid_size = edid_size;
-							} else
+							} else {
 								kfree(edid);
+							}
 						}
+						record += struct_size(fake_edid_record,
+								      ucFakeEDIDString,
+								      edid_size);
+					} else {
+						/* empty fake edid record must be 3 bytes long */
+						record += sizeof(ATOM_FAKE_EDID_PATCH_RECORD) + 1;
 					}
-					record += fake_edid_record->ucFakeEDIDLength ?
-						fake_edid_record->ucFakeEDIDLength + 2 :
-						sizeof(ATOM_FAKE_EDID_PATCH_RECORD);
 					break;
 				case LCD_PANEL_RESOLUTION_RECORD_TYPE:
 					panel_res_record = (ATOM_PANEL_RESOLUTION_PATCH_RECORD *)record;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/cik.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/cik.c
@@ -1384,7 +1384,6 @@
 static void cik_pcie_gen3_enable(struct amdgpu_device *adev)
 {
 	struct pci_dev *root = adev->pdev->bus->self;
-	int bridge_pos, gpu_pos;
 	u32 speed_cntl, current_data_rate;
 	int i;
 	u16 tmp16;
@@ -1419,12 +1418,7 @@
 		DRM_INFO("enabling PCIE gen 2 link speeds, disable with amdgpu.pcie_gen2=0\n");
 	}
 
-	bridge_pos = pci_pcie_cap(root);
-	if (!bridge_pos)
-		return;
-
-	gpu_pos = pci_pcie_cap(adev->pdev);
-	if (!gpu_pos)
+	if (!pci_is_pcie(root) || !pci_is_pcie(adev->pdev))
 		return;
 
 	if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) {
@@ -1434,14 +1428,8 @@
 			u16 bridge_cfg2, gpu_cfg2;
 			u32 max_lw, current_lw, tmp;
 
-			pci_read_config_word(root, bridge_pos + PCI_EXP_LNKCTL, &bridge_cfg);
-			pci_read_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL, &gpu_cfg);
-
-			tmp16 = bridge_cfg | PCI_EXP_LNKCTL_HAWD;
-			pci_write_config_word(root, bridge_pos + PCI_EXP_LNKCTL, tmp16);
-
-			tmp16 = gpu_cfg | PCI_EXP_LNKCTL_HAWD;
-			pci_write_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL, tmp16);
+			pcie_capability_set_word(root, PCI_EXP_LNKCTL, PCI_EXP_LNKCTL_HAWD);
+			pcie_capability_set_word(adev->pdev, PCI_EXP_LNKCTL, PCI_EXP_LNKCTL_HAWD);
 
 			tmp = RREG32_PCIE(ixPCIE_LC_STATUS1);
 			max_lw = (tmp & PCIE_LC_STATUS1__LC_DETECTED_LINK_WIDTH_MASK) >>
@@ -1465,15 +1453,23 @@
 
 			for (i = 0; i < 10; i++) {
 				/* check status */
-				pci_read_config_word(adev->pdev, gpu_pos + PCI_EXP_DEVSTA, &tmp16);
+				pcie_capability_read_word(adev->pdev,
+							  PCI_EXP_DEVSTA,
+							  &tmp16);
 				if (tmp16 & PCI_EXP_DEVSTA_TRPND)
 					break;
 
-				pci_read_config_word(root, bridge_pos + PCI_EXP_LNKCTL, &bridge_cfg);
-				pci_read_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL, &gpu_cfg);
-
-				pci_read_config_word(root, bridge_pos + PCI_EXP_LNKCTL2, &bridge_cfg2);
-				pci_read_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL2, &gpu_cfg2);
+				pcie_capability_read_word(root, PCI_EXP_LNKCTL,
+							  &bridge_cfg);
+				pcie_capability_read_word(adev->pdev,
+							  PCI_EXP_LNKCTL,
+							  &gpu_cfg);
+
+				pcie_capability_read_word(root, PCI_EXP_LNKCTL2,
+							  &bridge_cfg2);
+				pcie_capability_read_word(adev->pdev,
+							  PCI_EXP_LNKCTL2,
+							  &gpu_cfg2);
 
 				tmp = RREG32_PCIE(ixPCIE_LC_CNTL4);
 				tmp |= PCIE_LC_CNTL4__LC_SET_QUIESCE_MASK;
@@ -1486,26 +1482,38 @@
 				msleep(100);
 
 				/* linkctl */
-				pci_read_config_word(root, bridge_pos + PCI_EXP_LNKCTL, &tmp16);
-				tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
-				tmp16 |= (bridge_cfg & PCI_EXP_LNKCTL_HAWD);
-				pci_write_config_word(root, bridge_pos + PCI_EXP_LNKCTL, tmp16);
-
-				pci_read_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL, &tmp16);
-				tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
-				tmp16 |= (gpu_cfg & PCI_EXP_LNKCTL_HAWD);
-				pci_write_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL, tmp16);
+				pcie_capability_clear_and_set_word(root, PCI_EXP_LNKCTL,
+								   PCI_EXP_LNKCTL_HAWD,
+								   bridge_cfg &
+								   PCI_EXP_LNKCTL_HAWD);
+				pcie_capability_clear_and_set_word(adev->pdev, PCI_EXP_LNKCTL,
+								   PCI_EXP_LNKCTL_HAWD,
+								   gpu_cfg &
+								   PCI_EXP_LNKCTL_HAWD);
 
 				/* linkctl2 */
-				pci_read_config_word(root, bridge_pos + PCI_EXP_LNKCTL2, &tmp16);
-				tmp16 &= ~((1 << 4) | (7 << 9));
-				tmp16 |= (bridge_cfg2 & ((1 << 4) | (7 << 9)));
-				pci_write_config_word(root, bridge_pos + PCI_EXP_LNKCTL2, tmp16);
-
-				pci_read_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL2, &tmp16);
-				tmp16 &= ~((1 << 4) | (7 << 9));
-				tmp16 |= (gpu_cfg2 & ((1 << 4) | (7 << 9)));
-				pci_write_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL2, tmp16);
+				pcie_capability_read_word(root, PCI_EXP_LNKCTL2,
+							  &tmp16);
+				tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
+					   PCI_EXP_LNKCTL2_TX_MARGIN);
+				tmp16 |= (bridge_cfg2 &
+					  (PCI_EXP_LNKCTL2_ENTER_COMP |
+					   PCI_EXP_LNKCTL2_TX_MARGIN));
+				pcie_capability_write_word(root,
+							   PCI_EXP_LNKCTL2,
+							   tmp16);
+
+				pcie_capability_read_word(adev->pdev,
+							  PCI_EXP_LNKCTL2,
+							  &tmp16);
+				tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
+					   PCI_EXP_LNKCTL2_TX_MARGIN);
+				tmp16 |= (gpu_cfg2 &
+					  (PCI_EXP_LNKCTL2_ENTER_COMP |
+					   PCI_EXP_LNKCTL2_TX_MARGIN));
+				pcie_capability_write_word(adev->pdev,
+							   PCI_EXP_LNKCTL2,
+							   tmp16);
 
 				tmp = RREG32_PCIE(ixPCIE_LC_CNTL4);
 				tmp &= ~PCIE_LC_CNTL4__LC_SET_QUIESCE_MASK;
@@ -1520,15 +1528,16 @@
 	speed_cntl &= ~PCIE_LC_SPEED_CNTL__LC_FORCE_DIS_SW_SPEED_CHANGE_MASK;
 	WREG32_PCIE(ixPCIE_LC_SPEED_CNTL, speed_cntl);
 
-	pci_read_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL2, &tmp16);
-	tmp16 &= ~0xf;
+	pcie_capability_read_word(adev->pdev, PCI_EXP_LNKCTL2, &tmp16);
+	tmp16 &= ~PCI_EXP_LNKCTL2_TLS;
+
 	if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
-		tmp16 |= 3; /* gen3 */
+		tmp16 |= PCI_EXP_LNKCTL2_TLS_8_0GT; /* gen3 */
 	else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2)
-		tmp16 |= 2; /* gen2 */
+		tmp16 |= PCI_EXP_LNKCTL2_TLS_5_0GT; /* gen2 */
 	else
-		tmp16 |= 1; /* gen1 */
-	pci_write_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL2, tmp16);
+		tmp16 |= PCI_EXP_LNKCTL2_TLS_2_5GT; /* gen1 */
+	pcie_capability_write_word(adev->pdev, PCI_EXP_LNKCTL2, tmp16);
 
 	speed_cntl = RREG32_PCIE(ixPCIE_LC_SPEED_CNTL);
 	speed_cntl |= PCIE_LC_SPEED_CNTL__LC_INITIATE_LINK_SPEED_CHANGE_MASK;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/cik_ih.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/cik_ih.c
@@ -203,6 +203,12 @@
 		tmp = RREG32(mmIH_RB_CNTL);
 		tmp |= IH_RB_CNTL__WPTR_OVERFLOW_CLEAR_MASK;
 		WREG32(mmIH_RB_CNTL, tmp);
+
+		/* Unset the CLEAR_OVERFLOW bit immediately so new overflows
+		 * can be detected.
+		 */
+		tmp &= ~IH_RB_CNTL__WPTR_OVERFLOW_CLEAR_MASK;
+		WREG32(mmIH_RB_CNTL, tmp);
 	}
 	return (wptr & ih->ptr_mask);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
@@ -228,7 +228,7 @@
 	u32 extra_bits = vmid & 0xf;
 
 	/* IB packet must end on a 8 DW boundary */
-	cik_sdma_ring_insert_nop(ring, (12 - (lower_32_bits(ring->wptr) & 7)) % 8);
+	cik_sdma_ring_insert_nop(ring, (4 - lower_32_bits(ring->wptr)) & 7);
 
 	amdgpu_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_INDIRECT_BUFFER, 0, extra_bits));
 	amdgpu_ring_write(ring, ib->gpu_addr & 0xffffffe0); /* base must be 32 byte aligned */
@@ -811,7 +811,7 @@
 	u32 pad_count;
 	int i;
 
-	pad_count = (8 - (ib->length_dw & 0x7)) % 8;
+	pad_count = (-ib->length_dw) & 7;
 	for (i = 0; i < pad_count; i++)
 		if (sdma && sdma->burst_nop && (i == 0))
 			ib->ptr[ib->length_dw++] =
@@ -1071,22 +1071,19 @@
 {
 	u32 srbm_soft_reset = 0;
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-	u32 tmp = RREG32(mmSRBM_STATUS2);
+	u32 tmp;
 
-	if (tmp & SRBM_STATUS2__SDMA_BUSY_MASK) {
-		/* sdma0 */
-		tmp = RREG32(mmSDMA0_F32_CNTL + SDMA0_REGISTER_OFFSET);
-		tmp |= SDMA0_F32_CNTL__HALT_MASK;
-		WREG32(mmSDMA0_F32_CNTL + SDMA0_REGISTER_OFFSET, tmp);
-		srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_SDMA_MASK;
-	}
-	if (tmp & SRBM_STATUS2__SDMA1_BUSY_MASK) {
-		/* sdma1 */
-		tmp = RREG32(mmSDMA0_F32_CNTL + SDMA1_REGISTER_OFFSET);
-		tmp |= SDMA0_F32_CNTL__HALT_MASK;
-		WREG32(mmSDMA0_F32_CNTL + SDMA1_REGISTER_OFFSET, tmp);
-		srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_SDMA1_MASK;
-	}
+	/* sdma0 */
+	tmp = RREG32(mmSDMA0_F32_CNTL + SDMA0_REGISTER_OFFSET);
+	tmp |= SDMA0_F32_CNTL__HALT_MASK;
+	WREG32(mmSDMA0_F32_CNTL + SDMA0_REGISTER_OFFSET, tmp);
+	srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_SDMA_MASK;
+
+	/* sdma1 */
+	tmp = RREG32(mmSDMA0_F32_CNTL + SDMA1_REGISTER_OFFSET);
+	tmp |= SDMA0_F32_CNTL__HALT_MASK;
+	WREG32(mmSDMA0_F32_CNTL + SDMA1_REGISTER_OFFSET, tmp);
+	srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_SDMA1_MASK;
 
 	if (srbm_soft_reset) {
 		tmp = RREG32(mmSRBM_SOFT_RESET);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/cz_ih.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/cz_ih.c
@@ -193,19 +193,35 @@
 
 	wptr = le32_to_cpu(*ih->wptr_cpu);
 
-	if (REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) {
-		wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0);
-		/* When a ring buffer overflow happen start parsing interrupt
-		 * from the last not overwritten vector (wptr + 16). Hopefully
-		 * this should allow us to catchup.
-		 */
-		dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
-			wptr, ih->rptr, (wptr + 16) & ih->ptr_mask);
-		ih->rptr = (wptr + 16) & ih->ptr_mask;
-		tmp = RREG32(mmIH_RB_CNTL);
-		tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
-		WREG32(mmIH_RB_CNTL, tmp);
-	}
+	if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW))
+		goto out;
+
+	/* Double check that the overflow wasn't already cleared. */
+	wptr = RREG32(mmIH_RB_WPTR);
+
+	if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW))
+		goto out;
+
+	wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0);
+
+	/* When a ring buffer overflow happen start parsing interrupt
+	 * from the last not overwritten vector (wptr + 16). Hopefully
+	 * this should allow us to catchup.
+	 */
+	dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
+		wptr, ih->rptr, (wptr + 16) & ih->ptr_mask);
+	ih->rptr = (wptr + 16) & ih->ptr_mask;
+	tmp = RREG32(mmIH_RB_CNTL);
+	tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
+	WREG32(mmIH_RB_CNTL, tmp);
+
+	/* Unset the CLEAR_OVERFLOW bit immediately so new overflows
+	 * can be detected.
+	 */
+	tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 0);
+	WREG32(mmIH_RB_CNTL, tmp);
+
+out:
 	return (wptr & ih->ptr_mask);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/df_v1_7.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/df_v1_7.c
@@ -63,6 +63,8 @@
 	int fb_channel_number;
 
 	fb_channel_number = adev->df_funcs->get_fb_channel_number(adev);
+	if (fb_channel_number >= ARRAY_SIZE(df_v1_7_channel_number))
+		fb_channel_number = 0;
 
 	return df_v1_7_channel_number[fb_channel_number];
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/df_v3_6.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/df_v3_6.c
@@ -261,23 +261,29 @@
 {
 	u32 tmp;
 
-	/* Put DF on broadcast mode */
-	adev->df_funcs->enable_broadcast_mode(adev, true);
+	if (adev->cg_flags & AMD_CG_SUPPORT_DF_MGCG) {
+		/* Put DF on broadcast mode */
+		adev->df_funcs->enable_broadcast_mode(adev, true);
 
-	if (enable && (adev->cg_flags & AMD_CG_SUPPORT_DF_MGCG)) {
-		tmp = RREG32_SOC15(DF, 0, mmDF_PIE_AON0_DfGlobalClkGater);
-		tmp &= ~DF_PIE_AON0_DfGlobalClkGater__MGCGMode_MASK;
-		tmp |= DF_V3_6_MGCG_ENABLE_15_CYCLE_DELAY;
-		WREG32_SOC15(DF, 0, mmDF_PIE_AON0_DfGlobalClkGater, tmp);
-	} else {
-		tmp = RREG32_SOC15(DF, 0, mmDF_PIE_AON0_DfGlobalClkGater);
-		tmp &= ~DF_PIE_AON0_DfGlobalClkGater__MGCGMode_MASK;
-		tmp |= DF_V3_6_MGCG_DISABLE;
-		WREG32_SOC15(DF, 0, mmDF_PIE_AON0_DfGlobalClkGater, tmp);
-	}
+		if (enable) {
+			tmp = RREG32_SOC15(DF, 0,
+					mmDF_PIE_AON0_DfGlobalClkGater);
+			tmp &= ~DF_PIE_AON0_DfGlobalClkGater__MGCGMode_MASK;
+			tmp |= DF_V3_6_MGCG_ENABLE_15_CYCLE_DELAY;
+			WREG32_SOC15(DF, 0,
+					mmDF_PIE_AON0_DfGlobalClkGater, tmp);
+		} else {
+			tmp = RREG32_SOC15(DF, 0,
+					mmDF_PIE_AON0_DfGlobalClkGater);
+			tmp &= ~DF_PIE_AON0_DfGlobalClkGater__MGCGMode_MASK;
+			tmp |= DF_V3_6_MGCG_DISABLE;
+			WREG32_SOC15(DF, 0,
+					mmDF_PIE_AON0_DfGlobalClkGater, tmp);
+		}
 
-	/* Exit broadcast mode */
-	adev->df_funcs->enable_broadcast_mode(adev, false);
+		/* Exit broadcast mode */
+		adev->df_funcs->enable_broadcast_mode(adev, false);
+	}
 }
 
 static void df_v3_6_get_clockgating_state(struct amdgpu_device *adev,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
@@ -82,13 +82,6 @@
 MODULE_FIRMWARE("amdgpu/navi14_mec2.bin");
 MODULE_FIRMWARE("amdgpu/navi14_rlc.bin");
 
-MODULE_FIRMWARE("amdgpu/navi12_ce.bin");
-MODULE_FIRMWARE("amdgpu/navi12_pfp.bin");
-MODULE_FIRMWARE("amdgpu/navi12_me.bin");
-MODULE_FIRMWARE("amdgpu/navi12_mec.bin");
-MODULE_FIRMWARE("amdgpu/navi12_mec2.bin");
-MODULE_FIRMWARE("amdgpu/navi12_rlc.bin");
-
 static const struct soc15_reg_golden golden_settings_gc_10_1[] =
 {
 	SOC15_REG_GOLDEN_VALUE(GC, 0, mmCB_HW_CONTROL_4, 0xffffffff, 0x00400014),
@@ -190,9 +183,10 @@
 	SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG, 0xffffffff, 0x20000000),
 	SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG2, 0xffffffff, 0x00000420),
 	SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG3, 0xffffffff, 0x00000200),
-	SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG4, 0xffffffff, 0x04800000),
+	SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG4, 0xffffffff, 0x04900000),
 	SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DFSM_TILES_IN_FLIGHT, 0x0000ffff, 0x0000003f),
 	SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_LAST_OF_BURST_CONFIG, 0xffffffff, 0x03860204),
+	SOC15_REG_GOLDEN_VALUE(GC, 0, mmGB_ADDR_CONFIG, 0x0c1800ff, 0x00000044),
 	SOC15_REG_GOLDEN_VALUE(GC, 0, mmGCR_GENERAL_CNTL, 0x1ff0ffff, 0x00000500),
 	SOC15_REG_GOLDEN_VALUE(GC, 0, mmGE_PRIV_CONTROL, 0x00007fff, 0x000001fe),
 	SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL1_PIPE_STEER, 0xffffffff, 0xe4e4e4e4),
@@ -210,12 +204,13 @@
 	SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_ENHANCE_2, 0x00000820, 0x00000820),
 	SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_LINE_STIPPLE_STATE, 0x0000ff0f, 0x00000000),
 	SOC15_REG_GOLDEN_VALUE(GC, 0, mmRMI_SPARE, 0xffffffff, 0xffff3101),
+	SOC15_REG_GOLDEN_VALUE(GC, 0, mmSPI_CONFIG_CNTL_1, 0x001f0000, 0x00070104),
 	SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_ALU_CLK_CTRL, 0xffffffff, 0xffffffff),
 	SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_ARB_CONFIG, 0x00000133, 0x00000130),
 	SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_LDS_CLK_CTRL, 0xffffffff, 0xffffffff),
 	SOC15_REG_GOLDEN_VALUE(GC, 0, mmTA_CNTL_AUX, 0xfff7ffff, 0x01030000),
 	SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_CNTL, 0xffdf80ff, 0x479c0010),
-	SOC15_REG_GOLDEN_VALUE(GC, 0, mmUTCL1_CTRL, 0xffffffff, 0x00800000)
+	SOC15_REG_GOLDEN_VALUE(GC, 0, mmUTCL1_CTRL, 0xffffffff, 0x00c00000)
 };
 
 static const struct soc15_reg_golden golden_settings_gc_10_1_nv14[] =
@@ -993,39 +988,6 @@
 	return 0;
 }
 
-static int gfx_v10_0_csb_vram_pin(struct amdgpu_device *adev)
-{
-	int r;
-
-	r = amdgpu_bo_reserve(adev->gfx.rlc.clear_state_obj, false);
-	if (unlikely(r != 0))
-		return r;
-
-	r = amdgpu_bo_pin(adev->gfx.rlc.clear_state_obj,
-			AMDGPU_GEM_DOMAIN_VRAM);
-	if (!r)
-		adev->gfx.rlc.clear_state_gpu_addr =
-			amdgpu_bo_gpu_offset(adev->gfx.rlc.clear_state_obj);
-
-	amdgpu_bo_unreserve(adev->gfx.rlc.clear_state_obj);
-
-	return r;
-}
-
-static void gfx_v10_0_csb_vram_unpin(struct amdgpu_device *adev)
-{
-	int r;
-
-	if (!adev->gfx.rlc.clear_state_obj)
-		return;
-
-	r = amdgpu_bo_reserve(adev->gfx.rlc.clear_state_obj, true);
-	if (likely(r == 0)) {
-		amdgpu_bo_unpin(adev->gfx.rlc.clear_state_obj);
-		amdgpu_bo_unreserve(adev->gfx.rlc.clear_state_obj);
-	}
-}
-
 static void gfx_v10_0_mec_fini(struct amdgpu_device *adev)
 {
 	amdgpu_bo_free_kernel(&adev->gfx.mec.hpd_eop_obj, NULL, NULL);
@@ -1785,27 +1747,34 @@
 	WREG32_SOC15(GC, 0, mmCP_INT_CNTL_RING0, tmp);
 }
 
-static void gfx_v10_0_init_csb(struct amdgpu_device *adev)
+static int gfx_v10_0_init_csb(struct amdgpu_device *adev)
 {
+	adev->gfx.rlc.funcs->get_csb_buffer(adev, adev->gfx.rlc.cs_ptr);
+
 	/* csib */
 	WREG32_SOC15(GC, 0, mmRLC_CSIB_ADDR_HI,
 		     adev->gfx.rlc.clear_state_gpu_addr >> 32);
 	WREG32_SOC15(GC, 0, mmRLC_CSIB_ADDR_LO,
 		     adev->gfx.rlc.clear_state_gpu_addr & 0xfffffffc);
 	WREG32_SOC15(GC, 0, mmRLC_CSIB_LENGTH, adev->gfx.rlc.clear_state_size);
+
+	return 0;
 }
 
-static void gfx_v10_0_init_pg(struct amdgpu_device *adev)
+static int gfx_v10_0_init_pg(struct amdgpu_device *adev)
 {
 	int i;
+	int r;
 
-	gfx_v10_0_init_csb(adev);
+	r = gfx_v10_0_init_csb(adev);
+	if (r)
+		return r;
 
 	for (i = 0; i < adev->num_vmhubs; i++)
 		amdgpu_gmc_flush_gpu_tlb(adev, 0, i, 0);
 
 	/* TODO: init power gating */
-	return;
+	return 0;
 }
 
 void gfx_v10_0_rlc_stop(struct amdgpu_device *adev)
@@ -1907,7 +1876,10 @@
 		r = gfx_v10_0_wait_for_rlc_autoload_complete(adev);
 		if (r)
 			return r;
-		gfx_v10_0_init_pg(adev);
+
+		r = gfx_v10_0_init_pg(adev);
+		if (r)
+			return r;
 
 		/* enable RLC SRM */
 		gfx_v10_0_rlc_enable_srm(adev);
@@ -1933,7 +1905,10 @@
 				return r;
 		}
 
-		gfx_v10_0_init_pg(adev);
+		r = gfx_v10_0_init_pg(adev);
+		if (r)
+			return r;
+
 		adev->gfx.rlc.funcs->start(adev);
 
 		if (adev->firmware.load_type == AMDGPU_FW_LOAD_RLC_BACKDOOR_AUTO) {
@@ -2400,7 +2375,7 @@
 	return 0;
 }
 
-static void gfx_v10_0_cp_gfx_enable(struct amdgpu_device *adev, bool enable)
+static int gfx_v10_0_cp_gfx_enable(struct amdgpu_device *adev, bool enable)
 {
 	int i;
 	u32 tmp = RREG32_SOC15(GC, 0, mmCP_ME_CNTL);
@@ -2413,7 +2388,17 @@
 			adev->gfx.gfx_ring[i].sched.ready = false;
 	}
 	WREG32_SOC15(GC, 0, mmCP_ME_CNTL, tmp);
-	udelay(50);
+
+	for (i = 0; i < adev->usec_timeout; i++) {
+		if (RREG32_SOC15(GC, 0, mmCP_STAT) == 0)
+			break;
+		udelay(1);
+	}
+
+	if (i >= adev->usec_timeout)
+		DRM_ERROR("failed to %s cp gfx\n", enable ? "unhalt" : "halt");
+
+	return 0;
 }
 
 static int gfx_v10_0_cp_gfx_load_pfp_microcode(struct amdgpu_device *adev)
@@ -3514,6 +3499,7 @@
 
 		/* reset ring buffer */
 		ring->wptr = 0;
+		atomic64_set((atomic64_t *)&adev->wb.wb[ring->wptr_offs], 0);
 		amdgpu_ring_clear_ring(ring);
 	} else {
 		amdgpu_ring_clear_ring(ring);
@@ -3534,8 +3520,10 @@
 		return r;
 
 	r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr);
-	if (unlikely(r != 0))
+	if (unlikely(r != 0)) {
+		amdgpu_bo_unreserve(ring->mqd_obj);
 		return r;
+	}
 
 	gfx_v10_0_kiq_init_queue(ring);
 	amdgpu_bo_kunmap(ring->mqd_obj);
@@ -3732,10 +3720,6 @@
 	int r;
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-	r = gfx_v10_0_csb_vram_pin(adev);
-	if (r)
-		return r;
-
 	if (!amdgpu_emu_mode)
 		gfx_v10_0_init_golden_registers(adev);
 
@@ -3823,7 +3807,6 @@
 	}
 	gfx_v10_0_cp_enable(adev, false);
 	gfx_v10_0_enable_gui_idle_interrupt(adev, false);
-	gfx_v10_0_csb_vram_unpin(adev);
 
 	return 0;
 }
@@ -3936,11 +3919,13 @@
 {
 	uint64_t clock;
 
+	amdgpu_gfx_off_ctrl(adev, false);
 	mutex_lock(&adev->gfx.gpu_clock_mutex);
 	WREG32_SOC15(GC, 0, mmRLC_CAPTURE_GPU_CLOCK_COUNT, 1);
 	clock = (uint64_t)RREG32_SOC15(GC, 0, mmRLC_GPU_CLOCK_COUNT_LSB) |
 		((uint64_t)RREG32_SOC15(GC, 0, mmRLC_GPU_CLOCK_COUNT_MSB) << 32ULL);
 	mutex_unlock(&adev->gfx.gpu_clock_mutex);
+	amdgpu_gfx_off_ctrl(adev, true);
 	return clock;
 }
 
@@ -4050,10 +4035,8 @@
 		def = data = RREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE);
 		data &= ~(RLC_CGTT_MGCG_OVERRIDE__GRBM_CGTT_SCLK_OVERRIDE_MASK |
 			  RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGCG_OVERRIDE_MASK |
-			  RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGLS_OVERRIDE_MASK);
-
-		/* only for Vega10 & Raven1 */
-		data |= RLC_CGTT_MGCG_OVERRIDE__RLC_CGTT_SCLK_OVERRIDE_MASK;
+			  RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGLS_OVERRIDE_MASK |
+			  RLC_CGTT_MGCG_OVERRIDE__ENABLE_CGTS_LEGACY_MASK);
 
 		if (def != data)
 			WREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE, data);
@@ -4246,11 +4229,7 @@
 	switch (adev->asic_type) {
 	case CHIP_NAVI10:
 	case CHIP_NAVI14:
-		if (!enable) {
-			amdgpu_gfx_off_ctrl(adev, false);
-			cancel_delayed_work_sync(&adev->gfx.gfx_off_delay_work);
-		} else
-			amdgpu_gfx_off_ctrl(adev, true);
+		amdgpu_gfx_off_ctrl(adev, enable);
 		break;
 	default:
 		break;
@@ -4643,12 +4622,17 @@
 	struct amdgpu_device *adev = ring->adev;
 	struct amdgpu_kiq *kiq = &adev->gfx.kiq;
 	struct amdgpu_ring *kiq_ring = &kiq->ring;
+	unsigned long flags;
 
 	if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
 		return -EINVAL;
 
-	if (amdgpu_ring_alloc(kiq_ring, kiq->pmf->unmap_queues_size))
+	spin_lock_irqsave(&kiq->ring_lock, flags);
+
+	if (amdgpu_ring_alloc(kiq_ring, kiq->pmf->unmap_queues_size)) {
+		spin_unlock_irqrestore(&kiq->ring_lock, flags);
 		return -ENOMEM;
+	}
 
 	/* assert preemption condition */
 	amdgpu_ring_set_preempt_cond_exec(ring, false);
@@ -4659,6 +4643,8 @@
 				   ++ring->trail_seq);
 	amdgpu_ring_commit(kiq_ring);
 
+	spin_unlock_irqrestore(&kiq->ring_lock, flags);
+
 	/* poll the trailing fence */
 	for (i = 0; i < adev->usec_timeout; i++) {
 		if (ring->trail_seq ==
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
@@ -4554,6 +4554,8 @@
 
 	gfx_v7_0_constants_init(adev);
 
+	/* init CSB */
+	adev->gfx.rlc.funcs->get_csb_buffer(adev, adev->gfx.rlc.cs_ptr);
 	/* init rlc */
 	r = adev->gfx.rlc.funcs->resume(adev);
 	if (r)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
@@ -1321,39 +1321,6 @@
 	return 0;
 }
 
-static int gfx_v8_0_csb_vram_pin(struct amdgpu_device *adev)
-{
-	int r;
-
-	r = amdgpu_bo_reserve(adev->gfx.rlc.clear_state_obj, false);
-	if (unlikely(r != 0))
-		return r;
-
-	r = amdgpu_bo_pin(adev->gfx.rlc.clear_state_obj,
-			AMDGPU_GEM_DOMAIN_VRAM);
-	if (!r)
-		adev->gfx.rlc.clear_state_gpu_addr =
-			amdgpu_bo_gpu_offset(adev->gfx.rlc.clear_state_obj);
-
-	amdgpu_bo_unreserve(adev->gfx.rlc.clear_state_obj);
-
-	return r;
-}
-
-static void gfx_v8_0_csb_vram_unpin(struct amdgpu_device *adev)
-{
-	int r;
-
-	if (!adev->gfx.rlc.clear_state_obj)
-		return;
-
-	r = amdgpu_bo_reserve(adev->gfx.rlc.clear_state_obj, true);
-	if (likely(r == 0)) {
-		amdgpu_bo_unpin(adev->gfx.rlc.clear_state_obj);
-		amdgpu_bo_unreserve(adev->gfx.rlc.clear_state_obj);
-	}
-}
-
 static void gfx_v8_0_mec_fini(struct amdgpu_device *adev)
 {
 	amdgpu_bo_free_kernel(&adev->gfx.mec.hpd_eop_obj, NULL, NULL);
@@ -3917,6 +3884,7 @@
 
 static void gfx_v8_0_init_csb(struct amdgpu_device *adev)
 {
+	adev->gfx.rlc.funcs->get_csb_buffer(adev, adev->gfx.rlc.cs_ptr);
 	/* csib */
 	WREG32(mmRLC_CSIB_ADDR_HI,
 			adev->gfx.rlc.clear_state_gpu_addr >> 32);
@@ -4837,10 +4805,6 @@
 	gfx_v8_0_init_golden_registers(adev);
 	gfx_v8_0_constants_init(adev);
 
-	r = gfx_v8_0_csb_vram_pin(adev);
-	if (r)
-		return r;
-
 	r = adev->gfx.rlc.funcs->resume(adev);
 	if (r)
 		return r;
@@ -4958,8 +4922,6 @@
 		pr_err("rlc is busy, skip halt rlc\n");
 	amdgpu_gfx_rlc_exit_safe_mode(adev);
 
-	gfx_v8_0_csb_vram_unpin(adev);
-
 	return 0;
 }
 
@@ -6184,7 +6146,23 @@
 	bool write64bit = flags & AMDGPU_FENCE_FLAG_64BIT;
 	bool int_sel = flags & AMDGPU_FENCE_FLAG_INT;
 
-	/* EVENT_WRITE_EOP - flush caches, send int */
+	/* Workaround for cache flush problems. First send a dummy EOP
+	 * event down the pipe with seq one below.
+	 */
+	amdgpu_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE_EOP, 4));
+	amdgpu_ring_write(ring, (EOP_TCL1_ACTION_EN |
+				 EOP_TC_ACTION_EN |
+				 EOP_TC_WB_ACTION_EN |
+				 EVENT_TYPE(CACHE_FLUSH_AND_INV_TS_EVENT) |
+				 EVENT_INDEX(5)));
+	amdgpu_ring_write(ring, addr & 0xfffffffc);
+	amdgpu_ring_write(ring, (upper_32_bits(addr) & 0xffff) |
+				DATA_SEL(1) | INT_SEL(0));
+	amdgpu_ring_write(ring, lower_32_bits(seq - 1));
+	amdgpu_ring_write(ring, upper_32_bits(seq - 1));
+
+	/* Then send the real EOP event down the pipe:
+	 * EVENT_WRITE_EOP - flush caches, send int */
 	amdgpu_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE_EOP, 4));
 	amdgpu_ring_write(ring, (EOP_TCL1_ACTION_EN |
 				 EOP_TC_ACTION_EN |
@@ -6926,7 +6904,7 @@
 		5 +  /* COND_EXEC */
 		7 +  /* PIPELINE_SYNC */
 		VI_FLUSH_GPU_TLB_NUM_WREG * 5 + 9 + /* VM_FLUSH */
-		8 +  /* FENCE for VM_FLUSH */
+		12 +  /* FENCE for VM_FLUSH */
 		20 + /* GDS switch */
 		4 + /* double SWITCH_BUFFER,
 		       the first COND_EXEC jump to the place just
@@ -6938,7 +6916,7 @@
 		31 + /*	DE_META */
 		3 + /* CNTX_CTRL */
 		5 + /* HDP_INVL */
-		8 + 8 + /* FENCE x2 */
+		12 + 12 + /* FENCE x2 */
 		2, /* SWITCH_BUFFER */
 	.emit_ib_size =	4, /* gfx_v8_0_ring_emit_ib_gfx */
 	.emit_ib = gfx_v8_0_ring_emit_ib_gfx,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
@@ -107,10 +107,6 @@
 MODULE_FIRMWARE("amdgpu/raven2_rlc.bin");
 MODULE_FIRMWARE("amdgpu/raven_kicker_rlc.bin");
 
-MODULE_FIRMWARE("amdgpu/arcturus_mec.bin");
-MODULE_FIRMWARE("amdgpu/arcturus_mec2.bin");
-MODULE_FIRMWARE("amdgpu/arcturus_rlc.bin");
-
 MODULE_FIRMWARE("amdgpu/renoir_ce.bin");
 MODULE_FIRMWARE("amdgpu/renoir_pfp.bin");
 MODULE_FIRMWARE("amdgpu/renoir_me.bin");
@@ -1026,6 +1022,8 @@
 			adev->gfx.mec_fw_write_wait = true;
 		break;
 	default:
+		adev->gfx.me_fw_write_wait = true;
+		adev->gfx.mec_fw_write_wait = true;
 		break;
 	}
 }
@@ -1038,17 +1036,10 @@
 	case CHIP_VEGA20:
 		break;
 	case CHIP_RAVEN:
-		/* Disable GFXOFF on original raven.  There are combinations
-		 * of sbios and platforms that are not stable.
-		 */
-		if (!(adev->rev_id >= 0x8 || adev->pdev->device == 0x15d8))
-			adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
-		else if (!(adev->rev_id >= 0x8 || adev->pdev->device == 0x15d8)
-			 &&((adev->gfx.rlc_fw_version != 106 &&
-			     adev->gfx.rlc_fw_version < 531) ||
-			    (adev->gfx.rlc_fw_version == 53815) ||
-			    (adev->gfx.rlc_feature_version < 1) ||
-			    !adev->gfx.rlc.is_rlc_v2_1))
+		if (!(adev->rev_id >= 0x8 ||
+		      adev->pdev->device == 0x15d8) &&
+		    (adev->pm.fw_version < 0x41e2b || /* not raven1 fresh */
+		     !adev->gfx.rlc.is_rlc_v2_1)) /* without rlc save restore ucodes */
 			adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
 
 		if (adev->pm.pp_feature & PP_GFXOFF_MASK)
@@ -1680,39 +1671,6 @@
 	return 0;
 }
 
-static int gfx_v9_0_csb_vram_pin(struct amdgpu_device *adev)
-{
-	int r;
-
-	r = amdgpu_bo_reserve(adev->gfx.rlc.clear_state_obj, false);
-	if (unlikely(r != 0))
-		return r;
-
-	r = amdgpu_bo_pin(adev->gfx.rlc.clear_state_obj,
-			AMDGPU_GEM_DOMAIN_VRAM);
-	if (!r)
-		adev->gfx.rlc.clear_state_gpu_addr =
-			amdgpu_bo_gpu_offset(adev->gfx.rlc.clear_state_obj);
-
-	amdgpu_bo_unreserve(adev->gfx.rlc.clear_state_obj);
-
-	return r;
-}
-
-static void gfx_v9_0_csb_vram_unpin(struct amdgpu_device *adev)
-{
-	int r;
-
-	if (!adev->gfx.rlc.clear_state_obj)
-		return;
-
-	r = amdgpu_bo_reserve(adev->gfx.rlc.clear_state_obj, true);
-	if (likely(r == 0)) {
-		amdgpu_bo_unpin(adev->gfx.rlc.clear_state_obj);
-		amdgpu_bo_unreserve(adev->gfx.rlc.clear_state_obj);
-	}
-}
-
 static void gfx_v9_0_mec_fini(struct amdgpu_device *adev)
 {
 	amdgpu_bo_free_kernel(&adev->gfx.mec.hpd_eop_obj, NULL, NULL);
@@ -2510,7 +2468,8 @@
 
 	gfx_v9_0_tiling_mode_table_init(adev);
 
-	gfx_v9_0_setup_rb(adev);
+	if (adev->gfx.num_gfx_rings)
+		gfx_v9_0_setup_rb(adev);
 	gfx_v9_0_get_cu_info(adev, &adev->gfx.cu_info);
 	adev->gfx.config.db_debug2 = RREG32_SOC15(GC, 0, mmDB_DEBUG2);
 
@@ -2601,6 +2560,7 @@
 
 static void gfx_v9_0_init_csb(struct amdgpu_device *adev)
 {
+	adev->gfx.rlc.funcs->get_csb_buffer(adev, adev->gfx.rlc.cs_ptr);
 	/* csib */
 	WREG32_RLC(SOC15_REG_OFFSET(GC, 0, mmRLC_CSIB_ADDR_HI),
 			adev->gfx.rlc.clear_state_gpu_addr >> 32);
@@ -2930,7 +2890,10 @@
 	 * And it's needed by gfxoff feature.
 	 */
 	if (adev->gfx.rlc.is_rlc_v2_1) {
-		gfx_v9_1_init_rlc_save_restore_list(adev);
+		if (adev->asic_type == CHIP_VEGA12 ||
+		    (adev->asic_type == CHIP_RAVEN &&
+		     adev->rev_id >= 8))
+			gfx_v9_1_init_rlc_save_restore_list(adev);
 		gfx_v9_0_enable_save_restore_machine(adev);
 	}
 
@@ -2940,8 +2903,8 @@
 			      AMD_PG_SUPPORT_CP |
 			      AMD_PG_SUPPORT_GDS |
 			      AMD_PG_SUPPORT_RLC_SMU_HS)) {
-		WREG32(mmRLC_JUMP_TABLE_RESTORE,
-		       adev->gfx.rlc.cp_table_gpu_addr >> 8);
+		WREG32_SOC15(GC, 0, mmRLC_JUMP_TABLE_RESTORE,
+			     adev->gfx.rlc.cp_table_gpu_addr >> 8);
 		gfx_v9_0_init_gfx_power_gating(adev);
 	}
 }
@@ -3760,6 +3723,7 @@
 
 		/* reset ring buffer */
 		ring->wptr = 0;
+		atomic64_set((atomic64_t *)&adev->wb.wb[ring->wptr_offs], 0);
 		amdgpu_ring_clear_ring(ring);
 	} else {
 		amdgpu_ring_clear_ring(ring);
@@ -3780,8 +3744,10 @@
 		return r;
 
 	r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr);
-	if (unlikely(r != 0))
+	if (unlikely(r != 0)) {
+		amdgpu_bo_unreserve(ring->mqd_obj);
 		return r;
+	}
 
 	gfx_v9_0_kiq_init_queue(ring);
 	amdgpu_bo_kunmap(ring->mqd_obj);
@@ -3889,10 +3855,6 @@
 
 	gfx_v9_0_constants_init(adev);
 
-	r = gfx_v9_0_csb_vram_pin(adev);
-	if (r)
-		return r;
-
 	r = adev->gfx.rlc.funcs->resume(adev);
 	if (r)
 		return r;
@@ -3944,7 +3906,8 @@
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-	amdgpu_irq_put(adev, &adev->gfx.cp_ecc_error_irq, 0);
+	if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__GFX))
+		amdgpu_irq_put(adev, &adev->gfx.cp_ecc_error_irq, 0);
 	amdgpu_irq_put(adev, &adev->gfx.priv_reg_irq, 0);
 	amdgpu_irq_put(adev, &adev->gfx.priv_inst_irq, 0);
 
@@ -3978,8 +3941,6 @@
 	gfx_v9_0_cp_enable(adev, false);
 	adev->gfx.rlc.funcs->stop(adev);
 
-	gfx_v9_0_csb_vram_unpin(adev);
-
 	return 0;
 }
 
@@ -4084,11 +4045,13 @@
 {
 	uint64_t clock;
 
+	amdgpu_gfx_off_ctrl(adev, false);
 	mutex_lock(&adev->gfx.gpu_clock_mutex);
 	WREG32_SOC15(GC, 0, mmRLC_CAPTURE_GPU_CLOCK_COUNT, 1);
 	clock = (uint64_t)RREG32_SOC15(GC, 0, mmRLC_GPU_CLOCK_COUNT_LSB) |
 		((uint64_t)RREG32_SOC15(GC, 0, mmRLC_GPU_CLOCK_COUNT_MSB) << 32ULL);
 	mutex_unlock(&adev->gfx.gpu_clock_mutex);
+	amdgpu_gfx_off_ctrl(adev, true);
 	return clock;
 }
 
@@ -4698,7 +4661,7 @@
 	amdgpu_gfx_rlc_enter_safe_mode(adev);
 
 	/* Enable 3D CGCG/CGLS */
-	if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_3D_CGCG)) {
+	if (enable) {
 		/* write cmd to clear cgcg/cgls ov */
 		def = data = RREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE);
 		/* unset CGCG override */
@@ -4710,8 +4673,12 @@
 		/* enable 3Dcgcg FSM(0x0000363f) */
 		def = RREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D);
 
-		data = (0x36 << RLC_CGCG_CGLS_CTRL_3D__CGCG_GFX_IDLE_THRESHOLD__SHIFT) |
-			RLC_CGCG_CGLS_CTRL_3D__CGCG_EN_MASK;
+		if (adev->cg_flags & AMD_CG_SUPPORT_GFX_3D_CGCG)
+			data = (0x36 << RLC_CGCG_CGLS_CTRL_3D__CGCG_GFX_IDLE_THRESHOLD__SHIFT) |
+				RLC_CGCG_CGLS_CTRL_3D__CGCG_EN_MASK;
+		else
+			data = 0x0 << RLC_CGCG_CGLS_CTRL_3D__CGCG_GFX_IDLE_THRESHOLD__SHIFT;
+
 		if (adev->cg_flags & AMD_CG_SUPPORT_GFX_3D_CGLS)
 			data |= (0x000F << RLC_CGCG_CGLS_CTRL_3D__CGLS_REP_COMPANSAT_DELAY__SHIFT) |
 				RLC_CGCG_CGLS_CTRL_3D__CGLS_EN_MASK;
@@ -4838,10 +4805,9 @@
 	switch (adev->asic_type) {
 	case CHIP_RAVEN:
 	case CHIP_RENOIR:
-		if (!enable) {
+		if (!enable)
 			amdgpu_gfx_off_ctrl(adev, false);
-			cancel_delayed_work_sync(&adev->gfx.gfx_off_delay_work);
-		}
+
 		if (adev->pg_flags & AMD_PG_SUPPORT_RLC_SMU_HS) {
 			gfx_v9_0_enable_sck_slow_down_on_power_up(adev, true);
 			gfx_v9_0_enable_sck_slow_down_on_power_down(adev, true);
@@ -4867,12 +4833,7 @@
 			amdgpu_gfx_off_ctrl(adev, true);
 		break;
 	case CHIP_VEGA12:
-		if (!enable) {
-			amdgpu_gfx_off_ctrl(adev, false);
-			cancel_delayed_work_sync(&adev->gfx.gfx_off_delay_work);
-		} else {
-			amdgpu_gfx_off_ctrl(adev, true);
-		}
+		amdgpu_gfx_off_ctrl(adev, enable);
 		break;
 	default:
 		break;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c
@@ -365,6 +365,8 @@
 	hub->ctx0_ptb_addr_hi32 =
 		SOC15_REG_OFFSET(GC, 0,
 				 mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32);
+	hub->vm_inv_eng0_sem =
+		SOC15_REG_OFFSET(GC, 0, mmVM_INVALIDATE_ENG0_SEM);
 	hub->vm_inv_eng0_req =
 		SOC15_REG_OFFSET(GC, 0, mmVM_INVALIDATE_ENG0_REQ);
 	hub->vm_inv_eng0_ack =
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c
@@ -350,6 +350,8 @@
 	hub->ctx0_ptb_addr_hi32 =
 		SOC15_REG_OFFSET(GC, 0,
 				 mmGCVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32);
+	hub->vm_inv_eng0_sem =
+		SOC15_REG_OFFSET(GC, 0, mmGCVM_INVALIDATE_ENG0_SEM);
 	hub->vm_inv_eng0_req =
 		SOC15_REG_OFFSET(GC, 0, mmGCVM_INVALIDATE_ENG0_REQ);
 	hub->vm_inv_eng0_ack =
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
@@ -230,12 +230,36 @@
 				   unsigned int vmhub, uint32_t flush_type)
 {
 	struct amdgpu_vmhub *hub = &adev->vmhub[vmhub];
-	u32 tmp = gmc_v10_0_get_invalidate_req(vmid, flush_type);
+	u32 inv_req = gmc_v10_0_get_invalidate_req(vmid, flush_type);
+	u32 tmp;
 	/* Use register 17 for GART */
 	const unsigned eng = 17;
 	unsigned int i;
 
-	WREG32_NO_KIQ(hub->vm_inv_eng0_req + eng, tmp);
+	spin_lock(&adev->gmc.invalidate_lock);
+	/*
+	 * It may lose gpuvm invalidate acknowldege state across power-gating
+	 * off cycle, add semaphore acquire before invalidation and semaphore
+	 * release after invalidation to avoid entering power gated state
+	 * to WA the Issue
+	 */
+
+	/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
+	if (vmhub == AMDGPU_MMHUB_0 ||
+	    vmhub == AMDGPU_MMHUB_1) {
+		for (i = 0; i < adev->usec_timeout; i++) {
+			/* a read return value of 1 means semaphore acuqire */
+			tmp = RREG32_NO_KIQ(hub->vm_inv_eng0_sem + eng);
+			if (tmp & 0x1)
+				break;
+			udelay(1);
+		}
+
+		if (i >= adev->usec_timeout)
+			DRM_ERROR("Timeout waiting for sem acquire in VM flush!\n");
+	}
+
+	WREG32_NO_KIQ(hub->vm_inv_eng0_req + eng, inv_req);
 
 	/*
 	 * Issue a dummy read to wait for the ACK register to be cleared
@@ -254,6 +278,17 @@
 		udelay(1);
 	}
 
+	/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
+	if (vmhub == AMDGPU_MMHUB_0 ||
+	    vmhub == AMDGPU_MMHUB_1)
+		/*
+		 * add semaphore release after invalidation,
+		 * write with 0 means semaphore release
+		 */
+		WREG32_NO_KIQ(hub->vm_inv_eng0_sem + eng, 0);
+
+	spin_unlock(&adev->gmc.invalidate_lock);
+
 	if (i < adev->usec_timeout)
 		return;
 
@@ -338,6 +373,20 @@
 	uint32_t req = gmc_v10_0_get_invalidate_req(vmid, 0);
 	unsigned eng = ring->vm_inv_eng;
 
+	/*
+	 * It may lose gpuvm invalidate acknowldege state across power-gating
+	 * off cycle, add semaphore acquire before invalidation and semaphore
+	 * release after invalidation to avoid entering power gated state
+	 * to WA the Issue
+	 */
+
+	/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
+	if (ring->funcs->vmhub == AMDGPU_MMHUB_0 ||
+	    ring->funcs->vmhub == AMDGPU_MMHUB_1)
+		/* a read return value of 1 means semaphore acuqire */
+		amdgpu_ring_emit_reg_wait(ring,
+					  hub->vm_inv_eng0_sem + eng, 0x1, 0x1);
+
 	amdgpu_ring_emit_wreg(ring, hub->ctx0_ptb_addr_lo32 + (2 * vmid),
 			      lower_32_bits(pd_addr));
 
@@ -348,6 +397,15 @@
 					    hub->vm_inv_eng0_ack + eng,
 					    req, 1 << vmid);
 
+	/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
+	if (ring->funcs->vmhub == AMDGPU_MMHUB_0 ||
+	    ring->funcs->vmhub == AMDGPU_MMHUB_1)
+		/*
+		 * add semaphore release after invalidation,
+		 * write with 0 means semaphore release
+		 */
+		amdgpu_ring_emit_wreg(ring, hub->vm_inv_eng0_sem + eng, 0);
+
 	return pd_addr;
 }
 
@@ -845,6 +903,8 @@
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
+	gmc_v10_0_gart_disable(adev);
+
 	if (amdgpu_sriov_vf(adev)) {
 		/* full access mode, so don't touch any GMC register */
 		DRM_DEBUG("For SRIOV client, shouldn't do anything.\n");
@@ -852,7 +912,6 @@
 	}
 
 	amdgpu_irq_put(adev, &adev->gmc.vm_fault, 0);
-	gmc_v10_0_gart_disable(adev);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
@@ -863,12 +863,12 @@
 
 	adev->gmc.mc_mask = 0xffffffffffULL;
 
-	r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(44));
+	r = dma_set_mask_and_coherent(adev->dev, DMA_BIT_MASK(40));
 	if (r) {
 		dev_warn(adev->dev, "amdgpu: No suitable DMA available.\n");
 		return r;
 	}
-	adev->need_swiotlb = drm_need_swiotlb(44);
+	adev->need_swiotlb = drm_need_swiotlb(40);
 
 	r = gmc_v6_0_init_microcode(adev);
 	if (r) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
@@ -524,10 +524,10 @@
 static int gmc_v8_0_mc_init(struct amdgpu_device *adev)
 {
 	int r;
+	u32 tmp;
 
 	adev->gmc.vram_width = amdgpu_atombios_get_vram_width(adev);
 	if (!adev->gmc.vram_width) {
-		u32 tmp;
 		int chansize, numchan;
 
 		/* Get VRAM informations */
@@ -571,8 +571,15 @@
 		adev->gmc.vram_width = numchan * chansize;
 	}
 	/* size in MB on si */
-	adev->gmc.mc_vram_size = RREG32(mmCONFIG_MEMSIZE) * 1024ULL * 1024ULL;
-	adev->gmc.real_vram_size = RREG32(mmCONFIG_MEMSIZE) * 1024ULL * 1024ULL;
+	tmp = RREG32(mmCONFIG_MEMSIZE);
+	/* some boards may have garbage in the upper 16 bits */
+	if (tmp & 0xffff0000) {
+		DRM_INFO("Probable bad vram size: 0x%08x\n", tmp);
+		if (tmp & 0xffff)
+			tmp &= 0xffff;
+	}
+	adev->gmc.mc_vram_size = tmp * 1024ULL * 1024ULL;
+	adev->gmc.real_vram_size = adev->gmc.mc_vram_size;
 
 	if (!(adev->flags & AMD_IS_APU)) {
 		r = amdgpu_device_resize_fb_bar(adev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
@@ -448,6 +448,24 @@
 	return req;
 }
 
+/**
+ * gmc_v9_0_use_invalidate_semaphore - judge whether to use semaphore
+ *
+ * @adev: amdgpu_device pointer
+ * @vmhub: vmhub type
+ *
+ */
+static bool gmc_v9_0_use_invalidate_semaphore(struct amdgpu_device *adev,
+				       uint32_t vmhub)
+{
+	return ((vmhub == AMDGPU_MMHUB_0 ||
+		 vmhub == AMDGPU_MMHUB_1) &&
+		(!amdgpu_sriov_vf(adev)) &&
+		(!(adev->asic_type == CHIP_RAVEN &&
+		   adev->rev_id < 0x8 &&
+		   adev->pdev->device == 0x15d8)));
+}
+
 /*
  * GART
  * VMID 0 is the physical GPU addresses as used by the kernel.
@@ -467,14 +485,15 @@
 static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
 					uint32_t vmhub, uint32_t flush_type)
 {
+	bool use_semaphore = gmc_v9_0_use_invalidate_semaphore(adev, vmhub);
 	const unsigned eng = 17;
-	u32 j, tmp;
+	u32 j, inv_req, tmp;
 	struct amdgpu_vmhub *hub;
 
 	BUG_ON(vmhub >= adev->num_vmhubs);
 
 	hub = &adev->vmhub[vmhub];
-	tmp = gmc_v9_0_get_invalidate_req(vmid, flush_type);
+	inv_req = gmc_v9_0_get_invalidate_req(vmid, flush_type);
 
 	/* This is necessary for a HW workaround under SRIOV as well
 	 * as GFXOFF under bare metal
@@ -485,13 +504,35 @@
 		uint32_t req = hub->vm_inv_eng0_req + eng;
 		uint32_t ack = hub->vm_inv_eng0_ack + eng;
 
-		amdgpu_virt_kiq_reg_write_reg_wait(adev, req, ack, tmp,
+		amdgpu_virt_kiq_reg_write_reg_wait(adev, req, ack, inv_req,
 				1 << vmid);
 		return;
 	}
 
 	spin_lock(&adev->gmc.invalidate_lock);
-	WREG32_NO_KIQ(hub->vm_inv_eng0_req + eng, tmp);
+
+	/*
+	 * It may lose gpuvm invalidate acknowldege state across power-gating
+	 * off cycle, add semaphore acquire before invalidation and semaphore
+	 * release after invalidation to avoid entering power gated state
+	 * to WA the Issue
+	 */
+
+	/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
+	if (use_semaphore) {
+		for (j = 0; j < adev->usec_timeout; j++) {
+			/* a read return value of 1 means semaphore acuqire */
+			tmp = RREG32_NO_KIQ(hub->vm_inv_eng0_sem + eng);
+			if (tmp & 0x1)
+				break;
+			udelay(1);
+		}
+
+		if (j >= adev->usec_timeout)
+			DRM_ERROR("Timeout waiting for sem acquire in VM flush!\n");
+	}
+
+	WREG32_NO_KIQ(hub->vm_inv_eng0_req + eng, inv_req);
 
 	/*
 	 * Issue a dummy read to wait for the ACK register to be cleared
@@ -506,7 +547,17 @@
 			break;
 		udelay(1);
 	}
+
+	/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
+	if (use_semaphore)
+		/*
+		 * add semaphore release after invalidation,
+		 * write with 0 means semaphore release
+		 */
+		WREG32_NO_KIQ(hub->vm_inv_eng0_sem + eng, 0);
+
 	spin_unlock(&adev->gmc.invalidate_lock);
+
 	if (j < adev->usec_timeout)
 		return;
 
@@ -516,11 +567,25 @@
 static uint64_t gmc_v9_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
 					    unsigned vmid, uint64_t pd_addr)
 {
+	bool use_semaphore = gmc_v9_0_use_invalidate_semaphore(ring->adev, ring->funcs->vmhub);
 	struct amdgpu_device *adev = ring->adev;
 	struct amdgpu_vmhub *hub = &adev->vmhub[ring->funcs->vmhub];
 	uint32_t req = gmc_v9_0_get_invalidate_req(vmid, 0);
 	unsigned eng = ring->vm_inv_eng;
 
+	/*
+	 * It may lose gpuvm invalidate acknowldege state across power-gating
+	 * off cycle, add semaphore acquire before invalidation and semaphore
+	 * release after invalidation to avoid entering power gated state
+	 * to WA the Issue
+	 */
+
+	/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
+	if (use_semaphore)
+		/* a read return value of 1 means semaphore acuqire */
+		amdgpu_ring_emit_reg_wait(ring,
+					  hub->vm_inv_eng0_sem + eng, 0x1, 0x1);
+
 	amdgpu_ring_emit_wreg(ring, hub->ctx0_ptb_addr_lo32 + (2 * vmid),
 			      lower_32_bits(pd_addr));
 
@@ -531,6 +596,14 @@
 					    hub->vm_inv_eng0_ack + eng,
 					    req, 1 << vmid);
 
+	/* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
+	if (use_semaphore)
+		/*
+		 * add semaphore release after invalidation,
+		 * write with 0 means semaphore release
+		 */
+		amdgpu_ring_emit_wreg(ring, hub->vm_inv_eng0_sem + eng, 0);
+
 	return pd_addr;
 }
 
@@ -1310,6 +1383,19 @@
 }
 
 /**
+ * gmc_v9_0_restore_registers - restores regs
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * This restores register values, saved at suspend.
+ */
+static void gmc_v9_0_restore_registers(struct amdgpu_device *adev)
+{
+	if (adev->asic_type == CHIP_RAVEN)
+		WREG32(mmDCHUBBUB_SDPIF_MMIO_CNTRL_0, adev->gmc.sdpif_register);
+}
+
+/**
  * gmc_v9_0_gart_enable - gart enable
  *
  * @adev: amdgpu_device pointer
@@ -1406,6 +1492,20 @@
 }
 
 /**
+ * gmc_v9_0_save_registers - saves regs
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * This saves potential register values that should be
+ * restored upon resume
+ */
+static void gmc_v9_0_save_registers(struct amdgpu_device *adev)
+{
+	if (adev->asic_type == CHIP_RAVEN)
+		adev->gmc.sdpif_register = RREG32(mmDCHUBBUB_SDPIF_MMIO_CNTRL_0);
+}
+
+/**
  * gmc_v9_0_gart_disable - gart disable
  *
  * @adev: amdgpu_device pointer
@@ -1426,24 +1526,31 @@
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
+	gmc_v9_0_gart_disable(adev);
+
 	if (amdgpu_sriov_vf(adev)) {
 		/* full access mode, so don't touch any GMC register */
 		DRM_DEBUG("For SRIOV client, shouldn't do anything.\n");
 		return 0;
 	}
 
-	amdgpu_irq_put(adev, &adev->gmc.ecc_irq, 0);
 	amdgpu_irq_put(adev, &adev->gmc.vm_fault, 0);
-	gmc_v9_0_gart_disable(adev);
 
 	return 0;
 }
 
 static int gmc_v9_0_suspend(void *handle)
 {
+	int r;
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-	return gmc_v9_0_hw_fini(adev);
+	r = gmc_v9_0_hw_fini(adev);
+	if (r)
+		return r;
+
+	gmc_v9_0_save_registers(adev);
+
+	return 0;
 }
 
 static int gmc_v9_0_resume(void *handle)
@@ -1451,6 +1558,7 @@
 	int r;
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
+	gmc_v9_0_restore_registers(adev);
 	r = gmc_v9_0_hw_init(adev);
 	if (r)
 		return r;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/iceland_ih.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/iceland_ih.c
@@ -193,19 +193,34 @@
 
 	wptr = le32_to_cpu(*ih->wptr_cpu);
 
-	if (REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) {
-		wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0);
-		/* When a ring buffer overflow happen start parsing interrupt
-		 * from the last not overwritten vector (wptr + 16). Hopefully
-		 * this should allow us to catchup.
-		 */
-		dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
-			 wptr, ih->rptr, (wptr + 16) & ih->ptr_mask);
-		ih->rptr = (wptr + 16) & ih->ptr_mask;
-		tmp = RREG32(mmIH_RB_CNTL);
-		tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
-		WREG32(mmIH_RB_CNTL, tmp);
-	}
+	if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW))
+		goto out;
+
+	/* Double check that the overflow wasn't already cleared. */
+	wptr = RREG32(mmIH_RB_WPTR);
+
+	if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW))
+		goto out;
+
+	wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0);
+	/* When a ring buffer overflow happen start parsing interrupt
+	 * from the last not overwritten vector (wptr + 16). Hopefully
+	 * this should allow us to catchup.
+	 */
+	dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
+		wptr, ih->rptr, (wptr + 16) & ih->ptr_mask);
+	ih->rptr = (wptr + 16) & ih->ptr_mask;
+	tmp = RREG32(mmIH_RB_CNTL);
+	tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
+	WREG32(mmIH_RB_CNTL, tmp);
+
+	/* Unset the CLEAR_OVERFLOW bit immediately so new overflows
+	 * can be detected.
+	 */
+	tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 0);
+	WREG32(mmIH_RB_CNTL, tmp);
+
+out:
 	return (wptr & ih->ptr_mask);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/kv_dpm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/kv_dpm.c
@@ -163,6 +163,8 @@
 
 	for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++) {
 		if (table[i].ulSupportedSCLK != 0) {
+			if (table[i].usVoltageIndex >= SUMO_MAX_NUMBER_VOLTAGES)
+				continue;
 			vid_mapping_table->entries[table[i].usVoltageIndex].vid_7bit =
 				table[i].usVoltageID;
 			vid_mapping_table->entries[table[i].usVoltageIndex].vid_2bit =
@@ -1609,19 +1611,7 @@
 
 static u8 kv_get_acp_boot_level(struct amdgpu_device *adev)
 {
-	u8 i;
-	struct amdgpu_clock_voltage_dependency_table *table =
-		&adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table;
-
-	for (i = 0; i < table->count; i++) {
-		if (table->entries[i].clk >= 0) /* XXX */
-			break;
-	}
-
-	if (i >= table->count)
-		i = table->count - 1;
-
-	return i;
+	return 0;
 }
 
 static void kv_update_acp_boot_level(struct amdgpu_device *adev)
@@ -2745,10 +2735,8 @@
 		non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
 			&non_clock_info_array->nonClockInfo[non_clock_array_index];
 		ps = kzalloc(sizeof(struct kv_ps), GFP_KERNEL);
-		if (ps == NULL) {
-			kfree(adev->pm.dpm.ps);
+		if (ps == NULL)
 			return -ENOMEM;
-		}
 		adev->pm.dpm.ps[i].ps_priv = ps;
 		k = 0;
 		idx = (u8 *)&power_state->v2.clockInfoIndex[0];
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c
@@ -29,8 +29,6 @@
 #include "gc/gc_10_1_0_offset.h"
 #include "gc/gc_10_1_0_sh_mask.h"
 
-MODULE_FIRMWARE("amdgpu/navi10_mes.bin");
-
 static int mes_v10_1_add_hw_queue(struct amdgpu_mes *mes,
 				  struct mes_add_queue_input *input)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c
@@ -182,6 +182,7 @@
 	tmp = REG_SET_FIELD(tmp, VM_L2_CNTL2, INVALIDATE_L2_CACHE, 1);
 	WREG32_SOC15(MMHUB, 0, mmVM_L2_CNTL2, tmp);
 
+	tmp = mmVM_L2_CNTL3_DEFAULT;
 	if (adev->gmc.translate_further) {
 		tmp = REG_SET_FIELD(tmp, VM_L2_CNTL3, BANK_SELECT, 12);
 		tmp = REG_SET_FIELD(tmp, VM_L2_CNTL3,
@@ -418,6 +419,8 @@
 	hub->ctx0_ptb_addr_hi32 =
 		SOC15_REG_OFFSET(MMHUB, 0,
 				 mmVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32);
+	hub->vm_inv_eng0_sem =
+		SOC15_REG_OFFSET(MMHUB, 0, mmVM_INVALIDATE_ENG0_SEM);
 	hub->vm_inv_eng0_req =
 		SOC15_REG_OFFSET(MMHUB, 0, mmVM_INVALIDATE_ENG0_REQ);
 	hub->vm_inv_eng0_ack =
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c
@@ -341,6 +341,8 @@
 	hub->ctx0_ptb_addr_hi32 =
 		SOC15_REG_OFFSET(MMHUB, 0,
 				 mmMMVM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32);
+	hub->vm_inv_eng0_sem =
+		SOC15_REG_OFFSET(MMHUB, 0, mmMMVM_INVALIDATE_ENG0_SEM);
 	hub->vm_inv_eng0_req =
 		SOC15_REG_OFFSET(MMHUB, 0, mmMMVM_INVALIDATE_ENG0_REQ);
 	hub->vm_inv_eng0_ack =
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c
@@ -502,6 +502,10 @@
 			SOC15_REG_OFFSET(MMHUB, 0,
 			    mmVML2VC0_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR_HI32) +
 			    i * MMHUB_INSTANCE_REGISTER_OFFSET;
+		hub[i]->vm_inv_eng0_sem =
+			SOC15_REG_OFFSET(MMHUB, 0,
+					 mmVML2VC0_VM_INVALIDATE_ENG0_SEM) +
+					 i * MMHUB_INSTANCE_REGISTER_OFFSET;
 		hub[i]->vm_inv_eng0_req =
 			SOC15_REG_OFFSET(MMHUB, 0,
 					 mmVML2VC0_VM_INVALIDATE_ENG0_REQ) +
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/navi10_ih.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/navi10_ih.c
@@ -237,6 +237,12 @@
 	tmp = RREG32_NO_KIQ(reg);
 	tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
 	WREG32_NO_KIQ(reg, tmp);
+
+	/* Unset the CLEAR_OVERFLOW bit immediately so new overflows
+	 * can be detected.
+	 */
+	tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 0);
+	WREG32_NO_KIQ(reg, tmp);
 out:
 	return (wptr & ih->ptr_mask);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/navi10_sdma_pkt_open.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/navi10_sdma_pkt_open.h
@@ -73,6 +73,22 @@
 #define SDMA_OP_AQL_COPY  0
 #define SDMA_OP_AQL_BARRIER_OR  0
 
+#define SDMA_GCR_RANGE_IS_PA		(1 << 18)
+#define SDMA_GCR_SEQ(x)			(((x) & 0x3) << 16)
+#define SDMA_GCR_GL2_WB			(1 << 15)
+#define SDMA_GCR_GL2_INV		(1 << 14)
+#define SDMA_GCR_GL2_DISCARD		(1 << 13)
+#define SDMA_GCR_GL2_RANGE(x)		(((x) & 0x3) << 11)
+#define SDMA_GCR_GL2_US			(1 << 10)
+#define SDMA_GCR_GL1_INV		(1 << 9)
+#define SDMA_GCR_GLV_INV		(1 << 8)
+#define SDMA_GCR_GLK_INV		(1 << 7)
+#define SDMA_GCR_GLK_WB			(1 << 6)
+#define SDMA_GCR_GLM_INV		(1 << 5)
+#define SDMA_GCR_GLM_WB			(1 << 4)
+#define SDMA_GCR_GL1_RANGE(x)		(((x) & 0x3) << 2)
+#define SDMA_GCR_GLI_INV(x)		(((x) & 0x3) << 0)
+
 /*define for op field*/
 #define SDMA_PKT_HEADER_op_offset 0
 #define SDMA_PKT_HEADER_op_mask   0x000000FF
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/nv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/nv.c
@@ -660,6 +660,12 @@
 		adev->pg_flags = AMD_PG_SUPPORT_VCN |
 			AMD_PG_SUPPORT_VCN_DPG |
 			AMD_PG_SUPPORT_ATHUB;
+		/* guest vm gets 0xffffffff when reading RCC_DEV0_EPF0_STRAP0,
+		 * as a consequence, the rev_id and external_rev_id are wrong.
+		 * workaround it by hardcoding rev_id to 0 (default value).
+		 */
+		if (amdgpu_sriov_vf(adev))
+			adev->rev_id = 0;
 		adev->external_rev_id = adev->rev_id + 0xa;
 		break;
 	default:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/psp_gfx_if.h
@@ -44,7 +44,7 @@
     GFX_CTRL_CMD_ID_DISABLE_INT     = 0x00060000,   /* disable PSP-to-Gfx interrupt */
     GFX_CTRL_CMD_ID_MODE1_RST       = 0x00070000,   /* trigger the Mode 1 reset */
     GFX_CTRL_CMD_ID_GBR_IH_SET      = 0x00080000,   /* set Gbr IH_RB_CNTL registers */
-    GFX_CTRL_CMD_ID_CONSUME_CMD     = 0x000A0000,   /* send interrupt to psp for updating write pointer of vf */
+    GFX_CTRL_CMD_ID_CONSUME_CMD     = 0x00090000,   /* send interrupt to psp for updating write pointer of vf */
     GFX_CTRL_CMD_ID_DESTROY_GPCOM_RING = 0x000C0000, /* destroy GPCOM ring */
 
     GFX_CTRL_CMD_ID_MAX             = 0x000F0000,   /* max command ID */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
@@ -40,15 +40,10 @@
 
 MODULE_FIRMWARE("amdgpu/vega20_sos.bin");
 MODULE_FIRMWARE("amdgpu/vega20_asd.bin");
-MODULE_FIRMWARE("amdgpu/vega20_ta.bin");
 MODULE_FIRMWARE("amdgpu/navi10_sos.bin");
 MODULE_FIRMWARE("amdgpu/navi10_asd.bin");
 MODULE_FIRMWARE("amdgpu/navi14_sos.bin");
 MODULE_FIRMWARE("amdgpu/navi14_asd.bin");
-MODULE_FIRMWARE("amdgpu/navi12_sos.bin");
-MODULE_FIRMWARE("amdgpu/navi12_asd.bin");
-MODULE_FIRMWARE("amdgpu/arcturus_sos.bin");
-MODULE_FIRMWARE("amdgpu/arcturus_asd.bin");
 
 /* address block */
 #define smnMP1_FIRMWARE_FLAGS		0x3010024
@@ -398,6 +393,34 @@
 	return false;
 }
 
+static int psp_v11_0_ring_stop(struct psp_context *psp,
+			      enum psp_ring_type ring_type)
+{
+	int ret = 0;
+	struct amdgpu_device *adev = psp->adev;
+
+	/* Write the ring destroy command*/
+	if (psp_v11_0_support_vmr_ring(psp))
+		WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_101,
+				     GFX_CTRL_CMD_ID_DESTROY_GPCOM_RING);
+	else
+		WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_64,
+				     GFX_CTRL_CMD_ID_DESTROY_RINGS);
+
+	/* there might be handshake issue with hardware which needs delay */
+	mdelay(20);
+
+	/* Wait for response flag (bit 31) */
+	if (psp_v11_0_support_vmr_ring(psp))
+		ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_101),
+				   0x80000000, 0x80000000, false);
+	else
+		ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
+				   0x80000000, 0x80000000, false);
+
+	return ret;
+}
+
 static int psp_v11_0_ring_create(struct psp_context *psp,
 				enum psp_ring_type ring_type)
 {
@@ -407,6 +430,12 @@
 	struct amdgpu_device *adev = psp->adev;
 
 	if (psp_v11_0_support_vmr_ring(psp)) {
+		ret = psp_v11_0_ring_stop(psp, ring_type);
+		if (ret) {
+			DRM_ERROR("psp_v11_0_ring_stop_sriov failed!\n");
+			return ret;
+		}
+
 		/* Write low address of the ring to C2PMSG_102 */
 		psp_ring_reg = lower_32_bits(ring->ring_mem_mc_addr);
 		WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_102, psp_ring_reg);
@@ -451,33 +480,6 @@
 	return ret;
 }
 
-static int psp_v11_0_ring_stop(struct psp_context *psp,
-			      enum psp_ring_type ring_type)
-{
-	int ret = 0;
-	struct amdgpu_device *adev = psp->adev;
-
-	/* Write the ring destroy command*/
-	if (psp_v11_0_support_vmr_ring(psp))
-		WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_101,
-				     GFX_CTRL_CMD_ID_DESTROY_GPCOM_RING);
-	else
-		WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_64,
-				     GFX_CTRL_CMD_ID_DESTROY_RINGS);
-
-	/* there might be handshake issue with hardware which needs delay */
-	mdelay(20);
-
-	/* Wait for response flag (bit 31) */
-	if (psp_v11_0_support_vmr_ring(psp))
-		ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_101),
-				   0x80000000, 0x80000000, false);
-	else
-		ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
-				   0x80000000, 0x80000000, false);
-
-	return ret;
-}
 
 static int psp_v11_0_ring_destroy(struct psp_context *psp,
 				 enum psp_ring_type ring_type)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
@@ -255,7 +255,7 @@
 	unsigned vmid = AMDGPU_JOB_GET_VMID(job);
 
 	/* IB packet must end on a 8 DW boundary */
-	sdma_v2_4_ring_insert_nop(ring, (10 - (lower_32_bits(ring->wptr) & 7)) % 8);
+	sdma_v2_4_ring_insert_nop(ring, (2 - lower_32_bits(ring->wptr)) & 7);
 
 	amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_INDIRECT) |
 			  SDMA_PKT_INDIRECT_HEADER_VMID(vmid & 0xf));
@@ -750,7 +750,7 @@
 	u32 pad_count;
 	int i;
 
-	pad_count = (8 - (ib->length_dw & 0x7)) % 8;
+	pad_count = (-ib->length_dw) & 7;
 	for (i = 0; i < pad_count; i++)
 		if (sdma && sdma->burst_nop && (i == 0))
 			ib->ptr[ib->length_dw++] =
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
@@ -429,7 +429,7 @@
 	unsigned vmid = AMDGPU_JOB_GET_VMID(job);
 
 	/* IB packet must end on a 8 DW boundary */
-	sdma_v3_0_ring_insert_nop(ring, (10 - (lower_32_bits(ring->wptr) & 7)) % 8);
+	sdma_v3_0_ring_insert_nop(ring, (2 - lower_32_bits(ring->wptr)) & 7);
 
 	amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_INDIRECT) |
 			  SDMA_PKT_INDIRECT_HEADER_VMID(vmid & 0xf));
@@ -1021,7 +1021,7 @@
 	u32 pad_count;
 	int i;
 
-	pad_count = (8 - (ib->length_dw & 0x7)) % 8;
+	pad_count = (-ib->length_dw) & 7;
 	for (i = 0; i < pad_count; i++)
 		if (sdma && sdma->burst_nop && (i == 0))
 			ib->ptr[ib->length_dw++] =
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
@@ -67,7 +67,6 @@
 MODULE_FIRMWARE("amdgpu/raven_sdma.bin");
 MODULE_FIRMWARE("amdgpu/picasso_sdma.bin");
 MODULE_FIRMWARE("amdgpu/raven2_sdma.bin");
-MODULE_FIRMWARE("amdgpu/arcturus_sdma.bin");
 MODULE_FIRMWARE("amdgpu/renoir_sdma.bin");
 
 #define SDMA0_POWER_CNTL__ON_OFF_CONDITION_HOLD_TIME_MASK  0x000000F8L
@@ -698,7 +697,7 @@
 	unsigned vmid = AMDGPU_JOB_GET_VMID(job);
 
 	/* IB packet must end on a 8 DW boundary */
-	sdma_v4_0_ring_insert_nop(ring, (10 - (lower_32_bits(ring->wptr) & 7)) % 8);
+	sdma_v4_0_ring_insert_nop(ring, (2 - lower_32_bits(ring->wptr)) & 7);
 
 	amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_INDIRECT) |
 			  SDMA_PKT_INDIRECT_HEADER_VMID(vmid & 0xf));
@@ -1579,7 +1578,7 @@
 	u32 pad_count;
 	int i;
 
-	pad_count = (8 - (ib->length_dw & 0x7)) % 8;
+	pad_count = (-ib->length_dw) & 7;
 	for (i = 0; i < pad_count; i++)
 		if (sdma && sdma->burst_nop && (i == 0))
 			ib->ptr[ib->length_dw++] =
@@ -1911,9 +1910,11 @@
 	if (amdgpu_sriov_vf(adev))
 		return 0;
 
-	for (i = 0; i < adev->sdma.num_instances; i++) {
-		amdgpu_irq_put(adev, &adev->sdma.ecc_irq,
-			       AMDGPU_SDMA_IRQ_INSTANCE0 + i);
+	if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__SDMA)) {
+		for (i = 0; i < adev->sdma.num_instances; i++) {
+			amdgpu_irq_put(adev, &adev->sdma.ecc_irq,
+				       AMDGPU_SDMA_IRQ_INSTANCE0 + i);
+		}
 	}
 
 	sdma_v4_0_ctx_switch_enable(adev, false);
@@ -2001,10 +2002,13 @@
 				      struct amdgpu_irq_src *source,
 				      struct amdgpu_iv_entry *entry)
 {
-	uint32_t instance;
+	int instance;
 
 	DRM_DEBUG("IH: SDMA trap\n");
 	instance = sdma_v4_0_irq_id_to_seq(entry->client_id);
+	if (instance < 0)
+		return instance;
+
 	switch (entry->ring_id) {
 	case 0:
 		amdgpu_fence_process(&adev->sdma.instance[instance].ring);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c
@@ -48,9 +48,6 @@
 MODULE_FIRMWARE("amdgpu/navi14_sdma.bin");
 MODULE_FIRMWARE("amdgpu/navi14_sdma1.bin");
 
-MODULE_FIRMWARE("amdgpu/navi12_sdma.bin");
-MODULE_FIRMWARE("amdgpu/navi12_sdma1.bin");
-
 #define SDMA1_REG_OFFSET 0x600
 #define SDMA0_HYP_DEC_REG_START 0x5880
 #define SDMA0_HYP_DEC_REG_END 0x5893
@@ -100,6 +97,10 @@
 
 static const struct soc15_reg_golden golden_settings_sdma_nv12[] = {
 	SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_RLC3_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+	SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_GB_ADDR_CONFIG, 0x001877ff, 0x00000044),
+	SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_GB_ADDR_CONFIG_READ, 0x001877ff, 0x00000044),
+	SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_GB_ADDR_CONFIG, 0x001877ff, 0x00000044),
+	SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_GB_ADDR_CONFIG_READ, 0x001877ff, 0x00000044),
 	SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_RLC3_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
 };
 
@@ -286,30 +287,20 @@
 static uint64_t sdma_v5_0_ring_get_wptr(struct amdgpu_ring *ring)
 {
 	struct amdgpu_device *adev = ring->adev;
-	u64 *wptr = NULL;
-	uint64_t local_wptr = 0;
+	u64 wptr;
 
 	if (ring->use_doorbell) {
 		/* XXX check if swapping is necessary on BE */
-		wptr = ((u64 *)&adev->wb.wb[ring->wptr_offs]);
-		DRM_DEBUG("wptr/doorbell before shift == 0x%016llx\n", *wptr);
-		*wptr = (*wptr) >> 2;
-		DRM_DEBUG("wptr/doorbell after shift == 0x%016llx\n", *wptr);
+		wptr = READ_ONCE(*((u64 *)&adev->wb.wb[ring->wptr_offs]));
+		DRM_DEBUG("wptr/doorbell before shift == 0x%016llx\n", wptr);
 	} else {
-		u32 lowbit, highbit;
-
-		wptr = &local_wptr;
-		lowbit = RREG32(sdma_v5_0_get_reg_offset(adev, ring->me, mmSDMA0_GFX_RB_WPTR)) >> 2;
-		highbit = RREG32(sdma_v5_0_get_reg_offset(adev, ring->me, mmSDMA0_GFX_RB_WPTR_HI)) >> 2;
-
-		DRM_DEBUG("wptr [%i]high== 0x%08x low==0x%08x\n",
-				ring->me, highbit, lowbit);
-		*wptr = highbit;
-		*wptr = (*wptr) << 32;
-		*wptr |= lowbit;
+		wptr = RREG32(sdma_v5_0_get_reg_offset(adev, ring->me, mmSDMA0_GFX_RB_WPTR_HI));
+		wptr = wptr << 32;
+		wptr |= RREG32(sdma_v5_0_get_reg_offset(adev, ring->me, mmSDMA0_GFX_RB_WPTR));
+		DRM_DEBUG("wptr before shift [%i] wptr == 0x%016llx\n", ring->me, wptr);
 	}
 
-	return *wptr;
+	return wptr >> 2;
 }
 
 /**
@@ -382,8 +373,27 @@
 	unsigned vmid = AMDGPU_JOB_GET_VMID(job);
 	uint64_t csa_mc_addr = amdgpu_sdma_get_csa_mc_addr(ring, vmid);
 
-	/* IB packet must end on a 8 DW boundary */
-	sdma_v5_0_ring_insert_nop(ring, (10 - (lower_32_bits(ring->wptr) & 7)) % 8);
+	/* Invalidate L2, because if we don't do it, we might get stale cache
+	 * lines from previous IBs.
+	 */
+	amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_GCR_REQ));
+	amdgpu_ring_write(ring, 0);
+	amdgpu_ring_write(ring, (SDMA_GCR_GL2_INV |
+				 SDMA_GCR_GL2_WB |
+				 SDMA_GCR_GLM_INV |
+				 SDMA_GCR_GLM_WB) << 16);
+	amdgpu_ring_write(ring, 0xffffff80);
+	amdgpu_ring_write(ring, 0xffff);
+
+	/* An IB packet must end on a 8 DW boundary--the next dword
+	 * must be on a 8-dword boundary. Our IB packet below is 6
+	 * dwords long, thus add x number of NOPs, such that, in
+	 * modular arithmetic,
+	 * wptr + 6 + x = 8k, k >= 0, which in C is,
+	 * (wptr + 6 + x) % 8 = 0.
+	 * The expression below, is a solution of x.
+	 */
+	sdma_v5_0_ring_insert_nop(ring, (2 - lower_32_bits(ring->wptr)) & 7);
 
 	amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_INDIRECT) |
 			  SDMA_PKT_INDIRECT_HEADER_VMID(vmid & 0xf));
@@ -1086,10 +1096,10 @@
 }
 
 /**
- * sdma_v5_0_ring_pad_ib - pad the IB to the required number of dw
- *
+ * sdma_v5_0_ring_pad_ib - pad the IB
  * @ib: indirect buffer to fill with padding
  *
+ * Pad the IB with NOPs to a boundary multiple of 8.
  */
 static void sdma_v5_0_ring_pad_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib)
 {
@@ -1097,7 +1107,7 @@
 	u32 pad_count;
 	int i;
 
-	pad_count = (8 - (ib->length_dw & 0x7)) % 8;
+	pad_count = (-ib->length_dw) & 0x7;
 	for (i = 0; i < pad_count; i++)
 		if (sdma && sdma->burst_nop && (i == 0))
 			ib->ptr[ib->length_dw++] =
@@ -1254,8 +1264,12 @@
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 	int i;
 
-	for (i = 0; i < adev->sdma.num_instances; i++)
+	for (i = 0; i < adev->sdma.num_instances; i++) {
+		if (adev->sdma.instance[i].fw != NULL)
+			release_firmware(adev->sdma.instance[i].fw);
+
 		amdgpu_ring_fini(&adev->sdma.instance[i].ring);
+	}
 
 	return 0;
 }
@@ -1600,7 +1614,7 @@
 		SOC15_FLUSH_GPU_TLB_NUM_WREG * 3 +
 		SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 6 * 2 +
 		10 + 10 + 10, /* sdma_v5_0_ring_emit_fence x3 for user fence, vm fence */
-	.emit_ib_size = 7 + 6, /* sdma_v5_0_ring_emit_ib */
+	.emit_ib_size = 5 + 7 + 6, /* sdma_v5_0_ring_emit_ib */
 	.emit_ib = sdma_v5_0_ring_emit_ib,
 	.emit_fence = sdma_v5_0_ring_emit_fence,
 	.emit_pipeline_sync = sdma_v5_0_ring_emit_pipeline_sync,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/si.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/si.c
@@ -1633,7 +1633,6 @@
 static void si_pcie_gen3_enable(struct amdgpu_device *adev)
 {
 	struct pci_dev *root = adev->pdev->bus->self;
-	int bridge_pos, gpu_pos;
 	u32 speed_cntl, current_data_rate;
 	int i;
 	u16 tmp16;
@@ -1668,12 +1667,7 @@
 		DRM_INFO("enabling PCIE gen 2 link speeds, disable with amdgpu.pcie_gen2=0\n");
 	}
 
-	bridge_pos = pci_pcie_cap(root);
-	if (!bridge_pos)
-		return;
-
-	gpu_pos = pci_pcie_cap(adev->pdev);
-	if (!gpu_pos)
+	if (!pci_is_pcie(root) || !pci_is_pcie(adev->pdev))
 		return;
 
 	if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) {
@@ -1682,14 +1676,8 @@
 			u16 bridge_cfg2, gpu_cfg2;
 			u32 max_lw, current_lw, tmp;
 
-			pci_read_config_word(root, bridge_pos + PCI_EXP_LNKCTL, &bridge_cfg);
-			pci_read_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL, &gpu_cfg);
-
-			tmp16 = bridge_cfg | PCI_EXP_LNKCTL_HAWD;
-			pci_write_config_word(root, bridge_pos + PCI_EXP_LNKCTL, tmp16);
-
-			tmp16 = gpu_cfg | PCI_EXP_LNKCTL_HAWD;
-			pci_write_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL, tmp16);
+			pcie_capability_set_word(root, PCI_EXP_LNKCTL, PCI_EXP_LNKCTL_HAWD);
+			pcie_capability_set_word(adev->pdev, PCI_EXP_LNKCTL, PCI_EXP_LNKCTL_HAWD);
 
 			tmp = RREG32_PCIE(PCIE_LC_STATUS1);
 			max_lw = (tmp & LC_DETECTED_LINK_WIDTH_MASK) >> LC_DETECTED_LINK_WIDTH_SHIFT;
@@ -1706,15 +1694,23 @@
 			}
 
 			for (i = 0; i < 10; i++) {
-				pci_read_config_word(adev->pdev, gpu_pos + PCI_EXP_DEVSTA, &tmp16);
+				pcie_capability_read_word(adev->pdev,
+							  PCI_EXP_DEVSTA,
+							  &tmp16);
 				if (tmp16 & PCI_EXP_DEVSTA_TRPND)
 					break;
 
-				pci_read_config_word(root, bridge_pos + PCI_EXP_LNKCTL, &bridge_cfg);
-				pci_read_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL, &gpu_cfg);
-
-				pci_read_config_word(root, bridge_pos + PCI_EXP_LNKCTL2, &bridge_cfg2);
-				pci_read_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL2, &gpu_cfg2);
+				pcie_capability_read_word(root, PCI_EXP_LNKCTL,
+							  &bridge_cfg);
+				pcie_capability_read_word(adev->pdev,
+							  PCI_EXP_LNKCTL,
+							  &gpu_cfg);
+
+				pcie_capability_read_word(root, PCI_EXP_LNKCTL2,
+							  &bridge_cfg2);
+				pcie_capability_read_word(adev->pdev,
+							  PCI_EXP_LNKCTL2,
+							  &gpu_cfg2);
 
 				tmp = RREG32_PCIE_PORT(PCIE_LC_CNTL4);
 				tmp |= LC_SET_QUIESCE;
@@ -1726,25 +1722,37 @@
 
 				mdelay(100);
 
-				pci_read_config_word(root, bridge_pos + PCI_EXP_LNKCTL, &tmp16);
-				tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
-				tmp16 |= (bridge_cfg & PCI_EXP_LNKCTL_HAWD);
-				pci_write_config_word(root, bridge_pos + PCI_EXP_LNKCTL, tmp16);
-
-				pci_read_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL, &tmp16);
-				tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
-				tmp16 |= (gpu_cfg & PCI_EXP_LNKCTL_HAWD);
-				pci_write_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL, tmp16);
-
-				pci_read_config_word(root, bridge_pos + PCI_EXP_LNKCTL2, &tmp16);
-				tmp16 &= ~((1 << 4) | (7 << 9));
-				tmp16 |= (bridge_cfg2 & ((1 << 4) | (7 << 9)));
-				pci_write_config_word(root, bridge_pos + PCI_EXP_LNKCTL2, tmp16);
-
-				pci_read_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL2, &tmp16);
-				tmp16 &= ~((1 << 4) | (7 << 9));
-				tmp16 |= (gpu_cfg2 & ((1 << 4) | (7 << 9)));
-				pci_write_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL2, tmp16);
+				pcie_capability_clear_and_set_word(root, PCI_EXP_LNKCTL,
+								   PCI_EXP_LNKCTL_HAWD,
+								   bridge_cfg &
+								   PCI_EXP_LNKCTL_HAWD);
+				pcie_capability_clear_and_set_word(adev->pdev, PCI_EXP_LNKCTL,
+								   PCI_EXP_LNKCTL_HAWD,
+								   gpu_cfg &
+								   PCI_EXP_LNKCTL_HAWD);
+
+				pcie_capability_read_word(root, PCI_EXP_LNKCTL2,
+							  &tmp16);
+				tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
+					   PCI_EXP_LNKCTL2_TX_MARGIN);
+				tmp16 |= (bridge_cfg2 &
+					  (PCI_EXP_LNKCTL2_ENTER_COMP |
+					   PCI_EXP_LNKCTL2_TX_MARGIN));
+				pcie_capability_write_word(root,
+							   PCI_EXP_LNKCTL2,
+							   tmp16);
+
+				pcie_capability_read_word(adev->pdev,
+							  PCI_EXP_LNKCTL2,
+							  &tmp16);
+				tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
+					   PCI_EXP_LNKCTL2_TX_MARGIN);
+				tmp16 |= (gpu_cfg2 &
+					  (PCI_EXP_LNKCTL2_ENTER_COMP |
+					   PCI_EXP_LNKCTL2_TX_MARGIN));
+				pcie_capability_write_word(adev->pdev,
+							   PCI_EXP_LNKCTL2,
+							   tmp16);
 
 				tmp = RREG32_PCIE_PORT(PCIE_LC_CNTL4);
 				tmp &= ~LC_SET_QUIESCE;
@@ -1757,15 +1765,16 @@
 	speed_cntl &= ~LC_FORCE_DIS_SW_SPEED_CHANGE;
 	WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, speed_cntl);
 
-	pci_read_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL2, &tmp16);
-	tmp16 &= ~0xf;
+	pcie_capability_read_word(adev->pdev, PCI_EXP_LNKCTL2, &tmp16);
+	tmp16 &= ~PCI_EXP_LNKCTL2_TLS;
+
 	if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
-		tmp16 |= 3;
+		tmp16 |= PCI_EXP_LNKCTL2_TLS_8_0GT; /* gen3 */
 	else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2)
-		tmp16 |= 2;
+		tmp16 |= PCI_EXP_LNKCTL2_TLS_5_0GT; /* gen2 */
 	else
-		tmp16 |= 1;
-	pci_write_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL2, tmp16);
+		tmp16 |= PCI_EXP_LNKCTL2_TLS_2_5GT; /* gen1 */
+	pcie_capability_write_word(adev->pdev, PCI_EXP_LNKCTL2, tmp16);
 
 	speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL);
 	speed_cntl |= LC_INITIATE_LINK_SPEED_CHANGE;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/si_dpm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/si_dpm.c
@@ -7250,17 +7250,15 @@
 	if (!adev->pm.dpm.ps)
 		return -ENOMEM;
 	power_state_offset = (u8 *)state_array->states;
-	for (i = 0; i < state_array->ucNumEntries; i++) {
+	for (adev->pm.dpm.num_ps = 0, i = 0; i < state_array->ucNumEntries; i++) {
 		u8 *idx;
 		power_state = (union pplib_power_state *)power_state_offset;
 		non_clock_array_index = power_state->v2.nonClockInfoIndex;
 		non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
 			&non_clock_info_array->nonClockInfo[non_clock_array_index];
 		ps = kzalloc(sizeof(struct  si_ps), GFP_KERNEL);
-		if (ps == NULL) {
-			kfree(adev->pm.dpm.ps);
+		if (ps == NULL)
 			return -ENOMEM;
-		}
 		adev->pm.dpm.ps[i].ps_priv = ps;
 		si_parse_pplib_non_clock_info(adev, &adev->pm.dpm.ps[i],
 					      non_clock_info,
@@ -7282,8 +7280,8 @@
 			k++;
 		}
 		power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
+		adev->pm.dpm.num_ps++;
 	}
-	adev->pm.dpm.num_ps = state_array->ucNumEntries;
 
 	/* fill in the vce power states */
 	for (i = 0; i < adev->pm.dpm.num_of_vce_states; i++) {
@@ -7351,10 +7349,9 @@
 		kcalloc(4,
 			sizeof(struct amdgpu_clock_voltage_dependency_entry),
 			GFP_KERNEL);
-	if (!adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries) {
-		amdgpu_free_extended_power_table(adev);
+	if (!adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries)
 		return -ENOMEM;
-	}
+
 	adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.count = 4;
 	adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[0].clk = 0;
 	adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[0].v = 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/si_ih.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/si_ih.c
@@ -64,7 +64,8 @@
 	u32 interrupt_cntl, ih_cntl, ih_rb_cntl;
 
 	si_ih_disable_interrupts(adev);
-	WREG32(INTERRUPT_CNTL2, adev->irq.ih.gpu_addr >> 8);
+	/* set dummy read address to dummy page address */
+	WREG32(INTERRUPT_CNTL2, adev->dummy_page_addr >> 8);
 	interrupt_cntl = RREG32(INTERRUPT_CNTL);
 	interrupt_cntl &= ~IH_DUMMY_RD_OVERRIDE;
 	interrupt_cntl &= ~IH_REQ_NONSNOOP_EN;
@@ -116,6 +117,12 @@
 		tmp = RREG32(IH_RB_CNTL);
 		tmp |= IH_RB_CNTL__WPTR_OVERFLOW_CLEAR_MASK;
 		WREG32(IH_RB_CNTL, tmp);
+
+		/* Unset the CLEAR_OVERFLOW bit immediately so new overflows
+		 * can be detected.
+		 */
+		tmp &= ~IH_RB_CNTL__WPTR_OVERFLOW_CLEAR_MASK;
+		WREG32(IH_RB_CNTL, tmp);
 	}
 	return (wptr & ih->ptr_mask);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/soc15.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/soc15.c
@@ -84,6 +84,13 @@
 #define HDP_MEM_POWER_CTRL__RC_MEM_POWER_CTRL_EN_MASK	0x00010000L
 #define HDP_MEM_POWER_CTRL__RC_MEM_POWER_LS_EN_MASK		0x00020000L
 #define mmHDP_MEM_POWER_CTRL_BASE_IDX	0
+
+/* for Vega20/arcturus regiter offset change */
+#define	mmROM_INDEX_VG20				0x00e4
+#define	mmROM_INDEX_VG20_BASE_IDX			0
+#define	mmROM_DATA_VG20					0x00e5
+#define	mmROM_DATA_VG20_BASE_IDX			0
+
 /*
  * Indirect registers accessor
  */
@@ -267,7 +274,14 @@
 
 static u32 soc15_get_xclk(struct amdgpu_device *adev)
 {
-	return adev->clock.spll.reference_freq;
+	u32 reference_clock = adev->clock.spll.reference_freq;
+
+	if (adev->asic_type == CHIP_RENOIR)
+		return 10000;
+	if (adev->asic_type == CHIP_RAVEN)
+		return reference_clock / 4;
+
+	return reference_clock;
 }
 
 
@@ -299,6 +313,8 @@
 {
 	u32 *dw_ptr;
 	u32 i, length_dw;
+	uint32_t rom_index_offset;
+	uint32_t rom_data_offset;
 
 	if (bios == NULL)
 		return false;
@@ -311,11 +327,23 @@
 	dw_ptr = (u32 *)bios;
 	length_dw = ALIGN(length_bytes, 4) / 4;
 
+	switch (adev->asic_type) {
+	case CHIP_VEGA20:
+	case CHIP_ARCTURUS:
+		rom_index_offset = SOC15_REG_OFFSET(SMUIO, 0, mmROM_INDEX_VG20);
+		rom_data_offset = SOC15_REG_OFFSET(SMUIO, 0, mmROM_DATA_VG20);
+		break;
+	default:
+		rom_index_offset = SOC15_REG_OFFSET(SMUIO, 0, mmROM_INDEX);
+		rom_data_offset = SOC15_REG_OFFSET(SMUIO, 0, mmROM_DATA);
+		break;
+	}
+
 	/* set rom index to 0 */
-	WREG32(SOC15_REG_OFFSET(SMUIO, 0, mmROM_INDEX), 0);
+	WREG32(rom_index_offset, 0);
 	/* read out the rom data */
 	for (i = 0; i < length_dw; i++)
-		dw_ptr[i] = RREG32(SOC15_REG_OFFSET(SMUIO, 0, mmROM_DATA));
+		dw_ptr[i] = RREG32(rom_data_offset);
 
 	return true;
 }
@@ -1104,7 +1132,6 @@
 			adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG |
 				AMD_CG_SUPPORT_GFX_MGLS |
 				AMD_CG_SUPPORT_GFX_CP_LS |
-				AMD_CG_SUPPORT_GFX_3D_CGCG |
 				AMD_CG_SUPPORT_GFX_3D_CGLS |
 				AMD_CG_SUPPORT_GFX_CGCG |
 				AMD_CG_SUPPORT_GFX_CGLS |
@@ -1116,16 +1143,17 @@
 				AMD_CG_SUPPORT_SDMA_MGCG |
 				AMD_CG_SUPPORT_SDMA_LS;
 
+			/*
+			 * MMHUB PG needs to be disabled for Picasso for
+			 * stability reasons.
+			 */
 			adev->pg_flags = AMD_PG_SUPPORT_SDMA |
-				AMD_PG_SUPPORT_MMHUB |
-				AMD_PG_SUPPORT_VCN |
-				AMD_PG_SUPPORT_VCN_DPG;
+				AMD_PG_SUPPORT_VCN;
 		} else {
 			adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG |
 				AMD_CG_SUPPORT_GFX_MGLS |
 				AMD_CG_SUPPORT_GFX_RLC_LS |
 				AMD_CG_SUPPORT_GFX_CP_LS |
-				AMD_CG_SUPPORT_GFX_3D_CGCG |
 				AMD_CG_SUPPORT_GFX_3D_CGLS |
 				AMD_CG_SUPPORT_GFX_CGCG |
 				AMD_CG_SUPPORT_GFX_CGLS |
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/soc15.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/soc15.h
@@ -28,8 +28,8 @@
 #include "nbio_v7_0.h"
 #include "nbio_v7_4.h"
 
-#define SOC15_FLUSH_GPU_TLB_NUM_WREG		4
-#define SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT	1
+#define SOC15_FLUSH_GPU_TLB_NUM_WREG		6
+#define SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT	3
 
 extern const struct amd_ip_funcs soc15_common_ip_funcs;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/soc15_common.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/soc15_common.h
@@ -52,6 +52,7 @@
 		uint32_t old_ = 0;	\
 		uint32_t tmp_ = RREG32(adev->reg_offset[ip##_HWIP][inst][reg##_BASE_IDX] + reg); \
 		uint32_t loop = adev->usec_timeout;		\
+		ret = 0;					\
 		while ((tmp_ & (mask)) != (expected_value)) {	\
 			if (old_ != tmp_) {			\
 				loop = adev->usec_timeout;	\
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/tonga_ih.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/tonga_ih.c
@@ -195,19 +195,36 @@
 
 	wptr = le32_to_cpu(*ih->wptr_cpu);
 
-	if (REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) {
-		wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0);
-		/* When a ring buffer overflow happen start parsing interrupt
-		 * from the last not overwritten vector (wptr + 16). Hopefully
-		 * this should allow us to catchup.
-		 */
-		dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
-			 wptr, ih->rptr, (wptr + 16) & ih->ptr_mask);
-		ih->rptr = (wptr + 16) & ih->ptr_mask;
-		tmp = RREG32(mmIH_RB_CNTL);
-		tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
-		WREG32(mmIH_RB_CNTL, tmp);
-	}
+	if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW))
+		goto out;
+
+	/* Double check that the overflow wasn't already cleared. */
+	wptr = RREG32(mmIH_RB_WPTR);
+
+	if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW))
+		goto out;
+
+	wptr = REG_SET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW, 0);
+
+	/* When a ring buffer overflow happen start parsing interrupt
+	 * from the last not overwritten vector (wptr + 16). Hopefully
+	 * this should allow us to catchup.
+	 */
+
+	dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n",
+		wptr, ih->rptr, (wptr + 16) & ih->ptr_mask);
+	ih->rptr = (wptr + 16) & ih->ptr_mask;
+	tmp = RREG32(mmIH_RB_CNTL);
+	tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
+	WREG32(mmIH_RB_CNTL, tmp);
+
+	/* Unset the CLEAR_OVERFLOW bit immediately so new overflows
+	 * can be detected.
+	 */
+	tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 0);
+	WREG32(mmIH_RB_CNTL, tmp);
+
+out:
 	return (wptr & ih->ptr_mask);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
@@ -354,6 +354,7 @@
 
 error:
 	dma_fence_put(fence);
+	amdgpu_bo_unpin(bo);
 	amdgpu_bo_unreserve(bo);
 	amdgpu_bo_unref(&bo);
 	return r;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
@@ -233,9 +233,13 @@
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 	struct amdgpu_ring *ring = &adev->vcn.inst->ring_dec;
 
+	cancel_delayed_work_sync(&adev->vcn.idle_work);
+
 	if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
-		RREG32_SOC15(VCN, 0, mmUVD_STATUS))
+		(adev->vcn.cur_state != AMD_PG_STATE_GATE &&
+		 RREG32_SOC15(VCN, 0, mmUVD_STATUS))) {
 		vcn_v1_0_set_powergating_state(adev, AMD_PG_STATE_GATE);
+	}
 
 	ring->sched.ready = false;
 
@@ -1375,7 +1379,7 @@
 
 	if (enable) {
 		/* wait for STATUS to clear */
-		if (vcn_v1_0_is_idle(handle))
+		if (!vcn_v1_0_is_idle(handle))
 			return -EBUSY;
 		vcn_v1_0_enable_clock_gating(adev);
 	} else {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
@@ -293,6 +293,8 @@
 	struct amdgpu_ring *ring = &adev->vcn.inst->ring_dec;
 	int i;
 
+	cancel_delayed_work_sync(&adev->vcn.idle_work);
+
 	if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
 	    (adev->vcn.cur_state != AMD_PG_STATE_GATE &&
 	      RREG32_SOC15(VCN, 0, mmUVD_STATUS)))
@@ -1026,6 +1028,10 @@
 	tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_RPTR_WR_EN, 1);
 	WREG32_SOC15(UVD, 0, mmUVD_RBC_RB_CNTL, tmp);
 
+	/* Stall DPG before WPTR/RPTR reset */
+	WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_POWER_STATUS),
+		UVD_POWER_STATUS__STALL_DPG_POWER_UP_MASK,
+		~UVD_POWER_STATUS__STALL_DPG_POWER_UP_MASK);
 	/* set the write pointer delay */
 	WREG32_SOC15(UVD, 0, mmUVD_RBC_RB_WPTR_CNTL, 0);
 
@@ -1048,6 +1054,9 @@
 	WREG32_SOC15(UVD, 0, mmUVD_RBC_RB_WPTR,
 		lower_32_bits(ring->wptr));
 
+	/* Unstall DPG */
+	WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_POWER_STATUS),
+		0, ~UVD_POWER_STATUS__STALL_DPG_POWER_UP_MASK);
 	return 0;
 }
 
@@ -1357,8 +1366,13 @@
 					   UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK,
 					   UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK, ret_code);
 
+				/* Stall DPG before WPTR/RPTR reset */
+				WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_POWER_STATUS),
+					   UVD_POWER_STATUS__STALL_DPG_POWER_UP_MASK,
+					   ~UVD_POWER_STATUS__STALL_DPG_POWER_UP_MASK);
 				/* Restore */
 				ring = &adev->vcn.inst->ring_enc[0];
+				ring->wptr = 0;
 				WREG32_SOC15(UVD, 0, mmUVD_RB_BASE_LO, ring->gpu_addr);
 				WREG32_SOC15(UVD, 0, mmUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
 				WREG32_SOC15(UVD, 0, mmUVD_RB_SIZE, ring->ring_size / 4);
@@ -1366,6 +1380,7 @@
 				WREG32_SOC15(UVD, 0, mmUVD_RB_WPTR, lower_32_bits(ring->wptr));
 
 				ring = &adev->vcn.inst->ring_enc[1];
+				ring->wptr = 0;
 				WREG32_SOC15(UVD, 0, mmUVD_RB_BASE_LO2, ring->gpu_addr);
 				WREG32_SOC15(UVD, 0, mmUVD_RB_BASE_HI2, upper_32_bits(ring->gpu_addr));
 				WREG32_SOC15(UVD, 0, mmUVD_RB_SIZE2, ring->ring_size / 4);
@@ -1374,6 +1389,9 @@
 
 				WREG32_SOC15(UVD, 0, mmUVD_RBC_RB_WPTR,
 					   RREG32_SOC15(UVD, 0, mmUVD_SCRATCH2) & 0x7FFFFFFF);
+				/* Unstall DPG */
+				WREG32_P(SOC15_REG_OFFSET(UVD, 0, mmUVD_POWER_STATUS),
+					   0, ~UVD_POWER_STATUS__STALL_DPG_POWER_UP_MASK);
 
 				SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_POWER_STATUS,
 					   UVD_PGFSM_CONFIG__UVDM_UVDU_PWR_ON,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
@@ -302,6 +302,8 @@
 	struct amdgpu_ring *ring;
 	int i;
 
+	cancel_delayed_work_sync(&adev->vcn.idle_work);
+
 	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
 		if (adev->vcn.harvest_config & (1 << i))
 			continue;
@@ -423,7 +425,6 @@
  * vcn_v2_5_disable_clock_gating - disable VCN clock gating
  *
  * @adev: amdgpu_device pointer
- * @sw: enable SW clock gating
  *
  * Disable clock gating for VCN block
  */
@@ -542,7 +543,6 @@
  * vcn_v2_5_enable_clock_gating - enable VCN clock gating
  *
  * @adev: amdgpu_device pointer
- * @sw: enable SW clock gating
  *
  * Enable clock gating for VCN block
  */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/vega10_ih.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/vega10_ih.c
@@ -420,6 +420,12 @@
 	tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
 	WREG32_NO_KIQ(reg, tmp);
 
+	/* Unset the CLEAR_OVERFLOW bit immediately so new overflows
+	 * can be detected.
+	 */
+	tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 0);
+	WREG32_NO_KIQ(reg, tmp);
+
 out:
 	return (wptr & ih->ptr_mask);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdgpu/vi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdgpu/vi.c
@@ -329,8 +329,15 @@
 	u32 reference_clock = adev->clock.spll.reference_freq;
 	u32 tmp;
 
-	if (adev->flags & AMD_IS_APU)
-		return reference_clock;
+	if (adev->flags & AMD_IS_APU) {
+		switch (adev->asic_type) {
+		case CHIP_STONEY:
+			/* vbios says 48Mhz, but the actual freq is 100Mhz */
+			return 10000;
+		default:
+			return reference_clock;
+		}
+	}
 
 	tmp = RREG32_SMC(ixCG_CLKPIN_CNTL_2);
 	if (REG_GET_FIELD(tmp, CG_CLKPIN_CNTL_2, MUX_TCLK_TO_XCLK))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h
@@ -905,7 +905,7 @@
 	0x7a5d0000, 0x807c817c,
 	0x807aff7a, 0x00000080,
 	0xbf0a717c, 0xbf85fff8,
-	0xbf820141, 0xbef4037e,
+	0xbf820142, 0xbef4037e,
 	0x8775ff7f, 0x0000ffff,
 	0x8875ff75, 0x00040000,
 	0xbef60380, 0xbef703ff,
@@ -967,7 +967,7 @@
 	0x725d0000, 0xe0304080,
 	0x725d0100, 0xe0304100,
 	0x725d0200, 0xe0304180,
-	0x725d0300, 0xbf820031,
+	0x725d0300, 0xbf820032,
 	0xbef603ff, 0x01000000,
 	0xbef20378, 0x8078ff78,
 	0x00000400, 0xbefc0384,
@@ -992,83 +992,84 @@
 	0x725d0000, 0xe0304100,
 	0x725d0100, 0xe0304200,
 	0x725d0200, 0xe0304300,
-	0x725d0300, 0xb9782a05,
-	0x80788178, 0x907c9973,
-	0x877c817c, 0xbf06817c,
-	0xbf850002, 0x8f788978,
-	0xbf820001, 0x8f788a78,
-	0xb9721e06, 0x8f728a72,
-	0x80787278, 0x8078ff78,
-	0x00000200, 0x80f8ff78,
-	0x00000050, 0xbef603ff,
-	0x01000000, 0xbefc03ff,
-	0x0000006c, 0x80f89078,
-	0xf429003a, 0xf0000000,
-	0xbf8cc07f, 0x80fc847c,
-	0xbf800000, 0xbe803100,
-	0xbe823102, 0x80f8a078,
-	0xf42d003a, 0xf0000000,
-	0xbf8cc07f, 0x80fc887c,
-	0xbf800000, 0xbe803100,
-	0xbe823102, 0xbe843104,
-	0xbe863106, 0x80f8c078,
-	0xf431003a, 0xf0000000,
-	0xbf8cc07f, 0x80fc907c,
-	0xbf800000, 0xbe803100,
-	0xbe823102, 0xbe843104,
-	0xbe863106, 0xbe883108,
-	0xbe8a310a, 0xbe8c310c,
-	0xbe8e310e, 0xbf06807c,
-	0xbf84fff0, 0xb9782a05,
-	0x80788178, 0x907c9973,
-	0x877c817c, 0xbf06817c,
-	0xbf850002, 0x8f788978,
-	0xbf820001, 0x8f788a78,
-	0xb9721e06, 0x8f728a72,
-	0x80787278, 0x8078ff78,
-	0x00000200, 0xbef603ff,
-	0x01000000, 0xf4211bfa,
+	0x725d0300, 0xbf8c3f70,
+	0xb9782a05, 0x80788178,
+	0x907c9973, 0x877c817c,
+	0xbf06817c, 0xbf850002,
+	0x8f788978, 0xbf820001,
+	0x8f788a78, 0xb9721e06,
+	0x8f728a72, 0x80787278,
+	0x8078ff78, 0x00000200,
+	0x80f8ff78, 0x00000050,
+	0xbef603ff, 0x01000000,
+	0xbefc03ff, 0x0000006c,
+	0x80f89078, 0xf429003a,
+	0xf0000000, 0xbf8cc07f,
+	0x80fc847c, 0xbf800000,
+	0xbe803100, 0xbe823102,
+	0x80f8a078, 0xf42d003a,
+	0xf0000000, 0xbf8cc07f,
+	0x80fc887c, 0xbf800000,
+	0xbe803100, 0xbe823102,
+	0xbe843104, 0xbe863106,
+	0x80f8c078, 0xf431003a,
+	0xf0000000, 0xbf8cc07f,
+	0x80fc907c, 0xbf800000,
+	0xbe803100, 0xbe823102,
+	0xbe843104, 0xbe863106,
+	0xbe883108, 0xbe8a310a,
+	0xbe8c310c, 0xbe8e310e,
+	0xbf06807c, 0xbf84fff0,
+	0xb9782a05, 0x80788178,
+	0x907c9973, 0x877c817c,
+	0xbf06817c, 0xbf850002,
+	0x8f788978, 0xbf820001,
+	0x8f788a78, 0xb9721e06,
+	0x8f728a72, 0x80787278,
+	0x8078ff78, 0x00000200,
+	0xbef603ff, 0x01000000,
+	0xf4211bfa, 0xf0000000,
+	0x80788478, 0xf4211b3a,
 	0xf0000000, 0x80788478,
-	0xf4211b3a, 0xf0000000,
-	0x80788478, 0xf4211b7a,
+	0xf4211b7a, 0xf0000000,
+	0x80788478, 0xf4211eba,
 	0xf0000000, 0x80788478,
-	0xf4211eba, 0xf0000000,
-	0x80788478, 0xf4211efa,
+	0xf4211efa, 0xf0000000,
+	0x80788478, 0xf4211c3a,
 	0xf0000000, 0x80788478,
-	0xf4211c3a, 0xf0000000,
-	0x80788478, 0xf4211c7a,
+	0xf4211c7a, 0xf0000000,
+	0x80788478, 0xf4211e7a,
 	0xf0000000, 0x80788478,
-	0xf4211e7a, 0xf0000000,
-	0x80788478, 0xf4211cfa,
+	0xf4211cfa, 0xf0000000,
+	0x80788478, 0xf4211bba,
 	0xf0000000, 0x80788478,
+	0xbf8cc07f, 0xb9eef814,
 	0xf4211bba, 0xf0000000,
 	0x80788478, 0xbf8cc07f,
-	0xb9eef814, 0xf4211bba,
-	0xf0000000, 0x80788478,
-	0xbf8cc07f, 0xb9eef815,
-	0xbef2036d, 0x876dff72,
-	0x0000ffff, 0xbefc036f,
-	0xbefe037a, 0xbeff037b,
-	0x876f71ff, 0x000003ff,
-	0xb9ef4803, 0xb9f9f816,
-	0x876f71ff, 0xfffff800,
-	0x906f8b6f, 0xb9efa2c3,
-	0xb9f3f801, 0x876fff72,
-	0xfc000000, 0x906f9a6f,
-	0x8f6f906f, 0xbef30380,
+	0xb9eef815, 0xbef2036d,
+	0x876dff72, 0x0000ffff,
+	0xbefc036f, 0xbefe037a,
+	0xbeff037b, 0x876f71ff,
+	0x000003ff, 0xb9ef4803,
+	0xb9f9f816, 0x876f71ff,
+	0xfffff800, 0x906f8b6f,
+	0xb9efa2c3, 0xb9f3f801,
+	0x876fff72, 0xfc000000,
+	0x906f9a6f, 0x8f6f906f,
+	0xbef30380, 0x88736f73,
+	0x876fff72, 0x02000000,
+	0x906f996f, 0x8f6f8f6f,
 	0x88736f73, 0x876fff72,
-	0x02000000, 0x906f996f,
-	0x8f6f8f6f, 0x88736f73,
-	0x876fff72, 0x01000000,
-	0x906f986f, 0x8f6f996f,
-	0x88736f73, 0x876fff70,
-	0x00800000, 0x906f976f,
-	0xb9f3f807, 0x87fe7e7e,
-	0x87ea6a6a, 0xb9f0f802,
-	0xbf8a0000, 0xbe80226c,
-	0xbf810000, 0xbf9f0000,
+	0x01000000, 0x906f986f,
+	0x8f6f996f, 0x88736f73,
+	0x876fff70, 0x00800000,
+	0x906f976f, 0xb9f3f807,
+	0x87fe7e7e, 0x87ea6a6a,
+	0xb9f0f802, 0xbf8a0000,
+	0xbe80226c, 0xbf810000,
 	0xbf9f0000, 0xbf9f0000,
 	0xbf9f0000, 0xbf9f0000,
+	0xbf9f0000, 0x00000000,
 };
 static const uint32_t cwsr_trap_arcturus_hex[] = {
 	0xbf820001, 0xbf8202c4,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm
@@ -758,6 +758,7 @@
 	buffer_load_dword	v1, v0, s_restore_buf_rsrc0, s_restore_mem_offset_save slc:1 glc:1 offset:256
 	buffer_load_dword	v2, v0, s_restore_buf_rsrc0, s_restore_mem_offset_save slc:1 glc:1 offset:256*2
 	buffer_load_dword	v3, v0, s_restore_buf_rsrc0, s_restore_mem_offset_save slc:1 glc:1 offset:256*3
+	s_waitcnt	vmcnt(0)
 
 	/* restore SGPRs */
 	//will be 2+8+16*6
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
@@ -938,8 +938,8 @@
 	 * nodes, but not more than args->num_of_nodes as that is
 	 * the amount of memory allocated by user
 	 */
-	pa = kzalloc((sizeof(struct kfd_process_device_apertures) *
-				args->num_of_nodes), GFP_KERNEL);
+	pa = kcalloc(args->num_of_nodes, sizeof(struct kfd_process_device_apertures),
+		     GFP_KERNEL);
 	if (!pa)
 		return -ENOMEM;
 
@@ -1278,7 +1278,7 @@
 		if (args->size != PAGE_SIZE)
 			return -EINVAL;
 		offset = amdgpu_amdkfd_get_mmio_remap_phys_addr(dev->kgd);
-		if (!offset)
+		if (!offset || (PAGE_SIZE > 4096))
 			return -ENOMEM;
 	}
 
@@ -1664,6 +1664,7 @@
 	}
 
 	mutex_unlock(&p->mutex);
+	dma_buf_put(dmabuf);
 
 	args->handle = MAKE_HANDLE(args->gpu_id, idr_handle);
 
@@ -1673,6 +1674,7 @@
 	amdgpu_amdkfd_gpuvm_free_memory_of_gpu(dev->kgd, (struct kgd_mem *)mem);
 err_unlock:
 	mutex_unlock(&p->mutex);
+	dma_buf_put(dmabuf);
 	return r;
 }
 
@@ -1870,6 +1872,9 @@
 	if (vma->vm_end - vma->vm_start != PAGE_SIZE)
 		return -EINVAL;
 
+	if (PAGE_SIZE > 4096)
+		return -EINVAL;
+
 	address = amdgpu_amdkfd_get_mmio_remap_phys_addr(dev->kgd);
 
 	vma->vm_flags |= VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_NORESERVE |
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
@@ -407,6 +407,9 @@
 			return -ENODEV;
 		/* same everything but the other direction */
 		props2 = kmemdup(props, sizeof(*props2), GFP_KERNEL);
+		if (!props2)
+			return -ENOMEM;
+
 		props2->node_from = id_to;
 		props2->node_to = id_from;
 		props2->kobj = NULL;
@@ -758,7 +761,7 @@
 	/* Fetch the CRAT table from ACPI */
 	status = acpi_get_table(CRAT_SIGNATURE, 0, &crat_table);
 	if (status == AE_NOT_FOUND) {
-		pr_warn("CRAT table not found\n");
+		pr_info("CRAT table not found\n");
 		return -ENODATA;
 	} else if (ACPI_FAILURE(status)) {
 		const char *err = acpi_format_exception(status);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdkfd/kfd_crat.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdkfd/kfd_crat.h
@@ -42,8 +42,6 @@
 #define CRAT_OEMTABLEID_LENGTH	8
 #define CRAT_RESERVED_LENGTH	6
 
-#define CRAT_OEMID_64BIT_MASK ((1ULL << (CRAT_OEMID_LENGTH * 8)) - 1)
-
 /* Compute Unit flags */
 #define COMPUTE_UNIT_CPU	(1 << 0)  /* Create Virtual CRAT for CPU */
 #define COMPUTE_UNIT_GPU	(1 << 1)  /* Create Virtual CRAT for GPU */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdkfd/kfd_debugfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdkfd/kfd_debugfs.c
@@ -33,6 +33,11 @@
 
 	return single_open(file, show, NULL);
 }
+static int kfd_debugfs_hang_hws_read(struct seq_file *m, void *data)
+{
+	seq_printf(m, "echo gpu_id > hang_hws\n");
+	return 0;
+}
 
 static ssize_t kfd_debugfs_hang_hws_write(struct file *file,
 	const char __user *user_buf, size_t size, loff_t *ppos)
@@ -93,8 +98,8 @@
 			    kfd_debugfs_hqds_by_device, &kfd_debugfs_fops);
 	debugfs_create_file("rls", S_IFREG | 0444, debugfs_root,
 			    kfd_debugfs_rls_by_device, &kfd_debugfs_fops);
-	debugfs_create_file("hang_hws", S_IFREG | 0644, debugfs_root,
-			    NULL, &kfd_debugfs_hang_hws_fops);
+	debugfs_create_file("hang_hws", S_IFREG | 0200, debugfs_root,
+			    kfd_debugfs_hang_hws_read, &kfd_debugfs_hang_hws_fops);
 }
 
 void kfd_debugfs_fini(void)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdkfd/kfd_device.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdkfd/kfd_device.c
@@ -609,15 +609,10 @@
 			- kfd->vm_info.first_vmid_kfd + 1;
 
 	/* Verify module parameters regarding mapped process number*/
-	if ((hws_max_conc_proc < 0)
-			|| (hws_max_conc_proc > kfd->vm_info.vmid_num_kfd)) {
-		dev_err(kfd_device,
-			"hws_max_conc_proc %d must be between 0 and %d, use %d instead\n",
-			hws_max_conc_proc, kfd->vm_info.vmid_num_kfd,
-			kfd->vm_info.vmid_num_kfd);
+	if (hws_max_conc_proc >= 0)
+		kfd->max_proc_per_quantum = min((u32)hws_max_conc_proc, kfd->vm_info.vmid_num_kfd);
+	else
 		kfd->max_proc_per_quantum = kfd->vm_info.vmid_num_kfd;
-	} else
-		kfd->max_proc_per_quantum = hws_max_conc_proc;
 
 	/* Allocate global GWS that is shared by all KFD processes */
 	if (hws_gws_support && amdgpu_amdkfd_alloc_gws(kfd->kgd,
@@ -1112,9 +1107,9 @@
 	return 0;
 
 kfd_gtt_no_free_chunk:
-	pr_debug("Allocation failed with mem_obj = %p\n", mem_obj);
+	pr_debug("Allocation failed with mem_obj = %p\n", *mem_obj);
 	mutex_unlock(&kfd->gtt_sa_lock);
-	kfree(mem_obj);
+	kfree(*mem_obj);
 	return -ENOMEM;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
@@ -1011,6 +1011,9 @@
 
 static int initialize_cpsch(struct device_queue_manager *dqm)
 {
+	uint64_t num_sdma_queues;
+	uint64_t num_xgmi_sdma_queues;
+
 	pr_debug("num of pipes: %d\n", get_pipes_per_mec(dqm));
 
 	mutex_init(&dqm->lock_hidden);
@@ -1019,8 +1022,18 @@
 	dqm->sdma_queue_count = 0;
 	dqm->xgmi_sdma_queue_count = 0;
 	dqm->active_runlist = false;
-	dqm->sdma_bitmap = ~0ULL >> (64 - get_num_sdma_queues(dqm));
-	dqm->xgmi_sdma_bitmap = ~0ULL >> (64 - get_num_xgmi_sdma_queues(dqm));
+
+	num_sdma_queues = get_num_sdma_queues(dqm);
+	if (num_sdma_queues >= BITS_PER_TYPE(dqm->sdma_bitmap))
+		dqm->sdma_bitmap = ULLONG_MAX;
+	else
+		dqm->sdma_bitmap = (BIT_ULL(num_sdma_queues) - 1);
+
+	num_xgmi_sdma_queues = get_num_xgmi_sdma_queues(dqm);
+	if (num_xgmi_sdma_queues >= BITS_PER_TYPE(dqm->xgmi_sdma_bitmap))
+		dqm->xgmi_sdma_bitmap = ULLONG_MAX;
+	else
+		dqm->xgmi_sdma_bitmap = (BIT_ULL(num_xgmi_sdma_queues) - 1);
 
 	INIT_WORK(&dqm->hw_exception_work, kfd_process_hw_exception);
 
@@ -1075,6 +1088,8 @@
 	unmap_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0);
 	dqm_unlock(dqm);
 
+	pm_release_ib(&dqm->packets);
+
 	kfd_gtt_sa_free(dqm->dev, dqm->fence_mem);
 	pm_uninit(&dqm->packets);
 
@@ -1181,16 +1196,18 @@
 
 	list_add(&q->list, &qpd->queues_list);
 	qpd->queue_count++;
+
+	if (q->properties.type == KFD_QUEUE_TYPE_SDMA)
+		dqm->sdma_queue_count++;
+	else if (q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI)
+		dqm->xgmi_sdma_queue_count++;
+
 	if (q->properties.is_active) {
 		dqm->queue_count++;
 		retval = execute_queues_cpsch(dqm,
 				KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0);
 	}
 
-	if (q->properties.type == KFD_QUEUE_TYPE_SDMA)
-		dqm->sdma_queue_count++;
-	else if (q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI)
-		dqm->xgmi_sdma_queue_count++;
 	/*
 	 * Unconditionally increment this counter, regardless of the queue's
 	 * type or whether the queue is active.
@@ -1567,7 +1584,7 @@
 		struct qcm_process_device *qpd)
 {
 	int retval;
-	struct queue *q, *next;
+	struct queue *q;
 	struct kernel_queue *kq, *kq_next;
 	struct mqd_manager *mqd_mgr;
 	struct device_process_node *cur, *next_dpn;
@@ -1622,24 +1639,26 @@
 		qpd->reset_wavefronts = false;
 	}
 
-	dqm_unlock(dqm);
-
-	/* Outside the DQM lock because under the DQM lock we can't do
-	 * reclaim or take other locks that others hold while reclaiming.
-	 */
-	if (found)
-		kfd_dec_compute_active(dqm->dev);
-
 	/* Lastly, free mqd resources.
 	 * Do free_mqd() after dqm_unlock to avoid circular locking.
 	 */
-	list_for_each_entry_safe(q, next, &qpd->queues_list, list) {
+	while (!list_empty(&qpd->queues_list)) {
+		q = list_first_entry(&qpd->queues_list, struct queue, list);
 		mqd_mgr = dqm->mqd_mgrs[get_mqd_type_from_queue_type(
 				q->properties.type)];
 		list_del(&q->list);
 		qpd->queue_count--;
+		dqm_unlock(dqm);
 		mqd_mgr->free_mqd(mqd_mgr, q->mqd, q->mqd_mem_obj);
+		dqm_lock(dqm);
 	}
+	dqm_unlock(dqm);
+
+	/* Outside the DQM lock because under the DQM lock we can't do
+	 * reclaim or take other locks that others hold while reclaiming.
+	 */
+	if (found)
+		kfd_dec_compute_active(dqm->dev);
 
 	return retval;
 }
@@ -1676,7 +1695,8 @@
 	struct kfd_dev *dev = dqm->dev;
 	struct kfd_mem_obj *mem_obj = &dqm->hiq_sdma_mqd;
 	uint32_t size = dqm->mqd_mgrs[KFD_MQD_TYPE_SDMA]->mqd_size *
-		dev->device_info->num_sdma_engines *
+		(dev->device_info->num_sdma_engines +
+		dev->device_info->num_xgmi_sdma_engines) *
 		dev->device_info->num_sdma_queues_per_engine +
 		dqm->mqd_mgrs[KFD_MQD_TYPE_HIQ]->mqd_size;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v10.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v10.c
@@ -58,8 +58,9 @@
 	/* check if sh_mem_config register already configured */
 	if (qpd->sh_mem_config == 0) {
 		qpd->sh_mem_config =
-				SH_MEM_ALIGNMENT_MODE_UNALIGNED <<
-					SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT;
+			(SH_MEM_ALIGNMENT_MODE_UNALIGNED <<
+				SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT) |
+			(3 << SH_MEM_CONFIG__INITIAL_INST_PREFETCH__SHIFT);
 #if 0
 		/* TODO:
 		 *    This shouldn't be an issue with Navi10.  Verify.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdkfd/kfd_events.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdkfd/kfd_events.c
@@ -529,14 +529,13 @@
 	struct kfd_event_waiter *event_waiters;
 	uint32_t i;
 
-	event_waiters = kmalloc_array(num_events,
-					sizeof(struct kfd_event_waiter),
-					GFP_KERNEL);
+	event_waiters = kcalloc(num_events, sizeof(struct kfd_event_waiter),
+				GFP_KERNEL);
+	if (!event_waiters)
+		return NULL;
 
-	for (i = 0; (event_waiters) && (i < num_events) ; i++) {
+	for (i = 0; i < num_events; i++)
 		init_wait(&event_waiters[i].wait);
-		event_waiters[i].activated = false;
-	}
 
 	return event_waiters;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c
@@ -62,6 +62,11 @@
 	}
 
 	kfd->ih_wq = alloc_workqueue("KFD IH", WQ_HIGHPRI, 1);
+	if (unlikely(!kfd->ih_wq)) {
+		kfifo_free(&kfd->ih_fifo);
+		dev_err(kfd_chardev(), "Failed to allocate KFD IH workqueue\n");
+		return -ENOMEM;
+	}
 	spin_lock_init(&kfd->interrupt_lock);
 
 	INIT_WORK(&kfd->interrupt_work, interrupt_wq);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdkfd/kfd_iommu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdkfd/kfd_iommu.c
@@ -20,6 +20,10 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#include <linux/kconfig.h>
+
+#if IS_REACHABLE(CONFIG_AMD_IOMMU_V2)
+
 #include <linux/printk.h>
 #include <linux/device.h>
 #include <linux/slab.h>
@@ -358,3 +362,5 @@
 
 	return 0;
 }
+
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdkfd/kfd_iommu.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdkfd/kfd_iommu.h
@@ -23,7 +23,9 @@
 #ifndef __KFD_IOMMU_H__
 #define __KFD_IOMMU_H__
 
-#if defined(CONFIG_AMD_IOMMU_V2_MODULE) || defined(CONFIG_AMD_IOMMU_V2)
+#include <linux/kconfig.h>
+
+#if IS_REACHABLE(CONFIG_AMD_IOMMU_V2)
 
 #define KFD_SUPPORT_IOMMU_V2
 
@@ -46,6 +48,9 @@
 }
 static inline int kfd_iommu_device_init(struct kfd_dev *kfd)
 {
+#if IS_MODULE(CONFIG_AMD_IOMMU_V2)
+	WARN_ONCE(1, "iommu_v2 module is not usable by built-in KFD");
+#endif
 	return 0;
 }
 
@@ -73,6 +78,6 @@
 	return 0;
 }
 
-#endif /* defined(CONFIG_AMD_IOMMU_V2) */
+#endif /* IS_REACHABLE(CONFIG_AMD_IOMMU_V2) */
 
 #endif /* __KFD_IOMMU_H__ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdkfd/kfd_module.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdkfd/kfd_module.c
@@ -82,7 +82,7 @@
 	kfd_chardev_exit();
 }
 
-int kgd2kfd_init()
+int kgd2kfd_init(void)
 {
 	return kfd_init();
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c
@@ -98,36 +98,78 @@
 		uint32_t *se_mask)
 {
 	struct kfd_cu_info cu_info;
-	uint32_t cu_per_se[KFD_MAX_NUM_SE] = {0};
-	int i, se, sh, cu = 0;
-
+	uint32_t cu_per_sh[KFD_MAX_NUM_SE][KFD_MAX_NUM_SH_PER_SE] = {0};
+	int i, se, sh, cu;
 	amdgpu_amdkfd_get_cu_info(mm->dev->kgd, &cu_info);
 
 	if (cu_mask_count > cu_info.cu_active_number)
 		cu_mask_count = cu_info.cu_active_number;
 
+	/* Exceeding these bounds corrupts the stack and indicates a coding error.
+	 * Returning with no CU's enabled will hang the queue, which should be
+	 * attention grabbing.
+	 */
+	if (cu_info.num_shader_engines > KFD_MAX_NUM_SE) {
+		pr_err("Exceeded KFD_MAX_NUM_SE, chip reports %d\n", cu_info.num_shader_engines);
+		return;
+	}
+	if (cu_info.num_shader_arrays_per_engine > KFD_MAX_NUM_SH_PER_SE) {
+		pr_err("Exceeded KFD_MAX_NUM_SH, chip reports %d\n",
+			cu_info.num_shader_arrays_per_engine * cu_info.num_shader_engines);
+		return;
+	}
+	/* Count active CUs per SH.
+	 *
+	 * Some CUs in an SH may be disabled.	HW expects disabled CUs to be
+	 * represented in the high bits of each SH's enable mask (the upper and lower
+	 * 16 bits of se_mask) and will take care of the actual distribution of
+	 * disabled CUs within each SH automatically.
+	 * Each half of se_mask must be filled only on bits 0-cu_per_sh[se][sh]-1.
+	 *
+	 * See note on Arcturus cu_bitmap layout in gfx_v9_0_get_cu_info.
+	 */
 	for (se = 0; se < cu_info.num_shader_engines; se++)
 		for (sh = 0; sh < cu_info.num_shader_arrays_per_engine; sh++)
-			cu_per_se[se] += hweight32(cu_info.cu_bitmap[se % 4][sh + (se / 4)]);
+			cu_per_sh[se][sh] = hweight32(cu_info.cu_bitmap[se % 4][sh + (se / 4)]);
 
-	/* Symmetrically map cu_mask to all SEs:
-	 * cu_mask[0] bit0 -> se_mask[0] bit0;
-	 * cu_mask[0] bit1 -> se_mask[1] bit0;
-	 * ... (if # SE is 4)
-	 * cu_mask[0] bit4 -> se_mask[0] bit1;
+	/* Symmetrically map cu_mask to all SEs & SHs:
+	 * se_mask programs up to 2 SH in the upper and lower 16 bits.
+	 *
+	 * Examples
+	 * Assuming 1 SH/SE, 4 SEs:
+	 * cu_mask[0] bit0 -> se_mask[0] bit0
+	 * cu_mask[0] bit1 -> se_mask[1] bit0
+	 * ...
+	 * cu_mask[0] bit4 -> se_mask[0] bit1
+	 * ...
+	 *
+	 * Assuming 2 SH/SE, 4 SEs
+	 * cu_mask[0] bit0 -> se_mask[0] bit0 (SE0,SH0,CU0)
+	 * cu_mask[0] bit1 -> se_mask[1] bit0 (SE1,SH0,CU0)
+	 * ...
+	 * cu_mask[0] bit4 -> se_mask[0] bit16 (SE0,SH1,CU0)
+	 * cu_mask[0] bit5 -> se_mask[1] bit16 (SE1,SH1,CU0)
+	 * ...
+	 * cu_mask[0] bit8 -> se_mask[0] bit1 (SE0,SH0,CU1)
 	 * ...
+	 *
+	 * First ensure all CUs are disabled, then enable user specified CUs.
 	 */
-	se = 0;
-	for (i = 0; i < cu_mask_count; i++) {
-		if (cu_mask[i / 32] & (1 << (i % 32)))
-			se_mask[se] |= 1 << cu;
+	for (i = 0; i < cu_info.num_shader_engines; i++)
+		se_mask[i] = 0;
 
-		do {
-			se++;
-			if (se == cu_info.num_shader_engines) {
-				se = 0;
-				cu++;
+	i = 0;
+	for (cu = 0; cu < 16; cu++) {
+		for (sh = 0; sh < cu_info.num_shader_arrays_per_engine; sh++) {
+			for (se = 0; se < cu_info.num_shader_engines; se++) {
+				if (cu_per_sh[se][sh] > cu) {
+					if (cu_mask[i / 32] & (1 << (i % 32)))
+						se_mask[se] |= 1 << (cu + sh * 16);
+					i++;
+					if (i == cu_mask_count)
+						return;
+				}
 			}
-		} while (cu >= cu_per_se[se] && cu < 32);
+		}
 	}
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.h
@@ -27,6 +27,7 @@
 #include "kfd_priv.h"
 
 #define KFD_MAX_NUM_SE 8
+#define KFD_MAX_NUM_SH_PER_SE 2
 
 /**
  * struct mqd_manager
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c
@@ -101,18 +101,19 @@
 			&(mqd_mem_obj->gtt_mem),
 			&(mqd_mem_obj->gpu_addr),
 			(void *)&(mqd_mem_obj->cpu_ptr), true);
+
+		if (retval) {
+			kfree(mqd_mem_obj);
+			return NULL;
+		}
 	} else {
 		retval = kfd_gtt_sa_allocate(kfd, sizeof(struct v9_mqd),
 				&mqd_mem_obj);
-	}
-
-	if (retval) {
-		kfree(mqd_mem_obj);
-		return NULL;
+		if (retval)
+			return NULL;
 	}
 
 	return mqd_mem_obj;
-
 }
 
 static void init_mqd(struct mqd_manager *mm, void **mqd,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdkfd/kfd_process.c
@@ -289,6 +289,14 @@
 	if (process) {
 		pr_debug("Process already found\n");
 	} else {
+		/* If the process just called exec(3), it is possible that the
+		 * cleanup of the kfd_process (following the release of the mm
+		 * of the old process image) is still in the cleanup work queue.
+		 * Make sure to drain any job before trying to recreate any
+		 * resource for this process.
+		 */
+		flush_workqueue(kfd_process_wq);
+
 		process = create_process(thread);
 		if (IS_ERR(process))
 			goto out;
@@ -312,6 +320,7 @@
 					   (int)process->lead_thread->pid);
 		if (ret) {
 			pr_warn("Creating procfs pid directory failed");
+			kobject_put(process->kobj);
 			goto out;
 		}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
@@ -612,8 +612,10 @@
 
 	ret = kobject_init_and_add(dev->kobj_node, &node_type,
 			sys_props.kobj_nodes, "%d", id);
-	if (ret < 0)
+	if (ret < 0) {
+		kobject_put(dev->kobj_node);
 		return ret;
+	}
 
 	dev->kobj_mem = kobject_create_and_add("mem_banks", dev->kobj_node);
 	if (!dev->kobj_mem)
@@ -660,8 +662,10 @@
 			return -ENOMEM;
 		ret = kobject_init_and_add(mem->kobj, &mem_type,
 				dev->kobj_mem, "%d", i);
-		if (ret < 0)
+		if (ret < 0) {
+			kobject_put(mem->kobj);
 			return ret;
+		}
 
 		mem->attr.name = "properties";
 		mem->attr.mode = KFD_SYSFS_FILE_MODE;
@@ -679,8 +683,10 @@
 			return -ENOMEM;
 		ret = kobject_init_and_add(cache->kobj, &cache_type,
 				dev->kobj_cache, "%d", i);
-		if (ret < 0)
+		if (ret < 0) {
+			kobject_put(cache->kobj);
 			return ret;
+		}
 
 		cache->attr.name = "properties";
 		cache->attr.mode = KFD_SYSFS_FILE_MODE;
@@ -698,8 +704,10 @@
 			return -ENOMEM;
 		ret = kobject_init_and_add(iolink->kobj, &iolink_type,
 				dev->kobj_iolink, "%d", i);
-		if (ret < 0)
+		if (ret < 0) {
+			kobject_put(iolink->kobj);
 			return ret;
+		}
 
 		iolink->attr.name = "properties";
 		iolink->attr.mode = KFD_SYSFS_FILE_MODE;
@@ -779,8 +787,10 @@
 		ret = kobject_init_and_add(sys_props.kobj_topology,
 				&sysprops_type,  &kfd_device->kobj,
 				"topology");
-		if (ret < 0)
+		if (ret < 0) {
+			kobject_put(sys_props.kobj_topology);
 			return ret;
+		}
 
 		sys_props.kobj_nodes = kobject_create_and_add("nodes",
 				sys_props.kobj_topology);
@@ -873,8 +883,7 @@
 	dev = list_last_entry(&topology_device_list,
 			struct kfd_topology_device, list);
 	if (dev) {
-		sys_props.platform_id =
-			(*((uint64_t *)dev->oem_id)) & CRAT_OEMID_64BIT_MASK;
+		sys_props.platform_id = dev->oem_id64;
 		sys_props.platform_oem = *((uint64_t *)dev->oem_table_id);
 		sys_props.platform_rev = dev->oem_revision;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/amdkfd/kfd_topology.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/amdkfd/kfd_topology.h
@@ -172,7 +172,10 @@
 	struct attribute		attr_gpuid;
 	struct attribute		attr_name;
 	struct attribute		attr_props;
-	uint8_t				oem_id[CRAT_OEMID_LENGTH];
+	union {
+		uint8_t				oem_id[CRAT_OEMID_LENGTH];
+		uint64_t			oem_id64;
+	};
 	uint8_t				oem_table_id[CRAT_OEMTABLEID_LENGTH];
 	uint32_t			oem_revision;
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -664,6 +664,7 @@
 
 	init_data.asic_id.pci_revision_id = adev->rev_id;
 	init_data.asic_id.hw_internal_rev = adev->external_rev_id;
+	init_data.asic_id.chip_id = adev->pdev->device;
 
 	init_data.asic_id.vram_width = adev->gmc.vram_width;
 	/* TODO: initialize init_data.asic_id.vram_type here!!!! */
@@ -928,8 +929,13 @@
 	struct dmcu_iram_parameters params;
 	unsigned int linear_lut[16];
 	int i;
-	struct dmcu *dmcu = adev->dm.dc->res_pool->dmcu;
-	bool ret = false;
+	struct dmcu *dmcu = NULL;
+	bool ret;
+
+	if (!adev->dm.fw_dmcu)
+		return detect_mst_link_for_all_connectors(adev->ddev);
+
+	dmcu = adev->dm.dc->res_pool->dmcu;
 
 	for (i = 0; i < 16; i++)
 		linear_lut[i] = 0xFFFF * i / 15;
@@ -940,13 +946,15 @@
 	params.backlight_lut_array_size = 16;
 	params.backlight_lut_array = linear_lut;
 
-	/* todo will enable for navi10 */
-	if (adev->asic_type <= CHIP_RAVEN) {
-		ret = dmcu_load_iram(dmcu, params);
+	/* Min backlight level after ABM reduction,  Don't allow below 1%
+	 * 0xFFFF x 0.01 = 0x28F
+	 */
+	params.min_abm_backlight = 0x28F;
 
-		if (!ret)
-			return -EINVAL;
-	}
+	ret = dmcu_load_iram(dmcu, params);
+
+	if (!ret)
+		return -EINVAL;
 
 	return detect_mst_link_for_all_connectors(adev->ddev);
 }
@@ -1086,8 +1094,8 @@
 	link->type = dc_connection_none;
 	prev_sink = link->local_sink;
 
-	if (prev_sink != NULL)
-		dc_sink_retain(prev_sink);
+	if (prev_sink)
+		dc_sink_release(prev_sink);
 
 	switch (link->connector_signal) {
 	case SIGNAL_TYPE_HDMI_TYPE_A: {
@@ -1198,11 +1206,14 @@
 	list_for_each_entry(connector, &ddev->mode_config.connector_list, head) {
 		aconnector = to_amdgpu_dm_connector(connector);
 
+		if (!aconnector->dc_link)
+			continue;
+
 		/*
 		 * this is the case when traversing through already created
 		 * MST connectors, should be skipped
 		 */
-		if (aconnector->mst_port)
+		if (aconnector->dc_link->type == dc_connection_mst_branch)
 			continue;
 
 		mutex_lock(&aconnector->hpd_lock);
@@ -1240,6 +1251,7 @@
 			dc_stream_release(dm_new_crtc_state->stream);
 			dm_new_crtc_state->stream = NULL;
 		}
+		dm_new_crtc_state->base.color_mgmt_changed = true;
 	}
 
 	for_each_new_plane_in_state(dm->cached_state, plane, new_plane_state, i) {
@@ -1410,24 +1422,29 @@
 		 * TODO: check if we still need the S3 mode update workaround.
 		 * If yes, put it here.
 		 */
-		if (aconnector->dc_sink)
+		if (aconnector->dc_sink) {
 			amdgpu_dm_update_freesync_caps(connector, NULL);
+			dc_sink_release(aconnector->dc_sink);
+		}
 
 		aconnector->dc_sink = sink;
 		dc_sink_retain(aconnector->dc_sink);
 		if (sink->dc_edid.length == 0) {
 			aconnector->edid = NULL;
-			drm_dp_cec_unset_edid(&aconnector->dm_dp_aux.aux);
+			if (aconnector->dc_link->aux_mode) {
+				drm_dp_cec_unset_edid(
+					&aconnector->dm_dp_aux.aux);
+			}
 		} else {
 			aconnector->edid =
-				(struct edid *) sink->dc_edid.raw_edid;
+				(struct edid *)sink->dc_edid.raw_edid;
 
-
-			drm_connector_update_edid_property(connector,
-					aconnector->edid);
-			drm_dp_cec_set_edid(&aconnector->dm_dp_aux.aux,
-					    aconnector->edid);
+			if (aconnector->dc_link->aux_mode)
+				drm_dp_cec_set_edid(&aconnector->dm_dp_aux.aux,
+						    aconnector->edid);
 		}
+
+		drm_connector_update_edid_property(connector, aconnector->edid);
 		amdgpu_dm_update_freesync_caps(connector, aconnector->edid);
 
 	} else {
@@ -2030,12 +2047,18 @@
 				    &dm_atomic_state_funcs);
 
 	r = amdgpu_display_modeset_create_props(adev);
-	if (r)
+	if (r) {
+		dc_release_state(state->context);
+		kfree(state);
 		return r;
+	}
 
 	r = amdgpu_dm_audio_init(adev);
-	if (r)
+	if (r) {
+		dc_release_state(state->context);
+		kfree(state);
 		return r;
+	}
 
 	return 0;
 }
@@ -2051,6 +2074,8 @@
 #if defined(CONFIG_ACPI)
 	struct amdgpu_dm_backlight_caps caps;
 
+	memset(&caps, 0, sizeof(caps));
+
 	if (dm->backlight_caps.caps_valid)
 		return;
 
@@ -2238,7 +2263,10 @@
 
 	/* There is one primary plane per CRTC */
 	primary_planes = dm->dc->caps.max_streams;
-	ASSERT(primary_planes <= AMDGPU_MAX_PLANES);
+	if (primary_planes > AMDGPU_MAX_PLANES) {
+		DRM_ERROR("DM: Plane nums out of 6 planes\n");
+		return -EINVAL;
+	}
 
 	/*
 	 * Initialize primary planes, implicit planes for legacy IOCTLS.
@@ -2293,17 +2321,16 @@
 
 	dm->display_indexes_num = dm->dc->caps.max_streams;
 
+	if (link_cnt > (MAX_PIPES * 2)) {
+		DRM_ERROR(
+			"KMS: Cannot support more than %d display indexes\n",
+				MAX_PIPES * 2);
+		goto fail;
+	}
 	/* loops over all connectors on the board */
 	for (i = 0; i < link_cnt; i++) {
 		struct dc_link *link = NULL;
 
-		if (i > AMDGPU_DM_MAX_DISPLAY_INDEX) {
-			DRM_ERROR(
-				"KMS: Cannot support more than %d display indexes\n",
-					AMDGPU_DM_MAX_DISPLAY_INDEX);
-			continue;
-		}
-
 		aconnector = kzalloc(sizeof(*aconnector), GFP_KERNEL);
 		if (!aconnector)
 			goto fail;
@@ -2611,6 +2638,23 @@
 	scaling_info->src_rect.x = state->src_x >> 16;
 	scaling_info->src_rect.y = state->src_y >> 16;
 
+	/*
+	 * For reasons we don't (yet) fully understand a non-zero
+	 * src_y coordinate into an NV12 buffer can cause a
+	 * system hang. To avoid hangs (and maybe be overly cautious)
+	 * let's reject both non-zero src_x and src_y.
+	 *
+	 * We currently know of only one use-case to reproduce a
+	 * scenario with non-zero src_x and src_y for NV12, which
+	 * is to gesture the YouTube Android app into full screen
+	 * on ChromeOS.
+	 */
+	if (state->fb &&
+	    state->fb->format->format == DRM_FORMAT_NV12 &&
+	    (scaling_info->src_rect.x != 0 ||
+	     scaling_info->src_rect.y != 0))
+		return -EINVAL;
+
 	scaling_info->src_rect.width = state->src_w >> 16;
 	if (scaling_info->src_rect.width == 0)
 		return -EINVAL;
@@ -2693,7 +2737,8 @@
 			  const union dc_tiling_info *tiling_info,
 			  const uint64_t info,
 			  struct dc_plane_dcc_param *dcc,
-			  struct dc_plane_address *address)
+			  struct dc_plane_address *address,
+			  bool force_disable_dcc)
 {
 	struct dc *dc = adev->dm.dc;
 	struct dc_dcc_surface_param input;
@@ -2705,6 +2750,9 @@
 	memset(&input, 0, sizeof(input));
 	memset(&output, 0, sizeof(output));
 
+	if (force_disable_dcc)
+		return 0;
+
 	if (!offset)
 		return 0;
 
@@ -2754,7 +2802,8 @@
 			     union dc_tiling_info *tiling_info,
 			     struct plane_size *plane_size,
 			     struct dc_plane_dcc_param *dcc,
-			     struct dc_plane_address *address)
+			     struct dc_plane_address *address,
+			     bool force_disable_dcc)
 {
 	const struct drm_framebuffer *fb = &afb->base;
 	int ret;
@@ -2864,7 +2913,8 @@
 
 		ret = fill_plane_dcc_attributes(adev, afb, format, rotation,
 						plane_size, tiling_info,
-						tiling_flags, dcc, address);
+						tiling_flags, dcc, address,
+						force_disable_dcc);
 		if (ret)
 			return ret;
 	}
@@ -2956,7 +3006,8 @@
 			    const struct drm_plane_state *plane_state,
 			    const uint64_t tiling_flags,
 			    struct dc_plane_info *plane_info,
-			    struct dc_plane_address *address)
+			    struct dc_plane_address *address,
+			    bool force_disable_dcc)
 {
 	const struct drm_framebuffer *fb = plane_state->fb;
 	const struct amdgpu_framebuffer *afb =
@@ -3035,7 +3086,8 @@
 					   plane_info->rotation, tiling_flags,
 					   &plane_info->tiling_info,
 					   &plane_info->plane_size,
-					   &plane_info->dcc, address);
+					   &plane_info->dcc, address,
+					   force_disable_dcc);
 	if (ret)
 		return ret;
 
@@ -3058,6 +3110,7 @@
 	struct dc_plane_info plane_info;
 	uint64_t tiling_flags;
 	int ret;
+	bool force_disable_dcc = false;
 
 	ret = fill_dc_scaling_info(plane_state, &scaling_info);
 	if (ret)
@@ -3072,9 +3125,11 @@
 	if (ret)
 		return ret;
 
+	force_disable_dcc = adev->asic_type == CHIP_RAVEN && adev->in_suspend;
 	ret = fill_dc_plane_info_and_addr(adev, plane_state, tiling_flags,
 					  &plane_info,
-					  &dc_plane_state->address);
+					  &dc_plane_state->address,
+					  force_disable_dcc);
 	if (ret)
 		return ret;
 
@@ -3261,27 +3316,21 @@
 	return color_space;
 }
 
-static void reduce_mode_colour_depth(struct dc_crtc_timing *timing_out)
-{
-	if (timing_out->display_color_depth <= COLOR_DEPTH_888)
-		return;
-
-	timing_out->display_color_depth--;
-}
-
-static void adjust_colour_depth_from_display_info(struct dc_crtc_timing *timing_out,
-						const struct drm_display_info *info)
+static bool adjust_colour_depth_from_display_info(
+	struct dc_crtc_timing *timing_out,
+	const struct drm_display_info *info)
 {
+	enum dc_color_depth depth = timing_out->display_color_depth;
 	int normalized_clk;
-	if (timing_out->display_color_depth <= COLOR_DEPTH_888)
-		return;
 	do {
 		normalized_clk = timing_out->pix_clk_100hz / 10;
 		/* YCbCr 4:2:0 requires additional adjustment of 1/2 */
 		if (timing_out->pixel_encoding == PIXEL_ENCODING_YCBCR420)
 			normalized_clk /= 2;
 		/* Adjusting pix clock following on HDMI spec based on colour depth */
-		switch (timing_out->display_color_depth) {
+		switch (depth) {
+		case COLOR_DEPTH_888:
+			break;
 		case COLOR_DEPTH_101010:
 			normalized_clk = (normalized_clk * 30) / 24;
 			break;
@@ -3292,14 +3341,15 @@
 			normalized_clk = (normalized_clk * 48) / 24;
 			break;
 		default:
-			return;
+			/* The above depths are the only ones valid for HDMI. */
+			return false;
 		}
-		if (normalized_clk <= info->max_tmds_clock)
-			return;
-		reduce_mode_colour_depth(timing_out);
-
-	} while (timing_out->display_color_depth > COLOR_DEPTH_888);
-
+		if (normalized_clk <= info->max_tmds_clock) {
+			timing_out->display_color_depth = depth;
+			return true;
+		}
+	} while (--depth > COLOR_DEPTH_666);
+	return false;
 }
 
 static void fill_stream_properties_from_drm_display_mode(
@@ -3365,8 +3415,14 @@
 
 	stream->out_transfer_func->type = TF_TYPE_PREDEFINED;
 	stream->out_transfer_func->tf = TRANSFER_FUNCTION_SRGB;
-	if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
-		adjust_colour_depth_from_display_info(timing_out, info);
+	if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) {
+		if (!adjust_colour_depth_from_display_info(timing_out, info) &&
+		    drm_mode_is_420_also(info, mode_in) &&
+		    timing_out->pixel_encoding != PIXEL_ENCODING_YCBCR420) {
+			timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420;
+			adjust_colour_depth_from_display_info(timing_out, info);
+		}
+	}
 }
 
 static void fill_audio_info(struct audio_info *audio_info,
@@ -3923,6 +3979,13 @@
 	struct amdgpu_device *adev = connector->dev->dev_private;
 	struct amdgpu_display_manager *dm = &adev->dm;
 
+	/*
+	 * Call only if mst_mgr was iniitalized before since it's not done
+	 * for all connector types.
+	 */
+	if (aconnector->mst_mgr.dev)
+		drm_dp_mst_topology_mgr_destroy(&aconnector->mst_mgr);
+
 #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\
 	defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
 
@@ -4266,19 +4329,6 @@
 {
 }
 
-static bool does_crtc_have_active_cursor(struct drm_crtc_state *new_crtc_state)
-{
-	struct drm_device *dev = new_crtc_state->crtc->dev;
-	struct drm_plane *plane;
-
-	drm_for_each_plane_mask(plane, dev, new_crtc_state->plane_mask) {
-		if (plane->type == DRM_PLANE_TYPE_CURSOR)
-			return true;
-	}
-
-	return false;
-}
-
 static int count_crtc_active_planes(struct drm_crtc_state *new_crtc_state)
 {
 	struct drm_atomic_state *state = new_crtc_state->state;
@@ -4358,19 +4408,20 @@
 		return ret;
 	}
 
-	/* In some use cases, like reset, no stream is attached */
-	if (!dm_crtc_state->stream)
-		return 0;
-
 	/*
-	 * We want at least one hardware plane enabled to use
-	 * the stream with a cursor enabled.
+	 * We require the primary plane to be enabled whenever the CRTC is, otherwise
+	 * drm_mode_cursor_universal may end up trying to enable the cursor plane while all other
+	 * planes are disabled, which is not supported by the hardware. And there is legacy
+	 * userspace which stops using the HW cursor altogether in response to the resulting EINVAL.
 	 */
-	if (state->enable && state->active &&
-	    does_crtc_have_active_cursor(state) &&
-	    dm_crtc_state->active_planes == 0)
+	if (state->enable &&
+	    !(state->plane_mask & drm_plane_mask(crtc->primary)))
 		return -EINVAL;
 
+	/* In some use cases, like reset, no stream is attached */
+	if (!dm_crtc_state->stream)
+		return 0;
+
 	if (dc_validate_stream(dc, dm_crtc_state->stream) == DC_OK)
 		return 0;
 
@@ -4475,6 +4526,7 @@
 	uint64_t tiling_flags;
 	uint32_t domain;
 	int r;
+	bool force_disable_dcc = false;
 
 	dm_plane_state_old = to_dm_plane_state(plane->state);
 	dm_plane_state_new = to_dm_plane_state(new_state);
@@ -4533,11 +4585,13 @@
 			dm_plane_state_old->dc_state != dm_plane_state_new->dc_state) {
 		struct dc_plane_state *plane_state = dm_plane_state_new->dc_state;
 
+		force_disable_dcc = adev->asic_type == CHIP_RAVEN && adev->in_suspend;
 		fill_plane_buffer_attributes(
 			adev, afb, plane_state->format, plane_state->rotation,
 			tiling_flags, &plane_state->tiling_info,
 			&plane_state->plane_size, &plane_state->dcc,
-			&plane_state->address);
+			&plane_state->address,
+			force_disable_dcc);
 	}
 
 	return 0;
@@ -4947,6 +5001,9 @@
 		mode = amdgpu_dm_create_common_mode(encoder,
 				common_modes[i].name, common_modes[i].w,
 				common_modes[i].h);
+		if (!mode)
+			continue;
+
 		drm_mode_probed_add(connector, mode);
 		amdgpu_dm_connector->num_modes++;
 	}
@@ -5341,10 +5398,6 @@
 	int x, y;
 	int xorigin = 0, yorigin = 0;
 
-	position->enable = false;
-	position->x = 0;
-	position->y = 0;
-
 	if (!crtc || !plane->state->fb)
 		return 0;
 
@@ -5396,7 +5449,7 @@
 	struct dm_crtc_state *crtc_state = crtc ? to_dm_crtc_state(crtc->state) : NULL;
 	struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
 	uint64_t address = afb ? afb->address : 0;
-	struct dc_cursor_position position;
+	struct dc_cursor_position position = {0};
 	struct dc_cursor_attributes attributes;
 	int ret;
 
@@ -5709,6 +5762,8 @@
 			continue;
 
 		dc_plane = dm_new_plane_state->dc_state;
+		if (!dc_plane)
+			continue;
 
 		bundle->surface_updates[planes_count].surface = dc_plane;
 		if (new_pcrtc_state->color_mgmt_changed) {
@@ -5761,7 +5816,12 @@
 		fill_dc_plane_info_and_addr(
 			dm->adev, new_plane_state, tiling_flags,
 			&bundle->plane_infos[planes_count],
-			&bundle->flip_addrs[planes_count].address);
+			&bundle->flip_addrs[planes_count].address,
+			false);
+
+		DRM_DEBUG_DRIVER("plane: id=%d dcc_en=%d\n",
+				 new_plane_state->plane->index,
+				 bundle->plane_infos[planes_count].dcc.enable);
 
 		bundle->surface_updates[planes_count].plane_info =
 			&bundle->plane_infos[planes_count];
@@ -6429,14 +6489,14 @@
 
 	ret = PTR_ERR_OR_ZERO(conn_state);
 	if (ret)
-		goto err;
+		goto out;
 
 	/* Attach crtc to drm_atomic_state*/
 	crtc_state = drm_atomic_get_crtc_state(state, &disconnected_acrtc->base);
 
 	ret = PTR_ERR_OR_ZERO(crtc_state);
 	if (ret)
-		goto err;
+		goto out;
 
 	/* force a restore */
 	crtc_state->mode_changed = true;
@@ -6446,17 +6506,15 @@
 
 	ret = PTR_ERR_OR_ZERO(plane_state);
 	if (ret)
-		goto err;
-
+		goto out;
 
 	/* Call commit internally with the state we just constructed */
 	ret = drm_atomic_commit(state);
-	if (!ret)
-		return 0;
 
-err:
-	DRM_ERROR("Restoring old state failed with %i\n", ret);
+out:
 	drm_atomic_state_put(state);
+	if (ret)
+		DRM_ERROR("Restoring old state failed with %i\n", ret);
 
 	return ret;
 }
@@ -6785,7 +6843,8 @@
 	BUG_ON(dm_new_crtc_state->stream == NULL);
 
 	/* Scaling or underscan settings */
-	if (is_scaling_state_different(dm_old_conn_state, dm_new_conn_state))
+	if (is_scaling_state_different(dm_old_conn_state, dm_new_conn_state) ||
+				drm_atomic_crtc_needs_modeset(new_crtc_state))
 		update_stream_scaling_settings(
 			&new_crtc_state->mode, dm_new_conn_state, dm_new_crtc_state->stream);
 
@@ -6896,6 +6955,7 @@
 	struct drm_crtc_state *old_crtc_state, *new_crtc_state;
 	struct dm_crtc_state *dm_new_crtc_state, *dm_old_crtc_state;
 	struct dm_plane_state *dm_new_plane_state, *dm_old_plane_state;
+	struct amdgpu_crtc *new_acrtc;
 	bool needs_reset;
 	int ret = 0;
 
@@ -6905,9 +6965,23 @@
 	dm_new_plane_state = to_dm_plane_state(new_plane_state);
 	dm_old_plane_state = to_dm_plane_state(old_plane_state);
 
-	/*TODO Implement atomic check for cursor plane */
-	if (plane->type == DRM_PLANE_TYPE_CURSOR)
+	/*TODO Implement better atomic check for cursor plane */
+	if (plane->type == DRM_PLANE_TYPE_CURSOR) {
+		if (!enable || !new_plane_crtc ||
+			drm_atomic_plane_disabling(plane->state, new_plane_state))
+			return 0;
+
+		new_acrtc = to_amdgpu_crtc(new_plane_crtc);
+
+		if ((new_plane_state->crtc_w > new_acrtc->max_cursor_width) ||
+			(new_plane_state->crtc_h > new_acrtc->max_cursor_height)) {
+			DRM_DEBUG_ATOMIC("Bad cursor size %d x %d\n",
+							 new_plane_state->crtc_w, new_plane_state->crtc_h);
+			return -EINVAL;
+		}
+
 		return 0;
+	}
 
 	needs_reset = should_reset_plane(state, plane, old_plane_state,
 					 new_plane_state);
@@ -6940,12 +7014,12 @@
 				dm_old_plane_state->dc_state,
 				dm_state->context)) {
 
-			ret = EINVAL;
-			return ret;
+			return -EINVAL;
 		}
 
+		if (dm_old_plane_state->dc_state)
+			dc_plane_state_release(dm_old_plane_state->dc_state);
 
-		dc_plane_state_release(dm_old_plane_state->dc_state);
 		dm_new_plane_state->dc_state = NULL;
 
 		*lock_and_validation_needed = true;
@@ -7132,7 +7206,8 @@
 				ret = fill_dc_plane_info_and_addr(
 					dm->adev, new_plane_state, tiling_flags,
 					&plane_info,
-					&flip_addr.address);
+					&flip_addr.address,
+					false);
 				if (ret)
 					goto cleanup;
 
@@ -7180,6 +7255,80 @@
 	*out_type = update_type;
 	return ret;
 }
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm_crtc *crtc)
+{
+	struct drm_connector *connector;
+	struct drm_connector_state *conn_state, *old_conn_state;
+	struct amdgpu_dm_connector *aconnector = NULL;
+	int i;
+	for_each_oldnew_connector_in_state(state, connector, old_conn_state, conn_state, i) {
+		if (!conn_state->crtc)
+			conn_state = old_conn_state;
+
+		if (conn_state->crtc != crtc)
+			continue;
+
+		aconnector = to_amdgpu_dm_connector(connector);
+		if (!aconnector->port || !aconnector->mst_port)
+			aconnector = NULL;
+		else
+			break;
+	}
+
+	if (!aconnector)
+		return 0;
+
+	return drm_dp_mst_add_affected_dsc_crtcs(state, &aconnector->mst_port->mst_mgr);
+}
+#endif
+
+static int validate_overlay(struct drm_atomic_state *state)
+{
+	int i;
+	struct drm_plane *plane;
+	struct drm_plane_state *old_plane_state, *new_plane_state;
+	struct drm_plane_state *primary_state, *overlay_state = NULL;
+
+	/* Check if primary plane is contained inside overlay */
+	for_each_oldnew_plane_in_state_reverse(state, plane, old_plane_state, new_plane_state, i) {
+		if (plane->type == DRM_PLANE_TYPE_OVERLAY) {
+			if (drm_atomic_plane_disabling(plane->state, new_plane_state))
+				return 0;
+
+			overlay_state = new_plane_state;
+			continue;
+		}
+	}
+
+	/* check if we're making changes to the overlay plane */
+	if (!overlay_state)
+		return 0;
+
+	/* check if overlay plane is enabled */
+	if (!overlay_state->crtc)
+		return 0;
+
+	/* find the primary plane for the CRTC that the overlay is enabled on */
+	primary_state = drm_atomic_get_plane_state(state, overlay_state->crtc->primary);
+	if (IS_ERR(primary_state))
+		return PTR_ERR(primary_state);
+
+	/* check if primary plane is enabled */
+	if (!primary_state->crtc)
+		return 0;
+
+	/* Perform the bounds check to ensure the overlay plane covers the primary */
+	if (primary_state->crtc_x < overlay_state->crtc_x ||
+	    primary_state->crtc_y < overlay_state->crtc_y ||
+	    primary_state->crtc_x + primary_state->crtc_w > overlay_state->crtc_x + overlay_state->crtc_w ||
+	    primary_state->crtc_y + primary_state->crtc_h > overlay_state->crtc_y + overlay_state->crtc_h) {
+		DRM_DEBUG_ATOMIC("Overlay plane is enabled with hardware cursor but does not fully cover primary plane\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
 
 /**
  * amdgpu_dm_atomic_check() - Atomic check implementation for AMDgpu DM.
@@ -7233,12 +7382,50 @@
 	if (ret)
 		goto fail;
 
+	/* Check connector changes */
+	for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) {
+		struct dm_connector_state *dm_old_con_state = to_dm_connector_state(old_con_state);
+		struct dm_connector_state *dm_new_con_state = to_dm_connector_state(new_con_state);
+
+		/* Skip connectors that are disabled or part of modeset already. */
+		if (!old_con_state->crtc && !new_con_state->crtc)
+			continue;
+
+		if (!new_con_state->crtc)
+			continue;
+
+		new_crtc_state = drm_atomic_get_crtc_state(state, new_con_state->crtc);
+		if (IS_ERR(new_crtc_state)) {
+			ret = PTR_ERR(new_crtc_state);
+			goto fail;
+		}
+
+		if (dm_old_con_state->abm_level != dm_new_con_state->abm_level ||
+		    dm_old_con_state->scaling != dm_new_con_state->scaling)
+			new_crtc_state->connectors_changed = true;
+	}
+
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+	if (dc_resource_is_dsc_encoding_supported(dc)) {
+		for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
+			if (drm_atomic_crtc_needs_modeset(new_crtc_state)) {
+				ret = add_affected_mst_dsc_crtcs(state, crtc);
+				if (ret)
+					goto fail;
+			}
+		}
+	}
+#endif
 	for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
 		if (!drm_atomic_crtc_needs_modeset(new_crtc_state) &&
 		    !new_crtc_state->color_mgmt_changed &&
 		    old_crtc_state->vrr_enabled == new_crtc_state->vrr_enabled)
 			continue;
 
+		ret = amdgpu_dm_verify_lut_sizes(new_crtc_state);
+		if (ret)
+			goto fail;
+
 		if (!new_crtc_state->enable)
 			continue;
 
@@ -7320,6 +7507,10 @@
 			goto fail;
 	}
 
+	ret = validate_overlay(state);
+	if (ret)
+		goto fail;
+
 	/* Add new/modified planes */
 	for_each_oldnew_plane_in_state_reverse(state, plane, old_plane_state, new_plane_state, i) {
 		ret = dm_update_plane_state(dc, state, plane,
@@ -7416,20 +7607,38 @@
 		 * the same resource. If we have a new DC context as part of
 		 * the DM atomic state from validation we need to free it and
 		 * retain the existing one instead.
+		 *
+		 * Furthermore, since the DM atomic state only contains the DC
+		 * context and can safely be annulled, we can free the state
+		 * and clear the associated private object now to free
+		 * some memory and avoid a possible use-after-free later.
 		 */
-		struct dm_atomic_state *new_dm_state, *old_dm_state;
 
-		new_dm_state = dm_atomic_get_new_state(state);
-		old_dm_state = dm_atomic_get_old_state(state);
+		for (i = 0; i < state->num_private_objs; i++) {
+			struct drm_private_obj *obj = state->private_objs[i].ptr;
+
+			if (obj->funcs == adev->dm.atomic_obj.funcs) {
+				int j = state->num_private_objs-1;
 
-		if (new_dm_state && old_dm_state) {
-			if (new_dm_state->context)
-				dc_release_state(new_dm_state->context);
+				dm_atomic_destroy_state(obj,
+						state->private_objs[i].state);
 
-			new_dm_state->context = old_dm_state->context;
+				/* If i is not at the end of the array then the
+				 * last element needs to be moved to where i was
+				 * before the array can safely be truncated.
+				 */
+				if (i != j)
+					state->private_objs[i] =
+						state->private_objs[j];
+
+				state->private_objs[j].ptr = NULL;
+				state->private_objs[j].state = NULL;
+				state->private_objs[j].old_state = NULL;
+				state->private_objs[j].new_state = NULL;
 
-			if (old_dm_state->context)
-				dc_retain_state(old_dm_state->context);
+				state->num_private_objs = j;
+				break;
+			}
 		}
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -387,6 +387,7 @@
 #define MAX_COLOR_LEGACY_LUT_ENTRIES 256
 
 void amdgpu_dm_init_color_mod(void);
+int amdgpu_dm_verify_lut_sizes(const struct drm_crtc_state *crtc_state);
 int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc);
 int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc,
 				      struct dc_plane_state *dc_plane_state);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c
@@ -210,6 +210,8 @@
 	res = mod_color_calculate_regamma_params(func, gamma, true, has_rom,
 						 NULL);
 
+	dc_gamma_release(&gamma);
+
 	return res ? 0 : -ENOMEM;
 }
 
@@ -276,6 +278,37 @@
 }
 
 /**
+ * Verifies that the Degamma and Gamma LUTs attached to the |crtc_state| are of
+ * the expected size.
+ * Returns 0 on success.
+ */
+int amdgpu_dm_verify_lut_sizes(const struct drm_crtc_state *crtc_state)
+{
+	const struct drm_color_lut *lut = NULL;
+	uint32_t size = 0;
+
+	lut = __extract_blob_lut(crtc_state->degamma_lut, &size);
+	if (lut && size != MAX_COLOR_LUT_ENTRIES) {
+		DRM_DEBUG_DRIVER(
+			"Invalid Degamma LUT size. Should be %u but got %u.\n",
+			MAX_COLOR_LUT_ENTRIES, size);
+		return -EINVAL;
+	}
+
+	lut = __extract_blob_lut(crtc_state->gamma_lut, &size);
+	if (lut && size != MAX_COLOR_LUT_ENTRIES &&
+	    size != MAX_COLOR_LEGACY_LUT_ENTRIES) {
+		DRM_DEBUG_DRIVER(
+			"Invalid Gamma LUT size. Should be %u (or %u for legacy) but got %u.\n",
+			MAX_COLOR_LUT_ENTRIES, MAX_COLOR_LEGACY_LUT_ENTRIES,
+			size);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
  * amdgpu_dm_update_crtc_color_mgmt: Maps DRM color management to DC stream.
  * @crtc: amdgpu_dm crtc state
  *
@@ -309,14 +342,12 @@
 	bool is_legacy;
 	int r;
 
-	degamma_lut = __extract_blob_lut(crtc->base.degamma_lut, &degamma_size);
-	if (degamma_lut && degamma_size != MAX_COLOR_LUT_ENTRIES)
-		return -EINVAL;
+	r = amdgpu_dm_verify_lut_sizes(&crtc->base);
+	if (r)
+		return r;
 
+	degamma_lut = __extract_blob_lut(crtc->base.degamma_lut, &degamma_size);
 	regamma_lut = __extract_blob_lut(crtc->base.gamma_lut, &regamma_size);
-	if (regamma_lut && regamma_size != MAX_COLOR_LUT_ENTRIES &&
-	    regamma_size != MAX_COLOR_LEGACY_LUT_ENTRIES)
-		return -EINVAL;
 
 	has_degamma =
 		degamma_lut && !__is_lut_linear(degamma_lut, degamma_size);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
@@ -113,7 +113,7 @@
 	mutex_lock(&adev->dm.dc_lock);
 
 	/* Enable CRTC CRC generation if necessary. */
-	if (dm_is_crc_source_crtc(source)) {
+	if (dm_is_crc_source_crtc(source) || source == AMDGPU_DM_PIPE_CRC_SOURCE_NONE) {
 		if (!dc_stream_configure_crc(stream_state->ctx->dc,
 					     stream_state, enable, enable)) {
 			ret = -EINVAL;
@@ -221,6 +221,14 @@
 			ret = -EINVAL;
 			goto cleanup;
 		}
+
+		if ((aconn->base.connector_type != DRM_MODE_CONNECTOR_DisplayPort) &&
+				(aconn->base.connector_type != DRM_MODE_CONNECTOR_eDP)) {
+			DRM_DEBUG_DRIVER("No DP connector available for CRC source\n");
+			ret = -EINVAL;
+			goto cleanup;
+		}
+
 	}
 
 	if (amdgpu_dm_crtc_configure_crc_source(crtc, crtc_state, source)) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
@@ -95,29 +95,29 @@
 
 	rd_buf_ptr = rd_buf;
 
-	str_len = strlen("Current:  %d  %d  %d  ");
-	snprintf(rd_buf_ptr, str_len, "Current:  %d  %d  %d  ",
+	str_len = strlen("Current:  %d  0x%x  %d  ");
+	snprintf(rd_buf_ptr, str_len, "Current:  %d  0x%x  %d  ",
 			link->cur_link_settings.lane_count,
 			link->cur_link_settings.link_rate,
 			link->cur_link_settings.link_spread);
 	rd_buf_ptr += str_len;
 
-	str_len = strlen("Verified:  %d  %d  %d  ");
-	snprintf(rd_buf_ptr, str_len, "Verified:  %d  %d  %d  ",
+	str_len = strlen("Verified:  %d  0x%x  %d  ");
+	snprintf(rd_buf_ptr, str_len, "Verified:  %d  0x%x  %d  ",
 			link->verified_link_cap.lane_count,
 			link->verified_link_cap.link_rate,
 			link->verified_link_cap.link_spread);
 	rd_buf_ptr += str_len;
 
-	str_len = strlen("Reported:  %d  %d  %d  ");
-	snprintf(rd_buf_ptr, str_len, "Reported:  %d  %d  %d  ",
+	str_len = strlen("Reported:  %d  0x%x  %d  ");
+	snprintf(rd_buf_ptr, str_len, "Reported:  %d  0x%x  %d  ",
 			link->reported_link_cap.lane_count,
 			link->reported_link_cap.link_rate,
 			link->reported_link_cap.link_spread);
 	rd_buf_ptr += str_len;
 
-	str_len = strlen("Preferred:  %d  %d  %d  ");
-	snprintf(rd_buf_ptr, str_len, "Preferred:  %d  %d  %d\n",
+	str_len = strlen("Preferred:  %d  0x%x  %d  ");
+	snprintf(rd_buf_ptr, str_len, "Preferred:  %d  0x%x  %d\n",
 			link->preferred_link_setting.lane_count,
 			link->preferred_link_setting.link_rate,
 			link->preferred_link_setting.link_spread);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -247,7 +247,8 @@
 		drm_dp_mst_reset_vcpi_slots(mst_mgr, mst_port);
 	}
 
-	ret = drm_dp_update_payload_part1(mst_mgr);
+	/* It's OK for this to fail */
+	drm_dp_update_payload_part1(mst_mgr);
 
 	/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
 	 * AUX message. The sequence is slot 1-63 allocated sequence for each
@@ -256,9 +257,6 @@
 
 	get_payload_table(aconnector, proposed_table);
 
-	if (ret)
-		return false;
-
 	return true;
 }
 
@@ -316,7 +314,6 @@
 	struct amdgpu_dm_connector *aconnector;
 	struct drm_dp_mst_topology_mgr *mst_mgr;
 	struct drm_dp_mst_port *mst_port;
-	int ret;
 
 	aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context;
 
@@ -330,10 +327,8 @@
 	if (!mst_mgr->mst_state)
 		return false;
 
-	ret = drm_dp_update_payload_part2(mst_mgr);
-
-	if (ret)
-		return false;
+	/* It's OK for this to fail */
+	drm_dp_update_payload_part2(mst_mgr);
 
 	if (!enable)
 		drm_dp_mst_deallocate_vcpi(mst_mgr, mst_port);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -101,7 +101,7 @@
 	result = dc_link_aux_transfer_raw(TO_DM_AUX(aux)->ddc_service, &payload,
 				      &operation_result);
 
-	if (payload.write)
+	if (payload.write && result >= 0)
 		result = msg->size;
 
 	if (result < 0)
@@ -379,6 +379,7 @@
 					   aconnector->dc_sink);
 		dc_sink_release(aconnector->dc_sink);
 		aconnector->dc_sink = NULL;
+		aconnector->dc_link->cur_link_settings.lane_count = 0;
 	}
 
 	drm_connector_unregister(connector);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c
@@ -342,7 +342,8 @@
 	if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->get_clock_by_type) {
 		if (adev->powerplay.pp_funcs->get_clock_by_type(pp_handle,
 			dc_to_pp_clock_type(clk_type), &pp_clks)) {
-		/* Error in pplib. Provide default values. */
+			/* Error in pplib. Provide default values. */
+			get_default_clock_levels(clk_type, dc_clks);
 			return true;
 		}
 	} else if (adev->smu.funcs && adev->smu.funcs->get_clock_by_type) {
@@ -529,6 +530,8 @@
 			&pp_clk_info);
 	else if (adev->smu.funcs)
 		ret = smu_get_current_clocks(&adev->smu, &pp_clk_info);
+	else
+		return false;
 	if (ret)
 		return false;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
@@ -2543,7 +2543,6 @@
 
 	/* Sort voltage table from low to high*/
 	if (result == BP_RESULT_OK) {
-		struct clock_voltage_caps temp = {0, 0};
 		uint32_t i;
 		uint32_t j;
 
@@ -2553,10 +2552,8 @@
 						info->disp_clk_voltage[j].max_supported_clk <
 						info->disp_clk_voltage[j-1].max_supported_clk) {
 					/* swap j and j - 1*/
-					temp = info->disp_clk_voltage[j-1];
-					info->disp_clk_voltage[j-1] =
-							info->disp_clk_voltage[j];
-					info->disp_clk_voltage[j] = temp;
+					swap(info->disp_clk_voltage[j - 1],
+					     info->disp_clk_voltage[j]);
 				}
 			}
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
@@ -1613,8 +1613,6 @@
 
 	struct atom_common_table_header *header;
 	struct atom_data_revision revision;
-
-	struct clock_voltage_caps temp = {0, 0};
 	uint32_t i;
 	uint32_t j;
 
@@ -1644,10 +1642,8 @@
 				info->disp_clk_voltage[j-1].max_supported_clk
 				) {
 				/* swap j and j - 1*/
-				temp = info->disp_clk_voltage[j-1];
-				info->disp_clk_voltage[j-1] =
-					info->disp_clk_voltage[j];
-				info->disp_clk_voltage[j] = temp;
+				swap(info->disp_clk_voltage[j - 1],
+				     info->disp_clk_voltage[j]);
 			}
 		}
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/bios/command_table.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/bios/command_table.c
@@ -245,6 +245,23 @@
 					cntl->enable_dp_audio);
 	params.ucLaneNum = (uint8_t)(cntl->lanes_number);
 
+	switch (cntl->color_depth) {
+	case COLOR_DEPTH_888:
+		params.ucBitPerColor = PANEL_8BIT_PER_COLOR;
+		break;
+	case COLOR_DEPTH_101010:
+		params.ucBitPerColor = PANEL_10BIT_PER_COLOR;
+		break;
+	case COLOR_DEPTH_121212:
+		params.ucBitPerColor = PANEL_12BIT_PER_COLOR;
+		break;
+	case COLOR_DEPTH_161616:
+		params.ucBitPerColor = PANEL_16BIT_PER_COLOR;
+		break;
+	default:
+		break;
+	}
+
 	if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))
 		result = BP_RESULT_OK;
 
@@ -274,6 +291,23 @@
 					cntl->enable_dp_audio));
 	params.ucLaneNum = (uint8_t)(cntl->lanes_number);
 
+	switch (cntl->color_depth) {
+	case COLOR_DEPTH_888:
+		params.ucBitPerColor = PANEL_8BIT_PER_COLOR;
+		break;
+	case COLOR_DEPTH_101010:
+		params.ucBitPerColor = PANEL_10BIT_PER_COLOR;
+		break;
+	case COLOR_DEPTH_121212:
+		params.ucBitPerColor = PANEL_12BIT_PER_COLOR;
+		break;
+	case COLOR_DEPTH_161616:
+		params.ucBitPerColor = PANEL_16BIT_PER_COLOR;
+		break;
+	default:
+		break;
+	}
+
 	if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))
 		result = BP_RESULT_OK;
 
@@ -1057,6 +1091,19 @@
 		 * driver choose program it itself, i.e. here we program it
 		 * to 888 by default.
 		 */
+		if (bp_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A)
+			switch (bp_params->color_depth) {
+			case TRANSMITTER_COLOR_DEPTH_30:
+				/* yes this is correct, the atom define is wrong */
+				clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_32BPP;
+				break;
+			case TRANSMITTER_COLOR_DEPTH_36:
+				/* yes this is correct, the atom define is wrong */
+				clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_30BPP;
+				break;
+			default:
+				break;
+			}
 
 		if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))
 			result = BP_RESULT_OK;
@@ -1135,6 +1182,20 @@
 		 * driver choose program it itself, i.e. here we pass required
 		 * target rate that includes deep color.
 		 */
+		if (bp_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A)
+			switch (bp_params->color_depth) {
+			case TRANSMITTER_COLOR_DEPTH_30:
+				clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_30BPP_V6;
+				break;
+			case TRANSMITTER_COLOR_DEPTH_36:
+				clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_36BPP_V6;
+				break;
+			case TRANSMITTER_COLOR_DEPTH_48:
+				clk.sPCLKInput.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_48BPP;
+				break;
+			default:
+				break;
+			}
 
 		if (EXEC_BIOS_CMD_TABLE(SetPixelClock, clk))
 			result = BP_RESULT_OK;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c
@@ -26,12 +26,12 @@
 #include "bw_fixed.h"
 
 
-#define MIN_I64 \
-	(int64_t)(-(1LL << 63))
-
 #define MAX_I64 \
 	(int64_t)((1ULL << 63) - 1)
 
+#define MIN_I64 \
+	(-MAX_I64 - 1)
+
 #define FRACTIONAL_PART_MASK \
 	((1ULL << BW_FIXED_BITS_PER_FRACTIONAL_PART) - 1)
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c
@@ -1438,6 +1438,7 @@
 	struct dc_context *ctx = dc->ctx;
 	struct dm_pp_clock_levels_with_voltage fclks = {0}, dcfclks = {0};
 	bool res;
+	unsigned vmin0p65_idx, vmid0p72_idx, vnom0p8_idx, vmax0p9_idx;
 
 	/* TODO: This is not the proper way to obtain fabric_and_dram_bandwidth, should be min(fclk, memclk) */
 	res = dm_pp_get_clock_levels_by_type_with_voltage(
@@ -1449,17 +1450,28 @@
 		res = verify_clock_values(&fclks);
 
 	if (res) {
-		ASSERT(fclks.num_levels >= 3);
-		dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65 = 32 * (fclks.data[0].clocks_in_khz / 1000.0) / 1000.0;
-		dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72 = dc->dcn_soc->number_of_channels *
-				(fclks.data[fclks.num_levels - (fclks.num_levels > 2 ? 3 : 2)].clocks_in_khz / 1000.0)
-				* ddr4_dram_factor_single_Channel / 1000.0;
-		dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8 = dc->dcn_soc->number_of_channels *
-				(fclks.data[fclks.num_levels - 2].clocks_in_khz / 1000.0)
-				* ddr4_dram_factor_single_Channel / 1000.0;
-		dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = dc->dcn_soc->number_of_channels *
-				(fclks.data[fclks.num_levels - 1].clocks_in_khz / 1000.0)
-				* ddr4_dram_factor_single_Channel / 1000.0;
+		ASSERT(fclks.num_levels);
+
+		vmin0p65_idx = 0;
+		vmid0p72_idx = fclks.num_levels -
+			(fclks.num_levels > 2 ? 3 : (fclks.num_levels > 1 ? 2 : 1));
+		vnom0p8_idx = fclks.num_levels - (fclks.num_levels > 1 ? 2 : 1);
+		vmax0p9_idx = fclks.num_levels - 1;
+
+		dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65 =
+			32 * (fclks.data[vmin0p65_idx].clocks_in_khz / 1000.0) / 1000.0;
+		dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72 =
+			dc->dcn_soc->number_of_channels *
+			(fclks.data[vmid0p72_idx].clocks_in_khz / 1000.0)
+			* ddr4_dram_factor_single_Channel / 1000.0;
+		dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8 =
+			dc->dcn_soc->number_of_channels *
+			(fclks.data[vnom0p8_idx].clocks_in_khz / 1000.0)
+			* ddr4_dram_factor_single_Channel / 1000.0;
+		dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 =
+			dc->dcn_soc->number_of_channels *
+			(fclks.data[vmax0p9_idx].clocks_in_khz / 1000.0)
+			* ddr4_dram_factor_single_Channel / 1000.0;
 	} else
 		BREAK_TO_DEBUGGER();
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile
@@ -91,6 +91,12 @@
 ###############################################################################
 CLK_MGR_DCN21 = rn_clk_mgr.o rn_clk_mgr_vbios_smu.o
 
+# prevent build errors regarding soft-float vs hard-float FP ABI tags
+# this code is currently unused on ppc64, as it applies to Renoir APUs only
+ifdef CONFIG_PPC64
+CFLAGS_$(AMDDALPATH)/dc/clk_mgr/dcn21/rn_clk_mgr.o := $(call cc-option,-mno-gnu-attribute)
+endif
+
 AMD_DAL_CLK_MGR_DCN21 = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dcn21/,$(CLK_MGR_DCN21))
 
 AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN21)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c
@@ -85,12 +85,77 @@
 	return disp_clk_threshold;
 }
 
-static void ramp_up_dispclk_with_dpp(struct clk_mgr_internal *clk_mgr, struct dc *dc, struct dc_clocks *new_clocks)
+static void ramp_up_dispclk_with_dpp(
+		struct clk_mgr_internal *clk_mgr,
+		struct dc *dc,
+		struct dc_clocks *new_clocks,
+		bool safe_to_lower)
 {
 	int i;
 	int dispclk_to_dpp_threshold = rv1_determine_dppclk_threshold(clk_mgr, new_clocks);
 	bool request_dpp_div = new_clocks->dispclk_khz > new_clocks->dppclk_khz;
 
+	/* this function is to change dispclk, dppclk and dprefclk according to
+	 * bandwidth requirement. Its call stack is rv1_update_clocks -->
+	 * update_clocks --> dcn10_prepare_bandwidth / dcn10_optimize_bandwidth
+	 * --> prepare_bandwidth / optimize_bandwidth. before change dcn hw,
+	 * prepare_bandwidth will be called first to allow enough clock,
+	 * watermark for change, after end of dcn hw change, optimize_bandwidth
+	 * is executed to lower clock to save power for new dcn hw settings.
+	 *
+	 * below is sequence of commit_planes_for_stream:
+	 *
+	 * step 1: prepare_bandwidth - raise clock to have enough bandwidth
+	 * step 2: lock_doublebuffer_enable
+	 * step 3: pipe_control_lock(true) - make dchubp register change will
+	 * not take effect right way
+	 * step 4: apply_ctx_for_surface - program dchubp
+	 * step 5: pipe_control_lock(false) - dchubp register change take effect
+	 * step 6: optimize_bandwidth --> dc_post_update_surfaces_to_stream
+	 * for full_date, optimize clock to save power
+	 *
+	 * at end of step 1, dcn clocks (dprefclk, dispclk, dppclk) may be
+	 * changed for new dchubp configuration. but real dcn hub dchubps are
+	 * still running with old configuration until end of step 5. this need
+	 * clocks settings at step 1 should not less than that before step 1.
+	 * this is checked by two conditions: 1. if (should_set_clock(safe_to_lower
+	 * , new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz) ||
+	 * new_clocks->dispclk_khz == clk_mgr_base->clks.dispclk_khz)
+	 * 2. request_dpp_div = new_clocks->dispclk_khz > new_clocks->dppclk_khz
+	 *
+	 * the second condition is based on new dchubp configuration. dppclk
+	 * for new dchubp may be different from dppclk before step 1.
+	 * for example, before step 1, dchubps are as below:
+	 * pipe 0: recout=(0,40,1920,980) viewport=(0,0,1920,979)
+	 * pipe 1: recout=(0,0,1920,1080) viewport=(0,0,1920,1080)
+	 * for dppclk for pipe0 need dppclk = dispclk
+	 *
+	 * new dchubp pipe split configuration:
+	 * pipe 0: recout=(0,0,960,1080) viewport=(0,0,960,1080)
+	 * pipe 1: recout=(960,0,960,1080) viewport=(960,0,960,1080)
+	 * dppclk only needs dppclk = dispclk /2.
+	 *
+	 * dispclk, dppclk are not lock by otg master lock. they take effect
+	 * after step 1. during this transition, dispclk are the same, but
+	 * dppclk is changed to half of previous clock for old dchubp
+	 * configuration between step 1 and step 6. This may cause p-state
+	 * warning intermittently.
+	 *
+	 * for new_clocks->dispclk_khz == clk_mgr_base->clks.dispclk_khz, we
+	 * need make sure dppclk are not changed to less between step 1 and 6.
+	 * for new_clocks->dispclk_khz > clk_mgr_base->clks.dispclk_khz,
+	 * new display clock is raised, but we do not know ratio of
+	 * new_clocks->dispclk_khz and clk_mgr_base->clks.dispclk_khz,
+	 * new_clocks->dispclk_khz /2 does not guarantee equal or higher than
+	 * old dppclk. we could ignore power saving different between
+	 * dppclk = displck and dppclk = dispclk / 2 between step 1 and step 6.
+	 * as long as safe_to_lower = false, set dpclk = dispclk to simplify
+	 * condition check.
+	 * todo: review this change for other asic.
+	 **/
+	if (!safe_to_lower)
+		request_dpp_div = false;
+
 	/* set disp clk to dpp clk threshold */
 
 	clk_mgr->funcs->set_dispclk(clk_mgr, dispclk_to_dpp_threshold);
@@ -206,7 +271,7 @@
 	/* program dispclk on = as a w/a for sleep resume clock ramping issues */
 	if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)
 			|| new_clocks->dispclk_khz == clk_mgr_base->clks.dispclk_khz) {
-		ramp_up_dispclk_with_dpp(clk_mgr, dc, new_clocks);
+		ramp_up_dispclk_with_dpp(clk_mgr, dc, new_clocks, safe_to_lower);
 		clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz;
 		send_request_to_lower = true;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c
@@ -320,6 +320,8 @@
 		struct dc_state *context,
 		bool safe_to_lower)
 {
+	struct clk_mgr_internal *clk_mgr_int = TO_CLK_MGR_INTERNAL(clk_mgr);
+
 	struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk;
 	/* Min fclk = 1.2GHz since all the extra scemi logic seems to run off of it */
 	int fclk_adj = new_clocks->fclk_khz > 1200000 ? new_clocks->fclk_khz : 1200000;
@@ -357,14 +359,18 @@
 		clk_mgr->clks.dispclk_khz = new_clocks->dispclk_khz;
 	}
 
-	/* Both fclk and dppclk ref are run on the same scemi clock so we
-	 * need to keep the same value for both
+	/* Both fclk and ref_dppclk run on the same scemi clock.
+	 * So take the higher value since the DPP DTO is typically programmed
+	 * such that max dppclk is 1:1 with ref_dppclk.
 	 */
 	if (clk_mgr->clks.fclk_khz > clk_mgr->clks.dppclk_khz)
 		clk_mgr->clks.dppclk_khz = clk_mgr->clks.fclk_khz;
 	if (clk_mgr->clks.dppclk_khz > clk_mgr->clks.fclk_khz)
 		clk_mgr->clks.fclk_khz = clk_mgr->clks.dppclk_khz;
 
+	// Both fclk and ref_dppclk run on the same scemi clock.
+	clk_mgr_int->dccg->ref_dppclk = clk_mgr->clks.fclk_khz;
+
 	dm_set_dcn_clocks(clk_mgr->ctx, &clk_mgr->clks);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
@@ -91,8 +91,23 @@
 		rn_vbios_smu_set_min_deep_sleep_dcfclk(clk_mgr, clk_mgr_base->clks.dcfclk_deep_sleep_khz);
 	}
 
-	if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr->base.clks.dppclk_khz)) {
-		if (clk_mgr->base.clks.dppclk_khz > new_clocks->dppclk_khz)
+	// workaround: Limit dppclk to 100Mhz to avoid lower eDP panel switch to plus 4K monitor underflow.
+	if (!IS_DIAG_DC(dc->ctx->dce_environment)) {
+		if (new_clocks->dppclk_khz < 100000)
+			new_clocks->dppclk_khz = 100000;
+	}
+
+	/*
+	 * Temporally ignore thew 0 cases for disp and dpp clks.
+	 * We may have a new feature that requires 0 clks in the future.
+	 */
+	if (new_clocks->dppclk_khz == 0 || new_clocks->dispclk_khz == 0) {
+		new_clocks->dppclk_khz = clk_mgr_base->clks.dppclk_khz;
+		new_clocks->dispclk_khz = clk_mgr_base->clks.dispclk_khz;
+	}
+
+	if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr_base->clks.dppclk_khz)) {
+		if (clk_mgr_base->clks.dppclk_khz > new_clocks->dppclk_khz)
 			dpp_clock_lowered = true;
 		clk_mgr_base->clks.dppclk_khz = new_clocks->dppclk_khz;
 		update_dppclk = true;
@@ -438,7 +453,8 @@
 			ranges->reader_wm_sets[num_valid_sets].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
 
 			/* Modify previous watermark range to cover up to max */
-			ranges->reader_wm_sets[num_valid_sets - 1].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
+			if (num_valid_sets > 0)
+				ranges->reader_wm_sets[num_valid_sets - 1].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
 		}
 		num_valid_sets++;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.c
@@ -33,7 +33,7 @@
 #include "mp/mp_12_0_0_sh_mask.h"
 
 #define REG(reg_name) \
-	(MP1_BASE.instance[0].segment[mm ## reg_name ## _BASE_IDX] + mm ## reg_name)
+	(MP0_BASE.instance[0].segment[mm ## reg_name ## _BASE_IDX] + mm ## reg_name)
 
 #define FN(reg_name, field) \
 	FD(reg_name##__##field)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -283,6 +283,8 @@
 	int i = 0;
 	bool ret = false;
 
+	stream->adjust = *adjust;
+
 	for (i = 0; i < MAX_PIPES; i++) {
 		struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
 
@@ -905,15 +907,11 @@
 
 		/* set first pipe with plane as master */
 		for (j = 0; j < group_size; j++) {
-			struct pipe_ctx *temp;
-
 			if (pipe_set[j]->plane_state) {
 				if (j == 0)
 					break;
 
-				temp = pipe_set[0];
-				pipe_set[0] = pipe_set[j];
-				pipe_set[j] = temp;
+				swap(pipe_set[0], pipe_set[j]);
 				break;
 			}
 		}
@@ -1180,6 +1178,26 @@
 	return (result == DC_OK);
 }
 
+static bool is_flip_pending_in_pipes(struct dc *dc, struct dc_state *context)
+{
+	int i;
+	struct pipe_ctx *pipe;
+
+	for (i = 0; i < MAX_PIPES; i++) {
+		pipe = &context->res_ctx.pipe_ctx[i];
+
+		if (!pipe->plane_state)
+			continue;
+
+		/* Must set to false to start with, due to OR in update function */
+		pipe->plane_state->status.is_flip_pending = false;
+		dc->hwss.update_pending_status(pipe);
+		if (pipe->plane_state->status.is_flip_pending)
+			return true;
+	}
+	return false;
+}
+
 bool dc_post_update_surfaces_to_stream(struct dc *dc)
 {
 	int i;
@@ -1190,6 +1208,9 @@
 
 	post_surface_trace(dc);
 
+	if (is_flip_pending_in_pipes(dc, context))
+		return true;
+
 	for (i = 0; i < dc->res_pool->pipe_count; i++)
 		if (context->res_ctx.pipe_ctx[i].stream == NULL ||
 		    context->res_ctx.pipe_ctx[i].plane_state == NULL) {
@@ -1940,7 +1961,8 @@
 					if (pipe_ctx->stream_res.audio && !dc->debug.az_endpoint_mute_only)
 						pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
 
-					dc->hwss.optimize_bandwidth(dc, dc->current_state);
+					dc->optimized_required = true;
+
 				} else {
 					if (!dc->optimize_seamless_boot)
 						dc->hwss.prepare_bandwidth(dc, dc->current_state);
@@ -2028,6 +2050,10 @@
 						plane_state->triplebuffer_flips = true;
 				}
 			}
+			if (update_type == UPDATE_TYPE_FULL) {
+				/* force vsync flip when reconfiguring pipes to prevent underflow */
+				plane_state->flip_immediate = false;
+			}
 		}
 	}
 #endif
@@ -2152,7 +2178,7 @@
 	enum surface_update_type update_type;
 	struct dc_state *context;
 	struct dc_context *dc_ctx = dc->ctx;
-	int i;
+	int i, j;
 
 	stream_status = dc_stream_get_status(stream);
 	context = dc->current_state;
@@ -2190,10 +2216,29 @@
 
 		copy_surface_update_to_plane(surface, &srf_updates[i]);
 
+		if (update_type >= UPDATE_TYPE_MED) {
+			for (j = 0; j < dc->res_pool->pipe_count; j++) {
+				struct pipe_ctx *pipe_ctx =
+					&context->res_ctx.pipe_ctx[j];
+
+				if (pipe_ctx->plane_state != surface)
+					continue;
+
+				resource_build_scaling_params(pipe_ctx);
+			}
+		}
 	}
 
 	copy_stream_update_to_stream(dc, context, stream, stream_update);
 
+	if (update_type > UPDATE_TYPE_FAST) {
+		if (!dc->res_pool->funcs->validate_bandwidth(dc, context, false)) {
+			DC_ERROR("Mode validation failed for stream update!\n");
+			dc_release_state(context);
+			return;
+		}
+	}
+
 	commit_planes_for_stream(
 				dc,
 				srf_updates,
@@ -2267,12 +2312,7 @@
 	enum dc_acpi_cm_power_state power_state)
 {
 	struct kref refcount;
-	struct display_mode_lib *dml = kzalloc(sizeof(struct display_mode_lib),
-						GFP_KERNEL);
-
-	ASSERT(dml);
-	if (!dml)
-		return;
+	struct display_mode_lib *dml;
 
 	switch (power_state) {
 	case DC_ACPI_CM_POWER_STATE_D0:
@@ -2294,6 +2334,12 @@
 		 * clean state, and dc hw programming optimizations will not
 		 * cause any trouble.
 		 */
+		dml = kzalloc(sizeof(struct display_mode_lib),
+				GFP_KERNEL);
+
+		ASSERT(dml);
+		if (!dml)
+			return;
 
 		/* Preserve refcount */
 		refcount = dc->current_state->refcount;
@@ -2307,10 +2353,10 @@
 		dc->current_state->refcount = refcount;
 		dc->current_state->bw_ctx.dml = *dml;
 
+		kfree(dml);
+
 		break;
 	}
-
-	kfree(dml);
 }
 
 void dc_resume(struct dc *dc)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
@@ -92,8 +92,8 @@
 		{ 0xE00, 0xF349, 0xFEB7, 0x1000, 0x6CE, 0x16E3,
 				0x24F, 0x200, 0xFCCB, 0xF535, 0xE00, 0x1000} },
 	{ COLOR_SPACE_YCBCR2020_TYPE,
-		{ 0x1000, 0xF149, 0xFEB7, 0x0000, 0x0868, 0x15B2,
-				0x01E6, 0x0000, 0xFB88, 0xF478, 0x1000, 0x0000} },
+		{ 0x1000, 0xF149, 0xFEB7, 0x1004, 0x0868, 0x15B2,
+				0x01E6, 0x201, 0xFB88, 0xF478, 0x1000, 0x1004} },
 	{ COLOR_SPACE_YCBCR709_BLACK_TYPE,
 		{ 0x0000, 0x0000, 0x0000, 0x1000, 0x0000, 0x0000,
 				0x0000, 0x0200, 0x0000, 0x0000, 0x0000, 0x1000} },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/core/dc_link.c
@@ -373,7 +373,7 @@
 
 	if (GPIO_RESULT_OK != dal_ddc_open(
 		ddc, GPIO_MODE_INPUT, GPIO_DDC_CONFIG_TYPE_MODE_I2C)) {
-		dal_gpio_destroy_ddc(&ddc);
+		dal_ddc_close(ddc);
 
 		return present;
 	}
@@ -809,8 +809,8 @@
 		}
 
 		case SIGNAL_TYPE_EDP: {
-			read_edp_current_link_settings_on_detect(link);
 			detect_edp_sink_caps(link);
+			read_edp_current_link_settings_on_detect(link);
 			sink_caps.transaction_type =
 				DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
 			sink_caps.signal = SIGNAL_TYPE_EDP;
@@ -936,6 +936,24 @@
 			    dc_is_dvi_signal(link->connector_signal)) {
 				if (prev_sink != NULL)
 					dc_sink_release(prev_sink);
+				link_disconnect_sink(link);
+
+				return false;
+			}
+			/*
+			 * Abort detection for DP connectors if we have
+			 * no EDID and connector is active converter
+			 * as there are no display downstream
+			 *
+			 */
+			if (dc_is_dp_sst_signal(link->connector_signal) &&
+				(link->dpcd_caps.dongle_type ==
+						DISPLAY_DONGLE_DP_VGA_CONVERTER ||
+				link->dpcd_caps.dongle_type ==
+						DISPLAY_DONGLE_DP_DVI_CONVERTER)) {
+				if (prev_sink)
+					dc_sink_release(prev_sink);
+				link_disconnect_sink(link);
 
 				return false;
 			}
@@ -948,8 +966,7 @@
 			same_edid = is_same_edid(&prev_sink->dc_edid, &sink->dc_edid);
 
 		if (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT &&
-			sink_caps.transaction_type == DDC_TRANSACTION_TYPE_I2C_OVER_AUX &&
-			reason != DETECT_REASON_HPDRX) {
+			sink_caps.transaction_type == DDC_TRANSACTION_TYPE_I2C_OVER_AUX) {
 			/*
 			 * TODO debug why Dell 2413 doesn't like
 			 *  two link trainings
@@ -1304,6 +1321,11 @@
 		goto ddc_create_fail;
 	}
 
+	if (!link->ddc->ddc_pin) {
+		DC_ERROR("Failed to get I2C info for connector!\n");
+		goto ddc_create_fail;
+	}
+
 	link->ddc_hw_inst =
 		dal_ddc_get_line(
 			dal_ddc_service_get_ddc_pin(link->ddc));
@@ -1734,8 +1756,7 @@
 				slave_address, buffer[0], buffer[1], i2c_success?1:0);
 
 			if (!i2c_success)
-				/* Write failure */
-				ASSERT(i2c_success);
+				goto i2c_write_fail;
 
 			/* Based on DP159 specs, APPLY_RX_TX_CHANGE bit in 0x0A
 			 * needs to be set to 1 on every 0xA-0xC write.
@@ -1753,8 +1774,7 @@
 						pipe_ctx->stream->link->ddc,
 						slave_address, &offset, 1, &value, 1);
 					if (!i2c_success)
-						/* Write failure */
-						ASSERT(i2c_success);
+						goto i2c_write_fail;
 				}
 
 				buffer[0] = offset;
@@ -1766,8 +1786,7 @@
 					offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",
 					slave_address, buffer[0], buffer[1], i2c_success?1:0);
 				if (!i2c_success)
-					/* Write failure */
-					ASSERT(i2c_success);
+					goto i2c_write_fail;
 			}
 		}
 	}
@@ -1787,8 +1806,7 @@
 					slave_address, buffer[0], buffer[1], i2c_success?1:0);
 
 				if (!i2c_success)
-					/* Write failure */
-					ASSERT(i2c_success);
+					goto i2c_write_fail;
 
 				/* Based on DP159 specs, APPLY_RX_TX_CHANGE bit in 0x0A
 				 * needs to be set to 1 on every 0xA-0xC write.
@@ -1806,8 +1824,7 @@
 								pipe_ctx->stream->link->ddc,
 								slave_address, &offset, 1, &value, 1);
 						if (!i2c_success)
-							/* Write failure */
-							ASSERT(i2c_success);
+							goto i2c_write_fail;
 					}
 
 					buffer[0] = offset;
@@ -1819,8 +1836,7 @@
 						offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",
 						slave_address, buffer[0], buffer[1], i2c_success?1:0);
 					if (!i2c_success)
-						/* Write failure */
-						ASSERT(i2c_success);
+						goto i2c_write_fail;
 				}
 			}
 		}
@@ -1838,8 +1854,7 @@
 				offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",
 				slave_address, buffer[0], buffer[1], i2c_success?1:0);
 		if (!i2c_success)
-			/* Write failure */
-			ASSERT(i2c_success);
+			goto i2c_write_fail;
 
 		/* Write offset 0x00 to 0x23 */
 		buffer[0] = 0x00;
@@ -1850,8 +1865,7 @@
 			offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",
 			slave_address, buffer[0], buffer[1], i2c_success?1:0);
 		if (!i2c_success)
-			/* Write failure */
-			ASSERT(i2c_success);
+			goto i2c_write_fail;
 
 		/* Write offset 0xff to 0x00 */
 		buffer[0] = 0xff;
@@ -1862,10 +1876,14 @@
 			offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",
 			slave_address, buffer[0], buffer[1], i2c_success?1:0);
 		if (!i2c_success)
-			/* Write failure */
-			ASSERT(i2c_success);
+			goto i2c_write_fail;
 
 	}
+
+	return;
+
+i2c_write_fail:
+	DC_LOG_DEBUG("Set retimer failed");
 }
 
 static void write_i2c_default_retimer_setting(
@@ -1890,8 +1908,7 @@
 		offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",
 		slave_address, buffer[0], buffer[1], i2c_success?1:0);
 	if (!i2c_success)
-		/* Write failure */
-		ASSERT(i2c_success);
+		goto i2c_write_fail;
 
 	/* Write offset 0x0A to 0x17 */
 	buffer[0] = 0x0A;
@@ -1902,8 +1919,7 @@
 		offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",
 		slave_address, buffer[0], buffer[1], i2c_success?1:0);
 	if (!i2c_success)
-		/* Write failure */
-		ASSERT(i2c_success);
+		goto i2c_write_fail;
 
 	/* Write offset 0x0B to 0xDA or 0xD8 */
 	buffer[0] = 0x0B;
@@ -1914,8 +1930,7 @@
 		offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",
 		slave_address, buffer[0], buffer[1], i2c_success?1:0);
 	if (!i2c_success)
-		/* Write failure */
-		ASSERT(i2c_success);
+		goto i2c_write_fail;
 
 	/* Write offset 0x0A to 0x17 */
 	buffer[0] = 0x0A;
@@ -1926,8 +1941,7 @@
 		offset = 0x%x, reg_val= 0x%x, i2c_success = %d\n",
 		slave_address, buffer[0], buffer[1], i2c_success?1:0);
 	if (!i2c_success)
-		/* Write failure */
-		ASSERT(i2c_success);
+		goto i2c_write_fail;
 
 	/* Write offset 0x0C to 0x1D or 0x91 */
 	buffer[0] = 0x0C;
@@ -1938,8 +1952,7 @@
 		offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",
 		slave_address, buffer[0], buffer[1], i2c_success?1:0);
 	if (!i2c_success)
-		/* Write failure */
-		ASSERT(i2c_success);
+		goto i2c_write_fail;
 
 	/* Write offset 0x0A to 0x17 */
 	buffer[0] = 0x0A;
@@ -1950,8 +1963,7 @@
 		offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",
 		slave_address, buffer[0], buffer[1], i2c_success?1:0);
 	if (!i2c_success)
-		/* Write failure */
-		ASSERT(i2c_success);
+		goto i2c_write_fail;
 
 
 	if (is_vga_mode) {
@@ -1966,8 +1978,7 @@
 			offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",
 			slave_address, buffer[0], buffer[1], i2c_success?1:0);
 		if (!i2c_success)
-			/* Write failure */
-			ASSERT(i2c_success);
+			goto i2c_write_fail;
 
 		/* Write offset 0x00 to 0x23 */
 		buffer[0] = 0x00;
@@ -1978,8 +1989,7 @@
 			offset = 0x%x, reg_val= 0x%x, i2c_success = %d\n",
 			slave_address, buffer[0], buffer[1], i2c_success?1:0);
 		if (!i2c_success)
-			/* Write failure */
-			ASSERT(i2c_success);
+			goto i2c_write_fail;
 
 		/* Write offset 0xff to 0x00 */
 		buffer[0] = 0xff;
@@ -1990,9 +2000,13 @@
 			offset = 0x%x, reg_val= 0x%x, i2c_success = %d end here\n",
 			slave_address, buffer[0], buffer[1], i2c_success?1:0);
 		if (!i2c_success)
-			/* Write failure */
-			ASSERT(i2c_success);
+			goto i2c_write_fail;
 	}
+
+	return;
+
+i2c_write_fail:
+	DC_LOG_DEBUG("Set default retimer failed");
 }
 
 static void write_i2c_redriver_setting(
@@ -2021,8 +2035,7 @@
 		slave_address, buffer[3], buffer[4], buffer[5], buffer[6], i2c_success?1:0);
 
 	if (!i2c_success)
-		/* Write failure */
-		ASSERT(i2c_success);
+		DC_LOG_DEBUG("Set redriver failed");
 }
 
 static void enable_link_hdmi(struct pipe_ctx *pipe_ctx)
@@ -2169,8 +2182,10 @@
 			dp_set_fec_ready(link, false);
 		}
 #endif
-	} else
-		link->link_enc->funcs->disable_output(link->link_enc, signal);
+	} else {
+		if (signal != SIGNAL_TYPE_VIRTUAL)
+			link->link_enc->funcs->disable_output(link->link_enc, signal);
+	}
 
 	if (signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
 		/* MST disable link only when no stream use the link */
@@ -2217,7 +2232,7 @@
 		break;
 	}
 
-	if (dongle_caps->dongle_type != DISPLAY_DONGLE_DP_HDMI_CONVERTER ||
+	if (dpcd_caps->dongle_type != DISPLAY_DONGLE_DP_HDMI_CONVERTER ||
 		dongle_caps->extendedCapValid == false)
 		return true;
 
@@ -2276,7 +2291,7 @@
 	/* A hack to avoid failing any modes for EDID override feature on
 	 * topology change such as lower quality cable for DP or different dongle
 	 */
-	if (link->remote_sinks[0])
+	if (link->remote_sinks[0] && link->remote_sinks[0]->sink_signal == SIGNAL_TYPE_VIRTUAL)
 		return DC_OK;
 
 	/* Passive Dongle */
@@ -2917,8 +2932,12 @@
 
 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
 	if (timing->flags.DSC) {
-		kbps = (timing->pix_clk_100hz * timing->dsc_cfg.bits_per_pixel);
-		kbps = kbps / 160 + ((kbps % 160) ? 1 : 0);
+		struct fixed31_32 link_bw_kbps;
+
+		link_bw_kbps = dc_fixpt_from_int(timing->pix_clk_100hz);
+		link_bw_kbps = dc_fixpt_div_int(link_bw_kbps, 160);
+		link_bw_kbps = dc_fixpt_mul_int(link_bw_kbps, timing->dsc_cfg.bits_per_pixel);
+		kbps = dc_fixpt_ceil(link_bw_kbps);
 		return kbps;
 	}
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c
@@ -126,22 +126,16 @@
 	struct vector payloads;
 };
 
-static struct i2c_payloads *dal_ddc_i2c_payloads_create(struct dc_context *ctx, uint32_t count)
+static bool dal_ddc_i2c_payloads_create(
+		struct dc_context *ctx,
+		struct i2c_payloads *payloads,
+		uint32_t count)
 {
-	struct i2c_payloads *payloads;
-
-	payloads = kzalloc(sizeof(struct i2c_payloads), GFP_KERNEL);
-
-	if (!payloads)
-		return NULL;
-
 	if (dal_vector_construct(
 		&payloads->payloads, ctx, count, sizeof(struct i2c_payload)))
-		return payloads;
-
-	kfree(payloads);
-	return NULL;
+		return true;
 
+	return false;
 }
 
 static struct i2c_payload *dal_ddc_i2c_payloads_get(struct i2c_payloads *p)
@@ -154,14 +148,12 @@
 	return p->payloads.count;
 }
 
-static void dal_ddc_i2c_payloads_destroy(struct i2c_payloads **p)
+static void dal_ddc_i2c_payloads_destroy(struct i2c_payloads *p)
 {
-	if (!p || !*p)
+	if (!p)
 		return;
-	dal_vector_destruct(&(*p)->payloads);
-	kfree(*p);
-	*p = NULL;
 
+	dal_vector_destruct(&p->payloads);
 }
 
 #define DDC_MIN(a, b) (((a) < (b)) ? (a) : (b))
@@ -521,9 +513,13 @@
 
 	uint32_t payloads_num = write_payloads + read_payloads;
 
+
 	if (write_size > EDID_SEGMENT_SIZE || read_size > EDID_SEGMENT_SIZE)
 		return false;
 
+	if (!payloads_num)
+		return false;
+
 	/*TODO: len of payload data for i2c and aux is uint8!!!!,
 	 *  but we want to read 256 over i2c!!!!*/
 	if (dal_ddc_service_is_in_aux_transaction_mode(ddc)) {
@@ -556,23 +552,25 @@
 
 		ret = dc_link_aux_transfer_with_retries(ddc, &read_payload);
 	} else {
-		struct i2c_payloads *payloads =
-			dal_ddc_i2c_payloads_create(ddc->ctx, payloads_num);
+		struct i2c_command command = {0};
+		struct i2c_payloads payloads;
+
+		if (!dal_ddc_i2c_payloads_create(ddc->ctx, &payloads, payloads_num))
+			return false;
 
-		struct i2c_command command = {
-			.payloads = dal_ddc_i2c_payloads_get(payloads),
-			.number_of_payloads = 0,
-			.engine = DDC_I2C_COMMAND_ENGINE,
-			.speed = ddc->ctx->dc->caps.i2c_speed_in_khz };
+		command.payloads = dal_ddc_i2c_payloads_get(&payloads);
+		command.number_of_payloads = 0;
+		command.engine = DDC_I2C_COMMAND_ENGINE;
+		command.speed = ddc->ctx->dc->caps.i2c_speed_in_khz;
 
 		dal_ddc_i2c_payloads_add(
-			payloads, address, write_size, write_buf, true);
+			&payloads, address, write_size, write_buf, true);
 
 		dal_ddc_i2c_payloads_add(
-			payloads, address, read_size, read_buf, false);
+			&payloads, address, read_size, read_buf, false);
 
 		command.number_of_payloads =
-			dal_ddc_i2c_payloads_get_count(payloads);
+			dal_ddc_i2c_payloads_get_count(&payloads);
 
 		ret = dm_helpers_submit_i2c(
 				ddc->ctx,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
@@ -1284,6 +1284,8 @@
 		link->type = dc_connection_single;
 		link->local_sink = link->remote_sinks[0];
 		link->local_sink->sink_signal = SIGNAL_TYPE_DISPLAY_PORT;
+		dc_sink_retain(link->local_sink);
+		dm_helpers_dp_mst_stop_top_mgr(link->ctx, link);
 	} else if (mst_enable == true &&
 			link->type == dc_connection_single &&
 			link->remote_sinks[0] != NULL) {
@@ -1914,6 +1916,9 @@
 			initial_link_setting;
 	uint32_t link_bw;
 
+	if (req_bw > dc_link_bandwidth_kbps(link, &link->verified_link_cap))
+		return false;
+
 	/* search for the minimum link setting that:
 	 * 1. is supported according to the link training result
 	 * 2. could support the b/w requested by the timing
@@ -2545,6 +2550,7 @@
 	uint8_t data, struct dc_link *link)
 {
 	union dp_downstream_port_present ds_port = { .byte = data };
+	memset(&link->dpcd_caps.dongle_caps, 0, sizeof(link->dpcd_caps.dongle_caps));
 
 	/* decode converter info*/
 	if (!ds_port.fields.PORT_PRESENT) {
@@ -2691,6 +2697,7 @@
 		 * keep receiver powered all the time.*/
 		case DP_BRANCH_DEVICE_ID_0010FA:
 		case DP_BRANCH_DEVICE_ID_0080E1:
+		case DP_BRANCH_DEVICE_ID_00E04C:
 			link->wa_flags.dp_keep_receiver_powered = true;
 			break;
 
@@ -2877,6 +2884,17 @@
 		sink_id.ieee_device_id,
 		sizeof(sink_id.ieee_device_id));
 
+	/* Quirk Apple MBP 2017 15" Retina panel: Wrong DP_MAX_LINK_RATE */
+	{
+		uint8_t str_mbp_2017[] = { 101, 68, 21, 101, 98, 97 };
+
+		if ((link->dpcd_caps.sink_dev_id == 0x0010fa) &&
+		    !memcmp(link->dpcd_caps.sink_dev_id_str, str_mbp_2017,
+			    sizeof(str_mbp_2017))) {
+			link->reported_link_cap.link_rate = 0x0c;
+		}
+	}
+
 	core_link_read_dpcd(
 		link,
 		DP_SINK_HW_REVISION_START,
@@ -3365,7 +3383,7 @@
 
 		if (edp_config_set.bits.PANEL_MODE_EDP
 			!= panel_mode_edp) {
-			enum ddc_result result = DDC_RESULT_UNKNOWN;
+			enum dc_status result = DC_ERROR_UNEXPECTED;
 
 			edp_config_set.bits.PANEL_MODE_EDP =
 			panel_mode_edp;
@@ -3375,7 +3393,7 @@
 				&edp_config_set.raw,
 				sizeof(edp_config_set.raw));
 
-			ASSERT(result == DDC_RESULT_SUCESSFULL);
+			ASSERT(result == DC_OK);
 		}
 	}
 	DC_LOG_DETECTION_DP_CAPS("Link: %d eDP panel mode supported: %d "
@@ -3490,7 +3508,14 @@
 	if (link_enc->funcs->fec_set_enable &&
 			link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) {
 		if (link->fec_state == dc_link_fec_ready && enable) {
-			msleep(1);
+			/* Accord to DP spec, FEC enable sequence can first
+			 * be transmitted anytime after 1000 LL codes have
+			 * been transmitted on the link after link training
+			 * completion. Using 1 lane RBR should have the maximum
+			 * time for transmitting 1000 LL codes which is 6.173 us.
+			 * So use 7 microseconds delay instead.
+			 */
+			udelay(7);
 			link_enc->funcs->fec_set_enable(link_enc, true);
 			link->fec_state = dc_link_fec_enabled;
 		} else if (link->fec_state == dc_link_fec_enabled && !enable) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
@@ -277,7 +277,8 @@
 		if (pipes[i].stream != NULL &&
 			!pipes[i].top_pipe && !pipes[i].prev_odm_pipe &&
 			pipes[i].stream->link != NULL &&
-			pipes[i].stream_res.stream_enc != NULL) {
+			pipes[i].stream_res.stream_enc != NULL &&
+			pipes[i].stream->link == link) {
 			udelay(100);
 
 			pipes[i].stream_res.stream_enc->funcs->dp_blank(
@@ -399,6 +400,7 @@
 		dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;
 		dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
 		dsc_cfg.color_depth = stream->timing.display_color_depth;
+		dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false;
 		dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
 		ASSERT(dsc_cfg.dc_dsc_cfg.num_slices_h % opp_cnt == 0);
 		dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
@@ -495,11 +497,15 @@
 		struct dsc_config dsc_cfg;
 		uint8_t dsc_packed_pps[128];
 
+		memset(&dsc_cfg, 0, sizeof(dsc_cfg));
+		memset(dsc_packed_pps, 0, 128);
+
 		/* Enable DSC hw block */
 		dsc_cfg.pic_width = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;
 		dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;
 		dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
 		dsc_cfg.color_depth = stream->timing.display_color_depth;
+		dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false;
 		dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
 
 		DC_LOG_DSC(" ");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -1315,6 +1315,9 @@
 	struct dc_stream_status *stream_status = NULL;
 	struct resource_pool *pool = dc->res_pool;
 
+	if (!plane_state)
+		return true;
+
 	for (i = 0; i < context->stream_count; i++)
 		if (context->streams[i] == stream) {
 			stream_status = &context->stream_status[i];
@@ -1539,6 +1542,8 @@
 bool dc_is_stream_unchanged(
 	struct dc_stream_state *old_stream, struct dc_stream_state *stream)
 {
+	if (!old_stream || !stream)
+		return false;
 
 	if (!are_stream_backends_same(old_stream, stream))
 		return false;
@@ -1546,6 +1551,10 @@
 	if (old_stream->ignore_msa_timing_param != stream->ignore_msa_timing_param)
 		return false;
 
+	/*compare audio info*/
+	if (memcmp(&old_stream->audio_info, &stream->audio_info, sizeof(stream->audio_info)) != 0)
+		return false;
+
 	return true;
 }
 
@@ -1639,6 +1648,9 @@
 {
 	int i, available_audio_count;
 
+	if (id == ENGINE_ID_UNKNOWN)
+		return NULL;
+
 	available_audio_count = pool->audio_count;
 
 	for (i = 0; i < available_audio_count; i++) {
@@ -1822,10 +1834,13 @@
 			break;
 		case COLOR_DEPTH_121212:
 			normalized_pix_clk = (pix_clk * 36) / 24;
-		break;
+			break;
+		case COLOR_DEPTH_141414:
+			normalized_pix_clk = (pix_clk * 42) / 24;
+			break;
 		case COLOR_DEPTH_161616:
 			normalized_pix_clk = (pix_clk * 48) / 24;
-		break;
+			break;
 		default:
 			ASSERT(0);
 		break;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
@@ -423,10 +423,10 @@
 
 		if (dwb->funcs->is_enabled(dwb)) {
 			/* writeback pipe already enabled, only need to update */
-			dc->hwss.update_writeback(dc, stream_status, wb_info);
+			dc->hwss.update_writeback(dc, stream_status, wb_info, dc->current_state);
 		} else {
 			/* Enable writeback pipe from scratch*/
-			dc->hwss.enable_writeback(dc, stream_status, wb_info);
+			dc->hwss.enable_writeback(dc, stream_status, wb_info, dc->current_state);
 		}
 	}
 
@@ -492,7 +492,7 @@
 	for (i = 0; i < MAX_PIPES; i++) {
 		struct timing_generator *tg = res_ctx->pipe_ctx[i].stream_res.tg;
 
-		if (res_ctx->pipe_ctx[i].stream != stream)
+		if (res_ctx->pipe_ctx[i].stream != stream || !tg)
 			continue;
 
 		return tg->funcs->get_frame_count(tg);
@@ -551,7 +551,7 @@
 	for (i = 0; i < MAX_PIPES; i++) {
 		struct timing_generator *tg = res_ctx->pipe_ctx[i].stream_res.tg;
 
-		if (res_ctx->pipe_ctx[i].stream != stream)
+		if (res_ctx->pipe_ctx[i].stream != stream || !tg)
 			continue;
 
 		tg->funcs->get_scanoutpos(tg,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/core/dc_surface.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/core/dc_surface.c
@@ -165,7 +165,8 @@
 		if (pipe_ctx->plane_state != plane_state)
 			continue;
 
-		pipe_ctx->plane_state->status.is_flip_pending = false;
+		if (pipe_ctx->plane_state)
+			pipe_ctx->plane_state->status.is_flip_pending = false;
 
 		break;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/dc.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/dc.h
@@ -41,7 +41,7 @@
 
 #define DC_VER "3.2.48"
 
-#define MAX_SURFACES 3
+#define MAX_SURFACES 4
 #define MAX_PLANES 6
 #define MAX_STREAMS 6
 #define MAX_SINKS_PER_LINK 4
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c
@@ -77,6 +77,9 @@
 	/* notifyDMCUMsg */
 	REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1);
 
+	REG_WAIT(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 0,
+			1, 80000);
+
 	return true;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c
@@ -386,7 +386,7 @@
 {
 	enum gpio_result result;
 
-	if (!is_engine_available(engine))
+	if ((engine == NULL) || !is_engine_available(engine))
 		return false;
 
 	result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
@@ -546,9 +546,11 @@
 		switch (pix_clk_params->color_depth) {
 		case COLOR_DEPTH_101010:
 			actual_pixel_clock_100hz = (actual_pixel_clock_100hz * 5) >> 2;
+			actual_pixel_clock_100hz -= actual_pixel_clock_100hz % 10;
 			break;
 		case COLOR_DEPTH_121212:
 			actual_pixel_clock_100hz = (actual_pixel_clock_100hz * 6) >> 2;
+			actual_pixel_clock_100hz -= actual_pixel_clock_100hz % 10;
 			break;
 		case COLOR_DEPTH_161616:
 			actual_pixel_clock_100hz = actual_pixel_clock_100hz * 2;
@@ -871,6 +873,20 @@
 	bp_pc_params.flags.SET_EXTERNAL_REF_DIV_SRC =
 					pll_settings->use_external_clk;
 
+	switch (pix_clk_params->color_depth) {
+	case COLOR_DEPTH_101010:
+		bp_pc_params.color_depth = TRANSMITTER_COLOR_DEPTH_30;
+		break;
+	case COLOR_DEPTH_121212:
+		bp_pc_params.color_depth = TRANSMITTER_COLOR_DEPTH_36;
+		break;
+	case COLOR_DEPTH_161616:
+		bp_pc_params.color_depth = TRANSMITTER_COLOR_DEPTH_48;
+		break;
+	default:
+		break;
+	}
+
 	if (clk_src->bios->funcs->set_pixel_clock(
 			clk_src->bios, &bp_pc_params) != BP_RESULT_OK)
 		return false;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
@@ -563,6 +563,7 @@
 	cntl.enable_dp_audio = enable_audio;
 	cntl.pixel_clock = actual_pix_clk_khz;
 	cntl.lanes_number = LANE_COUNT_FOUR;
+	cntl.color_depth = crtc_timing->display_color_depth;
 
 	if (enc110->base.bp->funcs->encoder_control(
 			enc110->base.bp, &cntl) != BP_RESULT_OK)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c
@@ -429,12 +429,12 @@
 		clamp_max = 0x3FC0;
 		break;
 	case COLOR_DEPTH_101010:
-		/* 10bit MSB aligned on 14 bit bus '11 1111 1111 1100' */
-		clamp_max = 0x3FFC;
+		/* 10bit MSB aligned on 14 bit bus '11 1111 1111 0000' */
+		clamp_max = 0x3FF0;
 		break;
 	case COLOR_DEPTH_121212:
-		/* 12bit MSB aligned on 14 bit bus '11 1111 1111 1111' */
-		clamp_max = 0x3FFF;
+		/* 12bit MSB aligned on 14 bit bus '11 1111 1111 1100' */
+		clamp_max = 0x3FFC;
 		break;
 	default:
 		clamp_max = 0x3FC0;
@@ -778,7 +778,7 @@
 		color_depth = COLOR_DEPTH_101010;
 		pixel_depth = 0;
 		expan_mode  = 1;
-		BREAK_TO_DEBUGGER();
+		DC_LOG_DC("The pixel depth %d is not valid, set COLOR_DEPTH_101010 instead.", depth);
 		break;
 	}
 
@@ -792,8 +792,7 @@
 	if (!(xfm_dce->lb_pixel_depth_supported & depth)) {
 		/*we should use unsupported capabilities
 		 *  unless it is required by w/a*/
-		DC_LOG_WARNING("%s: Capability not supported",
-			__func__);
+		DC_LOG_DC("%s: Capability not supported", __func__);
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c
@@ -340,7 +340,8 @@
 	audio_regs(2),
 	audio_regs(3),
 	audio_regs(4),
-	audio_regs(5)
+	audio_regs(5),
+	audio_regs(6),
 };
 
 #define DCE120_AUD_COMMON_MASK_SH_LIST(mask_sh)\
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c
@@ -380,6 +380,11 @@
 				i += increment) {
 			if (j == hw_points - 1)
 				break;
+			if (i >= TRANSFER_FUNC_POINTS) {
+				DC_LOG_ERROR("Index out of bounds: i=%d, TRANSFER_FUNC_POINTS=%d\n",
+					     i, TRANSFER_FUNC_POINTS);
+				return false;
+			}
 			rgb_resulted[j].red = output_tf->tf_pts.red[i];
 			rgb_resulted[j].green = output_tf->tf_pts.green[i];
 			rgb_resulted[j].blue = output_tf->tf_pts.blue[i];
@@ -546,6 +551,8 @@
 				i += increment) {
 			if (j == hw_points - 1)
 				break;
+			if (i >= TRANSFER_FUNC_POINTS)
+				return false;
 			rgb_resulted[j].red = output_tf->tf_pts.red[i];
 			rgb_resulted[j].green = output_tf->tf_pts.green[i];
 			rgb_resulted[j].blue = output_tf->tf_pts.blue[i];
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c
@@ -484,10 +484,13 @@
 	int vtaps_c = scl_data->taps.v_taps_c;
 	int ceil_vratio = dc_fixpt_ceil(scl_data->ratios.vert);
 	int ceil_vratio_c = dc_fixpt_ceil(scl_data->ratios.vert_c);
-	enum lb_memory_config mem_cfg = LB_MEMORY_CONFIG_0;
 
-	if (dpp->base.ctx->dc->debug.use_max_lb)
-		return mem_cfg;
+	if (dpp->base.ctx->dc->debug.use_max_lb) {
+		if (scl_data->format == PIXEL_FORMAT_420BPP8
+				|| scl_data->format == PIXEL_FORMAT_420BPP10)
+			return LB_MEMORY_CONFIG_3;
+		return LB_MEMORY_CONFIG_0;
+	}
 
 	dpp->base.caps->dscl_calc_lb_num_partitions(
 			scl_data, LB_MEMORY_CONFIG_1, &num_part_y, &num_part_c);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c
@@ -840,8 +840,8 @@
 
 	hubbub1_get_blk256_size(&blk256_width, &blk256_height, bpe);
 
-	swath_bytes_horz_wc = height * blk256_height * bpe;
-	swath_bytes_vert_wc = width * blk256_width * bpe;
+	swath_bytes_horz_wc = width * blk256_height * bpe;
+	swath_bytes_vert_wc = height * blk256_width * bpe;
 
 	*req128_horz_wc = (2 * swath_bytes_horz_wc <= detile_buf_size) ?
 			false : /* full 256B request */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
@@ -1470,6 +1470,9 @@
 {
 	struct dpp *dpp = pipe_ctx->plane_res.dpp;
 
+	if (!stream)
+		return false;
+
 	if (dpp == NULL)
 		return false;
 
@@ -1492,8 +1495,8 @@
 	} else
 		dpp->funcs->dpp_program_regamma_pwl(dpp, NULL, OPP_REGAMMA_BYPASS);
 
-	if (stream != NULL && stream->ctx != NULL &&
-			stream->out_transfer_func != NULL) {
+	if (stream->ctx &&
+	    stream->out_transfer_func) {
 		log_tf(stream->ctx,
 				stream->out_transfer_func,
 				dpp->regamma_params.hw_points_num);
@@ -2202,14 +2205,18 @@
 				&blnd_cfg.black_color);
 	}
 
-	if (per_pixel_alpha)
-		blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA;
-	else
-		blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA;
-
 	blnd_cfg.overlap_only = false;
 	blnd_cfg.global_gain = 0xff;
 
+	if (per_pixel_alpha && pipe_ctx->plane_state->global_alpha) {
+		blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA_COMBINED_GLOBAL_GAIN;
+		blnd_cfg.global_gain = pipe_ctx->plane_state->global_alpha_value;
+	} else if (per_pixel_alpha) {
+		blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA;
+	} else {
+		blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA;
+	}
+
 	if (pipe_ctx->plane_state->global_alpha)
 		blnd_cfg.global_alpha = pipe_ctx->plane_state->global_alpha_value;
 	else
@@ -2898,7 +2905,9 @@
 		if (pipe_ctx->stream_res.opp->mpcc_disconnect_pending[mpcc_inst]) {
 			struct hubp *hubp = get_hubp_by_inst(res_pool, mpcc_inst);
 
-			res_pool->mpc->funcs->wait_for_idle(res_pool->mpc, mpcc_inst);
+			if (pipe_ctx->stream_res.tg &&
+				pipe_ctx->stream_res.tg->funcs->is_tg_enabled(pipe_ctx->stream_res.tg))
+				res_pool->mpc->funcs->wait_for_idle(res_pool->mpc, mpcc_inst);
 			pipe_ctx->stream_res.opp->mpcc_disconnect_pending[mpcc_inst] = false;
 			hubp->funcs->set_blank(hubp, true);
 		}
@@ -3264,13 +3273,12 @@
 	struct dc_clock_config clock_cfg = {0};
 	struct dc_clocks *current_clocks = &context->bw_ctx.bw.dcn.clk;
 
-	if (dc->clk_mgr && dc->clk_mgr->funcs->get_clock)
-				dc->clk_mgr->funcs->get_clock(dc->clk_mgr,
-						context, clock_type, &clock_cfg);
-
-	if (!dc->clk_mgr->funcs->get_clock)
+	if (!dc->clk_mgr || !dc->clk_mgr->funcs->get_clock)
 		return DC_FAIL_UNSUPPORTED_1;
 
+	dc->clk_mgr->funcs->get_clock(dc->clk_mgr,
+		context, clock_type, &clock_cfg);
+
 	if (clk_khz > clock_cfg.max_clock_khz)
 		return DC_FAIL_CLK_EXCEED_MAX;
 
@@ -3288,7 +3296,7 @@
 	else
 		return DC_ERROR_UNEXPECTED;
 
-	if (dc->clk_mgr && dc->clk_mgr->funcs->update_clocks)
+	if (dc->clk_mgr->funcs->update_clocks)
 				dc->clk_mgr->funcs->update_clocks(dc->clk_mgr,
 				context, true);
 	return DC_OK;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c
@@ -118,6 +118,12 @@
 	while (tmp_mpcc != NULL) {
 		if (tmp_mpcc->dpp_id == dpp_id)
 			return tmp_mpcc;
+
+		/* avoid circular linked list */
+		ASSERT(tmp_mpcc != tmp_mpcc->mpcc_bot);
+		if (tmp_mpcc == tmp_mpcc->mpcc_bot)
+			break;
+
 		tmp_mpcc = tmp_mpcc->mpcc_bot;
 	}
 	return NULL;
@@ -193,8 +199,9 @@
 		/* check insert_above_mpcc exist in tree->opp_list */
 		struct mpcc *temp_mpcc = tree->opp_list;
 
-		while (temp_mpcc && temp_mpcc->mpcc_bot != insert_above_mpcc)
-			temp_mpcc = temp_mpcc->mpcc_bot;
+		if (temp_mpcc != insert_above_mpcc)
+			while (temp_mpcc && temp_mpcc->mpcc_bot != insert_above_mpcc)
+				temp_mpcc = temp_mpcc->mpcc_bot;
 		if (temp_mpcc == NULL)
 			return NULL;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c
@@ -425,6 +425,11 @@
 				OTG_CLOCK_ON, 1,
 				1, 1000);
 	} else  {
+
+		//last chance to clear underflow, otherwise, it will always there due to clock is off.
+		if (optc->funcs->is_optc_underflow_occurred(optc) == true)
+			optc->funcs->clear_optc_underflow(optc);
+
 		REG_UPDATE_2(OTG_CLOCK_CONTROL,
 				OTG_CLOCK_GATE_DIS, 0,
 				OTG_CLOCK_EN, 0);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
@@ -1151,6 +1151,7 @@
 	bool video_large = false;
 	bool desktop_large = false;
 	bool dcc_disabled = false;
+	bool mpo_enabled = false;
 
 	for (i = 0; i < context->stream_count; i++) {
 		if (context->stream_status[i].plane_count == 0)
@@ -1159,6 +1160,9 @@
 		if (context->stream_status[i].plane_count > 2)
 			return DC_FAIL_UNSUPPORTED_1;
 
+		if (context->stream_status[i].plane_count > 1)
+			mpo_enabled = true;
+
 		for (j = 0; j < context->stream_status[i].plane_count; j++) {
 			struct dc_plane_state *plane =
 				context->stream_status[i].plane_states[j];
@@ -1182,6 +1186,10 @@
 		}
 	}
 
+	/* Disable MPO in multi-display configurations. */
+	if (context->stream_count > 1 && mpo_enabled)
+		return DC_FAIL_UNSUPPORTED_1;
+
 	/*
 	 * Workaround: On DCN10 there is UMC issue that causes underflow when
 	 * playing 4k video on 4k desktop with video downscaled and single channel
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c
@@ -121,35 +121,35 @@
 	switch (packet_index) {
 	case 0:
 		REG_UPDATE(AFMT_VBI_PACKET_CONTROL1,
-				AFMT_GENERIC0_FRAME_UPDATE, 1);
+				AFMT_GENERIC0_IMMEDIATE_UPDATE, 1);
 		break;
 	case 1:
 		REG_UPDATE(AFMT_VBI_PACKET_CONTROL1,
-				AFMT_GENERIC1_FRAME_UPDATE, 1);
+				AFMT_GENERIC1_IMMEDIATE_UPDATE, 1);
 		break;
 	case 2:
 		REG_UPDATE(AFMT_VBI_PACKET_CONTROL1,
-				AFMT_GENERIC2_FRAME_UPDATE, 1);
+				AFMT_GENERIC2_IMMEDIATE_UPDATE, 1);
 		break;
 	case 3:
 		REG_UPDATE(AFMT_VBI_PACKET_CONTROL1,
-				AFMT_GENERIC3_FRAME_UPDATE, 1);
+				AFMT_GENERIC3_IMMEDIATE_UPDATE, 1);
 		break;
 	case 4:
 		REG_UPDATE(AFMT_VBI_PACKET_CONTROL1,
-				AFMT_GENERIC4_FRAME_UPDATE, 1);
+				AFMT_GENERIC4_IMMEDIATE_UPDATE, 1);
 		break;
 	case 5:
 		REG_UPDATE(AFMT_VBI_PACKET_CONTROL1,
-				AFMT_GENERIC5_FRAME_UPDATE, 1);
+				AFMT_GENERIC5_IMMEDIATE_UPDATE, 1);
 		break;
 	case 6:
 		REG_UPDATE(AFMT_VBI_PACKET_CONTROL1,
-				AFMT_GENERIC6_FRAME_UPDATE, 1);
+				AFMT_GENERIC6_IMMEDIATE_UPDATE, 1);
 		break;
 	case 7:
 		REG_UPDATE(AFMT_VBI_PACKET_CONTROL1,
-				AFMT_GENERIC7_FRAME_UPDATE, 1);
+				AFMT_GENERIC7_IMMEDIATE_UPDATE, 1);
 		break;
 	default:
 		break;
@@ -635,6 +635,12 @@
 				x),
 			26));
 
+	// If y rounds up to integer, carry it over to x.
+	if (y >> 26) {
+		x += 1;
+		y = 0;
+	}
+
 	REG_SET_2(DP_MSE_RATE_CNTL, 0,
 		DP_MSE_RATE_X, x,
 		DP_MSE_RATE_Y, y);
@@ -898,10 +904,10 @@
 	 */
 	REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_DIS_DEFER, 2);
 	/* Larger delay to wait until VBLANK - use max retry of
-	 * 10us*5000=50ms. This covers 41.7ms of minimum 24 Hz mode +
+	 * 10us*10200=102ms. This covers 100.0ms of minimum 10 Hz mode +
 	 * a little more because we may not trust delay accuracy.
 	 */
-	max_retries = DP_BLANK_MAX_RETRY * 250;
+	max_retries = DP_BLANK_MAX_RETRY * 501;
 
 	/* disable DP stream */
 	REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, 0);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h
@@ -275,7 +275,14 @@
 	SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC2_FRAME_UPDATE, mask_sh),\
 	SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC3_FRAME_UPDATE, mask_sh),\
 	SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_FRAME_UPDATE, mask_sh),\
+	SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC0_IMMEDIATE_UPDATE, mask_sh),\
+	SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC1_IMMEDIATE_UPDATE, mask_sh),\
+	SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC2_IMMEDIATE_UPDATE, mask_sh),\
+	SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC3_IMMEDIATE_UPDATE, mask_sh),\
 	SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_IMMEDIATE_UPDATE, mask_sh),\
+	SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC5_IMMEDIATE_UPDATE, mask_sh),\
+	SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC6_IMMEDIATE_UPDATE, mask_sh),\
+	SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC7_IMMEDIATE_UPDATE, mask_sh),\
 	SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC5_FRAME_UPDATE, mask_sh),\
 	SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC6_FRAME_UPDATE, mask_sh),\
 	SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC7_FRAME_UPDATE, mask_sh),\
@@ -339,7 +346,14 @@
 	type AFMT_GENERIC2_FRAME_UPDATE;\
 	type AFMT_GENERIC3_FRAME_UPDATE;\
 	type AFMT_GENERIC4_FRAME_UPDATE;\
+	type AFMT_GENERIC0_IMMEDIATE_UPDATE;\
+	type AFMT_GENERIC1_IMMEDIATE_UPDATE;\
+	type AFMT_GENERIC2_IMMEDIATE_UPDATE;\
+	type AFMT_GENERIC3_IMMEDIATE_UPDATE;\
 	type AFMT_GENERIC4_IMMEDIATE_UPDATE;\
+	type AFMT_GENERIC5_IMMEDIATE_UPDATE;\
+	type AFMT_GENERIC6_IMMEDIATE_UPDATE;\
+	type AFMT_GENERIC7_IMMEDIATE_UPDATE;\
 	type AFMT_GENERIC5_FRAME_UPDATE;\
 	type AFMT_GENERIC6_FRAME_UPDATE;\
 	type AFMT_GENERIC7_FRAME_UPDATE;\
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.c
@@ -119,32 +119,6 @@
 
 void dccg2_init(struct dccg *dccg)
 {
-	struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
-
-	// Fallthrough intentional to program all available dpp_dto's
-	switch (dccg_dcn->base.ctx->dc->res_pool->pipe_count) {
-	case 6:
-		REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_DB_EN[5], 1);
-		/* Fall through */
-	case 5:
-		REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_DB_EN[4], 1);
-		/* Fall through */
-	case 4:
-		REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_DB_EN[3], 1);
-		/* Fall through */
-	case 3:
-		REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_DB_EN[2], 1);
-		/* Fall through */
-	case 2:
-		REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_DB_EN[1], 1);
-		/* Fall through */
-	case 1:
-		REG_UPDATE(DPPCLK_DTO_CTRL, DPPCLK_DTO_DB_EN[0], 1);
-		break;
-	default:
-		ASSERT(false);
-		break;
-	}
 }
 
 static const struct dccg_funcs dccg2_funcs = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c
@@ -207,6 +207,9 @@
 	struct dsc_reg_values dsc_reg_vals;
 	struct dsc_optc_config dsc_optc_cfg;
 
+	memset(&dsc_reg_vals, 0, sizeof(dsc_reg_vals));
+	memset(&dsc_optc_cfg, 0, sizeof(dsc_optc_cfg));
+
 	DC_LOG_DSC("Getting packed DSC PPS for DSC Config:");
 	dsc_config_log(dsc, dsc_cfg);
 	DC_LOG_DSC("DSC Picture Parameter Set (PPS):");
@@ -348,6 +351,7 @@
 	dsc_reg_vals->pps.block_pred_enable = dsc_cfg->dc_dsc_cfg.block_pred_enable;
 	dsc_reg_vals->pps.line_buf_depth = dsc_cfg->dc_dsc_cfg.linebuf_depth;
 	dsc_reg_vals->alternate_ich_encoding_en = dsc_reg_vals->pps.dsc_version_minor == 1 ? 0 : 1;
+	dsc_reg_vals->ich_reset_at_eol = (dsc_cfg->is_odm || dsc_reg_vals->num_slices_h > 1) ? 0xF : 0;
 
 	// TODO: in addition to validating slice height (pic height must be divisible by slice height),
 	// see what happens when the same condition doesn't apply for slice_width/pic_width.
@@ -510,7 +514,6 @@
 		reg_vals->pps.rc_buf_thresh[i] = reg_vals->pps.rc_buf_thresh[i] >> 6;
 
 	reg_vals->rc_buffer_model_size = dsc_params->rc_buffer_model_size;
-	reg_vals->ich_reset_at_eol = reg_vals->num_slices_h == 1 ? 0 : 0xf;
 }
 
 static void dsc_write_to_registers(struct display_stream_compressor *dsc, const struct dsc_reg_values *reg_vals)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dwb_scl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dwb_scl.c
@@ -690,6 +690,9 @@
 	int pair;
 	uint16_t odd_coef, even_coef;
 
+	if (!filter)
+		return;
+
 	for (phase = 0; phase < (NUM_PHASES / 2 + 1); phase++) {
 		for (pair = 0; pair < tap_pairs; pair++) {
 			even_coef = filter[phase * taps + 2 * pair];
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2012-17 Advanced Micro Devices, Inc.
+ * Copyright 2012-2021 Advanced Micro Devices, Inc.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -179,11 +179,14 @@
 	else
 		Set HUBP_VREADY_AT_OR_AFTER_VSYNC = 0
 	*/
-	if ((pipe_dest->vstartup_start - (pipe_dest->vready_offset+pipe_dest->vupdate_width
-		+ pipe_dest->vupdate_offset) / pipe_dest->htotal) <= pipe_dest->vblank_end) {
-		value = 1;
-	} else
-		value = 0;
+	if (pipe_dest->htotal != 0) {
+		if ((pipe_dest->vstartup_start - (pipe_dest->vready_offset+pipe_dest->vupdate_width
+			+ pipe_dest->vupdate_offset) / pipe_dest->htotal) <= pipe_dest->vblank_end) {
+			value = 1;
+		} else
+			value = 0;
+	}
+
 	REG_UPDATE(DCHUBP_CNTL, HUBP_VREADY_AT_OR_AFTER_VSYNC, value);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
@@ -126,7 +126,7 @@
 	REG_WRITE(MILLISECOND_TIME_BASE_DIV, 0x1186a0);
 
 	/* This value is dependent on the hardware pipeline delay so set once per SOC */
-	REG_WRITE(DISPCLK_FREQ_CHANGE_CNTL, 0x801003c);
+	REG_WRITE(DISPCLK_FREQ_CHANGE_CNTL, 0xe01003c);
 }
 void dcn20_display_init(struct dc *dc)
 {
@@ -493,7 +493,6 @@
 	dpp->funcs->dpp_dppclk_control(dpp, false, false);
 
 	hubp->power_gated = true;
-	dc->optimized_required = false; /* We're powering off, no need to optimize */
 
 	dc->hwss.plane_atomic_power_down(dc,
 			pipe_ctx->plane_res.dpp,
@@ -1103,6 +1102,25 @@
 	if (pipe->plane_state != NULL)
 		flip_immediate = pipe->plane_state->flip_immediate;
 
+	if (flip_immediate && lock) {
+		const int TIMEOUT_FOR_FLIP_PENDING = 100000;
+		int i;
+
+		for (i = 0; i < TIMEOUT_FOR_FLIP_PENDING; ++i) {
+			if (!pipe->plane_res.hubp->funcs->hubp_is_flip_pending(pipe->plane_res.hubp))
+				break;
+			udelay(1);
+		}
+
+		if (pipe->bottom_pipe != NULL) {
+			for (i = 0; i < TIMEOUT_FOR_FLIP_PENDING; ++i) {
+				if (!pipe->bottom_pipe->plane_res.hubp->funcs->hubp_is_flip_pending(pipe->bottom_pipe->plane_res.hubp))
+					break;
+				udelay(1);
+			}
+		}
+	}
+
 	/* In flip immediate and pipe splitting case, we need to use GSL
 	 * for synchronization. Only do setup on locking and on flip type change.
 	 */
@@ -1337,7 +1355,8 @@
 static void dcn20_enable_writeback(
 		struct dc *dc,
 		const struct dc_stream_status *stream_status,
-		struct dc_writeback_info *wb_info)
+		struct dc_writeback_info *wb_info,
+		struct dc_state *context)
 {
 	struct dwbc *dwb;
 	struct mcif_wb *mcif_wb;
@@ -1354,7 +1373,7 @@
 	optc->funcs->set_dwb_source(optc, wb_info->dwb_pipe_inst);
 	/* set MCIF_WB buffer and arbitration configuration */
 	mcif_wb->funcs->config_mcif_buf(mcif_wb, &wb_info->mcif_buf_params, wb_info->dwb_params.dest_height);
-	mcif_wb->funcs->config_mcif_arb(mcif_wb, &dc->current_state->bw_ctx.bw.dcn.bw_writeback.mcif_wb_arb[wb_info->dwb_pipe_inst]);
+	mcif_wb->funcs->config_mcif_arb(mcif_wb, &context->bw_ctx.bw.dcn.bw_writeback.mcif_wb_arb[wb_info->dwb_pipe_inst]);
 	/* Enable MCIF_WB */
 	mcif_wb->funcs->enable_mcif(mcif_wb);
 	/* Enable DWB */
@@ -1721,14 +1740,18 @@
 				pipe_ctx, &blnd_cfg.black_color);
 	}
 
-	if (per_pixel_alpha)
-		blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA;
-	else
-		blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA;
-
 	blnd_cfg.overlap_only = false;
 	blnd_cfg.global_gain = 0xff;
 
+	if (per_pixel_alpha && pipe_ctx->plane_state->global_alpha) {
+		blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA_COMBINED_GLOBAL_GAIN;
+		blnd_cfg.global_gain = pipe_ctx->plane_state->global_alpha_value;
+	} else if (per_pixel_alpha) {
+		blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA;
+	} else {
+		blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA;
+	}
+
 	if (pipe_ctx->plane_state->global_alpha)
 		blnd_cfg.global_alpha = pipe_ctx->plane_state->global_alpha_value;
 	else
@@ -1996,7 +2019,8 @@
 
 	REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, 2);
 	REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1);
-	REG_WRITE(REFCLK_CNTL, 0);
+	if (REG(REFCLK_CNTL))
+		REG_WRITE(REFCLK_CNTL, 0);
 	//
 
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.c
@@ -488,6 +488,12 @@
 	while (tmp_mpcc != NULL) {
 		if (tmp_mpcc->dpp_id == 0xf || tmp_mpcc->dpp_id == dpp_id)
 			return tmp_mpcc;
+
+		/* avoid circular linked list */
+		ASSERT(tmp_mpcc != tmp_mpcc->mpcc_bot);
+		if (tmp_mpcc == tmp_mpcc->mpcc_bot)
+			break;
+
 		tmp_mpcc = tmp_mpcc->mpcc_bot;
 	}
 	return NULL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
@@ -233,12 +233,13 @@
 		struct dc_crtc_timing *timing)
 {
 	struct optc *optc1 = DCN10TG_FROM_TG(optc);
-	/* 2 pieces of memory required for up to 5120 displays, 4 for up to 8192 */
 	int mpcc_hactive = (timing->h_addressable + timing->h_border_left + timing->h_border_right)
 			/ opp_cnt;
-	int memory_mask = mpcc_hactive <= 2560 ? 0x3 : 0xf;
+	uint32_t memory_mask;
 	uint32_t data_fmt = 0;
 
+	ASSERT(opp_cnt == 2);
+
 	/* TODO: In pseudocode but does not affect maximus, delete comment if we dont need on asic
 	 * REG_SET(OTG_GLOBAL_CONTROL2, 0, GLOBAL_UPDATE_LOCK_EN, 1);
 	 * Program OTG register MASTER_UPDATE_LOCK_DB_X/Y to the position before DP frame start
@@ -246,9 +247,17 @@
 	 *		MASTER_UPDATE_LOCK_DB_X, 160,
 	 *		MASTER_UPDATE_LOCK_DB_Y, 240);
 	 */
+
+	/* 2 pieces of memory required for up to 5120 displays, 4 for up to 8192,
+	 * however, for ODM combine we can simplify by always using 4.
+	 * To make sure there's no overlap, each instance "reserves" 2 memories and
+	 * they are uniquely combined here.
+	 */
+	memory_mask = 0x3 << (opp_id[0] * 2) | 0x3 << (opp_id[1] * 2);
+
 	if (REG(OPTC_MEMORY_CONFIG))
 		REG_SET(OPTC_MEMORY_CONFIG, 0,
-			OPTC_MEM_SEL, memory_mask << (optc->inst * 4));
+			OPTC_MEM_SEL, memory_mask);
 
 	if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422)
 		data_fmt = 1;
@@ -257,7 +266,6 @@
 
 	REG_UPDATE(OPTC_DATA_FORMAT_CONTROL, OPTC_DATA_FORMAT, data_fmt);
 
-	ASSERT(opp_cnt == 2);
 	REG_SET_3(OPTC_DATA_SOURCE_SELECT, 0,
 			OPTC_NUM_OF_INPUT_SEGMENT, 1,
 			OPTC_SEG0_SRC_SEL, opp_id[0],
@@ -287,6 +295,10 @@
 		*num_of_src_opp = 2;
 	else
 		*num_of_src_opp = 1;
+
+	/* Work around VBIOS not updating OPTC_NUM_OF_INPUT_SEGMENT */
+	if (*src_opp_id_1 == 0xf)
+		*num_of_src_opp = 1;
 }
 
 void optc2_set_dwb_source(struct timing_generator *optc,
@@ -350,7 +362,7 @@
 
 	REG_UPDATE_2(OTG_GLOBAL_CONTROL1,
 			MASTER_UPDATE_LOCK_DB_X,
-			h_blank_start - 200 - 1,
+			(h_blank_start - 200 - 1) / optc1->opp_count,
 			MASTER_UPDATE_LOCK_DB_Y,
 			v_blank_start - 1);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
@@ -269,6 +269,117 @@
 	.use_urgent_burst_bw = 0
 };
 
+struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv14_soc = {
+	.clock_limits = {
+			{
+				.state = 0,
+				.dcfclk_mhz = 560.0,
+				.fabricclk_mhz = 560.0,
+				.dispclk_mhz = 513.0,
+				.dppclk_mhz = 513.0,
+				.phyclk_mhz = 540.0,
+				.socclk_mhz = 560.0,
+				.dscclk_mhz = 171.0,
+				.dram_speed_mts = 8960.0,
+			},
+			{
+				.state = 1,
+				.dcfclk_mhz = 694.0,
+				.fabricclk_mhz = 694.0,
+				.dispclk_mhz = 642.0,
+				.dppclk_mhz = 642.0,
+				.phyclk_mhz = 600.0,
+				.socclk_mhz = 694.0,
+				.dscclk_mhz = 214.0,
+				.dram_speed_mts = 11104.0,
+			},
+			{
+				.state = 2,
+				.dcfclk_mhz = 875.0,
+				.fabricclk_mhz = 875.0,
+				.dispclk_mhz = 734.0,
+				.dppclk_mhz = 734.0,
+				.phyclk_mhz = 810.0,
+				.socclk_mhz = 875.0,
+				.dscclk_mhz = 245.0,
+				.dram_speed_mts = 14000.0,
+			},
+			{
+				.state = 3,
+				.dcfclk_mhz = 1000.0,
+				.fabricclk_mhz = 1000.0,
+				.dispclk_mhz = 1100.0,
+				.dppclk_mhz = 1100.0,
+				.phyclk_mhz = 810.0,
+				.socclk_mhz = 1000.0,
+				.dscclk_mhz = 367.0,
+				.dram_speed_mts = 16000.0,
+			},
+			{
+				.state = 4,
+				.dcfclk_mhz = 1200.0,
+				.fabricclk_mhz = 1200.0,
+				.dispclk_mhz = 1284.0,
+				.dppclk_mhz = 1284.0,
+				.phyclk_mhz = 810.0,
+				.socclk_mhz = 1200.0,
+				.dscclk_mhz = 428.0,
+				.dram_speed_mts = 16000.0,
+			},
+			/*Extra state, no dispclk ramping*/
+			{
+				.state = 5,
+				.dcfclk_mhz = 1200.0,
+				.fabricclk_mhz = 1200.0,
+				.dispclk_mhz = 1284.0,
+				.dppclk_mhz = 1284.0,
+				.phyclk_mhz = 810.0,
+				.socclk_mhz = 1200.0,
+				.dscclk_mhz = 428.0,
+				.dram_speed_mts = 16000.0,
+			},
+		},
+	.num_states = 5,
+	.sr_exit_time_us = 11.6,
+	.sr_enter_plus_exit_time_us = 13.9,
+	.urgent_latency_us = 4.0,
+	.urgent_latency_pixel_data_only_us = 4.0,
+	.urgent_latency_pixel_mixed_with_vm_data_us = 4.0,
+	.urgent_latency_vm_data_only_us = 4.0,
+	.urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096,
+	.urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096,
+	.urgent_out_of_order_return_per_channel_vm_only_bytes = 4096,
+	.pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 40.0,
+	.pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 40.0,
+	.pct_ideal_dram_sdp_bw_after_urgent_vm_only = 40.0,
+	.max_avg_sdp_bw_use_normal_percent = 40.0,
+	.max_avg_dram_bw_use_normal_percent = 40.0,
+	.writeback_latency_us = 12.0,
+	.ideal_dram_bw_after_urgent_percent = 40.0,
+	.max_request_size_bytes = 256,
+	.dram_channel_width_bytes = 2,
+	.fabric_datapath_to_dcn_data_return_bytes = 64,
+	.dcn_downspread_percent = 0.5,
+	.downspread_percent = 0.38,
+	.dram_page_open_time_ns = 50.0,
+	.dram_rw_turnaround_time_ns = 17.5,
+	.dram_return_buffer_per_channel_bytes = 8192,
+	.round_trip_ping_latency_dcfclk_cycles = 131,
+	.urgent_out_of_order_return_per_channel_bytes = 256,
+	.channel_interleave_bytes = 256,
+	.num_banks = 8,
+	.num_chans = 8,
+	.vmm_page_size_bytes = 4096,
+	.dram_clock_change_latency_us = 404.0,
+	.dummy_pstate_latency_us = 5.0,
+	.writeback_dram_clock_change_latency_us = 23.0,
+	.return_bus_width_bytes = 64,
+	.dispclk_dppclk_vco_speed_mhz = 3850,
+	.xfc_bus_transport_time_us = 20,
+	.xfc_xbuf_latency_tolerance_us = 4,
+	.use_urgent_burst_bw = 0
+};
+
 struct _vcs_dpi_soc_bounding_box_st dcn2_0_nv12_soc = { 0 };
 
 #ifndef mmDP0_DP_DPHY_INTERNAL_CTRL
@@ -1419,13 +1530,20 @@
 
 static void acquire_dsc(struct resource_context *res_ctx,
 			const struct resource_pool *pool,
-			struct display_stream_compressor **dsc)
+			struct display_stream_compressor **dsc,
+			int pipe_idx)
 {
 	int i;
 
 	ASSERT(*dsc == NULL);
 	*dsc = NULL;
 
+	if (pool->res_cap->num_dsc == pool->res_cap->num_opp) {
+		*dsc = pool->dscs[pipe_idx];
+		res_ctx->is_dsc_acquired[pipe_idx] = true;
+		return;
+	}
+
 	/* Find first free DSC */
 	for (i = 0; i < pool->res_cap->num_dsc; i++)
 		if (!res_ctx->is_dsc_acquired[i]) {
@@ -1468,7 +1586,7 @@
 		if (pipe_ctx->stream != dc_stream)
 			continue;
 
-		acquire_dsc(&dc_ctx->res_ctx, pool, &pipe_ctx->stream_res.dsc);
+		acquire_dsc(&dc_ctx->res_ctx, pool, &pipe_ctx->stream_res.dsc, i);
 
 		/* The number of DSCs can be less than the number of pipes */
 		if (!pipe_ctx->stream_res.dsc) {
@@ -1669,7 +1787,7 @@
 	next_odm_pipe->stream_res.opp = pool->opps[next_odm_pipe->pipe_idx];
 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
 	if (next_odm_pipe->stream->timing.flags.DSC == 1) {
-		acquire_dsc(res_ctx, pool, &next_odm_pipe->stream_res.dsc);
+		acquire_dsc(res_ctx, pool, &next_odm_pipe->stream_res.dsc, next_odm_pipe->pipe_idx);
 		ASSERT(next_odm_pipe->stream_res.dsc);
 		if (next_odm_pipe->stream_res.dsc == NULL)
 			return false;
@@ -1765,7 +1883,7 @@
 			pipe_cnt = i;
 			continue;
 		}
-		if (!resource_are_streams_timing_synchronizable(
+		if (dc->debug.disable_timing_sync || !resource_are_streams_timing_synchronizable(
 				res_ctx->pipe_ctx[pipe_cnt].stream,
 				res_ctx->pipe_ctx[i].stream)) {
 			synchronized_vblank = false;
@@ -2114,7 +2232,7 @@
 				wb_arb_params->cli_watermark[k] = get_wm_writeback_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
 				wb_arb_params->pstate_watermark[k] = get_wm_writeback_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000;
 			}
-			wb_arb_params->time_per_pixel = 16.0 / context->res_ctx.pipe_ctx[i].stream->phy_pix_clk; /* 4 bit fraction, ms */
+			wb_arb_params->time_per_pixel = 16.0 * 1000 / (context->res_ctx.pipe_ctx[i].stream->phy_pix_clk / 1000); /* 4 bit fraction, ms */
 			wb_arb_params->slice_lines = 32;
 			wb_arb_params->arbitration_slice = 2;
 			wb_arb_params->max_scaled_time = dcn20_calc_max_scaled_time(wb_arb_params->time_per_pixel,
@@ -2157,6 +2275,7 @@
 				+ stream->timing.v_border_bottom;
 		dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
 		dsc_cfg.color_depth = stream->timing.display_color_depth;
+		dsc_cfg.is_odm = pipe_ctx->next_odm_pipe ? true : false;
 		dsc_cfg.dc_dsc_cfg = stream->timing.dsc_cfg;
 		dsc_cfg.dc_dsc_cfg.num_slices_h /= opp_cnt;
 
@@ -2474,6 +2593,7 @@
 							&context->res_ctx, dc->res_pool,
 							pipe, hsplit_pipe))
 						goto validate_fail;
+					dcn20_build_mapped_resource(dc, context, pipe->stream);
 				} else
 					dcn20_split_stream_for_mpc(
 						&context->res_ctx, dc->res_pool,
@@ -2726,7 +2846,7 @@
 	int vlevel = 0;
 	int pipe_split_from[MAX_PIPES];
 	int pipe_cnt = 0;
-	display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_KERNEL);
+	display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_ATOMIC);
 	DC_LOGGER_INIT(dc->ctx->logger);
 
 	BW_VAL_TRACE_COUNT();
@@ -2797,7 +2917,7 @@
 	voltage_supported = dcn20_validate_bandwidth_internal(dc, context, false);
 	dummy_pstate_supported = context->bw_ctx.bw.dcn.clk.p_state_change_support;
 
-	if (voltage_supported && dummy_pstate_supported) {
+	if (voltage_supported && (dummy_pstate_supported || !(context->stream_count))) {
 		context->bw_ctx.bw.dcn.clk.p_state_change_support = false;
 		goto restore_dml_state;
 	}
@@ -3040,7 +3160,7 @@
 static void update_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st *bb,
 		struct pp_smu_nv_clock_table *max_clocks, unsigned int *uclk_states, unsigned int num_states)
 {
-	struct _vcs_dpi_voltage_scaling_st calculated_states[MAX_CLOCK_LIMIT_STATES] = {0};
+	struct _vcs_dpi_voltage_scaling_st calculated_states[MAX_CLOCK_LIMIT_STATES];
 	int i;
 	int num_calculated_states = 0;
 	int min_dcfclk = 0;
@@ -3048,6 +3168,8 @@
 	if (num_states == 0)
 		return;
 
+	memset(calculated_states, 0, sizeof(calculated_states));
+
 	if (dc->bb_overrides.min_dcfclk_mhz > 0)
 		min_dcfclk = dc->bb_overrides.min_dcfclk_mhz;
 	else
@@ -3125,6 +3247,9 @@
 static struct _vcs_dpi_soc_bounding_box_st *get_asic_rev_soc_bb(
 	uint32_t hw_internal_rev)
 {
+	if (ASICREV_IS_NAVI14_M(hw_internal_rev))
+		return &dcn2_0_nv14_soc;
+
 	if (ASICREV_IS_NAVI12_P(hw_internal_rev))
 		return &dcn2_0_nv12_soc;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c
@@ -492,15 +492,23 @@
 				DP_VID_N_MUL, n_multiply);
 	}
 
-	/* set DIG_START to 0x1 to reset FIFO */
+	/* make sure stream is disabled before resetting steer fifo */
+	REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, false);
+	REG_WAIT(DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, 0, 10, 5000);
 
+	/* set DIG_START to 0x1 to reset FIFO */
 	REG_UPDATE(DIG_FE_CNTL, DIG_START, 1);
+	udelay(1);
 
 	/* write 0 to take the FIFO out of reset */
 
 	REG_UPDATE(DIG_FE_CNTL, DIG_START, 0);
 
-	/* switch DP encoder to CRTC data */
+	/* switch DP encoder to CRTC data, but reset it the fifo first. It may happen
+	 * that it overflows during mode transition, and sometimes doesn't recover.
+	 */
+	REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 1);
+	udelay(10);
 
 	REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 0);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubbub.c
@@ -22,6 +22,7 @@
  * Authors: AMD
  *
  */
+#include <linux/delay.h>
 #include "dm_services.h"
 #include "dcn20/dcn20_hubbub.h"
 #include "dcn21_hubbub.h"
@@ -71,30 +72,39 @@
 void dcn21_dchvm_init(struct hubbub *hubbub)
 {
 	struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
+	uint32_t riommu_active;
+	int i;
 
 	//Init DCHVM block
 	REG_UPDATE(DCHVM_CTRL0, HOSTVM_INIT_REQ, 1);
 
 	//Poll until RIOMMU_ACTIVE = 1
-	//TODO: Figure out interval us and retry count
-	REG_WAIT(DCHVM_RIOMMU_STAT0, RIOMMU_ACTIVE, 1, 5, 100);
+	for (i = 0; i < 100; i++) {
+		REG_GET(DCHVM_RIOMMU_STAT0, RIOMMU_ACTIVE, &riommu_active);
 
-	//Reflect the power status of DCHUBBUB
-	REG_UPDATE(DCHVM_RIOMMU_CTRL0, HOSTVM_POWERSTATUS, 1);
-
-	//Start rIOMMU prefetching
-	REG_UPDATE(DCHVM_RIOMMU_CTRL0, HOSTVM_PREFETCH_REQ, 1);
-
-	// Enable dynamic clock gating
-	REG_UPDATE_4(DCHVM_CLK_CTRL,
-					HVM_DISPCLK_R_GATE_DIS, 0,
-					HVM_DISPCLK_G_GATE_DIS, 0,
-					HVM_DCFCLK_R_GATE_DIS, 0,
-					HVM_DCFCLK_G_GATE_DIS, 0);
-
-	//Poll until HOSTVM_PREFETCH_DONE = 1
-	//TODO: Figure out interval us and retry count
-	REG_WAIT(DCHVM_RIOMMU_STAT0, HOSTVM_PREFETCH_DONE, 1, 5, 100);
+		if (riommu_active)
+			break;
+		else
+			udelay(5);
+	}
+
+	if (riommu_active) {
+		//Reflect the power status of DCHUBBUB
+		REG_UPDATE(DCHVM_RIOMMU_CTRL0, HOSTVM_POWERSTATUS, 1);
+
+		//Start rIOMMU prefetching
+		REG_UPDATE(DCHVM_RIOMMU_CTRL0, HOSTVM_PREFETCH_REQ, 1);
+
+		// Enable dynamic clock gating
+		REG_UPDATE_4(DCHVM_CLK_CTRL,
+						HVM_DISPCLK_R_GATE_DIS, 0,
+						HVM_DISPCLK_G_GATE_DIS, 0,
+						HVM_DCFCLK_R_GATE_DIS, 0,
+						HVM_DCFCLK_G_GATE_DIS, 0);
+
+		//Poll until HOSTVM_PREFETCH_DONE = 1
+		REG_WAIT(DCHVM_RIOMMU_STAT0, HOSTVM_PREFETCH_DONE, 1, 5, 100);
+	}
 }
 
 static int hubbub21_init_dchub(struct hubbub *hubbub,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c
@@ -73,32 +73,47 @@
 		struct _vcs_dpi_display_dlg_regs_st *dlg_attr)
 {
 	struct dcn21_hubp *hubp21 = TO_DCN21_HUBP(hubp);
-	uint32_t cur_value;
+	uint32_t refcyc_per_vm_group_vblank;
+	uint32_t refcyc_per_vm_req_vblank;
+	uint32_t refcyc_per_vm_group_flip;
+	uint32_t refcyc_per_vm_req_flip;
+	const uint32_t uninitialized_hw_default = 0;
 
-	REG_GET(VBLANK_PARAMETERS_5, REFCYC_PER_VM_GROUP_VBLANK, &cur_value);
-	if (cur_value > dlg_attr->refcyc_per_vm_group_vblank)
+	REG_GET(VBLANK_PARAMETERS_5,
+			REFCYC_PER_VM_GROUP_VBLANK, &refcyc_per_vm_group_vblank);
+
+	if (refcyc_per_vm_group_vblank == uninitialized_hw_default ||
+			refcyc_per_vm_group_vblank > dlg_attr->refcyc_per_vm_group_vblank)
 		REG_SET(VBLANK_PARAMETERS_5, 0,
 				REFCYC_PER_VM_GROUP_VBLANK, dlg_attr->refcyc_per_vm_group_vblank);
 
 	REG_GET(VBLANK_PARAMETERS_6,
-			REFCYC_PER_VM_REQ_VBLANK,
-			&cur_value);
-	if (cur_value > dlg_attr->refcyc_per_vm_req_vblank)
+			REFCYC_PER_VM_REQ_VBLANK, &refcyc_per_vm_req_vblank);
+
+	if (refcyc_per_vm_req_vblank == uninitialized_hw_default ||
+			refcyc_per_vm_req_vblank > dlg_attr->refcyc_per_vm_req_vblank)
 		REG_SET(VBLANK_PARAMETERS_6, 0,
 				REFCYC_PER_VM_REQ_VBLANK, dlg_attr->refcyc_per_vm_req_vblank);
 
-	REG_GET(FLIP_PARAMETERS_3, REFCYC_PER_VM_GROUP_FLIP, &cur_value);
-	if (cur_value > dlg_attr->refcyc_per_vm_group_flip)
+	REG_GET(FLIP_PARAMETERS_3,
+			REFCYC_PER_VM_GROUP_FLIP, &refcyc_per_vm_group_flip);
+
+	if (refcyc_per_vm_group_flip == uninitialized_hw_default ||
+			refcyc_per_vm_group_flip > dlg_attr->refcyc_per_vm_group_flip)
 		REG_SET(FLIP_PARAMETERS_3, 0,
 				REFCYC_PER_VM_GROUP_FLIP, dlg_attr->refcyc_per_vm_group_flip);
 
-	REG_GET(FLIP_PARAMETERS_4, REFCYC_PER_VM_REQ_FLIP, &cur_value);
-	if (cur_value > dlg_attr->refcyc_per_vm_req_flip)
+	REG_GET(FLIP_PARAMETERS_4,
+			REFCYC_PER_VM_REQ_FLIP, &refcyc_per_vm_req_flip);
+
+	if (refcyc_per_vm_req_flip == uninitialized_hw_default ||
+			refcyc_per_vm_req_flip > dlg_attr->refcyc_per_vm_req_flip)
 		REG_SET(FLIP_PARAMETERS_4, 0,
 					REFCYC_PER_VM_REQ_FLIP, dlg_attr->refcyc_per_vm_req_flip);
 
 	REG_SET(FLIP_PARAMETERS_5, 0,
 			REFCYC_PER_PTE_GROUP_FLIP_C, dlg_attr->refcyc_per_pte_group_flip_c);
+
 	REG_SET(FLIP_PARAMETERS_6, 0,
 			REFCYC_PER_META_CHUNK_FLIP_C, dlg_attr->refcyc_per_meta_chunk_flip_c);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
@@ -57,6 +57,7 @@
 #include "dcn20/dcn20_dccg.h"
 #include "dcn21_hubbub.h"
 #include "dcn10/dcn10_resource.h"
+#include "dce110/dce110_resource.h"
 
 #include "dcn20/dcn20_dwb.h"
 #include "dcn20/dcn20_mmhubbub.h"
@@ -246,7 +247,7 @@
 	.dram_channel_width_bytes = 4,
 	.fabric_datapath_to_dcn_data_return_bytes = 32,
 	.dcn_downspread_percent = 0.5,
-	.downspread_percent = 0.5,
+	.downspread_percent = 0.38,
 	.dram_page_open_time_ns = 50.0,
 	.dram_rw_turnaround_time_ns = 17.5,
 	.dram_return_buffer_per_channel_bytes = 8192,
@@ -258,7 +259,7 @@
 	.vmm_page_size_bytes = 4096,
 	.dram_clock_change_latency_us = 23.84,
 	.return_bus_width_bytes = 64,
-	.dispclk_dppclk_vco_speed_mhz = 3550,
+	.dispclk_dppclk_vco_speed_mhz = 3600,
 	.xfc_bus_transport_time_us = 4,
 	.xfc_xbuf_latency_tolerance_us = 4,
 	.use_urgent_burst_bw = 1,
@@ -824,6 +825,9 @@
 enum dcn20_clk_src_array_id {
 	DCN20_CLK_SRC_PLL0,
 	DCN20_CLK_SRC_PLL1,
+	DCN20_CLK_SRC_PLL2,
+	DCN20_CLK_SRC_PLL3,
+	DCN20_CLK_SRC_PLL4,
 	DCN20_CLK_SRC_TOTAL_DCN21
 };
 
@@ -1136,6 +1140,7 @@
 		return &clk_src->base;
 	}
 
+	kfree(clk_src);
 	BREAK_TO_DEBUGGER();
 	return NULL;
 }
@@ -1492,6 +1497,18 @@
 			dcn21_clock_source_create(ctx, ctx->dc_bios,
 				CLOCK_SOURCE_COMBO_PHY_PLL1,
 				&clk_src_regs[1], false);
+	pool->base.clock_sources[DCN20_CLK_SRC_PLL2] =
+			dcn21_clock_source_create(ctx, ctx->dc_bios,
+				CLOCK_SOURCE_COMBO_PHY_PLL2,
+				&clk_src_regs[2], false);
+	pool->base.clock_sources[DCN20_CLK_SRC_PLL3] =
+			dcn21_clock_source_create(ctx, ctx->dc_bios,
+				CLOCK_SOURCE_COMBO_PHY_PLL3,
+				&clk_src_regs[3], false);
+	pool->base.clock_sources[DCN20_CLK_SRC_PLL4] =
+			dcn21_clock_source_create(ctx, ctx->dc_bios,
+				CLOCK_SOURCE_COMBO_PHY_PLL4,
+				&clk_src_regs[4], false);
 
 	pool->base.clk_src_count = DCN20_CLK_SRC_TOTAL_DCN21;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c
@@ -3435,6 +3435,7 @@
 			mode_lib->vba.DCCEnabledInAnyPlane = true;
 		}
 	}
+	mode_lib->vba.UrgentLatency = mode_lib->vba.UrgentLatencyPixelDataOnly;
 	for (i = 0; i <= mode_lib->vba.soc.num_states; i++) {
 		locals->FabricAndDRAMBandwidthPerState[i] = dml_min(
 				mode_lib->vba.DRAMSpeedPerState[i] * mode_lib->vba.NumberOfChannels
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c
@@ -3467,6 +3467,7 @@
 			mode_lib->vba.DCCEnabledInAnyPlane = true;
 		}
 	}
+	mode_lib->vba.UrgentLatency = mode_lib->vba.UrgentLatencyPixelDataOnly;
 	for (i = 0; i <= mode_lib->vba.soc.num_states; i++) {
 		locals->FabricAndDRAMBandwidthPerState[i] = dml_min(
 				mode_lib->vba.DRAMSpeedPerState[i] * mode_lib->vba.NumberOfChannels
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c
@@ -78,7 +78,7 @@
 
 static unsigned int get_bytes_per_element(enum source_format_class source_format, bool is_chroma)
 {
-	unsigned int ret_val = 0;
+	unsigned int ret_val = 1;
 
 	if (source_format == dm_444_16) {
 		if (!is_chroma)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c
@@ -54,7 +54,7 @@
 
 static unsigned int get_bytes_per_element(enum source_format_class source_format, bool is_chroma)
 {
-	unsigned int ret_val = 0;
+	unsigned int ret_val = 1;
 
 	if (source_format == dm_444_16) {
 		if (!is_chroma)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/dml/dml_common_defs.c
@@ -24,7 +24,7 @@
  */
 
 #include "dml_common_defs.h"
-#include "../calcs/dcn_calc_math.h"
+#include "dcn_calc_math.h"
 
 #include "dml_inline_defs.h"
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/dml/dml_inline_defs.h
@@ -27,7 +27,7 @@
 #define __DML_INLINE_DEFS_H__
 
 #include "dml_common_defs.h"
-#include "../calcs/dcn_calc_math.h"
+#include "dcn_calc_math.h"
 #include "dml_logger.h"
 
 static inline double dml_min(double a, double b)
@@ -67,11 +67,15 @@
 
 static inline double dml_ceil(double a, double granularity)
 {
+	if (granularity == 0)
+		return 0;
 	return (double) dcn_bw_ceil2(a, granularity);
 }
 
 static inline double dml_floor(double a, double granularity)
 {
+	if (granularity == 0)
+		return 0;
 	return (double) dcn_bw_floor2(a, granularity);
 }
 
@@ -97,11 +101,15 @@
 
 static inline double dml_ceil_ex(double x, double granularity)
 {
+	if (granularity == 0)
+		return 0;
 	return (double) dcn_bw_ceil2(x, granularity);
 }
 
 static inline double dml_floor_ex(double x, double granularity)
 {
+	if (granularity == 0)
+		return 0;
 	return (double) dcn_bw_floor2(x, granularity);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/gpio/gpio_base.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/gpio/gpio_base.c
@@ -63,13 +63,13 @@
 	enum gpio_mode mode)
 {
 	if (gpio->pin) {
-		ASSERT_CRITICAL(false);
+		BREAK_TO_DEBUGGER();
 		return GPIO_RESULT_ALREADY_OPENED;
 	}
 
 	// No action if allocation failed during gpio construct
 	if (!gpio->hw_container.ddc) {
-		ASSERT_CRITICAL(false);
+		BREAK_TO_DEBUGGER();
 		return GPIO_RESULT_NON_SPECIFIC_ERROR;
 	}
 	gpio->mode = mode;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c
@@ -53,12 +53,12 @@
  */
 
 struct gpio_service *dal_gpio_service_create(
-	enum dce_version dce_version_major,
-	enum dce_version dce_version_minor,
+	enum dce_version dce_version,
+	enum dce_environment dce_environment,
 	struct dc_context *ctx)
 {
 	struct gpio_service *service;
-	uint32_t index_of_id;
+	int32_t index_of_id;
 
 	service = kzalloc(sizeof(struct gpio_service), GFP_KERNEL);
 
@@ -67,14 +67,14 @@
 		return NULL;
 	}
 
-	if (!dal_hw_translate_init(&service->translate, dce_version_major,
-			dce_version_minor)) {
+	if (!dal_hw_translate_init(&service->translate, dce_version,
+			dce_environment)) {
 		BREAK_TO_DEBUGGER();
 		goto failure_1;
 	}
 
-	if (!dal_hw_factory_init(&service->factory, dce_version_major,
-			dce_version_minor)) {
+	if (!dal_hw_factory_init(&service->factory, dce_version,
+			dce_environment)) {
 		BREAK_TO_DEBUGGER();
 		goto failure_1;
 	}
@@ -114,7 +114,7 @@
 	return service;
 
 failure_2:
-	while (index_of_id) {
+	while (index_of_id > 0) {
 		--index_of_id;
 		kfree(service->busyness[index_of_id]);
 	}
@@ -242,6 +242,9 @@
 	enum gpio_id id,
 	uint32_t en)
 {
+	if (id == GPIO_ID_UNKNOWN)
+		return false;
+
 	return service->busyness[id][en];
 }
 
@@ -250,6 +253,9 @@
 	enum gpio_id id,
 	uint32_t en)
 {
+	if (id == GPIO_ID_UNKNOWN)
+		return;
+
 	service->busyness[id][en] = true;
 }
 
@@ -258,6 +264,9 @@
 	enum gpio_id id,
 	uint32_t en)
 {
+	if (id == GPIO_ID_UNKNOWN)
+		return;
+
 	service->busyness[id][en] = false;
 }
 
@@ -266,7 +275,7 @@
 	enum gpio_id id,
 	uint32_t en)
 {
-	if (!service->busyness[id]) {
+	if (id != GPIO_ID_UNKNOWN && !service->busyness[id]) {
 		ASSERT_CRITICAL(false);
 		return GPIO_RESULT_OPEN_FAILED;
 	}
@@ -280,7 +289,7 @@
 	enum gpio_id id,
 	uint32_t en)
 {
-	if (!service->busyness[id]) {
+	if (id != GPIO_ID_UNKNOWN && !service->busyness[id]) {
 		ASSERT_CRITICAL(false);
 		return GPIO_RESULT_OPEN_FAILED;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/inc/dcn_calc_math.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/inc/dcn_calc_math.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2017 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef _DCN_CALC_MATH_H_
+#define _DCN_CALC_MATH_H_
+
+float dcn_bw_mod(const float arg1, const float arg2);
+float dcn_bw_min2(const float arg1, const float arg2);
+unsigned int dcn_bw_max(const unsigned int arg1, const unsigned int arg2);
+float dcn_bw_max2(const float arg1, const float arg2);
+float dcn_bw_floor2(const float arg, const float significance);
+float dcn_bw_floor(const float arg);
+float dcn_bw_ceil2(const float arg, const float significance);
+float dcn_bw_ceil(const float arg);
+float dcn_bw_max3(float v1, float v2, float v3);
+float dcn_bw_max5(float v1, float v2, float v3, float v4, float v5);
+float dcn_bw_pow(float a, float exp);
+float dcn_bw_log(float a, float b);
+double dcn_bw_fabs(double a);
+
+#endif /* _DCN_CALC_MATH_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/inc/hw/dsc.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/inc/hw/dsc.h
@@ -36,6 +36,7 @@
 	uint32_t pic_height;
 	enum dc_pixel_encoding pixel_encoding;
 	enum dc_color_depth color_depth;  /* Bits per component */
+	bool is_odm;
 	struct dc_dsc_config dc_dsc_cfg;
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
@@ -321,10 +321,12 @@
 			struct dc_state *context);
 	void (*update_writeback)(struct dc *dc,
 			const struct dc_stream_status *stream_status,
-			struct dc_writeback_info *wb_info);
+			struct dc_writeback_info *wb_info,
+			struct dc_state *context);
 	void (*enable_writeback)(struct dc *dc,
 			const struct dc_stream_status *stream_status,
-			struct dc_writeback_info *wb_info);
+			struct dc_writeback_info *wb_info,
+			struct dc_state *context);
 	void (*disable_writeback)(struct dc *dc,
 			unsigned int dwb_pipe_inst);
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.c
@@ -299,8 +299,8 @@
 	pflip_int_entry(1),
 	pflip_int_entry(2),
 	pflip_int_entry(3),
-	[DC_IRQ_SOURCE_PFLIP5] = dummy_irq_entry(),
-	[DC_IRQ_SOURCE_PFLIP6] = dummy_irq_entry(),
+	pflip_int_entry(4),
+	pflip_int_entry(5),
 	[DC_IRQ_SOURCE_PFLIP_UNDERLAY0] = dummy_irq_entry(),
 	gpio_pad_int_entry(0),
 	gpio_pad_int_entry(1),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c
@@ -168,6 +168,11 @@
 	.ack = NULL
 };
 
+static const struct irq_source_info_funcs vupdate_no_lock_irq_info_funcs = {
+	.set = NULL,
+	.ack = NULL
+};
+
 #undef BASE_INNER
 #define BASE_INNER(seg) DMU_BASE__INST0_SEG ## seg
 
@@ -222,12 +227,15 @@
 		.funcs = &pflip_irq_info_funcs\
 	}
 
-#define vupdate_int_entry(reg_num)\
+/* vupdate_no_lock_int_entry maps to DC_IRQ_SOURCE_VUPDATEx, to match semantic
+ * of DCE's DC_IRQ_SOURCE_VUPDATEx.
+ */
+#define vupdate_no_lock_int_entry(reg_num)\
 	[DC_IRQ_SOURCE_VUPDATE1 + reg_num] = {\
 		IRQ_REG_ENTRY(OTG, reg_num,\
-			OTG_GLOBAL_SYNC_STATUS, VUPDATE_INT_EN,\
-			OTG_GLOBAL_SYNC_STATUS, VUPDATE_EVENT_CLEAR),\
-		.funcs = &vblank_irq_info_funcs\
+			OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_INT_EN,\
+			OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_EVENT_CLEAR),\
+		.funcs = &vupdate_no_lock_irq_info_funcs\
 	}
 
 #define vblank_int_entry(reg_num)\
@@ -332,12 +340,12 @@
 	dc_underflow_int_entry(6),
 	[DC_IRQ_SOURCE_DMCU_SCP] = dummy_irq_entry(),
 	[DC_IRQ_SOURCE_VBIOS_SW] = dummy_irq_entry(),
-	vupdate_int_entry(0),
-	vupdate_int_entry(1),
-	vupdate_int_entry(2),
-	vupdate_int_entry(3),
-	vupdate_int_entry(4),
-	vupdate_int_entry(5),
+	vupdate_no_lock_int_entry(0),
+	vupdate_no_lock_int_entry(1),
+	vupdate_no_lock_int_entry(2),
+	vupdate_no_lock_int_entry(3),
+	vupdate_no_lock_int_entry(4),
+	vupdate_no_lock_int_entry(5),
 	vblank_int_entry(0),
 	vblank_int_entry(1),
 	vblank_int_entry(2),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/irq_types.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/irq_types.h
@@ -163,7 +163,7 @@
 };
 
 #define DAL_VALID_IRQ_SRC_NUM(src) \
-	((src) <= DAL_IRQ_SOURCES_NUMBER && (src) > DC_IRQ_SOURCE_INVALID)
+	((src) < DAL_IRQ_SOURCES_NUMBER && (src) > DC_IRQ_SOURCE_INVALID)
 
 /* Number of Page Flip IRQ Sources. */
 #define DAL_PFLIP_IRQ_SRC_NUM \
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/dc/os_types.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/dc/os_types.h
@@ -57,7 +57,7 @@
  * general debug capabilities
  *
  */
-#if defined(CONFIG_HAVE_KGDB) || defined(CONFIG_KGDB)
+#if defined(CONFIG_DEBUG_KERNEL_DC) && (defined(CONFIG_HAVE_KGDB) || defined(CONFIG_KGDB))
 #define ASSERT_CRITICAL(expr) do {	\
 	if (WARN_ON(!(expr))) { \
 		kgdb_breakpoint(); \
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/include/ddc_service_types.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/include/ddc_service_types.h
@@ -31,6 +31,8 @@
 #define DP_BRANCH_DEVICE_ID_0022B9 0x0022B9
 #define DP_BRANCH_DEVICE_ID_00001A 0x00001A
 #define DP_BRANCH_DEVICE_ID_0080E1 0x0080e1
+#define DP_BRANCH_DEVICE_ID_90CC24 0x90CC24
+#define DP_BRANCH_DEVICE_ID_00E04C 0x00E04C
 
 enum ddc_result {
 	DDC_RESULT_UNKNOWN = 0,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/include/fixed31_32.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/include/fixed31_32.h
@@ -431,6 +431,9 @@
  */
 static inline struct fixed31_32 dc_fixpt_pow(struct fixed31_32 arg1, struct fixed31_32 arg2)
 {
+	if (arg1.value == 0)
+		return arg2.value == 0 ? dc_fixpt_one : dc_fixpt_zero;
+
 	return dc_fixpt_exp(
 		dc_fixpt_mul(
 			dc_fixpt_log(arg1),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/include/gpio_service_interface.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/include/gpio_service_interface.h
@@ -42,8 +42,8 @@
 	struct gpio **ptr);
 
 struct gpio_service *dal_gpio_service_create(
-	enum dce_version dce_version_major,
-	enum dce_version dce_version_minor,
+	enum dce_version dce_version,
+	enum dce_environment dce_environment,
 	struct dc_context *ctx);
 
 struct gpio *dal_gpio_service_create_irq(
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/modules/color/color_gamma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/modules/color/color_gamma.c
@@ -799,7 +799,7 @@
 	pow_buffer_ptr = -1; // reset back to no optimize
 	ret = true;
 release:
-	kfree(coeff);
+	kvfree(coeff);
 	return ret;
 }
 
@@ -1486,6 +1486,7 @@
 	struct fixed31_32 lut2;
 	struct fixed31_32 delta_lut;
 	struct fixed31_32 delta_index;
+	const struct fixed31_32 one = dc_fixpt_from_int(1);
 
 	i = 0;
 	/* fixed_pt library has problems handling too small values */
@@ -1514,6 +1515,9 @@
 			} else
 				hw_x = coordinates_x[i].x;
 
+			if (dc_fixpt_le(one, hw_x))
+				hw_x = one;
+
 			norm_x = dc_fixpt_mul(norm_factor, hw_x);
 			index = dc_fixpt_floor(norm_x);
 			if (index < 0 || index > 255)
@@ -1576,7 +1580,7 @@
 	struct pwl_float_data_ex *rgb = rgb_regamma;
 	const struct hw_x_point *coord_x = coordinates_x;
 
-	build_coefficients(&coeff, true);
+	build_coefficients(&coeff, TRANSFER_FUNCTION_SRGB);
 
 	i = 0;
 	while (i != hw_points_num + 1) {
@@ -1862,7 +1866,7 @@
 
 	kfree(rgb_regamma);
 rgb_regamma_alloc_fail:
-	kvfree(rgb_user);
+	kfree(rgb_user);
 rgb_user_alloc_fail:
 	return ret;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
@@ -37,8 +37,8 @@
 #define STATIC_SCREEN_RAMP_DELTA_REFRESH_RATE_PER_FRAME ((1000 / 60) * 65)
 /* Number of elements in the render times cache array */
 #define RENDER_TIMES_MAX_COUNT 10
-/* Threshold to exit BTR (to avoid frequent enter-exits at the lower limit) */
-#define BTR_EXIT_MARGIN 2000
+/* Threshold to exit/exit BTR (to avoid frequent enter-exits at the lower limit) */
+#define BTR_MAX_MARGIN 2500
 /* Threshold to change BTR multiplier (to avoid frequent changes) */
 #define BTR_DRIFT_MARGIN 2000
 /*Threshold to exit fixed refresh rate*/
@@ -131,7 +131,7 @@
 
 	v_total = div64_u64(div64_u64(((unsigned long long)(
 			frame_duration_in_ns) * (stream->timing.pix_clk_100hz / 10)),
-			stream->timing.h_total), 1000000);
+			stream->timing.h_total) + 500000, 1000000);
 
 	/* v_total cannot be less than nominal */
 	if (v_total < stream->timing.v_total) {
@@ -250,24 +250,22 @@
 	unsigned int delta_from_mid_point_in_us_1 = 0xFFFFFFFF;
 	unsigned int delta_from_mid_point_in_us_2 = 0xFFFFFFFF;
 	unsigned int frames_to_insert = 0;
-	unsigned int min_frame_duration_in_ns = 0;
-	unsigned int max_render_time_in_us = in_out_vrr->max_duration_in_us;
 	unsigned int delta_from_mid_point_delta_in_us;
-
-	min_frame_duration_in_ns = ((unsigned int) (div64_u64(
-		(1000000000ULL * 1000000),
-		in_out_vrr->max_refresh_in_uhz)));
+	unsigned int max_render_time_in_us =
+			in_out_vrr->max_duration_in_us - in_out_vrr->btr.margin_in_us;
 
 	/* Program BTR */
-	if (last_render_time_in_us + BTR_EXIT_MARGIN < max_render_time_in_us) {
+	if ((last_render_time_in_us + in_out_vrr->btr.margin_in_us / 2) < max_render_time_in_us) {
 		/* Exit Below the Range */
 		if (in_out_vrr->btr.btr_active) {
 			in_out_vrr->btr.frame_counter = 0;
 			in_out_vrr->btr.btr_active = false;
 		}
-	} else if (last_render_time_in_us > max_render_time_in_us) {
+	} else if (last_render_time_in_us > (max_render_time_in_us + in_out_vrr->btr.margin_in_us / 2)) {
 		/* Enter Below the Range */
-		in_out_vrr->btr.btr_active = true;
+		if (!in_out_vrr->btr.btr_active) {
+			in_out_vrr->btr.btr_active = true;
+		}
 	}
 
 	/* BTR set to "not active" so disengage */
@@ -322,24 +320,50 @@
 
 		/* Choose number of frames to insert based on how close it
 		 * can get to the mid point of the variable range.
+		 *  - Delta for CEIL: delta_from_mid_point_in_us_1
+		 *  - Delta for FLOOR: delta_from_mid_point_in_us_2
 		 */
-		if (delta_from_mid_point_in_us_1 < delta_from_mid_point_in_us_2) {
+		if (mid_point_frames_ceil &&
+		    (last_render_time_in_us / mid_point_frames_ceil) <
+		    in_out_vrr->min_duration_in_us) {
+			/* Check for out of range.
+			 * If using CEIL produces a value that is out of range,
+			 * then we are forced to use FLOOR.
+			 */
+			frames_to_insert = mid_point_frames_floor;
+		} else if (mid_point_frames_floor < 2) {
+			/* Check if FLOOR would result in non-LFC. In this case
+			 * choose to use CEIL
+			 */
+			frames_to_insert = mid_point_frames_ceil;
+		} else if (delta_from_mid_point_in_us_1 < delta_from_mid_point_in_us_2) {
+			/* If choosing CEIL results in a frame duration that is
+			 * closer to the mid point of the range.
+			 * Choose CEIL
+			 */
 			frames_to_insert = mid_point_frames_ceil;
-			delta_from_mid_point_delta_in_us = delta_from_mid_point_in_us_2 -
-					delta_from_mid_point_in_us_1;
 		} else {
+			/* If choosing FLOOR results in a frame duration that is
+			 * closer to the mid point of the range.
+			 * Choose FLOOR
+			 */
 			frames_to_insert = mid_point_frames_floor;
-			delta_from_mid_point_delta_in_us = delta_from_mid_point_in_us_1 -
-					delta_from_mid_point_in_us_2;
 		}
 
 		/* Prefer current frame multiplier when BTR is enabled unless it drifts
 		 * too far from the midpoint
 		 */
+		if (delta_from_mid_point_in_us_1 < delta_from_mid_point_in_us_2) {
+			delta_from_mid_point_delta_in_us = delta_from_mid_point_in_us_2 -
+					delta_from_mid_point_in_us_1;
+		} else {
+			delta_from_mid_point_delta_in_us = delta_from_mid_point_in_us_1 -
+					delta_from_mid_point_in_us_2;
+		}
 		if (in_out_vrr->btr.frames_to_insert != 0 &&
 				delta_from_mid_point_delta_in_us < BTR_DRIFT_MARGIN) {
 			if (((last_render_time_in_us / in_out_vrr->btr.frames_to_insert) <
-					in_out_vrr->max_duration_in_us) &&
+					max_render_time_in_us) &&
 				((last_render_time_in_us / in_out_vrr->btr.frames_to_insert) >
 					in_out_vrr->min_duration_in_us))
 				frames_to_insert = in_out_vrr->btr.frames_to_insert;
@@ -348,8 +372,9 @@
 		/* Either we've calculated the number of frames to insert,
 		 * or we need to insert min duration frames
 		 */
-		if (last_render_time_in_us / frames_to_insert <
-				in_out_vrr->min_duration_in_us){
+		if (frames_to_insert &&
+		    (last_render_time_in_us / frames_to_insert) <
+		    in_out_vrr->min_duration_in_us){
 			frames_to_insert -= (frames_to_insert > 1) ?
 					1 : 0;
 		}
@@ -743,6 +768,10 @@
 	nominal_field_rate_in_uhz =
 			mod_freesync_calc_nominal_field_rate(stream);
 
+	/* Rounded to the nearest Hz */
+	nominal_field_rate_in_uhz = 1000000ULL *
+			div_u64(nominal_field_rate_in_uhz + 500000, 1000000);
+
 	min_refresh_in_uhz = in_config->min_refresh_in_uhz;
 	max_refresh_in_uhz = in_config->max_refresh_in_uhz;
 
@@ -788,6 +817,11 @@
 		refresh_range = in_out_vrr->max_refresh_in_uhz -
 				in_out_vrr->min_refresh_in_uhz;
 
+		in_out_vrr->btr.margin_in_us = in_out_vrr->max_duration_in_us -
+				2 * in_out_vrr->min_duration_in_us;
+		if (in_out_vrr->btr.margin_in_us > BTR_MAX_MARGIN)
+			in_out_vrr->btr.margin_in_us = BTR_MAX_MARGIN;
+
 		in_out_vrr->supported = true;
 	}
 
@@ -799,10 +833,12 @@
 			2 * in_out_vrr->min_refresh_in_uhz)
 		in_out_vrr->btr.btr_enabled = false;
 
+	in_out_vrr->fixed.fixed_active = false;
 	in_out_vrr->btr.btr_active = false;
 	in_out_vrr->btr.inserted_duration_in_us = 0;
 	in_out_vrr->btr.frames_to_insert = 0;
 	in_out_vrr->btr.frame_counter = 0;
+
 	in_out_vrr->btr.mid_point_in_us =
 				(in_out_vrr->min_duration_in_us +
 				 in_out_vrr->max_duration_in_us) / 2;
@@ -818,6 +854,7 @@
 		in_out_vrr->adjust.v_total_max = stream->timing.v_total;
 	} else if (in_out_vrr->state == VRR_STATE_ACTIVE_VARIABLE &&
 			refresh_range >= MIN_REFRESH_RANGE_IN_US) {
+
 		in_out_vrr->adjust.v_total_min =
 			calc_v_total_from_refresh(stream,
 				in_out_vrr->max_refresh_in_uhz);
@@ -996,14 +1033,13 @@
 			const struct dc_stream_state *stream)
 {
 	unsigned long long nominal_field_rate_in_uhz = 0;
+	unsigned int total = stream->timing.h_total * stream->timing.v_total;
 
-	/* Calculate nominal field rate for stream */
+	/* Calculate nominal field rate for stream, rounded up to nearest integer */
 	nominal_field_rate_in_uhz = stream->timing.pix_clk_100hz / 10;
 	nominal_field_rate_in_uhz *= 1000ULL * 1000ULL * 1000ULL;
-	nominal_field_rate_in_uhz = div_u64(nominal_field_rate_in_uhz,
-						stream->timing.h_total);
-	nominal_field_rate_in_uhz = div_u64(nominal_field_rate_in_uhz,
-						stream->timing.v_total);
+
+	nominal_field_rate_in_uhz =	div_u64(nominal_field_rate_in_uhz, total);
 
 	return nominal_field_rate_in_uhz;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h
@@ -92,6 +92,7 @@
 	uint32_t inserted_duration_in_us;
 	uint32_t frames_to_insert;
 	uint32_t frame_counter;
+	uint32_t margin_in_us;
 };
 
 struct mod_vrr_params_fixed_refresh {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/modules/inc/mod_stats.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/modules/inc/mod_stats.h
@@ -51,10 +51,10 @@
 		unsigned int length);
 
 void mod_stats_update_flip(struct mod_stats *mod_stats,
-		unsigned long timestamp_in_ns);
+		unsigned long long timestamp_in_ns);
 
 void mod_stats_update_vupdate(struct mod_stats *mod_stats,
-		unsigned long timestamp_in_ns);
+		unsigned long long timestamp_in_ns);
 
 void mod_stats_update_freesync(struct mod_stats *mod_stats,
 		unsigned int v_total_min,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
@@ -85,7 +85,8 @@
 //PB7 = MD0
 #define MASK_VTEM_MD0__VRR_EN         0x01
 #define MASK_VTEM_MD0__M_CONST        0x02
-#define MASK_VTEM_MD0__RESERVED2      0x0C
+#define MASK_VTEM_MD0__QMS_EN         0x04
+#define MASK_VTEM_MD0__RESERVED2      0x08
 #define MASK_VTEM_MD0__FVA_FACTOR_M1  0xF0
 
 //MD1
@@ -94,7 +95,7 @@
 //MD2
 #define MASK_VTEM_MD2__BASE_REFRESH_RATE_98  0x03
 #define MASK_VTEM_MD2__RB                    0x04
-#define MASK_VTEM_MD2__RESERVED3             0xF8
+#define MASK_VTEM_MD2__NEXT_TFR              0xF8
 
 //MD3
 #define MASK_VTEM_MD3__BASE_REFRESH_RATE_07  0xFF
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/modules/power/power_helpers.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/modules/power/power_helpers.c
@@ -115,7 +115,7 @@
 /* NOTE: iRAM is 256B in size */
 struct iram_table_v_2 {
 	/* flags                      */
-	uint16_t flags;							/* 0x00 U16  */
+	uint16_t min_abm_backlight;					/* 0x00 U16  */
 
 	/* parameters for ABM2.0 algorithm */
 	uint8_t min_reduction[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL];		/* 0x02 U0.8 */
@@ -140,10 +140,10 @@
 
 	/* For reading PSR State directly from IRAM */
 	uint8_t psr_state;						/* 0xf0       */
-	uint8_t dmcu_mcp_interface_version;							/* 0xf1       */
-	uint8_t dmcu_abm_feature_version;							/* 0xf2       */
-	uint8_t dmcu_psr_feature_version;							/* 0xf3       */
-	uint16_t dmcu_version;										/* 0xf4       */
+	uint8_t dmcu_mcp_interface_version;				/* 0xf1       */
+	uint8_t dmcu_abm_feature_version;				/* 0xf2       */
+	uint8_t dmcu_psr_feature_version;				/* 0xf3       */
+	uint16_t dmcu_version;						/* 0xf4       */
 	uint8_t dmcu_state;						/* 0xf6       */
 
 	uint16_t blRampReduction;					/* 0xf7       */
@@ -164,42 +164,43 @@
 	uint8_t max_reduction[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL];		/* 0x16 U0.8 */
 	uint8_t bright_pos_gain[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL];	/* 0x2a U2.6 */
 	uint8_t dark_pos_gain[NUM_AMBI_LEVEL][NUM_AGGR_LEVEL];		/* 0x3e U2.6 */
-	uint8_t hybrid_factor[NUM_AGGR_LEVEL];						/* 0x52 U0.8 */
-	uint8_t contrast_factor[NUM_AGGR_LEVEL];					/* 0x56 U0.8 */
-	uint8_t deviation_gain[NUM_AGGR_LEVEL];						/* 0x5a U0.8 */
-	uint8_t iir_curve[NUM_AMBI_LEVEL];							/* 0x5e U0.8 */
-	uint8_t min_knee[NUM_AGGR_LEVEL];							/* 0x63 U0.8 */
-	uint8_t max_knee[NUM_AGGR_LEVEL];							/* 0x67 U0.8 */
-	uint8_t pad[21];											/* 0x6b U0.8 */
+	uint8_t hybrid_factor[NUM_AGGR_LEVEL];				/* 0x52 U0.8 */
+	uint8_t contrast_factor[NUM_AGGR_LEVEL];			/* 0x56 U0.8 */
+	uint8_t deviation_gain[NUM_AGGR_LEVEL];				/* 0x5a U0.8 */
+	uint8_t iir_curve[NUM_AMBI_LEVEL];				/* 0x5e U0.8 */
+	uint8_t min_knee[NUM_AGGR_LEVEL];				/* 0x63 U0.8 */
+	uint8_t max_knee[NUM_AGGR_LEVEL];				/* 0x67 U0.8 */
+	uint16_t min_abm_backlight;					/* 0x6b U16  */
+	uint8_t pad[19];						/* 0x6d U0.8 */
 
 	/* parameters for crgb conversion */
-	uint16_t crgb_thresh[NUM_POWER_FN_SEGS];					/* 0x80 U3.13 */
-	uint16_t crgb_offset[NUM_POWER_FN_SEGS];					/* 0x90 U1.15 */
-	uint16_t crgb_slope[NUM_POWER_FN_SEGS];						/* 0xa0 U4.12 */
+	uint16_t crgb_thresh[NUM_POWER_FN_SEGS];			/* 0x80 U3.13 */
+	uint16_t crgb_offset[NUM_POWER_FN_SEGS];			/* 0x90 U1.15 */
+	uint16_t crgb_slope[NUM_POWER_FN_SEGS];				/* 0xa0 U4.12 */
 
 	/* parameters for custom curve */
 	/* thresholds for brightness --> backlight */
-	uint16_t backlight_thresholds[NUM_BL_CURVE_SEGS];			/* 0xb0 U16.0 */
+	uint16_t backlight_thresholds[NUM_BL_CURVE_SEGS];		/* 0xb0 U16.0 */
 	/* offsets for brightness --> backlight */
-	uint16_t backlight_offsets[NUM_BL_CURVE_SEGS];				/* 0xd0 U16.0 */
+	uint16_t backlight_offsets[NUM_BL_CURVE_SEGS];			/* 0xd0 U16.0 */
 
 	/* For reading PSR State directly from IRAM */
-	uint8_t psr_state;											/* 0xf0       */
-	uint8_t dmcu_mcp_interface_version;							/* 0xf1       */
-	uint8_t dmcu_abm_feature_version;							/* 0xf2       */
-	uint8_t dmcu_psr_feature_version;							/* 0xf3       */
-	uint16_t dmcu_version;										/* 0xf4       */
-	uint8_t dmcu_state;											/* 0xf6       */
-
-	uint8_t dummy1;												/* 0xf7       */
-	uint8_t dummy2;												/* 0xf8       */
-	uint8_t dummy3;												/* 0xf9       */
-	uint8_t dummy4;												/* 0xfa       */
-	uint8_t dummy5;												/* 0xfb       */
-	uint8_t dummy6;												/* 0xfc       */
-	uint8_t dummy7;												/* 0xfd       */
-	uint8_t dummy8;												/* 0xfe       */
-	uint8_t dummy9;												/* 0xff       */
+	uint8_t psr_state;						/* 0xf0       */
+	uint8_t dmcu_mcp_interface_version;				/* 0xf1       */
+	uint8_t dmcu_abm_feature_version;				/* 0xf2       */
+	uint8_t dmcu_psr_feature_version;				/* 0xf3       */
+	uint16_t dmcu_version;						/* 0xf4       */
+	uint8_t dmcu_state;						/* 0xf6       */
+
+	uint8_t dummy1;							/* 0xf7       */
+	uint8_t dummy2;							/* 0xf8       */
+	uint8_t dummy3;							/* 0xf9       */
+	uint8_t dummy4;							/* 0xfa       */
+	uint8_t dummy5;							/* 0xfb       */
+	uint8_t dummy6;							/* 0xfc       */
+	uint8_t dummy7;							/* 0xfd       */
+	uint8_t dummy8;							/* 0xfe       */
+	uint8_t dummy9;							/* 0xff       */
 };
 #pragma pack(pop)
 
@@ -271,7 +272,8 @@
 {
 	unsigned int set = params.set;
 
-	ram_table->flags = 0x0;
+	ram_table->min_abm_backlight =
+			cpu_to_be16(params.min_abm_backlight);
 	ram_table->deviation_gain = 0xb3;
 
 	ram_table->blRampReduction =
@@ -445,6 +447,9 @@
 
 	ram_table->flags = 0x0;
 
+	ram_table->min_abm_backlight =
+			cpu_to_be16(params.min_abm_backlight);
+
 	ram_table->deviation_gain[0] = 0xb3;
 	ram_table->deviation_gain[1] = 0xa8;
 	ram_table->deviation_gain[2] = 0x98;
@@ -588,6 +593,10 @@
 	unsigned int set = params.set;
 
 	ram_table->flags = 0x0;
+
+	ram_table->min_abm_backlight =
+			cpu_to_be16(params.min_abm_backlight);
+
 	for (i = 0; i < NUM_AGGR_LEVEL; i++) {
 		ram_table->hybrid_factor[i] = abm_settings[set][i].brightness_gain;
 		ram_table->contrast_factor[i] = abm_settings[set][i].contrast_factor;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/display/modules/power/power_helpers.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/display/modules/power/power_helpers.h
@@ -38,6 +38,7 @@
 	unsigned int backlight_lut_array_size;
 	unsigned int backlight_ramping_reduction;
 	unsigned int backlight_ramping_start;
+	unsigned int min_abm_backlight;
 	unsigned int set;
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/include/asic_reg/dce/dce_12_0_offset.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/include/asic_reg/dce/dce_12_0_offset.h
@@ -7376,6 +7376,8 @@
 #define mmCRTC4_CRTC_DRR_CONTROL                                                                       0x0f3e
 #define mmCRTC4_CRTC_DRR_CONTROL_BASE_IDX                                                              2
 
+#define mmDCHUBBUB_SDPIF_MMIO_CNTRL_0                                                                  0x395d
+#define mmDCHUBBUB_SDPIF_MMIO_CNTRL_0_BASE_IDX                                                         2
 
 // addressBlock: dce_dc_fmt4_dispdec
 // base address: 0x2000
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/include/atombios.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/include/atombios.h
@@ -4107,7 +4107,7 @@
 {
   UCHAR ucRecordType;
   UCHAR ucFakeEDIDLength;       // = 128 means EDID length is 128 bytes, otherwise the EDID length = ucFakeEDIDLength*128
-  UCHAR ucFakeEDIDString[1];    // This actually has ucFakeEdidLength elements.
+  UCHAR ucFakeEDIDString[];     // This actually has ucFakeEdidLength elements.
 } ATOM_FAKE_EDID_PATCH_RECORD;
 
 typedef struct  _ATOM_PANEL_RESOLUTION_PATCH_RECORD
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/include/atomfirmware.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/include/atomfirmware.h
@@ -653,7 +653,7 @@
 {
   struct  atom_common_table_header  table_header;
   /*the real number of this included in the structure is calcualted by using the (whole structure size - the header size)/size of atom_gpio_pin_lut  */
-  struct  atom_gpio_pin_assignment  gpio_pin[8];
+  struct  atom_gpio_pin_assignment  gpio_pin[];
 };
 
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/include/discovery.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/include/discovery.h
@@ -25,7 +25,6 @@
 #define _DISCOVERY_H_
 
 #define PSP_HEADER_SIZE                 256
-#define BINARY_MAX_SIZE                 (64 << 10)
 #define BINARY_SIGNATURE                0x28211407
 #define DISCOVERY_TABLE_SIGNATURE       0x53445049
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/include/navi10_enum.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/include/navi10_enum.h
@@ -430,7 +430,7 @@
  */
 
 typedef enum ENUM_NUM_SIMD_PER_CU {
-NUM_SIMD_PER_CU                          = 0x00000004,
+NUM_SIMD_PER_CU                          = 0x00000002,
 } ENUM_NUM_SIMD_PER_CU;
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/include/pptable.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/include/pptable.h
@@ -78,7 +78,7 @@
 typedef struct _ATOM_PPLIB_STATE
 {
     UCHAR ucNonClockStateIndex;
-    UCHAR ucClockStateIndices[1]; // variable-sized
+    UCHAR ucClockStateIndices[]; // variable-sized
 } ATOM_PPLIB_STATE;
 
 
@@ -473,7 +473,7 @@
       /**
       * Driver will read the first ucNumDPMLevels in this array
       */
-      UCHAR clockInfoIndex[1];
+      UCHAR clockInfoIndex[];
 } ATOM_PPLIB_STATE_V2;
 
 typedef struct _StateArray{
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
@@ -320,12 +320,12 @@
 		if (*level & profile_mode_mask) {
 			hwmgr->saved_dpm_level = hwmgr->dpm_level;
 			hwmgr->en_umd_pstate = true;
-			amdgpu_device_ip_set_clockgating_state(hwmgr->adev,
-						AMD_IP_BLOCK_TYPE_GFX,
-						AMD_CG_STATE_UNGATE);
 			amdgpu_device_ip_set_powergating_state(hwmgr->adev,
 					AMD_IP_BLOCK_TYPE_GFX,
 					AMD_PG_STATE_UNGATE);
+			amdgpu_device_ip_set_clockgating_state(hwmgr->adev,
+						AMD_IP_BLOCK_TYPE_GFX,
+						AMD_CG_STATE_UNGATE);
 		}
 	} else {
 		/* exit umd pstate, restore level, enable gfx cg*/
@@ -1421,10 +1421,12 @@
 {
 	struct pp_hwmgr *hwmgr = handle;
 
+	*cap = false;
 	if (!hwmgr)
 		return -EINVAL;
 
-	if (!hwmgr->pm_en || !hwmgr->hwmgr_func->get_asic_baco_capability)
+	if (!(hwmgr->not_vf && amdgpu_dpm) ||
+		!hwmgr->hwmgr_func->get_asic_baco_capability)
 		return 0;
 
 	mutex_lock(&hwmgr->smu_lock);
@@ -1458,7 +1460,8 @@
 	if (!hwmgr)
 		return -EINVAL;
 
-	if (!hwmgr->pm_en || !hwmgr->hwmgr_func->set_asic_baco_state)
+	if (!(hwmgr->not_vf && amdgpu_dpm) ||
+		!hwmgr->hwmgr_func->set_asic_baco_state)
 		return 0;
 
 	mutex_lock(&hwmgr->smu_lock);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
@@ -521,8 +521,11 @@
 	}
 
 	mutex_lock(&smu->mutex);
-	if (!smu_table->hardcode_pptable)
+	if (!smu_table->hardcode_pptable || smu_table->power_play_table_size < size) {
+		kfree(smu_table->hardcode_pptable);
 		smu_table->hardcode_pptable = kzalloc(size, GFP_KERNEL);
+	}
+
 	if (!smu_table->hardcode_pptable) {
 		ret = -ENOMEM;
 		goto failed;
@@ -844,6 +847,7 @@
 	smu->smu_baco.platform_support = false;
 
 	mutex_init(&smu->sensor_lock);
+	mutex_init(&smu->metrics_lock);
 
 	smu->watermarks_bitmap = 0;
 	smu->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
@@ -1344,7 +1348,10 @@
 	int ret;
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 	struct smu_context *smu = &adev->smu;
-	bool baco_feature_is_enabled = smu_feature_is_enabled(smu, SMU_FEATURE_BACO_BIT);
+	bool baco_feature_is_enabled = false;
+
+	if(!(adev->flags & AMD_IS_APU))
+		baco_feature_is_enabled = smu_feature_is_enabled(smu, SMU_FEATURE_BACO_BIT);
 
 	ret = smu_system_features_control(smu, false);
 	if (ret)
@@ -1537,12 +1544,12 @@
 		if (*level & profile_mode_mask) {
 			smu_dpm_ctx->saved_dpm_level = smu_dpm_ctx->dpm_level;
 			smu_dpm_ctx->enable_umd_pstate = true;
-			amdgpu_device_ip_set_clockgating_state(smu->adev,
-							       AMD_IP_BLOCK_TYPE_GFX,
-							       AMD_CG_STATE_UNGATE);
 			amdgpu_device_ip_set_powergating_state(smu->adev,
 							       AMD_IP_BLOCK_TYPE_GFX,
 							       AMD_PG_STATE_UNGATE);
+			amdgpu_device_ip_set_clockgating_state(smu->adev,
+							       AMD_IP_BLOCK_TYPE_GFX,
+							       AMD_CG_STATE_UNGATE);
 		}
 	} else {
 		/* exit umd pstate, restore level, enable gfx cg*/
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c
@@ -910,18 +910,21 @@
 	struct smu_table_context *smu_table= &smu->smu_table;
 	int ret = 0;
 
+	mutex_lock(&smu->metrics_lock);
 	if (!smu_table->metrics_time ||
 	     time_after(jiffies, smu_table->metrics_time + HZ / 1000)) {
 		ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0,
 				(void *)smu_table->metrics_table, false);
 		if (ret) {
 			pr_info("Failed to export SMU metrics table!\n");
+			mutex_unlock(&smu->metrics_lock);
 			return ret;
 		}
 		smu_table->metrics_time = jiffies;
 	}
 
 	memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t));
+	mutex_unlock(&smu->metrics_lock);
 
 	return ret;
 }
@@ -1388,12 +1391,17 @@
 					"VR",
 					"COMPUTE",
 					"CUSTOM"};
+	static const char *title[] = {
+			"PROFILE_INDEX(NAME)"};
 	uint32_t i, size = 0;
 	int16_t workload_type = 0;
 
 	if (!smu->pm_enabled || !buf)
 		return -EINVAL;
 
+	size += sprintf(buf + size, "%16s\n",
+			title[0]);
+
 	for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) {
 		/*
 		 * Conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.c
@@ -73,8 +73,9 @@
 					j++;
 				} else if ((table->mc_reg_address[i].uc_pre_reg_data &
 							LOW_NIBBLE_MASK) == DATA_EQU_PREV) {
-					table->mc_reg_table_entry[num_ranges].mc_data[i] =
-						table->mc_reg_table_entry[num_ranges].mc_data[i-1];
+					if (i)
+						table->mc_reg_table_entry[num_ranges].mc_data[i] =
+							table->mc_reg_table_entry[num_ranges].mc_data[i-1];
 				}
 			}
 			num_ranges++;
@@ -1369,6 +1370,8 @@
 			GetIndexIntoMasterTable(DATA, SMU_Info),
 			&size, &frev, &crev);
 
+	if (!psmu_info)
+		return -EINVAL;
 
 	for (i = 0; i < psmu_info->ucSclkEntryNum; i++) {
 		table->entry[i].ucVco_setting = psmu_info->asSclkFcwRangeEntry[i].ucVco_setting;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/powerplay/hwmgr/pptable_v1_0.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/powerplay/hwmgr/pptable_v1_0.h
@@ -164,7 +164,7 @@
 typedef struct _ATOM_Tonga_State_Array {
 	UCHAR ucRevId;
 	UCHAR ucNumEntries;		/* Number of entries. */
-	ATOM_Tonga_State entries[1];	/* Dynamically allocate entries. */
+	ATOM_Tonga_State entries[];	/* Dynamically allocate entries. */
 } ATOM_Tonga_State_Array;
 
 typedef struct _ATOM_Tonga_MCLK_Dependency_Record {
@@ -179,7 +179,7 @@
 typedef struct _ATOM_Tonga_MCLK_Dependency_Table {
 	UCHAR ucRevId;
 	UCHAR ucNumEntries; 										/* Number of entries. */
-	ATOM_Tonga_MCLK_Dependency_Record entries[1];				/* Dynamically allocate entries. */
+	ATOM_Tonga_MCLK_Dependency_Record entries[];				/* Dynamically allocate entries. */
 } ATOM_Tonga_MCLK_Dependency_Table;
 
 typedef struct _ATOM_Tonga_SCLK_Dependency_Record {
@@ -194,7 +194,7 @@
 typedef struct _ATOM_Tonga_SCLK_Dependency_Table {
 	UCHAR ucRevId;
 	UCHAR ucNumEntries; 										/* Number of entries. */
-	ATOM_Tonga_SCLK_Dependency_Record entries[1];				 /* Dynamically allocate entries. */
+	ATOM_Tonga_SCLK_Dependency_Record entries[];				 /* Dynamically allocate entries. */
 } ATOM_Tonga_SCLK_Dependency_Table;
 
 typedef struct _ATOM_Polaris_SCLK_Dependency_Record {
@@ -210,7 +210,7 @@
 typedef struct _ATOM_Polaris_SCLK_Dependency_Table {
 	UCHAR ucRevId;
 	UCHAR ucNumEntries;							/* Number of entries. */
-	ATOM_Polaris_SCLK_Dependency_Record entries[1];				 /* Dynamically allocate entries. */
+	ATOM_Polaris_SCLK_Dependency_Record entries[];				 /* Dynamically allocate entries. */
 } ATOM_Polaris_SCLK_Dependency_Table;
 
 typedef struct _ATOM_Tonga_PCIE_Record {
@@ -222,7 +222,7 @@
 typedef struct _ATOM_Tonga_PCIE_Table {
 	UCHAR ucRevId;
 	UCHAR ucNumEntries; 										/* Number of entries. */
-	ATOM_Tonga_PCIE_Record entries[1];							/* Dynamically allocate entries. */
+	ATOM_Tonga_PCIE_Record entries[];							/* Dynamically allocate entries. */
 } ATOM_Tonga_PCIE_Table;
 
 typedef struct _ATOM_Polaris10_PCIE_Record {
@@ -235,7 +235,7 @@
 typedef struct _ATOM_Polaris10_PCIE_Table {
 	UCHAR ucRevId;
 	UCHAR ucNumEntries;                                         /* Number of entries. */
-	ATOM_Polaris10_PCIE_Record entries[1];                      /* Dynamically allocate entries. */
+	ATOM_Polaris10_PCIE_Record entries[];                      /* Dynamically allocate entries. */
 } ATOM_Polaris10_PCIE_Table;
 
 
@@ -252,7 +252,7 @@
 typedef struct _ATOM_Tonga_MM_Dependency_Table {
 	UCHAR ucRevId;
 	UCHAR ucNumEntries; 										/* Number of entries. */
-	ATOM_Tonga_MM_Dependency_Record entries[1]; 			   /* Dynamically allocate entries. */
+	ATOM_Tonga_MM_Dependency_Record entries[]; 			   /* Dynamically allocate entries. */
 } ATOM_Tonga_MM_Dependency_Table;
 
 typedef struct _ATOM_Tonga_Voltage_Lookup_Record {
@@ -265,7 +265,7 @@
 typedef struct _ATOM_Tonga_Voltage_Lookup_Table {
 	UCHAR ucRevId;
 	UCHAR ucNumEntries; 										/* Number of entries. */
-	ATOM_Tonga_Voltage_Lookup_Record entries[1];				/* Dynamically allocate entries. */
+	ATOM_Tonga_Voltage_Lookup_Record entries[];				/* Dynamically allocate entries. */
 } ATOM_Tonga_Voltage_Lookup_Table;
 
 typedef struct _ATOM_Tonga_Fan_Table {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c
@@ -984,6 +984,32 @@
 			struct pp_hwmgr *hwmgr,
 			const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table)
 {
+	hwmgr->thermal_controller.ucType =
+			powerplay_table->sThermalController.ucType;
+	hwmgr->thermal_controller.ucI2cLine =
+			powerplay_table->sThermalController.ucI2cLine;
+	hwmgr->thermal_controller.ucI2cAddress =
+			powerplay_table->sThermalController.ucI2cAddress;
+
+	hwmgr->thermal_controller.fanInfo.bNoFan =
+		(0 != (powerplay_table->sThermalController.ucFanParameters &
+			ATOM_PP_FANPARAMETERS_NOFAN));
+
+	hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution =
+		powerplay_table->sThermalController.ucFanParameters &
+		ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK;
+
+	hwmgr->thermal_controller.fanInfo.ulMinRPM
+		= powerplay_table->sThermalController.ucFanMinRPM * 100UL;
+	hwmgr->thermal_controller.fanInfo.ulMaxRPM
+		= powerplay_table->sThermalController.ucFanMaxRPM * 100UL;
+
+	set_hw_cap(hwmgr,
+		   ATOM_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType,
+		   PHM_PlatformCaps_ThermalController);
+
+	hwmgr->thermal_controller.use_hw_fan_control = 1;
+
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
@@ -209,8 +209,7 @@
 {
 	struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
 
-	if (smu10_data->need_min_deep_sleep_dcefclk &&
-		smu10_data->deep_sleep_dcefclk != clock) {
+	if (clock && smu10_data->deep_sleep_dcefclk != clock) {
 		smu10_data->deep_sleep_dcefclk = clock;
 		smum_send_msg_to_smc_with_parameter(hwmgr,
 					PPSMC_MSG_SetMinDeepSleepDcefclk,
@@ -223,8 +222,7 @@
 {
 	struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
 
-	if (smu10_data->dcf_actual_hard_min_freq &&
-		smu10_data->dcf_actual_hard_min_freq != clock) {
+	if (clock && smu10_data->dcf_actual_hard_min_freq != clock) {
 		smu10_data->dcf_actual_hard_min_freq = clock;
 		smum_send_msg_to_smc_with_parameter(hwmgr,
 					PPSMC_MSG_SetHardMinDcefclkByFreq,
@@ -237,8 +235,7 @@
 {
 	struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
 
-	if (smu10_data->f_actual_hard_min_freq &&
-		smu10_data->f_actual_hard_min_freq != clock) {
+	if (clock && smu10_data->f_actual_hard_min_freq != clock) {
 		smu10_data->f_actual_hard_min_freq = clock;
 		smum_send_msg_to_smc_with_parameter(hwmgr,
 					PPSMC_MSG_SetHardMinFclkByFreq,
@@ -1026,12 +1023,15 @@
 
 	clocks->num_levels = 0;
 	for (i = 0; i < pclk_vol_table->count; i++) {
-		clocks->data[i].clocks_in_khz = pclk_vol_table->entries[i].clk * 10;
-		clocks->data[i].latency_in_us = latency_required ?
-						smu10_get_mem_latency(hwmgr,
-						pclk_vol_table->entries[i].clk) :
-						0;
-		clocks->num_levels++;
+		if (pclk_vol_table->entries[i].clk) {
+			clocks->data[clocks->num_levels].clocks_in_khz =
+				pclk_vol_table->entries[i].clk * 10;
+			clocks->data[clocks->num_levels].latency_in_us = latency_required ?
+				smu10_get_mem_latency(hwmgr,
+						      pclk_vol_table->entries[i].clk) :
+				0;
+			clocks->num_levels++;
+		}
 	}
 
 	return 0;
@@ -1077,9 +1077,11 @@
 
 	clocks->num_levels = 0;
 	for (i = 0; i < pclk_vol_table->count; i++) {
-		clocks->data[i].clocks_in_khz = pclk_vol_table->entries[i].clk  * 10;
-		clocks->data[i].voltage_in_mv = pclk_vol_table->entries[i].vol;
-		clocks->num_levels++;
+		if (pclk_vol_table->entries[i].clk) {
+			clocks->data[clocks->num_levels].clocks_in_khz = pclk_vol_table->entries[i].clk  * 10;
+			clocks->data[clocks->num_levels].voltage_in_mv = pclk_vol_table->entries[i].vol;
+			clocks->num_levels++;
+		}
 	}
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
@@ -1533,6 +1533,10 @@
 	PP_ASSERT_WITH_CODE((tmp_result == 0),
 			"Failed to reset to default!", result = tmp_result);
 
+	tmp_result = smum_stop_smc(hwmgr);
+	PP_ASSERT_WITH_CODE((tmp_result == 0),
+			"Failed to stop smc!", result = tmp_result);
+
 	tmp_result = smu7_force_switch_to_arbf0(hwmgr);
 	PP_ASSERT_WITH_CODE((tmp_result == 0),
 			"Failed to force to switch arbf0!", result = tmp_result);
@@ -2864,7 +2868,7 @@
 		if (hwmgr->is_kicker)
 			switch_limit_us = data->is_memory_gddr5 ? 450 : 150;
 		else
-			switch_limit_us = data->is_memory_gddr5 ? 190 : 150;
+			switch_limit_us = data->is_memory_gddr5 ? 200 : 150;
 		break;
 	case CHIP_VEGAM:
 		switch_limit_us = 30;
@@ -3575,7 +3579,8 @@
 	case AMDGPU_PP_SENSOR_GPU_POWER:
 		return smu7_get_gpu_power(hwmgr, (uint32_t *)value);
 	case AMDGPU_PP_SENSOR_VDDGFX:
-		if ((data->vr_config & 0xff) == 0x2)
+		if ((data->vr_config & VRCONF_VDDGFX_MASK) ==
+		    (VR_SVI2_PLANE_2 << VRCONF_VDDGFX_SHIFT))
 			val_vid = PHM_READ_INDIRECT_FIELD(hwmgr->device,
 					CGS_IND_REG__SMC, PWR_SVI2_STATUS, PLANE2_VID);
 		else
@@ -3805,9 +3810,12 @@
 {
 	uint32_t i;
 
+	/* force the trim if mclk_switching is disabled to prevent flicker */
+	bool force_trim = (low_limit == high_limit);
 	for (i = 0; i < dpm_table->count; i++) {
 	/*skip the trim if od is enabled*/
-		if (!hwmgr->od_enabled && (dpm_table->dpm_levels[i].value < low_limit
+		if ((!hwmgr->od_enabled || force_trim)
+			&& (dpm_table->dpm_levels[i].value < low_limit
 			|| dpm_table->dpm_levels[i].value > high_limit))
 			dpm_table->dpm_levels[i].enabled = false;
 		else
@@ -3983,6 +3991,13 @@
 			"Failed to populate and upload SCLK MCLK DPM levels!",
 			result = tmp_result);
 
+	/*
+	 * If a custom pp table is loaded, set DPMTABLE_OD_UPDATE_VDDC flag.
+	 * That effectively disables AVFS feature.
+	 */
+	if (hwmgr->hardcode_pp_table != NULL)
+		data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_VDDC;
+
 	tmp_result = smu7_update_avfs(hwmgr);
 	PP_ASSERT_WITH_CODE((0 == tmp_result),
 			"Failed to update avfs voltages!",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
@@ -3691,6 +3691,13 @@
 	PP_ASSERT_WITH_CODE(!result,
 			"Failed to upload PPtable!", return result);
 
+	/*
+	 * If a custom pp table is loaded, set DPMTABLE_OD_UPDATE_VDDC flag.
+	 * That effectively disables AVFS feature.
+	 */
+	if(hwmgr->hardcode_pp_table != NULL)
+		data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_VDDC;
+
 	vega10_update_avfs(hwmgr);
 
 	/*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c
@@ -364,17 +364,29 @@
 static int vega10_thermal_set_temperature_range(struct pp_hwmgr *hwmgr,
 		struct PP_TemperatureRange *range)
 {
+	struct phm_ppt_v2_information *pp_table_info =
+		(struct phm_ppt_v2_information *)(hwmgr->pptable);
+	struct phm_tdp_table *tdp_table = pp_table_info->tdp_table;
 	struct amdgpu_device *adev = hwmgr->adev;
-	int low = VEGA10_THERMAL_MINIMUM_ALERT_TEMP *
-			PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
-	int high = VEGA10_THERMAL_MAXIMUM_ALERT_TEMP *
-			PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
+	int low = VEGA10_THERMAL_MINIMUM_ALERT_TEMP;
+	int high = VEGA10_THERMAL_MAXIMUM_ALERT_TEMP;
 	uint32_t val;
 
-	if (low < range->min)
-		low = range->min;
-	if (high > range->max)
-		high = range->max;
+	/* compare them in unit celsius degree */
+	if (low < range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)
+		low = range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
+
+	/*
+	 * As a common sense, usSoftwareShutdownTemp should be bigger
+	 * than ThotspotLimit. For any invalid usSoftwareShutdownTemp,
+	 * we will just use the max possible setting VEGA10_THERMAL_MAXIMUM_ALERT_TEMP
+	 * to avoid false alarms.
+	 */
+	if ((tdp_table->usSoftwareShutdownTemp >
+	     range->hotspot_crit_max / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)) {
+		if (high > tdp_table->usSoftwareShutdownTemp)
+			high = tdp_table->usSoftwareShutdownTemp;
+	}
 
 	if (low > high)
 		return -EINVAL;
@@ -383,8 +395,8 @@
 
 	val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5);
 	val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1);
-	val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES));
-	val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES));
+	val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, high);
+	val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, low);
 	val &= (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK) &
 			(~THM_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK) &
 			(~THM_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_thermal.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_thermal.c
@@ -170,17 +170,18 @@
 static int vega12_thermal_set_temperature_range(struct pp_hwmgr *hwmgr,
 		struct PP_TemperatureRange *range)
 {
+	struct phm_ppt_v3_information *pptable_information =
+		(struct phm_ppt_v3_information *)hwmgr->pptable;
 	struct amdgpu_device *adev = hwmgr->adev;
-	int low = VEGA12_THERMAL_MINIMUM_ALERT_TEMP *
-			PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
-	int high = VEGA12_THERMAL_MAXIMUM_ALERT_TEMP *
-			PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
+	int low = VEGA12_THERMAL_MINIMUM_ALERT_TEMP;
+	int high = VEGA12_THERMAL_MAXIMUM_ALERT_TEMP;
 	uint32_t val;
 
-	if (low < range->min)
-		low = range->min;
-	if (high > range->max)
-		high = range->max;
+	/* compare them in unit celsius degree */
+	if (low < range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)
+		low = range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
+	if (high > pptable_information->us_software_shutdown_temp)
+		high = pptable_information->us_software_shutdown_temp;
 
 	if (low > high)
 		return -EINVAL;
@@ -189,8 +190,8 @@
 
 	val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5);
 	val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1);
-	val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES));
-	val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES));
+	val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, high);
+	val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, low);
 	val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK);
 
 	WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_baco.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_baco.c
@@ -29,7 +29,7 @@
 #include "vega20_baco.h"
 #include "vega20_smumgr.h"
 
-
+#include "amdgpu_ras.h"
 
 static const struct soc15_baco_cmd_entry clean_baco_tbl[] =
 {
@@ -74,6 +74,7 @@
 int vega20_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state)
 {
 	struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev);
+	struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
 	enum BACO_STATE cur_state;
 	uint32_t data;
 
@@ -84,10 +85,11 @@
 		return 0;
 
 	if (state == BACO_STATE_IN) {
-		data = RREG32_SOC15(THM, 0, mmTHM_BACO_CNTL);
-		data |= 0x80000000;
-		WREG32_SOC15(THM, 0, mmTHM_BACO_CNTL, data);
-
+		if (!ras || !ras->supported) {
+			data = RREG32_SOC15(THM, 0, mmTHM_BACO_CNTL);
+			data |= 0x80000000;
+			WREG32_SOC15(THM, 0, mmTHM_BACO_CNTL, data);
+		}
 
 		if(smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_EnterBaco, 0))
 			return -EINVAL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
@@ -981,27 +981,15 @@
 {
 	struct vega20_hwmgr *data =
 			(struct vega20_hwmgr *)(hwmgr->backend);
-	uint64_t features_enabled;
-	int i;
-	bool enabled;
-	int ret = 0;
+	int i, ret = 0;
 
 	PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr,
 			PPSMC_MSG_DisableAllSmuFeatures)) == 0,
 			"[DisableAllSMUFeatures] Failed to disable all smu features!",
 			return ret);
 
-	ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled);
-	PP_ASSERT_WITH_CODE(!ret,
-			"[DisableAllSMUFeatures] Failed to get enabled smc features!",
-			return ret);
-
-	for (i = 0; i < GNLD_FEATURES_MAX; i++) {
-		enabled = (features_enabled & data->smu_features[i].smu_feature_bitmap) ?
-			true : false;
-		data->smu_features[i].enabled = enabled;
-		data->smu_features[i].supported = enabled;
-	}
+	for (i = 0; i < GNLD_FEATURES_MAX; i++)
+		data->smu_features[i].enabled = 0;
 
 	return 0;
 }
@@ -1652,12 +1640,6 @@
 
 	data->uvd_power_gated = true;
 	data->vce_power_gated = true;
-
-	if (data->smu_features[GNLD_DPM_UVD].enabled)
-		data->uvd_power_gated = false;
-
-	if (data->smu_features[GNLD_DPM_VCE].enabled)
-		data->vce_power_gated = false;
 }
 
 static int vega20_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
@@ -2912,7 +2894,8 @@
 			data->od8_settings.od8_settings_array;
 	OverDriveTable_t *od_table =
 			&(data->smc_state_table.overdrive_table);
-	int32_t input_index, input_clk, input_vol, i;
+	int32_t input_clk, input_vol, i;
+	uint32_t input_index;
 	int od8_id;
 	int ret;
 
@@ -3211,10 +3194,11 @@
 
 static int vega20_set_ppfeature_status(struct pp_hwmgr *hwmgr, uint64_t new_ppfeature_masks)
 {
-	uint64_t features_enabled;
-	uint64_t features_to_enable;
-	uint64_t features_to_disable;
-	int ret = 0;
+	struct vega20_hwmgr *data =
+			(struct vega20_hwmgr *)(hwmgr->backend);
+	uint64_t features_enabled, features_to_enable, features_to_disable;
+	int i, ret = 0;
+	bool enabled;
 
 	if (new_ppfeature_masks >= (1ULL << GNLD_FEATURES_MAX))
 		return -EINVAL;
@@ -3243,6 +3227,17 @@
 			return ret;
 	}
 
+	/* Update the cached feature enablement state */
+	ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < GNLD_FEATURES_MAX; i++) {
+		enabled = (features_enabled & data->smu_features[i].smu_feature_bitmap) ?
+			true : false;
+		data->smu_features[i].enabled = enabled;
+	}
+
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.c
@@ -240,17 +240,18 @@
 static int vega20_thermal_set_temperature_range(struct pp_hwmgr *hwmgr,
 		struct PP_TemperatureRange *range)
 {
+	struct phm_ppt_v3_information *pptable_information =
+		(struct phm_ppt_v3_information *)hwmgr->pptable;
 	struct amdgpu_device *adev = hwmgr->adev;
-	int low = VEGA20_THERMAL_MINIMUM_ALERT_TEMP *
-			PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
-	int high = VEGA20_THERMAL_MAXIMUM_ALERT_TEMP *
-			PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
+	int low = VEGA20_THERMAL_MINIMUM_ALERT_TEMP;
+	int high = VEGA20_THERMAL_MAXIMUM_ALERT_TEMP;
 	uint32_t val;
 
-	if (low < range->min)
-		low = range->min;
-	if (high > range->max)
-		high = range->max;
+	/* compare them in unit celsius degree */
+	if (low < range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)
+		low = range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
+	if (high > pptable_information->us_software_shutdown_temp)
+		high = pptable_information->us_software_shutdown_temp;
 
 	if (low > high)
 		return -EINVAL;
@@ -259,8 +260,8 @@
 
 	val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5);
 	val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1);
-	val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES));
-	val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES));
+	val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, high);
+	val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, low);
 	val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK);
 
 	WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
@@ -345,6 +345,7 @@
 	const struct pptable_funcs	*ppt_funcs;
 	struct mutex			mutex;
 	struct mutex			sensor_lock;
+	struct mutex			metrics_lock;
 	uint64_t pool_size;
 
 	struct smu_table_context	smu_table;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
@@ -229,6 +229,7 @@
 	bool (*is_hw_avfs_present)(struct pp_hwmgr  *hwmgr);
 	int (*update_dpm_settings)(struct pp_hwmgr *hwmgr, void *profile_setting);
 	int (*smc_table_manager)(struct pp_hwmgr *hwmgr, uint8_t *table, uint16_t table_id, bool rw); /*rw: true for read, false for write */
+	int (*stop_smc)(struct pp_hwmgr *hwmgr);
 };
 
 struct pp_hwmgr_func {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/powerplay/inc/smumgr.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/powerplay/inc/smumgr.h
@@ -114,4 +114,6 @@
 
 extern int smum_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table, uint16_t table_id, bool rw);
 
+extern int smum_stop_smc(struct pp_hwmgr *hwmgr);
+
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
@@ -547,17 +547,20 @@
 	struct smu_table_context *smu_table= &smu->smu_table;
 	int ret = 0;
 
+	mutex_lock(&smu->metrics_lock);
 	if (!smu_table->metrics_time || time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(100))) {
 		ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0,
 				(void *)smu_table->metrics_table, false);
 		if (ret) {
 			pr_info("Failed to export SMU metrics table!\n");
+			mutex_unlock(&smu->metrics_lock);
 			return ret;
 		}
 		smu_table->metrics_time = jiffies;
 	}
 
 	memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t));
+	mutex_unlock(&smu->metrics_lock);
 
 	return ret;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/powerplay/renoir_ppt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/powerplay/renoir_ppt.c
@@ -183,11 +183,14 @@
 	int i, size = 0, ret = 0;
 	uint32_t cur_value = 0, value = 0, count = 0, min = 0, max = 0;
 	DpmClocks_t *clk_table = smu->smu_table.clocks_table;
-	SmuMetrics_t metrics = {0};
+	SmuMetrics_t metrics;
+	bool cur_value_match_level = false;
 
 	if (!clk_table || clk_type >= SMU_CLK_COUNT)
 		return -EINVAL;
 
+	memset(&metrics, 0, sizeof(metrics));
+
 	ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0,
 			       (void *)&metrics, false);
 	if (ret)
@@ -241,8 +244,13 @@
 		GET_DPM_CUR_FREQ(clk_table, clk_type, i, value);
 		size += sprintf(buf + size, "%d: %uMhz %s\n", i, value,
 				cur_value == value ? "*" : "");
+		if (cur_value == value)
+			cur_value_match_level = true;
 	}
 
+	if (!cur_value_match_level)
+		size += sprintf(buf + size, "   %uMhz *\n", cur_value);
+
 	return size;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/powerplay/renoir_ppt.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/powerplay/renoir_ppt.h
@@ -37,7 +37,7 @@
 			freq = table->SocClocks[dpm_level].Freq;	\
 			break;						\
 		case SMU_MCLK:						\
-			freq = table->MemClocks[dpm_level].Freq;	\
+			freq = table->FClocks[dpm_level].Freq;	\
 			break;						\
 		case SMU_DCEFCLK:					\
 			freq = table->DcfClocks[dpm_level].Freq;	\
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
@@ -46,10 +46,8 @@
 #include "asic_reg/smuio/smuio_11_0_0_sh_mask.h"
 
 MODULE_FIRMWARE("amdgpu/vega20_smc.bin");
-MODULE_FIRMWARE("amdgpu/arcturus_smc.bin");
 MODULE_FIRMWARE("amdgpu/navi10_smc.bin");
 MODULE_FIRMWARE("amdgpu/navi14_smc.bin");
-MODULE_FIRMWARE("amdgpu/navi12_smc.bin");
 
 #define SMU11_VOLTAGE_SCALE 4
 
@@ -171,7 +169,8 @@
 		chip_name = "navi12";
 		break;
 	default:
-		BUG();
+		dev_err(adev->dev, "Unsupported ASIC type %d\n", adev->asic_type);
+		return -EINVAL;
 	}
 
 	snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_smc.bin", chip_name);
@@ -988,8 +987,12 @@
 	struct smu_11_0_max_sustainable_clocks *max_sustainable_clocks;
 	int ret = 0;
 
-	max_sustainable_clocks = kzalloc(sizeof(struct smu_11_0_max_sustainable_clocks),
+	if (!smu->smu_table.max_sustainable_clocks)
+		max_sustainable_clocks = kzalloc(sizeof(struct smu_11_0_max_sustainable_clocks),
 					 GFP_KERNEL);
+	else
+		max_sustainable_clocks = smu->smu_table.max_sustainable_clocks;
+
 	smu->smu_table.max_sustainable_clocks = (void *)max_sustainable_clocks;
 
 	max_sustainable_clocks->uclock = smu->smu_table.boot_values.uclk / 100;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c
@@ -239,7 +239,7 @@
 
 	switch (dev_id) {
 	case 0x67BA:
-	case 0x66B1:
+	case 0x67B1:
 		smu_data->power_tune_defaults = &defaults_hawaii_pro;
 		break;
 	case 0x67B8:
@@ -2933,6 +2933,29 @@
 	return 0;
 }
 
+static void ci_reset_smc(struct pp_hwmgr *hwmgr)
+{
+	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+				  SMC_SYSCON_RESET_CNTL,
+				  rst_reg, 1);
+}
+
+
+static void ci_stop_smc_clock(struct pp_hwmgr *hwmgr)
+{
+	PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
+				  SMC_SYSCON_CLOCK_CNTL_0,
+				  ck_disable, 1);
+}
+
+static int ci_stop_smc(struct pp_hwmgr *hwmgr)
+{
+	ci_reset_smc(hwmgr);
+	ci_stop_smc_clock(hwmgr);
+
+	return 0;
+}
+
 const struct pp_smumgr_func ci_smu_funcs = {
 	.name = "ci_smu",
 	.smu_init = ci_smu_init,
@@ -2957,4 +2980,5 @@
 	.is_dpm_running = ci_is_dpm_running,
 	.update_dpm_settings = ci_update_dpm_settings,
 	.update_smc_table = ci_update_smc_table,
+	.stop_smc = ci_stop_smc,
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c
@@ -217,3 +217,11 @@
 
 	return -EINVAL;
 }
+
+int smum_stop_smc(struct pp_hwmgr *hwmgr)
+{
+	if (hwmgr->smumgr_funcs->stop_smc)
+		return hwmgr->smumgr_funcs->stop_smc(hwmgr);
+
+	return 0;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/powerplay/smumgr/vegam_smumgr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/powerplay/smumgr/vegam_smumgr.c
@@ -642,9 +642,6 @@
 
 	/* sclk is bigger than max sclk in the dependence table */
 	*voltage |= (dep_table->entries[i - 1].vddc * VOLTAGE_SCALE) << VDDC_SHIFT;
-	vddci = phm_find_closest_vddci(&(data->vddci_voltage_table),
-			(dep_table->entries[i - 1].vddc -
-					(uint16_t)VDDC_VDDCI_DELTA));
 
 	if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control)
 		*voltage |= (data->vbios_boot_state.vddci_bootup_value *
@@ -652,8 +649,13 @@
 	else if (dep_table->entries[i - 1].vddci)
 		*voltage |= (dep_table->entries[i - 1].vddci *
 				VOLTAGE_SCALE) << VDDC_SHIFT;
-	else
+	else {
+		vddci = phm_find_closest_vddci(&(data->vddci_voltage_table),
+				(dep_table->entries[i - 1].vddc -
+						(uint16_t)VDDC_VDDCI_DELTA));
+
 		*voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT;
+	}
 
 	if (SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control)
 		*mvdd = data->vbios_boot_state.mvdd_bootup_value * VOLTAGE_SCALE;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/amd/powerplay/vega20_ppt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/amd/powerplay/vega20_ppt.c
@@ -1691,17 +1691,20 @@
 	struct smu_table_context *smu_table= &smu->smu_table;
 	int ret = 0;
 
+	mutex_lock(&smu->metrics_lock);
 	if (!smu_table->metrics_time || time_after(jiffies, smu_table->metrics_time + HZ / 1000)) {
 		ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0,
 				(void *)smu_table->metrics_table, false);
 		if (ret) {
 			pr_info("Failed to export SMU metrics table!\n");
+			mutex_unlock(&smu->metrics_lock);
 			return ret;
 		}
 		smu_table->metrics_time = jiffies;
 	}
 
 	memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t));
+	mutex_unlock(&smu->metrics_lock);
 
 	return ret;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
@@ -250,6 +250,7 @@
 {
 	komeda_crtc_prepare(to_kcrtc(crtc));
 	drm_crtc_vblank_on(crtc);
+	WARN_ON(drm_crtc_vblank_get(crtc));
 	komeda_crtc_do_flush(crtc, old);
 }
 
@@ -319,6 +320,7 @@
 		}
 	}
 
+	drm_crtc_vblank_put(crtc);
 	drm_crtc_vblank_off(crtc);
 	komeda_crtc_unprepare(kcrtc);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
@@ -148,6 +148,7 @@
 	struct drm_plane *plane;
 	struct list_head zorder_list;
 	int order = 0, err;
+	u32 slave_zpos = 0;
 
 	DRM_DEBUG_ATOMIC("[CRTC:%d:%s] calculating normalized zpos values\n",
 			 crtc->base.id, crtc->name);
@@ -187,10 +188,13 @@
 				 plane_st->zpos, plane_st->normalized_zpos);
 
 		/* calculate max slave zorder */
-		if (has_bit(drm_plane_index(plane), kcrtc->slave_planes))
+		if (has_bit(drm_plane_index(plane), kcrtc->slave_planes)) {
+			slave_zpos = plane_st->normalized_zpos;
+			if (to_kplane_st(plane_st)->layer_split)
+				slave_zpos++;
 			kcrtc_st->max_slave_zorder =
-				max(plane_st->normalized_zpos,
-				    kcrtc_st->max_slave_zorder);
+				max(slave_zpos, kcrtc_st->max_slave_zorder);
+		}
 	}
 
 	crtc_st->zpos_changed = true;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c
@@ -259,7 +259,7 @@
 	u32 avail_scalers;
 
 	pipe_st = komeda_pipeline_get_state(c->pipeline, state);
-	if (!pipe_st)
+	if (IS_ERR_OR_NULL(pipe_st))
 		return NULL;
 
 	avail_scalers = (pipe_st->active_comps & KOMEDA_PIPELINE_SCALERS) ^
@@ -1171,7 +1171,7 @@
 	return 0;
 }
 
-static void
+static int
 komeda_pipeline_unbound_components(struct komeda_pipeline *pipe,
 				   struct komeda_pipeline_state *new)
 {
@@ -1190,8 +1190,12 @@
 		c = komeda_pipeline_get_component(pipe, id);
 		c_st = komeda_component_get_state_and_set_user(c,
 				drm_st, NULL, new->crtc);
+		if (PTR_ERR(c_st) == -EDEADLK)
+			return -EDEADLK;
 		WARN_ON(IS_ERR(c_st));
 	}
+
+	return 0;
 }
 
 /* release unclaimed pipeline resource */
@@ -1213,9 +1217,8 @@
 	if (WARN_ON(IS_ERR_OR_NULL(st)))
 		return -EINVAL;
 
-	komeda_pipeline_unbound_components(pipe, st);
+	return komeda_pipeline_unbound_components(pipe, st);
 
-	return 0;
 }
 
 void komeda_pipeline_disable(struct komeda_pipeline *pipe,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/arm/display/komeda/komeda_plane.c
@@ -264,6 +264,10 @@
 
 	formats = komeda_get_layer_fourcc_list(&mdev->fmt_tbl,
 					       layer->layer_type, &n_formats);
+	if (!formats) {
+		kfree(kplane);
+		return -ENOMEM;
+	}
 
 	err = drm_universal_plane_init(&kms->base, plane,
 			get_possible_crtcs(kms, c->pipeline),
@@ -274,8 +278,10 @@
 
 	komeda_put_fourcc_list(formats);
 
-	if (err)
-		goto cleanup;
+	if (err) {
+		kfree(kplane);
+		return err;
+	}
 
 	drm_plane_helper_add(plane, &komeda_plane_helper_funcs);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/arm/display/komeda/komeda_wb_connector.c
@@ -159,6 +159,10 @@
 	formats = komeda_get_layer_fourcc_list(&mdev->fmt_tbl,
 					       kwb_conn->wb_layer->layer_type,
 					       &n_formats);
+	if (!formats) {
+		kfree(kwb_conn);
+		return -ENOMEM;
+	}
 
 	err = drm_writeback_connector_init(&kms->base, wb_conn,
 					   &komeda_wb_connector_funcs,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/arm/malidp_crtc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/arm/malidp_crtc.c
@@ -483,7 +483,10 @@
 	if (crtc->state)
 		malidp_crtc_destroy_state(crtc, crtc->state);
 
-	__drm_atomic_helper_crtc_reset(crtc, &state->base);
+	if (state)
+		__drm_atomic_helper_crtc_reset(crtc, &state->base);
+	else
+		__drm_atomic_helper_crtc_reset(crtc, NULL);
 }
 
 static int malidp_crtc_enable_vblank(struct drm_crtc *crtc)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/arm/malidp_mw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/arm/malidp_mw.c
@@ -56,7 +56,7 @@
 	return MODE_OK;
 }
 
-const struct drm_connector_helper_funcs malidp_mw_connector_helper_funcs = {
+static const struct drm_connector_helper_funcs malidp_mw_connector_helper_funcs = {
 	.get_modes = malidp_mw_connector_get_modes,
 	.mode_valid = malidp_mw_connector_mode_valid,
 };
@@ -70,7 +70,10 @@
 		__drm_atomic_helper_connector_destroy_state(connector->state);
 
 	kfree(connector->state);
-	__drm_atomic_helper_connector_reset(connector, &mw_state->base);
+	connector->state = NULL;
+
+	if (mw_state)
+		__drm_atomic_helper_connector_reset(connector, &mw_state->base);
 }
 
 static enum drm_connector_status
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/arm/malidp_planes.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/arm/malidp_planes.c
@@ -348,7 +348,7 @@
 		else
 			sgt = obj->dev->driver->gem_prime_get_sg_table(obj);
 
-		if (!sgt)
+		if (IS_ERR(sgt))
 			return false;
 
 		sgl = sgt->sgl;
@@ -922,13 +922,18 @@
 	.atomic_disable = malidp_de_plane_disable,
 };
 
+static const uint64_t linear_only_modifiers[] = {
+	DRM_FORMAT_MOD_LINEAR,
+	DRM_FORMAT_MOD_INVALID
+};
+
 int malidp_de_planes_init(struct drm_device *drm)
 {
 	struct malidp_drm *malidp = drm->dev_private;
 	const struct malidp_hw_regmap *map = &malidp->dev->hw->map;
 	struct malidp_plane *plane = NULL;
 	enum drm_plane_type plane_type;
-	unsigned long crtcs = 1 << drm->mode_config.num_crtc;
+	unsigned long crtcs = BIT(drm->mode_config.num_crtc);
 	unsigned long flags = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_180 |
 			      DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y;
 	unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) |
@@ -985,8 +990,8 @@
 		 */
 		ret = drm_universal_plane_init(drm, &plane->base, crtcs,
 				&malidp_de_plane_funcs, formats, n,
-				(id == DE_SMART) ? NULL : modifiers, plane_type,
-				NULL);
+				(id == DE_SMART) ? linear_only_modifiers : modifiers,
+				plane_type, NULL);
 
 		if (ret < 0)
 			goto cleanup;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/armada/armada_overlay.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/armada/armada_overlay.c
@@ -4,6 +4,8 @@
  *  Rewritten from the dovefb driver, and Armada510 manuals.
  */
 
+#include <linux/bitfield.h>
+
 #include <drm/armada_drm.h>
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
@@ -446,8 +448,8 @@
 			     drm_to_overlay_state(state)->colorkey_ug,
 			     drm_to_overlay_state(state)->colorkey_vb, 0);
 	} else if (property == priv->colorkey_mode_prop) {
-		*val = (drm_to_overlay_state(state)->colorkey_mode &
-			CFG_CKMODE_MASK) >> ffs(CFG_CKMODE_MASK);
+		*val = FIELD_GET(CFG_CKMODE_MASK,
+				 drm_to_overlay_state(state)->colorkey_mode);
 	} else if (property == priv->brightness_prop) {
 		*val = drm_to_overlay_state(state)->brightness + 256;
 	} else if (property == priv->contrast_prop) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/aspeed/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/aspeed/Kconfig
@@ -3,6 +3,7 @@
 	tristate "ASPEED BMC Display Controller"
 	depends on DRM && OF
 	depends on (COMPILE_TEST || ARCH_ASPEED)
+	depends on MMU
 	select DRM_KMS_HELPER
 	select DRM_KMS_CMA_HELPER
 	select DMA_CMA if HAVE_DMA_CONTIGUOUS
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/ast/ast_post.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/ast/ast_post.c
@@ -294,7 +294,7 @@
 				;
 			} while (ast_read32(ast, 0x10100) != 0xa8);
 		} else {/* AST2100/1100 */
-			if (ast->chip == AST2100 || ast->chip == 2200)
+			if (ast->chip == AST2100 || ast->chip == AST2200)
 				dram_reg_info = ast2100_dram_table_data;
 			else
 				dram_reg_info = ast1100_dram_table_data;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
@@ -73,7 +73,11 @@
 	unsigned long prate;
 	unsigned int mask = ATMEL_HLCDC_CLKDIV_MASK | ATMEL_HLCDC_CLKPOL;
 	unsigned int cfg = 0;
-	int div;
+	int div, ret;
+
+	ret = clk_prepare_enable(crtc->dc->hlcdc->sys_clk);
+	if (ret)
+		return;
 
 	vm.vfront_porch = adj->crtc_vsync_start - adj->crtc_vdisplay;
 	vm.vback_porch = adj->crtc_vtotal - adj->crtc_vsync_end;
@@ -95,14 +99,14 @@
 		     (adj->crtc_hdisplay - 1) |
 		     ((adj->crtc_vdisplay - 1) << 16));
 
+	prate = clk_get_rate(crtc->dc->hlcdc->sys_clk);
+	mode_rate = adj->crtc_clock * 1000;
 	if (!crtc->dc->desc->fixed_clksrc) {
+		prate *= 2;
 		cfg |= ATMEL_HLCDC_CLKSEL;
 		mask |= ATMEL_HLCDC_CLKSEL;
 	}
 
-	prate = 2 * clk_get_rate(crtc->dc->hlcdc->sys_clk);
-	mode_rate = adj->crtc_clock * 1000;
-
 	div = DIV_ROUND_UP(prate, mode_rate);
 	if (div < 2) {
 		div = 2;
@@ -117,8 +121,8 @@
 		int div_low = prate / mode_rate;
 
 		if (div_low >= 2 &&
-		    ((prate / div_low - mode_rate) <
-		     10 * (mode_rate - prate / div)))
+		    (10 * (prate / div_low - mode_rate) <
+		     (mode_rate - prate / div)))
 			/*
 			 * At least 10 times better when using a higher
 			 * frequency than requested, instead of a lower.
@@ -147,6 +151,8 @@
 			   ATMEL_HLCDC_VSPSU | ATMEL_HLCDC_VSPHO |
 			   ATMEL_HLCDC_GUARDTIME_MASK | ATMEL_HLCDC_MODE_MASK,
 			   cfg);
+
+	clk_disable_unprepare(crtc->dc->hlcdc->sys_clk);
 }
 
 static enum drm_mode_status
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/bochs/bochs_hw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/bochs/bochs_hw.c
@@ -156,10 +156,8 @@
 		size = min(size, mem);
 	}
 
-	if (pci_request_region(pdev, 0, "bochs-drm") != 0) {
-		DRM_ERROR("Cannot request framebuffer\n");
-		return -EBUSY;
-	}
+	if (pci_request_region(pdev, 0, "bochs-drm") != 0)
+		DRM_WARN("Cannot request framebuffer, boot fb still active?\n");
 
 	bochs->fb_map = ioremap(addr, size);
 	if (bochs->fb_map == NULL) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/bochs/bochs_kms.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/bochs/bochs_kms.c
@@ -194,6 +194,7 @@
 	bochs->dev->mode_config.preferred_depth = 24;
 	bochs->dev->mode_config.prefer_shadow = 0;
 	bochs->dev->mode_config.prefer_shadow_fbdev = 1;
+	bochs->dev->mode_config.fbdev_use_iomem = true;
 	bochs->dev->mode_config.quirk_addfb_prefer_host_byte_order = true;
 
 	bochs->dev->mode_config.funcs = &bochs_mode_funcs;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/bridge/adv7511/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/bridge/adv7511/Makefile
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
-adv7511-y := adv7511_drv.o
-adv7511-$(CONFIG_DRM_I2C_ADV7511_AUDIO) += adv7511_audio.o
-adv7511-$(CONFIG_DRM_I2C_ADV7511_CEC) += adv7511_cec.o
-adv7511-$(CONFIG_DRM_I2C_ADV7533) += adv7533.o
-obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511.o
+adv7511_drm-y := adv7511_drv.o
+adv7511_drm-$(CONFIG_DRM_I2C_ADV7511_AUDIO) += adv7511_audio.o
+adv7511_drm-$(CONFIG_DRM_I2C_ADV7511_CEC) += adv7511_cec.o
+adv7511_drm-$(CONFIG_DRM_I2C_ADV7533) += adv7533.o
+obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511_drm.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/bridge/adv7511/adv7511.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/bridge/adv7511/adv7511.h
@@ -384,10 +384,7 @@
 #else
 static inline int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511)
 {
-	unsigned int offset = adv7511->type == ADV7533 ?
-						ADV7533_REG_CEC_OFFSET : 0;
-
-	regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset,
+	regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL,
 		     ADV7511_CEC_CTRL_POWER_DOWN);
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c
@@ -19,13 +19,15 @@
 {
 	switch (fs) {
 	case 32000:
-		*n = 4096;
+	case 48000:
+	case 96000:
+	case 192000:
+		*n = fs * 128 / 1000;
 		break;
 	case 44100:
-		*n = 6272;
-		break;
-	case 48000:
-		*n = 6144;
+	case 88200:
+	case 176400:
+		*n = fs * 128 / 900;
 		break;
 	}
 
@@ -119,6 +121,9 @@
 		audio_source = ADV7511_AUDIO_SOURCE_I2S;
 		i2s_format = ADV7511_I2S_FORMAT_LEFT_J;
 		break;
+	case HDMI_SPDIF:
+		audio_source = ADV7511_AUDIO_SOURCE_SPDIF;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -142,7 +147,16 @@
 			   ADV7511_AUDIO_CFG3_LEN_MASK, len);
 	regmap_update_bits(adv7511->regmap, ADV7511_REG_I2C_FREQ_ID_CFG,
 			   ADV7511_I2C_FREQ_ID_CFG_RATE_MASK, rate << 4);
-	regmap_write(adv7511->regmap, 0x73, 0x1);
+
+	/* send current Audio infoframe values while updating */
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_INFOFRAME_UPDATE,
+			   BIT(5), BIT(5));
+
+	regmap_write(adv7511->regmap, ADV7511_REG_AUDIO_INFOFRAME(0), 0x1);
+
+	/* use Audio infoframe updated info */
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_INFOFRAME_UPDATE,
+			   BIT(5), 0);
 
 	return 0;
 }
@@ -173,13 +187,24 @@
 	regmap_update_bits(adv7511->regmap, ADV7511_REG_GC(0),
 				BIT(7) | BIT(6), BIT(7));
 	/* use Audio infoframe updated info */
-	regmap_update_bits(adv7511->regmap, ADV7511_REG_GC(1),
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_INFOFRAME_UPDATE,
 				BIT(5), 0);
+
+	/* enable SPDIF receiver */
+	if (adv7511->audio_source == ADV7511_AUDIO_SOURCE_SPDIF)
+		regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CONFIG,
+				   BIT(7), BIT(7));
+
 	return 0;
 }
 
 static void audio_shutdown(struct device *dev, void *data)
 {
+	struct adv7511 *adv7511 = dev_get_drvdata(dev);
+
+	if (adv7511->audio_source == ADV7511_AUDIO_SOURCE_SPDIF)
+		regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CONFIG,
+				   BIT(7), 0);
 }
 
 static int adv7511_hdmi_i2s_get_dai_id(struct snd_soc_component *component,
@@ -213,6 +238,7 @@
 	.ops = &adv7511_codec_ops,
 	.max_i2s_channels = 2,
 	.i2s = 1,
+	.spdif = 1,
 };
 
 int adv7511_audio_init(struct device *dev, struct adv7511 *adv7511)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c
@@ -316,7 +316,7 @@
 		goto err_cec_alloc;
 	}
 
-	regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset, 0);
+	regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL, 0);
 	/* cec soft reset */
 	regmap_write(adv7511->regmap_cec,
 		     ADV7511_REG_CEC_SOFT_RESET + offset, 0x01);
@@ -343,7 +343,7 @@
 	dev_info(dev, "Initializing CEC failed with error %d, disabling CEC\n",
 		 ret);
 err_cec_parse_dt:
-	regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset,
+	regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL,
 		     ADV7511_CEC_CTRL_POWER_DOWN);
 	return ret == -EPROBE_DEFER ? ret : 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
@@ -756,8 +756,13 @@
 	else
 		low_refresh_rate = ADV7511_LOW_REFRESH_RATE_NONE;
 
-	regmap_update_bits(adv7511->regmap, 0xfb,
-		0x6, low_refresh_rate << 1);
+	if (adv7511->type == ADV7511)
+		regmap_update_bits(adv7511->regmap, 0xfb,
+				   0x6, low_refresh_rate << 1);
+	else
+		regmap_update_bits(adv7511->regmap, 0x4a,
+				   0xc, low_refresh_rate << 2);
+
 	regmap_update_bits(adv7511->regmap, 0x17,
 		0x60, (vsync_polarity << 6) | (hsync_polarity << 5));
 
@@ -985,6 +990,10 @@
 						ADV7511_CEC_I2C_ADDR_DEFAULT);
 	if (IS_ERR(adv->i2c_cec))
 		return PTR_ERR(adv->i2c_cec);
+
+	regmap_write(adv->regmap, ADV7511_REG_CEC_I2C_ADDR,
+		     adv->i2c_cec->addr << 1);
+
 	i2c_set_clientdata(adv->i2c_cec, adv);
 
 	adv->regmap_cec = devm_regmap_init_i2c(adv->i2c_cec,
@@ -1189,9 +1198,6 @@
 	if (ret)
 		goto err_i2c_unregister_packet;
 
-	regmap_write(adv7511->regmap, ADV7511_REG_CEC_I2C_ADDR,
-		     adv7511->i2c_cec->addr << 1);
-
 	INIT_WORK(&adv7511->hpd_work, adv7511_hpd_work);
 
 	if (i2c->irq) {
@@ -1225,6 +1231,7 @@
 	return 0;
 
 err_unregister_cec:
+	cec_unregister_adapter(adv7511->cec_adap);
 	i2c_unregister_device(adv7511->i2c_cec);
 	if (adv7511->cec_clk)
 		clk_disable_unprepare(adv7511->cec_clk);
@@ -1300,10 +1307,21 @@
 
 static int __init adv7511_init(void)
 {
-	if (IS_ENABLED(CONFIG_DRM_MIPI_DSI))
-		mipi_dsi_driver_register(&adv7533_dsi_driver);
+	int ret;
 
-	return i2c_add_driver(&adv7511_driver);
+	if (IS_ENABLED(CONFIG_DRM_MIPI_DSI)) {
+		ret = mipi_dsi_driver_register(&adv7533_dsi_driver);
+		if (ret)
+			return ret;
+	}
+
+	ret = i2c_add_driver(&adv7511_driver);
+	if (ret) {
+		if (IS_ENABLED(CONFIG_DRM_MIPI_DSI))
+			mipi_dsi_driver_unregister(&adv7533_dsi_driver);
+	}
+
+	return ret;
 }
 module_init(adv7511_init);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/bridge/adv7511/adv7533.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/bridge/adv7511/adv7533.c
@@ -193,7 +193,7 @@
 
 	of_property_read_u32(np, "adi,dsi-lanes", &num_lanes);
 
-	if (num_lanes < 1 || num_lanes > 4)
+	if (num_lanes < 2 || num_lanes > 4)
 		return -EINVAL;
 
 	adv->num_dsi_lanes = num_lanes;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/bridge/analogix-anx78xx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/bridge/analogix-anx78xx.c
@@ -715,7 +715,9 @@
 	/* 1.0V digital core power regulator  */
 	pdata->dvdd10 = devm_regulator_get(dev, "dvdd10");
 	if (IS_ERR(pdata->dvdd10)) {
-		DRM_ERROR("DVDD10 regulator not found\n");
+		if (PTR_ERR(pdata->dvdd10) != -EPROBE_DEFER)
+			DRM_ERROR("DVDD10 regulator not found\n");
+
 		return PTR_ERR(pdata->dvdd10);
 	}
 
@@ -1332,7 +1334,9 @@
 
 	err = anx78xx_init_pdata(anx78xx);
 	if (err) {
-		DRM_ERROR("Failed to initialize pdata: %d\n", err);
+		if (err != -EPROBE_DEFER)
+			DRM_ERROR("Failed to initialize pdata: %d\n", err);
+
 		return err;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -1630,13 +1630,23 @@
 				       struct drm_dp_aux_msg *msg)
 {
 	struct analogix_dp_device *dp = to_dp(aux);
+	int ret;
+
+	pm_runtime_get_sync(dp->dev);
+
+	ret = analogix_dp_detect_hpd(dp);
+	if (ret)
+		goto out;
+
+	ret = analogix_dp_transfer(dp, msg);
+out:
+	pm_runtime_put(dp->dev);
 
-	return analogix_dp_transfer(dp, msg);
+	return ret;
 }
 
 struct analogix_dp_device *
-analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
-		 struct analogix_dp_plat_data *plat_data)
+analogix_dp_probe(struct device *dev, struct analogix_dp_plat_data *plat_data)
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct analogix_dp_device *dp;
@@ -1697,8 +1707,10 @@
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
 	dp->reg_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(dp->reg_base))
-		return ERR_CAST(dp->reg_base);
+	if (IS_ERR(dp->reg_base)) {
+		ret = PTR_ERR(dp->reg_base);
+		goto err_disable_clk;
+	}
 
 	dp->force_hpd = of_property_read_bool(dev->of_node, "force-hpd");
 
@@ -1710,7 +1722,8 @@
 	if (IS_ERR(dp->hpd_gpiod)) {
 		dev_err(dev, "error getting HDP GPIO: %ld\n",
 			PTR_ERR(dp->hpd_gpiod));
-		return ERR_CAST(dp->hpd_gpiod);
+		ret = PTR_ERR(dp->hpd_gpiod);
+		goto err_disable_clk;
 	}
 
 	if (dp->hpd_gpiod) {
@@ -1730,7 +1743,8 @@
 
 	if (dp->irq == -ENXIO) {
 		dev_err(&pdev->dev, "failed to get irq\n");
-		return ERR_PTR(-ENODEV);
+		ret = -ENODEV;
+		goto err_disable_clk;
 	}
 
 	ret = devm_request_threaded_irq(&pdev->dev, dp->irq,
@@ -1739,22 +1753,34 @@
 					irq_flags, "analogix-dp", dp);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to request irq\n");
-		goto err_disable_pm_runtime;
+		goto err_disable_clk;
 	}
 	disable_irq(dp->irq);
 
+	return dp;
+
+err_disable_clk:
+	clk_disable_unprepare(dp->clock);
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(analogix_dp_probe);
+
+int analogix_dp_bind(struct analogix_dp_device *dp, struct drm_device *drm_dev)
+{
+	int ret;
+
 	dp->drm_dev = drm_dev;
 	dp->encoder = dp->plat_data->encoder;
 
 	dp->aux.name = "DP-AUX";
 	dp->aux.transfer = analogix_dpaux_transfer;
-	dp->aux.dev = &pdev->dev;
+	dp->aux.dev = dp->dev;
 
 	ret = drm_dp_aux_register(&dp->aux);
 	if (ret)
-		return ERR_PTR(ret);
+		return ret;
 
-	pm_runtime_enable(dev);
+	pm_runtime_enable(dp->dev);
 
 	ret = analogix_dp_create_bridge(drm_dev, dp);
 	if (ret) {
@@ -1762,13 +1788,12 @@
 		goto err_disable_pm_runtime;
 	}
 
-	return dp;
+	return 0;
 
 err_disable_pm_runtime:
+	pm_runtime_disable(dp->dev);
 
-	pm_runtime_disable(dev);
-
-	return ERR_PTR(ret);
+	return ret;
 }
 EXPORT_SYMBOL_GPL(analogix_dp_bind);
 
@@ -1785,20 +1810,19 @@
 
 	drm_dp_aux_unregister(&dp->aux);
 	pm_runtime_disable(dp->dev);
-	clk_disable_unprepare(dp->clock);
 }
 EXPORT_SYMBOL_GPL(analogix_dp_unbind);
 
+void analogix_dp_remove(struct analogix_dp_device *dp)
+{
+	clk_disable_unprepare(dp->clock);
+}
+EXPORT_SYMBOL_GPL(analogix_dp_remove);
+
 #ifdef CONFIG_PM
 int analogix_dp_suspend(struct analogix_dp_device *dp)
 {
 	clk_disable_unprepare(dp->clock);
-
-	if (dp->plat_data->panel) {
-		if (drm_panel_unprepare(dp->plat_data->panel))
-			DRM_ERROR("failed to turnoff the panel\n");
-	}
-
 	return 0;
 }
 EXPORT_SYMBOL_GPL(analogix_dp_suspend);
@@ -1813,13 +1837,6 @@
 		return ret;
 	}
 
-	if (dp->plat_data->panel) {
-		if (drm_panel_prepare(dp->plat_data->panel)) {
-			DRM_ERROR("failed to setup the panel\n");
-			return -EBUSY;
-		}
-	}
-
 	return 0;
 }
 EXPORT_SYMBOL_GPL(analogix_dp_resume);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
@@ -1086,11 +1086,21 @@
 	if (!blocking)
 		return 0;
 
+	/*
+	 * db[1]!=0: entering PSR, wait for fully active remote frame buffer.
+	 * db[1]==0: exiting PSR, wait for either
+	 *  (a) ACTIVE_RESYNC - the sink "must display the
+	 *      incoming active frames from the Source device with no visible
+	 *      glitches and/or artifacts", even though timings may still be
+	 *      re-synchronizing; or
+	 *  (b) INACTIVE - the transition is fully complete.
+	 */
 	ret = readx_poll_timeout(analogix_dp_get_psr_status, dp, psr_status,
 		psr_status >= 0 &&
 		((vsc->db[1] && psr_status == DP_PSR_SINK_ACTIVE_RFB) ||
-		(!vsc->db[1] && psr_status == DP_PSR_SINK_INACTIVE)), 1500,
-		DP_TIMEOUT_PSR_LOOP_MS * 1000);
+		(!vsc->db[1] && (psr_status == DP_PSR_SINK_ACTIVE_RESYNC ||
+				 psr_status == DP_PSR_SINK_INACTIVE))),
+		1500, DP_TIMEOUT_PSR_LOOP_MS * 1000);
 	if (ret) {
 		dev_warn(dp->dev, "Failed to apply PSR %d\n", ret);
 		return ret;
@@ -1105,7 +1115,6 @@
 	u32 status_reg;
 	u8 *buffer = msg->buffer;
 	unsigned int i;
-	int num_transferred = 0;
 	int ret;
 
 	/* Buffer size of AUX CH is 16 bytes */
@@ -1157,7 +1166,6 @@
 			reg = buffer[i];
 			writel(reg, dp->reg_base + ANALOGIX_DP_BUF_DATA_0 +
 			       4 * i);
-			num_transferred++;
 		}
 	}
 
@@ -1205,7 +1213,6 @@
 			reg = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0 +
 				    4 * i);
 			buffer[i] = (unsigned char)reg;
-			num_transferred++;
 		}
 	}
 
@@ -1222,7 +1229,7 @@
 		 (msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_NATIVE_READ)
 		msg->reply = DP_AUX_NATIVE_REPLY_ACK;
 
-	return num_transferred > 0 ? num_transferred : -EBUSY;
+	return msg->size;
 
 aux_error:
 	/* if aux err happen, reset aux */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/bridge/cdns-dsi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/bridge/cdns-dsi.c
@@ -1026,7 +1026,7 @@
 	struct mipi_dsi_packet packet;
 	int ret, i, tx_len, rx_len;
 
-	ret = pm_runtime_get_sync(host->dev);
+	ret = pm_runtime_resume_and_get(host->dev);
 	if (ret < 0)
 		return ret;
 
@@ -1284,6 +1284,7 @@
 	{ .compatible = "cdns,dsi" },
 	{ },
 };
+MODULE_DEVICE_TABLE(of, cdns_dsi_of_match);
 
 static struct platform_driver cdns_dsi_platform_driver = {
 	.probe  = cdns_dsi_drm_probe,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
@@ -279,7 +279,9 @@
 	 * This check is to avoid both the drivers
 	 * removing the bridge in their remove() function
 	 */
-	if (!ge_b850v3_lvds_ptr)
+	if (!ge_b850v3_lvds_ptr ||
+	    !ge_b850v3_lvds_ptr->stdp2690_i2c ||
+		!ge_b850v3_lvds_ptr->stdp4028_i2c)
 		goto out;
 
 	drm_bridge_remove(&ge_b850v3_lvds_ptr->bridge);
@@ -291,16 +293,11 @@
 	mutex_unlock(&ge_b850v3_lvds_dev_mutex);
 }
 
-static int stdp4028_ge_b850v3_fw_probe(struct i2c_client *stdp4028_i2c,
-				       const struct i2c_device_id *id)
+static int ge_b850v3_register(void)
 {
+	struct i2c_client *stdp4028_i2c = ge_b850v3_lvds_ptr->stdp4028_i2c;
 	struct device *dev = &stdp4028_i2c->dev;
 
-	ge_b850v3_lvds_init(dev);
-
-	ge_b850v3_lvds_ptr->stdp4028_i2c = stdp4028_i2c;
-	i2c_set_clientdata(stdp4028_i2c, ge_b850v3_lvds_ptr);
-
 	/* drm bridge initialization */
 	ge_b850v3_lvds_ptr->bridge.funcs = &ge_b850v3_lvds_funcs;
 	ge_b850v3_lvds_ptr->bridge.of_node = dev->of_node;
@@ -321,6 +318,27 @@
 			"ge-b850v3-lvds-dp", ge_b850v3_lvds_ptr);
 }
 
+static int stdp4028_ge_b850v3_fw_probe(struct i2c_client *stdp4028_i2c,
+				       const struct i2c_device_id *id)
+{
+	struct device *dev = &stdp4028_i2c->dev;
+	int ret;
+
+	ret = ge_b850v3_lvds_init(dev);
+
+	if (ret)
+		return ret;
+
+	ge_b850v3_lvds_ptr->stdp4028_i2c = stdp4028_i2c;
+	i2c_set_clientdata(stdp4028_i2c, ge_b850v3_lvds_ptr);
+
+	/* Only register after both bridges are probed */
+	if (!ge_b850v3_lvds_ptr->stdp2690_i2c)
+		return 0;
+
+	return ge_b850v3_register();
+}
+
 static int stdp4028_ge_b850v3_fw_remove(struct i2c_client *stdp4028_i2c)
 {
 	ge_b850v3_lvds_remove();
@@ -354,13 +372,21 @@
 				       const struct i2c_device_id *id)
 {
 	struct device *dev = &stdp2690_i2c->dev;
+	int ret;
 
-	ge_b850v3_lvds_init(dev);
+	ret = ge_b850v3_lvds_init(dev);
+
+	if (ret)
+		return ret;
 
 	ge_b850v3_lvds_ptr->stdp2690_i2c = stdp2690_i2c;
 	i2c_set_clientdata(stdp2690_i2c, ge_b850v3_lvds_ptr);
 
-	return 0;
+	/* Only register after both bridges are probed */
+	if (!ge_b850v3_lvds_ptr->stdp4028_i2c)
+		return 0;
+
+	return ge_b850v3_register();
 }
 
 static int stdp2690_ge_b850v3_fw_remove(struct i2c_client *stdp2690_i2c)
@@ -400,7 +426,11 @@
 	if (ret)
 		return ret;
 
-	return i2c_add_driver(&stdp2690_ge_b850v3_fw_driver);
+	ret = i2c_add_driver(&stdp2690_ge_b850v3_fw_driver);
+	if (ret)
+		i2c_del_driver(&stdp4028_ge_b850v3_fw_driver);
+
+	return ret;
 }
 module_init(stdpxxxx_ge_b850v3_init);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/bridge/nxp-ptn3460.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/bridge/nxp-ptn3460.c
@@ -54,13 +54,13 @@
 	int ret;
 
 	ret = i2c_master_send(ptn_bridge->client, &addr, 1);
-	if (ret <= 0) {
+	if (ret < 0) {
 		DRM_ERROR("Failed to send i2c command, ret=%d\n", ret);
 		return ret;
 	}
 
 	ret = i2c_master_recv(ptn_bridge->client, buf, len);
-	if (ret <= 0) {
+	if (ret < 0) {
 		DRM_ERROR("Failed to recv i2c data, ret=%d\n", ret);
 		return ret;
 	}
@@ -78,7 +78,7 @@
 	buf[1] = val;
 
 	ret = i2c_master_send(ptn_bridge->client, buf, ARRAY_SIZE(buf));
-	if (ret <= 0) {
+	if (ret < 0) {
 		DRM_ERROR("Failed to send i2c command, ret=%d\n", ret);
 		return ret;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/bridge/panel.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/bridge/panel.c
@@ -87,8 +87,17 @@
 static void panel_bridge_detach(struct drm_bridge *bridge)
 {
 	struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
+	struct drm_connector *connector = &panel_bridge->connector;
 
-	drm_panel_detach(panel_bridge->panel);
+	/*
+	 * Cleanup the connector if we know it was initialized.
+	 *
+	 * FIXME: This wouldn't be needed if the panel_bridge structure was
+	 * allocated with drmm_kzalloc(). This might be tricky since the
+	 * drm_device pointer can only be retrieved when the bridge is attached.
+	 */
+	if (connector->dev)
+		drm_connector_cleanup(connector);
 }
 
 static void panel_bridge_pre_enable(struct drm_bridge *bridge)
@@ -203,9 +212,12 @@
 
 static void devm_drm_panel_bridge_release(struct device *dev, void *res)
 {
-	struct drm_bridge **bridge = res;
+	struct drm_bridge *bridge = *(struct drm_bridge **)res;
 
-	drm_panel_bridge_remove(*bridge);
+	if (!bridge)
+		return;
+
+	drm_bridge_remove(bridge);
 }
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/bridge/sii902x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/bridge/sii902x.c
@@ -1016,11 +1016,6 @@
 			return ret;
 	}
 
-	sii902x->bridge.funcs = &sii902x_bridge_funcs;
-	sii902x->bridge.of_node = dev->of_node;
-	sii902x->bridge.timings = &default_sii902x_timings;
-	drm_bridge_add(&sii902x->bridge);
-
 	sii902x_audio_codec_init(sii902x, dev);
 
 	i2c_set_clientdata(client, sii902x);
@@ -1033,16 +1028,24 @@
 		return -ENOMEM;
 
 	sii902x->i2cmux->priv = sii902x;
-	return i2c_mux_add_adapter(sii902x->i2cmux, 0, 0, 0);
+	ret = i2c_mux_add_adapter(sii902x->i2cmux, 0, 0, 0);
+	if (ret)
+		return ret;
+
+	sii902x->bridge.funcs = &sii902x_bridge_funcs;
+	sii902x->bridge.of_node = dev->of_node;
+	sii902x->bridge.timings = &default_sii902x_timings;
+	drm_bridge_add(&sii902x->bridge);
+
+	return 0;
 }
 
 static int sii902x_remove(struct i2c_client *client)
-
 {
 	struct sii902x *sii902x = i2c_get_clientdata(client);
 
-	i2c_mux_del_adapters(sii902x->i2cmux);
 	drm_bridge_remove(&sii902x->bridge);
+	i2c_mux_del_adapters(sii902x->i2cmux);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/bridge/sil-sii8620.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/bridge/sil-sii8620.c
@@ -177,7 +177,7 @@
 
 static u8 sii8620_readb(struct sii8620 *ctx, u16 addr)
 {
-	u8 ret;
+	u8 ret = 0;
 
 	sii8620_read_buf(ctx, addr, &ret, 1);
 	return ret;
@@ -604,7 +604,7 @@
 	u8 *buf = &ctx->burst.tx_buf[ctx->burst.tx_count];
 	int size = len + 2;
 
-	if (ctx->burst.tx_count + size > ARRAY_SIZE(ctx->burst.tx_buf)) {
+	if (ctx->burst.tx_count + size >= ARRAY_SIZE(ctx->burst.tx_buf)) {
 		dev_err(ctx->dev, "TX-BLK buffer exhausted\n");
 		ctx->error = -EINVAL;
 		return NULL;
@@ -621,7 +621,7 @@
 	u8 *buf = &ctx->burst.rx_buf[ctx->burst.rx_count];
 	int size = len + 1;
 
-	if (ctx->burst.tx_count + size > ARRAY_SIZE(ctx->burst.tx_buf)) {
+	if (ctx->burst.rx_count + size >= ARRAY_SIZE(ctx->burst.rx_buf)) {
 		dev_err(ctx->dev, "RX-BLK buffer exhausted\n");
 		ctx->error = -EINVAL;
 		return NULL;
@@ -985,7 +985,7 @@
 
 static void sii8620_stop_video(struct sii8620 *ctx)
 {
-	u8 uninitialized_var(val);
+	u8 val;
 
 	sii8620_write_seq_static(ctx,
 		REG_TPI_INTR_EN, 0,
@@ -2118,7 +2118,7 @@
 	if (ret) {
 		dev_err(ctx->dev, "Failed to register RC device\n");
 		ctx->error = ret;
-		rc_free_device(ctx->rc_dev);
+		rc_free_device(rc_dev);
 		return;
 	}
 	ctx->rc_dev = rc_dev;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -36,6 +36,7 @@
 #include "dw-hdmi-cec.h"
 #include "dw-hdmi.h"
 
+#define DDC_CI_ADDR		0x37
 #define DDC_SEGMENT_ADDR	0x30
 
 #define HDMI_EDID_LEN		512
@@ -398,6 +399,15 @@
 	u8 addr = msgs[0].addr;
 	int i, ret = 0;
 
+	if (addr == DDC_CI_ADDR)
+		/*
+		 * The internal I2C controller does not support the multi-byte
+		 * read and write operations needed for DDC/CI.
+		 * TOFIX: Blacklist the DDC/CI address until we filter out
+		 * unsupported I2C operations.
+		 */
+		return -EOPNOTSUPP;
+
 	dev_dbg(hdmi->dev, "xfer: num: %d, addr: %#x\n", num, addr);
 
 	for (i = 0; i < num; i++) {
@@ -1566,28 +1576,34 @@
 		frame.colorspace = HDMI_COLORSPACE_RGB;
 
 	/* Set up colorimetry */
-	switch (hdmi->hdmi_data.enc_out_encoding) {
-	case V4L2_YCBCR_ENC_601:
-		if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV601)
-			frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
-		else
+	if (!hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) {
+		switch (hdmi->hdmi_data.enc_out_encoding) {
+		case V4L2_YCBCR_ENC_601:
+			if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV601)
+				frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
+			else
+				frame.colorimetry = HDMI_COLORIMETRY_ITU_601;
+			frame.extended_colorimetry =
+					HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
+			break;
+		case V4L2_YCBCR_ENC_709:
+			if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV709)
+				frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
+			else
+				frame.colorimetry = HDMI_COLORIMETRY_ITU_709;
+			frame.extended_colorimetry =
+					HDMI_EXTENDED_COLORIMETRY_XV_YCC_709;
+			break;
+		default: /* Carries no data */
 			frame.colorimetry = HDMI_COLORIMETRY_ITU_601;
+			frame.extended_colorimetry =
+					HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
+			break;
+		}
+	} else {
+		frame.colorimetry = HDMI_COLORIMETRY_NONE;
 		frame.extended_colorimetry =
-				HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
-		break;
-	case V4L2_YCBCR_ENC_709:
-		if (hdmi->hdmi_data.enc_in_encoding == V4L2_YCBCR_ENC_XV709)
-			frame.colorimetry = HDMI_COLORIMETRY_EXTENDED;
-		else
-			frame.colorimetry = HDMI_COLORIMETRY_ITU_709;
-		frame.extended_colorimetry =
-				HDMI_EXTENDED_COLORIMETRY_XV_YCC_709;
-		break;
-	default: /* Carries no data */
-		frame.colorimetry = HDMI_COLORIMETRY_ITU_601;
-		frame.extended_colorimetry =
-				HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
-		break;
+			HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
 	}
 
 	frame.scan_mode = HDMI_SCAN_MODE_NONE;
@@ -2023,7 +2039,7 @@
 
 		/* HDMI Initialization Step E - Configure audio */
 		hdmi_clk_regenerator_update_pixel_clock(hdmi);
-		hdmi_enable_audio_clk(hdmi, true);
+		hdmi_enable_audio_clk(hdmi, hdmi->audio_enable);
 	}
 
 	/* not for DVI mode */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
@@ -365,7 +365,6 @@
 	if (lpm)
 		val |= CMD_MODE_ALL_LP;
 
-	dsi_write(dsi, DSI_LPCLK_CTRL, lpm ? 0 : PHY_TXREQUESTCLKHS);
 	dsi_write(dsi, DSI_CMD_MODE_CFG, val);
 }
 
@@ -541,16 +540,22 @@
 static void dw_mipi_dsi_set_mode(struct dw_mipi_dsi *dsi,
 				 unsigned long mode_flags)
 {
+	u32 val;
+
 	dsi_write(dsi, DSI_PWR_UP, RESET);
 
 	if (mode_flags & MIPI_DSI_MODE_VIDEO) {
 		dsi_write(dsi, DSI_MODE_CFG, ENABLE_VIDEO_MODE);
 		dw_mipi_dsi_video_mode_config(dsi);
-		dsi_write(dsi, DSI_LPCLK_CTRL, PHY_TXREQUESTCLKHS);
 	} else {
 		dsi_write(dsi, DSI_MODE_CFG, ENABLE_CMD_MODE);
 	}
 
+	val = PHY_TXREQUESTCLKHS;
+	if (dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)
+		val |= AUTO_CLKLANE_CTRL;
+	dsi_write(dsi, DSI_LPCLK_CTRL, val);
+
 	dsi_write(dsi, DSI_PWR_UP, POWERUP);
 }
 
@@ -1052,6 +1057,7 @@
 	ret = mipi_dsi_host_register(&dsi->dsi_host);
 	if (ret) {
 		dev_err(dev, "Failed to register MIPI host: %d\n", ret);
+		pm_runtime_disable(dev);
 		dw_mipi_dsi_debugfs_remove(dsi);
 		return ERR_PTR(ret);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/bridge/tc358764.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/bridge/tc358764.c
@@ -180,7 +180,7 @@
 	if (ret >= 0)
 		le32_to_cpus(val);
 
-	dev_dbg(ctx->dev, "read: %d, addr: %d\n", addr, *val);
+	dev_dbg(ctx->dev, "read: addr=0x%04x data=0x%08x\n", addr, *val);
 }
 
 static void tc358764_write(struct tc358764 *ctx, u16 addr, u32 val)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/bridge/tc358767.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/bridge/tc358767.c
@@ -294,7 +294,7 @@
 
 static int tc_aux_wait_busy(struct tc_data *tc)
 {
-	return tc_poll_timeout(tc, DP0_AUXSTATUS, AUX_BUSY, 0, 1000, 100000);
+	return tc_poll_timeout(tc, DP0_AUXSTATUS, AUX_BUSY, 0, 100, 100000);
 }
 
 static int tc_aux_write_data(struct tc_data *tc, const void *data,
@@ -637,7 +637,7 @@
 	if (ret)
 		goto err;
 
-	ret = tc_poll_timeout(tc, DP_PHY_CTRL, PHY_RDY, PHY_RDY, 1, 1000);
+	ret = tc_poll_timeout(tc, DP_PHY_CTRL, PHY_RDY, PHY_RDY, 100, 100000);
 	if (ret == -ETIMEDOUT) {
 		dev_err(tc->dev, "Timeout waiting for PHY to become ready");
 		return ret;
@@ -861,7 +861,7 @@
 	int ret;
 
 	ret = tc_poll_timeout(tc, DP0_LTSTAT, LT_LOOPDONE,
-			      LT_LOOPDONE, 1, 1000);
+			      LT_LOOPDONE, 500, 100000);
 	if (ret) {
 		dev_err(tc->dev, "Link training timeout waiting for LT_LOOPDONE!\n");
 		return ret;
@@ -934,7 +934,7 @@
 	dp_phy_ctrl &= ~(DP_PHY_RST | PHY_M1_RST | PHY_M0_RST);
 	ret = regmap_write(tc->regmap, DP_PHY_CTRL, dp_phy_ctrl);
 
-	ret = tc_poll_timeout(tc, DP_PHY_CTRL, PHY_RDY, PHY_RDY, 1, 1000);
+	ret = tc_poll_timeout(tc, DP_PHY_CTRL, PHY_RDY, PHY_RDY, 500, 100000);
 	if (ret) {
 		dev_err(dev, "timeout waiting for phy become ready");
 		return ret;
@@ -1574,7 +1574,7 @@
 	} else {
 		if (tc->hpd_pin < 0 || tc->hpd_pin > 1) {
 			dev_err(dev, "failed to parse HPD number\n");
-			return ret;
+			return -EINVAL;
 		}
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/bridge/ti-sn65dsi86.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/bridge/ti-sn65dsi86.c
@@ -115,6 +115,7 @@
 	.val_bits = 8,
 	.volatile_table = &ti_sn_bridge_volatile_table,
 	.cache_type = REGCACHE_NONE,
+	.max_register = 0xFF,
 };
 
 static void ti_sn_bridge_write_u16(struct ti_sn_bridge *pdata,
@@ -459,9 +460,9 @@
 		&pdata->bridge.encoder->crtc->state->adjusted_mode;
 	u8 hsync_polarity = 0, vsync_polarity = 0;
 
-	if (mode->flags & DRM_MODE_FLAG_PHSYNC)
+	if (mode->flags & DRM_MODE_FLAG_NHSYNC)
 		hsync_polarity = CHA_HSYNC_POLARITY;
-	if (mode->flags & DRM_MODE_FLAG_PVSYNC)
+	if (mode->flags & DRM_MODE_FLAG_NVSYNC)
 		vsync_polarity = CHA_VSYNC_POLARITY;
 
 	ti_sn_bridge_write_u16(pdata, SN_CHA_ACTIVE_LINE_LENGTH_LOW_REG,
@@ -647,6 +648,12 @@
 				     buf[i]);
 	}
 
+	/* Clear old status bits before start so we don't get confused */
+	regmap_write(pdata->regmap, SN_AUX_CMD_STATUS_REG,
+		     AUX_IRQ_STATUS_NAT_I2C_FAIL |
+		     AUX_IRQ_STATUS_AUX_RPLY_TOUT |
+		     AUX_IRQ_STATUS_AUX_SHORT);
+
 	regmap_write(pdata->regmap, SN_AUX_CMD_REG, request_val | AUX_CMD_SEND);
 
 	ret = regmap_read_poll_timeout(pdata->regmap, SN_AUX_CMD_REG, val,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_atomic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_atomic.c
@@ -97,6 +97,12 @@
 	if (!state->planes)
 		goto fail;
 
+	/*
+	 * Because drm_atomic_state can be committed asynchronously we need our
+	 * own reference and cannot rely on the on implied by drm_file in the
+	 * ioctl call.
+	 */
+	drm_dev_get(dev);
 	state->dev = dev;
 
 	DRM_DEBUG_ATOMIC("Allocated atomic state %p\n", state);
@@ -256,7 +262,8 @@
 void __drm_atomic_state_free(struct kref *ref)
 {
 	struct drm_atomic_state *state = container_of(ref, typeof(*state), ref);
-	struct drm_mode_config *config = &state->dev->mode_config;
+	struct drm_device *dev = state->dev;
+	struct drm_mode_config *config = &dev->mode_config;
 
 	drm_atomic_state_clear(state);
 
@@ -268,6 +275,8 @@
 		drm_atomic_state_default_release(state);
 		kfree(state);
 	}
+
+	drm_dev_put(dev);
 }
 EXPORT_SYMBOL(__drm_atomic_state_free);
 
@@ -1006,6 +1015,7 @@
 	drm_printf(p, "connector[%u]: %s\n", connector->base.id, connector->name);
 	drm_printf(p, "\tcrtc=%s\n", state->crtc ? state->crtc->name : "(null)");
 	drm_printf(p, "\tself_refresh_aware=%d\n", state->self_refresh_aware);
+	drm_printf(p, "\tmax_requested_bpc=%d\n", state->max_requested_bpc);
 
 	if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
 		if (state->writeback_job && state->writeback_job->fb)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_atomic_helper.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_atomic_helper.c
@@ -445,8 +445,9 @@
 		encoder = new_conn_state->best_encoder;
 		funcs = encoder->helper_private;
 
-		ret = drm_bridge_mode_fixup(encoder->bridge, &new_crtc_state->mode,
-				&new_crtc_state->adjusted_mode);
+		ret = drm_bridge_chain_mode_fixup(encoder->bridge,
+					&new_crtc_state->mode,
+					&new_crtc_state->adjusted_mode);
 		if (!ret) {
 			DRM_DEBUG_ATOMIC("Bridge fixup failed\n");
 			return -EINVAL;
@@ -511,7 +512,7 @@
 		return ret;
 	}
 
-	ret = drm_bridge_mode_valid(encoder->bridge, mode);
+	ret = drm_bridge_chain_mode_valid(encoder->bridge, mode);
 	if (ret != MODE_OK) {
 		DRM_DEBUG_ATOMIC("[BRIDGE] mode_valid() failed\n");
 		return ret;
@@ -588,6 +589,7 @@
  * &drm_crtc_state.connectors_changed is set when a connector is added or
  * removed from the crtc.  &drm_crtc_state.active_changed is set when
  * &drm_crtc_state.active changes, which is used for DPMS.
+ * &drm_crtc_state.no_vblank is set from the result of drm_dev_has_vblank().
  * See also: drm_atomic_crtc_needs_modeset()
  *
  * IMPORTANT:
@@ -654,6 +656,11 @@
 
 			return -EINVAL;
 		}
+
+		if (drm_dev_has_vblank(dev))
+			new_crtc_state->no_vblank = false;
+		else
+			new_crtc_state->no_vblank = true;
 	}
 
 	ret = handle_conflicting_encoders(state, false);
@@ -1030,7 +1037,7 @@
 		 * Each encoder has at most one connector (since we always steal
 		 * it away), so we won't call disable hooks twice.
 		 */
-		drm_atomic_bridge_disable(encoder->bridge, old_state);
+		drm_atomic_bridge_chain_disable(encoder->bridge, old_state);
 
 		/* Right function depends upon target state. */
 		if (funcs) {
@@ -1044,7 +1051,8 @@
 				funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
 		}
 
-		drm_atomic_bridge_post_disable(encoder->bridge, old_state);
+		drm_atomic_bridge_chain_post_disable(encoder->bridge,
+						     old_state);
 	}
 
 	for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) {
@@ -1078,7 +1086,16 @@
 			continue;
 
 		ret = drm_crtc_vblank_get(crtc);
-		WARN_ONCE(ret != -EINVAL, "driver forgot to call drm_crtc_vblank_off()\n");
+		/*
+		 * Self-refresh is not a true "disable"; ensure vblank remains
+		 * enabled.
+		 */
+		if (new_crtc_state->self_refresh_active)
+			WARN_ONCE(ret != 0,
+				  "driver disabled vblank in self-refresh\n");
+		else
+			WARN_ONCE(ret != -EINVAL,
+				  "driver forgot to call drm_crtc_vblank_off()\n");
 		if (ret == 0)
 			drm_crtc_vblank_put(crtc);
 	}
@@ -1225,7 +1242,8 @@
 			funcs->mode_set(encoder, mode, adjusted_mode);
 		}
 
-		drm_bridge_mode_set(encoder->bridge, mode, adjusted_mode);
+		drm_bridge_chain_mode_set(encoder->bridge, mode,
+					  adjusted_mode);
 	}
 }
 
@@ -1342,7 +1360,7 @@
 		 * Each encoder has at most one connector (since we always steal
 		 * it away), so we won't call enable hooks twice.
 		 */
-		drm_atomic_bridge_pre_enable(encoder->bridge, old_state);
+		drm_atomic_bridge_chain_pre_enable(encoder->bridge, old_state);
 
 		if (funcs) {
 			if (funcs->atomic_enable)
@@ -1353,7 +1371,7 @@
 				funcs->commit(encoder);
 		}
 
-		drm_atomic_bridge_enable(encoder->bridge, old_state);
+		drm_atomic_bridge_chain_enable(encoder->bridge, old_state);
 	}
 
 	drm_atomic_helper_commit_writebacks(dev, old_state);
@@ -2202,7 +2220,9 @@
  * when a job is queued, and any change to the pipeline that does not touch the
  * connector is leading to timeouts when calling
  * drm_atomic_helper_wait_for_vblanks() or
- * drm_atomic_helper_wait_for_flip_done().
+ * drm_atomic_helper_wait_for_flip_done(). In addition to writeback
+ * connectors, this function can also fake VBLANK events for CRTCs without
+ * VBLANK interrupt.
  *
  * This is part of the atomic helper support for nonblocking commits, see
  * drm_atomic_helper_setup_commit() for an overview.
@@ -2948,7 +2968,7 @@
 
 	ret = handle_conflicting_encoders(state, true);
 	if (ret)
-		return ret;
+		goto fail;
 
 	ret = drm_atomic_commit(state);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_atomic_state_helper.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_atomic_state_helper.c
@@ -417,6 +417,9 @@
 	if (state->hdr_output_metadata)
 		drm_property_blob_get(state->hdr_output_metadata);
 
+	if (state->gen_hdr_output_metadata)
+		drm_property_blob_get(state->gen_hdr_output_metadata);
+
 	/* Don't copy over a writeback job, they are used only once */
 	state->writeback_job = NULL;
 }
@@ -466,6 +469,7 @@
 		drm_writeback_cleanup_job(state->writeback_job);
 
 	drm_property_blob_put(state->hdr_output_metadata);
+	drm_property_blob_put(state->gen_hdr_output_metadata);
 }
 EXPORT_SYMBOL(__drm_atomic_helper_connector_destroy_state);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_atomic_uapi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_atomic_uapi.c
@@ -75,15 +75,17 @@
 	state->mode_blob = NULL;
 
 	if (mode) {
+		struct drm_property_blob *blob;
+
 		drm_mode_convert_to_umode(&umode, mode);
-		state->mode_blob =
-			drm_property_create_blob(state->crtc->dev,
-		                                 sizeof(umode),
-		                                 &umode);
-		if (IS_ERR(state->mode_blob))
-			return PTR_ERR(state->mode_blob);
+		blob = drm_property_create_blob(crtc->dev,
+						sizeof(umode), &umode);
+		if (IS_ERR(blob))
+			return PTR_ERR(blob);
 
 		drm_mode_copy(&state->mode, mode);
+
+		state->mode_blob = blob;
 		state->enable = true;
 		DRM_DEBUG_ATOMIC("Set [MODE:%s] for [CRTC:%d:%s] state %p\n",
 				 mode->name, crtc->base.id, crtc->name, state);
@@ -580,7 +582,7 @@
 					&state->fb_damage_clips,
 					val,
 					-1,
-					sizeof(struct drm_rect),
+					sizeof(struct drm_mode_rect),
 					&replaced);
 		return ret;
 	} else if (plane->funcs->atomic_set_property) {
@@ -735,6 +737,13 @@
 				sizeof(struct hdr_output_metadata), -1,
 				&replaced);
 		return ret;
+	} else if (property == config->gen_hdr_output_metadata_property) {
+		ret = drm_atomic_replace_property_blob_from_id(dev,
+				&state->gen_hdr_output_metadata,
+				val,
+				sizeof(struct gen_hdr_output_metadata), -1,
+				&replaced);
+		return ret;
 	} else if (property == config->aspect_ratio_property) {
 		state->picture_aspect_ratio = val;
 	} else if (property == config->content_type_property) {
@@ -831,6 +840,9 @@
 	} else if (property == config->hdr_output_metadata_property) {
 		*val = state->hdr_output_metadata ?
 			state->hdr_output_metadata->base.id : 0;
+	} else if (property == config->gen_hdr_output_metadata_property) {
+		*val = state->gen_hdr_output_metadata ?
+			state->gen_hdr_output_metadata->base.id : 0;
 	} else if (property == config->content_protection_property) {
 		*val = state->content_protection;
 	} else if (property == config->hdcp_content_type_property) {
@@ -927,6 +939,10 @@
 
 	if (mode != DRM_MODE_DPMS_ON)
 		mode = DRM_MODE_DPMS_OFF;
+
+	if (connector->dpms == mode)
+		goto out;
+
 	connector->dpms = mode;
 
 	crtc = connector->state->crtc;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_auth.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_auth.c
@@ -268,9 +268,10 @@
 void drm_master_release(struct drm_file *file_priv)
 {
 	struct drm_device *dev = file_priv->minor->dev;
-	struct drm_master *master = file_priv->master;
+	struct drm_master *master;
 
 	mutex_lock(&dev->master_mutex);
+	master = file_priv->master;
 	if (file_priv->magic)
 		idr_remove(&file_priv->master->magic_map, file_priv->magic);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_bridge.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_bridge.c
@@ -172,8 +172,8 @@
  */
 
 /**
- * drm_bridge_mode_fixup - fixup proposed mode for all bridges in the
- *			   encoder chain
+ * drm_bridge_chain_mode_fixup - fixup proposed mode for all bridges in the
+ *				 encoder chain
  * @bridge: bridge control structure
  * @mode: desired mode to be set for the bridge
  * @adjusted_mode: updated mode that works for this bridge
@@ -186,9 +186,9 @@
  * RETURNS:
  * true on success, false on failure
  */
-bool drm_bridge_mode_fixup(struct drm_bridge *bridge,
-			const struct drm_display_mode *mode,
-			struct drm_display_mode *adjusted_mode)
+bool drm_bridge_chain_mode_fixup(struct drm_bridge *bridge,
+				 const struct drm_display_mode *mode,
+				 struct drm_display_mode *adjusted_mode)
 {
 	bool ret = true;
 
@@ -198,15 +198,16 @@
 	if (bridge->funcs->mode_fixup)
 		ret = bridge->funcs->mode_fixup(bridge, mode, adjusted_mode);
 
-	ret = ret && drm_bridge_mode_fixup(bridge->next, mode, adjusted_mode);
+	ret = ret && drm_bridge_chain_mode_fixup(bridge->next, mode,
+						 adjusted_mode);
 
 	return ret;
 }
-EXPORT_SYMBOL(drm_bridge_mode_fixup);
+EXPORT_SYMBOL(drm_bridge_chain_mode_fixup);
 
 /**
- * drm_bridge_mode_valid - validate the mode against all bridges in the
- * 			   encoder chain.
+ * drm_bridge_chain_mode_valid - validate the mode against all bridges in the
+ *				 encoder chain.
  * @bridge: bridge control structure
  * @mode: desired mode to be validated
  *
@@ -219,8 +220,9 @@
  * RETURNS:
  * MODE_OK on success, drm_mode_status Enum error code on failure
  */
-enum drm_mode_status drm_bridge_mode_valid(struct drm_bridge *bridge,
-					   const struct drm_display_mode *mode)
+enum drm_mode_status
+drm_bridge_chain_mode_valid(struct drm_bridge *bridge,
+			    const struct drm_display_mode *mode)
 {
 	enum drm_mode_status ret = MODE_OK;
 
@@ -233,12 +235,12 @@
 	if (ret != MODE_OK)
 		return ret;
 
-	return drm_bridge_mode_valid(bridge->next, mode);
+	return drm_bridge_chain_mode_valid(bridge->next, mode);
 }
-EXPORT_SYMBOL(drm_bridge_mode_valid);
+EXPORT_SYMBOL(drm_bridge_chain_mode_valid);
 
 /**
- * drm_bridge_disable - disables all bridges in the encoder chain
+ * drm_bridge_chain_disable - disables all bridges in the encoder chain
  * @bridge: bridge control structure
  *
  * Calls &drm_bridge_funcs.disable op for all the bridges in the encoder
@@ -247,20 +249,21 @@
  *
  * Note: the bridge passed should be the one closest to the encoder
  */
-void drm_bridge_disable(struct drm_bridge *bridge)
+void drm_bridge_chain_disable(struct drm_bridge *bridge)
 {
 	if (!bridge)
 		return;
 
-	drm_bridge_disable(bridge->next);
+	drm_bridge_chain_disable(bridge->next);
 
 	if (bridge->funcs->disable)
 		bridge->funcs->disable(bridge);
 }
-EXPORT_SYMBOL(drm_bridge_disable);
+EXPORT_SYMBOL(drm_bridge_chain_disable);
 
 /**
- * drm_bridge_post_disable - cleans up after disabling all bridges in the encoder chain
+ * drm_bridge_chain_post_disable - cleans up after disabling all bridges in the
+ *				   encoder chain
  * @bridge: bridge control structure
  *
  * Calls &drm_bridge_funcs.post_disable op for all the bridges in the
@@ -269,7 +272,7 @@
  *
  * Note: the bridge passed should be the one closest to the encoder
  */
-void drm_bridge_post_disable(struct drm_bridge *bridge)
+void drm_bridge_chain_post_disable(struct drm_bridge *bridge)
 {
 	if (!bridge)
 		return;
@@ -277,25 +280,25 @@
 	if (bridge->funcs->post_disable)
 		bridge->funcs->post_disable(bridge);
 
-	drm_bridge_post_disable(bridge->next);
+	drm_bridge_chain_post_disable(bridge->next);
 }
-EXPORT_SYMBOL(drm_bridge_post_disable);
+EXPORT_SYMBOL(drm_bridge_chain_post_disable);
 
 /**
- * drm_bridge_mode_set - set proposed mode for all bridges in the
- *			 encoder chain
+ * drm_bridge_chain_mode_set - set proposed mode for all bridges in the
+ *			       encoder chain
  * @bridge: bridge control structure
- * @mode: desired mode to be set for the bridge
- * @adjusted_mode: updated mode that works for this bridge
+ * @mode: desired mode to be set for the encoder chain
+ * @adjusted_mode: updated mode that works for this encoder chain
  *
  * Calls &drm_bridge_funcs.mode_set op for all the bridges in the
  * encoder chain, starting from the first bridge to the last.
  *
  * Note: the bridge passed should be the one closest to the encoder
  */
-void drm_bridge_mode_set(struct drm_bridge *bridge,
-			 const struct drm_display_mode *mode,
-			 const struct drm_display_mode *adjusted_mode)
+void drm_bridge_chain_mode_set(struct drm_bridge *bridge,
+			       const struct drm_display_mode *mode,
+			       const struct drm_display_mode *adjusted_mode)
 {
 	if (!bridge)
 		return;
@@ -303,13 +306,13 @@
 	if (bridge->funcs->mode_set)
 		bridge->funcs->mode_set(bridge, mode, adjusted_mode);
 
-	drm_bridge_mode_set(bridge->next, mode, adjusted_mode);
+	drm_bridge_chain_mode_set(bridge->next, mode, adjusted_mode);
 }
-EXPORT_SYMBOL(drm_bridge_mode_set);
+EXPORT_SYMBOL(drm_bridge_chain_mode_set);
 
 /**
- * drm_bridge_pre_enable - prepares for enabling all
- *			   bridges in the encoder chain
+ * drm_bridge_chain_pre_enable - prepares for enabling all bridges in the
+ *				 encoder chain
  * @bridge: bridge control structure
  *
  * Calls &drm_bridge_funcs.pre_enable op for all the bridges in the encoder
@@ -318,20 +321,20 @@
  *
  * Note: the bridge passed should be the one closest to the encoder
  */
-void drm_bridge_pre_enable(struct drm_bridge *bridge)
+void drm_bridge_chain_pre_enable(struct drm_bridge *bridge)
 {
 	if (!bridge)
 		return;
 
-	drm_bridge_pre_enable(bridge->next);
+	drm_bridge_chain_pre_enable(bridge->next);
 
 	if (bridge->funcs->pre_enable)
 		bridge->funcs->pre_enable(bridge);
 }
-EXPORT_SYMBOL(drm_bridge_pre_enable);
+EXPORT_SYMBOL(drm_bridge_chain_pre_enable);
 
 /**
- * drm_bridge_enable - enables all bridges in the encoder chain
+ * drm_bridge_chain_enable - enables all bridges in the encoder chain
  * @bridge: bridge control structure
  *
  * Calls &drm_bridge_funcs.enable op for all the bridges in the encoder
@@ -340,7 +343,7 @@
  *
  * Note that the bridge passed should be the one closest to the encoder
  */
-void drm_bridge_enable(struct drm_bridge *bridge)
+void drm_bridge_chain_enable(struct drm_bridge *bridge)
 {
 	if (!bridge)
 		return;
@@ -348,12 +351,12 @@
 	if (bridge->funcs->enable)
 		bridge->funcs->enable(bridge);
 
-	drm_bridge_enable(bridge->next);
+	drm_bridge_chain_enable(bridge->next);
 }
-EXPORT_SYMBOL(drm_bridge_enable);
+EXPORT_SYMBOL(drm_bridge_chain_enable);
 
 /**
- * drm_atomic_bridge_disable - disables all bridges in the encoder chain
+ * drm_atomic_bridge_chain_disable - disables all bridges in the encoder chain
  * @bridge: bridge control structure
  * @state: atomic state being committed
  *
@@ -364,24 +367,24 @@
  *
  * Note: the bridge passed should be the one closest to the encoder
  */
-void drm_atomic_bridge_disable(struct drm_bridge *bridge,
-			       struct drm_atomic_state *state)
+void drm_atomic_bridge_chain_disable(struct drm_bridge *bridge,
+				     struct drm_atomic_state *state)
 {
 	if (!bridge)
 		return;
 
-	drm_atomic_bridge_disable(bridge->next, state);
+	drm_atomic_bridge_chain_disable(bridge->next, state);
 
 	if (bridge->funcs->atomic_disable)
 		bridge->funcs->atomic_disable(bridge, state);
 	else if (bridge->funcs->disable)
 		bridge->funcs->disable(bridge);
 }
-EXPORT_SYMBOL(drm_atomic_bridge_disable);
+EXPORT_SYMBOL(drm_atomic_bridge_chain_disable);
 
 /**
- * drm_atomic_bridge_post_disable - cleans up after disabling all bridges in the
- *				    encoder chain
+ * drm_atomic_bridge_chain_post_disable - cleans up after disabling all bridges
+ *					  in the encoder chain
  * @bridge: bridge control structure
  * @state: atomic state being committed
  *
@@ -392,8 +395,8 @@
  *
  * Note: the bridge passed should be the one closest to the encoder
  */
-void drm_atomic_bridge_post_disable(struct drm_bridge *bridge,
-				    struct drm_atomic_state *state)
+void drm_atomic_bridge_chain_post_disable(struct drm_bridge *bridge,
+					  struct drm_atomic_state *state)
 {
 	if (!bridge)
 		return;
@@ -403,13 +406,13 @@
 	else if (bridge->funcs->post_disable)
 		bridge->funcs->post_disable(bridge);
 
-	drm_atomic_bridge_post_disable(bridge->next, state);
+	drm_atomic_bridge_chain_post_disable(bridge->next, state);
 }
-EXPORT_SYMBOL(drm_atomic_bridge_post_disable);
+EXPORT_SYMBOL(drm_atomic_bridge_chain_post_disable);
 
 /**
- * drm_atomic_bridge_pre_enable - prepares for enabling all bridges in the
- *				  encoder chain
+ * drm_atomic_bridge_chain_pre_enable - prepares for enabling all bridges in
+ *					the encoder chain
  * @bridge: bridge control structure
  * @state: atomic state being committed
  *
@@ -420,23 +423,23 @@
  *
  * Note: the bridge passed should be the one closest to the encoder
  */
-void drm_atomic_bridge_pre_enable(struct drm_bridge *bridge,
-				  struct drm_atomic_state *state)
+void drm_atomic_bridge_chain_pre_enable(struct drm_bridge *bridge,
+					struct drm_atomic_state *state)
 {
 	if (!bridge)
 		return;
 
-	drm_atomic_bridge_pre_enable(bridge->next, state);
+	drm_atomic_bridge_chain_pre_enable(bridge->next, state);
 
 	if (bridge->funcs->atomic_pre_enable)
 		bridge->funcs->atomic_pre_enable(bridge, state);
 	else if (bridge->funcs->pre_enable)
 		bridge->funcs->pre_enable(bridge);
 }
-EXPORT_SYMBOL(drm_atomic_bridge_pre_enable);
+EXPORT_SYMBOL(drm_atomic_bridge_chain_pre_enable);
 
 /**
- * drm_atomic_bridge_enable - enables all bridges in the encoder chain
+ * drm_atomic_bridge_chain_enable - enables all bridges in the encoder chain
  * @bridge: bridge control structure
  * @state: atomic state being committed
  *
@@ -447,8 +450,8 @@
  *
  * Note: the bridge passed should be the one closest to the encoder
  */
-void drm_atomic_bridge_enable(struct drm_bridge *bridge,
-			      struct drm_atomic_state *state)
+void drm_atomic_bridge_chain_enable(struct drm_bridge *bridge,
+				    struct drm_atomic_state *state)
 {
 	if (!bridge)
 		return;
@@ -458,9 +461,9 @@
 	else if (bridge->funcs->enable)
 		bridge->funcs->enable(bridge);
 
-	drm_atomic_bridge_enable(bridge->next, state);
+	drm_atomic_bridge_chain_enable(bridge->next, state);
 }
-EXPORT_SYMBOL(drm_atomic_bridge_enable);
+EXPORT_SYMBOL(drm_atomic_bridge_chain_enable);
 
 #ifdef CONFIG_OF
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_client_modeset.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_client_modeset.c
@@ -281,6 +281,9 @@
 	can_clone = true;
 	dmt_mode = drm_mode_find_dmt(dev, 1024, 768, 60, false);
 
+	if (!dmt_mode)
+		goto fail;
+
 	for (i = 0; i < connector_count; i++) {
 		if (!enabled[i])
 			continue;
@@ -296,11 +299,13 @@
 		if (!modes[i])
 			can_clone = false;
 	}
+	kfree(dmt_mode);
 
 	if (can_clone) {
 		DRM_DEBUG_KMS("can clone using 1024x768\n");
 		return true;
 	}
+fail:
 	DRM_INFO("kms: can't enable cloning when we probably wanted to.\n");
 	return false;
 }
@@ -695,6 +700,7 @@
 	unsigned int total_modes_count = 0;
 	struct drm_client_offset *offsets;
 	unsigned int connector_count = 0;
+	/* points to modes protected by mode_config.mutex */
 	struct drm_display_mode **modes;
 	struct drm_crtc **crtcs;
 	int i, ret = 0;
@@ -763,7 +769,6 @@
 		drm_client_pick_crtcs(client, connectors, connector_count,
 				      crtcs, modes, 0, width, height);
 	}
-	mutex_unlock(&dev->mode_config.mutex);
 
 	drm_client_modeset_release(client);
 
@@ -785,13 +790,20 @@
 				break;
 			}
 
+			kfree(modeset->mode);
 			modeset->mode = drm_mode_duplicate(dev, mode);
+			if (!modeset->mode) {
+				ret = -ENOMEM;
+				break;
+			}
+
 			drm_connector_get(connector);
 			modeset->connectors[modeset->num_connectors++] = connector;
 			modeset->x = offset->x;
 			modeset->y = offset->y;
 		}
 	}
+	mutex_unlock(&dev->mode_config.mutex);
 
 	mutex_unlock(&client->modeset_mutex);
 out:
@@ -880,7 +892,8 @@
 	 * depending on the hardware this may require the framebuffer
 	 * to be in a specific tiling format.
 	 */
-	if ((*rotation & DRM_MODE_ROTATE_MASK) != DRM_MODE_ROTATE_180 ||
+	if (((*rotation & DRM_MODE_ROTATE_MASK) != DRM_MODE_ROTATE_0 &&
+	     (*rotation & DRM_MODE_ROTATE_MASK) != DRM_MODE_ROTATE_180) ||
 	    !plane->rotation_property)
 		return false;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_connector.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_connector.c
@@ -27,6 +27,7 @@
 #include <drm/drm_print.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_file.h>
+#include <drm/drm_sysfs.h>
 
 #include <linux/uaccess.h>
 
@@ -473,6 +474,9 @@
 	mutex_destroy(&connector->mutex);
 
 	memset(connector, 0, sizeof(*connector));
+
+	if (dev->registered)
+		drm_sysfs_hotplug_event(dev);
 }
 EXPORT_SYMBOL(drm_connector_cleanup);
 
@@ -511,6 +515,10 @@
 	drm_mode_object_register(connector->dev, &connector->base);
 
 	connector->registration_state = DRM_CONNECTOR_REGISTERED;
+
+	/* Let userspace know we have a new connector */
+	drm_sysfs_hotplug_event(connector->dev);
+
 	goto unlock;
 
 err_debugfs:
@@ -904,6 +912,10 @@
  * 	implemented in the DRM core.  This is the only standard connector
  * 	property that userspace can change.
  *
+ * 	On atomic drivers any DPMS setproperty ioctl where the value does not
+ * 	change is completely skipped, otherwise a full atomic commit will occur.
+ * 	On legacy drivers the exact behavior is driver specific.
+ *
  * 	Note that this property cannot be set through the MODE_ATOMIC ioctl,
  * 	userspace must use "ACTIVE" on the CRTC instead.
  *
@@ -1091,6 +1103,14 @@
  *	hdmi_drm_infoframe_pack() to pack the infoframe as per spec, in case of
  *	HDMI encoder.
  *
+ * GEN_HDR_OUTPUT_METADATA:
+ *  This connector property is functionally the same as HDR_OUTPUT_METADATA.
+ *  However, the existing structures for HDR_OUTPUT_METADATA are not flexible
+ *  enough for dynamic HDR or other connectivity devices like SDI. So, this
+ *  property was created to utilize more generic structures that would be
+ *  scalable in the future. This is currently experimental and may possibly
+ *  be merged with the original HDR_OUTPUT_METADATA property in the future.
+ *
  * max bpc:
  *	This range property is used by userspace to limit the bit depth. When
  *	used the driver would limit the bpc in accordance with the valid range
@@ -1192,6 +1212,12 @@
 		return -ENOMEM;
 	dev->mode_config.hdr_output_metadata_property = prop;
 
+	prop = drm_property_create(dev, DRM_MODE_PROP_BLOB,
+				   "GEN_HDR_OUTPUT_METADATA", 0);
+	if (!prop)
+		return -ENOMEM;
+	dev->mode_config.gen_hdr_output_metadata_property = prop;
+
 	return 0;
 }
 
@@ -1979,6 +2005,9 @@
 void drm_connector_set_vrr_capable_property(
 		struct drm_connector *connector, bool capable)
 {
+	if (!connector->vrr_capable_property)
+		return;
+
 	drm_object_property_set_value(&connector->base,
 				      connector->vrr_capable_property,
 				      capable);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_crtc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_crtc.c
@@ -535,8 +535,7 @@
 	struct drm_mode_set set;
 	uint32_t __user *set_connectors_ptr;
 	struct drm_modeset_acquire_ctx ctx;
-	int ret;
-	int i;
+	int ret, i, num_connectors = 0;
 
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		return -EOPNOTSUPP;
@@ -694,6 +693,7 @@
 					connector->name);
 
 			connector_set[i] = connector;
+			num_connectors++;
 		}
 	}
 
@@ -702,7 +702,7 @@
 	set.y = crtc_req->y;
 	set.mode = mode;
 	set.connectors = connector_set;
-	set.num_connectors = crtc_req->count_connectors;
+	set.num_connectors = num_connectors;
 	set.fb = fb;
 
 	if (drm_drv_uses_atomic_modeset(dev))
@@ -715,7 +715,7 @@
 		drm_framebuffer_put(fb);
 
 	if (connector_set) {
-		for (i = 0; i < crtc_req->count_connectors; i++) {
+		for (i = 0; i < num_connectors; i++) {
 			if (connector_set[i])
 				drm_connector_put(connector_set[i]);
 		}
@@ -727,6 +727,7 @@
 	connector_set = NULL;
 	fb = NULL;
 	mode = NULL;
+	num_connectors = 0;
 
 	DRM_MODESET_LOCK_ALL_END(ctx, ret);
 	mutex_unlock(&crtc->dev->mode_config.mutex);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_crtc_helper_internal.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_crtc_helper_internal.h
@@ -32,16 +32,6 @@
 #include <drm/drm_encoder.h>
 #include <drm/drm_modes.h>
 
-/* drm_fb_helper.c */
-#ifdef CONFIG_DRM_FBDEV_EMULATION
-int drm_fb_helper_modinit(void);
-#else
-static inline int drm_fb_helper_modinit(void)
-{
-	return 0;
-}
-#endif
-
 /* drm_dp_aux_dev.c */
 #ifdef CONFIG_DRM_DP_AUX_CHARDEV
 int drm_dp_aux_dev_init(void);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_crtc_internal.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_crtc_internal.h
@@ -216,6 +216,8 @@
 			void *data, struct drm_file *file_priv);
 int drm_mode_getfb(struct drm_device *dev,
 		   void *data, struct drm_file *file_priv);
+int drm_mode_getfb2_ioctl(struct drm_device *dev,
+			  void *data, struct drm_file *file_priv);
 int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
 			   void *data, struct drm_file *file_priv);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_damage_helper.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_damage_helper.c
@@ -212,8 +212,14 @@
 	drm_for_each_plane(plane, fb->dev) {
 		struct drm_plane_state *plane_state;
 
-		if (plane->state->fb != fb)
+		ret = drm_modeset_lock(&plane->mutex, state->acquire_ctx);
+		if (ret)
+			goto out;
+
+		if (plane->state->fb != fb) {
+			drm_modeset_unlock(&plane->mutex);
 			continue;
+		}
 
 		plane_state = drm_atomic_get_plane_state(state, plane);
 		if (IS_ERR(plane_state)) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_debugfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_debugfs.c
@@ -91,6 +91,7 @@
 	mutex_lock(&dev->filelist_mutex);
 	list_for_each_entry_reverse(priv, &dev->filelist, lhead) {
 		struct task_struct *task;
+		bool is_current_master = drm_is_current_master(priv);
 
 		rcu_read_lock(); /* locks pid_task()->comm */
 		task = pid_task(priv->pid, PIDTYPE_PID);
@@ -99,7 +100,7 @@
 			   task ? task->comm : "<unknown>",
 			   pid_vnr(priv->pid),
 			   priv->minor->index,
-			   drm_is_current_master(priv) ? 'y' : 'n',
+			   is_current_master ? 'y' : 'n',
 			   priv->authenticated ? 'y' : 'n',
 			   from_kuid_munged(seq_user_ns(m), uid),
 			   priv->magic);
@@ -337,13 +338,13 @@
 
 	buf[len] = '\0';
 
-	if (!strcmp(buf, "on"))
+	if (sysfs_streq(buf, "on"))
 		connector->force = DRM_FORCE_ON;
-	else if (!strcmp(buf, "digital"))
+	else if (sysfs_streq(buf, "digital"))
 		connector->force = DRM_FORCE_ON_DIGITAL;
-	else if (!strcmp(buf, "off"))
+	else if (sysfs_streq(buf, "off"))
 		connector->force = DRM_FORCE_OFF;
-	else if (!strcmp(buf, "unspecified"))
+	else if (sysfs_streq(buf, "unspecified"))
 		connector->force = DRM_FORCE_UNSPECIFIED;
 	else
 		return -EINVAL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_debugfs_crc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_debugfs_crc.c
@@ -140,12 +140,14 @@
 	if (IS_ERR(source))
 		return PTR_ERR(source);
 
-	if (source[len] == '\n')
-		source[len] = '\0';
+	if (source[len - 1] == '\n')
+		source[len - 1] = '\0';
 
 	ret = crtc->funcs->verify_crc_source(crtc, source, &values_cnt);
-	if (ret)
+	if (ret) {
+		kfree(source);
 		return ret;
+	}
 
 	spin_lock_irq(&crc->lock);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_dp_aux_dev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_dp_aux_dev.c
@@ -63,7 +63,7 @@
 
 	mutex_lock(&aux_idr_mutex);
 	aux_dev = idr_find(&aux_idr, index);
-	if (!kref_get_unless_zero(&aux_dev->refcount))
+	if (aux_dev && !kref_get_unless_zero(&aux_dev->refcount))
 		aux_dev = NULL;
 	mutex_unlock(&aux_idr_mutex);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_dp_cec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_dp_cec.c
@@ -303,16 +303,6 @@
 	if (!aux->transfer)
 		return;
 
-#ifndef CONFIG_MEDIA_CEC_RC
-	/*
-	 * CEC_CAP_RC is part of CEC_CAP_DEFAULTS, but it is stripped by
-	 * cec_allocate_adapter() if CONFIG_MEDIA_CEC_RC is undefined.
-	 *
-	 * Do this here as well to ensure the tests against cec_caps are
-	 * correct.
-	 */
-	cec_caps &= ~CEC_CAP_RC;
-#endif
 	cancel_delayed_work_sync(&aux->cec.unregister_work);
 
 	mutex_lock(&aux->cec.lock);
@@ -329,7 +319,9 @@
 		num_las = CEC_MAX_LOG_ADDRS;
 
 	if (aux->cec.adap) {
-		if (aux->cec.adap->capabilities == cec_caps &&
+		/* Check if the adapter properties have changed */
+		if ((aux->cec.adap->capabilities & CEC_CAP_MONITOR_ALL) ==
+		    (cec_caps & CEC_CAP_MONITOR_ALL) &&
 		    aux->cec.adap->available_log_addrs == num_las) {
 			/* Unchanged, so just set the phys addr */
 			cec_s_phys_addr_from_edid(aux->cec.adap, edid);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_dp_helper.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_dp_helper.c
@@ -1302,6 +1302,99 @@
 #undef DEVICE_ID_ANY
 #undef DEVICE_ID
 
+struct edid_quirk {
+	u8 mfg_id[2];
+	u8 prod_id[2];
+	u32 quirks;
+};
+
+#define MFG(first, second) { (first), (second) }
+#define PROD_ID(first, second) { (first), (second) }
+
+/*
+ * Some devices have unreliable OUIDs where they don't set the device ID
+ * correctly, and as a result we need to use the EDID for finding additional
+ * DP quirks in such cases.
+ */
+static const struct edid_quirk edid_quirk_list[] = {
+	/* Optional 4K AMOLED panel in the ThinkPad X1 Extreme 2nd Generation
+	 * only supports DPCD backlight controls
+	 */
+	{ MFG(0x4c, 0x83), PROD_ID(0x41, 0x41), BIT(DP_QUIRK_FORCE_DPCD_BACKLIGHT) },
+	/* HP Spectre x360 Convertible 13t-aw100 */
+	{ MFG(0x4c, 0x83), PROD_ID(0x42, 0x41), BIT(DP_QUIRK_FORCE_DPCD_BACKLIGHT) },
+	/* HP CML 2020 system */
+	{ MFG(0x4c, 0x83), PROD_ID(0x45, 0x41), BIT(DP_QUIRK_FORCE_DPCD_BACKLIGHT) },
+	/*
+	 * Some Dell CML 2020 systems have panels support both AUX and PWM
+	 * backlight control, and some only support AUX backlight control. All
+	 * said panels start up in AUX mode by default, and we don't have any
+	 * support for disabling HDR mode on these panels which would be
+	 * required to switch to PWM backlight control mode (plus, I'm not
+	 * even sure we want PWM backlight controls over DPCD backlight
+	 * controls anyway...). Until we have a better way of detecting these,
+	 * force DPCD backlight mode on all of them.
+	 */
+	{ MFG(0x06, 0xaf), PROD_ID(0x8c, 0xcd), BIT(DP_QUIRK_FORCE_DPCD_BACKLIGHT) },
+	{ MFG(0x06, 0xaf), PROD_ID(0x9b, 0x32), BIT(DP_QUIRK_FORCE_DPCD_BACKLIGHT) },
+	{ MFG(0x06, 0xaf), PROD_ID(0xeb, 0x41), BIT(DP_QUIRK_FORCE_DPCD_BACKLIGHT) },
+	{ MFG(0x30, 0xe4), PROD_ID(0x61, 0x06), BIT(DP_QUIRK_FORCE_DPCD_BACKLIGHT) },
+	{ MFG(0x4d, 0x10), PROD_ID(0xc7, 0x14), BIT(DP_QUIRK_FORCE_DPCD_BACKLIGHT) },
+	{ MFG(0x4d, 0x10), PROD_ID(0xe6, 0x14), BIT(DP_QUIRK_FORCE_DPCD_BACKLIGHT) },
+	{ MFG(0x4c, 0x83), PROD_ID(0x47, 0x41), BIT(DP_QUIRK_FORCE_DPCD_BACKLIGHT) },
+	{ MFG(0x4c, 0x83), PROD_ID(0x4f, 0x41), BIT(DP_QUIRK_FORCE_DPCD_BACKLIGHT) },
+	{ MFG(0x4c, 0x83), PROD_ID(0x4d, 0x41), BIT(DP_QUIRK_FORCE_DPCD_BACKLIGHT) },
+	/*
+	 * Some HP ZBook Studio G7 systems have panels support and relies on
+	 * PSR being enabled.
+	 */
+	{ MFG(0x0d, 0xae), PROD_ID(0x19, 0x15), BIT(DP_QUIRK_FORCE_PSR_CHIP_DEFAULT) },
+};
+
+#undef MFG
+#undef PROD_ID
+
+/**
+ * drm_dp_get_edid_quirks() - Check the EDID of a DP device to find additional
+ * DP-specific quirks
+ * @edid: The EDID to check
+ *
+ * While OUIDs are meant to be used to recognize a DisplayPort device, a lot
+ * of manufacturers don't seem to like following standards and neglect to fill
+ * the dev-ID in, making it impossible to only use OUIDs for determining
+ * quirks in some cases. This function can be used to check the EDID and look
+ * up any additional DP quirks. The bits returned by this function correspond
+ * to the quirk bits in &drm_dp_quirk.
+ *
+ * Returns: a bitmask of quirks, if any. The driver can check this using
+ * drm_dp_has_quirk().
+ */
+u32 drm_dp_get_edid_quirks(const struct edid *edid)
+{
+	const struct edid_quirk *quirk;
+	u32 quirks = 0;
+	int i;
+
+	if (!edid)
+		return 0;
+
+	for (i = 0; i < ARRAY_SIZE(edid_quirk_list); i++) {
+		quirk = &edid_quirk_list[i];
+		if (memcmp(quirk->mfg_id, edid->mfg_id,
+			   sizeof(edid->mfg_id)) == 0 &&
+		    memcmp(quirk->prod_id, edid->prod_code,
+			   sizeof(edid->prod_code)) == 0)
+			quirks |= quirk->quirks;
+	}
+
+	DRM_DEBUG_KMS("DP sink: EDID mfg %*phD prod-ID %*phD quirks: 0x%04x\n",
+		      (int)sizeof(edid->mfg_id), edid->mfg_id,
+		      (int)sizeof(edid->prod_code), edid->prod_code, quirks);
+
+	return quirks;
+}
+EXPORT_SYMBOL(drm_dp_get_edid_quirks);
+
 /**
  * drm_dp_read_desc - read sink/branch descriptor from DPCD
  * @aux: DisplayPort AUX channel
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_dp_mst_topology.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -27,6 +27,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/seq_file.h>
+#include <linux/iopoll.h>
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
@@ -339,7 +340,7 @@
 			memcpy(&buf[idx], req->u.i2c_read.transactions[i].bytes, req->u.i2c_read.transactions[i].num_bytes);
 			idx += req->u.i2c_read.transactions[i].num_bytes;
 
-			buf[idx] = (req->u.i2c_read.transactions[i].no_stop_bit & 0x1) << 5;
+			buf[idx] = (req->u.i2c_read.transactions[i].no_stop_bit & 0x1) << 4;
 			buf[idx] |= (req->u.i2c_read.transactions[i].i2c_transaction_delay & 0xf);
 			idx++;
 		}
@@ -1805,14 +1806,14 @@
 	struct drm_dp_mst_branch *found_mstb;
 	struct drm_dp_mst_port *port;
 
+	if (!mstb)
+		return NULL;
+
 	if (memcmp(mstb->guid, guid, 16) == 0)
 		return mstb;
 
 
 	list_for_each_entry(port, &mstb->ports, next) {
-		if (!port->mstb)
-			continue;
-
 		found_mstb = get_mst_branch_device_by_guid_helper(port->mstb, guid);
 
 		if (found_mstb)
@@ -2465,9 +2466,11 @@
 			drm_dp_mst_topology_put_port(port);
 	}
 
-	for (i = 0; i < mgr->max_payloads; i++) {
-		if (mgr->payloads[i].payload_state != DP_PAYLOAD_DELETE_LOCAL)
+	for (i = 0; i < mgr->max_payloads; /* do nothing */) {
+		if (mgr->payloads[i].payload_state != DP_PAYLOAD_DELETE_LOCAL) {
+			i++;
 			continue;
+		}
 
 		DRM_DEBUG_KMS("removing payload %d\n", i);
 		for (j = i; j < mgr->max_payloads - 1; j++) {
@@ -2694,6 +2697,7 @@
 	int ret = 0;
 	struct drm_dp_mst_branch *mstb = NULL;
 
+	mutex_lock(&mgr->payload_lock);
 	mutex_lock(&mgr->lock);
 	if (mst_state == mgr->mst_state)
 		goto out_unlock;
@@ -2752,7 +2756,10 @@
 		/* this can fail if the device is gone */
 		drm_dp_dpcd_writeb(mgr->aux, DP_MSTM_CTRL, 0);
 		ret = 0;
-		memset(mgr->payloads, 0, mgr->max_payloads * sizeof(struct drm_dp_payload));
+		memset(mgr->payloads, 0,
+		       mgr->max_payloads * sizeof(mgr->payloads[0]));
+		memset(mgr->proposed_vcpis, 0,
+		       mgr->max_payloads * sizeof(mgr->proposed_vcpis[0]));
 		mgr->payload_mask = 0;
 		set_bit(0, &mgr->payload_mask);
 		mgr->vcpi_mask = 0;
@@ -2760,6 +2767,7 @@
 
 out_unlock:
 	mutex_unlock(&mgr->lock);
+	mutex_unlock(&mgr->payload_lock);
 	if (mstb)
 		drm_dp_mst_topology_put_mstb(mstb);
 	return ret;
@@ -3361,11 +3369,11 @@
 {
 	int ret;
 
-	port = drm_dp_mst_topology_get_port_validated(mgr, port);
-	if (!port)
+	if (slots < 0)
 		return false;
 
-	if (slots < 0)
+	port = drm_dp_mst_topology_get_port_validated(mgr, port);
+	if (!port)
 		return false;
 
 	if (port->vcpi.vcpi > 0) {
@@ -3381,6 +3389,7 @@
 	if (ret) {
 		DRM_DEBUG_KMS("failed to init vcpi slots=%d max=63 ret=%d\n",
 			      DIV_ROUND_UP(pbn, mgr->pbn_div), ret);
+		drm_dp_mst_topology_put_port(port);
 		goto out;
 	}
 	DRM_DEBUG_KMS("initing vcpi for pbn=%d slots=%d\n",
@@ -3491,6 +3500,17 @@
 	return ret;
 }
 
+static int do_get_act_status(struct drm_dp_aux *aux)
+{
+	int ret;
+	u8 status;
+
+	ret = drm_dp_dpcd_readb(aux, DP_PAYLOAD_TABLE_UPDATE_STATUS, &status);
+	if (ret < 0)
+		return ret;
+
+	return status;
+}
 
 /**
  * drm_dp_check_act_status() - Check ACT handled status.
@@ -3500,33 +3520,29 @@
  */
 int drm_dp_check_act_status(struct drm_dp_mst_topology_mgr *mgr)
 {
-	u8 status;
-	int ret;
-	int count = 0;
-
-	do {
-		ret = drm_dp_dpcd_readb(mgr->aux, DP_PAYLOAD_TABLE_UPDATE_STATUS, &status);
-
-		if (ret < 0) {
-			DRM_DEBUG_KMS("failed to read payload table status %d\n", ret);
-			goto fail;
-		}
-
-		if (status & DP_PAYLOAD_ACT_HANDLED)
-			break;
-		count++;
-		udelay(100);
-
-	} while (count < 30);
+	/*
+	 * There doesn't seem to be any recommended retry count or timeout in
+	 * the MST specification. Since some hubs have been observed to take
+	 * over 1 second to update their payload allocations under certain
+	 * conditions, we use a rather large timeout value.
+	 */
+	const int timeout_ms = 3000;
+	int ret, status;
 
-	if (!(status & DP_PAYLOAD_ACT_HANDLED)) {
-		DRM_DEBUG_KMS("failed to get ACT bit %d after %d retries\n", status, count);
-		ret = -EINVAL;
-		goto fail;
+	ret = readx_poll_timeout(do_get_act_status, mgr->aux, status,
+				 status & DP_PAYLOAD_ACT_HANDLED || status < 0,
+				 200, timeout_ms * USEC_PER_MSEC);
+	if (ret < 0 && status >= 0) {
+		DRM_DEBUG_KMS("Failed to get ACT after %dms, last status: %02x\n",
+			      timeout_ms, status);
+		return -EINVAL;
+	} else if (status < 0) {
+		DRM_DEBUG_KMS("Failed to read payload table status: %d\n",
+			      status);
+		return status;
 	}
+
 	return 0;
-fail:
-	return ret;
 }
 EXPORT_SYMBOL(drm_dp_check_act_status);
 
@@ -3641,6 +3657,7 @@
 
 	mst_edid = drm_dp_mst_get_edid(port->connector, mgr, port);
 	drm_edid_get_monitor_name(mst_edid, name, namelen);
+	kfree(mst_edid);
 }
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_drv.c
@@ -984,8 +984,11 @@
 			goto err_minors;
 	}
 
-	if (drm_core_check_feature(dev, DRIVER_MODESET))
-		drm_modeset_register_all(dev);
+	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+		ret = drm_modeset_register_all(dev);
+		if (ret)
+			goto err_unload;
+	}
 
 	ret = 0;
 
@@ -997,6 +1000,9 @@
 
 	goto out_unlock;
 
+err_unload:
+	if (dev->driver->unload)
+		dev->driver->unload(dev);
 err_minors:
 	remove_compat_control_link(dev);
 	drm_minor_unregister(dev, DRM_MINOR_PRIMARY);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_edid.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_edid.c
@@ -191,10 +191,11 @@
 	{ "HVR", 0xaa01, EDID_QUIRK_NON_DESKTOP },
 	{ "HVR", 0xaa02, EDID_QUIRK_NON_DESKTOP },
 
-	/* Oculus Rift DK1, DK2, and CV1 VR Headsets */
+	/* Oculus Rift DK1, DK2, CV1 and Rift S VR Headsets */
 	{ "OVR", 0x0001, EDID_QUIRK_NON_DESKTOP },
 	{ "OVR", 0x0003, EDID_QUIRK_NON_DESKTOP },
 	{ "OVR", 0x0004, EDID_QUIRK_NON_DESKTOP },
+	{ "OVR", 0x0012, EDID_QUIRK_NON_DESKTOP },
 
 	/* Windows Mixed Reality Headsets */
 	{ "ACR", 0x7fce, EDID_QUIRK_NON_DESKTOP },
@@ -1701,9 +1702,6 @@
 
 		connector_bad_edid(connector, edid, edid[0x7e] + 1);
 
-		edid[EDID_LENGTH-1] += edid[0x7e] - valid_extensions;
-		edid[0x7e] = valid_extensions;
-
 		new = kmalloc_array(valid_extensions + 1, EDID_LENGTH,
 				    GFP_KERNEL);
 		if (!new)
@@ -1720,6 +1718,9 @@
 			base += EDID_LENGTH;
 		}
 
+		new[EDID_LENGTH - 1] += new[0x7e] - valid_extensions;
+		new[0x7e] = valid_extensions;
+
 		kfree(edid);
 		edid = new;
 	}
@@ -2770,7 +2771,7 @@
 	const u8 empty[3] = { 0, 0, 0 };
 
 	for (i = 0; i < 4; i++) {
-		int uninitialized_var(width), height;
+		int width, height;
 		cvt = &(timing->data.other_data.data.cvt[i]);
 
 		if (!memcmp(cvt->code, empty, 3))
@@ -2778,6 +2779,8 @@
 
 		height = (cvt->code[0] + ((cvt->code[1] & 0xf0) << 4) + 1) * 2;
 		switch (cvt->code[1] & 0x0c) {
+		/* default - because compiler doesn't see that we've enumerated all cases */
+		default:
 		case 0x00:
 			width = height * 4 / 3;
 			break;
@@ -3722,7 +3725,7 @@
 		if (*end < 4 || *end > 127)
 			return -ERANGE;
 	} else {
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 	}
 
 	return 0;
@@ -4191,7 +4194,7 @@
 
 	if (cea_revision(cea) < 3) {
 		DRM_DEBUG_KMS("SAD: wrong CEA revision\n");
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 	}
 
 	if (cea_db_offsets(cea, &start, &end)) {
@@ -4252,7 +4255,7 @@
 
 	if (cea_revision(cea) < 3) {
 		DRM_DEBUG_KMS("SAD: wrong CEA revision\n");
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 	}
 
 	if (cea_db_offsets(cea, &start, &end)) {
@@ -4379,7 +4382,8 @@
 	if (!edid_ext)
 		goto end;
 
-	has_audio = ((edid_ext[3] & EDID_BASIC_AUDIO) != 0);
+	has_audio = (edid_ext[0] == CEA_EXT &&
+		    (edid_ext[3] & EDID_BASIC_AUDIO) != 0);
 
 	if (has_audio) {
 		DRM_DEBUG_KMS("Monitor has basic audio support\n");
@@ -4532,16 +4536,8 @@
 		  connector->name, dc_bpc);
 	info->bpc = dc_bpc;
 
-	/*
-	 * Deep color support mandates RGB444 support for all video
-	 * modes and forbids YCRCB422 support for all video modes per
-	 * HDMI 1.3 spec.
-	 */
-	info->color_formats = DRM_COLOR_FORMAT_RGB444;
-
 	/* YCRCB444 is optional according to spec. */
 	if (hdmi[6] & DRM_EDID_HDMI_DC_Y444) {
-		info->color_formats |= DRM_COLOR_FORMAT_YCRCB444;
 		DRM_DEBUG("%s: HDMI sink does YCRCB444 in deep color.\n",
 			  connector->name);
 	}
@@ -4658,6 +4654,7 @@
 	if (!(edid->input & DRM_EDID_INPUT_DIGITAL))
 		return quirks;
 
+	info->color_formats |= DRM_COLOR_FORMAT_RGB444;
 	drm_parse_cea_ext(connector, edid);
 
 	/*
@@ -4706,7 +4703,6 @@
 	DRM_DEBUG("%s: Assigning EDID-1.4 digital sink color depth as %d bpc.\n",
 			  connector->name, info->bpc);
 
-	info->color_formats |= DRM_COLOR_FORMAT_RGB444;
 	if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB444)
 		info->color_formats |= DRM_COLOR_FORMAT_YCRCB444;
 	if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB422)
@@ -4743,7 +4739,7 @@
 	struct drm_display_mode *mode;
 	unsigned pixel_clock = (timings->pixel_clock[0] |
 				(timings->pixel_clock[1] << 8) |
-				(timings->pixel_clock[2] << 16));
+				(timings->pixel_clock[2] << 16)) + 1;
 	unsigned hactive = (timings->hactive[0] | timings->hactive[1] << 8) + 1;
 	unsigned hblank = (timings->hblank[0] | timings->hblank[1] << 8) + 1;
 	unsigned hsync = (timings->hsync[0] | (timings->hsync[1] & 0x7f) << 8) + 1;
@@ -5072,6 +5068,79 @@
 EXPORT_SYMBOL(drm_hdmi_infoframe_set_hdr_metadata);
 
 /**
+ * drm_hdmi_infoframe_set_gen_hdr_metadata() - fill an HDMI DRM infoframe with
+ *                                             HDR metadata from userspace
+ * @frame: HDMI DRM infoframe
+ * @conn_state: Connector state containing HDR metadata
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int
+drm_hdmi_infoframe_set_gen_hdr_metadata(struct hdmi_drm_infoframe *frame,
+					const struct drm_connector_state *conn_state)
+{
+	struct drm_connector *connector;
+	struct gen_hdr_output_metadata *gen_hdr_metadata;
+	struct hdr_metadata_infoframe *hdr_infoframe;
+	int err;
+
+	if (!frame || !conn_state)
+		return -EINVAL;
+
+	connector = conn_state->connector;
+
+	if (!conn_state->gen_hdr_output_metadata)
+		return -EINVAL;
+
+	gen_hdr_metadata = conn_state->gen_hdr_output_metadata->data;
+
+	if (!gen_hdr_metadata || !connector)
+		return -EINVAL;
+
+	if (gen_hdr_metadata->metadata_type == DRM_HDR_TYPE_HDR10) {
+		hdr_infoframe = (struct hdr_metadata_infoframe *)
+			gen_hdr_metadata->payload;
+
+		/* Sink EOTF is Bit map while infoframe is absolute values */
+		if (!is_eotf_supported(hdr_infoframe->eotf,
+		    connector->hdr_sink_metadata.hdmi_type1.eotf)) {
+			DRM_DEBUG_KMS("EOTF Not Supported\n");
+			return -EINVAL;
+		}
+
+		err = hdmi_drm_infoframe_init(frame);
+		if (err < 0)
+			return err;
+
+		frame->eotf = hdr_infoframe->eotf;
+		frame->metadata_type = hdr_infoframe->metadata_type;
+
+		BUILD_BUG_ON(sizeof(frame->display_primaries) !=
+			     sizeof(hdr_infoframe->display_primaries));
+		BUILD_BUG_ON(sizeof(frame->white_point) !=
+			     sizeof(hdr_infoframe->white_point));
+
+		memcpy(&frame->display_primaries,
+		       &hdr_infoframe->display_primaries,
+		       sizeof(frame->display_primaries));
+
+		memcpy(&frame->white_point,
+		       &hdr_infoframe->white_point,
+		       sizeof(frame->white_point));
+
+		frame->max_display_mastering_luminance =
+			hdr_infoframe->max_display_mastering_luminance;
+		frame->min_display_mastering_luminance =
+			hdr_infoframe->min_display_mastering_luminance;
+		frame->max_fall = hdr_infoframe->max_fall;
+		frame->max_cll = hdr_infoframe->max_cll;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_hdmi_infoframe_set_gen_hdr_metadata);
+
+/**
  * drm_hdmi_avi_infoframe_from_display_mode() - fill an HDMI AVI infoframe with
  *                                              data from a DRM display mode
  * @frame: HDMI AVI infoframe
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_encoder.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_encoder.c
@@ -170,7 +170,7 @@
 		struct drm_bridge *next;
 
 		while (bridge) {
-			next = bridge->next;
+			next = drm_bridge_get_next_bridge(bridge);
 			drm_bridge_detach(bridge);
 			bridge = next;
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_encoder_slave.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_encoder_slave.c
@@ -84,7 +84,7 @@
 
 	err = encoder_drv->encoder_init(client, dev, encoder);
 	if (err)
-		goto fail_unregister;
+		goto fail_module_put;
 
 	if (info->platform_data)
 		encoder->slave_funcs->set_config(&encoder->base,
@@ -92,9 +92,10 @@
 
 	return 0;
 
+fail_module_put:
+	module_put(module);
 fail_unregister:
 	i2c_unregister_device(client);
-	module_put(module);
 fail:
 	return err;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_fb_cma_helper.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_fb_cma_helper.c
@@ -68,7 +68,6 @@
 	u8 h_div = 1, v_div = 1;
 	u32 block_w = drm_format_info_block_width(fb->format, plane);
 	u32 block_h = drm_format_info_block_height(fb->format, plane);
-	u32 block_size = fb->format->char_per_block[plane];
 	u32 sample_x;
 	u32 sample_y;
 	u32 block_start_y;
@@ -91,7 +90,7 @@
 	num_hblocks = sample_x / block_w;
 
 	paddr += fb->pitches[plane] * block_start_y;
-	paddr += block_size * num_hblocks;
+	paddr += drm_format_plane_width_bytes(fb->format, plane, num_hblocks);
 
 	return paddr;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_fb_helper.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_fb_helper.c
@@ -72,7 +72,7 @@
  * considered as a broken and legacy behaviour from a modern fbdev device.
  */
 #if IS_ENABLED(CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM)
-static bool drm_leak_fbdev_smem = false;
+static bool drm_leak_fbdev_smem = true;
 module_param_unsafe(drm_leak_fbdev_smem, bool, 0600);
 MODULE_PARM_DESC(drm_leak_fbdev_smem,
 		 "Allow unsafe leaking fbdev physical smem address [default=false]");
@@ -390,7 +390,11 @@
 	unsigned int y;
 
 	for (y = clip->y1; y < clip->y2; y++) {
-		memcpy(dst, src, len);
+		if (!fb_helper->dev->mode_config.fbdev_use_iomem)
+			memcpy(dst, src, len);
+		else
+			memcpy_toio((void __iomem *)dst, src, len);
+
 		src += fb->pitches[0];
 		dst += fb->pitches[0];
 	}
@@ -961,11 +965,15 @@
 	drm_modeset_lock_all(fb_helper->dev);
 	drm_client_for_each_modeset(modeset, &fb_helper->client) {
 		crtc = modeset->crtc;
-		if (!crtc->funcs->gamma_set || !crtc->gamma_size)
-			return -EINVAL;
+		if (!crtc->funcs->gamma_set || !crtc->gamma_size) {
+			ret = -EINVAL;
+			goto out;
+		}
 
-		if (cmap->start + cmap->len > crtc->gamma_size)
-			return -EINVAL;
+		if (cmap->start + cmap->len > crtc->gamma_size) {
+			ret = -EINVAL;
+			goto out;
+		}
 
 		r = crtc->gamma_store;
 		g = r + crtc->gamma_size;
@@ -978,8 +986,9 @@
 		ret = crtc->funcs->gamma_set(crtc, r, g, b,
 					     crtc->gamma_size, NULL);
 		if (ret)
-			return ret;
+			goto out;
 	}
+out:
 	drm_modeset_unlock_all(fb_helper->dev);
 
 	return ret;
@@ -1320,7 +1329,7 @@
 	 * Changes struct fb_var_screeninfo are currently not pushed back
 	 * to KMS, hence fail if different settings are requested.
 	 */
-	if (var->bits_per_pixel != fb->format->cpp[0] * 8 ||
+	if (var->bits_per_pixel > fb->format->cpp[0] * 8 ||
 	    var->xres > fb->width || var->yres > fb->height ||
 	    var->xres_virtual > fb->width || var->yres_virtual > fb->height) {
 		DRM_DEBUG("fb requested width/height/bpp can't fit in current fb "
@@ -1331,6 +1340,9 @@
 		return -EINVAL;
 	}
 
+	var->xres_virtual = fb->width;
+	var->yres_virtual = fb->height;
+
 	/*
 	 * Workaround for SDL 1.2, which is known to be setting all pixel format
 	 * fields values to zero in some cases. We treat this situation as a
@@ -1346,6 +1358,11 @@
 	}
 
 	/*
+	 * Likewise, bits_per_pixel should be rounded up to a supported value.
+	 */
+	var->bits_per_pixel = fb->format->cpp[0] * 8;
+
+	/*
 	 * drm fbdev emulation doesn't support changing the pixel format at all,
 	 * so reject all pixel format changing requests.
 	 */
@@ -2401,24 +2418,3 @@
 	return 0;
 }
 EXPORT_SYMBOL(drm_fbdev_generic_setup);
-
-/* The Kconfig DRM_KMS_HELPER selects FRAMEBUFFER_CONSOLE (if !EXPERT)
- * but the module doesn't depend on any fb console symbols.  At least
- * attempt to load fbcon to avoid leaving the system without a usable console.
- */
-int __init drm_fb_helper_modinit(void)
-{
-#if defined(CONFIG_FRAMEBUFFER_CONSOLE_MODULE) && !defined(CONFIG_EXPERT)
-	const char name[] = "fbcon";
-	struct module *fbcon;
-
-	mutex_lock(&module_mutex);
-	fbcon = find_module(name);
-	mutex_unlock(&module_mutex);
-
-	if (!fbcon)
-		request_module_nowait(name);
-#endif
-	return 0;
-}
-EXPORT_SYMBOL(drm_fb_helper_modinit);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_file.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_file.c
@@ -369,7 +369,7 @@
 {
 	struct drm_device *dev;
 	struct drm_minor *minor;
-	int retcode;
+	int retcode = 0;
 	int need_setup = 0;
 
 	minor = drm_minor_acquire(iminor(inode));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_fourcc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_fourcc.c
@@ -29,6 +29,7 @@
 
 #include <drm/drm_device.h>
 #include <drm/drm_fourcc.h>
+#include <drm/drm_print.h>
 
 static char printable_char(int c)
 {
@@ -178,6 +179,10 @@
 		{ .format = DRM_FORMAT_BGRA5551,	.depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
 		{ .format = DRM_FORMAT_RGB565,		.depth = 16, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
 		{ .format = DRM_FORMAT_BGR565,		.depth = 16, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+#ifdef __BIG_ENDIAN
+		{ .format = DRM_FORMAT_XRGB1555 | DRM_FORMAT_BIG_ENDIAN, .depth = 15, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN, .depth = 16, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+#endif
 		{ .format = DRM_FORMAT_RGB888,		.depth = 24, .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1 },
 		{ .format = DRM_FORMAT_BGR888,		.depth = 24, .num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1 },
 		{ .format = DRM_FORMAT_XRGB8888,	.depth = 24, .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
@@ -224,6 +229,8 @@
 		{ .format = DRM_FORMAT_NV61,		.depth = 0,  .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
 		{ .format = DRM_FORMAT_NV24,		.depth = 0,  .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true },
 		{ .format = DRM_FORMAT_NV42,		.depth = 0,  .num_planes = 2, .cpp = { 1, 2, 0 }, .hsub = 1, .vsub = 1, .is_yuv = true },
+		{ .format = DRM_FORMAT_XV15,		.depth = 0,  .num_planes = 2, .pixels_per_macropixel = { 3, 3, 0 }, .bytes_per_macropixel = { 4, 8, 0 }, .hsub = 2, .vsub = 2, }, /* FIXME consider is_yuv = true */
+		{ .format = DRM_FORMAT_XV20,		.depth = 0,  .num_planes = 2, .pixels_per_macropixel = { 3, 3, 0 }, .bytes_per_macropixel = { 4, 8, 0 }, .hsub = 2, .vsub = 1, },
 		{ .format = DRM_FORMAT_YUYV,		.depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
 		{ .format = DRM_FORMAT_YVYU,		.depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
 		{ .format = DRM_FORMAT_UYVY,		.depth = 0,  .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 2, .vsub = 1, .is_yuv = true },
@@ -274,6 +281,11 @@
 		{ .format = DRM_FORMAT_YUV420_10BIT,    .depth = 0,
 		  .num_planes = 1, .cpp = { 0, 0, 0 }, .hsub = 2, .vsub = 2,
 		  .is_yuv = true },
+		{ .format = DRM_FORMAT_AVUY,		.depth = 0,  .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
+		{ .format = DRM_FORMAT_XVUY8888,	.depth = 0,  .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_XVUY2101010,	.depth = 0,  .num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_Y8,		.depth = 0,  .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 },
+		{ .format = DRM_FORMAT_Y10,		.depth = 0,  .num_planes = 1, .pixels_per_macropixel =  { 3, 0, 0 }, .bytes_per_macropixel = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
 	};
 
 	unsigned int i;
@@ -393,3 +405,38 @@
 			    drm_format_info_block_height(info, plane));
 }
 EXPORT_SYMBOL(drm_format_info_min_pitch);
+
+/**
+ * drm_format_plane_width_bytes - bytes of the given width of the plane
+ * @info: DRM format information
+ * @plane: plane index
+ * @width: width to get the number of bytes
+ *
+ * This returns the number of bytes for given @width and @plane.
+ * The @char_per_block or macro pixel information should be valid.
+ *
+ * Returns:
+ * The bytes of @width of @plane. 0 for invalid format info.
+ */
+uint64_t drm_format_plane_width_bytes(const struct drm_format_info *info,
+				 int plane, unsigned int width)
+{
+	if (!info || plane >= info->num_planes)
+		return 0;
+
+	if (info->char_per_block[plane])
+		return drm_format_info_min_pitch(info, plane, width);
+
+	if (WARN_ON(!info->bytes_per_macropixel[plane] ||
+		    !info->pixels_per_macropixel[plane])) {
+		struct drm_format_name_buf buf;
+
+		DRM_WARN("Either cpp or macro-pixel info should be valid: %s\n",
+			 drm_get_format_name(info->format, &buf));
+		return 0;
+	}
+
+	return DIV_ROUND_UP(width * info->bytes_per_macropixel[plane],
+			    info->pixels_per_macropixel[plane]);
+}
+EXPORT_SYMBOL(drm_format_plane_width_bytes);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_framebuffer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_framebuffer.c
@@ -31,6 +31,7 @@
 #include <drm/drm_file.h>
 #include <drm/drm_fourcc.h>
 #include <drm/drm_framebuffer.h>
+#include <drm/drm_gem.h>
 #include <drm/drm_print.h>
 #include <drm/drm_util.h>
 
@@ -201,7 +202,8 @@
 	for (i = 0; i < info->num_planes; i++) {
 		unsigned int width = fb_plane_width(r->width, info, i);
 		unsigned int height = fb_plane_height(r->height, info, i);
-		unsigned int block_size = info->char_per_block[i];
+		unsigned int block_size = info->char_per_block[i] ||
+					  info->bytes_per_macropixel[i];
 		u64 min_pitch = drm_format_info_min_pitch(info, i, width);
 
 		if (!block_size && (r->modifier[i] == DRM_FORMAT_MOD_LINEAR)) {
@@ -295,7 +297,8 @@
 	struct drm_framebuffer *fb;
 	int ret;
 
-	if (r->flags & ~(DRM_MODE_FB_INTERLACED | DRM_MODE_FB_MODIFIERS)) {
+	if (r->flags & ~(DRM_MODE_FB_INTERLACED | DRM_MODE_FB_MODIFIERS |
+	    DRM_MODE_FB_ALTERNATE_TOP | DRM_MODE_FB_ALTERNATE_BOTTOM)) {
 		DRM_DEBUG_KMS("bad framebuffer flags 0x%08x\n", r->flags);
 		return ERR_PTR(-EINVAL);
 	}
@@ -548,7 +551,128 @@
 
 out:
 	drm_framebuffer_put(fb);
+	return ret;
+}
+
+/**
+ * drm_mode_getfb2 - get extended FB info
+ * @dev: drm device for the ioctl
+ * @data: data pointer for the ioctl
+ * @file_priv: drm file for the ioctl call
+ *
+ * Lookup the FB given its ID and return info about it.
+ *
+ * Called by the user via ioctl.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_mode_getfb2_ioctl(struct drm_device *dev,
+			  void *data, struct drm_file *file_priv)
+{
+	struct drm_mode_fb_cmd2 *r = data;
+	struct drm_framebuffer *fb;
+	unsigned int i;
+	int ret;
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
+	fb = drm_framebuffer_lookup(dev, file_priv, r->fb_id);
+	if (!fb)
+		return -ENOENT;
+
+	/* For multi-plane framebuffers, we require the driver to place the
+	 * GEM objects directly in the drm_framebuffer. For single-plane
+	 * framebuffers, we can fall back to create_handle.
+	 */
+	if (!fb->obj[0] &&
+	    (fb->format->num_planes > 1 || !fb->funcs->create_handle)) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	r->height = fb->height;
+	r->width = fb->width;
+	r->pixel_format = fb->format->format;
+
+	r->flags = 0;
+	if (dev->mode_config.allow_fb_modifiers)
+		r->flags |= DRM_MODE_FB_MODIFIERS;
+
+	for (i = 0; i < ARRAY_SIZE(r->handles); i++) {
+		r->handles[i] = 0;
+		r->pitches[i] = 0;
+		r->offsets[i] = 0;
+		r->modifier[i] = 0;
+	}
+
+	for (i = 0; i < fb->format->num_planes; i++) {
+		r->pitches[i] = fb->pitches[i];
+		r->offsets[i] = fb->offsets[i];
+		if (dev->mode_config.allow_fb_modifiers)
+			r->modifier[i] = fb->modifier;
+	}
+
+	/* GET_FB2() is an unprivileged ioctl so we must not return a
+	 * buffer-handle to non master/root processes! To match GET_FB()
+	 * just return invalid handles (0) for non masters/root
+	 * rather than making GET_FB2() privileged.
+	 */
+	if (!drm_is_current_master(file_priv) && !capable(CAP_SYS_ADMIN)) {
+		ret = 0;
+		goto out;
+	}
+
+	for (i = 0; i < fb->format->num_planes; i++) {
+		int j;
+
+		/* If we reuse the same object for multiple planes, also
+		 * return the same handle.
+		 */
+		for (j = 0; j < i; j++) {
+			if (fb->obj[i] == fb->obj[j]) {
+				r->handles[i] = r->handles[j];
+				break;
+			}
+		}
 
+		if (r->handles[i])
+			continue;
+
+		if (fb->obj[i]) {
+			ret = drm_gem_handle_create(file_priv, fb->obj[i],
+						    &r->handles[i]);
+		} else {
+			WARN_ON(i > 0);
+			ret = fb->funcs->create_handle(fb, file_priv,
+						       &r->handles[i]);
+		}
+
+		if (ret != 0)
+			goto out;
+	}
+
+out:
+	if (ret != 0) {
+		/* Delete any previously-created handles on failure. */
+		for (i = 0; i < ARRAY_SIZE(r->handles); i++) {
+			int j;
+
+			if (r->handles[i])
+				drm_gem_handle_delete(file_priv, r->handles[i]);
+
+			/* Zero out any handles identical to the one we just
+			 * deleted.
+			 */
+			for (j = i + 1; j < ARRAY_SIZE(r->handles); j++) {
+				if (r->handles[j] == r->handles[i])
+					r->handles[j] = 0;
+			}
+		}
+	}
+
+	drm_framebuffer_put(fb);
 	return ret;
 }
 
@@ -580,7 +704,7 @@
 	struct drm_framebuffer *fb;
 	unsigned flags;
 	int num_clips;
-	int ret;
+	int ret = 0;
 
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		return -EOPNOTSUPP;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_gem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_gem.c
@@ -167,21 +167,6 @@
 }
 EXPORT_SYMBOL(drm_gem_private_object_init);
 
-static void
-drm_gem_remove_prime_handles(struct drm_gem_object *obj, struct drm_file *filp)
-{
-	/*
-	 * Note: obj->dma_buf can't disappear as long as we still hold a
-	 * handle reference in obj->handle_count.
-	 */
-	mutex_lock(&filp->prime.lock);
-	if (obj->dma_buf) {
-		drm_prime_remove_buf_handle_locked(&filp->prime,
-						   obj->dma_buf);
-	}
-	mutex_unlock(&filp->prime.lock);
-}
-
 /**
  * drm_gem_object_handle_free - release resources bound to userspace handles
  * @obj: GEM object to clean up.
@@ -255,7 +240,7 @@
 	else if (dev->driver->gem_close_object)
 		dev->driver->gem_close_object(obj, file_priv);
 
-	drm_gem_remove_prime_handles(obj, file_priv);
+	drm_prime_remove_buf_handle(&file_priv->prime, id);
 	drm_vma_node_revoke(&obj->vma_node, file_priv);
 
 	drm_gem_object_handle_put_unlocked(obj);
@@ -710,6 +695,8 @@
 	if (!objs)
 		return -ENOMEM;
 
+	*objs_out = objs;
+
 	handles = kvmalloc_array(count, sizeof(u32), GFP_KERNEL);
 	if (!handles) {
 		ret = -ENOMEM;
@@ -723,8 +710,6 @@
 	}
 
 	ret = objects_lookup(filp, handles, count, objs);
-	*objs_out = objs;
-
 out:
 	kvfree(handles);
 	return ret;
@@ -872,9 +857,6 @@
  * @file_priv: drm file-private structure
  *
  * Open an object using the global name, returning a handle and the size.
- *
- * This handle (of course) holds a reference to the object, so the object
- * will not go away until the handle is deleted.
  */
 int
 drm_gem_open_ioctl(struct drm_device *dev, void *data,
@@ -899,14 +881,15 @@
 
 	/* drm_gem_handle_create_tail unlocks dev->object_name_lock. */
 	ret = drm_gem_handle_create_tail(file_priv, obj, &handle);
-	drm_gem_object_put_unlocked(obj);
 	if (ret)
-		return ret;
+		goto err;
 
 	args->handle = handle;
 	args->size = obj->size;
 
-	return 0;
+err:
+	drm_gem_object_put_unlocked(obj);
+	return ret;
 }
 
 /**
@@ -1294,7 +1277,7 @@
 		ret = dma_resv_lock_slow_interruptible(obj->resv,
 								 acquire_ctx);
 		if (ret) {
-			ww_acquire_done(acquire_ctx);
+			ww_acquire_fini(acquire_ctx);
 			return ret;
 		}
 	}
@@ -1319,7 +1302,7 @@
 				goto retry;
 			}
 
-			ww_acquire_done(acquire_ctx);
+			ww_acquire_fini(acquire_ctx);
 			return ret;
 		}
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_gem_shmem_helper.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_gem_shmem_helper.c
@@ -474,14 +474,28 @@
 	struct drm_gem_object *obj = vma->vm_private_data;
 	struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
 	loff_t num_pages = obj->size >> PAGE_SHIFT;
+	vm_fault_t ret;
 	struct page *page;
+	pgoff_t page_offset;
 
-	if (vmf->pgoff >= num_pages || WARN_ON_ONCE(!shmem->pages))
-		return VM_FAULT_SIGBUS;
+	/* We don't use vmf->pgoff since that has the fake offset */
+	page_offset = (vmf->address - vma->vm_start) >> PAGE_SHIFT;
 
-	page = shmem->pages[vmf->pgoff];
+	mutex_lock(&shmem->pages_lock);
 
-	return vmf_insert_page(vma, vmf->address, page);
+	if (page_offset >= num_pages ||
+	    WARN_ON_ONCE(!shmem->pages) ||
+	    shmem->madv < 0) {
+		ret = VM_FAULT_SIGBUS;
+	} else {
+		page = shmem->pages[page_offset];
+
+		ret = vmf_insert_page(vma, vmf->address, page);
+	}
+
+	mutex_unlock(&shmem->pages_lock);
+
+	return ret;
 }
 
 static void drm_gem_shmem_vm_open(struct vm_area_struct *vma)
@@ -540,18 +554,13 @@
 	shmem = to_drm_gem_shmem_obj(vma->vm_private_data);
 
 	ret = drm_gem_shmem_get_pages(shmem);
-	if (ret) {
-		drm_gem_vm_close(vma);
+	if (ret)
 		return ret;
-	}
 
 	/* VM_PFNMAP was set by drm_gem_mmap() */
 	vma->vm_flags &= ~VM_PFNMAP;
 	vma->vm_flags |= VM_MIXEDMAP;
 
-	/* Remove the fake offset */
-	vma->vm_pgoff -= drm_vma_node_start(&shmem->base.vma_node);
-
 	return 0;
 }
 EXPORT_SYMBOL_GPL(drm_gem_shmem_mmap);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_gem_vram_helper.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_gem_vram_helper.c
@@ -73,6 +73,10 @@
 	}
 }
 
+/*
+ * Note that on error, drm_gem_vram_init will free the buffer object.
+ */
+
 static int drm_gem_vram_init(struct drm_device *dev,
 			     struct ttm_bo_device *bdev,
 			     struct drm_gem_vram_object *gbo,
@@ -86,8 +90,10 @@
 		gbo->bo.base.funcs = &drm_gem_vram_object_funcs;
 
 	ret = drm_gem_object_init(dev, &gbo->bo.base, size);
-	if (ret)
+	if (ret) {
+		kfree(gbo);
 		return ret;
+	}
 
 	acc_size = ttm_bo_dma_acc_size(bdev, size, sizeof(*gbo));
 
@@ -98,13 +104,13 @@
 			  &gbo->placement, pg_align, interruptible, acc_size,
 			  NULL, NULL, ttm_buffer_object_destroy);
 	if (ret)
-		goto err_drm_gem_object_release;
+		/*
+		 * A failing ttm_bo_init will call ttm_buffer_object_destroy
+		 * to release gbo->bo.base and kfree gbo.
+		 */
+		return ret;
 
 	return 0;
-
-err_drm_gem_object_release:
-	drm_gem_object_release(&gbo->bo.base);
-	return ret;
 }
 
 /**
@@ -134,13 +140,9 @@
 
 	ret = drm_gem_vram_init(dev, bdev, gbo, size, pg_align, interruptible);
 	if (ret < 0)
-		goto err_kfree;
+		return ERR_PTR(ret);
 
 	return gbo;
-
-err_kfree:
-	kfree(gbo);
-	return ERR_PTR(ret);
 }
 EXPORT_SYMBOL(drm_gem_vram_create);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_internal.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_internal.h
@@ -59,8 +59,8 @@
 
 void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv);
 void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv);
-void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpriv,
-					struct dma_buf *dma_buf);
+void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv,
+				 uint32_t handle);
 
 /* drm_drv.c */
 struct drm_minor *drm_minor_acquire(unsigned int minor_id);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_ioc32.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_ioc32.c
@@ -99,6 +99,8 @@
 	if (copy_from_user(&v32, (void __user *)arg, sizeof(v32)))
 		return -EFAULT;
 
+	memset(&v, 0, sizeof(v));
+
 	v = (struct drm_version) {
 		.name_len = v32.name_len,
 		.name = compat_ptr(v32.name),
@@ -137,6 +139,9 @@
 
 	if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32)))
 		return -EFAULT;
+
+	memset(&uq, 0, sizeof(uq));
+
 	uq = (struct drm_unique){
 		.unique_len = uq32.unique_len,
 		.unique = compat_ptr(uq32.unique),
@@ -265,6 +270,8 @@
 	if (copy_from_user(&c32, argp, sizeof(c32)))
 		return -EFAULT;
 
+	memset(&client, 0, sizeof(client));
+
 	client.idx = c32.idx;
 
 	err = drm_ioctl_kernel(file, drm_getclient, &client, 0);
@@ -850,12 +857,12 @@
 	if (copy_from_user(&req32, argp, sizeof(req32)))
 		return -EFAULT;
 
+	memset(&req, 0, sizeof(req));
+
 	req.request.type = req32.request.type;
 	req.request.sequence = req32.request.sequence;
 	req.request.signal = req32.request.signal;
 	err = drm_ioctl_kernel(file, drm_wait_vblank_ioctl, &req, DRM_UNLOCKED);
-	if (err)
-		return err;
 
 	req32.reply.type = req.reply.type;
 	req32.reply.sequence = req.reply.sequence;
@@ -864,7 +871,7 @@
 	if (copy_to_user(argp, &req32, sizeof(req32)))
 		return -EFAULT;
 
-	return 0;
+	return err;
 }
 
 #if defined(CONFIG_X86)
@@ -887,6 +894,8 @@
 	struct drm_mode_fb_cmd2 req64;
 	int err;
 
+	memset(&req64, 0, sizeof(req64));
+
 	if (copy_from_user(&req64, argp,
 			   offsetof(drm_mode_fb_cmd232_t, modifier)))
 		return -EFAULT;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_ioctl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_ioctl.c
@@ -118,17 +118,18 @@
 		  struct drm_file *file_priv)
 {
 	struct drm_unique *u = data;
-	struct drm_master *master = file_priv->master;
+	struct drm_master *master;
 
-	mutex_lock(&master->dev->master_mutex);
+	mutex_lock(&dev->master_mutex);
+	master = file_priv->master;
 	if (u->unique_len >= master->unique_len) {
 		if (copy_to_user(u->unique, master->unique, master->unique_len)) {
-			mutex_unlock(&master->dev->master_mutex);
+			mutex_unlock(&dev->master_mutex);
 			return -EFAULT;
 		}
 	}
 	u->unique_len = master->unique_len;
-	mutex_unlock(&master->dev->master_mutex);
+	mutex_unlock(&dev->master_mutex);
 
 	return 0;
 }
@@ -472,7 +473,13 @@
  */
 static int drm_copy_field(char __user *buf, size_t *buf_len, const char *value)
 {
-	int len;
+	size_t len;
+
+	/* don't attempt to copy a NULL pointer */
+	if (WARN_ONCE(!value, "BUG: the value to copy was not set!")) {
+		*buf_len = 0;
+		return 0;
+	}
 
 	/* don't overflow userbuf */
 	len = strlen(value);
@@ -671,6 +678,7 @@
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_connector_property_set_ioctl, DRM_MASTER),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, 0),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, 0),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB2, drm_mode_getfb2_ioctl, 0),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb_ioctl, 0),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2_ioctl, 0),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb_ioctl, 0),
@@ -825,6 +833,9 @@
 	if (drm_dev_is_unplugged(dev))
 		return -ENODEV;
 
+       if (DRM_IOCTL_TYPE(cmd) != DRM_IOCTL_BASE)
+               return -ENOTTY;
+
 	is_driver_ioctl = nr >= DRM_COMMAND_BASE && nr < DRM_COMMAND_END;
 
 	if (is_driver_ioctl) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_kms_helper_common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_kms_helper_common.c
@@ -64,19 +64,18 @@
 
 static int __init drm_kms_helper_init(void)
 {
-	int ret;
+	/*
+	 * The Kconfig DRM_KMS_HELPER selects FRAMEBUFFER_CONSOLE (if !EXPERT)
+	 * but the module doesn't depend on any fb console symbols.  At least
+	 * attempt to load fbcon to avoid leaving the system without a usable
+	 * console.
+	 */
+	if (IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION) &&
+	    IS_MODULE(CONFIG_FRAMEBUFFER_CONSOLE) &&
+	    !IS_ENABLED(CONFIG_EXPERT))
+		request_module_nowait("fbcon");
 
-	/* Call init functions from specific kms helpers here */
-	ret = drm_fb_helper_modinit();
-	if (ret < 0)
-		goto out;
-
-	ret = drm_dp_aux_dev_init();
-	if (ret < 0)
-		goto out;
-
-out:
-	return ret;
+	return drm_dp_aux_dev_init();
 }
 
 static void __exit drm_kms_helper_exit(void)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_lease.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_lease.c
@@ -542,10 +542,12 @@
 	}
 
 	DRM_DEBUG_LEASE("Creating lease\n");
+	/* lessee will take the ownership of leases */
 	lessee = drm_lease_create(lessor, &leases);
 
 	if (IS_ERR(lessee)) {
 		ret = PTR_ERR(lessee);
+		idr_destroy(&leases);
 		goto out_leases;
 	}
 
@@ -580,7 +582,6 @@
 
 out_leases:
 	put_unused_fd(fd);
-	idr_destroy(&leases);
 
 	DRM_DEBUG_LEASE("drm_mode_create_lease_ioctl failed: %d\n", ret);
 	return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_mipi_dbi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_mipi_dbi.c
@@ -367,9 +367,9 @@
 	memset(dbidev->tx_buf, 0, len);
 
 	mipi_dbi_command(dbi, MIPI_DCS_SET_COLUMN_ADDRESS, 0, 0,
-			 (width >> 8) & 0xFF, (width - 1) & 0xFF);
+			 ((width - 1) >> 8) & 0xFF, (width - 1) & 0xFF);
 	mipi_dbi_command(dbi, MIPI_DCS_SET_PAGE_ADDRESS, 0, 0,
-			 (height >> 8) & 0xFF, (height - 1) & 0xFF);
+			 ((height - 1) >> 8) & 0xFF, (height - 1) & 0xFF);
 	mipi_dbi_command_buf(dbi, MIPI_DCS_WRITE_MEMORY_START,
 			     (u8 *)dbidev->tx_buf, len);
 
@@ -937,7 +937,7 @@
 			}
 		}
 
-		tr.len = chunk;
+		tr.len = chunk * 2;
 		len -= chunk;
 
 		ret = spi_sync(spi, &m);
@@ -955,7 +955,7 @@
 	int ret;
 
 	if (mipi_dbi_command_is_read(dbi, *cmd))
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 
 	MIPI_DBI_DEBUG_COMMAND(*cmd, parameters, num);
 
@@ -1156,6 +1156,13 @@
 	size_t chunk;
 	int ret;
 
+	/* In __spi_validate, there's a validation that no partial transfers
+	 * are accepted (xfer->len % w_size must be zero).
+	 * Here we align max_chunk to multiple of 2 (16bits),
+	 * to prevent transfers from being rejected.
+	 */
+	max_chunk = ALIGN_DOWN(max_chunk, 2);
+
 	spi_message_init_with_transfers(&m, &tr, 1);
 
 	while (len) {
@@ -1187,8 +1194,7 @@
 	struct mipi_dbi_dev *dbidev = m->private;
 	u8 val, cmd = 0, parameters[64];
 	char *buf, *pos, *token;
-	unsigned int i;
-	int ret, idx;
+	int i, ret, idx;
 
 	if (!drm_dev_enter(&dbidev->drm, &idx))
 		return -ENODEV;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_mipi_dsi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_mipi_dsi.c
@@ -300,6 +300,8 @@
 {
 	struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
 
+	if (dsi->attached)
+		mipi_dsi_detach(dsi);
 	mipi_dsi_device_unregister(dsi);
 
 	return 0;
@@ -322,11 +324,18 @@
 int mipi_dsi_attach(struct mipi_dsi_device *dsi)
 {
 	const struct mipi_dsi_host_ops *ops = dsi->host->ops;
+	int ret;
 
 	if (!ops || !ops->attach)
 		return -ENOSYS;
 
-	return ops->attach(dsi->host, dsi);
+	ret = ops->attach(dsi->host, dsi);
+	if (ret)
+		return ret;
+
+	dsi->attached = true;
+
+	return 0;
 }
 EXPORT_SYMBOL(mipi_dsi_attach);
 
@@ -338,9 +347,14 @@
 {
 	const struct mipi_dsi_host_ops *ops = dsi->host->ops;
 
+	if (WARN_ON(!dsi->attached))
+		return -EINVAL;
+
 	if (!ops || !ops->detach)
 		return -ENOSYS;
 
+	dsi->attached = false;
+
 	return ops->detach(dsi->host, dsi);
 }
 EXPORT_SYMBOL(mipi_dsi_detach);
@@ -1029,11 +1043,11 @@
  */
 int mipi_dsi_dcs_set_tear_scanline(struct mipi_dsi_device *dsi, u16 scanline)
 {
-	u8 payload[3] = { MIPI_DCS_SET_TEAR_SCANLINE, scanline >> 8,
-			  scanline & 0xff };
+	u8 payload[2] = { scanline >> 8, scanline & 0xff };
 	ssize_t err;
 
-	err = mipi_dsi_generic_write(dsi, payload, sizeof(payload));
+	err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_TEAR_SCANLINE, payload,
+				 sizeof(payload));
 	if (err < 0)
 		return err;
 
@@ -1090,6 +1104,58 @@
 }
 EXPORT_SYMBOL(mipi_dsi_dcs_get_display_brightness);
 
+/**
+ * mipi_dsi_dcs_set_display_brightness_large() - sets the 16-bit brightness value
+ *    of the display
+ * @dsi: DSI peripheral device
+ * @brightness: brightness value
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int mipi_dsi_dcs_set_display_brightness_large(struct mipi_dsi_device *dsi,
+					     u16 brightness)
+{
+	u8 payload[2] = { brightness >> 8, brightness & 0xff };
+	ssize_t err;
+
+	err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_BRIGHTNESS,
+				 payload, sizeof(payload));
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+EXPORT_SYMBOL(mipi_dsi_dcs_set_display_brightness_large);
+
+/**
+ * mipi_dsi_dcs_get_display_brightness_large() - gets the current 16-bit
+ *    brightness value of the display
+ * @dsi: DSI peripheral device
+ * @brightness: brightness value
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+int mipi_dsi_dcs_get_display_brightness_large(struct mipi_dsi_device *dsi,
+					     u16 *brightness)
+{
+	u8 brightness_be[2];
+	ssize_t err;
+
+	err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_DISPLAY_BRIGHTNESS,
+				brightness_be, sizeof(brightness_be));
+	if (err <= 0) {
+		if (err == 0)
+			err = -ENODATA;
+
+		return err;
+	}
+
+	*brightness = (brightness_be[0] << 8) | brightness_be[1];
+
+	return 0;
+}
+EXPORT_SYMBOL(mipi_dsi_dcs_get_display_brightness_large);
+
 static int mipi_dsi_drv_probe(struct device *dev)
 {
 	struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_mm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_mm.c
@@ -154,7 +154,7 @@
 
 INTERVAL_TREE_DEFINE(struct drm_mm_node, rb,
 		     u64, __subtree_last,
-		     START, LAST, static inline, drm_mm_interval_tree)
+		     START, LAST, static inline __maybe_unused, drm_mm_interval_tree)
 
 struct drm_mm_node *
 __drm_mm_interval_first(const struct drm_mm *mm, u64 start, u64 last)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_modes.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_modes.c
@@ -1672,6 +1672,13 @@
 		}
 	}
 
+	if (!(rotation & DRM_MODE_ROTATE_MASK))
+		rotation |= DRM_MODE_ROTATE_0;
+
+	/* Make sure there is exactly one rotation defined */
+	if (!is_power_of_2(rotation & DRM_MODE_ROTATE_MASK))
+		return -EINVAL;
+
 	mode->rotation_reflection = rotation;
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_of.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_of.c
@@ -49,23 +49,23 @@
 EXPORT_SYMBOL(drm_of_crtc_port_mask);
 
 /**
- * drm_of_find_possible_crtcs - find the possible CRTCs for an encoder port
+ * drm_of_find_possible_crtcs - find the possible CRTCs for an encoder
  * @dev: DRM device
- * @port: encoder port to scan for endpoints
+ * @encoder: encoder OF node to scan for endpoints
  *
- * Scan all endpoints attached to a port, locate their attached CRTCs,
+ * Scan all endpoints attached to a encoder, locate their attached CRTCs,
  * and generate the DRM mask of CRTCs which may be attached to this
  * encoder.
  *
  * See Documentation/devicetree/bindings/graph.txt for the bindings.
  */
 uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
-				    struct device_node *port)
+				    struct device_node *encoder)
 {
 	struct device_node *remote_port, *ep;
 	uint32_t possible_crtcs = 0;
 
-	for_each_endpoint_of_node(port, ep) {
+	for_each_endpoint_of_node(encoder, ep) {
 		remote_port = of_graph_get_remote_port(ep);
 		if (!remote_port) {
 			of_node_put(ep);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_panel.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_panel.c
@@ -44,13 +44,21 @@
 /**
  * drm_panel_init - initialize a panel
  * @panel: DRM panel
+ * @dev: parent device of the panel
+ * @funcs: panel operations
+ * @connector_type: the connector type (DRM_MODE_CONNECTOR_*) corresponding to
+ *	the panel interface
  *
- * Sets up internal fields of the panel so that it can subsequently be added
- * to the registry.
+ * Initialize the panel structure for subsequent registration with
+ * drm_panel_add().
  */
-void drm_panel_init(struct drm_panel *panel)
+void drm_panel_init(struct drm_panel *panel, struct device *dev,
+		    const struct drm_panel_funcs *funcs, int connector_type)
 {
 	INIT_LIST_HEAD(&panel->list);
+	panel->dev = dev;
+	panel->funcs = funcs;
+	panel->connector_type = connector_type;
 }
 EXPORT_SYMBOL(drm_panel_init);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_panel_orientation_quirks.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_panel_orientation_quirks.c
@@ -30,12 +30,6 @@
 	int orientation;
 };
 
-static const struct drm_dmi_panel_orientation_data acer_s1003 = {
-	.width = 800,
-	.height = 1280,
-	.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
-};
-
 static const struct drm_dmi_panel_orientation_data asus_t100ha = {
 	.width = 800,
 	.height = 1280,
@@ -50,6 +44,14 @@
 	.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
 };
 
+static const struct drm_dmi_panel_orientation_data gpd_onemix2s = {
+	.width = 1200,
+	.height = 1920,
+	.bios_dates = (const char * const []){ "05/21/2018", "10/26/2018",
+		"03/04/2019", NULL },
+	.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
+};
+
 static const struct drm_dmi_panel_orientation_data gpd_pocket = {
 	.width = 1200,
 	.height = 1920,
@@ -90,6 +92,13 @@
 	.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
 };
 
+static const struct drm_dmi_panel_orientation_data onegx1_pro = {
+	.width = 1200,
+	.height = 1920,
+	.bios_dates = (const char * const []){ "12/17/2020", NULL },
+	.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
+};
+
 static const struct drm_dmi_panel_orientation_data lcd720x1280_rightside_up = {
 	.width = 720,
 	.height = 1280,
@@ -108,19 +117,67 @@
 	.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
 };
 
+static const struct drm_dmi_panel_orientation_data lcd1280x1920_rightside_up = {
+	.width = 1280,
+	.height = 1920,
+	.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
+};
+
+static const struct drm_dmi_panel_orientation_data lcd1600x2560_leftside_up = {
+	.width = 1600,
+	.height = 2560,
+	.orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP,
+};
+
 static const struct dmi_system_id orientation_data[] = {
 	{	/* Acer One 10 (S1003) */
 		.matches = {
 		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Acer"),
 		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "One S1003"),
 		},
-		.driver_data = (void *)&acer_s1003,
+		.driver_data = (void *)&lcd800x1280_rightside_up,
+	}, {	/* Acer Switch V 10 (SW5-017) */
+		.matches = {
+		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Acer"),
+		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "SW5-017"),
+		},
+		.driver_data = (void *)&lcd800x1280_rightside_up,
+	}, {	/* Anbernic Win600 */
+		.matches = {
+		  DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Anbernic"),
+		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Win600"),
+		},
+		.driver_data = (void *)&lcd720x1280_rightside_up,
 	}, {	/* Asus T100HA */
 		.matches = {
 		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
 		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100HAN"),
 		},
 		.driver_data = (void *)&asus_t100ha,
+	}, {	/* Asus T101HA */
+		.matches = {
+		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T101HA"),
+		},
+		.driver_data = (void *)&lcd800x1280_rightside_up,
+	}, {	/* Asus T103HAF */
+		.matches = {
+		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T103HAF"),
+		},
+		.driver_data = (void *)&lcd800x1280_rightside_up,
+	}, {	/* AYA NEO AYANEO 2 */
+		.matches = {
+		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYANEO"),
+		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "AYANEO 2"),
+		},
+		.driver_data = (void *)&lcd1200x1920_rightside_up,
+	}, {	/* AYA NEO 2021 */
+		.matches = {
+		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYADEVICE"),
+		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "AYA NEO 2021"),
+		},
+		.driver_data = (void *)&lcd800x1280_rightside_up,
 	}, {	/* GPD MicroPC (generic strings, also match on bios date) */
 		.matches = {
 		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Default string"),
@@ -135,6 +192,12 @@
 		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "MicroPC"),
 		},
 		.driver_data = (void *)&lcd720x1280_rightside_up,
+	}, {	/* GPD Win Max */
+		.matches = {
+		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "GPD"),
+		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "G1619-01"),
+		},
+		.driver_data = (void *)&lcd800x1280_rightside_up,
 	}, {	/*
 		 * GPD Pocket, note that the the DMI data is less generic then
 		 * it seems, devices with a board-vendor of "AMI Corporation"
@@ -172,6 +235,12 @@
 		  DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"),
 		},
 		.driver_data = (void *)&gpd_win2,
+	}, {	/* GPD Win 3 */
+		.matches = {
+		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "GPD"),
+		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "G1618-03")
+		},
+		.driver_data = (void *)&lcd720x1280_rightside_up,
 	}, {	/* I.T.Works TW891 */
 		.matches = {
 		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "To be filled by O.E.M."),
@@ -180,6 +249,13 @@
 		  DMI_EXACT_MATCH(DMI_BOARD_NAME, "TW891"),
 		},
 		.driver_data = (void *)&itworks_tw891,
+	}, {	/* KD Kurio Smart C15200 2-in-1 */
+		.matches = {
+		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "KD Interactive"),
+		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Kurio Smart"),
+		  DMI_EXACT_MATCH(DMI_BOARD_NAME, "KDM960BCP"),
+		},
+		.driver_data = (void *)&lcd800x1280_rightside_up,
 	}, {	/*
 		 * Lenovo Ideapad Miix 310 laptop, only some production batches
 		 * have a portrait screen, the resolution checks makes the quirk
@@ -198,19 +274,89 @@
 		  DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 320-10ICR"),
 		},
 		.driver_data = (void *)&lcd800x1280_rightside_up,
-	}, {	/* Lenovo Ideapad D330 */
+	}, {	/* Lenovo Ideapad D330-10IGM (HD) */
 		.matches = {
 		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "81H3"),
 		  DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad D330-10IGM"),
 		},
+		.driver_data = (void *)&lcd800x1280_rightside_up,
+	}, {	/* Lenovo Ideapad D330-10IGM (FHD) */
+		.matches = {
+		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+		  DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad D330-10IGM"),
+		},
+		.driver_data = (void *)&lcd1200x1920_rightside_up,
+	}, {	/* Lenovo Ideapad D330-10IGL (HD) */
+		.matches = {
+		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+		  DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad D330-10IGL"),
+		},
+		.driver_data = (void *)&lcd800x1280_rightside_up,
+	}, {	/* Lenovo IdeaPad Duet 3 10IGL5 */
+		.matches = {
+		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+		  DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "IdeaPad Duet 3 10IGL5"),
+		},
+		.driver_data = (void *)&lcd1200x1920_rightside_up,
+	}, {	/* Lenovo Yoga Book X90F / X90L */
+		.matches = {
+		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
+		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"),
+		  DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "YETI-11"),
+		},
+		.driver_data = (void *)&lcd1200x1920_rightside_up,
+	}, {	/* Lenovo Yoga Book X91F / X91L */
+		.matches = {
+		  /* Non exact match to match F + L versions */
+		  DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X91"),
+		},
+		.driver_data = (void *)&lcd1200x1920_rightside_up,
+	}, {	/* OneGX1 Pro */
+		.matches = {
+		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "SYSTEM_MANUFACTURER"),
+		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "SYSTEM_PRODUCT_NAME"),
+		  DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Default string"),
+		},
+		.driver_data = (void *)&onegx1_pro,
+	}, {	/* OneXPlayer */
+		.matches = {
+		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ONE-NETBOOK TECHNOLOGY CO., LTD."),
+		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ONE XPLAYER"),
+		},
+		.driver_data = (void *)&lcd1600x2560_leftside_up,
+	}, {	/* OrangePi Neo */
+		.matches = {
+		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "OrangePi"),
+		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "NEO-01"),
+		},
 		.driver_data = (void *)&lcd1200x1920_rightside_up,
+	}, {	/* Samsung GalaxyBook 10.6 */
+		.matches = {
+		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Galaxy Book 10.6"),
+		},
+		.driver_data = (void *)&lcd1280x1920_rightside_up,
+	}, {	/* Valve Steam Deck */
+		.matches = {
+		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Valve"),
+		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Jupiter"),
+		  DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "1"),
+		},
+		.driver_data = (void *)&lcd800x1280_rightside_up,
 	}, {	/* VIOS LTH17 */
 		.matches = {
 		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "VIOS"),
 		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "LTH17"),
 		},
 		.driver_data = (void *)&lcd800x1280_rightside_up,
+	}, {	/* One Mix 2S (generic strings, also match on bios date) */
+		.matches = {
+		  DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Default string"),
+		  DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Default string"),
+		  DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Default string"),
+		  DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"),
+		},
+		.driver_data = (void *)&gpd_onemix2s,
 	},
 	{}
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_pci.c
@@ -51,8 +51,6 @@
 drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t align)
 {
 	drm_dma_handle_t *dmah;
-	unsigned long addr;
-	size_t sz;
 
 	/* pci_alloc_consistent only guarantees alignment to the smallest
 	 * PAGE_SIZE order which is greater than or equal to the requested size.
@@ -68,20 +66,13 @@
 	dmah->size = size;
 	dmah->vaddr = dma_alloc_coherent(&dev->pdev->dev, size,
 					 &dmah->busaddr,
-					 GFP_KERNEL | __GFP_COMP);
+					 GFP_KERNEL);
 
 	if (dmah->vaddr == NULL) {
 		kfree(dmah);
 		return NULL;
 	}
 
-	/* XXX - Is virt_to_page() legal for consistent mem? */
-	/* Reserve */
-	for (addr = (unsigned long)dmah->vaddr, sz = size;
-	     sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
-		SetPageReserved(virt_to_page((void *)addr));
-	}
-
 	return dmah;
 }
 
@@ -94,19 +85,9 @@
  */
 void __drm_legacy_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah)
 {
-	unsigned long addr;
-	size_t sz;
-
-	if (dmah->vaddr) {
-		/* XXX - Is virt_to_page() legal for consistent mem? */
-		/* Unreserve */
-		for (addr = (unsigned long)dmah->vaddr, sz = dmah->size;
-		     sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) {
-			ClearPageReserved(virt_to_page((void *)addr));
-		}
+	if (dmah->vaddr)
 		dma_free_coherent(&dev->pdev->dev, dmah->size, dmah->vaddr,
 				  dmah->busaddr);
-	}
 }
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_plane.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_plane.c
@@ -186,6 +186,13 @@
 	if (WARN_ON(config->num_total_plane >= 32))
 		return -EINVAL;
 
+	/*
+	 * First driver to need more than 64 formats needs to fix this. Each
+	 * format is encoded as a bit and the current code only supports a u64.
+	 */
+	if (WARN_ON(format_count > 64))
+		return -EINVAL;
+
 	WARN_ON(drm_drv_uses_atomic_modeset(dev) &&
 		(!funcs->atomic_destroy_state ||
 		 !funcs->atomic_duplicate_state));
@@ -207,13 +214,6 @@
 		return -ENOMEM;
 	}
 
-	/*
-	 * First driver to need more than 64 formats needs to fix this. Each
-	 * format is encoded as a bit and the current code only supports a u64.
-	 */
-	if (WARN_ON(format_count > 64))
-		return -EINVAL;
-
 	if (format_modifiers) {
 		const uint64_t *temp_modifiers = format_modifiers;
 		while (*temp_modifiers++ != DRM_FORMAT_MOD_INVALID)
@@ -1203,6 +1203,7 @@
 out:
 	if (fb)
 		drm_framebuffer_put(fb);
+	fb = NULL;
 	if (plane->old_fb)
 		drm_framebuffer_put(plane->old_fb);
 	plane->old_fb = NULL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_plane_helper.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_plane_helper.c
@@ -123,7 +123,6 @@
 		.crtc_w = drm_rect_width(dst),
 		.crtc_h = drm_rect_height(dst),
 		.rotation = rotation,
-		.visible = *visible,
 	};
 	struct drm_crtc_state crtc_state = {
 		.crtc = crtc,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_prime.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_prime.c
@@ -187,29 +187,33 @@
 	return -ENOENT;
 }
 
-void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpriv,
-					struct dma_buf *dma_buf)
+void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv,
+				 uint32_t handle)
 {
 	struct rb_node *rb;
 
-	rb = prime_fpriv->dmabufs.rb_node;
+	mutex_lock(&prime_fpriv->lock);
+
+	rb = prime_fpriv->handles.rb_node;
 	while (rb) {
 		struct drm_prime_member *member;
 
-		member = rb_entry(rb, struct drm_prime_member, dmabuf_rb);
-		if (member->dma_buf == dma_buf) {
+		member = rb_entry(rb, struct drm_prime_member, handle_rb);
+		if (member->handle == handle) {
 			rb_erase(&member->handle_rb, &prime_fpriv->handles);
 			rb_erase(&member->dmabuf_rb, &prime_fpriv->dmabufs);
 
-			dma_buf_put(dma_buf);
+			dma_buf_put(member->dma_buf);
 			kfree(member);
-			return;
-		} else if (member->dma_buf < dma_buf) {
+			break;
+		} else if (member->handle < handle) {
 			rb = rb->rb_right;
 		} else {
 			rb = rb->rb_left;
 		}
 	}
+
+	mutex_unlock(&prime_fpriv->lock);
 }
 
 void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_print.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_print.c
@@ -59,8 +59,9 @@
 			copy = iterator->remain;
 
 		/* Copy out the bit of the string that we need */
-		memcpy(iterator->data,
-			str + (iterator->start - iterator->offset), copy);
+		if (iterator->data)
+			memcpy(iterator->data,
+			       str + (iterator->start - iterator->offset), copy);
 
 		iterator->offset = iterator->start + copy;
 		iterator->remain -= copy;
@@ -69,7 +70,8 @@
 
 		len = min_t(ssize_t, strlen(str), iterator->remain);
 
-		memcpy(iterator->data + pos, str, len);
+		if (iterator->data)
+			memcpy(iterator->data + pos, str, len);
 
 		iterator->offset += len;
 		iterator->remain -= len;
@@ -99,8 +101,9 @@
 	if ((iterator->offset >= iterator->start) && (len < iterator->remain)) {
 		ssize_t pos = iterator->offset - iterator->start;
 
-		snprintf(((char *) iterator->data) + pos,
-			iterator->remain, "%pV", vaf);
+		if (iterator->data)
+			snprintf(((char *) iterator->data) + pos,
+				 iterator->remain, "%pV", vaf);
 
 		iterator->offset += len;
 		iterator->remain -= len;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_probe_helper.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_probe_helper.c
@@ -112,7 +112,7 @@
 			continue;
 		}
 
-		ret = drm_bridge_mode_valid(encoder->bridge, mode);
+		ret = drm_bridge_chain_mode_valid(encoder->bridge, mode);
 		if (ret != MODE_OK) {
 			/* There is also no point in continuing for crtc check
 			 * here. */
@@ -460,8 +460,9 @@
 		 */
 		dev->mode_config.delayed_event = true;
 		if (dev->mode_config.poll_enabled)
-			schedule_delayed_work(&dev->mode_config.output_poll_work,
-					      0);
+			mod_delayed_work(system_wq,
+					 &dev->mode_config.output_poll_work,
+					 0);
 	}
 
 	/* Re-enable polling in case the global poll config changed. */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_property.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_property.c
@@ -561,7 +561,7 @@
 	struct drm_property_blob *blob;
 	int ret;
 
-	if (!length || length > ULONG_MAX - sizeof(struct drm_property_blob))
+	if (!length || length > INT_MAX - sizeof(struct drm_property_blob))
 		return ERR_PTR(-EINVAL);
 
 	blob = kvzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_rect.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_rect.c
@@ -54,7 +54,12 @@
 
 static u32 clip_scaled(u32 src, u32 dst, u32 clip)
 {
-	u64 tmp = mul_u32_u32(src, dst - clip);
+	u64 tmp;
+
+	if (dst == 0)
+		return 0;
+
+	tmp = mul_u32_u32(src, dst - clip);
 
 	/*
 	 * Round toward 1.0 when clipping so that we don't accidentally
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_syncobj.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_syncobj.c
@@ -325,20 +325,37 @@
 	if (!syncobj)
 		return -ENOENT;
 
+	/* Waiting for userspace with locks help is illegal cause that can
+	 * trivial deadlock with page faults for example. Make lockdep complain
+	 * about it early on.
+	 */
+	if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT) {
+		might_sleep();
+		lockdep_assert_none_held_once();
+	}
+
 	*fence = drm_syncobj_fence_get(syncobj);
-	drm_syncobj_put(syncobj);
 
 	if (*fence) {
 		ret = dma_fence_chain_find_seqno(fence, point);
-		if (!ret)
-			return 0;
+		if (!ret) {
+			/* If the requested seqno is already signaled
+			 * drm_syncobj_find_fence may return a NULL
+			 * fence. To make sure the recipient gets
+			 * signalled, use a new fence instead.
+			 */
+			if (!*fence)
+				*fence = dma_fence_get_stub();
+
+			goto out;
+		}
 		dma_fence_put(*fence);
 	} else {
 		ret = -EINVAL;
 	}
 
 	if (!(flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT))
-		return ret;
+		goto out;
 
 	memset(&wait, 0, sizeof(wait));
 	wait.task = current;
@@ -370,6 +387,9 @@
 	if (wait.node.next)
 		drm_syncobj_remove_wait(syncobj, &wait);
 
+out:
+	drm_syncobj_put(syncobj);
+
 	return ret;
 }
 EXPORT_SYMBOL(drm_syncobj_find_fence);
@@ -878,6 +898,10 @@
 	uint64_t *points;
 	uint32_t signaled_count, i;
 
+	if (flags & (DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT |
+		     DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE))
+		lockdep_assert_none_held_once();
+
 	points = kmalloc_array(count, sizeof(*points), GFP_KERNEL);
 	if (points == NULL)
 		return -ENOMEM;
@@ -910,7 +934,8 @@
 		fence = drm_syncobj_fence_get(syncobjs[i]);
 		if (!fence || dma_fence_chain_find_seqno(&fence, points[i])) {
 			dma_fence_put(fence);
-			if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT) {
+			if (flags & (DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT |
+				     DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE)) {
 				continue;
 			} else {
 				timeout = -EINVAL;
@@ -943,7 +968,8 @@
 	 * fallthough and try a 0 timeout wait!
 	 */
 
-	if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT) {
+	if (flags & (DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT |
+		     DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE)) {
 		for (i = 0; i < count; ++i)
 			drm_syncobj_fence_add_wait(syncobjs[i], &entries[i]);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_sysfs.c
@@ -293,9 +293,6 @@
 		return PTR_ERR(connector->kdev);
 	}
 
-	/* Let userspace know we have a new connector */
-	drm_sysfs_hotplug_event(dev);
-
 	if (connector->ddc)
 		return sysfs_create_link(&connector->kdev->kobj,
 				 &connector->ddc->dev.kobj, "ddc");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/drm_vblank.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/drm_vblank.c
@@ -69,6 +69,12 @@
  * &drm_driver.max_vblank_count. In that case the vblank core only disables the
  * vblanks after a timer has expired, which can be configured through the
  * ``vblankoffdelay`` module parameter.
+ *
+ * Drivers for hardware without support for vertical-blanking interrupts
+ * must not call drm_vblank_init(). For such drivers, atomic helpers will
+ * automatically generate fake vblank events as part of the display update.
+ * This functionality also can be controlled by the driver by enabling and
+ * disabling struct drm_crtc_state.no_vblank.
  */
 
 /* Retry timestamp calculation up to 3 times to satisfy
@@ -489,6 +495,28 @@
 EXPORT_SYMBOL(drm_vblank_init);
 
 /**
+ * drm_dev_has_vblank - test if vblanking has been initialized for
+ *                      a device
+ * @dev: the device
+ *
+ * Drivers may call this function to test if vblank support is
+ * initialized for a device. For most hardware this means that vblanking
+ * can also be enabled.
+ *
+ * Atomic helpers use this function to initialize
+ * &drm_crtc_state.no_vblank. See also drm_atomic_helper_check_modeset().
+ *
+ * Returns:
+ * True if vblanking has been initialized for the given device, false
+ * otherwise.
+ */
+bool drm_dev_has_vblank(const struct drm_device *dev)
+{
+	return dev->num_crtcs != 0;
+}
+EXPORT_SYMBOL(drm_dev_has_vblank);
+
+/**
  * drm_crtc_vblank_waitqueue - get vblank waitqueue for the CRTC
  * @crtc: which CRTC's vblank waitqueue to retrieve
  *
@@ -1581,7 +1609,7 @@
 	unsigned int flags, pipe, high_pipe;
 
 	if (!dev->irq_enabled)
-		return -EINVAL;
+		return -EOPNOTSUPP;
 
 	if (vblwait->request.type & _DRM_VBLANK_SIGNAL)
 		return -EINVAL;
@@ -1838,7 +1866,7 @@
 		return -EOPNOTSUPP;
 
 	if (!dev->irq_enabled)
-		return -EINVAL;
+		return -EOPNOTSUPP;
 
 	crtc = drm_crtc_find(dev, file_priv, get_seq->crtc_id);
 	if (!crtc)
@@ -1896,7 +1924,7 @@
 		return -EOPNOTSUPP;
 
 	if (!dev->irq_enabled)
-		return -EINVAL;
+		return -EOPNOTSUPP;
 
 	crtc = drm_crtc_find(dev, file_priv, queue_seq->crtc_id);
 	if (!crtc)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/etnaviv/etnaviv_buffer.c
@@ -12,6 +12,7 @@
 
 #include "common.xml.h"
 #include "state.xml.h"
+#include "state_blt.xml.h"
 #include "state_hi.xml.h"
 #include "state_3d.xml.h"
 #include "cmdstream.xml.h"
@@ -233,6 +234,8 @@
 	struct etnaviv_cmdbuf *buffer = &gpu->buffer;
 	unsigned int waitlink_offset = buffer->user_size - 16;
 	u32 link_target, flush = 0;
+	bool has_blt = !!(gpu->identity.minor_features5 &
+			  chipMinorFeatures5_BLT_ENGINE);
 
 	lockdep_assert_held(&gpu->lock);
 
@@ -248,16 +251,38 @@
 	if (flush) {
 		unsigned int dwords = 7;
 
+		if (has_blt)
+			dwords += 10;
+
 		link_target = etnaviv_buffer_reserve(gpu, buffer, dwords);
 
 		CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
 		CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
+		if (has_blt) {
+			CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x1);
+			CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_BLT);
+			CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_BLT);
+			CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x0);
+		}
 		CMD_LOAD_STATE(buffer, VIVS_GL_FLUSH_CACHE, flush);
-		if (gpu->exec_state == ETNA_PIPE_3D)
-			CMD_LOAD_STATE(buffer, VIVS_TS_FLUSH_CACHE,
-				       VIVS_TS_FLUSH_CACHE_FLUSH);
+		if (gpu->exec_state == ETNA_PIPE_3D) {
+			if (has_blt) {
+				CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x1);
+				CMD_LOAD_STATE(buffer, VIVS_BLT_SET_COMMAND, 0x1);
+				CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x0);
+			} else {
+				CMD_LOAD_STATE(buffer, VIVS_TS_FLUSH_CACHE,
+					       VIVS_TS_FLUSH_CACHE_FLUSH);
+			}
+		}
 		CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
 		CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
+		if (has_blt) {
+			CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x1);
+			CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_BLT);
+			CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_BLT);
+			CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x0);
+		}
 		CMD_END(buffer);
 
 		etnaviv_buffer_replace_wait(buffer, waitlink_offset,
@@ -323,6 +348,8 @@
 	bool switch_mmu_context = gpu->mmu_context != mmu_context;
 	unsigned int new_flush_seq = READ_ONCE(gpu->mmu_context->flush_seq);
 	bool need_flush = switch_mmu_context || gpu->flush_seq != new_flush_seq;
+	bool has_blt = !!(gpu->identity.minor_features5 &
+			  chipMinorFeatures5_BLT_ENGINE);
 
 	lockdep_assert_held(&gpu->lock);
 
@@ -370,8 +397,7 @@
 		if (switch_mmu_context) {
 			struct etnaviv_iommu_context *old_context = gpu->mmu_context;
 
-			etnaviv_iommu_context_get(mmu_context);
-			gpu->mmu_context = mmu_context;
+			gpu->mmu_context = etnaviv_iommu_context_get(mmu_context);
 			etnaviv_iommu_context_put(old_context);
 		}
 
@@ -433,6 +459,15 @@
 	 * 2 semaphore stall + 1 event + 1 wait + 1 link.
 	 */
 	return_dwords = 7;
+
+	/*
+	 * When the BLT engine is present we need 6 more dwords in the return
+	 * target: 3 enable/flush/disable + 4 enable/semaphore stall/disable,
+	 * but we don't need the normal TS flush state.
+	 */
+	if (has_blt)
+		return_dwords += 6;
+
 	return_target = etnaviv_buffer_reserve(gpu, buffer, return_dwords);
 	CMD_LINK(cmdbuf, return_dwords, return_target);
 
@@ -446,12 +481,27 @@
 	} else {
 		CMD_LOAD_STATE(buffer, VIVS_GL_FLUSH_CACHE,
 				       VIVS_GL_FLUSH_CACHE_DEPTH |
-				       VIVS_GL_FLUSH_CACHE_COLOR);
-		CMD_LOAD_STATE(buffer, VIVS_TS_FLUSH_CACHE,
-				       VIVS_TS_FLUSH_CACHE_FLUSH);
+				       VIVS_GL_FLUSH_CACHE_COLOR |
+				       VIVS_GL_FLUSH_CACHE_SHADER_L1);
+		if (has_blt) {
+			CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x1);
+			CMD_LOAD_STATE(buffer, VIVS_BLT_SET_COMMAND, 0x1);
+			CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x0);
+		} else {
+			CMD_LOAD_STATE(buffer, VIVS_TS_FLUSH_CACHE,
+					       VIVS_TS_FLUSH_CACHE_FLUSH);
+		}
 	}
 	CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
 	CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE);
+
+	if (has_blt) {
+		CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x1);
+		CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_BLT);
+		CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_BLT);
+		CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x0);
+	}
+
 	CMD_LOAD_STATE(buffer, VIVS_GL_EVENT, VIVS_GL_EVENT_EVENT_ID(event) |
 		       VIVS_GL_EVENT_FROM_PE);
 	CMD_WAIT(buffer);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/etnaviv/etnaviv_dump.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/etnaviv/etnaviv_dump.c
@@ -75,7 +75,7 @@
 	hdr->file_size = cpu_to_le32(data_end - iter->data);
 
 	iter->hdr++;
-	iter->data += hdr->file_size;
+	iter->data += le32_to_cpu(hdr->file_size);
 }
 
 static void etnaviv_core_dump_registers(struct core_dump_iterator *iter,
@@ -83,10 +83,15 @@
 {
 	struct etnaviv_dump_registers *reg = iter->data;
 	unsigned int i;
+	u32 read_addr;
 
 	for (i = 0; i < ARRAY_SIZE(etnaviv_dump_registers); i++, reg++) {
-		reg->reg = etnaviv_dump_registers[i];
-		reg->value = gpu_read(gpu, etnaviv_dump_registers[i]);
+		read_addr = etnaviv_dump_registers[i];
+		if (read_addr >= VIVS_PM_POWER_CONTROLS &&
+		    read_addr <= VIVS_PM_PULSE_EATER)
+			read_addr = gpu_fix_power_address(gpu, read_addr);
+		reg->reg = cpu_to_le32(etnaviv_dump_registers[i]);
+		reg->value = cpu_to_le32(gpu_read(gpu, read_addr));
 	}
 
 	etnaviv_core_dump_header(iter, ETDUMP_BUF_REG, reg);
@@ -125,9 +130,9 @@
 		return;
 	etnaviv_dump_core = false;
 
-	mutex_lock(&gpu->mmu_context->lock);
+	mutex_lock(&submit->mmu_context->lock);
 
-	mmu_size = etnaviv_iommu_dump_size(gpu->mmu_context);
+	mmu_size = etnaviv_iommu_dump_size(submit->mmu_context);
 
 	/* We always dump registers, mmu, ring, hanging cmdbuf and end marker */
 	n_obj = 5;
@@ -157,7 +162,7 @@
 	iter.start = __vmalloc(file_size, GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY,
 			       PAGE_KERNEL);
 	if (!iter.start) {
-		mutex_unlock(&gpu->mmu_context->lock);
+		mutex_unlock(&submit->mmu_context->lock);
 		dev_warn(gpu->dev, "failed to allocate devcoredump file\n");
 		return;
 	}
@@ -169,18 +174,18 @@
 	memset(iter.hdr, 0, iter.data - iter.start);
 
 	etnaviv_core_dump_registers(&iter, gpu);
-	etnaviv_core_dump_mmu(&iter, gpu->mmu_context, mmu_size);
+	etnaviv_core_dump_mmu(&iter, submit->mmu_context, mmu_size);
 	etnaviv_core_dump_mem(&iter, ETDUMP_BUF_RING, gpu->buffer.vaddr,
 			      gpu->buffer.size,
 			      etnaviv_cmdbuf_get_va(&gpu->buffer,
-					&gpu->mmu_context->cmdbuf_mapping));
+					&submit->mmu_context->cmdbuf_mapping));
 
 	etnaviv_core_dump_mem(&iter, ETDUMP_BUF_CMD,
 			      submit->cmdbuf.vaddr, submit->cmdbuf.size,
 			      etnaviv_cmdbuf_get_va(&submit->cmdbuf,
-					&gpu->mmu_context->cmdbuf_mapping));
+					&submit->mmu_context->cmdbuf_mapping));
 
-	mutex_unlock(&gpu->mmu_context->lock);
+	mutex_unlock(&submit->mmu_context->lock);
 
 	/* Reserve space for the bomap */
 	if (n_bomap_pages) {
@@ -207,7 +212,7 @@
 		if (!IS_ERR(pages)) {
 			int j;
 
-			iter.hdr->data[0] = bomap - bomap_start;
+			iter.hdr->data[0] = cpu_to_le32((bomap - bomap_start));
 
 			for (j = 0; j < obj->base.size >> PAGE_SHIFT; j++)
 				*bomap++ = cpu_to_le64(page_to_phys(*pages++));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/etnaviv/etnaviv_gem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/etnaviv/etnaviv_gem.c
@@ -27,7 +27,7 @@
 	 * because display controller, GPU, etc. are not coherent.
 	 */
 	if (etnaviv_obj->flags & ETNA_BO_CACHE_MASK)
-		dma_map_sg(dev->dev, sgt->sgl, sgt->nents, DMA_BIDIRECTIONAL);
+		dma_map_sgtable(dev->dev, sgt, DMA_BIDIRECTIONAL, 0);
 }
 
 static void etnaviv_gem_scatterlist_unmap(struct etnaviv_gem_object *etnaviv_obj)
@@ -51,7 +51,7 @@
 	 * discard those writes.
 	 */
 	if (etnaviv_obj->flags & ETNA_BO_CACHE_MASK)
-		dma_unmap_sg(dev->dev, sgt->sgl, sgt->nents, DMA_BIDIRECTIONAL);
+		dma_unmap_sgtable(dev->dev, sgt, DMA_BIDIRECTIONAL, 0);
 }
 
 /* called with etnaviv_obj->lock held */
@@ -304,8 +304,7 @@
 		list_del(&mapping->obj_node);
 	}
 
-	etnaviv_iommu_context_get(mmu_context);
-	mapping->context = mmu_context;
+	mapping->context = etnaviv_iommu_context_get(mmu_context);
 	mapping->use = 1;
 
 	ret = etnaviv_iommu_map_gem(mmu_context, etnaviv_obj,
@@ -351,6 +350,7 @@
 static void *etnaviv_gem_vmap_impl(struct etnaviv_gem_object *obj)
 {
 	struct page **pages;
+	pgprot_t prot;
 
 	lockdep_assert_held(&obj->lock);
 
@@ -358,15 +358,28 @@
 	if (IS_ERR(pages))
 		return NULL;
 
-	return vmap(pages, obj->base.size >> PAGE_SHIFT,
-			VM_MAP, pgprot_writecombine(PAGE_KERNEL));
+	switch (obj->flags & ETNA_BO_CACHE_MASK) {
+	case ETNA_BO_CACHED:
+		prot = PAGE_KERNEL;
+		break;
+	case ETNA_BO_UNCACHED:
+		prot = pgprot_noncached(PAGE_KERNEL);
+		break;
+	case ETNA_BO_WC:
+	default:
+		prot = pgprot_writecombine(PAGE_KERNEL);
+	}
+
+	return vmap(pages, obj->base.size >> PAGE_SHIFT, VM_MAP, prot);
 }
 
 static inline enum dma_data_direction etnaviv_op_to_dma_dir(u32 op)
 {
-	if (op & ETNA_PREP_READ)
+	op &= ETNA_PREP_READ | ETNA_PREP_WRITE;
+
+	if (op == ETNA_PREP_READ)
 		return DMA_FROM_DEVICE;
-	else if (op & ETNA_PREP_WRITE)
+	else if (op == ETNA_PREP_WRITE)
 		return DMA_TO_DEVICE;
 	else
 		return DMA_BIDIRECTIONAL;
@@ -404,9 +417,8 @@
 	}
 
 	if (etnaviv_obj->flags & ETNA_BO_CACHED) {
-		dma_sync_sg_for_cpu(dev->dev, etnaviv_obj->sgt->sgl,
-				    etnaviv_obj->sgt->nents,
-				    etnaviv_op_to_dma_dir(op));
+		dma_sync_sgtable_for_cpu(dev->dev, etnaviv_obj->sgt,
+					 etnaviv_op_to_dma_dir(op));
 		etnaviv_obj->last_cpu_prep_op = op;
 	}
 
@@ -421,8 +433,7 @@
 	if (etnaviv_obj->flags & ETNA_BO_CACHED) {
 		/* fini without a prep is almost certainly a userspace error */
 		WARN_ON(etnaviv_obj->last_cpu_prep_op == 0);
-		dma_sync_sg_for_device(dev->dev, etnaviv_obj->sgt->sgl,
-			etnaviv_obj->sgt->nents,
+		dma_sync_sgtable_for_device(dev->dev, etnaviv_obj->sgt,
 			etnaviv_op_to_dma_dir(etnaviv_obj->last_cpu_prep_op));
 		etnaviv_obj->last_cpu_prep_op = 0;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c
@@ -93,7 +93,15 @@
 static int etnaviv_gem_prime_mmap_obj(struct etnaviv_gem_object *etnaviv_obj,
 		struct vm_area_struct *vma)
 {
-	return dma_buf_mmap(etnaviv_obj->base.dma_buf, vma, 0);
+	int ret;
+
+	ret = dma_buf_mmap(etnaviv_obj->base.dma_buf, vma, 0);
+	if (!ret) {
+		/* Drop the reference acquired by drm_gem_mmap_obj(). */
+		drm_gem_object_put_unlocked(&etnaviv_obj->base);
+	}
+
+	return ret;
 }
 
 static const struct etnaviv_gem_ops etnaviv_gem_prime_ops = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
@@ -240,8 +240,10 @@
 		}
 
 		if ((submit->flags & ETNA_SUBMIT_SOFTPIN) &&
-		     submit->bos[i].va != mapping->iova)
+		     submit->bos[i].va != mapping->iova) {
+			etnaviv_gem_mapping_unreference(mapping);
 			return -EINVAL;
+		}
 
 		atomic_inc(&etnaviv_obj->gpu_active);
 
@@ -469,6 +471,12 @@
 		return -EINVAL;
 	}
 
+	if (args->stream_size > SZ_128K || args->nr_relocs > SZ_128K ||
+	    args->nr_bos > SZ_128K || args->nr_pmrs > 128) {
+		DRM_ERROR("submit arguments out of size limits\n");
+		return -EINVAL;
+	}
+
 	/*
 	 * Copy the command submission and bo array to kernel space in
 	 * one go, and do this outside of any locks.
@@ -532,8 +540,7 @@
 		goto err_submit_objects;
 
 	submit->ctx = file->driver_priv;
-	etnaviv_iommu_context_get(submit->ctx->mmu);
-	submit->mmu_context = submit->ctx->mmu;
+	submit->mmu_context = etnaviv_iommu_context_get(submit->ctx->mmu);
 	submit->exec_state = args->exec_state;
 	submit->flags = args->flags;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
@@ -392,6 +392,12 @@
 	if (gpu->identity.model == chipModel_GC700)
 		gpu->identity.features &= ~chipFeatures_FAST_CLEAR;
 
+	/* These models/revisions don't have the 2D pipe bit */
+	if ((gpu->identity.model == chipModel_GC500 &&
+	     gpu->identity.revision <= 2) ||
+	    gpu->identity.model == chipModel_GC300)
+		gpu->identity.features |= chipFeatures_PIPE_2D;
+
 	if ((gpu->identity.model == chipModel_GC500 &&
 	     gpu->identity.revision < 2) ||
 	    (gpu->identity.model == chipModel_GC300 &&
@@ -425,8 +431,9 @@
 				gpu_read(gpu, VIVS_HI_CHIP_MINOR_FEATURE_5);
 	}
 
-	/* GC600 idle register reports zero bits where modules aren't present */
-	if (gpu->identity.model == chipModel_GC600)
+	/* GC600/300 idle register reports zero bits where modules aren't present */
+	if (gpu->identity.model == chipModel_GC600 ||
+	    gpu->identity.model == chipModel_GC300)
 		gpu->idle_mask = VIVS_HI_IDLE_STATE_TX |
 				 VIVS_HI_IDLE_STATE_RA |
 				 VIVS_HI_IDLE_STATE_SE |
@@ -545,6 +552,12 @@
 	/* We rely on the GPU running, so program the clock */
 	etnaviv_gpu_update_clock(gpu);
 
+	gpu->fe_running = false;
+	gpu->exec_state = -1;
+	if (gpu->mmu_context)
+		etnaviv_iommu_context_put(gpu->mmu_context);
+	gpu->mmu_context = NULL;
+
 	return 0;
 }
 
@@ -553,7 +566,7 @@
 	u32 pmc, ppc;
 
 	/* enable clock gating */
-	ppc = gpu_read(gpu, VIVS_PM_POWER_CONTROLS);
+	ppc = gpu_read_power(gpu, VIVS_PM_POWER_CONTROLS);
 	ppc |= VIVS_PM_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING;
 
 	/* Disable stall module clock gating for 4.3.0.1 and 4.3.0.2 revs */
@@ -561,9 +574,9 @@
 	    gpu->identity.revision == 0x4302)
 		ppc |= VIVS_PM_POWER_CONTROLS_DISABLE_STALL_MODULE_CLOCK_GATING;
 
-	gpu_write(gpu, VIVS_PM_POWER_CONTROLS, ppc);
+	gpu_write_power(gpu, VIVS_PM_POWER_CONTROLS, ppc);
 
-	pmc = gpu_read(gpu, VIVS_PM_MODULE_CONTROLS);
+	pmc = gpu_read_power(gpu, VIVS_PM_MODULE_CONTROLS);
 
 	/* Disable PA clock gating for GC400+ without bugfix except for GC420 */
 	if (gpu->identity.model >= chipModel_GC400 &&
@@ -592,7 +605,7 @@
 	pmc |= VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_RA_HZ;
 	pmc |= VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_RA_EZ;
 
-	gpu_write(gpu, VIVS_PM_MODULE_CONTROLS, pmc);
+	gpu_write_power(gpu, VIVS_PM_MODULE_CONTROLS, pmc);
 }
 
 void etnaviv_gpu_start_fe(struct etnaviv_gpu *gpu, u32 address, u16 prefetch)
@@ -607,19 +620,23 @@
 			  VIVS_MMUv2_SEC_COMMAND_CONTROL_ENABLE |
 			  VIVS_MMUv2_SEC_COMMAND_CONTROL_PREFETCH(prefetch));
 	}
+
+	gpu->fe_running = true;
 }
 
-static void etnaviv_gpu_start_fe_idleloop(struct etnaviv_gpu *gpu)
+static void etnaviv_gpu_start_fe_idleloop(struct etnaviv_gpu *gpu,
+					  struct etnaviv_iommu_context *context)
 {
-	u32 address = etnaviv_cmdbuf_get_va(&gpu->buffer,
-				&gpu->mmu_context->cmdbuf_mapping);
 	u16 prefetch;
+	u32 address;
 
 	/* setup the MMU */
-	etnaviv_iommu_restore(gpu, gpu->mmu_context);
+	etnaviv_iommu_restore(gpu, context);
 
 	/* Start command processor */
 	prefetch = etnaviv_buffer_init(gpu);
+	address = etnaviv_cmdbuf_get_va(&gpu->buffer,
+					&gpu->mmu_context->cmdbuf_mapping);
 
 	etnaviv_gpu_start_fe(gpu, address, prefetch);
 }
@@ -648,11 +665,11 @@
 	    (gpu->identity.features & chipFeatures_PIPE_3D))
 	{
 		/* Performance fix: disable internal DFS */
-		pulse_eater = gpu_read(gpu, VIVS_PM_PULSE_EATER);
+		pulse_eater = gpu_read_power(gpu, VIVS_PM_PULSE_EATER);
 		pulse_eater |= BIT(18);
 	}
 
-	gpu_write(gpu, VIVS_PM_PULSE_EATER, pulse_eater);
+	gpu_write_power(gpu, VIVS_PM_PULSE_EATER, pulse_eater);
 }
 
 static void etnaviv_gpu_hw_init(struct etnaviv_gpu *gpu)
@@ -713,7 +730,7 @@
 	ret = pm_runtime_get_sync(gpu->dev);
 	if (ret < 0) {
 		dev_err(gpu->dev, "Failed to enable GPU power domain\n");
-		return ret;
+		goto pm_put;
 	}
 
 	etnaviv_hw_identify(gpu);
@@ -790,7 +807,6 @@
 	/* Now program the hardware */
 	mutex_lock(&gpu->lock);
 	etnaviv_gpu_hw_init(gpu);
-	gpu->exec_state = -1;
 	mutex_unlock(&gpu->lock);
 
 	pm_runtime_mark_last_busy(gpu->dev);
@@ -802,6 +818,7 @@
 
 fail:
 	pm_runtime_mark_last_busy(gpu->dev);
+pm_put:
 	pm_runtime_put_autosuspend(gpu->dev);
 
 	return ret;
@@ -842,7 +859,7 @@
 
 	ret = pm_runtime_get_sync(gpu->dev);
 	if (ret < 0)
-		return ret;
+		goto pm_put;
 
 	dma_lo = gpu_read(gpu, VIVS_FE_DMA_LOW);
 	dma_hi = gpu_read(gpu, VIVS_FE_DMA_HIGH);
@@ -965,6 +982,7 @@
 	ret = 0;
 
 	pm_runtime_mark_last_busy(gpu->dev);
+pm_put:
 	pm_runtime_put_autosuspend(gpu->dev);
 
 	return ret;
@@ -978,7 +996,7 @@
 	dev_err(gpu->dev, "recover hung GPU!\n");
 
 	if (pm_runtime_get_sync(gpu->dev) < 0)
-		return;
+		goto pm_put;
 
 	mutex_lock(&gpu->lock);
 
@@ -992,11 +1010,10 @@
 	spin_unlock(&gpu->event_spinlock);
 
 	etnaviv_gpu_hw_init(gpu);
-	gpu->exec_state = -1;
-	gpu->mmu_context = NULL;
 
 	mutex_unlock(&gpu->lock);
 	pm_runtime_mark_last_busy(gpu->dev);
+pm_put:
 	pm_runtime_put_autosuspend(gpu->dev);
 }
 
@@ -1219,10 +1236,12 @@
 {
 	u32 val;
 
+	mutex_lock(&gpu->lock);
+
 	/* disable clock gating */
-	val = gpu_read(gpu, VIVS_PM_POWER_CONTROLS);
+	val = gpu_read_power(gpu, VIVS_PM_POWER_CONTROLS);
 	val &= ~VIVS_PM_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING;
-	gpu_write(gpu, VIVS_PM_POWER_CONTROLS, val);
+	gpu_write_power(gpu, VIVS_PM_POWER_CONTROLS, val);
 
 	/* enable debug register */
 	val = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);
@@ -1230,6 +1249,8 @@
 	gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, val);
 
 	sync_point_perfmon_sample(gpu, event, ETNA_PM_PROCESS_PRE);
+
+	mutex_unlock(&gpu->lock);
 }
 
 static void sync_point_perfmon_sample_post(struct etnaviv_gpu *gpu,
@@ -1239,13 +1260,9 @@
 	unsigned int i;
 	u32 val;
 
-	sync_point_perfmon_sample(gpu, event, ETNA_PM_PROCESS_POST);
-
-	for (i = 0; i < submit->nr_pmrs; i++) {
-		const struct etnaviv_perfmon_request *pmr = submit->pmrs + i;
+	mutex_lock(&gpu->lock);
 
-		*pmr->bo_vma = pmr->sequence;
-	}
+	sync_point_perfmon_sample(gpu, event, ETNA_PM_PROCESS_POST);
 
 	/* disable debug register */
 	val = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);
@@ -1253,9 +1270,17 @@
 	gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, val);
 
 	/* enable clock gating */
-	val = gpu_read(gpu, VIVS_PM_POWER_CONTROLS);
+	val = gpu_read_power(gpu, VIVS_PM_POWER_CONTROLS);
 	val |= VIVS_PM_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING;
-	gpu_write(gpu, VIVS_PM_POWER_CONTROLS, val);
+	gpu_write_power(gpu, VIVS_PM_POWER_CONTROLS, val);
+
+	mutex_unlock(&gpu->lock);
+
+	for (i = 0; i < submit->nr_pmrs; i++) {
+		const struct etnaviv_perfmon_request *pmr = submit->pmrs + i;
+
+		*pmr->bo_vma = pmr->sequence;
+	}
 }
 
 
@@ -1269,8 +1294,10 @@
 
 	if (!submit->runtime_resumed) {
 		ret = pm_runtime_get_sync(gpu->dev);
-		if (ret < 0)
+		if (ret < 0) {
+			pm_runtime_put_noidle(gpu->dev);
 			return NULL;
+		}
 		submit->runtime_resumed = true;
 	}
 
@@ -1287,6 +1314,7 @@
 	ret = event_alloc(gpu, nr_events, event);
 	if (ret) {
 		DRM_ERROR("no free events\n");
+		pm_runtime_put_noidle(gpu->dev);
 		return NULL;
 	}
 
@@ -1300,14 +1328,12 @@
 		goto out_unlock;
 	}
 
-	if (!gpu->mmu_context) {
-		etnaviv_iommu_context_get(submit->mmu_context);
-		gpu->mmu_context = submit->mmu_context;
-		etnaviv_gpu_start_fe_idleloop(gpu);
-	} else {
-		etnaviv_iommu_context_get(gpu->mmu_context);
-		submit->prev_mmu_context = gpu->mmu_context;
-	}
+	if (!gpu->fe_running)
+		etnaviv_gpu_start_fe_idleloop(gpu, submit->mmu_context);
+
+	if (submit->prev_mmu_context)
+		etnaviv_iommu_context_put(submit->prev_mmu_context);
+	submit->prev_mmu_context = etnaviv_iommu_context_get(gpu->mmu_context);
 
 	if (submit->nr_pmrs) {
 		gpu->event[event[1]].sync_point = &sync_point_perfmon_sample_pre;
@@ -1457,7 +1483,7 @@
 	if (gpu->clk_bus) {
 		ret = clk_prepare_enable(gpu->clk_bus);
 		if (ret)
-			return ret;
+			goto disable_clk_reg;
 	}
 
 	if (gpu->clk_core) {
@@ -1480,6 +1506,9 @@
 disable_clk_bus:
 	if (gpu->clk_bus)
 		clk_disable_unprepare(gpu->clk_bus);
+disable_clk_reg:
+	if (gpu->clk_reg)
+		clk_disable_unprepare(gpu->clk_reg);
 
 	return ret;
 }
@@ -1521,7 +1550,7 @@
 
 static int etnaviv_gpu_hw_suspend(struct etnaviv_gpu *gpu)
 {
-	if (gpu->initialized && gpu->mmu_context) {
+	if (gpu->initialized && gpu->fe_running) {
 		/* Replace the last WAIT with END */
 		mutex_lock(&gpu->lock);
 		etnaviv_buffer_end(gpu);
@@ -1534,8 +1563,7 @@
 		 */
 		etnaviv_gpu_wait_idle(gpu, 100);
 
-		etnaviv_iommu_context_put(gpu->mmu_context);
-		gpu->mmu_context = NULL;
+		gpu->fe_running = false;
 	}
 
 	gpu->exec_state = -1;
@@ -1683,6 +1711,9 @@
 	etnaviv_gpu_hw_suspend(gpu);
 #endif
 
+	if (gpu->mmu_context)
+		etnaviv_iommu_context_put(gpu->mmu_context);
+
 	if (gpu->initialized) {
 		etnaviv_cmdbuf_free(&gpu->buffer);
 		etnaviv_iommu_global_fini(gpu);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
@@ -10,6 +10,7 @@
 #include "etnaviv_gem.h"
 #include "etnaviv_mmu.h"
 #include "etnaviv_drv.h"
+#include "common.xml.h"
 
 struct etnaviv_gem_submit;
 struct etnaviv_vram_mapping;
@@ -101,6 +102,7 @@
 	struct workqueue_struct *wq;
 	struct drm_gpu_scheduler sched;
 	bool initialized;
+	bool fe_running;
 
 	/* 'ring'-buffer: */
 	struct etnaviv_cmdbuf buffer;
@@ -157,6 +159,26 @@
 	return readl(gpu->mmio + reg);
 }
 
+static inline u32 gpu_fix_power_address(struct etnaviv_gpu *gpu, u32 reg)
+{
+	/* Power registers in GC300 < 2.0 are offset by 0x100 */
+	if (gpu->identity.model == chipModel_GC300 &&
+	    gpu->identity.revision < 0x2000)
+		reg += 0x100;
+
+	return reg;
+}
+
+static inline void gpu_write_power(struct etnaviv_gpu *gpu, u32 reg, u32 data)
+{
+	writel(data, gpu->mmio + gpu_fix_power_address(gpu, reg));
+}
+
+static inline u32 gpu_read_power(struct etnaviv_gpu *gpu, u32 reg)
+{
+	return readl(gpu->mmio + gpu_fix_power_address(gpu, reg));
+}
+
 int etnaviv_gpu_get_param(struct etnaviv_gpu *gpu, u32 param, u64 *value);
 
 int etnaviv_gpu_init(struct etnaviv_gpu *gpu);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/etnaviv/etnaviv_iommu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/etnaviv/etnaviv_iommu.c
@@ -92,6 +92,10 @@
 	struct etnaviv_iommuv1_context *v1_context = to_v1_context(context);
 	u32 pgtable;
 
+	if (gpu->mmu_context)
+		etnaviv_iommu_context_put(gpu->mmu_context);
+	gpu->mmu_context = etnaviv_iommu_context_get(context);
+
 	/* set base addresses */
 	gpu_write(gpu, VIVS_MC_MEMORY_BASE_ADDR_RA, context->global->memory_base);
 	gpu_write(gpu, VIVS_MC_MEMORY_BASE_ADDR_FE, context->global->memory_base);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c
@@ -172,6 +172,10 @@
 	if (gpu_read(gpu, VIVS_MMUv2_CONTROL) & VIVS_MMUv2_CONTROL_ENABLE)
 		return;
 
+	if (gpu->mmu_context)
+		etnaviv_iommu_context_put(gpu->mmu_context);
+	gpu->mmu_context = etnaviv_iommu_context_get(context);
+
 	prefetch = etnaviv_buffer_config_mmuv2(gpu,
 				(u32)v2_context->mtlb_dma,
 				(u32)context->global->bad_page_dma);
@@ -192,6 +196,10 @@
 	if (gpu_read(gpu, VIVS_MMUv2_SEC_CONTROL) & VIVS_MMUv2_SEC_CONTROL_ENABLE)
 		return;
 
+	if (gpu->mmu_context)
+		etnaviv_iommu_context_put(gpu->mmu_context);
+	gpu->mmu_context = etnaviv_iommu_context_get(context);
+
 	gpu_write(gpu, VIVS_MMUv2_PTA_ADDRESS_LOW,
 		  lower_32_bits(context->global->v2.pta_dma));
 	gpu_write(gpu, VIVS_MMUv2_PTA_ADDRESS_HIGH,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
@@ -73,17 +73,17 @@
 			     struct sg_table *sgt, unsigned len, int prot)
 {	struct scatterlist *sg;
 	unsigned int da = iova;
-	unsigned int i, j;
+	unsigned int i;
 	int ret;
 
 	if (!context || !sgt)
 		return -EINVAL;
 
-	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
-		u32 pa = sg_dma_address(sg) - sg->offset;
+	for_each_sgtable_dma_sg(sgt, sg, i) {
+		phys_addr_t pa = sg_dma_address(sg) - sg->offset;
 		size_t bytes = sg_dma_len(sg) + sg->offset;
 
-		VERB("map[%d]: %08x %08x(%zx)", i, iova, pa, bytes);
+		VERB("map[%d]: %08x %pap(%zx)", i, iova, &pa, bytes);
 
 		ret = etnaviv_context_map(context, da, pa, bytes, prot);
 		if (ret)
@@ -95,14 +95,7 @@
 	return 0;
 
 fail:
-	da = iova;
-
-	for_each_sg(sgt->sgl, sg, i, j) {
-		size_t bytes = sg_dma_len(sg) + sg->offset;
-
-		etnaviv_context_unmap(context, da, bytes);
-		da += bytes;
-	}
+	etnaviv_context_unmap(context, iova, da - iova);
 	return ret;
 }
 
@@ -113,7 +106,7 @@
 	unsigned int da = iova;
 	int i;
 
-	for_each_sg(sgt->sgl, sg, sgt->nents, i) {
+	for_each_sgtable_dma_sg(sgt, sg, i) {
 		size_t bytes = sg_dma_len(sg) + sg->offset;
 
 		etnaviv_context_unmap(context, da, bytes);
@@ -204,6 +197,7 @@
 		 */
 		list_for_each_entry_safe(m, n, &list, scan_node) {
 			etnaviv_iommu_remove_mapping(context, m);
+			etnaviv_iommu_context_put(m->context);
 			m->context = NULL;
 			list_del_init(&m->mmu_node);
 			list_del_init(&m->scan_node);
@@ -288,6 +282,12 @@
 
 	mutex_lock(&context->lock);
 
+	/* Bail if the mapping has been reaped by another thread */
+	if (!mapping->context) {
+		mutex_unlock(&context->lock);
+		return;
+	}
+
 	/* If the vram node is on the mm, unmap and remove the node */
 	if (mapping->vram_node.mm == &context->mm)
 		etnaviv_iommu_remove_mapping(context, mapping);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/etnaviv/etnaviv_mmu.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/etnaviv/etnaviv_mmu.h
@@ -105,9 +105,11 @@
 struct etnaviv_iommu_context *
 etnaviv_iommu_context_init(struct etnaviv_iommu_global *global,
 			   struct etnaviv_cmdbuf_suballoc *suballoc);
-static inline void etnaviv_iommu_context_get(struct etnaviv_iommu_context *ctx)
+static inline struct etnaviv_iommu_context *
+etnaviv_iommu_context_get(struct etnaviv_iommu_context *ctx)
 {
 	kref_get(&ctx->refcount);
+	return ctx;
 }
 void etnaviv_iommu_context_put(struct etnaviv_iommu_context *ctx);
 void etnaviv_iommu_restore(struct etnaviv_gpu *gpu,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/etnaviv/etnaviv_perfmon.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/etnaviv/etnaviv_perfmon.c
@@ -32,6 +32,7 @@
 };
 
 struct etnaviv_pm_domain_meta {
+	unsigned int feature;
 	const struct etnaviv_pm_domain *domains;
 	u32 nr_domains;
 };
@@ -410,36 +411,78 @@
 
 static const struct etnaviv_pm_domain_meta doms_meta[] = {
 	{
+		.feature = chipFeatures_PIPE_3D,
 		.nr_domains = ARRAY_SIZE(doms_3d),
 		.domains = &doms_3d[0]
 	},
 	{
+		.feature = chipFeatures_PIPE_2D,
 		.nr_domains = ARRAY_SIZE(doms_2d),
 		.domains = &doms_2d[0]
 	},
 	{
+		.feature = chipFeatures_PIPE_VG,
 		.nr_domains = ARRAY_SIZE(doms_vg),
 		.domains = &doms_vg[0]
 	}
 };
 
+static unsigned int num_pm_domains(const struct etnaviv_gpu *gpu)
+{
+	unsigned int num = 0, i;
+
+	for (i = 0; i < ARRAY_SIZE(doms_meta); i++) {
+		const struct etnaviv_pm_domain_meta *meta = &doms_meta[i];
+
+		if (gpu->identity.features & meta->feature)
+			num += meta->nr_domains;
+	}
+
+	return num;
+}
+
+static const struct etnaviv_pm_domain *pm_domain(const struct etnaviv_gpu *gpu,
+	unsigned int index)
+{
+	const struct etnaviv_pm_domain *domain = NULL;
+	unsigned int offset = 0, i;
+
+	for (i = 0; i < ARRAY_SIZE(doms_meta); i++) {
+		const struct etnaviv_pm_domain_meta *meta = &doms_meta[i];
+
+		if (!(gpu->identity.features & meta->feature))
+			continue;
+
+		if (index - offset >= meta->nr_domains) {
+			offset += meta->nr_domains;
+			continue;
+		}
+
+		domain = meta->domains + (index - offset);
+	}
+
+	return domain;
+}
+
 int etnaviv_pm_query_dom(struct etnaviv_gpu *gpu,
 	struct drm_etnaviv_pm_domain *domain)
 {
-	const struct etnaviv_pm_domain_meta *meta = &doms_meta[domain->pipe];
+	const unsigned int nr_domains = num_pm_domains(gpu);
 	const struct etnaviv_pm_domain *dom;
 
-	if (domain->iter >= meta->nr_domains)
+	if (domain->iter >= nr_domains)
 		return -EINVAL;
 
-	dom = meta->domains + domain->iter;
+	dom = pm_domain(gpu, domain->iter);
+	if (!dom)
+		return -EINVAL;
 
 	domain->id = domain->iter;
 	domain->nr_signals = dom->nr_signals;
 	strncpy(domain->name, dom->name, sizeof(domain->name));
 
 	domain->iter++;
-	if (domain->iter == meta->nr_domains)
+	if (domain->iter == nr_domains)
 		domain->iter = 0xff;
 
 	return 0;
@@ -448,14 +491,16 @@
 int etnaviv_pm_query_sig(struct etnaviv_gpu *gpu,
 	struct drm_etnaviv_pm_signal *signal)
 {
-	const struct etnaviv_pm_domain_meta *meta = &doms_meta[signal->pipe];
+	const unsigned int nr_domains = num_pm_domains(gpu);
 	const struct etnaviv_pm_domain *dom;
 	const struct etnaviv_pm_signal *sig;
 
-	if (signal->domain >= meta->nr_domains)
+	if (signal->domain >= nr_domains)
 		return -EINVAL;
 
-	dom = meta->domains + signal->domain;
+	dom = pm_domain(gpu, signal->domain);
+	if (!dom)
+		return -EINVAL;
 
 	if (signal->iter >= dom->nr_signals)
 		return -EINVAL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/etnaviv/state_blt.xml.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/etnaviv/state_blt.xml.h
@@ -46,6 +46,8 @@
 
 /* This is a cut-down version of the state_blt.xml.h file */
 
+#define VIVS_BLT_SET_COMMAND					0x000140ac
+
 #define VIVS_BLT_ENABLE						0x000140b8
 #define VIVS_BLT_ENABLE_ENABLE					0x00000001
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
@@ -55,6 +55,7 @@
 struct decon_context {
 	struct device			*dev;
 	struct drm_device		*drm_dev;
+	void				*dma_priv;
 	struct exynos_drm_crtc		*crtc;
 	struct exynos_drm_plane		planes[WINDOWS_NR];
 	struct exynos_drm_plane_config	configs[WINDOWS_NR];
@@ -317,9 +318,9 @@
 static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win,
 				 struct drm_framebuffer *fb)
 {
-	struct exynos_drm_plane plane = ctx->planes[win];
+	struct exynos_drm_plane *plane = &ctx->planes[win];
 	struct exynos_drm_plane_state *state =
-		to_exynos_plane_state(plane.base.state);
+		to_exynos_plane_state(plane->base.state);
 	unsigned int alpha = state->base.alpha;
 	unsigned int pixel_alpha;
 	unsigned long val;
@@ -644,7 +645,7 @@
 
 	decon_clear_channels(ctx->crtc);
 
-	return exynos_drm_register_dma(drm_dev, dev);
+	return exynos_drm_register_dma(drm_dev, dev, &ctx->dma_priv);
 }
 
 static void decon_unbind(struct device *dev, struct device *master, void *data)
@@ -654,7 +655,7 @@
 	decon_disable(ctx->crtc);
 
 	/* detach this sub driver from iommu mapping if supported. */
-	exynos_drm_unregister_dma(ctx->drm_dev, ctx->dev);
+	exynos_drm_unregister_dma(ctx->drm_dev, ctx->dev, &ctx->dma_priv);
 }
 
 static const struct component_ops decon_component_ops = {
@@ -774,8 +775,8 @@
 			return irq;
 		}
 	}
-	irq_set_status_flags(irq, IRQ_NOAUTOEN);
-	ret = devm_request_irq(ctx->dev, irq, handler, flags, "drm_decon", ctx);
+	ret = devm_request_irq(ctx->dev, irq, handler,
+			       flags | IRQF_NO_AUTOEN, "drm_decon", ctx);
 	if (ret < 0) {
 		dev_err(ctx->dev, "IRQ %s request failed\n", name);
 		return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/exynos/exynos7_drm_decon.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/exynos/exynos7_drm_decon.c
@@ -40,6 +40,7 @@
 struct decon_context {
 	struct device			*dev;
 	struct drm_device		*drm_dev;
+	void				*dma_priv;
 	struct exynos_drm_crtc		*crtc;
 	struct exynos_drm_plane		planes[WINDOWS_NR];
 	struct exynos_drm_plane_config	configs[WINDOWS_NR];
@@ -127,13 +128,13 @@
 
 	decon_clear_channels(ctx->crtc);
 
-	return exynos_drm_register_dma(drm_dev, ctx->dev);
+	return exynos_drm_register_dma(drm_dev, ctx->dev, &ctx->dma_priv);
 }
 
 static void decon_ctx_remove(struct decon_context *ctx)
 {
 	/* detach this sub driver from iommu mapping if supported. */
-	exynos_drm_unregister_dma(ctx->drm_dev, ctx->dev);
+	exynos_drm_unregister_dma(ctx->drm_dev, ctx->dev, &ctx->dma_priv);
 }
 
 static u32 decon_calc_clkdiv(struct decon_context *ctx,
@@ -799,31 +800,40 @@
 	if (ret < 0) {
 		DRM_DEV_ERROR(dev, "Failed to prepare_enable the pclk [%d]\n",
 			      ret);
-		return ret;
+		goto err_pclk_enable;
 	}
 
 	ret = clk_prepare_enable(ctx->aclk);
 	if (ret < 0) {
 		DRM_DEV_ERROR(dev, "Failed to prepare_enable the aclk [%d]\n",
 			      ret);
-		return ret;
+		goto err_aclk_enable;
 	}
 
 	ret = clk_prepare_enable(ctx->eclk);
 	if  (ret < 0) {
 		DRM_DEV_ERROR(dev, "Failed to prepare_enable the eclk [%d]\n",
 			      ret);
-		return ret;
+		goto err_eclk_enable;
 	}
 
 	ret = clk_prepare_enable(ctx->vclk);
 	if  (ret < 0) {
 		DRM_DEV_ERROR(dev, "Failed to prepare_enable the vclk [%d]\n",
 			      ret);
-		return ret;
+		goto err_vclk_enable;
 	}
 
 	return 0;
+
+err_vclk_enable:
+	clk_disable_unprepare(ctx->eclk);
+err_eclk_enable:
+	clk_disable_unprepare(ctx->aclk);
+err_aclk_enable:
+	clk_disable_unprepare(ctx->pclk);
+err_pclk_enable:
+	return ret;
 }
 #endif
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/exynos/exynos_dp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/exynos/exynos_dp.c
@@ -109,7 +109,6 @@
 		if (ret) {
 			DRM_DEV_ERROR(dp->dev,
 				      "Failed to attach bridge to drm\n");
-			bridge->next = NULL;
 			return ret;
 		}
 	}
@@ -158,15 +157,8 @@
 	struct drm_device *drm_dev = data;
 	int ret;
 
-	dp->dev = dev;
 	dp->drm_dev = drm_dev;
 
-	dp->plat_data.dev_type = EXYNOS_DP;
-	dp->plat_data.power_on_start = exynos_dp_poweron;
-	dp->plat_data.power_off = exynos_dp_poweroff;
-	dp->plat_data.attach = exynos_dp_bridge_attach;
-	dp->plat_data.get_modes = exynos_dp_get_modes;
-
 	if (!dp->plat_data.panel && !dp->ptn_bridge) {
 		ret = exynos_dp_dt_parse_panel(dp);
 		if (ret)
@@ -184,13 +176,11 @@
 
 	dp->plat_data.encoder = encoder;
 
-	dp->adp = analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data);
-	if (IS_ERR(dp->adp)) {
+	ret = analogix_dp_bind(dp->adp, dp->drm_dev);
+	if (ret)
 		dp->encoder.funcs->destroy(&dp->encoder);
-		return PTR_ERR(dp->adp);
-	}
 
-	return 0;
+	return ret;
 }
 
 static void exynos_dp_unbind(struct device *dev, struct device *master,
@@ -221,6 +211,7 @@
 	if (!dp)
 		return -ENOMEM;
 
+	dp->dev = dev;
 	/*
 	 * We just use the drvdata until driver run into component
 	 * add function, and then we would set drvdata to null, so
@@ -246,16 +237,29 @@
 
 	/* The remote port can be either a panel or a bridge */
 	dp->plat_data.panel = panel;
+	dp->plat_data.dev_type = EXYNOS_DP;
+	dp->plat_data.power_on_start = exynos_dp_poweron;
+	dp->plat_data.power_off = exynos_dp_poweroff;
+	dp->plat_data.attach = exynos_dp_bridge_attach;
+	dp->plat_data.get_modes = exynos_dp_get_modes;
 	dp->plat_data.skip_connector = !!bridge;
+
 	dp->ptn_bridge = bridge;
 
 out:
+	dp->adp = analogix_dp_probe(dev, &dp->plat_data);
+	if (IS_ERR(dp->adp))
+		return PTR_ERR(dp->adp);
+
 	return component_add(&pdev->dev, &exynos_dp_ops);
 }
 
 static int exynos_dp_remove(struct platform_device *pdev)
 {
+	struct exynos_dp_device *dp = platform_get_drvdata(pdev);
+
 	component_del(&pdev->dev, &exynos_dp_ops);
+	analogix_dp_remove(dp->adp);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -39,13 +39,12 @@
 	if (exynos_crtc->ops->disable)
 		exynos_crtc->ops->disable(exynos_crtc);
 
+	spin_lock_irq(&crtc->dev->event_lock);
 	if (crtc->state->event && !crtc->state->active) {
-		spin_lock_irq(&crtc->dev->event_lock);
 		drm_crtc_send_vblank_event(crtc, crtc->state->event);
-		spin_unlock_irq(&crtc->dev->event_lock);
-
 		crtc->state->event = NULL;
 	}
+	spin_unlock_irq(&crtc->dev->event_lock);
 }
 
 static int exynos_crtc_atomic_check(struct drm_crtc *crtc,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/exynos/exynos_drm_dma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/exynos/exynos_drm_dma.c
@@ -58,10 +58,10 @@
  * mapping.
  */
 static int drm_iommu_attach_device(struct drm_device *drm_dev,
-				struct device *subdrv_dev)
+				struct device *subdrv_dev, void **dma_priv)
 {
 	struct exynos_drm_private *priv = drm_dev->dev_private;
-	int ret;
+	int ret = 0;
 
 	if (get_dma_ops(priv->dma_dev) != get_dma_ops(subdrv_dev)) {
 		DRM_DEV_ERROR(subdrv_dev, "Device %s lacks support for IOMMU\n",
@@ -74,7 +74,14 @@
 		return ret;
 
 	if (IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)) {
-		if (to_dma_iommu_mapping(subdrv_dev))
+		/*
+		 * Keep the original DMA mapping of the sub-device and
+		 * restore it on Exynos DRM detach, otherwise the DMA
+		 * framework considers it as IOMMU-less during the next
+		 * probe (in case of deferred probe or modular build)
+		 */
+		*dma_priv = to_dma_iommu_mapping(subdrv_dev);
+		if (*dma_priv)
 			arm_iommu_detach_device(subdrv_dev);
 
 		ret = arm_iommu_attach_device(subdrv_dev, priv->mapping);
@@ -85,7 +92,7 @@
 	if (ret)
 		clear_dma_max_seg_size(subdrv_dev);
 
-	return 0;
+	return ret;
 }
 
 /*
@@ -98,19 +105,21 @@
  * mapping
  */
 static void drm_iommu_detach_device(struct drm_device *drm_dev,
-				struct device *subdrv_dev)
+				    struct device *subdrv_dev, void **dma_priv)
 {
 	struct exynos_drm_private *priv = drm_dev->dev_private;
 
-	if (IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU))
+	if (IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)) {
 		arm_iommu_detach_device(subdrv_dev);
-	else if (IS_ENABLED(CONFIG_IOMMU_DMA))
+		arm_iommu_attach_device(subdrv_dev, *dma_priv);
+	} else if (IS_ENABLED(CONFIG_IOMMU_DMA))
 		iommu_detach_device(priv->mapping, subdrv_dev);
 
 	clear_dma_max_seg_size(subdrv_dev);
 }
 
-int exynos_drm_register_dma(struct drm_device *drm, struct device *dev)
+int exynos_drm_register_dma(struct drm_device *drm, struct device *dev,
+			    void **dma_priv)
 {
 	struct exynos_drm_private *priv = drm->dev_private;
 
@@ -124,7 +133,7 @@
 		return 0;
 
 	if (!priv->mapping) {
-		void *mapping;
+		void *mapping = NULL;
 
 		if (IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU))
 			mapping = arm_iommu_create_mapping(&platform_bus_type,
@@ -132,18 +141,19 @@
 		else if (IS_ENABLED(CONFIG_IOMMU_DMA))
 			mapping = iommu_get_domain_for_dev(priv->dma_dev);
 
-		if (IS_ERR(mapping))
-			return PTR_ERR(mapping);
+		if (!mapping)
+			return -ENODEV;
 		priv->mapping = mapping;
 	}
 
-	return drm_iommu_attach_device(drm, dev);
+	return drm_iommu_attach_device(drm, dev, dma_priv);
 }
 
-void exynos_drm_unregister_dma(struct drm_device *drm, struct device *dev)
+void exynos_drm_unregister_dma(struct drm_device *drm, struct device *dev,
+			       void **dma_priv)
 {
 	if (IS_ENABLED(CONFIG_EXYNOS_IOMMU))
-		drm_iommu_detach_device(drm, dev);
+		drm_iommu_detach_device(drm, dev, dma_priv);
 }
 
 void exynos_drm_cleanup_dma(struct drm_device *drm)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -346,6 +346,7 @@
 	drm_mode_config_cleanup(drm);
 	exynos_drm_cleanup_dma(drm);
 	kfree(private);
+	dev_set_drvdata(dev, NULL);
 err_free_drm:
 	drm_dev_put(drm);
 
@@ -360,6 +361,7 @@
 
 	exynos_drm_fbdev_fini(drm);
 	drm_kms_helper_poll_fini(drm);
+	drm_atomic_helper_shutdown(drm);
 
 	component_unbind_all(drm->dev, drm);
 	drm_mode_config_cleanup(drm);
@@ -397,9 +399,18 @@
 	return 0;
 }
 
+static void exynos_drm_platform_shutdown(struct platform_device *pdev)
+{
+	struct drm_device *drm = platform_get_drvdata(pdev);
+
+	if (drm)
+		drm_atomic_helper_shutdown(drm);
+}
+
 static struct platform_driver exynos_drm_platform_driver = {
 	.probe	= exynos_drm_platform_probe,
 	.remove	= exynos_drm_platform_remove,
+	.shutdown = exynos_drm_platform_shutdown,
 	.driver	= {
 		.name	= "exynos-drm",
 		.pm	= &exynos_drm_pm_ops,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -223,8 +223,10 @@
 	return priv->mapping ? true : false;
 }
 
-int exynos_drm_register_dma(struct drm_device *drm, struct device *dev);
-void exynos_drm_unregister_dma(struct drm_device *drm, struct device *dev);
+int exynos_drm_register_dma(struct drm_device *drm, struct device *dev,
+			    void **dma_priv);
+void exynos_drm_unregister_dma(struct drm_device *drm, struct device *dev,
+			       void **dma_priv);
 void exynos_drm_cleanup_dma(struct drm_device *drm);
 
 #ifdef CONFIG_DRM_EXYNOS_DPI
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -544,9 +544,9 @@
 	unsigned long best_freq = 0;
 	u32 min_delta = 0xffffffff;
 	u8 p_min, p_max;
-	u8 _p, uninitialized_var(best_p);
-	u16 _m, uninitialized_var(best_m);
-	u8 _s, uninitialized_var(best_s);
+	u8 _p, best_p;
+	u16 _m, best_m;
+	u8 _s, best_s;
 
 	p_min = DIV_ROUND_UP(fin, (12 * MHZ));
 	p_max = fin / (6 * MHZ);
@@ -1350,10 +1350,9 @@
 	}
 
 	te_gpio_irq = gpio_to_irq(dsi->te_gpio);
-	irq_set_status_flags(te_gpio_irq, IRQ_NOAUTOEN);
 
 	ret = request_threaded_irq(te_gpio_irq, exynos_dsi_te_irq_handler, NULL,
-					IRQF_TRIGGER_RISING, "TE", dsi);
+				   IRQF_TRIGGER_RISING | IRQF_NO_AUTOEN, "TE", dsi);
 	if (ret) {
 		dev_err(dsi->dev, "request interrupt failed with %d\n", ret);
 		gpio_free(dsi->te_gpio);
@@ -1389,7 +1388,7 @@
 		if (ret < 0)
 			goto err_put_sync;
 	} else {
-		drm_bridge_pre_enable(dsi->out_bridge);
+		drm_bridge_chain_pre_enable(dsi->out_bridge);
 	}
 
 	exynos_dsi_set_display_mode(dsi);
@@ -1400,7 +1399,7 @@
 		if (ret < 0)
 			goto err_display_disable;
 	} else {
-		drm_bridge_enable(dsi->out_bridge);
+		drm_bridge_chain_enable(dsi->out_bridge);
 	}
 
 	dsi->state |= DSIM_STATE_VIDOUT_AVAILABLE;
@@ -1425,10 +1424,10 @@
 	dsi->state &= ~DSIM_STATE_VIDOUT_AVAILABLE;
 
 	drm_panel_disable(dsi->panel);
-	drm_bridge_disable(dsi->out_bridge);
+	drm_bridge_chain_disable(dsi->out_bridge);
 	exynos_dsi_set_display_enable(dsi, false);
 	drm_panel_unprepare(dsi->panel);
-	drm_bridge_post_disable(dsi->out_bridge);
+	drm_bridge_chain_post_disable(dsi->out_bridge);
 	dsi->state &= ~DSIM_STATE_ENABLED;
 	pm_runtime_put_sync(dsi->dev);
 }
@@ -1741,17 +1740,14 @@
 	dsi->dev = dev;
 	dsi->driver_data = of_device_get_match_data(dev);
 
-	ret = exynos_dsi_parse_dt(dsi);
-	if (ret)
-		return ret;
-
 	dsi->supplies[0].supply = "vddcore";
 	dsi->supplies[1].supply = "vddio";
 	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(dsi->supplies),
 				      dsi->supplies);
 	if (ret) {
-		dev_info(dev, "failed to get regulators: %d\n", ret);
-		return -EPROBE_DEFER;
+		if (ret != -EPROBE_DEFER)
+			dev_info(dev, "failed to get regulators: %d\n", ret);
+		return ret;
 	}
 
 	dsi->clks = devm_kcalloc(dev,
@@ -1764,9 +1760,10 @@
 		dsi->clks[i] = devm_clk_get(dev, clk_names[i]);
 		if (IS_ERR(dsi->clks[i])) {
 			if (strcmp(clk_names[i], "sclk_mipi") == 0) {
-				strcpy(clk_names[i], OLD_SCLK_MIPI_CLK_NAME);
-				i--;
-				continue;
+				dsi->clks[i] = devm_clk_get(dev,
+							OLD_SCLK_MIPI_CLK_NAME);
+				if (!IS_ERR(dsi->clks[i]))
+					continue;
 			}
 
 			dev_info(dev, "failed to get the clock: %s\n",
@@ -1794,20 +1791,34 @@
 		return dsi->irq;
 	}
 
-	irq_set_status_flags(dsi->irq, IRQ_NOAUTOEN);
 	ret = devm_request_threaded_irq(dev, dsi->irq, NULL,
-					exynos_dsi_irq, IRQF_ONESHOT,
+					exynos_dsi_irq,
+					IRQF_ONESHOT | IRQF_NO_AUTOEN,
 					dev_name(dev), dsi);
 	if (ret) {
 		dev_err(dev, "failed to request dsi irq\n");
 		return ret;
 	}
 
+	ret = exynos_dsi_parse_dt(dsi);
+	if (ret)
+		return ret;
+
 	platform_set_drvdata(pdev, &dsi->encoder);
 
 	pm_runtime_enable(dev);
 
-	return component_add(dev, &exynos_dsi_component_ops);
+	ret = component_add(dev, &exynos_dsi_component_ops);
+	if (ret)
+		goto err_disable_runtime;
+
+	return 0;
+
+err_disable_runtime:
+	pm_runtime_disable(dev);
+	of_node_put(dsi->in_bridge_node);
+
+	return ret;
 }
 
 static int exynos_dsi_remove(struct platform_device *pdev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/exynos/exynos_drm_fimc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/exynos/exynos_drm_fimc.c
@@ -97,6 +97,7 @@
 struct fimc_context {
 	struct exynos_drm_ipp ipp;
 	struct drm_device *drm_dev;
+	void		*dma_priv;
 	struct device	*dev;
 	struct exynos_drm_ipp_task	*task;
 	struct exynos_drm_ipp_formats	*formats;
@@ -1133,7 +1134,7 @@
 
 	ctx->drm_dev = drm_dev;
 	ipp->drm_dev = drm_dev;
-	exynos_drm_register_dma(drm_dev, dev);
+	exynos_drm_register_dma(drm_dev, dev, &ctx->dma_priv);
 
 	exynos_drm_ipp_register(dev, ipp, &ipp_funcs,
 			DRM_EXYNOS_IPP_CAP_CROP | DRM_EXYNOS_IPP_CAP_ROTATE |
@@ -1153,7 +1154,7 @@
 	struct exynos_drm_ipp *ipp = &ctx->ipp;
 
 	exynos_drm_ipp_unregister(dev, ipp);
-	exynos_drm_unregister_dma(drm_dev, dev);
+	exynos_drm_unregister_dma(drm_dev, dev, &ctx->dma_priv);
 }
 
 static const struct component_ops fimc_component_ops = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -167,6 +167,7 @@
 struct fimd_context {
 	struct device			*dev;
 	struct drm_device		*drm_dev;
+	void				*dma_priv;
 	struct exynos_drm_crtc		*crtc;
 	struct exynos_drm_plane		planes[WINDOWS_NR];
 	struct exynos_drm_plane_config	configs[WINDOWS_NR];
@@ -636,9 +637,9 @@
 static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win,
 				struct drm_framebuffer *fb, int width)
 {
-	struct exynos_drm_plane plane = ctx->planes[win];
+	struct exynos_drm_plane *plane = &ctx->planes[win];
 	struct exynos_drm_plane_state *state =
-		to_exynos_plane_state(plane.base.state);
+		to_exynos_plane_state(plane->base.state);
 	uint32_t pixel_format = fb->format->format;
 	unsigned int alpha = state->base.alpha;
 	u32 val = WINCONx_ENWIN;
@@ -1090,7 +1091,7 @@
 	if (is_drm_iommu_supported(drm_dev))
 		fimd_clear_channels(ctx->crtc);
 
-	return exynos_drm_register_dma(drm_dev, dev);
+	return exynos_drm_register_dma(drm_dev, dev, &ctx->dma_priv);
 }
 
 static void fimd_unbind(struct device *dev, struct device *master,
@@ -1100,7 +1101,7 @@
 
 	fimd_disable(ctx->crtc);
 
-	exynos_drm_unregister_dma(ctx->drm_dev, ctx->dev);
+	exynos_drm_unregister_dma(ctx->drm_dev, ctx->dev, &ctx->dma_priv);
 
 	if (ctx->encoder)
 		exynos_dpi_remove(ctx->encoder);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/exynos/exynos_drm_g2d.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/exynos/exynos_drm_g2d.c
@@ -232,6 +232,7 @@
 
 struct g2d_data {
 	struct device			*dev;
+	void				*dma_priv;
 	struct clk			*gate_clk;
 	void __iomem			*regs;
 	int				irq;
@@ -1331,7 +1332,7 @@
 	/* Let the runqueue know that there is work to do. */
 	queue_work(g2d->g2d_workq, &g2d->runqueue_work);
 
-	if (runqueue_node->async)
+	if (req->async)
 		goto out;
 
 	wait_for_completion(&runqueue_node->complete);
@@ -1409,7 +1410,7 @@
 		return ret;
 	}
 
-	ret = exynos_drm_register_dma(drm_dev, dev);
+	ret = exynos_drm_register_dma(drm_dev, dev, &g2d->dma_priv);
 	if (ret < 0) {
 		dev_err(dev, "failed to enable iommu.\n");
 		g2d_fini_cmdlist(g2d);
@@ -1434,7 +1435,7 @@
 	priv->g2d_dev = NULL;
 
 	cancel_work_sync(&g2d->runqueue_work);
-	exynos_drm_unregister_dma(g2d->drm_dev, dev);
+	exynos_drm_unregister_dma(g2d->drm_dev, dev, &g2d->dma_priv);
 }
 
 static const struct component_ops g2d_component_ops = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/exynos/exynos_drm_g2d.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/exynos/exynos_drm_g2d.h
@@ -34,11 +34,11 @@
 	return -ENODEV;
 }
 
-int g2d_open(struct drm_device *drm_dev, struct drm_file *file)
+static inline int g2d_open(struct drm_device *drm_dev, struct drm_file *file)
 {
 	return 0;
 }
 
-void g2d_close(struct drm_device *drm_dev, struct drm_file *file)
+static inline void g2d_close(struct drm_device *drm_dev, struct drm_file *file)
 { }
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/exynos/exynos_drm_gsc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/exynos/exynos_drm_gsc.c
@@ -97,6 +97,7 @@
 struct gsc_context {
 	struct exynos_drm_ipp ipp;
 	struct drm_device *drm_dev;
+	void		*dma_priv;
 	struct device	*dev;
 	struct exynos_drm_ipp_task	*task;
 	struct exynos_drm_ipp_formats	*formats;
@@ -1168,8 +1169,8 @@
 	struct exynos_drm_ipp *ipp = &ctx->ipp;
 
 	ctx->drm_dev = drm_dev;
-	ctx->drm_dev = drm_dev;
-	exynos_drm_register_dma(drm_dev, dev);
+	ipp->drm_dev = drm_dev;
+	exynos_drm_register_dma(drm_dev, dev, &ctx->dma_priv);
 
 	exynos_drm_ipp_register(dev, ipp, &ipp_funcs,
 			DRM_EXYNOS_IPP_CAP_CROP | DRM_EXYNOS_IPP_CAP_ROTATE |
@@ -1189,7 +1190,7 @@
 	struct exynos_drm_ipp *ipp = &ctx->ipp;
 
 	exynos_drm_ipp_unregister(dev, ipp);
-	exynos_drm_unregister_dma(drm_dev, dev);
+	exynos_drm_unregister_dma(drm_dev, dev, &ctx->dma_priv);
 }
 
 static const struct component_ops gsc_component_ops = {
@@ -1313,6 +1314,7 @@
 {
 	struct device *dev = &pdev->dev;
 
+	component_del(dev, &gsc_component_ops);
 	pm_runtime_dont_use_autosuspend(dev);
 	pm_runtime_disable(dev);
 
@@ -1342,7 +1344,7 @@
 	for (i = 0; i < ctx->num_clocks; i++) {
 		ret = clk_prepare_enable(ctx->clocks[i]);
 		if (ret) {
-			while (--i > 0)
+			while (--i >= 0)
 				clk_disable_unprepare(ctx->clocks[i]);
 			return ret;
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/exynos/exynos_drm_mic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/exynos/exynos_drm_mic.c
@@ -268,8 +268,10 @@
 		goto unlock;
 
 	ret = pm_runtime_get_sync(mic->dev);
-	if (ret < 0)
+	if (ret < 0) {
+		pm_runtime_put_noidle(mic->dev);
 		goto unlock;
+	}
 
 	mic_set_path(mic, 1);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/exynos/exynos_drm_rotator.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/exynos/exynos_drm_rotator.c
@@ -56,6 +56,7 @@
 struct rot_context {
 	struct exynos_drm_ipp ipp;
 	struct drm_device *drm_dev;
+	void		*dma_priv;
 	struct device	*dev;
 	void __iomem	*regs;
 	struct clk	*clock;
@@ -243,7 +244,7 @@
 
 	rot->drm_dev = drm_dev;
 	ipp->drm_dev = drm_dev;
-	exynos_drm_register_dma(drm_dev, dev);
+	exynos_drm_register_dma(drm_dev, dev, &rot->dma_priv);
 
 	exynos_drm_ipp_register(dev, ipp, &ipp_funcs,
 			   DRM_EXYNOS_IPP_CAP_CROP | DRM_EXYNOS_IPP_CAP_ROTATE,
@@ -261,7 +262,7 @@
 	struct exynos_drm_ipp *ipp = &rot->ipp;
 
 	exynos_drm_ipp_unregister(dev, ipp);
-	exynos_drm_unregister_dma(rot->drm_dev, rot->dev);
+	exynos_drm_unregister_dma(rot->drm_dev, rot->dev, &rot->dma_priv);
 }
 
 static const struct component_ops rotator_component_ops = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/exynos/exynos_drm_scaler.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/exynos/exynos_drm_scaler.c
@@ -39,6 +39,7 @@
 struct scaler_context {
 	struct exynos_drm_ipp		ipp;
 	struct drm_device		*drm_dev;
+	void				*dma_priv;
 	struct device			*dev;
 	void __iomem			*regs;
 	struct clk			*clock[SCALER_MAX_CLK];
@@ -450,7 +451,7 @@
 
 	scaler->drm_dev = drm_dev;
 	ipp->drm_dev = drm_dev;
-	exynos_drm_register_dma(drm_dev, dev);
+	exynos_drm_register_dma(drm_dev, dev, &scaler->dma_priv);
 
 	exynos_drm_ipp_register(dev, ipp, &ipp_funcs,
 			DRM_EXYNOS_IPP_CAP_CROP | DRM_EXYNOS_IPP_CAP_ROTATE |
@@ -470,7 +471,8 @@
 	struct exynos_drm_ipp *ipp = &scaler->ipp;
 
 	exynos_drm_ipp_unregister(dev, ipp);
-	exynos_drm_unregister_dma(scaler->drm_dev, scaler->dev);
+	exynos_drm_unregister_dma(scaler->drm_dev, scaler->dev,
+				  &scaler->dma_priv);
 }
 
 static const struct component_ops scaler_component_ops = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -301,6 +301,7 @@
 	struct vidi_context *ctx = ctx_from_connector(connector);
 	struct edid *edid;
 	int edid_len;
+	int count;
 
 	/*
 	 * the edid data comes from user side and it would be set
@@ -308,19 +309,23 @@
 	 */
 	if (!ctx->raw_edid) {
 		DRM_DEV_DEBUG_KMS(ctx->dev, "raw_edid is null.\n");
-		return -EFAULT;
+		return 0;
 	}
 
 	edid_len = (1 + ctx->raw_edid->extensions) * EDID_LENGTH;
 	edid = kmemdup(ctx->raw_edid, edid_len, GFP_KERNEL);
 	if (!edid) {
 		DRM_DEV_DEBUG_KMS(ctx->dev, "failed to allocate edid\n");
-		return -ENOMEM;
+		return 0;
 	}
 
 	drm_connector_update_edid_property(connector, edid);
 
-	return drm_add_edid_modes(connector, edid);
+	count = drm_add_edid_modes(connector, edid);
+
+	kfree(edid);
+
+	return count;
 }
 
 static const struct drm_connector_helper_funcs vidi_connector_helper_funcs = {
@@ -483,8 +488,6 @@
 	if (ctx->raw_edid != (struct edid *)fake_edid_info) {
 		kfree(ctx->raw_edid);
 		ctx->raw_edid = NULL;
-
-		return -EINVAL;
 	}
 
 	component_del(&pdev->dev, &vidi_component_ops);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -852,6 +852,10 @@
 
 static void hdmi_connector_destroy(struct drm_connector *connector)
 {
+	struct hdmi_context *hdata = connector_to_hdmi(connector);
+
+	cec_notifier_conn_unregister(hdata->notifier);
+
 	drm_connector_unregister(connector);
 	drm_connector_cleanup(connector);
 }
@@ -872,11 +876,11 @@
 	int ret;
 
 	if (!hdata->ddc_adpt)
-		return -ENODEV;
+		goto no_edid;
 
 	edid = drm_get_edid(connector, hdata->ddc_adpt);
 	if (!edid)
-		return -ENODEV;
+		goto no_edid;
 
 	hdata->dvi_mode = !drm_detect_hdmi_monitor(edid);
 	DRM_DEV_DEBUG_KMS(hdata->dev, "%s : width[%d] x height[%d]\n",
@@ -891,6 +895,9 @@
 	kfree(edid);
 
 	return ret;
+
+no_edid:
+	return drm_add_modes_noedid(connector, 640, 480);
 }
 
 static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock)
@@ -935,6 +942,7 @@
 {
 	struct hdmi_context *hdata = encoder_to_hdmi(encoder);
 	struct drm_connector *connector = &hdata->connector;
+	struct cec_connector_info conn_info;
 	int ret;
 
 	connector->interlace_allowed = true;
@@ -957,6 +965,15 @@
 			DRM_DEV_ERROR(hdata->dev, "Failed to attach bridge\n");
 	}
 
+	cec_fill_conn_info_from_drm(&conn_info, connector);
+
+	hdata->notifier = cec_notifier_conn_register(hdata->dev, NULL,
+						     &conn_info);
+	if (!hdata->notifier) {
+		ret = -ENOMEM;
+		DRM_DEV_ERROR(hdata->dev, "Failed to allocate CEC notifier\n");
+	}
+
 	return ret;
 }
 
@@ -1528,8 +1545,8 @@
 		 */
 		mutex_unlock(&hdata->mutex);
 		cancel_delayed_work(&hdata->hotplug_work);
-		cec_notifier_set_phys_addr(hdata->notifier,
-					   CEC_PHYS_ADDR_INVALID);
+		if (hdata->notifier)
+			cec_notifier_phys_addr_invalidate(hdata->notifier);
 		return;
 	}
 
@@ -1788,18 +1805,10 @@
 
 	hdata->reg_hdmi_en = devm_regulator_get_optional(dev, "hdmi-en");
 
-	if (PTR_ERR(hdata->reg_hdmi_en) != -ENODEV) {
+	if (PTR_ERR(hdata->reg_hdmi_en) != -ENODEV)
 		if (IS_ERR(hdata->reg_hdmi_en))
 			return PTR_ERR(hdata->reg_hdmi_en);
 
-		ret = regulator_enable(hdata->reg_hdmi_en);
-		if (ret) {
-			DRM_DEV_ERROR(dev,
-				      "failed to enable hdmi-en regulator\n");
-			return ret;
-		}
-	}
-
 	return hdmi_bridge_init(hdata);
 }
 
@@ -1844,6 +1853,8 @@
 		return ret;
 
 	crtc = exynos_drm_crtc_get_by_type(drm_dev, EXYNOS_DISPLAY_TYPE_HDMI);
+	if (IS_ERR(crtc))
+		return PTR_ERR(crtc);
 	crtc->pipe_clk = &hdata->phy_clk;
 
 	ret = hdmi_create_connector(encoder);
@@ -2006,10 +2017,13 @@
 		}
 	}
 
-	hdata->notifier = cec_notifier_get(&pdev->dev);
-	if (hdata->notifier == NULL) {
-		ret = -ENOMEM;
-		goto err_hdmiphy;
+	if (!IS_ERR(hdata->reg_hdmi_en)) {
+		ret = regulator_enable(hdata->reg_hdmi_en);
+		if (ret) {
+			DRM_DEV_ERROR(dev,
+			      "failed to enable hdmi-en regulator\n");
+			goto err_hdmiphy;
+		}
 	}
 
 	pm_runtime_enable(dev);
@@ -2023,7 +2037,7 @@
 
 	ret = hdmi_register_audio_device(hdata);
 	if (ret)
-		goto err_notifier_put;
+		goto err_rpm_disable;
 
 	ret = component_add(&pdev->dev, &hdmi_component_ops);
 	if (ret)
@@ -2034,10 +2048,10 @@
 err_unregister_audio:
 	platform_device_unregister(hdata->audio.pdev);
 
-err_notifier_put:
-	cec_notifier_put(hdata->notifier);
+err_rpm_disable:
 	pm_runtime_disable(dev);
-
+	if (!IS_ERR(hdata->reg_hdmi_en))
+		regulator_disable(hdata->reg_hdmi_en);
 err_hdmiphy:
 	if (hdata->hdmiphy_port)
 		put_device(&hdata->hdmiphy_port->dev);
@@ -2054,12 +2068,10 @@
 	struct hdmi_context *hdata = platform_get_drvdata(pdev);
 
 	cancel_delayed_work_sync(&hdata->hotplug_work);
-	cec_notifier_set_phys_addr(hdata->notifier, CEC_PHYS_ADDR_INVALID);
 
 	component_del(&pdev->dev, &hdmi_component_ops);
 	platform_device_unregister(hdata->audio.pdev);
 
-	cec_notifier_put(hdata->notifier);
 	pm_runtime_disable(&pdev->dev);
 
 	if (!IS_ERR(hdata->reg_hdmi_en))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/exynos/exynos_mixer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -94,6 +94,7 @@
 	struct platform_device *pdev;
 	struct device		*dev;
 	struct drm_device	*drm_dev;
+	void			*dma_priv;
 	struct exynos_drm_crtc	*crtc;
 	struct exynos_drm_plane	planes[MIXER_WIN_NR];
 	unsigned long		flags;
@@ -894,12 +895,14 @@
 		}
 	}
 
-	return exynos_drm_register_dma(drm_dev, mixer_ctx->dev);
+	return exynos_drm_register_dma(drm_dev, mixer_ctx->dev,
+				       &mixer_ctx->dma_priv);
 }
 
 static void mixer_ctx_remove(struct mixer_context *mixer_ctx)
 {
-	exynos_drm_unregister_dma(mixer_ctx->drm_dev, mixer_ctx->dev);
+	exynos_drm_unregister_dma(mixer_ctx->drm_dev, mixer_ctx->dev,
+				  &mixer_ctx->dma_priv);
 }
 
 static int mixer_enable_vblank(struct exynos_drm_crtc *crtc)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
@@ -70,8 +70,9 @@
 	return drm_panel_get_modes(fsl_connector->panel);
 }
 
-static int fsl_dcu_drm_connector_mode_valid(struct drm_connector *connector,
-					    struct drm_display_mode *mode)
+static enum drm_mode_status
+fsl_dcu_drm_connector_mode_valid(struct drm_connector *connector,
+				 struct drm_display_mode *mode)
 {
 	if (mode->hdisplay & 0xf)
 		return MODE_ERROR;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/gma500/cdv_intel_display.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/gma500/cdv_intel_display.c
@@ -405,6 +405,8 @@
 	struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
 	struct gma_clock_t clock;
 
+	memset(&clock, 0, sizeof(clock));
+
 	switch (refclk) {
 	case 27000:
 		if (target < 200000) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/gma500/cdv_intel_dp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/gma500/cdv_intel_dp.c
@@ -2120,12 +2120,12 @@
 					       intel_dp->dpcd,
 					       sizeof(intel_dp->dpcd));
 		cdv_intel_edp_panel_vdd_off(gma_encoder);
-		if (ret == 0) {
+		if (ret <= 0) {
 			/* if this fails, presume the device is a ghost */
 			DRM_INFO("failed to retrieve link info, disabling eDP\n");
 			cdv_intel_dp_encoder_destroy(encoder);
 			cdv_intel_dp_destroy(connector);
-			goto err_priv;
+			goto err_connector;
 		} else {
         		DRM_DEBUG_KMS("DPCD: Rev=%x LN_Rate=%x LN_CNT=%x LN_DOWNSP=%x\n",
 				intel_dp->dpcd[0], intel_dp->dpcd[1], 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/gma500/cdv_intel_lvds.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/gma500/cdv_intel_lvds.c
@@ -391,6 +391,9 @@
 	if (mode_dev->panel_fixed_mode != NULL) {
 		struct drm_display_mode *mode =
 		    drm_mode_duplicate(dev, mode_dev->panel_fixed_mode);
+		if (!mode)
+			return 0;
+
 		drm_mode_probed_add(connector, mode);
 		return 1;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/gma500/framebuffer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/gma500/framebuffer.c
@@ -462,6 +462,7 @@
 		container_of(helper, struct psb_fbdev, psb_fb_helper);
 	struct drm_device *dev = psb_fbdev->psb_fb_helper.dev;
 	struct drm_psb_private *dev_priv = dev->dev_private;
+	unsigned int fb_size;
 	int bytespp;
 
 	bytespp = sizes->surface_bpp / 8;
@@ -471,8 +472,11 @@
 	/* If the mode will not fit in 32bit then switch to 16bit to get
 	   a console on full resolution. The X mode setting server will
 	   allocate its own 32bit GEM framebuffer */
-	if (ALIGN(sizes->fb_width * bytespp, 64) * sizes->fb_height >
-	                dev_priv->vram_stolen_size) {
+	fb_size = ALIGN(sizes->surface_width * bytespp, 64) *
+		  sizes->surface_height;
+	fb_size = ALIGN(fb_size, PAGE_SIZE);
+
+	if (fb_size > dev_priv->vram_stolen_size) {
                 sizes->surface_bpp = 16;
                 sizes->surface_depth = 16;
         }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/gma500/mid_bios.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/gma500/mid_bios.c
@@ -277,6 +277,11 @@
 					    0, PCI_DEVFN(2, 0));
 	int ret = -1;
 
+	if (pci_gfx_root == NULL) {
+		WARN_ON(1);
+		return;
+	}
+
 	/* Get the address of the platform config vbt */
 	pci_read_config_dword(pci_gfx_root, 0xFC, &addr);
 	pci_dev_put(pci_gfx_root);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/gma500/oaktrail_crtc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/gma500/oaktrail_crtc.c
@@ -129,6 +129,7 @@
 	s32 freq_error, min_error = 100000;
 
 	memset(best_clock, 0, sizeof(*best_clock));
+	memset(&clock, 0, sizeof(clock));
 
 	for (clock.m = limit->m.min; clock.m <= limit->m.max; clock.m++) {
 		for (clock.n = limit->n.min; clock.n <= limit->n.max;
@@ -185,6 +186,7 @@
 	int err = target;
 
 	memset(best_clock, 0, sizeof(*best_clock));
+	memset(&clock, 0, sizeof(clock));
 
 	for (clock.m = limit->m.min; clock.m <= limit->m.max; clock.m++) {
 		for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c
@@ -279,11 +279,8 @@
 	hdmi_dev = pci_get_drvdata(dev);
 
 	i2c_dev = kzalloc(sizeof(struct hdmi_i2c_dev), GFP_KERNEL);
-	if (i2c_dev == NULL) {
-		DRM_ERROR("Can't allocate interface\n");
-		ret = -ENOMEM;
-		goto exit;
-	}
+	if (!i2c_dev)
+		return -ENOMEM;
 
 	i2c_dev->adap = &oaktrail_hdmi_i2c_adapter;
 	i2c_dev->status = I2C_STAT_INIT;
@@ -300,16 +297,23 @@
 			  oaktrail_hdmi_i2c_adapter.name, hdmi_dev);
 	if (ret) {
 		DRM_ERROR("Failed to request IRQ for I2C controller\n");
-		goto err;
+		goto free_dev;
 	}
 
 	/* Adapter registration */
 	ret = i2c_add_numbered_adapter(&oaktrail_hdmi_i2c_adapter);
-	return ret;
+	if (ret) {
+		DRM_ERROR("Failed to add I2C adapter\n");
+		goto free_irq;
+	}
+
+	return 0;
 
-err:
+free_irq:
+	free_irq(dev->irq, hdmi_dev);
+free_dev:
 	kfree(i2c_dev);
-exit:
+
 	return ret;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/gma500/psb_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/gma500/psb_drv.c
@@ -313,6 +313,8 @@
 	if (ret)
 		goto out_err;
 
+	ret = -ENOMEM;
+
 	dev_priv->mmu = psb_mmu_driver_init(dev, 1, 0, 0);
 	if (!dev_priv->mmu)
 		goto out_err;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/gma500/psb_intel_display.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/gma500/psb_intel_display.c
@@ -532,14 +532,15 @@
 
 struct drm_crtc *psb_intel_get_crtc_from_pipe(struct drm_device *dev, int pipe)
 {
-	struct drm_crtc *crtc = NULL;
+	struct drm_crtc *crtc;
 
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 		struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
+
 		if (gma_crtc->pipe == pipe)
-			break;
+			return crtc;
 	}
-	return crtc;
+	return NULL;
 }
 
 int gma_connector_clones(struct drm_device *dev, int type_mask)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/gma500/psb_intel_lvds.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/gma500/psb_intel_lvds.c
@@ -506,6 +506,9 @@
 	if (mode_dev->panel_fixed_mode != NULL) {
 		struct drm_display_mode *mode =
 		    drm_mode_duplicate(dev, mode_dev->panel_fixed_mode);
+		if (!mode)
+			return 0;
+
 		drm_mode_probed_add(connector, mode);
 		return 1;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/gma500/psb_irq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/gma500/psb_irq.c
@@ -337,6 +337,7 @@
 {
 	struct drm_psb_private *dev_priv = dev->dev_private;
 	unsigned long irqflags;
+	unsigned int i;
 
 	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
 
@@ -349,20 +350,12 @@
 	PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
 	PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
 
-	if (dev->vblank[0].enabled)
-		psb_enable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE);
-	else
-		psb_disable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE);
-
-	if (dev->vblank[1].enabled)
-		psb_enable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE);
-	else
-		psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE);
-
-	if (dev->vblank[2].enabled)
-		psb_enable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE);
-	else
-		psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE);
+	for (i = 0; i < dev->num_crtcs; ++i) {
+		if (dev->vblank[i].enabled)
+			psb_enable_pipestat(dev_priv, i, PIPE_VBLANK_INTERRUPT_ENABLE);
+		else
+			psb_disable_pipestat(dev_priv, i, PIPE_VBLANK_INTERRUPT_ENABLE);
+	}
 
 	if (dev_priv->ops->hotplug_enable)
 		dev_priv->ops->hotplug_enable(dev, true);
@@ -375,6 +368,7 @@
 {
 	struct drm_psb_private *dev_priv = dev->dev_private;
 	unsigned long irqflags;
+	unsigned int i;
 
 	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
 
@@ -383,14 +377,10 @@
 
 	PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
 
-	if (dev->vblank[0].enabled)
-		psb_disable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE);
-
-	if (dev->vblank[1].enabled)
-		psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE);
-
-	if (dev->vblank[2].enabled)
-		psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE);
+	for (i = 0; i < dev->num_crtcs; ++i) {
+		if (dev->vblank[i].enabled)
+			psb_disable_pipestat(dev_priv, i, PIPE_VBLANK_INTERRUPT_ENABLE);
+	}
 
 	dev_priv->vdc_irq_mask &= _PSB_IRQ_SGX_FLAG |
 				  _PSB_IRQ_MSVDX_FLAG |
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
@@ -376,7 +376,6 @@
 
 	drm_dev_unregister(dev);
 	hibmc_unload(dev);
-	drm_dev_put(dev);
 }
 
 static struct pci_device_id hibmc_pci_table[] = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h
@@ -83,7 +83,6 @@
 #define VSIZE_OFST			20
 #define LDI_INT_EN			0x741C
 #define FRAME_END_INT_EN_OFST		1
-#define UNDERFLOW_INT_EN_OFST		2
 #define LDI_CTRL			0x7420
 #define BPP_OFST			3
 #define DATA_GATE_EN			BIT(2)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
@@ -46,7 +46,6 @@
 	struct clk *media_noc_clk;
 	struct clk *ade_pix_clk;
 	struct reset_control *reset;
-	struct work_struct display_reset_wq;
 	bool power_on;
 	int irq;
 
@@ -136,7 +135,6 @@
 	 */
 	ade_update_bits(base + ADE_CTRL, FRM_END_START_OFST,
 			FRM_END_START_MASK, REG_EFFECTIVE_IN_ADEEN_FRMEND);
-	ade_update_bits(base + LDI_INT_EN, UNDERFLOW_INT_EN_OFST, MASK(1), 1);
 }
 
 static bool ade_crtc_mode_fixup(struct drm_crtc *crtc,
@@ -304,17 +302,6 @@
 			MASK(1), 0);
 }
 
-static void drm_underflow_wq(struct work_struct *work)
-{
-	struct ade_hw_ctx *ctx = container_of(work, struct ade_hw_ctx,
-					      display_reset_wq);
-	struct drm_device *drm_dev = ctx->crtc->dev;
-	struct drm_atomic_state *state;
-
-	state = drm_atomic_helper_suspend(drm_dev);
-	drm_atomic_helper_resume(drm_dev, state);
-}
-
 static irqreturn_t ade_irq_handler(int irq, void *data)
 {
 	struct ade_hw_ctx *ctx = data;
@@ -331,12 +318,6 @@
 				MASK(1), 1);
 		drm_crtc_handle_vblank(crtc);
 	}
-	if (status & BIT(UNDERFLOW_INT_EN_OFST)) {
-		ade_update_bits(base + LDI_INT_CLR, UNDERFLOW_INT_EN_OFST,
-				MASK(1), 1);
-		DRM_ERROR("LDI underflow!");
-		schedule_work(&ctx->display_reset_wq);
-	}
 
 	return IRQ_HANDLED;
 }
@@ -919,7 +900,6 @@
 	if (ret)
 		return ERR_PTR(-EIO);
 
-	INIT_WORK(&ctx->display_reset_wq, drm_underflow_wq);
 	ctx->crtc = crtc;
 
 	return ctx;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i2c/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i2c/Kconfig
@@ -2,6 +2,13 @@
 menu "I2C encoder or helper chips"
      depends on DRM && DRM_KMS_HELPER && I2C
 
+config DRM_I2C_ADV7511_LEGACY
+	tristate "AV7511 encoder"
+	depends on OF && !DRM_I2C_ADV7511
+	select REGMAP_I2C
+	help
+	  Support for the Analog Device ADV7511(W) and ADV7513 HDMI encoders.
+
 config DRM_I2C_CH7006
 	tristate "Chrontel ch7006 TV encoder"
 	default m if DRM_NOUVEAU
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i2c/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i2c/Makefile
@@ -1,4 +1,9 @@
 # SPDX-License-Identifier: GPL-2.0
+
+ccflags-y := -Iinclude/drm
+
+obj-$(CONFIG_DRM_I2C_ADV7511_LEGACY) += adv7511.o
+
 ch7006-y := ch7006_drv.o ch7006_mode.o
 obj-$(CONFIG_DRM_I2C_CH7006) += ch7006.o
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i2c/adv7511.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i2c/adv7511.c
@@ -0,0 +1,1025 @@
+/*
+ * Analog Devices ADV7511 HDMI transmitter driver
+ *
+ * Copyright 2012 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_encoder_slave.h>
+#include <drm/drm_probe_helper.h>
+
+#include "adv7511.h"
+
+struct adv7511 {
+	struct i2c_client *i2c_main;
+	struct i2c_client *i2c_edid;
+
+	struct regmap *regmap;
+	struct regmap *packet_memory_regmap;
+	enum drm_connector_status status;
+	bool powered;
+
+	unsigned int f_tmds;
+
+	unsigned int current_edid_segment;
+	uint8_t edid_buf[256];
+	bool edid_read;
+
+	wait_queue_head_t wq;
+	struct drm_encoder *encoder;
+
+	bool embedded_sync;
+	enum adv7511_sync_polarity vsync_polarity;
+	enum adv7511_sync_polarity hsync_polarity;
+	bool rgb;
+
+	struct edid *edid;
+
+	struct gpio_desc *gpio_pd;
+};
+
+static struct adv7511 *encoder_to_adv7511(struct drm_encoder *encoder)
+{
+	return to_encoder_slave(encoder)->slave_priv;
+}
+
+/* ADI recommended values for proper operation. */
+static const struct reg_sequence adv7511_fixed_registers[] = {
+	{ 0x98, 0x03 },
+	{ 0x9a, 0xe0 },
+	{ 0x9c, 0x30 },
+	{ 0x9d, 0x61 },
+	{ 0xa2, 0xa4 },
+	{ 0xa3, 0xa4 },
+	{ 0xe0, 0xd0 },
+	{ 0xf9, 0x00 },
+	{ 0x55, 0x02 },
+};
+
+/* -----------------------------------------------------------------------------
+ * Register access
+ */
+
+static const uint8_t adv7511_register_defaults[] = {
+	0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00 */
+	0x00, 0x00, 0x01, 0x0e, 0xbc, 0x18, 0x01, 0x13,
+	0x25, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 10 */
+	0x46, 0x62, 0x04, 0xa8, 0x00, 0x00, 0x1c, 0x84,
+	0x1c, 0xbf, 0x04, 0xa8, 0x1e, 0x70, 0x02, 0x1e, /* 20 */
+	0x00, 0x00, 0x04, 0xa8, 0x08, 0x12, 0x1b, 0xac,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 30 */
+	0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb0,
+	0x00, 0x50, 0x90, 0x7e, 0x79, 0x70, 0x00, 0x00, /* 40 */
+	0x00, 0xa8, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x02, 0x0d, 0x00, 0x00, 0x00, 0x00, /* 50 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 60 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x01, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 70 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 80 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, /* 90 */
+	0x0b, 0x02, 0x00, 0x18, 0x5a, 0x60, 0x00, 0x00,
+	0x00, 0x00, 0x80, 0x80, 0x08, 0x04, 0x00, 0x00, /* a0 */
+	0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x14,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b0 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c0 */
+	0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x01, 0x04,
+	0x30, 0xff, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, /* d0 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01,
+	0x80, 0x75, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, /* e0 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x11, 0x00, /* f0 */
+	0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static bool adv7511_register_volatile(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case ADV7511_REG_CHIP_REVISION:
+	case ADV7511_REG_SPDIF_FREQ:
+	case ADV7511_REG_CTS_AUTOMATIC1:
+	case ADV7511_REG_CTS_AUTOMATIC2:
+	case ADV7511_REG_VIC_DETECTED:
+	case ADV7511_REG_VIC_SEND:
+	case ADV7511_REG_AUX_VIC_DETECTED:
+	case ADV7511_REG_STATUS:
+	case ADV7511_REG_GC(1):
+	case ADV7511_REG_INT(0):
+	case ADV7511_REG_INT(1):
+	case ADV7511_REG_PLL_STATUS:
+	case ADV7511_REG_AN(0):
+	case ADV7511_REG_AN(1):
+	case ADV7511_REG_AN(2):
+	case ADV7511_REG_AN(3):
+	case ADV7511_REG_AN(4):
+	case ADV7511_REG_AN(5):
+	case ADV7511_REG_AN(6):
+	case ADV7511_REG_AN(7):
+	case ADV7511_REG_HDCP_STATUS:
+	case ADV7511_REG_BCAPS:
+	case ADV7511_REG_BKSV(0):
+	case ADV7511_REG_BKSV(1):
+	case ADV7511_REG_BKSV(2):
+	case ADV7511_REG_BKSV(3):
+	case ADV7511_REG_BKSV(4):
+	case ADV7511_REG_DDC_STATUS:
+	case ADV7511_REG_EDID_READ_CTRL:
+	case ADV7511_REG_BSTATUS(0):
+	case ADV7511_REG_BSTATUS(1):
+	case ADV7511_REG_CHIP_ID_HIGH:
+	case ADV7511_REG_CHIP_ID_LOW:
+		return true;
+	}
+
+	return false;
+}
+
+static const struct regmap_config adv7511_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = 0xff,
+	.cache_type = REGCACHE_RBTREE,
+	.reg_defaults_raw = adv7511_register_defaults,
+	.num_reg_defaults_raw = ARRAY_SIZE(adv7511_register_defaults),
+
+	.volatile_reg = adv7511_register_volatile,
+};
+
+/* -----------------------------------------------------------------------------
+ * Hardware configuration
+ */
+
+static void adv7511_set_colormap(struct adv7511 *adv7511, bool enable,
+				 const uint16_t *coeff,
+				 unsigned int scaling_factor)
+{
+	unsigned int i;
+
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_CSC_UPPER(1),
+			   ADV7511_CSC_UPDATE_MODE, ADV7511_CSC_UPDATE_MODE);
+
+	if (enable) {
+		for (i = 0; i < 12; ++i) {
+			regmap_update_bits(adv7511->regmap,
+					   ADV7511_REG_CSC_UPPER(i),
+					   0x1f, coeff[i] >> 8);
+			regmap_write(adv7511->regmap,
+				     ADV7511_REG_CSC_LOWER(i),
+				     coeff[i] & 0xff);
+		}
+	}
+
+	if (enable)
+		regmap_update_bits(adv7511->regmap, ADV7511_REG_CSC_UPPER(0),
+				   0xe0, 0x80 | (scaling_factor << 5));
+	else
+		regmap_update_bits(adv7511->regmap, ADV7511_REG_CSC_UPPER(0),
+				   0x80, 0x00);
+
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_CSC_UPPER(1),
+			   ADV7511_CSC_UPDATE_MODE, 0);
+}
+
+static int adv7511_packet_enable(struct adv7511 *adv7511, unsigned int packet)
+{
+	if (packet & 0xff)
+		regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE0,
+				   packet, 0xff);
+
+	if (packet & 0xff00) {
+		packet >>= 8;
+		regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE1,
+				   packet, 0xff);
+	}
+
+	return 0;
+}
+
+static int adv7511_packet_disable(struct adv7511 *adv7511, unsigned int packet)
+{
+	if (packet & 0xff)
+		regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE0,
+				   packet, 0x00);
+
+	if (packet & 0xff00) {
+		packet >>= 8;
+		regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE1,
+				   packet, 0x00);
+	}
+
+	return 0;
+}
+
+/* Coefficients for adv7511 color space conversion */
+static const uint16_t adv7511_csc_ycbcr_to_rgb[] = {
+	0x0734, 0x04ad, 0x0000, 0x1c1b,
+	0x1ddc, 0x04ad, 0x1f24, 0x0135,
+	0x0000, 0x04ad, 0x087c, 0x1b77,
+};
+
+static void adv7511_set_config_csc(struct adv7511 *adv7511,
+				   struct drm_connector *connector,
+				   bool rgb)
+{
+	struct adv7511_video_config config;
+	bool output_format_422, output_format_ycbcr;
+	unsigned int mode;
+	uint8_t infoframe[17];
+
+	if (adv7511->edid)
+		config.hdmi_mode = drm_detect_hdmi_monitor(adv7511->edid);
+	else
+		config.hdmi_mode = false;
+
+	hdmi_avi_infoframe_init(&config.avi_infoframe);
+
+	config.avi_infoframe.scan_mode = HDMI_SCAN_MODE_UNDERSCAN;
+
+	if (rgb) {
+		config.csc_enable = false;
+		config.avi_infoframe.colorspace = HDMI_COLORSPACE_RGB;
+	} else {
+		config.csc_scaling_factor = ADV7511_CSC_SCALING_4;
+		config.csc_coefficents = adv7511_csc_ycbcr_to_rgb;
+
+		if ((connector->display_info.color_formats &
+		     DRM_COLOR_FORMAT_YCRCB422) &&
+		    config.hdmi_mode) {
+			config.csc_enable = false;
+			config.avi_infoframe.colorspace =
+				HDMI_COLORSPACE_YUV422;
+		} else {
+			config.csc_enable = true;
+			config.avi_infoframe.colorspace = HDMI_COLORSPACE_RGB;
+		}
+	}
+
+	if (config.hdmi_mode) {
+		mode = ADV7511_HDMI_CFG_MODE_HDMI;
+
+		switch (config.avi_infoframe.colorspace) {
+		case HDMI_COLORSPACE_YUV444:
+			output_format_422 = false;
+			output_format_ycbcr = true;
+			break;
+		case HDMI_COLORSPACE_YUV422:
+			output_format_422 = true;
+			output_format_ycbcr = true;
+			break;
+		default:
+			output_format_422 = false;
+			output_format_ycbcr = false;
+			break;
+		}
+	} else {
+		mode = ADV7511_HDMI_CFG_MODE_DVI;
+		output_format_422 = false;
+		output_format_ycbcr = false;
+	}
+
+	adv7511_packet_disable(adv7511, ADV7511_PACKET_ENABLE_AVI_INFOFRAME);
+
+	adv7511_set_colormap(adv7511, config.csc_enable,
+			     config.csc_coefficents,
+			     config.csc_scaling_factor);
+
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_VIDEO_INPUT_CFG1, 0x81,
+			   (output_format_422 << 7) | output_format_ycbcr);
+
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_HDCP_HDMI_CFG,
+			   ADV7511_HDMI_CFG_MODE_MASK, mode);
+
+	hdmi_avi_infoframe_pack(&config.avi_infoframe, infoframe,
+				sizeof(infoframe));
+
+	/* The AVI infoframe id is not configurable */
+	regmap_bulk_write(adv7511->regmap, ADV7511_REG_AVI_INFOFRAME_VERSION,
+			  infoframe + 1, sizeof(infoframe) - 1);
+
+	adv7511_packet_enable(adv7511, ADV7511_PACKET_ENABLE_AVI_INFOFRAME);
+}
+
+static void adv7511_set_link_config(struct adv7511 *adv7511,
+				    const struct adv7511_link_config *config)
+{
+	/*
+	 * The input style values documented in the datasheet don't match the
+	 * hardware register field values :-(
+	 */
+	static const unsigned int input_styles[4] = { 0, 2, 1, 3 };
+
+	unsigned int clock_delay;
+	unsigned int color_depth;
+	unsigned int input_id;
+
+	clock_delay = (config->clock_delay + 1200) / 400;
+	color_depth = config->input_color_depth == 8 ? 3
+		    : (config->input_color_depth == 10 ? 1 : 2);
+
+	/* TODO Support input ID 6 */
+	if (config->input_colorspace != HDMI_COLORSPACE_YUV422)
+		input_id = config->input_clock == ADV7511_INPUT_CLOCK_DDR
+			 ? 5 : 0;
+	else if (config->input_clock == ADV7511_INPUT_CLOCK_DDR)
+		input_id = config->embedded_sync ? 8 : 7;
+	else if (config->input_clock == ADV7511_INPUT_CLOCK_2X)
+		input_id = config->embedded_sync ? 4 : 3;
+	else
+		input_id = config->embedded_sync ? 2 : 1;
+
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_I2C_FREQ_ID_CFG, 0xf,
+			   input_id);
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_VIDEO_INPUT_CFG1, 0x7e,
+			   (color_depth << 4) |
+			   (input_styles[config->input_style] << 2));
+	regmap_write(adv7511->regmap, ADV7511_REG_VIDEO_INPUT_CFG2,
+		     config->input_justification << 3);
+	regmap_write(adv7511->regmap, ADV7511_REG_TIMING_GEN_SEQ,
+		     config->sync_pulse << 2);
+
+	regmap_write(adv7511->regmap, 0xba, clock_delay << 5);
+
+	adv7511->embedded_sync = config->embedded_sync;
+	adv7511->hsync_polarity = config->hsync_polarity;
+	adv7511->vsync_polarity = config->vsync_polarity;
+	adv7511->rgb = config->input_colorspace == HDMI_COLORSPACE_RGB;
+}
+
+static void adv7511_power_on(struct adv7511 *adv7511)
+{
+	adv7511->current_edid_segment = -1;
+
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER,
+			   ADV7511_POWER_POWER_DOWN, 0);
+	if (adv7511->i2c_main->irq) {
+		/*
+		 * Documentation says the INT_ENABLE registers are reset in
+		 * POWER_DOWN mode. My 7511w preserved the bits, however.
+		 * Still, let's be safe and stick to the documentation.
+		 */
+		regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(0),
+			     ADV7511_INT0_EDID_READY);
+		regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(1),
+			     ADV7511_INT1_DDC_ERROR);
+	}
+
+	/*
+	 * Per spec it is allowed to pulse the HPD signal to indicate that the
+	 * EDID information has changed. Some monitors do this when they wakeup
+	 * from standby or are enabled. When the HPD goes low the adv7511 is
+	 * reset and the outputs are disabled which might cause the monitor to
+	 * go to standby again. To avoid this we ignore the HPD pin for the
+	 * first few seconds after enabling the output.
+	 */
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2,
+			   ADV7511_REG_POWER2_HPD_SRC_MASK,
+			   ADV7511_REG_POWER2_HPD_SRC_NONE);
+
+	/*
+	 * Most of the registers are reset during power down or when HPD is low.
+	 */
+	regcache_sync(adv7511->regmap);
+
+	adv7511->powered = true;
+}
+
+static void adv7511_power_off(struct adv7511 *adv7511)
+{
+	/* TODO: setup additional power down modes */
+	regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER,
+			   ADV7511_POWER_POWER_DOWN,
+			   ADV7511_POWER_POWER_DOWN);
+	regcache_mark_dirty(adv7511->regmap);
+
+	adv7511->powered = false;
+}
+
+/* -----------------------------------------------------------------------------
+ * Interrupt and hotplug detection
+ */
+
+static bool adv7511_hpd(struct adv7511 *adv7511)
+{
+	unsigned int irq0;
+	int ret;
+
+	ret = regmap_read(adv7511->regmap, ADV7511_REG_INT(0), &irq0);
+	if (ret < 0)
+		return false;
+
+	if (irq0 & ADV7511_INT0_HPD) {
+		regmap_write(adv7511->regmap, ADV7511_REG_INT(0),
+			     ADV7511_INT0_HPD);
+		return true;
+	}
+
+	return false;
+}
+
+static int adv7511_irq_process(struct adv7511 *adv7511)
+{
+	unsigned int irq0, irq1;
+	int ret;
+
+	ret = regmap_read(adv7511->regmap, ADV7511_REG_INT(0), &irq0);
+	if (ret < 0)
+		return ret;
+
+	ret = regmap_read(adv7511->regmap, ADV7511_REG_INT(1), &irq1);
+	if (ret < 0)
+		return ret;
+
+	regmap_write(adv7511->regmap, ADV7511_REG_INT(0), irq0);
+	regmap_write(adv7511->regmap, ADV7511_REG_INT(1), irq1);
+
+	if (irq0 & ADV7511_INT0_HPD && adv7511->encoder)
+		drm_helper_hpd_irq_event(adv7511->encoder->dev);
+
+	if (irq0 & ADV7511_INT0_EDID_READY || irq1 & ADV7511_INT1_DDC_ERROR) {
+		adv7511->edid_read = true;
+
+		if (adv7511->i2c_main->irq)
+			wake_up_all(&adv7511->wq);
+	}
+
+	return 0;
+}
+
+static irqreturn_t adv7511_irq_handler(int irq, void *devid)
+{
+	struct adv7511 *adv7511 = devid;
+	int ret;
+
+	ret = adv7511_irq_process(adv7511);
+	return ret < 0 ? IRQ_NONE : IRQ_HANDLED;
+}
+
+/* -----------------------------------------------------------------------------
+ * EDID retrieval
+ */
+
+static int adv7511_wait_for_edid(struct adv7511 *adv7511, int timeout)
+{
+	int ret;
+
+	if (adv7511->i2c_main->irq) {
+		ret = wait_event_interruptible_timeout(adv7511->wq,
+				adv7511->edid_read, msecs_to_jiffies(timeout));
+	} else {
+		for (; timeout > 0; timeout -= 25) {
+			ret = adv7511_irq_process(adv7511);
+			if (ret < 0)
+				break;
+
+			if (adv7511->edid_read)
+				break;
+
+			msleep(25);
+		}
+	}
+
+	return adv7511->edid_read ? 0 : -EIO;
+}
+
+static int adv7511_get_edid_block(void *data, u8 *buf, unsigned int block,
+				  size_t len)
+{
+	struct adv7511 *adv7511 = data;
+	struct i2c_msg xfer[2];
+	uint8_t offset;
+	unsigned int i;
+	int ret;
+
+	if (len > 128)
+		return -EINVAL;
+
+	if (adv7511->current_edid_segment != block / 2) {
+		unsigned int status;
+
+		ret = regmap_read(adv7511->regmap, ADV7511_REG_DDC_STATUS,
+				  &status);
+		if (ret < 0)
+			return ret;
+
+		if (status != 2) {
+			adv7511->edid_read = false;
+			regmap_write(adv7511->regmap, ADV7511_REG_EDID_SEGMENT,
+				     block);
+			ret = adv7511_wait_for_edid(adv7511, 200);
+			if (ret < 0)
+				return ret;
+		}
+
+		/* Break this apart, hopefully more I2C controllers will
+		 * support 64 byte transfers than 256 byte transfers
+		 */
+
+		xfer[0].addr = adv7511->i2c_edid->addr;
+		xfer[0].flags = 0;
+		xfer[0].len = 1;
+		xfer[0].buf = &offset;
+		xfer[1].addr = adv7511->i2c_edid->addr;
+		xfer[1].flags = I2C_M_RD;
+		xfer[1].len = 64;
+		xfer[1].buf = adv7511->edid_buf;
+
+		offset = 0;
+
+		for (i = 0; i < 4; ++i) {
+			ret = i2c_transfer(adv7511->i2c_edid->adapter, xfer,
+					   ARRAY_SIZE(xfer));
+			if (ret < 0)
+				return ret;
+			else if (ret != 2)
+				return -EIO;
+
+			xfer[1].buf += 64;
+			offset += 64;
+		}
+
+		adv7511->current_edid_segment = block / 2;
+	}
+
+	if (block % 2 == 0)
+		memcpy(buf, adv7511->edid_buf, len);
+	else
+		memcpy(buf, adv7511->edid_buf + 128, len);
+
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Encoder operations
+ */
+
+static int adv7511_get_modes(struct drm_encoder *encoder,
+			     struct drm_connector *connector)
+{
+	struct adv7511 *adv7511 = encoder_to_adv7511(encoder);
+	struct edid *edid;
+	unsigned int count;
+
+	/* Reading the EDID only works if the device is powered */
+	if (!adv7511->powered) {
+		regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER,
+				   ADV7511_POWER_POWER_DOWN, 0);
+		if (adv7511->i2c_main->irq) {
+			regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(0),
+				     ADV7511_INT0_EDID_READY);
+			regmap_write(adv7511->regmap, ADV7511_REG_INT_ENABLE(1),
+				     ADV7511_INT1_DDC_ERROR);
+		}
+		adv7511->current_edid_segment = -1;
+	}
+
+	edid = drm_do_get_edid(connector, adv7511_get_edid_block, adv7511);
+
+	if (!adv7511->powered)
+		regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER,
+				   ADV7511_POWER_POWER_DOWN,
+				   ADV7511_POWER_POWER_DOWN);
+
+	kfree(adv7511->edid);
+	adv7511->edid = edid;
+	if (!edid)
+		return 0;
+
+	drm_connector_update_edid_property(connector, edid);
+	count = drm_add_edid_modes(connector, edid);
+
+	adv7511_set_config_csc(adv7511, connector, adv7511->rgb);
+
+	return count;
+}
+
+static void adv7511_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct adv7511 *adv7511 = encoder_to_adv7511(encoder);
+
+	if (mode == DRM_MODE_DPMS_ON)
+		adv7511_power_on(adv7511);
+	else
+		adv7511_power_off(adv7511);
+}
+
+static enum drm_connector_status
+adv7511_encoder_detect(struct drm_encoder *encoder,
+		       struct drm_connector *connector)
+{
+	struct adv7511 *adv7511 = encoder_to_adv7511(encoder);
+	enum drm_connector_status status;
+	unsigned int val;
+	bool hpd;
+	int ret;
+
+	ret = regmap_read(adv7511->regmap, ADV7511_REG_STATUS, &val);
+	if (ret < 0)
+		return connector_status_disconnected;
+
+	if (val & ADV7511_STATUS_HPD)
+		status = connector_status_connected;
+	else
+		status = connector_status_disconnected;
+
+	hpd = adv7511_hpd(adv7511);
+
+	/* The chip resets itself when the cable is disconnected, so in case
+	 * there is a pending HPD interrupt and the cable is connected there was
+	 * at least one transition from disconnected to connected and the chip
+	 * has to be reinitialized. */
+	if (status == connector_status_connected && hpd && adv7511->powered) {
+		regcache_mark_dirty(adv7511->regmap);
+		adv7511_power_on(adv7511);
+		adv7511_get_modes(encoder, connector);
+		if (adv7511->status == connector_status_connected)
+			status = connector_status_disconnected;
+	} else {
+		/* Renable HPD sensing */
+		regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2,
+				   ADV7511_REG_POWER2_HPD_SRC_MASK,
+				   ADV7511_REG_POWER2_HPD_SRC_BOTH);
+	}
+
+	adv7511->status = status;
+	return status;
+}
+
+static int adv7511_encoder_mode_valid(struct drm_encoder *encoder,
+				      struct drm_display_mode *mode)
+{
+	if (mode->clock > 165000)
+		return MODE_CLOCK_HIGH;
+
+	return MODE_OK;
+}
+
+static void adv7511_encoder_mode_set(struct drm_encoder *encoder,
+				     struct drm_display_mode *mode,
+				     struct drm_display_mode *adj_mode)
+{
+	struct adv7511 *adv7511 = encoder_to_adv7511(encoder);
+	unsigned int low_refresh_rate;
+	unsigned int hsync_polarity = 0;
+	unsigned int vsync_polarity = 0;
+
+	if (adv7511->embedded_sync) {
+		unsigned int hsync_offset, hsync_len;
+		unsigned int vsync_offset, vsync_len;
+
+		hsync_offset = adj_mode->crtc_hsync_start -
+			       adj_mode->crtc_hdisplay;
+		vsync_offset = adj_mode->crtc_vsync_start -
+			       adj_mode->crtc_vdisplay;
+		hsync_len = adj_mode->crtc_hsync_end -
+			    adj_mode->crtc_hsync_start;
+		vsync_len = adj_mode->crtc_vsync_end -
+			    adj_mode->crtc_vsync_start;
+
+		/* The hardware vsync generator has a off-by-one bug */
+		vsync_offset += 1;
+
+		regmap_write(adv7511->regmap, ADV7511_REG_HSYNC_PLACEMENT_MSB,
+			     ((hsync_offset >> 10) & 0x7) << 5);
+		regmap_write(adv7511->regmap, ADV7511_REG_SYNC_DECODER(0),
+			     (hsync_offset >> 2) & 0xff);
+		regmap_write(adv7511->regmap, ADV7511_REG_SYNC_DECODER(1),
+			     ((hsync_offset & 0x3) << 6) |
+			     ((hsync_len >> 4) & 0x3f));
+		regmap_write(adv7511->regmap, ADV7511_REG_SYNC_DECODER(2),
+			     ((hsync_len & 0xf) << 4) |
+			     ((vsync_offset >> 6) & 0xf));
+		regmap_write(adv7511->regmap, ADV7511_REG_SYNC_DECODER(3),
+			     ((vsync_offset & 0x3f) << 2) |
+			     ((vsync_len >> 8) & 0x3));
+		regmap_write(adv7511->regmap, ADV7511_REG_SYNC_DECODER(4),
+			     vsync_len & 0xff);
+
+		hsync_polarity = !(adj_mode->flags & DRM_MODE_FLAG_PHSYNC);
+		vsync_polarity = !(adj_mode->flags & DRM_MODE_FLAG_PVSYNC);
+	} else {
+		enum adv7511_sync_polarity mode_hsync_polarity;
+		enum adv7511_sync_polarity mode_vsync_polarity;
+
+		/**
+		 * If the input signal is always low or always high we want to
+		 * invert or let it passthrough depending on the polarity of the
+		 * current mode.
+		 **/
+		if (adj_mode->flags & DRM_MODE_FLAG_NHSYNC)
+			mode_hsync_polarity = ADV7511_SYNC_POLARITY_LOW;
+		else
+			mode_hsync_polarity = ADV7511_SYNC_POLARITY_HIGH;
+
+		if (adj_mode->flags & DRM_MODE_FLAG_NVSYNC)
+			mode_vsync_polarity = ADV7511_SYNC_POLARITY_LOW;
+		else
+			mode_vsync_polarity = ADV7511_SYNC_POLARITY_HIGH;
+
+		if (adv7511->hsync_polarity != mode_hsync_polarity &&
+		    adv7511->hsync_polarity !=
+		    ADV7511_SYNC_POLARITY_PASSTHROUGH)
+			hsync_polarity = 1;
+
+		if (adv7511->vsync_polarity != mode_vsync_polarity &&
+		    adv7511->vsync_polarity !=
+		    ADV7511_SYNC_POLARITY_PASSTHROUGH)
+			vsync_polarity = 1;
+	}
+
+	if (mode->vrefresh <= 24000)
+		low_refresh_rate = ADV7511_LOW_REFRESH_RATE_24HZ;
+	else if (mode->vrefresh <= 25000)
+		low_refresh_rate = ADV7511_LOW_REFRESH_RATE_25HZ;
+	else if (mode->vrefresh <= 30000)
+		low_refresh_rate = ADV7511_LOW_REFRESH_RATE_30HZ;
+	else
+		low_refresh_rate = ADV7511_LOW_REFRESH_RATE_NONE;
+
+	regmap_update_bits(adv7511->regmap, 0xfb,
+		0x6, low_refresh_rate << 1);
+	regmap_update_bits(adv7511->regmap, 0x17,
+		0x60, (vsync_polarity << 6) | (hsync_polarity << 5));
+
+	/*
+	 * TODO Test first order 4:2:2 to 4:4:4 up conversion method, which is
+	 * supposed to give better results.
+	 */
+
+	adv7511->f_tmds = mode->clock;
+}
+
+static const struct drm_encoder_slave_funcs adv7511_encoder_funcs = {
+	.dpms = adv7511_encoder_dpms,
+	.mode_valid = adv7511_encoder_mode_valid,
+	.mode_set = adv7511_encoder_mode_set,
+	.detect = adv7511_encoder_detect,
+	.get_modes = adv7511_get_modes,
+};
+
+/* -----------------------------------------------------------------------------
+ * Probe & remove
+ */
+
+static int adv7511_parse_dt(struct device_node *np,
+			    struct adv7511_link_config *config)
+{
+	const char *str;
+	int ret;
+
+	memset(config, 0, sizeof(*config));
+
+	of_property_read_u32(np, "adi,input-depth", &config->input_color_depth);
+	if (config->input_color_depth != 8 && config->input_color_depth != 10 &&
+	    config->input_color_depth != 12)
+		return -EINVAL;
+
+	ret = of_property_read_string(np, "adi,input-colorspace", &str);
+	if (ret < 0)
+		return ret;
+
+	if (!strcmp(str, "rgb"))
+		config->input_colorspace = HDMI_COLORSPACE_RGB;
+	else if (!strcmp(str, "yuv422"))
+		config->input_colorspace = HDMI_COLORSPACE_YUV422;
+	else if (!strcmp(str, "yuv444"))
+		config->input_colorspace = HDMI_COLORSPACE_YUV444;
+	else
+		return -EINVAL;
+
+	ret = of_property_read_string(np, "adi,input-clock", &str);
+	if (ret < 0)
+		return ret;
+
+	if (!strcmp(str, "1x"))
+		config->input_clock = ADV7511_INPUT_CLOCK_1X;
+	else if (!strcmp(str, "2x"))
+		config->input_clock = ADV7511_INPUT_CLOCK_2X;
+	else if (!strcmp(str, "ddr"))
+		config->input_clock = ADV7511_INPUT_CLOCK_DDR;
+	else
+		return -EINVAL;
+
+	if (config->input_colorspace == HDMI_COLORSPACE_YUV422 ||
+	    config->input_clock != ADV7511_INPUT_CLOCK_1X) {
+		ret = of_property_read_u32(np, "adi,input-style",
+					   &config->input_style);
+		if (ret)
+			return ret;
+
+		if (config->input_style < 1 || config->input_style > 3)
+			return -EINVAL;
+
+		ret = of_property_read_string(np, "adi,input-justification",
+					      &str);
+		if (ret < 0)
+			return ret;
+
+		if (!strcmp(str, "left"))
+			config->input_justification =
+				ADV7511_INPUT_JUSTIFICATION_LEFT;
+		else if (!strcmp(str, "evenly"))
+			config->input_justification =
+				ADV7511_INPUT_JUSTIFICATION_EVENLY;
+		else if (!strcmp(str, "right"))
+			config->input_justification =
+				ADV7511_INPUT_JUSTIFICATION_RIGHT;
+		else
+			return -EINVAL;
+
+	} else {
+		config->input_style = 1;
+		config->input_justification = ADV7511_INPUT_JUSTIFICATION_LEFT;
+	}
+
+	of_property_read_u32(np, "adi,clock-delay", &config->clock_delay);
+	if (config->clock_delay < -1200 || config->clock_delay > 1600)
+		return -EINVAL;
+
+	config->embedded_sync = of_property_read_bool(np, "adi,embedded-sync");
+
+	/* Hardcode the sync pulse configurations for now. */
+	config->sync_pulse = ADV7511_INPUT_SYNC_PULSE_NONE;
+	config->vsync_polarity = ADV7511_SYNC_POLARITY_PASSTHROUGH;
+	config->hsync_polarity = ADV7511_SYNC_POLARITY_PASSTHROUGH;
+
+	return 0;
+}
+
+static const int edid_i2c_addr = 0x7e;
+static const int packet_i2c_addr = 0x70;
+static const int cec_i2c_addr = 0x78;
+
+static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
+{
+	struct adv7511_link_config link_config;
+	struct adv7511 *adv7511;
+	struct device *dev = &i2c->dev;
+	unsigned int val;
+	int ret;
+
+	if (!dev->of_node)
+		return -EINVAL;
+
+	adv7511 = devm_kzalloc(dev, sizeof(*adv7511), GFP_KERNEL);
+	if (!adv7511)
+		return -ENOMEM;
+
+	adv7511->powered = false;
+	adv7511->status = connector_status_disconnected;
+
+	ret = adv7511_parse_dt(dev->of_node, &link_config);
+	if (ret)
+		return ret;
+
+	/*
+	 * The power down GPIO is optional. If present, toggle it from active to
+	 * inactive to wake up the encoder.
+	 */
+	adv7511->gpio_pd = devm_gpiod_get_optional(dev, "pd", GPIOD_OUT_HIGH);
+	if (IS_ERR(adv7511->gpio_pd))
+		return PTR_ERR(adv7511->gpio_pd);
+
+	if (adv7511->gpio_pd) {
+		mdelay(5);
+		gpiod_set_value_cansleep(adv7511->gpio_pd, 0);
+	}
+
+	adv7511->regmap = devm_regmap_init_i2c(i2c, &adv7511_regmap_config);
+	if (IS_ERR(adv7511->regmap))
+		return PTR_ERR(adv7511->regmap);
+
+	ret = regmap_read(adv7511->regmap, ADV7511_REG_CHIP_REVISION, &val);
+	if (ret)
+		return ret;
+	dev_dbg(dev, "Rev. %d\n", val);
+
+	ret = regmap_register_patch(adv7511->regmap, adv7511_fixed_registers,
+				    ARRAY_SIZE(adv7511_fixed_registers));
+	if (ret)
+		return ret;
+
+	regmap_write(adv7511->regmap, ADV7511_REG_EDID_I2C_ADDR, edid_i2c_addr);
+	regmap_write(adv7511->regmap, ADV7511_REG_PACKET_I2C_ADDR,
+		     packet_i2c_addr);
+	regmap_write(adv7511->regmap, ADV7511_REG_CEC_I2C_ADDR, cec_i2c_addr);
+	adv7511_packet_disable(adv7511, 0xffff);
+
+	adv7511->i2c_main = i2c;
+	adv7511->i2c_edid = i2c_new_dummy(i2c->adapter, edid_i2c_addr >> 1);
+	if (!adv7511->i2c_edid)
+		return -ENOMEM;
+
+	if (i2c->irq) {
+		init_waitqueue_head(&adv7511->wq);
+
+		ret = devm_request_threaded_irq(dev, i2c->irq, NULL,
+						adv7511_irq_handler,
+						IRQF_ONESHOT, dev_name(dev),
+						adv7511);
+		if (ret)
+			goto err_i2c_unregister_device;
+	}
+
+	/* CEC is unused for now */
+	regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL,
+		     ADV7511_CEC_CTRL_POWER_DOWN);
+
+	adv7511_power_off(adv7511);
+
+	i2c_set_clientdata(i2c, adv7511);
+
+	adv7511_set_link_config(adv7511, &link_config);
+
+	return 0;
+
+err_i2c_unregister_device:
+	i2c_unregister_device(adv7511->i2c_edid);
+
+	return ret;
+}
+
+static int adv7511_remove(struct i2c_client *i2c)
+{
+	struct adv7511 *adv7511 = i2c_get_clientdata(i2c);
+
+	i2c_unregister_device(adv7511->i2c_edid);
+
+	kfree(adv7511->edid);
+
+	return 0;
+}
+
+static int adv7511_encoder_init(struct i2c_client *i2c, struct drm_device *dev,
+				struct drm_encoder_slave *encoder)
+{
+
+	struct adv7511 *adv7511 = i2c_get_clientdata(i2c);
+
+	encoder->slave_priv = adv7511;
+	encoder->slave_funcs = &adv7511_encoder_funcs;
+
+	adv7511->encoder = &encoder->base;
+
+	return 0;
+}
+
+static const struct i2c_device_id adv7511_i2c_ids[] = {
+	{ "adv7511", 0 },
+	{ "adv7511w", 0 },
+	{ "adv7513", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, adv7511_i2c_ids);
+
+static const struct of_device_id adv7511_of_ids[] = {
+	{ .compatible = "adi,adv7511", },
+	{ .compatible = "adi,adv7511w", },
+	{ .compatible = "adi,adv7513", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, adv7511_of_ids);
+
+static struct drm_i2c_encoder_driver adv7511_driver = {
+	.i2c_driver = {
+		.driver = {
+			.name = "adv7511",
+			.of_match_table = adv7511_of_ids,
+		},
+		.id_table = adv7511_i2c_ids,
+		.probe = adv7511_probe,
+		.remove = adv7511_remove,
+	},
+
+	.encoder_init = adv7511_encoder_init,
+};
+
+static int __init adv7511_init(void)
+{
+	return drm_i2c_encoder_register(THIS_MODULE, &adv7511_driver);
+}
+module_init(adv7511_init);
+
+static void __exit adv7511_exit(void)
+{
+	drm_i2c_encoder_unregister(&adv7511_driver);
+}
+module_exit(adv7511_exit);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("ADV7511 HDMI transmitter driver");
+MODULE_LICENSE("GPL");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i2c/adv7511.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i2c/adv7511.h
@@ -0,0 +1,289 @@
+/*
+ * Analog Devices ADV7511 HDMI transmitter driver
+ *
+ * Copyright 2012 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#ifndef __DRM_I2C_ADV7511_H__
+#define __DRM_I2C_ADV7511_H__
+
+#include <linux/hdmi.h>
+
+#define ADV7511_REG_CHIP_REVISION		0x00
+#define ADV7511_REG_N0				0x01
+#define ADV7511_REG_N1				0x02
+#define ADV7511_REG_N2				0x03
+#define ADV7511_REG_SPDIF_FREQ			0x04
+#define ADV7511_REG_CTS_AUTOMATIC1		0x05
+#define ADV7511_REG_CTS_AUTOMATIC2		0x06
+#define ADV7511_REG_CTS_MANUAL0			0x07
+#define ADV7511_REG_CTS_MANUAL1			0x08
+#define ADV7511_REG_CTS_MANUAL2			0x09
+#define ADV7511_REG_AUDIO_SOURCE		0x0a
+#define ADV7511_REG_AUDIO_CONFIG		0x0b
+#define ADV7511_REG_I2S_CONFIG			0x0c
+#define ADV7511_REG_I2S_WIDTH			0x0d
+#define ADV7511_REG_AUDIO_SUB_SRC0		0x0e
+#define ADV7511_REG_AUDIO_SUB_SRC1		0x0f
+#define ADV7511_REG_AUDIO_SUB_SRC2		0x10
+#define ADV7511_REG_AUDIO_SUB_SRC3		0x11
+#define ADV7511_REG_AUDIO_CFG1			0x12
+#define ADV7511_REG_AUDIO_CFG2			0x13
+#define ADV7511_REG_AUDIO_CFG3			0x14
+#define ADV7511_REG_I2C_FREQ_ID_CFG		0x15
+#define ADV7511_REG_VIDEO_INPUT_CFG1		0x16
+#define ADV7511_REG_CSC_UPPER(x)		(0x18 + (x) * 2)
+#define ADV7511_REG_CSC_LOWER(x)		(0x19 + (x) * 2)
+#define ADV7511_REG_SYNC_DECODER(x)		(0x30 + (x))
+#define ADV7511_REG_DE_GENERATOR		(0x35 + (x))
+#define ADV7511_REG_PIXEL_REPETITION		0x3b
+#define ADV7511_REG_VIC_MANUAL			0x3c
+#define ADV7511_REG_VIC_SEND			0x3d
+#define ADV7511_REG_VIC_DETECTED		0x3e
+#define ADV7511_REG_AUX_VIC_DETECTED		0x3f
+#define ADV7511_REG_PACKET_ENABLE0		0x40
+#define ADV7511_REG_POWER			0x41
+#define ADV7511_REG_STATUS			0x42
+#define ADV7511_REG_EDID_I2C_ADDR		0x43
+#define ADV7511_REG_PACKET_ENABLE1		0x44
+#define ADV7511_REG_PACKET_I2C_ADDR		0x45
+#define ADV7511_REG_DSD_ENABLE			0x46
+#define ADV7511_REG_VIDEO_INPUT_CFG2		0x48
+#define ADV7511_REG_INFOFRAME_UPDATE		0x4a
+#define ADV7511_REG_GC(x)			(0x4b + (x)) /* 0x4b - 0x51 */
+#define ADV7511_REG_AVI_INFOFRAME_VERSION	0x52
+#define ADV7511_REG_AVI_INFOFRAME_LENGTH	0x53
+#define ADV7511_REG_AVI_INFOFRAME_CHECKSUM	0x54
+#define ADV7511_REG_AVI_INFOFRAME(x)		(0x55 + (x)) /* 0x55 - 0x6f */
+#define ADV7511_REG_AUDIO_INFOFRAME_VERSION	0x70
+#define ADV7511_REG_AUDIO_INFOFRAME_LENGTH	0x71
+#define ADV7511_REG_AUDIO_INFOFRAME_CHECKSUM	0x72
+#define ADV7511_REG_AUDIO_INFOFRAME(x)		(0x73 + (x)) /* 0x73 - 0x7c */
+#define ADV7511_REG_INT_ENABLE(x)		(0x94 + (x))
+#define ADV7511_REG_INT(x)			(0x96 + (x))
+#define ADV7511_REG_INPUT_CLK_DIV		0x9d
+#define ADV7511_REG_PLL_STATUS			0x9e
+#define ADV7511_REG_HDMI_POWER			0xa1
+#define ADV7511_REG_HDCP_HDMI_CFG		0xaf
+#define ADV7511_REG_AN(x)			(0xb0 + (x)) /* 0xb0 - 0xb7 */
+#define ADV7511_REG_HDCP_STATUS			0xb8
+#define ADV7511_REG_BCAPS			0xbe
+#define ADV7511_REG_BKSV(x)			(0xc0 + (x)) /* 0xc0 - 0xc3 */
+#define ADV7511_REG_EDID_SEGMENT		0xc4
+#define ADV7511_REG_DDC_STATUS			0xc8
+#define ADV7511_REG_EDID_READ_CTRL		0xc9
+#define ADV7511_REG_BSTATUS(x)			(0xca + (x)) /* 0xca - 0xcb */
+#define ADV7511_REG_TIMING_GEN_SEQ		0xd0
+#define ADV7511_REG_POWER2			0xd6
+#define ADV7511_REG_HSYNC_PLACEMENT_MSB		0xfa
+
+#define ADV7511_REG_SYNC_ADJUSTMENT(x)		(0xd7 + (x)) /* 0xd7 - 0xdc */
+#define ADV7511_REG_TMDS_CLOCK_INV		0xde
+#define ADV7511_REG_ARC_CTRL			0xdf
+#define ADV7511_REG_CEC_I2C_ADDR		0xe1
+#define ADV7511_REG_CEC_CTRL			0xe2
+#define ADV7511_REG_CHIP_ID_HIGH		0xf5
+#define ADV7511_REG_CHIP_ID_LOW			0xf6
+
+#define ADV7511_CSC_ENABLE			BIT(7)
+#define ADV7511_CSC_UPDATE_MODE			BIT(5)
+
+#define ADV7511_INT0_HPD			BIT(7)
+#define ADV7511_INT0_VSYNC			BIT(5)
+#define ADV7511_INT0_AUDIO_FIFO_FULL		BIT(4)
+#define ADV7511_INT0_EDID_READY			BIT(2)
+#define ADV7511_INT0_HDCP_AUTHENTICATED		BIT(1)
+
+#define ADV7511_INT1_DDC_ERROR			BIT(7)
+#define ADV7511_INT1_BKSV			BIT(6)
+#define ADV7511_INT1_CEC_TX_READY		BIT(5)
+#define ADV7511_INT1_CEC_TX_ARBIT_LOST		BIT(4)
+#define ADV7511_INT1_CEC_TX_RETRY_TIMEOUT	BIT(3)
+#define ADV7511_INT1_CEC_RX_READY3		BIT(2)
+#define ADV7511_INT1_CEC_RX_READY2		BIT(1)
+#define ADV7511_INT1_CEC_RX_READY1		BIT(0)
+
+#define ADV7511_ARC_CTRL_POWER_DOWN		BIT(0)
+
+#define ADV7511_CEC_CTRL_POWER_DOWN		BIT(0)
+
+#define ADV7511_POWER_POWER_DOWN		BIT(6)
+
+#define ADV7511_HDMI_CFG_MODE_MASK		0x2
+#define ADV7511_HDMI_CFG_MODE_DVI		0x0
+#define ADV7511_HDMI_CFG_MODE_HDMI		0x2
+
+#define ADV7511_AUDIO_SELECT_I2C		0x0
+#define ADV7511_AUDIO_SELECT_SPDIF		0x1
+#define ADV7511_AUDIO_SELECT_DSD		0x2
+#define ADV7511_AUDIO_SELECT_HBR		0x3
+#define ADV7511_AUDIO_SELECT_DST		0x4
+
+#define ADV7511_I2S_SAMPLE_LEN_16		0x2
+#define ADV7511_I2S_SAMPLE_LEN_20		0x3
+#define ADV7511_I2S_SAMPLE_LEN_18		0x4
+#define ADV7511_I2S_SAMPLE_LEN_22		0x5
+#define ADV7511_I2S_SAMPLE_LEN_19		0x8
+#define ADV7511_I2S_SAMPLE_LEN_23		0x9
+#define ADV7511_I2S_SAMPLE_LEN_24		0xb
+#define ADV7511_I2S_SAMPLE_LEN_17		0xc
+#define ADV7511_I2S_SAMPLE_LEN_21		0xd
+
+#define ADV7511_SAMPLE_FREQ_44100		0x0
+#define ADV7511_SAMPLE_FREQ_48000		0x2
+#define ADV7511_SAMPLE_FREQ_32000		0x3
+#define ADV7511_SAMPLE_FREQ_88200		0x8
+#define ADV7511_SAMPLE_FREQ_96000		0xa
+#define ADV7511_SAMPLE_FREQ_176400		0xc
+#define ADV7511_SAMPLE_FREQ_192000		0xe
+
+#define ADV7511_STATUS_POWER_DOWN_POLARITY	BIT(7)
+#define ADV7511_STATUS_HPD			BIT(6)
+#define ADV7511_STATUS_MONITOR_SENSE		BIT(5)
+#define ADV7511_STATUS_I2S_32BIT_MODE		BIT(3)
+
+#define ADV7511_PACKET_ENABLE_N_CTS		BIT(8+6)
+#define ADV7511_PACKET_ENABLE_AUDIO_SAMPLE	BIT(8+5)
+#define ADV7511_PACKET_ENABLE_AVI_INFOFRAME	BIT(8+4)
+#define ADV7511_PACKET_ENABLE_AUDIO_INFOFRAME	BIT(8+3)
+#define ADV7511_PACKET_ENABLE_GC		BIT(7)
+#define ADV7511_PACKET_ENABLE_SPD		BIT(6)
+#define ADV7511_PACKET_ENABLE_MPEG		BIT(5)
+#define ADV7511_PACKET_ENABLE_ACP		BIT(4)
+#define ADV7511_PACKET_ENABLE_ISRC		BIT(3)
+#define ADV7511_PACKET_ENABLE_GM		BIT(2)
+#define ADV7511_PACKET_ENABLE_SPARE2		BIT(1)
+#define ADV7511_PACKET_ENABLE_SPARE1		BIT(0)
+
+#define ADV7511_REG_POWER2_HPD_SRC_MASK		0xc0
+#define ADV7511_REG_POWER2_HPD_SRC_BOTH		0x00
+#define ADV7511_REG_POWER2_HPD_SRC_HPD		0x40
+#define ADV7511_REG_POWER2_HPD_SRC_CEC		0x80
+#define ADV7511_REG_POWER2_HPD_SRC_NONE		0xc0
+#define ADV7511_REG_POWER2_TDMS_ENABLE		BIT(4)
+#define ADV7511_REG_POWER2_GATE_INPUT_CLK	BIT(0)
+
+#define ADV7511_LOW_REFRESH_RATE_NONE		0x0
+#define ADV7511_LOW_REFRESH_RATE_24HZ		0x1
+#define ADV7511_LOW_REFRESH_RATE_25HZ		0x2
+#define ADV7511_LOW_REFRESH_RATE_30HZ		0x3
+
+#define ADV7511_AUDIO_CFG3_LEN_MASK		0x0f
+#define ADV7511_I2C_FREQ_ID_CFG_RATE_MASK	0xf0
+
+#define ADV7511_AUDIO_SOURCE_I2S		0
+#define ADV7511_AUDIO_SOURCE_SPDIF		1
+
+#define ADV7511_I2S_FORMAT_I2S			0
+#define ADV7511_I2S_FORMAT_RIGHT_J		1
+#define ADV7511_I2S_FORMAT_LEFT_J		2
+
+#define ADV7511_PACKET(p, x)	    ((p) * 0x20 + (x))
+#define ADV7511_PACKET_SDP(x)	    ADV7511_PACKET(0, x)
+#define ADV7511_PACKET_MPEG(x)	    ADV7511_PACKET(1, x)
+#define ADV7511_PACKET_ACP(x)	    ADV7511_PACKET(2, x)
+#define ADV7511_PACKET_ISRC1(x)	    ADV7511_PACKET(3, x)
+#define ADV7511_PACKET_ISRC2(x)	    ADV7511_PACKET(4, x)
+#define ADV7511_PACKET_GM(x)	    ADV7511_PACKET(5, x)
+#define ADV7511_PACKET_SPARE(x)	    ADV7511_PACKET(6, x)
+
+enum adv7511_input_clock {
+	ADV7511_INPUT_CLOCK_1X,
+	ADV7511_INPUT_CLOCK_2X,
+	ADV7511_INPUT_CLOCK_DDR,
+};
+
+enum adv7511_input_justification {
+	ADV7511_INPUT_JUSTIFICATION_EVENLY = 0,
+	ADV7511_INPUT_JUSTIFICATION_RIGHT = 1,
+	ADV7511_INPUT_JUSTIFICATION_LEFT = 2,
+};
+
+enum adv7511_input_sync_pulse {
+	ADV7511_INPUT_SYNC_PULSE_DE = 0,
+	ADV7511_INPUT_SYNC_PULSE_HSYNC = 1,
+	ADV7511_INPUT_SYNC_PULSE_VSYNC = 2,
+	ADV7511_INPUT_SYNC_PULSE_NONE = 3,
+};
+
+/**
+ * enum adv7511_sync_polarity - Polarity for the input sync signals
+ * @ADV7511_SYNC_POLARITY_PASSTHROUGH:  Sync polarity matches that of
+ *				       the currently configured mode.
+ * @ADV7511_SYNC_POLARITY_LOW:	    Sync polarity is low
+ * @ADV7511_SYNC_POLARITY_HIGH:	    Sync polarity is high
+ *
+ * If the polarity is set to either LOW or HIGH the driver will configure the
+ * ADV7511 to internally invert the sync signal if required to match the sync
+ * polarity setting for the currently selected output mode.
+ *
+ * If the polarity is set to PASSTHROUGH, the ADV7511 will route the signal
+ * unchanged. This is used when the upstream graphics core already generates
+ * the sync signals with the correct polarity.
+ */
+enum adv7511_sync_polarity {
+	ADV7511_SYNC_POLARITY_PASSTHROUGH,
+	ADV7511_SYNC_POLARITY_LOW,
+	ADV7511_SYNC_POLARITY_HIGH,
+};
+
+/**
+ * struct adv7511_link_config - Describes adv7511 hardware configuration
+ * @input_color_depth:		Number of bits per color component (8, 10 or 12)
+ * @input_colorspace:		The input colorspace (RGB, YUV444, YUV422)
+ * @input_clock:		The input video clock style (1x, 2x, DDR)
+ * @input_style:		The input component arrangement variant
+ * @input_justification:	Video input format bit justification
+ * @clock_delay:		Clock delay for the input clock (in ps)
+ * @embedded_sync:		Video input uses BT.656-style embedded sync
+ * @sync_pulse:			Select the sync pulse
+ * @vsync_polarity:		vsync input signal configuration
+ * @hsync_polarity:		hsync input signal configuration
+ */
+struct adv7511_link_config {
+	unsigned int input_color_depth;
+	enum hdmi_colorspace input_colorspace;
+	enum adv7511_input_clock input_clock;
+	unsigned int input_style;
+	enum adv7511_input_justification input_justification;
+
+	int clock_delay;
+
+	bool embedded_sync;
+	enum adv7511_input_sync_pulse sync_pulse;
+	enum adv7511_sync_polarity vsync_polarity;
+	enum adv7511_sync_polarity hsync_polarity;
+};
+
+/**
+ * enum adv7511_csc_scaling - Scaling factor for the ADV7511 CSC
+ * @ADV7511_CSC_SCALING_1: CSC results are not scaled
+ * @ADV7511_CSC_SCALING_2: CSC results are scaled by a factor of two
+ * @ADV7511_CSC_SCALING_4: CSC results are scalled by a factor of four
+ */
+enum adv7511_csc_scaling {
+	ADV7511_CSC_SCALING_1 = 0,
+	ADV7511_CSC_SCALING_2 = 1,
+	ADV7511_CSC_SCALING_4 = 2,
+};
+
+/**
+ * struct adv7511_video_config - Describes adv7511 hardware configuration
+ * @csc_enable:			Whether to enable color space conversion
+ * @csc_scaling_factor:		Color space conversion scaling factor
+ * @csc_coefficents:		Color space conversion coefficents
+ * @hdmi_mode:			Whether to use HDMI or DVI output mode
+ * @avi_infoframe:		HDMI infoframe
+ */
+struct adv7511_video_config {
+	bool csc_enable;
+	enum adv7511_csc_scaling csc_scaling_factor;
+	const uint16_t *csc_coefficents;
+
+	bool hdmi_mode;
+	struct hdmi_avi_infoframe avi_infoframe;
+};
+
+#endif /* __DRM_I2C_ADV7511_H__ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i810/i810_dma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i810/i810_dma.c
@@ -728,7 +728,7 @@
 	if (nbox > I810_NR_SAREA_CLIPRECTS)
 		nbox = I810_NR_SAREA_CLIPRECTS;
 
-	if (used > 4 * 1024)
+	if (used < 0 || used > 4 * 1024)
 		used = 0;
 
 	if (sarea_priv->dirty)
@@ -1048,7 +1048,7 @@
 	if (u != I810_BUF_CLIENT)
 		DRM_DEBUG("MC found buffer that isn't mine!\n");
 
-	if (used > 4 * 1024)
+	if (used < 0 || used > 4 * 1024)
 		used = 0;
 
 	sarea_priv->dirty = 0x7f;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/Kconfig
@@ -75,9 +75,8 @@
 	help
 	  This option enables capturing the GPU state when a hang is detected.
 	  This information is vital for triaging hangs and assists in debugging.
-	  Please report any hang to
-            https://bugs.freedesktop.org/enter_bug.cgi?product=DRI
-	  for triaging.
+	  Please report any hang for triaging according to:
+	    https://gitlab.freedesktop.org/drm/intel/-/wikis/How-to-file-i915-bugs
 
 	  If in doubt, say "Y".
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/Kconfig.debug
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/Kconfig.debug
@@ -7,7 +7,6 @@
         # We use the dependency on !COMPILE_TEST to not be enabled in
         # allmodconfig or allyesconfig configurations
         depends on !COMPILE_TEST
-	select HEADER_TEST
         default n
         help
           Add -Werror to the build flags for (and only for) i915.ko.
@@ -22,7 +21,6 @@
         depends on DRM_I915
         select DEBUG_FS
         select PREEMPT_COUNT
-        select REFCOUNT_FULL
         select I2C_CHARDEV
         select STACKDEPOT
         select DRM_DP_AUX_CHARDEV
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/Makefile
@@ -83,6 +83,7 @@
 	gt/intel_gt_irq.o \
 	gt/intel_gt_pm.o \
 	gt/intel_gt_pm_irq.o \
+	gt/intel_gt_requests.o \
 	gt/intel_hangcheck.o \
 	gt/intel_lrc.o \
 	gt/intel_renderstate.o \
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/display/intel_acpi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/display/intel_acpi.c
@@ -83,13 +83,31 @@
 		return;
 	}
 
+	if (!pkg->package.count) {
+		DRM_DEBUG_DRIVER("no connection in _DSM\n");
+		return;
+	}
+
 	connector_count = &pkg->package.elements[0];
 	DRM_DEBUG_DRIVER("MUX info connectors: %lld\n",
 		  (unsigned long long)connector_count->integer.value);
 	for (i = 1; i < pkg->package.count; i++) {
 		union acpi_object *obj = &pkg->package.elements[i];
-		union acpi_object *connector_id = &obj->package.elements[0];
-		union acpi_object *info = &obj->package.elements[1];
+		union acpi_object *connector_id;
+		union acpi_object *info;
+
+		if (obj->type != ACPI_TYPE_PACKAGE || obj->package.count < 2) {
+			DRM_DEBUG_DRIVER("Invalid object for MUX #%d\n", i);
+			continue;
+		}
+
+		connector_id = &obj->package.elements[0];
+		info = &obj->package.elements[1];
+		if (info->type != ACPI_TYPE_BUFFER || info->buffer.length < 4) {
+			DRM_DEBUG_DRIVER("Invalid info for MUX obj #%d\n", i);
+			continue;
+		}
+
 		DRM_DEBUG_DRIVER("Connector id: 0x%016llx\n",
 			  (unsigned long long)connector_id->integer.value);
 		DRM_DEBUG_DRIVER("  port id: %s\n",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/display/intel_audio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/display/intel_audio.c
@@ -851,10 +851,16 @@
 	ret = intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO);
 
 	/* Force CDCLK to 2*BCLK as long as we need audio to be powered. */
-	if (dev_priv->audio_power_refcount++ == 0)
-		if (IS_CANNONLAKE(dev_priv) || IS_GEMINILAKE(dev_priv))
+	if (dev_priv->audio_power_refcount++ == 0) {
+		if (IS_GEMINILAKE(dev_priv))
 			glk_force_audio_cdclk(dev_priv, true);
 
+		if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
+			I915_WRITE(AUD_PIN_BUF_CTL,
+				   (I915_READ(AUD_PIN_BUF_CTL) |
+				    AUD_PIN_BUF_ENABLE));
+	}
+
 	return ret;
 }
 
@@ -865,7 +871,7 @@
 
 	/* Stop forcing CDCLK to 2*BCLK if no need for audio to be powered. */
 	if (--dev_priv->audio_power_refcount == 0)
-		if (IS_CANNONLAKE(dev_priv) || IS_GEMINILAKE(dev_priv))
+		if (IS_GEMINILAKE(dev_priv))
 			glk_force_audio_cdclk(dev_priv, false);
 
 	intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO, cookie);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/display/intel_bios.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/display/intel_bios.c
@@ -32,6 +32,7 @@
 #include "display/intel_gmbus.h"
 
 #include "i915_drv.h"
+#include <linux/dmi.h>
 
 #define _INTEL_BIOS_PRIVATE
 #include "intel_vbt_defs.h"
@@ -1828,6 +1829,22 @@
 	return NULL;
 }
 
+#define DRM_DMI_PRODUCT_VERSION 0x6
+
+static void parse_product_info(struct drm_i915_private *dev_priv)
+{
+	const char *product_ver = dmi_get_system_info(DRM_DMI_PRODUCT_VERSION);
+	if (!product_ver)
+		return;
+
+	if (!strncmp(product_ver, "ThinkPad X1", 11)) {
+		DRM_DEBUG_KMS("dmi: %s, Bypassing TMDS_OE write\n", product_ver);
+		dev_priv->bypass_tmds_oe = true;
+	}
+
+	return;
+}
+
 /**
  * intel_bios_init - find VBT and initialize settings from the BIOS
  * @dev_priv: i915 device instance
@@ -1886,6 +1903,8 @@
 	parse_sdvo_device_mapping(dev_priv, bdb->version);
 	parse_ddi_ports(dev_priv, bdb->version);
 
+	parse_product_info(dev_priv);
+
 out:
 	if (!vbt) {
 		DRM_INFO("Failed to find VBIOS tables (VBT)\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/display/intel_ddi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -2124,7 +2124,11 @@
 		return;
 
 	dig_port = enc_to_dig_port(&encoder->base);
-	intel_display_power_get(dev_priv, dig_port->ddi_io_power_domain);
+
+	if (!intel_phy_is_tc(dev_priv, phy) ||
+	    dig_port->tc_mode != TC_PORT_TBT_ALT)
+		intel_display_power_get(dev_priv,
+					dig_port->ddi_io_power_domain);
 
 	/*
 	 * AUX power is only needed for (e)DP mode, and for HDMI mode on TC
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/display/intel_display.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/display/intel_display.c
@@ -6753,20 +6753,30 @@
 	    dig_port->tc_mode == TC_PORT_TBT_ALT) {
 		switch (dig_port->aux_ch) {
 		case AUX_CH_C:
-			return POWER_DOMAIN_AUX_TBT1;
+			return POWER_DOMAIN_AUX_C_TBT;
 		case AUX_CH_D:
-			return POWER_DOMAIN_AUX_TBT2;
+			return POWER_DOMAIN_AUX_D_TBT;
 		case AUX_CH_E:
-			return POWER_DOMAIN_AUX_TBT3;
+			return POWER_DOMAIN_AUX_E_TBT;
 		case AUX_CH_F:
-			return POWER_DOMAIN_AUX_TBT4;
+			return POWER_DOMAIN_AUX_F_TBT;
 		default:
 			MISSING_CASE(dig_port->aux_ch);
-			return POWER_DOMAIN_AUX_TBT1;
+			return POWER_DOMAIN_AUX_C_TBT;
 		}
 	}
 
-	switch (dig_port->aux_ch) {
+	return intel_legacy_aux_to_power_domain(dig_port->aux_ch);
+}
+
+/*
+ * Converts aux_ch to power_domain without caring about TBT ports for that use
+ * intel_aux_power_domain()
+ */
+enum intel_display_power_domain
+intel_legacy_aux_to_power_domain(enum aux_ch aux_ch)
+{
+	switch (aux_ch) {
 	case AUX_CH_A:
 		return POWER_DOMAIN_AUX_A;
 	case AUX_CH_B:
@@ -6780,7 +6790,7 @@
 	case AUX_CH_F:
 		return POWER_DOMAIN_AUX_F;
 	default:
-		MISSING_CASE(dig_port->aux_ch);
+		MISSING_CASE(aux_ch);
 		return POWER_DOMAIN_AUX_A;
 	}
 }
@@ -10510,7 +10520,7 @@
 	u32 base;
 
 	if (INTEL_INFO(dev_priv)->display.cursor_needs_physical)
-		base = obj->phys_handle->busaddr;
+		base = sg_dma_address(obj->mm.pages->sgl);
 	else
 		base = intel_plane_ggtt_offset(plane_state);
 
@@ -11893,10 +11903,11 @@
 	case 10 ... 11:
 		bpp = 10 * 3;
 		break;
-	case 12:
+	case 12 ... 16:
 		bpp = 12 * 3;
 		break;
 	default:
+		MISSING_CASE(conn_state->max_bpc);
 		return -EINVAL;
 	}
 
@@ -14429,7 +14440,7 @@
 		return ret;
 
 	fb_obj_bump_render_priority(obj);
-	intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_DIRTYFB);
+	i915_gem_object_flush_frontbuffer(obj, ORIGIN_DIRTYFB);
 
 	if (!new_state->fence) { /* implicit fencing */
 		struct dma_fence *fence;
@@ -16860,8 +16871,11 @@
 
 static void intel_early_display_was(struct drm_i915_private *dev_priv)
 {
-	/* Display WA #1185 WaDisableDARBFClkGating:cnl,glk */
-	if (IS_CANNONLAKE(dev_priv) || IS_GEMINILAKE(dev_priv))
+	/*
+	 * Display WA #1185 WaDisableDARBFClkGating:cnl,glk,icl,ehl,tgl
+	 * Also known as Wa_14010480278.
+	 */
+	if (IS_GEN_RANGE(dev_priv, 10, 12) || IS_GEMINILAKE(dev_priv))
 		I915_WRITE(GEN9_CLKGATE_DIS_0, I915_READ(GEN9_CLKGATE_DIS_0) |
 			   DARBF_GATING_DIS);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/display/intel_display.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/display/intel_display.h
@@ -513,6 +513,8 @@
 enum intel_display_power_domain intel_port_to_power_domain(enum port port);
 enum intel_display_power_domain
 intel_aux_power_domain(struct intel_digital_port *dig_port);
+enum intel_display_power_domain
+intel_legacy_aux_to_power_domain(enum aux_ch aux_ch);
 void intel_mode_from_pipe_config(struct drm_display_mode *mode,
 				 struct intel_crtc_state *pipe_config);
 void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/display/intel_display_power.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/display/intel_display_power.c
@@ -20,15 +20,14 @@
 #include "intel_sideband.h"
 #include "intel_tc.h"
 
+static const struct i915_power_well_ops icl_tc_phy_aux_power_well_ops;
+
 bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv,
 					 enum i915_power_well_id power_well_id);
 
 const char *
-intel_display_power_domain_str(struct drm_i915_private *i915,
-			       enum intel_display_power_domain domain)
+intel_display_power_domain_str(enum intel_display_power_domain domain)
 {
-	bool ddi_tc_ports = IS_GEN(i915, 12);
-
 	switch (domain) {
 	case POWER_DOMAIN_DISPLAY_CORE:
 		return "DISPLAY_CORE";
@@ -71,23 +70,17 @@
 	case POWER_DOMAIN_PORT_DDI_C_LANES:
 		return "PORT_DDI_C_LANES";
 	case POWER_DOMAIN_PORT_DDI_D_LANES:
-		BUILD_BUG_ON(POWER_DOMAIN_PORT_DDI_D_LANES !=
-			     POWER_DOMAIN_PORT_DDI_TC1_LANES);
-		return ddi_tc_ports ? "PORT_DDI_TC1_LANES" : "PORT_DDI_D_LANES";
+		return "PORT_DDI_D_LANES";
 	case POWER_DOMAIN_PORT_DDI_E_LANES:
-		BUILD_BUG_ON(POWER_DOMAIN_PORT_DDI_E_LANES !=
-			     POWER_DOMAIN_PORT_DDI_TC2_LANES);
-		return ddi_tc_ports ? "PORT_DDI_TC2_LANES" : "PORT_DDI_E_LANES";
+		return "PORT_DDI_E_LANES";
 	case POWER_DOMAIN_PORT_DDI_F_LANES:
-		BUILD_BUG_ON(POWER_DOMAIN_PORT_DDI_F_LANES !=
-			     POWER_DOMAIN_PORT_DDI_TC3_LANES);
-		return ddi_tc_ports ? "PORT_DDI_TC3_LANES" : "PORT_DDI_F_LANES";
-	case POWER_DOMAIN_PORT_DDI_TC4_LANES:
-		return "PORT_DDI_TC4_LANES";
-	case POWER_DOMAIN_PORT_DDI_TC5_LANES:
-		return "PORT_DDI_TC5_LANES";
-	case POWER_DOMAIN_PORT_DDI_TC6_LANES:
-		return "PORT_DDI_TC6_LANES";
+		return "PORT_DDI_F_LANES";
+	case POWER_DOMAIN_PORT_DDI_G_LANES:
+		return "PORT_DDI_G_LANES";
+	case POWER_DOMAIN_PORT_DDI_H_LANES:
+		return "PORT_DDI_H_LANES";
+	case POWER_DOMAIN_PORT_DDI_I_LANES:
+		return "PORT_DDI_I_LANES";
 	case POWER_DOMAIN_PORT_DDI_A_IO:
 		return "PORT_DDI_A_IO";
 	case POWER_DOMAIN_PORT_DDI_B_IO:
@@ -95,23 +88,17 @@
 	case POWER_DOMAIN_PORT_DDI_C_IO:
 		return "PORT_DDI_C_IO";
 	case POWER_DOMAIN_PORT_DDI_D_IO:
-		BUILD_BUG_ON(POWER_DOMAIN_PORT_DDI_D_IO !=
-			     POWER_DOMAIN_PORT_DDI_TC1_IO);
-		return ddi_tc_ports ? "PORT_DDI_TC1_IO" : "PORT_DDI_D_IO";
+		return "PORT_DDI_D_IO";
 	case POWER_DOMAIN_PORT_DDI_E_IO:
-		BUILD_BUG_ON(POWER_DOMAIN_PORT_DDI_E_IO !=
-			     POWER_DOMAIN_PORT_DDI_TC2_IO);
-		return ddi_tc_ports ? "PORT_DDI_TC2_IO" : "PORT_DDI_E_IO";
+		return "PORT_DDI_E_IO";
 	case POWER_DOMAIN_PORT_DDI_F_IO:
-		BUILD_BUG_ON(POWER_DOMAIN_PORT_DDI_F_IO !=
-			     POWER_DOMAIN_PORT_DDI_TC3_IO);
-		return ddi_tc_ports ? "PORT_DDI_TC3_IO" : "PORT_DDI_F_IO";
-	case POWER_DOMAIN_PORT_DDI_TC4_IO:
-		return "PORT_DDI_TC4_IO";
-	case POWER_DOMAIN_PORT_DDI_TC5_IO:
-		return "PORT_DDI_TC5_IO";
-	case POWER_DOMAIN_PORT_DDI_TC6_IO:
-		return "PORT_DDI_TC6_IO";
+		return "PORT_DDI_F_IO";
+	case POWER_DOMAIN_PORT_DDI_G_IO:
+		return "PORT_DDI_G_IO";
+	case POWER_DOMAIN_PORT_DDI_H_IO:
+		return "PORT_DDI_H_IO";
+	case POWER_DOMAIN_PORT_DDI_I_IO:
+		return "PORT_DDI_I_IO";
 	case POWER_DOMAIN_PORT_DSI:
 		return "PORT_DSI";
 	case POWER_DOMAIN_PORT_CRT:
@@ -129,34 +116,33 @@
 	case POWER_DOMAIN_AUX_C:
 		return "AUX_C";
 	case POWER_DOMAIN_AUX_D:
-		BUILD_BUG_ON(POWER_DOMAIN_AUX_D != POWER_DOMAIN_AUX_TC1);
-		return ddi_tc_ports ? "AUX_TC1" : "AUX_D";
+		return "AUX_D";
 	case POWER_DOMAIN_AUX_E:
-		BUILD_BUG_ON(POWER_DOMAIN_AUX_E != POWER_DOMAIN_AUX_TC2);
-		return ddi_tc_ports ? "AUX_TC2" : "AUX_E";
+		return "AUX_E";
 	case POWER_DOMAIN_AUX_F:
-		BUILD_BUG_ON(POWER_DOMAIN_AUX_F != POWER_DOMAIN_AUX_TC3);
-		return ddi_tc_ports ? "AUX_TC3" : "AUX_F";
-	case POWER_DOMAIN_AUX_TC4:
-		return "AUX_TC4";
-	case POWER_DOMAIN_AUX_TC5:
-		return "AUX_TC5";
-	case POWER_DOMAIN_AUX_TC6:
-		return "AUX_TC6";
+		return "AUX_F";
+	case POWER_DOMAIN_AUX_G:
+		return "AUX_G";
+	case POWER_DOMAIN_AUX_H:
+		return "AUX_H";
+	case POWER_DOMAIN_AUX_I:
+		return "AUX_I";
 	case POWER_DOMAIN_AUX_IO_A:
 		return "AUX_IO_A";
-	case POWER_DOMAIN_AUX_TBT1:
-		return "AUX_TBT1";
-	case POWER_DOMAIN_AUX_TBT2:
-		return "AUX_TBT2";
-	case POWER_DOMAIN_AUX_TBT3:
-		return "AUX_TBT3";
-	case POWER_DOMAIN_AUX_TBT4:
-		return "AUX_TBT4";
-	case POWER_DOMAIN_AUX_TBT5:
-		return "AUX_TBT5";
-	case POWER_DOMAIN_AUX_TBT6:
-		return "AUX_TBT6";
+	case POWER_DOMAIN_AUX_C_TBT:
+		return "AUX_C_TBT";
+	case POWER_DOMAIN_AUX_D_TBT:
+		return "AUX_D_TBT";
+	case POWER_DOMAIN_AUX_E_TBT:
+		return "AUX_E_TBT";
+	case POWER_DOMAIN_AUX_F_TBT:
+		return "AUX_F_TBT";
+	case POWER_DOMAIN_AUX_G_TBT:
+		return "AUX_G_TBT";
+	case POWER_DOMAIN_AUX_H_TBT:
+		return "AUX_H_TBT";
+	case POWER_DOMAIN_AUX_I_TBT:
+		return "AUX_I_TBT";
 	case POWER_DOMAIN_GMBUS:
 		return "GMBUS";
 	case POWER_DOMAIN_INIT:
@@ -167,6 +153,8 @@
 		return "GT_IRQ";
 	case POWER_DOMAIN_DPLL_DC_OFF:
 		return "DPLL_DC_OFF";
+	case POWER_DOMAIN_TC_COLD_OFF:
+		return "TC_COLD_OFF";
 	default:
 		MISSING_CASE(domain);
 		return "?";
@@ -312,6 +300,70 @@
 		gen8_irq_power_well_pre_disable(dev_priv, irq_pipe_mask);
 }
 
+#define ICL_AUX_PW_TO_CH(pw_idx)	\
+	((pw_idx) - ICL_PW_CTL_IDX_AUX_A + AUX_CH_A)
+
+#define ICL_TBT_AUX_PW_TO_CH(pw_idx)	\
+	((pw_idx) - ICL_PW_CTL_IDX_AUX_TBT1 + AUX_CH_C)
+
+static enum aux_ch icl_tc_phy_aux_ch(struct drm_i915_private *dev_priv,
+				     struct i915_power_well *power_well)
+{
+	int pw_idx = power_well->desc->hsw.idx;
+
+	return power_well->desc->hsw.is_tc_tbt ? ICL_TBT_AUX_PW_TO_CH(pw_idx) :
+						 ICL_AUX_PW_TO_CH(pw_idx);
+}
+
+static struct intel_digital_port *
+aux_ch_to_digital_port(struct drm_i915_private *dev_priv,
+		       enum aux_ch aux_ch)
+{
+	struct intel_digital_port *dig_port = NULL;
+	struct intel_encoder *encoder;
+
+	for_each_intel_encoder(&dev_priv->drm, encoder) {
+		/* We'll check the MST primary port */
+		if (encoder->type == INTEL_OUTPUT_DP_MST)
+			continue;
+
+		dig_port = enc_to_dig_port(&encoder->base);
+		if (!dig_port)
+			continue;
+
+		if (dig_port->aux_ch != aux_ch) {
+			dig_port = NULL;
+			continue;
+		}
+
+		break;
+	}
+
+	return dig_port;
+}
+
+static bool tc_phy_aux_timeout_expected(struct drm_i915_private *dev_priv,
+					struct i915_power_well *power_well)
+{
+	/* An AUX timeout is expected if the TBT DP tunnel is down. */
+	if (power_well->desc->hsw.is_tc_tbt)
+		return true;
+
+	/*
+	 * An AUX timeout is expected because we enable TC legacy port aux
+	 * to hold port out of TC cold
+	 */
+	if (INTEL_GEN(dev_priv) == 11 &&
+	    power_well->desc->ops == &icl_tc_phy_aux_power_well_ops) {
+		enum aux_ch aux_ch = icl_tc_phy_aux_ch(dev_priv, power_well);
+		struct intel_digital_port *dig_port = aux_ch_to_digital_port(dev_priv, aux_ch);
+
+		return dig_port->tc_legacy_port;
+	}
+
+	return false;
+}
+
 static void hsw_wait_for_power_well_enable(struct drm_i915_private *dev_priv,
 					   struct i915_power_well *power_well)
 {
@@ -324,8 +376,8 @@
 		DRM_DEBUG_KMS("%s power well enable timeout\n",
 			      power_well->desc->name);
 
-		/* An AUX timeout is expected if the TBT DP tunnel is down. */
-		WARN_ON(!power_well->desc->hsw.is_tc_tbt);
+		WARN_ON(!tc_phy_aux_timeout_expected(dev_priv, power_well));
+
 	}
 }
 
@@ -381,16 +433,16 @@
 				      SKL_FUSE_PG_DIST_STATUS(pg), 1));
 }
 
-static void hsw_power_well_enable(struct drm_i915_private *dev_priv,
-				  struct i915_power_well *power_well)
+static void hsw_power_well_enable_prepare(struct drm_i915_private *dev_priv,
+					  struct i915_power_well *power_well)
 {
 	const struct i915_power_well_regs *regs = power_well->desc->hsw.regs;
 	int pw_idx = power_well->desc->hsw.idx;
-	bool wait_fuses = power_well->desc->hsw.has_fuses;
-	enum skl_power_gate uninitialized_var(pg);
 	u32 val;
 
-	if (wait_fuses) {
+	if (power_well->desc->hsw.has_fuses) {
+		enum skl_power_gate pg;
+
 		pg = INTEL_GEN(dev_priv) >= 11 ? ICL_PW_CTL_IDX_TO_PG(pw_idx) :
 						 SKL_PW_CTL_IDX_TO_PG(pw_idx);
 		/*
@@ -406,25 +458,46 @@
 
 	val = I915_READ(regs->driver);
 	I915_WRITE(regs->driver, val | HSW_PWR_WELL_CTL_REQ(pw_idx));
+}
+
+static void hsw_power_well_enable_complete(struct drm_i915_private *dev_priv,
+					   struct i915_power_well *power_well)
+{
+	int pw_idx = power_well->desc->hsw.idx;
+
 	hsw_wait_for_power_well_enable(dev_priv, power_well);
 
 	/* Display WA #1178: cnl */
 	if (IS_CANNONLAKE(dev_priv) &&
 	    pw_idx >= GLK_PW_CTL_IDX_AUX_B &&
 	    pw_idx <= CNL_PW_CTL_IDX_AUX_F) {
+		u32 val;
+
 		val = I915_READ(CNL_AUX_ANAOVRD1(pw_idx));
 		val |= CNL_AUX_ANAOVRD1_ENABLE | CNL_AUX_ANAOVRD1_LDO_BYPASS;
 		I915_WRITE(CNL_AUX_ANAOVRD1(pw_idx), val);
 	}
 
-	if (wait_fuses)
+	if (power_well->desc->hsw.has_fuses) {
+		enum skl_power_gate pg;
+
+		pg = INTEL_GEN(dev_priv) >= 11 ? ICL_PW_CTL_IDX_TO_PG(pw_idx) :
+						 SKL_PW_CTL_IDX_TO_PG(pw_idx);
 		gen9_wait_for_power_well_fuses(dev_priv, pg);
+	}
 
 	hsw_power_well_post_enable(dev_priv,
 				   power_well->desc->hsw.irq_pipe_mask,
 				   power_well->desc->hsw.has_vga);
 }
 
+static void hsw_power_well_enable(struct drm_i915_private *dev_priv,
+				  struct i915_power_well *power_well)
+{
+	hsw_power_well_enable_prepare(dev_priv, power_well);
+	hsw_power_well_enable_complete(dev_priv, power_well);
+}
+
 static void hsw_power_well_disable(struct drm_i915_private *dev_priv,
 				   struct i915_power_well *power_well)
 {
@@ -497,21 +570,6 @@
 	hsw_wait_for_power_well_disable(dev_priv, power_well);
 }
 
-#define ICL_AUX_PW_TO_CH(pw_idx)	\
-	((pw_idx) - ICL_PW_CTL_IDX_AUX_A + AUX_CH_A)
-
-#define ICL_TBT_AUX_PW_TO_CH(pw_idx)	\
-	((pw_idx) - ICL_PW_CTL_IDX_AUX_TBT1 + AUX_CH_C)
-
-static enum aux_ch icl_tc_phy_aux_ch(struct drm_i915_private *dev_priv,
-				     struct i915_power_well *power_well)
-{
-	int pw_idx = power_well->desc->hsw.idx;
-
-	return power_well->desc->hsw.is_tc_tbt ? ICL_TBT_AUX_PW_TO_CH(pw_idx) :
-						 ICL_AUX_PW_TO_CH(pw_idx);
-}
-
 #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
 
 static u64 async_put_domains_mask(struct i915_power_domains *power_domains);
@@ -528,64 +586,63 @@
 }
 
 static void icl_tc_port_assert_ref_held(struct drm_i915_private *dev_priv,
-					struct i915_power_well *power_well)
+					struct i915_power_well *power_well,
+					struct intel_digital_port *dig_port)
 {
-	enum aux_ch aux_ch = icl_tc_phy_aux_ch(dev_priv, power_well);
-	struct intel_digital_port *dig_port = NULL;
-	struct intel_encoder *encoder;
-
 	/* Bypass the check if all references are released asynchronously */
 	if (power_well_async_ref_count(dev_priv, power_well) ==
 	    power_well->count)
 		return;
 
-	aux_ch = icl_tc_phy_aux_ch(dev_priv, power_well);
-
-	for_each_intel_encoder(&dev_priv->drm, encoder) {
-		enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
-
-		if (!intel_phy_is_tc(dev_priv, phy))
-			continue;
-
-		/* We'll check the MST primary port */
-		if (encoder->type == INTEL_OUTPUT_DP_MST)
-			continue;
-
-		dig_port = enc_to_dig_port(&encoder->base);
-		if (WARN_ON(!dig_port))
-			continue;
-
-		if (dig_port->aux_ch != aux_ch) {
-			dig_port = NULL;
-			continue;
-		}
-
-		break;
-	}
-
 	if (WARN_ON(!dig_port))
 		return;
 
+	if (INTEL_GEN(dev_priv) == 11 && dig_port->tc_legacy_port)
+		return;
+
 	WARN_ON(!intel_tc_port_ref_held(dig_port));
 }
 
 #else
 
 static void icl_tc_port_assert_ref_held(struct drm_i915_private *dev_priv,
-					struct i915_power_well *power_well)
+					struct i915_power_well *power_well,
+					struct intel_digital_port *dig_port)
 {
 }
 
 #endif
 
+static void icl_tc_cold_exit(struct drm_i915_private *i915)
+{
+	int ret, tries = 0;
+
+	while (1) {
+		ret = sandybridge_pcode_write_timeout(i915,
+						      ICL_PCODE_EXIT_TCCOLD,
+						      0, 250, 1);
+		if (ret != -EAGAIN || ++tries == 3)
+			break;
+		msleep(1);
+	}
+
+	/* Spec states that TC cold exit can take up to 1ms to complete */
+	if (!ret)
+		msleep(1);
+
+	/* TODO: turn failure into a error as soon i915 CI updates ICL IFWI */
+	DRM_DEBUG_KMS("TC cold block %s\n", ret ? "failed" : "succeeded");
+}
+
 static void
 icl_tc_phy_aux_power_well_enable(struct drm_i915_private *dev_priv,
 				 struct i915_power_well *power_well)
 {
 	enum aux_ch aux_ch = icl_tc_phy_aux_ch(dev_priv, power_well);
+	struct intel_digital_port *dig_port = aux_ch_to_digital_port(dev_priv, aux_ch);
 	u32 val;
 
-	icl_tc_port_assert_ref_held(dev_priv, power_well);
+	icl_tc_port_assert_ref_held(dev_priv, power_well, dig_port);
 
 	val = I915_READ(DP_AUX_CH_CTL(aux_ch));
 	val &= ~DP_AUX_CH_CTL_TBT_IO;
@@ -593,14 +650,22 @@
 		val |= DP_AUX_CH_CTL_TBT_IO;
 	I915_WRITE(DP_AUX_CH_CTL(aux_ch), val);
 
-	hsw_power_well_enable(dev_priv, power_well);
+	hsw_power_well_enable_prepare(dev_priv, power_well);
+
+	if (INTEL_GEN(dev_priv) == 11 && dig_port->tc_legacy_port)
+		icl_tc_cold_exit(dev_priv);
+
+	hsw_power_well_enable_complete(dev_priv, power_well);
 }
 
 static void
 icl_tc_phy_aux_power_well_disable(struct drm_i915_private *dev_priv,
 				  struct i915_power_well *power_well)
 {
-	icl_tc_port_assert_ref_held(dev_priv, power_well);
+	enum aux_ch aux_ch = icl_tc_phy_aux_ch(dev_priv, power_well);
+	struct intel_digital_port *dig_port = aux_ch_to_digital_port(dev_priv, aux_ch);
+
+	icl_tc_port_assert_ref_held(dev_priv, power_well, dig_port);
 
 	hsw_power_well_disable(dev_priv, power_well);
 }
@@ -1718,15 +1783,12 @@
 static void print_power_domains(struct i915_power_domains *power_domains,
 				const char *prefix, u64 mask)
 {
-	struct drm_i915_private *i915 =
-		container_of(power_domains, struct drm_i915_private,
-			     power_domains);
 	enum intel_display_power_domain domain;
 
 	DRM_DEBUG_DRIVER("%s (%lu):\n", prefix, hweight64(mask));
 	for_each_power_domain(domain, mask)
 		DRM_DEBUG_DRIVER("%s use_count %d\n",
-				 intel_display_power_domain_str(i915, domain),
+				 intel_display_power_domain_str(domain),
 				 power_domains->domain_use_count[domain]);
 }
 
@@ -1896,7 +1958,7 @@
 {
 	struct i915_power_domains *power_domains;
 	struct i915_power_well *power_well;
-	const char *name = intel_display_power_domain_str(dev_priv, domain);
+	const char *name = intel_display_power_domain_str(domain);
 
 	power_domains = &dev_priv->power_domains;
 
@@ -2487,10 +2549,10 @@
 	BIT_ULL(POWER_DOMAIN_AUX_D) |			\
 	BIT_ULL(POWER_DOMAIN_AUX_E) |			\
 	BIT_ULL(POWER_DOMAIN_AUX_F) |			\
-	BIT_ULL(POWER_DOMAIN_AUX_TBT1) |		\
-	BIT_ULL(POWER_DOMAIN_AUX_TBT2) |		\
-	BIT_ULL(POWER_DOMAIN_AUX_TBT3) |		\
-	BIT_ULL(POWER_DOMAIN_AUX_TBT4) |		\
+	BIT_ULL(POWER_DOMAIN_AUX_C_TBT) |		\
+	BIT_ULL(POWER_DOMAIN_AUX_D_TBT) |		\
+	BIT_ULL(POWER_DOMAIN_AUX_E_TBT) |		\
+	BIT_ULL(POWER_DOMAIN_AUX_F_TBT) |		\
 	BIT_ULL(POWER_DOMAIN_VGA) |			\
 	BIT_ULL(POWER_DOMAIN_AUDIO) |			\
 	BIT_ULL(POWER_DOMAIN_INIT))
@@ -2530,22 +2592,22 @@
 	BIT_ULL(POWER_DOMAIN_AUX_A))
 #define ICL_AUX_B_IO_POWER_DOMAINS (			\
 	BIT_ULL(POWER_DOMAIN_AUX_B))
-#define ICL_AUX_C_IO_POWER_DOMAINS (			\
+#define ICL_AUX_C_TC1_IO_POWER_DOMAINS (		\
 	BIT_ULL(POWER_DOMAIN_AUX_C))
-#define ICL_AUX_D_IO_POWER_DOMAINS (			\
+#define ICL_AUX_D_TC2_IO_POWER_DOMAINS (		\
 	BIT_ULL(POWER_DOMAIN_AUX_D))
-#define ICL_AUX_E_IO_POWER_DOMAINS (			\
+#define ICL_AUX_E_TC3_IO_POWER_DOMAINS (		\
 	BIT_ULL(POWER_DOMAIN_AUX_E))
-#define ICL_AUX_F_IO_POWER_DOMAINS (			\
+#define ICL_AUX_F_TC4_IO_POWER_DOMAINS (		\
 	BIT_ULL(POWER_DOMAIN_AUX_F))
-#define ICL_AUX_TBT1_IO_POWER_DOMAINS (			\
-	BIT_ULL(POWER_DOMAIN_AUX_TBT1))
-#define ICL_AUX_TBT2_IO_POWER_DOMAINS (			\
-	BIT_ULL(POWER_DOMAIN_AUX_TBT2))
-#define ICL_AUX_TBT3_IO_POWER_DOMAINS (			\
-	BIT_ULL(POWER_DOMAIN_AUX_TBT3))
-#define ICL_AUX_TBT4_IO_POWER_DOMAINS (			\
-	BIT_ULL(POWER_DOMAIN_AUX_TBT4))
+#define ICL_AUX_C_TBT1_IO_POWER_DOMAINS (		\
+	BIT_ULL(POWER_DOMAIN_AUX_C_TBT))
+#define ICL_AUX_D_TBT2_IO_POWER_DOMAINS (		\
+	BIT_ULL(POWER_DOMAIN_AUX_D_TBT))
+#define ICL_AUX_E_TBT3_IO_POWER_DOMAINS (		\
+	BIT_ULL(POWER_DOMAIN_AUX_E_TBT))
+#define ICL_AUX_F_TBT4_IO_POWER_DOMAINS (		\
+	BIT_ULL(POWER_DOMAIN_AUX_F_TBT))
 
 #define TGL_PW_5_POWER_DOMAINS (			\
 	BIT_ULL(POWER_DOMAIN_PIPE_D) |			\
@@ -2565,24 +2627,24 @@
 	BIT_ULL(POWER_DOMAIN_PIPE_B) |			\
 	BIT_ULL(POWER_DOMAIN_TRANSCODER_B) |		\
 	BIT_ULL(POWER_DOMAIN_PIPE_B_PANEL_FITTER) |	\
-	BIT_ULL(POWER_DOMAIN_PORT_DDI_TC1_LANES) |	\
-	BIT_ULL(POWER_DOMAIN_PORT_DDI_TC2_LANES) |	\
-	BIT_ULL(POWER_DOMAIN_PORT_DDI_TC3_LANES) |	\
-	BIT_ULL(POWER_DOMAIN_PORT_DDI_TC4_LANES) |	\
-	BIT_ULL(POWER_DOMAIN_PORT_DDI_TC5_LANES) |	\
-	BIT_ULL(POWER_DOMAIN_PORT_DDI_TC6_LANES) |	\
-	BIT_ULL(POWER_DOMAIN_AUX_TC1) |		\
-	BIT_ULL(POWER_DOMAIN_AUX_TC2) |		\
-	BIT_ULL(POWER_DOMAIN_AUX_TC3) |		\
-	BIT_ULL(POWER_DOMAIN_AUX_TC4) |		\
-	BIT_ULL(POWER_DOMAIN_AUX_TC5) |		\
-	BIT_ULL(POWER_DOMAIN_AUX_TC6) |		\
-	BIT_ULL(POWER_DOMAIN_AUX_TBT1) |		\
-	BIT_ULL(POWER_DOMAIN_AUX_TBT2) |		\
-	BIT_ULL(POWER_DOMAIN_AUX_TBT3) |		\
-	BIT_ULL(POWER_DOMAIN_AUX_TBT4) |		\
-	BIT_ULL(POWER_DOMAIN_AUX_TBT5) |		\
-	BIT_ULL(POWER_DOMAIN_AUX_TBT6) |		\
+	BIT_ULL(POWER_DOMAIN_PORT_DDI_D_LANES) |	\
+	BIT_ULL(POWER_DOMAIN_PORT_DDI_E_LANES) |	\
+	BIT_ULL(POWER_DOMAIN_PORT_DDI_F_LANES) |	\
+	BIT_ULL(POWER_DOMAIN_PORT_DDI_G_LANES) |	\
+	BIT_ULL(POWER_DOMAIN_PORT_DDI_H_LANES) |	\
+	BIT_ULL(POWER_DOMAIN_PORT_DDI_I_LANES) |	\
+	BIT_ULL(POWER_DOMAIN_AUX_D) |			\
+	BIT_ULL(POWER_DOMAIN_AUX_E) |			\
+	BIT_ULL(POWER_DOMAIN_AUX_F) |			\
+	BIT_ULL(POWER_DOMAIN_AUX_G) |			\
+	BIT_ULL(POWER_DOMAIN_AUX_H) |			\
+	BIT_ULL(POWER_DOMAIN_AUX_I) |			\
+	BIT_ULL(POWER_DOMAIN_AUX_D_TBT) |		\
+	BIT_ULL(POWER_DOMAIN_AUX_E_TBT) |		\
+	BIT_ULL(POWER_DOMAIN_AUX_F_TBT) |		\
+	BIT_ULL(POWER_DOMAIN_AUX_G_TBT) |		\
+	BIT_ULL(POWER_DOMAIN_AUX_H_TBT) |		\
+	BIT_ULL(POWER_DOMAIN_AUX_I_TBT) |		\
 	BIT_ULL(POWER_DOMAIN_VGA) |			\
 	BIT_ULL(POWER_DOMAIN_AUDIO) |			\
 	BIT_ULL(POWER_DOMAIN_INIT))
@@ -2598,35 +2660,65 @@
 	BIT_ULL(POWER_DOMAIN_AUX_A) |			\
 	BIT_ULL(POWER_DOMAIN_INIT))
 
-#define TGL_DDI_IO_TC1_POWER_DOMAINS (		\
-	BIT_ULL(POWER_DOMAIN_PORT_DDI_TC1_IO))
-#define TGL_DDI_IO_TC2_POWER_DOMAINS (		\
-	BIT_ULL(POWER_DOMAIN_PORT_DDI_TC2_IO))
-#define TGL_DDI_IO_TC3_POWER_DOMAINS (		\
-	BIT_ULL(POWER_DOMAIN_PORT_DDI_TC3_IO))
-#define TGL_DDI_IO_TC4_POWER_DOMAINS (		\
-	BIT_ULL(POWER_DOMAIN_PORT_DDI_TC4_IO))
-#define TGL_DDI_IO_TC5_POWER_DOMAINS (		\
-	BIT_ULL(POWER_DOMAIN_PORT_DDI_TC5_IO))
-#define TGL_DDI_IO_TC6_POWER_DOMAINS (		\
-	BIT_ULL(POWER_DOMAIN_PORT_DDI_TC6_IO))
-
-#define TGL_AUX_TC1_IO_POWER_DOMAINS (		\
-	BIT_ULL(POWER_DOMAIN_AUX_TC1))
-#define TGL_AUX_TC2_IO_POWER_DOMAINS (		\
-	BIT_ULL(POWER_DOMAIN_AUX_TC2))
-#define TGL_AUX_TC3_IO_POWER_DOMAINS (		\
-	BIT_ULL(POWER_DOMAIN_AUX_TC3))
-#define TGL_AUX_TC4_IO_POWER_DOMAINS (		\
-	BIT_ULL(POWER_DOMAIN_AUX_TC4))
-#define TGL_AUX_TC5_IO_POWER_DOMAINS (		\
-	BIT_ULL(POWER_DOMAIN_AUX_TC5))
-#define TGL_AUX_TC6_IO_POWER_DOMAINS (		\
-	BIT_ULL(POWER_DOMAIN_AUX_TC6))
-#define TGL_AUX_TBT5_IO_POWER_DOMAINS (		\
-	BIT_ULL(POWER_DOMAIN_AUX_TBT5))
-#define TGL_AUX_TBT6_IO_POWER_DOMAINS (		\
-	BIT_ULL(POWER_DOMAIN_AUX_TBT6))
+#define TGL_DDI_IO_D_TC1_POWER_DOMAINS (	\
+	BIT_ULL(POWER_DOMAIN_PORT_DDI_D_IO))
+#define TGL_DDI_IO_E_TC2_POWER_DOMAINS (	\
+	BIT_ULL(POWER_DOMAIN_PORT_DDI_E_IO))
+#define TGL_DDI_IO_F_TC3_POWER_DOMAINS (	\
+	BIT_ULL(POWER_DOMAIN_PORT_DDI_F_IO))
+#define TGL_DDI_IO_G_TC4_POWER_DOMAINS (	\
+	BIT_ULL(POWER_DOMAIN_PORT_DDI_G_IO))
+#define TGL_DDI_IO_H_TC5_POWER_DOMAINS (	\
+	BIT_ULL(POWER_DOMAIN_PORT_DDI_H_IO))
+#define TGL_DDI_IO_I_TC6_POWER_DOMAINS (	\
+	BIT_ULL(POWER_DOMAIN_PORT_DDI_I_IO))
+
+#define TGL_AUX_A_IO_POWER_DOMAINS (		\
+	BIT_ULL(POWER_DOMAIN_AUX_IO_A) |	\
+	BIT_ULL(POWER_DOMAIN_AUX_A))
+#define TGL_AUX_B_IO_POWER_DOMAINS (		\
+	BIT_ULL(POWER_DOMAIN_AUX_B))
+#define TGL_AUX_C_IO_POWER_DOMAINS (		\
+	BIT_ULL(POWER_DOMAIN_AUX_C))
+#define TGL_AUX_D_TC1_IO_POWER_DOMAINS (	\
+	BIT_ULL(POWER_DOMAIN_AUX_D))
+#define TGL_AUX_E_TC2_IO_POWER_DOMAINS (	\
+	BIT_ULL(POWER_DOMAIN_AUX_E))
+#define TGL_AUX_F_TC3_IO_POWER_DOMAINS (	\
+	BIT_ULL(POWER_DOMAIN_AUX_F))
+#define TGL_AUX_G_TC4_IO_POWER_DOMAINS (	\
+	BIT_ULL(POWER_DOMAIN_AUX_G))
+#define TGL_AUX_H_TC5_IO_POWER_DOMAINS (	\
+	BIT_ULL(POWER_DOMAIN_AUX_H))
+#define TGL_AUX_I_TC6_IO_POWER_DOMAINS (	\
+	BIT_ULL(POWER_DOMAIN_AUX_I))
+#define TGL_AUX_D_TBT1_IO_POWER_DOMAINS (	\
+	BIT_ULL(POWER_DOMAIN_AUX_D_TBT))
+#define TGL_AUX_E_TBT2_IO_POWER_DOMAINS (	\
+	BIT_ULL(POWER_DOMAIN_AUX_E_TBT))
+#define TGL_AUX_F_TBT3_IO_POWER_DOMAINS (	\
+	BIT_ULL(POWER_DOMAIN_AUX_F_TBT))
+#define TGL_AUX_G_TBT4_IO_POWER_DOMAINS (	\
+	BIT_ULL(POWER_DOMAIN_AUX_G_TBT))
+#define TGL_AUX_H_TBT5_IO_POWER_DOMAINS (	\
+	BIT_ULL(POWER_DOMAIN_AUX_H_TBT))
+#define TGL_AUX_I_TBT6_IO_POWER_DOMAINS (	\
+	BIT_ULL(POWER_DOMAIN_AUX_I_TBT))
+
+#define TGL_TC_COLD_OFF_POWER_DOMAINS (		\
+	BIT_ULL(POWER_DOMAIN_AUX_D)	|	\
+	BIT_ULL(POWER_DOMAIN_AUX_E)	|	\
+	BIT_ULL(POWER_DOMAIN_AUX_F)	|	\
+	BIT_ULL(POWER_DOMAIN_AUX_G)	|	\
+	BIT_ULL(POWER_DOMAIN_AUX_H)	|	\
+	BIT_ULL(POWER_DOMAIN_AUX_I)	|	\
+	BIT_ULL(POWER_DOMAIN_AUX_D_TBT)	|	\
+	BIT_ULL(POWER_DOMAIN_AUX_E_TBT)	|	\
+	BIT_ULL(POWER_DOMAIN_AUX_F_TBT)	|	\
+	BIT_ULL(POWER_DOMAIN_AUX_G_TBT)	|	\
+	BIT_ULL(POWER_DOMAIN_AUX_H_TBT)	|	\
+	BIT_ULL(POWER_DOMAIN_AUX_I_TBT)	|	\
+	BIT_ULL(POWER_DOMAIN_TC_COLD_OFF))
 
 static const struct i915_power_well_ops i9xx_always_on_power_well_ops = {
 	.sync_hw = i9xx_power_well_sync_hw_noop,
@@ -3484,8 +3576,8 @@
 		},
 	},
 	{
-		.name = "AUX C",
-		.domains = ICL_AUX_C_IO_POWER_DOMAINS,
+		.name = "AUX C TC1",
+		.domains = ICL_AUX_C_TC1_IO_POWER_DOMAINS,
 		.ops = &icl_tc_phy_aux_power_well_ops,
 		.id = DISP_PW_ID_NONE,
 		{
@@ -3495,8 +3587,8 @@
 		},
 	},
 	{
-		.name = "AUX D",
-		.domains = ICL_AUX_D_IO_POWER_DOMAINS,
+		.name = "AUX D TC2",
+		.domains = ICL_AUX_D_TC2_IO_POWER_DOMAINS,
 		.ops = &icl_tc_phy_aux_power_well_ops,
 		.id = DISP_PW_ID_NONE,
 		{
@@ -3506,8 +3598,8 @@
 		},
 	},
 	{
-		.name = "AUX E",
-		.domains = ICL_AUX_E_IO_POWER_DOMAINS,
+		.name = "AUX E TC3",
+		.domains = ICL_AUX_E_TC3_IO_POWER_DOMAINS,
 		.ops = &icl_tc_phy_aux_power_well_ops,
 		.id = DISP_PW_ID_NONE,
 		{
@@ -3517,8 +3609,8 @@
 		},
 	},
 	{
-		.name = "AUX F",
-		.domains = ICL_AUX_F_IO_POWER_DOMAINS,
+		.name = "AUX F TC4",
+		.domains = ICL_AUX_F_TC4_IO_POWER_DOMAINS,
 		.ops = &icl_tc_phy_aux_power_well_ops,
 		.id = DISP_PW_ID_NONE,
 		{
@@ -3528,8 +3620,8 @@
 		},
 	},
 	{
-		.name = "AUX TBT1",
-		.domains = ICL_AUX_TBT1_IO_POWER_DOMAINS,
+		.name = "AUX C TBT1",
+		.domains = ICL_AUX_C_TBT1_IO_POWER_DOMAINS,
 		.ops = &icl_tc_phy_aux_power_well_ops,
 		.id = DISP_PW_ID_NONE,
 		{
@@ -3539,8 +3631,8 @@
 		},
 	},
 	{
-		.name = "AUX TBT2",
-		.domains = ICL_AUX_TBT2_IO_POWER_DOMAINS,
+		.name = "AUX D TBT2",
+		.domains = ICL_AUX_D_TBT2_IO_POWER_DOMAINS,
 		.ops = &icl_tc_phy_aux_power_well_ops,
 		.id = DISP_PW_ID_NONE,
 		{
@@ -3550,8 +3642,8 @@
 		},
 	},
 	{
-		.name = "AUX TBT3",
-		.domains = ICL_AUX_TBT3_IO_POWER_DOMAINS,
+		.name = "AUX E TBT3",
+		.domains = ICL_AUX_E_TBT3_IO_POWER_DOMAINS,
 		.ops = &icl_tc_phy_aux_power_well_ops,
 		.id = DISP_PW_ID_NONE,
 		{
@@ -3561,8 +3653,8 @@
 		},
 	},
 	{
-		.name = "AUX TBT4",
-		.domains = ICL_AUX_TBT4_IO_POWER_DOMAINS,
+		.name = "AUX F TBT4",
+		.domains = ICL_AUX_F_TBT4_IO_POWER_DOMAINS,
 		.ops = &icl_tc_phy_aux_power_well_ops,
 		.id = DISP_PW_ID_NONE,
 		{
@@ -3585,6 +3677,89 @@
 	},
 };
 
+static void
+tgl_tc_cold_request(struct drm_i915_private *i915, bool block)
+{
+	u8 tries = 0;
+	int ret;
+
+	while (1) {
+		u32 low_val = 0, high_val;
+
+		if (block)
+			high_val = TGL_PCODE_EXIT_TCCOLD_DATA_H_BLOCK_REQ;
+		else
+			high_val = TGL_PCODE_EXIT_TCCOLD_DATA_H_UNBLOCK_REQ;
+
+		/*
+		 * Spec states that we should timeout the request after 200us
+		 * but the function below will timeout after 500us
+		 */
+		ret = sandybridge_pcode_read(i915, TGL_PCODE_TCCOLD, &low_val,
+					     &high_val);
+		if (ret == 0) {
+			if (block &&
+			    (low_val & TGL_PCODE_EXIT_TCCOLD_DATA_L_EXIT_FAILED))
+				ret = -EIO;
+			else
+				break;
+		}
+
+		if (++tries == 3)
+			break;
+
+		if (ret == -EAGAIN)
+			msleep(1);
+	}
+
+	if (ret)
+		DRM_ERROR("TC cold %sblock failed\n", block ? "" : "un");
+	else
+		DRM_DEBUG_KMS("TC cold %sblock succeeded\n", block ? "" : "un");
+}
+
+static void
+tgl_tc_cold_off_power_well_enable(struct drm_i915_private *i915,
+				  struct i915_power_well *power_well)
+{
+	tgl_tc_cold_request(i915, true);
+}
+
+static void
+tgl_tc_cold_off_power_well_disable(struct drm_i915_private *i915,
+				   struct i915_power_well *power_well)
+{
+	tgl_tc_cold_request(i915, false);
+}
+
+static void
+tgl_tc_cold_off_power_well_sync_hw(struct drm_i915_private *i915,
+				   struct i915_power_well *power_well)
+{
+	if (power_well->count > 0)
+		tgl_tc_cold_off_power_well_enable(i915, power_well);
+	else
+		tgl_tc_cold_off_power_well_disable(i915, power_well);
+}
+
+static bool
+tgl_tc_cold_off_power_well_is_enabled(struct drm_i915_private *dev_priv,
+				      struct i915_power_well *power_well)
+{
+	/*
+	 * Not the correctly implementation but there is no way to just read it
+	 * from PCODE, so returning count to avoid state mismatch errors
+	 */
+	return power_well->count;
+}
+
+static const struct i915_power_well_ops tgl_tc_cold_off_ops = {
+	.sync_hw = tgl_tc_cold_off_power_well_sync_hw,
+	.enable = tgl_tc_cold_off_power_well_enable,
+	.disable = tgl_tc_cold_off_power_well_disable,
+	.is_enabled = tgl_tc_cold_off_power_well_is_enabled,
+};
+
 static const struct i915_power_well_desc tgl_power_wells[] = {
 	{
 		.name = "always-on",
@@ -3667,8 +3842,8 @@
 		}
 	},
 	{
-		.name = "DDI TC1 IO",
-		.domains = TGL_DDI_IO_TC1_POWER_DOMAINS,
+		.name = "DDI D TC1 IO",
+		.domains = TGL_DDI_IO_D_TC1_POWER_DOMAINS,
 		.ops = &hsw_power_well_ops,
 		.id = DISP_PW_ID_NONE,
 		{
@@ -3677,8 +3852,8 @@
 		},
 	},
 	{
-		.name = "DDI TC2 IO",
-		.domains = TGL_DDI_IO_TC2_POWER_DOMAINS,
+		.name = "DDI E TC2 IO",
+		.domains = TGL_DDI_IO_E_TC2_POWER_DOMAINS,
 		.ops = &hsw_power_well_ops,
 		.id = DISP_PW_ID_NONE,
 		{
@@ -3687,8 +3862,8 @@
 		},
 	},
 	{
-		.name = "DDI TC3 IO",
-		.domains = TGL_DDI_IO_TC3_POWER_DOMAINS,
+		.name = "DDI F TC3 IO",
+		.domains = TGL_DDI_IO_F_TC3_POWER_DOMAINS,
 		.ops = &hsw_power_well_ops,
 		.id = DISP_PW_ID_NONE,
 		{
@@ -3697,8 +3872,8 @@
 		},
 	},
 	{
-		.name = "DDI TC4 IO",
-		.domains = TGL_DDI_IO_TC4_POWER_DOMAINS,
+		.name = "DDI G TC4 IO",
+		.domains = TGL_DDI_IO_G_TC4_POWER_DOMAINS,
 		.ops = &hsw_power_well_ops,
 		.id = DISP_PW_ID_NONE,
 		{
@@ -3707,8 +3882,8 @@
 		},
 	},
 	{
-		.name = "DDI TC5 IO",
-		.domains = TGL_DDI_IO_TC5_POWER_DOMAINS,
+		.name = "DDI H TC5 IO",
+		.domains = TGL_DDI_IO_H_TC5_POWER_DOMAINS,
 		.ops = &hsw_power_well_ops,
 		.id = DISP_PW_ID_NONE,
 		{
@@ -3717,8 +3892,8 @@
 		},
 	},
 	{
-		.name = "DDI TC6 IO",
-		.domains = TGL_DDI_IO_TC6_POWER_DOMAINS,
+		.name = "DDI I TC6 IO",
+		.domains = TGL_DDI_IO_I_TC6_POWER_DOMAINS,
 		.ops = &hsw_power_well_ops,
 		.id = DISP_PW_ID_NONE,
 		{
@@ -3728,7 +3903,7 @@
 	},
 	{
 		.name = "AUX A",
-		.domains = ICL_AUX_A_IO_POWER_DOMAINS,
+		.domains = TGL_AUX_A_IO_POWER_DOMAINS,
 		.ops = &icl_combo_phy_aux_power_well_ops,
 		.id = DISP_PW_ID_NONE,
 		{
@@ -3738,7 +3913,7 @@
 	},
 	{
 		.name = "AUX B",
-		.domains = ICL_AUX_B_IO_POWER_DOMAINS,
+		.domains = TGL_AUX_B_IO_POWER_DOMAINS,
 		.ops = &icl_combo_phy_aux_power_well_ops,
 		.id = DISP_PW_ID_NONE,
 		{
@@ -3748,7 +3923,7 @@
 	},
 	{
 		.name = "AUX C",
-		.domains = ICL_AUX_C_IO_POWER_DOMAINS,
+		.domains = TGL_AUX_C_IO_POWER_DOMAINS,
 		.ops = &icl_combo_phy_aux_power_well_ops,
 		.id = DISP_PW_ID_NONE,
 		{
@@ -3757,8 +3932,8 @@
 		},
 	},
 	{
-		.name = "AUX TC1",
-		.domains = TGL_AUX_TC1_IO_POWER_DOMAINS,
+		.name = "AUX D TC1",
+		.domains = TGL_AUX_D_TC1_IO_POWER_DOMAINS,
 		.ops = &icl_tc_phy_aux_power_well_ops,
 		.id = DISP_PW_ID_NONE,
 		{
@@ -3768,8 +3943,8 @@
 		},
 	},
 	{
-		.name = "AUX TC2",
-		.domains = TGL_AUX_TC2_IO_POWER_DOMAINS,
+		.name = "AUX E TC2",
+		.domains = TGL_AUX_E_TC2_IO_POWER_DOMAINS,
 		.ops = &icl_tc_phy_aux_power_well_ops,
 		.id = DISP_PW_ID_NONE,
 		{
@@ -3779,8 +3954,8 @@
 		},
 	},
 	{
-		.name = "AUX TC3",
-		.domains = TGL_AUX_TC3_IO_POWER_DOMAINS,
+		.name = "AUX F TC3",
+		.domains = TGL_AUX_F_TC3_IO_POWER_DOMAINS,
 		.ops = &icl_tc_phy_aux_power_well_ops,
 		.id = DISP_PW_ID_NONE,
 		{
@@ -3790,8 +3965,8 @@
 		},
 	},
 	{
-		.name = "AUX TC4",
-		.domains = TGL_AUX_TC4_IO_POWER_DOMAINS,
+		.name = "AUX G TC4",
+		.domains = TGL_AUX_G_TC4_IO_POWER_DOMAINS,
 		.ops = &icl_tc_phy_aux_power_well_ops,
 		.id = DISP_PW_ID_NONE,
 		{
@@ -3801,8 +3976,8 @@
 		},
 	},
 	{
-		.name = "AUX TC5",
-		.domains = TGL_AUX_TC5_IO_POWER_DOMAINS,
+		.name = "AUX H TC5",
+		.domains = TGL_AUX_H_TC5_IO_POWER_DOMAINS,
 		.ops = &icl_tc_phy_aux_power_well_ops,
 		.id = DISP_PW_ID_NONE,
 		{
@@ -3812,8 +3987,8 @@
 		},
 	},
 	{
-		.name = "AUX TC6",
-		.domains = TGL_AUX_TC6_IO_POWER_DOMAINS,
+		.name = "AUX I TC6",
+		.domains = TGL_AUX_I_TC6_IO_POWER_DOMAINS,
 		.ops = &icl_tc_phy_aux_power_well_ops,
 		.id = DISP_PW_ID_NONE,
 		{
@@ -3823,8 +3998,8 @@
 		},
 	},
 	{
-		.name = "AUX TBT1",
-		.domains = ICL_AUX_TBT1_IO_POWER_DOMAINS,
+		.name = "AUX D TBT1",
+		.domains = TGL_AUX_D_TBT1_IO_POWER_DOMAINS,
 		.ops = &hsw_power_well_ops,
 		.id = DISP_PW_ID_NONE,
 		{
@@ -3834,8 +4009,8 @@
 		},
 	},
 	{
-		.name = "AUX TBT2",
-		.domains = ICL_AUX_TBT2_IO_POWER_DOMAINS,
+		.name = "AUX E TBT2",
+		.domains = TGL_AUX_E_TBT2_IO_POWER_DOMAINS,
 		.ops = &hsw_power_well_ops,
 		.id = DISP_PW_ID_NONE,
 		{
@@ -3845,8 +4020,8 @@
 		},
 	},
 	{
-		.name = "AUX TBT3",
-		.domains = ICL_AUX_TBT3_IO_POWER_DOMAINS,
+		.name = "AUX F TBT3",
+		.domains = TGL_AUX_F_TBT3_IO_POWER_DOMAINS,
 		.ops = &hsw_power_well_ops,
 		.id = DISP_PW_ID_NONE,
 		{
@@ -3856,8 +4031,8 @@
 		},
 	},
 	{
-		.name = "AUX TBT4",
-		.domains = ICL_AUX_TBT4_IO_POWER_DOMAINS,
+		.name = "AUX G TBT4",
+		.domains = TGL_AUX_G_TBT4_IO_POWER_DOMAINS,
 		.ops = &hsw_power_well_ops,
 		.id = DISP_PW_ID_NONE,
 		{
@@ -3867,8 +4042,8 @@
 		},
 	},
 	{
-		.name = "AUX TBT5",
-		.domains = TGL_AUX_TBT5_IO_POWER_DOMAINS,
+		.name = "AUX H TBT5",
+		.domains = TGL_AUX_H_TBT5_IO_POWER_DOMAINS,
 		.ops = &hsw_power_well_ops,
 		.id = DISP_PW_ID_NONE,
 		{
@@ -3878,8 +4053,8 @@
 		},
 	},
 	{
-		.name = "AUX TBT6",
-		.domains = TGL_AUX_TBT6_IO_POWER_DOMAINS,
+		.name = "AUX I TBT6",
+		.domains = TGL_AUX_I_TBT6_IO_POWER_DOMAINS,
 		.ops = &hsw_power_well_ops,
 		.id = DISP_PW_ID_NONE,
 		{
@@ -3912,6 +4087,12 @@
 			.hsw.irq_pipe_mask = BIT(PIPE_D),
 		},
 	},
+	{
+		.name = "TC cold off",
+		.domains = TGL_TC_COLD_OFF_POWER_DOMAINS,
+		.ops = &tgl_tc_cold_off_ops,
+		.id = DISP_PW_ID_NONE,
+	},
 };
 
 static int
@@ -4205,13 +4386,19 @@
 
 static void icl_mbus_init(struct drm_i915_private *dev_priv)
 {
-	u32 val;
+	u32 mask, val;
 
-	val = MBUS_ABOX_BT_CREDIT_POOL1(16) |
-	      MBUS_ABOX_BT_CREDIT_POOL2(16) |
-	      MBUS_ABOX_B_CREDIT(1) |
-	      MBUS_ABOX_BW_CREDIT(1);
+	mask = MBUS_ABOX_BT_CREDIT_POOL1_MASK |
+		MBUS_ABOX_BT_CREDIT_POOL2_MASK |
+		MBUS_ABOX_B_CREDIT_MASK |
+		MBUS_ABOX_BW_CREDIT_MASK;
 
+	val = I915_READ(MBUS_ABOX_CTL);
+	val &= ~mask;
+	val |= MBUS_ABOX_BT_CREDIT_POOL1(16) |
+		MBUS_ABOX_BT_CREDIT_POOL2(16) |
+		MBUS_ABOX_B_CREDIT(1) |
+		MBUS_ABOX_BW_CREDIT(1);
 	I915_WRITE(MBUS_ABOX_CTL, val);
 }
 
@@ -5107,8 +5294,7 @@
 
 		for_each_power_domain(domain, power_well->desc->domains)
 			DRM_DEBUG_DRIVER("  %-23s %d\n",
-					 intel_display_power_domain_str(i915,
-									domain),
+					 intel_display_power_domain_str(domain),
 					 power_domains->domain_use_count[domain]);
 	}
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/display/intel_display_power.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/display/intel_display_power.h
@@ -36,29 +36,20 @@
 	POWER_DOMAIN_PORT_DDI_B_LANES,
 	POWER_DOMAIN_PORT_DDI_C_LANES,
 	POWER_DOMAIN_PORT_DDI_D_LANES,
-	POWER_DOMAIN_PORT_DDI_TC1_LANES = POWER_DOMAIN_PORT_DDI_D_LANES,
 	POWER_DOMAIN_PORT_DDI_E_LANES,
-	POWER_DOMAIN_PORT_DDI_TC2_LANES = POWER_DOMAIN_PORT_DDI_E_LANES,
 	POWER_DOMAIN_PORT_DDI_F_LANES,
-	POWER_DOMAIN_PORT_DDI_TC3_LANES = POWER_DOMAIN_PORT_DDI_F_LANES,
-	POWER_DOMAIN_PORT_DDI_TC4_LANES,
-	POWER_DOMAIN_PORT_DDI_TC5_LANES,
-	POWER_DOMAIN_PORT_DDI_TC6_LANES,
+	POWER_DOMAIN_PORT_DDI_G_LANES,
+	POWER_DOMAIN_PORT_DDI_H_LANES,
+	POWER_DOMAIN_PORT_DDI_I_LANES,
 	POWER_DOMAIN_PORT_DDI_A_IO,
 	POWER_DOMAIN_PORT_DDI_B_IO,
 	POWER_DOMAIN_PORT_DDI_C_IO,
 	POWER_DOMAIN_PORT_DDI_D_IO,
-	POWER_DOMAIN_PORT_DDI_TC1_IO = POWER_DOMAIN_PORT_DDI_D_IO,
 	POWER_DOMAIN_PORT_DDI_E_IO,
-	POWER_DOMAIN_PORT_DDI_TC2_IO = POWER_DOMAIN_PORT_DDI_E_IO,
 	POWER_DOMAIN_PORT_DDI_F_IO,
-	POWER_DOMAIN_PORT_DDI_TC3_IO = POWER_DOMAIN_PORT_DDI_F_IO,
 	POWER_DOMAIN_PORT_DDI_G_IO,
-	POWER_DOMAIN_PORT_DDI_TC4_IO = POWER_DOMAIN_PORT_DDI_G_IO,
 	POWER_DOMAIN_PORT_DDI_H_IO,
-	POWER_DOMAIN_PORT_DDI_TC5_IO = POWER_DOMAIN_PORT_DDI_H_IO,
 	POWER_DOMAIN_PORT_DDI_I_IO,
-	POWER_DOMAIN_PORT_DDI_TC6_IO = POWER_DOMAIN_PORT_DDI_I_IO,
 	POWER_DOMAIN_PORT_DSI,
 	POWER_DOMAIN_PORT_CRT,
 	POWER_DOMAIN_PORT_OTHER,
@@ -68,25 +59,24 @@
 	POWER_DOMAIN_AUX_B,
 	POWER_DOMAIN_AUX_C,
 	POWER_DOMAIN_AUX_D,
-	POWER_DOMAIN_AUX_TC1 = POWER_DOMAIN_AUX_D,
 	POWER_DOMAIN_AUX_E,
-	POWER_DOMAIN_AUX_TC2 = POWER_DOMAIN_AUX_E,
 	POWER_DOMAIN_AUX_F,
-	POWER_DOMAIN_AUX_TC3 = POWER_DOMAIN_AUX_F,
-	POWER_DOMAIN_AUX_TC4,
-	POWER_DOMAIN_AUX_TC5,
-	POWER_DOMAIN_AUX_TC6,
+	POWER_DOMAIN_AUX_G,
+	POWER_DOMAIN_AUX_H,
+	POWER_DOMAIN_AUX_I,
 	POWER_DOMAIN_AUX_IO_A,
-	POWER_DOMAIN_AUX_TBT1,
-	POWER_DOMAIN_AUX_TBT2,
-	POWER_DOMAIN_AUX_TBT3,
-	POWER_DOMAIN_AUX_TBT4,
-	POWER_DOMAIN_AUX_TBT5,
-	POWER_DOMAIN_AUX_TBT6,
+	POWER_DOMAIN_AUX_C_TBT,
+	POWER_DOMAIN_AUX_D_TBT,
+	POWER_DOMAIN_AUX_E_TBT,
+	POWER_DOMAIN_AUX_F_TBT,
+	POWER_DOMAIN_AUX_G_TBT,
+	POWER_DOMAIN_AUX_H_TBT,
+	POWER_DOMAIN_AUX_I_TBT,
 	POWER_DOMAIN_GMBUS,
 	POWER_DOMAIN_MODESET,
 	POWER_DOMAIN_GT_IRQ,
 	POWER_DOMAIN_DPLL_DC_OFF,
+	POWER_DOMAIN_TC_COLD_OFF,
 	POWER_DOMAIN_INIT,
 
 	POWER_DOMAIN_NUM,
@@ -269,8 +259,7 @@
 void intel_display_power_resume(struct drm_i915_private *i915);
 
 const char *
-intel_display_power_domain_str(struct drm_i915_private *i915,
-			       enum intel_display_power_domain domain);
+intel_display_power_domain_str(enum intel_display_power_domain domain);
 
 bool intel_display_power_is_enabled(struct drm_i915_private *dev_priv,
 				    enum intel_display_power_domain domain);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/display/intel_display_types.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -214,6 +214,9 @@
 		u8 controller;		/* bxt+ only */
 		struct pwm_device *pwm;
 
+		/* DPCD backlight */
+		u8 pwmgen_bit_count;
+
 		struct backlight_device *device;
 
 		/* Connector and platform specific backlight functions */
@@ -1176,6 +1179,7 @@
 	int max_link_rate;
 	/* sink or branch descriptor */
 	struct drm_dp_desc desc;
+	u32 edid_quirks;
 	struct drm_dp_aux aux;
 	u8 train_set[4];
 	int panel_power_up_delay;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/display/intel_dp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/display/intel_dp.c
@@ -166,6 +166,12 @@
 				      enum pipe pipe);
 static void intel_dp_unset_edid(struct intel_dp *intel_dp);
 
+static void intel_dp_set_default_sink_rates(struct intel_dp *intel_dp)
+{
+	intel_dp->sink_rates[0] = 162000;
+	intel_dp->num_sink_rates = 1;
+}
+
 /* update sink rates from dpcd */
 static void intel_dp_set_sink_rates(struct intel_dp *intel_dp)
 {
@@ -567,7 +573,7 @@
 		return 0;
 	}
 	/* Also take into account max slice width */
-	min_slice_count = min_t(u8, min_slice_count,
+	min_slice_count = max_t(u8, min_slice_count,
 				DIV_ROUND_UP(mode_hdisplay,
 					     max_slice_width));
 
@@ -1292,8 +1298,7 @@
 	bool is_tc_port = intel_phy_is_tc(i915, phy);
 	i915_reg_t ch_ctl, ch_data[5];
 	u32 aux_clock_divider;
-	enum intel_display_power_domain aux_domain =
-		intel_aux_power_domain(intel_dig_port);
+	enum intel_display_power_domain aux_domain;
 	intel_wakeref_t aux_wakeref;
 	intel_wakeref_t pps_wakeref;
 	int i, ret, recv_bytes;
@@ -1308,6 +1313,8 @@
 	if (is_tc_port)
 		intel_tc_port_lock(intel_dig_port);
 
+	aux_domain = intel_aux_power_domain(intel_dig_port);
+
 	aux_wakeref = intel_display_power_get(i915, aux_domain);
 	pps_wakeref = pps_lock(intel_dp);
 
@@ -2251,7 +2258,7 @@
 	struct intel_connector *intel_connector = intel_dp->attached_connector;
 	struct intel_digital_connector_state *intel_conn_state =
 		to_intel_digital_connector_state(conn_state);
-	bool constant_n = drm_dp_has_quirk(&intel_dp->desc,
+	bool constant_n = drm_dp_has_quirk(&intel_dp->desc, 0,
 					   DP_DPCD_QUIRK_CONSTANT_N);
 	int ret = 0, output_bpp;
 
@@ -3633,7 +3640,7 @@
  * link status information
  */
 bool
-intel_dp_get_link_status(struct intel_dp *intel_dp, u8 link_status[DP_LINK_STATUS_SIZE])
+intel_dp_get_link_status(struct intel_dp *intel_dp, u8 *link_status)
 {
 	return drm_dp_dpcd_read(&intel_dp->aux, DP_LANE0_1_STATUS, link_status,
 				DP_LINK_STATUS_SIZE) == DP_LINK_STATUS_SIZE;
@@ -4260,6 +4267,9 @@
 	 */
 	intel_psr_init_dpcd(intel_dp);
 
+	/* Clear the default sink rates */
+	intel_dp->num_sink_rates = 0;
+
 	/* Read the eDP 1.4+ supported link rates. */
 	if (intel_dp->edp_dpcd[0] >= DP_EDP_14) {
 		__le16 sink_rates[DP_MAX_SUPPORTED_RATES];
@@ -4327,7 +4337,8 @@
 	 * it don't care about read it here and in intel_edp_init_dpcd().
 	 */
 	if (!intel_dp_is_edp(intel_dp) &&
-	    !drm_dp_has_quirk(&intel_dp->desc, DP_DPCD_QUIRK_NO_SINK_COUNT)) {
+	    !drm_dp_has_quirk(&intel_dp->desc, 0,
+			      DP_DPCD_QUIRK_NO_SINK_COUNT)) {
 		u8 count;
 		ssize_t r;
 
@@ -4705,7 +4716,18 @@
 	bool bret;
 
 	if (intel_dp->is_mst) {
-		u8 esi[DP_DPRX_ESI_LEN] = { 0 };
+		/*
+		 * The +2 is because DP_DPRX_ESI_LEN is 14, but we then
+		 * pass in "esi+10" to drm_dp_channel_eq_ok(), which
+		 * takes a 6-byte array. So we actually need 16 bytes
+		 * here.
+		 *
+		 * Somebody who knows what the limits actually are
+		 * should check this, but for now this is at least
+		 * harmless and avoids a valid compiler warning about
+		 * using more of the array than we have allocated.
+		 */
+		u8 esi[DP_DPRX_ESI_LEN+2] = {};
 		int ret = 0;
 		int retry;
 		bool handled;
@@ -5328,6 +5350,7 @@
 
 	intel_dp->has_audio = drm_detect_monitor_audio(edid);
 	drm_dp_cec_set_edid(&intel_dp->aux, edid);
+	intel_dp->edid_quirks = drm_dp_get_edid_quirks(edid);
 }
 
 static void
@@ -5340,6 +5363,7 @@
 	intel_connector->detect_edid = NULL;
 
 	intel_dp->has_audio = false;
+	intel_dp->edid_quirks = 0;
 }
 
 static int
@@ -7046,8 +7070,8 @@
 	edid = drm_get_edid(connector, &intel_dp->aux.ddc);
 	if (edid) {
 		if (drm_add_edid_modes(connector, edid)) {
-			drm_connector_update_edid_property(connector,
-								edid);
+			drm_connector_update_edid_property(connector, edid);
+			intel_dp->edid_quirks = drm_dp_get_edid_quirks(edid);
 		} else {
 			kfree(edid);
 			edid = ERR_PTR(-EINVAL);
@@ -7155,6 +7179,8 @@
 		return false;
 
 	intel_dp_set_source_rates(intel_dp);
+	intel_dp_set_default_sink_rates(intel_dp);
+	intel_dp_set_common_rates(intel_dp);
 
 	intel_dp->reset_link_params = true;
 	intel_dp->pps_pipe = INVALID_PIPE;
@@ -7218,11 +7244,8 @@
 		intel_connector->get_hw_state = intel_connector_get_hw_state;
 
 	/* init MST on ports that can support it */
-	if (HAS_DP_MST(dev_priv) && !intel_dp_is_edp(intel_dp) &&
-	    (port == PORT_B || port == PORT_C ||
-	     port == PORT_D || port == PORT_F))
-		intel_dp_mst_encoder_init(intel_dig_port,
-					  intel_connector->base.base.id);
+	intel_dp_mst_encoder_init(intel_dig_port,
+				  intel_connector->base.base.id);
 
 	if (!intel_edp_init_connector(intel_dp, intel_connector)) {
 		intel_dp_aux_fini(intel_dp);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c
@@ -59,8 +59,23 @@
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(&connector->encoder->base);
 	u8 read_val[2] = { 0x0 };
+	u8 control_reg;
 	u16 level = 0;
 
+	if (drm_dp_dpcd_readb(&intel_dp->aux, DP_EDP_DISPLAY_CONTROL_REGISTER,
+			      &control_reg) != 1) {
+		DRM_DEBUG_KMS("Failed to read the DPCD register 0x%x\n",
+			      DP_EDP_DISPLAY_CONTROL_REGISTER);
+		return 0;
+	}
+
+	/*
+	 * If we're not in DPCD control mode yet, the programmed brightness
+	 * value is meaningless and we should assume max brightness
+	 */
+	if (!(control_reg & DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD))
+		return connector->panel.backlight.max;
+
 	if (drm_dp_dpcd_read(&intel_dp->aux, DP_EDP_BACKLIGHT_BRIGHTNESS_MSB,
 			     &read_val, sizeof(read_val)) < 0) {
 		DRM_DEBUG_KMS("Failed to read DPCD register 0x%x\n",
@@ -111,61 +126,28 @@
 {
 	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
 	struct intel_dp *intel_dp = enc_to_intel_dp(&connector->encoder->base);
-	int freq, fxp, fxp_min, fxp_max, fxp_actual, f = 1;
-	u8 pn, pn_min, pn_max;
+	const u8 pn = connector->panel.backlight.pwmgen_bit_count;
+	int freq, fxp, f, fxp_actual, fxp_min, fxp_max;
 
-	/* Find desired value of (F x P)
-	 * Note that, if F x P is out of supported range, the maximum value or
-	 * minimum value will applied automatically. So no need to check that.
-	 */
 	freq = dev_priv->vbt.backlight.pwm_freq_hz;
-	DRM_DEBUG_KMS("VBT defined backlight frequency %u Hz\n", freq);
 	if (!freq) {
 		DRM_DEBUG_KMS("Use panel default backlight frequency\n");
 		return false;
 	}
 
 	fxp = DIV_ROUND_CLOSEST(KHz(DP_EDP_BACKLIGHT_FREQ_BASE_KHZ), freq);
+	f = clamp(DIV_ROUND_CLOSEST(fxp, 1 << pn), 1, 255);
+	fxp_actual = f << pn;
 
-	/* Use highest possible value of Pn for more granularity of brightness
-	 * adjustment while satifying the conditions below.
-	 * - Pn is in the range of Pn_min and Pn_max
-	 * - F is in the range of 1 and 255
-	 * - FxP is within 25% of desired value.
-	 *   Note: 25% is arbitrary value and may need some tweak.
-	 */
-	if (drm_dp_dpcd_readb(&intel_dp->aux,
-			       DP_EDP_PWMGEN_BIT_COUNT_CAP_MIN, &pn_min) != 1) {
-		DRM_DEBUG_KMS("Failed to read pwmgen bit count cap min\n");
-		return false;
-	}
-	if (drm_dp_dpcd_readb(&intel_dp->aux,
-			       DP_EDP_PWMGEN_BIT_COUNT_CAP_MAX, &pn_max) != 1) {
-		DRM_DEBUG_KMS("Failed to read pwmgen bit count cap max\n");
-		return false;
-	}
-	pn_min &= DP_EDP_PWMGEN_BIT_COUNT_MASK;
-	pn_max &= DP_EDP_PWMGEN_BIT_COUNT_MASK;
-
+	/* Ensure frequency is within 25% of desired value */
 	fxp_min = DIV_ROUND_CLOSEST(fxp * 3, 4);
 	fxp_max = DIV_ROUND_CLOSEST(fxp * 5, 4);
-	if (fxp_min < (1 << pn_min) || (255 << pn_max) < fxp_max) {
-		DRM_DEBUG_KMS("VBT defined backlight frequency out of range\n");
-		return false;
-	}
-
-	for (pn = pn_max; pn >= pn_min; pn--) {
-		f = clamp(DIV_ROUND_CLOSEST(fxp, 1 << pn), 1, 255);
-		fxp_actual = f << pn;
-		if (fxp_min <= fxp_actual && fxp_actual <= fxp_max)
-			break;
-	}
 
-	if (drm_dp_dpcd_writeb(&intel_dp->aux,
-			       DP_EDP_PWMGEN_BIT_COUNT, pn) < 0) {
-		DRM_DEBUG_KMS("Failed to write aux pwmgen bit count\n");
+	if (fxp_min > fxp_actual || fxp_actual > fxp_max) {
+		DRM_DEBUG_KMS("Actual frequency out of range\n");
 		return false;
 	}
+
 	if (drm_dp_dpcd_writeb(&intel_dp->aux,
 			       DP_EDP_BACKLIGHT_FREQ_SET, (u8) f) < 0) {
 		DRM_DEBUG_KMS("Failed to write aux backlight freq\n");
@@ -178,6 +160,7 @@
 					  const struct drm_connector_state *conn_state)
 {
 	struct intel_connector *connector = to_intel_connector(conn_state->connector);
+	struct intel_panel *panel = &connector->panel;
 	struct intel_dp *intel_dp = enc_to_intel_dp(&connector->encoder->base);
 	u8 dpcd_buf, new_dpcd_buf, edp_backlight_mode;
 
@@ -197,6 +180,12 @@
 	case DP_EDP_BACKLIGHT_CONTROL_MODE_PRODUCT:
 		new_dpcd_buf &= ~DP_EDP_BACKLIGHT_CONTROL_MODE_MASK;
 		new_dpcd_buf |= DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD;
+
+		if (drm_dp_dpcd_writeb(&intel_dp->aux,
+				       DP_EDP_PWMGEN_BIT_COUNT,
+				       panel->backlight.pwmgen_bit_count) < 0)
+			DRM_DEBUG_KMS("Failed to write aux pwmgen bit count\n");
+
 		break;
 
 	/* Do nothing when it is already DPCD mode */
@@ -216,8 +205,9 @@
 		}
 	}
 
+	intel_dp_aux_set_backlight(conn_state,
+				   connector->panel.backlight.level);
 	set_aux_backlight_enable(intel_dp, true);
-	intel_dp_aux_set_backlight(conn_state, connector->panel.backlight.level);
 }
 
 static void intel_dp_aux_disable_backlight(const struct drm_connector_state *old_conn_state)
@@ -225,20 +215,91 @@
 	set_aux_backlight_enable(enc_to_intel_dp(old_conn_state->best_encoder), false);
 }
 
+static u32 intel_dp_aux_calc_max_backlight(struct intel_connector *connector)
+{
+	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
+	struct intel_dp *intel_dp = enc_to_intel_dp(&connector->encoder->base);
+	struct intel_panel *panel = &connector->panel;
+	u32 max_backlight = 0;
+	int freq, fxp, fxp_min, fxp_max, fxp_actual, f = 1;
+	u8 pn, pn_min, pn_max;
+
+	if (drm_dp_dpcd_readb(&intel_dp->aux, DP_EDP_PWMGEN_BIT_COUNT, &pn)) {
+		pn &= DP_EDP_PWMGEN_BIT_COUNT_MASK;
+		max_backlight = (1 << pn) - 1;
+	}
+
+	/* Find desired value of (F x P)
+	 * Note that, if F x P is out of supported range, the maximum value or
+	 * minimum value will applied automatically. So no need to check that.
+	 */
+	freq = dev_priv->vbt.backlight.pwm_freq_hz;
+	DRM_DEBUG_KMS("VBT defined backlight frequency %u Hz\n", freq);
+	if (!freq) {
+		DRM_DEBUG_KMS("Use panel default backlight frequency\n");
+		return max_backlight;
+	}
+
+	fxp = DIV_ROUND_CLOSEST(KHz(DP_EDP_BACKLIGHT_FREQ_BASE_KHZ), freq);
+
+	/* Use highest possible value of Pn for more granularity of brightness
+	 * adjustment while satifying the conditions below.
+	 * - Pn is in the range of Pn_min and Pn_max
+	 * - F is in the range of 1 and 255
+	 * - FxP is within 25% of desired value.
+	 *   Note: 25% is arbitrary value and may need some tweak.
+	 */
+	if (drm_dp_dpcd_readb(&intel_dp->aux,
+			      DP_EDP_PWMGEN_BIT_COUNT_CAP_MIN, &pn_min) != 1) {
+		DRM_DEBUG_KMS("Failed to read pwmgen bit count cap min\n");
+		return max_backlight;
+	}
+	if (drm_dp_dpcd_readb(&intel_dp->aux,
+			      DP_EDP_PWMGEN_BIT_COUNT_CAP_MAX, &pn_max) != 1) {
+		DRM_DEBUG_KMS("Failed to read pwmgen bit count cap max\n");
+		return max_backlight;
+	}
+	pn_min &= DP_EDP_PWMGEN_BIT_COUNT_MASK;
+	pn_max &= DP_EDP_PWMGEN_BIT_COUNT_MASK;
+
+	fxp_min = DIV_ROUND_CLOSEST(fxp * 3, 4);
+	fxp_max = DIV_ROUND_CLOSEST(fxp * 5, 4);
+	if (fxp_min < (1 << pn_min) || (255 << pn_max) < fxp_max) {
+		DRM_DEBUG_KMS("VBT defined backlight frequency out of range\n");
+		return max_backlight;
+	}
+
+	for (pn = pn_max; pn >= pn_min; pn--) {
+		f = clamp(DIV_ROUND_CLOSEST(fxp, 1 << pn), 1, 255);
+		fxp_actual = f << pn;
+		if (fxp_min <= fxp_actual && fxp_actual <= fxp_max)
+			break;
+	}
+
+	DRM_DEBUG_KMS("Using eDP pwmgen bit count of %d\n", pn);
+	if (drm_dp_dpcd_writeb(&intel_dp->aux,
+			       DP_EDP_PWMGEN_BIT_COUNT, pn) < 0) {
+		DRM_DEBUG_KMS("Failed to write aux pwmgen bit count\n");
+		return max_backlight;
+	}
+	panel->backlight.pwmgen_bit_count = pn;
+
+	max_backlight = (1 << pn) - 1;
+
+	return max_backlight;
+}
+
 static int intel_dp_aux_setup_backlight(struct intel_connector *connector,
 					enum pipe pipe)
 {
-	struct intel_dp *intel_dp = enc_to_intel_dp(&connector->encoder->base);
 	struct intel_panel *panel = &connector->panel;
 
-	if (intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_BYTE_COUNT)
-		panel->backlight.max = 0xFFFF;
-	else
-		panel->backlight.max = 0xFF;
+	panel->backlight.max = intel_dp_aux_calc_max_backlight(connector);
+	if (!panel->backlight.max)
+		return -ENODEV;
 
 	panel->backlight.min = 0;
 	panel->backlight.level = intel_dp_aux_get_backlight(connector);
-
 	panel->backlight.enabled = panel->backlight.level != 0;
 
 	return 0;
@@ -264,15 +325,35 @@
 int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector)
 {
 	struct intel_panel *panel = &intel_connector->panel;
-	struct drm_i915_private *dev_priv = to_i915(intel_connector->base.dev);
+	struct intel_dp *intel_dp = enc_to_intel_dp(&intel_connector->encoder->base);
+	struct drm_device *dev = intel_connector->base.dev;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	bool force_dpcd;
+
+	force_dpcd = drm_dp_has_quirk(&intel_dp->desc, intel_dp->edid_quirks,
+				      DP_QUIRK_FORCE_DPCD_BACKLIGHT);
 
 	if (i915_modparams.enable_dpcd_backlight == 0 ||
-	    (i915_modparams.enable_dpcd_backlight == -1 &&
-	    dev_priv->vbt.backlight.type != INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE))
+	    (!force_dpcd && !intel_dp_aux_display_control_capable(intel_connector)))
 		return -ENODEV;
 
-	if (!intel_dp_aux_display_control_capable(intel_connector))
+	/*
+	 * There are a lot of machines that don't advertise the backlight
+	 * control interface to use properly in their VBIOS, :\
+	 */
+	if (dev_priv->vbt.backlight.type !=
+	    INTEL_BACKLIGHT_VESA_EDP_AUX_INTERFACE &&
+	    i915_modparams.enable_dpcd_backlight != 1 && !force_dpcd) {
+		DRM_DEV_INFO(dev->dev,
+			     "Panel advertises DPCD backlight support, but "
+			     "VBT disagrees. If your backlight controls "
+			     "don't work try booting with "
+			     "i915.enable_dpcd_backlight=1. If your machine "
+			     "needs this, please file a _new_ bug report on "
+			     "bugs.freedesktop.org against DRI -> "
+			     "DRM/Intel\n");
 		return -ENODEV;
+	}
 
 	panel->backlight.setup = intel_dp_aux_setup_backlight;
 	panel->backlight.enable = intel_dp_aux_enable_backlight;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -50,7 +50,7 @@
 	const struct drm_display_mode *adjusted_mode =
 		&crtc_state->base.adjusted_mode;
 	void *port = connector->port;
-	bool constant_n = drm_dp_has_quirk(&intel_dp->desc,
+	bool constant_n = drm_dp_has_quirk(&intel_dp->desc, 0,
 					   DP_DPCD_QUIRK_CONSTANT_N);
 	int bpp, slots = -EINVAL;
 
@@ -520,6 +520,7 @@
 	ret = drm_connector_init(dev, connector, &intel_dp_mst_connector_funcs,
 				 DRM_MODE_CONNECTOR_DisplayPort);
 	if (ret) {
+		drm_dp_mst_put_port_malloc(port);
 		intel_connector_free(intel_connector);
 		return NULL;
 	}
@@ -653,21 +654,31 @@
 int
 intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_base_id)
 {
+	struct drm_i915_private *i915 = to_i915(intel_dig_port->base.base.dev);
 	struct intel_dp *intel_dp = &intel_dig_port->dp;
-	struct drm_device *dev = intel_dig_port->base.base.dev;
+	enum port port = intel_dig_port->base.port;
 	int ret;
 
-	intel_dp->can_mst = true;
+	if (!HAS_DP_MST(i915) || intel_dp_is_edp(intel_dp))
+		return 0;
+
+	if (INTEL_GEN(i915) < 12 && port == PORT_A)
+		return 0;
+
+	if (INTEL_GEN(i915) < 11 && port == PORT_E)
+		return 0;
+
 	intel_dp->mst_mgr.cbs = &mst_cbs;
 
 	/* create encoders */
 	intel_dp_create_fake_mst_encoders(intel_dig_port);
-	ret = drm_dp_mst_topology_mgr_init(&intel_dp->mst_mgr, dev,
+	ret = drm_dp_mst_topology_mgr_init(&intel_dp->mst_mgr, &i915->drm,
 					   &intel_dp->aux, 16, 3, conn_base_id);
-	if (ret) {
-		intel_dp->can_mst = false;
+	if (ret)
 		return ret;
-	}
+
+	intel_dp->can_mst = true;
+
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/display/intel_fbc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/display/intel_fbc.c
@@ -504,8 +504,7 @@
 	if (!ret)
 		goto err_llb;
 	else if (ret > 1) {
-		DRM_INFO("Reducing the compressed framebuffer size. This may lead to less power savings than a non-reduced-size. Try to increase stolen memory size if available in BIOS.\n");
-
+		DRM_INFO_ONCE("Reducing the compressed framebuffer size. This may lead to less power savings than a non-reduced-size. Try to increase stolen memory size if available in BIOS.\n");
 	}
 
 	fbc->threshold = ret;
@@ -1284,7 +1283,7 @@
 		return 0;
 
 	/* https://bugs.freedesktop.org/show_bug.cgi?id=108085 */
-	if (IS_GEMINILAKE(dev_priv))
+	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
 		return 0;
 
 	if (IS_BROADWELL(dev_priv) || INTEL_GEN(dev_priv) >= 9)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/display/intel_frontbuffer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/display/intel_frontbuffer.c
@@ -221,11 +221,11 @@
 	struct intel_frontbuffer *front =
 		container_of(ref, typeof(*front), ref);
 
-	front->obj->frontbuffer = NULL;
+	RCU_INIT_POINTER(front->obj->frontbuffer, NULL);
 	spin_unlock(&to_i915(front->obj->base.dev)->fb_tracking.lock);
 
 	i915_gem_object_put(front->obj);
-	kfree(front);
+	kfree_rcu(front, rcu);
 }
 
 struct intel_frontbuffer *
@@ -234,11 +234,7 @@
 	struct drm_i915_private *i915 = to_i915(obj->base.dev);
 	struct intel_frontbuffer *front;
 
-	spin_lock(&i915->fb_tracking.lock);
-	front = obj->frontbuffer;
-	if (front)
-		kref_get(&front->ref);
-	spin_unlock(&i915->fb_tracking.lock);
+	front = __intel_frontbuffer_get(obj);
 	if (front)
 		return front;
 
@@ -253,13 +249,13 @@
 			 frontbuffer_active, frontbuffer_retire);
 
 	spin_lock(&i915->fb_tracking.lock);
-	if (obj->frontbuffer) {
+	if (rcu_access_pointer(obj->frontbuffer)) {
 		kfree(front);
-		front = obj->frontbuffer;
+		front = rcu_dereference_protected(obj->frontbuffer, true);
 		kref_get(&front->ref);
 	} else {
 		i915_gem_object_get(obj);
-		obj->frontbuffer = front;
+		rcu_assign_pointer(obj->frontbuffer, front);
 	}
 	spin_unlock(&i915->fb_tracking.lock);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/display/intel_frontbuffer.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/display/intel_frontbuffer.h
@@ -27,10 +27,10 @@
 #include <linux/atomic.h>
 #include <linux/kref.h>
 
+#include "gem/i915_gem_object_types.h"
 #include "i915_active.h"
 
 struct drm_i915_private;
-struct drm_i915_gem_object;
 
 enum fb_op_origin {
 	ORIGIN_GTT,
@@ -45,6 +45,7 @@
 	atomic_t bits;
 	struct i915_active write;
 	struct drm_i915_gem_object *obj;
+	struct rcu_head rcu;
 };
 
 void intel_frontbuffer_flip_prepare(struct drm_i915_private *i915,
@@ -54,6 +55,35 @@
 void intel_frontbuffer_flip(struct drm_i915_private *i915,
 			    unsigned frontbuffer_bits);
 
+void intel_frontbuffer_put(struct intel_frontbuffer *front);
+
+static inline struct intel_frontbuffer *
+__intel_frontbuffer_get(const struct drm_i915_gem_object *obj)
+{
+	struct intel_frontbuffer *front;
+
+	if (likely(!rcu_access_pointer(obj->frontbuffer)))
+		return NULL;
+
+	rcu_read_lock();
+	do {
+		front = rcu_dereference(obj->frontbuffer);
+		if (!front)
+			break;
+
+		if (unlikely(!kref_get_unless_zero(&front->ref)))
+			continue;
+
+		if (likely(front == rcu_access_pointer(obj->frontbuffer)))
+			break;
+
+		intel_frontbuffer_put(front);
+	} while (1);
+	rcu_read_unlock();
+
+	return front;
+}
+
 struct intel_frontbuffer *
 intel_frontbuffer_get(struct drm_i915_gem_object *obj);
 
@@ -119,6 +149,4 @@
 			     struct intel_frontbuffer *new,
 			     unsigned int frontbuffer_bits);
 
-void intel_frontbuffer_put(struct intel_frontbuffer *front);
-
 #endif /* __INTEL_FRONTBUFFER_H__ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/display/intel_hdcp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/display/intel_hdcp.c
@@ -61,11 +61,16 @@
 /* Is HDCP1.4 capable on Platform and Sink */
 bool intel_hdcp_capable(struct intel_connector *connector)
 {
-	struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
+	struct intel_digital_port *intel_dig_port;
 	const struct intel_hdcp_shim *shim = connector->hdcp.shim;
 	bool capable = false;
 	u8 bksv[5];
 
+	if (!connector->encoder)
+		return capable;
+
+	intel_dig_port = conn_to_dig_port(connector);
+
 	if (!shim)
 		return capable;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -1232,6 +1232,11 @@
 	if (hdmi->dp_dual_mode.type < DRM_DP_DUAL_MODE_TYPE2_DVI)
 		return;
 
+	if (dev_priv->bypass_tmds_oe) {
+		DRM_DEBUG_KMS("Bypassing TMDS_OE setting\n");
+		return;
+	}
+
 	DRM_DEBUG_KMS("%s DP dual mode adaptor TMDS output\n",
 		      enable ? "Enabling" : "Disabling");
 
@@ -2129,7 +2134,11 @@
 	if (clock > hdmi_port_clock_limit(hdmi, respect_downstream_limits, force_dvi))
 		return MODE_CLOCK_HIGH;
 
-	/* BXT DPLL can't generate 223-240 MHz */
+	/* GLK DPLL can't generate 446-480 MHz */
+	if (IS_GEMINILAKE(dev_priv) && clock > 446666 && clock < 480000)
+		return MODE_CLOCK_RANGE;
+
+	/* BXT/GLK DPLL can't generate 223-240 MHz */
 	if (IS_GEN9_LP(dev_priv) && clock > 223333 && clock < 240000)
 		return MODE_CLOCK_RANGE;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/display/intel_lpe_audio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/display/intel_lpe_audio.c
@@ -172,6 +172,14 @@
 				handle_simple_irq,
 				"hdmi_lpe_audio_irq_handler");
 
+	static const struct pci_device_id irq_quirk_ids[] = {
+		/* Dell Wyse 3040 */
+		{PCI_DEVICE_SUB(PCI_VENDOR_ID_INTEL, 0x22b0, 0x1028, 0x07c1)},
+		{}
+	};
+
+	if (pci_dev_present(irq_quirk_ids))
+		return 0;
 	return irq_set_chip_data(irq, dev_priv);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/display/intel_overlay.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/display/intel_overlay.c
@@ -278,12 +278,21 @@
 				       struct i915_vma *vma)
 {
 	enum pipe pipe = overlay->crtc->pipe;
+	struct intel_frontbuffer *from = NULL, *to = NULL;
 
 	WARN_ON(overlay->old_vma);
 
-	intel_frontbuffer_track(overlay->vma ? overlay->vma->obj->frontbuffer : NULL,
-				vma ? vma->obj->frontbuffer : NULL,
-				INTEL_FRONTBUFFER_OVERLAY(pipe));
+	if (overlay->vma)
+		from = intel_frontbuffer_get(overlay->vma->obj);
+	if (vma)
+		to = intel_frontbuffer_get(vma->obj);
+
+	intel_frontbuffer_track(from, to, INTEL_FRONTBUFFER_OVERLAY(pipe));
+
+	if (to)
+		intel_frontbuffer_put(to);
+	if (from)
+		intel_frontbuffer_put(from);
 
 	intel_frontbuffer_flip_prepare(overlay->i915,
 				       INTEL_FRONTBUFFER_OVERLAY(pipe));
@@ -768,7 +777,7 @@
 		ret = PTR_ERR(vma);
 		goto out_pin_section;
 	}
-	intel_frontbuffer_flush(new_bo->frontbuffer, ORIGIN_DIRTYFB);
+	i915_gem_object_flush_frontbuffer(new_bo, ORIGIN_DIRTYFB);
 
 	if (!overlay->active) {
 		u32 oconfig;
@@ -913,6 +922,9 @@
 	const struct intel_crtc_state *pipe_config =
 		overlay->crtc->config;
 
+	if (rec->dst_height == 0 || rec->dst_width == 0)
+		return -EINVAL;
+
 	if (rec->dst_x < pipe_config->pipe_src_w &&
 	    rec->dst_x + rec->dst_width <= pipe_config->pipe_src_w &&
 	    rec->dst_y < pipe_config->pipe_src_h &&
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/display/intel_panel.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/display/intel_panel.c
@@ -1603,20 +1603,21 @@
 		val = pch_get_backlight(connector);
 	else
 		val = lpt_get_backlight(connector);
-	val = intel_panel_compute_brightness(connector, val);
-	panel->backlight.level = clamp(val, panel->backlight.min,
-				       panel->backlight.max);
 
 	if (cpu_mode) {
 		DRM_DEBUG_KMS("CPU backlight register was enabled, switching to PCH override\n");
 
 		/* Write converted CPU PWM value to PCH override register */
-		lpt_set_backlight(connector->base.state, panel->backlight.level);
+		lpt_set_backlight(connector->base.state, val);
 		I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_OVERRIDE_ENABLE);
 
 		I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2 & ~BLM_PWM_ENABLE);
 	}
 
+	val = intel_panel_compute_brightness(connector, val);
+	panel->backlight.level = clamp(val, panel->backlight.min,
+				       panel->backlight.max);
+
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/display/intel_psr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/display/intel_psr.c
@@ -291,7 +291,7 @@
 	DRM_DEBUG_KMS("eDP panel supports PSR version %x\n",
 		      intel_dp->psr_dpcd[0]);
 
-	if (drm_dp_has_quirk(&intel_dp->desc, DP_DPCD_QUIRK_NO_PSR)) {
+	if (drm_dp_has_quirk(&intel_dp->desc, 0, DP_DPCD_QUIRK_NO_PSR)) {
 		DRM_DEBUG_KMS("PSR support not currently available for this panel\n");
 		return;
 	}
@@ -1219,6 +1219,14 @@
 	if (!dev_priv->psr.sink_support)
 		return;
 
+	/*
+	 * PSR was disabled by module parameters but the underlying panel is
+	 * depending on it, so use per-chip default to probe that automatically.
+	 */
+	if ((dev_priv->psr.dp->edid_quirks & BIT(DP_QUIRK_FORCE_PSR_CHIP_DEFAULT)) &&
+	    i915_modparams.enable_psr == 0)
+		i915_modparams.enable_psr = -1;
+
 	if (i915_modparams.enable_psr == -1)
 		if (INTEL_GEN(dev_priv) < 9 || !dev_priv->vbt.psr.enable)
 			i915_modparams.enable_psr = 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/display/intel_quirks.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/display/intel_quirks.c
@@ -146,6 +146,11 @@
 	/* ASRock ITX*/
 	{ 0x3185, 0x1849, 0x2212, quirk_increase_ddi_disabled_time },
 	{ 0x3184, 0x1849, 0x2212, quirk_increase_ddi_disabled_time },
+	/* ECS Liva Q2 */
+	{ 0x3185, 0x1019, 0xa94d, quirk_increase_ddi_disabled_time },
+	{ 0x3184, 0x1019, 0xa94d, quirk_increase_ddi_disabled_time },
+	/* HP Notebook - 14-r206nv */
+	{ 0x0f31, 0x103c, 0x220f, quirk_invert_brightness },
 };
 
 void intel_init_quirks(struct drm_i915_private *i915)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/display/intel_sdvo.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/display/intel_sdvo.c
@@ -2693,13 +2693,10 @@
 	if (!intel_sdvo_connector)
 		return false;
 
-	if (device == 0) {
-		intel_sdvo->controlled_output |= SDVO_OUTPUT_TMDS0;
+	if (device == 0)
 		intel_sdvo_connector->output_flag = SDVO_OUTPUT_TMDS0;
-	} else if (device == 1) {
-		intel_sdvo->controlled_output |= SDVO_OUTPUT_TMDS1;
+	else if (device == 1)
 		intel_sdvo_connector->output_flag = SDVO_OUTPUT_TMDS1;
-	}
 
 	intel_connector = &intel_sdvo_connector->base;
 	connector = &intel_connector->base;
@@ -2753,7 +2750,6 @@
 	encoder->encoder_type = DRM_MODE_ENCODER_TVDAC;
 	connector->connector_type = DRM_MODE_CONNECTOR_SVIDEO;
 
-	intel_sdvo->controlled_output |= type;
 	intel_sdvo_connector->output_flag = type;
 
 	if (intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo) < 0) {
@@ -2794,13 +2790,10 @@
 	encoder->encoder_type = DRM_MODE_ENCODER_DAC;
 	connector->connector_type = DRM_MODE_CONNECTOR_VGA;
 
-	if (device == 0) {
-		intel_sdvo->controlled_output |= SDVO_OUTPUT_RGB0;
+	if (device == 0)
 		intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB0;
-	} else if (device == 1) {
-		intel_sdvo->controlled_output |= SDVO_OUTPUT_RGB1;
+	else if (device == 1)
 		intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB1;
-	}
 
 	if (intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo) < 0) {
 		kfree(intel_sdvo_connector);
@@ -2830,13 +2823,10 @@
 	encoder->encoder_type = DRM_MODE_ENCODER_LVDS;
 	connector->connector_type = DRM_MODE_CONNECTOR_LVDS;
 
-	if (device == 0) {
-		intel_sdvo->controlled_output |= SDVO_OUTPUT_LVDS0;
+	if (device == 0)
 		intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS0;
-	} else if (device == 1) {
-		intel_sdvo->controlled_output |= SDVO_OUTPUT_LVDS1;
+	else if (device == 1)
 		intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1;
-	}
 
 	if (intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo) < 0) {
 		kfree(intel_sdvo_connector);
@@ -2869,16 +2859,39 @@
 	return false;
 }
 
+static u16 intel_sdvo_filter_output_flags(u16 flags)
+{
+	flags &= SDVO_OUTPUT_MASK;
+
+	/* SDVO requires XXX1 function may not exist unless it has XXX0 function.*/
+	if (!(flags & SDVO_OUTPUT_TMDS0))
+		flags &= ~SDVO_OUTPUT_TMDS1;
+
+	if (!(flags & SDVO_OUTPUT_RGB0))
+		flags &= ~SDVO_OUTPUT_RGB1;
+
+	if (!(flags & SDVO_OUTPUT_LVDS0))
+		flags &= ~SDVO_OUTPUT_LVDS1;
+
+	return flags;
+}
+
 static bool
 intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, u16 flags)
 {
-	/* SDVO requires XXX1 function may not exist unless it has XXX0 function.*/
+	struct drm_i915_private *i915 = to_i915(intel_sdvo->base.base.dev);
+
+	flags = intel_sdvo_filter_output_flags(flags);
+
+	intel_sdvo->controlled_output = flags;
+
+	intel_sdvo_select_ddc_bus(i915, intel_sdvo);
 
 	if (flags & SDVO_OUTPUT_TMDS0)
 		if (!intel_sdvo_dvi_init(intel_sdvo, 0))
 			return false;
 
-	if ((flags & SDVO_TMDS_MASK) == SDVO_TMDS_MASK)
+	if (flags & SDVO_OUTPUT_TMDS1)
 		if (!intel_sdvo_dvi_init(intel_sdvo, 1))
 			return false;
 
@@ -2899,7 +2912,7 @@
 		if (!intel_sdvo_analog_init(intel_sdvo, 0))
 			return false;
 
-	if ((flags & SDVO_RGB_MASK) == SDVO_RGB_MASK)
+	if (flags & SDVO_OUTPUT_RGB1)
 		if (!intel_sdvo_analog_init(intel_sdvo, 1))
 			return false;
 
@@ -2907,14 +2920,13 @@
 		if (!intel_sdvo_lvds_init(intel_sdvo, 0))
 			return false;
 
-	if ((flags & SDVO_LVDS_MASK) == SDVO_LVDS_MASK)
+	if (flags & SDVO_OUTPUT_LVDS1)
 		if (!intel_sdvo_lvds_init(intel_sdvo, 1))
 			return false;
 
-	if ((flags & SDVO_OUTPUT_MASK) == 0) {
+	if (flags == 0) {
 		unsigned char bytes[2];
 
-		intel_sdvo->controlled_output = 0;
 		memcpy(bytes, &intel_sdvo->caps.output_flags, 2);
 		DRM_DEBUG_KMS("%s: Unknown SDVO output type (0x%02x%02x)\n",
 			      SDVO_NAME(intel_sdvo),
@@ -3321,8 +3333,6 @@
 	 */
 	intel_sdvo->base.cloneable = 0;
 
-	intel_sdvo_select_ddc_bus(dev_priv, intel_sdvo);
-
 	/* Set the input timing to the screen. Assume always input 0. */
 	if (!intel_sdvo_set_target_input(intel_sdvo))
 		goto err_output;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/display/intel_tc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/display/intel_tc.c
@@ -45,6 +45,62 @@
 	return tc_port / 2;
 }
 
+static enum intel_display_power_domain
+tc_cold_get_power_domain(struct intel_digital_port *dig_port)
+{
+	struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+
+	if (INTEL_GEN(i915) == 11)
+		return intel_legacy_aux_to_power_domain(dig_port->aux_ch);
+	else
+		return POWER_DOMAIN_TC_COLD_OFF;
+}
+
+static intel_wakeref_t
+tc_cold_block(struct intel_digital_port *dig_port)
+{
+	struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+	enum intel_display_power_domain domain;
+
+	if (INTEL_GEN(i915) == 11 && !dig_port->tc_legacy_port)
+		return 0;
+
+	domain = tc_cold_get_power_domain(dig_port);
+	return intel_display_power_get(i915, domain);
+}
+
+static void
+tc_cold_unblock(struct intel_digital_port *dig_port, intel_wakeref_t wakeref)
+{
+	struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+	enum intel_display_power_domain domain;
+
+	/*
+	 * wakeref == -1, means some error happened saving save_depot_stack but
+	 * power should still be put down and 0 is a invalid save_depot_stack
+	 * id so can be used to skip it for non TC legacy ports.
+	 */
+	if (wakeref == 0)
+		return;
+
+	domain = tc_cold_get_power_domain(dig_port);
+	intel_display_power_put_async(i915, domain, wakeref);
+}
+
+static void
+assert_tc_cold_blocked(struct intel_digital_port *dig_port)
+{
+	struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+	bool enabled;
+
+	if (INTEL_GEN(i915) == 11 && !dig_port->tc_legacy_port)
+		return;
+
+	enabled = intel_display_power_is_enabled(i915,
+						 tc_cold_get_power_domain(dig_port));
+	WARN_ON(!enabled);
+}
+
 u32 intel_tc_port_get_lane_mask(struct intel_digital_port *dig_port)
 {
 	struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
@@ -56,6 +112,7 @@
 				      PORT_TX_DFLEXDPSP(dig_port->tc_phy_fia));
 
 	WARN_ON(lane_mask == 0xffffffff);
+	assert_tc_cold_blocked(dig_port);
 
 	return (lane_mask & DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
 	       DP_LANE_ASSIGNMENT_SHIFT(tc_port);
@@ -70,6 +127,8 @@
 	if (dig_port->tc_mode != TC_PORT_DP_ALT)
 		return 4;
 
+	assert_tc_cold_blocked(dig_port);
+
 	lane_mask = 0;
 	with_intel_display_power(i915, POWER_DOMAIN_DISPLAY_CORE, wakeref)
 		lane_mask = intel_tc_port_get_lane_mask(dig_port);
@@ -102,6 +161,8 @@
 
 	WARN_ON(lane_reversal && dig_port->tc_mode != TC_PORT_LEGACY);
 
+	assert_tc_cold_blocked(dig_port);
+
 	val = intel_uncore_read(uncore,
 				PORT_TX_DFLEXDPMLE1(dig_port->tc_phy_fia));
 	val &= ~DFLEXDPMLE1_DPMLETC_MASK(tc_port);
@@ -390,8 +451,14 @@
 	enum tc_port_mode old_tc_mode = dig_port->tc_mode;
 
 	intel_display_power_flush_work(i915);
-	WARN_ON(intel_display_power_is_enabled(i915,
-					       intel_aux_power_domain(dig_port)));
+	if (INTEL_GEN(i915) != 11 || !dig_port->tc_legacy_port) {
+		enum intel_display_power_domain aux_domain;
+		bool aux_powered;
+
+		aux_domain = intel_aux_power_domain(dig_port);
+		aux_powered = intel_display_power_is_enabled(i915, aux_domain);
+		WARN_ON(aux_powered);
+	}
 
 	icl_tc_phy_disconnect(dig_port);
 	icl_tc_phy_connect(dig_port, required_lanes);
@@ -413,9 +480,11 @@
 void intel_tc_port_sanitize(struct intel_digital_port *dig_port)
 {
 	struct intel_encoder *encoder = &dig_port->base;
+	intel_wakeref_t tc_cold_wref;
 	int active_links = 0;
 
 	mutex_lock(&dig_port->tc_lock);
+	tc_cold_wref = tc_cold_block(dig_port);
 
 	dig_port->tc_mode = intel_tc_port_get_current_mode(dig_port);
 	if (dig_port->dp.is_mst)
@@ -440,6 +509,7 @@
 		      dig_port->tc_port_name,
 		      tc_port_mode_name(dig_port->tc_mode));
 
+	tc_cold_unblock(dig_port, tc_cold_wref);
 	mutex_unlock(&dig_port->tc_lock);
 }
 
@@ -461,10 +531,15 @@
 bool intel_tc_port_connected(struct intel_digital_port *dig_port)
 {
 	bool is_connected;
+	intel_wakeref_t tc_cold_wref;
 
 	intel_tc_port_lock(dig_port);
+	tc_cold_wref = tc_cold_block(dig_port);
+
 	is_connected = tc_port_live_status_mask(dig_port) &
 		       BIT(dig_port->tc_mode);
+
+	tc_cold_unblock(dig_port, tc_cold_wref);
 	intel_tc_port_unlock(dig_port);
 
 	return is_connected;
@@ -480,9 +555,16 @@
 
 	mutex_lock(&dig_port->tc_lock);
 
-	if (!dig_port->tc_link_refcount &&
-	    intel_tc_port_needs_reset(dig_port))
-		intel_tc_port_reset_mode(dig_port, required_lanes);
+	if (!dig_port->tc_link_refcount) {
+		intel_wakeref_t tc_cold_wref;
+
+		tc_cold_wref = tc_cold_block(dig_port);
+
+		if (intel_tc_port_needs_reset(dig_port))
+			intel_tc_port_reset_mode(dig_port, required_lanes);
+
+		tc_cold_unblock(dig_port, tc_cold_wref);
+	}
 
 	WARN_ON(dig_port->tc_lock_wakeref);
 	dig_port->tc_lock_wakeref = wakeref;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/display/vlv_dsi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/display/vlv_dsi.c
@@ -797,10 +797,20 @@
 	if (intel_dsi->gpio_panel)
 		gpiod_set_value_cansleep(intel_dsi->gpio_panel, 1);
 	intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_POWER_ON);
-	intel_dsi_msleep(intel_dsi, intel_dsi->panel_on_delay);
 
-	/* Deassert reset */
-	intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_DEASSERT_RESET);
+	/*
+	 * Give the panel time to power-on and then deassert its reset.
+	 * Depending on the VBT MIPI sequences version the deassert-seq
+	 * may contain the necessary delay, intel_dsi_msleep() will skip
+	 * the delay in that case. If there is no deassert-seq, then an
+	 * unconditional msleep is used to give the panel time to power-on.
+	 */
+	if (dev_priv->vbt.dsi.sequence[MIPI_SEQ_DEASSERT_RESET]) {
+		intel_dsi_msleep(intel_dsi, intel_dsi->panel_on_delay);
+		intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_DEASSERT_RESET);
+	} else {
+		msleep(intel_dsi->panel_on_delay);
+	}
 
 	if (IS_GEMINILAKE(dev_priv)) {
 		glk_cold_boot = glk_dsi_enable_io(encoder);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gem/i915_gem_busy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gem/i915_gem_busy.c
@@ -9,16 +9,16 @@
 #include "i915_gem_ioctls.h"
 #include "i915_gem_object.h"
 
-static __always_inline u32 __busy_read_flag(u8 id)
+static __always_inline u32 __busy_read_flag(u16 id)
 {
-	if (id == (u8)I915_ENGINE_CLASS_INVALID)
+	if (id == (u16)I915_ENGINE_CLASS_INVALID)
 		return 0xffff0000u;
 
 	GEM_BUG_ON(id >= 16);
 	return 0x10000u << id;
 }
 
-static __always_inline u32 __busy_write_id(u8 id)
+static __always_inline u32 __busy_write_id(u16 id)
 {
 	/*
 	 * The uABI guarantees an active writer is also amongst the read
@@ -29,14 +29,14 @@
 	 * last_read - hence we always set both read and write busy for
 	 * last_write.
 	 */
-	if (id == (u8)I915_ENGINE_CLASS_INVALID)
+	if (id == (u16)I915_ENGINE_CLASS_INVALID)
 		return 0xffffffffu;
 
 	return (id + 1) | __busy_read_flag(id);
 }
 
 static __always_inline unsigned int
-__busy_set_if_active(const struct dma_fence *fence, u32 (*flag)(u8 id))
+__busy_set_if_active(const struct dma_fence *fence, u32 (*flag)(u16 id))
 {
 	const struct i915_request *rq;
 
@@ -57,7 +57,7 @@
 		return 0;
 
 	/* Beware type-expansion follies! */
-	BUILD_BUG_ON(!typecheck(u8, rq->engine->uabi_class));
+	BUILD_BUG_ON(!typecheck(u16, rq->engine->uabi_class));
 	return flag(rq->engine->uabi_class);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gem/i915_gem_clflush.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gem/i915_gem_clflush.c
@@ -20,7 +20,8 @@
 {
 	GEM_BUG_ON(!i915_gem_object_has_pages(obj));
 	drm_clflush_sg(obj->mm.pages);
-	intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU);
+
+	i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU);
 }
 
 static int clflush_work(struct dma_fence_work *base)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gem/i915_gem_context.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gem/i915_gem_context.c
@@ -2094,8 +2094,7 @@
 	ext_data.fpriv = file->driver_priv;
 	if (client_is_banned(ext_data.fpriv)) {
 		DRM_DEBUG("client %s[%d] banned from creating ctx\n",
-			  current->comm,
-			  pid_nr(get_task_pid(current, PIDTYPE_PID)));
+			  current->comm, task_pid_nr(current));
 		return -EIO;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
@@ -36,13 +36,13 @@
 		goto err_unpin_pages;
 	}
 
-	ret = sg_alloc_table(st, obj->mm.pages->nents, GFP_KERNEL);
+	ret = sg_alloc_table(st, obj->mm.pages->orig_nents, GFP_KERNEL);
 	if (ret)
 		goto err_free;
 
 	src = obj->mm.pages->sgl;
 	dst = st->sgl;
-	for (i = 0; i < obj->mm.pages->nents; i++) {
+	for (i = 0; i < obj->mm.pages->orig_nents; i++) {
 		sg_set_page(dst, sg_page(src), src->length, 0);
 		dst = sg_next(dst);
 		src = sg_next(src);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gem/i915_gem_domain.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gem/i915_gem_domain.c
@@ -606,21 +606,6 @@
 		return -ENOENT;
 
 	/*
-	 * Already in the desired write domain? Nothing for us to do!
-	 *
-	 * We apply a little bit of cunning here to catch a broader set of
-	 * no-ops. If obj->write_domain is set, we must be in the same
-	 * obj->read_domains, and only that domain. Therefore, if that
-	 * obj->write_domain matches the request read_domains, we are
-	 * already in the same read/write domain and can skip the operation,
-	 * without having to further check the requested write_domain.
-	 */
-	if (READ_ONCE(obj->write_domain) == read_domains) {
-		err = 0;
-		goto out;
-	}
-
-	/*
 	 * Try to flush the object off the GPU without holding the lock.
 	 * We will repeat the flush holding the lock in the normal manner
 	 * to catch cases where we are gazumped.
@@ -657,6 +642,19 @@
 	if (err)
 		goto out;
 
+	/*
+	 * Already in the desired write domain? Nothing for us to do!
+	 *
+	 * We apply a little bit of cunning here to catch a broader set of
+	 * no-ops. If obj->write_domain is set, we must be in the same
+	 * obj->read_domains, and only that domain. Therefore, if that
+	 * obj->write_domain matches the request read_domains, we are
+	 * already in the same read/write domain and can skip the operation,
+	 * without having to further check the requested write_domain.
+	 */
+	if (READ_ONCE(obj->write_domain) == read_domains)
+		goto out_unpin;
+
 	err = i915_gem_object_lock_interruptible(obj);
 	if (err)
 		goto out_unpin;
@@ -674,7 +672,7 @@
 	i915_gem_object_unlock(obj);
 
 	if (write_domain)
-		intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CPU);
+		i915_gem_object_invalidate_frontbuffer(obj, ORIGIN_CPU);
 
 out_unpin:
 	i915_gem_object_unpin_pages(obj);
@@ -794,7 +792,7 @@
 	}
 
 out:
-	intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CPU);
+	i915_gem_object_invalidate_frontbuffer(obj, ORIGIN_CPU);
 	obj->mm.dirty = true;
 	/* return with the pages pinned */
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
@@ -367,7 +367,7 @@
 		return true;
 
 	if (!(flags & EXEC_OBJECT_SUPPORTS_48B_ADDRESS) &&
-	    (vma->node.start + vma->node.size - 1) >> 32)
+	    (vma->node.start + vma->node.size + 4095) >> 32)
 		return true;
 
 	if (flags & __EXEC_OBJECT_NEEDS_MAP &&
@@ -439,7 +439,8 @@
 	if (unlikely(entry->flags & eb->invalid_flags))
 		return -EINVAL;
 
-	if (unlikely(entry->alignment && !is_power_of_2(entry->alignment)))
+	if (unlikely(entry->alignment &&
+		     !is_power_of_2_u64(entry->alignment)))
 		return -EINVAL;
 
 	/*
@@ -930,11 +931,13 @@
 
 static void reloc_gpu_flush(struct reloc_cache *cache)
 {
-	GEM_BUG_ON(cache->rq_size >= cache->rq->batch->obj->base.size / sizeof(u32));
+	struct drm_i915_gem_object *obj = cache->rq->batch->obj;
+
+	GEM_BUG_ON(cache->rq_size >= obj->base.size / sizeof(u32));
 	cache->rq_cmd[cache->rq_size] = MI_BATCH_BUFFER_END;
 
-	__i915_gem_object_flush_map(cache->rq->batch->obj, 0, cache->rq_size);
-	i915_gem_object_unpin_map(cache->rq->batch->obj);
+	i915_gem_object_flush_map(obj);
+	i915_gem_object_unpin_map(obj);
 
 	intel_gt_chipset_flush(cache->rq->engine->gt);
 
@@ -1160,6 +1163,8 @@
 		goto out_pool;
 	}
 
+	memset32(cmd, 0, pool->obj->base.size / sizeof(u32));
+
 	batch = i915_vma_instance(pool->obj, vma->vm, NULL);
 	if (IS_ERR(batch)) {
 		err = PTR_ERR(batch);
@@ -1447,7 +1452,7 @@
 
 	urelocs = u64_to_user_ptr(entry->relocs_ptr);
 	remain = entry->relocation_count;
-	if (unlikely(remain > N_RELOC(ULONG_MAX)))
+	if (unlikely((unsigned long)remain > N_RELOC(ULONG_MAX)))
 		return -EINVAL;
 
 	/*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gem/i915_gem_mman.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gem/i915_gem_mman.c
@@ -181,7 +181,7 @@
 	struct i915_ggtt_view view;
 
 	if (i915_gem_object_is_tiled(obj))
-		chunk = roundup(chunk, tile_row_pages(obj));
+		chunk = roundup(chunk, tile_row_pages(obj) ?: 1);
 
 	view.type = I915_GGTT_VIEW_PARTIAL;
 	view.partial.offset = rounddown(page_offset, chunk);
@@ -196,6 +196,39 @@
 	return view;
 }
 
+static void set_address_limits(struct vm_area_struct *area,
+			       struct i915_vma *vma,
+			       unsigned long *start_vaddr,
+			       unsigned long *end_vaddr)
+{
+	unsigned long vm_start, vm_end, vma_size; /* user's memory parameters */
+	long start, end; /* memory boundaries */
+
+	/*
+	 * Let's move into the ">> PAGE_SHIFT"
+	 * domain to be sure not to lose bits
+	 */
+	vm_start = area->vm_start >> PAGE_SHIFT;
+	vm_end = area->vm_end >> PAGE_SHIFT;
+	vma_size = vma->size >> PAGE_SHIFT;
+
+	/*
+	 * Calculate the memory boundaries by considering the offset
+	 * provided by the user during memory mapping and the offset
+	 * provided for the partial mapping.
+	 */
+	start = vm_start;
+	start += vma->ggtt_view.partial.offset;
+	end = start + vma_size;
+
+	start = max_t(long, start, vm_start);
+	end = min_t(long, end, vm_end);
+
+	/* Let's move back into the "<< PAGE_SHIFT" domain */
+	*start_vaddr = (unsigned long)start << PAGE_SHIFT;
+	*end_vaddr = (unsigned long)end << PAGE_SHIFT;
+}
+
 /**
  * i915_gem_fault - fault a page into the GTT
  * @vmf: fault info
@@ -224,9 +257,11 @@
 	struct intel_runtime_pm *rpm = &i915->runtime_pm;
 	struct i915_ggtt *ggtt = &i915->ggtt;
 	bool write = area->vm_flags & VM_WRITE;
+	unsigned long start, end; /* memory boundaries */
 	intel_wakeref_t wakeref;
 	struct i915_vma *vma;
 	pgoff_t page_offset;
+	unsigned long pfn;
 	int srcu;
 	int ret;
 
@@ -295,12 +330,14 @@
 	if (ret)
 		goto err_unpin;
 
+	set_address_limits(area, vma, &start, &end);
+
+	pfn = (ggtt->gmadr.start + i915_ggtt_offset(vma)) >> PAGE_SHIFT;
+	pfn += (start - area->vm_start) >> PAGE_SHIFT;
+	pfn -= vma->ggtt_view.partial.offset;
+
 	/* Finally, remap it using the new GTT offset */
-	ret = remap_io_mapping(area,
-			       area->vm_start + (vma->ggtt_view.partial.offset << PAGE_SHIFT),
-			       (ggtt->gmadr.start + vma->node.start) >> PAGE_SHIFT,
-			       min_t(u64, vma->size, area->vm_end - area->vm_start),
-			       &ggtt->iomap);
+	ret = remap_io_mapping(area, start, pfn, end - start, &ggtt->iomap);
 	if (ret)
 		goto err_fence;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gem/i915_gem_object.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gem/i915_gem_object.c
@@ -270,7 +270,7 @@
 		for_each_ggtt_vma(vma, obj)
 			intel_gt_flush_ggtt_writes(vma->vm->gt);
 
-		intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU);
+		i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU);
 
 		for_each_ggtt_vma(vma, obj) {
 			if (vma->iomap)
@@ -298,6 +298,30 @@
 	obj->write_domain = 0;
 }
 
+void __i915_gem_object_flush_frontbuffer(struct drm_i915_gem_object *obj,
+					 enum fb_op_origin origin)
+{
+	struct intel_frontbuffer *front;
+
+	front = __intel_frontbuffer_get(obj);
+	if (front) {
+		intel_frontbuffer_flush(front, origin);
+		intel_frontbuffer_put(front);
+	}
+}
+
+void __i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj,
+					      enum fb_op_origin origin)
+{
+	struct intel_frontbuffer *front;
+
+	front = __intel_frontbuffer_get(obj);
+	if (front) {
+		intel_frontbuffer_invalidate(front, origin);
+		intel_frontbuffer_put(front);
+	}
+}
+
 void i915_gem_init__objects(struct drm_i915_private *i915)
 {
 	INIT_WORK(&i915->mm.free_work, __i915_gem_free_work);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gem/i915_gem_object.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gem/i915_gem_object.h
@@ -13,8 +13,8 @@
 
 #include <drm/i915_drm.h>
 
+#include "display/intel_frontbuffer.h"
 #include "i915_gem_object_types.h"
-
 #include "i915_gem_gtt.h"
 
 void i915_gem_init__objects(struct drm_i915_private *i915);
@@ -431,4 +431,25 @@
 				  const struct i915_sched_attr *attr);
 #define I915_PRIORITY_DISPLAY I915_USER_PRIORITY(I915_PRIORITY_MAX)
 
+void __i915_gem_object_flush_frontbuffer(struct drm_i915_gem_object *obj,
+					 enum fb_op_origin origin);
+void __i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj,
+					      enum fb_op_origin origin);
+
+static inline void
+i915_gem_object_flush_frontbuffer(struct drm_i915_gem_object *obj,
+				  enum fb_op_origin origin)
+{
+	if (unlikely(rcu_access_pointer(obj->frontbuffer)))
+		__i915_gem_object_flush_frontbuffer(obj, origin);
+}
+
+static inline void
+i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj,
+				       enum fb_op_origin origin)
+{
+	if (unlikely(rcu_access_pointer(obj->frontbuffer)))
+		__i915_gem_object_invalidate_frontbuffer(obj, origin);
+}
+
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gem/i915_gem_object_types.h
@@ -118,6 +118,9 @@
 
 	I915_SELFTEST_DECLARE(struct list_head st_link);
 
+	unsigned long flags;
+#define I915_BO_WAS_BOUND_BIT    0
+
 	/*
 	 * Is the object to be mapped as read-only to the GPU
 	 * Only honoured if hardware has relevant pte bit
@@ -143,7 +146,7 @@
 	 */
 	u16 write_domain;
 
-	struct intel_frontbuffer *frontbuffer;
+	struct intel_frontbuffer __rcu *frontbuffer;
 
 	/** Current tiling stride for the object, if it's tiled. */
 	unsigned int tiling_and_stride;
@@ -240,9 +243,6 @@
 
 		void *gvt_info;
 	};
-
-	/** for phys allocated objects */
-	struct drm_dma_handle *phys_handle;
 };
 
 static inline struct drm_i915_gem_object *
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gem/i915_gem_pages.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gem/i915_gem_pages.c
@@ -8,6 +8,8 @@
 #include "i915_gem_object.h"
 #include "i915_scatterlist.h"
 
+#include "gt/intel_gt.h"
+
 void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj,
 				 struct sg_table *pages,
 				 unsigned int sg_page_sizes)
@@ -176,6 +178,14 @@
 	__i915_gem_object_reset_page_iter(obj);
 	obj->mm.page_sizes.phys = obj->mm.page_sizes.sg = 0;
 
+	if (test_and_clear_bit(I915_BO_WAS_BOUND_BIT, &obj->flags)) {
+		struct drm_i915_private *i915 = to_i915(obj->base.dev);
+		intel_wakeref_t wakeref;
+
+		with_intel_runtime_pm_if_in_use(&i915->runtime_pm, wakeref)
+			intel_gt_invalidate_tlbs(&i915->gt);
+	}
+
 	return pages;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gem/i915_gem_phys.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gem/i915_gem_phys.c
@@ -21,88 +21,87 @@
 static int i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
 {
 	struct address_space *mapping = obj->base.filp->f_mapping;
-	struct drm_dma_handle *phys;
-	struct sg_table *st;
 	struct scatterlist *sg;
-	char *vaddr;
+	struct sg_table *st;
+	dma_addr_t dma;
+	void *vaddr;
+	void *dst;
 	int i;
-	int err;
 
 	if (WARN_ON(i915_gem_object_needs_bit17_swizzle(obj)))
 		return -EINVAL;
 
-	/* Always aligning to the object size, allows a single allocation
+	/*
+	 * Always aligning to the object size, allows a single allocation
 	 * to handle all possible callers, and given typical object sizes,
 	 * the alignment of the buddy allocation will naturally match.
 	 */
-	phys = drm_pci_alloc(obj->base.dev,
-			     roundup_pow_of_two(obj->base.size),
-			     roundup_pow_of_two(obj->base.size));
-	if (!phys)
+	vaddr = dma_alloc_coherent(&obj->base.dev->pdev->dev,
+				   roundup_pow_of_two(obj->base.size),
+				   &dma, GFP_KERNEL);
+	if (!vaddr)
 		return -ENOMEM;
 
-	vaddr = phys->vaddr;
+	st = kmalloc(sizeof(*st), GFP_KERNEL);
+	if (!st)
+		goto err_pci;
+
+	if (sg_alloc_table(st, 1, GFP_KERNEL))
+		goto err_st;
+
+	sg = st->sgl;
+	sg->offset = 0;
+	sg->length = obj->base.size;
+
+	sg_assign_page(sg, (struct page *)vaddr);
+	sg_dma_address(sg) = dma;
+	sg_dma_len(sg) = obj->base.size;
+
+	dst = vaddr;
 	for (i = 0; i < obj->base.size / PAGE_SIZE; i++) {
 		struct page *page;
-		char *src;
+		void *src;
 
 		page = shmem_read_mapping_page(mapping, i);
-		if (IS_ERR(page)) {
-			err = PTR_ERR(page);
-			goto err_phys;
-		}
+		if (IS_ERR(page))
+			goto err_st;
 
 		src = kmap_atomic(page);
-		memcpy(vaddr, src, PAGE_SIZE);
-		drm_clflush_virt_range(vaddr, PAGE_SIZE);
+		memcpy(dst, src, PAGE_SIZE);
+		drm_clflush_virt_range(dst, PAGE_SIZE);
 		kunmap_atomic(src);
 
 		put_page(page);
-		vaddr += PAGE_SIZE;
+		dst += PAGE_SIZE;
 	}
 
 	intel_gt_chipset_flush(&to_i915(obj->base.dev)->gt);
 
-	st = kmalloc(sizeof(*st), GFP_KERNEL);
-	if (!st) {
-		err = -ENOMEM;
-		goto err_phys;
-	}
-
-	if (sg_alloc_table(st, 1, GFP_KERNEL)) {
-		kfree(st);
-		err = -ENOMEM;
-		goto err_phys;
-	}
-
-	sg = st->sgl;
-	sg->offset = 0;
-	sg->length = obj->base.size;
-
-	sg_dma_address(sg) = phys->busaddr;
-	sg_dma_len(sg) = obj->base.size;
-
-	obj->phys_handle = phys;
-
 	__i915_gem_object_set_pages(obj, st, sg->length);
 
 	return 0;
 
-err_phys:
-	drm_pci_free(obj->base.dev, phys);
-
-	return err;
+err_st:
+	kfree(st);
+err_pci:
+	dma_free_coherent(&obj->base.dev->pdev->dev,
+			  roundup_pow_of_two(obj->base.size),
+			  vaddr, dma);
+	return -ENOMEM;
 }
 
 static void
 i915_gem_object_put_pages_phys(struct drm_i915_gem_object *obj,
 			       struct sg_table *pages)
 {
+	dma_addr_t dma = sg_dma_address(pages->sgl);
+	void *vaddr = sg_page(pages->sgl);
+
 	__i915_gem_object_release_shmem(obj, pages, false);
 
 	if (obj->mm.dirty) {
 		struct address_space *mapping = obj->base.filp->f_mapping;
-		char *vaddr = obj->phys_handle->vaddr;
+		void *src = vaddr;
 		int i;
 
 		for (i = 0; i < obj->base.size / PAGE_SIZE; i++) {
@@ -114,15 +113,16 @@
 				continue;
 
 			dst = kmap_atomic(page);
-			drm_clflush_virt_range(vaddr, PAGE_SIZE);
-			memcpy(dst, vaddr, PAGE_SIZE);
+			drm_clflush_virt_range(src, PAGE_SIZE);
+			memcpy(dst, src, PAGE_SIZE);
 			kunmap_atomic(dst);
 
 			set_page_dirty(page);
 			if (obj->mm.madv == I915_MADV_WILLNEED)
 				mark_page_accessed(page);
 			put_page(page);
-			vaddr += PAGE_SIZE;
+
+			src += PAGE_SIZE;
 		}
 		obj->mm.dirty = false;
 	}
@@ -130,7 +130,9 @@
 	sg_free_table(pages);
 	kfree(pages);
 
-	drm_pci_free(obj->base.dev, obj->phys_handle);
+	dma_free_coherent(&obj->base.dev->pdev->dev,
+			  roundup_pow_of_two(obj->base.size),
+			  vaddr, dma);
 }
 
 static void phys_release(struct drm_i915_gem_object *obj)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
@@ -36,7 +36,6 @@
 	unsigned long last_pfn = 0;	/* suppress gcc warning */
 	unsigned int max_segment = i915_sg_segment_size();
 	unsigned int sg_page_sizes;
-	struct pagevec pvec;
 	gfp_t noreclaim;
 	int ret;
 
@@ -188,13 +187,17 @@
 	sg_mark_end(sg);
 err_pages:
 	mapping_clear_unevictable(mapping);
-	pagevec_init(&pvec);
-	for_each_sgt_page(page, sgt_iter, st) {
-		if (!pagevec_add(&pvec, page))
+	if (sg != st->sgl) {
+		struct pagevec pvec;
+
+		pagevec_init(&pvec);
+		for_each_sgt_page(page, sgt_iter, st) {
+			if (!pagevec_add(&pvec, page))
+				check_release_pagevec(&pvec);
+		}
+		if (pagevec_count(&pvec))
 			check_release_pagevec(&pvec);
 	}
-	if (pagevec_count(&pvec))
-		check_release_pagevec(&pvec);
 	sg_free_table(st);
 	kfree(st);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c
@@ -357,8 +357,7 @@
 				sc->nr_to_scan,
 				&sc->nr_scanned,
 				I915_SHRINK_BOUND |
-				I915_SHRINK_UNBOUND |
-				I915_SHRINK_WRITEBACK);
+				I915_SHRINK_UNBOUND);
 	if (sc->nr_scanned < sc->nr_to_scan && current_is_kswapd()) {
 		intel_wakeref_t wakeref;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
@@ -427,7 +427,7 @@
 
 static struct sg_table *
 __i915_gem_userptr_alloc_pages(struct drm_i915_gem_object *obj,
-			       struct page **pvec, int num_pages)
+			       struct page **pvec, unsigned long num_pages)
 {
 	unsigned int max_segment = i915_sg_segment_size();
 	struct sg_table *st;
@@ -473,9 +473,10 @@
 {
 	struct get_pages_work *work = container_of(_work, typeof(*work), work);
 	struct drm_i915_gem_object *obj = work->obj;
-	const int npages = obj->base.size >> PAGE_SHIFT;
+	const unsigned long npages = obj->base.size >> PAGE_SHIFT;
+	unsigned long pinned;
 	struct page **pvec;
-	int pinned, ret;
+	int ret;
 
 	ret = -ENOMEM;
 	pinned = 0;
@@ -578,7 +579,7 @@
 
 static int i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj)
 {
-	const int num_pages = obj->base.size >> PAGE_SHIFT;
+	const unsigned long num_pages = obj->base.size >> PAGE_SHIFT;
 	struct mm_struct *mm = obj->userptr.mm->mm;
 	struct page **pvec;
 	struct sg_table *pages;
@@ -618,6 +619,14 @@
 				      GFP_KERNEL |
 				      __GFP_NORETRY |
 				      __GFP_NOWARN);
+		/*
+		 * Using __get_user_pages_fast() with a read-only
+		 * access is questionable. A read-only page may be
+		 * COW-broken, and then this might end up giving
+		 * the wrong side of the COW..
+		 *
+		 * We may or may not care.
+		 */
 		if (pvec) /* defer to worker if malloc fails */
 			pinned = __get_user_pages_fast(obj->userptr.ptr,
 						       num_pages,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
@@ -375,7 +375,7 @@
 
 	obj = i915_gem_object_create_internal(i915, size);
 	if (IS_ERR(obj))
-		return PTR_ERR(obj);
+		return false;
 
 	err = create_mmap_offset(obj);
 	i915_gem_object_put(obj);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gt/intel_engine.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gt/intel_engine.h
@@ -250,6 +250,14 @@
 	return pos & (ring->size - 1);
 }
 
+static inline int intel_ring_direction(const struct intel_ring *ring,
+				       u32 next, u32 prev)
+{
+	typecheck(typeof(ring->size), next);
+	typecheck(typeof(ring->size), prev);
+	return (next - prev) << ring->wrap;
+}
+
 static inline bool
 intel_ring_offset_valid(const struct intel_ring *ring,
 			unsigned int pos)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gt/intel_engine_cs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gt/intel_engine_cs.c
@@ -28,13 +28,13 @@
 
 #include "i915_drv.h"
 
-#include "gt/intel_gt.h"
-
+#include "intel_context.h"
 #include "intel_engine.h"
 #include "intel_engine_pm.h"
 #include "intel_engine_pool.h"
 #include "intel_engine_user.h"
-#include "intel_context.h"
+#include "intel_gt.h"
+#include "intel_gt_requests.h"
 #include "intel_lrc.h"
 #include "intel_reset.h"
 
@@ -354,7 +354,8 @@
 		 * instances.
 		 */
 		if ((INTEL_GEN(i915) >= 11 &&
-		     RUNTIME_INFO(i915)->vdbox_sfc_access & engine->mask) ||
+		     (RUNTIME_INFO(i915)->vdbox_sfc_access &
+		      BIT(engine->instance))) ||
 		    (INTEL_GEN(i915) >= 9 && engine->instance == 0))
 			engine->uabi_capabilities |=
 				I915_VIDEO_AND_ENHANCE_CLASS_CAPABILITY_SFC;
@@ -600,6 +601,7 @@
 	intel_engine_init_hangcheck(engine);
 	intel_engine_init_cmd_parser(engine);
 	intel_engine_init__pm(engine);
+	intel_engine_init_retire(engine);
 
 	intel_engine_pool_init(&engine->pool);
 
@@ -807,6 +809,7 @@
 
 	cleanup_status_page(engine);
 
+	intel_engine_fini_retire(engine);
 	intel_engine_pool_fini(&engine->pool);
 	intel_engine_fini_breadcrumbs(engine);
 	intel_engine_cleanup_cmd_parser(engine);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gt/intel_engine_pm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gt/intel_engine_pm.c
@@ -70,8 +70,43 @@
 
 #endif /* !IS_ENABLED(CONFIG_LOCKDEP) */
 
+static void
+__queue_and_release_pm(struct i915_request *rq,
+		       struct intel_timeline *tl,
+		       struct intel_engine_cs *engine)
+{
+	struct intel_gt_timelines *timelines = &engine->gt->timelines;
+	unsigned long flags;
+
+	GEM_TRACE("%s\n", engine->name);
+
+	/*
+	 * We have to serialise all potential retirement paths with our
+	 * submission, as we don't want to underflow either the
+	 * engine->wakeref.counter or our timeline->active_count.
+	 *
+	 * Equally, we cannot allow a new submission to start until
+	 * after we finish queueing, nor could we allow that submitter
+	 * to retire us before we are ready!
+	 */
+	spin_lock_irqsave(&timelines->lock, flags);
+
+	/* Let intel_gt_retire_requests() retire us (acquired under lock) */
+	if (!atomic_fetch_inc(&tl->active_count))
+		list_add_tail(&tl->link, &timelines->active_list);
+
+	/* Hand the request over to HW and so engine_retire() */
+	__i915_request_queue(rq, NULL);
+
+	/* Let new submissions commence (and maybe retire this timeline) */
+	__intel_wakeref_defer_park(&engine->wakeref);
+
+	spin_unlock_irqrestore(&timelines->lock, flags);
+}
+
 static bool switch_to_kernel_context(struct intel_engine_cs *engine)
 {
+	struct intel_context *ce = engine->kernel_context;
 	struct i915_request *rq;
 	unsigned long flags;
 	bool result = true;
@@ -96,15 +131,13 @@
 	 * retiring the last request, thus all rings should be empty and
 	 * all timelines idle.
 	 */
-	flags = __timeline_mark_lock(engine->kernel_context);
+	flags = __timeline_mark_lock(ce);
 
-	rq = __i915_request_create(engine->kernel_context, GFP_NOWAIT);
+	rq = __i915_request_create(ce, GFP_NOWAIT);
 	if (IS_ERR(rq))
 		/* Context switch failed, hope for the best! Maybe reset? */
 		goto out_unlock;
 
-	intel_timeline_enter(rq->timeline);
-
 	/* Check again on the next retirement. */
 	engine->wakeref_serial = engine->serial + 1;
 	i915_request_add_active_barriers(rq);
@@ -113,13 +146,12 @@
 	rq->sched.attr.priority = I915_PRIORITY_UNPREEMPTABLE;
 	__i915_request_commit(rq);
 
-	/* Release our exclusive hold on the engine */
-	__intel_wakeref_defer_park(&engine->wakeref);
-	__i915_request_queue(rq, NULL);
+	/* Expose ourselves to the world */
+	__queue_and_release_pm(rq, ce->timeline, engine);
 
 	result = false;
 out_unlock:
-	__timeline_mark_unlock(engine->kernel_context, flags);
+	__timeline_mark_unlock(ce, flags);
 	return result;
 }
 
@@ -145,9 +177,6 @@
 	intel_engine_disarm_breadcrumbs(engine);
 	intel_engine_pool_park(&engine->pool);
 
-	/* Must be reset upon idling, or we may miss the busy wakeup. */
-	GEM_BUG_ON(engine->execlists.queue_priority_hint != INT_MIN);
-
 	if (engine->park)
 		engine->park(engine);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gt/intel_engine_types.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gt/intel_engine_types.h
@@ -107,6 +107,7 @@
 
 	u32 space;
 	u32 size;
+	u32 wrap;
 	u32 effective_size;
 };
 
@@ -300,8 +301,8 @@
 	u8 class;
 	u8 instance;
 
-	u8 uabi_class;
-	u8 uabi_instance;
+	u16 uabi_class;
+	u16 uabi_instance;
 
 	u32 context_size;
 	u32 mmio_base;
@@ -470,6 +471,14 @@
 
 	struct intel_engine_execlists execlists;
 
+	/*
+	 * Keep track of completed timelines on this engine for early
+	 * retirement with the goal of quickly enabling powersaving as
+	 * soon as the engine is idle.
+	 */
+	struct intel_timeline *retire;
+	struct work_struct retire_work;
+
 	/* status_notifier: list of callbacks for context-switch changes */
 	struct atomic_notifier_head context_status_notifier;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gt/intel_gt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gt/intel_gt.c
@@ -15,6 +15,8 @@
 
 	spin_lock_init(&gt->irq_lock);
 
+	mutex_init(&gt->tlb_invalidate_lock);
+
 	INIT_LIST_HEAD(&gt->closed_vma);
 	spin_lock_init(&gt->closed_lock);
 
@@ -266,3 +268,117 @@
 	intel_uc_driver_late_release(&gt->uc);
 	intel_gt_fini_reset(gt);
 }
+
+struct reg_and_bit {
+	i915_reg_t reg;
+	u32 bit;
+};
+
+static struct reg_and_bit
+get_reg_and_bit(const struct intel_engine_cs *engine, const bool gen8,
+		const i915_reg_t *regs, const unsigned int num)
+{
+	const unsigned int class = engine->class;
+	struct reg_and_bit rb = { };
+
+	if (WARN_ON_ONCE(class >= num || !regs[class].reg))
+		return rb;
+
+	rb.reg = regs[class];
+	if (gen8 && class == VIDEO_DECODE_CLASS)
+		rb.reg.reg += 4 * engine->instance; /* GEN8_M2TCR */
+	else
+		rb.bit = engine->instance;
+
+	rb.bit = BIT(rb.bit);
+
+	return rb;
+}
+
+void intel_gt_invalidate_tlbs(struct intel_gt *gt)
+{
+	static const i915_reg_t gen8_regs[] = {
+		[RENDER_CLASS]			= GEN8_RTCR,
+		[VIDEO_DECODE_CLASS]		= GEN8_M1TCR, /* , GEN8_M2TCR */
+		[VIDEO_ENHANCEMENT_CLASS]	= GEN8_VTCR,
+		[COPY_ENGINE_CLASS]		= GEN8_BTCR,
+	};
+	static const i915_reg_t gen12_regs[] = {
+		[RENDER_CLASS]			= GEN12_GFX_TLB_INV_CR,
+		[VIDEO_DECODE_CLASS]		= GEN12_VD_TLB_INV_CR,
+		[VIDEO_ENHANCEMENT_CLASS]	= GEN12_VE_TLB_INV_CR,
+		[COPY_ENGINE_CLASS]		= GEN12_BLT_TLB_INV_CR,
+	};
+	struct drm_i915_private *i915 = gt->i915;
+	struct intel_uncore *uncore = gt->uncore;
+	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
+	const i915_reg_t *regs;
+	unsigned int num = 0;
+
+	if (I915_SELFTEST_ONLY(gt->awake == -ENODEV))
+		return;
+
+	if (INTEL_GEN(i915) == 12) {
+		regs = gen12_regs;
+		num = ARRAY_SIZE(gen12_regs);
+	} else if (INTEL_GEN(i915) >= 8 && INTEL_GEN(i915) <= 11) {
+		regs = gen8_regs;
+		num = ARRAY_SIZE(gen8_regs);
+	} else if (INTEL_GEN(i915) < 8) {
+		return;
+	}
+
+	if (WARN_ONCE(!num, "Platform does not implement TLB invalidation!"))
+		return;
+
+	GEM_TRACE("\n");
+
+	assert_rpm_wakelock_held(&i915->runtime_pm);
+
+	mutex_lock(&gt->tlb_invalidate_lock);
+	intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL);
+
+	spin_lock_irq(&uncore->lock); /* serialise invalidate with GT reset */
+
+	for_each_engine(engine, gt, id) {
+		struct reg_and_bit rb;
+
+		rb = get_reg_and_bit(engine, regs == gen8_regs, regs, num);
+		if (!i915_mmio_reg_offset(rb.reg))
+			continue;
+
+		if (INTEL_GEN(i915) == 12 && (engine->class == VIDEO_DECODE_CLASS ||
+		    engine->class == VIDEO_ENHANCEMENT_CLASS))
+			rb.bit = _MASKED_BIT_ENABLE(rb.bit);
+
+		intel_uncore_write_fw(uncore, rb.reg, rb.bit);
+	}
+
+	spin_unlock_irq(&uncore->lock);
+
+	for_each_engine(engine, gt, id) {
+		/*
+		 * HW architecture suggest typical invalidation time at 40us,
+		 * with pessimistic cases up to 100us and a recommendation to
+		 * cap at 1ms. We go a bit higher just in case.
+		 */
+		const unsigned int timeout_us = 100;
+		const unsigned int timeout_ms = 4;
+		struct reg_and_bit rb;
+
+		rb = get_reg_and_bit(engine, regs == gen8_regs, regs, num);
+		if (!i915_mmio_reg_offset(rb.reg))
+			continue;
+
+		if (__intel_wait_for_register_fw(uncore,
+						 rb.reg, rb.bit, 0,
+						 timeout_us, timeout_ms,
+						 NULL))
+			DRM_ERROR_RATELIMITED("%s TLB invalidation did not complete in %ums!\n",
+					      engine->name, timeout_ms);
+	}
+
+	intel_uncore_forcewake_put(uncore, FORCEWAKE_ALL);
+	mutex_unlock(&gt->tlb_invalidate_lock);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gt/intel_gt.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gt/intel_gt.h
@@ -57,4 +57,6 @@
 
 void intel_gt_queue_hangcheck(struct intel_gt *gt);
 
+void intel_gt_invalidate_tlbs(struct intel_gt *gt);
+
 #endif /* __INTEL_GT_H__ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gt/intel_gt_requests.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gt/intel_gt_requests.c
@@ -0,0 +1,98 @@
+/*
+ * SPDX-License-Identifier: MIT
+ *
+ * Copyright © 2019 Intel Corporation
+ */
+
+#include <linux/workqueue.h>
+
+#include "i915_drv.h" /* for_each_engine() */
+#include "i915_request.h"
+#include "intel_gt.h"
+#include "intel_gt_pm.h"
+#include "intel_gt_requests.h"
+#include "intel_timeline.h"
+
+static void retire_requests(struct intel_timeline *tl)
+{
+	struct i915_request *rq, *rn;
+
+	list_for_each_entry_safe(rq, rn, &tl->requests, link)
+		if (!i915_request_retire(rq))
+			break;
+}
+
+static void engine_retire(struct work_struct *work)
+{
+	struct intel_engine_cs *engine =
+		container_of(work, typeof(*engine), retire_work);
+	struct intel_timeline *tl = xchg(&engine->retire, NULL);
+
+	mutex_lock(&engine->i915->drm.struct_mutex);
+	do {
+		struct intel_timeline *next = xchg(&tl->retire, NULL);
+
+		/*
+		 * Our goal here is to retire _idle_ timelines as soon as
+		 * possible (as they are idle, we do not expect userspace
+		 * to be cleaning up anytime soon).
+		 *
+		 * If the timeline is currently locked, either it is being
+		 * retired elsewhere or about to be!
+		 */
+		if (mutex_trylock(&tl->mutex)) {
+			retire_requests(tl);
+			mutex_unlock(&tl->mutex);
+		}
+		intel_timeline_put(tl);
+
+		GEM_BUG_ON(!next);
+		tl = ptr_mask_bits(next, 1);
+	} while (tl);
+	mutex_unlock(&engine->i915->drm.struct_mutex);
+}
+
+static bool add_retire(struct intel_engine_cs *engine,
+		       struct intel_timeline *tl)
+{
+	struct intel_timeline *first;
+
+	/*
+	 * We open-code a llist here to include the additional tag [BIT(0)]
+	 * so that we know when the timeline is already on a
+	 * retirement queue: either this engine or another.
+	 *
+	 * However, we rely on that a timeline can only be active on a single
+	 * engine at any one time and that add_retire() is called before the
+	 * engine releases the timeline and transferred to another to retire.
+	 */
+
+	if (READ_ONCE(tl->retire)) /* already queued */
+		return false;
+
+	intel_timeline_get(tl);
+	first = READ_ONCE(engine->retire);
+	do
+		tl->retire = ptr_pack_bits(first, 1, 1);
+	while (!try_cmpxchg(&engine->retire, &first, tl));
+
+	return !first;
+}
+
+void intel_engine_add_retire(struct intel_engine_cs *engine,
+			     struct intel_timeline *tl)
+{
+	if (add_retire(engine, tl))
+		schedule_work(&engine->retire_work);
+}
+
+void intel_engine_init_retire(struct intel_engine_cs *engine)
+{
+	INIT_WORK(&engine->retire_work, engine_retire);
+}
+
+void intel_engine_fini_retire(struct intel_engine_cs *engine)
+{
+	flush_work(&engine->retire_work);
+	GEM_BUG_ON(engine->retire);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gt/intel_gt_requests.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gt/intel_gt_requests.h
@@ -0,0 +1,18 @@
+/*
+ * SPDX-License-Identifier: MIT
+ *
+ * Copyright © 2019 Intel Corporation
+ */
+
+#ifndef INTEL_GT_REQUESTS_H
+#define INTEL_GT_REQUESTS_H
+
+struct intel_engine_cs;
+struct intel_timeline;
+
+void intel_engine_init_retire(struct intel_engine_cs *engine);
+void intel_engine_add_retire(struct intel_engine_cs *engine,
+			     struct intel_timeline *tl);
+void intel_engine_fini_retire(struct intel_engine_cs *engine);
+
+#endif /* INTEL_GT_REQUESTS_H */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gt/intel_gt_types.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gt/intel_gt_types.h
@@ -40,6 +40,8 @@
 
 	struct intel_uc uc;
 
+	struct mutex tlb_invalidate_lock;
+
 	struct intel_gt_timelines {
 		spinlock_t lock; /* protects active_list */
 		struct list_head active_list;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gt/intel_lrc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gt/intel_lrc.c
@@ -142,6 +142,7 @@
 #include "intel_engine_pm.h"
 #include "intel_gt.h"
 #include "intel_gt_pm.h"
+#include "intel_gt_requests.h"
 #include "intel_lrc_reg.h"
 #include "intel_mocs.h"
 #include "intel_reset.h"
@@ -471,17 +472,11 @@
 	return desc;
 }
 
-static void unwind_wa_tail(struct i915_request *rq)
-{
-	rq->tail = intel_ring_wrap(rq->ring, rq->wa_tail - WA_TAIL_BYTES);
-	assert_ring_tail_valid(rq->ring, rq->tail);
-}
-
 static struct i915_request *
 __unwind_incomplete_requests(struct intel_engine_cs *engine)
 {
 	struct i915_request *rq, *rn, *active = NULL;
-	struct list_head *uninitialized_var(pl);
+	struct list_head *pl;
 	int prio = I915_PRIORITY_INVALID;
 
 	lockdep_assert_held(&engine->active.lock);
@@ -495,7 +490,6 @@
 			continue; /* XXX */
 
 		__i915_request_unsubmit(rq);
-		unwind_wa_tail(rq);
 
 		/*
 		 * Push the request back into the queue for later resubmission.
@@ -525,7 +519,8 @@
 			 */
 			if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT,
 				     &rq->fence.flags)) {
-				spin_lock(&rq->lock);
+				spin_lock_nested(&rq->lock,
+						 SINGLE_DEPTH_NESTING);
 				i915_request_cancel_breadcrumb(rq);
 				spin_unlock(&rq->lock);
 			}
@@ -612,6 +607,20 @@
 {
 	struct intel_context * const ce = rq->hw_context;
 
+	/*
+	 * NB process_csb() is not under the engine->active.lock and hence
+	 * schedule_out can race with schedule_in meaning that we should
+	 * refrain from doing non-trivial work here.
+	 */
+
+	/*
+	 * If we have just completed this context, the engine may now be
+	 * idle and we want to re-enter powersaving.
+	 */
+	if (list_is_last(&rq->link, &ce->timeline->requests) &&
+	    i915_request_completed(rq))
+		intel_engine_add_retire(engine, ce->timeline);
+
 	intel_engine_context_out(engine);
 	execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_OUT);
 	intel_gt_pm_put(engine->gt);
@@ -649,13 +658,35 @@
 	i915_request_put(rq);
 }
 
-static u64 execlists_update_context(const struct i915_request *rq)
+static u64 execlists_update_context(struct i915_request *rq)
 {
 	struct intel_context *ce = rq->hw_context;
-	u64 desc;
+	u64 desc = ce->lrc_desc;
+	u32 tail, prev;
 
-	ce->lrc_reg_state[CTX_RING_TAIL + 1] =
-		intel_ring_set_tail(rq->ring, rq->tail);
+	/*
+	 * WaIdleLiteRestore:bdw,skl
+	 *
+	 * We should never submit the context with the same RING_TAIL twice
+	 * just in case we submit an empty ring, which confuses the HW.
+	 *
+	 * We append a couple of NOOPs (gen8_emit_wa_tail) after the end of
+	 * the normal request to be able to always advance the RING_TAIL on
+	 * subsequent resubmissions (for lite restore). Should that fail us,
+	 * and we try and submit the same tail again, force the context
+	 * reload.
+	 *
+	 * If we need to return to a preempted context, we need to skip the
+	 * lite-restore and force it to reload the RING_TAIL. Otherwise, the
+	 * HW has a tendency to ignore us rewinding the TAIL to the end of
+	 * an earlier request.
+	 */
+	tail = intel_ring_set_tail(rq->ring, rq->tail);
+	prev = ce->lrc_reg_state[CTX_RING_TAIL + 1];
+	if (unlikely(intel_ring_direction(rq->ring, tail, prev) <= 0))
+		desc |= CTX_DESC_FORCE_RESTORE;
+	ce->lrc_reg_state[CTX_RING_TAIL + 1] = tail;
+	rq->tail = rq->wa_tail;
 
 	/*
 	 * Make sure the context image is complete before we submit it to HW.
@@ -674,7 +705,6 @@
 	 */
 	mb();
 
-	desc = ce->lrc_desc;
 	ce->lrc_desc &= ~CTX_DESC_FORCE_RESTORE;
 
 	return desc;
@@ -918,6 +948,11 @@
 	return *last;
 }
 
+#define for_each_waiter(p__, rq__) \
+	list_for_each_entry_lockless(p__, \
+				     &(rq__)->sched.waiters_list, \
+				     wait_link)
+
 static void defer_request(struct i915_request *rq, struct list_head * const pl)
 {
 	LIST_HEAD(list);
@@ -935,7 +970,7 @@
 		GEM_BUG_ON(i915_request_is_active(rq));
 		list_move_tail(&rq->sched.link, pl);
 
-		list_for_each_entry(p, &rq->sched.waiters_list, wait_link) {
+		for_each_waiter(p, rq) {
 			struct i915_request *w =
 				container_of(p->waiter, typeof(*w), sched);
 
@@ -1101,14 +1136,6 @@
 			 */
 			__unwind_incomplete_requests(engine);
 
-			/*
-			 * If we need to return to the preempted context, we
-			 * need to skip the lite-restore and force it to
-			 * reload the RING_TAIL. Otherwise, the HW has a
-			 * tendency to ignore us rewinding the TAIL to the
-			 * end of an earlier request.
-			 */
-			last->hw_context->lrc_desc |= CTX_DESC_FORCE_RESTORE;
 			last = NULL;
 		} else if (need_timeslice(engine, last) &&
 			   !timer_pending(&engine->execlists.timer)) {
@@ -1149,16 +1176,6 @@
 			if (!list_is_last(&last->sched.link,
 					  &engine->active.requests))
 				return;
-
-			/*
-			 * WaIdleLiteRestore:bdw,skl
-			 * Apply the wa NOOPs to prevent
-			 * ring:HEAD == rq:TAIL as we resubmit the
-			 * request. See gen8_emit_fini_breadcrumb() for
-			 * where we prepare the padding after the
-			 * end of the request.
-			 */
-			last->tail = last->wa_tail;
 		}
 	}
 
@@ -1572,6 +1589,9 @@
 			if (!inject_preempt_hang(execlists))
 				ring_set_paused(engine, 0);
 
+			/* XXX Magic delay for tgl */
+			ENGINE_POSTING_READ(engine, RING_CONTEXT_STATUS_PTR);
+
 			WRITE_ONCE(execlists->pending[0], NULL);
 			break;
 
@@ -2131,6 +2151,14 @@
 	/* WaFlushCoherentL3CacheLinesAtContextSwitch:skl,bxt,glk */
 	batch = gen8_emit_flush_coherentl3_wa(engine, batch);
 
+	/* WaClearSlmSpaceAtContextSwitch:skl,bxt,kbl,glk,cfl */
+	batch = gen8_emit_pipe_control(batch,
+				       PIPE_CONTROL_FLUSH_L3 |
+				       PIPE_CONTROL_GLOBAL_GTT_IVB |
+				       PIPE_CONTROL_CS_STALL |
+				       PIPE_CONTROL_QW_WRITE,
+				       slm_offset(engine));
+
 	batch = emit_lri(batch, lri, ARRAY_SIZE(lri));
 
 	/* WaMediaPoolStateCmdInWABB:bxt,glk */
@@ -2232,6 +2260,9 @@
 static void lrc_destroy_wa_ctx(struct intel_engine_cs *engine)
 {
 	i915_vma_unpin_and_release(&engine->wa_ctx.vma, 0);
+
+	/* Called on error unwind, clear all flags to prevent further use */
+	memset(&engine->wa_ctx, 0, sizeof(engine->wa_ctx));
 }
 
 typedef u32 *(*wa_bb_func_t)(struct intel_engine_cs *engine, u32 *batch);
@@ -2976,6 +3007,9 @@
 static void execlists_park(struct intel_engine_cs *engine)
 {
 	del_timer(&engine->execlists.timer);
+
+	/* Reset upon idling, or we may delay the busy wakeup. */
+	WRITE_ONCE(engine->execlists.queue_priority_hint, INT_MIN);
 }
 
 void intel_execlists_set_default_submission(struct intel_engine_cs *engine)
@@ -3715,9 +3749,11 @@
 	ve->base.i915 = ctx->i915;
 	ve->base.gt = siblings[0]->gt;
 	ve->base.id = -1;
+
 	ve->base.class = OTHER_CLASS;
 	ve->base.uabi_class = I915_ENGINE_CLASS_INVALID;
 	ve->base.instance = I915_ENGINE_CLASS_INVALID_VIRTUAL;
+	ve->base.uabi_instance = I915_ENGINE_CLASS_INVALID_VIRTUAL;
 
 	/*
 	 * The decision on whether to submit a request using semaphores
@@ -3739,6 +3775,7 @@
 	intel_engine_init_active(&ve->base, ENGINE_VIRTUAL);
 
 	intel_engine_init_execlists(&ve->base);
+	ve->base.breadcrumbs.irq_armed = true; /* fake HW, used for irq_work */
 
 	ve->base.cops = &virtual_context_ops;
 	ve->base.request_alloc = execlists_request_alloc;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gt/intel_mocs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gt/intel_mocs.c
@@ -130,7 +130,19 @@
 	GEN9_MOCS_ENTRIES,
 	MOCS_ENTRY(I915_MOCS_CACHED,
 		   LE_3_WB | LE_TC_2_LLC_ELLC | LE_LRUM(3),
-		   L3_3_WB)
+		   L3_3_WB),
+
+	/*
+	 * mocs:63
+	 * - used by the L3 for all of its evictions.
+	 *   Thus it is expected to allow LLC cacheability to enable coherent
+	 *   flows to be maintained.
+	 * - used to force L3 uncachable cycles.
+	 *   Thus it is expected to make the surface L3 uncacheable.
+	 */
+	MOCS_ENTRY(63,
+		   LE_3_WB | LE_TC_1_LLC | LE_LRUM(3),
+		   L3_1_UC)
 };
 
 /* NOTE: the LE_TGT_CACHE is not used on Broxton */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gt/intel_reset.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gt/intel_reset.c
@@ -257,6 +257,7 @@
 static int gen6_hw_domain_reset(struct intel_gt *gt, u32 hw_domain_mask)
 {
 	struct intel_uncore *uncore = gt->uncore;
+	int loops = 2;
 	int err;
 
 	/*
@@ -264,17 +265,38 @@
 	 * for fifo space for the write or forcewake the chip for
 	 * the read
 	 */
-	intel_uncore_write_fw(uncore, GEN6_GDRST, hw_domain_mask);
+	do {
+		intel_uncore_write_fw(uncore, GEN6_GDRST, hw_domain_mask);
 
-	/* Wait for the device to ack the reset requests */
-	err = __intel_wait_for_register_fw(uncore,
-					   GEN6_GDRST, hw_domain_mask, 0,
-					   500, 0,
-					   NULL);
+		/*
+		 * Wait for the device to ack the reset requests.
+		 *
+		 * On some platforms, e.g. Jasperlake, we see that the
+		 * engine register state is not cleared until shortly after
+		 * GDRST reports completion, causing a failure as we try
+		 * to immediately resume while the internal state is still
+		 * in flux. If we immediately repeat the reset, the second
+		 * reset appears to serialise with the first, and since
+		 * it is a no-op, the registers should retain their reset
+		 * value. However, there is still a concern that upon
+		 * leaving the second reset, the internal engine state
+		 * is still in flux and not ready for resuming.
+		 */
+		err = __intel_wait_for_register_fw(uncore, GEN6_GDRST,
+						   hw_domain_mask, 0,
+						   2000, 0,
+						   NULL);
+	} while (err == 0 && --loops);
 	if (err)
 		DRM_DEBUG_DRIVER("Wait for 0x%08x engines reset failed\n",
 				 hw_domain_mask);
 
+	/*
+	 * As we have observed that the engine state is still volatile
+	 * after GDRST is acked, impose a small delay to let everything settle.
+	 */
+	udelay(50);
+
 	return err;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gt/intel_ringbuffer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gt/intel_ringbuffer.c
@@ -1208,7 +1208,7 @@
 	if (unlikely(ret))
 		goto err_unpin;
 
-	if (i915_vma_is_map_and_fenceable(vma))
+	if (i915_vma_is_map_and_fenceable(vma) && !HAS_LLC(vma->vm->i915))
 		addr = (void __force *)i915_vma_pin_iomap(vma);
 	else
 		addr = i915_gem_object_pin_map(vma->obj,
@@ -1220,9 +1220,10 @@
 
 	i915_vma_make_unshrinkable(vma);
 
-	GEM_BUG_ON(ring->vaddr);
-	ring->vaddr = addr;
+	/* Discard any unused bytes beyond that submitted to hw. */
+	intel_ring_reset(ring, ring->emit);
 
+	ring->vaddr = addr;
 	return 0;
 
 err_ring:
@@ -1248,30 +1249,25 @@
 	if (!atomic_dec_and_test(&ring->pin_count))
 		return;
 
-	/* Discard any unused bytes beyond that submitted to hw. */
-	intel_ring_reset(ring, ring->emit);
-
 	i915_vma_unset_ggtt_write(vma);
-	if (i915_vma_is_map_and_fenceable(vma))
+	if (i915_vma_is_map_and_fenceable(vma) && !HAS_LLC(vma->vm->i915))
 		i915_vma_unpin_iomap(vma);
 	else
 		i915_gem_object_unpin_map(vma->obj);
 
-	GEM_BUG_ON(!ring->vaddr);
-	ring->vaddr = NULL;
-
-	i915_vma_unpin(vma);
 	i915_vma_make_purgeable(vma);
+	i915_vma_unpin(vma);
 }
 
 static struct i915_vma *create_ring_vma(struct i915_ggtt *ggtt, int size)
 {
 	struct i915_address_space *vm = &ggtt->vm;
 	struct drm_i915_private *i915 = vm->i915;
-	struct drm_i915_gem_object *obj;
+	struct drm_i915_gem_object *obj = NULL;
 	struct i915_vma *vma;
 
-	obj = i915_gem_object_create_stolen(i915, size);
+	if (!HAS_LLC(i915))
+		obj = i915_gem_object_create_stolen(i915, size);
 	if (!obj)
 		obj = i915_gem_object_create_internal(i915, size);
 	if (IS_ERR(obj))
@@ -1310,8 +1306,9 @@
 		return ERR_PTR(-ENOMEM);
 
 	kref_init(&ring->ref);
-
 	ring->size = size;
+	ring->wrap = BITS_PER_TYPE(ring->size) - ilog2(size);
+
 	/* Workaround an erratum on the i830 which causes a hang if
 	 * the TAIL pointer points to within the last 2 cachelines
 	 * of the buffer.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gt/intel_timeline.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gt/intel_timeline.c
@@ -282,6 +282,7 @@
 {
 	GEM_BUG_ON(atomic_read(&timeline->pin_count));
 	GEM_BUG_ON(!list_empty(&timeline->requests));
+	GEM_BUG_ON(timeline->retire);
 
 	if (timeline->hwsp_cacheline)
 		cacheline_free(timeline->hwsp_cacheline);
@@ -289,6 +290,14 @@
 		i915_gem_object_unpin_map(timeline->hwsp_ggtt->obj);
 
 	i915_vma_put(timeline->hwsp_ggtt);
+
+	/*
+	 * A small race exists between intel_gt_retire_requests_timeout and
+	 * intel_timeline_exit which could result in the syncmap not getting
+	 * free'd. Rather than work to hard to seal this race, simply cleanup
+	 * the syncmap on fini.
+	 */
+	i915_syncmap_free(&timeline->sync);
 }
 
 struct intel_timeline *
@@ -339,15 +348,33 @@
 	struct intel_gt_timelines *timelines = &tl->gt->timelines;
 	unsigned long flags;
 
+	/*
+	 * Pretend we are serialised by the timeline->mutex.
+	 *
+	 * While generally true, there are a few exceptions to the rule
+	 * for the engine->kernel_context being used to manage power
+	 * transitions. As the engine_park may be called from under any
+	 * timeline, it uses the power mutex as a global serialisation
+	 * lock to prevent any other request entering its timeline.
+	 *
+	 * The rule is generally tl->mutex, otherwise engine->wakeref.mutex.
+	 *
+	 * However, intel_gt_retire_request() does not know which engine
+	 * it is retiring along and so cannot partake in the engine-pm
+	 * barrier, and there we use the tl->active_count as a means to
+	 * pin the timeline in the active_list while the locks are dropped.
+	 * Ergo, as that is outside of the engine-pm barrier, we need to
+	 * use atomic to manipulate tl->active_count.
+	 */
 	lockdep_assert_held(&tl->mutex);
-
 	GEM_BUG_ON(!atomic_read(&tl->pin_count));
-	if (tl->active_count++)
+
+	if (atomic_add_unless(&tl->active_count, 1, 0))
 		return;
-	GEM_BUG_ON(!tl->active_count); /* overflow? */
 
 	spin_lock_irqsave(&timelines->lock, flags);
-	list_add(&tl->link, &timelines->active_list);
+	if (!atomic_fetch_inc(&tl->active_count))
+		list_add_tail(&tl->link, &timelines->active_list);
 	spin_unlock_irqrestore(&timelines->lock, flags);
 }
 
@@ -356,14 +383,16 @@
 	struct intel_gt_timelines *timelines = &tl->gt->timelines;
 	unsigned long flags;
 
+	/* See intel_timeline_enter() */
 	lockdep_assert_held(&tl->mutex);
 
-	GEM_BUG_ON(!tl->active_count);
-	if (--tl->active_count)
+	GEM_BUG_ON(!atomic_read(&tl->active_count));
+	if (atomic_add_unless(&tl->active_count, -1, 1))
 		return;
 
 	spin_lock_irqsave(&timelines->lock, flags);
-	list_del(&tl->link);
+	if (atomic_dec_and_test(&tl->active_count))
+		list_del(&tl->link);
 	spin_unlock_irqrestore(&timelines->lock, flags);
 
 	/*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gt/intel_timeline_types.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gt/intel_timeline_types.h
@@ -42,7 +42,7 @@
 	 * from the intel_context caller plus internal atomicity.
 	 */
 	atomic_t pin_count;
-	unsigned int active_count;
+	atomic_t active_count;
 
 	const u32 *hwsp_seqno;
 	struct i915_vma *hwsp_ggtt;
@@ -65,6 +65,9 @@
 	 */
 	struct i915_active_request last_request;
 
+	/** A chain of completed timelines ready for early retirement. */
+	struct intel_timeline *retire;
+
 	/**
 	 * We track the most recent seqno that we wait on in every context so
 	 * that we only have to emit a new await and dependency on a more
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gvt/cmd_parser.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gvt/cmd_parser.c
@@ -963,18 +963,6 @@
 	int i, ret = 0;
 	int cmd_len = cmd_length(s);
 	struct intel_gvt *gvt = s->vgpu->gvt;
-	u32 valid_len = CMD_LEN(1);
-
-	/*
-	 * Official intel docs are somewhat sloppy , check the definition of
-	 * MI_LOAD_REGISTER_IMM.
-	 */
-	#define MAX_VALID_LEN 127
-	if ((cmd_len < valid_len) || (cmd_len > MAX_VALID_LEN)) {
-		gvt_err("len is not valid:  len=%u  valid_len=%u\n",
-			cmd_len, valid_len);
-		return -EFAULT;
-	}
 
 	for (i = 1; i < cmd_len; i += 2) {
 		if (IS_BROADWELL(gvt->dev_priv) && s->ring_id != RCS0) {
@@ -1597,9 +1585,9 @@
 	if (!(cmd_val(s, 0) & (1 << 22)))
 		return ret;
 
-	/* check if QWORD */
-	if (DWORD_FIELD(0, 20, 19) == 1)
-		valid_len += 8;
+	/* check inline data */
+	if (cmd_val(s, 0) & BIT(18))
+		valid_len = CMD_LEN(9);
 	ret = gvt_check_valid_cmd_length(cmd_length(s),
 			valid_len);
 	if (ret)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gvt/display.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gvt/display.c
@@ -172,21 +172,176 @@
 	int pipe;
 
 	if (IS_BROXTON(dev_priv)) {
+		enum transcoder trans;
+		enum port port;
+
+		/* Clear PIPE, DDI, PHY, HPD before setting new */
 		vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) &= ~(BXT_DE_PORT_HP_DDIA |
 			BXT_DE_PORT_HP_DDIB |
 			BXT_DE_PORT_HP_DDIC);
 
+		for_each_pipe(dev_priv, pipe) {
+			vgpu_vreg_t(vgpu, PIPECONF(pipe)) &=
+				~(PIPECONF_ENABLE | I965_PIPECONF_ACTIVE);
+			vgpu_vreg_t(vgpu, DSPCNTR(pipe)) &= ~DISPLAY_PLANE_ENABLE;
+			vgpu_vreg_t(vgpu, SPRCTL(pipe)) &= ~SPRITE_ENABLE;
+			vgpu_vreg_t(vgpu, CURCNTR(pipe)) &= ~MCURSOR_MODE;
+			vgpu_vreg_t(vgpu, CURCNTR(pipe)) |= MCURSOR_MODE_DISABLE;
+		}
+
+		for (trans = TRANSCODER_A; trans <= TRANSCODER_EDP; trans++) {
+			vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(trans)) &=
+				~(TRANS_DDI_BPC_MASK | TRANS_DDI_MODE_SELECT_MASK |
+				  TRANS_DDI_PORT_MASK | TRANS_DDI_FUNC_ENABLE);
+		}
+		vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) &=
+			~(TRANS_DDI_BPC_MASK | TRANS_DDI_MODE_SELECT_MASK |
+			  TRANS_DDI_PORT_MASK);
+
+		for (port = PORT_A; port <= PORT_C; port++) {
+			vgpu_vreg_t(vgpu, BXT_PHY_CTL(port)) &=
+				~BXT_PHY_LANE_ENABLED;
+			vgpu_vreg_t(vgpu, BXT_PHY_CTL(port)) |=
+				(BXT_PHY_CMNLANE_POWERDOWN_ACK |
+				 BXT_PHY_LANE_POWERDOWN_ACK);
+
+			vgpu_vreg_t(vgpu, BXT_PORT_PLL_ENABLE(port)) &=
+				~(PORT_PLL_POWER_STATE | PORT_PLL_POWER_ENABLE |
+				  PORT_PLL_REF_SEL | PORT_PLL_LOCK |
+				  PORT_PLL_ENABLE);
+
+			vgpu_vreg_t(vgpu, DDI_BUF_CTL(port)) &=
+				~(DDI_INIT_DISPLAY_DETECTED |
+				  DDI_BUF_CTL_ENABLE);
+			vgpu_vreg_t(vgpu, DDI_BUF_CTL(port)) |= DDI_BUF_IS_IDLE;
+		}
+		vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) &=
+			~(PORTA_HOTPLUG_ENABLE | PORTA_HOTPLUG_STATUS_MASK);
+		vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) &=
+			~(PORTB_HOTPLUG_ENABLE | PORTB_HOTPLUG_STATUS_MASK);
+		vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) &=
+			~(PORTC_HOTPLUG_ENABLE | PORTC_HOTPLUG_STATUS_MASK);
+		/* No hpd_invert set in vgpu vbt, need to clear invert mask */
+		vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) &= ~BXT_DDI_HPD_INVERT_MASK;
+		vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) &= ~BXT_DE_PORT_HOTPLUG_MASK;
+
+		vgpu_vreg_t(vgpu, BXT_P_CR_GT_DISP_PWRON) &= ~(BIT(0) | BIT(1));
+		vgpu_vreg_t(vgpu, BXT_PORT_CL1CM_DW0(DPIO_PHY0)) &=
+			~PHY_POWER_GOOD;
+		vgpu_vreg_t(vgpu, BXT_PORT_CL1CM_DW0(DPIO_PHY1)) &=
+			~PHY_POWER_GOOD;
+		vgpu_vreg_t(vgpu, BXT_PHY_CTL_FAMILY(DPIO_PHY0)) &= ~BIT(30);
+		vgpu_vreg_t(vgpu, BXT_PHY_CTL_FAMILY(DPIO_PHY1)) &= ~BIT(30);
+
+		vgpu_vreg_t(vgpu, SFUSE_STRAP) &= ~SFUSE_STRAP_DDIB_DETECTED;
+		vgpu_vreg_t(vgpu, SFUSE_STRAP) &= ~SFUSE_STRAP_DDIC_DETECTED;
+
+		/*
+		 * Only 1 PIPE enabled in current vGPU display and PIPE_A is
+		 *  tied to TRANSCODER_A in HW, so it's safe to assume PIPE_A,
+		 *   TRANSCODER_A can be enabled. PORT_x depends on the input of
+		 *   setup_virtual_dp_monitor.
+		 */
+		vgpu_vreg_t(vgpu, PIPECONF(PIPE_A)) |= PIPECONF_ENABLE;
+		vgpu_vreg_t(vgpu, PIPECONF(PIPE_A)) |= I965_PIPECONF_ACTIVE;
+
+		/*
+		 * Golden M/N are calculated based on:
+		 *   24 bpp, 4 lanes, 154000 pixel clk (from virtual EDID),
+		 *   DP link clk 1620 MHz and non-constant_n.
+		 * TODO: calculate DP link symbol clk and stream clk m/n.
+		 */
+		vgpu_vreg_t(vgpu, PIPE_DATA_M1(TRANSCODER_A)) = 63 << TU_SIZE_SHIFT;
+		vgpu_vreg_t(vgpu, PIPE_DATA_M1(TRANSCODER_A)) |= 0x5b425e;
+		vgpu_vreg_t(vgpu, PIPE_DATA_N1(TRANSCODER_A)) = 0x800000;
+		vgpu_vreg_t(vgpu, PIPE_LINK_M1(TRANSCODER_A)) = 0x3cd6e;
+		vgpu_vreg_t(vgpu, PIPE_LINK_N1(TRANSCODER_A)) = 0x80000;
+
+		/* Enable per-DDI/PORT vreg */
 		if (intel_vgpu_has_monitor_on_port(vgpu, PORT_A)) {
+			vgpu_vreg_t(vgpu, BXT_P_CR_GT_DISP_PWRON) |= BIT(1);
+			vgpu_vreg_t(vgpu, BXT_PORT_CL1CM_DW0(DPIO_PHY1)) |=
+				PHY_POWER_GOOD;
+			vgpu_vreg_t(vgpu, BXT_PHY_CTL_FAMILY(DPIO_PHY1)) |=
+				BIT(30);
+			vgpu_vreg_t(vgpu, BXT_PHY_CTL(PORT_A)) |=
+				BXT_PHY_LANE_ENABLED;
+			vgpu_vreg_t(vgpu, BXT_PHY_CTL(PORT_A)) &=
+				~(BXT_PHY_CMNLANE_POWERDOWN_ACK |
+				  BXT_PHY_LANE_POWERDOWN_ACK);
+			vgpu_vreg_t(vgpu, BXT_PORT_PLL_ENABLE(PORT_A)) |=
+				(PORT_PLL_POWER_STATE | PORT_PLL_POWER_ENABLE |
+				 PORT_PLL_REF_SEL | PORT_PLL_LOCK |
+				 PORT_PLL_ENABLE);
+			vgpu_vreg_t(vgpu, DDI_BUF_CTL(PORT_A)) |=
+				(DDI_BUF_CTL_ENABLE | DDI_INIT_DISPLAY_DETECTED);
+			vgpu_vreg_t(vgpu, DDI_BUF_CTL(PORT_A)) &=
+				~DDI_BUF_IS_IDLE;
+			vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_EDP)) |=
+				(TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DP_SST |
+				 TRANS_DDI_FUNC_ENABLE);
+			vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) |=
+				PORTA_HOTPLUG_ENABLE;
 			vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) |=
 				BXT_DE_PORT_HP_DDIA;
 		}
 
 		if (intel_vgpu_has_monitor_on_port(vgpu, PORT_B)) {
+			vgpu_vreg_t(vgpu, SFUSE_STRAP) |= SFUSE_STRAP_DDIB_DETECTED;
+			vgpu_vreg_t(vgpu, BXT_P_CR_GT_DISP_PWRON) |= BIT(0);
+			vgpu_vreg_t(vgpu, BXT_PORT_CL1CM_DW0(DPIO_PHY0)) |=
+				PHY_POWER_GOOD;
+			vgpu_vreg_t(vgpu, BXT_PHY_CTL_FAMILY(DPIO_PHY0)) |=
+				BIT(30);
+			vgpu_vreg_t(vgpu, BXT_PHY_CTL(PORT_B)) |=
+				BXT_PHY_LANE_ENABLED;
+			vgpu_vreg_t(vgpu, BXT_PHY_CTL(PORT_B)) &=
+				~(BXT_PHY_CMNLANE_POWERDOWN_ACK |
+				  BXT_PHY_LANE_POWERDOWN_ACK);
+			vgpu_vreg_t(vgpu, BXT_PORT_PLL_ENABLE(PORT_B)) |=
+				(PORT_PLL_POWER_STATE | PORT_PLL_POWER_ENABLE |
+				 PORT_PLL_REF_SEL | PORT_PLL_LOCK |
+				 PORT_PLL_ENABLE);
+			vgpu_vreg_t(vgpu, DDI_BUF_CTL(PORT_B)) |=
+				DDI_BUF_CTL_ENABLE;
+			vgpu_vreg_t(vgpu, DDI_BUF_CTL(PORT_B)) &=
+				~DDI_BUF_IS_IDLE;
+			vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) |=
+				(TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DP_SST |
+				 (PORT_B << TRANS_DDI_PORT_SHIFT) |
+				 TRANS_DDI_FUNC_ENABLE);
+			vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) |=
+				PORTB_HOTPLUG_ENABLE;
 			vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) |=
 				BXT_DE_PORT_HP_DDIB;
 		}
 
 		if (intel_vgpu_has_monitor_on_port(vgpu, PORT_C)) {
+			vgpu_vreg_t(vgpu, SFUSE_STRAP) |= SFUSE_STRAP_DDIC_DETECTED;
+			vgpu_vreg_t(vgpu, BXT_P_CR_GT_DISP_PWRON) |= BIT(0);
+			vgpu_vreg_t(vgpu, BXT_PORT_CL1CM_DW0(DPIO_PHY0)) |=
+				PHY_POWER_GOOD;
+			vgpu_vreg_t(vgpu, BXT_PHY_CTL_FAMILY(DPIO_PHY0)) |=
+				BIT(30);
+			vgpu_vreg_t(vgpu, BXT_PHY_CTL(PORT_C)) |=
+				BXT_PHY_LANE_ENABLED;
+			vgpu_vreg_t(vgpu, BXT_PHY_CTL(PORT_C)) &=
+				~(BXT_PHY_CMNLANE_POWERDOWN_ACK |
+				  BXT_PHY_LANE_POWERDOWN_ACK);
+			vgpu_vreg_t(vgpu, BXT_PORT_PLL_ENABLE(PORT_C)) |=
+				(PORT_PLL_POWER_STATE | PORT_PLL_POWER_ENABLE |
+				 PORT_PLL_REF_SEL | PORT_PLL_LOCK |
+				 PORT_PLL_ENABLE);
+			vgpu_vreg_t(vgpu, DDI_BUF_CTL(PORT_C)) |=
+				DDI_BUF_CTL_ENABLE;
+			vgpu_vreg_t(vgpu, DDI_BUF_CTL(PORT_C)) &=
+				~DDI_BUF_IS_IDLE;
+			vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) |=
+				(TRANS_DDI_BPC_8 | TRANS_DDI_MODE_SELECT_DP_SST |
+				 (PORT_B << TRANS_DDI_PORT_SHIFT) |
+				 TRANS_DDI_FUNC_ENABLE);
+			vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) |=
+				PORTC_HOTPLUG_ENABLE;
 			vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) |=
 				BXT_DE_PORT_HP_DDIC;
 		}
@@ -207,14 +362,41 @@
 				SKL_FUSE_PG_DIST_STATUS(SKL_PG0) |
 				SKL_FUSE_PG_DIST_STATUS(SKL_PG1) |
 				SKL_FUSE_PG_DIST_STATUS(SKL_PG2);
-		vgpu_vreg_t(vgpu, LCPLL1_CTL) |=
-				LCPLL_PLL_ENABLE |
-				LCPLL_PLL_LOCK;
-		vgpu_vreg_t(vgpu, LCPLL2_CTL) |= LCPLL_PLL_ENABLE;
-
+		/*
+		 * Only 1 PIPE enabled in current vGPU display and PIPE_A is
+		 *  tied to TRANSCODER_A in HW, so it's safe to assume PIPE_A,
+		 *   TRANSCODER_A can be enabled. PORT_x depends on the input of
+		 *   setup_virtual_dp_monitor, we can bind DPLL0 to any PORT_x
+		 *   so we fixed to DPLL0 here.
+		 * Setup DPLL0: DP link clk 1620 MHz, non SSC, DP Mode
+		 */
+		vgpu_vreg_t(vgpu, DPLL_CTRL1) =
+			DPLL_CTRL1_OVERRIDE(DPLL_ID_SKL_DPLL0);
+		vgpu_vreg_t(vgpu, DPLL_CTRL1) |=
+			DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, DPLL_ID_SKL_DPLL0);
+		vgpu_vreg_t(vgpu, LCPLL1_CTL) =
+			LCPLL_PLL_ENABLE | LCPLL_PLL_LOCK;
+		vgpu_vreg_t(vgpu, DPLL_STATUS) = DPLL_LOCK(DPLL_ID_SKL_DPLL0);
+		/*
+		 * Golden M/N are calculated based on:
+		 *   24 bpp, 4 lanes, 154000 pixel clk (from virtual EDID),
+		 *   DP link clk 1620 MHz and non-constant_n.
+		 * TODO: calculate DP link symbol clk and stream clk m/n.
+		 */
+		vgpu_vreg_t(vgpu, PIPE_DATA_M1(TRANSCODER_A)) = 63 << TU_SIZE_SHIFT;
+		vgpu_vreg_t(vgpu, PIPE_DATA_M1(TRANSCODER_A)) |= 0x5b425e;
+		vgpu_vreg_t(vgpu, PIPE_DATA_N1(TRANSCODER_A)) = 0x800000;
+		vgpu_vreg_t(vgpu, PIPE_LINK_M1(TRANSCODER_A)) = 0x3cd6e;
+		vgpu_vreg_t(vgpu, PIPE_LINK_N1(TRANSCODER_A)) = 0x80000;
 	}
 
 	if (intel_vgpu_has_monitor_on_port(vgpu, PORT_B)) {
+		vgpu_vreg_t(vgpu, DPLL_CTRL2) &=
+			~DPLL_CTRL2_DDI_CLK_OFF(PORT_B);
+		vgpu_vreg_t(vgpu, DPLL_CTRL2) |=
+			DPLL_CTRL2_DDI_CLK_SEL(DPLL_ID_SKL_DPLL0, PORT_B);
+		vgpu_vreg_t(vgpu, DPLL_CTRL2) |=
+			DPLL_CTRL2_DDI_SEL_OVERRIDE(PORT_B);
 		vgpu_vreg_t(vgpu, SFUSE_STRAP) |= SFUSE_STRAP_DDIB_DETECTED;
 		vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) &=
 			~(TRANS_DDI_BPC_MASK | TRANS_DDI_MODE_SELECT_MASK |
@@ -235,6 +417,12 @@
 	}
 
 	if (intel_vgpu_has_monitor_on_port(vgpu, PORT_C)) {
+		vgpu_vreg_t(vgpu, DPLL_CTRL2) &=
+			~DPLL_CTRL2_DDI_CLK_OFF(PORT_C);
+		vgpu_vreg_t(vgpu, DPLL_CTRL2) |=
+			DPLL_CTRL2_DDI_CLK_SEL(DPLL_ID_SKL_DPLL0, PORT_C);
+		vgpu_vreg_t(vgpu, DPLL_CTRL2) |=
+			DPLL_CTRL2_DDI_SEL_OVERRIDE(PORT_C);
 		vgpu_vreg_t(vgpu, SDEISR) |= SDE_PORTC_HOTPLUG_CPT;
 		vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) &=
 			~(TRANS_DDI_BPC_MASK | TRANS_DDI_MODE_SELECT_MASK |
@@ -255,6 +443,12 @@
 	}
 
 	if (intel_vgpu_has_monitor_on_port(vgpu, PORT_D)) {
+		vgpu_vreg_t(vgpu, DPLL_CTRL2) &=
+			~DPLL_CTRL2_DDI_CLK_OFF(PORT_D);
+		vgpu_vreg_t(vgpu, DPLL_CTRL2) |=
+			DPLL_CTRL2_DDI_CLK_SEL(DPLL_ID_SKL_DPLL0, PORT_D);
+		vgpu_vreg_t(vgpu, DPLL_CTRL2) |=
+			DPLL_CTRL2_DDI_SEL_OVERRIDE(PORT_D);
 		vgpu_vreg_t(vgpu, SDEISR) |= SDE_PORTD_HOTPLUG_CPT;
 		vgpu_vreg_t(vgpu, TRANS_DDI_FUNC_CTL(TRANSCODER_A)) &=
 			~(TRANS_DDI_BPC_MASK | TRANS_DDI_MODE_SELECT_MASK |
@@ -457,7 +651,8 @@
 	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
 
 	/* TODO: add more platforms support */
-	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
+	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv) ||
+		IS_COFFEELAKE(dev_priv)) {
 		if (connected) {
 			vgpu_vreg_t(vgpu, SFUSE_STRAP) |=
 				SFUSE_STRAP_DDID_DETECTED;
@@ -471,6 +666,63 @@
 		vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) |=
 				PORTD_HOTPLUG_STATUS_MASK;
 		intel_vgpu_trigger_virtual_event(vgpu, DP_D_HOTPLUG);
+	} else if (IS_BROXTON(dev_priv)) {
+		if (intel_vgpu_has_monitor_on_port(vgpu, PORT_A)) {
+			if (connected) {
+				vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) |=
+					BXT_DE_PORT_HP_DDIA;
+			} else {
+				vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) &=
+					~BXT_DE_PORT_HP_DDIA;
+			}
+			vgpu_vreg_t(vgpu, GEN8_DE_PORT_IIR) |=
+				BXT_DE_PORT_HP_DDIA;
+			vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) &=
+				~PORTA_HOTPLUG_STATUS_MASK;
+			vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) |=
+				PORTA_HOTPLUG_LONG_DETECT;
+			intel_vgpu_trigger_virtual_event(vgpu, DP_A_HOTPLUG);
+		}
+		if (intel_vgpu_has_monitor_on_port(vgpu, PORT_B)) {
+			if (connected) {
+				vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) |=
+					BXT_DE_PORT_HP_DDIB;
+				vgpu_vreg_t(vgpu, SFUSE_STRAP) |=
+					SFUSE_STRAP_DDIB_DETECTED;
+			} else {
+				vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) &=
+					~BXT_DE_PORT_HP_DDIB;
+				vgpu_vreg_t(vgpu, SFUSE_STRAP) &=
+					~SFUSE_STRAP_DDIB_DETECTED;
+			}
+			vgpu_vreg_t(vgpu, GEN8_DE_PORT_IIR) |=
+				BXT_DE_PORT_HP_DDIB;
+			vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) &=
+				~PORTB_HOTPLUG_STATUS_MASK;
+			vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) |=
+				PORTB_HOTPLUG_LONG_DETECT;
+			intel_vgpu_trigger_virtual_event(vgpu, DP_B_HOTPLUG);
+		}
+		if (intel_vgpu_has_monitor_on_port(vgpu, PORT_C)) {
+			if (connected) {
+				vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) |=
+					BXT_DE_PORT_HP_DDIC;
+				vgpu_vreg_t(vgpu, SFUSE_STRAP) |=
+					SFUSE_STRAP_DDIC_DETECTED;
+			} else {
+				vgpu_vreg_t(vgpu, GEN8_DE_PORT_ISR) &=
+					~BXT_DE_PORT_HP_DDIC;
+				vgpu_vreg_t(vgpu, SFUSE_STRAP) &=
+					~SFUSE_STRAP_DDIC_DETECTED;
+			}
+			vgpu_vreg_t(vgpu, GEN8_DE_PORT_IIR) |=
+				BXT_DE_PORT_HP_DDIC;
+			vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) &=
+				~PORTC_HOTPLUG_STATUS_MASK;
+			vgpu_vreg_t(vgpu, PCH_PORT_HOTPLUG) |=
+				PORTC_HOTPLUG_LONG_DETECT;
+			intel_vgpu_trigger_virtual_event(vgpu, DP_C_HOTPLUG);
+		}
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gvt/dmabuf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gvt/dmabuf.c
@@ -96,12 +96,12 @@
 			dmabuf_obj = container_of(pos,
 					struct intel_vgpu_dmabuf_obj, list);
 			if (dmabuf_obj == obj) {
+				list_del(pos);
 				intel_gvt_hypervisor_put_vfio_device(vgpu);
 				idr_remove(&vgpu->object_idr,
 					   dmabuf_obj->dmabuf_id);
 				kfree(dmabuf_obj->info);
 				kfree(dmabuf_obj);
-				list_del(pos);
 				break;
 			}
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gvt/gtt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gvt/gtt.c
@@ -1186,10 +1186,8 @@
 	for_each_shadow_entry(sub_spt, &sub_se, sub_index) {
 		ret = intel_gvt_hypervisor_dma_map_guest_page(vgpu,
 				start_gfn + sub_index, PAGE_SIZE, &dma_addr);
-		if (ret) {
-			ppgtt_invalidate_spt(spt);
-			return ret;
-		}
+		if (ret)
+			goto err;
 		sub_se.val64 = se->val64;
 
 		/* Copy the PAT field from PDE. */
@@ -1208,6 +1206,17 @@
 	ops->set_pfn(se, sub_spt->shadow_page.mfn);
 	ppgtt_set_shadow_entry(spt, se, index);
 	return 0;
+err:
+	/* Cancel the existing addess mappings of DMA addr. */
+	for_each_present_shadow_entry(sub_spt, &sub_se, sub_index) {
+		gvt_vdbg_mm("invalidate 4K entry\n");
+		ppgtt_invalidate_pte(sub_spt, &sub_se);
+	}
+	/* Release the new allocated spt. */
+	trace_spt_change(sub_spt->vgpu->id, "release", sub_spt,
+		sub_spt->guest_page.gfn, sub_spt->shadow_page.type);
+	ppgtt_free_spt(sub_spt);
+	return ret;
 }
 
 static int split_64KB_gtt_entry(struct intel_vgpu *vgpu,
@@ -1956,7 +1965,11 @@
 
 	if (mm->type == INTEL_GVT_MM_PPGTT) {
 		list_del(&mm->ppgtt_mm.list);
+
+		mutex_lock(&mm->vgpu->gvt->gtt.ppgtt_mm_lock);
 		list_del(&mm->ppgtt_mm.lru_list);
+		mutex_unlock(&mm->vgpu->gvt->gtt.ppgtt_mm_lock);
+
 		invalidate_ppgtt_mm(mm);
 	} else {
 		vfree(mm->ggtt_mm.virtual_ggtt);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gvt/gvt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gvt/gvt.c
@@ -128,7 +128,7 @@
 	return true;
 }
 
-static bool intel_gvt_init_vgpu_type_groups(struct intel_gvt *gvt)
+static int intel_gvt_init_vgpu_type_groups(struct intel_gvt *gvt)
 {
 	int i, j;
 	struct intel_vgpu_type *type;
@@ -146,7 +146,7 @@
 		gvt_vgpu_type_groups[i] = group;
 	}
 
-	return true;
+	return 0;
 
 unwind:
 	for (j = 0; j < i; j++) {
@@ -154,7 +154,7 @@
 		kfree(group);
 	}
 
-	return false;
+	return -ENOMEM;
 }
 
 static void intel_gvt_cleanup_vgpu_type_groups(struct intel_gvt *gvt)
@@ -362,7 +362,7 @@
 		goto out_clean_thread;
 
 	ret = intel_gvt_init_vgpu_type_groups(gvt);
-	if (ret == false) {
+	if (ret) {
 		gvt_err("failed to init vgpu type groups: %d\n", ret);
 		goto out_clean_types;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gvt/handlers.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gvt/handlers.c
@@ -654,7 +654,7 @@
 	else if (FDI_RX_IMR_TO_PIPE(offset) != INVALID_INDEX)
 		index = FDI_RX_IMR_TO_PIPE(offset);
 	else {
-		gvt_vgpu_err("Unsupport registers %x\n", offset);
+		gvt_vgpu_err("Unsupported registers %x\n", offset);
 		return -EINVAL;
 	}
 
@@ -1632,6 +1632,34 @@
 	return 0;
 }
 
+/**
+ * FixMe:
+ * If guest fills non-priv batch buffer on ApolloLake/Broxton as Mesa i965 did:
+ * 717e7539124d (i965: Use a WC map and memcpy for the batch instead of pwrite.)
+ * Due to the missing flush of bb filled by VM vCPU, host GPU hangs on executing
+ * these MI_BATCH_BUFFER.
+ * Temporarily workaround this by setting SNOOP bit for PAT3 used by PPGTT
+ * PML4 PTE: PAT(0) PCD(1) PWT(1).
+ * The performance is still expected to be low, will need further improvement.
+ */
+static int bxt_ppat_low_write(struct intel_vgpu *vgpu, unsigned int offset,
+			      void *p_data, unsigned int bytes)
+{
+	u64 pat =
+		GEN8_PPAT(0, CHV_PPAT_SNOOP) |
+		GEN8_PPAT(1, 0) |
+		GEN8_PPAT(2, 0) |
+		GEN8_PPAT(3, CHV_PPAT_SNOOP) |
+		GEN8_PPAT(4, CHV_PPAT_SNOOP) |
+		GEN8_PPAT(5, CHV_PPAT_SNOOP) |
+		GEN8_PPAT(6, CHV_PPAT_SNOOP) |
+		GEN8_PPAT(7, CHV_PPAT_SNOOP);
+
+	vgpu_vreg(vgpu, offset) = lower_32_bits(pat);
+
+	return 0;
+}
+
 static int mmio_read_from_hw(struct intel_vgpu *vgpu,
 		unsigned int offset, void *p_data, unsigned int bytes)
 {
@@ -2778,7 +2806,7 @@
 
 	MMIO_DH(GEN6_PCODE_MAILBOX, D_BDW_PLUS, NULL, mailbox_write);
 
-	MMIO_D(GEN8_PRIVATE_PAT_LO, D_BDW_PLUS);
+	MMIO_D(GEN8_PRIVATE_PAT_LO, D_BDW_PLUS & ~D_BXT);
 	MMIO_D(GEN8_PRIVATE_PAT_HI, D_BDW_PLUS);
 
 	MMIO_D(GAMTARBMODE, D_BDW_PLUS);
@@ -3103,8 +3131,8 @@
 	MMIO_DFH(GEN9_WM_CHICKEN3, D_SKL_PLUS, F_MODE_MASK | F_CMD_ACCESS,
 		 NULL, NULL);
 
-	MMIO_D(GAMT_CHKN_BIT_REG, D_KBL);
-	MMIO_D(GEN9_CTX_PREEMPT_REG, D_KBL | D_SKL);
+	MMIO_D(GAMT_CHKN_BIT_REG, D_KBL | D_CFL);
+	MMIO_D(GEN9_CTX_PREEMPT_REG, D_SKL_PLUS & ~D_BXT);
 
 	return 0;
 }
@@ -3278,9 +3306,17 @@
 	MMIO_D(GEN8_PUSHBUS_SHIFT, D_BXT);
 	MMIO_D(GEN6_GFXPAUSE, D_BXT);
 	MMIO_DFH(GEN8_L3SQCREG1, D_BXT, F_CMD_ACCESS, NULL, NULL);
+	MMIO_DFH(GEN8_L3CNTLREG, D_BXT, F_CMD_ACCESS, NULL, NULL);
+	MMIO_DFH(_MMIO(0x20D8), D_BXT, F_CMD_ACCESS, NULL, NULL);
+	MMIO_F(HSW_CS_GPR(0), 0x40, F_CMD_ACCESS, 0, 0, D_BXT, NULL, NULL);
+	MMIO_F(_MMIO(0x12600), 0x40, F_CMD_ACCESS, 0, 0, D_BXT, NULL, NULL);
+	MMIO_F(BCS_GPR(0), 0x40, F_CMD_ACCESS, 0, 0, D_BXT, NULL, NULL);
+	MMIO_F(_MMIO(0x1a600), 0x40, F_CMD_ACCESS, 0, 0, D_BXT, NULL, NULL);
 
 	MMIO_DFH(GEN9_CTX_PREEMPT_REG, D_BXT, F_CMD_ACCESS, NULL, NULL);
 
+	MMIO_DH(GEN8_PRIVATE_PAT_LO, D_BXT, NULL, bxt_ppat_low_write);
+
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gvt/mmio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gvt/mmio.c
@@ -271,6 +271,11 @@
 			vgpu_vreg_t(vgpu, BXT_PHY_CTL(PORT_C)) |=
 				    BXT_PHY_CMNLANE_POWERDOWN_ACK |
 				    BXT_PHY_LANE_POWERDOWN_ACK;
+			vgpu_vreg_t(vgpu, SKL_FUSE_STATUS) |=
+				SKL_FUSE_DOWNLOAD_STATUS |
+				SKL_FUSE_PG_DIST_STATUS(SKL_PG0) |
+				SKL_FUSE_PG_DIST_STATUS(SKL_PG1) |
+				SKL_FUSE_PG_DIST_STATUS(SKL_PG2);
 		}
 	} else {
 #define GVT_GEN8_MMIO_RESET_OFFSET		(0x44200)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gvt/scheduler.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gvt/scheduler.c
@@ -374,7 +374,11 @@
 		for (i = 0; i < GVT_RING_CTX_NR_PDPS; i++) {
 			struct i915_page_directory * const pd =
 				i915_pd_entry(ppgtt->pd, i);
-
+			/* skip now as current i915 ppgtt alloc won't allocate
+			   top level pdp for non 4-level table, won't impact
+			   shadow ppgtt. */
+			if (!pd)
+				break;
 			px_dma(pd) = mm->ppgtt_mm.shadow_pdps[i];
 		}
 	}
@@ -628,6 +632,7 @@
 
 	if (workload->shadow_mm->type != INTEL_GVT_MM_PPGTT ||
 	    !workload->shadow_mm->ppgtt_mm.shadowed) {
+		intel_vgpu_unpin_mm(workload->shadow_mm);
 		gvt_vgpu_err("workload shadow ppgtt isn't ready\n");
 		return -EINVAL;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/gvt/vgpu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/gvt/vgpu.c
@@ -272,10 +272,17 @@
 {
 	struct intel_gvt *gvt = vgpu->gvt;
 
-	mutex_lock(&vgpu->vgpu_lock);
-
 	WARN(vgpu->active, "vGPU is still active!\n");
 
+	/*
+	 * remove idr first so later clean can judge if need to stop
+	 * service if no active vgpu.
+	 */
+	mutex_lock(&gvt->lock);
+	idr_remove(&gvt->vgpu_idr, vgpu->id);
+	mutex_unlock(&gvt->lock);
+
+	mutex_lock(&vgpu->vgpu_lock);
 	intel_gvt_debugfs_remove_vgpu(vgpu);
 	intel_vgpu_clean_sched_policy(vgpu);
 	intel_vgpu_clean_submission(vgpu);
@@ -290,7 +297,6 @@
 	mutex_unlock(&vgpu->vgpu_lock);
 
 	mutex_lock(&gvt->lock);
-	idr_remove(&gvt->vgpu_idr, vgpu->id);
 	if (idr_is_empty(&gvt->vgpu_idr))
 		intel_gvt_clean_irq(gvt);
 	intel_gvt_update_vgpu_types(gvt);
@@ -426,8 +432,9 @@
 	if (ret)
 		goto out_clean_sched_policy;
 
-	/*TODO: add more platforms support */
-	if (IS_SKYLAKE(gvt->dev_priv) || IS_KABYLAKE(gvt->dev_priv))
+	if (IS_BROADWELL(gvt->dev_priv) || IS_BROXTON(gvt->dev_priv))
+		ret = intel_gvt_hypervisor_set_edid(vgpu, PORT_B);
+	else
 		ret = intel_gvt_hypervisor_set_edid(vgpu, PORT_D);
 	if (ret)
 		goto out_clean_sched_policy;
@@ -560,9 +567,9 @@
 
 		intel_vgpu_reset_mmio(vgpu, dmlr);
 		populate_pvinfo_page(vgpu);
-		intel_vgpu_reset_display(vgpu);
 
 		if (dmlr) {
+			intel_vgpu_reset_display(vgpu);
 			intel_vgpu_reset_cfg_space(vgpu);
 			/* only reset the failsafe mode when dmlr reset */
 			vgpu->failsafe = false;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/i915_active.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/i915_active.c
@@ -121,7 +121,7 @@
 #endif
 
 static void
-__active_retire(struct i915_active *ref)
+__active_retire(struct i915_active *ref, bool lock)
 {
 	struct active_node *it, *n;
 	struct rb_root root;
@@ -138,7 +138,8 @@
 		retire = true;
 	}
 
-	mutex_unlock(&ref->mutex);
+	if (likely(lock))
+		mutex_unlock(&ref->mutex);
 	if (!retire)
 		return;
 
@@ -153,21 +154,28 @@
 }
 
 static void
-active_retire(struct i915_active *ref)
+active_retire(struct i915_active *ref, bool lock)
 {
 	GEM_BUG_ON(!atomic_read(&ref->count));
 	if (atomic_add_unless(&ref->count, -1, 1))
 		return;
 
 	/* One active may be flushed from inside the acquire of another */
-	mutex_lock_nested(&ref->mutex, SINGLE_DEPTH_NESTING);
-	__active_retire(ref);
+	if (likely(lock))
+		mutex_lock_nested(&ref->mutex, SINGLE_DEPTH_NESTING);
+	__active_retire(ref, lock);
 }
 
 static void
 node_retire(struct i915_active_request *base, struct i915_request *rq)
 {
-	active_retire(node_from_active(base)->ref);
+	active_retire(node_from_active(base)->ref, true);
+}
+
+static void
+node_retire_nolock(struct i915_active_request *base, struct i915_request *rq)
+{
+	active_retire(node_from_active(base)->ref, false);
 }
 
 static struct i915_active_request *
@@ -364,7 +372,7 @@
 void i915_active_release(struct i915_active *ref)
 {
 	debug_active_assert(ref);
-	active_retire(ref);
+	active_retire(ref, true);
 }
 
 static void __active_ungrab(struct i915_active *ref)
@@ -391,7 +399,7 @@
 {
 	GEM_BUG_ON(!test_bit(I915_ACTIVE_GRAB_BIT, &ref->flags));
 
-	active_retire(ref);
+	active_retire(ref, true);
 	__active_ungrab(ref);
 }
 
@@ -421,12 +429,13 @@
 			break;
 		}
 
-		err = i915_active_request_retire(&it->base, BKL(ref));
+		err = i915_active_request_retire(&it->base, BKL(ref),
+						 node_retire_nolock);
 		if (err)
 			break;
 	}
 
-	__active_retire(ref);
+	__active_retire(ref, true);
 	if (err)
 		return err;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/i915_active.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/i915_active.h
@@ -309,7 +309,7 @@
  */
 static inline int __must_check
 i915_active_request_retire(struct i915_active_request *active,
-			   struct mutex *mutex)
+			   struct mutex *mutex, i915_active_retire_fn retire)
 {
 	struct i915_request *request;
 	long ret;
@@ -327,7 +327,7 @@
 	list_del_init(&active->link);
 	RCU_INIT_POINTER(active->request, NULL);
 
-	active->retire(active, request);
+	retire(active, request);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/i915_cmd_parser.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/i915_cmd_parser.c
@@ -572,6 +572,9 @@
 #define REG32(_reg, ...) \
 	{ .addr = (_reg), __VA_ARGS__ }
 
+#define REG32_IDX(_reg, idx) \
+	{ .addr = _reg(idx) }
+
 /*
  * Convenience macro for adding 64-bit registers.
  *
@@ -669,6 +672,7 @@
 	REG64_IDX(RING_TIMESTAMP, BSD_RING_BASE),
 	REG32(BCS_SWCTRL),
 	REG64_IDX(RING_TIMESTAMP, BLT_RING_BASE),
+	REG32_IDX(RING_CTX_TIMESTAMP, BLT_RING_BASE),
 	REG64_IDX(BCS_GPR, 0),
 	REG64_IDX(BCS_GPR, 1),
 	REG64_IDX(BCS_GPR, 2),
@@ -1203,6 +1207,12 @@
 	return dst;
 }
 
+static inline bool cmd_desc_is(const struct drm_i915_cmd_descriptor * const desc,
+			       const u32 cmd)
+{
+	return desc->cmd.value == (cmd & desc->cmd.mask);
+}
+
 static bool check_cmd(const struct intel_engine_cs *engine,
 		      const struct drm_i915_cmd_descriptor *desc,
 		      const u32 *cmd, u32 length)
@@ -1241,19 +1251,19 @@
 			 * allowed mask/value pair given in the whitelist entry.
 			 */
 			if (reg->mask) {
-				if (desc->cmd.value == MI_LOAD_REGISTER_MEM) {
+				if (cmd_desc_is(desc, MI_LOAD_REGISTER_MEM)) {
 					DRM_DEBUG_DRIVER("CMD: Rejected LRM to masked register 0x%08X\n",
 							 reg_addr);
 					return false;
 				}
 
-				if (desc->cmd.value == MI_LOAD_REGISTER_REG) {
+				if (cmd_desc_is(desc, MI_LOAD_REGISTER_REG)) {
 					DRM_DEBUG_DRIVER("CMD: Rejected LRR to masked register 0x%08X\n",
 							 reg_addr);
 					return false;
 				}
 
-				if (desc->cmd.value == MI_LOAD_REGISTER_IMM(1) &&
+				if (cmd_desc_is(desc, MI_LOAD_REGISTER_IMM(1)) &&
 				    (offset + 2 > length ||
 				     (cmd[offset + 1] & reg->mask) != reg->value)) {
 					DRM_DEBUG_DRIVER("CMD: Rejected LRI to masked register 0x%08X\n",
@@ -1484,7 +1494,7 @@
 			goto err;
 		}
 
-		if (desc->cmd.value == MI_BATCH_BUFFER_START) {
+		if (cmd_desc_is(desc, MI_BATCH_BUFFER_START)) {
 			ret = check_bbstart(ctx, cmd, offset, length,
 					    batch_len, batch_start,
 					    shadow_batch_start);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/i915_debugfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2360,8 +2360,7 @@
 
 		for_each_power_domain(power_domain, power_well->desc->domains)
 			seq_printf(m, "  %-23s %d\n",
-				 intel_display_power_domain_str(dev_priv,
-								power_domain),
+				 intel_display_power_domain_str(power_domain),
 				 power_domains->domain_use_count[power_domain]);
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/i915_drv.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/i915_drv.h
@@ -33,6 +33,8 @@
 #include <uapi/drm/i915_drm.h>
 #include <uapi/drm/drm_fourcc.h>
 
+#include <asm/hypervisor.h>
+
 #include <linux/io-mapping.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
@@ -1740,6 +1742,9 @@
 
 	bool ipc_enabled;
 
+	/* Hack to bypass TMDS_OE write on DP->HDMI dongle */
+	bool bypass_tmds_oe;
+
 	/* Used to save the pipe-to-encoder mapping for audio */
 	struct intel_encoder *av_enc_map[I915_MAX_PIPES];
 
@@ -1892,7 +1897,7 @@
 {
 	const unsigned int pi = __platform_mask_index(info, p);
 
-	return info->platform_mask[pi] & INTEL_SUBPLATFORM_BITS;
+	return info->platform_mask[pi] & ((1 << INTEL_SUBPLATFORM_BITS) - 1);
 }
 
 static __always_inline bool
@@ -2197,7 +2202,9 @@
 	if (intel_iommu_gfx_mapped)
 		return true;
 #endif
-	return false;
+
+	/* Running as a guest, we assume the host is enforcing VT'd */
+	return !hypervisor_is_type(X86_HYPER_NATIVE);
 }
 
 static inline bool intel_scanout_needs_vtd_wa(struct drm_i915_private *dev_priv)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/i915_gem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/i915_gem.c
@@ -136,14 +136,14 @@
 		     struct drm_i915_gem_pwrite *args,
 		     struct drm_file *file)
 {
-	void *vaddr = obj->phys_handle->vaddr + args->offset;
+	void *vaddr = sg_page(obj->mm.pages->sgl) + args->offset;
 	char __user *user_data = u64_to_user_ptr(args->data_ptr);
 
 	/*
 	 * We manually control the domain here and pretend that it
 	 * remains coherent i.e. in the GTT domain, like shmem_pwrite.
 	 */
-	intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CPU);
+	i915_gem_object_invalidate_frontbuffer(obj, ORIGIN_CPU);
 
 	if (copy_from_user(vaddr, user_data, args->size))
 		return -EFAULT;
@@ -151,7 +151,7 @@
 	drm_clflush_virt_range(vaddr, args->size);
 	intel_gt_chipset_flush(&to_i915(obj->base.dev)->gt);
 
-	intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU);
+	i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU);
 	return 0;
 }
 
@@ -588,7 +588,7 @@
 		goto out_unpin;
 	}
 
-	intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CPU);
+	i915_gem_object_invalidate_frontbuffer(obj, ORIGIN_CPU);
 
 	user_data = u64_to_user_ptr(args->data_ptr);
 	offset = args->offset;
@@ -630,7 +630,7 @@
 		user_data += page_length;
 		offset += page_length;
 	}
-	intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU);
+	i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU);
 
 	i915_gem_object_unlock_fence(obj, fence);
 out_unpin:
@@ -723,7 +723,7 @@
 		offset = 0;
 	}
 
-	intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU);
+	i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU);
 	i915_gem_object_unlock_fence(obj, fence);
 
 	return ret;
@@ -802,10 +802,10 @@
 		ret = i915_gem_gtt_pwrite_fast(obj, args);
 
 	if (ret == -EFAULT || ret == -ENOSPC) {
-		if (obj->phys_handle)
-			ret = i915_gem_phys_pwrite(obj, args, file);
-		else
+		if (i915_gem_object_has_struct_page(obj))
 			ret = i915_gem_shmem_pwrite(obj, args);
+		else
+			ret = i915_gem_phys_pwrite(obj, args, file);
 	}
 
 	i915_gem_object_unpin_pages(obj);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -1178,6 +1178,7 @@
 	pd = i915_pd_entry(pdp, gen8_pd_index(idx, 2));
 	vaddr = kmap_atomic_px(i915_pt_entry(pd, gen8_pd_index(idx, 1)));
 	do {
+		GEM_BUG_ON(iter->sg->length < I915_GTT_PAGE_SIZE);
 		vaddr[gen8_pd_index(idx, 0)] = pte_encode | iter->dma;
 
 		iter->dma += I915_GTT_PAGE_SIZE;
@@ -1657,6 +1658,7 @@
 
 	vaddr = kmap_atomic_px(i915_pt_entry(pd, act_pt));
 	do {
+		GEM_BUG_ON(iter.sg->length < I915_GTT_PAGE_SIZE);
 		vaddr[act_pte] = pte_encode | GEN6_PTE_ADDR_ENCODE(iter.dma);
 
 		iter.dma += I915_GTT_PAGE_SIZE;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/i915_gpu_error.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -307,6 +307,8 @@
 
 		if (zlib_deflate(zstream, Z_NO_FLUSH) != Z_OK)
 			return -EIO;
+
+		cond_resched();
 	} while (zstream->avail_in);
 
 	/* Fallback to uncompressed if we increase size? */
@@ -392,6 +394,7 @@
 	if (!i915_memcpy_from_wc(ptr, src, PAGE_SIZE))
 		memcpy(ptr, src, PAGE_SIZE);
 	dst->pages[dst->page_count++] = ptr;
+	cond_resched();
 
 	return 0;
 }
@@ -1768,7 +1771,8 @@
 	if (!xchg(&warned, true) &&
 	    ktime_get_real_seconds() - DRIVER_TIMESTAMP < DAY_AS_SECONDS(180)) {
 		pr_info("GPU hangs can indicate a bug anywhere in the entire gfx stack, including userspace.\n");
-		pr_info("Please file a _new_ bug report on bugs.freedesktop.org against DRI -> DRM/Intel\n");
+		pr_info("Please file a _new_ bug report at https://gitlab.freedesktop.org/drm/intel/issues/new.\n");
+		pr_info("Please see https://gitlab.freedesktop.org/drm/intel/-/wikis/How-to-file-i915-bugs for details.\n");
 		pr_info("drm/i915 developers can then reassign to the right component if it's not a kernel issue.\n");
 		pr_info("The GPU crash dump is required to analyze GPU hangs, so please always attach it.\n");
 		pr_info("GPU crash dump saved to /sys/class/drm/card%d/error\n",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/i915_irq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/i915_irq.c
@@ -3500,6 +3500,7 @@
 
 	val = I915_READ(GEN11_DE_HPD_IMR);
 	val &= ~hotplug_irqs;
+	val |= ~enabled_irqs & hotplug_irqs;
 	I915_WRITE(GEN11_DE_HPD_IMR, val);
 	POSTING_READ(GEN11_DE_HPD_IMR);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/i915_params.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/i915_params.c
@@ -84,8 +84,7 @@
 
 i915_param_named_unsafe(enable_psr, int, 0600,
 	"Enable PSR "
-	"(0=disabled, 1=enabled) "
-	"Default: -1 (use per-chip default)");
+	"(-1=use per-chip default, 0=disabled [default], 1=enabled) ");
 
 i915_param_named_unsafe(force_probe, charp, 0400,
 	"Force probe the driver for specified devices. "
@@ -171,7 +170,7 @@
 
 i915_param_named(enable_dpcd_backlight, int, 0600,
 	"Enable support for DPCD backlight control"
-	"(-1=use per-VBT LFP backlight type setting, 0=disabled [default], 1=enabled)");
+	"(-1=use per-VBT LFP backlight type setting [default], 0=disabled, 1=enabled)");
 
 #if IS_ENABLED(CONFIG_DRM_I915_GVT)
 i915_param_named(enable_gvt, bool, 0400,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/i915_params.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/i915_params.h
@@ -50,7 +50,7 @@
 	param(int, vbt_sdvo_panel_type, -1) \
 	param(int, enable_dc, -1) \
 	param(int, enable_fbc, -1) \
-	param(int, enable_psr, -1) \
+	param(int, enable_psr, 0) \
 	param(int, disable_power_well, -1) \
 	param(int, enable_ips, 1) \
 	param(int, invert_brightness, 0) \
@@ -64,7 +64,7 @@
 	param(int, reset, 2) \
 	param(unsigned int, inject_load_failure, 0) \
 	param(int, fastboot, -1) \
-	param(int, enable_dpcd_backlight, 0) \
+	param(int, enable_dpcd_backlight, -1) \
 	param(char *, force_probe, CONFIG_DRM_I915_FORCE_PROBE) \
 	/* leave bools at the end to not create holes */ \
 	param(bool, alpha_support, IS_ENABLED(CONFIG_DRM_I915_ALPHA_SUPPORT)) \
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/i915_pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/i915_pci.c
@@ -418,7 +418,8 @@
 	.has_coherent_ggtt = true, \
 	.has_llc = 1, \
 	.has_rc6 = 1, \
-	.has_rc6p = 1, \
+	/* snb does support rc6p, but enabling it causes various issues */ \
+	.has_rc6p = 0, \
 	.has_rps = true, \
 	.ppgtt_type = INTEL_PPGTT_FULL, \
 	.ppgtt_size = 31, \
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/i915_perf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/i915_perf.c
@@ -2313,49 +2313,6 @@
 }
 
 /**
- * i915_perf_read_locked - &i915_perf_stream_ops->read with error normalisation
- * @stream: An i915 perf stream
- * @file: An i915 perf stream file
- * @buf: destination buffer given by userspace
- * @count: the number of bytes userspace wants to read
- * @ppos: (inout) file seek position (unused)
- *
- * Besides wrapping &i915_perf_stream_ops->read this provides a common place to
- * ensure that if we've successfully copied any data then reporting that takes
- * precedence over any internal error status, so the data isn't lost.
- *
- * For example ret will be -ENOSPC whenever there is more buffered data than
- * can be copied to userspace, but that's only interesting if we weren't able
- * to copy some data because it implies the userspace buffer is too small to
- * receive a single record (and we never split records).
- *
- * Another case with ret == -EFAULT is more of a grey area since it would seem
- * like bad form for userspace to ask us to overrun its buffer, but the user
- * knows best:
- *
- *   http://yarchive.net/comp/linux/partial_reads_writes.html
- *
- * Returns: The number of bytes copied or a negative error code on failure.
- */
-static ssize_t i915_perf_read_locked(struct i915_perf_stream *stream,
-				     struct file *file,
-				     char __user *buf,
-				     size_t count,
-				     loff_t *ppos)
-{
-	/* Note we keep the offset (aka bytes read) separate from any
-	 * error status so that the final check for whether we return
-	 * the bytes read with a higher precedence than any error (see
-	 * comment below) doesn't need to be handled/duplicated in
-	 * stream->ops->read() implementations.
-	 */
-	size_t offset = 0;
-	int ret = stream->ops->read(stream, buf, count, &offset);
-
-	return offset ?: (ret ?: -EAGAIN);
-}
-
-/**
  * i915_perf_read - handles read() FOP for i915 perf stream FDs
  * @file: An i915 perf stream file
  * @buf: destination buffer given by userspace
@@ -2380,7 +2337,8 @@
 {
 	struct i915_perf_stream *stream = file->private_data;
 	struct drm_i915_private *dev_priv = stream->dev_priv;
-	ssize_t ret;
+	size_t offset = 0;
+	int ret;
 
 	/* To ensure it's handled consistently we simply treat all reads of a
 	 * disabled stream as an error. In particular it might otherwise lead
@@ -2403,13 +2361,12 @@
 				return ret;
 
 			mutex_lock(&dev_priv->perf.lock);
-			ret = i915_perf_read_locked(stream, file,
-						    buf, count, ppos);
+			ret = stream->ops->read(stream, buf, count, &offset);
 			mutex_unlock(&dev_priv->perf.lock);
-		} while (ret == -EAGAIN);
+		} while (!offset && !ret);
 	} else {
 		mutex_lock(&dev_priv->perf.lock);
-		ret = i915_perf_read_locked(stream, file, buf, count, ppos);
+		ret = stream->ops->read(stream, buf, count, &offset);
 		mutex_unlock(&dev_priv->perf.lock);
 	}
 
@@ -2420,15 +2377,15 @@
 	 * and read() returning -EAGAIN. Clearing the oa.pollin state here
 	 * effectively ensures we back off until the next hrtimer callback
 	 * before reporting another EPOLLIN event.
+	 * The exception to this is if ops->read() returned -ENOSPC which means
+	 * that more OA data is available than could fit in the user provided
+	 * buffer. In this case we want the next poll() call to not block.
 	 */
-	if (ret >= 0 || ret == -EAGAIN) {
-		/* Maybe make ->pollin per-stream state if we support multiple
-		 * concurrent streams in the future.
-		 */
+	if (ret != -ENOSPC)
 		stream->pollin = false;
-	}
 
-	return ret;
+	/* Possible values for ret are 0, -EFAULT, -ENOSPC, -EIO, ... */
+	return offset ?: (ret ?: -EAGAIN);
 }
 
 static enum hrtimer_restart oa_poll_check_timer_cb(struct hrtimer *hrtimer)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/i915_reg.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/i915_reg.h
@@ -2519,6 +2519,12 @@
 #define   GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING	(1 << 28)
 #define   GAMT_CHKN_DISABLE_I2M_CYCLE_ON_WR_PORT	(1 << 24)
 
+#define GEN8_RTCR	_MMIO(0x4260)
+#define GEN8_M1TCR	_MMIO(0x4264)
+#define GEN8_M2TCR	_MMIO(0x4268)
+#define GEN8_BTCR	_MMIO(0x426c)
+#define GEN8_VTCR	_MMIO(0x4270)
+
 #if 0
 #define PRB0_TAIL	_MMIO(0x2030)
 #define PRB0_HEAD	_MMIO(0x2034)
@@ -2602,6 +2608,11 @@
 #define   FAULT_VA_HIGH_BITS		(0xf << 0)
 #define   FAULT_GTT_SEL			(1 << 4)
 
+#define GEN12_GFX_TLB_INV_CR	_MMIO(0xced8)
+#define GEN12_VD_TLB_INV_CR	_MMIO(0xcedc)
+#define GEN12_VE_TLB_INV_CR	_MMIO(0xcee0)
+#define GEN12_BLT_TLB_INV_CR	_MMIO(0xcee4)
+
 #define FPGA_DBG		_MMIO(0x42300)
 #define   FPGA_DBG_RM_NOCLAIM	(1 << 31)
 
@@ -4049,7 +4060,13 @@
 #define  GWUNIT_CLKGATE_DIS		(1 << 16)
 
 #define UNSLICE_UNIT_LEVEL_CLKGATE	_MMIO(0x9434)
-#define  VFUNIT_CLKGATE_DIS		(1 << 20)
+#define   VFUNIT_CLKGATE_DIS		REG_BIT(20)
+#define   HSUNIT_CLKGATE_DIS		REG_BIT(8)
+#define   VSUNIT_CLKGATE_DIS		REG_BIT(3)
+
+#define UNSLICE_UNIT_LEVEL_CLKGATE2	_MMIO(0x94e4)
+#define   VSUNIT_CLKGATE_DIS_TGL	REG_BIT(19)
+#define   PSDUNIT_CLKGATE_DIS		REG_BIT(5)
 
 #define INF_UNIT_LEVEL_CLKGATE		_MMIO(0x9560)
 #define   CGPSF_CLKGATE_DIS		(1 << 3)
@@ -8832,8 +8849,13 @@
 #define     ICL_PCODE_MEM_SS_READ_QGV_POINT_INFO(point)	(((point) << 16) | (0x1 << 8))
 #define   GEN6_PCODE_READ_D_COMP		0x10
 #define   GEN6_PCODE_WRITE_D_COMP		0x11
+#define   ICL_PCODE_EXIT_TCCOLD			0x12
 #define   HSW_PCODE_DE_WRITE_FREQ_REQ		0x17
 #define   DISPLAY_IPS_CONTROL			0x19
+#define   TGL_PCODE_TCCOLD			0x26
+#define     TGL_PCODE_EXIT_TCCOLD_DATA_L_EXIT_FAILED	REG_BIT(0)
+#define     TGL_PCODE_EXIT_TCCOLD_DATA_H_BLOCK_REQ	0
+#define     TGL_PCODE_EXIT_TCCOLD_DATA_H_UNBLOCK_REQ	REG_BIT(0)
             /* See also IPS_CTL */
 #define     IPS_PCODE_CONTROL			(1 << 30)
 #define   HSW_PCODE_DYNAMIC_DUTY_CYCLE_CONTROL	0x1A
@@ -9104,6 +9126,9 @@
 #define HSW_AUD_CHICKENBIT			_MMIO(0x65f10)
 #define   SKL_AUD_CODEC_WAKE_SIGNAL		(1 << 15)
 
+#define AUD_PIN_BUF_CTL		_MMIO(0x48414)
+#define   AUD_PIN_BUF_ENABLE		REG_BIT(31)
+
 /*
  * HSW - ICL power wells
  *
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/i915_request.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/i915_request.c
@@ -215,7 +215,7 @@
 	spin_unlock(&locked->active.lock);
 }
 
-static bool i915_request_retire(struct i915_request *rq)
+bool i915_request_retire(struct i915_request *rq)
 {
 	struct i915_active_request *active, *next;
 
@@ -560,19 +560,31 @@
 	return NOTIFY_DONE;
 }
 
+static void irq_semaphore_cb(struct irq_work *wrk)
+{
+	struct i915_request *rq =
+		container_of(wrk, typeof(*rq), semaphore_work);
+
+	i915_schedule_bump_priority(rq, I915_PRIORITY_NOSEMAPHORE);
+	i915_request_put(rq);
+}
+
 static int __i915_sw_fence_call
 semaphore_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state)
 {
-	struct i915_request *request =
-		container_of(fence, typeof(*request), semaphore);
+	struct i915_request *rq = container_of(fence, typeof(*rq), semaphore);
 
 	switch (state) {
 	case FENCE_COMPLETE:
-		i915_schedule_bump_priority(request, I915_PRIORITY_NOSEMAPHORE);
+		if (!(READ_ONCE(rq->sched.attr.priority) & I915_PRIORITY_NOSEMAPHORE)) {
+			i915_request_get(rq);
+			init_irq_work(&rq->semaphore_work, irq_semaphore_cb);
+			irq_work_queue(&rq->semaphore_work);
+		}
 		break;
 
 	case FENCE_FREE:
-		i915_request_put(request);
+		i915_request_put(rq);
 		break;
 	}
 
@@ -882,8 +894,10 @@
 	GEM_BUG_ON(to == from);
 	GEM_BUG_ON(to->timeline == from->timeline);
 
-	if (i915_request_completed(from))
+	if (i915_request_completed(from)) {
+		i915_sw_fence_set_error_once(&to->submit, from->fence.error);
 		return 0;
+	}
 
 	if (to->engine->schedule) {
 		ret = i915_sched_node_add_dependency(&to->sched, &from->sched);
@@ -1215,9 +1229,9 @@
 	 * decide whether to preempt the entire chain so that it is ready to
 	 * run at the earliest possible convenience.
 	 */
-	i915_sw_fence_commit(&rq->semaphore);
 	if (attr && rq->engine->schedule)
 		rq->engine->schedule(rq, attr);
+	i915_sw_fence_commit(&rq->semaphore);
 	i915_sw_fence_commit(&rq->submit);
 }
 
@@ -1513,8 +1527,8 @@
 			continue;
 
 		intel_timeline_get(tl);
-		GEM_BUG_ON(!tl->active_count);
-		tl->active_count++; /* pin the list element */
+		GEM_BUG_ON(!atomic_read(&tl->active_count));
+		atomic_inc(&tl->active_count); /* pin the list element */
 		spin_unlock_irqrestore(&timelines->lock, flags);
 
 		retire_requests(tl);
@@ -1523,14 +1537,14 @@
 
 		/* Resume iteration after dropping lock */
 		list_safe_reset_next(tl, tn, link);
-		if (!--tl->active_count)
+		if (atomic_dec_and_test(&tl->active_count))
 			list_del(&tl->link);
 
 		mutex_unlock(&tl->mutex);
 
 		/* Defer the final release to after the spinlock */
 		if (refcount_dec_and_test(&tl->kref.refcount)) {
-			GEM_BUG_ON(tl->active_count);
+			GEM_BUG_ON(atomic_read(&tl->active_count));
 			list_add(&tl->link, &free);
 		}
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/i915_request.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/i915_request.h
@@ -26,6 +26,7 @@
 #define I915_REQUEST_H
 
 #include <linux/dma-fence.h>
+#include <linux/irq_work.h>
 #include <linux/lockdep.h>
 
 #include "gt/intel_context_types.h"
@@ -147,6 +148,7 @@
 	};
 	struct list_head execute_cb;
 	struct i915_sw_fence semaphore;
+	struct irq_work semaphore_work;
 
 	/*
 	 * A list of everyone we wait upon, and everyone who waits upon us.
@@ -251,6 +253,7 @@
 void __i915_request_queue(struct i915_request *rq,
 			  const struct i915_sched_attr *attr);
 
+bool i915_request_retire(struct i915_request *rq);
 void i915_request_retire_upto(struct i915_request *rq);
 
 static inline struct i915_request *
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/i915_scheduler.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/i915_scheduler.c
@@ -418,8 +418,6 @@
 
 	if (!node_signaled(signal)) {
 		INIT_LIST_HEAD(&dep->dfs_link);
-		list_add(&dep->wait_link, &signal->waiters_list);
-		list_add(&dep->signal_link, &node->signalers_list);
 		dep->signaler = signal;
 		dep->waiter = node;
 		dep->flags = flags;
@@ -429,6 +427,10 @@
 		    !node_started(signal))
 			node->flags |= I915_SCHED_HAS_SEMAPHORE_CHAIN;
 
+		/* All set, now publish. Beware the lockless walkers. */
+		list_add(&dep->signal_link, &node->signalers_list);
+		list_add_rcu(&dep->wait_link, &signal->waiters_list);
+
 		/*
 		 * As we do not allow WAIT to preempt inflight requests,
 		 * once we have executed a request, along with triggering
@@ -531,6 +533,6 @@
 	return 0;
 
 err_priorities:
-	kmem_cache_destroy(global.slab_priorities);
+	kmem_cache_destroy(global.slab_dependencies);
 	return -ENOMEM;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/i915_sw_fence.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/i915_sw_fence.c
@@ -38,7 +38,7 @@
 	debug_object_init(fence, &i915_sw_fence_debug_descr);
 }
 
-static inline void debug_fence_init_onstack(struct i915_sw_fence *fence)
+static inline __maybe_unused void debug_fence_init_onstack(struct i915_sw_fence *fence)
 {
 	debug_object_init_on_stack(fence, &i915_sw_fence_debug_descr);
 }
@@ -64,7 +64,7 @@
 	debug_object_destroy(fence, &i915_sw_fence_debug_descr);
 }
 
-static inline void debug_fence_free(struct i915_sw_fence *fence)
+static inline __maybe_unused void debug_fence_free(struct i915_sw_fence *fence)
 {
 	debug_object_free(fence, &i915_sw_fence_debug_descr);
 	smp_wmb(); /* flush the change in state before reallocation */
@@ -81,7 +81,7 @@
 {
 }
 
-static inline void debug_fence_init_onstack(struct i915_sw_fence *fence)
+static inline __maybe_unused void debug_fence_init_onstack(struct i915_sw_fence *fence)
 {
 }
 
@@ -102,7 +102,7 @@
 {
 }
 
-static inline void debug_fence_free(struct i915_sw_fence *fence)
+static inline __maybe_unused void debug_fence_free(struct i915_sw_fence *fence)
 {
 }
 
@@ -158,9 +158,13 @@
 
 		do {
 			list_for_each_entry_safe(pos, next, &x->head, entry) {
-				pos->func(pos,
-					  TASK_NORMAL, fence->error,
-					  &extra);
+				int wake_flags;
+
+				wake_flags = fence->error;
+				if (pos->func == autoremove_wake_function)
+					wake_flags = 0;
+
+				pos->func(pos, TASK_NORMAL, wake_flags, &extra);
 			}
 
 			if (list_empty(&extra))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/i915_utils.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/i915_utils.c
@@ -8,9 +8,8 @@
 #include "i915_drv.h"
 #include "i915_utils.h"
 
-#define FDO_BUG_URL "https://bugs.freedesktop.org/enter_bug.cgi?product=DRI"
-#define FDO_BUG_MSG "Please file a bug at " FDO_BUG_URL " against DRM/Intel " \
-		    "providing the dmesg log by booting with drm.debug=0xf"
+#define FDO_BUG_URL "https://gitlab.freedesktop.org/drm/intel/-/wikis/How-to-file-i915-bugs"
+#define FDO_BUG_MSG "Please file a bug on drm/i915; see " FDO_BUG_URL " for details."
 
 void
 __i915_printk(struct drm_i915_private *dev_priv, const char *level,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/i915_utils.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/i915_utils.h
@@ -233,6 +233,11 @@
 	__idx;								\
 })
 
+static inline bool is_power_of_2_u64(u64 n)
+{
+	return (n != 0 && ((n & (n - 1)) == 0));
+}
+
 static inline void __list_del_many(struct list_head *head,
 				   struct list_head *first)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/i915_vma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/i915_vma.c
@@ -341,6 +341,10 @@
 		return ret;
 
 	vma->flags |= bind_flags;
+
+	if (vma->obj)
+		set_bit(I915_BO_WAS_BOUND_BIT, &vma->obj->flags);
+
 	return 0;
 }
 
@@ -907,10 +911,16 @@
 		return err;
 
 	if (flags & EXEC_OBJECT_WRITE) {
-		if (intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CS))
-			i915_active_ref(&obj->frontbuffer->write,
-					rq->timeline,
-					rq);
+		struct intel_frontbuffer *front;
+
+		front = __intel_frontbuffer_get(obj);
+		if (unlikely(front)) {
+			if (intel_frontbuffer_invalidate(front, ORIGIN_CS))
+				i915_active_ref(&front->write,
+						rq->timeline,
+						rq);
+			intel_frontbuffer_put(front);
+		}
 
 		dma_resv_add_excl_fence(vma->resv, &rq->fence);
 		obj->write_domain = I915_GEM_DOMAIN_RENDER;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/intel_pch.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/intel_pch.c
@@ -74,6 +74,11 @@
 		WARN_ON(!IS_COFFEELAKE(dev_priv));
 		/* CometPoint is CNP Compatible */
 		return PCH_CNP;
+	case INTEL_PCH_CMP_V_DEVICE_ID_TYPE:
+		DRM_DEBUG_KMS("Found Comet Lake V PCH (CMP-V)\n");
+		WARN_ON(!IS_COFFEELAKE(dev_priv));
+		/* Comet Lake V PCH is based on KBP, which is SPT compatible */
+		return PCH_SPT;
 	case INTEL_PCH_ICP_DEVICE_ID_TYPE:
 		DRM_DEBUG_KMS("Found Ice Lake PCH\n");
 		WARN_ON(!IS_ICELAKE(dev_priv));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/intel_pch.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/intel_pch.h
@@ -42,6 +42,7 @@
 #define INTEL_PCH_CNP_LP_DEVICE_ID_TYPE		0x9D80
 #define INTEL_PCH_CMP_DEVICE_ID_TYPE		0x0280
 #define INTEL_PCH_CMP2_DEVICE_ID_TYPE		0x0680
+#define INTEL_PCH_CMP_V_DEVICE_ID_TYPE		0xA380
 #define INTEL_PCH_ICP_DEVICE_ID_TYPE		0x3480
 #define INTEL_PCH_MCC_DEVICE_ID_TYPE		0x4B00
 #define INTEL_PCH_MCC2_DEVICE_ID_TYPE		0x3880
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/intel_pm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/intel_pm.c
@@ -2822,7 +2822,7 @@
 }
 
 static void intel_read_wm_latency(struct drm_i915_private *dev_priv,
-				  u16 wm[8])
+				  u16 wm[])
 {
 	struct intel_uncore *uncore = &dev_priv->uncore;
 
@@ -2966,7 +2966,7 @@
 
 static void intel_print_wm_latency(struct drm_i915_private *dev_priv,
 				   const char *name,
-				   const u16 wm[8])
+				   const u16 wm[])
 {
 	int level, max_level = ilk_wm_max_level(dev_priv);
 
@@ -3017,9 +3017,9 @@
 	 * The BIOS provided WM memory latency values are often
 	 * inadequate for high resolution displays. Adjust them.
 	 */
-	changed = ilk_increase_wm_latency(dev_priv, dev_priv->wm.pri_latency, 12) |
-		ilk_increase_wm_latency(dev_priv, dev_priv->wm.spr_latency, 12) |
-		ilk_increase_wm_latency(dev_priv, dev_priv->wm.cur_latency, 12);
+	changed = ilk_increase_wm_latency(dev_priv, dev_priv->wm.pri_latency, 12);
+	changed |= ilk_increase_wm_latency(dev_priv, dev_priv->wm.spr_latency, 12);
+	changed |= ilk_increase_wm_latency(dev_priv, dev_priv->wm.cur_latency, 12);
 
 	if (!changed)
 		return;
@@ -4784,7 +4784,7 @@
 	 * WaIncreaseLatencyIPCEnabled: kbl,cfl
 	 * Display WA #1141: kbl,cfl
 	 */
-	if ((IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) ||
+	if ((IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) &&
 	    dev_priv->ipc_enabled)
 		latency += 4;
 
@@ -9194,6 +9194,17 @@
 	/* WaEnable32PlaneMode:icl */
 	I915_WRITE(GEN9_CSFE_CHICKEN1_RCS,
 		   _MASKED_BIT_ENABLE(GEN11_ENABLE_32_PLANE_MODE));
+
+	/*
+	 * Wa_1408615072:icl,ehl  (vsunit)
+	 * Wa_1407596294:icl,ehl  (hsunit)
+	 */
+	intel_uncore_rmw(&dev_priv->uncore, UNSLICE_UNIT_LEVEL_CLKGATE,
+			 0, VSUNIT_CLKGATE_DIS | HSUNIT_CLKGATE_DIS);
+
+	/* Wa_1407352427:icl,ehl */
+	intel_uncore_rmw(&dev_priv->uncore, UNSLICE_UNIT_LEVEL_CLKGATE2,
+			 0, PSDUNIT_CLKGATE_DIS);
 }
 
 static void cnp_init_clock_gating(struct drm_i915_private *dev_priv)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/intel_uncore.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/intel_uncore.c
@@ -1124,6 +1124,18 @@
 		spin_unlock(&uncore->debug->lock);
 }
 
+#define __vgpu_read(x) \
+static u##x \
+vgpu_read##x(struct intel_uncore *uncore, i915_reg_t reg, bool trace) { \
+	u##x val = __raw_uncore_read##x(uncore, reg); \
+	trace_i915_reg_rw(false, reg, val, sizeof(val), trace); \
+	return val; \
+}
+__vgpu_read(8)
+__vgpu_read(16)
+__vgpu_read(32)
+__vgpu_read(64)
+
 #define GEN2_READ_HEADER(x) \
 	u##x val = 0; \
 	assert_rpm_wakelock_held(uncore->rpm);
@@ -1327,6 +1339,16 @@
 #undef GEN6_WRITE_FOOTER
 #undef GEN6_WRITE_HEADER
 
+#define __vgpu_write(x) \
+static void \
+vgpu_write##x(struct intel_uncore *uncore, i915_reg_t reg, u##x val, bool trace) { \
+	trace_i915_reg_rw(true, reg, val, sizeof(val), trace); \
+	__raw_uncore_write##x(uncore, reg, val); \
+}
+__vgpu_write(8)
+__vgpu_write(16)
+__vgpu_write(32)
+
 #define ASSIGN_RAW_WRITE_MMIO_VFUNCS(uncore, x) \
 do { \
 	(uncore)->funcs.mmio_writeb = x##_write8; \
@@ -1647,7 +1669,10 @@
 {
 	GEM_BUG_ON(intel_uncore_has_forcewake(uncore));
 
-	if (IS_GEN(uncore->i915, 5)) {
+	if (intel_vgpu_active(uncore->i915)) {
+		ASSIGN_RAW_WRITE_MMIO_VFUNCS(uncore, vgpu);
+		ASSIGN_RAW_READ_MMIO_VFUNCS(uncore, vgpu);
+	} else if (IS_GEN(uncore->i915, 5)) {
 		ASSIGN_RAW_WRITE_MMIO_VFUNCS(uncore, gen5);
 		ASSIGN_RAW_READ_MMIO_VFUNCS(uncore, gen5);
 	} else {
@@ -1901,13 +1926,14 @@
 				 unsigned int slow_timeout_ms,
 				 u32 *out_value)
 {
-	u32 uninitialized_var(reg_value);
+	u32 reg_value = 0;
 #define done (((reg_value = intel_uncore_read_fw(uncore, reg)) & mask) == value)
 	int ret;
 
 	/* Catch any overuse of this function */
 	might_sleep_if(slow_timeout_ms);
 	GEM_BUG_ON(fast_timeout_us > 20000);
+	GEM_BUG_ON(!fast_timeout_us && !slow_timeout_ms);
 
 	ret = -ETIMEDOUT;
 	if (fast_timeout_us && fast_timeout_us <= 20000)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/i915/selftests/i915_random.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/i915/selftests/i915_random.h
@@ -25,6 +25,7 @@
 #ifndef __I915_SELFTESTS_RANDOM_H__
 #define __I915_SELFTESTS_RANDOM_H__
 
+#include <linux/math64.h>
 #include <linux/random.h>
 
 #include "../i915_selftest.h"
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/imx/dw_hdmi-imx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/imx/dw_hdmi-imx.c
@@ -212,9 +212,8 @@
 	if (!pdev->dev.of_node)
 		return -ENODEV;
 
-	hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
-	if (!hdmi)
-		return -ENOMEM;
+	hdmi = dev_get_drvdata(dev);
+	memset(hdmi, 0, sizeof(*hdmi));
 
 	match = of_match_node(dw_hdmi_imx_dt_ids, pdev->dev.of_node);
 	plat_data = match->data;
@@ -239,8 +238,6 @@
 	drm_encoder_init(drm, encoder, &dw_hdmi_imx_encoder_funcs,
 			 DRM_MODE_ENCODER_TMDS, NULL);
 
-	platform_set_drvdata(pdev, hdmi);
-
 	hdmi->hdmi = dw_hdmi_bind(pdev, encoder, plat_data);
 
 	/*
@@ -270,6 +267,14 @@
 
 static int dw_hdmi_imx_probe(struct platform_device *pdev)
 {
+	struct imx_hdmi *hdmi;
+
+	hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
+	if (!hdmi)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, hdmi);
+
 	return component_add(&pdev->dev, &dw_hdmi_imx_ops);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/imx/imx-drm-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/imx/imx-drm-core.c
@@ -281,9 +281,10 @@
 
 	drm_kms_helper_poll_fini(drm);
 
+	component_unbind_all(drm->dev, drm);
+
 	drm_mode_config_cleanup(drm);
 
-	component_unbind_all(drm->dev, drm);
 	dev_set_drvdata(dev, NULL);
 
 	drm_dev_put(drm);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/imx/imx-ldb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/imx/imx-ldb.c
@@ -197,6 +197,11 @@
 	int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN;
 	int mux = drm_of_encoder_active_port_id(imx_ldb_ch->child, encoder);
 
+	if (mux < 0 || mux >= ARRAY_SIZE(ldb->clk_sel)) {
+		dev_warn(ldb->dev, "%s: invalid mux %d\n", __func__, mux);
+		return;
+	}
+
 	drm_panel_prepare(imx_ldb_ch->panel);
 
 	if (dual) {
@@ -255,6 +260,11 @@
 	int mux = drm_of_encoder_active_port_id(imx_ldb_ch->child, encoder);
 	u32 bus_format = imx_ldb_ch->bus_format;
 
+	if (mux < 0 || mux >= ARRAY_SIZE(ldb->clk_sel)) {
+		dev_warn(ldb->dev, "%s: invalid mux %d\n", __func__, mux);
+		return;
+	}
+
 	if (mode->clock > 170000) {
 		dev_warn(ldb->dev,
 			 "%s: mode exceeds 170 MHz pixel clock\n", __func__);
@@ -302,18 +312,19 @@
 {
 	struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder);
 	struct imx_ldb *ldb = imx_ldb_ch->ldb;
+	int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN;
 	int mux, ret;
 
 	drm_panel_disable(imx_ldb_ch->panel);
 
-	if (imx_ldb_ch == &ldb->channel[0])
+	if (imx_ldb_ch == &ldb->channel[0] || dual)
 		ldb->ldb_ctrl &= ~LDB_CH0_MODE_EN_MASK;
-	else if (imx_ldb_ch == &ldb->channel[1])
+	if (imx_ldb_ch == &ldb->channel[1] || dual)
 		ldb->ldb_ctrl &= ~LDB_CH1_MODE_EN_MASK;
 
 	regmap_write(ldb->regmap, IOMUXC_GPR2, ldb->ldb_ctrl);
 
-	if (ldb->ldb_ctrl & LDB_SPLIT_MODE_EN) {
+	if (dual) {
 		clk_disable_unprepare(ldb->clk[0]);
 		clk_disable_unprepare(ldb->clk[1]);
 	}
@@ -593,9 +604,8 @@
 	int ret;
 	int i;
 
-	imx_ldb = devm_kzalloc(dev, sizeof(*imx_ldb), GFP_KERNEL);
-	if (!imx_ldb)
-		return -ENOMEM;
+	imx_ldb = dev_get_drvdata(dev);
+	memset(imx_ldb, 0, sizeof(*imx_ldb));
 
 	imx_ldb->regmap = syscon_regmap_lookup_by_phandle(np, "gpr");
 	if (IS_ERR(imx_ldb->regmap)) {
@@ -703,8 +713,6 @@
 		}
 	}
 
-	dev_set_drvdata(dev, imx_ldb);
-
 	return 0;
 
 free_child:
@@ -736,6 +744,14 @@
 
 static int imx_ldb_probe(struct platform_device *pdev)
 {
+	struct imx_ldb *imx_ldb;
+
+	imx_ldb = devm_kzalloc(&pdev->dev, sizeof(*imx_ldb), GFP_KERNEL);
+	if (!imx_ldb)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, imx_ldb);
+
 	return component_add(&pdev->dev, &imx_ldb_ops);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/imx/imx-tve.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/imx/imx-tve.c
@@ -237,8 +237,9 @@
 	return ret;
 }
 
-static int imx_tve_connector_mode_valid(struct drm_connector *connector,
-					struct drm_display_mode *mode)
+static enum drm_mode_status
+imx_tve_connector_mode_valid(struct drm_connector *connector,
+			     struct drm_display_mode *mode)
 {
 	struct imx_tve *tve = con_to_tve(connector);
 	unsigned long rate;
@@ -494,6 +495,13 @@
 	return 0;
 }
 
+static void imx_tve_disable_regulator(void *data)
+{
+	struct imx_tve *tve = data;
+
+	regulator_disable(tve->dac_reg);
+}
+
 static bool imx_tve_readable_reg(struct device *dev, unsigned int reg)
 {
 	return (reg % 4 == 0) && (reg <= 0xdc);
@@ -546,9 +554,8 @@
 	int irq;
 	int ret;
 
-	tve = devm_kzalloc(dev, sizeof(*tve), GFP_KERNEL);
-	if (!tve)
-		return -ENOMEM;
+	tve = dev_get_drvdata(dev);
+	memset(tve, 0, sizeof(*tve));
 
 	tve->dev = dev;
 	spin_lock_init(&tve->lock);
@@ -618,6 +625,9 @@
 		ret = regulator_enable(tve->dac_reg);
 		if (ret)
 			return ret;
+		ret = devm_add_action_or_reset(dev, imx_tve_disable_regulator, tve);
+		if (ret)
+			return ret;
 	}
 
 	tve->clk = devm_clk_get(dev, "tve");
@@ -659,27 +669,23 @@
 	if (ret)
 		return ret;
 
-	dev_set_drvdata(dev, tve);
-
 	return 0;
 }
 
-static void imx_tve_unbind(struct device *dev, struct device *master,
-	void *data)
-{
-	struct imx_tve *tve = dev_get_drvdata(dev);
-
-	if (!IS_ERR(tve->dac_reg))
-		regulator_disable(tve->dac_reg);
-}
-
 static const struct component_ops imx_tve_ops = {
 	.bind	= imx_tve_bind,
-	.unbind	= imx_tve_unbind,
 };
 
 static int imx_tve_probe(struct platform_device *pdev)
 {
+	struct imx_tve *tve;
+
+	tve = devm_kzalloc(&pdev->dev, sizeof(*tve), GFP_KERNEL);
+	if (!tve)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, tve);
+
 	return component_add(&pdev->dev, &imx_tve_ops);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/imx/ipuv3-crtc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/imx/ipuv3-crtc.c
@@ -68,7 +68,7 @@
 	drm_atomic_crtc_state_for_each_plane(plane, old_crtc_state) {
 		if (plane == &ipu_crtc->plane[0]->base)
 			disable_full = true;
-		if (&ipu_crtc->plane[1] && plane == &ipu_crtc->plane[1]->base)
+		if (ipu_crtc->plane[1] && plane == &ipu_crtc->plane[1]->base)
 			disable_partial = true;
 	}
 
@@ -411,14 +411,12 @@
 	}
 
 	ipu_crtc->irq = ipu_plane_irq(ipu_crtc->plane[0]);
-	ret = devm_request_irq(ipu_crtc->dev, ipu_crtc->irq, ipu_irq_handler, 0,
-			"imx_drm", ipu_crtc);
+	ret = devm_request_irq(ipu_crtc->dev, ipu_crtc->irq, ipu_irq_handler,
+			       IRQF_NO_AUTOEN, "imx_drm", ipu_crtc);
 	if (ret < 0) {
 		dev_err(ipu_crtc->dev, "irq request failed with %d.\n", ret);
 		goto err_put_plane1_res;
 	}
-	/* Only enable IRQ when we actually need it to trigger work. */
-	disable_irq(ipu_crtc->irq);
 
 	return 0;
 
@@ -438,21 +436,13 @@
 	struct ipu_client_platformdata *pdata = dev->platform_data;
 	struct drm_device *drm = data;
 	struct ipu_crtc *ipu_crtc;
-	int ret;
 
-	ipu_crtc = devm_kzalloc(dev, sizeof(*ipu_crtc), GFP_KERNEL);
-	if (!ipu_crtc)
-		return -ENOMEM;
+	ipu_crtc = dev_get_drvdata(dev);
+	memset(ipu_crtc, 0, sizeof(*ipu_crtc));
 
 	ipu_crtc->dev = dev;
 
-	ret = ipu_crtc_init(ipu_crtc, pdata, drm);
-	if (ret)
-		return ret;
-
-	dev_set_drvdata(dev, ipu_crtc);
-
-	return 0;
+	return ipu_crtc_init(ipu_crtc, pdata, drm);
 }
 
 static void ipu_drm_unbind(struct device *dev, struct device *master,
@@ -474,6 +464,7 @@
 static int ipu_drm_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
+	struct ipu_crtc *ipu_crtc;
 	int ret;
 
 	if (!dev->platform_data)
@@ -483,6 +474,12 @@
 	if (ret)
 		return ret;
 
+	ipu_crtc = devm_kzalloc(dev, sizeof(*ipu_crtc), GFP_KERNEL);
+	if (!ipu_crtc)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, ipu_crtc);
+
 	return component_add(dev, &ipu_crtc_ops);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/imx/parallel-display.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/imx/parallel-display.c
@@ -63,13 +63,15 @@
 		int ret;
 
 		if (!mode)
-			return -EINVAL;
+			return 0;
 
 		ret = of_get_drm_display_mode(np, &imxpd->mode,
 					      &imxpd->bus_flags,
 					      OF_USE_NATIVE_MODE);
-		if (ret)
-			return ret;
+		if (ret) {
+			drm_mode_destroy(connector->dev, mode);
+			return 0;
+		}
 
 		drm_mode_copy(mode, &imxpd->mode);
 		mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
@@ -204,9 +206,8 @@
 	u32 bus_format = 0;
 	const char *fmt;
 
-	imxpd = devm_kzalloc(dev, sizeof(*imxpd), GFP_KERNEL);
-	if (!imxpd)
-		return -ENOMEM;
+	imxpd = dev_get_drvdata(dev);
+	memset(imxpd, 0, sizeof(*imxpd));
 
 	edidp = of_get_property(np, "edid", &imxpd->edid_len);
 	if (edidp)
@@ -236,8 +237,6 @@
 	if (ret)
 		return ret;
 
-	dev_set_drvdata(dev, imxpd);
-
 	return 0;
 }
 
@@ -259,6 +258,14 @@
 
 static int imx_pd_probe(struct platform_device *pdev)
 {
+	struct imx_parallel_display *imxpd;
+
+	imxpd = devm_kzalloc(&pdev->dev, sizeof(*imxpd), GFP_KERNEL);
+	if (!imxpd)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, imxpd);
+
 	return component_add(&pdev->dev, &imx_pd_ops);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/ingenic/ingenic-drm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/ingenic/ingenic-drm.c
@@ -371,14 +371,18 @@
 	struct ingenic_drm *priv = drm_plane_get_priv(plane);
 	struct drm_plane_state *state = plane->state;
 	unsigned int width, height, cpp;
+	dma_addr_t addr;
 
-	width = state->crtc->state->adjusted_mode.hdisplay;
-	height = state->crtc->state->adjusted_mode.vdisplay;
-	cpp = state->fb->format->cpp[plane->index];
-
-	priv->dma_hwdesc->addr = drm_fb_cma_get_gem_addr(state->fb, state, 0);
-	priv->dma_hwdesc->cmd = width * height * cpp / 4;
-	priv->dma_hwdesc->cmd |= JZ_LCD_CMD_EOF_IRQ;
+	if (state && state->fb) {
+		addr = drm_fb_cma_get_gem_addr(state->fb, state, 0);
+		width = state->src_w >> 16;
+		height = state->src_h >> 16;
+		cpp = state->fb->format->cpp[0];
+
+		priv->dma_hwdesc->addr = addr;
+		priv->dma_hwdesc->cmd = width * height * cpp / 4;
+		priv->dma_hwdesc->cmd |= JZ_LCD_CMD_EOF_IRQ;
+	}
 }
 
 static void ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder,
@@ -463,7 +467,7 @@
 
 static irqreturn_t ingenic_drm_irq_handler(int irq, void *arg)
 {
-	struct ingenic_drm *priv = arg;
+	struct ingenic_drm *priv = drm_device_get_priv(arg);
 	unsigned int state;
 
 	regmap_read(priv->map, JZ_REG_LCD_STATE, &state);
@@ -820,6 +824,7 @@
 	{ .compatible = "ingenic,jz4725b-lcd", .data = &jz4725b_soc_info },
 	{ /* sentinel */ },
 };
+MODULE_DEVICE_TABLE(of, ingenic_drm_of_match);
 
 static struct platform_driver ingenic_drm_driver = {
 	.driver = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/lima/lima_device.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/lima/lima_device.c
@@ -293,6 +293,7 @@
 	struct resource *res;
 
 	dma_set_coherent_mask(ldev->dev, DMA_BIT_MASK(32));
+	dma_set_max_seg_size(ldev->dev, UINT_MAX);
 
 	err = lima_clk_init(ldev);
 	if (err)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/lima/lima_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/lima/lima_drv.c
@@ -300,8 +300,10 @@
 
 	/* Allocate and initialize the DRM device. */
 	ddev = drm_dev_alloc(&lima_drm_driver, &pdev->dev);
-	if (IS_ERR(ddev))
-		return PTR_ERR(ddev);
+	if (IS_ERR(ddev)) {
+		err = PTR_ERR(ddev);
+		goto err_out0;
+	}
 
 	ddev->dev_private = ldev;
 	ldev->ddev = ddev;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/lima/lima_gp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/lima/lima_gp.c
@@ -138,6 +138,11 @@
 	gp_write(LIMA_GP_CMD, cmd);
 }
 
+static int lima_gp_bus_stop_poll(struct lima_ip *ip)
+{
+	return !!(gp_read(LIMA_GP_STATUS) & LIMA_GP_STATUS_BUS_STOPPED);
+}
+
 static int lima_gp_hard_reset_poll(struct lima_ip *ip)
 {
 	gp_write(LIMA_GP_PERF_CNT_0_LIMIT, 0xC01A0000);
@@ -151,6 +156,13 @@
 
 	gp_write(LIMA_GP_PERF_CNT_0_LIMIT, 0xC0FFE000);
 	gp_write(LIMA_GP_INT_MASK, 0);
+
+	gp_write(LIMA_GP_CMD, LIMA_GP_CMD_STOP_BUS);
+	ret = lima_poll_timeout(ip, lima_gp_bus_stop_poll, 10, 100);
+	if (ret) {
+		dev_err(dev->dev, "%s bus stop timeout\n", lima_ip_name(ip));
+		return ret;
+	}
 	gp_write(LIMA_GP_CMD, LIMA_GP_CMD_RESET);
 	ret = lima_poll_timeout(ip, lima_gp_hard_reset_poll, 10, 100);
 	if (ret) {
@@ -244,7 +256,9 @@
 
 void lima_gp_fini(struct lima_ip *ip)
 {
+	struct lima_device *dev = ip->dev;
 
+	devm_free_irq(dev->dev, ip->irq, ip);
 }
 
 int lima_gp_pipe_init(struct lima_device *dev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/lima/lima_mmu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/lima/lima_mmu.c
@@ -97,7 +97,12 @@
 
 void lima_mmu_fini(struct lima_ip *ip)
 {
+	struct lima_device *dev = ip->dev;
 
+	if (ip->id == lima_ip_ppmmu_bcast)
+		return;
+
+	devm_free_irq(dev->dev, ip->irq, ip);
 }
 
 void lima_mmu_switch_vm(struct lima_ip *ip, struct lima_vm *vm)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/lima/lima_pp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/lima/lima_pp.c
@@ -251,7 +251,9 @@
 
 void lima_pp_fini(struct lima_ip *ip)
 {
+	struct lima_device *dev = ip->dev;
 
+	devm_free_irq(dev->dev, ip->irq, ip);
 }
 
 int lima_pp_bcast_init(struct lima_ip *ip)
@@ -272,7 +274,9 @@
 
 void lima_pp_bcast_fini(struct lima_ip *ip)
 {
+	struct lima_device *dev = ip->dev;
 
+	devm_free_irq(dev->dev, ip->irq, ip);
 }
 
 static int lima_pp_task_validate(struct lima_sched_pipe *pipe,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/mcde/mcde_display.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/mcde/mcde_display.c
@@ -946,6 +946,7 @@
 	struct drm_crtc *crtc = &pipe->crtc;
 	struct drm_device *drm = crtc->dev;
 	struct mcde *mcde = drm->dev_private;
+	struct drm_pending_vblank_event *event;
 
 	if (mcde->te_sync)
 		drm_crtc_vblank_off(crtc);
@@ -953,6 +954,15 @@
 	/* Disable FIFO A flow */
 	mcde_disable_fifo(mcde, MCDE_FIFO_A, true);
 
+	event = crtc->state->event;
+	if (event) {
+		crtc->state->event = NULL;
+
+		spin_lock_irq(&crtc->dev->event_lock);
+		drm_crtc_send_vblank_event(crtc, event);
+		spin_unlock_irq(&crtc->dev->event_lock);
+	}
+
 	dev_info(drm->dev, "MCDE display is disabled\n");
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/mcde/mcde_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/mcde/mcde_drv.c
@@ -215,7 +215,6 @@
 
 	drm_mode_config_reset(drm);
 	drm_kms_helper_poll_init(drm);
-	drm_fbdev_generic_setup(drm, 32);
 
 	return 0;
 
@@ -282,6 +281,8 @@
 	if (ret < 0)
 		goto unbind;
 
+	drm_fbdev_generic_setup(drm, 32);
+
 	return 0;
 
 unbind:
@@ -409,8 +410,8 @@
 	}
 
 	irq = platform_get_irq(pdev, 0);
-	if (!irq) {
-		ret = -EINVAL;
+	if (irq < 0) {
+		ret = irq;
 		goto clk_disable;
 	}
 
@@ -484,7 +485,8 @@
 	}
 	if (!match) {
 		dev_err(dev, "no matching components\n");
-		return -ENODEV;
+		ret = -ENODEV;
+		goto clk_disable;
 	}
 	if (IS_ERR(match)) {
 		dev_err(dev, "could not create component match\n");
@@ -531,6 +533,7 @@
 	},
 	{},
 };
+MODULE_DEVICE_TABLE(of, mcde_of_match);
 
 static struct platform_driver mcde_driver = {
 	.driver = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/mcde/mcde_dsi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/mcde/mcde_dsi.c
@@ -935,13 +935,15 @@
 	for_each_available_child_of_node(dev->of_node, child) {
 		panel = of_drm_find_panel(child);
 		if (IS_ERR(panel)) {
-			dev_err(dev, "failed to find panel try bridge (%lu)\n",
+			dev_err(dev, "failed to find panel try bridge (%ld)\n",
 				PTR_ERR(panel));
+			panel = NULL;
+
 			bridge = of_drm_find_bridge(child);
-			if (IS_ERR(bridge)) {
-				dev_err(dev, "failed to find bridge (%lu)\n",
-					PTR_ERR(bridge));
-				return PTR_ERR(bridge);
+			if (!bridge) {
+				dev_err(dev, "failed to find bridge\n");
+				of_node_put(child);
+				return -EINVAL;
 			}
 		}
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/mediatek/mtk_cec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/mediatek/mtk_cec.c
@@ -84,7 +84,7 @@
 	u32 tmp = readl(cec->regs + offset) & ~mask;
 
 	tmp |= val & mask;
-	writel(val, cec->regs + offset);
+	writel(tmp, cec->regs + offset);
 }
 
 void mtk_cec_set_hpd_event(struct device *dev,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/mediatek/mtk_dpi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/mediatek/mtk_dpi.c
@@ -10,7 +10,9 @@
 #include <linux/kernel.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/of_gpio.h>
 #include <linux/of_graph.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/platform_device.h>
 #include <linux/types.h>
 
@@ -48,13 +50,7 @@
 };
 
 enum mtk_dpi_out_color_format {
-	MTK_DPI_COLOR_FORMAT_RGB,
-	MTK_DPI_COLOR_FORMAT_RGB_FULL,
-	MTK_DPI_COLOR_FORMAT_YCBCR_444,
-	MTK_DPI_COLOR_FORMAT_YCBCR_422,
-	MTK_DPI_COLOR_FORMAT_XV_YCC,
-	MTK_DPI_COLOR_FORMAT_YCBCR_444_FULL,
-	MTK_DPI_COLOR_FORMAT_YCBCR_422_FULL
+	MTK_DPI_COLOR_FORMAT_RGB
 };
 
 struct mtk_dpi {
@@ -73,6 +69,9 @@
 	enum mtk_dpi_out_yc_map yc_map;
 	enum mtk_dpi_out_bit_num bit_num;
 	enum mtk_dpi_out_channel_swap channel_swap;
+	struct pinctrl *pinctrl;
+	struct pinctrl_state *pins_gpio;
+	struct pinctrl_state *pins_dpi;
 	int refcount;
 };
 
@@ -350,24 +349,11 @@
 static void mtk_dpi_config_color_format(struct mtk_dpi *dpi,
 					enum mtk_dpi_out_color_format format)
 {
-	if ((format == MTK_DPI_COLOR_FORMAT_YCBCR_444) ||
-	    (format == MTK_DPI_COLOR_FORMAT_YCBCR_444_FULL)) {
-		mtk_dpi_config_yuv422_enable(dpi, false);
-		mtk_dpi_config_csc_enable(dpi, true);
-		mtk_dpi_config_swap_input(dpi, false);
-		mtk_dpi_config_channel_swap(dpi, MTK_DPI_OUT_CHANNEL_SWAP_BGR);
-	} else if ((format == MTK_DPI_COLOR_FORMAT_YCBCR_422) ||
-		   (format == MTK_DPI_COLOR_FORMAT_YCBCR_422_FULL)) {
-		mtk_dpi_config_yuv422_enable(dpi, true);
-		mtk_dpi_config_csc_enable(dpi, true);
-		mtk_dpi_config_swap_input(dpi, true);
-		mtk_dpi_config_channel_swap(dpi, MTK_DPI_OUT_CHANNEL_SWAP_RGB);
-	} else {
-		mtk_dpi_config_yuv422_enable(dpi, false);
-		mtk_dpi_config_csc_enable(dpi, false);
-		mtk_dpi_config_swap_input(dpi, false);
-		mtk_dpi_config_channel_swap(dpi, MTK_DPI_OUT_CHANNEL_SWAP_RGB);
-	}
+	/* only support RGB888 */
+	mtk_dpi_config_yuv422_enable(dpi, false);
+	mtk_dpi_config_csc_enable(dpi, false);
+	mtk_dpi_config_swap_input(dpi, false);
+	mtk_dpi_config_channel_swap(dpi, MTK_DPI_OUT_CHANNEL_SWAP_RGB);
 }
 
 static void mtk_dpi_power_off(struct mtk_dpi *dpi)
@@ -402,7 +388,6 @@
 		goto err_pixel;
 	}
 
-	mtk_dpi_enable(dpi);
 	return 0;
 
 err_pixel:
@@ -538,14 +523,21 @@
 	struct mtk_dpi *dpi = mtk_dpi_from_encoder(encoder);
 
 	mtk_dpi_power_off(dpi);
+
+	if (dpi->pinctrl && dpi->pins_gpio)
+		pinctrl_select_state(dpi->pinctrl, dpi->pins_gpio);
 }
 
 static void mtk_dpi_encoder_enable(struct drm_encoder *encoder)
 {
 	struct mtk_dpi *dpi = mtk_dpi_from_encoder(encoder);
 
+	if (dpi->pinctrl && dpi->pins_dpi)
+		pinctrl_select_state(dpi->pinctrl, dpi->pins_dpi);
+
 	mtk_dpi_power_on(dpi);
 	mtk_dpi_set_display_mode(dpi, &dpi->mode);
+	mtk_dpi_enable(dpi);
 }
 
 static int mtk_dpi_atomic_check(struct drm_encoder *encoder,
@@ -689,6 +681,26 @@
 	dpi->dev = dev;
 	dpi->conf = (struct mtk_dpi_conf *)of_device_get_match_data(dev);
 
+	dpi->pinctrl = devm_pinctrl_get(&pdev->dev);
+	if (IS_ERR(dpi->pinctrl)) {
+		dpi->pinctrl = NULL;
+		dev_dbg(&pdev->dev, "Cannot find pinctrl!\n");
+	}
+	if (dpi->pinctrl) {
+		dpi->pins_gpio = pinctrl_lookup_state(dpi->pinctrl, "sleep");
+		if (IS_ERR(dpi->pins_gpio)) {
+			dpi->pins_gpio = NULL;
+			dev_dbg(&pdev->dev, "Cannot find pinctrl idle!\n");
+		}
+		if (dpi->pins_gpio)
+			pinctrl_select_state(dpi->pinctrl, dpi->pins_gpio);
+
+		dpi->pins_dpi = pinctrl_lookup_state(dpi->pinctrl, "default");
+		if (IS_ERR(dpi->pins_dpi)) {
+			dpi->pins_dpi = NULL;
+			dev_dbg(&pdev->dev, "Cannot find pinctrl active!\n");
+		}
+	}
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	dpi->regs = devm_ioremap_resource(dev, mem);
 	if (IS_ERR(dpi->regs)) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
@@ -73,11 +73,13 @@
 	struct drm_crtc *crtc = &mtk_crtc->base;
 	unsigned long flags;
 
-	spin_lock_irqsave(&crtc->dev->event_lock, flags);
-	drm_crtc_send_vblank_event(crtc, mtk_crtc->event);
-	drm_crtc_vblank_put(crtc);
-	mtk_crtc->event = NULL;
-	spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+	if (mtk_crtc->event) {
+		spin_lock_irqsave(&crtc->dev->event_lock, flags);
+		drm_crtc_send_vblank_event(crtc, mtk_crtc->event);
+		drm_crtc_vblank_put(crtc);
+		mtk_crtc->event = NULL;
+		spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
+	}
 }
 
 static void mtk_drm_finish_page_flip(struct mtk_drm_crtc *mtk_crtc)
@@ -240,7 +242,7 @@
 		drm_connector_list_iter_end(&conn_iter);
 	}
 
-	ret = pm_runtime_get_sync(crtc->dev->dev);
+	ret = pm_runtime_resume_and_get(crtc->dev->dev);
 	if (ret < 0) {
 		DRM_ERROR("Failed to enable power domain: %d\n", ret);
 		return ret;
@@ -298,6 +300,7 @@
 static void mtk_crtc_ddp_hw_fini(struct mtk_drm_crtc *mtk_crtc)
 {
 	struct drm_device *drm = mtk_crtc->base.dev;
+	struct drm_crtc *crtc = &mtk_crtc->base;
 	int i;
 
 	DRM_DEBUG_DRIVER("%s\n", __func__);
@@ -319,6 +322,13 @@
 	mtk_disp_mutex_unprepare(mtk_crtc->mutex);
 
 	pm_runtime_put(drm->dev);
+
+	if (crtc->state->event && !crtc->state->active) {
+		spin_lock_irq(&crtc->dev->event_lock);
+		drm_crtc_send_vblank_event(crtc, crtc->state->event);
+		crtc->state->event = NULL;
+		spin_unlock_irq(&crtc->dev->event_lock);
+	}
 }
 
 static void mtk_crtc_ddp_config(struct drm_crtc *crtc)
@@ -488,10 +498,18 @@
 
 static int mtk_drm_crtc_init(struct drm_device *drm,
 			     struct mtk_drm_crtc *mtk_crtc,
-			     struct drm_plane *primary,
-			     struct drm_plane *cursor, unsigned int pipe)
+			     unsigned int pipe)
 {
-	int ret;
+	struct drm_plane *primary = NULL;
+	struct drm_plane *cursor = NULL;
+	int i, ret;
+
+	for (i = 0; i < mtk_crtc->layer_nr; i++) {
+		if (mtk_crtc->planes[i].type == DRM_PLANE_TYPE_PRIMARY)
+			primary = &mtk_crtc->planes[i];
+		else if (mtk_crtc->planes[i].type == DRM_PLANE_TYPE_CURSOR)
+			cursor = &mtk_crtc->planes[i];
+	}
 
 	ret = drm_crtc_init_with_planes(drm, &mtk_crtc->base, primary, cursor,
 					&mtk_crtc_funcs, NULL);
@@ -529,6 +547,7 @@
 	int pipe = priv->num_pipes;
 	int ret;
 	int i;
+	uint gamma_lut_size = 0;
 
 	if (!path)
 		return 0;
@@ -579,6 +598,9 @@
 		}
 
 		mtk_crtc->ddp_comp[i] = comp;
+
+		if (comp->funcs && comp->funcs->gamma_set)
+			gamma_lut_size = MTK_LUT_SIZE;
 	}
 
 	mtk_crtc->layer_nr = mtk_ddp_comp_layer_nr(mtk_crtc->ddp_comp[0]);
@@ -596,13 +618,13 @@
 			return ret;
 	}
 
-	ret = mtk_drm_crtc_init(drm_dev, mtk_crtc, &mtk_crtc->planes[0],
-				mtk_crtc->layer_nr > 1 ? &mtk_crtc->planes[1] :
-				NULL, pipe);
+	ret = mtk_drm_crtc_init(drm_dev, mtk_crtc, pipe);
 	if (ret < 0)
 		return ret;
-	drm_mode_crtc_set_gamma_size(&mtk_crtc->base, MTK_LUT_SIZE);
-	drm_crtc_enable_color_mgmt(&mtk_crtc->base, 0, false, MTK_LUT_SIZE);
+
+	if (gamma_lut_size)
+		drm_mode_crtc_set_gamma_size(&mtk_crtc->base, gamma_lut_size);
+	drm_crtc_enable_color_mgmt(&mtk_crtc->base, 0, false, gamma_lut_size);
 	priv->num_pipes++;
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -417,6 +417,7 @@
 err_deinit:
 	mtk_drm_kms_deinit(drm);
 err_free:
+	private->drm = NULL;
 	drm_dev_put(drm);
 	return ret;
 }
@@ -594,8 +595,13 @@
 	pm_runtime_disable(dev);
 err_node:
 	of_node_put(private->mutex_node);
-	for (i = 0; i < DDP_COMPONENT_ID_MAX; i++)
+	for (i = 0; i < DDP_COMPONENT_ID_MAX; i++) {
 		of_node_put(private->comp_node[i]);
+		if (private->ddp_comp[i]) {
+			put_device(private->ddp_comp[i]->larb_dev);
+			private->ddp_comp[i] = NULL;
+		}
+	}
 	return ret;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/mediatek/mtk_drm_gem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/mediatek/mtk_drm_gem.c
@@ -21,6 +21,9 @@
 
 	size = round_up(size, PAGE_SIZE);
 
+	if (size == 0)
+		return ERR_PTR(-EINVAL);
+
 	mtk_gem_obj = kzalloc(sizeof(*mtk_gem_obj), GFP_KERNEL);
 	if (!mtk_gem_obj)
 		return ERR_PTR(-ENOMEM);
@@ -142,8 +145,6 @@
 
 	ret = dma_mmap_attrs(priv->dma_dev, vma, mtk_gem->cookie,
 			     mtk_gem->dma_addr, obj->size, mtk_gem->dma_attrs);
-	if (ret)
-		drm_gem_vm_close(vma);
 
 	return ret;
 }
@@ -269,9 +270,13 @@
 	}
 	mtk_gem->kvaddr = vmap(mtk_gem->pages, npages, VM_MAP,
 			       pgprot_writecombine(PAGE_KERNEL));
-
+	if (!mtk_gem->kvaddr) {
+		kfree(sgt);
+		kfree(mtk_gem->pages);
+		return ERR_PTR(-ENOMEM);
+	}
 out:
-	kfree((void *)sgt);
+	kfree(sgt);
 
 	return mtk_gem->kvaddr;
 }
@@ -284,6 +289,6 @@
 		return;
 
 	vunmap(vaddr);
-	mtk_gem->kvaddr = 0;
-	kfree((void *)mtk_gem->pages);
+	mtk_gem->kvaddr = NULL;
+	kfree(mtk_gem->pages);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/mediatek/mtk_drm_plane.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/mediatek/mtk_drm_plane.c
@@ -101,6 +101,16 @@
 						   true, true);
 }
 
+static void mtk_plane_atomic_disable(struct drm_plane *plane,
+				     struct drm_plane_state *old_state)
+{
+	struct mtk_plane_state *state = to_mtk_plane_state(plane->state);
+
+	state->pending.enable = false;
+	wmb(); /* Make sure the above parameter is set before update */
+	state->pending.dirty = true;
+}
+
 static void mtk_plane_atomic_update(struct drm_plane *plane,
 				    struct drm_plane_state *old_state)
 {
@@ -115,6 +125,11 @@
 	if (!crtc || WARN_ON(!fb))
 		return;
 
+	if (!plane->state->visible) {
+		mtk_plane_atomic_disable(plane, old_state);
+		return;
+	}
+
 	gem = fb->obj[0];
 	mtk_gem = to_mtk_gem_obj(gem);
 	addr = mtk_gem->dma_addr;
@@ -136,16 +151,6 @@
 	state->pending.dirty = true;
 }
 
-static void mtk_plane_atomic_disable(struct drm_plane *plane,
-				     struct drm_plane_state *old_state)
-{
-	struct mtk_plane_state *state = to_mtk_plane_state(plane->state);
-
-	state->pending.enable = false;
-	wmb(); /* Make sure the above parameter is set before update */
-	state->pending.dirty = true;
-}
-
 static const struct drm_plane_helper_funcs mtk_plane_helper_funcs = {
 	.prepare_fb = drm_gem_fb_prepare_fb,
 	.atomic_check = mtk_plane_atomic_check,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -64,8 +64,8 @@
 #define DSI_PS_WC			0x3fff
 #define DSI_PS_SEL			(3 << 16)
 #define PACKED_PS_16BIT_RGB565		(0 << 16)
-#define LOOSELY_PS_18BIT_RGB666		(1 << 16)
-#define PACKED_PS_18BIT_RGB666		(2 << 16)
+#define PACKED_PS_18BIT_RGB666		(1 << 16)
+#define LOOSELY_PS_24BIT_RGB666		(2 << 16)
 #define PACKED_PS_24BIT_RGB888		(3 << 16)
 
 #define DSI_VSA_NL		0x20
@@ -321,10 +321,10 @@
 		ps_bpp_mode |= PACKED_PS_24BIT_RGB888;
 		break;
 	case MIPI_DSI_FMT_RGB666:
-		ps_bpp_mode |= PACKED_PS_18BIT_RGB666;
+		ps_bpp_mode |= LOOSELY_PS_24BIT_RGB666;
 		break;
 	case MIPI_DSI_FMT_RGB666_PACKED:
-		ps_bpp_mode |= LOOSELY_PS_18BIT_RGB666;
+		ps_bpp_mode |= PACKED_PS_18BIT_RGB666;
 		break;
 	case MIPI_DSI_FMT_RGB565:
 		ps_bpp_mode |= PACKED_PS_16BIT_RGB565;
@@ -375,7 +375,7 @@
 		dsi_tmp_buf_bpp = 3;
 		break;
 	case MIPI_DSI_FMT_RGB666:
-		tmp_reg = LOOSELY_PS_18BIT_RGB666;
+		tmp_reg = LOOSELY_PS_24BIT_RGB666;
 		dsi_tmp_buf_bpp = 3;
 		break;
 	case MIPI_DSI_FMT_RGB666_PACKED:
@@ -645,6 +645,8 @@
 	mtk_dsi_reset_engine(dsi);
 	mtk_dsi_lane0_ulp_mode_enter(dsi);
 	mtk_dsi_clk_ulp_mode_enter(dsi);
+	/* set the lane number as 0 to pull down mipi */
+	writel(0, dsi->regs + DSI_TXRX_CTRL);
 
 	mtk_dsi_disable(dsi);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/mediatek/mtk_hdmi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/mediatek/mtk_hdmi.c
@@ -135,7 +135,7 @@
 
 struct hdmi_audio_param {
 	enum hdmi_audio_coding_type aud_codec;
-	enum hdmi_audio_sample_size aud_sampe_size;
+	enum hdmi_audio_sample_size aud_sample_size;
 	enum hdmi_aud_input_type aud_input_type;
 	enum hdmi_aud_i2s_fmt aud_i2s_fmt;
 	enum hdmi_aud_mclk aud_mclk;
@@ -1085,7 +1085,7 @@
 
 	hdmi->csp = HDMI_COLORSPACE_RGB;
 	aud_param->aud_codec = HDMI_AUDIO_CODING_TYPE_PCM;
-	aud_param->aud_sampe_size = HDMI_AUDIO_SAMPLE_SIZE_16;
+	aud_param->aud_sample_size = HDMI_AUDIO_SAMPLE_SIZE_16;
 	aud_param->aud_input_type = HDMI_AUD_INPUT_I2S;
 	aud_param->aud_i2s_fmt = HDMI_I2S_MODE_I2S_24BIT;
 	aud_param->aud_mclk = HDMI_AUD_MCLK_128FS;
@@ -1237,17 +1237,19 @@
 				    struct drm_display_mode *mode)
 {
 	struct mtk_hdmi *hdmi = hdmi_ctx_from_conn(conn);
+	struct drm_bridge *next_bridge;
 
 	dev_dbg(hdmi->dev, "xres=%d, yres=%d, refresh=%d, intl=%d clock=%d\n",
 		mode->hdisplay, mode->vdisplay, mode->vrefresh,
 		!!(mode->flags & DRM_MODE_FLAG_INTERLACE), mode->clock * 1000);
 
-	if (hdmi->bridge.next) {
+	next_bridge = drm_bridge_get_next_bridge(&hdmi->bridge);
+	if (next_bridge) {
 		struct drm_display_mode adjusted_mode;
 
 		drm_mode_copy(&adjusted_mode, mode);
-		if (!drm_bridge_mode_fixup(hdmi->bridge.next, mode,
-					   &adjusted_mode))
+		if (!drm_bridge_chain_mode_fixup(next_bridge, mode,
+						 &adjusted_mode))
 			return MODE_BAD;
 	}
 
@@ -1482,25 +1484,30 @@
 		dev_err(dev,
 			"Failed to get system configuration registers: %d\n",
 			ret);
-		return ret;
+		goto put_device;
 	}
 	hdmi->sys_regmap = regmap;
 
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	hdmi->regs = devm_ioremap_resource(dev, mem);
-	if (IS_ERR(hdmi->regs))
-		return PTR_ERR(hdmi->regs);
+	if (IS_ERR(hdmi->regs)) {
+		ret = PTR_ERR(hdmi->regs);
+		goto put_device;
+	}
 
 	remote = of_graph_get_remote_node(np, 1, 0);
-	if (!remote)
-		return -EINVAL;
+	if (!remote) {
+		ret = -EINVAL;
+		goto put_device;
+	}
 
 	if (!of_device_is_compatible(remote, "hdmi-connector")) {
 		hdmi->next_bridge = of_drm_find_bridge(remote);
 		if (!hdmi->next_bridge) {
 			dev_err(dev, "Waiting for external bridge\n");
 			of_node_put(remote);
-			return -EPROBE_DEFER;
+			ret = -EPROBE_DEFER;
+			goto put_device;
 		}
 	}
 
@@ -1509,7 +1516,8 @@
 		dev_err(dev, "Failed to find ddc-i2c-bus node in %pOF\n",
 			remote);
 		of_node_put(remote);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto put_device;
 	}
 	of_node_put(remote);
 
@@ -1517,10 +1525,14 @@
 	of_node_put(i2c_np);
 	if (!hdmi->ddc_adpt) {
 		dev_err(dev, "Failed to get ddc i2c adapter by node\n");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto put_device;
 	}
 
 	return 0;
+put_device:
+	put_device(hdmi->cec_dev);
+	return ret;
 }
 
 /*
@@ -1577,14 +1589,14 @@
 	switch (daifmt->fmt) {
 	case HDMI_I2S:
 		hdmi_params.aud_codec = HDMI_AUDIO_CODING_TYPE_PCM;
-		hdmi_params.aud_sampe_size = HDMI_AUDIO_SAMPLE_SIZE_16;
+		hdmi_params.aud_sample_size = HDMI_AUDIO_SAMPLE_SIZE_16;
 		hdmi_params.aud_input_type = HDMI_AUD_INPUT_I2S;
 		hdmi_params.aud_i2s_fmt = HDMI_I2S_MODE_I2S_24BIT;
 		hdmi_params.aud_mclk = HDMI_AUD_MCLK_128FS;
 		break;
 	case HDMI_SPDIF:
 		hdmi_params.aud_codec = HDMI_AUDIO_CODING_TYPE_PCM;
-		hdmi_params.aud_sampe_size = HDMI_AUDIO_SAMPLE_SIZE_16;
+		hdmi_params.aud_sample_size = HDMI_AUDIO_SAMPLE_SIZE_16;
 		hdmi_params.aud_input_type = HDMI_AUD_INPUT_SPDIF;
 		break;
 	default:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/mediatek/mtk_hdmi_phy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/mediatek/mtk_hdmi_phy.c
@@ -84,8 +84,9 @@
 	    hdmi_phy->conf->hdmi_phy_disable_tmds)
 		return &mtk_hdmi_phy_dev_ops;
 
-	dev_err(hdmi_phy->dev, "Failed to get dev ops of phy\n");
-		return NULL;
+	if (hdmi_phy)
+		dev_err(hdmi_phy->dev, "Failed to get dev ops of phy\n");
+	return NULL;
 }
 
 static void mtk_hdmi_phy_clk_get_data(struct mtk_hdmi_phy *hdmi_phy,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/meson/meson_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/meson/meson_drv.c
@@ -124,8 +124,11 @@
 	for_each_endpoint_of_node(dev->of_node, ep) {
 		/* If the endpoint node exists, consider it enabled */
 		remote = of_graph_get_remote_port(ep);
-		if (remote)
+		if (remote) {
+			of_node_put(remote);
+			of_node_put(ep);
 			return true;
+		}
 	}
 
 	return false;
@@ -420,6 +423,17 @@
 	return count;
 }
 
+static void meson_drv_shutdown(struct platform_device *pdev)
+{
+	struct meson_drm *priv = dev_get_drvdata(&pdev->dev);
+
+	if (!priv)
+		return;
+
+	drm_kms_helper_poll_fini(priv->drm);
+	drm_atomic_helper_shutdown(priv->drm);
+}
+
 static int meson_drv_probe(struct platform_device *pdev)
 {
 	struct component_match *match = NULL;
@@ -469,6 +483,7 @@
 
 static struct platform_driver meson_drm_platform_driver = {
 	.probe      = meson_drv_probe,
+	.shutdown   = meson_drv_shutdown,
 	.driver     = {
 		.name	= "meson-drm",
 		.of_match_table = dt_match,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/meson/meson_plane.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/meson/meson_plane.c
@@ -128,7 +128,7 @@
 
 	/* Enable OSD and BLK0, set max global alpha */
 	priv->viu.osd1_ctrl_stat = OSD_ENABLE |
-				   (0xFF << OSD_GLOBAL_ALPHA_SHIFT) |
+				   (0x100 << OSD_GLOBAL_ALPHA_SHIFT) |
 				   OSD_BLK0_ENABLE;
 
 	canvas_id_osd1 = priv->canvas_id_osd1;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/meson/meson_registers.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/meson/meson_registers.h
@@ -590,6 +590,11 @@
 #define VPP_WRAP_OSD3_MATRIX_PRE_OFFSET2 0x3dbc
 #define VPP_WRAP_OSD3_MATRIX_EN_CTRL 0x3dbd
 
+/* osd1 HDR */
+#define OSD1_HDR2_CTRL 0x38a0
+#define OSD1_HDR2_CTRL_VDIN0_HDR2_TOP_EN       BIT(13)
+#define OSD1_HDR2_CTRL_REG_ONLY_MAT            BIT(16)
+
 /* osd2 scaler */
 #define OSD2_VSC_PHASE_STEP 0x3d00
 #define OSD2_VSC_INI_PHASE 0x3d01
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/meson/meson_vclk.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/meson/meson_vclk.c
@@ -638,13 +638,18 @@
 		if (frac >= HDMI_FRAC_MAX_GXBB)
 			return false;
 	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
-		   meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL) ||
-		   meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
+		   meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) {
 		/* Empiric supported min/max dividers */
 		if (m < 106 || m > 247)
 			return false;
 		if (frac >= HDMI_FRAC_MAX_GXL)
 			return false;
+	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
+		/* Empiric supported min/max dividers */
+		if (m < 106 || m > 247)
+			return false;
+		if (frac >= HDMI_FRAC_MAX_G12A)
+			return false;
 	}
 
 	return true;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/meson/meson_venc_cvbs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/meson/meson_venc_cvbs.c
@@ -64,6 +64,25 @@
 	},
 };
 
+static const struct meson_cvbs_mode *
+meson_cvbs_get_mode(const struct drm_display_mode *req_mode)
+{
+	int i;
+
+	for (i = 0; i < MESON_CVBS_MODES_COUNT; ++i) {
+		struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i];
+
+		if (drm_mode_match(req_mode, &meson_mode->mode,
+				   DRM_MODE_MATCH_TIMINGS |
+				   DRM_MODE_MATCH_CLOCK |
+				   DRM_MODE_MATCH_FLAGS |
+				   DRM_MODE_MATCH_3D_FLAGS))
+			return meson_mode;
+	}
+
+	return NULL;
+}
+
 /* Connector */
 
 static void meson_cvbs_connector_destroy(struct drm_connector *connector)
@@ -136,14 +155,8 @@
 					struct drm_crtc_state *crtc_state,
 					struct drm_connector_state *conn_state)
 {
-	int i;
-
-	for (i = 0; i < MESON_CVBS_MODES_COUNT; ++i) {
-		struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i];
-
-		if (drm_mode_equal(&crtc_state->mode, &meson_mode->mode))
-			return 0;
-	}
+	if (meson_cvbs_get_mode(&crtc_state->mode))
+		return 0;
 
 	return -EINVAL;
 }
@@ -191,24 +204,17 @@
 				   struct drm_display_mode *mode,
 				   struct drm_display_mode *adjusted_mode)
 {
+	const struct meson_cvbs_mode *meson_mode = meson_cvbs_get_mode(mode);
 	struct meson_venc_cvbs *meson_venc_cvbs =
 					encoder_to_meson_venc_cvbs(encoder);
 	struct meson_drm *priv = meson_venc_cvbs->priv;
-	int i;
 
-	for (i = 0; i < MESON_CVBS_MODES_COUNT; ++i) {
-		struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i];
+	if (meson_mode) {
+		meson_venci_cvbs_mode_set(priv, meson_mode->enci);
 
-		if (drm_mode_equal(mode, &meson_mode->mode)) {
-			meson_venci_cvbs_mode_set(priv,
-						  meson_mode->enci);
-
-			/* Setup 27MHz vclk2 for ENCI and VDAC */
-			meson_vclk_setup(priv, MESON_VCLK_TARGET_CVBS,
-					 MESON_VCLK_CVBS, MESON_VCLK_CVBS,
-					 MESON_VCLK_CVBS, true);
-			break;
-		}
+		/* Setup 27MHz vclk2 for ENCI and VDAC */
+		meson_vclk_setup(priv, MESON_VCLK_TARGET_CVBS, MESON_VCLK_CVBS,
+				 MESON_VCLK_CVBS, MESON_VCLK_CVBS, true);
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/meson/meson_viu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/meson/meson_viu.c
@@ -91,7 +91,7 @@
 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF11_12));
 	writel(((m[9] & 0x1fff) << 16) | (m[10] & 0x1fff),
 		priv->io_base + _REG(VPP_WRAP_OSD1_MATRIX_COEF20_21));
-	writel((m[11] & 0x1fff) << 16,
+	writel((m[11] & 0x1fff),
 		priv->io_base +	_REG(VPP_WRAP_OSD1_MATRIX_COEF22));
 
 	writel(((m[18] & 0xfff) << 16) | (m[19] & 0xfff),
@@ -356,9 +356,14 @@
 	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
 	    meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
 		meson_viu_load_matrix(priv);
-	else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
+	else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
 		meson_viu_set_g12a_osd1_matrix(priv, RGB709_to_YUV709l_coeff,
 					       true);
+		/* fix green/pink color distortion from vendor u-boot */
+		writel_bits_relaxed(OSD1_HDR2_CTRL_REG_ONLY_MAT |
+				OSD1_HDR2_CTRL_VDIN0_HDR2_TOP_EN, 0,
+				priv->io_base + _REG(OSD1_HDR2_CTRL));
+	}
 
 	/* Initialize OSD1 fifo control register */
 	reg = VIU_OSD_DDR_PRIORITY_URGENT |
@@ -395,17 +400,17 @@
 			priv->io_base + _REG(VD2_IF0_LUMA_FIFO_SIZE));
 
 	if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
-		writel_relaxed(VIU_OSD_BLEND_REORDER(0, 1) |
-			       VIU_OSD_BLEND_REORDER(1, 0) |
-			       VIU_OSD_BLEND_REORDER(2, 0) |
-			       VIU_OSD_BLEND_REORDER(3, 0) |
-			       VIU_OSD_BLEND_DIN_EN(1) |
-			       VIU_OSD_BLEND1_DIN3_BYPASS_TO_DOUT1 |
-			       VIU_OSD_BLEND1_DOUT_BYPASS_TO_BLEND2 |
-			       VIU_OSD_BLEND_DIN0_BYPASS_TO_DOUT0 |
-			       VIU_OSD_BLEND_BLEN2_PREMULT_EN(1) |
-			       VIU_OSD_BLEND_HOLD_LINES(4),
-			       priv->io_base + _REG(VIU_OSD_BLEND_CTRL));
+		u32 val = (u32)VIU_OSD_BLEND_REORDER(0, 1) |
+			  (u32)VIU_OSD_BLEND_REORDER(1, 0) |
+			  (u32)VIU_OSD_BLEND_REORDER(2, 0) |
+			  (u32)VIU_OSD_BLEND_REORDER(3, 0) |
+			  (u32)VIU_OSD_BLEND_DIN_EN(1) |
+			  (u32)VIU_OSD_BLEND1_DIN3_BYPASS_TO_DOUT1 |
+			  (u32)VIU_OSD_BLEND1_DOUT_BYPASS_TO_BLEND2 |
+			  (u32)VIU_OSD_BLEND_DIN0_BYPASS_TO_DOUT0 |
+			  (u32)VIU_OSD_BLEND_BLEN2_PREMULT_EN(1) |
+			  (u32)VIU_OSD_BLEND_HOLD_LINES(4);
+		writel_relaxed(val, priv->io_base + _REG(VIU_OSD_BLEND_CTRL));
 
 		writel_relaxed(OSD_BLEND_PATH_SEL_ENABLE,
 			       priv->io_base + _REG(OSD1_BLEND_SRC_CTRL));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/meson/meson_vpp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/meson/meson_vpp.c
@@ -100,6 +100,8 @@
 			       priv->io_base + _REG(VPP_DOLBY_CTRL));
 		writel_relaxed(0x1020080,
 				priv->io_base + _REG(VPP_DUMMY_DATA1));
+		writel_relaxed(0x42020,
+				priv->io_base + _REG(VPP_DUMMY_DATA));
 	} else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
 		writel_relaxed(0xf, priv->io_base + _REG(DOLBY_PATH_CTRL));
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/mgag200/mgag200_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/mgag200/mgag200_drv.c
@@ -30,7 +30,8 @@
 static struct drm_driver driver;
 
 static const struct pci_device_id pciidlist[] = {
-	{ PCI_VENDOR_ID_MATROX, 0x522, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_SE_A },
+	{ PCI_VENDOR_ID_MATROX, 0x522, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		G200_SE_A | MGAG200_FLAG_HW_BUG_NO_STARTADD},
 	{ PCI_VENDOR_ID_MATROX, 0x524, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_SE_B },
 	{ PCI_VENDOR_ID_MATROX, 0x530, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_EV },
 	{ PCI_VENDOR_ID_MATROX, 0x532, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_WB },
@@ -63,6 +64,35 @@
 	DRM_VRAM_MM_FILE_OPERATIONS
 };
 
+static bool mgag200_pin_bo_at_0(const struct mga_device *mdev)
+{
+	return mdev->flags & MGAG200_FLAG_HW_BUG_NO_STARTADD;
+}
+
+int mgag200_driver_dumb_create(struct drm_file *file,
+			       struct drm_device *dev,
+			       struct drm_mode_create_dumb *args)
+{
+	struct mga_device *mdev = dev->dev_private;
+	unsigned long pg_align;
+
+	if (WARN_ONCE(!dev->vram_mm, "VRAM MM not initialized"))
+		return -EINVAL;
+
+	pg_align = 0ul;
+
+	/*
+	 * Aligning scanout buffers to the size of the video ram forces
+	 * placement at offset 0. Works around a bug where HW does not
+	 * respect 'startadd' field.
+	 */
+	if (mgag200_pin_bo_at_0(mdev))
+		pg_align = PFN_UP(mdev->mc.vram_size);
+
+	return drm_gem_vram_fill_create_dumb(file, dev, &dev->vram_mm->bdev,
+					     pg_align, false, args);
+}
+
 static struct drm_driver driver = {
 	.driver_features = DRIVER_GEM | DRIVER_MODESET,
 	.load = mgag200_driver_load,
@@ -74,7 +104,9 @@
 	.major = DRIVER_MAJOR,
 	.minor = DRIVER_MINOR,
 	.patchlevel = DRIVER_PATCHLEVEL,
-	DRM_GEM_VRAM_DRIVER
+	.dumb_create = mgag200_driver_dumb_create,
+	.dumb_map_offset = drm_gem_vram_driver_dumb_mmap_offset,
+	.gem_prime_mmap = drm_gem_prime_mmap,
 };
 
 static struct pci_driver mgag200_pci_driver = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/mgag200/mgag200_drv.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/mgag200/mgag200_drv.h
@@ -159,6 +159,12 @@
 	G200_EW3,
 };
 
+/* HW does not handle 'startadd' field correct. */
+#define MGAG200_FLAG_HW_BUG_NO_STARTADD	(1ul << 8)
+
+#define MGAG200_TYPE_MASK	(0x000000ff)
+#define MGAG200_FLAG_MASK	(0x00ffff00)
+
 #define IS_G200_SE(mdev) (mdev->type == G200_SE_A || mdev->type == G200_SE_B)
 
 struct mga_device {
@@ -188,6 +194,18 @@
 	u32 unique_rev_id;
 };
 
+static inline enum mga_type
+mgag200_type_from_driver_data(kernel_ulong_t driver_data)
+{
+	return (enum mga_type)(driver_data & MGAG200_TYPE_MASK);
+}
+
+static inline unsigned long
+mgag200_flags_from_driver_data(kernel_ulong_t driver_data)
+{
+	return driver_data & MGAG200_FLAG_MASK;
+}
+
 				/* mgag200_mode.c */
 int mgag200_modeset_init(struct mga_device *mdev);
 void mgag200_modeset_fini(struct mga_device *mdev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/mgag200/mgag200_i2c.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/mgag200/mgag200_i2c.c
@@ -135,7 +135,7 @@
 	i2c->adapter.algo_data = &i2c->bit;
 
 	i2c->bit.udelay = 10;
-	i2c->bit.timeout = 2;
+	i2c->bit.timeout = usecs_to_jiffies(2200);
 	i2c->bit.data = i2c;
 	i2c->bit.setsda		= mga_gpio_setsda;
 	i2c->bit.setscl		= mga_gpio_setscl;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/mgag200/mgag200_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/mgag200/mgag200_main.c
@@ -94,7 +94,8 @@
 	struct mga_device *mdev = dev->dev_private;
 	int ret, option;
 
-	mdev->type = flags;
+	mdev->flags = mgag200_flags_from_driver_data(flags);
+	mdev->type = mgag200_type_from_driver_data(flags);
 
 	/* Hardcode the number of CRTCs to 1 */
 	mdev->num_crtc = 1;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/adreno/a2xx_gpu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/adreno/a2xx_gpu.c
@@ -164,6 +164,11 @@
 	if (ret)
 		return ret;
 
+	gpu_write(gpu, REG_AXXX_CP_RB_CNTL,
+		MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE);
+
+	gpu_write(gpu, REG_AXXX_CP_RB_BASE, lower_32_bits(gpu->rb[0]->iova));
+
 	/* NOTE: PM4/micro-engine firmware registers look to be the same
 	 * for a2xx and a3xx.. we could possibly push that part down to
 	 * adreno_gpu base class.  Or push both PM4 and PFP but
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
@@ -215,6 +215,16 @@
 	if (ret)
 		return ret;
 
+	/*
+	 * Use the default ringbuffer size and block size but disable the RPTR
+	 * shadow
+	 */
+	gpu_write(gpu, REG_AXXX_CP_RB_CNTL,
+		MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE);
+
+	/* Set the ringbuffer address */
+	gpu_write(gpu, REG_AXXX_CP_RB_BASE, lower_32_bits(gpu->rb[0]->iova));
+
 	/* setup access protection: */
 	gpu_write(gpu, REG_A3XX_CP_PROTECT_CTRL, 0x00000007);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
@@ -265,6 +265,16 @@
 	if (ret)
 		return ret;
 
+	/*
+	 * Use the default ringbuffer size and block size but disable the RPTR
+	 * shadow
+	 */
+	gpu_write(gpu, REG_A4XX_CP_RB_CNTL,
+		MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE);
+
+	/* Set the ringbuffer address */
+	gpu_write(gpu, REG_A4XX_CP_RB_BASE, lower_32_bits(gpu->rb[0]->iova));
+
 	/* Load PM4: */
 	ptr = (uint32_t *)(adreno_gpu->fw[ADRENO_FW_PM4]->data);
 	len = adreno_gpu->fw[ADRENO_FW_PM4]->size / 4;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
@@ -71,7 +71,7 @@
 			 * since we've already mapped it once in
 			 * submit_reloc()
 			 */
-			if (WARN_ON(!ptr))
+			if (WARN_ON(IS_ERR_OR_NULL(ptr)))
 				return;
 
 			for (i = 0; i < dwords; i++) {
@@ -134,9 +134,13 @@
 	OUT_PKT7(ring, CP_SET_PROTECTED_MODE, 1);
 	OUT_RING(ring, 1);
 
-	/* Enable local preemption for finegrain preemption */
-	OUT_PKT7(ring, CP_PREEMPT_ENABLE_GLOBAL, 1);
-	OUT_RING(ring, 0x02);
+	/*
+	 * Disable local preemption by default because it requires
+	 * user-space to be aware of it and provide additional handling
+	 * to restore rendering state or do various flushes on switch.
+	 */
+	OUT_PKT7(ring, CP_PREEMPT_ENABLE_LOCAL, 1);
+	OUT_RING(ring, 0x0);
 
 	/* Allow CP_CONTEXT_SWITCH_YIELD packets in the IB2 */
 	OUT_PKT7(ring, CP_YIELD_ENABLE, 1);
@@ -581,8 +585,6 @@
 	if (adreno_gpu->info->quirks & ADRENO_QUIRK_TWO_PASS_USE_WFI)
 		gpu_rmw(gpu, REG_A5XX_PC_DBG_ECO_CNTL, 0, (1 << 8));
 
-	gpu_write(gpu, REG_A5XX_PC_DBG_ECO_CNTL, 0xc0200100);
-
 	/* Enable USE_RETENTION_FLOPS */
 	gpu_write(gpu, REG_A5XX_CP_CHICKEN_DBG, 0x02000000);
 
@@ -677,14 +679,21 @@
 	if (ret)
 		return ret;
 
-	a5xx_preempt_hw_init(gpu);
-
 	a5xx_gpmu_ucode_init(gpu);
 
 	ret = a5xx_ucode_init(gpu);
 	if (ret)
 		return ret;
 
+	/* Set the ringbuffer address */
+	gpu_write64(gpu, REG_A5XX_CP_RB_BASE, REG_A5XX_CP_RB_BASE_HI,
+		gpu->rb[0]->iova);
+
+	gpu_write(gpu, REG_A5XX_CP_RB_CNTL,
+		MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE);
+
+	a5xx_preempt_hw_init(gpu);
+
 	/* Disable the interrupts through the initial bringup stage */
 	gpu_write(gpu, REG_A5XX_RBBM_INT_0_MASK, A5XX_INT_MASK);
 
@@ -726,11 +735,18 @@
 		gpu->funcs->flush(gpu, gpu->rb[0]);
 		if (!a5xx_idle(gpu, gpu->rb[0]))
 			return -EINVAL;
-	} else {
-		/* Print a warning so if we die, we know why */
+	} else if (ret == -ENODEV) {
+		/*
+		 * This device does not use zap shader (but print a warning
+		 * just in case someone got their dt wrong.. hopefully they
+		 * have a debug UART to realize the error of their ways...
+		 * if you mess this up you are about to crash horribly)
+		 */
 		dev_warn_once(gpu->dev->dev,
 			"Zap shader not enabled - using SECVID_TRUST_CNTL instead\n");
 		gpu_write(gpu, REG_A5XX_RBBM_SECVID_TRUST_CNTL, 0x0);
+	} else {
+		return ret;
 	}
 
 	/* Last step - yield the ringbuffer */
@@ -1119,8 +1135,8 @@
 
 static int a5xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value)
 {
-	*value = gpu_read64(gpu, REG_A5XX_RBBM_PERFCTR_CP_0_LO,
-		REG_A5XX_RBBM_PERFCTR_CP_0_HI);
+	*value = gpu_read64(gpu, REG_A5XX_RBBM_ALWAYSON_COUNTER_LO,
+		REG_A5XX_RBBM_ALWAYSON_COUNTER_HI);
 
 	return 0;
 }
@@ -1352,6 +1368,10 @@
 {
 	u64 busy_cycles, busy_time;
 
+	/* Only read the gpu busy if the hardware is already active */
+	if (pm_runtime_get_if_in_use(&gpu->pdev->dev) == 0)
+		return 0;
+
 	busy_cycles = gpu_read64(gpu, REG_A5XX_RBBM_PERFCTR_RBBM_0_LO,
 			REG_A5XX_RBBM_PERFCTR_RBBM_0_HI);
 
@@ -1360,6 +1380,8 @@
 
 	gpu->devfreq.busy_cycles = busy_cycles;
 
+	pm_runtime_put(&gpu->pdev->dev);
+
 	if (WARN_ON(busy_time > ~0LU))
 		return ~0LU;
 
@@ -1394,18 +1416,31 @@
 static void check_speed_bin(struct device *dev)
 {
 	struct nvmem_cell *cell;
-	u32 bin, val;
+	u32 val;
+
+	/*
+	 * If the OPP table specifies a opp-supported-hw property then we have
+	 * to set something with dev_pm_opp_set_supported_hw() or the table
+	 * doesn't get populated so pick an arbitrary value that should
+	 * ensure the default frequencies are selected but not conflict with any
+	 * actual bins
+	 */
+	val = 0x80;
 
 	cell = nvmem_cell_get(dev, "speed_bin");
 
-	/* If a nvmem cell isn't defined, nothing to do */
-	if (IS_ERR(cell))
-		return;
+	if (!IS_ERR(cell)) {
+		void *buf = nvmem_cell_read(cell, NULL);
 
-	bin = *((u32 *) nvmem_cell_read(cell, NULL));
-	nvmem_cell_put(cell);
+		if (!IS_ERR(buf)) {
+			u8 bin = *((u8 *) buf);
 
-	val = (1 << bin);
+			val = (1 << bin);
+			kfree(buf);
+		}
+
+		nvmem_cell_put(cell);
+	}
 
 	dev_pm_opp_set_supported_hw(dev, &val, 1);
 }
@@ -1438,7 +1473,8 @@
 
 	check_speed_bin(&pdev->dev);
 
-	ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 4);
+	/* Restricting nr_rings to 1 to temporarily disable preemption */
+	ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1);
 	if (ret) {
 		a5xx_destroy(&(a5xx_gpu->base.base));
 		return ERR_PTR(ret);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/adreno/a5xx_gpu.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/adreno/a5xx_gpu.h
@@ -35,6 +35,7 @@
 	uint64_t preempt_iova[MSM_GPU_MAX_RINGS];
 
 	atomic_t preempt_state;
+	spinlock_t preempt_start_lock;
 	struct timer_list preempt_timer;
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/adreno/a5xx_power.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/adreno/a5xx_power.c
@@ -300,7 +300,7 @@
 	/* Set up the limits management */
 	if (adreno_is_a530(adreno_gpu))
 		a530_lm_setup(gpu);
-	else
+	else if (adreno_is_a540(adreno_gpu))
 		a540_lm_setup(gpu);
 
 	/* Set up SP/TP power collpase */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/adreno/a5xx_preempt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/adreno/a5xx_preempt.c
@@ -99,11 +99,18 @@
 		return;
 
 	/*
+	 * Serialize preemption start to ensure that we always make
+	 * decision on latest state. Otherwise we can get stuck in
+	 * lower priority or empty ring.
+	 */
+	spin_lock_irqsave(&a5xx_gpu->preempt_start_lock, flags);
+
+	/*
 	 * Try to start preemption by moving from NONE to START. If
 	 * unsuccessful, a preemption is already in flight
 	 */
 	if (!try_preempt_state(a5xx_gpu, PREEMPT_NONE, PREEMPT_START))
-		return;
+		goto out;
 
 	/* Get the next ring to preempt to */
 	ring = get_next_ring(gpu);
@@ -128,9 +135,11 @@
 		set_preempt_state(a5xx_gpu, PREEMPT_ABORT);
 		update_wptr(gpu, a5xx_gpu->cur_ring);
 		set_preempt_state(a5xx_gpu, PREEMPT_NONE);
-		return;
+		goto out;
 	}
 
+	spin_unlock_irqrestore(&a5xx_gpu->preempt_start_lock, flags);
+
 	/* Make sure the wptr doesn't update while we're in motion */
 	spin_lock_irqsave(&ring->lock, flags);
 	a5xx_gpu->preempt[ring->id]->wptr = get_wptr(ring);
@@ -154,6 +163,10 @@
 
 	/* And actually start the preemption */
 	gpu_write(gpu, REG_A5XX_CP_CONTEXT_SWITCH_CNTL, 1);
+	return;
+
+out:
+	spin_unlock_irqrestore(&a5xx_gpu->preempt_start_lock, flags);
 }
 
 void a5xx_preempt_irq(struct msm_gpu *gpu)
@@ -191,6 +204,12 @@
 	update_wptr(gpu, a5xx_gpu->cur_ring);
 
 	set_preempt_state(a5xx_gpu, PREEMPT_NONE);
+
+	/*
+	 * Try to trigger preemption again in case there was a submit or
+	 * retire during ring switch
+	 */
+	a5xx_preempt_trigger(gpu);
 }
 
 void a5xx_preempt_hw_init(struct msm_gpu *gpu)
@@ -207,6 +226,8 @@
 		return;
 
 	for (i = 0; i < gpu->nr_rings; i++) {
+		a5xx_gpu->preempt[i]->data = 0;
+		a5xx_gpu->preempt[i]->info = 0;
 		a5xx_gpu->preempt[i]->wptr = 0;
 		a5xx_gpu->preempt[i]->rptr = 0;
 		a5xx_gpu->preempt[i]->rbase = gpu->rb[i]->iova;
@@ -287,5 +308,6 @@
 		}
 	}
 
+	spin_lock_init(&a5xx_gpu->preempt_start_lock);
 	timer_setup(&a5xx_gpu->preempt_timer, a5xx_preempt_timer, 0);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -107,6 +107,13 @@
 	struct msm_gpu *gpu = &adreno_gpu->base;
 	int ret;
 
+	/*
+	 * This can get called from devfreq while the hardware is idle. Don't
+	 * bring up the power if it isn't already active
+	 */
+	if (pm_runtime_get_if_in_use(gmu->dev) == 0)
+		return;
+
 	gmu_write(gmu, REG_A6XX_GMU_DCVS_ACK_OPTION, 0);
 
 	gmu_write(gmu, REG_A6XX_GMU_DCVS_PERF_SETTING,
@@ -133,6 +140,7 @@
 	 * for now leave it at max so that the performance is nominal.
 	 */
 	icc_set_bw(gpu->icc_path, 0, MBps_to_icc(7216));
+	pm_runtime_put(gmu->dev);
 }
 
 void a6xx_gmu_set_freq(struct msm_gpu *gpu, unsigned long freq)
@@ -191,12 +199,22 @@
 {
 	int ret;
 	u32 val;
+	u32 mask, reset_val;
+
+	val = gmu_read(gmu, REG_A6XX_GMU_CM3_DTCM_START + 0xff8);
+	if (val <= 0x20010004) {
+		mask = 0xffffffff;
+		reset_val = 0xbabeface;
+	} else {
+		mask = 0x1ff;
+		reset_val = 0x100;
+	}
 
 	gmu_write(gmu, REG_A6XX_GMU_CM3_SYSRESET, 1);
 	gmu_write(gmu, REG_A6XX_GMU_CM3_SYSRESET, 0);
 
 	ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_CM3_FW_INIT_RESULT, val,
-		val == 0xbabeface, 100, 10000);
+		(val & mask) == reset_val, 100, 10000);
 
 	if (ret)
 		DRM_DEV_ERROR(gmu->dev, "GMU firmware initialization timed out\n");
@@ -705,10 +723,19 @@
 	/* Turn on the resources */
 	pm_runtime_get_sync(gmu->dev);
 
+	/*
+	 * "enable" the GX power domain which won't actually do anything but it
+	 * will make sure that the refcounting is correct in case we need to
+	 * bring down the GX after a GMU failure
+	 */
+	if (!IS_ERR_OR_NULL(gmu->gxpd))
+		pm_runtime_get_sync(gmu->gxpd);
+
 	/* Use a known rate to bring up the GMU */
 	clk_set_rate(gmu->core_clk, 200000000);
 	ret = clk_bulk_prepare_enable(gmu->nr_clocks, gmu->clocks);
 	if (ret) {
+		pm_runtime_put(gmu->gxpd);
 		pm_runtime_put(gmu->dev);
 		return ret;
 	}
@@ -744,19 +771,12 @@
 	/* Set the GPU to the highest power frequency */
 	__a6xx_gmu_set_freq(gmu, gmu->nr_gpu_freqs - 1);
 
-	/*
-	 * "enable" the GX power domain which won't actually do anything but it
-	 * will make sure that the refcounting is correct in case we need to
-	 * bring down the GX after a GMU failure
-	 */
-	if (!IS_ERR_OR_NULL(gmu->gxpd))
-		pm_runtime_get(gmu->gxpd);
-
 out:
 	/* On failure, shut down the GMU to leave it in a good state */
 	if (ret) {
 		disable_irq(gmu->gmu_irq);
 		a6xx_rpmh_stop(gmu);
+		pm_runtime_put(gmu->gxpd);
 		pm_runtime_put(gmu->dev);
 	}
 
@@ -1213,15 +1233,13 @@
 
 	irq = platform_get_irq_byname(pdev, name);
 
-	ret = request_irq(irq, handler, IRQF_TRIGGER_HIGH, name, gmu);
+	ret = request_irq(irq, handler, IRQF_TRIGGER_HIGH | IRQF_NO_AUTOEN, name, gmu);
 	if (ret) {
 		DRM_DEV_ERROR(&pdev->dev, "Unable to get interrupt %s %d\n",
 			      name, ret);
 		return ret;
 	}
 
-	disable_irq(irq);
-
 	return irq;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -512,6 +512,13 @@
 	if (ret)
 		goto out;
 
+	/* Set the ringbuffer address */
+	gpu_write64(gpu, REG_A6XX_CP_RB_BASE, REG_A6XX_CP_RB_BASE_HI,
+		gpu->rb[0]->iova);
+
+	gpu_write(gpu, REG_A6XX_CP_RB_CNTL,
+		MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE);
+
 	/* Always come up on rb 0 */
 	a6xx_gpu->cur_ring = gpu->rb[0];
 
@@ -537,12 +544,19 @@
 		a6xx_flush(gpu, gpu->rb[0]);
 		if (!a6xx_idle(gpu, gpu->rb[0]))
 			return -EINVAL;
-	} else {
-		/* Print a warning so if we die, we know why */
+	} else if (ret == -ENODEV) {
+		/*
+		 * This device does not use zap shader (but print a warning
+		 * just in case someone got their dt wrong.. hopefully they
+		 * have a debug UART to realize the error of their ways...
+		 * if you mess this up you are about to crash horribly)
+		 */
 		dev_warn_once(gpu->dev->dev,
 			"Zap shader not enabled - using SECVID_TRUST_CNTL instead\n");
 		gpu_write(gpu, REG_A6XX_RBBM_SECVID_TRUST_CNTL, 0x0);
 		ret = 0;
+	} else {
+		return ret;
 	}
 
 out:
@@ -759,8 +773,8 @@
 	/* Force the GPU power on so we can read this register */
 	a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET);
 
-	*value = gpu_read64(gpu, REG_A6XX_RBBM_PERFCTR_CP_0_LO,
-		REG_A6XX_RBBM_PERFCTR_CP_0_HI);
+	*value = gpu_read64(gpu, REG_A6XX_CP_ALWAYS_ON_COUNTER_LO,
+		REG_A6XX_CP_ALWAYS_ON_COUNTER_HI);
 
 	a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET);
 	return 0;
@@ -796,6 +810,11 @@
 	struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
 	u64 busy_cycles, busy_time;
 
+
+	/* Only read the gpu busy if the hardware is already active */
+	if (pm_runtime_get_if_in_use(a6xx_gpu->gmu.dev) == 0)
+		return 0;
+
 	busy_cycles = gmu_read64(&a6xx_gpu->gmu,
 			REG_A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_0_L,
 			REG_A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_0_H);
@@ -805,6 +824,8 @@
 
 	gpu->devfreq.busy_cycles = busy_cycles;
 
+	pm_runtime_put(a6xx_gpu->gmu.dev);
+
 	if (WARN_ON(busy_time > ~0LU))
 		return ~0LU;
 
@@ -870,6 +891,7 @@
 	BUG_ON(!node);
 
 	ret = a6xx_gmu_init(a6xx_gpu, node);
+	of_node_put(node);
 	if (ret) {
 		a6xx_destroy(&(a6xx_gpu->base.base));
 		return ERR_PTR(ret);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
@@ -352,26 +352,26 @@
 		cxdbg = ioremap(res->start, resource_size(res));
 
 	if (cxdbg) {
-		cxdbg_write(cxdbg, REG_A6XX_DBGC_CFG_DBGBUS_CNTLT,
+		cxdbg_write(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_CNTLT,
 			A6XX_DBGC_CFG_DBGBUS_CNTLT_SEGT(0xf));
 
-		cxdbg_write(cxdbg, REG_A6XX_DBGC_CFG_DBGBUS_CNTLM,
+		cxdbg_write(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_CNTLM,
 			A6XX_DBGC_CFG_DBGBUS_CNTLM_ENABLE(0xf));
 
-		cxdbg_write(cxdbg, REG_A6XX_DBGC_CFG_DBGBUS_IVTL_0, 0);
-		cxdbg_write(cxdbg, REG_A6XX_DBGC_CFG_DBGBUS_IVTL_1, 0);
-		cxdbg_write(cxdbg, REG_A6XX_DBGC_CFG_DBGBUS_IVTL_2, 0);
-		cxdbg_write(cxdbg, REG_A6XX_DBGC_CFG_DBGBUS_IVTL_3, 0);
+		cxdbg_write(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_IVTL_0, 0);
+		cxdbg_write(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_IVTL_1, 0);
+		cxdbg_write(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_IVTL_2, 0);
+		cxdbg_write(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_IVTL_3, 0);
 
-		cxdbg_write(cxdbg, REG_A6XX_DBGC_CFG_DBGBUS_BYTEL_0,
+		cxdbg_write(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0,
 			0x76543210);
-		cxdbg_write(cxdbg, REG_A6XX_DBGC_CFG_DBGBUS_BYTEL_1,
+		cxdbg_write(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1,
 			0xFEDCBA98);
 
-		cxdbg_write(cxdbg, REG_A6XX_DBGC_CFG_DBGBUS_MASKL_0, 0);
-		cxdbg_write(cxdbg, REG_A6XX_DBGC_CFG_DBGBUS_MASKL_1, 0);
-		cxdbg_write(cxdbg, REG_A6XX_DBGC_CFG_DBGBUS_MASKL_2, 0);
-		cxdbg_write(cxdbg, REG_A6XX_DBGC_CFG_DBGBUS_MASKL_3, 0);
+		cxdbg_write(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_MASKL_0, 0);
+		cxdbg_write(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_MASKL_1, 0);
+		cxdbg_write(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_MASKL_2, 0);
+		cxdbg_write(cxdbg, REG_A6XX_CX_DBGC_CFG_DBGBUS_MASKL_3, 0);
 	}
 
 	a6xx_state->debugbus = state_kcalloc(a6xx_state,
@@ -834,7 +834,7 @@
 	int i;
 
 	a6xx_state->indexed_regs = state_kcalloc(a6xx_state, count,
-		sizeof(a6xx_state->indexed_regs));
+		sizeof(*a6xx_state->indexed_regs));
 	if (!a6xx_state->indexed_regs)
 		return;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h
@@ -200,7 +200,7 @@
 	SHADER(A6XX_SP_LB_3_DATA, 0x800),
 	SHADER(A6XX_SP_LB_4_DATA, 0x800),
 	SHADER(A6XX_SP_LB_5_DATA, 0x200),
-	SHADER(A6XX_SP_CB_BINDLESS_DATA, 0x2000),
+	SHADER(A6XX_SP_CB_BINDLESS_DATA, 0x800),
 	SHADER(A6XX_SP_CB_LEGACY_DATA, 0x280),
 	SHADER(A6XX_SP_UAV_DATA, 0x80),
 	SHADER(A6XX_SP_INST_TAG, 0x80),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/adreno/adreno_device.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/adreno/adreno_device.c
@@ -233,8 +233,11 @@
 	if (ret)
 		return NULL;
 
-	/* Make sure pm runtime is active and reset any previous errors */
-	pm_runtime_set_active(&pdev->dev);
+	/*
+	 * Now that we have firmware loaded, and are ready to begin
+	 * booting the gpu, go ahead and enable runpm:
+	 */
+	pm_runtime_enable(&pdev->dev);
 
 	ret = pm_runtime_get_sync(&pdev->dev);
 	if (ret < 0) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -247,7 +247,7 @@
 		ret = request_firmware_direct(&fw, fwname, drm->dev);
 		if (!ret) {
 			DRM_DEV_INFO(drm->dev, "loaded %s from legacy location\n",
-				newname);
+				fwname);
 			adreno_gpu->fwloc = FW_LOCATION_LEGACY;
 			goto out;
 		} else if (adreno_gpu->fwloc != FW_LOCATION_UNKNOWN) {
@@ -350,30 +350,10 @@
 		ring->next = ring->start;
 
 		/* reset completed fence seqno: */
-		ring->memptrs->fence = ring->seqno;
+		ring->memptrs->fence = ring->fctx->completed_fence;
 		ring->memptrs->rptr = 0;
 	}
 
-	/*
-	 * Setup REG_CP_RB_CNTL.  The same value is used across targets (with
-	 * the excpetion of A430 that disables the RPTR shadow) - the cacluation
-	 * for the ringbuffer size and block size is moved to msm_gpu.h for the
-	 * pre-processor to deal with and the A430 variant is ORed in here
-	 */
-	adreno_gpu_write(adreno_gpu, REG_ADRENO_CP_RB_CNTL,
-		MSM_GPU_RB_CNTL_DEFAULT |
-		(adreno_is_a430(adreno_gpu) ? AXXX_CP_RB_CNTL_NO_UPDATE : 0));
-
-	/* Setup ringbuffer address - use ringbuffer[0] for GPU init */
-	adreno_gpu_write64(adreno_gpu, REG_ADRENO_CP_RB_BASE,
-		REG_ADRENO_CP_RB_BASE_HI, gpu->rb[0]->iova);
-
-	if (!adreno_is_a430(adreno_gpu)) {
-		adreno_gpu_write64(adreno_gpu, REG_ADRENO_CP_RB_RPTR_ADDR,
-			REG_ADRENO_CP_RB_RPTR_ADDR_HI,
-			rbmemptr(gpu->rb[0], rptr));
-	}
-
 	return 0;
 }
 
@@ -381,11 +361,8 @@
 static uint32_t get_rptr(struct adreno_gpu *adreno_gpu,
 		struct msm_ringbuffer *ring)
 {
-	if (adreno_is_a430(adreno_gpu))
-		return ring->memptrs->rptr = adreno_gpu_read(
-			adreno_gpu, REG_ADRENO_CP_RB_RPTR);
-	else
-		return ring->memptrs->rptr;
+	return ring->memptrs->rptr = adreno_gpu_read(
+		adreno_gpu, REG_ADRENO_CP_RB_RPTR);
 }
 
 struct msm_ringbuffer *adreno_active_ring(struct msm_gpu *gpu)
@@ -922,7 +899,6 @@
 	pm_runtime_set_autosuspend_delay(&pdev->dev,
 		adreno_gpu->info->inactive_period);
 	pm_runtime_use_autosuspend(&pdev->dev);
-	pm_runtime_enable(&pdev->dev);
 
 	return msm_gpu_init(drm, pdev, &adreno_gpu->base, &funcs->base,
 			adreno_gpu->info->name, &adreno_gpu_config);
@@ -931,11 +907,15 @@
 void adreno_gpu_cleanup(struct adreno_gpu *adreno_gpu)
 {
 	struct msm_gpu *gpu = &adreno_gpu->base;
+	struct msm_drm_private *priv = gpu->dev ? gpu->dev->dev_private : NULL;
 	unsigned int i;
 
 	for (i = 0; i < ARRAY_SIZE(adreno_gpu->info->fw); i++)
 		release_firmware(adreno_gpu->fw[i]);
 
+	if (priv && pm_runtime_enabled(&priv->gpu_pdev->dev))
+		pm_runtime_disable(&priv->gpu_pdev->dev);
+
 	icc_put(gpu->icc_path);
 
 	msm_gpu_cleanup(&adreno_gpu->base);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -47,11 +47,9 @@
 	ADRENO_FW_MAX,
 };
 
-enum adreno_quirks {
-	ADRENO_QUIRK_TWO_PASS_USE_WFI = 1,
-	ADRENO_QUIRK_FAULT_DETECT_MASK = 2,
-	ADRENO_QUIRK_LMLOADKILL_DISABLE = 3,
-};
+#define ADRENO_QUIRK_TWO_PASS_USE_WFI		BIT(0)
+#define ADRENO_QUIRK_FAULT_DETECT_MASK		BIT(1)
+#define ADRENO_QUIRK_LMLOADKILL_DISABLE		BIT(2)
 
 struct adreno_rev {
 	uint8_t  core;
@@ -74,7 +72,7 @@
 	const char *name;
 	const char *fw[ADRENO_FW_MAX];
 	uint32_t gmem;
-	enum adreno_quirks quirks;
+	u64 quirks;
 	struct msm_gpu *(*init)(struct drm_device *dev);
 	const char *zapfw;
 	u32 inactive_period;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h
@@ -15,19 +15,6 @@
 #define	DPU_PERF_DEFAULT_MAX_CORE_CLK_RATE	412500000
 
 /**
- * enum dpu_core_perf_data_bus_id - data bus identifier
- * @DPU_CORE_PERF_DATA_BUS_ID_MNOC: DPU/MNOC data bus
- * @DPU_CORE_PERF_DATA_BUS_ID_LLCC: MNOC/LLCC data bus
- * @DPU_CORE_PERF_DATA_BUS_ID_EBI: LLCC/EBI data bus
- */
-enum dpu_core_perf_data_bus_id {
-	DPU_CORE_PERF_DATA_BUS_ID_MNOC,
-	DPU_CORE_PERF_DATA_BUS_ID_LLCC,
-	DPU_CORE_PERF_DATA_BUS_ID_EBI,
-	DPU_CORE_PERF_DATA_BUS_ID_MAX,
-};
-
-/**
  * struct dpu_core_perf_params - definition of performance parameters
  * @max_per_pipe_ib: maximum instantaneous bandwidth request
  * @bw_ctl: arbitrated bandwidth request
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -381,7 +381,7 @@
 	spin_unlock_irqrestore(&dpu_crtc->spin_lock, flags);
 
 	if (!fevent) {
-		DRM_ERROR("crtc%d event %d overflow\n", crtc->base.id, event);
+		DRM_ERROR_RATELIMITED("crtc%d event %d overflow\n", crtc->base.id, event);
 		return;
 	}
 
@@ -651,7 +651,10 @@
 	if (crtc->state)
 		dpu_crtc_destroy_state(crtc, crtc->state);
 
-	__drm_atomic_helper_crtc_reset(crtc, &cstate->base);
+	if (cstate)
+		__drm_atomic_helper_crtc_reset(crtc, &cstate->base);
+	else
+		__drm_atomic_helper_crtc_reset(crtc, NULL);
 }
 
 /**
@@ -819,7 +822,7 @@
 	struct drm_plane *plane;
 	struct drm_display_mode *mode;
 
-	int cnt = 0, rc = 0, mixer_width, i, z_pos;
+	int cnt = 0, rc = 0, mixer_width = 0, i, z_pos;
 
 	struct dpu_multirect_plane_states multirect_plane[DPU_STAGE_MAX * 2];
 	int multirect_count = 0;
@@ -833,6 +836,8 @@
 	}
 
 	pstates = kzalloc(sizeof(*pstates) * DPU_STAGE_MAX * 4, GFP_KERNEL);
+	if (!pstates)
+		return -ENOMEM;
 
 	dpu_crtc = to_dpu_crtc(crtc);
 	cstate = to_dpu_crtc_state(state);
@@ -852,9 +857,11 @@
 
 	memset(pipe_staged, 0, sizeof(pipe_staged));
 
-	mixer_width = mode->hdisplay / cstate->num_mixers;
+	if (cstate->num_mixers) {
+		mixer_width = mode->hdisplay / cstate->num_mixers;
 
-	_dpu_crtc_setup_lm_bounds(crtc, state);
+		_dpu_crtc_setup_lm_bounds(crtc, state);
+	}
 
 	crtc_rect.x2 = mode->hdisplay;
 	crtc_rect.y2 = mode->vdisplay;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -44,6 +44,9 @@
 		(p) ? ((p)->hw_pp ? (p)->hw_pp->idx - PINGPONG_0 : -1) : -1, \
 		##__VA_ARGS__)
 
+#define DPU_ERROR_ENC_RATELIMITED(e, fmt, ...) DPU_ERROR_RATELIMITED("enc%d " fmt,\
+		(e) ? (e)->base.base.id : -1, ##__VA_ARGS__)
+
 /*
  * Two to anticipate panels that can do cmd/vid dynamic switching
  * plan is to create all possible physical encoder types, and switch between
@@ -2151,7 +2154,7 @@
 		return;
 	}
 
-	DPU_ERROR_ENC(dpu_enc, "frame done timeout\n");
+	DPU_ERROR_ENC_RATELIMITED(dpu_enc, "frame done timeout\n");
 
 	event = DPU_ENCODER_FRAME_EVENT_ERROR;
 	trace_dpu_enc_frame_done_timeout(DRMID(drm_enc), event);
@@ -2185,7 +2188,6 @@
 
 	dpu_enc = to_dpu_encoder_virt(enc);
 
-	mutex_init(&dpu_enc->enc_lock);
 	ret = dpu_encoder_setup_display(dpu_enc, dpu_kms, disp_info);
 	if (ret)
 		goto fail;
@@ -2200,7 +2202,6 @@
 				0);
 
 
-	mutex_init(&dpu_enc->rc_lock);
 	INIT_DELAYED_WORK(&dpu_enc->delayed_off_work,
 			dpu_encoder_off_work);
 	dpu_enc->idle_timeout = IDLE_TIMEOUT;
@@ -2232,7 +2233,7 @@
 
 	dpu_enc = devm_kzalloc(dev->dev, sizeof(*dpu_enc), GFP_KERNEL);
 	if (!dpu_enc)
-		return ERR_PTR(ENOMEM);
+		return ERR_PTR(-ENOMEM);
 
 	rc = drm_encoder_init(dev, &dpu_enc->base, &dpu_encoder_funcs,
 			drm_enc_mode, NULL);
@@ -2245,6 +2246,8 @@
 
 	spin_lock_init(&dpu_enc->enc_spinlock);
 	dpu_enc->enabled = false;
+	mutex_init(&dpu_enc->enc_lock);
+	mutex_init(&dpu_enc->rc_lock);
 
 	return &dpu_enc->base;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
@@ -479,9 +479,6 @@
 
 	_dpu_encoder_phys_cmd_pingpong_config(phys_enc);
 
-	if (!dpu_encoder_phys_cmd_is_master(phys_enc))
-		return;
-
 	ctl = phys_enc->hw_ctl;
 	ctl->ops.get_bitmask_intf(ctl, &flush_mask, phys_enc->intf_idx);
 	ctl->ops.update_pending_flush(ctl, flush_mask);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
@@ -258,12 +258,14 @@
 		mode.htotal >>= 1;
 		mode.hsync_start >>= 1;
 		mode.hsync_end >>= 1;
+		mode.hskew >>= 1;
 
 		DPU_DEBUG_VIDENC(phys_enc,
-			"split_role %d, halve horizontal %d %d %d %d\n",
+			"split_role %d, halve horizontal %d %d %d %d %d\n",
 			phys_enc->split_role,
 			mode.hdisplay, mode.htotal,
-			mode.hsync_start, mode.hsync_end);
+			mode.hsync_start, mode.hsync_end,
+			mode.hskew);
 	}
 
 	drm_mode_to_intf_timing_params(phys_enc, &mode, &timing_params);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
@@ -255,13 +255,13 @@
 
 	INTERLEAVED_RGB_FMT(RGB565,
 		0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT,
-		C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3,
+		C1_B_Cb, C0_G_Y, C2_R_Cr, 0, 3,
 		false, 2, 0,
 		DPU_FETCH_LINEAR, 1),
 
 	INTERLEAVED_RGB_FMT(BGR565,
 		0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT,
-		C1_B_Cb, C0_G_Y, C2_R_Cr, 0, 3,
+		C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3,
 		false, 2, 0,
 		DPU_FETCH_LINEAR, 1),
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -281,10 +281,12 @@
 	int i;
 
 	for (i = 0; i < ctx->mixer_count; i++) {
-		DPU_REG_WRITE(c, CTL_LAYER(LM_0 + i), 0);
-		DPU_REG_WRITE(c, CTL_LAYER_EXT(LM_0 + i), 0);
-		DPU_REG_WRITE(c, CTL_LAYER_EXT2(LM_0 + i), 0);
-		DPU_REG_WRITE(c, CTL_LAYER_EXT3(LM_0 + i), 0);
+		enum dpu_lm mixer_id = ctx->mixer_hw_caps[i].id;
+
+		DPU_REG_WRITE(c, CTL_LAYER(mixer_id), 0);
+		DPU_REG_WRITE(c, CTL_LAYER_EXT(mixer_id), 0);
+		DPU_REG_WRITE(c, CTL_LAYER_EXT2(mixer_id), 0);
+		DPU_REG_WRITE(c, CTL_LAYER_EXT3(mixer_id), 0);
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
@@ -137,11 +137,13 @@
 		u32 *idx)
 {
 	int rc = 0;
-	const struct dpu_sspp_sub_blks *sblk = ctx->cap->sblk;
+	const struct dpu_sspp_sub_blks *sblk;
 
-	if (!ctx)
+	if (!ctx || !ctx->cap || !ctx->cap->sblk)
 		return -EINVAL;
 
+	sblk = ctx->cap->sblk;
+
 	switch (s_id) {
 	case DPU_SSPP_SRC:
 		*idx = sblk->src_blk.base;
@@ -404,7 +406,7 @@
 
 	(void)pe;
 	if (_sspp_subblk_offset(ctx, DPU_SSPP_SCALER_QSEED3, &idx) || !sspp
-		|| !scaler3_cfg || !ctx || !ctx->cap || !ctx->cap->sblk)
+		|| !scaler3_cfg)
 		return;
 
 	dpu_hw_setup_scaler3(&ctx->hw, scaler3_cfg, idx,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -88,8 +88,8 @@
 					&status);
 	} else {
 		seq_puts(s, "\nSafe signal status:\n");
-		if (kms->hw_mdp->ops.get_danger_status)
-			kms->hw_mdp->ops.get_danger_status(kms->hw_mdp,
+		if (kms->hw_mdp->ops.get_safe_status)
+			kms->hw_mdp->ops.get_safe_status(kms->hw_mdp,
 					&status);
 	}
 	pm_runtime_put_sync(&kms->pdev->dev);
@@ -596,11 +596,11 @@
 	_dpu_kms_mmu_destroy(dpu_kms);
 
 	if (dpu_kms->catalog) {
-		for (i = 0; i < dpu_kms->catalog->vbif_count; i++) {
-			u32 vbif_idx = dpu_kms->catalog->vbif[i].id;
-
-			if ((vbif_idx < VBIF_MAX) && dpu_kms->hw_vbif[vbif_idx])
-				dpu_hw_vbif_destroy(dpu_kms->hw_vbif[vbif_idx]);
+		for (i = 0; i < ARRAY_SIZE(dpu_kms->hw_vbif); i++) {
+			if (dpu_kms->hw_vbif[i]) {
+				dpu_hw_vbif_destroy(dpu_kms->hw_vbif[i]);
+				dpu_kms->hw_vbif[i] = NULL;
+			}
 		}
 	}
 
@@ -897,7 +897,7 @@
 	for (i = 0; i < dpu_kms->catalog->vbif_count; i++) {
 		u32 vbif_idx = dpu_kms->catalog->vbif[i].id;
 
-		dpu_kms->hw_vbif[i] = dpu_hw_vbif_init(vbif_idx,
+		dpu_kms->hw_vbif[vbif_idx] = dpu_hw_vbif_init(vbif_idx,
 				dpu_kms->vbif[vbif_idx], dpu_kms->catalog);
 		if (IS_ERR_OR_NULL(dpu_kms->hw_vbif[vbif_idx])) {
 			rc = PTR_ERR(dpu_kms->hw_vbif[vbif_idx]);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
@@ -30,26 +30,17 @@
  * @fmt: Pointer to format string
  */
 #define DPU_DEBUG(fmt, ...)                                                \
-	do {                                                               \
-		if (unlikely(drm_debug & DRM_UT_KMS))                      \
-			DRM_DEBUG(fmt, ##__VA_ARGS__); \
-		else                                                       \
-			pr_debug(fmt, ##__VA_ARGS__);                      \
-	} while (0)
+	DRM_DEBUG_DRIVER(fmt, ##__VA_ARGS__)
 
 /**
  * DPU_DEBUG_DRIVER - macro for hardware driver logging
  * @fmt: Pointer to format string
  */
 #define DPU_DEBUG_DRIVER(fmt, ...)                                         \
-	do {                                                               \
-		if (unlikely(drm_debug & DRM_UT_DRIVER))                   \
-			DRM_ERROR(fmt, ##__VA_ARGS__); \
-		else                                                       \
-			pr_debug(fmt, ##__VA_ARGS__);                      \
-	} while (0)
+	DRM_DEBUG_DRIVER(fmt, ##__VA_ARGS__)
 
 #define DPU_ERROR(fmt, ...) pr_err("[dpu error]" fmt, ##__VA_ARGS__)
+#define DPU_ERROR_RATELIMITED(fmt, ...) pr_err_ratelimited("[dpu error]" fmt, ##__VA_ARGS__)
 
 /**
  * ktime_compare_safe - compare two ktime structures
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -853,9 +853,9 @@
 		crtc_state = drm_atomic_get_new_crtc_state(state->state,
 							   state->crtc);
 
-	min_scale = FRAC_16_16(1, pdpu->pipe_sblk->maxdwnscale);
+	min_scale = FRAC_16_16(1, pdpu->pipe_sblk->maxupscale);
 	ret = drm_atomic_helper_check_plane_state(state, crtc_state, min_scale,
-					  pdpu->pipe_sblk->maxupscale << 16,
+					  pdpu->pipe_sblk->maxdwnscale << 16,
 					  true, true);
 	if (ret) {
 		DPU_ERROR_PLANE(pdpu, "Check plane state failed (%d)\n", ret);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/disp/dpu1/dpu_vbif.c
@@ -11,6 +11,14 @@
 #include "dpu_hw_vbif.h"
 #include "dpu_trace.h"
 
+static struct dpu_hw_vbif *dpu_get_vbif(struct dpu_kms *dpu_kms, enum dpu_vbif vbif_idx)
+{
+	if (vbif_idx < ARRAY_SIZE(dpu_kms->hw_vbif))
+		return dpu_kms->hw_vbif[vbif_idx];
+
+	return NULL;
+}
+
 /**
  * _dpu_vbif_wait_for_xin_halt - wait for the xin to halt
  * @vbif:	Pointer to hardware vbif driver
@@ -148,11 +156,11 @@
 void dpu_vbif_set_ot_limit(struct dpu_kms *dpu_kms,
 		struct dpu_vbif_set_ot_params *params)
 {
-	struct dpu_hw_vbif *vbif = NULL;
+	struct dpu_hw_vbif *vbif;
 	struct dpu_hw_mdp *mdp;
 	bool forced_on = false;
 	u32 ot_lim;
-	int ret, i;
+	int ret;
 
 	if (!dpu_kms) {
 		DPU_ERROR("invalid arguments\n");
@@ -160,12 +168,7 @@
 	}
 	mdp = dpu_kms->hw_mdp;
 
-	for (i = 0; i < ARRAY_SIZE(dpu_kms->hw_vbif); i++) {
-		if (dpu_kms->hw_vbif[i] &&
-				dpu_kms->hw_vbif[i]->idx == params->vbif_idx)
-			vbif = dpu_kms->hw_vbif[i];
-	}
-
+	vbif = dpu_get_vbif(dpu_kms, params->vbif_idx);
 	if (!vbif || !mdp) {
 		DPU_DEBUG("invalid arguments vbif %d mdp %d\n",
 				vbif != 0, mdp != 0);
@@ -208,7 +211,7 @@
 void dpu_vbif_set_qos_remap(struct dpu_kms *dpu_kms,
 		struct dpu_vbif_set_qos_params *params)
 {
-	struct dpu_hw_vbif *vbif = NULL;
+	struct dpu_hw_vbif *vbif;
 	struct dpu_hw_mdp *mdp;
 	bool forced_on = false;
 	const struct dpu_vbif_qos_tbl *qos_tbl;
@@ -220,13 +223,7 @@
 	}
 	mdp = dpu_kms->hw_mdp;
 
-	for (i = 0; i < ARRAY_SIZE(dpu_kms->hw_vbif); i++) {
-		if (dpu_kms->hw_vbif[i] &&
-				dpu_kms->hw_vbif[i]->idx == params->vbif_idx) {
-			vbif = dpu_kms->hw_vbif[i];
-			break;
-		}
-	}
+	vbif = dpu_get_vbif(dpu_kms, params->vbif_idx);
 
 	if (!vbif || !vbif->cap) {
 		DPU_ERROR("invalid vbif %d\n", params->vbif_idx);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c
@@ -268,6 +268,7 @@
 {
 	struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
 	struct mdp4_kms *mdp4_kms = get_kms(crtc);
+	unsigned long flags;
 
 	DBG("%s", mdp4_crtc->name);
 
@@ -280,6 +281,14 @@
 	mdp_irq_unregister(&mdp4_kms->base, &mdp4_crtc->err);
 	mdp4_disable(mdp4_kms);
 
+	if (crtc->state->event && !crtc->state->active) {
+		WARN_ON(mdp4_crtc->event);
+		spin_lock_irqsave(&mdp4_kms->dev->event_lock, flags);
+		drm_crtc_send_vblank_event(crtc, crtc->state->event);
+		crtc->state->event = NULL;
+		spin_unlock_irqrestore(&mdp4_kms->dev->event_lock, flags);
+	}
+
 	mdp4_crtc->enabled = false;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c
@@ -121,7 +121,7 @@
 	if (mdp4_dsi_encoder->enabled)
 		return;
 
-	 mdp4_crtc_set_config(encoder->crtc,
+	mdp4_crtc_set_config(encoder->crtc,
 			MDP4_DMA_CONFIG_PACK_ALIGN_MSB |
 			MDP4_DMA_CONFIG_DEFLKR_EN |
 			MDP4_DMA_CONFIG_DITHER_EN |
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
@@ -88,8 +88,6 @@
 	if (mdp4_kms->rev > 1)
 		mdp4_write(mdp4_kms, REG_MDP4_RESET_STATUS, 1);
 
-	dev->mode_config.allow_fb_modifiers = true;
-
 out:
 	pm_runtime_put_sync(dev->dev);
 
@@ -110,13 +108,6 @@
 
 static void mdp4_prepare_commit(struct msm_kms *kms, struct drm_atomic_state *state)
 {
-	int i;
-	struct drm_crtc *crtc;
-	struct drm_crtc_state *crtc_state;
-
-	/* see 119ecb7fd */
-	for_each_new_crtc_in_state(state, crtc, crtc_state, i)
-		drm_crtc_vblank_get(crtc);
 }
 
 static void mdp4_flush_commit(struct msm_kms *kms, unsigned crtc_mask)
@@ -135,12 +126,6 @@
 
 static void mdp4_complete_commit(struct msm_kms *kms, unsigned crtc_mask)
 {
-	struct mdp4_kms *mdp4_kms = to_mdp4_kms(to_mdp_kms(kms));
-	struct drm_crtc *crtc;
-
-	/* see 119ecb7fd */
-	for_each_crtc_mask(mdp4_kms->dev, crtc, crtc_mask)
-		drm_crtc_vblank_put(crtc);
 }
 
 static long mdp4_round_pixclk(struct msm_kms *kms, unsigned long rate,
@@ -260,6 +245,7 @@
 		encoder = mdp4_lcdc_encoder_init(dev, panel_node);
 		if (IS_ERR(encoder)) {
 			DRM_DEV_ERROR(dev->dev, "failed to construct LCDC encoder\n");
+			of_node_put(panel_node);
 			return PTR_ERR(encoder);
 		}
 
@@ -269,6 +255,7 @@
 		connector = mdp4_lvds_connector_init(dev, panel_node, encoder);
 		if (IS_ERR(connector)) {
 			DRM_DEV_ERROR(dev->dev, "failed to initialize LVDS connector\n");
+			of_node_put(panel_node);
 			return PTR_ERR(connector);
 		}
 
@@ -420,6 +407,7 @@
 {
 	struct platform_device *pdev = to_platform_device(dev->dev);
 	struct mdp4_platform_config *config = mdp4_get_config(pdev);
+	struct msm_drm_private *priv = dev->dev_private;
 	struct mdp4_kms *mdp4_kms;
 	struct msm_kms *kms = NULL;
 	struct msm_gem_address_space *aspace;
@@ -434,7 +422,8 @@
 
 	mdp_kms_init(&mdp4_kms->base, &kms_funcs);
 
-	kms = &mdp4_kms->base.base;
+	priv->kms = &mdp4_kms->base.base;
+	kms = priv->kms;
 
 	mdp4_kms->dev = dev;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c
@@ -61,8 +61,9 @@
 	return ret;
 }
 
-static int mdp4_lvds_connector_mode_valid(struct drm_connector *connector,
-				 struct drm_display_mode *mode)
+static enum drm_mode_status
+mdp4_lvds_connector_mode_valid(struct drm_connector *connector,
+			       struct drm_display_mode *mode)
 {
 	struct mdp4_lvds_connector *mdp4_lvds_connector =
 			to_mdp4_lvds_connector(connector);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c
@@ -347,6 +347,12 @@
 	return mdp4_plane->pipe;
 }
 
+static const uint64_t supported_format_modifiers[] = {
+	DRM_FORMAT_MOD_SAMSUNG_64_32_TILE,
+	DRM_FORMAT_MOD_LINEAR,
+	DRM_FORMAT_MOD_INVALID
+};
+
 /* initialize plane */
 struct drm_plane *mdp4_plane_init(struct drm_device *dev,
 		enum mdp4_pipe pipe_id, bool private_plane)
@@ -375,7 +381,7 @@
 	type = private_plane ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
 	ret = drm_universal_plane_init(dev, plane, 0xff, &mdp4_plane_funcs,
 				 mdp4_plane->formats, mdp4_plane->nformats,
-				 NULL, type, NULL);
+				 supported_format_modifiers, type, NULL);
 	if (ret)
 		goto fail;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/disp/mdp5/mdp5_cmd_encoder.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/disp/mdp5/mdp5_cmd_encoder.c
@@ -41,7 +41,7 @@
 {
 	struct mdp5_kms *mdp5_kms = get_kms(encoder);
 	struct device *dev = encoder->dev->dev;
-	u32 total_lines_x100, vclks_line, cfg;
+	u32 total_lines, vclks_line, cfg;
 	long vsync_clk_speed;
 	struct mdp5_hw_mixer *mixer = mdp5_crtc_get_mixer(encoder->crtc);
 	int pp_id = mixer->pp;
@@ -51,8 +51,8 @@
 		return -EINVAL;
 	}
 
-	total_lines_x100 = mode->vtotal * drm_mode_vrefresh(mode);
-	if (!total_lines_x100) {
+	total_lines = mode->vtotal * drm_mode_vrefresh(mode);
+	if (!total_lines) {
 		DRM_DEV_ERROR(dev, "%s: vtotal(%d) or vrefresh(%d) is 0\n",
 			      __func__, mode->vtotal, drm_mode_vrefresh(mode));
 		return -EINVAL;
@@ -64,15 +64,23 @@
 							vsync_clk_speed);
 		return -EINVAL;
 	}
-	vclks_line = vsync_clk_speed * 100 / total_lines_x100;
+	vclks_line = vsync_clk_speed / total_lines;
 
 	cfg = MDP5_PP_SYNC_CONFIG_VSYNC_COUNTER_EN
 		| MDP5_PP_SYNC_CONFIG_VSYNC_IN_EN;
 	cfg |= MDP5_PP_SYNC_CONFIG_VSYNC_COUNT(vclks_line);
 
+	/*
+	 * Tearcheck emits a blanking signal every vclks_line * vtotal * 2 ticks on
+	 * the vsync_clk equating to roughly half the desired panel refresh rate.
+	 * This is only necessary as stability fallback if interrupts from the
+	 * panel arrive too late or not at all, but is currently used by default
+	 * because these panel interrupts are not wired up yet.
+	 */
 	mdp5_write(mdp5_kms, REG_MDP5_PP_SYNC_CONFIG_VSYNC(pp_id), cfg);
 	mdp5_write(mdp5_kms,
-		REG_MDP5_PP_SYNC_CONFIG_HEIGHT(pp_id), 0xfff0);
+		REG_MDP5_PP_SYNC_CONFIG_HEIGHT(pp_id), (2 * mode->vtotal));
+
 	mdp5_write(mdp5_kms,
 		REG_MDP5_PP_VSYNC_INIT_VAL(pp_id), mode->vdisplay);
 	mdp5_write(mdp5_kms, REG_MDP5_PP_RD_PTR_IRQ(pp_id), mode->vdisplay + 1);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
@@ -534,9 +534,15 @@
 		if (ret)
 			return ret;
 
-		mdp5_mixer_release(new_crtc_state->state, old_mixer);
+		ret = mdp5_mixer_release(new_crtc_state->state, old_mixer);
+		if (ret)
+			return ret;
+
 		if (old_r_mixer) {
-			mdp5_mixer_release(new_crtc_state->state, old_r_mixer);
+			ret = mdp5_mixer_release(new_crtc_state->state, old_r_mixer);
+			if (ret)
+				return ret;
+
 			if (!need_right_mixer)
 				pipeline->r_mixer = NULL;
 		}
@@ -903,8 +909,10 @@
 
 	ret = msm_gem_get_and_pin_iova(cursor_bo, kms->aspace,
 			&mdp5_crtc->cursor.iova);
-	if (ret)
+	if (ret) {
+		drm_gem_object_put(cursor_bo);
 		return -EINVAL;
+	}
 
 	pm_runtime_get_sync(&pdev->dev);
 
@@ -1042,7 +1050,10 @@
 	if (crtc->state)
 		mdp5_crtc_destroy_state(crtc, crtc->state);
 
-	__drm_atomic_helper_crtc_reset(crtc, &mdp5_cstate->base);
+	if (mdp5_cstate)
+		__drm_atomic_helper_crtc_reset(crtc, &mdp5_cstate->base);
+	else
+		__drm_atomic_helper_crtc_reset(crtc, NULL);
 
 	drm_crtc_vblank_reset(crtc);
 }
@@ -1099,7 +1110,7 @@
 	struct mdp5_crtc *mdp5_crtc = container_of(irq, struct mdp5_crtc,
 								pp_done);
 
-	complete(&mdp5_crtc->pp_completion);
+	complete_all(&mdp5_crtc->pp_completion);
 }
 
 static void mdp5_crtc_wait_for_pp_done(struct drm_crtc *crtc)
@@ -1112,8 +1123,8 @@
 	ret = wait_for_completion_timeout(&mdp5_crtc->pp_completion,
 						msecs_to_jiffies(50));
 	if (ret == 0)
-		dev_warn(dev->dev, "pp done time out, lm=%d\n",
-			 mdp5_cstate->pipeline.mixer->lm);
+		dev_warn_ratelimited(dev->dev, "pp done time out, lm=%d\n",
+				     mdp5_cstate->pipeline.mixer->lm);
 }
 
 static void mdp5_crtc_wait_for_flush_done(struct drm_crtc *crtc)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
@@ -698,9 +698,9 @@
 	pdev = mdp5_kms->pdev;
 
 	irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
-	if (irq < 0) {
-		ret = irq;
-		DRM_DEV_ERROR(&pdev->dev, "failed to get irq: %d\n", ret);
+	if (!irq) {
+		ret = -EINVAL;
+		DRM_DEV_ERROR(&pdev->dev, "failed to get irq\n");
 		goto fail;
 	}
 
@@ -1037,7 +1037,8 @@
 
 	return 0;
 fail:
-	mdp5_destroy(pdev);
+	if (mdp5_kms)
+		mdp5_destroy(pdev);
 	return ret;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.c
@@ -116,21 +116,28 @@
 	return 0;
 }
 
-void mdp5_mixer_release(struct drm_atomic_state *s, struct mdp5_hw_mixer *mixer)
+int mdp5_mixer_release(struct drm_atomic_state *s, struct mdp5_hw_mixer *mixer)
 {
 	struct mdp5_global_state *global_state = mdp5_get_global_state(s);
-	struct mdp5_hw_mixer_state *new_state = &global_state->hwmixer;
+	struct mdp5_hw_mixer_state *new_state;
 
 	if (!mixer)
-		return;
+		return 0;
+
+	if (IS_ERR(global_state))
+		return PTR_ERR(global_state);
+
+	new_state = &global_state->hwmixer;
 
 	if (WARN_ON(!new_state->hwmixer_to_crtc[mixer->idx]))
-		return;
+		return -EINVAL;
 
 	DBG("%s: release from crtc %s", mixer->name,
 	    new_state->hwmixer_to_crtc[mixer->idx]->name);
 
 	new_state->hwmixer_to_crtc[mixer->idx] = NULL;
+
+	return 0;
 }
 
 void mdp5_mixer_destroy(struct mdp5_hw_mixer *mixer)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.h
@@ -30,7 +30,7 @@
 int mdp5_mixer_assign(struct drm_atomic_state *s, struct drm_crtc *crtc,
 		      uint32_t caps, struct mdp5_hw_mixer **mixer,
 		      struct mdp5_hw_mixer **r_mixer);
-void mdp5_mixer_release(struct drm_atomic_state *s,
-			struct mdp5_hw_mixer *mixer);
+int mdp5_mixer_release(struct drm_atomic_state *s,
+		       struct mdp5_hw_mixer *mixer);
 
 #endif /* __MDP5_LM_H__ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.c
@@ -119,18 +119,24 @@
 	return 0;
 }
 
-void mdp5_pipe_release(struct drm_atomic_state *s, struct mdp5_hw_pipe *hwpipe)
+int mdp5_pipe_release(struct drm_atomic_state *s, struct mdp5_hw_pipe *hwpipe)
 {
 	struct msm_drm_private *priv = s->dev->dev_private;
 	struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));
-	struct mdp5_global_state *state = mdp5_get_global_state(s);
-	struct mdp5_hw_pipe_state *new_state = &state->hwpipe;
+	struct mdp5_global_state *state;
+	struct mdp5_hw_pipe_state *new_state;
 
 	if (!hwpipe)
-		return;
+		return 0;
+
+	state = mdp5_get_global_state(s);
+	if (IS_ERR(state))
+		return PTR_ERR(state);
+
+	new_state = &state->hwpipe;
 
 	if (WARN_ON(!new_state->hwpipe_to_plane[hwpipe->idx]))
-		return;
+		return -EINVAL;
 
 	DBG("%s: release from plane %s", hwpipe->name,
 		new_state->hwpipe_to_plane[hwpipe->idx]->name);
@@ -141,6 +147,8 @@
 	}
 
 	new_state->hwpipe_to_plane[hwpipe->idx] = NULL;
+
+	return 0;
 }
 
 void mdp5_pipe_destroy(struct mdp5_hw_pipe *hwpipe)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.h
@@ -37,7 +37,7 @@
 		     uint32_t caps, uint32_t blkcfg,
 		     struct mdp5_hw_pipe **hwpipe,
 		     struct mdp5_hw_pipe **r_hwpipe);
-void mdp5_pipe_release(struct drm_atomic_state *s, struct mdp5_hw_pipe *hwpipe);
+int mdp5_pipe_release(struct drm_atomic_state *s, struct mdp5_hw_pipe *hwpipe);
 
 struct mdp5_hw_pipe *mdp5_pipe_init(enum mdp5_pipe pipe,
 		uint32_t reg_offset, uint32_t caps);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c
@@ -179,7 +179,10 @@
 		drm_framebuffer_put(plane->state->fb);
 
 	kfree(to_mdp5_plane_state(plane->state));
+	plane->state = NULL;
 	mdp5_state = kzalloc(sizeof(*mdp5_state), GFP_KERNEL);
+	if (!mdp5_state)
+		return;
 
 	/* assign default blend parameters */
 	mdp5_state->alpha = 255;
@@ -218,8 +221,7 @@
 {
 	struct mdp5_plane_state *pstate = to_mdp5_plane_state(state);
 
-	if (state->fb)
-		drm_framebuffer_put(state->fb);
+	__drm_atomic_helper_plane_destroy_state(state);
 
 	kfree(pstate);
 }
@@ -390,12 +392,24 @@
 				mdp5_state->r_hwpipe = NULL;
 
 
-			mdp5_pipe_release(state->state, old_hwpipe);
-			mdp5_pipe_release(state->state, old_right_hwpipe);
+			ret = mdp5_pipe_release(state->state, old_hwpipe);
+			if (ret)
+				return ret;
+
+			ret = mdp5_pipe_release(state->state, old_right_hwpipe);
+			if (ret)
+				return ret;
+
 		}
 	} else {
-		mdp5_pipe_release(state->state, mdp5_state->hwpipe);
-		mdp5_pipe_release(state->state, mdp5_state->r_hwpipe);
+		ret = mdp5_pipe_release(state->state, mdp5_state->hwpipe);
+		if (ret)
+			return ret;
+
+		ret = mdp5_pipe_release(state->state, mdp5_state->r_hwpipe);
+		if (ret)
+			return ret;
+
 		mdp5_state->hwpipe = mdp5_state->r_hwpipe = NULL;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c
@@ -358,7 +358,7 @@
 
 			drm_printf(p, "%s:%d\t%d\t%s\n",
 				pipe2name(pipe), j, inuse,
-				plane ? plane->name : NULL);
+				plane ? plane->name : "(null)");
 
 			total += inuse;
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/dsi/dsi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/dsi/dsi.c
@@ -26,17 +26,22 @@
 	}
 
 	phy_pdev = of_find_device_by_node(phy_node);
-	if (phy_pdev)
+	if (phy_pdev) {
 		msm_dsi->phy = platform_get_drvdata(phy_pdev);
+		msm_dsi->phy_dev = &phy_pdev->dev;
+	}
 
 	of_node_put(phy_node);
 
-	if (!phy_pdev || !msm_dsi->phy) {
+	if (!phy_pdev) {
+		DRM_DEV_ERROR(&pdev->dev, "%s: phy driver is not ready\n", __func__);
+		return -EPROBE_DEFER;
+	}
+	if (!msm_dsi->phy) {
+		put_device(&phy_pdev->dev);
 		DRM_DEV_ERROR(&pdev->dev, "%s: phy driver is not ready\n", __func__);
 		return -EPROBE_DEFER;
 	}
-
-	msm_dsi->phy_dev = get_device(&phy_pdev->dev);
 
 	return 0;
 }
@@ -198,6 +203,12 @@
 		return -EINVAL;
 
 	priv = dev->dev_private;
+
+	if (priv->num_bridges == ARRAY_SIZE(priv->bridges)) {
+		DRM_DEV_ERROR(dev->dev, "too many bridges\n");
+		return -ENOSPC;
+	}
+
 	msm_dsi->dev = dev;
 
 	ret = msm_dsi_host_modeset_init(msm_dsi->host, dev);
@@ -206,8 +217,10 @@
 		goto fail;
 	}
 
-	if (!msm_dsi_manager_validate_current_config(msm_dsi->id))
+	if (!msm_dsi_manager_validate_current_config(msm_dsi->id)) {
+		ret = -EINVAL;
 		goto fail;
+	}
 
 	msm_dsi->encoder = encoder;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/dsi/dsi_cfg.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/dsi/dsi_cfg.c
@@ -97,7 +97,7 @@
 static const struct msm_dsi_config msm8996_dsi_cfg = {
 	.io_offset = DSI_6G_REG_SHIFT,
 	.reg_cfg = {
-		.num = 2,
+		.num = 3,
 		.regs = {
 			{"vdda", 18160, 1 },	/* 1.25 V */
 			{"vcca", 17000, 32 },	/* 0.925 V */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -460,7 +460,7 @@
 
 	return 0;
 err:
-	for (; i > 0; i--)
+	while (--i >= 0)
 		clk_disable_unprepare(msm_host->bus_clks[i]);
 
 	return ret;
@@ -663,7 +663,7 @@
 	struct drm_display_mode *mode = msm_host->mode;
 	u32 pclk_rate;
 
-	pclk_rate = mode->clock * 1000;
+	pclk_rate = mode->clock * 1000u;
 
 	/*
 	 * For dual DSI mode, the current DRM mode has the complete width of the
@@ -1051,9 +1051,21 @@
 
 static void dsi_wait4video_eng_busy(struct msm_dsi_host *msm_host)
 {
+	u32 data;
+
 	if (!(msm_host->mode_flags & MIPI_DSI_MODE_VIDEO))
 		return;
 
+	data = dsi_read(msm_host, REG_DSI_STATUS0);
+
+	/* if video mode engine is not busy, its because
+	 * either timing engine was not turned on or the
+	 * DSI controller has finished transmitting the video
+	 * data already, so no need to wait in those cases
+	 */
+	if (!(data & DSI_STATUS0_VIDEO_MODE_ENGINE_BUSY))
+		return;
+
 	if (msm_host->power_on && msm_host->enabled) {
 		dsi_wait4video_done(msm_host);
 		/* delay 4 ms to skip BLLP */
@@ -1348,10 +1360,10 @@
 			dsi_get_bpp(msm_host->format) / 8;
 
 	len = dsi_cmd_dma_add(msm_host, msg);
-	if (!len) {
+	if (len < 0) {
 		pr_err("%s: failed to add cmd type = 0x%x\n",
 			__func__,  msg->type);
-		return -EINVAL;
+		return len;
 	}
 
 	/* for video mode, do not send cmds more than
@@ -1370,10 +1382,14 @@
 	}
 
 	ret = dsi_cmd_dma_tx(msm_host, len);
-	if (ret < len) {
-		pr_err("%s: cmd dma tx failed, type=0x%x, data0=0x%x, len=%d\n",
-			__func__, msg->type, (*(u8 *)(msg->tx_buf)), len);
-		return -ECOMM;
+	if (ret < 0) {
+		pr_err("%s: cmd dma tx failed, type=0x%x, data0=0x%x, len=%d, ret=%d\n",
+			__func__, msg->type, (*(u8 *)(msg->tx_buf)), len, ret);
+		return ret;
+	} else if (ret < len) {
+		pr_err("%s: cmd dma tx failed, type=0x%x, data0=0x%x, ret=%d len=%d\n",
+			__func__, msg->type, (*(u8 *)(msg->tx_buf)), ret, len);
+		return -EIO;
 	}
 
 	return len;
@@ -1669,6 +1685,8 @@
 	if (!prop) {
 		DRM_DEV_DEBUG(dev,
 			"failed to find data lane mapping, using default\n");
+		/* Set the number of date lanes to 4 by default. */
+		msm_host->num_data_lanes = 4;
 		return 0;
 	}
 
@@ -1871,6 +1889,9 @@
 
 	/* setup workqueue */
 	msm_host->workqueue = alloc_ordered_workqueue("dsi_drm_work", 0);
+	if (!msm_host->workqueue)
+		return -ENOMEM;
+
 	INIT_WORK(&msm_host->err_work, dsi_err_worker);
 	INIT_WORK(&msm_host->hpd_work, dsi_hpd_worker);
 
@@ -2097,9 +2118,12 @@
 		}
 
 		ret = dsi_cmds2buf_tx(msm_host, msg);
-		if (ret < msg->tx_len) {
+		if (ret < 0) {
 			pr_err("%s: Read cmd Tx failed, %d\n", __func__, ret);
 			return ret;
+		} else if (ret < msg->tx_len) {
+			pr_err("%s: Read cmd Tx failed, too short: %d\n", __func__, ret);
+			return -ECOMM;
 		}
 
 		/*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -336,7 +336,7 @@
 	return num;
 }
 
-static int dsi_mgr_connector_mode_valid(struct drm_connector *connector,
+static enum drm_mode_status dsi_mgr_connector_mode_valid(struct drm_connector *connector,
 				struct drm_display_mode *mode)
 {
 	int id = dsi_mgr_connector_get_id(connector);
@@ -479,6 +479,7 @@
 	struct msm_dsi *msm_dsi1 = dsi_mgr_get_dsi(DSI_1);
 	struct mipi_dsi_host *host = msm_dsi->host;
 	struct drm_panel *panel = msm_dsi->panel;
+	struct msm_dsi_pll *src_pll;
 	bool is_dual_dsi = IS_DUAL_DSI();
 	int ret;
 
@@ -519,6 +520,10 @@
 								id, ret);
 	}
 
+	/* Save PLL status if it is a clock source */
+	src_pll = msm_dsi_phy_get_pll(msm_dsi->phy);
+	msm_dsi_pll_save_state(src_pll);
+
 	ret = msm_dsi_host_power_off(host);
 	if (ret)
 		pr_err("%s: host %d power off failed,%d\n", __func__, id, ret);
@@ -620,7 +625,7 @@
 	return connector;
 
 fail:
-	connector->funcs->destroy(msm_dsi->connector);
+	connector->funcs->destroy(connector);
 	return ERR_PTR(ret);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
@@ -347,7 +347,7 @@
 	} else {
 		timing->shared_timings.clk_pre =
 			linear_inter(tmax, tmin, pcnt2, 0, false);
-			timing->shared_timings.clk_pre_inc_by_2 = 0;
+		timing->shared_timings.clk_pre_inc_by_2 = 0;
 	}
 
 	timing->ta_go = 3;
@@ -464,7 +464,9 @@
 	struct device *dev = &phy->pdev->dev;
 	int ret;
 
-	pm_runtime_get_sync(dev);
+	ret = pm_runtime_resume_and_get(dev);
+	if (ret)
+		return ret;
 
 	ret = clk_prepare_enable(phy->ahb_clk);
 	if (ret) {
@@ -604,6 +606,10 @@
 			goto fail;
 	}
 
+	ret = devm_pm_runtime_enable(&pdev->dev);
+	if (ret)
+		return ret;
+
 	/* PLL init will call into clk_register which requires
 	 * register access, so we need to enable power and ahb clock.
 	 */
@@ -665,12 +671,14 @@
 int msm_dsi_phy_enable(struct msm_dsi_phy *phy, int src_pll_id,
 			struct msm_dsi_phy_clk_request *clk_req)
 {
-	struct device *dev = &phy->pdev->dev;
+	struct device *dev;
 	int ret;
 
 	if (!phy || !phy->cfg->ops.enable)
 		return -EINVAL;
 
+	dev = &phy->pdev->dev;
+
 	ret = dsi_phy_enable_resource(phy);
 	if (ret) {
 		DRM_DEV_ERROR(dev, "%s: resource enable failed, %d\n",
@@ -724,10 +732,6 @@
 	if (!phy || !phy->cfg->ops.disable)
 		return;
 
-	/* Save PLL status if it is a clock source */
-	if (phy->usecase != MSM_DSI_PHY_SLAVE)
-		msm_dsi_pll_save_state(phy->pll);
-
 	phy->cfg->ops.disable(phy);
 
 	dsi_phy_regulator_disable(phy);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c
@@ -139,7 +139,7 @@
 		.disable = dsi_20nm_phy_disable,
 		.init = msm_dsi_phy_init_common,
 	},
-	.io_start = { 0xfd998300, 0xfd9a0300 },
+	.io_start = { 0xfd998500, 0xfd9a0500 },
 	.num_dsi_phy = 2,
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c
@@ -411,6 +411,12 @@
 	if (pll_10nm->slave)
 		dsi_pll_enable_pll_bias(pll_10nm->slave);
 
+	rc = dsi_pll_10nm_vco_set_rate(hw,pll_10nm->vco_current_rate, 0);
+	if (rc) {
+		pr_err("vco_set_rate failed, rc=%d\n", rc);
+		return rc;
+	}
+
 	/* Start PLL */
 	pll_write(pll_10nm->phy_cmn_mmio + REG_DSI_10nm_PHY_CMN_PLL_CNTRL,
 		  0x01);
@@ -553,6 +559,7 @@
 	struct pll_10nm_cached_state *cached = &pll_10nm->cached_state;
 	void __iomem *phy_base = pll_10nm->phy_cmn_mmio;
 	u32 val;
+	int ret;
 
 	val = pll_read(pll_10nm->mmio + REG_DSI_10nm_PHY_PLL_PLL_OUTDIV_RATE);
 	val &= ~0x3;
@@ -567,6 +574,13 @@
 	val |= cached->pll_mux;
 	pll_write(phy_base + REG_DSI_10nm_PHY_CMN_CLK_CFG1, val);
 
+	ret = dsi_pll_10nm_vco_set_rate(&pll->clk_hw, pll_10nm->vco_current_rate, pll_10nm->vco_ref_clk_rate);
+	if (ret) {
+		DRM_DEV_ERROR(&pll_10nm->pdev->dev,
+			"restore vco rate failed. ret=%d\n", ret);
+		return ret;
+	}
+
 	DBG("DSI PLL%d", pll_10nm->id);
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/edp/edp_ctrl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/edp/edp_ctrl.c
@@ -1082,7 +1082,7 @@
 int msm_edp_ctrl_init(struct msm_edp *edp)
 {
 	struct edp_ctrl *ctrl = NULL;
-	struct device *dev = &edp->pdev->dev;
+	struct device *dev;
 	int ret;
 
 	if (!edp) {
@@ -1090,6 +1090,7 @@
 		return -EINVAL;
 	}
 
+	dev = &edp->pdev->dev;
 	ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
 	if (!ctrl)
 		return -ENOMEM;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -97,10 +97,15 @@
 
 	of_node_put(phy_node);
 
-	if (!phy_pdev || !hdmi->phy) {
+	if (!phy_pdev) {
 		DRM_DEV_ERROR(&pdev->dev, "phy driver is not ready\n");
 		return -EPROBE_DEFER;
 	}
+	if (!hdmi->phy) {
+		DRM_DEV_ERROR(&pdev->dev, "phy driver is not ready\n");
+		put_device(&phy_pdev->dev);
+		return -EPROBE_DEFER;
+	}
 
 	hdmi->phy_dev = get_device(&phy_pdev->dev);
 
@@ -137,6 +142,10 @@
 	/* HDCP needs physical address of hdmi register */
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 		config->mmio_name);
+	if (!res) {
+		ret = -EINVAL;
+		goto fail;
+	}
 	hdmi->mmio_phy_addr = res->start;
 
 	hdmi->qfprom_mmio = msm_ioremap(pdev,
@@ -239,6 +248,10 @@
 	pm_runtime_enable(&pdev->dev);
 
 	hdmi->workq = alloc_ordered_workqueue("msm_hdmi", 0);
+	if (!hdmi->workq) {
+		ret = -ENOMEM;
+		goto fail;
+	}
 
 	hdmi->i2c = msm_hdmi_i2c_init(hdmi);
 	if (IS_ERR(hdmi->i2c)) {
@@ -284,6 +297,11 @@
 	struct platform_device *pdev = hdmi->pdev;
 	int ret;
 
+	if (priv->num_bridges == ARRAY_SIZE(priv->bridges)) {
+		DRM_DEV_ERROR(dev->dev, "too many bridges\n");
+		return -ENOSPC;
+	}
+
 	hdmi->dev = dev;
 	hdmi->encoder = encoder;
 
@@ -306,9 +324,9 @@
 	}
 
 	hdmi->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
-	if (hdmi->irq < 0) {
-		ret = hdmi->irq;
-		DRM_DEV_ERROR(dev->dev, "failed to get irq: %d\n", ret);
+	if (!hdmi->irq) {
+		ret = -EINVAL;
+		DRM_DEV_ERROR(dev->dev, "failed to get irq\n");
 		goto fail;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/msm_atomic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/msm_atomic.c
@@ -27,6 +27,34 @@
 	return msm_framebuffer_prepare(new_state->fb, kms->aspace);
 }
 
+/*
+ * Helpers to control vblanks while we flush.. basically just to ensure
+ * that vblank accounting is switched on, so we get valid seqn/timestamp
+ * on pageflip events (if requested)
+ */
+
+static void vblank_get(struct msm_kms *kms, unsigned crtc_mask)
+{
+	struct drm_crtc *crtc;
+
+	for_each_crtc_mask(kms->dev, crtc, crtc_mask) {
+		if (!crtc->state->active)
+			continue;
+		drm_crtc_vblank_get(crtc);
+	}
+}
+
+static void vblank_put(struct msm_kms *kms, unsigned crtc_mask)
+{
+	struct drm_crtc *crtc;
+
+	for_each_crtc_mask(kms->dev, crtc, crtc_mask) {
+		if (!crtc->state->active)
+			continue;
+		drm_crtc_vblank_put(crtc);
+	}
+}
+
 static void msm_atomic_async_commit(struct msm_kms *kms, int crtc_idx)
 {
 	unsigned crtc_mask = BIT(crtc_idx);
@@ -44,6 +72,8 @@
 
 	kms->funcs->enable_commit(kms);
 
+	vblank_get(kms, crtc_mask);
+
 	/*
 	 * Flush hardware updates:
 	 */
@@ -58,6 +88,8 @@
 	kms->funcs->wait_flush(kms, crtc_mask);
 	trace_msm_atomic_wait_flush_finish(crtc_mask);
 
+	vblank_put(kms, crtc_mask);
+
 	mutex_lock(&kms->commit_lock);
 	kms->funcs->complete_commit(kms, crtc_mask);
 	mutex_unlock(&kms->commit_lock);
@@ -221,6 +253,8 @@
 	 */
 	kms->pending_crtc_mask &= ~crtc_mask;
 
+	vblank_get(kms, crtc_mask);
+
 	/*
 	 * Flush hardware updates:
 	 */
@@ -235,6 +269,8 @@
 	kms->funcs->wait_flush(kms, crtc_mask);
 	trace_msm_atomic_wait_flush_finish(crtc_mask);
 
+	vblank_put(kms, crtc_mask);
+
 	mutex_lock(&kms->commit_lock);
 	kms->funcs->complete_commit(kms, crtc_mask);
 	mutex_unlock(&kms->commit_lock);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/msm_debugfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/msm_debugfs.c
@@ -47,12 +47,8 @@
 	struct msm_gpu_show_priv *show_priv = m->private;
 	struct msm_drm_private *priv = show_priv->dev->dev_private;
 	struct msm_gpu *gpu = priv->gpu;
-	int ret;
-
-	ret = mutex_lock_interruptible(&show_priv->dev->struct_mutex);
-	if (ret)
-		return ret;
 
+	mutex_lock(&show_priv->dev->struct_mutex);
 	gpu->funcs->gpu_state_put(show_priv->state);
 	mutex_unlock(&show_priv->dev->struct_mutex);
 
@@ -81,6 +77,7 @@
 		goto free_priv;
 
 	pm_runtime_get_sync(&gpu->pdev->dev);
+	msm_gpu_hw_init(gpu);
 	show_priv->state = gpu->funcs->gpu_state_get(gpu);
 	pm_runtime_put_sync(&gpu->pdev->dev);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/msm_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/msm_drv.c
@@ -337,7 +337,7 @@
 		of_node_put(node);
 		if (ret)
 			return ret;
-		size = r.end - r.start;
+		size = r.end - r.start + 1;
 		DRM_INFO("using VRAM carveout: %lx@%pa\n", size, &r.start);
 
 		/* if we have no IOMMU, then we need to use carveout allocator.
@@ -432,14 +432,24 @@
 
 	drm_mode_config_init(ddev);
 
+	ret = msm_init_vram(ddev);
+	if (ret)
+		goto err_destroy_mdss;
+
 	/* Bind all our sub-components: */
 	ret = component_bind_all(dev, ddev);
 	if (ret)
 		goto err_destroy_mdss;
 
-	ret = msm_init_vram(ddev);
-	if (ret)
-		goto err_msm_uninit;
+	if (!dev->dma_parms) {
+		dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms),
+					      GFP_KERNEL);
+		if (!dev->dma_parms) {
+			ret = -ENOMEM;
+			goto err_msm_uninit;
+		}
+	}
+	dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
 
 	msm_gem_shrinker_init(ddev);
 
@@ -557,6 +567,7 @@
 	kfree(priv);
 err_put_drm_dev:
 	drm_dev_put(ddev);
+	platform_set_drvdata(pdev, NULL);
 	return ret;
 }
 
@@ -1313,6 +1324,17 @@
 	return 0;
 }
 
+static void msm_pdev_shutdown(struct platform_device *pdev)
+{
+	struct drm_device *drm = platform_get_drvdata(pdev);
+	struct msm_drm_private *priv = drm ? drm->dev_private : NULL;
+
+	if (!priv || !priv->kms)
+		return;
+
+	drm_atomic_helper_shutdown(drm);
+}
+
 static const struct of_device_id dt_match[] = {
 	{ .compatible = "qcom,mdp4", .data = (void *)KMS_MDP4 },
 	{ .compatible = "qcom,mdss", .data = (void *)KMS_MDP5 },
@@ -1324,6 +1346,7 @@
 static struct platform_driver msm_platform_driver = {
 	.probe      = msm_pdev_probe,
 	.remove     = msm_pdev_remove,
+	.shutdown   = msm_pdev_shutdown,
 	.driver     = {
 		.name   = "msm",
 		.of_match_table = dt_match,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/msm_fence.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/msm_fence.c
@@ -20,7 +20,7 @@
 		return ERR_PTR(-ENOMEM);
 
 	fctx->dev = dev;
-	strncpy(fctx->name, name, sizeof(fctx->name));
+	strscpy(fctx->name, name, sizeof(fctx->name));
 	fctx->context = dma_fence_context_alloc(1);
 	init_waitqueue_head(&fctx->event);
 	spin_lock_init(&fctx->spinlock);
@@ -45,7 +45,7 @@
 	int ret;
 
 	if (fence > fctx->last_fence) {
-		DRM_ERROR("%s: waiting on invalid fence: %u (of %u)\n",
+		DRM_ERROR_RATELIMITED("%s: waiting on invalid fence: %u (of %u)\n",
 				fctx->name, fence, fctx->last_fence);
 		return -EINVAL;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/msm_gem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/msm_gem.c
@@ -977,10 +977,8 @@
 
 static int msm_gem_new_impl(struct drm_device *dev,
 		uint32_t size, uint32_t flags,
-		struct drm_gem_object **obj,
-		bool struct_mutex_locked)
+		struct drm_gem_object **obj)
 {
-	struct msm_drm_private *priv = dev->dev_private;
 	struct msm_gem_object *msm_obj;
 
 	switch (flags & MSM_BO_CACHE_MASK) {
@@ -1006,15 +1004,6 @@
 	INIT_LIST_HEAD(&msm_obj->submit_entry);
 	INIT_LIST_HEAD(&msm_obj->vmas);
 
-	if (struct_mutex_locked) {
-		WARN_ON(!mutex_is_locked(&dev->struct_mutex));
-		list_add_tail(&msm_obj->mm_list, &priv->inactive_list);
-	} else {
-		mutex_lock(&dev->struct_mutex);
-		list_add_tail(&msm_obj->mm_list, &priv->inactive_list);
-		mutex_unlock(&dev->struct_mutex);
-	}
-
 	*obj = &msm_obj->base;
 
 	return 0;
@@ -1024,6 +1013,7 @@
 		uint32_t size, uint32_t flags, bool struct_mutex_locked)
 {
 	struct msm_drm_private *priv = dev->dev_private;
+	struct msm_gem_object *msm_obj;
 	struct drm_gem_object *obj = NULL;
 	bool use_vram = false;
 	int ret;
@@ -1044,14 +1034,15 @@
 	if (size == 0)
 		return ERR_PTR(-EINVAL);
 
-	ret = msm_gem_new_impl(dev, size, flags, &obj, struct_mutex_locked);
+	ret = msm_gem_new_impl(dev, size, flags, &obj);
 	if (ret)
-		goto fail;
+		return ERR_PTR(ret);
+
+	msm_obj = to_msm_bo(obj);
 
 	if (use_vram) {
 		struct msm_gem_vma *vma;
 		struct page **pages;
-		struct msm_gem_object *msm_obj = to_msm_bo(obj);
 
 		mutex_lock(&msm_obj->lock);
 
@@ -1086,6 +1077,15 @@
 		mapping_set_gfp_mask(obj->filp->f_mapping, GFP_HIGHUSER);
 	}
 
+	if (struct_mutex_locked) {
+		WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+		list_add_tail(&msm_obj->mm_list, &priv->inactive_list);
+	} else {
+		mutex_lock(&dev->struct_mutex);
+		list_add_tail(&msm_obj->mm_list, &priv->inactive_list);
+		mutex_unlock(&dev->struct_mutex);
+	}
+
 	return obj;
 
 fail:
@@ -1108,6 +1108,7 @@
 struct drm_gem_object *msm_gem_import(struct drm_device *dev,
 		struct dma_buf *dmabuf, struct sg_table *sgt)
 {
+	struct msm_drm_private *priv = dev->dev_private;
 	struct msm_gem_object *msm_obj;
 	struct drm_gem_object *obj;
 	uint32_t size;
@@ -1121,9 +1122,9 @@
 
 	size = PAGE_ALIGN(dmabuf->size);
 
-	ret = msm_gem_new_impl(dev, size, MSM_BO_WC, &obj, false);
+	ret = msm_gem_new_impl(dev, size, MSM_BO_WC, &obj);
 	if (ret)
-		goto fail;
+		return ERR_PTR(ret);
 
 	drm_gem_private_object_init(dev, obj, size);
 
@@ -1146,6 +1147,11 @@
 	}
 
 	mutex_unlock(&msm_obj->lock);
+
+	mutex_lock(&dev->struct_mutex);
+	list_add_tail(&msm_obj->mm_list, &priv->inactive_list);
+	mutex_unlock(&dev->struct_mutex);
+
 	return obj;
 
 fail:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/msm_gem_prime.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/msm_gem_prime.c
@@ -17,7 +17,7 @@
 	int npages = obj->size >> PAGE_SHIFT;
 
 	if (WARN_ON(!msm_obj->pages))  /* should have already pinned! */
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 
 	return drm_prime_pages_to_sg(msm_obj->pages, npages);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/msm_gpu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/msm_gpu.c
@@ -16,6 +16,7 @@
 #include <linux/pm_opp.h>
 #include <linux/devfreq.h>
 #include <linux/devcoredump.h>
+#include <linux/sched/task.h>
 
 /*
  * Power Management:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/msm_rd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/msm_rd.c
@@ -191,6 +191,9 @@
 	file->private_data = rd;
 	rd->open = true;
 
+	/* Reset fifo to clear any previously unread data: */
+	rd->fifo.head = rd->fifo.tail = 0;
+
 	/* the parsing tools need to know gpu-id to know which
 	 * register database to load.
 	 */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/msm_ringbuffer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/msm_ringbuffer.c
@@ -27,7 +27,8 @@
 	ring->id = id;
 
 	ring->start = msm_gem_kernel_new(gpu->dev, MSM_GPU_RINGBUFFER_SZ,
-		MSM_BO_WC, gpu->aspace, &ring->bo, &ring->iova);
+		MSM_BO_WC | MSM_BO_GPU_READONLY, gpu->aspace, &ring->bo,
+		&ring->iova);
 
 	if (IS_ERR(ring->start)) {
 		ret = PTR_ERR(ring->start);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/msm/msm_submitqueue.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/msm/msm_submitqueue.c
@@ -71,8 +71,10 @@
 	queue->flags = flags;
 
 	if (priv->gpu) {
-		if (prio >= priv->gpu->nr_rings)
+		if (prio >= priv->gpu->nr_rings) {
+			kfree(queue);
 			return -EINVAL;
+		}
 
 		queue->prio = prio;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/mxsfb/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/mxsfb/Kconfig
@@ -8,9 +8,9 @@
 	tristate "i.MX23/i.MX28/i.MX6SX MXSFB LCD controller"
 	depends on DRM && OF
 	depends on COMMON_CLK
+	depends on ARCH_MXS || ARCH_MXC || COMPILE_TEST
 	select DRM_MXS
 	select DRM_KMS_HELPER
-	select DRM_KMS_FB_HELPER
 	select DRM_KMS_CMA_HELPER
 	select DRM_PANEL
 	help
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -26,6 +26,7 @@
 #include <drm/drm_drv.h>
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fb_helper.h>
+#include <drm/drm_fourcc.h>
 #include <drm/drm_gem_cma_helper.h>
 #include <drm/drm_gem_framebuffer_helper.h>
 #include <drm/drm_irq.h>
@@ -87,8 +88,26 @@
 		clk_disable_unprepare(mxsfb->clk_axi);
 }
 
+static struct drm_framebuffer *
+mxsfb_fb_create(struct drm_device *dev, struct drm_file *file_priv,
+		const struct drm_mode_fb_cmd2 *mode_cmd)
+{
+	const struct drm_format_info *info;
+
+	info = drm_get_format_info(dev, mode_cmd);
+	if (!info)
+		return ERR_PTR(-EINVAL);
+
+	if (mode_cmd->width * info->cpp[0] != mode_cmd->pitches[0]) {
+		dev_dbg(dev->dev, "Invalid pitch: fb width must match pitch\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	return drm_gem_fb_create(dev, file_priv, mode_cmd);
+}
+
 static const struct drm_mode_config_funcs mxsfb_mode_config_funcs = {
-	.fb_create		= drm_gem_fb_create,
+	.fb_create		= mxsfb_fb_create,
 	.atomic_check		= drm_atomic_helper_check,
 	.atomic_commit		= drm_atomic_helper_commit,
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/dispnv04/disp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/dispnv04/disp.c
@@ -179,7 +179,7 @@
 	nvif_notify_fini(&disp->flip);
 
 	nouveau_display(dev)->priv = NULL;
-	kfree(disp);
+	vfree(disp);
 
 	nvif_object_unmap(&drm->client.device.object);
 }
@@ -197,7 +197,7 @@
 	struct nv04_display *disp;
 	int i, ret;
 
-	disp = kzalloc(sizeof(*disp), GFP_KERNEL);
+	disp = vzalloc(sizeof(*disp));
 	if (!disp)
 		return -ENOMEM;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
@@ -208,6 +208,8 @@
 		struct drm_display_mode *mode;
 
 		mode = drm_mode_duplicate(encoder->dev, tv_mode);
+		if (!mode)
+			continue;
 
 		mode->clock = tv_norm->tv_enc_mode.vrefresh *
 			mode->htotal / 1000 *
@@ -257,6 +259,8 @@
 		if (modes[i].hdisplay == output_mode->hdisplay &&
 		    modes[i].vdisplay == output_mode->vdisplay) {
 			mode = drm_mode_duplicate(encoder->dev, output_mode);
+			if (!mode)
+				continue;
 			mode->type |= DRM_MODE_TYPE_PREFERRED;
 
 		} else {
@@ -264,6 +268,8 @@
 					    modes[i].vdisplay, 60, false,
 					    (output_mode->flags &
 					     DRM_MODE_FLAG_INTERLACE), false);
+			if (!mode)
+				continue;
 		}
 
 		/* CVT modes are sometimes unsuitable... */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/dispnv50/atom.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/dispnv50/atom.h
@@ -114,6 +114,7 @@
 		u8 nhsync:1;
 		u8 nvsync:1;
 		u8 depth:4;
+		u8 bpc;
 	} or;
 
 	/* Currently only used for MST */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/dispnv50/core.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/dispnv50/core.h
@@ -6,6 +6,7 @@
 struct nv50_core {
 	const struct nv50_core_func *func;
 	struct nv50_dmac chan;
+	bool assign_windows;
 };
 
 int nv50_core_new(struct nouveau_drm *, struct nv50_core **);
@@ -18,6 +19,10 @@
 			      struct nvif_device *);
 	void (*update)(struct nv50_core *, u32 *interlock, bool ntfy);
 
+	struct {
+		void (*owner)(struct nv50_core *);
+	} wndw;
+
 	const struct nv50_head_func *head;
 	const struct nv50_outp_func {
 		void (*ctrl)(struct nv50_core *, int or, u32 ctrl,
@@ -48,6 +53,7 @@
 int corec37d_new(struct nouveau_drm *, s32, struct nv50_core **);
 int corec37d_ntfy_wait_done(struct nouveau_bo *, u32, struct nvif_device *);
 void corec37d_update(struct nv50_core *, u32 *, bool);
+void corec37d_wndw_owner(struct nv50_core *);
 extern const struct nv50_outp_func sorc37d;
 
 int corec57d_new(struct nouveau_drm *, s32, struct nv50_core **);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/dispnv50/corec37d.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/dispnv50/corec37d.c
@@ -25,6 +25,20 @@
 #include <nouveau_bo.h>
 
 void
+corec37d_wndw_owner(struct nv50_core *core)
+{
+	const u32 windows = 8; /*XXX*/
+	u32 *push, i;
+	if ((push = evo_wait(&core->chan, 2 * windows))) {
+		for (i = 0; i < windows; i++) {
+			evo_mthd(push, 0x1000 + (i * 0x080), 1);
+			evo_data(push, i >> 1);
+		}
+		evo_kick(push, &core->chan);
+	}
+}
+
+void
 corec37d_update(struct nv50_core *core, u32 *interlock, bool ntfy)
 {
 	u32 *push;
@@ -76,20 +90,18 @@
 {
 	const u32 windows = 8; /*XXX*/
 	u32 *push, i;
-	if ((push = evo_wait(&core->chan, 2 + 6 * windows + 2))) {
+	if ((push = evo_wait(&core->chan, 2 + 5 * windows))) {
 		evo_mthd(push, 0x0208, 1);
 		evo_data(push, core->chan.sync.handle);
 		for (i = 0; i < windows; i++) {
-			evo_mthd(push, 0x1000 + (i * 0x080), 3);
-			evo_data(push, i >> 1);
+			evo_mthd(push, 0x1004 + (i * 0x080), 2);
 			evo_data(push, 0x0000001f);
 			evo_data(push, 0x00000000);
 			evo_mthd(push, 0x1010 + (i * 0x080), 1);
 			evo_data(push, 0x00127fff);
 		}
-		evo_mthd(push, 0x0200, 1);
-		evo_data(push, 0x00000001);
 		evo_kick(push, &core->chan);
+		core->assign_windows = true;
 	}
 }
 
@@ -99,6 +111,7 @@
 	.ntfy_init = corec37d_ntfy_init,
 	.ntfy_wait_done = corec37d_ntfy_wait_done,
 	.update = corec37d_update,
+	.wndw.owner = corec37d_wndw_owner,
 	.head = &headc37d,
 	.sor = &sorc37d,
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/dispnv50/corec57d.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/dispnv50/corec57d.c
@@ -27,20 +27,18 @@
 {
 	const u32 windows = 8; /*XXX*/
 	u32 *push, i;
-	if ((push = evo_wait(&core->chan, 2 + 6 * windows + 2))) {
+	if ((push = evo_wait(&core->chan, 2 + 5 * windows))) {
 		evo_mthd(push, 0x0208, 1);
 		evo_data(push, core->chan.sync.handle);
 		for (i = 0; i < windows; i++) {
-			evo_mthd(push, 0x1000 + (i * 0x080), 3);
-			evo_data(push, i >> 1);
+			evo_mthd(push, 0x1004 + (i * 0x080), 2);
 			evo_data(push, 0x0000000f);
 			evo_data(push, 0x00000000);
 			evo_mthd(push, 0x1010 + (i * 0x080), 1);
 			evo_data(push, 0x00117fff);
 		}
-		evo_mthd(push, 0x0200, 1);
-		evo_data(push, 0x00000001);
 		evo_kick(push, &core->chan);
+		core->assign_windows = true;
 	}
 }
 
@@ -50,6 +48,7 @@
 	.ntfy_init = corec37d_ntfy_init,
 	.ntfy_wait_done = corec37d_ntfy_wait_done,
 	.update = corec37d_update,
+	.wndw.owner = corec37d_wndw_owner,
 	.head = &headc57d,
 	.sor = &sorc37d,
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -132,7 +132,7 @@
 
 int
 nv50_dmac_create(struct nvif_device *device, struct nvif_object *disp,
-		 const s32 *oclass, u8 head, void *data, u32 size, u64 syncbuf,
+		 const s32 *oclass, u8 head, void *data, u32 size, s64 syncbuf,
 		 struct nv50_dmac *dmac)
 {
 	struct nouveau_cli *cli = (void *)device->object.client;
@@ -167,7 +167,7 @@
 	if (ret)
 		return ret;
 
-	if (!syncbuf)
+	if (syncbuf < 0)
 		return 0;
 
 	ret = nvif_object_init(&dmac->base.user, 0xf0000000, NV_DMA_IN_MEMORY,
@@ -326,9 +326,9 @@
 			 * same size as the native one (e.g. different
 			 * refresh rate)
 			 */
-			if (adjusted_mode->hdisplay == native_mode->hdisplay &&
-			    adjusted_mode->vdisplay == native_mode->vdisplay &&
-			    adjusted_mode->type & DRM_MODE_TYPE_DRIVER)
+			if (mode->hdisplay == native_mode->hdisplay &&
+			    mode->vdisplay == native_mode->vdisplay &&
+			    mode->type & DRM_MODE_TYPE_DRIVER)
 				break;
 			mode = native_mode;
 			asyc->scaler.full = true;
@@ -353,10 +353,20 @@
 		       struct drm_crtc_state *crtc_state,
 		       struct drm_connector_state *conn_state)
 {
-	struct nouveau_connector *nv_connector =
-		nouveau_connector(conn_state->connector);
-	return nv50_outp_atomic_check_view(encoder, crtc_state, conn_state,
-					   nv_connector->native_mode);
+	struct drm_connector *connector = conn_state->connector;
+	struct nouveau_connector *nv_connector = nouveau_connector(connector);
+	struct nv50_head_atom *asyh = nv50_head_atom(crtc_state);
+	int ret;
+
+	ret = nv50_outp_atomic_check_view(encoder, crtc_state, conn_state,
+					  nv_connector->native_mode);
+	if (ret)
+		return ret;
+
+	if (crtc_state->mode_changed || crtc_state->connectors_changed)
+		asyh->or.bpc = connector->display_info.bpc;
+
+	return 0;
 }
 
 /******************************************************************************
@@ -770,32 +780,54 @@
 	struct nv50_mstm *mstm = mstc->mstm;
 	struct nv50_head_atom *asyh = nv50_head_atom(crtc_state);
 	int slots;
+	int ret;
+
+	ret = nv50_outp_atomic_check_view(encoder, crtc_state, conn_state,
+					  mstc->native);
+	if (ret)
+		return ret;
+
+	if (!crtc_state->mode_changed && !crtc_state->connectors_changed)
+		return 0;
+
+	/*
+	 * When restoring duplicated states, we need to make sure that the bw
+	 * remains the same and avoid recalculating it, as the connector's bpc
+	 * may have changed after the state was duplicated
+	 */
+	if (!state->duplicated) {
+		const int clock = crtc_state->adjusted_mode.clock;
 
-	if (crtc_state->mode_changed || crtc_state->connectors_changed) {
 		/*
-		 * When restoring duplicated states, we need to make sure that
-		 * the bw remains the same and avoid recalculating it, as the
-		 * connector's bpc may have changed after the state was
-		 * duplicated
+		 * XXX: Since we don't use HDR in userspace quite yet, limit
+		 * the bpc to 8 to save bandwidth on the topology. In the
+		 * future, we'll want to properly fix this by dynamically
+		 * selecting the highest possible bpc that would fit in the
+		 * topology
 		 */
-		if (!state->duplicated) {
-			const int bpp = connector->display_info.bpc * 3;
-			const int clock = crtc_state->adjusted_mode.clock;
+		asyh->or.bpc = min(connector->display_info.bpc, 8U);
+		asyh->dp.pbn = drm_dp_calc_pbn_mode(clock, asyh->or.bpc * 3);
+	}
 
-			asyh->dp.pbn = drm_dp_calc_pbn_mode(clock, bpp);
-		}
+	slots = drm_dp_atomic_find_vcpi_slots(state, &mstm->mgr, mstc->port,
+					      asyh->dp.pbn);
+	if (slots < 0)
+		return slots;
 
-		slots = drm_dp_atomic_find_vcpi_slots(state, &mstm->mgr,
-						      mstc->port,
-						      asyh->dp.pbn);
-		if (slots < 0)
-			return slots;
+	asyh->dp.tu = slots;
 
-		asyh->dp.tu = slots;
-	}
+	return 0;
+}
 
-	return nv50_outp_atomic_check_view(encoder, crtc_state, conn_state,
-					   mstc->native);
+static u8
+nv50_dp_bpc_to_depth(unsigned int bpc)
+{
+	switch (bpc) {
+	case  6: return 0x2;
+	case  8: return 0x5;
+	case 10: /* fall-through */
+	default: return 0x6;
+	}
 }
 
 static void
@@ -808,7 +840,7 @@
 	struct nv50_mstm *mstm = NULL;
 	struct drm_connector *connector;
 	struct drm_connector_list_iter conn_iter;
-	u8 proto, depth;
+	u8 proto;
 	bool r;
 
 	drm_connector_list_iter_begin(encoder->dev, &conn_iter);
@@ -837,14 +869,8 @@
 	else
 		proto = 0x9;
 
-	switch (mstc->connector.display_info.bpc) {
-	case  6: depth = 0x2; break;
-	case  8: depth = 0x5; break;
-	case 10:
-	default: depth = 0x6; break;
-	}
-
-	mstm->outp->update(mstm->outp, head->base.index, armh, proto, depth);
+	mstm->outp->update(mstm->outp, head->base.index, armh, proto,
+			   nv50_dp_bpc_to_depth(armh->or.bpc));
 
 	msto->head = head;
 	msto->mstc = mstc;
@@ -1006,8 +1032,10 @@
 		return connector_status_disconnected;
 
 	ret = pm_runtime_get_sync(connector->dev->dev);
-	if (ret < 0 && ret != -EACCES)
+	if (ret < 0 && ret != -EACCES) {
+		pm_runtime_put_autosuspend(connector->dev->dev);
 		return connector_status_disconnected;
+	}
 
 	conn_status = drm_dp_mst_detect_port(connector, mstc->port->mgr,
 					     mstc->port);
@@ -1498,20 +1526,14 @@
 					lvds.lvds.script |= 0x0200;
 			}
 
-			if (nv_connector->base.display_info.bpc == 8)
+			if (asyh->or.bpc == 8)
 				lvds.lvds.script |= 0x0200;
 		}
 
 		nvif_mthd(&disp->disp->object, 0, &lvds, sizeof(lvds));
 		break;
 	case DCB_OUTPUT_DP:
-		if (nv_connector->base.display_info.bpc == 6)
-			depth = 0x2;
-		else
-		if (nv_connector->base.display_info.bpc == 8)
-			depth = 0x5;
-		else
-			depth = 0x6;
+		depth = nv50_dp_bpc_to_depth(asyh->or.bpc);
 
 		if (nv_encoder->link & 1)
 			proto = 0x8;
@@ -1662,7 +1684,7 @@
 	nv50_outp_acquire(nv_encoder);
 
 	nv_connector = nouveau_encoder_connector_get(nv_encoder);
-	switch (nv_connector->base.display_info.bpc) {
+	switch (asyh->or.bpc) {
 	case 10: asyh->or.depth = 0x6; break;
 	case  8: asyh->or.depth = 0x5; break;
 	case  6: asyh->or.depth = 0x2; break;
@@ -1812,6 +1834,7 @@
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	struct nv50_disp *disp = nv50_disp(dev);
 	struct nv50_atom *atom = nv50_atom(state);
+	struct nv50_core *core = disp->core;
 	struct nv50_outp_atom *outp, *outt;
 	u32 interlock[NV50_DISP_INTERLOCK__SIZE] = {};
 	int i;
@@ -1930,6 +1953,21 @@
 		}
 	}
 
+	/* Update window->head assignment.
+	 *
+	 * This has to happen in an update that's not interlocked with
+	 * any window channels to avoid hitting HW error checks.
+	 *
+	 *TODO: Proper handling of window ownership (Turing apparently
+	 *      supports non-fixed mappings).
+	 */
+	if (core->assign_windows) {
+		core->func->wndw.owner(core);
+		core->func->update(core, interlock, false);
+		core->assign_windows = false;
+		interlock[NV50_DISP_INTERLOCK_CORE] = 0;
+	}
+
 	/* Update plane(s). */
 	for_each_new_plane_in_state(state, plane, new_plane_state, i) {
 		struct nv50_wndw_atom *asyw = nv50_wndw_atom(new_plane_state);
@@ -2012,8 +2050,10 @@
 	int ret, i;
 
 	ret = pm_runtime_get_sync(dev->dev);
-	if (ret < 0 && ret != -EACCES)
+	if (ret < 0 && ret != -EACCES) {
+		pm_runtime_put_autosuspend(dev->dev);
 		return ret;
+	}
 
 	ret = drm_atomic_helper_setup_commit(state, nonblock);
 	if (ret)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/dispnv50/disp.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/dispnv50/disp.h
@@ -70,7 +70,7 @@
 
 int nv50_dmac_create(struct nvif_device *device, struct nvif_object *disp,
 		     const s32 *oclass, u8 head, void *data, u32 size,
-		     u64 syncbuf, struct nv50_dmac *dmac);
+		     s64 syncbuf, struct nv50_dmac *dmac);
 void nv50_dmac_destroy(struct nv50_dmac *);
 
 u32 *evo_wait(struct nv50_dmac *, int nr);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/dispnv50/head.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/dispnv50/head.c
@@ -81,21 +81,22 @@
 			      struct nv50_head_atom *asyh,
 			      struct nouveau_conn_atom *asyc)
 {
-	struct drm_connector *connector = asyc->state.connector;
 	u32 mode = 0x00;
 
-	if (asyc->dither.mode == DITHERING_MODE_AUTO) {
-		if (asyh->base.depth > connector->display_info.bpc * 3)
-			mode = DITHERING_MODE_DYNAMIC2X2;
-	} else {
-		mode = asyc->dither.mode;
-	}
+	if (asyc->dither.mode) {
+		if (asyc->dither.mode == DITHERING_MODE_AUTO) {
+			if (asyh->base.depth > asyh->or.bpc * 3)
+				mode = DITHERING_MODE_DYNAMIC2X2;
+		} else {
+			mode = asyc->dither.mode;
+		}
 
-	if (asyc->dither.depth == DITHERING_DEPTH_AUTO) {
-		if (connector->display_info.bpc >= 8)
-			mode |= DITHERING_DEPTH_8BPC;
-	} else {
-		mode |= asyc->dither.depth;
+		if (asyc->dither.depth == DITHERING_DEPTH_AUTO) {
+			if (asyh->or.bpc >= 8)
+				mode |= DITHERING_DEPTH_8BPC;
+		} else {
+			mode |= asyc->dither.depth;
+		}
 	}
 
 	asyh->dither.enable = mode;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/dispnv50/wimmc37b.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/dispnv50/wimmc37b.c
@@ -68,7 +68,7 @@
 	int ret;
 
 	ret = nv50_dmac_create(&drm->client.device, &disp->disp->object,
-			       &oclass, 0, &args, sizeof(args), 0,
+			       &oclass, 0, &args, sizeof(args), -1,
 			       &wndw->wimm);
 	if (ret) {
 		NV_ERROR(drm, "wimm%04x allocation failed: %d\n", oclass, ret);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/dispnv50/wndw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/dispnv50/wndw.c
@@ -451,6 +451,8 @@
 		asyw->clr.ntfy = armw->ntfy.handle != 0;
 		asyw->clr.sema = armw->sema.handle != 0;
 		asyw->clr.xlut = armw->xlut.handle != 0;
+		if (asyw->clr.xlut && asyw->visible)
+			asyw->set.xlut = asyw->xlut.handle != 0;
 		asyw->clr.csc  = armw->csc.valid;
 		if (wndw->func->image_clr)
 			asyw->clr.image = armw->image.handle[0] != 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/conn.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/conn.h
@@ -14,6 +14,7 @@
 	DCB_CONNECTOR_LVDS_SPWG = 0x41,
 	DCB_CONNECTOR_DP = 0x46,
 	DCB_CONNECTOR_eDP = 0x47,
+	DCB_CONNECTOR_mDP = 0x48,
 	DCB_CONNECTOR_HDMI_0 = 0x60,
 	DCB_CONNECTOR_HDMI_1 = 0x61,
 	DCB_CONNECTOR_HDMI_C = 0x63,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nouveau_backlight.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nouveau_backlight.c
@@ -51,8 +51,9 @@
 nouveau_get_backlight_name(char backlight_name[BL_NAME_SIZE],
 			   struct nouveau_backlight *bl)
 {
-	const int nb = ida_simple_get(&bl_ida, 0, 0, GFP_KERNEL);
-	if (nb < 0 || nb >= 100)
+	const int nb = ida_alloc_max(&bl_ida, 99, GFP_KERNEL);
+
+	if (nb < 0)
 		return false;
 	if (nb > 0)
 		snprintf(backlight_name, BL_NAME_SIZE, "nv_backlight%d", nb);
@@ -280,7 +281,7 @@
 					    nv_encoder, ops, &props);
 	if (IS_ERR(bl->dev)) {
 		if (bl->id >= 0)
-			ida_simple_remove(&bl_ida, bl->id);
+			ida_free(&bl_ida, bl->id);
 		ret = PTR_ERR(bl->dev);
 		goto fail_alloc;
 	}
@@ -306,7 +307,7 @@
 		return;
 
 	if (bl->id >= 0)
-		ida_simple_remove(&bl_ida, bl->id);
+		ida_free(&bl_ida, bl->id);
 
 	backlight_device_unregister(bl->dev);
 	nv_conn->backlight = NULL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nouveau_bios.c
@@ -23,6 +23,7 @@
  */
 
 #include "nouveau_drv.h"
+#include "nouveau_bios.h"
 #include "nouveau_reg.h"
 #include "dispnv04/hw.h"
 #include "nouveau_encoder.h"
@@ -1672,7 +1673,7 @@
 	 */
 	if (nv_match_device(dev, 0x0201, 0x1462, 0x8851)) {
 		if (*conn == 0xf2005014 && *conf == 0xffffffff) {
-			fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 1, 1, 1);
+			fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 1, 1, DCB_OUTPUT_B);
 			return false;
 		}
 	}
@@ -1758,26 +1759,26 @@
 #ifdef __powerpc__
 	/* Apple iMac G4 NV17 */
 	if (of_machine_is_compatible("PowerMac4,5")) {
-		fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 0, all_heads, 1);
-		fabricate_dcb_output(dcb, DCB_OUTPUT_ANALOG, 1, all_heads, 2);
+		fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 0, all_heads, DCB_OUTPUT_B);
+		fabricate_dcb_output(dcb, DCB_OUTPUT_ANALOG, 1, all_heads, DCB_OUTPUT_C);
 		return;
 	}
 #endif
 
 	/* Make up some sane defaults */
 	fabricate_dcb_output(dcb, DCB_OUTPUT_ANALOG,
-			     bios->legacy.i2c_indices.crt, 1, 1);
+			     bios->legacy.i2c_indices.crt, 1, DCB_OUTPUT_B);
 
 	if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0)
 		fabricate_dcb_output(dcb, DCB_OUTPUT_TV,
 				     bios->legacy.i2c_indices.tv,
-				     all_heads, 0);
+				     all_heads, DCB_OUTPUT_A);
 
 	else if (bios->tmds.output0_script_ptr ||
 		 bios->tmds.output1_script_ptr)
 		fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS,
 				     bios->legacy.i2c_indices.panel,
-				     all_heads, 1);
+				     all_heads, DCB_OUTPUT_B);
 }
 
 static int
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -276,8 +276,10 @@
 			break;
 	}
 
-	if (WARN_ON(pi < 0))
+	if (WARN_ON(pi < 0)) {
+		kfree(nvbo);
 		return ERR_PTR(-EINVAL);
+	}
 
 	/* Disable compression if suitable settings couldn't be found. */
 	if (nvbo->comp && !vmm->page[pi].comp) {
@@ -542,7 +544,7 @@
 	struct ttm_dma_tt *ttm_dma = (struct ttm_dma_tt *)nvbo->bo.ttm;
 	int i;
 
-	if (!ttm_dma)
+	if (!ttm_dma || !ttm_dma->dma_address)
 		return;
 
 	/* Don't waste time looping if the object is coherent */
@@ -562,7 +564,7 @@
 	struct ttm_dma_tt *ttm_dma = (struct ttm_dma_tt *)nvbo->bo.ttm;
 	int i;
 
-	if (!ttm_dma)
+	if (!ttm_dma || !ttm_dma->dma_address)
 		return;
 
 	/* Don't waste time looping if the object is coherent */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nouveau_chan.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nouveau_chan.c
@@ -497,6 +497,7 @@
 	if (ret) {
 		NV_PRINTK(err, cli, "channel failed to initialise, %d\n", ret);
 		nouveau_channel_del(pchan);
+		goto done;
 	}
 
 	ret = nouveau_svmm_join((*pchan)->vmm->svmm, (*pchan)->inst);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -245,14 +245,22 @@
 void
 nouveau_conn_reset(struct drm_connector *connector)
 {
+	struct nouveau_connector *nv_connector = nouveau_connector(connector);
 	struct nouveau_conn_atom *asyc;
 
-	if (WARN_ON(!(asyc = kzalloc(sizeof(*asyc), GFP_KERNEL))))
-		return;
+	if (drm_drv_uses_atomic_modeset(connector->dev)) {
+		if (WARN_ON(!(asyc = kzalloc(sizeof(*asyc), GFP_KERNEL))))
+			return;
+
+		if (connector->state)
+			nouveau_conn_atomic_destroy_state(connector,
+							  connector->state);
+
+		__drm_atomic_helper_connector_reset(connector, &asyc->state);
+	} else {
+		asyc = &nv_connector->properties_state;
+	}
 
-	if (connector->state)
-		nouveau_conn_atomic_destroy_state(connector, connector->state);
-	__drm_atomic_helper_connector_reset(connector, &asyc->state);
 	asyc->dither.mode = DITHERING_MODE_AUTO;
 	asyc->dither.depth = DITHERING_DEPTH_AUTO;
 	asyc->scaler.mode = DRM_MODE_SCALE_NONE;
@@ -276,8 +284,14 @@
 nouveau_conn_attach_properties(struct drm_connector *connector)
 {
 	struct drm_device *dev = connector->dev;
-	struct nouveau_conn_atom *armc = nouveau_conn_atom(connector->state);
 	struct nouveau_display *disp = nouveau_display(dev);
+	struct nouveau_connector *nv_connector = nouveau_connector(connector);
+	struct nouveau_conn_atom *armc;
+
+	if (drm_drv_uses_atomic_modeset(connector->dev))
+		armc = nouveau_conn_atom(connector->state);
+	else
+		armc = &nv_connector->properties_state;
 
 	/* Init DVI-I specific properties. */
 	if (connector->connector_type == DRM_MODE_CONNECTOR_DVII)
@@ -524,6 +538,19 @@
 	}
 }
 
+static void
+nouveau_connector_set_edid(struct nouveau_connector *nv_connector,
+			   struct edid *edid)
+{
+	if (nv_connector->edid != edid) {
+		struct edid *old_edid = nv_connector->edid;
+
+		drm_connector_update_edid_property(&nv_connector->base, edid);
+		kfree(old_edid);
+		nv_connector->edid = edid;
+	}
+}
+
 static enum drm_connector_status
 nouveau_connector_detect(struct drm_connector *connector, bool force)
 {
@@ -537,13 +564,6 @@
 	int ret;
 	enum drm_connector_status conn_status = connector_status_disconnected;
 
-	/* Cleanup the previous EDID block. */
-	if (nv_connector->edid) {
-		drm_connector_update_edid_property(connector, NULL);
-		kfree(nv_connector->edid);
-		nv_connector->edid = NULL;
-	}
-
 	/* Outputs are only polled while runtime active, so resuming the
 	 * device here is unnecessary (and would deadlock upon runtime suspend
 	 * because it waits for polling to finish). We do however, want to
@@ -554,22 +574,25 @@
 		pm_runtime_get_noresume(dev->dev);
 	} else {
 		ret = pm_runtime_get_sync(dev->dev);
-		if (ret < 0 && ret != -EACCES)
+		if (ret < 0 && ret != -EACCES) {
+			pm_runtime_put_autosuspend(dev->dev);
+			nouveau_connector_set_edid(nv_connector, NULL);
 			return conn_status;
+		}
 	}
 
 	nv_encoder = nouveau_connector_ddc_detect(connector);
 	if (nv_encoder && (i2c = nv_encoder->i2c) != NULL) {
+		struct edid *new_edid;
+
 		if ((vga_switcheroo_handler_flags() &
 		     VGA_SWITCHEROO_CAN_SWITCH_DDC) &&
 		    nv_connector->type == DCB_CONNECTOR_LVDS)
-			nv_connector->edid = drm_get_edid_switcheroo(connector,
-								     i2c);
+			new_edid = drm_get_edid_switcheroo(connector, i2c);
 		else
-			nv_connector->edid = drm_get_edid(connector, i2c);
+			new_edid = drm_get_edid(connector, i2c);
 
-		drm_connector_update_edid_property(connector,
-							nv_connector->edid);
+		nouveau_connector_set_edid(nv_connector, new_edid);
 		if (!nv_connector->edid) {
 			NV_ERROR(drm, "DDC responded, but no EDID for %s\n",
 				 connector->name);
@@ -603,6 +626,8 @@
 		conn_status = connector_status_connected;
 		drm_dp_cec_set_edid(&nv_connector->aux, nv_connector->edid);
 		goto out;
+	} else {
+		nouveau_connector_set_edid(nv_connector, NULL);
 	}
 
 	nv_encoder = nouveau_connector_of_detect(connector);
@@ -645,24 +670,20 @@
 	struct nouveau_drm *drm = nouveau_drm(dev);
 	struct nouveau_connector *nv_connector = nouveau_connector(connector);
 	struct nouveau_encoder *nv_encoder = NULL;
+	struct edid *edid = NULL;
 	enum drm_connector_status status = connector_status_disconnected;
 
-	/* Cleanup the previous EDID block. */
-	if (nv_connector->edid) {
-		drm_connector_update_edid_property(connector, NULL);
-		kfree(nv_connector->edid);
-		nv_connector->edid = NULL;
-	}
-
 	nv_encoder = find_encoder(connector, DCB_OUTPUT_LVDS);
 	if (!nv_encoder)
-		return connector_status_disconnected;
+		goto out;
 
 	/* Try retrieving EDID via DDC */
 	if (!drm->vbios.fp_no_ddc) {
 		status = nouveau_connector_detect(connector, force);
-		if (status == connector_status_connected)
+		if (status == connector_status_connected) {
+			edid = nv_connector->edid;
 			goto out;
+		}
 	}
 
 	/* On some laptops (Sony, i'm looking at you) there appears to
@@ -675,7 +696,8 @@
 	 * valid - it's not (rh#613284)
 	 */
 	if (nv_encoder->dcb->lvdsconf.use_acpi_for_edid) {
-		if ((nv_connector->edid = nouveau_acpi_edid(dev, connector))) {
+		edid = nouveau_acpi_edid(dev, connector);
+		if (edid) {
 			status = connector_status_connected;
 			goto out;
 		}
@@ -695,12 +717,10 @@
 	 * stored for the panel stored in them.
 	 */
 	if (!drm->vbios.fp_no_ddc) {
-		struct edid *edid =
-			(struct edid *)nouveau_bios_embedded_edid(dev);
+		edid = (struct edid *)nouveau_bios_embedded_edid(dev);
 		if (edid) {
-			nv_connector->edid =
-					kmemdup(edid, EDID_LENGTH, GFP_KERNEL);
-			if (nv_connector->edid)
+			edid = kmemdup(edid, EDID_LENGTH, GFP_KERNEL);
+			if (edid)
 				status = connector_status_connected;
 		}
 	}
@@ -713,8 +733,9 @@
 		status = connector_status_unknown;
 #endif
 
-	drm_connector_update_edid_property(connector, nv_connector->edid);
-	nouveau_connector_set_encoder(connector, nv_encoder);
+	nouveau_connector_set_edid(nv_connector, edid);
+	if (nv_encoder)
+		nouveau_connector_set_encoder(connector, nv_encoder);
 	return status;
 }
 
@@ -738,7 +759,6 @@
 	if (!nv_encoder) {
 		NV_ERROR(drm, "can't find encoder to force %s on!\n",
 			 connector->name);
-		connector->status = connector_status_disconnected;
 		return;
 	}
 
@@ -749,9 +769,9 @@
 nouveau_connector_set_property(struct drm_connector *connector,
 			       struct drm_property *property, uint64_t value)
 {
-	struct nouveau_conn_atom *asyc = nouveau_conn_atom(connector->state);
 	struct nouveau_connector *nv_connector = nouveau_connector(connector);
 	struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
+	struct nouveau_conn_atom *asyc = &nv_connector->properties_state;
 	struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
 	int ret;
 
@@ -947,6 +967,9 @@
 		struct drm_display_mode *mode;
 
 		mode = drm_mode_duplicate(dev, nv_connector->native_mode);
+		if (!mode)
+			return 0;
+
 		drm_mode_probed_add(connector, mode);
 		ret = 1;
 	}
@@ -955,7 +978,7 @@
 	 * "native" mode as some VBIOS tables require us to use the
 	 * pixel clock as part of the lookup...
 	 */
-	if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
+	if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS && nv_connector->native_mode)
 		nouveau_connector_detect_depth(connector);
 
 	if (nv_encoder->dcb->type == DCB_OUTPUT_TV)
@@ -1131,6 +1154,16 @@
 	const char *name = connector->name;
 	struct nouveau_encoder *nv_encoder;
 	int ret;
+	bool plugged = (rep->mask != NVIF_NOTIFY_CONN_V0_UNPLUG);
+
+	if (rep->mask & NVIF_NOTIFY_CONN_V0_IRQ) {
+		NV_DEBUG(drm, "service %s\n", name);
+		drm_dp_cec_irq(&nv_connector->aux);
+		if ((nv_encoder = find_encoder(connector, DCB_OUTPUT_DP)))
+			nv50_mstm_service(nv_encoder->dp.mstm);
+
+		return NVIF_NOTIFY_KEEP;
+	}
 
 	ret = pm_runtime_get(drm->dev->dev);
 	if (ret == 0) {
@@ -1151,25 +1184,16 @@
 		return NVIF_NOTIFY_DROP;
 	}
 
-	if (rep->mask & NVIF_NOTIFY_CONN_V0_IRQ) {
-		NV_DEBUG(drm, "service %s\n", name);
-		drm_dp_cec_irq(&nv_connector->aux);
-		if ((nv_encoder = find_encoder(connector, DCB_OUTPUT_DP)))
-			nv50_mstm_service(nv_encoder->dp.mstm);
-	} else {
-		bool plugged = (rep->mask != NVIF_NOTIFY_CONN_V0_UNPLUG);
-
+	if (!plugged)
+		drm_dp_cec_unset_edid(&nv_connector->aux);
+	NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", name);
+	if ((nv_encoder = find_encoder(connector, DCB_OUTPUT_DP))) {
 		if (!plugged)
-			drm_dp_cec_unset_edid(&nv_connector->aux);
-		NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", name);
-		if ((nv_encoder = find_encoder(connector, DCB_OUTPUT_DP))) {
-			if (!plugged)
-				nv50_mstm_remove(nv_encoder->dp.mstm);
-		}
-
-		drm_helper_hpd_irq_event(connector->dev);
+			nv50_mstm_remove(nv_encoder->dp.mstm);
 	}
 
+	drm_helper_hpd_irq_event(connector->dev);
+
 	pm_runtime_mark_last_busy(drm->dev->dev);
 	pm_runtime_put_autosuspend(drm->dev->dev);
 	return NVIF_NOTIFY_KEEP;
@@ -1223,6 +1247,7 @@
 	case DCB_CONNECTOR_DMS59_DP0:
 	case DCB_CONNECTOR_DMS59_DP1:
 	case DCB_CONNECTOR_DP       :
+	case DCB_CONNECTOR_mDP      :
 	case DCB_CONNECTOR_USB_C    : return DRM_MODE_CONNECTOR_DisplayPort;
 	case DCB_CONNECTOR_eDP      : return DRM_MODE_CONNECTOR_eDP;
 	case DCB_CONNECTOR_HDMI_0   :
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nouveau_connector.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nouveau_connector.h
@@ -29,6 +29,7 @@
 
 #include <nvif/notify.h>
 
+#include <drm/drm_crtc.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_encoder.h>
 #include <drm/drm_dp_helper.h>
@@ -44,6 +45,60 @@
 struct nouveau_backlight;
 #endif
 
+#define nouveau_conn_atom(p)                                                   \
+	container_of((p), struct nouveau_conn_atom, state)
+
+struct nouveau_conn_atom {
+	struct drm_connector_state state;
+
+	struct {
+		/* The enum values specifically defined here match nv50/gf119
+		 * hw values, and the code relies on this.
+		 */
+		enum {
+			DITHERING_MODE_OFF = 0x00,
+			DITHERING_MODE_ON = 0x01,
+			DITHERING_MODE_DYNAMIC2X2 = 0x10 | DITHERING_MODE_ON,
+			DITHERING_MODE_STATIC2X2 = 0x18 | DITHERING_MODE_ON,
+			DITHERING_MODE_TEMPORAL = 0x20 | DITHERING_MODE_ON,
+			DITHERING_MODE_AUTO
+		} mode;
+		enum {
+			DITHERING_DEPTH_6BPC = 0x00,
+			DITHERING_DEPTH_8BPC = 0x02,
+			DITHERING_DEPTH_AUTO
+		} depth;
+	} dither;
+
+	struct {
+		int mode;	/* DRM_MODE_SCALE_* */
+		struct {
+			enum {
+				UNDERSCAN_OFF,
+				UNDERSCAN_ON,
+				UNDERSCAN_AUTO,
+			} mode;
+			u32 hborder;
+			u32 vborder;
+		} underscan;
+		bool full;
+	} scaler;
+
+	struct {
+		int color_vibrance;
+		int vibrant_hue;
+	} procamp;
+
+	union {
+		struct {
+			bool dither:1;
+			bool scaler:1;
+			bool procamp:1;
+		};
+		u8 mask;
+	} set;
+};
+
 struct nouveau_connector {
 	struct drm_connector base;
 	enum dcb_connector_type type;
@@ -63,6 +118,12 @@
 #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
 	struct nouveau_backlight *backlight;
 #endif
+	/*
+	 * Our connector property code expects a nouveau_conn_atom struct
+	 * even on pre-nv50 where we do not support atomic. This embedded
+	 * version gets used in the non atomic modeset case.
+	 */
+	struct nouveau_conn_atom properties_state;
 };
 
 static inline struct nouveau_connector *nouveau_connector(
@@ -121,61 +182,6 @@
 extern int nouveau_duallink;
 extern int nouveau_hdmimhz;
 
-#include <drm/drm_crtc.h>
-#define nouveau_conn_atom(p)                                                   \
-	container_of((p), struct nouveau_conn_atom, state)
-
-struct nouveau_conn_atom {
-	struct drm_connector_state state;
-
-	struct {
-		/* The enum values specifically defined here match nv50/gf119
-		 * hw values, and the code relies on this.
-		 */
-		enum {
-			DITHERING_MODE_OFF = 0x00,
-			DITHERING_MODE_ON = 0x01,
-			DITHERING_MODE_DYNAMIC2X2 = 0x10 | DITHERING_MODE_ON,
-			DITHERING_MODE_STATIC2X2 = 0x18 | DITHERING_MODE_ON,
-			DITHERING_MODE_TEMPORAL = 0x20 | DITHERING_MODE_ON,
-			DITHERING_MODE_AUTO
-		} mode;
-		enum {
-			DITHERING_DEPTH_6BPC = 0x00,
-			DITHERING_DEPTH_8BPC = 0x02,
-			DITHERING_DEPTH_AUTO
-		} depth;
-	} dither;
-
-	struct {
-		int mode;	/* DRM_MODE_SCALE_* */
-		struct {
-			enum {
-				UNDERSCAN_OFF,
-				UNDERSCAN_ON,
-				UNDERSCAN_AUTO,
-			} mode;
-			u32 hborder;
-			u32 vborder;
-		} underscan;
-		bool full;
-	} scaler;
-
-	struct {
-		int color_vibrance;
-		int vibrant_hue;
-	} procamp;
-
-	union {
-		struct {
-			bool dither:1;
-			bool scaler:1;
-			bool procamp:1;
-		};
-		u8 mask;
-	} set;
-};
-
 void nouveau_conn_attach_properties(struct drm_connector *);
 void nouveau_conn_reset(struct drm_connector *);
 struct drm_connector_state *
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nouveau_debugfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nouveau_debugfs.c
@@ -54,8 +54,10 @@
 	int ret;
 
 	ret = pm_runtime_get_sync(drm->dev->dev);
-	if (ret < 0 && ret != -EACCES)
+	if (ret < 0 && ret != -EACCES) {
+		pm_runtime_put_autosuspend(drm->dev->dev);
 		return ret;
+	}
 
 	seq_printf(m, "0x%08x\n",
 		   nvif_rd32(&drm->client.device.object, 0x101000));
@@ -181,8 +183,11 @@
 	}
 
 	ret = pm_runtime_get_sync(drm->dev);
-	if (ret < 0 && ret != -EACCES)
+	if (ret < 0 && ret != -EACCES) {
+		pm_runtime_put_autosuspend(drm->dev);
 		return ret;
+	}
+
 	ret = nvif_mthd(ctrl, NVIF_CONTROL_PSTATE_USER, &args, sizeof(args));
 	pm_runtime_put_autosuspend(drm->dev);
 	if (ret < 0)
@@ -202,6 +207,7 @@
 	.open = nouveau_debugfs_pstate_open,
 	.read = seq_read,
 	.write = nouveau_debugfs_pstate_set,
+	.release = single_release,
 };
 
 static struct drm_info_list nouveau_debugfs_list[] = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nouveau_dmem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nouveau_dmem.c
@@ -139,7 +139,7 @@
 	if (!spage || !(args->src[0] & MIGRATE_PFN_MIGRATE))
 		return 0;
 
-	dpage = alloc_page_vma(GFP_HIGHUSER, vmf->vma, vmf->address);
+	dpage = alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO, vmf->vma, vmf->address);
 	if (!dpage)
 		return VM_FAULT_SIGBUS;
 	lock_page(dpage);
@@ -635,10 +635,10 @@
 	unsigned long c, i;
 	int ret = -ENOMEM;
 
-	args.src = kcalloc(max, sizeof(args.src), GFP_KERNEL);
+	args.src = kcalloc(max, sizeof(*args.src), GFP_KERNEL);
 	if (!args.src)
 		goto out;
-	args.dst = kcalloc(max, sizeof(args.dst), GFP_KERNEL);
+	args.dst = kcalloc(max, sizeof(*args.dst), GFP_KERNEL);
 	if (!args.dst)
 		goto out_free_src;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -123,10 +123,16 @@
 static inline bool
 nouveau_cli_work_ready(struct dma_fence *fence)
 {
-	if (!dma_fence_is_signaled(fence))
-		return false;
-	dma_fence_put(fence);
-	return true;
+	bool ret = true;
+
+	spin_lock_irq(fence->lock);
+	if (!dma_fence_is_signaled_locked(fence))
+		ret = false;
+	spin_unlock_irq(fence->lock);
+
+	if (ret == true)
+		dma_fence_put(fence);
+	return ret;
 }
 
 static void
@@ -520,6 +526,7 @@
 		nvkm_dbgopt(nouveau_debug, "DRM");
 
 	INIT_LIST_HEAD(&drm->clients);
+	mutex_init(&drm->clients_lock);
 	spin_lock_init(&drm->tile.lock);
 
 	/* workaround an odd issue on nvc1 by disabling the device's
@@ -589,6 +596,7 @@
 static void
 nouveau_drm_device_fini(struct drm_device *dev)
 {
+	struct nouveau_cli *cli, *temp_cli;
 	struct nouveau_drm *drm = nouveau_drm(dev);
 
 	if (nouveau_pmops_runtime()) {
@@ -613,11 +621,88 @@
 	nouveau_ttm_fini(drm);
 	nouveau_vga_fini(drm);
 
+	/*
+	 * There may be existing clients from as-yet unclosed files. For now,
+	 * clean them up here rather than deferring until the file is closed,
+	 * but this likely not correct if we want to support hot-unplugging
+	 * properly.
+	 */
+	mutex_lock(&drm->clients_lock);
+	list_for_each_entry_safe(cli, temp_cli, &drm->clients, head) {
+		list_del(&cli->head);
+		mutex_lock(&cli->mutex);
+		if (cli->abi16)
+			nouveau_abi16_fini(cli->abi16);
+		mutex_unlock(&cli->mutex);
+		nouveau_cli_fini(cli);
+		kfree(cli);
+	}
+	mutex_unlock(&drm->clients_lock);
+
 	nouveau_cli_fini(&drm->client);
 	nouveau_cli_fini(&drm->master);
+	mutex_destroy(&drm->clients_lock);
 	kfree(drm);
 }
 
+/*
+ * On some Intel PCIe bridge controllers doing a
+ * D0 -> D3hot -> D3cold -> D0 sequence causes Nvidia GPUs to not reappear.
+ * Skipping the intermediate D3hot step seems to make it work again. This is
+ * probably caused by not meeting the expectation the involved AML code has
+ * when the GPU is put into D3hot state before invoking it.
+ *
+ * This leads to various manifestations of this issue:
+ *  - AML code execution to power on the GPU hits an infinite loop (as the
+ *    code waits on device memory to change).
+ *  - kernel crashes, as all PCI reads return -1, which most code isn't able
+ *    to handle well enough.
+ *
+ * In all cases dmesg will contain at least one line like this:
+ * 'nouveau 0000:01:00.0: Refused to change power state, currently in D3'
+ * followed by a lot of nouveau timeouts.
+ *
+ * In the \_SB.PCI0.PEG0.PG00._OFF code deeper down writes bit 0x80 to the not
+ * documented PCI config space register 0x248 of the Intel PCIe bridge
+ * controller (0x1901) in order to change the state of the PCIe link between
+ * the PCIe port and the GPU. There are alternative code paths using other
+ * registers, which seem to work fine (executed pre Windows 8):
+ *  - 0xbc bit 0x20 (publicly available documentation claims 'reserved')
+ *  - 0xb0 bit 0x10 (link disable)
+ * Changing the conditions inside the firmware by poking into the relevant
+ * addresses does resolve the issue, but it seemed to be ACPI private memory
+ * and not any device accessible memory at all, so there is no portable way of
+ * changing the conditions.
+ * On a XPS 9560 that means bits [0,3] on \CPEX need to be cleared.
+ *
+ * The only systems where this behavior can be seen are hybrid graphics laptops
+ * with a secondary Nvidia Maxwell, Pascal or Turing GPU. It's unclear whether
+ * this issue only occurs in combination with listed Intel PCIe bridge
+ * controllers and the mentioned GPUs or other devices as well.
+ *
+ * documentation on the PCIe bridge controller can be found in the
+ * "7th Generation Intel® Processor Families for H Platforms Datasheet Volume 2"
+ * Section "12 PCI Express* Controller (x16) Registers"
+ */
+
+static void quirk_broken_nv_runpm(struct pci_dev *pdev)
+{
+	struct drm_device *dev = pci_get_drvdata(pdev);
+	struct nouveau_drm *drm = nouveau_drm(dev);
+	struct pci_dev *bridge = pci_upstream_bridge(pdev);
+
+	if (!bridge || bridge->vendor != PCI_VENDOR_ID_INTEL)
+		return;
+
+	switch (bridge->device) {
+	case 0x1901:
+		drm->old_pm_cap = pdev->pm_cap;
+		pdev->pm_cap = 0;
+		NV_INFO(drm, "Disabling PCI power management to avoid bug\n");
+		break;
+	}
+}
+
 static int nouveau_drm_probe(struct pci_dev *pdev,
 			     const struct pci_device_id *pent)
 {
@@ -699,6 +784,7 @@
 	if (ret)
 		goto fail_drm_dev_init;
 
+	quirk_broken_nv_runpm(pdev);
 	return 0;
 
 fail_drm_dev_init:
@@ -720,7 +806,7 @@
 	struct nvkm_client *client;
 	struct nvkm_device *device;
 
-	drm_dev_unregister(dev);
+	drm_dev_unplug(dev);
 
 	dev->irq_enabled = false;
 	client = nvxx_client(&drm->client.base);
@@ -736,7 +822,11 @@
 nouveau_drm_remove(struct pci_dev *pdev)
 {
 	struct drm_device *dev = pci_get_drvdata(pdev);
+	struct nouveau_drm *drm = nouveau_drm(dev);
 
+	/* revert our workaround */
+	if (drm->old_pm_cap)
+		pdev->pm_cap = drm->old_pm_cap;
 	nouveau_drm_device_remove(dev);
 }
 
@@ -989,8 +1079,10 @@
 
 	/* need to bring up power immediately if opening device */
 	ret = pm_runtime_get_sync(dev->dev);
-	if (ret < 0 && ret != -EACCES)
+	if (ret < 0 && ret != -EACCES) {
+		pm_runtime_put_autosuspend(dev->dev);
 		return ret;
+	}
 
 	get_task_comm(tmpname, current);
 	snprintf(name, sizeof(name), "%s[%d]", tmpname, pid_nr(fpriv->pid));
@@ -1008,9 +1100,9 @@
 
 	fpriv->driver_priv = cli;
 
-	mutex_lock(&drm->client.mutex);
+	mutex_lock(&drm->clients_lock);
 	list_add(&cli->head, &drm->clients);
-	mutex_unlock(&drm->client.mutex);
+	mutex_unlock(&drm->clients_lock);
 
 done:
 	if (ret && cli) {
@@ -1028,6 +1120,16 @@
 {
 	struct nouveau_cli *cli = nouveau_cli(fpriv);
 	struct nouveau_drm *drm = nouveau_drm(dev);
+	int dev_index;
+
+	/*
+	 * The device is gone, and as it currently stands all clients are
+	 * cleaned up in the removal codepath. In the future this may change
+	 * so that we can support hot-unplugging, but for now we immediately
+	 * return to avoid a double-free situation.
+	 */
+	if (!drm_dev_enter(dev, &dev_index))
+		return;
 
 	pm_runtime_get_sync(dev->dev);
 
@@ -1036,14 +1138,15 @@
 		nouveau_abi16_fini(cli->abi16);
 	mutex_unlock(&cli->mutex);
 
-	mutex_lock(&drm->client.mutex);
+	mutex_lock(&drm->clients_lock);
 	list_del(&cli->head);
-	mutex_unlock(&drm->client.mutex);
+	mutex_unlock(&drm->clients_lock);
 
 	nouveau_cli_fini(cli);
 	kfree(cli);
 	pm_runtime_mark_last_busy(dev->dev);
 	pm_runtime_put_autosuspend(dev->dev);
+	drm_dev_exit(dev_index);
 }
 
 static const struct drm_ioctl_desc
@@ -1072,8 +1175,10 @@
 	long ret;
 
 	ret = pm_runtime_get_sync(dev->dev);
-	if (ret < 0 && ret != -EACCES)
+	if (ret < 0 && ret != -EACCES) {
+		pm_runtime_put_autosuspend(dev->dev);
 		return ret;
+	}
 
 	switch (_IOC_NR(cmd) - DRM_COMMAND_BASE) {
 	case DRM_NOUVEAU_NVIF:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -138,6 +138,13 @@
 
 	struct list_head clients;
 
+	/**
+	 * @clients_lock: Protects access to the @clients list of &struct nouveau_cli.
+	 */
+	struct mutex clients_lock;
+
+	u8 old_pm_cap;
+
 	struct {
 		struct agp_bridge_data *bridge;
 		u32 base;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -189,8 +189,10 @@
 	struct nouveau_fbdev *fbcon = info->par;
 	struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev);
 	int ret = pm_runtime_get_sync(drm->dev->dev);
-	if (ret < 0 && ret != -EACCES)
+	if (ret < 0 && ret != -EACCES) {
+		pm_runtime_put(drm->dev->dev);
 		return ret;
+	}
 	return 0;
 }
 
@@ -315,7 +317,7 @@
 	struct nouveau_framebuffer *fb;
 	struct nouveau_channel *chan;
 	struct nouveau_bo *nvbo;
-	struct drm_mode_fb_cmd2 mode_cmd;
+	struct drm_mode_fb_cmd2 mode_cmd = {};
 	int ret;
 
 	mode_cmd.width = sizes->surface_width;
@@ -592,6 +594,7 @@
 	drm_fb_helper_fini(&fbcon->helper);
 free:
 	kfree(fbcon);
+	drm->fbcon = NULL;
 	return ret;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nouveau_fence.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nouveau_fence.c
@@ -156,7 +156,7 @@
 
 		fence = list_entry(fctx->pending.next, typeof(*fence), head);
 		chan = rcu_dereference_protected(fence->channel, lockdep_is_held(&fctx->lock));
-		if (nouveau_fence_update(fence->channel, fctx))
+		if (nouveau_fence_update(chan, fctx))
 			ret = NVIF_NOTIFY_DROP;
 	}
 	spin_unlock_irqrestore(&fctx->lock, flags);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -45,8 +45,10 @@
 	int ret;
 
 	ret = pm_runtime_get_sync(dev);
-	if (WARN_ON(ret < 0 && ret != -EACCES))
+	if (WARN_ON(ret < 0 && ret != -EACCES)) {
+		pm_runtime_put_autosuspend(dev);
 		return;
+	}
 
 	if (gem->import_attach)
 		drm_prime_gem_destroy(gem, nvbo->bo.sg);
@@ -76,8 +78,10 @@
 		return ret;
 
 	ret = pm_runtime_get_sync(dev);
-	if (ret < 0 && ret != -EACCES)
+	if (ret < 0 && ret != -EACCES) {
+		pm_runtime_put_autosuspend(dev);
 		goto out;
+	}
 
 	ret = nouveau_vma_new(nvbo, vmm, &vma);
 	pm_runtime_mark_last_busy(dev);
@@ -193,7 +197,8 @@
 	 * to the caller, instead of a normal nouveau_bo ttm reference. */
 	ret = drm_gem_object_init(drm->dev, &nvbo->bo.base, size);
 	if (ret) {
-		nouveau_bo_ref(NULL, &nvbo);
+		drm_gem_object_release(&nvbo->bo.base);
+		kfree(nvbo);
 		return ret;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nouveau_mem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nouveau_mem.c
@@ -176,6 +176,8 @@
 nouveau_mem_del(struct ttm_mem_reg *reg)
 {
 	struct nouveau_mem *mem = nouveau_mem(reg);
+	if (!mem)
+		return;
 	nouveau_mem_fini(mem);
 	kfree(reg->mm_node);
 	reg->mm_node = NULL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nouveau_prime.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nouveau_prime.c
@@ -83,14 +83,14 @@
 	 * to the caller, instead of a normal nouveau_bo ttm reference. */
 	ret = drm_gem_object_init(dev, &nvbo->bo.base, size);
 	if (ret) {
-		nouveau_bo_ref(NULL, &nvbo);
+		drm_gem_object_release(&nvbo->bo.base);
+		kfree(nvbo);
 		obj = ERR_PTR(-ENOMEM);
 		goto unlock;
 	}
 
 	ret = nouveau_bo_init(nvbo, size, align, flags, sg, robj);
 	if (ret) {
-		nouveau_bo_ref(NULL, &nvbo);
 		obj = ERR_PTR(ret);
 		goto unlock;
 	}
@@ -112,7 +112,22 @@
 	if (ret)
 		return -EINVAL;
 
-	return 0;
+	ret = ttm_bo_reserve(&nvbo->bo, false, false, NULL);
+	if (ret)
+		goto error;
+
+	if (nvbo->bo.moving)
+		ret = dma_fence_wait(nvbo->bo.moving, true);
+
+	ttm_bo_unreserve(&nvbo->bo);
+	if (ret)
+		goto error;
+
+	return ret;
+
+error:
+	nouveau_bo_unpin(nvbo);
+	return ret;
 }
 
 void nouveau_gem_prime_unpin(struct drm_gem_object *obj)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nouveau_sgdma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nouveau_sgdma.c
@@ -96,12 +96,9 @@
 	else
 		nvbe->ttm.ttm.func = &nv50_sgdma_backend;
 
-	if (ttm_dma_tt_init(&nvbe->ttm, bo, page_flags))
-		/*
-		 * A failing ttm_dma_tt_init() will call ttm_tt_destroy()
-		 * and thus our nouveau_sgdma_destroy() hook, so we don't need
-		 * to free nvbe here.
-		 */
+	if (ttm_dma_tt_init(&nvbe->ttm, bo, page_flags)) {
+		kfree(nvbe);
 		return NULL;
+	}
 	return &nvbe->ttm.ttm;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nouveau_svm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nouveau_svm.c
@@ -112,11 +112,11 @@
 	struct nouveau_cli *cli = nouveau_cli(file_priv);
 	struct drm_nouveau_svm_bind *args = data;
 	unsigned target, cmd, priority;
-	unsigned long addr, end, size;
+	unsigned long addr, end;
 	struct mm_struct *mm;
 
 	args->va_start &= PAGE_MASK;
-	args->va_end &= PAGE_MASK;
+	args->va_end = ALIGN(args->va_end, PAGE_SIZE);
 
 	/* Sanity check arguments */
 	if (args->reserved0 || args->reserved1)
@@ -125,8 +125,6 @@
 		return -EINVAL;
 	if (args->va_start >= args->va_end)
 		return -EINVAL;
-	if (!args->npages)
-		return -EINVAL;
 
 	cmd = args->header >> NOUVEAU_SVM_BIND_COMMAND_SHIFT;
 	cmd &= NOUVEAU_SVM_BIND_COMMAND_MASK;
@@ -158,12 +156,6 @@
 	if (args->stride)
 		return -EINVAL;
 
-	size = ((unsigned long)args->npages) << PAGE_SHIFT;
-	if ((args->va_start + size) <= args->va_start)
-		return -EINVAL;
-	if ((args->va_start + size) > args->va_end)
-		return -EINVAL;
-
 	/*
 	 * Ok we are ask to do something sane, for now we only support migrate
 	 * commands but we will add things like memory policy (what to do on
@@ -173,7 +165,12 @@
 	mm = get_task_mm(current);
 	down_read(&mm->mmap_sem);
 
-	for (addr = args->va_start, end = args->va_start + size; addr < end;) {
+	if (!cli->svm.svmm) {
+		up_read(&mm->mmap_sem);
+		return -EINVAL;
+	}
+
+	for (addr = args->va_start, end = args->va_end; addr < end;) {
 		struct vm_area_struct *vma;
 		unsigned long next;
 
@@ -181,6 +178,7 @@
 		if (!vma)
 			break;
 
+		addr = max(addr, vma->vm_start);
 		next = min(vma->vm_end, end);
 		/* This is a best effort so we ignore errors */
 		nouveau_dmem_migrate_vma(cli->drm, vma, addr, next);
@@ -308,6 +306,10 @@
 	struct drm_nouveau_svm_init *args = data;
 	int ret;
 
+	/* We need to fail if svm is disabled */
+	if (!cli->drm->svm)
+		return -ENOSYS;
+
 	/* Allocate tracking for SVM-enabled VMM. */
 	if (!(svmm = kzalloc(sizeof(*svmm), GFP_KERNEL)))
 		return -ENOMEM;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nouveau_ttm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nouveau_ttm.c
@@ -63,14 +63,12 @@
 {
 	struct nouveau_bo *nvbo = nouveau_bo(bo);
 	struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
-	struct nouveau_mem *mem;
 	int ret;
 
 	if (drm->client.device.info.ram_size == 0)
 		return -ENOMEM;
 
 	ret = nouveau_mem_new(&drm->master, nvbo->kind, nvbo->comp, reg);
-	mem = nouveau_mem(reg);
 	if (ret)
 		return ret;
 
@@ -103,11 +101,9 @@
 {
 	struct nouveau_bo *nvbo = nouveau_bo(bo);
 	struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
-	struct nouveau_mem *mem;
 	int ret;
 
 	ret = nouveau_mem_new(&drm->master, nvbo->kind, nvbo->comp, reg);
-	mem = nouveau_mem(reg);
 	if (ret)
 		return ret;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nouveau_vmm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nouveau_vmm.c
@@ -108,6 +108,9 @@
 	} else {
 		ret = nvif_vmm_get(&vmm->vmm, PTES, false, mem->mem.page, 0,
 				   mem->mem.size, &tmp);
+		if (ret)
+			goto done;
+
 		vma->addr = tmp.addr;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nvkm/core/memory.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nvkm/core/memory.c
@@ -91,8 +91,8 @@
 	}
 
 	refcount_set(&tags->refcount, 1);
+	*ptags = memory->tags = tags;
 	mutex_unlock(&fb->subdev.mutex);
-	*ptags = tags;
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nvkm/engine/device/ctrl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nvkm/engine/device/ctrl.c
@@ -57,7 +57,7 @@
 		args->v0.count = 0;
 		args->v0.ustate_ac = NVIF_CONTROL_PSTATE_INFO_V0_USTATE_DISABLE;
 		args->v0.ustate_dc = NVIF_CONTROL_PSTATE_INFO_V0_USTATE_DISABLE;
-		args->v0.pwrsrc = -ENOSYS;
+		args->v0.pwrsrc = -ENODEV;
 		args->v0.pstate = NVIF_CONTROL_PSTATE_INFO_V0_PSTATE_UNKNOWN;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
@@ -123,7 +123,7 @@
 
 	mutex_init(&tdev->iommu.mutex);
 
-	if (iommu_present(&platform_bus_type)) {
+	if (device_iommu_mapped(dev)) {
 		tdev->iommu.domain = iommu_domain_alloc(&platform_bus_type);
 		if (!tdev->iommu.domain)
 			goto error;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c
@@ -74,6 +74,8 @@
 
 	if (debug > subdev->debug)
 		return;
+	if (!mthd)
+		return;
 
 	for (i = 0; (list = mthd->data[i].mthd) != NULL; i++) {
 		u32 base = chan->head * mthd->addr;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
@@ -419,7 +419,7 @@
 	return ret;
 }
 
-static void
+void
 nvkm_dp_disable(struct nvkm_outp *outp, struct nvkm_ior *ior)
 {
 	struct nvkm_dp *dp = nvkm_dp(outp);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.h
@@ -32,6 +32,7 @@
 
 int nvkm_dp_new(struct nvkm_disp *, int index, struct dcb_output *,
 		struct nvkm_outp **);
+void nvkm_dp_disable(struct nvkm_outp *, struct nvkm_ior *);
 
 /* DPCD Receiver Capabilities */
 #define DPCD_RC00_DPCD_REV                                              0x00000
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c
@@ -144,6 +144,12 @@
 	if (stat & 0x00000008)
 		stat &= ~0x00000008;
 
+	if (stat & 0x00000080) {
+		u32 error = nvkm_mask(device, 0x611848, 0x00000000, 0x00000000);
+		nvkm_warn(subdev, "error %08x\n", error);
+		stat &= ~0x00000080;
+	}
+
 	if (stat & 0x00000100) {
 		unsigned long wndws = nvkm_rd32(device, 0x611858);
 		unsigned long other = nvkm_rd32(device, 0x61185c);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigm200.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigm200.c
@@ -27,10 +27,10 @@
 gm200_hdmi_scdc(struct nvkm_ior *ior, int head, u8 scdc)
 {
 	struct nvkm_device *device = ior->disp->engine.subdev.device;
-	const u32 hoff = head * 0x800;
+	const u32 soff = nv50_ior_base(ior);
 	const u32 ctrl = scdc & 0x3;
 
-	nvkm_mask(device, 0x61c5bc + hoff, 0x00000003, ctrl);
+	nvkm_mask(device, 0x61c5bc + soff, 0x00000003, ctrl);
 
 	ior->tmds.high_speed = !!(scdc & 0x2);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigv100.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigv100.c
@@ -62,7 +62,6 @@
 		nvkm_wr32(device, 0x6f0108 + hdmi, vendor_infoframe.header);
 		nvkm_wr32(device, 0x6f010c + hdmi, vendor_infoframe.subpack0_low);
 		nvkm_wr32(device, 0x6f0110 + hdmi, vendor_infoframe.subpack0_high);
-		nvkm_wr32(device, 0x6f0110 + hdmi, 0x00000000);
 		nvkm_wr32(device, 0x6f0114 + hdmi, 0x00000000);
 		nvkm_wr32(device, 0x6f0118 + hdmi, 0x00000000);
 		nvkm_wr32(device, 0x6f011c + hdmi, 0x00000000);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c
@@ -22,6 +22,7 @@
  * Authors: Ben Skeggs
  */
 #include "outp.h"
+#include "dp.h"
 #include "ior.h"
 
 #include <subdev/bios.h>
@@ -216,6 +217,14 @@
 	if (!ior->arm.head || ior->arm.proto != proto) {
 		OUTP_DBG(outp, "no heads (%x %d %d)", ior->arm.head,
 			 ior->arm.proto, proto);
+
+		/* The EFI GOP driver on Ampere can leave unused DP links routed,
+		 * which we don't expect.  The DisableLT IED script *should* get
+		 * us back to where we need to be.
+		 */
+		if (ior->func->route.get && !ior->arm.head && outp->info.type == DCB_OUTPUT_DP)
+			nvkm_dp_disable(outp, ior);
+
 		return;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h
@@ -121,6 +121,7 @@
 
 extern const struct gf100_grctx_func gk110_grctx;
 void gk110_grctx_generate_r419eb0(struct gf100_gr *);
+void gk110_grctx_generate_r419f78(struct gf100_gr *);
 
 extern const struct gf100_grctx_func gk110b_grctx;
 extern const struct gf100_grctx_func gk208_grctx;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c
@@ -916,7 +916,9 @@
 gk104_grctx_generate_r419f78(struct gf100_gr *gr)
 {
 	struct nvkm_device *device = gr->base.engine.subdev.device;
-	nvkm_mask(device, 0x419f78, 0x00000001, 0x00000000);
+
+	/* bit 3 set disables loads in fp helper invocations, we need it enabled */
+	nvkm_mask(device, 0x419f78, 0x00000009, 0x00000000);
 }
 
 void
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110.c
@@ -820,6 +820,15 @@
 	nvkm_mask(device, 0x419eb0, 0x00001000, 0x00001000);
 }
 
+void
+gk110_grctx_generate_r419f78(struct gf100_gr *gr)
+{
+	struct nvkm_device *device = gr->base.engine.subdev.device;
+
+	/* bit 3 set disables loads in fp helper invocations, we need it enabled */
+	nvkm_mask(device, 0x419f78, 0x00000008, 0x00000000);
+}
+
 const struct gf100_grctx_func
 gk110_grctx = {
 	.main  = gf100_grctx_generate_main,
@@ -852,4 +861,5 @@
 	.gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr,
 	.r418800 = gk104_grctx_generate_r418800,
 	.r419eb0 = gk110_grctx_generate_r419eb0,
+	.r419f78 = gk110_grctx_generate_r419f78,
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110b.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110b.c
@@ -101,4 +101,5 @@
 	.gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr,
 	.r418800 = gk104_grctx_generate_r418800,
 	.r419eb0 = gk110_grctx_generate_r419eb0,
+	.r419f78 = gk110_grctx_generate_r419f78,
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk208.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk208.c
@@ -566,4 +566,5 @@
 	.dist_skip_table = gf117_grctx_generate_dist_skip_table,
 	.gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr,
 	.r418800 = gk104_grctx_generate_r418800,
+	.r419f78 = gk110_grctx_generate_r419f78,
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c
@@ -991,4 +991,5 @@
 	.r406500 = gm107_grctx_generate_r406500,
 	.gpc_tpc_nr = gk104_grctx_generate_gpc_tpc_nr,
 	.r419e00 = gm107_grctx_generate_r419e00,
+	.r419f78 = gk110_grctx_generate_r419f78,
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
@@ -1988,8 +1988,34 @@
 {
 	struct gf100_gr *gr = gf100_gr(base);
 	struct nvkm_subdev *subdev = &base->engine.subdev;
+	struct nvkm_device *device = subdev->device;
+	bool reset = device->chipset == 0x137 || device->chipset == 0x138;
 	u32 ret;
 
+	/* On certain GP107/GP108 boards, we trigger a weird issue where
+	 * GR will stop responding to PRI accesses after we've asked the
+	 * SEC2 RTOS to boot the GR falcons.  This happens with far more
+	 * frequency when cold-booting a board (ie. returning from D3).
+	 *
+	 * The root cause for this is not known and has proven difficult
+	 * to isolate, with many avenues being dead-ends.
+	 *
+	 * A workaround was discovered by Karol, whereby putting GR into
+	 * reset for an extended period right before initialisation
+	 * prevents the problem from occuring.
+	 *
+	 * XXX: As RM does not require any such workaround, this is more
+	 *      of a hack than a true fix.
+	 */
+	reset = nvkm_boolopt(device->cfgopt, "NvGrResetWar", reset);
+	if (reset) {
+		nvkm_mask(device, 0x000200, 0x00001000, 0x00000000);
+		nvkm_rd32(device, 0x000200);
+		msleep(50);
+		nvkm_mask(device, 0x000200, 0x00001000, 0x00001000);
+		nvkm_rd32(device, 0x000200);
+	}
+
 	nvkm_pmu_pgob(gr->base.engine.subdev.device->pmu, false);
 
 	ret = nvkm_falcon_get(gr->fecs.falcon, subdev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c
@@ -143,23 +143,24 @@
 
 	nent = (fuc.size / sizeof(struct gk20a_fw_av));
 
-	pack = vzalloc((sizeof(*pack) * max_classes) +
-		       (sizeof(*init) * (nent + 1)));
+	pack = vzalloc((sizeof(*pack) * (max_classes + 1)) +
+		       (sizeof(*init) * (nent + max_classes + 1)));
 	if (!pack) {
 		ret = -ENOMEM;
 		goto end;
 	}
 
-	init = (void *)(pack + max_classes);
+	init = (void *)(pack + max_classes + 1);
 
-	for (i = 0; i < nent; i++) {
-		struct gf100_gr_init *ent = &init[i];
+	for (i = 0; i < nent; i++, init++) {
 		struct gk20a_fw_av *av = &((struct gk20a_fw_av *)fuc.data)[i];
 		u32 class = av->addr & 0xffff;
 		u32 addr = (av->addr & 0xffff0000) >> 14;
 
 		if (prevclass != class) {
-			pack[classidx].init = ent;
+			if (prevclass) /* Add terminator to the method list. */
+				init++;
+			pack[classidx].init = init;
 			pack[classidx].type = class;
 			prevclass = class;
 			if (++classidx >= max_classes) {
@@ -169,10 +170,10 @@
 			}
 		}
 
-		ent->addr = addr;
-		ent->data = av->data;
-		ent->count = 1;
-		ent->pitch = 1;
+		init->addr = addr;
+		init->data = av->data;
+		init->count = 1;
+		init->pitch = 1;
 	}
 
 	*ppack = pack;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nvkm/subdev/bios/base.c
@@ -33,12 +33,12 @@
 {
 	u32 p = *addr;
 
-	if (*addr > bios->image0_size && bios->imaged_addr) {
+	if (*addr >= bios->image0_size && bios->imaged_addr) {
 		*addr -= bios->image0_size;
 		*addr += bios->imaged_addr;
 	}
 
-	if (unlikely(*addr + size >= bios->size)) {
+	if (unlikely(*addr + size > bios->size)) {
 		nvkm_error(&bios->subdev, "OOB %d %08x %08x\n", size, p, *addr);
 		return false;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c
@@ -75,7 +75,7 @@
 	nvkm_debug(subdev, "%08x: type %02x, %d bytes\n",
 		   image.base, image.type, image.size);
 
-	if (!shadow_fetch(bios, mthd, image.size)) {
+	if (!shadow_fetch(bios, mthd, image.base + image.size)) {
 		nvkm_debug(subdev, "%08x: fetch failed\n", image.base);
 		return 0;
 	}
@@ -154,11 +154,17 @@
 	return (void *)fw;
 }
 
+static void
+shadow_fw_release(void *fw)
+{
+	release_firmware(fw);
+}
+
 static const struct nvbios_source
 shadow_fw = {
 	.name = "firmware",
 	.init = shadow_fw_init,
-	.fini = (void(*)(void *))release_firmware,
+	.fini = shadow_fw_release,
 	.read = shadow_fw_read,
 	.rw = false,
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c
@@ -66,11 +66,16 @@
 	return ERR_PTR(-EINVAL);
 }
 
+static void of_fini(void *p)
+{
+	kfree(p);
+}
+
 const struct nvbios_source
 nvbios_of = {
 	.name = "OpenFirmware",
 	.init = of_init,
-	.fini = (void(*)(void *))kfree,
+	.fini = of_fini,
 	.read = of_read,
 	.size = of_size,
 	.rw = false,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowpci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowpci.c
@@ -101,9 +101,13 @@
 	else
 		return ERR_PTR(-ENODEV);
 
+	if (!pdev->rom || pdev->romlen == 0)
+		return ERR_PTR(-ENODEV);
+
 	if ((priv = kmalloc(sizeof(*priv), GFP_KERNEL))) {
+		priv->size = pdev->romlen;
 		if (ret = -ENODEV,
-		    (priv->rom = pci_platform_rom(pdev, &priv->size)))
+		    (priv->rom = ioremap(pdev->rom, pdev->romlen)))
 			return priv;
 		kfree(priv);
 	}
@@ -111,11 +115,20 @@
 	return ERR_PTR(ret);
 }
 
+static void
+platform_fini(void *data)
+{
+	struct priv *priv = data;
+
+	iounmap(priv->rom);
+	kfree(priv);
+}
+
 const struct nvbios_source
 nvbios_platform = {
 	.name = "PLATFORM",
 	.init = platform_init,
-	.fini = (void(*)(void *))kfree,
+	.fini = platform_fini,
 	.read = pcirom_read,
 	.rw = true,
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nvkm/subdev/clk/base.c
@@ -135,10 +135,10 @@
 
 	list_for_each_entry_from_reverse(cstate, &pstate->list, head) {
 		if (nvkm_cstate_valid(clk, cstate, max_volt, clk->temp))
-			break;
+			return cstate;
 	}
 
-	return cstate;
+	return NULL;
 }
 
 static struct nvkm_cstate *
@@ -169,6 +169,8 @@
 	if (!list_empty(&pstate->list)) {
 		cstate = nvkm_cstate_get(clk, pstate, cstatei);
 		cstate = nvkm_cstate_find_best(clk, pstate, cstate);
+		if (!cstate)
+			return -EINVAL;
 	} else {
 		cstate = &pstate->base;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c
@@ -146,6 +146,7 @@
 	struct nvkm_fault *fault = nvkm_fault(subdev);
 	int i;
 
+	nvkm_notify_fini(&fault->nrpfb);
 	nvkm_event_fini(&fault->event);
 
 	for (i = 0; i < fault->buffer_nr; i++) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxg94.c
@@ -118,10 +118,10 @@
 		if (retries)
 			udelay(400);
 
-		/* transaction request, wait up to 1ms for it to complete */
+		/* transaction request, wait up to 2ms for it to complete */
 		nvkm_wr32(device, 0x00e4e4 + base, 0x00010000 | ctrl);
 
-		timeout = 1000;
+		timeout = 2000;
 		do {
 			ctrl = nvkm_rd32(device, 0x00e4e4 + base);
 			udelay(1);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c
@@ -33,7 +33,7 @@
 gm200_i2c_aux_fini(struct gm200_i2c_aux *aux)
 {
 	struct nvkm_device *device = aux->base.pad->i2c->subdev.device;
-	nvkm_mask(device, 0x00d954 + (aux->ch * 0x50), 0x00310000, 0x00000000);
+	nvkm_mask(device, 0x00d954 + (aux->ch * 0x50), 0x00710000, 0x00000000);
 }
 
 static int
@@ -54,10 +54,10 @@
 			AUX_ERR(&aux->base, "begin idle timeout %08x", ctrl);
 			return -EBUSY;
 		}
-	} while (ctrl & 0x03010000);
+	} while (ctrl & 0x07010000);
 
 	/* set some magic, and wait up to 1ms for it to appear */
-	nvkm_mask(device, 0x00d954 + (aux->ch * 0x50), 0x00300000, ureq);
+	nvkm_mask(device, 0x00d954 + (aux->ch * 0x50), 0x00700000, ureq);
 	timeout = 1000;
 	do {
 		ctrl = nvkm_rd32(device, 0x00d954 + (aux->ch * 0x50));
@@ -67,7 +67,7 @@
 			gm200_i2c_aux_fini(aux);
 			return -EBUSY;
 		}
-	} while ((ctrl & 0x03000000) != urep);
+	} while ((ctrl & 0x07000000) != urep);
 
 	return 0;
 }
@@ -118,10 +118,10 @@
 		if (retries)
 			udelay(400);
 
-		/* transaction request, wait up to 1ms for it to complete */
+		/* transaction request, wait up to 2ms for it to complete */
 		nvkm_wr32(device, 0x00d954 + base, 0x00010000 | ctrl);
 
-		timeout = 1000;
+		timeout = 2000;
 		do {
 			ctrl = nvkm_rd32(device, 0x00d954 + base);
 			udelay(1);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf100.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf100.c
@@ -22,6 +22,7 @@
  * Authors: Ben Skeggs
  */
 #include "priv.h"
+#include <subdev/timer.h>
 
 static void
 gf100_ibus_intr_hub(struct nvkm_subdev *ibus, int i)
@@ -31,7 +32,6 @@
 	u32 data = nvkm_rd32(device, 0x122124 + (i * 0x0400));
 	u32 stat = nvkm_rd32(device, 0x122128 + (i * 0x0400));
 	nvkm_debug(ibus, "HUB%d: %06x %08x (%08x)\n", i, addr, data, stat);
-	nvkm_mask(device, 0x122128 + (i * 0x0400), 0x00000200, 0x00000000);
 }
 
 static void
@@ -42,7 +42,6 @@
 	u32 data = nvkm_rd32(device, 0x124124 + (i * 0x0400));
 	u32 stat = nvkm_rd32(device, 0x124128 + (i * 0x0400));
 	nvkm_debug(ibus, "ROP%d: %06x %08x (%08x)\n", i, addr, data, stat);
-	nvkm_mask(device, 0x124128 + (i * 0x0400), 0x00000200, 0x00000000);
 }
 
 static void
@@ -53,7 +52,6 @@
 	u32 data = nvkm_rd32(device, 0x128124 + (i * 0x0400));
 	u32 stat = nvkm_rd32(device, 0x128128 + (i * 0x0400));
 	nvkm_debug(ibus, "GPC%d: %06x %08x (%08x)\n", i, addr, data, stat);
-	nvkm_mask(device, 0x128128 + (i * 0x0400), 0x00000200, 0x00000000);
 }
 
 void
@@ -90,6 +88,12 @@
 			intr1 &= ~stat;
 		}
 	}
+
+	nvkm_mask(device, 0x121c4c, 0x0000003f, 0x00000002);
+	nvkm_msec(device, 2000,
+		if (!(nvkm_rd32(device, 0x121c4c) & 0x0000003f))
+			break;
+	);
 }
 
 static int
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk104.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk104.c
@@ -22,6 +22,7 @@
  * Authors: Ben Skeggs
  */
 #include "priv.h"
+#include <subdev/timer.h>
 
 static void
 gk104_ibus_intr_hub(struct nvkm_subdev *ibus, int i)
@@ -31,7 +32,6 @@
 	u32 data = nvkm_rd32(device, 0x122124 + (i * 0x0800));
 	u32 stat = nvkm_rd32(device, 0x122128 + (i * 0x0800));
 	nvkm_debug(ibus, "HUB%d: %06x %08x (%08x)\n", i, addr, data, stat);
-	nvkm_mask(device, 0x122128 + (i * 0x0800), 0x00000200, 0x00000000);
 }
 
 static void
@@ -42,7 +42,6 @@
 	u32 data = nvkm_rd32(device, 0x124124 + (i * 0x0800));
 	u32 stat = nvkm_rd32(device, 0x124128 + (i * 0x0800));
 	nvkm_debug(ibus, "ROP%d: %06x %08x (%08x)\n", i, addr, data, stat);
-	nvkm_mask(device, 0x124128 + (i * 0x0800), 0x00000200, 0x00000000);
 }
 
 static void
@@ -53,7 +52,6 @@
 	u32 data = nvkm_rd32(device, 0x128124 + (i * 0x0800));
 	u32 stat = nvkm_rd32(device, 0x128128 + (i * 0x0800));
 	nvkm_debug(ibus, "GPC%d: %06x %08x (%08x)\n", i, addr, data, stat);
-	nvkm_mask(device, 0x128128 + (i * 0x0800), 0x00000200, 0x00000000);
 }
 
 void
@@ -90,6 +88,12 @@
 			intr1 &= ~stat;
 		}
 	}
+
+	nvkm_mask(device, 0x12004c, 0x0000003f, 0x00000002);
+	nvkm_msec(device, 2000,
+		if (!(nvkm_rd32(device, 0x12004c) & 0x0000003f))
+			break;
+	);
 }
 
 static int
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c
@@ -221,8 +221,11 @@
 	void __iomem *map = NULL;
 
 	/* Already mapped? */
-	if (refcount_inc_not_zero(&iobj->maps))
+	if (refcount_inc_not_zero(&iobj->maps)) {
+		/* read barrier match the wmb on refcount set */
+		smp_rmb();
 		return iobj->map;
+	}
 
 	/* Take the lock, and re-check that another thread hasn't
 	 * already mapped the object in the meantime.
@@ -249,6 +252,8 @@
 			iobj->base.memory.ptrs = &nv50_instobj_fast;
 		else
 			iobj->base.memory.ptrs = &nv50_instobj_slow;
+		/* barrier to ensure the ptrs are written before refcount is set */
+		smp_wmb();
 		refcount_set(&iobj->maps, 1);
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c
@@ -316,9 +316,9 @@
 {
 	struct nvkm_device *device = mmu->subdev.device;
 	struct nvkm_mm *mm = &device->fb->ram->vram;
-	const u32 sizeN = nvkm_mm_heap_size(mm, NVKM_RAM_MM_NORMAL);
-	const u32 sizeU = nvkm_mm_heap_size(mm, NVKM_RAM_MM_NOMAP);
-	const u32 sizeM = nvkm_mm_heap_size(mm, NVKM_RAM_MM_MIXED);
+	const u64 sizeN = nvkm_mm_heap_size(mm, NVKM_RAM_MM_NORMAL);
+	const u64 sizeU = nvkm_mm_heap_size(mm, NVKM_RAM_MM_NOMAP);
+	const u64 sizeM = nvkm_mm_heap_size(mm, NVKM_RAM_MM_MIXED);
 	u8 type = NVKM_MEM_KIND * !!mmu->func->kind;
 	u8 heap = NVKM_MEM_VRAM;
 	int heapM, heapN, heapU;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmtu102.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmtu102.c
@@ -32,7 +32,7 @@
 
 	type = 0x00000001; /* PAGE_ALL */
 	if (atomic_read(&vmm->engref[NVKM_SUBDEV_BAR]))
-		type |= 0x00000004; /* HUB_ONLY */
+		type |= 0x00000006; /* HUB_ONLY | ALL PDB (hack) */
 
 	mutex_lock(&subdev->mutex);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm20b.c
@@ -108,6 +108,7 @@
 	struct gm200_secboot *gsb;
 	struct nvkm_acr *acr;
 
+	*psb = NULL;
 	acr = acr_r352_new(BIT(NVKM_SECBOOT_FALCON_FECS) |
 			   BIT(NVKM_SECBOOT_FALCON_PMU));
 	if (IS_ERR(acr))
@@ -116,10 +117,8 @@
 	acr->optional_falcons = BIT(NVKM_SECBOOT_FALCON_PMU);
 
 	gsb = kzalloc(sizeof(*gsb), GFP_KERNEL);
-	if (!gsb) {
-		psb = NULL;
+	if (!gsb)
 		return -ENOMEM;
-	}
 	*psb = &gsb->base;
 
 	ret = nvkm_secboot_ctor(&gm20b_secboot, acr, device, index, &gsb->base);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -1444,22 +1444,26 @@
 {
 	struct dsi_data *dsi = s->private;
 	unsigned long flags;
-	struct dsi_irq_stats stats;
+	struct dsi_irq_stats *stats;
+
+	stats = kmalloc(sizeof(*stats), GFP_KERNEL);
+	if (!stats)
+		return -ENOMEM;
 
 	spin_lock_irqsave(&dsi->irq_stats_lock, flags);
 
-	stats = dsi->irq_stats;
+	*stats = dsi->irq_stats;
 	memset(&dsi->irq_stats, 0, sizeof(dsi->irq_stats));
 	dsi->irq_stats.last_reset = jiffies;
 
 	spin_unlock_irqrestore(&dsi->irq_stats_lock, flags);
 
 	seq_printf(s, "period %u ms\n",
-			jiffies_to_msecs(jiffies - stats.last_reset));
+			jiffies_to_msecs(jiffies - stats->last_reset));
 
-	seq_printf(s, "irqs %d\n", stats.irq_count);
+	seq_printf(s, "irqs %d\n", stats->irq_count);
 #define PIS(x) \
-	seq_printf(s, "%-20s %10d\n", #x, stats.dsi_irqs[ffs(DSI_IRQ_##x)-1]);
+	seq_printf(s, "%-20s %10d\n", #x, stats->dsi_irqs[ffs(DSI_IRQ_##x)-1]);
 
 	seq_printf(s, "-- DSI%d interrupts --\n", dsi->module_id + 1);
 	PIS(VC0);
@@ -1483,10 +1487,10 @@
 
 #define PIS(x) \
 	seq_printf(s, "%-20s %10d %10d %10d %10d\n", #x, \
-			stats.vc_irqs[0][ffs(DSI_VC_IRQ_##x)-1], \
-			stats.vc_irqs[1][ffs(DSI_VC_IRQ_##x)-1], \
-			stats.vc_irqs[2][ffs(DSI_VC_IRQ_##x)-1], \
-			stats.vc_irqs[3][ffs(DSI_VC_IRQ_##x)-1]);
+			stats->vc_irqs[0][ffs(DSI_VC_IRQ_##x)-1], \
+			stats->vc_irqs[1][ffs(DSI_VC_IRQ_##x)-1], \
+			stats->vc_irqs[2][ffs(DSI_VC_IRQ_##x)-1], \
+			stats->vc_irqs[3][ffs(DSI_VC_IRQ_##x)-1]);
 
 	seq_printf(s, "-- VC interrupts --\n");
 	PIS(CS);
@@ -1502,7 +1506,7 @@
 
 #define PIS(x) \
 	seq_printf(s, "%-20s %10d\n", #x, \
-			stats.cio_irqs[ffs(DSI_CIO_IRQ_##x)-1]);
+			stats->cio_irqs[ffs(DSI_CIO_IRQ_##x)-1]);
 
 	seq_printf(s, "-- CIO interrupts --\n");
 	PIS(ERRSYNCESC1);
@@ -1527,6 +1531,8 @@
 	PIS(ULPSACTIVENOT_ALL1);
 #undef PIS
 
+	kfree(stats);
+
 	return 0;
 }
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/omapdrm/dss/dss.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/omapdrm/dss/dss.c
@@ -1151,46 +1151,39 @@
 	.has_lcd_clk_src	=	true,
 };
 
-static int dss_init_ports(struct dss_device *dss)
+static void __dss_uninit_ports(struct dss_device *dss, unsigned int num_ports)
 {
 	struct platform_device *pdev = dss->pdev;
 	struct device_node *parent = pdev->dev.of_node;
 	struct device_node *port;
 	unsigned int i;
-	int r;
 
-	for (i = 0; i < dss->feat->num_ports; i++) {
+	for (i = 0; i < num_ports; i++) {
 		port = of_graph_get_port_by_id(parent, i);
 		if (!port)
 			continue;
 
 		switch (dss->feat->ports[i]) {
 		case OMAP_DISPLAY_TYPE_DPI:
-			r = dpi_init_port(dss, pdev, port, dss->feat->model);
-			if (r)
-				return r;
+			dpi_uninit_port(port);
 			break;
-
 		case OMAP_DISPLAY_TYPE_SDI:
-			r = sdi_init_port(dss, pdev, port);
-			if (r)
-				return r;
+			sdi_uninit_port(port);
 			break;
-
 		default:
 			break;
 		}
+		of_node_put(port);
 	}
-
-	return 0;
 }
 
-static void dss_uninit_ports(struct dss_device *dss)
+static int dss_init_ports(struct dss_device *dss)
 {
 	struct platform_device *pdev = dss->pdev;
 	struct device_node *parent = pdev->dev.of_node;
 	struct device_node *port;
-	int i;
+	unsigned int i;
+	int r;
 
 	for (i = 0; i < dss->feat->num_ports; i++) {
 		port = of_graph_get_port_by_id(parent, i);
@@ -1199,15 +1192,34 @@
 
 		switch (dss->feat->ports[i]) {
 		case OMAP_DISPLAY_TYPE_DPI:
-			dpi_uninit_port(port);
+			r = dpi_init_port(dss, pdev, port, dss->feat->model);
+			if (r)
+				goto error;
 			break;
+
 		case OMAP_DISPLAY_TYPE_SDI:
-			sdi_uninit_port(port);
+			r = sdi_init_port(dss, pdev, port);
+			if (r)
+				goto error;
 			break;
+
 		default:
 			break;
 		}
+		of_node_put(port);
 	}
+
+	return 0;
+
+error:
+	of_node_put(port);
+	__dss_uninit_ports(dss, i);
+	return r;
+}
+
+static void dss_uninit_ports(struct dss_device *dss)
+{
+	__dss_uninit_ports(dss, dss->feat->num_ports);
 }
 
 static int dss_video_pll_probe(struct dss_device *dss)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c
@@ -192,7 +192,7 @@
 	dss = of_find_matching_node(NULL, omapdss_of_match);
 
 	if (dss == NULL || !of_device_is_available(dss))
-		return 0;
+		goto put_node;
 
 	omapdss_walk_device(dss, true);
 
@@ -217,6 +217,8 @@
 		kfree(n);
 	}
 
+put_node:
+	of_node_put(dss);
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -451,11 +451,12 @@
 	if (omap_state->manually_updated)
 		return;
 
-	spin_lock_irq(&crtc->dev->event_lock);
 	drm_crtc_vblank_on(crtc);
+
 	ret = drm_crtc_vblank_get(crtc);
 	WARN_ON(ret != 0);
 
+	spin_lock_irq(&crtc->dev->event_lock);
 	omap_crtc_arm_event(crtc);
 	spin_unlock_irq(&crtc->dev->event_lock);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
@@ -891,6 +891,7 @@
 					   &omap_dmm->refill_pa, GFP_KERNEL);
 	if (!omap_dmm->refill_va) {
 		dev_err(&dev->dev, "could not allocate refill memory\n");
+		ret = -ENOMEM;
 		goto fail;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/omapdrm/omap_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -216,8 +216,8 @@
 	} else if (output->bridge) {
 		struct drm_bridge *bridge = output->bridge;
 
-		while (bridge->next)
-			bridge = bridge->next;
+		while (drm_bridge_get_next_bridge(bridge))
+			bridge = drm_bridge_get_next_bridge(bridge);
 
 		node = bridge->of_node;
 	} else if (output->panel) {
@@ -580,6 +580,10 @@
 	soc = soc_device_match(omapdrm_soc_devices);
 	priv->omaprev = soc ? (unsigned int)soc->data : 0;
 	priv->wq = alloc_ordered_workqueue("omapdrm", 0);
+	if (!priv->wq) {
+		ret = -ENOMEM;
+		goto err_alloc_workqueue;
+	}
 
 	mutex_init(&priv->list_lock);
 	INIT_LIST_HEAD(&priv->obj_list);
@@ -633,6 +637,7 @@
 err_gem_deinit:
 	omap_gem_deinit(ddev);
 	destroy_workqueue(priv->wq);
+err_alloc_workqueue:
 	omap_disconnect_pipelines(ddev);
 	omap_crtc_pre_uninit(priv);
 	drm_dev_put(ddev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/omapdrm/omap_encoder.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/omapdrm/omap_encoder.c
@@ -125,7 +125,8 @@
 	for (dssdev = output; dssdev; dssdev = dssdev->next)
 		omap_encoder_update_videomode_flags(&vm, dssdev->bus_flags);
 
-	for (bridge = output->bridge; bridge; bridge = bridge->next) {
+	for (bridge = output->bridge; bridge;
+	     bridge = drm_bridge_get_next_bridge(bridge)) {
 		if (!bridge->timings)
 			continue;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/omapdrm/omap_gem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/omapdrm/omap_gem.c
@@ -1244,8 +1244,6 @@
 
 	omap_obj = to_omap_bo(obj);
 
-	mutex_lock(&omap_obj->lock);
-
 	omap_obj->sgt = sgt;
 
 	if (sgt->orig_nents == 1) {
@@ -1261,8 +1259,7 @@
 		pages = kcalloc(npages, sizeof(*pages), GFP_KERNEL);
 		if (!pages) {
 			omap_gem_free_object(obj);
-			obj = ERR_PTR(-ENOMEM);
-			goto done;
+			return ERR_PTR(-ENOMEM);
 		}
 
 		omap_obj->pages = pages;
@@ -1275,13 +1272,10 @@
 
 		if (WARN_ON(i != npages)) {
 			omap_gem_free_object(obj);
-			obj = ERR_PTR(-ENOMEM);
-			goto done;
+			return ERR_PTR(-ENOMEM);
 		}
 	}
 
-done:
-	mutex_unlock(&omap_obj->lock);
 	return obj;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/Kconfig
@@ -141,6 +141,7 @@
 	depends on OF
 	depends on I2C
 	depends on BACKLIGHT_CLASS_DEVICE
+	select CRC32
 	help
 	  The panel is used with different sizes LCDs, from 480x272 to
 	  1280x800, and 24 bit per pixel.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-arm-versatile.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-arm-versatile.c
@@ -271,6 +271,8 @@
 	connector->display_info.bus_flags = vpanel->panel_type->bus_flags;
 
 	mode = drm_mode_duplicate(panel->drm, &vpanel->panel_type->mode);
+	if (!mode)
+		return -ENOMEM;
 	drm_mode_set_name(mode);
 	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
 
@@ -350,9 +352,8 @@
 			dev_info(dev, "panel mounted on IB2 daughterboard\n");
 	}
 
-	drm_panel_init(&vpanel->panel);
-	vpanel->panel.dev = dev;
-	vpanel->panel.funcs = &versatile_panel_drm_funcs;
+	drm_panel_init(&vpanel->panel, dev, &versatile_panel_drm_funcs,
+		       DRM_MODE_CONNECTOR_DPI);
 
 	return drm_panel_add(&vpanel->panel);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-feiyang-fy07024di26a30d.c
@@ -204,9 +204,8 @@
 	mipi_dsi_set_drvdata(dsi, ctx);
 	ctx->dsi = dsi;
 
-	drm_panel_init(&ctx->panel);
-	ctx->panel.dev = &dsi->dev;
-	ctx->panel.funcs = &feiyang_funcs;
+	drm_panel_init(&ctx->panel, &dsi->dev, &feiyang_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
 
 	ctx->dvdd = devm_regulator_get(&dsi->dev, "dvdd");
 	if (IS_ERR(ctx->dvdd)) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-ilitek-ili9322.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-ilitek-ili9322.c
@@ -895,9 +895,8 @@
 		ili->input = ili->conf->input;
 	}
 
-	drm_panel_init(&ili->panel);
-	ili->panel.dev = dev;
-	ili->panel.funcs = &ili9322_drm_funcs;
+	drm_panel_init(&ili->panel, dev, &ili9322_drm_funcs,
+		       DRM_MODE_CONNECTOR_DPI);
 
 	return drm_panel_add(&ili->panel);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c
@@ -307,10 +307,10 @@
 	msleep(5);
 
 	/* And reset it */
-	gpiod_set_value(ctx->reset, 1);
+	gpiod_set_value_cansleep(ctx->reset, 1);
 	msleep(20);
 
-	gpiod_set_value(ctx->reset, 0);
+	gpiod_set_value_cansleep(ctx->reset, 0);
 	msleep(20);
 
 	for (i = 0; i < ARRAY_SIZE(ili9881c_init); i++) {
@@ -367,7 +367,7 @@
 
 	mipi_dsi_dcs_enter_sleep_mode(ctx->dsi);
 	regulator_disable(ctx->power);
-	gpiod_set_value(ctx->reset, 1);
+	gpiod_set_value_cansleep(ctx->reset, 1);
 
 	return 0;
 }
@@ -433,9 +433,8 @@
 	mipi_dsi_set_drvdata(dsi, ctx);
 	ctx->dsi = dsi;
 
-	drm_panel_init(&ctx->panel);
-	ctx->panel.dev = &dsi->dev;
-	ctx->panel.funcs = &ili9881c_funcs;
+	drm_panel_init(&ctx->panel, &dsi->dev, &ili9881c_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
 
 	ctx->power = devm_regulator_get(&dsi->dev, "power");
 	if (IS_ERR(ctx->power)) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-innolux-p079zca.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-innolux-p079zca.c
@@ -487,9 +487,8 @@
 	if (IS_ERR(innolux->backlight))
 		return PTR_ERR(innolux->backlight);
 
-	drm_panel_init(&innolux->base);
-	innolux->base.funcs = &innolux_panel_funcs;
-	innolux->base.dev = dev;
+	drm_panel_init(&innolux->base, dev, &innolux_panel_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
 
 	err = drm_panel_add(&innolux->base);
 	if (err < 0)
@@ -509,6 +508,7 @@
 static int innolux_panel_probe(struct mipi_dsi_device *dsi)
 {
 	const struct panel_desc *desc;
+	struct innolux_panel *innolux;
 	int err;
 
 	desc = of_device_get_match_data(&dsi->dev);
@@ -520,7 +520,14 @@
 	if (err < 0)
 		return err;
 
-	return mipi_dsi_attach(dsi);
+	err = mipi_dsi_attach(dsi);
+	if (err < 0) {
+		innolux = mipi_dsi_get_drvdata(dsi);
+		innolux_panel_del(innolux);
+		return err;
+	}
+
+	return 0;
 }
 
 static int innolux_panel_remove(struct mipi_dsi_device *dsi)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c
@@ -437,9 +437,8 @@
 		return ret;
 	}
 
-	drm_panel_init(&jdi->base);
-	jdi->base.funcs = &jdi_panel_funcs;
-	jdi->base.dev = &jdi->dsi->dev;
+	drm_panel_init(&jdi->base, &jdi->dsi->dev, &jdi_panel_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
 
 	ret = drm_panel_add(&jdi->base);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-kingdisplay-kd097d04.c
@@ -391,9 +391,8 @@
 	if (IS_ERR(kingdisplay->backlight))
 		return PTR_ERR(kingdisplay->backlight);
 
-	drm_panel_init(&kingdisplay->base);
-	kingdisplay->base.funcs = &kingdisplay_panel_funcs;
-	kingdisplay->base.dev = &kingdisplay->link->dev;
+	drm_panel_init(&kingdisplay->base, &kingdisplay->link->dev,
+		       &kingdisplay_panel_funcs, DRM_MODE_CONNECTOR_DSI);
 
 	return drm_panel_add(&kingdisplay->base);
 }
@@ -424,7 +423,13 @@
 	if (err < 0)
 		return err;
 
-	return mipi_dsi_attach(dsi);
+	err = mipi_dsi_attach(dsi);
+	if (err < 0) {
+		kingdisplay_panel_del(kingdisplay);
+		return err;
+	}
+
+	return 0;
 }
 
 static int kingdisplay_panel_remove(struct mipi_dsi_device *dsi)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-lg-lb035q02.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-lg-lb035q02.c
@@ -196,9 +196,8 @@
 	if (ret < 0)
 		return ret;
 
-	drm_panel_init(&lcd->panel);
-	lcd->panel.dev = &lcd->spi->dev;
-	lcd->panel.funcs = &lb035q02_funcs;
+	drm_panel_init(&lcd->panel, &lcd->spi->dev, &lb035q02_funcs,
+		       DRM_MODE_CONNECTOR_DPI);
 
 	return drm_panel_add(&lcd->panel);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-lg-lg4573.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-lg-lg4573.c
@@ -259,9 +259,8 @@
 		return ret;
 	}
 
-	drm_panel_init(&ctx->panel);
-	ctx->panel.dev = &spi->dev;
-	ctx->panel.funcs = &lg4573_drm_funcs;
+	drm_panel_init(&ctx->panel, &spi->dev, &lg4573_drm_funcs,
+		       DRM_MODE_CONNECTOR_DPI);
 
 	return drm_panel_add(&ctx->panel);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-lvds.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-lvds.c
@@ -197,7 +197,6 @@
 static int panel_lvds_probe(struct platform_device *pdev)
 {
 	struct panel_lvds *lvds;
-	struct device_node *np;
 	int ret;
 
 	lvds = devm_kzalloc(&pdev->dev, sizeof(*lvds), GFP_KERNEL);
@@ -243,14 +242,9 @@
 		return ret;
 	}
 
-	np = of_parse_phandle(lvds->dev->of_node, "backlight", 0);
-	if (np) {
-		lvds->backlight = of_find_backlight_by_node(np);
-		of_node_put(np);
-
-		if (!lvds->backlight)
-			return -EPROBE_DEFER;
-	}
+	lvds->backlight = devm_of_find_backlight(lvds->dev);
+	if (IS_ERR(lvds->backlight))
+		return PTR_ERR(lvds->backlight);
 
 	/*
 	 * TODO: Handle all power supplies specified in the DT node in a generic
@@ -260,20 +254,15 @@
 	 */
 
 	/* Register the panel. */
-	drm_panel_init(&lvds->panel);
-	lvds->panel.dev = lvds->dev;
-	lvds->panel.funcs = &panel_lvds_funcs;
+	drm_panel_init(&lvds->panel, lvds->dev, &panel_lvds_funcs,
+		       DRM_MODE_CONNECTOR_LVDS);
 
 	ret = drm_panel_add(&lvds->panel);
 	if (ret < 0)
-		goto error;
+		return ret;
 
 	dev_set_drvdata(lvds->dev, lvds);
 	return 0;
-
-error:
-	put_device(&lvds->backlight->dev);
-	return ret;
 }
 
 static int panel_lvds_remove(struct platform_device *pdev)
@@ -284,9 +273,6 @@
 
 	panel_lvds_disable(&lvds->panel);
 
-	if (lvds->backlight)
-		put_device(&lvds->backlight->dev);
-
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-nec-nl8048hl11.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-nec-nl8048hl11.c
@@ -205,9 +205,8 @@
 	if (ret < 0)
 		return ret;
 
-	drm_panel_init(&lcd->panel);
-	lcd->panel.dev = &lcd->spi->dev;
-	lcd->panel.funcs = &nl8048_funcs;
+	drm_panel_init(&lcd->panel, &lcd->spi->dev, &nl8048_funcs,
+		       DRM_MODE_CONNECTOR_DPI);
 
 	return drm_panel_add(&lcd->panel);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-novatek-nt39016.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-novatek-nt39016.c
@@ -292,9 +292,8 @@
 		return err;
 	}
 
-	drm_panel_init(&panel->drm_panel);
-	panel->drm_panel.dev = dev;
-	panel->drm_panel.funcs = &nt39016_funcs;
+	drm_panel_init(&panel->drm_panel, dev, &nt39016_funcs,
+		       DRM_MODE_CONNECTOR_DPI);
 
 	err = drm_panel_add(&panel->drm_panel);
 	if (err < 0) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c
@@ -288,9 +288,8 @@
 	if (IS_ERR(lcd->backlight))
 		return PTR_ERR(lcd->backlight);
 
-	drm_panel_init(&lcd->panel);
-	lcd->panel.dev = dev;
-	lcd->panel.funcs = &lcd_olinuxino_funcs;
+	drm_panel_init(&lcd->panel, dev, &lcd_olinuxino_funcs,
+		       DRM_MODE_CONNECTOR_DPI);
 
 	return drm_panel_add(&lcd->panel);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-orisetech-otm8009a.c
@@ -455,12 +455,11 @@
 	dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
 			  MIPI_DSI_MODE_LPM;
 
-	drm_panel_init(&ctx->panel);
-	ctx->panel.dev = dev;
-	ctx->panel.funcs = &otm8009a_drm_funcs;
+	drm_panel_init(&ctx->panel, dev, &otm8009a_drm_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
 
 	ctx->bl_dev = devm_backlight_device_register(dev, dev_name(dev),
-						     dsi->host->dev, ctx,
+						     dev, ctx,
 						     &otm8009a_backlight_ops,
 						     NULL);
 	if (IS_ERR(ctx->bl_dev)) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-osd-osd101t2587-53ts.c
@@ -166,9 +166,8 @@
 	if (IS_ERR(osd101t2587->backlight))
 		return PTR_ERR(osd101t2587->backlight);
 
-	drm_panel_init(&osd101t2587->base);
-	osd101t2587->base.funcs = &osd101t2587_panel_funcs;
-	osd101t2587->base.dev = &osd101t2587->dsi->dev;
+	drm_panel_init(&osd101t2587->base, &osd101t2587->dsi->dev,
+		       &osd101t2587_panel_funcs, DRM_MODE_CONNECTOR_DSI);
 
 	return drm_panel_add(&osd101t2587->base);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-panasonic-vvx10f034n00.c
@@ -223,9 +223,8 @@
 			return -EPROBE_DEFER;
 	}
 
-	drm_panel_init(&wuxga_nt->base);
-	wuxga_nt->base.funcs = &wuxga_nt_panel_funcs;
-	wuxga_nt->base.dev = &wuxga_nt->dsi->dev;
+	drm_panel_init(&wuxga_nt->base, &wuxga_nt->dsi->dev,
+		       &wuxga_nt_panel_funcs, DRM_MODE_CONNECTOR_DSI);
 
 	ret = drm_panel_add(&wuxga_nt->base);
 	if (ret < 0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c
@@ -232,7 +232,7 @@
 
 	ret = i2c_smbus_write_byte_data(ts->i2c, reg, val);
 	if (ret)
-		dev_err(&ts->dsi->dev, "I2C write failed: %d\n", ret);
+		dev_err(&ts->i2c->dev, "I2C write failed: %d\n", ret);
 }
 
 static int rpi_touchscreen_write(struct rpi_touchscreen *ts, u16 reg, u32 val)
@@ -268,7 +268,7 @@
 	return 0;
 }
 
-static int rpi_touchscreen_enable(struct drm_panel *panel)
+static int rpi_touchscreen_prepare(struct drm_panel *panel)
 {
 	struct rpi_touchscreen *ts = panel_to_ts(panel);
 	int i;
@@ -298,6 +298,13 @@
 	rpi_touchscreen_write(ts, DSI_STARTDSI, 0x01);
 	msleep(100);
 
+	return 0;
+}
+
+static int rpi_touchscreen_enable(struct drm_panel *panel)
+{
+	struct rpi_touchscreen *ts = panel_to_ts(panel);
+
 	/* Turn on the backlight. */
 	rpi_touchscreen_i2c_write(ts, REG_PWM, 255);
 
@@ -352,7 +359,7 @@
 static const struct drm_panel_funcs rpi_touchscreen_funcs = {
 	.disable = rpi_touchscreen_disable,
 	.unprepare = rpi_touchscreen_noop,
-	.prepare = rpi_touchscreen_noop,
+	.prepare = rpi_touchscreen_prepare,
 	.enable = rpi_touchscreen_enable,
 	.get_modes = rpi_touchscreen_get_modes,
 };
@@ -426,8 +433,8 @@
 		return PTR_ERR(ts->dsi);
 	}
 
-	ts->base.dev = dev;
-	ts->base.funcs = &rpi_touchscreen_funcs;
+	drm_panel_init(&ts->base, dev, &rpi_touchscreen_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
 
 	/* This appears last, as it's what will unblock the DSI host
 	 * driver's component bind function.
@@ -452,7 +459,6 @@
 	drm_panel_remove(&ts->base);
 
 	mipi_dsi_device_unregister(ts->dsi);
-	kfree(ts->dsi);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-raydium-rm67191.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-raydium-rm67191.c
@@ -606,9 +606,8 @@
 	if (ret)
 		return ret;
 
-	drm_panel_init(&panel->panel);
-	panel->panel.funcs = &rad_panel_funcs;
-	panel->panel.dev = dev;
+	drm_panel_init(&panel->panel, dev, &rad_panel_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
 	dev_set_drvdata(dev, panel);
 
 	ret = drm_panel_add(&panel->panel);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-raydium-rm68200.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-raydium-rm68200.c
@@ -404,9 +404,8 @@
 	dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
 			  MIPI_DSI_MODE_LPM;
 
-	drm_panel_init(&ctx->panel);
-	ctx->panel.dev = dev;
-	ctx->panel.funcs = &rm68200_drm_funcs;
+	drm_panel_init(&ctx->panel, dev, &rm68200_drm_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
 
 	drm_panel_add(&ctx->panel);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-rocktech-jh057n00900.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-rocktech-jh057n00900.c
@@ -343,9 +343,8 @@
 		return ret;
 	}
 
-	drm_panel_init(&ctx->panel);
-	ctx->panel.dev = dev;
-	ctx->panel.funcs = &jh057n_drm_funcs;
+	drm_panel_init(&ctx->panel, dev, &jh057n_drm_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
 
 	drm_panel_add(&ctx->panel);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-ronbo-rb070d30.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-ronbo-rb070d30.c
@@ -173,9 +173,8 @@
 	mipi_dsi_set_drvdata(dsi, ctx);
 	ctx->dsi = dsi;
 
-	drm_panel_init(&ctx->panel);
-	ctx->panel.dev = &dsi->dev;
-	ctx->panel.funcs = &rb070d30_panel_funcs;
+	drm_panel_init(&ctx->panel, &dsi->dev, &rb070d30_panel_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
 
 	ctx->gpios.reset = devm_gpiod_get(&dsi->dev, "reset", GPIOD_OUT_LOW);
 	if (IS_ERR(ctx->gpios.reset)) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-samsung-ld9040.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-samsung-ld9040.c
@@ -351,9 +351,8 @@
 		return ret;
 	}
 
-	drm_panel_init(&ctx->panel);
-	ctx->panel.dev = dev;
-	ctx->panel.funcs = &ld9040_drm_funcs;
+	drm_panel_init(&ctx->panel, dev, &ld9040_drm_funcs,
+		       DRM_MODE_CONNECTOR_DPI);
 
 	return drm_panel_add(&ctx->panel);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-samsung-s6d16d0.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-samsung-s6d16d0.c
@@ -215,9 +215,8 @@
 		return ret;
 	}
 
-	drm_panel_init(&s6->panel);
-	s6->panel.dev = dev;
-	s6->panel.funcs = &s6d16d0_drm_funcs;
+	drm_panel_init(&s6->panel, dev, &s6d16d0_drm_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
 
 	ret = drm_panel_add(&s6->panel);
 	if (ret < 0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-samsung-s6e3ha2.c
@@ -732,9 +732,8 @@
 	ctx->bl_dev->props.brightness = S6E3HA2_DEFAULT_BRIGHTNESS;
 	ctx->bl_dev->props.power = FB_BLANK_POWERDOWN;
 
-	drm_panel_init(&ctx->panel);
-	ctx->panel.dev = dev;
-	ctx->panel.funcs = &s6e3ha2_drm_funcs;
+	drm_panel_init(&ctx->panel, dev, &s6e3ha2_drm_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
 
 	ret = drm_panel_add(&ctx->panel);
 	if (ret < 0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-samsung-s6e63j0x03.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-samsung-s6e63j0x03.c
@@ -466,9 +466,8 @@
 		return PTR_ERR(ctx->reset_gpio);
 	}
 
-	drm_panel_init(&ctx->panel);
-	ctx->panel.dev = dev;
-	ctx->panel.funcs = &s6e63j0x03_funcs;
+	drm_panel_init(&ctx->panel, dev, &s6e63j0x03_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
 
 	ctx->bl_dev = backlight_device_register("s6e63j0x03", dev, ctx,
 						&s6e63j0x03_bl_ops, NULL);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c
@@ -473,9 +473,8 @@
 		return ret;
 	}
 
-	drm_panel_init(&ctx->panel);
-	ctx->panel.dev = dev;
-	ctx->panel.funcs = &s6e63m0_drm_funcs;
+	drm_panel_init(&ctx->panel, dev, &s6e63m0_drm_funcs,
+		       DRM_MODE_CONNECTOR_DPI);
 
 	ret = s6e63m0_backlight_register(ctx);
 	if (ret < 0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c
@@ -1017,9 +1017,8 @@
 
 	ctx->brightness = GAMMA_LEVEL_NUM - 1;
 
-	drm_panel_init(&ctx->panel);
-	ctx->panel.dev = dev;
-	ctx->panel.funcs = &s6e8aa0_drm_funcs;
+	drm_panel_init(&ctx->panel, dev, &s6e8aa0_drm_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
 
 	ret = drm_panel_add(&ctx->panel);
 	if (ret < 0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c
@@ -274,9 +274,8 @@
 			return -EPROBE_DEFER;
 	}
 
-	drm_panel_init(&panel->base);
-	panel->base.dev = dev;
-	panel->base.funcs = &seiko_panel_funcs;
+	drm_panel_init(&panel->base, dev, &seiko_panel_funcs,
+		       DRM_MODE_CONNECTOR_DPI);
 
 	err = drm_panel_add(&panel->base);
 	if (err < 0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-sharp-lq101r1sx01.c
@@ -329,9 +329,8 @@
 	if (IS_ERR(sharp->backlight))
 		return PTR_ERR(sharp->backlight);
 
-	drm_panel_init(&sharp->base);
-	sharp->base.funcs = &sharp_panel_funcs;
-	sharp->base.dev = &sharp->link1->dev;
+	drm_panel_init(&sharp->base, &sharp->link1->dev, &sharp_panel_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
 
 	return drm_panel_add(&sharp->base);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-sharp-ls037v7dw01.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-sharp-ls037v7dw01.c
@@ -185,9 +185,8 @@
 		return PTR_ERR(lcd->ud_gpio);
 	}
 
-	drm_panel_init(&lcd->panel);
-	lcd->panel.dev = &pdev->dev;
-	lcd->panel.funcs = &ls037v7dw01_funcs;
+	drm_panel_init(&lcd->panel, &pdev->dev, &ls037v7dw01_funcs,
+		       DRM_MODE_CONNECTOR_DPI);
 
 	return drm_panel_add(&lcd->panel);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c
@@ -264,9 +264,8 @@
 	if (IS_ERR(sharp_nt->backlight))
 		return PTR_ERR(sharp_nt->backlight);
 
-	drm_panel_init(&sharp_nt->base);
-	sharp_nt->base.funcs = &sharp_nt_panel_funcs;
-	sharp_nt->base.dev = &sharp_nt->dsi->dev;
+	drm_panel_init(&sharp_nt->base, &sharp_nt->dsi->dev,
+		       &sharp_nt_panel_funcs, DRM_MODE_CONNECTOR_DSI);
 
 	return drm_panel_add(&sharp_nt->base);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-simple.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-simple.c
@@ -94,6 +94,7 @@
 
 	u32 bus_format;
 	u32 bus_flags;
+	int connector_type;
 };
 
 struct panel_simple {
@@ -464,9 +465,8 @@
 	if (!of_get_display_timing(dev->of_node, "panel-timing", &dt))
 		panel_simple_parse_panel_timing_node(dev, panel, &dt);
 
-	drm_panel_init(&panel->base);
-	panel->base.dev = dev;
-	panel->base.funcs = &panel_simple_funcs;
+	drm_panel_init(&panel->base, dev, &panel_simple_funcs,
+		       desc->connector_type);
 
 	err = drm_panel_add(&panel->base);
 	if (err < 0)
@@ -531,8 +531,8 @@
 	.num_modes = 1,
 	.bpc = 8,
 	.size = {
-		.width = 105,
-		.height = 67,
+		.width = 99,
+		.height = 58,
 	},
 	.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
 };
@@ -833,6 +833,7 @@
 		.unprepare = 1000,
 	},
 	.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA,
+	.connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct display_timing auo_g185han01_timings = {
@@ -862,6 +863,7 @@
 		.unprepare = 1000,
 	},
 	.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+	.connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct display_timing auo_p320hvn03_timings = {
@@ -890,6 +892,7 @@
 		.unprepare = 500,
 	},
 	.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+	.connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct drm_display_mode auo_t215hvn01_mode = {
@@ -916,7 +919,9 @@
 	.delay = {
 		.disable = 5,
 		.unprepare = 1000,
-	}
+	},
+	.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+	.connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct drm_display_mode avic_tm070ddh03_mode = {
@@ -1205,6 +1210,7 @@
 		.disable = 200,
 	},
 	.bus_format = MEDIA_BUS_FMT_RGB666_1X7X3_SPWG,
+	.connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct display_timing dlc_dlc1010gig_timing = {
@@ -1235,6 +1241,7 @@
 		.unprepare = 60,
 	},
 	.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+	.connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct drm_display_mode edt_et035012dm6_mode = {
@@ -1501,6 +1508,7 @@
 		.height = 94,
 	},
 	.bus_format = MEDIA_BUS_FMT_RGB666_1X7X3_SPWG,
+	.connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct display_timing hannstar_hsd100pxn1_timing = {
@@ -1525,6 +1533,7 @@
 		.height = 152,
 	},
 	.bus_format = MEDIA_BUS_FMT_RGB666_1X7X3_SPWG,
+	.connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct drm_display_mode hitachi_tx23d38vm0caa_mode = {
@@ -1577,6 +1586,7 @@
 		.height = 54,
 	},
 	.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
+	.connector_type = DRM_MODE_CONNECTOR_DPI,
 	.bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE,
 };
 
@@ -1619,7 +1629,7 @@
 static const struct panel_desc innolux_g070y2_l01 = {
 	.timings = &innolux_g070y2_l01_timing,
 	.num_timings = 1,
-	.bpc = 6,
+	.bpc = 8,
 	.size = {
 		.width = 152,
 		.height = 91,
@@ -1631,18 +1641,19 @@
 		.unprepare = 800,
 	},
 	.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+	.connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct display_timing innolux_g101ice_l01_timing = {
 	.pixelclock = { 60400000, 71100000, 74700000 },
 	.hactive = { 1280, 1280, 1280 },
-	.hfront_porch = { 41, 80, 100 },
-	.hback_porch = { 40, 79, 99 },
-	.hsync_len = { 1, 1, 1 },
+	.hfront_porch = { 30, 60, 70 },
+	.hback_porch = { 30, 60, 70 },
+	.hsync_len = { 22, 40, 60 },
 	.vactive = { 800, 800, 800 },
-	.vfront_porch = { 5, 11, 14 },
-	.vback_porch = { 4, 11, 14 },
-	.vsync_len = { 1, 1, 1 },
+	.vfront_porch = { 3, 8, 14 },
+	.vback_porch = { 3, 8, 14 },
+	.vsync_len = { 4, 7, 12 },
 	.flags = DISPLAY_FLAGS_DE_HIGH,
 };
 
@@ -1659,6 +1670,8 @@
 		.disable = 200,
 	},
 	.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+	.bus_flags = DRM_BUS_FLAG_DE_HIGH,
+	.connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct display_timing innolux_g121i1_l01_timing = {
@@ -1686,6 +1699,7 @@
 		.disable = 20,
 	},
 	.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+	.connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct drm_display_mode innolux_g121x1_l03_mode = {
@@ -1715,6 +1729,9 @@
 		.unprepare = 200,
 		.disable = 400,
 	},
+	.bus_format = MEDIA_BUS_FMT_RGB666_1X7X3_SPWG,
+	.bus_flags = DRM_BUS_FLAG_DE_HIGH,
+	.connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 /*
@@ -1869,6 +1886,7 @@
 		.height = 109,
 	},
 	.bus_format = MEDIA_BUS_FMT_RGB666_1X7X3_SPWG,
+	.connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct display_timing kyo_tcg121xglp_timing = {
@@ -1893,6 +1911,7 @@
 		.height = 184,
 	},
 	.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+	.connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct drm_display_mode lemaker_bl035_rgb_002_mode = {
@@ -1935,12 +1954,13 @@
 static const struct panel_desc lg_lb070wv8 = {
 	.modes = &lg_lb070wv8_mode,
 	.num_modes = 1,
-	.bpc = 16,
+	.bpc = 8,
 	.size = {
 		.width = 151,
 		.height = 91,
 	},
 	.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+	.connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct drm_display_mode lg_lp079qx1_sp0v_mode = {
@@ -2048,6 +2068,40 @@
 	.flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
 };
 
+static const struct drm_display_mode logicpd_type_28_mode = {
+	.clock = 9000,
+	.hdisplay = 480,
+	.hsync_start = 480 + 3,
+	.hsync_end = 480 + 3 + 42,
+	.htotal = 480 + 3 + 42 + 2,
+
+	.vdisplay = 272,
+	.vsync_start = 272 + 2,
+	.vsync_end = 272 + 2 + 11,
+	.vtotal = 272 + 2 + 11 + 3,
+	.vrefresh = 60,
+	.flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC,
+};
+
+static const struct panel_desc logicpd_type_28 = {
+	.modes = &logicpd_type_28_mode,
+	.num_modes = 1,
+	.bpc = 8,
+	.size = {
+		.width = 105,
+		.height = 67,
+	},
+	.delay = {
+		.prepare = 200,
+		.enable = 200,
+		.unprepare = 200,
+		.disable = 200,
+	},
+	.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
+	.bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE |
+		     DRM_BUS_FLAG_SYNC_DRIVE_NEGEDGE,
+};
+
 static const struct panel_desc mitsubishi_aa070mc01 = {
 	.modes = &mitsubishi_aa070mc01_mode,
 	.num_modes = 1,
@@ -2063,6 +2117,7 @@
 		.disable = 400,
 	},
 	.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+	.connector_type = DRM_MODE_CONNECTOR_LVDS,
 	.bus_flags = DRM_BUS_FLAG_DE_HIGH,
 };
 
@@ -2091,6 +2146,7 @@
 		.disable = 50,
 	},
 	.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+	.connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct drm_display_mode nec_nl4827hc19_05b_mode = {
@@ -2193,6 +2249,7 @@
 		.unprepare = 500,
 	},
 	.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+	.connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct drm_display_mode nvd_9128_mode = {
@@ -2216,6 +2273,7 @@
 		.height = 88,
 	},
 	.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+	.connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct display_timing okaya_rs800480t_7x0gp_timing = {
@@ -2348,12 +2406,12 @@
 static const struct panel_desc ortustech_com43h4m85ulc = {
 	.modes = &ortustech_com43h4m85ulc_mode,
 	.num_modes = 1,
-	.bpc = 8,
+	.bpc = 6,
 	.size = {
 		.width = 56,
 		.height = 93,
 	},
-	.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
+	.bus_format = MEDIA_BUS_FMT_RGB666_1X18,
 	.bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE,
 };
 
@@ -2628,6 +2686,7 @@
 		.height = 136,
 	},
 	.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA,
+	.connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct display_timing sharp_lq123p1jx31_timing = {
@@ -2807,6 +2866,7 @@
 		.height = 95,
 	},
 	.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+	.connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct display_timing tianma_tm070rvhg71_timing = {
@@ -2831,6 +2891,7 @@
 		.height = 86,
 	},
 	.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+	.connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct drm_display_mode ti_nspire_cx_lcd_mode[] = {
@@ -2913,6 +2974,7 @@
 	},
 	.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
 	.bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE,
+	.connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct drm_display_mode tpk_f07a_0102_mode = {
@@ -2983,6 +3045,7 @@
 		.height = 91,
 	},
 	.bus_format = MEDIA_BUS_FMT_RGB666_1X7X3_SPWG,
+	.connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
 static const struct panel_desc urt_umsh_8596md_parallel = {
@@ -3265,6 +3328,9 @@
 		.compatible = "lg,lp129qe",
 		.data = &lg_lp129qe,
 	}, {
+		.compatible = "logicpd,type28",
+		.data = &logicpd_type_28,
+	}, {
 		.compatible = "mitsubishi,aa070mc01-ca1",
 		.data = &mitsubishi_aa070mc01,
 	}, {
@@ -3472,6 +3538,34 @@
 	.lanes = 4,
 };
 
+static const struct drm_display_mode auo_b101uan01_mode = {
+	.clock = 154500,
+	.hdisplay = 1920,
+	.hsync_start = 1920 + 185,
+	.hsync_end = 1920 + 185,
+	.htotal = 1920 + 185 + 925,
+	.vdisplay = 1200,
+	.vsync_start = 1200 + 3,
+	.vsync_end = 1200 + 3 + 5,
+	.vtotal = 1200 + 3 + 5 + 4,
+	.vrefresh = 60,
+};
+
+static const struct panel_desc_dsi auo_b101uan01 = {
+	.desc = {
+		.modes = &auo_b101uan01_mode,
+		.num_modes = 1,
+		.bpc = 8,
+		.size = {
+			.width = 108,
+			.height = 272,
+		},
+	},
+	.flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE,
+	.format = MIPI_DSI_FMT_RGB888,
+	.lanes = 4,
+};
+
 static const struct drm_display_mode boe_tv080wum_nl0_mode = {
 	.clock = 160000,
 	.hdisplay = 1200,
@@ -3651,6 +3745,9 @@
 		.compatible = "auo,b080uan01",
 		.data = &auo_b080uan01
 	}, {
+		.compatible = "auo,b101uan01",
+		.data = &auo_b101uan01
+	}, {
 		.compatible = "boe,tv080wum-nl0",
 		.data = &boe_tv080wum_nl0
 	}, {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-sitronix-st7701.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-sitronix-st7701.c
@@ -369,7 +369,8 @@
 	if (IS_ERR(st7701->backlight))
 		return PTR_ERR(st7701->backlight);
 
-	drm_panel_init(&st7701->panel);
+	drm_panel_init(&st7701->panel, &dsi->dev, &st7701_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
 
 	/**
 	 * Once sleep out has been issued, ST7701 IC required to wait 120ms
@@ -381,8 +382,6 @@
 	 * ts8550b and there is no valid documentation for that.
 	 */
 	st7701->sleep_delay = 120 + desc->panel_sleep_delay;
-	st7701->panel.funcs = &st7701_funcs;
-	st7701->panel.dev = &dsi->dev;
 
 	ret = drm_panel_add(&st7701->panel);
 	if (ret < 0)
@@ -392,7 +391,15 @@
 	st7701->dsi = dsi;
 	st7701->desc = desc;
 
-	return mipi_dsi_attach(dsi);
+	ret = mipi_dsi_attach(dsi);
+	if (ret)
+		goto err_attach;
+
+	return 0;
+
+err_attach:
+	drm_panel_remove(&st7701->panel);
+	return ret;
 }
 
 static int st7701_dsi_remove(struct mipi_dsi_device *dsi)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-sitronix-st7789v.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-sitronix-st7789v.c
@@ -381,8 +381,8 @@
 	spi_set_drvdata(spi, ctx);
 	ctx->spi = spi;
 
-	ctx->panel.dev = &spi->dev;
-	ctx->panel.funcs = &st7789v_drm_funcs;
+	drm_panel_init(&ctx->panel, &spi->dev, &st7789v_drm_funcs,
+		       DRM_MODE_CONNECTOR_DPI);
 
 	ctx->power = devm_regulator_get(&spi->dev, "power");
 	if (IS_ERR(ctx->power))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-sony-acx565akm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-sony-acx565akm.c
@@ -648,9 +648,8 @@
 			return ret;
 	}
 
-	drm_panel_init(&lcd->panel);
-	lcd->panel.dev = &lcd->spi->dev;
-	lcd->panel.funcs = &acx565akm_funcs;
+	drm_panel_init(&lcd->panel, &lcd->spi->dev, &acx565akm_funcs,
+		       DRM_MODE_CONNECTOR_DPI);
 
 	ret = drm_panel_add(&lcd->panel);
 	if (ret < 0) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-tpo-td028ttec1.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-tpo-td028ttec1.c
@@ -347,9 +347,8 @@
 		return ret;
 	}
 
-	drm_panel_init(&lcd->panel);
-	lcd->panel.dev = &lcd->spi->dev;
-	lcd->panel.funcs = &td028ttec1_funcs;
+	drm_panel_init(&lcd->panel, &lcd->spi->dev, &td028ttec1_funcs,
+		       DRM_MODE_CONNECTOR_DPI);
 
 	return drm_panel_add(&lcd->panel);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-tpo-td043mtea1.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-tpo-td043mtea1.c
@@ -458,9 +458,8 @@
 		return ret;
 	}
 
-	drm_panel_init(&lcd->panel);
-	lcd->panel.dev = &lcd->spi->dev;
-	lcd->panel.funcs = &td043mtea1_funcs;
+	drm_panel_init(&lcd->panel, &lcd->spi->dev, &td043mtea1_funcs,
+		       DRM_MODE_CONNECTOR_DPI);
 
 	ret = drm_panel_add(&lcd->panel);
 	if (ret < 0) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-tpo-tpg110.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-tpo-tpg110.c
@@ -457,9 +457,8 @@
 	if (ret)
 		return ret;
 
-	drm_panel_init(&tpg->panel);
-	tpg->panel.dev = dev;
-	tpg->panel.funcs = &tpg110_drm_funcs;
+	drm_panel_init(&tpg->panel, dev, &tpg110_drm_funcs,
+		       DRM_MODE_CONNECTOR_DPI);
 	spi_set_drvdata(spi, tpg);
 
 	return drm_panel_add(&tpg->panel);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panel/panel-truly-nt35597.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panel/panel-truly-nt35597.c
@@ -518,9 +518,8 @@
 	/* dual port */
 	gpiod_set_value(ctx->mode_gpio, 0);
 
-	drm_panel_init(&ctx->panel);
-	ctx->panel.dev = dev;
-	ctx->panel.funcs = &truly_nt35597_drm_funcs;
+	drm_panel_init(&ctx->panel, dev, &truly_nt35597_drm_funcs,
+		       DRM_MODE_CONNECTOR_DSI);
 	drm_panel_add(&ctx->panel);
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panfrost/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panfrost/Kconfig
@@ -3,7 +3,8 @@
 config DRM_PANFROST
 	tristate "Panfrost (DRM support for ARM Mali Midgard/Bifrost GPUs)"
 	depends on DRM
-	depends on ARM || ARM64 || (COMPILE_TEST && !GENERIC_ATOMIC64)
+	depends on ARM || ARM64 || COMPILE_TEST
+	depends on !GENERIC_ATOMIC64    # for IOMMU_IO_PGTABLE_LPAE
 	depends on MMU
 	select DRM_SCHED
 	select IOMMU_SUPPORT
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panfrost/panfrost_devfreq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panfrost/panfrost_devfreq.c
@@ -53,8 +53,10 @@
 	if (err) {
 		dev_err(dev, "Cannot set frequency %lu (%d)\n", target_rate,
 			err);
-		regulator_set_voltage(pfdev->regulator, pfdev->devfreq.cur_volt,
-				      pfdev->devfreq.cur_volt);
+		if (pfdev->regulator)
+			regulator_set_voltage(pfdev->regulator,
+					      pfdev->devfreq.cur_volt,
+					      pfdev->devfreq.cur_volt);
 		return err;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panfrost/panfrost_device.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panfrost/panfrost_device.c
@@ -59,7 +59,8 @@
 	if (IS_ERR(pfdev->bus_clock)) {
 		dev_err(pfdev->dev, "get bus_clock failed %ld\n",
 			PTR_ERR(pfdev->bus_clock));
-		return PTR_ERR(pfdev->bus_clock);
+		err = PTR_ERR(pfdev->bus_clock);
+		goto disable_clock;
 	}
 
 	if (pfdev->bus_clock) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panfrost/panfrost_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panfrost/panfrost_drv.c
@@ -78,8 +78,10 @@
 static int panfrost_ioctl_create_bo(struct drm_device *dev, void *data,
 		struct drm_file *file)
 {
+	struct panfrost_file_priv *priv = file->driver_priv;
 	struct panfrost_gem_object *bo;
 	struct drm_panfrost_create_bo *args = data;
+	struct panfrost_gem_mapping *mapping;
 
 	if (!args->size || args->pad ||
 	    (args->flags & ~(PANFROST_BO_NOEXEC | PANFROST_BO_HEAP)))
@@ -95,7 +97,14 @@
 	if (IS_ERR(bo))
 		return PTR_ERR(bo);
 
-	args->offset = bo->node.start << PAGE_SHIFT;
+	mapping = panfrost_gem_mapping_get(bo, priv);
+	if (!mapping) {
+		drm_gem_object_put_unlocked(&bo->base.base);
+		return -EINVAL;
+	}
+
+	args->offset = mapping->mmnode.start << PAGE_SHIFT;
+	panfrost_gem_mapping_put(mapping);
 
 	return 0;
 }
@@ -119,6 +128,11 @@
 		  struct drm_panfrost_submit *args,
 		  struct panfrost_job *job)
 {
+	struct panfrost_file_priv *priv = file_priv->driver_priv;
+	struct panfrost_gem_object *bo;
+	unsigned int i;
+	int ret;
+
 	job->bo_count = args->bo_handle_count;
 
 	if (!job->bo_count)
@@ -130,9 +144,33 @@
 	if (!job->implicit_fences)
 		return -ENOMEM;
 
-	return drm_gem_objects_lookup(file_priv,
-				      (void __user *)(uintptr_t)args->bo_handles,
-				      job->bo_count, &job->bos);
+	ret = drm_gem_objects_lookup(file_priv,
+				     (void __user *)(uintptr_t)args->bo_handles,
+				     job->bo_count, &job->bos);
+	if (ret)
+		return ret;
+
+	job->mappings = kvmalloc_array(job->bo_count,
+				       sizeof(struct panfrost_gem_mapping *),
+				       GFP_KERNEL | __GFP_ZERO);
+	if (!job->mappings)
+		return -ENOMEM;
+
+	for (i = 0; i < job->bo_count; i++) {
+		struct panfrost_gem_mapping *mapping;
+
+		bo = to_panfrost_bo(job->bos[i]);
+		mapping = panfrost_gem_mapping_get(bo, priv);
+		if (!mapping) {
+			ret = -EINVAL;
+			break;
+		}
+
+		atomic_inc(&bo->gpu_usecount);
+		job->mappings[i] = mapping;
+	}
+
+	return ret;
 }
 
 /**
@@ -303,21 +341,26 @@
 	}
 
 	/* Don't allow mmapping of heap objects as pages are not pinned. */
-	if (to_panfrost_bo(gem_obj)->is_heap)
-		return -EINVAL;
+	if (to_panfrost_bo(gem_obj)->is_heap) {
+		ret = -EINVAL;
+		goto out;
+	}
 
 	ret = drm_gem_create_mmap_offset(gem_obj);
 	if (ret == 0)
 		args->offset = drm_vma_node_offset_addr(&gem_obj->vma_node);
-	drm_gem_object_put_unlocked(gem_obj);
 
+out:
+	drm_gem_object_put_unlocked(gem_obj);
 	return ret;
 }
 
 static int panfrost_ioctl_get_bo_offset(struct drm_device *dev, void *data,
 			    struct drm_file *file_priv)
 {
+	struct panfrost_file_priv *priv = file_priv->driver_priv;
 	struct drm_panfrost_get_bo_offset *args = data;
+	struct panfrost_gem_mapping *mapping;
 	struct drm_gem_object *gem_obj;
 	struct panfrost_gem_object *bo;
 
@@ -328,18 +371,26 @@
 	}
 	bo = to_panfrost_bo(gem_obj);
 
-	args->offset = bo->node.start << PAGE_SHIFT;
-
+	mapping = panfrost_gem_mapping_get(bo, priv);
 	drm_gem_object_put_unlocked(gem_obj);
+
+	if (!mapping)
+		return -EINVAL;
+
+	args->offset = mapping->mmnode.start << PAGE_SHIFT;
+	panfrost_gem_mapping_put(mapping);
 	return 0;
 }
 
 static int panfrost_ioctl_madvise(struct drm_device *dev, void *data,
 				  struct drm_file *file_priv)
 {
+	struct panfrost_file_priv *priv = file_priv->driver_priv;
 	struct drm_panfrost_madvise *args = data;
 	struct panfrost_device *pfdev = dev->dev_private;
 	struct drm_gem_object *gem_obj;
+	struct panfrost_gem_object *bo;
+	int ret = 0;
 
 	gem_obj = drm_gem_object_lookup(file_priv, args->handle);
 	if (!gem_obj) {
@@ -347,23 +398,48 @@
 		return -ENOENT;
 	}
 
-	args->retained = drm_gem_shmem_madvise(gem_obj, args->madv);
+	bo = to_panfrost_bo(gem_obj);
 
-	if (args->retained) {
-		struct panfrost_gem_object *bo = to_panfrost_bo(gem_obj);
+	mutex_lock(&pfdev->shrinker_lock);
+	mutex_lock(&bo->mappings.lock);
+	if (args->madv == PANFROST_MADV_DONTNEED) {
+		struct panfrost_gem_mapping *first;
+
+		first = list_first_entry(&bo->mappings.list,
+					 struct panfrost_gem_mapping,
+					 node);
+
+		/*
+		 * If we want to mark the BO purgeable, there must be only one
+		 * user: the caller FD.
+		 * We could do something smarter and mark the BO purgeable only
+		 * when all its users have marked it purgeable, but globally
+		 * visible/shared BOs are likely to never be marked purgeable
+		 * anyway, so let's not bother.
+		 */
+		if (!list_is_singular(&bo->mappings.list) ||
+		    WARN_ON_ONCE(first->mmu != &priv->mmu)) {
+			ret = -EINVAL;
+			goto out_unlock_mappings;
+		}
+	}
 
-		mutex_lock(&pfdev->shrinker_lock);
+	args->retained = drm_gem_shmem_madvise(gem_obj, args->madv);
 
+	if (args->retained) {
 		if (args->madv == PANFROST_MADV_DONTNEED)
-			list_add_tail(&bo->base.madv_list, &pfdev->shrinker_list);
+			list_move_tail(&bo->base.madv_list,
+				       &pfdev->shrinker_list);
 		else if (args->madv == PANFROST_MADV_WILLNEED)
 			list_del_init(&bo->base.madv_list);
-
-		mutex_unlock(&pfdev->shrinker_lock);
 	}
 
+out_unlock_mappings:
+	mutex_unlock(&bo->mappings.lock);
+	mutex_unlock(&pfdev->shrinker_lock);
+
 	drm_gem_object_put_unlocked(gem_obj);
-	return 0;
+	return ret;
 }
 
 int panfrost_unstable_ioctl_check(void)
@@ -443,7 +519,7 @@
 {
 	struct panfrost_file_priv *panfrost_priv = file->driver_priv;
 
-	panfrost_perfcnt_close(panfrost_priv);
+	panfrost_perfcnt_close(file);
 	panfrost_job_close(panfrost_priv);
 
 	panfrost_mmu_pgtable_free(panfrost_priv);
@@ -616,3 +692,4 @@
 MODULE_AUTHOR("Panfrost Project Developers");
 MODULE_DESCRIPTION("Panfrost DRM Driver");
 MODULE_LICENSE("GPL v2");
+MODULE_SOFTDEP("pre: governor_simpleondemand");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panfrost/panfrost_gem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panfrost/panfrost_gem.c
@@ -19,6 +19,22 @@
 	struct panfrost_gem_object *bo = to_panfrost_bo(obj);
 	struct panfrost_device *pfdev = obj->dev->dev_private;
 
+	/*
+	 * Make sure the BO is no longer inserted in the shrinker list before
+	 * taking care of the destruction itself. If we don't do that we have a
+	 * race condition between this function and what's done in
+	 * panfrost_gem_shrinker_scan().
+	 */
+	mutex_lock(&pfdev->shrinker_lock);
+	list_del_init(&bo->base.madv_list);
+	mutex_unlock(&pfdev->shrinker_lock);
+
+	/*
+	 * If we still have mappings attached to the BO, there's a problem in
+	 * our refcounting.
+	 */
+	WARN_ON_ONCE(!list_empty(&bo->mappings.list));
+
 	if (bo->sgts) {
 		int i;
 		int n_sgt = bo->base.base.size / SZ_2M;
@@ -30,18 +46,74 @@
 				sg_free_table(&bo->sgts[i]);
 			}
 		}
-		kfree(bo->sgts);
+		kvfree(bo->sgts);
 	}
 
-	mutex_lock(&pfdev->shrinker_lock);
-	if (!list_empty(&bo->base.madv_list))
-		list_del(&bo->base.madv_list);
-	mutex_unlock(&pfdev->shrinker_lock);
-
 	drm_gem_shmem_free_object(obj);
 }
 
-static int panfrost_gem_open(struct drm_gem_object *obj, struct drm_file *file_priv)
+struct panfrost_gem_mapping *
+panfrost_gem_mapping_get(struct panfrost_gem_object *bo,
+			 struct panfrost_file_priv *priv)
+{
+	struct panfrost_gem_mapping *iter, *mapping = NULL;
+
+	mutex_lock(&bo->mappings.lock);
+	list_for_each_entry(iter, &bo->mappings.list, node) {
+		if (iter->mmu == &priv->mmu) {
+			kref_get(&iter->refcount);
+			mapping = iter;
+			break;
+		}
+	}
+	mutex_unlock(&bo->mappings.lock);
+
+	return mapping;
+}
+
+static void
+panfrost_gem_teardown_mapping(struct panfrost_gem_mapping *mapping)
+{
+	struct panfrost_file_priv *priv;
+
+	if (mapping->active)
+		panfrost_mmu_unmap(mapping);
+
+	priv = container_of(mapping->mmu, struct panfrost_file_priv, mmu);
+	spin_lock(&priv->mm_lock);
+	if (drm_mm_node_allocated(&mapping->mmnode))
+		drm_mm_remove_node(&mapping->mmnode);
+	spin_unlock(&priv->mm_lock);
+}
+
+static void panfrost_gem_mapping_release(struct kref *kref)
+{
+	struct panfrost_gem_mapping *mapping;
+
+	mapping = container_of(kref, struct panfrost_gem_mapping, refcount);
+
+	panfrost_gem_teardown_mapping(mapping);
+	drm_gem_object_put_unlocked(&mapping->obj->base.base);
+	kfree(mapping);
+}
+
+void panfrost_gem_mapping_put(struct panfrost_gem_mapping *mapping)
+{
+	if (!mapping)
+		return;
+
+	kref_put(&mapping->refcount, panfrost_gem_mapping_release);
+}
+
+void panfrost_gem_teardown_mappings_locked(struct panfrost_gem_object *bo)
+{
+	struct panfrost_gem_mapping *mapping;
+
+	list_for_each_entry(mapping, &bo->mappings.list, node)
+		panfrost_gem_teardown_mapping(mapping);
+}
+
+int panfrost_gem_open(struct drm_gem_object *obj, struct drm_file *file_priv)
 {
 	int ret;
 	size_t size = obj->size;
@@ -49,6 +121,16 @@
 	struct panfrost_gem_object *bo = to_panfrost_bo(obj);
 	unsigned long color = bo->noexec ? PANFROST_BO_NOEXEC : 0;
 	struct panfrost_file_priv *priv = file_priv->driver_priv;
+	struct panfrost_gem_mapping *mapping;
+
+	mapping = kzalloc(sizeof(*mapping), GFP_KERNEL);
+	if (!mapping)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&mapping->node);
+	kref_init(&mapping->refcount);
+	drm_gem_object_get(obj);
+	mapping->obj = bo;
 
 	/*
 	 * Executable buffers cannot cross a 16MB boundary as the program
@@ -61,37 +143,48 @@
 	else
 		align = size >= SZ_2M ? SZ_2M >> PAGE_SHIFT : 0;
 
-	bo->mmu = &priv->mmu;
+	mapping->mmu = &priv->mmu;
 	spin_lock(&priv->mm_lock);
-	ret = drm_mm_insert_node_generic(&priv->mm, &bo->node,
+	ret = drm_mm_insert_node_generic(&priv->mm, &mapping->mmnode,
 					 size >> PAGE_SHIFT, align, color, 0);
 	spin_unlock(&priv->mm_lock);
 	if (ret)
-		return ret;
+		goto err;
 
 	if (!bo->is_heap) {
-		ret = panfrost_mmu_map(bo);
-		if (ret) {
-			spin_lock(&priv->mm_lock);
-			drm_mm_remove_node(&bo->node);
-			spin_unlock(&priv->mm_lock);
-		}
+		ret = panfrost_mmu_map(mapping);
+		if (ret)
+			goto err;
 	}
+
+	mutex_lock(&bo->mappings.lock);
+	WARN_ON(bo->base.madv != PANFROST_MADV_WILLNEED);
+	list_add_tail(&mapping->node, &bo->mappings.list);
+	mutex_unlock(&bo->mappings.lock);
+
+err:
+	if (ret)
+		panfrost_gem_mapping_put(mapping);
 	return ret;
 }
 
-static void panfrost_gem_close(struct drm_gem_object *obj, struct drm_file *file_priv)
+void panfrost_gem_close(struct drm_gem_object *obj, struct drm_file *file_priv)
 {
-	struct panfrost_gem_object *bo = to_panfrost_bo(obj);
 	struct panfrost_file_priv *priv = file_priv->driver_priv;
+	struct panfrost_gem_object *bo = to_panfrost_bo(obj);
+	struct panfrost_gem_mapping *mapping = NULL, *iter;
 
-	if (bo->is_mapped)
-		panfrost_mmu_unmap(bo);
+	mutex_lock(&bo->mappings.lock);
+	list_for_each_entry(iter, &bo->mappings.list, node) {
+		if (iter->mmu == &priv->mmu) {
+			mapping = iter;
+			list_del(&iter->node);
+			break;
+		}
+	}
+	mutex_unlock(&bo->mappings.lock);
 
-	spin_lock(&priv->mm_lock);
-	if (drm_mm_node_allocated(&bo->node))
-		drm_mm_remove_node(&bo->node);
-	spin_unlock(&priv->mm_lock);
+	panfrost_gem_mapping_put(mapping);
 }
 
 static int panfrost_gem_pin(struct drm_gem_object *obj)
@@ -131,6 +224,8 @@
 	if (!obj)
 		return NULL;
 
+	INIT_LIST_HEAD(&obj->mappings.list);
+	mutex_init(&obj->mappings.lock);
 	obj->base.base.funcs = &panfrost_gem_funcs;
 
 	return &obj->base.base;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panfrost/panfrost_gem.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panfrost/panfrost_gem.h
@@ -13,23 +13,52 @@
 	struct drm_gem_shmem_object base;
 	struct sg_table *sgts;
 
-	struct panfrost_mmu *mmu;
-	struct drm_mm_node node;
-	bool is_mapped		:1;
+	/*
+	 * Use a list for now. If searching a mapping ever becomes the
+	 * bottleneck, we should consider using an RB-tree, or even better,
+	 * let the core store drm_gem_object_mapping entries (where we
+	 * could place driver specific data) instead of drm_gem_object ones
+	 * in its drm_file->object_idr table.
+	 *
+	 * struct drm_gem_object_mapping {
+	 *	struct drm_gem_object *obj;
+	 *	void *driver_priv;
+	 * };
+	 */
+	struct {
+		struct list_head list;
+		struct mutex lock;
+	} mappings;
+
+	/*
+	 * Count the number of jobs referencing this BO so we don't let the
+	 * shrinker reclaim this object prematurely.
+	 */
+	atomic_t gpu_usecount;
+
 	bool noexec		:1;
 	bool is_heap		:1;
 };
 
+struct panfrost_gem_mapping {
+	struct list_head node;
+	struct kref refcount;
+	struct panfrost_gem_object *obj;
+	struct drm_mm_node mmnode;
+	struct panfrost_mmu *mmu;
+	bool active		:1;
+};
+
 static inline
 struct  panfrost_gem_object *to_panfrost_bo(struct drm_gem_object *obj)
 {
 	return container_of(to_drm_gem_shmem_obj(obj), struct panfrost_gem_object, base);
 }
 
-static inline
-struct  panfrost_gem_object *drm_mm_node_to_panfrost_bo(struct drm_mm_node *node)
+static inline struct panfrost_gem_mapping *
+drm_mm_node_to_panfrost_mapping(struct drm_mm_node *node)
 {
-	return container_of(node, struct panfrost_gem_object, node);
+	return container_of(node, struct panfrost_gem_mapping, mmnode);
 }
 
 struct drm_gem_object *panfrost_gem_create_object(struct drm_device *dev, size_t size);
@@ -45,6 +74,16 @@
 				u32 flags,
 				uint32_t *handle);
 
+int panfrost_gem_open(struct drm_gem_object *obj, struct drm_file *file_priv);
+void panfrost_gem_close(struct drm_gem_object *obj,
+			struct drm_file *file_priv);
+
+struct panfrost_gem_mapping *
+panfrost_gem_mapping_get(struct panfrost_gem_object *bo,
+			 struct panfrost_file_priv *priv);
+void panfrost_gem_mapping_put(struct panfrost_gem_mapping *mapping);
+void panfrost_gem_teardown_mappings_locked(struct panfrost_gem_object *bo);
+
 void panfrost_gem_shrinker_init(struct drm_device *dev);
 void panfrost_gem_shrinker_cleanup(struct drm_device *dev);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panfrost/panfrost_gem_shrinker.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panfrost/panfrost_gem_shrinker.c
@@ -39,15 +39,27 @@
 static bool panfrost_gem_purge(struct drm_gem_object *obj)
 {
 	struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
+	struct panfrost_gem_object *bo = to_panfrost_bo(obj);
+	bool ret = false;
 
-	if (!mutex_trylock(&shmem->pages_lock))
+	if (atomic_read(&bo->gpu_usecount))
+		return false;
+
+	if (!mutex_trylock(&bo->mappings.lock))
 		return false;
 
-	panfrost_mmu_unmap(to_panfrost_bo(obj));
+	if (!mutex_trylock(&shmem->pages_lock))
+		goto unlock_mappings;
+
+	panfrost_gem_teardown_mappings_locked(bo);
 	drm_gem_shmem_purge_locked(obj);
+	ret = true;
 
 	mutex_unlock(&shmem->pages_lock);
-	return true;
+
+unlock_mappings:
+	mutex_unlock(&bo->mappings.lock);
+	return ret;
 }
 
 static unsigned long
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panfrost/panfrost_gpu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panfrost/panfrost_gpu.c
@@ -75,6 +75,17 @@
 	return 0;
 }
 
+void panfrost_gpu_amlogic_quirk(struct panfrost_device *pfdev)
+{
+	/*
+	 * The Amlogic integrated Mali-T820, Mali-G31 & Mali-G52 needs
+	 * these undocumented bits in GPU_PWR_OVERRIDE1 to be set in order
+	 * to operate correctly.
+	 */
+	gpu_write(pfdev, GPU_PWR_KEY, GPU_PWR_KEY_UNLOCK);
+	gpu_write(pfdev, GPU_PWR_OVERRIDE1, 0xfff | (0x20 << 16));
+}
+
 static void panfrost_gpu_init_quirks(struct panfrost_device *pfdev)
 {
 	u32 quirks = 0;
@@ -142,7 +153,6 @@
 struct panfrost_model {
 	const char *name;
 	u32 id;
-	u32 id_mask;
 	u64 features;
 	u64 issues;
 	struct {
@@ -304,6 +314,8 @@
 	int ret;
 	u32 val;
 
+	panfrost_gpu_init_quirks(pfdev);
+
 	/* Just turn on everything for now */
 	gpu_write(pfdev, L2_PWRON_LO, pfdev->features.l2_present);
 	ret = readl_relaxed_poll_timeout(pfdev->iomem + L2_READY_LO,
@@ -357,7 +369,6 @@
 		return err;
 	}
 
-	panfrost_gpu_init_quirks(pfdev);
 	panfrost_gpu_power_on(pfdev);
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panfrost/panfrost_gpu.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panfrost/panfrost_gpu.h
@@ -16,4 +16,6 @@
 void panfrost_gpu_power_on(struct panfrost_device *pfdev);
 void panfrost_gpu_power_off(struct panfrost_device *pfdev);
 
+void panfrost_gpu_amlogic_quirk(struct panfrost_device *pfdev);
+
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panfrost/panfrost_job.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panfrost/panfrost_job.c
@@ -269,9 +269,25 @@
 	dma_fence_put(job->done_fence);
 	dma_fence_put(job->render_done_fence);
 
+	if (job->mappings) {
+		for (i = 0; i < job->bo_count; i++) {
+			if (!job->mappings[i])
+				break;
+
+			atomic_dec(&job->mappings[i]->obj->gpu_usecount);
+			panfrost_gem_mapping_put(job->mappings[i]);
+		}
+		kvfree(job->mappings);
+	}
+
 	if (job->bos) {
-		for (i = 0; i < job->bo_count; i++)
+		struct panfrost_gem_object *bo;
+
+		for (i = 0; i < job->bo_count; i++) {
+			bo = to_panfrost_bo(job->bos[i]);
 			drm_gem_object_put_unlocked(job->bos[i]);
+		}
+
 		kvfree(job->bos);
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panfrost/panfrost_job.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panfrost/panfrost_job.h
@@ -32,6 +32,7 @@
 
 	/* Exclusive fences we have taken from the BOs to wait for */
 	struct dma_fence **implicit_fences;
+	struct panfrost_gem_mapping **mappings;
 	struct drm_gem_object **bos;
 	u32 bo_count;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panfrost/panfrost_mmu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panfrost/panfrost_mmu.c
@@ -52,25 +52,16 @@
 }
 
 static void lock_region(struct panfrost_device *pfdev, u32 as_nr,
-			u64 iova, size_t size)
+			u64 iova, u64 size)
 {
 	u8 region_width;
 	u64 region = iova & PAGE_MASK;
-	/*
-	 * fls returns:
-	 * 1 .. 32
-	 *
-	 * 10 + fls(num_pages)
-	 * results in the range (11 .. 42)
-	 */
-
-	size = round_up(size, PAGE_SIZE);
 
-	region_width = 10 + fls(size >> PAGE_SHIFT);
-	if ((size >> PAGE_SHIFT) != (1ul << (region_width - 11))) {
-		/* not pow2, so must go up to the next pow2 */
-		region_width += 1;
-	}
+	/* The size is encoded as ceil(log2) minus(1), which may be calculated
+	 * with fls. The size must be clamped to hardware bounds.
+	 */
+	size = max_t(u64, size, AS_LOCK_REGION_MIN_SIZE);
+	region_width = fls64(size - 1) - 1;
 	region |= region_width;
 
 	/* Lock the region that needs to be updated */
@@ -81,7 +72,7 @@
 
 
 static int mmu_hw_do_operation_locked(struct panfrost_device *pfdev, int as_nr,
-				      u64 iova, size_t size, u32 op)
+				      u64 iova, u64 size, u32 op)
 {
 	if (as_nr < 0)
 		return 0;
@@ -98,7 +89,7 @@
 
 static int mmu_hw_do_operation(struct panfrost_device *pfdev,
 			       struct panfrost_mmu *mmu,
-			       u64 iova, size_t size, u32 op)
+			       u64 iova, u64 size, u32 op)
 {
 	int ret;
 
@@ -115,7 +106,7 @@
 	u64 transtab = cfg->arm_mali_lpae_cfg.transtab;
 	u64 memattr = cfg->arm_mali_lpae_cfg.memattr;
 
-	mmu_hw_do_operation_locked(pfdev, as_nr, 0, ~0UL, AS_COMMAND_FLUSH_MEM);
+	mmu_hw_do_operation_locked(pfdev, as_nr, 0, ~0ULL, AS_COMMAND_FLUSH_MEM);
 
 	mmu_write(pfdev, AS_TRANSTAB_LO(as_nr), transtab & 0xffffffffUL);
 	mmu_write(pfdev, AS_TRANSTAB_HI(as_nr), transtab >> 32);
@@ -131,7 +122,7 @@
 
 static void panfrost_mmu_disable(struct panfrost_device *pfdev, u32 as_nr)
 {
-	mmu_hw_do_operation_locked(pfdev, as_nr, 0, ~0UL, AS_COMMAND_FLUSH_MEM);
+	mmu_hw_do_operation_locked(pfdev, as_nr, 0, ~0ULL, AS_COMMAND_FLUSH_MEM);
 
 	mmu_write(pfdev, AS_TRANSTAB_LO(as_nr), 0);
 	mmu_write(pfdev, AS_TRANSTAB_HI(as_nr), 0);
@@ -151,7 +142,12 @@
 	as = mmu->as;
 	if (as >= 0) {
 		int en = atomic_inc_return(&mmu->as_count);
-		WARN_ON(en >= NUM_JOB_SLOTS);
+
+		/*
+		 * AS can be retained by active jobs or a perfcnt context,
+		 * hence the '+ 1' here.
+		 */
+		WARN_ON(en >= (NUM_JOB_SLOTS + 1));
 
 		list_move(&mmu->list, &pfdev->as_lru_list);
 		goto out;
@@ -226,7 +222,7 @@
 
 static void panfrost_mmu_flush_range(struct panfrost_device *pfdev,
 				     struct panfrost_mmu *mmu,
-				     u64 iova, size_t size)
+				     u64 iova, u64 size)
 {
 	if (mmu->as < 0)
 		return;
@@ -237,7 +233,7 @@
 	if (pm_runtime_active(pfdev->dev))
 		mmu_hw_do_operation(pfdev, mmu, iova, size, AS_COMMAND_FLUSH_PT);
 
-	pm_runtime_put_sync_autosuspend(pfdev->dev);
+	pm_runtime_put_autosuspend(pfdev->dev);
 }
 
 static int mmu_map_sg(struct panfrost_device *pfdev, struct panfrost_mmu *mmu,
@@ -269,14 +265,15 @@
 	return 0;
 }
 
-int panfrost_mmu_map(struct panfrost_gem_object *bo)
+int panfrost_mmu_map(struct panfrost_gem_mapping *mapping)
 {
+	struct panfrost_gem_object *bo = mapping->obj;
 	struct drm_gem_object *obj = &bo->base.base;
 	struct panfrost_device *pfdev = to_panfrost_device(obj->dev);
 	struct sg_table *sgt;
 	int prot = IOMMU_READ | IOMMU_WRITE;
 
-	if (WARN_ON(bo->is_mapped))
+	if (WARN_ON(mapping->active))
 		return 0;
 
 	if (bo->noexec)
@@ -286,25 +283,28 @@
 	if (WARN_ON(IS_ERR(sgt)))
 		return PTR_ERR(sgt);
 
-	mmu_map_sg(pfdev, bo->mmu, bo->node.start << PAGE_SHIFT, prot, sgt);
-	bo->is_mapped = true;
+	mmu_map_sg(pfdev, mapping->mmu, mapping->mmnode.start << PAGE_SHIFT,
+		   prot, sgt);
+	mapping->active = true;
 
 	return 0;
 }
 
-void panfrost_mmu_unmap(struct panfrost_gem_object *bo)
+void panfrost_mmu_unmap(struct panfrost_gem_mapping *mapping)
 {
+	struct panfrost_gem_object *bo = mapping->obj;
 	struct drm_gem_object *obj = &bo->base.base;
 	struct panfrost_device *pfdev = to_panfrost_device(obj->dev);
-	struct io_pgtable_ops *ops = bo->mmu->pgtbl_ops;
-	u64 iova = bo->node.start << PAGE_SHIFT;
-	size_t len = bo->node.size << PAGE_SHIFT;
+	struct io_pgtable_ops *ops = mapping->mmu->pgtbl_ops;
+	u64 iova = mapping->mmnode.start << PAGE_SHIFT;
+	size_t len = mapping->mmnode.size << PAGE_SHIFT;
 	size_t unmapped_len = 0;
 
-	if (WARN_ON(!bo->is_mapped))
+	if (WARN_ON(!mapping->active))
 		return;
 
-	dev_dbg(pfdev->dev, "unmap: as=%d, iova=%llx, len=%zx", bo->mmu->as, iova, len);
+	dev_dbg(pfdev->dev, "unmap: as=%d, iova=%llx, len=%zx",
+		mapping->mmu->as, iova, len);
 
 	while (unmapped_len < len) {
 		size_t unmapped_page;
@@ -318,8 +318,9 @@
 		unmapped_len += pgsize;
 	}
 
-	panfrost_mmu_flush_range(pfdev, bo->mmu, bo->node.start << PAGE_SHIFT, len);
-	bo->is_mapped = false;
+	panfrost_mmu_flush_range(pfdev, mapping->mmu,
+				 mapping->mmnode.start << PAGE_SHIFT, len);
+	mapping->active = false;
 }
 
 static void mmu_tlb_inv_context_s1(void *cookie)
@@ -394,10 +395,10 @@
 	free_io_pgtable_ops(mmu->pgtbl_ops);
 }
 
-static struct panfrost_gem_object *
-addr_to_drm_mm_node(struct panfrost_device *pfdev, int as, u64 addr)
+static struct panfrost_gem_mapping *
+addr_to_mapping(struct panfrost_device *pfdev, int as, u64 addr)
 {
-	struct panfrost_gem_object *bo = NULL;
+	struct panfrost_gem_mapping *mapping = NULL;
 	struct panfrost_file_priv *priv;
 	struct drm_mm_node *node;
 	u64 offset = addr >> PAGE_SHIFT;
@@ -418,8 +419,9 @@
 	drm_mm_for_each_node(node, &priv->mm) {
 		if (offset >= node->start &&
 		    offset < (node->start + node->size)) {
-			bo = drm_mm_node_to_panfrost_bo(node);
-			drm_gem_object_get(&bo->base.base);
+			mapping = drm_mm_node_to_panfrost_mapping(node);
+
+			kref_get(&mapping->refcount);
 			break;
 		}
 	}
@@ -427,7 +429,7 @@
 	spin_unlock(&priv->mm_lock);
 out:
 	spin_unlock(&pfdev->as_lock);
-	return bo;
+	return mapping;
 }
 
 #define NUM_FAULT_PAGES (SZ_2M / PAGE_SIZE)
@@ -436,28 +438,30 @@
 				       u64 addr)
 {
 	int ret, i;
+	struct panfrost_gem_mapping *bomapping;
 	struct panfrost_gem_object *bo;
 	struct address_space *mapping;
 	pgoff_t page_offset;
 	struct sg_table *sgt;
 	struct page **pages;
 
-	bo = addr_to_drm_mm_node(pfdev, as, addr);
-	if (!bo)
+	bomapping = addr_to_mapping(pfdev, as, addr);
+	if (!bomapping)
 		return -ENOENT;
 
+	bo = bomapping->obj;
 	if (!bo->is_heap) {
 		dev_WARN(pfdev->dev, "matching BO is not heap type (GPU VA = %llx)",
-			 bo->node.start << PAGE_SHIFT);
+			 bomapping->mmnode.start << PAGE_SHIFT);
 		ret = -EINVAL;
 		goto err_bo;
 	}
-	WARN_ON(bo->mmu->as != as);
+	WARN_ON(bomapping->mmu->as != as);
 
 	/* Assume 2MB alignment and size multiple */
 	addr &= ~((u64)SZ_2M - 1);
 	page_offset = addr >> PAGE_SHIFT;
-	page_offset -= bo->node.start;
+	page_offset -= bomapping->mmnode.start;
 
 	mutex_lock(&bo->base.pages_lock);
 
@@ -473,7 +477,7 @@
 		pages = kvmalloc_array(bo->base.base.size >> PAGE_SHIFT,
 				       sizeof(struct page *), GFP_KERNEL | __GFP_ZERO);
 		if (!pages) {
-			kfree(bo->sgts);
+			kvfree(bo->sgts);
 			bo->sgts = NULL;
 			mutex_unlock(&bo->base.pages_lock);
 			ret = -ENOMEM;
@@ -481,18 +485,32 @@
 		}
 		bo->base.pages = pages;
 		bo->base.pages_use_count = 1;
-	} else
+	} else {
 		pages = bo->base.pages;
+		if (pages[page_offset]) {
+			/* Pages are already mapped, bail out. */
+			mutex_unlock(&bo->base.pages_lock);
+			goto out;
+		}
+	}
 
 	mapping = bo->base.base.filp->f_mapping;
 	mapping_set_unevictable(mapping);
 
 	for (i = page_offset; i < page_offset + NUM_FAULT_PAGES; i++) {
+		/* Can happen if the last fault only partially filled this
+		 * section of the pages array before failing. In that case
+		 * we skip already filled pages.
+		 */
+		if (pages[i])
+			continue;
+
 		pages[i] = shmem_read_mapping_page(mapping, i);
 		if (IS_ERR(pages[i])) {
 			mutex_unlock(&bo->base.pages_lock);
 			ret = PTR_ERR(pages[i]);
-			goto err_pages;
+			pages[i] = NULL;
+			goto err_bo;
 		}
 	}
 
@@ -502,27 +520,27 @@
 	ret = sg_alloc_table_from_pages(sgt, pages + page_offset,
 					NUM_FAULT_PAGES, 0, SZ_2M, GFP_KERNEL);
 	if (ret)
-		goto err_pages;
+		goto err_bo;
 
 	if (!dma_map_sg(pfdev->dev, sgt->sgl, sgt->nents, DMA_BIDIRECTIONAL)) {
 		ret = -EINVAL;
 		goto err_map;
 	}
 
-	mmu_map_sg(pfdev, bo->mmu, addr, IOMMU_WRITE | IOMMU_READ | IOMMU_NOEXEC, sgt);
+	mmu_map_sg(pfdev, bomapping->mmu, addr,
+		   IOMMU_WRITE | IOMMU_READ | IOMMU_NOEXEC, sgt);
 
-	bo->is_mapped = true;
+	bomapping->active = true;
 
 	dev_dbg(pfdev->dev, "mapped page fault @ AS%d %llx", as, addr);
 
-	drm_gem_object_put_unlocked(&bo->base.base);
+out:
+	panfrost_gem_mapping_put(bomapping);
 
 	return 0;
 
 err_map:
 	sg_free_table(sgt);
-err_pages:
-	drm_gem_shmem_put_pages(&bo->base);
 err_bo:
 	drm_gem_object_put_unlocked(&bo->base.base);
 	return ret;
@@ -586,36 +604,30 @@
 		access_type = (fault_status >> 8) & 0x3;
 		source_id = (fault_status >> 16);
 
-		/* Page fault only */
-		if ((status & mask) == BIT(i)) {
-			WARN_ON(exception_type < 0xC1 || exception_type > 0xC4);
+		mmu_write(pfdev, MMU_INT_CLEAR, mask);
 
+		/* Page fault only */
+		ret = -1;
+		if ((status & mask) == BIT(i) && (exception_type & 0xF8) == 0xC0)
 			ret = panfrost_mmu_map_fault_addr(pfdev, i, addr);
-			if (!ret) {
-				mmu_write(pfdev, MMU_INT_CLEAR, BIT(i));
-				status &= ~mask;
-				continue;
-			}
-		}
 
-		/* terminal fault, print info about the fault */
-		dev_err(pfdev->dev,
-			"Unhandled Page fault in AS%d at VA 0x%016llX\n"
-			"Reason: %s\n"
-			"raw fault status: 0x%X\n"
-			"decoded fault status: %s\n"
-			"exception type 0x%X: %s\n"
-			"access type 0x%X: %s\n"
-			"source id 0x%X\n",
-			i, addr,
-			"TODO",
-			fault_status,
-			(fault_status & (1 << 10) ? "DECODER FAULT" : "SLAVE FAULT"),
-			exception_type, panfrost_exception_name(pfdev, exception_type),
-			access_type, access_type_name(pfdev, fault_status),
-			source_id);
-
-		mmu_write(pfdev, MMU_INT_CLEAR, mask);
+		if (ret)
+			/* terminal fault, print info about the fault */
+			dev_err(pfdev->dev,
+				"Unhandled Page fault in AS%d at VA 0x%016llX\n"
+				"Reason: %s\n"
+				"raw fault status: 0x%X\n"
+				"decoded fault status: %s\n"
+				"exception type 0x%X: %s\n"
+				"access type 0x%X: %s\n"
+				"source id 0x%X\n",
+				i, addr,
+				"TODO",
+				fault_status,
+				(fault_status & (1 << 10) ? "DECODER FAULT" : "SLAVE FAULT"),
+				exception_type, panfrost_exception_name(pfdev, exception_type),
+				access_type, access_type_name(pfdev, fault_status),
+				source_id);
 
 		status &= ~mask;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panfrost/panfrost_mmu.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panfrost/panfrost_mmu.h
@@ -4,12 +4,12 @@
 #ifndef __PANFROST_MMU_H__
 #define __PANFROST_MMU_H__
 
-struct panfrost_gem_object;
+struct panfrost_gem_mapping;
 struct panfrost_file_priv;
 struct panfrost_mmu;
 
-int panfrost_mmu_map(struct panfrost_gem_object *bo);
-void panfrost_mmu_unmap(struct panfrost_gem_object *bo);
+int panfrost_mmu_map(struct panfrost_gem_mapping *mapping);
+void panfrost_mmu_unmap(struct panfrost_gem_mapping *mapping);
 
 int panfrost_mmu_init(struct panfrost_device *pfdev);
 void panfrost_mmu_fini(struct panfrost_device *pfdev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panfrost/panfrost_perfcnt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panfrost/panfrost_perfcnt.c
@@ -25,7 +25,7 @@
 #define V4_SHADERS_PER_COREGROUP	4
 
 struct panfrost_perfcnt {
-	struct panfrost_gem_object *bo;
+	struct panfrost_gem_mapping *mapping;
 	size_t bosize;
 	void *buf;
 	struct panfrost_file_priv *user;
@@ -49,7 +49,7 @@
 	int ret;
 
 	reinit_completion(&pfdev->perfcnt->dump_comp);
-	gpuva = pfdev->perfcnt->bo->node.start << PAGE_SHIFT;
+	gpuva = pfdev->perfcnt->mapping->mmnode.start << PAGE_SHIFT;
 	gpu_write(pfdev, GPU_PERFCNT_BASE_LO, gpuva);
 	gpu_write(pfdev, GPU_PERFCNT_BASE_HI, gpuva >> 32);
 	gpu_write(pfdev, GPU_INT_CLEAR,
@@ -67,12 +67,13 @@
 }
 
 static int panfrost_perfcnt_enable_locked(struct panfrost_device *pfdev,
-					  struct panfrost_file_priv *user,
+					  struct drm_file *file_priv,
 					  unsigned int counterset)
 {
+	struct panfrost_file_priv *user = file_priv->driver_priv;
 	struct panfrost_perfcnt *perfcnt = pfdev->perfcnt;
 	struct drm_gem_shmem_object *bo;
-	u32 cfg;
+	u32 cfg, as;
 	int ret;
 
 	if (user == perfcnt->user)
@@ -88,17 +89,22 @@
 	if (IS_ERR(bo))
 		return PTR_ERR(bo);
 
-	perfcnt->bo = to_panfrost_bo(&bo->base);
-
 	/* Map the perfcnt buf in the address space attached to file_priv. */
-	ret = panfrost_mmu_map(perfcnt->bo);
+	ret = panfrost_gem_open(&bo->base, file_priv);
 	if (ret)
 		goto err_put_bo;
 
+	perfcnt->mapping = panfrost_gem_mapping_get(to_panfrost_bo(&bo->base),
+						    user);
+	if (!perfcnt->mapping) {
+		ret = -EINVAL;
+		goto err_close_bo;
+	}
+
 	perfcnt->buf = drm_gem_shmem_vmap(&bo->base);
 	if (IS_ERR(perfcnt->buf)) {
 		ret = PTR_ERR(perfcnt->buf);
-		goto err_put_bo;
+		goto err_put_mapping;
 	}
 
 	/*
@@ -120,12 +126,8 @@
 
 	perfcnt->user = user;
 
-	/*
-	 * Always use address space 0 for now.
-	 * FIXME: this needs to be updated when we start using different
-	 * address space.
-	 */
-	cfg = GPU_PERFCNT_CFG_AS(0) |
+	as = panfrost_mmu_as_get(pfdev, perfcnt->mapping->mmu);
+	cfg = GPU_PERFCNT_CFG_AS(as) |
 	      GPU_PERFCNT_CFG_MODE(GPU_PERFCNT_CFG_MODE_MANUAL);
 
 	/*
@@ -153,18 +155,26 @@
 	if (panfrost_has_hw_issue(pfdev, HW_ISSUE_8186))
 		gpu_write(pfdev, GPU_PRFCNT_TILER_EN, 0xffffffff);
 
+	/* The BO ref is retained by the mapping. */
+	drm_gem_object_put_unlocked(&bo->base);
+
 	return 0;
 
 err_vunmap:
-	drm_gem_shmem_vunmap(&perfcnt->bo->base.base, perfcnt->buf);
+	drm_gem_shmem_vunmap(&bo->base, perfcnt->buf);
+err_put_mapping:
+	panfrost_gem_mapping_put(perfcnt->mapping);
+err_close_bo:
+	panfrost_gem_close(&bo->base, file_priv);
 err_put_bo:
 	drm_gem_object_put_unlocked(&bo->base);
 	return ret;
 }
 
 static int panfrost_perfcnt_disable_locked(struct panfrost_device *pfdev,
-					   struct panfrost_file_priv *user)
+					   struct drm_file *file_priv)
 {
+	struct panfrost_file_priv *user = file_priv->driver_priv;
 	struct panfrost_perfcnt *perfcnt = pfdev->perfcnt;
 
 	if (user != perfcnt->user)
@@ -178,10 +188,12 @@
 		  GPU_PERFCNT_CFG_MODE(GPU_PERFCNT_CFG_MODE_OFF));
 
 	perfcnt->user = NULL;
-	drm_gem_shmem_vunmap(&perfcnt->bo->base.base, perfcnt->buf);
+	drm_gem_shmem_vunmap(&perfcnt->mapping->obj->base.base, perfcnt->buf);
 	perfcnt->buf = NULL;
-	drm_gem_object_put_unlocked(&perfcnt->bo->base.base);
-	perfcnt->bo = NULL;
+	panfrost_gem_close(&perfcnt->mapping->obj->base.base, file_priv);
+	panfrost_mmu_as_put(pfdev, perfcnt->mapping->mmu);
+	panfrost_gem_mapping_put(perfcnt->mapping);
+	perfcnt->mapping = NULL;
 	pm_runtime_mark_last_busy(pfdev->dev);
 	pm_runtime_put_autosuspend(pfdev->dev);
 
@@ -191,7 +203,6 @@
 int panfrost_ioctl_perfcnt_enable(struct drm_device *dev, void *data,
 				  struct drm_file *file_priv)
 {
-	struct panfrost_file_priv *pfile = file_priv->driver_priv;
 	struct panfrost_device *pfdev = dev->dev_private;
 	struct panfrost_perfcnt *perfcnt = pfdev->perfcnt;
 	struct drm_panfrost_perfcnt_enable *req = data;
@@ -207,10 +218,10 @@
 
 	mutex_lock(&perfcnt->lock);
 	if (req->enable)
-		ret = panfrost_perfcnt_enable_locked(pfdev, pfile,
+		ret = panfrost_perfcnt_enable_locked(pfdev, file_priv,
 						     req->counterset);
 	else
-		ret = panfrost_perfcnt_disable_locked(pfdev, pfile);
+		ret = panfrost_perfcnt_disable_locked(pfdev, file_priv);
 	mutex_unlock(&perfcnt->lock);
 
 	return ret;
@@ -248,15 +259,16 @@
 	return ret;
 }
 
-void panfrost_perfcnt_close(struct panfrost_file_priv *pfile)
+void panfrost_perfcnt_close(struct drm_file *file_priv)
 {
+	struct panfrost_file_priv *pfile = file_priv->driver_priv;
 	struct panfrost_device *pfdev = pfile->pfdev;
 	struct panfrost_perfcnt *perfcnt = pfdev->perfcnt;
 
 	pm_runtime_get_sync(pfdev->dev);
 	mutex_lock(&perfcnt->lock);
 	if (perfcnt->user == pfile)
-		panfrost_perfcnt_disable_locked(pfdev, pfile);
+		panfrost_perfcnt_disable_locked(pfdev, file_priv);
 	mutex_unlock(&perfcnt->lock);
 	pm_runtime_mark_last_busy(pfdev->dev);
 	pm_runtime_put_autosuspend(pfdev->dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panfrost/panfrost_perfcnt.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panfrost/panfrost_perfcnt.h
@@ -9,7 +9,7 @@
 void panfrost_perfcnt_clean_cache_done(struct panfrost_device *pfdev);
 int panfrost_perfcnt_init(struct panfrost_device *pfdev);
 void panfrost_perfcnt_fini(struct panfrost_device *pfdev);
-void panfrost_perfcnt_close(struct panfrost_file_priv *pfile);
+void panfrost_perfcnt_close(struct drm_file *file_priv);
 int panfrost_ioctl_perfcnt_enable(struct drm_device *dev, void *data,
 				  struct drm_file *file_priv);
 int panfrost_ioctl_perfcnt_dump(struct drm_device *dev, void *data,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/panfrost/panfrost_regs.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/panfrost/panfrost_regs.h
@@ -51,6 +51,10 @@
 #define GPU_STATUS			0x34
 #define   GPU_STATUS_PRFCNT_ACTIVE	BIT(2)
 #define GPU_LATEST_FLUSH_ID		0x38
+#define GPU_PWR_KEY			0x50	/* (WO) Power manager key register */
+#define  GPU_PWR_KEY_UNLOCK		0x2968A819
+#define GPU_PWR_OVERRIDE0		0x54	/* (RW) Power manager override settings */
+#define GPU_PWR_OVERRIDE1		0x58	/* (RW) Power manager override settings */
 #define GPU_FAULT_STATUS		0x3C
 #define GPU_FAULT_ADDRESS_LO		0x40
 #define GPU_FAULT_ADDRESS_HI		0x44
@@ -314,6 +318,8 @@
 #define AS_FAULTSTATUS_ACCESS_TYPE_READ		(0x2 << 8)
 #define AS_FAULTSTATUS_ACCESS_TYPE_WRITE	(0x3 << 8)
 
+#define AS_LOCK_REGION_MIN_SIZE                 (1ULL << 15)
+
 #define gpu_write(dev, reg, data) writel(data, dev->iomem + reg)
 #define gpu_read(dev, reg) readl(dev->iomem + reg)
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/qxl/qxl_cmd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/qxl/qxl_cmd.c
@@ -480,9 +480,10 @@
 		return ret;
 
 	ret = qxl_release_reserve_list(release, true);
-	if (ret)
+	if (ret) {
+		qxl_release_free(qdev, release);
 		return ret;
-
+	}
 	cmd = (struct qxl_surface_cmd *)qxl_release_map(qdev, release);
 	cmd->type = QXL_SURFACE_CMD_CREATE;
 	cmd->flags = QXL_SURF_FLAG_KEEP_DATA;
@@ -499,8 +500,8 @@
 	/* no need to add a release to the fence for this surface bo,
 	   since it is only released when we ask to destroy the surface
 	   and it would never signal otherwise */
-	qxl_push_command_ring_release(qdev, release, QXL_CMD_SURFACE, false);
 	qxl_release_fence_buffer_objects(release);
+	qxl_push_command_ring_release(qdev, release, QXL_CMD_SURFACE, false);
 
 	surf->hw_surf_alloc = true;
 	spin_lock(&qdev->surf_id_idr_lock);
@@ -542,9 +543,8 @@
 	cmd->surface_id = id;
 	qxl_release_unmap(qdev, release, &cmd->release_info);
 
-	qxl_push_command_ring_release(qdev, release, QXL_CMD_SURFACE, false);
-
 	qxl_release_fence_buffer_objects(release);
+	qxl_push_command_ring_release(qdev, release, QXL_CMD_SURFACE, false);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/qxl/qxl_display.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/qxl/qxl_display.c
@@ -230,6 +230,9 @@
 		return 0;
 
 	mode = drm_cvt_mode(dev, width, height, 60, false, false, false);
+	if (!mode)
+		return 0;
+
 	if (preferred)
 		mode->type |= DRM_MODE_TYPE_PREFERRED;
 	mode->hdisplay = width;
@@ -325,6 +328,7 @@
 
 	head.id = i;
 	head.flags = 0;
+	head.surface_id = 0;
 	oldcount = qdev->monitors_config->count;
 	if (crtc->state->active) {
 		struct drm_display_mode *mode = &crtc->mode;
@@ -523,8 +527,8 @@
 	cmd->u.set.visible = 1;
 	qxl_release_unmap(qdev, release, &cmd->release_info);
 
-	qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
 	qxl_release_fence_buffer_objects(release);
+	qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
 
 	return ret;
 
@@ -665,8 +669,8 @@
 	cmd->u.position.y = plane->state->crtc_y + fb->hot_y;
 
 	qxl_release_unmap(qdev, release, &cmd->release_info);
-	qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
 	qxl_release_fence_buffer_objects(release);
+	qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
 
 	if (old_cursor_bo != NULL)
 		qxl_bo_unpin(old_cursor_bo);
@@ -713,8 +717,8 @@
 	cmd->type = QXL_CURSOR_HIDE;
 	qxl_release_unmap(qdev, release, &cmd->release_info);
 
-	qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
 	qxl_release_fence_buffer_objects(release);
+	qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
 }
 
 static void qxl_update_dumb_head(struct qxl_device *qdev,
@@ -1236,6 +1240,10 @@
 
 void qxl_modeset_fini(struct qxl_device *qdev)
 {
+	if (qdev->dumb_shadow_bo) {
+		drm_gem_object_put(&qdev->dumb_shadow_bo->tbo.base);
+		qdev->dumb_shadow_bo = NULL;
+	}
 	qxl_destroy_monitors_object(qdev);
 	drm_mode_config_cleanup(&qdev->ddev);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/qxl/qxl_draw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/qxl/qxl_draw.c
@@ -209,9 +209,10 @@
 		goto out_release_backoff;
 
 	rects = drawable_set_clipping(qdev, num_clips, clips_bo);
-	if (!rects)
+	if (!rects) {
+		ret = -EINVAL;
 		goto out_release_backoff;
-
+	}
 	drawable = (struct qxl_drawable *)qxl_release_map(qdev, release);
 
 	drawable->clip.type = SPICE_CLIP_TYPE_RECTS;
@@ -242,8 +243,8 @@
 	}
 	qxl_bo_kunmap(clips_bo);
 
-	qxl_push_command_ring_release(qdev, release, QXL_CMD_DRAW, false);
 	qxl_release_fence_buffer_objects(release);
+	qxl_push_command_ring_release(qdev, release, QXL_CMD_DRAW, false);
 
 out_release_backoff:
 	if (ret)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/qxl/qxl_dumb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/qxl/qxl_dumb.c
@@ -58,6 +58,8 @@
 	surf.height = args->height;
 	surf.stride = pitch;
 	surf.format = format;
+	surf.data = 0;
+
 	r = qxl_gem_object_create_with_handle(qdev, file_priv,
 					      QXL_GEM_DOMAIN_SURFACE,
 					      args->size, &surf, &qobj,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/qxl/qxl_image.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/qxl/qxl_image.c
@@ -212,7 +212,8 @@
 		break;
 	default:
 		DRM_ERROR("unsupported image bit depth\n");
-		return -EINVAL; /* TODO: cleanup */
+		qxl_bo_kunmap_atomic_page(qdev, image_bo, ptr);
+		return -EINVAL;
 	}
 	image->u.bitmap.flags = QXL_BITMAP_TOP_DOWN;
 	image->u.bitmap.x = width;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/qxl/qxl_ioctl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/qxl/qxl_ioctl.c
@@ -261,11 +261,8 @@
 			apply_surf_reloc(qdev, &reloc_info[i]);
 	}
 
+	qxl_release_fence_buffer_objects(release);
 	ret = qxl_push_command_ring_release(qdev, release, cmd->type, true);
-	if (ret)
-		qxl_release_backoff_reserve_list(release);
-	else
-		qxl_release_fence_buffer_objects(release);
 
 out_free_bos:
 out_free_release:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/qxl/qxl_kms.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/qxl/qxl_kms.c
@@ -184,7 +184,7 @@
 
 	if (!qxl_check_device(qdev)) {
 		r = -ENODEV;
-		goto surface_mapping_free;
+		goto rom_unmap;
 	}
 
 	r = qxl_bo_init(qdev);
@@ -218,7 +218,7 @@
 				&(qdev->ram_header->cursor_ring_hdr),
 				sizeof(struct qxl_command),
 				QXL_CURSOR_RING_SIZE,
-				qdev->io_base + QXL_IO_NOTIFY_CMD,
+				qdev->io_base + QXL_IO_NOTIFY_CURSOR,
 				false,
 				&qdev->cursor_event);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/atombios.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/atombios.h
@@ -3615,7 +3615,7 @@
 {
   UCHAR ucRecordType;
   UCHAR ucFakeEDIDLength;
-  UCHAR ucFakeEDIDString[1];    // This actually has ucFakeEdidLength elements.
+  UCHAR ucFakeEDIDString[];    // This actually has ucFakeEdidLength elements.
 } ATOM_FAKE_EDID_PATCH_RECORD;
 
 typedef struct  _ATOM_PANEL_RESOLUTION_PATCH_RECORD
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/atombios_encoders.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/atombios_encoders.c
@@ -197,7 +197,8 @@
 	 * so don't register a backlight device
 	 */
 	if ((rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE) &&
-	    (rdev->pdev->device == 0x6741))
+	    (rdev->pdev->device == 0x6741) &&
+	    !dmi_match(DMI_PRODUCT_NAME, "iMac12,1"))
 		return;
 
 	if (!radeon_encoder->enc_priv)
@@ -2191,11 +2192,12 @@
 
 	/*
 	 * On DCE32 any encoder can drive any block so usually just use crtc id,
-	 * but Apple thinks different at least on iMac10,1, so there use linkb,
+	 * but Apple thinks different at least on iMac10,1 and iMac11,2, so there use linkb,
 	 * otherwise the internal eDP panel will stay dark.
 	 */
 	if (ASIC_IS_DCE32(rdev)) {
-		if (dmi_match(DMI_PRODUCT_NAME, "iMac10,1"))
+		if (dmi_match(DMI_PRODUCT_NAME, "iMac10,1") ||
+		    dmi_match(DMI_PRODUCT_NAME, "iMac11,2"))
 			enc_idx = (dig->linkb) ? 1 : 0;
 		else
 			enc_idx = radeon_crtc->crtc_id;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/ci_dpm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/ci_dpm.c
@@ -4366,7 +4366,7 @@
 					table->mc_reg_table_entry[k].mc_data[j] |= 0x100;
 			}
 			j++;
-			if (j > SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE)
+			if (j >= SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE)
 				return -EINVAL;
 
 			if (!pi->mem_gddr5) {
@@ -5556,6 +5556,7 @@
 	u8 frev, crev;
 	u8 *power_state_offset;
 	struct ci_ps *ps;
+	int ret;
 
 	if (!atom_parse_data_header(mode_info->atom_context, index, NULL,
 				   &frev, &crev, &data_offset))
@@ -5578,18 +5579,21 @@
 	if (!rdev->pm.dpm.ps)
 		return -ENOMEM;
 	power_state_offset = (u8 *)state_array->states;
+	rdev->pm.dpm.num_ps = 0;
 	for (i = 0; i < state_array->ucNumEntries; i++) {
 		u8 *idx;
 		power_state = (union pplib_power_state *)power_state_offset;
 		non_clock_array_index = power_state->v2.nonClockInfoIndex;
 		non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
 			&non_clock_info_array->nonClockInfo[non_clock_array_index];
-		if (!rdev->pm.power_state[i].clock_info)
-			return -EINVAL;
+		if (!rdev->pm.power_state[i].clock_info) {
+			ret = -EINVAL;
+			goto err_free_ps;
+		}
 		ps = kzalloc(sizeof(struct ci_ps), GFP_KERNEL);
 		if (ps == NULL) {
-			kfree(rdev->pm.dpm.ps);
-			return -ENOMEM;
+			ret = -ENOMEM;
+			goto err_free_ps;
 		}
 		rdev->pm.dpm.ps[i].ps_priv = ps;
 		ci_parse_pplib_non_clock_info(rdev, &rdev->pm.dpm.ps[i],
@@ -5612,8 +5616,8 @@
 			k++;
 		}
 		power_state_offset += 2 + power_state->v2.ucNumDPMLevels;
+		rdev->pm.dpm.num_ps = i + 1;
 	}
-	rdev->pm.dpm.num_ps = state_array->ucNumEntries;
 
 	/* fill in the vce power states */
 	for (i = 0; i < RADEON_MAX_VCE_LEVELS; i++) {
@@ -5630,6 +5634,12 @@
 	}
 
 	return 0;
+
+err_free_ps:
+	for (i = 0; i < rdev->pm.dpm.num_ps; i++)
+		kfree(rdev->pm.dpm.ps[i].ps_priv);
+	kfree(rdev->pm.dpm.ps);
+	return ret;
 }
 
 static int ci_get_vbios_boot_values(struct radeon_device *rdev,
@@ -5718,25 +5728,26 @@
 
 	ret = ci_get_vbios_boot_values(rdev, &pi->vbios_boot_state);
 	if (ret) {
-		ci_dpm_fini(rdev);
+		kfree(rdev->pm.dpm.priv);
 		return ret;
 	}
 
 	ret = r600_get_platform_caps(rdev);
 	if (ret) {
-		ci_dpm_fini(rdev);
+		kfree(rdev->pm.dpm.priv);
 		return ret;
 	}
 
 	ret = r600_parse_extended_power_table(rdev);
 	if (ret) {
-		ci_dpm_fini(rdev);
+		kfree(rdev->pm.dpm.priv);
 		return ret;
 	}
 
 	ret = ci_parse_power_table(rdev);
 	if (ret) {
-		ci_dpm_fini(rdev);
+		kfree(rdev->pm.dpm.priv);
+		r600_free_extended_power_table(rdev);
 		return ret;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/cik.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/cik.c
@@ -6969,8 +6969,8 @@
 	}
 
 	/* setup interrupt control */
-	/* XXX this should actually be a bus address, not an MC address. same on older asics */
-	WREG32(INTERRUPT_CNTL2, rdev->ih.gpu_addr >> 8);
+	/* set dummy read address to dummy page address */
+	WREG32(INTERRUPT_CNTL2, rdev->dummy_page.addr >> 8);
 	interrupt_cntl = RREG32(INTERRUPT_CNTL);
 	/* IH_DUMMY_RD_OVERRIDE=0 - dummy read disabled with msi, enabled without msi
 	 * IH_DUMMY_RD_OVERRIDE=1 - dummy read controlled by IH_DUMMY_RD_EN
@@ -9504,7 +9504,6 @@
 {
 	struct pci_dev *root = rdev->pdev->bus->self;
 	enum pci_bus_speed speed_cap;
-	int bridge_pos, gpu_pos;
 	u32 speed_cntl, current_data_rate;
 	int i;
 	u16 tmp16;
@@ -9546,12 +9545,7 @@
 		DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n");
 	}
 
-	bridge_pos = pci_pcie_cap(root);
-	if (!bridge_pos)
-		return;
-
-	gpu_pos = pci_pcie_cap(rdev->pdev);
-	if (!gpu_pos)
+	if (!pci_is_pcie(root) || !pci_is_pcie(rdev->pdev))
 		return;
 
 	if (speed_cap == PCIE_SPEED_8_0GT) {
@@ -9561,14 +9555,8 @@
 			u16 bridge_cfg2, gpu_cfg2;
 			u32 max_lw, current_lw, tmp;
 
-			pci_read_config_word(root, bridge_pos + PCI_EXP_LNKCTL, &bridge_cfg);
-			pci_read_config_word(rdev->pdev, gpu_pos + PCI_EXP_LNKCTL, &gpu_cfg);
-
-			tmp16 = bridge_cfg | PCI_EXP_LNKCTL_HAWD;
-			pci_write_config_word(root, bridge_pos + PCI_EXP_LNKCTL, tmp16);
-
-			tmp16 = gpu_cfg | PCI_EXP_LNKCTL_HAWD;
-			pci_write_config_word(rdev->pdev, gpu_pos + PCI_EXP_LNKCTL, tmp16);
+			pcie_capability_set_word(root, PCI_EXP_LNKCTL, PCI_EXP_LNKCTL_HAWD);
+			pcie_capability_set_word(rdev->pdev, PCI_EXP_LNKCTL, PCI_EXP_LNKCTL_HAWD);
 
 			tmp = RREG32_PCIE_PORT(PCIE_LC_STATUS1);
 			max_lw = (tmp & LC_DETECTED_LINK_WIDTH_MASK) >> LC_DETECTED_LINK_WIDTH_SHIFT;
@@ -9586,15 +9574,23 @@
 
 			for (i = 0; i < 10; i++) {
 				/* check status */
-				pci_read_config_word(rdev->pdev, gpu_pos + PCI_EXP_DEVSTA, &tmp16);
+				pcie_capability_read_word(rdev->pdev,
+							  PCI_EXP_DEVSTA,
+							  &tmp16);
 				if (tmp16 & PCI_EXP_DEVSTA_TRPND)
 					break;
 
-				pci_read_config_word(root, bridge_pos + PCI_EXP_LNKCTL, &bridge_cfg);
-				pci_read_config_word(rdev->pdev, gpu_pos + PCI_EXP_LNKCTL, &gpu_cfg);
-
-				pci_read_config_word(root, bridge_pos + PCI_EXP_LNKCTL2, &bridge_cfg2);
-				pci_read_config_word(rdev->pdev, gpu_pos + PCI_EXP_LNKCTL2, &gpu_cfg2);
+				pcie_capability_read_word(root, PCI_EXP_LNKCTL,
+							  &bridge_cfg);
+				pcie_capability_read_word(rdev->pdev,
+							  PCI_EXP_LNKCTL,
+							  &gpu_cfg);
+
+				pcie_capability_read_word(root, PCI_EXP_LNKCTL2,
+							  &bridge_cfg2);
+				pcie_capability_read_word(rdev->pdev,
+							  PCI_EXP_LNKCTL2,
+							  &gpu_cfg2);
 
 				tmp = RREG32_PCIE_PORT(PCIE_LC_CNTL4);
 				tmp |= LC_SET_QUIESCE;
@@ -9607,26 +9603,38 @@
 				msleep(100);
 
 				/* linkctl */
-				pci_read_config_word(root, bridge_pos + PCI_EXP_LNKCTL, &tmp16);
-				tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
-				tmp16 |= (bridge_cfg & PCI_EXP_LNKCTL_HAWD);
-				pci_write_config_word(root, bridge_pos + PCI_EXP_LNKCTL, tmp16);
-
-				pci_read_config_word(rdev->pdev, gpu_pos + PCI_EXP_LNKCTL, &tmp16);
-				tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
-				tmp16 |= (gpu_cfg & PCI_EXP_LNKCTL_HAWD);
-				pci_write_config_word(rdev->pdev, gpu_pos + PCI_EXP_LNKCTL, tmp16);
+				pcie_capability_clear_and_set_word(root, PCI_EXP_LNKCTL,
+								   PCI_EXP_LNKCTL_HAWD,
+								   bridge_cfg &
+								   PCI_EXP_LNKCTL_HAWD);
+				pcie_capability_clear_and_set_word(rdev->pdev, PCI_EXP_LNKCTL,
+								   PCI_EXP_LNKCTL_HAWD,
+								   gpu_cfg &
+								   PCI_EXP_LNKCTL_HAWD);
 
 				/* linkctl2 */
-				pci_read_config_word(root, bridge_pos + PCI_EXP_LNKCTL2, &tmp16);
-				tmp16 &= ~((1 << 4) | (7 << 9));
-				tmp16 |= (bridge_cfg2 & ((1 << 4) | (7 << 9)));
-				pci_write_config_word(root, bridge_pos + PCI_EXP_LNKCTL2, tmp16);
-
-				pci_read_config_word(rdev->pdev, gpu_pos + PCI_EXP_LNKCTL2, &tmp16);
-				tmp16 &= ~((1 << 4) | (7 << 9));
-				tmp16 |= (gpu_cfg2 & ((1 << 4) | (7 << 9)));
-				pci_write_config_word(rdev->pdev, gpu_pos + PCI_EXP_LNKCTL2, tmp16);
+				pcie_capability_read_word(root, PCI_EXP_LNKCTL2,
+							  &tmp16);
+				tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
+					   PCI_EXP_LNKCTL2_TX_MARGIN);
+				tmp16 |= (bridge_cfg2 &
+					  (PCI_EXP_LNKCTL2_ENTER_COMP |
+					   PCI_EXP_LNKCTL2_TX_MARGIN));
+				pcie_capability_write_word(root,
+							   PCI_EXP_LNKCTL2,
+							   tmp16);
+
+				pcie_capability_read_word(rdev->pdev,
+							  PCI_EXP_LNKCTL2,
+							  &tmp16);
+				tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
+					   PCI_EXP_LNKCTL2_TX_MARGIN);
+				tmp16 |= (gpu_cfg2 &
+					  (PCI_EXP_LNKCTL2_ENTER_COMP |
+					   PCI_EXP_LNKCTL2_TX_MARGIN));
+				pcie_capability_write_word(rdev->pdev,
+							   PCI_EXP_LNKCTL2,
+							   tmp16);
 
 				tmp = RREG32_PCIE_PORT(PCIE_LC_CNTL4);
 				tmp &= ~LC_SET_QUIESCE;
@@ -9640,15 +9648,15 @@
 	speed_cntl &= ~LC_FORCE_DIS_SW_SPEED_CHANGE;
 	WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, speed_cntl);
 
-	pci_read_config_word(rdev->pdev, gpu_pos + PCI_EXP_LNKCTL2, &tmp16);
-	tmp16 &= ~0xf;
+	pcie_capability_read_word(rdev->pdev, PCI_EXP_LNKCTL2, &tmp16);
+	tmp16 &= ~PCI_EXP_LNKCTL2_TLS;
 	if (speed_cap == PCIE_SPEED_8_0GT)
-		tmp16 |= 3; /* gen3 */
+		tmp16 |= PCI_EXP_LNKCTL2_TLS_8_0GT; /* gen3 */
 	else if (speed_cap == PCIE_SPEED_5_0GT)
-		tmp16 |= 2; /* gen2 */
+		tmp16 |= PCI_EXP_LNKCTL2_TLS_5_0GT; /* gen2 */
 	else
-		tmp16 |= 1; /* gen1 */
-	pci_write_config_word(rdev->pdev, gpu_pos + PCI_EXP_LNKCTL2, tmp16);
+		tmp16 |= PCI_EXP_LNKCTL2_TLS_2_5GT; /* gen1 */
+	pcie_capability_write_word(rdev->pdev, PCI_EXP_LNKCTL2, tmp16);
 
 	speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL);
 	speed_cntl |= LC_INITIATE_LINK_SPEED_CHANGE;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/cypress_dpm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/cypress_dpm.c
@@ -559,8 +559,12 @@
 						     ASIC_INTERNAL_MEMORY_SS, vco_freq)) {
 			u32 reference_clock = rdev->clock.mpll.reference_freq;
 			u32 decoded_ref = rv740_get_decoded_reference_divider(dividers.ref_div);
-			u32 clk_s = reference_clock * 5 / (decoded_ref * ss.rate);
-			u32 clk_v = ss.percentage *
+			u32 clk_s, clk_v;
+
+			if (!decoded_ref)
+				return -EINVAL;
+			clk_s = reference_clock * 5 / (decoded_ref * ss.rate);
+			clk_v = ss.percentage *
 				(0x4000 * dividers.whole_fb_div + 0x800 * dividers.frac_fb_div) / (clk_s * 625);
 
 			mpll_ss1 &= ~CLKV_MASK;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/evergreen.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/evergreen.c
@@ -4819,14 +4819,15 @@
 			break;
 		case 44: /* hdmi */
 			afmt_idx = src_data;
-			if (!(afmt_status[afmt_idx] & AFMT_AZ_FORMAT_WTRIG))
-				DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
-
 			if (afmt_idx > 5) {
 				DRM_ERROR("Unhandled interrupt: %d %d\n",
 					  src_id, src_data);
 				break;
 			}
+
+			if (!(afmt_status[afmt_idx] & AFMT_AZ_FORMAT_WTRIG))
+				DRM_DEBUG("IH: IH event w/o asserted irq bit?\n");
+
 			afmt_status[afmt_idx] &= ~AFMT_AZ_FORMAT_WTRIG;
 			queue_hdmi = true;
 			DRM_DEBUG("IH: HDMI%d\n", afmt_idx + 1);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/evergreen_cs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/evergreen_cs.c
@@ -396,7 +396,7 @@
 	struct evergreen_cs_track *track = p->track;
 	struct eg_surface surf;
 	unsigned pitch, slice, mslice;
-	unsigned long offset;
+	u64 offset;
 	int r;
 
 	mslice = G_028C6C_SLICE_MAX(track->cb_color_view[id]) + 1;
@@ -434,14 +434,14 @@
 		return r;
 	}
 
-	offset = track->cb_color_bo_offset[id] << 8;
+	offset = (u64)track->cb_color_bo_offset[id] << 8;
 	if (offset & (surf.base_align - 1)) {
-		dev_warn(p->dev, "%s:%d cb[%d] bo base %ld not aligned with %ld\n",
+		dev_warn(p->dev, "%s:%d cb[%d] bo base %llu not aligned with %ld\n",
 			 __func__, __LINE__, id, offset, surf.base_align);
 		return -EINVAL;
 	}
 
-	offset += surf.layer_size * mslice;
+	offset += (u64)surf.layer_size * mslice;
 	if (offset > radeon_bo_size(track->cb_color_bo[id])) {
 		/* old ddx are broken they allocate bo with w*h*bpp but
 		 * program slice with ALIGN(h, 8), catch this and patch
@@ -449,14 +449,14 @@
 		 */
 		if (!surf.mode) {
 			uint32_t *ib = p->ib.ptr;
-			unsigned long tmp, nby, bsize, size, min = 0;
+			u64 tmp, nby, bsize, size, min = 0;
 
 			/* find the height the ddx wants */
 			if (surf.nby > 8) {
 				min = surf.nby - 8;
 			}
 			bsize = radeon_bo_size(track->cb_color_bo[id]);
-			tmp = track->cb_color_bo_offset[id] << 8;
+			tmp = (u64)track->cb_color_bo_offset[id] << 8;
 			for (nby = surf.nby; nby > min; nby--) {
 				size = nby * surf.nbx * surf.bpe * surf.nsamples;
 				if ((tmp + size * mslice) <= bsize) {
@@ -468,7 +468,7 @@
 				slice = ((nby * surf.nbx) / 64) - 1;
 				if (!evergreen_surface_check(p, &surf, "cb")) {
 					/* check if this one works */
-					tmp += surf.layer_size * mslice;
+					tmp += (u64)surf.layer_size * mslice;
 					if (tmp <= bsize) {
 						ib[track->cb_color_slice_idx[id]] = slice;
 						goto old_ddx_ok;
@@ -477,9 +477,9 @@
 			}
 		}
 		dev_warn(p->dev, "%s:%d cb[%d] bo too small (layer size %d, "
-			 "offset %d, max layer %d, bo size %ld, slice %d)\n",
+			 "offset %llu, max layer %d, bo size %ld, slice %d)\n",
 			 __func__, __LINE__, id, surf.layer_size,
-			track->cb_color_bo_offset[id] << 8, mslice,
+			(u64)track->cb_color_bo_offset[id] << 8, mslice,
 			radeon_bo_size(track->cb_color_bo[id]), slice);
 		dev_warn(p->dev, "%s:%d problematic surf: (%d %d) (%d %d %d %d %d %d %d)\n",
 			 __func__, __LINE__, surf.nbx, surf.nby,
@@ -563,7 +563,7 @@
 	struct evergreen_cs_track *track = p->track;
 	struct eg_surface surf;
 	unsigned pitch, slice, mslice;
-	unsigned long offset;
+	u64 offset;
 	int r;
 
 	mslice = G_028008_SLICE_MAX(track->db_depth_view) + 1;
@@ -609,18 +609,18 @@
 		return r;
 	}
 
-	offset = track->db_s_read_offset << 8;
+	offset = (u64)track->db_s_read_offset << 8;
 	if (offset & (surf.base_align - 1)) {
-		dev_warn(p->dev, "%s:%d stencil read bo base %ld not aligned with %ld\n",
+		dev_warn(p->dev, "%s:%d stencil read bo base %llu not aligned with %ld\n",
 			 __func__, __LINE__, offset, surf.base_align);
 		return -EINVAL;
 	}
-	offset += surf.layer_size * mslice;
+	offset += (u64)surf.layer_size * mslice;
 	if (offset > radeon_bo_size(track->db_s_read_bo)) {
 		dev_warn(p->dev, "%s:%d stencil read bo too small (layer size %d, "
-			 "offset %ld, max layer %d, bo size %ld)\n",
+			 "offset %llu, max layer %d, bo size %ld)\n",
 			 __func__, __LINE__, surf.layer_size,
-			(unsigned long)track->db_s_read_offset << 8, mslice,
+			(u64)track->db_s_read_offset << 8, mslice,
 			radeon_bo_size(track->db_s_read_bo));
 		dev_warn(p->dev, "%s:%d stencil invalid (0x%08x 0x%08x 0x%08x 0x%08x)\n",
 			 __func__, __LINE__, track->db_depth_size,
@@ -628,18 +628,18 @@
 		return -EINVAL;
 	}
 
-	offset = track->db_s_write_offset << 8;
+	offset = (u64)track->db_s_write_offset << 8;
 	if (offset & (surf.base_align - 1)) {
-		dev_warn(p->dev, "%s:%d stencil write bo base %ld not aligned with %ld\n",
+		dev_warn(p->dev, "%s:%d stencil write bo base %llu not aligned with %ld\n",
 			 __func__, __LINE__, offset, surf.base_align);
 		return -EINVAL;
 	}
-	offset += surf.layer_size * mslice;
+	offset += (u64)surf.layer_size * mslice;
 	if (offset > radeon_bo_size(track->db_s_write_bo)) {
 		dev_warn(p->dev, "%s:%d stencil write bo too small (layer size %d, "
-			 "offset %ld, max layer %d, bo size %ld)\n",
+			 "offset %llu, max layer %d, bo size %ld)\n",
 			 __func__, __LINE__, surf.layer_size,
-			(unsigned long)track->db_s_write_offset << 8, mslice,
+			(u64)track->db_s_write_offset << 8, mslice,
 			radeon_bo_size(track->db_s_write_bo));
 		return -EINVAL;
 	}
@@ -660,7 +660,7 @@
 	struct evergreen_cs_track *track = p->track;
 	struct eg_surface surf;
 	unsigned pitch, slice, mslice;
-	unsigned long offset;
+	u64 offset;
 	int r;
 
 	mslice = G_028008_SLICE_MAX(track->db_depth_view) + 1;
@@ -707,34 +707,34 @@
 		return r;
 	}
 
-	offset = track->db_z_read_offset << 8;
+	offset = (u64)track->db_z_read_offset << 8;
 	if (offset & (surf.base_align - 1)) {
-		dev_warn(p->dev, "%s:%d stencil read bo base %ld not aligned with %ld\n",
+		dev_warn(p->dev, "%s:%d stencil read bo base %llu not aligned with %ld\n",
 			 __func__, __LINE__, offset, surf.base_align);
 		return -EINVAL;
 	}
-	offset += surf.layer_size * mslice;
+	offset += (u64)surf.layer_size * mslice;
 	if (offset > radeon_bo_size(track->db_z_read_bo)) {
 		dev_warn(p->dev, "%s:%d depth read bo too small (layer size %d, "
-			 "offset %ld, max layer %d, bo size %ld)\n",
+			 "offset %llu, max layer %d, bo size %ld)\n",
 			 __func__, __LINE__, surf.layer_size,
-			(unsigned long)track->db_z_read_offset << 8, mslice,
+			(u64)track->db_z_read_offset << 8, mslice,
 			radeon_bo_size(track->db_z_read_bo));
 		return -EINVAL;
 	}
 
-	offset = track->db_z_write_offset << 8;
+	offset = (u64)track->db_z_write_offset << 8;
 	if (offset & (surf.base_align - 1)) {
-		dev_warn(p->dev, "%s:%d stencil write bo base %ld not aligned with %ld\n",
+		dev_warn(p->dev, "%s:%d stencil write bo base %llu not aligned with %ld\n",
 			 __func__, __LINE__, offset, surf.base_align);
 		return -EINVAL;
 	}
-	offset += surf.layer_size * mslice;
+	offset += (u64)surf.layer_size * mslice;
 	if (offset > radeon_bo_size(track->db_z_write_bo)) {
 		dev_warn(p->dev, "%s:%d depth write bo too small (layer size %d, "
-			 "offset %ld, max layer %d, bo size %ld)\n",
+			 "offset %llu, max layer %d, bo size %ld)\n",
 			 __func__, __LINE__, surf.layer_size,
-			(unsigned long)track->db_z_write_offset << 8, mslice,
+			(u64)track->db_z_write_offset << 8, mslice,
 			radeon_bo_size(track->db_z_write_bo));
 		return -EINVAL;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/ni.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/ni.c
@@ -826,7 +826,7 @@
 			err = 0;
 		} else if (rdev->smc_fw->size != smc_req_size) {
 			pr_err("ni_mc: Bogus length %zu in firmware \"%s\"\n",
-			       rdev->mc_fw->size, fw_name);
+			       rdev->smc_fw->size, fw_name);
 			err = -EINVAL;
 		}
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/ni_dpm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/ni_dpm.c
@@ -2128,7 +2128,7 @@
 		if (clk_s & ~(SMC_NISLANDS_SPLL_DIV_TABLE_CLKS_MASK >> SMC_NISLANDS_SPLL_DIV_TABLE_CLKS_SHIFT))
 			ret = -EINVAL;
 
-		if (clk_s & ~(SMC_NISLANDS_SPLL_DIV_TABLE_CLKS_MASK >> SMC_NISLANDS_SPLL_DIV_TABLE_CLKS_SHIFT))
+		if (fb_div & ~(SMC_NISLANDS_SPLL_DIV_TABLE_FBDIV_MASK >> SMC_NISLANDS_SPLL_DIV_TABLE_FBDIV_SHIFT))
 			ret = -EINVAL;
 
 		if (clk_v & ~(SMC_NISLANDS_SPLL_DIV_TABLE_CLKV_MASK >> SMC_NISLANDS_SPLL_DIV_TABLE_CLKV_SHIFT))
@@ -2241,8 +2241,12 @@
 						     ASIC_INTERNAL_MEMORY_SS, vco_freq)) {
 			u32 reference_clock = rdev->clock.mpll.reference_freq;
 			u32 decoded_ref = rv740_get_decoded_reference_divider(dividers.ref_div);
-			u32 clk_s = reference_clock * 5 / (decoded_ref * ss.rate);
-			u32 clk_v = ss.percentage *
+			u32 clk_s, clk_v;
+
+			if (!decoded_ref)
+				return -EINVAL;
+			clk_s = reference_clock * 5 / (decoded_ref * ss.rate);
+			clk_v = ss.percentage *
 				(0x4000 * dividers.whole_fb_div + 0x800 * dividers.frac_fb_div) / (clk_s * 625);
 
 			mpll_ss1 &= ~CLKV_MASK;
@@ -2740,10 +2744,10 @@
 					table->mc_reg_table_entry[k].mc_data[j] |= 0x100;
 			}
 			j++;
-			if (j > SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE)
-				return -EINVAL;
 			break;
 		case MC_SEQ_RESERVE_M >> 2:
+			if (j >= SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE)
+				return -EINVAL;
 			temp_reg = RREG32(MC_PMG_CMD_MRS1);
 			table->mc_reg_address[j].s1 = MC_PMG_CMD_MRS1 >> 2;
 			table->mc_reg_address[j].s0 = MC_SEQ_PMG_CMD_MRS1_LP >> 2;
@@ -2752,8 +2756,6 @@
 					(temp_reg & 0xffff0000) |
 					(table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff);
 			j++;
-			if (j > SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE)
-				return -EINVAL;
 			break;
 		default:
 			break;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/r100.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/r100.c
@@ -1005,45 +1005,65 @@
 
 	DRM_DEBUG_KMS("\n");
 
-	if ((rdev->family == CHIP_R100) || (rdev->family == CHIP_RV100) ||
-	    (rdev->family == CHIP_RV200) || (rdev->family == CHIP_RS100) ||
-	    (rdev->family == CHIP_RS200)) {
+	switch (rdev->family) {
+	case CHIP_R100:
+	case CHIP_RV100:
+	case CHIP_RV200:
+	case CHIP_RS100:
+	case CHIP_RS200:
 		DRM_INFO("Loading R100 Microcode\n");
 		fw_name = FIRMWARE_R100;
-	} else if ((rdev->family == CHIP_R200) ||
-		   (rdev->family == CHIP_RV250) ||
-		   (rdev->family == CHIP_RV280) ||
-		   (rdev->family == CHIP_RS300)) {
+		break;
+
+	case CHIP_R200:
+	case CHIP_RV250:
+	case CHIP_RV280:
+	case CHIP_RS300:
 		DRM_INFO("Loading R200 Microcode\n");
 		fw_name = FIRMWARE_R200;
-	} else if ((rdev->family == CHIP_R300) ||
-		   (rdev->family == CHIP_R350) ||
-		   (rdev->family == CHIP_RV350) ||
-		   (rdev->family == CHIP_RV380) ||
-		   (rdev->family == CHIP_RS400) ||
-		   (rdev->family == CHIP_RS480)) {
+		break;
+
+	case CHIP_R300:
+	case CHIP_R350:
+	case CHIP_RV350:
+	case CHIP_RV380:
+	case CHIP_RS400:
+	case CHIP_RS480:
 		DRM_INFO("Loading R300 Microcode\n");
 		fw_name = FIRMWARE_R300;
-	} else if ((rdev->family == CHIP_R420) ||
-		   (rdev->family == CHIP_R423) ||
-		   (rdev->family == CHIP_RV410)) {
+		break;
+
+	case CHIP_R420:
+	case CHIP_R423:
+	case CHIP_RV410:
 		DRM_INFO("Loading R400 Microcode\n");
 		fw_name = FIRMWARE_R420;
-	} else if ((rdev->family == CHIP_RS690) ||
-		   (rdev->family == CHIP_RS740)) {
+		break;
+
+	case CHIP_RS690:
+	case CHIP_RS740:
 		DRM_INFO("Loading RS690/RS740 Microcode\n");
 		fw_name = FIRMWARE_RS690;
-	} else if (rdev->family == CHIP_RS600) {
+		break;
+
+	case CHIP_RS600:
 		DRM_INFO("Loading RS600 Microcode\n");
 		fw_name = FIRMWARE_RS600;
-	} else if ((rdev->family == CHIP_RV515) ||
-		   (rdev->family == CHIP_R520) ||
-		   (rdev->family == CHIP_RV530) ||
-		   (rdev->family == CHIP_R580) ||
-		   (rdev->family == CHIP_RV560) ||
-		   (rdev->family == CHIP_RV570)) {
+		break;
+
+	case CHIP_RV515:
+	case CHIP_R520:
+	case CHIP_RV530:
+	case CHIP_R580:
+	case CHIP_RV560:
+	case CHIP_RV570:
 		DRM_INFO("Loading R500 Microcode\n");
 		fw_name = FIRMWARE_R520;
+		break;
+
+	default:
+		DRM_ERROR("Unsupported Radeon family %u\n", rdev->family);
+		return -EINVAL;
 	}
 
 	err = request_firmware(&rdev->me_fw, fw_name, rdev->dev);
@@ -1826,8 +1846,8 @@
 			track->textures[i].use_pitch = 1;
 		} else {
 			track->textures[i].use_pitch = 0;
-			track->textures[i].width = 1 << ((idx_value >> RADEON_TXFORMAT_WIDTH_SHIFT) & RADEON_TXFORMAT_WIDTH_MASK);
-			track->textures[i].height = 1 << ((idx_value >> RADEON_TXFORMAT_HEIGHT_SHIFT) & RADEON_TXFORMAT_HEIGHT_MASK);
+			track->textures[i].width = 1 << ((idx_value & RADEON_TXFORMAT_WIDTH_MASK) >> RADEON_TXFORMAT_WIDTH_SHIFT);
+			track->textures[i].height = 1 << ((idx_value & RADEON_TXFORMAT_HEIGHT_MASK) >> RADEON_TXFORMAT_HEIGHT_SHIFT);
 		}
 		if (idx_value & RADEON_TXFORMAT_CUBIC_MAP_ENABLE)
 			track->textures[i].tex_coord_type = 2;
@@ -2313,7 +2333,7 @@
 	switch (prim_walk) {
 	case 1:
 		for (i = 0; i < track->num_arrays; i++) {
-			size = track->arrays[i].esize * track->max_indx * 4;
+			size = track->arrays[i].esize * track->max_indx * 4UL;
 			if (track->arrays[i].robj == NULL) {
 				DRM_ERROR("(PW %u) Vertex array %u no buffer "
 					  "bound\n", prim_walk, i);
@@ -2332,7 +2352,7 @@
 		break;
 	case 2:
 		for (i = 0; i < track->num_arrays; i++) {
-			size = track->arrays[i].esize * (nverts - 1) * 4;
+			size = track->arrays[i].esize * (nverts - 1) * 4UL;
 			if (track->arrays[i].robj == NULL) {
 				DRM_ERROR("(PW %u) Vertex array %u no buffer "
 					  "bound\n", prim_walk, i);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/r200.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/r200.c
@@ -476,8 +476,8 @@
 			track->textures[i].use_pitch = 1;
 		} else {
 			track->textures[i].use_pitch = 0;
-			track->textures[i].width = 1 << ((idx_value >> RADEON_TXFORMAT_WIDTH_SHIFT) & RADEON_TXFORMAT_WIDTH_MASK);
-			track->textures[i].height = 1 << ((idx_value >> RADEON_TXFORMAT_HEIGHT_SHIFT) & RADEON_TXFORMAT_HEIGHT_MASK);
+			track->textures[i].width = 1 << ((idx_value & RADEON_TXFORMAT_WIDTH_MASK) >> RADEON_TXFORMAT_WIDTH_SHIFT);
+			track->textures[i].height = 1 << ((idx_value & RADEON_TXFORMAT_HEIGHT_MASK) >> RADEON_TXFORMAT_HEIGHT_SHIFT);
 		}
 		if (idx_value & R200_TXFORMAT_LOOKUP_DISABLE)
 			track->textures[i].lookup_disable = true;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/r300.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/r300.c
@@ -361,7 +361,8 @@
 	return -1;
 }
 
-static void r300_gpu_init(struct radeon_device *rdev)
+/* rs400_gpu_init also calls this! */
+void r300_gpu_init(struct radeon_device *rdev)
 {
 	uint32_t gb_tile_config, tmp;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/r600.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/r600.c
@@ -3696,8 +3696,8 @@
 	}
 
 	/* setup interrupt control */
-	/* set dummy read address to ring address */
-	WREG32(INTERRUPT_CNTL2, rdev->ih.gpu_addr >> 8);
+	/* set dummy read address to dummy page address */
+	WREG32(INTERRUPT_CNTL2, rdev->dummy_page.addr >> 8);
 	interrupt_cntl = RREG32(INTERRUPT_CNTL);
 	/* IH_DUMMY_RD_OVERRIDE=0 - dummy read disabled with msi, enabled without msi
 	 * IH_DUMMY_RD_OVERRIDE=1 - dummy read controlled by IH_DUMMY_RD_EN
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/r600_cs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/r600_cs.c
@@ -1278,7 +1278,7 @@
 			return -EINVAL;
 		}
 		tmp = (reg - CB_COLOR0_BASE) / 4;
-		track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8;
+		track->cb_color_bo_offset[tmp] = (u64)radeon_get_ib_value(p, idx) << 8;
 		ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
 		track->cb_color_base_last[tmp] = ib[idx];
 		track->cb_color_bo[tmp] = reloc->robj;
@@ -1305,7 +1305,7 @@
 					"0x%04X\n", reg);
 			return -EINVAL;
 		}
-		track->htile_offset = radeon_get_ib_value(p, idx) << 8;
+		track->htile_offset = (u64)radeon_get_ib_value(p, idx) << 8;
 		ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
 		track->htile_bo = reloc->robj;
 		track->db_dirty = true;
@@ -2104,7 +2104,7 @@
 				return -EINVAL;
 			}
 
-			offset = radeon_get_ib_value(p, idx+1) << 8;
+			offset = (u64)radeon_get_ib_value(p, idx+1) << 8;
 			if (offset != track->vgt_strmout_bo_offset[idx_value]) {
 				DRM_ERROR("bad STRMOUT_BASE_UPDATE, bo offset does not match: 0x%llx, 0x%x\n",
 					  offset, track->vgt_strmout_bo_offset[idx_value]);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/radeon.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/radeon.h
@@ -1554,6 +1554,7 @@
 	void                    *priv;
 	u32			new_active_crtcs;
 	int			new_active_crtc_count;
+	int			high_pixelclock_count;
 	u32			current_active_crtcs;
 	int			current_active_crtc_count;
 	bool single_display;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/radeon_asic.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/radeon_asic.h
@@ -165,6 +165,7 @@
  */
 extern int r300_init(struct radeon_device *rdev);
 extern void r300_fini(struct radeon_device *rdev);
+extern void r300_gpu_init(struct radeon_device *rdev);
 extern int r300_suspend(struct radeon_device *rdev);
 extern int r300_resume(struct radeon_device *rdev);
 extern int r300_asic_reset(struct radeon_device *rdev, bool hard);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/radeon_atombios.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -1730,23 +1730,29 @@
 					fake_edid_record = (ATOM_FAKE_EDID_PATCH_RECORD *)record;
 					if (fake_edid_record->ucFakeEDIDLength) {
 						struct edid *edid;
-						int edid_size =
-							max((int)EDID_LENGTH, (int)fake_edid_record->ucFakeEDIDLength);
-						edid = kmalloc(edid_size, GFP_KERNEL);
-						if (edid) {
-							memcpy((u8 *)edid, (u8 *)&fake_edid_record->ucFakeEDIDString[0],
-							       fake_edid_record->ucFakeEDIDLength);
+						int edid_size;
 
+						if (fake_edid_record->ucFakeEDIDLength == 128)
+							edid_size = fake_edid_record->ucFakeEDIDLength;
+						else
+							edid_size = fake_edid_record->ucFakeEDIDLength * 128;
+						edid = kmemdup(&fake_edid_record->ucFakeEDIDString[0],
+							       edid_size, GFP_KERNEL);
+						if (edid) {
 							if (drm_edid_is_valid(edid)) {
 								rdev->mode_info.bios_hardcoded_edid = edid;
 								rdev->mode_info.bios_hardcoded_edid_size = edid_size;
-							} else
+							} else {
 								kfree(edid);
+							}
 						}
+						record += struct_size(fake_edid_record,
+								      ucFakeEDIDString,
+								      edid_size);
+					} else {
+						/* empty fake edid record must be 3 bytes long */
+						record += sizeof(ATOM_FAKE_EDID_PATCH_RECORD) + 1;
 					}
-					record += fake_edid_record->ucFakeEDIDLength ?
-						fake_edid_record->ucFakeEDIDLength + 2 :
-						sizeof(ATOM_FAKE_EDID_PATCH_RECORD);
 					break;
 				case LCD_PANEL_RESOLUTION_RECORD_TYPE:
 					panel_res_record = (ATOM_PANEL_RESOLUTION_PATCH_RECORD *)record;
@@ -2136,11 +2142,14 @@
 		return state_index;
 	/* last mode is usually default, array is low to high */
 	for (i = 0; i < num_modes; i++) {
-		rdev->pm.power_state[state_index].clock_info =
-			kcalloc(1, sizeof(struct radeon_pm_clock_info),
-				GFP_KERNEL);
+		/* avoid memory leaks from invalid modes or unknown frev. */
+		if (!rdev->pm.power_state[state_index].clock_info) {
+			rdev->pm.power_state[state_index].clock_info =
+				kzalloc(sizeof(struct radeon_pm_clock_info),
+					GFP_KERNEL);
+		}
 		if (!rdev->pm.power_state[state_index].clock_info)
-			return state_index;
+			goto out;
 		rdev->pm.power_state[state_index].num_clock_modes = 1;
 		rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
 		switch (frev) {
@@ -2259,17 +2268,24 @@
 			break;
 		}
 	}
+out:
+	/* free any unused clock_info allocation. */
+	if (state_index && state_index < num_modes) {
+		kfree(rdev->pm.power_state[state_index].clock_info);
+		rdev->pm.power_state[state_index].clock_info = NULL;
+	}
+
 	/* last mode is usually default */
-	if (rdev->pm.default_power_state_index == -1) {
+	if (state_index && rdev->pm.default_power_state_index == -1) {
 		rdev->pm.power_state[state_index - 1].type =
 			POWER_STATE_TYPE_DEFAULT;
 		rdev->pm.default_power_state_index = state_index - 1;
 		rdev->pm.power_state[state_index - 1].default_clock_mode =
 			&rdev->pm.power_state[state_index - 1].clock_info[0];
-		rdev->pm.power_state[state_index].flags &=
+		rdev->pm.power_state[state_index - 1].flags &=
 			~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
-		rdev->pm.power_state[state_index].misc = 0;
-		rdev->pm.power_state[state_index].misc2 = 0;
+		rdev->pm.power_state[state_index - 1].misc = 0;
+		rdev->pm.power_state[state_index - 1].misc2 = 0;
 	}
 	return state_index;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/radeon_bios.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/radeon_bios.c
@@ -108,25 +108,33 @@
 
 static bool radeon_read_platform_bios(struct radeon_device *rdev)
 {
-	uint8_t __iomem *bios;
-	size_t size;
+	phys_addr_t rom = rdev->pdev->rom;
+	size_t romlen = rdev->pdev->romlen;
+	void __iomem *bios;
 
 	rdev->bios = NULL;
 
-	bios = pci_platform_rom(rdev->pdev, &size);
-	if (!bios) {
+	if (!rom || romlen == 0)
 		return false;
-	}
 
-	if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) {
-		return false;
-	}
-	rdev->bios = kmemdup(bios, size, GFP_KERNEL);
-	if (rdev->bios == NULL) {
+	rdev->bios = kzalloc(romlen, GFP_KERNEL);
+	if (!rdev->bios)
 		return false;
-	}
+
+	bios = ioremap(rom, romlen);
+	if (!bios)
+		goto free_bios;
+
+	memcpy_fromio(rdev->bios, bios, romlen);
+	iounmap(bios);
+
+	if (rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa)
+		goto free_bios;
 
 	return true;
+free_bios:
+	kfree(rdev->bios);
+	return false;
 }
 
 #ifdef CONFIG_ACPI
@@ -219,6 +227,7 @@
 
 	if (!found)
 		return false;
+	pci_dev_put(pdev);
 
 	rdev->bios = kmalloc(size, GFP_KERNEL);
 	if (!rdev->bios) {
@@ -604,13 +613,14 @@
 	acpi_size tbl_size;
 	UEFI_ACPI_VFCT *vfct;
 	unsigned offset;
+	bool r = false;
 
 	if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr)))
 		return false;
 	tbl_size = hdr->length;
 	if (tbl_size < sizeof(UEFI_ACPI_VFCT)) {
 		DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n");
-		return false;
+		goto out;
 	}
 
 	vfct = (UEFI_ACPI_VFCT *)hdr;
@@ -623,13 +633,13 @@
 		offset += sizeof(VFCT_IMAGE_HEADER);
 		if (offset > tbl_size) {
 			DRM_ERROR("ACPI VFCT image header truncated\n");
-			return false;
+			goto out;
 		}
 
 		offset += vhdr->ImageLength;
 		if (offset > tbl_size) {
 			DRM_ERROR("ACPI VFCT image truncated\n");
-			return false;
+			goto out;
 		}
 
 		if (vhdr->ImageLength &&
@@ -641,15 +651,18 @@
 			rdev->bios = kmemdup(&vbios->VbiosContent,
 					     vhdr->ImageLength,
 					     GFP_KERNEL);
+			if (rdev->bios)
+				r = true;
 
-			if (!rdev->bios)
-				return false;
-			return true;
+			goto out;
 		}
 	}
 
 	DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n");
-	return false;
+
+out:
+	acpi_put_table(hdr);
+	return r;
 }
 #else
 static inline bool radeon_acpi_vfct_bios(struct radeon_device *rdev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/radeon_connectors.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -477,6 +477,8 @@
 	    native_mode->vdisplay != 0 &&
 	    native_mode->clock != 0) {
 		mode = drm_mode_duplicate(dev, native_mode);
+		if (!mode)
+			return NULL;
 		mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
 		drm_mode_set_name(mode);
 
@@ -491,6 +493,8 @@
 		 * simpler.
 		 */
 		mode = drm_cvt_mode(dev, native_mode->hdisplay, native_mode->vdisplay, 60, true, false, false);
+		if (!mode)
+			return NULL;
 		mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
 		DRM_DEBUG_KMS("Adding cvt approximation of native panel mode %s\n", mode->name);
 	}
@@ -883,8 +887,10 @@
 
 	if (!drm_kms_helper_is_poll_worker()) {
 		r = pm_runtime_get_sync(connector->dev->dev);
-		if (r < 0)
+		if (r < 0) {
+			pm_runtime_put_autosuspend(connector->dev->dev);
 			return connector_status_disconnected;
+		}
 	}
 
 	if (encoder) {
@@ -1029,8 +1035,10 @@
 
 	if (!drm_kms_helper_is_poll_worker()) {
 		r = pm_runtime_get_sync(connector->dev->dev);
-		if (r < 0)
+		if (r < 0) {
+			pm_runtime_put_autosuspend(connector->dev->dev);
 			return connector_status_disconnected;
+		}
 	}
 
 	encoder = radeon_best_single_encoder(connector);
@@ -1167,8 +1175,10 @@
 
 	if (!drm_kms_helper_is_poll_worker()) {
 		r = pm_runtime_get_sync(connector->dev->dev);
-		if (r < 0)
+		if (r < 0) {
+			pm_runtime_put_autosuspend(connector->dev->dev);
 			return connector_status_disconnected;
+		}
 	}
 
 	encoder = radeon_best_single_encoder(connector);
@@ -1251,8 +1261,10 @@
 
 	if (!drm_kms_helper_is_poll_worker()) {
 		r = pm_runtime_get_sync(connector->dev->dev);
-		if (r < 0)
+		if (r < 0) {
+			pm_runtime_put_autosuspend(connector->dev->dev);
 			return connector_status_disconnected;
+		}
 	}
 
 	if (radeon_connector->detected_hpd_without_ddc) {
@@ -1666,8 +1678,10 @@
 
 	if (!drm_kms_helper_is_poll_worker()) {
 		r = pm_runtime_get_sync(connector->dev->dev);
-		if (r < 0)
+		if (r < 0) {
+			pm_runtime_put_autosuspend(connector->dev->dev);
 			return connector_status_disconnected;
+		}
 	}
 
 	if (!force && radeon_check_hpd_status_unchanged(connector)) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/radeon_cs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/radeon_cs.c
@@ -271,7 +271,8 @@
 {
 	struct drm_radeon_cs *cs = data;
 	uint64_t *chunk_array_ptr;
-	unsigned size, i;
+	u64 size;
+	unsigned i;
 	u32 ring = RADEON_CS_RING_GFX;
 	s32 priority = 0;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/radeon_device.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/radeon_device.c
@@ -1022,6 +1022,7 @@
 {
 	if (rdev->mode_info.atom_context) {
 		kfree(rdev->mode_info.atom_context->scratch);
+		kfree(rdev->mode_info.atom_context->iio);
 	}
 	kfree(rdev->mode_info.atom_context);
 	rdev->mode_info.atom_context = NULL;
@@ -1623,6 +1624,9 @@
 		if (r) {
 			/* delay GPU reset to resume */
 			radeon_fence_driver_force_completion(rdev, i);
+		} else {
+			/* finish executing delayed work */
+			flush_delayed_work(&rdev->fence_drv[i].lockup_work);
 		}
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/radeon_display.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/radeon_display.c
@@ -127,6 +127,8 @@
 
 	DRM_DEBUG_KMS("%d\n", radeon_crtc->crtc_id);
 
+	msleep(10);
+
 	WREG32(NI_INPUT_CSC_CONTROL + radeon_crtc->crtc_offset,
 	       (NI_INPUT_CSC_GRPH_MODE(NI_INPUT_CSC_BYPASS) |
 		NI_INPUT_CSC_OVL_MODE(NI_INPUT_CSC_BYPASS)));
@@ -629,8 +631,10 @@
 	dev = set->crtc->dev;
 
 	ret = pm_runtime_get_sync(dev->dev);
-	if (ret < 0)
+	if (ret < 0) {
+		pm_runtime_put_autosuspend(dev->dev);
 		return ret;
+	}
 
 	ret = drm_crtc_helper_set_config(set, ctx);
 
@@ -678,11 +682,16 @@
 	if (radeon_crtc == NULL)
 		return;
 
+	radeon_crtc->flip_queue = alloc_workqueue("radeon-crtc", WQ_HIGHPRI, 0);
+	if (!radeon_crtc->flip_queue) {
+		kfree(radeon_crtc);
+		return;
+	}
+
 	drm_crtc_init(dev, &radeon_crtc->base, &radeon_crtc_funcs);
 
 	drm_mode_crtc_set_gamma_size(&radeon_crtc->base, 256);
 	radeon_crtc->crtc_id = index;
-	radeon_crtc->flip_queue = alloc_workqueue("radeon-crtc", WQ_HIGHPRI, 0);
 	rdev->mode_info.crtcs[index] = radeon_crtc;
 
 	if (rdev->family >= CHIP_BONAIRE) {
@@ -1329,6 +1338,7 @@
 	/* Handle is imported dma-buf, so cannot be migrated to VRAM for scanout */
 	if (obj->import_attach) {
 		DRM_DEBUG_KMS("Cannot create framebuffer from imported dma_buf\n");
+		drm_gem_object_put(obj);
 		return ERR_PTR(-EINVAL);
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/radeon_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/radeon_drv.c
@@ -37,6 +37,7 @@
 #include <linux/vga_switcheroo.h>
 #include <linux/mmu_notifier.h>
 
+#include <drm/drm_agpsupport.h>
 #include <drm/drm_crtc_helper.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_fb_helper.h>
@@ -173,12 +174,7 @@
 int radeon_modeset = -1;
 int radeon_dynclks = -1;
 int radeon_r4xx_atom = 0;
-#ifdef __powerpc__
-/* Default to PCI on PowerPC (fdo #95017) */
 int radeon_agpmode = -1;
-#else
-int radeon_agpmode = 0;
-#endif
 int radeon_vram_limit = 0;
 int radeon_gart_size = -1; /* auto */
 int radeon_benchmarking = 0;
@@ -325,6 +321,7 @@
 			    const struct pci_device_id *ent)
 {
 	unsigned long flags = 0;
+	struct drm_device *dev;
 	int ret;
 
 	if (!ent)
@@ -365,7 +362,44 @@
 	if (ret)
 		return ret;
 
-	return drm_get_pci_dev(pdev, ent, &kms_driver);
+	dev = drm_dev_alloc(&kms_driver, &pdev->dev);
+	if (IS_ERR(dev))
+		return PTR_ERR(dev);
+
+	ret = pci_enable_device(pdev);
+	if (ret)
+		goto err_free;
+
+	dev->pdev = pdev;
+#ifdef __alpha__
+	dev->hose = pdev->sysdata;
+#endif
+
+	pci_set_drvdata(pdev, dev);
+
+	if (pci_find_capability(dev->pdev, PCI_CAP_ID_AGP))
+		dev->agp = drm_agp_init(dev);
+	if (dev->agp) {
+		dev->agp->agp_mtrr = arch_phys_wc_add(
+			dev->agp->agp_info.aper_base,
+			dev->agp->agp_info.aper_size *
+			1024 * 1024);
+	}
+
+	ret = drm_dev_register(dev, ent->driver_data);
+	if (ret)
+		goto err_agp;
+
+	return 0;
+
+err_agp:
+	if (dev->agp)
+		arch_phys_wc_del(dev->agp->agp_mtrr);
+	kfree(dev->agp);
+	pci_disable_device(pdev);
+err_free:
+	drm_dev_put(dev);
+	return ret;
 }
 
 static void
@@ -516,8 +550,10 @@
 	long ret;
 	dev = file_priv->minor->dev;
 	ret = pm_runtime_get_sync(dev->dev);
-	if (ret < 0)
+	if (ret < 0) {
+		pm_runtime_put_autosuspend(dev->dev);
 		return ret;
+	}
 
 	ret = drm_ioctl(filp, cmd, arg);
 	
@@ -578,7 +614,7 @@
 
 static struct drm_driver kms_driver = {
 	.driver_features =
-	    DRIVER_USE_AGP | DRIVER_GEM | DRIVER_RENDER,
+	    DRIVER_GEM | DRIVER_RENDER,
 	.load = radeon_driver_load_kms,
 	.open = radeon_driver_open_kms,
 	.postclose = radeon_driver_postclose_kms,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/radeon_gem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/radeon_gem.c
@@ -384,7 +384,6 @@
 	struct radeon_device *rdev = dev->dev_private;
 	struct drm_radeon_gem_set_domain *args = data;
 	struct drm_gem_object *gobj;
-	struct radeon_bo *robj;
 	int r;
 
 	/* for now if someone requests domain CPU -
@@ -397,13 +396,12 @@
 		up_read(&rdev->exclusive_lock);
 		return -ENOENT;
 	}
-	robj = gem_to_radeon_bo(gobj);
 
 	r = radeon_gem_set_domain(gobj, args->read_domains, args->write_domain);
 
 	drm_gem_object_put_unlocked(gobj);
 	up_read(&rdev->exclusive_lock);
-	r = radeon_gem_handle_lockup(robj->rdev, r);
+	r = radeon_gem_handle_lockup(rdev, r);
 	return r;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/radeon_kms.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/radeon_kms.c
@@ -31,6 +31,7 @@
 #include <linux/uaccess.h>
 #include <linux/vga_switcheroo.h>
 
+#include <drm/drm_agpsupport.h>
 #include <drm/drm_fb_helper.h>
 #include <drm/drm_file.h>
 #include <drm/drm_ioctl.h>
@@ -77,6 +78,11 @@
 	radeon_modeset_fini(rdev);
 	radeon_device_fini(rdev);
 
+	if (dev->agp)
+		arch_phys_wc_del(dev->agp->agp_mtrr);
+	kfree(dev->agp);
+	dev->agp = NULL;
+
 done_free:
 	kfree(rdev);
 	dev->dev_private = NULL;
@@ -506,6 +512,7 @@
 			*value = rdev->config.si.backend_enable_mask;
 		} else {
 			DRM_DEBUG_KMS("BACKEND_ENABLED_MASK is si+ only!\n");
+			return -EINVAL;
 		}
 		break;
 	case RADEON_INFO_MAX_SCLK:
@@ -627,58 +634,66 @@
 int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
 {
 	struct radeon_device *rdev = dev->dev_private;
+	struct radeon_fpriv *fpriv;
+	struct radeon_vm *vm;
 	int r;
 
 	file_priv->driver_priv = NULL;
 
 	r = pm_runtime_get_sync(dev->dev);
-	if (r < 0)
+	if (r < 0) {
+		pm_runtime_put_autosuspend(dev->dev);
 		return r;
+	}
 
 	/* new gpu have virtual address space support */
 	if (rdev->family >= CHIP_CAYMAN) {
-		struct radeon_fpriv *fpriv;
-		struct radeon_vm *vm;
 
 		fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL);
 		if (unlikely(!fpriv)) {
 			r = -ENOMEM;
-			goto out_suspend;
+			goto err_suspend;
 		}
 
 		if (rdev->accel_working) {
 			vm = &fpriv->vm;
 			r = radeon_vm_init(rdev, vm);
-			if (r) {
-				kfree(fpriv);
-				goto out_suspend;
-			}
+			if (r)
+				goto err_fpriv;
 
 			r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false);
-			if (r) {
-				radeon_vm_fini(rdev, vm);
-				kfree(fpriv);
-				goto out_suspend;
-			}
+			if (r)
+				goto err_vm_fini;
 
 			/* map the ib pool buffer read only into
 			 * virtual address space */
 			vm->ib_bo_va = radeon_vm_bo_add(rdev, vm,
 							rdev->ring_tmp_bo.bo);
+			if (!vm->ib_bo_va) {
+				r = -ENOMEM;
+				goto err_vm_fini;
+			}
+
 			r = radeon_vm_bo_set_addr(rdev, vm->ib_bo_va,
 						  RADEON_VA_IB_OFFSET,
 						  RADEON_VM_PAGE_READABLE |
 						  RADEON_VM_PAGE_SNOOPED);
-			if (r) {
-				radeon_vm_fini(rdev, vm);
-				kfree(fpriv);
-				goto out_suspend;
-			}
+			if (r)
+				goto err_vm_fini;
 		}
 		file_priv->driver_priv = fpriv;
 	}
 
-out_suspend:
+	pm_runtime_mark_last_busy(dev->dev);
+	pm_runtime_put_autosuspend(dev->dev);
+	return 0;
+
+err_vm_fini:
+	radeon_vm_fini(rdev, vm);
+err_fpriv:
+	kfree(fpriv);
+
+err_suspend:
 	pm_runtime_mark_last_busy(dev->dev);
 	pm_runtime_put_autosuspend(dev->dev);
 	return r;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/radeon_pm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/radeon_pm.c
@@ -1720,6 +1720,7 @@
 	struct drm_device *ddev = rdev->ddev;
 	struct drm_crtc *crtc;
 	struct radeon_crtc *radeon_crtc;
+	struct radeon_connector *radeon_connector;
 
 	if (!rdev->pm.dpm_enabled)
 		return;
@@ -1729,6 +1730,7 @@
 	/* update active crtc counts */
 	rdev->pm.dpm.new_active_crtcs = 0;
 	rdev->pm.dpm.new_active_crtc_count = 0;
+	rdev->pm.dpm.high_pixelclock_count = 0;
 	if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) {
 		list_for_each_entry(crtc,
 				    &ddev->mode_config.crtc_list, head) {
@@ -1736,6 +1738,12 @@
 			if (crtc->enabled) {
 				rdev->pm.dpm.new_active_crtcs |= (1 << radeon_crtc->crtc_id);
 				rdev->pm.dpm.new_active_crtc_count++;
+				if (!radeon_crtc->connector)
+					continue;
+
+				radeon_connector = to_radeon_connector(radeon_crtc->connector);
+				if (radeon_connector->pixelclock_for_modeset > 297000)
+					rdev->pm.dpm.high_pixelclock_count++;
 			}
 		}
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/radeon_prime.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/radeon_prime.c
@@ -94,9 +94,19 @@
 
 	/* pin buffer into GTT */
 	ret = radeon_bo_pin(bo, RADEON_GEM_DOMAIN_GTT, NULL);
-	if (likely(ret == 0))
-		bo->prime_shared_count++;
+	if (unlikely(ret))
+		goto error;
 
+	if (bo->tbo.moving) {
+		ret = dma_fence_wait(bo->tbo.moving, false);
+		if (unlikely(ret)) {
+			radeon_bo_unpin(bo);
+			goto error;
+		}
+	}
+
+	bo->prime_shared_count++;
+error:
 	radeon_bo_unreserve(bo);
 	return ret;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/radeon_uvd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/radeon_uvd.c
@@ -286,7 +286,7 @@
 	if (rdev->uvd.vcpu_bo == NULL)
 		return -EINVAL;
 
-	memcpy(rdev->uvd.cpu_addr, rdev->uvd_fw->data, rdev->uvd_fw->size);
+	memcpy_toio((void __iomem *)rdev->uvd.cpu_addr, rdev->uvd_fw->data, rdev->uvd_fw->size);
 
 	size = radeon_bo_size(rdev->uvd.vcpu_bo);
 	size -= rdev->uvd_fw->size;
@@ -294,7 +294,7 @@
 	ptr = rdev->uvd.cpu_addr;
 	ptr += rdev->uvd_fw->size;
 
-	memset(ptr, 0, size);
+	memset_io((void __iomem *)ptr, 0, size);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/radeon_vce.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/radeon_vce.c
@@ -558,7 +558,7 @@
 {
 	int session_idx = -1;
 	bool destroyed = false, created = false, allocated = false;
-	uint32_t tmp, handle = 0;
+	uint32_t tmp = 0, handle = 0;
 	uint32_t *size = &tmp;
 	int i, r = 0;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/radeon_vm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/radeon_vm.c
@@ -1206,13 +1206,17 @@
 	r = radeon_bo_create(rdev, pd_size, align, true,
 			     RADEON_GEM_DOMAIN_VRAM, 0, NULL,
 			     NULL, &vm->page_directory);
-	if (r)
+	if (r) {
+		kfree(vm->page_tables);
+		vm->page_tables = NULL;
 		return r;
-
+	}
 	r = radeon_vm_clear_bo(rdev, vm->page_directory);
 	if (r) {
 		radeon_bo_unref(&vm->page_directory);
 		vm->page_directory = NULL;
+		kfree(vm->page_tables);
+		vm->page_tables = NULL;
 		return r;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/rs400.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/rs400.c
@@ -257,8 +257,22 @@
 
 static void rs400_gpu_init(struct radeon_device *rdev)
 {
-	/* FIXME: is this correct ? */
-	r420_pipes_init(rdev);
+	/* Earlier code was calling r420_pipes_init and then
+	 * rs400_mc_wait_for_idle(rdev). The problem is that
+	 * at least on my Mobility Radeon Xpress 200M RC410 card
+	 * that ends up in this code path ends up num_gb_pipes == 3
+	 * while the card seems to have only one pipe. With the
+	 * r420 pipe initialization method.
+	 *
+	 * Problems shown up as HyperZ glitches, see:
+	 * https://bugs.freedesktop.org/show_bug.cgi?id=110897
+	 *
+	 * Delegating initialization to r300 code seems to work
+	 * and results in proper pipe numbers. The rs400 cards
+	 * are said to be not r400, but r300 kind of cards.
+	 */
+	r300_gpu_init(rdev);
+
 	if (rs400_mc_wait_for_idle(rdev)) {
 		pr_warn("rs400: Failed to wait MC idle while programming pipes. Bad things might happen. %08x\n",
 			RREG32(RADEON_MC_STATUS));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/rv740_dpm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/rv740_dpm.c
@@ -250,8 +250,12 @@
 						     ASIC_INTERNAL_MEMORY_SS, vco_freq)) {
 			u32 reference_clock = rdev->clock.mpll.reference_freq;
 			u32 decoded_ref = rv740_get_decoded_reference_divider(dividers.ref_div);
-			u32 clk_s = reference_clock * 5 / (decoded_ref * ss.rate);
-			u32 clk_v = 0x40000 * ss.percentage *
+			u32 clk_s, clk_v;
+
+			if (!decoded_ref)
+				return -EINVAL;
+			clk_s = reference_clock * 5 / (decoded_ref * ss.rate);
+			clk_v = 0x40000 * ss.percentage *
 				(dividers.whole_fb_div + (dividers.frac_fb_div / 8)) / (clk_s * 10000);
 
 			mpll_ss1 &= ~CLKV_MASK;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/si.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/si.c
@@ -3257,7 +3257,7 @@
 		/* XXX what about 12? */
 		rdev->config.si.tile_config |= (3 << 0);
 		break;
-	}	
+	}
 	switch ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) {
 	case 0: /* four banks */
 		rdev->config.si.tile_config |= 0 << 4;
@@ -3616,6 +3616,10 @@
 	for (i = RADEON_RING_TYPE_GFX_INDEX; i <= CAYMAN_RING_TYPE_CP2_INDEX; ++i) {
 		ring = &rdev->ring[i];
 		r = radeon_ring_lock(rdev, ring, 2);
+		if (r) {
+			DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r);
+			return r;
+		}
 
 		/* clear the compute context state */
 		radeon_ring_write(ring, PACKET3_COMPUTE(PACKET3_CLEAR_STATE, 0));
@@ -5997,8 +6001,8 @@
 	}
 
 	/* setup interrupt control */
-	/* set dummy read address to ring address */
-	WREG32(INTERRUPT_CNTL2, rdev->ih.gpu_addr >> 8);
+	/* set dummy read address to dummy page address */
+	WREG32(INTERRUPT_CNTL2, rdev->dummy_page.addr >> 8);
 	interrupt_cntl = RREG32(INTERRUPT_CNTL);
 	/* IH_DUMMY_RD_OVERRIDE=0 - dummy read disabled with msi, enabled without msi
 	 * IH_DUMMY_RD_OVERRIDE=1 - dummy read controlled by IH_DUMMY_RD_EN
@@ -7087,7 +7091,6 @@
 {
 	struct pci_dev *root = rdev->pdev->bus->self;
 	enum pci_bus_speed speed_cap;
-	int bridge_pos, gpu_pos;
 	u32 speed_cntl, current_data_rate;
 	int i;
 	u16 tmp16;
@@ -7129,12 +7132,7 @@
 		DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n");
 	}
 
-	bridge_pos = pci_pcie_cap(root);
-	if (!bridge_pos)
-		return;
-
-	gpu_pos = pci_pcie_cap(rdev->pdev);
-	if (!gpu_pos)
+	if (!pci_is_pcie(root) || !pci_is_pcie(rdev->pdev))
 		return;
 
 	if (speed_cap == PCIE_SPEED_8_0GT) {
@@ -7144,14 +7142,8 @@
 			u16 bridge_cfg2, gpu_cfg2;
 			u32 max_lw, current_lw, tmp;
 
-			pci_read_config_word(root, bridge_pos + PCI_EXP_LNKCTL, &bridge_cfg);
-			pci_read_config_word(rdev->pdev, gpu_pos + PCI_EXP_LNKCTL, &gpu_cfg);
-
-			tmp16 = bridge_cfg | PCI_EXP_LNKCTL_HAWD;
-			pci_write_config_word(root, bridge_pos + PCI_EXP_LNKCTL, tmp16);
-
-			tmp16 = gpu_cfg | PCI_EXP_LNKCTL_HAWD;
-			pci_write_config_word(rdev->pdev, gpu_pos + PCI_EXP_LNKCTL, tmp16);
+			pcie_capability_set_word(root, PCI_EXP_LNKCTL, PCI_EXP_LNKCTL_HAWD);
+			pcie_capability_set_word(rdev->pdev, PCI_EXP_LNKCTL, PCI_EXP_LNKCTL_HAWD);
 
 			tmp = RREG32_PCIE(PCIE_LC_STATUS1);
 			max_lw = (tmp & LC_DETECTED_LINK_WIDTH_MASK) >> LC_DETECTED_LINK_WIDTH_SHIFT;
@@ -7169,15 +7161,23 @@
 
 			for (i = 0; i < 10; i++) {
 				/* check status */
-				pci_read_config_word(rdev->pdev, gpu_pos + PCI_EXP_DEVSTA, &tmp16);
+				pcie_capability_read_word(rdev->pdev,
+							  PCI_EXP_DEVSTA,
+							  &tmp16);
 				if (tmp16 & PCI_EXP_DEVSTA_TRPND)
 					break;
 
-				pci_read_config_word(root, bridge_pos + PCI_EXP_LNKCTL, &bridge_cfg);
-				pci_read_config_word(rdev->pdev, gpu_pos + PCI_EXP_LNKCTL, &gpu_cfg);
-
-				pci_read_config_word(root, bridge_pos + PCI_EXP_LNKCTL2, &bridge_cfg2);
-				pci_read_config_word(rdev->pdev, gpu_pos + PCI_EXP_LNKCTL2, &gpu_cfg2);
+				pcie_capability_read_word(root, PCI_EXP_LNKCTL,
+							  &bridge_cfg);
+				pcie_capability_read_word(rdev->pdev,
+							  PCI_EXP_LNKCTL,
+							  &gpu_cfg);
+
+				pcie_capability_read_word(root, PCI_EXP_LNKCTL2,
+							  &bridge_cfg2);
+				pcie_capability_read_word(rdev->pdev,
+							  PCI_EXP_LNKCTL2,
+							  &gpu_cfg2);
 
 				tmp = RREG32_PCIE_PORT(PCIE_LC_CNTL4);
 				tmp |= LC_SET_QUIESCE;
@@ -7190,26 +7190,38 @@
 				msleep(100);
 
 				/* linkctl */
-				pci_read_config_word(root, bridge_pos + PCI_EXP_LNKCTL, &tmp16);
-				tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
-				tmp16 |= (bridge_cfg & PCI_EXP_LNKCTL_HAWD);
-				pci_write_config_word(root, bridge_pos + PCI_EXP_LNKCTL, tmp16);
-
-				pci_read_config_word(rdev->pdev, gpu_pos + PCI_EXP_LNKCTL, &tmp16);
-				tmp16 &= ~PCI_EXP_LNKCTL_HAWD;
-				tmp16 |= (gpu_cfg & PCI_EXP_LNKCTL_HAWD);
-				pci_write_config_word(rdev->pdev, gpu_pos + PCI_EXP_LNKCTL, tmp16);
+				pcie_capability_clear_and_set_word(root, PCI_EXP_LNKCTL,
+								   PCI_EXP_LNKCTL_HAWD,
+								   bridge_cfg &
+								   PCI_EXP_LNKCTL_HAWD);
+				pcie_capability_clear_and_set_word(rdev->pdev, PCI_EXP_LNKCTL,
+								   PCI_EXP_LNKCTL_HAWD,
+								   gpu_cfg &
+								   PCI_EXP_LNKCTL_HAWD);
 
 				/* linkctl2 */
-				pci_read_config_word(root, bridge_pos + PCI_EXP_LNKCTL2, &tmp16);
-				tmp16 &= ~((1 << 4) | (7 << 9));
-				tmp16 |= (bridge_cfg2 & ((1 << 4) | (7 << 9)));
-				pci_write_config_word(root, bridge_pos + PCI_EXP_LNKCTL2, tmp16);
-
-				pci_read_config_word(rdev->pdev, gpu_pos + PCI_EXP_LNKCTL2, &tmp16);
-				tmp16 &= ~((1 << 4) | (7 << 9));
-				tmp16 |= (gpu_cfg2 & ((1 << 4) | (7 << 9)));
-				pci_write_config_word(rdev->pdev, gpu_pos + PCI_EXP_LNKCTL2, tmp16);
+				pcie_capability_read_word(root, PCI_EXP_LNKCTL2,
+							  &tmp16);
+				tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
+					   PCI_EXP_LNKCTL2_TX_MARGIN);
+				tmp16 |= (bridge_cfg2 &
+					  (PCI_EXP_LNKCTL2_ENTER_COMP |
+					   PCI_EXP_LNKCTL2_TX_MARGIN));
+				pcie_capability_write_word(root,
+							   PCI_EXP_LNKCTL2,
+							   tmp16);
+
+				pcie_capability_read_word(rdev->pdev,
+							  PCI_EXP_LNKCTL2,
+							  &tmp16);
+				tmp16 &= ~(PCI_EXP_LNKCTL2_ENTER_COMP |
+					   PCI_EXP_LNKCTL2_TX_MARGIN);
+				tmp16 |= (gpu_cfg2 &
+					  (PCI_EXP_LNKCTL2_ENTER_COMP |
+					   PCI_EXP_LNKCTL2_TX_MARGIN));
+				pcie_capability_write_word(rdev->pdev,
+							   PCI_EXP_LNKCTL2,
+							   tmp16);
 
 				tmp = RREG32_PCIE_PORT(PCIE_LC_CNTL4);
 				tmp &= ~LC_SET_QUIESCE;
@@ -7223,15 +7235,15 @@
 	speed_cntl &= ~LC_FORCE_DIS_SW_SPEED_CHANGE;
 	WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, speed_cntl);
 
-	pci_read_config_word(rdev->pdev, gpu_pos + PCI_EXP_LNKCTL2, &tmp16);
-	tmp16 &= ~0xf;
+	pcie_capability_read_word(rdev->pdev, PCI_EXP_LNKCTL2, &tmp16);
+	tmp16 &= ~PCI_EXP_LNKCTL2_TLS;
 	if (speed_cap == PCIE_SPEED_8_0GT)
-		tmp16 |= 3; /* gen3 */
+		tmp16 |= PCI_EXP_LNKCTL2_TLS_8_0GT; /* gen3 */
 	else if (speed_cap == PCIE_SPEED_5_0GT)
-		tmp16 |= 2; /* gen2 */
+		tmp16 |= PCI_EXP_LNKCTL2_TLS_5_0GT; /* gen2 */
 	else
-		tmp16 |= 1; /* gen1 */
-	pci_write_config_word(rdev->pdev, gpu_pos + PCI_EXP_LNKCTL2, tmp16);
+		tmp16 |= PCI_EXP_LNKCTL2_TLS_2_5GT; /* gen1 */
+	pcie_capability_write_word(rdev->pdev, PCI_EXP_LNKCTL2, tmp16);
 
 	speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL);
 	speed_cntl |= LC_INITIATE_LINK_SPEED_CHANGE;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/si_dpm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/si_dpm.c
@@ -3002,6 +3002,9 @@
 		    (rdev->pdev->device == 0x6605)) {
 			max_sclk = 75000;
 		}
+
+		if (rdev->pm.dpm.high_pixelclock_count > 1)
+			disable_sclk_switching = true;
 	}
 
 	if (rps->vce_active) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/sumo_dpm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/sumo_dpm.c
@@ -1493,8 +1493,10 @@
 		non_clock_array_index = power_state->v2.nonClockInfoIndex;
 		non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
 			&non_clock_info_array->nonClockInfo[non_clock_array_index];
-		if (!rdev->pm.power_state[i].clock_info)
+		if (!rdev->pm.power_state[i].clock_info) {
+			kfree(rdev->pm.dpm.ps);
 			return -EINVAL;
+		}
 		ps = kzalloc(sizeof(struct sumo_ps), GFP_KERNEL);
 		if (ps == NULL) {
 			kfree(rdev->pm.dpm.ps);
@@ -1619,6 +1621,8 @@
 
 	for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++) {
 		if (table[i].ulSupportedSCLK != 0) {
+			if (table[i].usVoltageIndex >= SUMO_MAX_NUMBER_VOLTAGES)
+				continue;
 			vid_mapping_table->entries[table[i].usVoltageIndex].vid_7bit =
 				table[i].usVoltageID;
 			vid_mapping_table->entries[table[i].usVoltageIndex].vid_2bit =
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/radeon/trinity_dpm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/radeon/trinity_dpm.c
@@ -1771,8 +1771,10 @@
 		non_clock_array_index = power_state->v2.nonClockInfoIndex;
 		non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
 			&non_clock_info_array->nonClockInfo[non_clock_array_index];
-		if (!rdev->pm.power_state[i].clock_info)
+		if (!rdev->pm.power_state[i].clock_info) {
+			kfree(rdev->pm.dpm.ps);
 			return -EINVAL;
+		}
 		ps = kzalloc(sizeof(struct sumo_ps), GFP_KERNEL);
 		if (ps == NULL) {
 			kfree(rdev->pm.dpm.ps);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/rcar-du/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/rcar-du/Kconfig
@@ -23,6 +23,7 @@
 config DRM_RCAR_LVDS
 	tristate "R-Car DU LVDS Encoder Support"
 	depends on DRM && DRM_BRIDGE && OF
+	select DRM_KMS_HELPER
 	select DRM_PANEL
 	select OF_FLATTREE
 	select OF_OVERLAY
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -785,13 +785,15 @@
 
 		drm_plane_create_alpha_property(&plane->plane);
 
-		if (type == DRM_PLANE_TYPE_PRIMARY)
-			continue;
-
-		drm_object_attach_property(&plane->plane.base,
-					   rcdu->props.colorkey,
-					   RCAR_DU_COLORKEY_NONE);
-		drm_plane_create_zpos_property(&plane->plane, 1, 1, 7);
+		if (type == DRM_PLANE_TYPE_PRIMARY) {
+			drm_plane_create_zpos_immutable_property(&plane->plane,
+								 0);
+		} else {
+			drm_object_attach_property(&plane->plane.base,
+						   rcdu->props.colorkey,
+						   RCAR_DU_COLORKEY_NONE);
+			drm_plane_create_zpos_property(&plane->plane, 1, 1, 7);
+		}
 	}
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/rcar-du/rcar_du_vsp.c
@@ -392,12 +392,14 @@
 		drm_plane_helper_add(&plane->plane,
 				     &rcar_du_vsp_plane_helper_funcs);
 
-		if (type == DRM_PLANE_TYPE_PRIMARY)
-			continue;
-
-		drm_plane_create_alpha_property(&plane->plane);
-		drm_plane_create_zpos_property(&plane->plane, 1, 1,
-					       vsp->num_planes - 1);
+		if (type == DRM_PLANE_TYPE_PRIMARY) {
+			drm_plane_create_zpos_immutable_property(&plane->plane,
+								 0);
+		} else {
+			drm_plane_create_alpha_property(&plane->plane);
+			drm_plane_create_zpos_property(&plane->plane, 1, 1,
+						       vsp->num_planes - 1);
+		}
 	}
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/rcar-du/rcar_lvds.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/rcar-du/rcar_lvds.c
@@ -16,6 +16,7 @@
 #include <linux/of_graph.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
+#include <linux/sys_soc.h>
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
@@ -842,8 +843,23 @@
 	return 0;
 }
 
+static const struct rcar_lvds_device_info rcar_lvds_r8a7790es1_info = {
+	.gen = 2,
+	.quirks = RCAR_LVDS_QUIRK_LANES,
+	.pll_setup = rcar_lvds_pll_setup_gen2,
+};
+
+static const struct soc_device_attribute lvds_quirk_matches[] = {
+	{
+		.soc_id = "r8a7790", .revision = "ES1.*",
+		.data = &rcar_lvds_r8a7790es1_info,
+	},
+	{ /* sentinel */ }
+};
+
 static int rcar_lvds_probe(struct platform_device *pdev)
 {
+	const struct soc_device_attribute *attr;
 	struct rcar_lvds *lvds;
 	struct resource *mem;
 	int ret;
@@ -857,6 +873,10 @@
 	lvds->dev = &pdev->dev;
 	lvds->info = of_device_get_match_data(&pdev->dev);
 
+	attr = soc_device_match(lvds_quirk_matches);
+	if (attr)
+		lvds->info = attr->data;
+
 	ret = rcar_lvds_parse_dt(lvds);
 	if (ret < 0)
 		return ret;
@@ -893,12 +913,6 @@
 	.pll_setup = rcar_lvds_pll_setup_gen2,
 };
 
-static const struct rcar_lvds_device_info rcar_lvds_r8a7790_info = {
-	.gen = 2,
-	.quirks = RCAR_LVDS_QUIRK_LANES,
-	.pll_setup = rcar_lvds_pll_setup_gen2,
-};
-
 static const struct rcar_lvds_device_info rcar_lvds_gen3_info = {
 	.gen = 3,
 	.quirks = RCAR_LVDS_QUIRK_PWD,
@@ -930,7 +944,7 @@
 	{ .compatible = "renesas,r8a7744-lvds", .data = &rcar_lvds_gen2_info },
 	{ .compatible = "renesas,r8a774a1-lvds", .data = &rcar_lvds_gen3_info },
 	{ .compatible = "renesas,r8a774c0-lvds", .data = &rcar_lvds_r8a77990_info },
-	{ .compatible = "renesas,r8a7790-lvds", .data = &rcar_lvds_r8a7790_info },
+	{ .compatible = "renesas,r8a7790-lvds", .data = &rcar_lvds_gen2_info },
 	{ .compatible = "renesas,r8a7791-lvds", .data = &rcar_lvds_gen2_info },
 	{ .compatible = "renesas,r8a7793-lvds", .data = &rcar_lvds_gen2_info },
 	{ .compatible = "renesas,r8a7795-lvds", .data = &rcar_lvds_gen3_info },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -325,15 +325,9 @@
 			    void *data)
 {
 	struct rockchip_dp_device *dp = dev_get_drvdata(dev);
-	const struct rockchip_dp_chip_data *dp_data;
 	struct drm_device *drm_dev = data;
 	int ret;
 
-	dp_data = of_device_get_match_data(dev);
-	if (!dp_data)
-		return -ENODEV;
-
-	dp->data = dp_data;
 	dp->drm_dev = drm_dev;
 
 	ret = rockchip_dp_drm_create_encoder(dp);
@@ -344,16 +338,9 @@
 
 	dp->plat_data.encoder = &dp->encoder;
 
-	dp->plat_data.dev_type = dp->data->chip_type;
-	dp->plat_data.power_on_start = rockchip_dp_poweron_start;
-	dp->plat_data.power_off = rockchip_dp_powerdown;
-	dp->plat_data.get_modes = rockchip_dp_get_modes;
-
-	dp->adp = analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data);
-	if (IS_ERR(dp->adp)) {
-		ret = PTR_ERR(dp->adp);
+	ret = analogix_dp_bind(dp->adp, drm_dev);
+	if (ret)
 		goto err_cleanup_encoder;
-	}
 
 	return 0;
 err_cleanup_encoder:
@@ -368,8 +355,6 @@
 
 	analogix_dp_unbind(dp->adp);
 	dp->encoder.funcs->destroy(&dp->encoder);
-
-	dp->adp = ERR_PTR(-ENODEV);
 }
 
 static const struct component_ops rockchip_dp_component_ops = {
@@ -380,10 +365,15 @@
 static int rockchip_dp_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
+	const struct rockchip_dp_chip_data *dp_data;
 	struct drm_panel *panel = NULL;
 	struct rockchip_dp_device *dp;
 	int ret;
 
+	dp_data = of_device_get_match_data(dev);
+	if (!dp_data)
+		return -ENODEV;
+
 	ret = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, &panel, NULL);
 	if (ret < 0)
 		return ret;
@@ -394,7 +384,12 @@
 
 	dp->dev = dev;
 	dp->adp = ERR_PTR(-ENODEV);
+	dp->data = dp_data;
 	dp->plat_data.panel = panel;
+	dp->plat_data.dev_type = dp->data->chip_type;
+	dp->plat_data.power_on_start = rockchip_dp_poweron_start;
+	dp->plat_data.power_off = rockchip_dp_powerdown;
+	dp->plat_data.get_modes = rockchip_dp_get_modes;
 
 	ret = rockchip_dp_of_probe(dp);
 	if (ret < 0)
@@ -402,12 +397,27 @@
 
 	platform_set_drvdata(pdev, dp);
 
-	return component_add(dev, &rockchip_dp_component_ops);
+	dp->adp = analogix_dp_probe(dev, &dp->plat_data);
+	if (IS_ERR(dp->adp))
+		return PTR_ERR(dp->adp);
+
+	ret = component_add(dev, &rockchip_dp_component_ops);
+	if (ret)
+		goto err_dp_remove;
+
+	return 0;
+
+err_dp_remove:
+	analogix_dp_remove(dp->adp);
+	return ret;
 }
 
 static int rockchip_dp_remove(struct platform_device *pdev)
 {
+	struct rockchip_dp_device *dp = platform_get_drvdata(pdev);
+
 	component_del(&pdev->dev, &rockchip_dp_component_ops);
+	analogix_dp_remove(dp->adp);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -72,6 +72,7 @@
 	ret = regmap_write(dp->grf, reg, val);
 	if (ret) {
 		DRM_DEV_ERROR(dp->dev, "Could not write to GRF: %d\n", ret);
+		clk_disable_unprepare(dp->grf_clk);
 		return ret;
 	}
 
@@ -274,8 +275,9 @@
 	return ret;
 }
 
-static int cdn_dp_connector_mode_valid(struct drm_connector *connector,
-				       struct drm_display_mode *mode)
+static enum drm_mode_status
+cdn_dp_connector_mode_valid(struct drm_connector *connector,
+			    struct drm_display_mode *mode)
 {
 	struct cdn_dp_device *dp = connector_to_dp(connector);
 	struct drm_display_info *display_info = &dp->connector.display_info;
@@ -561,7 +563,7 @@
 	video->v_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NVSYNC);
 	video->h_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NHSYNC);
 
-	memcpy(&dp->mode, adjusted, sizeof(*mode));
+	drm_mode_copy(&dp->mode, adjusted);
 }
 
 static bool cdn_dp_check_link_status(struct cdn_dp_device *dp)
@@ -1145,6 +1147,7 @@
 	struct cdn_dp_device *dp;
 	struct extcon_dev *extcon;
 	struct phy *phy;
+	int ret;
 	int i;
 
 	dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
@@ -1185,9 +1188,19 @@
 	mutex_init(&dp->lock);
 	dev_set_drvdata(dev, dp);
 
-	cdn_dp_audio_codec_init(dp, dev);
+	ret = cdn_dp_audio_codec_init(dp, dev);
+	if (ret)
+		return ret;
+
+	ret = component_add(dev, &cdn_dp_component_ops);
+	if (ret)
+		goto err_audio_deinit;
+
+	return 0;
 
-	return component_add(dev, &cdn_dp_component_ops);
+err_audio_deinit:
+	platform_device_unregister(dp->audio_pdev);
+	return ret;
 }
 
 static int cdn_dp_remove(struct platform_device *pdev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
@@ -231,7 +231,8 @@
 	struct dw_mipi_dsi *dmd;
 	const struct rockchip_dw_dsi_chip_data *cdata;
 	struct dw_mipi_dsi_plat_data pdata;
-	int devcnt;
+
+	bool dsi_bound;
 };
 
 struct dphy_pll_parameter_map {
@@ -480,8 +481,8 @@
 	unsigned long best_freq = 0;
 	unsigned long fvco_min, fvco_max, fin, fout;
 	unsigned int min_prediv, max_prediv;
-	unsigned int _prediv, uninitialized_var(best_prediv);
-	unsigned long _fbdiv, uninitialized_var(best_fbdiv);
+	unsigned int _prediv, best_prediv;
+	unsigned long _fbdiv, best_fbdiv;
 	unsigned long min_delta = ULONG_MAX;
 
 	dsi->format = format;
@@ -564,13 +565,8 @@
 	.get_lane_mbps = dw_mipi_dsi_get_lane_mbps,
 };
 
-static void dw_mipi_dsi_rockchip_config(struct dw_mipi_dsi_rockchip *dsi,
-					int mux)
+static void dw_mipi_dsi_rockchip_config(struct dw_mipi_dsi_rockchip *dsi)
 {
-	if (dsi->cdata->lcdsel_grf_reg)
-		regmap_write(dsi->grf_regmap, dsi->cdata->lcdsel_grf_reg,
-			mux ? dsi->cdata->lcdsel_lit : dsi->cdata->lcdsel_big);
-
 	if (dsi->cdata->lanecfg1_grf_reg)
 		regmap_write(dsi->grf_regmap, dsi->cdata->lanecfg1_grf_reg,
 					      dsi->cdata->lanecfg1);
@@ -584,6 +580,13 @@
 					      dsi->cdata->enable);
 }
 
+static void dw_mipi_dsi_rockchip_set_lcdsel(struct dw_mipi_dsi_rockchip *dsi,
+					    int mux)
+{
+	regmap_write(dsi->grf_regmap, dsi->cdata->lcdsel_grf_reg,
+		mux ? dsi->cdata->lcdsel_lit : dsi->cdata->lcdsel_big);
+}
+
 static int
 dw_mipi_dsi_encoder_atomic_check(struct drm_encoder *encoder,
 				 struct drm_crtc_state *crtc_state,
@@ -624,10 +627,6 @@
 	if (mux < 0)
 		return;
 
-	pm_runtime_get_sync(dsi->dev);
-	if (dsi->slave)
-		pm_runtime_get_sync(dsi->slave->dev);
-
 	/*
 	 * For the RK3399, the clk of grf must be enabled before writing grf
 	 * register. And for RK3288 or other soc, this grf_clk must be NULL,
@@ -639,27 +638,17 @@
 		return;
 	}
 
-	dw_mipi_dsi_rockchip_config(dsi, mux);
+	dw_mipi_dsi_rockchip_set_lcdsel(dsi, mux);
 	if (dsi->slave)
-		dw_mipi_dsi_rockchip_config(dsi->slave, mux);
+		dw_mipi_dsi_rockchip_set_lcdsel(dsi->slave, mux);
 
 	clk_disable_unprepare(dsi->grf_clk);
 }
 
-static void dw_mipi_dsi_encoder_disable(struct drm_encoder *encoder)
-{
-	struct dw_mipi_dsi_rockchip *dsi = to_dsi(encoder);
-
-	if (dsi->slave)
-		pm_runtime_put(dsi->slave->dev);
-	pm_runtime_put(dsi->dev);
-}
-
 static const struct drm_encoder_helper_funcs
 dw_mipi_dsi_encoder_helper_funcs = {
 	.atomic_check = dw_mipi_dsi_encoder_atomic_check,
 	.enable = dw_mipi_dsi_encoder_enable,
-	.disable = dw_mipi_dsi_encoder_disable,
 };
 
 static const struct drm_encoder_funcs dw_mipi_dsi_encoder_funcs = {
@@ -794,25 +783,56 @@
 		put_device(second);
 	}
 
+	pm_runtime_get_sync(dsi->dev);
+	if (dsi->slave)
+		pm_runtime_get_sync(dsi->slave->dev);
+
 	ret = clk_prepare_enable(dsi->pllref_clk);
 	if (ret) {
 		DRM_DEV_ERROR(dev, "Failed to enable pllref_clk: %d\n", ret);
-		return ret;
+		goto out_pm_runtime;
+	}
+
+	/*
+	 * With the GRF clock running, write lane and dual-mode configurations
+	 * that won't change immediately. If we waited until enable() to do
+	 * this, things like panel preparation would not be able to send
+	 * commands over DSI.
+	 */
+	ret = clk_prepare_enable(dsi->grf_clk);
+	if (ret) {
+		DRM_DEV_ERROR(dsi->dev, "Failed to enable grf_clk: %d\n", ret);
+		goto out_pm_runtime;
 	}
 
+	dw_mipi_dsi_rockchip_config(dsi);
+	if (dsi->slave)
+		dw_mipi_dsi_rockchip_config(dsi->slave);
+
+	clk_disable_unprepare(dsi->grf_clk);
+
 	ret = rockchip_dsi_drm_create_encoder(dsi, drm_dev);
 	if (ret) {
 		DRM_DEV_ERROR(dev, "Failed to create drm encoder\n");
-		return ret;
+		goto out_pm_runtime;
 	}
 
 	ret = dw_mipi_dsi_bind(dsi->dmd, &dsi->encoder);
 	if (ret) {
 		DRM_DEV_ERROR(dev, "Failed to bind: %d\n", ret);
-		return ret;
+		goto out_pm_runtime;
 	}
 
+	dsi->dsi_bound = true;
+
 	return 0;
+
+out_pm_runtime:
+	pm_runtime_put(dsi->dev);
+	if (dsi->slave)
+		pm_runtime_put(dsi->slave->dev);
+
+	return ret;
 }
 
 static void dw_mipi_dsi_rockchip_unbind(struct device *dev,
@@ -824,9 +844,15 @@
 	if (dsi->is_slave)
 		return;
 
+	dsi->dsi_bound = false;
+
 	dw_mipi_dsi_unbind(dsi->dmd);
 
 	clk_disable_unprepare(dsi->pllref_clk);
+
+	pm_runtime_put(dsi->dev);
+	if (dsi->slave)
+		pm_runtime_put(dsi->slave->dev);
 }
 
 static const struct component_ops dw_mipi_dsi_rockchip_ops = {
@@ -884,6 +910,36 @@
 	.detach = dw_mipi_dsi_rockchip_host_detach,
 };
 
+static int __maybe_unused dw_mipi_dsi_rockchip_resume(struct device *dev)
+{
+	struct dw_mipi_dsi_rockchip *dsi = dev_get_drvdata(dev);
+	int ret;
+
+	/*
+	 * Re-configure DSI state, if we were previously initialized. We need
+	 * to do this before rockchip_drm_drv tries to re-enable() any panels.
+	 */
+	if (dsi->dsi_bound) {
+		ret = clk_prepare_enable(dsi->grf_clk);
+		if (ret) {
+			DRM_DEV_ERROR(dsi->dev, "Failed to enable grf_clk: %d\n", ret);
+			return ret;
+		}
+
+		dw_mipi_dsi_rockchip_config(dsi);
+		if (dsi->slave)
+			dw_mipi_dsi_rockchip_config(dsi->slave);
+
+		clk_disable_unprepare(dsi->grf_clk);
+	}
+
+	return 0;
+}
+
+static const struct dev_pm_ops dw_mipi_dsi_rockchip_pm_ops = {
+	SET_LATE_SYSTEM_SLEEP_PM_OPS(NULL, dw_mipi_dsi_rockchip_resume)
+};
+
 static int dw_mipi_dsi_rockchip_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -967,23 +1023,16 @@
 		if (ret != -EPROBE_DEFER)
 			DRM_DEV_ERROR(dev,
 				      "Failed to probe dw_mipi_dsi: %d\n", ret);
-		goto err_clkdisable;
+		return ret;
 	}
 
 	return 0;
-
-err_clkdisable:
-	clk_disable_unprepare(dsi->pllref_clk);
-	return ret;
 }
 
 static int dw_mipi_dsi_rockchip_remove(struct platform_device *pdev)
 {
 	struct dw_mipi_dsi_rockchip *dsi = platform_get_drvdata(pdev);
 
-	if (dsi->devcnt == 0)
-		component_del(dsi->dev, &dw_mipi_dsi_rockchip_ops);
-
 	dw_mipi_dsi_remove(dsi->dmd);
 
 	return 0;
@@ -1072,6 +1121,13 @@
 	.remove		= dw_mipi_dsi_rockchip_remove,
 	.driver		= {
 		.of_match_table = dw_mipi_dsi_rockchip_dt_ids,
+		.pm	= &dw_mipi_dsi_rockchip_pm_ops,
 		.name	= "dw-mipi-dsi-rockchip",
+		/*
+		 * For dual-DSI display, one DSI pokes at the other DSI's
+		 * drvdata in dw_mipi_dsi_rockchip_find_second(). This is not
+		 * safe for asynchronous probe.
+		 */
+		.probe_type = PROBE_FORCE_SYNCHRONOUS,
 	},
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -390,6 +390,8 @@
 		HIWORD_UPDATE(RK3328_HDMI_SDAIN_MSK | RK3328_HDMI_SCLIN_MSK,
 			      RK3328_HDMI_SDAIN_MSK | RK3328_HDMI_SCLIN_MSK |
 			      RK3328_HDMI_HPD_IOE));
+
+	dw_hdmi_rk3328_read_hpd(dw_hdmi, data);
 }
 
 static const struct dw_hdmi_phy_ops rk3228_hdmi_phy_ops = {
@@ -528,13 +530,6 @@
 		return ret;
 	}
 
-	ret = clk_prepare_enable(hdmi->vpll_clk);
-	if (ret) {
-		DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI vpll: %d\n",
-			      ret);
-		return ret;
-	}
-
 	hdmi->phy = devm_phy_optional_get(dev, "hdmi");
 	if (IS_ERR(hdmi->phy)) {
 		ret = PTR_ERR(hdmi->phy);
@@ -543,6 +538,13 @@
 		return ret;
 	}
 
+	ret = clk_prepare_enable(hdmi->vpll_clk);
+	if (ret) {
+		DRM_DEV_ERROR(hdmi->dev, "Failed to enable HDMI vpll: %d\n",
+			      ret);
+		return ret;
+	}
+
 	drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs);
 	drm_encoder_init(drm, encoder, &dw_hdmi_rockchip_encoder_funcs,
 			 DRM_MODE_ENCODER_TMDS, NULL);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/rockchip/inno_hdmi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/rockchip/inno_hdmi.c
@@ -401,7 +401,7 @@
 	hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_L, value & 0xFF);
 	hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_H, (value >> 8) & 0xFF);
 
-	value = mode->hsync_start - mode->hdisplay;
+	value = mode->htotal - mode->hsync_start;
 	hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_L, value & 0xFF);
 	hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_H, (value >> 8) & 0xFF);
 
@@ -416,7 +416,7 @@
 	value = mode->vtotal - mode->vdisplay;
 	hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VBLANK, value & 0xFF);
 
-	value = mode->vsync_start - mode->vdisplay;
+	value = mode->vtotal - mode->vsync_start;
 	hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VDELAY, value & 0xFF);
 
 	value = mode->vsync_end - mode->vsync_start;
@@ -487,7 +487,7 @@
 	inno_hdmi_setup(hdmi, adj_mode);
 
 	/* Store the display mode for plugin/DPMS poweron events */
-	memcpy(&hdmi->previous_mode, adj_mode, sizeof(hdmi->previous_mode));
+	drm_mode_copy(&hdmi->previous_mode, adj_mode);
 }
 
 static void inno_hdmi_encoder_enable(struct drm_encoder *encoder)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/rockchip/rk3066_hdmi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/rockchip/rk3066_hdmi.c
@@ -382,7 +382,7 @@
 	struct rk3066_hdmi *hdmi = to_rk3066_hdmi(encoder);
 
 	/* Store the display mode for plugin/DPMS poweron events. */
-	memcpy(&hdmi->previous_mode, adj_mode, sizeof(hdmi->previous_mode));
+	drm_mode_copy(&hdmi->previous_mode, adj_mode);
 }
 
 static void rk3066_hdmi_encoder_enable(struct drm_encoder *encoder)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
@@ -249,9 +249,6 @@
 	else
 		ret = rockchip_drm_gem_object_mmap_dma(obj, vma);
 
-	if (ret)
-		drm_gem_vm_close(vma);
-
 	return ret;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -234,14 +234,22 @@
 	VOP_REG_SET(vop, common, cfg_done, 1);
 }
 
-static bool has_rb_swapped(uint32_t format)
+static bool has_rb_swapped(uint32_t version, uint32_t format)
 {
 	switch (format) {
 	case DRM_FORMAT_XBGR8888:
 	case DRM_FORMAT_ABGR8888:
-	case DRM_FORMAT_BGR888:
 	case DRM_FORMAT_BGR565:
 		return true;
+	/*
+	 * full framework (IP version 3.x) only need rb swapped for RGB888 and
+	 * little framework (IP version 2.x) only need rb swapped for BGR888,
+	 * check for 3.x to also only rb swap BGR888 for unknown vop version
+	 */
+	case DRM_FORMAT_RGB888:
+		return VOP_MAJOR(version) == 3;
+	case DRM_FORMAT_BGR888:
+		return VOP_MAJOR(version) != 3;
 	default:
 		return false;
 	}
@@ -325,8 +333,8 @@
 	if (info->is_yuv)
 		is_yuv = true;
 
-	if (dst_w > 3840) {
-		DRM_DEV_ERROR(vop->dev, "Maximum dst width (3840) exceeded\n");
+	if (dst_w > 4096) {
+		DRM_DEV_ERROR(vop->dev, "Maximum dst width (4096) exceeded\n");
 		return;
 	}
 
@@ -654,13 +662,13 @@
 	if (crtc->state->self_refresh_active)
 		rockchip_drm_set_win_enabled(crtc, false);
 
+	if (crtc->state->self_refresh_active)
+		goto out;
+
 	mutex_lock(&vop->vop_lock);
 
 	drm_crtc_vblank_off(crtc);
 
-	if (crtc->state->self_refresh_active)
-		goto out;
-
 	/*
 	 * Vop standby will take effect at end of current frame,
 	 * if dsp hold valid irq happen, it means standby complete.
@@ -692,9 +700,9 @@
 	vop_core_clks_disable(vop);
 	pm_runtime_put(vop->dev);
 
-out:
 	mutex_unlock(&vop->vop_lock);
 
+out:
 	if (crtc->state->event && !crtc->state->active) {
 		spin_lock_irq(&crtc->dev->event_lock);
 		drm_crtc_send_vblank_event(crtc, crtc->state->event);
@@ -886,7 +894,7 @@
 	VOP_WIN_SET(vop, win, dsp_info, dsp_info);
 	VOP_WIN_SET(vop, win, dsp_st, dsp_st);
 
-	rb_swap = has_rb_swapped(fb->format->format);
+	rb_swap = has_rb_swapped(vop->data->version, fb->format->format);
 	VOP_WIN_SET(vop, win, rb_swap, rb_swap);
 
 	/*
@@ -1040,10 +1048,41 @@
 				struct drm_display_mode *adjusted_mode)
 {
 	struct vop *vop = to_vop(crtc);
+	unsigned long rate;
 
-	adjusted_mode->clock =
-		DIV_ROUND_UP(clk_round_rate(vop->dclk,
-					    adjusted_mode->clock * 1000), 1000);
+	/*
+	 * Clock craziness.
+	 *
+	 * Key points:
+	 *
+	 * - DRM works in in kHz.
+	 * - Clock framework works in Hz.
+	 * - Rockchip's clock driver picks the clock rate that is the
+	 *   same _OR LOWER_ than the one requested.
+	 *
+	 * Action plan:
+	 *
+	 * 1. When DRM gives us a mode, we should add 999 Hz to it.  That way
+	 *    if the clock we need is 60000001 Hz (~60 MHz) and DRM tells us to
+	 *    make 60000 kHz then the clock framework will actually give us
+	 *    the right clock.
+	 *
+	 *    NOTE: if the PLL (maybe through a divider) could actually make
+	 *    a clock rate 999 Hz higher instead of the one we want then this
+	 *    could be a problem.  Unfortunately there's not much we can do
+	 *    since it's baked into DRM to use kHz.  It shouldn't matter in
+	 *    practice since Rockchip PLLs are controlled by tables and
+	 *    even if there is a divider in the middle I wouldn't expect PLL
+	 *    rates in the table that are just a few kHz different.
+	 *
+	 * 2. Get the clock framework to round the rate for us to tell us
+	 *    what it will actually make.
+	 *
+	 * 3. Store the rounded up rate so that we don't need to worry about
+	 *    this in the actual clk_set_rate().
+	 */
+	rate = clk_round_rate(vop->dclk, adjusted_mode->clock * 1000 + 999);
+	adjusted_mode->clock = DIV_ROUND_UP(rate, 1000);
 
 	return true;
 }
@@ -1257,7 +1296,11 @@
 {
 	struct rockchip_crtc_state *rockchip_state;
 
-	rockchip_state = kzalloc(sizeof(*rockchip_state), GFP_KERNEL);
+	if (WARN_ON(!crtc->state))
+		return NULL;
+
+	rockchip_state = kmemdup(to_rockchip_crtc_state(crtc->state),
+				 sizeof(*rockchip_state), GFP_KERNEL);
 	if (!rockchip_state)
 		return NULL;
 
@@ -1282,7 +1325,10 @@
 	if (crtc->state)
 		vop_crtc_destroy_state(crtc, crtc->state);
 
-	__drm_atomic_helper_crtc_reset(crtc, &crtc_state->base);
+	if (crtc_state)
+		__drm_atomic_helper_crtc_reset(crtc, &crtc_state->base);
+	else
+		__drm_atomic_helper_crtc_reset(crtc, NULL);
 }
 
 #ifdef CONFIG_DRM_ANALOGIX_DP
@@ -1817,10 +1863,10 @@
 	vop_win_init(vop);
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	vop->len = resource_size(res);
 	vop->regs = devm_ioremap_resource(dev, res);
 	if (IS_ERR(vop->regs))
 		return PTR_ERR(vop->regs);
+	vop->len = resource_size(res);
 
 	vop->regsbak = devm_kzalloc(dev, vop->len, GFP_KERNEL);
 	if (!vop->regsbak)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/rockchip/rockchip_lvds.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/rockchip/rockchip_lvds.c
@@ -366,7 +366,6 @@
 		goto err_put_port;
 	} else if (ret) {
 		DRM_DEV_ERROR(dev, "failed to find panel and bridge node\n");
-		ret = -EPROBE_DEFER;
 		goto err_put_port;
 	}
 	if (lvds->panel)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/scheduler/gpu_scheduler_trace.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/scheduler/gpu_scheduler_trace.h
@@ -21,7 +21,7 @@
  *
  */
 
-#if !defined(_GPU_SCHED_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+#if !defined(_GPU_SCHED_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
 #define _GPU_SCHED_TRACE_H_
 
 #include <linux/stringify.h>
@@ -96,7 +96,7 @@
 		      __entry->seqno)
 );
 
-#endif
+#endif /* _GPU_SCHED_TRACE_H_ */
 
 /* This part must be outside protection */
 #undef TRACE_INCLUDE_PATH
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/scheduler/sched_entity.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/scheduler/sched_entity.c
@@ -235,11 +235,16 @@
 static void drm_sched_entity_kill_jobs(struct drm_sched_entity *entity)
 {
 	struct drm_sched_job *job;
+	struct dma_fence *f;
 	int r;
 
 	while ((job = to_drm_sched_job(spsc_queue_pop(&entity->job_queue)))) {
 		struct drm_sched_fence *s_fence = job->s_fence;
 
+		/* Wait for all dependencies to avoid data corruptions */
+		while ((f = job->sched->ops->dependency(job, entity)))
+			dma_fence_wait(f, false);
+
 		drm_sched_fence_scheduled(s_fence);
 		dma_fence_set_error(&s_fence->finished, -ESRCH);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/scheduler/sched_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/scheduler/sched_main.c
@@ -284,10 +284,21 @@
 	unsigned long flags;
 
 	sched = container_of(work, struct drm_gpu_scheduler, work_tdr.work);
+
+	/* Protects against concurrent deletion in drm_sched_get_cleanup_job */
+	spin_lock_irqsave(&sched->job_list_lock, flags);
 	job = list_first_entry_or_null(&sched->ring_mirror_list,
 				       struct drm_sched_job, node);
 
 	if (job) {
+		/*
+		 * Remove the bad job so it cannot be freed by concurrent
+		 * drm_sched_cleanup_jobs. It will be reinserted back after sched->thread
+		 * is parked at which point it's safe.
+		 */
+		list_del_init(&job->node);
+		spin_unlock_irqrestore(&sched->job_list_lock, flags);
+
 		job->sched->ops->timedout_job(job);
 
 		/*
@@ -298,6 +309,8 @@
 			job->sched->ops->free_job(job);
 			sched->free_guilty = false;
 		}
+	} else {
+		spin_unlock_irqrestore(&sched->job_list_lock, flags);
 	}
 
 	spin_lock_irqsave(&sched->job_list_lock, flags);
@@ -370,6 +383,20 @@
 	kthread_park(sched->thread);
 
 	/*
+	 * Reinsert back the bad job here - now it's safe as
+	 * drm_sched_get_cleanup_job cannot race against us and release the
+	 * bad job at this point - we parked (waited for) any in progress
+	 * (earlier) cleanups and drm_sched_get_cleanup_job will not be called
+	 * now until the scheduler thread is unparked.
+	 */
+	if (bad && bad->sched == sched)
+		/*
+		 * Add at the head of the queue to reflect it was the earliest
+		 * job extracted.
+		 */
+		list_add(&bad->node, &sched->ring_mirror_list);
+
+	/*
 	 * Iterate the job list from later to  earlier one and either deactive
 	 * their HW callbacks or remove them from mirror list if they already
 	 * signaled.
@@ -496,8 +523,10 @@
 		fence = sched->ops->run_job(s_job);
 
 		if (IS_ERR_OR_NULL(fence)) {
+			if (IS_ERR(fence))
+				dma_fence_set_error(&s_fence->finished, PTR_ERR(fence));
+
 			s_job->s_fence->parent = NULL;
-			dma_fence_set_error(&s_fence->finished, PTR_ERR(fence));
 		} else {
 			s_job->s_fence->parent = fence;
 		}
@@ -627,48 +656,48 @@
 
 	trace_drm_sched_process_job(s_fence);
 
+	dma_fence_get(&s_fence->finished);
 	drm_sched_fence_finished(s_fence);
+	dma_fence_put(&s_fence->finished);
 	wake_up_interruptible(&sched->wake_up_worker);
 }
 
 /**
- * drm_sched_cleanup_jobs - destroy finished jobs
+ * drm_sched_get_cleanup_job - fetch the next finished job to be destroyed
  *
  * @sched: scheduler instance
  *
- * Remove all finished jobs from the mirror list and destroy them.
+ * Returns the next finished job from the mirror list (if there is one)
+ * ready for it to be destroyed.
  */
-static void drm_sched_cleanup_jobs(struct drm_gpu_scheduler *sched)
+static struct drm_sched_job *
+drm_sched_get_cleanup_job(struct drm_gpu_scheduler *sched)
 {
+	struct drm_sched_job *job;
 	unsigned long flags;
 
 	/* Don't destroy jobs while the timeout worker is running */
 	if (sched->timeout != MAX_SCHEDULE_TIMEOUT &&
 	    !cancel_delayed_work(&sched->work_tdr))
-		return;
-
+		return NULL;
 
-	while (!list_empty(&sched->ring_mirror_list)) {
-		struct drm_sched_job *job;
+	spin_lock_irqsave(&sched->job_list_lock, flags);
 
-		job = list_first_entry(&sched->ring_mirror_list,
+	job = list_first_entry_or_null(&sched->ring_mirror_list,
 				       struct drm_sched_job, node);
-		if (!dma_fence_is_signaled(&job->s_fence->finished))
-			break;
 
-		spin_lock_irqsave(&sched->job_list_lock, flags);
+	if (job && dma_fence_is_signaled(&job->s_fence->finished)) {
 		/* remove job from ring_mirror_list */
 		list_del_init(&job->node);
-		spin_unlock_irqrestore(&sched->job_list_lock, flags);
-
-		sched->ops->free_job(job);
+	} else {
+		job = NULL;
+		/* queue timeout for next job */
+		drm_sched_start_timeout(sched);
 	}
 
-	/* queue timeout for next job */
-	spin_lock_irqsave(&sched->job_list_lock, flags);
-	drm_sched_start_timeout(sched);
 	spin_unlock_irqrestore(&sched->job_list_lock, flags);
 
+	return job;
 }
 
 /**
@@ -708,12 +737,19 @@
 		struct drm_sched_fence *s_fence;
 		struct drm_sched_job *sched_job;
 		struct dma_fence *fence;
+		struct drm_sched_job *cleanup_job = NULL;
 
 		wait_event_interruptible(sched->wake_up_worker,
-					 (drm_sched_cleanup_jobs(sched),
+					 (cleanup_job = drm_sched_get_cleanup_job(sched)) ||
 					 (!drm_sched_blocked(sched) &&
 					  (entity = drm_sched_select_entity(sched))) ||
-					 kthread_should_stop()));
+					 kthread_should_stop());
+
+		if (cleanup_job) {
+			sched->ops->free_job(cleanup_job);
+			/* queue timeout for next job */
+			drm_sched_start_timeout(sched);
+		}
 
 		if (!entity)
 			continue;
@@ -741,8 +777,9 @@
 					  r);
 			dma_fence_put(fence);
 		} else {
+			if (IS_ERR(fence))
+				dma_fence_set_error(&s_fence->finished, PTR_ERR(fence));
 
-			dma_fence_set_error(&s_fence->finished, PTR_ERR(fence));
 			drm_sched_process_job(NULL, &sched_job->cb);
 		}
 
@@ -814,6 +851,9 @@
 	if (sched->thread)
 		kthread_stop(sched->thread);
 
+	/* Confirm no work left behind accessing device structures */
+	cancel_delayed_work_sync(&sched->work_tdr);
+
 	sched->ready = false;
 }
 EXPORT_SYMBOL(drm_sched_fini);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/selftests/drm_cmdline_selftests.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/selftests/drm_cmdline_selftests.h
@@ -53,6 +53,7 @@
 cmdline_test(drm_cmdline_test_rotate_90)
 cmdline_test(drm_cmdline_test_rotate_180)
 cmdline_test(drm_cmdline_test_rotate_270)
+cmdline_test(drm_cmdline_test_rotate_multiple)
 cmdline_test(drm_cmdline_test_rotate_invalid_val)
 cmdline_test(drm_cmdline_test_rotate_truncated)
 cmdline_test(drm_cmdline_test_hmirror)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/selftests/test-drm_cmdline_parser.c
@@ -856,6 +856,17 @@
 	return 0;
 }
 
+static int drm_cmdline_test_rotate_multiple(void *ignored)
+{
+	struct drm_cmdline_mode mode = { };
+
+	FAIL_ON(drm_mode_parse_command_line_for_connector("720x480,rotate=0,rotate=90",
+							  &no_connector,
+							  &mode));
+
+	return 0;
+}
+
 static int drm_cmdline_test_rotate_invalid_val(void *ignored)
 {
 	struct drm_cmdline_mode mode = { };
@@ -888,7 +899,7 @@
 	FAIL_ON(!mode.specified);
 	FAIL_ON(mode.xres != 720);
 	FAIL_ON(mode.yres != 480);
-	FAIL_ON(mode.rotation_reflection != DRM_MODE_REFLECT_X);
+	FAIL_ON(mode.rotation_reflection != (DRM_MODE_ROTATE_0 | DRM_MODE_REFLECT_X));
 
 	FAIL_ON(mode.refresh_specified);
 
@@ -913,7 +924,7 @@
 	FAIL_ON(!mode.specified);
 	FAIL_ON(mode.xres != 720);
 	FAIL_ON(mode.yres != 480);
-	FAIL_ON(mode.rotation_reflection != DRM_MODE_REFLECT_Y);
+	FAIL_ON(mode.rotation_reflection != (DRM_MODE_ROTATE_0 | DRM_MODE_REFLECT_Y));
 
 	FAIL_ON(mode.refresh_specified);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/sti/sti_dvo.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/sti/sti_dvo.c
@@ -287,7 +287,7 @@
 
 	DRM_DEBUG_DRIVER("\n");
 
-	memcpy(&dvo->mode, mode, sizeof(struct drm_display_mode));
+	drm_mode_copy(&dvo->mode, mode);
 
 	/* According to the path used (main or aux), the dvo clocks should
 	 * have a different parent clock. */
@@ -345,8 +345,9 @@
 
 #define CLK_TOLERANCE_HZ 50
 
-static int sti_dvo_connector_mode_valid(struct drm_connector *connector,
-					struct drm_display_mode *mode)
+static enum drm_mode_status
+sti_dvo_connector_mode_valid(struct drm_connector *connector,
+			     struct drm_display_mode *mode)
 {
 	int target = mode->clock * 1000;
 	int target_min = target - CLK_TOLERANCE_HZ;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/sti/sti_hda.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/sti/sti_hda.c
@@ -522,7 +522,7 @@
 
 	DRM_DEBUG_DRIVER("\n");
 
-	memcpy(&hda->mode, mode, sizeof(struct drm_display_mode));
+	drm_mode_copy(&hda->mode, mode);
 
 	if (!hda_get_mode_idx(hda->mode, &mode_idx)) {
 		DRM_ERROR("Undefined mode\n");
@@ -600,8 +600,9 @@
 
 #define CLK_TOLERANCE_HZ 50
 
-static int sti_hda_connector_mode_valid(struct drm_connector *connector,
-					struct drm_display_mode *mode)
+static enum drm_mode_status
+sti_hda_connector_mode_valid(struct drm_connector *connector,
+			     struct drm_display_mode *mode)
 {
 	int target = mode->clock * 1000;
 	int target_min = target - CLK_TOLERANCE_HZ;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/sti/sti_hdmi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/sti/sti_hdmi.c
@@ -933,7 +933,7 @@
 	DRM_DEBUG_DRIVER("\n");
 
 	/* Copy the drm display mode in the connector local structure */
-	memcpy(&hdmi->mode, mode, sizeof(struct drm_display_mode));
+	drm_mode_copy(&hdmi->mode, mode);
 
 	/* Update clock framerate according to the selected mode */
 	ret = clk_set_rate(hdmi->clk_pix, mode->clock * 1000);
@@ -996,8 +996,9 @@
 
 #define CLK_TOLERANCE_HZ 50
 
-static int sti_hdmi_connector_mode_valid(struct drm_connector *connector,
-					struct drm_display_mode *mode)
+static enum drm_mode_status
+sti_hdmi_connector_mode_valid(struct drm_connector *connector,
+			      struct drm_display_mode *mode)
 {
 	int target = mode->clock * 1000;
 	int target_min = target - CLK_TOLERANCE_HZ;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/sti/sti_mixer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/sti/sti_mixer.c
@@ -137,7 +137,7 @@
 	}
 }
 
-static void mixer_dbg_mxn(struct seq_file *s, void *addr)
+static void mixer_dbg_mxn(struct seq_file *s, void __iomem *addr)
 {
 	int i;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/stm/drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/stm/drv.c
@@ -208,12 +208,14 @@
 
 	ret = drm_dev_register(ddev, 0);
 	if (ret)
-		goto err_put;
+		goto err_unload;
 
 	drm_fbdev_generic_setup(ddev, 16);
 
 	return 0;
 
+err_unload:
+	drv_unload(ddev);
 err_put:
 	drm_dev_put(ddev);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/stm/ltdc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/stm/ltdc.c
@@ -424,9 +424,12 @@
 				    struct drm_crtc_state *old_state)
 {
 	struct ltdc_device *ldev = crtc_to_ltdc(crtc);
+	struct drm_device *ddev = crtc->dev;
 
 	DRM_DEBUG_DRIVER("\n");
 
+	pm_runtime_get_sync(ddev->dev);
+
 	/* Sets the background color value */
 	reg_write(ldev->regs, LTDC_BCCR, BCCR_BCBLACK);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/sun4i/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/sun4i/Kconfig
@@ -46,6 +46,7 @@
 	default MACH_SUN8I
 	select CRC_CCITT
 	select DRM_MIPI_DSI
+	select RESET_CONTROLLER
 	select PHY_SUN6I_MIPI_DPHY
 	help
 	  Choose this option if you want have an Allwinner SoC with
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/sun4i/sun4i_backend.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/sun4i/sun4i_backend.c
@@ -589,8 +589,7 @@
 
 	/* We can't have an alpha plane at the lowest position */
 	if (!backend->quirks->supports_lowest_plane_alpha &&
-	    (plane_states[0]->fb->format->has_alpha ||
-	    (plane_states[0]->alpha != DRM_BLEND_ALPHA_OPAQUE)))
+	    (plane_states[0]->alpha != DRM_BLEND_ALPHA_OPAQUE))
 		return -EINVAL;
 
 	for (i = 1; i < num_planes; i++) {
@@ -986,7 +985,6 @@
 
 static const struct sun4i_backend_quirks sun7i_backend_quirks = {
 	.needs_output_muxing = true,
-	.supports_lowest_plane_alpha = true,
 };
 
 static const struct sun4i_backend_quirks sun8i_a33_backend_quirks = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -85,7 +85,6 @@
 	}
 
 	drm_mode_config_init(drm);
-	drm->mode_config.allow_fb_modifiers = true;
 
 	ret = component_bind_all(drm->dev, drm);
 	if (ret) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/sun4i/sun4i_frontend.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/sun4i/sun4i_frontend.c
@@ -407,6 +407,7 @@
 	struct drm_framebuffer *fb = state->fb;
 	const struct drm_format_info *format = fb->format;
 	uint64_t modifier = fb->modifier;
+	unsigned int ch1_phase_idx;
 	u32 out_fmt_val;
 	u32 in_fmt_val, in_mod_val, in_ps_val;
 	unsigned int i;
@@ -442,18 +443,19 @@
 	 * I have no idea what this does exactly, but it seems to be
 	 * related to the scaler FIR filter phase parameters.
 	 */
+	ch1_phase_idx = (format->num_planes > 1) ? 1 : 0;
 	regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_HORZPHASE_REG,
-		     frontend->data->ch_phase[0].horzphase);
+		     frontend->data->ch_phase[0]);
 	regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_HORZPHASE_REG,
-		     frontend->data->ch_phase[1].horzphase);
+		     frontend->data->ch_phase[ch1_phase_idx]);
 	regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTPHASE0_REG,
-		     frontend->data->ch_phase[0].vertphase[0]);
+		     frontend->data->ch_phase[0]);
 	regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTPHASE0_REG,
-		     frontend->data->ch_phase[1].vertphase[0]);
+		     frontend->data->ch_phase[ch1_phase_idx]);
 	regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTPHASE1_REG,
-		     frontend->data->ch_phase[0].vertphase[1]);
+		     frontend->data->ch_phase[0]);
 	regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTPHASE1_REG,
-		     frontend->data->ch_phase[1].vertphase[1]);
+		     frontend->data->ch_phase[ch1_phase_idx]);
 
 	/*
 	 * Checking the input format is sufficient since we currently only
@@ -687,30 +689,12 @@
 };
 
 static const struct sun4i_frontend_data sun4i_a10_frontend = {
-	.ch_phase		= {
-		{
-			.horzphase = 0,
-			.vertphase = { 0, 0 },
-		},
-		{
-			.horzphase = 0xfc000,
-			.vertphase = { 0xfc000, 0xfc000 },
-		},
-	},
+	.ch_phase		= { 0x000, 0xfc000 },
 	.has_coef_rdy		= true,
 };
 
 static const struct sun4i_frontend_data sun8i_a33_frontend = {
-	.ch_phase		= {
-		{
-			.horzphase = 0x400,
-			.vertphase = { 0x400, 0x400 },
-		},
-		{
-			.horzphase = 0x400,
-			.vertphase = { 0x400, 0x400 },
-		},
-	},
+	.ch_phase		= { 0x400, 0xfc400 },
 	.has_coef_access_ctrl	= true,
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/sun4i/sun4i_frontend.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/sun4i/sun4i_frontend.h
@@ -115,11 +115,7 @@
 struct sun4i_frontend_data {
 	bool	has_coef_access_ctrl;
 	bool	has_coef_rdy;
-
-	struct {
-		u32	horzphase;
-		u32	vertphase[2];
-	} ch_phase[2];
+	u32	ch_phase[2];
 };
 
 struct sun4i_frontend {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/sun4i/sun4i_hdmi.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/sun4i/sun4i_hdmi.h
@@ -148,7 +148,7 @@
 #define SUN4I_HDMI_DDC_CMD_IMPLICIT_WRITE	3
 
 #define SUN4I_HDMI_DDC_CLK_REG		0x528
-#define SUN4I_HDMI_DDC_CLK_M(m)			(((m) & 0x7) << 3)
+#define SUN4I_HDMI_DDC_CLK_M(m)			(((m) & 0xf) << 3)
 #define SUN4I_HDMI_DDC_CLK_N(n)			((n) & 0x7)
 
 #define SUN4I_HDMI_DDC_LINE_CTRL_REG	0x540
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/sun4i/sun4i_hdmi_ddc_clk.c
@@ -33,7 +33,7 @@
 	unsigned long best_rate = 0;
 	u8 best_m = 0, best_n = 0, _m, _n;
 
-	for (_m = 0; _m < 8; _m++) {
+	for (_m = 0; _m < 16; _m++) {
 		for (_n = 0; _n < 8; _n++) {
 			unsigned long tmp_rate;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
@@ -262,9 +262,8 @@
 	struct sun4i_hdmi *hdmi = drm_connector_to_sun4i_hdmi(connector);
 	unsigned long reg;
 
-	if (readl_poll_timeout(hdmi->base + SUN4I_HDMI_HPD_REG, reg,
-			       reg & SUN4I_HDMI_HPD_HIGH,
-			       0, 500000)) {
+	reg = readl(hdmi->base + SUN4I_HDMI_HPD_REG);
+	if (!(reg & SUN4I_HDMI_HPD_HIGH)) {
 		cec_phys_addr_invalidate(hdmi->cec_adap);
 		return connector_status_disconnected;
 	}
@@ -683,8 +682,6 @@
 	struct sun4i_hdmi *hdmi = dev_get_drvdata(dev);
 
 	cec_unregister_adapter(hdmi->cec_adap);
-	drm_connector_cleanup(&hdmi->connector);
-	drm_encoder_cleanup(&hdmi->encoder);
 	i2c_del_adapter(hdmi->i2c);
 	i2c_put_adapter(hdmi->ddc_i2c);
 	clk_disable_unprepare(hdmi->mod_clk);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -488,7 +488,7 @@
 
 	WARN_ON(!tcon->quirks->has_channel_0);
 
-	tcon->dclk_min_div = 1;
+	tcon->dclk_min_div = tcon->quirks->dclk_min_div;
 	tcon->dclk_max_div = 127;
 	sun4i_tcon0_mode_set_common(tcon, mode);
 
@@ -545,30 +545,13 @@
 	if (info->bus_flags & DRM_BUS_FLAG_DE_LOW)
 		val |= SUN4I_TCON0_IO_POL_DE_NEGATIVE;
 
-	/*
-	 * On A20 and similar SoCs, the only way to achieve Positive Edge
-	 * (Rising Edge), is setting dclk clock phase to 2/3(240°).
-	 * By default TCON works in Negative Edge(Falling Edge),
-	 * this is why phase is set to 0 in that case.
-	 * Unfortunately there's no way to logically invert dclk through
-	 * IO_POL register.
-	 * The only acceptable way to work, triple checked with scope,
-	 * is using clock phase set to 0° for Negative Edge and set to 240°
-	 * for Positive Edge.
-	 * On A33 and similar SoCs there would be a 90° phase option,
-	 * but it divides also dclk by 2.
-	 * Following code is a way to avoid quirks all around TCON
-	 * and DOTCLOCK drivers.
-	 */
-	if (info->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE)
-		clk_set_phase(tcon->dclk, 240);
-
 	if (info->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE)
-		clk_set_phase(tcon->dclk, 0);
+		val |= SUN4I_TCON0_IO_POL_DCLK_DRIVE_NEGEDGE;
 
 	regmap_update_bits(tcon->regs, SUN4I_TCON0_IO_POL_REG,
 			   SUN4I_TCON0_IO_POL_HSYNC_POSITIVE |
 			   SUN4I_TCON0_IO_POL_VSYNC_POSITIVE |
+			   SUN4I_TCON0_IO_POL_DCLK_DRIVE_NEGEDGE |
 			   SUN4I_TCON0_IO_POL_DE_NEGATIVE,
 			   val);
 
@@ -665,6 +648,30 @@
 		     SUN4I_TCON1_BASIC5_V_SYNC(vsync) |
 		     SUN4I_TCON1_BASIC5_H_SYNC(hsync));
 
+	/* Setup the polarity of multiple signals */
+	if (tcon->quirks->polarity_in_ch0) {
+		val = 0;
+
+		if (mode->flags & DRM_MODE_FLAG_PHSYNC)
+			val |= SUN4I_TCON0_IO_POL_HSYNC_POSITIVE;
+
+		if (mode->flags & DRM_MODE_FLAG_PVSYNC)
+			val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE;
+
+		regmap_write(tcon->regs, SUN4I_TCON0_IO_POL_REG, val);
+	} else {
+		/* according to vendor driver, this bit must be always set */
+		val = SUN4I_TCON1_IO_POL_UNKNOWN;
+
+		if (mode->flags & DRM_MODE_FLAG_PHSYNC)
+			val |= SUN4I_TCON1_IO_POL_HSYNC_POSITIVE;
+
+		if (mode->flags & DRM_MODE_FLAG_PVSYNC)
+			val |= SUN4I_TCON1_IO_POL_VSYNC_POSITIVE;
+
+		regmap_write(tcon->regs, SUN4I_TCON1_IO_POL_REG, val);
+	}
+
 	/* Map output pins to channel 1 */
 	regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
 			   SUN4I_TCON_GCTL_IOMAP_MASK,
@@ -746,21 +753,19 @@
 static int sun4i_tcon_init_clocks(struct device *dev,
 				  struct sun4i_tcon *tcon)
 {
-	tcon->clk = devm_clk_get(dev, "ahb");
+	tcon->clk = devm_clk_get_enabled(dev, "ahb");
 	if (IS_ERR(tcon->clk)) {
 		dev_err(dev, "Couldn't get the TCON bus clock\n");
 		return PTR_ERR(tcon->clk);
 	}
-	clk_prepare_enable(tcon->clk);
 
 	if (tcon->quirks->has_channel_0) {
-		tcon->sclk0 = devm_clk_get(dev, "tcon-ch0");
+		tcon->sclk0 = devm_clk_get_enabled(dev, "tcon-ch0");
 		if (IS_ERR(tcon->sclk0)) {
 			dev_err(dev, "Couldn't get the TCON channel 0 clock\n");
 			return PTR_ERR(tcon->sclk0);
 		}
 	}
-	clk_prepare_enable(tcon->sclk0);
 
 	if (tcon->quirks->has_channel_1) {
 		tcon->sclk1 = devm_clk_get(dev, "tcon-ch1");
@@ -773,12 +778,6 @@
 	return 0;
 }
 
-static void sun4i_tcon_free_clocks(struct sun4i_tcon *tcon)
-{
-	clk_disable_unprepare(tcon->sclk0);
-	clk_disable_unprepare(tcon->clk);
-}
-
 static int sun4i_tcon_init_irq(struct device *dev,
 			       struct sun4i_tcon *tcon)
 {
@@ -1195,14 +1194,14 @@
 	ret = sun4i_tcon_init_regmap(dev, tcon);
 	if (ret) {
 		dev_err(dev, "Couldn't init our TCON regmap\n");
-		goto err_free_clocks;
+		goto err_assert_reset;
 	}
 
 	if (tcon->quirks->has_channel_0) {
 		ret = sun4i_dclk_create(dev, tcon);
 		if (ret) {
 			dev_err(dev, "Couldn't create our TCON dot clock\n");
-			goto err_free_clocks;
+			goto err_assert_reset;
 		}
 	}
 
@@ -1265,8 +1264,6 @@
 err_free_dotclock:
 	if (tcon->quirks->has_channel_0)
 		sun4i_dclk_free(tcon);
-err_free_clocks:
-	sun4i_tcon_free_clocks(tcon);
 err_assert_reset:
 	reset_control_assert(tcon->lcd_rst);
 	return ret;
@@ -1280,7 +1277,6 @@
 	list_del(&tcon->list);
 	if (tcon->quirks->has_channel_0)
 		sun4i_dclk_free(tcon);
-	sun4i_tcon_free_clocks(tcon);
 }
 
 static const struct component_ops sun4i_tcon_ops = {
@@ -1409,14 +1405,18 @@
 	if (IS_ENABLED(CONFIG_DRM_SUN8I_TCON_TOP) &&
 	    encoder->encoder_type == DRM_MODE_ENCODER_TMDS) {
 		ret = sun8i_tcon_top_set_hdmi_src(&pdev->dev, id);
-		if (ret)
+		if (ret) {
+			put_device(&pdev->dev);
 			return ret;
+		}
 	}
 
 	if (IS_ENABLED(CONFIG_DRM_SUN8I_TCON_TOP)) {
 		ret = sun8i_tcon_top_de_config(&pdev->dev, tcon->id, id);
-		if (ret)
+		if (ret) {
+			put_device(&pdev->dev);
 			return ret;
+		}
 	}
 
 	return 0;
@@ -1425,12 +1425,14 @@
 static const struct sun4i_tcon_quirks sun4i_a10_quirks = {
 	.has_channel_0		= true,
 	.has_channel_1		= true,
+	.dclk_min_div		= 4,
 	.set_mux		= sun4i_a10_tcon_set_mux,
 };
 
 static const struct sun4i_tcon_quirks sun5i_a13_quirks = {
 	.has_channel_0		= true,
 	.has_channel_1		= true,
+	.dclk_min_div		= 4,
 	.set_mux		= sun5i_a13_tcon_set_mux,
 };
 
@@ -1439,6 +1441,7 @@
 	.has_channel_1		= true,
 	.has_lvds_alt		= true,
 	.needs_de_be_mux	= true,
+	.dclk_min_div		= 1,
 	.set_mux		= sun6i_tcon_set_mux,
 };
 
@@ -1446,11 +1449,13 @@
 	.has_channel_0		= true,
 	.has_channel_1		= true,
 	.needs_de_be_mux	= true,
+	.dclk_min_div		= 1,
 };
 
 static const struct sun4i_tcon_quirks sun7i_a20_quirks = {
 	.has_channel_0		= true,
 	.has_channel_1		= true,
+	.dclk_min_div		= 4,
 	/* Same display pipeline structure as A10 */
 	.set_mux		= sun4i_a10_tcon_set_mux,
 };
@@ -1458,11 +1463,13 @@
 static const struct sun4i_tcon_quirks sun8i_a33_quirks = {
 	.has_channel_0		= true,
 	.has_lvds_alt		= true,
+	.dclk_min_div		= 1,
 };
 
 static const struct sun4i_tcon_quirks sun8i_a83t_lcd_quirks = {
 	.supports_lvds		= true,
 	.has_channel_0		= true,
+	.dclk_min_div		= 1,
 };
 
 static const struct sun4i_tcon_quirks sun8i_a83t_tv_quirks = {
@@ -1471,16 +1478,19 @@
 
 static const struct sun4i_tcon_quirks sun8i_r40_tv_quirks = {
 	.has_channel_1		= true,
+	.polarity_in_ch0	= true,
 	.set_mux		= sun8i_r40_tcon_tv_set_mux,
 };
 
 static const struct sun4i_tcon_quirks sun8i_v3s_quirks = {
 	.has_channel_0		= true,
+	.dclk_min_div		= 1,
 };
 
 static const struct sun4i_tcon_quirks sun9i_a80_tcon_lcd_quirks = {
-	.has_channel_0	= true,
-	.needs_edp_reset = true,
+	.has_channel_0		= true,
+	.needs_edp_reset	= true,
+	.dclk_min_div		= 1,
 };
 
 static const struct sun4i_tcon_quirks sun9i_a80_tcon_tv_quirks = {
@@ -1495,6 +1505,8 @@
 	{ .compatible = "allwinner,sun6i-a31-tcon", .data = &sun6i_a31_quirks },
 	{ .compatible = "allwinner,sun6i-a31s-tcon", .data = &sun6i_a31s_quirks },
 	{ .compatible = "allwinner,sun7i-a20-tcon", .data = &sun7i_a20_quirks },
+	{ .compatible = "allwinner,sun7i-a20-tcon0", .data = &sun7i_a20_quirks },
+	{ .compatible = "allwinner,sun7i-a20-tcon1", .data = &sun7i_a20_quirks },
 	{ .compatible = "allwinner,sun8i-a23-tcon", .data = &sun8i_a33_quirks },
 	{ .compatible = "allwinner,sun8i-a33-tcon", .data = &sun8i_a33_quirks },
 	{ .compatible = "allwinner,sun8i-a83t-tcon-lcd", .data = &sun8i_a83t_lcd_quirks },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -113,6 +113,7 @@
 #define SUN4I_TCON0_IO_POL_REG			0x88
 #define SUN4I_TCON0_IO_POL_DCLK_PHASE(phase)		((phase & 3) << 28)
 #define SUN4I_TCON0_IO_POL_DE_NEGATIVE			BIT(27)
+#define SUN4I_TCON0_IO_POL_DCLK_DRIVE_NEGEDGE		BIT(26)
 #define SUN4I_TCON0_IO_POL_HSYNC_POSITIVE		BIT(25)
 #define SUN4I_TCON0_IO_POL_VSYNC_POSITIVE		BIT(24)
 
@@ -153,6 +154,11 @@
 #define SUN4I_TCON1_BASIC5_V_SYNC(height)		(((height) - 1) & 0x3ff)
 
 #define SUN4I_TCON1_IO_POL_REG			0xf0
+/* there is no documentation about this bit */
+#define SUN4I_TCON1_IO_POL_UNKNOWN			BIT(26)
+#define SUN4I_TCON1_IO_POL_HSYNC_POSITIVE		BIT(25)
+#define SUN4I_TCON1_IO_POL_VSYNC_POSITIVE		BIT(24)
+
 #define SUN4I_TCON1_IO_TRI_REG			0xf4
 
 #define SUN4I_TCON_ECC_FIFO_REG			0xf8
@@ -224,6 +230,8 @@
 	bool	needs_de_be_mux; /* sun6i needs mux to select backend */
 	bool    needs_edp_reset; /* a80 edp reset needed for tcon0 access */
 	bool	supports_lvds;   /* Does the TCON support an LVDS output? */
+	bool	polarity_in_ch0; /* some tcon1 channels have polarity bits in tcon0 pol register */
+	u8	dclk_min_div;	/* minimum divider for TCON0 DCLK */
 
 	/* callback to handle tcon muxing options */
 	int	(*set_mux)(struct sun4i_tcon *, const struct drm_encoder *);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -365,8 +365,7 @@
 static u16 sun6i_dsi_get_video_start_delay(struct sun6i_dsi *dsi,
 					   struct drm_display_mode *mode)
 {
-	u16 start = clamp(mode->vtotal - mode->vdisplay - 10, 8, 100);
-	u16 delay = mode->vtotal - (mode->vsync_end - mode->vdisplay) + start;
+	u16 delay = mode->vtotal - (mode->vsync_end - mode->vdisplay) + 1;
 
 	if (delay > mode->vtotal)
 		delay = delay % mode->vtotal;
@@ -437,9 +436,9 @@
 			     SUN6I_DSI_BURST_LINE_SYNC_POINT(SUN6I_DSI_SYNC_POINT));
 
 		val = SUN6I_DSI_TCON_DRQ_ENABLE_MODE;
-	} else if ((mode->hsync_end - mode->hdisplay) > 20) {
+	} else if ((mode->hsync_start - mode->hdisplay) > 20) {
 		/* Maaaaaagic */
-		u16 drq = (mode->hsync_end - mode->hdisplay) - 20;
+		u16 drq = (mode->hsync_start - mode->hdisplay) - 20;
 
 		drq *= mipi_dsi_pixel_format_to_bpp(device->format);
 		drq /= 32;
@@ -718,7 +717,7 @@
 	struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
 	struct sun6i_dsi *dsi = encoder_to_sun6i_dsi(encoder);
 	struct mipi_dsi_device *device = dsi->device;
-	union phy_configure_opts opts = { 0 };
+	union phy_configure_opts opts = { };
 	struct phy_configure_opts_mipi_dphy *cfg = &opts.mipi_dphy;
 	u16 delay;
 
@@ -867,7 +866,7 @@
 	regmap_write(dsi->regs, SUN6I_DSI_CMD_TX_REG(0),
 		     sun6i_dsi_dcs_build_pkt_hdr(dsi, msg));
 
-	bounce = kzalloc(msg->tx_len + sizeof(crc), GFP_KERNEL);
+	bounce = kzalloc(ALIGN(msg->tx_len + sizeof(crc), 4), GFP_KERNEL);
 	if (!bounce)
 		return -ENOMEM;
 
@@ -878,7 +877,7 @@
 	memcpy((u8 *)bounce + msg->tx_len, &crc, sizeof(crc));
 	len += sizeof(crc);
 
-	regmap_bulk_write(dsi->regs, SUN6I_DSI_CMD_TX_REG(1), bounce, len);
+	regmap_bulk_write(dsi->regs, SUN6I_DSI_CMD_TX_REG(1), bounce, DIV_ROUND_UP(len, 4));
 	regmap_write(dsi->regs, SUN6I_DSI_CMD_CTL_REG, len + 4 - 1);
 	kfree(bounce);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/sun4i/sun8i_csc.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/sun4i/sun8i_csc.h
@@ -12,7 +12,7 @@
 
 /* VI channel CSC units offsets */
 #define CCSC00_OFFSET 0xAA050
-#define CCSC01_OFFSET 0xFA000
+#define CCSC01_OFFSET 0xFA050
 #define CCSC10_OFFSET 0xA0000
 #define CCSC11_OFFSET 0xF0000
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
@@ -49,11 +49,9 @@
 {
 	/*
 	 * Controller support maximum of 594 MHz, which correlates to
-	 * 4K@60Hz 4:4:4 or RGB. However, for frequencies greater than
-	 * 340 MHz scrambling has to be enabled. Because scrambling is
-	 * not yet implemented, just limit to 340 MHz for now.
+	 * 4K@60Hz 4:4:4 or RGB.
 	 */
-	if (mode->clock > 340000)
+	if (mode->clock > 594000)
 		return MODE_CLOCK_HIGH;
 
 	return MODE_OK;
@@ -209,6 +207,7 @@
 	phy_node = of_parse_phandle(dev->of_node, "phys", 0);
 	if (!phy_node) {
 		dev_err(dev, "Can't found PHY phandle\n");
+		ret = -EINVAL;
 		goto err_disable_clk_tmds;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -104,29 +104,21 @@
 
 static const struct dw_hdmi_curr_ctrl sun50i_h6_cur_ctr[] = {
 	/* pixelclk    bpp8    bpp10   bpp12 */
-	{ 25175000,  { 0x0000, 0x0000, 0x0000 }, },
 	{ 27000000,  { 0x0012, 0x0000, 0x0000 }, },
-	{ 59400000,  { 0x0008, 0x0008, 0x0008 }, },
-	{ 72000000,  { 0x0008, 0x0008, 0x001b }, },
-	{ 74250000,  { 0x0013, 0x0013, 0x0013 }, },
-	{ 90000000,  { 0x0008, 0x001a, 0x001b }, },
-	{ 118800000, { 0x001b, 0x001a, 0x001b }, },
-	{ 144000000, { 0x001b, 0x001a, 0x0034 }, },
-	{ 180000000, { 0x001b, 0x0033, 0x0034 }, },
-	{ 216000000, { 0x0036, 0x0033, 0x0034 }, },
-	{ 237600000, { 0x0036, 0x0033, 0x001b }, },
-	{ 288000000, { 0x0036, 0x001b, 0x001b }, },
-	{ 297000000, { 0x0019, 0x001b, 0x0019 }, },
-	{ 330000000, { 0x0036, 0x001b, 0x001b }, },
-	{ 594000000, { 0x003f, 0x001b, 0x001b }, },
+	{ 74250000,  { 0x0013, 0x001a, 0x001b }, },
+	{ 148500000, { 0x0019, 0x0033, 0x0034 }, },
+	{ 297000000, { 0x0019, 0x001b, 0x001b }, },
+	{ 594000000, { 0x0010, 0x001b, 0x001b }, },
 	{ ~0UL,      { 0x0000, 0x0000, 0x0000 }, }
 };
 
 static const struct dw_hdmi_phy_config sun50i_h6_phy_config[] = {
 	/*pixelclk   symbol   term   vlev*/
-	{ 74250000,  0x8009, 0x0004, 0x0232},
-	{ 148500000, 0x8029, 0x0004, 0x0273},
-	{ 594000000, 0x8039, 0x0004, 0x014a},
+	{ 27000000,  0x8009, 0x0007, 0x02b0 },
+	{ 74250000,  0x8009, 0x0006, 0x022d },
+	{ 148500000, 0x8029, 0x0006, 0x0270 },
+	{ 297000000, 0x8039, 0x0005, 0x01ab },
+	{ 594000000, 0x8029, 0x0000, 0x008a },
 	{ ~0UL,	     0x0000, 0x0000, 0x0000}
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -107,48 +107,128 @@
 		.csc = SUN8I_CSC_MODE_OFF,
 	},
 	{
+		/* for DE2 VI layer which ignores alpha */
+		.drm_fmt = DRM_FORMAT_XRGB4444,
+		.de2_fmt = SUN8I_MIXER_FBFMT_ARGB4444,
+		.rgb = true,
+		.csc = SUN8I_CSC_MODE_OFF,
+	},
+	{
 		.drm_fmt = DRM_FORMAT_ABGR4444,
 		.de2_fmt = SUN8I_MIXER_FBFMT_ABGR4444,
 		.rgb = true,
 		.csc = SUN8I_CSC_MODE_OFF,
 	},
 	{
+		/* for DE2 VI layer which ignores alpha */
+		.drm_fmt = DRM_FORMAT_XBGR4444,
+		.de2_fmt = SUN8I_MIXER_FBFMT_ABGR4444,
+		.rgb = true,
+		.csc = SUN8I_CSC_MODE_OFF,
+	},
+	{
 		.drm_fmt = DRM_FORMAT_RGBA4444,
 		.de2_fmt = SUN8I_MIXER_FBFMT_RGBA4444,
 		.rgb = true,
 		.csc = SUN8I_CSC_MODE_OFF,
 	},
 	{
+		/* for DE2 VI layer which ignores alpha */
+		.drm_fmt = DRM_FORMAT_RGBX4444,
+		.de2_fmt = SUN8I_MIXER_FBFMT_RGBA4444,
+		.rgb = true,
+		.csc = SUN8I_CSC_MODE_OFF,
+	},
+	{
 		.drm_fmt = DRM_FORMAT_BGRA4444,
 		.de2_fmt = SUN8I_MIXER_FBFMT_BGRA4444,
 		.rgb = true,
 		.csc = SUN8I_CSC_MODE_OFF,
 	},
 	{
+		/* for DE2 VI layer which ignores alpha */
+		.drm_fmt = DRM_FORMAT_BGRX4444,
+		.de2_fmt = SUN8I_MIXER_FBFMT_BGRA4444,
+		.rgb = true,
+		.csc = SUN8I_CSC_MODE_OFF,
+	},
+	{
 		.drm_fmt = DRM_FORMAT_ARGB1555,
 		.de2_fmt = SUN8I_MIXER_FBFMT_ARGB1555,
 		.rgb = true,
 		.csc = SUN8I_CSC_MODE_OFF,
 	},
 	{
+		/* for DE2 VI layer which ignores alpha */
+		.drm_fmt = DRM_FORMAT_XRGB1555,
+		.de2_fmt = SUN8I_MIXER_FBFMT_ARGB1555,
+		.rgb = true,
+		.csc = SUN8I_CSC_MODE_OFF,
+	},
+	{
 		.drm_fmt = DRM_FORMAT_ABGR1555,
 		.de2_fmt = SUN8I_MIXER_FBFMT_ABGR1555,
 		.rgb = true,
 		.csc = SUN8I_CSC_MODE_OFF,
 	},
 	{
+		/* for DE2 VI layer which ignores alpha */
+		.drm_fmt = DRM_FORMAT_XBGR1555,
+		.de2_fmt = SUN8I_MIXER_FBFMT_ABGR1555,
+		.rgb = true,
+		.csc = SUN8I_CSC_MODE_OFF,
+	},
+	{
 		.drm_fmt = DRM_FORMAT_RGBA5551,
 		.de2_fmt = SUN8I_MIXER_FBFMT_RGBA5551,
 		.rgb = true,
 		.csc = SUN8I_CSC_MODE_OFF,
 	},
 	{
+		/* for DE2 VI layer which ignores alpha */
+		.drm_fmt = DRM_FORMAT_RGBX5551,
+		.de2_fmt = SUN8I_MIXER_FBFMT_RGBA5551,
+		.rgb = true,
+		.csc = SUN8I_CSC_MODE_OFF,
+	},
+	{
 		.drm_fmt = DRM_FORMAT_BGRA5551,
 		.de2_fmt = SUN8I_MIXER_FBFMT_BGRA5551,
 		.rgb = true,
 		.csc = SUN8I_CSC_MODE_OFF,
 	},
 	{
+		/* for DE2 VI layer which ignores alpha */
+		.drm_fmt = DRM_FORMAT_BGRX5551,
+		.de2_fmt = SUN8I_MIXER_FBFMT_BGRA5551,
+		.rgb = true,
+		.csc = SUN8I_CSC_MODE_OFF,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_ARGB2101010,
+		.de2_fmt = SUN8I_MIXER_FBFMT_ARGB2101010,
+		.rgb = true,
+		.csc = SUN8I_CSC_MODE_OFF,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_ABGR2101010,
+		.de2_fmt = SUN8I_MIXER_FBFMT_ABGR2101010,
+		.rgb = true,
+		.csc = SUN8I_CSC_MODE_OFF,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_RGBA1010102,
+		.de2_fmt = SUN8I_MIXER_FBFMT_RGBA1010102,
+		.rgb = true,
+		.csc = SUN8I_CSC_MODE_OFF,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_BGRA1010102,
+		.de2_fmt = SUN8I_MIXER_FBFMT_BGRA1010102,
+		.rgb = true,
+		.csc = SUN8I_CSC_MODE_OFF,
+	},
+	{
 		.drm_fmt = DRM_FORMAT_UYVY,
 		.de2_fmt = SUN8I_MIXER_FBFMT_UYVY,
 		.rgb = false,
@@ -197,12 +277,6 @@
 		.csc = SUN8I_CSC_MODE_YUV2RGB,
 	},
 	{
-		.drm_fmt = DRM_FORMAT_YUV444,
-		.de2_fmt = SUN8I_MIXER_FBFMT_RGB888,
-		.rgb = true,
-		.csc = SUN8I_CSC_MODE_YUV2RGB,
-	},
-	{
 		.drm_fmt = DRM_FORMAT_YUV422,
 		.de2_fmt = SUN8I_MIXER_FBFMT_YUV422,
 		.rgb = false,
@@ -221,12 +295,6 @@
 		.csc = SUN8I_CSC_MODE_YUV2RGB,
 	},
 	{
-		.drm_fmt = DRM_FORMAT_YVU444,
-		.de2_fmt = SUN8I_MIXER_FBFMT_RGB888,
-		.rgb = true,
-		.csc = SUN8I_CSC_MODE_YVU2RGB,
-	},
-	{
 		.drm_fmt = DRM_FORMAT_YVU422,
 		.de2_fmt = SUN8I_MIXER_FBFMT_YUV422,
 		.rgb = false,
@@ -244,6 +312,18 @@
 		.rgb = false,
 		.csc = SUN8I_CSC_MODE_YVU2RGB,
 	},
+	{
+		.drm_fmt = DRM_FORMAT_P010,
+		.de2_fmt = SUN8I_MIXER_FBFMT_P010_YUV,
+		.rgb = false,
+		.csc = SUN8I_CSC_MODE_YUV2RGB,
+	},
+	{
+		.drm_fmt = DRM_FORMAT_P210,
+		.de2_fmt = SUN8I_MIXER_FBFMT_P210_YUV,
+		.rgb = false,
+		.csc = SUN8I_CSC_MODE_YUV2RGB,
+	},
 };
 
 const struct de2_fmt_info *sun8i_mixer_format_info(u32 format)
@@ -316,7 +396,7 @@
 	.reg_bits	= 32,
 	.val_bits	= 32,
 	.reg_stride	= 4,
-	.max_register	= 0xbfffc, /* guessed */
+	.max_register	= 0xffffc, /* guessed */
 };
 
 static int sun8i_mixer_of_get_id(struct device_node *node)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/sun4i/sun8i_mixer.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/sun4i/sun8i_mixer.h
@@ -93,6 +93,10 @@
 #define SUN8I_MIXER_FBFMT_ABGR1555	17
 #define SUN8I_MIXER_FBFMT_RGBA5551	18
 #define SUN8I_MIXER_FBFMT_BGRA5551	19
+#define SUN8I_MIXER_FBFMT_ARGB2101010	20
+#define SUN8I_MIXER_FBFMT_ABGR2101010	21
+#define SUN8I_MIXER_FBFMT_RGBA1010102	22
+#define SUN8I_MIXER_FBFMT_BGRA1010102	23
 
 #define SUN8I_MIXER_FBFMT_YUYV		0
 #define SUN8I_MIXER_FBFMT_UYVY		1
@@ -109,6 +113,13 @@
 /* format 12 is semi-planar YUV411 UVUV */
 /* format 13 is semi-planar YUV411 VUVU */
 #define SUN8I_MIXER_FBFMT_YUV411	14
+/* format 15 doesn't exist */
+#define SUN8I_MIXER_FBFMT_P010_YUV	16
+/* format 17 is P010 YVU */
+#define SUN8I_MIXER_FBFMT_P210_YUV	18
+/* format 19 is P210 YVU */
+/* format 20 is packed YVU444 10-bit */
+/* format 21 is packed YUV444 10-bit */
 
 /*
  * Sub-engines listed bellow are unused for now. The EN registers are here only
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/sun4i/sun8i_vi_layer.c
@@ -398,24 +398,66 @@
 };
 
 /*
- * While all RGB formats are supported, VI planes don't support
- * alpha blending, so there is no point having formats with alpha
- * channel if their opaque analog exist.
+ * While DE2 VI layer supports same RGB formats as UI layer, alpha
+ * channel is ignored. This structure lists all unique variants
+ * where alpha channel is replaced with "don't care" (X) channel.
  */
 static const u32 sun8i_vi_layer_formats[] = {
+	DRM_FORMAT_BGR565,
+	DRM_FORMAT_BGR888,
+	DRM_FORMAT_BGRX4444,
+	DRM_FORMAT_BGRX5551,
+	DRM_FORMAT_BGRX8888,
+	DRM_FORMAT_RGB565,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_RGBX4444,
+	DRM_FORMAT_RGBX5551,
+	DRM_FORMAT_RGBX8888,
+	DRM_FORMAT_XBGR1555,
+	DRM_FORMAT_XBGR4444,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_XRGB1555,
+	DRM_FORMAT_XRGB4444,
+	DRM_FORMAT_XRGB8888,
+
+	DRM_FORMAT_NV16,
+	DRM_FORMAT_NV12,
+	DRM_FORMAT_NV21,
+	DRM_FORMAT_NV61,
+	DRM_FORMAT_UYVY,
+	DRM_FORMAT_VYUY,
+	DRM_FORMAT_YUYV,
+	DRM_FORMAT_YVYU,
+	DRM_FORMAT_YUV411,
+	DRM_FORMAT_YUV420,
+	DRM_FORMAT_YUV422,
+	DRM_FORMAT_YVU411,
+	DRM_FORMAT_YVU420,
+	DRM_FORMAT_YVU422,
+};
+
+static const u32 sun8i_vi_layer_de3_formats[] = {
 	DRM_FORMAT_ABGR1555,
+	DRM_FORMAT_ABGR2101010,
 	DRM_FORMAT_ABGR4444,
+	DRM_FORMAT_ABGR8888,
 	DRM_FORMAT_ARGB1555,
+	DRM_FORMAT_ARGB2101010,
 	DRM_FORMAT_ARGB4444,
+	DRM_FORMAT_ARGB8888,
 	DRM_FORMAT_BGR565,
 	DRM_FORMAT_BGR888,
+	DRM_FORMAT_BGRA1010102,
 	DRM_FORMAT_BGRA5551,
 	DRM_FORMAT_BGRA4444,
+	DRM_FORMAT_BGRA8888,
 	DRM_FORMAT_BGRX8888,
 	DRM_FORMAT_RGB565,
 	DRM_FORMAT_RGB888,
+	DRM_FORMAT_RGBA1010102,
 	DRM_FORMAT_RGBA4444,
 	DRM_FORMAT_RGBA5551,
+	DRM_FORMAT_RGBA8888,
 	DRM_FORMAT_RGBX8888,
 	DRM_FORMAT_XBGR8888,
 	DRM_FORMAT_XRGB8888,
@@ -424,6 +466,8 @@
 	DRM_FORMAT_NV12,
 	DRM_FORMAT_NV21,
 	DRM_FORMAT_NV61,
+	DRM_FORMAT_P010,
+	DRM_FORMAT_P210,
 	DRM_FORMAT_UYVY,
 	DRM_FORMAT_VYUY,
 	DRM_FORMAT_YUYV,
@@ -431,11 +475,9 @@
 	DRM_FORMAT_YUV411,
 	DRM_FORMAT_YUV420,
 	DRM_FORMAT_YUV422,
-	DRM_FORMAT_YUV444,
 	DRM_FORMAT_YVU411,
 	DRM_FORMAT_YVU420,
 	DRM_FORMAT_YVU422,
-	DRM_FORMAT_YVU444,
 };
 
 struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm,
@@ -443,19 +485,27 @@
 					       int index)
 {
 	u32 supported_encodings, supported_ranges;
+	unsigned int plane_cnt, format_count;
 	struct sun8i_vi_layer *layer;
-	unsigned int plane_cnt;
+	const u32 *formats;
 	int ret;
 
 	layer = devm_kzalloc(drm->dev, sizeof(*layer), GFP_KERNEL);
 	if (!layer)
 		return ERR_PTR(-ENOMEM);
 
+	if (mixer->cfg->is_de3) {
+		formats = sun8i_vi_layer_de3_formats;
+		format_count = ARRAY_SIZE(sun8i_vi_layer_de3_formats);
+	} else {
+		formats = sun8i_vi_layer_formats;
+		format_count = ARRAY_SIZE(sun8i_vi_layer_formats);
+	}
+
 	/* possible crtcs are set later */
 	ret = drm_universal_plane_init(drm, &layer->plane, 0,
 				       &sun8i_vi_layer_funcs,
-				       sun8i_vi_layer_formats,
-				       ARRAY_SIZE(sun8i_vi_layer_formats),
+				       formats, format_count,
 				       NULL, DRM_PLANE_TYPE_OVERLAY, NULL);
 	if (ret) {
 		dev_err(drm->dev, "Couldn't initialize layer\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/tegra/dc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/tegra/dc.c
@@ -919,6 +919,11 @@
 	.atomic_disable = tegra_cursor_atomic_disable,
 };
 
+static const uint64_t linear_modifiers[] = {
+	DRM_FORMAT_MOD_LINEAR,
+	DRM_FORMAT_MOD_INVALID
+};
+
 static struct drm_plane *tegra_dc_cursor_plane_create(struct drm_device *drm,
 						      struct tegra_dc *dc)
 {
@@ -947,7 +952,7 @@
 
 	err = drm_universal_plane_init(drm, &plane->base, possible_crtcs,
 				       &tegra_plane_funcs, formats,
-				       num_formats, NULL,
+				       num_formats, linear_modifiers,
 				       DRM_PLANE_TYPE_CURSOR, NULL);
 	if (err < 0) {
 		kfree(plane);
@@ -1065,7 +1070,8 @@
 
 	err = drm_universal_plane_init(drm, &plane->base, possible_crtcs,
 				       &tegra_plane_funcs, formats,
-				       num_formats, NULL, type, NULL);
+				       num_formats, linear_modifiers,
+				       type, NULL);
 	if (err < 0) {
 		kfree(plane);
 		return ERR_PTR(err);
@@ -1667,6 +1673,11 @@
 			dev_err(dc->dev,
 				"failed to set clock rate to %lu Hz\n",
 				state->pclk);
+
+		err = clk_set_rate(dc->clk, state->pclk);
+		if (err < 0)
+			dev_err(dc->dev, "failed to set clock %pC to %lu Hz: %d\n",
+				dc->clk, state->pclk, err);
 	}
 
 	DRM_DEBUG_KMS("rate: %lu, div: %u\n", clk_get_rate(dc->clk),
@@ -1677,11 +1688,6 @@
 		value = SHIFT_CLK_DIVIDER(state->div) | PIXEL_CLK_DIVIDER_PCD1;
 		tegra_dc_writel(dc, value, DC_DISP_DISP_CLOCK_CONTROL);
 	}
-
-	err = clk_set_rate(dc->clk, state->pclk);
-	if (err < 0)
-		dev_err(dc->dev, "failed to set clock %pC to %lu Hz: %d\n",
-			dc->clk, state->pclk, err);
 }
 
 static void tegra_dc_stop(struct tegra_dc *dc)
@@ -2452,8 +2458,10 @@
 	usleep_range(2000, 4000);
 
 	err = reset_control_assert(dc->rst);
-	if (err < 0)
+	if (err < 0) {
+		clk_disable_unprepare(dc->clk);
 		return err;
+	}
 
 	usleep_range(2000, 4000);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/tegra/dpaux.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/tegra/dpaux.c
@@ -447,10 +447,8 @@
 		return PTR_ERR(dpaux->regs);
 
 	dpaux->irq = platform_get_irq(pdev, 0);
-	if (dpaux->irq < 0) {
-		dev_err(&pdev->dev, "failed to get IRQ\n");
-		return -ENXIO;
-	}
+	if (dpaux->irq < 0)
+		return dpaux->irq;
 
 	if (!pdev->dev.pm_domain) {
 		dpaux->rst = devm_reset_control_get(&pdev->dev, "dpaux");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/tegra/drm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/tegra/drm.c
@@ -122,8 +122,6 @@
 	drm->mode_config.max_width = 4096;
 	drm->mode_config.max_height = 4096;
 
-	drm->mode_config.allow_fb_modifiers = true;
-
 	drm->mode_config.normalize_zpos = true;
 
 	drm->mode_config.funcs = &tegra_drm_mode_config_funcs;
@@ -201,19 +199,19 @@
 	if (tegra->hub)
 		tegra_display_hub_cleanup(tegra->hub);
 device:
-	host1x_device_exit(device);
-fbdev:
-	drm_kms_helper_poll_fini(drm);
-	tegra_drm_fb_free(drm);
-config:
-	drm_mode_config_cleanup(drm);
-
 	if (tegra->domain) {
 		mutex_destroy(&tegra->mm_lock);
 		drm_mm_takedown(&tegra->mm);
 		put_iova_domain(&tegra->carveout.domain);
 		iova_cache_put();
 	}
+
+	host1x_device_exit(device);
+fbdev:
+	drm_kms_helper_poll_fini(drm);
+	tegra_drm_fb_free(drm);
+config:
+	drm_mode_config_cleanup(drm);
 domain:
 	if (tegra->domain)
 		iommu_domain_free(tegra->domain);
@@ -256,7 +254,7 @@
 	if (!fpriv)
 		return -ENOMEM;
 
-	idr_init(&fpriv->contexts);
+	idr_init_base(&fpriv->contexts, 1);
 	mutex_init(&fpriv->lock);
 	filp->driver_priv = fpriv;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/tegra/dsi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/tegra/dsi.c
@@ -1451,12 +1451,16 @@
 	np = of_parse_phandle(dsi->dev->of_node, "nvidia,ganged-mode", 0);
 	if (np) {
 		struct platform_device *gangster = of_find_device_by_node(np);
+		of_node_put(np);
+		if (!gangster)
+			return -EPROBE_DEFER;
 
 		dsi->slave = platform_get_drvdata(gangster);
-		of_node_put(np);
 
-		if (!dsi->slave)
+		if (!dsi->slave) {
+			put_device(&gangster->dev);
 			return -EPROBE_DEFER;
+		}
 
 		dsi->slave->master = dsi;
 	}
@@ -1499,48 +1503,58 @@
 
 	if (!pdev->dev.pm_domain) {
 		dsi->rst = devm_reset_control_get(&pdev->dev, "dsi");
-		if (IS_ERR(dsi->rst))
-			return PTR_ERR(dsi->rst);
+		if (IS_ERR(dsi->rst)) {
+			err = PTR_ERR(dsi->rst);
+			goto remove;
+		}
 	}
 
 	dsi->clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(dsi->clk)) {
-		dev_err(&pdev->dev, "cannot get DSI clock\n");
-		return PTR_ERR(dsi->clk);
+		err = dev_err_probe(&pdev->dev, PTR_ERR(dsi->clk),
+				    "cannot get DSI clock\n");
+		goto remove;
 	}
 
 	dsi->clk_lp = devm_clk_get(&pdev->dev, "lp");
 	if (IS_ERR(dsi->clk_lp)) {
-		dev_err(&pdev->dev, "cannot get low-power clock\n");
-		return PTR_ERR(dsi->clk_lp);
+		err = dev_err_probe(&pdev->dev, PTR_ERR(dsi->clk_lp),
+				    "cannot get low-power clock\n");
+		goto remove;
 	}
 
 	dsi->clk_parent = devm_clk_get(&pdev->dev, "parent");
 	if (IS_ERR(dsi->clk_parent)) {
-		dev_err(&pdev->dev, "cannot get parent clock\n");
-		return PTR_ERR(dsi->clk_parent);
+		err = dev_err_probe(&pdev->dev, PTR_ERR(dsi->clk_parent),
+				    "cannot get parent clock\n");
+		goto remove;
 	}
 
 	dsi->vdd = devm_regulator_get(&pdev->dev, "avdd-dsi-csi");
 	if (IS_ERR(dsi->vdd)) {
-		dev_err(&pdev->dev, "cannot get VDD supply\n");
-		return PTR_ERR(dsi->vdd);
+		err = dev_err_probe(&pdev->dev, PTR_ERR(dsi->vdd),
+				    "cannot get VDD supply\n");
+		goto remove;
 	}
 
 	err = tegra_dsi_setup_clocks(dsi);
 	if (err < 0) {
 		dev_err(&pdev->dev, "cannot setup clocks\n");
-		return err;
+		goto remove;
 	}
 
 	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	dsi->regs = devm_ioremap_resource(&pdev->dev, regs);
-	if (IS_ERR(dsi->regs))
-		return PTR_ERR(dsi->regs);
+	if (IS_ERR(dsi->regs)) {
+		err = PTR_ERR(dsi->regs);
+		goto remove;
+	}
 
-	dsi->mipi = tegra_mipi_request(&pdev->dev);
-	if (IS_ERR(dsi->mipi))
-		return PTR_ERR(dsi->mipi);
+	dsi->mipi = tegra_mipi_request(&pdev->dev, pdev->dev.of_node);
+	if (IS_ERR(dsi->mipi)) {
+		err = PTR_ERR(dsi->mipi);
+		goto remove;
+	}
 
 	dsi->host.ops = &tegra_dsi_host_ops;
 	dsi->host.dev = &pdev->dev;
@@ -1568,9 +1582,12 @@
 	return 0;
 
 unregister:
+	pm_runtime_disable(&pdev->dev);
 	mipi_dsi_host_unregister(&dsi->host);
 mipi_free:
 	tegra_mipi_free(dsi->mipi);
+remove:
+	tegra_output_remove(&dsi->output);
 	return err;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/tegra/fb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/tegra/fb.c
@@ -155,6 +155,7 @@
 
 		if (gem->size < size) {
 			err = -EINVAL;
+			drm_gem_object_put(gem);
 			goto unreference;
 		}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/tegra/hub.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/tegra/hub.c
@@ -141,7 +141,9 @@
 	for (i = 0; i < hub->soc->num_wgrps; i++) {
 		struct tegra_windowgroup *wgrp = &hub->wgrps[i];
 
-		tegra_windowgroup_enable(wgrp);
+		/* Skip orphaned window group whose parent DC is disabled */
+		if (wgrp->parent)
+			tegra_windowgroup_enable(wgrp);
 	}
 
 	return 0;
@@ -158,7 +160,9 @@
 	for (i = 0; i < hub->soc->num_wgrps; i++) {
 		struct tegra_windowgroup *wgrp = &hub->wgrps[i];
 
-		tegra_windowgroup_disable(wgrp);
+		/* Skip orphaned window group whose parent DC is disabled */
+		if (wgrp->parent)
+			tegra_windowgroup_disable(wgrp);
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/tegra/output.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/tegra/output.c
@@ -127,8 +127,10 @@
 						       GPIOD_IN,
 						       "HDMI hotplug detect");
 	if (IS_ERR(output->hpd_gpio)) {
-		if (PTR_ERR(output->hpd_gpio) != -ENOENT)
-			return PTR_ERR(output->hpd_gpio);
+		if (PTR_ERR(output->hpd_gpio) != -ENOENT) {
+			err = PTR_ERR(output->hpd_gpio);
+			goto put_i2c;
+		}
 
 		output->hpd_gpio = NULL;
 	}
@@ -137,7 +139,7 @@
 		err = gpiod_to_irq(output->hpd_gpio);
 		if (err < 0) {
 			dev_err(output->dev, "gpiod_to_irq(): %d\n", err);
-			return err;
+			goto put_i2c;
 		}
 
 		output->hpd_irq = err;
@@ -150,7 +152,7 @@
 		if (err < 0) {
 			dev_err(output->dev, "failed to request IRQ#%u: %d\n",
 				output->hpd_irq, err);
-			return err;
+			goto put_i2c;
 		}
 
 		output->connector.polled = DRM_CONNECTOR_POLL_HPD;
@@ -168,6 +170,12 @@
 		return -ENOMEM;
 
 	return 0;
+
+put_i2c:
+	if (output->ddc)
+		i2c_put_adapter(output->ddc);
+
+	return err;
 }
 
 void tegra_output_remove(struct tegra_output *output)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/tegra/sor.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/tegra/sor.c
@@ -906,7 +906,7 @@
 				    struct drm_dp_link *link)
 {
 	const u64 f = 100000, link_rate = link->rate * 1000;
-	const u64 pclk = mode->clock * 1000;
+	const u64 pclk = (u64)mode->clock * 1000;
 	u64 input, output, watermark, num;
 	struct tegra_sor_params params;
 	u32 num_syms_per_line;
@@ -2875,21 +2875,21 @@
 		if (err < 0) {
 			dev_err(sor->dev, "failed to acquire SOR reset: %d\n",
 				err);
-			return err;
+			goto rpm_put;
 		}
 
 		err = reset_control_assert(sor->rst);
 		if (err < 0) {
 			dev_err(sor->dev, "failed to assert SOR reset: %d\n",
 				err);
-			return err;
+			goto rpm_put;
 		}
 	}
 
 	err = clk_prepare_enable(sor->clk);
 	if (err < 0) {
 		dev_err(sor->dev, "failed to enable clock: %d\n", err);
-		return err;
+		goto rpm_put;
 	}
 
 	usleep_range(1000, 3000);
@@ -2899,19 +2899,25 @@
 		if (err < 0) {
 			dev_err(sor->dev, "failed to deassert SOR reset: %d\n",
 				err);
-			return err;
+			clk_disable_unprepare(sor->clk);
+			goto rpm_put;
 		}
 
 		reset_control_release(sor->rst);
 	}
 
 	err = clk_prepare_enable(sor->clk_safe);
-	if (err < 0)
+	if (err < 0) {
+		clk_disable_unprepare(sor->clk);
 		return err;
+	}
 
 	err = clk_prepare_enable(sor->clk_dp);
-	if (err < 0)
+	if (err < 0) {
+		clk_disable_unprepare(sor->clk_safe);
+		clk_disable_unprepare(sor->clk);
 		return err;
+	}
 
 	/*
 	 * Enable and unmask the HDA codec SCRATCH0 register interrupt. This
@@ -2923,6 +2929,12 @@
 	tegra_sor_writel(sor, value, SOR_INT_MASK);
 
 	return 0;
+
+rpm_put:
+	if (sor->rst)
+		pm_runtime_put(sor->dev);
+
+	return err;
 }
 
 static int tegra_sor_exit(struct host1x_client *client)
@@ -3200,6 +3212,11 @@
 		 * earlier
 		 */
 		sor->pad = TEGRA_IO_PAD_HDMI_DP0 + sor->index;
+	} else {
+		if (sor->soc->supports_edp)
+			sor->index = 0;
+		else
+			sor->index = 1;
 	}
 
 	err = of_property_read_u32_array(np, "nvidia,xbar-cfg", xbar_cfg, 5);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/tilcdc/tilcdc_external.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/tilcdc/tilcdc_external.c
@@ -58,11 +58,13 @@
 int tilcdc_add_component_encoder(struct drm_device *ddev)
 {
 	struct tilcdc_drm_private *priv = ddev->dev_private;
-	struct drm_encoder *encoder;
+	struct drm_encoder *encoder = NULL, *iter;
 
-	list_for_each_entry(encoder, &ddev->mode_config.encoder_list, head)
-		if (encoder->possible_crtcs & (1 << priv->crtc->index))
+	list_for_each_entry(iter, &ddev->mode_config.encoder_list, head)
+		if (iter->possible_crtcs & (1 << priv->crtc->index)) {
+			encoder = iter;
 			break;
+		}
 
 	if (!encoder) {
 		dev_err(ddev->dev, "%s: No suitable encoder found\n", __func__);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/tilcdc/tilcdc_panel.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/tilcdc/tilcdc_panel.c
@@ -143,12 +143,16 @@
 	int i;
 
 	for (i = 0; i < timings->num_timings; i++) {
-		struct drm_display_mode *mode = drm_mode_create(dev);
+		struct drm_display_mode *mode;
 		struct videomode vm;
 
 		if (videomode_from_timings(timings, &vm, i))
 			break;
 
+		mode = drm_mode_create(dev);
+		if (!mode)
+			break;
+
 		drm_display_mode_from_videomode(&vm, mode);
 
 		mode->type = DRM_MODE_TYPE_DRIVER;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/ttm/ttm_bo.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/ttm/ttm_bo.c
@@ -517,8 +517,10 @@
 
 		dma_resv_unlock(bo->base.resv);
 	}
-	if (bo->base.resv != &bo->base._resv)
+	if (bo->base.resv != &bo->base._resv) {
+		ttm_bo_flush_all_fences(bo);
 		dma_resv_unlock(&bo->base._resv);
+	}
 
 error:
 	kref_get(&bo->list_kref);
@@ -759,7 +761,7 @@
 	/* Don't evict this BO if it's outside of the
 	 * requested placement range
 	 */
-	if (place->fpfn >= (bo->mem.start + bo->mem.size) ||
+	if (place->fpfn >= (bo->mem.start + bo->mem.num_pages) ||
 	    (place->lpfn && place->lpfn <= bo->mem.start))
 		return false;
 
@@ -926,7 +928,8 @@
  */
 static int ttm_bo_add_move_fence(struct ttm_buffer_object *bo,
 				 struct ttm_mem_type_manager *man,
-				 struct ttm_mem_reg *mem)
+				 struct ttm_mem_reg *mem,
+				 bool no_wait_gpu)
 {
 	struct dma_fence *fence;
 	int ret;
@@ -935,19 +938,24 @@
 	fence = dma_fence_get(man->move);
 	spin_unlock(&man->move_lock);
 
-	if (fence) {
-		dma_resv_add_shared_fence(bo->base.resv, fence);
+	if (!fence)
+		return 0;
 
-		ret = dma_resv_reserve_shared(bo->base.resv, 1);
-		if (unlikely(ret)) {
-			dma_fence_put(fence);
-			return ret;
-		}
+	if (no_wait_gpu) {
+		dma_fence_put(fence);
+		return -EBUSY;
+	}
+
+	dma_resv_add_shared_fence(bo->base.resv, fence);
 
-		dma_fence_put(bo->moving);
-		bo->moving = fence;
+	ret = dma_resv_reserve_shared(bo->base.resv, 1);
+	if (unlikely(ret)) {
+		dma_fence_put(fence);
+		return ret;
 	}
 
+	dma_fence_put(bo->moving);
+	bo->moving = fence;
 	return 0;
 }
 
@@ -978,7 +986,7 @@
 			return ret;
 	} while (1);
 
-	return ttm_bo_add_move_fence(bo, man, mem);
+	return ttm_bo_add_move_fence(bo, man, mem, ctx->no_wait_gpu);
 }
 
 static uint32_t ttm_bo_select_caching(struct ttm_mem_type_manager *man,
@@ -1120,14 +1128,18 @@
 		if (unlikely(ret))
 			goto error;
 
-		if (mem->mm_node) {
-			ret = ttm_bo_add_move_fence(bo, man, mem);
-			if (unlikely(ret)) {
-				(*man->func->put_node)(man, mem);
-				goto error;
-			}
-			return 0;
+		if (!mem->mm_node)
+			continue;
+
+		ret = ttm_bo_add_move_fence(bo, man, mem, ctx->no_wait_gpu);
+		if (unlikely(ret)) {
+			(*man->func->put_node)(man, mem);
+			if (ret == -EBUSY)
+				continue;
+
+			goto error;
 		}
+		return 0;
 	}
 
 	for (i = 0; i < placement->num_busy_placement; ++i) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/ttm/ttm_bo_vm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/ttm/ttm_bo_vm.c
@@ -358,8 +358,10 @@
 static int ttm_bo_vm_access(struct vm_area_struct *vma, unsigned long addr,
 			    void *buf, int len, int write)
 {
-	unsigned long offset = (addr) - vma->vm_start;
 	struct ttm_buffer_object *bo = vma->vm_private_data;
+	unsigned long offset = (addr) - vma->vm_start +
+		((vma->vm_pgoff - drm_vma_node_start(&bo->base.vma_node))
+		 << PAGE_SHIFT);
 	int ret;
 
 	if (len < 1 || (offset + len) >> PAGE_SHIFT > bo->num_pages)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/ttm/ttm_tt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/ttm/ttm_tt.c
@@ -241,7 +241,6 @@
 	ttm_tt_init_fields(ttm, bo, page_flags);
 
 	if (ttm_tt_alloc_page_directory(ttm)) {
-		ttm_tt_destroy(ttm);
 		pr_err("Failed allocating page table\n");
 		return -ENOMEM;
 	}
@@ -265,7 +264,6 @@
 
 	INIT_LIST_HEAD(&ttm_dma->pages_list);
 	if (ttm_dma_tt_alloc_page_directory(ttm_dma)) {
-		ttm_tt_destroy(ttm);
 		pr_err("Failed allocating page table\n");
 		return -ENOMEM;
 	}
@@ -287,7 +285,6 @@
 	else
 		ret = ttm_dma_tt_alloc_page_directory(ttm_dma);
 	if (ret) {
-		ttm_tt_destroy(ttm);
 		pr_err("Failed allocating page table\n");
 		return -ENOMEM;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/tve200/tve200_display.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/tve200/tve200_display.c
@@ -14,6 +14,7 @@
 #include <linux/version.h>
 #include <linux/dma-buf.h>
 #include <linux/of_graph.h>
+#include <linux/delay.h>
 
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_fourcc.h>
@@ -130,9 +131,25 @@
 	struct drm_connector *connector = priv->connector;
 	u32 format = fb->format->format;
 	u32 ctrl1 = 0;
+	int retries;
 
 	clk_prepare_enable(priv->clk);
 
+	/* Reset the TVE200 and wait for it to come back online */
+	writel(TVE200_CTRL_4_RESET, priv->regs + TVE200_CTRL_4);
+	for (retries = 0; retries < 5; retries++) {
+		usleep_range(30000, 50000);
+		if (readl(priv->regs + TVE200_CTRL_4) & TVE200_CTRL_4_RESET)
+			continue;
+		else
+			break;
+	}
+	if (retries == 5 &&
+	    readl(priv->regs + TVE200_CTRL_4) & TVE200_CTRL_4_RESET) {
+		dev_err(drm->dev, "can't get hardware out of reset\n");
+		return;
+	}
+
 	/* Function 1 */
 	ctrl1 |= TVE200_CTRL_CSMODE;
 	/* Interlace mode for CCIR656: parameterize? */
@@ -230,8 +247,9 @@
 
 	drm_crtc_vblank_off(crtc);
 
-	/* Disable and Power Down */
+	/* Disable put into reset and Power Down */
 	writel(0, priv->regs + TVE200_CTRL);
+	writel(TVE200_CTRL_4_RESET, priv->regs + TVE200_CTRL_4);
 
 	clk_disable_unprepare(priv->clk);
 }
@@ -279,6 +297,8 @@
 	struct drm_device *drm = crtc->dev;
 	struct tve200_drm_dev_private *priv = drm->dev_private;
 
+	/* Clear any IRQs and enable */
+	writel(0xFF, priv->regs + TVE200_INT_CLR);
 	writel(TVE200_INT_V_STATUS, priv->regs + TVE200_INT_EN);
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/tve200/tve200_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/tve200/tve200_drv.c
@@ -210,8 +210,8 @@
 	}
 
 	irq = platform_get_irq(pdev, 0);
-	if (!irq) {
-		ret = -EINVAL;
+	if (irq < 0) {
+		ret = irq;
 		goto clk_disable;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/udl/udl_connector.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/udl/udl_connector.c
@@ -29,7 +29,7 @@
 		ret = usb_control_msg(udl->udev,
 				      usb_rcvctrlpipe(udl->udev, 0),
 					  (0x02), (0x80 | (0x02 << 5)), bval,
-					  0xA1, read_buff, 2, HZ);
+					  0xA1, read_buff, 2, 1000);
 		if (ret < 1) {
 			DRM_ERROR("Read EDID byte %d failed err %x\n", i, ret);
 			kfree(read_buff);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/v3d/v3d_gem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/v3d/v3d_gem.c
@@ -195,8 +195,8 @@
 
 	V3D_CORE_WRITE(core, V3D_CTL_L2TCACTL, V3D_L2TCACTL_TMUWCF);
 	if (wait_for(!(V3D_CORE_READ(core, V3D_CTL_L2TCACTL) &
-		       V3D_L2TCACTL_L2TFLS), 100)) {
-		DRM_ERROR("Timeout waiting for L1T write combiner flush\n");
+		       V3D_L2TCACTL_TMUWCF), 100)) {
+		DRM_ERROR("Timeout waiting for TMU write combiner flush\n");
 	}
 
 	mutex_lock(&v3d->cache_clean_lock);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/v3d/v3d_irq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/v3d/v3d_irq.c
@@ -102,7 +102,10 @@
 			to_v3d_fence(v3d->bin_job->base.irq_fence);
 
 		trace_v3d_bcl_irq(&v3d->drm, fence->seqno);
+
+		v3d->bin_job = NULL;
 		dma_fence_signal(&fence->base);
+
 		status = IRQ_HANDLED;
 	}
 
@@ -111,7 +114,10 @@
 			to_v3d_fence(v3d->render_job->base.irq_fence);
 
 		trace_v3d_rcl_irq(&v3d->drm, fence->seqno);
+
+		v3d->render_job = NULL;
 		dma_fence_signal(&fence->base);
+
 		status = IRQ_HANDLED;
 	}
 
@@ -120,7 +126,10 @@
 			to_v3d_fence(v3d->csd_job->base.irq_fence);
 
 		trace_v3d_csd_irq(&v3d->drm, fence->seqno);
+
+		v3d->csd_job = NULL;
 		dma_fence_signal(&fence->base);
+
 		status = IRQ_HANDLED;
 	}
 
@@ -156,7 +165,10 @@
 			to_v3d_fence(v3d->tfu_job->base.irq_fence);
 
 		trace_v3d_tfu_irq(&v3d->drm, fence->seqno);
+
+		v3d->tfu_job = NULL;
 		dma_fence_signal(&fence->base);
+
 		status = IRQ_HANDLED;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/v3d/v3d_sched.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/v3d/v3d_sched.c
@@ -188,11 +188,15 @@
 	struct drm_device *dev = &v3d->drm;
 	struct dma_fence *fence;
 
+	if (unlikely(job->base.base.s_fence->finished.error))
+		return NULL;
+
+	v3d->tfu_job = job;
+
 	fence = v3d_fence_create(v3d, V3D_TFU);
 	if (IS_ERR(fence))
 		return NULL;
 
-	v3d->tfu_job = job;
 	if (job->base.irq_fence)
 		dma_fence_put(job->base.irq_fence);
 	job->base.irq_fence = dma_fence_get(fence);
@@ -226,6 +230,9 @@
 	struct dma_fence *fence;
 	int i;
 
+	if (unlikely(job->base.base.s_fence->finished.error))
+		return NULL;
+
 	v3d->csd_job = job;
 
 	v3d_invalidate_caches(v3d);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/vboxvideo/hgsmi_base.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/vboxvideo/hgsmi_base.c
@@ -135,7 +135,15 @@
 		flags |= VBOX_MOUSE_POINTER_VISIBLE;
 	}
 
-	p = hgsmi_buffer_alloc(ctx, sizeof(*p) + pixel_len, HGSMI_CH_VBVA,
+	/*
+	 * The 4 extra bytes come from switching struct vbva_mouse_pointer_shape
+	 * from having a 4 bytes fixed array at the end to using a proper VLA
+	 * at the end. These 4 extra bytes were not subtracted from sizeof(*p)
+	 * before the switch to the VLA, so this way the behavior is unchanged.
+	 * Chances are these 4 extra bytes are not necessary but they are kept
+	 * to avoid regressions.
+	 */
+	p = hgsmi_buffer_alloc(ctx, sizeof(*p) + pixel_len + 4, HGSMI_CH_VBVA,
 			       VBVA_MOUSE_POINTER_SHAPE);
 	if (!p)
 		return -ENOMEM;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/vboxvideo/vboxvideo.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/vboxvideo/vboxvideo.h
@@ -351,10 +351,8 @@
 	 * Bytes in the gap between the AND and the XOR mask are undefined.
 	 * XOR mask scanlines have no gap between them and size of XOR mask is:
 	 * xor_len = width * 4 * height.
-	 *
-	 * Preallocate 4 bytes for accessing actual data as p->data.
 	 */
-	u8 data[4];
+	u8 data[];
 } __packed;
 
 /* pointer is visible */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/vc4/vc4_bo.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/vc4/vc4_bo.c
@@ -389,7 +389,7 @@
 
 	bo = kzalloc(sizeof(*bo), GFP_KERNEL);
 	if (!bo)
-		return ERR_PTR(-ENOMEM);
+		return NULL;
 
 	bo->madv = VC4_MADV_WILLNEED;
 	refcount_set(&bo->usecnt, 0);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/vc4/vc4_dpi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/vc4/vc4_dpi.c
@@ -151,35 +151,45 @@
 	}
 	drm_connector_list_iter_end(&conn_iter);
 
-	if (connector && connector->display_info.num_bus_formats) {
-		u32 bus_format = connector->display_info.bus_formats[0];
+	if (connector) {
+		if (connector->display_info.num_bus_formats) {
+			u32 bus_format = connector->display_info.bus_formats[0];
 
-		switch (bus_format) {
-		case MEDIA_BUS_FMT_RGB888_1X24:
-			dpi_c |= VC4_SET_FIELD(DPI_FORMAT_24BIT_888_RGB,
-					       DPI_FORMAT);
-			break;
-		case MEDIA_BUS_FMT_BGR888_1X24:
-			dpi_c |= VC4_SET_FIELD(DPI_FORMAT_24BIT_888_RGB,
-					       DPI_FORMAT);
-			dpi_c |= VC4_SET_FIELD(DPI_ORDER_BGR, DPI_ORDER);
-			break;
-		case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
-			dpi_c |= VC4_SET_FIELD(DPI_FORMAT_18BIT_666_RGB_2,
-					       DPI_FORMAT);
-			break;
-		case MEDIA_BUS_FMT_RGB666_1X18:
-			dpi_c |= VC4_SET_FIELD(DPI_FORMAT_18BIT_666_RGB_1,
-					       DPI_FORMAT);
-			break;
-		case MEDIA_BUS_FMT_RGB565_1X16:
-			dpi_c |= VC4_SET_FIELD(DPI_FORMAT_16BIT_565_RGB_3,
-					       DPI_FORMAT);
-			break;
-		default:
-			DRM_ERROR("Unknown media bus format %d\n", bus_format);
-			break;
+			switch (bus_format) {
+			case MEDIA_BUS_FMT_RGB888_1X24:
+				dpi_c |= VC4_SET_FIELD(DPI_FORMAT_24BIT_888_RGB,
+						       DPI_FORMAT);
+				break;
+			case MEDIA_BUS_FMT_BGR888_1X24:
+				dpi_c |= VC4_SET_FIELD(DPI_FORMAT_24BIT_888_RGB,
+						       DPI_FORMAT);
+				dpi_c |= VC4_SET_FIELD(DPI_ORDER_BGR,
+						       DPI_ORDER);
+				break;
+			case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
+				dpi_c |= VC4_SET_FIELD(DPI_FORMAT_18BIT_666_RGB_2,
+						       DPI_FORMAT);
+				break;
+			case MEDIA_BUS_FMT_RGB666_1X18:
+				dpi_c |= VC4_SET_FIELD(DPI_FORMAT_18BIT_666_RGB_1,
+						       DPI_FORMAT);
+				break;
+			case MEDIA_BUS_FMT_RGB565_1X16:
+				dpi_c |= VC4_SET_FIELD(DPI_FORMAT_16BIT_565_RGB_1,
+						       DPI_FORMAT);
+				break;
+			default:
+				DRM_ERROR("Unknown media bus format %d\n",
+					  bus_format);
+				break;
+			}
 		}
+
+		if (connector->display_info.bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE)
+			dpi_c |= DPI_PIXEL_CLK_INVERT;
+
+		if (connector->display_info.bus_flags & DRM_BUS_FLAG_DE_LOW)
+			dpi_c |= DPI_OUTPUT_ENABLE_INVERT;
 	} else {
 		/* Default to 24bit if no connector found. */
 		dpi_c |= VC4_SET_FIELD(DPI_FORMAT_24BIT_888_RGB, DPI_FORMAT);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/vc4/vc4_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/vc4/vc4_drv.c
@@ -309,6 +309,7 @@
 	component_unbind_all(dev, drm);
 gem_destroy:
 	vc4_gem_destroy(drm);
+	drm_mode_config_cleanup(drm);
 	vc4_bo_cache_destroy(drm);
 dev_put:
 	drm_dev_put(drm);
@@ -391,7 +392,12 @@
 	if (ret)
 		return ret;
 
-	return platform_driver_register(&vc4_platform_driver);
+	ret = platform_driver_register(&vc4_platform_driver);
+	if (ret)
+		platform_unregister_drivers(component_drivers,
+					    ARRAY_SIZE(component_drivers));
+
+	return ret;
 }
 
 static void __exit vc4_drm_unregister(void)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/vc4/vc4_drv.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/vc4/vc4_drv.h
@@ -750,7 +750,7 @@
 void vc4_crtc_handle_vblank(struct vc4_crtc *crtc);
 void vc4_crtc_txp_armed(struct drm_crtc_state *state);
 void vc4_crtc_get_margins(struct drm_crtc_state *state,
-			  unsigned int *right, unsigned int *left,
+			  unsigned int *left, unsigned int *right,
 			  unsigned int *top, unsigned int *bottom);
 
 /* vc4_debugfs.c */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/vc4/vc4_dsi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/vc4/vc4_dsi.c
@@ -752,9 +752,9 @@
 	struct vc4_dsi *dsi = vc4_encoder->dsi;
 	struct device *dev = &dsi->pdev->dev;
 
-	drm_bridge_disable(dsi->bridge);
+	drm_bridge_chain_disable(dsi->bridge);
 	vc4_dsi_ulps(dsi, true);
-	drm_bridge_post_disable(dsi->bridge);
+	drm_bridge_chain_post_disable(dsi->bridge);
 
 	clk_disable_unprepare(dsi->pll_phy_clock);
 	clk_disable_unprepare(dsi->escape_clock);
@@ -791,11 +791,9 @@
 	/* Find what divider gets us a faster clock than the requested
 	 * pixel clock.
 	 */
-	for (divider = 1; divider < 8; divider++) {
-		if (parent_rate / divider < pll_clock) {
-			divider--;
+	for (divider = 1; divider < 255; divider++) {
+		if (parent_rate / (divider + 1) < pll_clock)
 			break;
-		}
 	}
 
 	/* Now that we've picked a PLL divider, calculate back to its
@@ -831,7 +829,7 @@
 	unsigned long phy_clock;
 	int ret;
 
-	ret = pm_runtime_get_sync(dev);
+	ret = pm_runtime_resume_and_get(dev);
 	if (ret) {
 		DRM_ERROR("Failed to runtime PM enable on DSI%d\n", dsi->port);
 		return;
@@ -1054,7 +1052,7 @@
 
 	vc4_dsi_ulps(dsi, false);
 
-	drm_bridge_pre_enable(dsi->bridge);
+	drm_bridge_chain_pre_enable(dsi->bridge);
 
 	if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
 		DSI_PORT_WRITE(DISP0_CTRL,
@@ -1071,7 +1069,7 @@
 			       DSI_DISP0_ENABLE);
 	}
 
-	drm_bridge_enable(dsi->bridge);
+	drm_bridge_chain_enable(dsi->bridge);
 
 	if (debug_dump_regs) {
 		struct drm_printer p = drm_info_printer(&dsi->pdev->dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -236,7 +236,7 @@
 	edid = drm_get_edid(connector, vc4->hdmi->ddc);
 	cec_s_phys_addr_from_edid(vc4->hdmi->cec_adap, edid);
 	if (!edid)
-		return -ENODEV;
+		return 0;
 
 	vc4_encoder->hdmi_monitor = drm_detect_hdmi_monitor(edid);
 
@@ -681,11 +681,23 @@
 vc4_hdmi_encoder_mode_valid(struct drm_encoder *crtc,
 			    const struct drm_display_mode *mode)
 {
-	/* HSM clock must be 108% of the pixel clock.  Additionally,
-	 * the AXI clock needs to be at least 25% of pixel clock, but
-	 * HSM ends up being the limiting factor.
+	/*
+	 * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must
+	 * be faster than pixel clock, infinitesimally faster, tested in
+	 * simulation. Otherwise, exact value is unimportant for HDMI
+	 * operation." This conflicts with bcm2835's vc4 documentation, which
+	 * states HSM's clock has to be at least 108% of the pixel clock.
+	 *
+	 * Real life tests reveal that vc4's firmware statement holds up, and
+	 * users are able to use pixel clocks closer to HSM's, namely for
+	 * 1920x1200@60Hz. So it was decided to have leave a 1% margin between
+	 * both clocks. Which, for RPi0-3 implies a maximum pixel clock of
+	 * 162MHz.
+	 *
+	 * Additionally, the AXI clock needs to be at least 25% of
+	 * pixel clock, but HSM ends up being the limiting factor.
 	 */
-	if (mode->clock > HSM_CLOCK_FREQ / (1000 * 108 / 100))
+	if (mode->clock > HSM_CLOCK_FREQ / (1000 * 101 / 100))
 		return MODE_CLOCK_HIGH;
 
 	return MODE_OK;
@@ -1113,6 +1125,7 @@
 	card->num_links = 1;
 	card->name = "vc4-hdmi";
 	card->dev = dev;
+	card->owner = THIS_MODULE;
 
 	/*
 	 * Be careful, snd_soc_register_card() calls dev_set_drvdata() and
@@ -1285,6 +1298,9 @@
 
 static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
 {
+#ifdef CONFIG_DRM_VC4_HDMI_CEC
+	struct cec_connector_info conn_info;
+#endif
 	struct platform_device *pdev = to_platform_device(dev);
 	struct drm_device *drm = dev_get_drvdata(master);
 	struct vc4_dev *vc4 = drm->dev_private;
@@ -1403,13 +1419,15 @@
 #ifdef CONFIG_DRM_VC4_HDMI_CEC
 	hdmi->cec_adap = cec_allocate_adapter(&vc4_hdmi_cec_adap_ops,
 					      vc4, "vc4",
-					      CEC_CAP_TRANSMIT |
-					      CEC_CAP_LOG_ADDRS |
-					      CEC_CAP_PASSTHROUGH |
-					      CEC_CAP_RC, 1);
+					      CEC_CAP_DEFAULTS |
+					      CEC_CAP_CONNECTOR_INFO, 1);
 	ret = PTR_ERR_OR_ZERO(hdmi->cec_adap);
 	if (ret < 0)
 		goto err_destroy_conn;
+
+	cec_fill_conn_info_from_drm(&conn_info, hdmi->connector);
+	cec_s_conn_info(hdmi->cec_adap, &conn_info);
+
 	HDMI_WRITE(VC4_HDMI_CPU_MASK_SET, 0xffffffff);
 	value = HDMI_READ(VC4_HDMI_CEC_CNTRL_1);
 	value &= ~VC4_HDMI_CEC_DIV_CLK_CNT_MASK;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/vc4/vc4_plane.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/vc4/vc4_plane.c
@@ -205,7 +205,7 @@
 	__drm_atomic_helper_plane_reset(plane, &vc4_state->base);
 }
 
-static void vc4_dlist_write(struct vc4_plane_state *vc4_state, u32 val)
+static void vc4_dlist_counter_increment(struct vc4_plane_state *vc4_state)
 {
 	if (vc4_state->dlist_count == vc4_state->dlist_size) {
 		u32 new_size = max(4u, vc4_state->dlist_count * 2);
@@ -220,7 +220,15 @@
 		vc4_state->dlist_size = new_size;
 	}
 
-	vc4_state->dlist[vc4_state->dlist_count++] = val;
+	vc4_state->dlist_count++;
+}
+
+static void vc4_dlist_write(struct vc4_plane_state *vc4_state, u32 val)
+{
+	unsigned int idx = vc4_state->dlist_count;
+
+	vc4_dlist_counter_increment(vc4_state);
+	vc4_state->dlist[idx] = val;
 }
 
 /* Returns the scl0/scl1 field based on whether the dimensions need to
@@ -280,16 +288,16 @@
 					       adjhdisplay,
 					       crtc_state->mode.hdisplay);
 	vc4_pstate->crtc_x += left;
-	if (vc4_pstate->crtc_x > crtc_state->mode.hdisplay - left)
-		vc4_pstate->crtc_x = crtc_state->mode.hdisplay - left;
+	if (vc4_pstate->crtc_x > crtc_state->mode.hdisplay - right)
+		vc4_pstate->crtc_x = crtc_state->mode.hdisplay - right;
 
 	adjvdisplay = crtc_state->mode.vdisplay - (top + bottom);
 	vc4_pstate->crtc_y = DIV_ROUND_CLOSEST(vc4_pstate->crtc_y *
 					       adjvdisplay,
 					       crtc_state->mode.vdisplay);
 	vc4_pstate->crtc_y += top;
-	if (vc4_pstate->crtc_y > crtc_state->mode.vdisplay - top)
-		vc4_pstate->crtc_y = crtc_state->mode.vdisplay - top;
+	if (vc4_pstate->crtc_y > crtc_state->mode.vdisplay - bottom)
+		vc4_pstate->crtc_y = crtc_state->mode.vdisplay - bottom;
 
 	vc4_pstate->crtc_w = DIV_ROUND_CLOSEST(vc4_pstate->crtc_w *
 					       adjhdisplay,
@@ -309,7 +317,6 @@
 	struct vc4_plane_state *vc4_state = to_vc4_plane_state(state);
 	struct drm_framebuffer *fb = state->fb;
 	struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
-	u32 subpixel_src_mask = (1 << 16) - 1;
 	int num_planes = fb->format->num_planes;
 	struct drm_crtc_state *crtc_state;
 	u32 h_subsample = fb->format->hsub;
@@ -331,18 +338,15 @@
 	for (i = 0; i < num_planes; i++)
 		vc4_state->offsets[i] = bo->paddr + fb->offsets[i];
 
-	/* We don't support subpixel source positioning for scaling. */
-	if ((state->src.x1 & subpixel_src_mask) ||
-	    (state->src.x2 & subpixel_src_mask) ||
-	    (state->src.y1 & subpixel_src_mask) ||
-	    (state->src.y2 & subpixel_src_mask)) {
-		return -EINVAL;
-	}
-
-	vc4_state->src_x = state->src.x1 >> 16;
-	vc4_state->src_y = state->src.y1 >> 16;
-	vc4_state->src_w[0] = (state->src.x2 - state->src.x1) >> 16;
-	vc4_state->src_h[0] = (state->src.y2 - state->src.y1) >> 16;
+	/*
+	 * We don't support subpixel source positioning for scaling,
+	 * but fractional coordinates can be generated by clipping
+	 * so just round for now
+	 */
+	vc4_state->src_x = DIV_ROUND_CLOSEST(state->src.x1, 1 << 16);
+	vc4_state->src_y = DIV_ROUND_CLOSEST(state->src.y1, 1 << 16);
+	vc4_state->src_w[0] = DIV_ROUND_CLOSEST(state->src.x2, 1 << 16) - vc4_state->src_x;
+	vc4_state->src_h[0] = DIV_ROUND_CLOSEST(state->src.y2, 1 << 16) - vc4_state->src_y;
 
 	vc4_state->crtc_x = state->dst.x1;
 	vc4_state->crtc_y = state->dst.y1;
@@ -871,8 +875,10 @@
 		 * be set when calling vc4_plane_allocate_lbm().
 		 */
 		if (vc4_state->y_scaling[0] != VC4_SCALING_NONE ||
-		    vc4_state->y_scaling[1] != VC4_SCALING_NONE)
-			vc4_state->lbm_offset = vc4_state->dlist_count++;
+		    vc4_state->y_scaling[1] != VC4_SCALING_NONE) {
+			vc4_state->lbm_offset = vc4_state->dlist_count;
+			vc4_dlist_counter_increment(vc4_state);
+		}
 
 		if (num_planes > 1) {
 			/* Emit Cb/Cr as channel 0 and Y as channel
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/vc4/vc4_txp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/vc4/vc4_txp.c
@@ -285,12 +285,18 @@
 	if (WARN_ON(i == ARRAY_SIZE(drm_fmts)))
 		return;
 
-	ctrl = TXP_GO | TXP_VSTART_AT_EOF | TXP_EI |
+	ctrl = TXP_GO | TXP_EI |
 	       VC4_SET_FIELD(0xf, TXP_BYTE_ENABLE) |
 	       VC4_SET_FIELD(txp_fmts[i], TXP_FORMAT);
 
 	if (fb->format->has_alpha)
 		ctrl |= TXP_ALPHA_ENABLE;
+	else
+		/*
+		 * If TXP_ALPHA_ENABLE isn't set and TXP_ALPHA_INVERT is, the
+		 * hardware will force the output padding to be 0xff.
+		 */
+		ctrl |= TXP_ALPHA_INVERT;
 
 	gem = drm_fb_cma_get_gem_obj(fb, 0);
 	TXP_WRITE(TXP_DST_PTR, gem->paddr + fb->offsets[0]);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/vc4/vc4_vec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/vc4/vc4_vec.c
@@ -256,7 +256,7 @@
 static const struct drm_display_mode ntsc_mode = {
 	DRM_MODE("720x480", DRM_MODE_TYPE_DRIVER, 13500,
 		 720, 720 + 14, 720 + 14 + 64, 720 + 14 + 64 + 60, 0,
-		 480, 480 + 3, 480 + 3 + 3, 480 + 3 + 3 + 16, 0,
+		 480, 480 + 7, 480 + 7 + 6, 525, 0,
 		 DRM_MODE_FLAG_INTERLACE)
 };
 
@@ -278,7 +278,7 @@
 static const struct drm_display_mode pal_mode = {
 	DRM_MODE("720x576", DRM_MODE_TYPE_DRIVER, 13500,
 		 720, 720 + 20, 720 + 20 + 64, 720 + 20 + 64 + 60, 0,
-		 576, 576 + 2, 576 + 2 + 3, 576 + 2 + 3 + 20, 0,
+		 576, 576 + 4, 576 + 4 + 6, 625, 0,
 		 DRM_MODE_FLAG_INTERLACE)
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/vgem/vgem_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/vgem/vgem_drv.c
@@ -196,9 +196,10 @@
 		return ERR_CAST(obj);
 
 	ret = drm_gem_handle_create(file, &obj->base, handle);
-	drm_gem_object_put_unlocked(&obj->base);
-	if (ret)
+	if (ret) {
+		drm_gem_object_put_unlocked(&obj->base);
 		return ERR_PTR(ret);
+	}
 
 	return &obj->base;
 }
@@ -221,35 +222,11 @@
 	args->size = gem_object->size;
 	args->pitch = pitch;
 
-	DRM_DEBUG("Created object of size %lld\n", size);
+	drm_gem_object_put_unlocked(gem_object);
 
-	return 0;
-}
-
-static int vgem_gem_dumb_map(struct drm_file *file, struct drm_device *dev,
-			     uint32_t handle, uint64_t *offset)
-{
-	struct drm_gem_object *obj;
-	int ret;
+	DRM_DEBUG("Created object of size %llu\n", args->size);
 
-	obj = drm_gem_object_lookup(file, handle);
-	if (!obj)
-		return -ENOENT;
-
-	if (!obj->filp) {
-		ret = -EINVAL;
-		goto unref;
-	}
-
-	ret = drm_gem_create_mmap_offset(obj);
-	if (ret)
-		goto unref;
-
-	*offset = drm_vma_node_offset_addr(&obj->vma_node);
-unref:
-	drm_gem_object_put_unlocked(obj);
-
-	return ret;
+	return 0;
 }
 
 static struct drm_ioctl_desc vgem_ioctls[] = {
@@ -445,7 +422,6 @@
 	.fops				= &vgem_driver_fops,
 
 	.dumb_create			= vgem_gem_dumb_create,
-	.dumb_map_offset		= vgem_gem_dumb_map,
 
 	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
 	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/vgem/vgem_fence.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/vgem/vgem_fence.c
@@ -249,4 +249,5 @@
 {
 	idr_for_each(&vfile->fence_idr, __vgem_fence_idr_fini, vfile);
 	idr_destroy(&vfile->fence_idr);
+	mutex_destroy(&vfile->fence_mutex);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/virtio/virtgpu_display.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/virtio/virtgpu_display.c
@@ -174,6 +174,8 @@
 		DRM_DEBUG("add mode: %dx%d\n", width, height);
 		mode = drm_cvt_mode(connector->dev, width, height, 60,
 				    false, false, false);
+		if (!mode)
+			return count;
 		mode->type |= DRM_MODE_TYPE_PREFERRED;
 		drm_mode_probed_add(connector, mode);
 		count++;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/virtio/virtgpu_ioctl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/virtio/virtgpu_ioctl.c
@@ -327,10 +327,18 @@
 		drm_gem_object_release(obj);
 		return ret;
 	}
-	drm_gem_object_put_unlocked(obj);
 
 	rc->res_handle = qobj->hw_res_handle; /* similiar to a VM address */
 	rc->bo_handle = handle;
+
+	/*
+	 * The handle owns the reference now.  But we must drop our
+	 * remaining reference *after* we no longer need to dereference
+	 * the obj.  Otherwise userspace could guess the handle and
+	 * race closing it from another thread.
+	 */
+	drm_gem_object_put_unlocked(obj);
+
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/virtio/virtgpu_kms.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/virtio/virtgpu_kms.c
@@ -96,8 +96,10 @@
 					 vgdev->capsets[i].id > 0, 5 * HZ);
 		if (ret == 0) {
 			DRM_ERROR("timed out waiting for cap set %d\n", i);
+			spin_lock(&vgdev->display_info_lock);
 			kfree(vgdev->capsets);
 			vgdev->capsets = NULL;
+			spin_unlock(&vgdev->display_info_lock);
 			return;
 		}
 		DRM_INFO("cap set %d: id %d, max-version %d, max-size %d\n",
@@ -216,6 +218,7 @@
 err_vbufs:
 	vgdev->vdev->config->del_vqs(vgdev->vdev);
 err_vqs:
+	dev->dev_private = NULL;
 	kfree(vgdev);
 	return ret;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/virtio/virtgpu_object.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/virtio/virtgpu_object.c
@@ -23,38 +23,44 @@
  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#include <linux/moduleparam.h>
+
 #include <drm/ttm/ttm_execbuf_util.h>
 
 #include "virtgpu_drv.h"
 
+static int virtio_gpu_virglrenderer_workaround = 1;
+module_param_named(virglhack, virtio_gpu_virglrenderer_workaround, int, 0400);
+
 static int virtio_gpu_resource_id_get(struct virtio_gpu_device *vgdev,
 				       uint32_t *resid)
 {
-#if 0
-	int handle = ida_alloc(&vgdev->resource_ida, GFP_KERNEL);
-
-	if (handle < 0)
-		return handle;
-#else
-	static int handle;
-
-	/*
-	 * FIXME: dirty hack to avoid re-using IDs, virglrenderer
-	 * can't deal with that.  Needs fixing in virglrenderer, also
-	 * should figure a better way to handle that in the guest.
-	 */
-	handle++;
-#endif
-
-	*resid = handle + 1;
+	if (virtio_gpu_virglrenderer_workaround) {
+		/*
+		 * Hack to avoid re-using resource IDs.
+		 *
+		 * virglrenderer versions up to (and including) 0.7.0
+		 * can't deal with that.  virglrenderer commit
+		 * "f91a9dd35715 Fix unlinking resources from hash
+		 * table." (Feb 2019) fixes the bug.
+		 */
+		static atomic_t seqno = ATOMIC_INIT(0);
+		int handle = atomic_inc_return(&seqno);
+		*resid = handle + 1;
+	} else {
+		int handle = ida_alloc(&vgdev->resource_ida, GFP_KERNEL);
+		if (handle < 0)
+			return handle;
+		*resid = handle + 1;
+	}
 	return 0;
 }
 
 static void virtio_gpu_resource_id_put(struct virtio_gpu_device *vgdev, uint32_t id)
 {
-#if 0
-	ida_free(&vgdev->resource_ida, id - 1);
-#endif
+	if (!virtio_gpu_virglrenderer_workaround) {
+		ida_free(&vgdev->resource_ida, id - 1);
+	}
 }
 
 static void virtio_gpu_ttm_bo_destroy(struct ttm_buffer_object *tbo)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/virtio/virtgpu_vq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/virtio/virtgpu_vq.c
@@ -80,9 +80,7 @@
 {
 	struct virtio_gpu_vbuffer *vbuf;
 
-	vbuf = kmem_cache_zalloc(vgdev->vbufs, GFP_KERNEL);
-	if (!vbuf)
-		return ERR_PTR(-ENOMEM);
+	vbuf = kmem_cache_zalloc(vgdev->vbufs, GFP_KERNEL | __GFP_NOFAIL);
 
 	BUG_ON(size > MAX_INLINE_CMD_SIZE);
 	vbuf->buf = (void *)vbuf + sizeof(*vbuf);
@@ -142,10 +140,6 @@
 
 	vbuf = virtio_gpu_get_vbuf(vgdev, cmd_size,
 				   resp_size, resp_buf, cb);
-	if (IS_ERR(vbuf)) {
-		*vbuffer_p = NULL;
-		return ERR_CAST(vbuf);
-	}
 	*vbuffer_p = vbuf;
 	return (struct virtio_gpu_command *)vbuf->buf;
 }
@@ -572,9 +566,13 @@
 	int i = le32_to_cpu(cmd->capset_index);
 
 	spin_lock(&vgdev->display_info_lock);
-	vgdev->capsets[i].id = le32_to_cpu(resp->capset_id);
-	vgdev->capsets[i].max_version = le32_to_cpu(resp->capset_max_version);
-	vgdev->capsets[i].max_size = le32_to_cpu(resp->capset_max_size);
+	if (vgdev->capsets) {
+		vgdev->capsets[i].id = le32_to_cpu(resp->capset_id);
+		vgdev->capsets[i].max_version = le32_to_cpu(resp->capset_max_version);
+		vgdev->capsets[i].max_size = le32_to_cpu(resp->capset_max_size);
+	} else {
+		DRM_ERROR("invalid capset memory.");
+	}
 	spin_unlock(&vgdev->display_info_lock);
 	wake_up(&vgdev->resp_wq);
 }
@@ -988,8 +986,9 @@
 	}
 
 	/* gets freed when the ring has consumed it */
-	ents = kmalloc_array(nents, sizeof(struct virtio_gpu_mem_entry),
-			     GFP_KERNEL);
+	ents = kvmalloc_array(nents,
+			      sizeof(struct virtio_gpu_mem_entry),
+			      GFP_KERNEL);
 	if (!ents) {
 		DRM_ERROR("failed to allocate ent list\n");
 		return -ENOMEM;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/vkms/vkms_composer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/vkms/vkms_composer.c
@@ -33,7 +33,7 @@
 				     + (i * composer->pitch)
 				     + (j * composer->cpp);
 			/* XRGB format ignores Alpha channel */
-			memset(vaddr_out + src_offset + 24, 0,  8);
+			bitmap_clear(vaddr_out + src_offset, 24, 8);
 			crc = crc32_le(crc, vaddr_out + src_offset,
 				       sizeof(u32));
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/vkms/vkms_crtc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/vkms/vkms_crtc.c
@@ -20,7 +20,8 @@
 
 	ret_overrun = hrtimer_forward_now(&output->vblank_hrtimer,
 					  output->period_ns);
-	WARN_ON(ret_overrun != 1);
+	if (ret_overrun != 1)
+		pr_warn("%s: vblank timer overrun\n", __func__);
 
 	ret = drm_crtc_handle_vblank(crtc);
 	if (!ret)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/vkms/vkms_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/vkms/vkms_drv.c
@@ -60,7 +60,6 @@
 	struct vkms_device *vkms = container_of(dev, struct vkms_device, drm);
 
 	platform_device_unregister(vkms->platform);
-	drm_atomic_helper_shutdown(&vkms->drm);
 	drm_mode_config_cleanup(&vkms->drm);
 	drm_dev_fini(&vkms->drm);
 	destroy_workqueue(vkms->output.composer_workq);
@@ -194,6 +193,7 @@
 	}
 
 	drm_dev_unregister(&vkms_device->drm);
+	drm_atomic_helper_shutdown(&vkms_device->drm);
 	drm_dev_put(&vkms_device->drm);
 
 	kfree(vkms_device);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/vkms/vkms_drv.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/vkms/vkms_drv.h
@@ -121,11 +121,6 @@
 				  enum drm_plane_type type, int index);
 
 /* Gem stuff */
-struct drm_gem_object *vkms_gem_create(struct drm_device *dev,
-				       struct drm_file *file,
-				       u32 *handle,
-				       u64 size);
-
 vm_fault_t vkms_gem_fault(struct vm_fault *vmf);
 
 int vkms_dumb_create(struct drm_file *file, struct drm_device *dev,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/vkms/vkms_gem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/vkms/vkms_gem.c
@@ -95,10 +95,10 @@
 	return ret;
 }
 
-struct drm_gem_object *vkms_gem_create(struct drm_device *dev,
-				       struct drm_file *file,
-				       u32 *handle,
-				       u64 size)
+static struct drm_gem_object *vkms_gem_create(struct drm_device *dev,
+					      struct drm_file *file,
+					      u32 *handle,
+					      u64 size)
 {
 	struct vkms_gem_object *obj;
 	int ret;
@@ -111,7 +111,6 @@
 		return ERR_CAST(obj);
 
 	ret = drm_gem_handle_create(file, &obj->gem, handle);
-	drm_gem_object_put_unlocked(&obj->gem);
 	if (ret)
 		return ERR_PTR(ret);
 
@@ -140,6 +139,8 @@
 	args->size = gem_obj->size;
 	args->pitch = pitch;
 
+	drm_gem_object_put_unlocked(gem_obj);
+
 	DRM_DEBUG_DRIVER("Created object of size %lld\n", size);
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c
@@ -209,8 +209,10 @@
 
 	cres->hash.key = user_key | (res_type << 24);
 	ret = drm_ht_insert_item(&man->resources, &cres->hash);
-	if (unlikely(ret != 0))
+	if (unlikely(ret != 0)) {
+		kfree(cres);
 		goto out_invalid_key;
+	}
 
 	cres->state = VMW_CMDBUF_RES_ADD;
 	cres->res = vmw_resource_reference(res);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/vmwgfx/vmwgfx_context.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/vmwgfx/vmwgfx_context.c
@@ -731,7 +731,7 @@
 	};
 	int ret;
 
-	if (!dev_priv->has_dx && dx) {
+	if (!has_sm4_context(dev_priv) && dx) {
 		VMW_DEBUG_USER("DX contexts not supported by device.\n");
 		return -EINVAL;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -442,7 +442,7 @@
 	dev_priv->cman = vmw_cmdbuf_man_create(dev_priv);
 	if (IS_ERR(dev_priv->cman)) {
 		dev_priv->cman = NULL;
-		dev_priv->has_dx = false;
+		dev_priv->sm_type = VMW_SM_LEGACY;
 	}
 
 	ret = vmw_request_device_late(dev_priv);
@@ -870,11 +870,22 @@
 	if (dev_priv->has_mob) {
 		spin_lock(&dev_priv->cap_lock);
 		vmw_write(dev_priv, SVGA_REG_DEV_CAP, SVGA3D_DEVCAP_DXCONTEXT);
-		dev_priv->has_dx = !!vmw_read(dev_priv, SVGA_REG_DEV_CAP);
+		if (vmw_read(dev_priv, SVGA_REG_DEV_CAP))
+			dev_priv->sm_type = VMW_SM_4;
 		spin_unlock(&dev_priv->cap_lock);
 	}
 
 	vmw_validation_mem_init_ttm(dev_priv, VMWGFX_VALIDATION_MEM_GRAN);
+
+	/* SVGA_CAP2_DX2 (DefineGBSurface_v3) is needed for SM4_1 support */
+	if (has_sm4_context(dev_priv) &&
+	    (dev_priv->capabilities2 & SVGA_CAP2_DX2)) {
+		vmw_write(dev_priv, SVGA_REG_DEV_CAP, SVGA3D_DEVCAP_SM41);
+
+		if (vmw_read(dev_priv, SVGA_REG_DEV_CAP))
+			dev_priv->sm_type = VMW_SM_4_1;
+	}
+
 	ret = vmw_kms_init(dev_priv);
 	if (unlikely(ret != 0))
 		goto out_no_kms;
@@ -884,23 +895,12 @@
 	if (ret)
 		goto out_no_fifo;
 
-	if (dev_priv->has_dx) {
-		/*
-		 * SVGA_CAP2_DX2 (DefineGBSurface_v3) is needed for SM4_1
-		 * support
-		 */
-		if ((dev_priv->capabilities2 & SVGA_CAP2_DX2) != 0) {
-			vmw_write(dev_priv, SVGA_REG_DEV_CAP,
-					SVGA3D_DEVCAP_SM41);
-			dev_priv->has_sm4_1 = vmw_read(dev_priv,
-							SVGA_REG_DEV_CAP);
-		}
-	}
-
-	DRM_INFO("DX: %s\n", dev_priv->has_dx ? "yes." : "no.");
 	DRM_INFO("Atomic: %s\n", (dev->driver->driver_features & DRIVER_ATOMIC)
 		 ? "yes." : "no.");
-	DRM_INFO("SM4_1: %s\n", dev_priv->has_sm4_1 ? "yes." : "no.");
+	if (dev_priv->sm_type == VMW_SM_4_1)
+		DRM_INFO("SM4_1 support available.\n");
+	if (dev_priv->sm_type == VMW_SM_4)
+		DRM_INFO("SM4 support available.\n");
 
 	snprintf(host_log, sizeof(host_log), "vmwgfx: %s-%s",
 		VMWGFX_REPO, VMWGFX_GIT_VERSION);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -432,6 +432,20 @@
 	VMW_IRQTHREAD_MAX
 };
 
+/**
+ * enum vmw_sm_type - Graphics context capability supported by device.
+ * @VMW_SM_LEGACY: Pre DX context.
+ * @VMW_SM_4: Context support upto SM4.
+ * @VMW_SM_4_1: Context support upto SM4_1.
+ * @VMW_SM_MAX: Should be the last.
+ */
+enum vmw_sm_type {
+	VMW_SM_LEGACY = 0,
+	VMW_SM_4,
+	VMW_SM_4_1,
+	VMW_SM_MAX
+};
+
 struct vmw_private {
 	struct ttm_bo_device bdev;
 
@@ -465,9 +479,9 @@
 	bool has_mob;
 	spinlock_t hw_lock;
 	spinlock_t cap_lock;
-	bool has_dx;
 	bool assume_16bpp;
-	bool has_sm4_1;
+
+	enum vmw_sm_type sm_type;
 
 	/*
 	 * VGA registers.
@@ -651,6 +665,28 @@
 	return val;
 }
 
+/**
+ * has_sm4_context - Does the device support SM4 context.
+ * @dev_priv: Device private.
+ *
+ * Return: Bool value if device support SM4 context or not.
+ */
+static inline bool has_sm4_context(const struct vmw_private *dev_priv)
+{
+	return (dev_priv->sm_type >= VMW_SM_4);
+}
+
+/**
+ * has_sm4_1_context - Does the device support SM4_1 context.
+ * @dev_priv: Device private.
+ *
+ * Return: Bool value if device support SM4_1 context or not.
+ */
+static inline bool has_sm4_1_context(const struct vmw_private *dev_priv)
+{
+	return (dev_priv->sm_type >= VMW_SM_4_1);
+}
+
 extern void vmw_svga_enable(struct vmw_private *dev_priv);
 extern void vmw_svga_disable(struct vmw_private *dev_priv);
 
@@ -1002,15 +1038,14 @@
 				      struct vmw_private *dev_priv,
 				      struct vmw_fence_obj **p_fence,
 				      uint32_t *p_handle);
-extern void vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv,
+extern int vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv,
 					struct vmw_fpriv *vmw_fp,
 					int ret,
 					struct drm_vmw_fence_rep __user
 					*user_fence_rep,
 					struct vmw_fence_obj *fence,
 					uint32_t fence_handle,
-					int32_t out_fence_fd,
-					struct sync_file *sync_file);
+					int32_t out_fence_fd);
 bool vmw_cmd_describe(const void *buf, u32 *size, char const **cmd);
 
 /**
@@ -1487,4 +1522,15 @@
 {
 	WRITE_ONCE(*addr, value);
 }
+
+static inline bool vmw_shadertype_is_valid(enum vmw_sm_type shader_model,
+					   u32 shader_type)
+{
+	SVGA3dShaderType max_allowed = SVGA3D_SHADERTYPE_PREDX_MAX;
+
+	if (shader_model >= VMW_SM_4)
+		max_allowed = SVGA3D_SHADERTYPE_DX10_MAX;
+	return shader_type >= SVGA3D_SHADERTYPE_MIN && shader_type < max_allowed;
+}
+
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -461,10 +461,11 @@
 	u32 i;
 
 	/* Add all cotables to the validation list. */
-	if (dev_priv->has_dx && vmw_res_type(ctx) == vmw_res_dx_context) {
+	if (has_sm4_context(dev_priv) &&
+	    vmw_res_type(ctx) == vmw_res_dx_context) {
 		for (i = 0; i < SVGA_COTABLE_DX10_MAX; ++i) {
 			res = vmw_context_cotable(ctx, i);
-			if (IS_ERR(res))
+			if (IS_ERR_OR_NULL(res))
 				continue;
 
 			ret = vmw_execbuf_res_noctx_val_add(sw_context, res,
@@ -489,7 +490,8 @@
 			break;
 	}
 
-	if (dev_priv->has_dx && vmw_res_type(ctx) == vmw_res_dx_context) {
+	if (has_sm4_context(dev_priv) &&
+	    vmw_res_type(ctx) == vmw_res_dx_context) {
 		struct vmw_buffer_object *dx_query_mob;
 
 		dx_query_mob = vmw_context_get_dx_query_mob(ctx);
@@ -1268,6 +1270,8 @@
 		return -EINVAL;
 
 	cotable_res = vmw_context_cotable(ctx_node->ctx, SVGA_COTABLE_DXQUERY);
+	if (IS_ERR_OR_NULL(cotable_res))
+		return cotable_res ? PTR_ERR(cotable_res) : -EINVAL;
 	ret = vmw_cotable_notify(cotable_res, cmd->body.queryId);
 
 	return ret;
@@ -1623,7 +1627,7 @@
 {
 	VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdSetTextureState);
 	SVGA3dTextureState *last_state = (SVGA3dTextureState *)
-	  ((unsigned long) header + header->size + sizeof(header));
+	  ((unsigned long) header + header->size + sizeof(*header));
 	SVGA3dTextureState *cur_state = (SVGA3dTextureState *)
 		((unsigned long) header + sizeof(*cmd));
 	struct vmw_resource *ctx;
@@ -1994,7 +1998,7 @@
 
 	cmd = container_of(header, typeof(*cmd), header);
 
-	if (cmd->body.type >= SVGA3D_SHADERTYPE_PREDX_MAX) {
+	if (!vmw_shadertype_is_valid(VMW_SM_LEGACY, cmd->body.type)) {
 		VMW_DEBUG_USER("Illegal shader type %u.\n",
 			       (unsigned int) cmd->body.type);
 		return -EINVAL;
@@ -2131,6 +2135,14 @@
 	if (unlikely(ret != 0))
 		return ret;
 
+	if (!vmw_shadertype_is_valid(dev_priv->sm_type, cmd->body.type) ||
+	    cmd->body.slot >= SVGA3D_DX_MAX_CONSTBUFFERS) {
+		VMW_DEBUG_USER("Illegal const buffer shader %u slot %u.\n",
+			       (unsigned int) cmd->body.type,
+			       (unsigned int) cmd->body.slot);
+		return -EINVAL;
+	}
+
 	binding.bi.ctx = ctx_node->ctx;
 	binding.bi.res = res;
 	binding.bi.bt = vmw_ctx_binding_cb;
@@ -2139,14 +2151,6 @@
 	binding.size = cmd->body.sizeInBytes;
 	binding.slot = cmd->body.slot;
 
-	if (binding.shader_slot >= SVGA3D_NUM_SHADERTYPE_DX10 ||
-	    binding.slot >= SVGA3D_DX_MAX_CONSTBUFFERS) {
-		VMW_DEBUG_USER("Illegal const buffer shader %u slot %u.\n",
-			       (unsigned int) cmd->body.type,
-			       (unsigned int) binding.slot);
-		return -EINVAL;
-	}
-
 	vmw_binding_add(ctx_node->staged, &binding.bi, binding.shader_slot,
 			binding.slot);
 
@@ -2167,12 +2171,13 @@
 {
 	VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXSetShaderResources) =
 		container_of(header, typeof(*cmd), header);
+
 	u32 num_sr_view = (cmd->header.size - sizeof(cmd->body)) /
 		sizeof(SVGA3dShaderResourceViewId);
 
 	if ((u64) cmd->body.startView + (u64) num_sr_view >
 	    (u64) SVGA3D_DX_MAX_SRVIEWS ||
-	    cmd->body.type >= SVGA3D_SHADERTYPE_DX10_MAX) {
+	    !vmw_shadertype_is_valid(dev_priv->sm_type, cmd->body.type)) {
 		VMW_DEBUG_USER("Invalid shader binding.\n");
 		return -EINVAL;
 	}
@@ -2206,8 +2211,7 @@
 
 	cmd = container_of(header, typeof(*cmd), header);
 
-	if (cmd->body.type >= SVGA3D_SHADERTYPE_DX10_MAX ||
-	    cmd->body.type < SVGA3D_SHADERTYPE_MIN) {
+	if (!vmw_shadertype_is_valid(dev_priv->sm_type, cmd->body.type)) {
 		VMW_DEBUG_USER("Illegal shader type %u.\n",
 			       (unsigned int) cmd->body.type);
 		return -EINVAL;
@@ -2439,6 +2443,8 @@
 		return ret;
 
 	res = vmw_context_cotable(ctx_node->ctx, vmw_view_cotables[view_type]);
+	if (IS_ERR_OR_NULL(res))
+		return res ? PTR_ERR(res) : -EINVAL;
 	ret = vmw_cotable_notify(res, cmd->defined_id);
 	if (unlikely(ret != 0))
 		return ret;
@@ -2524,6 +2530,8 @@
 
 	so_type = vmw_so_cmd_to_type(header->id);
 	res = vmw_context_cotable(ctx_node->ctx, vmw_so_cotables[so_type]);
+	if (IS_ERR_OR_NULL(res))
+		return res ? PTR_ERR(res) : -EINVAL;
 	cmd = container_of(header, typeof(*cmd), header);
 	ret = vmw_cotable_notify(res, cmd->defined_id);
 
@@ -2643,6 +2651,8 @@
 		return -EINVAL;
 
 	res = vmw_context_cotable(ctx_node->ctx, SVGA_COTABLE_DXSHADER);
+	if (IS_ERR_OR_NULL(res))
+		return res ? PTR_ERR(res) : -EINVAL;
 	ret = vmw_cotable_notify(res, cmd->body.shaderId);
 	if (ret)
 		return ret;
@@ -3413,17 +3423,17 @@
  * Also if copying fails, user-space will be unable to signal the fence object
  * so we wait for it immediately, and then unreference the user-space reference.
  */
-void
+int
 vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv,
 			    struct vmw_fpriv *vmw_fp, int ret,
 			    struct drm_vmw_fence_rep __user *user_fence_rep,
 			    struct vmw_fence_obj *fence, uint32_t fence_handle,
-			    int32_t out_fence_fd, struct sync_file *sync_file)
+			    int32_t out_fence_fd)
 {
 	struct drm_vmw_fence_rep fence_rep;
 
 	if (user_fence_rep == NULL)
-		return;
+		return 0;
 
 	memset(&fence_rep, 0, sizeof(fence_rep));
 
@@ -3451,20 +3461,14 @@
 	 * handle.
 	 */
 	if (unlikely(ret != 0) && (fence_rep.error == 0)) {
-		if (sync_file)
-			fput(sync_file->file);
-
-		if (fence_rep.fd != -1) {
-			put_unused_fd(fence_rep.fd);
-			fence_rep.fd = -1;
-		}
-
 		ttm_ref_object_base_unref(vmw_fp->tfile, fence_handle,
 					  TTM_REF_USAGE);
 		VMW_DEBUG_USER("Fence copy error. Syncing.\n");
 		(void) vmw_fence_obj_wait(fence, false, false,
 					  VMW_FENCE_WAIT_TIMEOUT);
 	}
+
+	return ret ? -EFAULT : 0;
 }
 
 /**
@@ -3806,16 +3810,23 @@
 
 			(void) vmw_fence_obj_wait(fence, false, false,
 						  VMW_FENCE_WAIT_TIMEOUT);
+		}
+	}
+
+	ret = vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv), ret,
+				    user_fence_rep, fence, handle, out_fence_fd);
+
+	if (sync_file) {
+		if (ret) {
+			/* usercopy of fence failed, put the file object */
+			fput(sync_file->file);
+			put_unused_fd(out_fence_fd);
 		} else {
 			/* Link the fence with the FD created earlier */
 			fd_install(out_fence_fd, sync_file->file);
 		}
 	}
 
-	vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv), ret,
-				    user_fence_rep, fence, handle, out_fence_fd,
-				    sync_file);
-
 	/* Don't unreference when handing fence out */
 	if (unlikely(out_fence != NULL)) {
 		*out_fence = fence;
@@ -3833,7 +3844,7 @@
 	 */
 	vmw_validation_unref_lists(&val_ctx);
 
-	return 0;
+	return ret;
 
 out_unlock_binding:
 	mutex_unlock(&dev_priv->binding_mutex);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
@@ -498,7 +498,7 @@
 
 static int vmw_fb_kms_framebuffer(struct fb_info *info)
 {
-	struct drm_mode_fb_cmd2 mode_cmd;
+	struct drm_mode_fb_cmd2 mode_cmd = {0};
 	struct vmw_fb_par *par = info->par;
 	struct fb_var_screeninfo *var = &info->var;
 	struct drm_framebuffer *cur_fb;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
@@ -32,7 +32,6 @@
 #define VMW_FENCE_WRAP (1 << 31)
 
 struct vmw_fence_manager {
-	int num_fence_objects;
 	struct vmw_private *dev_priv;
 	spinlock_t lock;
 	struct list_head fence_list;
@@ -113,13 +112,13 @@
 {
 	struct vmw_fence_obj *fence =
 		container_of(f, struct vmw_fence_obj, base);
-
 	struct vmw_fence_manager *fman = fman_from_fence(fence);
 
-	spin_lock(&fman->lock);
-	list_del_init(&fence->head);
-	--fman->num_fence_objects;
-	spin_unlock(&fman->lock);
+	if (!list_empty(&fence->head)) {
+		spin_lock(&fman->lock);
+		list_del_init(&fence->head);
+		spin_unlock(&fman->lock);
+	}
 	fence->destroy(fence);
 }
 
@@ -353,7 +352,6 @@
 		goto out_unlock;
 	}
 	list_add_tail(&fence->head, &fman->fence_list);
-	++fman->num_fence_objects;
 
 out_unlock:
 	spin_unlock(&fman->lock);
@@ -402,7 +400,7 @@
 {
 	u32 goal_seqno;
 	u32 *fifo_mem;
-	struct vmw_fence_obj *fence;
+	struct vmw_fence_obj *fence, *next_fence;
 
 	if (likely(!fman->seqno_valid))
 		return false;
@@ -413,7 +411,7 @@
 		return false;
 
 	fman->seqno_valid = false;
-	list_for_each_entry(fence, &fman->fence_list, head) {
+	list_for_each_entry_safe(fence, next_fence, &fman->fence_list, head) {
 		if (!list_empty(&fence->seq_passed_actions)) {
 			fman->seqno_valid = true;
 			vmw_mmio_write(fence->base.seqno,
@@ -1066,7 +1064,7 @@
 	}
 
 	event->event.base.type = DRM_VMW_EVENT_FENCE_SIGNALED;
-	event->event.base.length = sizeof(*event);
+	event->event.base.length = sizeof(event->event);
 	event->event.user_data = user_data;
 
 	ret = drm_event_reserve_init(dev, file_priv, &event->base, &event->event.base);
@@ -1171,7 +1169,7 @@
 	}
 
 	vmw_execbuf_copy_fence_user(dev_priv, vmw_fp, 0, user_fence_rep, fence,
-				    handle, -1, NULL);
+				    handle, -1);
 	vmw_fence_obj_unreference(&fence);
 	return 0;
 out_no_create:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
@@ -114,10 +114,10 @@
 			(dev_priv->active_display_unit == vmw_du_screen_target);
 		break;
 	case DRM_VMW_PARAM_DX:
-		param->value = dev_priv->has_dx;
+		param->value = has_sm4_context(dev_priv);
 		break;
 	case DRM_VMW_PARAM_SM4_1:
-		param->value = dev_priv->has_sm4_1;
+		param->value = has_sm4_1_context(dev_priv);
 		break;
 	default:
 		return -EINVAL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -182,7 +182,8 @@
 	if (cmd->dma.guest.ptr.offset % PAGE_SIZE ||
 	    box->x != 0    || box->y != 0    || box->z != 0    ||
 	    box->srcx != 0 || box->srcy != 0 || box->srcz != 0 ||
-	    box->d != 1    || box_count != 1) {
+	    box->d != 1    || box_count != 1 ||
+	    box->w > 64 || box->h > 64) {
 		/* TODO handle none page aligned offsets */
 		/* TODO handle more dst & src != 0 */
 		/* TODO handle more then one copy */
@@ -941,7 +942,7 @@
 	 * For DX, surface format validation is done when surface->scanout
 	 * is set.
 	 */
-	if (!dev_priv->has_dx && format != surface->format) {
+	if (!has_sm4_context(dev_priv) && format != surface->format) {
 		DRM_ERROR("Invalid surface format for requested mode.\n");
 		return -EINVAL;
 	}
@@ -1409,6 +1410,7 @@
 		DRM_ERROR("Surface size cannot exceed %dx%d",
 			dev_priv->texture_max_width,
 			dev_priv->texture_max_height);
+		ret = -EINVAL;
 		goto err_out;
 	}
 
@@ -2570,7 +2572,7 @@
 	if (file_priv)
 		vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv),
 					    ret, user_fence_rep, fence,
-					    handle, -1, NULL);
+					    handle, -1);
 	if (out_fence)
 		*out_fence = fence;
 	else
@@ -2666,7 +2668,7 @@
 		++i;
 	}
 
-	if (i != unit) {
+	if (&con->head == &dev_priv->dev->mode_config.connector_list) {
 		DRM_ERROR("Could not find initial display unit.\n");
 		ret = -EINVAL;
 		goto out_unlock;
@@ -2690,13 +2692,13 @@
 			break;
 	}
 
-	if (mode->type & DRM_MODE_TYPE_PREFERRED)
-		*p_mode = mode;
-	else {
+	if (&mode->head == &con->modes) {
 		WARN_ONCE(true, "Could not find initial preferred mode.\n");
 		*p_mode = list_first_entry(&con->modes,
 					   struct drm_display_mode,
 					   head);
+	} else {
+		*p_mode = mode;
 	}
 
  out_unlock:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -81,7 +81,7 @@
 	struct vmw_legacy_display_unit *entry;
 	struct drm_framebuffer *fb = NULL;
 	struct drm_crtc *crtc = NULL;
-	int i = 0;
+	int i;
 
 	/* If there is no display topology the host just assumes
 	 * that the guest will set the same layout as the host.
@@ -92,12 +92,11 @@
 			crtc = &entry->base.crtc;
 			w = max(w, crtc->x + crtc->mode.hdisplay);
 			h = max(h, crtc->y + crtc->mode.vdisplay);
-			i++;
 		}
 
 		if (crtc == NULL)
 			return 0;
-		fb = entry->base.crtc.primary->state->fb;
+		fb = crtc->primary->state->fb;
 
 		return vmw_kms_write_svga(dev_priv, w, h, fb->pitches[0],
 					  fb->format->cpp[0] * 8,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c
@@ -320,7 +320,7 @@
 	struct vmw_otable **otables = &dev_priv->otable_batch.otables;
 	int ret;
 
-	if (dev_priv->has_dx) {
+	if (has_sm4_context(dev_priv)) {
 		*otables = kmemdup(dx_tables, sizeof(dx_tables), GFP_KERNEL);
 		if (!(*otables))
 			return -ENOMEM;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
@@ -98,7 +98,7 @@
 {
 	struct vmw_escape_video_flush *flush;
 	size_t fifo_size;
-	bool have_so = (dev_priv->active_display_unit == vmw_du_screen_object);
+	bool have_so = (dev_priv->active_display_unit != vmw_du_legacy);
 	int i, num_items;
 	SVGAGuestPtr ptr;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
@@ -1059,12 +1059,12 @@
 		goto out_no_fifo;
 	}
 
-	if (dev_priv->has_sm4_1 && srf->array_size > 0) {
+	if (has_sm4_1_context(dev_priv) && srf->array_size > 0) {
 		cmd_id = SVGA_3D_CMD_DEFINE_GB_SURFACE_V3;
 		cmd_len = sizeof(cmd3->body);
 		submit_len = sizeof(*cmd3);
 	} else if (srf->array_size > 0) {
-		/* has_dx checked on creation time. */
+		/* VMW_SM_4 support verified at creation time. */
 		cmd_id = SVGA_3D_CMD_DEFINE_GB_SURFACE_V2;
 		cmd_len = sizeof(cmd2->body);
 		submit_len = sizeof(*cmd2);
@@ -1082,7 +1082,7 @@
 		goto out_no_fifo;
 	}
 
-	if (dev_priv->has_sm4_1 && srf->array_size > 0) {
+	if (has_sm4_1_context(dev_priv) && srf->array_size > 0) {
 		cmd3->header.id = cmd_id;
 		cmd3->header.size = cmd_len;
 		cmd3->body.sid = srf->res.id;
@@ -1404,7 +1404,7 @@
 	}
 
 	/* array_size must be null for non-GL3 host. */
-	if (array_size > 0 && !dev_priv->has_dx) {
+	if (array_size > 0 && !has_sm4_context(dev_priv)) {
 		VMW_DEBUG_USER("Tried to create DX surface on non-DX host.\n");
 		return -EINVAL;
 	}
@@ -1562,7 +1562,7 @@
 		SVGA3D_FLAGS_64(req->svga3d_flags_upper_32_bits,
 				req->base.svga3d_flags);
 
-	if (!dev_priv->has_sm4_1) {
+	if (!has_sm4_1_context(dev_priv)) {
 		/*
 		 * If SM4_1 is not support then cannot send 64-bit flag to
 		 * device.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/xen/xen_drm_front.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/xen/xen_drm_front.c
@@ -400,7 +400,7 @@
 	args->size = args->pitch * args->height;
 
 	obj = xen_drm_front_gem_create(dev, args->size);
-	if (IS_ERR_OR_NULL(obj)) {
+	if (IS_ERR(obj)) {
 		ret = PTR_ERR(obj);
 		goto fail;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/xen/xen_drm_front_gem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/xen/xen_drm_front_gem.c
@@ -83,7 +83,7 @@
 
 	size = round_up(size, PAGE_SIZE);
 	xen_obj = gem_create_obj(dev, size);
-	if (IS_ERR_OR_NULL(xen_obj))
+	if (IS_ERR(xen_obj))
 		return xen_obj;
 
 	if (drm_info->front_info->cfg.be_alloc) {
@@ -117,7 +117,7 @@
 	 */
 	xen_obj->num_pages = DIV_ROUND_UP(size, PAGE_SIZE);
 	xen_obj->pages = drm_gem_get_pages(&xen_obj->base);
-	if (IS_ERR_OR_NULL(xen_obj->pages)) {
+	if (IS_ERR(xen_obj->pages)) {
 		ret = PTR_ERR(xen_obj->pages);
 		xen_obj->pages = NULL;
 		goto fail;
@@ -136,7 +136,7 @@
 	struct xen_gem_object *xen_obj;
 
 	xen_obj = gem_create(dev, size);
-	if (IS_ERR_OR_NULL(xen_obj))
+	if (IS_ERR(xen_obj))
 		return ERR_CAST(xen_obj);
 
 	return &xen_obj->base;
@@ -194,7 +194,7 @@
 
 	size = attach->dmabuf->size;
 	xen_obj = gem_create_obj(dev, size);
-	if (IS_ERR_OR_NULL(xen_obj))
+	if (IS_ERR(xen_obj))
 		return ERR_CAST(xen_obj);
 
 	ret = gem_alloc_pages_array(xen_obj, size);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/xen/xen_drm_front_kms.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/xen/xen_drm_front_kms.c
@@ -60,7 +60,7 @@
 	int ret;
 
 	fb = drm_gem_fb_create_with_funcs(dev, filp, mode_cmd, &fb_funcs);
-	if (IS_ERR_OR_NULL(fb))
+	if (IS_ERR(fb))
 		return fb;
 
 	gem_obj = drm_gem_object_lookup(filp, mode_cmd->handles[0]);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/xlnx/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/xlnx/Kconfig
@@ -0,0 +1,115 @@
+config DRM_XLNX
+	tristate "Xilinx DRM KMS Driver"
+	depends on DRM && OF
+	select DRM_KMS_HELPER
+	select DRM_KMS_CMA_HELPER
+	select DRM_GEM_CMA_HELPER
+	help
+	  Xilinx DRM KMS driver. Choose this option if you have
+	  a Xilinx SoCs with hardened display pipeline or soft
+	  display pipeline using Xilinx IPs in FPGA. This module
+	  provides the kernel mode setting functionalities
+	  for Xilinx display drivers.
+
+config DRM_XLNX_BRIDGE
+	tristate "Xilinx DRM KMS bridge"
+	depends on DRM_XLNX
+	help
+	  Xilinx DRM KMS bridge. This module provides some interfaces
+	  to enable inter-module communication. Choose this option
+	  from the provider driver when the Xilinx bridge interface is
+	  needed.
+
+config DRM_XLNX_BRIDGE_DEBUG_FS
+	bool "Xilinx DRM KMS bridge debugfs"
+	depends on DEBUG_FS && DRM_XLNX_BRIDGE
+	help
+	  Enable the debugfs code for Xilinx bridge. The debugfs code
+	  enables debugging or testing related features. It exposes some
+	  low level controls to the user space to help testing automation,
+	  as well as can enable additional diagnostic or statistical
+	  information.
+
+config DRM_ZYNQMP_DPSUB
+	tristate "ZynqMP DP Subsystem Driver"
+	depends on ARCH_ZYNQMP && OF && DRM_XLNX && COMMON_CLK
+	select DMADEVICES
+	select XILINX_DMA_ENGINES
+	select XILINX_DPDMA
+	select PHY_XILINX_ZYNQMP
+	help
+	  DRM KMS driver for ZynqMP DP Subsystem controller. Choose
+	  this option if you have a Xilinx ZynqMP SoC with DisplayPort
+	  subsystem. The driver provides the kernel mode setting
+	  functionalities for ZynqMP DP subsystem.
+
+config DRM_XLNX_DPTX
+	tristate "Xilinx DRM DisplayPort Subsystem Driver"
+	depends on DRM_XLNX
+	help
+	  DRM driver for Xilinx DisplayPort Tx Subsystem for FPGA. Choose
+	  this option if you have a FPGA display pipeline that includes
+	  the Xilinx DisplayPort Tx Subsystem IP. The driver provides
+	  the kernel mode setting functionalities for the IP.
+
+config DRM_XLNX_DSI
+	tristate "Xilinx DRM DSI Subsystem Driver"
+	depends on DRM_XLNX
+	select DRM_MIPI_DSI
+	select DRM_PANEL
+	select BACKLIGHT_LCD_SUPPORT
+	select BACKLIGHT_CLASS_DEVICE
+	select DRM_PANEL_SIMPLE
+	help
+	  DRM driver for Xilinx MIPI-DSI.
+
+config DRM_XLNX_MIXER
+	tristate "Xilinx DRM Mixer Driver"
+	depends on DRM_XLNX
+	select VIDEOMODE_HELPERS
+	help
+	  DRM driver for Xilinx Mixer driver.
+
+config DRM_XLNX_PL_DISP
+	tristate "Xilinx DRM PL display driver"
+	depends on DRM_XLNX
+	select VIDEOMODE_HELPERS
+	help
+	  DRM driver for Xilinx PL display driver, provides drm
+	  crtc and plane object to display pipeline. You need to
+	  choose this option if your display pipeline needs one
+	  crtc and plane object with single DMA connected.
+
+config DRM_XLNX_SDI
+	tristate "Xilinx DRM SDI Subsystem Driver"
+	depends on DRM_XLNX
+	help
+	  DRM driver for Xilinx SDI Tx Subsystem.
+
+config DRM_XLNX_BRIDGE_CSC
+	tristate "Xilinx DRM CSC Driver"
+	depends on DRM_XLNX_BRIDGE
+	help
+	  DRM brige driver for color space converter of VPSS. Choose
+	  this option if color space converter is connected to an encoder.
+	  The driver provides set/get resolution and color format
+	  functionality through bridge layer.
+
+config DRM_XLNX_BRIDGE_SCALER
+	tristate "Xilinx DRM Scaler Driver"
+	depends on DRM_XLNX_BRIDGE
+	help
+	  DRM brige driver for scaler of VPSS. Choose this option
+	  if scaler is connected to an encoder. The driver provides
+	  upscaling, down scaling and no scaling functionality through
+	  bridge layer.
+
+config DRM_XLNX_BRIDGE_VTC
+	tristate "Xilinx DRM VTC Driver"
+	depends on DRM_XLNX_BRIDGE
+	help
+	  DRM brige driver for Xilinx Video Timing Controller. Choose
+	  this option to make VTC a part of the CRTC in display pipeline.
+	  Currently the support is added to the Xilinx Video Mixer and
+	  Xilinx PL display CRTC drivers. This driver provides ability
+	  to generate timings through the bridge layer.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/xlnx/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/xlnx/Makefile
@@ -0,0 +1,23 @@
+xlnx_drm-objs += xlnx_crtc.o xlnx_drv.o xlnx_fb.o xlnx_gem.o
+xlnx_drm-$(CONFIG_DRM_XLNX_BRIDGE) += xlnx_bridge.o
+obj-$(CONFIG_DRM_XLNX) += xlnx_drm.o
+
+obj-$(CONFIG_DRM_XLNX_BRIDGE_CSC) += xlnx_csc.o
+
+obj-$(CONFIG_DRM_XLNX_BRIDGE_SCALER) += xlnx_scaler.o
+
+obj-$(CONFIG_DRM_XLNX_BRIDGE_VTC) += xlnx_vtc.o
+
+obj-$(CONFIG_DRM_XLNX_DPTX) += xlnx_dptx.o
+
+obj-$(CONFIG_DRM_XLNX_DSI) += xlnx_dsi.o
+
+obj-$(CONFIG_DRM_XLNX_MIXER) += xlnx_mixer.o
+
+obj-$(CONFIG_DRM_XLNX_PL_DISP) += xlnx_pl_disp.o
+
+xlnx-sdi-objs += xlnx_sdi.o xlnx_sdi_timing.o
+obj-$(CONFIG_DRM_XLNX_SDI) += xlnx-sdi.o
+
+zynqmp-dpsub-objs += zynqmp_disp.o zynqmp_dpsub.o zynqmp_dp.o
+obj-$(CONFIG_DRM_ZYNQMP_DPSUB) += zynqmp-dpsub.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/xlnx/xlnx_bridge.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/xlnx/xlnx_bridge.c
@@ -0,0 +1,565 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx DRM bridge driver
+ *
+ *  Copyright (C) 2017 Xilinx, Inc.
+ *
+ *  Author: Hyun Woo Kwon <hyun.kwon@xilinx.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <drm/drmP.h>
+
+#include <linux/list.h>
+
+#include "xlnx_bridge.h"
+#include "xlnx_drv.h"
+
+/*
+ * Overview
+ * --------
+ *
+ * Similar to drm bridge, but this can be used by any DRM driver. There
+ * is no limitation to be used by non DRM drivers as well. No complex topology
+ * is modeled, thus it's assumed that the Xilinx bridge device is directly
+ * attached to client. The client should call Xilinx bridge functions explicitly
+ * where it's needed, as opposed to drm bridge functions which are called
+ * implicitly by DRM core.
+ * One Xlnx bridge can be owned by one driver at a time.
+ */
+
+/**
+ * struct xlnx_bridge_helper - Xilinx bridge helper
+ * @xlnx_bridges: list of Xilinx bridges
+ * @lock: lock to protect @xlnx_crtcs
+ * @refcnt: reference count
+ * @error: flag if in error state
+ */
+struct xlnx_bridge_helper {
+	struct list_head xlnx_bridges;
+	struct mutex lock; /* lock for @xlnx_bridges */
+	unsigned int refcnt;
+	bool error;
+};
+
+static struct xlnx_bridge_helper helper;
+
+struct videomode;
+/*
+ * Client functions
+ */
+
+/**
+ * xlnx_bridge_enable - Enable the bridge
+ * @bridge: bridge to enable
+ *
+ * Enable bridge.
+ *
+ * Return: 0 on success. -ENOENT if no callback, -EFAULT in error state,
+ * or return code from callback.
+ */
+int xlnx_bridge_enable(struct xlnx_bridge *bridge)
+{
+	if (!bridge)
+		return 0;
+
+	if (helper.error)
+		return -EFAULT;
+
+	if (bridge->enable)
+		return bridge->enable(bridge);
+
+	return -ENOENT;
+}
+EXPORT_SYMBOL(xlnx_bridge_enable);
+
+/**
+ * xlnx_bridge_disable - Disable the bridge
+ * @bridge: bridge to disable
+ *
+ * Disable bridge.
+ */
+void xlnx_bridge_disable(struct xlnx_bridge *bridge)
+{
+	if (!bridge)
+		return;
+
+	if (helper.error)
+		return;
+
+	if (bridge->disable)
+		bridge->disable(bridge);
+}
+EXPORT_SYMBOL(xlnx_bridge_disable);
+
+/**
+ * xlnx_bridge_set_input - Set the input of @bridge
+ * @bridge: bridge to set
+ * @width: width
+ * @height: height
+ * @bus_fmt: bus format (ex, MEDIA_BUS_FMT_*);
+ *
+ * Set the bridge input with height / width / format.
+ *
+ * Return: 0 on success. -ENOENT if no callback, -EFAULT if in error state,
+ * or return code from callback.
+ */
+int xlnx_bridge_set_input(struct xlnx_bridge *bridge,
+			  u32 width, u32 height, u32 bus_fmt)
+{
+	if (!bridge)
+		return 0;
+
+	if (helper.error)
+		return -EFAULT;
+
+	if (bridge->set_input)
+		return bridge->set_input(bridge, width, height, bus_fmt);
+
+	return -ENOENT;
+}
+EXPORT_SYMBOL(xlnx_bridge_set_input);
+
+/**
+ * xlnx_bridge_get_input_fmts - Get the supported input formats
+ * @bridge: bridge to set
+ * @fmts: pointer to formats
+ * @count: pointer to format count
+ *
+ * Get the list of supported input bus formats.
+ *
+ * Return: 0 on success. -ENOENT if no callback, -EFAULT if in error state,
+ * or return code from callback.
+ */
+int xlnx_bridge_get_input_fmts(struct xlnx_bridge *bridge,
+			       const u32 **fmts, u32 *count)
+{
+	if (!bridge)
+		return 0;
+
+	if (helper.error)
+		return -EFAULT;
+
+	if (bridge->get_input_fmts)
+		return bridge->get_input_fmts(bridge, fmts, count);
+
+	return -ENOENT;
+}
+EXPORT_SYMBOL(xlnx_bridge_get_input_fmts);
+
+/**
+ * xlnx_bridge_set_output - Set the output of @bridge
+ * @bridge: bridge to set
+ * @width: width
+ * @height: height
+ * @bus_fmt: bus format (ex, MEDIA_BUS_FMT_*);
+ *
+ * Set the bridge output with height / width / format.
+ *
+ * Return: 0 on success. -ENOENT if no callback, -EFAULT if in error state,
+ * or return code from callback.
+ */
+int xlnx_bridge_set_output(struct xlnx_bridge *bridge,
+			   u32 width, u32 height, u32 bus_fmt)
+{
+	if (!bridge)
+		return 0;
+
+	if (helper.error)
+		return -EFAULT;
+
+	if (bridge->set_output)
+		return bridge->set_output(bridge, width, height, bus_fmt);
+
+	return -ENOENT;
+}
+EXPORT_SYMBOL(xlnx_bridge_set_output);
+
+/**
+ * xlnx_bridge_get_output_fmts - Get the supported output formats
+ * @bridge: bridge to set
+ * @fmts: pointer to formats
+ * @count: pointer to format count
+ *
+ * Get the list of supported output bus formats.
+ *
+ * Return: 0 on success. -ENOENT if no callback, -EFAULT if in error state,
+ * or return code from callback.
+ */
+int xlnx_bridge_get_output_fmts(struct xlnx_bridge *bridge,
+				const u32 **fmts, u32 *count)
+{
+	if (!bridge)
+		return 0;
+
+	if (helper.error)
+		return -EFAULT;
+
+	if (bridge->get_output_fmts)
+		return bridge->get_output_fmts(bridge, fmts, count);
+
+	return -ENOENT;
+}
+EXPORT_SYMBOL(xlnx_bridge_get_output_fmts);
+
+/**
+ * xlnx_bridge_set_timing - Set the video timing
+ * @bridge: bridge to set
+ * @vm: Videomode
+ *
+ * Set the video mode so that timing can be generated using this
+ * by the video timing controller.
+ *
+ * Return: 0 on success. -ENOENT if no callback, -EFAULT if in error state,
+ * or return code from callback.
+ */
+int xlnx_bridge_set_timing(struct xlnx_bridge *bridge, struct videomode *vm)
+{
+	if (!bridge)
+		return 0;
+
+	if (helper.error)
+		return -EFAULT;
+
+	if (bridge->set_timing) {
+		bridge->set_timing(bridge, vm);
+		return 0;
+	}
+
+	return -ENOENT;
+}
+EXPORT_SYMBOL(xlnx_bridge_set_timing);
+
+/**
+ * of_xlnx_bridge_get - Get the corresponding Xlnx bridge instance
+ * @bridge_np: The device node of the bridge device
+ *
+ * The function walks through the Xlnx bridge list of @drm, and return
+ * if any registered bridge matches the device node. The returned
+ * bridge will not be accesible by others.
+ *
+ * Return: the matching Xlnx bridge instance, or NULL
+ */
+struct xlnx_bridge *of_xlnx_bridge_get(struct device_node *bridge_np)
+{
+	struct xlnx_bridge *found = NULL;
+	struct xlnx_bridge *bridge;
+
+	if (helper.error)
+		return NULL;
+
+	mutex_lock(&helper.lock);
+	list_for_each_entry(bridge, &helper.xlnx_bridges, list) {
+		if (bridge->of_node == bridge_np && !bridge->owned) {
+			found = bridge;
+			bridge->owned = true;
+			break;
+		}
+	}
+	mutex_unlock(&helper.lock);
+
+	return found;
+}
+EXPORT_SYMBOL_GPL(of_xlnx_bridge_get);
+
+/**
+ * of_xlnx_bridge_put - Put the Xlnx bridge instance
+ * @bridge: Xlnx bridge instance to release
+ *
+ * Return the @bridge. After this, the bridge will be available for
+ * other drivers to use.
+ */
+void of_xlnx_bridge_put(struct xlnx_bridge *bridge)
+{
+	if (WARN_ON(helper.error))
+		return;
+
+	mutex_lock(&helper.lock);
+	WARN_ON(!bridge->owned);
+	bridge->owned = false;
+	mutex_unlock(&helper.lock);
+}
+EXPORT_SYMBOL_GPL(of_xlnx_bridge_put);
+
+#ifdef CONFIG_DRM_XLNX_BRIDGE_DEBUG_FS
+
+#include <linux/debugfs.h>
+
+struct xlnx_bridge_debugfs_dir {
+	struct dentry *dir;
+	int ref_cnt;
+};
+
+static struct xlnx_bridge_debugfs_dir *dir;
+
+struct xlnx_bridge_debugfs_file {
+	struct dentry *file;
+	const char *status;
+};
+
+#define XLNX_BRIDGE_DEBUGFS_MAX_BYTES	16
+
+static ssize_t xlnx_bridge_debugfs_read(struct file *f, char __user *buf,
+					size_t size, loff_t *pos)
+{
+	struct xlnx_bridge *bridge = f->f_inode->i_private;
+	int ret;
+
+	if (size <= 0)
+		return -EINVAL;
+
+	if (*pos != 0)
+		return 0;
+
+	size = min(size, strlen(bridge->debugfs_file->status));
+	ret = copy_to_user(buf, bridge->debugfs_file->status, size);
+	if (ret)
+		return ret;
+
+	*pos = size + 1;
+	return size;
+}
+
+static ssize_t xlnx_bridge_debugfs_write(struct file *f, const char __user *buf,
+					 size_t size, loff_t *pos)
+{
+	struct xlnx_bridge *bridge = f->f_inode->i_private;
+
+	if (*pos != 0 || size <= 0)
+		return -EINVAL;
+
+	if (!strncmp(buf, "enable", 5)) {
+		xlnx_bridge_enable(bridge);
+	} else if (!strncmp(buf, "disable", 6)) {
+		xlnx_bridge_disable(bridge);
+	} else if (!strncmp(buf, "set_input", 3)) {
+		char *cmd, **tmp;
+		char *w, *h, *bus_fmt;
+		u32 width = 0, height = 0, fmt = 0;
+		int ret;
+
+		cmd = kzalloc(size, GFP_KERNEL);
+		if (!cmd)
+			return -ENOMEM;
+
+		ret = strncpy_from_user(cmd, buf, size);
+		if (ret < 0) {
+			pr_err("%s %d failed to copy the command  %s\n",
+			       __func__, __LINE__, buf);
+			kfree(cmd);
+			return ret;
+		}
+
+		tmp = &cmd;
+		strsep(tmp, " ");
+		w = strsep(tmp, " ");
+		h = strsep(tmp, " ");
+		bus_fmt = strsep(tmp, " ");
+		if (w && h && bus_fmt) {
+			ret = kstrtouint(w, 0, &width);
+			ret |= kstrtouint(h, 0, &height);
+			ret |= kstrtouint(bus_fmt, 0, &fmt);
+		}
+
+		kfree(cmd);
+		if (ret) {
+			pr_err("%s %d invalid command: %s\n",
+			       __func__, __LINE__, buf);
+			return -EINVAL;
+		}
+		xlnx_bridge_set_input(bridge, width, height, fmt);
+	}
+
+	return size;
+}
+
+static const struct file_operations xlnx_bridge_debugfs_fops = {
+	.owner	= THIS_MODULE,
+	.read	= xlnx_bridge_debugfs_read,
+	.write	= xlnx_bridge_debugfs_write,
+};
+
+static int xlnx_bridge_debugfs_register(struct xlnx_bridge *bridge)
+{
+	struct xlnx_bridge_debugfs_file *file;
+	char file_name[32];
+
+	file = kzalloc(sizeof(*file), GFP_KERNEL);
+	if (!file)
+		return -ENOMEM;
+
+	snprintf(file_name, sizeof(file_name), "xlnx_bridge-%s",
+		 bridge->of_node->name);
+	file->file = debugfs_create_file(file_name, 0444, dir->dir, bridge,
+					 &xlnx_bridge_debugfs_fops);
+	bridge->debugfs_file = file;
+
+	return 0;
+}
+
+static void xlnx_bridge_debugfs_unregister(struct xlnx_bridge *bridge)
+{
+	debugfs_remove(bridge->debugfs_file->file);
+	kfree(bridge->debugfs_file);
+}
+
+static int xlnx_bridge_debugfs_init(void)
+{
+	if (dir) {
+		dir->ref_cnt++;
+		return 0;
+	}
+
+	dir = kzalloc(sizeof(*dir), GFP_KERNEL);
+	if (!dir)
+		return -ENOMEM;
+
+	dir->dir = debugfs_create_dir("xlnx-bridge", NULL);
+	if (!dir->dir)
+		return -ENODEV;
+	dir->ref_cnt++;
+
+	return 0;
+}
+
+static void xlnx_bridge_debugfs_fini(void)
+{
+	if (--dir->ref_cnt)
+		return;
+
+	debugfs_remove_recursive(dir->dir);
+	dir = NULL;
+}
+
+#else
+
+static int xlnx_bridge_debugfs_register(struct xlnx_bridge *bridge)
+{
+	return 0;
+}
+
+static void xlnx_bridge_debugfs_unregister(struct xlnx_bridge *bridge)
+{
+}
+
+static int xlnx_bridge_debugfs_init(void)
+{
+	return 0;
+}
+
+static void xlnx_bridge_debugfs_fini(void)
+{
+}
+
+#endif
+
+/*
+ * Provider functions
+ */
+
+/**
+ * xlnx_bridge_register - Register the bridge instance
+ * @bridge: Xlnx bridge instance to register
+ *
+ * Register @bridge to be available for clients.
+ *
+ * Return: 0 on success. -EPROBE_DEFER if helper is not initialized, or
+ * -EFAULT if in error state.
+ */
+int xlnx_bridge_register(struct xlnx_bridge *bridge)
+{
+	if (!helper.refcnt)
+		return -EPROBE_DEFER;
+
+	if (helper.error)
+		return -EFAULT;
+
+	mutex_lock(&helper.lock);
+	WARN_ON(!bridge->of_node);
+	bridge->owned = false;
+	xlnx_bridge_debugfs_register(bridge);
+	list_add_tail(&bridge->list, &helper.xlnx_bridges);
+	mutex_unlock(&helper.lock);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(xlnx_bridge_register);
+
+/**
+ * xlnx_bridge_unregister - Unregister the bridge instance
+ * @bridge: Xlnx bridge instance to unregister
+ *
+ * Unregister @bridge. The bridge shouldn't be owned by any client
+ * at this point.
+ */
+void xlnx_bridge_unregister(struct xlnx_bridge *bridge)
+{
+	if (helper.error)
+		return;
+
+	mutex_lock(&helper.lock);
+	WARN_ON(bridge->owned);
+	xlnx_bridge_debugfs_unregister(bridge);
+	list_del(&bridge->list);
+	mutex_unlock(&helper.lock);
+}
+EXPORT_SYMBOL_GPL(xlnx_bridge_unregister);
+
+/*
+ * Internal functions: used by Xlnx DRM
+ */
+
+/**
+ * xlnx_bridge_helper_init - Initialize the bridge helper
+ * @void: No arg
+ *
+ * Initialize the bridge helper or increment the reference count
+ * if already initialized.
+ *
+ * Return: 0 on success, or -EFAULT if in error state.
+ */
+int xlnx_bridge_helper_init(void)
+{
+	if (helper.refcnt++ > 0) {
+		if (helper.error)
+			return -EFAULT;
+		return 0;
+	}
+
+	INIT_LIST_HEAD(&helper.xlnx_bridges);
+	mutex_init(&helper.lock);
+	helper.error = false;
+
+	if (xlnx_bridge_debugfs_init())
+		pr_err("failed to init xlnx bridge debugfs\n");
+
+	return 0;
+}
+
+/**
+ * xlnx_bridge_helper_fini - Release the bridge helper
+ *
+ * Clean up or decrement the reference of the bridge helper.
+ */
+void xlnx_bridge_helper_fini(void)
+{
+	if (--helper.refcnt > 0)
+		return;
+
+	xlnx_bridge_debugfs_fini();
+
+	if (WARN_ON(!list_empty(&helper.xlnx_bridges))) {
+		helper.error = true;
+		pr_err("any further xlnx bridge call will fail\n");
+	}
+
+	mutex_destroy(&helper.lock);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/xlnx/xlnx_bridge.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/xlnx/xlnx_bridge.h
@@ -0,0 +1,178 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx DRM bridge header
+ *
+ *  Copyright (C) 2017 Xilinx, Inc.
+ *
+ *  Author: Hyun Woo Kwon <hyun.kwon@xilinx.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _XLNX_BRIDGE_H_
+#define _XLNX_BRIDGE_H_
+
+struct videomode;
+
+struct xlnx_bridge_debugfs_file;
+
+/**
+ * struct xlnx_bridge - Xilinx bridge device
+ * @list: list node for Xilinx bridge device list
+ * @of_node: OF node for the bridge
+ * @owned: flag if the bridge is owned
+ * @enable: callback to enable the bridge
+ * @disable: callback to disable the bridge
+ * @set_input: callback to set the input
+ * @get_input_fmts: callback to get supported input formats.
+ * @set_output: callback to set the output
+ * @get_output_fmts: callback to get supported output formats.
+ * @set_timing: callback to set timing in connected video timing controller.
+ * @debugfs_file: for debugfs support
+ */
+struct xlnx_bridge {
+	struct list_head list;
+	struct device_node *of_node;
+	bool owned;
+	int (*enable)(struct xlnx_bridge *bridge);
+	void (*disable)(struct xlnx_bridge *bridge);
+	int (*set_input)(struct xlnx_bridge *bridge,
+			 u32 width, u32 height, u32 bus_fmt);
+	int (*get_input_fmts)(struct xlnx_bridge *bridge,
+			      const u32 **fmts, u32 *count);
+	int (*set_output)(struct xlnx_bridge *bridge,
+			  u32 width, u32 height, u32 bus_fmt);
+	int (*get_output_fmts)(struct xlnx_bridge *bridge,
+			       const u32 **fmts, u32 *count);
+	int (*set_timing)(struct xlnx_bridge *bridge, struct videomode *vm);
+	struct xlnx_bridge_debugfs_file *debugfs_file;
+};
+
+#if IS_ENABLED(CONFIG_DRM_XLNX_BRIDGE)
+/*
+ * Helper functions: used within Xlnx DRM
+ */
+
+struct xlnx_bridge_helper;
+
+int xlnx_bridge_helper_init(void);
+void xlnx_bridge_helper_fini(void);
+
+/*
+ * Helper functions: used by client driver
+ */
+
+int xlnx_bridge_enable(struct xlnx_bridge *bridge);
+void xlnx_bridge_disable(struct xlnx_bridge *bridge);
+int xlnx_bridge_set_input(struct xlnx_bridge *bridge,
+			  u32 width, u32 height, u32 bus_fmt);
+int xlnx_bridge_get_input_fmts(struct xlnx_bridge *bridge,
+			       const u32 **fmts, u32 *count);
+int xlnx_bridge_set_output(struct xlnx_bridge *bridge,
+			   u32 width, u32 height, u32 bus_fmt);
+int xlnx_bridge_get_output_fmts(struct xlnx_bridge *bridge,
+				const u32 **fmts, u32 *count);
+int xlnx_bridge_set_timing(struct xlnx_bridge *bridge, struct videomode *vm);
+struct xlnx_bridge *of_xlnx_bridge_get(struct device_node *bridge_np);
+void of_xlnx_bridge_put(struct xlnx_bridge *bridge);
+
+/*
+ * Bridge registration: used by bridge driver
+ */
+
+int xlnx_bridge_register(struct xlnx_bridge *bridge);
+void xlnx_bridge_unregister(struct xlnx_bridge *bridge);
+
+#else /* CONFIG_DRM_XLNX_BRIDGE */
+
+struct xlnx_bridge_helper;
+
+static inline inline int xlnx_bridge_helper_init(void)
+{
+	return 0;
+}
+
+static inline void xlnx_bridge_helper_fini(void)
+{
+}
+
+static inline int xlnx_bridge_enable(struct xlnx_bridge *bridge)
+{
+	if (bridge)
+		return -ENODEV;
+	return 0;
+}
+
+static inline void xlnx_bridge_disable(struct xlnx_bridge *bridge)
+{
+}
+
+static inline int xlnx_bridge_set_input(struct xlnx_bridge *bridge,
+					u32 width, u32 height, u32 bus_fmt)
+{
+	if (bridge)
+		return -ENODEV;
+	return 0;
+}
+
+static inline int xlnx_bridge_get_input_fmts(struct xlnx_bridge *bridge,
+					     const u32 **fmts, u32 *count)
+{
+	if (bridge)
+		return -ENODEV;
+	return 0;
+}
+
+static inline int xlnx_bridge_set_output(struct xlnx_bridge *bridge,
+					 u32 width, u32 height, u32 bus_fmt)
+{
+	if (bridge)
+		return -ENODEV;
+	return 0;
+}
+
+static inline int xlnx_bridge_get_output_fmts(struct xlnx_bridge *bridge,
+					      const u32 **fmts, u32 *count)
+{
+	if (bridge)
+		return -ENODEV;
+	return 0;
+}
+
+static inline int xlnx_bridge_set_timing(struct xlnx_bridge *bridge,
+					 struct videomode *vm)
+{
+	if (bridge)
+		return -ENODEV;
+	return 0;
+}
+
+static inline struct xlnx_bridge *
+of_xlnx_bridge_get(struct device_node *bridge_np)
+{
+	return NULL;
+}
+
+static inline void of_xlnx_bridge_put(struct xlnx_bridge *bridge)
+{
+}
+
+static inline int xlnx_bridge_register(struct xlnx_bridge *bridge)
+{
+	return 0;
+}
+
+static inline void xlnx_bridge_unregister(struct xlnx_bridge *bridge)
+{
+}
+
+#endif /* CONFIG_DRM_XLNX_BRIDGE */
+
+#endif /* _XLNX_BRIDGE_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/xlnx/xlnx_crtc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/xlnx/xlnx_crtc.c
@@ -0,0 +1,206 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx DRM crtc driver
+ *
+ *  Copyright (C) 2017 - 2018 Xilinx, Inc.
+ *
+ *  Author: Hyun Woo Kwon <hyun.kwon@xilinx.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <drm/drmP.h>
+
+#include <linux/list.h>
+
+#include "xlnx_crtc.h"
+#include "xlnx_drv.h"
+
+/*
+ * Overview
+ * --------
+ *
+ * The Xilinx CRTC layer is to enable the custom interface to CRTC drivers.
+ * The interface is used by Xilinx DRM driver where it needs CRTC
+ * functionailty. CRTC drivers should attach the desired callbacks
+ * to struct xlnx_crtc and register the xlnx_crtc with correcsponding
+ * drm_device. It's highly recommended CRTC drivers register all callbacks
+ * even though many of them are optional.
+ * The CRTC helper simply walks through the registered CRTC device,
+ * and call the callbacks.
+ */
+
+/**
+ * struct xlnx_crtc_helper - Xilinx CRTC helper
+ * @xlnx_crtcs: list of Xilinx CRTC devices
+ * @lock: lock to protect @xlnx_crtcs
+ * @drm: back pointer to DRM core
+ */
+struct xlnx_crtc_helper {
+	struct list_head xlnx_crtcs;
+	struct mutex lock; /* lock for @xlnx_crtcs */
+	struct drm_device *drm;
+};
+
+#define XLNX_CRTC_MAX_HEIGHT_WIDTH	INT_MAX
+
+unsigned int xlnx_crtc_helper_get_align(struct xlnx_crtc_helper *helper)
+{
+	struct xlnx_crtc *crtc;
+	unsigned int align = 1, tmp;
+
+	list_for_each_entry(crtc, &helper->xlnx_crtcs, list) {
+		if (crtc->get_align) {
+			tmp = crtc->get_align(crtc);
+			align = ALIGN(align, tmp);
+		}
+	}
+
+	return align;
+}
+
+u64 xlnx_crtc_helper_get_dma_mask(struct xlnx_crtc_helper *helper)
+{
+	struct xlnx_crtc *crtc;
+	u64 mask = DMA_BIT_MASK(sizeof(dma_addr_t) * 8), tmp;
+
+	list_for_each_entry(crtc, &helper->xlnx_crtcs, list) {
+		if (crtc->get_dma_mask) {
+			tmp = crtc->get_dma_mask(crtc);
+			mask = min(mask, tmp);
+		}
+	}
+
+	return mask;
+}
+
+int xlnx_crtc_helper_get_max_width(struct xlnx_crtc_helper *helper)
+{
+	struct xlnx_crtc *crtc;
+	int width = XLNX_CRTC_MAX_HEIGHT_WIDTH, tmp;
+
+	list_for_each_entry(crtc, &helper->xlnx_crtcs, list) {
+		if (crtc->get_max_width) {
+			tmp = crtc->get_max_width(crtc);
+			width = min(width, tmp);
+		}
+	}
+
+	return width;
+}
+
+int xlnx_crtc_helper_get_max_height(struct xlnx_crtc_helper *helper)
+{
+	struct xlnx_crtc *crtc;
+	int height = XLNX_CRTC_MAX_HEIGHT_WIDTH, tmp;
+
+	list_for_each_entry(crtc, &helper->xlnx_crtcs, list) {
+		if (crtc->get_max_height) {
+			tmp = crtc->get_max_height(crtc);
+			height = min(height, tmp);
+		}
+	}
+
+	return height;
+}
+
+uint32_t xlnx_crtc_helper_get_format(struct xlnx_crtc_helper *helper)
+{
+	struct xlnx_crtc *crtc;
+	u32 format = 0, tmp;
+
+	list_for_each_entry(crtc, &helper->xlnx_crtcs, list) {
+		if (crtc->get_format) {
+			tmp = crtc->get_format(crtc);
+			if (format && format != tmp)
+				return 0;
+			format = tmp;
+		}
+	}
+
+	return format;
+}
+
+u32 xlnx_crtc_helper_get_cursor_width(struct xlnx_crtc_helper *helper)
+{
+	struct xlnx_crtc *crtc;
+	u32 width = XLNX_CRTC_MAX_HEIGHT_WIDTH, tmp;
+
+	list_for_each_entry(crtc, &helper->xlnx_crtcs, list) {
+		if (crtc->get_cursor_width) {
+			tmp = crtc->get_cursor_width(crtc);
+			width = min(width, tmp);
+		}
+	}
+
+	return width;
+}
+
+u32 xlnx_crtc_helper_get_cursor_height(struct xlnx_crtc_helper *helper)
+{
+	struct xlnx_crtc *crtc;
+	u32 height = XLNX_CRTC_MAX_HEIGHT_WIDTH, tmp;
+
+	list_for_each_entry(crtc, &helper->xlnx_crtcs, list) {
+		if (crtc->get_cursor_height) {
+			tmp = crtc->get_cursor_height(crtc);
+			height = min(height, tmp);
+		}
+	}
+
+	return height;
+}
+struct xlnx_crtc_helper *xlnx_crtc_helper_init(struct drm_device *drm)
+{
+	struct xlnx_crtc_helper *helper;
+
+	helper = devm_kzalloc(drm->dev, sizeof(*helper), GFP_KERNEL);
+	if (!helper)
+		return ERR_PTR(-ENOMEM);
+
+	INIT_LIST_HEAD(&helper->xlnx_crtcs);
+	mutex_init(&helper->lock);
+	helper->drm = drm;
+
+	return helper;
+}
+
+void xlnx_crtc_helper_fini(struct drm_device *drm,
+			   struct xlnx_crtc_helper *helper)
+{
+	if (WARN_ON(helper->drm != drm))
+		return;
+
+	if (WARN_ON(!list_empty(&helper->xlnx_crtcs)))
+		return;
+
+	mutex_destroy(&helper->lock);
+	devm_kfree(drm->dev, helper);
+}
+
+void xlnx_crtc_register(struct drm_device *drm, struct xlnx_crtc *crtc)
+{
+	struct xlnx_crtc_helper *helper = xlnx_get_crtc_helper(drm);
+
+	mutex_lock(&helper->lock);
+	list_add_tail(&crtc->list, &helper->xlnx_crtcs);
+	mutex_unlock(&helper->lock);
+}
+EXPORT_SYMBOL_GPL(xlnx_crtc_register);
+
+void xlnx_crtc_unregister(struct drm_device *drm, struct xlnx_crtc *crtc)
+{
+	struct xlnx_crtc_helper *helper = xlnx_get_crtc_helper(drm);
+
+	mutex_lock(&helper->lock);
+	list_del(&crtc->list);
+	mutex_unlock(&helper->lock);
+}
+EXPORT_SYMBOL_GPL(xlnx_crtc_unregister);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/xlnx/xlnx_crtc.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/xlnx/xlnx_crtc.h
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx DRM crtc header
+ *
+ *  Copyright (C) 2017 - 2018 Xilinx, Inc.
+ *
+ *  Author: Hyun Woo Kwon <hyun.kwon@xilinx.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _XLNX_CRTC_H_
+#define _XLNX_CRTC_H_
+
+/**
+ * struct xlnx_crtc - Xilinx CRTC device
+ * @crtc: DRM CRTC device
+ * @list: list node for Xilinx CRTC device list
+ * @get_align: Get the alignment requirement of CRTC device
+ * @get_dma_mask: Get the dma mask of CRTC device
+ * @get_max_width: Get the maximum supported width
+ * @get_max_height: Get the maximum supported height
+ * @get_format: Get the current format of CRTC device
+ * @get_cursor_width: Get the cursor width
+ * @get_cursor_height: Get the cursor height
+ */
+struct xlnx_crtc {
+	struct drm_crtc crtc;
+	struct list_head list;
+	unsigned int (*get_align)(struct xlnx_crtc *crtc);
+	u64 (*get_dma_mask)(struct xlnx_crtc *crtc);
+	int (*get_max_width)(struct xlnx_crtc *crtc);
+	int (*get_max_height)(struct xlnx_crtc *crtc);
+	uint32_t (*get_format)(struct xlnx_crtc *crtc);
+	uint32_t (*get_cursor_width)(struct xlnx_crtc *crtc);
+	uint32_t (*get_cursor_height)(struct xlnx_crtc *crtc);
+};
+
+/*
+ * Helper functions: used within Xlnx DRM
+ */
+
+struct xlnx_crtc_helper;
+
+unsigned int xlnx_crtc_helper_get_align(struct xlnx_crtc_helper *helper);
+u64 xlnx_crtc_helper_get_dma_mask(struct xlnx_crtc_helper *helper);
+int xlnx_crtc_helper_get_max_width(struct xlnx_crtc_helper *helper);
+int xlnx_crtc_helper_get_max_height(struct xlnx_crtc_helper *helper);
+uint32_t xlnx_crtc_helper_get_format(struct xlnx_crtc_helper *helper);
+u32 xlnx_crtc_helper_get_cursor_width(struct xlnx_crtc_helper *helper);
+u32 xlnx_crtc_helper_get_cursor_height(struct xlnx_crtc_helper *helper);
+
+struct xlnx_crtc_helper *xlnx_crtc_helper_init(struct drm_device *drm);
+void xlnx_crtc_helper_fini(struct drm_device *drm,
+			   struct xlnx_crtc_helper *helper);
+
+/*
+ * CRTC registration: used by other sub-driver modules
+ */
+
+static inline struct xlnx_crtc *to_xlnx_crtc(struct drm_crtc *crtc)
+{
+	return container_of(crtc, struct xlnx_crtc, crtc);
+}
+
+void xlnx_crtc_register(struct drm_device *drm, struct xlnx_crtc *crtc);
+void xlnx_crtc_unregister(struct drm_device *drm, struct xlnx_crtc *crtc);
+
+#endif /* _XLNX_CRTC_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/xlnx/xlnx_csc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/xlnx/xlnx_csc.c
@@ -0,0 +1,571 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * VPSS CSC DRM bridge driver
+ *
+ * Copyright (C) 2017-2018 Xilinx, Inc.
+ *
+ * Author: Venkateshwar rao G <vgannava@xilinx.com>
+ */
+
+/*
+ * Overview:
+ * This experimentatl driver works as a bridge driver and
+ * reused the code from V4L2.
+ * TODO:
+ * Need to implement in a modular approach to share driver code between
+ * V4L2 and DRM frameworks.
+ * Should be integrated with plane
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <uapi/linux/media-bus-format.h>
+
+#include "xlnx_bridge.h"
+
+/* Register offset */
+#define XV_CSC_AP_CTRL			(0x000)
+#define XV_CSC_INVIDEOFORMAT		(0x010)
+#define XV_CSC_OUTVIDEOFORMAT		(0x018)
+#define XV_CSC_WIDTH			(0x020)
+#define XV_CSC_HEIGHT			(0x028)
+#define XV_CSC_K11			(0x050)
+#define XV_CSC_K12			(0x058)
+#define XV_CSC_K13			(0x060)
+#define XV_CSC_K21			(0x068)
+#define XV_CSC_K22			(0x070)
+#define XV_CSC_K23			(0x078)
+#define XV_CSC_K31			(0x080)
+#define XV_CSC_K32			(0x088)
+#define XV_CSC_K33			(0x090)
+#define XV_CSC_ROFFSET			(0x098)
+#define XV_CSC_GOFFSET			(0x0a0)
+#define XV_CSC_BOFFSET			(0x0a8)
+#define XV_CSC_CLAMPMIN			(0x0b0)
+#define XV_CSC_CLIPMAX			(0x0b8)
+#define XV_CSC_SCALE_FACTOR		(4096)
+#define XV_CSC_DIVISOR			(10000)
+/* Streaming Macros */
+#define XCSC_CLAMP_MIN_ZERO		(0)
+#define XCSC_AP_START			BIT(0)
+#define XCSC_AP_AUTO_RESTART		BIT(7)
+#define XCSC_STREAM_ON			(XCSC_AP_START | XCSC_AP_AUTO_RESTART)
+#define XCSC_STREAM_OFF			(0)
+/* GPIO Reset Assert/De-assert */
+#define XCSC_RESET_ASSERT		(1)
+#define XCSC_RESET_DEASSERT		(0)
+
+#define XCSC_MIN_WIDTH			(64)
+#define XCSC_MAX_WIDTH			(8192)
+#define XCSC_MIN_HEIGHT			(64)
+#define XCSC_MAX_HEIGHT			(4320)
+
+static const u32 xilinx_csc_video_fmts[] = {
+	MEDIA_BUS_FMT_RGB888_1X24,
+	MEDIA_BUS_FMT_VUY8_1X24,
+	MEDIA_BUS_FMT_UYVY8_1X16,
+	MEDIA_BUS_FMT_VYYUYY8_1X24,
+};
+
+/* vpss_csc_color_fmt - Color format type */
+enum vpss_csc_color_fmt {
+	XVIDC_CSF_RGB = 0,
+	XVIDC_CSF_YCRCB_444,
+	XVIDC_CSF_YCRCB_422,
+	XVIDC_CSF_YCRCB_420,
+};
+
+/**
+ * struct xilinx_csc - Core configuration of csc device structure
+ * @base: pointer to register base address
+ * @dev: device structure
+ * @bridge: xilinx bridge
+ * @cft_in: input color format
+ * @cft_out: output color format
+ * @color_depth: color depth
+ * @k_hw: array of hardware values
+ * @clip_max: clipping maximum value
+ * @width: width of the video
+ * @height: height of video
+ * @max_width: maximum number of pixels in a line
+ * @max_height: maximum number of lines per frame
+ * @rst_gpio: Handle to GPIO specifier to assert/de-assert the reset line
+ * @aclk: IP clock struct
+ */
+struct xilinx_csc {
+	void __iomem *base;
+	struct device *dev;
+	struct xlnx_bridge bridge;
+	enum vpss_csc_color_fmt cft_in;
+	enum vpss_csc_color_fmt cft_out;
+	u32 color_depth;
+	s32 k_hw[3][4];
+	s32 clip_max;
+	u32 width;
+	u32 height;
+	u32 max_width;
+	u32 max_height;
+	struct gpio_desc *rst_gpio;
+	struct clk *aclk;
+};
+
+static inline void xilinx_csc_write(void __iomem *base, u32 offset, u32 val)
+{
+	writel(val, base + offset);
+}
+
+static inline u32 xilinx_csc_read(void __iomem *base, u32 offset)
+{
+	return readl(base + offset);
+}
+
+/**
+ * bridge_to_layer - Gets the parent structure
+ * @bridge: pointer to the member.
+ *
+ * Return: parent structure pointer
+ */
+static inline struct xilinx_csc *bridge_to_layer(struct xlnx_bridge *bridge)
+{
+	return container_of(bridge, struct xilinx_csc, bridge);
+}
+
+static void xilinx_csc_write_rgb_3x3(struct xilinx_csc *csc)
+{
+	xilinx_csc_write(csc->base, XV_CSC_K11, csc->k_hw[0][0]);
+	xilinx_csc_write(csc->base, XV_CSC_K12, csc->k_hw[0][1]);
+	xilinx_csc_write(csc->base, XV_CSC_K13, csc->k_hw[0][2]);
+	xilinx_csc_write(csc->base, XV_CSC_K21, csc->k_hw[1][0]);
+	xilinx_csc_write(csc->base, XV_CSC_K22, csc->k_hw[1][1]);
+	xilinx_csc_write(csc->base, XV_CSC_K23, csc->k_hw[1][2]);
+	xilinx_csc_write(csc->base, XV_CSC_K31, csc->k_hw[2][0]);
+	xilinx_csc_write(csc->base, XV_CSC_K32, csc->k_hw[2][1]);
+	xilinx_csc_write(csc->base, XV_CSC_K33, csc->k_hw[2][2]);
+}
+
+static void xilinx_csc_write_rgb_offset(struct xilinx_csc *csc)
+{
+	xilinx_csc_write(csc->base, XV_CSC_ROFFSET, csc->k_hw[0][3]);
+	xilinx_csc_write(csc->base, XV_CSC_GOFFSET, csc->k_hw[1][3]);
+	xilinx_csc_write(csc->base, XV_CSC_BOFFSET, csc->k_hw[2][3]);
+}
+
+static void xilinx_csc_write_coeff(struct xilinx_csc *csc)
+{
+	xilinx_csc_write_rgb_3x3(csc);
+	xilinx_csc_write_rgb_offset(csc);
+}
+
+static void xcsc_set_default_state(struct xilinx_csc *csc)
+{
+	csc->cft_in = XVIDC_CSF_YCRCB_422;
+	csc->cft_out = XVIDC_CSF_YCRCB_422;
+
+	/* This represents an identity matrix mutliped by 2^12 */
+	csc->k_hw[0][0] = XV_CSC_SCALE_FACTOR;
+	csc->k_hw[0][1] = 0;
+	csc->k_hw[0][2] = 0;
+	csc->k_hw[1][0] = 0;
+	csc->k_hw[1][1] = XV_CSC_SCALE_FACTOR;
+	csc->k_hw[1][2] = 0;
+	csc->k_hw[2][0] = 0;
+	csc->k_hw[2][1] = 0;
+	csc->k_hw[2][2] = XV_CSC_SCALE_FACTOR;
+	csc->k_hw[0][3] = 0;
+	csc->k_hw[1][3] = 0;
+	csc->k_hw[2][3] = 0;
+	csc->clip_max = ((1 << csc->color_depth) - 1);
+	xilinx_csc_write(csc->base, XV_CSC_INVIDEOFORMAT, csc->cft_in);
+	xilinx_csc_write(csc->base, XV_CSC_OUTVIDEOFORMAT, csc->cft_out);
+	xilinx_csc_write_coeff(csc);
+	xilinx_csc_write(csc->base, XV_CSC_CLIPMAX, csc->clip_max);
+	xilinx_csc_write(csc->base, XV_CSC_CLAMPMIN, XCSC_CLAMP_MIN_ZERO);
+}
+
+static void xcsc_ycrcb_to_rgb(struct xilinx_csc *csc, s32 *clip_max)
+{
+	u16 bpc_scale = (1 << (csc->color_depth - 8));
+	/*
+	 * See http://graficaobscura.com/matrix/index.html for
+	 * how these numbers are derived. The VPSS CSC IP is
+	 * derived from this Matrix style algorithm. And the
+	 * 'magic' numbers here are derived from the algorithm.
+	 *
+	 * XV_CSC_DIVISOR is used to help with floating constants
+	 * while performing multiplicative operations.
+	 *
+	 * Coefficients valid only for BT 709
+	 */
+	csc->k_hw[0][0] = 11644 * XV_CSC_SCALE_FACTOR / XV_CSC_DIVISOR;
+	csc->k_hw[0][1] = 0;
+	csc->k_hw[0][2] = 17927 * XV_CSC_SCALE_FACTOR / XV_CSC_DIVISOR;
+	csc->k_hw[1][0] = 11644 * XV_CSC_SCALE_FACTOR / XV_CSC_DIVISOR;
+	csc->k_hw[1][1] = -2132 * XV_CSC_SCALE_FACTOR / XV_CSC_DIVISOR;
+	csc->k_hw[1][2] = -5329 * XV_CSC_SCALE_FACTOR / XV_CSC_DIVISOR;
+	csc->k_hw[2][0] = 11644 * XV_CSC_SCALE_FACTOR / XV_CSC_DIVISOR;
+	csc->k_hw[2][1] = 21124 * XV_CSC_SCALE_FACTOR / XV_CSC_DIVISOR;
+	csc->k_hw[2][2] = 0;
+	csc->k_hw[0][3] = -248 * bpc_scale;
+	csc->k_hw[1][3] = 77 * bpc_scale;
+	csc->k_hw[2][3] = -289 * bpc_scale;
+	*clip_max = ((1 << csc->color_depth) - 1);
+}
+
+static void xcsc_rgb_to_ycrcb(struct xilinx_csc *csc, s32 *clip_max)
+{
+	u16 bpc_scale = (1 << (csc->color_depth - 8));
+	/*
+	 * See http://graficaobscura.com/matrix/index.html for
+	 * how these numbers are derived. The VPSS CSC
+	 * derived from this Matrix style algorithm. And the
+	 * 'magic' numbers here are derived from the algorithm.
+	 *
+	 * XV_CSC_DIVISOR is used to help with floating constants
+	 * while performing multiplicative operations.
+	 *
+	 * Coefficients valid only for BT 709
+	 */
+	csc->k_hw[0][0] = 1826 * XV_CSC_SCALE_FACTOR / XV_CSC_DIVISOR;
+	csc->k_hw[0][1] = 6142 * XV_CSC_SCALE_FACTOR / XV_CSC_DIVISOR;
+	csc->k_hw[0][2] = 620 * XV_CSC_SCALE_FACTOR / XV_CSC_DIVISOR;
+	csc->k_hw[1][0] = -1006 * XV_CSC_SCALE_FACTOR / XV_CSC_DIVISOR;
+	csc->k_hw[1][1] = -3386 * XV_CSC_SCALE_FACTOR / XV_CSC_DIVISOR;
+	csc->k_hw[1][2] = 4392 * XV_CSC_SCALE_FACTOR / XV_CSC_DIVISOR;
+	csc->k_hw[2][0] = 4392 * XV_CSC_SCALE_FACTOR / XV_CSC_DIVISOR;
+	csc->k_hw[2][1] = -3989 * XV_CSC_SCALE_FACTOR / XV_CSC_DIVISOR;
+	csc->k_hw[2][2] = -403 * XV_CSC_SCALE_FACTOR / XV_CSC_DIVISOR;
+	csc->k_hw[0][3] = 16 * bpc_scale;
+	csc->k_hw[1][3] = 128 * bpc_scale;
+	csc->k_hw[2][3] = 128 * bpc_scale;
+	*clip_max = ((1 << csc->color_depth) - 1);
+}
+
+/**
+ * xcsc_set_coeff- Sets the coefficients
+ * @csc: Pointer to csc device structure
+ *
+ * This function set the coefficients
+ *
+ */
+static void xcsc_set_coeff(struct xilinx_csc *csc)
+{
+	xilinx_csc_write(csc->base, XV_CSC_INVIDEOFORMAT, csc->cft_in);
+	xilinx_csc_write(csc->base, XV_CSC_OUTVIDEOFORMAT, csc->cft_out);
+	xilinx_csc_write_coeff(csc);
+	xilinx_csc_write(csc->base, XV_CSC_CLIPMAX, csc->clip_max);
+	xilinx_csc_write(csc->base, XV_CSC_CLAMPMIN, XCSC_CLAMP_MIN_ZERO);
+}
+
+/**
+ * xilinx_csc_bridge_enable - enabes csc core
+ * @bridge: bridge instance
+ *
+ * This function enables the csc core
+ *
+ * Return: 0 on success.
+ *
+ */
+static int xilinx_csc_bridge_enable(struct xlnx_bridge *bridge)
+{
+	struct xilinx_csc *csc = bridge_to_layer(bridge);
+
+	xilinx_csc_write(csc->base, XV_CSC_AP_CTRL, XCSC_STREAM_ON);
+
+	return 0;
+}
+
+/**
+ * xilinx_csc_bridge_disable - disables csc core
+ * @bridge: bridge instance
+ *
+ * This function disables the csc core
+ */
+static void xilinx_csc_bridge_disable(struct xlnx_bridge *bridge)
+{
+	struct xilinx_csc *csc = bridge_to_layer(bridge);
+
+	xilinx_csc_write(csc->base, XV_CSC_AP_CTRL, XCSC_STREAM_OFF);
+	/* Reset the Global IP Reset through GPIO */
+	gpiod_set_value_cansleep(csc->rst_gpio, XCSC_RESET_ASSERT);
+	gpiod_set_value_cansleep(csc->rst_gpio, XCSC_RESET_DEASSERT);
+}
+
+/**
+ * xilinx_csc_bridge_set_input - Sets the input parameters of csc
+ * @bridge: bridge instance
+ * @width: width of video
+ * @height: height of video
+ * @bus_fmt: video bus format
+ *
+ * This function sets the input parameters of csc
+ * Return: 0 on success. -EINVAL for invalid parameters.
+ */
+static int xilinx_csc_bridge_set_input(struct xlnx_bridge *bridge, u32 width,
+				       u32 height, u32 bus_fmt)
+{
+	struct xilinx_csc *csc = bridge_to_layer(bridge);
+
+	xcsc_set_default_state(csc);
+
+	if (height > csc->max_height || height < XCSC_MIN_HEIGHT)
+		return -EINVAL;
+
+	if (width > csc->max_width || width < XCSC_MIN_WIDTH)
+		return -EINVAL;
+
+	csc->height = height;
+	csc->width = width;
+
+	switch (bus_fmt) {
+	case MEDIA_BUS_FMT_RGB888_1X24:
+		csc->cft_in = XVIDC_CSF_RGB;
+		break;
+	case MEDIA_BUS_FMT_VUY8_1X24:
+		csc->cft_in = XVIDC_CSF_YCRCB_444;
+		break;
+	case MEDIA_BUS_FMT_UYVY8_1X16:
+		csc->cft_in = XVIDC_CSF_YCRCB_422;
+		break;
+	case MEDIA_BUS_FMT_VYYUYY8_1X24:
+		csc->cft_in = XVIDC_CSF_YCRCB_420;
+		break;
+	default:
+		dev_dbg(csc->dev, "unsupported input video format\n");
+		return -EINVAL;
+	}
+
+	xilinx_csc_write(csc->base, XV_CSC_WIDTH, width);
+	xilinx_csc_write(csc->base, XV_CSC_HEIGHT, height);
+
+	return 0;
+}
+
+/**
+ * xilinx_csc_bridge_get_input_fmts - input formats supported by csc
+ * @bridge: bridge instance
+ * @fmts: Pointer to be updated with formats information
+ * @count: count of video bus formats
+ *
+ * This function provides the input video formats information csc
+ * Return: 0 on success.
+ */
+static int xilinx_csc_bridge_get_input_fmts(struct xlnx_bridge *bridge,
+					    const u32 **fmts, u32 *count)
+{
+	*fmts = xilinx_csc_video_fmts;
+	*count = ARRAY_SIZE(xilinx_csc_video_fmts);
+
+	return 0;
+}
+
+/**
+ * xilinx_csc_bridge_set_output - Sets the output parameters of csc
+ * @bridge: bridge instance
+ * @width: width of video
+ * @height: height of video
+ * @bus_fmt: video bus format
+ *
+ * This function sets the output parameters of csc
+ * Return: 0 on success. -EINVAL for invalid parameters.
+ */
+static int xilinx_csc_bridge_set_output(struct xlnx_bridge *bridge, u32 width,
+					u32 height, u32 bus_fmt)
+{
+	struct xilinx_csc *csc = bridge_to_layer(bridge);
+
+	if (width != csc->width || height != csc->height)
+		return -EINVAL;
+
+	switch (bus_fmt) {
+	case MEDIA_BUS_FMT_RGB888_1X24:
+		csc->cft_out = XVIDC_CSF_RGB;
+		dev_dbg(csc->dev, "Media Format Out : RGB");
+		if (csc->cft_in != MEDIA_BUS_FMT_RBG888_1X24)
+			xcsc_ycrcb_to_rgb(csc, &csc->clip_max);
+		break;
+	case MEDIA_BUS_FMT_VUY8_1X24:
+		csc->cft_out = XVIDC_CSF_YCRCB_444;
+		dev_dbg(csc->dev, "Media Format Out : YUV 444");
+		if (csc->cft_in == MEDIA_BUS_FMT_RBG888_1X24)
+			xcsc_rgb_to_ycrcb(csc, &csc->clip_max);
+		break;
+	case MEDIA_BUS_FMT_UYVY8_1X16:
+		csc->cft_out = XVIDC_CSF_YCRCB_422;
+		dev_dbg(csc->dev, "Media Format Out : YUV 422");
+		if (csc->cft_in == MEDIA_BUS_FMT_RBG888_1X24)
+			xcsc_rgb_to_ycrcb(csc, &csc->clip_max);
+		break;
+	case MEDIA_BUS_FMT_VYYUYY8_1X24:
+		csc->cft_out = XVIDC_CSF_YCRCB_420;
+		dev_dbg(csc->dev, "Media Format Out : YUV 420");
+		if (csc->cft_in == MEDIA_BUS_FMT_RBG888_1X24)
+			xcsc_rgb_to_ycrcb(csc, &csc->clip_max);
+		break;
+	default:
+		dev_info(csc->dev, "unsupported output video format\n");
+		return -EINVAL;
+	}
+	xcsc_set_coeff(csc);
+
+	return 0;
+}
+
+/**
+ * xilinx_csc_bridge_get_output_fmts - output formats supported by csc
+ * @bridge: bridge instance
+ * @fmts: Pointer to be updated with formats information
+ * @count: count of video bus formats
+ *
+ * This function provides the output video formats information csc
+ * Return: 0 on success.
+ */
+static int xilinx_csc_bridge_get_output_fmts(struct xlnx_bridge *bridge,
+					     const u32 **fmts, u32 *count)
+{
+	*fmts = xilinx_csc_video_fmts;
+	*count = ARRAY_SIZE(xilinx_csc_video_fmts);
+	return 0;
+}
+
+static int xcsc_parse_of(struct xilinx_csc *csc)
+{
+	int ret;
+	struct device_node *node = csc->dev->of_node;
+
+	csc->aclk = devm_clk_get(csc->dev, NULL);
+	if (IS_ERR(csc->aclk)) {
+		ret = PTR_ERR(csc->aclk);
+		dev_err(csc->dev, "failed to get aclk %d\n", ret);
+		return ret;
+	}
+
+	ret = of_property_read_u32(node, "xlnx,video-width",
+				   &csc->color_depth);
+	if (ret < 0) {
+		dev_info(csc->dev, "video width not present in DT\n");
+		return ret;
+	}
+	if (csc->color_depth != 8 && csc->color_depth != 10 &&
+	    csc->color_depth != 12 && csc->color_depth != 16) {
+		dev_err(csc->dev, "Invalid video width in DT\n");
+		return -EINVAL;
+	}
+	/* Reset GPIO */
+	csc->rst_gpio = devm_gpiod_get(csc->dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(csc->rst_gpio)) {
+		if (PTR_ERR(csc->rst_gpio) != -EPROBE_DEFER)
+			dev_err(csc->dev, "Reset GPIO not setup in DT");
+		return PTR_ERR(csc->rst_gpio);
+	}
+
+	ret = of_property_read_u32(node, "xlnx,max-height", &csc->max_height);
+	if (ret < 0) {
+		dev_err(csc->dev, "xlnx,max-height is missing!");
+		return -EINVAL;
+	} else if (csc->max_height > XCSC_MAX_HEIGHT ||
+		   csc->max_height < XCSC_MIN_HEIGHT) {
+		dev_err(csc->dev, "Invalid height in dt");
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32(node, "xlnx,max-width", &csc->max_width);
+	if (ret < 0) {
+		dev_err(csc->dev, "xlnx,max-width is missing!");
+		return -EINVAL;
+	} else if (csc->max_width > XCSC_MAX_WIDTH ||
+		   csc->max_width < XCSC_MIN_WIDTH) {
+		dev_err(csc->dev, "Invalid width in dt");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int xilinx_csc_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct xilinx_csc *csc;
+	int ret;
+
+	csc = devm_kzalloc(dev, sizeof(*csc), GFP_KERNEL);
+	if (!csc)
+		return -ENOMEM;
+
+	csc->dev = dev;
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	csc->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(csc->base))
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, csc);
+	ret = xcsc_parse_of(csc);
+	if (ret < 0)
+		return ret;
+
+	ret = clk_prepare_enable(csc->aclk);
+	if (ret) {
+		dev_err(csc->dev, "failed to enable clock %d\n", ret);
+		return ret;
+	}
+
+	gpiod_set_value_cansleep(csc->rst_gpio, XCSC_RESET_DEASSERT);
+	csc->bridge.enable = &xilinx_csc_bridge_enable;
+	csc->bridge.disable = &xilinx_csc_bridge_disable;
+	csc->bridge.set_input = &xilinx_csc_bridge_set_input;
+	csc->bridge.get_input_fmts = &xilinx_csc_bridge_get_input_fmts;
+	csc->bridge.set_output = &xilinx_csc_bridge_set_output;
+	csc->bridge.get_output_fmts = &xilinx_csc_bridge_get_output_fmts;
+	csc->bridge.of_node = dev->of_node;
+
+	ret = xlnx_bridge_register(&csc->bridge);
+	if (ret) {
+		dev_info(csc->dev, "Bridge registration failed\n");
+		goto err_clk;
+	}
+
+	dev_info(csc->dev, "Xilinx VPSS CSC DRM experimental driver probed\n");
+
+	return 0;
+
+err_clk:
+	clk_disable_unprepare(csc->aclk);
+	return ret;
+}
+
+static int xilinx_csc_remove(struct platform_device *pdev)
+{
+	struct xilinx_csc *csc = platform_get_drvdata(pdev);
+
+	xlnx_bridge_unregister(&csc->bridge);
+	clk_disable_unprepare(csc->aclk);
+
+	return 0;
+}
+
+static const struct of_device_id xilinx_csc_of_match[] = {
+	{ .compatible = "xlnx,vpss-csc"},
+	{ }
+};
+MODULE_DEVICE_TABLE(of, xilinx_csc_of_match);
+
+static struct platform_driver csc_bridge_driver = {
+	.probe = xilinx_csc_probe,
+	.remove = xilinx_csc_remove,
+	.driver = {
+		.name = "xlnx,csc-bridge",
+		.of_match_table = xilinx_csc_of_match,
+	},
+};
+
+module_platform_driver(csc_bridge_driver);
+
+MODULE_AUTHOR("Venkateshwar Rao <vgannava@xilinx.com>");
+MODULE_DESCRIPTION("Xilinx FPGA CSC Bridge Driver");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/xlnx/xlnx_dptx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/xlnx/xlnx_dptx.c
@@ -0,0 +1,2118 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx FPGA DisplayPort TX Subsystem Driver
+ *
+ *  Copyright (C) 2020 Xilinx, Inc.
+ *
+ * Author: Rajesh Gugulothu <gugulothu.rajesh@xilinx.com>
+ *	 : Venkateshwar Rao G <vgannava.xilinx.com>
+ *
+ */
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/of_address.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/phy/phy.h>
+#include <linux/phy/phy-dp.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_connector.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_dp_helper.h>
+#include <drm/drm_of.h>
+#include <drm/drm_probe_helper.h>
+
+/* Link configuration registers */
+#define XDPTX_LINKBW_SET_REG			0x0
+#define XDPTX_LANECNT_SET_REG			0x4
+#define XDPTX_EFRAME_EN_REG			0x8
+#define XDPTX_TRNGPAT_SET_REG			0xc
+#define XDPTX_SCRAMBLING_DIS_REG		0x14
+#define XDPTX_DOWNSPREAD_CTL_REG		0x18
+
+/* DPTX Core enable registers */
+#define XDPTX_ENABLE_REG			0x80
+#define XDPTX_MAINSTRM_ENABLE_REG		0x84
+
+/* AUX channel interface registers */
+#define XDPTX_AUXCMD_REG			0x100
+#define XDPTX_AUX_WRITEFIFO_REG			0x104
+#define XDPTX_AUX_ADDR_REG			0x108
+#define XDPTX_AUXCMD_ADDRONLY_MASK		BIT(12)
+#define XDPTX_AUXCMD_SHIFT			0x8
+#define XDPTX_AUXCMD_BYTES_SHIFT		0x0
+#define XDPTX_AUX_READ_BIT				0x1
+
+#define XDPTX_CLKDIV_REG			0x10c
+#define XDPTX_CLKDIV_MHZ			1000000
+#define XDPTX_CLKDIV_AUXFILTER_SHIFT		0x8
+
+#define XDPTX_INTR_SIGSTATE_REG			0x130
+#define XDPTX_INTR_SIGHPDSTATE			BIT(0)
+#define XDPTX_INTR_SIGREQSTATE			BIT(1)
+#define XDPTX_INTR_SIGRPLYSTATE			BIT(2)
+#define XDPTX_INTR_RPLYTIMEOUT			BIT(3)
+
+#define XDPTX_AUXREPLY_DATA_REG			0x134
+#define XDPTX_AUXREPLY_CODE_REG			0x138
+#define XDPTX_AUXREPLYCODE_AUXACK_MASK		(0)
+#define XDPTX_AUXREPLYCODE_I2CACK_MASK		(0)
+
+#define XDPTX_AUXREPLY_DATACNT_REG		0x148
+#define XDPTX_AUXREPLY_DATACNT_MASK		GENMASK(7, 0)
+#define XDPTX_INTR_STATUS_REG			0x140
+#define XDPTX_INTR_MASK_REG			0x144
+#define XDPTX_INTR_HPDEVENT_MASK		BIT(1)
+#define XDPTX_INTR_HPDPULSE_MASK		BIT(4)
+#define XDPTX_INTR_CHBUFUNDFW_MASK		GENMASK(21, 16)
+#define XDPTX_INTR_CHBUFOVFW_MASK		GENMASK(27, 22)
+#define XDPTX_HPD_DURATION_REG			0x150
+
+/* Main stream attribute registers */
+#define XDPTX_MAINSTRM_HTOTAL_REG		0x180
+#define XDPTX_MAINSTRM_VTOTAL_REG		0x184
+#define XDPTX_MAINSTRM_POL_REG			0x188
+#define XDPTX_MAINSTRM_POLHSYNC_SHIFT		0x0
+#define XDPTX_MAINSTRM_POLVSYNC_SHIFT		0x1
+#define XDPTX_MAINSTRM_HSWIDTH_REG		0x18c
+#define XDPTX_MAINSTRM_VSWIDTH_REG		0x190
+#define XDPTX_MAINSTRM_HRES_REG			0x194
+#define XDPTX_MAINSTRM_VRES_REG			0x198
+#define XDPTX_MAINSTRM_HSTART_REG		0x19c
+#define XDPTX_MAINSTRM_VSTART_REG		0x1a0
+#define XDPTX_MAINSTRM_MISC0_REG		0x1a4
+#define XDPTX_MAINSTRM_MISC0_MASK		BIT(0)
+#define XDPTX_MAINSTRM_MISC1_REG		0x1a8
+
+#define XDPTX_M_VID_REG				0x1ac
+#define XDPTX_TRANSFER_UNITSIZE_REG		0x1b0
+#define XDPTX_DEF_TRANSFER_UNITSIZE		0x40
+#define XDPTX_N_VID_REG				0x1b4
+#define XDPTX_USER_PIXELWIDTH_REG		0x1b8
+#define XDPTX_USER_DATACNTPERLANE_REG		0x1bc
+#define XDPTX_MINBYTES_PERTU_REG		0x1c4
+#define XDPTX_FRACBYTES_PERTU_REG		0x1c8
+#define XDPTX_INIT_WAIT_REG			0x1cc
+
+/* PHY configuration and status registers */
+#define XDPTX_PHYCONFIG_REG			0x200
+#define XDPTX_PHYCONFIG_RESET_MASK		BIT(0)
+#define XDPTX_PHYCONFIG_GTTXRESET_MASK		BIT(1)
+#define XDPTX_PHYCONFIG_PMARESET_MASK		BIT(8)
+#define XDPTX_PHYCONFIG_PCSRESET_MASK		BIT(9)
+#define XDPTX_PHYCONFIG_ALLRESET_MASK	(XDPTX_PHYCONFIG_RESET_MASK | \
+					 XDPTX_PHYCONFIG_GTTXRESET_MASK | \
+					 XDPTX_PHYCONFIG_PMARESET_MASK | \
+					 XDPTX_PHYCONFIG_PCSRESET_MASK)
+
+#define XDPTX_PHYCLOCK_FBSETTING_REG		0x234
+#define XDPTX_PHYCLOCK_FBSETTING162_MASK	0x1
+#define XDPTX_PHYCLOCK_FBSETTING270_MASK	0x3
+#define XDPTX_PHYCLOCK_FBSETTING810_MASK	0x5
+
+#define XDPTX_VS_PE_LEVEL_MAXCOUNT		0x3
+#define XDPTX_VS_LEVEL_MAXCOUNT			0x5
+
+#define XDPTX_PHYSTATUS_REG			0x280
+#define XDPTX_PHYSTATUS_FPGAPLLLOCK_MASK	BIT(6)
+#define XDPTX_MAX_RATE(bw, lanecnt, bpp)	((bw) * (lanecnt) * 8 / (bpp))
+
+#define XDPTX_MISC0_RGB_MASK			(0)
+#define XDPTX_MISC0_YCRCB422_MASK		(5 << 1)
+#define XDPTX_MISC0_YCRCB444_MASK		GENMASK(3, 2)
+#define XDPTX_MISC0_FORMAT_MASK			GENMASK(3, 1)
+#define XDPTX_MISC0_BPC6_MASK			(0 << 5)
+#define XDPTX_MISC0_BPC8_MASK			BIT(5)
+#define XDPTX_MISC0_BPC10_MASK			BIT(6)
+#define XDPTX_MISC0_BPC12_MASK			GENMASK(6, 5)
+#define XDPTX_MISC0_BPC16_MASK			BIT(7)
+#define XDPTX_MISC0_BPC_MASK			GENMASK(7, 5)
+#define XDPTX_MISC1_YONLY_MASK			BIT(7)
+
+#define XDPTX_MAX_LANES				0x4
+#define XDPTX_MAX_FREQ				3000000
+
+#define XDPTX_REDUCED_BIT_RATE			162000
+#define XDPTX_HIGH_BIT_RATE_1			270000
+#define XDPTX_HIGH_BIT_RATE_2			540000
+#define XDPTX_HIGH_BIT_RATE_3			810000
+
+#define XDPTX_V1_2				0x12
+#define XDPTX_V1_4				0x14
+
+#define XDP_TRAIN_MAX_SWING_REACHED			BIT(2)
+#define XDP_TRAIN_PRE_EMPHASIS_SHIFT			GENMASK(1, 0)
+#define XDP_DPCD_TRAINING_LANEX_SET_MAX_PE_MASK		BIT(5)
+
+#define XDPTX_PHYPRECURSOR_LANE0_REG			0x23c
+#define XDPTX_PHYPOSTCURSOR_LANE0_REG			0x24c
+
+/* Transceiver PHY reset and Differential voltage swing */
+#define XDPTX_PHYVOLTAGE_DIFFLANE0_REG			0x220
+#define XDPTX_VS_LEVEL_OFFSET				0x4
+
+#define XDPTX_VTC_BASE					0x1000
+
+/* VTC register offsets and bit masks */
+#define XDPTX_VTC_CTL					0x000
+#define XDPTX_VTC_CTL_MASK				GENMASK(18, 8)
+#define XDPTX_VTC_CTL_GE				BIT(2)
+#define XDPTX_VTC_CTL_RU				BIT(1)
+
+#define XDPTX_VTC_GASIZE_F0				0x060
+#define XDPTX_VTC_ACTIVE_SIZE_MASK			GENMASK(12, 0)
+
+#define XDPTX_VTC_GFENC					0x068
+#define XDPTX_VTC_GFENC_MASK				BIT(6)
+
+#define XDPTX_VTC_GPOL					0x06c
+#define XDPTX_VTC_GPOL_FIELD_ID_POL			BIT(6)
+#define XDPTX_VTC_ACTIVE_CHROMA_POL			BIT(5)
+#define	XDPTX_VTC_ACTIVE_VIDEO_POL			BIT(4)
+#define XDPTX_VTC_HSYNC_POL				BIT(3)
+#define XDPTX_VTC_VSYNC_POL				BIT(2)
+#define XDPTX_VTC_HBLANK_POL				BIT(1)
+#define XDPTX_VTC_VBLANK_POL				BIT(0)
+#define XDPTX_VTC_GPOL_MASK		(XDPTX_VTC_VBLANK_POL |\
+					 XDPTX_VTC_HBLANK_POL |\
+					 XDPTX_VTC_VSYNC_POL |\
+					 XDPTX_VTC_HSYNC_POL |\
+					 XDPTX_VTC_ACTIVE_VIDEO_POL |\
+					 XDPTX_VTC_ACTIVE_CHROMA_POL)
+
+#define XDPTX_VTC_INT_GPOL_MASK		(XDPTX_VTC_GPOL_FIELD_ID_POL |\
+					 XDPTX_VTC_ACTIVE_CHROMA_POL |\
+					 XDPTX_VTC_ACTIVE_VIDEO_POL)
+
+#define XDPTX_VTC_GHSIZE				0x070
+#define XDPTX_VTC_GHSIZE_FRAME_HSIZE			GENMASK(12, 0)
+
+#define XDPTX_VTC_GVSIZE				0x074
+#define XDPTX_VTC_FIELD1_VSIZE_SHIFT			16
+#define XDPTX_VTC_GVSIZE_FRAME_VSIZE			GENMASK(12, 0)
+
+#define XDPTX_VTC_GHSYNC				0x078
+#define XDPTX_VTC_GH1BPSTART_SHIFT			16
+#define XDPTX_VTC_GHSYNC_END_MASK			GENMASK(28, 16)
+#define XDPTX_VTC_GHSYNC_START_MASK			GENMASK(12, 0)
+
+#define XDPTX_VTC_GVBHOFF				0x07c
+#define XDPTX_VTC_F0VSYNC_HEND_SHIFT			16
+#define XDPTX_VTC_F0VBLANK_HEND_MASK			GENMASK(28, 16)
+#define XDPTX_VTC_F0VBLANK_HSTART_MASK			GENMASK(12, 0)
+
+#define XDPTX_VTC_GVSYNC				0x080
+#define XDPTX_VTC_F0_VSYNC_VEND_MASK			GENMASK(28, 16)
+#define XDPTX_VTC_F0_VSYNC_VSTART_MASK			GENMASK(12, 0)
+
+#define XDPTX_VTC_GVSHOFF				0x084
+#define XDPTX_VTC_GVBHOFF_F1				0x088
+#define XDPTX_VTC_GVSYNC_F1				0x08c
+#define XDPTX_VTC_GVSHOFF_F1				0x090
+#define XDPTX_VTC_GASIZE_F1				0x094
+
+/*
+ * struct xlnx_dp_link_config - Common link config between source and sink
+ * @max_rate: Miaximum link rate
+ * @max_lanes: Maximum number of lanes
+ */
+struct xlnx_dp_link_config {
+	int max_rate;
+	u8 max_lanes;
+};
+
+/**
+ * struct xlnx_dp_tx_link_config - configuration information of the source
+ * @vs_level: voltage swing level
+ * @pe_level: pre emphasis level
+ */
+struct xlnx_dp_tx_link_config {
+	u8 vs_level;
+	u8 pe_level;
+};
+
+/**
+ * struct xlnx_dp_mode - Configured mode of DisplayPort
+ * @pclock: pixel clock frequency of current mode
+ * @bw_code: code for bandwidth(link rate)
+ * @lane_cnt: number of lanes
+ */
+struct xlnx_dp_mode {
+	int pclock;
+	u8 bw_code;
+	u8 lane_cnt;
+};
+
+/**
+ * struct xlnx_dp_config - Configuration of DisplayPort from DTS
+ * @max_lanes: Maximum number of lanes
+ * @max_link_rate: Maximum supported link rate
+ * @misc0: Misc0 configuration
+ * @bpp: Bits per pixel
+ * @bpc: Bits per component
+ * @num_colors: Number of color components
+ * @ppc: Pixels per component
+ * @fmt: Color format
+ */
+struct xlnx_dp_config {
+	u32 max_lanes;
+	u32 max_link_rate;
+	u8 misc0;
+	u8 bpp;
+	u8 bpc;
+	u8 num_colors;
+	u8 ppc;
+	u8 fmt;
+};
+
+/**
+ * struct xlnx_dp - Xilinx DisplayPort core
+ * @dev: device structure
+ * @encoder: the drm encoder structure
+ * @connector: the drm connector structure
+ * @sync_prop: synchronous mode property
+ * @bpc_prop: bpc mode property
+ * @aux: aux channel
+ * @config: IP core configuration from DTS
+ * @tx_link_config: source configuration
+ * @rx_config: sink configuration
+ * @link_config: common link configuration between IP core and sink device
+ * @drm: DRM core
+ * @mode: current mode between IP core and sink device
+ * @phy: PHY handles for DP lanes
+ * @axi_lite_clk: axi lite clock
+ * @tx_vid_clk: tx video clock
+ * @reset_gpio: reset gpio
+ * @hpd_work: hot plug detection worker
+ * @phy_opts: Opaque generic phy configuration
+ * @status: connection status
+ * @dp_base: Base address of DisplayPort Tx subsystem
+ * @dpms: current dpms state
+ * @dpcd: DP configuration data from currently connected sink device
+ * @train_set: set of training data
+ * @num_lanes: number of enabled phy lanes
+ * @enabled: flag to indicate if the device is enabled
+ *
+ */
+struct xlnx_dp {
+	struct device *dev;
+	struct drm_encoder encoder;
+	struct drm_connector connector;
+	struct drm_property *sync_prop;
+	struct drm_property *bpc_prop;
+	struct drm_dp_aux aux;
+	struct xlnx_dp_config config;
+	struct xlnx_dp_tx_link_config tx_link_config;
+	struct xlnx_dp_link_config link_config;
+	struct drm_device *drm;
+	struct xlnx_dp_mode mode;
+	struct phy *phy[XDPTX_MAX_LANES];
+	struct clk *axi_lite_clk;
+	struct clk *tx_vid_clk;
+	struct gpio_desc *reset_gpio;
+	struct delayed_work hpd_work;
+	union phy_configure_opts phy_opts;
+	enum drm_connector_status status;
+	void __iomem *dp_base;
+	int dpms;
+	u8 dpcd[DP_RECEIVER_CAP_SIZE];
+	u8 train_set[XDPTX_MAX_LANES];
+	u8 num_lanes;
+	unsigned int enabled : 1;
+};
+
+static inline struct xlnx_dp *encoder_to_dp(struct drm_encoder *encoder)
+{
+	return container_of(encoder, struct xlnx_dp, encoder);
+}
+
+static inline struct xlnx_dp *connector_to_dp(struct drm_connector *connector)
+{
+	return container_of(connector, struct xlnx_dp, connector);
+}
+
+static void xlnx_dp_write(void __iomem *base, int offset, u32 val)
+{
+	writel(val, base + offset);
+}
+
+static u32 xlnx_dp_read(void __iomem *base, int offset)
+{
+	return readl(base + offset);
+}
+
+static void xlnx_dp_set(void __iomem *base, int offset, u32 set)
+{
+	xlnx_dp_write(base, offset, xlnx_dp_read(base, offset) | set);
+}
+
+static void xlnx_dp_clr(void __iomem *base, int offset, u32 clr)
+{
+	xlnx_dp_write(base, offset, xlnx_dp_read(base, offset) & ~clr);
+}
+
+static void xlnx_dp_vtc_set_timing(struct xlnx_dp *dp,
+				   struct drm_display_mode *mode)
+{
+	u32 reg;
+	u32 htotal, hactive, hsync_start, hbackporch_start;
+	u32 vtotal, vactive, vsync_start, vbackporch_start;
+	u32 hsync_len, hfront_porch, hback_porch;
+	u32 vsync_len, vfront_porch, vback_porch;
+
+	/*
+	 * TODO : For now driver does not support interlace mode
+	 * In future  driver may add interlace support
+	 */
+
+	/*
+	 * Note that pixels-per-clock for video data and timing is non-existent
+	 * in the Video Timing Controller. There is only a single set of timing
+	 * signals for the video data bus. This means that horizontal (acive
+	 * pixles, hsync, hblank) timing settings can be detected and generated
+	 * only for a multiple of the pixels-per-clock configured in the system.
+	 */
+	hactive = mode->hdisplay / dp->config.ppc;
+	hfront_porch = (mode->hsync_start - mode->hdisplay) / dp->config.ppc;
+	hback_porch = (mode->htotal - mode->hsync_end) / dp->config.ppc;
+	hsync_len = (mode->hsync_end - mode->hsync_start) / dp->config.ppc;
+	htotal = hactive + hfront_porch + hsync_len + hback_porch;
+	hsync_start = hactive + hfront_porch;
+	hbackporch_start = hsync_start + hsync_len;
+
+	vactive = mode->vdisplay;
+	vfront_porch = mode->vsync_start - mode->vdisplay;
+	vback_porch = mode->vtotal - mode->vsync_end;
+	vsync_len = mode->vsync_end - mode->vsync_start;
+	vtotal = vactive + vfront_porch + vsync_len + vback_porch;
+	vsync_start = vactive + vfront_porch;
+	vbackporch_start = vsync_start + vsync_len;
+
+	reg = htotal & XDPTX_VTC_GHSIZE_FRAME_HSIZE;
+	xlnx_dp_write(dp->dp_base, XDPTX_VTC_BASE + XDPTX_VTC_GHSIZE, reg);
+
+	reg = vtotal & XDPTX_VTC_GVSIZE_FRAME_VSIZE;
+	reg |= reg << XDPTX_VTC_FIELD1_VSIZE_SHIFT;
+	xlnx_dp_write(dp->dp_base, XDPTX_VTC_BASE + XDPTX_VTC_GVSIZE, reg);
+
+	reg = hactive & XDPTX_VTC_ACTIVE_SIZE_MASK;
+	reg |= (vactive & XDPTX_VTC_ACTIVE_SIZE_MASK) <<
+		XDPTX_VTC_FIELD1_VSIZE_SHIFT;
+	xlnx_dp_write(dp->dp_base, XDPTX_VTC_BASE + XDPTX_VTC_GASIZE_F0, reg);
+
+	reg = hsync_start & XDPTX_VTC_GHSYNC_START_MASK;
+	reg |= (hbackporch_start << XDPTX_VTC_GH1BPSTART_SHIFT) &
+		XDPTX_VTC_GHSYNC_END_MASK;
+	xlnx_dp_write(dp->dp_base, XDPTX_VTC_BASE + XDPTX_VTC_GHSYNC, reg);
+
+	reg = vsync_start & XDPTX_VTC_F0_VSYNC_VSTART_MASK;
+	reg |= (vbackporch_start << XDPTX_VTC_FIELD1_VSIZE_SHIFT) &
+		XDPTX_VTC_F0_VSYNC_VEND_MASK;
+	xlnx_dp_write(dp->dp_base, XDPTX_VTC_BASE + XDPTX_VTC_GVSYNC, reg);
+	xlnx_dp_clr(dp->dp_base, XDPTX_VTC_BASE + XDPTX_VTC_GFENC,
+		    XDPTX_VTC_GFENC_MASK);
+
+	/* Calculate and update Generator VBlank Hori field 0 */
+	reg = hactive & XDPTX_VTC_F0VBLANK_HSTART_MASK;
+	reg |= (hactive << XDPTX_VTC_F0VSYNC_HEND_SHIFT) &
+		XDPTX_VTC_F0VBLANK_HEND_MASK;
+	xlnx_dp_write(dp->dp_base, XDPTX_VTC_BASE + XDPTX_VTC_GVBHOFF, reg);
+
+	/* Calculate and update Generator VSync Hori field 0 */
+	reg = hsync_start & XDPTX_VTC_F0VBLANK_HSTART_MASK;
+	reg |= (hsync_start << XDPTX_VTC_F0VSYNC_HEND_SHIFT) &
+		XDPTX_VTC_F0VBLANK_HEND_MASK;
+	xlnx_dp_write(dp->dp_base, XDPTX_VTC_BASE + XDPTX_VTC_GVSHOFF, reg);
+
+	/* sets all polarities as active high */
+	xlnx_dp_write(dp->dp_base, XDPTX_VTC_BASE + XDPTX_VTC_GPOL,
+		      XDPTX_VTC_GPOL_MASK);
+
+	/* configure timing source */
+	xlnx_dp_set(dp->dp_base,
+		    XDPTX_VTC_BASE + XDPTX_VTC_CTL, XDPTX_VTC_CTL_MASK);
+	xlnx_dp_set(dp->dp_base,
+		    XDPTX_VTC_BASE + XDPTX_VTC_CTL, XDPTX_VTC_CTL_RU);
+}
+
+/**
+ * xlnx_dp_update_bpp - Update the current bpp config
+ * @dp: DisplayPort IP core structure
+ *
+ * Update the current bpp based on the color format: bpc & num_colors.
+ * Any function that changes bpc or num_colors should call this
+ * to keep the bpp value in sync.
+ */
+static void xlnx_dp_update_bpp(struct xlnx_dp *dp)
+{
+	struct xlnx_dp_config *config = &dp->config;
+
+	config->bpp = dp->config.bpc * dp->config.num_colors;
+}
+
+/**
+ * xlnx_dp_set_color - Set the color format
+ * @dp: DisplayPort IP core structure
+ * @drm_fourcc: Color string, from xlnx_disp_color_enum
+ *
+ * This function updates misc register values based on color string.
+ */
+static void xlnx_dp_set_color(struct xlnx_dp *dp, u32 drm_fourcc)
+{
+	struct xlnx_dp_config *config = &dp->config;
+
+	config->misc0 &= ~XDPTX_MISC0_FORMAT_MASK;
+
+	switch (drm_fourcc) {
+	case DRM_FORMAT_XBGR8888:
+		/* fall-through */
+	case DRM_FORMAT_XRGB8888:
+		/* fall-through */
+	case DRM_FORMAT_BGR888:
+		/* fall-through */
+	case DRM_FORMAT_RGB888:
+		/* fall-through */
+	case DRM_FORMAT_XBGR2101010:
+		config->misc0 |= XDPTX_MISC0_RGB_MASK;
+		config->num_colors = 3;
+		config->fmt = 0x0;
+		break;
+	case DRM_FORMAT_VUY888:
+		/* fall-through */
+	case DRM_FORMAT_XVUY8888:
+		/* fall-through */
+	case DRM_FORMAT_Y8:
+		/* fall-through */
+	case DRM_FORMAT_XVUY2101010:
+		/* fall-through */
+	case DRM_FORMAT_Y10:
+		config->misc0 |= XDPTX_MISC0_YCRCB444_MASK;
+		config->num_colors = 3;
+		config->fmt = 0x1;
+		break;
+	case DRM_FORMAT_YUYV:
+		/* fall-through */
+	case DRM_FORMAT_UYVY:
+		/* fall-through */
+	case DRM_FORMAT_NV16:
+		/* fall-through */
+	case DRM_FORMAT_XV20:
+		config->misc0 |= XDPTX_MISC0_YCRCB422_MASK;
+		config->num_colors = 2;
+		config->fmt = 0x2;
+		break;
+	default:
+		dev_dbg(dp->dev, "Warning: Unknown drm_fourcc format :%d\n",
+			drm_fourcc);
+		config->misc0 |= XDPTX_MISC0_RGB_MASK;
+	}
+	xlnx_dp_update_bpp(dp);
+}
+
+/**
+ * xlnx_dp_init_phy - Initialize the phy
+ * @dp: DisplayPort IP core structure
+ *
+ * Initialize the phy.
+ *
+ * Return: 0 if the phy instances are initialized correctly, or the error code
+ * returned from the callee functions.
+ */
+static int xlnx_dp_init_phy(struct xlnx_dp *dp)
+{
+	unsigned int i;
+	int ret;
+
+	xlnx_dp_clr(dp->dp_base, XDPTX_PHYCONFIG_REG,
+		    XDPTX_PHYCONFIG_ALLRESET_MASK);
+
+	for (i = 0; i < XDPTX_MAX_LANES; i++) {
+		ret = phy_init(dp->phy[i]);
+		if (ret) {
+			dev_err(dp->dev,
+				"failed to init phy lane %d\n", i);
+			return ret;
+		}
+	}
+
+	return ret;
+}
+
+/**
+ * xlnx_dp_exit_phy - Exit the phy
+ * @dp: DisplayPort IP core structure
+ *
+ * Exit the phy.
+ */
+static void xlnx_dp_exit_phy(struct xlnx_dp *dp)
+{
+	unsigned int i;
+	int ret;
+
+	for (i = 0; i < XDPTX_MAX_LANES; i++) {
+		ret = phy_exit(dp->phy[i]);
+		if (ret)
+			dev_err(dp->dev, "fail to exit phy(%d) %d\n", i, ret);
+		dp->phy[i] = NULL;
+	}
+}
+
+/**
+ * xlnx_dp_phy_ready - check if PHY is ready
+ * @dp: DisplayPort IP core structure
+ *
+ * check if PHY is ready. If PHY is not ready, wait 1ms to check for 100 times.
+ * This amount of delay was suggested by IP designer.
+ *
+ * Return: 0 if PHY is ready, or -ENODEV if PHY is not ready.
+ */
+static int xlnx_dp_phy_ready(struct xlnx_dp *dp)
+{
+	u32 i, reg, ready;
+
+	ready = (1 << XDPTX_MAX_LANES) - 1;
+	ready |= XDPTX_PHYSTATUS_FPGAPLLLOCK_MASK;
+
+	/* Wait for 100ms. This should be enough time for PHY to be ready */
+	for (i = 0; ; i++) {
+		reg = xlnx_dp_read(dp->dp_base, XDPTX_PHYSTATUS_REG);
+		if ((reg & ready) == ready)
+			return 0;
+		if (i == 100) {
+			dev_err(dp->dev, "PHY isn't ready\n");
+			return -ENODEV;
+		}
+		usleep_range(1000, 1100);
+	}
+
+	return 0;
+}
+
+/**
+ * xlnx_dp_mode_configure - Configure the link values
+ * @dp: DisplayPort IP core structure
+ * @pclock: pixel clock for requested display mode
+ * @current_bw: current link rate
+ *
+ * Find the link configuration values, rate and lane count for requested pixel
+ * clock @pclock. The @pclock is stored in the mode to be used in other
+ * functions later. The returned rate is downshifted from the current rate
+ * @current_bw.
+ *
+ * Return: Current link rate code, or -EINVAL.
+ */
+static int xlnx_dp_mode_configure(struct xlnx_dp *dp, int pclock,
+				  u8 current_bw)
+{
+	int max_rate = dp->link_config.max_rate;
+	u8 bw_code;
+	u8 max_lanes = dp->link_config.max_lanes;
+	u8 max_link_rate_code = drm_dp_link_rate_to_bw_code(max_rate);
+	u8 bpp = dp->config.bpp;
+	u8 lane_cnt;
+
+	/* Downshift from current bandwidth */
+	switch (current_bw) {
+	case DP_LINK_BW_8_1:
+		bw_code = DP_LINK_BW_5_4;
+		break;
+	case DP_LINK_BW_5_4:
+		bw_code = DP_LINK_BW_2_7;
+		break;
+	case DP_LINK_BW_2_7:
+		bw_code = DP_LINK_BW_1_62;
+		break;
+	case DP_LINK_BW_1_62:
+		dev_err(dp->dev, "can't downshift. already lowest link rate\n");
+		return -EINVAL;
+	default:
+		/* If not given, start with max supported */
+		bw_code = max_link_rate_code;
+		break;
+	}
+
+	for (lane_cnt = max_lanes; lane_cnt >= 1; lane_cnt >>= 1) {
+		int bw;
+		u32 rate;
+
+		bw = drm_dp_bw_code_to_link_rate(bw_code);
+		rate = XDPTX_MAX_RATE(bw, lane_cnt, bpp);
+		if (pclock <= rate) {
+			dp->mode.bw_code = bw_code;
+			dp->mode.lane_cnt = lane_cnt;
+			dp->mode.pclock = pclock;
+			return dp->mode.bw_code;
+		}
+	}
+
+	dev_err(dp->dev, "failed to configure link values\n");
+
+	return -EINVAL;
+}
+
+/**
+ * xlnx_dp_tx_set_vswing_preemp - This function sets current voltage swing and
+ * pre-emphasis level settings from the link_config structure to hardware.
+ * @dp: DisplayPort IP core structure
+ * @aux_data: Aux_data is a pointer to the array used for preparing a burst
+ * write over the AUX channel.
+ */
+static void xlnx_dp_tx_set_vswing_preemp(struct xlnx_dp *dp, u8 *aux_data)
+{
+	static const u32 tx_pe_levels[] = { 0x00, 0x0e, 0x14, 0x1b };
+	static const u8 tx_vs_levels[] = { 0x2, 0x5, 0x8, 0xf };
+	u32 pe_level, vs_level;
+	u8 data, i;
+
+	u8 vs_level_rx = dp->tx_link_config.vs_level;
+	u8 pe_level_rx = dp->tx_link_config.pe_level;
+
+	pe_level = tx_pe_levels[pe_level_rx];
+	vs_level = tx_vs_levels[vs_level_rx];
+
+	/*
+	 * Redriver in path requires different voltage-swing and pre-emphasis
+	 * values. Below case assumes there is no redriver in the path so
+	 * voltage-swing compensation offset is used when pre-emphasis is used.
+	 * See the VESA DisplayPort v1.4 Specification, section 3.6.1.1.
+	 */
+	if (!pe_level_rx)
+		vs_level += XDPTX_VS_LEVEL_OFFSET;
+
+	data = (pe_level_rx << XDP_TRAIN_PRE_EMPHASIS_SHIFT) |
+		vs_level_rx;
+
+	if (vs_level_rx == XDPTX_VS_PE_LEVEL_MAXCOUNT)
+		data |= XDP_TRAIN_MAX_SWING_REACHED;
+	if (pe_level_rx == XDPTX_VS_PE_LEVEL_MAXCOUNT)
+		data |= XDP_DPCD_TRAINING_LANEX_SET_MAX_PE_MASK;
+
+	memset(aux_data, data, XDPTX_MAX_LANES);
+
+	for (i = 0; i < dp->mode.lane_cnt; i++) {
+		xlnx_dp_write(dp->dp_base,
+			      XDPTX_PHYPRECURSOR_LANE0_REG + 4 * i, 0x0);
+		xlnx_dp_write(dp->dp_base,
+			      XDPTX_PHYVOLTAGE_DIFFLANE0_REG + 4 * i, vs_level);
+		xlnx_dp_write(dp->dp_base,
+			      XDPTX_PHYPOSTCURSOR_LANE0_REG + 4 * i, pe_level);
+	}
+}
+
+/**
+ * xlnx_dp_tx_adj_vswing_preemp - Sets voltage swing and pre-emphasis levels
+ * @dp:Pointer to xlnx_dp structure
+ * @link_status: An array of link status register
+ *
+ * This function sets new voltage swing and pre-emphasis levels using the
+ * adjustment requests obtained from the sink.
+ *
+ * Return: 0 if the new levels were written successfully.
+ * error value on failure.
+ */
+static int xlnx_dp_tx_adj_vswing_preemp(struct xlnx_dp *dp, u8 link_status[6])
+{
+	struct phy_configure_opts_dp *phy_cfg = &dp->phy_opts.dp;
+	int ret;
+	u8 i, aux_data[4];
+	u8 vs_level_adj_req[4];
+	u8 pe_level_adj_req[4];
+	u8 max_lanes = dp->link_config.max_lanes;
+
+	/*
+	 * Analyze the adjustment requests for changes in voltage swing and
+	 * pre-emphasis levels.
+	 */
+	vs_level_adj_req[0] = FIELD_GET(DP_ADJUST_VOLTAGE_SWING_LANE0_MASK,
+					link_status[4]);
+	vs_level_adj_req[1] = FIELD_GET(DP_ADJUST_VOLTAGE_SWING_LANE1_MASK,
+					link_status[4]);
+	vs_level_adj_req[2] = FIELD_GET(DP_ADJUST_VOLTAGE_SWING_LANE0_MASK,
+					link_status[5]);
+	vs_level_adj_req[3] = FIELD_GET(DP_ADJUST_VOLTAGE_SWING_LANE1_MASK,
+					link_status[5]);
+	pe_level_adj_req[0] = FIELD_GET(DP_ADJUST_PRE_EMPHASIS_LANE0_MASK,
+					link_status[4]);
+	pe_level_adj_req[1] = FIELD_GET(DP_ADJUST_PRE_EMPHASIS_LANE1_MASK,
+					link_status[4]);
+	pe_level_adj_req[2] = FIELD_GET(DP_ADJUST_PRE_EMPHASIS_LANE0_MASK,
+					link_status[5]);
+	pe_level_adj_req[3] = FIELD_GET(DP_ADJUST_PRE_EMPHASIS_LANE1_MASK,
+					link_status[5]);
+
+	/*
+	 * change the drive settings to match the adjustment requests. Use the
+	 * greatest level requested.
+	 */
+	dp->tx_link_config.vs_level = 0;
+	dp->tx_link_config.pe_level = 0;
+	for (i = 0; i < dp->mode.lane_cnt ; i++) {
+		if (vs_level_adj_req[i] > dp->tx_link_config.vs_level)
+			dp->tx_link_config.vs_level = vs_level_adj_req[i];
+		if (pe_level_adj_req[i] > dp->tx_link_config.pe_level)
+			dp->tx_link_config.pe_level = pe_level_adj_req[i];
+	}
+
+	/*
+	 * Verify that the voltage swing and pre-emphasis combination is
+	 * allowed. Some combinations will result in differential peak-to-peak
+	 * voltage that is outside the permissible range. See the VESA
+	 * DisplayPort v1.4 Specification, section 3.1.5.2.
+	 * The valid combinations are:
+	 *      PE=0    PE=1    PE=2    PE=3
+	 * VS=0 Valid   Valid   Valid   Valid
+	 * VS=1 Valid   Valid   Valid
+	 * VS=2 Valid   Valid
+	 * VS=3 Valid
+	 */
+	if (dp->tx_link_config.pe_level > (4 - dp->tx_link_config.vs_level))
+		dp->tx_link_config.pe_level = 4 - dp->tx_link_config.vs_level;
+
+	/*
+	 * Make the adjustments to both the DisplayPort TX core and the RX
+	 * device.
+	 */
+	xlnx_dp_tx_set_vswing_preemp(dp, aux_data);
+	/*
+	 * Write the voltage swing and pre-emphasis levels for each lane to the
+	 * RX device.
+	 */
+	ret = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_LANE0_SET,
+				&aux_data[0], 1);
+	if (ret < 0)
+		return ret;
+
+	phy_cfg->lanes = max_lanes;
+	phy_cfg->pre[0] = dp->tx_link_config.pe_level;
+	phy_cfg->voltage[0] = dp->tx_link_config.vs_level;
+	phy_cfg->set_voltages = 1;
+
+	phy_configure(dp->phy[0], &dp->phy_opts);
+
+	return 0;
+}
+
+/**
+ * xlnx_dp_link_train_cr - Train clock recovery
+ * @dp: DisplayPort IP core structure
+ *
+ * Return: 0 if clock recovery train is done successfully, or corresponding
+ * error code.
+ */
+static int xlnx_dp_link_train_cr(struct xlnx_dp *dp)
+{
+	u8 prev_vs_level = 0;
+	u8 same_vs_level_count = 0;
+	u8 aux_data;
+	u16 max_tries;
+	u8 link_status[DP_LINK_STATUS_SIZE];
+	u8 lane_cnt = dp->mode.lane_cnt;
+	bool cr_done = 0;
+	int ret;
+	struct xlnx_dp_tx_link_config *link_config = &dp->tx_link_config;
+
+	dp->tx_link_config.vs_level = 0;
+	dp->tx_link_config.pe_level = 0;
+
+	xlnx_dp_write(dp->dp_base, XDPTX_TRNGPAT_SET_REG,
+		      DP_TRAINING_PATTERN_1);
+	xlnx_dp_write(dp->dp_base, XDPTX_SCRAMBLING_DIS_REG, 1);
+	aux_data = DP_TRAINING_PATTERN_1 | DP_LINK_SCRAMBLING_DISABLE;
+	ret = drm_dp_dpcd_writeb(&dp->aux, DP_TRAINING_PATTERN_SET, aux_data);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * 256 loops should be maximum iterations for 4 lanes and 4 values.
+	 * So, This loop should exit before 512 iterations
+	 */
+	for (max_tries = 0; max_tries < 512; max_tries++) {
+		/*
+		 * Obtain the required delay for clock recovery as specified
+		 * by the RX device.
+		 * Wait delay specified in TRAINING_AUX_RD_INTERVAL(0x0E)
+		 */
+		drm_dp_link_train_clock_recovery_delay(dp->dpcd);
+		/*
+		 * check if all lanes have realized and maintained the
+		 * frequency lock and get adjustment requests.
+		 */
+		ret = drm_dp_dpcd_read_link_status(&dp->aux, link_status);
+		if (ret < 0)
+			return ret;
+		cr_done = drm_dp_clock_recovery_ok(link_status, lane_cnt);
+		if (cr_done)
+			break;
+		/*
+		 * check if the same voltage swing for each lane has been
+		 * used 5 consecutive times.
+		 */
+		if (prev_vs_level == link_config->vs_level) {
+			same_vs_level_count++;
+		} else {
+			same_vs_level_count = 0;
+			prev_vs_level = link_config->vs_level;
+		}
+
+		if (same_vs_level_count == XDPTX_VS_LEVEL_MAXCOUNT)
+			break;
+
+		if (link_config->vs_level == XDPTX_VS_PE_LEVEL_MAXCOUNT)
+			break;
+
+		ret = xlnx_dp_tx_adj_vswing_preemp(dp, link_status);
+		if (ret < 0)
+			return ret;
+	}
+	if (!cr_done) {
+		dev_err(dp->dev, "training cr failed\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+/**
+ * xlnx_dp_link_train_ce - Train channel equalization
+ * @dp: DisplayPort IP core structure
+ *
+ * Return: 0 if channel equalization train is done successfully, or
+ * corresponding error code.
+ */
+
+static int xlnx_dp_link_train_ce(struct xlnx_dp *dp)
+{
+	int ret;
+	u8 pat;
+	u32 i;
+	u8 link_status[DP_LINK_STATUS_SIZE];
+	u8 lane_cnt = dp->mode.lane_cnt;
+	u8 aux_data[5];
+	bool ce_done;
+
+	if (dp->dpcd[DP_DPCD_REV] == XDPTX_V1_4 &&
+	    dp->dpcd[DP_MAX_DOWNSPREAD] & DP_TPS4_SUPPORTED) {
+		pat = DP_TRAINING_PATTERN_4;
+	} else if (dp->dpcd[DP_DPCD_REV] >= XDPTX_V1_2 &&
+		dp->dpcd[DP_MAX_LANE_COUNT] & DP_TPS3_SUPPORTED) {
+		pat = DP_TRAINING_PATTERN_3;
+	} else {
+		pat = DP_TRAINING_PATTERN_2;
+	}
+
+	xlnx_dp_write(dp->dp_base, XDPTX_TRNGPAT_SET_REG, pat);
+
+	if (dp->dpcd[DP_DPCD_REV] == XDPTX_V1_4) {
+		xlnx_dp_write(dp->dp_base, XDPTX_SCRAMBLING_DIS_REG, 0);
+		aux_data[0] = DP_TRAINING_PATTERN_4;
+	} else {
+		xlnx_dp_write(dp->dp_base, XDPTX_SCRAMBLING_DIS_REG, 1);
+		aux_data[0] = pat | DP_LINK_SCRAMBLING_DISABLE;
+	}
+	xlnx_dp_tx_set_vswing_preemp(dp, &aux_data[1]);
+	ret = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_PATTERN_SET,
+				&aux_data[0], 5);
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < 8; i++) {
+		/*
+		 * Obtain the required delay for channel equalization as
+		 * specified by the RX device.
+		 */
+		drm_dp_link_train_channel_eq_delay(dp->dpcd);
+
+		ret = drm_dp_dpcd_read_link_status(&dp->aux, link_status);
+		if (ret < 0)
+			return ret;
+
+		/*
+		 * check if all lanes have accomplished channel equalization,
+		 * symbol lock, and interlane alignment.
+		 */
+		ce_done = drm_dp_channel_eq_ok(link_status, lane_cnt);
+		if (ce_done)
+			break;
+
+		ret = drm_dp_dpcd_read_link_status(&dp->aux, link_status);
+		if (ret < 0)
+			return ret;
+
+		ret = xlnx_dp_tx_adj_vswing_preemp(dp, link_status);
+		if (ret != 0)
+			return ret;
+	}
+	/*
+	 * Tried 8 times with no success. Try a reduced bitrate first, then
+	 * reduce the number of lanes.
+	 */
+	if (!ce_done) {
+		dev_err(dp->dev, "training ce failed\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+/**
+ * xlnx_dp_link_train - Train the link
+ * @dp: DisplayPort IP core structure
+ *
+ * Return: 0 if all trains are done successfully, or corresponding error code.
+ */
+static int xlnx_dp_train(struct xlnx_dp *dp)
+{
+	u32 reg;
+	u8 bw_code = dp->mode.bw_code;
+	u8 lane_cnt = dp->mode.lane_cnt;
+	u8 aux_lane_cnt = lane_cnt;
+	u8 data;
+	bool enhanced;
+	int ret;
+
+	xlnx_dp_write(dp->dp_base, XDPTX_LANECNT_SET_REG, lane_cnt);
+	enhanced = drm_dp_enhanced_frame_cap(dp->dpcd);
+	if (enhanced) {
+		xlnx_dp_write(dp->dp_base, XDPTX_EFRAME_EN_REG, 1);
+		aux_lane_cnt |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
+	}
+
+	if (dp->dpcd[3] & 0x1) {
+		xlnx_dp_write(dp->dp_base, XDPTX_DOWNSPREAD_CTL_REG, 1);
+		drm_dp_dpcd_writeb(&dp->aux, DP_MAX_DOWNSPREAD,
+				   DP_MAX_DOWNSPREAD_0_5);
+	} else {
+		xlnx_dp_write(dp->dp_base, XDPTX_DOWNSPREAD_CTL_REG, 0);
+		drm_dp_dpcd_writeb(&dp->aux, DP_DOWNSPREAD_CTRL, 0);
+	}
+
+	ret = drm_dp_dpcd_writeb(&dp->aux, DP_LANE_COUNT_SET, aux_lane_cnt);
+	if (ret < 0) {
+		dev_err(dp->dev, "failed to set lane count\n");
+		return ret;
+	}
+
+	ret = drm_dp_dpcd_writeb(&dp->aux, DP_MAIN_LINK_CHANNEL_CODING_SET,
+				 DP_SET_ANSI_8B10B);
+	if (ret < 0) {
+		dev_err(dp->dev, "failed to set ANSI 8B/10B encoding\n");
+		return ret;
+	}
+
+	ret = drm_dp_dpcd_writeb(&dp->aux, DP_LINK_BW_SET, bw_code);
+	if (ret < 0) {
+		dev_err(dp->dev, "failed to set DP bandwidth\n");
+		return ret;
+	}
+	xlnx_dp_write(dp->dp_base, XDPTX_LINKBW_SET_REG, bw_code);
+
+	switch (bw_code) {
+	case DP_LINK_BW_1_62:
+		reg = XDPTX_PHYCLOCK_FBSETTING162_MASK;
+		break;
+	case DP_LINK_BW_2_7:
+		reg = XDPTX_PHYCLOCK_FBSETTING270_MASK;
+		break;
+	case DP_LINK_BW_5_4:
+		/* fall-through */
+	case DP_LINK_BW_8_1:
+		reg = XDPTX_PHYCLOCK_FBSETTING810_MASK;
+		break;
+	default:
+		reg = XDPTX_PHYCLOCK_FBSETTING810_MASK;
+	}
+	xlnx_dp_write(dp->dp_base, XDPTX_PHYCLOCK_FBSETTING_REG,
+		      reg);
+	ret = xlnx_dp_phy_ready(dp);
+	if (ret < 0)
+		return ret;
+
+	memset(dp->train_set, 0, XDPTX_MAX_LANES);
+	ret = xlnx_dp_link_train_cr(dp);
+	if (ret)
+		return ret;
+
+	ret = xlnx_dp_link_train_ce(dp);
+	if (ret)
+		return ret;
+
+	if (dp->dpcd[DP_DPCD_REV] == XDPTX_V1_4) {
+		ret = drm_dp_dpcd_readb(&dp->aux, DP_LANE_COUNT_SET, &data);
+		if (ret < 0) {
+			dev_dbg(dp->dev, "DPCD read first try fails");
+			ret = drm_dp_dpcd_readb(&dp->aux,
+						DP_LANE_COUNT_SET, &data);
+			if (ret < 0) {
+				dev_err(dp->dev, "DPCD read retry fails");
+				return ret;
+			}
+		}
+
+		/*
+		 * Post Link Training ; An upstream device with a DPTX sets
+		 * this bit to 1 to grant the POST_LT_ADJ_REQ sequence by the
+		 * downstream DPRX if the downstream DPRX supports
+		 * POST_LT_ADJ_REQ
+		 */
+		data |= 0x20;
+		ret = drm_dp_dpcd_writeb(&dp->aux, DP_LANE_COUNT_SET, data);
+		if (ret < 0) {
+			dev_dbg(dp->dev, "DPCD write first try fails");
+			ret = drm_dp_dpcd_writeb(&dp->aux,
+						 DP_LANE_COUNT_SET, data);
+			if (ret < 0) {
+				dev_err(dp->dev, "DPCD write retry fails");
+				return ret;
+			}
+		}
+	}
+	xlnx_dp_write(dp->dp_base, XDPTX_SCRAMBLING_DIS_REG, 0);
+
+	xlnx_dp_write(dp->dp_base, XDPTX_TRNGPAT_SET_REG,
+		      DP_TRAINING_PATTERN_DISABLE);
+	ret = drm_dp_dpcd_writeb(&dp->aux, DP_TRAINING_PATTERN_SET,
+				 DP_TRAINING_PATTERN_DISABLE);
+	if (ret < 0) {
+		dev_err(dp->dev, "failed to disable training pattern\n");
+		return ret;
+	}
+	/* Disable the scrambler.*/
+	xlnx_dp_write(dp->dp_base, XDPTX_SCRAMBLING_DIS_REG, 0);
+
+	return 0;
+}
+
+/**
+ * xlnx_dp_train_loop - Downshift the link rate during training
+ * @dp: DisplayPort IP core structure
+ *
+ * Train the link by downshifting the link rate if training is not successful.
+ */
+static void xlnx_dp_train_loop(struct xlnx_dp *dp)
+{
+	struct xlnx_dp_mode *mode = &dp->mode;
+	u8 bw = mode->bw_code;
+	int ret;
+
+	do {
+		if (dp->status == connector_status_disconnected ||
+		    !dp->enabled)
+			return;
+		ret = xlnx_dp_train(dp);
+		if (!ret)
+			return;
+		ret = xlnx_dp_mode_configure(dp, mode->pclock, bw);
+		if (ret < 0)
+			goto err_out;
+
+		bw = ret;
+	} while (bw >= DP_LINK_BW_1_62);
+
+err_out:
+	dev_err(dp->dev, "failed to train the DP link\n");
+}
+
+/**
+ * xlnx_dp_aux_cmd_submit - Submit aux command
+ * @dp: DisplayPort IP core structure
+ * @cmd: aux command
+ * @addr: aux address
+ * @buf: buffer for command data
+ * @bytes: number of bytes for @buf
+ * @reply: reply code to be returned
+ *
+ * Submit an aux command. All aux related commands, native or i2c aux
+ * read/write, are submitted through this function. The function is mapped to
+ * the transfer function of struct drm_dp_aux. This function involves in
+ * multiple register reads/writes, thus synchronization is needed, and it is
+ * done by drm_dp_helper using @hw_mutex. The calling thread goes into sleep
+ * if there's no immediate reply to the command submission. The reply code is
+ * returned at @reply if @reply != NULL.
+ *
+ * Return: 0 if the command is submitted properly, or corresponding error code:
+ * -EBUSY when there is any request already being processed
+ * -ETIMEDOUT when receiving reply is timed out
+ * -EIO when received bytes are less than requested
+ */
+static int xlnx_dp_aux_cmd_submit(struct xlnx_dp *dp, u32 cmd, u16 addr,
+				  u8 *buf, u8 bytes, u8 *reply)
+{
+	bool is_read = (cmd & XDPTX_AUX_READ_BIT) ? true : false;
+	void __iomem *dp_base = dp->dp_base;
+	u32 reg, i;
+
+	reg = xlnx_dp_read(dp_base, XDPTX_INTR_SIGSTATE_REG);
+	if (reg & XDPTX_INTR_SIGREQSTATE)
+		return -EBUSY;
+
+	xlnx_dp_write(dp_base, XDPTX_AUX_ADDR_REG, addr);
+	if (!is_read) {
+		for (i = 0; i < bytes; i++) {
+			xlnx_dp_write(dp_base, XDPTX_AUX_WRITEFIFO_REG,
+				      buf[i]);
+		}
+	}
+
+	reg = cmd << XDPTX_AUXCMD_SHIFT;
+	if (!buf || !bytes)
+		reg |= XDPTX_AUXCMD_ADDRONLY_MASK;
+	else
+		reg |= (bytes - 1) << XDPTX_AUXCMD_BYTES_SHIFT;
+	xlnx_dp_write(dp_base, XDPTX_AUXCMD_REG, reg);
+
+	/* Wait for reply to be delivered upto 2ms */
+	for (i = 0; ; i++) {
+		reg = xlnx_dp_read(dp_base, XDPTX_INTR_SIGSTATE_REG);
+		if (reg & XDPTX_INTR_SIGRPLYSTATE)
+			break;
+
+		if (reg & XDPTX_INTR_RPLYTIMEOUT ||
+		    i == 2)
+			return -ETIMEDOUT;
+
+		usleep_range(1000, 1100);
+	}
+
+	reg = xlnx_dp_read(dp_base, XDPTX_AUXREPLY_CODE_REG);
+	if (reply)
+		*reply = reg;
+
+	if (is_read && !reg) {
+		reg = xlnx_dp_read(dp_base, XDPTX_AUXREPLY_DATACNT_REG);
+		if ((reg & XDPTX_AUXREPLY_DATACNT_MASK) != bytes)
+			return -EIO;
+
+		for (i = 0; i < bytes; i++) {
+			buf[i] = xlnx_dp_read(dp_base,
+					      XDPTX_AUXREPLY_DATA_REG);
+		}
+	}
+
+	return 0;
+}
+
+static ssize_t
+xlnx_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
+{
+	struct xlnx_dp *dp = container_of(aux, struct xlnx_dp, aux);
+	int ret;
+	unsigned int i, iter;
+
+	/* This is to iterate at least 50 msec */
+	iter = 50 * 1000 / 400;
+
+	for (i = 0; i < iter; i++) {
+		ret = xlnx_dp_aux_cmd_submit(dp, msg->request, msg->address,
+					     msg->buffer, msg->size,
+					       &msg->reply);
+		if (!ret) {
+			dev_dbg(dp->dev, "aux %d retries\n", i);
+			return msg->size;
+		}
+
+		if (dp->status == connector_status_disconnected) {
+			dev_info(dp->dev, "no connected aux device\n");
+			return -ENODEV;
+		}
+
+		usleep_range(400, 500);
+	}
+
+	dev_info(dp->dev, "failed aux transfer\n");
+
+	return ret;
+}
+
+/**
+ * xlnx_dp_init_aux - Initialize the DP aux
+ * @dp: DisplayPort IP core structure
+ *
+ * Initialize the DP aux. The aux clock is derived from the axi clock, so
+ * this function gets the axi clock frequency and calculates the filter
+ * value. Additionally, the interrupts and transmitter are enabled.
+ *
+ * Return: 0 on success, error value otherwise
+ */
+static int xlnx_dp_init_aux(struct xlnx_dp *dp)
+{
+	unsigned long rate;
+	u32 reg, w;
+
+	rate = clk_get_rate(dp->axi_lite_clk);
+	if (rate < XDPTX_CLKDIV_MHZ) {
+		dev_err(dp->dev, "aclk should be higher than 1MHz\n");
+		return -EINVAL;
+	}
+
+	/* Allowable values for this register are: 8, 16, 24, 32, 40, 48 */
+	for (w = 8; w <= 48; w += 8) {
+		/* AUX pulse width should be between 0.4 to 0.6 usec */
+		if (w >= (4 * rate / 10000000) &&
+		    w <= (6 * rate / 10000000))
+			break;
+	}
+
+	if (w > 48) {
+		dev_err(dp->dev, "aclk frequency too high\n");
+		return -EINVAL;
+	}
+	reg = w << XDPTX_CLKDIV_AUXFILTER_SHIFT;
+	reg |= rate / XDPTX_CLKDIV_MHZ;
+	xlnx_dp_write(dp->dp_base, XDPTX_CLKDIV_REG, reg);
+
+	xlnx_dp_write(dp->dp_base, XDPTX_ENABLE_REG, 1);
+	return 0;
+}
+
+/**
+ * xlnx_dp_exit_aux - De-initialize the DP aux
+ * @dp: DisplayPort IP core structure
+ *
+ * De-initialize the DP aux. Disable all interrupts which are enabled
+ * through aux initialization, as well as the transmitter.
+ */
+static void xlnx_dp_exit_aux(struct xlnx_dp *dp)
+{
+	xlnx_dp_write(dp->dp_base, XDPTX_ENABLE_REG, 0);
+	xlnx_dp_write(dp->dp_base, XDPTX_INTR_MASK_REG, 0xfff);
+}
+
+/**
+ * xlnx_dp_update_misc - Write the misc registers
+ * @dp: DisplayPort IP core structure
+ *
+ * The misc register values are stored in the structure, and this
+ * function applies the values into the registers.
+ */
+static void xlnx_dp_update_misc(struct xlnx_dp *dp)
+{
+	struct xlnx_dp_config *config = &dp->config;
+
+	xlnx_dp_write(dp->dp_base, XDPTX_MAINSTRM_MISC0_REG, config->misc0);
+	xlnx_dp_write(dp->dp_base, XDPTX_MAINSTRM_MISC1_REG, 0x0);
+}
+
+/**
+ * xlnx_dp_set_sync_mode - Set the sync mode bit in the software misc state
+ * @dp: DisplayPort IP core structure
+ * @mode: flag if the sync mode should be on or off
+ *
+ * Set the bit in software misc state. To apply to hardware,
+ * xlnx_dp_update_misc() should be called.
+ */
+static void xlnx_dp_set_sync_mode(struct xlnx_dp *dp, bool mode)
+{
+	struct xlnx_dp_config *config = &dp->config;
+
+	if (mode)
+		config->misc0 |= XDPTX_MAINSTRM_MISC0_MASK;
+	else
+		config->misc0 &= ~XDPTX_MAINSTRM_MISC0_MASK;
+}
+
+/**
+ * xlnx_dp_set_bpc - Set bpc value in software misc state
+ * @dp: DisplayPort IP core structure
+ * @bpc: bits per component
+ *
+ * Return: 0 on success, or the fallback bpc value
+ */
+static u32 xlnx_dp_set_bpc(struct xlnx_dp *dp, u8 bpc)
+{
+	struct xlnx_dp_config *config = &dp->config;
+	unsigned int ret = 0;
+
+	if (dp->connector.display_info.bpc &&
+	    dp->connector.display_info.bpc != bpc) {
+		dev_err(dp->dev, "requested bpc (%u) != display info (%u)\n",
+			bpc, dp->connector.display_info.bpc);
+		bpc = dp->connector.display_info.bpc;
+	}
+
+	config->misc0 &= ~XDPTX_MISC0_BPC_MASK;
+	switch (bpc) {
+	case 6:
+		config->misc0 |= XDPTX_MISC0_BPC6_MASK;
+		break;
+	case 8:
+		config->misc0 |= XDPTX_MISC0_BPC8_MASK;
+		break;
+	case 10:
+		config->misc0 |= XDPTX_MISC0_BPC10_MASK;
+		break;
+	case 12:
+		config->misc0 |= XDPTX_MISC0_BPC12_MASK;
+		break;
+	case 16:
+		config->misc0 |= XDPTX_MISC0_BPC16_MASK;
+		break;
+	default:
+		dev_err(dp->dev, "Not supported bpc (%u). fall back to 8bpc\n",
+			bpc);
+		config->misc0 |= XDPTX_MISC0_BPC8_MASK;
+		ret = 8;
+	}
+	config->bpc = bpc;
+	xlnx_dp_update_bpp(dp);
+
+	return ret;
+}
+
+/**
+ * xlnx_dp_encoder_mode_set_transfer_unit - Set the transfer unit values
+ * @dp: DisplayPort IP core structure
+ * @mode: requested display mode
+ *
+ * Set the transfer unit, and calculate all transfer unit size related values.
+ * Calculation is based on DP and IP core specification.
+ */
+static void
+xlnx_dp_encoder_mode_set_transfer_unit(struct xlnx_dp *dp,
+				       struct drm_display_mode *mode)
+{
+	u32 tu = XDPTX_DEF_TRANSFER_UNITSIZE, temp;
+	u32 bw, vid_kbytes, avg_bytes_per_tu, init_wait;
+
+	/* Use the max transfer unit size (default) */
+	xlnx_dp_write(dp->dp_base, XDPTX_TRANSFER_UNITSIZE_REG, tu);
+
+	vid_kbytes = (mode->clock / 1000) * (dp->config.bpp / 8);
+	bw = drm_dp_bw_code_to_link_rate(dp->mode.bw_code);
+	avg_bytes_per_tu = vid_kbytes * tu / (dp->mode.lane_cnt * bw);
+
+	xlnx_dp_write(dp->dp_base, XDPTX_MINBYTES_PERTU_REG,
+		      avg_bytes_per_tu / 1000);
+
+	temp = (avg_bytes_per_tu % 1000) * 1024 / 1000;
+	xlnx_dp_write(dp->dp_base, XDPTX_FRACBYTES_PERTU_REG, temp);
+
+	/* Configure the initial wait cycle based on transfer unit size */
+	if (tu < (avg_bytes_per_tu / 1000))
+		init_wait = 0;
+	else if ((avg_bytes_per_tu / 1000) <= 4)
+		init_wait = tu;
+	else
+		init_wait = tu - avg_bytes_per_tu / 1000;
+
+	xlnx_dp_write(dp->dp_base, XDPTX_INIT_WAIT_REG, init_wait);
+}
+
+/**
+ * xlnx_dp_encoder_mode_set_stream - Configure the main stream
+ * @dp: DisplayPort IP core structure
+ * @mode: requested display mode
+ *
+ * Configure the main stream based on the requested mode @mode. Calculation is
+ * based on IP core specification.
+ */
+static void xlnx_dp_encoder_mode_set_stream(struct xlnx_dp *dp,
+					    struct drm_display_mode *mode)
+{
+	void __iomem *dp_base = dp->dp_base;
+	u8 lane_cnt = dp->mode.lane_cnt;
+	u32 reg, wpl;
+	unsigned int ppc;
+
+	xlnx_dp_write(dp_base, XDPTX_MAINSTRM_HTOTAL_REG, mode->htotal);
+	xlnx_dp_write(dp_base, XDPTX_MAINSTRM_VTOTAL_REG, mode->vtotal);
+
+	xlnx_dp_write(dp_base, XDPTX_MAINSTRM_POL_REG,
+		      (!!(mode->flags & DRM_MODE_FLAG_PVSYNC) <<
+		      XDPTX_MAINSTRM_POLVSYNC_SHIFT) |
+		      (!!(mode->flags & DRM_MODE_FLAG_PHSYNC) <<
+		      XDPTX_MAINSTRM_POLHSYNC_SHIFT));
+
+	xlnx_dp_write(dp_base, XDPTX_MAINSTRM_HSWIDTH_REG,
+		      mode->hsync_end - mode->hsync_start);
+	xlnx_dp_write(dp_base, XDPTX_MAINSTRM_VSWIDTH_REG,
+		      mode->vsync_end - mode->vsync_start);
+	xlnx_dp_write(dp_base, XDPTX_MAINSTRM_HRES_REG, mode->hdisplay);
+	xlnx_dp_write(dp_base, XDPTX_MAINSTRM_VRES_REG, mode->vdisplay);
+
+	xlnx_dp_write(dp_base, XDPTX_MAINSTRM_HSTART_REG,
+		      mode->htotal - mode->hsync_start);
+	xlnx_dp_write(dp_base, XDPTX_MAINSTRM_VSTART_REG,
+		      mode->vtotal - mode->vsync_start);
+	xlnx_dp_update_misc(dp);
+
+	reg = drm_dp_bw_code_to_link_rate(dp->mode.bw_code);
+	xlnx_dp_write(dp_base, XDPTX_N_VID_REG, reg);
+	xlnx_dp_write(dp_base, XDPTX_M_VID_REG, mode->clock);
+
+	/* In synchronous mode, set the dividers */
+	if (dp->config.misc0 & XDPTX_MAINSTRM_MISC0_MASK) {
+		reg = drm_dp_bw_code_to_link_rate(dp->mode.bw_code);
+		xlnx_dp_write(dp_base, XDPTX_N_VID_REG, reg);
+		xlnx_dp_write(dp_base, XDPTX_M_VID_REG, mode->clock);
+	}
+
+	if (mode->clock > 530000)
+		ppc = 4;
+	else if (mode->clock > 270000)
+		ppc = 2;
+	else
+		ppc = 1;
+
+	xlnx_dp_write(dp_base, XDPTX_USER_PIXELWIDTH_REG, ppc);
+	dp->config.ppc = ppc;
+
+	wpl = (mode->hdisplay * dp->config.bpp + 15) / 16;
+	reg = wpl + wpl % lane_cnt - lane_cnt;
+	xlnx_dp_write(dp_base, XDPTX_USER_DATACNTPERLANE_REG, reg);
+	xlnx_dp_write(dp_base, XDPTX_TRANSFER_UNITSIZE_REG, 0x40);
+}
+
+/*
+ * DRM connector functions
+ */
+static enum drm_connector_status
+xlnx_dp_connector_detect(struct drm_connector *connector, bool force)
+{
+	struct xlnx_dp *dp = connector_to_dp(connector);
+	struct xlnx_dp_link_config *link_config = &dp->link_config;
+	struct phy_configure_opts_dp *phy_cfg = &dp->phy_opts.dp;
+	u32 state, i;
+	int ret;
+
+	/*
+	 * This is from heuristic. It takes some delay (ex, 100 ~ 500 msec) to
+	 * get the HPD signal with some monitors.
+	 */
+	for (i = 0; i < 10; i++) {
+		state = xlnx_dp_read(dp->dp_base, XDPTX_INTR_SIGSTATE_REG);
+		if (state & XDPTX_INTR_SIGHPDSTATE)
+			break;
+		msleep(100);
+	}
+	if (state & XDPTX_INTR_SIGHPDSTATE) {
+		ret = drm_dp_dpcd_read(&dp->aux, 0x0, dp->dpcd,
+				       sizeof(dp->dpcd));
+		if (ret < 0) {
+			dev_info(dp->dev, "DPCD read failes");
+			goto disconnected;
+		}
+		dp->dpcd[1] = 0x1e;
+		link_config->max_rate = min_t(int,
+					      drm_dp_max_link_rate(dp->dpcd),
+					      dp->config.max_link_rate);
+		link_config->max_lanes = min_t(u8,
+					       drm_dp_max_lane_count(dp->dpcd),
+					       dp->config.max_lanes);
+		dp->status = connector_status_connected;
+
+		switch (dp->dpcd[1]) {
+		case DP_LINK_BW_1_62:
+			phy_cfg->link_rate = 1620;
+			break;
+		case DP_LINK_BW_2_7:
+			phy_cfg->link_rate = 2700;
+			break;
+		case DP_LINK_BW_5_4:
+			phy_cfg->link_rate = 5400;
+			break;
+		case DP_LINK_BW_8_1:
+			phy_cfg->link_rate = 8100;
+			break;
+		default:
+			dev_err(dp->dev, "invalid link rate\n");
+			break;
+		}
+
+		phy_cfg->set_rate = 1;
+		phy_cfg->lanes = link_config->max_lanes;
+		phy_configure(dp->phy[0], &dp->phy_opts);
+
+		return connector_status_connected;
+	}
+disconnected:
+	dp->status = connector_status_disconnected;
+
+	return connector_status_disconnected;
+}
+
+static int xlnx_dp_connector_get_modes(struct drm_connector *connector)
+{
+	struct xlnx_dp *dp = connector_to_dp(connector);
+	struct edid *edid;
+	int ret;
+
+	edid = drm_get_edid(connector, &dp->aux.ddc);
+	if (!edid) {
+		drm_connector_update_edid_property(connector, NULL);
+		return 0;
+	}
+
+	drm_connector_update_edid_property(connector, edid);
+	ret = drm_add_edid_modes(connector, edid);
+	kfree(edid);
+
+	return ret;
+}
+
+static struct drm_encoder *
+xlnx_dp_connector_best_encoder(struct drm_connector *connector)
+{
+	struct xlnx_dp *dp = connector_to_dp(connector);
+
+	return &dp->encoder;
+}
+
+static int xlnx_dp_connector_mode_valid(struct drm_connector *connector,
+					struct drm_display_mode *mode)
+{
+	struct xlnx_dp *dp = connector_to_dp(connector);
+	u8 max_lanes = dp->link_config.max_lanes;
+	u8 bpp = dp->config.bpp;
+	int max_rate = dp->link_config.max_rate;
+	int rate;
+
+	if (mode->clock > XDPTX_MAX_FREQ) {
+		dev_info(dp->dev, "filtered the mode, %s,for high pixel rate\n",
+			 mode->name);
+		drm_mode_debug_printmodeline(mode);
+		return MODE_CLOCK_HIGH;
+	}
+
+	/* check with link rate and lane count */
+	rate = XDPTX_MAX_RATE(max_rate, max_lanes, bpp);
+	if (mode->clock > rate) {
+		dev_dbg(dp->dev, "filtered the mode, %s,for high pixel rate\n",
+			mode->name);
+		drm_mode_debug_printmodeline(mode);
+
+		return MODE_CLOCK_HIGH;
+	}
+
+	return MODE_OK;
+}
+
+static void xlnx_dp_connector_destroy(struct drm_connector *connector)
+{
+	drm_connector_unregister(connector);
+	drm_connector_cleanup(connector);
+}
+
+static int
+xlnx_dp_connector_atomic_set_property(struct drm_connector *connector,
+				      struct drm_connector_state *state,
+				      struct drm_property *property,
+				      uint64_t val)
+{
+	struct xlnx_dp *dp = connector_to_dp(connector);
+	unsigned int bpc;
+
+	if (property == dp->sync_prop) {
+		xlnx_dp_set_sync_mode(dp, val);
+	} else if (property == dp->bpc_prop) {
+		bpc = xlnx_dp_set_bpc(dp, val);
+		if (bpc) {
+			drm_object_property_set_value(&connector->base,
+						      property, bpc);
+			return -EINVAL;
+		}
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+xlnx_dp_connector_atomic_get_property(struct drm_connector *connector,
+				      const struct drm_connector_state *state,
+					struct drm_property *property,
+					uint64_t *val)
+{
+	struct xlnx_dp *dp = connector_to_dp(connector);
+
+	if (property == dp->sync_prop)
+		*val = (dp->config.misc0 & XDPTX_MAINSTRM_MISC0_MASK);
+	else if (property == dp->bpc_prop)
+		*val = dp->config.bpc;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+static const struct drm_connector_funcs xlnx_dp_connector_funcs = {
+	.detect			= xlnx_dp_connector_detect,
+	.fill_modes		= drm_helper_probe_single_connector_modes,
+	.destroy		= xlnx_dp_connector_destroy,
+	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
+	.reset			= drm_atomic_helper_connector_reset,
+	.atomic_set_property	= xlnx_dp_connector_atomic_set_property,
+	.atomic_get_property	= xlnx_dp_connector_atomic_get_property,
+};
+
+static struct drm_connector_helper_funcs xlnx_dp_connector_helper_funcs = {
+	.get_modes	= xlnx_dp_connector_get_modes,
+	.best_encoder	= xlnx_dp_connector_best_encoder,
+	.mode_valid	= xlnx_dp_connector_mode_valid,
+};
+
+static void xlnx_dp_encoder_enable(struct drm_encoder *encoder)
+{
+	struct xlnx_dp *dp = encoder_to_dp(encoder);
+	struct drm_dp_link link;
+	void __iomem *dp_base = dp->dp_base;
+	unsigned int i;
+	int ret = 0;
+	unsigned int xlnx_dp_power_on_delay_ms = 4;
+
+	pm_runtime_get_sync(dp->dev);
+	dp->enabled = true;
+	xlnx_dp_init_aux(dp);
+	if (dp->status == connector_status_connected) {
+		for (i = 0; i < 3; i++) {
+			ret = drm_dp_link_power_down(&dp->aux, &link);
+			ret = drm_dp_link_power_up(&dp->aux, &link);
+			if (ret == 0)
+				break;
+			usleep_range(300, 500);
+		}
+		/* Some monitors take time to wake up properly */
+		msleep(xlnx_dp_power_on_delay_ms);
+	}
+	if (ret < 0)
+		dev_err(dp->dev, "DP aux failed\n");
+	else
+		xlnx_dp_train_loop(dp);
+
+	/* Enable VTC */
+	xlnx_dp_set(dp->dp_base,
+		    XDPTX_VTC_BASE + XDPTX_VTC_CTL, XDPTX_VTC_CTL_GE);
+	xlnx_dp_write(dp_base, XDPTX_MAINSTRM_ENABLE_REG, 1);
+}
+
+static void xlnx_dp_encoder_disable(struct drm_encoder *encoder)
+{
+	struct xlnx_dp *dp = encoder_to_dp(encoder);
+	void __iomem *dp_base = dp->dp_base;
+
+	xlnx_dp_write(dp_base, XDPTX_MAINSTRM_ENABLE_REG, 0);
+	dp->enabled = false;
+	cancel_delayed_work(&dp->hpd_work);
+	/* Disable VTC */
+	xlnx_dp_clr(dp->dp_base,
+		    XDPTX_VTC_BASE + XDPTX_VTC_CTL, XDPTX_VTC_CTL_GE);
+	pm_runtime_put_sync(dp->dev);
+}
+
+static void
+xlnx_dp_encoder_atomic_mode_set(struct drm_encoder *encoder,
+				struct drm_crtc_state *crtc_state,
+				struct drm_connector_state *connector_state)
+{
+	struct xlnx_dp *dp = encoder_to_dp(encoder);
+	struct drm_display_mode *mode = &crtc_state->mode;
+	struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
+	u8 max_lanes = dp->link_config.max_lanes;
+	u8 bpp = dp->config.bpp;
+	int rate, max_rate = dp->link_config.max_rate;
+	int ret;
+	u32 clock;
+	u32 drm_fourcc;
+
+	/*
+	 * This assumes that there is no conversion  between framebuffer
+	 * and DP Tx
+	 */
+	drm_fourcc = encoder->crtc->primary->state->fb->format->format;
+
+	xlnx_dp_set_color(dp, drm_fourcc);
+
+	rate = XDPTX_MAX_RATE(max_rate, max_lanes, bpp);
+	if (mode->clock > rate) {
+		dev_err(dp->dev, "the mode, %s,has too high pixel rate\n",
+			mode->name);
+		drm_mode_debug_printmodeline(mode);
+	}
+	ret = xlnx_dp_mode_configure(dp, adjusted_mode->clock, 0);
+	if (ret < 0)
+		return;
+
+	/* The timing register should be programmed always */
+	xlnx_dp_encoder_mode_set_stream(dp, adjusted_mode);
+	xlnx_dp_encoder_mode_set_transfer_unit(dp, adjusted_mode);
+	clock = adjusted_mode->clock * 1000;
+	clk_set_rate(dp->tx_vid_clk, clock / dp->config.ppc);
+
+	xlnx_dp_vtc_set_timing(dp, adjusted_mode);
+}
+
+static const struct drm_encoder_funcs xlnx_dp_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+static const struct drm_encoder_helper_funcs xlnx_dp_encoder_helper_funcs = {
+	.enable			= xlnx_dp_encoder_enable,
+	.disable		= xlnx_dp_encoder_disable,
+	.atomic_mode_set	= xlnx_dp_encoder_atomic_mode_set,
+};
+
+static void xlnx_dp_hpd_work_func(struct work_struct *work)
+{
+	struct xlnx_dp *dp;
+
+	dp = container_of(work, struct xlnx_dp, hpd_work.work);
+
+	if (dp->drm)
+		drm_helper_hpd_irq_event(dp->drm);
+}
+
+static struct drm_prop_enum_list xlnx_dp_bpc_enum[] = {
+	{ 6, "6BPC" },
+	{ 8, "8BPC" },
+	{ 10, "10BPC" },
+	{ 12, "12BPC" },
+};
+
+static int xlnx_dp_bind(struct device *dev, struct device *master, void *data)
+{
+	struct xlnx_dp *dp = dev_get_drvdata(dev);
+	struct drm_encoder *encoder = &dp->encoder;
+	struct drm_connector *connector = &dp->connector;
+	struct drm_device *drm = data;
+	unsigned int ret;
+
+	encoder->possible_crtcs = 1;
+	drm_encoder_init(drm, encoder, &xlnx_dp_encoder_funcs,
+			 DRM_MODE_ENCODER_TMDS, NULL);
+	drm_encoder_helper_add(encoder, &xlnx_dp_encoder_helper_funcs);
+
+	connector->polled = DRM_CONNECTOR_POLL_HPD;
+	ret = drm_connector_init(encoder->dev, connector,
+				 &xlnx_dp_connector_funcs,
+				 DRM_MODE_CONNECTOR_DisplayPort);
+	if (ret) {
+		dev_err(dp->dev, "failed to initialize the drm connector");
+		goto error_encoder;
+	}
+
+	drm_connector_helper_add(connector, &xlnx_dp_connector_helper_funcs);
+	drm_connector_register(connector);
+	drm_connector_attach_encoder(connector, encoder);
+	connector->dpms = DRM_MODE_DPMS_OFF;
+
+	dp->drm = drm;
+	dp->sync_prop = drm_property_create_bool(drm, 0, "sync");
+	dp->bpc_prop = drm_property_create_enum(drm, 0, "bpc",
+						xlnx_dp_bpc_enum,
+						ARRAY_SIZE(xlnx_dp_bpc_enum));
+	dp->config.misc0 &= ~XDPTX_MAINSTRM_MISC0_MASK;
+	drm_object_attach_property(&connector->base, dp->sync_prop, false);
+	ret = xlnx_dp_set_bpc(dp, 8);
+	drm_object_attach_property(&connector->base, dp->bpc_prop,
+				   ret ? ret : 8);
+	xlnx_dp_update_bpp(dp);
+
+	/* This enables interrupts, so should be called after DRM init */
+	ret = xlnx_dp_init_aux(dp);
+	if (ret) {
+		dev_err(dp->dev, "failed to initialize DP aux");
+		goto error_prop;
+	}
+	INIT_DELAYED_WORK(&dp->hpd_work, xlnx_dp_hpd_work_func);
+
+	return 0;
+
+error_prop:
+	drm_property_destroy(dp->drm, dp->bpc_prop);
+	drm_property_destroy(dp->drm, dp->sync_prop);
+	xlnx_dp_connector_destroy(&dp->connector);
+error_encoder:
+	drm_encoder_cleanup(&dp->encoder);
+
+	return ret;
+}
+
+static void xlnx_dp_unbind(struct device *dev,
+			   struct device *master, void *data)
+{
+	struct xlnx_dp *dp = dev_get_drvdata(dev);
+
+	cancel_delayed_work_sync(&dp->hpd_work);
+	xlnx_dp_exit_aux(dp);
+	drm_property_destroy(dp->drm, dp->bpc_prop);
+	drm_property_destroy(dp->drm, dp->sync_prop);
+	xlnx_dp_connector_destroy(&dp->connector);
+	drm_encoder_cleanup(&dp->encoder);
+}
+
+static int xlnx_dp_txconnected(struct xlnx_dp *dp)
+{
+	u32 status;
+	u8 retries = 0;
+
+	do {
+		status = xlnx_dp_read(dp->dp_base,
+				      XDPTX_INTR_SIGSTATE_REG) & 0x1;
+		if (retries > 5)
+			return false;
+		retries++;
+		usleep_range(1000, 1100);
+	} while (status == 0);
+
+	return true;
+}
+
+static irqreturn_t xlnx_dp_irq_handler(int irq, void *data)
+{
+	struct xlnx_dp *dp = (struct xlnx_dp *)data;
+	u32 intrstatus;
+	u32 hpdduration;
+
+	/* Determine what kind of interrupt occurred. */
+	intrstatus = xlnx_dp_read(dp->dp_base, XDPTX_INTR_STATUS_REG);
+
+	if (!intrstatus)
+		return IRQ_NONE;
+	if (intrstatus & XDPTX_INTR_HPDEVENT_MASK) {
+		dev_dbg_ratelimited(dp->dev, "hpdevent detected\n");
+	} else if (intrstatus & XDPTX_INTR_HPDPULSE_MASK &&
+		   xlnx_dp_txconnected(dp)) {
+		/*
+		 * Some monitors give HPD pulse repeatedly which cause
+		 * HPD pulse function to be executed huge number of times.
+		 * Hence HPD pulse interrupt is disabled if pulse duration
+		 * is longer than 500 microseconds.
+		 */
+		hpdduration = xlnx_dp_read(dp->dp_base, XDPTX_HPD_DURATION_REG);
+		if (hpdduration >= 500)
+			xlnx_dp_write(dp->dp_base, XDPTX_INTR_MASK_REG, 0x10);
+	}
+
+	if (intrstatus & XDPTX_INTR_CHBUFUNDFW_MASK)
+		dev_dbg_ratelimited(dp->dev, "underflow interrupt\n");
+	if (intrstatus & XDPTX_INTR_CHBUFOVFW_MASK)
+		dev_dbg_ratelimited(dp->dev, "overflow interrupt\n");
+
+	if (intrstatus & XDPTX_INTR_HPDEVENT_MASK)
+		schedule_delayed_work(&dp->hpd_work, 0);
+
+	return IRQ_HANDLED;
+}
+
+static const struct component_ops xlnx_dp_component_ops = {
+	.bind	= xlnx_dp_bind,
+	.unbind	= xlnx_dp_unbind,
+};
+
+static int xlnx_dp_parse_of(struct xlnx_dp *dp)
+{
+	struct xlnx_dp_config *config = &dp->config;
+	struct device_node *node = dp->dev->of_node;
+	u32 bpc;
+	int ret;
+
+	ret = of_property_read_u32(node, "xlnx,max-lanes", &config->max_lanes);
+	if (ret < 0) {
+		dev_err(dp->dev, "No lane count in DT\n");
+		return ret;
+	}
+	if (config->max_lanes != 1 && config->max_lanes != 2 &&
+	    config->max_lanes != 4) {
+		dev_err(dp->dev, "Invalid max lanes in DT\n");
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32(node, "xlnx,max-link-rate",
+				   &config->max_link_rate);
+	if (ret < 0) {
+		dev_err(dp->dev, "No link rate in DT\n");
+		return ret;
+	}
+	if (config->max_link_rate != XDPTX_REDUCED_BIT_RATE &&
+	    config->max_link_rate != XDPTX_HIGH_BIT_RATE_1 &&
+	    config->max_link_rate != XDPTX_HIGH_BIT_RATE_2 &&
+	    config->max_link_rate != XDPTX_HIGH_BIT_RATE_3) {
+		dev_err(dp->dev, "Invalid link rate in DT\n");
+		return -EINVAL;
+	}
+
+	xlnx_dp_set_color(dp, DRM_FORMAT_RGB888);
+
+	ret = of_property_read_u32(node, "xlnx,bpc", &bpc);
+	if (ret < 0) {
+		dev_err(dp->dev, "No color depth(bpc) in DT\n");
+		return ret;
+	}
+
+	switch (bpc) {
+	case 6:
+		config->misc0 |= XDPTX_MISC0_BPC6_MASK;
+		break;
+	case 8:
+		config->misc0 |= XDPTX_MISC0_BPC8_MASK;
+		break;
+	case 10:
+		config->misc0 |= XDPTX_MISC0_BPC10_MASK;
+		break;
+	case 12:
+		config->misc0 |= XDPTX_MISC0_BPC12_MASK;
+		break;
+	case 16:
+		config->misc0 |= XDPTX_MISC0_BPC16_MASK;
+		break;
+	default:
+		dev_err(dp->dev, "Not supported color depth in DT\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int xlnx_dp_probe(struct platform_device *pdev)
+{
+	struct xlnx_dp *dp;
+	struct resource *res;
+	unsigned int i;
+	int irq, ret;
+
+	dp = devm_kzalloc(&pdev->dev, sizeof(*dp), GFP_KERNEL);
+	if (!dp)
+		return -ENOMEM;
+
+	dp->dpms = DRM_MODE_DPMS_OFF;
+	dp->status = connector_status_disconnected;
+	dp->dev = &pdev->dev;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dp_base");
+	dp->dp_base = devm_ioremap_resource(dp->dev, res);
+	if (IS_ERR(dp->dp_base)) {
+		dev_err(&pdev->dev, "couldn't map DisplayPort registers\n");
+		return -ENODEV;
+	}
+
+	ret = xlnx_dp_parse_of(dp);
+	if (ret < 0)
+		return ret;
+
+	dp->axi_lite_clk = devm_clk_get(&pdev->dev, "s_axi_aclk");
+	if (IS_ERR(dp->axi_lite_clk))
+		return PTR_ERR(dp->axi_lite_clk);
+
+	dp->tx_vid_clk = devm_clk_get(&pdev->dev, "tx_vid_clk");
+	if (IS_ERR(dp->tx_vid_clk))
+		dev_err(dp->dev, "failed to get vid clk stream1\n");
+
+	platform_set_drvdata(pdev, dp);
+	xlnx_dp_write(dp->dp_base, XDPTX_ENABLE_REG, 0);
+	xlnx_dp_write(dp->dp_base, XDPTX_MAINSTRM_ENABLE_REG, 0);
+
+	dp->tx_link_config.vs_level = 0;
+	dp->tx_link_config.pe_level = 0;
+
+	/* acquire vphy lanes */
+	for (i = 0; i < dp->config.max_lanes; i++) {
+		char phy_name[16];
+
+		snprintf(phy_name, sizeof(phy_name), "dp-phy%d", i);
+		dp->phy[i] = devm_phy_get(dp->dev, phy_name);
+		if (IS_ERR(dp->phy[i])) {
+			ret = PTR_ERR(dp->phy[i]);
+			dp->phy[i] = NULL;
+			if (ret == -EPROBE_DEFER) {
+				dev_info(dp->dev,
+					 "xvphy not ready -EPROBE_DEFER\n");
+				return ret;
+			}
+			if (ret != -EPROBE_DEFER)
+				dev_err(dp->dev, "failed to get phy lane %s i %d, error %d\n",
+					phy_name, i, ret);
+			goto error_phy;
+		}
+	}
+
+	ret = xlnx_dp_init_phy(dp);
+	if (ret)
+		goto error_phy;
+
+	ret = clk_prepare_enable(dp->axi_lite_clk);
+	if (ret) {
+		dev_err(dp->dev, "failed to enable axi_lite_clk (%d)\n", ret);
+		return ret;
+	}
+
+	ret = clk_prepare_enable(dp->tx_vid_clk);
+	if (ret) {
+		dev_err(dp->dev, "failed to enable tx_vid_clk (%d)\n", ret);
+		goto tx_vid_clk_err;
+	}
+
+	dp->aux.name = "Xlnx DP AUX";
+	dp->aux.dev = dp->dev;
+	dp->aux.transfer = xlnx_dp_aux_transfer;
+	ret = drm_dp_aux_register(&dp->aux);
+	if (ret < 0) {
+		dev_err(dp->dev, "failed to initialize DP aux\n");
+		goto error;
+	}
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		ret = irq;
+		goto error;
+	}
+	ret = devm_request_threaded_irq(dp->dev, irq, NULL,
+					xlnx_dp_irq_handler, IRQF_ONESHOT,
+					dev_name(dp->dev), dp);
+
+	if (ret < 0)
+		goto error;
+
+	return component_add(&pdev->dev, &xlnx_dp_component_ops);
+
+tx_vid_clk_err:
+	clk_disable_unprepare(dp->axi_lite_clk);
+error:
+	drm_dp_aux_unregister(&dp->aux);
+error_phy:
+	dev_dbg(&pdev->dev, "xdprxss_probe() error_phy:\n");
+	xlnx_dp_exit_phy(dp);
+
+	return ret;
+}
+
+static int xlnx_dp_remove(struct platform_device *pdev)
+{
+	struct xlnx_dp *dp = platform_get_drvdata(pdev);
+
+	xlnx_dp_write(dp->dp_base, XDPTX_ENABLE_REG, 0);
+	drm_dp_aux_unregister(&dp->aux);
+	xlnx_dp_exit_phy(dp);
+	component_del(&pdev->dev, &xlnx_dp_component_ops);
+
+	return 0;
+}
+
+static const struct of_device_id xlnx_dp_of_match[] = {
+	{ .compatible = "xlnx,v-dp-txss-3.0", },
+	{ /* end of table */ }
+};
+MODULE_DEVICE_TABLE(of, xlnx_dp_of_match);
+
+static struct platform_driver dp_tx_driver = {
+	.probe = xlnx_dp_probe,
+	.remove = xlnx_dp_remove,
+	.driver = {
+		.name = "xlnx-dp-tx",
+		.of_match_table = xlnx_dp_of_match,
+	},
+};
+
+module_platform_driver(dp_tx_driver);
+
+MODULE_AUTHOR("Rajesh Gugulothu <gugulothu.rajesh@xilinx.com>");
+MODULE_DESCRIPTION("Xilinx FPGA DisplayPort Tx Driver");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/xlnx/xlnx_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/xlnx/xlnx_drv.c
@@ -0,0 +1,542 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx DRM KMS Driver
+ *
+ *  Copyright (C) 2013 - 2018 Xilinx, Inc.
+ *
+ *  Author: Hyun Woo Kwon <hyun.kwon@xilinx.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_of.h>
+#include <drm/drm_probe_helper.h>
+
+#include <linux/component.h>
+#include <linux/device.h>
+#include <linux/dma-buf.h>
+#include <linux/dma-resv.h>
+#include <linux/module.h>
+#include <linux/of_graph.h>
+#include <linux/platform_device.h>
+
+#include "xlnx_bridge.h"
+#include "xlnx_crtc.h"
+#include "xlnx_drv.h"
+#include "xlnx_fb.h"
+#include "xlnx_gem.h"
+
+#define DRIVER_NAME	"xlnx"
+#define DRIVER_DESC	"Xilinx DRM KMS Driver"
+#define DRIVER_DATE	"20130509"
+#define DRIVER_MAJOR	1
+#define DRIVER_MINOR	0
+
+static uint xlnx_fbdev_vres = 2;
+module_param_named(fbdev_vres, xlnx_fbdev_vres, uint, 0444);
+MODULE_PARM_DESC(fbdev_vres,
+		 "fbdev virtual resolution multiplier for fb (default: 2)");
+
+/**
+ * struct xlnx_drm - Xilinx DRM private data
+ * @drm: DRM core
+ * @crtc: Xilinx DRM CRTC helper
+ * @fb: DRM fb helper
+ * @master: logical master device for pipeline
+ * @suspend_state: atomic state for suspend / resume
+ * @master_count: Counter to track number of fake master instances
+ */
+struct xlnx_drm {
+	struct drm_device *drm;
+	struct xlnx_crtc_helper *crtc;
+	struct drm_fb_helper *fb;
+	struct platform_device *master;
+	struct drm_atomic_state *suspend_state;
+	u32 master_count;
+};
+
+/**
+ * xlnx_get_crtc_helper - Return the crtc helper instance
+ * @drm: DRM device
+ *
+ * Return: the crtc helper instance
+ */
+struct xlnx_crtc_helper *xlnx_get_crtc_helper(struct drm_device *drm)
+{
+	struct xlnx_drm *xlnx_drm = drm->dev_private;
+
+	return xlnx_drm->crtc;
+}
+
+/**
+ * xlnx_get_align - Return the align requirement through CRTC helper
+ * @drm: DRM device
+ *
+ * Return: the alignment requirement
+ */
+unsigned int xlnx_get_align(struct drm_device *drm)
+{
+	struct xlnx_drm *xlnx_drm = drm->dev_private;
+
+	return xlnx_crtc_helper_get_align(xlnx_drm->crtc);
+}
+
+/**
+ * xlnx_get_format - Return the current format of CRTC
+ * @drm: DRM device
+ *
+ * Return: the current CRTC format
+ */
+uint32_t xlnx_get_format(struct drm_device *drm)
+{
+	struct xlnx_drm *xlnx_drm = drm->dev_private;
+
+	return xlnx_crtc_helper_get_format(xlnx_drm->crtc);
+}
+
+static void xlnx_output_poll_changed(struct drm_device *drm)
+{
+	struct xlnx_drm *xlnx_drm = drm->dev_private;
+
+	if (xlnx_drm->fb)
+		drm_fb_helper_hotplug_event(xlnx_drm->fb);
+}
+
+static const struct drm_mode_config_funcs xlnx_mode_config_funcs = {
+	.fb_create		= xlnx_fb_create,
+	.output_poll_changed	= xlnx_output_poll_changed,
+	.atomic_check		= drm_atomic_helper_check,
+	.atomic_commit		= drm_atomic_helper_commit,
+};
+
+static void xlnx_mode_config_init(struct drm_device *drm)
+{
+	struct xlnx_drm *xlnx_drm = drm->dev_private;
+	struct xlnx_crtc_helper *crtc = xlnx_drm->crtc;
+
+	drm->mode_config.min_width = 0;
+	drm->mode_config.min_height = 0;
+	drm->mode_config.max_width = xlnx_crtc_helper_get_max_width(crtc);
+	drm->mode_config.max_height = xlnx_crtc_helper_get_max_height(crtc);
+	drm->mode_config.cursor_width =
+		xlnx_crtc_helper_get_cursor_width(crtc);
+	drm->mode_config.cursor_height =
+		xlnx_crtc_helper_get_cursor_height(crtc);
+}
+
+static int xlnx_drm_open(struct drm_device *dev, struct drm_file *file)
+{
+	struct xlnx_drm *xlnx_drm = dev->dev_private;
+
+	/* This is a hacky way to allow the root user to run as a master */
+	if (!(drm_is_primary_client(file) && !dev->master) &&
+	    !file->is_master && capable(CAP_SYS_ADMIN)) {
+		file->is_master = 1;
+		xlnx_drm->master_count++;
+	}
+
+	return 0;
+}
+
+static int xlnx_drm_release(struct inode *inode, struct file *filp)
+{
+	struct drm_file *file = filp->private_data;
+	struct drm_minor *minor = file->minor;
+	struct drm_device *drm = minor->dev;
+	struct xlnx_drm *xlnx_drm = drm->dev_private;
+
+	if (file->is_master && xlnx_drm->master_count) {
+		xlnx_drm->master_count--;
+		file->is_master = 0;
+	}
+
+	return drm_release(inode, filp);
+}
+
+static void xlnx_lastclose(struct drm_device *drm)
+{
+	struct xlnx_drm *xlnx_drm = drm->dev_private;
+
+	if (xlnx_drm->fb)
+		drm_fb_helper_restore_fbdev_mode_unlocked(xlnx_drm->fb);
+}
+
+static const struct file_operations xlnx_fops = {
+	.owner		= THIS_MODULE,
+	.open		= drm_open,
+	.release	= xlnx_drm_release,
+	.unlocked_ioctl	= drm_ioctl,
+	.mmap		= drm_gem_cma_mmap,
+	.poll		= drm_poll,
+	.read		= drm_read,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= drm_compat_ioctl,
+#endif
+	.llseek		= noop_llseek,
+};
+
+static struct drm_driver xlnx_drm_driver = {
+	.driver_features		= DRIVER_MODESET | DRIVER_GEM |
+					  DRIVER_ATOMIC,
+	.open				= xlnx_drm_open,
+	.lastclose			= xlnx_lastclose,
+
+	.prime_handle_to_fd		= drm_gem_prime_handle_to_fd,
+	.prime_fd_to_handle		= drm_gem_prime_fd_to_handle,
+	.gem_prime_export		= drm_gem_prime_export,
+	.gem_prime_import		= drm_gem_prime_import,
+	.gem_prime_get_sg_table		= drm_gem_cma_prime_get_sg_table,
+	.gem_prime_import_sg_table	= drm_gem_cma_prime_import_sg_table,
+	.gem_prime_vmap			= drm_gem_cma_prime_vmap,
+	.gem_prime_vunmap		= drm_gem_cma_prime_vunmap,
+	.gem_prime_mmap			= drm_gem_cma_prime_mmap,
+	.gem_free_object		= drm_gem_cma_free_object,
+	.gem_vm_ops			= &drm_gem_cma_vm_ops,
+	.dumb_create			= xlnx_gem_cma_dumb_create,
+	.dumb_destroy			= drm_gem_dumb_destroy,
+
+	.fops				= &xlnx_fops,
+
+	.name				= DRIVER_NAME,
+	.desc				= DRIVER_DESC,
+	.date				= DRIVER_DATE,
+	.major				= DRIVER_MAJOR,
+	.minor				= DRIVER_MINOR,
+};
+
+static int xlnx_bind(struct device *dev)
+{
+	struct xlnx_drm *xlnx_drm;
+	struct drm_device *drm;
+	const struct drm_format_info *info;
+	struct platform_device *master = to_platform_device(dev);
+	struct platform_device *pdev = to_platform_device(dev->parent);
+	int ret;
+	u32 format;
+
+	drm = drm_dev_alloc(&xlnx_drm_driver, &pdev->dev);
+	if (IS_ERR(drm))
+		return PTR_ERR(drm);
+
+	xlnx_drm = devm_kzalloc(drm->dev, sizeof(*xlnx_drm), GFP_KERNEL);
+	if (!xlnx_drm) {
+		ret = -ENOMEM;
+		goto err_drm;
+	}
+
+	drm_mode_config_init(drm);
+	drm->mode_config.funcs = &xlnx_mode_config_funcs;
+
+	ret = drm_vblank_init(drm, 1);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to initialize vblank\n");
+		goto err_xlnx_drm;
+	}
+
+	drm->irq_enabled = 1;
+	drm->dev_private = xlnx_drm;
+	xlnx_drm->drm = drm;
+	xlnx_drm->master = master;
+	drm_kms_helper_poll_init(drm);
+	platform_set_drvdata(master, xlnx_drm);
+
+	xlnx_drm->crtc = xlnx_crtc_helper_init(drm);
+	if (IS_ERR(xlnx_drm->crtc)) {
+		ret = PTR_ERR(xlnx_drm->crtc);
+		goto err_xlnx_drm;
+	}
+
+	ret = component_bind_all(&master->dev, drm);
+	if (ret)
+		goto err_crtc;
+
+	xlnx_mode_config_init(drm);
+	drm_mode_config_reset(drm);
+	dma_set_mask(drm->dev, xlnx_crtc_helper_get_dma_mask(xlnx_drm->crtc));
+
+	format = xlnx_crtc_helper_get_format(xlnx_drm->crtc);
+	info = drm_format_info(format);
+	if (info && info->depth && info->cpp[0]) {
+		unsigned int align;
+
+		align = xlnx_crtc_helper_get_align(xlnx_drm->crtc);
+		xlnx_drm->fb = xlnx_fb_init(drm, info->cpp[0] * 8, 1, align,
+					    xlnx_fbdev_vres);
+		if (IS_ERR(xlnx_drm->fb)) {
+			dev_err(&pdev->dev,
+				"failed to initialize drm fb\n");
+			xlnx_drm->fb = NULL;
+		}
+	} else {
+		/* fbdev emulation is optional */
+		dev_info(&pdev->dev, "fbdev is not initialized\n");
+	}
+
+	ret = drm_dev_register(drm, 0);
+	if (ret < 0)
+		goto err_fb;
+
+	return 0;
+
+err_fb:
+	if (xlnx_drm->fb)
+		xlnx_fb_fini(xlnx_drm->fb);
+	component_unbind_all(drm->dev, drm);
+err_crtc:
+	xlnx_crtc_helper_fini(drm, xlnx_drm->crtc);
+err_xlnx_drm:
+	drm_mode_config_cleanup(drm);
+err_drm:
+	drm_dev_put(drm);
+	return ret;
+}
+
+static void xlnx_unbind(struct device *dev)
+{
+	struct xlnx_drm *xlnx_drm = dev_get_drvdata(dev);
+	struct drm_device *drm = xlnx_drm->drm;
+
+	drm_dev_unregister(drm);
+	component_unbind_all(&xlnx_drm->master->dev, drm);
+	if (xlnx_drm->fb) {
+		xlnx_fb_fini(xlnx_drm->fb);
+		xlnx_drm->fb = NULL;
+	}
+	xlnx_crtc_helper_fini(drm, xlnx_drm->crtc);
+	drm_kms_helper_poll_fini(drm);
+	drm_mode_config_cleanup(drm);
+	drm_dev_put(drm);
+}
+
+static const struct component_master_ops xlnx_master_ops = {
+	.bind	= xlnx_bind,
+	.unbind	= xlnx_unbind,
+};
+
+static int xlnx_of_component_probe(struct device *master_dev,
+				   int (*compare_of)(struct device *, void *),
+				   const struct component_master_ops *m_ops)
+{
+	struct device *dev = master_dev->parent;
+	struct device_node *ep, *port, *remote, *parent;
+	struct component_match *match = NULL;
+	int i;
+
+	if (!dev->of_node)
+		return -EINVAL;
+
+	component_match_add(master_dev, &match, compare_of, dev->of_node);
+
+	for (i = 0; ; i++) {
+		port = of_parse_phandle(dev->of_node, "ports", i);
+		if (!port)
+			break;
+
+		parent = port->parent;
+		if (!of_node_cmp(parent->name, "ports"))
+			parent = parent->parent;
+		parent = of_node_get(parent);
+
+		if (!of_device_is_available(parent)) {
+			of_node_put(parent);
+			of_node_put(port);
+			continue;
+		}
+
+		component_match_add(master_dev, &match, compare_of, parent);
+		of_node_put(parent);
+		of_node_put(port);
+	}
+
+	parent = dev->of_node;
+	for (i = 0; ; i++) {
+		parent = of_node_get(parent);
+		if (!of_device_is_available(parent)) {
+			of_node_put(parent);
+			continue;
+		}
+
+		for_each_endpoint_of_node(parent, ep) {
+			remote = of_graph_get_remote_port_parent(ep);
+			if (!remote || !of_device_is_available(remote) ||
+			    remote == dev->of_node) {
+				of_node_put(remote);
+				continue;
+			} else if (!of_device_is_available(remote->parent)) {
+				dev_warn(dev, "parent dev of %s unavailable\n",
+					 remote->full_name);
+				of_node_put(remote);
+				continue;
+			}
+			component_match_add(master_dev, &match, compare_of,
+					    remote);
+			of_node_put(remote);
+		}
+		of_node_put(parent);
+
+		port = of_parse_phandle(dev->of_node, "ports", i);
+		if (!port)
+			break;
+
+		parent = port->parent;
+		if (!of_node_cmp(parent->name, "ports"))
+			parent = parent->parent;
+		of_node_put(port);
+	}
+
+	return component_master_add_with_match(master_dev, m_ops, match);
+}
+
+static int xlnx_compare_of(struct device *dev, void *data)
+{
+	return dev->of_node == data;
+}
+
+static int xlnx_platform_probe(struct platform_device *pdev)
+{
+	return xlnx_of_component_probe(&pdev->dev, xlnx_compare_of,
+				       &xlnx_master_ops);
+}
+
+static int xlnx_platform_remove(struct platform_device *pdev)
+{
+	component_master_del(&pdev->dev, &xlnx_master_ops);
+	return 0;
+}
+
+static void xlnx_platform_shutdown(struct platform_device *pdev)
+{
+	component_master_del(&pdev->dev, &xlnx_master_ops);
+}
+
+static int __maybe_unused xlnx_pm_suspend(struct device *dev)
+{
+	struct xlnx_drm *xlnx_drm = dev_get_drvdata(dev);
+	struct drm_device *drm = xlnx_drm->drm;
+
+	drm_kms_helper_poll_disable(drm);
+
+	xlnx_drm->suspend_state = drm_atomic_helper_suspend(drm);
+	if (IS_ERR(xlnx_drm->suspend_state)) {
+		drm_kms_helper_poll_enable(drm);
+		return PTR_ERR(xlnx_drm->suspend_state);
+	}
+
+	return 0;
+}
+
+static int __maybe_unused xlnx_pm_resume(struct device *dev)
+{
+	struct xlnx_drm *xlnx_drm = dev_get_drvdata(dev);
+	struct drm_device *drm = xlnx_drm->drm;
+
+	drm_atomic_helper_resume(drm, xlnx_drm->suspend_state);
+	drm_kms_helper_poll_enable(drm);
+
+	return 0;
+}
+
+static const struct dev_pm_ops xlnx_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(xlnx_pm_suspend, xlnx_pm_resume)
+};
+
+static struct platform_driver xlnx_driver = {
+	.probe			= xlnx_platform_probe,
+	.remove			= xlnx_platform_remove,
+	.shutdown		= xlnx_platform_shutdown,
+	.driver			= {
+		.name		= "xlnx-drm",
+		.pm		= &xlnx_pm_ops,
+	},
+};
+
+/* bitmap for master id */
+static u32 xlnx_master_ids = GENMASK(31, 0);
+
+/**
+ * xlnx_drm_pipeline_init - Initialize the drm pipeline for the device
+ * @pdev: The platform device to initialize the drm pipeline device
+ *
+ * This function initializes the drm pipeline device, struct drm_device,
+ * on @pdev by creating a logical master platform device. The logical platform
+ * device acts as a master device to bind slave devices and represents
+ * the entire pipeline.
+ * The logical master uses the port bindings of the calling device to
+ * figure out the pipeline topology.
+ *
+ * Return: the logical master platform device if the drm device is initialized
+ * on @pdev. Error code otherwise.
+ */
+struct platform_device *xlnx_drm_pipeline_init(struct platform_device *pdev)
+{
+	struct platform_device *master;
+	int id, ret;
+
+	id = ffs(xlnx_master_ids);
+	if (!id)
+		return ERR_PTR(-ENOSPC);
+
+	master = platform_device_alloc("xlnx-drm", id - 1);
+	if (!master)
+		return ERR_PTR(-ENOMEM);
+
+	master->dev.parent = &pdev->dev;
+	ret = platform_device_add(master);
+	if (ret)
+		goto err_out;
+
+	WARN_ON(master->id != id - 1);
+	xlnx_master_ids &= ~BIT(master->id);
+	return master;
+
+err_out:
+	platform_device_unregister(master);
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(xlnx_drm_pipeline_init);
+
+/**
+ * xlnx_drm_pipeline_exit - Release the drm pipeline for the device
+ * @master: The master pipeline device to release
+ *
+ * Release the logical pipeline device returned by xlnx_drm_pipeline_init().
+ */
+void xlnx_drm_pipeline_exit(struct platform_device *master)
+{
+	xlnx_master_ids |= BIT(master->id);
+	platform_device_unregister(master);
+}
+EXPORT_SYMBOL_GPL(xlnx_drm_pipeline_exit);
+
+static int __init xlnx_drm_drv_init(void)
+{
+	xlnx_bridge_helper_init();
+	platform_driver_register(&xlnx_driver);
+	return 0;
+}
+
+static void __exit xlnx_drm_drv_exit(void)
+{
+	platform_driver_unregister(&xlnx_driver);
+	xlnx_bridge_helper_fini();
+}
+
+module_init(xlnx_drm_drv_init);
+module_exit(xlnx_drm_drv_exit);
+
+MODULE_AUTHOR("Xilinx, Inc.");
+MODULE_DESCRIPTION("Xilinx DRM KMS Driver");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/xlnx/xlnx_drv.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/xlnx/xlnx_drv.h
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx DRM KMS Header for Xilinx
+ *
+ *  Copyright (C) 2013 - 2018 Xilinx, Inc.
+ *
+ *  Author: Hyun Woo Kwon <hyunk@xilinx.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _XLNX_DRV_H_
+#define _XLNX_DRV_H_
+
+struct drm_device;
+struct xlnx_crtc_helper;
+
+struct platform_device *xlnx_drm_pipeline_init(struct platform_device *parent);
+void xlnx_drm_pipeline_exit(struct platform_device *pipeline);
+
+uint32_t xlnx_get_format(struct drm_device *drm);
+unsigned int xlnx_get_align(struct drm_device *drm);
+struct xlnx_crtc_helper *xlnx_get_crtc_helper(struct drm_device *drm);
+struct xlnx_bridge_helper *xlnx_get_bridge_helper(struct drm_device *drm);
+
+#endif /* _XLNX_DRV_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/xlnx/xlnx_dsi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/xlnx/xlnx_dsi.c
@@ -0,0 +1,1038 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx FPGA MIPI DSI Tx Controller driver.
+ *
+ * Copyright (C) 2017 - 2018 Xilinx, Inc.
+ *
+ * Author : Saurabh Sengar <saurabhs@xilinx.com>
+ *        : Siva Rajesh J <siva.rajesh.jarugula@xilinx.com>
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_probe_helper.h>
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/device.h>
+#include <linux/iopoll.h>
+#include <linux/of_device.h>
+#include <linux/of_graph.h>
+#include <linux/phy/phy.h>
+#include <video/mipi_display.h>
+#include <video/videomode.h>
+
+#include "xlnx_bridge.h"
+
+/* DSI Tx IP registers */
+#define XDSI_CCR			0x00
+#define XDSI_CCR_COREENB		BIT(0)
+#define XDSI_CCR_SOFTRST		BIT(1)
+#define XDSI_CCR_CRREADY		BIT(2)
+#define XDSI_CCR_CMDMODE		BIT(3)
+#define XDSI_CCR_DFIFORST		BIT(4)
+#define XDSI_CCR_CMDFIFORST		BIT(5)
+#define XDSI_PCR			0x04
+#define XDSI_PCR_VIDEOMODE(x)		(((x) & 0x3) << 3)
+#define XDSI_PCR_VIDEOMODE_MASK		(0x3 << 3)
+#define XDSI_PCR_VIDEOMODE_SHIFT	3
+#define XDSI_PCR_BLLPTYPE(x)		((x) << 5)
+#define XDSI_PCR_BLLPMODE(x)		((x) << 6)
+#define XDSI_PCR_EOTPENABLE(x)		((x) << 13)
+#define XDSI_GIER			0x20
+#define XDSI_ISR			0x24
+#define XDSI_IER			0x28
+#define XDSI_STR			0x2C
+#define XDSI_STR_RDY_SHPKT		BIT(6)
+#define XDSI_STR_RDY_LNGPKT		BIT(7)
+#define XDSI_STR_DFIFO_FULL		BIT(8)
+#define XDSI_STR_DFIFO_EMPTY		BIT(9)
+#define XDSI_STR_WAITFR_DATA		BIT(10)
+#define XDSI_STR_CMD_EXE_PGS		BIT(11)
+#define XDSI_STR_CCMD_PROC		BIT(12)
+#define XDSI_STR_LPKT_MASK		(0x5 << 7)
+#define XDSI_CMD			0x30
+#define XDSI_CMD_QUEUE_PACKET(x)	((x) & GENMASK(23, 0))
+#define XDSI_DFR			0x34
+#define XDSI_TIME1			0x50
+#define XDSI_TIME1_BLLP_BURST(x)	((x) & GENMASK(15, 0))
+#define XDSI_TIME1_HSA(x)		(((x) & GENMASK(15, 0)) << 16)
+#define XDSI_TIME2			0x54
+#define XDSI_TIME2_VACT(x)		((x) & GENMASK(15, 0))
+#define XDSI_TIME2_HACT(x)		(((x) & GENMASK(15, 0)) << 16)
+#define XDSI_HACT_MULTIPLIER		GENMASK(1, 0)
+#define XDSI_TIME3			0x58
+#define XDSI_TIME3_HFP(x)		((x) & GENMASK(15, 0))
+#define XDSI_TIME3_HBP(x)		(((x) & GENMASK(15, 0)) << 16)
+#define XDSI_TIME4			0x5c
+#define XDSI_TIME4_VFP(x)		((x) & GENMASK(7, 0))
+#define XDSI_TIME4_VBP(x)		(((x) & GENMASK(7, 0)) << 8)
+#define XDSI_TIME4_VSA(x)		(((x) & GENMASK(7, 0)) << 16)
+#define XDSI_LTIME			0x60
+#define XDSI_BLLP_TIME			0x64
+/*
+ * XDSI_NUM_DATA_T represents number of data types in the
+ * enum mipi_dsi_pixel_format in the MIPI DSI part of DRM framework.
+ */
+#define XDSI_NUM_DATA_T			4
+#define XDSI_VIDEO_MODE_SYNC_PULSE	0x0
+#define XDSI_VIDEO_MODE_SYNC_EVENT	0x1
+#define XDSI_VIDEO_MODE_BURST		0x2
+
+#define XDSI_DPHY_CLK_MIN	197000000000UL
+#define XDSI_DPHY_CLK_MAX	203000000000UL
+#define XDSI_DPHY_CLK_REQ	200000000000UL
+
+/* command timeout in usec */
+#define XDSI_CMD_TIMEOUT_VAL	(3000)
+
+/**
+ * struct xlnx_dsi - Core configuration DSI Tx subsystem device structure
+ * @encoder: DRM encoder structure
+ * @dsi_host: DSI host device
+ * @connector: DRM connector structure
+ * @panel_node: MIPI DSI device panel node
+ * @panel:  DRM panel structure
+ * @dev: device structure
+ * @iomem: Base address of DSI subsystem
+ * @lanes: number of active data lanes supported by DSI controller
+ * @cmdmode: command mode support
+ * @mode_flags: DSI operation mode related flags
+ * @format: pixel format for video mode of DSI controller
+ * @vm: videomode data structure
+ * @mul_factor: multiplication factor for HACT timing parameter
+ * @eotp_prop: configurable EoTP DSI parameter
+ * @bllp_mode_prop: configurable BLLP mode DSI parameter
+ * @bllp_type_prop: configurable BLLP type DSI parameter
+ * @video_mode_prop: configurable Video mode DSI parameter
+ * @bllp_burst_time_prop: Configurable BLLP time for burst mode
+ * @cmd_queue_prop: configurable command queue
+ * @eotp_prop_val: configurable EoTP DSI parameter value
+ * @bllp_mode_prop_val: configurable BLLP mode DSI parameter value
+ * @bllp_type_prop_val: configurable BLLP type DSI parameter value
+ * @video_mode_prop_val: configurable Video mode DSI parameter value
+ * @bllp_burst_time_prop_val: Configurable BLLP time for burst mode value
+ * @cmd_queue_prop_val: configurable command queue value
+ * @bridge: bridge structure
+ * @height_out: configurable bridge output height parameter
+ * @height_out_prop_val: configurable bridge output height parameter value
+ * @width_out: configurable bridge output width parameter
+ * @width_out_prop_val: configurable bridge output width parameter value
+ * @in_fmt: configurable bridge input media format
+ * @in_fmt_prop_val: configurable media bus format value
+ * @out_fmt: configurable bridge output media format
+ * @out_fmt_prop_val: configurable media bus format value
+ * @video_aclk: Video clock
+ * @dphy_clk_200M: 200MHz DPHY clock and AXI Lite clock
+ */
+struct xlnx_dsi {
+	struct drm_encoder encoder;
+	struct mipi_dsi_host dsi_host;
+	struct drm_connector connector;
+	struct device_node *panel_node;
+	struct drm_panel *panel;
+	struct device *dev;
+	void __iomem *iomem;
+	u32 lanes;
+	bool cmdmode;
+	u32 mode_flags;
+	enum mipi_dsi_pixel_format format;
+	struct videomode vm;
+	u32 mul_factor;
+	struct drm_property *eotp_prop;
+	struct drm_property *bllp_mode_prop;
+	struct drm_property *bllp_type_prop;
+	struct drm_property *video_mode_prop;
+	struct drm_property *bllp_burst_time_prop;
+	struct drm_property *cmd_queue_prop;
+	bool eotp_prop_val;
+	bool bllp_mode_prop_val;
+	bool bllp_type_prop_val;
+	u32 video_mode_prop_val;
+	u32 bllp_burst_time_prop_val;
+	u32 cmd_queue_prop_val;
+	struct xlnx_bridge *bridge;
+	struct drm_property *height_out;
+	u32 height_out_prop_val;
+	struct drm_property *width_out;
+	u32 width_out_prop_val;
+	struct drm_property *in_fmt;
+	u32 in_fmt_prop_val;
+	struct drm_property *out_fmt;
+	u32 out_fmt_prop_val;
+	struct clk *video_aclk;
+	struct clk *dphy_clk_200M;
+};
+
+#define host_to_dsi(host) container_of(host, struct xlnx_dsi, dsi_host)
+#define connector_to_dsi(c) container_of(c, struct xlnx_dsi, connector)
+#define encoder_to_dsi(e) container_of(e, struct xlnx_dsi, encoder)
+
+static inline void xlnx_dsi_writel(void __iomem *base, int offset, u32 val)
+{
+	writel(val, base + offset);
+}
+
+static inline u32 xlnx_dsi_readl(void __iomem *base, int offset)
+{
+	return readl(base + offset);
+}
+
+/**
+ * xlnx_dsi_set_config_parameters - Configure DSI Tx registers with parameters
+ * given from user application.
+ * @dsi: DSI structure having the updated user parameters
+ *
+ * This function takes the DSI structure having drm_property parameters
+ * configured from  user application and writes them into DSI IP registers.
+ */
+static void xlnx_dsi_set_config_parameters(struct xlnx_dsi *dsi)
+{
+	u32 reg;
+
+	reg = XDSI_PCR_EOTPENABLE(dsi->eotp_prop_val);
+	reg |= XDSI_PCR_VIDEOMODE(dsi->video_mode_prop_val);
+	reg |= XDSI_PCR_BLLPTYPE(dsi->bllp_type_prop_val);
+	reg |= XDSI_PCR_BLLPMODE(dsi->bllp_mode_prop_val);
+
+	xlnx_dsi_writel(dsi->iomem, XDSI_PCR, reg);
+	/*
+	 * Configure the burst time if video mode is burst.
+	 * HSA of TIME1 register is ignored in this mode.
+	 */
+	if (dsi->video_mode_prop_val == XDSI_VIDEO_MODE_BURST) {
+		reg = XDSI_TIME1_BLLP_BURST(dsi->bllp_burst_time_prop_val);
+		xlnx_dsi_writel(dsi->iomem, XDSI_TIME1, reg);
+	}
+
+	reg = XDSI_CMD_QUEUE_PACKET(dsi->cmd_queue_prop_val);
+	xlnx_dsi_writel(dsi->iomem, XDSI_CMD, reg);
+
+	dev_dbg(dsi->dev, "PCR register value is = %x\n",
+		xlnx_dsi_readl(dsi->iomem, XDSI_PCR));
+}
+
+/**
+ * xlnx_dsi_set_display_mode - Configure DSI timing registers
+ * @dsi: DSI structure having the updated user parameters
+ *
+ * This function writes the timing parameters of DSI IP which are
+ * retrieved from panel timing values.
+ */
+static void xlnx_dsi_set_display_mode(struct xlnx_dsi *dsi)
+{
+	struct videomode *vm = &dsi->vm;
+	u32 reg, video_mode;
+
+	reg = xlnx_dsi_readl(dsi->iomem, XDSI_PCR);
+	video_mode = (reg & XDSI_PCR_VIDEOMODE_MASK) >>
+		      XDSI_PCR_VIDEOMODE_SHIFT;
+
+	/* configure the HSA value only if non_burst_sync_pluse video mode */
+	if (!video_mode &&
+	    (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)) {
+		reg = XDSI_TIME1_HSA(vm->hsync_len);
+		xlnx_dsi_writel(dsi->iomem, XDSI_TIME1, reg);
+	}
+
+	reg = XDSI_TIME4_VFP(vm->vfront_porch) |
+	      XDSI_TIME4_VBP(vm->vback_porch) |
+	      XDSI_TIME4_VSA(vm->vsync_len);
+	xlnx_dsi_writel(dsi->iomem, XDSI_TIME4, reg);
+
+	reg = XDSI_TIME3_HFP(vm->hfront_porch) |
+	      XDSI_TIME3_HBP(vm->hback_porch);
+	xlnx_dsi_writel(dsi->iomem, XDSI_TIME3, reg);
+
+	dev_dbg(dsi->dev, "mul factor for parsed datatype is = %d\n",
+		(dsi->mul_factor) / 100);
+	/*
+	 * The HACT parameter received from panel timing values should be
+	 * divisible by 4. The reason for this is, the word count given as
+	 * input to DSI controller is HACT * mul_factor. The mul_factor is
+	 * 3, 2.25, 2.25, 2 respectively for RGB888, RGB666_L, RGB666_P and
+	 * RGB565.
+	 * e.g. for RGB666_L color format and 1080p, the word count is
+	 * 1920*2.25 = 4320 which is divisible by 4 and it is a valid input
+	 * to DSI controller. Based on this 2.25 mul factor, we come up with
+	 * the division factor of (XDSI_HACT_MULTIPLIER) as 4 for checking
+	 */
+	if ((vm->hactive & XDSI_HACT_MULTIPLIER) != 0)
+		dev_warn(dsi->dev, "Incorrect HACT will be programmed\n");
+
+	reg = XDSI_TIME2_HACT((vm->hactive) * (dsi->mul_factor) / 100) |
+	      XDSI_TIME2_VACT(vm->vactive);
+	xlnx_dsi_writel(dsi->iomem, XDSI_TIME2, reg);
+
+	dev_dbg(dsi->dev, "LCD size = %dx%d\n", vm->hactive, vm->vactive);
+}
+
+/**
+ * xlnx_dsi_set_display_enable - Enables the DSI Tx IP core enable
+ * register bit
+ * @dsi: DSI structure having the updated user parameters
+ *
+ * This function takes the DSI strucure and enables the core enable bit
+ * of core configuration register.
+ */
+static void xlnx_dsi_set_display_enable(struct xlnx_dsi *dsi)
+{
+	u32 reg;
+
+	reg = xlnx_dsi_readl(dsi->iomem, XDSI_CCR);
+	reg |= XDSI_CCR_COREENB;
+
+	xlnx_dsi_writel(dsi->iomem, XDSI_CCR, reg);
+	dev_dbg(dsi->dev, "MIPI DSI Tx controller is enabled.\n");
+}
+
+/**
+ * xlnx_dsi_set_display_disable - Disable the DSI Tx IP core enable
+ * register bit
+ * @dsi: DSI structure having the updated user parameters
+ *
+ * This function takes the DSI strucure and disables the core enable bit
+ * of core configuration register.
+ */
+static void xlnx_dsi_set_display_disable(struct xlnx_dsi *dsi)
+{
+	u32 reg;
+
+	reg = xlnx_dsi_readl(dsi->iomem, XDSI_CCR);
+	reg &= ~XDSI_CCR_COREENB;
+
+	xlnx_dsi_writel(dsi->iomem, XDSI_CCR, reg);
+	dev_dbg(dsi->dev, "DSI Tx is disabled. reset regs to default values\n");
+}
+
+/**
+ * xlnx_dsi_atomic_set_property - implementation of drm_connector_funcs
+ * set_property invoked by IOCTL call to DRM_IOCTL_MODE_OBJ_SETPROPERTY
+ *
+ * @connector: pointer Xilinx DSI connector
+ * @state: DRM connector state
+ * @prop: pointer to the drm_property structure
+ * @val: DSI parameter value that is configured from user application
+ *
+ * This function takes a drm_property name and value given from user application
+ * and update the DSI structure property varabiles with the values.
+ * These values are later used to configure the DSI Rx IP.
+ *
+ * Return: 0 on success OR -EINVAL if setting property fails
+ */
+static int xlnx_dsi_atomic_set_property(struct drm_connector *connector,
+					struct drm_connector_state *state,
+					struct drm_property *prop, u64 val)
+{
+	struct xlnx_dsi *dsi = connector_to_dsi(connector);
+
+	dev_dbg(dsi->dev, "property name = %s, value = %lld\n",
+		prop->name, val);
+
+	if (prop == dsi->eotp_prop)
+		dsi->eotp_prop_val = !!val;
+	else if (prop == dsi->bllp_mode_prop)
+		dsi->bllp_mode_prop_val = !!val;
+	else if (prop == dsi->bllp_type_prop)
+		dsi->bllp_type_prop_val = !!val;
+	else if (prop == dsi->video_mode_prop)
+		dsi->video_mode_prop_val = (unsigned int)val;
+	else if (prop == dsi->bllp_burst_time_prop)
+		dsi->bllp_burst_time_prop_val = (unsigned int)val;
+	else if (prop == dsi->cmd_queue_prop)
+		dsi->cmd_queue_prop_val = (unsigned int)val;
+	else if (prop == dsi->height_out)
+		dsi->height_out_prop_val = (u32)val;
+	else if (prop == dsi->width_out)
+		dsi->width_out_prop_val = (u32)val;
+	else if (prop == dsi->in_fmt)
+		dsi->in_fmt_prop_val = (u32)val;
+	else if (prop == dsi->out_fmt)
+		dsi->out_fmt_prop_val = (u32)val;
+	else
+		return -EINVAL;
+
+	xlnx_dsi_set_config_parameters(dsi);
+
+	return 0;
+}
+
+static int
+xlnx_dsi_atomic_get_property(struct drm_connector *connector,
+			     const struct drm_connector_state *state,
+			     struct drm_property *prop, uint64_t *val)
+{
+	struct xlnx_dsi *dsi = connector_to_dsi(connector);
+
+	if (prop == dsi->eotp_prop)
+		*val = dsi->eotp_prop_val;
+	else if (prop == dsi->bllp_mode_prop)
+		*val = dsi->bllp_mode_prop_val;
+	else if (prop == dsi->bllp_type_prop)
+		*val = dsi->bllp_type_prop_val;
+	else if (prop == dsi->video_mode_prop)
+		*val = dsi->video_mode_prop_val;
+	else if (prop == dsi->bllp_burst_time_prop)
+		*val = dsi->bllp_burst_time_prop_val;
+	else if (prop == dsi->cmd_queue_prop)
+		*val = dsi->cmd_queue_prop_val;
+	else if (prop == dsi->height_out)
+		*val = dsi->height_out_prop_val;
+	else if (prop == dsi->width_out)
+		*val = dsi->width_out_prop_val;
+	else if (prop == dsi->in_fmt)
+		*val = dsi->in_fmt_prop_val;
+	else if (prop == dsi->out_fmt)
+		*val = dsi->out_fmt_prop_val;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
+ * xlnx_dsi_host_transfer - transfer command to panel
+ * @host: mipi dsi host structure
+ * @msg: mipi dsi msg with type, length and data
+ *
+ * This function is valid only in command mode.
+ * It checks the command fifo empty status and writes into
+ * data or cmd register and waits for the completion status.
+ *
+ * Return:	number of bytes, on success and error number on failure
+ */
+static ssize_t xlnx_dsi_host_transfer(struct mipi_dsi_host *host,
+				      const struct mipi_dsi_msg *msg)
+{
+	struct xlnx_dsi *dsi = host_to_dsi(host);
+	u32 data0, data1, cmd0, val, offset;
+	int status;
+	const char *tx_buf = msg->tx_buf;
+
+	switch (msg->type) {
+	case MIPI_DSI_DCS_LONG_WRITE:
+		status = readl_poll_timeout(dsi->iomem + XDSI_STR, val,
+					    (val & XDSI_STR_LPKT_MASK) ==
+					     XDSI_STR_LPKT_MASK, 1,
+					    XDSI_CMD_TIMEOUT_VAL);
+		if (status) {
+			dev_err(dsi->dev, "long cmd fifo not empty!\n");
+			return -ETIMEDOUT;
+		}
+		data0 = tx_buf[0] | (tx_buf[1] << 8) | (tx_buf[2] << 16) |
+			(tx_buf[3] << 24);
+		data1 = tx_buf[4] | (tx_buf[5] << 8);
+		cmd0 = msg->type | (MIPI_DSI_DCS_READ << 8);
+
+		xlnx_dsi_writel(dsi->iomem, XDSI_DFR, data0);
+		xlnx_dsi_writel(dsi->iomem, XDSI_DFR, data1);
+		xlnx_dsi_writel(dsi->iomem, XDSI_CMD, cmd0);
+		break;
+	case MIPI_DSI_GENERIC_LONG_WRITE:
+		status = readl_poll_timeout(dsi->iomem + XDSI_STR, val,
+					    (val & XDSI_STR_LPKT_MASK) ==
+					    XDSI_STR_LPKT_MASK, 1,
+					    XDSI_CMD_TIMEOUT_VAL);
+		if (status) {
+			dev_err(dsi->dev, "long cmd fifo not empty!\n");
+			return -EBUSY;
+		}
+		cmd0 = msg->type | (msg->tx_len << 8);
+		xlnx_dsi_writel(dsi->iomem, XDSI_CMD, cmd0);
+
+		for (offset = 0; offset <= msg->tx_len; offset += 4) {
+			data0 = tx_buf[0 + offset] | tx_buf[1 + offset] << 8 |
+				tx_buf[2 + offset] << 16 |
+				tx_buf[3 + offset] << 24;
+			xlnx_dsi_writel(dsi->iomem, XDSI_DFR, data0);
+		}
+		break;
+	case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
+		status = readl_poll_timeout(dsi->iomem + XDSI_STR, val,
+					    (val & XDSI_STR_RDY_SHPKT) ==
+					    XDSI_STR_RDY_SHPKT, 1,
+					    XDSI_CMD_TIMEOUT_VAL);
+		if (status) {
+			dev_err(dsi->dev, "short cmd fifo not empty\n");
+			return -EBUSY;
+		}
+		data0 = MIPI_DSI_DCS_SHORT_WRITE_PARAM |
+			(tx_buf[0] << 8) | (tx_buf[1] << 16);
+		xlnx_dsi_writel(dsi->iomem, XDSI_CMD, data0);
+		break;
+	case MIPI_DSI_DCS_SHORT_WRITE:
+		status = readl_poll_timeout(dsi->iomem + XDSI_STR, val,
+					    (val & XDSI_STR_RDY_SHPKT) ==
+					    XDSI_STR_RDY_SHPKT, 1,
+					    XDSI_CMD_TIMEOUT_VAL);
+		if (status) {
+			dev_err(dsi->dev, "short cmd fifo not empty\n");
+			return -EBUSY;
+		}
+		data0 = MIPI_DSI_DCS_SHORT_WRITE | (tx_buf[0] << 8);
+		xlnx_dsi_writel(dsi->iomem, XDSI_CMD, data0);
+		break;
+	default:
+		dev_err(dsi->dev, "Unsupported command type\n");
+		return -EINVAL;
+	}
+
+	status = readl_poll_timeout(dsi->iomem + XDSI_STR, val,
+				    !(val & XDSI_STR_CMD_EXE_PGS), 1,
+				    XDSI_CMD_TIMEOUT_VAL);
+	if (status) {
+		dev_err(dsi->dev, "cmd timeout\n");
+		return status;
+	}
+
+	return msg->tx_len;
+}
+
+static int xlnx_dsi_host_attach(struct mipi_dsi_host *host,
+				struct mipi_dsi_device *device)
+{
+	u32 panel_lanes;
+	struct xlnx_dsi *dsi = host_to_dsi(host);
+
+	panel_lanes = device->lanes;
+	dsi->mode_flags = device->mode_flags;
+	dsi->panel_node = device->dev.of_node;
+
+	if (panel_lanes != dsi->lanes) {
+		dev_err(dsi->dev, "Mismatch of lanes. panel = %d, DSI = %d\n",
+			panel_lanes, dsi->lanes);
+		return -EINVAL;
+	}
+
+	if (dsi->lanes > 4 || dsi->lanes < 1) {
+		dev_err(dsi->dev, "%d lanes : invalid xlnx,dsi-num-lanes\n",
+			dsi->lanes);
+		return -EINVAL;
+	}
+
+	if (device->format != dsi->format) {
+		dev_err(dsi->dev, "Mismatch of format. panel = %d, DSI = %d\n",
+			device->format, dsi->format);
+		return -EINVAL;
+	}
+
+	if (dsi->connector.dev)
+		drm_helper_hpd_irq_event(dsi->connector.dev);
+
+	return 0;
+}
+
+static int xlnx_dsi_host_detach(struct mipi_dsi_host *host,
+				struct mipi_dsi_device *device)
+{
+	struct xlnx_dsi *dsi = host_to_dsi(host);
+
+	dsi->panel = NULL;
+
+	if (dsi->connector.dev)
+		drm_helper_hpd_irq_event(dsi->connector.dev);
+
+	return 0;
+}
+
+static const struct mipi_dsi_host_ops xlnx_dsi_ops = {
+	.attach = xlnx_dsi_host_attach,
+	.detach = xlnx_dsi_host_detach,
+	.transfer = xlnx_dsi_host_transfer,
+};
+
+static int xlnx_dsi_connector_dpms(struct drm_connector *connector, int mode)
+{
+	struct xlnx_dsi *dsi = connector_to_dsi(connector);
+	int ret;
+
+	dev_dbg(dsi->dev, "connector dpms state: %d\n", mode);
+
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+		ret = drm_panel_prepare(dsi->panel);
+		if (ret < 0) {
+			dev_err(dsi->dev, "DRM panel not found\n");
+			return ret;
+		}
+
+		ret = drm_panel_enable(dsi->panel);
+		if (ret < 0) {
+			drm_panel_unprepare(dsi->panel);
+			dev_err(dsi->dev, "DRM panel not enabled\n");
+			return ret;
+		}
+		break;
+	default:
+		drm_panel_disable(dsi->panel);
+		drm_panel_unprepare(dsi->panel);
+		break;
+	}
+
+	return drm_helper_connector_dpms(connector, mode);
+}
+
+static enum drm_connector_status
+xlnx_dsi_detect(struct drm_connector *connector, bool force)
+{
+	struct xlnx_dsi *dsi = connector_to_dsi(connector);
+
+	if (!dsi->panel) {
+		dsi->panel = of_drm_find_panel(dsi->panel_node);
+		if (dsi->panel) {
+			drm_panel_attach(dsi->panel, &dsi->connector);
+			if (dsi->cmdmode) {
+				xlnx_dsi_writel(dsi->iomem, XDSI_CCR,
+						XDSI_CCR_CMDMODE |
+						XDSI_CCR_COREENB);
+				drm_panel_prepare(dsi->panel);
+				xlnx_dsi_writel(dsi->iomem, XDSI_CCR, 0);
+			}
+		}
+	} else if (!dsi->panel_node) {
+		xlnx_dsi_connector_dpms(connector, DRM_MODE_DPMS_OFF);
+		drm_panel_detach(dsi->panel);
+		dsi->panel = NULL;
+	}
+
+	if (dsi->panel)
+		return connector_status_connected;
+
+	return connector_status_disconnected;
+}
+
+static void xlnx_dsi_connector_destroy(struct drm_connector *connector)
+{
+	drm_connector_unregister(connector);
+	drm_connector_cleanup(connector);
+	connector->dev = NULL;
+}
+
+static const struct drm_connector_funcs xlnx_dsi_connector_funcs = {
+	.dpms = xlnx_dsi_connector_dpms,
+	.detect = xlnx_dsi_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = xlnx_dsi_connector_destroy,
+	.atomic_set_property = xlnx_dsi_atomic_set_property,
+	.atomic_get_property = xlnx_dsi_atomic_get_property,
+	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
+	.reset			= drm_atomic_helper_connector_reset,
+};
+
+static int xlnx_dsi_get_modes(struct drm_connector *connector)
+{
+	struct xlnx_dsi *dsi = connector_to_dsi(connector);
+
+	if (dsi->panel)
+		return dsi->panel->funcs->get_modes(dsi->panel);
+
+	return 0;
+}
+
+static struct drm_encoder *
+xlnx_dsi_best_encoder(struct drm_connector *connector)
+{
+	return &(connector_to_dsi(connector)->encoder);
+}
+
+static struct drm_connector_helper_funcs xlnx_dsi_connector_helper_funcs = {
+	.get_modes = xlnx_dsi_get_modes,
+	.best_encoder = xlnx_dsi_best_encoder,
+};
+
+/**
+ * xlnx_dsi_connector_create_property -  create DSI connector properties
+ *
+ * @connector: pointer to Xilinx DSI connector
+ *
+ * This function takes the xilinx DSI connector component and defines
+ * the drm_property variables with their default values.
+ */
+static void xlnx_dsi_connector_create_property(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct xlnx_dsi *dsi  = connector_to_dsi(connector);
+
+	dsi->eotp_prop = drm_property_create_bool(dev, 0, "eotp");
+	dsi->video_mode_prop = drm_property_create_range(dev, 0, "video_mode",
+							 0, 2);
+	dsi->bllp_mode_prop = drm_property_create_bool(dev, 0, "bllp_mode");
+	dsi->bllp_type_prop = drm_property_create_bool(dev, 0, "bllp_type");
+	dsi->bllp_burst_time_prop =
+		drm_property_create_range(dev, 0, "bllp_burst_time", 0, 0xFFFF);
+	dsi->cmd_queue_prop = drm_property_create_range(dev, 0, "cmd_queue", 0,
+							0xffffff);
+	dsi->height_out = drm_property_create_range(dev, 0, "height_out",
+						    2, 4096);
+	dsi->width_out = drm_property_create_range(dev, 0, "width_out",
+						   2, 4096);
+	dsi->in_fmt = drm_property_create_range(dev, 0, "in_fmt", 0, 16384);
+	dsi->out_fmt = drm_property_create_range(dev, 0, "out_fmt", 0, 16384);
+}
+
+/**
+ * xlnx_dsi_connector_attach_property -  attach DSI connector
+ * properties
+ *
+ * @connector: pointer to Xilinx DSI connector
+ */
+static void xlnx_dsi_connector_attach_property(struct drm_connector *connector)
+{
+	struct xlnx_dsi *dsi = connector_to_dsi(connector);
+	struct drm_mode_object *obj = &connector->base;
+
+	if (dsi->eotp_prop)
+		drm_object_attach_property(obj, dsi->eotp_prop, 1);
+
+	if (dsi->video_mode_prop)
+		drm_object_attach_property(obj, dsi->video_mode_prop, 0);
+
+	if (dsi->bllp_burst_time_prop)
+		drm_object_attach_property(&connector->base,
+					   dsi->bllp_burst_time_prop, 0);
+
+	if (dsi->bllp_mode_prop)
+		drm_object_attach_property(&connector->base,
+					   dsi->bllp_mode_prop, 0);
+
+	if (dsi->bllp_type_prop)
+		drm_object_attach_property(&connector->base,
+					   dsi->bllp_type_prop, 0);
+
+	if (dsi->cmd_queue_prop)
+		drm_object_attach_property(&connector->base,
+					   dsi->cmd_queue_prop, 0);
+
+	if (dsi->height_out)
+		drm_object_attach_property(obj, dsi->height_out, 0);
+
+	if (dsi->width_out)
+		drm_object_attach_property(obj, dsi->width_out, 0);
+
+	if (dsi->in_fmt)
+		drm_object_attach_property(obj, dsi->in_fmt, 0);
+
+	if (dsi->out_fmt)
+		drm_object_attach_property(obj, dsi->out_fmt, 0);
+}
+
+static int xlnx_dsi_create_connector(struct drm_encoder *encoder)
+{
+	struct xlnx_dsi *dsi = encoder_to_dsi(encoder);
+	struct drm_connector *connector = &dsi->connector;
+	int ret;
+
+	connector->polled = DRM_CONNECTOR_POLL_HPD;
+
+	ret = drm_connector_init(encoder->dev, connector,
+				 &xlnx_dsi_connector_funcs,
+				 DRM_MODE_CONNECTOR_DSI);
+	if (ret) {
+		dev_err(dsi->dev, "Failed to initialize connector with drm\n");
+		return ret;
+	}
+
+	drm_connector_helper_add(connector, &xlnx_dsi_connector_helper_funcs);
+	drm_connector_register(connector);
+	drm_connector_attach_encoder(connector, encoder);
+	xlnx_dsi_connector_create_property(connector);
+	xlnx_dsi_connector_attach_property(connector);
+
+	return 0;
+}
+
+/**
+ * xlnx_dsi_atomic_mode_set -  derive the DSI timing parameters
+ *
+ * @encoder: pointer to Xilinx DRM encoder
+ * @crtc_state: Pointer to drm core crtc state
+ * @connector_state: DSI connector drm state
+ *
+ * This function derives the DSI IP timing parameters from the timing
+ * values given in the attached panel driver.
+ */
+static void
+xlnx_dsi_atomic_mode_set(struct drm_encoder *encoder,
+			 struct drm_crtc_state *crtc_state,
+				 struct drm_connector_state *connector_state)
+{
+	struct xlnx_dsi *dsi = encoder_to_dsi(encoder);
+	struct videomode *vm = &dsi->vm;
+	struct drm_display_mode *m = &crtc_state->adjusted_mode;
+
+	/* Set bridge input and output parameters */
+	xlnx_bridge_set_input(dsi->bridge, m->hdisplay, m->vdisplay,
+			      dsi->in_fmt_prop_val);
+	xlnx_bridge_set_output(dsi->bridge, dsi->width_out_prop_val,
+			       dsi->height_out_prop_val,
+			       dsi->out_fmt_prop_val);
+	xlnx_bridge_enable(dsi->bridge);
+
+	vm->hactive = m->hdisplay;
+	vm->vactive = m->vdisplay;
+	vm->vfront_porch = m->vsync_start - m->vdisplay;
+	vm->vback_porch = m->vtotal - m->vsync_end;
+	vm->vsync_len = m->vsync_end - m->vsync_start;
+	vm->hfront_porch = m->hsync_start - m->hdisplay;
+	vm->hback_porch = m->htotal - m->hsync_end;
+	vm->hsync_len = m->hsync_end - m->hsync_start;
+	xlnx_dsi_set_display_mode(dsi);
+}
+
+static void xlnx_dsi_disable(struct drm_encoder *encoder)
+{
+	struct xlnx_dsi *dsi = encoder_to_dsi(encoder);
+
+	if (dsi->bridge)
+		xlnx_bridge_disable(dsi->bridge);
+
+	xlnx_dsi_set_display_disable(dsi);
+}
+
+static void xlnx_dsi_enable(struct drm_encoder *encoder)
+{
+	struct xlnx_dsi *dsi = encoder_to_dsi(encoder);
+
+	xlnx_dsi_set_display_enable(dsi);
+}
+
+static const struct drm_encoder_helper_funcs xlnx_dsi_encoder_helper_funcs = {
+	.atomic_mode_set = xlnx_dsi_atomic_mode_set,
+	.enable = xlnx_dsi_enable,
+	.disable = xlnx_dsi_disable,
+};
+
+static const struct drm_encoder_funcs xlnx_dsi_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+static int xlnx_dsi_parse_dt(struct xlnx_dsi *dsi)
+{
+	struct device *dev = dsi->dev;
+	struct device_node *node = dev->of_node;
+	int ret;
+	u32 datatype;
+	static const int xdsi_mul_fact[XDSI_NUM_DATA_T] = {300, 225, 225, 200};
+
+	dsi->dphy_clk_200M = devm_clk_get(dev, "dphy_clk_200M");
+	if (IS_ERR(dsi->dphy_clk_200M)) {
+		ret = PTR_ERR(dsi->dphy_clk_200M);
+		dev_err(dev, "failed to get dphy_clk_200M %d\n", ret);
+		return ret;
+	}
+
+	dsi->video_aclk = devm_clk_get(dev, "s_axis_aclk");
+	if (IS_ERR(dsi->video_aclk)) {
+		ret = PTR_ERR(dsi->video_aclk);
+		dev_err(dev, "failed to get video_clk %d\n", ret);
+		return ret;
+	}
+
+	/*
+	 * Used as a multiplication factor for HACT based on used
+	 * DSI data type.
+	 *
+	 * e.g. for RGB666_L datatype and 1920x1080 resolution,
+	 * the Hact (WC) would be as follows -
+	 * 1920 pixels * 18 bits per pixel / 8 bits per byte
+	 * = 1920 pixels * 2.25 bytes per pixel = 4320 bytes.
+	 *
+	 * Data Type - Multiplication factor
+	 * RGB888    - 3
+	 * RGB666_L  - 2.25
+-	 * RGB666_P  - 2.25
+	 * RGB565    - 2
+	 *
+	 * Since the multiplication factor maybe a floating number,
+	 * a 100x multiplication factor is used.
+	 */
+	ret = of_property_read_u32(node, "xlnx,dsi-num-lanes", &dsi->lanes);
+	if (ret < 0) {
+		dev_err(dsi->dev, "missing xlnx,dsi-num-lanes property\n");
+		return ret;
+	}
+	if (dsi->lanes > 4 || dsi->lanes < 1) {
+		dev_err(dsi->dev, "%d lanes : invalid lanes\n", dsi->lanes);
+		return -EINVAL;
+	}
+	ret = of_property_read_u32(node, "xlnx,dsi-data-type", &datatype);
+	if (ret < 0) {
+		dev_err(dsi->dev, "missing xlnx,dsi-data-type property\n");
+		return ret;
+	}
+	dsi->format = datatype;
+	if (datatype > MIPI_DSI_FMT_RGB565) {
+		dev_err(dsi->dev, "Invalid xlnx,dsi-data-type string\n");
+		return -EINVAL;
+	}
+	dsi->mul_factor = xdsi_mul_fact[datatype];
+
+	dsi->cmdmode = of_property_read_bool(node, "xlnx,dsi-cmd-mode");
+
+	dev_dbg(dsi->dev, "DSI controller num lanes = %d", dsi->lanes);
+	dev_dbg(dsi->dev, "DSI controller datatype = %d\n", datatype);
+	dev_dbg(dsi->dev, "DSI controller cmd mode = %d\n", dsi->cmdmode);
+
+	return 0;
+}
+
+static int xlnx_dsi_bind(struct device *dev, struct device *master,
+			 void *data)
+{
+	struct xlnx_dsi *dsi = dev_get_drvdata(dev);
+	struct drm_encoder *encoder = &dsi->encoder;
+	struct drm_device *drm_dev = data;
+	int ret;
+
+	/*
+	 * TODO: The possible CRTCs are 1 now as per current implementation of
+	 * DSI tx drivers. DRM framework can support more than one CRTCs and
+	 * DSI driver can be enhanced for that.
+	 */
+	encoder->possible_crtcs = 1;
+	drm_encoder_init(drm_dev, encoder, &xlnx_dsi_encoder_funcs,
+			 DRM_MODE_ENCODER_DSI, NULL);
+	drm_encoder_helper_add(encoder, &xlnx_dsi_encoder_helper_funcs);
+	ret = xlnx_dsi_create_connector(encoder);
+	if (ret) {
+		dev_err(dsi->dev, "fail creating connector, ret = %d\n", ret);
+		drm_encoder_cleanup(encoder);
+		return ret;
+	}
+	ret = mipi_dsi_host_register(&dsi->dsi_host);
+	if (ret) {
+		xlnx_dsi_connector_destroy(&dsi->connector);
+		drm_encoder_cleanup(encoder);
+		return ret;
+	}
+	return 0;
+}
+
+static void xlnx_dsi_unbind(struct device *dev, struct device *master,
+			    void *data)
+{
+	struct xlnx_dsi *dsi = dev_get_drvdata(dev);
+
+	xlnx_dsi_disable(&dsi->encoder);
+	mipi_dsi_host_unregister(&dsi->dsi_host);
+	xlnx_bridge_disable(dsi->bridge);
+}
+
+static const struct component_ops xlnx_dsi_component_ops = {
+	.bind	= xlnx_dsi_bind,
+	.unbind	= xlnx_dsi_unbind,
+};
+
+static int xlnx_dsi_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct xlnx_dsi *dsi;
+	struct device_node *vpss_node;
+	int ret;
+	unsigned long rate;
+
+	dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);
+	if (!dsi)
+		return -ENOMEM;
+
+	dsi->dsi_host.ops = &xlnx_dsi_ops;
+	dsi->dsi_host.dev = dev;
+	dsi->dev = dev;
+
+	ret = xlnx_dsi_parse_dt(dsi);
+	if (ret)
+		return ret;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	dsi->iomem = devm_ioremap_resource(dev, res);
+	if (IS_ERR(dsi->iomem))
+		return PTR_ERR(dsi->iomem);
+
+	platform_set_drvdata(pdev, dsi);
+
+	/* Bridge support */
+	vpss_node = of_parse_phandle(dsi->dev->of_node, "xlnx,vpss", 0);
+	if (vpss_node) {
+		dsi->bridge = of_xlnx_bridge_get(vpss_node);
+		if (!dsi->bridge) {
+			dev_info(dsi->dev, "Didn't get bridge instance\n");
+			return -EPROBE_DEFER;
+		}
+	}
+
+	ret = clk_set_rate(dsi->dphy_clk_200M, XDSI_DPHY_CLK_REQ);
+	if (ret) {
+		dev_err(dev, "failed to set dphy clk rate %d\n", ret);
+		return ret;
+	}
+
+	ret = clk_prepare_enable(dsi->dphy_clk_200M);
+	if (ret) {
+		dev_err(dev, "failed to enable dphy clk %d\n", ret);
+		return ret;
+	}
+
+	rate = clk_get_rate(dsi->dphy_clk_200M);
+	if (rate < XDSI_DPHY_CLK_MIN && rate > XDSI_DPHY_CLK_MAX) {
+		dev_err(dev, "Error DPHY clock = %lu\n", rate);
+		ret = -EINVAL;
+		goto err_disable_dphy_clk;
+	}
+
+	ret = clk_prepare_enable(dsi->video_aclk);
+	if (ret) {
+		dev_err(dev, "failed to enable video clk %d\n", ret);
+		goto err_disable_dphy_clk;
+	}
+
+	ret = component_add(dev, &xlnx_dsi_component_ops);
+	if (ret < 0)
+		goto err_disable_video_clk;
+
+	return ret;
+
+err_disable_video_clk:
+	clk_disable_unprepare(dsi->video_aclk);
+err_disable_dphy_clk:
+	clk_disable_unprepare(dsi->dphy_clk_200M);
+	return ret;
+}
+
+static int xlnx_dsi_remove(struct platform_device *pdev)
+{
+	struct xlnx_dsi *dsi = platform_get_drvdata(pdev);
+
+	component_del(&pdev->dev, &xlnx_dsi_component_ops);
+	clk_disable_unprepare(dsi->video_aclk);
+	clk_disable_unprepare(dsi->dphy_clk_200M);
+
+	return 0;
+}
+
+static const struct of_device_id xlnx_dsi_of_match[] = {
+	{ .compatible = "xlnx,dsi"},
+	{ }
+};
+MODULE_DEVICE_TABLE(of, xlnx_dsi_of_match);
+
+static struct platform_driver dsi_driver = {
+	.probe = xlnx_dsi_probe,
+	.remove = xlnx_dsi_remove,
+	.driver = {
+		.name = "xlnx-dsi",
+		.of_match_table = xlnx_dsi_of_match,
+	},
+};
+
+module_platform_driver(dsi_driver);
+
+MODULE_AUTHOR("Siva Rajesh <sivaraj@xilinx.com>");
+MODULE_DESCRIPTION("Xilinx FPGA MIPI DSI Tx Driver");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/xlnx/xlnx_fb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/xlnx/xlnx_fb.c
@@ -0,0 +1,358 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx DRM KMS Framebuffer helper
+ *
+ *  Copyright (C) 2015 - 2018 Xilinx, Inc.
+ *
+ *  Author: Hyun Woo Kwon <hyun.kwon@xilinx.com>
+ *
+ * Based on drm_fb_cma_helper.c
+ *
+ *  Copyright (C) 2012 Analog Device Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+
+#include "xlnx_crtc.h"
+#include "xlnx_drv.h"
+#include "xlnx_fb.h"
+
+static struct drm_framebuffer_funcs xlnx_fb_funcs = {
+	.destroy	= drm_gem_fb_destroy,
+	.create_handle	= drm_gem_fb_create_handle,
+};
+
+/**
+ * xlnx_fb_create - (struct drm_mode_config_funcs *)->fb_create callback
+ * @drm: DRM device
+ * @file_priv: drm file private data
+ * @mode_cmd: mode command for fb creation
+ *
+ * This functions creates a drm_framebuffer with xlnx_fb_funcs for given mode
+ * @mode_cmd. This functions is intended to be used for the fb_create callback
+ * function of drm_mode_config_funcs.
+ *
+ * Return: a drm_framebuffer object if successful, or
+ * ERR_PTR from drm_gem_fb_create_with_funcs().
+ */
+struct drm_framebuffer *
+xlnx_fb_create(struct drm_device *drm, struct drm_file *file_priv,
+	       const struct drm_mode_fb_cmd2 *mode_cmd)
+{
+	return drm_gem_fb_create_with_funcs(drm, file_priv, mode_cmd,
+					    &xlnx_fb_funcs);
+}
+
+#ifdef CONFIG_DRM_FBDEV_EMULATION
+
+struct xlnx_fbdev {
+	struct drm_fb_helper fb_helper;
+	struct drm_framebuffer *fb;
+	unsigned int align;
+	unsigned int vres_mult;
+};
+
+static inline struct xlnx_fbdev *to_fbdev(struct drm_fb_helper *fb_helper)
+{
+	return container_of(fb_helper, struct xlnx_fbdev, fb_helper);
+}
+
+static int
+xlnx_fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
+{
+	struct drm_fb_helper *fb_helper = info->par;
+	struct drm_mode_set *mode_set;
+	int ret = 0;
+
+	switch (cmd) {
+	case FBIO_WAITFORVSYNC:
+		drm_client_for_each_modeset(mode_set, &fb_helper->client) {
+			struct drm_crtc *crtc;
+
+			crtc = mode_set->crtc;
+			ret = drm_crtc_vblank_get(crtc);
+			if (!ret) {
+				drm_crtc_wait_one_vblank(crtc);
+				drm_crtc_vblank_put(crtc);
+			}
+		}
+		return ret;
+	default:
+		return -ENOTTY;
+	}
+
+	return 0;
+}
+
+static struct fb_ops xlnx_fbdev_ops = {
+	.owner		= THIS_MODULE,
+	.fb_fillrect	= sys_fillrect,
+	.fb_copyarea	= sys_copyarea,
+	.fb_imageblit	= sys_imageblit,
+	.fb_check_var	= drm_fb_helper_check_var,
+	.fb_set_par	= drm_fb_helper_set_par,
+	.fb_blank	= drm_fb_helper_blank,
+	.fb_pan_display	= drm_fb_helper_pan_display,
+	.fb_setcmap	= drm_fb_helper_setcmap,
+	.fb_ioctl	= xlnx_fb_ioctl,
+};
+
+static struct drm_framebuffer *
+xlnx_fb_gem_fb_alloc(struct drm_device *drm,
+		     const struct drm_mode_fb_cmd2 *mode_cmd,
+		     struct drm_gem_object **obj, unsigned int num_planes,
+		     const struct drm_framebuffer_funcs *funcs)
+{
+	struct drm_framebuffer *fb;
+	int ret, i;
+
+	fb = kzalloc(sizeof(*fb), GFP_KERNEL);
+	if (!fb)
+		return ERR_PTR(-ENOMEM);
+
+	drm_helper_mode_fill_fb_struct(drm, fb, mode_cmd);
+
+	for (i = 0; i < num_planes; i++)
+		fb->obj[i] = obj[i];
+
+	ret = drm_framebuffer_init(drm, fb, funcs);
+	if (ret) {
+		dev_err(drm->dev, "Failed to init framebuffer: %d\n", ret);
+		kfree(fb);
+		return ERR_PTR(ret);
+	}
+
+	return fb;
+}
+
+static struct drm_framebuffer *
+xlnx_fb_gem_fbdev_fb_create(struct drm_device *drm,
+			struct drm_fb_helper_surface_size *size,
+			unsigned int pitch_align, struct drm_gem_object *obj,
+			const struct drm_framebuffer_funcs *funcs)
+{
+	struct drm_mode_fb_cmd2 mode_cmd = { 0 };
+
+	mode_cmd.width = size->surface_width;
+	mode_cmd.height = size->surface_height;
+	mode_cmd.pitches[0] = size->surface_width *
+			      DIV_ROUND_UP(size->surface_bpp, 8);
+	if (pitch_align)
+		mode_cmd.pitches[0] = roundup(mode_cmd.pitches[0],
+					      pitch_align);
+	mode_cmd.pixel_format = drm_driver_legacy_fb_format(drm,
+							    size->surface_bpp,
+							    size->surface_depth);
+	if (obj->size < (size_t)mode_cmd.pitches[0] * mode_cmd.height)
+		return ERR_PTR(-EINVAL);
+
+	return xlnx_fb_gem_fb_alloc(drm, &mode_cmd, &obj, 1, funcs);
+}
+
+/**
+ * xlnx_fbdev_create - Create the fbdev with a framebuffer
+ * @fb_helper: fb helper structure
+ * @size: framebuffer size info
+ *
+ * This function is based on drm_fbdev_cma_create().
+ *
+ * Return: 0 if successful, or the error code.
+ */
+static int xlnx_fbdev_create(struct drm_fb_helper *fb_helper,
+			     struct drm_fb_helper_surface_size *size)
+{
+	struct xlnx_fbdev *fbdev = to_fbdev(fb_helper);
+	struct drm_device *drm = fb_helper->dev;
+	struct drm_gem_cma_object *obj;
+	struct drm_framebuffer *fb;
+	unsigned int bytes_per_pixel;
+	unsigned long offset;
+	struct fb_info *fbi;
+	u32 format;
+	const struct drm_format_info *info;
+	size_t bytes;
+	int ret;
+
+	dev_dbg(drm->dev, "surface width(%d), height(%d) and bpp(%d)\n",
+		size->surface_width, size->surface_height, size->surface_bpp);
+
+	size->surface_height *= fbdev->vres_mult;
+	bytes_per_pixel = DIV_ROUND_UP(size->surface_bpp, 8);
+	bytes = ALIGN((size_t)size->surface_width * bytes_per_pixel,
+		      fbdev->align);
+	bytes *= size->surface_height;
+
+	obj = drm_gem_cma_create(drm, bytes);
+	if (IS_ERR(obj))
+		return PTR_ERR(obj);
+
+	fbi = framebuffer_alloc(0, drm->dev);
+	if (!fbi) {
+		dev_err(drm->dev, "Failed to allocate framebuffer info.\n");
+		ret = -ENOMEM;
+		goto err_drm_gem_cma_free_object;
+	}
+
+	/* Override the depth given by fb helper with current format value */
+	format = xlnx_get_format(drm);
+	info = drm_format_info(format);
+	if (size->surface_bpp == info->cpp[0] * 8)
+		size->surface_depth = info->depth;
+
+	fbdev->fb = xlnx_fb_gem_fbdev_fb_create(drm, size, fbdev->align,
+						&obj->base, &xlnx_fb_funcs);
+	if (IS_ERR(fbdev->fb)) {
+		dev_err(drm->dev, "Failed to allocate DRM framebuffer.\n");
+		ret = PTR_ERR(fbdev->fb);
+		goto err_framebuffer_release;
+	}
+
+	fb = fbdev->fb;
+	fb_helper->fb = fb;
+	fb_helper->fbdev = fbi;
+	fbi->flags = FBINFO_FLAG_DEFAULT;
+	fbi->fbops = &xlnx_fbdev_ops;
+
+	ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
+	if (ret) {
+		dev_err(drm->dev, "Failed to allocate color map.\n");
+		goto err_fb_destroy;
+	}
+
+	drm_fb_helper_fill_info(fbi, fb_helper, size);
+	fbi->var.yres = fb->height / fbdev->vres_mult;
+
+	offset = (unsigned long)fbi->var.xoffset * bytes_per_pixel;
+	offset += fbi->var.yoffset * fb->pitches[0];
+
+	drm->mode_config.fb_base = (resource_size_t)obj->paddr;
+	fbi->screen_base = (char __iomem *)(obj->vaddr + offset);
+	fbi->fix.smem_start = (unsigned long)(obj->paddr + offset);
+	fbi->screen_size = bytes;
+	fbi->fix.smem_len = bytes;
+
+	return 0;
+
+err_fb_destroy:
+	drm_framebuffer_unregister_private(fb);
+	drm_gem_fb_destroy(fb);
+err_framebuffer_release:
+	framebuffer_release(fbi);
+err_drm_gem_cma_free_object:
+	drm_gem_cma_free_object(&obj->base);
+	return ret;
+}
+
+static struct drm_fb_helper_funcs xlnx_fb_helper_funcs = {
+	.fb_probe = xlnx_fbdev_create,
+};
+
+/**
+ * xlnx_fb_init - Allocate and initializes the Xilinx framebuffer
+ * @drm: DRM device
+ * @preferred_bpp: preferred bits per pixel for the device
+ * @max_conn_count: maximum number of connectors
+ * @align: alignment value for pitch
+ * @vres_mult: multiplier for virtual resolution
+ *
+ * This function is based on drm_fbdev_cma_init().
+ *
+ * Return: a newly allocated drm_fb_helper struct or a ERR_PTR.
+ */
+struct drm_fb_helper *
+xlnx_fb_init(struct drm_device *drm, int preferred_bpp,
+	     unsigned int max_conn_count, unsigned int align,
+	     unsigned int vres_mult)
+{
+	struct xlnx_fbdev *fbdev;
+	struct drm_fb_helper *fb_helper;
+	int ret;
+
+	fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
+	if (!fbdev)
+		return ERR_PTR(-ENOMEM);
+
+	fbdev->vres_mult = vres_mult;
+	fbdev->align = align;
+	fb_helper = &fbdev->fb_helper;
+	drm_fb_helper_prepare(drm, fb_helper, &xlnx_fb_helper_funcs);
+
+	ret = drm_fb_helper_init(drm, fb_helper, max_conn_count);
+	if (ret < 0) {
+		dev_err(drm->dev, "Failed to initialize drm fb helper.\n");
+		goto err_free;
+	}
+
+	ret = drm_fb_helper_single_add_all_connectors(fb_helper);
+	if (ret < 0) {
+		dev_err(drm->dev, "Failed to add connectors.\n");
+		goto err_drm_fb_helper_fini;
+	}
+
+	ret = drm_fb_helper_initial_config(fb_helper, preferred_bpp);
+	if (ret < 0) {
+		dev_err(drm->dev, "Failed to set initial hw configuration.\n");
+		goto err_drm_fb_helper_fini;
+	}
+
+	return fb_helper;
+
+err_drm_fb_helper_fini:
+	drm_fb_helper_fini(fb_helper);
+err_free:
+	kfree(fbdev);
+	return ERR_PTR(ret);
+}
+
+/**
+ * xlnx_fbdev_defio_fini - Free the defio fb
+ * @fbi: fb_info struct
+ *
+ * This function is based on drm_fbdev_cma_defio_fini().
+ */
+static void xlnx_fbdev_defio_fini(struct fb_info *fbi)
+{
+	if (!fbi->fbdefio)
+		return;
+
+	fb_deferred_io_cleanup(fbi);
+	kfree(fbi->fbdefio);
+	kfree(fbi->fbops);
+}
+
+/**
+ * xlnx_fbdev_fini - Free the Xilinx framebuffer
+ * @fb_helper: drm_fb_helper struct
+ *
+ * This function is based on drm_fbdev_cma_fini().
+ */
+void xlnx_fb_fini(struct drm_fb_helper *fb_helper)
+{
+	struct xlnx_fbdev *fbdev = to_fbdev(fb_helper);
+
+	drm_fb_helper_unregister_fbi(&fbdev->fb_helper);
+	if (fbdev->fb_helper.fbdev)
+		xlnx_fbdev_defio_fini(fbdev->fb_helper.fbdev);
+
+	if (fbdev->fb_helper.fb)
+		drm_framebuffer_remove(fbdev->fb_helper.fb);
+
+	drm_fb_helper_fini(&fbdev->fb_helper);
+	kfree(fbdev);
+}
+
+#endif /* CONFIG_DRM_FBDEV_EMULATION */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/xlnx/xlnx_fb.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/xlnx/xlnx_fb.h
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx DRM KMS Framebuffer helper header
+ *
+ *  Copyright (C) 2015 - 2018 Xilinx, Inc.
+ *
+ *  Author: Hyun Woo Kwon <hyun.kwon@xilinx.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _XLNX_FB_H_
+#define _XLNX_FB_H_
+
+struct drm_fb_helper;
+
+struct drm_framebuffer *
+xlnx_fb_create(struct drm_device *drm, struct drm_file *file_priv,
+	       const struct drm_mode_fb_cmd2 *mode_cmd);
+
+#ifdef CONFIG_DRM_FBDEV_EMULATION
+
+struct drm_fb_helper *
+xlnx_fb_init(struct drm_device *drm, int preferred_bpp,
+	     unsigned int max_conn_count, unsigned int align,
+	     unsigned int vres_mult);
+void xlnx_fb_fini(struct drm_fb_helper *fb_helper);
+
+#else /* CONFIG_DRM_FBDEV_EMULATION */
+
+static inline struct drm_fb_helper *
+xlnx_fb_init(struct drm_device *drm, int preferred_bpp,
+	     unsigned int max_conn_count, unsigned int align,
+	     unsigned int vres_mult)
+{
+	return NULL;
+}
+
+static inline void xlnx_fb_fini(struct drm_fb_helper *fb_helper)
+{
+}
+
+#endif /* CONFIG_DRM_FBDEV_EMULATION */
+
+#endif /* _XLNX_FB_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/xlnx/xlnx_gem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/xlnx/xlnx_gem.c
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx DRM KMS GEM helper
+ *
+ *  Copyright (C) 2015 - 2018 Xilinx, Inc.
+ *
+ *  Author: Hyun Woo Kwon <hyun.kwon@xilinx.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_gem_cma_helper.h>
+
+#include "xlnx_drv.h"
+#include "xlnx_gem.h"
+
+/*
+ * xlnx_gem_cma_dumb_create - (struct drm_driver)->dumb_create callback
+ * @file_priv: drm_file object
+ * @drm: DRM object
+ * @args: info for dumb scanout buffer creation
+ *
+ * This function is for dumb_create callback of drm_driver struct. Simply
+ * it wraps around drm_gem_cma_dumb_create() and sets the pitch value
+ * by retrieving the value from the device.
+ *
+ * Return: The return value from drm_gem_cma_dumb_create()
+ */
+int xlnx_gem_cma_dumb_create(struct drm_file *file_priv, struct drm_device *drm,
+			     struct drm_mode_create_dumb *args)
+{
+	int pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
+	unsigned int align = xlnx_get_align(drm);
+
+	if (!args->pitch || !IS_ALIGNED(args->pitch, align))
+		args->pitch = ALIGN(pitch, align);
+
+	return drm_gem_cma_dumb_create_internal(file_priv, drm, args);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/xlnx/xlnx_gem.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/xlnx/xlnx_gem.h
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx DRM KMS GEM helper header
+ *
+ *  Copyright (C) 2015 - 2018 Xilinx, Inc.
+ *
+ *  Author: Hyun Woo Kwon <hyun.kwon@xilinx.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _XLNX_GEM_H_
+#define _XLNX_GEM_H_
+
+int xlnx_gem_cma_dumb_create(struct drm_file *file_priv,
+			     struct drm_device *drm,
+			     struct drm_mode_create_dumb *args);
+
+#endif /* _XLNX_GEM_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/xlnx/xlnx_mixer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/xlnx/xlnx_mixer.c
@@ -0,0 +1,3136 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx logicore video mixer driver
+ *
+ * Copyright (C) 2017 - 2018 Xilinx, Inc.
+ *
+ * Author: Saurabh Sengar <saurabhs@xilinx.com>
+ *       : Jeffrey Mouroux <jmouroux@xilinx.com>
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_atomic_uapi.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_modeset_helper_vtables.h>
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/dma/xilinx_frmbuf.h>
+#include <linux/gpio/consumer.h>
+#include <linux/of.h>
+#include <linux/of_dma.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/dmaengine.h>
+#include <video/videomode.h>
+#include "xlnx_bridge.h"
+#include "xlnx_crtc.h"
+#include "xlnx_drv.h"
+
+/**************************** Register Data **********************************/
+#define XVMIX_AP_CTRL			0x00000
+#define XVMIX_GIE			0x00004
+#define XVMIX_IER			0x00008
+#define XVMIX_ISR			0x0000c
+#define XVMIX_WIDTH_DATA		0x00010
+#define XVMIX_HEIGHT_DATA		0x00018
+#define XVMIX_BACKGROUND_Y_R_DATA	0x00028
+#define XVMIX_BACKGROUND_U_G_DATA	0x00030
+#define XVMIX_BACKGROUND_V_B_DATA	0x00038
+#define XVMIX_LAYERENABLE_DATA		0x00040
+#define XVMIX_K00_1			0x00048
+#define XVMIX_K01_1			0x00050
+#define XVMIX_K02_1			0x00058
+#define XVMIX_K10_1			0x00060
+#define XVMIX_K11_1			0x00068
+#define XVMIX_K12_1			0x00070
+#define XVMIX_K20_1			0x00078
+#define XVMIX_K21_1			0x00080
+#define XVMIX_K22_1			0x00088
+#define XVMIX_Y_DATA			0x00090
+#define XVMIX_U_DATA			0x00098
+#define XVMIX_V_DATA			0x000A0
+#define XVMIX_LAYERALPHA_0_DATA		0x00100
+#define XVMIX_LAYERSTARTX_0_DATA	0x00108
+#define XVMIX_LAYERSTARTY_0_DATA	0x00110
+#define XVMIX_LAYERWIDTH_0_DATA		0x00118
+#define XVMIX_LAYERSTRIDE_0_DATA	0x00120
+#define XVMIX_LAYERHEIGHT_0_DATA	0x00128
+#define XVMIX_LAYERSCALE_0_DATA		0x00130
+#define XVMIX_LAYERVIDEOFORMAT_0_DATA	0x00138
+#define XVMIX_K00_2			0x00140
+#define XVMIX_K01_2			0x00148
+#define XVMIX_K02_2			0x00150
+#define XVMIX_K10_2			0x00158
+#define XVMIX_K11_2			0x00160
+#define XVMIX_K12_2			0x00168
+#define XVMIX_K20_2			0x00170
+#define XVMIX_K21_2			0x00178
+#define XVMIX_K22_2			0x00180
+#define XVMIX_R_DATA			0x00188
+#define XVMIX_G_DATA			0x00190
+#define XVMIX_B_DATA			0x00198
+#define XVMIX_LAYER1_BUF1_V_DATA	0x00240
+#define XVMIX_LAYER1_BUF2_V_DATA	0x0024c
+#define XVMIX_LOGOSTARTX_DATA		0x01000
+#define XVMIX_LOGOSTARTY_DATA		0x01008
+#define XVMIX_LOGOWIDTH_DATA		0x01010
+#define XVMIX_LOGOHEIGHT_DATA		0x01018
+#define XVMIX_LOGOSCALEFACTOR_DATA	0x01020
+#define XVMIX_LOGOALPHA_DATA		0x01028
+#define XVMIX_LOGOCLRKEYMIN_R_DATA	0x01030
+#define XVMIX_LOGOCLRKEYMIN_G_DATA	0x01038
+#define XVMIX_LOGOCLRKEYMIN_B_DATA	0x01040
+#define XVMIX_LOGOCLRKEYMAX_R_DATA	0x01048
+#define XVMIX_LOGOCLRKEYMAX_G_DATA	0x01050
+#define XVMIX_LOGOCLRKEYMAX_B_DATA	0x01058
+#define XVMIX_LOGOR_V_BASE		0x10000
+#define XVMIX_LOGOR_V_HIGH		0x10fff
+#define XVMIX_LOGOG_V_BASE		0x20000
+#define XVMIX_LOGOG_V_HIGH		0x20fff
+#define XVMIX_LOGOB_V_BASE		0x30000
+#define XVMIX_LOGOB_V_HIGH		0x30fff
+#define XVMIX_LOGOA_V_BASE		0x40000
+#define XVMIX_LOGOA_V_HIGH		0x40fff
+
+/************************** Constant Definitions *****************************/
+#define XVMIX_LOGO_OFFSET		0x1000
+#define XVMIX_MASK_DISABLE_ALL_LAYERS   0x0
+#define XVMIX_REG_OFFSET                0x100
+#define XVMIX_MASTER_LAYER_IDX		0x0
+#define XVMIX_LOGO_LAYER_IDX		0x1
+#define XVMIX_DISP_MAX_WIDTH		8192
+#define XVMIX_DISP_MAX_HEIGHT		4320
+#define XVMIX_DISP_MIN_WIDTH		64
+#define XVMIX_DISP_MIN_HEIGHT		64
+#define XVMIX_MAX_OVERLAY_LAYERS	16
+#define XVMIX_MAX_BPC			16
+#define XVMIX_ALPHA_MIN			0
+#define XVMIX_ALPHA_MAX			256
+#define XVMIX_LAYER_WIDTH_MIN		64
+#define XVMIX_LAYER_HEIGHT_MIN		64
+#define XVMIX_LOGO_LAYER_WIDTH_MIN	32
+#define XVMIX_LOGO_LAYER_HEIGHT_MIN	32
+#define XVMIX_LOGO_LAYER_WIDTH_MAX	256
+#define XVMIX_LOGO_LAYER_HEIGHT_MAX	256
+#define XVMIX_IRQ_DONE_MASK		BIT(0)
+#define XVMIX_GIE_EN_MASK		BIT(0)
+#define XVMIX_AP_EN_MASK		BIT(0)
+#define XVMIX_AP_RST_MASK		BIT(7)
+#define XVMIX_MAX_NUM_SUB_PLANES	4
+#define XVMIX_SCALE_FACTOR_1X		0
+#define	XVMIX_SCALE_FACTOR_2X		1
+#define	XVMIX_SCALE_FACTOR_4X		2
+#define	XVMIX_SCALE_FACTOR_INVALID	3
+#define	XVMIX_BASE_ALIGN		8
+#define XVMIX_CSC_MAX_ROWS		(3)
+#define XVMIX_CSC_MAX_COLS		(3)
+#define XVMIX_CSC_MATRIX_SIZE	(XVMIX_CSC_MAX_ROWS * XVMIX_CSC_MAX_COLS)
+#define XVMIX_CSC_COEFF_SIZE		(12)
+#define XVMIX_CSC_SCALE_FACTOR		(4096)
+#define XVMIX_CSC_DIVISOR		(10000)
+
+/*************************** STATIC DATA  ************************************/
+static const s16
+xlnx_mix_yuv2rgb_coeffs[][DRM_COLOR_ENCODING_MAX][XVMIX_CSC_COEFF_SIZE] = {
+	[DRM_COLOR_YCBCR_BT601][DRM_COLOR_YCBCR_LIMITED_RANGE] = {
+		10000, 0, 13669,
+		10000, -3367, -6986,
+		10000, 17335, 0,
+		-175, 132, -222
+	},
+	[DRM_COLOR_YCBCR_BT601][DRM_COLOR_YCBCR_FULL_RANGE] = {
+		10479, 0, 13979,
+		10479, -3443, -7145,
+		10479, 17729, 0,
+		-179, 136, -227
+	},
+	[DRM_COLOR_YCBCR_BT709][DRM_COLOR_YCBCR_LIMITED_RANGE] = {
+		10000, 0, 15406,
+		10000, -1832, -4579,
+		10000, 18153, 0,
+		-197, 82, -232
+	},
+	[DRM_COLOR_YCBCR_BT709][DRM_COLOR_YCBCR_FULL_RANGE] = {
+		10233, 0, 15756,
+		10233, -1873, -4683,
+		10233, 18566, 0,
+		-202, 84, -238
+	},
+	[DRM_COLOR_YCBCR_BT2020][DRM_COLOR_YCBCR_LIMITED_RANGE] = {
+		10000, 0, 14426,
+		10000, -1609, -5589,
+		10000, 18406, 0,
+		-185, 92, -236
+	},
+	[DRM_COLOR_YCBCR_BT2020][DRM_COLOR_YCBCR_FULL_RANGE] = {
+		10233, 0, 14754,
+		10233, -1646, -5716,
+		10233, 18824, 0,
+		-189, 94, -241
+	}
+};
+
+static const s16
+xlnx_mix_rgb2yuv_coeffs[][DRM_COLOR_ENCODING_MAX][XVMIX_CSC_COEFF_SIZE] = {
+	[DRM_COLOR_YCBCR_BT601][DRM_COLOR_YCBCR_LIMITED_RANGE] = {
+		2990, 5870, 1440,
+		-1720, -3390, 5110,
+		5110, -4280, -830,
+		0, 128, 128
+	},
+	[DRM_COLOR_YCBCR_BT601][DRM_COLOR_YCBCR_FULL_RANGE] = {
+		2921, 5735, 1113,
+		-1686, -3310, 4393,
+		4393, -4184, -812,
+		0, 128, 128
+	},
+	[DRM_COLOR_YCBCR_BT709][DRM_COLOR_YCBCR_LIMITED_RANGE] = {
+		2120, 7150, 720,
+		-1170, -3940, 5110,
+		5110, -4640, -470,
+		0, 128, 128
+	},
+	[DRM_COLOR_YCBCR_BT709][DRM_COLOR_YCBCR_FULL_RANGE] = {
+		2077, 6988, 705,
+		-1144, -3582, 4997,
+		4997, -4538, -458,
+		0, 128, 128
+	},
+	[DRM_COLOR_YCBCR_BT2020][DRM_COLOR_YCBCR_LIMITED_RANGE] = {
+		2625, 6775, 592,
+		-1427, -3684, 5110,
+		5110, -4699, -410,
+		0, 128, 128
+	},
+	[DRM_COLOR_YCBCR_BT2020][DRM_COLOR_YCBCR_FULL_RANGE] = {
+		2566, 6625, 579,
+		-1396, -3602, 4997,
+		4997, -4595, -401,
+		0, 128, 128
+	}
+};
+
+static const u32 color_table[] = {
+	DRM_FORMAT_BGR888,
+	DRM_FORMAT_RGB888,
+	DRM_FORMAT_XBGR2101010,
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_RGBA8888,
+	DRM_FORMAT_ABGR8888,
+	DRM_FORMAT_ARGB8888,
+	DRM_FORMAT_XBGR8888,
+	DRM_FORMAT_YUYV,
+	DRM_FORMAT_UYVY,
+	DRM_FORMAT_AYUV,
+	DRM_FORMAT_NV12,
+	DRM_FORMAT_NV16,
+	DRM_FORMAT_Y8,
+	DRM_FORMAT_Y10,
+	DRM_FORMAT_XVUY2101010,
+	DRM_FORMAT_VUY888,
+	DRM_FORMAT_XVUY8888,
+	DRM_FORMAT_XV15,
+	DRM_FORMAT_XV20,
+};
+
+/*********************** Inline Functions/Macros *****************************/
+#define to_mixer_hw(p) (&((p)->mixer->mixer_hw))
+#define to_xlnx_crtc(x)	container_of(x, struct xlnx_crtc, crtc)
+#define to_xlnx_plane(x)	container_of(x, struct xlnx_mix_plane, base)
+#define to_xlnx_mixer(x)	container_of(x, struct xlnx_mix, crtc)
+
+/**
+ * enum xlnx_mix_layer_id - Describes the layer by index to be acted upon
+ * @XVMIX_LAYER_MASTER: Master layer
+ * @XVMIX_LAYER_1: Layer 1
+ * @XVMIX_LAYER_2: Layer 2
+ * @XVMIX_LAYER_3: Layer 3
+ * @XVMIX_LAYER_4: Layer 4
+ * @XVMIX_LAYER_5: Layer 5
+ * @XVMIX_LAYER_6: Layer 6
+ * @XVMIX_LAYER_7: Layer 7
+ * @XVMIX_LAYER_8: Layer 8
+ * @XVMIX_LAYER_9: Layer 9
+ * @XVMIX_LAYER_10: Layer 10
+ * @XVMIX_LAYER_11: Layer 11
+ * @XVMIX_LAYER_12: Layer 12
+ * @XVMIX_LAYER_13: Layer 13
+ * @XVMIX_LAYER_14: Layer 14
+ * @XVMIX_LAYER_15: Layer 15
+ * @XVMIX_LAYER_16: Layer 16
+ */
+enum xlnx_mix_layer_id {
+	XVMIX_LAYER_MASTER = 0,
+	XVMIX_LAYER_1,
+	XVMIX_LAYER_2,
+	XVMIX_LAYER_3,
+	XVMIX_LAYER_4,
+	XVMIX_LAYER_5,
+	XVMIX_LAYER_6,
+	XVMIX_LAYER_7,
+	XVMIX_LAYER_8,
+	XVMIX_LAYER_9,
+	XVMIX_LAYER_10,
+	XVMIX_LAYER_11,
+	XVMIX_LAYER_12,
+	XVMIX_LAYER_13,
+	XVMIX_LAYER_14,
+	XVMIX_LAYER_15,
+	XVMIX_LAYER_16
+};
+
+/**
+ * struct xlnx_mix_layer_data - Describes the hardware configuration of a given
+ * mixer layer
+ * @hw_config: struct specifying the IP hardware constraints for this layer
+ * @vid_fmt: DRM format for this layer
+ * @can_alpha: Indicates that layer alpha is enabled for this layer
+ * @can_scale: Indicates that layer scaling is enabled for this layer
+ * @is_streaming: Indicates layer is not using mixer DMA but streaming from
+ *  external DMA
+ * @max_width: Max possible pixel width
+ * @max_height: Max possible pixel height
+ * @min_width: Min possible pixel width
+ * @min_height: Min possible pixel height
+ * @layer_regs: struct containing current cached register values
+ * @buff_addr: Current physical address of image buffer
+ * @x_pos: Current CRTC x offset
+ * @y_pos: Current CRTC y offset
+ * @width: Current width in pixels
+ * @height: Current hight in pixels
+ * @stride: Current stride (when Mixer is performing DMA)
+ * @alpha: Current alpha setting
+ * @is_active: Logical flag indicating layer in use.  If false, calls to
+ *  enable layer will be ignored.
+ * @scale_fact: Current scaling factor applied to layer
+ * @id: The logical layer id identifies which layer this struct describes
+ *  (e.g. 0 = master, 1-15 = overlay).
+ *
+ * All mixer layers are reprsented by an instance of this struct:
+ * output streaming, overlay, logo.
+ * Current layer-specific register state is stored in the layer_regs struct.
+ * The hardware configuration is stored in struct hw_config.
+ *
+ * Note:
+ * Some properties of the logo layer are unique and not described in this
+ * struct.  Those properites are part of the xlnx_mix struct as global
+ * properties.
+ */
+struct xlnx_mix_layer_data {
+	struct {
+		u32     vid_fmt;
+		bool    can_alpha;
+		bool    can_scale;
+		bool    is_streaming;
+		u32     max_width;
+		u32     max_height;
+		u32     min_width;
+		u32     min_height;
+	} hw_config;
+
+	struct {
+		u64     buff_addr1;
+		u64     buff_addr2;
+		u32     x_pos;
+		u32     y_pos;
+		u32     width;
+		u32     height;
+		u32     stride;
+		u32     alpha;
+		bool	is_active;
+		u32	scale_fact;
+	} layer_regs;
+
+	enum xlnx_mix_layer_id id;
+};
+
+/**
+ * struct xlnx_mix_hw - Describes a mixer IP block instance within the design
+ * @base: Base physical address of Mixer IP in memory map
+ * @logo_layer_en: Indicates logo layer is enabled in hardware
+ * @logo_pixel_alpha_enabled: Indicates that per-pixel alpha supported for logo
+ *  layer
+ * @csc_enabled: Indicates that colorimetry coefficients are programmable
+ * @max_layer_width: Max possible width for any layer on this Mixer
+ * @max_layer_height: Max possible height for any layer on this Mixer
+ * @max_logo_layer_width: Min possible width for any layer on this Mixer
+ * @max_logo_layer_height: Min possible height for any layer on this Mixer
+ * @num_layers: Max number of layers (excl: logo)
+ * @bg_layer_bpc: Bits per component for the background streaming layer
+ * @dma_addr_size: dma address size in bits
+ * @ppc: Pixels per component
+ * @irq: Interrupt request number assigned
+ * @bg_color: Current RGB color value for internal background color generator
+ * @layer_data: Array of layer data
+ * @layer_cnt: Layer data array count
+ * @max_layers: Maximum number of layers supported by hardware
+ * @logo_layer_id: Index of logo layer
+ * @logo_en_mask: Mask used to enable logo layer
+ * @enable_all_mask: Mask used to enable all layers
+ * @reset_gpio: GPIO line used to reset IP between modesetting operations
+ * @intrpt_handler_fn: Interrupt handler function called when frame is completed
+ * @intrpt_data: Data pointer passed to interrupt handler
+ *
+ * Used as the primary data structure for many L2 driver functions. Logo layer
+ * data, if enabled within the IP, is described in this structure.  All other
+ * layers are described by an instance of xlnx_mix_layer_data referenced by this
+ * struct.
+ *
+ */
+struct xlnx_mix_hw {
+	void __iomem        *base;
+	bool                logo_layer_en;
+	bool                logo_pixel_alpha_enabled;
+	u32		    csc_enabled;
+	u32                 max_layer_width;
+	u32                 max_layer_height;
+	u32                 max_logo_layer_width;
+	u32                 max_logo_layer_height;
+	u32                 num_layers;
+	u32                 bg_layer_bpc;
+	u32		    dma_addr_size;
+	u32                 ppc;
+	int		    irq;
+	u64		    bg_color;
+	struct xlnx_mix_layer_data *layer_data;
+	u32 layer_cnt;
+	u32 max_layers;
+	u32 logo_layer_id;
+	u32 logo_en_mask;
+	u32 enable_all_mask;
+	struct gpio_desc *reset_gpio;
+	void (*intrpt_handler_fn)(void *);
+	void *intrpt_data;
+};
+
+/**
+ * struct xlnx_mix - Container for interfacing DRM driver to mixer
+ * @mixer_hw: Object representing actual hardware state of mixer
+ * @master: Logical master device from xlnx drm
+ * @crtc: Xilinx DRM driver crtc object
+ * @drm_primary_layer: Hardware layer serving as logical DRM primary layer
+ * @hw_master_layer: Base video streaming layer
+ * @hw_logo_layer: Hardware logo layer
+ * @planes: Mixer overlay layers
+ * @num_planes : number of planes
+ * @max_width : maximum width of plane
+ * @max_height : maximum height of plane
+ * @max_cursor_width : maximum cursor width
+ * @max_cursor_height: maximum cursor height
+ * @alpha_prop: Global layer alpha property
+ * @scale_prop: Layer scale property (1x, 2x or 4x)
+ * @bg_color: Background color property for primary layer
+ * @drm: core drm object
+ * @pixel_clock: pixel clock for mixer
+ * @pixel_clock_enabled: pixel clock status
+ * @dpms: mixer drm state
+ * @event: vblank pending event
+ * @vtc_bridge: vtc_bridge structure
+ *
+ * Contains pointers to logical constructions such as the DRM plane manager as
+ * well as pointers to distinquish the mixer layer serving as the DRM "primary"
+ * plane from the actual mixer layer which serves as the background layer in
+ * hardware.
+ *
+ */
+struct xlnx_mix {
+	struct xlnx_mix_hw mixer_hw;
+	struct platform_device *master;
+	struct xlnx_crtc crtc;
+	struct xlnx_mix_plane *drm_primary_layer;
+	struct xlnx_mix_plane *hw_master_layer;
+	struct xlnx_mix_plane *hw_logo_layer;
+	struct xlnx_mix_plane *planes;
+	u32 num_planes;
+	u32 max_width;
+	u32 max_height;
+	u32 max_cursor_width;
+	u32 max_cursor_height;
+	struct drm_property *alpha_prop;
+	struct drm_property *scale_prop;
+	struct drm_property *bg_color;
+	struct drm_device *drm;
+	struct clk *pixel_clock;
+	bool pixel_clock_enabled;
+	int dpms;
+	struct drm_pending_vblank_event *event;
+	struct xlnx_bridge *vtc_bridge;
+	struct xlnx_bridge *disp_bridge;
+};
+
+/**
+ * struct xlnx_mix_plane_dma - Xilinx drm plane VDMA object
+ *
+ * @chan: dma channel
+ * @xt: dma interleaved configuration template
+ * @sgl: data chunk for dma_interleaved_template
+ * @is_active: flag if the DMA is active
+ */
+struct xlnx_mix_plane_dma {
+	struct dma_chan *chan;
+	struct dma_interleaved_template xt;
+	struct data_chunk sgl[1];
+	bool is_active;
+};
+
+/**
+ * struct xlnx_mix_plane - Xilinx drm plane object
+ *
+ * @base: base drm plane object
+ * @mixer_layer: video mixer hardware layer data instance
+ * @mixer: mixer DRM object
+ * @dma: dma object
+ * @id: plane id
+ * @dpms: current dpms level
+ * @format: pixel format
+ */
+struct xlnx_mix_plane {
+	struct drm_plane base;
+	struct xlnx_mix_layer_data *mixer_layer;
+	struct xlnx_mix *mixer;
+	struct xlnx_mix_plane_dma dma[XVMIX_MAX_NUM_SUB_PLANES];
+	int id;
+	int dpms;
+	u32 format;
+};
+
+static inline void reg_writel(void __iomem *base, int offset, u32 val)
+{
+	writel(val, base + offset);
+}
+
+static inline void reg_writeq(void __iomem *base, int offset, u64 val)
+{
+	writel(lower_32_bits(val), base + offset);
+	writel(upper_32_bits(val), base + offset + 4);
+}
+
+static inline u32 reg_readl(void __iomem *base, int offset)
+{
+	return readl(base + offset);
+}
+
+static u32 xlnx_mix_get_bus_fmt(struct xlnx_mix *mixer)
+{
+	struct xlnx_mix_layer_data *master;
+
+	master = &mixer->mixer_hw.layer_data[XVMIX_MASTER_LAYER_IDX];
+
+	switch (master->hw_config.vid_fmt) {
+	case DRM_FORMAT_BGR888:
+	case DRM_FORMAT_RGB888:
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_RGBA8888:
+	case DRM_FORMAT_ABGR8888:
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_XBGR8888:
+		return MEDIA_BUS_FMT_RBG888_1X24;
+	case DRM_FORMAT_XBGR2101010:
+		return MEDIA_BUS_FMT_RBG101010_1X30;
+	case DRM_FORMAT_YUYV:
+	case DRM_FORMAT_UYVY:
+	case DRM_FORMAT_NV16:
+		return MEDIA_BUS_FMT_UYVY8_1X16;
+	case DRM_FORMAT_AYUV:
+	case DRM_FORMAT_VUY888:
+	case DRM_FORMAT_XVUY8888:
+		return MEDIA_BUS_FMT_VUY8_1X24;
+	case DRM_FORMAT_NV12:
+		return MEDIA_BUS_FMT_VYYUYY8_1X24;
+	case DRM_FORMAT_Y8:
+		return MEDIA_BUS_FMT_Y8_1X8;
+	case DRM_FORMAT_Y10:
+		return MEDIA_BUS_FMT_Y10_1X10;
+	case DRM_FORMAT_XVUY2101010:
+		return MEDIA_BUS_FMT_VUY10_1X30;
+	case DRM_FORMAT_XV15:
+		return MEDIA_BUS_FMT_VYYUYY10_4X20;
+	case DRM_FORMAT_XV20:
+		return MEDIA_BUS_FMT_UYVY10_1X20;
+	default:
+		DRM_DEBUG_KMS("invalid layer format: %d\n",
+			      master->hw_config.vid_fmt);
+		return 0;
+	}
+}
+
+/**
+ * xlnx_mix_intrpt_enable_done - Enables interrupts
+ * @mixer: instance of mixer IP core
+ *
+ * Enables interrupts in the mixer core
+ */
+static void xlnx_mix_intrpt_enable_done(struct xlnx_mix_hw *mixer)
+{
+	u32 curr_val = reg_readl(mixer->base, XVMIX_IER);
+
+	/* Enable Interrupts */
+	reg_writel(mixer->base, XVMIX_IER, curr_val | XVMIX_IRQ_DONE_MASK);
+	reg_writel(mixer->base, XVMIX_GIE, XVMIX_GIE_EN_MASK);
+}
+
+/**
+ * xlnx_mix_intrpt_disable - Disable interrupts
+ * @mixer: instance of mixer IP core
+ *
+ * Disables interrupts in the mixer core
+ */
+static void xlnx_mix_intrpt_disable(struct xlnx_mix_hw *mixer)
+{
+	u32 curr_val =  reg_readl(mixer->base, XVMIX_IER);
+
+	reg_writel(mixer->base, XVMIX_IER, curr_val & (~XVMIX_IRQ_DONE_MASK));
+	reg_writel(mixer->base, XVMIX_GIE, 0);
+}
+
+/**
+ * xlnx_mix_start - Start the mixer core video generator
+ * @mixer: Mixer core instance for which to start video output
+ *
+ * Starts the core to generate a video frame.
+ */
+static void xlnx_mix_start(struct xlnx_mix_hw *mixer)
+{
+	u32 val;
+
+	val = XVMIX_AP_RST_MASK | XVMIX_AP_EN_MASK;
+	reg_writel(mixer->base, XVMIX_AP_CTRL, val);
+}
+
+/**
+ * xlnx_mix_stop - Stop the mixer core video generator
+ * @mixer: Mixer core instance for which to stop video output
+ *
+ * Starts the core to generate a video frame.
+ */
+static void xlnx_mix_stop(struct xlnx_mix_hw *mixer)
+{
+	reg_writel(mixer->base, XVMIX_AP_CTRL, 0);
+}
+
+static inline uint32_t xlnx_mix_get_intr_status(struct xlnx_mix_hw *mixer)
+{
+	return reg_readl(mixer->base, XVMIX_ISR) & XVMIX_IRQ_DONE_MASK;
+}
+
+static inline void xlnx_mix_clear_intr_status(struct xlnx_mix_hw *mixer,
+					      uint32_t intr)
+{
+	reg_writel(mixer->base, XVMIX_ISR, intr);
+}
+
+/**
+ * xlnx_mix_set_yuv2_rgb_coeff - Programs yuv to rgb coeffiecients
+ * @plane: Xilinx drm plane object
+ * @enc: Colorimetry encoding scheme
+ * @range: Colorimetry range
+ * Programs the colorimetry coefficients required for yuv to rgb
+ * conversion.
+ */
+static void xlnx_mix_set_yuv2_rgb_coeff(struct xlnx_mix_plane *plane,
+					enum drm_color_encoding enc,
+					enum drm_color_range range)
+{
+	struct xlnx_mix *mixer = plane->mixer;
+	u32 i;
+	u32 bpc_scale = 1 << (mixer->mixer_hw.bg_layer_bpc - 8);
+
+	for (i = 0; i < XVMIX_CSC_MATRIX_SIZE; i++)
+		reg_writel(mixer->mixer_hw.base, XVMIX_K00_1 + i * 8,
+			   xlnx_mix_yuv2rgb_coeffs[enc][range][i] *
+			   XVMIX_CSC_SCALE_FACTOR / XVMIX_CSC_DIVISOR);
+
+	for (i = XVMIX_CSC_MATRIX_SIZE; i < XVMIX_CSC_COEFF_SIZE; i++)
+		reg_writel(mixer->mixer_hw.base, XVMIX_K00_1 + i * 8,
+			   (xlnx_mix_yuv2rgb_coeffs[enc][range][i] *
+			    bpc_scale));
+}
+
+/**
+ * xlnx_mix_set_rgb2_yuv_coeff - Programs rgb to yuv coeffiecients
+ * @plane: Xilinx drm plane object
+ * @enc: Colorimetry encoding scheme
+ * @range: Colorimetry range
+ * Programs the colorimetry coefficients required for rgb to yuv
+ * conversion.
+ */
+static void xlnx_mix_set_rgb2_yuv_coeff(struct xlnx_mix_plane *plane,
+					enum drm_color_encoding enc,
+					enum drm_color_range range)
+{
+	struct xlnx_mix *mixer = plane->mixer;
+	u32 i;
+	u32 bpc_scale = 1 << (mixer->mixer_hw.bg_layer_bpc - 8);
+
+	for (i = 0; i < XVMIX_CSC_MATRIX_SIZE; i++)
+		reg_writel(mixer->mixer_hw.base, XVMIX_K00_2 + i * 8,
+			   xlnx_mix_rgb2yuv_coeffs[enc][range][i] *
+			   XVMIX_CSC_SCALE_FACTOR / XVMIX_CSC_DIVISOR);
+
+	for (i = XVMIX_CSC_MATRIX_SIZE; i < XVMIX_CSC_COEFF_SIZE; i++)
+		reg_writel(mixer->mixer_hw.base, XVMIX_K00_2 + i * 8,
+			   (xlnx_mix_rgb2yuv_coeffs[enc][range][i] *
+			    bpc_scale));
+}
+
+/**
+ * xlnx_mix_get_layer_data - Retrieve current hardware and register
+ * values for a logical video layer
+ * @mixer: Mixer instance to interrogate
+ * @id: Id of layer for which data is requested
+ *
+ * Return:
+ * Structure containing layer-specific data; NULL upon failure
+ */
+static struct xlnx_mix_layer_data *
+xlnx_mix_get_layer_data(struct xlnx_mix_hw *mixer, enum xlnx_mix_layer_id id)
+{
+	u32 i;
+	struct xlnx_mix_layer_data *layer_data;
+
+	for (i = 0; i <= (mixer->layer_cnt - 1); i++) {
+		layer_data = &mixer->layer_data[i];
+		if (layer_data->id == id)
+			return layer_data;
+	}
+	return NULL;
+}
+
+/**
+ * xlnx_mix_set_active_area - Sets the number of active horizontal and
+ * vertical scan lines for the mixer background layer.
+ * @mixer: Mixer instance for which to set a new viewable area
+ * @hactive: Width of new background image dimension
+ * @vactive: Height of new background image dimension
+ *
+ * Minimum values are 64x64 with maximum values determined by the IP hardware
+ * design.
+ *
+ * Return:
+ * Zero on success, -EINVAL on failure
+ */
+static int xlnx_mix_set_active_area(struct xlnx_mix_hw *mixer,
+				    u32 hactive, u32 vactive)
+{
+	struct xlnx_mix_layer_data *ld =
+		xlnx_mix_get_layer_data(mixer, XVMIX_LAYER_MASTER);
+
+	if (hactive > ld->hw_config.max_width ||
+	    vactive > ld->hw_config.max_height) {
+		DRM_ERROR("Invalid layer dimention\n");
+		return -EINVAL;
+	}
+	/* set resolution */
+	reg_writel(mixer->base, XVMIX_HEIGHT_DATA, vactive);
+	reg_writel(mixer->base, XVMIX_WIDTH_DATA, hactive);
+	ld->layer_regs.width  = hactive;
+	ld->layer_regs.height = vactive;
+
+	return 0;
+}
+
+/**
+ * is_window_valid - Validate requested plane dimensions
+ * @mixer: Mixer core instance for which to stop video output
+ * @x_pos: x position requested for start of plane
+ * @y_pos: y position requested for start of plane
+ * @width: width of plane
+ * @height: height of plane
+ * @scale: scale factor of plane
+ *
+ * Validates if the requested window is within the frame boundary
+ *
+ * Return:
+ * true on success, false on failure
+ */
+static bool is_window_valid(struct xlnx_mix_hw *mixer, u32 x_pos, u32 y_pos,
+			    u32 width, u32 height, u32 scale)
+{
+	struct xlnx_mix_layer_data *master_layer;
+	int scale_factor[3] = {1, 2, 4};
+
+	master_layer = xlnx_mix_get_layer_data(mixer, XVMIX_LAYER_MASTER);
+
+	/* Check if window scale factor is set */
+	if (scale < XVMIX_SCALE_FACTOR_INVALID) {
+		width  *= scale_factor[scale];
+		height *= scale_factor[scale];
+	}
+
+	/* verify overlay falls within currently active background area */
+	if (((x_pos + width)  <= master_layer->layer_regs.width) &&
+	    ((y_pos + height) <= master_layer->layer_regs.height))
+		return true;
+
+	DRM_ERROR("Requested plane dimensions can't be set\n");
+	return false;
+}
+
+/**
+ *  xlnx_mix_layer_enable - Enables the requested layers
+ * @mixer: Mixer instance in which to enable a video layer
+ * @id: Logical id (e.g. 16 = logo layer) to enable
+ *
+ * Enables (permit video output) for layers in mixer
+ * Enables the layer denoted by id in the IP core.
+ * Layer 0 will indicate the background layer and layer 8 the logo
+ * layer. Passing max layers value will enable all
+ */
+static void xlnx_mix_layer_enable(struct xlnx_mix_hw *mixer,
+				  enum xlnx_mix_layer_id id)
+{
+	struct xlnx_mix_layer_data *layer_data;
+	u32 curr_state;
+
+	/* Ensure layer is marked as 'active' by application before
+	 * turning on in hardware.  In some cases, layer register data
+	 * may be written to otherwise inactive layers in lieu of, eventually,
+	 * turning them on.
+	 */
+	layer_data = xlnx_mix_get_layer_data(mixer, id);
+	if (!layer_data) {
+		DRM_ERROR("Invalid layer id %d\n", id);
+		return;
+	}
+	if (!layer_data->layer_regs.is_active)
+		return; /* for inactive layers silently return */
+
+	/* Check if request is to enable all layers or single layer */
+	if (id == mixer->max_layers) {
+		reg_writel(mixer->base, XVMIX_LAYERENABLE_DATA,
+			   mixer->enable_all_mask);
+
+	} else if ((id < mixer->layer_cnt) || ((id == mixer->logo_layer_id) &&
+		   mixer->logo_layer_en)) {
+		curr_state = reg_readl(mixer->base, XVMIX_LAYERENABLE_DATA);
+		if (id == mixer->logo_layer_id)
+			curr_state |= mixer->logo_en_mask;
+		else
+			curr_state |= BIT(id);
+		reg_writel(mixer->base, XVMIX_LAYERENABLE_DATA, curr_state);
+	} else {
+		DRM_ERROR("Can't enable requested layer %d\n", id);
+	}
+}
+
+/**
+ * xlnx_mix_disp_layer_enable - Enables video output represented by the
+ * plane object
+ * @plane: Drm plane object describing video layer to enable
+ *
+ */
+static void xlnx_mix_disp_layer_enable(struct xlnx_mix_plane *plane)
+{
+	struct xlnx_mix_hw *mixer_hw;
+	struct xlnx_mix_layer_data *l_data;
+	u32 id;
+
+	if (!plane)
+		return;
+	mixer_hw = to_mixer_hw(plane);
+	l_data = plane->mixer_layer;
+	id = l_data->id;
+	if (id > mixer_hw->logo_layer_id) {
+		DRM_DEBUG_KMS("Attempt to activate invalid layer: %d\n", id);
+		return;
+	}
+	if (id == XVMIX_LAYER_MASTER && !l_data->hw_config.is_streaming)
+		return;
+
+	xlnx_mix_layer_enable(mixer_hw, id);
+}
+
+/**
+ * xlnx_mix_layer_disable - Disables the requested layer
+ * @mixer:  Mixer for which the layer will be disabled
+ * @id: Logical id of the layer to be disabled (0-16)
+ *
+ * Disables the layer denoted by layer_id in the IP core.
+ * Layer 0 will indicate the background layer and layer 16 the logo
+ * layer. Passing the value of max layers will disable all
+ * layers.
+ */
+static void xlnx_mix_layer_disable(struct xlnx_mix_hw *mixer,
+				   enum xlnx_mix_layer_id id)
+{
+	u32 num_layers, curr_state;
+
+	num_layers = mixer->layer_cnt;
+
+	if (id == mixer->max_layers) {
+		reg_writel(mixer->base, XVMIX_LAYERENABLE_DATA,
+			   XVMIX_MASK_DISABLE_ALL_LAYERS);
+	} else if ((id < num_layers) ||
+		   ((id == mixer->logo_layer_id) && (mixer->logo_layer_en))) {
+		curr_state = reg_readl(mixer->base, XVMIX_LAYERENABLE_DATA);
+		if (id == mixer->logo_layer_id)
+			curr_state &= ~(mixer->logo_en_mask);
+		else
+			curr_state &= ~(BIT(id));
+		reg_writel(mixer->base, XVMIX_LAYERENABLE_DATA, curr_state);
+	} else {
+		DRM_ERROR("Can't disable requested layer %d\n", id);
+	}
+}
+
+/**
+ * xlnx_mix_disp_layer_disable - Disables video output represented by the
+ * plane object
+ * @plane: Drm plane object describing video layer to disable
+ *
+ */
+static void xlnx_mix_disp_layer_disable(struct xlnx_mix_plane *plane)
+{
+	struct xlnx_mix_hw *mixer_hw;
+	u32 layer_id;
+
+	if (plane)
+		mixer_hw = to_mixer_hw(plane);
+	else
+		return;
+	layer_id = plane->mixer_layer->id;
+	if (layer_id > mixer_hw->logo_layer_id)
+		return;
+
+	xlnx_mix_layer_disable(mixer_hw, layer_id);
+}
+
+static int xlnx_mix_mark_layer_inactive(struct xlnx_mix_plane *plane)
+{
+	if (!plane || !plane->mixer_layer)
+		return -ENODEV;
+
+	plane->mixer_layer->layer_regs.is_active = false;
+
+	return 0;
+}
+
+/* apply mode to plane pipe */
+static void xlnx_mix_plane_commit(struct drm_plane *base_plane)
+{
+	struct xlnx_mix_plane *plane = to_xlnx_plane(base_plane);
+	struct dma_async_tx_descriptor *desc;
+	enum dma_ctrl_flags flags;
+	unsigned int i;
+
+	/* for xlnx video framebuffer dma, if used */
+	xilinx_xdma_drm_config(plane->dma[0].chan, plane->format);
+	for (i = 0; i < XVMIX_MAX_NUM_SUB_PLANES; i++) {
+		struct xlnx_mix_plane_dma *dma = &plane->dma[i];
+
+		if (dma->chan && dma->is_active) {
+			flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
+			desc = dmaengine_prep_interleaved_dma(dma->chan,
+							      &dma->xt,
+							      flags);
+			if (!desc) {
+				DRM_ERROR("failed to prepare DMA descriptor\n");
+				return;
+			}
+			dmaengine_submit(desc);
+			dma_async_issue_pending(dma->chan);
+		}
+	}
+}
+
+static int xlnx_mix_plane_get_max_width(struct drm_plane *base_plane)
+{
+	struct xlnx_mix_plane *plane = to_xlnx_plane(base_plane);
+
+	return plane->mixer->max_width;
+}
+
+static int xlnx_mix_plane_get_max_height(struct drm_plane *base_plane)
+{
+	struct xlnx_mix_plane *plane = to_xlnx_plane(base_plane);
+
+	return plane->mixer->max_height;
+}
+
+static int xlnx_mix_plane_get_max_cursor_width(struct drm_plane *base_plane)
+{
+	struct xlnx_mix_plane *plane = to_xlnx_plane(base_plane);
+
+	return plane->mixer->max_cursor_width;
+}
+
+static int xlnx_mix_plane_get_max_cursor_height(struct drm_plane *base_plane)
+{
+	struct xlnx_mix_plane *plane = to_xlnx_plane(base_plane);
+
+	return plane->mixer->max_cursor_height;
+}
+
+static int xlnx_mix_crtc_get_max_width(struct xlnx_crtc *crtc)
+{
+	return xlnx_mix_plane_get_max_width(crtc->crtc.primary);
+}
+
+static int xlnx_mix_crtc_get_max_height(struct xlnx_crtc *crtc)
+{
+	return xlnx_mix_plane_get_max_height(crtc->crtc.primary);
+}
+
+static unsigned int xlnx_mix_crtc_get_max_cursor_width(struct xlnx_crtc *crtc)
+{
+	return xlnx_mix_plane_get_max_cursor_width(crtc->crtc.primary);
+}
+
+static unsigned int xlnx_mix_crtc_get_max_cursor_height(struct xlnx_crtc *crtc)
+{
+	return xlnx_mix_plane_get_max_cursor_height(crtc->crtc.primary);
+}
+
+/**
+ * xlnx_mix_crtc_get_format - Get the current device format
+ * @crtc: xlnx crtc object
+ *
+ * Get the current format of pipeline
+ *
+ * Return: the corresponding DRM_FORMAT_XXX
+ */
+static uint32_t xlnx_mix_crtc_get_format(struct xlnx_crtc *crtc)
+{
+	struct xlnx_mix_plane *plane = to_xlnx_plane(crtc->crtc.primary);
+
+	return plane->format;
+}
+
+/**
+ * xlnx_mix_crtc_get_align - Get the alignment value for pitch
+ * @crtc: xlnx crtc object
+ *
+ * Get the alignment value for pitch from the plane
+ *
+ * Return: The alignment value if successful, or the error code.
+ */
+static unsigned int xlnx_mix_crtc_get_align(struct xlnx_crtc *crtc)
+{
+	struct xlnx_mix_plane *plane = to_xlnx_plane(crtc->crtc.primary);
+	struct xlnx_mix *m = plane->mixer;
+
+	return XVMIX_BASE_ALIGN * m->mixer_hw.ppc;
+}
+
+/**
+ * xlnx_mix_attach_plane_prop - Attach mixer-specific drm property to
+ * the given plane
+ * @plane: Xilinx drm plane object to inspect and attach appropriate
+ *  properties to
+ *
+ * The linked mixer layer will be inspected to see what capabilities it offers
+ * (e.g. global layer alpha; scaling) and drm property objects that indicate
+ * those capabilities will then be attached and initialized to default values.
+ */
+static void xlnx_mix_attach_plane_prop(struct xlnx_mix_plane *plane)
+{
+	struct drm_mode_object *base = &plane->base.base;
+	struct xlnx_mix *mixer = plane->mixer;
+
+	if (plane->mixer_layer->hw_config.can_scale)
+		drm_object_attach_property(base, mixer->scale_prop,
+					   XVMIX_SCALE_FACTOR_1X);
+	if (plane->mixer_layer->hw_config.can_alpha)
+		drm_object_attach_property(base, mixer->alpha_prop,
+					   XVMIX_ALPHA_MAX);
+	if (mixer->mixer_hw.csc_enabled) {
+		u32 supported_encodings = BIT(DRM_COLOR_YCBCR_BT601) |
+					  BIT(DRM_COLOR_YCBCR_BT709) |
+					  BIT(DRM_COLOR_YCBCR_BT2020);
+		u32 supported_ranges = BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
+				       BIT(DRM_COLOR_YCBCR_FULL_RANGE);
+		enum drm_color_encoding encoding = DRM_COLOR_YCBCR_BT709;
+		enum drm_color_range range = DRM_COLOR_YCBCR_LIMITED_RANGE;
+
+		drm_plane_create_color_properties(&plane->base,
+						  supported_encodings,
+						  supported_ranges,
+						  encoding, range);
+	}
+}
+
+static int xlnx_mix_mark_layer_active(struct xlnx_mix_plane *plane)
+{
+	if (!plane->mixer_layer)
+		return -ENODEV;
+	plane->mixer_layer->layer_regs.is_active = true;
+
+	return 0;
+}
+
+static bool xlnx_mix_isfmt_support(u32 format)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(color_table); i++) {
+		if (format == color_table[i])
+			return true;
+	}
+	return false;
+}
+
+/*************** DISPLAY ************/
+
+/**
+ * xlnx_mix_get_layer_scaling - Get layer scaling factor
+ * @mixer: Mixer instance to program with new background color
+ * @id: Plane id
+ *
+ * Applicable only for overlay layers
+ *
+ * Return:
+ * scaling factor of the specified layer
+ */
+static int xlnx_mix_get_layer_scaling(struct xlnx_mix_hw *mixer,
+				      enum xlnx_mix_layer_id id)
+{
+	int scale_factor = 0;
+	u32 reg;
+	struct xlnx_mix_layer_data *l_data = xlnx_mix_get_layer_data(mixer, id);
+
+	if (id == mixer->logo_layer_id) {
+		if (mixer->logo_layer_en) {
+			if (mixer->max_layers > XVMIX_MAX_OVERLAY_LAYERS)
+				reg = XVMIX_LOGOSCALEFACTOR_DATA +
+					XVMIX_LOGO_OFFSET;
+			else
+				reg = XVMIX_LOGOSCALEFACTOR_DATA;
+			scale_factor = reg_readl(mixer->base, reg);
+			l_data->layer_regs.scale_fact = scale_factor;
+		}
+	} else {
+		/*Layer0-Layer15*/
+		if (id < mixer->logo_layer_id && l_data->hw_config.can_scale) {
+			reg = XVMIX_LAYERSCALE_0_DATA + (id * XVMIX_REG_OFFSET);
+			scale_factor = reg_readl(mixer->base, reg);
+			l_data->layer_regs.scale_fact = scale_factor;
+		}
+	}
+	return scale_factor;
+}
+
+/**
+ * xlnx_mix_set_layer_window - Sets the position of an overlay layer
+ * @mixer: Specific mixer object instance controlling the video
+ * @id: Logical layer id (1-15) to be positioned
+ * @x_pos: new: Column to start display of overlay layer
+ * @y_pos: new: Row to start display of overlay layer
+ * @width: Number of active columns to dislay for overlay layer
+ * @height: Number of active columns to display for overlay layer
+ * @stride: Width in bytes of overaly memory buffer (memory layer only)
+ *
+ * Sets the position of an overlay layer over the background layer (layer 0)
+ * Applicable only for layers 1-15 or the logo layer
+ *
+ * Return:
+ * Zero on success, -EINVAL if position is invalid or -ENODEV if layer
+ */
+static int xlnx_mix_set_layer_window(struct xlnx_mix_hw *mixer,
+				     enum xlnx_mix_layer_id id, u32 x_pos,
+				     u32 y_pos, u32 width, u32 height,
+				     u32 stride)
+{
+	struct xlnx_mix_layer_data *l_data;
+	u32 scale = 0;
+	int status = -EINVAL;
+	u32 x_reg, y_reg, w_reg, h_reg, s_reg;
+	u32 off;
+
+	l_data = xlnx_mix_get_layer_data(mixer, id);
+	if (!l_data)
+		return status;
+
+	scale = xlnx_mix_get_layer_scaling(mixer, id);
+	if (!is_window_valid(mixer, x_pos, y_pos, width, height, scale))
+		return status;
+
+	if (id == mixer->logo_layer_id) {
+		if (!(mixer->logo_layer_en &&
+		      width <= l_data->hw_config.max_width &&
+		      height <= l_data->hw_config.max_height &&
+		      height >= l_data->hw_config.min_height &&
+		      width >= l_data->hw_config.min_width))
+			return status;
+
+		if (mixer->max_layers > XVMIX_MAX_OVERLAY_LAYERS) {
+			x_reg = XVMIX_LOGOSTARTX_DATA + XVMIX_LOGO_OFFSET;
+			y_reg = XVMIX_LOGOSTARTY_DATA + XVMIX_LOGO_OFFSET;
+			w_reg = XVMIX_LOGOWIDTH_DATA + XVMIX_LOGO_OFFSET;
+			h_reg = XVMIX_LOGOHEIGHT_DATA + XVMIX_LOGO_OFFSET;
+		} else {
+			x_reg = XVMIX_LOGOSTARTX_DATA;
+			y_reg = XVMIX_LOGOSTARTY_DATA;
+			w_reg = XVMIX_LOGOWIDTH_DATA;
+			h_reg = XVMIX_LOGOHEIGHT_DATA;
+		}
+		reg_writel(mixer->base, x_reg, x_pos);
+		reg_writel(mixer->base, y_reg, y_pos);
+		reg_writel(mixer->base, w_reg, width);
+		reg_writel(mixer->base, h_reg, height);
+		l_data->layer_regs.x_pos = x_pos;
+		l_data->layer_regs.y_pos = y_pos;
+		l_data->layer_regs.width = width;
+		l_data->layer_regs.height = height;
+		status = 0;
+	} else {
+		 /*Layer1-Layer15*/
+
+		if (!(id < mixer->layer_cnt &&
+		      width <= l_data->hw_config.max_width &&
+		      width >= l_data->hw_config.min_width))
+			return status;
+		x_reg = XVMIX_LAYERSTARTX_0_DATA;
+		y_reg = XVMIX_LAYERSTARTY_0_DATA;
+		w_reg = XVMIX_LAYERWIDTH_0_DATA;
+		h_reg = XVMIX_LAYERHEIGHT_0_DATA;
+		s_reg = XVMIX_LAYERSTRIDE_0_DATA;
+
+		off = id * XVMIX_REG_OFFSET;
+		reg_writel(mixer->base, (x_reg + off), x_pos);
+		reg_writel(mixer->base, (y_reg + off), y_pos);
+		reg_writel(mixer->base, (w_reg + off), width);
+		reg_writel(mixer->base, (h_reg + off), height);
+		l_data->layer_regs.x_pos = x_pos;
+		l_data->layer_regs.y_pos = y_pos;
+		l_data->layer_regs.width = width;
+		l_data->layer_regs.height = height;
+
+		if (!l_data->hw_config.is_streaming)
+			reg_writel(mixer->base, (s_reg + off), stride);
+		status = 0;
+	}
+	return status;
+}
+
+/**
+ * xlnx_mix_set_layer_dimensions - Set layer dimensions
+ * @plane: Drm plane object desribing video layer to reposition
+ * @crtc_x: New horizontal anchor postion from which to begin rendering
+ * @crtc_y: New vertical anchor position from which to begin rendering
+ * @width: Width, in pixels, to render from stream or memory buffer
+ * @height: Height, in pixels, to render from stream or memory buffer
+ * @stride: Width, in bytes, of a memory buffer.  Used only for
+ *  memory layers.  Use 0 for streaming layers.
+ *
+ * Establishes new coordinates and dimensions for a video plane layer
+ * New size and coordinates of window must fit within the currently active
+ * area of the crtc (e.g. the background resolution)
+ *
+ * Return: 0 if successful; Either -EINVAL if coordindate data is invalid
+ * or -ENODEV if layer data not present
+ */
+static int xlnx_mix_set_layer_dimensions(struct xlnx_mix_plane *plane,
+					 u32 crtc_x, u32 crtc_y,
+					  u32 width, u32 height, u32 stride)
+{
+	struct xlnx_mix *mixer = plane->mixer;
+	struct xlnx_mix_hw *mixer_hw = to_mixer_hw(plane);
+	struct xlnx_mix_layer_data *layer_data;
+	enum xlnx_mix_layer_id layer_id;
+	int ret = 0;
+
+	layer_data = plane->mixer_layer;
+	layer_id = layer_data->id;
+	if (layer_data->layer_regs.height != height ||
+	    layer_data->layer_regs.width != width) {
+		if (mixer->drm_primary_layer == plane)
+			xlnx_mix_layer_disable(mixer_hw, XVMIX_LAYER_MASTER);
+
+		xlnx_mix_layer_disable(mixer_hw, layer_id);
+	}
+	if (mixer->drm_primary_layer == plane) {
+		crtc_x = 0;
+		crtc_y = 0;
+		ret = xlnx_mix_set_active_area(mixer_hw, width, height);
+		if (ret)
+			return ret;
+		xlnx_mix_layer_enable(mixer_hw, XVMIX_LAYER_MASTER);
+	}
+	if (layer_id != XVMIX_LAYER_MASTER && layer_id < mixer_hw->max_layers) {
+		ret = xlnx_mix_set_layer_window(mixer_hw, layer_id, crtc_x,
+						crtc_y, width, height, stride);
+		if (ret)
+			return ret;
+		xlnx_mix_disp_layer_enable(plane);
+	}
+	return ret;
+}
+
+/**
+ * xlnx_mix_set_layer_scaling - Sets scaling factor
+ * @mixer: Instance of mixer to be subject of scaling request
+ * @id: Logical id of video layer subject to new scale setting
+ * @scale: scale Factor (1x, 2x or 4x) for horiz. and vert. dimensions
+ *
+ * Sets the scaling factor for the specified video layer
+ * Not applicable to background stream layer (layer 0)
+ *
+ * Return:
+ * Zero on success, -EINVAL on failure to set scale for layer (likely
+ * returned if resulting size of layer exceeds dimensions of active
+ * display area
+ */
+static int xlnx_mix_set_layer_scaling(struct xlnx_mix_hw *mixer,
+				      enum xlnx_mix_layer_id id, u32 scale)
+{
+	void __iomem *reg = mixer->base;
+	struct xlnx_mix_layer_data *l_data;
+	int status = 0;
+	u32 x_pos, y_pos, width, height, offset;
+
+	l_data = xlnx_mix_get_layer_data(mixer, id);
+	x_pos = l_data->layer_regs.x_pos;
+	y_pos = l_data->layer_regs.y_pos;
+	width  = l_data->layer_regs.width;
+	height = l_data->layer_regs.height;
+
+	if (!is_window_valid(mixer, x_pos, y_pos, width, height, scale))
+		return -EINVAL;
+
+	if (id == mixer->logo_layer_id) {
+		if (mixer->logo_layer_en) {
+			if (mixer->max_layers > XVMIX_MAX_OVERLAY_LAYERS)
+				reg_writel(reg, XVMIX_LOGOSCALEFACTOR_DATA +
+					   XVMIX_LOGO_OFFSET, scale);
+			else
+				reg_writel(reg, XVMIX_LOGOSCALEFACTOR_DATA,
+					   scale);
+			l_data->layer_regs.scale_fact = scale;
+			status = 0;
+		}
+	} else {
+		 /* Layer0-Layer15 */
+		if (id < mixer->layer_cnt && l_data->hw_config.can_scale) {
+			offset = id * XVMIX_REG_OFFSET;
+
+			reg_writel(reg, (XVMIX_LAYERSCALE_0_DATA + offset),
+				   scale);
+			l_data->layer_regs.scale_fact = scale;
+			status = 0;
+		}
+	}
+	return status;
+}
+
+/**
+ * xlnx_mix_set_layer_scale - Change video scale factor for video plane
+ * @plane: Drm plane object describing layer to be modified
+ * @val: Index of scale factor to use:
+ *		0 = 1x
+ *		1 = 2x
+ *		2 = 4x
+ *
+ * Return:
+ * Zero on success, either -EINVAL if scale value is illegal or
+ * -ENODEV if layer does not exist (null)
+ */
+static int xlnx_mix_set_layer_scale(struct xlnx_mix_plane *plane,
+				    uint64_t val)
+{
+	struct xlnx_mix_hw *mixer_hw = to_mixer_hw(plane);
+	struct xlnx_mix_layer_data *layer = plane->mixer_layer;
+	int ret;
+
+	if (!layer || !layer->hw_config.can_scale)
+		return -ENODEV;
+	if (val > XVMIX_SCALE_FACTOR_4X) {
+		DRM_ERROR("Mixer layer scale value illegal.\n");
+		return -EINVAL;
+	}
+	xlnx_mix_disp_layer_disable(plane);
+	msleep(50);
+	ret = xlnx_mix_set_layer_scaling(mixer_hw, layer->id, val);
+	xlnx_mix_disp_layer_enable(plane);
+
+	return ret;
+}
+
+/**
+ * xlnx_mix_set_layer_alpha - Set the alpha value
+ * @mixer: Instance of mixer controlling layer to modify
+ * @layer_id: Logical id of video overlay to adjust alpha setting
+ * @alpha: Desired alpha setting (0-255) for layer specified
+ *            255 = completely opaque
+ *            0 = fully transparent
+ *
+ * Set the layer global transparency for a video overlay
+ * Not applicable to background streaming layer
+ *
+ * Return:
+ * Zero on success, -EINVAL on failure
+ */
+static int xlnx_mix_set_layer_alpha(struct xlnx_mix_hw *mixer,
+				    enum xlnx_mix_layer_id layer_id, u32 alpha)
+{
+	struct xlnx_mix_layer_data *layer_data;
+	u32 reg;
+	int status = -EINVAL;
+
+	layer_data = xlnx_mix_get_layer_data(mixer, layer_id);
+
+	if (layer_id == mixer->logo_layer_id) {
+		if (mixer->logo_layer_en) {
+			if (mixer->max_layers > XVMIX_MAX_OVERLAY_LAYERS)
+				reg = XVMIX_LOGOALPHA_DATA + XVMIX_LOGO_OFFSET;
+			else
+				reg = XVMIX_LOGOALPHA_DATA;
+			reg_writel(mixer->base, reg, alpha);
+			layer_data->layer_regs.alpha = alpha;
+			status = 0;
+		}
+	} else {
+		 /*Layer1-Layer15*/
+		if (layer_id < mixer->layer_cnt &&
+		    layer_data->hw_config.can_alpha) {
+			u32 offset =  layer_id * XVMIX_REG_OFFSET;
+
+			reg = XVMIX_LAYERALPHA_0_DATA;
+			reg_writel(mixer->base, (reg + offset), alpha);
+			layer_data->layer_regs.alpha = alpha;
+			status = 0;
+		}
+	}
+	return status;
+}
+
+/**
+ * xlnx_mix_disp_set_layer_alpha - Change the transparency of an entire plane
+ * @plane: Video layer affected by new alpha setting
+ * @val: Value of transparency setting (0-255) with 255 being opaque
+ *  0 being fully transparent
+ *
+ * Return:
+ * Zero on success, -EINVAL on failure
+ */
+static int xlnx_mix_disp_set_layer_alpha(struct xlnx_mix_plane *plane,
+					 uint64_t val)
+{
+	struct xlnx_mix_hw *mixer_hw = to_mixer_hw(plane);
+	struct xlnx_mix_layer_data *layer = plane->mixer_layer;
+
+	if (!layer || !layer->hw_config.can_alpha)
+		return -ENODEV;
+	if (val > XVMIX_ALPHA_MAX) {
+		DRM_ERROR("Mixer layer alpha dts value illegal.\n");
+		return -EINVAL;
+	}
+	return xlnx_mix_set_layer_alpha(mixer_hw, layer->id, val);
+}
+
+/**
+ * xlnx_mix_set_layer_buff_addr - Set buff addr for layer
+ * @mixer: Instance of mixer controlling layer to modify
+ * @id: Logical id of video overlay to adjust alpha setting
+ * @luma_addr: Start address of plane 1 of frame buffer for layer 1
+ * @chroma_addr: Start address of plane 2 of frame buffer for layer 1
+ *
+ * Sets the buffer address of the specified layer
+ * Return:
+ * Zero on success, -EINVAL on failure
+ */
+static int xlnx_mix_set_layer_buff_addr(struct xlnx_mix_hw *mixer,
+					enum xlnx_mix_layer_id id,
+					dma_addr_t luma_addr,
+					dma_addr_t chroma_addr)
+{
+	struct xlnx_mix_layer_data *layer_data;
+	u32 align, offset;
+	u32 reg1, reg2;
+
+	if (id >= mixer->layer_cnt)
+		return -EINVAL;
+
+	/* Check if addr is aligned to aximm width (PPC * 64-bits) */
+	align = mixer->ppc * 8;
+	if ((luma_addr % align) != 0 || (chroma_addr % align) != 0)
+		return -EINVAL;
+
+	offset = (id - 1) * XVMIX_REG_OFFSET;
+	reg1 = XVMIX_LAYER1_BUF1_V_DATA + offset;
+	reg2 = XVMIX_LAYER1_BUF2_V_DATA + offset;
+	layer_data = &mixer->layer_data[id];
+	if (mixer->dma_addr_size == 64 && sizeof(dma_addr_t) == 8) {
+		reg_writeq(mixer->base, reg1, luma_addr);
+		reg_writeq(mixer->base, reg2, chroma_addr);
+	} else {
+		reg_writel(mixer->base, reg1, (u32)luma_addr);
+		reg_writel(mixer->base, reg2, (u32)chroma_addr);
+	}
+	layer_data->layer_regs.buff_addr1 = luma_addr;
+	layer_data->layer_regs.buff_addr2 = chroma_addr;
+
+	return 0;
+}
+
+/**
+ * xlnx_mix_hw_plane_dpms - Implementation of display power management
+ * system call (dpms).
+ * @plane: Plane/mixer layer to enable/disable (based on dpms value)
+ * @dpms: Display power management state to act upon
+ *
+ * Designed to disable and turn off a plane and restore all attached drm
+ * properities to their initial values.  Alterntively, if dpms is "on", will
+ * enable a layer.
+ */
+
+static void
+xlnx_mix_hw_plane_dpms(struct xlnx_mix_plane *plane, int dpms)
+{
+	struct xlnx_mix *mixer;
+
+	if (!plane->mixer)
+		return;
+	mixer = plane->mixer;
+	plane->dpms = dpms;
+
+	switch (dpms) {
+	case DRM_MODE_DPMS_ON:
+		xlnx_mix_disp_layer_enable(plane);
+		break;
+	default:
+		xlnx_mix_mark_layer_inactive(plane);
+		xlnx_mix_disp_layer_disable(plane);
+		/* restore to default property values */
+		if (mixer->alpha_prop)
+			xlnx_mix_disp_set_layer_alpha(plane, XVMIX_ALPHA_MAX);
+		if (mixer->scale_prop)
+			xlnx_mix_set_layer_scale(plane, XVMIX_SCALE_FACTOR_1X);
+	}
+}
+
+static void xlnx_mix_plane_dpms(struct drm_plane *base_plane, int dpms)
+{
+	struct xlnx_mix_plane *plane = to_xlnx_plane(base_plane);
+	unsigned int i;
+
+	DRM_DEBUG_KMS("plane->id: %d\n", plane->id);
+	DRM_DEBUG_KMS("dpms: %d -> %d\n", plane->dpms, dpms);
+
+	if (plane->dpms == dpms)
+		return;
+	plane->dpms = dpms;
+	switch (dpms) {
+	case DRM_MODE_DPMS_ON:
+		/* start dma engine */
+		for (i = 0; i < XVMIX_MAX_NUM_SUB_PLANES; i++)
+			if (plane->dma[i].chan && plane->dma[i].is_active)
+				dma_async_issue_pending(plane->dma[i].chan);
+		xlnx_mix_hw_plane_dpms(plane, dpms);
+		break;
+	default:
+		xlnx_mix_hw_plane_dpms(plane, dpms);
+		/* stop dma engine and release descriptors */
+		for (i = 0; i < XVMIX_MAX_NUM_SUB_PLANES; i++) {
+			if (plane->dma[i].chan && plane->dma[i].is_active) {
+				dmaengine_terminate_sync(plane->dma[i].chan);
+				plane->dma[i].is_active = false;
+			}
+		}
+		break;
+	}
+}
+
+static int
+xlnx_mix_disp_plane_atomic_set_property(struct drm_plane *base_plane,
+					struct drm_plane_state *state,
+				      struct drm_property *property, u64 val)
+{
+	struct xlnx_mix_plane *plane = to_xlnx_plane(base_plane);
+	struct xlnx_mix *mixer = plane->mixer;
+
+	if (property == mixer->alpha_prop)
+		return xlnx_mix_disp_set_layer_alpha(plane, val);
+	else if (property == mixer->scale_prop)
+		return xlnx_mix_set_layer_scale(plane, val);
+	else
+		return -EINVAL;
+	return 0;
+}
+
+static int
+xlnx_mix_disp_plane_atomic_get_property(struct drm_plane *base_plane,
+					const struct drm_plane_state *state,
+				      struct drm_property *property,
+				      uint64_t *val)
+{
+	struct xlnx_mix_plane *plane = to_xlnx_plane(base_plane);
+	struct xlnx_mix *mixer = plane->mixer;
+	struct xlnx_mix_hw *mixer_hw = to_mixer_hw(plane);
+	u32 layer_id = plane->mixer_layer->id;
+
+	if (property == mixer->alpha_prop)
+		*val = mixer_hw->layer_data[layer_id].layer_regs.alpha;
+	else if (property == mixer->scale_prop)
+		*val = mixer_hw->layer_data[layer_id].layer_regs.scale_fact;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
+ * xlnx_mix_disp_plane_atomic_update_plane - plane update using atomic
+ * @plane: plane object to update
+ * @crtc: owning CRTC of owning plane
+ * @fb: framebuffer to flip onto plane
+ * @crtc_x: x offset of primary plane on crtc
+ * @crtc_y: y offset of primary plane on crtc
+ * @crtc_w: width of primary plane rectangle on crtc
+ * @crtc_h: height of primary plane rectangle on crtc
+ * @src_x: x offset of @fb for panning
+ * @src_y: y offset of @fb for panning
+ * @src_w: width of source rectangle in @fb
+ * @src_h: height of source rectangle in @fb
+ * @ctx: lock acquire context
+ *
+ * Provides a default plane update handler using the atomic driver interface.
+ *
+ * RETURNS:
+ * Zero on success, error code on failure
+ */
+static int
+xlnx_mix_disp_plane_atomic_update_plane(struct drm_plane *plane,
+					struct drm_crtc *crtc,
+					struct drm_framebuffer *fb,
+					int crtc_x, int crtc_y,
+					unsigned int crtc_w,
+					unsigned int crtc_h,
+					uint32_t src_x, uint32_t src_y,
+					uint32_t src_w, uint32_t src_h,
+					struct drm_modeset_acquire_ctx *ctx)
+{
+	struct drm_atomic_state *state;
+	struct drm_plane_state *plane_state;
+	int ret = 0;
+
+	state = drm_atomic_state_alloc(plane->dev);
+	if (!state)
+		return -ENOMEM;
+
+	state->acquire_ctx = ctx;
+	plane_state = drm_atomic_get_plane_state(state, plane);
+	if (IS_ERR(plane_state)) {
+		ret = PTR_ERR(plane_state);
+		goto fail;
+	}
+
+	ret = drm_atomic_set_crtc_for_plane(plane_state, crtc);
+	if (ret != 0)
+		goto fail;
+
+	drm_atomic_set_fb_for_plane(plane_state, fb);
+	plane_state->crtc_x = crtc_x;
+	plane_state->crtc_y = crtc_y;
+	plane_state->crtc_w = crtc_w;
+	plane_state->crtc_h = crtc_h;
+	plane_state->src_x = src_x;
+	plane_state->src_y = src_y;
+	plane_state->src_w = src_w;
+	plane_state->src_h = src_h;
+
+	if (plane == crtc->cursor)
+		state->legacy_cursor_update = true;
+
+	/* Do async-update if possible */
+	state->async_update = !drm_atomic_helper_async_check(plane->dev, state);
+
+	ret = drm_atomic_commit(state);
+
+fail:
+	drm_atomic_state_put(state);
+	return ret;
+}
+
+static struct drm_plane_funcs xlnx_mix_plane_funcs = {
+	.update_plane	= xlnx_mix_disp_plane_atomic_update_plane,
+	.disable_plane	= drm_atomic_helper_disable_plane,
+	.atomic_set_property	= xlnx_mix_disp_plane_atomic_set_property,
+	.atomic_get_property	= xlnx_mix_disp_plane_atomic_get_property,
+	.destroy		= drm_plane_cleanup,
+	.reset			= drm_atomic_helper_plane_reset,
+	.atomic_duplicate_state	= drm_atomic_helper_plane_duplicate_state,
+	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
+};
+
+/**
+ * xlnx_mix_logo_load - Loads mixer's internal bram
+ * @mixer: Mixer instance to act upon
+ * @logo_w: Width of logo in pixels
+ * @logo_h: Height of logo in pixels
+ * @r_buf: Pointer to byte buffer array of R data values
+ * @g_buf: Pointer to byte buffer array of G data values
+ * @b_buf: Pointer to byte buffer array of B data values
+ * @a_buf: Pointer to byte buffer array of A data values
+ *
+ * Loads mixer's internal bram with planar R, G, B and A data
+ *
+ * Return:
+ * Zero on success, -ENODEV if logo layer not enabled; -EINVAL otherwise
+ */
+static int xlnx_mix_logo_load(struct xlnx_mix_hw *mixer, u32 logo_w, u32 logo_h,
+			      u8 *r_buf, u8 *g_buf, u8 *b_buf, u8 *a_buf)
+{
+	void __iomem *reg = mixer->base;
+	struct xlnx_mix_layer_data *layer_data;
+
+	int x;
+	u32 shift;
+	u32 rword, gword, bword, aword;
+	u32 pixel_cnt = logo_w * logo_h;
+	u32 unaligned_pix_cnt = pixel_cnt % 4;
+	u32 curr_x_pos, curr_y_pos;
+	u32 rbase_addr, gbase_addr, bbase_addr, abase_addr;
+
+	layer_data = xlnx_mix_get_layer_data(mixer, mixer->logo_layer_id);
+	rword = 0;
+	gword = 0;
+	bword = 0;
+	aword = 0;
+
+	if (!layer_data)
+		return -ENODEV;
+
+	/* RGBA data should be 32-bit word aligned */
+	if (unaligned_pix_cnt && mixer->logo_pixel_alpha_enabled)
+		return -EINVAL;
+
+	if (!(mixer->logo_layer_en &&
+	      logo_w <= layer_data->hw_config.max_width &&
+	    logo_h <= layer_data->hw_config.max_height))
+		return -EINVAL;
+
+	rbase_addr = XVMIX_LOGOR_V_BASE;
+	gbase_addr = XVMIX_LOGOG_V_BASE;
+	bbase_addr = XVMIX_LOGOB_V_BASE;
+	abase_addr = XVMIX_LOGOA_V_BASE;
+
+	for (x = 0; x < pixel_cnt; x++) {
+		shift = (x % 4) * 8;
+		rword |= r_buf[x] << shift;
+		gword |= g_buf[x] << shift;
+		bword |= b_buf[x] << shift;
+		if (mixer->logo_pixel_alpha_enabled)
+			aword |= a_buf[x] << shift;
+
+		if (x % 4 == 3) {
+			reg_writel(reg, (rbase_addr + (x - 3)), rword);
+			reg_writel(reg, (gbase_addr + (x - 3)), gword);
+			reg_writel(reg, (bbase_addr + (x - 3)), bword);
+			if (mixer->logo_pixel_alpha_enabled)
+				reg_writel(reg, (abase_addr + (x - 3)), aword);
+		}
+	}
+
+	curr_x_pos = layer_data->layer_regs.x_pos;
+	curr_y_pos = layer_data->layer_regs.y_pos;
+	return xlnx_mix_set_layer_window(mixer, mixer->logo_layer_id,
+					 curr_x_pos, curr_y_pos,
+					 logo_w, logo_h, 0);
+}
+
+static int xlnx_mix_update_logo_img(struct xlnx_mix_plane *plane,
+				    struct drm_gem_cma_object *buffer,
+				     u32 src_w, u32 src_h)
+{
+	struct xlnx_mix_layer_data *logo_layer = plane->mixer_layer;
+	struct xlnx_mix_hw *mixer = to_mixer_hw(plane);
+	size_t pixel_cnt = src_h * src_w;
+	bool per_pixel_alpha = false;
+	u32 max_width = logo_layer->hw_config.max_width;
+	u32 max_height = logo_layer->hw_config.max_height;
+	u32 min_width = logo_layer->hw_config.min_width;
+	u32 min_height = logo_layer->hw_config.min_height;
+	u8 *r_data = NULL;
+	u8 *g_data = NULL;
+	u8 *b_data = NULL;
+	u8 *a_data = NULL;
+	size_t el_size = sizeof(u8);
+	u8 *pixel_mem_data;
+	int ret, i, j;
+
+	/* ensure valid conditions for update */
+	if (logo_layer->id != mixer->logo_layer_id)
+		return 0;
+
+	if (src_h > max_height || src_w > max_width ||
+	    src_h < min_height || src_w < min_width) {
+		DRM_ERROR("Mixer logo/cursor layer dimensions illegal.\n");
+		return -EINVAL;
+	}
+
+	if (!xlnx_mix_isfmt_support(plane->mixer_layer->hw_config.vid_fmt)) {
+		DRM_ERROR("DRM color format not supported for logo layer\n");
+		return -EINVAL;
+	}
+	per_pixel_alpha = (logo_layer->hw_config.vid_fmt ==
+			   DRM_FORMAT_RGBA8888) ? true : false;
+	r_data = kcalloc(pixel_cnt, el_size, GFP_KERNEL);
+	g_data = kcalloc(pixel_cnt, el_size, GFP_KERNEL);
+	b_data = kcalloc(pixel_cnt, el_size, GFP_KERNEL);
+	if (per_pixel_alpha)
+		a_data = kcalloc(pixel_cnt, el_size, GFP_KERNEL);
+
+	if (!r_data || !g_data || !b_data || (per_pixel_alpha && !a_data)) {
+		DRM_ERROR("Unable to allocate memory for logo layer data\n");
+		ret = -ENOMEM;
+		goto free;
+	}
+	/* ensure buffer attributes have changed to indicate new logo
+	 * has been created
+	 */
+	if ((phys_addr_t)buffer->vaddr == logo_layer->layer_regs.buff_addr1 &&
+	    src_w == logo_layer->layer_regs.width &&
+	    src_h == logo_layer->layer_regs.height)
+		return 0;
+
+	/* cache buffer address for future comparison */
+	logo_layer->layer_regs.buff_addr1 = (phys_addr_t)buffer->vaddr;
+	pixel_mem_data = (u8 *)(buffer->vaddr);
+	for (i = 0, j = 0; j < pixel_cnt; j++) {
+		if (per_pixel_alpha && a_data)
+			a_data[j] = pixel_mem_data[i++];
+
+		b_data[j] = pixel_mem_data[i++];
+		g_data[j] = pixel_mem_data[i++];
+		r_data[j] = pixel_mem_data[i++];
+	}
+	ret = xlnx_mix_logo_load(to_mixer_hw(plane), src_w, src_h, r_data,
+				 g_data, b_data,
+				 per_pixel_alpha ? a_data : NULL);
+free:
+	kfree(r_data);
+	kfree(g_data);
+	kfree(b_data);
+	kfree(a_data);
+
+	return ret;
+}
+
+/**
+ * xlnx_mix_set_plane - Implementation of DRM plane_update callback
+ * @plane: xlnx_mix_plane object containing references to
+ *  the base plane and mixer
+ * @fb: Framebuffer descriptor
+ * @crtc_x: X position of layer on crtc.  Note, if the plane represents either
+ *  the master hardware layer (video0) or the layer representing the DRM primary
+ *  layer, the crtc x/y coordinates are either ignored and/or set to 0/0
+ *  respectively.
+ * @crtc_y: Y position of layer.  See description of crtc_x handling
+ * for more inforation.
+ * @src_x: x-offset in memory buffer from which to start reading
+ * @src_y: y-offset in memory buffer from which to start reading
+ * @src_w: Number of horizontal pixels to read from memory per row
+ * @src_h: Number of rows of video data to read from memory
+ *
+ * Configures a mixer layer to comply with user space SET_PLANE icotl
+ * call.
+ *
+ * Return:
+ * Zero on success, non-zero linux error code otherwise.
+ */
+static int xlnx_mix_set_plane(struct xlnx_mix_plane *plane,
+			      struct drm_framebuffer *fb,
+			      int crtc_x, int crtc_y,
+			      u32 src_x, u32 src_y,
+			      u32 src_w, u32 src_h)
+{
+	struct xlnx_mix_hw *mixer_hw;
+	struct xlnx_mix *mixer;
+	struct drm_gem_cma_object *luma_buffer;
+	u32 luma_stride = fb->pitches[0];
+	dma_addr_t luma_addr, chroma_addr = 0;
+	u32 active_area_width;
+	u32 active_area_height;
+	enum xlnx_mix_layer_id layer_id;
+	int ret;
+	const struct drm_format_info *info = fb->format;
+
+	mixer = plane->mixer;
+	mixer_hw = &mixer->mixer_hw;
+	layer_id = plane->mixer_layer->id;
+	active_area_width =
+		mixer->drm_primary_layer->mixer_layer->layer_regs.width;
+	active_area_height =
+		mixer->drm_primary_layer->mixer_layer->layer_regs.height;
+	/* compute memory data */
+	luma_buffer = drm_fb_cma_get_gem_obj(fb, 0);
+	luma_addr = drm_fb_cma_get_gem_addr(fb, plane->base.state, 0);
+	if (!luma_addr) {
+		DRM_ERROR("%s failed to get luma paddr\n", __func__);
+		return -EINVAL;
+	}
+
+	if (info->num_planes > 1) {
+		chroma_addr = drm_fb_cma_get_gem_addr(fb, plane->base.state, 1);
+		if (!chroma_addr) {
+			DRM_ERROR("failed to get chroma paddr\n");
+			return -EINVAL;
+		}
+	}
+	ret = xlnx_mix_mark_layer_active(plane);
+	if (ret)
+		return ret;
+
+	switch (layer_id) {
+	case XVMIX_LAYER_MASTER:
+		if (!plane->mixer_layer->hw_config.is_streaming)
+			xlnx_mix_mark_layer_inactive(plane);
+		if (mixer->drm_primary_layer == mixer->hw_master_layer) {
+			xlnx_mix_layer_disable(mixer_hw, layer_id);
+			ret = xlnx_mix_set_active_area(mixer_hw, src_w, src_h);
+			if (ret)
+				return ret;
+			xlnx_mix_layer_enable(mixer_hw, layer_id);
+
+		} else if (src_w != active_area_width ||
+			   src_h != active_area_height) {
+			DRM_ERROR("Invalid dimensions for mixer layer 0.\n");
+			return -EINVAL;
+		}
+		break;
+
+	default:
+		ret = xlnx_mix_set_layer_dimensions(plane, crtc_x, crtc_y,
+						    src_w, src_h, luma_stride);
+		if (ret)
+			break;
+		if (layer_id == mixer_hw->logo_layer_id) {
+			ret = xlnx_mix_update_logo_img(plane, luma_buffer,
+						       src_w, src_h);
+		} else {
+			if (!plane->mixer_layer->hw_config.is_streaming)
+				ret = xlnx_mix_set_layer_buff_addr
+					(mixer_hw, plane->mixer_layer->id,
+					 luma_addr, chroma_addr);
+		}
+	}
+	return ret;
+}
+
+/* mode set a plane */
+static int xlnx_mix_plane_mode_set(struct drm_plane *base_plane,
+				   struct drm_framebuffer *fb,
+				   int crtc_x, int crtc_y,
+				   unsigned int crtc_w, unsigned int crtc_h,
+				   u32 src_x, uint32_t src_y,
+				   u32 src_w, uint32_t src_h)
+{
+	struct xlnx_mix_plane *plane = to_xlnx_plane(base_plane);
+	struct xlnx_mix_hw *mixer_hw = to_mixer_hw(plane);
+	const struct drm_format_info *info = fb->format;
+	size_t i = 0;
+	dma_addr_t luma_paddr;
+	int ret;
+	u32 stride;
+
+	/* JPM TODO begin start of code to extract into prep-interleaved*/
+	DRM_DEBUG_KMS("plane->id: %d\n", plane->id);
+	DRM_DEBUG_KMS("h: %d(%d), v: %d(%d)\n", src_w, crtc_x, src_h, crtc_y);
+
+	/* We have multiple dma channels.  Set each per video plane */
+	for (; i < info->num_planes; i++) {
+		unsigned int width = src_w / (i ? info->hsub : 1);
+		unsigned int height = src_h / (i ? info->vsub : 1);
+
+		luma_paddr = drm_fb_cma_get_gem_addr(fb, base_plane->state, i);
+		if (!luma_paddr) {
+			DRM_ERROR("%s failed to get luma paddr\n", __func__);
+			return -EINVAL;
+		}
+
+		plane->dma[i].xt.numf = height;
+		plane->dma[i].sgl[0].size =
+			drm_format_plane_width_bytes(info, 0, width);
+		plane->dma[i].sgl[0].icg = fb->pitches[0] -
+						plane->dma[i].sgl[0].size;
+		plane->dma[i].xt.src_start = luma_paddr;
+		plane->dma[i].xt.frame_size = info->num_planes;
+		plane->dma[i].xt.dir = DMA_MEM_TO_DEV;
+		plane->dma[i].xt.src_sgl = true;
+		plane->dma[i].xt.dst_sgl = false;
+		plane->dma[i].is_active = true;
+	}
+
+	for (; i < XVMIX_MAX_NUM_SUB_PLANES; i++)
+		plane->dma[i].is_active = false;
+	/* Do we have a video format aware dma channel?
+	 * If so, modify descriptor accordingly
+	 */
+	if (plane->dma[0].chan && !plane->dma[1].chan && info->num_planes > 1) {
+		stride = plane->dma[0].sgl[0].size + plane->dma[0].sgl[0].icg;
+		plane->dma[0].sgl[0].src_icg = plane->dma[1].xt.src_start -
+				plane->dma[0].xt.src_start -
+				(plane->dma[0].xt.numf * stride);
+	}
+
+	if (mixer_hw->csc_enabled) {
+		/**
+		 * magic numbers of coefficient table for colorimetry
+		 * and range are derived from the following references:
+		 * [1] Rec. ITU-R BT.601-6
+		 * [2] Rec. ITU-R BT.709-5
+		 * [3] Rec. ITU-R BT.2020
+		 * [4] http://en.wikipedia.org/wiki/YCbCr
+		 * coefficient table supports BT601 / BT709 / BT2020 encoding
+		 * schemes and 16-235(limited) / 16-240(full) range.
+		 */
+		xlnx_mix_set_yuv2_rgb_coeff(plane,
+					    base_plane->state->color_encoding,
+					    base_plane->state->color_range);
+		xlnx_mix_set_rgb2_yuv_coeff(plane,
+					    base_plane->state->color_encoding,
+					    base_plane->state->color_range);
+	}
+
+	ret = xlnx_mix_set_plane(plane, fb, crtc_x, crtc_y, src_x, src_y,
+				 src_w, src_h);
+	return ret;
+}
+
+static int xlnx_mix_plane_prepare_fb(struct drm_plane *plane,
+				     struct drm_plane_state *new_state)
+{
+	return 0;
+}
+
+static void xlnx_mix_plane_cleanup_fb(struct drm_plane *plane,
+				      struct drm_plane_state *old_state)
+{
+}
+
+static int xlnx_mix_plane_atomic_check(struct drm_plane *plane,
+				       struct drm_plane_state *state)
+{
+	int scale;
+	struct xlnx_mix_plane *mix_plane = to_xlnx_plane(plane);
+	struct xlnx_mix_hw *mixer_hw = to_mixer_hw(mix_plane);
+	struct xlnx_mix *mix;
+
+	/* No check required for the drm_primary_plane */
+	mix = container_of(mixer_hw, struct xlnx_mix, mixer_hw);
+	if (mix->drm_primary_layer == mix_plane)
+		return 0;
+
+	scale = xlnx_mix_get_layer_scaling(mixer_hw,
+					   mix_plane->mixer_layer->id);
+	if (is_window_valid(mixer_hw, state->crtc_x, state->crtc_y,
+			    state->src_w >> 16, state->src_h >> 16, scale))
+		return 0;
+
+	return -EINVAL;
+}
+
+static void xlnx_mix_plane_atomic_update(struct drm_plane *plane,
+					 struct drm_plane_state *old_state)
+{
+	int ret;
+
+	if (!plane->state->crtc || !plane->state->fb)
+		return;
+
+	if (old_state->fb &&
+	    old_state->fb->format->format != plane->state->fb->format->format)
+		xlnx_mix_plane_dpms(plane, DRM_MODE_DPMS_OFF);
+
+	ret = xlnx_mix_plane_mode_set(plane, plane->state->fb,
+				      plane->state->crtc_x,
+				      plane->state->crtc_y,
+				      plane->state->crtc_w,
+				      plane->state->crtc_h,
+				      plane->state->src_x >> 16,
+				      plane->state->src_y >> 16,
+				      plane->state->src_w >> 16,
+				      plane->state->src_h >> 16);
+	if (ret) {
+		DRM_ERROR("failed to mode-set a plane\n");
+		return;
+	}
+	/* apply the new fb addr */
+	xlnx_mix_plane_commit(plane);
+	/* make sure a plane is on */
+	xlnx_mix_plane_dpms(plane, DRM_MODE_DPMS_ON);
+}
+
+static void xlnx_mix_plane_atomic_disable(struct drm_plane *plane,
+					  struct drm_plane_state *old_state)
+{
+	xlnx_mix_plane_dpms(plane, DRM_MODE_DPMS_OFF);
+}
+
+static int xlnx_mix_plane_atomic_async_check(struct drm_plane *plane,
+					     struct drm_plane_state *state)
+{
+	return 0;
+}
+
+static void
+xlnx_mix_plane_atomic_async_update(struct drm_plane *plane,
+				   struct drm_plane_state *new_state)
+{
+	struct drm_plane_state *old_state =
+		drm_atomic_get_old_plane_state(new_state->state, plane);
+
+	/* Update the current state with new configurations */
+	swap(plane->state->fb, new_state->fb);
+	plane->state->crtc = new_state->crtc;
+	plane->state->crtc_x = new_state->crtc_x;
+	plane->state->crtc_y = new_state->crtc_y;
+	plane->state->crtc_w = new_state->crtc_w;
+	plane->state->crtc_h = new_state->crtc_h;
+	plane->state->src_x = new_state->src_x;
+	plane->state->src_y = new_state->src_y;
+	plane->state->src_w = new_state->src_w;
+	plane->state->src_h = new_state->src_h;
+	plane->state->state = new_state->state;
+
+	xlnx_mix_plane_atomic_update(plane, old_state);
+}
+
+static const struct drm_plane_helper_funcs xlnx_mix_plane_helper_funcs = {
+	.prepare_fb	= xlnx_mix_plane_prepare_fb,
+	.cleanup_fb	= xlnx_mix_plane_cleanup_fb,
+	.atomic_check	= xlnx_mix_plane_atomic_check,
+	.atomic_update	= xlnx_mix_plane_atomic_update,
+	.atomic_disable	= xlnx_mix_plane_atomic_disable,
+	.atomic_async_check = xlnx_mix_plane_atomic_async_check,
+	.atomic_async_update = xlnx_mix_plane_atomic_async_update,
+};
+
+static int xlnx_mix_init_plane(struct xlnx_mix_plane *plane,
+			       unsigned int poss_crtcs,
+			       struct device_node *layer_node)
+{
+	struct xlnx_mix *mixer = plane->mixer;
+	char name[16];
+	enum drm_plane_type type;
+	int ret, i;
+
+	plane->dpms = DRM_MODE_DPMS_OFF;
+	type = DRM_PLANE_TYPE_OVERLAY;
+
+	for (i = 0; i < XVMIX_MAX_NUM_SUB_PLANES; i++) {
+		snprintf(name, sizeof(name), "dma%d", i);
+		plane->dma[i].chan = of_dma_request_slave_channel(layer_node,
+								  name);
+		if (PTR_ERR(plane->dma[i].chan) == -ENODEV) {
+			plane->dma[i].chan = NULL;
+			continue;
+		}
+		if (IS_ERR(plane->dma[i].chan)) {
+			DRM_ERROR("failed to request dma channel\n");
+			ret = PTR_ERR(plane->dma[i].chan);
+			plane->dma[i].chan = NULL;
+			goto err_dma;
+		}
+	}
+	if (!xlnx_mix_isfmt_support(plane->mixer_layer->hw_config.vid_fmt)) {
+		DRM_ERROR("DRM color format not supported by mixer\n");
+		ret = -ENODEV;
+		goto err_init;
+	}
+	plane->format = plane->mixer_layer->hw_config.vid_fmt;
+	if (plane == mixer->hw_logo_layer)
+		type = DRM_PLANE_TYPE_CURSOR;
+	if (plane == mixer->drm_primary_layer)
+		type = DRM_PLANE_TYPE_PRIMARY;
+
+	/* initialize drm plane */
+	ret = drm_universal_plane_init(mixer->drm, &plane->base,
+				       poss_crtcs, &xlnx_mix_plane_funcs,
+				       &plane->format,
+				       1, NULL, type, NULL);
+
+	if (ret) {
+		DRM_ERROR("failed to initialize plane\n");
+		goto err_init;
+	}
+	drm_plane_helper_add(&plane->base, &xlnx_mix_plane_helper_funcs);
+	of_node_put(layer_node);
+
+	return 0;
+
+err_init:
+	xlnx_mix_disp_layer_disable(plane);
+err_dma:
+	for (i = 0; i < XVMIX_MAX_NUM_SUB_PLANES; i++)
+		if (plane->dma[i].chan)
+			dma_release_channel(plane->dma[i].chan);
+
+	of_node_put(layer_node);
+	return ret;
+}
+
+static int xlnx_mix_parse_dt_bg_video_fmt(struct device_node *node,
+					  struct xlnx_mix_hw *mixer_hw)
+{
+	struct device_node *layer_node;
+	struct xlnx_mix_layer_data *layer;
+	const char *vformat;
+
+	layer_node = of_get_child_by_name(node, "layer_0");
+	layer = &mixer_hw->layer_data[XVMIX_MASTER_LAYER_IDX];
+
+	/* Set default values */
+	layer->hw_config.can_alpha = false;
+	layer->hw_config.can_scale = false;
+	layer->hw_config.min_width = XVMIX_LAYER_WIDTH_MIN;
+	layer->hw_config.min_height = XVMIX_LAYER_HEIGHT_MIN;
+
+	if (of_property_read_string(layer_node, "xlnx,vformat",
+				    &vformat)) {
+		DRM_ERROR("No xlnx,vformat value for layer 0 in dts\n");
+		return -EINVAL;
+	}
+	strcpy((char *)&layer->hw_config.vid_fmt, vformat);
+	layer->hw_config.is_streaming =
+		of_property_read_bool(layer_node, "xlnx,layer-streaming");
+	if (of_property_read_u32(node, "xlnx,bpc", &mixer_hw->bg_layer_bpc)) {
+		DRM_ERROR("Failed to get bits per component (bpc) prop\n");
+		return -EINVAL;
+	}
+	if (of_property_read_u32(layer_node, "xlnx,layer-max-width",
+				 &layer->hw_config.max_width)) {
+		DRM_ERROR("Failed to get screen width prop\n");
+		return -EINVAL;
+	} else if (layer->hw_config.max_width > XVMIX_DISP_MAX_WIDTH ||
+		   layer->hw_config.max_width < XVMIX_DISP_MIN_WIDTH) {
+		DRM_ERROR("Invalid width in dt");
+		return -EINVAL;
+	}
+
+	mixer_hw->max_layer_width = layer->hw_config.max_width;
+	if (of_property_read_u32(layer_node, "xlnx,layer-max-height",
+				 &layer->hw_config.max_height)) {
+		DRM_ERROR("Failed to get screen height prop\n");
+		return -EINVAL;
+	} else if (layer->hw_config.max_height > XVMIX_DISP_MAX_HEIGHT ||
+		   layer->hw_config.max_height < XVMIX_DISP_MIN_HEIGHT) {
+		DRM_ERROR("Invalid height in dt");
+		return -EINVAL;
+	}
+
+	mixer_hw->max_layer_height = layer->hw_config.max_height;
+	layer->id = XVMIX_LAYER_MASTER;
+
+	return 0;
+}
+
+static int xlnx_mix_parse_dt_logo_data(struct device_node *node,
+				       struct xlnx_mix_hw *mixer_hw)
+{
+	struct xlnx_mix_layer_data *layer_data;
+	struct device_node *logo_node;
+	u32 max_width, max_height;
+
+	logo_node = of_get_child_by_name(node, "logo");
+	if (!logo_node) {
+		DRM_ERROR("No logo node specified in device tree.\n");
+		return -EINVAL;
+	}
+
+	layer_data = &mixer_hw->layer_data[XVMIX_LOGO_LAYER_IDX];
+
+	/* set defaults for logo layer */
+	layer_data->hw_config.min_height = XVMIX_LOGO_LAYER_HEIGHT_MIN;
+	layer_data->hw_config.min_width = XVMIX_LOGO_LAYER_WIDTH_MIN;
+	layer_data->hw_config.is_streaming = false;
+	layer_data->hw_config.vid_fmt = DRM_FORMAT_RGB888;
+	layer_data->hw_config.can_alpha = true;
+	layer_data->hw_config.can_scale = true;
+	layer_data->layer_regs.buff_addr1 = 0;
+	layer_data->layer_regs.buff_addr2 = 0;
+	layer_data->id = mixer_hw->logo_layer_id;
+
+	if (of_property_read_u32(logo_node, "xlnx,logo-width", &max_width)) {
+		DRM_ERROR("Failed to get logo width prop\n");
+		return -EINVAL;
+	}
+	if (max_width > XVMIX_LOGO_LAYER_WIDTH_MAX ||
+	    max_width < XVMIX_LOGO_LAYER_WIDTH_MIN) {
+		DRM_ERROR("Illegal mixer logo layer width.\n");
+		return -EINVAL;
+	}
+	layer_data->hw_config.max_width = max_width;
+	mixer_hw->max_logo_layer_width = layer_data->hw_config.max_width;
+
+	if (of_property_read_u32(logo_node, "xlnx,logo-height", &max_height)) {
+		DRM_ERROR("Failed to get logo height prop\n");
+		return -EINVAL;
+	}
+	if (max_height > XVMIX_LOGO_LAYER_HEIGHT_MAX ||
+	    max_height < XVMIX_LOGO_LAYER_HEIGHT_MIN) {
+		DRM_ERROR("Illegal mixer logo layer height.\n");
+		return -EINVAL;
+	}
+	layer_data->hw_config.max_height = max_height;
+	mixer_hw->max_logo_layer_height = layer_data->hw_config.max_height;
+	mixer_hw->logo_pixel_alpha_enabled =
+		of_property_read_bool(logo_node, "xlnx,logo-pixel-alpha");
+	if (mixer_hw->logo_pixel_alpha_enabled)
+		layer_data->hw_config.vid_fmt = DRM_FORMAT_RGBA8888;
+
+	return 0;
+}
+
+static int xlnx_mix_dt_dp_bridge(struct device *dev, struct xlnx_mix *mixer)
+{
+	struct device_node *node, *vtc_node, *disp_node, *port;
+
+	node = dev->of_node;
+	/* Disp Bridge support */
+	disp_node = of_parse_phandle(node, "xlnx,disp-bridge", 0);
+	if (disp_node) {
+		mixer->disp_bridge = of_xlnx_bridge_get(disp_node);
+		if (!mixer->disp_bridge) {
+			dev_info(dev, "Didn't get disp bridge instance\n");
+			return -1;
+		}
+	} else {
+		dev_info(dev, "disp bridge property not present\n");
+		return -1;
+	}
+	return 0;
+}
+
+static int xlnx_mix_dt_parse(struct device *dev, struct xlnx_mix *mixer)
+{
+	struct xlnx_mix_plane *planes;
+	struct xlnx_mix_hw *mixer_hw;
+	struct device_node *node, *vtc_node, *port;
+	struct xlnx_mix_layer_data *l_data;
+	struct resource	res;
+	int ret, l_cnt, i;
+
+	node = dev->of_node;
+	mixer_hw = &mixer->mixer_hw;
+	mixer->dpms = DRM_MODE_DPMS_OFF;
+
+	mixer_hw->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
+	if (IS_ERR(mixer_hw->reset_gpio)) {
+		ret = PTR_ERR(mixer_hw->reset_gpio);
+		if (ret == -EPROBE_DEFER)
+			dev_dbg(dev, "No gpio probed for mixer. Deferring\n");
+		else
+			dev_err(dev, "No reset gpio info from dts for mixer\n");
+		return ret;
+	}
+	gpiod_set_raw_value(mixer_hw->reset_gpio, 0);
+	gpiod_set_raw_value(mixer_hw->reset_gpio, 1);
+
+	ret = of_address_to_resource(node, 0, &res);
+	if (ret) {
+		dev_err(dev, "Invalid memory address for mixer %d\n", ret);
+		return ret;
+	}
+	/* Read in mandatory global dts properties */
+	mixer_hw->base = devm_ioremap_resource(dev, &res);
+	if (IS_ERR(mixer_hw->base)) {
+		dev_err(dev, "Failed to map io mem space for mixer\n");
+		return PTR_ERR(mixer_hw->base);
+	}
+	if (of_device_is_compatible(dev->of_node, "xlnx,mixer-4.0") ||
+	    of_device_is_compatible(dev->of_node, "xlnx,mixer-5.0")) {
+		mixer_hw->max_layers = 18;
+		mixer_hw->logo_en_mask = BIT(23);
+		mixer_hw->enable_all_mask = (GENMASK(16, 0) |
+						mixer_hw->logo_en_mask);
+	} else {
+		mixer_hw->max_layers = 10;
+		mixer_hw->logo_en_mask = BIT(15);
+		mixer_hw->enable_all_mask = (GENMASK(8, 0) |
+						mixer_hw->logo_en_mask);
+	}
+	if (of_device_is_compatible(dev->of_node, "xlnx,mixer-5.0")) {
+		const char *prop_name = "xlnx,enable-csc-coefficient-register";
+
+		mixer_hw->csc_enabled = of_property_read_bool(node, prop_name);
+	}
+
+	ret = of_property_read_u32(node, "xlnx,num-layers",
+				   &mixer_hw->num_layers);
+	if (ret) {
+		dev_err(dev, "No xlnx,num-layers dts prop for mixer node\n");
+		return ret;
+	}
+	mixer_hw->logo_layer_id = mixer_hw->max_layers - 1;
+	if (mixer_hw->num_layers > mixer_hw->max_layers) {
+		dev_err(dev, "Num layer nodes in device tree > mixer max\n");
+		return -EINVAL;
+	}
+	ret = of_property_read_u32(node, "xlnx,dma-addr-width",
+				   &mixer_hw->dma_addr_size);
+	if (ret) {
+		dev_err(dev, "missing addr-width dts prop\n");
+		return ret;
+	}
+	if (mixer_hw->dma_addr_size != 32 && mixer_hw->dma_addr_size != 64) {
+		dev_err(dev, "invalid addr-width dts prop\n");
+		return -EINVAL;
+	}
+
+	/* VTC Bridge support */
+	vtc_node = of_parse_phandle(node, "xlnx,bridge", 0);
+	if (vtc_node) {
+		mixer->vtc_bridge = of_xlnx_bridge_get(vtc_node);
+		if (!mixer->vtc_bridge) {
+			dev_info(dev, "Didn't get vtc bridge instance\n");
+			return -EPROBE_DEFER;
+		}
+	} else {
+		dev_info(dev, "vtc bridge property not present\n");
+	}
+
+	mixer_hw->logo_layer_en = of_property_read_bool(node,
+							"xlnx,logo-layer");
+	l_cnt = mixer_hw->num_layers + (mixer_hw->logo_layer_en ? 1 : 0);
+	mixer_hw->layer_cnt = l_cnt;
+
+	l_data = devm_kzalloc(dev, sizeof(*l_data) * l_cnt, GFP_KERNEL);
+	if (!l_data)
+		return -ENOMEM;
+	mixer_hw->layer_data = l_data;
+	/* init DRM planes */
+	planes = devm_kzalloc(dev, sizeof(*planes) * l_cnt, GFP_KERNEL);
+	if (!planes)
+		return -ENOMEM;
+	mixer->planes = planes;
+	mixer->num_planes = l_cnt;
+	for (i = 0; i < mixer->num_planes; i++)
+		mixer->planes[i].mixer = mixer;
+
+	/* establish background layer video properties from dts */
+	ret = xlnx_mix_parse_dt_bg_video_fmt(node, mixer_hw);
+	if (ret)
+		return ret;
+	if (mixer_hw->logo_layer_en) {
+		/* read logo data from dts */
+		ret = xlnx_mix_parse_dt_logo_data(node, mixer_hw);
+		return ret;
+	}
+
+	/* Fill out crtc port OF node */
+	for_each_child_of_node(node, port) {
+		if (!port->name || of_node_cmp(port->name, "port"))
+			continue;
+		mixer->crtc.crtc.port = port;
+		break;
+	}
+	return 0;
+}
+
+static int xlnx_mix_of_init_layer(struct device *dev, struct device_node *node,
+				  char *name, struct xlnx_mix_layer_data *layer,
+				  u32 max_width, struct xlnx_mix *mixer, int id)
+{
+	struct device_node *layer_node;
+	const char *vformat;
+	int ret;
+
+	layer_node = of_get_child_by_name(node, name);
+	if (!layer_node)
+		return -EINVAL;
+
+	/* Set default values */
+	layer->hw_config.can_alpha = false;
+	layer->hw_config.can_scale = false;
+	layer->hw_config.is_streaming = false;
+	layer->hw_config.max_width = max_width;
+	layer->hw_config.min_width = XVMIX_LAYER_WIDTH_MIN;
+	layer->hw_config.min_height = XVMIX_LAYER_HEIGHT_MIN;
+	layer->hw_config.vid_fmt = 0;
+	layer->id = 0;
+	mixer->planes[id].mixer_layer = layer;
+
+	ret = of_property_read_u32(layer_node, "xlnx,layer-id", &layer->id);
+	if (ret) {
+		dev_err(dev, "xlnx,layer-id property not found\n");
+		return ret;
+	}
+	if (layer->id < 1 || layer->id >= mixer->mixer_hw.max_layers) {
+		dev_err(dev, "Mixer layer id %u in dts is out of legal range\n",
+			layer->id);
+		return -EINVAL;
+	}
+	ret = of_property_read_string(layer_node, "xlnx,vformat", &vformat);
+	if (ret) {
+		dev_err(dev, "No mixer layer vformat in dts for layer id %d\n",
+			layer->id);
+		return ret;
+	}
+
+	strcpy((char *)&layer->hw_config.vid_fmt, vformat);
+	layer->hw_config.can_scale =
+		    of_property_read_bool(layer_node, "xlnx,layer-scale");
+	if (layer->hw_config.can_scale) {
+		ret = of_property_read_u32(layer_node, "xlnx,layer-max-width",
+					   &layer->hw_config.max_width);
+		if (ret) {
+			dev_err(dev, "Mixer layer %d dts missing width prop.\n",
+				layer->id);
+			return ret;
+		}
+
+		if (layer->hw_config.max_width > max_width) {
+			dev_err(dev, "Illlegal Mixer layer %d width %d\n",
+				layer->id, layer->hw_config.max_width);
+			return -EINVAL;
+		}
+	}
+	layer->hw_config.can_alpha =
+		    of_property_read_bool(layer_node, "xlnx,layer-alpha");
+	layer->hw_config.is_streaming =
+		    of_property_read_bool(layer_node, "xlnx,layer-streaming");
+	if (of_property_read_bool(layer_node, "xlnx,layer-primary")) {
+		if (mixer->drm_primary_layer) {
+			dev_err(dev,
+				"More than one primary layer in mixer dts\n");
+			return -EINVAL;
+		}
+		mixer->drm_primary_layer = &mixer->planes[id];
+	}
+	ret = xlnx_mix_init_plane(&mixer->planes[id], 1, layer_node);
+	if (ret)
+		dev_err(dev, "Unable to init drm mixer plane id = %u", id);
+
+	return ret;
+}
+
+static irqreturn_t xlnx_mix_intr_handler(int irq, void *data)
+{
+	struct xlnx_mix_hw *mixer = data;
+	u32 intr = xlnx_mix_get_intr_status(mixer);
+
+	if (!intr)
+		return IRQ_NONE;
+	if (mixer->intrpt_handler_fn)
+		mixer->intrpt_handler_fn(mixer->intrpt_data);
+	xlnx_mix_clear_intr_status(mixer, intr);
+
+	return IRQ_HANDLED;
+}
+
+static void xlnx_mix_create_plane_properties(struct xlnx_mix *mixer)
+{
+	mixer->scale_prop = drm_property_create_range(mixer->drm, 0, "scale",
+						      XVMIX_SCALE_FACTOR_1X,
+						      XVMIX_SCALE_FACTOR_4X);
+	mixer->alpha_prop = drm_property_create_range(mixer->drm, 0, "alpha",
+						      XVMIX_ALPHA_MIN,
+						      XVMIX_ALPHA_MAX);
+}
+
+static int xlnx_mix_plane_create(struct device *dev, struct xlnx_mix *mixer)
+{
+	struct xlnx_mix_hw		*mixer_hw;
+	struct device_node		*node, *layer_node;
+	char				name[20];
+	struct xlnx_mix_layer_data	*layer_data;
+	int				ret, i;
+	int				layer_idx;
+
+	node = dev->of_node;
+	mixer_hw = &mixer->mixer_hw;
+	xlnx_mix_create_plane_properties(mixer);
+
+	mixer->planes[XVMIX_MASTER_LAYER_IDX].mixer_layer =
+				&mixer_hw->layer_data[XVMIX_MASTER_LAYER_IDX];
+	mixer->planes[XVMIX_MASTER_LAYER_IDX].id = XVMIX_MASTER_LAYER_IDX;
+	mixer->hw_master_layer = &mixer->planes[XVMIX_MASTER_LAYER_IDX];
+
+	if (mixer_hw->logo_layer_en) {
+		mixer->planes[XVMIX_LOGO_LAYER_IDX].mixer_layer =
+				&mixer_hw->layer_data[XVMIX_LOGO_LAYER_IDX];
+		mixer->planes[XVMIX_LOGO_LAYER_IDX].id = XVMIX_LOGO_LAYER_IDX;
+		mixer->hw_logo_layer = &mixer->planes[XVMIX_LOGO_LAYER_IDX];
+		layer_node = of_get_child_by_name(node, "logo");
+		ret = xlnx_mix_init_plane(&mixer->planes[XVMIX_LOGO_LAYER_IDX],
+					  1, layer_node);
+		if (ret)
+			return ret;
+	}
+	layer_idx = mixer_hw->logo_layer_en ? 2 : 1;
+	for (i = 1; i < mixer_hw->num_layers; i++, layer_idx++) {
+		snprintf(name, sizeof(name), "layer_%d", i);
+		ret = xlnx_mix_of_init_layer(dev, node, name,
+					     &mixer_hw->layer_data[layer_idx],
+					     mixer_hw->max_layer_width,
+					     mixer, layer_idx);
+		if (ret)
+			return ret;
+	}
+	/* If none of the overlay layers were designated as the drm
+	 * primary layer, default to the mixer's video0 layer as drm primary
+	 */
+	if (!mixer->drm_primary_layer)
+		mixer->drm_primary_layer = mixer->hw_master_layer;
+	layer_node = of_get_child_by_name(node, "layer_0");
+	ret = xlnx_mix_init_plane(&mixer->planes[XVMIX_MASTER_LAYER_IDX], 1,
+				  layer_node);
+	/* request irq and obtain pixels-per-clock (ppc) property */
+	mixer_hw->irq = irq_of_parse_and_map(node, 0);
+	if (mixer_hw->irq > 0) {
+		ret = devm_request_irq(dev, mixer_hw->irq,
+				       xlnx_mix_intr_handler,
+				       IRQF_SHARED, "xlnx-mixer", mixer_hw);
+		if (ret) {
+			dev_err(dev, "Failed to request irq\n");
+			return ret;
+		}
+	}
+	ret = of_property_read_u32(node, "xlnx,ppc", &mixer_hw->ppc);
+	if (ret) {
+		dev_err(dev, "No xlnx,ppc property for mixer dts\n");
+		return ret;
+	}
+
+	mixer->max_width = mixer_hw->max_layer_width;
+	mixer->max_height = mixer_hw->max_layer_height;
+
+	if (mixer->hw_logo_layer) {
+		layer_data = &mixer_hw->layer_data[XVMIX_LOGO_LAYER_IDX];
+		mixer->max_cursor_width = layer_data->hw_config.max_width;
+		mixer->max_cursor_height = layer_data->hw_config.max_height;
+	}
+	return 0;
+}
+
+/**
+ * xlnx_mix_plane_restore - Restore the plane states
+ * @mixer: mixer device core structure
+ *
+ * Restore the plane states to the default ones. Any state that needs to be
+ * restored should be here. This improves consistency as applications see
+ * the same default values, and removes mismatch between software and hardware
+ * values as software values are updated as hardware values are reset.
+ */
+static void xlnx_mix_plane_restore(struct xlnx_mix *mixer)
+{
+	struct xlnx_mix_plane *plane;
+	unsigned int i;
+
+	if (!mixer)
+		return;
+	/*
+	 * Reinitialize property default values as they get reset by DPMS OFF
+	 * operation. User will read the correct default values later, and
+	 * planes will be initialized with default values.
+	 */
+	for (i = 0; i < mixer->num_planes; i++) {
+		plane = &mixer->planes[i];
+		if (!plane)
+			continue;
+		xlnx_mix_hw_plane_dpms(plane, DRM_MODE_DPMS_OFF);
+	}
+}
+
+/**
+ * xlnx_mix_set_bkg_col - Set background color
+ * @mixer: Mixer instance to program with new background color
+ * @rgb_value: RGB encoded as 32-bit integer in little-endian format
+ *
+ * Set the color to be output as background color when background stream layer
+ */
+static void xlnx_mix_set_bkg_col(struct xlnx_mix_hw *mixer, u64 rgb_value)
+{
+	u32 bg_bpc = mixer->bg_layer_bpc;
+	u32 bpc_mask_shift = XVMIX_MAX_BPC - bg_bpc;
+	u32 val_mask = (GENMASK(15, 0) >> bpc_mask_shift);
+	u16 b_val = (rgb_value >> (bg_bpc * 2)) & val_mask;
+	u16 g_val = (rgb_value >> bg_bpc) & val_mask;
+	u16 r_val = (rgb_value >> 0) &  val_mask;
+
+	/* Set Background Color */
+	reg_writel(mixer->base, XVMIX_BACKGROUND_Y_R_DATA, r_val);
+	reg_writel(mixer->base, XVMIX_BACKGROUND_U_G_DATA, g_val);
+	reg_writel(mixer->base, XVMIX_BACKGROUND_V_B_DATA, b_val);
+	mixer->bg_color = rgb_value;
+}
+
+/**
+ * xlnx_mix_reset - Reset the mixer core video generator
+ * @mixer: Mixer core instance for which to start video output
+ *
+ * Toggle the reset gpio and restores the bg color, plane and interrupt mask.
+ */
+static void xlnx_mix_reset(struct xlnx_mix *mixer)
+{
+	struct xlnx_mix_hw *mixer_hw = &mixer->mixer_hw;
+
+	gpiod_set_raw_value(mixer_hw->reset_gpio, 0);
+	gpiod_set_raw_value(mixer_hw->reset_gpio, 1);
+	/* restore layer properties and bg color after reset */
+	xlnx_mix_set_bkg_col(mixer_hw, mixer_hw->bg_color);
+	xlnx_mix_plane_restore(mixer);
+	xlnx_mix_intrpt_enable_done(&mixer->mixer_hw);
+}
+
+static void xlnx_mix_dpms(struct xlnx_mix *mixer, int dpms)
+{
+	switch (dpms) {
+	case DRM_MODE_DPMS_ON:
+		xlnx_mix_start(&mixer->mixer_hw);
+		break;
+	default:
+		xlnx_mix_stop(&mixer->mixer_hw);
+		mdelay(50); /* let IP shut down */
+		xlnx_mix_reset(mixer);
+	}
+}
+
+/* set crtc dpms */
+static void xlnx_mix_crtc_dpms(struct drm_crtc *base_crtc, int dpms)
+{
+	struct xlnx_crtc *crtc = to_xlnx_crtc(base_crtc);
+	struct xlnx_mix *mixer = to_xlnx_mixer(crtc);
+	int ret;
+	struct videomode vm;
+	struct drm_display_mode *mode = &base_crtc->mode;
+	struct drm_display_mode *adjusted_mode =
+					&base_crtc->state->adjusted_mode;
+	struct xlnx_mix_hw *mixer_hw = &mixer->mixer_hw;
+
+	DRM_DEBUG_KMS("dpms: %d\n", dpms);
+	if (mixer->dpms == dpms)
+		return;
+	mixer->dpms = dpms;
+
+	switch (dpms) {
+	case DRM_MODE_DPMS_ON:
+		if (!mixer->pixel_clock_enabled) {
+			ret = clk_prepare_enable(mixer->pixel_clock);
+			if (ret) {
+				DRM_ERROR("failed to enable a pixel clock\n");
+				mixer->pixel_clock_enabled = false;
+			}
+		}
+		mixer->pixel_clock_enabled = true;
+
+		if (mixer->vtc_bridge) {
+			drm_display_mode_to_videomode(mode, &vm);
+			xlnx_bridge_set_timing(mixer->vtc_bridge, &vm);
+			xlnx_bridge_enable(mixer->vtc_bridge);
+		}
+
+		if (mixer->disp_bridge) {
+			drm_display_mode_to_videomode(adjusted_mode, &vm);
+			xlnx_bridge_set_input(mixer->disp_bridge,
+					      adjusted_mode->hdisplay,
+					      adjusted_mode->vdisplay,
+					      xlnx_mix_get_bus_fmt(mixer));
+			xlnx_bridge_set_timing(mixer->disp_bridge, &vm);
+			xlnx_bridge_enable(mixer->disp_bridge);
+		}
+
+		xlnx_mix_dpms(mixer, dpms);
+		xlnx_mix_plane_dpms(base_crtc->primary, dpms);
+		break;
+	default:
+		xlnx_mix_plane_dpms(base_crtc->primary, dpms);
+		xlnx_mix_dpms(mixer, dpms);
+		xlnx_bridge_disable(mixer->vtc_bridge);
+		if (mixer->pixel_clock_enabled) {
+			clk_disable_unprepare(mixer->pixel_clock);
+			mixer->pixel_clock_enabled = false;
+		}
+		break;
+	}
+}
+
+static void xlnx_mix_set_intr_handler(struct xlnx_mix *mixer,
+				      void (*intr_handler_fn)(void *),
+				       void *data)
+{
+	mixer->mixer_hw.intrpt_handler_fn = intr_handler_fn;
+	mixer->mixer_hw.intrpt_data = data;
+}
+
+static void xlnx_mix_crtc_vblank_handler(void *data)
+{
+	struct drm_crtc *base_crtc = data;
+	struct xlnx_crtc *crtc = to_xlnx_crtc(base_crtc);
+	struct xlnx_mix *mixer = to_xlnx_mixer(crtc);
+	struct drm_device *drm = base_crtc->dev;
+	struct drm_pending_vblank_event *event;
+	unsigned long flags;
+
+	drm_crtc_handle_vblank(base_crtc);
+	/* Finish page flip */
+	spin_lock_irqsave(&drm->event_lock, flags);
+	event = mixer->event;
+	mixer->event = NULL;
+	if (event) {
+		drm_crtc_send_vblank_event(base_crtc, event);
+		drm_crtc_vblank_put(base_crtc);
+	}
+	spin_unlock_irqrestore(&drm->event_lock, flags);
+}
+
+static int xlnx_mix_crtc_enable_vblank(struct drm_crtc *base_crtc)
+{
+	struct xlnx_crtc *crtc = to_xlnx_crtc(base_crtc);
+	struct xlnx_mix *mixer = to_xlnx_mixer(crtc);
+
+	xlnx_mix_set_intr_handler(mixer, xlnx_mix_crtc_vblank_handler,
+				  base_crtc);
+	return 0;
+}
+
+static void xlnx_mix_crtc_disable_vblank(struct drm_crtc *base_crtc)
+{
+	struct xlnx_crtc *crtc = to_xlnx_crtc(base_crtc);
+	struct xlnx_mix *mixer = to_xlnx_mixer(crtc);
+
+	mixer->mixer_hw.intrpt_handler_fn = NULL;
+	mixer->mixer_hw.intrpt_data = NULL;
+}
+
+static void xlnx_mix_crtc_destroy(struct drm_crtc *base_crtc)
+{
+	struct xlnx_crtc *crtc = to_xlnx_crtc(base_crtc);
+	struct xlnx_mix *mixer = to_xlnx_mixer(crtc);
+
+	/* make sure crtc is off */
+	mixer->alpha_prop = NULL;
+	mixer->scale_prop = NULL;
+	mixer->bg_color = NULL;
+	xlnx_mix_crtc_dpms(base_crtc, DRM_MODE_DPMS_OFF);
+
+	if (mixer->pixel_clock_enabled) {
+		clk_disable_unprepare(mixer->pixel_clock);
+		mixer->pixel_clock_enabled = false;
+	}
+	drm_crtc_cleanup(base_crtc);
+}
+
+static int
+xlnx_mix_disp_crtc_atomic_set_property(struct drm_crtc *crtc,
+				       struct drm_crtc_state *state,
+				     struct drm_property *property,
+				     uint64_t val)
+{
+	return 0;
+}
+
+static int
+xlnx_mix_disp_crtc_atomic_get_property(struct drm_crtc *crtc,
+				       const struct drm_crtc_state *state,
+				     struct drm_property *property,
+				     uint64_t *val)
+{
+	return 0;
+}
+
+static struct drm_crtc_funcs xlnx_mix_crtc_funcs = {
+	.destroy		= xlnx_mix_crtc_destroy,
+	.set_config		= drm_atomic_helper_set_config,
+	.page_flip		= drm_atomic_helper_page_flip,
+	.atomic_set_property	= xlnx_mix_disp_crtc_atomic_set_property,
+	.atomic_get_property	= xlnx_mix_disp_crtc_atomic_get_property,
+	.reset			= drm_atomic_helper_crtc_reset,
+	.atomic_duplicate_state	= drm_atomic_helper_crtc_duplicate_state,
+	.atomic_destroy_state	= drm_atomic_helper_crtc_destroy_state,
+	.enable_vblank		= xlnx_mix_crtc_enable_vblank,
+	.disable_vblank		= xlnx_mix_crtc_disable_vblank,
+};
+
+static void
+xlnx_mix_crtc_atomic_enable(struct drm_crtc *crtc,
+			    struct drm_crtc_state *old_crtc_state)
+{
+	struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
+	int vrefresh;
+
+	xlnx_mix_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
+
+	/* Delay of 3 vblank interval for timing gen to be stable */
+	vrefresh = ((adjusted_mode->clock * 1000) /
+		    (adjusted_mode->vtotal * adjusted_mode->htotal));
+	msleep(3 * 1000 / vrefresh);
+}
+
+/**
+ * xlnx_mix_clear_event - Clear any event if pending
+ * @crtc: DRM crtc object
+ *
+ */
+static void xlnx_mix_clear_event(struct drm_crtc *crtc)
+{
+	if (crtc->state->event) {
+		complete_all(crtc->state->event->base.completion);
+		crtc->state->event = NULL;
+	}
+}
+
+static void
+xlnx_mix_crtc_atomic_disable(struct drm_crtc *crtc,
+			     struct drm_crtc_state *old_crtc_state)
+{
+	xlnx_mix_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
+	xlnx_mix_clear_event(crtc);
+	drm_crtc_vblank_off(crtc);
+}
+
+static void xlnx_mix_crtc_mode_set_nofb(struct drm_crtc *crtc)
+{
+}
+
+static int xlnx_mix_crtc_atomic_check(struct drm_crtc *crtc,
+				      struct drm_crtc_state *state)
+{
+	return drm_atomic_add_affected_planes(state->state, crtc);
+}
+
+static void
+xlnx_mix_crtc_atomic_begin(struct drm_crtc *crtc,
+			   struct drm_crtc_state *old_crtc_state)
+{
+	drm_crtc_vblank_on(crtc);
+	/* Don't rely on vblank when disabling crtc */
+	if (crtc->state->event) {
+		struct xlnx_crtc *xcrtc = to_xlnx_crtc(crtc);
+		struct xlnx_mix *mixer = to_xlnx_mixer(xcrtc);
+
+		/* Consume the flip_done event from atomic helper */
+		crtc->state->event->pipe = drm_crtc_index(crtc);
+		WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+		mixer->event = crtc->state->event;
+		crtc->state->event = NULL;
+	}
+}
+
+static struct drm_crtc_helper_funcs xlnx_mix_crtc_helper_funcs = {
+	.atomic_enable	= xlnx_mix_crtc_atomic_enable,
+	.atomic_disable	= xlnx_mix_crtc_atomic_disable,
+	.mode_set_nofb	= xlnx_mix_crtc_mode_set_nofb,
+	.atomic_check	= xlnx_mix_crtc_atomic_check,
+	.atomic_begin	= xlnx_mix_crtc_atomic_begin,
+};
+
+/**
+ * xlnx_mix_crtc_create - create crtc for mixer
+ * @mixer: xilinx video mixer object
+ *
+ * Return:
+ * Zero on success, error on failure
+ *
+ */
+static int xlnx_mix_crtc_create(struct xlnx_mix *mixer)
+{
+	struct xlnx_crtc *crtc;
+	int ret, i;
+
+	crtc = &mixer->crtc;
+
+	for (i = 0; i < mixer->num_planes; i++)
+		xlnx_mix_attach_plane_prop(&mixer->planes[i]);
+	mixer->pixel_clock = devm_clk_get(mixer->drm->dev, NULL);
+	if (IS_ERR(mixer->pixel_clock)) {
+		DRM_DEBUG_KMS("failed to get pixel clock\n");
+		mixer->pixel_clock = NULL;
+	}
+	ret = clk_prepare_enable(mixer->pixel_clock);
+	if (ret) {
+		DRM_ERROR("failed to enable a pixel clock\n");
+		mixer->pixel_clock_enabled = false;
+		goto err_plane;
+	}
+	mixer->pixel_clock_enabled = true;
+	/* initialize drm crtc */
+	ret = drm_crtc_init_with_planes(mixer->drm, &crtc->crtc,
+					&mixer->drm_primary_layer->base,
+					&mixer->hw_logo_layer->base,
+					&xlnx_mix_crtc_funcs, NULL);
+	if (ret) {
+		DRM_ERROR("failed to initialize mixer crtc\n");
+		goto err_pixel_clk;
+	}
+	drm_crtc_helper_add(&crtc->crtc, &xlnx_mix_crtc_helper_funcs);
+	crtc->get_max_width = &xlnx_mix_crtc_get_max_width;
+	crtc->get_max_height = &xlnx_mix_crtc_get_max_height;
+	crtc->get_align = &xlnx_mix_crtc_get_align;
+	crtc->get_format = &xlnx_mix_crtc_get_format;
+	crtc->get_cursor_height = &xlnx_mix_crtc_get_max_cursor_height;
+	crtc->get_cursor_width = &xlnx_mix_crtc_get_max_cursor_width;
+	xlnx_crtc_register(mixer->drm, crtc);
+	dev_info(mixer->drm->dev,
+		 "Registered mixer CRTC with id: %d\n", crtc->crtc.base.id);
+
+	return 0;
+
+err_pixel_clk:
+	if (mixer->pixel_clock_enabled) {
+		clk_disable_unprepare(mixer->pixel_clock);
+		mixer->pixel_clock_enabled = false;
+	}
+err_plane:
+	return ret;
+}
+
+/**
+ * xlnx_mix_init - Establishes a default power-on state for the mixer IP
+ * core
+ * @mixer: instance of IP core to initialize to a default state
+ *
+ * Background layer initialized to maximum height and width settings based on
+ * device tree properties and all overlay layers set to minimum height and width
+ * sizes and positioned to 0,0 in the crtc.   All layers are inactive (resulting
+ * in video output being generated by the background color generator).
+ * Interrupts are disabled and the IP is started (with auto-restart enabled).
+ */
+static void xlnx_mix_init(struct xlnx_mix_hw *mixer)
+{
+	u32 i;
+	u32 bg_bpc = mixer->bg_layer_bpc;
+	u64 rgb_bg_clr = (0xFFFF >> (XVMIX_MAX_BPC - bg_bpc)) << (bg_bpc * 2);
+	enum xlnx_mix_layer_id layer_id;
+	struct xlnx_mix_layer_data *layer_data;
+
+	layer_data = xlnx_mix_get_layer_data(mixer, XVMIX_LAYER_MASTER);
+	xlnx_mix_layer_disable(mixer, mixer->max_layers);
+	xlnx_mix_set_active_area(mixer, layer_data->hw_config.max_width,
+				 layer_data->hw_config.max_height);
+	/* default to blue */
+	xlnx_mix_set_bkg_col(mixer, rgb_bg_clr);
+
+	for (i = 0; i < mixer->layer_cnt; i++) {
+		layer_id = mixer->layer_data[i].id;
+		layer_data = &mixer->layer_data[i];
+		if (layer_id == XVMIX_LAYER_MASTER)
+			continue;
+		xlnx_mix_set_layer_window(mixer, layer_id, 0, 0,
+					  XVMIX_LAYER_WIDTH_MIN,
+					  XVMIX_LAYER_HEIGHT_MIN, 0);
+		if (layer_data->hw_config.can_scale)
+			xlnx_mix_set_layer_scaling(mixer, layer_id, 0);
+		if (layer_data->hw_config.can_alpha)
+			xlnx_mix_set_layer_alpha(mixer, layer_id,
+						 XVMIX_ALPHA_MAX);
+	}
+	xlnx_mix_intrpt_enable_done(mixer);
+}
+
+static int xlnx_mix_bind(struct device *dev, struct device *master,
+			 void *data)
+{
+	struct xlnx_mix *mixer = dev_get_drvdata(dev);
+	struct drm_device *drm = data;
+	u32 ret;
+
+	xlnx_mix_dt_dp_bridge(dev, mixer);
+
+	mixer->drm = drm;
+	ret = xlnx_mix_plane_create(dev, mixer);
+	if (ret)
+		return ret;
+	ret = xlnx_mix_crtc_create(mixer);
+	if (ret)
+		return ret;
+	xlnx_mix_init(&mixer->mixer_hw);
+
+	return ret;
+}
+
+static void xlnx_mix_unbind(struct device *dev, struct device *master,
+			    void *data)
+{
+	struct xlnx_mix *mixer = dev_get_drvdata(dev);
+
+	dev_set_drvdata(dev, NULL);
+	xlnx_mix_intrpt_disable(&mixer->mixer_hw);
+	xlnx_crtc_unregister(mixer->drm, &mixer->crtc);
+}
+
+static const struct component_ops xlnx_mix_component_ops = {
+	.bind	= xlnx_mix_bind,
+	.unbind	= xlnx_mix_unbind,
+};
+
+static int xlnx_mix_probe(struct platform_device *pdev)
+{
+	struct xlnx_mix *mixer;
+	int ret;
+
+	mixer = devm_kzalloc(&pdev->dev, sizeof(*mixer), GFP_KERNEL);
+	if (!mixer)
+		return -ENOMEM;
+
+	/* Sub-driver will access mixer from drvdata */
+	platform_set_drvdata(pdev, mixer);
+	ret = xlnx_mix_dt_parse(&pdev->dev, mixer);
+	if (ret) {
+		if (ret != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "Failed to probe mixer\n");
+		return ret;
+	}
+
+	ret = component_add(&pdev->dev, &xlnx_mix_component_ops);
+	if (ret)
+		goto err;
+
+	mixer->master = xlnx_drm_pipeline_init(pdev);
+	if (IS_ERR(mixer->master)) {
+		dev_err(&pdev->dev, "Failed to initialize the drm pipeline\n");
+		goto err_component;
+	}
+
+	dev_info(&pdev->dev, "Xilinx Mixer driver probed success\n");
+	return ret;
+
+err_component:
+	component_del(&pdev->dev, &xlnx_mix_component_ops);
+err:
+	return ret;
+}
+
+static int xlnx_mix_remove(struct platform_device *pdev)
+{
+	struct xlnx_mix *mixer = platform_get_drvdata(pdev);
+
+	if (mixer->vtc_bridge)
+		of_xlnx_bridge_put(mixer->vtc_bridge);
+	if (mixer->disp_bridge) {
+		of_xlnx_bridge_put(mixer->disp_bridge);
+		xlnx_mix_crtc_atomic_disable(&mixer->crtc.crtc, NULL);
+		xlnx_drm_pipeline_exit(mixer->master);
+	} else {
+		xlnx_drm_pipeline_exit(mixer->master);
+		component_del(&pdev->dev, &xlnx_mix_component_ops);
+	}
+	return 0;
+}
+
+/*
+ * TODO:
+ * In Mixer IP core version 4.0, layer enable bits and logo layer offsets
+ * have been changed. To provide backward compatibility number of max layers
+ * field has been taken to differentiate IP versions.
+ * This logic will have to be changed properly using the IP core version.
+ */
+
+static const struct of_device_id xlnx_mix_of_match[] = {
+	{ .compatible = "xlnx,mixer-3.0", },
+	{ .compatible = "xlnx,mixer-4.0", },
+	{ .compatible = "xlnx,mixer-5.0", },
+	{ /* end of table */ },
+};
+MODULE_DEVICE_TABLE(of, xlnx_mix_of_match);
+
+static struct platform_driver xlnx_mix_driver = {
+	.probe			= xlnx_mix_probe,
+	.remove			= xlnx_mix_remove,
+	.driver			= {
+		.name		= "xlnx-mixer",
+		.of_match_table	= xlnx_mix_of_match,
+	},
+};
+
+module_platform_driver(xlnx_mix_driver);
+
+MODULE_AUTHOR("Saurabh Sengar");
+MODULE_DESCRIPTION("Xilinx Mixer Driver");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/xlnx/xlnx_pl_disp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/xlnx/xlnx_pl_disp.c
@@ -0,0 +1,646 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx DRM CRTC DMA engine driver
+ *
+ * Copyright (C) 2017 - 2018 Xilinx, Inc.
+ *
+ * Author : Saurabh Sengar <saurabhs@xilinx.com>
+ *        : Hyun Woo Kwon <hyun.kwon@xilinx.com>
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <linux/component.h>
+#include <linux/device.h>
+#include <linux/dmaengine.h>
+#include <linux/dma/xilinx_frmbuf.h>
+#include <linux/of.h>
+#include <linux/of_dma.h>
+#include <linux/platform_device.h>
+#include <video/videomode.h>
+#include "xlnx_bridge.h"
+#include "xlnx_crtc.h"
+#include "xlnx_drv.h"
+
+/*
+ * Overview
+ * --------
+ *
+ * This driver intends to support the display pipeline with DMA engine
+ * driver by initializing DRM crtc and plane objects. The driver makes
+ * an assumption that it's single plane pipeline, as multi-plane pipeline
+ * would require programing beyond the DMA engine interface.
+ */
+
+/**
+ * struct xlnx_dma_chan - struct for DMA engine
+ * @dma_chan: DMA channel
+ * @xt: Interleaved desc config container
+ * @sgl: Data chunk for dma_interleaved_template
+ */
+struct xlnx_dma_chan {
+	struct dma_chan *dma_chan;
+	struct dma_interleaved_template xt;
+	struct data_chunk sgl[1];
+};
+
+/**
+ * struct xlnx_pl_disp - struct for display subsystem
+ * @dev: device structure
+ * @master: logical master device from xlnx drm
+ * @xlnx_crtc: Xilinx DRM driver crtc object
+ * @plane: base drm plane object
+ * @chan: struct for DMA engine
+ * @event: vblank pending event
+ * @callback: callback for registering DMA callback function
+ * @callback_param: parameter for passing  to DMA callback function
+ * @drm: core drm object
+ * @fmt: drm color format
+ * @vtc_bridge: vtc_bridge structure
+ * @fid: field id
+ * @prev_fid: previous field id
+ */
+struct xlnx_pl_disp {
+	struct device *dev;
+	struct platform_device *master;
+	struct xlnx_crtc xlnx_crtc;
+	struct drm_plane plane;
+	struct xlnx_dma_chan *chan;
+	struct drm_pending_vblank_event *event;
+	dma_async_tx_callback callback;
+	void *callback_param;
+	struct drm_device *drm;
+	u32 fmt;
+	struct xlnx_bridge *vtc_bridge;
+	u32 fid;
+	u32 prev_fid;
+};
+
+/*
+ * Xlnx crtc functions
+ */
+static inline struct xlnx_pl_disp *crtc_to_dma(struct xlnx_crtc *xlnx_crtc)
+{
+	return container_of(xlnx_crtc, struct xlnx_pl_disp, xlnx_crtc);
+}
+
+/**
+ * xlnx_pl_disp_complete - vblank handler
+ * @param: parameter to vblank handler
+ *
+ * This function handles the vblank interrupt, and sends an event to
+ * CRTC object.
+ */
+static void xlnx_pl_disp_complete(void *param)
+{
+	struct xlnx_pl_disp *xlnx_pl_disp = param;
+	struct drm_device *drm = xlnx_pl_disp->drm;
+
+	drm_handle_vblank(drm, 0);
+}
+
+/**
+ * xlnx_pl_disp_get_format - Get the current display pipeline format
+ * @xlnx_crtc: xlnx crtc object
+ *
+ * Get the current format of pipeline
+ *
+ * Return: the corresponding DRM_FORMAT_XXX
+ */
+static uint32_t xlnx_pl_disp_get_format(struct xlnx_crtc *xlnx_crtc)
+{
+	struct xlnx_pl_disp *xlnx_pl_disp = crtc_to_dma(xlnx_crtc);
+
+	return xlnx_pl_disp->fmt;
+}
+
+/**
+ * xlnx_pl_disp_get_align - Get the alignment value for pitch
+ * @xlnx_crtc: xlnx crtc object
+ *
+ * Get the alignment value for pitch from the plane
+ *
+ * Return: The alignment value if successful, or the error code.
+ */
+static unsigned int xlnx_pl_disp_get_align(struct xlnx_crtc *xlnx_crtc)
+{
+	struct xlnx_pl_disp *xlnx_pl_disp = crtc_to_dma(xlnx_crtc);
+
+	return 1 << xlnx_pl_disp->chan->dma_chan->device->copy_align;
+}
+
+/*
+ * DRM plane functions
+ */
+static inline struct xlnx_pl_disp *plane_to_dma(struct drm_plane *plane)
+{
+	return container_of(plane, struct xlnx_pl_disp, plane);
+}
+
+/**
+ * xlnx_pl_disp_plane_disable - Disables DRM plane
+ * @plane: DRM plane object
+ *
+ * Disable the DRM plane, by stopping the corrosponding DMA
+ */
+static void xlnx_pl_disp_plane_disable(struct drm_plane *plane)
+{
+	struct xlnx_pl_disp *xlnx_pl_disp = plane_to_dma(plane);
+	struct xlnx_dma_chan *xlnx_dma_chan = xlnx_pl_disp->chan;
+
+	dmaengine_terminate_sync(xlnx_dma_chan->dma_chan);
+}
+
+/**
+ * xlnx_pl_disp_plane_enable - Enables DRM plane
+ * @plane: DRM plane object
+ *
+ * Enable the DRM plane, by enabling the corresponding DMA
+ */
+static void xlnx_pl_disp_plane_enable(struct drm_plane *plane)
+{
+	struct xlnx_pl_disp *xlnx_pl_disp = plane_to_dma(plane);
+	struct dma_async_tx_descriptor *desc;
+	unsigned long flags;
+	struct xlnx_dma_chan *xlnx_dma_chan = xlnx_pl_disp->chan;
+	struct dma_chan *dma_chan = xlnx_dma_chan->dma_chan;
+	struct dma_interleaved_template *xt = &xlnx_dma_chan->xt;
+
+	flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
+	desc = dmaengine_prep_interleaved_dma(dma_chan, xt, flags);
+	if (!desc) {
+		dev_err(xlnx_pl_disp->dev,
+			"failed to prepare DMA descriptor\n");
+		return;
+	}
+	desc->callback = xlnx_pl_disp->callback;
+	desc->callback_param = xlnx_pl_disp->callback_param;
+	xilinx_xdma_set_earlycb(xlnx_dma_chan->dma_chan, desc, EARLY_CALLBACK);
+
+	if (plane->state->crtc->state->adjusted_mode.flags &
+			DRM_MODE_FLAG_INTERLACE) {
+		/*
+		 * Framebuffer DMA Reader sends the first field twice, which
+		 * causes the following fields out of order. The fid is
+		 * reverted to restore the order
+		 */
+		if (plane->state->fb->flags == DRM_MODE_FB_ALTERNATE_TOP) {
+			xlnx_pl_disp->fid = 0;
+		} else if (plane->state->fb->flags ==
+				DRM_MODE_FB_ALTERNATE_BOTTOM) {
+			xlnx_pl_disp->fid = 1;
+		} else {
+			/*
+			 * FIXME: for interlace mode, application may send
+			 * dummy packets before the video field, need to set
+			 * the fid correctly to avoid display distortion
+			 */
+			xlnx_pl_disp->fid = !xlnx_pl_disp->prev_fid;
+		}
+
+		if (xlnx_pl_disp->fid == xlnx_pl_disp->prev_fid) {
+			xlnx_pl_disp_complete(xlnx_pl_disp);
+			return;
+		}
+
+		xilinx_xdma_set_fid(xlnx_dma_chan->dma_chan, desc,
+				    xlnx_pl_disp->fid);
+		xlnx_pl_disp->prev_fid = xlnx_pl_disp->fid;
+	}
+
+	dmaengine_submit(desc);
+	dma_async_issue_pending(xlnx_dma_chan->dma_chan);
+}
+
+static void xlnx_pl_disp_plane_atomic_disable(struct drm_plane *plane,
+					      struct drm_plane_state *old_state)
+{
+	xlnx_pl_disp_plane_disable(plane);
+}
+
+static int xlnx_pl_disp_plane_mode_set(struct drm_plane *plane,
+				       struct drm_framebuffer *fb,
+				       int crtc_x, int crtc_y,
+				       unsigned int crtc_w, unsigned int crtc_h,
+				       u32 src_x, uint32_t src_y,
+				       u32 src_w, uint32_t src_h)
+{
+	struct xlnx_pl_disp *xlnx_pl_disp = plane_to_dma(plane);
+	const struct drm_format_info *info = fb->format;
+	dma_addr_t luma_paddr, chroma_paddr;
+	size_t stride;
+	struct xlnx_dma_chan *xlnx_dma_chan = xlnx_pl_disp->chan;
+
+	if (info->num_planes > 2) {
+		dev_err(xlnx_pl_disp->dev, "Color format not supported\n");
+		return -EINVAL;
+	}
+	luma_paddr = drm_fb_cma_get_gem_addr(fb, plane->state, 0);
+	if (!luma_paddr) {
+		dev_err(xlnx_pl_disp->dev, "failed to get luma paddr\n");
+		return -EINVAL;
+	}
+
+	dev_dbg(xlnx_pl_disp->dev, "num planes = %d\n", info->num_planes);
+	xlnx_dma_chan->xt.numf = src_h;
+	xlnx_dma_chan->sgl[0].size = drm_format_plane_width_bytes(info,
+								  0, src_w);
+	xlnx_dma_chan->sgl[0].icg = fb->pitches[0] - xlnx_dma_chan->sgl[0].size;
+	xlnx_dma_chan->xt.src_start = luma_paddr;
+	xlnx_dma_chan->xt.frame_size = info->num_planes;
+	xlnx_dma_chan->xt.dir = DMA_MEM_TO_DEV;
+	xlnx_dma_chan->xt.src_sgl = true;
+	xlnx_dma_chan->xt.dst_sgl = false;
+
+	/* Do we have a video format aware dma channel?
+	 * so, modify descriptor accordingly. Hueristic test:
+	 * we have a multi-plane format but only one dma channel
+	 */
+	if (info->num_planes > 1) {
+		chroma_paddr = drm_fb_cma_get_gem_addr(fb, plane->state, 1);
+		if (!chroma_paddr) {
+			dev_err(xlnx_pl_disp->dev,
+				"failed to get chroma paddr\n");
+			return -EINVAL;
+		}
+		stride = xlnx_dma_chan->sgl[0].size +
+			xlnx_dma_chan->sgl[0].icg;
+		xlnx_dma_chan->sgl[0].src_icg = chroma_paddr -
+			xlnx_dma_chan->xt.src_start -
+			(xlnx_dma_chan->xt.numf * stride);
+	}
+
+	return 0;
+}
+
+static void xlnx_pl_disp_plane_atomic_update(struct drm_plane *plane,
+					     struct drm_plane_state *old_state)
+{
+	int ret;
+	struct xlnx_pl_disp *xlnx_pl_disp = plane_to_dma(plane);
+
+	ret = xlnx_pl_disp_plane_mode_set(plane,
+					  plane->state->fb,
+					  plane->state->crtc_x,
+					  plane->state->crtc_y,
+					  plane->state->crtc_w,
+					  plane->state->crtc_h,
+					  plane->state->src_x >> 16,
+					  plane->state->src_y >> 16,
+					  plane->state->src_w >> 16,
+					  plane->state->src_h >> 16);
+	if (ret) {
+		dev_err(xlnx_pl_disp->dev, "failed to mode set a plane\n");
+		return;
+	}
+	/* in case frame buffer is used set the color format */
+	xilinx_xdma_drm_config(xlnx_pl_disp->chan->dma_chan,
+			       xlnx_pl_disp->plane.state->fb->format->format);
+	/* apply the new fb addr and enable */
+	xlnx_pl_disp_plane_enable(plane);
+}
+
+static int
+xlnx_pl_disp_plane_atomic_check(struct drm_plane *plane,
+				struct drm_plane_state *new_plane_state)
+{
+	struct drm_atomic_state *state = new_plane_state->state;
+	const struct drm_plane_state *old_plane_state =
+		drm_atomic_get_old_plane_state(state, plane);
+	struct drm_crtc *crtc = new_plane_state->crtc ?: old_plane_state->crtc;
+	struct drm_crtc_state *new_crtc_state;
+
+	if (!crtc)
+		return 0;
+
+	new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+
+	/* plane must be enabled when state is active */
+	if (new_crtc_state->active && !new_plane_state->crtc)
+		return -EINVAL;
+
+	/*
+	 * This check is required to call modeset if there is a change in color
+	 * format
+	 */
+	if (new_plane_state->fb && old_plane_state->fb &&
+	    new_plane_state->fb->format->format !=
+	    old_plane_state->fb->format->format)
+		new_crtc_state->mode_changed = true;
+
+	return 0;
+}
+
+static const struct drm_plane_helper_funcs xlnx_pl_disp_plane_helper_funcs = {
+	.atomic_update = xlnx_pl_disp_plane_atomic_update,
+	.atomic_disable = xlnx_pl_disp_plane_atomic_disable,
+	.atomic_check = xlnx_pl_disp_plane_atomic_check,
+};
+
+static struct drm_plane_funcs xlnx_pl_disp_plane_funcs = {
+	.update_plane = drm_atomic_helper_update_plane,
+	.disable_plane = drm_atomic_helper_disable_plane,
+	.destroy = drm_plane_cleanup,
+	.reset = drm_atomic_helper_plane_reset,
+	.atomic_duplicate_state	= drm_atomic_helper_plane_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+};
+
+static inline struct xlnx_pl_disp *drm_crtc_to_dma(struct drm_crtc *crtc)
+{
+	struct xlnx_crtc *xlnx_crtc = to_xlnx_crtc(crtc);
+
+	return crtc_to_dma(xlnx_crtc);
+}
+
+static void xlnx_pl_disp_crtc_atomic_begin(struct drm_crtc *crtc,
+					   struct drm_crtc_state *old_state)
+{
+	drm_crtc_vblank_on(crtc);
+	spin_lock_irq(&crtc->dev->event_lock);
+	if (crtc->state->event) {
+		/* Consume the flip_done event from atomic helper */
+		crtc->state->event->pipe = drm_crtc_index(crtc);
+		WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+		drm_crtc_arm_vblank_event(crtc, crtc->state->event);
+		crtc->state->event = NULL;
+	}
+	spin_unlock_irq(&crtc->dev->event_lock);
+}
+
+static void xlnx_pl_disp_clear_event(struct drm_crtc *crtc)
+{
+	if (crtc->state->event) {
+		complete_all(crtc->state->event->base.completion);
+		crtc->state->event = NULL;
+	}
+}
+
+static void xlnx_pl_disp_crtc_atomic_enable(struct drm_crtc *crtc,
+					    struct drm_crtc_state *old_state)
+{
+	struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
+	int vrefresh;
+	struct xlnx_crtc *xlnx_crtc = to_xlnx_crtc(crtc);
+	struct xlnx_pl_disp *xlnx_pl_disp = crtc_to_dma(xlnx_crtc);
+	struct videomode vm;
+
+	if (xlnx_pl_disp->vtc_bridge) {
+		/* set video timing */
+		drm_display_mode_to_videomode(adjusted_mode, &vm);
+		xlnx_bridge_set_timing(xlnx_pl_disp->vtc_bridge, &vm);
+		xlnx_bridge_enable(xlnx_pl_disp->vtc_bridge);
+	}
+
+	xlnx_pl_disp_plane_enable(crtc->primary);
+
+	/* Delay of 1 vblank interval for timing gen to be stable */
+	vrefresh = (adjusted_mode->clock * 1000) /
+		   (adjusted_mode->vtotal * adjusted_mode->htotal);
+	msleep(1 * 1000 / vrefresh);
+}
+
+static void xlnx_pl_disp_crtc_atomic_disable(struct drm_crtc *crtc,
+					     struct drm_crtc_state *old_state)
+{
+	struct xlnx_crtc *xlnx_crtc = to_xlnx_crtc(crtc);
+	struct xlnx_pl_disp *xlnx_pl_disp = crtc_to_dma(xlnx_crtc);
+
+	xlnx_pl_disp_plane_disable(crtc->primary);
+	xlnx_pl_disp_clear_event(crtc);
+	drm_crtc_vblank_off(crtc);
+	xlnx_bridge_disable(xlnx_pl_disp->vtc_bridge);
+
+	/* first field is expected to be bottom so init previous field to top */
+	xlnx_pl_disp->prev_fid = 1;
+}
+
+static int xlnx_pl_disp_crtc_atomic_check(struct drm_crtc *crtc,
+					  struct drm_crtc_state *state)
+{
+	return drm_atomic_add_affected_planes(state->state, crtc);
+}
+
+static struct drm_crtc_helper_funcs xlnx_pl_disp_crtc_helper_funcs = {
+	.atomic_enable = xlnx_pl_disp_crtc_atomic_enable,
+	.atomic_disable = xlnx_pl_disp_crtc_atomic_disable,
+	.atomic_check = xlnx_pl_disp_crtc_atomic_check,
+	.atomic_begin = xlnx_pl_disp_crtc_atomic_begin,
+};
+
+static void xlnx_pl_disp_crtc_destroy(struct drm_crtc *crtc)
+{
+	xlnx_pl_disp_plane_disable(crtc->primary);
+	drm_crtc_cleanup(crtc);
+}
+
+static int xlnx_pl_disp_crtc_enable_vblank(struct drm_crtc *crtc)
+{
+	struct xlnx_crtc *xlnx_crtc = to_xlnx_crtc(crtc);
+	struct xlnx_pl_disp *xlnx_pl_disp = crtc_to_dma(xlnx_crtc);
+
+	/*
+	 * Use the complete callback for vblank event assuming the dma engine
+	 * starts on the next descriptor upon this event. This may not be safe
+	 * assumption for some dma engines.
+	 */
+	xlnx_pl_disp->callback = xlnx_pl_disp_complete;
+	xlnx_pl_disp->callback_param = xlnx_pl_disp;
+
+	return 0;
+}
+
+static void xlnx_pl_disp_crtc_disable_vblank(struct drm_crtc *crtc)
+{
+	struct xlnx_crtc *xlnx_crtc = to_xlnx_crtc(crtc);
+	struct xlnx_pl_disp *xlnx_pl_disp = crtc_to_dma(xlnx_crtc);
+
+	xlnx_pl_disp->callback = NULL;
+	xlnx_pl_disp->callback_param = NULL;
+}
+
+static struct drm_crtc_funcs xlnx_pl_disp_crtc_funcs = {
+	.destroy = xlnx_pl_disp_crtc_destroy,
+	.set_config = drm_atomic_helper_set_config,
+	.page_flip = drm_atomic_helper_page_flip,
+	.reset = drm_atomic_helper_crtc_reset,
+	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+	.enable_vblank = xlnx_pl_disp_crtc_enable_vblank,
+	.disable_vblank = xlnx_pl_disp_crtc_disable_vblank,
+};
+
+static int xlnx_pl_disp_bind(struct device *dev, struct device *master,
+			     void *data)
+{
+	struct drm_device *drm = data;
+	struct xlnx_pl_disp *xlnx_pl_disp = dev_get_drvdata(dev);
+	int ret;
+	u32 *fmts = NULL;
+	unsigned int num_fmts = 0;
+
+	/* in case of fb IP query the supported formats and there count */
+	xilinx_xdma_get_drm_vid_fmts(xlnx_pl_disp->chan->dma_chan,
+				     &num_fmts, &fmts);
+	ret = drm_universal_plane_init(drm, &xlnx_pl_disp->plane, 0,
+				       &xlnx_pl_disp_plane_funcs,
+				       fmts ? fmts : &xlnx_pl_disp->fmt,
+				       num_fmts ? num_fmts : 1,
+				       NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
+	if (ret)
+		return ret;
+
+	drm_plane_helper_add(&xlnx_pl_disp->plane,
+			     &xlnx_pl_disp_plane_helper_funcs);
+
+	ret = drm_crtc_init_with_planes(drm, &xlnx_pl_disp->xlnx_crtc.crtc,
+					&xlnx_pl_disp->plane, NULL,
+					&xlnx_pl_disp_crtc_funcs, NULL);
+	if (ret) {
+		drm_plane_cleanup(&xlnx_pl_disp->plane);
+		return ret;
+	}
+
+	drm_crtc_helper_add(&xlnx_pl_disp->xlnx_crtc.crtc,
+			    &xlnx_pl_disp_crtc_helper_funcs);
+	xlnx_pl_disp->xlnx_crtc.get_format = &xlnx_pl_disp_get_format;
+	xlnx_pl_disp->xlnx_crtc.get_align = &xlnx_pl_disp_get_align;
+	xlnx_pl_disp->drm = drm;
+	xlnx_crtc_register(xlnx_pl_disp->drm, &xlnx_pl_disp->xlnx_crtc);
+
+	return 0;
+}
+
+static void xlnx_pl_disp_unbind(struct device *dev, struct device *master,
+				void *data)
+{
+	struct xlnx_pl_disp *xlnx_pl_disp = dev_get_drvdata(dev);
+
+	xlnx_crtc_unregister(xlnx_pl_disp->drm, &xlnx_pl_disp->xlnx_crtc);
+	drm_plane_cleanup(&xlnx_pl_disp->plane);
+	drm_crtc_cleanup(&xlnx_pl_disp->xlnx_crtc.crtc);
+}
+
+static const struct component_ops xlnx_pl_disp_component_ops = {
+	.bind	= xlnx_pl_disp_bind,
+	.unbind	= xlnx_pl_disp_unbind,
+};
+
+static int xlnx_pl_disp_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *vtc_node;
+	struct xlnx_pl_disp *xlnx_pl_disp;
+	int ret;
+	const char *vformat;
+	struct dma_chan *dma_chan;
+	struct xlnx_dma_chan *xlnx_dma_chan;
+
+	xlnx_pl_disp = devm_kzalloc(dev, sizeof(*xlnx_pl_disp), GFP_KERNEL);
+	if (!xlnx_pl_disp)
+		return -ENOMEM;
+
+	dma_chan = of_dma_request_slave_channel(dev->of_node, "dma0");
+	if (IS_ERR_OR_NULL(dma_chan)) {
+		dev_err(dev, "failed to request dma channel\n");
+		return PTR_ERR(dma_chan);
+	}
+
+	xlnx_dma_chan = devm_kzalloc(dev, sizeof(*xlnx_dma_chan), GFP_KERNEL);
+	if (!xlnx_dma_chan)
+		return -ENOMEM;
+
+	xlnx_dma_chan->dma_chan = dma_chan;
+	xlnx_pl_disp->chan = xlnx_dma_chan;
+	ret = of_property_read_string(dev->of_node, "xlnx,vformat", &vformat);
+	if (ret) {
+		dev_err(dev, "No xlnx,vformat value in dts\n");
+		goto err_dma;
+	}
+
+	strcpy((char *)&xlnx_pl_disp->fmt, vformat);
+
+	/* VTC Bridge support */
+	vtc_node = of_parse_phandle(dev->of_node, "xlnx,bridge", 0);
+	if (vtc_node) {
+		xlnx_pl_disp->vtc_bridge = of_xlnx_bridge_get(vtc_node);
+		if (!xlnx_pl_disp->vtc_bridge) {
+			dev_info(dev, "Didn't get vtc bridge instance\n");
+			ret = -EPROBE_DEFER;
+			goto err_dma;
+		}
+	} else {
+		dev_info(dev, "vtc bridge property not present\n");
+	}
+
+	xlnx_pl_disp->dev = dev;
+	platform_set_drvdata(pdev, xlnx_pl_disp);
+
+	ret = component_add(dev, &xlnx_pl_disp_component_ops);
+	if (ret)
+		goto err_dma;
+
+	xlnx_pl_disp->master = xlnx_drm_pipeline_init(pdev);
+	if (IS_ERR(xlnx_pl_disp->master)) {
+		ret = PTR_ERR(xlnx_pl_disp->master);
+		dev_err(dev, "failed to initialize the drm pipeline\n");
+		goto err_component;
+	}
+
+	/* first field is expected to be bottom so init previous field to top */
+	xlnx_pl_disp->prev_fid = 1;
+
+	dev_info(&pdev->dev, "Xlnx PL display driver probed\n");
+
+	return 0;
+
+err_component:
+	component_del(dev, &xlnx_pl_disp_component_ops);
+err_dma:
+	dma_release_channel(xlnx_pl_disp->chan->dma_chan);
+
+	return ret;
+}
+
+static int xlnx_pl_disp_remove(struct platform_device *pdev)
+{
+	struct xlnx_pl_disp *xlnx_pl_disp = platform_get_drvdata(pdev);
+	struct xlnx_dma_chan *xlnx_dma_chan = xlnx_pl_disp->chan;
+
+	of_xlnx_bridge_put(xlnx_pl_disp->vtc_bridge);
+	xlnx_drm_pipeline_exit(xlnx_pl_disp->master);
+	component_del(&pdev->dev, &xlnx_pl_disp_component_ops);
+
+	/* Make sure the channel is terminated before release */
+	dmaengine_terminate_sync(xlnx_dma_chan->dma_chan);
+	dma_release_channel(xlnx_dma_chan->dma_chan);
+
+	return 0;
+}
+
+static const struct of_device_id xlnx_pl_disp_of_match[] = {
+	{ .compatible = "xlnx,pl-disp"},
+	{ }
+};
+MODULE_DEVICE_TABLE(of, xlnx_pl_disp_of_match);
+
+static struct platform_driver xlnx_pl_disp_driver = {
+	.probe = xlnx_pl_disp_probe,
+	.remove = xlnx_pl_disp_remove,
+	.driver = {
+		.name = "xlnx-pl-disp",
+		.of_match_table = xlnx_pl_disp_of_match,
+	},
+};
+
+module_platform_driver(xlnx_pl_disp_driver);
+
+MODULE_AUTHOR("Saurabh Sengar");
+MODULE_DESCRIPTION("Xilinx DRM Display Driver for PL IPs");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/xlnx/xlnx_scaler.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/xlnx/xlnx_scaler.c
@@ -0,0 +1,1980 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * VPSS SCALER DRM bridge driver
+ *
+ * Copyright (C) 2017-2018 Xilinx, Inc.
+ *
+ * Author: Venkateshwar rao G <vgannava@xilinx.com>
+ *	   Rohit Athavale <rathavale@xilinx.com>
+ */
+
+/*
+ * Overview:
+ * This experimentatl driver works as a bridge driver and
+ * reused the code from V4L2.
+ * TODO:
+ * Need to implement in a modular approach to share driver code between
+ * V4L2 and DRM frameworks.
+ * Should be integrated with plane.
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <uapi/linux/media-bus-format.h>
+
+#include "xlnx_bridge.h"
+
+#define XSCALER_MAX_WIDTH		(3840)
+#define XSCALER_MAX_HEIGHT		(2160)
+#define XSCALER_MAX_PHASES		(64)
+#define XSCALER_MIN_WIDTH		(64)
+#define XSCALER_MIN_HEIGHT		(64)
+
+/* Video subsytems block offset */
+#define S_AXIS_RESET_OFF		(0x00010000)
+#define V_HSCALER_OFF			(0x00000000)
+#define V_VSCALER_OFF			(0x00020000)
+
+/* HW Reset Network GPIO Channel */
+#define XGPIO_CH_RESET_SEL		(1)
+#define XGPIO_RESET_MASK_VIDEO_IN	BIT(0)
+#define XGPIO_RESET_MASK_IP_AXIS	BIT(1)
+#define XGPIO_RESET_MASK_ALL_BLOCKS	(XGPIO_RESET_MASK_VIDEO_IN | \
+						XGPIO_RESET_MASK_IP_AXIS)
+#define XGPIO_DATA_OFFSET		(0x0)
+#define XGPIO_DATA2_OFFSET		(0x8)
+#define XGPIO_TRI2_OFFSET		(0xc)
+
+#define XGPIO_ISR_OFFSET		(0x120)
+#define XGPIO_IER_OFFSET		(0x128)
+#define XGPIO_CHAN_OFFSET		(8)
+#define STEP_PRECISION			(65536)
+
+/* SCALER POWER MACROS */
+#define XSCALER_RESET_ASSERT            (0x1)
+#define XSCALER_RESET_DEASSERT          (0x0)
+
+/* Video IP PPC */
+#define XSCALER_PPC_1			(1)
+#define XSCALER_PPC_2			(2)
+
+#define XV_HSCALER_MAX_H_TAPS		(12)
+#define XV_HSCALER_MAX_H_PHASES		(64)
+#define XV_HSCALER_MAX_LINE_WIDTH	(3840)
+#define XV_VSCALER_MAX_V_TAPS		(12)
+#define XV_VSCALER_MAX_V_PHASES		(64)
+
+#define XV_HSCALER_TAPS_2		(2)
+#define XV_HSCALER_TAPS_4		(4)
+#define XV_HSCALER_TAPS_6		(6)
+#define XV_HSCALER_TAPS_8		(8)
+#define XV_HSCALER_TAPS_10		(10)
+#define XV_HSCALER_TAPS_12		(12)
+#define XV_VSCALER_TAPS_2		(2)
+#define XV_VSCALER_TAPS_4		(4)
+#define XV_VSCALER_TAPS_6		(6)
+#define XV_VSCALER_TAPS_8		(8)
+#define XV_VSCALER_TAPS_10		(10)
+#define XV_VSCALER_TAPS_12		(12)
+
+/* Mask definitions for Low and high 16 bits in a 32 bit number */
+#define XHSC_MASK_LOW_16BITS		GENMASK(15, 0)
+#define XHSC_MASK_HIGH_16BITS		GENMASK(31, 16)
+#define XHSC_MASK_LOW_32BITS		GENMASK(31, 0)
+#define XHSC_STEP_PRECISION_SHIFT	(16)
+#define XHSC_HPHASE_SHIFT_BY_6		(6)
+#define XHSC_HPHASE_MULTIPLIER		(9)
+#define XSCALER_BITSHIFT_16		(16)
+
+/* Mask definitions for Low and high 16 bits in a 32 bit number */
+#define XVSC_MASK_LOW_16BITS		GENMASK(15, 0)
+#define XVSC_MASK_HIGH_16BITS		GENMASK(31, 16)
+
+/* Scaler AP Control Registers */
+#define XSCALER_START			BIT(0)
+#define XSCALER_AUTO_RESTART		BIT(7)
+#define XSCALER_STREAM_ON		(XSCALER_START | XSCALER_AUTO_RESTART)
+
+/* H-scaler registers */
+#define XV_HSCALER_CTRL_ADDR_AP_CTRL			(0x0000)
+#define XV_HSCALER_CTRL_ADDR_GIE			(0x0004)
+#define XV_HSCALER_CTRL_ADDR_IER			(0x0008)
+#define XV_HSCALER_CTRL_ADDR_ISR			(0x000c)
+#define XV_HSCALER_CTRL_ADDR_HWREG_HEIGHT_DATA		(0x0010)
+#define XV_HSCALER_CTRL_ADDR_HWREG_WIDTHIN_DATA		(0x0018)
+#define XV_HSCALER_CTRL_ADDR_HWREG_WIDTHOUT_DATA	(0x0020)
+#define XV_HSCALER_CTRL_ADDR_HWREG_COLORMODE_DATA	(0x0028)
+#define XV_HSCALER_CTRL_ADDR_HWREG_PIXELRATE_DATA	(0x0030)
+#define XV_HSCALER_CTRL_ADDR_HWREG_COLORMODEOUT_DATA	(0X0038)
+#define XV_HSCALER_CTRL_ADDR_HWREG_HFLTCOEFF_BASE	(0x0800)
+#define XV_HSCALER_CTRL_ADDR_HWREG_HFLTCOEFF_HIGH	(0x0bff)
+
+#define XV_HSCALER_CTRL_WIDTH_HWREG_HFLTCOEFF		(16)
+#define XV_HSCALER_CTRL_DEPTH_HWREG_HFLTCOEFF		(384)
+#define XV_HSCALER_CTRL_ADDR_HWREG_PHASESH_V_BASE	(0x2000)
+#define XV_HSCALER_CTRL_ADDR_HWREG_PHASESH_V_HIGH	(0x3fff)
+#define XV_HSCALER_CTRL_WIDTH_HWREG_PHASESH_V		(18)
+#define XV_HSCALER_CTRL_DEPTH_HWREG_PHASESH_V		(1920)
+#define XV_HSCALER_CTRL_ADDR_HWREG_PHASEH_FIX		(0x4000)
+
+/* H-scaler masks */
+#define XV_HSCALER_PHASESH_V_OUTPUT_WR_EN		BIT(8)
+
+/* V-scaler registers */
+#define XV_VSCALER_CTRL_ADDR_AP_CTRL			(0x000)
+#define XV_VSCALER_CTRL_ADDR_GIE			(0x004)
+#define XV_VSCALER_CTRL_ADDR_IER			(0x008)
+#define XV_VSCALER_CTRL_ADDR_ISR			(0x00c)
+#define XV_VSCALER_CTRL_ADDR_HWREG_HEIGHTIN_DATA	(0x010)
+#define XV_VSCALER_CTRL_ADDR_HWREG_WIDTH_DATA		(0x018)
+#define XV_VSCALER_CTRL_ADDR_HWREG_HEIGHTOUT_DATA	(0x020)
+#define XV_VSCALER_CTRL_ADDR_HWREG_LINERATE_DATA	(0x028)
+#define XV_VSCALER_CTRL_ADDR_HWREG_COLORMODE_DATA	(0x030)
+#define XV_VSCALER_CTRL_ADDR_HWREG_VFLTCOEFF_BASE	(0x800)
+#define XV_VSCALER_CTRL_ADDR_HWREG_VFLTCOEFF_HIGH	(0xbff)
+
+/* Coefficients for 6, 8, 10 and 12 tap filters */
+
+static const s16
+XV_lanczos2_taps6[XV_HSCALER_MAX_H_PHASES][XV_HSCALER_TAPS_6] = {
+	{   0,    0, 4096,    0,    0,   0, },
+	{   0,  -40, 4099,   42,    0,  -5, },
+	{  -1,  -77, 4097,   87,   -1,  -9, },
+	{  -2, -111, 4092,  134,   -2, -15, },
+	{  -4, -143, 4082,  184,   -4, -19, },
+	{  -6, -173, 4068,  237,   -7, -23, },
+	{  -8, -201, 4051,  292,  -10, -28, },
+	{ -11, -226, 4029,  350,  -13, -33, },
+	{ -14, -248, 4003,  411,  -18, -38, },
+	{ -17, -269, 3974,  474,  -23, -43, },
+	{ -21, -287, 3940,  539,  -28, -47, },
+	{ -24, -303, 3903,  608,  -34, -54, },
+	{ -28, -317, 3862,  678,  -41, -58, },
+	{ -32, -329, 3817,  751,  -49, -62, },
+	{ -37, -339, 3768,  826,  -57, -65, },
+	{ -41, -347, 3716,  903,  -65, -70, },
+	{ -45, -353, 3661,  982,  -75, -74, },
+	{ -50, -358, 3602, 1063,  -84, -77, },
+	{ -54, -361, 3539, 1146,  -95, -79, },
+	{ -58, -362, 3474, 1230, -106, -82, },
+	{ -62, -361, 3406, 1317, -117, -87, },
+	{ -66, -359, 3335, 1404, -128, -90, },
+	{ -70, -356, 3261, 1493, -140, -92, },
+	{ -74, -351, 3185, 1583, -153, -94, },
+	{ -77, -346, 3106, 1673, -165, -95, },
+	{ -81, -339, 3025, 1765, -178, -96, },
+	{ -84, -331, 2942, 1857, -191, -97, },
+	{ -87, -322, 2858, 1950, -204, -99, },
+	{ -89, -313, 2771, 2043, -217, -99, },
+	{ -92, -302, 2683, 2136, -230, -99, },
+	{ -94, -292, 2594, 2228, -243, -97, },
+	{ -95, -280, 2504, 2321, -256, -98, },
+	{ -97, -268, 2413, 2413, -268, -97, },
+	{ -97, -256, 2321, 2504, -280, -96, },
+	{ -98, -243, 2228, 2594, -292, -93, },
+	{ -98, -230, 2136, 2683, -302, -93, },
+	{ -98, -217, 2043, 2771, -313, -90, },
+	{ -98, -204, 1950, 2858, -322, -88, },
+	{ -97, -191, 1857, 2942, -331, -84, },
+	{ -96, -178, 1765, 3025, -339, -81, },
+	{ -95, -165, 1673, 3106, -346, -77, },
+	{ -93, -153, 1583, 3185, -351, -75, },
+	{ -91, -140, 1493, 3261, -356, -71, },
+	{ -89, -128, 1404, 3335, -359, -67, },
+	{ -86, -117, 1317, 3406, -361, -63, },
+	{ -83, -106, 1230, 3474, -362, -57, },
+	{ -80,  -95, 1146, 3539, -361, -53, },
+	{ -77,  -84, 1063, 3602, -358, -50, },
+	{ -73,  -75,  982, 3661, -353, -46, },
+	{ -69,  -65,  903, 3716, -347, -42, },
+	{ -65,  -57,  826, 3768, -339, -37, },
+	{ -61,  -49,  751, 3817, -329, -33, },
+	{ -57,  -41,  678, 3862, -317, -29, },
+	{ -52,  -34,  608, 3903, -303, -26, },
+	{ -47,  -28,  539, 3940, -287, -21, },
+	{ -43,  -23,  474, 3974, -269, -17, },
+	{ -38,  -18,  411, 4003, -248, -14, },
+	{ -33,  -13,  350, 4029, -226, -11, },
+	{ -28,  -10,  292, 4051, -201,  -8, },
+	{ -24,   -7,  237, 4068, -173,  -5, },
+	{ -19,   -4,  184, 4082, -143,  -4, },
+	{ -14,   -2,  134, 4092, -111,  -3, },
+	{  -9,   -1,   87, 4097,  -77,  -1, },
+	{  -5,    0,   42, 4099,  -40,   0, }
+};
+
+/* ScalingRatio = 1.25 */
+static const s16
+XV_fixedcoeff_taps6_SR1p2[XV_HSCALER_MAX_H_PHASES][XV_HSCALER_TAPS_6] = {
+	{ -102,  512, 3208,  512, -102,  68, },
+	{  -97,  471, 3209,  555, -107,  65, },
+	{  -92,  431, 3208,  599, -113,  63, },
+	{  -87,  392, 3205,  645, -118,  59, },
+	{  -82,  354, 3199,  691, -124,  58, },
+	{  -77,  318, 3191,  739, -130,  55, },
+	{  -72,  282, 3181,  788, -136,  53, },
+	{  -68,  248, 3169,  838, -141,  50, },
+	{  -64,  216, 3155,  889, -147,  47, },
+	{  -59,  184, 3139,  941, -153,  44, },
+	{  -55,  154, 3120,  993, -158,  42, },
+	{  -52,  125, 3100, 1047, -164,  40, },
+	{  -48,   98, 3077, 1101, -169,  37, },
+	{  -44,   71, 3052, 1157, -174,  34, },
+	{  -41,   46, 3025, 1212, -180,  34, },
+	{  -38,   23, 2996, 1269, -184,  30, },
+	{  -35,    0, 2965, 1326, -189,  29, },
+	{  -32,  -21, 2933, 1383, -193,  26, },
+	{  -29,  -41, 2898, 1441, -198,  25, },
+	{  -26,  -60, 2862, 1500, -201,  21, },
+	{  -24,  -78, 2823, 1558, -205,  22, },
+	{  -21,  -94, 2784, 1617, -208,  18, },
+	{  -19, -109, 2742, 1676, -210,  16, },
+	{  -17, -123, 2699, 1734, -212,  15, },
+	{  -14, -136, 2654, 1793, -214,  13, },
+	{  -12, -148, 2608, 1852, -214,  10, },
+	{  -10, -159, 2560, 1910, -215,  10, },
+	{   -9, -168, 2512, 1968, -215,   8, },
+	{   -7, -177, 2461, 2026, -214,   7, },
+	{   -5, -185, 2410, 2083, -212,   5, },
+	{   -3, -192, 2358, 2139, -209,   3, },
+	{   -2, -197, 2304, 2195, -206,   2, },
+	{    0, -202, 2250, 2250, -202,   0, },
+	{    2, -206, 2195, 2304, -197,  -2, },
+	{    3, -209, 2139, 2358, -192,  -3, },
+	{    5, -212, 2083, 2410, -185,  -5, },
+	{    6, -214, 2026, 2461, -177,  -6, },
+	{    8, -215, 1968, 2512, -168,  -9, },
+	{   10, -215, 1910, 2560, -159, -10, },
+	{   11, -214, 1852, 2608, -148, -13, },
+	{   13, -214, 1793, 2654, -136, -14, },
+	{   15, -212, 1734, 2699, -123, -17, },
+	{   17, -210, 1676, 2742, -109, -20, },
+	{   18, -208, 1617, 2784,  -94, -21, },
+	{   20, -205, 1558, 2823,  -78, -22, },
+	{   22, -201, 1500, 2862,  -60, -27, },
+	{   24, -198, 1441, 2898,  -41, -28, },
+	{   26, -193, 1383, 2933,  -21, -32, },
+	{   28, -189, 1326, 2965,    0, -34, },
+	{   30, -184, 1269, 2996,   23, -38, },
+	{   33, -180, 1212, 3025,   46, -40, },
+	{   35, -174, 1157, 3052,   71, -45, },
+	{   37, -169, 1101, 3077,   98, -48, },
+	{   40, -164, 1047, 3100,  125, -52, },
+	{   42, -158,  993, 3120,  154, -55, },
+	{   44, -153,  941, 3139,  184, -59, },
+	{   47, -147,  889, 3155,  216, -64, },
+	{   50, -141,  838, 3169,  248, -68, },
+	{   52, -136,  788, 3181,  282, -71, },
+	{   55, -130,  739, 3191,  318, -77, },
+	{   57, -124,  691, 3199,  354, -81, },
+	{   60, -118,  645, 3205,  392, -88, },
+	{   63, -113,  599, 3208,  431, -92, },
+	{   65, -107,  555, 3209,  471, -97, }
+};
+
+/* ScalingRatio = 2.0 */
+static const s16
+XV_fixedcoeff_taps6_SR2[XV_HSCALER_MAX_H_PHASES][XV_HSCALER_TAPS_6] = {
+	{   0, 970, 2235,  970,   0, -79, },
+	{  -3, 943, 2233,  997,   3, -77, },
+	{  -5, 915, 2231, 1025,   6, -76, },
+	{  -8, 888, 2227, 1052,  10, -73, },
+	{ -10, 861, 2223, 1079,  14, -71, },
+	{ -12, 834, 2218, 1107,  18, -69, },
+	{ -14, 808, 2213, 1134,  22, -67, },
+	{ -15, 782, 2206, 1162,  27, -66, },
+	{ -17, 756, 2199, 1189,  32, -63, },
+	{ -18, 731, 2191, 1217,  37, -62, },
+	{ -20, 706, 2182, 1245,  42, -59, },
+	{ -21, 681, 2172, 1272,  48, -56, },
+	{ -22, 657, 2162, 1300,  55, -56, },
+	{ -22, 633, 2151, 1327,  61, -54, },
+	{ -23, 609, 2139, 1355,  68, -52, },
+	{ -24, 586, 2126, 1382,  76, -50, },
+	{ -25, 564, 2113, 1410,  83, -49, },
+	{ -25, 541, 2099, 1437,  91, -47, },
+	{ -26, 520, 2084, 1464, 100, -46, },
+	{ -26, 498, 2069, 1491, 109, -45, },
+	{ -27, 477, 2053, 1517, 118, -42, },
+	{ -27, 457, 2036, 1544, 128, -42, },
+	{ -27, 437, 2019, 1570, 138, -41, },
+	{ -28, 418, 2001, 1596, 148, -39, },
+	{ -28, 399, 1983, 1622, 160, -40, },
+	{ -29, 380, 1964, 1647, 171, -37, },
+	{ -29, 362, 1944, 1672, 183, -36, },
+	{ -29, 345, 1924, 1697, 195, -36, },
+	{ -30, 328, 1903, 1722, 208, -35, },
+	{ -30, 311, 1882, 1746, 221, -34, },
+	{ -31, 295, 1860, 1770, 235, -33, },
+	{ -31, 279, 1838, 1793, 249, -32, },
+	{ -32, 264, 1816, 1816, 264, -32, },
+	{ -32, 249, 1793, 1838, 279, -31, },
+	{ -33, 235, 1770, 1860, 295, -31, },
+	{ -34, 221, 1746, 1882, 311, -30, },
+	{ -35, 208, 1722, 1903, 328, -30, },
+	{ -35, 195, 1697, 1924, 345, -30, },
+	{ -36, 183, 1672, 1944, 362, -29, },
+	{ -37, 171, 1647, 1964, 380, -29, },
+	{ -38, 160, 1622, 1983, 399, -30, },
+	{ -39, 148, 1596, 2001, 418, -28, },
+	{ -40, 138, 1570, 2019, 437, -28, },
+	{ -42, 128, 1544, 2036, 457, -27, },
+	{ -43, 118, 1517, 2053, 477, -26, },
+	{ -44, 109, 1491, 2069, 498, -27, },
+	{ -46, 100, 1464, 2084, 520, -26, },
+	{ -47,  91, 1437, 2099, 541, -25, },
+	{ -49,  83, 1410, 2113, 564, -25, },
+	{ -50,  76, 1382, 2126, 586, -24, },
+	{ -52,  68, 1355, 2139, 609, -23, },
+	{ -54,  61, 1327, 2151, 633, -22, },
+	{ -55,  55, 1300, 2162, 657, -23, },
+	{ -57,  48, 1272, 2172, 681, -20, },
+	{ -59,  42, 1245, 2182, 706, -20, },
+	{ -61,  37, 1217, 2191, 731, -19, },
+	{ -63,  32, 1189, 2199, 756, -17, },
+	{ -65,  27, 1162, 2206, 782, -16, },
+	{ -67,  22, 1134, 2213, 808, -14, },
+	{ -69,  18, 1107, 2218, 834, -12, },
+	{ -71,  14, 1079, 2223, 861, -10, },
+	{ -73,  10, 1052, 2227, 888,  -8, },
+	{ -75,   6, 1025, 2231, 915,  -6, },
+	{ -77,   3,  997, 2233, 943,  -3, }
+};
+
+/* ScalingRatio = 3.0 */
+static const s16
+XV_fixedcoeff_taps6_SR3[XV_HSCALER_MAX_H_PHASES][XV_HSCALER_TAPS_6] = {
+	{ 126, 1019, 1806, 1019,  126,   0, },
+	{ 120, 1000, 1805, 1038,  132,   1, },
+	{ 114,  980, 1804, 1057,  138,   3, },
+	{ 108,  961, 1802, 1075,  145,   5, },
+	{ 103,  942, 1800, 1094,  152,   5, },
+	{  98,  922, 1797, 1113,  159,   7, },
+	{  93,  903, 1794, 1131,  167,   8, },
+	{  88,  884, 1790, 1150,  174,  10, },
+	{  84,  865, 1786, 1168,  182,  11, },
+	{  80,  846, 1782, 1187,  191,  10, },
+	{  76,  827, 1777, 1205,  199,  12, },
+	{  72,  809, 1771, 1223,  208,  13, },
+	{  68,  790, 1766, 1241,  217,  14, },
+	{  65,  772, 1759, 1259,  226,  15, },
+	{  61,  753, 1753, 1277,  236,  16, },
+	{  58,  735, 1746, 1295,  246,  16, },
+	{  56,  717, 1738, 1313,  256,  16, },
+	{  53,  699, 1730, 1330,  266,  18, },
+	{  50,  682, 1722, 1347,  277,  18, },
+	{  48,  664, 1713, 1364,  288,  19, },
+	{  46,  647, 1704, 1381,  299,  19, },
+	{  43,  630, 1694, 1398,  311,  20, },
+	{  41,  613, 1684, 1414,  323,  21, },
+	{  40,  596, 1674, 1430,  335,  21, },
+	{  38,  580, 1663, 1446,  347,  22, },
+	{  36,  563, 1652, 1462,  360,  23, },
+	{  35,  547, 1641, 1478,  373,  22, },
+	{  33,  531, 1629, 1493,  386,  24, },
+	{  32,  516, 1617, 1508,  399,  24, },
+	{  31,  500, 1604, 1523,  413,  25, },
+	{  30,  485, 1592, 1537,  427,  25, },
+	{  29,  470, 1578, 1551,  441,  27, },
+	{  28,  455, 1565, 1565,  455,  28, },
+	{  27,  441, 1551, 1578,  470,  29, },
+	{  26,  427, 1537, 1592,  485,  29, },
+	{  25,  413, 1523, 1604,  500,  31, },
+	{  24,  399, 1508, 1617,  516,  32, },
+	{  24,  386, 1493, 1629,  531,  33, },
+	{  23,  373, 1478, 1641,  547,  34, },
+	{  22,  360, 1462, 1652,  563,  37, },
+	{  22,  347, 1446, 1663,  580,  38, },
+	{  21,  335, 1430, 1674,  596,  40, },
+	{  20,  323, 1414, 1684,  613,  42, },
+	{  20,  311, 1398, 1694,  630,  43, },
+	{  19,  299, 1381, 1704,  647,  46, },
+	{  19,  288, 1364, 1713,  664,  48, },
+	{  18,  277, 1347, 1722,  682,  50, },
+	{  17,  266, 1330, 1730,  699,  54, },
+	{  17,  256, 1313, 1738,  717,  55, },
+	{  16,  246, 1295, 1746,  735,  58, },
+	{  15,  236, 1277, 1753,  753,  62, },
+	{  15,  226, 1259, 1759,  772,  65, },
+	{  14,  217, 1241, 1766,  790,  68, },
+	{  13,  208, 1223, 1771,  809,  72, },
+	{  12,  199, 1205, 1777,  827,  76, },
+	{  11,  191, 1187, 1782,  846,  79, },
+	{  10,  182, 1168, 1786,  865,  85, },
+	{   9,  174, 1150, 1790,  884,  89, },
+	{   8,  167, 1131, 1794,  903,  93, },
+	{   7,  159, 1113, 1797,  922,  98, },
+	{   6,  152, 1094, 1800,  942, 102, },
+	{   5,  145, 1075, 1802,  961, 108, },
+	{   3,  138, 1057, 1804,  980, 114, },
+	{   2,  132, 1038, 1805, 1000, 119, }
+};
+
+/* ScalingRatio = 4 */
+static const s16
+XV_fixedcoeff_taps6_SR4[XV_HSCALER_MAX_H_PHASES][XV_HSCALER_TAPS_6] = {
+	{ 176, 1009, 1643, 1009, 176,  83, },
+	{ 169,  993, 1644, 1026, 183,  81, },
+	{ 162,  978, 1644, 1042, 190,  80, },
+	{ 156,  962, 1643, 1058, 198,  79, },
+	{ 150,  946, 1642, 1074, 205,  79, },
+	{ 144,  930, 1641, 1091, 213,  77, },
+	{ 138,  914, 1640, 1107, 222,  75, },
+	{ 133,  898, 1638, 1123, 230,  74, },
+	{ 128,  882, 1635, 1139, 239,  73, },
+	{ 123,  866, 1633, 1154, 248,  72, },
+	{ 118,  850, 1629, 1170, 257,  72, },
+	{ 114,  834, 1626, 1186, 267,  69, },
+	{ 109,  818, 1622, 1201, 276,  70, },
+	{ 105,  802, 1618, 1217, 286,  68, },
+	{ 101,  786, 1613, 1232, 297,  67, },
+	{  97,  771, 1608, 1247, 307,  66, },
+	{  94,  755, 1603, 1262, 318,  64, },
+	{  91,  739, 1597, 1276, 328,  65, },
+	{  87,  724, 1591, 1291, 339,  64, },
+	{  85,  708, 1585, 1305, 351,  62, },
+	{  82,  693, 1578, 1319, 362,  62, },
+	{  79,  677, 1571, 1333, 374,  62, },
+	{  77,  662, 1563, 1347, 386,  61, },
+	{  75,  647, 1556, 1360, 398,  60, },
+	{  73,  632, 1547, 1373, 410,  61, },
+	{  71,  617, 1539, 1386, 423,  60, },
+	{  69,  602, 1530, 1399, 436,  60, },
+	{  68,  587, 1521, 1412, 449,  59, },
+	{  66,  573, 1511, 1424, 462,  60, },
+	{  65,  558, 1501, 1436, 475,  61, },
+	{  64,  544, 1491, 1447, 488,  62, },
+	{  63,  530, 1481, 1459, 502,  61, },
+	{  62,  516, 1470, 1470, 516,  62, },
+	{  62,  502, 1459, 1481, 530,  62, },
+	{  61,  488, 1447, 1491, 544,  65, },
+	{  61,  475, 1436, 1501, 558,  65, },
+	{  60,  462, 1424, 1511, 573,  66, },
+	{  60,  449, 1412, 1521, 587,  67, },
+	{  60,  436, 1399, 1530, 602,  69, },
+	{  60,  423, 1386, 1539, 617,  71, },
+	{  61,  410, 1373, 1547, 632,  73, },
+	{  61,  398, 1360, 1556, 647,  74, },
+	{  61,  386, 1347, 1563, 662,  77, },
+	{  62,  374, 1333, 1571, 677,  79, },
+	{  62,  362, 1319, 1578, 693,  82, },
+	{  63,  351, 1305, 1585, 708,  84, },
+	{  64,  339, 1291, 1591, 724,  87, },
+	{  64,  328, 1276, 1597, 739,  92, },
+	{  65,  318, 1262, 1603, 755,  93, },
+	{  66,  307, 1247, 1608, 771,  97, },
+	{  67,  297, 1232, 1613, 786, 101, },
+	{  68,  286, 1217, 1618, 802, 105, },
+	{  69,  276, 1201, 1622, 818, 110, },
+	{  70,  267, 1186, 1626, 834, 113, },
+	{  71,  257, 1170, 1629, 850, 119, },
+	{  72,  248, 1154, 1633, 866, 123, },
+	{  73,  239, 1139, 1635, 882, 128, },
+	{  75,  230, 1123, 1638, 898, 132, },
+	{  76,  222, 1107, 1640, 914, 137, },
+	{  77,  213, 1091, 1641, 930, 144, },
+	{  78,  205, 1074, 1642, 946, 151, },
+	{  79,  198, 1058, 1643, 962, 156, },
+	{  80,  190, 1042, 1644, 978, 162, },
+	{  82,  183, 1026, 1644, 993, 168, }
+};
+
+/* ScalingRatio = 2.0 */
+static const s16
+XV_fixedcoeff_taps8_SR2[XV_HSCALER_MAX_H_PHASES][XV_HSCALER_TAPS_8] = {
+	{ -55,   0, 1078, 2049, 1078,    0, -55,   1, },
+	{ -53,  -7, 1055, 2049, 1102,    7, -56,  -1, },
+	{ -52, -13, 1032, 2048, 1126,   15, -58,  -2, },
+	{ -50, -20, 1009, 2047, 1149,   22, -59,  -2, },
+	{ -49, -26,  986, 2046, 1173,   31, -61,  -4, },
+	{ -47, -31,  963, 2043, 1197,   39, -62,  -6, },
+	{ -46, -37,  940, 2040, 1220,   48, -64,  -5, },
+	{ -45, -42,  917, 2037, 1244,   57, -65,  -7, },
+	{ -43, -47,  894, 2033, 1267,   66, -67,  -7, },
+	{ -42, -51,  871, 2028, 1290,   76, -69,  -7, },
+	{ -41, -55,  848, 2023, 1313,   86, -70,  -8, },
+	{ -40, -59,  826, 2017, 1336,   97, -72,  -9, },
+	{ -38, -63,  803, 2010, 1359,  108, -73, -10, },
+	{ -37, -67,  781, 2003, 1382,  119, -75, -10, },
+	{ -36, -70,  759, 1996, 1405,  130, -76, -12, },
+	{ -35, -73,  737, 1987, 1427,  142, -78, -11, },
+	{ -34, -76,  715, 1979, 1449,  154, -79, -12, },
+	{ -33, -78,  693, 1969, 1471,  167, -81, -12, },
+	{ -32, -81,  672, 1959, 1493,  180, -82, -13, },
+	{ -31, -83,  650, 1949, 1514,  193, -83, -13, },
+	{ -30, -85,  629, 1938, 1536,  207, -85, -14, },
+	{ -29, -86,  609, 1926, 1557,  221, -86, -16, },
+	{ -28, -88,  588, 1914, 1577,  235, -87, -15, },
+	{ -28, -89,  568, 1902, 1598,  250, -88, -17, },
+	{ -27, -90,  548, 1889, 1618,  265, -89, -18, },
+	{ -26, -91,  528, 1875, 1638,  280, -90, -18, },
+	{ -25, -92,  508, 1861, 1657,  296, -91, -18, },
+	{ -24, -93,  489, 1846, 1676,  312, -92, -18, },
+	{ -24, -93,  470, 1831, 1695,  328, -92, -19, },
+	{ -23, -94,  451, 1816, 1714,  345, -93, -20, },
+	{ -22, -94,  432, 1800, 1732,  361, -93, -20, },
+	{ -22, -94,  414, 1783, 1749,  379, -94, -19, },
+	{ -21, -94,  396, 1767, 1767,  396, -94, -21, },
+	{ -21, -94,  379, 1749, 1783,  414, -94, -20, },
+	{ -20, -93,  361, 1732, 1800,  432, -94, -22, },
+	{ -19, -93,  345, 1714, 1816,  451, -94, -24, },
+	{ -19, -92,  328, 1695, 1831,  470, -93, -24, },
+	{ -18, -92,  312, 1676, 1846,  489, -93, -24, },
+	{ -18, -91,  296, 1657, 1861,  508, -92, -25, },
+	{ -17, -90,  280, 1638, 1875,  528, -91, -27, },
+	{ -17, -89,  265, 1618, 1889,  548, -90, -28, },
+	{ -16, -88,  250, 1598, 1902,  568, -89, -29, },
+	{ -16, -87,  235, 1577, 1914,  588, -88, -27, },
+	{ -15, -86,  221, 1557, 1926,  609, -86, -30, },
+	{ -14, -85,  207, 1536, 1938,  629, -85, -30, },
+	{ -14, -83,  193, 1514, 1949,  650, -83, -30, },
+	{ -13, -82,  180, 1493, 1959,  672, -81, -32, },
+	{ -13, -81,  167, 1471, 1969,  693, -78, -32, },
+	{ -12, -79,  154, 1449, 1979,  715, -76, -34, },
+	{ -12, -78,  142, 1427, 1987,  737, -73, -34, },
+	{ -11, -76,  130, 1405, 1996,  759, -70, -37, },
+	{ -10, -75,  119, 1382, 2003,  781, -67, -37, },
+	{ -10, -73,  108, 1359, 2010,  803, -63, -38, },
+	{  -9, -72,   97, 1336, 2017,  826, -59, -40, },
+	{  -8, -70,   86, 1313, 2023,  848, -55, -41, },
+	{  -8, -69,   76, 1290, 2028,  871, -51, -41, },
+	{  -7, -67,   66, 1267, 2033,  894, -47, -43, },
+	{  -6, -65,   57, 1244, 2037,  917, -42, -46, },
+	{  -5, -64,   48, 1220, 2040,  940, -37, -46, },
+	{  -5, -62,   39, 1197, 2043,  963, -31, -48, },
+	{  -4, -61,   31, 1173, 2046,  986, -26, -49, },
+	{  -3, -59,   22, 1149, 2047, 1009, -20, -49, },
+	{  -2, -58,   15, 1126, 2048, 1032, -13, -52, },
+	{  -1, -56,    7, 1102, 2049, 1055,  -7, -53, }
+};
+
+/* ScalingRatio = 3.0 */
+static const s16
+XV_fixedcoeff_taps8_SR3[XV_HSCALER_MAX_H_PHASES][XV_HSCALER_TAPS_8] = {
+	{   0, 275, 1036, 1514, 1036,  275,   0, -40, },
+	{  -1, 266, 1023, 1514, 1048,  283,   1, -38, },
+	{  -2, 257, 1010, 1513, 1060,  292,   2, -36, },
+	{  -3, 249,  997, 1512, 1073,  301,   3, -36, },
+	{  -3, 241,  983, 1510, 1085,  310,   5, -35, },
+	{  -4, 233,  970, 1509, 1097,  319,   6, -34, },
+	{  -5, 225,  957, 1507, 1109,  329,   7, -33, },
+	{  -6, 217,  944, 1505, 1121,  338,   9, -32, },
+	{  -6, 210,  931, 1503, 1133,  348,  10, -33, },
+	{  -7, 202,  917, 1500, 1144,  358,  12, -30, },
+	{  -7, 195,  904, 1497, 1156,  368,  13, -30, },
+	{  -8, 188,  891, 1494, 1167,  378,  15, -29, },
+	{  -9, 181,  877, 1491, 1179,  388,  17, -28, },
+	{  -9, 174,  864, 1487, 1190,  398,  19, -27, },
+	{  -9, 168,  851, 1483, 1201,  409,  21, -28, },
+	{ -10, 161,  837, 1479, 1212,  419,  23, -25, },
+	{ -10, 155,  824, 1475, 1223,  430,  25, -26, },
+	{ -11, 149,  811, 1470, 1233,  441,  27, -24, },
+	{ -11, 142,  798, 1465, 1244,  452,  29, -23, },
+	{ -12, 137,  784, 1460, 1254,  463,  32, -22, },
+	{ -12, 131,  771, 1455, 1264,  474,  34, -21, },
+	{ -12, 125,  758, 1449, 1275,  486,  37, -22, },
+	{ -13, 120,  745, 1444, 1284,  497,  40, -21, },
+	{ -13, 115,  732, 1438, 1294,  509,  42, -21, },
+	{ -13, 109,  719, 1432, 1304,  520,  45, -20, },
+	{ -14, 104,  706, 1425, 1313,  532,  48, -18, },
+	{ -14, 100,  693, 1418, 1322,  544,  52, -19, },
+	{ -14,  95,  680, 1412, 1332,  556,  55, -20, },
+	{ -15,  90,  667, 1404, 1340,  568,  58, -16, },
+	{ -15,  86,  655, 1397, 1349,  580,  62, -18, },
+	{ -16,  82,  642, 1390, 1358,  592,  66, -18, },
+	{ -16,  77,  630, 1382, 1366,  605,  69, -17, },
+	{ -16,  73,  617, 1374, 1374,  617,  73, -16, },
+	{ -17,  69,  605, 1366, 1382,  630,  77, -16, },
+	{ -17,  66,  592, 1358, 1390,  642,  82, -17, },
+	{ -18,  62,  580, 1349, 1397,  655,  86, -15, },
+	{ -18,  58,  568, 1340, 1404,  667,  90, -13, },
+	{ -18,  55,  556, 1332, 1412,  680,  95, -16, },
+	{ -19,  52,  544, 1322, 1418,  693, 100, -14, },
+	{ -19,  48,  532, 1313, 1425,  706, 104, -13, },
+	{ -20,  45,  520, 1304, 1432,  719, 109, -13, },
+	{ -20,  42,  509, 1294, 1438,  732, 115, -14, },
+	{ -21,  40,  497, 1284, 1444,  745, 120, -13, },
+	{ -22,  37,  486, 1275, 1449,  758, 125, -12, },
+	{ -22,  34,  474, 1264, 1455,  771, 131, -11, },
+	{ -23,  32,  463, 1254, 1460,  784, 137, -11, },
+	{ -23,  29,  452, 1244, 1465,  798, 142, -11, },
+	{ -24,  27,  441, 1233, 1470,  811, 149, -11, },
+	{ -25,  25,  430, 1223, 1475,  824, 155, -11, },
+	{ -26,  23,  419, 1212, 1479,  837, 161,  -9, },
+	{ -26,  21,  409, 1201, 1483,  851, 168, -11, },
+	{ -27,  19,  398, 1190, 1487,  864, 174,  -9, },
+	{ -28,  17,  388, 1179, 1491,  877, 181,  -9, },
+	{ -29,  15,  378, 1167, 1494,  891, 188,  -8, },
+	{ -29,  13,  368, 1156, 1497,  904, 195,  -8, },
+	{ -30,  12,  358, 1144, 1500,  917, 202,  -7, },
+	{ -31,  10,  348, 1133, 1503,  931, 210,  -8, },
+	{ -32,   9,  338, 1121, 1505,  944, 217,  -6, },
+	{ -33,   7,  329, 1109, 1507,  957, 225,  -5, },
+	{ -34,   6,  319, 1097, 1509,  970, 233,  -4, },
+	{ -35,   5,  310, 1085, 1510,  983, 241,  -3, },
+	{ -36,   3,  301, 1073, 1512,  997, 249,  -3, },
+	{ -37,   2,  292, 1060, 1513, 1010, 257,  -1, },
+	{ -38,   1,  283, 1048, 1514, 1023, 266,  -1, }
+};
+
+/* ScalingRatio = 4 */
+static const s16
+XV_fixedcoeff_taps8_SR4[XV_HSCALER_MAX_H_PHASES][XV_HSCALER_TAPS_8] = {
+	{ 49, 366, 977, 1312,  977, 366,  49,  0, },
+	{ 48, 357, 967, 1312,  986, 374,  51,  1, },
+	{ 46, 349, 958, 1311,  995, 382,  54,  1, },
+	{ 44, 342, 948, 1311, 1004, 390,  56,  1, },
+	{ 42, 334, 939, 1310, 1013, 399,  58,  1, },
+	{ 40, 326, 929, 1309, 1021, 407,  60,  4, },
+	{ 39, 318, 919, 1308, 1030, 415,  63,  4, },
+	{ 37, 311, 910, 1307, 1039, 424,  65,  3, },
+	{ 36, 303, 900, 1305, 1047, 433,  68,  4, },
+	{ 34, 296, 890, 1303, 1055, 442,  70,  6, },
+	{ 33, 289, 880, 1301, 1064, 450,  73,  6, },
+	{ 32, 282, 870, 1299, 1072, 459,  76,  6, },
+	{ 31, 275, 861, 1297, 1080, 468,  79,  5, },
+	{ 29, 268, 851, 1295, 1088, 477,  82,  6, },
+	{ 28, 261, 841, 1292, 1096, 486,  85,  7, },
+	{ 27, 254, 831, 1289, 1104, 496,  88,  7, },
+	{ 26, 248, 821, 1287, 1112, 505,  91,  6, },
+	{ 25, 241, 811, 1284, 1119, 514,  94,  8, },
+	{ 24, 235, 800, 1280, 1127, 523,  98,  9, },
+	{ 23, 228, 790, 1277, 1134, 533, 101, 10, },
+	{ 22, 222, 780, 1273, 1141, 542, 105, 11, },
+	{ 22, 216, 770, 1270, 1148, 552, 109,  9, },
+	{ 21, 210, 760, 1266, 1155, 561, 112, 11, },
+	{ 20, 204, 750, 1262, 1162, 571, 116, 11, },
+	{ 19, 198, 740, 1257, 1169, 581, 120, 12, },
+	{ 19, 193, 730, 1253, 1175, 590, 124, 12, },
+	{ 18, 187, 720, 1248, 1182, 600, 129, 12, },
+	{ 17, 182, 710, 1244, 1188, 610, 133, 12, },
+	{ 17, 176, 700, 1239, 1194, 620, 137, 13, },
+	{ 16, 171, 690, 1234, 1201, 630, 142, 12, },
+	{ 16, 166, 680, 1229, 1206, 640, 146, 13, },
+	{ 15, 161, 670, 1223, 1212, 650, 151, 14, },
+	{ 15, 156, 660, 1218, 1218, 660, 156, 13, },
+	{ 14, 151, 650, 1212, 1223, 670, 161, 15, },
+	{ 14, 146, 640, 1206, 1229, 680, 166, 15, },
+	{ 13, 142, 630, 1201, 1234, 690, 171, 15, },
+	{ 13, 137, 620, 1194, 1239, 700, 176, 17, },
+	{ 12, 133, 610, 1188, 1244, 710, 182, 17, },
+	{ 12, 129, 600, 1182, 1248, 720, 187, 18, },
+	{ 11, 124, 590, 1175, 1253, 730, 193, 20, },
+	{ 11, 120, 581, 1169, 1257, 740, 198, 20, },
+	{ 11, 116, 571, 1162, 1262, 750, 204, 20, },
+	{ 10, 112, 561, 1155, 1266, 760, 210, 22, },
+	{ 10, 109, 552, 1148, 1270, 770, 216, 21, },
+	{ 10, 105, 542, 1141, 1273, 780, 222, 23, },
+	{  9, 101, 533, 1134, 1277, 790, 228, 24, },
+	{  9,  98, 523, 1127, 1280, 800, 235, 24, },
+	{  8,  94, 514, 1119, 1284, 811, 241, 25, },
+	{  8,  91, 505, 1112, 1287, 821, 248, 24, },
+	{  8,  88, 496, 1104, 1289, 831, 254, 26, },
+	{  7,  85, 486, 1096, 1292, 841, 261, 28, },
+	{  7,  82, 477, 1088, 1295, 851, 268, 28, },
+	{  6,  79, 468, 1080, 1297, 861, 275, 30, },
+	{  6,  76, 459, 1072, 1299, 870, 282, 32, },
+	{  5,  73, 450, 1064, 1301, 880, 289, 34, },
+	{  5,  70, 442, 1055, 1303, 890, 296, 35, },
+	{  4,  68, 433, 1047, 1305, 900, 303, 36, },
+	{  4,  65, 424, 1039, 1307, 910, 311, 36, },
+	{  3,  63, 415, 1030, 1308, 919, 318, 40, },
+	{  3,  60, 407, 1021, 1309, 929, 326, 41, },
+	{  2,  58, 399, 1013, 1310, 939, 334, 41, },
+	{  2,  56, 390, 1004, 1311, 948, 342, 43, },
+	{  1,  54, 382,  995, 1311, 958, 349, 46, },
+	{  1,  51, 374,  986, 1312, 967, 357, 48, }
+};
+
+/* ScalingRatio = 3.0 */
+static const s16
+XV_fixedcoeff_taps10_SR3[XV_HSCALER_MAX_H_PHASES][XV_HSCALER_TAPS_10] = {
+	{ -31,   0, 359, 1033, 1399, 1033,  359,   0, -31, -25, },
+	{ -31,  -2, 350, 1022, 1398, 1043,  368,   3, -31, -24, },
+	{ -30,  -4, 341, 1012, 1398, 1053,  378,   5, -32, -25, },
+	{ -30,  -6, 333, 1002, 1398, 1062,  387,   8, -32, -26, },
+	{ -30,  -8, 324,  992, 1397, 1072,  396,  10, -32, -25, },
+	{ -30, -10, 315,  981, 1396, 1082,  406,  13, -33, -24, },
+	{ -29, -12, 307,  971, 1395, 1091,  415,  16, -33, -25, },
+	{ -29, -13, 298,  960, 1393, 1101,  425,  18, -33, -24, },
+	{ -29, -15, 290,  949, 1392, 1110,  434,  21, -34, -22, },
+	{ -28, -17, 282,  939, 1390, 1120,  444,  25, -34, -25, },
+	{ -28, -18, 274,  928, 1388, 1129,  454,  28, -34, -25, },
+	{ -28, -20, 266,  917, 1386, 1138,  464,  31, -34, -24, },
+	{ -27, -21, 258,  906, 1384, 1147,  474,  34, -35, -24, },
+	{ -27, -22, 250,  895, 1381, 1156,  484,  38, -35, -24, },
+	{ -27, -23, 242,  885, 1379, 1164,  494,  41, -35, -24, },
+	{ -27, -25, 235,  874, 1376, 1173,  504,  45, -35, -24, },
+	{ -26, -26, 227,  863, 1373, 1181,  515,  49, -36, -24, },
+	{ -26, -27, 220,  852, 1369, 1190,  525,  53, -36, -24, },
+	{ -26, -28, 213,  841, 1366, 1198,  535,  56, -36, -23, },
+	{ -26, -29, 206,  830, 1362, 1206,  546,  61, -36, -24, },
+	{ -25, -29, 199,  819, 1358, 1214,  556,  65, -36, -25, },
+	{ -25, -30, 192,  808, 1354, 1222,  567,  69, -36, -25, },
+	{ -25, -31, 185,  797, 1350, 1229,  577,  73, -36, -23, },
+	{ -25, -32, 178,  785, 1346, 1237,  588,  78, -36, -23, },
+	{ -25, -32, 172,  774, 1341, 1244,  599,  83, -36, -24, },
+	{ -25, -33, 165,  763, 1336, 1252,  610,  87, -36, -23, },
+	{ -24, -33, 159,  752, 1331, 1259,  620,  92, -36, -24, },
+	{ -24, -34, 153,  741, 1326, 1266,  631,  97, -36, -24, },
+	{ -24, -34, 147,  730, 1321, 1272,  642, 102, -36, -24, },
+	{ -24, -35, 141,  719, 1315, 1279,  653, 107, -36, -23, },
+	{ -24, -35, 135,  708, 1310, 1285,  664, 113, -36, -24, },
+	{ -24, -35, 129,  697, 1304, 1292,  675, 118, -36, -24, },
+	{ -24, -36, 124,  686, 1298, 1298,  686, 124, -36, -24, },
+	{ -24, -36, 118,  675, 1292, 1304,  697, 129, -35, -24, },
+	{ -24, -36, 113,  664, 1285, 1310,  708, 135, -35, -24, },
+	{ -24, -36, 107,  653, 1279, 1315,  719, 141, -35, -23, },
+	{ -24, -36, 102,  642, 1272, 1321,  730, 147, -34, -24, },
+	{ -23, -36,  97,  631, 1266, 1326,  741, 153, -34, -25, },
+	{ -23, -36,  92,  620, 1259, 1331,  752, 159, -33, -25, },
+	{ -23, -36,  87,  610, 1252, 1336,  763, 165, -33, -25, },
+	{ -23, -36,  83,  599, 1244, 1341,  774, 172, -32, -26, },
+	{ -23, -36,  78,  588, 1237, 1346,  785, 178, -32, -25, },
+	{ -23, -36,  73,  577, 1229, 1350,  797, 185, -31, -25, },
+	{ -23, -36,  69,  567, 1222, 1354,  808, 192, -30, -27, },
+	{ -23, -36,  65,  556, 1214, 1358,  819, 199, -29, -27, },
+	{ -24, -36,  61,  546, 1206, 1362,  830, 206, -29, -26, },
+	{ -24, -36,  56,  535, 1198, 1366,  841, 213, -28, -25, },
+	{ -24, -36,  53,  525, 1190, 1369,  852, 220, -27, -26, },
+	{ -24, -36,  49,  515, 1181, 1373,  863, 227, -26, -26, },
+	{ -24, -35,  45,  504, 1173, 1376,  874, 235, -25, -27, },
+	{ -24, -35,  41,  494, 1164, 1379,  885, 242, -23, -27, },
+	{ -24, -35,  38,  484, 1156, 1381,  895, 250, -22, -27, },
+	{ -24, -35,  34,  474, 1147, 1384,  906, 258, -21, -27, },
+	{ -24, -34,  31,  464, 1138, 1386,  917, 266, -20, -28, },
+	{ -24, -34,  28,  454, 1129, 1388,  928, 274, -18, -29, },
+	{ -24, -34,  25,  444, 1120, 1390,  939, 282, -17, -29, },
+	{ -24, -34,  21,  434, 1110, 1392,  949, 290, -15, -27, },
+	{ -24, -33,  18,  425, 1101, 1393,  960, 298, -13, -29, },
+	{ -24, -33,  16,  415, 1091, 1395,  971, 307, -12, -30, },
+	{ -25, -33,  13,  406, 1082, 1396,  981, 315, -10, -29, },
+	{ -25, -32,  10,  396, 1072, 1397,  992, 324,  -8, -30, },
+	{ -25, -32,   8,  387, 1062, 1398, 1002, 333,  -6, -31, },
+	{ -25, -32,   5,  378, 1053, 1398, 1012, 341,  -4, -30, },
+	{ -25, -31,   3,  368, 1043, 1398, 1022, 350,  -2, -30, }
+};
+
+/* ScalingRatio = 4 */
+static const s16
+XV_fixedcoeff_taps10_SR4[XV_HSCALER_MAX_H_PHASES][XV_HSCALER_TAPS_10] = {
+	{   0, 107, 454, 924, 1150,  924, 454, 107,   0, -24, },
+	{   0, 104, 446, 917, 1149,  930, 461, 110,   0, -21, },
+	{  -1, 100, 439, 910, 1149,  936, 468, 114,   1, -20, },
+	{  -1,  97, 432, 904, 1149,  942, 475, 117,   2, -21, },
+	{  -2,  94, 425, 897, 1148,  948, 482, 121,   2, -19, },
+	{  -2,  91, 418, 890, 1147,  954, 490, 125,   3, -20, },
+	{  -3,  88, 411, 883, 1147,  960, 497, 128,   3, -18, },
+	{  -3,  85, 404, 876, 1146,  966, 504, 132,   4, -18, },
+	{  -3,  82, 397, 869, 1145,  972, 512, 136,   5, -19, },
+	{  -4,  79, 390, 862, 1144,  978, 519, 140,   5, -17, },
+	{  -4,  76, 384, 855, 1142,  983, 526, 144,   6, -16, },
+	{  -4,  74, 377, 848, 1141,  989, 534, 148,   7, -18, },
+	{  -5,  71, 370, 841, 1139,  995, 541, 152,   7, -15, },
+	{  -5,  68, 364, 834, 1138, 1000, 549, 156,   8, -16, },
+	{  -5,  66, 357, 827, 1136, 1005, 556, 160,   9, -15, },
+	{  -6,  63, 350, 820, 1134, 1011, 564, 165,  10, -15, },
+	{  -6,  61, 344, 812, 1132, 1016, 571, 169,  11, -14, },
+	{  -6,  59, 338, 805, 1130, 1021, 579, 174,  12, -16, },
+	{  -6,  56, 331, 798, 1128, 1026, 586, 178,  13, -14, },
+	{  -7,  54, 325, 790, 1126, 1031, 594, 183,  14, -14, },
+	{  -7,  52, 319, 783, 1124, 1036, 601, 187,  15, -14, },
+	{  -7,  50, 312, 776, 1121, 1041, 609, 192,  16, -14, },
+	{  -7,  48, 306, 768, 1119, 1045, 617, 197,  17, -14, },
+	{  -8,  46, 300, 761, 1116, 1050, 624, 202,  18, -13, },
+	{  -8,  44, 294, 753, 1113, 1054, 632, 207,  19, -12, },
+	{  -8,  42, 288, 746, 1110, 1059, 639, 212,  20, -12, },
+	{  -8,  40, 282, 738, 1107, 1063, 647, 217,  22, -12, },
+	{  -9,  38, 277, 731, 1104, 1067, 655, 222,  23, -12, },
+	{  -9,  36, 271, 723, 1101, 1071, 662, 227,  24, -10, },
+	{  -9,  35, 265, 715, 1097, 1075, 670, 232,  26, -10, },
+	{  -9,  33, 259, 708, 1094, 1079, 677, 238,  27, -10, },
+	{ -10,  32, 254, 700, 1091, 1083, 685, 243,  28, -10, },
+	{ -10,  30, 248, 693, 1087, 1087, 693, 248,  30, -10, },
+	{ -10,  28, 243, 685, 1083, 1091, 700, 254,  32, -10, },
+	{ -10,  27, 238, 677, 1079, 1094, 708, 259,  33,  -9, },
+	{ -11,  26, 232, 670, 1075, 1097, 715, 265,  35,  -8, },
+	{ -11,  24, 227, 662, 1071, 1101, 723, 271,  36,  -8, },
+	{ -11,  23, 222, 655, 1067, 1104, 731, 277,  38, -10, },
+	{ -12,  22, 217, 647, 1063, 1107, 738, 282,  40,  -8, },
+	{ -12,  20, 212, 639, 1059, 1110, 746, 288,  42,  -8, },
+	{ -12,  19, 207, 632, 1054, 1113, 753, 294,  44,  -8, },
+	{ -12,  18, 202, 624, 1050, 1116, 761, 300,  46,  -9, },
+	{ -13,  17, 197, 617, 1045, 1119, 768, 306,  48,  -8, },
+	{ -13,  16, 192, 609, 1041, 1121, 776, 312,  50,  -8, },
+	{ -13,  15, 187, 601, 1036, 1124, 783, 319,  52,  -8, },
+	{ -14,  14, 183, 594, 1031, 1126, 790, 325,  54,  -7, },
+	{ -14,  13, 178, 586, 1026, 1128, 798, 331,  56,  -6, },
+	{ -14,  12, 174, 579, 1021, 1130, 805, 338,  59,  -8, },
+	{ -15,  11, 169, 571, 1016, 1132, 812, 344,  61,  -5, },
+	{ -15,  10, 165, 564, 1011, 1134, 820, 350,  63,  -6, },
+	{ -16,   9, 160, 556, 1005, 1136, 827, 357,  66,  -4, },
+	{ -16,   8, 156, 549, 1000, 1138, 834, 364,  68,  -5, },
+	{ -16,   7, 152, 541,  995, 1139, 841, 370,  71,  -4, },
+	{ -17,   7, 148, 534,  989, 1141, 848, 377,  74,  -5, },
+	{ -17,   6, 144, 526,  983, 1142, 855, 384,  76,  -3, },
+	{ -18,   5, 140, 519,  978, 1144, 862, 390,  79,  -3, },
+	{ -18,   5, 136, 512,  972, 1145, 869, 397,  82,  -4, },
+	{ -19,   4, 132, 504,  966, 1146, 876, 404,  85,  -2, },
+	{ -19,   3, 128, 497,  960, 1147, 883, 411,  88,  -2, },
+	{ -20,   3, 125, 490,  954, 1147, 890, 418,  91,  -2, },
+	{ -20,   2, 121, 482,  948, 1148, 897, 425,  94,  -1, },
+	{ -21,   2, 117, 475,  942, 1149, 904, 432,  97,  -1, },
+	{ -21,   1, 114, 468,  936, 1149, 910, 439, 100,   0, },
+	{ -22,   0, 110, 461,  930, 1149, 917, 446, 104,   1, }
+};
+
+/* ScalingRatio = 4 */
+static const s16
+XV_fixedcoeff_taps12_SR4[XV_HSCALER_MAX_H_PHASES][XV_HSCALER_TAPS_12] = {
+	{ -19,   0, 152, 498, 893, 1070,  893, 498, 152,   0, -19, -22, },
+	{ -19,  -1, 147, 487, 879, 1059,  889, 499, 155,   1, -19,  19, },
+	{ -19,  -2, 143, 480, 874, 1059,  894, 506, 159,   2, -19,  19, },
+	{ -19,  -3, 139, 474, 869, 1059,  899, 512, 163,   3, -19,  19, },
+	{ -19,  -4, 136, 468, 863, 1059,  904, 519, 167,   4, -19,  18, },
+	{ -19,  -5, 132, 461, 858, 1058,  909, 525, 171,   5, -19,  20, },
+	{ -19,  -5, 128, 455, 853, 1058,  913, 531, 175,   7, -19,  19, },
+	{ -18,  -6, 125, 449, 847, 1057,  918, 538, 180,   8, -19,  17, },
+	{ -18,  -7, 121, 443, 842, 1056,  923, 544, 184,   9, -19,  18, },
+	{ -18,  -8, 118, 436, 836, 1056,  927, 551, 188,  10, -19,  19, },
+	{ -18,  -8, 114, 430, 831, 1055,  932, 557, 193,  12, -19,  17, },
+	{ -18,  -9, 111, 424, 825, 1054,  936, 564, 197,  13, -19,  18, },
+	{ -18, -10, 107, 418, 819, 1053,  941, 570, 202,  14, -19,  19, },
+	{ -18, -10, 104, 412, 814, 1052,  945, 577, 206,  16, -19,  17, },
+	{ -18, -11, 101, 406, 808, 1050,  949, 583, 211,  17, -19,  19, },
+	{ -18, -11,  98, 400, 802, 1049,  954, 590, 216,  19, -19,  16, },
+	{ -18, -12,  95, 394, 796, 1048,  958, 596, 220,  20, -19,  18, },
+	{ -18, -12,  92, 388, 791, 1046,  962, 603, 225,  22, -19,  16, },
+	{ -18, -13,  89, 382, 785, 1045,  966, 609, 230,  24, -19,  16, },
+	{ -18, -13,  86, 376, 779, 1043,  970, 616, 235,  25, -19,  16, },
+	{ -18, -14,  83, 370, 773, 1041,  973, 622, 240,  27, -19,  18, },
+	{ -18, -14,  80, 364, 767, 1039,  977, 629, 244,  29, -19,  18, },
+	{ -18, -15,  77, 358, 761, 1037,  981, 635, 249,  31, -19,  19, },
+	{ -18, -15,  74, 352, 755, 1035,  984, 642, 255,  33, -19,  18, },
+	{ -18, -15,  71, 347, 749, 1033,  988, 648, 260,  35, -19,  17, },
+	{ -18, -16,  69, 341, 743, 1031,  991, 654, 265,  36, -19,  19, },
+	{ -18, -16,  66, 335, 736, 1029,  995, 661, 270,  38, -19,  19, },
+	{ -18, -16,  64, 330, 730, 1026,  998, 667, 275,  41, -18,  17, },
+	{ -18, -17,  61, 324, 724, 1024, 1001, 674, 280,  43, -18,  18, },
+	{ -18, -17,  59, 318, 718, 1021, 1004, 680, 286,  45, -18,  18, },
+	{ -18, -17,  56, 313, 712, 1019, 1007, 686, 291,  47, -18,  18, },
+	{ -18, -17,  54, 307, 705, 1016, 1010, 693, 296,  49, -18,  19, },
+	{ -18, -18,  51, 302, 699, 1013, 1013, 699, 302,  51, -18,  20, },
+	{ -18, -18,  49, 296, 693, 1010, 1016, 705, 307,  54, -17,  19, },
+	{ -18, -18,  47, 291, 686, 1007, 1019, 712, 313,  56, -17,  18, },
+	{ -18, -18,  45, 286, 680, 1004, 1021, 718, 318,  59, -17,  18, },
+	{ -18, -18,  43, 280, 674, 1001, 1024, 724, 324,  61, -17,  18, },
+	{ -18, -18,  41, 275, 667,  998, 1026, 730, 330,  64, -16,  17, },
+	{ -18, -19,  38, 270, 661,  995, 1029, 736, 335,  66, -16,  19, },
+	{ -19, -19,  36, 265, 654,  991, 1031, 743, 341,  69, -16,  20, },
+	{ -19, -19,  35, 260, 648,  988, 1033, 749, 347,  71, -15,  18, },
+	{ -19, -19,  33, 255, 642,  984, 1035, 755, 352,  74, -15,  19, },
+	{ -19, -19,  31, 249, 635,  981, 1037, 761, 358,  77, -15,  20, },
+	{ -19, -19,  29, 244, 629,  977, 1039, 767, 364,  80, -14,  19, },
+	{ -19, -19,  27, 240, 622,  973, 1041, 773, 370,  83, -14,  19, },
+	{ -19, -19,  25, 235, 616,  970, 1043, 779, 376,  86, -13,  17, },
+	{ -19, -19,  24, 230, 609,  966, 1045, 785, 382,  89, -13,  17, },
+	{ -19, -19,  22, 225, 603,  962, 1046, 791, 388,  92, -12,  17, },
+	{ -19, -19,  20, 220, 596,  958, 1048, 796, 394,  95, -12,  19, },
+	{ -20, -19,  19, 216, 590,  954, 1049, 802, 400,  98, -11,  18, },
+	{ -20, -19,  17, 211, 583,  949, 1050, 808, 406, 101, -11,  21, },
+	{ -20, -19,  16, 206, 577,  945, 1052, 814, 412, 104, -10,  19, },
+	{ -20, -19,  14, 202, 570,  941, 1053, 819, 418, 107, -10,  21, },
+	{ -20, -19,  13, 197, 564,  936, 1054, 825, 424, 111,  -9,  20, },
+	{ -20, -19,  12, 193, 557,  932, 1055, 831, 430, 114,  -8,  19, },
+	{ -21, -19,  10, 188, 551,  927, 1056, 836, 436, 118,  -8,  22, },
+	{ -21, -19,   9, 184, 544,  923, 1056, 842, 443, 121,  -7,  21, },
+	{ -21, -19,   8, 180, 538,  918, 1057, 847, 449, 125,  -6,  20, },
+	{ -21, -19,   7, 175, 531,  913, 1058, 853, 455, 128,  -5,  21, },
+	{ -21, -19,   5, 171, 525,  909, 1058, 858, 461, 132,  -5,  22, },
+	{ -21, -19,   4, 167, 519,  904, 1059, 863, 468, 136,  -4,  20, },
+	{ -22, -19,   3, 163, 512,  899, 1059, 869, 474, 139,  -3,  22, },
+	{ -22, -19,   2, 159, 506,  894, 1059, 874, 480, 143,  -2,  22, },
+	{ -22, -19,   1, 155, 499,  889, 1059, 879, 487, 147,  -1,  22, }
+};
+
+enum xilinx_scaler_vid_reg_fmts {
+	XVIDC_CSF_RGB = 0,
+	XVIDC_CSF_YCRCB_444,
+	XVIDC_CSF_YCRCB_422,
+	XVIDC_CSF_YCRCB_420,
+};
+
+static const u32 xilinx_scaler_video_fmts[] = {
+	MEDIA_BUS_FMT_RGB888_1X24,
+	MEDIA_BUS_FMT_VUY8_1X24,
+	MEDIA_BUS_FMT_UYVY8_1X16,
+	MEDIA_BUS_FMT_VYYUYY8_1X24,
+};
+
+/* This bit is for xscaler feature flag */
+#define XSCALER_HPHASE_FIX	BIT(0)
+
+/**
+ * struct xscaler_feature - dt or IP property structure
+ * @flags: Bitmask of properties enabled in IP or dt
+ */
+struct xscaler_feature {
+	u32 flags;
+};
+
+/**
+ * struct xilinx_scaler - Core configuration of scaler device structure
+ * @base: pointer to register base address
+ * @dev: device structure
+ * @bridge: xilinx bridge
+ * @width_in: input width
+ * @height_in: input height
+ * @width_out: output width
+ * @height_out: output height
+ * @fmt_in: input format
+ * @fmt_out: output format
+ * @num_hori_taps: number of horizontal taps
+ * @num_vert_taps: number of vertical taps
+ * @max_num_phases: maximum number of phases
+ * @pix_per_clk: Pixels per Clock cycle the IP operates upon
+ * @max_pixels: The maximum number of pixels that the H-scaler examines
+ * @max_lines: The maximum number of lines that the V-scaler examines
+ * @H_phases: The phases needed to program the H-scaler for different taps
+ * @hscaler_coeff: The complete array of H-scaler coefficients
+ * @vscaler_coeff: The complete array of V-scaler coefficients
+ * @is_polyphase: Track if scaling algorithm is polyphase or not
+ * @rst_gpio: GPIO reset line to bring VPSS Scaler out of reset
+ * @ctrl_clk: AXI Lite clock
+ * @axis_clk: Video Clock
+ * @cfg: Pointer to scaler config structure
+ */
+struct xilinx_scaler {
+	void __iomem *base;
+	struct device *dev;
+	struct xlnx_bridge bridge;
+	u32 width_in;
+	u32 height_in;
+	u32 width_out;
+	u32 height_out;
+	u32 fmt_in;
+	u32 fmt_out;
+	u32 num_hori_taps;
+	u32 num_vert_taps;
+	u32 max_num_phases;
+	u32 pix_per_clk;
+	u32 max_pixels;
+	u32 max_lines;
+	u32 H_phases[XV_HSCALER_MAX_LINE_WIDTH];
+	short hscaler_coeff[XV_HSCALER_MAX_H_PHASES][XV_HSCALER_MAX_H_TAPS];
+	short vscaler_coeff[XV_VSCALER_MAX_V_PHASES][XV_VSCALER_MAX_V_TAPS];
+	bool is_polyphase;
+	struct gpio_desc *rst_gpio;
+	struct clk *ctrl_clk;
+	struct clk *axis_clk;
+	const struct xscaler_feature *cfg;
+};
+
+static inline void xilinx_scaler_write(void __iomem *base, u32 offset, u32 val)
+{
+	writel(val, base + offset);
+}
+
+static inline u32 xilinx_scaler_read(void __iomem *base, u32 offset)
+{
+	return readl(base + offset);
+}
+
+static inline void xilinx_scaler_clr(void __iomem *base, u32 offset, u32 clr)
+{
+	xilinx_scaler_write(base, offset,
+			    xilinx_scaler_read(base, offset) & ~clr);
+}
+
+static inline void xilinx_scaler_set(void __iomem *base, u32 offset, u32 set)
+{
+	xilinx_scaler_write(base, offset,
+			    xilinx_scaler_read(base, offset) | set);
+}
+
+static inline void
+xilinx_scaler_disable_block(struct xilinx_scaler *scaler, u32 channel,
+			    u32 ip_block)
+{
+	xilinx_scaler_clr(scaler->base, ((channel - 1) * XGPIO_CHAN_OFFSET) +
+			  XGPIO_DATA_OFFSET + S_AXIS_RESET_OFF, ip_block);
+}
+
+static inline void
+xilinx_scaler_enable_block(struct xilinx_scaler *scaler, u32 channel,
+			   u32 ip_block)
+{
+	xilinx_scaler_set(scaler->base, ((channel - 1) * XGPIO_CHAN_OFFSET) +
+			  XGPIO_DATA_OFFSET + S_AXIS_RESET_OFF, ip_block);
+}
+
+/**
+ * bridge_to_layer - Gets the parent structure
+ * @bridge: pointer to the member.
+ *
+ * Return: parent structure pointer
+ */
+static inline struct xilinx_scaler *bridge_to_layer(struct xlnx_bridge *bridge)
+{
+	return container_of(bridge, struct xilinx_scaler, bridge);
+}
+
+/**
+ * xilinx_scaler_reset - Resets scaler block
+ * @scaler: Pointer to scaler device structure
+ *
+ * This function resets scaler block
+ */
+static void xilinx_scaler_reset(struct xilinx_scaler *scaler)
+{
+	xilinx_scaler_disable_block(scaler, XGPIO_CH_RESET_SEL,
+				    XGPIO_RESET_MASK_ALL_BLOCKS);
+	xilinx_scaler_enable_block(scaler, XGPIO_CH_RESET_SEL,
+				   XGPIO_RESET_MASK_IP_AXIS);
+}
+
+/**
+ * xv_hscaler_calculate_phases - Calculates h-scaler phases
+ * @scaler: Pointer to scaler registers base
+ * @width_in: input width
+ * @width_out: output width
+ * @pixel_rate: pixel rate
+ */
+static void
+xv_hscaler_calculate_phases(struct xilinx_scaler *scaler,
+			    u32 width_in, u32 width_out, u32 pixel_rate)
+{
+	unsigned int loop_width;
+	unsigned int x, s;
+	int offset = 0;
+	int xwrite_pos = 0;
+	bool output_write_en;
+	bool get_new_pix;
+	u64 phaseH;
+	u32 array_idx = 0;
+	int nr_rds;
+	int nr_rds_clck;
+	unsigned int nphases = scaler->max_num_phases;
+	unsigned int nppc = scaler->pix_per_clk;
+	unsigned int shift = XHSC_STEP_PRECISION_SHIFT - ilog2(nphases);
+
+	loop_width = max_t(u32, width_in, width_out);
+	loop_width = ALIGN(loop_width + nppc - 1, nppc);
+
+	for (x = 0; x < loop_width; x++) {
+		nr_rds_clck = 0;
+		for (s = 0; s < nppc; s++) {
+			phaseH = (offset >> shift) & (nphases - 1);
+			get_new_pix = false;
+			output_write_en = false;
+			if ((offset >> XHSC_STEP_PRECISION_SHIFT) != 0) {
+				get_new_pix = true;
+				offset -= (1 << XHSC_STEP_PRECISION_SHIFT);
+				array_idx++;
+			}
+
+			if (((offset >> XHSC_STEP_PRECISION_SHIFT) == 0) &&
+			    xwrite_pos < width_out) {
+				offset += pixel_rate;
+				output_write_en = true;
+				xwrite_pos++;
+			}
+
+			scaler->H_phases[x] |= (phaseH <<
+						(s * XHSC_HPHASE_MULTIPLIER));
+			scaler->H_phases[x] |= (array_idx <<
+						(XHSC_HPHASE_SHIFT_BY_6 +
+						(s * XHSC_HPHASE_MULTIPLIER)));
+			if (output_write_en) {
+				scaler->H_phases[x] |=
+				(XV_HSCALER_PHASESH_V_OUTPUT_WR_EN <<
+				(s * XHSC_HPHASE_MULTIPLIER));
+			}
+
+			if (get_new_pix)
+				nr_rds_clck++;
+		}
+		if (array_idx >= nppc)
+			array_idx &= (nppc - 1);
+
+		nr_rds += nr_rds_clck;
+		if (nr_rds >= nppc)
+			nr_rds -= nppc;
+	}
+}
+
+/**
+ * xv_hscaler_load_ext_coeff - Loads external coefficients of h-scaler
+ * @scaler: Pointer to scaler registers base
+ * @coeff: Pointer to coeff array
+ * @ntaps: number of taps
+ *
+ * This function loads h-scaler coefficients.
+ */
+static void
+xv_hscaler_load_ext_coeff(struct xilinx_scaler *scaler,
+			  const short *coeff, u32 ntaps)
+{
+	unsigned int i, j, pad, offset;
+	u32 nphases = scaler->max_num_phases;
+
+	/* Determine if coefficient needs padding (effective vs. max taps) */
+	pad = XV_HSCALER_MAX_H_TAPS - ntaps;
+	offset = pad >> 1;
+	/* Load coefficients into scaler coefficient table */
+	for (i = 0; i < nphases; i++) {
+		for (j = 0; j < ntaps; ++j)
+			scaler->hscaler_coeff[i][j + offset] =
+						coeff[i * ntaps + j];
+	}
+
+	if (pad) {
+		for (i = 0; i < nphases; i++) {
+			for (j = 0; j < offset; j++)
+				scaler->hscaler_coeff[i][j] = 0;
+			j = ntaps + offset;
+			for (; j < XV_HSCALER_MAX_H_TAPS; j++)
+				scaler->hscaler_coeff[i][j] = 0;
+		}
+	}
+}
+
+static const short *xv_select_coeff(struct xilinx_scaler *scaler,
+				    u32 in, u32 out, u32 *ntaps)
+{
+	const short *coeff = NULL;
+
+	/*
+	 * Scale Down Mode will use dynamic filter selection logic
+	 * Scale Up Mode (including 1:1) will always use 6 tap filter
+	 */
+	if (out < in) {
+		u16 scale_ratio = (in * 10) / out;
+
+		/* Since XV_HSCALER_TAPS_* is same as XV_VSCALER_TAPS_* */
+		switch (*ntaps) {
+		case XV_HSCALER_TAPS_6:
+			*ntaps = XV_HSCALER_TAPS_6;
+			if (scale_ratio > 35)
+				coeff = &XV_fixedcoeff_taps6_SR4[0][0];
+			else if (scale_ratio > 25)
+				coeff = &XV_fixedcoeff_taps6_SR3[0][0];
+			else if (scale_ratio > 15)
+				coeff = &XV_fixedcoeff_taps6_SR2[0][0];
+			else
+				coeff = &XV_fixedcoeff_taps6_SR1p2[0][0];
+			break;
+		case XV_HSCALER_TAPS_8:
+			if (scale_ratio > 35) {
+				coeff = &XV_fixedcoeff_taps8_SR4[0][0];
+				*ntaps = XV_HSCALER_TAPS_8;
+			} else if (scale_ratio > 25) {
+				coeff = &XV_fixedcoeff_taps8_SR3[0][0];
+				*ntaps = XV_HSCALER_TAPS_8;
+			} else if (scale_ratio > 15) {
+				coeff = &XV_fixedcoeff_taps8_SR2[0][0];
+				*ntaps = XV_HSCALER_TAPS_8;
+			} else {
+				coeff = &XV_fixedcoeff_taps6_SR1p2[0][0];
+				*ntaps = XV_HSCALER_TAPS_6;
+			}
+			break;
+		case XV_HSCALER_TAPS_10:
+			if (scale_ratio > 35) {
+				coeff = &XV_fixedcoeff_taps10_SR4[0][0];
+				*ntaps = XV_HSCALER_TAPS_10;
+			} else if (scale_ratio > 25) {
+				coeff = &XV_fixedcoeff_taps10_SR3[0][0];
+				*ntaps = XV_HSCALER_TAPS_10;
+			} else if (scale_ratio > 15) {
+				coeff = &XV_fixedcoeff_taps8_SR2[0][0];
+				*ntaps = XV_HSCALER_TAPS_8;
+			} else {
+				coeff = &XV_fixedcoeff_taps6_SR1p2[0][0];
+				*ntaps = XV_HSCALER_TAPS_6;
+			}
+			break;
+		case XV_HSCALER_TAPS_12:
+			if (scale_ratio > 35) {
+				coeff = &XV_fixedcoeff_taps12_SR4[0][0];
+				*ntaps = XV_HSCALER_TAPS_12;
+			} else if (scale_ratio > 25) {
+				coeff = &XV_fixedcoeff_taps10_SR3[0][0];
+				*ntaps = XV_HSCALER_TAPS_10;
+			} else if (scale_ratio > 15) {
+				coeff = &XV_fixedcoeff_taps8_SR2[0][0];
+				*ntaps = XV_HSCALER_TAPS_8;
+			} else {
+				coeff = &XV_fixedcoeff_taps6_SR1p2[0][0];
+				*ntaps = XV_HSCALER_TAPS_6;
+			}
+			break;
+		default:
+			dev_err(scaler->dev,
+				"Unsupported number of taps = %d",
+				*ntaps);
+		}
+	} else {
+		dev_dbg(scaler->dev, "scaler : scale up 6 tap");
+		coeff = &XV_lanczos2_taps6[0][0];
+		*ntaps = XV_HSCALER_TAPS_6;
+	}
+
+	return coeff;
+}
+
+/**
+ * xv_hscaler_coeff_select - Selection of H-Scaler coefficients of operation
+ * @scaler: Pointer to Scaler device structure
+ * @width_in: Width of input video
+ * @width_out: Width of desired output video
+ *
+ * There are instances when a N-tap filter might operate in an M-tap
+ * configuration where N > M.
+ *
+ * For example :
+ * Depending on the ratio of scaling (while downscaling), a 12-tap
+ * filter may operate with 10 tap coefficients and zero-pads the remaining
+ * coefficients.
+ *
+ * While upscaling the driver will program 6-tap filter coefficients
+ * in any N-tap configurations (for N >= 6).
+ *
+ * This selection is adopted by the as it gives optimal
+ * video output determined by repeated testing of the IP
+ *
+ * Return: Will return 0 if successful. Returns -EINVAL on an unsupported
+ * H-scaler number of taps.
+ */
+static int
+xv_hscaler_select_coeff(struct xilinx_scaler *scaler,
+			u32 width_in, u32 width_out)
+{
+	const short *coeff;
+	u32 ntaps = scaler->num_hori_taps;
+
+	coeff = xv_select_coeff(scaler, width_in, width_out, &ntaps);
+	if (!coeff)
+		return -EINVAL;
+
+	xv_hscaler_load_ext_coeff(scaler, coeff, ntaps);
+	return 0;
+}
+
+/**
+ * xv_hscaler_set_coeff - Sets h-scaler coefficients
+ * @scaler: Pointer to scaler device structure
+ *
+ * This function sets coefficients of h-scaler.
+ */
+static void xv_hscaler_set_coeff(struct xilinx_scaler *scaler)
+{
+	int val, i, j, offset, rd_indx;
+	u32 ntaps = scaler->num_hori_taps;
+	u32 nphases = scaler->max_num_phases;
+	u32 base_addr;
+
+	offset = (XV_HSCALER_MAX_H_TAPS - ntaps) / 2;
+	base_addr = V_HSCALER_OFF + XV_HSCALER_CTRL_ADDR_HWREG_HFLTCOEFF_BASE;
+	for (i = 0; i < nphases; i++) {
+		for (j = 0; j < ntaps / 2; j++) {
+			rd_indx = j * 2 + offset;
+			val = (scaler->hscaler_coeff[i][rd_indx + 1] <<
+			       XSCALER_BITSHIFT_16) |
+			       (scaler->hscaler_coeff[i][rd_indx] &
+			       XHSC_MASK_LOW_16BITS);
+			xilinx_scaler_write(scaler->base, base_addr +
+				((i * ntaps / 2 + j) * 4), val);
+		}
+	}
+}
+
+/**
+ * xv_vscaler_load_ext_coeff - Loads external coefficients of v-scaler
+ * @scaler: Pointer to scaler device structure
+ * @coeff: Pointer to coeff array
+ * @ntaps: number of taps
+ *
+ * This function loads v-scaler coefficients.
+ */
+static void
+xv_vscaler_load_ext_coeff(struct xilinx_scaler *scaler,
+			  const short *coeff, u32 ntaps)
+{
+	int i, j, pad, offset;
+	u32 nphases = scaler->max_num_phases;
+
+	/* Determine if coefficient needs padding (effective vs. max taps) */
+	pad = XV_VSCALER_MAX_V_TAPS - ntaps;
+	offset = pad ? (pad >> 1) : 0;
+	/* Load User defined coefficients into scaler coefficient table */
+	for (i = 0; i < nphases; i++) {
+		for (j = 0; j < ntaps; ++j)
+			scaler->vscaler_coeff[i][j + offset] =
+						coeff[i * ntaps + j];
+	}
+	if (pad) {
+		/* effective taps < max_taps */
+		for (i = 0; i < nphases; i++) {
+			/* pad left */
+			for (j = 0; j < offset; j++)
+				scaler->vscaler_coeff[i][j] = 0;
+			/* pad right */
+			j = ntaps + offset;
+			for (; j < XV_VSCALER_MAX_V_TAPS; j++)
+				scaler->vscaler_coeff[i][j] = 0;
+		}
+	}
+}
+
+/**
+ * xv_vscaler_set_coeff - Sets v-scaler coefficients
+ * @scaler: Pointer to scaler device structure
+ *
+ * This function sets coefficients of v-scaler.
+ */
+static void xv_vscaler_set_coeff(struct xilinx_scaler *scaler)
+{
+	u32 nphases = scaler->max_num_phases;
+	u32 ntaps = scaler->num_vert_taps;
+	int val, i, j, offset, rd_indx;
+	u32 base_addr;
+
+	offset = (XV_VSCALER_MAX_V_TAPS - ntaps) / 2;
+	base_addr = V_VSCALER_OFF + XV_VSCALER_CTRL_ADDR_HWREG_VFLTCOEFF_BASE;
+
+	for (i = 0; i < nphases; i++) {
+		for (j = 0; j < ntaps / 2; j++) {
+			rd_indx = j * 2 + offset;
+			val = (scaler->vscaler_coeff[i][rd_indx + 1] <<
+			       XSCALER_BITSHIFT_16) |
+			       (scaler->vscaler_coeff[i][rd_indx] &
+			       XVSC_MASK_LOW_16BITS);
+			xilinx_scaler_write(scaler->base, base_addr +
+				((i * ntaps / 2 + j) * 4), val);
+		}
+	}
+}
+
+/**
+ * xv_vscaler_coeff_select - Selection of V-Scaler coefficients of operation
+ * @scaler: Pointer to Scaler device structure
+ * @height_in: Height of input video
+ * @height_out: Height of desired output video
+ *
+ * There are instances when a N-tap filter might operate in an M-tap
+ * configuration where N > M.
+ *
+ * For example :
+ * Depending on the ratio of scaling (while downscaling), a 10-tap
+ * filter may operate with 6 tap coefficients and zero-pads the remaining
+ * coefficients.
+ *
+ * While upscaling the driver will program 6-tap filter coefficients
+ * in any N-tap configurations (for N >= 6).
+ *
+ * This selection is adopted by the as it gives optimal
+ * video output determined by repeated testing of the IP
+ *
+ * Return: Will return 0 if successful. Returns -EINVAL on an unsupported
+ * V-scaler number of taps.
+ */
+static int
+xv_vscaler_select_coeff(struct xilinx_scaler *scaler,
+			u32 height_in, u32 height_out)
+{
+	const short *coeff;
+	u32 ntaps = scaler->num_vert_taps;
+
+	coeff = xv_select_coeff(scaler, height_in, height_out, &ntaps);
+	if (!coeff)
+		return -EINVAL;
+
+	xv_vscaler_load_ext_coeff(scaler, coeff, ntaps);
+	return 0;
+}
+
+/**
+ * xv_hscaler_set_phases - Sets phases of h-scaler
+ * @scaler: Pointer to scaler device structure
+ *
+ * This function sets phases of h-scaler.
+ */
+static void
+xv_hscaler_set_phases(struct xilinx_scaler *scaler)
+{
+	u32 loop_width;
+	u32 index, val;
+	u32 offset, i, lsb, msb;
+
+	loop_width = scaler->max_pixels / scaler->pix_per_clk;
+	if (scaler->cfg->flags & XSCALER_HPHASE_FIX) {
+		offset = V_HSCALER_OFF +
+			XV_HSCALER_CTRL_ADDR_HWREG_PHASEH_FIX;
+	} else {
+		offset = V_HSCALER_OFF +
+			XV_HSCALER_CTRL_ADDR_HWREG_PHASESH_V_BASE;
+	}
+
+	switch (scaler->pix_per_clk) {
+	case XSCALER_PPC_1:
+		index = 0;
+		for (i = 0; i < loop_width; i += 2) {
+			lsb = scaler->H_phases[i] & XHSC_MASK_LOW_16BITS;
+			msb = scaler->H_phases[i + 1] & XHSC_MASK_LOW_16BITS;
+			val = (msb << 16 | lsb);
+			xilinx_scaler_write(scaler->base, offset +
+				(index * 4), val);
+			++index;
+		}
+		return;
+	case XSCALER_PPC_2:
+		for (i = 0; i < loop_width; i++) {
+			val = (scaler->H_phases[i] & XHSC_MASK_LOW_32BITS);
+			xilinx_scaler_write(scaler->base, offset +
+				(i * 4), val);
+		}
+		return;
+	}
+}
+
+/**
+ * xv_vscaler_setup_video_fmt - Sets video format of v-scaler
+ * @scaler: Pointer to scaler device structure
+ * @code_in: format to be set
+ *
+ * This function set the given format of v-scaler
+ *
+ * Return: format value on success. -EINVAL for invalid format.
+ *
+ */
+static int
+xv_vscaler_setup_video_fmt(struct xilinx_scaler *scaler, u32 code_in)
+{
+	u32 video_in;
+
+	switch (code_in) {
+	case MEDIA_BUS_FMT_UYVY8_1X16:
+		video_in = XVIDC_CSF_YCRCB_422;
+		break;
+	case MEDIA_BUS_FMT_VUY8_1X24:
+		video_in = XVIDC_CSF_YCRCB_444;
+		break;
+	case MEDIA_BUS_FMT_RGB888_1X24:
+		video_in = XVIDC_CSF_RGB;
+		break;
+	case MEDIA_BUS_FMT_VYYUYY8_1X24:
+		video_in = XVIDC_CSF_YCRCB_420;
+		break;
+	default:
+		dev_info(scaler->dev, "Vscaler Unsupported media fmt\n");
+		return -EINVAL;
+	}
+	xilinx_scaler_write(scaler->base, V_VSCALER_OFF +
+			    XV_VSCALER_CTRL_ADDR_HWREG_COLORMODE_DATA,
+			    video_in);
+	return video_in;
+}
+
+/**
+ * xv_hscaler_setup_video_fmt - Sets video format of h-scaler
+ * @scaler: Pointer to scaler device structure
+ * @code_out: bus format to be set
+ * @vsc_out: return value of vscaler
+ *
+ * This function set the given video format of h-scaler
+ *
+ * Return: format value on success. -EINVAL for invalid format.
+ *
+ */
+static int xv_hscaler_setup_video_fmt(struct xilinx_scaler *scaler,
+				      u32 code_out, u32 vsc_out)
+{
+	u32 video_out;
+
+	switch (vsc_out) {
+	case XVIDC_CSF_YCRCB_422:
+		break;
+	case XVIDC_CSF_YCRCB_444:
+		break;
+	case XVIDC_CSF_RGB:
+		break;
+	case XVIDC_CSF_YCRCB_420:
+		break;
+	default:
+		dev_info(scaler->dev, "unsupported format from Vscaler");
+		return -EINVAL;
+	}
+
+	xilinx_scaler_write(scaler->base, V_HSCALER_OFF +
+		XV_HSCALER_CTRL_ADDR_HWREG_COLORMODE_DATA,
+		vsc_out);
+
+	switch (code_out) {
+	case MEDIA_BUS_FMT_UYVY8_1X16:
+		video_out = XVIDC_CSF_YCRCB_422;
+		break;
+	case MEDIA_BUS_FMT_VUY8_1X24:
+		video_out = XVIDC_CSF_YCRCB_444;
+		break;
+	case MEDIA_BUS_FMT_RGB888_1X24:
+		video_out = XVIDC_CSF_RGB;
+		break;
+	case MEDIA_BUS_FMT_VYYUYY8_1X24:
+		video_out = XVIDC_CSF_YCRCB_420;
+		break;
+	default:
+		dev_info(scaler->dev, "Hscaler Unsupported Out media fmt\n");
+		return -EINVAL;
+	}
+	xilinx_scaler_write(scaler->base, V_HSCALER_OFF +
+			    XV_HSCALER_CTRL_ADDR_HWREG_COLORMODEOUT_DATA,
+			    video_out);
+	return 0;
+}
+
+/**
+ * xilinx_scaler_parse_of - Parse device tree information
+ * @scaler: Pointer to scaler device structure
+ *
+ * This function reads the device tree contents
+ *
+ * Return: 0 on success. -EINVAL for invalid value.
+ *
+ */
+static int xilinx_scaler_parse_of(struct xilinx_scaler *scaler)
+{
+	int ret;
+	u32 dt_ppc;
+	struct device_node *node = scaler->dev->of_node;
+
+	scaler->ctrl_clk = devm_clk_get(scaler->dev, "aclk_ctrl");
+	if (IS_ERR(scaler->ctrl_clk)) {
+		ret = PTR_ERR(scaler->ctrl_clk);
+		dev_err(scaler->dev, "failed to get axi lite clk %d\n", ret);
+		return ret;
+	}
+
+	scaler->axis_clk = devm_clk_get(scaler->dev, "aclk_axis");
+	if (IS_ERR(scaler->axis_clk)) {
+		ret = PTR_ERR(scaler->axis_clk);
+		dev_err(scaler->dev, "failed to get video clk %d\n", ret);
+		return ret;
+	}
+
+	ret = of_property_read_u32(node, "xlnx,h-scaler-taps",
+				   &scaler->num_hori_taps);
+	if (ret < 0) {
+		dev_info(scaler->dev, "h-scaler-taps not present in DT\n");
+		return ret;
+	}
+	switch (scaler->num_hori_taps) {
+	case XV_HSCALER_TAPS_2:
+	case XV_HSCALER_TAPS_4:
+		scaler->is_polyphase = false;
+		break;
+	case XV_HSCALER_TAPS_6:
+	case XV_HSCALER_TAPS_8:
+	case XV_HSCALER_TAPS_10:
+	case XV_HSCALER_TAPS_12:
+		scaler->is_polyphase = true;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32(node, "xlnx,v-scaler-taps",
+				   &scaler->num_vert_taps);
+	if (ret < 0) {
+		dev_info(scaler->dev, "v-scaler-taps not present in DT\n");
+		return ret;
+	}
+
+	switch (scaler->num_vert_taps) {
+	case XV_HSCALER_TAPS_2:
+	case XV_VSCALER_TAPS_4:
+		if (scaler->num_vert_taps != scaler->num_hori_taps)
+			return -EINVAL;
+		break;
+	case XV_VSCALER_TAPS_6:
+	case XV_VSCALER_TAPS_8:
+	case XV_VSCALER_TAPS_10:
+	case XV_VSCALER_TAPS_12:
+		scaler->is_polyphase = true;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32(node, "xlnx,samples-per-clk", &dt_ppc);
+	if (ret < 0) {
+		dev_info(scaler->dev, "PPC is missing in DT\n");
+		return ret;
+	}
+	if (dt_ppc != XSCALER_PPC_1 && dt_ppc != XSCALER_PPC_2) {
+		dev_info(scaler->dev, "Unsupported ppc: %d", dt_ppc);
+		return -EINVAL;
+	}
+	scaler->pix_per_clk = dt_ppc;
+
+	/* Reset GPIO */
+	scaler->rst_gpio = devm_gpiod_get(scaler->dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(scaler->rst_gpio)) {
+		if (PTR_ERR(scaler->rst_gpio) != -EPROBE_DEFER)
+			dev_err(scaler->dev, "Reset GPIO not setup in DT");
+		return PTR_ERR(scaler->rst_gpio);
+	}
+
+	ret = of_property_read_u32(node, "xlnx,max-height",
+				   &scaler->max_lines);
+	if (ret < 0) {
+		dev_err(scaler->dev, "xlnx,max-height is missing!");
+		return -EINVAL;
+	} else if (scaler->max_lines > XSCALER_MAX_HEIGHT ||
+		   scaler->max_lines < XSCALER_MIN_HEIGHT) {
+		dev_err(scaler->dev, "Invalid height in dt");
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32(node, "xlnx,max-width",
+				   &scaler->max_pixels);
+	if (ret < 0) {
+		dev_err(scaler->dev, "xlnx,max-width is missing!");
+		return -EINVAL;
+	} else if (scaler->max_pixels > XSCALER_MAX_WIDTH ||
+		   scaler->max_pixels < XSCALER_MIN_WIDTH) {
+		dev_err(scaler->dev, "Invalid width in dt");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * xilinx_scaler_stream - Set up v-scaler and h-scaler for streaming
+ * @scaler: Pointer to scaler device structure
+ *
+ * This function sets up the required configuration of v-scaler and h-scaler
+ *
+ * Return: 0 on success. Returns -EINVAL on failure conditions.
+ */
+static int xilinx_scaler_stream(struct xilinx_scaler *scaler)
+{
+	u32 fmt_in, fmt_out;
+	u32 pixel_rate;
+	u32 line_rate;
+	int ret;
+
+	fmt_in = scaler->fmt_in;
+	fmt_out = scaler->fmt_out;
+	line_rate = (scaler->height_in * STEP_PRECISION) / scaler->height_out;
+
+	if (scaler->is_polyphase) {
+		ret = xv_vscaler_select_coeff(scaler, scaler->height_in,
+					      scaler->height_out);
+		if (ret < 0) {
+			dev_info(scaler->dev, "Failed: vscaler select coeff\n");
+			return ret;
+		}
+		xv_vscaler_set_coeff(scaler);
+	}
+	xilinx_scaler_write(scaler->base, V_VSCALER_OFF +
+			    XV_VSCALER_CTRL_ADDR_HWREG_LINERATE_DATA,
+			    line_rate);
+	ret = xv_vscaler_setup_video_fmt(scaler, scaler->fmt_in);
+	if (ret < 0) {
+		dev_info(scaler->dev, "Failed: vscaler setup video format\n");
+		return ret;
+	}
+	pixel_rate = (scaler->width_in * STEP_PRECISION) / scaler->width_out;
+	xilinx_scaler_write(scaler->base, V_HSCALER_OFF +
+			    XV_HSCALER_CTRL_ADDR_HWREG_PIXELRATE_DATA,
+			    pixel_rate);
+	ret = xv_hscaler_setup_video_fmt(scaler, scaler->fmt_out, ret);
+	if (ret < 0) {
+		dev_info(scaler->dev, "Failed: vscaler setup video format\n");
+		return ret;
+	}
+	if (scaler->is_polyphase) {
+		ret = xv_hscaler_select_coeff(scaler, scaler->width_in,
+					      scaler->width_out);
+		if (ret < 0) {
+			dev_info(scaler->dev, "Failed: hscaler select coeff\n");
+			return ret;
+		}
+		xv_hscaler_set_coeff(scaler);
+	}
+	xv_hscaler_calculate_phases(scaler, scaler->width_in,
+				    scaler->width_out, pixel_rate);
+	xv_hscaler_set_phases(scaler);
+	return 0;
+}
+
+/**
+ * xilinx_scaler_bridge_enable - enabes scaler sub-cores
+ * @bridge: bridge instance
+ *
+ * This function enables the scaler sub-cores
+ *
+ * Return: 0 on success. Return -EINVAL on failure conditions.
+ *
+ */
+static int xilinx_scaler_bridge_enable(struct xlnx_bridge *bridge)
+{
+	int ret;
+	struct xilinx_scaler *scaler = bridge_to_layer(bridge);
+
+	ret = xilinx_scaler_stream(scaler);
+	if (ret)
+		return ret;
+
+	xilinx_scaler_write(scaler->base, V_HSCALER_OFF +
+			    XV_HSCALER_CTRL_ADDR_AP_CTRL, XSCALER_STREAM_ON);
+	xilinx_scaler_write(scaler->base, V_VSCALER_OFF +
+			    XV_VSCALER_CTRL_ADDR_AP_CTRL, XSCALER_STREAM_ON);
+	xilinx_scaler_enable_block(scaler, XGPIO_CH_RESET_SEL,
+				   XGPIO_RESET_MASK_IP_AXIS);
+	return ret;
+}
+
+/**
+ * xilinx_scaler_bridge_disable - disables scaler sub-cores
+ * @bridge: bridge instance
+ *
+ * This function disables the scaler sub-cores
+ */
+static void xilinx_scaler_bridge_disable(struct xlnx_bridge *bridge)
+{
+	struct xilinx_scaler *scaler = bridge_to_layer(bridge);
+
+	xilinx_scaler_disable_block(scaler, XGPIO_CH_RESET_SEL,
+				    XGPIO_RESET_MASK_ALL_BLOCKS);
+}
+
+/**
+ * xilinx_scaler_bridge_set_input - Sets the input parameters of scaler
+ * @bridge: bridge instance
+ * @width: width of video
+ * @height: height of video
+ * @bus_fmt: video bus format
+ *
+ * This function sets the input parameters of scaler
+ * Return: 0 on success. -EINVAL for invalid parameters.
+ */
+static int xilinx_scaler_bridge_set_input(struct xlnx_bridge *bridge,
+					  u32 width, u32 height, u32 bus_fmt)
+{
+	struct xilinx_scaler *scaler = bridge_to_layer(bridge);
+
+	if (width > scaler->max_pixels || height > scaler->max_lines)
+		return -EINVAL;
+
+	scaler->height_in = height;
+	scaler->width_in = width;
+	scaler->fmt_in = bus_fmt;
+
+	/* IP Reset through GPIO */
+	gpiod_set_value_cansleep(scaler->rst_gpio, XSCALER_RESET_ASSERT);
+	gpiod_set_value_cansleep(scaler->rst_gpio, XSCALER_RESET_DEASSERT);
+	xilinx_scaler_reset(scaler);
+	memset(scaler->H_phases, 0, sizeof(scaler->H_phases));
+
+	xilinx_scaler_write(scaler->base, V_VSCALER_OFF +
+			    XV_VSCALER_CTRL_ADDR_HWREG_HEIGHTIN_DATA, height);
+	xilinx_scaler_write(scaler->base, V_VSCALER_OFF +
+			    XV_VSCALER_CTRL_ADDR_HWREG_WIDTH_DATA, width);
+	xilinx_scaler_write(scaler->base, V_HSCALER_OFF +
+			    XV_HSCALER_CTRL_ADDR_HWREG_WIDTHIN_DATA, width);
+
+	return 0;
+}
+
+/**
+ * xilinx_scaler_bridge_get_input_fmts - input formats supported by scaler
+ * @bridge: bridge instance
+ * @fmts: Pointer to be updated with formats information
+ * @count: count of video bus formats
+ *
+ * This function provides the input video formats information scaler
+ * Return: 0 on success.
+ */
+static int xilinx_scaler_bridge_get_input_fmts(struct xlnx_bridge *bridge,
+					       const u32 **fmts, u32 *count)
+{
+	*fmts = xilinx_scaler_video_fmts;
+	*count = ARRAY_SIZE(xilinx_scaler_video_fmts);
+	return 0;
+}
+
+/**
+ * xilinx_scaler_bridge_set_output - Sets the output parameters of scaler
+ * @bridge: bridge instance
+ * @width: width of video
+ * @height: height of video
+ * @bus_fmt: video bus format
+ *
+ * This function sets the output parameters of scaler
+ * Return: 0 on success. -EINVAL for invalid parameters.
+ */
+static int xilinx_scaler_bridge_set_output(struct xlnx_bridge *bridge,
+					   u32 width, u32 height, u32 bus_fmt)
+{
+	struct xilinx_scaler *scaler = bridge_to_layer(bridge);
+
+	if (width > scaler->max_pixels || height > scaler->max_lines)
+		return -EINVAL;
+
+	scaler->height_out = height;
+	scaler->width_out = width;
+	scaler->fmt_out = bus_fmt;
+
+	xilinx_scaler_write(scaler->base, V_VSCALER_OFF +
+			    XV_VSCALER_CTRL_ADDR_HWREG_HEIGHTOUT_DATA, height);
+	xilinx_scaler_write(scaler->base, V_HSCALER_OFF +
+			    XV_HSCALER_CTRL_ADDR_HWREG_HEIGHT_DATA, height);
+	xilinx_scaler_write(scaler->base, V_HSCALER_OFF +
+			    XV_HSCALER_CTRL_ADDR_HWREG_WIDTHOUT_DATA, width);
+	return 0;
+}
+
+/**
+ * xilinx_scaler_bridge_get_output_fmts - output formats supported by scaler
+ * @bridge: bridge instance
+ * @fmts: Pointer to be updated with formats information
+ * @count: count of video bus formats
+ *
+ * This function provides the output video formats information scaler
+ * Return: 0 on success.
+ */
+static int xilinx_scaler_bridge_get_output_fmts(struct xlnx_bridge *bridge,
+						const u32 **fmts, u32 *count)
+{
+	*fmts = xilinx_scaler_video_fmts;
+	*count = ARRAY_SIZE(xilinx_scaler_video_fmts);
+	return 0;
+}
+
+static const struct xscaler_feature xlnx_scaler_v2_2 = {
+	.flags = XSCALER_HPHASE_FIX,
+};
+
+static const struct xscaler_feature xlnx_scaler = {
+	.flags = 0,
+};
+
+static const struct of_device_id xilinx_scaler_of_match[] = {
+	{ .compatible = "xlnx,vpss-scaler",
+		.data = &xlnx_scaler},
+	{ .compatible = "xlnx,vpss-scaler-2.2",
+		.data = &xlnx_scaler_v2_2},
+	{ }
+};
+
+MODULE_DEVICE_TABLE(of, xilinx_scaler_of_match);
+
+static int xilinx_scaler_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct xilinx_scaler *scaler;
+	const struct of_device_id *match;
+	struct device_node *node = pdev->dev.of_node;
+	int ret;
+
+	scaler = devm_kzalloc(dev, sizeof(*scaler), GFP_KERNEL);
+	if (!scaler)
+		return -ENOMEM;
+	scaler->dev = dev;
+
+	match = of_match_node(xilinx_scaler_of_match, node);
+	if (!match)
+		return -ENODEV;
+
+	scaler->cfg = match->data;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	scaler->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(scaler->base)) {
+		dev_err(dev, "failed to remap io region\n");
+		return -ENOMEM;
+	}
+	platform_set_drvdata(pdev, scaler);
+
+	ret = xilinx_scaler_parse_of(scaler);
+	if (ret < 0) {
+		dev_info(scaler->dev, "parse_of failed\n");
+		return ret;
+	}
+
+	ret = clk_prepare_enable(scaler->ctrl_clk);
+	if (ret) {
+		dev_err(scaler->dev, "unable to enable axi lite clk %d\n", ret);
+		return ret;
+	}
+
+	ret = clk_prepare_enable(scaler->axis_clk);
+	if (ret) {
+		dev_err(scaler->dev, "unable to enable video clk %d\n", ret);
+		goto err_ctrl_clk;
+	}
+
+	scaler->max_num_phases = XSCALER_MAX_PHASES;
+
+	/* Reset the Global IP Reset through a GPIO */
+	gpiod_set_value_cansleep(scaler->rst_gpio, XSCALER_RESET_DEASSERT);
+	xilinx_scaler_reset(scaler);
+
+	scaler->bridge.enable = &xilinx_scaler_bridge_enable;
+	scaler->bridge.disable = &xilinx_scaler_bridge_disable;
+	scaler->bridge.set_input = &xilinx_scaler_bridge_set_input;
+	scaler->bridge.get_input_fmts = &xilinx_scaler_bridge_get_input_fmts;
+	scaler->bridge.set_output = &xilinx_scaler_bridge_set_output;
+	scaler->bridge.get_output_fmts = &xilinx_scaler_bridge_get_output_fmts;
+	scaler->bridge.of_node = dev->of_node;
+
+	ret = xlnx_bridge_register(&scaler->bridge);
+	if (ret) {
+		dev_info(scaler->dev, "Bridge registration failed\n");
+		goto err_axis_clk;
+	}
+	dev_info(scaler->dev, "xlnx drm scaler experimental driver probed\n");
+
+	return 0;
+
+err_axis_clk:
+	clk_disable_unprepare(scaler->axis_clk);
+err_ctrl_clk:
+	clk_disable_unprepare(scaler->ctrl_clk);
+	return ret;
+}
+
+static int xilinx_scaler_remove(struct platform_device *pdev)
+{
+	struct xilinx_scaler *scaler = platform_get_drvdata(pdev);
+
+	xlnx_bridge_unregister(&scaler->bridge);
+	clk_disable_unprepare(scaler->axis_clk);
+	clk_disable_unprepare(scaler->ctrl_clk);
+	return 0;
+}
+
+static struct platform_driver scaler_bridge_driver = {
+	.probe = xilinx_scaler_probe,
+	.remove = xilinx_scaler_remove,
+	.driver = {
+		.name = "xlnx,scaler-bridge",
+		.of_match_table = xilinx_scaler_of_match,
+	},
+};
+
+module_platform_driver(scaler_bridge_driver);
+
+MODULE_AUTHOR("Venkateshwar Rao <vgannava@xilinx.com>");
+MODULE_DESCRIPTION("Xilinx FPGA SCALER Bridge Driver");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/xlnx/xlnx_sdi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/xlnx/xlnx_sdi.c
@@ -0,0 +1,1445 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx FPGA SDI Tx Subsystem driver.
+ *
+ * Copyright (c) 2017 Xilinx Pvt., Ltd
+ *
+ * Contacts: Saurabh Sengar <saurabhs@xilinx.com>
+ */
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drmP.h>
+#include <drm/drm_probe_helper.h>
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/component.h>
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/of_device.h>
+#include <linux/of_graph.h>
+#include <linux/phy/phy.h>
+#include <media/hdr-ctrls.h>
+#include <video/videomode.h>
+#include "xlnx_sdi_modes.h"
+#include "xlnx_sdi_timing.h"
+
+#include "xlnx_bridge.h"
+
+/* SDI register offsets */
+#define XSDI_TX_RST_CTRL		0x00
+#define XSDI_TX_MDL_CTRL		0x04
+#define XSDI_TX_GLBL_IER		0x0C
+#define XSDI_TX_ISR_STAT		0x10
+#define XSDI_TX_IER_STAT		0x14
+#define XSDI_TX_ST352_LINE		0x18
+#define XSDI_TX_ST352_DATA_CH0		0x1C
+#define XSDI_TX_VER			0x3C
+#define XSDI_TX_SYS_CFG			0x40
+#define XSDI_TX_STS_SB_TDATA		0x60
+#define XSDI_TX_AXI4S_STS1		0x68
+#define XSDI_TX_AXI4S_STS2		0x6C
+#define XSDI_TX_ST352_DATA_DS2		0x70
+
+/* MODULE_CTRL register masks */
+#define XSDI_TX_CTRL_M			BIT(7)
+#define XSDI_TX_CTRL_INS_CRC		BIT(12)
+#define XSDI_TX_CTRL_INS_ST352		BIT(13)
+#define XSDI_TX_CTRL_OVR_ST352		BIT(14)
+#define XSDI_TX_CTRL_INS_SYNC_BIT	BIT(16)
+#define XSDI_TX_CTRL_USE_ANC_IN		BIT(18)
+#define XSDI_TX_CTRL_INS_LN		BIT(19)
+#define XSDI_TX_CTRL_INS_EDH		BIT(20)
+#define XSDI_TX_CTRL_MODE		0x7
+#define XSDI_TX_CTRL_MUX		0x7
+#define XSDI_TX_CTRL_MODE_SHIFT		4
+#define XSDI_TX_CTRL_M_SHIFT		7
+#define XSDI_TX_CTRL_MUX_SHIFT		8
+#define XSDI_TX_CTRL_ST352_F2_EN_SHIFT	15
+#define XSDI_TX_CTRL_420_BIT		BIT(21)
+#define XSDI_TX_CTRL_INS_ST352_CHROMA	BIT(23)
+#define XSDI_TX_CTRL_USE_DS2_3GA	BIT(24)
+
+/* TX_ST352_LINE register masks */
+#define XSDI_TX_ST352_LINE_MASK		GENMASK(10, 0)
+#define XSDI_TX_ST352_LINE_F2_SHIFT	16
+
+/* ISR STAT register masks */
+#define XSDI_GTTX_RSTDONE_INTR		BIT(0)
+#define XSDI_TX_CE_ALIGN_ERR_INTR	BIT(1)
+#define XSDI_TX_VSYNC_INTR		BIT(2)
+#define XSDI_AXI4S_VID_LOCK_INTR	BIT(8)
+#define XSDI_OVERFLOW_INTR		BIT(9)
+#define XSDI_UNDERFLOW_INTR		BIT(10)
+#define XSDI_IER_EN_MASK		(XSDI_GTTX_RSTDONE_INTR | \
+					 XSDI_TX_CE_ALIGN_ERR_INTR | \
+					 XSDI_TX_VSYNC_INTR | \
+					 XSDI_OVERFLOW_INTR | \
+					 XSDI_UNDERFLOW_INTR)
+
+/* RST_CTRL_OFFSET masks */
+#define XSDI_TX_CTRL_EN			BIT(0)
+#define XSDI_TX_BRIDGE_CTRL_EN		BIT(8)
+#define XSDI_TX_AXI4S_CTRL_EN		BIT(9)
+/* STS_SB_TX_TDATA masks */
+#define XSDI_TX_TDATA_GT_RESETDONE	BIT(2)
+
+#define XSDI_TX_MUX_SD_HD_3GA		0
+#define	XSDI_TX_MUX_3GB			1
+#define	XSDI_TX_MUX_8STREAM_6G_12G	2
+#define	XSDI_TX_MUX_4STREAM_6G		3
+#define	XSDI_TX_MUX_16STREAM_12G	4
+
+#define SDI_MAX_DATASTREAM		8
+#define PIXELS_PER_CLK			2
+#define XSDI_CH_SHIFT			29
+#define XST352_PROG_PIC			BIT(6)
+#define XST352_PROG_TRANS		BIT(7)
+#define XST352_2048_SHIFT		BIT(6)
+#define XST352_YUV420_MASK		0x03
+#define ST352_BYTE3			0x00
+
+/* Electro Optical Transfer Function */
+#define XST352_BYTE2_EOTF_MASK		GENMASK(13, 12)
+#define XST352_BYTE2_EOTF_SDRTV		0x0
+#define XST352_BYTE2_EOTF_HLG		0x1
+#define XST352_BYTE2_EOTF_SMPTE2084	0x2
+#define XST352_BYTE2_EOTF_UNKNOWN	0x3
+#define XST352_BYTE3_COLORIMETRY_HD	BIT(23)
+#define XST352_BYTE3_COLORIMETRY	BIT(21)
+
+#define ST352_BYTE4			0x01
+#define GT_TIMEOUT			50
+/* SDI modes */
+#define XSDI_MODE_HD			0
+#define	XSDI_MODE_SD			1
+#define	XSDI_MODE_3GA			2
+#define	XSDI_MODE_3GB			3
+#define	XSDI_MODE_6G			4
+#define	XSDI_MODE_12G			5
+
+#define SDI_TIMING_PARAMS_SIZE		48
+#define CLK_RATE			148500000UL
+
+/**
+ * enum payload_line_1 - Payload Ids Line 1 number
+ * @PAYLD_LN1_HD_3_6_12G:	line 1 HD,3G,6G or 12G mode value
+ * @PAYLD_LN1_SDPAL:		line 1 SD PAL mode value
+ * @PAYLD_LN1_SDNTSC:		line 1 SD NTSC mode value
+ */
+enum payload_line_1 {
+	PAYLD_LN1_HD_3_6_12G = 10,
+	PAYLD_LN1_SDPAL = 9,
+	PAYLD_LN1_SDNTSC = 13
+};
+
+/**
+ * enum payload_line_2 - Payload Ids Line 2 number
+ * @PAYLD_LN2_HD_3_6_12G:	line 2 HD,3G,6G or 12G mode value
+ * @PAYLD_LN2_SDPAL:		line 2 SD PAL mode value
+ * @PAYLD_LN2_SDNTSC:		line 2 SD NTSC mode value
+ */
+enum payload_line_2 {
+	PAYLD_LN2_HD_3_6_12G = 572,
+	PAYLD_LN2_SDPAL = 322,
+	PAYLD_LN2_SDNTSC = 276
+};
+
+/**
+ * struct xlnx_sdi - Core configuration SDI Tx subsystem device structure
+ * @encoder: DRM encoder structure
+ * @connector: DRM connector structure
+ * @dev: device structure
+ * @gt_rst_gpio: GPIO handle to reset GT phy
+ * @base: Base address of SDI subsystem
+ * @mode_flags: SDI operation mode related flags
+ * @wait_event: wait event
+ * @event_received: wait event status
+ * @enable_st352_chroma: Able to send ST352 packets in Chroma stream.
+ * @enable_anc_data: Enable/Disable Ancillary Data insertion for Audio
+ * @sdi_mode: configurable SDI mode parameter, supported values are:
+ *		0 - HD
+ *		1 - SD
+ *		2 - 3GA
+ *		3 - 3GB
+ *		4 - 6G
+ *		5 - 12G
+ * @sdi_mod_prop_val: configurable SDI mode parameter value
+ * @sdi_data_strm: configurable SDI data stream parameter
+ * @sdi_data_strm_prop_val: configurable number of SDI data streams
+ *			    value currently supported are 2, 4 and 8
+ * @sdi_420_in: Specifying input bus color format parameter to SDI
+ * @sdi_420_in_val: 1 for yuv420 and 0 for yuv422
+ * @sdi_420_out: configurable SDI out color format parameter
+ * @sdi_420_out_val: 1 for yuv420 and 0 for yuv422
+ * @is_frac_prop: configurable SDI fractional fps parameter
+ * @is_frac_prop_val: configurable SDI fractional fps parameter value
+ * @bridge: bridge structure
+ * @height_out: configurable bridge output height parameter
+ * @height_out_prop_val: configurable bridge output height parameter value
+ * @width_out: configurable bridge output width parameter
+ * @width_out_prop_val: configurable bridge output width parameter value
+ * @in_fmt: configurable bridge input media format
+ * @in_fmt_prop_val: configurable media bus format value
+ * @out_fmt: configurable bridge output media format
+ * @out_fmt_prop_val: configurable media bus format value
+ * @en_st352_c_prop: configurable ST352 payload on Chroma stream parameter
+ * @en_st352_c_val: configurable ST352 payload on Chroma parameter value
+ * @use_ds2_3ga_prop: Use DS2 instead of DS3 in 3GA mode parameter
+ * @use_ds2_3ga_val: Use DS2 instead of DS3 in 3GA mode parameter value
+ * @c_encoding: configurable color encoding
+ * @c_encoding_prop_val: 1 for UHDTV and 0 for Rec709
+ * @video_mode: current display mode
+ * @axi_clk: AXI Lite interface clock
+ * @sditx_clk: SDI Tx Clock
+ * @vidin_clk: Video Clock
+ * @qpll1_enabled: indicates qpll1 presence
+ * @picxo_enabled: indicates picxo core presence
+ * @prev_eotf: previous end of transfer function
+ */
+struct xlnx_sdi {
+	struct drm_encoder encoder;
+	struct drm_connector connector;
+	struct device *dev;
+	struct gpio_desc *gt_rst_gpio;
+	void __iomem *base;
+	u32 mode_flags;
+	wait_queue_head_t wait_event;
+	bool event_received;
+	bool enable_st352_chroma;
+	bool enable_anc_data;
+	struct drm_property *sdi_mode;
+	u32 sdi_mod_prop_val;
+	struct drm_property *sdi_data_strm;
+	u32 sdi_data_strm_prop_val;
+	struct drm_property *sdi_420_in;
+	bool sdi_420_in_val;
+	struct drm_property *sdi_420_out;
+	bool sdi_420_out_val;
+	struct drm_property *is_frac_prop;
+	bool is_frac_prop_val;
+	struct xlnx_bridge *bridge;
+	struct drm_property *height_out;
+	u32 height_out_prop_val;
+	struct drm_property *width_out;
+	u32 width_out_prop_val;
+	struct drm_property *in_fmt;
+	u32 in_fmt_prop_val;
+	struct drm_property *out_fmt;
+	u32 out_fmt_prop_val;
+	struct drm_property *en_st352_c_prop;
+	bool en_st352_c_val;
+	struct drm_property *use_ds2_3ga_prop;
+	bool use_ds2_3ga_val;
+	struct drm_property *c_encoding;
+	u32 c_encoding_prop_val;
+	struct drm_display_mode video_mode;
+	struct clk *axi_clk;
+	struct clk *sditx_clk;
+	struct clk *vidin_clk;
+	bool qpll1_enabled;
+	bool picxo_enabled;
+	u8 prev_eotf;
+};
+
+#define connector_to_sdi(c) container_of(c, struct xlnx_sdi, connector)
+#define encoder_to_sdi(e) container_of(e, struct xlnx_sdi, encoder)
+
+static inline void xlnx_sdi_writel(void __iomem *base, int offset, u32 val)
+{
+	writel(val, base + offset);
+}
+
+static inline u32 xlnx_sdi_readl(void __iomem *base, int offset)
+{
+	return readl(base + offset);
+}
+
+/**
+ * xlnx_sdi_en_axi4s - Enable SDI Tx AXI4S-to-Video core
+ * @sdi:	Pointer to SDI Tx structure
+ *
+ * This function enables the SDI Tx AXI4S-to-Video core.
+ */
+static void xlnx_sdi_en_axi4s(struct xlnx_sdi *sdi)
+{
+	u32 data;
+
+	data = xlnx_sdi_readl(sdi->base, XSDI_TX_RST_CTRL);
+	data |= XSDI_TX_AXI4S_CTRL_EN;
+	xlnx_sdi_writel(sdi->base, XSDI_TX_RST_CTRL, data);
+}
+
+/**
+ * xlnx_sdi_en_bridge - Enable SDI Tx bridge
+ * @sdi:	Pointer to SDI Tx structure
+ *
+ * This function enables the SDI Tx bridge.
+ */
+static void xlnx_sdi_en_bridge(struct xlnx_sdi *sdi)
+{
+	u32 data;
+
+	data = xlnx_sdi_readl(sdi->base, XSDI_TX_RST_CTRL);
+	data |= XSDI_TX_BRIDGE_CTRL_EN;
+	xlnx_sdi_writel(sdi->base, XSDI_TX_RST_CTRL, data);
+}
+
+/**
+ * xlnx_sdi_gt_reset - Reset cores through gpio
+ * @sdi: Pointer to SDI Tx structure
+ *
+ * This function resets the GT phy core.
+ */
+static void xlnx_sdi_gt_reset(struct xlnx_sdi *sdi)
+{
+	gpiod_set_value(sdi->gt_rst_gpio, 1);
+	gpiod_set_value(sdi->gt_rst_gpio, 0);
+	/* delay added to get vtc_en signal */
+	mdelay(5);
+}
+
+/**
+ * xlnx_sdi_set_eotf - Set eotf field in payload
+ * @sdi: Pointer to SDI Tx structure
+ *
+ * This function parse the hdr metadata and sets
+ * eotf and colorimetry fields of payload.
+ */
+static void xlnx_sdi_set_eotf(struct xlnx_sdi *sdi)
+{
+	struct hdmi_drm_infoframe frame;
+	struct drm_connector_state *state = sdi->connector.state;
+	u32 payload, i;
+	int ret;
+	u8 eotf, colori;
+
+	ret = drm_hdmi_infoframe_set_gen_hdr_metadata(&frame, state);
+	if (ret)
+		return;
+
+	eotf = (__u8)frame.eotf;
+
+	if (sdi->prev_eotf == eotf || eotf > XST352_BYTE2_EOTF_UNKNOWN)
+		return;
+
+	switch (eotf) {
+	case V4L2_EOTF_BT_2100_HLG:
+		eotf = XST352_BYTE2_EOTF_HLG;
+		break;
+	case V4L2_EOTF_TRADITIONAL_GAMMA_SDR:
+		eotf = XST352_BYTE2_EOTF_SDRTV;
+		break;
+	case V4L2_EOTF_SMPTE_ST2084:
+		eotf = XST352_BYTE2_EOTF_SMPTE2084;
+		break;
+	}
+
+	colori = sdi->c_encoding_prop_val;
+	payload = xlnx_sdi_readl(sdi->base, XSDI_TX_ST352_DATA_CH0);
+
+	/*
+	 * For HD mode, bit 23 and 20 of payload represents
+	 * colorimetry as per SMPTE 292-1:2018 Sec 9.5.
+	 * For other modes, its bit 21 and 20.
+	 * For BT709 & BT2020 - bit 20 is always zero
+	 */
+	if (sdi->sdi_mod_prop_val == XSDI_MODE_HD) {
+		payload &= ~(XST352_BYTE2_EOTF_MASK |
+			     XST352_BYTE3_COLORIMETRY_HD);
+		payload |= FIELD_PREP(XST352_BYTE2_EOTF_MASK, eotf) |
+			FIELD_PREP(XST352_BYTE3_COLORIMETRY_HD, colori);
+	} else {
+		payload &= ~(XST352_BYTE2_EOTF_MASK |
+			     XST352_BYTE3_COLORIMETRY);
+		payload |= FIELD_PREP(XST352_BYTE2_EOTF_MASK, eotf) |
+			FIELD_PREP(XST352_BYTE3_COLORIMETRY, colori);
+	}
+
+	dev_dbg(sdi->dev, "payload = 0x%x, eotf = %d\n", payload, eotf);
+	for (i = 0; i < sdi->sdi_data_strm_prop_val / 2; i++)
+		xlnx_sdi_writel(sdi->base,
+				(XSDI_TX_ST352_DATA_CH0 + (i * 4)), payload);
+	sdi->prev_eotf = eotf;
+}
+
+/**
+ * xlnx_sdi_irq_handler - SDI Tx interrupt
+ * @irq:	irq number
+ * @data:	irq data
+ *
+ * Return: IRQ_HANDLED for all cases.
+ *
+ * This is the compact GT ready interrupt.
+ */
+static irqreturn_t xlnx_sdi_irq_handler(int irq, void *data)
+{
+	struct xlnx_sdi *sdi = (struct xlnx_sdi *)data;
+	u32 reg;
+
+	reg = xlnx_sdi_readl(sdi->base, XSDI_TX_ISR_STAT);
+
+	if (reg & XSDI_TX_VSYNC_INTR)
+		xlnx_sdi_set_eotf(sdi);
+	if (reg & XSDI_GTTX_RSTDONE_INTR)
+		dev_dbg(sdi->dev, "GT reset interrupt received\n");
+	if (reg & XSDI_TX_CE_ALIGN_ERR_INTR)
+		dev_err_ratelimited(sdi->dev, "SDI SD CE align error\n");
+	if (reg & XSDI_OVERFLOW_INTR)
+		dev_err_ratelimited(sdi->dev, "AXI-4 Stream Overflow error\n");
+	if (reg & XSDI_UNDERFLOW_INTR)
+		dev_err_ratelimited(sdi->dev, "AXI-4 Stream Underflow error\n");
+	xlnx_sdi_writel(sdi->base, XSDI_TX_ISR_STAT,
+			reg & ~(XSDI_AXI4S_VID_LOCK_INTR));
+
+	reg = xlnx_sdi_readl(sdi->base, XSDI_TX_STS_SB_TDATA);
+	if (reg & XSDI_TX_TDATA_GT_RESETDONE) {
+		sdi->event_received = true;
+		wake_up_interruptible(&sdi->wait_event);
+	}
+	return IRQ_HANDLED;
+}
+
+/**
+ * xlnx_sdi_set_payload_line - set ST352 packet line number
+ * @sdi:	Pointer to SDI Tx structure
+ * @line_1:	line number used to insert st352 packet for field 1.
+ * @line_2:	line number used to insert st352 packet for field 2.
+ *
+ * This function set 352 packet line number.
+ */
+static void xlnx_sdi_set_payload_line(struct xlnx_sdi *sdi,
+				      u32 line_1, u32 line_2)
+{
+	u32 data;
+
+	data = ((line_1 & XSDI_TX_ST352_LINE_MASK) |
+		((line_2 & XSDI_TX_ST352_LINE_MASK) <<
+		XSDI_TX_ST352_LINE_F2_SHIFT));
+
+	xlnx_sdi_writel(sdi->base, XSDI_TX_ST352_LINE, data);
+
+	data = xlnx_sdi_readl(sdi->base, XSDI_TX_MDL_CTRL);
+	data |= (1 << XSDI_TX_CTRL_ST352_F2_EN_SHIFT);
+
+	xlnx_sdi_writel(sdi->base, XSDI_TX_MDL_CTRL, data);
+}
+
+/**
+ * xlnx_sdi_set_payload_data - set ST352 packet payload
+ * @sdi:		Pointer to SDI Tx structure
+ * @data_strm:		data stream number
+ * @payload:		st352 packet payload
+ *
+ * This function set ST352 payload data to corresponding stream.
+ */
+static void xlnx_sdi_set_payload_data(struct xlnx_sdi *sdi,
+				      u32 data_strm, u32 payload)
+{
+	xlnx_sdi_writel(sdi->base,
+			(XSDI_TX_ST352_DATA_CH0 + (data_strm * 4)), payload);
+
+	dev_dbg(sdi->dev, "enable_st352_chroma = %d and en_st352_c_val = %d\n",
+		sdi->enable_st352_chroma, sdi->en_st352_c_val);
+	if (sdi->enable_st352_chroma && sdi->en_st352_c_val) {
+		xlnx_sdi_writel(sdi->base,
+				(XSDI_TX_ST352_DATA_DS2 + (data_strm * 4)),
+				payload);
+	}
+}
+
+/**
+ * xlnx_sdi_set_display_disable - Disable the SDI Tx IP core enable
+ * register bit
+ * @sdi: SDI structure having the updated user parameters
+ *
+ * This function takes the SDI strucure and disables the core enable bit
+ * of core configuration register.
+ */
+static void xlnx_sdi_set_display_disable(struct xlnx_sdi *sdi)
+{
+	u32 i;
+
+	for (i = 0; i < SDI_MAX_DATASTREAM; i++)
+		xlnx_sdi_set_payload_data(sdi, i, 0);
+
+	xlnx_sdi_writel(sdi->base, XSDI_TX_GLBL_IER, 0);
+	xlnx_sdi_writel(sdi->base, XSDI_TX_RST_CTRL, 0);
+}
+
+/**
+ * xlnx_sdi_payload_config -  config the SDI payload parameters
+ * @sdi:	pointer Xilinx SDI Tx structure
+ * @mode:	display mode
+ *
+ * This function config the SDI st352 payload parameter.
+ */
+static void xlnx_sdi_payload_config(struct xlnx_sdi *sdi, u32 mode)
+{
+	u32 payload_1, payload_2;
+
+	switch (mode) {
+	case XSDI_MODE_SD:
+		payload_1 = PAYLD_LN1_SDPAL;
+		payload_2 = PAYLD_LN2_SDPAL;
+		break;
+	case XSDI_MODE_HD:
+	case XSDI_MODE_3GA:
+	case XSDI_MODE_3GB:
+	case XSDI_MODE_6G:
+	case XSDI_MODE_12G:
+		payload_1 = PAYLD_LN1_HD_3_6_12G;
+		payload_2 = PAYLD_LN2_HD_3_6_12G;
+		break;
+	default:
+		payload_1 = 0;
+		payload_2 = 0;
+		break;
+	}
+
+	xlnx_sdi_set_payload_line(sdi, payload_1, payload_2);
+}
+
+/**
+ * xlnx_sdi_set_mode -  Set mode parameters in SDI Tx
+ * @sdi:	pointer Xilinx SDI Tx structure
+ * @mode:	SDI Tx display mode
+ * @is_frac:	0 - integer 1 - fractional
+ * @mux_ptrn:	specifiy the data stream interleaving pattern to be used
+ * This function config the SDI st352 payload parameter.
+ */
+static void xlnx_sdi_set_mode(struct xlnx_sdi *sdi, u32 mode,
+			      bool is_frac, u32 mux_ptrn)
+{
+	u32 data;
+
+	xlnx_sdi_payload_config(sdi, mode);
+
+	data = xlnx_sdi_readl(sdi->base, XSDI_TX_MDL_CTRL);
+	data &= ~(XSDI_TX_CTRL_MODE << XSDI_TX_CTRL_MODE_SHIFT);
+	data &= ~(XSDI_TX_CTRL_M);
+	data &= ~(XSDI_TX_CTRL_MUX << XSDI_TX_CTRL_MUX_SHIFT);
+	data &= ~XSDI_TX_CTRL_420_BIT;
+
+	data |= (((mode & XSDI_TX_CTRL_MODE) << XSDI_TX_CTRL_MODE_SHIFT) |
+		(is_frac  << XSDI_TX_CTRL_M_SHIFT) |
+		((mux_ptrn & XSDI_TX_CTRL_MUX) << XSDI_TX_CTRL_MUX_SHIFT));
+
+	if (sdi->sdi_420_out_val)
+		data |= XSDI_TX_CTRL_420_BIT;
+	xlnx_sdi_writel(sdi->base, XSDI_TX_MDL_CTRL, data);
+}
+
+/**
+ * xlnx_sdi_set_config_parameters - Configure SDI Tx registers with parameters
+ * given from user application.
+ * @sdi: SDI structure having the updated user parameters
+ *
+ * This function takes the SDI structure having drm_property parameters
+ * configured from  user application and writes them into SDI IP registers.
+ */
+static void xlnx_sdi_set_config_parameters(struct xlnx_sdi *sdi)
+{
+	int mux_ptrn = -EINVAL;
+
+	switch (sdi->sdi_mod_prop_val) {
+	case XSDI_MODE_3GA:
+		mux_ptrn = XSDI_TX_MUX_SD_HD_3GA;
+		break;
+	case XSDI_MODE_3GB:
+		mux_ptrn = XSDI_TX_MUX_3GB;
+		break;
+	case XSDI_MODE_6G:
+		if (sdi->sdi_data_strm_prop_val == 4)
+			mux_ptrn = XSDI_TX_MUX_4STREAM_6G;
+		else if (sdi->sdi_data_strm_prop_val == 8)
+			mux_ptrn = XSDI_TX_MUX_8STREAM_6G_12G;
+		break;
+	case XSDI_MODE_12G:
+		if (sdi->sdi_data_strm_prop_val == 8)
+			mux_ptrn = XSDI_TX_MUX_8STREAM_6G_12G;
+		break;
+	default:
+		mux_ptrn = 0;
+		break;
+	}
+	if (mux_ptrn == -EINVAL) {
+		dev_err(sdi->dev, "%d data stream not supported for %d mode",
+			sdi->sdi_data_strm_prop_val, sdi->sdi_mod_prop_val);
+		return;
+	}
+	xlnx_sdi_set_mode(sdi, sdi->sdi_mod_prop_val, sdi->is_frac_prop_val,
+			  mux_ptrn);
+}
+
+/**
+ * xlnx_sdi_atomic_set_property - implementation of drm_connector_funcs
+ * set_property invoked by IOCTL call to DRM_IOCTL_MODE_OBJ_SETPROPERTY
+ *
+ * @connector: pointer Xilinx SDI connector
+ * @state: DRM connector state
+ * @property: pointer to the drm_property structure
+ * @val: SDI parameter value that is configured from user application
+ *
+ * This function takes a drm_property name and value given from user application
+ * and update the SDI structure property varabiles with the values.
+ * These values are later used to configure the SDI Rx IP.
+ *
+ * Return: 0 on success OR -EINVAL if setting property fails
+ */
+static int
+xlnx_sdi_atomic_set_property(struct drm_connector *connector,
+			     struct drm_connector_state *state,
+			     struct drm_property *property, uint64_t val)
+{
+	struct xlnx_sdi *sdi = connector_to_sdi(connector);
+
+	if (property == sdi->sdi_mode)
+		sdi->sdi_mod_prop_val = (unsigned int)val;
+	else if (property == sdi->sdi_data_strm)
+		sdi->sdi_data_strm_prop_val = (unsigned int)val;
+	else if (property == sdi->sdi_420_in)
+		sdi->sdi_420_in_val = val;
+	else if (property == sdi->sdi_420_out)
+		sdi->sdi_420_out_val = val;
+	else if (property == sdi->is_frac_prop)
+		sdi->is_frac_prop_val = !!val;
+	else if (property == sdi->height_out)
+		sdi->height_out_prop_val = (unsigned int)val;
+	else if (property == sdi->width_out)
+		sdi->width_out_prop_val = (unsigned int)val;
+	else if (property == sdi->in_fmt)
+		sdi->in_fmt_prop_val = (unsigned int)val;
+	else if (property == sdi->out_fmt)
+		sdi->out_fmt_prop_val = (unsigned int)val;
+	else if (property == sdi->en_st352_c_prop)
+		sdi->en_st352_c_val = !!val;
+	else if (property == sdi->use_ds2_3ga_prop)
+		sdi->use_ds2_3ga_val = !!val;
+	else if (property == sdi->c_encoding)
+		sdi->c_encoding_prop_val = val;
+	else
+		return -EINVAL;
+	return 0;
+}
+
+static int
+xlnx_sdi_atomic_get_property(struct drm_connector *connector,
+			     const struct drm_connector_state *state,
+			     struct drm_property *property, uint64_t *val)
+{
+	struct xlnx_sdi *sdi = connector_to_sdi(connector);
+
+	if (property == sdi->sdi_mode)
+		*val = sdi->sdi_mod_prop_val;
+	else if (property == sdi->sdi_data_strm)
+		*val =  sdi->sdi_data_strm_prop_val;
+	else if (property == sdi->sdi_420_in)
+		*val = sdi->sdi_420_in_val;
+	else if (property == sdi->sdi_420_out)
+		*val = sdi->sdi_420_out_val;
+	else if (property == sdi->is_frac_prop)
+		*val =  sdi->is_frac_prop_val;
+	else if (property == sdi->height_out)
+		*val = sdi->height_out_prop_val;
+	else if (property == sdi->width_out)
+		*val = sdi->width_out_prop_val;
+	else if (property == sdi->in_fmt)
+		*val = sdi->in_fmt_prop_val;
+	else if (property == sdi->out_fmt)
+		*val = sdi->out_fmt_prop_val;
+	else if (property == sdi->en_st352_c_prop)
+		*val =  sdi->en_st352_c_val;
+	else if (property == sdi->use_ds2_3ga_prop)
+		*val =  sdi->use_ds2_3ga_val;
+	else if (property == sdi->c_encoding)
+		*val = sdi->c_encoding_prop_val;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
+ * xlnx_sdi_get_mode_id - Search for a video mode in the supported modes table
+ *
+ * @mode: mode being searched
+ *
+ * Return: mode id if mode is found OR -EINVAL otherwise
+ */
+static int xlnx_sdi_get_mode_id(struct drm_display_mode *mode)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(xlnx_sdi_modes); i++)
+		if (xlnx_sdi_modes[i].mode.htotal == mode->htotal &&
+		    xlnx_sdi_modes[i].mode.vtotal == mode->vtotal &&
+		    xlnx_sdi_modes[i].mode.clock == mode->clock &&
+		    xlnx_sdi_modes[i].mode.flags == mode->flags)
+			return i;
+	return -EINVAL;
+}
+
+/**
+ * xlnx_sdi_drm_add_modes - Adds SDI supported modes
+ * @connector: pointer Xilinx SDI connector
+ *
+ * Return:	Count of modes added
+ *
+ * This function adds the SDI modes supported and returns its count
+ */
+static int xlnx_sdi_drm_add_modes(struct drm_connector *connector)
+{
+	int num_modes = 0;
+	u32 i;
+	struct drm_display_mode *mode;
+	struct drm_device *dev = connector->dev;
+
+	for (i = 0; i < ARRAY_SIZE(xlnx_sdi_modes); i++) {
+		const struct drm_display_mode *ptr = &xlnx_sdi_modes[i].mode;
+
+		mode = drm_mode_duplicate(dev, ptr);
+		if (mode) {
+			drm_mode_probed_add(connector, mode);
+			num_modes++;
+		}
+	}
+	return num_modes;
+}
+
+static enum drm_connector_status
+xlnx_sdi_detect(struct drm_connector *connector, bool force)
+{
+	return connector_status_connected;
+}
+
+static void xlnx_sdi_connector_destroy(struct drm_connector *connector)
+{
+	drm_connector_unregister(connector);
+	drm_connector_cleanup(connector);
+	connector->dev = NULL;
+}
+
+static const struct drm_connector_funcs xlnx_sdi_connector_funcs = {
+	.detect = xlnx_sdi_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = xlnx_sdi_connector_destroy,
+	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+	.reset = drm_atomic_helper_connector_reset,
+	.atomic_set_property = xlnx_sdi_atomic_set_property,
+	.atomic_get_property = xlnx_sdi_atomic_get_property,
+};
+
+static struct drm_encoder *
+xlnx_sdi_best_encoder(struct drm_connector *connector)
+{
+	return &(connector_to_sdi(connector)->encoder);
+}
+
+static int xlnx_sdi_get_modes(struct drm_connector *connector)
+{
+	return xlnx_sdi_drm_add_modes(connector);
+}
+
+static int xlnx_sdi_mode_valid(struct drm_connector *connector,
+			       struct drm_display_mode *mode)
+{
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+		mode->vdisplay /= 2;
+
+	return MODE_OK;
+}
+
+static struct drm_connector_helper_funcs xlnx_sdi_connector_helper_funcs = {
+	.get_modes = xlnx_sdi_get_modes,
+	.best_encoder = xlnx_sdi_best_encoder,
+	.mode_valid = xlnx_sdi_mode_valid,
+};
+
+/**
+ * xlnx_sdi_drm_connector_create_property -  create SDI connector properties
+ *
+ * @base_connector: pointer to Xilinx SDI connector
+ *
+ * This function takes the xilinx SDI connector component and defines
+ * the drm_property variables with their default values.
+ */
+static void
+xlnx_sdi_drm_connector_create_property(struct drm_connector *base_connector)
+{
+	struct drm_device *dev = base_connector->dev;
+	struct xlnx_sdi *sdi  = connector_to_sdi(base_connector);
+
+	sdi->is_frac_prop = drm_property_create_bool(dev, 0, "is_frac");
+	sdi->sdi_mode = drm_property_create_range(dev, 0,
+						  "sdi_mode", 0, 5);
+	sdi->sdi_data_strm = drm_property_create_range(dev, 0,
+						       "sdi_data_stream", 2, 8);
+	sdi->sdi_420_in = drm_property_create_bool(dev, 0, "sdi_420_in");
+	sdi->sdi_420_out = drm_property_create_bool(dev, 0, "sdi_420_out");
+	sdi->height_out = drm_property_create_range(dev, 0,
+						    "height_out", 2, 4096);
+	sdi->width_out = drm_property_create_range(dev, 0,
+						   "width_out", 2, 4096);
+	sdi->in_fmt = drm_property_create_range(dev, 0,
+						"in_fmt", 0, 16384);
+	sdi->out_fmt = drm_property_create_range(dev, 0,
+						 "out_fmt", 0, 16384);
+	if (sdi->enable_st352_chroma) {
+		sdi->en_st352_c_prop = drm_property_create_bool(dev, 0,
+								"en_st352_c");
+		sdi->use_ds2_3ga_prop = drm_property_create_bool(dev, 0,
+								 "use_ds2_3ga");
+	}
+	sdi->c_encoding = drm_property_create_bool(dev, 0, "c_encoding");
+}
+
+/**
+ * xlnx_sdi_drm_connector_attach_property -  attach SDI connector
+ * properties
+ *
+ * @base_connector: pointer to Xilinx SDI connector
+ */
+static void
+xlnx_sdi_drm_connector_attach_property(struct drm_connector *base_connector)
+{
+	struct xlnx_sdi *sdi = connector_to_sdi(base_connector);
+	struct drm_mode_object *obj = &base_connector->base;
+
+	if (sdi->sdi_mode)
+		drm_object_attach_property(obj, sdi->sdi_mode, 0);
+
+	if (sdi->sdi_data_strm)
+		drm_object_attach_property(obj, sdi->sdi_data_strm, 0);
+
+	if (sdi->sdi_420_in)
+		drm_object_attach_property(obj, sdi->sdi_420_in, 0);
+
+	if (sdi->sdi_420_out)
+		drm_object_attach_property(obj, sdi->sdi_420_out, 0);
+
+	if (sdi->is_frac_prop)
+		drm_object_attach_property(obj, sdi->is_frac_prop, 0);
+
+	if (sdi->height_out)
+		drm_object_attach_property(obj, sdi->height_out, 0);
+
+	if (sdi->width_out)
+		drm_object_attach_property(obj, sdi->width_out, 0);
+
+	if (sdi->in_fmt)
+		drm_object_attach_property(obj, sdi->in_fmt, 0);
+
+	if (sdi->out_fmt)
+		drm_object_attach_property(obj, sdi->out_fmt, 0);
+
+	if (sdi->en_st352_c_prop)
+		drm_object_attach_property(obj, sdi->en_st352_c_prop, 0);
+
+	if (sdi->use_ds2_3ga_prop)
+		drm_object_attach_property(obj, sdi->use_ds2_3ga_prop, 0);
+
+	if (sdi->c_encoding)
+		drm_object_attach_property(obj, sdi->c_encoding, 0);
+
+	drm_object_attach_property(obj,
+				   base_connector->dev->mode_config.gen_hdr_output_metadata_property, 0);
+}
+
+static int xlnx_sdi_create_connector(struct drm_encoder *encoder)
+{
+	struct xlnx_sdi *sdi = encoder_to_sdi(encoder);
+	struct drm_connector *connector = &sdi->connector;
+	int ret;
+
+	connector->interlace_allowed = true;
+	connector->doublescan_allowed = true;
+
+	ret = drm_connector_init(encoder->dev, connector,
+				 &xlnx_sdi_connector_funcs,
+				 DRM_MODE_CONNECTOR_Unknown);
+	if (ret) {
+		dev_err(sdi->dev, "Failed to initialize connector with drm\n");
+		return ret;
+	}
+
+	drm_connector_helper_add(connector, &xlnx_sdi_connector_helper_funcs);
+	drm_connector_register(connector);
+	drm_connector_attach_encoder(connector, encoder);
+	xlnx_sdi_drm_connector_create_property(connector);
+	xlnx_sdi_drm_connector_attach_property(connector);
+
+	/* Fill out the supported EOTFs */
+	connector->hdr_sink_metadata.hdmi_type1.eotf |=
+		BIT(V4L2_EOTF_BT_2100_HLG) |
+		BIT(V4L2_EOTF_TRADITIONAL_GAMMA_SDR) |
+		BIT(V4L2_EOTF_SMPTE_ST2084);
+
+	return 0;
+}
+
+/**
+ * xlnx_sdi_set_display_enable - Enables the SDI Tx IP core enable
+ * register bit
+ * @sdi: SDI structure having the updated user parameters
+ *
+ * This function takes the SDI strucure and enables the core enable bit
+ * of core configuration register.
+ */
+static void xlnx_sdi_set_display_enable(struct xlnx_sdi *sdi)
+{
+	u32 data;
+
+	data = xlnx_sdi_readl(sdi->base, XSDI_TX_RST_CTRL);
+	data |= XSDI_TX_CTRL_EN;
+	xlnx_sdi_writel(sdi->base, XSDI_TX_RST_CTRL, data);
+}
+
+/**
+ * xlnx_sdi_calc_st352_payld -  calculate the st352 payload
+ *
+ * @sdi: pointer to SDI Tx structure
+ * @mode: DRM display mode
+ *
+ * This function calculates the st352 payload to be configured.
+ * Please refer to SMPTE ST352 documents for it.
+ * Return:	return st352 payload
+ */
+static u32 xlnx_sdi_calc_st352_payld(struct xlnx_sdi *sdi,
+				     struct drm_display_mode *mode)
+{
+	u8 byt1, byt2;
+	u16 is_p;
+	int id;
+	u32 sdi_mode = sdi->sdi_mod_prop_val;
+	bool is_frac = sdi->is_frac_prop_val;
+	u32 byt3 = ST352_BYTE3;
+
+	id = xlnx_sdi_get_mode_id(mode);
+	dev_dbg(sdi->dev, "mode id: %d\n", id);
+	if (mode->hdisplay == 2048 || mode->hdisplay == 4096)
+		byt3 |= XST352_2048_SHIFT;
+	if (sdi->sdi_420_in_val)
+		byt3 |= XST352_YUV420_MASK;
+
+	/* byte 2 calculation */
+	is_p = !(mode->flags & DRM_MODE_FLAG_INTERLACE);
+	byt2 = xlnx_sdi_modes[id].st352_byt2[is_frac];
+	if (sdi_mode == XSDI_MODE_3GB ||
+	    (mode->flags & DRM_MODE_FLAG_DBLSCAN) || is_p)
+		byt2 |= XST352_PROG_PIC;
+	if (is_p && mode->vtotal >= 1125)
+		byt2 |= XST352_PROG_TRANS;
+
+	/* byte 1 calculation */
+	byt1 = xlnx_sdi_modes[id].st352_byt1[sdi_mode];
+
+	return (ST352_BYTE4 << 24 | byt3 << 16 | byt2 << 8 | byt1);
+}
+
+static void xlnx_sdi_setup(struct xlnx_sdi *sdi)
+{
+	u32 reg;
+
+	dev_dbg(sdi->dev, "%s\n", __func__);
+
+	reg = xlnx_sdi_readl(sdi->base, XSDI_TX_MDL_CTRL);
+	reg |= XSDI_TX_CTRL_INS_CRC | XSDI_TX_CTRL_INS_ST352 |
+		XSDI_TX_CTRL_OVR_ST352 | XSDI_TX_CTRL_INS_SYNC_BIT |
+		XSDI_TX_CTRL_INS_EDH;
+
+	if (sdi->enable_anc_data)
+		reg |= XSDI_TX_CTRL_USE_ANC_IN;
+
+	if (sdi->enable_st352_chroma) {
+		if (sdi->en_st352_c_val) {
+			reg |= XSDI_TX_CTRL_INS_ST352_CHROMA;
+			if (sdi->use_ds2_3ga_val)
+				reg |= XSDI_TX_CTRL_USE_DS2_3GA;
+			else
+				reg &= ~XSDI_TX_CTRL_USE_DS2_3GA;
+		} else {
+			reg &= ~XSDI_TX_CTRL_INS_ST352_CHROMA;
+			reg &= ~XSDI_TX_CTRL_USE_DS2_3GA;
+		}
+	}
+
+	xlnx_sdi_writel(sdi->base, XSDI_TX_MDL_CTRL, reg);
+	xlnx_sdi_writel(sdi->base, XSDI_TX_IER_STAT, XSDI_IER_EN_MASK);
+	xlnx_sdi_writel(sdi->base, XSDI_TX_GLBL_IER, 1);
+	xlnx_stc_reset(sdi->base);
+}
+
+/**
+ * xlnx_sdi_encoder_atomic_mode_set -  drive the SDI timing parameters
+ *
+ * @encoder: pointer to Xilinx DRM encoder
+ * @crtc_state: DRM crtc state
+ * @connector_state: DRM connector state
+ *
+ * This function derives the SDI IP timing parameters from the timing
+ * values given to timing module.
+ */
+static void xlnx_sdi_encoder_atomic_mode_set(struct drm_encoder *encoder,
+					     struct drm_crtc_state *crtc_state,
+				  struct drm_connector_state *connector_state)
+{
+	struct xlnx_sdi *sdi = encoder_to_sdi(encoder);
+	struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
+	struct videomode vm;
+	u32 payload, i;
+	u32 sditx_blank, vtc_blank;
+	unsigned long clkrate;
+	int ret;
+
+	/*
+	 * For the transceiver TX, for integer and fractional frame rate, the
+	 * PLL ref clock must be a different frequency. Other than SD mode
+	 * its 148.5MHz for an integer & 148.5/1.001 for fractional framerate.
+	 * Program clocks followed by reset, if picxo is not enabled.
+	 */
+	if (!sdi->picxo_enabled) {
+		if (sdi->is_frac_prop_val &&
+		    sdi->sdi_mod_prop_val != XSDI_MODE_SD)
+			clkrate = (CLK_RATE * 1000) / 1001;
+		else
+			clkrate = CLK_RATE;
+		ret = clk_set_rate(sdi->sditx_clk, clkrate);
+		if (ret)
+			dev_err(sdi->dev, "failed to set clk rate = %lu\n",
+				clkrate);
+		clkrate = clk_get_rate(sdi->sditx_clk);
+		dev_info(sdi->dev, "clkrate = %lu is_frac = %d\n", clkrate,
+			 sdi->is_frac_prop_val);
+		/*
+		 * Delay required to get QPLL1 lock as per the si5328
+		 * datasheet
+		 */
+		mdelay(50);
+		xlnx_sdi_gt_reset(sdi);
+	}
+
+	/* Set timing parameters as per bridge output parameters */
+	xlnx_bridge_set_input(sdi->bridge, adjusted_mode->hdisplay,
+			      adjusted_mode->vdisplay, sdi->in_fmt_prop_val);
+	xlnx_bridge_set_output(sdi->bridge, sdi->width_out_prop_val,
+			       sdi->height_out_prop_val, sdi->out_fmt_prop_val);
+	xlnx_bridge_enable(sdi->bridge);
+
+	if (sdi->bridge) {
+		for (i = 0; i < ARRAY_SIZE(xlnx_sdi_modes); i++) {
+			if (xlnx_sdi_modes[i].mode.hdisplay ==
+			    sdi->width_out_prop_val &&
+			    xlnx_sdi_modes[i].mode.vdisplay ==
+			    sdi->height_out_prop_val &&
+			    xlnx_sdi_modes[i].mode.vrefresh ==
+			    adjusted_mode->vrefresh) {
+				memcpy((char *)adjusted_mode +
+				       offsetof(struct drm_display_mode,
+						clock),
+				       &xlnx_sdi_modes[i].mode.clock,
+				       SDI_TIMING_PARAMS_SIZE);
+				break;
+			}
+		}
+	}
+
+	xlnx_sdi_setup(sdi);
+	xlnx_sdi_set_config_parameters(sdi);
+
+	/* set st352 payloads */
+	payload = xlnx_sdi_calc_st352_payld(sdi, adjusted_mode);
+	dev_dbg(sdi->dev, "payload : %0x\n", payload);
+
+	for (i = 0; i < sdi->sdi_data_strm_prop_val / 2; i++) {
+		if (sdi->sdi_mod_prop_val == XSDI_MODE_3GB)
+			payload |= (i << 1) << XSDI_CH_SHIFT;
+		xlnx_sdi_set_payload_data(sdi, i, payload);
+	}
+
+	/* UHDSDI is fixed 2 pixels per clock, horizontal timings div by 2 */
+	vm.hactive = adjusted_mode->hdisplay / PIXELS_PER_CLK;
+	vm.hfront_porch = (adjusted_mode->hsync_start -
+			  adjusted_mode->hdisplay) / PIXELS_PER_CLK;
+	vm.hback_porch = (adjusted_mode->htotal -
+			 adjusted_mode->hsync_end) / PIXELS_PER_CLK;
+	vm.hsync_len = (adjusted_mode->hsync_end -
+		       adjusted_mode->hsync_start) / PIXELS_PER_CLK;
+
+	vm.vactive = adjusted_mode->vdisplay;
+	if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {
+		vm.vfront_porch = adjusted_mode->vsync_start / 2 -
+				  adjusted_mode->vdisplay;
+		vm.vback_porch = (adjusted_mode->vtotal -
+				  adjusted_mode->vsync_end) / 2;
+		vm.vsync_len = (adjusted_mode->vsync_end -
+				adjusted_mode->vsync_start) / 2;
+	} else {
+		vm.vfront_porch = adjusted_mode->vsync_start -
+				  adjusted_mode->vdisplay;
+		vm.vback_porch = adjusted_mode->vtotal -
+				 adjusted_mode->vsync_end;
+		vm.vsync_len = adjusted_mode->vsync_end -
+			       adjusted_mode->vsync_start;
+	}
+
+	vm.flags = 0;
+	if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
+		vm.flags |= DISPLAY_FLAGS_INTERLACED;
+	if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
+		vm.flags |= DISPLAY_FLAGS_HSYNC_LOW;
+	if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
+		vm.flags |= DISPLAY_FLAGS_VSYNC_LOW;
+
+	do {
+		sditx_blank = (adjusted_mode->hsync_start -
+			       adjusted_mode->hdisplay) +
+			      (adjusted_mode->hsync_end -
+			       adjusted_mode->hsync_start) +
+			      (adjusted_mode->htotal -
+			       adjusted_mode->hsync_end);
+
+		vtc_blank = (vm.hfront_porch + vm.hback_porch +
+			     vm.hsync_len) * PIXELS_PER_CLK;
+
+		if (vtc_blank != sditx_blank)
+			vm.hfront_porch++;
+	} while (vtc_blank < sditx_blank);
+
+	vm.pixelclock = adjusted_mode->clock * 1000;
+
+	/* parameters for sdi audio */
+	sdi->video_mode.vdisplay = adjusted_mode->vdisplay;
+	sdi->video_mode.hdisplay = adjusted_mode->hdisplay;
+	sdi->video_mode.vrefresh = adjusted_mode->vrefresh;
+	sdi->video_mode.flags = adjusted_mode->flags;
+
+	xlnx_stc_sig(sdi->base, &vm);
+}
+
+static void xlnx_sdi_commit(struct drm_encoder *encoder)
+{
+	struct xlnx_sdi *sdi = encoder_to_sdi(encoder);
+	long ret;
+
+	dev_dbg(sdi->dev, "%s\n", __func__);
+	xlnx_sdi_set_display_enable(sdi);
+	ret = wait_event_interruptible_timeout(sdi->wait_event,
+					       sdi->event_received,
+					       usecs_to_jiffies(GT_TIMEOUT));
+	if (!ret) {
+		dev_err(sdi->dev, "Timeout: GT interrupt not received\n");
+		return;
+	}
+	sdi->event_received = false;
+	/* enable sdi bridge, timing controller and Axi4s_vid_out_ctrl */
+	xlnx_sdi_en_bridge(sdi);
+	xlnx_stc_enable(sdi->base);
+	xlnx_sdi_en_axi4s(sdi);
+}
+
+static void xlnx_sdi_disable(struct drm_encoder *encoder)
+{
+	struct xlnx_sdi *sdi = encoder_to_sdi(encoder);
+
+	if (sdi->bridge)
+		xlnx_bridge_disable(sdi->bridge);
+
+	xlnx_sdi_set_display_disable(sdi);
+	xlnx_stc_disable(sdi->base);
+}
+
+static const struct drm_encoder_helper_funcs xlnx_sdi_encoder_helper_funcs = {
+	.atomic_mode_set	= xlnx_sdi_encoder_atomic_mode_set,
+	.enable			= xlnx_sdi_commit,
+	.disable		= xlnx_sdi_disable,
+};
+
+static const struct drm_encoder_funcs xlnx_sdi_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+static int xlnx_sdi_bind(struct device *dev, struct device *master,
+			 void *data)
+{
+	struct xlnx_sdi *sdi = dev_get_drvdata(dev);
+	struct drm_encoder *encoder = &sdi->encoder;
+	struct drm_device *drm_dev = data;
+	int ret;
+
+	/*
+	 * TODO: The possible CRTCs are 1 now as per current implementation of
+	 * SDI tx drivers. DRM framework can support more than one CRTCs and
+	 * SDI driver can be enhanced for that.
+	 */
+	encoder->possible_crtcs = 1;
+
+	drm_encoder_init(drm_dev, encoder, &xlnx_sdi_encoder_funcs,
+			 DRM_MODE_ENCODER_TMDS, NULL);
+
+	drm_encoder_helper_add(encoder, &xlnx_sdi_encoder_helper_funcs);
+
+	ret = xlnx_sdi_create_connector(encoder);
+	if (ret) {
+		dev_err(sdi->dev, "fail creating connector, ret = %d\n", ret);
+		drm_encoder_cleanup(encoder);
+	}
+	return ret;
+}
+
+static void xlnx_sdi_unbind(struct device *dev, struct device *master,
+			    void *data)
+{
+	struct xlnx_sdi *sdi = dev_get_drvdata(dev);
+
+	xlnx_sdi_set_display_disable(sdi);
+	xlnx_stc_disable(sdi->base);
+	drm_encoder_cleanup(&sdi->encoder);
+	drm_connector_cleanup(&sdi->connector);
+	xlnx_bridge_disable(sdi->bridge);
+}
+
+static const struct component_ops xlnx_sdi_component_ops = {
+	.bind	= xlnx_sdi_bind,
+	.unbind	= xlnx_sdi_unbind,
+};
+
+static int xlnx_sdi_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct xlnx_sdi *sdi;
+	struct device_node *vpss_node;
+	int ret, irq;
+	struct device_node *ports, *port;
+	u32 nports = 0, portmask = 0;
+	unsigned long clkrate = 0;
+	enum gpiod_flags flags;
+
+	sdi = devm_kzalloc(dev, sizeof(*sdi), GFP_KERNEL);
+	if (!sdi)
+		return -ENOMEM;
+
+	sdi->dev = dev;
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	sdi->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(sdi->base)) {
+		dev_err(dev, "failed to remap io region\n");
+		return PTR_ERR(sdi->base);
+	}
+	platform_set_drvdata(pdev, sdi);
+
+	sdi->axi_clk = devm_clk_get(dev, "s_axi_aclk");
+	if (IS_ERR(sdi->axi_clk)) {
+		ret = PTR_ERR(sdi->axi_clk);
+		dev_err(dev, "failed to get s_axi_aclk %d\n", ret);
+		return ret;
+	}
+
+	sdi->sditx_clk = devm_clk_get(dev, "sdi_tx_clk");
+	if (IS_ERR(sdi->sditx_clk)) {
+		ret = PTR_ERR(sdi->sditx_clk);
+		dev_err(dev, "failed to get sdi_tx_clk %d\n", ret);
+		return ret;
+	}
+
+	sdi->vidin_clk = devm_clk_get(dev, "video_in_clk");
+	if (IS_ERR(sdi->vidin_clk)) {
+		ret = PTR_ERR(sdi->vidin_clk);
+		dev_err(dev, "failed to get video_in_clk %d\n", ret);
+		return ret;
+	}
+
+	ret = clk_prepare_enable(sdi->axi_clk);
+	if (ret) {
+		dev_err(dev, "failed to enable axi_clk %d\n", ret);
+		return ret;
+	}
+
+	ret = clk_prepare_enable(sdi->sditx_clk);
+	if (ret) {
+		dev_err(dev, "failed to enable sditx_clk %d\n", ret);
+		goto err_disable_axi_clk;
+	}
+
+	ret = clk_prepare_enable(sdi->vidin_clk);
+	if (ret) {
+		dev_err(dev, "failed to enable vidin_clk %d\n", ret);
+		goto err_disable_sditx_clk;
+	}
+
+	sdi->qpll1_enabled = of_property_read_bool(sdi->dev->of_node,
+						   "xlnx,qpll1_enabled");
+
+	sdi->picxo_enabled = of_property_read_bool(sdi->dev->of_node,
+						   "xlnx,picxo_enabled");
+	dev_dbg(dev, "sdi-tx: value of qpll1_en = %d picxo_en = %d\n",
+		sdi->qpll1_enabled, sdi->picxo_enabled);
+
+	if (sdi->qpll1_enabled)
+		flags = GPIOD_OUT_LOW;
+	else
+		flags = GPIOD_OUT_HIGH;
+
+	sdi->gt_rst_gpio = devm_gpiod_get_optional(&pdev->dev, "phy-reset",
+						   flags);
+
+	if (IS_ERR(sdi->gt_rst_gpio)) {
+		ret = PTR_ERR(sdi->gt_rst_gpio);
+		if (ret != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "Unable to get phy gpio\n");
+		goto err_disable_vidin_clk;
+	}
+
+	ret = clk_set_rate(sdi->sditx_clk, CLK_RATE);
+	if (ret)
+		dev_err(sdi->dev, "failed to set clk rate = %lu\n", CLK_RATE);
+
+	clkrate = clk_get_rate(sdi->sditx_clk);
+	dev_dbg(sdi->dev, "clkrate = %lu\n", clkrate);
+
+	/* in case all "port" nodes are grouped under a "ports" node */
+	ports = of_get_child_by_name(sdi->dev->of_node, "ports");
+	if (!ports) {
+		dev_dbg(dev, "Searching for port nodes in device node.\n");
+		ports = sdi->dev->of_node;
+	}
+
+	for_each_child_of_node(ports, port) {
+		struct device_node *endpoint;
+		u32 index;
+
+		if (!port->name || of_node_cmp(port->name, "port")) {
+			dev_dbg(dev, "port name is null or node name is not port!\n");
+			continue;
+		}
+
+		endpoint = of_get_next_child(port, NULL);
+		if (!endpoint) {
+			dev_err(dev, "No remote port at %s\n", port->name);
+			of_node_put(endpoint);
+			ret = -EINVAL;
+			goto err_disable_vidin_clk;
+		}
+
+		of_node_put(endpoint);
+
+		ret = of_property_read_u32(port, "reg", &index);
+		if (ret) {
+			dev_err(dev, "reg property not present - %d\n", ret);
+			goto err_disable_vidin_clk;
+		}
+
+		portmask |= (1 << index);
+
+		nports++;
+	}
+
+	if (nports == 2 && portmask & 0x3) {
+		dev_dbg(dev, "enable ancillary port\n");
+		sdi->enable_anc_data = true;
+	} else if (nports == 1 && portmask & 0x1) {
+		dev_dbg(dev, "no ancillary port\n");
+		sdi->enable_anc_data = false;
+	} else {
+		dev_err(dev, "Incorrect dt node!\n");
+		ret = -EINVAL;
+		goto err_disable_vidin_clk;
+	}
+
+	sdi->enable_st352_chroma = of_property_read_bool(sdi->dev->of_node,
+							 "xlnx,tx-insert-c-str-st352");
+
+	/* disable interrupt */
+	xlnx_sdi_writel(sdi->base, XSDI_TX_GLBL_IER, 0);
+	irq = platform_get_irq_byname(pdev, "sdi_tx_irq");
+	if (irq < 0) {
+		/*
+		 * If there is no IRQ with this name, try to get the first
+		 * IRQ defined in the device tree.
+		 */
+		irq = platform_get_irq(pdev, 0);
+		if (irq < 0) {
+			ret = irq;
+			goto err_disable_vidin_clk;
+		}
+	}
+
+	ret = devm_request_threaded_irq(sdi->dev, irq, NULL,
+					xlnx_sdi_irq_handler, IRQF_ONESHOT,
+					dev_name(sdi->dev), sdi);
+	if (ret < 0)
+		goto err_disable_vidin_clk;
+
+	/* initialize the wait queue for GT reset event */
+	init_waitqueue_head(&sdi->wait_event);
+
+	/* Bridge support */
+	vpss_node = of_parse_phandle(sdi->dev->of_node, "xlnx,vpss", 0);
+	if (vpss_node) {
+		sdi->bridge = of_xlnx_bridge_get(vpss_node);
+		if (!sdi->bridge) {
+			dev_info(sdi->dev, "Didn't get bridge instance\n");
+			ret = -EPROBE_DEFER;
+			goto err_disable_vidin_clk;
+		}
+	}
+
+	/* video mode properties needed by audio driver are shared to audio
+	 * driver through a pointer in platform data. This will be used in
+	 * audio driver. The solution may be needed to modify/extend to avoid
+	 * probable error scenarios
+	 */
+	pdev->dev.platform_data = &sdi->video_mode;
+	/* Initialize to IP default value */
+	sdi->prev_eotf = XST352_BYTE2_EOTF_SDRTV;
+
+	ret = component_add(dev, &xlnx_sdi_component_ops);
+	if (ret < 0)
+		goto err_disable_vidin_clk;
+
+	return ret;
+
+err_disable_vidin_clk:
+	clk_disable_unprepare(sdi->vidin_clk);
+err_disable_sditx_clk:
+	clk_disable_unprepare(sdi->sditx_clk);
+err_disable_axi_clk:
+	clk_disable_unprepare(sdi->axi_clk);
+
+	return ret;
+}
+
+static int xlnx_sdi_remove(struct platform_device *pdev)
+{
+	struct xlnx_sdi *sdi = platform_get_drvdata(pdev);
+
+	component_del(&pdev->dev, &xlnx_sdi_component_ops);
+	clk_disable_unprepare(sdi->vidin_clk);
+	clk_disable_unprepare(sdi->sditx_clk);
+	clk_disable_unprepare(sdi->axi_clk);
+
+	return 0;
+}
+
+static const struct of_device_id xlnx_sdi_of_match[] = {
+	{ .compatible = "xlnx,sdi-tx"},
+	{ }
+};
+MODULE_DEVICE_TABLE(of, xlnx_sdi_of_match);
+
+static struct platform_driver sdi_tx_driver = {
+	.probe = xlnx_sdi_probe,
+	.remove = xlnx_sdi_remove,
+	.driver = {
+		.name = "xlnx-sdi-tx",
+		.of_match_table = xlnx_sdi_of_match,
+	},
+};
+
+module_platform_driver(sdi_tx_driver);
+
+MODULE_AUTHOR("Saurabh Sengar <saurabhs@xilinx.com>");
+MODULE_DESCRIPTION("Xilinx FPGA SDI Tx Driver");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/xlnx/xlnx_sdi_modes.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/xlnx/xlnx_sdi_modes.h
@@ -0,0 +1,411 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx FPGA SDI modes timing values for various
+ * resolutions
+ *
+ * Copyright (c) 2017 Xilinx Pvt., Ltd
+ *
+ * Contacts: Saurabh Sengar <saurabhs@xilinx.com>
+ */
+
+#ifndef _XLNX_SDI_MODES_H_
+#define _XLNX_SDI_MODES_H_
+
+/**
+ * struct xlnx_sdi_display_config - SDI supported modes structure
+ * @mode: drm display mode
+ * @st352_byt2: st352 byte 2 value
+ *		index 0 : value for integral fps
+ *		index 1 : value for fractional fps
+ * @st352_byt1: st352 byte 1 value
+ *		index 0 : value for HD mode
+ *		index 1 : value for SD mode
+ *		index 2 : value for 3GA
+ *		index 3 : value for 3GB
+ *		index 4 : value for 6G
+ *		index 5 : value for 12G
+ */
+struct xlnx_sdi_display_config {
+	struct drm_display_mode mode;
+	u8 st352_byt2[2];
+	u8 st352_byt1[6];
+};
+
+/*
+ * xlnx_sdi_modes - SDI DRM modes
+ */
+static const struct xlnx_sdi_display_config xlnx_sdi_modes[] = {
+	/* 0 - dummy, VICs start at 1 */
+	{ },
+	/* SD: 720x486i@59.94Hz */
+	{{ DRM_MODE("720x486i", DRM_MODE_TYPE_DRIVER, 13500, 720, 739,
+		   801, 858, 0, 486, 494, 500, 525, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
+		   DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
+		   .vrefresh = 60, }, {0x7, 0x6},
+		   {0x81, 0x81, 0x81, 0x81, 0x81, 0x81} },
+	/* SD: 720x576i@50Hz */
+	{{ DRM_MODE("720x576i", DRM_MODE_TYPE_DRIVER, 13500, 720, 732,
+		   795, 864, 0, 576, 580, 586, 625, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
+		   DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLCLK),
+		   .vrefresh = 50, }, {0x9, 0x9},
+		   {0x81, 0x81, 0x81, 0x81, 0x81, 0x81} },
+	/* HD: 1280x720@25Hz */
+	{{ DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 2250,
+		   2990, 3960, 0, 720, 725, 730, 750, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 25, }, {0x5, 0x5},
+		   {0x84, 0x84, 0x88, 0x84, 0x84, 0x84} },
+	/* HD: 1280x720@24Hz */
+	{{ DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 2250,
+		   3155, 4125, 0, 720, 725, 730, 750, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 24, }, {0x3, 0x2},
+		   {0x84, 0x84, 0x88, 0x84, 0x84, 0x84} },
+	/* HD: 1280x720@30Hz */
+	 {{ DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 2250,
+		   2330, 3300, 0, 720, 725, 730, 750, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 30, }, {0x7, 0x6},
+		   {0x84, 0x84, 0x88, 0x84, 0x84, 0x84} },
+	/* HD: 1280x720@50Hz */
+	{{ DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1720,
+		   1760, 1980, 0, 720, 725, 730, 750, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 50, }, {0x9, 0x9},
+		   {0x84, 0x84, 0x88, 0x84, 0x84, 0x84} },
+	/* HD: 1280x720@60Hz */
+	{{ DRM_MODE("1280x720", DRM_MODE_TYPE_DRIVER, 74250, 1280, 1390,
+		   1430, 1650, 0, 720, 725, 730, 750, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 60, }, {0xB, 0xA},
+		   {0x84, 0x84, 0x88, 0x84, 0x84, 0x84} },
+	/* HD: 1920x1080@24Hz */
+	{{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2558,
+		   2602, 2750, 0, 1080, 1084, 1089, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 24, }, {0x3, 0x2},
+		   {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
+	/* HD: 1920x1080@25Hz */
+	{{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2448,
+		   2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 25, }, {0x5, 0x5},
+		   {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
+	/* HD: 1920x1080@30Hz */
+	{{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2008,
+		   2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 30, }, {0x7, 0x6},
+		   {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
+	/* HD: 1920x1080i@48Hz */
+	{{ DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2291,
+		   2379, 2750, 0, 1080, 1084, 1094, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
+		   DRM_MODE_FLAG_INTERLACE),
+		   .vrefresh = 48, }, {0x3, 0x2},
+		   {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
+	/* HD: 1920x1080i@50Hz */
+	{{ DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2448,
+		   2492, 2640, 0, 1080, 1084, 1094, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
+		   DRM_MODE_FLAG_INTERLACE),
+		   .vrefresh = 50, }, {0x5, 0x5},
+		   {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
+	/* HD: 1920x1080i@60Hz */
+	{{ DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2008,
+		   2052, 2200, 0, 1080, 1084, 1094, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
+		   DRM_MODE_FLAG_INTERLACE),
+		   .vrefresh = 60, }, {0x7, 0x6},
+		   {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
+	/* HD: 1920x1080i@59.94Hz */
+	{{ DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 74175, 1920, 2008,
+		   2052, 2200, 0, 1080, 1084, 1094, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
+		   DRM_MODE_FLAG_INTERLACE),
+		   .vrefresh = 60, }, {0x7, 0x6},
+		   {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
+	/* HD: 1920x1080sf@24Hz */
+	{{ DRM_MODE("1920x1080sf", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2291,
+		   2379, 2750, 0, 1080, 1084, 1094, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
+		   DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLSCAN),
+		   .vrefresh = 48, }, {0x3, 0x2},
+		   {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
+	/* HD: 1920x1080sf@25Hz */
+	{{ DRM_MODE("1920x1080sf", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2448,
+		   2492, 2640, 0, 1080, 1084, 1094, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
+		   DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLSCAN),
+		   .vrefresh = 50, }, {0x5, 0x5},
+		   {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
+	/* HD: 1920x1080sf@30Hz */
+	{{ DRM_MODE("1920x1080sf", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2008,
+		   2052, 2200, 0, 1080, 1084, 1094, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
+		   DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLSCAN),
+		   .vrefresh = 60, }, {0x7, 0x6},
+		   {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
+	/* HD: 2048x1080i@48Hz */
+	{{ DRM_MODE("2048x1080i", DRM_MODE_TYPE_DRIVER, 74250, 2048, 2377,
+		   2421, 2750, 0, 1080, 1084, 1094, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
+		   DRM_MODE_FLAG_INTERLACE),
+		   .vrefresh = 48, }, {0x3, 0x2},
+		   {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
+	/* HD: 2048x1080i@50Hz */
+	{{ DRM_MODE("2048x1080i", DRM_MODE_TYPE_DRIVER, 74250, 2048, 2322,
+		   2366, 2640, 0, 1080, 1084, 1094, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
+		   DRM_MODE_FLAG_INTERLACE),
+		   .vrefresh = 50, }, {0x5, 0x5},
+		   {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
+	/* HD: 2048x1080i@60Hz */
+	{{ DRM_MODE("2048x1080i", DRM_MODE_TYPE_DRIVER, 74250, 2048, 2114,
+		   2134, 2200, 0, 1080, 1084, 1094, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
+		   DRM_MODE_FLAG_INTERLACE),
+		   .vrefresh = 60, }, {0x7, 0x6},
+		   {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
+	/* HD: 2048x1080sf@24Hz */
+	{{ DRM_MODE("2048x1080sf", DRM_MODE_TYPE_DRIVER, 74250, 2048, 2377,
+		   2421, 2750, 0, 1080, 1084, 1094, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
+		   DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLSCAN),
+		   .vrefresh = 48, }, {0x3, 0x2},
+		   {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
+	/* HD: 2048x1080sf@25Hz */
+	{{ DRM_MODE("2048x1080sf", DRM_MODE_TYPE_DRIVER, 74250, 2048, 2322,
+		   2366, 2640, 0, 1080, 1084, 1094, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
+		   DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLSCAN),
+		   .vrefresh = 50, }, {0x5, 0x5},
+		   {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
+	/* HD: 2048x1080sf@30Hz */
+	{{ DRM_MODE("2048x1080sf", DRM_MODE_TYPE_DRIVER, 74250, 2048, 2114,
+		   2134, 2200, 0, 1080, 1084, 1094, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
+		   DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLSCAN),
+		   .vrefresh = 60, }, {0x7, 0x6},
+		   {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
+	/* HD: 2048x1080@30Hz */
+	{{ DRM_MODE("2048x1080", DRM_MODE_TYPE_DRIVER, 74250, 2048, 2114,
+		   2134, 2200, 0, 1080, 1084, 1089, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 30, }, {0x7, 0x6},
+		   {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
+	/* HD: 2048x1080@25Hz */
+	{{ DRM_MODE("2048x1080", DRM_MODE_TYPE_DRIVER, 74250, 2048, 2448,
+		   2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 25, }, {0x5, 0x5},
+		   {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
+	/* HD: 2048x1080@24Hz */
+	{{ DRM_MODE("2048x1080", DRM_MODE_TYPE_DRIVER, 74250, 2048, 2558,
+		   2602, 2750, 0, 1080, 1084, 1089, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 24, }, {0x3, 0x2},
+		   {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
+	/* 3G: 1920x1080@48Hz */
+	{{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2558,
+		   2602, 2750, 0, 1080, 1084, 1089, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 48, }, {0x8, 0x4},
+		   {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
+	/* 3G: 1920x1080@50Hz */
+	{{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2448,
+		   2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 50, }, {0x9, 0x9},
+		   {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
+	/* 3G: 1920x1080@60Hz */
+	{{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2008,
+		   2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 60, }, {0xB, 0xA},
+		   {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
+	/* 3G: 1920x1080@59.94Hz */
+	{{ DRM_MODE("1920x1080", DRM_MODE_TYPE_DRIVER, 148350, 1920, 2008,
+		   2052, 2200, 0, 1080, 1084, 1089, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 60, }, {0xB, 0xA},
+		   {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
+	/* 3G: 2048x1080@60Hz */
+	{{ DRM_MODE("2048x1080", DRM_MODE_TYPE_DRIVER, 148500, 2048, 2136,
+		   2180, 2200, 0, 1080, 1084, 1089, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 60, }, {0xB, 0xA},
+		   {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
+	/* 3G: 2048x1080@50Hz */
+	{{ DRM_MODE("2048x1080", DRM_MODE_TYPE_DRIVER, 148500, 2048, 2448,
+		   2492, 2640, 0, 1080, 1084, 1089, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 50, }, {0x9, 0x9},
+		   {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
+	/* 3G: 2048x1080@48Hz */
+	{{ DRM_MODE("2048x1080", DRM_MODE_TYPE_DRIVER, 148500, 2048, 2558,
+		   2602, 2750, 0, 1080, 1084, 1089, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 48, }, {0x8, 0x4},
+		   {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
+	/* 3G-B: 1920x1080i@96Hz */
+	{{ DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2291,
+		   2379, 2750, 0, 1080, 1084, 1094, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
+		   DRM_MODE_FLAG_INTERLACE),
+		   .vrefresh = 96, }, {0x8, 0x4},
+		   {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
+	/* 3G-B: 1920x1080i@100Hz */
+	{{ DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2448,
+		   2492, 2640, 0, 1080, 1084, 1094, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
+		   DRM_MODE_FLAG_INTERLACE),
+		   .vrefresh = 100, }, {0x9, 0x9},
+		   {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
+	/* 3G-B: 1920x1080i@120Hz */
+	{{ DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 148500, 1920, 2008,
+		   2052, 2200, 0, 1080, 1084, 1094, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
+		   DRM_MODE_FLAG_INTERLACE),
+		   .vrefresh = 120, }, {0xB, 0xA},
+		   {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
+	/* 3G-B: 2048x1080i@96Hz */
+	{{ DRM_MODE("2048x1080i", DRM_MODE_TYPE_DRIVER, 148500, 2048, 2377,
+		   2421, 2750, 0, 1080, 1084, 1094, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
+		   DRM_MODE_FLAG_INTERLACE),
+		   .vrefresh = 96, }, {0x8, 0x4},
+		   {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
+	/* 3G-B: 2048x1080i@100Hz */
+	{{ DRM_MODE("2048x1080i", DRM_MODE_TYPE_DRIVER, 148500, 2048, 2322,
+		   2366, 2640, 0, 1080, 1084, 1094, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
+		   DRM_MODE_FLAG_INTERLACE),
+		   .vrefresh = 100, }, {0x9, 0x9},
+		   {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
+	/* 3G-B: 2048x1080i@120Hz */
+	{{ DRM_MODE("2048x1080i", DRM_MODE_TYPE_DRIVER, 148500, 2048, 2114,
+		   2134, 2200, 0, 1080, 1084, 1094, 1125, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
+		   DRM_MODE_FLAG_INTERLACE),
+		   .vrefresh = 120, }, {0xB, 0xA},
+		   {0x85, 0x85, 0x89, 0x8A, 0xC1, 0xC1} },
+	/* 6G: 3840x2160@29.97Hz */
+	{{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 296704, 3840, 4016,
+		   4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 30, }, {0x7, 0x6},
+		   {0x98, 0x98, 0x97, 0x98, 0xC0, 0xCE} },
+	/* 6G: 3840x2160@30Hz */
+	{{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4016,
+		   4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 30, }, {0x7, 0x6},
+		   {0x98, 0x98, 0x97, 0x98, 0xC0, 0xCE} },
+	/* 6G: 3840x2160@25Hz */
+	{{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 4896,
+		   4984, 5280, 0, 2160, 2168, 2178, 2250, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 25, }, {0x5, 0x5},
+		   {0x98, 0x98, 0x97, 0x98, 0xC0, 0xCE} },
+	/* 6G: 3840x2160@23.98Hz */
+	{{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 296704, 3840, 5116,
+		   5204, 5500, 0, 2160, 2168, 2178, 2250, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 24, }, {0x3, 0x2},
+		   {0x98, 0x98, 0x97, 0x98, 0xC0, 0xCE} },
+	/* 6G: 3840x2160@24Hz */
+	{{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 297000, 3840, 5116,
+		   5204, 5500, 0, 2160, 2168, 2178, 2250, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 24, }, {0x3, 0x2},
+		   {0x98, 0x98, 0x97, 0x98, 0xC0, 0xCE} },
+	/* 6G: 4096x2160@23.98 */
+	{{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 296704, 4096, 5116,
+		   5204, 5500, 0, 2160, 2168, 2178, 2250, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 24, }, {0x3, 0x2},
+		   {0x98, 0x98, 0x97, 0x98, 0xC0, 0xCE} },
+	/* 6G: 4096x2160@24Hz */
+	{{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 297000, 4096, 5116,
+		   5204, 5500, 0, 2160, 2168, 2178, 2250, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 24, }, {0x3, 0x2},
+		   {0x98, 0x98, 0x97, 0x98, 0xC0, 0xCE} },
+	/* 6G: 4096x2160@25Hz */
+	{{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 297000, 4096, 5064,
+		   5152, 5280, 0, 2160, 2168, 2178, 2250, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 25, }, {0x5, 0x5},
+		   {0x98, 0x98, 0x97, 0x98, 0xC0, 0xCE} },
+	/* 6G: 4096x2160@29.97Hz */
+	{{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 296704, 4096, 4184,
+		   4272, 4400, 0, 2160, 2168, 2178, 2250, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 30, }, {0x7, 0x6},
+		   {0x98, 0x98, 0x97, 0x98, 0xC0, 0xCE} },
+	/* 6G: 4096x2160@30Hz */
+	{{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 297000, 4096, 4184,
+		   4272, 4400, 0, 2160, 2168, 2178, 2250, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 30, }, {0x7, 0x6},
+		   {0x98, 0x98, 0x97, 0x98, 0xC0, 0xCE} },
+	/* 12G: 3840x2160@48Hz */
+	{{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 5116,
+		   5204, 5500, 0, 2160, 2168, 2178, 2250, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 48, }, {0x8, 0x4},
+		   {0x98, 0x98, 0x97, 0x98, 0xC0, 0xCE} },
+	/* 12G: 3840x2160@50Hz */
+	{{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4896,
+		   4984, 5280, 0, 2160, 2168, 2178, 2250, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 50, }, {0x9, 0x9},
+		   {0x98, 0x98, 0x97, 0x98, 0xC0, 0xCE} },
+	/* 12G: 3840x2160@59.94Hz */
+	{{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 593406, 3840, 4016,
+		   4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 60, }, {0xB, 0xA},
+		   {0x98, 0x98, 0x97, 0x98, 0xC0, 0xCE} },
+	/* 12G: 3840x2160@60Hz */
+	{{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4016,
+		   4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 60, }, {0xB, 0xA},
+		   {0x98, 0x98, 0x97, 0x98, 0xC0, 0xCE} },
+	/* 12G: 4096x2160@47.95Hz */
+	{{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 593406, 4096, 5116,
+		   5204, 5500, 0, 2160, 2168, 2178, 2250, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 48, }, {0x8, 0x4},
+		   {0x98, 0x98, 0x97, 0x98, 0xC0, 0xCE} },
+	/* 12G: 4096x2160@48Hz */
+	{{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 594000, 4096, 5116,
+		   5204, 5500, 0, 2160, 2168, 2178, 2250, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 48, }, {0x8, 0x4},
+		   {0x98, 0x98, 0x97, 0x98, 0xC0, 0xCE} },
+	/* 12G: 4096x2160@50Hz */
+	{{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 594000, 4096, 5064,
+		   5152, 5280, 0, 2160, 2168, 2178, 2250, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 50, }, {0x9, 0x9},
+		   {0x98, 0x98, 0x97, 0x98, 0xC0, 0xCE} },
+	/* 12G: 4096x2160@59.94Hz */
+	{{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 593408, 4096, 4184,
+		   4272, 4400, 0, 2160, 2168, 2178, 2250, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 60, }, {0xB, 0xA},
+		   {0x98, 0x98, 0x97, 0x98, 0xC0, 0xCE} },
+	/* 12G: 4096x2160@60Hz */
+	{{ DRM_MODE("4096x2160", DRM_MODE_TYPE_DRIVER, 594000, 4096, 4184,
+		   4272, 4400, 0, 2160, 2168, 2178, 2250, 0,
+		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
+		   .vrefresh = 60, }, {0xB, 0xA},
+		   {0x98, 0x98, 0x97, 0x98, 0xC0, 0xCE} },
+};
+
+#endif /* _XLNX_SDI_MODES_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/xlnx/xlnx_sdi_timing.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/xlnx/xlnx_sdi_timing.c
@@ -0,0 +1,425 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx FPGA SDI Tx timing controller driver
+ *
+ * Copyright (c) 2017 Xilinx Pvt., Ltd
+ *
+ * Contacts: Saurabh Sengar <saurabhs@xilinx.com>
+ */
+
+#include <drm/drmP.h>
+#include <linux/device.h>
+#include <video/videomode.h>
+#include "xlnx_sdi_timing.h"
+
+/* timing controller register offsets */
+#define XSTC_CTL	0x00
+#define XSTC_STATS	0x04
+#define XSTC_ERROR	0x08
+#define XSTC_GASIZE	0x60
+#define XSTC_GENC	0x68
+#define XSTC_GPOL	0x6c
+#define XSTC_GHSIZE	0x70
+#define XSTC_GVSIZE	0x74
+#define XSTC_GHSYNC	0x78
+#define XSTC_GVBH_F0	0x7c
+#define XSTC_GVSYNC_F0	0x80
+#define XSTC_GVSH_F0	0x84
+#define XSTC_GVBH_F1	0x88
+#define XSTC_GVSYNC_F1	0x8C
+#define XSTC_GVSH_F1	0x90
+#define XSTC_GASIZE_F1	0x94
+#define XSTC_OFFSET	0x10000
+
+/* timing controller register bit */
+#define XSTC_CTL_FIP	BIT(6)	/* field id polarity */
+#define XSTC_CTL_ACP	BIT(5)	/* active chroma polarity */
+#define XSTC_CTL_AVP	BIT(4)	/* active video polarity */
+#define XSTC_CTL_HSP	BIT(3)	/* hori sync polarity */
+#define XSTC_CTL_VSP	BIT(2)	/* vert sync polarity */
+#define XSTC_CTL_HBP	BIT(1)	/* hori blank polarity */
+#define XSTC_CTL_VBP	BIT(0)	/* vert blank polarity */
+#define XSTC_CTL_FIPSS	BIT(26)	/* field id polarity source */
+#define XSTC_CTL_ACPSS	BIT(25)	/* active chroma polarity src */
+#define XSTC_CTL_AVPSS	BIT(24)	/* active video polarity src */
+#define XSTC_CTL_HSPSS	BIT(23)	/* hori sync polarity src */
+#define XSTC_CTL_VSPSS	BIT(22)	/* vert sync polarity src */
+#define XSTC_CTL_HBPSS	BIT(21)	/* hori blank polarity src */
+#define XSTC_CTL_VBPSS	BIT(20)	/* vert blank polarity src */
+#define XSTC_CTL_VCSS	BIT(18)	/* chroma src */
+#define XSTC_CTL_VASS	BIT(17)	/* vertical offset src */
+#define XSTC_CTL_VBSS	BIT(16)	/* vertical sync end src */
+#define XSTC_CTL_VSSS	BIT(15)	/* vertical sync start src */
+#define XSTC_CTL_VFSS	BIT(14)	/* vertical active size src */
+#define XSTC_CTL_VTSS	BIT(13)	/* vertical frame size src */
+#define XSTC_CTL_HBSS	BIT(11)	/* horiz sync end src */
+#define XSTC_CTL_HSSS	BIT(10)	/* horiz sync start src */
+#define XSTC_CTL_HFSS	BIT(9)	/* horiz active size src */
+#define XSTC_CTL_HTSS	BIT(8)	/* horiz frame size src */
+#define XSTC_CTL_GE	BIT(2)	/* timing generator enable */
+#define XSTC_CTL_RU	BIT(1)	/* timing register update */
+
+/* timing generator horizontal 1 */
+#define XSTC_GH1_BPSTART_MASK	GENMASK(28, 16)
+#define XSTC_GH1_BPSTART_SHIFT	16
+#define XSTC_GH1_SYNCSTART_MASK	GENMASK(12, 0)
+/* timing generator vertical 1 (filed 0) */
+#define XSTC_GV1_BPSTART_MASK	GENMASK(28, 16)
+#define XSTC_GV1_BPSTART_SHIFT	16
+#define XSTC_GV1_SYNCSTART_MASK	GENMASK(12, 0)
+/* timing generator/detector vblank/vsync horizontal offset registers */
+#define XSTC_XVXHOX_HEND_MASK	GENMASK(28, 16)
+#define XSTC_XVXHOX_HEND_SHIFT	16
+#define XSTC_XVXHOX_HSTART_MASK	GENMASK(12, 0)
+
+#define XSTC_GHFRAME_HSIZE	GENMASK(12, 0)
+#define XSTC_GVFRAME_HSIZE_F1	GENMASK(12, 0)
+#define XSTC_GA_ACTSIZE_MASK	GENMASK(12, 0)
+/* reset register bit definition */
+#define XSTC_RST		BIT(31)
+/* Interlaced bit in XSTC_GENC */
+#define XSTC_GENC_INTERL	BIT(6)
+
+/**
+ * struct xlnx_stc_polarity - timing signal polarity
+ *
+ * @field_id: field ID polarity
+ * @vblank: vblank polarity
+ * @vsync: vsync polarity
+ * @hblank: hblank polarity
+ * @hsync: hsync polarity
+ */
+struct xlnx_stc_polarity {
+	u8 field_id;
+	u8 vblank;
+	u8 vsync;
+	u8 hblank;
+	u8 hsync;
+};
+
+/**
+ * struct xlnx_stc_hori_off - timing signal horizontal offset
+ *
+ * @v0blank_hori_start: vblank horizontal start (field 0)
+ * @v0blank_hori_end: vblank horizontal end (field 0)
+ * @v0sync_hori_start: vsync horizontal start (field 0)
+ * @v0sync_hori_end: vsync horizontal end (field 0)
+ * @v1blank_hori_start: vblank horizontal start (field 1)
+ * @v1blank_hori_end: vblank horizontal end (field 1)
+ * @v1sync_hori_start: vsync horizontal start (field 1)
+ * @v1sync_hori_end: vsync horizontal end (field 1)
+ */
+struct xlnx_stc_hori_off {
+	u16 v0blank_hori_start;
+	u16 v0blank_hori_end;
+	u16 v0sync_hori_start;
+	u16 v0sync_hori_end;
+	u16 v1blank_hori_start;
+	u16 v1blank_hori_end;
+	u16 v1sync_hori_start;
+	u16 v1sync_hori_end;
+};
+
+/**
+ * xlnx_stc_writel - Memory mapped SDI Tx timing controller write
+ * @base:	Pointer to SDI Tx registers base
+ * @offset:	Register offset
+ * @val:	value to be written
+ *
+ * This function writes the value to SDI TX timing controller registers
+ */
+static inline void xlnx_stc_writel(void __iomem *base, int offset, u32 val)
+{
+	writel(val, base + XSTC_OFFSET + offset);
+}
+
+/**
+ * xlnx_stc_readl - Memory mapped timing controllerregister read
+ * @base:	Pointer to SDI Tx registers base
+ * @offset:	Register offset
+ *
+ * Return: The contents of the SDI Tx timing controller register
+ *
+ * This function returns the contents of the corresponding SDI Tx register.
+ */
+static inline u32 xlnx_stc_readl(void __iomem *base, int offset)
+{
+	return readl(base + XSTC_OFFSET + offset);
+}
+
+/**
+ * xlnx_stc_enable - Enable timing controller
+ * @base:	Base address of SDI Tx subsystem
+ *
+ * This function enables the SDI Tx subsystem's timing controller
+ */
+void xlnx_stc_enable(void __iomem *base)
+{
+	u32 reg;
+
+	reg = xlnx_stc_readl(base, XSTC_CTL);
+	xlnx_stc_writel(base, XSTC_CTL, reg | XSTC_CTL_GE);
+}
+
+/**
+ * xlnx_stc_disable - Disable timing controller
+ * @base:	Base address of SDI Tx subsystem
+ *
+ * This function disables the SDI Tx subsystem's timing controller
+ */
+void xlnx_stc_disable(void __iomem *base)
+{
+	u32 reg;
+
+	reg = xlnx_stc_readl(base, XSTC_CTL);
+	xlnx_stc_writel(base, XSTC_CTL, reg & ~XSTC_CTL_GE);
+}
+
+/**
+ * xlnx_stc_reset - Reset timing controller
+ * @base:	Base address of SDI Tx subsystem
+ *
+ * This function resets the SDI Tx subsystem's timing controller
+ */
+void xlnx_stc_reset(void __iomem *base)
+{
+	u32 reg;
+
+	xlnx_stc_writel(base, XSTC_CTL, XSTC_RST);
+
+	/* enable register update */
+	reg = xlnx_stc_readl(base, XSTC_CTL);
+	xlnx_stc_writel(base, XSTC_CTL, reg | XSTC_CTL_RU);
+}
+
+/**
+ * xlnx_stc_polarity - Configure timing signal polarity
+ * @base:	Base address of SDI Tx subsystem
+ * @polarity:	timing signal polarity data
+ *
+ * This function configure timing signal polarity
+ */
+static void xlnx_stc_polarity(void __iomem *base,
+			      struct xlnx_stc_polarity *polarity)
+{
+	u32 reg = 0;
+
+	reg = XSTC_CTL_ACP;
+	reg |= XSTC_CTL_AVP;
+	if (polarity->field_id)
+		reg |= XSTC_CTL_FIP;
+	if (polarity->vblank)
+		reg |= XSTC_CTL_VBP;
+	if (polarity->vsync)
+		reg |= XSTC_CTL_VSP;
+	if (polarity->hblank)
+		reg |= XSTC_CTL_HBP;
+	if (polarity->hsync)
+		reg |= XSTC_CTL_HSP;
+
+	xlnx_stc_writel(base, XSTC_GPOL, reg);
+}
+
+/**
+ * xlnx_stc_hori_off - Configure horzontal timing offset
+ * @base:	Base address of SDI Tx subsystem
+ * @hori_off:	horizontal offset configuration data
+ * @flags:	Display flags
+ *
+ * This function configure horizontal offset
+ */
+static void xlnx_stc_hori_off(void __iomem *base,
+			      struct xlnx_stc_hori_off *hori_off,
+			      enum display_flags flags)
+{
+	u32 reg;
+
+	/* Calculate and update Generator VBlank Hori field 0 */
+	reg = hori_off->v0blank_hori_start & XSTC_XVXHOX_HSTART_MASK;
+	reg |= (hori_off->v0blank_hori_end << XSTC_XVXHOX_HEND_SHIFT) &
+		XSTC_XVXHOX_HEND_MASK;
+	xlnx_stc_writel(base, XSTC_GVBH_F0, reg);
+
+	/* Calculate and update Generator VSync Hori field 0 */
+	reg = hori_off->v0sync_hori_start & XSTC_XVXHOX_HSTART_MASK;
+	reg |= (hori_off->v0sync_hori_end << XSTC_XVXHOX_HEND_SHIFT) &
+		XSTC_XVXHOX_HEND_MASK;
+	xlnx_stc_writel(base, XSTC_GVSH_F0, reg);
+
+	/* Calculate and update Generator VBlank Hori field 1 */
+	if (flags & DISPLAY_FLAGS_INTERLACED) {
+		reg = hori_off->v1blank_hori_start & XSTC_XVXHOX_HSTART_MASK;
+		reg |= (hori_off->v1blank_hori_end << XSTC_XVXHOX_HEND_SHIFT) &
+			XSTC_XVXHOX_HEND_MASK;
+		xlnx_stc_writel(base, XSTC_GVBH_F1, reg);
+	}
+
+	/* Calculate and update Generator VBlank Hori field 1 */
+	if (flags & DISPLAY_FLAGS_INTERLACED) {
+		reg = hori_off->v1sync_hori_start & XSTC_XVXHOX_HSTART_MASK;
+		reg |= (hori_off->v1sync_hori_end << XSTC_XVXHOX_HEND_SHIFT) &
+			XSTC_XVXHOX_HEND_MASK;
+		xlnx_stc_writel(base, XSTC_GVSH_F1, reg);
+	}
+}
+
+/**
+ * xlnx_stc_src - Configure timing source
+ * @base:	Base address of SDI Tx subsystem
+ *
+ * This function configure timing source
+ */
+static void xlnx_stc_src(void __iomem *base)
+{
+	u32 reg;
+
+	reg = xlnx_stc_readl(base, XSTC_CTL);
+	reg |= XSTC_CTL_VCSS;
+	reg |= XSTC_CTL_VASS;
+	reg |= XSTC_CTL_VBSS;
+	reg |= XSTC_CTL_VSSS;
+	reg |= XSTC_CTL_VFSS;
+	reg |= XSTC_CTL_VTSS;
+	reg |= XSTC_CTL_HBSS;
+	reg |= XSTC_CTL_HSSS;
+	reg |= XSTC_CTL_HFSS;
+	reg |= XSTC_CTL_HTSS;
+	xlnx_stc_writel(base, XSTC_CTL, reg);
+}
+
+/**
+ * xlnx_stc_sig - Generates timing signal
+ * @base:	Base address of SDI Tx subsystem
+ * @vm:		video mode
+ *
+ * This function generated the timing for given vide mode
+ */
+void xlnx_stc_sig(void __iomem *base, struct videomode *vm)
+{
+	u32 reg;
+	u32 htotal, hactive, hsync_start, hbackporch_start;
+	u32 vtotal, vactive, vsync_start, vbackporch_start;
+	struct xlnx_stc_hori_off hori_off;
+	struct xlnx_stc_polarity polarity;
+
+	reg = xlnx_stc_readl(base, XSTC_CTL);
+	xlnx_stc_writel(base, XSTC_CTL, reg & ~XSTC_CTL_RU);
+
+	htotal = vm->hactive + vm->hfront_porch + vm->hsync_len +
+		 vm->hback_porch;
+	vtotal = vm->vactive + vm->vfront_porch + vm->vsync_len +
+		 vm->vback_porch;
+	hactive = vm->hactive;
+	vactive = vm->vactive;
+	hsync_start = vm->hactive + vm->hfront_porch;
+	vsync_start = vm->vactive + vm->vfront_porch;
+	hbackporch_start = hsync_start + vm->hsync_len;
+	vbackporch_start = vsync_start + vm->vsync_len;
+
+	DRM_DEBUG_DRIVER("ha: %d, va: %d\n", hactive, vactive);
+	DRM_DEBUG_DRIVER("hs: %d, hb: %d\n", hsync_start, hbackporch_start);
+	DRM_DEBUG_DRIVER("vs: %d, vb: %d\n", vsync_start, vbackporch_start);
+	DRM_DEBUG_DRIVER("ht: %d, vt: %d\n", htotal, vtotal);
+
+	reg = htotal & XSTC_GHFRAME_HSIZE;
+	xlnx_stc_writel(base, XSTC_GHSIZE, reg);
+	reg = vtotal & XSTC_GVFRAME_HSIZE_F1;
+	if (vm->flags & DISPLAY_FLAGS_INTERLACED) {
+		if (vm->pixelclock == 148500000)
+			reg |= (reg + 2) <<
+				XSTC_GV1_BPSTART_SHIFT;
+		else
+			reg |= (reg + 1) <<
+				XSTC_GV1_BPSTART_SHIFT;
+	} else {
+		reg |= reg << XSTC_GV1_BPSTART_SHIFT;
+	}
+	xlnx_stc_writel(base, XSTC_GVSIZE, reg);
+	reg = hactive & XSTC_GA_ACTSIZE_MASK;
+	reg |= (vactive & XSTC_GA_ACTSIZE_MASK) << 16;
+	xlnx_stc_writel(base, XSTC_GASIZE, reg);
+
+	if (vm->flags & DISPLAY_FLAGS_INTERLACED) {
+		if (vactive == 243)
+			reg = ((vactive + 1) & XSTC_GA_ACTSIZE_MASK) << 16;
+		else
+			reg = (vactive & XSTC_GA_ACTSIZE_MASK) << 16;
+		xlnx_stc_writel(base, XSTC_GASIZE_F1, reg);
+	}
+
+	reg = hsync_start & XSTC_GH1_SYNCSTART_MASK;
+	reg |= (hbackporch_start << XSTC_GH1_BPSTART_SHIFT) &
+	       XSTC_GH1_BPSTART_MASK;
+	xlnx_stc_writel(base, XSTC_GHSYNC, reg);
+	reg = vsync_start & XSTC_GV1_SYNCSTART_MASK;
+	reg |= (vbackporch_start << XSTC_GV1_BPSTART_SHIFT) &
+	       XSTC_GV1_BPSTART_MASK;
+
+	/*
+	 * Fix the Vsync_vstart and vsync_vend of Field 0
+	 * for all interlaced modes including 3GB.
+	 */
+	if (vm->flags & DISPLAY_FLAGS_INTERLACED)
+		reg = ((((reg & XSTC_GV1_BPSTART_MASK) >>
+			XSTC_GV1_BPSTART_SHIFT) - 1) <<
+			XSTC_GV1_BPSTART_SHIFT) |
+			((reg & XSTC_GV1_SYNCSTART_MASK) - 1);
+
+	xlnx_stc_writel(base, XSTC_GVSYNC_F0, reg);
+
+	/*
+	 * Fix the Vsync_vstart and vsync_vend of Field 1
+	 * for interlaced and 3GB modes.
+	 */
+	if (vm->flags & DISPLAY_FLAGS_INTERLACED) {
+		if (vm->pixelclock == 148500000)
+			/* Revert and increase by 1 for 3GB mode */
+			reg = ((((reg & XSTC_GV1_BPSTART_MASK) >>
+				XSTC_GV1_BPSTART_SHIFT) + 2) <<
+				XSTC_GV1_BPSTART_SHIFT) |
+				((reg & XSTC_GV1_SYNCSTART_MASK) + 2);
+		else
+			/* Only revert the reduction */
+			reg = ((((reg & XSTC_GV1_BPSTART_MASK) >>
+				XSTC_GV1_BPSTART_SHIFT) + 1) <<
+				XSTC_GV1_BPSTART_SHIFT) |
+				((reg & XSTC_GV1_SYNCSTART_MASK) + 1);
+	}
+
+	hori_off.v0blank_hori_start = hactive;
+	hori_off.v0blank_hori_end = hactive;
+	hori_off.v0sync_hori_start = hsync_start;
+	hori_off.v0sync_hori_end = hsync_start;
+	hori_off.v1blank_hori_start = hactive;
+	hori_off.v1blank_hori_end = hactive;
+
+	if (vm->flags & DISPLAY_FLAGS_INTERLACED) {
+		hori_off.v1sync_hori_start = hsync_start - (htotal / 2);
+		hori_off.v1sync_hori_end = hsync_start - (htotal / 2);
+		xlnx_stc_writel(base, XSTC_GVSYNC_F1, reg);
+		reg = xlnx_stc_readl(base, XSTC_GENC)
+				     | XSTC_GENC_INTERL;
+		xlnx_stc_writel(base, XSTC_GENC, reg);
+	} else {
+		hori_off.v1sync_hori_start = hsync_start;
+		hori_off.v1sync_hori_end = hsync_start;
+		reg = xlnx_stc_readl(base, XSTC_GENC)
+				     & ~XSTC_GENC_INTERL;
+		xlnx_stc_writel(base, XSTC_GENC, reg);
+	}
+
+	xlnx_stc_hori_off(base, &hori_off, vm->flags);
+	/* set up polarity */
+	memset(&polarity, 0x0, sizeof(polarity));
+	polarity.hsync = !!(vm->flags & DISPLAY_FLAGS_HSYNC_LOW);
+	polarity.vsync = !!(vm->flags & DISPLAY_FLAGS_VSYNC_LOW);
+	polarity.hblank = !!(vm->flags & DISPLAY_FLAGS_HSYNC_LOW);
+	polarity.vblank = !!(vm->flags & DISPLAY_FLAGS_VSYNC_LOW);
+	polarity.field_id = !!(vm->flags & DISPLAY_FLAGS_INTERLACED);
+	xlnx_stc_polarity(base, &polarity);
+
+	xlnx_stc_src(base);
+
+	reg = xlnx_stc_readl(base, XSTC_CTL);
+	xlnx_stc_writel(base, XSTC_CTL, reg | XSTC_CTL_RU);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/xlnx/xlnx_sdi_timing.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/xlnx/xlnx_sdi_timing.h
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx FPGA SDI Tx timing controller driver
+ *
+ * Copyright (c) 2017 Xilinx Pvt., Ltd
+ *
+ * Contacts: Saurabh Sengar <saurabhs@xilinx.com>
+ */
+
+#ifndef _XLNX_SDI_TIMING_H_
+#define _XLNX_SDI_TIMING_H_
+
+struct videomode;
+
+void xlnx_stc_enable(void __iomem *base);
+void xlnx_stc_disable(void __iomem *base);
+void xlnx_stc_reset(void __iomem *base);
+void xlnx_stc_sig(void __iomem *base, struct videomode *vm);
+
+#endif /* _XLNX_SDI_TIMING_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/xlnx/xlnx_vtc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/xlnx/xlnx_vtc.c
@@ -0,0 +1,447 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Video Timing Controller support for Xilinx DRM KMS
+ *
+ * Copyright (C) 2013 - 2018 Xilinx, Inc.
+ *
+ * Author: Hyun Woo Kwon <hyunk@xilinx.com>
+ *	   Saurabh Sengar <saurabhs@xilinx.com>
+ *	   Vishal Sagar <vishal.sagar@xilinx.com>
+ *
+ * This driver adds support to control the Xilinx Video Timing
+ * Controller connected to the CRTC.
+ */
+
+#include <drm/drmP.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <video/videomode.h>
+#include "xlnx_bridge.h"
+
+/* register offsets */
+#define XVTC_CTL		0x000
+#define XVTC_VER		0x010
+#define XVTC_GASIZE		0x060
+#define XVTC_GENC		0x068
+#define XVTC_GPOL		0x06c
+#define XVTC_GHSIZE		0x070
+#define XVTC_GVSIZE		0x074
+#define XVTC_GHSYNC		0x078
+#define XVTC_GVBHOFF_F0		0x07c
+#define XVTC_GVSYNC_F0		0x080
+#define XVTC_GVSHOFF_F0		0x084
+#define XVTC_GVBHOFF_F1		0x088
+#define XVTC_GVSYNC_F1		0x08C
+#define XVTC_GVSHOFF_F1		0x090
+#define XVTC_GASIZE_F1		0x094
+
+/* vtc control register bits */
+#define XVTC_CTL_SWRESET	BIT(31)
+#define XVTC_CTL_FIPSS		BIT(26)
+#define XVTC_CTL_ACPSS		BIT(25)
+#define XVTC_CTL_AVPSS		BIT(24)
+#define XVTC_CTL_HSPSS		BIT(23)
+#define XVTC_CTL_VSPSS		BIT(22)
+#define XVTC_CTL_HBPSS		BIT(21)
+#define XVTC_CTL_VBPSS		BIT(20)
+#define XVTC_CTL_VCSS		BIT(18)
+#define XVTC_CTL_VASS		BIT(17)
+#define XVTC_CTL_VBSS		BIT(16)
+#define XVTC_CTL_VSSS		BIT(15)
+#define XVTC_CTL_VFSS		BIT(14)
+#define XVTC_CTL_VTSS		BIT(13)
+#define XVTC_CTL_HBSS		BIT(11)
+#define XVTC_CTL_HSSS		BIT(10)
+#define XVTC_CTL_HFSS		BIT(9)
+#define XVTC_CTL_HTSS		BIT(8)
+#define XVTC_CTL_GE		BIT(2)
+#define XVTC_CTL_RU		BIT(1)
+
+/* vtc generator polarity register bits */
+#define XVTC_GPOL_FIP		BIT(6)
+#define XVTC_GPOL_ACP		BIT(5)
+#define XVTC_GPOL_AVP		BIT(4)
+#define XVTC_GPOL_HSP		BIT(3)
+#define XVTC_GPOL_VSP		BIT(2)
+#define XVTC_GPOL_HBP		BIT(1)
+#define XVTC_GPOL_VBP		BIT(0)
+
+/* vtc generator horizontal 1 */
+#define XVTC_GH1_BPSTART_MASK	GENMASK(28, 16)
+#define XVTC_GH1_BPSTART_SHIFT	16
+#define XVTC_GH1_SYNCSTART_MASK GENMASK(12, 0)
+/* vtc generator vertical 1 (field 0) */
+#define XVTC_GV1_BPSTART_MASK	GENMASK(28, 16)
+#define XVTC_GV1_BPSTART_SHIFT	16
+#define XVTC_GV1_SYNCSTART_MASK	GENMASK(12, 0)
+/* vtc generator/detector vblank/vsync horizontal offset registers */
+#define XVTC_XVXHOX_HEND_MASK	GENMASK(28, 16)
+#define XVTC_XVXHOX_HEND_SHIFT	16
+#define XVTC_XVXHOX_HSTART_MASK	GENMASK(12, 0)
+
+#define XVTC_GHFRAME_HSIZE	GENMASK(12, 0)
+#define XVTC_GVFRAME_HSIZE_F1	GENMASK(12, 0)
+#define XVTC_GA_ACTSIZE_MASK	GENMASK(12, 0)
+
+/* vtc generator encoding register bits */
+#define XVTC_GENC_INTERL	BIT(6)
+
+/**
+ * struct xlnx_vtc - Xilinx VTC object
+ *
+ * @bridge: xilinx bridge structure
+ * @dev: device structure
+ * @base: base addr
+ * @ppc: pixels per clock
+ * @axi_clk: AXI Lite clock
+ * @vid_clk: Video clock
+ */
+struct xlnx_vtc {
+	struct xlnx_bridge bridge;
+	struct device *dev;
+	void __iomem *base;
+	u32 ppc;
+	struct clk *axi_clk;
+	struct clk *vid_clk;
+};
+
+static inline void xlnx_vtc_writel(void __iomem *base, int offset, u32 val)
+{
+	writel(val, base + offset);
+}
+
+static inline u32 xlnx_vtc_readl(void __iomem *base, int offset)
+{
+	return readl(base + offset);
+}
+
+static inline struct xlnx_vtc *bridge_to_vtc(struct xlnx_bridge *bridge)
+{
+	return container_of(bridge, struct xlnx_vtc, bridge);
+}
+
+static void xlnx_vtc_reset(struct xlnx_vtc *vtc)
+{
+	u32 reg;
+
+	xlnx_vtc_writel(vtc->base, XVTC_CTL, XVTC_CTL_SWRESET);
+
+	/* enable register update */
+	reg = xlnx_vtc_readl(vtc->base, XVTC_CTL);
+	xlnx_vtc_writel(vtc->base, XVTC_CTL, reg | XVTC_CTL_RU);
+}
+
+/**
+ * xlnx_vtc_enable - Enable the VTC
+ * @bridge: xilinx bridge structure pointer
+ *
+ * Return:
+ * Zero on success.
+ *
+ * This function enables the VTC
+ */
+static int xlnx_vtc_enable(struct xlnx_bridge *bridge)
+{
+	u32 reg;
+	struct xlnx_vtc *vtc = bridge_to_vtc(bridge);
+
+	/* enable generator */
+	reg = xlnx_vtc_readl(vtc->base, XVTC_CTL);
+	xlnx_vtc_writel(vtc->base, XVTC_CTL, reg | XVTC_CTL_GE);
+	dev_dbg(vtc->dev, "enabled\n");
+	return 0;
+}
+
+/**
+ * xlnx_vtc_disable - Disable the VTC
+ * @bridge: xilinx bridge structure pointer
+ *
+ * This function disables and resets the VTC.
+ */
+static void xlnx_vtc_disable(struct xlnx_bridge *bridge)
+{
+	u32 reg;
+	struct xlnx_vtc *vtc = bridge_to_vtc(bridge);
+
+	/* disable generator and reset */
+	reg = xlnx_vtc_readl(vtc->base, XVTC_CTL);
+	xlnx_vtc_writel(vtc->base, XVTC_CTL, reg & ~XVTC_CTL_GE);
+	xlnx_vtc_reset(vtc);
+	dev_dbg(vtc->dev, "disabled\n");
+}
+
+/**
+ * xlnx_vtc_set_timing - Configures the VTC
+ * @bridge: xilinx bridge structure pointer
+ * @vm: video mode requested
+ *
+ * Return:
+ * Zero on success.
+ *
+ * This function calculates the timing values from the video mode
+ * structure passed from the CRTC and configures the VTC.
+ */
+static int xlnx_vtc_set_timing(struct xlnx_bridge *bridge,
+			       struct videomode *vm)
+{
+	u32 reg;
+	u32 htotal, hactive, hsync_start, hbackporch_start;
+	u32 vtotal, vactive, vsync_start, vbackporch_start;
+	struct xlnx_vtc *vtc = bridge_to_vtc(bridge);
+
+	reg = xlnx_vtc_readl(vtc->base, XVTC_CTL);
+	xlnx_vtc_writel(vtc->base, XVTC_CTL, reg & ~XVTC_CTL_RU);
+
+	vm->hactive /= vtc->ppc;
+	vm->hfront_porch /= vtc->ppc;
+	vm->hback_porch /= vtc->ppc;
+	vm->hsync_len /= vtc->ppc;
+
+	htotal = vm->hactive + vm->hfront_porch + vm->hsync_len +
+		 vm->hback_porch;
+	vtotal = vm->vactive + vm->vfront_porch + vm->vsync_len +
+		 vm->vback_porch;
+
+	hactive = vm->hactive;
+	vactive = vm->vactive;
+
+	hsync_start = vm->hactive + vm->hfront_porch;
+	vsync_start = vm->vactive + vm->vfront_porch;
+
+	hbackporch_start = hsync_start + vm->hsync_len;
+	vbackporch_start = vsync_start + vm->vsync_len;
+
+	dev_dbg(vtc->dev, "ha: %d, va: %d\n", hactive, vactive);
+	dev_dbg(vtc->dev, "ht: %d, vt: %d\n", htotal, vtotal);
+	dev_dbg(vtc->dev, "hs: %d, hb: %d\n", hsync_start, hbackporch_start);
+	dev_dbg(vtc->dev, "vs: %d, vb: %d\n", vsync_start, vbackporch_start);
+
+	reg = htotal & XVTC_GHFRAME_HSIZE;
+	xlnx_vtc_writel(vtc->base, XVTC_GHSIZE, reg);
+
+	reg = vtotal & XVTC_GVFRAME_HSIZE_F1;
+	reg |= reg << XVTC_GV1_BPSTART_SHIFT;
+	xlnx_vtc_writel(vtc->base, XVTC_GVSIZE, reg);
+
+	reg = hactive & XVTC_GA_ACTSIZE_MASK;
+	reg |= (vactive & XVTC_GA_ACTSIZE_MASK) << 16;
+	xlnx_vtc_writel(vtc->base, XVTC_GASIZE, reg);
+
+	if (vm->flags & DISPLAY_FLAGS_INTERLACED)
+		xlnx_vtc_writel(vtc->base, XVTC_GASIZE_F1, reg);
+
+	reg = hsync_start & XVTC_GH1_SYNCSTART_MASK;
+	reg |= (hbackporch_start << XVTC_GH1_BPSTART_SHIFT) &
+	       XVTC_GH1_BPSTART_MASK;
+	xlnx_vtc_writel(vtc->base, XVTC_GHSYNC, reg);
+
+	reg = vsync_start & XVTC_GV1_SYNCSTART_MASK;
+	reg |= (vbackporch_start << XVTC_GV1_BPSTART_SHIFT) &
+	       XVTC_GV1_BPSTART_MASK;
+	xlnx_vtc_writel(vtc->base, XVTC_GVSYNC_F0, reg);
+
+	if (vm->flags & DISPLAY_FLAGS_INTERLACED) {
+		xlnx_vtc_writel(vtc->base, XVTC_GVSYNC_F1, reg);
+		reg = xlnx_vtc_readl(vtc->base, XVTC_GENC) | XVTC_GENC_INTERL;
+		xlnx_vtc_writel(vtc->base, XVTC_GENC, reg);
+	} else {
+		reg = xlnx_vtc_readl(vtc->base, XVTC_GENC) & ~XVTC_GENC_INTERL;
+		xlnx_vtc_writel(vtc->base, XVTC_GENC, reg);
+	}
+
+	/* configure horizontal offset */
+	/* Calculate and update Generator VBlank Hori field 0 */
+	reg = hactive & XVTC_XVXHOX_HSTART_MASK;
+	reg |= (hactive << XVTC_XVXHOX_HEND_SHIFT) &
+		XVTC_XVXHOX_HEND_MASK;
+	xlnx_vtc_writel(vtc->base, XVTC_GVBHOFF_F0, reg);
+
+	/* Calculate and update Generator VSync Hori field 0 */
+	reg = hsync_start & XVTC_XVXHOX_HSTART_MASK;
+	reg |= (hsync_start << XVTC_XVXHOX_HEND_SHIFT) &
+		XVTC_XVXHOX_HEND_MASK;
+	xlnx_vtc_writel(vtc->base, XVTC_GVSHOFF_F0, reg);
+
+	/* Calculate and update Generator VBlank Hori field 1 */
+	if (vm->flags & DISPLAY_FLAGS_INTERLACED) {
+		reg = hactive & XVTC_XVXHOX_HSTART_MASK;
+		reg |= (hactive << XVTC_XVXHOX_HEND_SHIFT) &
+			XVTC_XVXHOX_HEND_MASK;
+		xlnx_vtc_writel(vtc->base, XVTC_GVBHOFF_F1, reg);
+	}
+
+	/* Calculate and update Generator VBlank Hori field 1 */
+	if (vm->flags & DISPLAY_FLAGS_INTERLACED) {
+		reg =  (hsync_start - (htotal / 2)) & XVTC_XVXHOX_HSTART_MASK;
+		reg |= ((hsync_start - (htotal / 2)) <<
+			XVTC_XVXHOX_HEND_SHIFT) & XVTC_XVXHOX_HEND_MASK;
+	} else {
+		reg =  hsync_start & XVTC_XVXHOX_HSTART_MASK;
+		reg |= (hsync_start << XVTC_XVXHOX_HEND_SHIFT) &
+			XVTC_XVXHOX_HEND_MASK;
+	}
+
+	if (vm->flags & DISPLAY_FLAGS_INTERLACED)
+		xlnx_vtc_writel(vtc->base, XVTC_GVSHOFF_F1, reg);
+
+	/* configure polarity of signals */
+	reg = 0;
+	reg |= XVTC_GPOL_ACP;
+	reg |= XVTC_GPOL_AVP;
+	if (vm->flags & DISPLAY_FLAGS_INTERLACED)
+		reg |= XVTC_GPOL_FIP;
+	if (vm->flags & DISPLAY_FLAGS_VSYNC_HIGH) {
+		reg |= XVTC_GPOL_VBP;
+		reg |= XVTC_GPOL_VSP;
+	}
+	if (vm->flags & DISPLAY_FLAGS_HSYNC_HIGH) {
+		reg |= XVTC_GPOL_HBP;
+		reg |= XVTC_GPOL_HSP;
+	}
+	xlnx_vtc_writel(vtc->base, XVTC_GPOL, reg);
+
+	/* configure timing source */
+	reg = xlnx_vtc_readl(vtc->base, XVTC_CTL);
+	reg |= XVTC_CTL_VCSS;
+	reg |= XVTC_CTL_VASS;
+	reg |= XVTC_CTL_VBSS;
+	reg |= XVTC_CTL_VSSS;
+	reg |= XVTC_CTL_VFSS;
+	reg |= XVTC_CTL_VTSS;
+	reg |= XVTC_CTL_HBSS;
+	reg |= XVTC_CTL_HSSS;
+	reg |= XVTC_CTL_HFSS;
+	reg |= XVTC_CTL_HTSS;
+	xlnx_vtc_writel(vtc->base, XVTC_CTL, reg);
+
+	reg = xlnx_vtc_readl(vtc->base, XVTC_CTL);
+	xlnx_vtc_writel(vtc->base, XVTC_CTL, reg | XVTC_CTL_RU);
+	dev_dbg(vtc->dev, "set timing done\n");
+
+	return 0;
+}
+
+static int xlnx_vtc_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct xlnx_vtc *vtc;
+	struct resource *res;
+	int ret;
+
+	vtc = devm_kzalloc(dev, sizeof(*vtc), GFP_KERNEL);
+	if (!vtc)
+		return -ENOMEM;
+
+	vtc->dev = dev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "failed to get resource for device\n");
+		return -EFAULT;
+	}
+
+	vtc->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(vtc->base)) {
+		dev_err(dev, "failed to remap io region\n");
+		return PTR_ERR(vtc->base);
+	}
+
+	platform_set_drvdata(pdev, vtc);
+
+	ret = of_property_read_u32(dev->of_node, "xlnx,pixels-per-clock",
+				   &vtc->ppc);
+	if (ret || (vtc->ppc != 1 && vtc->ppc != 2 && vtc->ppc != 4)) {
+		dev_err(dev, "failed to get ppc\n");
+		return ret;
+	}
+	dev_info(dev, "vtc ppc = %d\n", vtc->ppc);
+
+	vtc->axi_clk = devm_clk_get(vtc->dev, "s_axi_aclk");
+	if (IS_ERR(vtc->axi_clk)) {
+		ret = PTR_ERR(vtc->axi_clk);
+		dev_err(dev, "failed to get axi lite clk %d\n", ret);
+		return ret;
+	}
+
+	vtc->vid_clk = devm_clk_get(vtc->dev, "clk");
+	if (IS_ERR(vtc->vid_clk)) {
+		ret = PTR_ERR(vtc->vid_clk);
+		dev_err(dev, "failed to get video clk %d\n", ret);
+		return ret;
+	}
+
+	ret = clk_prepare_enable(vtc->axi_clk);
+	if (ret) {
+		dev_err(vtc->dev, "unable to enable axilite clk %d\n", ret);
+		return ret;
+	}
+
+	ret = clk_prepare_enable(vtc->vid_clk);
+	if (ret) {
+		dev_err(vtc->dev, "unable to enable video clk %d\n", ret);
+		goto err_axi_clk;
+	}
+
+	xlnx_vtc_reset(vtc);
+
+	vtc->bridge.enable = &xlnx_vtc_enable;
+	vtc->bridge.disable = &xlnx_vtc_disable;
+	vtc->bridge.set_timing = &xlnx_vtc_set_timing;
+	vtc->bridge.of_node = dev->of_node;
+	ret = xlnx_bridge_register(&vtc->bridge);
+	if (ret) {
+		dev_err(dev, "Bridge registration failed\n");
+		goto err_vid_clk;
+	}
+
+	dev_info(dev, "Xilinx VTC IP version : 0x%08x\n",
+		 xlnx_vtc_readl(vtc->base, XVTC_VER));
+	dev_info(dev, "Xilinx VTC DRM Bridge driver probed\n");
+	return 0;
+
+err_vid_clk:
+	clk_disable_unprepare(vtc->vid_clk);
+err_axi_clk:
+	clk_disable_unprepare(vtc->axi_clk);
+	return ret;
+}
+
+static int xlnx_vtc_remove(struct platform_device *pdev)
+{
+	struct xlnx_vtc *vtc = platform_get_drvdata(pdev);
+
+	xlnx_bridge_unregister(&vtc->bridge);
+	clk_disable_unprepare(vtc->vid_clk);
+	clk_disable_unprepare(vtc->axi_clk);
+
+	return 0;
+}
+
+static const struct of_device_id xlnx_vtc_of_match[] = {
+	{ .compatible = "xlnx,bridge-v-tc-6.1" },
+	{ /* end of table */ },
+};
+
+MODULE_DEVICE_TABLE(of, xlnx_vtc_of_match);
+
+static struct platform_driver xlnx_vtc_bridge_driver = {
+	.probe = xlnx_vtc_probe,
+	.remove = xlnx_vtc_remove,
+	.driver = {
+		.name = "xlnx,bridge-vtc",
+		.of_match_table = xlnx_vtc_of_match,
+	},
+};
+
+module_platform_driver(xlnx_vtc_bridge_driver);
+
+MODULE_AUTHOR("Vishal Sagar");
+MODULE_DESCRIPTION("Xilinx VTC Bridge Driver");
+MODULE_LICENSE("GPL v2");
+
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/xlnx/zynqmp_disp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/xlnx/zynqmp_disp.c
@@ -0,0 +1,3418 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ZynqMP Display Controller Driver
+ *
+ *  Copyright (C) 2017 - 2018 Xilinx, Inc.
+ *
+ *  Author: Hyun Woo Kwon <hyun.kwon@xilinx.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_atomic_uapi.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_plane_helper.h>
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/dmaengine.h>
+#include <linux/interrupt.h>
+#include <linux/irqreturn.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_dma.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/spinlock.h>
+#include <linux/uaccess.h>
+#include <video/videomode.h>
+
+#include "xlnx_bridge.h"
+#include "xlnx_crtc.h"
+#include "xlnx_fb.h"
+#include "zynqmp_disp.h"
+#include "zynqmp_dp.h"
+#include "zynqmp_dpsub.h"
+
+/*
+ * Overview
+ * --------
+ *
+ * The display part of ZynqMP DP subsystem. Internally, the device
+ * is partitioned into 3 blocks: AV buffer manager, Blender, Audio.
+ * The driver creates the DRM crtc and plane objectes and maps the DRM
+ * interface into those 3 blocks. In high level, the driver is layered
+ * in the following way:
+ *
+ * zynqmp_disp_crtc & zynqmp_disp_plane
+ * |->zynqmp_disp
+ *	|->zynqmp_disp_aud
+ *	|->zynqmp_disp_blend
+ *	|->zynqmp_disp_av_buf
+ *
+ * The driver APIs are used externally by
+ * - zynqmp_dpsub: Top level ZynqMP DP subsystem driver
+ * - zynqmp_dp: ZynqMP DP driver
+ * - xlnx_crtc: Xilinx DRM specific crtc functions
+ */
+
+/* The default value is ZYNQMP_DISP_AV_BUF_GFX_FMT_RGB565 */
+static uint zynqmp_disp_gfx_init_fmt;
+module_param_named(gfx_init_fmt, zynqmp_disp_gfx_init_fmt, uint, 0444);
+MODULE_PARM_DESC(gfx_init_fmt, "The initial format of the graphics layer\n"
+			       "\t\t0 = rgb565 (default)\n"
+			       "\t\t1 = rgb888\n"
+			       "\t\t2 = argb8888\n");
+/* These value should be mapped to index of av_buf_gfx_fmts[] */
+#define ZYNQMP_DISP_AV_BUF_GFX_FMT_RGB565		10
+#define ZYNQMP_DISP_AV_BUF_GFX_FMT_RGB888		5
+#define ZYNQMP_DISP_AV_BUF_GFX_FMT_ARGB8888		1
+static const u32 zynqmp_disp_gfx_init_fmts[] = {
+	ZYNQMP_DISP_AV_BUF_GFX_FMT_RGB565,
+	ZYNQMP_DISP_AV_BUF_GFX_FMT_RGB888,
+	ZYNQMP_DISP_AV_BUF_GFX_FMT_ARGB8888,
+};
+
+/* Blender registers */
+#define ZYNQMP_DISP_V_BLEND_BG_CLR_0			0x0
+#define ZYNQMP_DISP_V_BLEND_BG_CLR_1			0x4
+#define ZYNQMP_DISP_V_BLEND_BG_CLR_2			0x8
+#define ZYNQMP_DISP_V_BLEND_BG_MAX			0xfff
+#define ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA		0xc
+#define ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_MASK	0x1fe
+#define ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_MAX	0xff
+#define ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT		0x14
+#define ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_RGB		0x0
+#define ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_YCBCR444	0x1
+#define ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_YCBCR422	0x2
+#define ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_YONLY	0x3
+#define ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_XVYCC	0x4
+#define ZYNQMP_DISP_V_BLEND_OUTPUT_EN_DOWNSAMPLE	BIT(4)
+#define ZYNQMP_DISP_V_BLEND_LAYER_CONTROL		0x18
+#define ZYNQMP_DISP_V_BLEND_LAYER_CONTROL_EN_US		BIT(0)
+#define ZYNQMP_DISP_V_BLEND_LAYER_CONTROL_RGB		BIT(1)
+#define ZYNQMP_DISP_V_BLEND_LAYER_CONTROL_BYPASS	BIT(8)
+#define ZYNQMP_DISP_V_BLEND_NUM_COEFF			9
+#define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF0		0x20
+#define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF1		0x24
+#define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF2		0x28
+#define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF3		0x2c
+#define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF4		0x30
+#define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF5		0x34
+#define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF6		0x38
+#define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF7		0x3c
+#define ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF8		0x40
+#define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF0		0x44
+#define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF1		0x48
+#define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF2		0x4c
+#define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF3		0x50
+#define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF4		0x54
+#define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF5		0x58
+#define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF6		0x5c
+#define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF7		0x60
+#define ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF8		0x64
+#define ZYNQMP_DISP_V_BLEND_NUM_OFFSET			3
+#define ZYNQMP_DISP_V_BLEND_LUMA_IN1CSC_OFFSET		0x68
+#define ZYNQMP_DISP_V_BLEND_CR_IN1CSC_OFFSET		0x6c
+#define ZYNQMP_DISP_V_BLEND_CB_IN1CSC_OFFSET		0x70
+#define ZYNQMP_DISP_V_BLEND_LUMA_OUTCSC_OFFSET		0x74
+#define ZYNQMP_DISP_V_BLEND_CR_OUTCSC_OFFSET		0x78
+#define ZYNQMP_DISP_V_BLEND_CB_OUTCSC_OFFSET		0x7c
+#define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF0		0x80
+#define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF1		0x84
+#define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF2		0x88
+#define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF3		0x8c
+#define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF4		0x90
+#define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF5		0x94
+#define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF6		0x98
+#define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF7		0x9c
+#define ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF8		0xa0
+#define ZYNQMP_DISP_V_BLEND_LUMA_IN2CSC_OFFSET		0xa4
+#define ZYNQMP_DISP_V_BLEND_CR_IN2CSC_OFFSET		0xa8
+#define ZYNQMP_DISP_V_BLEND_CB_IN2CSC_OFFSET		0xac
+#define ZYNQMP_DISP_V_BLEND_CHROMA_KEY_ENABLE		0x1d0
+#define ZYNQMP_DISP_V_BLEND_CHROMA_KEY_COMP1		0x1d4
+#define ZYNQMP_DISP_V_BLEND_CHROMA_KEY_COMP2		0x1d8
+#define ZYNQMP_DISP_V_BLEND_CHROMA_KEY_COMP3		0x1dc
+
+/* AV buffer manager registers */
+#define ZYNQMP_DISP_AV_BUF_FMT				0x0
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_SHIFT		0
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_MASK		(0x1f << 0)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_UYVY		(0 << 0)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_VYUY		(1 << 0)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YVYU		(2 << 0)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YUYV		(3 << 0)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16		(4 << 0)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV24		(5 << 0)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI		(6 << 0)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_MONO		(7 << 0)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI2		(8 << 0)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YUV444		(9 << 0)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGB888		(10 << 0)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGBA8880		(11 << 0)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGB888_10		(12 << 0)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YUV444_10		(13 << 0)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI2_10	(14 << 0)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI_10		(15 << 0)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16_10		(16 << 0)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV24_10		(17 << 0)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YONLY_10		(18 << 0)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16_420		(19 << 0)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI_420	(20 << 0)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI2_420	(21 << 0)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16_420_10	(22 << 0)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI_420_10	(23 << 0)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI2_420_10	(24 << 0)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_SHIFT		8
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_MASK		(0xf << 8)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA8888		(0 << 8)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_ABGR8888		(1 << 8)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGB888		(2 << 8)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_BGR888		(3 << 8)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA5551		(4 << 8)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA4444		(5 << 8)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGB565		(6 << 8)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_8BPP		(7 << 8)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_4BPP		(8 << 8)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_2BPP		(9 << 8)
+#define ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_1BPP		(10 << 8)
+#define ZYNQMP_DISP_AV_BUF_NON_LIVE_LATENCY		0x8
+#define ZYNQMP_DISP_AV_BUF_CHBUF			0x10
+#define ZYNQMP_DISP_AV_BUF_CHBUF_EN			BIT(0)
+#define ZYNQMP_DISP_AV_BUF_CHBUF_FLUSH			BIT(1)
+#define ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_SHIFT	2
+#define ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_MASK		(0xf << 2)
+#define ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_MAX		0xf
+#define ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_AUD_MAX	0x3
+#define ZYNQMP_DISP_AV_BUF_STATUS			0x28
+#define ZYNQMP_DISP_AV_BUF_STC_CTRL			0x2c
+#define ZYNQMP_DISP_AV_BUF_STC_CTRL_EN			BIT(0)
+#define ZYNQMP_DISP_AV_BUF_STC_CTRL_EVENT_SHIFT		1
+#define ZYNQMP_DISP_AV_BUF_STC_CTRL_EVENT_EX_VSYNC	0
+#define ZYNQMP_DISP_AV_BUF_STC_CTRL_EVENT_EX_VID	1
+#define ZYNQMP_DISP_AV_BUF_STC_CTRL_EVENT_EX_AUD	2
+#define ZYNQMP_DISP_AV_BUF_STC_CTRL_EVENT_INT_VSYNC	3
+#define ZYNQMP_DISP_AV_BUF_STC_INIT_VALUE0		0x30
+#define ZYNQMP_DISP_AV_BUF_STC_INIT_VALUE1		0x34
+#define ZYNQMP_DISP_AV_BUF_STC_ADJ			0x38
+#define ZYNQMP_DISP_AV_BUF_STC_VID_VSYNC_TS0		0x3c
+#define ZYNQMP_DISP_AV_BUF_STC_VID_VSYNC_TS1		0x40
+#define ZYNQMP_DISP_AV_BUF_STC_EXT_VSYNC_TS0		0x44
+#define ZYNQMP_DISP_AV_BUF_STC_EXT_VSYNC_TS1		0x48
+#define ZYNQMP_DISP_AV_BUF_STC_CUSTOM_EVENT_TS0		0x4c
+#define ZYNQMP_DISP_AV_BUF_STC_CUSTOM_EVENT_TS1		0x50
+#define ZYNQMP_DISP_AV_BUF_STC_CUSTOM_EVENT2_TS0	0x54
+#define ZYNQMP_DISP_AV_BUF_STC_CUSTOM_EVENT2_TS1	0x58
+#define ZYNQMP_DISP_AV_BUF_STC_SNAPSHOT0		0x60
+#define ZYNQMP_DISP_AV_BUF_STC_SNAPSHOT1		0x64
+#define ZYNQMP_DISP_AV_BUF_OUTPUT			0x70
+#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_SHIFT		0
+#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MASK		(0x3 << 0)
+#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_LIVE		(0 << 0)
+#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MEM		(1 << 0)
+#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_PATTERN		(2 << 0)
+#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_NONE		(3 << 0)
+#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_SHIFT		2
+#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MASK		(0x3 << 2)
+#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_DISABLE		(0 << 2)
+#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MEM		(1 << 2)
+#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_LIVE		(2 << 2)
+#define ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_NONE		(3 << 2)
+#define ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_SHIFT		4
+#define ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_MASK		(0x3 << 4)
+#define ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_PL		(0 << 4)
+#define ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_MEM		(1 << 4)
+#define ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_PATTERN		(2 << 4)
+#define ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_DISABLE		(3 << 4)
+#define ZYNQMP_DISP_AV_BUF_OUTPUT_AUD2_EN		BIT(6)
+#define ZYNQMP_DISP_AV_BUF_HCOUNT_VCOUNT_INT0		0x74
+#define ZYNQMP_DISP_AV_BUF_HCOUNT_VCOUNT_INT1		0x78
+#define ZYNQMP_DISP_AV_BUF_PATTERN_GEN_SELECT		0x100
+#define ZYNQMP_DISP_AV_BUF_CLK_SRC			0x120
+#define ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_FROM_PS		BIT(0)
+#define ZYNQMP_DISP_AV_BUF_CLK_SRC_AUD_FROM_PS		BIT(1)
+#define ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_INTERNAL_TIMING	BIT(2)
+#define ZYNQMP_DISP_AV_BUF_SRST_REG			0x124
+#define ZYNQMP_DISP_AV_BUF_SRST_REG_VID_RST		BIT(1)
+#define ZYNQMP_DISP_AV_BUF_AUDIO_CH_CONFIG		0x12c
+#define ZYNQMP_DISP_AV_BUF_GFX_COMP0_SF			0x200
+#define ZYNQMP_DISP_AV_BUF_GFX_COMP1_SF			0x204
+#define ZYNQMP_DISP_AV_BUF_GFX_COMP2_SF			0x208
+#define ZYNQMP_DISP_AV_BUF_VID_COMP0_SF			0x20c
+#define ZYNQMP_DISP_AV_BUF_VID_COMP1_SF			0x210
+#define ZYNQMP_DISP_AV_BUF_VID_COMP2_SF			0x214
+#define ZYNQMP_DISP_AV_BUF_LIVE_VID_COMP0_SF		0x218
+#define ZYNQMP_DISP_AV_BUF_LIVE_VID_COMP1_SF		0x21c
+#define ZYNQMP_DISP_AV_BUF_LIVE_VID_COMP2_SF		0x220
+#define ZYNQMP_DISP_AV_BUF_LIVE_VID_CONFIG		0x224
+#define ZYNQMP_DISP_AV_BUF_LIVE_GFX_COMP0_SF		0x228
+#define ZYNQMP_DISP_AV_BUF_LIVE_GFX_COMP1_SF		0x22c
+#define ZYNQMP_DISP_AV_BUF_LIVE_GFX_COMP2_SF		0x230
+#define ZYNQMP_DISP_AV_BUF_LIVE_GFX_CONFIG		0x234
+#define ZYNQMP_DISP_AV_BUF_4BIT_SF			0x11111
+#define ZYNQMP_DISP_AV_BUF_5BIT_SF			0x10842
+#define ZYNQMP_DISP_AV_BUF_6BIT_SF			0x10410
+#define ZYNQMP_DISP_AV_BUF_8BIT_SF			0x10101
+#define ZYNQMP_DISP_AV_BUF_10BIT_SF			0x10040
+#define ZYNQMP_DISP_AV_BUF_NULL_SF			0
+#define ZYNQMP_DISP_AV_BUF_NUM_SF			3
+#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_6		0x0
+#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_8		0x1
+#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_10		0x2
+#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_12		0x3
+#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_MASK		GENMASK(2, 0)
+#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_RGB		0x00
+#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV444	0x10
+#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV422	0x20
+#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YONLY	0x30
+#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_MASK		GENMASK(5, 4)
+#define ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_CB_FIRST		BIT(8)
+#define ZYNQMP_DISP_AV_BUF_PALETTE_MEMORY		0x400
+
+/* Audio registers */
+#define ZYNQMP_DISP_AUD_MIXER_VOLUME			0x0
+#define ZYNQMP_DISP_AUD_MIXER_VOLUME_NO_SCALE		0x20002000
+#define ZYNQMP_DISP_AUD_MIXER_META_DATA			0x4
+#define ZYNQMP_DISP_AUD_CH_STATUS0			0x8
+#define ZYNQMP_DISP_AUD_CH_STATUS1			0xc
+#define ZYNQMP_DISP_AUD_CH_STATUS2			0x10
+#define ZYNQMP_DISP_AUD_CH_STATUS3			0x14
+#define ZYNQMP_DISP_AUD_CH_STATUS4			0x18
+#define ZYNQMP_DISP_AUD_CH_STATUS5			0x1c
+#define ZYNQMP_DISP_AUD_CH_A_DATA0			0x20
+#define ZYNQMP_DISP_AUD_CH_A_DATA1			0x24
+#define ZYNQMP_DISP_AUD_CH_A_DATA2			0x28
+#define ZYNQMP_DISP_AUD_CH_A_DATA3			0x2c
+#define ZYNQMP_DISP_AUD_CH_A_DATA4			0x30
+#define ZYNQMP_DISP_AUD_CH_A_DATA5			0x34
+#define ZYNQMP_DISP_AUD_CH_B_DATA0			0x38
+#define ZYNQMP_DISP_AUD_CH_B_DATA1			0x3c
+#define ZYNQMP_DISP_AUD_CH_B_DATA2			0x40
+#define ZYNQMP_DISP_AUD_CH_B_DATA3			0x44
+#define ZYNQMP_DISP_AUD_CH_B_DATA4			0x48
+#define ZYNQMP_DISP_AUD_CH_B_DATA5			0x4c
+#define ZYNQMP_DISP_AUD_SOFT_RESET			0xc00
+#define ZYNQMP_DISP_AUD_SOFT_RESET_AUD_SRST		BIT(0)
+
+#define ZYNQMP_DISP_AV_BUF_NUM_VID_GFX_BUFFERS		4
+#define ZYNQMP_DISP_AV_BUF_NUM_BUFFERS			6
+
+#define ZYNQMP_DISP_NUM_LAYERS				2
+#define ZYNQMP_DISP_MAX_NUM_SUB_PLANES			3
+/*
+ * 3840x2160 is advertised max resolution, but almost any resolutions under
+ * 300Mhz pixel rate would work. Thus put 4096 as maximum width and height.
+ */
+#define ZYNQMP_DISP_MAX_WIDTH				4096
+#define ZYNQMP_DISP_MAX_HEIGHT				4096
+/* 44 bit addressing. This is acutally DPDMA limitation */
+#define ZYNQMP_DISP_MAX_DMA_BIT				44
+
+/**
+ * enum zynqmp_disp_layer_type - Layer type (can be used for hw ID)
+ * @ZYNQMP_DISP_LAYER_VID: Video layer
+ * @ZYNQMP_DISP_LAYER_GFX: Graphics layer
+ */
+enum zynqmp_disp_layer_type {
+	ZYNQMP_DISP_LAYER_VID,
+	ZYNQMP_DISP_LAYER_GFX
+};
+
+/**
+ * enum zynqmp_disp_layer_mode - Layer mode
+ * @ZYNQMP_DISP_LAYER_NONLIVE: non-live (memory) mode
+ * @ZYNQMP_DISP_LAYER_LIVE: live (stream) mode
+ */
+enum zynqmp_disp_layer_mode {
+	ZYNQMP_DISP_LAYER_NONLIVE,
+	ZYNQMP_DISP_LAYER_LIVE
+};
+
+/**
+ * struct zynqmp_disp_layer_dma - struct for DMA engine
+ * @chan: DMA channel
+ * @is_active: flag if the DMA is active
+ * @xt: Interleaved desc config container
+ * @sgl: Data chunk for dma_interleaved_template
+ */
+struct zynqmp_disp_layer_dma {
+	struct dma_chan *chan;
+	bool is_active;
+	struct dma_interleaved_template xt;
+	struct data_chunk sgl[1];
+};
+
+/**
+ * struct zynqmp_disp_layer - Display subsystem layer
+ * @plane: DRM plane
+ * @bridge: Xlnx bridge
+ * @of_node: device node
+ * @dma: struct for DMA engine
+ * @num_chan: Number of DMA channel
+ * @id: Layer ID
+ * @offset: Layer offset in the register space
+ * @enabled: flag if enabled
+ * @fmt: Current format descriptor
+ * @drm_fmts: Array of supported DRM formats
+ * @num_fmts: Number of supported DRM formats
+ * @bus_fmts: Array of supported bus formats
+ * @num_bus_fmts: Number of supported bus formats
+ * @w: Width
+ * @h: Height
+ * @mode: the operation mode
+ * @other: other layer
+ * @disp: back pointer to struct zynqmp_disp
+ */
+struct zynqmp_disp_layer {
+	struct drm_plane plane;
+	struct xlnx_bridge bridge;
+	struct device_node *of_node;
+	struct zynqmp_disp_layer_dma dma[ZYNQMP_DISP_MAX_NUM_SUB_PLANES];
+	unsigned int num_chan;
+	enum zynqmp_disp_layer_type id;
+	u32 offset;
+	u8 enabled;
+	const struct zynqmp_disp_fmt *fmt;
+	u32 *drm_fmts;
+	unsigned int num_fmts;
+	u32 *bus_fmts;
+	unsigned int num_bus_fmts;
+	u32 w;
+	u32 h;
+	enum zynqmp_disp_layer_mode mode;
+	struct zynqmp_disp_layer *other;
+	struct zynqmp_disp *disp;
+};
+
+/**
+ * struct zynqmp_disp_blend - Blender
+ * @base: Base address offset
+ */
+struct zynqmp_disp_blend {
+	void __iomem *base;
+};
+
+/**
+ * struct zynqmp_disp_av_buf - AV buffer manager
+ * @base: Base address offset
+ */
+struct zynqmp_disp_av_buf {
+	void __iomem *base;
+};
+
+/**
+ * struct zynqmp_disp_aud - Audio
+ * @base: Base address offset
+ */
+struct zynqmp_disp_aud {
+	void __iomem *base;
+};
+
+/**
+ * struct zynqmp_disp - Display subsystem
+ * @xlnx_crtc: Xilinx DRM crtc
+ * @dev: device structure
+ * @dpsub: Display subsystem
+ * @drm: DRM core
+ * @enabled: flag if enabled
+ * @blend: Blender block
+ * @av_buf: AV buffer manager block
+ * @aud:Audio block
+ * @layers: layers
+ * @g_alpha_prop: global alpha property
+ * @alpha: current global alpha value
+ * @g_alpha_en_prop: the global alpha enable property
+ * @alpha_en: flag if the global alpha is enabled
+ * @color_prop: output color format property
+ * @color: current output color value
+ * @bg_c0_prop: 1st component of background color property
+ * @bg_c0: current value of 1st background color component
+ * @bg_c1_prop: 2nd component of background color property
+ * @bg_c1: current value of 2nd background color component
+ * @bg_c2_prop: 3rd component of background color property
+ * @bg_c2: current value of 3rd background color component
+ * @tpg_prop: Test Pattern Generation mode property
+ * @tpg_on: current TPG mode state
+ * @event: pending vblank event request
+ * @_ps_pclk: Pixel clock from PS
+ * @_pl_pclk: Pixel clock from PL
+ * @pclk: Pixel clock
+ * @pclk_en: Flag if the pixel clock is enabled
+ * @_ps_audclk: Audio clock from PS
+ * @_pl_audclk: Audio clock from PL
+ * @audclk: Audio clock
+ * @audclk_en: Flag if the audio clock is enabled
+ * @aclk: APB clock
+ * @aclk_en: Flag if the APB clock is enabled
+ */
+struct zynqmp_disp {
+	struct xlnx_crtc xlnx_crtc;
+	struct device *dev;
+	struct zynqmp_dpsub *dpsub;
+	struct drm_device *drm;
+	bool enabled;
+	struct zynqmp_disp_blend blend;
+	struct zynqmp_disp_av_buf av_buf;
+	struct zynqmp_disp_aud aud;
+	struct zynqmp_disp_layer layers[ZYNQMP_DISP_NUM_LAYERS];
+	struct drm_property *g_alpha_prop;
+	u32 alpha;
+	struct drm_property *g_alpha_en_prop;
+	bool alpha_en;
+	struct drm_property *color_prop;
+	unsigned int color;
+	struct drm_property *bg_c0_prop;
+	u32 bg_c0;
+	struct drm_property *bg_c1_prop;
+	u32 bg_c1;
+	struct drm_property *bg_c2_prop;
+	u32 bg_c2;
+	struct drm_property *tpg_prop;
+	bool tpg_on;
+	struct drm_pending_vblank_event *event;
+	/* Don't operate directly on _ps_ */
+	struct clk *_ps_pclk;
+	struct clk *_pl_pclk;
+	struct clk *pclk;
+	bool pclk_en;
+	struct clk *_ps_audclk;
+	struct clk *_pl_audclk;
+	struct clk *audclk;
+	bool audclk_en;
+	struct clk *aclk;
+	bool aclk_en;
+	struct xlnx_bridge *vtc_bridge;
+};
+
+/**
+ * struct zynqmp_disp_fmt - Display subsystem format mapping
+ * @drm_fmt: drm format
+ * @disp_fmt: Display subsystem format
+ * @bus_fmt: Bus formats (live formats)
+ * @rgb: flag for RGB formats
+ * @swap: flag to swap r & b for rgb formats, and u & v for yuv formats
+ * @chroma_sub: flag for chroma subsampled formats
+ * @sf: scaling factors for upto 3 color components
+ */
+struct zynqmp_disp_fmt {
+	u32 drm_fmt;
+	u32 disp_fmt;
+	u32 bus_fmt;
+	bool rgb;
+	bool swap;
+	bool chroma_sub;
+	u32 sf[3];
+};
+
+static void zynqmp_disp_write(void __iomem *base, int offset, u32 val)
+{
+	writel(val, base + offset);
+}
+
+static u32 zynqmp_disp_read(void __iomem *base, int offset)
+{
+	return readl(base + offset);
+}
+
+static void zynqmp_disp_clr(void __iomem *base, int offset, u32 clr)
+{
+	zynqmp_disp_write(base, offset, zynqmp_disp_read(base, offset) & ~clr);
+}
+
+static void zynqmp_disp_set(void __iomem *base, int offset, u32 set)
+{
+	zynqmp_disp_write(base, offset, zynqmp_disp_read(base, offset) | set);
+}
+
+/*
+ * Clock functions
+ */
+
+/**
+ * zynqmp_disp_clk_enable - Enable the clock if needed
+ * @clk: clk device
+ * @flag: flag if the clock is enabled
+ *
+ * Enable the clock only if it's not enabled @flag.
+ *
+ * Return: value from clk_prepare_enable().
+ */
+static int zynqmp_disp_clk_enable(struct clk *clk, bool *flag)
+{
+	int ret = 0;
+
+	if (!*flag) {
+		ret = clk_prepare_enable(clk);
+		if (!ret)
+			*flag = true;
+	}
+
+	return ret;
+}
+
+/**
+ * zynqmp_disp_clk_enable - Enable the clock if needed
+ * @clk: clk device
+ * @flag: flag if the clock is enabled
+ *
+ * Disable the clock only if it's enabled @flag.
+ */
+static void zynqmp_disp_clk_disable(struct clk *clk, bool *flag)
+{
+	if (*flag) {
+		clk_disable_unprepare(clk);
+		*flag = false;
+	}
+}
+
+/**
+ * zynqmp_disp_clk_enable - Enable and disable the clock
+ * @clk: clk device
+ * @flag: flag if the clock is enabled
+ *
+ * This is to ensure the clock is disabled. The initial hardware state is
+ * unknown, and this makes sure that the clock is disabled.
+ *
+ * Return: value from clk_prepare_enable().
+ */
+static int zynqmp_disp_clk_enable_disable(struct clk *clk, bool *flag)
+{
+	int ret = 0;
+
+	if (!*flag) {
+		ret = clk_prepare_enable(clk);
+		clk_disable_unprepare(clk);
+	}
+
+	return ret;
+}
+
+/*
+ * Blender functions
+ */
+
+/**
+ * zynqmp_disp_blend_set_output_fmt - Set the output format of the blend
+ * @blend: blend object
+ * @fmt: output format
+ *
+ * Set the output format to @fmt.
+ */
+static void
+zynqmp_disp_blend_set_output_fmt(struct zynqmp_disp_blend *blend, u32 fmt)
+{
+	u16 reset_coeffs[] = { 0x1000, 0x0, 0x0,
+			       0x0, 0x1000, 0x0,
+			       0x0, 0x0, 0x1000 };
+	u32 reset_offsets[] = { 0x0, 0x0, 0x0 };
+	u16 sdtv_coeffs[] = { 0x4c9, 0x864, 0x1d3,
+			      0x7d4d, 0x7ab3, 0x800,
+			      0x800, 0x794d, 0x7eb3 };
+	u32 full_range_offsets[] = { 0x0, 0x8000000, 0x8000000 };
+	u16 *coeffs;
+	u32 *offsets;
+	u32 offset, i;
+
+	zynqmp_disp_write(blend->base, ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT, fmt);
+	if (fmt == ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_RGB) {
+		coeffs = reset_coeffs;
+		offsets = reset_offsets;
+	} else {
+		/* Hardcode Full-range SDTV values. Can be runtime config */
+		coeffs = sdtv_coeffs;
+		offsets = full_range_offsets;
+	}
+
+	offset = ZYNQMP_DISP_V_BLEND_RGB2YCBCR_COEFF0;
+	for (i = 0; i < ZYNQMP_DISP_V_BLEND_NUM_COEFF; i++)
+		zynqmp_disp_write(blend->base, offset + i * 4, coeffs[i]);
+
+	offset = ZYNQMP_DISP_V_BLEND_LUMA_OUTCSC_OFFSET;
+	for (i = 0; i < ZYNQMP_DISP_V_BLEND_NUM_OFFSET; i++)
+		zynqmp_disp_write(blend->base, offset + i * 4, offsets[i]);
+}
+
+/**
+ * zynqmp_disp_blend_layer_coeff - Set the coefficients for @layer
+ * @blend: blend object
+ * @layer: layer to set the coefficients for
+ * @on: if layer is on / off
+ *
+ * Depending on the format (rgb / yuv and swap), and the status (on / off),
+ * this function sets the coefficients for the given layer @layer accordingly.
+ */
+static void zynqmp_disp_blend_layer_coeff(struct zynqmp_disp_blend *blend,
+					  struct zynqmp_disp_layer *layer,
+					  bool on)
+{
+	u32 offset, i, s0, s1;
+	u16 sdtv_coeffs[] = { 0x1000, 0x166f, 0x0,
+			      0x1000, 0x7483, 0x7a7f,
+			      0x1000, 0x0, 0x1c5a };
+	u16 sdtv_coeffs_yonly[] = { 0x0, 0x0, 0x1000,
+				    0x0, 0x0, 0x1000,
+				    0x0, 0x0, 0x1000 };
+	u16 swap_coeffs[] = { 0x1000, 0x0, 0x0,
+			      0x0, 0x1000, 0x0,
+			      0x0, 0x0, 0x1000 };
+	u16 null_coeffs[] = { 0x0, 0x0, 0x0,
+			      0x0, 0x0, 0x0,
+			      0x0, 0x0, 0x0 };
+	u16 *coeffs;
+	u32 sdtv_offsets[] = { 0x0, 0x1800, 0x1800 };
+	u32 sdtv_offsets_yonly[] = { 0x1800, 0x1800, 0x0 };
+	u32 null_offsets[] = { 0x0, 0x0, 0x0 };
+	u32 *offsets;
+
+	if (layer->id == ZYNQMP_DISP_LAYER_VID)
+		offset = ZYNQMP_DISP_V_BLEND_IN1CSC_COEFF0;
+	else
+		offset = ZYNQMP_DISP_V_BLEND_IN2CSC_COEFF0;
+
+	if (!on) {
+		coeffs = null_coeffs;
+		offsets = null_offsets;
+	} else {
+		if (!layer->fmt->rgb) {
+			/*
+			 * In case of Y_ONLY formats, pixels are unpacked
+			 * differently compared to YCbCr
+			 */
+			if (layer->fmt->drm_fmt == DRM_FORMAT_Y8 ||
+			    layer->fmt->drm_fmt == DRM_FORMAT_Y10) {
+				coeffs = sdtv_coeffs_yonly;
+				offsets = sdtv_offsets_yonly;
+			} else {
+				coeffs = sdtv_coeffs;
+				offsets = sdtv_offsets;
+			}
+
+			s0 = 1;
+			s1 = 2;
+		} else {
+			coeffs = swap_coeffs;
+			s0 = 0;
+			s1 = 2;
+
+			/* No offset for RGB formats */
+			offsets = null_offsets;
+		}
+
+		if (layer->fmt->swap) {
+			for (i = 0; i < 3; i++) {
+				coeffs[i * 3 + s0] ^= coeffs[i * 3 + s1];
+				coeffs[i * 3 + s1] ^= coeffs[i * 3 + s0];
+				coeffs[i * 3 + s0] ^= coeffs[i * 3 + s1];
+			}
+		}
+	}
+
+	/* Program coefficients. Can be runtime configurable */
+	for (i = 0; i < ZYNQMP_DISP_V_BLEND_NUM_COEFF; i++)
+		zynqmp_disp_write(blend->base, offset + i * 4, coeffs[i]);
+
+	if (layer->id == ZYNQMP_DISP_LAYER_VID)
+		offset = ZYNQMP_DISP_V_BLEND_LUMA_IN1CSC_OFFSET;
+	else
+		offset = ZYNQMP_DISP_V_BLEND_LUMA_IN2CSC_OFFSET;
+
+	/* Program offsets. Can be runtime configurable */
+	for (i = 0; i < ZYNQMP_DISP_V_BLEND_NUM_OFFSET; i++)
+		zynqmp_disp_write(blend->base, offset + i * 4, offsets[i]);
+}
+
+/**
+ * zynqmp_disp_blend_layer_enable - Enable a layer
+ * @blend: blend object
+ * @layer: layer to enable
+ *
+ * Enable a layer @layer.
+ */
+static void zynqmp_disp_blend_layer_enable(struct zynqmp_disp_blend *blend,
+					   struct zynqmp_disp_layer *layer)
+{
+	u32 reg;
+
+	reg = layer->fmt->rgb ? ZYNQMP_DISP_V_BLEND_LAYER_CONTROL_RGB : 0;
+	reg |= layer->fmt->chroma_sub ?
+	       ZYNQMP_DISP_V_BLEND_LAYER_CONTROL_EN_US : 0;
+
+	zynqmp_disp_write(blend->base,
+			  ZYNQMP_DISP_V_BLEND_LAYER_CONTROL + layer->offset,
+			  reg);
+
+	zynqmp_disp_blend_layer_coeff(blend, layer, true);
+}
+
+/**
+ * zynqmp_disp_blend_layer_disable - Disable a layer
+ * @blend: blend object
+ * @layer: layer to disable
+ *
+ * Disable a layer @layer.
+ */
+static void zynqmp_disp_blend_layer_disable(struct zynqmp_disp_blend *blend,
+					    struct zynqmp_disp_layer *layer)
+{
+	zynqmp_disp_write(blend->base,
+			  ZYNQMP_DISP_V_BLEND_LAYER_CONTROL + layer->offset, 0);
+
+	zynqmp_disp_blend_layer_coeff(blend, layer, false);
+}
+
+/**
+ * zynqmp_disp_blend_set_bg_color - Set the background color
+ * @blend: blend object
+ * @c0: color component 0
+ * @c1: color component 1
+ * @c2: color component 2
+ *
+ * Set the background color.
+ */
+static void zynqmp_disp_blend_set_bg_color(struct zynqmp_disp_blend *blend,
+					   u32 c0, u32 c1, u32 c2)
+{
+	zynqmp_disp_write(blend->base, ZYNQMP_DISP_V_BLEND_BG_CLR_0, c0);
+	zynqmp_disp_write(blend->base, ZYNQMP_DISP_V_BLEND_BG_CLR_1, c1);
+	zynqmp_disp_write(blend->base, ZYNQMP_DISP_V_BLEND_BG_CLR_2, c2);
+}
+
+/**
+ * zynqmp_disp_blend_set_alpha - Set the alpha for blending
+ * @blend: blend object
+ * @alpha: alpha value to be used
+ *
+ * Set the alpha for blending.
+ */
+static void
+zynqmp_disp_blend_set_alpha(struct zynqmp_disp_blend *blend, u32 alpha)
+{
+	u32 reg;
+
+	reg = zynqmp_disp_read(blend->base,
+			       ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA);
+	reg &= ~ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_MASK;
+	reg |= alpha << 1;
+	zynqmp_disp_write(blend->base, ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA,
+			  reg);
+}
+
+/**
+ * zynqmp_disp_blend_enable_alpha - Enable/disable the global alpha
+ * @blend: blend object
+ * @enable: flag to enable or disable alpha blending
+ *
+ * Enable/disable the global alpha blending based on @enable.
+ */
+static void
+zynqmp_disp_blend_enable_alpha(struct zynqmp_disp_blend *blend, bool enable)
+{
+	if (enable)
+		zynqmp_disp_set(blend->base,
+				ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA, BIT(0));
+	else
+		zynqmp_disp_clr(blend->base,
+				ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA, BIT(0));
+}
+
+/* List of blend output formats */
+/* The id / order should be aligned with zynqmp_disp_color_enum */
+static const struct zynqmp_disp_fmt blend_output_fmts[] = {
+	{
+		.disp_fmt	= ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_RGB,
+	}, {
+		.disp_fmt	= ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_YCBCR444,
+	}, {
+		.disp_fmt	= ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_YCBCR422,
+	}, {
+		.disp_fmt	= ZYNQMP_DISP_V_BLEND_OUTPUT_VID_FMT_YONLY,
+	}
+};
+
+/*
+ * AV buffer manager functions
+ */
+
+/* List of video layer formats */
+#define ZYNQMP_DISP_AV_BUF_VID_FMT_YUYV	2
+static const struct zynqmp_disp_fmt av_buf_vid_fmts[] = {
+	{
+		.drm_fmt	= DRM_FORMAT_VYUY,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_VID_VYUY,
+		.rgb		= false,
+		.swap		= true,
+		.chroma_sub	= true,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+	}, {
+		.drm_fmt	= DRM_FORMAT_UYVY,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_VID_VYUY,
+		.rgb		= false,
+		.swap		= false,
+		.chroma_sub	= true,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+	}, {
+		.drm_fmt	= DRM_FORMAT_YUYV,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YUYV,
+		.rgb		= false,
+		.swap		= false,
+		.chroma_sub	= true,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+	}, {
+		.drm_fmt	= DRM_FORMAT_YVYU,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YUYV,
+		.rgb		= false,
+		.swap		= true,
+		.chroma_sub	= true,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+	}, {
+		.drm_fmt	= DRM_FORMAT_YUV422,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16,
+		.rgb		= false,
+		.swap		= false,
+		.chroma_sub	= true,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+	}, {
+		.drm_fmt	= DRM_FORMAT_YVU422,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16,
+		.rgb		= false,
+		.swap		= true,
+		.chroma_sub	= true,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+	}, {
+		.drm_fmt	= DRM_FORMAT_YUV444,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV24,
+		.rgb		= false,
+		.swap		= false,
+		.chroma_sub	= false,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+	}, {
+		.drm_fmt	= DRM_FORMAT_YVU444,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV24,
+		.rgb		= false,
+		.swap		= true,
+		.chroma_sub	= false,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+	}, {
+		.drm_fmt	= DRM_FORMAT_NV16,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI,
+		.rgb		= false,
+		.swap		= false,
+		.chroma_sub	= true,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+	}, {
+		.drm_fmt	= DRM_FORMAT_NV61,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI,
+		.rgb		= false,
+		.swap		= true,
+		.chroma_sub	= true,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+	}, {
+		.drm_fmt	= DRM_FORMAT_Y8,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_VID_MONO,
+		.rgb		= false,
+		.swap		= false,
+		.chroma_sub	= false,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+	}, {
+		.drm_fmt	= DRM_FORMAT_Y10,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YONLY_10,
+		.rgb		= false,
+		.swap		= false,
+		.chroma_sub	= false,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_10BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_10BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_10BIT_SF,
+	}, {
+		.drm_fmt	= DRM_FORMAT_BGR888,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGB888,
+		.rgb		= true,
+		.swap		= false,
+		.chroma_sub	= false,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+	}, {
+		.drm_fmt	= DRM_FORMAT_RGB888,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGB888,
+		.rgb		= true,
+		.swap		= true,
+		.chroma_sub	= false,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+	}, {
+		.drm_fmt	= DRM_FORMAT_XBGR8888,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGBA8880,
+		.rgb		= true,
+		.swap		= false,
+		.chroma_sub	= false,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+	}, {
+		.drm_fmt	= DRM_FORMAT_XRGB8888,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGBA8880,
+		.rgb		= true,
+		.swap		= true,
+		.chroma_sub	= false,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+	}, {
+		.drm_fmt	= DRM_FORMAT_XBGR2101010,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGB888_10,
+		.rgb		= true,
+		.swap		= false,
+		.chroma_sub	= false,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_10BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_10BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_10BIT_SF,
+	}, {
+		.drm_fmt	= DRM_FORMAT_XRGB2101010,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_VID_RGB888_10,
+		.rgb		= true,
+		.swap		= true,
+		.chroma_sub	= false,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_10BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_10BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_10BIT_SF,
+	}, {
+		.drm_fmt	= DRM_FORMAT_YUV420,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16_420,
+		.rgb		= false,
+		.swap		= false,
+		.chroma_sub	= true,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+	}, {
+		.drm_fmt	= DRM_FORMAT_YVU420,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16_420,
+		.rgb		= false,
+		.swap		= true,
+		.chroma_sub	= true,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+	}, {
+		.drm_fmt	= DRM_FORMAT_NV12,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI_420,
+		.rgb		= false,
+		.swap		= false,
+		.chroma_sub	= true,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+	}, {
+		.drm_fmt	= DRM_FORMAT_NV21,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI_420,
+		.rgb		= false,
+		.swap		= true,
+		.chroma_sub	= true,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+	}, {
+		.drm_fmt	= DRM_FORMAT_XV15,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI_420_10,
+		.rgb		= false,
+		.swap		= false,
+		.chroma_sub	= true,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_10BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_10BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_10BIT_SF,
+	}, {
+		.drm_fmt	= DRM_FORMAT_XV20,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_VID_YV16CI_10,
+		.rgb		= false,
+		.swap		= false,
+		.chroma_sub	= true,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_10BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_10BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_10BIT_SF,
+	}
+};
+
+/* List of graphics layer formats */
+static const struct zynqmp_disp_fmt av_buf_gfx_fmts[] = {
+	{
+		.drm_fmt	= DRM_FORMAT_ABGR8888,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA8888,
+		.rgb		= true,
+		.swap		= false,
+		.chroma_sub	= false,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+	}, {
+		.drm_fmt	= DRM_FORMAT_ARGB8888,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA8888,
+		.rgb		= true,
+		.swap		= true,
+		.chroma_sub	= false,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+	}, {
+		.drm_fmt	= DRM_FORMAT_RGBA8888,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_ABGR8888,
+		.rgb		= true,
+		.swap		= false,
+		.chroma_sub	= false,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+	}, {
+		.drm_fmt	= DRM_FORMAT_BGRA8888,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_ABGR8888,
+		.rgb		= true,
+		.swap		= true,
+		.chroma_sub	= false,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+	}, {
+		.drm_fmt	= DRM_FORMAT_BGR888,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGB888,
+		.rgb		= true,
+		.swap		= false,
+		.chroma_sub	= false,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+	}, {
+		.drm_fmt	= DRM_FORMAT_RGB888,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_BGR888,
+		.rgb		= true,
+		.swap		= false,
+		.chroma_sub	= false,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+	}, {
+		.drm_fmt	= DRM_FORMAT_RGBA5551,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA5551,
+		.rgb		= true,
+		.swap		= false,
+		.chroma_sub	= false,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_5BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_5BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_5BIT_SF,
+	}, {
+		.drm_fmt	= DRM_FORMAT_BGRA5551,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA5551,
+		.rgb		= true,
+		.swap		= true,
+		.chroma_sub	= false,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_5BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_5BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_5BIT_SF,
+	}, {
+		.drm_fmt	= DRM_FORMAT_RGBA4444,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA4444,
+		.rgb		= true,
+		.swap		= false,
+		.chroma_sub	= false,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_4BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_4BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_4BIT_SF,
+	}, {
+		.drm_fmt	= DRM_FORMAT_BGRA4444,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGBA4444,
+		.rgb		= true,
+		.swap		= true,
+		.chroma_sub	= false,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_4BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_4BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_4BIT_SF,
+	}, {
+		.drm_fmt	= DRM_FORMAT_RGB565,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGB565,
+		.rgb		= true,
+		.swap		= false,
+		.chroma_sub	= false,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_5BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_6BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_5BIT_SF,
+	}, {
+		.drm_fmt	= DRM_FORMAT_BGR565,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_RGB565,
+		.rgb		= true,
+		.swap		= true,
+		.chroma_sub	= false,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_5BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_6BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_5BIT_SF,
+	}
+};
+
+/* List of live formats */
+/* Format can be combination of color, bpc, and cb-cr order.
+ * - Color: RGB / YUV444 / YUV422 / Y only
+ * - BPC: 6, 8, 10, 12
+ * - Swap: Cb and Cr swap
+ * which can be 32 bus formats. Only list the subset of those for now.
+ */
+static const struct zynqmp_disp_fmt av_buf_live_fmts[] = {
+	{
+		.bus_fmt	= MEDIA_BUS_FMT_RGB666_1X18,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_6 |
+				  ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_RGB,
+		.rgb		= true,
+		.swap		= false,
+		.chroma_sub	= false,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_6BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_6BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_6BIT_SF,
+	}, {
+		.bus_fmt	= MEDIA_BUS_FMT_RBG888_1X24,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_8 |
+				  ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_RGB,
+		.rgb		= true,
+		.swap		= false,
+		.chroma_sub	= false,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+	}, {
+		.bus_fmt	= MEDIA_BUS_FMT_UYVY8_1X16,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_8 |
+				  ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV422,
+		.rgb		= false,
+		.swap		= false,
+		.chroma_sub	= true,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+	}, {
+		.bus_fmt	= MEDIA_BUS_FMT_VUY8_1X24,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_8 |
+				  ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV444,
+		.rgb		= false,
+		.swap		= false,
+		.chroma_sub	= false,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_8BIT_SF,
+	}, {
+		.bus_fmt	= MEDIA_BUS_FMT_UYVY10_1X20,
+		.disp_fmt	= ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_BPC_10 |
+				  ZYNQMP_DISP_AV_BUF_LIVE_CONFIG_FMT_YUV422,
+		.rgb		= false,
+		.swap		= false,
+		.chroma_sub	= true,
+		.sf[0]		= ZYNQMP_DISP_AV_BUF_10BIT_SF,
+		.sf[1]		= ZYNQMP_DISP_AV_BUF_10BIT_SF,
+		.sf[2]		= ZYNQMP_DISP_AV_BUF_10BIT_SF,
+	}
+};
+
+/**
+ * zynqmp_disp_av_buf_set_fmt - Set the input formats
+ * @av_buf: av buffer manager
+ * @fmt: formats
+ *
+ * Set the av buffer manager format to @fmt. @fmt should have valid values
+ * for both video and graphics layer.
+ */
+static void
+zynqmp_disp_av_buf_set_fmt(struct zynqmp_disp_av_buf *av_buf, u32 fmt)
+{
+	zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_FMT, fmt);
+}
+
+/**
+ * zynqmp_disp_av_buf_get_fmt - Get the input formats
+ * @av_buf: av buffer manager
+ *
+ * Get the input formats (which include video and graphics) of
+ * av buffer manager.
+ *
+ * Return: value of ZYNQMP_DISP_AV_BUF_FMT register.
+ */
+static u32
+zynqmp_disp_av_buf_get_fmt(struct zynqmp_disp_av_buf *av_buf)
+{
+	return zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_FMT);
+}
+
+/**
+ * zynqmp_disp_av_buf_set_live_fmt - Set the live_input format
+ * @av_buf: av buffer manager
+ * @fmt: format
+ * @is_vid: if it's for video layer
+ *
+ * Set the live input format to @fmt. @fmt should have valid values.
+ * @vid will determine if it's for video layer or graphics layer
+ * @fmt should be a valid hardware value.
+ */
+static void zynqmp_disp_av_buf_set_live_fmt(struct zynqmp_disp_av_buf *av_buf,
+					    u32 fmt, bool is_vid)
+{
+	u32 offset;
+
+	if (is_vid)
+		offset = ZYNQMP_DISP_AV_BUF_LIVE_VID_CONFIG;
+	else
+		offset = ZYNQMP_DISP_AV_BUF_LIVE_GFX_CONFIG;
+
+	zynqmp_disp_write(av_buf->base, offset, fmt);
+}
+
+/**
+ * zynqmp_disp_av_buf_set_vid_clock_src - Set the video clock source
+ * @av_buf: av buffer manager
+ * @from_ps: flag if the video clock is from ps
+ *
+ * Set the video clock source based on @from_ps. It can come from either PS or
+ * PL.
+ */
+static void
+zynqmp_disp_av_buf_set_vid_clock_src(struct zynqmp_disp_av_buf *av_buf,
+				     bool from_ps)
+{
+	u32 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC);
+
+	if (from_ps)
+		reg |= ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_FROM_PS;
+	else
+		reg &= ~ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_FROM_PS;
+	zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC, reg);
+}
+
+/**
+ * zynqmp_disp_av_buf_vid_clock_src_is_ps - if ps clock is used
+ * @av_buf: av buffer manager
+ *
+ * Return: if ps clock is used
+ */
+static bool
+zynqmp_disp_av_buf_vid_clock_src_is_ps(struct zynqmp_disp_av_buf *av_buf)
+{
+	u32 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC);
+
+	return !!(reg & ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_FROM_PS);
+}
+
+/**
+ * zynqmp_disp_av_buf_set_vid_timing_src - Set the video timing source
+ * @av_buf: av buffer manager
+ * @internal: flag if the video timing is generated internally
+ *
+ * Set the video timing source based on @internal. It can come externally or
+ * be generated internally.
+ */
+static void
+zynqmp_disp_av_buf_set_vid_timing_src(struct zynqmp_disp_av_buf *av_buf,
+				      bool internal)
+{
+	u32 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC);
+
+	if (internal)
+		reg |= ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_INTERNAL_TIMING;
+	else
+		reg &= ~ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_INTERNAL_TIMING;
+	zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC, reg);
+}
+
+/**
+ * zynqmp_disp_av_buf_vid_timing_src_is_int - if internal timing is used
+ * @av_buf: av buffer manager
+ *
+ * Return: if the internal timing is used
+ */
+static bool
+zynqmp_disp_av_buf_vid_timing_src_is_int(struct zynqmp_disp_av_buf *av_buf)
+{
+	u32 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC);
+
+	return !!(reg & ZYNQMP_DISP_AV_BUF_CLK_SRC_VID_INTERNAL_TIMING);
+}
+
+/**
+ * zynqmp_disp_av_buf_set_aud_clock_src - Set the audio clock source
+ * @av_buf: av buffer manager
+ * @from_ps: flag if the video clock is from ps
+ *
+ * Set the audio clock source based on @from_ps. It can come from either PS or
+ * PL.
+ */
+static void
+zynqmp_disp_av_buf_set_aud_clock_src(struct zynqmp_disp_av_buf *av_buf,
+				     bool from_ps)
+{
+	u32 reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC);
+
+	if (from_ps)
+		reg |= ZYNQMP_DISP_AV_BUF_CLK_SRC_AUD_FROM_PS;
+	else
+		reg &= ~ZYNQMP_DISP_AV_BUF_CLK_SRC_AUD_FROM_PS;
+	zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_CLK_SRC, reg);
+}
+
+/**
+ * zynqmp_disp_av_buf_enable_buf - Enable buffers
+ * @av_buf: av buffer manager
+ *
+ * Enable all (video and audio) buffers.
+ */
+static void
+zynqmp_disp_av_buf_enable_buf(struct zynqmp_disp_av_buf *av_buf)
+{
+	u32 reg, i;
+
+	reg = ZYNQMP_DISP_AV_BUF_CHBUF_EN;
+	reg |= ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_MAX <<
+	       ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_SHIFT;
+
+	for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_VID_GFX_BUFFERS; i++)
+		zynqmp_disp_write(av_buf->base,
+				  ZYNQMP_DISP_AV_BUF_CHBUF + i * 4, reg);
+
+	reg = ZYNQMP_DISP_AV_BUF_CHBUF_EN;
+	reg |= ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_AUD_MAX <<
+	       ZYNQMP_DISP_AV_BUF_CHBUF_BURST_LEN_SHIFT;
+
+	for (; i < ZYNQMP_DISP_AV_BUF_NUM_BUFFERS; i++)
+		zynqmp_disp_write(av_buf->base,
+				  ZYNQMP_DISP_AV_BUF_CHBUF + i * 4, reg);
+}
+
+/**
+ * zynqmp_disp_av_buf_disable_buf - Disable buffers
+ * @av_buf: av buffer manager
+ *
+ * Disable all (video and audio) buffers.
+ */
+static void
+zynqmp_disp_av_buf_disable_buf(struct zynqmp_disp_av_buf *av_buf)
+{
+	u32 reg, i;
+
+	reg = ZYNQMP_DISP_AV_BUF_CHBUF_FLUSH & ~ZYNQMP_DISP_AV_BUF_CHBUF_EN;
+	for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_BUFFERS; i++)
+		zynqmp_disp_write(av_buf->base,
+				  ZYNQMP_DISP_AV_BUF_CHBUF + i * 4, reg);
+}
+
+/**
+ * zynqmp_disp_av_buf_enable_aud - Enable audio
+ * @av_buf: av buffer manager
+ *
+ * Enable all audio buffers.
+ */
+static void
+zynqmp_disp_av_buf_enable_aud(struct zynqmp_disp_av_buf *av_buf)
+{
+	u32 reg;
+
+	reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT);
+	reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_MASK;
+	reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_MEM;
+	reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_AUD2_EN;
+	zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT, reg);
+}
+
+/**
+ * zynqmp_disp_av_buf_enable - Enable the video pipe
+ * @av_buf: av buffer manager
+ *
+ * De-assert the video pipe reset
+ */
+static void
+zynqmp_disp_av_buf_enable(struct zynqmp_disp_av_buf *av_buf)
+{
+	zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_SRST_REG, 0);
+}
+
+/**
+ * zynqmp_disp_av_buf_disable - Disable the video pipe
+ * @av_buf: av buffer manager
+ *
+ * Assert the video pipe reset
+ */
+static void
+zynqmp_disp_av_buf_disable(struct zynqmp_disp_av_buf *av_buf)
+{
+	zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_SRST_REG,
+			  ZYNQMP_DISP_AV_BUF_SRST_REG_VID_RST);
+}
+
+/**
+ * zynqmp_disp_av_buf_disable_aud - Disable audio
+ * @av_buf: av buffer manager
+ *
+ * Disable all audio buffers.
+ */
+static void
+zynqmp_disp_av_buf_disable_aud(struct zynqmp_disp_av_buf *av_buf)
+{
+	u32 reg;
+
+	reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT);
+	reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_MASK;
+	reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_AUD1_DISABLE;
+	reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_AUD2_EN;
+	zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT, reg);
+}
+
+/**
+ * zynqmp_disp_av_buf_set_tpg - Set TPG mode
+ * @av_buf: av buffer manager
+ * @tpg_on: if TPG should be on
+ *
+ * Set the TPG mode based on @tpg_on.
+ */
+static void zynqmp_disp_av_buf_set_tpg(struct zynqmp_disp_av_buf *av_buf,
+				       bool tpg_on)
+{
+	u32 reg;
+
+	reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT);
+	reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MASK;
+	if (tpg_on)
+		reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_PATTERN;
+	else
+		reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_PATTERN;
+	zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT, reg);
+}
+
+/**
+ * zynqmp_disp_av_buf_enable_vid - Enable the video layer buffer
+ * @av_buf: av buffer manager
+ * @layer: layer to enable
+ * @mode: operation mode of layer
+ *
+ * Enable the video/graphics buffer for @layer.
+ */
+static void zynqmp_disp_av_buf_enable_vid(struct zynqmp_disp_av_buf *av_buf,
+					  struct zynqmp_disp_layer *layer,
+					  enum zynqmp_disp_layer_mode mode)
+{
+	u32 reg;
+
+	reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT);
+	if (layer->id == ZYNQMP_DISP_LAYER_VID) {
+		reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MASK;
+		if (mode == ZYNQMP_DISP_LAYER_NONLIVE)
+			reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MEM;
+		else
+			reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_LIVE;
+	} else {
+		reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MASK;
+		reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MEM;
+		if (mode == ZYNQMP_DISP_LAYER_NONLIVE)
+			reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MEM;
+		else
+			reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_LIVE;
+	}
+	zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT, reg);
+}
+
+/**
+ * zynqmp_disp_av_buf_disable_vid - Disable the video layer buffer
+ * @av_buf: av buffer manager
+ * @layer: layer to disable
+ *
+ * Disable the video/graphics buffer for @layer.
+ */
+static void
+zynqmp_disp_av_buf_disable_vid(struct zynqmp_disp_av_buf *av_buf,
+			       struct zynqmp_disp_layer *layer)
+{
+	u32 reg;
+
+	reg = zynqmp_disp_read(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT);
+	if (layer->id == ZYNQMP_DISP_LAYER_VID) {
+		reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MASK;
+		reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_NONE;
+	} else {
+		reg &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MASK;
+		reg |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_DISABLE;
+	}
+	zynqmp_disp_write(av_buf->base, ZYNQMP_DISP_AV_BUF_OUTPUT, reg);
+}
+
+/**
+ * zynqmp_disp_av_buf_init_sf - Initialize scaling factors
+ * @av_buf: av buffer manager
+ * @vid_fmt: video format descriptor
+ * @gfx_fmt: graphics format descriptor
+ *
+ * Initialize scaling factors for both video and graphics layers.
+ * If the format descriptor is NULL, the function skips the programming.
+ */
+static void zynqmp_disp_av_buf_init_sf(struct zynqmp_disp_av_buf *av_buf,
+				       const struct zynqmp_disp_fmt *vid_fmt,
+				       const struct zynqmp_disp_fmt *gfx_fmt)
+{
+	unsigned int i;
+	u32 offset;
+
+	if (gfx_fmt) {
+		offset = ZYNQMP_DISP_AV_BUF_GFX_COMP0_SF;
+		for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_SF; i++)
+			zynqmp_disp_write(av_buf->base, offset + i * 4,
+					  gfx_fmt->sf[i]);
+	}
+
+	if (vid_fmt) {
+		offset = ZYNQMP_DISP_AV_BUF_VID_COMP0_SF;
+		for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_SF; i++)
+			zynqmp_disp_write(av_buf->base, offset + i * 4,
+					  vid_fmt->sf[i]);
+	}
+}
+
+/**
+ * zynqmp_disp_av_buf_init_live_sf - Initialize scaling factors for live source
+ * @av_buf: av buffer manager
+ * @fmt: format descriptor
+ * @is_vid: flag if this is for video layer
+ *
+ * Initialize scaling factors for live source.
+ */
+static void zynqmp_disp_av_buf_init_live_sf(struct zynqmp_disp_av_buf *av_buf,
+					    const struct zynqmp_disp_fmt *fmt,
+					    bool is_vid)
+{
+	unsigned int i;
+	u32 offset;
+
+	if (is_vid)
+		offset = ZYNQMP_DISP_AV_BUF_LIVE_VID_COMP0_SF;
+	else
+		offset = ZYNQMP_DISP_AV_BUF_LIVE_GFX_COMP0_SF;
+
+	for (i = 0; i < ZYNQMP_DISP_AV_BUF_NUM_SF; i++)
+		zynqmp_disp_write(av_buf->base, offset + i * 4,
+				  fmt->sf[i]);
+}
+
+/*
+ * Audio functions
+ */
+
+/**
+ * zynqmp_disp_aud_init - Initialize the audio
+ * @aud: audio
+ *
+ * Initialize the audio with default mixer volume. The de-assertion will
+ * initialize the audio states.
+ */
+static void zynqmp_disp_aud_init(struct zynqmp_disp_aud *aud)
+{
+	/* Clear the audio soft reset register as it's an non-reset flop */
+	zynqmp_disp_write(aud->base, ZYNQMP_DISP_AUD_SOFT_RESET, 0);
+	zynqmp_disp_write(aud->base, ZYNQMP_DISP_AUD_MIXER_VOLUME,
+			  ZYNQMP_DISP_AUD_MIXER_VOLUME_NO_SCALE);
+}
+
+/**
+ * zynqmp_disp_aud_deinit - De-initialize the audio
+ * @aud: audio
+ *
+ * Put the audio in reset.
+ */
+static void zynqmp_disp_aud_deinit(struct zynqmp_disp_aud *aud)
+{
+	zynqmp_disp_set(aud->base, ZYNQMP_DISP_AUD_SOFT_RESET,
+			ZYNQMP_DISP_AUD_SOFT_RESET_AUD_SRST);
+}
+
+/*
+ * ZynqMP Display layer functions
+ */
+
+/**
+ * zynqmp_disp_layer_check_size - Verify width and height for the layer
+ * @disp: Display subsystem
+ * @layer: layer
+ * @width: width
+ * @height: height
+ *
+ * The Display subsystem has the limitation that both layers should have
+ * identical size. This function stores width and height of @layer, and verifies
+ * if the size (width and height) is valid.
+ *
+ * Return: 0 on success, or -EINVAL if width or/and height is invalid.
+ */
+static int zynqmp_disp_layer_check_size(struct zynqmp_disp *disp,
+					struct zynqmp_disp_layer *layer,
+					u32 width, u32 height)
+{
+	struct zynqmp_disp_layer *other = layer->other;
+
+	if (other->enabled && (other->w != width || other->h != height)) {
+		dev_err(disp->dev, "Layer width:height must be %d:%d\n",
+			other->w, other->h);
+		return -EINVAL;
+	}
+
+	layer->w = width;
+	layer->h = height;
+
+	return 0;
+}
+
+/**
+ * zynqmp_disp_map_fmt - Find the Display subsystem format for given drm format
+ * @fmts: format table to look up
+ * @size: size of the table @fmts
+ * @drm_fmt: DRM format to search
+ *
+ * Search a Display subsystem format corresponding to the given DRM format
+ * @drm_fmt, and return the format descriptor which contains the Display
+ * subsystem format value.
+ *
+ * Return: a Display subsystem format descriptor on success, or NULL.
+ */
+static const struct zynqmp_disp_fmt *
+zynqmp_disp_map_fmt(const struct zynqmp_disp_fmt fmts[],
+		    unsigned int size, uint32_t drm_fmt)
+{
+	unsigned int i;
+
+	for (i = 0; i < size; i++)
+		if (fmts[i].drm_fmt == drm_fmt)
+			return &fmts[i];
+
+	return NULL;
+}
+
+/**
+ * zynqmp_disp_set_fmt - Set the format of the layer
+ * @disp: Display subsystem
+ * @layer: layer to set the format
+ * @drm_fmt: DRM format to set
+ *
+ * Set the format of the given layer to @drm_fmt.
+ *
+ * Return: 0 on success. -EINVAL if @drm_fmt is not supported by the layer.
+ */
+static int zynqmp_disp_layer_set_fmt(struct zynqmp_disp *disp,
+				     struct zynqmp_disp_layer *layer,
+				     uint32_t drm_fmt)
+{
+	const struct zynqmp_disp_fmt *fmt;
+	const struct zynqmp_disp_fmt *vid_fmt = NULL, *gfx_fmt = NULL;
+	u32 size, fmts, mask;
+
+	if (layer->id == ZYNQMP_DISP_LAYER_VID) {
+		size = ARRAY_SIZE(av_buf_vid_fmts);
+		mask = ~ZYNQMP_DISP_AV_BUF_FMT_NL_VID_MASK;
+		fmt = zynqmp_disp_map_fmt(av_buf_vid_fmts, size, drm_fmt);
+		vid_fmt = fmt;
+	} else {
+		size = ARRAY_SIZE(av_buf_gfx_fmts);
+		mask = ~ZYNQMP_DISP_AV_BUF_FMT_NL_GFX_MASK;
+		fmt = zynqmp_disp_map_fmt(av_buf_gfx_fmts, size, drm_fmt);
+		gfx_fmt = fmt;
+	}
+
+	if (!fmt)
+		return -EINVAL;
+
+	fmts = zynqmp_disp_av_buf_get_fmt(&disp->av_buf);
+	fmts &= mask;
+	fmts |= fmt->disp_fmt;
+	zynqmp_disp_av_buf_set_fmt(&disp->av_buf, fmts);
+	zynqmp_disp_av_buf_init_sf(&disp->av_buf, vid_fmt, gfx_fmt);
+	layer->fmt = fmt;
+
+	return 0;
+}
+
+/**
+ * zynqmp_disp_map_live_fmt - Find the hardware format for given bus format
+ * @fmts: format table to look up
+ * @size: size of the table @fmts
+ * @bus_fmt: bus format to search
+ *
+ * Search a Display subsystem format corresponding to the given bus format
+ * @bus_fmt, and return the format descriptor which contains the Display
+ * subsystem format value.
+ *
+ * Return: a Display subsystem format descriptor on success, or NULL.
+ */
+static const struct zynqmp_disp_fmt *
+zynqmp_disp_map_live_fmt(const struct zynqmp_disp_fmt fmts[],
+			 unsigned int size, uint32_t bus_fmt)
+{
+	unsigned int i;
+
+	for (i = 0; i < size; i++)
+		if (fmts[i].bus_fmt == bus_fmt)
+			return &fmts[i];
+
+	return NULL;
+}
+
+/**
+ * zynqmp_disp_set_live_fmt - Set the live format of the layer
+ * @disp: Display subsystem
+ * @layer: layer to set the format
+ * @bus_fmt: bus format to set
+ *
+ * Set the live format of the given layer to @live_fmt.
+ *
+ * Return: 0 on success. -EINVAL if @bus_fmt is not supported by the layer.
+ */
+static int zynqmp_disp_layer_set_live_fmt(struct zynqmp_disp *disp,
+					  struct zynqmp_disp_layer *layer,
+					  uint32_t bus_fmt)
+{
+	const struct zynqmp_disp_fmt *fmt;
+	u32 size;
+	bool is_vid = layer->id == ZYNQMP_DISP_LAYER_VID;
+
+	size = ARRAY_SIZE(av_buf_live_fmts);
+	fmt = zynqmp_disp_map_live_fmt(av_buf_live_fmts, size, bus_fmt);
+	if (!fmt)
+		return -EINVAL;
+
+	zynqmp_disp_av_buf_set_live_fmt(&disp->av_buf, fmt->disp_fmt, is_vid);
+	zynqmp_disp_av_buf_init_live_sf(&disp->av_buf, fmt, is_vid);
+	layer->fmt = fmt;
+
+	return 0;
+}
+
+/**
+ * zynqmp_disp_set_tpg - Enable or disable TPG
+ * @disp: Display subsystem
+ * @layer: Video layer
+ * @tpg_on: flag if TPG needs to be enabled or disabled
+ *
+ * Enable / disable the TPG mode on the video layer @layer depending on
+ * @tpg_on. The video layer should be disabled prior to enable request.
+ *
+ * Return: 0 on success. -ENODEV if it's not video layer. -EIO if
+ * the video layer is enabled.
+ */
+static int zynqmp_disp_layer_set_tpg(struct zynqmp_disp *disp,
+				     struct zynqmp_disp_layer *layer,
+				     bool tpg_on)
+{
+	if (layer->id != ZYNQMP_DISP_LAYER_VID) {
+		dev_err(disp->dev,
+			"only the video layer has the tpg mode\n");
+		return -ENODEV;
+	}
+
+	if (layer->enabled) {
+		dev_err(disp->dev,
+			"the video layer should be disabled for tpg mode\n");
+		return -EIO;
+	}
+
+	zynqmp_disp_blend_layer_coeff(&disp->blend, layer, tpg_on);
+	zynqmp_disp_av_buf_set_tpg(&disp->av_buf, tpg_on);
+	disp->tpg_on = tpg_on;
+
+	return 0;
+}
+
+/**
+ * zynqmp_disp_get_tpg - Get the TPG mode status
+ * @disp: Display subsystem
+ * @layer: Video layer
+ *
+ * Return if the TPG is enabled or not.
+ *
+ * Return: true if TPG is on, otherwise false
+ */
+static bool zynqmp_disp_layer_get_tpg(struct zynqmp_disp *disp,
+				      struct zynqmp_disp_layer *layer)
+{
+	return disp->tpg_on;
+}
+
+/**
+ * zynqmp_disp_get_fmt - Get the supported DRM formats of the layer
+ * @disp: Display subsystem
+ * @layer: layer to get the formats
+ * @drm_fmts: pointer to array of DRM format strings
+ * @num_fmts: pointer to number of returned DRM formats
+ *
+ * Get the supported DRM formats of the given layer.
+ */
+static void zynqmp_disp_layer_get_fmts(struct zynqmp_disp *disp,
+				       struct zynqmp_disp_layer *layer,
+				       u32 **drm_fmts, unsigned int *num_fmts)
+{
+	*drm_fmts = layer->drm_fmts;
+	*num_fmts = layer->num_fmts;
+}
+
+/**
+ * zynqmp_disp_layer_enable - Enable the layer
+ * @disp: Display subsystem
+ * @layer: layer to esable
+ * @mode: operation mode
+ *
+ * Enable the layer @layer.
+ *
+ * Return: 0 on success, otherwise error code.
+ */
+static int zynqmp_disp_layer_enable(struct zynqmp_disp *disp,
+				    struct zynqmp_disp_layer *layer,
+				    enum zynqmp_disp_layer_mode mode)
+{
+	struct device *dev = disp->dev;
+	struct dma_async_tx_descriptor *desc;
+	unsigned long flags;
+	unsigned int i;
+
+	if (layer->enabled && layer->mode != mode) {
+		dev_err(dev, "layer is already enabled in different mode\n");
+		return -EBUSY;
+	}
+
+	zynqmp_disp_av_buf_enable_vid(&disp->av_buf, layer, mode);
+	zynqmp_disp_blend_layer_enable(&disp->blend, layer);
+
+	layer->enabled = true;
+	layer->mode = mode;
+
+	if (mode == ZYNQMP_DISP_LAYER_LIVE)
+		return 0;
+
+	for (i = 0; i < ZYNQMP_DISP_MAX_NUM_SUB_PLANES; i++) {
+		struct zynqmp_disp_layer_dma *dma = &layer->dma[i];
+
+		if (dma->chan && dma->is_active) {
+			flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
+			desc = dmaengine_prep_interleaved_dma(dma->chan,
+							      &dma->xt, flags);
+			if (!desc) {
+				dev_err(dev, "failed to prep DMA descriptor\n");
+				return -ENOMEM;
+			}
+
+			dmaengine_submit(desc);
+			dma_async_issue_pending(dma->chan);
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * zynqmp_disp_layer_disable - Disable the layer
+ * @disp: Display subsystem
+ * @layer: layer to disable
+ * @mode: operation mode
+ *
+ * Disable the layer @layer.
+ *
+ * Return: 0 on success, or -EBUSY if the layer is in different mode.
+ */
+static int zynqmp_disp_layer_disable(struct zynqmp_disp *disp,
+				     struct zynqmp_disp_layer *layer,
+				     enum zynqmp_disp_layer_mode mode)
+{
+	struct device *dev = disp->dev;
+	unsigned int i;
+
+	if (layer->mode != mode) {
+		dev_err(dev, "the layer is operating in different mode\n");
+		return -EBUSY;
+	}
+
+	for (i = 0; i < ZYNQMP_DISP_MAX_NUM_SUB_PLANES; i++)
+		if (layer->dma[i].chan && layer->dma[i].is_active)
+			dmaengine_terminate_sync(layer->dma[i].chan);
+
+	zynqmp_disp_av_buf_disable_vid(&disp->av_buf, layer);
+	zynqmp_disp_blend_layer_disable(&disp->blend, layer);
+	layer->enabled = false;
+
+	return 0;
+}
+
+/**
+ * zynqmp_disp_layer_request_dma - Request DMA channels for a layer
+ * @disp: Display subsystem
+ * @layer: layer to request DMA channels
+ * @name: identifier string for layer type
+ *
+ * Request DMA engine channels for corresponding layer.
+ *
+ * Return: 0 on success, or err value from of_dma_request_slave_channel().
+ */
+static int
+zynqmp_disp_layer_request_dma(struct zynqmp_disp *disp,
+			      struct zynqmp_disp_layer *layer, const char *name)
+{
+	struct zynqmp_disp_layer_dma *dma;
+	unsigned int i;
+	int ret;
+
+	for (i = 0; i < layer->num_chan; i++) {
+		char temp[16];
+
+		dma = &layer->dma[i];
+		snprintf(temp, sizeof(temp), "%s%d", name, i);
+		dma->chan = of_dma_request_slave_channel(layer->of_node,
+							 temp);
+		if (IS_ERR(dma->chan)) {
+			dev_err(disp->dev, "failed to request dma channel\n");
+			ret = PTR_ERR(dma->chan);
+			dma->chan = NULL;
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * zynqmp_disp_layer_release_dma - Release DMA channels for a layer
+ * @disp: Display subsystem
+ * @layer: layer to release DMA channels
+ *
+ * Release the dma channels associated with @layer.
+ */
+static void zynqmp_disp_layer_release_dma(struct zynqmp_disp *disp,
+					  struct zynqmp_disp_layer *layer)
+{
+	unsigned int i;
+
+	for (i = 0; i < layer->num_chan; i++) {
+		if (layer->dma[i].chan) {
+			/* Make sure the channel is terminated before release */
+			dmaengine_terminate_all(layer->dma[i].chan);
+			dma_release_channel(layer->dma[i].chan);
+		}
+	}
+}
+
+/**
+ * zynqmp_disp_layer_is_live - if any layer is live
+ * @disp: Display subsystem
+ *
+ * Return: true if any layer is live
+ */
+static bool zynqmp_disp_layer_is_live(struct zynqmp_disp *disp)
+{
+	unsigned int i;
+
+	for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++) {
+		if (disp->layers[i].enabled &&
+		    disp->layers[i].mode == ZYNQMP_DISP_LAYER_LIVE)
+			return true;
+	}
+
+	return false;
+}
+
+/**
+ * zynqmp_disp_layer_is_enabled - if any layer is enabled
+ * @disp: Display subsystem
+ *
+ * Return: true if any layer is enabled
+ */
+static bool zynqmp_disp_layer_is_enabled(struct zynqmp_disp *disp)
+{
+	unsigned int i;
+
+	for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++)
+		if (disp->layers[i].enabled)
+			return true;
+
+	return false;
+}
+
+/**
+ * zynqmp_disp_layer_destroy - Destroy all layers
+ * @disp: Display subsystem
+ *
+ * Destroy all layers.
+ */
+static void zynqmp_disp_layer_destroy(struct zynqmp_disp *disp)
+{
+	unsigned int i;
+
+	for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++) {
+		zynqmp_disp_layer_release_dma(disp, &disp->layers[i]);
+		if (disp->layers[i].of_node)
+			of_node_put(disp->layers[i].of_node);
+	}
+}
+
+/**
+ * zynqmp_disp_layer_create - Create all layers
+ * @disp: Display subsystem
+ *
+ * Create all layers.
+ *
+ * Return: 0 on success, otherwise error code from failed function
+ */
+static int zynqmp_disp_layer_create(struct zynqmp_disp *disp)
+{
+	struct zynqmp_disp_layer *layer;
+	unsigned int i;
+	int num_chans[ZYNQMP_DISP_NUM_LAYERS] = { 3, 1 };
+	const char * const dma_name[] = { "vid", "gfx" };
+	int ret = -EINVAL;
+
+	for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++) {
+		char temp[16];
+
+		layer = &disp->layers[i];
+		layer->id = (enum zynqmp_disp_layer_type)i;
+		layer->offset = i * 4;
+		layer->other = &disp->layers[!i];
+		layer->num_chan = num_chans[i];
+		snprintf(temp, sizeof(temp), "%s-layer", dma_name[i]);
+		layer->of_node = of_get_child_by_name(disp->dev->of_node, temp);
+		if (!layer->of_node)
+			goto err;
+		ret = zynqmp_disp_layer_request_dma(disp, layer, dma_name[i]);
+		if (ret)
+			goto err;
+		layer->disp = disp;
+	}
+
+	return 0;
+
+err:
+	zynqmp_disp_layer_destroy(disp);
+	return ret;
+}
+
+/*
+ * ZynqMP Display internal functions
+ */
+
+/*
+ * Output format enumeration.
+ * The ID should be aligned with blend_output_fmts.
+ * The string should be aligned with how zynqmp_dp_set_color() decodes.
+ */
+static struct drm_prop_enum_list zynqmp_disp_color_enum[] = {
+	{ 0, "rgb" },
+	{ 1, "ycrcb444" },
+	{ 2, "ycrcb422" },
+	{ 3, "yonly" },
+};
+
+/**
+ * zynqmp_disp_set_output_fmt - Set the output format
+ * @disp: Display subsystem
+ * @id: the format ID. Refer to zynqmp_disp_color_enum[].
+ *
+ * This function sets the output format of the display / blender as well as
+ * the format of DP controller. The @id should be aligned with
+ * zynqmp_disp_color_enum.
+ */
+static void
+zynqmp_disp_set_output_fmt(struct zynqmp_disp *disp, unsigned int id)
+{
+	const struct zynqmp_disp_fmt *fmt = &blend_output_fmts[id];
+
+	zynqmp_dp_set_color(disp->dpsub->dp, zynqmp_disp_color_enum[id].name);
+	zynqmp_disp_blend_set_output_fmt(&disp->blend, fmt->disp_fmt);
+}
+
+/**
+ * zynqmp_disp_set_bg_color - Set the background color
+ * @disp: Display subsystem
+ * @c0: color component 0
+ * @c1: color component 1
+ * @c2: color component 2
+ *
+ * Set the background color with given color components (@c0, @c1, @c2).
+ */
+static void zynqmp_disp_set_bg_color(struct zynqmp_disp *disp,
+				     u32 c0, u32 c1, u32 c2)
+{
+	zynqmp_disp_blend_set_bg_color(&disp->blend, c0, c1, c2);
+}
+
+/**
+ * zynqmp_disp_set_alpha - Set the alpha value
+ * @disp: Display subsystem
+ * @alpha: alpha value to set
+ *
+ * Set the alpha value for blending.
+ */
+static void zynqmp_disp_set_alpha(struct zynqmp_disp *disp, u32 alpha)
+{
+	disp->alpha = alpha;
+	zynqmp_disp_blend_set_alpha(&disp->blend, alpha);
+}
+
+/**
+ * zynqmp_disp_get_alpha - Get the alpha value
+ * @disp: Display subsystem
+ *
+ * Get the alpha value for blending.
+ *
+ * Return: current alpha value.
+ */
+static u32 zynqmp_disp_get_alpha(struct zynqmp_disp *disp)
+{
+	return disp->alpha;
+}
+
+/**
+ * zynqmp_disp_set_g_alpha - Enable/disable the global alpha blending
+ * @disp: Display subsystem
+ * @enable: flag to enable or disable alpha blending
+ *
+ * Set the alpha value for blending.
+ */
+static void zynqmp_disp_set_g_alpha(struct zynqmp_disp *disp, bool enable)
+{
+	disp->alpha_en = enable;
+	zynqmp_disp_blend_enable_alpha(&disp->blend, enable);
+}
+
+/**
+ * zynqmp_disp_get_g_alpha - Get the global alpha status
+ * @disp: Display subsystem
+ *
+ * Get the global alpha statue.
+ *
+ * Return: true if global alpha is enabled, or false.
+ */
+static bool zynqmp_disp_get_g_alpha(struct zynqmp_disp *disp)
+{
+	return disp->alpha_en;
+}
+
+/**
+ * zynqmp_disp_enable - Enable the Display subsystem
+ * @disp: Display subsystem
+ *
+ * Enable the Display subsystem.
+ */
+static void zynqmp_disp_enable(struct zynqmp_disp *disp)
+{
+	bool live;
+
+	if (disp->enabled)
+		return;
+
+	zynqmp_disp_av_buf_enable(&disp->av_buf);
+	/* Choose clock source based on the DT clock handle */
+	zynqmp_disp_av_buf_set_vid_clock_src(&disp->av_buf, !!disp->_ps_pclk);
+	zynqmp_disp_av_buf_set_aud_clock_src(&disp->av_buf, !!disp->_ps_audclk);
+	live = zynqmp_disp_layer_is_live(disp);
+	zynqmp_disp_av_buf_set_vid_timing_src(&disp->av_buf, !live);
+	zynqmp_disp_av_buf_enable_buf(&disp->av_buf);
+	zynqmp_disp_av_buf_enable_aud(&disp->av_buf);
+	zynqmp_disp_aud_init(&disp->aud);
+	disp->enabled = true;
+}
+
+/**
+ * zynqmp_disp_disable - Disable the Display subsystem
+ * @disp: Display subsystem
+ * @force: flag to disable forcefully
+ *
+ * Disable the Display subsystem.
+ */
+static void zynqmp_disp_disable(struct zynqmp_disp *disp, bool force)
+{
+	struct drm_crtc *crtc = &disp->xlnx_crtc.crtc;
+
+	if (!force && (!disp->enabled || zynqmp_disp_layer_is_enabled(disp)))
+		return;
+
+	zynqmp_disp_aud_deinit(&disp->aud);
+	zynqmp_disp_av_buf_disable_aud(&disp->av_buf);
+	zynqmp_disp_av_buf_disable_buf(&disp->av_buf);
+	zynqmp_disp_av_buf_disable(&disp->av_buf);
+
+	/* Mark the flip is done as crtc is disabled anyway */
+	if (crtc->state->event) {
+		complete_all(crtc->state->event->base.completion);
+		crtc->state->event = NULL;
+	}
+
+	disp->enabled = false;
+}
+
+/**
+ * zynqmp_disp_init - Initialize the Display subsystem states
+ * @disp: Display subsystem
+ *
+ * Some states are not initialized as desired. For example, the output select
+ * register resets to the live source. This function is to initialize
+ * some register states as desired.
+ */
+static void zynqmp_disp_init(struct zynqmp_disp *disp)
+{
+	struct zynqmp_disp_layer *layer;
+	unsigned int i;
+
+	for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++) {
+		layer = &disp->layers[i];
+		zynqmp_disp_av_buf_disable_vid(&disp->av_buf, layer);
+	}
+}
+
+/*
+ * ZynqMP Display external functions for zynqmp_dp
+ */
+
+/**
+ * zynqmp_disp_handle_vblank - Handle the vblank event
+ * @disp: Display subsystem
+ *
+ * This function handles the vblank interrupt, and sends an event to
+ * CRTC object. This will be called by the DP vblank interrupt handler.
+ */
+void zynqmp_disp_handle_vblank(struct zynqmp_disp *disp)
+{
+	struct drm_crtc *crtc = &disp->xlnx_crtc.crtc;
+
+	drm_crtc_handle_vblank(crtc);
+}
+
+/**
+ * zynqmp_disp_get_apb_clk_rate - Get the current APB clock rate
+ * @disp: Display subsystem
+ *
+ * Return: the current APB clock rate.
+ */
+unsigned int zynqmp_disp_get_apb_clk_rate(struct zynqmp_disp *disp)
+{
+	return clk_get_rate(disp->aclk);
+}
+
+/**
+ * zynqmp_disp_aud_enabled - If the audio is enabled
+ * @disp: Display subsystem
+ *
+ * Return if the audio is enabled depending on the audio clock.
+ *
+ * Return: true if audio is enabled, or false.
+ */
+bool zynqmp_disp_aud_enabled(struct zynqmp_disp *disp)
+{
+	return !!disp->audclk;
+}
+
+/**
+ * zynqmp_disp_get_aud_clk_rate - Get the current audio clock rate
+ * @disp: Display subsystem
+ *
+ * Return: the current audio clock rate.
+ */
+unsigned int zynqmp_disp_get_aud_clk_rate(struct zynqmp_disp *disp)
+{
+	if (zynqmp_disp_aud_enabled(disp))
+		return 0;
+	return clk_get_rate(disp->aclk);
+}
+
+/**
+ * zynqmp_disp_get_crtc_mask - Return the CRTC bit mask
+ * @disp: Display subsystem
+ *
+ * Return: the crtc mask of the zyqnmp_disp CRTC.
+ */
+uint32_t zynqmp_disp_get_crtc_mask(struct zynqmp_disp *disp)
+{
+	return drm_crtc_mask(&disp->xlnx_crtc.crtc);
+}
+
+/*
+ * DRM plane functions
+ */
+
+static inline struct zynqmp_disp_layer *plane_to_layer(struct drm_plane *plane)
+{
+	return container_of(plane, struct zynqmp_disp_layer, plane);
+}
+
+static int zynqmp_disp_plane_enable(struct drm_plane *plane)
+{
+	struct zynqmp_disp_layer *layer = plane_to_layer(plane);
+	struct zynqmp_disp *disp = layer->disp;
+	int ret;
+
+	zynqmp_disp_set_g_alpha(disp, disp->alpha_en);
+	zynqmp_disp_set_alpha(disp, disp->alpha);
+	ret = zynqmp_disp_layer_enable(layer->disp, layer,
+				       ZYNQMP_DISP_LAYER_NONLIVE);
+	if (ret)
+		return ret;
+
+	if (layer->id == ZYNQMP_DISP_LAYER_GFX && disp->tpg_on) {
+		layer = &disp->layers[ZYNQMP_DISP_LAYER_VID];
+		zynqmp_disp_layer_set_tpg(disp, layer, disp->tpg_on);
+	}
+
+	return 0;
+}
+
+static int zynqmp_disp_plane_disable(struct drm_plane *plane)
+{
+	struct zynqmp_disp_layer *layer = plane_to_layer(plane);
+	struct zynqmp_disp *disp = layer->disp;
+
+	zynqmp_disp_layer_disable(disp, layer, ZYNQMP_DISP_LAYER_NONLIVE);
+	if (layer->id == ZYNQMP_DISP_LAYER_VID && disp->tpg_on)
+		zynqmp_disp_layer_set_tpg(disp, layer, disp->tpg_on);
+
+	return 0;
+}
+
+static int zynqmp_disp_plane_mode_set(struct drm_plane *plane,
+				      struct drm_framebuffer *fb,
+				      int crtc_x, int crtc_y,
+				      unsigned int crtc_w, unsigned int crtc_h,
+				      u32 src_x, u32 src_y,
+				      u32 src_w, u32 src_h)
+{
+	struct zynqmp_disp_layer *layer = plane_to_layer(plane);
+	const struct drm_format_info *info = fb->format;
+	struct device *dev = layer->disp->dev;
+	dma_addr_t paddr;
+	unsigned int i;
+	int ret;
+
+	if (!info) {
+		dev_err(dev, "No format info found\n");
+		return -EINVAL;
+	}
+
+	ret = zynqmp_disp_layer_check_size(layer->disp, layer, src_w, src_h);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < info->num_planes; i++) {
+		unsigned int width = src_w / (i ? info->hsub : 1);
+		unsigned int height = src_h / (i ? info->vsub : 1);
+		int width_bytes;
+
+		paddr = drm_fb_cma_get_gem_addr(fb, plane->state, i);
+		if (!paddr) {
+			dev_err(dev, "failed to get a paddr\n");
+			return -EINVAL;
+		}
+
+		layer->dma[i].xt.numf = height;
+		width_bytes = drm_format_plane_width_bytes(info, i, width);
+		layer->dma[i].sgl[0].size = width_bytes;
+		layer->dma[i].sgl[0].icg = fb->pitches[i] -
+					   layer->dma[i].sgl[0].size;
+		layer->dma[i].xt.src_start = paddr;
+		layer->dma[i].xt.frame_size = 1;
+		layer->dma[i].xt.dir = DMA_MEM_TO_DEV;
+		layer->dma[i].xt.src_sgl = true;
+		layer->dma[i].xt.dst_sgl = false;
+		layer->dma[i].is_active = true;
+	}
+
+	for (; i < ZYNQMP_DISP_MAX_NUM_SUB_PLANES; i++)
+		layer->dma[i].is_active = false;
+
+	ret = zynqmp_disp_layer_set_fmt(layer->disp,  layer, info->format);
+	if (ret)
+		dev_err(dev, "failed to set dp_sub layer fmt\n");
+
+	return ret;
+}
+
+static void zynqmp_disp_plane_destroy(struct drm_plane *plane)
+{
+	struct zynqmp_disp_layer *layer = plane_to_layer(plane);
+
+	xlnx_bridge_unregister(&layer->bridge);
+	drm_plane_cleanup(plane);
+}
+
+static int
+zynqmp_disp_plane_atomic_set_property(struct drm_plane *plane,
+				      struct drm_plane_state *state,
+				      struct drm_property *property, u64 val)
+{
+	struct zynqmp_disp_layer *layer = plane_to_layer(plane);
+	struct zynqmp_disp *disp = layer->disp;
+	int ret = 0;
+
+	if (property == disp->g_alpha_prop)
+		zynqmp_disp_set_alpha(disp, val);
+	else if (property == disp->g_alpha_en_prop)
+		zynqmp_disp_set_g_alpha(disp, val);
+	else if (property == disp->tpg_prop)
+		ret = zynqmp_disp_layer_set_tpg(disp, layer, val);
+	else
+		return -EINVAL;
+
+	return ret;
+}
+
+static int
+zynqmp_disp_plane_atomic_get_property(struct drm_plane *plane,
+				      const struct drm_plane_state *state,
+				      struct drm_property *property,
+				      uint64_t *val)
+{
+	struct zynqmp_disp_layer *layer = plane_to_layer(plane);
+	struct zynqmp_disp *disp = layer->disp;
+	int ret = 0;
+
+	if (property == disp->g_alpha_prop)
+		*val = zynqmp_disp_get_alpha(disp);
+	else if (property == disp->g_alpha_en_prop)
+		*val = zynqmp_disp_get_g_alpha(disp);
+	else if (property == disp->tpg_prop)
+		*val = zynqmp_disp_layer_get_tpg(disp, layer);
+	else
+		return -EINVAL;
+
+	return ret;
+}
+
+static int
+zynqmp_disp_plane_atomic_update_plane(struct drm_plane *plane,
+				      struct drm_crtc *crtc,
+				      struct drm_framebuffer *fb,
+				      int crtc_x, int crtc_y,
+				      unsigned int crtc_w, unsigned int crtc_h,
+				      u32 src_x, u32 src_y,
+				      u32 src_w, u32 src_h,
+				      struct drm_modeset_acquire_ctx *ctx)
+{
+	struct drm_atomic_state *state;
+	struct drm_plane_state *plane_state;
+	int ret;
+
+	state = drm_atomic_state_alloc(plane->dev);
+	if (!state)
+		return -ENOMEM;
+
+	state->acquire_ctx = ctx;
+	plane_state = drm_atomic_get_plane_state(state, plane);
+	if (IS_ERR(plane_state)) {
+		ret = PTR_ERR(plane_state);
+		goto fail;
+	}
+
+	ret = drm_atomic_set_crtc_for_plane(plane_state, crtc);
+	if (ret)
+		goto fail;
+	drm_atomic_set_fb_for_plane(plane_state, fb);
+	plane_state->crtc_x = crtc_x;
+	plane_state->crtc_y = crtc_y;
+	plane_state->crtc_w = crtc_w;
+	plane_state->crtc_h = crtc_h;
+	plane_state->src_x = src_x;
+	plane_state->src_y = src_y;
+	plane_state->src_w = src_w;
+	plane_state->src_h = src_h;
+
+	if (plane == crtc->cursor)
+		state->legacy_cursor_update = true;
+
+	/* Do async-update if possible */
+	state->async_update = !drm_atomic_helper_async_check(plane->dev, state);
+	ret = drm_atomic_commit(state);
+fail:
+	drm_atomic_state_put(state);
+	return ret;
+}
+
+static struct drm_plane_funcs zynqmp_disp_plane_funcs = {
+	.update_plane		= zynqmp_disp_plane_atomic_update_plane,
+	.disable_plane		= drm_atomic_helper_disable_plane,
+	.atomic_set_property	= zynqmp_disp_plane_atomic_set_property,
+	.atomic_get_property	= zynqmp_disp_plane_atomic_get_property,
+	.destroy		= zynqmp_disp_plane_destroy,
+	.reset			= drm_atomic_helper_plane_reset,
+	.atomic_duplicate_state	= drm_atomic_helper_plane_duplicate_state,
+	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
+};
+
+static void
+zynqmp_disp_plane_atomic_update(struct drm_plane *plane,
+				struct drm_plane_state *old_state)
+{
+	int ret;
+
+	if (!plane->state->crtc || !plane->state->fb)
+		return;
+
+	if (plane->state->fb == old_state->fb &&
+	    plane->state->crtc_x == old_state->crtc_x &&
+	    plane->state->crtc_y == old_state->crtc_y &&
+	    plane->state->crtc_w == old_state->crtc_w &&
+	    plane->state->crtc_h == old_state->crtc_h &&
+	    plane->state->src_x == old_state->src_x &&
+	    plane->state->src_y == old_state->src_y &&
+	    plane->state->src_w == old_state->src_w &&
+	    plane->state->src_h == old_state->src_h)
+		return;
+
+	if (old_state->fb &&
+	    old_state->fb->format->format != plane->state->fb->format->format)
+		zynqmp_disp_plane_disable(plane);
+
+	ret = zynqmp_disp_plane_mode_set(plane, plane->state->fb,
+					 plane->state->crtc_x,
+					 plane->state->crtc_y,
+					 plane->state->crtc_w,
+					 plane->state->crtc_h,
+					 plane->state->src_x >> 16,
+					 plane->state->src_y >> 16,
+					 plane->state->src_w >> 16,
+					 plane->state->src_h >> 16);
+	if (ret)
+		return;
+
+	zynqmp_disp_plane_enable(plane);
+}
+
+static void
+zynqmp_disp_plane_atomic_disable(struct drm_plane *plane,
+				 struct drm_plane_state *old_state)
+{
+	zynqmp_disp_plane_disable(plane);
+}
+
+static int zynqmp_disp_plane_atomic_async_check(struct drm_plane *plane,
+						struct drm_plane_state *state)
+{
+	return 0;
+}
+
+static void
+zynqmp_disp_plane_atomic_async_update(struct drm_plane *plane,
+				      struct drm_plane_state *new_state)
+{
+	int ret;
+
+	if (plane->state->fb == new_state->fb)
+		return;
+
+	if (plane->state->fb &&
+	    plane->state->fb->format->format != new_state->fb->format->format)
+		zynqmp_disp_plane_disable(plane);
+
+	 /* Update the current state with new configurations */
+	swap(plane->state->fb, new_state->fb);
+	plane->state->crtc = new_state->crtc;
+	plane->state->crtc_x = new_state->crtc_x;
+	plane->state->crtc_y = new_state->crtc_y;
+	plane->state->crtc_w = new_state->crtc_w;
+	plane->state->crtc_h = new_state->crtc_h;
+	plane->state->src_x = new_state->src_x;
+	plane->state->src_y = new_state->src_y;
+	plane->state->src_w = new_state->src_w;
+	plane->state->src_h = new_state->src_h;
+	plane->state->state = new_state->state;
+
+	ret = zynqmp_disp_plane_mode_set(plane, plane->state->fb,
+					 plane->state->crtc_x,
+					 plane->state->crtc_y,
+					 plane->state->crtc_w,
+					 plane->state->crtc_h,
+					 plane->state->src_x >> 16,
+					 plane->state->src_y >> 16,
+					 plane->state->src_w >> 16,
+					 plane->state->src_h >> 16);
+	if (ret)
+		return;
+
+	zynqmp_disp_plane_enable(plane);
+}
+
+static const struct drm_plane_helper_funcs zynqmp_disp_plane_helper_funcs = {
+	.atomic_update		= zynqmp_disp_plane_atomic_update,
+	.atomic_disable		= zynqmp_disp_plane_atomic_disable,
+	.atomic_async_check	= zynqmp_disp_plane_atomic_async_check,
+	.atomic_async_update	= zynqmp_disp_plane_atomic_async_update,
+};
+
+static int zynqmp_disp_create_plane(struct zynqmp_disp *disp)
+{
+	struct zynqmp_disp_layer *layer;
+	unsigned int i;
+	u32 *fmts = NULL;
+	unsigned int num_fmts = 0;
+	enum drm_plane_type type;
+	int ret;
+
+	/* graphics layer is primary, and video layer is overaly */
+	type = DRM_PLANE_TYPE_OVERLAY;
+	for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++) {
+		layer = &disp->layers[i];
+		zynqmp_disp_layer_get_fmts(disp, layer, &fmts, &num_fmts);
+		ret = drm_universal_plane_init(disp->drm, &layer->plane, 0,
+					       &zynqmp_disp_plane_funcs, fmts,
+					       num_fmts, NULL, type, NULL);
+		if (ret)
+			goto err_plane;
+		drm_plane_helper_add(&layer->plane,
+				     &zynqmp_disp_plane_helper_funcs);
+		type = DRM_PLANE_TYPE_PRIMARY;
+	}
+
+	/* Attach properties to each layers */
+	drm_object_attach_property(&layer->plane.base, disp->g_alpha_prop,
+				   ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_MAX);
+	disp->alpha = ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_MAX;
+	/* Enable the global alpha as default */
+	drm_object_attach_property(&layer->plane.base, disp->g_alpha_en_prop,
+				   true);
+	disp->alpha_en = true;
+
+	layer = &disp->layers[ZYNQMP_DISP_LAYER_VID];
+	drm_object_attach_property(&layer->plane.base, disp->tpg_prop, false);
+
+	return ret;
+
+err_plane:
+	if (i)
+		drm_plane_cleanup(&disp->layers[0].plane);
+	return ret;
+}
+
+static void zynqmp_disp_destroy_plane(struct zynqmp_disp *disp)
+{
+	unsigned int i;
+
+	for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++)
+		zynqmp_disp_plane_destroy(&disp->layers[i].plane);
+}
+
+/*
+ * Xlnx crtc functions
+ */
+
+static inline struct zynqmp_disp *xlnx_crtc_to_disp(struct xlnx_crtc *xlnx_crtc)
+{
+	return container_of(xlnx_crtc, struct zynqmp_disp, xlnx_crtc);
+}
+
+static int zynqmp_disp_get_max_width(struct xlnx_crtc *xlnx_crtc)
+{
+	return ZYNQMP_DISP_MAX_WIDTH;
+}
+
+static int zynqmp_disp_get_max_height(struct xlnx_crtc *xlnx_crtc)
+{
+	return ZYNQMP_DISP_MAX_HEIGHT;
+}
+
+static uint32_t zynqmp_disp_get_format(struct xlnx_crtc *xlnx_crtc)
+{
+	struct zynqmp_disp *disp = xlnx_crtc_to_disp(xlnx_crtc);
+
+	return disp->layers[ZYNQMP_DISP_LAYER_GFX].fmt->drm_fmt;
+}
+
+static unsigned int zynqmp_disp_get_align(struct xlnx_crtc *xlnx_crtc)
+{
+	struct zynqmp_disp *disp = xlnx_crtc_to_disp(xlnx_crtc);
+	struct zynqmp_disp_layer *layer = &disp->layers[ZYNQMP_DISP_LAYER_VID];
+
+	return 1 << layer->dma->chan->device->copy_align;
+}
+
+static u64 zynqmp_disp_get_dma_mask(struct xlnx_crtc *xlnx_crtc)
+{
+	return DMA_BIT_MASK(ZYNQMP_DISP_MAX_DMA_BIT);
+}
+
+/*
+ * DRM crtc functions
+ */
+
+static inline struct zynqmp_disp *crtc_to_disp(struct drm_crtc *crtc)
+{
+	struct xlnx_crtc *xlnx_crtc = to_xlnx_crtc(crtc);
+
+	return xlnx_crtc_to_disp(xlnx_crtc);
+}
+
+static int zynqmp_disp_crtc_mode_set(struct drm_crtc *crtc,
+				     struct drm_display_mode *mode,
+				     struct drm_display_mode *adjusted_mode,
+				     int x, int y,
+				     struct drm_framebuffer *old_fb)
+{
+	struct zynqmp_disp *disp = crtc_to_disp(crtc);
+	unsigned long rate;
+	long diff;
+	int ret;
+
+	zynqmp_disp_clk_disable(disp->pclk, &disp->pclk_en);
+	ret = clk_set_rate(disp->pclk,
+			   (unsigned long)adjusted_mode->clock * 1000);
+	if (ret) {
+		dev_err(disp->dev, "failed to set a pixel clock\n");
+		return ret;
+	}
+
+	rate = clk_get_rate(disp->pclk);
+	diff = rate - (unsigned long)adjusted_mode->clock * 1000;
+	if (abs(diff) > ((long)adjusted_mode->clock * 1000) / 20) {
+		dev_info(disp->dev, "request pixel rate: %d actual rate: %lu\n",
+			 adjusted_mode->clock, rate);
+	} else {
+		dev_dbg(disp->dev, "request pixel rate: %d actual rate: %lu\n",
+			adjusted_mode->clock, rate);
+	}
+
+	/* The timing register should be programmed always */
+	zynqmp_dp_encoder_mode_set_stream(disp->dpsub->dp, adjusted_mode);
+
+	return 0;
+}
+
+static void
+zynqmp_disp_crtc_atomic_enable(struct drm_crtc *crtc,
+			       struct drm_crtc_state *old_crtc_state)
+{
+	struct zynqmp_disp *disp = crtc_to_disp(crtc);
+	struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
+	int ret, vrefresh;
+
+	zynqmp_disp_crtc_mode_set(crtc, &crtc->state->mode,
+				  adjusted_mode, crtc->x, crtc->y, NULL);
+
+	ret = pm_runtime_get_sync(disp->dev);
+	if (ret < 0) {
+		dev_err(disp->dev, "IRQ sync failed to resume: %d\n", ret);
+		return;
+	}
+
+	ret = zynqmp_disp_clk_enable(disp->pclk, &disp->pclk_en);
+	if (ret) {
+		dev_err(disp->dev, "failed to enable a pixel clock\n");
+		return;
+	}
+	zynqmp_disp_set_output_fmt(disp, disp->color);
+	zynqmp_disp_set_bg_color(disp, disp->bg_c0, disp->bg_c1, disp->bg_c2);
+	zynqmp_disp_enable(disp);
+	/* Delay of 3 vblank intervals for timing gen to be stable */
+	vrefresh = (adjusted_mode->clock * 1000) /
+		   (adjusted_mode->vtotal * adjusted_mode->htotal);
+	msleep(3 * 1000 / vrefresh);
+}
+
+static void
+zynqmp_disp_crtc_atomic_disable(struct drm_crtc *crtc,
+				struct drm_crtc_state *old_crtc_state)
+{
+	struct zynqmp_disp *disp = crtc_to_disp(crtc);
+
+	zynqmp_disp_clk_disable(disp->pclk, &disp->pclk_en);
+	zynqmp_disp_plane_disable(crtc->primary);
+	zynqmp_disp_disable(disp, true);
+	if (!disp->dpsub->external_crtc_attached)
+		drm_crtc_vblank_off(crtc);
+	pm_runtime_put_sync(disp->dev);
+}
+
+static int zynqmp_disp_crtc_atomic_check(struct drm_crtc *crtc,
+					 struct drm_crtc_state *state)
+{
+	return drm_atomic_add_affected_planes(state->state, crtc);
+}
+
+static void
+zynqmp_disp_crtc_atomic_begin(struct drm_crtc *crtc,
+			      struct drm_crtc_state *old_crtc_state)
+{
+	drm_crtc_vblank_on(crtc);
+	/* Don't rely on vblank when disabling crtc */
+	spin_lock_irq(&crtc->dev->event_lock);
+	if (crtc->state->event) {
+		/* Consume the flip_done event from atomic helper */
+		crtc->state->event->pipe = drm_crtc_index(crtc);
+		WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+		drm_crtc_arm_vblank_event(crtc, crtc->state->event);
+		crtc->state->event = NULL;
+	}
+	spin_unlock_irq(&crtc->dev->event_lock);
+}
+
+static struct drm_crtc_helper_funcs zynqmp_disp_crtc_helper_funcs = {
+	.atomic_enable	= zynqmp_disp_crtc_atomic_enable,
+	.atomic_disable	= zynqmp_disp_crtc_atomic_disable,
+	.atomic_check	= zynqmp_disp_crtc_atomic_check,
+	.atomic_begin	= zynqmp_disp_crtc_atomic_begin,
+};
+
+static void zynqmp_disp_crtc_destroy(struct drm_crtc *crtc)
+{
+	zynqmp_disp_crtc_atomic_disable(crtc, NULL);
+	drm_crtc_cleanup(crtc);
+}
+
+static int zynqmp_disp_crtc_enable_vblank(struct drm_crtc *crtc)
+{
+	struct zynqmp_disp *disp = crtc_to_disp(crtc);
+
+	zynqmp_dp_enable_vblank(disp->dpsub->dp);
+
+	return 0;
+}
+
+static void zynqmp_disp_crtc_disable_vblank(struct drm_crtc *crtc)
+{
+	struct zynqmp_disp *disp = crtc_to_disp(crtc);
+
+	zynqmp_dp_disable_vblank(disp->dpsub->dp);
+}
+
+static int
+zynqmp_disp_crtc_atomic_set_property(struct drm_crtc *crtc,
+				     struct drm_crtc_state *state,
+				     struct drm_property *property,
+				     uint64_t val)
+{
+	struct zynqmp_disp *disp = crtc_to_disp(crtc);
+
+	/*
+	 * CRTC prop values are just stored here and applied when CRTC gets
+	 * enabled
+	 */
+	if (property == disp->color_prop)
+		disp->color = val;
+	else if (property == disp->bg_c0_prop)
+		disp->bg_c0 = val;
+	else if (property == disp->bg_c1_prop)
+		disp->bg_c1 = val;
+	else if (property == disp->bg_c2_prop)
+		disp->bg_c2 = val;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+static int
+zynqmp_disp_crtc_atomic_get_property(struct drm_crtc *crtc,
+				     const struct drm_crtc_state *state,
+				     struct drm_property *property,
+				     uint64_t *val)
+{
+	struct zynqmp_disp *disp = crtc_to_disp(crtc);
+
+	if (property == disp->color_prop)
+		*val = disp->color;
+	else if (property == disp->bg_c0_prop)
+		*val = disp->bg_c0;
+	else if (property == disp->bg_c1_prop)
+		*val = disp->bg_c1;
+	else if (property == disp->bg_c2_prop)
+		*val = disp->bg_c2;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+static struct drm_crtc_funcs zynqmp_disp_crtc_funcs = {
+	.destroy		= zynqmp_disp_crtc_destroy,
+	.set_config		= drm_atomic_helper_set_config,
+	.page_flip		= drm_atomic_helper_page_flip,
+	.atomic_set_property	= zynqmp_disp_crtc_atomic_set_property,
+	.atomic_get_property	= zynqmp_disp_crtc_atomic_get_property,
+	.reset			= drm_atomic_helper_crtc_reset,
+	.atomic_duplicate_state	= drm_atomic_helper_crtc_duplicate_state,
+	.atomic_destroy_state	= drm_atomic_helper_crtc_destroy_state,
+	.enable_vblank		= zynqmp_disp_crtc_enable_vblank,
+	.disable_vblank		= zynqmp_disp_crtc_disable_vblank,
+};
+
+static int zynqmp_disp_create_crtc(struct zynqmp_disp *disp)
+{
+	struct drm_plane *plane = &disp->layers[ZYNQMP_DISP_LAYER_GFX].plane;
+	struct drm_mode_object *obj = &disp->xlnx_crtc.crtc.base;
+	int ret;
+
+	ret = drm_crtc_init_with_planes(disp->drm, &disp->xlnx_crtc.crtc,
+					plane, NULL, &zynqmp_disp_crtc_funcs,
+					NULL);
+	if (ret < 0) {
+		dev_err(disp->dev, "failed to initialize disp CRTC: %d\n",
+			ret);
+		return ret;
+	}
+
+	drm_crtc_helper_add(&disp->xlnx_crtc.crtc,
+			    &zynqmp_disp_crtc_helper_funcs);
+	drm_object_attach_property(obj, disp->color_prop, 0);
+	zynqmp_dp_set_color(disp->dpsub->dp, zynqmp_disp_color_enum[0].name);
+	drm_object_attach_property(obj, disp->bg_c0_prop, 0);
+	drm_object_attach_property(obj, disp->bg_c1_prop, 0);
+	drm_object_attach_property(obj, disp->bg_c2_prop, 0);
+
+	disp->xlnx_crtc.get_max_width = &zynqmp_disp_get_max_width;
+	disp->xlnx_crtc.get_max_height = &zynqmp_disp_get_max_height;
+	disp->xlnx_crtc.get_format = &zynqmp_disp_get_format;
+	disp->xlnx_crtc.get_align = &zynqmp_disp_get_align;
+	disp->xlnx_crtc.get_dma_mask = &zynqmp_disp_get_dma_mask;
+	/* Only register the PS DP CRTC if there is no external port/CRTC */
+	if (!disp->dpsub->external_crtc_attached)
+		xlnx_crtc_register(disp->drm, &disp->xlnx_crtc);
+
+	return 0;
+}
+
+static void zynqmp_disp_destroy_crtc(struct zynqmp_disp *disp)
+{
+	if (!disp->dpsub->external_crtc_attached)
+		xlnx_crtc_unregister(disp->drm, &disp->xlnx_crtc);
+	zynqmp_disp_crtc_destroy(&disp->xlnx_crtc.crtc);
+}
+
+static void zynqmp_disp_map_crtc_to_plane(struct zynqmp_disp *disp)
+{
+	u32 possible_crtcs = drm_crtc_mask(&disp->xlnx_crtc.crtc);
+	unsigned int i;
+
+	for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++)
+		disp->layers[i].plane.possible_crtcs = possible_crtcs;
+}
+
+/*
+ * Xlnx bridge functions
+ */
+
+static inline struct zynqmp_disp_layer
+*bridge_to_layer(struct xlnx_bridge *bridge)
+{
+	return container_of(bridge, struct zynqmp_disp_layer, bridge);
+}
+
+static int zynqmp_disp_bridge_enable(struct xlnx_bridge *bridge)
+{
+	struct zynqmp_disp_layer *layer = bridge_to_layer(bridge);
+	struct zynqmp_disp *disp = layer->disp;
+	struct drm_crtc *crtc = &disp->xlnx_crtc.crtc;
+	struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
+	struct videomode vm;
+	int ret, vrefresh;
+
+	if (!disp->_pl_pclk) {
+		dev_err(disp->dev, "PL clock is required for live\n");
+		return -ENODEV;
+	}
+
+	ret = zynqmp_disp_layer_check_size(disp, layer, layer->w, layer->h);
+	if (ret)
+		return ret;
+
+	/* Enable DP encoder if external CRTC attached */
+	if (disp->dpsub->external_crtc_attached)
+		zynqmp_disp_crtc_atomic_enable(crtc, NULL);
+
+	if (disp->vtc_bridge) {
+		drm_display_mode_to_videomode(adjusted_mode, &vm);
+		xlnx_bridge_set_timing(disp->vtc_bridge, &vm);
+		xlnx_bridge_enable(disp->vtc_bridge);
+	}
+
+	/* If external CRTC is connected through video layer, set alpha to 0 */
+	if (disp->dpsub->external_crtc_attached &&
+		layer->id == ZYNQMP_DISP_LAYER_VID)
+		disp->alpha = 0;
+
+	zynqmp_disp_set_g_alpha(disp, disp->alpha_en);
+	zynqmp_disp_set_alpha(disp, disp->alpha);
+	ret = zynqmp_disp_layer_enable(layer->disp, layer,
+				       ZYNQMP_DISP_LAYER_LIVE);
+	if (ret)
+		return ret;
+
+	if (layer->id == ZYNQMP_DISP_LAYER_GFX && disp->tpg_on) {
+		layer = &disp->layers[ZYNQMP_DISP_LAYER_VID];
+		zynqmp_disp_layer_set_tpg(disp, layer, disp->tpg_on);
+	}
+
+	if (zynqmp_disp_av_buf_vid_timing_src_is_int(&disp->av_buf) ||
+	    zynqmp_disp_av_buf_vid_clock_src_is_ps(&disp->av_buf)) {
+		dev_info(disp->dev,
+			 "Disabling the pipeline to change the clk/timing src");
+		zynqmp_disp_disable(disp, true);
+		zynqmp_disp_av_buf_set_vid_clock_src(&disp->av_buf, false);
+		zynqmp_disp_av_buf_set_vid_timing_src(&disp->av_buf, false);
+	}
+
+	zynqmp_disp_enable(disp);
+
+	return 0;
+}
+
+static void zynqmp_disp_bridge_disable(struct xlnx_bridge *bridge)
+{
+	struct zynqmp_disp_layer *layer = bridge_to_layer(bridge);
+	struct zynqmp_disp *disp = layer->disp;
+
+	zynqmp_disp_disable(disp, false);
+
+	zynqmp_disp_layer_disable(disp, layer, ZYNQMP_DISP_LAYER_LIVE);
+	if (layer->id == ZYNQMP_DISP_LAYER_VID && disp->tpg_on)
+		zynqmp_disp_layer_set_tpg(disp, layer, disp->tpg_on);
+
+	if (!zynqmp_disp_layer_is_live(disp)) {
+		dev_info(disp->dev,
+			 "Disabling the pipeline to change the clk/timing src");
+		zynqmp_disp_disable(disp, true);
+		zynqmp_disp_av_buf_set_vid_clock_src(&disp->av_buf, true);
+		zynqmp_disp_av_buf_set_vid_timing_src(&disp->av_buf, true);
+		if (zynqmp_disp_layer_is_enabled(disp))
+			zynqmp_disp_enable(disp);
+	}
+}
+
+static int zynqmp_disp_bridge_set_input(struct xlnx_bridge *bridge,
+					u32 width, u32 height, u32 bus_fmt)
+{
+	struct zynqmp_disp_layer *layer = bridge_to_layer(bridge);
+	int ret;
+
+	ret = zynqmp_disp_layer_check_size(layer->disp, layer, width, height);
+	if (ret)
+		return ret;
+
+	ret = zynqmp_disp_layer_set_live_fmt(layer->disp,  layer, bus_fmt);
+	if (ret)
+		dev_err(layer->disp->dev, "failed to set live fmt\n");
+
+	return ret;
+}
+
+static int zynqmp_disp_bridge_get_input_fmts(struct xlnx_bridge *bridge,
+					     const u32 **fmts, u32 *count)
+{
+	struct zynqmp_disp_layer *layer = bridge_to_layer(bridge);
+
+	*fmts = layer->bus_fmts;
+	*count = layer->num_bus_fmts;
+
+	return 0;
+}
+
+static int zynqmp_disp_bridge_set_timing(struct xlnx_bridge *bridge,
+					     struct videomode *vm)
+{
+	struct zynqmp_disp_layer *layer = bridge_to_layer(bridge);
+	struct zynqmp_disp *disp = layer->disp;
+	struct drm_crtc *crtc = &disp->xlnx_crtc.crtc;
+	struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
+
+	drm_display_mode_from_videomode(vm, adjusted_mode);
+
+	return 0;
+}
+
+/*
+ * Component functions
+ */
+
+int zynqmp_disp_bind(struct device *dev, struct device *master, void *data)
+{
+	struct zynqmp_dpsub *dpsub = dev_get_drvdata(dev);
+	struct zynqmp_disp *disp = dpsub->disp;
+	struct drm_device *drm = data;
+	int num;
+	u64 max;
+	int ret;
+
+	disp->drm = drm;
+
+	max = ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_MAX;
+	disp->g_alpha_prop = drm_property_create_range(drm, 0, "alpha", 0, max);
+	disp->g_alpha_en_prop = drm_property_create_bool(drm, 0,
+							 "g_alpha_en");
+	num = ARRAY_SIZE(zynqmp_disp_color_enum);
+	disp->color_prop = drm_property_create_enum(drm, 0,
+						    "output_color",
+						    zynqmp_disp_color_enum,
+						    num);
+	max = ZYNQMP_DISP_V_BLEND_BG_MAX;
+	disp->bg_c0_prop = drm_property_create_range(drm, 0, "bg_c0", 0, max);
+	disp->bg_c1_prop = drm_property_create_range(drm, 0, "bg_c1", 0, max);
+	disp->bg_c2_prop = drm_property_create_range(drm, 0, "bg_c2", 0, max);
+	disp->tpg_prop = drm_property_create_bool(drm, 0, "tpg");
+
+	ret = zynqmp_disp_create_plane(disp);
+	if (ret)
+		return ret;
+	ret = zynqmp_disp_create_crtc(disp);
+	if (ret)
+		return ret;
+	zynqmp_disp_map_crtc_to_plane(disp);
+
+	return 0;
+}
+
+void zynqmp_disp_unbind(struct device *dev, struct device *master, void *data)
+{
+	struct zynqmp_dpsub *dpsub = dev_get_drvdata(dev);
+	struct zynqmp_disp *disp = dpsub->disp;
+
+	if (disp->vtc_bridge)
+		of_xlnx_bridge_put(disp->vtc_bridge);
+
+	zynqmp_disp_destroy_crtc(disp);
+	zynqmp_disp_destroy_plane(disp);
+	drm_property_destroy(disp->drm, disp->bg_c2_prop);
+	drm_property_destroy(disp->drm, disp->bg_c1_prop);
+	drm_property_destroy(disp->drm, disp->bg_c0_prop);
+	drm_property_destroy(disp->drm, disp->color_prop);
+	drm_property_destroy(disp->drm, disp->g_alpha_en_prop);
+	drm_property_destroy(disp->drm, disp->g_alpha_prop);
+}
+
+/*
+ * Platform initialization functions
+ */
+
+static int zynqmp_disp_enumerate_fmts(struct zynqmp_disp *disp)
+{
+	struct zynqmp_disp_layer *layer;
+	u32 *bus_fmts;
+	u32 i, size, num_bus_fmts;
+	u32 gfx_fmt = ZYNQMP_DISP_AV_BUF_GFX_FMT_RGB565;
+
+	num_bus_fmts = ARRAY_SIZE(av_buf_live_fmts);
+	bus_fmts = devm_kzalloc(disp->dev, sizeof(*bus_fmts) * num_bus_fmts,
+				GFP_KERNEL);
+	if (!bus_fmts)
+		return -ENOMEM;
+	for (i = 0; i < num_bus_fmts; i++)
+		bus_fmts[i] = av_buf_live_fmts[i].bus_fmt;
+
+	layer = &disp->layers[ZYNQMP_DISP_LAYER_VID];
+	layer->num_bus_fmts = num_bus_fmts;
+	layer->bus_fmts = bus_fmts;
+	size = ARRAY_SIZE(av_buf_vid_fmts);
+	layer->num_fmts = size;
+	layer->drm_fmts = devm_kzalloc(disp->dev,
+				       sizeof(*layer->drm_fmts) * size,
+				       GFP_KERNEL);
+	if (!layer->drm_fmts)
+		return -ENOMEM;
+	for (i = 0; i < layer->num_fmts; i++)
+		layer->drm_fmts[i] = av_buf_vid_fmts[i].drm_fmt;
+	layer->fmt = &av_buf_vid_fmts[ZYNQMP_DISP_AV_BUF_VID_FMT_YUYV];
+
+	layer = &disp->layers[ZYNQMP_DISP_LAYER_GFX];
+	layer->num_bus_fmts = num_bus_fmts;
+	layer->bus_fmts = bus_fmts;
+	size = ARRAY_SIZE(av_buf_gfx_fmts);
+	layer->num_fmts = size;
+	layer->drm_fmts = devm_kzalloc(disp->dev,
+				       sizeof(*layer->drm_fmts) * size,
+				       GFP_KERNEL);
+	if (!layer->drm_fmts)
+		return -ENOMEM;
+
+	for (i = 0; i < layer->num_fmts; i++)
+		layer->drm_fmts[i] = av_buf_gfx_fmts[i].drm_fmt;
+	if (zynqmp_disp_gfx_init_fmt < ARRAY_SIZE(zynqmp_disp_gfx_init_fmts))
+		gfx_fmt = zynqmp_disp_gfx_init_fmts[zynqmp_disp_gfx_init_fmt];
+	layer->fmt = &av_buf_gfx_fmts[gfx_fmt];
+
+	return 0;
+}
+
+int zynqmp_disp_probe(struct platform_device *pdev)
+{
+	struct zynqmp_dpsub *dpsub;
+	struct zynqmp_disp *disp;
+	struct resource *res;
+	int ret;
+	struct zynqmp_disp_layer *layer;
+	unsigned int i;
+	struct device_node *vtc_node;
+
+	disp = devm_kzalloc(&pdev->dev, sizeof(*disp), GFP_KERNEL);
+	if (!disp)
+		return -ENOMEM;
+	disp->dev = &pdev->dev;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "blend");
+	disp->blend.base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(disp->blend.base))
+		return PTR_ERR(disp->blend.base);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "av_buf");
+	disp->av_buf.base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(disp->av_buf.base))
+		return PTR_ERR(disp->av_buf.base);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "aud");
+	disp->aud.base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(disp->aud.base))
+		return PTR_ERR(disp->aud.base);
+
+	dpsub = platform_get_drvdata(pdev);
+	dpsub->disp = disp;
+	disp->dpsub = dpsub;
+
+	ret = zynqmp_disp_enumerate_fmts(disp);
+	if (ret)
+		return ret;
+
+	/* Try the live PL video clock */
+	disp->_pl_pclk = devm_clk_get(disp->dev, "dp_live_video_in_clk");
+	if (!IS_ERR(disp->_pl_pclk)) {
+		disp->pclk = disp->_pl_pclk;
+		ret = zynqmp_disp_clk_enable_disable(disp->pclk,
+						     &disp->pclk_en);
+		if (ret)
+			disp->pclk = NULL;
+	} else if (PTR_ERR(disp->_pl_pclk) == -EPROBE_DEFER) {
+		return PTR_ERR(disp->_pl_pclk);
+	}
+
+	/* If the live PL video clock is not valid, fall back to PS clock */
+	if (!disp->pclk) {
+		disp->_ps_pclk = devm_clk_get(disp->dev, "dp_vtc_pixel_clk_in");
+		if (IS_ERR(disp->_ps_pclk)) {
+			dev_err(disp->dev, "failed to init any video clock\n");
+			return PTR_ERR(disp->_ps_pclk);
+		}
+		disp->pclk = disp->_ps_pclk;
+		ret = zynqmp_disp_clk_enable_disable(disp->pclk,
+						     &disp->pclk_en);
+		if (ret) {
+			dev_err(disp->dev, "failed to init any video clock\n");
+			return ret;
+		}
+	}
+
+	disp->aclk = devm_clk_get(disp->dev, "dp_apb_clk");
+	if (IS_ERR(disp->aclk))
+		return PTR_ERR(disp->aclk);
+	ret = zynqmp_disp_clk_enable(disp->aclk, &disp->aclk_en);
+	if (ret) {
+		dev_err(disp->dev, "failed to enable the APB clk\n");
+		return ret;
+	}
+
+	/* Try the live PL audio clock */
+	disp->_pl_audclk = devm_clk_get(disp->dev, "dp_live_audio_aclk");
+	if (!IS_ERR(disp->_pl_audclk)) {
+		disp->audclk = disp->_pl_audclk;
+		ret = zynqmp_disp_clk_enable_disable(disp->audclk,
+						     &disp->audclk_en);
+		if (ret)
+			disp->audclk = NULL;
+	}
+
+	/* If the live PL audio clock is not valid, fall back to PS clock */
+	if (!disp->audclk) {
+		disp->_ps_audclk = devm_clk_get(disp->dev, "dp_aud_clk");
+		if (!IS_ERR(disp->_ps_audclk)) {
+			disp->audclk = disp->_ps_audclk;
+			ret = zynqmp_disp_clk_enable_disable(disp->audclk,
+							     &disp->audclk_en);
+			if (ret)
+				disp->audclk = NULL;
+		}
+
+		if (!disp->audclk) {
+			dev_err(disp->dev,
+				"audio is disabled due to clock failure\n");
+		}
+	}
+
+	/* VTC Bridge support */
+	vtc_node = of_parse_phandle(disp->dev->of_node, "xlnx,bridge", 0);
+	if (vtc_node) {
+		disp->vtc_bridge = of_xlnx_bridge_get(vtc_node);
+		if (!disp->vtc_bridge) {
+			dev_info(disp->dev, "Didn't get vtc bridge instance\n");
+			return -EPROBE_DEFER;
+		}
+	} else {
+		dev_info(disp->dev, "vtc bridge property not present\n");
+	}
+
+	ret = zynqmp_disp_layer_create(disp);
+	if (ret)
+		goto error_aclk;
+
+	zynqmp_disp_init(disp);
+
+	/*
+	 * Register live bridges so external CRTCs will be able probe
+	 * successfully
+	 */
+	for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++) {
+		layer = &disp->layers[i];
+		layer->bridge.enable = &zynqmp_disp_bridge_enable;
+		layer->bridge.disable = &zynqmp_disp_bridge_disable;
+		layer->bridge.set_input = &zynqmp_disp_bridge_set_input;
+		layer->bridge.get_input_fmts =
+			&zynqmp_disp_bridge_get_input_fmts;
+		layer->bridge.set_timing = &zynqmp_disp_bridge_set_timing;
+		layer->bridge.of_node = layer->of_node;
+		xlnx_bridge_register(&layer->bridge);
+	}
+
+	return 0;
+
+error_aclk:
+	zynqmp_disp_clk_disable(disp->aclk, &disp->aclk_en);
+	return ret;
+}
+
+int zynqmp_disp_remove(struct platform_device *pdev)
+{
+	struct zynqmp_dpsub *dpsub = platform_get_drvdata(pdev);
+	struct zynqmp_disp *disp = dpsub->disp;
+
+	zynqmp_disp_layer_destroy(disp);
+	if (disp->audclk)
+		zynqmp_disp_clk_disable(disp->audclk, &disp->audclk_en);
+	zynqmp_disp_clk_disable(disp->aclk, &disp->aclk_en);
+	zynqmp_disp_clk_disable(disp->pclk, &disp->pclk_en);
+	dpsub->disp = NULL;
+
+	return 0;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/xlnx/zynqmp_disp.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/xlnx/zynqmp_disp.h
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ZynqMP Display Driver
+ *
+ *  Copyright (C) 2017 - 2018 Xilinx, Inc.
+ *
+ *  Author: Hyun Woo Kwon <hyun.kwon@xilinx.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _ZYNQMP_DISP_H_
+#define _ZYNQMP_DISP_H_
+
+struct zynqmp_disp;
+
+void zynqmp_disp_handle_vblank(struct zynqmp_disp *disp);
+unsigned int zynqmp_disp_get_apb_clk_rate(struct zynqmp_disp *disp);
+bool zynqmp_disp_aud_enabled(struct zynqmp_disp *disp);
+unsigned int zynqmp_disp_get_aud_clk_rate(struct zynqmp_disp *disp);
+uint32_t zynqmp_disp_get_crtc_mask(struct zynqmp_disp *disp);
+
+int zynqmp_disp_bind(struct device *dev, struct device *master, void *data);
+void zynqmp_disp_unbind(struct device *dev, struct device *master, void *data);
+
+int zynqmp_disp_probe(struct platform_device *pdev);
+int zynqmp_disp_remove(struct platform_device *pdev);
+
+#endif /* _ZYNQMP_DISP_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/xlnx/zynqmp_dp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/xlnx/zynqmp_dp.c
@@ -0,0 +1,1937 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ZynqMP DisplayPort Driver
+ *
+ *  Copyright (C) 2017 - 2018 Xilinx, Inc.
+ *
+ *  Author: Hyun Woo Kwon <hyun.kwon@xilinx.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_connector.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_dp_helper.h>
+#include <drm/drm_of.h>
+#include <drm/drm_probe_helper.h>
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/phy/phy.h>
+#include <linux/phy/phy-zynqmp.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/uaccess.h>
+
+#include "zynqmp_disp.h"
+#include "zynqmp_dp.h"
+#include "zynqmp_dpsub.h"
+
+static uint zynqmp_dp_aux_timeout_ms = 50;
+module_param_named(aux_timeout_ms, zynqmp_dp_aux_timeout_ms, uint, 0444);
+MODULE_PARM_DESC(aux_timeout_ms, "DP aux timeout value in msec (default: 50)");
+
+/*
+ * Some sink requires a delay after power on request
+ */
+static uint zynqmp_dp_power_on_delay_ms = 4;
+module_param_named(power_on_delay_ms, zynqmp_dp_power_on_delay_ms, uint, 0444);
+MODULE_PARM_DESC(power_on_delay_ms, "DP power on delay in msec (default: 4)");
+
+/* Link configuration registers */
+#define ZYNQMP_DP_TX_LINK_BW_SET			0x0
+#define ZYNQMP_DP_TX_LANE_CNT_SET			0x4
+#define ZYNQMP_DP_TX_ENHANCED_FRAME_EN			0x8
+#define ZYNQMP_DP_TX_TRAINING_PATTERN_SET		0xc
+#define ZYNQMP_DP_TX_SCRAMBLING_DISABLE			0x14
+#define ZYNQMP_DP_TX_DOWNSPREAD_CTL			0x18
+#define ZYNQMP_DP_TX_SW_RESET				0x1c
+#define ZYNQMP_DP_TX_SW_RESET_STREAM1			BIT(0)
+#define ZYNQMP_DP_TX_SW_RESET_STREAM2			BIT(1)
+#define ZYNQMP_DP_TX_SW_RESET_STREAM3			BIT(2)
+#define ZYNQMP_DP_TX_SW_RESET_STREAM4			BIT(3)
+#define ZYNQMP_DP_TX_SW_RESET_AUX			BIT(7)
+#define ZYNQMP_DP_TX_SW_RESET_ALL			(ZYNQMP_DP_TX_SW_RESET_STREAM1 | \
+							 ZYNQMP_DP_TX_SW_RESET_STREAM2 | \
+							 ZYNQMP_DP_TX_SW_RESET_STREAM3 | \
+							 ZYNQMP_DP_TX_SW_RESET_STREAM4 | \
+							 ZYNQMP_DP_TX_SW_RESET_AUX)
+
+/* Core enable registers */
+#define ZYNQMP_DP_TX_ENABLE				0x80
+#define ZYNQMP_DP_TX_ENABLE_MAIN_STREAM			0x84
+#define ZYNQMP_DP_TX_FORCE_SCRAMBLER_RESET		0xc0
+#define ZYNQMP_DP_TX_VERSION				0xf8
+#define ZYNQMP_DP_TX_VERSION_MAJOR_MASK			GENMASK(31, 24)
+#define ZYNQMP_DP_TX_VERSION_MAJOR_SHIFT		24
+#define ZYNQMP_DP_TX_VERSION_MINOR_MASK			GENMASK(23, 16)
+#define ZYNQMP_DP_TX_VERSION_MINOR_SHIFT		16
+#define ZYNQMP_DP_TX_VERSION_REVISION_MASK		GENMASK(15, 12)
+#define ZYNQMP_DP_TX_VERSION_REVISION_SHIFT		12
+#define ZYNQMP_DP_TX_VERSION_PATCH_MASK			GENMASK(11, 8)
+#define ZYNQMP_DP_TX_VERSION_PATCH_SHIFT		8
+#define ZYNQMP_DP_TX_VERSION_INTERNAL_MASK		GENMASK(7, 0)
+#define ZYNQMP_DP_TX_VERSION_INTERNAL_SHIFT		0
+
+/* Core ID registers */
+#define ZYNQMP_DP_TX_CORE_ID				0xfc
+#define ZYNQMP_DP_TX_CORE_ID_MAJOR_MASK			GENMASK(31, 24)
+#define ZYNQMP_DP_TX_CORE_ID_MAJOR_SHIFT		24
+#define ZYNQMP_DP_TX_CORE_ID_MINOR_MASK			GENMASK(23, 16)
+#define ZYNQMP_DP_TX_CORE_ID_MINOR_SHIFT		16
+#define ZYNQMP_DP_TX_CORE_ID_REVISION_MASK		GENMASK(15, 8)
+#define ZYNQMP_DP_TX_CORE_ID_REVISION_SHIFT		8
+#define ZYNQMP_DP_TX_CORE_ID_DIRECTION			GENMASK(1)
+
+/* AUX channel interface registers */
+#define ZYNQMP_DP_TX_AUX_COMMAND			0x100
+#define ZYNQMP_DP_TX_AUX_COMMAND_CMD_SHIFT		8
+#define ZYNQMP_DP_TX_AUX_COMMAND_ADDRESS_ONLY		BIT(12)
+#define ZYNQMP_DP_TX_AUX_COMMAND_BYTES_SHIFT		0
+#define ZYNQMP_DP_TX_AUX_WRITE_FIFO			0x104
+#define ZYNQMP_DP_TX_AUX_ADDRESS			0x108
+#define ZYNQMP_DP_TX_CLK_DIVIDER			0x10c
+#define ZYNQMP_DP_TX_CLK_DIVIDER_MHZ			1000000
+#define ZYNQMP_DP_TX_CLK_DIVIDER_AUX_FILTER_SHIFT	8
+#define ZYNQMP_DP_TX_INTR_SIGNAL_STATE			0x130
+#define ZYNQMP_DP_TX_INTR_SIGNAL_STATE_HPD		BIT(0)
+#define ZYNQMP_DP_TX_INTR_SIGNAL_STATE_REQUEST		BIT(1)
+#define ZYNQMP_DP_TX_INTR_SIGNAL_STATE_REPLY		BIT(2)
+#define ZYNQMP_DP_TX_INTR_SIGNAL_STATE_REPLY_TIMEOUT	BIT(3)
+#define ZYNQMP_DP_TX_AUX_REPLY_DATA			0x134
+#define ZYNQMP_DP_TX_AUX_REPLY_CODE			0x138
+#define ZYNQMP_DP_TX_AUX_REPLY_CODE_AUX_ACK		(0)
+#define ZYNQMP_DP_TX_AUX_REPLY_CODE_AUX_NACK		BIT(0)
+#define ZYNQMP_DP_TX_AUX_REPLY_CODE_AUX_DEFER		BIT(1)
+#define ZYNQMP_DP_TX_AUX_REPLY_CODE_I2C_ACK		(0)
+#define ZYNQMP_DP_TX_AUX_REPLY_CODE_I2C_NACK		BIT(2)
+#define ZYNQMP_DP_TX_AUX_REPLY_CODE_I2C_DEFER		BIT(3)
+#define ZYNQMP_DP_TX_AUX_REPLY_CNT			0x13c
+#define ZYNQMP_DP_TX_AUX_REPLY_CNT_MASK			0xff
+#define ZYNQMP_DP_TX_INTR_STATUS			0x140
+#define ZYNQMP_DP_TX_INTR_MASK				0x144
+#define ZYNQMP_DP_TX_INTR_HPD_IRQ			BIT(0)
+#define ZYNQMP_DP_TX_INTR_HPD_EVENT			BIT(1)
+#define ZYNQMP_DP_TX_INTR_REPLY_RECV			BIT(2)
+#define ZYNQMP_DP_TX_INTR_REPLY_TIMEOUT			BIT(3)
+#define ZYNQMP_DP_TX_INTR_HPD_PULSE			BIT(4)
+#define ZYNQMP_DP_TX_INTR_EXT_PKT_TXD			BIT(5)
+#define ZYNQMP_DP_TX_INTR_LIV_ABUF_UNDRFLW		BIT(12)
+#define ZYNQMP_DP_TX_INTR_VBLANK_START			BIT(13)
+#define ZYNQMP_DP_TX_INTR_PIXEL0_MATCH			BIT(14)
+#define ZYNQMP_DP_TX_INTR_PIXEL1_MATCH			BIT(15)
+#define ZYNQMP_DP_TX_INTR_CHBUF_UNDERFLW_MASK		0x3f0000
+#define ZYNQMP_DP_TX_INTR_CHBUF_OVERFLW_MASK		0xfc00000
+#define ZYNQMP_DP_TX_INTR_CUST_TS_2			BIT(28)
+#define ZYNQMP_DP_TX_INTR_CUST_TS			BIT(29)
+#define ZYNQMP_DP_TX_INTR_EXT_VSYNC_TS			BIT(30)
+#define ZYNQMP_DP_TX_INTR_VSYNC_TS			BIT(31)
+#define ZYNQMP_DP_TX_INTR_ALL				(ZYNQMP_DP_TX_INTR_HPD_IRQ | \
+							 ZYNQMP_DP_TX_INTR_HPD_EVENT | \
+							 ZYNQMP_DP_TX_INTR_REPLY_RECV | \
+							 ZYNQMP_DP_TX_INTR_REPLY_TIMEOUT | \
+							 ZYNQMP_DP_TX_INTR_HPD_PULSE | \
+							 ZYNQMP_DP_TX_INTR_EXT_PKT_TXD | \
+							 ZYNQMP_DP_TX_INTR_LIV_ABUF_UNDRFLW | \
+							 ZYNQMP_DP_TX_INTR_CHBUF_UNDERFLW_MASK | \
+							 ZYNQMP_DP_TX_INTR_CHBUF_OVERFLW_MASK)
+#define ZYNQMP_DP_TX_NO_INTR_ALL			(ZYNQMP_DP_TX_INTR_PIXEL0_MATCH | \
+							 ZYNQMP_DP_TX_INTR_PIXEL1_MATCH | \
+							 ZYNQMP_DP_TX_INTR_CUST_TS_2 | \
+							 ZYNQMP_DP_TX_INTR_CUST_TS | \
+							 ZYNQMP_DP_TX_INTR_EXT_VSYNC_TS | \
+							 ZYNQMP_DP_TX_INTR_VSYNC_TS)
+#define ZYNQMP_DP_TX_REPLY_DATA_CNT			0x148
+#define ZYNQMP_DP_SUB_TX_INTR_STATUS			0x3a0
+#define ZYNQMP_DP_SUB_TX_INTR_MASK			0x3a4
+#define ZYNQMP_DP_SUB_TX_INTR_EN			0x3a8
+#define ZYNQMP_DP_SUB_TX_INTR_DS			0x3ac
+
+/* Main stream attribute registers */
+#define ZYNQMP_DP_TX_MAIN_STREAM_HTOTAL			0x180
+#define ZYNQMP_DP_TX_MAIN_STREAM_VTOTAL			0x184
+#define ZYNQMP_DP_TX_MAIN_STREAM_POLARITY		0x188
+#define ZYNQMP_DP_TX_MAIN_STREAM_POLARITY_HSYNC_SHIFT	0
+#define ZYNQMP_DP_TX_MAIN_STREAM_POLARITY_VSYNC_SHIFT	1
+#define ZYNQMP_DP_TX_MAIN_STREAM_HSWIDTH		0x18c
+#define ZYNQMP_DP_TX_MAIN_STREAM_VSWIDTH		0x190
+#define ZYNQMP_DP_TX_MAIN_STREAM_HRES			0x194
+#define ZYNQMP_DP_TX_MAIN_STREAM_VRES			0x198
+#define ZYNQMP_DP_TX_MAIN_STREAM_HSTART			0x19c
+#define ZYNQMP_DP_TX_MAIN_STREAM_VSTART			0x1a0
+#define ZYNQMP_DP_TX_MAIN_STREAM_MISC0			0x1a4
+#define ZYNQMP_DP_TX_MAIN_STREAM_MISC0_SYNC		BIT(0)
+#define ZYNQMP_DP_TX_MAIN_STREAM_MISC0_FORMAT_SHIFT	1
+#define ZYNQMP_DP_TX_MAIN_STREAM_MISC0_DYNAMIC_RANGE	BIT(3)
+#define ZYNQMP_DP_TX_MAIN_STREAM_MISC0_YCBCR_COLRIMETRY	BIT(4)
+#define ZYNQMP_DP_TX_MAIN_STREAM_MISC0_BPC_SHIFT	5
+#define ZYNQMP_DP_TX_MAIN_STREAM_MISC1			0x1a8
+#define ZYNQMP_DP_TX_MAIN_STREAM_MISC0_INTERLACED_VERT	BIT(0)
+#define ZYNQMP_DP_TX_MAIN_STREAM_MISC0_STEREO_VID_SHIFT	1
+#define ZYNQMP_DP_TX_M_VID				0x1ac
+#define ZYNQMP_DP_TX_TRANSFER_UNIT_SIZE			0x1b0
+#define ZYNQMP_DP_TX_DEF_TRANSFER_UNIT_SIZE		64
+#define ZYNQMP_DP_TX_N_VID				0x1b4
+#define ZYNQMP_DP_TX_USER_PIXEL_WIDTH			0x1b8
+#define ZYNQMP_DP_TX_USER_DATA_CNT_PER_LANE		0x1bc
+#define ZYNQMP_DP_TX_MIN_BYTES_PER_TU			0x1c4
+#define ZYNQMP_DP_TX_FRAC_BYTES_PER_TU			0x1c8
+#define ZYNQMP_DP_TX_INIT_WAIT				0x1cc
+
+/* PHY configuration and status registers */
+#define ZYNQMP_DP_TX_PHY_CONFIG				0x200
+#define ZYNQMP_DP_TX_PHY_CONFIG_PHY_RESET		BIT(0)
+#define ZYNQMP_DP_TX_PHY_CONFIG_GTTX_RESET		BIT(1)
+#define ZYNQMP_DP_TX_PHY_CONFIG_PHY_PMA_RESET		BIT(8)
+#define ZYNQMP_DP_TX_PHY_CONFIG_PHY_PCS_RESET		BIT(9)
+#define ZYNQMP_DP_TX_PHY_CONFIG_ALL_RESET		(ZYNQMP_DP_TX_PHY_CONFIG_PHY_RESET | \
+							 ZYNQMP_DP_TX_PHY_CONFIG_GTTX_RESET | \
+							 ZYNQMP_DP_TX_PHY_CONFIG_PHY_PMA_RESET | \
+							 ZYNQMP_DP_TX_PHY_CONFIG_PHY_PCS_RESET)
+#define ZYNQMP_DP_TX_PHY_PREEMPHASIS_LANE_0		0x210
+#define ZYNQMP_DP_TX_PHY_PREEMPHASIS_LANE_1		0x214
+#define ZYNQMP_DP_TX_PHY_PREEMPHASIS_LANE_2		0x218
+#define ZYNQMP_DP_TX_PHY_PREEMPHASIS_LANE_3		0x21c
+#define ZYNQMP_DP_TX_PHY_VOLTAGE_DIFF_LANE_0		0x220
+#define ZYNQMP_DP_TX_PHY_VOLTAGE_DIFF_LANE_1		0x224
+#define ZYNQMP_DP_TX_PHY_VOLTAGE_DIFF_LANE_2		0x228
+#define ZYNQMP_DP_TX_PHY_VOLTAGE_DIFF_LANE_3		0x22c
+#define ZYNQMP_DP_TX_PHY_CLOCK_FEEDBACK_SETTING		0x234
+#define ZYNQMP_DP_TX_PHY_CLOCK_FEEDBACK_SETTING_162	0x1
+#define ZYNQMP_DP_TX_PHY_CLOCK_FEEDBACK_SETTING_270	0x3
+#define ZYNQMP_DP_TX_PHY_CLOCK_FEEDBACK_SETTING_540	0x5
+#define ZYNQMP_DP_TX_PHY_POWER_DOWN			0x238
+#define ZYNQMP_DP_TX_PHY_POWER_DOWN_LANE_0		BIT(0)
+#define ZYNQMP_DP_TX_PHY_POWER_DOWN_LANE_1		BIT(1)
+#define ZYNQMP_DP_TX_PHY_POWER_DOWN_LANE_2		BIT(2)
+#define ZYNQMP_DP_TX_PHY_POWER_DOWN_LANE_3		BIT(3)
+#define ZYNQMP_DP_TX_PHY_POWER_DOWN_ALL			0xf
+#define ZYNQMP_DP_TX_PHY_PRECURSOR_LANE_0		0x23c
+#define ZYNQMP_DP_TX_PHY_PRECURSOR_LANE_1		0x240
+#define ZYNQMP_DP_TX_PHY_PRECURSOR_LANE_2		0x244
+#define ZYNQMP_DP_TX_PHY_PRECURSOR_LANE_3		0x248
+#define ZYNQMP_DP_TX_PHY_POSTCURSOR_LANE_0		0x24c
+#define ZYNQMP_DP_TX_PHY_POSTCURSOR_LANE_1		0x250
+#define ZYNQMP_DP_TX_PHY_POSTCURSOR_LANE_2		0x254
+#define ZYNQMP_DP_TX_PHY_POSTCURSOR_LANE_3		0x258
+#define ZYNQMP_DP_SUB_TX_PHY_PRECURSOR_LANE_0		0x24c
+#define ZYNQMP_DP_SUB_TX_PHY_PRECURSOR_LANE_1		0x250
+#define ZYNQMP_DP_TX_PHY_STATUS				0x280
+#define ZYNQMP_DP_TX_PHY_STATUS_PLL_LOCKED_SHIFT	4
+#define ZYNQMP_DP_TX_PHY_STATUS_FPGA_PLL_LOCKED		BIT(6)
+
+/* Audio registers */
+#define ZYNQMP_DP_TX_AUDIO_CONTROL			0x300
+#define ZYNQMP_DP_TX_AUDIO_CHANNELS			0x304
+#define ZYNQMP_DP_TX_AUDIO_INFO_DATA			0x308
+#define ZYNQMP_DP_TX_AUDIO_M_AUD			0x328
+#define ZYNQMP_DP_TX_AUDIO_N_AUD			0x32c
+#define ZYNQMP_DP_TX_AUDIO_EXT_DATA			0x330
+
+#define ZYNQMP_DP_MISC0_RGB				(0)
+#define ZYNQMP_DP_MISC0_YCRCB_422			(5 << 1)
+#define ZYNQMP_DP_MISC0_YCRCB_444			(6 << 1)
+#define ZYNQMP_DP_MISC0_FORMAT_MASK			0xe
+#define ZYNQMP_DP_MISC0_BPC_6				(0 << 5)
+#define ZYNQMP_DP_MISC0_BPC_8				(1 << 5)
+#define ZYNQMP_DP_MISC0_BPC_10				(2 << 5)
+#define ZYNQMP_DP_MISC0_BPC_12				(3 << 5)
+#define ZYNQMP_DP_MISC0_BPC_16				(4 << 5)
+#define ZYNQMP_DP_MISC0_BPC_MASK			0xe0
+#define ZYNQMP_DP_MISC1_Y_ONLY				(1 << 7)
+
+#define ZYNQMP_DP_MAX_LANES				2
+#define ZYNQMP_MAX_FREQ					3000000
+
+#define DP_REDUCED_BIT_RATE				162000
+#define DP_HIGH_BIT_RATE				270000
+#define DP_HIGH_BIT_RATE2				540000
+#define DP_MAX_TRAINING_TRIES				10
+#define DP_V1_2						0x12
+
+/**
+ * struct zynqmp_dp_link_config - Common link config between source and sink
+ * @max_rate: maximum link rate
+ * @max_lanes: maximum number of lanes
+ */
+struct zynqmp_dp_link_config {
+	int max_rate;
+	u8 max_lanes;
+};
+
+/**
+ * struct zynqmp_dp_mode - Configured mode of DisplayPort
+ * @bw_code: code for bandwidth(link rate)
+ * @lane_cnt: number of lanes
+ * @pclock: pixel clock frequency of current mode
+ * @fmt: format identifier string
+ */
+struct zynqmp_dp_mode {
+	u8 bw_code;
+	u8 lane_cnt;
+	int pclock;
+	const char *fmt;
+};
+
+/**
+ * struct zynqmp_dp_config - Configuration of DisplayPort from DTS
+ * @misc0: misc0 configuration (per DP v1.2 spec)
+ * @misc1: misc1 configuration (per DP v1.2 spec)
+ * @bpp: bits per pixel
+ * @bpc: bits per component
+ * @num_colors: number of color components
+ */
+struct zynqmp_dp_config {
+	u8 misc0;
+	u8 misc1;
+	u8 bpp;
+	u8 bpc;
+	u8 num_colors;
+};
+
+/**
+ * struct zynqmp_dp - Xilinx DisplayPort core
+ * @encoder: the drm encoder structure
+ * @connector: the drm connector structure
+ * @sync_prop: synchronous mode property
+ * @bpc_prop: bpc mode property
+ * @dev: device structure
+ * @dpsub: Display subsystem
+ * @drm: DRM core
+ * @iomem: device I/O memory for register access
+ * @irq: irq
+ * @config: IP core configuration from DTS
+ * @aux: aux channel
+ * @phy: PHY handles for DP lanes
+ * @num_lanes: number of enabled phy lanes
+ * @hpd_work: hot plug detection worker
+ * @status: connection status
+ * @enabled: flag to indicate if the device is enabled
+ * @dpms: current dpms state
+ * @dpcd: DP configuration data from currently connected sink device
+ * @link_config: common link configuration between IP core and sink device
+ * @mode: current mode between IP core and sink device
+ * @train_set: set of training data
+ */
+struct zynqmp_dp {
+	struct drm_encoder encoder;
+	struct drm_connector connector;
+	struct drm_property *sync_prop;
+	struct drm_property *bpc_prop;
+	struct device *dev;
+	struct zynqmp_dpsub *dpsub;
+	struct drm_device *drm;
+	void __iomem *iomem;
+	int irq;
+
+	struct zynqmp_dp_config config;
+	struct drm_dp_aux aux;
+	struct phy *phy[ZYNQMP_DP_MAX_LANES];
+	u8 num_lanes;
+	struct delayed_work hpd_work;
+	enum drm_connector_status status;
+	bool enabled;
+
+	int dpms;
+	u8 dpcd[DP_RECEIVER_CAP_SIZE];
+	struct zynqmp_dp_link_config link_config;
+	struct zynqmp_dp_mode mode;
+	u8 train_set[ZYNQMP_DP_MAX_LANES];
+};
+
+static inline struct zynqmp_dp *encoder_to_dp(struct drm_encoder *encoder)
+{
+	return container_of(encoder, struct zynqmp_dp, encoder);
+}
+
+static inline struct zynqmp_dp *connector_to_dp(struct drm_connector *connector)
+{
+	return container_of(connector, struct zynqmp_dp, connector);
+}
+
+static void zynqmp_dp_write(void __iomem *base, int offset, u32 val)
+{
+	writel(val, base + offset);
+}
+
+static u32 zynqmp_dp_read(void __iomem *base, int offset)
+{
+	return readl(base + offset);
+}
+
+static void zynqmp_dp_clr(void __iomem *base, int offset, u32 clr)
+{
+	zynqmp_dp_write(base, offset, zynqmp_dp_read(base, offset) & ~clr);
+}
+
+static void zynqmp_dp_set(void __iomem *base, int offset, u32 set)
+{
+	zynqmp_dp_write(base, offset, zynqmp_dp_read(base, offset) | set);
+}
+
+/*
+ * Internal functions: used by zynqmp_disp.c
+ */
+
+/**
+ * zynqmp_dp_update_bpp - Update the current bpp config
+ * @dp: DisplayPort IP core structure
+ *
+ * Update the current bpp based on the color format: bpc & num_colors.
+ * Any function that changes bpc or num_colors should call this
+ * to keep the bpp value in sync.
+ */
+static void zynqmp_dp_update_bpp(struct zynqmp_dp *dp)
+{
+	struct zynqmp_dp_config *config = &dp->config;
+
+	config->bpp = dp->config.bpc * dp->config.num_colors;
+}
+
+/**
+ * zynqmp_dp_set_color - Set the color
+ * @dp: DisplayPort IP core structure
+ * @color: color string, from zynqmp_disp_color_enum
+ *
+ * Update misc register values based on @color string.
+ *
+ * Return: 0 on success, or -EINVAL.
+ */
+int zynqmp_dp_set_color(struct zynqmp_dp *dp, const char *color)
+{
+	struct zynqmp_dp_config *config = &dp->config;
+
+	config->misc0 &= ~ZYNQMP_DP_MISC0_FORMAT_MASK;
+	config->misc1 &= ~ZYNQMP_DP_MISC1_Y_ONLY;
+	if (strcmp(color, "rgb") == 0) {
+		config->misc0 |= ZYNQMP_DP_MISC0_RGB;
+		config->num_colors = 3;
+	} else if (strcmp(color, "ycrcb422") == 0) {
+		config->misc0 |= ZYNQMP_DP_MISC0_YCRCB_422;
+		config->num_colors = 2;
+	} else if (strcmp(color, "ycrcb444") == 0) {
+		config->misc0 |= ZYNQMP_DP_MISC0_YCRCB_444;
+		config->num_colors = 3;
+	} else if (strcmp(color, "yonly") == 0) {
+		config->misc1 |= ZYNQMP_DP_MISC1_Y_ONLY;
+		config->num_colors = 1;
+	} else {
+		dev_err(dp->dev, "Invalid colormetry in DT\n");
+		return -EINVAL;
+	}
+	zynqmp_dp_update_bpp(dp);
+
+	return 0;
+}
+
+/**
+ * zynqmp_dp_enable_vblank - Enable vblank
+ * @dp: DisplayPort IP core structure
+ *
+ * Enable vblank interrupt
+ */
+void zynqmp_dp_enable_vblank(struct zynqmp_dp *dp)
+{
+	zynqmp_dp_write(dp->iomem, ZYNQMP_DP_SUB_TX_INTR_EN,
+			ZYNQMP_DP_TX_INTR_VBLANK_START);
+}
+
+/**
+ * zynqmp_dp_disable_vblank - Disable vblank
+ * @dp: DisplayPort IP core structure
+ *
+ * Disable vblank interrupt
+ */
+void zynqmp_dp_disable_vblank(struct zynqmp_dp *dp)
+{
+	zynqmp_dp_write(dp->iomem, ZYNQMP_DP_SUB_TX_INTR_DS,
+			ZYNQMP_DP_TX_INTR_VBLANK_START);
+}
+
+/*
+ * DP PHY functions
+ */
+
+/**
+ * zynqmp_dp_init_phy - Initialize the phy
+ * @dp: DisplayPort IP core structure
+ *
+ * Initialize the phy.
+ *
+ * Return: 0 if the phy instances are initialized correctly, or the error code
+ * returned from the callee functions.
+ * Note: We can call this function without any phy lane assigned to DP.
+ */
+static int zynqmp_dp_init_phy(struct zynqmp_dp *dp)
+{
+	unsigned int i;
+	int ret;
+
+	for (i = 0; i < dp->num_lanes; i++) {
+		ret = phy_init(dp->phy[i]);
+		if (ret) {
+			dev_err(dp->dev, "failed to init phy lane %d\n", i);
+			return ret;
+		}
+	}
+	/* Wait for PLL to be locked for the primary (1st) lane */
+	if (dp->phy[0]) {
+		zynqmp_dp_write(dp->iomem, ZYNQMP_DP_SUB_TX_INTR_DS,
+				ZYNQMP_DP_TX_INTR_ALL);
+		zynqmp_dp_clr(dp->iomem, ZYNQMP_DP_TX_PHY_CONFIG,
+			      ZYNQMP_DP_TX_PHY_CONFIG_ALL_RESET);
+		ret = xpsgtr_wait_pll_lock(dp->phy[0]);
+		if (ret) {
+			dev_err(dp->dev, "failed to lock pll\n");
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * zynqmp_dp_exit_phy - Exit the phy
+ * @dp: DisplayPort IP core structure
+ *
+ * Exit the phy.
+ */
+static void zynqmp_dp_exit_phy(struct zynqmp_dp *dp)
+{
+	unsigned int i;
+	int ret;
+
+	for (i = 0; i < dp->num_lanes; i++) {
+		ret = phy_exit(dp->phy[i]);
+		if (ret)
+			dev_err(dp->dev, "failed to exit phy(%d) %d\n", i, ret);
+	}
+}
+
+/**
+ * zynqmp_dp_phy_ready - Check if PHY is ready
+ * @dp: DisplayPort IP core structure
+ *
+ * Check if PHY is ready. If PHY is not ready, wait 1ms to check for 100 times.
+ * This amount of delay was suggested by IP designer.
+ *
+ * Return: 0 if PHY is ready, or -ENODEV if PHY is not ready.
+ */
+static int zynqmp_dp_phy_ready(struct zynqmp_dp *dp)
+{
+	u32 i, reg, ready;
+
+	ready = (1 << dp->num_lanes) - 1;
+
+	/* Wait for 100 * 1ms. This should be enough time for PHY to be ready */
+	for (i = 0; ; i++) {
+		reg = zynqmp_dp_read(dp->iomem, ZYNQMP_DP_TX_PHY_STATUS);
+		if ((reg & ready) == ready)
+			return 0;
+
+		if (i == 100) {
+			dev_err(dp->dev, "PHY isn't ready\n");
+			return -ENODEV;
+		}
+
+		usleep_range(1000, 1100);
+	}
+
+	return 0;
+}
+
+/*
+ * Power Management functions
+ */
+/**
+ * zynqmp_dp_pm_resume - Resume DP IP
+ * @dp: DisplayPort IP core structure
+ *
+ * Resume the DP IP including PHY and pipeline.
+ */
+void zynqmp_dp_pm_resume(struct zynqmp_dp *dp)
+{
+	zynqmp_dp_init_phy(dp);
+}
+/**
+ * zynqmp_dp_pm_suspend - Suspend DP IP
+ * @dp: DisplayPort IP core structure
+ *
+ * Suspend the DP IP including PHY and pipeline.
+ */
+void zynqmp_dp_pm_suspend(struct zynqmp_dp *dp)
+{
+	zynqmp_dp_exit_phy(dp);
+}
+/*
+ * DP functions
+ */
+
+/**
+ * zynqmp_dp_max_rate - Calculate and return available max pixel clock
+ * @link_rate: link rate (Kilo-bytes / sec)
+ * @lane_num: number of lanes
+ * @bpp: bits per pixel
+ *
+ * Return: max pixel clock (KHz) supported by current link config.
+ */
+static inline int zynqmp_dp_max_rate(int link_rate, u8 lane_num, u8 bpp)
+{
+	return link_rate * lane_num * 8 / bpp;
+}
+
+/**
+ * zynqmp_dp_mode_configure - Configure the link values
+ * @dp: DisplayPort IP core structure
+ * @pclock: pixel clock for requested display mode
+ * @current_bw: current link rate
+ *
+ * Find the link configuration values, rate and lane count for requested pixel
+ * clock @pclock. The @pclock is stored in the mode to be used in other
+ * functions later. The returned rate is downshifted from the current rate
+ * @current_bw.
+ *
+ * Return: Current link rate code, or -EINVAL.
+ */
+static int zynqmp_dp_mode_configure(struct zynqmp_dp *dp, int pclock,
+				    u8 current_bw)
+{
+	int max_rate = dp->link_config.max_rate;
+	u8 bw_code;
+	u8 max_lanes = dp->link_config.max_lanes;
+	u8 max_link_rate_code = drm_dp_link_rate_to_bw_code(max_rate);
+	u8 bpp = dp->config.bpp;
+	u8 lane_cnt;
+
+	/* Downshift from current bandwidth */
+	switch (current_bw) {
+	case DP_LINK_BW_5_4:
+		bw_code = DP_LINK_BW_2_7;
+		break;
+	case DP_LINK_BW_2_7:
+		bw_code = DP_LINK_BW_1_62;
+		break;
+	case DP_LINK_BW_1_62:
+		dev_err(dp->dev, "can't downshift. already lowest link rate\n");
+		return -EINVAL;
+	default:
+		/* If not given, start with max supported */
+		bw_code = max_link_rate_code;
+		break;
+	}
+
+	for (lane_cnt = 1; lane_cnt <= max_lanes; lane_cnt <<= 1) {
+		int bw;
+		u32 rate;
+
+		bw = drm_dp_bw_code_to_link_rate(bw_code);
+		rate = zynqmp_dp_max_rate(bw, lane_cnt, bpp);
+		if (pclock <= rate) {
+			dp->mode.bw_code = bw_code;
+			dp->mode.lane_cnt = lane_cnt;
+			dp->mode.pclock = pclock;
+			return dp->mode.bw_code;
+		}
+	}
+
+	dev_err(dp->dev, "failed to configure link values\n");
+
+	return -EINVAL;
+}
+
+/**
+ * zynqmp_dp_adjust_train - Adjust train values
+ * @dp: DisplayPort IP core structure
+ * @link_status: link status from sink which contains requested training values
+ */
+static void zynqmp_dp_adjust_train(struct zynqmp_dp *dp,
+				   u8 link_status[DP_LINK_STATUS_SIZE])
+{
+	u8 *train_set = dp->train_set;
+	u8 voltage = 0, preemphasis = 0;
+	u8 i;
+
+	for (i = 0; i < dp->mode.lane_cnt; i++) {
+		u8 v = drm_dp_get_adjust_request_voltage(link_status, i);
+		u8 p = drm_dp_get_adjust_request_pre_emphasis(link_status, i);
+
+		if (v > voltage)
+			voltage = v;
+
+		if (p > preemphasis)
+			preemphasis = p;
+	}
+
+	if (voltage >= DP_TRAIN_VOLTAGE_SWING_LEVEL_3)
+		voltage |= DP_TRAIN_MAX_SWING_REACHED;
+
+	if (preemphasis >= DP_TRAIN_PRE_EMPH_LEVEL_2)
+		preemphasis |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
+
+	for (i = 0; i < dp->mode.lane_cnt; i++)
+		train_set[i] = voltage | preemphasis;
+}
+
+/**
+ * zynqmp_dp_update_vs_emph - Update the training values
+ * @dp: DisplayPort IP core structure
+ *
+ * Update the training values based on the request from sink. The mapped values
+ * are predefined, and values(vs, pe, pc) are from the device manual.
+ *
+ * Return: 0 if vs and emph are updated successfully, or the error code returned
+ * by drm_dp_dpcd_write().
+ */
+static int zynqmp_dp_update_vs_emph(struct zynqmp_dp *dp)
+{
+	u8 *train_set = dp->train_set;
+	u8 i, v_level, p_level;
+	int ret;
+
+	ret = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_LANE0_SET, train_set,
+				dp->mode.lane_cnt);
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < dp->mode.lane_cnt; i++) {
+		u32 reg = ZYNQMP_DP_SUB_TX_PHY_PRECURSOR_LANE_0 + i * 4;
+
+		v_level = (train_set[i] & DP_TRAIN_VOLTAGE_SWING_MASK) >>
+			  DP_TRAIN_VOLTAGE_SWING_SHIFT;
+		p_level = (train_set[i] & DP_TRAIN_PRE_EMPHASIS_MASK) >>
+			  DP_TRAIN_PRE_EMPHASIS_SHIFT;
+
+		xpsgtr_margining_factor(dp->phy[i], p_level, v_level);
+		xpsgtr_override_deemph(dp->phy[i], p_level, v_level);
+		zynqmp_dp_write(dp->iomem, reg, 0x2);
+	}
+
+	return 0;
+}
+
+/**
+ * zynqmp_dp_link_train_cr - Train clock recovery
+ * @dp: DisplayPort IP core structure
+ *
+ * Return: 0 if clock recovery train is done successfully, or corresponding
+ * error code.
+ */
+static int zynqmp_dp_link_train_cr(struct zynqmp_dp *dp)
+{
+	u8 link_status[DP_LINK_STATUS_SIZE];
+	u8 lane_cnt = dp->mode.lane_cnt;
+	u8 vs = 0, tries = 0;
+	u16 max_tries, i;
+	bool cr_done;
+	int ret;
+
+	zynqmp_dp_write(dp->iomem, ZYNQMP_DP_TX_TRAINING_PATTERN_SET,
+			DP_TRAINING_PATTERN_1);
+	ret = drm_dp_dpcd_writeb(&dp->aux, DP_TRAINING_PATTERN_SET,
+				 DP_TRAINING_PATTERN_1 |
+				 DP_LINK_SCRAMBLING_DISABLE);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * 256 loops should be maximum iterations for 4 lanes and 4 values.
+	 * So, This loop should exit before 512 iterations
+	 */
+	for (max_tries = 0; max_tries < 512; max_tries++) {
+		ret = zynqmp_dp_update_vs_emph(dp);
+		if (ret)
+			return ret;
+
+		drm_dp_link_train_clock_recovery_delay(dp->dpcd);
+		ret = drm_dp_dpcd_read_link_status(&dp->aux, link_status);
+		if (ret < 0)
+			return ret;
+
+		cr_done = drm_dp_clock_recovery_ok(link_status, lane_cnt);
+		if (cr_done)
+			break;
+
+		for (i = 0; i < lane_cnt; i++)
+			if (!(dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED))
+				break;
+		if (i == lane_cnt)
+			break;
+
+		if ((dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == vs)
+			tries++;
+		else
+			tries = 0;
+
+		if (tries == DP_MAX_TRAINING_TRIES)
+			break;
+
+		vs = dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
+		zynqmp_dp_adjust_train(dp, link_status);
+	}
+
+	if (!cr_done)
+		return -EIO;
+
+	return 0;
+}
+
+/**
+ * zynqmp_dp_link_train_ce - Train channel equalization
+ * @dp: DisplayPort IP core structure
+ *
+ * Return: 0 if channel equalization train is done successfully, or
+ * corresponding error code.
+ */
+static int zynqmp_dp_link_train_ce(struct zynqmp_dp *dp)
+{
+	u8 link_status[DP_LINK_STATUS_SIZE];
+	u8 lane_cnt = dp->mode.lane_cnt;
+	u32 pat, tries;
+	int ret;
+	bool ce_done;
+
+	if (dp->dpcd[DP_DPCD_REV] >= DP_V1_2 &&
+	    dp->dpcd[DP_MAX_LANE_COUNT] & DP_TPS3_SUPPORTED)
+		pat = DP_TRAINING_PATTERN_3;
+	else
+		pat = DP_TRAINING_PATTERN_2;
+
+	zynqmp_dp_write(dp->iomem, ZYNQMP_DP_TX_TRAINING_PATTERN_SET, pat);
+	ret = drm_dp_dpcd_writeb(&dp->aux, DP_TRAINING_PATTERN_SET,
+				 pat | DP_LINK_SCRAMBLING_DISABLE);
+	if (ret < 0)
+		return ret;
+
+	for (tries = 0; tries < DP_MAX_TRAINING_TRIES; tries++) {
+		ret = zynqmp_dp_update_vs_emph(dp);
+		if (ret)
+			return ret;
+
+		drm_dp_link_train_channel_eq_delay(dp->dpcd);
+		ret = drm_dp_dpcd_read_link_status(&dp->aux, link_status);
+		if (ret < 0)
+			return ret;
+
+		ce_done = drm_dp_channel_eq_ok(link_status, lane_cnt);
+		if (ce_done)
+			break;
+
+		zynqmp_dp_adjust_train(dp, link_status);
+	}
+
+	if (!ce_done)
+		return -EIO;
+
+	return 0;
+}
+
+/**
+ * zynqmp_dp_link_train - Train the link
+ * @dp: DisplayPort IP core structure
+ *
+ * Return: 0 if all trains are done successfully, or corresponding error code.
+ */
+static int zynqmp_dp_train(struct zynqmp_dp *dp)
+{
+	u32 reg;
+	u8 bw_code = dp->mode.bw_code;
+	u8 lane_cnt = dp->mode.lane_cnt;
+	u8 aux_lane_cnt = lane_cnt;
+	bool enhanced;
+	int ret;
+
+	zynqmp_dp_write(dp->iomem, ZYNQMP_DP_TX_LANE_CNT_SET, lane_cnt);
+	enhanced = drm_dp_enhanced_frame_cap(dp->dpcd);
+	if (enhanced) {
+		zynqmp_dp_write(dp->iomem, ZYNQMP_DP_TX_ENHANCED_FRAME_EN, 1);
+		aux_lane_cnt |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
+	}
+
+	if (dp->dpcd[3] & 0x1) {
+		zynqmp_dp_write(dp->iomem, ZYNQMP_DP_TX_DOWNSPREAD_CTL, 1);
+		drm_dp_dpcd_writeb(&dp->aux, DP_DOWNSPREAD_CTRL,
+				   DP_SPREAD_AMP_0_5);
+	} else {
+		zynqmp_dp_write(dp->iomem, ZYNQMP_DP_TX_DOWNSPREAD_CTL, 0);
+		drm_dp_dpcd_writeb(&dp->aux, DP_DOWNSPREAD_CTRL, 0);
+	}
+
+	ret = drm_dp_dpcd_writeb(&dp->aux, DP_LANE_COUNT_SET, aux_lane_cnt);
+	if (ret < 0) {
+		dev_err(dp->dev, "failed to set lane count\n");
+		return ret;
+	}
+
+	ret = drm_dp_dpcd_writeb(&dp->aux, DP_MAIN_LINK_CHANNEL_CODING_SET,
+				 DP_SET_ANSI_8B10B);
+	if (ret < 0) {
+		dev_err(dp->dev, "failed to set ANSI 8B/10B encoding\n");
+		return ret;
+	}
+
+	ret = drm_dp_dpcd_writeb(&dp->aux, DP_LINK_BW_SET, bw_code);
+	if (ret < 0) {
+		dev_err(dp->dev, "failed to set DP bandwidth\n");
+		return ret;
+	}
+
+	zynqmp_dp_write(dp->iomem, ZYNQMP_DP_TX_LINK_BW_SET, bw_code);
+	switch (bw_code) {
+	case DP_LINK_BW_1_62:
+		reg = ZYNQMP_DP_TX_PHY_CLOCK_FEEDBACK_SETTING_162;
+		break;
+	case DP_LINK_BW_2_7:
+		reg = ZYNQMP_DP_TX_PHY_CLOCK_FEEDBACK_SETTING_270;
+		break;
+	case DP_LINK_BW_5_4:
+	default:
+		reg = ZYNQMP_DP_TX_PHY_CLOCK_FEEDBACK_SETTING_540;
+		break;
+	}
+
+	zynqmp_dp_write(dp->iomem, ZYNQMP_DP_TX_PHY_CLOCK_FEEDBACK_SETTING,
+			reg);
+	ret = zynqmp_dp_phy_ready(dp);
+	if (ret < 0)
+		return ret;
+
+	zynqmp_dp_write(dp->iomem, ZYNQMP_DP_TX_SCRAMBLING_DISABLE, 1);
+	memset(dp->train_set, 0, ARRAY_SIZE(dp->train_set));
+	ret = zynqmp_dp_link_train_cr(dp);
+	if (ret)
+		return ret;
+
+	ret = zynqmp_dp_link_train_ce(dp);
+	if (ret)
+		return ret;
+
+	ret = drm_dp_dpcd_writeb(&dp->aux, DP_TRAINING_PATTERN_SET,
+				 DP_TRAINING_PATTERN_DISABLE);
+	if (ret < 0) {
+		dev_err(dp->dev, "failed to disable training pattern\n");
+		return ret;
+	}
+	zynqmp_dp_write(dp->iomem, ZYNQMP_DP_TX_TRAINING_PATTERN_SET,
+			DP_TRAINING_PATTERN_DISABLE);
+
+	zynqmp_dp_write(dp->iomem, ZYNQMP_DP_TX_SCRAMBLING_DISABLE, 0);
+
+	return 0;
+}
+
+/**
+ * zynqmp_dp_train_loop - Downshift the link rate during training
+ * @dp: DisplayPort IP core structure
+ *
+ * Train the link by downshifting the link rate if training is not successful.
+ */
+static void zynqmp_dp_train_loop(struct zynqmp_dp *dp)
+{
+	struct zynqmp_dp_mode *mode = &dp->mode;
+	u8 bw = mode->bw_code;
+	int ret;
+
+	do {
+		if (dp->status == connector_status_disconnected ||
+		    !dp->enabled)
+			return;
+
+		ret = zynqmp_dp_train(dp);
+		if (!ret)
+			return;
+
+		ret = zynqmp_dp_mode_configure(dp, mode->pclock, bw);
+		if (ret < 0)
+			goto err_out;
+
+		bw = ret;
+	} while (bw >= DP_LINK_BW_1_62);
+
+err_out:
+	dev_err(dp->dev, "failed to train the DP link\n");
+}
+
+/*
+ * DP Aux functions
+ */
+
+#define AUX_READ_BIT	0x1
+
+/**
+ * zynqmp_dp_aux_cmd_submit - Submit aux command
+ * @dp: DisplayPort IP core structure
+ * @cmd: aux command
+ * @addr: aux address
+ * @buf: buffer for command data
+ * @bytes: number of bytes for @buf
+ * @reply: reply code to be returned
+ *
+ * Submit an aux command. All aux related commands, native or i2c aux
+ * read/write, are submitted through this function. The function is mapped to
+ * the transfer function of struct drm_dp_aux. This function involves in
+ * multiple register reads/writes, thus synchronization is needed, and it is
+ * done by drm_dp_helper using @hw_mutex. The calling thread goes into sleep
+ * if there's no immediate reply to the command submission. The reply code is
+ * returned at @reply if @reply != NULL.
+ *
+ * Return: 0 if the command is submitted properly, or corresponding error code:
+ * -EBUSY when there is any request already being processed
+ * -ETIMEDOUT when receiving reply is timed out
+ * -EIO when received bytes are less than requested
+ */
+static int zynqmp_dp_aux_cmd_submit(struct zynqmp_dp *dp, u32 cmd, u16 addr,
+				    u8 *buf, u8 bytes, u8 *reply)
+{
+	bool is_read = (cmd & AUX_READ_BIT) ? true : false;
+	void __iomem *iomem = dp->iomem;
+	u32 reg, i;
+
+	reg = zynqmp_dp_read(iomem, ZYNQMP_DP_TX_INTR_SIGNAL_STATE);
+	if (reg & ZYNQMP_DP_TX_INTR_SIGNAL_STATE_REQUEST)
+		return -EBUSY;
+
+	zynqmp_dp_write(iomem, ZYNQMP_DP_TX_AUX_ADDRESS, addr);
+	if (!is_read)
+		for (i = 0; i < bytes; i++)
+			zynqmp_dp_write(iomem, ZYNQMP_DP_TX_AUX_WRITE_FIFO,
+					buf[i]);
+
+	reg = cmd << ZYNQMP_DP_TX_AUX_COMMAND_CMD_SHIFT;
+	if (!buf || !bytes)
+		reg |= ZYNQMP_DP_TX_AUX_COMMAND_ADDRESS_ONLY;
+	else
+		reg |= (bytes - 1) << ZYNQMP_DP_TX_AUX_COMMAND_BYTES_SHIFT;
+	zynqmp_dp_write(iomem, ZYNQMP_DP_TX_AUX_COMMAND, reg);
+
+	/* Wait for reply to be delivered upto 2ms */
+	for (i = 0; ; i++) {
+		reg = zynqmp_dp_read(iomem, ZYNQMP_DP_TX_INTR_SIGNAL_STATE);
+		if (reg & ZYNQMP_DP_TX_INTR_SIGNAL_STATE_REPLY)
+			break;
+
+		if (reg & ZYNQMP_DP_TX_INTR_SIGNAL_STATE_REPLY_TIMEOUT ||
+		    i == 2)
+			return -ETIMEDOUT;
+
+		usleep_range(1000, 1100);
+	}
+
+	reg = zynqmp_dp_read(iomem, ZYNQMP_DP_TX_AUX_REPLY_CODE);
+	if (reply)
+		*reply = reg;
+
+	if (is_read &&
+	    (reg == ZYNQMP_DP_TX_AUX_REPLY_CODE_AUX_ACK ||
+	     reg == ZYNQMP_DP_TX_AUX_REPLY_CODE_I2C_ACK)) {
+		reg = zynqmp_dp_read(iomem, ZYNQMP_DP_TX_REPLY_DATA_CNT);
+		if ((reg & ZYNQMP_DP_TX_AUX_REPLY_CNT_MASK) != bytes)
+			return -EIO;
+
+		for (i = 0; i < bytes; i++) {
+			buf[i] = zynqmp_dp_read(iomem,
+						ZYNQMP_DP_TX_AUX_REPLY_DATA);
+		}
+	}
+
+	return 0;
+}
+
+static ssize_t
+zynqmp_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
+{
+	struct zynqmp_dp *dp = container_of(aux, struct zynqmp_dp, aux);
+	int ret;
+	unsigned int i, iter;
+
+	/* Number of loops = timeout in msec / aux delay (400 usec) */
+	iter = zynqmp_dp_aux_timeout_ms * 1000 / 400;
+	iter = iter ? iter : 1;
+
+	for (i = 0; i < iter; i++) {
+		ret = zynqmp_dp_aux_cmd_submit(dp, msg->request, msg->address,
+					       msg->buffer, msg->size,
+					       &msg->reply);
+		if (!ret) {
+			dev_dbg(dp->dev, "aux %d retries\n", i);
+			return msg->size;
+		}
+
+		if (dp->status == connector_status_disconnected) {
+			dev_dbg(dp->dev, "no connected aux device\n");
+			return -ENODEV;
+		}
+
+		usleep_range(400, 500);
+	}
+
+	dev_dbg(dp->dev, "failed to do aux transfer (%d)\n", ret);
+
+	return ret;
+}
+
+/**
+ * zynqmp_dp_init_aux - Initialize the DP aux
+ * @dp: DisplayPort IP core structure
+ *
+ * Initialize the DP aux. The aux clock is derived from the axi clock, so
+ * this function gets the axi clock frequency and calculates the filter
+ * value. Additionally, the interrupts and transmitter are enabled.
+ *
+ * Return: 0 on success, error value otherwise
+ */
+static int zynqmp_dp_init_aux(struct zynqmp_dp *dp)
+{
+	unsigned int rate;
+	u32 reg, w;
+
+	rate = zynqmp_disp_get_apb_clk_rate(dp->dpsub->disp);
+	if (rate < ZYNQMP_DP_TX_CLK_DIVIDER_MHZ) {
+		dev_err(dp->dev, "aclk should be higher than 1MHz\n");
+		return -EINVAL;
+	}
+
+	/* Allowable values for this register are: 8, 16, 24, 32, 40, 48 */
+	for (w = 8; w <= 48; w += 8) {
+		/* AUX pulse width should be between 0.4 to 0.6 usec */
+		if (w >= (4 * rate / 10000000) &&
+		    w <= (6 * rate / 10000000))
+			break;
+	}
+
+	if (w > 48) {
+		dev_err(dp->dev, "aclk frequency too high\n");
+		return -EINVAL;
+	}
+	reg = w << ZYNQMP_DP_TX_CLK_DIVIDER_AUX_FILTER_SHIFT;
+	reg |= rate / ZYNQMP_DP_TX_CLK_DIVIDER_MHZ;
+	zynqmp_dp_write(dp->iomem, ZYNQMP_DP_TX_CLK_DIVIDER, reg);
+	zynqmp_dp_write(dp->iomem, ZYNQMP_DP_SUB_TX_INTR_EN,
+			ZYNQMP_DP_TX_INTR_ALL);
+	zynqmp_dp_write(dp->iomem, ZYNQMP_DP_SUB_TX_INTR_DS,
+			ZYNQMP_DP_TX_NO_INTR_ALL);
+	zynqmp_dp_write(dp->iomem, ZYNQMP_DP_TX_ENABLE, 1);
+
+	return 0;
+}
+
+/**
+ * zynqmp_dp_exit_aux - De-initialize the DP aux
+ * @dp: DisplayPort IP core structure
+ *
+ * De-initialize the DP aux. Disable all interrupts which are enabled
+ * through aux initialization, as well as the transmitter.
+ */
+static void zynqmp_dp_exit_aux(struct zynqmp_dp *dp)
+{
+	zynqmp_dp_write(dp->iomem, ZYNQMP_DP_TX_ENABLE, 0);
+	zynqmp_dp_write(dp->iomem, ZYNQMP_DP_SUB_TX_INTR_DS, 0xffffffff);
+}
+
+/*
+ * Generic DP functions
+ */
+
+/**
+ * zynqmp_dp_update_misc - Write the misc registers
+ * @dp: DisplayPort IP core structure
+ *
+ * The misc register values are stored in the structure, and this
+ * function applies the values into the registers.
+ */
+static void zynqmp_dp_update_misc(struct zynqmp_dp *dp)
+{
+	zynqmp_dp_write(dp->iomem, ZYNQMP_DP_TX_MAIN_STREAM_MISC0,
+			dp->config.misc0);
+	zynqmp_dp_write(dp->iomem, ZYNQMP_DP_TX_MAIN_STREAM_MISC1,
+			dp->config.misc1);
+}
+
+/**
+ * zynqmp_dp_set_sync_mode - Set the sync mode bit in the software misc state
+ * @dp: DisplayPort IP core structure
+ * @mode: flag if the sync mode should be on or off
+ *
+ * Set the bit in software misc state. To apply to hardware,
+ * zynqmp_dp_update_misc() should be called.
+ */
+static void zynqmp_dp_set_sync_mode(struct zynqmp_dp *dp, bool mode)
+{
+	struct zynqmp_dp_config *config = &dp->config;
+
+	if (mode)
+		config->misc0 |= ZYNQMP_DP_TX_MAIN_STREAM_MISC0_SYNC;
+	else
+		config->misc0 &= ~ZYNQMP_DP_TX_MAIN_STREAM_MISC0_SYNC;
+}
+
+/**
+ * zynqmp_dp_get_sync_mode - Get the sync mode state
+ * @dp: DisplayPort IP core structure
+ *
+ * Return: true if the sync mode is on, or false
+ */
+static bool zynqmp_dp_get_sync_mode(struct zynqmp_dp *dp)
+{
+	struct zynqmp_dp_config *config = &dp->config;
+
+	return !!(config->misc0 & ZYNQMP_DP_TX_MAIN_STREAM_MISC0_SYNC);
+}
+
+/**
+ * zynqmp_dp_set_bpc - Set bpc value in software misc state
+ * @dp: DisplayPort IP core structure
+ * @bpc: bits per component
+ *
+ * Return: 0 on success, or the fallback bpc value
+ */
+static u8 zynqmp_dp_set_bpc(struct zynqmp_dp *dp, u8 bpc)
+{
+	struct zynqmp_dp_config *config = &dp->config;
+	u8 ret = 0;
+
+	if (dp->connector.display_info.bpc &&
+	    dp->connector.display_info.bpc != bpc) {
+		dev_err(dp->dev, "requested bpc (%u) != display info (%u)\n",
+			bpc, dp->connector.display_info.bpc);
+		bpc = dp->connector.display_info.bpc;
+	}
+
+	config->misc0 &= ~ZYNQMP_DP_MISC0_BPC_MASK;
+	switch (bpc) {
+	case 6:
+		config->misc0 |= ZYNQMP_DP_MISC0_BPC_6;
+		break;
+	case 8:
+		config->misc0 |= ZYNQMP_DP_MISC0_BPC_8;
+		break;
+	case 10:
+		config->misc0 |= ZYNQMP_DP_MISC0_BPC_10;
+		break;
+	case 12:
+		config->misc0 |= ZYNQMP_DP_MISC0_BPC_12;
+		break;
+	case 16:
+		config->misc0 |= ZYNQMP_DP_MISC0_BPC_16;
+		break;
+	default:
+		dev_err(dp->dev, "Not supported bpc (%u). fall back to 8bpc\n",
+			bpc);
+		config->misc0 |= ZYNQMP_DP_MISC0_BPC_8;
+		ret = 8;
+		break;
+	}
+	config->bpc = bpc;
+	zynqmp_dp_update_bpp(dp);
+
+	return ret;
+}
+
+/**
+ * zynqmp_dp_get_bpc - Set bpc value from software state
+ * @dp: DisplayPort IP core structure
+ *
+ * Return: current bpc value
+ */
+static u8 zynqmp_dp_get_bpc(struct zynqmp_dp *dp)
+{
+	return dp->config.bpc;
+}
+
+/**
+ * zynqmp_dp_encoder_mode_set_transfer_unit - Set the transfer unit values
+ * @dp: DisplayPort IP core structure
+ * @mode: requested display mode
+ *
+ * Set the transfer unit, and caculate all transfer unit size related values.
+ * Calculation is based on DP and IP core specification.
+ */
+static void
+zynqmp_dp_encoder_mode_set_transfer_unit(struct zynqmp_dp *dp,
+					 struct drm_display_mode *mode)
+{
+	u32 tu = ZYNQMP_DP_TX_DEF_TRANSFER_UNIT_SIZE;
+	u32 bw, vid_kbytes, avg_bytes_per_tu, init_wait;
+
+	/* Use the max transfer unit size (default) */
+	zynqmp_dp_write(dp->iomem, ZYNQMP_DP_TX_TRANSFER_UNIT_SIZE, tu);
+
+	vid_kbytes = mode->clock * (dp->config.bpp / 8);
+	bw = drm_dp_bw_code_to_link_rate(dp->mode.bw_code);
+	avg_bytes_per_tu = vid_kbytes * tu / (dp->mode.lane_cnt * bw / 1000);
+	zynqmp_dp_write(dp->iomem, ZYNQMP_DP_TX_MIN_BYTES_PER_TU,
+			avg_bytes_per_tu / 1000);
+	zynqmp_dp_write(dp->iomem, ZYNQMP_DP_TX_FRAC_BYTES_PER_TU,
+			avg_bytes_per_tu % 1000);
+
+	/* Configure the initial wait cycle based on transfer unit size */
+	if (tu < (avg_bytes_per_tu / 1000))
+		init_wait = 0;
+	else if ((avg_bytes_per_tu / 1000) <= 4)
+		init_wait = tu;
+	else
+		init_wait = tu - avg_bytes_per_tu / 1000;
+
+	zynqmp_dp_write(dp->iomem, ZYNQMP_DP_TX_INIT_WAIT, init_wait);
+}
+
+/**
+ * zynqmp_dp_encoder_mode_set_stream - Configure the main stream
+ * @dp: DisplayPort IP core structure
+ * @mode: requested display mode
+ *
+ * Configure the main stream based on the requested mode @mode. Calculation is
+ * based on IP core specification.
+ */
+void zynqmp_dp_encoder_mode_set_stream(struct zynqmp_dp *dp,
+				       struct drm_display_mode *mode)
+{
+	void __iomem *iomem = dp->iomem;
+	u8 lane_cnt = dp->mode.lane_cnt;
+	u32 reg, wpl;
+	unsigned int rate;
+
+	zynqmp_dp_write(iomem, ZYNQMP_DP_TX_MAIN_STREAM_HTOTAL, mode->htotal);
+	zynqmp_dp_write(iomem, ZYNQMP_DP_TX_MAIN_STREAM_VTOTAL, mode->vtotal);
+	zynqmp_dp_write(iomem, ZYNQMP_DP_TX_MAIN_STREAM_POLARITY,
+			(!!(mode->flags & DRM_MODE_FLAG_PVSYNC) <<
+			 ZYNQMP_DP_TX_MAIN_STREAM_POLARITY_VSYNC_SHIFT) |
+			(!!(mode->flags & DRM_MODE_FLAG_PHSYNC) <<
+			 ZYNQMP_DP_TX_MAIN_STREAM_POLARITY_HSYNC_SHIFT));
+	zynqmp_dp_write(iomem, ZYNQMP_DP_TX_MAIN_STREAM_HSWIDTH,
+			mode->hsync_end - mode->hsync_start);
+	zynqmp_dp_write(iomem, ZYNQMP_DP_TX_MAIN_STREAM_VSWIDTH,
+			mode->vsync_end - mode->vsync_start);
+	zynqmp_dp_write(iomem, ZYNQMP_DP_TX_MAIN_STREAM_HRES, mode->hdisplay);
+	zynqmp_dp_write(iomem, ZYNQMP_DP_TX_MAIN_STREAM_VRES, mode->vdisplay);
+	zynqmp_dp_write(iomem, ZYNQMP_DP_TX_MAIN_STREAM_HSTART,
+			mode->htotal - mode->hsync_start);
+	zynqmp_dp_write(iomem, ZYNQMP_DP_TX_MAIN_STREAM_VSTART,
+			mode->vtotal - mode->vsync_start);
+
+	/* In synchronous mode, set the diviers */
+	if (dp->config.misc0 & ZYNQMP_DP_TX_MAIN_STREAM_MISC0_SYNC) {
+		reg = drm_dp_bw_code_to_link_rate(dp->mode.bw_code);
+		zynqmp_dp_write(iomem, ZYNQMP_DP_TX_N_VID, reg);
+		zynqmp_dp_write(iomem, ZYNQMP_DP_TX_M_VID, mode->clock);
+		rate = zynqmp_disp_get_aud_clk_rate(dp->dpsub->disp);
+		if (rate) {
+			dev_dbg(dp->dev, "Audio rate: %d\n", rate / 512);
+			zynqmp_dp_write(iomem, ZYNQMP_DP_TX_AUDIO_N_AUD, reg);
+			zynqmp_dp_write(iomem, ZYNQMP_DP_TX_AUDIO_M_AUD,
+					rate / 1000);
+		}
+	}
+
+	/* Only 2 channel audio is supported now */
+	if (zynqmp_disp_aud_enabled(dp->dpsub->disp))
+		zynqmp_dp_write(iomem, ZYNQMP_DP_TX_AUDIO_CHANNELS, 1);
+
+	zynqmp_dp_write(iomem, ZYNQMP_DP_TX_USER_PIXEL_WIDTH, 1);
+
+	/* Translate to the native 16 bit datapath based on IP core spec */
+	wpl = (mode->hdisplay * dp->config.bpp + 15) / 16;
+	reg = wpl + wpl % lane_cnt - lane_cnt;
+	zynqmp_dp_write(iomem, ZYNQMP_DP_TX_USER_DATA_CNT_PER_LANE, reg);
+}
+
+/*
+ * DRM connector functions
+ */
+
+static enum drm_connector_status
+zynqmp_dp_connector_detect(struct drm_connector *connector, bool force)
+{
+	struct zynqmp_dp *dp = connector_to_dp(connector);
+	struct zynqmp_dp_link_config *link_config = &dp->link_config;
+	u32 state, i;
+	int ret;
+
+	/*
+	 * This is from heuristic. It takes some delay (ex, 100 ~ 500 msec) to
+	 * get the HPD signal with some monitors.
+	 */
+	for (i = 0; i < 10; i++) {
+		state = zynqmp_dp_read(dp->iomem,
+				       ZYNQMP_DP_TX_INTR_SIGNAL_STATE);
+		if (state & ZYNQMP_DP_TX_INTR_SIGNAL_STATE_HPD)
+			break;
+		msleep(100);
+	}
+
+	if (state & ZYNQMP_DP_TX_INTR_SIGNAL_STATE_HPD) {
+		dp->status = connector_status_connected;
+		ret = drm_dp_dpcd_read(&dp->aux, 0x0, dp->dpcd,
+				       sizeof(dp->dpcd));
+		if (ret < 0) {
+			dev_dbg(dp->dev, "DPCD read first try fails");
+			ret = drm_dp_dpcd_read(&dp->aux, 0x0, dp->dpcd,
+					       sizeof(dp->dpcd));
+			if (ret < 0) {
+				dev_dbg(dp->dev, "DPCD read retry fails");
+				goto disconnected;
+			}
+		}
+
+		link_config->max_rate = min_t(int,
+					      drm_dp_max_link_rate(dp->dpcd),
+					      DP_HIGH_BIT_RATE2);
+		link_config->max_lanes = min_t(u8,
+					       drm_dp_max_lane_count(dp->dpcd),
+					       dp->num_lanes);
+
+		return connector_status_connected;
+	}
+
+disconnected:
+	dp->status = connector_status_disconnected;
+	return connector_status_disconnected;
+}
+
+static int zynqmp_dp_connector_get_modes(struct drm_connector *connector)
+{
+	struct zynqmp_dp *dp = connector_to_dp(connector);
+	struct edid *edid;
+	int ret;
+
+	edid = drm_get_edid(connector, &dp->aux.ddc);
+	if (!edid)
+		return 0;
+
+	drm_connector_update_edid_property(connector, edid);
+	ret = drm_add_edid_modes(connector, edid);
+	kfree(edid);
+
+	return ret;
+}
+
+static struct drm_encoder *
+zynqmp_dp_connector_best_encoder(struct drm_connector *connector)
+{
+	struct zynqmp_dp *dp = connector_to_dp(connector);
+
+	return &dp->encoder;
+}
+
+static int zynqmp_dp_connector_mode_valid(struct drm_connector *connector,
+					  struct drm_display_mode *mode)
+{
+	struct zynqmp_dp *dp = connector_to_dp(connector);
+	u8 max_lanes = dp->link_config.max_lanes;
+	u8 bpp = dp->config.bpp;
+	int max_rate = dp->link_config.max_rate;
+	int rate;
+
+	if (mode->clock > ZYNQMP_MAX_FREQ) {
+		dev_dbg(dp->dev, "filtered the mode, %s,for high pixel rate\n",
+			mode->name);
+		drm_mode_debug_printmodeline(mode);
+		return MODE_CLOCK_HIGH;
+	}
+
+	/* Check with link rate and lane count */
+	rate = zynqmp_dp_max_rate(max_rate, max_lanes, bpp);
+	if (mode->clock > rate) {
+		dev_dbg(dp->dev, "filtered the mode, %s,for high pixel rate\n",
+			mode->name);
+		drm_mode_debug_printmodeline(mode);
+		return MODE_CLOCK_HIGH;
+	}
+
+	return MODE_OK;
+}
+
+static void zynqmp_dp_connector_destroy(struct drm_connector *connector)
+{
+	drm_connector_unregister(connector);
+	drm_connector_cleanup(connector);
+}
+
+static int
+zynqmp_dp_connector_atomic_set_property(struct drm_connector *connector,
+					struct drm_connector_state *state,
+					struct drm_property *property,
+					uint64_t val)
+{
+	struct zynqmp_dp *dp = connector_to_dp(connector);
+
+	if (property == dp->sync_prop) {
+		zynqmp_dp_set_sync_mode(dp, val);
+	} else if (property == dp->bpc_prop) {
+		u8 bpc;
+
+		bpc = zynqmp_dp_set_bpc(dp, val);
+		if (bpc) {
+			drm_object_property_set_value(&connector->base,
+						      property, bpc);
+			return -EINVAL;
+		}
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+zynqmp_dp_connector_atomic_get_property(struct drm_connector *connector,
+					const struct drm_connector_state *state,
+					struct drm_property *property,
+					uint64_t *val)
+{
+	struct zynqmp_dp *dp = connector_to_dp(connector);
+
+	if (property == dp->sync_prop)
+		*val = zynqmp_dp_get_sync_mode(dp);
+	else if (property == dp->bpc_prop)
+		*val =  zynqmp_dp_get_bpc(dp);
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+static const struct drm_connector_funcs zynqmp_dp_connector_funcs = {
+	.detect			= zynqmp_dp_connector_detect,
+	.fill_modes		= drm_helper_probe_single_connector_modes,
+	.destroy		= zynqmp_dp_connector_destroy,
+	.atomic_duplicate_state	= drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state	= drm_atomic_helper_connector_destroy_state,
+	.reset			= drm_atomic_helper_connector_reset,
+	.atomic_set_property	= zynqmp_dp_connector_atomic_set_property,
+	.atomic_get_property	= zynqmp_dp_connector_atomic_get_property,
+};
+
+static struct drm_connector_helper_funcs zynqmp_dp_connector_helper_funcs = {
+	.get_modes	= zynqmp_dp_connector_get_modes,
+	.best_encoder	= zynqmp_dp_connector_best_encoder,
+	.mode_valid	= zynqmp_dp_connector_mode_valid,
+};
+
+/*
+ * DRM encoder functions
+ */
+
+static void zynqmp_dp_encoder_enable(struct drm_encoder *encoder)
+{
+	struct zynqmp_dp *dp = encoder_to_dp(encoder);
+	void __iomem *iomem = dp->iomem;
+	unsigned int i;
+	int ret = 0;
+
+	ret = pm_runtime_get_sync(dp->dev);
+	if (ret < 0) {
+		dev_err(dp->dev, "IRQ sync failed to resume: %d\n", ret);
+		return;
+	}
+
+	dp->enabled = true;
+	zynqmp_dp_init_aux(dp);
+	zynqmp_dp_update_misc(dp);
+	if (zynqmp_disp_aud_enabled(dp->dpsub->disp))
+		zynqmp_dp_write(iomem, ZYNQMP_DP_TX_AUDIO_CONTROL, 1);
+	zynqmp_dp_write(iomem, ZYNQMP_DP_TX_PHY_POWER_DOWN, 0);
+	if (dp->status == connector_status_connected) {
+		for (i = 0; i < 3; i++) {
+			ret = drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER,
+						 DP_SET_POWER_D0);
+			if (ret == 1)
+				break;
+			usleep_range(300, 500);
+		}
+		/* Some monitors take time to wake up properly */
+		msleep(zynqmp_dp_power_on_delay_ms);
+	}
+	if (ret != 1)
+		dev_dbg(dp->dev, "DP aux failed\n");
+	else
+		zynqmp_dp_train_loop(dp);
+	zynqmp_dp_write(iomem, ZYNQMP_DP_TX_SW_RESET,
+			ZYNQMP_DP_TX_SW_RESET_ALL);
+	zynqmp_dp_write(iomem, ZYNQMP_DP_TX_ENABLE_MAIN_STREAM, 1);
+}
+
+static void zynqmp_dp_encoder_disable(struct drm_encoder *encoder)
+{
+	struct zynqmp_dp *dp = encoder_to_dp(encoder);
+	void __iomem *iomem = dp->iomem;
+	int ret;
+
+	dp->enabled = false;
+	cancel_delayed_work(&dp->hpd_work);
+	zynqmp_dp_write(iomem, ZYNQMP_DP_TX_ENABLE_MAIN_STREAM, 0);
+	ret = drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, DP_SET_POWER_D3);
+	if (ret < 0) {
+		dev_err(dp->dev, "failed to write a byte to the DPCD: %d\n",
+			ret);
+		return;
+	}
+	zynqmp_dp_write(iomem, ZYNQMP_DP_TX_PHY_POWER_DOWN,
+			ZYNQMP_DP_TX_PHY_POWER_DOWN_ALL);
+	if (zynqmp_disp_aud_enabled(dp->dpsub->disp))
+		zynqmp_dp_write(iomem, ZYNQMP_DP_TX_AUDIO_CONTROL, 0);
+	pm_runtime_put_sync(dp->dev);
+}
+
+static void
+zynqmp_dp_encoder_atomic_mode_set(struct drm_encoder *encoder,
+				  struct drm_crtc_state *crtc_state,
+				  struct drm_connector_state *connector_state)
+{
+	struct zynqmp_dp *dp = encoder_to_dp(encoder);
+	struct drm_display_mode *mode = &crtc_state->mode;
+	struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
+	u8 max_lanes = dp->link_config.max_lanes;
+	u8 bpp = dp->config.bpp;
+	int rate, max_rate = dp->link_config.max_rate;
+	int ret;
+
+	/* Check again as bpp or format might have been chagned */
+	rate = zynqmp_dp_max_rate(max_rate, max_lanes, bpp);
+	if (mode->clock > rate) {
+		dev_err(dp->dev, "the mode, %s,has too high pixel rate\n",
+			mode->name);
+		drm_mode_debug_printmodeline(mode);
+	}
+
+	ret = zynqmp_dp_mode_configure(dp, adjusted_mode->clock, 0);
+	if (ret < 0)
+		return;
+
+	zynqmp_dp_encoder_mode_set_transfer_unit(dp, adjusted_mode);
+}
+
+#define ZYNQMP_DP_MIN_H_BACKPORCH	20
+
+static int
+zynqmp_dp_encoder_atomic_check(struct drm_encoder *encoder,
+			       struct drm_crtc_state *crtc_state,
+			       struct drm_connector_state *conn_state)
+{
+	struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
+	int diff = adjusted_mode->htotal - adjusted_mode->hsync_end;
+
+	/*
+	 * ZynqMP DP requires horizontal backporch to be greater than 12.
+	 * This limitation may not be compatible with the sink device.
+	 */
+	if (diff < ZYNQMP_DP_MIN_H_BACKPORCH) {
+		dev_dbg(encoder->dev->dev, "hbackporch adjusted: %d to %d",
+			diff, ZYNQMP_DP_MIN_H_BACKPORCH - diff);
+		diff = ZYNQMP_DP_MIN_H_BACKPORCH - diff;
+		adjusted_mode->htotal += diff;
+		adjusted_mode->clock = (adjusted_mode->clock *
+					adjusted_mode->htotal) /
+				       (adjusted_mode->htotal - diff);
+	}
+
+	return 0;
+}
+
+static const struct drm_encoder_funcs zynqmp_dp_encoder_funcs = {
+	.destroy = drm_encoder_cleanup,
+};
+
+static const struct drm_encoder_helper_funcs zynqmp_dp_encoder_helper_funcs = {
+	.enable			= zynqmp_dp_encoder_enable,
+	.disable		= zynqmp_dp_encoder_disable,
+	.atomic_mode_set	= zynqmp_dp_encoder_atomic_mode_set,
+	.atomic_check		= zynqmp_dp_encoder_atomic_check,
+};
+
+/*
+ * Component functions
+ */
+
+static void zynqmp_dp_hpd_work_func(struct work_struct *work)
+{
+	struct zynqmp_dp *dp;
+
+	dp = container_of(work, struct zynqmp_dp, hpd_work.work);
+
+	if (dp->drm)
+		drm_helper_hpd_irq_event(dp->drm);
+}
+
+static struct drm_prop_enum_list zynqmp_dp_bpc_enum[] = {
+	{ 6, "6BPC" },
+	{ 8, "8BPC" },
+	{ 10, "10BPC" },
+	{ 12, "12BPC" },
+};
+
+int zynqmp_dp_bind(struct device *dev, struct device *master, void *data)
+{
+	struct zynqmp_dpsub *dpsub = dev_get_drvdata(dev);
+	struct zynqmp_dp *dp = dpsub->dp;
+	struct drm_encoder *encoder = &dp->encoder;
+	struct drm_connector *connector = &dp->connector;
+	struct drm_device *drm = data;
+	int ret;
+
+	if (!dp->num_lanes)
+		return 0;
+
+	encoder->possible_crtcs |= zynqmp_disp_get_crtc_mask(dpsub->disp);
+	if (dpsub->external_crtc_attached)
+		encoder->possible_crtcs |=
+			drm_of_find_possible_crtcs(drm, dev->of_node);
+
+	drm_encoder_init(drm, encoder, &zynqmp_dp_encoder_funcs,
+			 DRM_MODE_ENCODER_TMDS, NULL);
+	drm_encoder_helper_add(encoder, &zynqmp_dp_encoder_helper_funcs);
+
+	connector->polled = DRM_CONNECTOR_POLL_HPD;
+	ret = drm_connector_init(encoder->dev, connector,
+				 &zynqmp_dp_connector_funcs,
+				 DRM_MODE_CONNECTOR_DisplayPort);
+	if (ret) {
+		dev_err(dp->dev, "failed to initialize the drm connector");
+		goto error_encoder;
+	}
+
+	drm_connector_helper_add(connector, &zynqmp_dp_connector_helper_funcs);
+	drm_connector_register(connector);
+	drm_connector_attach_encoder(connector, encoder);
+	connector->dpms = DRM_MODE_DPMS_OFF;
+
+	dp->drm = drm;
+	dp->sync_prop = drm_property_create_bool(drm, 0, "sync");
+	dp->bpc_prop = drm_property_create_enum(drm, 0, "bpc",
+						zynqmp_dp_bpc_enum,
+						ARRAY_SIZE(zynqmp_dp_bpc_enum));
+
+	dp->config.misc0 &= ~ZYNQMP_DP_TX_MAIN_STREAM_MISC0_SYNC;
+	drm_object_attach_property(&connector->base, dp->sync_prop, false);
+	ret = zynqmp_dp_set_bpc(dp, 8);
+	drm_object_attach_property(&connector->base, dp->bpc_prop,
+				   ret ? ret : 8);
+	zynqmp_dp_update_bpp(dp);
+
+	INIT_DELAYED_WORK(&dp->hpd_work, zynqmp_dp_hpd_work_func);
+
+	/* This enables interrupts, so should be called after DRM init */
+	ret = zynqmp_dp_init_aux(dp);
+	if (ret) {
+		dev_err(dp->dev, "failed to initialize DP aux");
+		goto error_prop;
+	}
+
+	return 0;
+
+error_prop:
+	drm_property_destroy(dp->drm, dp->bpc_prop);
+	drm_property_destroy(dp->drm, dp->sync_prop);
+	zynqmp_dp_connector_destroy(&dp->connector);
+error_encoder:
+	drm_encoder_cleanup(&dp->encoder);
+	return ret;
+}
+
+void zynqmp_dp_unbind(struct device *dev, struct device *master, void *data)
+{
+	struct zynqmp_dpsub *dpsub = dev_get_drvdata(dev);
+	struct zynqmp_dp *dp = dpsub->dp;
+
+	disable_irq(dp->irq);
+	if (!dp->num_lanes)
+		return;
+
+	cancel_delayed_work_sync(&dp->hpd_work);
+	zynqmp_dp_exit_aux(dp);
+	drm_property_destroy(dp->drm, dp->bpc_prop);
+	drm_property_destroy(dp->drm, dp->sync_prop);
+	zynqmp_dp_connector_destroy(&dp->connector);
+	drm_encoder_cleanup(&dp->encoder);
+}
+
+/*
+ * Platform functions
+ */
+
+static irqreturn_t zynqmp_dp_irq_handler(int irq, void *data)
+{
+	struct zynqmp_dp *dp = (struct zynqmp_dp *)data;
+	u32 status, mask;
+
+	status = zynqmp_dp_read(dp->iomem, ZYNQMP_DP_SUB_TX_INTR_STATUS);
+	mask = zynqmp_dp_read(dp->iomem, ZYNQMP_DP_SUB_TX_INTR_MASK);
+	if (!(status & ~mask))
+		return IRQ_NONE;
+
+	/* dbg for diagnostic, but not much that the driver can do */
+	if (status & ZYNQMP_DP_TX_INTR_CHBUF_UNDERFLW_MASK)
+		dev_dbg_ratelimited(dp->dev, "underflow interrupt\n");
+	if (status & ZYNQMP_DP_TX_INTR_CHBUF_OVERFLW_MASK)
+		dev_dbg_ratelimited(dp->dev, "overflow interrupt\n");
+
+	zynqmp_dp_write(dp->iomem, ZYNQMP_DP_SUB_TX_INTR_STATUS, status);
+
+	/* The DP vblank will not be enabled with remote crtc device */
+	if (status & ZYNQMP_DP_TX_INTR_VBLANK_START &&
+		!dp->dpsub->external_crtc_attached)
+		zynqmp_disp_handle_vblank(dp->dpsub->disp);
+
+	if (status & ZYNQMP_DP_TX_INTR_HPD_EVENT)
+		schedule_delayed_work(&dp->hpd_work, 0);
+
+	if (status & ZYNQMP_DP_TX_INTR_HPD_IRQ) {
+		int ret;
+		u8 buf[DP_LINK_STATUS_SIZE + 2];
+
+		memset(buf, 0, ARRAY_SIZE(buf));
+
+		ret = drm_dp_dpcd_read(&dp->aux, DP_SINK_COUNT, buf,
+				       DP_LINK_STATUS_SIZE + 2);
+		if (ret < 0)
+			goto handled;
+
+		if (buf[4] & DP_LINK_STATUS_UPDATED ||
+		    !drm_dp_clock_recovery_ok(&buf[2], dp->mode.lane_cnt) ||
+		    !drm_dp_channel_eq_ok(&buf[2], dp->mode.lane_cnt)) {
+			zynqmp_dp_train_loop(dp);
+		}
+	}
+
+handled:
+	return IRQ_HANDLED;
+}
+
+int zynqmp_dp_probe(struct platform_device *pdev)
+{
+	struct zynqmp_dpsub *dpsub;
+	struct zynqmp_dp *dp;
+	struct resource *res;
+	struct device_node *port;
+	unsigned int i;
+	int irq, ret;
+
+	dp = devm_kzalloc(&pdev->dev, sizeof(*dp), GFP_KERNEL);
+	if (!dp)
+		return -ENOMEM;
+
+	dp->dpms = DRM_MODE_DPMS_OFF;
+	dp->status = connector_status_disconnected;
+	dp->dev = &pdev->dev;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dp");
+	dp->iomem = devm_ioremap_resource(dp->dev, res);
+	if (IS_ERR(dp->iomem))
+		return PTR_ERR(dp->iomem);
+
+	zynqmp_dp_write(dp->iomem, ZYNQMP_DP_TX_PHY_POWER_DOWN,
+			ZYNQMP_DP_TX_PHY_POWER_DOWN_ALL);
+	zynqmp_dp_set(dp->iomem, ZYNQMP_DP_TX_PHY_CONFIG,
+		      ZYNQMP_DP_TX_PHY_CONFIG_ALL_RESET);
+	zynqmp_dp_write(dp->iomem, ZYNQMP_DP_TX_FORCE_SCRAMBLER_RESET, 1);
+	zynqmp_dp_write(dp->iomem, ZYNQMP_DP_TX_ENABLE, 0);
+
+	dp->num_lanes = 2;
+	for (i = 0; i < ZYNQMP_DP_MAX_LANES; i++) {
+		char phy_name[16];
+
+		snprintf(phy_name, sizeof(phy_name), "dp-phy%d", i);
+		dp->phy[i] = devm_phy_get(dp->dev, phy_name);
+		if (IS_ERR(dp->phy[i])) {
+			ret = PTR_ERR(dp->phy[i]);
+			dp->phy[i] = NULL;
+
+			/* 2nd lane is optional */
+			if (i == 1 && ret == -ENODEV) {
+				dp->num_lanes = 1;
+				break;
+			}
+
+			/*
+			 * If no phy lane is assigned, the DP Tx gets disabled.
+			 * The display part of the DP subsystem can still be
+			 * used to drive the output to FPGA, thus let the DP
+			 * subsystem driver to proceed without this DP Tx.
+			 */
+			if (i == 0 && ret == -ENODEV) {
+				dp->num_lanes = 0;
+				goto out;
+			}
+
+			if (ret != -EPROBE_DEFER)
+				dev_err(dp->dev, "failed to get phy lane\n");
+
+			return ret;
+		}
+	}
+
+	ret = zynqmp_dp_init_phy(dp);
+	if (ret)
+		goto error_phy;
+
+	dp->aux.name = "ZynqMP DP AUX";
+	dp->aux.dev = dp->dev;
+	dp->aux.transfer = zynqmp_dp_aux_transfer;
+	ret = drm_dp_aux_register(&dp->aux);
+	if (ret < 0) {
+		dev_err(dp->dev, "failed to initialize DP aux\n");
+		goto error;
+	}
+
+out:
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		ret = irq;
+		goto error;
+	}
+
+	ret = devm_request_threaded_irq(dp->dev, irq, NULL,
+					zynqmp_dp_irq_handler, IRQF_ONESHOT,
+					dev_name(dp->dev), dp);
+	if (ret < 0)
+		goto error;
+	dp->irq = irq;
+
+	dpsub = platform_get_drvdata(pdev);
+	dpsub->dp = dp;
+	dp->dpsub = dpsub;
+
+	for_each_child_of_node(pdev->dev.of_node, port) {
+		if (!port->name || of_node_cmp(port->name, "port"))
+			continue;
+
+		dpsub->external_crtc_attached = true;
+		break;
+	}
+
+	dev_dbg(dp->dev,
+		"ZynqMP DisplayPort Tx driver probed with %u phy lanes\n",
+		dp->num_lanes);
+
+	return 0;
+
+error:
+	drm_dp_aux_unregister(&dp->aux);
+error_phy:
+	zynqmp_dp_exit_phy(dp);
+	return ret;
+}
+
+int zynqmp_dp_remove(struct platform_device *pdev)
+{
+	struct zynqmp_dpsub *dpsub = platform_get_drvdata(pdev);
+	struct zynqmp_dp *dp = dpsub->dp;
+
+	zynqmp_dp_write(dp->iomem, ZYNQMP_DP_TX_ENABLE, 0);
+	drm_dp_aux_unregister(&dp->aux);
+	zynqmp_dp_exit_phy(dp);
+	dpsub->dp = NULL;
+
+	return 0;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/xlnx/zynqmp_dp.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/xlnx/zynqmp_dp.h
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ZynqMP DisplayPort Driver
+ *
+ *  Copyright (C) 2017 - 2018 Xilinx, Inc.
+ *
+ *  Author: Hyun Woo Kwon <hyun.kwon@xilinx.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _ZYNQMP_DP_H_
+#define _ZYNQMP_DP_H_
+
+struct zynqmp_dp;
+struct drm_display_mode;
+
+int zynqmp_dp_set_color(struct zynqmp_dp *dp, const char *color);
+void zynqmp_dp_enable_vblank(struct zynqmp_dp *dp);
+void zynqmp_dp_disable_vblank(struct zynqmp_dp *dp);
+void zynqmp_dp_encoder_mode_set_stream(struct zynqmp_dp *dp,
+				       struct drm_display_mode *mode);
+void __maybe_unused zynqmp_dp_pm_suspend(struct zynqmp_dp *dp);
+void __maybe_unused zynqmp_dp_pm_resume(struct zynqmp_dp *dp);
+int zynqmp_dp_bind(struct device *dev, struct device *master, void *data);
+void zynqmp_dp_unbind(struct device *dev, struct device *master, void *data);
+
+int zynqmp_dp_probe(struct platform_device *pdev);
+int zynqmp_dp_remove(struct platform_device *pdev);
+
+#endif /* _ZYNQMP_DP_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/xlnx/zynqmp_dpsub.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/xlnx/zynqmp_dpsub.c
@@ -0,0 +1,207 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ZynqMP DP Subsystem Driver
+ *
+ *  Copyright (C) 2017 - 2018 Xilinx, Inc.
+ *
+ *  Author: Hyun Woo Kwon <hyun.kwon@xilinx.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/component.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/of_reserved_mem.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+
+#include "xlnx_drv.h"
+
+#include "zynqmp_disp.h"
+#include "zynqmp_dp.h"
+#include "zynqmp_dpsub.h"
+
+#define DP_PCM_NAME_0 "zynqmp_dp_snd_pcm0"
+#define DP_PCM_NAME_1 "zynqmp_dp_snd_pcm1"
+
+static int
+zynqmp_dpsub_bind(struct device *dev, struct device *master, void *data)
+{
+	int ret;
+
+	ret = zynqmp_disp_bind(dev, master, data);
+	if (ret)
+		return ret;
+
+	/* zynqmp_disp should bind first, so zynqmp_dp encoder can find crtc */
+	ret = zynqmp_dp_bind(dev, master, data);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static void
+zynqmp_dpsub_unbind(struct device *dev, struct device *master, void *data)
+{
+	zynqmp_dp_unbind(dev, master, data);
+	zynqmp_disp_unbind(dev, master, data);
+}
+
+static const struct component_ops zynqmp_dpsub_component_ops = {
+	.bind	= zynqmp_dpsub_bind,
+	.unbind	= zynqmp_dpsub_unbind,
+};
+
+static struct of_dev_auxdata zynqmp_dpsub_auxdata_lookup[] = {
+	OF_DEV_AUXDATA("xlnx,dp-snd-pcm0", 0, DP_PCM_NAME_0, NULL),
+	OF_DEV_AUXDATA("xlnx,dp-snd-pcm1", 0, DP_PCM_NAME_1, NULL),
+	{ /* end of table */ }
+};
+
+static int zynqmp_dpsub_probe(struct platform_device *pdev)
+{
+	struct zynqmp_dpsub *dpsub;
+	int ret;
+
+	dpsub = devm_kzalloc(&pdev->dev, sizeof(*dpsub), GFP_KERNEL);
+	if (!dpsub)
+		return -ENOMEM;
+
+	/* Sub-driver will access dpsub from drvdata */
+	platform_set_drvdata(pdev, dpsub);
+	pm_runtime_enable(&pdev->dev);
+
+	/*
+	 * DP should be probed first so that the zynqmp_disp can set the output
+	 * format accordingly.
+	 */
+	ret = zynqmp_dp_probe(pdev);
+	if (ret)
+		goto err_pm;
+
+	ret = zynqmp_disp_probe(pdev);
+	if (ret)
+		goto err_dp;
+
+	ret = component_add(&pdev->dev, &zynqmp_dpsub_component_ops);
+	if (ret)
+		goto err_disp;
+
+	/* Try the reserved memory. Proceed if there's none */
+	of_reserved_mem_device_init(&pdev->dev);
+
+	/* Populate the sound child nodes */
+	ret = of_platform_populate(pdev->dev.of_node, NULL,
+				   zynqmp_dpsub_auxdata_lookup, &pdev->dev);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to populate child nodes\n");
+		goto err_rmem;
+	}
+
+	if (!dpsub->external_crtc_attached) {
+		dpsub->master = xlnx_drm_pipeline_init(pdev);
+		if (IS_ERR(dpsub->master)) {
+			dev_err(&pdev->dev, "failed to initialize the drm pipeline\n");
+			goto err_populate;
+		}
+	}
+
+	dev_info(&pdev->dev, "ZynqMP DisplayPort Subsystem driver probed");
+
+	return 0;
+
+err_populate:
+	of_platform_depopulate(&pdev->dev);
+err_rmem:
+	of_reserved_mem_device_release(&pdev->dev);
+	component_del(&pdev->dev, &zynqmp_dpsub_component_ops);
+err_disp:
+	zynqmp_disp_remove(pdev);
+err_dp:
+	zynqmp_dp_remove(pdev);
+err_pm:
+	pm_runtime_disable(&pdev->dev);
+	return ret;
+}
+
+static int zynqmp_dpsub_remove(struct platform_device *pdev)
+{
+	struct zynqmp_dpsub *dpsub = platform_get_drvdata(pdev);
+	int err, ret = 0;
+
+	if (!dpsub->external_crtc_attached)
+		xlnx_drm_pipeline_exit(dpsub->master);
+	of_platform_depopulate(&pdev->dev);
+	of_reserved_mem_device_release(&pdev->dev);
+	component_del(&pdev->dev, &zynqmp_dpsub_component_ops);
+
+	err = zynqmp_disp_remove(pdev);
+	if (err)
+		ret = -EIO;
+
+	err = zynqmp_dp_remove(pdev);
+	if (err)
+		ret = -EIO;
+
+	pm_runtime_disable(&pdev->dev);
+
+	return ret;
+}
+
+static int __maybe_unused zynqmp_dpsub_pm_suspend(struct device *dev)
+{
+	struct platform_device *pdev =
+		container_of(dev, struct platform_device, dev);
+	struct zynqmp_dpsub *dpsub = platform_get_drvdata(pdev);
+
+	zynqmp_dp_pm_suspend(dpsub->dp);
+
+	return 0;
+}
+
+static int __maybe_unused zynqmp_dpsub_pm_resume(struct device *dev)
+{
+	struct platform_device *pdev =
+		container_of(dev, struct platform_device, dev);
+	struct zynqmp_dpsub *dpsub = platform_get_drvdata(pdev);
+
+	zynqmp_dp_pm_resume(dpsub->dp);
+
+	return 0;
+}
+
+static const struct dev_pm_ops zynqmp_dpsub_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(zynqmp_dpsub_pm_suspend,
+			zynqmp_dpsub_pm_resume)
+};
+
+static const struct of_device_id zynqmp_dpsub_of_match[] = {
+	{ .compatible = "xlnx,zynqmp-dpsub-1.7", },
+	{ /* end of table */ },
+};
+MODULE_DEVICE_TABLE(of, zynqmp_dpsub_of_match);
+
+static struct platform_driver zynqmp_dpsub_driver = {
+	.probe			= zynqmp_dpsub_probe,
+	.remove			= zynqmp_dpsub_remove,
+	.driver			= {
+		.name		= "zynqmp-display",
+		.of_match_table	= zynqmp_dpsub_of_match,
+		.pm             = &zynqmp_dpsub_pm_ops,
+	},
+};
+
+module_platform_driver(zynqmp_dpsub_driver);
+
+MODULE_AUTHOR("Xilinx, Inc.");
+MODULE_DESCRIPTION("ZynqMP DP Subsystem Driver");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/xlnx/zynqmp_dpsub.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/xlnx/zynqmp_dpsub.h
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ZynqMP DPSUB Subsystem Driver
+ *
+ *  Copyright (C) 2017 - 2018 Xilinx, Inc.
+ *
+ *  Author: Hyun Woo Kwon <hyun.kwon@xilinx.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _ZYNQMP_DPSUB_H_
+#define _ZYNQMP_DPSUB_H_
+
+struct zynqmp_dpsub {
+	struct zynqmp_dp *dp;
+	struct zynqmp_disp *disp;
+	bool external_crtc_attached;
+	struct platform_device *master;
+};
+
+#endif /* _ZYNQMP_DPSUB_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/Kconfig
@@ -0,0 +1,8 @@
+config DRM_ZOCL
+	tristate "Xilinx Zynq OpenCL"
+	depends on DRM
+	select DRM_KMS_HELPER
+	select DRM_KMS_CMA_HELPER
+	select DRM_GEM_CMA_HELPER
+	help
+	  Xilinx Zynq OpenCL Manager
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/LICENSE
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/LICENSE
@@ -0,0 +1,481 @@
+All "zocl" Linux kernel driver code authored by Xilinx is released
+under the terms of either Apache License, Version 2.0, or alternatively
+under the terms of the GNU General Public License version 2:
+
+Copyright (C) 2016-2020 Xilinx, Inc. All rights reserved.
+
+This software is licensed under the terms of the GNU General Public
+License version 2, as published by the Free Software Foundation, and
+may be copied, distributed, and modified under those terms.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You may use the Linux kernel driver code according to either of these
+licenses as is most appropriate for your project on a case-by-case basis.
+
+The full text for both licenses is included for reference below.
+
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+---------------------------------------------------------------------------
+
+ GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/Makefile
@@ -0,0 +1,34 @@
+# SPDX-License-Identifier: GPL-2.0
+
+export XRT_DRIVER_VERSION := 2.8.0
+ccflags-y := -I $(srctree)/$(src)/include -I $(srctree)/$(src)/../include -I $(src)/include -I $(src)/../include -DXRT_HASH=\"$(GIT_HASH)\" -DXRT_HASH_DATE=\"$(GIT_HASH_DATE)\" -DXRT_BRANCH=\"$(GIT_BRANCH)\" -DXRT_MODIFIED_FILES=\"$(GIT_MODIFIED_FILES)\" -DXRT_DATE=\"$(DATE_NOW)\" -DXRT_DRIVER_VERSION=\"$(XRT_DRIVER_VERSION)\"
+
+common_dir = common
+drv_common-y   := $(common_dir)/kds_core.o \
+                  $(common_dir)/cu_hls.o \
+                  $(common_dir)/fast_adapter.o \
+                  $(common_dir)/xrt_cu.o \
+                  $(common_dir)/xrt_xclbin.o
+
+zocl-y := \
+	$(drv_common-y) \
+	sched_exec.o \
+	zocl_sysfs.o \
+	zocl_ioctl.o \
+	zocl_ert.o \
+	zocl_drv.o \
+	zocl_bo.o \
+	zocl_dma.o \
+	zocl_cu.o \
+	zocl_mailbox.o \
+	zocl_ov_sysfs.o \
+	zocl_ospi_versal.o \
+	zocl_xclbin.o \
+	zocl_sk.o \
+	zocl_kds.o \
+	cu.o \
+	zocl_generic_cu.o \
+	zocl_error.o \
+	zocl_aie.o
+
+obj-$(CONFIG_DRM_ZOCL) += zocl.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/common/cu_hls.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/common/cu_hls.c
@@ -0,0 +1,330 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * Xilinx HLS CU
+ *
+ * Copyright (C) 2020 Xilinx, Inc. All rights reserved.
+ *
+ * Authors: min.ma@xilinx.com
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#include "xrt_cu.h"
+
+/* Control register bits and special behavior if any.
+ * Bit 0: ap_start(Read/Set). Clear by CU when ap_ready assert.
+ * Bit 1: ap_done(Read only). Clear on read.
+ * Bit 2: ap_idle(Read only).
+ * Bit 3: ap_ready(Read only). Self clear after clear ap_start.
+ * Bit 4: ap_continue(Read/Set). Self clear.
+ */
+#define CTRL		0x0
+/* Global interrupt enable: Set bit 0 to enable. Clear it to disable */
+#define GIE		0x4
+/* Interrupt Enable Register
+ * Bit 0: ap_done. 0 - disable; 1 - enable.
+ * Bit 1: ap_ready. 0 - disable; 1 - enable.
+ */
+#define IER		0x8
+/* Interrupt Status Register
+ * Bit 0: ap_done(Toggle on set).
+ * Bit 1: ap_done(Toggle on set).
+ *   Toggle on set - Write 1 would flip the bit. Write 0 has no change.
+ */
+#define ISR		0xC
+#define ARGS		0x10
+
+extern int kds_echo;
+
+static inline u32 cu_read32(struct xrt_cu_hls *cu, u32 reg)
+{
+	u32 ret;
+
+	ret = ioread32(cu->vaddr + reg);
+	return ret;
+}
+
+static inline void cu_write32(struct xrt_cu_hls *cu, u32 reg, u32 val)
+{
+	iowrite32(val, cu->vaddr + reg);
+}
+
+static int cu_hls_alloc_credit(void *core)
+{
+	struct xrt_cu_hls *cu_hls = core;
+
+	return (cu_hls->credits) ? cu_hls->credits-- : 0;
+}
+
+static void cu_hls_free_credit(void *core, u32 count)
+{
+	struct xrt_cu_hls *cu_hls = core;
+
+	cu_hls->credits += count;
+	if (cu_hls->credits > cu_hls->max_credits)
+		cu_hls->credits = cu_hls->max_credits;
+}
+
+static int cu_hls_peek_credit(void *core)
+{
+	struct xrt_cu_hls *cu_hls = core;
+
+	return cu_hls->credits;
+}
+
+static void cu_hls_configure(void *core, u32 *data, size_t sz, int type)
+{
+	struct xrt_cu_hls *cu_hls = core;
+	size_t num_reg;
+	u32 i;
+
+	if (kds_echo)
+		return;
+
+	num_reg = sz / sizeof(u32);
+	for (i = 0; i < num_reg; ++i)
+		cu_write32(cu_hls, ARGS + i * 4, data[i]);
+}
+
+static void cu_hls_start(void *core)
+{
+	struct xrt_cu_hls *cu_hls = core;
+
+	cu_hls->run_cnts++;
+
+	if (kds_echo)
+		return;
+
+	cu_write32(cu_hls, CTRL, CU_AP_START);
+}
+
+/*
+ * In ap_ctrl_hs protocol, HLS CU can run one task at a time. Once CU is
+ * started, software should wait for CU done before configure/start CU again.
+ * The done bit is clear on read. So, the software just need to read control
+ * register.
+ */
+static inline void
+cu_hls_ctrl_hs_check(struct xrt_cu_hls *cu_hls, struct xcu_status *status)
+{
+	u32 ctrl_reg = 0;
+	u32 done_reg = 0;
+	u32 ready_reg = 0;
+
+	/* Avoid access CU register unless we do have running commands.
+	 * This has a huge impact on performance.
+	 */
+	if (!cu_hls->run_cnts)
+		return;
+
+	ctrl_reg = cu_read32(cu_hls, CTRL);
+	/* ap_ready and ap_done would assert at the same cycle */
+	if (ctrl_reg & CU_AP_DONE) {
+		done_reg  = 1;
+		ready_reg = 1;
+		cu_hls->run_cnts--;
+	}
+
+	status->num_done  = done_reg;
+	status->num_ready = ready_reg;
+	status->new_status = ctrl_reg;
+}
+
+/*
+ * In ap_ctrl_check protocol, HLS CU can setup next task before CU is done.
+ * After CU started, the start bit will keep high until CU assert ap_ready.
+ * Once a CU is ready, it means CU is ready to be configured.
+ * If CU is done, it means the previous task is completed. But the CU would
+ * stall until ap_continue bit is set.
+ */
+static inline void
+cu_hls_ctrl_chain_check(struct xrt_cu_hls *cu_hls, struct xcu_status *status)
+{
+	u32 ctrl_reg;
+	u32 done_reg = 0;
+	u32 ready_reg = 0;
+	u32 used_credit;
+
+	used_credit = cu_hls->max_credits - cu_hls->credits;
+
+	/* Access CU when there are unsed credits or running commands
+	 * This has a huge impact on performance.
+	 */
+	if (!used_credit && !cu_hls->run_cnts)
+		return;
+
+	ctrl_reg  = cu_read32(cu_hls, CTRL);
+
+	/* if there is submitted tasks, then check if ap_start bit is clear
+	 * See comments in cu_hls_start().
+	 */
+	if (used_credit && !(ctrl_reg & CU_AP_START))
+		ready_reg = 1;
+
+	if (ctrl_reg & CU_AP_DONE) {
+		done_reg = 1;
+		cu_hls->run_cnts--;
+		cu_write32(cu_hls, CTRL, CU_AP_CONTINUE);
+	}
+
+	status->num_done  = done_reg;
+	status->num_ready = ready_reg;
+	status->new_status = ctrl_reg;
+}
+
+static void cu_hls_check(void *core, struct xcu_status *status)
+{
+	struct xrt_cu_hls *cu_hls = core;
+
+	if (kds_echo) {
+		cu_hls->run_cnts--;
+		status->num_done = 1;
+		status->num_ready = 1;
+		status->new_status = CU_AP_IDLE;
+		return;
+	}
+
+	if (cu_hls->ctrl_chain)
+		cu_hls_ctrl_chain_check(cu_hls, status);
+	else
+		cu_hls_ctrl_hs_check(cu_hls, status);
+}
+
+static void cu_hls_enable_intr(void *core, u32 intr_type)
+{
+	struct xrt_cu_hls *cu_hls = core;
+
+	cu_write32(cu_hls, GIE, 0x1);
+	cu_write32(cu_hls, IER, intr_type);
+}
+
+static void cu_hls_disable_intr(void *core, u32 intr_type)
+{
+	struct xrt_cu_hls *cu_hls = core;
+	u32 orig = cu_read32(cu_hls, ISR);
+	/* if bit 0 of intr_type is set, it means disable ap_done,
+	 * same to bit 1 for ap_ready.
+	 */
+	u32 new = orig & (~intr_type);
+
+	cu_write32(cu_hls, GIE, 0x0);
+	cu_write32(cu_hls, IER, new);
+}
+
+static u32 cu_hls_clear_intr(void *core)
+{
+	struct xrt_cu_hls *cu_hls = core;
+
+	/* Clear all interrupts of the CU
+	 *
+	 * HLS style kernel has Interrupt Status Register at offset 0x0C
+	 * It has two interrupt bits, bit[0] is ap_done, bit[1] is ap_ready.
+	 *
+	 * The ap_done interrupt means this CU is complete.
+	 * The ap_ready interrupt means all inputs have been read.
+	 */
+	if (cu_hls->max_credits == 1) {
+		u32 isr;
+
+		/*
+		 * The old HLS adapter.
+		 *
+		 * The Interrupt Status Register is Toggle On Write
+		 * RegData = RegData ^ WriteData
+		 *
+		 * So, the reliable way to clear this register is read
+		 * then write the same value back.
+		 *
+		 * Do not write 1 to this register.  If, somehow, the
+		 * status register is 0, write 1 to this register will
+		 * trigger interrupt.
+		 */
+		isr = cu_read32(cu_hls, ISR);
+		cu_write32(cu_hls, ISR, isr);
+		return isr;
+	}
+
+	/*
+	 * The new HLS adapter with queue.
+	 *
+	 * The Interrupt Status Register is Clear on Read.
+	 *
+	 * For debug purpose, This register is toggle on write.
+	 * Write 1 to this register will trigger interrupt.
+	 */
+	return cu_read32(cu_hls, ISR);
+}
+
+static struct xcu_funcs xrt_cu_hls_funcs = {
+	.alloc_credit	= cu_hls_alloc_credit,
+	.free_credit	= cu_hls_free_credit,
+	.peek_credit	= cu_hls_peek_credit,
+	.configure	= cu_hls_configure,
+	.start		= cu_hls_start,
+	.check		= cu_hls_check,
+	.enable_intr	= cu_hls_enable_intr,
+	.disable_intr	= cu_hls_disable_intr,
+	.clear_intr	= cu_hls_clear_intr,
+};
+
+int xrt_cu_hls_init(struct xrt_cu *xcu)
+{
+	struct xrt_cu_hls *core;
+	struct resource *res;
+	size_t size;
+	int err = 0;
+
+	core = kzalloc(sizeof(struct xrt_cu_hls), GFP_KERNEL);
+	if (!core) {
+		err = -ENOMEM;
+		goto err;
+	}
+
+	/* map CU register */
+	/* TODO: add comment why uses res[0] */
+	res = xcu->res[0];
+	size = res->end - res->start + 1;
+	core->vaddr = ioremap_nocache(res->start, size);
+	if (!core->vaddr) {
+		err = -ENOMEM;
+		xcu_err(xcu, "Map CU register failed");
+		goto err;
+	}
+
+	core->max_credits = 1;
+	core->credits = core->max_credits;
+	core->run_cnts = 0;
+	core->ctrl_chain = (xcu->info.protocol == CTRL_CHAIN)? true : false;
+
+	xcu->status = cu_read32(core, CTRL);
+	xcu->core = core;
+	xcu->funcs = &xrt_cu_hls_funcs;
+
+	xcu->busy_threshold = -1;
+	xcu->interval_min = 2;
+	xcu->interval_max = 5;
+
+	err = xrt_cu_init(xcu);
+	if (err)
+		return err;
+
+	return 0;
+
+err:
+	kfree(core);
+	return err;
+}
+
+void xrt_cu_hls_fini(struct xrt_cu *xcu)
+{
+	struct xrt_cu_hls *core = xcu->core;
+
+	xrt_cu_fini(xcu);
+
+	if (xcu->core) {
+		if (core->vaddr)
+			iounmap(core->vaddr);
+		kfree(xcu->core);
+	}
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/common/cu_plram.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/common/cu_plram.c
@@ -0,0 +1,179 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * Xilinx PLRAM Queue Based CU
+ *
+ * Copyright (C) 2020 Xilinx, Inc. All rights reserved.
+ *
+ * Authors: min.ma@xilinx.com
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#include "xrt_cu.h"
+
+extern int kds_echo;
+
+static int cu_plram_alloc_credit(void *core)
+{
+	struct xrt_cu_plram *cu_plram = core;
+
+	return (cu_plram->credits) ? cu_plram->credits-- : 0;
+}
+
+static void cu_plram_free_credit(void *core, u32 count)
+{
+	struct xrt_cu_plram *cu_plram = core;
+
+	cu_plram->credits += count;
+	if (cu_plram->credits > cu_plram->max_credits)
+		cu_plram->credits = cu_plram->max_credits;
+}
+
+static int cu_plram_peek_credit(void *core)
+{
+	struct xrt_cu_plram *cu_plram = core;
+
+	return cu_plram->credits;
+}
+
+static void cu_plram_configure(void *core, u32 *data, size_t sz, int type)
+{
+	struct xrt_cu_plram *cu_plram = core;
+
+	if (kds_echo)
+		return;
+
+	/* TODO: Configure in specific slot */
+	memcpy(cu_plram->plram, data, sz);
+}
+
+static void cu_plram_start(void *core)
+{
+	struct xrt_cu_plram *cu_plram = core;
+
+	if (kds_echo)
+		return;
+
+	/* TODO: Start CU in specific slot */
+	iowrite32(0x0, cu_plram->vaddr + 0x10);
+}
+
+static void cu_plram_check(void *core, struct xcu_status *status)
+{
+	struct xrt_cu_plram *cu_plram = core;
+	u32 done_reg = 0;
+
+	if (kds_echo) {
+		done_reg = 1;
+		goto out;
+	}
+
+	/* There is only one done commands counter in the plram CU
+	 * It tells how many commands are done and how many FIFO slots
+	 * are ready for more commands.
+	 *
+	 * ioread32 is expensive! If no credits are taken(CU is not running),
+	 * DO NOT read done register.
+	 */
+	if (cu_plram->credits != cu_plram->max_credits)
+		done_reg = ioread32(cu_plram->vaddr + 0x1C);
+out:
+	status->num_done = done_reg;
+	status->num_ready = done_reg;
+}
+
+static struct xcu_funcs xrt_cu_plram_funcs = {
+	.alloc_credit	= cu_plram_alloc_credit,
+	.free_credit	= cu_plram_free_credit,
+	.peek_credit	= cu_plram_peek_credit,
+	.configure	= cu_plram_configure,
+	.start		= cu_plram_start,
+	.check		= cu_plram_check,
+};
+
+int xrt_cu_plram_init(struct xrt_cu *xcu)
+{
+	struct xrt_cu_plram *core;
+	struct xrt_cu_info *info = &xcu->info;
+	struct resource *res;
+	size_t size;
+	u32 val;
+	int err = 0;
+
+	if (info->num_res != 2) {
+		xcu_err(xcu, "2 resources are required");
+		return -EINVAL;
+	}
+
+	core = kzalloc(sizeof(struct xrt_cu_plram), GFP_KERNEL);
+	if (!core)
+		return -ENOMEM;
+
+	/* map CU register */
+	res = xcu->res[0];
+	size = res->end - res->start + 1;
+	core->vaddr = ioremap_nocache(res->start, size);
+	if (!core->vaddr) {
+		err = -ENOMEM;
+		xcu_err(xcu, "Map CU register failed");
+		goto err;
+	}
+
+	/* NOTE: Dummy read needed on kernel 0x18 and 0x1c register because
+	 * of some bug in kernel, first read will give some garbage data
+	 */
+	val = ioread32(core->vaddr + 0x1C);
+	val = ioread32(core->vaddr + 0x18);
+
+	val = ioread32(core->vaddr + 0x1C);
+	val = ioread32(core->vaddr + 0x18);
+	xcu_info(xcu, "FIFO depth 0x%x", val);
+	core->max_credits = val;
+	core->credits = core->max_credits;
+
+	/* Set plram base address, this is hard coding */
+	iowrite32(0x00, core->vaddr + 0x20);
+	iowrite32(0x41, core->vaddr + 0x24);
+
+	/* map plram */
+	res = xcu->res[1];
+	size = res->end - res->start + 1;
+	/* use wc would make huge different on IOPS */
+	//core->plram = ioremap_nocache(res->start, size);
+	core->plram = ioremap_wc(res->start, size);
+	if (!core->plram) {
+		err = -ENOMEM;
+		xcu_err(xcu, "Map CU arguments RAM failed");
+		goto err1;
+	}
+
+	xcu->core = core;
+	xcu->funcs = &xrt_cu_plram_funcs;
+
+	err = xrt_cu_init(xcu);
+	if (err)
+		return err;
+
+	return 0;
+err1:
+	iounmap(core->vaddr);
+err:
+	kfree(core);
+	return err;
+}
+
+void xrt_cu_plram_fini(struct xrt_cu *xcu)
+{
+	struct xrt_cu_plram *core = xcu->core;
+
+	if (xcu->core) {
+		if (core->vaddr)
+			iounmap(core->vaddr);
+		if (core->plram)
+			iounmap(core->plram);
+		kfree(xcu->core);
+	}
+
+	xrt_cu_fini(xcu);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/common/fast_adapter.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/common/fast_adapter.c
@@ -0,0 +1,265 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * Xilinx CU with fast adapter.
+ *
+ * Copyright (C) 2020 Xilinx, Inc. All rights reserved.
+ *
+ * Authors: min.ma@xilinx.com
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#include "xrt_cu.h"
+
+/* Fast Adapter register layout
+ * nextDescriptorAddr_MSW: Most significant word of paddr of descriptor
+ * nextDescriptorAddr_LSW: Least significant word of paddr of descriptor
+ * interruptStatus: Interrupt status register
+ * Status: Flagging error conditions, e.g. FIFO overrun
+ * taskCount: Task Counter that tracks how many tasks have been processed
+ * currentDescriptorAddr: Address of descriptor currently being processed by CU
+ * fifoDepth: Current adapter FIFO depth
+ */
+#define MSWR		0x0
+#define LSWR		0x4
+#define ISR		0x8
+#define IER		0xC
+#define SR		0x10
+#define TCR		0x14
+#define CDAR		0x18
+#define FDR		0x1C
+
+extern int kds_echo;
+
+static inline u32 cu_read32(struct xrt_cu_fa *cu, u32 reg)
+{
+	u32 ret;
+
+	ret = ioread32(cu->vaddr + reg);
+	return ret;
+}
+
+static inline void cu_write32(struct xrt_cu_fa *cu, u32 reg, u32 val)
+{
+	iowrite32(val, cu->vaddr + reg);
+}
+
+static int cu_fa_alloc_credit(void *core)
+{
+	struct xrt_cu_fa *cu_fa = core;
+
+	return (cu_fa->credits) ? cu_fa->credits-- : 0;
+}
+
+static void cu_fa_free_credit(void *core, u32 count)
+{
+	struct xrt_cu_fa *cu_fa = core;
+	int max_credits;
+
+	cu_fa->credits += count;
+
+	max_credits = (cu_fa->num_slots < cu_fa->max_credits)?
+		       cu_fa->num_slots : cu_fa->max_credits;
+
+	if (cu_fa->credits > max_credits)
+		cu_fa->credits = max_credits;
+}
+
+static int cu_fa_peek_credit(void *core)
+{
+	struct xrt_cu_fa *cu_fa = core;
+
+	return cu_fa->credits;
+}
+
+static void cu_fa_configure(void *core, u32 *data, size_t sz, int type)
+{
+	struct xrt_cu_fa *cu_fa = core;
+	u32 *slot = cu_fa->plram + cu_fa->head_slot;
+
+	/* avoid plram is not update properly */
+	WARN_ON(!cu_fa->plram);
+
+	if (kds_echo || !cu_fa->plram)
+		return;
+
+	/* move commands to device quickly is the key of performance */
+	memcpy(&slot[1], &data[1], sz - 4);
+
+	/* Update status of descriptor */
+	wmb();
+	slot[0] = data[0];
+}
+
+static void cu_fa_start(void *core)
+{
+	struct xrt_cu_fa *cu_fa = core;
+	u32 desc_msw = cu_fa->paddr >> 32;
+	u32 desc_lsw = (u32)cu_fa->paddr;
+
+	cu_fa->run_cnts++;
+
+	if (kds_echo || !cu_fa->plram)
+		return;
+
+	/* The MSW of descriptor is fixed */
+	if (desc_msw != cu_fa->desc_msw) {
+		cu_write32(cu_fa, MSWR, desc_msw);
+		cu_fa->desc_msw = desc_msw;
+	}
+
+	/* Write LSW would kick off CU */
+	cu_write32(cu_fa, LSWR, desc_lsw + cu_fa->head_slot);
+
+	/* move to next descriptor slot */
+	cu_fa->head_slot += cu_fa->slot_sz;
+	if (cu_fa->head_slot == cu_fa->slot_sz * cu_fa->num_slots)
+		cu_fa->head_slot = 0;
+}
+
+static void cu_fa_check(void *core, struct xcu_status *status)
+{
+	struct xrt_cu_fa *cu_fa = core;
+	u32 task_count;
+	u32 done = 0;
+
+	if (kds_echo || !cu_fa->plram) {
+		cu_fa->run_cnts--;
+		status->num_done = 1;
+		status->num_ready = 1;
+		return;
+	}
+
+	/* Avoid access CU register unless we do have running commands.
+	 * This has a huge impact on performance.
+	 */
+	if (!cu_fa->run_cnts)
+		return;
+
+	cu_fa->check_count++;
+	task_count = cu_read32(cu_fa, TCR);
+	/* If taskCount register overflow once, below calculate is still correct.
+	 * Only when the register overflow more than once, this is wrong.
+	 * But this should never be the case.
+	 */
+	done = task_count - cu_fa->task_cnt;
+	cu_fa->task_cnt = task_count;
+
+	cu_fa->run_cnts -= done;
+
+	status->num_done  = done;
+	status->num_ready = done;
+}
+
+static void cu_fa_enable_intr(void *core, u32 intr_type)
+{
+	return;
+}
+
+static void cu_fa_disable_intr(void *core, u32 intr_type)
+{
+	return;
+}
+
+static u32 cu_fa_clear_intr(void *core)
+{
+	return 0;
+}
+
+static struct xcu_funcs xrt_cu_fa_funcs = {
+	.alloc_credit	= cu_fa_alloc_credit,
+	.free_credit	= cu_fa_free_credit,
+	.peek_credit	= cu_fa_peek_credit,
+	.configure	= cu_fa_configure,
+	.start		= cu_fa_start,
+	.check		= cu_fa_check,
+	.enable_intr	= cu_fa_enable_intr,
+	.disable_intr	= cu_fa_disable_intr,
+	.clear_intr	= cu_fa_clear_intr,
+};
+
+int xrt_cu_fa_init(struct xrt_cu *xcu)
+{
+	struct xrt_cu_fa *core;
+	struct resource *res;
+	size_t size;
+	int err = 0;
+
+	core = kzalloc(sizeof(struct xrt_cu_fa), GFP_KERNEL);
+	if (!core) {
+		err = -ENOMEM;
+		goto err;
+	}
+
+	/* map CU register */
+	res = xcu->res[0];
+	size = res->end - res->start + 1;
+	core->vaddr = ioremap_nocache(res->start, size);
+	if (!core->vaddr) {
+		err = -ENOMEM;
+		xcu_err(xcu, "Map CU register failed");
+		goto err;
+	}
+
+	/* TODO:
+	 * Looks like it would read wrong value from a just downloaded
+	 * fast adapter. This is a hardware bug.
+	 * We could write 0x0 to Status Register (read only) to workaround
+	 * this issue.
+	 * But, read any register doesn't always work.
+	 * Please do not remove below line until it is fixed on hardware.
+	 */
+	cu_write32(core, SR, 0x0);
+	core->max_credits = cu_read32(core, FDR);
+	core->task_cnt = cu_read32(core, TCR);
+	core->desc_msw = cu_read32(core, MSWR);
+	xcu_info(xcu, "Fast adapter FIFO depth %d", core->max_credits);
+	xcu_info(xcu, "Fast adapter init taskCount 0x%x", core->task_cnt);
+	core->credits = core->max_credits;
+	core->run_cnts = 0;
+
+	/* TODO:
+	 * Maybe in the future, we could initial all of the CU resource at this
+	 * place. Now, this is just to note that below variables will initial
+	 * when xclbin download finished and kds get update.
+	 *   core->plram
+	 *   core->paddr
+	 *   core->head_slot
+	 *   core->num_slots
+	 */
+
+	xcu->core = core;
+	xcu->funcs = &xrt_cu_fa_funcs;
+	/* Not sure what is the best initial value.
+	 * But below parameters are configurable to user. No worry.
+	 */
+	xcu->busy_threshold = core->max_credits / 2;
+	xcu->interval_min = 2;
+	xcu->interval_max = 5;
+
+	err = xrt_cu_init(xcu);
+	if (err)
+		return err;
+
+	return 0;
+
+err:
+	kfree(core);
+	return err;
+}
+
+void xrt_cu_fa_fini(struct xrt_cu *xcu)
+{
+	struct xrt_cu_fa *core = xcu->core;
+
+	xrt_cu_fini(xcu);
+
+	if (xcu->core) {
+		if (core->vaddr)
+			iounmap(core->vaddr);
+		if (core->plram)
+			iounmap(core->plram);
+		kfree(xcu->core);
+	}
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/common/kds_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/common/kds_core.c
@@ -0,0 +1,1008 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * Xilinx Kernel Driver Scheduler
+ *
+ * Copyright (C) 2020 Xilinx, Inc. All rights reserved.
+ *
+ * Authors: min.ma@xilinx.com
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/vmalloc.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include "kds_core.h"
+
+/* for sysfs */
+int store_kds_echo(struct kds_sched *kds, const char *buf, size_t count,
+		   int kds_mode, u32 clients, int *echo)
+{
+	u32 enable;
+	u32 live_clients;
+
+	if (kds)
+		live_clients = kds_live_clients(kds, NULL);
+	else
+		live_clients = clients;
+
+	/* Ideally, KDS should be locked to reject new client.
+	 * But, this node is hidden for internal test purpose.
+	 * Let's refine it after new KDS is the default and
+	 * user is allow to configure it through xbutil.
+	 */
+	if (live_clients > 0)
+		return -EBUSY;
+
+	if (kstrtou32(buf, 10, &enable) == -EINVAL || enable > 1)
+		return -EINVAL;
+
+	*echo = enable;
+
+	return count;
+}
+
+/* Each line is a CU, format:
+ * "cu_idx kernel_name:cu_name address status usage"
+ */
+ssize_t show_kds_custat_raw(struct kds_sched *kds, char *buf)
+{
+	struct kds_cu_mgmt *cu_mgmt = &kds->cu_mgmt;
+	struct xrt_cu *xcu = NULL;
+	char *cu_fmt = "%d,%s:%s,0x%llx,0x%x,%llu\n";
+	ssize_t sz = 0;
+	int i;
+
+	mutex_lock(&cu_mgmt->lock);
+	for (i = 0; i < cu_mgmt->num_cus; ++i) {
+		xcu = cu_mgmt->xcus[i];
+		sz += scnprintf(buf+sz, PAGE_SIZE - sz, cu_fmt, i,
+				xcu->info.kname, xcu->info.iname,
+				xcu->info.addr, xcu->status,
+				cu_mgmt->cu_usage[i]);
+	}
+	mutex_unlock(&cu_mgmt->lock);
+
+	if (sz < PAGE_SIZE - 1)
+		buf[sz++] = 0;
+	else
+		buf[PAGE_SIZE - 1] = 0;
+
+	return sz;
+}
+
+ssize_t show_kds_stat(struct kds_sched *kds, char *buf)
+{
+	struct kds_cu_mgmt *cu_mgmt = &kds->cu_mgmt;
+	char *cu_fmt = "  CU[%d] usage(%llu) shared(%d) refcnt(%d) intr(%s)\n";
+	ssize_t sz = 0;
+	bool shared;
+	int ref;
+	int i;
+
+	mutex_lock(&cu_mgmt->lock);
+	sz += scnprintf(buf+sz, PAGE_SIZE - sz,
+			"CU to host interrupt capability: %d\n",
+			kds->cu_intr_cap);
+	sz += scnprintf(buf+sz, PAGE_SIZE - sz, "Interrupt mode: %s\n",
+			(kds->cu_intr)? "cu" : "ert");
+	sz += scnprintf(buf+sz, PAGE_SIZE - sz, "Configured: %d\n",
+			cu_mgmt->configured);
+	sz += scnprintf(buf+sz, PAGE_SIZE - sz, "Number of CUs: %d\n",
+			cu_mgmt->num_cus);
+	for (i = 0; i < cu_mgmt->num_cus; ++i) {
+		shared = !(cu_mgmt->cu_refs[i] & CU_EXCLU_MASK);
+		ref = cu_mgmt->cu_refs[i] & ~CU_EXCLU_MASK;
+		sz += scnprintf(buf+sz, PAGE_SIZE - sz, cu_fmt,
+				i, cu_mgmt->cu_usage[i], shared, ref,
+				(cu_mgmt->cu_intr[i])? "enable" : "disable");
+	}
+	mutex_unlock(&cu_mgmt->lock);
+
+	if (sz < PAGE_SIZE - 1)
+		buf[sz++] = 0;
+	else
+		buf[PAGE_SIZE - 1] = 0;
+
+	return sz;
+}
+/* sysfs end */
+
+/**
+ * get_cu_by_addr -Get CU index by address
+ *
+ * @cu_mgmt: KDS CU management struct
+ * @addr: The address of the target CU
+ *
+ * Returns CU index if found. Returns an out of range number if not found.
+ */
+static __attribute__((unused)) int
+get_cu_by_addr(struct kds_cu_mgmt *cu_mgmt, u32 addr)
+{
+	int i;
+
+	/* Do not use this search in critical path */
+	for (i = 0; i < cu_mgmt->num_cus; ++i) {
+		if (cu_mgmt->xcus[i]->info.addr == addr)
+			break;
+	}
+
+	return i;
+}
+
+static int
+kds_cu_config(struct kds_cu_mgmt *cu_mgmt, struct kds_command *xcmd)
+{
+	struct kds_client *client = xcmd->client;
+	int ret = 0;
+
+	/* This is no-op. The new KDS doesn't need configure command.
+	 * But ERT 2.0 flow still need configure command.
+	 *
+	 * KDS could construct ERT configure command but not sure when.
+	 * Before figure this out, keep this function.
+	 */
+	mutex_lock(&cu_mgmt->lock);
+
+	if (cu_mgmt->configured) {
+		kds_info(client, "CU already configured in KDS\n");
+		goto out;
+	}
+
+	cu_mgmt->configured = 1;
+
+out:
+	mutex_unlock(&cu_mgmt->lock);
+	return ret;
+}
+
+/**
+ * acquire_cu_idx - Get ready CU index
+ *
+ * @xcmd: Command
+ *
+ * Returns: Negative value for error. 0 or positive value for index
+ *
+ */
+static int
+acquire_cu_idx(struct kds_cu_mgmt *cu_mgmt, struct kds_command *xcmd)
+{
+	struct kds_client *client = xcmd->client;
+	/* User marked CUs */
+	uint8_t user_cus[MAX_CUS];
+	int num_marked;
+	/* After validation */
+	uint8_t valid_cus[MAX_CUS];
+	int num_valid = 0;
+	uint8_t index;
+	int i;
+
+	num_marked = cu_mask_to_cu_idx(xcmd, user_cus);
+	if (unlikely(num_marked > cu_mgmt->num_cus)) {
+		kds_err(client, "Too many CUs in CU mask");
+		return -EINVAL;
+	}
+
+	/* Check if CU is added in the context */
+	for (i = 0; i < num_marked; ++i) {
+		if (test_bit(user_cus[i], client->cu_bitmap)) {
+			valid_cus[num_valid] = user_cus[i];
+			++num_valid;
+		}
+	}
+
+	if (num_valid == 1) {
+		index = valid_cus[0];
+		mutex_lock(&cu_mgmt->lock);
+		goto out;
+	} else if (num_valid == 0) {
+		kds_err(client, "All CUs in mask are out of context");
+		return -EINVAL;
+	}
+
+	/* There are more than one valid candidate
+	 * TODO: test if the lock impact the performance on multi processes
+	 */
+	mutex_lock(&cu_mgmt->lock);
+	for (i = 1, index = valid_cus[0]; i < num_valid; ++i) {
+		if (cu_mgmt->cu_usage[valid_cus[i]] < cu_mgmt->cu_usage[index])
+			index = valid_cus[i];
+	}
+
+out:
+	++cu_mgmt->cu_usage[index];
+	mutex_unlock(&cu_mgmt->lock);
+	return index;
+}
+
+static int
+kds_cu_dispatch(struct kds_cu_mgmt *cu_mgmt, struct kds_command *xcmd)
+{
+	int cu_idx;
+
+	cu_idx = acquire_cu_idx(cu_mgmt, xcmd);
+	if (cu_idx < 0)
+		return cu_idx;
+
+	xrt_cu_submit(cu_mgmt->xcus[cu_idx], xcmd);
+	return 0;
+}
+
+static int
+kds_submit_cu(struct kds_cu_mgmt *cu_mgmt, struct kds_command *xcmd)
+{
+	int ret = 0;
+
+	if (xcmd->opcode != OP_CONFIG)
+		ret = kds_cu_dispatch(cu_mgmt, xcmd);
+	else {
+		ret = kds_cu_config(cu_mgmt, xcmd);
+		if (ret == 0) {
+			xcmd->cb.notify_host(xcmd, KDS_COMPLETED);
+			xcmd->cb.free(xcmd);
+		}
+	}
+
+	return ret;
+}
+
+static int
+kds_submit_ert(struct kds_sched *kds, struct kds_command *xcmd)
+{
+	struct kds_ert *ert = kds->ert;
+	int ret = 0;
+	int cu_idx;
+
+	/* BUG_ON(!ert || !ert->submit); */
+
+	if (xcmd->opcode == OP_START) {
+		/* KDS should select a CU and set it in cu_mask */
+		cu_idx = acquire_cu_idx(&kds->cu_mgmt, xcmd);
+		if (cu_idx < 0)
+			return cu_idx;
+		xcmd->cu_idx = cu_idx;
+	} else {
+		/* Configure command define CU index */
+		ret = kds_cu_config(&kds->cu_mgmt, xcmd);
+		if (ret)
+			return ret;
+	}
+
+	ert->submit(ert, xcmd);
+	return 0;
+}
+
+static int
+kds_add_cu_context(struct kds_sched *kds, struct kds_client *client,
+		   struct kds_ctx_info *info)
+{
+	struct kds_cu_mgmt *cu_mgmt = &kds->cu_mgmt;
+	int cu_idx = info->cu_idx;
+	u32 prop;
+	bool shared;
+	int ret = 0;
+
+	if (cu_idx >= cu_mgmt->num_cus) {
+		kds_err(client, "CU(%d) not found", cu_idx);
+		return -EINVAL;
+	}
+
+	if (test_and_set_bit(cu_idx, client->cu_bitmap)) {
+		kds_err(client, "CU(%d) has been added", cu_idx);
+		return -EINVAL;
+	}
+
+	prop = info->flags & CU_CTX_PROP_MASK;
+	shared = (prop != CU_CTX_EXCLUSIVE);
+
+	/* cu_mgmt->cu_refs is the critical section of multiple clients */
+	mutex_lock(&cu_mgmt->lock);
+	/* Must check exclusive bit is set first */
+	if (cu_mgmt->cu_refs[cu_idx] & CU_EXCLU_MASK) {
+		kds_err(client, "CU(%d) has been exclusively reserved", cu_idx);
+		ret = -EBUSY;
+		goto err;
+	}
+
+	/* Not allow exclusively reserved if CU is shared */
+	if (!shared && cu_mgmt->cu_refs[cu_idx]) {
+		kds_err(client, "CU(%d) has been shared", cu_idx);
+		ret = -EBUSY;
+		goto err;
+	}
+
+	/* CU is not shared and not exclusively reserved */
+	if (!shared)
+		cu_mgmt->cu_refs[cu_idx] |= CU_EXCLU_MASK;
+	else
+		++cu_mgmt->cu_refs[cu_idx];
+	mutex_unlock(&cu_mgmt->lock);
+
+	return 0;
+err:
+	mutex_unlock(&cu_mgmt->lock);
+	clear_bit(cu_idx, client->cu_bitmap);
+	return ret;
+}
+
+static int
+kds_del_cu_context(struct kds_sched *kds, struct kds_client *client,
+		   struct kds_ctx_info *info)
+{
+	struct kds_cu_mgmt *cu_mgmt = &kds->cu_mgmt;
+	int cu_idx = info->cu_idx;
+	int state;
+
+	if (cu_idx >= cu_mgmt->num_cus) {
+		kds_err(client, "CU(%d) not found", cu_idx);
+		return -EINVAL;
+	}
+
+	if (!test_and_clear_bit(cu_idx, client->cu_bitmap)) {
+		kds_err(client, "CU(%d) has never been reserved", cu_idx);
+		return -EINVAL;
+	}
+
+	/* TODO: finish ERT abort process later */
+	if (!kds->ert_disable)
+		goto skip;
+
+	/* Before close, make sure no remain commands in CU's queue.
+	 * There is no reason to sleep 500ms :)
+	 */
+	while (xrt_cu_abort(cu_mgmt->xcus[cu_idx], client) == -EAGAIN)
+		msleep(500);
+
+	do {
+		msleep(100);
+		state = xrt_cu_abort_done(cu_mgmt->xcus[cu_idx]);
+	} while (!state);
+
+	if (state == CU_STATE_BAD) {
+		kds_info(client, "CU(%d) hangs, please reset device", cu_idx);
+		/* No lock to protect bad_state.
+		 * If a new client doesn't get the updated status and send commands,
+		 * those commands would failed with TIMEOUT state.
+		 */
+		kds->bad_state = 1;
+		xrt_cu_set_bad_state(cu_mgmt->xcus[cu_idx]);
+	}
+
+skip:
+	/* cu_mgmt->cu_refs is the critical section of multiple clients */
+	mutex_lock(&cu_mgmt->lock);
+	if (cu_mgmt->cu_refs[cu_idx] & CU_EXCLU_MASK)
+		cu_mgmt->cu_refs[cu_idx] = 0;
+	else
+		--cu_mgmt->cu_refs[cu_idx];
+	mutex_unlock(&cu_mgmt->lock);
+
+	return 0;
+}
+
+int kds_init_sched(struct kds_sched *kds)
+{
+	INIT_LIST_HEAD(&kds->clients);
+	mutex_init(&kds->lock);
+	mutex_init(&kds->cu_mgmt.lock);
+	kds->num_client = 0;
+	kds->bad_state = 0;
+	/* At this point, I don't know if ERT subdev exist or not */
+	kds->ert_disable = true;
+	kds->ini_disable = false;
+
+	return 0;
+}
+
+void kds_fini_sched(struct kds_sched *kds)
+{
+	mutex_destroy(&kds->lock);
+	mutex_destroy(&kds->cu_mgmt.lock);
+}
+
+struct kds_command *kds_alloc_command(struct kds_client *client, u32 size)
+{
+#if PRE_ALLOC
+	struct kds_command *xcmds;
+#endif
+	struct kds_command *xcmd;
+
+	/* TODO: Allocate buffer on critical path is not good
+	 * Consider kmem_cache_alloc()
+	 */
+#if PRE_ALLOC
+	xcmds = client->xcmds;
+	xcmd = &xcmds[client->xcmd_idx];
+#else
+	xcmd = kzalloc(sizeof(struct kds_command), GFP_KERNEL);
+	if (!xcmd)
+		return NULL;
+#endif
+
+	xcmd->client = client;
+	xcmd->type = 0;
+
+#if PRE_ALLOC
+	xcmd->info = client->infos + sizeof(u32) * 128;
+	++client->xcmd_idx;
+	client->xcmd_idx &= (client->max_xcmd - 1);
+#else
+	xcmd->info = kzalloc(size, GFP_KERNEL);
+	if (!xcmd->info) {
+		kfree(xcmd);
+		return NULL;
+	}
+#endif
+
+	return xcmd;
+}
+
+void kds_free_command(struct kds_command *xcmd)
+{
+#if PRE_ALLOC
+	return;
+#else
+	if (xcmd) {
+		kfree(xcmd->info);
+		kfree(xcmd);
+		xcmd = NULL;
+	}
+#endif
+}
+
+int kds_add_command(struct kds_sched *kds, struct kds_command *xcmd)
+{
+	struct kds_client *client = xcmd->client;
+	int err = 0;
+
+	BUG_ON(!xcmd->cb.notify_host);
+	BUG_ON(!xcmd->cb.free);
+
+	/* TODO: Check if command is blocked */
+
+	/* Command is good to submit */
+	switch (xcmd->type) {
+	case KDS_CU:
+		err = kds_submit_cu(&kds->cu_mgmt, xcmd);
+		break;
+	case KDS_ERT:
+		err = kds_submit_ert(kds, xcmd);
+		break;
+	default:
+		kds_err(client, "Unknown type");
+		err = -EINVAL;
+	}
+
+	if (err) {
+		xcmd->cb.notify_host(xcmd, KDS_ERROR);
+		xcmd->cb.free(xcmd);
+	}
+	return err;
+}
+
+int kds_init_client(struct kds_sched *kds, struct kds_client *client)
+{
+	client->pid = get_pid(task_pid(current));
+	mutex_init(&client->lock);
+
+	init_waitqueue_head(&client->waitq);
+	atomic_set(&client->event, 0);
+
+	mutex_lock(&kds->lock);
+	list_add_tail(&client->link, &kds->clients);
+	kds->num_client++;
+	mutex_unlock(&kds->lock);
+
+#if PRE_ALLOC
+	client->max_xcmd = 0x8000;
+	client->xcmd_idx = 0;
+	client->xcmds = vzalloc(sizeof(struct kds_command) * client->max_xcmd);
+	if (!client->xcmds) {
+		kds_err(client, "cound not allocate xcmds");
+		return -ENOMEM;
+	}
+	client->infos = vzalloc(sizeof(u32) * 128 * client->max_xcmd);
+	if (!client->infos) {
+		kds_err(client, "cound not allocate infos");
+		return -ENOMEM;
+	}
+#endif
+
+	return 0;
+}
+
+static inline void
+_kds_fini_client(struct kds_sched *kds, struct kds_client *client)
+{
+	struct kds_ctx_info info;
+	u32 bit;
+
+	kds_info(client, "Client pid(%d) has %d opening context",
+		 pid_nr(client->pid), client->num_ctx);
+
+	mutex_lock(&client->lock);
+	while (client->virt_cu_ref) {
+		info.cu_idx = CU_CTX_VIRT_CU;
+		kds_del_context(kds, client, &info);
+	}
+
+	bit = find_first_bit(client->cu_bitmap, MAX_CUS);
+	while (bit < MAX_CUS) {
+		info.cu_idx = bit;
+		kds_del_context(kds, client, &info);
+		bit = find_next_bit(client->cu_bitmap, MAX_CUS, bit + 1);
+	};
+	bitmap_zero(client->cu_bitmap, MAX_CUS);
+	mutex_unlock(&client->lock);
+
+	WARN_ON(client->num_ctx);
+}
+
+void kds_fini_client(struct kds_sched *kds, struct kds_client *client)
+{
+#if PRE_ALLOC
+	vfree(client->xcmds);
+	vfree(client->infos);
+#endif
+
+	/* Release client's resources */
+	if (client->num_ctx)
+		_kds_fini_client(kds, client);
+
+	put_pid(client->pid);
+	mutex_destroy(&client->lock);
+
+	mutex_lock(&kds->lock);
+	list_del(&client->link);
+	kds->num_client--;
+	if (!kds->num_client)
+		kds->cu_mgmt.configured = 0;
+	mutex_unlock(&kds->lock);
+}
+
+int kds_add_context(struct kds_sched *kds, struct kds_client *client,
+		    struct kds_ctx_info *info)
+{
+	u32 cu_idx = info->cu_idx;
+	bool shared = (info->flags != CU_CTX_EXCLUSIVE);
+	int i;
+
+	BUG_ON(!mutex_is_locked(&client->lock));
+
+	/* TODO: In lagcy KDS, there is a concept of implicit CUs.
+	 * It looks like that part is related to cdma. But it use the same
+	 * cu bit map and it relies on to how user open context.
+	 * Let's consider that kind of CUs later.
+	 */
+	if (cu_idx == CU_CTX_VIRT_CU) {
+		if (!shared) {
+			kds_err(client, "Only allow share virtual CU");
+			return -EINVAL;
+		}
+		/* a special handling for m2m cu :( */
+		if (kds->cu_mgmt.num_cdma && !client->virt_cu_ref) {
+			i = kds->cu_mgmt.num_cus - kds->cu_mgmt.num_cdma;
+			test_and_set_bit(i, client->cu_bitmap);
+			mutex_lock(&kds->cu_mgmt.lock);
+			++kds->cu_mgmt.cu_refs[i];
+			mutex_unlock(&kds->cu_mgmt.lock);
+		}
+		++client->virt_cu_ref;
+	} else {
+		if (kds_add_cu_context(kds, client, info))
+			return -EINVAL;
+	}
+
+	++client->num_ctx;
+	kds_info(client, "Client pid(%d) add context CU(0x%x) shared(%s)",
+		 pid_nr(client->pid), cu_idx, shared? "true" : "false");
+	return 0;
+}
+
+int kds_del_context(struct kds_sched *kds, struct kds_client *client,
+		    struct kds_ctx_info *info)
+{
+	u32 cu_idx = info->cu_idx;
+	int i;
+
+	BUG_ON(!mutex_is_locked(&client->lock));
+
+	if (cu_idx == CU_CTX_VIRT_CU) {
+		if (!client->virt_cu_ref) {
+			kds_err(client, "No opening virtual CU");
+			return -EINVAL;
+		}
+		--client->virt_cu_ref;
+		/* a special handling for m2m cu :( */
+		if (kds->cu_mgmt.num_cdma && !client->virt_cu_ref) {
+			i = kds->cu_mgmt.num_cus - kds->cu_mgmt.num_cdma;
+			if (!test_and_clear_bit(i, client->cu_bitmap)) {
+				kds_err(client, "never reserved cmda");
+				return -EINVAL;
+			}
+			mutex_lock(&kds->cu_mgmt.lock);
+			--kds->cu_mgmt.cu_refs[i];
+			mutex_unlock(&kds->cu_mgmt.lock);
+		}
+	} else {
+		if (kds_del_cu_context(kds, client, info))
+			return -EINVAL;
+	}
+
+	--client->num_ctx;
+	kds_info(client, "Client pid(%d) del context CU(0x%x)",
+		 pid_nr(client->pid), cu_idx);
+	return 0;
+}
+
+static inline void
+insert_cu(struct kds_cu_mgmt *cu_mgmt, int i, struct xrt_cu *xcu)
+{
+	cu_mgmt->xcus[i] = xcu;
+	xcu->info.cu_idx = i;
+	/* m2m cu */
+	if (xcu->info.intr_id == M2M_CU_ID)
+		cu_mgmt->num_cdma++;
+}
+
+int kds_add_cu(struct kds_sched *kds, struct xrt_cu *xcu)
+{
+	struct kds_cu_mgmt *cu_mgmt = &kds->cu_mgmt;
+	struct xrt_cu *prev_cu;
+	int i;
+
+	if (cu_mgmt->num_cus >= MAX_CUS)
+		return -ENOMEM;
+
+	/* Determin CUs ordering:
+	 * Sort CU in interrupt ID increase order.
+	 * If interrupt ID is the same, sort CU in address
+	 * increase order.
+	 * This strategy is good for both legacy xclbin and latest xclbin.
+	 *
+	 * - For legacy xclbin, all of the interrupt IDs are 0. The
+	 * interrupt is wiring by CU address increase order.
+	 * - For latest xclbin, the interrupt ID is from 0 ~ 127.
+	 *   -- One exception is if only 1 CU, the interrupt ID would be 1.
+	 *
+	 * Do NOT add code in KDS to check if xclbin is legacy. We don't
+	 * want to coupling KDS and xclbin parsing.
+	 */
+	if (cu_mgmt->num_cus == 0) {
+		insert_cu(cu_mgmt, 0, xcu);
+		++cu_mgmt->num_cus;
+		return 0;
+	}
+
+	/* Insertion sort */
+	for (i = cu_mgmt->num_cus; i > 0; i--) {
+		prev_cu = cu_mgmt->xcus[i-1];
+		if (prev_cu->info.intr_id < xcu->info.intr_id) {
+			insert_cu(cu_mgmt, i, xcu);
+			++cu_mgmt->num_cus;
+			return 0;
+		} else if (prev_cu->info.intr_id > xcu->info.intr_id) {
+			insert_cu(cu_mgmt, i, prev_cu);
+			continue;
+		}
+
+		// Same intr ID.
+		if (prev_cu->info.addr < xcu->info.addr) {
+			insert_cu(cu_mgmt, i, xcu);
+			++cu_mgmt->num_cus;
+			return 0;
+		} else if (prev_cu->info.addr > xcu->info.addr) {
+			insert_cu(cu_mgmt, i, prev_cu);
+			continue;
+		}
+
+		/* Same CU address? Something wrong */
+		break;
+	}
+
+	if (i == 0) {
+		insert_cu(cu_mgmt, 0, xcu);
+		++cu_mgmt->num_cus;
+		return 0;
+	}
+
+	return -ENOSPC;
+}
+
+int kds_del_cu(struct kds_sched *kds, struct xrt_cu *xcu)
+{
+	struct kds_cu_mgmt *cu_mgmt = &kds->cu_mgmt;
+	int i;
+
+	if (cu_mgmt->num_cus == 0)
+		return -EINVAL;
+
+	for (i = 0; i < MAX_CUS; i++) {
+		if (cu_mgmt->xcus[i] != xcu)
+			continue;
+
+		--cu_mgmt->num_cus;
+		cu_mgmt->xcus[i] = NULL;
+		cu_mgmt->cu_usage[i] = 0;
+
+		/* m2m cu */
+		if (xcu->info.intr_id == M2M_CU_ID)
+			cu_mgmt->num_cdma--;
+
+		return 0;
+	}
+
+	return -ENODEV;
+}
+
+int kds_init_ert(struct kds_sched *kds, struct kds_ert *ert)
+{
+	kds->ert = ert;
+	/* By default enable ERT if it exist */
+	kds->ert_disable = false;
+	return 0;
+}
+
+int kds_fini_ert(struct kds_sched *kds)
+{
+	return 0;
+}
+
+void kds_reset(struct kds_sched *kds)
+{
+	kds->bad_state = 0;
+	kds->ert_disable = true;
+	kds->ini_disable = false;
+}
+
+static int kds_fa_assign_plram(struct kds_sched *kds)
+{
+	struct kds_cu_mgmt *cu_mgmt = &kds->cu_mgmt;
+	u32 total_sz = 0;
+	u32 num_slots;
+	u32 size;
+	u64 bar_addr;
+	u64 dev_addr;
+	int ret = 0;
+	int i;
+	void __iomem *vaddr;
+
+	for (i = 0; i < cu_mgmt->num_cus; i++) {
+		if (!xrt_is_fa(cu_mgmt->xcus[i], &size))
+			continue;
+
+		total_sz += size;
+		/* Release old resoruces if exist */
+		xrt_fa_cfg_update(cu_mgmt->xcus[i], 0, 0, 0, 0);
+	}
+
+	total_sz = round_up_to_next_power2(total_sz);
+
+	if (kds->plram.size < total_sz)
+		return -EINVAL;
+
+	num_slots = kds->plram.size / total_sz;
+
+	bar_addr = kds->plram.bar_paddr;
+	dev_addr = kds->plram.dev_paddr;
+	vaddr = kds->plram.vaddr;
+	for (i = 0; i < cu_mgmt->num_cus; i++) {
+		if (!xrt_is_fa(cu_mgmt->xcus[i], &size))
+			continue;
+
+		/* The updated FA CU would release when it is removed */
+		ret = xrt_fa_cfg_update(cu_mgmt->xcus[i], bar_addr, dev_addr, vaddr, num_slots);
+		if (ret)
+			return ret;
+		bar_addr += size * num_slots;
+		dev_addr += size * num_slots;
+		vaddr += size * num_slots;
+	}
+
+	return 0;
+}
+
+int kds_cfg_update(struct kds_sched *kds)
+{
+	struct kds_cu_mgmt *cu_mgmt = &kds->cu_mgmt;
+	struct xrt_cu *xcu;
+	int ret = 0;
+	int i;
+
+	/* Update PLRAM CU */
+	if (kds->plram.dev_paddr) {
+		ret = kds_fa_assign_plram(kds);
+		if (ret)
+			return -EINVAL;
+		/* ERT doesn't understand Fast adapter
+		 * Host crash at around configure command if ERT is enabled.
+		 * TODO: Support fast adapter in ERT?
+		 */
+		kds->ert_disable = true;
+	}
+
+	/* Update CU interrupt mode */
+	if (kds->cu_intr_cap) {
+		for (i = 0; i < cu_mgmt->num_cus; i++) {
+			if (cu_mgmt->cu_intr[i] == kds->cu_intr)
+				continue;
+
+			xcu = cu_mgmt->xcus[i];
+			ret = xrt_cu_cfg_update(xcu, kds->cu_intr);
+			if (!ret)
+				cu_mgmt->cu_intr[i] = kds->cu_intr;
+			else if (ret == -ENOSYS) {
+				/* CU doesn't support interrupt */
+				cu_mgmt->cu_intr[i] = 0;
+				ret = 0;
+			}
+		}
+	}
+
+	return ret;
+}
+
+int is_bad_state(struct kds_sched *kds)
+{
+	return kds->bad_state;
+}
+
+u32 kds_live_clients(struct kds_sched *kds, pid_t **plist)
+{
+	u32 count = 0;
+
+	mutex_lock(&kds->lock);
+	count = kds_live_clients_nolock(kds, plist);
+	mutex_unlock(&kds->lock);
+
+	return count;
+}
+
+/*
+ * Return number of client with open ("live") contexts on CUs.
+ * If this number > 0, xclbin is locked down.
+ * If plist is non-NULL, the list of PIDs of live clients will also be returned.
+ * Note that plist should be freed by caller.
+ */
+u32 kds_live_clients_nolock(struct kds_sched *kds, pid_t **plist)
+{
+	const struct list_head *ptr;
+	struct kds_client *client;
+	pid_t *pl = NULL;
+	u32 count = 0;
+	u32 i = 0;
+
+	/* Find out number of active client */
+	list_for_each(ptr, &kds->clients) {
+		client = list_entry(ptr, struct kds_client, link);
+		if (client->num_ctx > 0)
+			count++;
+	}
+	if (count == 0 || plist == NULL)
+		goto out;
+
+	/* Collect list of PIDs of active client */
+	pl = (pid_t *)vmalloc(sizeof(pid_t) * count);
+	if (pl == NULL)
+		goto out;
+
+	list_for_each(ptr, &kds->clients) {
+		client = list_entry(ptr, struct kds_client, link);
+		if (client->num_ctx > 0) {
+			pl[i] = pid_nr(client->pid);
+			i++;
+		}
+	}
+
+	*plist = pl;
+out:
+	return count;
+}
+
+/* User space execbuf command related functions below */
+void cfg_ecmd2xcmd(struct ert_configure_cmd *ecmd,
+		   struct kds_command *xcmd)
+{
+	int i;
+
+	/* To let ERT 3.0 firmware aware new KDS is talking to it,
+	 * set kds_30 bit. This is no harm for ERT 2.0 firmware.
+	 */
+	ecmd->kds_30 = 1;
+
+	xcmd->opcode = OP_CONFIG;
+
+	xcmd->execbuf = (u32 *)ecmd;
+
+	xcmd->isize = ecmd->num_cus * sizeof(u32);
+	/* Remove encoding at the low bits
+	 * The same information is stored in CU already.
+	 */
+	for (i = 0; i < ecmd->num_cus; i++)
+		ecmd->data[i] &= ~0x000000FF;
+
+	/* Expect a ordered list of CU address */
+	memcpy(xcmd->info, ecmd->data, xcmd->isize);
+}
+
+void start_krnl_ecmd2xcmd(struct ert_start_kernel_cmd *ecmd,
+			  struct kds_command *xcmd)
+{
+	xcmd->opcode = OP_START;
+
+	xcmd->execbuf = (u32 *)ecmd;
+
+	xcmd->cu_mask[0] = ecmd->cu_mask;
+	memcpy(&xcmd->cu_mask[1], ecmd->data, ecmd->extra_cu_masks);
+	xcmd->num_mask = 1 + ecmd->extra_cu_masks;
+
+	/* Copy resigter map into info and isize is the size of info in bytes.
+	 *
+	 * Based on ert.h, ecmd->count is the number of words following header.
+	 * In ert_start_kernel_cmd, the CU register map size is
+	 * (count - (1 + extra_cu_masks)) and I would like to Skip
+	 * first 4 control registers
+	 */
+	xcmd->isize = (ecmd->count - xcmd->num_mask - 4) * sizeof(u32);
+	memcpy(xcmd->info, &ecmd->data[4 + ecmd->extra_cu_masks], xcmd->isize);
+}
+
+void start_fa_ecmd2xcmd(struct ert_start_kernel_cmd *ecmd,
+			  struct kds_command *xcmd)
+{
+	xcmd->opcode = OP_START;
+
+	xcmd->execbuf = (u32 *)ecmd;
+
+	xcmd->cu_mask[0] = ecmd->cu_mask;
+	memcpy(&xcmd->cu_mask[1], ecmd->data, ecmd->extra_cu_masks);
+	xcmd->num_mask = 1 + ecmd->extra_cu_masks;
+
+	/* Copy descriptor into info and isize is the size of info in bytes.
+	 *
+	 * Based on ert.h, ecmd->count is the number of words following header.
+	 * The descriptor size is (count - (1 + extra_cu_masks)).
+	 */
+	xcmd->isize = (ecmd->count - xcmd->num_mask) * sizeof(u32);
+	memcpy(xcmd->info, &ecmd->data[ecmd->extra_cu_masks], xcmd->isize);
+}
+
+/**
+ * cu_mask_to_cu_idx - Convert CU mask to CU index list
+ *
+ * @xcmd: Command
+ * @cus:  CU index list
+ *
+ * Returns: Number of CUs
+ *
+ */
+inline int
+cu_mask_to_cu_idx(struct kds_command *xcmd, uint8_t *cus)
+{
+	int num_cu = 0;
+	u32 mask;
+	/* i for iterate masks, j for iterate bits */
+	int i, j;
+
+	for (i = 0; i < xcmd->num_mask; ++i) {
+		if (xcmd->cu_mask[i] == 0)
+			continue;
+
+		mask = xcmd->cu_mask[i];
+		for (j = 0; mask > 0; ++j) {
+			if (!(mask & 0x1)) {
+				mask >>= 1;
+				continue;
+			}
+
+			cus[num_cu] = i * 32 + j;
+			num_cu++;
+			mask >>= 1;
+		}
+	}
+
+	return num_cu;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/common/xrt_cu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/common/xrt_cu.c
@@ -0,0 +1,688 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * Xilinx Unify CU Model
+ *
+ * Copyright (C) 2020 Xilinx, Inc. All rights reserved.
+ *
+ * Authors: min.ma@xilinx.com
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#include <linux/delay.h>
+#include "xrt_cu.h"
+
+/* Use for flush queue */
+static inline void
+flush_queue(struct list_head *q, u32 *len, int status, void *client)
+{
+	struct kds_command *xcmd;
+	struct kds_command *next;
+
+	if (*len == 0)
+		return;
+
+	list_for_each_entry_safe(xcmd, next, q, list) {
+		if (client && client != xcmd->client)
+			continue;
+		xcmd->cb.notify_host(xcmd, status);
+		list_del(&xcmd->list);
+		xcmd->cb.free(xcmd);
+		--(*len);
+	}
+}
+
+/**
+ * process_cq() - Process completed queue
+ * @xcu: Target XRT CU
+ */
+static inline void process_cq(struct xrt_cu *xcu)
+{
+	struct kds_command *xcmd;
+
+	if (!xcu->num_cq)
+		return;
+
+	/* Notify host and free command
+	 *
+	 * NOTE: Use loop to handle completed commands could improve
+	 * performance (Reduce sleep time and increase chance for more
+	 * pending commands at one time)
+	 */
+	while (xcu->num_cq) {
+		xcmd = list_first_entry(&xcu->cq, struct kds_command, list);
+		xcmd->cb.notify_host(xcmd, KDS_COMPLETED);
+		list_del(&xcmd->list);
+		xcmd->cb.free(xcmd);
+		--xcu->num_cq;
+	}
+}
+
+/**
+ * __process_sq() - Process submitted queue
+ * @xcu: Target XRT CU
+ */
+static inline void __process_sq(struct xrt_cu *xcu)
+{
+	struct kds_command *xcmd;
+	u64 time;
+
+	/* CU is ready to accept more commands
+	 * Return credits to allow submit more commands
+	 */
+	if (xcu->ready_cnt) {
+		xrt_cu_put_credit(xcu, xcu->ready_cnt);
+		xcu->ready_cnt = 0;
+	}
+
+	if (xcu->run_timeout && !xcu->done_cnt && xcu->num_sq) {
+		xcmd = list_first_entry(&xcu->sq, struct kds_command, list);
+		if (!xcu->old_cmd || xcu->old_cmd != xcmd) {
+			xcmd->start = ktime_get_raw_fast_ns();
+			xcu->old_cmd = xcmd;
+			return;
+		}
+
+		time = ktime_get_raw_fast_ns();
+		if (time - xcmd->start > xcu->run_timeout)
+			xcu->bad_state = 1;
+		return;
+	}
+
+	/* Move all of the completed commands to completed queue */
+	while (xcu->done_cnt && xcu->num_sq) {
+		xcmd = list_first_entry(&xcu->sq, struct kds_command, list);
+		list_move_tail(&xcmd->list, &xcu->cq);
+		--xcu->num_sq;
+		++xcu->num_cq;
+		--xcu->done_cnt;
+	}
+}
+
+/**
+ * process_sq() - Process submitted queue
+ * @xcu: Target XRT CU
+ */
+static inline void process_sq(struct xrt_cu *xcu)
+{
+	/* A submitted command might be done but the CU is still
+	 * not ready for next command. In this case, check CU status
+	 * to get ready count.
+	 */
+	if (!xcu->num_sq && !is_zero_credit(xcu))
+		return;
+
+	/* If no command is running on the hardware,
+	 * this would not really access hardware.
+	 */
+	xrt_cu_check(xcu);
+
+	__process_sq(xcu);
+}
+
+/**
+ * process_rq() - Process run queue
+ * @xcu: Target XRT CU
+ *
+ * Return: return 0 if run queue is empty or no credit
+ *	   Otherwise, return 1
+ */
+static inline int process_rq(struct xrt_cu *xcu)
+{
+	struct kds_command *xcmd;
+
+	if (!xcu->num_rq)
+		return 0;
+
+	xcmd = list_first_entry(&xcu->rq, struct kds_command, list);
+
+	if (!xrt_cu_get_credit(xcu))
+		return 0;
+
+	/* if successfully get credit, you must start cu */
+	xrt_cu_config(xcu, (u32 *)xcmd->info, xcmd->isize, 0);
+	xrt_cu_start(xcu);
+
+	/* ktime_get_* is still heavy. This impact ~20% of IOPS on echo mode.
+	 * For some sort of CU, which usually has a relative long execute time,
+	 * we could hide this overhead and provide timestamp for each command.
+	 * But this implementation is used for general purpose. Please create CU
+	 * specific thread if needed.
+	 */
+	//xcmd->start = ktime_get_raw_fast_ns();
+	/* Move xcmd to submmited queue */
+	list_move_tail(&xcmd->list, &xcu->sq);
+	--xcu->num_rq;
+	++xcu->num_sq;
+
+	return 1;
+}
+
+/**
+ * process_pq() - Process pending queue
+ * @xcu: Target XRT CU
+ *
+ * Move all of the pending queue commands to the tail of run queue
+ * and re-initialized pending queue
+ */
+static inline void process_pq(struct xrt_cu *xcu)
+{
+	unsigned long flags;
+
+	/* Get pending queue command number without lock.
+	 * The idea is to reduce the possibility of conflict on lock.
+	 * Need to check pending command number again after lock.
+	 */
+	if (!xcu->num_pq)
+		return;
+	spin_lock_irqsave(&xcu->pq_lock, flags);
+	if (xcu->num_pq) {
+		list_splice_tail_init(&xcu->pq, &xcu->rq);
+		xcu->num_rq += xcu->num_pq;
+		xcu->num_pq = 0;
+	}
+	spin_unlock_irqrestore(&xcu->pq_lock, flags);
+	if (xcu->max_running < xcu->num_rq)
+		xcu->max_running = xcu->num_rq;
+}
+
+/**
+ * process_event() - Process event
+ * @xcu: Target XRT CU
+ *
+ * This is used to process low frequency events.
+ * For example, client abort event would happen when closing client.
+ * Before the client close, make sure all of the client commands have
+ * been handle properly.
+ */
+static inline void process_event(struct xrt_cu *xcu)
+{
+	void *client = NULL;
+	struct kds_command *xcmd;
+
+	mutex_lock(&xcu->ev.lock);
+	if (!xcu->ev.client)
+		goto done;
+
+	client = xcu->ev.client;
+
+	flush_queue(&xcu->rq, &xcu->num_rq, KDS_ABORT, client);
+
+	/* Let's check submitted commands one more time */
+	process_sq(xcu);
+	if (xcu->num_sq) {
+		/* This rarely happens */
+		list_for_each_entry(xcmd, &xcu->sq, list) {
+			if (xcmd->client == client) {
+				/* It is possible to print 'hang' command
+				 * details for debug. Should we?
+				 */
+				xcu->ev.state = CU_STATE_BAD;
+				break;
+			}
+		}
+		flush_queue(&xcu->sq, &xcu->num_sq, KDS_ABORT, client);
+	}
+
+	while (xcu->num_cq)
+		process_cq(xcu);
+
+	/* Maybe pending queue has commands of this client */
+	process_pq(xcu);
+	flush_queue(&xcu->rq, &xcu->num_rq, KDS_ABORT, client);
+
+	if (!xcu->ev.state)
+		xcu->ev.state = CU_STATE_GOOD;
+done:
+	mutex_unlock(&xcu->ev.lock);
+}
+
+int xrt_cu_polling_thread(void *data)
+{
+	struct xrt_cu *xcu = (struct xrt_cu *)data;
+	int ret = 0;
+
+	xcu_info(xcu, "start");
+	while (!xcu->stop) {
+		/* Make sure to submit as many commands as possible.
+		 * This is why we call continue here. This is important to make
+		 * CU busy, especially CU has hardware queue.
+		 */
+		if (process_rq(xcu))
+			continue;
+		/* process completed queue before submitted queue, for
+		 * two reasons:
+		 * - The last submitted command may be still running
+		 * - while handling completed queue, running command might done
+		 * - process_sq will check CU status, which is thru slow bus
+		 */
+		process_cq(xcu);
+		process_sq(xcu);
+		process_event(xcu);
+
+		if (xcu->bad_state)
+			break;
+
+		/* The idea is when CU's credit is less than busy threshold,
+		 * sleep a while to wait for CU completion.
+		 * The interval is configurable and it should be determin by
+		 * kernel execution.
+		 * If threshold is -1, then this is a busy loop to check CU
+		 * statue.
+		 */
+		if (xrt_cu_peek_credit(xcu) <= xcu->busy_threshold)
+			usleep_range(xcu->interval_min, xcu->interval_max);
+
+		/* Continue until run queue empty */
+		if (xcu->num_rq)
+			continue;
+
+		if (!xcu->num_sq && !xcu->num_cq) {
+			xcu->sleep_cnt++;
+			if (down_interruptible(&xcu->sem))
+				ret = -ERESTARTSYS;
+		}
+
+		process_pq(xcu);
+	}
+
+	if (!xcu->bad_state) {
+		xcu_info(xcu, "end");
+		return ret;
+	}
+
+	xcu_info(xcu, "bad state handling");
+	/* CU in bad state mode, abort all new commands */
+	flush_queue(&xcu->sq, &xcu->num_sq, KDS_ABORT, NULL);
+	flush_queue(&xcu->cq, &xcu->num_cq, KDS_ABORT, NULL);
+	while (!xcu->stop) {
+		flush_queue(&xcu->rq, &xcu->num_rq, KDS_ABORT, NULL);
+		process_event(xcu);
+
+		if (down_interruptible(&xcu->sem))
+			ret = -ERESTARTSYS;
+
+		process_pq(xcu);
+	}
+
+	xcu_info(xcu, "end handling");
+	return ret;
+}
+
+int xrt_cu_intr_thread(void *data)
+{
+	struct xrt_cu *xcu = (struct xrt_cu *)data;
+	int ret = 0;
+
+	xcu_info(xcu, "start");
+	xrt_cu_enable_intr(xcu, CU_INTR_DONE | CU_INTR_READY);
+	while (!xcu->stop) {
+		/* Make sure to submit as many commands as possible.
+		 * This is why we call continue here. This is important to make
+		 * CU busy, especially CU has hardware queue.
+		 */
+		if (process_rq(xcu))
+			continue;
+
+		if (xcu->num_sq) {
+			if (down_interruptible(&xcu->sem_cu))
+				ret = -ERESTARTSYS;
+			__process_sq(xcu);
+		}
+
+		process_cq(xcu);
+		process_event(xcu);
+
+		if (xcu->bad_state)
+			break;
+
+		/* Continue until run queue empty */
+		if (xcu->num_rq)
+			continue;
+
+		if (!xcu->num_sq && !xcu->num_cq) {
+			xcu->sleep_cnt++;
+			if (down_interruptible(&xcu->sem))
+				ret = -ERESTARTSYS;
+		}
+
+		process_pq(xcu);
+	}
+	xrt_cu_disable_intr(xcu, CU_INTR_DONE | CU_INTR_READY);
+
+	if (!xcu->bad_state) {
+		xcu_info(xcu, "end");
+		return ret;
+	}
+
+	xcu_info(xcu, "bad state handling");
+	/* CU in bad state mode, abort all new commands */
+	flush_queue(&xcu->sq, &xcu->num_sq, KDS_ABORT, NULL);
+	flush_queue(&xcu->cq, &xcu->num_cq, KDS_ABORT, NULL);
+	while (!xcu->stop) {
+		flush_queue(&xcu->rq, &xcu->num_rq, KDS_ABORT, NULL);
+		process_event(xcu);
+
+		if (down_interruptible(&xcu->sem))
+			ret = -ERESTARTSYS;
+
+		process_pq(xcu);
+	}
+
+	xcu_info(xcu, "end handling");
+	return ret;
+}
+
+void xrt_cu_submit(struct xrt_cu *xcu, struct kds_command *xcmd)
+{
+	unsigned long flags;
+	bool first_command = false;
+
+	/* Add command to pending queue
+	 * wakeup CU thread if it is the first command
+	 */
+	spin_lock_irqsave(&xcu->pq_lock, flags);
+	list_add_tail(&xcmd->list, &xcu->pq);
+	++xcu->num_pq;
+	first_command = (xcu->num_pq == 1);
+	spin_unlock_irqrestore(&xcu->pq_lock, flags);
+	if (first_command)
+		up(&xcu->sem);
+}
+
+/**
+ * xrt_cu_abort() - Sent an abort event to CU thread
+ * @xcu: Target XRT CU
+ * @client: The client tries to abort commands
+ *
+ * This is used to ask CU thread to abort all commands from the client.
+ */
+int xrt_cu_abort(struct xrt_cu *xcu, void *client)
+{
+	int ret = 0;
+
+	mutex_lock(&xcu->ev.lock);
+	if (xcu->ev.client) {
+		ret = -EAGAIN;
+		goto done;
+	}
+
+	xcu->ev.client = client;
+	xcu->ev.state = 0;
+
+done:
+	mutex_unlock(&xcu->ev.lock);
+	up(&xcu->sem);
+	up(&xcu->sem_cu);
+	return ret;
+}
+
+/**
+ * xrt_cu_abort() - Get done flag of abort
+ * @xcu: Target XRT CU
+ *
+ * Use this to wait for abort event done
+ */
+int xrt_cu_abort_done(struct xrt_cu *xcu)
+{
+	int state = 0;
+
+	mutex_lock(&xcu->ev.lock);
+	if (xcu->ev.state) {
+		xcu->ev.client = NULL;
+		state = xcu->ev.state;
+	}
+	mutex_unlock(&xcu->ev.lock);
+
+	return state;
+}
+
+int xrt_cu_cfg_update(struct xrt_cu *xcu, int intr)
+{
+	int (* cu_thread)(void *data);
+	int err = 0;
+
+	/* Check if CU support interrupt in hardware */
+	if (!xcu->info.intr_enable)
+		return -ENOSYS;
+
+	if (intr)
+		cu_thread = xrt_cu_intr_thread;
+	else
+		cu_thread = xrt_cu_polling_thread;
+
+	/* Stop old thread */
+	xcu->stop = 1;
+	up(&xcu->sem_cu);
+	up(&xcu->sem);
+	if (!IS_ERR(xcu->thread))
+		(void) kthread_stop(xcu->thread);
+
+	/* launch new thread */
+	xcu->stop = 0;
+	sema_init(&xcu->sem, 0);
+	sema_init(&xcu->sem_cu, 0);
+	xcu->thread = kthread_run(cu_thread, xcu, xcu->info.iname);
+	if (IS_ERR(xcu->thread)) {
+		err = IS_ERR(xcu->thread);
+		xcu_err(xcu, "Create CU thread failed, err %d\n", err);
+	}
+
+	return err;
+}
+
+/* 
+ * If KDS has to manage PLRAM resources, we should come up with a better design.
+ * Ideally, CU subdevice should request for plram resource instead of KDS assign
+ * plram resource to CU.
+ * Or, another solution is to let KDS create CU subdevice indtead of
+ * icap/zocl_xclbin.
+ */
+static u32 cu_fa_get_desc_size(struct xrt_cu *xcu)
+{
+	struct xrt_cu_info *info = &xcu->info;
+	u32 size = sizeof(descriptor_t);
+	int i;
+
+	for (i = 0; i < info->num_args; i++) {
+		/* The "nextDescriptorAddr" argument is a fast adapter argument.
+		 * It is not required to construct descriptor
+		 */
+		if (!strcmp(info->args[i].name, "nextDescriptorAddr") || !info->args[i].size)
+			continue;
+
+		size += (sizeof(descEntry_t)+info->args[i].size);
+	}
+
+	return round_up_to_next_power2(size);
+}
+
+int xrt_is_fa(struct xrt_cu *xcu, u32 *size)
+{
+	struct xrt_cu_info *info = &xcu->info;
+	int ret;
+
+	ret = (info->model == XCU_FA)? 1 : 0;
+
+	if (ret && size)
+		*size = cu_fa_get_desc_size(xcu);
+
+	return ret;
+}
+
+int xrt_fa_cfg_update(struct xrt_cu *xcu, u64 bar, u64 dev, void __iomem *vaddr, u32 num_slots)
+{
+	struct xrt_cu_fa *cu_fa = xcu->core;
+	u32 slot_size;
+
+	if (bar == 0) {
+		cu_fa->plram = NULL;
+		cu_fa->paddr = 0;
+		cu_fa->slot_sz = 0;
+		cu_fa->num_slots = 0;
+		return 0;
+	}
+
+	slot_size = cu_fa_get_desc_size(xcu);
+
+	cu_fa->plram = vaddr;
+	cu_fa->paddr = dev;
+	cu_fa->slot_sz = slot_size;
+	cu_fa->num_slots = num_slots;
+
+	cu_fa->credits = (cu_fa->num_slots < cu_fa->max_credits)?
+			 cu_fa->num_slots : cu_fa->max_credits;
+
+	return 0;
+}
+
+void xrt_cu_set_bad_state(struct xrt_cu *xcu)
+{
+	xcu->bad_state = 1;
+}
+
+int xrt_cu_init(struct xrt_cu *xcu)
+{
+	int err = 0;
+	char *name = xcu->info.iname;
+
+	/* TODO A workaround to avoid m2m subdev launch thread */
+	if (!strlen(name))
+		return 0;
+
+	/* Use list for driver space command queue
+	 * Should we consider ring buffer?
+	 */
+
+	/* Initialize pending queue and lock */
+	INIT_LIST_HEAD(&xcu->pq);
+	spin_lock_init(&xcu->pq_lock);
+	/* Initialize run queue */
+	INIT_LIST_HEAD(&xcu->rq);
+	/* Initialize submitted queue */
+	INIT_LIST_HEAD(&xcu->sq);
+	/* Initialize completed queue */
+	INIT_LIST_HEAD(&xcu->cq);
+
+	mutex_init(&xcu->ev.lock);
+	xcu->ev.client = NULL;
+	/* default timeout, 0 means infinity */
+	xcu->run_timeout = 0;
+	sema_init(&xcu->sem, 0);
+	sema_init(&xcu->sem_cu, 0);
+	/* A CU maybe doesn't support interrupt, polling */
+	xcu->thread = kthread_run(xrt_cu_polling_thread, xcu, name);
+	if (IS_ERR(xcu->thread)) {
+		err = IS_ERR(xcu->thread);
+		xcu_err(xcu, "Create CU thread failed, err %d\n", err);
+	}
+
+	return err;
+}
+
+void xrt_cu_fini(struct xrt_cu *xcu)
+{
+	/* TODO A workaround for m2m subdev */
+	if (!strlen(xcu->info.iname))
+		return;
+
+	xcu->stop = 1;
+	up(&xcu->sem_cu);
+	up(&xcu->sem);
+	if (!IS_ERR(xcu->thread))
+		(void) kthread_stop(xcu->thread);
+
+	return;
+}
+
+ssize_t show_cu_stat(struct xrt_cu *xcu, char *buf)
+{
+	ssize_t sz = 0;
+
+	/* Add CU dynamic statistic information in below */
+	sz += scnprintf(buf+sz, PAGE_SIZE - sz, "Pending queue:    %d\n",
+			xcu->num_pq);
+	sz += scnprintf(buf+sz, PAGE_SIZE - sz, "Running queue:    %d\n",
+			xcu->num_rq);
+	sz += scnprintf(buf+sz, PAGE_SIZE - sz, "Submitted queue:  %d\n",
+			xcu->num_sq);
+	sz += scnprintf(buf+sz, PAGE_SIZE - sz, "Completed queue:  %d\n",
+			xcu->num_cq);
+	sz += scnprintf(buf+sz, PAGE_SIZE - sz, "Bad state:        %d\n",
+			xcu->bad_state);
+	sz += scnprintf(buf+sz, PAGE_SIZE - sz, "Current credit:   %d\n",
+			xcu->funcs->peek_credit(xcu->core));
+	sz += scnprintf(buf+sz, PAGE_SIZE - sz, "CU status:        0x%x\n",
+			xcu->status);
+	sz += scnprintf(buf+sz, PAGE_SIZE - sz, "sleep cnt:        %d\n",
+			xcu->sleep_cnt);
+	sz += scnprintf(buf+sz, PAGE_SIZE - sz, "max running:      %d\n",
+			xcu->max_running);
+
+	if (xcu->info.model == XCU_FA) {
+		sz += scnprintf(buf+sz, PAGE_SIZE - sz, "-- FA CU specific --\n");
+		sz += scnprintf(buf+sz, PAGE_SIZE - sz, "Check count: %lld\n",
+				to_cu_fa(xcu->core)->check_count);
+	}
+
+	if (sz < PAGE_SIZE - 1)
+		buf[sz++] = 0;
+	else
+		buf[PAGE_SIZE - 1] = 0;
+
+	return sz;
+}
+
+ssize_t show_cu_info(struct xrt_cu *xcu, char *buf)
+{
+	struct xrt_cu_info *info = &xcu->info;
+	ssize_t sz = 0;
+	char dir[10];
+	int i;
+
+	/* Add any CU static information in below */
+	sz += scnprintf(buf+sz, PAGE_SIZE - sz, "Kernel name: %s\n",
+			info->kname);
+	sz += scnprintf(buf+sz, PAGE_SIZE - sz, "Instance(CU) name: %s\n",
+			info->iname);
+	sz += scnprintf(buf+sz, PAGE_SIZE - sz, "CU address: 0x%llx\n",
+			info->addr);
+	sz += scnprintf(buf+sz, PAGE_SIZE - sz, "CU index: %d\n",
+			info->cu_idx);
+	sz += scnprintf(buf+sz, PAGE_SIZE - sz, "Protocol: %s\n",
+			prot2str(info->protocol));
+	sz += scnprintf(buf+sz, PAGE_SIZE - sz, "Interrupt cap: %d\n",
+			info->intr_enable);
+	sz += scnprintf(buf+sz, PAGE_SIZE - sz, "Interrupt ID:  %d\n",
+			info->intr_id);
+
+	sz += scnprintf(buf+sz, PAGE_SIZE - sz, "--- Arguments ---\n");
+	sz += scnprintf(buf+sz, PAGE_SIZE - sz, "Number of arguments: %d\n",
+			info->num_args);
+	for (i = 0; i < info->num_args; i++) {
+		if (info->args[i].dir == DIR_INPUT)
+			strcpy(dir, "input");
+		else if (info->args[i].dir == DIR_OUTPUT)
+			strcpy(dir, "output");
+		else
+			strcpy(dir, "unknown");
+
+		sz += scnprintf(buf+sz, PAGE_SIZE - sz, "arg name: %s\n",
+				info->args[i].name);
+		sz += scnprintf(buf+sz, PAGE_SIZE - sz, "  size: %d\n",
+				info->args[i].size);
+		sz += scnprintf(buf+sz, PAGE_SIZE - sz, "  offset: 0x%x\n",
+				info->args[i].offset);
+		sz += scnprintf(buf+sz, PAGE_SIZE - sz, "  direction: %s\n",
+				dir);
+	}
+
+	if (sz < PAGE_SIZE - 1)
+		buf[sz++] = 0;
+	else
+		buf[PAGE_SIZE - 1] = 0;
+
+
+	return sz;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/common/xrt_xclbin.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/common/xrt_xclbin.c
@@ -0,0 +1,264 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * Xilinx Kernel Driver XCLBIN parser
+ *
+ * Copyright (C) 2020 Xilinx, Inc. All rights reserved.
+ *
+ * Authors: David Zhang <davidzha@xilinx.com>
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#include <asm/errno.h>
+#include <linux/vmalloc.h>
+#include "xclbin.h"
+#include "xrt_xclbin.h"
+
+int xrt_xclbin_parse_header(const unsigned char *data,
+	unsigned int size, struct XHwIcap_Bit_Header *header)
+{
+	unsigned int i;
+	unsigned int len;
+	unsigned int tmp;
+	unsigned int index;
+
+	/* Start Index at start of bitstream */
+	index = 0;
+
+	/* Initialize HeaderLength.  If header returned early inidicates
+	 * failure.
+	 */
+	header->HeaderLength = XHI_BIT_HEADER_FAILURE;
+
+	/* Get "Magic" length */
+	header->MagicLength = data[index++];
+	header->MagicLength = (header->MagicLength << 8) | data[index++];
+
+	/* Read in "magic" */
+	for (i = 0; i < header->MagicLength - 1; i++) {
+		tmp = data[index++];
+		if (i%2 == 0 && tmp != XHI_EVEN_MAGIC_BYTE)
+			return -1;   /* INVALID_FILE_HEADER_ERROR */
+
+		if (i%2 == 1 && tmp != XHI_ODD_MAGIC_BYTE)
+			return -1;   /* INVALID_FILE_HEADER_ERROR */
+
+	}
+
+	/* Read null end of magic data. */
+	tmp = data[index++];
+
+	/* Read 0x01 (short) */
+	tmp = data[index++];
+	tmp = (tmp << 8) | data[index++];
+
+	/* Check the "0x01" half word */
+	if (tmp != 0x01)
+		return -1;	 /* INVALID_FILE_HEADER_ERROR */
+
+	/* Read 'a' */
+	tmp = data[index++];
+	if (tmp != 'a')
+		return -1;	  /* INVALID_FILE_HEADER_ERROR	*/
+
+	/* Get Design Name length */
+	len = data[index++];
+	len = (len << 8) | data[index++];
+
+	/* allocate space for design name and final null character. */
+	header->DesignName = vmalloc(len);
+
+	/* Read in Design Name */
+	for (i = 0; i < len; i++)
+		header->DesignName[i] = data[index++];
+
+
+	if (header->DesignName[len-1] != '\0')
+		return -1;
+
+	/* Read 'b' */
+	tmp = data[index++];
+	if (tmp != 'b')
+		return -1;	/* INVALID_FILE_HEADER_ERROR */
+
+	/* Get Part Name length */
+	len = data[index++];
+	len = (len << 8) | data[index++];
+
+	/* allocate space for part name and final null character. */
+	header->PartName = vmalloc(len);
+
+	/* Read in part name */
+	for (i = 0; i < len; i++)
+		header->PartName[i] = data[index++];
+
+	if (header->PartName[len-1] != '\0')
+		return -1;
+
+	/* Read 'c' */
+	tmp = data[index++];
+	if (tmp != 'c')
+		return -1;	/* INVALID_FILE_HEADER_ERROR */
+
+	/* Get date length */
+	len = data[index++];
+	len = (len << 8) | data[index++];
+
+	/* allocate space for date and final null character. */
+	header->Date = vmalloc(len);
+
+	/* Read in date name */
+	for (i = 0; i < len; i++)
+		header->Date[i] = data[index++];
+
+	if (header->Date[len - 1] != '\0')
+		return -1;
+
+	/* Read 'd' */
+	tmp = data[index++];
+	if (tmp != 'd')
+		return -1;	/* INVALID_FILE_HEADER_ERROR  */
+
+	/* Get time length */
+	len = data[index++];
+	len = (len << 8) | data[index++];
+
+	/* allocate space for time and final null character. */
+	header->Time = vmalloc(len);
+
+	/* Read in time name */
+	for (i = 0; i < len; i++)
+		header->Time[i] = data[index++];
+
+	if (header->Time[len - 1] != '\0')
+		return -1;
+
+	/* Read 'e' */
+	tmp = data[index++];
+	if (tmp != 'e')
+		return -1;	/* INVALID_FILE_HEADER_ERROR */
+
+	/* Get byte length of bitstream */
+	header->BitstreamLength = data[index++];
+	header->BitstreamLength = (header->BitstreamLength << 8) | data[index++];
+	header->BitstreamLength = (header->BitstreamLength << 8) | data[index++];
+	header->BitstreamLength = (header->BitstreamLength << 8) | data[index++];
+	header->HeaderLength = index;
+
+	return 0;
+}
+
+void
+xrt_xclbin_free_header(struct XHwIcap_Bit_Header *header)
+{
+	vfree(header->DesignName);
+	vfree(header->PartName);
+	vfree(header->Date);
+	vfree(header->Time);
+}
+
+char *
+xrt_xclbin_kind_to_string(enum axlf_section_kind kind)
+{
+	switch (kind) {
+	case BITSTREAM:  		return "BITSTREAM";
+	case CLEARING_BITSTREAM:  	return "CLEARING_BITSTREAM";
+	case EMBEDDED_METADATA:  	return "EMBEDDED_METADATA";
+	case FIRMWARE:  		return "FIRMWARE";
+	case DEBUG_DATA:  		return "DEBUG_DATA";
+	case SCHED_FIRMWARE:  		return "SCHED_FIRMWARE";
+	case MEM_TOPOLOGY:  		return "MEM_TOPOLOGY";
+	case CONNECTIVITY:  		return "CONNECTIVITY";
+	case IP_LAYOUT:  		return "IP_LAYOUT";
+	case DEBUG_IP_LAYOUT:  		return "DEBUG_IP_LAYOUT";
+	case DESIGN_CHECK_POINT: 	return "DESIGN_CHECK_POINT";
+	case CLOCK_FREQ_TOPOLOGY: 	return "CLOCK_FREQ_TOPOLOGY";
+	case MCS: 			return "MCS";
+	case BMC: 			return "BMC";
+	case BUILD_METADATA: 		return "BUILD_METADATA";
+	case KEYVALUE_METADATA: 	return "KEYVALUE_METADATA";
+	case USER_METADATA: 		return "USER_METADATA";
+	case DNA_CERTIFICATE: 		return "DNA_CERTIFICATE";
+	case PDI: 			return "PDI";
+	case BITSTREAM_PARTIAL_PDI: 	return "BITSTREAM_PARTIAL_PDI";
+	case PARTITION_METADATA: 	return "PARTITION_METADATA";
+	case EMULATION_DATA: 		return "EMULATION_DATA";
+	case SYSTEM_METADATA: 		return "SYSTEM_METADATA";
+	case SOFT_KERNEL: 		return "SOFT_KERNEL";
+	case ASK_FLASH: 		return "ASK_FLASH";
+	case AIE_METADATA: 		return "AIE_METADATA";
+	case ASK_GROUP_TOPOLOGY: 	return "ASK_GROUP_TOPOLOGY";
+	case ASK_GROUP_CONNECTIVITY: 	return "ASK_GROUP_CONNECTIVITY";
+	default: 			return "UNKNOWN";
+	}
+}
+
+const struct axlf_section_header *
+xrt_xclbin_get_section_hdr(const struct axlf *xclbin, enum axlf_section_kind kind)
+{
+	int i = 0;
+
+	for (i = 0; i < xclbin->m_header.m_numSections; i++) {
+		if (xclbin->m_sections[i].m_sectionKind == kind)
+			return &xclbin->m_sections[i];
+	}
+
+	return NULL;
+}
+
+int
+xrt_xclbin_check_section_hdr(const struct axlf_section_header *header,
+	uint64_t xclbin_len)
+{
+	return (header->m_sectionOffset + header->m_sectionSize) > xclbin_len ?
+		-EINVAL : 0;
+}
+
+int
+xrt_xclbin_section_info(const struct axlf *xclbin, enum axlf_section_kind kind,
+	uint64_t *offset, uint64_t *size)
+{
+	const struct axlf_section_header *memHeader = NULL;
+	uint64_t xclbin_len;
+	int err = 0;
+
+	memHeader = xrt_xclbin_get_section_hdr(xclbin, kind);
+	if (!memHeader)
+		return -EINVAL;
+
+	xclbin_len = xclbin->m_header.m_length;
+	err = xrt_xclbin_check_section_hdr(memHeader, xclbin_len);
+	if (err)
+		return err;
+
+	*offset = memHeader->m_sectionOffset;
+	*size = memHeader->m_sectionSize;
+
+	return 0;
+}
+
+/* caller should free the allocated memory for **data */
+int xrt_xclbin_get_section(const struct axlf *xclbin,
+	enum axlf_section_kind kind, void **data, uint64_t *len)
+{
+	void *section = NULL;
+	int err = 0;
+	uint64_t offset = 0;
+	uint64_t size = 0;
+
+	err = xrt_xclbin_section_info(xclbin, kind, &offset, &size);
+	if (err)
+		return err;
+
+	section = vmalloc(size);
+	if (section == NULL)
+		return -ENOMEM;
+
+	memcpy(section, ((const char *)xclbin) + offset, size);
+
+	*data = section;
+	*len = size;
+
+	return 0;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/cu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/cu.c
@@ -0,0 +1,222 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * Copyright (C) 2020 Xilinx, Inc. All rights reserved.
+ *
+ * Author(s):
+ *        Min Ma <min.ma@xilinx.com>
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#include "zocl_drv.h"
+#include "xrt_cu.h"
+
+struct zocl_cu {
+	struct xrt_cu		 base;
+	struct platform_device	*pdev;
+};
+
+static ssize_t debug_show(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+#if 0
+	struct platform_device *pdev = to_platform_device(dev);
+	struct zocl_cu *cu = platform_get_drvdata(pdev);
+	struct xrt_cu *xcu = &cu->base;
+#endif
+	/* Place holder for now. */
+	return 0;
+}
+
+static ssize_t debug_store(struct device *dev,
+	struct device_attribute *da, const char *buf, size_t count)
+{
+#if 0
+	struct platform_device *pdev = to_platform_device(dev);
+	struct zocl_cu *cu = platform_get_drvdata(pdev);
+	struct xrt_cu *xcu = &cu->base;
+#endif
+
+	/* Place holder for now. */
+	return count;
+}
+static DEVICE_ATTR_RW(debug);
+
+static ssize_t
+cu_stat_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct zocl_cu *cu = platform_get_drvdata(pdev);
+
+	return show_cu_stat(&cu->base, buf);
+}
+static DEVICE_ATTR_RO(cu_stat);
+
+static ssize_t
+cu_info_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct zocl_cu *cu = platform_get_drvdata(pdev);
+
+	return show_cu_info(&cu->base, buf);
+}
+static DEVICE_ATTR_RO(cu_info);
+
+static struct attribute *cu_attrs[] = {
+	&dev_attr_debug.attr,
+	&dev_attr_cu_stat.attr,
+	&dev_attr_cu_info.attr,
+	NULL,
+};
+
+static const struct attribute_group cu_attrgroup = {
+	.attrs = cu_attrs,
+};
+
+static int cu_probe(struct platform_device *pdev)
+{
+	struct zocl_cu *zcu;
+	struct resource **res;
+	struct xrt_cu_info *info;
+	struct drm_zocl_dev *zdev;
+	struct kernel_info *krnl_info;
+	struct xrt_cu_arg *args = NULL;
+	int err = 0;
+	int i;
+
+	zcu = kzalloc(sizeof(*zcu), GFP_KERNEL);
+	if (!zcu)
+		return -ENOMEM;
+
+	zcu->pdev = pdev;
+	zcu->base.dev = &pdev->dev;
+
+	info = dev_get_platdata(&pdev->dev);
+	memcpy(&zcu->base.info, info, sizeof(struct xrt_cu_info));
+
+	res = vzalloc(sizeof(struct resource *) * info->num_res);
+	if (!res) {
+		err = -ENOMEM;
+		goto err;
+	}
+
+	for (i = 0; i < info->num_res; ++i) {
+		res[i] = platform_get_resource(pdev, IORESOURCE_MEM, i);
+		if (!res[i]) {
+			err = -EINVAL;
+			goto err1;
+		}
+	}
+	zcu->base.res = res;
+
+	zdev = platform_get_drvdata(to_platform_device(pdev->dev.parent));
+
+	krnl_info = zocl_query_kernel(zdev, info->kname);
+	if (!krnl_info) {
+		err = -EFAULT;
+		goto err1;
+	}
+
+	args = vmalloc(sizeof(struct xrt_cu_arg) * krnl_info->anums);
+	if (!args) {
+		err = -ENOMEM;
+		goto err1;
+	}
+
+	for (i = 0; i < krnl_info->anums; i++) {
+		strcpy(args[i].name, krnl_info->args[i].name);
+		args[i].offset = krnl_info->args[i].offset;
+		args[i].size = krnl_info->args[i].size;
+		args[i].dir = krnl_info->args[i].dir;
+	}
+	zcu->base.info.num_args = krnl_info->anums;
+	zcu->base.info.args = args;
+
+	err = zocl_kds_add_cu(zdev, &zcu->base);
+	if (err) {
+		DRM_ERROR("Not able to add CU %p to KDS", zcu);
+		goto err1;
+	}
+
+	switch (info->model) {
+	case XCU_HLS:
+		err = xrt_cu_hls_init(&zcu->base);
+		break;
+	case XCU_FA:
+		err = xrt_cu_fa_init(&zcu->base);
+		break;
+	default:
+		err = -EINVAL;
+	}
+	if (err) {
+		DRM_ERROR("Not able to initial CU %p\n", zcu);
+		goto err2;
+	}
+
+	platform_set_drvdata(pdev, zcu);
+
+	err = sysfs_create_group(&pdev->dev.kobj, &cu_attrgroup);
+	if (err)
+		zocl_err(&pdev->dev, "create CU attrs failed: %d", err);
+
+	return 0;
+err2:
+	zocl_kds_del_cu(zdev, &zcu->base);
+err1:
+	vfree(args);
+	vfree(res);
+err:
+	kfree(zcu);
+	return err;
+}
+
+static int cu_remove(struct platform_device *pdev)
+{
+	struct zocl_cu *zcu;
+	struct drm_zocl_dev *zdev;
+	struct xrt_cu_info *info;
+
+	zcu = platform_get_drvdata(pdev);
+	if (!zcu)
+		return -EINVAL;
+
+	info = &zcu->base.info;
+	switch (info->model) {
+	case XCU_HLS:
+		xrt_cu_hls_fini(&zcu->base);
+		break;
+	case XCU_FA:
+		xrt_cu_fa_fini(&zcu->base);
+		break;
+	}
+
+	zdev = platform_get_drvdata(to_platform_device(pdev->dev.parent));
+	zocl_kds_del_cu(zdev, &zcu->base);
+
+	if (zcu->base.res)
+		vfree(zcu->base.res);
+
+	if (info->args)
+		vfree(info->args);
+
+	sysfs_remove_group(&pdev->dev.kobj, &cu_attrgroup);
+
+	kfree(zcu);
+
+	return 0;
+}
+
+static struct platform_device_id cu_id_table[] = {
+	{"CU", 0 },
+	{ },
+};
+
+struct platform_driver cu_driver = {
+	.probe		= cu_probe,
+	.remove		= cu_remove,
+	.driver		= {
+		.name = "cu_drv",
+	},
+	.id_table	= cu_id_table,
+};
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/include/ert.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/include/ert.h
@@ -0,0 +1,694 @@
+/*
+ *  Copyright (C) 2019-2020, Xilinx Inc
+ *
+ *  This file is dual licensed.  It may be redistributed and/or modified
+ *  under the terms of the Apache 2.0 License OR version 2 of the GNU
+ *  General Public License.
+ *
+ *  Apache License Verbiage
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  GPL license Verbiage:
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License as
+ *  published by the Free Software Foundation; either version 2 of the
+ *  License, or (at your option) any later version.  This program is
+ *  distributed in the hope that it will be useful, but WITHOUT ANY
+ *  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ *  License for more details.  You should have received a copy of the
+ *  GNU General Public License along with this program; if not, write
+ *  to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ *  Boston, MA 02111-1307 USA
+ *
+ */
+
+/**
+ * DOC: Xilinx SDAccel Embedded Runtime definition
+ *
+ * Header file *ert.h* defines data structures used by Emebdded Runtime (ERT) and
+ * XRT xclExecBuf() API.
+ */
+
+#ifndef _ERT_H_
+#define _ERT_H_
+
+#if defined(__KERNEL__)
+# include <linux/types.h>
+#else
+# include <stdint.h>
+#endif
+
+#ifdef _WIN32
+# pragma warning( push )
+# pragma warning( disable : 4201 )
+#endif
+
+#define to_cfg_pkg(pkg) \
+    ((struct ert_configure_cmd *)(pkg))
+#define to_start_krnl_pkg(pkg) \
+    ((struct ert_start_kernel_cmd *)(pkg))
+#define to_copybo_pkg(pkg) \
+    ((struct ert_start_copybo_cmd *)(pkg))
+
+/**
+ * struct ert_packet: ERT generic packet format
+ *
+ * @state:   [3-0] current state of a command
+ * @custom:  [11-4] custom per specific commands
+ * @count:   [22-12] number of words in payload (data)
+ * @opcode:  [27-23] opcode identifying specific command
+ * @type:    [31-28] type of command (currently 0)
+ * @data:    count number of words representing packet payload
+ */
+struct ert_packet {
+  union {
+    struct {
+      uint32_t state:4;   /* [3-0]   */
+      uint32_t custom:8;  /* [11-4]  */
+      uint32_t count:11;  /* [22-12] */
+      uint32_t opcode:5;  /* [27-23] */
+      uint32_t type:4;    /* [31-28] */
+    };
+    uint32_t header;
+  };
+  uint32_t data[1];   /* count number of words */
+};
+
+/**
+ * struct ert_start_kernel_cmd: ERT start kernel command format
+ *
+ * @state:           [3-0]   current state of a command
+ * @stat_enabled:    [4]     enabled driver to record timestamp for various
+ *                           states cmd has gone through. The stat data
+ *                           is appended after cmd data.
+ * @extra_cu_masks:  [11-10] extra CU masks in addition to mandatory mask
+ * @count:           [22-12] number of words following header for cmd data. Not
+ *                           include stat data.
+ * @opcode:          [27-23] 0, opcode for start_kernel
+ * @type:            [31-27] 0, type of start_kernel
+ *
+ * @cu_mask:         first mandatory CU mask
+ * @data:            count-1 number of words representing interpreted payload
+ *
+ * The packet payload is comprised of reserved id field, a mandatory CU mask,
+ * and extra_cu_masks per header field, followed by a CU register map of size
+ * (count - (1 + extra_cu_masks)) uint32_t words.
+ */
+struct ert_start_kernel_cmd {
+  union {
+    struct {
+      uint32_t state:4;          /* [3-0]   */
+      uint32_t stat_enabled:1;   /* [4]     */
+      uint32_t unused:5;         /* [9-5]   */
+      uint32_t extra_cu_masks:2; /* [11-10] */
+      uint32_t count:11;         /* [22-12] */
+      uint32_t opcode:5;         /* [27-23] */
+      uint32_t type:4;           /* [31-27] */
+    };
+    uint32_t header;
+  };
+
+  /* payload */
+  uint32_t cu_mask;          /* mandatory cu mask */
+  uint32_t data[1];          /* count-1 number of words */
+};
+
+/**
+ * struct ert_init_kernel_cmd: ERT initialize kernel command format
+ * this command initializes CUs by writing CU registers. CUs are
+ * represented by cu_mask and extra_cu_masks.
+ *
+ * @state:           [3-0]   current state of a command
+ * @update_rtp:      [4]     command is for runtime update of cu argument
+ * @extra_cu_masks:  [11-10] extra CU masks in addition to mandatory mask
+ * @count:           [22-12] number of words following header
+ * @opcode:          [27-23] 0, opcode for init_kernel
+ * @type:            [31-27] 0, type of init_kernel
+ *
+ * @cu_run_timeout   the configured CU timeout value in Microseconds
+ *                   setting to 0 means CU should not timeout
+ * @cu_reset_timeout the configured CU reset timeout value in Microseconds
+ *                   when CU timeout, CU will be reset. this indicates
+ *                   CU reset should be completed within the timeout value.
+ *                   if cu_run_timeout is set to 0, this field is undefined.
+ *
+ * @cu_mask:         first mandatory CU mask
+ * @data:            count-9 number of words representing interpreted payload
+ *
+ * The packet payload is comprised of reserved id field, 8 reserved fields,
+ * a mandatory CU mask, and extra_cu_masks per header field, followed by a
+ * CU register map of size (count - (9 + extra_cu_masks)) uint32_t words.
+ */
+struct ert_init_kernel_cmd {
+  union {
+    struct {
+      uint32_t state:4;          /* [3-0]   */
+      uint32_t update_rtp:1;     /* [4]  */
+      uint32_t unused:5;         /* [9-5]  */
+      uint32_t extra_cu_masks:2; /* [11-10]  */
+      uint32_t count:11;         /* [22-12] */
+      uint32_t opcode:5;         /* [27-23] */
+      uint32_t type:4;           /* [31-27] */
+    };
+    uint32_t header;
+  };
+
+  uint32_t cu_run_timeout;   /* CU timeout value in Microseconds */
+  uint32_t cu_reset_timeout; /* CU reset timeout value in Microseconds */
+  uint32_t reserved[6];      /* reserved for future use */
+
+  /* payload */
+  uint32_t cu_mask;          /* mandatory cu mask */
+  uint32_t data[1];          /* count-9 number of words */
+};
+
+#define KDMA_BLOCK_SIZE 64   /* Limited by KDMA CU */
+struct ert_start_copybo_cmd {
+  uint32_t state:4;          /* [3-0], must be ERT_CMD_STATE_NEW */
+  uint32_t unused:6;         /* [9-4] */
+  uint32_t extra_cu_masks:2; /* [11-10], = 3 */
+  uint32_t count:11;         /* [22-12], = 16, exclude 'arg' */
+  uint32_t opcode:5;         /* [27-23], = ERT_START_COPYBO */
+  uint32_t type:4;           /* [31-27], = ERT_DEFAULT */
+  uint32_t cu_mask[4];       /* mandatory cu masks */
+  uint32_t reserved[4];      /* for scheduler use */
+  uint32_t src_addr_lo;      /* low 32 bit of src addr */
+  uint32_t src_addr_hi;      /* high 32 bit of src addr */
+  uint32_t src_bo_hdl;       /* src bo handle, cleared by driver */
+  uint32_t dst_addr_lo;      /* low 32 bit of dst addr */
+  uint32_t dst_addr_hi;      /* high 32 bit of dst addr */
+  uint32_t dst_bo_hdl;       /* dst bo handle, cleared by driver */
+  uint32_t size;             /* size in bytes low 32 bit*/
+  uint32_t size_hi;          /* size in bytes high 32 bit*/
+  void     *arg;             /* pointer to aux data for KDS */
+};
+
+/**
+ * struct ert_configure_cmd: ERT configure command format
+ *
+ * @state:           [3-0] current state of a command
+ * @count:           [22-12] number of words in payload (5 + num_cus)
+ * @opcode:          [27-23] 1, opcode for configure
+ * @type:            [31-27] 0, type of configure
+ *
+ * @slot_size:       command queue slot size
+ * @num_cus:         number of compute units in program
+ * @cu_shift:        shift value to convert CU idx to CU addr
+ * @cu_base_addr:    base address to add to CU addr for actual physical address
+ *
+ * @ert:1            enable embedded HW scheduler
+ * @polling:1        poll for command completion
+ * @cu_dma:1         enable CUDMA custom module for HW scheduler
+ * @cu_isr:1         enable CUISR custom module for HW scheduler
+ * @cq_int:1         enable interrupt from host to HW scheduler
+ * @cdma:1           enable CDMA kernel
+ * @unused:25
+ * @dsa52:1          reserved for internal use
+ *
+ * @data:            addresses of @num_cus CUs
+ */
+struct ert_configure_cmd {
+  union {
+    struct {
+      uint32_t state:4;          /* [3-0]   */
+      uint32_t unused:8;         /* [11-4]  */
+      uint32_t count:11;         /* [22-12] */
+      uint32_t opcode:5;         /* [27-23] */
+      uint32_t type:4;           /* [31-27] */
+    };
+    uint32_t header;
+  };
+
+  /* payload */
+  uint32_t slot_size;
+  uint32_t num_cus;
+  uint32_t cu_shift;
+  uint32_t cu_base_addr;
+
+  /* features */
+  uint32_t ert:1;
+  uint32_t polling:1;
+  uint32_t cu_dma:1;
+  uint32_t cu_isr:1;
+  uint32_t cq_int:1;
+  uint32_t cdma:1;
+  uint32_t dataflow:1;
+  /* WORKAROUND: allow xclRegWrite/xclRegRead access shared CU */
+  uint32_t rw_shared:1;
+  uint32_t kds_30:1;
+  uint32_t dmsg:1;
+  uint32_t unusedf:21;
+  uint32_t dsa52:1;
+
+  /* cu address map size is num_cus */
+  uint32_t data[1];
+};
+
+/**
+ * struct ert_configure_sk_cmd: ERT configure soft kernel command format
+ *
+ * @state:           [3-0] current state of a command
+ * @count:           [22-12] number of words in payload (13 DWords)
+ * @opcode:          [27-23] 1, opcode for configure
+ * @type:            [31-27] 0, type of configure
+ *
+ * @start_cuidx:     start index of compute units
+ * @sk_type:         type of soft kernel.
+ * @num_cus:         number of compute units in program
+ * @sk_size:         size in bytes of soft kernel image
+ * @sk_name:         symbol name of soft kernel
+ * @sk_addr:         soft kernel image's physical address (little endian)
+ */
+struct ert_configure_sk_cmd {
+  union {
+    struct {
+      uint32_t state:4;          /* [3-0]   */
+      uint32_t unused:8;         /* [11-4]  */
+      uint32_t count:11;         /* [22-12] */
+      uint32_t opcode:5;         /* [27-23] */
+      uint32_t type:4;           /* [31-27] */
+    };
+    uint32_t header;
+  };
+
+  /* payload */
+  uint32_t start_cuidx:16;
+  uint32_t sk_type:16;
+  uint32_t num_cus;
+  uint32_t sk_size;		/* soft kernel size */
+  uint32_t sk_name[8];		/* soft kernel name */
+  uint64_t sk_addr;
+};
+
+/**
+ * struct ert_unconfigure_sk_cmd: ERT unconfigure soft kernel command format
+ *
+ * @state:           [3-0] current state of a command
+ * @count:           [22-12] number of words in payload
+ * @opcode:          [27-23] 1, opcode for configure
+ * @type:            [31-27] 0, type of configure
+ *
+ * @start_cuidx:     start index of compute units
+ * @num_cus:         number of compute units in program
+ */
+struct ert_unconfigure_sk_cmd {
+  union {
+    struct {
+      uint32_t state:4;          /* [3-0]   */
+      uint32_t unused:8;         /* [11-4]  */
+      uint32_t count:11;         /* [22-12] */
+      uint32_t opcode:5;         /* [27-23] */
+      uint32_t type:4;           /* [31-27] */
+    };
+    uint32_t header;
+  };
+
+  /* payload */
+  uint32_t start_cuidx;
+  uint32_t num_cus;
+};
+
+/**
+ * struct ert_abort_cmd: ERT abort command format.
+ *
+ * @idx: The slot index of command to abort
+ */
+struct ert_abort_cmd {
+  union {
+    struct {
+      uint32_t state:4;          /* [3-0]   */
+      uint32_t unused:11;        /* [14-4]  */
+      uint32_t idx:8;            /* [22-15] */
+      uint32_t opcode:5;         /* [27-23] */
+      uint32_t type:4;           /* [31-27] */
+    };
+    uint32_t header;
+  };
+};
+
+/**
+ * ERT command state
+ *
+ * @ERT_CMD_STATE_NEW:         Set by host before submitting a command to
+ *                             scheduler
+ * @ERT_CMD_STATE_QUEUED:      Internal scheduler state
+ * @ERT_CMD_STATE_SUBMITTED:   Internal scheduler state
+ * @ERT_CMD_STATE_RUNNING:     Internal scheduler state
+ * @ERT_CMD_STATE_COMPLETE:    Set by scheduler when command completes
+ * @ERT_CMD_STATE_ERROR:       Set by scheduler if command failed
+ * @ERT_CMD_STATE_ABORT:       Set by scheduler if command abort
+ * @ERT_CMD_STATE_TIMEOUT:     Set by scheduler if command timeout and reset
+ * @ERT_CMD_STATE_NORESPONSE:  Set by scheduler if command timeout and fail to
+ *                             reset
+ */
+enum ert_cmd_state {
+  ERT_CMD_STATE_NEW = 1,
+  ERT_CMD_STATE_QUEUED = 2,
+  ERT_CMD_STATE_RUNNING = 3,
+  ERT_CMD_STATE_COMPLETED = 4,
+  ERT_CMD_STATE_ERROR = 5,
+  ERT_CMD_STATE_ABORT = 6,
+  ERT_CMD_STATE_SUBMITTED = 7,
+  ERT_CMD_STATE_TIMEOUT = 8,
+  ERT_CMD_STATE_NORESPONSE = 9,
+  ERT_CMD_STATE_MAX, // Always the last one
+};
+
+struct cu_cmd_state_timestamps {
+  uint64_t skc_timestamps[ERT_CMD_STATE_MAX]; // In nano-second
+};
+
+/**
+ * Opcode types for commands
+ *
+ * @ERT_START_CU:       start a workgroup on a CU
+ * @ERT_START_KERNEL:   currently aliased to ERT_START_CU
+ * @ERT_CONFIGURE:      configure command scheduler
+ * @ERT_EXEC_WRITE:     execute a specified CU after writing
+ * @ERT_CU_STAT:        get stats about CU execution
+ * @ERT_START_COPYBO:   start KDMA CU or P2P, may be converted to ERT_START_CU
+ *                      before cmd reach to scheduler, short-term hack
+ * @ERT_SK_CONFIG:      configure soft kernel
+ * @ERT_SK_START:       start a soft kernel
+ * @ERT_SK_UNCONFIG:    unconfigure a soft kernel
+ */
+enum ert_cmd_opcode {
+  ERT_START_CU      = 0,
+  ERT_START_KERNEL  = 0,
+  ERT_CONFIGURE     = 2,
+  ERT_EXIT          = 3,
+  ERT_ABORT         = 4,
+  ERT_EXEC_WRITE    = 5,
+  ERT_CU_STAT       = 6,
+  ERT_START_COPYBO  = 7,
+  ERT_SK_CONFIG     = 8,
+  ERT_SK_START      = 9,
+  ERT_SK_UNCONFIG   = 10,
+  ERT_INIT_CU       = 11,
+  ERT_START_FA      = 12,
+};
+
+/**
+ * Command types
+ *
+ * @ERT_DEFAULT:        default command type
+ * @ERT_KDS_LOCAL:      command processed by KDS locally
+ * @ERT_CTRL:           control command uses reserved command queue slot
+ * @ERT_CU:             compute unit command
+ */
+enum ert_cmd_type {
+  ERT_DEFAULT = 0,
+  ERT_KDS_LOCAL = 1,
+  ERT_CTRL = 2,
+  ERT_CU = 3,
+  ERT_SCU = 4,
+};
+
+/**
+ * Soft kernel types
+ *
+ * @SOFTKERNEL_TYPE_EXEC:       executable
+ */
+enum softkernel_type {
+  SOFTKERNEL_TYPE_EXEC = 0,
+};
+
+/*
+ * Base address GPIO per spec
+ * | Offset  | Description
+ * -----------------------
+ * | 0x00    | ERT_MGMT_PF_base_addr (Not sure where this should be use)
+ * | 0x08    | ERT_USER_PF_base_addr. The base address of ERT peripherals
+ */
+#if defined(ERT_BUILD_V20)
+uint32_t ert_base_addr = 0;
+# define ERT_BASE_ADDR                     0x01F30008
+#endif
+
+#if defined(ERT_BUILD_V30)
+uint32_t ert_base_addr = 0;
+# define ERT_BASE_ADDR                     0x01F30008
+#endif
+
+/**
+ * Address constants per spec
+ */
+#define ERT_WORD_SIZE                      4          /* 4 bytes */
+#define ERT_CQ_SIZE                        0x10000    /* 64K */
+#if defined(ERT_BUILD_U50)
+# define ERT_CQ_BASE_ADDR                  0x340000
+# define ERT_CSR_ADDR                      0x360000
+#elif defined(ERT_BUILD_V20)
+# define ERT_CQ_BASE_ADDR                  (0x000000 + ert_base_addr)
+# define ERT_CSR_ADDR                      (0x010000 + ert_base_addr)
+#elif defined(ERT_BUILD_V30)
+# define ERT_CQ_BASE_ADDR                  0x1F60000
+# define ERT_CSR_ADDR                      (0x010000 + ert_base_addr)
+#else
+# define ERT_CQ_BASE_ADDR                  0x190000
+# define ERT_CSR_ADDR                      0x180000
+#endif
+
+/**
+ * The STATUS REGISTER is for communicating completed CQ slot indices
+ * MicroBlaze write, host reads.  MB(W) / HOST(COR)
+ */
+#define ERT_STATUS_REGISTER_ADDR          (ERT_CSR_ADDR)
+#define ERT_STATUS_REGISTER_ADDR0         (ERT_CSR_ADDR)
+#define ERT_STATUS_REGISTER_ADDR1         (ERT_CSR_ADDR + 0x4)
+#define ERT_STATUS_REGISTER_ADDR2         (ERT_CSR_ADDR + 0x8)
+#define ERT_STATUS_REGISTER_ADDR3         (ERT_CSR_ADDR + 0xC)
+
+/**
+ * The CU DMA REGISTER is for communicating which CQ slot is to be started
+ * on a specific CU.  MB selects a free CU on which the command can
+ * run, then writes the 1<<CU back to the command slot CU mask and
+ * writes the slot index to the CU DMA REGISTER.  HW is notified when
+ * the register is written and now does the DMA transfer of CU regmap
+ * map from command to CU, while MB continues its work. MB(W) / HW(R)
+ */
+#define ERT_CU_DMA_ENABLE_ADDR            (ERT_CSR_ADDR + 0x18)
+#define ERT_CU_DMA_REGISTER_ADDR          (ERT_CSR_ADDR + 0x1C)
+#define ERT_CU_DMA_REGISTER_ADDR0         (ERT_CSR_ADDR + 0x1C)
+#define ERT_CU_DMA_REGISTER_ADDR1         (ERT_CSR_ADDR + 0x20)
+#define ERT_CU_DMA_REGISTER_ADDR2         (ERT_CSR_ADDR + 0x24)
+#define ERT_CU_DMA_REGISTER_ADDR3         (ERT_CSR_ADDR + 0x28)
+
+/**
+ * The SLOT SIZE is the size of slots in command queue, it is
+ * configurable per xclbin. MB(W) / HW(R)
+ */
+#define ERT_CQ_SLOT_SIZE_ADDR             (ERT_CSR_ADDR + 0x2C)
+
+/**
+ * The CU_OFFSET is the size of a CU's address map in power of 2.  For
+ * example a 64K regmap is 2^16 so 16 is written to the CU_OFFSET_ADDR.
+ * MB(W) / HW(R)
+ */
+#define ERT_CU_OFFSET_ADDR                (ERT_CSR_ADDR + 0x30)
+
+/**
+ * The number of slots is command_queue_size / slot_size.
+ * MB(W) / HW(R)
+ */
+#define ERT_CQ_NUMBER_OF_SLOTS_ADDR       (ERT_CSR_ADDR + 0x34)
+
+/**
+ * All CUs placed in same address space separated by CU_OFFSET. The
+ * CU_BASE_ADDRESS is the address of the first CU. MB(W) / HW(R)
+ */
+#define ERT_CU_BASE_ADDRESS_ADDR          (ERT_CSR_ADDR + 0x38)
+
+/**
+ * The CQ_BASE_ADDRESS is the base address of the command queue.
+ * MB(W) / HW(R)
+ */
+#define ERT_CQ_BASE_ADDRESS_ADDR          (ERT_CSR_ADDR + 0x3C)
+
+/**
+ * The CU_ISR_HANDLER_ENABLE (MB(W)/HW(R)) enables the HW handling of
+ * CU interrupts.  When a CU interrupts (when done), hardware handles
+ * the interrupt and writes the index of the CU that completed into
+ * the CU_STATUS_REGISTER (HW(W)/MB(COR)) as a bitmask
+ */
+#define ERT_CU_ISR_HANDLER_ENABLE_ADDR    (ERT_CSR_ADDR + 0x40)
+#define ERT_CU_STATUS_REGISTER_ADDR       (ERT_CSR_ADDR + 0x44)
+#define ERT_CU_STATUS_REGISTER_ADDR0      (ERT_CSR_ADDR + 0x44)
+#define ERT_CU_STATUS_REGISTER_ADDR1      (ERT_CSR_ADDR + 0x48)
+#define ERT_CU_STATUS_REGISTER_ADDR2      (ERT_CSR_ADDR + 0x4C)
+#define ERT_CU_STATUS_REGISTER_ADDR3      (ERT_CSR_ADDR + 0x50)
+
+/**
+ * The CQ_STATUS_ENABLE (MB(W)/HW(R)) enables interrupts from HOST to
+ * MB to indicate the presense of a new command in some slot.  The
+ * slot index is written to the CQ_STATUS_REGISTER (HOST(W)/MB(R))
+ */
+#define ERT_CQ_STATUS_ENABLE_ADDR         (ERT_CSR_ADDR + 0x54)
+#define ERT_CQ_STATUS_REGISTER_ADDR       (ERT_CSR_ADDR + 0x58)
+#define ERT_CQ_STATUS_REGISTER_ADDR0      (ERT_CSR_ADDR + 0x58)
+#define ERT_CQ_STATUS_REGISTER_ADDR1      (ERT_CSR_ADDR + 0x5C)
+#define ERT_CQ_STATUS_REGISTER_ADDR2      (ERT_CSR_ADDR + 0x60)
+#define ERT_CQ_STATUS_REGISTER_ADDR3      (ERT_CSR_ADDR + 0x64)
+
+/**
+ * The NUMBER_OF_CU (MB(W)/HW(R) is the number of CUs per current
+ * xclbin.  This is an optimization that allows HW to only check CU
+ * completion on actual CUs.
+ */
+#define ERT_NUMBER_OF_CU_ADDR             (ERT_CSR_ADDR + 0x68)
+
+/**
+ * Enable global interrupts from MB to HOST on command completion.
+ * When enabled writing to STATUS_REGISTER causes an interrupt in HOST.
+ * MB(W)
+ */
+#define ERT_HOST_INTERRUPT_ENABLE_ADDR    (ERT_CSR_ADDR + 0x100)
+
+/**
+ * Interrupt controller base address
+ * This value is per hardware BSP (XPAR_INTC_SINGLE_BASEADDR)
+ */
+#if defined(ERT_BUILD_U50)
+# define ERT_INTC_ADDR                     0x00310000
+#elif defined(ERT_BUILD_V20)
+# define ERT_INTC_ADDR                     0x01F20000
+#elif defined(ERT_BUILD_V30)
+# define ERT_INTC_ADDR                     0x01F20000
+# define ERT_INTC_CU_0_31_ADDR             (0x0000 + ert_base_addr)
+# define ERT_INTC_CU_32_63_ADDR            (0x1000 + ert_base_addr)
+# define ERT_INTC_CU_64_95_ADDR            (0x2000 + ert_base_addr)
+# define ERT_INTC_CU_96_127_ADDR           (0x3000 + ert_base_addr)
+#else
+# define ERT_INTC_ADDR                     0x41200000
+# define ERT_INTC_CU_0_31_ADDR             0x0000
+# define ERT_INTC_CU_32_63_ADDR            0x1000
+# define ERT_INTC_CU_64_95_ADDR            0x2000
+# define ERT_INTC_CU_96_127_ADDR           0x3000
+#endif
+
+/**
+ * Look up table for CUISR for CU addresses
+ */
+#define ERT_CUISR_LUT_ADDR                (ERT_CSR_ADDR + 0x400)
+
+/**
+ * ERT exit command/ack
+ */
+#define	ERT_EXIT_CMD			  ((ERT_EXIT << 23) | ERT_CMD_STATE_NEW)
+#define	ERT_EXIT_ACK			  (ERT_CMD_STATE_COMPLETED)
+#define	ERT_EXIT_CMD_OP			  (ERT_EXIT << 23)
+
+/**
+ * State machine for both CUDMA and CUISR modules
+ */
+#define ERT_HLS_MODULE_IDLE               0x1
+#define ERT_CUDMA_STATE                   (ERT_CSR_ADDR + 0x318)
+#define ERT_CUISR_STATE                   (ERT_CSR_ADDR + 0x328)
+
+/**
+ * Interrupt address masks written by MB when interrupts from
+ * CU are enabled
+ */
+#define ERT_INTC_IPR_ADDR                 (ERT_INTC_ADDR + 0x4)  /* pending */
+#define ERT_INTC_IER_ADDR                 (ERT_INTC_ADDR + 0x8)  /* enable */
+#define ERT_INTC_IAR_ADDR                 (ERT_INTC_ADDR + 0x0C) /* acknowledge */
+#define ERT_INTC_MER_ADDR                 (ERT_INTC_ADDR + 0x1C) /* master enable */
+
+#define ERT_INTC_CU_0_31_IPR              (ERT_INTC_CU_0_31_ADDR + 0x4)  /* pending */
+#define ERT_INTC_CU_0_31_IER              (ERT_INTC_CU_0_31_ADDR + 0x8)  /* enable */
+#define ERT_INTC_CU_0_31_IAR              (ERT_INTC_CU_0_31_ADDR + 0x0C) /* acknowledge */
+#define ERT_INTC_CU_0_31_MER              (ERT_INTC_CU_0_31_ADDR + 0x1C) /* master enable */
+
+#define ERT_INTC_CU_32_63_IPR             (ERT_INTC_CU_32_63_ADDR + 0x4)  /* pending */
+#define ERT_INTC_CU_32_63_IER             (ERT_INTC_CU_32_63_ADDR + 0x8)  /* enable */
+#define ERT_INTC_CU_32_63_IAR             (ERT_INTC_CU_32_63_ADDR + 0x0C) /* acknowledge */
+#define ERT_INTC_CU_32_63_MER             (ERT_INTC_CU_32_63_ADDR + 0x1C) /* master enable */
+
+#define ERT_INTC_CU_64_95_IPR             (ERT_INTC_CU_64_95_ADDR + 0x4)  /* pending */
+#define ERT_INTC_CU_64_95_IER             (ERT_INTC_CU_64_95_ADDR + 0x8)  /* enable */
+#define ERT_INTC_CU_64_95_IAR             (ERT_INTC_CU_64_95_ADDR + 0x0C) /* acknowledge */
+#define ERT_INTC_CU_64_95_MER             (ERT_INTC_CU_64_95_ADDR + 0x1C) /* master enable */
+
+#define ERT_INTC_CU_96_127_IPR            (ERT_INTC_CU_96_127_ADDR + 0x4)  /* pending */
+#define ERT_INTC_CU_96_127_IER            (ERT_INTC_CU_96_127_ADDR + 0x8)  /* enable */
+#define ERT_INTC_CU_96_127_IAR            (ERT_INTC_CU_96_127_ADDR + 0x0C) /* acknowledge */
+#define ERT_INTC_CU_96_127_MER            (ERT_INTC_CU_96_127_ADDR + 0x1C) /* master enable */
+
+/*
+* Used in driver and user space code
+* Upper limit on number of dependencies in execBuf waitlist
+*/
+#define MAX_DEPS        8
+
+/*
+ * Helper functions to hide details of ert_start_copybo_cmd
+ */
+static inline void
+ert_fill_copybo_cmd(struct ert_start_copybo_cmd *pkt, uint32_t src_bo,
+  uint32_t dst_bo, uint64_t src_offset, uint64_t dst_offset, uint32_t size)
+{
+  pkt->state = ERT_CMD_STATE_NEW;
+  pkt->extra_cu_masks = 3;
+  pkt->count = 16;
+  pkt->opcode = ERT_START_COPYBO;
+  pkt->type = ERT_DEFAULT;
+  pkt->cu_mask[0] = 0;
+  pkt->cu_mask[1] = 0;
+  pkt->cu_mask[2] = 0;
+  pkt->cu_mask[3] = 0;
+  pkt->src_addr_lo = (uint32_t)src_offset;
+  pkt->src_addr_hi = (src_offset >> 32) & 0xFFFFFFFF;
+  pkt->src_bo_hdl = src_bo;
+  pkt->dst_addr_lo = (uint32_t)dst_offset;
+  pkt->dst_addr_hi = (dst_offset >> 32) & 0xFFFFFFFF;
+  pkt->dst_bo_hdl = dst_bo;
+  pkt->size = size;
+  pkt->size_hi = 0; /* set to 0 explicitly */
+  pkt->arg = 0;
+}
+static inline uint64_t
+ert_copybo_src_offset(struct ert_start_copybo_cmd *pkt)
+{
+  return (uint64_t)pkt->src_addr_hi << 32 | pkt->src_addr_lo;
+}
+static inline uint64_t
+ert_copybo_dst_offset(struct ert_start_copybo_cmd *pkt)
+{
+  return (uint64_t)pkt->dst_addr_hi << 32 | pkt->dst_addr_lo;
+}
+static inline uint64_t
+ert_copybo_size(struct ert_start_copybo_cmd *pkt)
+{
+  return pkt->size;
+}
+
+#ifdef __GNUC__
+#define P2ROUNDUP(x, align)     (-(-(x) & -(align)))
+static inline struct cu_cmd_state_timestamps *
+ert_start_kernel_timestamps(struct ert_start_kernel_cmd *pkt)
+{
+  uint64_t offset = pkt->count * sizeof(uint32_t) + sizeof(pkt->header);
+  /* Make sure the offset of timestamps are properly aligned. */
+  return (struct cu_cmd_state_timestamps *)
+    ((char *)pkt + P2ROUNDUP(offset, sizeof(uint64_t)));
+}
+#endif
+
+#ifdef _WIN32
+# pragma warning( pop )
+#endif
+
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/include/kds_command.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/include/kds_command.h
@@ -0,0 +1,88 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * Xilinx Kernel Driver Scheduler
+ *
+ * Copyright (C) 2020 Xilinx, Inc. All rights reserved.
+ *
+ * Authors: min.ma@xilinx.com
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#ifndef _KDS_COMMAND_H
+#define _KDS_COMMAND_H
+
+/* Userspace command format */
+#include "ert.h"
+
+#define REGMAP 0
+#define KEY_VAL 1
+
+enum kds_opcode {
+	OP_CONFIG = 0,
+	OP_START,
+};
+
+enum kds_status {
+	KDS_COMPLETED	= 0,
+	KDS_ERROR	= 1,
+	KDS_ABORT,
+	KDS_TIMEOUT,
+};
+
+struct kds_command;
+
+struct kds_cmd_ops {
+	void (*notify_host)(struct kds_command *xcmd, int status);
+	void (*free)(struct kds_command *xcmd);
+};
+
+struct in_kernel_cb {
+	struct work_struct work;
+	void (*func)(unsigned long cb_data, int err);
+	void *data;
+	int  cmd_state;
+};
+
+/**
+ * struct kds_command: KDS command struct
+ * @client: the client that the command belongs to
+ * @type:   type of the command. Use this to determin controller
+ */
+struct kds_command {
+	struct kds_client	*client;
+	u32			cu_idx;
+	u32			 type;
+	u32			 opcode;
+	struct list_head	 list;
+	void			*info;
+	size_t			 isize;
+	/* TODO: may rethink if we should have cu bit mask here
+	 * or move it to info.
+	 * Since NO all types of command have cu_mask
+	 */
+	u32			 cu_mask[4];
+	u32			 num_mask;
+	u32			 payload_type;
+	u64			 start;
+	struct kds_cmd_ops	 cb;
+	/* execbuf is used to update the header
+	 * of execbuf when notifying host
+	 */
+	u32			*execbuf;
+	void			*gem_obj;
+	/* to notify inkernel exec completion */
+	struct in_kernel_cb	*inkern_cb;
+};
+
+/* execbuf command related funtions */
+void cfg_ecmd2xcmd(struct ert_configure_cmd *ecmd,
+		   struct kds_command *xcmd);
+void start_krnl_ecmd2xcmd(struct ert_start_kernel_cmd *ecmd,
+			  struct kds_command *xcmd);
+void start_fa_ecmd2xcmd(struct ert_start_kernel_cmd *ecmd,
+			struct kds_command *xcmd);
+int cu_mask_to_cu_idx(struct kds_command *xcmd, uint8_t *cus);
+
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/include/kds_core.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/include/kds_core.h
@@ -0,0 +1,180 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * Xilinx Kernel Driver Scheduler
+ *
+ * Copyright (C) 2020 Xilinx, Inc. All rights reserved.
+ *
+ * Authors: min.ma@xilinx.com
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#ifndef _KDS_CORE_H
+#define _KDS_CORE_H
+
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/pid.h>
+#include <linux/device.h>
+#include <linux/uuid.h>
+
+#include "kds_command.h"
+#include "xrt_cu.h"
+
+#define kds_info(client, fmt, args...)			\
+	dev_info(client->dev, " %llx %s: "fmt, (u64)client->dev, __func__, ##args)
+#define kds_err(client, fmt, args...)			\
+	dev_err(client->dev, " %llx %s: "fmt, (u64)client->dev, __func__, ##args)
+#define kds_dbg(client, fmt, args...)			\
+	dev_dbg(client->dev, " %llx %s: "fmt, (u64)client->dev, __func__, ##args)
+
+#define PRE_ALLOC 0
+
+enum kds_type {
+	KDS_CU		= 0,
+	KDS_ERT,
+	KDS_MAX_TYPE, // always the last one
+};
+
+/* Context properties */
+#define	CU_CTX_PROP_MASK	0x0F
+#define	CU_CTX_SHARED		0x00
+#define	CU_CTX_EXCLUSIVE	0x01
+
+/* Virtual CU index
+ * This is useful when there is no need to open a context on hardware CU,
+ * but still need to lockdown the xclbin.
+ */
+#define	CU_CTX_VIRT_CU		0xffffffff
+struct kds_ctx_info {
+	u32		  cu_idx;
+	u32		  flags;
+};
+
+/**
+ * struct kds_client: Manage user client
+ * Whenever user applciation open the device, a client would be created.
+ * A client will keep alive util application close the device or being killed.
+ * The client could open multiple contexts to access compute resources.
+ *
+ * @link: Client is added to list in KDS scheduler
+ * @dev:  Device
+ * @pid:  Client process ID
+ * @lock: Mutex to protext context related members
+ * @xclbin_id: UUID of xclbin cache
+ * @num_ctx: Number of context that opened
+ * @virt_cu_ref: Reference count of virtual CU
+ * @cu_bitmap: bitmap of opening CU
+ * @waitq: Wait queue for poll client
+ * @event: Events to notify user client
+ */
+struct kds_client {
+	struct list_head	  link;
+	struct device	         *dev;
+	struct pid	         *pid;
+	struct mutex		  lock;
+	void			 *xclbin_id;
+	int			  num_ctx;
+	int			  virt_cu_ref;
+	DECLARE_BITMAP(cu_bitmap, MAX_CUS);
+#if PRE_ALLOC
+	u32			  max_xcmd;
+	u32			  xcmd_idx;
+	void			 *xcmds;
+	void			 *infos;
+#endif
+	/*
+	 * "waitq" and "event" are modified in thread that is completing them.
+	 * In order to prevent false sharing, they need to be in different
+	 * cache lines. Hence we add a "padding" in between (assuming 128-byte
+	 * is big enough for most CPU architectures).
+	 */
+	u64			  padding[16];
+	wait_queue_head_t	  waitq;
+	atomic_t		  event;
+};
+
+/* the MSB of cu_refs is used for exclusive flag */
+#define CU_EXCLU_MASK		0x80000000
+struct kds_cu_mgmt {
+	struct xrt_cu		 *xcus[MAX_CUS];
+	struct mutex		  lock;
+	int			  num_cus;
+	int			  num_cdma;
+	u32			  cu_intr[MAX_CUS];
+	u32			  cu_refs[MAX_CUS];
+	u64			  cu_usage[MAX_CUS];
+	int			  configured;
+};
+
+/* ERT core */
+struct kds_ert {
+	void (* submit)(struct kds_ert *ert, struct kds_command *xcmd);
+};
+
+struct plram_info {
+	/* This is use for free bo, do not use it in shared code */
+	void		       *bo;
+	u64			bar_paddr;
+	u64			dev_paddr;
+	void __iomem		*vaddr;
+	u32			size;
+};
+
+/**
+ * struct kds_sched: KDS scheduler manage CUs and client list.
+ *		     There should be only one KDS per device.
+ *
+ * @list_head: Client list
+ * @num_client: Number of clients
+ * @lock: Mutex to protect client list
+ * @cu_mgmt: hardware CUs management data structure
+ * @ert: remote scheduler
+ * @ert_disable: remote scheduler is disabled or not
+ * @cu_intr_cap: capbility of CU interrupt support
+ * @cu_intr: CU or ERT interrupt. 1 for CU, 0 for ERT.
+ */
+struct kds_sched {
+	struct list_head	clients;
+	int			num_client;
+	struct mutex		lock;
+	bool			bad_state;
+	struct kds_cu_mgmt	cu_mgmt;
+	struct kds_ert	       *ert;
+	bool			ini_disable;
+	bool			ert_disable;
+	u32			cu_intr_cap;
+	u32			cu_intr;
+	struct plram_info	plram;
+};
+
+int kds_init_sched(struct kds_sched *kds);
+int kds_init_ert(struct kds_sched *kds, struct kds_ert *ert);
+int kds_init_client(struct kds_sched *kds, struct kds_client *client);
+void kds_fini_sched(struct kds_sched *kds);
+int kds_fini_ert(struct kds_sched *kds);
+void kds_fini_client(struct kds_sched *kds, struct kds_client *client);
+void kds_reset(struct kds_sched *kds);
+int kds_cfg_update(struct kds_sched *kds);
+int is_bad_state(struct kds_sched *kds);
+u32 kds_live_clients(struct kds_sched *kds, pid_t **plist);
+u32 kds_live_clients_nolock(struct kds_sched *kds, pid_t **plist);
+int kds_add_cu(struct kds_sched *kds, struct xrt_cu *xcu);
+int kds_del_cu(struct kds_sched *kds, struct xrt_cu *xcu);
+int kds_add_context(struct kds_sched *kds, struct kds_client *client,
+		    struct kds_ctx_info *info);
+int kds_del_context(struct kds_sched *kds, struct kds_client *client,
+		    struct kds_ctx_info *info);
+int kds_add_command(struct kds_sched *kds, struct kds_command *xcmd);
+
+struct kds_command *kds_alloc_command(struct kds_client *client, u32 size);
+
+void kds_free_command(struct kds_command *xcmd);
+
+/* sysfs */
+int store_kds_echo(struct kds_sched *kds, const char *buf, size_t count,
+		   int kds_mode, u32 clients, int *echo);
+ssize_t show_kds_stat(struct kds_sched *kds, char *buf);
+ssize_t show_kds_custat_raw(struct kds_sched *kds, char *buf);
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/include/sched_exec.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/include/sched_exec.h
@@ -0,0 +1,288 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * Compute unit execution, interrupt management and
+ * client context core data structures.
+ *
+ * Copyright (C) 2017-2020 Xilinx, Inc. All rights reserved.
+ *
+ * Authors:
+ *    Sonal Santan <sonal.santan@xilinx.com>
+ *    Min Ma <min.ma@xilinx.com>
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#ifndef _XCL_SCHE_EXEC_H_
+#define _XCL_SCHE_EXEC_H_
+
+#include <linux/mutex.h>
+#include <linux/init_task.h>
+#include <linux/list.h>
+#include <linux/wait.h>
+#include "zocl_drv.h"
+#include "zocl_cu.h"
+#include "ert.h"
+
+#define MAX_SLOTS 128
+#define MAX_U32_SLOT_MASKS (((MAX_SLOTS-1)>>5) + 1)
+/* MAX_CU_NUM are defined in zocl_util.h */
+#define MAX_U32_CU_MASKS (((MAX_CU_NUM-1)>>5) + 1)
+
+/* Timer thread wake up interval in Millisecond */
+#define	ZOCL_CU_TIMER_INTERVAL		(500)
+
+/* Reset timer interval in Microsecond */
+#define	ZOCL_CU_RESET_TIMER_INTERVAL	(1000)
+
+/*
+ * For zocl cu version 1. The done counter will have risk to overflow
+ * if more than 31 commands done but kds still not able to read done counter.
+ * TBD. This is related to the hardware implementation.
+ */
+#define MAX_PENDING_CMD         31
+
+/**
+ * Timestamp only use in set_cmd_ext_timestamp()
+ */
+enum zocl_ts_type {
+	CU_START_TIME,
+	CU_DONE_TIME,
+};
+
+enum zocl_cu_type {
+	ZOCL_HARD_CU,
+	ZOCL_SOFT_CU,
+};
+
+enum zocl_exec_status {
+	ZOCL_EXEC_NORMAL = 0,
+	ZOCL_EXEC_STOP,
+	ZOCL_EXEC_FLUSH,
+};
+
+struct sched_dev;
+struct sched_ops;
+
+/*
+ * struct sched_client_ctx: Manage user space client attached to device
+ *
+ * @link: Client context is added to list in device
+ * @trigger: Poll wait counter for number of completed exec buffers
+ * @outstanding_execs: Counter for number outstanding exec buffers
+ * @lock: Mutex lock for exclusive access
+ * @num_cus: Number of resources (CUs) explcitly acquired
+ * @pid: process ID that this context belongs to
+ * @abort: Flag to indicate that this context has detached from user space
+ * @shcus: CUs shared reserved by this context
+ * @excus: CUs exclusively reserved by this context
+ */
+struct sched_client_ctx {
+	struct list_head   link;
+	atomic_t           trigger;
+	atomic_t           outstanding_execs;
+	struct mutex       lock;
+	int		   num_cus;
+	struct pid	   *pid;
+	unsigned int	   abort;
+	DECLARE_BITMAP(shcus, MAX_CU_NUM);
+	DECLARE_BITMAP(excus, MAX_CU_NUM);
+};
+#define CLIENT_NUM_CU_CTX(client) ((client)->num_cus)
+
+/**
+ * struct sched_exec_core: Core data structure for command execution on a device
+ *
+ * @ctx_list: Context list populated with device context
+ * @ctx_list_lock: Context list lock
+ * @poll_wait_queue: Wait queue for device polling
+ * @scheduler: Command queue scheduler
+ * @submitted_cmds: Tracking of command submitted for execution on this device
+ * @num_slots: Number of command queue slots
+ * @num_cus: Number of CUs in loaded program
+ * @cu_shift_offset: CU idx to CU address shift value
+ * @cu_base_addr: Base address of CU address space
+ * @polling_mode: If set then poll for command completion
+ * @cq_interrupt: If set then X86 host will trigger interrupt to PS
+ * @configured: Flag of the core data structure has been initialized
+ * @slot_status: Status (busy(1)/free(0)) of slots in command queue
+ * @num_slot_masks: Number of slots status masks used
+ * @cu_status: Status (busy(1)/free(0)) of CUs. Unused in ERT mode.
+ * @num_cu_masks: Number of CU masks used (computed from @num_cus)
+ * @cu_addr_phy: Physical address of CUs.
+ * @cu: Per CU structure.
+ * @ops: Scheduler operations vtable
+ * @cq_thread: Kernel thread to check the ert command queue.
+ * @timer_task: Kernel thread as a timer interrupt.
+ */
+struct sched_exec_core {
+	void __iomem               *base;
+	struct list_head           ctx_list;
+	spinlock_t                 ctx_list_lock;
+	wait_queue_head_t          poll_wait_queue;
+
+	struct scheduler          *scheduler;
+
+	struct sched_cmd          *submitted_cmds[MAX_SLOTS];
+
+	unsigned int               num_slots;
+	unsigned int               num_cus;
+	unsigned int               cu_shift_offset;
+	u32                        cu_base_addr;
+	unsigned int               polling_mode;
+	unsigned int               cq_interrupt;
+	unsigned int               cu_dma;
+	unsigned int               cu_isr;
+	unsigned int               configured;
+
+
+	/* Bitmap tracks busy(1)/free(0) slots in cmd_slots*/
+	u32                        slot_status[MAX_U32_SLOT_MASKS];
+	unsigned int               num_slot_masks; /* ((num_slots-1)>>5)+1 */
+
+	/* Bitmap tracks CU busy(1)/free(0) */
+	u32                        cu_status[MAX_U32_CU_MASKS];
+	unsigned int               num_cu_masks; /* ((num_cus-1)>>5+1 */
+
+	/* Bitmap tracks CU initialization initialized(1)/uninitialized(0) */
+	u32                        cu_init[MAX_U32_CU_MASKS];
+
+	/* Soft kernel definitions */
+	u32                        scu_status[MAX_U32_CU_MASKS];
+
+	/* Bitmap tracks valid CU valid(1)/invalid(0) */
+	u32			   cu_valid[MAX_U32_CU_MASKS];
+
+	struct zocl_cu		  *zcu;
+
+	struct sched_ops          *ops;
+	struct task_struct        *cq_thread;
+	wait_queue_head_t          cq_wait_queue;
+
+	struct task_struct        *timer_task;
+
+	/* Context switch */
+	atomic_t		  exec_status;
+};
+
+/**
+ * struct scheduler: scheduler for sched_cmd objects
+ *
+ * @sched_thread: thread associated with this scheduler
+ * @use_count: use count for this scheduler
+ * @wait_queue: conditional wait queue for scheduler thread
+ * @error: set to 1 to indicate scheduler error
+ * @stop: set to 1 to indicate scheduler should stop
+ * @cq: list of command objects managed by scheduler
+ * @intc: set when there is a pending interrupt for command completion
+ * @poll: number of running commands in polling mode
+ * @check: flag to indicate a CU timerout check
+ */
+struct scheduler {
+	struct task_struct        *sched_thread;
+	unsigned int               use_count;
+	// KDS CMD Stats
+	atomic_t 		   num_pending;
+	atomic_t 		   num_running;
+	atomic_t 		   num_received;
+	atomic_t 		   num_notified;
+
+	wait_queue_head_t          wait_queue;
+	unsigned int               error;
+	unsigned int               stop;
+
+	struct list_head           cq;
+	unsigned int               intc; /* pending intr shared with isr*/
+	unsigned int               poll; /* number of cmds to poll */
+	atomic_t                   check;
+};
+
+/**
+ * Command data used by scheduler
+ *
+ * @list: command object moves from list to list
+ * @exec: core data structure for scheduler
+ * @state: state of command object per scheduling
+ * @cu_idx: index of CU executing this cmd object; used in penguin mode only
+ * @slot_idx: command queue index of this command object
+ * @buffer: underlying buffer (ex. drm buffer object)
+ * @exectime: time unit elapsed after CU is triggered to run
+ * @packet: mapped ert packet object from user space
+ * @check_timeout: flag to indicate if we should check timeout on this CU
+ */
+struct sched_cmd {
+	struct list_head list;
+	struct list_head rq_list;
+	struct drm_device *ddev;
+	struct scheduler *sched;
+	struct sched_exec_core *exec;
+	struct sched_client_ctx *client;
+	enum ert_cmd_state state;
+	int cu_idx; /* running cu, initialized to -1 */
+	int slot_idx;
+	int cq_slot_idx;
+	void *buffer;
+	void (*free_buffer)(struct sched_cmd *xcmd);
+
+	/*
+	 * This is a rough time unit elapsed after the CU is running.
+	 * It is set to a initial value configured by init CU command
+	 * and decreased every time unit. If it reaches zero, this CU
+	 * timeouts.
+	 *
+	 * The time unit is 500 Milliseconds now.
+	 */
+	uint32_t exectime;
+
+	/*
+	 * If this flag is set, we should check the timeout of this
+	 * command. It is set based on the CU timeout value. If the
+	 * timeout value is 0, we should not set this flag.
+	 */
+	int check_timeout;
+
+	/*
+	 * If this flag is set, record time stamps in the user's command
+	 * package when the command state change.
+	 */
+	bool timestamp_enabled;
+
+	/* The actual cmd object representation */
+	union {
+		struct ert_packet *packet;
+		struct ert_start_copybo_cmd *ert_cp;
+		struct ert_start_kernel_cmd *ert_cu;
+	};
+
+	zocl_dma_handle_t dma_handle;
+};
+
+/**
+ * struct sched_ops: scheduler specific operations
+ *
+ * Scheduler can operate in MicroBlaze mode (mb/ert) or in penguin mode. This
+ * struct differentiates specific operations.  The struct is per device node,
+ * meaning that one device can operate in ert mode while another can operate in
+ * penguin mode.
+ */
+struct sched_ops {
+	int (*submit)(struct sched_cmd *xcmd);
+	void (*query)(struct sched_cmd *xcmd);
+};
+
+int sched_init_exec(struct drm_device *drm);
+int sched_fini_exec(struct drm_device *drm);
+int sched_reset_exec(struct drm_device *drm);
+int sched_reset_scheduler(struct drm_device *drm);
+
+void zocl_track_ctx(struct drm_device *dev, struct sched_client_ctx *fpriv);
+void zocl_untrack_ctx(struct drm_device *dev, struct sched_client_ctx *fpriv);
+
+int zocl_exec_valid_cu(struct sched_exec_core *exec, unsigned int cuid);
+u32 sched_is_busy(struct drm_zocl_dev *zdev);
+u32 sched_live_clients(struct drm_zocl_dev *zdev, pid_t **plist);
+int sched_attach_cu(struct drm_zocl_dev *zdev, int cu_idx);
+int sched_detach_cu(struct drm_zocl_dev *zdev, int cu_idx);
+int zocl_execbuf_exec(struct drm_device *dev, void *data,
+		      struct drm_file *filp);
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/include/xclbin.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/include/xclbin.h
@@ -0,0 +1,542 @@
+/**
+ *  Copyright (C) 2015-2020, Xilinx Inc
+ *
+ *  This file is dual licensed.  It may be redistributed and/or modified
+ *  under the terms of the Apache 2.0 License OR version 2 of the GNU
+ *  General Public License.
+ *
+ *  Apache License Verbiage
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  GPL license Verbiage:
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef _XCLBIN_H_
+#define _XCLBIN_H_
+
+#ifdef _WIN32
+  #include <cstdint>
+  #include <algorithm>
+  #include "windows/uuid.h"
+#else
+  #if defined(__KERNEL__)
+    #include <linux/types.h>
+    #include <linux/uuid.h>
+    #include <linux/version.h>
+  #elif defined(__cplusplus)
+    #include <cstdlib>
+    #include <cstdint>
+    #include <algorithm>
+    #include <uuid/uuid.h>
+  #else
+    #include <stdlib.h>
+    #include <stdint.h>
+    #include <uuid/uuid.h>
+  #endif
+
+  #if !defined(__KERNEL__)
+    typedef uuid_t xuid_t;
+  #else //(__KERNEL__)
+    #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+      typedef uuid_t xuid_t;
+    #elif defined(RHEL_RELEASE_CODE)
+      #if RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(7,4)
+        typedef uuid_t xuid_t;
+      #else
+        typedef uuid_le xuid_t;
+      #endif
+    #else
+      typedef uuid_le xuid_t;
+    #endif
+  #endif
+#endif
+
+// ----------------- Custom Assert Macro -------------------------
+// The xclbin.h header file is used both by the driver and host
+// applications/libraries.  For C++ static_assert() would be used, but
+// for the the drivers (e.g., linux) a more custom solution is needed
+// e.g., BUILD_BUG_ON_ZERO()).  Instead of creating a wrapper around the
+// various OS builds, a custom assert (based on the linux assert) is used.
+
+#ifdef __cplusplus
+  // Used C++ static assert
+  #define XCLBIN_STATIC_ASSERT(e,m) \
+    static_assert (e, m)
+#else
+  // Use our "custom" kernel compilation assert
+  #define XLCBIN_ASSERT_CONCAT_(a, b) a##b
+  #define XLCBIN_ASSERT_CONCAT(a, b) XLCBIN_ASSERT_CONCAT_(a, b)
+
+  // Create an artifitial assertion via a bad divide by zero assertion.
+  #define XCLBIN_STATIC_ASSERT(e,m) \
+    enum { XLCBIN_ASSERT_CONCAT(assert_line_, __LINE__) = 1/(int)(!!(e)) }
+#endif
+
+// Reports a size of structure via an error
+#define SIZE_OF_STRUCT(s) \
+   char (*__fail)[sizeof(struct s)] = 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+    /**
+     * Container format for Xilinx bitstreams, metadata and other
+     * binary blobs.
+     * Every segment must be aligned at 8 byte boundary with null byte padding
+     * between adjacent segments if required.
+     * For segements which are not present both offset and length must be 0 in
+     * the header.
+     * Currently only xclbin0\0 is recognized as file magic. In future if/when file
+     * format is updated the magic string will be changed to xclbin1\0 and so on.
+     */
+    enum XCLBIN_MODE {
+        XCLBIN_FLAT,
+        XCLBIN_PR,
+        XCLBIN_TANDEM_STAGE2,
+        XCLBIN_TANDEM_STAGE2_WITH_PR,
+        XCLBIN_HW_EMU,
+        XCLBIN_SW_EMU,
+        XCLBIN_HW_EMU_PR,
+        XCLBIN_MODE_MAX
+    };
+
+    /*
+     *  AXLF LAYOUT
+     *  -----------
+     *
+     *  -----------------------------------------
+     *  | Magic                                 |
+     *  -----------------------------------------
+     *  | Header                                |
+     *  -----------------------------------------
+     *  | One or more section headers           |
+     *  -----------------------------------------
+     *  | Matching number of sections with data |
+     *  -----------------------------------------
+     *
+     */
+
+    enum axlf_section_kind {
+        BITSTREAM             =  0,
+        CLEARING_BITSTREAM    =  1,
+        EMBEDDED_METADATA     =  2,
+        FIRMWARE              =  3,
+        DEBUG_DATA            =  4,
+        SCHED_FIRMWARE        =  5,
+        MEM_TOPOLOGY          =  6,
+        CONNECTIVITY          =  7,
+        IP_LAYOUT             =  8,
+        DEBUG_IP_LAYOUT       =  9,
+        DESIGN_CHECK_POINT    = 10,
+        CLOCK_FREQ_TOPOLOGY   = 11,
+        MCS                   = 12,
+        BMC                   = 13,
+        BUILD_METADATA        = 14,
+        KEYVALUE_METADATA     = 15,
+        USER_METADATA         = 16,
+        DNA_CERTIFICATE       = 17,
+        PDI                   = 18,
+        BITSTREAM_PARTIAL_PDI = 19,
+        PARTITION_METADATA    = 20,
+        EMULATION_DATA        = 21,
+        SYSTEM_METADATA       = 22,
+        SOFT_KERNEL           = 23,
+        ASK_FLASH             = 24,
+        AIE_METADATA          = 25,
+        ASK_GROUP_TOPOLOGY    = 26,
+        ASK_GROUP_CONNECTIVITY = 27
+    };
+
+    enum MEM_TYPE {
+        MEM_DDR3,
+        MEM_DDR4,
+        MEM_DRAM,
+        MEM_STREAMING,
+        MEM_PREALLOCATED_GLOB,
+        MEM_ARE, //Aurora
+        MEM_HBM,
+        MEM_BRAM,
+        MEM_URAM,
+        MEM_STREAMING_CONNECTION
+    };
+
+    enum IP_TYPE {
+        IP_MB = 0,
+        IP_KERNEL, //kernel instance
+        IP_DNASC,
+        IP_DDR4_CONTROLLER,
+        IP_MEM_DDR4,
+        IP_MEM_HBM
+    };
+
+    enum ACTION_MASK {
+      AM_LOAD_AIE = 0x1                     /* Indicates to the driver to load the AIE PID section */
+    };
+
+    struct axlf_section_header {
+        uint32_t m_sectionKind;             /* Section type */
+        char m_sectionName[16];             /* Examples: "stage2", "clear1", "clear2", "ocl1", "ocl2, "ublaze", "sched" */
+        uint64_t m_sectionOffset;           /* File offset of section data */
+        uint64_t m_sectionSize;             /* Size of section data */
+    };
+    XCLBIN_STATIC_ASSERT(sizeof(struct axlf_section_header) == 40, "axlf_section_header structure no longer is 40 bytes in size");
+
+    struct axlf_header {
+        uint64_t m_length;                  /* Total size of the xclbin file */
+        uint64_t m_timeStamp;               /* Number of seconds since epoch when xclbin was created */
+        uint64_t m_featureRomTimeStamp;     /* TimeSinceEpoch of the featureRom */
+        uint16_t m_versionPatch;            /* Patch Version */
+        uint8_t m_versionMajor;             /* Major Version - Version: 2.1.0*/
+        uint8_t m_versionMinor;             /* Minor Version */
+        uint16_t m_mode;                    /* XCLBIN_MODE */
+        uint16_t m_actionMask;              /* Bit Mask */
+	union {
+	    struct {
+		uint64_t m_platformId;      /* 64 bit platform ID: vendor-device-subvendor-subdev */
+		uint64_t m_featureId;       /* 64 bit feature id */
+	    } rom;
+	    unsigned char rom_uuid[16];     /* feature ROM UUID for which this xclbin was generated */
+	};
+        unsigned char m_platformVBNV[64];   /* e.g. xilinx:xil-accel-rd-ku115:4ddr-xpr:3.4: null terminated */
+	union {
+	    char m_next_axlf[16];           /* Name of next xclbin file in the daisy chain */
+	    xuid_t uuid;                    /* uuid of this xclbin*/
+	};
+        char m_debug_bin[16];               /* Name of binary with debug information */
+        uint32_t m_numSections;             /* Number of section headers */
+    };
+    XCLBIN_STATIC_ASSERT(sizeof(struct axlf_header) == 152, "axlf_header structure no longer is 152 bytes in size");
+
+    struct axlf {
+        char m_magic[8];                            /* Should be "xclbin2\0"  */
+        int32_t m_signature_length;                 /* Length of the signature. -1 indicates no signature */
+        unsigned char reserved[28];                 /* Note: Initialized to 0xFFs */
+
+        unsigned char m_keyBlock[256];              /* Signature for validation of binary */
+        uint64_t m_uniqueId;                        /* axlf's uniqueId, use it to skip redownload etc */
+        struct axlf_header m_header;                /* Inline header */
+        struct axlf_section_header m_sections[1];   /* One or more section headers follow */
+    };
+    XCLBIN_STATIC_ASSERT(sizeof(struct axlf) == 496, "axlf structure no longer is 496 bytes in size");
+
+    typedef struct axlf xclBin;
+
+    /**** BEGIN : Xilinx internal section *****/
+
+    /* bitstream information */
+    struct xlnx_bitstream {
+        uint8_t m_freq[8];
+        char bits[1];
+    };
+    XCLBIN_STATIC_ASSERT(sizeof(struct xlnx_bitstream) == 9, "xlnx_bitstream structure no longer is 9 bytes in size");
+
+
+    /****   MEMORY TOPOLOGY SECTION ****/
+    struct mem_data {
+        uint8_t m_type;          // enum corresponding to mem_type.
+        uint8_t m_used;          // if 0 this bank is not present
+        uint8_t padding[6];      // 8 Byte alignment padding (initialized to zeros)
+        union {
+            uint64_t m_size;     // if mem_type DDR, then size in KB;
+            uint64_t route_id;   // if streaming then "route_id"
+        };
+        union {
+            uint64_t m_base_address; // if DDR then the base address;
+            uint64_t flow_id;        // if streaming then "flow id"
+        };
+        unsigned char m_tag[16]; // DDR: BANK0,1,2,3, has to be null terminated; if streaming then stream0, 1 etc
+    };
+    XCLBIN_STATIC_ASSERT(sizeof(struct mem_data) == 40, "mem_data structure no longer is 40 bytes in size");
+
+    struct mem_topology {
+        int32_t m_count; //Number of mem_data
+        struct mem_data m_mem_data[1]; //Should be sorted on mem_type
+    };
+    XCLBIN_STATIC_ASSERT(sizeof(struct mem_topology) == 48, "mem_topology structure no longer is 48 bytes in size");
+
+
+    /****   CONNECTIVITY SECTION ****/
+    /* Connectivity of each argument of Kernel. It will be in terms of argument
+     * index associated. For associating kernel instances with arguments and
+     * banks, start at the connectivity section. Using the m_ip_layout_index
+     * access the ip_data.m_name. Now we can associate this kernel instance
+     * with its original kernel name and get the connectivity as well. This
+     * enables us to form related groups of kernel instances.
+     */
+
+    struct connection {
+        int32_t arg_index; //From 0 to n, may not be contiguous as scalars skipped
+        int32_t m_ip_layout_index; //index into the ip_layout section. ip_layout.m_ip_data[index].m_type == IP_KERNEL
+        int32_t mem_data_index; //index of the m_mem_data . Flag error is m_used false.
+    };
+    XCLBIN_STATIC_ASSERT(sizeof(struct connection) == 12, "connection structure no longer is 12 bytes in size");
+
+    struct connectivity {
+        int32_t m_count;
+        struct connection m_connection[1];
+    };
+    XCLBIN_STATIC_ASSERT(sizeof(struct connectivity) == 16, "connectivity structure no longer is 16 bytes in size");
+
+    /****   IP_LAYOUT SECTION ****/
+
+    // IP Kernel
+    #define IP_INT_ENABLE_MASK    0x0001
+    #define IP_INTERRUPT_ID_MASK  0x00FE
+    #define IP_INTERRUPT_ID_SHIFT 0x1
+
+    enum IP_CONTROL {
+        AP_CTRL_HS = 0,
+        AP_CTRL_CHAIN = 1,
+        AP_CTRL_NONE = 2,
+        AP_CTRL_ME = 3,
+        ACCEL_ADAPTER = 4,
+        FAST_ADAPTER = 5
+    };
+
+    #define IP_CONTROL_MASK  0xFF00
+    #define IP_CONTROL_SHIFT 0x8
+
+    /* IPs on AXI lite - their types, names, and base addresses.*/
+    struct ip_data {
+        uint32_t m_type; //map to IP_TYPE enum
+        union {
+            uint32_t properties; // Default: 32-bits to indicate ip specific property.
+                                 // m_type: IP_KERNEL
+                                 //         m_int_enable   : Bit  - 0x0000_0001;
+                                 //         m_interrupt_id : Bits - 0x0000_00FE;
+                                 //         m_ip_control   : Bits = 0x0000_FF00;
+            struct {             // m_type: IP_MEM_*
+               uint16_t m_index;
+               uint8_t m_pc_index;
+               uint8_t unused;
+            } indices;
+        };
+        uint64_t m_base_address;
+        uint8_t m_name[64]; //eg Kernel name corresponding to KERNEL instance, can embed CU name in future.
+    };
+    XCLBIN_STATIC_ASSERT(sizeof(struct ip_data) == 80, "ip_data structure no longer is 80 bytes in size");
+
+    struct ip_layout {
+        int32_t m_count;
+        struct ip_data m_ip_data[1]; //All the ip_data needs to be sorted by m_base_address.
+    };
+    XCLBIN_STATIC_ASSERT(sizeof(struct ip_layout) == 88, "ip_layout structure no longer is 88 bytes in size");
+
+    /*** Debug IP section layout ****/
+    enum DEBUG_IP_TYPE {
+        UNDEFINED = 0,
+        LAPC,
+        ILA,
+        AXI_MM_MONITOR,
+        AXI_TRACE_FUNNEL,
+        AXI_MONITOR_FIFO_LITE,
+        AXI_MONITOR_FIFO_FULL,
+        ACCEL_MONITOR,
+        AXI_STREAM_MONITOR,
+        AXI_STREAM_PROTOCOL_CHECKER,
+        TRACE_S2MM,
+        AXI_DMA,
+        TRACE_S2MM_FULL,
+        AXI_NOC
+    };
+
+    struct debug_ip_data {
+        uint8_t m_type; // type of enum DEBUG_IP_TYPE
+        uint8_t m_index_lowbyte;
+        uint8_t m_properties;
+        uint8_t m_major;
+        uint8_t m_minor;
+        uint8_t m_index_highbyte;
+        uint8_t m_reserved[2];
+        uint64_t m_base_address;
+        char    m_name[128];
+    };
+    XCLBIN_STATIC_ASSERT(sizeof(struct debug_ip_data) == 144, "debug_ip_data structure no longer is 144 bytes in size");
+
+    struct debug_ip_layout {
+        uint16_t m_count;
+        struct debug_ip_data m_debug_ip_data[1];
+    };
+    XCLBIN_STATIC_ASSERT(sizeof(struct debug_ip_layout) == 152, "debug_ip_layout structure no longer is 152 bytes in size");
+
+    enum CLOCK_TYPE {                      /* Supported clock frequency types */
+        CT_UNUSED = 0,                     /* Initialized value */
+        CT_DATA   = 1,                     /* Data clock */
+        CT_KERNEL = 2,                     /* Kernel clock */
+        CT_SYSTEM = 3                      /* System Clock */
+    };
+
+    struct clock_freq {                    /* Clock Frequency Entry */
+        uint16_t m_freq_Mhz;               /* Frequency in MHz */
+        uint8_t m_type;                    /* Clock type (enum CLOCK_TYPE) */
+        uint8_t m_unused[5];               /* Not used - padding */
+        char m_name[128];                  /* Clock Name */
+    };
+    XCLBIN_STATIC_ASSERT(sizeof(struct clock_freq) == 136, "clock_freq structure no longer is 136 bytes in size");
+
+    struct clock_freq_topology {           /* Clock frequency section */
+        int16_t m_count;                   /* Number of entries */
+        struct clock_freq m_clock_freq[1]; /* Clock array */
+    };
+    XCLBIN_STATIC_ASSERT(sizeof(struct clock_freq_topology) == 138, "clock_freq_topology structure no longer is 138 bytes in size");
+
+    enum MCS_TYPE {                        /* Supported MCS file types */
+        MCS_UNKNOWN = 0,                   /* Initialized value */
+        MCS_PRIMARY = 1,                   /* The primary mcs file data */
+        MCS_SECONDARY = 2,                 /* The secondary mcs file data */
+    };
+
+    struct mcs_chunk {                     /* One chunk of MCS data */
+        uint8_t m_type;                    /* MCS data type */
+        uint8_t m_unused[7];               /* padding */
+        uint64_t m_offset;                 /* data offset from the start of the section */
+        uint64_t m_size;                   /* data size */
+    };
+    XCLBIN_STATIC_ASSERT(sizeof(struct mcs_chunk) == 24, "mcs_chunk structure no longer is 24 bytes in size");
+
+    struct mcs {                           /* MCS data section */
+        int8_t m_count;                    /* Number of chunks */
+        int8_t m_unused[7];                /* padding */
+        struct mcs_chunk m_chunk[1];       /* MCS chunks followed by data */
+    };
+    XCLBIN_STATIC_ASSERT(sizeof(struct mcs) == 32, "mcs structure no longer is 32 bytes in size");
+
+    struct bmc {                           /* bmc data section  */
+        uint64_t m_offset;                 /* data offset from the start of the section */
+        uint64_t m_size;                   /* data size (bytes)*/
+        char m_image_name[64];             /* Name of the image (e.g., MSP432P401R) */
+        char m_device_name[64];            /* Device ID         (e.g., VCU1525)  */
+        char m_version[64];
+        char m_md5value[33];               /* MD5 Expected Value(e.g., 56027182079c0bd621761b7dab5a27ca)*/
+        char m_padding[7];                 /* Padding */
+    };
+    XCLBIN_STATIC_ASSERT(sizeof(struct bmc) == 248, "bmc structure no longer is 248 bytes in size");
+
+    struct soft_kernel {                   /* soft kernel data section  */
+        // Prefix Syntax:
+        //   mpo - member, pointer, offset
+        //     This variable represents a zero terminated string
+        //     that is offseted from the beginning of the section.
+        //
+        //     The pointer to access the string is initialized as follows:
+        //     char * pCharString = (address_of_section) + (mpo value)
+        uint32_t mpo_name;         // Name of the soft kernel
+        uint32_t m_image_offset;   // Image offset
+        uint32_t m_image_size;     // Image size
+        uint32_t mpo_version;      // Version
+        uint32_t mpo_md5_value;    // MD5 checksum
+        uint32_t mpo_symbol_name;  // Symbol name
+        uint32_t m_num_instances;  // Number of instances
+        uint8_t padding[36];       // Reserved for future use
+        uint8_t reservedExt[16];   // Reserved for future extended data
+    };
+    XCLBIN_STATIC_ASSERT(sizeof(struct soft_kernel) == 80, "soft_kernel structure no longer is 80 bytes in size");
+
+    enum FLASH_TYPE
+    {
+        FLT_UNKNOWN = 0,
+        FLT_BIN_PRIMARY
+    };
+
+    struct flash {                 /* flash data section  */
+        // Prefix Syntax:
+        //   mpo - member, pointer, offset
+        //     This variable represents a zero terminated string
+        //     that is offseted from the beginning of the section.
+        //
+        //     The pointer to access the string is initialized as follows:
+        //     char * pCharString = (address_of_section) + (mpo value)
+        uint16_t m_flash_type;     // ENUM FLASH_TYPE
+        uint8_t padding[2];        // Alignment buffer
+        uint32_t m_image_offset;   // Image offset
+        uint32_t m_image_size;     // Image size
+        uint32_t mpo_name;         // Name of the flash image
+        uint32_t mpo_version;      // Version
+        uint32_t mpo_md5_value;    // MD5 checksum
+        uint8_t reserved[32];      // Reserved for future use
+        uint8_t reservedExt[16];   // Reserved for future extended data
+    };
+    XCLBIN_STATIC_ASSERT(sizeof(struct flash) == 72, "flash structure no longer is 72 bytes in size");
+
+    enum CHECKSUM_TYPE
+    {
+        CST_UNKNOWN = 0,
+        CST_SDBM = 1,
+        CST_LAST
+    };
+
+    /**** END : Xilinx internal section *****/
+
+# ifdef __cplusplus
+    namespace xclbin {
+      inline const axlf_section_header*
+      get_axlf_section(const axlf* top, axlf_section_kind kind)
+      {
+        auto begin = top->m_sections;
+        auto end = begin + top->m_header.m_numSections;
+        auto itr = std::find_if(begin,end,[kind](const axlf_section_header& sec) { return sec.m_sectionKind == static_cast<uint32_t>(kind); });
+        return (itr!=end) ? &(*itr) : nullptr;
+      }
+
+      // Helper C++ section iteration
+      // To keep with with the current "coding" them, the function get_axlf_section_next() was
+      // introduced find 'next' common section names.
+      //
+      // Future TODO: Create a custom iterator and refactor the code base to use it.
+      //
+      // Example on how this function may be used:
+      //
+      // const axlf_section_header * pSection;
+      // const axlf* top = <xclbin image in memory>;
+      // for (pSection = xclbin::get_axlf_section( top, SOFT_KERNEL);
+      //      pSection != nullptr;
+      //      pSection = xclbin::get_axlf_section_next( top, pSection, SOFT_KERNEL)) {
+      //   <code to do work>
+      // }
+      inline const axlf_section_header*
+      get_axlf_section_next(const axlf* top, const axlf_section_header* current_section, axlf_section_kind kind)
+      {
+        if (top == nullptr) { return nullptr; }
+        if (current_section == nullptr) { return nullptr; }
+
+        auto end = top->m_sections + top->m_header.m_numSections;
+
+        auto begin = current_section + 1;        // Point to the next section
+        if (begin == end) { return nullptr; }
+
+        auto itr = std::find_if(begin, end, [kind](const axlf_section_header &sec) {return sec.m_sectionKind == static_cast<uint32_t>(kind); });
+        return (itr!=end) ? &(*itr) : nullptr;
+      }
+    }
+# endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/include/xclerr.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/include/xclerr.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2017 Xilinx, Inc
+ * Author: Umang Parekh
+ *
+ * This file is dual licensed.  It may be redistributed and/or modified
+ * under the terms of the Apache 2.0 License OR version 2 of the GNU
+ * General Public License.
+ *
+ * Apache License Verbiage
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"). You may
+ * not use this file except in compliance with the License. A copy of the
+ * License is located at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ * GPL license Verbiage:
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program;
+ * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/**
+ * DOC: Device error status related structs and defines
+ * This file is used by both userspace and xclmgmt kernel driver.
+ */
+
+#ifndef XCLERR_H_
+#define XCLERR_H_
+
+/**
+ * enum xclFirewallID - AXI Firewall IDs used to identify individual AXI Firewalls
+ *
+ * @XCL_FW_MGMT_CONTROL:  MGMT BAR AXI-Lite BAR access protection
+ * @XCL_FW_USER_CONTROL:  USER BAR AXI-Lite BAR access protection
+ * @XCL_FW_DATAPATH:      DMA data path protection
+ */
+enum xclFirewallID {
+        XCL_FW_MGMT_CONTROL = 0,
+        XCL_FW_USER_CONTROL,
+        XCL_FW_DATAPATH,
+        XCL_FW_MAX_LEVEL // always the last one
+};
+
+/**
+ * struct xclAXIErrorStatus - Record used to capture specific error
+ *
+ * @mErrFirewallTime:    Timestamp of when Firewall tripped
+ * @mErrFirewallStatus:  Error code obtained from the Firewall
+ * @mErrFirewallID:      Firewall ID
+ */
+struct xclAXIErrorStatus {
+        unsigned long       mErrFirewallTime;
+        unsigned            mErrFirewallStatus;
+        enum xclFirewallID  mErrFirewallID;
+};
+
+struct xclPCIErrorStatus {
+        unsigned mDeviceStatus;
+        unsigned mUncorrErrStatus;
+        unsigned mCorrErrStatus;
+        unsigned rsvd1;
+        unsigned rsvd2;
+};
+
+/**
+ * struct xclErrorStatus - Container for all error records
+ *
+ * @mNumFirewalls:    Count of Firewalls in the record (max is 8)
+ * @mAXIErrorStatus:  Records holding Firewall information
+ * @mPCIErrorStatus:  Unused
+ */
+struct xclErrorStatus {
+        unsigned  mNumFirewalls;
+        struct xclAXIErrorStatus mAXIErrorStatus[8];
+        struct xclPCIErrorStatus mPCIErrorStatus;
+        unsigned mFirewallLevel;
+};
+
+#endif /* XCLERR_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/include/xclfeatures.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/include/xclfeatures.h
@@ -0,0 +1,146 @@
+/**
+ *  Copyright (C) 2015-2018, Xilinx Inc
+ *
+ *  This file is dual licensed.	 It may be redistributed and/or modified
+ *  under the terms of the Apache 2.0 License OR version 2 of the GNU
+ *  General Public License.
+ *
+ *  Apache License Verbiage
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  GPL license Verbiage:
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License as
+ *  published by the Free Software Foundation; either version 2 of the
+ *  License, or (at your option) any later version.  This program is
+ *  distributed in the hope that it will be useful, but WITHOUT ANY
+ *  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ *  License for more details.  You should have received a copy of the
+ *  GNU General Public License along with this program; if not, write
+ *  to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ *  Boston, MA 02111-1307 USA
+ *
+ */
+
+
+/**
+ *  Xilinx SDAccel FPGA BIOS definition
+ *  Copyright (C) 2016-2018, Xilinx Inc - All rights reserved
+ */
+
+#ifndef xclfeatures_h_
+#define xclfeatures_h_
+
+#define FEATURE_ROM_MAJOR_VERSION 10
+#define FEATURE_ROM_MINOR_VERSION 1
+
+//Layout: At address 0xB0000, we will have the FeatureRomHeader that comprises:
+//
+//1. First have FeatureRomHeader: 152 bytes of information followed by
+//2. Then, as a part of FeatureRomHeader we have the PRRegion struct(s).
+//	The number of such structs will be same as OCLRegionCount.
+//3. After this the freq scaling table is laid out.
+//
+
+//#include <stdint.h>
+
+struct PartialRegion {
+	uint16_t clk[4];
+	int8_t XPR; //0 : non-xpt, 1: xpr
+};
+
+// Each entry represents one row in freq scaling table.
+struct FreqScalingTableRow {
+	short config0;
+	short freq;
+	short config2;
+};
+
+enum PROMType  {
+	BPI	= 0
+	, SPI	= 1
+   //room for 6 more types of flash devices.
+};
+
+enum DebugType	{
+	DT_NIFD	 = 0x01,
+	DT_FIREWALL  = 0x02
+  //There is room for future expansion upto 8 IPs
+};
+
+// This bit mask is used with the FeatureBitMap to calculate 64 bool features
+//
+// To test if a feature is provided:
+//   FeatureRomHeader header;
+//   if (FeatureBitMask::FBM_IS_UNIFIED & header.FeatureBitMap)
+//     // it is supported
+//   else
+//     // it is not supported
+//
+// To set if a feature is provided:
+//   header.FeatureBitMap = 0;
+//   header.FeatureBitMap |= FeatureBitMask::FBM_IS_UNIFIED;
+//
+enum FeatureBitMask {
+	UNIFIED_PLATFORM       =   0x0000000000000001	     /* bit 1 : Unified platform */
+	, XARE_ENBLD	       =   0x0000000000000002	    /* bit 2 : Aurora link enabled DSA */
+	, BOARD_MGMT_ENBLD     =   0x0000000000000004	    /* bit 3 : Has MB based power monitoring */
+	, MB_SCHEDULER	       =   0x0000000000000008	    /* bit 4:  Has MB based scheduler */
+	, PROM_MASK	       =   0x0000000000000070	    /* bits 5,6 &7  : 3 bits for PROMType */
+	/**  ------ Bit 8 unused **/
+	, DEBUG_MASK	       =   0x000000000000FF00	    /* bits 9 through 16  : 8 bits for DebugType */
+	, PEER_TO_PEER	       =   0x0000000000010000	    /* bits 17	: Bar 2 is a peer to peer bar*/
+	, FBM_UUID		       =   0x0000000000020000	    /* bits 18	: UUID enabled. uuid[16] field is valid*/
+	, HBM		       =   0x0000000000040000	    /* bits 19	: Device has HBM's. HBMCount/Size are valid*/
+	, CDMA		       =   0x0000000000080000	    /* bits 21	: Device has CDMA*/
+	, QDMA		       =   0x0000000000100000	    /* bits 20	: Device has QDMA*/
+	, RUNTIME_CLK_SCALE    =   0x0000000000200000	    /* bit 22 : Device has RUNTIME CLOCK SCALING feature*/
+	, PASSTHROUGH_VIRTUALIZATION    =   0x0000000000400000	/* bit 23 : Device has Passthrough Virtualization feature*/
+
+   //....more
+};
+
+
+
+// In the following data structures, the EntryPointString, MajorVersion, and MinorVersion
+// values are all used in the Runtime to identify if the ROM is producing valid data, and
+// to pick the schema to read the rest of the data; Ergo, these values shall not change.
+
+/*
+ * Struct used for >  2017.2_sdx
+ * This struct should be used for version (==) 10.0 (Major: 10, Minor: 0)
+ */
+struct FeatureRomHeader {
+	unsigned char EntryPointString[4];  // This is "xlnx"
+	uint8_t MajorVersion;		    // Feature ROM's major version eg 1
+	uint8_t MinorVersion;		    // minor version eg 2.
+	// -- DO NOT CHANGE THE TYPES ABOVE THIS LINE --
+	uint32_t VivadoBuildID;		    // Vivado Software Build (e.g., 1761098 ). From ./vivado --version
+	uint32_t IPBuildID;		    // IP Build (e.g., 1759159 from abve)
+	uint64_t TimeSinceEpoch;	    // linux time(NULL) call, at write_dsa_rom invocation
+	unsigned char FPGAPartName[64];	    // The hardware FPGA part. Null termninated
+	unsigned char VBNVName[64];	    // eg : xilinx:xil-accel-rd-ku115:4ddr-xpr:3.4: null terminated
+	uint8_t DDRChannelCount;	    // 4 for TUL
+	uint8_t DDRChannelSize;		    // 4 (in GB)
+	uint64_t DRBaseAddress;		    // The Dynamic Range's (AppPF/CL/Userspace) Base Address
+	uint64_t FeatureBitMap;		    // Feature Bit Map, 64 different bool features, maps to enum FeatureBitMask
+	unsigned char uuid[16];		    // UUID of the DSA.
+	uint8_t HBMCount;		    // Number of HBMs
+	uint8_t HBMSize;		    // Size of (each) HBM in GB
+	uint32_t CDMABaseAddress[4];	    // CDMA base addresses
+};
+
+#endif // xclfeatures_h_
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/include/xclhal2_mem.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/include/xclhal2_mem.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2019, Xilinx Inc - All rights reserved.
+ * Xilinx Runtime (XRT) APIs
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"). You may
+ * not use this file except in compliance with the License. A copy of the
+ * License is located at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _XCLHAL2_MEM_H_
+#define _XCLHAL2_MEM_H_
+
+#include "xrt_mem.h"
+
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/include/xrt_cu.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/include/xrt_cu.h
@@ -0,0 +1,436 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * Xilinx Unify CU Model
+ *
+ * Copyright (C) 2020 Xilinx, Inc. All rights reserved.
+ *
+ * Authors: min.ma@xilinx.com
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#ifndef _XRT_CU_H
+#define _XRT_CU_H
+
+#include <linux/version.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/semaphore.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/kthread.h>
+#include "kds_command.h"
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
+#define ioremap_nocache         ioremap
+#endif
+
+#define MAX_CUS 128
+
+/* The normal CU in ip_layout would assign a interrupt
+ * ID in range 0 to 127. Use 128 for m2m cu could ensure
+ * m2m CU is at the end of the CU, which is compatible with
+ * legacy implementation.
+ */
+#define M2M_CU_ID 128
+
+#define xcu_info(xcu, fmt, args...)			\
+	dev_info(xcu->dev, " %llx %s: "fmt, (u64)xcu->dev, __func__, ##args)
+#define xcu_err(xcu, fmt, args...)			\
+	dev_err(xcu->dev, " %llx %s: "fmt, (u64)xcu->dev, __func__, ##args)
+#define xcu_dbg(xcu, fmt, args...)			\
+	dev_dbg(xcu->dev, " %llx %s: "fmt, (u64)xcu->dev, __func__, ##args)
+
+/* HLS CU macros */
+#define CU_AP_START	(0x1 << 0)
+#define CU_AP_DONE	(0x1 << 1)
+#define CU_AP_IDLE	(0x1 << 2)
+#define CU_AP_READY	(0x1 << 3)
+#define CU_AP_CONTINUE	(0x1 << 4)
+#define CU_AP_RESET	(0x1 << 5)
+
+#define CU_INTR_DONE  0x1
+#define CU_INTR_READY 0x2
+
+enum xcu_model {
+	XCU_HLS,
+	XCU_ACC,
+	XCU_PLRAM,
+	XCU_FA,
+};
+
+enum xcu_config_type {
+	CONSECUTIVE_T,
+	PAIRS_T,
+};
+
+/* Let's use HLS style status bits in new_status
+ * Bit 0: start (running)
+ * Bit 1: done
+ * Bit 2: idle
+ */
+struct xcu_status {
+	u32	num_done;
+	u32	num_ready;
+	u32	new_status;
+};
+
+typedef void *xcu_core_t;
+struct xcu_funcs {
+	/**
+	 * @alloc_credit:
+	 *
+	 * Try to alloc one credit on the CU. A credit is required before
+	 * submit a task to the CU. Otherwise, it would lead to unknown CU
+	 * behaviour.
+	 * Return: the number of remaining credit.
+	 */
+	int (*alloc_credit)(void *core);
+
+	/**
+	 * @free_credit:
+	 *
+	 * free credits.
+	 */
+	void (*free_credit)(void *core, u32 count);
+
+	/**
+	 * @peek_credit:
+	 *
+	 * Check how many credits the CU could provide with side effect.
+	 */
+	int (*peek_credit)(void *core);
+
+	/**
+	 * @configure:
+	 *
+	 * Congifure CU arguments.
+	 *
+	 * There are two types of configuration format.
+	 *
+	 * 1. CONSECUTIVE: Which is a blind copy from data to CU.
+	 * 2. PAIRS: The data contains {offset, val} pairs.
+	 */
+	void (*configure)(void *core, u32 *data, size_t sz, int type);
+
+	/**
+	 * @start:
+	 *
+	 * Start a CU.
+	 */
+	void (*start)(void *core);
+
+	/**
+	 * @check:
+	 *
+	 * Check CU status and the pending task status.
+	 */
+	void (*check)(void *core, struct xcu_status *status);
+
+	/**
+	 * @reset:
+	 *
+	 * Reset CU.
+	 */
+	void (*reset)(void *core);
+
+	/**
+	 * @reset_done:
+	 *
+	 * Check if CU is properly reset
+	 */
+	int (*reset_done)(void *core);
+
+	/**
+	 * @enable_intr:
+	 *
+	 * Enable interrupt. Support DONE and READY interrupt.
+	 */
+	void (*enable_intr)(void *core, u32 intr_type);
+
+	/**
+	 * @disable_intr:
+	 *
+	 * Disable interrupt.
+	 */
+	void (*disable_intr)(void *core, u32 intr_type);
+
+	/**
+	 * @clear_intr:
+	 *
+	 * Clear interrupt.
+	 */
+	u32 (*clear_intr)(void *core);
+};
+
+enum arg_dir {
+	DIR_NONE = 0,
+	DIR_INPUT,
+	DIR_OUTPUT
+};
+
+struct xrt_cu_arg {
+	char	name[32];
+	u32	offset;
+	u32	size;
+	u32	dir;
+};
+
+enum CU_PROTOCOL {
+	CTRL_HS = 0,
+	CTRL_CHAIN = 1,
+	CTRL_NONE = 2,
+	CTRL_ME = 3,
+	CTRL_ACC = 4,
+	CTRL_FA = 5
+};
+
+struct xrt_cu_info {
+	u32			 model;
+	int			 cu_idx;
+	int			 inst_idx;
+	u64			 addr;
+	u32			 protocol;
+	u32			 intr_id;
+	u32			 is_m2m;
+	u32			 num_res;
+	bool			 intr_enable;
+	struct xrt_cu_arg	*args;
+	u32			 num_args;
+	char			 iname[32];
+	char			 kname[32];
+};
+
+#define CU_STATE_GOOD  0x1
+#define CU_STATE_BAD   0x2
+struct xrt_cu_event {
+	struct mutex		  lock;
+	void			 *client;
+	int			  state;
+};
+
+struct xrt_cu {
+	struct device		 *dev;
+	struct xrt_cu_info	  info;
+	struct resource		**res;
+	/* pending queue */
+	struct list_head	  pq;
+	spinlock_t		  pq_lock;
+	u32			  num_pq;
+	/*
+	 * Pending Q is used in thread that is submitting CU cmds.
+	 * Other Qs are used in thread that is completing them.
+	 * In order to prevent false sharing, they need to be in different
+	 * cache lines. Hence we add a "padding" in between (assuming 128-byte
+	 * is big enough for most CPU architectures).
+	 */
+	u64			  padding[16];
+	/* run queue */
+	struct list_head	  rq;
+	u32			  num_rq;
+	/* submitted queue */
+	struct list_head	  sq;
+	u32			  num_sq;
+	/* completed queue */
+	struct list_head	  cq;
+	u32			  num_cq;
+	struct semaphore	  sem;
+	struct semaphore	  sem_cu;
+	void			 *core;
+	u32			  stop;
+	bool			  bad_state;
+	u32			  done_cnt;
+	u32			  ready_cnt;
+	u32			  status;
+	u64			  run_timeout;
+	int			  busy_threshold;
+	u32			  interval_min;
+	u32			  interval_max;
+	struct kds_command	 *old_cmd;
+	struct xrt_cu_event	  ev;
+	/**
+	 * @funcs:
+	 *
+	 * Compute unit functions.
+	 */
+	struct xcu_funcs          *funcs;
+	/* TODO: Maybe rethink if we should use two threads,
+	 * one for submit, one for complete
+	 */
+	struct task_struct	  *thread;
+	/* Good for debug */
+	u32			   sleep_cnt;
+	u32			   max_running;
+};
+
+static inline char *prot2str(enum CU_PROTOCOL prot)
+{
+	switch (prot) {
+	case CTRL_HS:		return "CTRL_HS";
+	case CTRL_CHAIN:	return "CTRL_CHAIN";
+	case CTRL_NONE:		return "CTRL_NONE";
+	case CTRL_ME:		return "CTRL_ME";
+	case CTRL_ACC:		return "CTRL_ACC";
+	case CTRL_FA:		return "CTRL_FA";
+	default:		return "UNKNOWN";
+	}
+}
+
+void xrt_cu_reset(struct xrt_cu *xcu);
+int  xrt_cu_reset_done(struct xrt_cu *xcu);
+
+static void inline xrt_cu_enable_intr(struct xrt_cu *xcu, u32 intr_type)
+{
+	if (xcu->funcs)
+		xcu->funcs->enable_intr(xcu->core, intr_type);
+}
+
+static void inline xrt_cu_disable_intr(struct xrt_cu *xcu, u32 intr_type)
+{
+	if (xcu->funcs)
+		xcu->funcs->disable_intr(xcu->core, intr_type);
+}
+
+static u32 inline xrt_cu_clear_intr(struct xrt_cu *xcu)
+{
+	return xcu->funcs ? xcu->funcs->clear_intr(xcu->core) : 0;
+}
+
+static inline void xrt_cu_config(struct xrt_cu *xcu, u32 *data, size_t sz, int type)
+{
+	xcu->funcs->configure(xcu->core, data, sz, type);
+}
+
+static inline void xrt_cu_start(struct xrt_cu *xcu)
+{
+	xcu->funcs->start(xcu->core);
+}
+
+static inline void xrt_cu_check(struct xrt_cu *xcu)
+{
+	struct xcu_status status;
+
+	status.num_done = 0;
+	status.num_ready = 0;
+	status.new_status = 0;
+	xcu->funcs->check(xcu->core, &status);
+	/* XRT CU assume command finished in order */
+	xcu->done_cnt += status.num_done;
+	xcu->ready_cnt += status.num_ready;
+	xcu->status = status.new_status;
+}
+
+static inline int xrt_cu_get_credit(struct xrt_cu *xcu)
+{
+	return xcu->funcs->alloc_credit(xcu->core);
+}
+
+static inline int is_zero_credit(struct xrt_cu *xcu)
+{
+	return (xcu->funcs->peek_credit(xcu->core) == 0);
+}
+
+static inline int xrt_cu_peek_credit(struct xrt_cu *xcu)
+{
+	return xcu->funcs->peek_credit(xcu->core);
+}
+
+static inline void xrt_cu_put_credit(struct xrt_cu *xcu, u32 count)
+{
+	xcu->funcs->free_credit(xcu->core, count);
+}
+
+/* This is a bit trick to calculate next highest power of 2.
+ * If size is a power of 2, the return would be the same as size.
+ */
+static __attribute__((unused))
+u32 round_up_to_next_power2(u32 size)
+{
+	u32 v = --size;
+	v |= v >> 1;
+	v |= v >> 2;
+	v |= v >> 4;
+	v |= v >> 8;
+	v |= v >> 16;
+	return ++v;
+}
+
+/* 1. Move commands from pending command queue to running queue
+ * 2. If CU is ready, submit command(Configure hardware)
+ * 3. Check if submitted command is completed or not
+ */
+void xrt_cu_submit(struct xrt_cu *xcu, struct kds_command *xcmd);
+int xrt_cu_abort(struct xrt_cu *xcu, void *client);
+int xrt_cu_abort_done(struct xrt_cu *xcu);
+int xrt_cu_cfg_update(struct xrt_cu *xcu, int intr);
+int xrt_fa_cfg_update(struct xrt_cu *xcu, u64 bar, u64 dev, void __iomem *vaddr, u32 num_slots);
+int xrt_is_fa(struct xrt_cu *xcu, u32 *size);
+void xrt_cu_set_bad_state(struct xrt_cu *xcu);
+
+int  xrt_cu_init(struct xrt_cu *xcu);
+void xrt_cu_fini(struct xrt_cu *xcu);
+
+ssize_t show_cu_stat(struct xrt_cu *xcu, char *buf);
+ssize_t show_cu_info(struct xrt_cu *xcu, char *buf);
+
+/* CU Implementations */
+struct xrt_cu_hls {
+	void __iomem		*vaddr;
+	int			 max_credits;
+	int			 credits;
+	int			 run_cnts;
+	bool			 ctrl_chain;
+};
+
+int xrt_cu_hls_init(struct xrt_cu *xcu);
+void xrt_cu_hls_fini(struct xrt_cu *xcu);
+
+typedef struct {
+	u32 argOffset;
+	u32 argSize;
+	u32 argValue[];
+} descEntry_t;
+
+typedef struct {
+	u32 status;
+	u32 numInputEntries;
+	u32 inputEntryBytes;
+	u32 numOutputEntries;
+	u32 outputEntryBytes;
+	u32 data[];
+} descriptor_t;
+
+#define to_cu_fa(core) ((struct xrt_cu_fa *)(core))
+struct xrt_cu_fa {
+	void __iomem		*vaddr;
+	void __iomem		*plram;
+	u64			 paddr;
+	u32			 slot_sz;
+	u32			 num_slots;
+	u32			 head_slot;
+	u32			 desc_msw;
+	u32			 task_cnt;
+	int			 max_credits;
+	int			 credits;
+	int			 run_cnts;
+	u64			 check_count;
+};
+
+int xrt_cu_fa_init(struct xrt_cu *xcu);
+void xrt_cu_fa_fini(struct xrt_cu *xcu);
+
+/* PLRAM CU -- deprecated
+ * TODO: Delete this type of CU once fast adapter is full supported
+ */
+struct xrt_cu_plram {
+	void __iomem		*vaddr;
+	void __iomem		*plram;
+	int			 max_credits;
+	int			 credits;
+};
+
+int xrt_cu_plram_init(struct xrt_cu *xcu);
+void xrt_cu_plram_fini(struct xrt_cu *xcu);
+
+#endif /* _XRT_CU_H */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/include/xrt_drv.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/include/xrt_drv.h
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * A GEM style device manager for PCIe based OpenCL accelerators.
+ *
+ * Copyright (C) 2019-2020 Xilinx, Inc. All rights reserved.
+ *
+ * Authors:
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#ifndef _XRT_DRV_H
+#define _XRT_DRV_H
+
+#define XRT_DRV_BO_DEVICE_MEM 	(1 << 31)
+#define XRT_DRV_BO_HOST_MEM	(1 << 30)
+#define XRT_DRV_BO_DRV_ALLOC	(1 << 29)
+#define XRT_DRV_BO_DRM_IMPORT 	(1 << 28)
+#define XRT_DRV_BO_P2P		(1 << 27)
+#define XRT_DRV_BO_DRM_SHMEM	(1 << 26)
+#define XRT_DRV_BO_USER_ALLOC	(1 << 25)
+#define XRT_DRV_BO_CMA		(1 << 24)
+#define XRT_DRV_BO_CACHEABLE	(1 << 23)
+#define XRT_DRV_BO_SGL		(1 << 22)
+#define XRT_DRV_BO_KERN_BUF	(1 << 21)
+
+/* Versal transfer cache packet definition */
+
+#define	XRT_XFR_VER			1
+
+/*
+ * Note: we should keep the existing PKT status and flags
+ *       stable to not breaking the old versal platform
+ */
+#define	XRT_XFR_PKT_STATUS_IDLE		0
+#define	XRT_XFR_PKT_STATUS_NEW		1
+#define	XRT_XFR_PKT_STATUS_DONE		2
+#define	XRT_XFR_PKT_STATUS_FAIL		3
+
+#define	XRT_XFR_PKT_TYPE_SHIFT		1
+#define	XRT_XFR_PKT_TYPE_MASK		7
+
+#define	XRT_XFR_PKT_VER_SHIFT		4
+#define	XRT_XFR_PKT_VER_MASK		3
+
+#define	XRT_XFR_PKT_TYPE_PDI		0
+#define	XRT_XFR_PKT_TYPE_XCLBIN		1
+
+#define	XRT_XFR_PKT_FLAGS_LAST		(1 << 0)
+#define	XRT_XFR_PKT_FLAGS_PDI		(XRT_XFR_PKT_TYPE_PDI << \
+	XRT_XFR_PKT_TYPE_SHIFT)
+#define	XRT_XFR_PKT_FLAGS_XCLBIN	(XRT_XFR_PKT_TYPE_XCLBIN << \
+	XRT_XFR_PKT_TYPE_SHIFT)
+#define	XRT_XFR_PKT_FLAGS_VER		(XRT_XFR_VER << XRT_XFR_PKT_VER_SHIFT)
+
+struct pdi_packet {
+	union {
+		struct {
+			u8	pkt_status;
+			u8	pkt_flags;
+			u16	pkt_size;
+		};
+		u32 header;
+	};
+} __packed;
+
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/include/xrt_error_code.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/include/xrt_error_code.h
@@ -0,0 +1,152 @@
+/*
+ *  Copyright (C) 2020, Xilinx Inc
+ *
+ *  This file is dual licensed.  It may be redistributed and/or modified
+ *  under the terms of the Apache 2.0 License OR version 2 of the GNU
+ *  General Public License.
+ *
+ *  Apache License Verbiage
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  GPL license Verbiage:
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License as
+ *  published by the Free Software Foundation; either version 2 of the
+ *  License, or (at your option) any later version.  This program is
+ *  distributed in the hope that it will be useful, but WITHOUT ANY
+ *  WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ *  License for more details.  You should have received a copy of the
+ *  GNU General Public License along with this program; if not, write
+ *  to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ *  Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef XRT_ERROR_CODE_H_
+#define XRT_ERROR_CODE_H_
+
+#if defined(__KERNEL__)
+# include <linux/types.h>
+#else
+# include <stdint.h>
+#endif
+
+/**
+ * xrtErrorCode layout
+ *
+ * This layout is internal to XRT (akin to a POSIX error code).
+ *
+ * The error code is populated by driver and consumed by XRT
+ * implementation where it is translated into an actual error / info /
+ * warning that is propagated to the end user.
+ *
+ * 63 - 48  47 - 40   39 - 32   31 - 24   23 - 16    15 - 0
+ * --------------------------------------------------------
+ * |    |    |    |    |    |    |    |    |    |    |----| xrtErrorNum
+ * |    |    |    |    |    |    |    |    |----|---------- xrtErrorDriver
+ * |    |    |    |    |    |    |----|-------------------- xrtErrorSeverity
+ * |    |    |    |    |----|------------------------------ xrtErrorModule
+ * |    |    |----|---------------------------------------- xrtErrorClass
+ * |----|-------------------------------------------------- reserved
+ *
+ */
+typedef uint64_t xrtErrorCode;
+typedef uint64_t xrtErrorTime;
+
+#define XRT_ERROR_NUM_MASK		0xFFFFUL
+#define XRT_ERROR_NUM_SHIFT		0
+#define XRT_ERROR_DRIVER_MASK		0xFUL
+#define XRT_ERROR_DRIVER_SHIFT		16
+#define XRT_ERROR_SEVERITY_MASK		0xFUL
+#define XRT_ERROR_SEVERITY_SHIFT	24
+#define XRT_ERROR_MODULE_MASK		0xFUL
+#define XRT_ERROR_MODULE_SHIFT		32
+#define XRT_ERROR_CLASS_MASK		0xFUL
+#define XRT_ERROR_CLASS_SHIFT		40
+
+#define	XRT_ERROR_CODE_BUILD(num, driver, severity, module, eclass) \
+	((((num) & XRT_ERROR_NUM_MASK) << XRT_ERROR_NUM_SHIFT) | \
+	(((driver) & XRT_ERROR_DRIVER_MASK) << XRT_ERROR_DRIVER_SHIFT) | \
+	(((severity) & XRT_ERROR_SEVERITY_MASK) << XRT_ERROR_SEVERITY_SHIFT) | \
+	(((module) & XRT_ERROR_MODULE_MASK) << XRT_ERROR_MODULE_SHIFT) | \
+	(((eclass) & XRT_ERROR_CLASS_MASK) << XRT_ERROR_CLASS_SHIFT))
+
+#define XRT_ERROR_NUM(code) (((code) >> XRT_ERROR_NUM_SHIFT) & XRT_ERROR_NUM_MASK)
+#define XRT_ERROR_DRIVER(code) (((code) >> XRT_ERROR_DRIVER_SHIFT) & XRT_ERROR_DRIVER_MASK)
+#define XRT_ERROR_SEVERITY(code) (((code) >> XRT_ERROR_SEVERITY_SHIFT) & XRT_ERROR_SEVERITY_MASK)
+#define XRT_ERROR_MODULE(code) (((code) >> XRT_ERROR_MODULE_SHIFT) & XRT_ERROR_MODULE_MASK)
+#define XRT_ERROR_CLASS(code) (((code) >> XRT_ERROR_CLASS_SHIFT) & XRT_ERROR_CLASS_MASK)
+
+/**
+ * xrt_error_num - XRT specific error numbers
+ */
+enum xrtErrorNum {
+  XRT_ERROR_NUM_FIRWWALL_TRIP = 1,
+  XRT_ERROR_NUM_TEMP_HIGH,
+  XRT_ERROR_NUM_AIE_SATURATION,
+  XRT_ERROR_NUM_AIE_FP,
+  XRT_ERROR_NUM_AIE_STREAM,
+  XRT_ERROR_NUM_AIE_ACCESS,
+  XRT_ERROR_NUM_AIE_BUS,
+  XRT_ERROR_NUM_AIE_INSTRUCTION,
+  XRT_ERROR_NUM_AIE_ECC,
+  XRT_ERROR_NUM_AIE_LOCK,
+  XRT_ERROR_NUM_AIE_DMA,
+  XRT_ERROR_NUM_AIE_MEM_PARITY,
+  XRT_ERROR_NUM_UNKNOWN
+};
+
+enum xrtErrorDriver {
+  XRT_ERROR_DRIVER_XOCL = 1,
+  XRT_ERROR_DRIVER_XCLMGMT,
+  XRT_ERROR_DRIVER_ZOCL,
+  XRT_ERROR_DRIVER_AIE,
+  XRT_ERROR_DRIVER_UNKNOWN
+};
+
+enum xrtErrorSeverity {
+  XRT_ERROR_SEVERITY_EMERGENCY = 1,
+  XRT_ERROR_SEVERITY_ALERT,
+  XRT_ERROR_SEVERITY_CRITICAL,
+  XRT_ERROR_SEVERITY_ERROR,
+  XRT_ERROR_SEVERITY_WARNING,
+  XRT_ERROR_SEVERITY_NOTICE,
+  XRT_ERROR_SEVERITY_INFO,
+  XRT_ERROR_SEVERITY_DEBUG,
+  XRT_ERROR_SEVERITY_UNKNOWN
+};
+
+enum xrtErrorModule {
+  XRT_ERROR_MODULE_FIREWALL = 1,
+  XRT_ERROR_MODULE_CMC,
+  XRT_ERROR_MODULE_AIE_CORE,
+  XRT_ERROR_MODULE_AIE_MEMORY,
+  XRT_ERROR_MODULE_AIE_SHIM,
+  XRT_ERROR_MODULE_AIE_NOC,
+  XRT_ERROR_MODULE_AIE_PL,
+  XRT_ERROR_MODULE_UNKNOWN
+};
+
+enum xrtErrorClass {
+  XRT_ERROR_CLASS_FIRST_ENTRY = 1,
+  XRT_ERROR_CLASS_SYSTEM = XRT_ERROR_CLASS_FIRST_ENTRY,
+  XRT_ERROR_CLASS_AIE,
+  XRT_ERROR_CLASS_HARDWARE,
+  XRT_ERROR_CLASS_UNKNOWN,
+  XRT_ERROR_CLASS_LAST_ENTRY = XRT_ERROR_CLASS_UNKNOWN
+};
+
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/include/xrt_mem.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/include/xrt_mem.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2019, Xilinx Inc - All rights reserved.
+ * Xilinx Runtime (XRT) APIs
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"). You may
+ * not use this file except in compliance with the License. A copy of the
+ * License is located at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _XRT_MEM_H_
+#define _XRT_MEM_H_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * XCL BO Flags bits layout
+ *
+ * bits  0 ~ 15: DDR BANK index
+ * bits 24 ~ 31: BO flags
+ */
+#define XRT_BO_FLAGS_MEMIDX_MASK	(0xFFFFFFUL)
+#define	XCL_BO_FLAGS_NONE		(0)
+#define	XCL_BO_FLAGS_CACHEABLE		(1U << 24)
+#define	XCL_BO_FLAGS_KERNBUF		(1U << 25)
+#define	XCL_BO_FLAGS_SGL		(1U << 26)
+#define	XCL_BO_FLAGS_SVM		(1U << 27)
+#define	XCL_BO_FLAGS_DEV_ONLY		(1U << 28)
+#define	XCL_BO_FLAGS_HOST_ONLY		(1U << 29)
+#define	XCL_BO_FLAGS_P2P		(1U << 30)
+#define	XCL_BO_FLAGS_EXECBUF		(1U << 31)
+
+/**
+ * XRT Native BO flags
+ *
+ * These flags are simple aliases for use with XRT native BO APIs.
+ */
+#define XRT_BO_FLAGS_NONE      XCL_BO_FLAGS_NONE
+#define XRT_BO_FLAGS_CACHEABLE XCL_BO_FLAGS_CACHEABLE
+#define XRT_BO_FLAGS_DEV_ONLY  XCL_BO_FLAGS_DEV_ONLY
+#define XRT_BO_FLAGS_HOST_ONLY XCL_BO_FLAGS_HOST_ONLY
+#define XRT_BO_FLAGS_P2P       XCL_BO_FLAGS_P2P
+
+/**
+ * This is the legacy usage of XCL DDR Flags.
+ *
+ * byte-0 lower 4 bits for DDR Flags are one-hot encoded
+ */
+enum xclDDRFlags {
+    XCL_DEVICE_RAM_BANK0 = 0x00000000,
+    XCL_DEVICE_RAM_BANK1 = 0x00000002,
+    XCL_DEVICE_RAM_BANK2 = 0x00000004,
+    XCL_DEVICE_RAM_BANK3 = 0x00000008,
+};
+
+#ifdef __cplusplus
+}
+#endif
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/include/xrt_xclbin.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/include/xrt_xclbin.h
@@ -0,0 +1,73 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * Xilinx Kernel Driver XCLBIN parser
+ *
+ * Copyright (C) 2020 Xilinx, Inc. All rights reserved.
+ *
+ * Authors: David Zhang <davidzha@xilinx.com>
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#ifndef _XRT_XCLBIN_H
+#define _XRT_XCLBIN_H
+
+#include <linux/types.h>
+
+/* Used for parsing bitstream header */
+#define XHI_EVEN_MAGIC_BYTE     0x0f
+#define XHI_ODD_MAGIC_BYTE      0xf0
+
+/* Extra mode for IDLE */
+#define XHI_OP_IDLE  -1
+#define XHI_BIT_HEADER_FAILURE -1
+
+/* The imaginary module length register */
+#define XHI_MLR                  15
+
+#define DMA_HWICAP_BITFILE_BUFFER_SIZE 1024
+
+enum axlf_section_kind;
+struct axlf_section_header;
+struct axlf;
+
+/**
+ * Bitstream header information.
+ */
+struct XHwIcap_Bit_Header {
+	unsigned int HeaderLength;     /* Length of header in 32 bit words */
+	unsigned int BitstreamLength;  /* Length of bitstream to read in bytes*/
+	unsigned char *DesignName;     /* Design name get from bitstream */
+	unsigned char *PartName;       /* Part name read from bitstream */
+	unsigned char *Date;           /* Date read from bitstream header */
+	unsigned char *Time;           /* Bitstream creation time*/
+	unsigned int MagicLength;      /* Length of the magic numbers*/
+};
+
+int
+xrt_xclbin_parse_header(const unsigned char *data,
+	unsigned int size, struct XHwIcap_Bit_Header *header);
+
+void
+xrt_xclbin_free_header(struct XHwIcap_Bit_Header *header);
+
+char *
+xrt_xclbin_kind_to_string(enum axlf_section_kind kind);
+
+const struct axlf_section_header *
+xrt_xclbin_get_section_hdr(const struct axlf *xclbin, enum axlf_section_kind kind);
+
+int
+xrt_xclbin_check_section_hdr(const struct axlf_section_header *header,
+	uint64_t xclbin_len);
+
+int
+xrt_xclbin_section_info(const struct axlf *xclbin, enum axlf_section_kind kind,
+	uint64_t *offset, uint64_t *size);
+
+int
+xrt_xclbin_get_section(const struct axlf *xclbin,
+	enum axlf_section_kind kind, void **data, uint64_t *len);
+
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/include/zocl_aie.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/include/zocl_aie.h
@@ -0,0 +1,152 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * Copyright (C) 2020 Xilinx, Inc. All rights reserved.
+ *
+ * Authors:
+ *    Larry Liu <yliu@xilinx.com>
+ *    Himanshu Choudhary <hchoudha@xilinx.com>
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#ifndef _ZOCL_AIE_H_
+#define _ZOCL_AIE_H_
+
+#include <drm/zynq_ioctl.h>
+
+/* Wait 100 * 1 ms before AIE parition is availabe after reset */
+#define	ZOCL_AIE_RESET_TIMEOUT_INTERVAL	1
+#define	ZOCL_AIE_RESET_TIMEOUT_NUMBER	100
+
+#define	ZOCL_AIE_ERROR_CACHE_CAP	8
+
+struct aie_work_data {
+	struct work_struct work;
+	struct drm_zocl_dev *zdev;
+};
+
+struct aie_error_cache {
+	u32			num;		/* Cached error # */
+	u32			cap;		/* Cache capacity */
+	struct aie_error	*errors;	/* Error array */
+};
+
+struct zocl_aie {
+	struct device	*aie_dev;	/* AI engine partition device */
+	u32		partition_id;	/* Partition ID */
+	u32		uid;		/* Imiage identifier loaded */
+	u32		fd_cnt;		/* # of fd requested */
+	bool		aie_reset;	/* If AIE is reset */
+
+	struct aie_error_cache	err;	/* AIE error cache */
+	struct workqueue_struct *wq;	/* AIE work queue */
+};
+
+#ifdef __NONE_PETALINUX__
+
+#define AIE_ERROR_CATEGORY_SATURATION		0U
+#define AIE_ERROR_CATEGORY_FP			1U
+#define AIE_ERROR_CATEGORY_STREAM		2U
+#define AIE_ERROR_CATEGORY_ACCESS		3U
+#define AIE_ERROR_CATEGORY_BUS			4U
+#define AIE_ERROR_CATEGORY_INSTRUCTION		5U
+#define AIE_ERROR_CATEGORY_ECC			6U
+#define AIE_ERROR_CATEGORY_LOCK			7U
+#define AIE_ERROR_CATEGORY_DMA			8U
+#define AIE_ERROR_CATEGORY_MEM_PARITY		9U
+
+enum aie_module_type {
+	AIE_MEM_MOD,
+	AIE_CORE_MOD,
+	AIE_PL_MOD,
+	AIE_NOC_MOD,
+};
+
+struct aie_location {
+	__u32 col;
+	__u32 row;
+};
+
+struct aie_partition_req {
+	__u32 partition_id;
+	__u32 uid;
+	__u64 meta_data;
+	__u32 flag;
+};
+
+struct aie_error {
+	struct aie_location loc;
+	enum aie_module_type module;
+	u32 error_id;
+	u32 category;
+};
+
+struct aie_errors {
+	struct device *dev;
+	struct aie_error *errors;
+	u32 num_err;
+};
+
+static inline struct device *
+aie_partition_request(struct aie_partition_req *req)
+{
+	return NULL;
+}
+
+static inline int
+aie_partition_get_fd(struct device *aie_dev)
+{
+	return -EINVAL;
+
+}
+
+static inline void aie_partition_release(struct device *dev) {}
+
+static inline bool
+aie_partition_is_available(struct aie_partition_req *req)
+{
+	return false;
+}
+
+static inline int
+aie_register_error_notification(struct device *dev, void (*cb)(void *priv),
+		void *priv)
+{
+	return -1;
+}
+
+static inline struct aie_errors *
+aie_get_errors(struct device *dev)
+{
+	return NULL;
+}
+
+static inline void
+aie_free_errors(struct aie_errors *aie_errs)
+{
+}
+#endif
+
+struct aie_info {
+	struct list_head	aie_cmd_list;
+	struct mutex		aie_lock;
+	struct aie_info_cmd	*cmd_inprogress;
+	wait_queue_head_t	aie_wait_queue;
+};
+
+struct aie_info_packet {
+	enum aie_info_code	opcode;
+	uint32_t		size;
+	char			info[AIE_INFO_SIZE];
+};
+
+struct aie_info_cmd {
+	struct list_head	aiec_list;
+	struct semaphore	aiec_sem;
+	struct aie_info_packet	*aiec_packet;
+};
+
+int zocl_init_aie(struct drm_zocl_dev *zdev);
+
+#endif /* _ZOCL_AIE_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/include/zocl_bo.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/include/zocl_bo.h
@@ -0,0 +1,76 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * A GEM style (optionally CMA backed) device manager for ZynQ based
+ * OpenCL accelerators.
+ *
+ * Copyright (C) 2019 Xilinx, Inc. All rights reserved.
+ *
+ * Authors:
+ *    Larry Liu    <yliu@xilinx.com>
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#ifndef _ZOCL_BO_H
+#define _ZOCL_BO_H
+
+#include "xclhal2_mem.h"
+
+/**
+ * XCL BO Flags bits layout
+ *
+ * bits  0 ~ 15: DDR BANK index
+ * bits 16 ~ 31: BO flags
+ *
+ * TODO These flags are copied from old xclhal2_mem.h. BO flags
+ * in current xclhal2_mem.h are modified. To prevent zocl from
+ * being broken, we keep a copy of old flags and implement a
+ * converter from the new flags to these old ones. These flags
+ * will be removed when we implement BO BO BO project at edge
+ * side.
+ */
+#define ZOCL_BO_FLAGS_CACHEABLE		(1 << 24)
+#define ZOCL_BO_FLAGS_HOST_BO		(1 << 25)
+#define ZOCL_BO_FLAGS_COHERENT		(1 << 26)
+#define ZOCL_BO_FLAGS_SVM		(1 << 27)
+#define ZOCL_BO_FLAGS_USERPTR		(1 << 28)
+#define ZOCL_BO_FLAGS_CMA		(1 << 29)
+#define ZOCL_BO_FLAGS_P2P		(1 << 30)
+#define ZOCL_BO_FLAGS_EXECBUF		(1 << 31)
+
+/* BO types we support */
+#define ZOCL_BO_NORMAL	(XRT_DRV_BO_HOST_MEM | XRT_DRM_SHMEM | \
+			XRT_DRV_BO_DRM_ALLOC)
+#define ZOCL_BO_EXECBUF	(ZOCL_BO_NORMAL)
+#define ZOCL_BO_CACHE	(ZOCL_BO_NORMAL | XRT_CACHEABLE)
+#define ZOCL_BO_USERPTR	(XRT_USER_MEM | XRT_DRV_BO_USER_ALLOC)
+#define ZOCL_BO_SVM	(XRT_DRV_BO_HOST_MEM | XRT_DRM_SHMEM | \
+			XRT_DRV_BO_DRM_ALLOC)
+#define ZOCL_BO_PL_DDR	(XRT_DEVICE_MEM)
+#define ZOCL_BO_HOST_BO	(XRT_DRV_BO_HOST_MEM)
+#define ZOCL_BO_IMPORT	(XRT_DRM_IMPORT | XRT_DRV_BO_HOST_MEM)
+
+static inline uint32_t zocl_convert_bo_uflags(uint32_t uflags)
+{
+	uint32_t zflags = 0;
+
+	/*
+	 * Keep the bank index and remove all flags, except EXECBUF and
+	 * CACHEABLE.
+	 */
+	if (uflags & XCL_BO_FLAGS_EXECBUF)
+		zflags |= ZOCL_BO_FLAGS_EXECBUF;
+
+	if (uflags & XCL_BO_FLAGS_CACHEABLE)
+		zflags |= ZOCL_BO_FLAGS_CACHEABLE;
+
+	zflags |= (uflags & 0xFFFF);
+
+	return zflags;
+}
+
+struct drm_gem_object *
+zocl_gem_import(struct drm_device *dev, struct dma_buf *dma_buf);
+
+#endif /* _ZOCL_BO_H */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/include/zocl_cu.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/include/zocl_cu.h
@@ -0,0 +1,187 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * Compute unit structures.
+ *
+ * Copyright (C) 2019-2020 Xilinx, Inc. All rights reserved.
+ *
+ * Authors:
+ *    Min Ma <min.ma@xilinx.com>
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#ifndef _ZOCL_CU_H_
+#define _ZOCL_CU_H_
+
+#include <linux/types.h>
+
+#include "zocl_util.h"
+
+#define U32_MASK 0xFFFFFFFF
+
+#define ZOCL_KDS_MASK		(~0xFF)
+#define ZOCL_CU_FREE_RUNNING	(U32_MASK & ZOCL_KDS_MASK)
+
+#define CU_INTR_DONE  0x1
+#define CU_INTR_READY 0x2
+
+#define CU_VERSION_MASK         0x00000F00
+#define CU_MAX_CAP_MASK         0x0000F000
+#define CU_READY_CNT_MASK       0x00FF0000
+#define CU_DONE_CNT_MASK        0xFF000000
+
+#define CU_AP_START	(0x1 << 0)
+#define CU_AP_DONE	(0x1 << 1)
+#define CU_AP_IDLE	(0x1 << 2)
+#define CU_AP_READY	(0x1 << 3)
+#define CU_AP_CONTINUE	(0x1 << 4)
+#define CU_AP_RESET	(0x1 << 5)
+
+struct zocl_cu;
+
+/* Supported CU models */
+enum zcu_model {
+	MODEL_ACC,
+	MODEL_HLS,
+};
+
+enum zcu_configure_type {
+	PAIRS,
+	CONSECUTIVE,
+};
+
+struct zcu_tasks_info {
+	u32	num_tasks_done;
+	u32	num_tasks_ready;
+};
+
+struct zcu_core {
+	phys_addr_t		 paddr;
+	u32 __iomem		*vaddr;
+	u32			 max_credits;
+	u32			 credits;
+	u32			 intr_type;
+	u32			 pending_intr;
+	u32			 running;
+	u32			 control;
+};
+
+struct zcu_funcs {
+	/**
+	 * @get_credit:
+	 *
+	 * Try to get one credit from the CU. A credit is required before
+	 * submit a task to the CU. Otherwise, it would lead to unknown CU
+	 * behaviour.
+	 * Return: the number of remaining credit.
+	 */
+	int (*get_credit)(void *core);
+
+	/**
+	 * @refund_credit:
+	 *
+	 * refund credit to the CU.
+	 */
+	void (*refund_credit)(void *core, u32 count);
+
+	/**
+	 * @configure:
+	 *
+	 * Congifure CU registers. It supports two types of configuration
+	 * format.
+	 *
+	 * 1. CONSECUTIVE: Which is a blind copy from data to CU.
+	 * 2. PAIRS: The data contains {addr, val} pairs.
+	 */
+	void (*configure)(void *core, u32 *data, size_t sz, int type);
+
+	/**
+	 * @start:
+	 *
+	 * Start a CU.
+	 */
+	void (*start)(void *core);
+
+	/**
+	 * @check:
+	 *
+	 * Check CU status and the pending task status.
+	 */
+	void (*check)(void *core, struct zcu_tasks_info *tasks);
+
+	/**
+	 * @reset:
+	 *
+	 * Reset CU.
+	 */
+	void (*reset)(void *core);
+
+	/**
+	 * @reset_done:
+	 *
+	 * Check if CU is properly reset
+	 */
+	int (*reset_done)(void *core);
+
+	/**
+	 * @enable_intr:
+	 *
+	 * Enable interrupt. Support DONE and READY interrupt.
+	 */
+	void (*enable_intr)(void *core, u32 intr_type);
+
+	/**
+	 * @disable_intr:
+	 *
+	 * Disable interrupt.
+	 */
+	void (*disable_intr)(void *core, u32 intr_type);
+
+	/**
+	 * @clear_intr:
+	 *
+	 * Clear interrupt.
+	 */
+	u32 (*clear_intr)(void *core);
+};
+
+struct zocl_cu {
+	enum zcu_model	          model;
+	struct list_head	  running_queue;
+	void                     *core;
+	u32			  usage;
+	u32			  done_cnt;
+	u32			  ready_cnt;
+	u32                       run_timeout;
+	u32                       reset_timeout;
+	u32			  irq;
+	char			 *irq_name;
+	/**
+	 * @funcs:
+	 *
+	 * Compute unit functions. Use these functions for operating the CU.
+	 */
+	struct zcu_funcs          *funcs;
+};
+
+int zocl_cu_init(struct zocl_cu *cu, enum zcu_model m, phys_addr_t paddr);
+int zocl_cu_fini(struct zocl_cu *cu);
+
+int  zocl_cu_get_credit(struct zocl_cu *cu);
+void zocl_cu_refund_credit(struct zocl_cu *cu, u32 count);
+void zocl_cu_configure(struct zocl_cu *cu, u32 *data, size_t sz, int type);
+void zocl_cu_start(struct zocl_cu *cu);
+void zocl_cu_check(struct zocl_cu *cu);
+void zocl_cu_reset(struct zocl_cu *cu);
+int  zocl_cu_reset_done(struct zocl_cu *cu);
+void zocl_cu_enable_intr(struct zocl_cu *cu, u32 intr_type);
+void zocl_cu_disable_intr(struct zocl_cu *cu, u32 intr_type);
+u32  zocl_cu_clear_intr(struct zocl_cu *cu);
+
+phys_addr_t zocl_cu_get_paddr(struct zocl_cu *cu);
+void zocl_cu_status_print(struct zocl_cu *cu);
+int zocl_cu_status_get(struct zocl_cu *cu);
+u32 zocl_cu_get_control(struct zocl_cu *cu);
+
+#endif /* _ZOCL_CU_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/include/zocl_dma.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/include/zocl_dma.h
@@ -0,0 +1,78 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * A GEM style (optionally CMA backed) device manager for ZynQ based
+ * OpenCL accelerators.
+ *
+ * Copyright (C) 2016-2020 Xilinx, Inc. All rights reserved.
+ *
+ * Authors:
+ *    Sonal Santan <sonal.santan@xilinx.com>
+ *    Umang Parekh <umang.parekh@xilinx.com>
+ *    Jan Stephan  <j.stephan@hzdr.de>
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+
+/**
+ * DOC: Embedded driver handler interface for DMA
+ *
+ * Internal interfaces designed for interacting with Embedded Linux DMA Engine.
+ */
+#ifndef _ZOCL_DMA_H_
+#define _ZOCL_DMA_H_
+
+#define ZOCL_DMA_DONE	(1 << 0)
+#define ZOCL_DMA_ERROR	(1 << 1)
+
+typedef void (*zocl_dma_complete_cb)(void *arg, int ret);
+
+/**
+ * struct zocl_dma_handle - DMA handler for zocl driver
+ *
+ * @dma_flags: indicate if DMA returns error
+ * @dma_chan: DMA Channel, acquired before use DMA
+ * @dma_cookie: DMA Engine cookie
+ * @dma_done: DMA completion opaque
+ * @dma_func: call back function when dma complete
+ * @dma_arg: private data for dma_func call back function
+ *
+ * Prior to pass this handler to ZOCL DMA Engine, user can set dma_func and
+ * dma_arg for handling subsequent asynchronous operations. When DMA is
+ * completed the dma_func will be called with dma_arg. DMA error is returned
+ * via zocl_dma_complete_cb argument ret.
+ */
+typedef struct zocl_dma_handle {
+	int			dma_flags;
+	struct dma_chan		*dma_chan;
+	dma_cookie_t		dma_cookie;
+	struct completion	dma_done;
+	zocl_dma_complete_cb	dma_func;
+	void			*dma_arg;
+} zocl_dma_handle_t;
+
+/**
+ * zocl_dma_memcpy_pre() - DMA memory copy preparation.
+ *
+ * @dma_handle: zocl dma handler
+ * @dst_paddr: destination dma address
+ * @src_paddr: source dma address
+ * @size: number of bytes to read from source
+ */
+int zocl_dma_memcpy_pre(zocl_dma_handle_t *dma_handle, dma_addr_t dst_paddr,
+			dma_addr_t src_paddr, size_t size);
+
+/**
+ * zocl_dma_start() - Start DMA Engine.
+ *
+ * @dma_handle: zocl dma handler
+ *
+ * Common API for starting async DMA Engine. Current ZOCL DMA Engine only
+ * support memcpy, it can be enhanced for other type of DMAs when necessary.
+ */
+void zocl_dma_start(zocl_dma_handle_t *dma_handle);
+
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/include/zocl_drv.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/include/zocl_drv.h
@@ -0,0 +1,268 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * A GEM style (optionally CMA backed) device manager for ZynQ based
+ * OpenCL accelerators.
+ *
+ * Copyright (C) 2016-2020 Xilinx, Inc. All rights reserved.
+ *
+ * Authors:
+ *    Sonal Santan <sonal.santan@xilinx.com>
+ *    Umang Parekh <umang.parekh@xilinx.com>
+ *    Jan Stephan  <j.stephan@hzdr.de>
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#ifndef _ZOCL_DRV_H_
+#define _ZOCL_DRV_H_
+#include <drm/drm.h>
+#include <drm/drm_device.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_gem.h>
+#include <drm/drm_mm.h>
+#include <drm/drm_gem_cma_helper.h>
+#include <linux/version.h>
+#include <linux/poll.h>
+#include "zocl_util.h"
+#include <drm/zocl_ioctl.h>
+#include "zocl_ert.h"
+#include "zocl_bo.h"
+#include "zocl_dma.h"
+#include "zocl_ospi_versal.h"
+#include "xrt_cu.h"
+
+#if defined(CONFIG_ARM64)
+#define ZOCL_PLATFORM_ARM64   1
+#else
+#define ZOCL_PLATFORM_ARM64   0
+#endif
+
+/* Ensure compatibility with newer kernels and backported Red Hat kernels. */
+/* The y2k38 bug fix was introduced with Kernel 3.17 and backported to Red Hat
+ * 7.2.
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)
+	#define ZOCL_TIMESPEC struct timespec64
+	#define ZOCL_GETTIME ktime_get_real_ts64
+	#define ZOCL_USEC tv_nsec / NSEC_PER_USEC
+#elif defined(RHEL_RELEASE_CODE)
+	#if RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7, 2)
+		#define ZOCL_TIMESPEC struct timespec64
+		#define ZOCL_GETTIME ktime_get_real_ts64
+		#define ZOCL_USEC tv_nsec / NSEC_PER_USEC
+	#else
+		#define ZOCL_TIMESPEC struct timeval
+		#define ZOCL_GETTIME do_gettimeofday
+		#define ZOCL_USEC tv_usec
+	#endif
+#else
+	#define ZOCL_TIMESPEC struct timeval
+	#define ZOCL_GETTIME do_gettimeofday
+	#define ZOCL_USEC tv_usec
+#endif
+
+/* drm_gem_object_put_unlocked was introduced with Kernel 4.12 and backported to
+ * Red Hat 7.5
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
+	#define ZOCL_DRM_GEM_OBJECT_PUT_UNLOCKED drm_gem_object_put_unlocked
+#elif defined(RHEL_RELEASE_CODE)
+	#if RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7, 5)
+		#define ZOCL_DRM_GEM_OBJECT_PUT_UNLOCKED \
+			drm_gem_object_put_unlocked
+	#else
+		#define ZOCL_DRM_GEM_OBJECT_PUT_UNLOCKED \
+			drm_gem_object_unreference_unlocked
+	#endif
+#else
+	#define ZOCL_DRM_GEM_OBJECT_PUT_UNLOCKED \
+		drm_gem_object_unreference_unlocked
+#endif
+
+/* drm_dev_put was introduced with Kernel 4.15 and backported to Red Hat 7.6. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+	#define ZOCL_DRM_DEV_PUT drm_dev_put
+#elif defined(RHEL_RELEASE_CODE)
+	#if RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7, 6)
+		#define ZOCL_DRM_DEV_PUT drm_dev_put
+	#else
+		#define ZOCL_DRM_DEV_PUT drm_dev_unref
+	#endif
+#else
+	#define ZOCL_DRM_DEV_PUT drm_dev_unref
+#endif
+
+/* access_ok lost its first parameter with Linux 5.0. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
+	#define ZOCL_ACCESS_OK(TYPE, ADDR, SIZE) access_ok(ADDR, SIZE)
+#else
+	#define ZOCL_ACCESS_OK(TYPE, ADDR, SIZE) access_ok(TYPE, ADDR, SIZE)
+#endif
+
+struct drm_zocl_exec_metadata {
+	enum drm_zocl_execbuf_state state;
+	unsigned int                index;
+};
+
+struct zocl_drv_private {
+	void		       *ops;
+};
+
+struct drm_zocl_bo {
+	union {
+		struct drm_gem_cma_object       cma_base;
+		struct {
+			struct drm_gem_object         gem_base;
+			struct page                 **pages;
+			struct sg_table              *sgt;
+			void                         *vmapping;
+			uint64_t                      uaddr;
+		};
+	};
+	struct drm_mm_node            *mm_node;
+	struct drm_zocl_exec_metadata  metadata;
+	unsigned int                   bank;
+	uint32_t                       flags;
+};
+
+struct drm_zocl_copy_bo {
+	uint32_t dst_handle;
+	uint32_t src_handle;
+	uint64_t size;
+	uint64_t dst_offset;
+	uint64_t src_offset;
+};
+
+static inline struct drm_gem_object *
+zocl_gem_object_lookup(struct drm_device *dev,
+		struct drm_file   *filp,
+		u32                handle)
+{
+	return drm_gem_object_lookup(filp, handle);
+}
+
+static inline struct
+drm_zocl_bo *to_zocl_bo(struct drm_gem_object *bo)
+{
+	return (struct drm_zocl_bo *) bo;
+}
+
+static inline bool
+zocl_bo_userptr(const struct drm_zocl_bo *bo)
+{
+	return (bo->flags & ZOCL_BO_FLAGS_USERPTR);
+}
+
+static inline bool
+zocl_bo_execbuf(const struct drm_zocl_bo *bo)
+{
+	return (bo->flags & ZOCL_BO_FLAGS_EXECBUF);
+}
+
+static inline struct kernel_info *
+zocl_query_kernel(struct drm_zocl_dev *zdev, const char *name)
+{
+	struct kernel_info *kernel;
+	int off = 0;
+
+	while (off < zdev->ksize) {
+		kernel = (struct kernel_info *)(zdev->kernels + off);
+		if (!strcmp(kernel->name, name))
+			break;
+		off += sizeof(struct kernel_info);
+		off += sizeof(struct argument_info) * kernel->anums;
+	}
+
+	if (off < zdev->ksize)
+		return kernel;
+
+	return NULL;
+}
+
+static inline int
+zocl_kds_add_cu(struct drm_zocl_dev *zdev, struct xrt_cu *xcu)
+{
+	return kds_add_cu(&zdev->kds, xcu);
+}
+
+static inline int
+zocl_kds_del_cu(struct drm_zocl_dev *zdev, struct xrt_cu *xcu)
+{
+	return kds_del_cu(&zdev->kds, xcu);
+}
+
+int zocl_copy_bo_async(struct drm_device *dev, struct drm_file *fipl,
+		zocl_dma_handle_t *handle, struct drm_zocl_copy_bo *bo);
+
+bool zocl_can_dma_performed(struct drm_device *dev, struct drm_file *filp,
+	struct drm_zocl_copy_bo *args, uint64_t *dst_paddr,
+	uint64_t *src_paddr);
+
+void zocl_describe(const struct drm_zocl_bo *obj);
+
+void zocl_free_userptr_bo(struct drm_gem_object *obj);
+void zocl_free_host_bo(struct drm_gem_object *obj);
+int zocl_iommu_map_bo(struct drm_device *dev, struct drm_zocl_bo *bo);
+int zocl_iommu_unmap_bo(struct drm_device *dev, struct drm_zocl_bo *bo);
+
+int zocl_init_sysfs(struct device *dev);
+void zocl_fini_sysfs(struct device *dev);
+void zocl_free_sections(struct drm_zocl_dev *zdev);
+void zocl_free_bo(struct drm_gem_object *obj);
+void zocl_drm_free_bo(struct drm_zocl_bo *bo);
+struct drm_zocl_bo *zocl_drm_create_bo(struct drm_device *dev,
+		uint64_t unaligned_size, unsigned user_flags);
+void zocl_update_mem_stat(struct drm_zocl_dev *zdev, u64 size,
+		int count, uint32_t bank);
+void zocl_init_mem(struct drm_zocl_dev *zdev, struct mem_topology *mtopo);
+void zocl_clear_mem(struct drm_zocl_dev *zdev);
+int zocl_create_aie(struct drm_zocl_dev *zdev, struct axlf *axlf);
+void zocl_destroy_aie(struct drm_zocl_dev *zdev);
+int zocl_aie_request_part_fd(struct drm_zocl_dev *zdev, void *data);
+int zocl_aie_reset(struct drm_zocl_dev *zdev);
+
+int zocl_inject_error(struct drm_zocl_dev *zdev, void *data,
+		struct drm_file *filp);
+int zocl_init_error(struct drm_zocl_dev *zdev);
+void zocl_fini_error(struct drm_zocl_dev *zdev);
+int zocl_insert_error_record(struct drm_zocl_dev *zdev, xrtErrorCode err_code);
+
+/* zocl_kds.c */
+int zocl_init_sched(struct drm_zocl_dev *zdev);
+void zocl_fini_sched(struct drm_zocl_dev *zdev);
+int zocl_create_client(struct drm_zocl_dev *zdev, void **priv);
+void zocl_destroy_client(struct drm_zocl_dev *zdev, void **priv);
+uint zocl_poll_client(struct file *filp, poll_table *wait);
+int zocl_command_ioctl(struct drm_zocl_dev *zdev, void *data,
+		       struct drm_file *filp);
+int zocl_context_ioctl(struct drm_zocl_dev *zdev, void *data,
+		       struct drm_file *filp);
+struct platform_device *zocl_find_pdev(char *name);
+
+int get_apt_index_by_addr(struct drm_zocl_dev *zdev, phys_addr_t addr);
+int get_apt_index_by_cu_idx(struct drm_zocl_dev *zdev, int cu_idx);
+void update_cu_idx_in_apt(struct drm_zocl_dev *zdev, int apt_idx, int cu_idx);
+
+int subdev_create_cu(struct drm_zocl_dev *zdev, struct xrt_cu_info *info);
+void subdev_destroy_cu(struct drm_zocl_dev *zdev);
+/* Sub device driver */
+extern struct platform_driver cu_driver;
+struct zocl_cu_ops {
+	int (*submit)(struct platform_device *pdev, struct kds_command *xcmd);
+};
+
+static inline int
+zocl_cu_submit_xcmd(struct drm_zocl_dev *zdev, int i, struct kds_command *xcmd)
+{
+	struct platform_device *pdev;
+	struct zocl_drv_private *priv;
+	struct zocl_cu_ops *ops;
+
+	pdev = zdev->cu_pldev[i];
+	priv = (void *)platform_get_device_id(pdev)->driver_data;
+	ops = (struct zocl_cu_ops *)priv->ops;
+	return ops->submit(pdev, xcmd);
+}
+
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/include/zocl_error.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/include/zocl_error.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * A GEM style (optionally CMA backed) device manager for ZynQ based
+ * OpenCL accelerators.
+ *
+ * Copyright (C) 2020 Xilinx, Inc. All rights reserved.
+ *
+ * Authors:
+ *    Larry Liu    <yliu@xilinx.com>
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#ifndef _ZOCL_ERROR_H
+#define _ZOCL_ERROR_H
+
+#include "xrt_error_code.h"
+
+#define	ZOCL_DEFAULT_ERROR_CAPACITY	8
+
+struct zocl_err_record {
+	xrtErrorCode	zer_err_code;	/* XRT error code */
+	u64		zer_ts;		/* timestamp */
+};
+
+struct zocl_error {
+	int		ze_num;		/* number of errors recorded */
+	int		ze_cap;		/* capacity of current error array */
+	struct zocl_err_record *ze_err;	/* error array pointer */
+};
+
+#endif /* _ZOCL_ERROR_H */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/include/zocl_ert.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/include/zocl_ert.h
@@ -0,0 +1,201 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * Copyright (C) 2016-2020 Xilinx, Inc. All rights reserved.
+ *
+ * Author(s):
+ *        Min Ma <min.ma@xilinx.com>
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#ifndef _ZOCL_ERT_H_
+#define _ZOCL_ERT_H_
+
+#include <linux/of.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include "ert.h"
+
+/* DSA and/or Device tree related */
+#define ERT_IRQ_NUMBER 2
+#define ERT_CQ_IRQ     0
+#define ERT_CU_IRQ     1
+
+#define ZOCL_ERT_HW_RES     0
+#define ZOCL_ERT_CQ_RES     1
+
+/**
+ * Address constants per spec
+ */
+#define WORD_SIZE                     4          /* 4 bytes */
+#define CQ_SIZE                       0x10000    /* 64K */
+#define CQ_SLOT_SIZE                  0x1000     /* 4K each cq slot */
+#define CQ_BASE_ADDR                  0x190000
+#define CSR_ADDR                      0x180000
+
+#define CQ_SLOT_NUM	(CQ_SIZE / CQ_SLOT_SIZE)      /* defult cq slot num = 16 */
+
+/**
+ * The STATUS REGISTER is for communicating completed CQ slot indices
+ * MicroBlaze write, host reads.  MB(W) / HOST(COR)
+ */
+#define ERT_STATUS_REG          0x0
+#define ERT_STATUS_REG0         0x0
+#define ERT_STATUS_REG1         0x4
+#define ERT_STATUS_REG2         0x8
+#define ERT_STATUS_REG3         0xC
+
+/**
+ * The CU DMA REGISTER is for communicating which CQ slot is to be started
+ * on a specific CU.  MB selects a free CU on which the command can
+ * run, then writes the 1<<CU back to the command slot CU mask and
+ * writes the slot index to the CU DMA REGISTER.  HW is notified when
+ * the register is written and now does the DMA transfer of CU regmap
+ * map from command to CU, while MB continues its work. MB(W) / HW(R)
+ */
+#define ERT_CU_DMA_ENABLE       0x18
+#define ERT_CU_DMA_REG          0x1C
+#define ERT_CU_DMA_REG0         0x1C
+#define ERT_CU_DMA_REG1         0x20
+#define ERT_CU_DMA_REG2         0x24
+#define ERT_CU_DMA_REG3         0x28
+
+/**
+ * The SLOT SIZE is the size of slots in command queue, it is
+ * configurable per xclbin. MB(W) / HW(R)
+ */
+#define ERT_CQ_SLOT_SIZE_REG    0x2C
+
+/**
+ * The CU_OFFSET is the size of a CU's address map in power of 2.  For
+ * example a 64K regmap is 2^16 so 16 is written to the CU_OFFSET_ADDR.
+ * MB(W) / HW(R)
+ */
+#define ERT_CU_OFFSET_REG       0x30
+
+/**
+ * The number of slots is command_queue_size / slot_size.
+ * MB(W) / HW(R)
+ */
+#define ERT_CQ_NUM_OF_SLOTS_REG 0x34
+
+/**
+ * All CUs placed in same address space separated by CU_OFFSET. The
+ * CU_BASE_ADDRESS is the address of the first CU. MB(W) / HW(R)
+ */
+#define ERT_CU_BASE_ADDR_REG    0x38
+
+/**
+ * The CQ_BASE_ADDRESS is the base address of the command queue.
+ * MB(W) / HW(R)
+ */
+#define ERT_CQ_BASE_ADDR_REG    0x3C
+
+/**
+ * The CU_ISR_HANDLER_ENABLE (MB(W)/HW(R)) enables the HW handling of
+ * CU interrupts.  When a CU interrupts (when done), hardware handles
+ * the interrupt and writes the index of the CU that completed into
+ * the CU_STATUS_REGISTER (HW(W)/MB(COR)) as a bitmask
+ */
+#define ERT_CU_ISR_ENABLE       0x40
+#define ERT_CU_STATUS_REG       0x44
+#define ERT_CU_STATUS_REG0      0x44
+#define ERT_CU_STATUS_REG1      0x48
+#define ERT_CU_STATUS_REG2      0x4C
+#define ERT_CU_STATUS_REG3      0x50
+
+/**
+ * The CQ_STATUS_ENABLE (MB(W)/HW(R)) enables interrupts from HOST to
+ * MB to indicate the presense of a new command in some slot.  The
+ * slot index is written to the CQ_STATUS_REGISTER (HOST(W)/MB(R))
+ */
+#define ERT_CQ_STATUS_ENABLE    0x54
+#define ERT_CQ_STATUS_REG       0x58
+#define ERT_CQ_STATUS_REG0      0x58
+#define ERT_CQ_STATUS_REG1      0x5C
+#define ERT_CQ_STATUS_REG2      0x60
+#define ERT_CQ_STATUS_REG3      0x64
+
+/**
+ * The NUMBER_OF_CU (MB(W)/HW(R) is the number of CUs per current
+ * xclbin.  This is an optimization that allows HW to only check CU
+ * completion on actual CUs.
+ */
+#define ERT_NUM_OF_CU_REG       0x68
+
+/**
+ * Enable global interrupts from MB to HOST on command completion.
+ * When enabled writing to STATUS_REGISTER causes an interrupt in HOST.
+ * MB(W)
+ */
+#define ERT_HOST_INT_ENABLE     0x100
+
+/* ERT drive name */
+#define ZOCL_ERT_NAME "zocl_ert"
+
+extern struct platform_driver zocl_ert_driver;
+struct zocl_ert_ops;
+
+struct zocl_ert_dev {
+	struct platform_device       *pdev;
+	void __iomem                 *hw_ioremap;
+	void __iomem                 *cq_ioremap;
+	unsigned int                  irq[ERT_IRQ_NUMBER];
+	const struct zocl_ert_ops    *ops;
+};
+
+struct zocl_ert_ops {
+	/**
+	 * @init:
+	 *
+	 * Initial ERT dedicated FPGA module
+	 */
+	void (*init)(struct zocl_ert_dev *ert);
+	/**
+	 * @fini:
+	 *
+	 * Finish ERT dedicated FPGA module
+	 */
+	void (*fini)(struct zocl_ert_dev *ert);
+	/**
+	 * @config:
+	 *
+	 * Configure command could configure ERT dedicated module
+	 */
+	void (*config)(struct zocl_ert_dev *ert,
+		       struct ert_configure_cmd *cfg);
+	/**
+	 * @get_next_cmd:
+	 *
+	 * Return next cmd. If no command found, return NULL.
+	 */
+	struct ert_packet *
+	(*get_next_cmd)(struct zocl_ert_dev *ert,
+			struct ert_packet *pkg, int *idx_ret);
+	/**
+	 * @notify_host:
+	 *
+	 * Notify host the status of a command is changed.
+	 */
+	void (*notify_host)(struct zocl_ert_dev *ert, int slot_idx);
+
+	/**
+	 * @updata_cmd:
+	 *
+	 * Update the data section of a CQ slot
+	 */
+	void (*update_cmd)(struct zocl_ert_dev *ert, int idx,
+			    void *data, int sz);
+};
+
+struct zocl_ert_info {
+	int			model;
+	struct zocl_ert_ops    *ops;
+};
+
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/include/zocl_generic_cu.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/include/zocl_generic_cu.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * Generic compute unit structures.
+ *
+ * Copyright (C) 2020 Xilinx, Inc. All rights reserved.
+ *
+ * Authors:
+ *    Min Ma <min.ma@xilinx.com>
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#ifndef _ZOCL_GENERIC_CU_H_
+#define _ZOCL_GENERIC_CU_H_
+
+/* Bits in generic_cu_info.flag */
+#define GCU_IRQ_DISABLED 0
+
+struct generic_cu {
+	struct drm_zocl_dev	*zdev;
+	struct generic_cu_info	*info;
+	wait_queue_head_t	waitq;
+	atomic_t		event;
+	unsigned long		flag;
+	spinlock_t		lock;
+};
+
+struct generic_cu_info {
+	const char		*name;
+	int			cu_idx;
+	int                     irq;
+};
+
+int zocl_open_gcu(struct drm_zocl_dev *zdev, struct drm_zocl_ctx *ctx,
+		  struct sched_client_ctx *client);
+
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/include/zocl_mailbox.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/include/zocl_mailbox.h
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * A GEM style (optionally CMA backed) device manager for ZynQ based
+ * OpenCL accelerators.
+ *
+ * Copyright (C) 2019-2020 Xilinx, Inc. All rights reserved.
+ *
+ * Authors:
+ *    David Zhang <davidzha@xilinx.com>
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#ifndef _ZOCL_MAILBOX_H_
+#define _ZOCL_MAILBOX_H_
+
+#define	MBX_STATUS_EMPTY	(1 << 0)
+#define	MBX_STATUS_FULL		(1 << 1)
+#define	MBX_STATUS_STA		(1 << 2)
+#define	MBX_STATUS_RTA		(1 << 3)
+
+/*
+ * Mailbox IP register layout
+ */
+struct mailbox_reg {
+	u32			mbr_wrdata;
+	u32			mbr_resv1;
+	u32			mbr_rddata;
+	u32			mbr_resv2;
+	u32			mbr_status;
+	u32			mbr_error;
+	u32			mbr_sit;
+	u32			mbr_rit;
+	u32			mbr_is;
+	u32			mbr_ie;
+	u32			mbr_ip;
+	u32			mbr_ctrl;
+} __packed;
+
+struct mailbox {
+	struct mailbox_reg	*mbx_regs;
+};
+
+u32 zocl_mailbox_status(struct mailbox *mbx);
+u32 zocl_mailbox_get(struct mailbox *mbx);
+void zocl_mailbox_set(struct mailbox *mbx, u32 val);
+
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/include/zocl_ospi_versal.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/include/zocl_ospi_versal.h
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * A GEM style (optionally CMA backed) device manager for ZynQ based
+ * OpenCL accelerators.
+ *
+ * Copyright (C) 2019-2020 Xilinx, Inc. All rights reserved.
+ *
+ * Authors:
+ *    Larry Liu <yliu@xilinx.com>
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#ifndef _ZOCL_OSPI_VERSAL_H_
+#define	_ZOCL_OSPI_VERSAL_H_
+
+extern struct platform_driver zocl_ospi_versal_driver;
+
+struct zocl_ov_pkt_node {
+	size_t			zn_size;
+	u32			*zn_datap;
+	struct zocl_ov_pkt_node	*zn_next;
+};
+
+/**
+ * Main structure of ospi versal subdev.
+ * @timer_task:	main thread pointer
+ * @base:	PDI packet area base address
+ * @size:	PDI packet area size
+ * @pdi_ready:	flag to indicate PDI image is ready
+ * @pdi_done:	flag to indicate PDI flashing is done
+ * @pdev:	platform_device
+ * @head:	head node of PDI packet linked list
+ */
+struct zocl_ov_dev {
+	struct task_struct	*timer_task;
+	void __iomem		*base;
+	size_t			size;
+	u8			pdi_ready;
+	u8			pdi_done;
+	rwlock_t		att_rwlock;
+
+	/* platform device */
+	struct platform_device  *pdev;
+
+	/* parent platform device */
+	struct platform_device	*ppdev;
+
+	struct zocl_ov_pkt_node	*head;
+};
+
+/* Timer thread wake up interval in Millisecond */
+#define	ZOCL_OV_TIMER_INTERVAL		(1000)
+
+#define	ZOCL_OSPI_VERSAL_BRAM_RES	0
+
+/* OSPI VERSAL driver name */
+#define	ZOCL_OSPI_VERSAL_NAME "zocl_ospi_versal"
+
+int zocl_ov_init_sysfs(struct device *dev);
+void zocl_ov_fini_sysfs(struct device *dev);
+
+#endif /* _ZOCL_OSPI_VERSAL_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/include/zocl_sk.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/include/zocl_sk.h
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * A GEM style (optionally CMA backed) device manager for ZynQ based
+ * OpenCL accelerators.
+ *
+ * Copyright (C) 2019 Xilinx, Inc. All rights reserved.
+ *
+ * Authors:
+ *    Larry Liu <yliu@xilinx.com>
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#ifndef _ZOCL_SK_H_
+#define _ZOCL_SK_H_
+
+#define	MAX_SOFT_KERNEL		128
+
+#define	ZOCL_SCU_FLAGS_RELEASE	1
+
+struct soft_cu {
+	void			*sc_vregs;
+	struct drm_gem_object	*gem_obj;
+
+	/*
+	 * This semaphore is used for each soft kernel
+	 * CU to wait for next command. When new command
+	 * for this CU comes in or we are told to abort
+	 * a CU, ert will up this semaphore.
+	 */
+	struct semaphore	sc_sem;
+
+	uint32_t		sc_flags;
+	uint64_t		usage;
+
+	/*
+	 * soft cu pid and parent pid. This can be used to identify if the
+	 * soft cu is still running or not. The parent should never crash
+	 */
+	uint32_t		sc_pid;
+	uint32_t		sc_parent_pid;
+};
+
+struct soft_krnl {
+	struct list_head	sk_cmd_list;
+	struct mutex		sk_lock;
+	struct soft_cu		*sk_cu[MAX_SOFT_KERNEL];
+
+	/*
+	 * sk_ncus is a counter represents how many
+	 * compute units are configured.
+	 */
+	uint32_t		sk_ncus;
+
+	wait_queue_head_t	sk_wait_queue;
+};
+
+struct soft_krnl_cmd {
+	struct list_head	skc_list;
+	struct ert_packet	*skc_packet;
+};
+
+int zocl_init_soft_kernel(struct drm_device *drm);
+void zocl_fini_soft_kernel(struct drm_device *drm);
+
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/include/zocl_util.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/include/zocl_util.h
@@ -0,0 +1,154 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * Copyright (C) 2016-2020 Xilinx, Inc. All rights reserved.
+ *
+ * Author(s):
+ *        Min Ma <min.ma@xilinx.com>
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#ifndef _ZOCL_UTIL_H_
+#define _ZOCL_UTIL_H_
+
+#include "kds_core.h"
+#include "zocl_error.h"
+
+#define zocl_err(dev, fmt, args...)     \
+	dev_err(dev, "%s: "fmt, __func__, ##args)
+#define zocl_info(dev, fmt, args...)    \
+	dev_info(dev, "%s: "fmt, __func__, ##args)
+#define zocl_dbg(dev, fmt, args...)     \
+	dev_dbg(dev, "%s: "fmt, __func__, ##args)
+
+#define _4KB	0x1000
+#define _8KB	0x2000
+#define _64KB	0x10000
+
+#define MAX_CU_NUM     128
+#define CU_SIZE        _64KB
+#define PR_ISO_SIZE    _4KB
+
+#define CLEAR(x) \
+	memset(&x, 0, sizeof(x))
+
+#define sizeof_section(sect, data) \
+({ \
+	size_t ret; \
+	size_t data_size; \
+	data_size = sect->m_count * sizeof(typeof(sect->data)); \
+	ret = (sect) ? offsetof(typeof(*sect), data) + data_size : 0; \
+	(ret); \
+})
+
+/*
+ * Get the bank index from BO creation flags.
+ * bits  0 ~ 15: DDR BANK index
+ */
+#define	GET_MEM_BANK(x)		((x) & 0xFFFF)
+
+#define ZOCL_GET_ZDEV(ddev) (ddev->dev_private)
+
+struct drm_zocl_mm_stat {
+	size_t memory_usage;
+	unsigned int bo_count;
+};
+
+struct addr_aperture {
+	phys_addr_t	addr;
+	size_t		size;
+	u32		prop;
+	int		cu_idx;
+};
+
+enum zocl_mem_type {
+	ZOCL_MEM_TYPE_CMA	= 0,
+	ZOCL_MEM_TYPE_PL_LP_DDR	= 1,
+	ZOCL_MEM_TYPE_STREAMING = 2,
+};
+
+/*
+ * Memory structure in zocl driver. There will be an array of this
+ * structure where each element is representing each section in
+ * the memory topology in xclbin.
+ */
+struct zocl_mem {
+	enum zocl_mem_type	zm_type;
+	unsigned int		zm_used;
+	u64			zm_base_addr;
+	u64			zm_size;
+	struct drm_zocl_mm_stat zm_stat;
+	struct drm_mm          *zm_mm;    /* DRM MM node for PL-DDR */
+};
+
+/*
+ * zocl dev specific data info, if there are different configs across
+ * different compitible device, add their specific data here.
+ */
+struct zdev_data {
+	char fpga_driver_name[64];
+};
+
+struct aie_metadata {
+	size_t size;
+	void *data;
+};
+
+struct drm_zocl_dev {
+	struct drm_device       *ddev;
+	struct fpga_manager     *fpga_mgr;
+	struct zocl_ert_dev     *ert;
+	struct iommu_domain     *domain;
+	phys_addr_t              host_mem;
+	resource_size_t          host_mem_len;
+	/* Record start address, this is only for MPSoC as PCIe platform */
+	phys_addr_t		 res_start;
+	unsigned int		 cu_num;
+	unsigned int             irq[MAX_CU_NUM];
+	struct sched_exec_core  *exec;
+	unsigned int		 num_mem;
+	struct zocl_mem		*mem;
+	struct mutex		 mm_lock;
+	struct mutex		 aie_lock;
+
+	struct list_head	 ctx_list;
+
+	struct mem_topology	*topology;
+	struct ip_layout	*ip;
+	struct debug_ip_layout	*debug_ip;
+	struct connectivity	*connectivity;
+	struct addr_aperture	*apertures;
+	struct aie_metadata	 aie_data;
+	unsigned int		 num_apts;
+
+	struct kds_sched	 kds;
+	struct platform_device	*cu_pldev[MAX_CU_NUM];
+
+	/*
+	 * This RW lock is to protect the sysfs nodes exported
+	 * by zocl driver. Currently, all zocl attributes exported
+	 * to sysfs nodes are protected by a single lock. Any read
+	 * functions which not atomically touch those attributes should
+	 * hold read lock; And all write functions which not atomically
+	 * touch those attributes should hold write lock.
+	 */
+	rwlock_t		attr_rwlock;
+
+	struct soft_krnl	*soft_kernel;
+	struct aie_info		*aie_information;
+	struct dma_chan		*zdev_dma_chan;
+	struct mailbox		*zdev_mailbox;
+	const struct zdev_data	*zdev_data_info;
+	u64			pr_isolation_addr;
+	struct zocl_xclbin	*zdev_xclbin;
+	struct mutex		zdev_xclbin_lock;
+	struct generic_cu	*generic_cu;
+	int			 ksize;
+	char			*kernels;
+	struct zocl_error	zdev_error;
+	struct zocl_aie		*aie;
+};
+
+int zocl_kds_update(struct drm_zocl_dev *zdev);
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/include/zocl_xclbin.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/include/zocl_xclbin.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * Copyright (C) 2019 Xilinx, Inc. All rights reserved.
+ *
+ * Authors:
+ *    David Zhang <davidzha@xilinx.com>
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#ifndef _ZOCL_XCLBIN_H_
+#define _ZOCL_XCLBIN_H_
+
+#include <linux/uuid.h>
+
+struct zocl_xclbin {
+	int		zx_refcnt;
+	void		*zx_uuid;
+};
+
+int zocl_xclbin_init(struct drm_zocl_dev *zdev);
+void zocl_xclbin_fini(struct drm_zocl_dev *zdev);
+
+int zocl_xclbin_set_uuid(struct drm_zocl_dev *zdev, void *uuid);
+void *zocl_xclbin_get_uuid(struct drm_zocl_dev *zdev);
+int zocl_lock_bitstream(struct drm_zocl_dev *zdev, const uuid_t *id);
+int zocl_unlock_bitstream(struct drm_zocl_dev *zdev, const uuid_t *id);
+
+int zocl_xclbin_refcount(struct drm_zocl_dev *zdev);
+int zocl_xclbin_read_axlf(struct drm_zocl_dev *zdev,
+	struct drm_zocl_axlf *axlf_obj);
+int zocl_xclbin_load_pdi(struct drm_zocl_dev *zdev, void *data);
+
+bool zocl_xclbin_accel_adapter(int kds_mask);
+bool zocl_xclbin_legacy_intr(struct drm_zocl_dev *zdev);
+u32  zocl_xclbin_intr_id(struct drm_zocl_dev *zdev, u32 idx);
+bool zocl_xclbin_cus_support_intr(struct drm_zocl_dev *zdev);
+
+#endif /* _ZOCL_XCLBIN_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/sched_exec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/sched_exec.c
@@ -0,0 +1,3612 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * A GEM style device manager for MPSoC based OpenCL accelerators.
+ *
+ * Copyright (C) 2017-2020 Xilinx, Inc. All rights reserved.
+ *
+ * Authors:
+ *    Soren Soe   <soren.soe@xilinx.com>
+ *    Min Ma      <min.ma@xilinx.com>
+ *    Jan Stephan <j.stephan@hzdr.de>
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+#include <linux/bitmap.h>
+#include <linux/list.h>
+#include <linux/kthread.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include "ert.h"
+#include "sched_exec.h"
+#include "zocl_sk.h"
+#include "zocl_xclbin.h"
+#include "xclbin.h"
+
+/* #define SCHED_VERBOSE */
+
+#if defined(__GNUC__)
+#define SCHED_UNUSED __attribute__((unused))
+#endif
+
+#ifndef ERT_VERSION
+#define ERT_VERSION 0
+#endif
+
+#define sched_error_on(exec, expr) \
+({ \
+	unsigned int ret = 0; \
+	if ((expr)) { \
+		DRM_ERROR("Assertion failed: %s:%s\n",  __func__, #expr); \
+		exec->scheduler->error = 1; \
+		ret = 1; \
+	} \
+	(ret); \
+})
+
+#ifdef SCHED_VERBOSE
+# define SCHED_DEBUG(format, ...) DRM_INFO(format, ##__VA_ARGS__)
+#else
+# define SCHED_DEBUG(format, ...)
+#endif
+
+static int cq_check(void *data);
+static irqreturn_t sched_cq_isr(int irq, void *arg);
+
+/* Scheduler call schedule() every MAX_SCHED_LOOP loop*/
+#define MAX_SCHED_LOOP 8
+static int    sched_loop_cnt;
+
+static struct scheduler g_sched0;
+static struct sched_ops penguin_ops;
+static struct sched_ops ps_ert_ops;
+
+/**
+ * List of free sched_cmd objects.
+ *
+ * @free_cmds: populated with recycled sched_cmd objects
+ * @cmd_mutex: mutex lock for cmd_list
+ *
+ * Command objects are recycled for later use and only freed when kernel
+ * module is unloaded.
+ */
+static LIST_HEAD(free_cmds);
+static DEFINE_MUTEX(free_cmds_mutex);
+
+/**
+ * List of new pending sched_cmd objects
+ *
+ * @pending_cmds: populated from user space with new commands for buffer objects
+ * @num_pending: number of pending commands
+ *
+ * Scheduler copies pending commands to its private queue when necessary
+ */
+static LIST_HEAD(pending_cmds);
+static DEFINE_SPINLOCK(pending_cmds_lock);
+
+/**
+ * is_ert() - Check if running in embedded (ert) mode.
+ *
+ * Return: %true of ert mode, %false otherwise
+ */
+inline unsigned int
+is_ert(struct drm_device *dev)
+{
+	struct drm_zocl_dev *zdev = dev->dev_private;
+
+	return zdev->ert != NULL;
+}
+
+/**
+ * ffs_or_neg_one() - Find first set bit in a 32 bit mask.
+ *
+ * @mask: mask to check
+ *
+ * First LSBit is at position 0.
+ *
+ * Return: Position of first set bit, or -1 if none
+ */
+inline int
+ffs_or_neg_one(u32 mask)
+{
+	if (!mask)
+		return -1;
+	return ffs(mask)-1;
+}
+
+/**
+ * ffz_or_neg_one() - Find first zero bit in bit mask
+ *
+ * @mask: mask to check
+ * Return: Position of first zero bit, or -1 if none
+ */
+inline int
+ffz_or_neg_one(u32 mask)
+{
+	if (mask == U32_MASK)
+		return -1;
+	return ffz(mask);
+}
+
+/**
+ * slot_size() - slot size per device configuration
+ *
+ * Return: Command queue slot size
+ */
+inline unsigned int
+slot_size(struct drm_device *dev)
+{
+	struct drm_zocl_dev *zdev = dev->dev_private;
+
+	return CQ_SIZE / zdev->exec->num_slots;
+}
+
+/**
+ * cu_mask_idx() - CU mask index for a given cu index
+ *
+ * @cu_idx: Global [0..127] index of a CU
+ * Return: Index of the CU mask containing the CU with cu_idx
+ */
+static inline unsigned int
+cu_mask_idx(unsigned int cu_idx)
+{
+	return cu_idx >> 5; /* 32 cus per mask */
+}
+
+/**
+ * cu_idx_in_mask() - CU idx within its mask
+ *
+ * @cu_idx: Global [0..127] index of a CU
+ * Return: Index of the CU within the mask that contains it
+ */
+static inline unsigned int
+cu_idx_in_mask(unsigned int cu_idx)
+{
+	return cu_idx - (cu_mask_idx(cu_idx) << 5);
+}
+
+/**
+ * cu_idx_from_mask() - Get CU's global idx [0..127] by CU idx in a mask
+ *
+ * @cu_idx: Index of CU with mask identified by mask_idx
+ * @mask_idx: Mask index of the has CU with cu_idx
+ * Return: Global cu_idx [0..127]
+ */
+static inline unsigned int
+cu_idx_from_mask(unsigned int cu_idx, unsigned int mask_idx)
+{
+	return cu_idx + (mask_idx << 5);
+}
+
+/* explicitly set cucu_valid bitmap to valid(1) for cuid */
+static inline void
+zocl_cu_set_valid(struct sched_exec_core *exec_core, unsigned int cu_idx)
+{
+	exec_core->cu_valid[cu_mask_idx(cu_idx)] |=
+		(1 << cu_idx_in_mask(cu_idx));
+}
+
+/* explicitly set cu_valid bitmap to invalid(0) for cuid */
+static inline void
+zocl_cu_set_invalid(struct sched_exec_core *exec_core, unsigned int cu_idx)
+{
+	exec_core->cu_valid[cu_mask_idx(cu_idx)] ^=
+		(1 << cu_idx_in_mask(cu_idx));
+}
+
+/* return values: valid(1)/invalid(0) */
+static inline unsigned int
+zocl_cu_is_valid(struct sched_exec_core *exec_core, unsigned int cu_idx)
+{
+	return (exec_core->cu_valid[cu_mask_idx(cu_idx)] &
+		(1 << cu_idx_in_mask(cu_idx))) > 0;
+}
+
+int
+zocl_exec_valid_cu(struct sched_exec_core *exec, unsigned int cuid)
+{
+	return zocl_cu_is_valid(exec, cuid);
+}
+
+/**
+ * slot_mask_idx() - Slot mask idx index for a given slot_idx
+ *
+ * @slot_idx: Global [0..127] index of a CQ slot
+ * Return: Index of the slot mask containing the slot_idx
+ */
+inline unsigned int
+slot_mask_idx(unsigned int slot_idx)
+{
+	return slot_idx >> 5;
+}
+
+/**
+ * slot_idx_in_mask() - Index of CQ slot within the mask that contains it
+ *
+ * @slot_idx: Global [0..127] index of a CQ slot
+ * Return: Index of slot within the mask that contains it
+ */
+inline unsigned int
+slot_idx_in_mask(unsigned int slot_idx)
+{
+	return slot_idx - (slot_mask_idx(slot_idx) << 5);
+}
+
+/**
+ * slot_idx_from_mask_idx() - Get slot global idx [0..127] by slot idx in mask
+ *
+ * @slot_idx: Index of slot with mask identified by mask_idx
+ * @mask_idx: Mask index of the mask hat has slot with slot_idx
+ * Return: Global slot_idx [0..127]
+ */
+inline unsigned int
+slot_idx_from_mask_idx(unsigned int slot_idx, unsigned int mask_idx)
+{
+	return slot_idx + (mask_idx << 5);
+}
+
+/**
+ * opcode() - Command opcode
+ *
+ * @cmd: Command object
+ * Return: Opcode per command packet
+ */
+inline u32
+opcode(struct sched_cmd *cmd)
+{
+	return cmd->packet->opcode;
+}
+
+static inline u32
+type(struct sched_cmd *cmd)
+{
+	return cmd->packet->type;
+}
+
+/**
+ * payload_size() - Command payload size
+ *
+ * @cmd: Command object
+ * Return: Size in number of words of command packet payload
+ */
+inline u32
+payload_size(struct sched_cmd *cmd)
+{
+	return cmd->packet->count;
+}
+
+/**
+ * packet_size() - Command packet size
+ *
+ * @cmd: Command object
+ * Return: Size in number of words of command packet
+ */
+inline u32
+packet_size(struct sched_cmd *cmd)
+{
+	return payload_size(cmd) + 1;
+}
+
+/**
+ * cu_masks() - Number of command packet cu_masks
+ *
+ * @cmd: Command object
+ * Return: Total number of CU masks in command packet
+ */
+inline u32
+cu_masks(struct sched_cmd *cmd)
+{
+	struct ert_start_kernel_cmd *sk;
+	u32 op = opcode(cmd);
+
+	if (op != ERT_START_KERNEL && op != ERT_SK_START &&
+	    op != ERT_INIT_CU && op != ERT_EXEC_WRITE)
+		return 0;
+	sk = (struct ert_start_kernel_cmd *)cmd->packet;
+	return 1 + sk->extra_cu_masks;
+}
+
+/**
+ * regmap_size() - Size of regmap
+ *                 It is calculated by payload size + one packet header size -
+ *                 offset of cu_mask field - cu_masks
+ *                 This is based on the assumption that regmap is located
+ *                 right after the cu_masks (including extra_cu_masks).
+ * @xcmd: Command object
+ * Return: Size of register map in number of words
+ */
+inline u32
+regmap_size(struct sched_cmd *cmd)
+{
+	switch (opcode(cmd)) {
+
+	case ERT_INIT_CU:
+		return
+		    payload_size(cmd) + 1 -
+		    offsetof(struct ert_init_kernel_cmd, cu_mask) / WORD_SIZE -
+		    cu_masks(cmd);
+
+	case ERT_START_CU:
+	case ERT_EXEC_WRITE:
+	case ERT_SK_START:
+		return
+		    payload_size(cmd) + 1 -
+		    offsetof(struct ert_start_kernel_cmd, cu_mask) / WORD_SIZE -
+		    cu_masks(cmd);
+
+	default:
+		DRM_WARN("Command %d does not support regmap.\n", opcode(cmd));
+		return 0;
+	}
+}
+
+/**
+ * cu_idx_to_timeout() - Get CU's timeout value for CU index.
+ *                       CU timeout is in Microsecond. Our timer thread wakes
+ *                       up every ZOCL_CU_TIMER_INTERVAL (500) Milliseconds.
+ *                       So we return the timeout value in our timer interval
+ *                       unit plus one in case we just miss one timer slot.
+ * @dev: Device handle
+ * @cu_idx: Global CU idx
+ *
+ * Return: run timeout value of CU
+ */
+inline uint32_t
+cu_idx_to_timeout(struct drm_device *dev, unsigned int cu_idx)
+{
+	struct drm_zocl_dev *zdev = dev->dev_private;
+
+	if (!zdev->exec->zcu[cu_idx].run_timeout)
+		return 0;
+
+	return zdev->exec->zcu[cu_idx].run_timeout /
+	    (ZOCL_CU_TIMER_INTERVAL * 1000) + 1;
+}
+
+/**
+ * cu_idx_to_reset_timeout() - Get CU's reset timeout value for CU index.
+ *                             CU reset timeout is in Microsecond. We busy
+ *                             check the reset status every
+ *                             ZOCL_CU_RESET_TIMER_INTERVAL (1000) Microsecond.
+ * @dev: Device handle
+ * @cu_idx: Global CU idx
+ *
+ * Return: reset timeout value of CU in Microsecond
+ */
+inline uint32_t
+cu_idx_to_reset_timeout(struct drm_device *dev, unsigned int cu_idx)
+{
+	struct drm_zocl_dev *zdev = dev->dev_private;
+
+	return zdev->exec->zcu[cu_idx].reset_timeout /
+	    (ZOCL_CU_RESET_TIMER_INTERVAL) + 1;
+}
+
+/**
+ * enable_cmd_timestamps() - Enable timestamps for start CU commands
+ *
+ * @cmd: Command Object
+ */
+static inline bool
+enable_cmd_timestamps(struct sched_cmd *cmd)
+{
+	struct ert_start_kernel_cmd *sk = cmd->ert_cu;
+	struct cu_cmd_state_timestamps *ts;
+	size_t ts_sz = sizeof(struct cu_cmd_state_timestamps);
+	struct drm_zocl_bo *bo = cmd->buffer;
+
+	if (!(opcode(cmd) == ERT_START_CU ||
+	    opcode(cmd) == ERT_EXEC_WRITE) ||
+	    !sk->stat_enabled)
+		return false;
+
+	ts = ert_start_kernel_timestamps(sk);
+	if ((char *)ts + ts_sz > (char *)sk + bo->cma_base.base.size) {
+		DRM_ERROR("No enough space for timestamps in command.\n");
+		return false;
+	}
+	return true;
+}
+
+/**
+ * set_cmd_timestamp() - Set time stamp for specific state
+ *
+ * @cmd: Command Object
+ * @state: Command state
+ */
+static inline void
+set_cmd_timestamp(struct sched_cmd *cmd, enum ert_cmd_state state)
+{
+	struct cu_cmd_state_timestamps *ts;
+
+	if (!cmd->timestamp_enabled)
+		return;
+
+	ts = ert_start_kernel_timestamps(cmd->ert_cu);
+	/* The command state enum is using default integer value.
+	 * So we could use it for index.
+	 */
+	ts->skc_timestamps[state] = ktime_to_ns(ktime_get());
+}
+
+/**
+ * set_cmd_int_state() - Set internal command state used by scheduler only
+ *
+ * @xcmd: command to change internal state on
+ * @state: new command state per ert.h
+ */
+static inline void
+set_cmd_int_state(struct sched_cmd *cmd, enum ert_cmd_state state)
+{
+	SCHED_DEBUG("-> %s (,%d)\n", __func__, state);
+	set_cmd_timestamp(cmd, state);
+	cmd->state = state;
+	SCHED_DEBUG("<- %s\n", __func__);
+}
+
+/*
+ * This is the timer thread function. In the case that a CU timeout
+ * value is initialized, we start a timer thread. This thread wakes
+ * up every ZOCL_CU_TIMER_INTERVAL (500) Milliseconds. And each time,
+ * it sets a flag in scheduler and wakes up scheduler so that scheduler
+ * can check if a CU timeouts.
+ */
+static int zocl_cu_timer_thread(void *data)
+{
+	struct drm_zocl_dev *zdev = (struct drm_zocl_dev *)data;
+	struct sched_exec_core *exec = zdev->exec;
+	struct scheduler *sched = exec->scheduler;
+
+	while (1) {
+		if (kthread_should_stop())
+			break;
+
+		msleep(ZOCL_CU_TIMER_INTERVAL);
+
+		atomic_set(&sched->check, 1);
+		wake_up_interruptible(&g_sched0.wait_queue);
+	}
+
+	return 0;
+}
+
+int zocl_init_cu_timer(struct drm_zocl_dev *zdev)
+{
+	struct sched_exec_core *exec = zdev->exec;
+	char thread_name[256] = "zocl-cu-timer-thread";
+
+	/* If the timer is initialized, return here */
+	if (exec->timer_task)
+		return 0;
+
+	exec->timer_task = kthread_run(zocl_cu_timer_thread, zdev, thread_name);
+	if (IS_ERR(exec->timer_task)) {
+		int ret = PTR_ERR(exec->timer_task);
+
+		DRM_ERROR("Unable to create CU timer.\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+void zocl_cleanup_cu_timer(struct drm_zocl_dev *zdev)
+{
+	struct sched_exec_core *exec = zdev->exec;
+
+	if (!exec)
+		return;
+
+	if (!exec->timer_task)
+		return;
+
+	kthread_stop(exec->timer_task);
+}
+
+static irqreturn_t sched_exec_isr(int irq, void *arg)
+{
+	struct drm_zocl_dev *zdev = arg;
+	int cu_idx;
+
+	SCHED_DEBUG("-> %s irq %d", __func__, irq);
+	for (cu_idx = 0; cu_idx < zdev->cu_num; cu_idx++) {
+		if (zdev->exec->zcu[cu_idx].irq == irq)
+			break;
+	}
+
+	SCHED_DEBUG("cu_idx %d interrupt handle", cu_idx);
+	if (cu_idx >= zdev->cu_num) {
+		/* This should never happen */
+		DRM_ERROR("Unknown isr irq %d, polling %d\n",
+			  irq, zdev->exec->polling_mode);
+		return IRQ_NONE;
+	}
+
+	/* Check for done and write ap_continue to stop redundent interrupts */
+	if (zocl_cu_get_control(&zdev->exec->zcu[cu_idx]) == AP_CTRL_CHAIN)
+		zocl_cu_check(&zdev->exec->zcu[cu_idx]);
+
+	/* This function returns the value of the interrupt status register
+	 * No need to check the interrupt type for now.
+	 */
+	zocl_cu_clear_intr(&zdev->exec->zcu[cu_idx]);
+
+	/* wake up all scheduler ... currently one only
+	 *
+	 * This might have race with sched_wait_cond(), which will read then set
+	 * intc to 0; This race should has no impact on the functionality.
+	 *
+	 * 1. If scheduler thread is on sleeping, there is no race.
+	 * 2. If scheduler thread has waked up, and returned from
+	 * sched_wait_cond(), there is no race.
+	 * 3. Only when scheduler thread waked up and accessing sched->intc,
+	 * race might happen. It has two results:
+	 *	a. intc set to 0 here. But then the scheduler thread will still
+	 *	iterate all submitted commands.
+	 *	b. intc set to 1 here. The scheduler thread failed to reset intc
+	 *	to 0. In this case, after iterate all submitted commands, the
+	 *	scheduler loop will go to sched_wait_cond() again and try to
+	 *	reset intc and start the second time iteration.
+	 *
+	 */
+	g_sched0.intc = 1;
+	wake_up_interruptible(&g_sched0.wait_queue);
+
+	SCHED_DEBUG("<- %s", __func__);
+	return IRQ_HANDLED;
+}
+
+static void
+init_cu_by_idx(struct sched_cmd *cmd, int cu_idx)
+{
+	u32 size = regmap_size(cmd);
+	struct ert_init_kernel_cmd *ik;
+	struct zocl_cu *cu = &cmd->exec->zcu[cu_idx];
+
+	ik = (struct ert_init_kernel_cmd *)cmd->packet;
+
+	zocl_cu_configure(cu, ik->data + ik->extra_cu_masks, size, CONSECUTIVE);
+
+}
+
+/**
+ * update_cus_rtp() - Update CUs Run Time Parameters from user space command.
+ *
+ * Use {offset, value} pairs to update CU arguments.
+ *
+ * Note: we only support asynchronously update 32 bits scaler.
+ */
+static void
+update_cus_rtp(struct sched_cmd *cmd)
+{
+	struct drm_zocl_dev *zdev = cmd->ddev->dev_private;
+	struct ert_init_kernel_cmd *ik;
+	uint32_t *cmp;
+	int num_masks = cu_masks(cmd);
+	int mask_idx;
+	u32 size = regmap_size(cmd);
+
+	ik = (struct ert_init_kernel_cmd *)cmd->packet;
+	cmp = &ik->cu_mask;
+
+	for (mask_idx = 0; mask_idx < num_masks; ++mask_idx) {
+		u32 cmd_mask = cmp[mask_idx];
+		int cu_idx;
+
+		while ((cu_idx = ffs(cmd_mask))) {
+			struct zocl_cu *cu;
+
+			/* ffs is "1" based */
+			cu_idx = ffs(cmd_mask) - 1;
+
+			/* Clear the mask bit we checked */
+			cmd_mask &= ~(1 << cu_idx);
+
+			cu_idx = cu_idx_from_mask(cu_idx, mask_idx);
+
+			if (!zocl_cu_is_valid(zdev->exec, cu_idx)) {
+				DRM_WARN("Update invalid CU %d, Skipped.\n",
+				    cu_idx);
+				continue;
+			}
+
+			cu = &cmd->exec->zcu[cu_idx];
+			zocl_cu_configure(cu, ik->data + ik->extra_cu_masks,
+			    size, PAIRS);
+		}
+	}
+}
+
+/**
+ * init_cus() - Initialize CUs from user space command.
+ *
+ * Process the initialize CUs command sent from user space. Only one process
+ * can initialize a given CU, so if a CU in the CU masks is initialized,
+ * this function ignores the initialize request.
+ *
+ * The initialization is done by copying the user regmap to register map.
+ */
+static void
+init_cus(struct sched_cmd *cmd)
+{
+	struct drm_zocl_dev *zdev = cmd->ddev->dev_private;
+	struct ert_init_kernel_cmd *ik;
+	unsigned int i;
+	uint32_t *cmp;
+	uint32_t run_timeout;
+	uint32_t reset_timeout;
+	int num_masks = cu_masks(cmd);
+	int mask_idx;
+	int warn_flag = 0;
+
+	ik = (struct ert_init_kernel_cmd *)cmd->packet;
+	if (ik->update_rtp)
+		return update_cus_rtp(cmd);
+
+	cmp = &ik->cu_mask;
+
+	run_timeout = ik->cu_run_timeout;
+	reset_timeout = ik->cu_reset_timeout;
+	if (run_timeout != 0 && reset_timeout == 0) {
+		DRM_WARN("Init CU fail: invalid cu reset timeout.\n");
+		goto done;
+	}
+
+	for (mask_idx = 0; mask_idx < num_masks; ++mask_idx) {
+		u32 cmd_mask = cmp[mask_idx];
+		u32 inited_mask = zdev->exec->cu_init[mask_idx];
+		u32 uninited_mask = (cmd_mask | inited_mask) ^ inited_mask;
+		u32 busy_mask = zdev->exec->cu_status[mask_idx];
+
+		/*
+		 * If some requested CUs are initialized already,
+		 * record a flag and post some log later.
+		 */
+		if (!warn_flag && (inited_mask & cmd_mask))
+			warn_flag = 1;
+
+		/*
+		 * We don't have uninitialized CU for this 32 mask_id.
+		 * Move to next 32 CUs.
+		 */
+		if (!uninited_mask)
+			continue;
+
+		for (i = 0; i < 32; ++i) {
+			int cu_idx;
+
+			if (!(uninited_mask & (1 << i)))
+				continue;
+
+			cu_idx = cu_idx_from_mask(i, mask_idx);
+
+			if (busy_mask & (1 << i)) {
+				DRM_WARN("Can not init CU %d while running.\n",
+				   cu_idx);
+				continue;
+			}
+
+			if (!zocl_cu_is_valid(zdev->exec, cu_idx)) {
+				DRM_WARN("Init CU %d fail: NOT a valid CU.\n",
+				    cu_idx);
+				continue;
+			}
+
+			if (cu_idx >= zdev->exec->num_cus) {
+				/*
+				 * Requested CU index exceeds the configured
+				 * CU numbers.
+				 */
+				DRM_WARN("Init CU %d fail: NOT configured.\n",
+				    cu_idx);
+				goto done;
+			}
+
+			zdev->exec->zcu[cu_idx].run_timeout = run_timeout;
+			zdev->exec->zcu[cu_idx].reset_timeout = reset_timeout;
+
+			init_cu_by_idx(cmd, cu_idx);
+
+			zdev->exec->cu_init[mask_idx] ^= (1 << i);
+		}
+	}
+
+	/*
+	 * If CU is initialized with a timeout value, we start the timer
+	 * thread to track CU timeout.
+	 */
+	if (run_timeout != 0)
+		zocl_init_cu_timer(zdev);
+
+done:
+	if (warn_flag)
+		DRM_INFO("CU can only be initialized once.\n");
+}
+
+static void kill_soft_kernel(struct sched_cmd *cmd)
+{
+	struct drm_zocl_dev *zdev = cmd->ddev->dev_private;
+	struct soft_krnl *sk = zdev->soft_kernel;
+	struct pid *p;
+	struct task_struct *task;
+	uint32_t pid;
+	int i, ret;
+
+	mutex_lock(&sk->sk_lock);
+
+	for (i = 0; i < ARRAY_SIZE(sk->sk_cu); i++) {
+		if (!sk->sk_cu[i])
+			continue;
+
+		p = find_get_pid(sk->sk_cu[i]->sc_pid);
+		if (!p) {
+			/* cu process is gone. cleanup it anyway */
+			ret = 0;
+			goto skip_kill;
+		}
+
+		task = pid_task(p, PIDTYPE_PID);
+		if (!task) {
+			DRM_WARN("failed to get task for pid %d\n",
+				sk->sk_cu[i]->sc_pid);
+			put_pid(p);
+			continue;
+		}
+
+		if (sk->sk_cu[i]->sc_parent_pid != task_ppid_nr(task)) {
+			DRM_WARN("parent pid does not match\n");
+			put_pid(p);
+			continue;
+		}
+
+		pid = sk->sk_cu[i]->sc_pid;
+		ret = kill_pid(p, SIGKILL, 1);
+		if (ret) {
+			DRM_WARN("failed to kill cu pid %d\n", pid);
+		}
+		put_pid(p);
+skip_kill:
+		if (!ret) {
+			ZOCL_DRM_GEM_OBJECT_PUT_UNLOCKED(sk->sk_cu[i]->gem_obj);
+			kfree(sk->sk_cu[i]);
+			sk->sk_cu[i] = NULL;
+		}
+	}
+
+	sk->sk_ncus = 0;
+
+	mutex_unlock(&sk->sk_lock);
+}
+
+/**
+ * configure() - Configure the scheduler from user space command
+ *
+ * Process the configure command sent from user space. Only one process can
+ * configure the scheduler, so if scheduler is already configured, the
+ * function should verify that another process doesn't expect different
+ * configuration.
+ *
+ * Future may need ability to query current configuration so as to keep
+ * multiple processes in sync.
+ *
+ * Return: 0 on success, 1 on failure
+ */
+static int
+configure(struct sched_cmd *cmd)
+{
+	struct drm_zocl_dev *zdev = cmd->ddev->dev_private;
+	struct sched_exec_core *exec = zdev->exec;
+	struct ert_configure_cmd *cfg;
+	unsigned int i, j;
+	phys_addr_t cu_addr;
+	char name[256] = "zocl-ert-thread";
+	int cq_irq;
+	int acc_cu = 0;
+	int has_acc_cu = 0;
+	int apt_idx, irq_id;
+	bool is_legacy_intr = true;
+	int ret;
+	u32 control;
+
+	if (sched_error_on(exec, opcode(cmd) != ERT_CONFIGURE))
+		return 1;
+
+	if (!zdev->ert && exec->configured) {
+		DRM_WARN("Reconfiguration not supported\n");
+		return 1;
+	}
+
+	if (!list_empty(&pending_cmds)) {
+		DRM_ERROR("Pending commands list not empty\n");
+		return 1;
+	}
+
+	if (!list_is_singular(&g_sched0.cq)) {
+		DRM_ERROR("Queued commands list not empty\n");
+		return 1;
+	}
+
+	cfg = (struct ert_configure_cmd *)(cmd->packet);
+
+	/*
+	 * In ert mode, no ert config cmd for the same xclbin will be coming
+	 * from host. so always unconfig ert when there is ert config cmd
+	 * arriving
+	 */
+	if (zdev->ert) {
+		kill_soft_kernel(cmd);
+		sched_reset_scheduler(zdev->ddev);
+	}
+
+	SCHED_DEBUG("Configuring scheduler\n");
+	write_lock(&zdev->attr_rwlock);
+
+	if (!zdev->ert) {
+		if (cfg->ert)
+			DRM_INFO("No ERT scheduler on MPSoC, using KDS\n");
+		SCHED_DEBUG("++ configuring penguin scheduler mode\n");
+		exec->ops = &penguin_ops;
+		exec->polling_mode = cfg->polling;
+		/*
+		 * Interrupt may not be enabled for some of the kernel,
+		 * Need to use polling mode in that case
+		 */
+		if (!zocl_xclbin_cus_support_intr(zdev)) {
+			DRM_WARN("Interrupt is not enabled for at least one "
+			    "kernel. Fall back to polling mode.");
+			exec->polling_mode = 1;
+		}
+		exec->configured = 1;
+	} else {
+		SCHED_DEBUG("++ configuring PS ERT mode\n");
+
+		exec->ops = &ps_ert_ops;
+		exec->polling_mode = cfg->polling;
+		exec->cq_interrupt = cfg->cq_int;
+		exec->cu_dma = cfg->cu_dma;
+		exec->cu_isr = cfg->cu_isr;
+		DRM_INFO("PS ERT enabled features:");
+		DRM_INFO("  cu_dma(%d)", exec->cu_dma);
+		DRM_INFO("  cu_isr(%d)", exec->cu_isr);
+		DRM_INFO("  host_polling_mode(%d)", exec->polling_mode);
+		DRM_INFO("  cq_interrupt(%d)", exec->cq_interrupt);
+		zdev->ert->ops->config(zdev->ert, cfg);
+		exec->configured = 1;
+	}
+
+	/*
+	 * Note: for current design: the slot_size can be not 4k,
+	 * but cq_size is always 64k.
+	 */
+	exec->num_slots       = CQ_SIZE / cfg->slot_size;
+	exec->num_cus         = cfg->num_cus;
+	exec->cu_shift_offset = cfg->cu_shift;
+	exec->cu_base_addr    = cfg->cu_base_addr;
+	exec->num_cu_masks    = exec->num_cus == 0 ? 0 :
+	    ((exec->num_cus - 1)>>5) + 1;
+
+	write_unlock(&zdev->attr_rwlock);
+
+	/* Enable interrupt from host to PS when new commands are ready */
+	if (zdev->ert && exec->cq_interrupt) {
+		/* Stop CQ check thread */
+		if (zdev->exec->cq_thread)
+			kthread_stop(zdev->exec->cq_thread);
+
+		/* At this point we are good. No one is polling CQ */
+		cq_irq = zdev->ert->irq[ERT_CQ_IRQ];
+		ret = request_irq(cq_irq, sched_cq_isr, 0, "zocl_cq", zdev);
+		if (ret) {
+			DRM_WARN("Failed to initial CQ interrupt. "
+			    "Fall back to polling\n");
+			exec->cq_interrupt = 0;
+			exec->cq_thread = kthread_run(cq_check, zdev, name);
+		}
+	}
+	/* TODO: let's consider how to support reconfigurable KDS/ERT later.
+	 * At that time, ERT should be able to change back to CQ polling mode.
+	 */
+
+	if (exec->num_cus == 0)
+		goto print_and_out;
+
+	exec->zcu = vzalloc(sizeof(struct zocl_cu) * exec->num_cus);
+	if (!exec->zcu) {
+		DRM_ERROR("Could not allocate CU objects\n");
+		return -ENOMEM;
+	}
+
+	if (!zdev->ert)
+		is_legacy_intr = zocl_xclbin_legacy_intr(zdev);
+
+	for (i = 0; i < exec->num_cus; i++) {
+		if (zocl_xclbin_accel_adapter(cfg->data[i] & ~ZOCL_KDS_MASK)) {
+			/* If the ACCEL adapter is used */
+			acc_cu = 1;
+			if (has_acc_cu == 0)
+				has_acc_cu = 1;
+		}
+
+		control = cfg->data[i] & 0x7; //bit [2:0]
+		/* CU address should be masked by encoded handshake for KDS. */
+		cu_addr = cfg->data[i] & ZOCL_KDS_MASK;
+		if (cu_addr == ZOCL_CU_FREE_RUNNING) {
+			DRM_INFO("CU %x is free-running.", cfg->data[i]);
+			continue;
+		}
+		/*
+		 * Explicity set cu is valid,
+		 * only valid cu will be processed below.
+		 */
+		zocl_cu_set_valid(exec, i);
+
+		/* If it is in ert mode, there is no XCLBIN parsed now
+		 * Trust configuration from host. Once host download XCLBIN to
+		 * PS side, verify host configuration in the same way.
+		 *
+		 * Now the zdev->ert is heavily used in configure()
+		 * Need cleanup.
+		 */
+		if (!zdev->ert) {
+			apt_idx = get_apt_index_by_addr(zdev, cu_addr);
+			if (apt_idx < 0) {
+				DRM_ERROR("CU address %x is not found in XCLBIN\n",
+					  cfg->data[i]);
+				return 1;
+			}
+			update_cu_idx_in_apt(zdev, apt_idx, i);
+			if (is_legacy_intr)
+				irq_id = i;
+			else
+				irq_id = zocl_xclbin_intr_id(zdev, apt_idx);
+			exec->zcu[i].irq = zdev->irq[irq_id];
+		}
+
+		/* For MPSoC as PCIe device, the CU address for PS = base
+		 * address + PCIe offset.
+		 *
+		 * For Pure MPSoC device, the base address is always 0
+		 */
+		SCHED_DEBUG(
+		    "++ config cu(%d) at res_start: 0x%llx + cu_addr: 0x%llx\n",
+		    i, (uint64_t)zdev->res_start, (uint64_t)cu_addr);
+		cu_addr = zdev->res_start + cu_addr;
+
+		if (!acc_cu)
+			zocl_cu_init(&exec->zcu[i], MODEL_HLS, cu_addr|control);
+		else {
+			zocl_cu_init(&exec->zcu[i], MODEL_ACC, cu_addr);
+			/* ACCEL adapter CU initial finished.
+			 * The next CU might be HLS CU.
+			 */
+			acc_cu = 0;
+		}
+	}
+
+	/* If ERT mode or ACC adapters is used, only support polling mode */
+	if (zdev->ert || has_acc_cu) {
+		if (has_acc_cu) {
+			DRM_WARN("Interrupt is not support for ACC adapter. "
+				"    Fall back to polling mode\n");
+		}
+		exec->polling_mode = 1;
+		goto print_and_out;
+	}
+
+	/* Right now only support 128 CUs interrupts
+	 * If there are more than 128 CUs, fall back to polling mode
+	 */
+	if (!exec->polling_mode && exec->num_cus > MAX_CU_NUM) {
+		DRM_WARN("Only support up to %d CUs interrupts, "
+		    "request %d CUs. Fall back to polling mode\n", MAX_CU_NUM,
+		    exec->num_cus);
+		exec->polling_mode = 1;
+	}
+
+	/* If user prefer polling_mode, skip interrupt setup */
+	if (exec->polling_mode)
+		goto set_cu_and_print;
+
+	/* If re-config KDS is supported, should free old irq and disable cu
+	 * interrupt according to the command
+	 */
+	for (i = 0; i < exec->num_cus; i++) {
+		if (!zocl_cu_is_valid(exec, i))
+			continue;
+
+		exec->zcu[i].irq_name = kzalloc(20, GFP_KERNEL);
+		sprintf(exec->zcu[i].irq_name, "zocl_cu[%d]", i);
+		ret = request_irq(exec->zcu[i].irq, sched_exec_isr, 0,
+				  exec->zcu[i].irq_name, zdev);
+		if (ret) {
+			/* Fail to install at least one interrupt
+			 * handler. We need to free the handler(s)
+			 * already installed and fall back to
+			 * polling mode.
+			 */
+			for (j = 0; j < i; j++) {
+				if (zocl_cu_is_valid(exec, j)) {
+					kfree(exec->zcu[j].irq_name);
+					free_irq(exec->zcu[j].irq, zdev);
+				}
+			}
+			DRM_WARN("request_irq failed on CU %d error: %d."
+			    "Fall back to polling mode.\n", i, ret);
+			exec->polling_mode = 1;
+			break;
+		}
+	}
+
+set_cu_and_print:
+	/* Do not trust user's interrupt enable setting in the start cu cmd */
+	for (i = 0; i < exec->num_cus; i++) {
+		if (!zocl_cu_is_valid(exec, i))
+			continue;
+
+		if (exec->polling_mode)
+			zocl_cu_disable_intr(&exec->zcu[i], CU_INTR_DONE);
+		else
+			zocl_cu_enable_intr(&exec->zcu[i], CU_INTR_DONE);
+	}
+
+print_and_out:
+	DRM_INFO("scheduler config ert(%d)", is_ert(cmd->ddev));
+	DRM_INFO("  cus(%d)", exec->num_cus);
+	DRM_INFO("  slots(%d)", exec->num_slots);
+	DRM_INFO("  num_cu_masks(%d)", exec->num_cu_masks);
+	DRM_INFO("  cu_shift(%d)", exec->cu_shift_offset);
+	DRM_INFO("  cu_base(0x%x)", exec->cu_base_addr);
+	DRM_INFO("  polling(%d)", exec->polling_mode);
+	return 0;
+}
+
+/**
+ * Gather ERT stats in ctrl command packet
+ * [1  ]      : header
+ * [1  ]      : custat version
+ * [1  ]      : ert version
+ * [1  ]      : number of cq slots
+ * [1  ]      : number of cus
+ * [#numcus]  : cu execution stats (number of executions)
+ * [#numcus]  : cu status (1: running, 0: idle)
+ * [#slots]   : command queue slot status
+ */
+static void
+cu_stat(struct sched_cmd *cmd)
+{
+	struct drm_zocl_dev *zdev = cmd->ddev->dev_private;
+	struct zocl_ert_dev *ert = zdev->ert;
+	struct sched_exec_core *exec = zdev->exec;
+	struct soft_krnl *sk = zdev->soft_kernel;
+	struct ert_packet *pkg;
+	int slot_idx;
+	int pkt_idx = 0;
+	int max_idx = (slot_size(cmd->ddev) >> 2) - 1;
+	int i;
+
+	SCHED_DEBUG("-> %s cq_slot_idx %d\n", __func__, cmd->cq_slot_idx);
+	slot_idx = cmd->cq_slot_idx;
+	pkg = cmd->packet;
+
+	/* custat version, update when changing layout of packet */
+	pkg->data[pkt_idx++] = 0x51a10000;
+
+	/* should be git version */
+	pkg->data[pkt_idx++] = ERT_VERSION;
+
+	/* number of CQ slots */
+	pkg->data[pkt_idx++] = exec->num_slots;
+
+	/* number of CUs */
+	pkg->data[pkt_idx++] = exec->num_cus + sk->sk_ncus;
+
+	/* individual CU execution stat */
+	for (i = 0; i < exec->num_cus && pkt_idx < max_idx; ++i)
+		pkg->data[pkt_idx++] = exec->zcu[i].usage;
+
+	/* individual SK CU execution stat */
+	mutex_lock(&sk->sk_lock);
+	for (i = 0; i < sk->sk_ncus && pkt_idx < max_idx; ++i) {
+		if (sk->sk_cu[i])
+			pkg->data[pkt_idx++] = sk->sk_cu[i]->usage;
+		else //soft kernel cu has crashed
+			pkg->data[pkt_idx++] = -1;
+	}
+	mutex_unlock(&sk->sk_lock);
+
+	/* individual CU status */
+	for (i = 0; i < exec->num_cus && pkt_idx < max_idx; ++i) {
+		pkg->data[pkt_idx++] = (exec->cu_status[cu_mask_idx(i)] &
+			(1 << (i % sizeof(exec->cu_status[0])))) ? 1 : 0;
+	}
+
+	/* indevidual SK CU status */
+	for (i = 0; i < sk->sk_ncus && pkt_idx < max_idx; ++i) {
+		if (sk->sk_cu[i])
+			pkg->data[pkt_idx++] = (exec->scu_status[cu_mask_idx(i)] &
+				(1 << (i % sizeof(exec->scu_status[0])))) ? 1 : 0;
+		else
+			pkg->data[pkt_idx++] = -1; //soft cu has crashed
+	}
+
+	/* Command slot status
+	 * Hard code QUEUED state. When a NEW command is found,
+	 * ERT/PS will set it to QUEUED. Then no CQ write.
+	 */
+	for (i = 0; i < exec->num_slots && pkt_idx < max_idx; ++i)
+		pkg->data[pkt_idx++] = ERT_CMD_STATE_QUEUED;
+
+	/* update command slot in CQ */
+	ert->ops->update_cmd(ert, slot_idx, pkg->data, pkt_idx * 4);
+	SCHED_DEBUG("<- %s\n", __func__);
+}
+
+static void
+zocl_cu_reclaim(struct drm_zocl_dev *zdev)
+{
+	struct sched_exec_core *exec = zdev->exec;
+	int i;
+
+	for (i = 0; i < exec->num_cus; i++) {
+		if (zocl_cu_is_valid(exec, i)) {
+			zocl_cu_set_invalid(exec, i);
+			zocl_cu_fini(&exec->zcu[i]);
+		}
+	}
+
+	vfree(zdev->exec->zcu);
+}
+
+static int
+configure_soft_kernel(struct sched_cmd *cmd)
+{
+	struct drm_zocl_dev *zdev = cmd->ddev->dev_private;
+	struct soft_krnl *sk = zdev->soft_kernel;
+	struct ert_configure_sk_cmd *cfg;
+	u32 i;
+	struct soft_krnl_cmd *scmd;
+	int ret;
+
+	SCHED_DEBUG("-> %s", __func__);
+
+	cfg = (struct ert_configure_sk_cmd *)(cmd->packet);
+
+	mutex_lock(&sk->sk_lock);
+	atomic_inc(&cmd->exec->scheduler->num_running);//Else num_running becomes -1 by missing SK_CONFIG command increment
+
+	/* Check if the CU configuration exceeds maximum CU number */
+	if (cfg->start_cuidx + cfg->num_cus > MAX_CU_NUM) {
+		DRM_WARN("Soft kernel CU %d exceed maximum cu number %d.\n",
+		    cfg->start_cuidx + cfg->num_cus, MAX_CU_NUM);
+		mutex_unlock(&sk->sk_lock);
+		return -EINVAL;
+	}
+
+	/* Check if any CU is configured already */
+	for (i = cfg->start_cuidx; i < cfg->start_cuidx + cfg->num_cus; i++)
+		if (sk->sk_cu[i]) {
+			DRM_WARN("Soft Kernel CU %d is configured already.\n",
+			    i);
+			mutex_unlock(&sk->sk_lock);
+			return -EINVAL;
+		}
+
+	sk->sk_ncus += cfg->num_cus;
+
+	mutex_unlock(&sk->sk_lock);
+
+	/* NOTE: any failure after this point needs to resume sk_ncus */
+
+	/* Fill up a soft kernel command and add to soft kernel command list */
+	scmd = kmalloc(sizeof(struct soft_krnl_cmd), GFP_KERNEL);
+	if (!scmd) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	scmd->skc_packet = (struct ert_packet *)cfg;
+
+	mutex_lock(&sk->sk_lock);
+	list_add_tail(&scmd->skc_list, &sk->sk_cmd_list);
+	mutex_unlock(&sk->sk_lock);
+
+	/* start CU by waking up Soft Kernel handler */
+	wake_up_interruptible(&sk->sk_wait_queue);
+
+	SCHED_DEBUG("<- %s\n", __func__);
+
+	return 0;
+
+fail:
+	mutex_lock(&sk->sk_lock);
+	sk->sk_ncus -= cfg->num_cus;
+	mutex_unlock(&sk->sk_lock);
+	return ret;
+}
+
+static int
+unconfigure_soft_kernel(struct sched_cmd *cmd)
+{
+	struct drm_zocl_dev *zdev = cmd->ddev->dev_private;
+	struct soft_krnl *sk = zdev->soft_kernel;
+	struct soft_cu *scu;
+	struct ert_unconfigure_sk_cmd *cfg;
+	u32 i;
+
+	SCHED_DEBUG("-> %s\n", __func__);
+
+	cfg = (struct ert_unconfigure_sk_cmd *)(cmd->packet);
+
+	mutex_lock(&sk->sk_lock);
+
+	/* Check if the CU unconfiguration exceeds maximum CU number */
+	if (cfg->start_cuidx + cfg->num_cus > MAX_CU_NUM) {
+		DRM_WARN("Soft kernel CU %d exceed maximum cu number %d.\n",
+		    cfg->start_cuidx + cfg->num_cus, MAX_CU_NUM);
+		mutex_unlock(&sk->sk_lock);
+		return -EINVAL;
+	}
+
+	/* Check if any CU is not configured */
+	for (i = cfg->start_cuidx; i < cfg->start_cuidx + cfg->num_cus; i++)
+		if (!sk->sk_cu[i]) {
+			DRM_WARN("Soft Kernel CU %d is not configured.\n", i);
+			mutex_unlock(&sk->sk_lock);
+			return -EINVAL;
+		}
+
+	sk->sk_ncus -= cfg->num_cus;
+
+	/*
+	 * For each soft kernel, we set the RELEASE flag and wake up
+	 * waiting thread to release soft kenel.
+	 */
+	for (i = cfg->start_cuidx; i < cfg->start_cuidx + cfg->num_cus; i++) {
+		scu = sk->sk_cu[i];
+		scu->sc_flags |= ZOCL_SCU_FLAGS_RELEASE;
+		up(&scu->sc_sem);
+	}
+
+	mutex_unlock(&sk->sk_lock);
+
+	SCHED_DEBUG("<- %s\n", __func__);
+
+	return 0;
+}
+
+/**
+ * set_cmd_state() - Set both internal and external state of a command
+ *
+ * The state is reflected externally through the command packet
+ * as well as being captured in internal state variable
+ *
+ * @cmd: command object
+ * @state: new state
+ */
+static inline void
+set_cmd_state(struct sched_cmd *cmd, enum ert_cmd_state state)
+{
+	SCHED_DEBUG("-> %s (,%d)\n", __func__, state);
+	set_cmd_timestamp(cmd, state);
+	cmd->state = state;
+	cmd->packet->state = state;
+	SCHED_DEBUG("<- %s\n", __func__);
+}
+
+/**
+ * set_cmd_ext_cu_idx() - Set external cu_idx of a command
+ *
+ * The cu_idx is reflected externally through the command packet
+ *
+ * @cmd: command object
+ * @cu_idx: CU idex
+ */
+static inline void
+set_cmd_ext_cu_idx(struct sched_cmd *cmd, int cu_idx)
+{
+	int mask_idx = cu_mask_idx(cu_idx);
+	int mask_cu_idx = cu_idx_in_mask(cu_idx);
+
+	cmd->packet->data[mask_idx] &= 1 << mask_cu_idx;
+}
+
+/**
+ * set_cmd_ext_timestamp() - Set timestamp in the command packet
+ *
+ * The timestamp is reflected externally through the command packet
+ * TODO: Should have scheduler profiling solution in the future.
+ *
+ * @cmd: command object
+ * @ts: timestamp type
+ */
+static inline void
+set_cmd_ext_timestamp(struct sched_cmd *cmd, enum zocl_ts_type ts)
+{
+	u32 opc = opcode(cmd);
+	ZOCL_TIMESPEC tv;
+	struct ert_start_kernel_cmd *sk;
+
+	sk = (struct ert_start_kernel_cmd *)cmd->packet;
+
+	/* Simply skip if it is not start CU and exec write command */
+	if (opc != ERT_START_CU && opc != ERT_EXEC_WRITE)
+		return;
+	/* Use the first 4 32bits in the regmap to record CU start/end time.
+	 * To let user application know the CU start/end time.
+	 * The first  32 bits - CU start seconds
+	 * The second 32 bits - CU start microseconds
+	 * The third  32 bits - CU done  seconds
+	 * The fourth 32 bits - CU done  microseconds
+	 * Use 32 bits timestamp is good enough for this purpose for now.
+	 */
+	ZOCL_GETTIME(&tv);
+	if (ts == CU_START_TIME) {
+		*(sk->data + sk->extra_cu_masks) = (u32)tv.tv_sec;
+		*(sk->data + sk->extra_cu_masks + 1) = (u32)tv.ZOCL_USEC;
+	} else if (ts == CU_DONE_TIME) {
+		*(sk->data + sk->extra_cu_masks + 2) = (u32)tv.tv_sec;
+		*(sk->data + sk->extra_cu_masks + 3) = (u32)tv.ZOCL_USEC;
+	}
+}
+
+/**
+ * acquire_slot_idx() - Acquire a slot index if available.
+ *                      Update slot status to busy so it cannot be reacquired.
+ *
+ * This function is called from scheduler thread
+ *
+ * Return: Command queue slot index, or -1 if none available
+ */
+static int
+acquire_slot_idx(struct drm_device *dev)
+{
+	struct drm_zocl_dev *zdev = dev->dev_private;
+	unsigned int mask_idx = 0, slot_idx = -1, tmp_idx;
+	u32 mask;
+
+	SCHED_DEBUG("-> %s\n", __func__);
+	for (mask_idx = 0; mask_idx < zdev->exec->num_slot_masks; ++mask_idx) {
+		mask = zdev->exec->slot_status[mask_idx];
+		slot_idx = ffz_or_neg_one(mask);
+		tmp_idx = slot_idx_from_mask_idx(slot_idx, mask_idx);
+		if (slot_idx == -1 || tmp_idx >= zdev->exec->num_slots)
+			continue;
+		zdev->exec->slot_status[mask_idx] ^= (1<<slot_idx);
+		SCHED_DEBUG("<- %s returns %d\n", __func__,
+			    slot_idx_from_mask_idx(slot_idx, mask_idx));
+		return slot_idx_from_mask_idx(slot_idx, mask_idx);
+	}
+	SCHED_DEBUG("<- %s returns -1\n", __func__);
+	return -1;
+}
+
+/**
+ * release_slot_idx() - Release a slot index
+ *
+ * Update slot status mask for slot index. Notify scheduler in case
+ * release is via ISR
+ *
+ * @dev: scheduler
+ * @slot_idx: the slot index to release
+ */
+static void
+release_slot_idx(struct drm_device *dev, unsigned int slot_idx)
+{
+	struct drm_zocl_dev *zdev = dev->dev_private;
+	unsigned int mask_idx = slot_mask_idx(slot_idx);
+	unsigned int pos = slot_idx_in_mask(slot_idx);
+
+	SCHED_DEBUG("<-> %s slot_status[%d]=0x%x, pos=%d\n",
+	    __func__, mask_idx, zdev->exec->slot_status[mask_idx], pos);
+	zdev->exec->slot_status[mask_idx] ^= (1<<pos);
+}
+
+inline struct cu_ctrl_reg *
+to_cu_ctrl_reg(u32 *reg)
+{
+	return (struct cu_ctrl_reg *)reg;
+}
+
+/**
+ * cu_done() - Check status of CU which execute cmd
+ *
+ * @cmd: submmited command
+ *
+ * This function is called to check if the CU which execute cmd is done.
+ * The cmd should be guaranteed to have been submitted.
+ *
+ * Return: %true if cu done, %false otherwise
+ */
+inline int
+cu_done(struct sched_cmd *cmd)
+{
+	struct drm_zocl_dev *zdev = cmd->ddev->dev_private;
+	int cu_idx = cmd->cu_idx;
+	struct zocl_cu *cu = &cmd->exec->zcu[cu_idx];
+	struct sched_cmd *fc;
+
+	SCHED_DEBUG("-> %s (,%d)\n", __func__, cu_idx);
+
+	fc = list_first_entry(&cu->running_queue, struct sched_cmd, rq_list);
+	/* Check if this cmd is the first one running on the CU */
+	if (fc != cmd) {
+		SCHED_DEBUG("<- %s returns 0\n", __func__);
+		return false;
+	}
+
+	zocl_cu_check(cu);
+
+	if (cu->done_cnt > 0) {
+		unsigned int mask_idx = cu_mask_idx(cu_idx);
+		unsigned int pos = cu_idx_in_mask(cu_idx);
+
+		set_cmd_ext_timestamp(cmd, CU_DONE_TIME);
+		/* if cu is busy, change the status to free */
+		if (zdev->exec->cu_status[mask_idx] & 1<<pos)
+			zdev->exec->cu_status[mask_idx] ^= 1<<pos;
+
+		/* This command is completed, refund credit and delete it */
+		zocl_cu_refund_credit(cu, 1);
+		list_del(&cmd->rq_list);
+		cu->done_cnt--;
+
+		SCHED_DEBUG("<- %s returns 1\n", __func__);
+		return true;
+	}
+	SCHED_DEBUG("<- %s returns 0\n", __func__);
+	return false;
+}
+
+inline int
+scu_done(struct sched_cmd *cmd)
+{
+	struct drm_zocl_dev *zdev = cmd->ddev->dev_private;
+	int cu_idx = cmd->cu_idx;
+	struct soft_krnl *sk = zdev->soft_kernel;
+	u32 *virt_addr;
+
+	/* We simulate hard CU here.
+	 * done is indicated by AP_DONE(2) alone or by AP_DONE(2) | AP_IDLE(4)
+	 * but not by AP_IDLE itself.  Since 0x10 | (0x10 | 0x100) = 0x110
+	 * checking for 0x10 is sufficient.
+	 */
+	mutex_lock(&sk->sk_lock);
+	if (!sk->sk_cu[cu_idx]) {
+		mutex_unlock(&sk->sk_lock);
+		return true;
+	}
+	virt_addr = sk->sk_cu[cu_idx]->sc_vregs;
+	SCHED_DEBUG("-> %s (,%d) checks scu at address 0x%p\n",
+	    __func__, cu_idx, virt_addr);
+	if (*virt_addr & 2) {
+		unsigned int mask_idx = cu_mask_idx(cu_idx);
+		unsigned int pos = cu_idx_in_mask(cu_idx);
+
+		zdev->exec->scu_status[mask_idx] ^= 1 << pos;
+		*virt_addr &= ~2;
+		mutex_unlock(&sk->sk_lock);
+		SCHED_DEBUG("<- %s returns 1\n", __func__);
+		return true;
+	}
+	mutex_unlock(&sk->sk_lock);
+	SCHED_DEBUG("<- %s returns 0\n", __func__);
+	return false;
+}
+
+inline int
+scu_configure_done(struct sched_cmd *cmd)
+{
+	struct drm_device *dev = cmd->ddev;
+	struct drm_zocl_dev *zdev = dev->dev_private;
+	struct soft_krnl *sk = zdev->soft_kernel;
+	struct ert_configure_sk_cmd *cfg;
+	int i;
+
+	cfg = (struct ert_configure_sk_cmd *)(cmd->packet);
+
+	mutex_lock(&sk->sk_lock);
+
+	for (i = cfg->start_cuidx; i < cfg->start_cuidx + cfg->num_cus; i++)
+		if (sk->sk_cu[i] == NULL) {
+			/*
+			 * If we have any unconfigured soft kernel CU, this
+			 * configure command is not completed yet.
+			 */
+			mutex_unlock(&sk->sk_lock);
+			return false;
+		}
+
+	mutex_unlock(&sk->sk_lock);
+
+	return true;
+}
+
+inline int
+scu_unconfig_done(struct sched_cmd *cmd)
+{
+	struct drm_device *dev = cmd->ddev;
+	struct drm_zocl_dev *zdev = dev->dev_private;
+	struct soft_krnl *sk = zdev->soft_kernel;
+	struct ert_unconfigure_sk_cmd *cfg;
+	int i;
+
+	cfg = (struct ert_unconfigure_sk_cmd *)(cmd->packet);
+
+	mutex_lock(&sk->sk_lock);
+	for (i = cfg->start_cuidx; i < cfg->start_cuidx + cfg->num_cus; i++)
+		if (sk->sk_cu[i]) {
+			/*
+			 * If we have any configured soft kernel CU, this
+			 * unconfigure command is not completed yet.
+			 */
+			mutex_unlock(&sk->sk_lock);
+			return false;
+		}
+
+	mutex_unlock(&sk->sk_lock);
+
+	return true;
+}
+
+/**
+ * notify_host() - Notify user space that a command is complete.
+ */
+static void
+notify_host(struct sched_cmd *cmd)
+{
+	struct list_head *ptr;
+	struct sched_client_ctx *entry;
+	struct drm_zocl_dev *zdev = cmd->ddev->dev_private;
+	struct sched_exec_core *exec = zdev->exec;
+	unsigned long flags = 0;
+
+	SCHED_DEBUG("-> %s from num_running: %d\n",
+	    __func__, atomic_read(&exec->scheduler->num_running));
+
+	atomic_dec(&exec->scheduler->num_running);
+
+	if (!zdev->ert) {
+		/* for each client update the trigger counter in the context */
+		spin_lock_irqsave(&zdev->exec->ctx_list_lock, flags);
+		list_for_each(ptr, &zdev->exec->ctx_list) {
+			entry = list_entry(ptr, struct sched_client_ctx, link);
+			atomic_inc(&entry->trigger);
+			SCHED_DEBUG("-> %s trigger %d\n", __func__,
+			    atomic_read(&entry->trigger));
+		}
+		spin_unlock_irqrestore(&zdev->exec->ctx_list_lock, flags);
+		/* wake up all the clients */
+		wake_up_interruptible(&zdev->exec->poll_wait_queue);
+	} else {
+		zdev->ert->ops->notify_host(zdev->ert, cmd->cq_slot_idx);
+                atomic_inc(&exec->scheduler->num_notified);
+	}
+	SCHED_DEBUG("<- %s to num_running: %d\n",
+	    __func__, atomic_read(&exec->scheduler->num_running));
+}
+
+/**
+ * Note: zocl copy bo will use built-in dma without
+ * using any real ERT CU kernel, we will need to increase
+ * the poll count to wake up scheduler when dma is done
+ */
+static inline void
+polling_cnt_inc(struct sched_cmd *cmd)
+{
+	struct drm_zocl_dev *zdev = cmd->ddev->dev_private;
+
+	if (zdev->ert || zdev->exec->polling_mode ||
+	    (opcode(cmd) == ERT_START_COPYBO))
+		++cmd->sched->poll;
+}
+
+static inline void
+polling_cnt_dec(struct sched_cmd *cmd)
+{
+	struct drm_zocl_dev *zdev = cmd->ddev->dev_private;
+
+	if (zdev->ert || zdev->exec->polling_mode ||
+	    (opcode(cmd) == ERT_START_COPYBO))
+		--cmd->sched->poll;
+}
+
+/**
+ * mark_cmd_complete() - Move a command to complete state
+ *
+ * Commands are marked complete in two ways
+ *  1. Through polling of CUs or polling of MB status register
+ *  2. Through interrupts from MB
+ * In both cases, the completed commands are residing in the completed_cmds
+ * list and the number of completed commands is reflected in num_completed.
+ *
+ * @xcmd: Command to mark complete
+ *
+ * The command is removed from the slot it occupies in the device command
+ * queue. The slot is released so new commands can be submitted. The host
+ * is notified that some command has completed.
+ */
+static void
+mark_cmd_complete(struct sched_cmd *cmd, enum ert_cmd_state cmd_state)
+{
+	struct drm_zocl_dev *zdev = cmd->ddev->dev_private;
+
+	SCHED_DEBUG("-> %s(,%d)\n", __func__, cmd->slot_idx);
+	zdev->exec->submitted_cmds[cmd->slot_idx] = NULL;
+	set_cmd_state(cmd, cmd_state);
+	polling_cnt_dec(cmd);
+	release_slot_idx(cmd->ddev, cmd->slot_idx);
+	notify_host(cmd);
+	SCHED_DEBUG("<- %s\n", __func__);
+}
+
+/**
+ * During cmd submit within queued_to_running, we need to handle cases that
+ * submit failed then we want to bail out this cmd by setting it as ERROR.
+ * We will need to notify host as well.
+ */
+static void
+mark_cmd_submit_error(struct sched_cmd *cmd)
+{
+	set_cmd_state(cmd, ERT_CMD_STATE_ERROR);
+	notify_host(cmd);
+}
+
+/**
+ * For pending cmds before or during cmd submit, scheduler might has been
+ * set to stop. We want to bail out those cmds by set it to ABORT. We will
+ * need to notify host as well.
+ */
+static void
+mark_cmd_submit_abort(struct sched_cmd *cmd)
+{
+	set_cmd_state(cmd, ERT_CMD_STATE_ABORT);
+	notify_host(cmd);
+}
+
+/**
+ * get_free_sched_cmd() - Get a free command object
+ *
+ * Get from free/recycled list or allocate a new command if necessary.
+ *
+ * Return: Free command object
+ */
+static struct sched_cmd*
+get_free_sched_cmd(void)
+{
+	struct sched_cmd *cmd;
+
+	SCHED_DEBUG("-> %s\n", __func__);
+	mutex_lock(&free_cmds_mutex);
+	cmd = list_first_entry_or_null(&free_cmds, struct sched_cmd, list);
+	if (cmd)
+		list_del(&cmd->list);
+	mutex_unlock(&free_cmds_mutex);
+	if (!cmd)
+		cmd = kmalloc(sizeof(struct sched_cmd), GFP_KERNEL);
+	if (!cmd)
+		return ERR_PTR(-ENOMEM);
+	memset(&cmd->dma_handle, 0, sizeof(zocl_dma_handle_t));
+	SCHED_DEBUG("<- %s %p\n", __func__, cmd);
+	return cmd;
+}
+
+/**
+ * zocl_gem_object_unref() - unreference a drm object
+ *
+ * @cmd: cmd owning the drm object to be unreference,
+ *       it could be CMA or normal gem buffer
+ *
+ * Use the correct way to unreference a gem object
+ *
+ */
+void zocl_gem_object_unref(struct sched_cmd *cmd)
+{
+	struct drm_zocl_dev *zdev = cmd->ddev->dev_private;
+	struct drm_zocl_bo *bo = cmd->buffer;
+
+	if (zdev->domain)
+		ZOCL_DRM_GEM_OBJECT_PUT_UNLOCKED(&bo->gem_base);
+	else
+		ZOCL_DRM_GEM_OBJECT_PUT_UNLOCKED(&bo->cma_base.base);
+}
+
+/*
+ * add_cmd() - Add a new command to the pending list
+ *
+ * @ddev: drm device owning adding the buffer object
+ * @bo: buffer objects from user space from which new command is created
+ *
+ * Scheduler copies pending commands to its internal command queue.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int
+add_cmd(struct sched_cmd *cmd)
+{
+	int ret = 0;
+	unsigned long flags;
+
+	SCHED_DEBUG("-> %s\n", __func__);
+
+	if (atomic_read(&cmd->exec->exec_status) != ZOCL_EXEC_NORMAL)
+		return -EBUSY;
+
+	cmd->cu_idx = -1;
+	cmd->slot_idx = -1;
+	DRM_DEBUG("packet header 0x%08x, data 0x%08x\n",
+		  cmd->packet->header, cmd->packet->data[0]);
+	set_cmd_state(cmd, ERT_CMD_STATE_NEW);
+	spin_lock_irqsave(&pending_cmds_lock, flags);
+	list_add_tail(&cmd->list, &pending_cmds);
+	spin_unlock_irqrestore(&pending_cmds_lock, flags);
+
+	/* wake scheduler */
+	atomic_inc(&cmd->exec->scheduler->num_pending);
+	wake_up_interruptible(&cmd->sched->wait_queue);
+
+	SCHED_DEBUG("<- %s\n", __func__);
+	return ret;
+}
+
+/*
+ * add_gem_bo_cmd() - add a command by gem buffer object
+ *
+ * @ddev: drm device owning adding the buffer object
+ * @bo: buffer objects from user space from which new command is created
+ *
+ * Get a free scheduler command and initial it by gem buffer object.
+ * After all, add this command to pending list.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int
+add_gem_bo_cmd(struct drm_device *dev, struct drm_zocl_bo *bo,
+	struct sched_client_ctx *client)
+{
+	struct sched_cmd *cmd;
+	struct drm_zocl_dev *zdev = dev->dev_private;
+	struct ert_packet *packet;
+	int ret;
+
+	cmd = get_free_sched_cmd();
+	if (!cmd)
+		return -ENOMEM;
+
+	SCHED_DEBUG("-> %s\n", __func__);
+	cmd->ddev = dev;
+	cmd->sched = zdev->exec->scheduler;
+	cmd->buffer = (void *)bo;
+	cmd->exec = zdev->exec;
+	cmd->client = client;
+	if (zdev->domain)
+		packet = (struct ert_packet *)bo->vmapping;
+	else
+		packet = (struct ert_packet *)bo->cma_base.vaddr;
+	cmd->packet = packet;
+	cmd->timestamp_enabled = enable_cmd_timestamps(cmd);
+	cmd->cq_slot_idx = 0;
+	cmd->free_buffer = zocl_gem_object_unref;
+	atomic_inc(&client->outstanding_execs);
+
+	ret = add_cmd(cmd);
+
+	SCHED_DEBUG("<- %s\n", __func__);
+	return ret;
+}
+
+/**
+ * recycle_cmd() - recycle a command objects
+ *
+ * @cmd: command object to recycle
+ *
+ * Command object is added to the freelist
+ *
+ * Return: 0
+ */
+static int
+recycle_cmd(struct sched_cmd *cmd)
+{
+	SCHED_DEBUG("%s %p\n", __func__, cmd);
+	mutex_lock(&free_cmds_mutex);
+	list_move_tail(&cmd->list, &free_cmds);
+	mutex_unlock(&free_cmds_mutex);
+
+	if (!is_ert(cmd->ddev))
+		atomic_dec(&cmd->client->outstanding_execs);
+
+	return 0;
+}
+
+/**
+ * delete_cmd_list() - reclaim memory for all allocated command objects
+ */
+static void
+delete_cmd_list(void)
+{
+	struct sched_cmd *cmd;
+	struct list_head *pos, *next;
+
+	mutex_lock(&free_cmds_mutex);
+	list_for_each_safe(pos, next, &free_cmds) {
+		cmd = list_entry(pos, struct sched_cmd, list);
+		list_del(pos);
+		kfree(cmd);
+	}
+	mutex_unlock(&free_cmds_mutex);
+}
+
+static inline void
+zocl_print_stale_cmd(struct sched_cmd *cmd)
+{
+	DRM_INFO("stale cmd state[%d], cu[%d], slot[%d], cq_slot[%d]",
+	    cmd->state, cmd->cu_idx, cmd->slot_idx, cmd->cq_slot_idx);
+	if (!is_ert(cmd->ddev)) {
+		DRM_INFO("          check_timeout=%d, client pid %d.",
+			 cmd->check_timeout, pid_nr(cmd->client->pid));
+	}
+}
+
+/**
+ * reset_all() - Reset the scheduler
+ *
+ * Clear stale command objects if any. This can occur if the HW for
+ * some reason hangs.
+ */
+static void
+reset_all(void)
+{
+	struct sched_cmd *cmd;
+
+	/* clear stale command object if any */
+	while (!list_empty(&pending_cmds)) {
+		cmd = list_first_entry(&pending_cmds, struct sched_cmd, list);
+		DRM_INFO("deleting stale pending cmd\n");
+		zocl_print_stale_cmd(cmd);
+		cmd->free_buffer(cmd);
+		recycle_cmd(cmd);
+	}
+	while (!list_empty(&g_sched0.cq)) {
+		cmd = list_first_entry(&g_sched0.cq, struct sched_cmd, list);
+		DRM_INFO("deleting stale scheduler cmd\n");
+		zocl_print_stale_cmd(cmd);
+		cmd->free_buffer(cmd);
+		recycle_cmd(cmd);
+	}
+}
+
+static int
+ert_get_cu(struct sched_cmd *cmd, enum zocl_cu_type cu_type)
+{
+	struct drm_zocl_dev *zdev = cmd->ddev->dev_private;
+	struct sched_exec_core *exec = zdev->exec;
+	u32 busy_mask;
+	int cu_idx, cu_bit;
+
+	/* Let's trust host, the cu_idx should be valid */
+	cu_idx = cmd->packet->data[0];
+	cu_bit = cu_idx_in_mask(cu_idx);
+
+	/* Check if the specific CU is busy */
+	busy_mask = cu_type == ZOCL_SOFT_CU ?
+	    exec->scu_status[cu_mask_idx(cu_idx)] :
+	    exec->cu_status[cu_mask_idx(cu_idx)];
+
+	if (busy_mask & (1 << cu_bit))
+		return -1;
+
+	if (cu_type == ZOCL_HARD_CU) {
+		/* The specific CU is ready */
+		if (!zocl_cu_get_credit(&exec->zcu[cu_idx]))
+			exec->cu_status[cu_mask_idx(cu_idx)] ^= 1 << cu_bit;
+	} else
+		exec->scu_status[cu_mask_idx(cu_idx)] ^= 1 << cu_bit;
+
+	return cu_idx;
+}
+
+/**
+ * get_free_cu() - get index of first available CU per command cu mask
+ *
+ * @cmd:    command containing CUs to check for availability
+ * @cu_type: ZOCL_SOFT_CU(1) to get free soft CU,
+ *           ZOCL_HARD_CU(0) to get free hard CU
+ *
+ * This function is called kernel software scheduler mode only, in embedded
+ * scheduler mode, the hardware scheduler handles the commands directly.
+ *
+ * Return: Index of free CU,
+ *         -1 of no CU is available,
+ *         -EINVAL cu_mask is invalid.
+ */
+static int
+get_free_cu(struct sched_cmd *cmd, enum zocl_cu_type cu_type)
+{
+	int mask_idx = 0;
+	struct drm_zocl_dev *zdev = cmd->ddev->dev_private;
+	int num_masks = cu_masks(cmd);
+	struct sched_exec_core *exec = zdev->exec;
+	int cu_idx, cu_bit;
+	int valid_found = 0;
+
+	SCHED_DEBUG("-> %s\n", __func__);
+
+	for (mask_idx = 0; mask_idx < num_masks; ++mask_idx) {
+		u32 cmd_mask = cmd->packet->data[mask_idx]; /* skip header */
+		u32 busy_mask = cu_type == ZOCL_SOFT_CU ?
+		    exec->scu_status[mask_idx]
+		    : exec->cu_status[mask_idx];
+		u32 free_mask = (cmd_mask | busy_mask) ^ busy_mask;
+		/* for soft cu, cu is always valid */
+		u32 valid_mask = cu_type == ZOCL_SOFT_CU ?
+		    (u32)-1 : exec->cu_valid[mask_idx];
+
+		if (cmd_mask & valid_mask)
+			valid_found = 1;
+
+		/* For hardware cu, we have to search on valid CUs only. */
+		if (cu_type == ZOCL_HARD_CU)
+			free_mask &= exec->cu_valid[mask_idx];
+
+		cu_bit = ffs_or_neg_one(free_mask);
+
+		if (cu_bit < 0)
+			continue;
+
+		cu_idx = cu_idx_from_mask(cu_bit, mask_idx);
+		if (cu_type == ZOCL_HARD_CU) {
+			 /* KDS should not over spending credits */
+			if (!zocl_cu_get_credit(&exec->zcu[cu_idx]))
+				exec->cu_status[mask_idx] ^= 1 << cu_bit;
+		} else
+			exec->scu_status[mask_idx] ^= 1 << cu_bit;
+		SCHED_DEBUG("<- %s returns %d\n", __func__, cu_idx);
+		return cu_idx;
+	}
+
+	if (!valid_found)
+		DRM_WARN("Cannot find valid cu from cu_mask");
+	valid_found = valid_found ? -1 : -EINVAL;
+	SCHED_DEBUG("<- %s exhausted returns %d\n", __func__, valid_found);
+	return valid_found;
+}
+
+/**
+ * configure_cu() - transfer command register map to specified CU and
+ *                  start the CU.
+ *
+ * @cmd: command with register map to transfer to CU
+ * @cu_idx: index of CU to configure
+ *
+ * This function is called in kernel software scheduler mode only.
+ */
+static void
+configure_cu(struct sched_cmd *cmd, int cu_idx)
+{
+	u32 size = regmap_size(cmd);
+	struct ert_start_kernel_cmd *sk;
+	struct zocl_cu *cu = &cmd->exec->zcu[cu_idx];
+	int type;
+
+	SCHED_DEBUG("-> %s cu_idx=%d, regmap_size=%d\n",
+	    __func__, cu_idx, size);
+
+	sk = (struct ert_start_kernel_cmd *)cmd->packet;
+
+	if (opcode(cmd) == ERT_EXEC_WRITE)
+		type = PAIRS;
+	else
+		type = CONSECUTIVE;
+
+	zocl_cu_configure(cu, sk->data + sk->extra_cu_masks, size, type);
+
+	/* Let user know which CU execute this command */
+	set_cmd_ext_cu_idx(cmd, cu_idx);
+
+	set_cmd_ext_timestamp(cmd, CU_START_TIME);
+
+	/* Set the initial command execute time */
+	cmd->exectime = cu_idx_to_timeout(cmd->ddev, cmd->cu_idx);
+	cmd->check_timeout = cmd->exectime > 0 ? 1 : 0;
+
+	zocl_cu_start(cu);
+	list_add_tail(&cmd->rq_list, &cu->running_queue);
+
+	SCHED_DEBUG("<- %s\n", __func__);
+}
+
+/**
+ * ert_configure_cu() - transfer command register map to specified CU and
+ *                      start the CU.
+ *
+ * @cmd: command with register map to transfer to CU
+ * @cu_idx: index of CU to configure
+ *
+ * This function is called in kernel software scheduler mode only.
+ */
+static void
+ert_configure_cu(struct sched_cmd *cmd, int cu_idx)
+{
+	u32 size = regmap_size(cmd);
+	struct ert_start_kernel_cmd *sk;
+	struct zocl_cu *cu = &cmd->exec->zcu[cu_idx];
+	int type;
+
+	SCHED_DEBUG("-> %s cu_idx=%d, regmap_size=%d\n",
+	    __func__, cu_idx, size);
+
+	sk = (struct ert_start_kernel_cmd *)cmd->packet;
+
+	if (opcode(cmd) == ERT_EXEC_WRITE)
+		type = PAIRS;
+	else
+		type = CONSECUTIVE;
+
+	zocl_cu_configure(cu, sk->data + sk->extra_cu_masks, size, type);
+
+	zocl_cu_start(cu);
+	list_add_tail(&cmd->rq_list, &cu->running_queue);
+
+	SCHED_DEBUG("<- %s\n", __func__);
+}
+
+static int
+ert_configure_scu(struct sched_cmd *cmd, int cu_idx)
+{
+	struct drm_zocl_dev *zdev = cmd->ddev->dev_private;
+	struct soft_krnl *sk = zdev->soft_kernel;
+	struct soft_cu *scu;
+	u32 i, size = regmap_size(cmd);
+	u32 *cu_regfile;
+	struct ert_start_kernel_cmd *skc;
+
+	skc = (struct ert_start_kernel_cmd *)cmd->packet;
+
+	SCHED_DEBUG("-> %s", __func__);
+
+	mutex_lock(&sk->sk_lock);
+	scu = sk->sk_cu[cu_idx];
+	if (!scu) {
+		DRM_ERROR("Error: soft cu %d does not exist.\n", cu_idx);
+		mutex_unlock(&sk->sk_lock);
+		return -ENXIO;
+	}
+
+	cu_regfile = scu->sc_vregs;
+
+	SCHED_DEBUG("cu_idx=%d, cu_addr=0x%p, regmap_size=%d\n",
+		    cu_idx, cu_regfile, size);
+
+	/* Copy payload to soft CU register */
+	for (i = 1; i < size; ++i)
+		cu_regfile[i] = *(skc->data + skc->extra_cu_masks + i);
+
+	up(&scu->sc_sem);
+	scu->usage++;
+	mutex_unlock(&sk->sk_lock);
+
+	SCHED_DEBUG("<- %s", __func__);
+
+	return 0;
+}
+
+/**
+ * zocl_reset_cu() - Reset a running command and CU.
+ *
+ * @cmd: Command to reset. CU is pointed by cmd->cu_idx.
+ *
+ * Reset a CU when detecting CU timeout. After resetting CU, we will
+ * busy wait a preset reset_timeout Microseconds. If CU is reset
+ * successfully, we set cmd state to TIMEOUT so that this CU can be
+ * restarted. If reset is not done after this period of time, we set
+ * cmd state to NORESPONSE to indicate the CU timeout and reset fails.
+ */
+static void
+zocl_reset_cu(struct sched_cmd *cmd)
+{
+	struct drm_zocl_dev *zdev = cmd->ddev->dev_private;
+	int cu_idx = cmd->cu_idx;
+	uint32_t reset_timeout = cu_idx_to_reset_timeout(cmd->ddev, cu_idx);
+	unsigned int mask_idx = cu_mask_idx(cu_idx);
+	unsigned int pos = cu_idx_in_mask(cu_idx);
+	enum ert_cmd_state cmd_state;
+
+	SCHED_DEBUG("-> %s (,%d)\n", __func__, cmd->slot_idx);
+
+	zocl_cu_reset(&zdev->exec->zcu[cu_idx]);
+	while (reset_timeout) {
+		if (zocl_cu_reset_done(&zdev->exec->zcu[cu_idx]))
+			break;
+		udelay(ZOCL_CU_RESET_TIMER_INTERVAL);
+		reset_timeout--;
+	}
+
+	if (reset_timeout == 0) {
+		DRM_ERROR("CU %d timeouts and reset fails.\n", cmd->cu_idx);
+		cmd_state = ERT_CMD_STATE_NORESPONSE;
+	} else {
+		DRM_WARN("CU %d timeouts and has been reset successfully.\n",
+		    cmd->cu_idx);
+		cmd_state = ERT_CMD_STATE_TIMEOUT;
+	}
+
+	zdev->exec->cu_status[mask_idx] ^= 1<<pos;
+	mark_cmd_complete(cmd, cmd_state);
+
+	SCHED_DEBUG("<- %s (,%d)\n", __func__, cmd->slot_idx);
+}
+
+/**
+ * check_cmds_timeout() - Decrease the execute time and check cmds timeout.
+ *
+ * We reach the checkpoint indicated by the timer thread. So we do a
+ * special check for every command in the running state. Decrease the
+ * command's run time and check if it goes to zero.
+ */
+static void
+check_cmds_timeout(struct scheduler *sched)
+{
+	struct sched_cmd *cmd;
+	struct list_head *pos, *next;
+
+	list_for_each_safe(pos, next, &sched->cq) {
+		cmd = list_entry(pos, struct sched_cmd, list);
+
+		if (cmd->check_timeout && cmd->state == ERT_CMD_STATE_RUNNING) {
+			cmd->exectime--;
+			if (cmd->exectime == 0) {
+				/*
+				 * Detected command timeout. We mark the
+				 * internal command state to TIMEOUT so that
+				 * we can perform reset operation on this
+				 * command and CU.
+				 */
+				set_cmd_int_state(cmd, ERT_CMD_STATE_TIMEOUT);
+			}
+		}
+	}
+}
+
+/**
+ * queued_to_running() - Move a command from queued to running state if possible
+ *
+ * @cmd: Command to start
+ *
+ * Upon success, the command is not necessarily running. In ert mode the
+ * command will have been submitted to the embedded scheduler, whereas in
+ * penguin mode the command has been started on a CU.
+ *
+ * Return: %true if command was submitted to device, %false otherwise
+ */
+static int
+queued_to_running(struct sched_cmd *cmd)
+{
+	struct drm_zocl_dev *zdev = cmd->ddev->dev_private;
+	int retval = false;
+
+	SCHED_DEBUG("-> %s\n", __func__);
+	if (opcode(cmd) == ERT_CONFIGURE)
+		configure(cmd);
+
+	if (opcode(cmd) == ERT_CU_STAT)
+		cu_stat(cmd);
+
+	if (opcode(cmd) == ERT_INIT_CU)
+		init_cus(cmd);
+
+	if (zdev->exec->ops->submit(cmd)) {
+		set_cmd_int_state(cmd, ERT_CMD_STATE_RUNNING);
+		polling_cnt_inc(cmd);
+		zdev->exec->submitted_cmds[cmd->slot_idx] = cmd;
+		retval = true;
+	}
+	SCHED_DEBUG("<- %s returns %d\n", __func__, retval);
+
+	return retval;
+}
+
+/**
+ * running_to_complete() - Check status of running commands
+ *
+ * @cmd: Command is in running state
+ *
+ * If a command is found to be complete, it marked complete prior to return
+ * from this function.
+ */
+static void
+running_to_complete(struct sched_cmd *cmd)
+{
+	struct drm_zocl_dev *zdev = cmd->ddev->dev_private;
+
+	SCHED_DEBUG("-> %s\n", __func__);
+	zdev->exec->ops->query(cmd);
+	SCHED_DEBUG("<- %s\n", __func__);
+}
+
+/**
+ * complete_to_free() - Recycle a complete command objects
+ *
+ * @xcmd: Command is in complete state
+ */
+static void
+complete_to_free(struct sched_cmd *cmd)
+{
+
+	SCHED_DEBUG("-> %s\n", __func__);
+	cmd->free_buffer(cmd);
+	recycle_cmd(cmd);
+	SCHED_DEBUG("<- %s\n", __func__);
+}
+
+
+/**
+ * scheduler_queue_cmds() - Queue any pending commands
+ *
+ * The scheduler copies pending commands to its internal command queue where
+ * is is now in queued state.
+ */
+static void
+scheduler_queue_cmds(struct scheduler *sched)
+{
+	struct sched_cmd *cmd;
+	struct list_head *pos, *next;
+	unsigned long flags;
+
+	SCHED_DEBUG("-> %s\n", __func__);
+
+	spin_lock_irqsave(&pending_cmds_lock, flags);
+	list_for_each_safe(pos, next, &pending_cmds) {
+		cmd = list_entry(pos, struct sched_cmd, list);
+		if (cmd->sched != sched)
+			continue;
+		list_del(&cmd->list);
+		atomic_dec(&cmd->exec->scheduler->num_pending);
+		list_add_tail(&cmd->list, &sched->cq);
+		atomic_inc(&sched->num_running);
+		set_cmd_int_state(cmd, ERT_CMD_STATE_QUEUED);
+	}
+	spin_unlock_irqrestore(&pending_cmds_lock, flags);
+	SCHED_DEBUG("<- %s\n", __func__);
+}
+
+static void
+cmd_update_state(struct sched_cmd *cmd)
+{
+	/*
+	 * In the case of ERT, stalled commands are handled by host
+	 * XRT. So we just bail out here.
+	 */
+	if (is_ert(cmd->ddev))
+		return;
+
+	if (cmd->state != ERT_CMD_STATE_RUNNING && cmd->client->abort) {
+		DRM_INFO("Aborting cmds for closing pid(%d)",
+		    pid_nr(cmd->client->pid));
+		zocl_print_stale_cmd(cmd);
+		mark_cmd_submit_abort(cmd);
+	}
+	/* Abort stuck CUs, but still let 'healthy' CU continue */
+	if ((atomic_read(&cmd->exec->exec_status) ==
+	    ZOCL_EXEC_FLUSH) && (cmd->cu_idx < 0)) {
+		zocl_print_stale_cmd(cmd);
+		mark_cmd_submit_abort(cmd);
+	}
+}
+
+/**
+ * scheduler_iterate_cmds() - Iterate all commands in scheduler command queue
+ */
+static void
+scheduler_iterate_cmds(struct scheduler *sched)
+{
+	struct sched_cmd *cmd;
+	struct list_head *pos, *next;
+
+	SCHED_DEBUG("-> %s\n", __func__);
+
+	if (atomic_read(&sched->check)) {
+		atomic_set(&sched->check, 0);
+		check_cmds_timeout(sched);
+	}
+
+	list_for_each_safe(pos, next, &sched->cq) {
+		cmd = list_entry(pos, struct sched_cmd, list);
+
+		cmd_update_state(cmd);
+
+		if (cmd->state == ERT_CMD_STATE_QUEUED)
+			queued_to_running(cmd);
+		if (cmd->state == ERT_CMD_STATE_RUNNING)
+			running_to_complete(cmd);
+		if (cmd->state == ERT_CMD_STATE_TIMEOUT)
+			zocl_reset_cu(cmd);
+		if (cmd->state == ERT_CMD_STATE_COMPLETED ||
+		    cmd->state == ERT_CMD_STATE_ABORT ||
+		    cmd->state == ERT_CMD_STATE_TIMEOUT ||
+		    cmd->state == ERT_CMD_STATE_ERROR ||
+		    cmd->state == ERT_CMD_STATE_NORESPONSE)
+			complete_to_free(cmd);
+	}
+
+	SCHED_DEBUG("<- %s\n", __func__);
+}
+
+/**
+ * sched_wait_cond() - Check status of scheduler wait condition
+ *
+ * Scheduler must wait (sleep) if
+ *  1. there are no pending commands
+ *  2. no pending interrupt from embedded scheduler
+ *  3. no pending complete commands in polling mode
+ *
+ * Return: 1 if scheduler must wait, 0 othewise
+ */
+static int
+sched_wait_cond(struct scheduler *sched)
+{
+	if (kthread_should_stop() || sched->error) {
+		sched->stop = 1;
+		SCHED_DEBUG("scheduler wakes kthread_should_stop\n");
+		return 0;
+	}
+
+	if (atomic_read(&sched->num_pending)) {
+		SCHED_DEBUG("scheduler wakes to copy new pending commands\n");
+		return 0;
+	}
+
+	if (sched->intc) {
+		SCHED_DEBUG("scheduler wakes on interrupt\n");
+		sched->intc = 0;
+		return 0;
+	}
+
+	if (sched->poll) {
+		SCHED_DEBUG("scheduler wakes to poll\n");
+		return 0;
+	}
+
+	if (atomic_read(&sched->check)) {
+		SCHED_DEBUG("scheduler wakes on timer\n");
+		return 0;
+	}
+
+	SCHED_DEBUG("scheduler waits ...\n");
+	return 1;
+}
+
+/**
+ * scheduler_wait() - check if scheduler should wait
+ *
+ * See sched_wait_cond().
+ */
+static void
+scheduler_wait(struct scheduler *sched)
+{
+	wait_event_interruptible(sched->wait_queue, !sched_wait_cond(sched));
+}
+
+/**
+ * scheduler_loop() - Run one loop of the scheduler
+ */
+static void
+scheduler_loop(struct scheduler *sched)
+{
+	SCHED_DEBUG("-> %s\n", __func__);
+
+	scheduler_wait(sched);
+
+	if (sched->stop) {
+		if (sched->error)
+			DRM_ERROR("Unexpected error and exits\n");
+		return;
+	}
+
+	/* queue new pending commands */
+	scheduler_queue_cmds(sched);
+
+	/* iterate all commands */
+	scheduler_iterate_cmds(sched);
+
+	if (sched_loop_cnt < MAX_SCHED_LOOP)
+		sched_loop_cnt++;
+	else {
+		sched_loop_cnt = 0;
+		schedule();
+	}
+}
+
+/**
+ * scheduler() - Command scheduler thread routine
+ */
+static int
+scheduler(void *data)
+{
+	struct scheduler *sched = (struct scheduler *)data;
+
+	while (!sched->stop)
+		scheduler_loop(sched);
+	DRM_DEBUG("%s thread exits with value %d\n", __func__, sched->error);
+	return sched->error;
+}
+
+/**
+ * init_scheduler_thread() - Initialize scheduler thread if necessary
+ *
+ * Return: 0 on success, -errno otherwise
+ */
+static int
+init_scheduler_thread(void)
+{
+	char name[256] = "zocl-scheduler-thread0";
+
+	SCHED_DEBUG("%s use_count=%d\n", __func__, g_sched0.use_count);
+	if (g_sched0.use_count++)
+		return 0;
+
+	sched_loop_cnt = 0;
+
+	init_waitqueue_head(&g_sched0.wait_queue);
+	g_sched0.error = 0;
+	g_sched0.stop = 0;
+
+	INIT_LIST_HEAD(&g_sched0.cq);
+	g_sched0.intc = 0;
+	g_sched0.poll = 0;
+	atomic_set(&g_sched0.check, 0);
+
+	g_sched0.sched_thread = kthread_run(scheduler, &g_sched0, name);
+	if (IS_ERR(g_sched0.sched_thread)) {
+		int ret = PTR_ERR(g_sched0.sched_thread);
+
+		DRM_ERROR(__func__);
+		return ret;
+	}
+	return 0;
+}
+
+/**
+ * fini_scheduler_thread() - Finalize scheduler thread if unused
+ *
+ * Return: 0 on success, -errno otherwise
+ */
+static int
+fini_scheduler_thread(void)
+{
+	int retval = 0;
+
+	SCHED_DEBUG("%s use_count=%d\n", __func__, g_sched0.use_count);
+	if (--g_sched0.use_count)
+		return 0;
+
+	retval = kthread_stop(g_sched0.sched_thread);
+
+	/* clear stale command objects if any */
+	reset_all();
+
+	/* reclaim memory for allocate command objects */
+	delete_cmd_list();
+
+	return retval;
+}
+
+static inline int
+dma_done(struct sched_cmd *cmd)
+{
+	return (cmd->dma_handle.dma_flags & ZOCL_DMA_DONE) != 0;
+}
+
+static inline bool
+dma_error(struct sched_cmd *cmd)
+{
+	return (cmd->dma_handle.dma_flags & ZOCL_DMA_ERROR) != 0;
+}
+
+static inline void
+dma_clear(struct sched_cmd *cmd)
+{
+	cmd->dma_handle.dma_flags = 0;
+}
+
+/**
+ * penguin_query() - Check command status of argument command
+ *
+ * @cmd: Command to check
+ *
+ * Function is called in penguin mode (no embedded scheduler).
+ */
+static void
+penguin_query(struct sched_cmd *cmd)
+{
+	u32 opc = opcode(cmd);
+
+	SCHED_DEBUG("-> %s() slot_idx=%d\n", __func__, cmd->slot_idx);
+	switch (opc) {
+	case ERT_START_COPYBO:
+		if (dma_done(cmd)) {
+			dma_error(cmd) ?
+			    mark_cmd_complete(cmd, ERT_CMD_STATE_ERROR) :
+			    mark_cmd_complete(cmd, ERT_CMD_STATE_COMPLETED);
+			dma_clear(cmd);
+		}
+		break;
+	case ERT_START_CU:
+	case ERT_EXEC_WRITE:
+		if (cu_done(cmd))
+			mark_cmd_complete(cmd, ERT_CMD_STATE_COMPLETED);
+		break;
+	case ERT_CU_STAT:
+	case ERT_INIT_CU:
+	case ERT_CONFIGURE:
+		mark_cmd_complete(cmd, ERT_CMD_STATE_COMPLETED);
+		break;
+	default:
+		mark_cmd_complete(cmd, ERT_CMD_STATE_ERROR);
+		DRM_ERROR("unknown opcode %d", opc);
+	}
+	SCHED_DEBUG("<- %s\n", __func__);
+}
+
+/**
+ * callback function provided to the dma engine, when dma complete
+ * this function will be called. scheduler should have the knowledge
+ * to update its internal status.
+ */
+static void zocl_dma_complete(void *arg, int ret)
+{
+	struct sched_cmd *cmd = (struct sched_cmd *)arg;
+
+	cmd->dma_handle.dma_flags |= ZOCL_DMA_DONE;
+	if (ret != 0)
+		cmd->dma_handle.dma_flags |= ZOCL_DMA_ERROR;
+
+	wake_up_interruptible(&cmd->sched->wait_queue);
+}
+
+static int
+zocl_dma_channel_instance(zocl_dma_handle_t *dma_handle,
+	struct drm_zocl_dev *zdev)
+{
+	dma_cap_mask_t dma_mask;
+
+	if (!dma_handle->dma_chan && ZOCL_PLATFORM_ARM64) {
+		/* If zdev_dma_chan is NULL, we haven't initialized it yet. */
+		if (!zdev->zdev_dma_chan) {
+			dma_cap_zero(dma_mask);
+			dma_cap_set(DMA_MEMCPY, dma_mask);
+			zdev->zdev_dma_chan =
+			    dma_request_channel(dma_mask, 0, NULL);
+			if (!zdev->zdev_dma_chan) {
+				DRM_WARN("no DMA Channel available.\n");
+				return -EBUSY;
+			}
+		}
+		dma_handle->dma_chan = zdev->zdev_dma_chan;
+	}
+
+	return dma_handle->dma_chan ? 0 : -EINVAL;
+}
+
+static int
+zocl_copy_bo_submit(struct sched_cmd *cmd)
+{
+	struct ert_start_copybo_cmd *ecmd = cmd->ert_cp;
+	struct drm_file *filp = (struct drm_file *)ecmd->arg;
+	struct drm_device *ddev = cmd->ddev;
+	struct drm_zocl_dev *zdev = ddev->dev_private;
+	zocl_dma_handle_t *dma_handle = &cmd->dma_handle;
+	struct drm_zocl_copy_bo args = {
+		.dst_handle = ecmd->dst_bo_hdl,
+		.src_handle = ecmd->src_bo_hdl,
+		.size = ert_copybo_size(ecmd),
+		.dst_offset = ert_copybo_dst_offset(ecmd),
+		.src_offset = ert_copybo_src_offset(ecmd),
+	};
+	int err = 0;
+
+	/* Get single dma channel instance. */
+	err = zocl_dma_channel_instance(dma_handle, zdev);
+	if (err)
+		return err;
+
+	/* We must set up callback for async dma operations. */
+	dma_handle->dma_func = zocl_dma_complete;
+	dma_handle->dma_arg = cmd;
+
+	return zocl_copy_bo_async(ddev, filp, dma_handle, &args);
+}
+
+/**
+ * penguin_submit() - penguin submit of a command
+ *
+ * @cmd: command to submit
+ *
+ * Special processing for configure and init command.
+ * Configuration and initialization are done/called by queued_to_running
+ * before calling penguin_submit. In penguin mode configuration and
+ * initialization need to ensure that the commands are retired properly by
+ * scheduler, so assign them slot indexes and let normal flow continue.
+ *
+ * Return: %true on successful submit, %false otherwise
+ */
+static int
+penguin_submit(struct sched_cmd *cmd)
+{
+	SCHED_DEBUG("-> %s\n", __func__);
+
+	/**
+	 * copy bo will be handled as ert command via execbuf. If submission
+	 * failed, we should bail out and notify polling waiters.
+	 */
+	if (opcode(cmd) == ERT_START_COPYBO) {
+		if (zocl_copy_bo_submit(cmd) != 0) {
+			mark_cmd_submit_error(cmd);
+			return false;
+		}
+		cmd->slot_idx = acquire_slot_idx(cmd->ddev);
+		return true;
+	}
+
+	if (opcode(cmd) == ERT_CONFIGURE) {
+		cmd->slot_idx = acquire_slot_idx(cmd->ddev);
+		SCHED_DEBUG("<- %s (configure)\n", __func__);
+		return true;
+	}
+
+	if (opcode(cmd) == ERT_CU_STAT) {
+		cmd->slot_idx = acquire_slot_idx(cmd->ddev);
+		SCHED_DEBUG("<- %s (cu_stat)\n", __func__);
+		return true;
+	}
+
+	if (opcode(cmd) == ERT_INIT_CU) {
+		cmd->slot_idx = acquire_slot_idx(cmd->ddev);
+		SCHED_DEBUG("<- %s (init CU)\n", __func__);
+		return true;
+	}
+
+	if (opcode(cmd) != ERT_START_CU && opcode(cmd) != ERT_EXEC_WRITE)
+		return false;
+
+	/* extract cu list */
+	cmd->cu_idx = get_free_cu(cmd, ZOCL_HARD_CU);
+	if (cmd->cu_idx < 0) {
+		if (cmd->cu_idx == -EINVAL)
+			mark_cmd_submit_error(cmd);
+		return false;
+	}
+
+	/* track cu executions */
+	++(cmd->exec->zcu[cmd->cu_idx].usage);
+
+	cmd->slot_idx = acquire_slot_idx(cmd->ddev);
+	if (cmd->slot_idx < 0)
+		return false;
+
+	/* found free cu, transfer regmap and start it */
+	configure_cu(cmd, cmd->cu_idx);
+
+	SCHED_DEBUG("<- %s cu_idx=%d slot=%d\n",
+	    __func__, cmd->cu_idx, cmd->slot_idx);
+
+	return true;
+}
+
+/**
+ * penguin_ops: operations for kernel mode scheduling
+ */
+static struct sched_ops penguin_ops = {
+	.submit = penguin_submit,
+	.query = penguin_query,
+};
+
+/**
+ * ps_ert_query() - Check command status of argument command
+ *
+ * @cmd: Command to check
+ *
+ * Function is called in penguin mode (no embedded scheduler).
+ */
+static void
+ps_ert_query(struct sched_cmd *cmd)
+{
+	u32 opc = opcode(cmd);
+
+	SCHED_DEBUG("-> %s() slot_idx=%d\n", __func__, cmd->slot_idx);
+	switch (opc) {
+
+	case ERT_SK_CONFIG:
+		if (scu_configure_done(cmd))
+			mark_cmd_complete(cmd, ERT_CMD_STATE_COMPLETED);
+		break;
+
+	case ERT_SK_UNCONFIG:
+		if (scu_unconfig_done(cmd))
+			mark_cmd_complete(cmd, ERT_CMD_STATE_COMPLETED);
+		break;
+
+	case ERT_SK_START:
+		if (scu_done(cmd))
+			mark_cmd_complete(cmd, ERT_CMD_STATE_COMPLETED);
+		break;
+
+	case ERT_START_CU:
+	case ERT_EXEC_WRITE:
+		if (!cu_done(cmd))
+			break;
+#if KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE
+		__attribute__ ((fallthrough));
+#else
+		__attribute__ ((__fallthrough__));
+#endif
+		/* pass through */
+
+	case ERT_CU_STAT:
+	case ERT_CONFIGURE:
+		mark_cmd_complete(cmd, ERT_CMD_STATE_COMPLETED);
+		break;
+
+	default:
+		mark_cmd_complete(cmd, ERT_CMD_STATE_ERROR);
+		DRM_ERROR("unknown opcode %d", opc);
+	}
+	SCHED_DEBUG("<- %s()", __func__);
+}
+
+/**
+ * ps_ert_submit() - PS ERT submit of a command
+ *
+ * @cmd: command to submit
+ *
+ * Special processing for configure command. Configuration itself is
+ * done/called by queued_to_running before calling penguin_submit. In penguin
+ * mode configuration need to ensure that the command is retired properly by
+ * scheduler, so assign it a slot index and let normal flow continue.
+ *
+ * Return: %true on successful submit, %false otherwise
+ */
+static int
+ps_ert_submit(struct sched_cmd *cmd)
+{
+	int ret;
+
+	SCHED_DEBUG("-> %s()", __func__);
+
+	cmd->slot_idx = acquire_slot_idx(cmd->ddev);
+	if (cmd->slot_idx < 0)
+		return false;
+
+	switch (opcode(cmd)) {
+	case ERT_CONFIGURE:
+		SCHED_DEBUG("<- %s (configure)\n", __func__);
+		break;
+
+	case ERT_CU_STAT:
+		SCHED_DEBUG("<- %s (cu stat)\n", __func__);
+		break;
+
+	case ERT_SK_CONFIG:
+		SCHED_DEBUG("<- %s (configure soft kernel)\n", __func__);
+		ret = configure_soft_kernel(cmd);
+		if (ret) {
+			release_slot_idx(cmd->ddev, cmd->slot_idx);
+			if (ret != -ENOMEM)
+				mark_cmd_submit_error(cmd);
+			return false;
+		}
+		break;
+
+	case ERT_SK_UNCONFIG:
+		SCHED_DEBUG("<- %s (unconfigure soft kernel)\n", __func__);
+		if (unconfigure_soft_kernel(cmd)) {
+			release_slot_idx(cmd->ddev, cmd->slot_idx);
+			mark_cmd_submit_error(cmd);
+			return false;
+		}
+		break;
+
+	case ERT_SK_START:
+		if (type(cmd) == ERT_CU)
+			cmd->cu_idx = ert_get_cu(cmd, ZOCL_SOFT_CU);
+		else
+			cmd->cu_idx = get_free_cu(cmd, ZOCL_SOFT_CU);
+
+		if (cmd->cu_idx < 0) {
+			release_slot_idx(cmd->ddev, cmd->slot_idx);
+			if (cmd->cu_idx == -EINVAL)
+				mark_cmd_submit_error(cmd);
+			return false;
+		}
+		if (ert_configure_scu(cmd, cmd->cu_idx)) {
+			release_slot_idx(cmd->ddev, cmd->slot_idx);
+			return false;
+		}
+
+		SCHED_DEBUG("<- %s() cu_idx=%d slot=%d cq_slot=%d\n",
+		    __func__, cmd->cu_idx, cmd->slot_idx, cmd->cq_slot_idx);
+		break;
+
+	case ERT_START_CU:
+	case ERT_EXEC_WRITE:
+		/* When command type is ERT_CU, host would set cu_idx instead of
+		 * cu_mask. The cu index is set at right after packet header.
+		 */
+		if (type(cmd) == ERT_CU)
+			cmd->cu_idx = ert_get_cu(cmd, ZOCL_HARD_CU);
+		else
+			cmd->cu_idx = get_free_cu(cmd, ZOCL_HARD_CU);
+		if (cmd->cu_idx < 0)
+			goto invalid_cu_idx;
+
+		/* found free cu, transfer regmap and start it */
+		ert_configure_cu(cmd, cmd->cu_idx);
+
+		SCHED_DEBUG("<- %s() cu_idx=%d slot=%d cq_slot=%d\n",
+		    __func__, cmd->cu_idx, cmd->slot_idx, cmd->cq_slot_idx);
+		break;
+
+	default:
+		release_slot_idx(cmd->ddev, cmd->slot_idx);
+		return false;
+	}
+
+	return true;
+
+invalid_cu_idx:
+	release_slot_idx(cmd->ddev, cmd->slot_idx);
+	if (cmd->cu_idx == -EINVAL)
+		mark_cmd_submit_error(cmd);
+	return false;
+}
+
+/**
+ * ps_ert_ops: operations for ps scheduling
+ */
+static struct sched_ops ps_ert_ops = {
+	.submit = ps_ert_submit,
+	.query = ps_ert_query,
+};
+
+/**
+ * Only process ERT_START_COPYBO command.
+ * On MPSoC ARM64 platforms, the DMA engine is not a real HLS CU,
+ * thus the cmd->arg is not being used. We use it to preserve the
+ * filp.
+ */
+static bool
+zocl_execbuf_to_ert(struct drm_zocl_bo *bo, struct drm_file *filp)
+{
+	struct ert_start_copybo_cmd *scmd =
+	    (struct ert_start_copybo_cmd *)bo->cma_base.vaddr;
+
+	if (scmd->opcode != ERT_START_COPYBO)
+		return true;
+
+	if (!ZOCL_PLATFORM_ARM64) {
+		DRM_WARN("only support built-in copybo for ARM64");
+		return false;
+	}
+
+	/* preserve filp for looking up bo */
+	scmd->arg = filp;
+	return true;
+}
+
+/**
+ * zocl_dma_check() - Checks whether DMA can be performed or not
+ *
+ * @dev: Device node calling execbuf
+ * @bo: buffer objects from user space from which new command is created
+ *
+ */
+static bool
+zocl_dma_check(struct drm_device *dev, struct drm_zocl_bo *bo)
+{
+	uint64_t dst_paddr, src_paddr;
+	struct ert_start_copybo_cmd *cmd =
+	  (struct ert_start_copybo_cmd *)bo->cma_base.vaddr;
+	struct drm_file *filp = cmd->arg;
+	struct drm_zocl_copy_bo args = {
+	  .dst_handle = cmd->dst_bo_hdl,
+	  .src_handle = cmd->src_bo_hdl,
+	  .size = ert_copybo_size(cmd),
+	  .dst_offset = ert_copybo_dst_offset(cmd),
+	  .src_offset = ert_copybo_src_offset(cmd),
+	};
+
+	if (cmd->opcode != ERT_START_COPYBO)
+		return true;
+
+	return zocl_can_dma_performed(dev, filp, &args, &dst_paddr, &src_paddr);
+}
+
+/**
+ * zocl_execbuf_exec() - Entry point for exec buffer.
+ *
+ * @dev: Device node calling execbuf
+ * @data: Payload
+ * @filp:
+ *
+ * Function adds exec buffer to the pending list of commands
+ *
+ * Return: 0 on success, -errno otherwise
+ */
+int
+zocl_execbuf_exec(struct drm_device *dev, void *data, struct drm_file *filp)
+{
+	struct drm_gem_object *gem_obj;
+	struct drm_zocl_bo *zocl_bo;
+	struct drm_zocl_dev *zdev = dev->dev_private;
+	struct drm_zocl_execbuf *args = data;
+	struct sched_client_ctx *client;
+	int ret = 0;
+
+	SCHED_DEBUG("-> %s", __func__);
+	gem_obj = zocl_gem_object_lookup(dev, filp, args->exec_bo_handle);
+	if (!gem_obj) {
+		DRM_ERROR("Look up GEM BO %d failed\n", args->exec_bo_handle);
+		return -EINVAL;
+	}
+
+	zocl_bo = to_zocl_bo(gem_obj);
+	if (!zocl_bo_execbuf(zocl_bo) || !zocl_execbuf_to_ert(zocl_bo, filp)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* check whether dma can be perfomed or not */
+	if (!zocl_dma_check(dev, zocl_bo)) {
+		ZOCL_DRM_GEM_OBJECT_PUT_UNLOCKED(gem_obj);
+		return -EOPNOTSUPP;
+	}
+
+	/* TODO:
+	 * When we start validating CUs, make a client_validate function
+	 */
+	client = filp->driver_priv;
+	if (add_gem_bo_cmd(dev, zocl_bo, client)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	SCHED_DEBUG("<- %s", __func__);
+	return ret;
+
+out:
+	if (zdev->domain)
+		drm_gem_cma_free_object(&zocl_bo->gem_base);
+	else
+		drm_gem_cma_free_object(&zocl_bo->cma_base.base);
+	return ret;
+}
+
+struct ert_packet *
+get_next_packet(struct ert_packet *packet, unsigned int size)
+{
+	char *bytes = (char *)packet;
+
+	return (struct ert_packet *)(bytes+size);
+}
+
+void
+zocl_cmd_buffer_free(struct sched_cmd *cmd)
+{
+	SCHED_DEBUG("-> %s", __func__);
+	kfree(cmd->buffer);
+	SCHED_DEBUG("<- %s", __func__);
+}
+
+static unsigned int
+get_packet_size(struct ert_packet *packet)
+{
+	unsigned int payload;
+
+	SCHED_DEBUG("-> %s", __func__);
+	switch (packet->opcode) {
+
+	case ERT_CONFIGURE:
+		SCHED_DEBUG("configure cmd");
+		payload = 5 + packet->count;
+		break;
+
+	case ERT_SK_CONFIG:
+		SCHED_DEBUG("configure soft kernel cmd");
+		payload = packet->count;
+		break;
+
+	case ERT_SK_UNCONFIG:
+		SCHED_DEBUG("unconfigure soft kernel cmd");
+		payload = packet->count;
+		break;
+
+	case ERT_SK_START:
+		SCHED_DEBUG("start Soft CU/Kernel cmd");
+		payload = packet->count;
+		break;
+
+	case ERT_START_CU:
+	case ERT_EXEC_WRITE:
+		SCHED_DEBUG("start CU/Kernel cmd");
+		payload = packet->count;
+		break;
+
+	case ERT_EXIT:
+	case ERT_ABORT:
+		SCHED_DEBUG("abort or stop cmd");
+
+	default:
+		payload = 0;
+	}
+
+	SCHED_DEBUG("<- %s", __func__);
+	return 1 + payload;
+}
+
+/*
+ * add_ert_cq_cmd() - add a command by ERT command queue
+ *
+ * @ddev: drm device owning adding the buffer object
+ * @buffer: buffer
+ * @cq_idx: index of the CQ slot in BRAM
+ *
+ * Get a free scheduler command and initial it by gem buffer object.
+ * After all, add this command to pending list.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int
+add_ert_cq_cmd(struct drm_device *drm, void *buffer, unsigned int cq_idx)
+{
+	struct sched_cmd *cmd = get_free_sched_cmd();
+	struct drm_zocl_dev *zdev = drm->dev_private;
+	struct sched_exec_core *exec = zdev->exec;
+	int ret;
+
+	SCHED_DEBUG("-> %s", __func__);
+	cmd->ddev = drm;
+	cmd->sched = zdev->exec->scheduler;
+	cmd->buffer = buffer;
+	cmd->packet = buffer;
+	cmd->exec = zdev->exec;
+	cmd->cq_slot_idx = cq_idx;
+	cmd->free_buffer = zocl_cmd_buffer_free;
+
+	ret = add_cmd(cmd);
+	atomic_inc(&exec->scheduler->num_received);
+
+	SCHED_DEBUG("<- %s", __func__);
+	return ret;
+}
+
+/**
+ * create_cmd_buffer() - Create cmd command buffer of packet if state is NEW
+ *
+ * @packet:    Scheduler packet from ERT Command Queue
+ * @slot_size: slot_size
+ *
+ * Return: buffer pointer
+ */
+static void*
+create_cmd_buffer(struct ert_packet *packet, unsigned int slot_size)
+{
+	void *buffer;
+	size_t size;
+
+	if (packet->state != ERT_CMD_STATE_NEW)
+		return ERR_PTR(-EAGAIN);
+
+	packet->state = ERT_CMD_STATE_QUEUED;
+	SCHED_DEBUG("packet header 0x%8x, packet addr 0x%p slot size %d",
+		    packet->header, packet, slot_size);
+	buffer = kzalloc(slot_size, GFP_KERNEL);
+	if (!buffer)
+		return ERR_PTR(-ENOMEM);
+	/**
+	 * In 2018.2, CQ BRAM is used. Access PL by AXI lite is expense,
+	 * so copy packet to PS DDR. If host can directly submit command
+	 * to PS DDR, we don't need this copy.
+	 */
+	size = get_packet_size(packet) * sizeof(uint32_t);
+	memcpy_fromio(buffer, packet, size);
+	return buffer;
+}
+
+/**
+ * iterate_packets() - iterate packets in HW Command Queue
+ *
+ * @drm:  DRM device
+ *
+ * Return: 0: One iteration done
+ *	   1: Exit command...
+ *	   -errno: error number
+ */
+static int
+iterate_packets(struct drm_device *drm)
+{
+	struct drm_zocl_dev *zdev = drm->dev_private;
+	struct zocl_ert_dev *ert = zdev->ert;
+	struct sched_exec_core *exec_core = zdev->exec;
+	struct ert_packet *packet;
+	unsigned int slot_idx, num_slots, slot_sz;
+	void *buffer;
+	int ret;
+
+	packet = ert->cq_ioremap;
+	num_slots = exec_core->num_slots;
+	slot_sz = slot_size(zdev->ddev);
+
+	/* The first slot is ctrl slot in CQ.
+	 * It might has special command.
+	 */
+	if (packet->opcode == ERT_EXIT) {
+		packet->state = ERT_CMD_STATE_COMPLETED;
+		return 1;
+	}
+
+	for (slot_idx = 0; slot_idx < num_slots; slot_idx++) {
+		buffer = create_cmd_buffer(packet, slot_sz);
+		packet = get_next_packet(packet, slot_sz);
+		if (IS_ERR(buffer))
+			continue;
+
+		if (add_ert_cq_cmd(zdev->ddev, buffer, slot_idx)) {
+			ret = -EINVAL;
+			goto err;
+		}
+	}
+
+	return 0;
+err:
+	kfree(buffer);
+	return ret;
+}
+
+/**
+ * cq_check() - Check CQ status and submit new command to KDS
+ *
+ * @data: drm zocl device
+ *
+ * Iterate CQ BRAM for new command.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int
+cq_check(void *data)
+{
+	struct drm_zocl_dev *zdev = data;
+	struct sched_exec_core *exec_core = zdev->exec;
+
+	SCHED_DEBUG("-> %s", __func__);
+	while (!kthread_should_stop() && !exec_core->cq_interrupt) {
+		if (iterate_packets(zdev->ddev) == 1) {
+			/* This thread should exit */
+			exec_core->cq_thread = NULL;
+			break;
+		}
+		schedule();
+	}
+	SCHED_DEBUG("<- %s", __func__);
+	return 0;
+}
+
+static irqreturn_t sched_cq_isr(int irq, void *arg)
+{
+	struct drm_zocl_dev *zdev = arg;
+	struct ert_packet *pkg;
+	int slot_sz, slot_idx = 0;
+	int good_pkg;
+	void *buffer;
+
+	SCHED_DEBUG("-> %s", __func__);
+
+	good_pkg = 1;
+	slot_sz = slot_size(zdev->ddev);
+	pkg = zdev->ert->ops->get_next_cmd(zdev->ert, NULL, &slot_idx);
+	/* The first slot is ctrl slot in CQ.
+	 * It might has special command.
+	 */
+	if (slot_idx == 0 && pkg->opcode == ERT_EXIT) {
+		/* Exit command, do not response to CQ interrupt anymore */
+		disable_irq_nosync(irq);
+		pkg->state = ERT_CMD_STATE_COMPLETED;
+		goto out;
+	}
+
+	while (pkg) {
+		/* Usually, if the status of the pkg is not NEW. We think it is
+		 * not 'good' at this point.
+		 */
+		buffer = create_cmd_buffer(pkg, slot_sz);
+		if (IS_ERR(buffer))
+			good_pkg = 0;
+
+		if (good_pkg)
+			if (add_ert_cq_cmd(zdev->ddev, buffer, slot_idx))
+				kfree(buffer);
+
+		pkg = zdev->ert->ops->get_next_cmd(zdev->ert, pkg, &slot_idx);
+		/* No harm to assume the next pkg is good */
+		good_pkg = 1;
+	}
+
+out:
+	SCHED_DEBUG("<- %s", __func__);
+	return IRQ_HANDLED;
+}
+
+static inline void init_exec(struct sched_exec_core *exec_core)
+{
+	unsigned int i;
+
+	exec_core->scheduler = &g_sched0;
+	exec_core->num_slots = CQ_SLOT_NUM;
+	exec_core->num_cus = 0;
+	exec_core->cu_base_addr = 0;
+	exec_core->cu_shift_offset = 0;
+	exec_core->polling_mode = 1;
+	exec_core->cq_interrupt = 0;
+	exec_core->configured = 0;
+	atomic_set(&exec_core->scheduler->num_pending, 0);
+	atomic_set(&exec_core->scheduler->num_running, 0);
+	atomic_set(&exec_core->scheduler->num_received, 0);
+	atomic_set(&exec_core->scheduler->num_notified, 0);
+
+	exec_core->cu_isr = 0;
+	exec_core->cu_dma = 0;
+	exec_core->num_slot_masks = MAX_U32_SLOT_MASKS;
+	exec_core->num_cu_masks = 0;
+	exec_core->ops = &penguin_ops;
+
+	for (i = 0; i < MAX_SLOTS; ++i)
+		exec_core->submitted_cmds[i] = NULL;
+
+	for (i = 0; i < MAX_U32_SLOT_MASKS; ++i)
+		exec_core->slot_status[i] = 0;
+
+	for (i = 0; i < MAX_U32_CU_MASKS; ++i) {
+		exec_core->cu_status[i] = 0;
+		exec_core->cu_init[i] = 0;
+		exec_core->cu_valid[i] = 0; /* default value is invalid(0) */
+	}
+}
+
+/**
+ * sched_init_exec() - Initialize the command execution for device
+ *
+ * @drm: Device node to initialize
+ *
+ * Return: 0 on success, -errno otherwise
+ */
+int
+sched_init_exec(struct drm_device *drm)
+{
+	struct sched_exec_core *exec_core;
+	struct drm_zocl_dev *zdev = drm->dev_private;
+	unsigned int i;
+	char name[256] = "zocl-ert-thread";
+
+	SCHED_DEBUG("-> %s\n", __func__);
+
+	exec_core = devm_kzalloc(drm->dev, sizeof(*exec_core), GFP_KERNEL);
+	if (!exec_core) {
+		DRM_ERROR("Alloc exec_core failed: no memory\n");
+		return -ENOMEM;
+	}
+
+	zdev->exec = exec_core;
+	spin_lock_init(&exec_core->ctx_list_lock);
+	INIT_LIST_HEAD(&exec_core->ctx_list);
+	init_waitqueue_head(&exec_core->poll_wait_queue);
+
+	init_exec(exec_core);
+	init_scheduler_thread();
+
+	if (zdev->ert) {
+		for (i = 0; i < MAX_U32_CU_MASKS; ++i)
+			exec_core->scu_status[i] = 0;
+
+		/* Initialize soft kernel */
+		zocl_init_soft_kernel(drm);
+
+		exec_core->cq_thread = kthread_run(cq_check, zdev, name);
+	}
+
+	SCHED_DEBUG("<- %s\n", __func__);
+	return 0;
+}
+
+/*
+ * fini_configure() - clean up configure() specific data.
+ *    As a matter of fact, the configure() will potentially request_irq for
+ *    both KDS and ERT. The other configuration data can be easily reset to 0 or
+ *    initial value, but for requested interrupt resources, we should recycle
+ *    them by free_irq.
+ */
+static inline void
+fini_configure(struct drm_device *drm)
+{
+	struct drm_zocl_dev *zdev = drm->dev_private;
+	unsigned int i;
+
+	if (!(zdev->ert || zdev->exec->polling_mode)) {
+		for (i = 0; i < zdev->exec->num_cus; i++) {
+			if (zocl_cu_is_valid(zdev->exec, i)) {
+				kfree(zdev->exec->zcu[i].irq_name);
+				free_irq(zdev->exec->zcu[i].irq, zdev);
+			}
+		}
+	}
+
+	if (zdev->exec->cq_interrupt)
+		free_irq(zdev->ert->irq[ERT_CQ_IRQ], zdev);
+
+	zocl_cu_reclaim(zdev);
+}
+
+/**
+ * sched_fini_exec() - Finalize the command execution for device
+ *
+ * @xdev: Device node to finalize
+ *
+ * Return: 0 on success, -errno otherwise
+ */
+int sched_fini_exec(struct drm_device *drm)
+{
+	struct drm_zocl_dev *zdev = drm->dev_private;
+
+	SCHED_DEBUG("-> %s\n", __func__);
+
+	fini_configure(drm);
+
+	if (zdev->exec->cq_thread)
+		kthread_stop(zdev->exec->cq_thread);
+
+	if (zdev->ert)
+		zocl_fini_soft_kernel(drm);
+
+	fini_scheduler_thread();
+	zocl_cleanup_cu_timer(zdev);
+	SCHED_DEBUG("<- %s\n", __func__);
+
+	return 0;
+}
+
+/*
+ * A simplified version of reset scheduler. This is to support DFX on
+ * Hybrid-platform which is running in ert mode. All the context and
+ * command draining are managed by host side XRT.
+ */
+int
+sched_reset_scheduler(struct drm_device *drm)
+{
+	struct drm_zocl_dev *zdev = drm->dev_private;
+	struct sched_exec_core *exec = zdev->exec;
+
+	DRM_INFO("%s: stop scheduler", __func__);
+
+	/* Once stopped, keep this status until reset done */
+	atomic_set(&exec->exec_status, ZOCL_EXEC_STOP);
+
+	fini_configure(drm);
+	init_exec(exec);
+
+	/* start receiving cmds */
+	atomic_set(&exec->exec_status, ZOCL_EXEC_NORMAL);
+
+	return 0;
+}
+
+/*
+ * Block comment for the resetting theory.
+ *
+ * Note:
+ *   1) Run as a transaction:
+ *      Done or rollback to original config.
+ *   2) Can retry:
+ *      Suppose user understands switching xclbin depends on previous
+ *      xclbin is not being used. Some stale cmds might not be drained safely
+ *      in XRT, it is safter to check if hardware is hung too. For example:
+ *      if hls cu status is 0x1, we don't know if this is going to be
+ *      finished. In the future, once hls cu reset is fully supported, we
+ *      might consider enabling CU reset to accelate the procedure of
+ *      draining running CUs.
+ *
+ * Reset stages:
+ *   Stage 1: stop scheduler, no more new cmds. Wait for existing cmds
+ *            to be drained.
+ *   Stage 2: flush scheduler (see cmd_update_state),
+ *         2.1: any pending cmds should be set to abort.
+ *         2.2: any running cmds should be set to:
+ *           2.2.1: abort when cu idx is -1.
+ *           2.2.2: abort cu status is not ap_start.
+ *           2.2.3: retry running cu for certain time.
+ *              if still running, return EBUSY.
+ *              if completed, continue.
+ *         3: fini, init scheduler
+ *         4: start scheduler, accept adding cmds
+ */
+int
+sched_reset_exec(struct drm_device *drm)
+{
+	struct drm_zocl_dev *zdev = drm->dev_private;
+	struct sched_exec_core *exec = zdev->exec;
+	int wait_ms = 100;
+	int retry = 20;
+	int outstanding = 0;
+
+	DRM_INFO("%s: stop scheduler", __func__);
+
+	/* Once stopped, keep this status until reset done */
+	atomic_set(&exec->exec_status, ZOCL_EXEC_STOP);
+
+	outstanding = atomic_read(&exec->scheduler->num_pending);
+	while (retry-- && outstanding) {
+		DRM_INFO("Wait for (%d) pending cmds to finish", outstanding);
+		msleep(wait_ms);
+		outstanding = atomic_read(&exec->scheduler->num_pending);
+	}
+
+	retry = 20;
+	outstanding = atomic_read(&exec->scheduler->num_running);
+	while (retry-- && outstanding) {
+		DRM_INFO("Wait for (%d) pending cmds to finish", outstanding);
+		msleep(wait_ms);
+		outstanding = atomic_read(&exec->scheduler->num_running);
+	}
+
+	/*
+	 * Set scheduler to flash status, so that abormal cmds will be
+	 * aborted. If there are still outstanding commands, return EBUSY.
+	 * User should deal with potential hung or long time running CUs.
+	 */
+	if (atomic_read(&exec->scheduler->num_pending) || atomic_read(&exec->scheduler->num_running)) {
+		atomic_set(&exec->exec_status, ZOCL_EXEC_FLUSH);
+		msleep(1000); /* wait a second */
+	}
+
+	if (atomic_read(&exec->scheduler->num_pending) || atomic_read(&exec->scheduler->num_running)) {
+		/* set back to normal, user can retry next time */
+		DRM_WARN("Still have pending(%d), running(%d) cmds",
+		    atomic_read(&exec->scheduler->num_pending), atomic_read(&exec->scheduler->num_running));
+		atomic_set(&exec->exec_status, ZOCL_EXEC_NORMAL);
+		return -EBUSY;
+	}
+
+	/*
+	 * When scheduler is stopped, reset exec_core.
+	 * 1) cleanup additional irqs from configure
+	 * 2) reset exec initial value
+	 *
+	 * Note: no need to check stale commands, becuase we return EBUSY above
+	 * for this condition.
+	 */
+	fini_configure(drm);
+	init_exec(exec);
+	/* start receiving cmds */
+	atomic_set(&exec->exec_status, ZOCL_EXEC_NORMAL);
+	return 0;
+}
+
+u32
+sched_is_busy(struct drm_zocl_dev *zdev)
+{
+	struct sched_exec_core *exec = zdev->exec;
+	return (atomic_read(&exec->scheduler->num_pending) + atomic_read(&exec->scheduler->num_running));
+}
+
+int sched_attach_cu(struct drm_zocl_dev *zdev, int cu_idx)
+{
+	struct sched_exec_core *exec = zdev->exec;
+	int ret;
+
+	if (cu_idx >= exec->num_cus)
+		return -EINVAL;
+
+	/* CU health check? */
+	zocl_cu_set_valid(exec, cu_idx);
+
+	if (exec->polling_mode)
+		return 0;
+
+	exec->zcu[cu_idx].irq_name = kzalloc(20, GFP_KERNEL);
+	sprintf(exec->zcu[cu_idx].irq_name, "zocl_cu[%d]", cu_idx);
+	ret = request_irq(exec->zcu[cu_idx].irq, sched_exec_isr, 0,
+			  exec->zcu[cu_idx].irq_name, zdev);
+
+	return ret;
+}
+
+int sched_detach_cu(struct drm_zocl_dev *zdev, int cu_idx)
+{
+	struct sched_exec_core *exec = zdev->exec;
+	int cu_mask;
+	int cu_bit;
+
+	WARN_ON(cu_idx >= exec->num_cus);
+	if (cu_idx >= exec->num_cus)
+		return -EINVAL;
+
+	cu_mask = cu_mask_idx(cu_idx);
+	cu_bit = cu_idx_in_mask(cu_idx);
+	if (exec->cu_status[cu_mask] & (1 << cu_bit))
+		return -EBUSY;
+
+	if (exec->polling_mode)
+		goto invalid_cu;
+
+	if (zocl_cu_is_valid(exec, cu_idx)) {
+		kfree(exec->zcu[cu_idx].irq_name);
+		free_irq(exec->zcu[cu_idx].irq, zdev);
+	}
+
+	DRM_DEBUG("%s: detached CU[%d] and irq %d\n", __func__,
+		  cu_idx, exec->zcu[cu_idx].irq);
+
+invalid_cu:
+	zocl_cu_set_invalid(exec, cu_idx);
+
+	return 0;
+}
+
+/*
+ * Return number of client with open ("live") contexts on CUs.
+ * If this number > 0, xclbin is locked down.
+ * If plist is non-NULL, the list of PIDs of live clients will also be
+ * returned.
+ * Note that plist should be freed by caller.
+ */
+u32
+sched_live_clients(struct drm_zocl_dev *zdev, pid_t **plist)
+{
+	const struct list_head *ptr;
+	const struct sched_client_ctx *entry;
+	uint count = 0;
+	u32 i = 0;
+	pid_t *pl = NULL;
+
+	/* Find out number of active client */
+	list_for_each(ptr, &zdev->exec->ctx_list) {
+		entry = list_entry(ptr, struct sched_client_ctx, link);
+		if (CLIENT_NUM_CU_CTX(entry) > 0)
+			count++;
+	}
+	if (count == 0 || plist == NULL)
+		goto out;
+
+	/* Collect list of PIDs of active client */
+	pl = vmalloc(sizeof(pid_t) * count);
+	if (pl == NULL)
+		goto out;
+
+	list_for_each(ptr, &zdev->exec->ctx_list) {
+		entry = list_entry(ptr, struct sched_client_ctx, link);
+		if (CLIENT_NUM_CU_CTX(entry) > 0) {
+			pl[i] = pid_nr(entry->pid);
+			i++;
+		}
+	}
+
+	*plist = pl;
+
+out:
+	return count;
+}
+
+void zocl_track_ctx(struct drm_device *dev, struct sched_client_ctx *fpriv)
+{
+	unsigned long flags;
+	struct drm_zocl_dev *zdev = dev->dev_private;
+
+	spin_lock_irqsave(&zdev->exec->ctx_list_lock, flags);
+	list_add_tail(&fpriv->link, &zdev->exec->ctx_list);
+	spin_unlock_irqrestore(&zdev->exec->ctx_list_lock, flags);
+}
+
+void zocl_untrack_ctx(struct drm_device *dev, struct sched_client_ctx *fpriv)
+{
+	unsigned long flags;
+	struct drm_zocl_dev *zdev = dev->dev_private;
+
+	spin_lock_irqsave(&zdev->exec->ctx_list_lock, flags);
+	list_del(&fpriv->link);
+	spin_unlock_irqrestore(&zdev->exec->ctx_list_lock, flags);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/zocl_aie.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/zocl_aie.c
@@ -0,0 +1,518 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * A GEM style (optionally CMA backed) device manager for ZynQ based
+ * OpenCL accelerators.
+ *
+ * Copyright (C) 2020 Xilinx, Inc. All rights reserved.
+ *
+ * Authors:
+ *    Larry Liu <yliu@xilinc.com>
+ *    Himanshu Choudhary <hchoudha@xilinx.com>
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#include "zocl_drv.h"
+#include "zocl_aie.h"
+#include "xrt_xclbin.h"
+#include "xclbin.h"
+
+#ifndef __NONE_PETALINUX__
+#include <linux/xlnx-ai-engine.h>
+#endif
+
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+
+static inline u8
+get_error_module(enum aie_module_type aie_module) {
+	switch (aie_module) {
+	case AIE_MEM_MOD:
+		return XRT_ERROR_MODULE_AIE_MEMORY;
+	case AIE_CORE_MOD:
+		return XRT_ERROR_MODULE_AIE_CORE;
+	case AIE_PL_MOD:
+		return XRT_ERROR_MODULE_AIE_PL;
+	case AIE_NOC_MOD:
+		return XRT_ERROR_MODULE_AIE_NOC;
+	default:
+		return XRT_ERROR_MODULE_UNKNOWN;
+	}
+}
+
+static inline u8
+get_error_num(u8 aie_category) {
+	switch (aie_category) {
+	case AIE_ERROR_CATEGORY_SATURATION:
+		return XRT_ERROR_NUM_AIE_SATURATION;
+	case AIE_ERROR_CATEGORY_FP:
+		return XRT_ERROR_NUM_AIE_FP;
+	case AIE_ERROR_CATEGORY_STREAM:
+		return XRT_ERROR_NUM_AIE_STREAM;
+	case AIE_ERROR_CATEGORY_ACCESS:
+		return XRT_ERROR_NUM_AIE_ACCESS;
+	case AIE_ERROR_CATEGORY_BUS:
+		return XRT_ERROR_NUM_AIE_BUS;
+	case AIE_ERROR_CATEGORY_INSTRUCTION:
+		return XRT_ERROR_NUM_AIE_INSTRUCTION;
+	case AIE_ERROR_CATEGORY_ECC:
+		return XRT_ERROR_NUM_AIE_ECC;
+	case AIE_ERROR_CATEGORY_LOCK:
+		return XRT_ERROR_NUM_AIE_LOCK;
+	case AIE_ERROR_CATEGORY_DMA:
+		return XRT_ERROR_NUM_AIE_DMA;
+	case AIE_ERROR_CATEGORY_MEM_PARITY:
+		return XRT_ERROR_NUM_AIE_MEM_PARITY;
+	default:
+		return XRT_ERROR_NUM_UNKNOWN;
+	}
+}
+
+static int
+zocl_aie_cache_error(struct aie_error_cache *zerr, struct aie_error *err)
+{
+	struct aie_error *temp;
+
+	/* If the current error cache is full, double the cache size */
+	if (zerr->num == zerr->cap) {
+		temp = vzalloc(sizeof (struct aie_error) * zerr->cap * 2);
+		if (!temp)
+			return -ENOMEM;
+
+		memcpy(temp, zerr->errors, sizeof (struct aie_error) *
+		    zerr->num);
+		zerr->cap *= 2;
+		vfree(zerr->errors);
+		zerr->errors = temp;
+	}
+
+	zerr->errors[zerr->num].error_id = err->error_id;
+	zerr->errors[zerr->num].module = err->module;
+	zerr->errors[zerr->num].loc.col = err->loc.col;
+	zerr->errors[zerr->num].loc.row = err->loc.row;
+	zerr->num++;
+
+	return 0;
+}
+
+static bool
+is_cached_error(struct aie_error_cache *zerr, struct aie_error *err)
+{
+	int i;
+
+	for (i = 0; i < zerr->num; i++) {
+		if (zerr->errors[i].error_id == err->error_id &&
+		    zerr->errors[i].category == err->category &&
+		    zerr->errors[i].module == err->module &&
+		    zerr->errors[i].loc.col == err->loc.col &&
+		    zerr->errors[i].loc.row == err->loc.row)
+			break;
+	}
+
+	return i < zerr->num ? true : false;
+}
+
+static void
+zocl_aie_error_cb(void *arg)
+{
+	struct drm_zocl_dev *zdev = arg;
+	struct aie_errors *errors;
+	int i;
+
+	if (!zdev) {
+		DRM_WARN("%s: zdev is not initialized\n", __func__);
+		return;
+	}
+
+	mutex_lock(&zdev->aie_lock);
+	if (!zdev->aie) {
+		DRM_WARN("%s: AIE image is not loaded.\n", __func__);
+		mutex_unlock(&zdev->aie_lock);
+		return;
+	}
+
+	if (!zdev->aie->aie_dev) {
+		DRM_WARN("%s: No available AIE partition.\n", __func__);
+		mutex_unlock(&zdev->aie_lock);
+		return;
+	}
+
+	errors = aie_get_errors(zdev->aie->aie_dev);
+	if (IS_ERR(errors)) {
+		DRM_WARN("%s: aie_get_errors failed\n", __func__);
+		mutex_unlock(&zdev->aie_lock);
+		return;
+	}
+
+	for (i = 0; i < errors->num_err; i++) {
+		xrtErrorCode err_code;
+
+		DRM_INFO("Get AIE asynchronous Error: "
+		    "error_id %d Mod %d, category %d, Col %d, Row %d\n",
+		    errors->errors[i].error_id,
+		    errors->errors[i].module,
+		    errors->errors[i].category,
+		    errors->errors[i].loc.col,
+		    errors->errors[i].loc.row
+		    );
+
+		if (is_cached_error(&zdev->aie->err, &((errors->errors)[i])))
+			continue;
+
+		err_code = XRT_ERROR_CODE_BUILD(
+		    get_error_num(errors->errors[i].category),
+		    XRT_ERROR_DRIVER_AIE,
+		    XRT_ERROR_SEVERITY_CRITICAL,
+		    get_error_module(errors->errors[i].module),
+		    XRT_ERROR_CLASS_AIE
+		    );
+
+		zocl_insert_error_record(zdev, err_code);
+		zocl_aie_cache_error(&zdev->aie->err, &((errors->errors)[i]));
+	}
+
+	aie_free_errors(errors);
+
+	mutex_unlock(&zdev->aie_lock);
+}
+
+int
+zocl_aie_request_part_fd(struct drm_zocl_dev *zdev, void *data)
+{
+	struct drm_zocl_aie_fd *args = data;
+	int fd;
+	int rval = 0;
+
+	mutex_lock(&zdev->aie_lock);
+
+	if (!zdev->aie) {
+		DRM_ERROR("AIE image is not loaded.\n");
+		rval = -ENODEV;
+		goto done;
+	}
+
+	if (!zdev->aie->aie_dev) {
+		DRM_ERROR("No available AIE partition.\n");
+		rval = -ENODEV;
+		goto done;
+	}
+
+	if (zdev->aie->partition_id != args->partition_id) {
+		DRM_ERROR("AIE partition %d does not exist.\n",
+		    args->partition_id);
+		rval = -ENODEV;
+		goto done;
+	}
+
+	fd = aie_partition_get_fd(zdev->aie->aie_dev);
+	if (fd < 0) {
+		DRM_ERROR("Get AIE partition %d fd: %d\n",
+		    args->partition_id, fd);
+		rval = fd;
+		goto done;
+	}
+
+	args->fd = fd;
+
+	zdev->aie->fd_cnt++;
+
+done:
+	mutex_unlock(&zdev->aie_lock);
+
+	return rval;
+}
+
+int
+zocl_create_aie(struct drm_zocl_dev *zdev, struct axlf *axlf)
+{
+	uint64_t offset;
+	uint64_t size;
+	struct aie_partition_req req;
+	int rval = 0;
+
+	rval = xrt_xclbin_section_info(axlf, AIE_METADATA, &offset, &size);
+	if (rval)
+		return rval;
+
+	mutex_lock(&zdev->aie_lock);
+
+	/* AIE is reset and no PDI is loaded after reset */
+	if (zdev->aie && zdev->aie->aie_reset) {
+		rval = -ENODEV;
+		DRM_ERROR("PDI is not loaded after AIE reset.\n");
+		goto done;
+	}
+
+	if (!zdev->aie) {
+		zdev->aie = vzalloc(sizeof (struct zocl_aie));
+		if (!zdev->aie) {
+			rval = -ENOMEM;
+			DRM_ERROR("Fail to allocate memory.\n");
+			goto done;
+		}
+
+		zdev->aie->err.errors = vzalloc(sizeof (struct aie_error) *
+		    ZOCL_AIE_ERROR_CACHE_CAP);
+		if (!zdev->aie->err.errors) {
+			rval = -ENOMEM;
+			vfree(zdev->aie);
+			DRM_ERROR("Fail to allocate memory.\n");
+			goto done;
+		}
+
+		zdev->aie->err.num = 0;
+		zdev->aie->err.cap = ZOCL_AIE_ERROR_CACHE_CAP;
+
+	}
+
+	if (!zdev->aie->wq) {
+		zdev->aie->wq = create_singlethread_workqueue("aie-workq");
+		if (!zdev->aie->wq) {
+			rval = -ENOMEM;
+			DRM_ERROR("Fail to create work queue.\n");
+			goto done;
+		}
+	}
+
+	/* TODO figure out the partition id and uid from xclbin or PDI */
+	req.partition_id = 1;
+	req.uid = 0;
+
+	if (zdev->aie->aie_dev) {
+		DRM_INFO("Partition %d already requested\n",
+		    req.partition_id);
+		goto done;
+	}
+
+	zdev->aie->aie_dev = aie_partition_request(&req);
+
+	if (IS_ERR(zdev->aie->aie_dev)) {
+		rval = PTR_ERR(zdev->aie->aie_dev);
+		DRM_ERROR("Request AIE partition %d, %d\n",
+		    req.partition_id, rval);
+		goto done;
+	}
+
+	zdev->aie->partition_id = req.partition_id;
+	zdev->aie->uid = req.uid;
+
+	/* Register AIE error call back function. */
+	rval = aie_register_error_notification(zdev->aie->aie_dev,
+	    zocl_aie_error_cb, zdev);
+
+	mutex_unlock(&zdev->aie_lock);
+
+	zocl_init_aie(zdev);
+
+	return 0;
+
+done:
+	mutex_unlock(&zdev->aie_lock);
+
+	return rval;
+}
+
+void
+zocl_destroy_aie(struct drm_zocl_dev *zdev)
+{
+	vfree(zdev->aie_information);
+	mutex_lock(&zdev->aie_lock);
+
+	if (!zdev->aie) {
+		mutex_unlock(&zdev->aie_lock);
+		return;
+	}
+
+	if (zdev->aie->aie_dev)
+		aie_partition_release(zdev->aie->aie_dev);
+
+	if (zdev->aie->wq)
+		destroy_workqueue(zdev->aie->wq);
+
+	vfree(zdev->aie->err.errors);
+	vfree(zdev->aie);
+	zdev->aie = NULL;
+	mutex_unlock(&zdev->aie_lock);
+}
+
+static void
+zocl_aie_reset_work(struct work_struct *aie_work)
+{
+	struct aie_work_data *data = container_of(aie_work,
+	    struct aie_work_data, work);
+	struct drm_zocl_dev *zdev= data->zdev;
+	int i;
+
+	/*
+	 * Note: we can not hold lock here because this
+	 *       work thread is invoked within a lock and
+	 *       that lock will not be relased until the
+	 *       work is flushed.
+	 */
+
+	/*
+	 * Reset AIE by releasing AIE partition. The times we
+	 * release AIE partition is based on the # of fd is
+	 * requested + 1.
+	 */
+	for (i = 0; i < zdev->aie->fd_cnt + 1; i++)
+		aie_partition_release(zdev->aie->aie_dev);
+
+	zdev->aie->fd_cnt = 0;
+}
+
+int
+zocl_aie_reset(struct drm_zocl_dev *zdev)
+{
+	struct aie_partition_req req;
+	bool aie_available = false;
+	struct aie_work_data *data;
+	int count;
+
+	mutex_lock(&zdev->aie_lock);
+
+	if (!zdev->aie) {
+		mutex_unlock(&zdev->aie_lock);
+		DRM_ERROR("AIE image is not loaded.\n");
+		return -ENODEV;
+	}
+
+	if (!zdev->aie->aie_dev) {
+		mutex_unlock(&zdev->aie_lock);
+		DRM_ERROR("No available AIE partition.\n");
+		return -ENODEV;
+	}
+
+	data = kmalloc(sizeof(struct aie_work_data), GFP_KERNEL);
+	if (!data) {
+		mutex_unlock(&zdev->aie_lock);
+		DRM_ERROR("Can not allocate memory,\n");
+		return -ENOMEM;
+	}
+	data->zdev = zdev;
+
+	/*
+	 * Per the requrirement of current AIE driver, we
+	 * need to release the partition in a separate thread.
+	 */
+	INIT_WORK(&data->work, zocl_aie_reset_work);
+	queue_work(zdev->aie->wq, &data->work);
+
+	/* Make sure the reset thread is done */
+	flush_workqueue(zdev->aie->wq);
+	kfree(data);
+
+	req.partition_id = zdev->aie->partition_id;
+	req.uid = zdev->aie->uid;
+
+	/* Check if AIE partition is available in a given time */
+	count = 0;
+	while (1) {
+		aie_available = aie_partition_is_available(&req);
+		if (aie_available)
+			break;
+		count++;
+		if (count == ZOCL_AIE_RESET_TIMEOUT_NUMBER) {
+			mutex_unlock(&zdev->aie_lock);
+			DRM_ERROR("AIE Reset fail: timeout.");
+			return -ETIME;
+		}
+		msleep(ZOCL_AIE_RESET_TIMEOUT_INTERVAL);
+	}
+
+	zdev->aie->aie_dev = NULL;
+	zdev->aie->aie_reset = true;
+	zdev->aie->err.num = 0;
+
+	mutex_unlock(&zdev->aie_lock);
+
+	return 0;
+}
+
+int
+zocl_aie_getcmd_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
+{
+	int ret;
+	struct drm_zocl_dev *zdev = dev->dev_private;
+	struct aie_info *aie = zdev->aie_information;
+	struct aie_info_cmd *acmd;
+	struct drm_zocl_aie_cmd *kdata = data;
+
+	if(aie == NULL)
+		return -EAGAIN;
+
+	/* If no command, the process who calls this ioctl will block here */
+	mutex_lock(&aie->aie_lock);
+	while (list_empty(&aie->aie_cmd_list)) {
+		mutex_unlock(&aie->aie_lock);
+		/* 
+ 		 * Return greater than 0 if condition true before timeout,
+ 		 * 0 when time out, else -ERESTARTSYS.
+ 		 */
+		ret = wait_event_interruptible_timeout(aie->aie_wait_queue,
+		    !list_empty(&aie->aie_cmd_list), msecs_to_jiffies(500));
+		if (ret <= 0) {
+			return -ERESTARTSYS;
+                }
+		mutex_lock(&aie->aie_lock);
+	}
+
+	acmd = list_first_entry(&aie->aie_cmd_list, struct aie_info_cmd,
+	    aiec_list);
+	list_del(&acmd->aiec_list);
+
+	/* Only one aied thread */
+	aie->cmd_inprogress = acmd;
+	mutex_unlock(&aie->aie_lock);
+
+	kdata->opcode = acmd->aiec_packet->opcode;
+
+	return 0;
+}
+int
+zocl_aie_putcmd_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
+{
+	struct drm_zocl_dev *zdev = dev->dev_private;
+	struct aie_info *aie = zdev->aie_information;
+	struct aie_info_cmd *acmd;
+	struct drm_zocl_aie_cmd *kdata = data;
+	struct aie_info_packet *cmd;
+
+	if(aie == NULL)
+		return -EAGAIN;
+
+	mutex_lock(&aie->aie_lock);
+	acmd = aie->cmd_inprogress;
+	mutex_unlock(&aie->aie_lock);
+	if (!acmd) {
+		return -ENOMEM;
+	}
+
+	cmd = acmd->aiec_packet;
+	cmd->size = (kdata->size < AIE_INFO_SIZE) ? kdata->size : AIE_INFO_SIZE;
+	snprintf(cmd->info, cmd->size, "%s", (char *)kdata->info);
+
+	up(&acmd->aiec_sem);
+
+	return 0;
+}
+
+int
+zocl_init_aie(struct drm_zocl_dev *zdev)
+{
+	struct aie_info *aie;
+	aie = vzalloc(sizeof(struct aie_info));
+	if (!aie) {
+		zdev->aie_information = NULL;
+		return -ENOMEM;
+	}
+
+	mutex_init(&aie->aie_lock);
+	INIT_LIST_HEAD(&aie->aie_cmd_list);
+	init_waitqueue_head(&aie->aie_wait_queue);
+	aie->cmd_inprogress = NULL;
+	zdev->aie_information = aie;
+
+	return 0;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/zocl_bo.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/zocl_bo.c
@@ -0,0 +1,988 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * A GEM style (optionally CMA backed) device manager for ZynQ based
+ * OpenCL accelerators.
+ *
+ * Copyright (C) 2016-2020 Xilinx, Inc. All rights reserved.
+ *
+ * Authors:
+ *    Sonal Santan <sonal.santan@xilinx.com>
+ *    Umang Parekh <umang.parekh@xilinx.com>
+ *    Jan Stephan  <j.stephan@hzdr.de>
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#include <linux/pagemap.h>
+#include <linux/iommu.h>
+#include <asm/io.h>
+#include "xrt_drv.h"
+#include "zocl_drv.h"
+#include "xclbin.h"
+#include "zocl_bo.h"
+
+static inline void __user *to_user_ptr(u64 address)
+{
+	return (void __user *)(uintptr_t)address;
+}
+
+void zocl_describe(const struct drm_zocl_bo *obj)
+{
+	size_t size_in_kb = obj->cma_base.base.size / 1024;
+	size_t physical_addr = obj->cma_base.paddr;
+
+	DRM_DEBUG("%px: H[0x%zxKB] D[0x%zx]\n",
+			obj,
+			size_in_kb,
+			physical_addr);
+}
+
+static inline void
+zocl_bo_describe(const struct drm_zocl_bo *bo, uint64_t *size, uint64_t *paddr)
+{
+	if (bo->flags & (ZOCL_BO_FLAGS_CMA | ZOCL_BO_FLAGS_USERPTR)) {
+		*size = (uint64_t)bo->cma_base.base.size;
+		*paddr = (uint64_t)bo->cma_base.paddr;
+	} else {
+		*size = (uint64_t)bo->gem_base.size;
+		*paddr = (uint64_t)bo->mm_node->start;
+	}
+}
+
+int zocl_iommu_map_bo(struct drm_device *dev, struct drm_zocl_bo *bo)
+{
+	int prot = IOMMU_READ | IOMMU_WRITE;
+	struct drm_zocl_dev *zdev = dev->dev_private;
+	size_t bo_size = bo->gem_base.size;
+	ssize_t err;
+
+	/* Create scatter gather list from user's pages */
+	bo->sgt = drm_prime_pages_to_sg(bo->pages, bo_size >> PAGE_SHIFT);
+	if (IS_ERR(bo->sgt)) {
+		bo->uaddr = 0;
+		return PTR_ERR(bo->sgt);
+	}
+
+	/* MAP user's VA to pages table into IOMMU */
+	err = iommu_map_sg(zdev->domain, bo->uaddr, bo->sgt->sgl,
+			bo->sgt->nents, prot);
+	if (err < 0) {
+		/* If IOMMU map failed forget user's VA */
+		bo->uaddr = 0;
+		DRM_ERROR("Failed to map buffer through IOMMU: %zd\n", err);
+		return err;
+	}
+	return 0;
+}
+
+int zocl_iommu_unmap_bo(struct drm_device *dev, struct drm_zocl_bo *bo)
+{
+	struct drm_zocl_dev *zdev = dev->dev_private;
+	/* If IOMMU map had failed before bo->uaddr will be zero */
+	if (bo->uaddr)
+		iommu_unmap(zdev->domain, bo->uaddr, bo->gem_base.size);
+	return 0;
+}
+
+static struct drm_zocl_bo *zocl_create_userprt_bo(struct drm_device *dev,
+		uint64_t unaligned_size)
+{
+	size_t size = PAGE_ALIGN(unaligned_size);
+	struct drm_gem_cma_object *cma_obj;
+	int err = 0;
+
+	if (!size)
+		return ERR_PTR(-EINVAL);
+
+	cma_obj = kzalloc(sizeof(*cma_obj), GFP_KERNEL);
+	if (!cma_obj) {
+		DRM_DEBUG("cma object create failed\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	err = drm_gem_object_init(dev, &cma_obj->base, size);
+	if (err) {
+		DRM_DEBUG("drm gem object initial failed\n");
+		goto out1;
+	}
+
+	cma_obj->sgt   = NULL;
+	cma_obj->vaddr = NULL;
+	cma_obj->paddr = 0x0;
+
+	return to_zocl_bo(&cma_obj->base);
+out1:
+	kfree(cma_obj);
+	return NULL;
+}
+
+void zocl_free_userptr_bo(struct drm_gem_object *gem_obj)
+{
+	/* Do all drm_gem_cma_free_object(bo->base) do, execpt free vaddr */
+	struct drm_zocl_bo *zocl_bo = to_zocl_bo(gem_obj);
+
+	DRM_DEBUG("%s: obj 0x%px", __func__, zocl_bo);
+	if (zocl_bo->cma_base.sgt)
+		sg_free_table(zocl_bo->cma_base.sgt);
+
+	drm_gem_object_release(gem_obj);
+
+	kfree(&zocl_bo->cma_base);
+}
+
+static struct drm_zocl_bo *
+zocl_create_bo(struct drm_device *dev, uint64_t unaligned_size, u32 user_flags)
+{
+	size_t size = PAGE_ALIGN(unaligned_size);
+	struct drm_zocl_dev *zdev = dev->dev_private;
+	struct drm_gem_cma_object *cma_obj;
+	struct drm_zocl_bo *bo;
+	int err;
+
+	if (!size)
+		return ERR_PTR(-EINVAL);
+
+	if (zdev->domain) {
+		bo = kzalloc(sizeof(*bo), GFP_KERNEL);
+		if (!bo)
+			return ERR_PTR(-ENOMEM);
+
+		err = drm_gem_object_init(dev, &bo->gem_base, size);
+		if (err < 0)
+			goto free;
+	} else if (user_flags & ZOCL_BO_FLAGS_CMA) {
+		/* Allocate from CMA buffer */
+		cma_obj = drm_gem_cma_create(dev, size);
+		if (IS_ERR(cma_obj))
+			return ERR_PTR(-ENOMEM);
+
+		bo = to_zocl_bo(&cma_obj->base);
+	} else {
+		/* We are allocating from a separate BANK, i.e. PL-DDR or LPDDR */
+		unsigned int bank = GET_MEM_BANK(user_flags);
+
+		if (bank >= zdev->num_mem || !zdev->mem[bank].zm_used ||
+		    zdev->mem[bank].zm_type != ZOCL_MEM_TYPE_PL_LP_DDR)
+			return ERR_PTR(-EINVAL);
+
+		bo = kzalloc(sizeof(struct drm_zocl_bo), GFP_KERNEL);
+		if (IS_ERR(bo))
+			return ERR_PTR(-ENOMEM);
+
+		err = drm_gem_object_init(dev, &bo->gem_base, size);
+		if (err) {
+			kfree(bo);
+			return ERR_PTR(err);
+		}
+
+		bo->mm_node = kzalloc(sizeof(struct drm_mm_node),
+		    GFP_KERNEL);
+		if (IS_ERR(bo->mm_node)) {
+			kfree(bo);
+			return ERR_PTR(-ENOMEM);
+		}
+
+		mutex_lock(&zdev->mm_lock);
+		err = drm_mm_insert_node_generic(zdev->mem[bank].zm_mm,
+		    bo->mm_node, size, PAGE_SIZE, 0, 0);
+		if (err) {
+			DRM_ERROR("Fail to allocate BO: size %ld\n",
+			    (long)size);
+			mutex_unlock(&zdev->mm_lock);
+			kfree(bo->mm_node);
+			kfree(bo);
+			return ERR_PTR(-ENOMEM);
+		}
+		mutex_unlock(&zdev->mm_lock);
+
+		/*
+		 * Set up a kernel mapping for direct BO access.
+		 * We don't have to fail BO allocation if we can
+		 * not establish the kernel mapping. We just can not
+		 * access BO directly from kernel.
+		 */
+		bo->vmapping = memremap(bo->mm_node->start, size, MEMREMAP_WC);
+
+		err = drm_gem_create_mmap_offset(&bo->gem_base);
+		if (err) {
+			DRM_ERROR("Fail to create BO mmap offset.\n");
+			zocl_free_bo(&bo->gem_base);
+			return ERR_PTR(err);
+		}
+	}
+
+	if (user_flags & ZOCL_BO_FLAGS_EXECBUF) {
+		bo->flags = ZOCL_BO_FLAGS_EXECBUF;
+		bo->metadata.state = DRM_ZOCL_EXECBUF_STATE_ABORT;
+	}
+
+	return bo;
+free:
+	kfree(bo);
+	return ERR_PTR(err);
+}
+
+int
+zocl_create_svm_bo(struct drm_device *dev, void *data, struct drm_file *filp)
+{
+	struct drm_zocl_create_bo *args = data;
+	struct drm_zocl_bo *bo;
+	size_t bo_size;
+	int ret = 0;
+
+	if ((args->flags & ZOCL_BO_FLAGS_COHERENT) ||
+			(args->flags & ZOCL_BO_FLAGS_CMA))
+		return -EINVAL;
+
+	args->flags |= ZOCL_BO_FLAGS_SVM;
+	if (!(args->flags & ZOCL_BO_FLAGS_SVM))
+		return -EINVAL;
+
+	bo = zocl_create_bo(dev, args->size, args->flags);
+	bo->flags |= ZOCL_BO_FLAGS_SVM;
+	bo->bank = GET_MEM_BANK(args->flags);
+
+	if (IS_ERR(bo)) {
+		DRM_DEBUG("object creation failed\n");
+		return PTR_ERR(bo);
+	}
+	bo->pages = drm_gem_get_pages(&bo->gem_base);
+	if (IS_ERR(bo->pages)) {
+		ret = PTR_ERR(bo->pages);
+		goto out_free;
+	}
+
+	bo_size = bo->gem_base.size;
+	bo->sgt = drm_prime_pages_to_sg(bo->pages, bo_size >> PAGE_SHIFT);
+	if (IS_ERR(bo->sgt))
+		goto out_free;
+
+	bo->vmapping = vmap(bo->pages, bo->gem_base.size >> PAGE_SHIFT, VM_MAP,
+			pgprot_writecombine(PAGE_KERNEL));
+
+	if (!bo->vmapping) {
+		ret = -ENOMEM;
+		goto out_free;
+	}
+
+	ret = drm_gem_create_mmap_offset(&bo->gem_base);
+	if (ret < 0)
+		goto out_free;
+
+	ret = drm_gem_handle_create(filp, &bo->gem_base, &args->handle);
+	if (ret < 0)
+		goto out_free;
+
+	zocl_describe(bo);
+	ZOCL_DRM_GEM_OBJECT_PUT_UNLOCKED(&bo->gem_base);
+
+	/* Update memory usage statistics */
+	zocl_update_mem_stat(dev->dev_private, args->size, 1, bo->bank);
+
+	return ret;
+
+out_free:
+	zocl_free_bo(&bo->gem_base);
+	return ret;
+}
+
+int
+zocl_create_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
+{
+	int ret = 0;
+	struct drm_zocl_create_bo *args = data;
+	struct drm_zocl_bo *bo;
+	struct drm_zocl_dev *zdev = dev->dev_private;
+	unsigned int bank;
+
+	args->flags = zocl_convert_bo_uflags(args->flags);
+
+	if (zdev->domain)
+		return zocl_create_svm_bo(dev, data, filp);
+
+	bank = GET_MEM_BANK(args->flags);
+
+	/* Always allocate EXECBUF from CMA */
+	if (args->flags & ZOCL_BO_FLAGS_EXECBUF)
+		args->flags |= ZOCL_BO_FLAGS_CMA;
+	else {
+		/*
+		 * For specified valid DDR bank, we only mark CMA flags
+		 * if the bank type is CMA, non-CMA type bank will use
+		 * PL-DDR; For any other cases (invalid bank index), we
+		 * allocate from CMA by default.
+		 */
+		if (bank < zdev->num_mem && zdev->mem[bank].zm_used) {
+			if (zdev->mem[bank].zm_type == ZOCL_MEM_TYPE_CMA)
+				args->flags |= ZOCL_BO_FLAGS_CMA;
+		} else
+			args->flags |= ZOCL_BO_FLAGS_CMA;
+	}
+
+	if (!(args->flags & ZOCL_BO_FLAGS_CACHEABLE)) {
+		/* If cacheable is not set, make sure we set COHERENT. */
+		args->flags |= ZOCL_BO_FLAGS_COHERENT;
+	} else if (!(args->flags & ZOCL_BO_FLAGS_CMA)) {
+		/* We do not support allocating cacheable BO from PL-DDR or LPDDR */
+		DRM_WARN("Cache is not supported and turned off for PL-DDR or LPDDR\n");
+		args->flags &= ~ZOCL_BO_FLAGS_CACHEABLE;
+	}
+
+	bo = zocl_create_bo(dev, args->size, args->flags);
+	if (IS_ERR(bo)) {
+		DRM_DEBUG("object creation failed\n");
+		return PTR_ERR(bo);
+	}
+
+	bo->bank = bank;
+	if (args->flags & ZOCL_BO_FLAGS_CACHEABLE)
+		bo->flags |= ZOCL_BO_FLAGS_CACHEABLE;
+	else
+		bo->flags |= ZOCL_BO_FLAGS_COHERENT;
+
+	if (args->flags & ZOCL_BO_FLAGS_CMA) {
+		bo->flags |= ZOCL_BO_FLAGS_CMA;
+		ret = drm_gem_handle_create(filp, &bo->cma_base.base,
+		    &args->handle);
+		if (ret) {
+			drm_gem_cma_free_object(&bo->cma_base.base);
+			DRM_DEBUG("handle creation failed\n");
+			return ret;
+		}
+	} else {
+		ret = drm_gem_handle_create(filp, &bo->gem_base,
+		    &args->handle);
+		if (ret) {
+			zocl_free_bo(&bo->gem_base);
+			DRM_DEBUG("handle create failed\n");
+			return ret;
+		}
+	}
+
+	zocl_describe(bo);
+	ZOCL_DRM_GEM_OBJECT_PUT_UNLOCKED(&bo->cma_base.base);
+
+	/*
+	 * Update memory usage statistics.
+	 *
+	 * Note: We can not use args->size here because it is
+	 *       the required size while gem object records the
+	 *       actual size allocated.
+	 */
+	zocl_update_mem_stat(zdev, bo->gem_base.size, 1, bo->bank);
+
+	return ret;
+}
+
+int
+zocl_userptr_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
+{
+	int ret;
+	struct drm_zocl_bo *bo;
+	unsigned int page_count;
+	struct drm_zocl_userptr_bo *args = data;
+	struct page **pages;
+	unsigned int sg_count;
+
+	if (offset_in_page(args->addr)) {
+		DRM_ERROR("User ptr not PAGE aligned\n");
+		return -EINVAL;
+	}
+
+	if (args->flags & ZOCL_BO_FLAGS_EXECBUF) {
+		DRM_ERROR("Exec buf could not be a user buffer\n");
+		return -EINVAL;
+	}
+
+	bo = zocl_create_userprt_bo(dev, args->size);
+	if (IS_ERR(bo)) {
+		DRM_ERROR("Object creation failed\n");
+		return PTR_ERR(bo);
+	}
+
+	/* For accurately account for number of pages */
+	page_count = bo->cma_base.base.size >> PAGE_SHIFT;
+
+	pages = kvmalloc_array(page_count, sizeof(*pages), GFP_KERNEL);
+	if (!pages) {
+		ret = -ENOMEM;
+		goto out1;
+	}
+
+	ret = get_user_pages_fast(args->addr, page_count, 1, pages);
+	if (ret != page_count) {
+		DRM_ERROR("Unable to get user pages\n");
+		ret = -ENOMEM;
+		goto out0;
+	}
+
+	bo->cma_base.sgt = drm_prime_pages_to_sg(pages, page_count);
+	if (IS_ERR(bo->cma_base.sgt)) {
+		ret = PTR_ERR(bo->cma_base.sgt);
+		goto out0;
+	}
+
+	sg_count = dma_map_sg(dev->dev, bo->cma_base.sgt->sgl,
+				bo->cma_base.sgt->nents, 0);
+	if (sg_count <= 0) {
+		DRM_ERROR("Map SG list failed\n");
+		ret = -ENOMEM;
+		goto out0;
+	}
+
+	bo->cma_base.paddr = sg_dma_address((bo->cma_base.sgt)->sgl);
+
+	/* Physical address must be continuous */
+	if (sg_count != 1) {
+		DRM_WARN("User buffer is not physical contiguous\n");
+		ret = -EINVAL;
+		goto out0;
+	}
+
+	bo->cma_base.vaddr = (void *)(uintptr_t)args->addr;
+
+	ret = drm_gem_handle_create(filp, &bo->cma_base.base, &args->handle);
+	if (ret) {
+		ret = -EINVAL;
+		DRM_ERROR("Handle creation failed\n");
+		goto out0;
+	}
+
+	bo->flags |= ZOCL_BO_FLAGS_USERPTR;
+
+	zocl_describe(bo);
+	ZOCL_DRM_GEM_OBJECT_PUT_UNLOCKED(&bo->cma_base.base);
+
+	kvfree(pages);
+
+	return ret;
+
+out0:
+	kvfree(pages);
+out1:
+	zocl_free_userptr_bo(&bo->cma_base.base);
+	DRM_DEBUG("handle creation failed\n");
+	return ret;
+}
+
+struct drm_zocl_bo *zocl_drm_create_bo(struct drm_device *dev,
+					  uint64_t unaligned_size,
+					  unsigned user_flags)
+{
+	return zocl_create_bo(dev, unaligned_size, user_flags);
+}
+
+int zocl_map_bo_ioctl(struct drm_device *dev,
+		void *data,
+		struct drm_file *filp)
+{
+	int ret = 0;
+	struct drm_zocl_map_bo *args = data;
+	struct drm_gem_object *gem_obj;
+
+	gem_obj = zocl_gem_object_lookup(dev, filp, args->handle);
+	if (!gem_obj) {
+		DRM_ERROR("Failed to look up GEM BO %d\n", args->handle);
+		return -EINVAL;
+	}
+
+	if (zocl_bo_userptr(to_zocl_bo(gem_obj))) {
+		ret = -EPERM;
+		goto out;
+	}
+
+	/* The mmap offset was set up at BO allocation time. */
+	args->offset = drm_vma_node_offset_addr(&gem_obj->vma_node);
+	zocl_describe(to_zocl_bo(gem_obj));
+
+out:
+	ZOCL_DRM_GEM_OBJECT_PUT_UNLOCKED(gem_obj);
+	return ret;
+}
+
+int zocl_sync_bo_ioctl(struct drm_device *dev,
+		void *data,
+		struct drm_file *filp)
+{
+	const struct drm_zocl_sync_bo	*args = data;
+	struct drm_gem_object		*gem_obj;
+	struct drm_gem_cma_object	*cma_obj;
+	struct drm_zocl_bo		*bo;
+	dma_addr_t			bus_addr;
+	int				rc = 0;
+
+	gem_obj = zocl_gem_object_lookup(dev, filp, args->handle);
+	if (!gem_obj) {
+		DRM_ERROR("Failed to look up GEM BO %d\n", args->handle);
+		return -EINVAL;
+	}
+
+	if ((args->offset > gem_obj->size) || (args->size > gem_obj->size) ||
+			((args->offset + args->size) > gem_obj->size)) {
+		rc = -EINVAL;
+		goto out;
+	}
+
+	bo = to_zocl_bo(gem_obj);
+	if (bo->flags & ZOCL_BO_FLAGS_COHERENT) {
+		/* The CMA buf is coherent, we don't need to do anything */
+		rc = 0;
+		goto out;
+	}
+
+	cma_obj = to_drm_gem_cma_obj(gem_obj);
+	bus_addr = cma_obj->paddr;
+
+	/* only invalidate the range of addresses requested by the user */
+	bus_addr += args->offset;
+
+	/**
+	 * NOTE: We a little bit abuse the dma_sync_single_* API here because
+	 *       it is documented as for the DMA buffer mapped by dma_map_*
+	 *       API. The buffer we are syncing here is mapped through
+	 *       remap_pfn_range(). But so far this is our best choice
+	 *       and it works.
+	 */
+	if (args->dir == DRM_ZOCL_SYNC_BO_TO_DEVICE) {
+		dma_sync_single_for_device(dev->dev, bus_addr, args->size,
+		    DMA_TO_DEVICE);
+	} else if (args->dir == DRM_ZOCL_SYNC_BO_FROM_DEVICE) {
+		dma_sync_single_for_cpu(dev->dev, bus_addr, args->size,
+		    DMA_FROM_DEVICE);
+	} else
+		rc = -EINVAL;
+
+out:
+	ZOCL_DRM_GEM_OBJECT_PUT_UNLOCKED(gem_obj);
+
+	return rc;
+}
+
+bool
+zocl_can_dma_performed(struct drm_device *dev, struct drm_file *filp,
+	struct drm_zocl_copy_bo *args, uint64_t *dst_paddr, uint64_t *src_paddr)
+{
+	struct drm_gem_object  *dst_gem_obj, *src_gem_obj;
+	struct drm_zocl_bo     *dst_bo, *src_bo;
+	uint64_t               dst_size, src_size;
+	int                    unsupported_flags = 0;
+	bool                   rc = true;
+
+	dst_gem_obj = zocl_gem_object_lookup(dev, filp, args->dst_handle);
+	if (!dst_gem_obj) {
+		DRM_ERROR("Failed to look up GEM dst handle %d\n",
+		    args->dst_handle);
+		return false;
+	}
+
+	src_gem_obj = zocl_gem_object_lookup(dev, filp, args->src_handle);
+	if (!src_gem_obj) {
+		DRM_ERROR("Failed to look up GEM src handle %d\n",
+		    args->src_handle);
+		rc = false;
+		goto out;
+	}
+
+	dst_bo = to_zocl_bo(dst_gem_obj);
+	src_bo = to_zocl_bo(src_gem_obj);
+	unsupported_flags = (ZOCL_BO_FLAGS_USERPTR | ZOCL_BO_FLAGS_HOST_BO |
+		ZOCL_BO_FLAGS_SVM);
+	if ((dst_bo->flags & unsupported_flags) ||
+	    (src_bo->flags & unsupported_flags)) {
+		DRM_ERROR("Failed: Not supported dst flags 0x%x and "
+		    "src flags 0x%x\n", dst_bo->flags, src_bo->flags);
+		rc = false;
+		goto out;
+	}
+
+	zocl_bo_describe(dst_bo, &dst_size, dst_paddr);
+	zocl_bo_describe(src_bo, &src_size, src_paddr);
+
+	/*
+	 * pre check before requesting DMA memory copy.
+	 *    dst_offset + size <= dst_size
+	 *    src_offset + size <= src_size`
+	 */
+	if (args->size == 0) {
+		DRM_ERROR("Failed: request size cannot be ZERO!");
+		rc = false;
+		goto out;
+	}
+	if (args->dst_offset + args->size > dst_size) {
+		DRM_ERROR("Failed: dst_offset + size out of boundary");
+		rc = false;
+		goto out;
+	}
+	if (args->src_offset + args->size > src_size) {
+		DRM_ERROR("Failed: src_offset + size out of boundary");
+		rc = false;
+		goto out;
+	}
+
+out:
+	if (dst_gem_obj)
+		ZOCL_DRM_GEM_OBJECT_PUT_UNLOCKED(dst_gem_obj);
+
+	if (src_gem_obj)
+		ZOCL_DRM_GEM_OBJECT_PUT_UNLOCKED(src_gem_obj);
+
+	return rc;
+}
+
+int zocl_copy_bo_async(struct drm_device *dev,
+		struct drm_file *filp,
+		zocl_dma_handle_t *dma_handle,
+		struct drm_zocl_copy_bo *args)
+{
+	uint64_t dst_paddr, src_paddr;
+	int rc = 0;
+	bool ret = false;
+
+	if (dma_handle->dma_func == NULL) {
+		DRM_ERROR("Failed: no callback dma_func for async dma");
+		return -EINVAL;
+	}
+
+	ret = zocl_can_dma_performed(dev, filp, args, &dst_paddr, &src_paddr);
+	if (!ret) {
+		DRM_ERROR("Failed: Cannot perform DMA due to previous Errors");
+		return -EINVAL;
+	}
+
+	dst_paddr += args->dst_offset;
+	src_paddr += args->src_offset;
+
+	rc = zocl_dma_memcpy_pre(dma_handle, (dma_addr_t)dst_paddr,
+	    (dma_addr_t)src_paddr, (size_t)args->size);
+	if (!rc)
+		zocl_dma_start(dma_handle);
+
+	return rc;
+}
+
+int zocl_info_bo_ioctl(struct drm_device *dev,
+		void *data,
+		struct drm_file *filp)
+{
+	const struct drm_zocl_bo *bo;
+	struct drm_zocl_info_bo *args = data;
+	struct drm_gem_object *gem_obj = zocl_gem_object_lookup(dev, filp,
+			args->handle);
+
+	if (!gem_obj) {
+		DRM_ERROR("Failed to look up GEM BO %d\n", args->handle);
+		return -EINVAL;
+	}
+
+	bo = to_zocl_bo(gem_obj);
+	zocl_bo_describe(bo, &args->size, &args->paddr);
+
+	ZOCL_DRM_GEM_OBJECT_PUT_UNLOCKED(gem_obj);
+
+	return 0;
+}
+
+static int zocl_bo_rdwr_ioctl(struct drm_device *dev, void *data,
+		struct drm_file *filp, bool is_read)
+{
+	const struct drm_zocl_pwrite_bo *args = data;
+	struct drm_gem_object *gem_obj = zocl_gem_object_lookup(dev, filp,
+			args->handle);
+	char __user *user_data = to_user_ptr(args->data_ptr);
+	struct drm_zocl_bo *bo;
+	int ret = 0;
+	char *kaddr;
+
+	if (!gem_obj) {
+		DRM_ERROR("Failed to look up GEM BO %d\n", args->handle);
+		return -EINVAL;
+	}
+
+	if ((args->offset > gem_obj->size) || (args->size > gem_obj->size)
+			|| ((args->offset + args->size) > gem_obj->size)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (args->size == 0) {
+		ret = 0;
+		goto out;
+	}
+	if (!ZOCL_ACCESS_OK(VERIFY_READ, user_data, args->size)) {
+		ret = -EFAULT;
+		goto out;
+	}
+
+	bo = to_zocl_bo(gem_obj);
+	if (bo->flags & ZOCL_BO_FLAGS_CMA)
+		kaddr = drm_gem_cma_prime_vmap(gem_obj);
+	else
+		kaddr = bo->vmapping;
+	if (!kaddr) {
+		DRM_ERROR("Fail to map BO %d\n", args->handle);
+		ret = -EFAULT;
+		goto out;
+	}
+
+	kaddr += args->offset;
+
+	if (is_read)
+		ret = copy_to_user(user_data, kaddr, args->size);
+	else
+		ret = copy_from_user(kaddr, user_data, args->size);
+
+out:
+	ZOCL_DRM_GEM_OBJECT_PUT_UNLOCKED(gem_obj);
+
+	return ret;
+
+}
+
+int zocl_pwrite_bo_ioctl(struct drm_device *dev, void *data,
+		struct drm_file *filp)
+{
+	return (zocl_bo_rdwr_ioctl(dev, data, filp, false));
+}
+
+int zocl_pread_bo_ioctl(struct drm_device *dev, void *data,
+		struct drm_file *filp)
+{
+	return (zocl_bo_rdwr_ioctl(dev, data, filp, true));
+}
+
+static struct drm_gem_cma_object *
+zocl_cma_create(struct drm_device *dev, size_t size)
+{
+	struct drm_gem_cma_object *cma_obj;
+	struct drm_gem_object *gem_obj;
+	int ret;
+
+	gem_obj = kzalloc(sizeof(struct drm_zocl_bo), GFP_KERNEL);
+	if (!gem_obj)
+		return ERR_PTR(-ENOMEM);
+	cma_obj = container_of(gem_obj, struct drm_gem_cma_object, base);
+
+	ret = drm_gem_object_init(dev, gem_obj, size);
+	if (ret)
+		goto error;
+
+	ret = drm_gem_create_mmap_offset(gem_obj);
+	if (ret) {
+		drm_gem_object_release(gem_obj);
+		goto error;
+	}
+
+	return cma_obj;
+
+error:
+	kfree(cma_obj);
+	return ERR_PTR(ret);
+}
+
+int zocl_get_hbo_ioctl(struct drm_device *dev, void *data,
+		       struct drm_file *filp)
+{
+	struct drm_zocl_bo *bo;
+	struct drm_zocl_host_bo *args = data;
+	struct drm_gem_cma_object *cma_obj;
+	struct drm_zocl_dev *zdev = dev->dev_private;
+	u64 host_mem_start = zdev->host_mem;
+	u64 host_mem_end = zdev->host_mem + zdev->host_mem_len;
+	int ret;
+
+	if (!(host_mem_start <= args->paddr &&
+	      args->paddr + args->size <= host_mem_end)) {
+		DRM_ERROR("Buffer at out side of reserved memory region\n");
+		return -ENOMEM;
+	}
+
+	cma_obj = zocl_cma_create(dev, args->size);
+	if (IS_ERR(cma_obj))
+		return -ENOMEM;
+
+	cma_obj->paddr = args->paddr;
+	cma_obj->vaddr = memremap(args->paddr, args->size, MEMREMAP_WB);
+	if (!cma_obj->vaddr) {
+		DRM_ERROR("failed to allocate buffer with size %zu\n",
+			  args->size);
+		ret = -ENOMEM;
+		goto error;
+	}
+
+	bo = to_zocl_bo(&cma_obj->base);
+
+	bo->flags |= ZOCL_BO_FLAGS_HOST_BO;
+	bo->flags |= ZOCL_BO_FLAGS_CMA;
+
+	ret = drm_gem_handle_create(filp, &bo->cma_base.base, &args->handle);
+	if (ret) {
+		drm_gem_cma_free_object(&bo->cma_base.base);
+		DRM_DEBUG("handle creation failed\n");
+		return ret;
+	}
+
+	zocl_describe(bo);
+	ZOCL_DRM_GEM_OBJECT_PUT_UNLOCKED(&bo->cma_base.base);
+
+	return ret;
+error:
+	ZOCL_DRM_GEM_OBJECT_PUT_UNLOCKED(&cma_obj->base);
+	return ret;
+}
+
+void zocl_free_host_bo(struct drm_gem_object *gem_obj)
+{
+	struct drm_zocl_bo *zocl_bo = to_zocl_bo(gem_obj);
+
+	DRM_DEBUG("%s: obj 0x%px", __func__, zocl_bo);
+
+	memunmap(zocl_bo->cma_base.vaddr);
+
+	drm_gem_object_release(gem_obj);
+
+	kfree(&zocl_bo->cma_base);
+}
+
+/*
+ * Update the memory usage of by BO.
+ *
+ * count is the number of BOs being allocated/freed. If count > 0, we are
+ * allocating 'count' BOs with total size 'size'; If count < 0, we are
+ * freeing 'count' BOs with total size 'size'.
+ */
+void zocl_update_mem_stat(struct drm_zocl_dev *zdev, u64 size, int count,
+		uint32_t bank)
+{
+	int i, update_bank = zdev->num_mem;
+
+	/*
+	 * If the 'bank' passed in is a valid bank and its type is
+	 * PL-DDR or LPDDR , we update that bank usage. Otherwise, we go
+	 * through our bank list and find the CMA bank to update
+	 * its usage.
+	 */
+	if (bank < zdev->num_mem &&
+	    zdev->mem[bank].zm_type == ZOCL_MEM_TYPE_PL_LP_DDR) {
+		update_bank = bank;
+	} else {
+		for (i = 0; i < zdev->num_mem; i++) {
+			if (zdev->mem[i].zm_used &&
+			    zdev->mem[i].zm_type == ZOCL_MEM_TYPE_CMA) {
+				update_bank = i;
+				break;
+			}
+		}
+	}
+
+	if (update_bank == zdev->num_mem)
+		return;
+
+	write_lock(&zdev->attr_rwlock);
+	zdev->mem[update_bank].zm_stat.memory_usage +=
+	    (count > 0) ?  size : -size;
+	zdev->mem[update_bank].zm_stat.bo_count += count;
+	write_unlock(&zdev->attr_rwlock);
+}
+
+/*
+ * Initialize the memory structure in zocl driver based on the memory
+ * topology extracted from xclbin.
+ *
+ * Currently, we could have multiple memory sections but only two type
+ * of them could be marked as used. We identify the memory type by its
+ * tag. If the tag field contains "MIG", it is PL-DDR. Tag filed LPDDR
+ * for higher order LPDDR memory. Other tags e.g. "HP", "HPC", it is
+ * CMA memory.
+ *
+ * PL-DDR and LPDDR are managed by DRM MM Range Allocator;
+ * CMA is managed by DRM CMA Allocator.
+ */
+void zocl_init_mem(struct drm_zocl_dev *zdev, struct mem_topology *mtopo)
+{
+	struct zocl_mem *memp;
+	int i;
+
+	if (!mtopo)
+		return;
+
+	zdev->num_mem = mtopo->m_count;
+	zdev->mem = vzalloc(zdev->num_mem * sizeof(struct zocl_mem));
+
+	for (i = 0; i < zdev->num_mem; i++) {
+		struct mem_data *md = &mtopo->m_mem_data[i];
+
+		if (!md->m_used)
+			continue;
+
+		memp = &zdev->mem[i];
+		if (md->m_type == MEM_STREAMING) {
+			memp->zm_type = ZOCL_MEM_TYPE_STREAMING;
+			continue;
+		}
+
+		memp->zm_base_addr = md->m_base_address;
+		/* In mem_topology, size is in KB */
+		memp->zm_size = md->m_size * 1024;
+		memp->zm_used = 1;
+
+		if (!strstr(md->m_tag, "MIG") && !strstr(md->m_tag, "LPDDR")) {
+			memp->zm_type = ZOCL_MEM_TYPE_CMA;
+			continue;
+		}
+
+		memp->zm_mm = vzalloc(sizeof(struct drm_mm));
+		memp->zm_type = ZOCL_MEM_TYPE_PL_LP_DDR;
+
+		drm_mm_init(memp->zm_mm, memp->zm_base_addr, memp->zm_size);
+	}
+}
+
+void zocl_clear_mem(struct drm_zocl_dev *zdev)
+{
+	int i;
+
+	if (!zdev->mem)
+		return;
+
+	mutex_lock(&zdev->mm_lock);
+
+	for (i = 0; i < zdev->num_mem; i++) {
+		struct zocl_mem *md = &zdev->mem[i];
+
+		if (md->zm_mm) {
+			drm_mm_takedown(md->zm_mm);
+			vfree(md->zm_mm);
+		}
+	}
+
+	vfree(zdev->mem);
+	zdev->mem = NULL;
+	zdev->num_mem = 0;
+
+	mutex_unlock(&zdev->mm_lock);
+}
+
+struct drm_gem_object *zocl_gem_import(struct drm_device *dev,
+				       struct dma_buf *dma_buf)
+{
+	struct drm_gem_object *gem_obj;
+	struct drm_zocl_bo *zocl_bo;
+
+	gem_obj = drm_gem_prime_import(dev, dma_buf);
+	if (!IS_ERR(gem_obj)) {
+		zocl_bo = to_zocl_bo(gem_obj);
+		/* drm_gem_cma_prime_import_sg_table() is used for hook
+		 * gem_prime_import_sg_table. It will check if import buffer
+		 * is a CMA buffer and create CMA object.
+		 */
+		zocl_bo->flags |= ZOCL_BO_FLAGS_CMA;
+	}
+
+	return gem_obj;
+}
+
+void zocl_drm_free_bo(struct drm_zocl_bo *bo)
+{
+	zocl_free_bo(&bo->gem_base);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/zocl_cu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/zocl_cu.c
@@ -0,0 +1,546 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * MPSoC based OpenCL accelerators Compute Units.
+ *
+ * Copyright (C) 2019-2020 Xilinx, Inc. All rights reserved.
+ *
+ * Authors:
+ *    Min Ma      <min.ma@xilinx.com>
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+
+#include <drm/drm.h>
+#include <drm/drm_print.h>
+#include <linux/io.h>
+
+#include "zocl_cu.h"
+
+void
+zocl_cu_disable_intr(struct zocl_cu *cu, u32 type)
+{
+	cu->funcs->disable_intr(cu->core, type);
+}
+
+void
+zocl_cu_enable_intr(struct zocl_cu *cu, u32 type)
+{
+	cu->funcs->enable_intr(cu->core, type);
+}
+
+u32
+zocl_cu_clear_intr(struct zocl_cu *cu)
+{
+	return cu->funcs->clear_intr(cu->core);
+}
+
+int
+zocl_cu_get_credit(struct zocl_cu *cu)
+{
+	struct zcu_core *cu_core = cu->core;
+
+	cu_core->credits--;
+	return cu_core->credits;
+}
+
+void
+zocl_cu_refund_credit(struct zocl_cu *cu, u32 count)
+{
+	struct zcu_core *cu_core = cu->core;
+
+	cu_core->credits += count;
+}
+
+void
+zocl_cu_configure(struct zocl_cu *cu, u32 *data, size_t sz, int type)
+{
+	cu->funcs->configure(cu->core, data, sz, type);
+}
+
+void
+zocl_cu_start(struct zocl_cu *cu)
+{
+	cu->funcs->start(cu->core);
+}
+
+void
+zocl_cu_check(struct zocl_cu *cu)
+{
+	struct zcu_tasks_info tasks;
+
+	cu->funcs->check(cu->core, &tasks);
+	cu->done_cnt += tasks.num_tasks_done;
+	cu->ready_cnt += tasks.num_tasks_ready;
+}
+
+void
+zocl_cu_reset(struct zocl_cu *cu)
+{
+	cu->funcs->reset(cu->core);
+}
+
+int
+zocl_cu_reset_done(struct zocl_cu *cu)
+{
+	return cu->funcs->reset_done(cu->core);
+}
+
+phys_addr_t
+zocl_cu_get_paddr(struct zocl_cu *cu)
+{
+	struct zcu_core *cu_core = cu->core;
+
+	return cu_core->paddr;
+}
+
+void
+zocl_cu_status_print(struct zocl_cu *cu)
+{
+	struct zcu_core *cu_core = cu->core;
+
+	if (!cu_core)
+		return;
+
+	DRM_INFO("addr 0x%llx, status 0x%x",
+	    (u64)cu_core->paddr, ioread32(cu_core->vaddr));
+}
+
+int
+zocl_cu_status_get(struct zocl_cu *cu)
+{
+	struct zcu_core *cu_core = cu->core;
+
+	if (!cu_core)
+		return -1;//soft cu has crashed
+
+	return (u32)ioread32(cu_core->vaddr);
+}
+
+u32
+zocl_cu_get_control(struct zocl_cu *cu)
+{
+	struct zcu_core *cu_core = cu->core;
+
+	return cu_core->control;
+}
+
+/* -- HLS adapter start -- */
+/* HLS adapter implementation realted code. */
+static void
+zocl_hls_enable_intr(void *core, u32 intr_type)
+{
+	struct zcu_core *cu_core = core;
+	u32 intr_mask = intr_type & CU_INTR_DONE;
+
+	/* 0x04 and 0x08 -- Interrupt Enable Registers */
+	iowrite32(0x1, cu_core->vaddr + 1);
+	/*
+	 * bit 0 is ap_done, bit 1 is ap_ready
+	 * only enable ap_done before dataflow support, interrupts are handled
+	 * in sched_exec_isr, please see dataflow comments for more information.
+	 */
+	iowrite32(intr_mask, cu_core->vaddr + 2);
+}
+
+static void
+zocl_hls_disable_intr(void *core, u32 intr_type)
+{
+	struct zcu_core *cu_core = core;
+	u32 intr_mask = intr_type & ioread32(cu_core->vaddr + 2);
+
+	/* 0x04 and 0x08 -- Interrupt Enable Registers */
+	iowrite32(0x0, cu_core->vaddr + 1);
+	/* bit 0 is ap_done, bit 1 is ap_ready, disable both of interrupts */
+	iowrite32(intr_mask, cu_core->vaddr + 2);
+}
+
+static u32
+zocl_hls_clear_intr(void *core)
+{
+	struct zcu_core *cu_core = core;
+
+	/* Clear all interrupts of the CU
+	 *
+	 * HLS style kernel has Interrupt Status Register at offset 0x0C
+	 * It has two interrupt bits, bit[0] is ap_done, bit[1] is ap_ready.
+	 *
+	 * The ap_done interrupt means this CU is complete.
+	 * The ap_ready interrupt means all inputs have been read.
+	 */
+	if (cu_core->max_credits == 1) {
+		u32 isr;
+
+		/*
+		 * The old HLS adapter.
+		 *
+		 * The Interrupt Status Register is Toggle On Write
+		 * RegData = RegData ^ WriteData
+		 *
+		 * So, the reliable way to clear this register is read
+		 * then write the same value back.
+		 *
+		 * Do not write 1 to this register.  If, somehow, the
+		 * status register is 0, write 1 to this register will
+		 * trigger interrupt.
+		 */
+		isr = ioread32(cu_core->vaddr + 3);
+		iowrite32(isr, cu_core->vaddr + 3);
+		return isr;
+	}
+
+	/*
+	 * The new HLS adapter with queue.
+	 *
+	 * The Interrupt Status Register is Clear on Read.
+	 *
+	 * For debug purpose, This register is toggle on write.
+	 * Write 1 to this register will trigger interrupt.
+	 */
+	return ioread32(cu_core->vaddr + 3);
+}
+
+static void
+zocl_hls_configure(void *core, u32 *data, size_t sz, int type)
+{
+	struct zcu_core *cu_core = core;
+	u32 *base_addr = cu_core->vaddr;
+	u32 i, offset, val;
+
+	switch (type) {
+	case CONSECUTIVE:
+		/* Write register map, starting at base_addr + 0x10 (byte)
+		 * This based on the fact that kernel used
+		 *	0x00 -- Control Register
+		 *	0x04 and 0x08 -- Interrupt Enable Registers
+		 *	0x0C -- Interrupt Status Register
+		 * Skip the first 4 words in user regmap.
+		 */
+		for (i = 4; i < sz; ++i)
+			iowrite32(data[i], base_addr + i);
+		break;
+	case PAIRS:
+		/* This is the {offset, value} pairs to configure CU.
+		 * It relies on the KDS/ERT command format.
+		 * The data in the command is 32 bits.
+		 */
+		for (i = 0; i < sz - 1; i += 2) {
+			 /* The offset is the offset to CU base address */
+			offset = *(data + i);
+			val = *(data + i + 1);
+
+			iowrite32(val, base_addr + offset / 4);
+		}
+		break;
+	}
+}
+
+static void
+zocl_hls_start(void *core)
+{
+	struct zcu_core *cu_core = core;
+
+	/* Bit 0 -- The CU start control bit.
+	 * Write 0 to this bit will be ignored.
+	 * Until the CU is ready to take next task, this bit will reamin 1.
+	 * Once ths CU is ready, it will clear this bit.
+	 * So, if this bit is 1, it means the CU is running.
+	 */
+	iowrite32(0x1, cu_core->vaddr);
+}
+
+static void
+zocl_hls_check(void *core, struct zcu_tasks_info *tasks_info)
+{
+	struct zcu_core *cu_core = core;
+	u32 version;
+	u32 ctrl_reg;
+	u32 ready_cnt = 0;
+	u32 done_cnt = 0;
+
+	/* done is indicated by AP_DONE(2) alone or by AP_DONE(2) | AP_IDLE(4)
+	 * but not by AP_IDLE itself.  Since 0x10 | (0x10 | 0x100) = 0x110
+	 * checking for 0x10 is sufficient.
+	 */
+	ctrl_reg  = ioread32(cu_core->vaddr);
+	version   = (ctrl_reg & CU_VERSION_MASK) >> 8;
+
+	/* For the old version of HLS adapter
+	 * There is no ready and done counter. If done bit is 1, means CU is
+	 * ready for a new command and a command was done.
+	 */
+	if (version != 0) {
+		ready_cnt = (ctrl_reg & CU_READY_CNT_MASK) >> 16;
+		done_cnt  = (ctrl_reg & CU_DONE_CNT_MASK) >> 24;
+	} else if (ctrl_reg & CU_AP_DONE) {
+		ready_cnt = 1;
+		done_cnt = 1;
+
+		/*
+		 * wrtie AP_CONTINUE to restart CU.
+		 * this is safe for all hls/versal kernel
+		 */
+		iowrite32(CU_AP_CONTINUE, cu_core->vaddr);
+		/*
+		 * reading AP_DONE is redudent, it should be done in next cycle.
+		 */
+		ctrl_reg = ioread32(cu_core->vaddr);
+		if ((ctrl_reg & CU_AP_DONE) != 0)
+			DRM_ERROR("AP_DONE is not zero: 0x%x", ctrl_reg);
+
+	}
+
+	tasks_info->num_tasks_ready = ready_cnt;
+	tasks_info->num_tasks_done = done_cnt;
+}
+
+static void
+zocl_hls_reset(void *core)
+{
+	struct zcu_core *cu_core = core;
+
+	iowrite32(CU_AP_RESET, cu_core->vaddr);
+}
+
+static int
+zocl_hls_reset_done(void *core)
+{
+	struct zcu_core *cu_core = core;
+	u32 status;
+
+	status = ioread32(cu_core->vaddr);
+
+	/* reset done is indicated by AP_RESET_DONE, bit 6 */
+	if (status & (1 << 6))
+		return true;
+
+	return false;
+}
+
+static struct zcu_funcs hls_adapter_ops = {
+	.enable_intr	= zocl_hls_enable_intr,
+	.disable_intr	= zocl_hls_disable_intr,
+	.clear_intr	= zocl_hls_clear_intr,
+	.configure	= zocl_hls_configure,
+	.start		= zocl_hls_start,
+	.check		= zocl_hls_check,
+	.reset		= zocl_hls_reset,
+	.reset_done	= zocl_hls_reset_done,
+};
+
+static int
+zocl_hls_cu_init(struct zocl_cu *cu, phys_addr_t paddr)
+{
+	struct zcu_core *core;
+	u32 ctrl_reg;
+	u32 version;
+	u32 max_cap;
+
+	core = vzalloc(sizeof(struct zcu_core));
+	if (!core) {
+		DRM_ERROR("Could not allocate CU core object\n");
+		return -ENOMEM;
+	}
+
+	core->control = paddr & 0x7;
+	paddr = paddr & ZOCL_KDS_MASK;
+	core->paddr = paddr;
+	core->vaddr = ioremap(paddr, CU_SIZE);
+	if (!core->vaddr) {
+		DRM_ERROR("Mapping CU failed\n");
+		vfree(core);
+		return -ENOMEM;
+	}
+
+	DRM_DEBUG("CU 0x%llx map to 0x%p\n", (u64)core->paddr, core->vaddr);
+	ctrl_reg = ioread32(core->vaddr);
+	version = (ctrl_reg & CU_VERSION_MASK) >> 8;
+	max_cap = (ctrl_reg & CU_MAX_CAP_MASK) >> 12;
+	switch (version) {
+	case 1:
+		core->max_credits = 1 << max_cap;
+		break;
+	default:
+		core->max_credits = 1;
+	}
+	core->credits = core->max_credits;
+
+	core->intr_type = CU_INTR_DONE | CU_INTR_READY;
+
+	/* In case CU object is not initialled as 0 */
+	cu->done_cnt = 0;
+	cu->ready_cnt = 0;
+	cu->usage = 0;
+	cu->core = core;
+	cu->funcs = &hls_adapter_ops;
+
+	INIT_LIST_HEAD(&cu->running_queue);
+
+	return 0;
+}
+
+static int
+zocl_hls_cu_fini(struct zocl_cu *cu)
+{
+	struct zcu_core *core = cu->core;
+
+	if (!core)
+		return 0;
+
+	if (core->vaddr)
+		iounmap(core->vaddr);
+	vfree(core);
+
+	return 0;
+}
+
+/* -- HLS adapter end -- */
+
+/* -- ACC adapter start -- */
+static void
+zocl_acc_configure(void *core, u32 *data, size_t sz, int type)
+{
+	struct zcu_core *cu_core = core;
+	u32 *base_addr = cu_core->vaddr;
+	u32 i, offset, val;
+
+	if (type != PAIRS)
+		return;
+
+	/*
+	 * Same open issue like HLS adapter
+	 * Skip 6 data,this is how user layer construct the command.
+	 */
+	for (i = 6; i < sz - 1; i += 2) {
+		offset = *(data + i) - cu_core->paddr;
+		val = *(data + i + 1);
+
+		iowrite32(val, base_addr + offset/4);
+	}
+}
+
+static void
+zocl_acc_start(void *core)
+{
+	struct zcu_core *cu_core = core;
+	/* 0x08 -- Command register
+	 * Write a zero to the command queue to indicate the start of a command
+	 */
+	iowrite32(0x0, cu_core->vaddr + 2);
+}
+
+static void
+zocl_acc_check(void *core, struct zcu_tasks_info *tasks_info)
+{
+	struct zcu_core *cu_core = core;
+	u32 status;
+
+	tasks_info->num_tasks_ready = 0;
+	tasks_info->num_tasks_done = 0;
+	/* 0x04 -- Status register. If the CU is idle, the value is 0x6 or 0x4.
+	 * Bit 5, O means a task is finished. 1 means done queue empty
+	 * So, if the CU is running or idle, this bit would be 1.
+	 */
+	status = ioread32(cu_core->vaddr + 1);
+	if ((status & 0x20) == 0) {
+		/* One command is done.
+		 * This adapter didn't support CU ready signal.
+		 * So think the CU alway ready and done at the same time.
+		 */
+		tasks_info->num_tasks_ready = 1;
+		tasks_info->num_tasks_done = 1;
+	}
+}
+
+static struct zcu_funcs acc_adapter_ops = {
+	.configure	= zocl_acc_configure,
+	.start		= zocl_acc_start,
+	.check		= zocl_acc_check,
+};
+
+static int
+zocl_acc_cu_init(struct zocl_cu *cu, phys_addr_t paddr)
+{
+	struct zcu_core *core;
+
+	core = vzalloc(sizeof(struct zcu_core));
+	if (!core) {
+		DRM_ERROR("Could not allocate CU core object\n");
+		return -ENOMEM;
+	}
+
+	core->paddr = paddr;
+	core->vaddr = ioremap(paddr, CU_SIZE);
+	if (!core->vaddr) {
+		DRM_ERROR("Mapping CU failed\n");
+		vfree(core);
+		return -ENOMEM;
+	}
+
+	DRM_DEBUG("CU 0x%llx map to 0x%p\n", (u64)core->paddr, core->vaddr);
+	/* Unless otherwise configured, the adapter IP has space for 16
+	 * outstanding computations.
+	 */
+	core->max_credits = 16;
+	core->credits = core->max_credits;
+
+	core->intr_type = 0;
+	core->control = 0;
+
+	cu->done_cnt = 0;
+	cu->ready_cnt = 0;
+	cu->usage = 0;
+	cu->core = core;
+	cu->funcs = &acc_adapter_ops;
+
+	INIT_LIST_HEAD(&cu->running_queue);
+
+	return 0;
+}
+
+static int
+zocl_acc_cu_fini(struct zocl_cu *cu)
+{
+	struct zcu_core *core = cu->core;
+
+	if (!core)
+		return 0;
+
+	if (core->vaddr)
+		iounmap(core->vaddr);
+	vfree(core);
+
+	return 0;
+}
+/* -- ACC adapter end -- */
+
+int zocl_cu_init(struct zocl_cu *cu, enum zcu_model m, phys_addr_t paddr)
+{
+	cu->model = m;
+	switch (cu->model) {
+	case MODEL_HLS:
+		return zocl_hls_cu_init(cu, paddr);
+	case MODEL_ACC:
+		return zocl_acc_cu_init(cu, paddr);
+	default:
+		DRM_ERROR("Unknown CU model\n");
+		return -EINVAL;
+	}
+}
+
+int zocl_cu_fini(struct zocl_cu *cu)
+{
+	if (!cu)
+		return 0;
+
+	switch (cu->model) {
+	case MODEL_HLS:
+		return zocl_hls_cu_fini(cu);
+	case MODEL_ACC:
+		return zocl_acc_cu_fini(cu);
+	default:
+		DRM_ERROR("Unknown CU model\n");
+		return -EINVAL;
+	}
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/zocl_dma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/zocl_dma.c
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * A GEM style (optionally CMA backed) device manager for ZynQ based
+ * OpenCL accelerators.
+ *
+ * Copyright (C) 2016-2019 Xilinx, Inc. All rights reserved.
+ *
+ * Authors:
+ *    Sonal Santan <sonal.santan@xilinx.com>
+ *    Umang Parekh <umang.parekh@xilinx.com>
+ *    Jan Stephan  <j.stephan@hzdr.de>
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#include "zocl_dma.h"
+#include <drm/drm_print.h>
+
+static void zocl_dma_irq_done(void *data)
+{
+	zocl_dma_handle_t *dma_handle = data;
+	enum dma_status status;
+
+	status = dmaengine_tx_status(dma_handle->dma_chan,
+	    dma_handle->dma_cookie, NULL);
+
+	switch (status) {
+	case DMA_IN_PROGRESS:
+		DRM_DEBUG("%s: Received DMA_IN_PROGRESS", __func__);
+		break;
+	case DMA_PAUSED:
+		DRM_ERROR("Received DMA_PAUSED");
+		break;
+	case DMA_ERROR:
+		DRM_ERROR("Received DMA_ERROR");
+		complete(&dma_handle->dma_done);
+		/* registered callback function from user */
+		if (dma_handle->dma_func)
+			dma_handle->dma_func(dma_handle->dma_arg, -EIO);
+		break;
+	case DMA_COMPLETE:
+		complete(&dma_handle->dma_done);
+		/* registered callback function from user */
+		if (dma_handle->dma_func)
+			dma_handle->dma_func(dma_handle->dma_arg, 0);
+		break;
+	default:
+		DRM_ERROR("Received Unknown status: %d", status);
+	}
+}
+
+int zocl_dma_memcpy_pre(zocl_dma_handle_t *dma_handle,
+    dma_addr_t dst_paddr, dma_addr_t src_paddr, size_t size)
+{
+	struct dma_async_tx_descriptor 	*dma_tx;
+	int 				rc = 0;
+
+	/* prep dma memcpy engine */
+	dma_tx = dmaengine_prep_dma_memcpy(dma_handle->dma_chan, dst_paddr,
+	    src_paddr, size, DMA_CTRL_ACK);
+	if (!dma_tx) {
+		DRM_ERROR("Failed to prepare DMA memcpy\n");
+		rc = -EINVAL;
+		goto out;
+	}
+
+	dma_tx->callback = zocl_dma_irq_done;
+	dma_tx->callback_param = dma_handle;
+
+	/* submit dma engine */
+	dma_handle->dma_cookie = dmaengine_submit(dma_tx);
+	if (dma_submit_error(dma_handle->dma_cookie)) {
+		DRM_ERROR("Failed to submit dma\n");
+		rc = -EINVAL;
+		goto out;
+	}
+out:
+	return rc;
+}
+
+void zocl_dma_start(zocl_dma_handle_t *dma_handle)
+{
+	init_completion(&dma_handle->dma_done);
+	dma_async_issue_pending(dma_handle->dma_chan);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/zocl_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/zocl_drv.c
@@ -0,0 +1,1071 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * A GEM style (optionally CMA backed) device manager for ZynQ based
+ * OpenCL accelerators.
+ *
+ * Copyright (C) 2016-2020 Xilinx, Inc. All rights reserved.
+ *
+ * Authors:
+ *    Sonal Santan <sonal.santan@xilinx.com>
+ *    Umang Parekh <umang.parekh@xilinx.com>
+ *    Min Ma       <min.ma@xilinx.com>
+ *    Jan Stephan  <j.stephan@hzdr.de>
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#include <linux/delay.h>
+#include <linux/dma-buf.h>
+#include <linux/module.h>
+#include <linux/fpga/fpga-mgr.h>
+#include <linux/iommu.h>
+#include <linux/pagemap.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/poll.h>
+#include <linux/spinlock.h>
+#include "zocl_drv.h"
+#include "zocl_sk.h"
+#include "zocl_aie.h"
+#include "zocl_bo.h"
+#include "sched_exec.h"
+#include "zocl_xclbin.h"
+#include "zocl_error.h"
+
+#define ZOCL_DRIVER_NAME        "zocl"
+#define ZOCL_DRIVER_DESC        "Zynq BO manager"
+
+static char driver_date[9];
+
+/* This should be the same as DRM_FILE_PAGE_OFFSET_START in drm_gem.c */
+#if defined(CONFIG_ARM64)
+#define ZOCL_FILE_PAGE_OFFSET   0x00100000
+#else
+#define ZOCL_FILE_PAGE_OFFSET   0x00010000
+#endif
+
+#ifndef VM_RESERVED
+#define VM_RESERVED (VM_DONTEXPAND | VM_DONTDUMP)
+#endif
+
+extern int kds_mode;
+
+static const struct vm_operations_struct reg_physical_vm_ops = {
+#ifdef CONFIG_HAVE_IOREMAP_PROT
+	.access = generic_access_phys,
+#endif
+};
+
+void zocl_free_sections(struct drm_zocl_dev *zdev)
+{
+	if (zdev->ip) {
+		vfree(zdev->ip);
+		CLEAR(zdev->ip);
+	}
+	if (zdev->debug_ip) {
+		vfree(zdev->debug_ip);
+		CLEAR(zdev->debug_ip);
+	}
+	if (zdev->connectivity) {
+		vfree(zdev->connectivity);
+		CLEAR(zdev->connectivity);
+	}
+	if (zdev->topology) {
+		vfree(zdev->topology);
+		CLEAR(zdev->topology);
+	}
+}
+
+#if KERNEL_VERSION(5, 3, 0) <= LINUX_VERSION_CODE
+static int
+match_name(struct device *dev, const void *data)
+#else
+static int
+match_name(struct device *dev, void *data)
+#endif
+{
+	const char *name = data;
+	/*
+	 * check if given name is substring inside dev.
+	 * the dev_name is like: 20300030000.ert_hw
+	 */
+	return strstr(dev_name(dev), name) != NULL;
+}
+
+/**
+ * get_reserved_mem_region - Get reserved memory region
+ *
+ * @dev: device struct
+ * @res: resource struct
+ *
+ * Returns 0 is get reserved memory resion successfully.
+ * Returns -EINVAL if not found.
+ */
+static int get_reserved_mem_region(struct device *dev, struct resource *res)
+{
+	struct device_node *np = NULL;
+	int ret;
+
+	np = of_parse_phandle(dev->of_node, "memory-region", 0);
+	if (!np)
+		return -EINVAL;
+
+	ret = of_address_to_resource(np, 0, res);
+	if (ret)
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
+ * zocl_find_pdev - Find platform device by name
+ *
+ * @name: device name
+ *
+ * Returns a platform device. Returns NULL if not found.
+ */
+struct platform_device *zocl_find_pdev(char *name)
+{
+	struct device *dev;
+	struct platform_device *pdev;
+
+	dev = bus_find_device(&platform_bus_type, NULL, (void *)name,
+	    match_name);
+	if (!dev)
+		return NULL;
+
+	pdev = container_of(dev, struct platform_device, dev);
+	return pdev;
+}
+
+/**
+ * update_cu_idx_in_apt - Set scheduler CU index in aperture
+ *
+ * @zdev: zocl device struct
+ * @apt_idx: aperture index in the IP_LAYOUT ordering
+ * @cu_idx: CU index in the scheduler ordering
+ *
+ */
+void update_cu_idx_in_apt(struct drm_zocl_dev *zdev, int apt_idx, int cu_idx)
+{
+	struct addr_aperture *apts = zdev->apertures;
+
+	/* Actually, we should consider lock this.
+	 * So far, let do this without lock. Since the scheduler would only
+	 * update this when xclbin was changed.
+	 */
+	apts[apt_idx].cu_idx = cu_idx;
+}
+
+/**
+ * get_apt_index_by_addr - Get the index of the geiven phys address,
+ *		   if it is the start of an aperture
+ *
+ * @zdev: zocl device struct
+ * @addr: physical address of the aperture
+ *
+ * Returns the index if aperture was found.
+ * Returns -EINVAL if not found.
+ *
+ */
+int get_apt_index_by_addr(struct drm_zocl_dev *zdev, phys_addr_t addr)
+{
+	struct addr_aperture *apts = zdev->apertures;
+	int i;
+
+	/* Haven't consider search efficiency yet. */
+	for (i = 0; i < zdev->num_apts; ++i)
+		if (apts[i].addr == addr)
+			break;
+
+	return (i == zdev->num_apts) ? -EINVAL : i;
+}
+
+/**
+ * get_apt_index_by_cu_idx - Get the index of the geiven phys address,
+ *		   if it is the start of an aperture
+ *
+ * @zdev: zocl device struct
+ * @cu_idx: CU index
+ *
+ * Returns the index if aperture was found.
+ * Returns -EINVAL if not found.
+ *
+ */
+int get_apt_index_by_cu_idx(struct drm_zocl_dev *zdev, int cu_idx)
+{
+	struct addr_aperture *apts = zdev->apertures;
+	int i;
+
+	WARN_ON(cu_idx >= MAX_CU_NUM);
+	if (cu_idx >= MAX_CU_NUM)
+		return -EINVAL;
+
+	/* Haven't consider search efficiency yet. */
+	for (i = 0; i < zdev->num_apts; ++i)
+		if (apts[i].cu_idx == cu_idx)
+			break;
+
+	return (i == zdev->num_apts) ? -EINVAL : i;
+}
+
+int subdev_create_cu(struct drm_zocl_dev *zdev, struct xrt_cu_info *info)
+{
+	struct platform_device *pldev;
+	struct resource res;
+	int ret;
+
+	pldev = platform_device_alloc("CU", PLATFORM_DEVID_AUTO);
+	if (!pldev) {
+		DRM_ERROR("Failed to alloc device CU\n");
+		return -ENOMEM;
+	}
+
+	/* hard code resource
+	 * TODO: maybe we should define resource in a header file
+	 */
+	/* zdev->res_start provides higher 32 bits address */
+	res.start = zdev->res_start + info->addr;
+	res.end = res.start + 0xFFFF;
+	res.flags = IORESOURCE_MEM;
+	res.parent = NULL;
+	ret = platform_device_add_resources(pldev, &res, 1);
+	if (ret) {
+		DRM_ERROR("Failed to add resource\n");
+		goto err;
+	}
+
+	ret = platform_device_add_data(pldev, info, sizeof(*info));
+	if (ret) {
+		DRM_ERROR("Failed to add data\n");
+		goto err;
+	}
+
+	pldev->dev.parent = zdev->ddev->dev;
+
+	ret = platform_device_add(pldev);
+	if (ret) {
+		DRM_ERROR("Failed to add device\n");
+		goto err;
+	}
+
+	/*
+	 * force probe to avoid dependence issue. if probing
+	 * failed, it could be the driver is not registered.
+	 */
+	ret = device_attach(&pldev->dev);
+	if (ret != 1) {
+		DRM_ERROR("Failed to probe device\n");
+		goto err1;
+	}
+	zdev->cu_pldev[info->inst_idx] = pldev;
+
+	return 0;
+err1:
+	platform_device_del(pldev);
+err:
+	platform_device_put(pldev);
+	return ret;
+}
+
+void subdev_destroy_cu(struct drm_zocl_dev *zdev)
+{
+	int i;
+
+	for (i = 0; i < MAX_CU_NUM; ++i) {
+		if (!zdev->cu_pldev[i])
+			continue;
+		platform_device_del(zdev->cu_pldev[i]);
+		platform_device_put(zdev->cu_pldev[i]);
+		zdev->cu_pldev[i] = NULL;
+	}
+}
+
+/**
+ * zocl_gem_create_object - Create drm_zocl_bo object instead of DRM CMA object.
+ *
+ * @dev: DRM device struct
+ * @size: This size was not use, just to match function prototype.
+ *
+ */
+struct drm_gem_object *
+zocl_gem_create_object(struct drm_device *dev, size_t size)
+{
+	return kzalloc(sizeof(struct drm_zocl_bo), GFP_KERNEL);
+}
+
+void zocl_free_bo(struct drm_gem_object *obj)
+{
+	struct drm_zocl_bo *zocl_obj;
+	struct drm_zocl_dev *zdev;
+	int npages;
+
+	if (IS_ERR(obj) || !obj)
+		return;
+
+	DRM_DEBUG("Freeing BO\n");
+	zocl_obj = to_zocl_bo(obj);
+	zdev = obj->dev->dev_private;
+
+	if (!zdev->domain) {
+		zocl_describe(zocl_obj);
+		if (zocl_obj->flags & ZOCL_BO_FLAGS_USERPTR)
+			zocl_free_userptr_bo(obj);
+		else if (zocl_obj->flags & ZOCL_BO_FLAGS_HOST_BO)
+			zocl_free_host_bo(obj);
+		else if (zocl_obj->flags & ZOCL_BO_FLAGS_CMA) {
+			drm_gem_cma_free_object(obj);
+
+			/* Update memory usage statistics */
+			zocl_update_mem_stat(zdev, obj->size, -1,
+			    zocl_obj->bank);
+		} else {
+			if (zocl_obj->mm_node) {
+				mutex_lock(&zdev->mm_lock);
+				drm_mm_remove_node(zocl_obj->mm_node);
+				mutex_unlock(&zdev->mm_lock);
+				kfree(zocl_obj->mm_node);
+				if (zocl_obj->vmapping) {
+					memunmap(zocl_obj->vmapping);
+					zocl_obj->vmapping = NULL;
+				}
+				zocl_update_mem_stat(zdev, obj->size, -1,
+				    zocl_obj->bank);
+			}
+			drm_gem_object_release(obj);
+			kfree(zocl_obj);
+		}
+
+		return;
+	}
+
+	npages = obj->size >> PAGE_SHIFT;
+	drm_gem_object_release(obj);
+
+	if (zocl_obj->vmapping)
+		vunmap(zocl_obj->vmapping);
+	zocl_obj->vmapping = NULL;
+
+	zocl_iommu_unmap_bo(obj->dev, zocl_obj);
+	if (zocl_obj->pages) {
+		if (zocl_bo_userptr(zocl_obj)) {
+#if KERNEL_VERSION(4, 15, 0) <= LINUX_VERSION_CODE
+			release_pages(zocl_obj->pages, npages);
+#else
+			release_pages(zocl_obj->pages, npages, 0);
+#endif
+			kvfree(zocl_obj->pages);
+		} else {
+			drm_gem_put_pages(obj, zocl_obj->pages, false, false);
+
+			/* Update memory usage statistics */
+			zocl_update_mem_stat(zdev, obj->size, -1,
+			    zocl_obj->bank);
+		}
+	}
+	if (zocl_obj->sgt)
+		sg_free_table(zocl_obj->sgt);
+	zocl_obj->sgt = NULL;
+	zocl_obj->pages = NULL;
+	kfree(zocl_obj);
+}
+
+static int
+zocl_gem_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+	struct drm_gem_cma_object *cma_obj = NULL;
+	struct drm_gem_object *gem_obj;
+	struct drm_zocl_bo *bo;
+	dma_addr_t paddr;
+	pgprot_t prot;
+	int rc;
+
+	/**
+	 * drm_gem_mmap may modify the vma prot as non-cacheable.
+	 * We need to preserve this field and resume it in case
+	 * the BO is cacheable.
+	 */
+	prot = vma->vm_page_prot;
+
+	rc = drm_gem_mmap(filp, vma);
+
+	if (rc)
+		return rc;
+
+	/**
+	 * Clear the VM_PFNMAP flag that was set by drm_gem_mmap(),
+	 * and set the vm_pgoff (used as a fake buffer offset by DRM)
+	 * to 0 as we want to map the whole buffer.
+	 */
+	vma->vm_flags &= ~VM_PFNMAP;
+	vma->vm_pgoff = 0;
+
+	gem_obj = vma->vm_private_data;
+	bo = to_zocl_bo(gem_obj);
+
+	if (bo->flags & ZOCL_BO_FLAGS_CACHEABLE)
+		/**
+		 * Resume the protection field from mmap(). Most likely
+		 * it will be cacheable. If there is a case that mmap()
+		 * protection field explicitly tells us not to map with
+		 * cache enabled, we should comply with it and overwrite
+		 * the cacheable BO property.
+		 */
+		vma->vm_page_prot = prot;
+
+	if (bo->flags & ZOCL_BO_FLAGS_CMA) {
+		cma_obj = to_drm_gem_cma_obj(gem_obj);
+		paddr = cma_obj->paddr;
+	} else
+		paddr = bo->mm_node->start;
+
+	if ((!(bo->flags & ZOCL_BO_FLAGS_CMA)) ||
+	    (bo->flags & ZOCL_BO_FLAGS_CMA &&
+	    bo->flags & ZOCL_BO_FLAGS_CACHEABLE)) {
+		/* Map PL-DDR and cacheable CMA */
+		rc = remap_pfn_range(vma, vma->vm_start,
+		    paddr >> PAGE_SHIFT, vma->vm_end - vma->vm_start,
+		    vma->vm_page_prot);
+	} else {
+		/* Map non-cacheable CMA */
+		rc = dma_mmap_wc(cma_obj->base.dev->dev, vma, cma_obj->vaddr,
+		    paddr, vma->vm_end - vma->vm_start);
+	}
+
+	if (rc)
+		drm_gem_vm_close(vma);
+
+	return rc;
+}
+
+/* This function map two types of kernel address to user space.
+ * The first type is pysical registers of a hardware IP, like CUs.
+ * The second type is GEM buffer.
+ */
+static int zocl_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+	struct drm_file     *priv = filp->private_data;
+	struct drm_device   *dev = priv->minor->dev;
+	struct drm_zocl_dev *zdev = dev->dev_private;
+	struct addr_aperture *apts = zdev->apertures;
+	struct drm_zocl_bo  *bo = NULL;
+	unsigned long        vsize;
+	phys_addr_t          phy_addr;
+	int apt_idx;
+	int rc;
+
+	/* A GEM buffer object has a fake mmap offset start from page offset
+	 * DRM_FILE_PAGE_OFFSET_START. See drm_gem_init().
+	 * ZOCL_FILE_PAGE_OFFSET should equal to DRM_FILE_PAGE_OFFSET_START.
+	 * ZOCL_FILE_PAGE_OFFSET is 4GB for 64 bits system.
+	 */
+	if (likely(vma->vm_pgoff >= ZOCL_FILE_PAGE_OFFSET)) {
+		if (!zdev->domain)
+			return zocl_gem_mmap(filp, vma);
+
+		/* Map user's pages into his VM */
+		rc = drm_gem_mmap(filp, vma);
+		if (rc)
+			return rc;
+		/* vma->vm_private_data is set by drm_gem_mmap */
+		bo = to_zocl_bo(vma->vm_private_data);
+
+		bo->uaddr = vma->vm_start;
+		/* Map user's VA into IOMMU */
+		rc = zocl_iommu_map_bo(dev, bo);
+		if (rc)
+			return rc;
+		vma->vm_flags &= ~VM_PFNMAP;
+		vma->vm_flags |= VM_MIXEDMAP;
+		/* Reset the fake offset used to identify the BO */
+		vma->vm_pgoff = 0;
+		return 0;
+	}
+
+	/* Hardware component physical address mapping. Typically, this is used
+	 * to map the registers of a compute unit to user space.
+	 *
+	 * For the most of the time, the hardware is at 0 to 4GB address range.
+	 * *NOTE* Base on MPSoC TRM, it is possible to assign hardware to higher
+	 * address than 4GB. But for now, no one use those higher address range
+	 * for IPs. The RPU is not able to access outside of 4GB memory.
+	 *
+	 * Still use this approach before it requires to support hardware
+	 * address mapping from higher than 4GB space.
+	 */
+	if (kds_mode == 0 && !zdev->exec->configured) {
+		DRM_ERROR("Schduler is not configured\n");
+		return -EINVAL;
+	}
+
+	/* Only allow user to map register ranges in apertures list.
+	 * Could not map from the middle of an aperture.
+	 */
+	apt_idx = vma->vm_pgoff;
+	if (apt_idx < 0 || apt_idx >= zdev->num_apts) {
+		DRM_ERROR("The offset is not in the apertures list\n");
+		return -EINVAL;
+	}
+	phy_addr = apts[apt_idx].addr;
+	vma->vm_pgoff = phy_addr >> PAGE_SHIFT;
+
+	vsize = vma->vm_end - vma->vm_start;
+	if (vsize > zdev->apertures[apt_idx].size)
+		return -EINVAL;
+
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+	vma->vm_flags |= VM_IO;
+	vma->vm_flags |= VM_RESERVED;
+
+	vma->vm_ops = &reg_physical_vm_ops;
+	rc = io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+				vsize, vma->vm_page_prot);
+
+	return rc;
+}
+
+static vm_fault_t zocl_bo_fault(struct vm_fault *vmf)
+{
+	struct vm_area_struct *vma = vmf->vma;
+	struct drm_gem_object *obj = vma->vm_private_data;
+	struct drm_zocl_bo *bo = to_zocl_bo(obj);
+	struct drm_zocl_dev *zdev = obj->dev->dev_private;
+	struct page *page;
+	pgoff_t offset;
+	int err;
+
+	if (!zdev->domain)
+		return 0;
+
+	if (!bo->pages)
+		return VM_FAULT_SIGBUS;
+
+	offset = ((unsigned long)vmf->address - vma->vm_start) >> PAGE_SHIFT;
+	page = bo->pages[offset];
+
+	err = vm_insert_page(vma, (unsigned long)vmf->address, page);
+	switch (err) {
+	case -EAGAIN:
+	case 0:
+	case -ERESTARTSYS:
+	case -EINTR:
+	case -EBUSY:
+		return VM_FAULT_NOPAGE;
+	case -ENOMEM:
+		return VM_FAULT_OOM;
+	}
+	return VM_FAULT_SIGBUS;
+}
+
+static int zocl_client_open(struct drm_device *dev, struct drm_file *filp)
+{
+	struct sched_client_ctx *fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL);
+	int ret = 0;
+
+	if (!fpriv)
+		return -ENOMEM;
+
+	if (kds_mode == 1) {
+		kfree(fpriv);
+		ret = zocl_create_client(dev->dev_private, &filp->driver_priv);
+	} else {
+		filp->driver_priv = fpriv;
+		mutex_init(&fpriv->lock);
+		atomic_set(&fpriv->trigger, 0);
+		atomic_set(&fpriv->outstanding_execs, 0);
+		fpriv->abort = false;
+		fpriv->pid = get_pid(task_pid(current));
+		zocl_track_ctx(dev, fpriv);
+		DRM_INFO("Pid %d opened device\n", pid_nr(task_tgid(current)));
+	}
+
+	return ret;
+}
+
+static void zocl_client_release(struct drm_device *dev, struct drm_file *filp)
+{
+	struct sched_client_ctx *client = filp->driver_priv;
+	struct drm_zocl_dev *zdev = dev->dev_private;
+	int pid;
+	u32 outstanding = 0;
+	int retry = 20;
+	int i;
+
+	if (kds_mode == 1) {
+		zocl_destroy_client(dev->dev_private, &filp->driver_priv);
+		return;
+	}
+
+	if (!client)
+		return;
+
+	pid = pid_nr(client->pid);
+
+	/* force scheduler to abort scheduled cmds for this client */
+	client->abort = true;
+	outstanding = atomic_read(&client->outstanding_execs);
+	while (retry-- && outstanding) {
+		DRM_INFO("pid(%d) waiting for outstanding %d cmds to finish",
+		    pid, outstanding);
+		msleep(500);
+		outstanding = atomic_read(&client->outstanding_execs);
+	}
+	outstanding = atomic_read(&client->outstanding_execs);
+	if (outstanding) {
+		DRM_ERROR("Please investigate stale cmds\n");
+		for (i = 0; i < zdev->exec->num_cus; i++) {
+			zocl_cu_status_print(&zdev->exec->zcu[i]);
+		}
+	}
+
+	put_pid(client->pid);
+	client->pid = NULL;
+	if (CLIENT_NUM_CU_CTX(client) == 0)
+		goto done;
+
+	/*
+	 * This happens when application exits without releasing the
+	 * contexts. Give up contexts and release xclbin.
+	 */
+	client->num_cus = 0;
+	(void) zocl_unlock_bitstream(zdev, &uuid_null);
+done:
+	zocl_untrack_ctx(dev, client);
+	kfree(client);
+
+	DRM_INFO("Pid %d closed device\n", pid_nr(task_tgid(current)));
+}
+
+static unsigned int zocl_poll(struct file *filp, poll_table *wait)
+{
+	int counter;
+	struct drm_file *priv = filp->private_data;
+	struct drm_device *dev = priv->minor->dev;
+	struct drm_zocl_dev *zdev = dev->dev_private;
+	struct sched_client_ctx *fpriv = priv->driver_priv;
+	int ret = 0;
+
+	BUG_ON(!fpriv);
+
+	if (kds_mode == 1)
+		return zocl_poll_client(filp, wait);
+
+	poll_wait(filp, &zdev->exec->poll_wait_queue, wait);
+
+	mutex_lock(&fpriv->lock);
+	counter = atomic_read(&fpriv->trigger);
+	if (counter > 0) {
+		atomic_dec(&fpriv->trigger);
+		ret = POLLIN;
+	}
+	mutex_unlock(&fpriv->lock);
+
+	return ret;
+}
+
+static int zocl_iommu_init(struct drm_zocl_dev *zdev,
+		struct platform_device *pdev)
+{
+	struct iommu_domain_geometry *geometry;
+	u64 start, end;
+	int ret;
+
+	zdev->domain = iommu_domain_alloc(&platform_bus_type);
+	if (!zdev->domain)
+		return -ENOMEM;
+
+	ret = iommu_attach_device(zdev->domain, &pdev->dev);
+	if (ret) {
+		DRM_INFO("IOMMU attach device failed. ret(%d)\n", ret);
+		iommu_domain_free(zdev->domain);
+		zdev->domain = NULL;
+		return ret;
+	}
+
+	geometry = &zdev->domain->geometry;
+	start = geometry->aperture_start;
+	end = geometry->aperture_end;
+
+	DRM_INFO("IOMMU aperture initialized (%#llx-%#llx)\n",
+				start, end);
+
+	return 0;
+}
+
+const struct vm_operations_struct zocl_bo_vm_ops = {
+	.fault = zocl_bo_fault,
+	.open  = drm_gem_vm_open,
+	.close = drm_gem_vm_close,
+};
+
+static const struct drm_ioctl_desc zocl_ioctls[] = {
+	DRM_IOCTL_DEF_DRV(ZOCL_CREATE_BO, zocl_create_bo_ioctl,
+			DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(ZOCL_USERPTR_BO, zocl_userptr_bo_ioctl,
+			DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(ZOCL_GET_HOST_BO, zocl_get_hbo_ioctl,
+			DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(ZOCL_MAP_BO, zocl_map_bo_ioctl,
+			DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(ZOCL_SYNC_BO, zocl_sync_bo_ioctl,
+			DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(ZOCL_INFO_BO, zocl_info_bo_ioctl,
+			DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(ZOCL_PWRITE_BO, zocl_pwrite_bo_ioctl,
+			DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(ZOCL_PREAD_BO, zocl_pread_bo_ioctl,
+			DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(ZOCL_EXECBUF, zocl_execbuf_ioctl,
+			DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(ZOCL_READ_AXLF, zocl_read_axlf_ioctl,
+			DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(ZOCL_SK_GETCMD, zocl_sk_getcmd_ioctl,
+			DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(ZOCL_SK_CREATE, zocl_sk_create_ioctl,
+			DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(ZOCL_SK_REPORT, zocl_sk_report_ioctl,
+			DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(ZOCL_INFO_CU, zocl_info_cu_ioctl,
+			DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(ZOCL_CTX, zocl_ctx_ioctl,
+			DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(ZOCL_ERROR_INJECT, zocl_error_ioctl,
+			DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(ZOCL_AIE_FD, zocl_aie_fd_ioctl,
+			DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(ZOCL_AIE_RESET, zocl_aie_reset_ioctl,
+			DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(ZOCL_AIE_GETCMD, zocl_aie_getcmd_ioctl,
+			DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(ZOCL_AIE_PUTCMD, zocl_aie_putcmd_ioctl,
+			DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
+};
+
+static const struct file_operations zocl_driver_fops = {
+	.owner          = THIS_MODULE,
+	.open           = drm_open,
+	.mmap           = zocl_mmap,
+	.poll           = zocl_poll,
+	.read           = drm_read,
+	.unlocked_ioctl = drm_ioctl,
+	.release        = drm_release,
+};
+
+static struct drm_driver zocl_driver = {
+#if KERNEL_VERSION(5, 4, 0) > LINUX_VERSION_CODE
+	.driver_features           = DRIVER_GEM | DRIVER_PRIME | DRIVER_RENDER,
+#else
+	.driver_features           = DRIVER_GEM | DRIVER_RENDER,
+#endif
+	.open                      = zocl_client_open,
+	.postclose                 = zocl_client_release,
+	.gem_free_object           = zocl_free_bo,
+	.gem_vm_ops                = &zocl_bo_vm_ops,
+	.gem_create_object         = zocl_gem_create_object,
+	.prime_handle_to_fd        = drm_gem_prime_handle_to_fd,
+	.prime_fd_to_handle        = drm_gem_prime_fd_to_handle,
+	.gem_prime_import          = zocl_gem_import,
+	.gem_prime_export          = drm_gem_prime_export,
+	.gem_prime_get_sg_table    = drm_gem_cma_prime_get_sg_table,
+	.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
+	.gem_prime_vmap            = drm_gem_cma_prime_vmap,
+	.gem_prime_vunmap          = drm_gem_cma_prime_vunmap,
+	.gem_prime_mmap            = drm_gem_cma_prime_mmap,
+	.ioctls                    = zocl_ioctls,
+	.num_ioctls                = ARRAY_SIZE(zocl_ioctls),
+	.fops                      = &zocl_driver_fops,
+	.name                      = ZOCL_DRIVER_NAME,
+	.desc                      = ZOCL_DRIVER_DESC,
+	.date                      = driver_date,
+};
+
+static const struct zdev_data zdev_data_mpsoc = {
+	.fpga_driver_name = "pcap",
+};
+
+static const struct zdev_data zdev_data_versal = {
+	.fpga_driver_name = "versal_fpga"
+};
+
+static const struct of_device_id zocl_drm_of_match[] = {
+	{ .compatible = "xlnx,zocl", .data = &zdev_data_mpsoc},
+	{ .compatible = "xlnx,zoclsvm", .data = &zdev_data_mpsoc},
+	{ .compatible = "xlnx,zocl-ert", .data = &zdev_data_mpsoc},
+	{ .compatible = "xlnx,zocl-versal", .data = &zdev_data_versal},
+	{ /* end of table */ },
+};
+MODULE_DEVICE_TABLE(of, zocl_drm_of_match);
+
+/* init xilinx opencl drm platform */
+static int zocl_drm_platform_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *id;
+	struct drm_device *drm;
+	struct drm_zocl_dev	*zdev;
+	struct platform_device *subdev;
+	struct resource res_mem;
+	struct resource *res;
+	struct device_node *fnode;
+	int index;
+	int irq;
+	int ret;
+	int year, mon, day;
+
+	id = of_match_node(zocl_drm_of_match, pdev->dev.of_node);
+	DRM_INFO("Probing for %s\n", id->compatible);
+
+	/* Create zocl device and initial */
+	zdev = devm_kzalloc(&pdev->dev, sizeof(*zdev), GFP_KERNEL);
+	if (!zdev)
+		return -ENOMEM;
+
+	zdev->zdev_data_info = id->data;
+	INIT_LIST_HEAD(&zdev->ctx_list);
+
+	/* Record and get IRQ number */
+	for (index = 0; index < MAX_CU_NUM; index++) {
+		irq = platform_get_irq(pdev, index);
+		if (irq < 0)
+			break;
+		DRM_DEBUG("CU(%d) IRQ %d\n", index, irq);
+		zdev->irq[index] = irq;
+	}
+	zdev->cu_num = index;
+
+	/* set to 0xFFFFFFFF(32bit) or 0xFFFFFFFFFFFFFFFF(64bit) */
+	zdev->host_mem = (phys_addr_t) -1;
+	zdev->host_mem_len = 0;
+	/* If reserved memory region are not found, just keep going */
+	ret = get_reserved_mem_region(&pdev->dev, &res_mem);
+	if (!ret) {
+		DRM_INFO("Reserved memory for host at 0x%lx, size 0x%lx\n",
+			 (unsigned long)res_mem.start,
+			 (unsigned long)resource_size(&res_mem));
+		zdev->host_mem = res_mem.start;
+		zdev->host_mem_len = resource_size(&res_mem);
+	}
+	mutex_init(&zdev->mm_lock);
+
+	subdev = zocl_find_pdev("ert_hw");
+	if (subdev) {
+		DRM_INFO("ert_hw found: 0x%llx\n", (uint64_t)(uintptr_t)subdev);
+		/* Trust device tree for now, but a better place should be
+		 * feature rom.
+		 */
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+		if (!res) {
+			DRM_ERROR("The base address of CU is not found or 0\n");
+			return -EINVAL;
+		}
+
+		zdev->res_start = res->start;
+		zdev->ert = (struct zocl_ert_dev *)platform_get_drvdata(subdev);
+	}
+
+	/* For Non PR platform, there is not need to have FPGA manager
+	 * For PR platform, the FPGA manager is required. No good way to
+	 * determin if it is a PR platform at probe.
+	 */
+	fnode = of_find_node_by_name(of_root,
+	    zdev->zdev_data_info->fpga_driver_name);
+	if (fnode) {
+		zdev->fpga_mgr = of_fpga_mgr_get(fnode);
+		if (IS_ERR(zdev->fpga_mgr))
+			zdev->fpga_mgr = NULL;
+		DRM_INFO("FPGA programming device %s founded.\n",
+		    zdev->zdev_data_info->fpga_driver_name);
+	}
+
+	if (ZOCL_PLATFORM_ARM64) {
+		if (of_property_read_u64(pdev->dev.of_node,
+		    "xlnx,pr-isolation-addr", &zdev->pr_isolation_addr))
+			zdev->pr_isolation_addr = 0;
+	} else {
+		u32 prop_addr = 0;
+
+		if (of_property_read_u32(pdev->dev.of_node,
+		    "xlnx,pr-isolation-addr", &prop_addr))
+			zdev->pr_isolation_addr = 0;
+		else
+			zdev->pr_isolation_addr = prop_addr;
+	}
+	DRM_INFO("PR Isolation addr 0x%llx", zdev->pr_isolation_addr);
+
+	/* Initialzie IOMMU */
+	if (iommu_present(&platform_bus_type)) {
+		/*
+		 * Note: we ignore the return value of zocl_iommu_init().
+		 * In the case of failing to initialize iommu, zocl
+		 * driver will keep working with iommu disabled.
+		 */
+		(void) zocl_iommu_init(zdev, pdev);
+	}
+
+	platform_set_drvdata(pdev, zdev);
+
+	sscanf(XRT_DRIVER_VERSION, "%d.%d.%d",
+		&zocl_driver.major,
+		&zocl_driver.minor,
+		&zocl_driver.patchlevel);
+	sscanf(XRT_DATE, "%d-%d-%d ", &year, &mon, &day);
+        //e.g HASH_DATE ==> Wed, 4 Nov 2020 08:46:44 -0800
+        //e.g XRT_DATE ==> 2020-11-04
+	snprintf(driver_date, sizeof(driver_date),
+		"%d%02d%02d", year, mon, day);
+
+	/* Create and register DRM device */
+	drm = drm_dev_alloc(&zocl_driver, &pdev->dev);
+	if (IS_ERR(drm))
+		return PTR_ERR(drm);
+
+	ret = drm_dev_register(drm, 0);
+	if (ret)
+		goto err_drm;
+
+	/* During attach, we don't request dma channel */
+	zdev->zdev_dma_chan = NULL;
+
+	/* Initial xclbin */
+	ret = zocl_xclbin_init(zdev);
+	if (ret)
+		goto err_drm;
+	mutex_init(&zdev->zdev_xclbin_lock);
+
+	/* doen with zdev initialization */
+	drm->dev_private = zdev;
+	zdev->ddev       = drm;
+
+	ret = zocl_init_error(zdev);
+	if (ret)
+		goto err_sysfs;
+
+	mutex_init(&zdev->aie_lock);
+
+	/* Initial sysfs */
+	rwlock_init(&zdev->attr_rwlock);
+	ret = zocl_init_sysfs(drm->dev);
+	if (ret)
+		goto err_err;
+
+	/* Now initial kds */
+	if (kds_mode == 1) {
+		ret = zocl_init_sched(zdev);
+		if (ret)
+			goto err_sched;
+	} else {
+		ret = sched_init_exec(drm);
+		if (ret)
+			goto err_sched;
+	}
+
+	return 0;
+
+/* error out in exact reverse order of init */
+err_sched:
+	zocl_fini_sysfs(drm->dev);
+err_err:
+	mutex_destroy(&zdev->aie_lock);
+	zocl_fini_error(zdev);
+err_sysfs:
+	zocl_xclbin_fini(zdev);
+	mutex_destroy(&zdev->zdev_xclbin_lock);
+err_drm:
+	ZOCL_DRM_DEV_PUT(drm);
+	return ret;
+}
+
+/* exit xilinx opencl drm platform */
+static int zocl_drm_platform_remove(struct platform_device *pdev)
+{
+	struct drm_zocl_dev *zdev = platform_get_drvdata(pdev);
+	struct drm_device *drm = zdev->ddev;
+
+	if (zdev->domain) {
+		iommu_detach_device(zdev->domain, drm->dev);
+		iommu_domain_free(zdev->domain);
+	}
+
+	/* If dma channel has been requested, make sure it is released */
+	if (zdev->zdev_dma_chan) {
+		dma_release_channel(zdev->zdev_dma_chan);
+		zdev->zdev_dma_chan = NULL;
+	}
+
+	if (zdev->fpga_mgr)
+		fpga_mgr_put(zdev->fpga_mgr);
+
+	if (kds_mode == 0)
+		sched_fini_exec(drm);
+
+	zocl_clear_mem(zdev);
+	mutex_destroy(&zdev->mm_lock);
+	zocl_free_sections(zdev);
+	zocl_xclbin_fini(zdev);
+	mutex_destroy(&zdev->zdev_xclbin_lock);
+	zocl_destroy_aie(zdev);
+	mutex_destroy(&zdev->aie_lock);
+	zocl_fini_sysfs(drm->dev);
+	zocl_fini_error(zdev);
+
+	if (kds_mode == 1)
+		zocl_fini_sched(zdev);
+
+	kfree(zdev->apertures);
+
+	drm_dev_unregister(drm);
+	ZOCL_DRM_DEV_PUT(drm);
+
+	return 0;
+}
+
+static struct platform_driver zocl_drm_private_driver = {
+	.probe			= zocl_drm_platform_probe,
+	.remove			= zocl_drm_platform_remove,
+	.driver			= {
+		.name		        = "zocl-drm",
+		.of_match_table	= zocl_drm_of_match,
+	},
+};
+
+static struct platform_driver *const drivers[] = {
+	&zocl_ert_driver,
+	&zocl_ospi_versal_driver,
+	&cu_driver,
+};
+
+static int __init zocl_init(void)
+{
+	int ret;
+
+	/* Make sure register sub device in the first place. */
+	ret = platform_register_drivers(drivers, ARRAY_SIZE(drivers));
+	if (ret < 0)
+		return ret;
+
+	ret = platform_driver_register(&zocl_drm_private_driver);
+	if (ret < 0)
+		goto err;
+
+	return 0;
+err:
+	platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
+	return ret;
+}
+module_init(zocl_init);
+
+static void __exit zocl_exit(void)
+{
+	/* Remove zocl driver first, as it is using other driver */
+	platform_driver_unregister(&zocl_drm_private_driver);
+	platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
+}
+module_exit(zocl_exit);
+
+MODULE_VERSION(XRT_DRIVER_VERSION);
+
+MODULE_DESCRIPTION(ZOCL_DRIVER_DESC);
+MODULE_AUTHOR("Sonal Santan <sonal.santan@xilinx.com>");
+MODULE_LICENSE("GPL");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/zocl_error.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/zocl_error.c
@@ -0,0 +1,130 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * A GEM style (optionally CMA backed) device manager for ZynQ based
+ * OpenCL accelerators.
+ *
+ * Copyright (C) 2020 Xilinx, Inc. All rights reserved.
+ *
+ * Authors:
+ *    Larry Liu <yliu@xilinx.com>
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#include <linux/mutex.h>
+
+#include "zocl_error.h"
+#include "zocl_drv.h"
+
+static void
+zocl_clear_all_error_record(struct drm_zocl_dev *zdev)
+{
+	struct zocl_error *zer = &zdev->zdev_error;
+
+	write_lock(&zdev->attr_rwlock);
+
+	memset(zer->ze_err, 0, sizeof(struct zocl_err_record) * zer->ze_num);
+	zer->ze_num = 0;
+
+	write_unlock(&zdev->attr_rwlock);
+}
+
+int
+zocl_insert_error_record(struct drm_zocl_dev *zdev, xrtErrorCode err_code)
+{
+	struct zocl_error *zer = &zdev->zdev_error;
+	u64 timestamp = ktime_to_ns(ktime_get_real());
+	enum xrtErrorClass class;
+	int i;
+
+	write_lock(&zdev->attr_rwlock);
+
+	if (zer->ze_num == zer->ze_cap) {
+		DRM_INFO("Error cache is full. "
+		    "No more asynchronous error will be recorded.\n");
+		write_unlock(&zdev->attr_rwlock);
+		return -ENOSPC;
+	}
+
+	/*
+	 * We only record one error for each error class.
+	 * If we can find existing error class, replace it;
+	 * Otherwise, record the error at the end.
+	 */
+	class = XRT_ERROR_CLASS(err_code);
+	for (i = 0; i < zer->ze_num; i++) {
+		if (class == XRT_ERROR_CLASS(zer->ze_err[i].zer_err_code))
+			break;
+	}
+
+	zer->ze_err[i].zer_err_code = err_code;
+	zer->ze_err[i].zer_ts = timestamp;
+	if (i == zer->ze_num)
+		zer->ze_num++;
+
+	write_unlock(&zdev->attr_rwlock);
+
+	return 0;
+}
+
+int
+zocl_inject_error(struct drm_zocl_dev *zdev, void *data,
+		struct drm_file *filp)
+{
+	struct drm_zocl_error_inject *args = data;
+	xrtErrorCode err_code;
+	int ret = 0;
+
+	switch (args->err_ops) {
+	case ZOCL_ERROR_OP_INJECT:
+		err_code = XRT_ERROR_CODE_BUILD(
+		    args->err_num,
+		    args->err_driver,
+		    args->err_severity,
+		    args->err_module,
+		    args->err_class
+		    );
+
+		ret = zocl_insert_error_record(zdev, err_code);
+		break;
+
+	case ZOCL_ERROR_OP_CLEAR_ALL:
+		zocl_clear_all_error_record(zdev);
+		break;
+
+	default:
+		DRM_ERROR("Unknow error ioctl operation code: %d\n",
+		    args->err_ops);
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+int
+zocl_init_error(struct drm_zocl_dev *zdev)
+{
+	struct zocl_error *zer = &zdev->zdev_error;
+
+	zer->ze_num = 0;
+	zer->ze_cap = ZOCL_DEFAULT_ERROR_CAPACITY;
+
+	zer->ze_err = vzalloc(zer->ze_cap * sizeof(struct zocl_err_record));
+	if (!zer->ze_err) {
+		zer->ze_cap = 0;
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+void
+zocl_fini_error(struct drm_zocl_dev *zdev)
+{
+	struct zocl_error *zer = &zdev->zdev_error;
+
+	vfree(zer->ze_err);
+	zer->ze_err = NULL;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/zocl_ert.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/zocl_ert.c
@@ -0,0 +1,314 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * Copyright (C) 2016-2020 Xilinx, Inc. All rights reserved.
+ *
+ * Author(s):
+ *        Min Ma <min.ma@xilinx.com>
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+#include "ert.h"
+#include "zocl_ert.h"
+#include "zocl_util.h"
+#include "zocl_mailbox.h"
+
+#define ert_err(pdev, fmt, args...)  \
+	zocl_err(&pdev->dev, fmt"\n", ##args)
+#define ert_info(pdev, fmt, args...)  \
+	zocl_info(&pdev->dev, fmt"\n", ##args)
+#define ert_dbg(pdev, fmt, args...)  \
+	zocl_dbg(&pdev->dev, fmt"\n", ##args)
+
+struct ert_packet *
+get_packet(struct ert_packet *packet, u32 idx, u32 size)
+{
+	char *bytes = (char *)packet;
+
+	return (struct ert_packet *)(bytes + idx * size);
+}
+
+static void
+ert_mpsoc_init(struct zocl_ert_dev *ert)
+{
+	return;
+}
+
+static void
+ert_mpsoc_fini(struct zocl_ert_dev *ert)
+{
+	return;
+}
+
+static void
+ert_mpsoc_config(struct zocl_ert_dev *ert, struct ert_configure_cmd *cfg)
+{
+	char *ert_hw = ert->hw_ioremap;
+
+	/* Set slot size(4K) */
+	iowrite32(cfg->slot_size / 4, ert_hw + ERT_CQ_SLOT_SIZE_REG);
+
+	/* CU offset in shift value */
+	iowrite32(cfg->cu_shift, ert_hw + ERT_CU_OFFSET_REG);
+
+	/* Number of command slots */
+	iowrite32(CQ_SIZE / cfg->slot_size, ert_hw + ERT_CQ_NUM_OF_SLOTS_REG);
+
+	/* CU physical address */
+	/* TODO: Think about how to make the address mapping correct */
+	iowrite32(0x81800000/4, ert_hw + ERT_CU_BASE_ADDR_REG);
+
+	/* Command queue physical address */
+	iowrite32(0x80190000/4, ert_hw + ERT_CQ_BASE_ADDR_REG);
+
+	/* Number of CUs */
+	iowrite32(cfg->num_cus, ert_hw + ERT_NUM_OF_CU_REG);
+
+	/* Enable/Disable CU_DMA module */
+	iowrite32(cfg->cu_dma, ert_hw + ERT_CU_DMA_ENABLE);
+
+	if (cfg->cq_int)
+		iowrite32(1, ert_hw + ERT_CQ_STATUS_ENABLE);
+	else
+		iowrite32(0, ert_hw + ERT_CQ_STATUS_ENABLE);
+
+	/* Enable device to host interrupts */
+	iowrite32(1, ert_hw + ERT_HOST_INT_ENABLE);
+}
+
+static u32 cq_status[4];
+
+static struct ert_packet *
+ert_mpsoc_next(struct zocl_ert_dev *ert, struct ert_packet *pkg, int *idx_ret)
+{
+	char *ert_hw = ert->hw_ioremap;
+	int slot_idx, mask_idx, slot_tmp;
+	int slot_sz;
+	int i, found;
+	u64 slot_info;
+
+	slot_sz = ioread32(ert_hw + ERT_CQ_SLOT_SIZE_REG) * 4;
+	/* Calculate current slot index */
+	if (pkg == NULL) {
+		slot_idx = -1;
+		/* ERT CQ STATUS register is W/COR
+		 * Store all of the status
+		 * registers when getting the first command.
+		 */
+		cq_status[0] = ioread32(ert_hw + ERT_CQ_STATUS_REG0);
+		cq_status[1] = ioread32(ert_hw + ERT_CQ_STATUS_REG1);
+		cq_status[2] = ioread32(ert_hw + ERT_CQ_STATUS_REG2);
+		cq_status[3] = ioread32(ert_hw + ERT_CQ_STATUS_REG3);
+	} else {
+		/* ERT mode is only for 64 bits system */
+		slot_info = ((u64)pkg - (u64)ert->cq_ioremap);
+		do_div(slot_info, slot_sz);
+		slot_idx = slot_info;
+	}
+
+	/* Get mask index and local slot index for the next commmand */
+	slot_idx += 1;
+	mask_idx = slot_idx >> 5;
+	slot_tmp = slot_idx % 32;
+
+	found = 0;
+	for (i = mask_idx; i < 4; i++) {
+		while (cq_status[i] && (slot_tmp < 32)) {
+			if (cq_status[i] & (1 << slot_tmp)) {
+				found = 1;
+				cq_status[i] ^= (1 << slot_tmp);
+				break;
+			}
+			slot_tmp++;
+			slot_idx++;
+		}
+		if (found)
+			break;
+
+		slot_tmp = 0;
+	}
+
+	if (found) {
+		*idx_ret = slot_idx;
+		return get_packet(ert->cq_ioremap, slot_idx, slot_sz);
+	} else {
+		*idx_ret = -1;
+		return NULL;
+	}
+}
+
+static void ert_mpsoc_notify_host(struct zocl_ert_dev *ert, int slot_idx)
+{
+	u32 mask_idx = slot_idx >> 5;
+	u32 csr_offset = ERT_STATUS_REG + (mask_idx<<2);
+	u32 pos = slot_idx % 32;
+
+	iowrite32(1 << pos, ert->hw_ioremap + csr_offset);
+}
+
+/* ert versal ops */
+static void
+ert_versal_init(struct zocl_ert_dev *ert)
+{
+	return;
+}
+
+static void
+ert_versal_fini(struct zocl_ert_dev *ert)
+{
+	return;
+}
+
+static void
+ert_versal_config(struct zocl_ert_dev *ert, struct ert_configure_cmd *cfg)
+{
+	return;
+}
+
+static struct ert_packet *
+ert_versal_next(struct zocl_ert_dev *ert, struct ert_packet *pkg, int *idx_ret)
+{
+	return NULL;
+}
+
+static void
+ert_versal_notify_host(struct zocl_ert_dev *ert, int slot_idx)
+{
+	struct mailbox mbx;
+	u32 status = (u32)-1;
+	mbx.mbx_regs = (struct mailbox_reg *)ert->hw_ioremap;
+
+	while (1) {
+		status = zocl_mailbox_status(&mbx);
+		if (status == (u32)-1) {
+			ert_err(ert->pdev, "mailbox error: 0x%x", status);
+			break;
+		}
+
+		if ((status & MBX_STATUS_FULL) == 0) {
+			zocl_mailbox_set(&mbx, slot_idx);
+			break;
+		}
+	}
+}
+
+static void
+update_cmd(struct zocl_ert_dev *ert, int idx, void *data, int sz)
+{
+	struct ert_packet *pkg;
+	char *ert_hw = ert->hw_ioremap;
+	int slot_sz;
+
+	slot_sz = ioread32(ert_hw + ERT_CQ_SLOT_SIZE_REG) * 4;
+
+	pkg = ert->cq_ioremap + idx * slot_sz;
+	memcpy_toio(pkg->data, data, sz);
+}
+
+static struct zocl_ert_ops mpsoc_ops = {
+	.init         = ert_mpsoc_init,
+	.fini         = ert_mpsoc_fini,
+	.config       = ert_mpsoc_config,
+	.get_next_cmd = ert_mpsoc_next,
+	.notify_host  = ert_mpsoc_notify_host,
+	.update_cmd   = update_cmd,
+};
+
+static struct zocl_ert_ops versal_ops = {
+	.init         = ert_versal_init,
+	.fini         = ert_versal_fini,
+	.config       = ert_versal_config,
+	.get_next_cmd = ert_versal_next,
+	.notify_host  = ert_versal_notify_host,
+	.update_cmd   = update_cmd,
+};
+
+static const struct zocl_ert_info mpsoc_ert_info = {
+	.ops   = &mpsoc_ops,
+};
+
+static const struct zocl_ert_info versal_ert_info = {
+	.ops   = &versal_ops,
+};
+
+static const struct of_device_id zocl_ert_of_match[] = {
+	{ .compatible = "xlnx,embedded_sched",
+	  .data = &mpsoc_ert_info,
+	},
+	{ .compatible = "xlnx,embedded_sched_versal",
+	  .data = &versal_ert_info,
+	},
+	{ /* end of table */ },
+};
+
+MODULE_DEVICE_TABLE(of, zocl_ert_of_match);
+
+static int zocl_ert_probe(struct platform_device *pdev)
+{
+	struct zocl_ert_dev *ert;
+	const struct of_device_id *id;
+	struct resource *res;
+	const struct zocl_ert_info *info;
+	void __iomem *map;
+
+	id = of_match_node(zocl_ert_of_match, pdev->dev.of_node);
+	ert_info(pdev, "Probing for %s", id->compatible);
+
+	ert = devm_kzalloc(&pdev->dev, sizeof(*ert), GFP_KERNEL);
+	ert->pdev = pdev;
+
+	info = of_device_get_match_data(&pdev->dev);
+	ert->ops = info->ops;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, ZOCL_ERT_HW_RES);
+	map = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(map)) {
+		ert_err(pdev, "Failed to map ERT HW registers: %0lx",
+				PTR_ERR(map));
+		return PTR_ERR(map);
+	}
+	ert->hw_ioremap = map;
+	ert_info(pdev, "IP(embedded_scheduler_hw) IO start %lx, end %lx",
+	      (unsigned long)res->start, (unsigned long)res->end);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, ZOCL_ERT_CQ_RES);
+	map = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(map)) {
+		ert_err(pdev, "Failed to map Command Queue: %0lx",
+				PTR_ERR(map));
+		return PTR_ERR(map);
+	}
+	ert->cq_ioremap = map;
+	ert_info(pdev, "Command Queue IO start %lx, end %lx",
+		(unsigned long)res->start, (unsigned long)res->end);
+
+	/* Initial CQ */
+	memset_io(ert->cq_ioremap, 0, res->end - res->start + 1);
+
+	ert->irq[ERT_CQ_IRQ] = platform_get_irq(pdev, ERT_CQ_IRQ);
+	ert->irq[ERT_CU_IRQ] = platform_get_irq(pdev, ERT_CU_IRQ);
+	ert_info(pdev, "CQ irq %d, CU irq %d", ert->irq[ERT_CQ_IRQ],
+			ert->irq[ERT_CU_IRQ]);
+
+	if (info->ops == NULL) {
+		ert_err(pdev, "zocl ert probe failed due to ops has not been set");
+		return -ENODEV;
+	}
+	platform_set_drvdata(pdev, ert);
+	return 0;
+}
+
+static int zocl_ert_remove(struct platform_device *pdev)
+{
+	ert_dbg(pdev, "Release resource");
+	return 0;
+}
+
+struct platform_driver zocl_ert_driver = {
+	.driver = {
+		.name = ZOCL_ERT_NAME,
+		.of_match_table = zocl_ert_of_match,
+	},
+	.probe  = zocl_ert_probe,
+	.remove = zocl_ert_remove,
+};
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/zocl_generic_cu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/zocl_generic_cu.c
@@ -0,0 +1,201 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * MPSoC based OpenCL accelerators Generic Compute Units.
+ *
+ * Copyright (C) 2020 Xilinx, Inc. All rights reserved.
+ *
+ * Authors:
+ *    Min Ma      <min.ma@xilinx.com>
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#include <drm/drm_print.h>
+#include <linux/anon_inodes.h>
+#include <linux/poll.h>
+#include "zocl_util.h"
+#include "sched_exec.h"
+#include "zocl_generic_cu.h"
+
+#define WAIT_CONDITION (atomic_read(&gcu->event) > 0)
+
+static int generic_cu_release(struct inode *inode, struct file *filp)
+{
+	struct generic_cu *gcu = filp->private_data;
+	struct generic_cu_info *info = gcu->info;
+	int ret;
+
+	free_irq(info->irq, gcu);
+	ret = sched_attach_cu(gcu->zdev, info->cu_idx);
+	if (ret < 0)
+		DRM_WARN("Scheduler attach CU[%d] failed.\n", info->cu_idx);
+
+	kfree(info->name);
+	kfree(info);
+	kfree(gcu);
+	return 0;
+}
+
+static __poll_t generic_cu_poll(struct file *filp, poll_table *wait)
+{
+	struct generic_cu *gcu = filp->private_data;
+	__poll_t ret = 0;
+
+	poll_wait(filp, &gcu->waitq, wait);
+
+	if (atomic_read(&gcu->event) > 0)
+		ret = POLLIN;
+
+	return ret;
+}
+
+static ssize_t generic_cu_read(struct file *filp, char __user *buf,
+			       size_t count, loff_t *ppos)
+{
+	struct generic_cu *gcu = filp->private_data;
+	ssize_t ret = 0;
+	s32 events = 0;
+
+	if (count != sizeof(s32))
+		return -EINVAL;
+
+	ret = wait_event_interruptible(gcu->waitq, WAIT_CONDITION);
+	if (ret == -ERESTARTSYS)
+		return 0;
+
+	/* This could be different from when it just wake up.
+	 * But it is okay, since this is the only place reset event count.
+	 */
+	events = atomic_xchg(&gcu->event, 0);
+	if (copy_to_user(buf, &events, count))
+		return -EFAULT;
+
+	return sizeof(events);
+}
+
+static ssize_t generic_cu_write(struct file *filp, const char __user *buf,
+				size_t count, loff_t *ppos)
+{
+	struct generic_cu *gcu = filp->private_data;
+	unsigned long flags;
+	s32 enable;
+
+	if (count != sizeof(s32))
+		return -EINVAL;
+
+	if (copy_from_user(&enable, buf, count))
+		return -EFAULT;
+
+	if (!gcu->info)
+		return -EINVAL;
+
+	spin_lock_irqsave(&gcu->lock, flags);
+	if (enable) {
+		if (__test_and_clear_bit(GCU_IRQ_DISABLED, &gcu->flag))
+			enable_irq(gcu->info->irq);
+	} else {
+		if (!__test_and_set_bit(GCU_IRQ_DISABLED, &gcu->flag))
+			disable_irq(gcu->info->irq);
+	}
+	spin_unlock_irqrestore(&gcu->lock, flags);
+
+	return sizeof(s32);
+}
+
+static const struct file_operations generic_cu_fops = {
+	.release	= generic_cu_release,
+	.poll		= generic_cu_poll,
+	.read		= generic_cu_read,
+	.write		= generic_cu_write,
+	.llseek		= noop_llseek,
+};
+
+static irqreturn_t generic_cu_isr(int irq, void *arg)
+{
+	struct generic_cu *gcu = arg;
+	unsigned long flags;
+
+	spin_lock_irqsave(&gcu->lock, flags);
+	atomic_inc(&gcu->event);
+	/* To handle level interrupt, have to disable this irq line.
+	 * We could esaily support edge interrupt if needed.
+	 * Like, provide one more gcu->flag to permanently enabl irq.
+	 */
+	if (!__test_and_set_bit(GCU_IRQ_DISABLED, &gcu->flag))
+		disable_irq_nosync(irq);
+	spin_unlock_irqrestore(&gcu->lock, flags);
+
+	wake_up_interruptible(&gcu->waitq);
+
+	return IRQ_HANDLED;
+}
+
+int _open_generic_cu(struct drm_zocl_dev *zdev, struct generic_cu_info *info)
+{
+	struct generic_cu *gcu;
+	int fd;
+	int ret;
+
+	gcu = kzalloc(sizeof(*gcu), GFP_KERNEL);
+	if (!gcu)
+		return -ENOMEM;
+
+	/* Do not use IRQF_SHARED! */
+	ret = request_irq(info->irq, generic_cu_isr, 0, info->name, gcu);
+	if (ret) {
+		DRM_INFO("%s: request_irq() failed\n", __func__);
+		return ret;
+	}
+
+	__set_bit(GCU_IRQ_DISABLED, &gcu->flag);
+	disable_irq(info->irq);
+
+	init_waitqueue_head(&gcu->waitq);
+	gcu->zdev = zdev;
+	gcu->info = info;
+	atomic_set(&gcu->event, 0);
+	spin_lock_init(&gcu->lock);
+
+	fd = anon_inode_getfd("[generic_cu]", &generic_cu_fops, gcu, O_RDWR);
+	if (fd < 0)
+		kfree(gcu);
+
+	return fd;
+}
+
+int zocl_open_gcu(struct drm_zocl_dev *zdev, struct drm_zocl_ctx *ctx,
+		  struct sched_client_ctx *client)
+{
+	struct generic_cu_info *info;
+	char *name;
+	int ret;
+
+	/* Check if the CU is exclusively reserved */
+	ret = test_bit(ctx->cu_index, client->excus);
+	if (!ret) {
+		DRM_WARN("%s: CU[%d] is not exclusive\n",
+			 __func__, ctx->cu_index);
+		return -EINVAL;
+	}
+
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	name = kzalloc(40, GFP_KERNEL);
+	if (!name)
+		return -ENOMEM;
+
+	ret = sched_detach_cu(zdev, ctx->cu_index);
+	if (ret)
+		return ret;
+
+	sprintf(name, "zocl_generic_cu[%d]", ctx->cu_index);
+	info->name = name;
+	info->cu_idx = ctx->cu_index;
+	/* TODO: We have better not use exec here. Refine this in new KDS */
+	info->irq    = zdev->exec->zcu[ctx->cu_index].irq;
+
+	return _open_generic_cu(zdev, info);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/zocl_ioctl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/zocl_ioctl.c
@@ -0,0 +1,165 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * A GEM style (optionally CMA backed) device manager for ZynQ based
+ * OpenCL accelerators.
+ *
+ * Copyright (C) 2016-2020 Xilinx, Inc. All rights reserved.
+ *
+ * Authors:
+ *    Sonal Santan <sonal.santan@xilinx.com>
+ *    Jan Stephan  <j.stephan@hzdr.de>
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#include "sched_exec.h"
+#include "zocl_xclbin.h"
+#include "zocl_generic_cu.h"
+#include "zocl_error.h"
+
+extern int kds_mode;
+
+/* TODO: remove this once new KDS is ready */
+int zocl_xclbin_ctx(struct drm_zocl_dev *zdev, struct drm_zocl_ctx *ctx,
+		    struct sched_client_ctx *client);
+
+/*
+ * read_axlf and ctx should be protected by zdev_xclbin_lock exclusively.
+ */
+int
+zocl_read_axlf_ioctl(struct drm_device *ddev, void *data, struct drm_file *filp)
+{
+	struct drm_zocl_axlf *axlf_obj = data;
+	struct drm_zocl_dev *zdev = ZOCL_GET_ZDEV(ddev);
+	int ret;
+
+	mutex_lock(&zdev->zdev_xclbin_lock);
+	ret = zocl_xclbin_read_axlf(zdev, axlf_obj);
+	mutex_unlock(&zdev->zdev_xclbin_lock);
+
+	return ret;
+}
+
+/*
+ * Block comment for context switch.
+ * The read_axlf_ioctl can happen without calling open context, we need to use mutex
+ * lock to exclude access between read_axlf_ioctl and zocl_ctx_ioctl. At one
+ * time, only one operation can be accessed.
+ *
+ * When swaping xclbin, first call read_axlf_ioctl to download new xclbin, the
+ * following conditions have to be true:
+ *   -  When we lock the zdev_xclbin_lock, no more zocl_ctx/read_axlf
+ *   -  If still have live context, we cannot swap xclbin
+ *   -  If no live contexts, but still live cmds from previous closed context,
+ *      we cannot swap xclbin.
+ * If all the above conditions is cleared, we start changing to new xclbin.
+ */
+int
+zocl_ctx_ioctl(struct drm_device *ddev, void *data, struct drm_file *filp)
+{
+	struct drm_zocl_ctx *args = data;
+	struct drm_zocl_dev *zdev = ZOCL_GET_ZDEV(ddev);
+	int ret = 0;
+
+	if (kds_mode == 1) {
+		return zocl_context_ioctl(zdev, data, filp);
+	}
+
+	if (args->op == ZOCL_CTX_OP_OPEN_GCU_FD) {
+		ret = zocl_open_gcu(zdev, args, filp->driver_priv);
+		return ret;
+	}
+
+	mutex_lock(&zdev->zdev_xclbin_lock);
+	ret = zocl_xclbin_ctx(zdev, args, filp->driver_priv);
+	mutex_unlock(&zdev->zdev_xclbin_lock);
+
+	return ret;
+}
+
+/* IOCTL to get CU index in aperture list
+ * used for recognizing BO and CU in mmap
+ */
+int
+zocl_info_cu_ioctl(struct drm_device *ddev, void *data, struct drm_file *filp)
+{
+	struct drm_zocl_info_cu *args = data;
+	struct drm_zocl_dev *zdev = ddev->dev_private;
+	struct sched_exec_core *exec = zdev->exec;
+	struct addr_aperture *apts = zdev->apertures;
+	int apt_idx = args->apt_idx;
+	int cu_idx = args->cu_idx;
+	phys_addr_t addr = args->paddr;
+
+	if (kds_mode == 0 && !exec->configured) {
+		DRM_ERROR("Schduler is not configured\n");
+		return -EINVAL;
+	}
+
+	if (cu_idx != -1) {
+		apt_idx = get_apt_index_by_cu_idx(zdev, cu_idx);
+		if (apt_idx != -EINVAL) {
+			addr = apts[apt_idx].addr;
+			goto out;
+		}
+	}
+
+	apt_idx = get_apt_index_by_addr(zdev, args->paddr);
+	if (apt_idx != -EINVAL)
+		cu_idx = apts[apt_idx].cu_idx;
+
+out:
+	args->paddr = addr;
+	args->apt_idx = apt_idx;
+	args->cu_idx = cu_idx;
+	return 0;
+}
+
+int
+zocl_execbuf_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
+{
+	struct drm_zocl_dev *zdev = dev->dev_private;
+	int ret = 0;
+
+	if (kds_mode == 1)
+		ret = zocl_command_ioctl(zdev, data, filp);
+	else
+		ret = zocl_execbuf_exec(dev, data, filp);
+
+	return ret;
+}
+
+int
+zocl_error_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
+{
+	struct drm_zocl_dev *zdev = dev->dev_private;
+	int ret;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EACCES;
+
+	ret = zocl_inject_error(zdev, data, filp);
+	return ret;
+}
+
+int
+zocl_aie_fd_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
+{
+	struct drm_zocl_aie *args = data;
+	struct drm_zocl_dev *zdev = ZOCL_GET_ZDEV(dev);
+	int ret = 0;
+
+	ret = zocl_aie_request_part_fd(zdev, args);
+	return ret;
+}
+
+int
+zocl_aie_reset_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
+{
+	struct drm_zocl_dev *zdev = ZOCL_GET_ZDEV(dev);
+	int ret;
+
+	ret = zocl_aie_reset(zdev);
+	return ret;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/zocl_kds.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/zocl_kds.c
@@ -0,0 +1,419 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * Copyright (C) 2020 Xilinx, Inc. All rights reserved.
+ *
+ * Author(s):
+ *        Min Ma <min.ma@xilinx.com>
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#include <linux/sched/signal.h>
+#include "zocl_drv.h"
+#include "zocl_util.h"
+#include "zocl_xclbin.h"
+#include "kds_core.h"
+#include "xclbin.h"
+
+#define print_ecmd_info(ecmd) \
+do {\
+	int i;\
+	printk("%s: ecmd header 0x%x\n", __func__, ecmd->header);\
+	for (i = 0; i < ecmd->count; i++) {\
+		printk("%s: ecmd data[%d] 0x%x\n", __func__, i, ecmd->data[i]);\
+	}\
+} while(0)
+
+int kds_mode = 0;
+module_param(kds_mode, int, (S_IRUGO|S_IWUSR));
+MODULE_PARM_DESC(kds_mode,
+		 "enable new KDS (0 = disable (default), 1 = enable)");
+
+int kds_echo = 0;
+
+static inline void
+zocl_ctx_to_info(struct drm_zocl_ctx *args, struct kds_ctx_info *info)
+{
+	if (args->cu_index == ZOCL_CTX_VIRT_CU_INDEX)
+		info->cu_idx = CU_CTX_VIRT_CU;
+	else
+		info->cu_idx = args->cu_index;
+
+	/* Ignore ZOCL_CTX_SHARED bit if ZOCL_CTX_EXCLUSIVE bit is set */
+	if (args->flags & ZOCL_CTX_EXCLUSIVE)
+		info->flags = CU_CTX_EXCLUSIVE;
+	else
+		info->flags = CU_CTX_SHARED;
+}
+
+static int
+zocl_add_context(struct drm_zocl_dev *zdev, struct kds_client *client,
+		 struct drm_zocl_ctx *args)
+{
+	struct kds_ctx_info info;
+	void *uuid_ptr = (void *)(uintptr_t)args->uuid_ptr;
+	uuid_t *id;
+	int ret;
+
+	id = vmalloc(sizeof(uuid_t));
+	if (!id)
+		return -ENOMEM;
+
+	ret = copy_from_user(id, uuid_ptr, sizeof(uuid_t));
+	if (ret) {
+		vfree(id);
+		return ret;
+	}
+
+	mutex_lock(&client->lock);
+	if (!client->num_ctx) {
+		ret = zocl_lock_bitstream(zdev, id);
+		if (ret)
+			goto out;
+		client->xclbin_id = vzalloc(sizeof(*id));
+		if (!client->xclbin_id) {
+			ret = -ENOMEM;
+			goto out;
+		}
+		uuid_copy(client->xclbin_id, id);
+	}
+
+	/* Bitstream is locked. No one could load a new one
+	 * until this client close all of the contexts.
+	 */
+	zocl_ctx_to_info(args, &info);
+	ret = kds_add_context(&zdev->kds, client, &info);
+
+out:
+	if (!client->num_ctx) {
+		vfree(client->xclbin_id);
+		client->xclbin_id = NULL;
+		(void) zocl_unlock_bitstream(zdev, id);
+	}
+	mutex_unlock(&client->lock);
+	vfree(id);
+	return ret;
+}
+
+static int
+zocl_del_context(struct drm_zocl_dev *zdev, struct kds_client *client,
+		 struct drm_zocl_ctx *args)
+{
+	struct kds_ctx_info info;
+	void *uuid_ptr = (void *)(uintptr_t)args->uuid_ptr;
+	uuid_t *id;
+	uuid_t *uuid;
+	int ret;
+
+	id = vmalloc(sizeof(uuid_t));
+	if (!id)
+		return -ENOMEM;
+
+	ret = copy_from_user(id, uuid_ptr, sizeof(uuid_t));
+	if (ret) {
+		vfree(id);
+		return ret;
+	}
+
+	mutex_lock(&client->lock);
+	uuid = client->xclbin_id;
+	/* xclCloseContext() would send xclbin_id and cu_idx.
+	 * Be more cautious while delete. Do sanity check
+	 */
+	if (!uuid) {
+		DRM_ERROR("No context was opened");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* If xclbin id looks good, unlock bitstream should not fail. */
+	if (!uuid_equal(uuid, id)) {
+		DRM_ERROR("Try to delete CTX on wrong xclbin");
+		ret = -EBUSY;
+		goto out;
+	}
+
+	zocl_ctx_to_info(args, &info);
+	ret = kds_del_context(&zdev->kds, client, &info);
+	if (ret)
+		goto out;
+
+	if (!client->num_ctx) {
+		vfree(client->xclbin_id);
+		client->xclbin_id = NULL;
+		(void) zocl_unlock_bitstream(zdev, id);
+	}
+
+out:
+	mutex_unlock(&client->lock);
+	vfree(id);
+	return ret;
+}
+
+int zocl_context_ioctl(struct drm_zocl_dev *zdev, void *data,
+		       struct drm_file *filp)
+{
+	struct drm_zocl_ctx *args = data;
+	struct kds_client *client = filp->driver_priv;
+	int ret = 0;
+
+	switch (args->op) {
+	case ZOCL_CTX_OP_ALLOC_CTX:
+		ret = zocl_add_context(zdev, client, args);
+		break;
+	case ZOCL_CTX_OP_FREE_CTX:
+		ret = zocl_del_context(zdev, client, args);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static void notify_execbuf(struct kds_command *xcmd, int status)
+{
+	struct kds_client *client = xcmd->client;
+	struct ert_packet *ecmd = (struct ert_packet *)xcmd->execbuf;
+
+	if (status == KDS_COMPLETED)
+		ecmd->state = ERT_CMD_STATE_COMPLETED;
+	else if (status == KDS_ERROR)
+		ecmd->state = ERT_CMD_STATE_ERROR;
+	else if (status == KDS_TIMEOUT)
+		ecmd->state = ERT_CMD_STATE_TIMEOUT;
+	else if (status == KDS_ABORT)
+		ecmd->state = ERT_CMD_STATE_ABORT;
+
+	ZOCL_DRM_GEM_OBJECT_PUT_UNLOCKED(xcmd->gem_obj);
+
+	atomic_inc(&client->event);
+	wake_up_interruptible(&client->waitq);
+}
+
+int zocl_command_ioctl(struct drm_zocl_dev *zdev, void *data,
+		       struct drm_file *filp)
+{
+	struct drm_gem_object *gem_obj;
+	struct drm_device *dev = zdev->ddev;
+	struct drm_zocl_execbuf *args = data;
+	struct kds_client *client = filp->driver_priv;
+	struct drm_zocl_bo *zocl_bo;
+	struct ert_packet *ecmd;
+	struct kds_command *xcmd;
+	int ret = 0;
+
+	if (!client->xclbin_id) {
+		DRM_ERROR("The client has no opening context\n");
+		return -EINVAL;
+	}
+
+	if (zdev->kds.bad_state) {
+		DRM_ERROR("KDS is in bad state\n");
+		return -EDEADLK;
+	}
+
+	gem_obj = zocl_gem_object_lookup(dev, filp, args->exec_bo_handle);
+	if (!gem_obj) {
+		DRM_ERROR("Look up GEM BO %d failed\n", args->exec_bo_handle);
+		return -EINVAL;
+	}
+
+	zocl_bo = to_zocl_bo(gem_obj);
+	if (!zocl_bo_execbuf(zocl_bo)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ecmd = (struct ert_packet *)zocl_bo->cma_base.vaddr;
+
+	ecmd->state = ERT_CMD_STATE_NEW;
+	/* only the user command knows the real size of the payload.
+	 * count is more than enough!
+	 */
+	xcmd = kds_alloc_command(client, ecmd->count * sizeof(u32));
+	if (!xcmd) {
+		DRM_ERROR("Failed to alloc xcmd\n");
+		ret = -ENOMEM;
+		goto out;
+	}
+	xcmd->cb.free = kds_free_command;
+
+	//print_ecmd_info(ecmd);
+
+	/* TODO: one ecmd to one xcmd now. Maybe we will need
+	 * one ecmd to multiple xcmds
+	 */
+	if (ecmd->opcode == ERT_CONFIGURE)
+		cfg_ecmd2xcmd(to_cfg_pkg(ecmd), xcmd);
+	else if (ecmd->opcode == ERT_START_CU)
+		start_krnl_ecmd2xcmd(to_start_krnl_pkg(ecmd), xcmd);
+	else if (ecmd->opcode == ERT_START_FA)
+		start_fa_ecmd2xcmd(to_start_krnl_pkg(ecmd), xcmd);
+	xcmd->cb.notify_host = notify_execbuf;
+	xcmd->gem_obj = gem_obj;
+
+	/* Now, we could forget execbuf */
+	ret = kds_add_command(&zdev->kds, xcmd);
+
+out:
+	return ret;
+}
+
+uint zocl_poll_client(struct file *filp, poll_table *wait)
+{
+	struct drm_file *priv = filp->private_data;
+	struct kds_client *client = (struct kds_client *)priv->driver_priv;
+	int event;
+
+	poll_wait(filp, &client->waitq, wait);
+
+	event = atomic_dec_if_positive(&client->event);
+	if (event == -1)
+		return 0;
+
+	return POLLIN;
+}
+
+int zocl_create_client(struct drm_zocl_dev *zdev, void **priv)
+{
+	struct kds_client *client;
+	struct kds_sched  *kds;
+	struct drm_device *ddev;
+	int ret = 0;
+
+	client = kzalloc(sizeof(*client), GFP_KERNEL);
+	if (!client)
+		return -ENOMEM;
+
+	ddev = zdev->ddev;
+
+	kds = &zdev->kds;
+	client->dev = ddev->dev;
+	ret = kds_init_client(kds, client);
+	if (ret) {
+		kfree(client);
+		goto out;
+	}
+	*priv = client;
+
+out:
+	zocl_info(ddev->dev, "created KDS client for pid(%d), ret: %d\n",
+		  pid_nr(task_tgid(current)), ret);
+
+	return ret;
+}
+
+void zocl_destroy_client(struct drm_zocl_dev *zdev, void **priv)
+{
+	struct kds_client *client = *priv;
+	struct kds_sched  *kds;
+	struct drm_device *ddev;
+	int pid = pid_nr(client->pid);
+
+	ddev = zdev->ddev;
+
+	kds = &zdev->kds;
+	/* kds_fini_client should released resources hold by the client.
+	 * release xclbin_id and unlock bitstream if needed.
+	 */
+	kds_fini_client(kds, client);
+	if (client->xclbin_id) {
+		(void) zocl_unlock_bitstream(zdev, client->xclbin_id);
+		vfree(client->xclbin_id);
+	}
+
+	/* Make sure all resources of the client are released */
+	kfree(client);
+	zocl_info(ddev->dev, "client exits pid(%d)\n", pid);
+}
+
+int zocl_init_sched(struct drm_zocl_dev *zdev)
+{
+	return kds_init_sched(&zdev->kds);
+}
+
+void zocl_fini_sched(struct drm_zocl_dev *zdev)
+{
+	struct drm_zocl_bo *bo = NULL;
+
+	bo = zdev->kds.plram.bo;
+	if (bo)
+		zocl_drm_free_bo(bo);
+	zdev->kds.plram.bo = NULL;
+
+	kds_fini_sched(&zdev->kds);
+}
+
+static void zocl_detect_fa_plram(struct drm_zocl_dev *zdev)
+{
+	struct ip_layout    *ip_layout = NULL;
+	struct drm_zocl_bo *bo = NULL;
+	struct drm_zocl_create_bo args;
+	int i;
+	uint64_t size;
+	uint64_t base_addr;
+	void __iomem *vaddr;
+	ulong bar_paddr = 0;
+
+	/* Detect Fast adapter */
+	ip_layout = zdev->ip;
+
+	for (i = 0; i < ip_layout->m_count; ++i) {
+		struct ip_data *ip = &ip_layout->m_ip_data[i];
+		u32 prot;
+
+		if (ip->m_type != IP_KERNEL)
+			continue;
+
+		prot = (ip->properties & IP_CONTROL_MASK) >> IP_CONTROL_SHIFT;
+		if (prot != FAST_ADAPTER)
+			continue;
+
+		break;
+	}
+
+	if (i == ip_layout->m_count)
+		return;
+
+	/* TODO: logic to dynamicly select size */
+	size = 4096;
+
+	args.size = size;
+	args.flags = ZOCL_BO_FLAGS_CMA;
+	bo = zocl_drm_create_bo(zdev->ddev, size, args.flags);
+	if (IS_ERR(bo))
+		return;
+
+	
+	bar_paddr = (uint64_t)bo->cma_base.paddr;	
+	base_addr = (uint64_t)bo->cma_base.paddr;	
+	vaddr = bo->cma_base.vaddr;	
+
+	zdev->kds.plram.bo = bo;
+	zdev->kds.plram.bar_paddr = bar_paddr;
+	zdev->kds.plram.dev_paddr = base_addr;
+	zdev->kds.plram.vaddr = vaddr;
+	zdev->kds.plram.size = size;
+}
+
+int zocl_kds_update(struct drm_zocl_dev *zdev)
+{
+	struct drm_zocl_bo *bo = NULL;
+
+	if (zdev->kds.plram.bo) {
+		bo = zdev->kds.plram.bo;
+		zocl_drm_free_bo(bo);
+		zdev->kds.plram.bo = NULL;
+		zdev->kds.plram.bar_paddr = 0;
+		zdev->kds.plram.dev_paddr = 0;
+		zdev->kds.plram.vaddr = 0;
+		zdev->kds.plram.size = 0;
+	}
+
+	zocl_detect_fa_plram(zdev);
+	zdev->kds.cu_intr = 0;
+	return kds_cfg_update(&zdev->kds);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/zocl_mailbox.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/zocl_mailbox.c
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * A GEM style (optionally CMA backed) device manager for ZynQ based
+ * OpenCL accelerators.
+ *
+ * Copyright (C) 2019 Xilinx, Inc. All rights reserved.
+ *
+ * Authors:
+ *    Larry Liu       <yliu@xilinx.com>
+ *    David Zhang     <davidzha@xilinx.com>
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#include "ert.h"
+#include "zocl_drv.h"
+#include "zocl_mailbox.h"
+
+static inline const char *
+reg2name(struct mailbox *mbx, u32 *reg)
+{
+	const char *reg_names[] = {
+		"wrdata",
+		"reserved1",
+		"rddata",
+		"reserved2",
+		"status",
+		"error",
+		"sit",
+		"rit",
+		"is",
+		"ie",
+		"ip",
+		"ctrl"
+	};
+
+	return reg_names[((uintptr_t)reg -
+		(uintptr_t)mbx->mbx_regs) / sizeof(u32)];
+}
+
+static inline u32
+mailbox_reg_read(u32 *reg)
+{
+	return ioread32(reg);
+}
+
+static inline void
+mailbox_reg_write(u32 *reg, u32 val)
+{
+	iowrite32(val, reg);
+}
+
+u32
+zocl_mailbox_status(struct mailbox *mbx)
+{
+	return mailbox_reg_read(&mbx->mbx_regs->mbr_status);
+}
+
+u32
+zocl_mailbox_get(struct mailbox *mbx)
+{
+	return mailbox_reg_read(&mbx->mbx_regs->mbr_rddata);
+}
+
+void
+zocl_mailbox_set(struct mailbox *mbx, u32 val)
+{
+	mailbox_reg_write(&mbx->mbx_regs->mbr_wrdata, val);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/zocl_ospi_versal.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/zocl_ospi_versal.c
@@ -0,0 +1,509 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * A GEM style (optionally CMA backed) device manager for ZynQ based
+ * OpenCL accelerators.
+ *
+ * Copyright (C) 2019-2020 Xilinx, Inc. All rights reserved.
+ *
+ * Authors:
+ *    Larry Liu <yliu@xilinx.com>
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/platform_device.h>
+
+#include "zocl_drv.h"
+#include "xrt_drv.h"
+#include "sched_exec.h"
+#include "zocl_xclbin.h"
+#include "zocl_ospi_versal.h"
+
+#define ov_err(pdev, fmt, args...)  \
+	zocl_err(&pdev->dev, fmt"\n", ##args)
+#define ov_info(pdev, fmt, args...)  \
+	zocl_info(&pdev->dev, fmt"\n", ##args)
+#define ov_dbg(pdev, fmt, args...)  \
+	zocl_dbg(&pdev->dev, fmt"\n", ##args)
+
+static inline u32 wait_for_status(struct zocl_ov_dev *ov, u8 status)
+{
+	u32 header;
+	struct pdi_packet *pkt = (struct pdi_packet *)&header;
+
+	for (;;) {
+		header = ioread32(ov->base);
+		if (pkt->pkt_status == status)
+			break;
+	}
+
+	return header;
+}
+
+static inline u8 get_pkt_flags(struct zocl_ov_dev *ov)
+{
+	struct pdi_packet *pkt;
+	u32 header;
+
+	pkt = (struct pdi_packet *)&header;
+	header = ioread32(ov->base);
+	return pkt->pkt_flags;
+}
+
+static inline bool check_for_status(struct zocl_ov_dev *ov, u8 status)
+{
+	struct pdi_packet *pkt;
+	u32 header;
+
+	pkt = (struct pdi_packet *)&header;
+	header = ioread32(ov->base);
+	return (pkt->pkt_status == status);
+}
+
+static inline void set_flags(struct zocl_ov_dev *ov, u8 flags)
+{
+	struct pdi_packet *pkt;
+	u32 header;
+
+	pkt = (struct pdi_packet *)&header;
+	header = ioread32(ov->base);
+	pkt->pkt_flags = flags;
+
+	iowrite32(pkt->header, ov->base);
+}
+
+static inline void set_version(struct zocl_ov_dev *ov)
+{
+	set_flags(ov, XRT_XFR_VER <<  XRT_XFR_PKT_VER_SHIFT);
+}
+
+static inline void set_status(struct zocl_ov_dev *ov, u8 status)
+{
+	struct pdi_packet *pkt;
+	u32 header;
+
+	pkt = (struct pdi_packet *)&header;
+	header = ioread32(ov->base);
+	pkt->pkt_status = status;
+
+	iowrite32(pkt->header, ov->base);
+}
+
+static inline void read_data(u32 *addr, u32 *data, size_t sz)
+{
+	int i;
+
+	for (i = 0; i < sz; ++i)
+		*(data + i) = ioread32(addr + i);
+}
+
+static void zocl_ov_clean(struct zocl_ov_dev *ov)
+{
+	struct zocl_ov_pkt_node *node;
+	struct zocl_ov_pkt_node *pnode;
+
+	node = ov->head;
+	while (node != NULL) {
+		pnode = node;
+		node = pnode->zn_next;
+		vfree(pnode->zn_datap);
+		vfree(pnode);
+	}
+
+	ov->head = NULL;
+}
+
+static int zocl_ov_find_parent_dev(struct zocl_ov_dev *ov)
+{
+	struct platform_device *parent_dev;
+
+	parent_dev = zocl_find_pdev("zyxclmm_drm");
+	if (parent_dev) {
+		ov_info(ov->pdev, "Found parent pdev zyxclmm_drv: 0x%llx",
+		    (uint64_t)(uintptr_t)parent_dev);
+		ov->ppdev = parent_dev;
+		return 0;
+	}
+
+	ov_err(ov->pdev, "Can NOT find parent pdev zyxclmm_drv");
+
+	ov->ppdev = NULL;
+	return -ENXIO;
+}
+
+static int zocl_ov_copy_xclbin(struct zocl_ov_dev *ov, struct axlf **xclbin)
+{
+	struct zocl_ov_pkt_node *node = ov->head;
+	char *xp;
+	size_t len = 0;
+
+	while (node) {
+		len += node->zn_size;
+		node = node->zn_next;
+	}
+
+	if (len == 0) {
+		ov_err(ov->pdev, "Load xclbin failed: size is 0");
+		return -EINVAL;
+	}
+
+	*xclbin = vmalloc(len);
+	if (!(*xclbin)) {
+		ov_err(ov->pdev, "Load xclbin failed to allocate buf");
+		return -ENOMEM;
+	}
+
+	xp = (char *)*xclbin;
+	node = ov->head;
+	while (node) {
+		memcpy(xp, node->zn_datap, node->zn_size);
+		xp += node->zn_size;
+		node = node->zn_next;
+	}
+
+	return 0;
+}
+
+static int zocl_ov_recieve(struct zocl_ov_dev *ov)
+{
+	struct zocl_ov_pkt_node *node = ov->head;
+	u32 *base = ov->base;
+	int len = 0, next = 0;
+	int ret;
+
+	for (;;) {
+		u32 pkt_header;
+		struct pdi_packet *pkt = (struct pdi_packet *)&pkt_header;
+		struct zocl_ov_pkt_node *new;
+
+		/* Busy wait here until we get a new packet */
+		pkt_header = wait_for_status(ov, XRT_XFR_PKT_STATUS_NEW);
+
+		new = vzalloc(sizeof(struct zocl_ov_pkt_node));
+		if (!new) {
+			ret = -ENOMEM;
+			break;
+		}
+		new->zn_datap = vmalloc(ov->size);
+		if (!new->zn_datap) {
+			ret = -ENOMEM;
+			break;
+		}
+		new->zn_size = pkt->pkt_size;
+
+		/* Read packet data payload on a 4 bytes base */
+		read_data(base + (sizeof(struct pdi_packet)) / 4,
+		    new->zn_datap, (ov->size - sizeof(struct pdi_packet)) / 4);
+
+		/* Notify host that the data has been read */
+		set_status(ov, XRT_XFR_PKT_STATUS_IDLE);
+
+		len += ov->size;
+		if ((len / 1000000) > next) {
+			ov_dbg(ov->pdev, "%d M", len / 1000000);
+			next++;
+		}
+
+		/* Add packet data to linked list */
+		if (node)
+			node->zn_next = new;
+		else
+			ov->head = new;
+		node = new;
+
+		/* Bail out here if this is the last packet */
+		if (pkt->pkt_flags & XRT_XFR_PKT_FLAGS_LAST) {
+			ret = 0;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+/*
+ * This function is called once we detect there is a new XCLBIN packet and it
+ * will communicate with host driver to collect all XCLBIN packets and then
+ * call zocl driver service to load this xclbin.
+ *
+ * 1) start receiving XCLBIN packets
+ * 2) put all XCLBIN packets into a linked packets list
+ * 3) once got all packets, copy XCLBIN packets to a XCLBIN buffer
+ * 4) call zocl driver service to load XCLBIN
+ * 5) update XCLBIN packet status to notify host
+ */
+static int zocl_ov_get_xclbin(struct zocl_ov_dev *ov)
+{
+	struct axlf *xclbin = NULL;
+	void *pdrv;
+	int ret = 0;
+
+	ov_info(ov->pdev, "xclbin is being downloaded...");
+
+	write_lock(&ov->att_rwlock);
+
+	ret = zocl_ov_recieve(ov);
+	if (ret) {
+		set_status(ov, XRT_XFR_PKT_STATUS_FAIL);
+		ov_err(ov->pdev, "Fail to recieve XCLBIN file %d", ret);
+		goto out;
+	}
+
+	ov_info(ov->pdev, "XCLBIN is transfered");
+
+	ret = zocl_ov_copy_xclbin(ov, &xclbin);
+	if (ret) {
+		set_status(ov, XRT_XFR_PKT_STATUS_FAIL);
+		goto out;
+	}
+
+	if (!ov->ppdev) {
+		ret = zocl_ov_find_parent_dev(ov);
+		if (ret) {
+			set_status(ov, XRT_XFR_PKT_STATUS_FAIL);
+			goto out;
+		}
+	}
+
+	pdrv = platform_get_drvdata(ov->ppdev);
+	if (!pdrv) {
+		ov_err(ov->pdev, "Fail to get parent dev driver data");
+		set_status(ov, XRT_XFR_PKT_STATUS_FAIL);
+		ret = -ENXIO;
+		goto out;
+	}
+
+	write_unlock(&ov->att_rwlock);
+	ret = zocl_xclbin_load_pdi(pdrv, xclbin);
+	if (ret) {
+		set_status(ov, XRT_XFR_PKT_STATUS_FAIL);
+		goto out;
+	}
+	write_lock(&ov->att_rwlock);
+
+	ov_info(ov->pdev, "xclbin_done: %d", ov->pdi_done);
+
+	set_status(ov, XRT_XFR_PKT_STATUS_DONE);
+
+out:
+	zocl_ov_clean(ov);
+	write_unlock(&ov->att_rwlock);
+	vfree(xclbin);
+
+	wait_for_status(ov, XRT_XFR_PKT_STATUS_IDLE);
+	set_version(ov);
+
+	return ret;
+}
+
+/*
+ * This function is called once we detect there is a new PDI packet and it
+ * will communicate with host driver to collect all PDI packets and then
+ * communicate with user space daemon to flash the PDI.
+ *
+ * 1) start receiving PDI packets
+ * 2) put all pdi packets into a linked packets list
+ * 3) once got all packets, update sysfs node to indicate PDI is ready
+ * 4) wait on sysfs node on PDI flash done
+ * 5) update PDI packet status to notify host
+ */
+static int zocl_ov_get_pdi(struct zocl_ov_dev *ov)
+{
+	int ret;
+
+	ov_info(ov->pdev, "pdi is being downloaded...");
+
+	/* Clear the done flag */
+	write_lock(&ov->att_rwlock);
+	ov->pdi_done = 0;
+
+	ret = zocl_ov_recieve(ov);
+	if (ret) {
+		write_unlock(&ov->att_rwlock);
+		set_status(ov, XRT_XFR_PKT_STATUS_FAIL);
+		ov_err(ov->pdev, "Fail to recieve PDI file %d", ret);
+		goto fail;
+	}
+
+	ov_info(ov->pdev, "pdi is ready for ospi_daemon");
+
+	/* Set ready flag */
+	ov->pdi_ready = 1;
+	write_unlock(&ov->att_rwlock);
+
+	/* Wait for done */
+	read_lock(&ov->att_rwlock);
+	while (true) {
+		/*
+		 * pdi_done indicates the status of the flashing
+		 * 0: in progress
+		 * 1: completed successfully
+		 * 2: fail
+		 */
+		if (!ov->pdi_done) {
+			read_unlock(&ov->att_rwlock);
+			msleep(ZOCL_OV_TIMER_INTERVAL);
+			read_lock(&ov->att_rwlock);
+			continue;
+		}
+		if (ov->pdi_done == 1)
+			set_status(ov, XRT_XFR_PKT_STATUS_DONE);
+		else
+			set_status(ov, XRT_XFR_PKT_STATUS_FAIL);
+		break;
+	}
+	read_unlock(&ov->att_rwlock);
+
+	ov_info(ov->pdev, "pdi_done: %d", ov->pdi_done);
+
+	/* Clear ready flag */
+	write_lock(&ov->att_rwlock);
+	ov->pdi_ready = 0;
+	zocl_ov_clean(ov);
+	write_unlock(&ov->att_rwlock);
+
+	wait_for_status(ov, XRT_XFR_PKT_STATUS_IDLE);
+	set_version(ov);
+
+	return 0;
+
+fail:
+	write_lock(&ov->att_rwlock);
+	zocl_ov_clean(ov);
+	write_unlock(&ov->att_rwlock);
+
+	wait_for_status(ov, XRT_XFR_PKT_STATUS_IDLE);
+	set_version(ov);
+
+	return ret;
+}
+
+/*
+ * This is the main thread in zocl ospi versal subdriver.
+ *
+ * The thread will wake up every second and check the packet
+ * status. If there is a new packet ready, it will start load and
+ * handle the packets.
+ */
+static int zocl_ov_thread(void *data)
+{
+	struct zocl_ov_dev *ov = (struct zocl_ov_dev *)data;
+	u8 pkt_flags, pkt_type;
+
+	set_status(ov, XRT_XFR_PKT_STATUS_IDLE);
+
+	while (1) {
+		if (kthread_should_stop())
+			break;
+
+		if (check_for_status(ov, XRT_XFR_PKT_STATUS_IDLE)) {
+			msleep(ZOCL_OV_TIMER_INTERVAL);
+			continue;
+		}
+
+		pkt_flags = get_pkt_flags(ov);
+		pkt_type = pkt_flags >> XRT_XFR_PKT_TYPE_SHIFT &
+		    XRT_XFR_PKT_TYPE_MASK;
+		switch (pkt_type) {
+		case XRT_XFR_PKT_TYPE_PDI:
+			zocl_ov_get_pdi(ov);
+			break;
+		case XRT_XFR_PKT_TYPE_XCLBIN:
+			zocl_ov_get_xclbin(ov);
+			break;
+		default:
+			ov_err(ov->pdev, "Unknow packet type: %d", pkt_type);
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static const struct of_device_id zocl_ospi_versal_of_match[] = {
+	{ .compatible = "xlnx,ospi_versal",
+	},
+	{ /* end of table */ },
+};
+
+MODULE_DEVICE_TABLE(of, zocl_ospi_versal_of_match);
+
+static int zocl_ov_probe(struct platform_device  *pdev)
+{
+	struct zocl_ov_dev *ov;
+	const struct of_device_id *id;
+	struct resource *res;
+	void __iomem *map;
+	char thread_name[256] = "zocl-ov-thread";
+	int ret;
+
+	id = of_match_node(zocl_ospi_versal_of_match, pdev->dev.of_node);
+	ov_info(pdev, "Probing for %s", id->compatible);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM,
+	    ZOCL_OSPI_VERSAL_BRAM_RES);
+	map = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(map)) {
+		ov_err(pdev, "Unable to map OSPI resource: %0lx",
+		    PTR_ERR(map));
+		return PTR_ERR(map);
+	}
+
+	ov = devm_kzalloc(&pdev->dev, sizeof(*ov), GFP_KERNEL);
+	if (!ov)
+		return -ENOMEM;
+
+	ov->base = map;
+	ov->size = res->end - res->start + 1;
+	memset_io(ov->base, 0, ov->size);
+	ov->pdev = pdev;
+
+	rwlock_init(&ov->att_rwlock);
+
+	ret = zocl_ov_init_sysfs(&pdev->dev);
+	if (ret) {
+		ov_err(pdev, "Unable to create ospi versal sysfs node");
+		kfree(ov);
+		return ret;
+	}
+
+	set_version(ov);
+
+	/* Start the thread. */
+	ov->timer_task = kthread_run(zocl_ov_thread, ov, thread_name);
+	if (IS_ERR(ov->timer_task)) {
+		ret = PTR_ERR(ov->timer_task);
+
+		ov_err(pdev, "Unable to create ospi versal thread");
+		kfree(ov);
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, ov);
+
+	return 0;
+}
+
+static int zocl_ov_remove(struct platform_device *pdev)
+{
+	struct zocl_ov_dev *ov = platform_get_drvdata(pdev);
+
+	zocl_ov_fini_sysfs(&pdev->dev);
+
+	if (ov && ov->timer_task)
+		kthread_stop(ov->timer_task);
+
+	return 0;
+}
+
+struct platform_driver zocl_ospi_versal_driver = {
+	.driver = {
+		.name = ZOCL_OSPI_VERSAL_NAME,
+		.of_match_table = zocl_ospi_versal_of_match,
+	},
+	.probe  = zocl_ov_probe,
+	.remove = zocl_ov_remove,
+};
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/zocl_ov_sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/zocl_ov_sysfs.c
@@ -0,0 +1,145 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * A GEM style (optionally CMA backed) device manager for ZynQ base
+ * OpenCL accelerators.
+ *
+ * Copyright (C) 2019 Xilinx, Inc. All rights reserved.
+ *
+ * Authors:
+ *    Larry Liu   <yliu@xilinx.com>
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#include "zocl_drv.h"
+#include "zocl_ospi_versal.h"
+
+static ssize_t pdi_done_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct zocl_ov_dev *ov = dev_get_drvdata(dev);
+	u8 val;
+
+	if (!ov)
+		return 0;
+
+	if (kstrtou8(buf, 16, &val) == -EINVAL)
+		return -EINVAL;
+
+	write_lock(&ov->att_rwlock);
+	ov->pdi_done = val;
+	write_unlock(&ov->att_rwlock);
+
+	return count;
+}
+static DEVICE_ATTR_WO(pdi_done);
+
+static ssize_t pdi_ready_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct zocl_ov_dev *ov = dev_get_drvdata(dev);
+	ssize_t size = 0;
+
+	if (!ov)
+		return 0;
+
+	read_lock(&ov->att_rwlock);
+	size += sprintf(buf, "%d\n", ov->pdi_ready);
+	read_unlock(&ov->att_rwlock);
+
+	return size;
+}
+static DEVICE_ATTR_RO(pdi_ready);
+
+static struct attribute *zocl_ov_attrs[] = {
+	&dev_attr_pdi_ready.attr,
+	&dev_attr_pdi_done.attr,
+	NULL,
+};
+
+static ssize_t read_versal_pdi(struct file *filp, struct kobject *kobj,
+		struct bin_attribute *attr, char *buf, loff_t off, size_t count)
+{
+	struct zocl_ov_dev *ov;
+	struct zocl_ov_pkt_node *node;
+	size_t pre_size = 0, size = 0, cp_size;
+	size_t rem_count = count;
+	loff_t cp_start;
+	u32 nread = 0;
+
+	ov = dev_get_drvdata(container_of(kobj, struct device, kobj));
+	if (!ov)
+		return 0;
+
+	read_lock(&ov->att_rwlock);
+	node = ov->head;
+	if (!node) {
+		read_unlock(&ov->att_rwlock);
+		return 0;
+	}
+
+	while (node) {
+		size += node->zn_size;
+		if (off > size) {
+			node = node->zn_next;
+			pre_size = size;
+			continue;
+		}
+
+		cp_start = off >= pre_size ? off - pre_size : 0;
+		if (node->zn_size - cp_start >= rem_count)
+			cp_size = rem_count;
+		else
+			cp_size = node->zn_size - cp_start;
+		rem_count -= cp_size;
+
+		memcpy(buf + nread, ((char *)node->zn_datap) + cp_start,
+		    cp_size);
+		nread += cp_size;
+		if (rem_count == 0)
+			break;
+
+		pre_size = size;
+		node = node->zn_next;
+	}
+
+	read_unlock(&ov->att_rwlock);
+	return nread;
+}
+
+static struct bin_attribute versal_pdi_attr = {
+	.attr = {
+		.name = "versal_pdi",
+		.mode = 0444
+	},
+	.read = read_versal_pdi,
+	.write = NULL,
+	.size = 0
+};
+
+static struct bin_attribute *zocl_ov_bin_attrs[] = {
+	&versal_pdi_attr,
+	NULL,
+};
+
+static struct attribute_group zocl_ov_attr_group = {
+	.attrs = zocl_ov_attrs,
+	.bin_attrs = zocl_ov_bin_attrs,
+};
+
+int zocl_ov_init_sysfs(struct device *dev)
+{
+	int ret;
+
+	ret = sysfs_create_group(&dev->kobj, &zocl_ov_attr_group);
+	if (ret)
+		DRM_ERROR("Create zocl attrs failed: %d\n", ret);
+
+	return ret;
+}
+
+void zocl_ov_fini_sysfs(struct device *dev)
+{
+	sysfs_remove_group(&dev->kobj, &zocl_ov_attr_group);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/zocl_sk.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/zocl_sk.c
@@ -0,0 +1,237 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * A GEM style (optionally CMA backed) device manager for ZynQ based
+ * OpenCL accelerators.
+ *
+ * Copyright (C) 2019 Xilinx, Inc. All rights reserved.
+ *
+ * Authors:
+ *    Larry Liu       <yliu@xilinx.com>
+ *    Jan Stephan     <j.stephan@hzdr.de>
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#include "ert.h"
+#include "zocl_drv.h"
+#include "zocl_sk.h"
+#include "sched_exec.h"
+
+int
+zocl_sk_getcmd_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
+{
+	struct drm_zocl_dev *zdev = dev->dev_private;
+	struct soft_krnl *sk = zdev->soft_kernel;
+	struct soft_krnl_cmd *scmd;
+	struct drm_zocl_sk_getcmd *kdata = data;
+
+	/* If no command, the process who calls this ioctl will block here */
+	mutex_lock(&sk->sk_lock);
+	while (list_empty(&sk->sk_cmd_list)) {
+		mutex_unlock(&sk->sk_lock);
+		if (wait_event_interruptible(sk->sk_wait_queue,
+		    !list_empty(&sk->sk_cmd_list)))
+			return -ERESTARTSYS;
+		mutex_lock(&sk->sk_lock);
+	}
+
+	scmd = list_first_entry(&sk->sk_cmd_list, struct soft_krnl_cmd,
+	    skc_list);
+	list_del(&scmd->skc_list);
+	mutex_unlock(&sk->sk_lock);
+
+	kdata->opcode = scmd->skc_packet->opcode;
+
+	if (kdata->opcode == ERT_SK_CONFIG) {
+		struct ert_configure_sk_cmd *cmd;
+
+		/* Copy the command to ioctl caller */
+		cmd = (struct ert_configure_sk_cmd *)scmd->skc_packet;
+		kdata->start_cuidx = cmd->start_cuidx;
+		kdata->cu_nums = cmd->num_cus;
+		kdata->size = cmd->sk_size;
+
+		/* soft kernel's physical address (little endian) */
+		kdata->paddr = cmd->sk_addr;
+
+		snprintf(kdata->name, ZOCL_MAX_NAME_LENGTH, "%s",
+		    (char *)cmd->sk_name);
+	} else
+		/* We will handle more opcodes */
+		DRM_WARN("Unknown soft kernel command: %d\n",
+		    kdata->opcode);
+
+	kfree(scmd);
+	return 0;
+}
+
+int
+zocl_sk_create_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
+{
+	struct drm_zocl_dev *zdev = dev->dev_private;
+	struct soft_krnl *sk = zdev->soft_kernel;
+	struct drm_zocl_sk_create *args = data;
+	struct drm_gem_object *gem_obj;
+	struct drm_zocl_bo *bo;
+	uint32_t cu_idx = args->cu_idx;
+
+	gem_obj = zocl_gem_object_lookup(dev, filp, args->handle);
+	if (!gem_obj) {
+		DRM_ERROR("Fail to create soft kernel: BO %d does not exist.\n",
+		    args->handle);
+		return -ENXIO;
+	}
+	bo = to_zocl_bo(gem_obj);
+
+	mutex_lock(&sk->sk_lock);
+
+	if (sk->sk_cu[cu_idx]) {
+		DRM_ERROR("Fail to create soft kernel: CU %d created.\n",
+		    cu_idx);
+		mutex_unlock(&sk->sk_lock);
+		ZOCL_DRM_GEM_OBJECT_PUT_UNLOCKED(gem_obj);
+		return -EINVAL;
+	}
+
+	sk->sk_cu[cu_idx] = kzalloc(sizeof(struct soft_krnl), GFP_KERNEL);
+	if (!sk->sk_cu[cu_idx]) {
+		DRM_ERROR("Fail to create soft kernel: no memory.\n");
+		mutex_unlock(&sk->sk_lock);
+		ZOCL_DRM_GEM_OBJECT_PUT_UNLOCKED(gem_obj);
+		return -ENOMEM;
+	}
+
+	sk->sk_cu[cu_idx]->sc_pid = task_pid_nr(current);
+	sk->sk_cu[cu_idx]->sc_parent_pid = task_ppid_nr(current);
+
+	sk->sk_cu[cu_idx]->sc_vregs = bo->cma_base.vaddr;
+	sk->sk_cu[cu_idx]->gem_obj = gem_obj;
+	sema_init(&sk->sk_cu[cu_idx]->sc_sem, 0);
+
+	mutex_unlock(&sk->sk_lock);
+
+	/* Hold refcnt till soft kernel is released or driver unload */
+
+	return 0;
+}
+
+int
+zocl_sk_report_ioctl(struct drm_device *dev, void *data,
+		struct drm_file *filp)
+{
+	struct drm_zocl_dev *zdev = dev->dev_private;
+	struct soft_krnl *sk = zdev->soft_kernel;
+	struct drm_zocl_sk_report *args = data;
+	struct soft_cu *scu;
+	uint32_t cu_idx = args->cu_idx;
+	uint32_t *vaddr;
+	enum drm_zocl_scu_state state = args->cu_state;
+	int ret = 0;
+
+	mutex_lock(&sk->sk_lock);
+
+	if (args->cu_idx > sk->sk_ncus) {
+		DRM_ERROR("Fail to get cu state: CU %d does not exist.\n",
+		    cu_idx);
+		mutex_unlock(&sk->sk_lock);
+		return -ENXIO;
+	}
+
+	scu = sk->sk_cu[args->cu_idx];
+	if (!scu) {
+		DRM_ERROR("CU %d does not exist. \n", cu_idx);
+		mutex_unlock(&sk->sk_lock);
+		return -EINVAL;
+	}
+
+	switch (state) {
+
+	case ZOCL_SCU_STATE_DONE:
+
+		vaddr = scu->sc_vregs;
+
+		/* If the CU is running, mark it as done */
+		if (*vaddr & 1)
+			/* Clear Bit 0 and set Bit 1 */
+			*vaddr = 2 | (*vaddr & ~3);
+
+		mutex_unlock(&sk->sk_lock);
+		if (down_killable(&scu->sc_sem))
+			ret = -EINTR;
+		mutex_lock(&sk->sk_lock);
+		/* if scu does not equal, it means been killed. */
+		if (scu != sk->sk_cu[args->cu_idx]) {
+			mutex_unlock(&sk->sk_lock);
+			return ret;
+		}
+
+		if (ret || scu->sc_flags & ZOCL_SCU_FLAGS_RELEASE) {
+			/*
+			 * If we are interrupted or explictly
+			 * told to exit.
+			 */
+			ZOCL_DRM_GEM_OBJECT_PUT_UNLOCKED(scu->gem_obj);
+			kfree(sk->sk_cu[args->cu_idx]);
+			sk->sk_cu[args->cu_idx] = NULL;
+
+			mutex_unlock(&sk->sk_lock);
+			return ret ? ret : -ESRCH;
+		}
+
+		/* Clear Bit 1 and set Bit 0 */
+		*vaddr = 1 | (*vaddr & ~3);
+
+		mutex_unlock(&sk->sk_lock);
+
+		break;
+
+	default:
+		/*
+		 * More soft kernel state will be added as the kernel
+		 * is not completed but ready to take another run.
+		 */
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int
+zocl_init_soft_kernel(struct drm_device *drm)
+{
+	struct drm_zocl_dev *zdev = drm->dev_private;
+	struct soft_krnl *sk;
+
+	sk = devm_kzalloc(drm->dev, sizeof (*sk), GFP_KERNEL);
+	if (!sk)
+		return -ENOMEM;
+
+	zdev->soft_kernel = sk;
+	mutex_init(&sk->sk_lock);
+	INIT_LIST_HEAD(&sk->sk_cmd_list);
+	init_waitqueue_head(&sk->sk_wait_queue);
+
+	return 0;
+}
+
+void
+zocl_fini_soft_kernel(struct drm_device *drm)
+{
+	struct drm_zocl_dev *zdev = drm->dev_private;
+	struct soft_krnl *sk;
+	u32 cu_idx;
+
+	sk = zdev->soft_kernel;
+	mutex_lock(&sk->sk_lock);
+	for (cu_idx = 0; cu_idx < sk->sk_ncus; cu_idx++) {
+		if (!sk->sk_cu[cu_idx])
+			continue;
+
+		ZOCL_DRM_GEM_OBJECT_PUT_UNLOCKED(sk->sk_cu[cu_idx]->gem_obj);
+		kfree(sk->sk_cu[cu_idx]);
+		sk->sk_cu[cu_idx] = NULL;
+	}
+	mutex_unlock(&sk->sk_lock);
+	mutex_destroy(&sk->sk_lock);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/zocl_sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/zocl_sysfs.c
@@ -0,0 +1,652 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * A GEM style device manager for PCIe based OpenCL accelerators.
+ *
+ * Copyright (C) 2016-2019 Xilinx, Inc. All rights reserved.
+ *
+ * Authors:
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#include "zocl_drv.h"
+#include "zocl_aie.h"
+#include "sched_exec.h"
+#include "zocl_xclbin.h"
+#include "xclbin.h"
+#include "zocl_sk.h"
+#include "kds_core.h"
+
+extern int kds_mode;
+extern int kds_echo;
+
+/* -KDS sysfs-- */
+static ssize_t
+kds_echo_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%d\n", kds_echo);
+}
+
+static ssize_t
+kds_echo_store(struct device *dev, struct device_attribute *da,
+	       const char *buf, size_t count)
+{
+	struct drm_zocl_dev *zdev = dev_get_drvdata(dev);
+
+	/* TODO: this should be as simple as */
+	/* return stroe_kds_echo(&zdev->kds, buf, count); */
+	return store_kds_echo(&zdev->kds, buf, count,
+			      kds_mode, 0, &kds_echo);
+}
+static DEVICE_ATTR(kds_echo, 0644, kds_echo_show, kds_echo_store);
+
+static ssize_t
+kds_stat_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct drm_zocl_dev *zdev = dev_get_drvdata(dev);
+
+	return show_kds_stat(&zdev->kds, buf);
+}
+static DEVICE_ATTR_RO(kds_stat);
+
+static ssize_t xclbinid_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct drm_zocl_dev *zdev = dev_get_drvdata(dev);
+	ssize_t size;
+
+	if (!zdev)
+		return 0;
+
+	size = sprintf(buf, "%pUb\n", zdev->zdev_xclbin->zx_uuid);
+
+	return size;
+}
+static DEVICE_ATTR_RO(xclbinid);
+
+static ssize_t kds_numcus_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct drm_zocl_dev *zdev = dev_get_drvdata(dev);
+	ssize_t size;
+
+	if (!zdev || !zdev->exec)
+		return 0;
+
+	size = sprintf(buf, "%d\n", zdev->exec->num_cus);
+
+	return size;
+}
+static DEVICE_ATTR_RO(kds_numcus);
+
+static ssize_t kds_custat_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct drm_zocl_dev *zdev = dev_get_drvdata(dev);
+	struct zocl_cu *zcu = NULL;
+	ssize_t size = 0;
+	phys_addr_t paddr;
+	u32 usage;
+	int status;
+	int i;
+
+	if (!zdev)
+		return 0;
+
+	read_lock(&zdev->attr_rwlock);
+
+	if (!zdev->exec) {
+		read_unlock(&zdev->attr_rwlock);
+		return 0;
+	}
+
+	for (i = 0; i < zdev->exec->num_cus; i++) {
+		zcu = &zdev->exec->zcu[i];
+		if (!zcu) {
+			read_unlock(&zdev->attr_rwlock);
+			return 0;
+		}
+
+		paddr = zocl_cu_get_paddr(zcu);
+		usage = zcu->usage;
+		status = zocl_cu_status_get(zcu);
+		/* Use %x for now. Needs to use a better approach when support
+		 * CU at higher than 4GB address range.
+		 */
+		size += sprintf(buf + size, "CU[@0x%llx] : %d status : %d\n",
+		    (uint64_t)paddr, usage, status);
+	}
+
+	read_unlock(&zdev->attr_rwlock);
+
+	return size;
+}
+static DEVICE_ATTR_RO(kds_custat);
+
+static ssize_t kds_stats_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct drm_zocl_dev *zdev = dev_get_drvdata(dev);
+	struct sched_exec_core *exec = zdev->exec;
+	int pending, running;
+	struct list_head *pos, *next;
+	struct sched_cmd *cmd;
+	struct ert_packet *pkg;
+	ssize_t sz;
+	int i;
+
+	if (!zdev || !zdev->exec)
+		return 0;
+
+	pending = atomic_read(&exec->scheduler->num_pending);
+	running = atomic_read(&exec->scheduler->num_running);
+	sz  = sprintf(buf,    "num_pending %d\n", atomic_read(&exec->scheduler->num_pending));
+	sz += sprintf(buf+sz, "num_running %d\n", atomic_read(&exec->scheduler->num_running));
+	sz += sprintf(buf+sz, "num_received %d\n", atomic_read(&exec->scheduler->num_received));
+	sz += sprintf(buf+sz, "num_notified %d\n", atomic_read(&exec->scheduler->num_notified));
+
+	if (running == 0)
+		return sz;
+
+	sz += sprintf(buf+sz, "running commands:\n");
+	list_for_each_safe(pos, next, &exec->scheduler->cq) {
+		cmd = list_entry(pos, struct sched_cmd, list);
+		pkg = cmd->packet;
+		sz += sprintf(buf+sz, " opcode %d\n", pkg->opcode);
+		sz += sprintf(buf+sz, " count %d\n", pkg->count);
+		sz += sprintf(buf+sz, " cu idx %d\n", pkg->data[0]);
+		for (i = 1; i < pkg->count; i++) {
+			sz += sprintf(buf+sz, " data: 0x%x\n", pkg->data[i]);
+		}
+	}
+
+	return sz;
+}
+static DEVICE_ATTR_RO(kds_stats);
+
+static ssize_t kds_skstat_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct drm_zocl_dev *zdev = dev_get_drvdata(dev);
+	struct soft_krnl *sk;
+	struct soft_cu *scu;
+	ssize_t sz = 0;
+	int i;
+
+	if (!zdev || !zdev->soft_kernel)
+		return 0;
+
+	sk = zdev->soft_kernel;
+	mutex_lock(&sk->sk_lock);
+	for (i = 0; i < sk->sk_ncus; i++) {
+		scu = sk->sk_cu[i];
+		if (scu) {
+			sz += sprintf(buf+sz, "SK %d\n", i);
+			sz += sprintf(buf+sz, " flags %d\n", scu->sc_flags);
+			sz += sprintf(buf+sz, " usage %lld\n", scu->usage);
+			sz += sprintf(buf+sz, " vregs[0] 0x%x\n", ((u32*)scu->sc_vregs)[0]);
+		} else {
+			sz += sprintf(buf+sz, "SK %d is released\n", i);
+		}
+	}
+	mutex_unlock(&sk->sk_lock);
+
+	return sz;
+}
+static DEVICE_ATTR_RO(kds_skstat);
+
+
+static ssize_t kds_xrt_version_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct drm_zocl_dev *zdev = dev_get_drvdata(dev);
+	ssize_t sz = 0;
+
+	if (!zdev || !zdev->soft_kernel)
+		return 0;
+
+	sz += sprintf(buf+sz, "XRT GIT BRANCH: %s\n", XRT_BRANCH);
+	sz += sprintf(buf+sz, "XRT GIT HASH: %s\n", XRT_HASH);
+	sz += sprintf(buf+sz, "XRT GIT HASH DATE: %s\n", XRT_HASH_DATE);
+	sz += sprintf(buf+sz, "XRT GIT Modified Files: %s\n", XRT_MODIFIED_FILES);
+
+	return sz;
+}
+static DEVICE_ATTR_RO(kds_xrt_version);
+
+static ssize_t zocl_get_memstat(struct device *dev, char *buf, bool raw)
+{
+	struct drm_zocl_dev *zdev = dev_get_drvdata(dev);
+	struct zocl_mem *memp;
+	struct mem_topology *topo;
+	ssize_t size = 0;
+	ssize_t count;
+	size_t memory_usage;
+	unsigned int bo_count;
+	const char *txt_fmt = "[%s] %s@0x%012llx\t(%4lluMB):\t%lluKB\t%dBOs\n";
+	const char *raw_fmt = "%llu %d\n";
+	int i;
+
+	if (!zdev)
+		return 0;
+
+	read_lock(&zdev->attr_rwlock);
+
+	if (!zdev->topology || !zdev->mem) {
+		read_unlock(&zdev->attr_rwlock);
+		return 0;
+	}
+
+	memp = zdev->mem;
+	topo = zdev->topology;
+
+	for (i = 0; i < topo->m_count; i++) {
+		if (topo->m_mem_data[i].m_type == MEM_STREAMING)
+			continue;
+
+		memory_usage = memp[i].zm_stat.memory_usage;
+		bo_count = memp[i].zm_stat.bo_count;
+
+		if (raw)
+			count = sprintf(buf, raw_fmt, memory_usage, bo_count);
+		else {
+			count = sprintf(buf, txt_fmt,
+			    topo->m_mem_data[i].m_used ? "IN-USE" : "UNUSED",
+			    topo->m_mem_data[i].m_tag,
+			    topo->m_mem_data[i].m_base_address,
+			    topo->m_mem_data[i].m_size / 1024,
+			    memory_usage / 1024,
+			    bo_count);
+		}
+		buf += count;
+		size += count;
+	}
+
+	read_unlock(&zdev->attr_rwlock);
+
+	return size;
+}
+
+static ssize_t graph_status_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct drm_zocl_dev *zdev = NULL;
+	struct aie_info *aie;
+	struct aie_info_cmd *acmd;
+	struct aie_info_packet *aiec_packet;
+	ssize_t nread = 0;
+	zdev = dev_get_drvdata(dev);
+	if (!zdev)
+		return 0;
+
+	aie = zdev->aie_information;
+	if (!aie)
+		return 0;
+
+	/* create request */
+	acmd = kmalloc(sizeof(struct aie_info_cmd), GFP_KERNEL);
+	if (!acmd) {
+		return -ENOMEM;
+	}
+
+	aiec_packet = kmalloc(sizeof(struct aie_info_packet), GFP_KERNEL);
+	if (!aiec_packet) {
+		return -ENOMEM;
+	}
+
+	/* set command */
+	aiec_packet->opcode = GRAPH_STATUS;
+	acmd->aiec_packet = aiec_packet;
+
+	/* init semaphore */
+	sema_init(&acmd->aiec_sem, 0);
+
+	/* caller release the wait aied thread and wait for result */
+	mutex_lock(&aie->aie_lock);
+	if (waitqueue_active(&aie->aie_wait_queue)) {
+		list_add_tail(&acmd->aiec_list, &aie->aie_cmd_list);
+		mutex_unlock(&aie->aie_lock);
+		wake_up_interruptible(&aie->aie_wait_queue);
+		if (down_interruptible(&acmd->aiec_sem)) {
+			nread = -ERESTARTSYS;
+			goto clean;
+		}
+	} else {
+		mutex_unlock(&aie->aie_lock);
+		nread =  -ERESTARTSYS;
+		goto clean;
+	}
+
+	nread = snprintf(buf, acmd->aiec_packet->size, "%s\n", acmd->aiec_packet->info);
+
+clean:
+	kfree(acmd->aiec_packet);
+	kfree(acmd);
+	return nread;
+}
+static DEVICE_ATTR_RO(graph_status);
+
+static ssize_t read_aie_metadata(struct file *filp, struct kobject *kobj,
+		struct bin_attribute *attr, char *buf, loff_t off, size_t count)
+{
+	struct drm_zocl_dev *zdev;
+	size_t size;
+	u32 nread = 0;
+
+	zdev = dev_get_drvdata(container_of(kobj, struct device, kobj));
+	if (!zdev)
+		return 0;
+
+	read_lock(&zdev->attr_rwlock);
+
+	size = zdev->aie_data.size;
+
+	/* Read offset should be lesser then total size of metadata */
+	if (off >= size) {
+		read_unlock(&zdev->attr_rwlock);
+		return 0;
+	}
+
+	/* Buffer size should be greater than the size of metadata to be read */
+	if (count < size - off)
+		nread = count;
+	else
+		nread = size - off;
+
+	memcpy(buf, (char *)zdev->aie_data.data + off, nread);
+
+	read_unlock(&zdev->attr_rwlock);
+
+	return nread;
+}
+
+static ssize_t memstat_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	return zocl_get_memstat(dev, buf, false);
+}
+static DEVICE_ATTR_RO(memstat);
+
+static ssize_t memstat_raw_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	return zocl_get_memstat(dev, buf, true);
+}
+static DEVICE_ATTR_RO(memstat_raw);
+
+static ssize_t errors_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct drm_zocl_dev *zdev = dev_get_drvdata(dev);
+	ssize_t size = 0;
+	xrtErrorCode error_code;
+	u64 timestamp;
+	int i;
+
+	if (!zdev)
+		return 0;
+
+	read_lock(&zdev->attr_rwlock);
+
+	if (!zdev->zdev_error.ze_err) {
+		read_unlock(&zdev->attr_rwlock);
+		return 0;
+	}
+
+	for (i = 0; i < zdev->zdev_error.ze_num; i++) {
+		error_code = zdev->zdev_error.ze_err[i].zer_err_code;
+		timestamp = zdev->zdev_error.ze_err[i].zer_ts;
+		size += sprintf(buf + size, "%llu%20llu\n",
+		    error_code, timestamp);
+	}
+
+	read_unlock(&zdev->attr_rwlock);
+
+	return size;
+}
+static DEVICE_ATTR_RO(errors);
+
+static struct attribute *zocl_attrs[] = {
+	&dev_attr_xclbinid.attr,
+	&dev_attr_kds_numcus.attr,
+	&dev_attr_kds_custat.attr,
+	&dev_attr_kds_stats.attr,
+	&dev_attr_kds_skstat.attr,
+	&dev_attr_kds_xrt_version.attr,
+	&dev_attr_kds_echo.attr,
+	&dev_attr_kds_stat.attr,
+	&dev_attr_memstat.attr,
+	&dev_attr_memstat_raw.attr,
+	&dev_attr_errors.attr,
+	&dev_attr_graph_status.attr,
+	NULL,
+};
+
+static ssize_t read_debug_ip_layout(struct file *filp, struct kobject *kobj,
+		struct bin_attribute *attr, char *buf, loff_t off, size_t count)
+{
+	struct drm_zocl_dev *zdev;
+	size_t size;
+	u32 nread = 0;
+
+	zdev = dev_get_drvdata(container_of(kobj, struct device, kobj));
+	if (!zdev)
+		return 0;
+
+	read_lock(&zdev->attr_rwlock);
+
+	if (!zdev->debug_ip) {
+		read_unlock(&zdev->attr_rwlock);
+		return 0;
+	}
+
+	size = sizeof_section(zdev->debug_ip, m_debug_ip_data);
+
+	if (off >= size) {
+		read_unlock(&zdev->attr_rwlock);
+		return 0;
+	}
+
+	if (count < size - off)
+		nread = count;
+	else
+		nread = size - off;
+
+	memcpy(buf, ((char *)zdev->debug_ip) + off, nread);
+
+	read_unlock(&zdev->attr_rwlock);
+
+	return nread;
+}
+
+static ssize_t read_ip_layout(struct file *filp, struct kobject *kobj,
+		struct bin_attribute *attr, char *buf, loff_t off, size_t count)
+{
+	struct drm_zocl_dev *zdev;
+	size_t size;
+	u32 nread = 0;
+
+	zdev = dev_get_drvdata(container_of(kobj, struct device, kobj));
+	if (!zdev)
+		return 0;
+
+	read_lock(&zdev->attr_rwlock);
+
+	if (!zdev->ip) {
+		read_unlock(&zdev->attr_rwlock);
+		return 0;
+	}
+
+	size = sizeof_section(zdev->ip, m_ip_data);
+
+	if (off >= size) {
+		read_unlock(&zdev->attr_rwlock);
+		return 0;
+	}
+
+	if (count < size - off)
+		nread = count;
+	else
+		nread = size - off;
+
+	memcpy(buf, ((char *)zdev->ip) + off, nread);
+
+	read_unlock(&zdev->attr_rwlock);
+
+	return nread;
+}
+
+static ssize_t read_connectivity(struct file *filp, struct kobject *kobj,
+		struct bin_attribute *attr, char *buf, loff_t off, size_t count)
+{
+	struct drm_zocl_dev *zdev;
+	size_t size;
+	u32 nread = 0;
+
+	zdev = dev_get_drvdata(container_of(kobj, struct device, kobj));
+	if (!zdev)
+		return 0;
+
+	read_lock(&zdev->attr_rwlock);
+
+	if (!zdev->connectivity) {
+		read_unlock(&zdev->attr_rwlock);
+		return 0;
+	}
+
+	size = sizeof_section(zdev->connectivity, m_connection);
+
+	if (off >= size) {
+		read_unlock(&zdev->attr_rwlock);
+		return 0;
+	}
+
+	if (count < size - off)
+		nread = count;
+	else
+		nread = size - off;
+
+	memcpy(buf, ((char *)zdev->connectivity + off), nread);
+
+	read_unlock(&zdev->attr_rwlock);
+
+	return nread;
+}
+
+static ssize_t read_mem_topology(struct file *filp, struct kobject *kobj,
+		struct bin_attribute *attr, char *buf, loff_t off, size_t count)
+{
+	struct drm_zocl_dev *zdev;
+	size_t size;
+	u32 nread = 0;
+
+	zdev = dev_get_drvdata(container_of(kobj, struct device, kobj));
+	if (!zdev)
+		return 0;
+
+	read_lock(&zdev->attr_rwlock);
+
+	if (!zdev->topology) {
+		read_unlock(&zdev->attr_rwlock);
+		return 0;
+	}
+
+	size = sizeof_section(zdev->topology, m_mem_data);
+
+	if (off >= size) {
+		read_unlock(&zdev->attr_rwlock);
+		return 0;
+	}
+
+	if (count < size - off)
+		nread = count;
+	else
+		nread = size - off;
+
+	memcpy(buf, ((char *)zdev->topology + off), nread);
+
+	read_unlock(&zdev->attr_rwlock);
+
+	return nread;
+}
+
+static struct bin_attribute aie_metadata_attr = {
+	.attr = {
+		.name = "aie_metadata",
+		.mode = 0444
+	},
+	.read = read_aie_metadata,
+	.write = NULL,
+	.size = 0
+};
+
+static struct bin_attribute debug_ip_layout_attr = {
+	.attr = {
+		.name = "debug_ip_layout",
+		.mode = 0444
+	},
+	.read = read_debug_ip_layout,
+	.write = NULL,
+	.size = 0
+};
+
+static struct bin_attribute ip_layout_attr = {
+	.attr = {
+		.name = "ip_layout",
+		.mode = 0444
+	},
+	.read = read_ip_layout,
+	.write = NULL,
+	.size = 0
+};
+
+static struct bin_attribute connectivity_attr = {
+	.attr = {
+		.name = "connectivity",
+		.mode = 0444
+	},
+	.read = read_connectivity,
+	.write = NULL,
+	.size = 0
+};
+
+static struct bin_attribute mem_topology_attr = {
+	.attr = {
+		.name = "mem_topology",
+		.mode = 0444
+	},
+	.read = read_mem_topology,
+	.write = NULL,
+	.size = 0
+};
+
+
+static struct bin_attribute *zocl_bin_attrs[] = {
+	&debug_ip_layout_attr,
+	&ip_layout_attr,
+	&connectivity_attr,
+	&mem_topology_attr,
+	&aie_metadata_attr,
+	NULL,
+};
+
+static struct attribute_group zocl_attr_group = {
+	.attrs = zocl_attrs,
+	.bin_attrs = zocl_bin_attrs,
+};
+
+int zocl_init_sysfs(struct device *dev)
+{
+	int ret;
+
+	ret = sysfs_create_group(&dev->kobj, &zocl_attr_group);
+	if (ret)
+		DRM_ERROR("Create zocl attrs failed: %d\n", ret);
+
+	return ret;
+}
+
+void zocl_fini_sysfs(struct device *dev)
+{
+	sysfs_remove_group(&dev->kobj, &zocl_attr_group);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zocl/zocl_xclbin.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zocl/zocl_xclbin.c
@@ -0,0 +1,1029 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Apache-2.0 */
+/*
+ * MPSoC based OpenCL accelerators Compute Units.
+ *
+ * Copyright (C) 2019-2020 Xilinx, Inc. All rights reserved.
+ *
+ * Authors:
+ *    David Zhang <davidzha@xilinx.com>
+ *
+ * This file is dual-licensed; you may select either the GNU General Public
+ * License version 2 or Apache License, Version 2.0.
+ */
+
+#include <linux/fpga/fpga-mgr.h>
+#include "sched_exec.h"
+#include "zocl_xclbin.h"
+#include "zocl_aie.h"
+#include "xrt_xclbin.h"
+#include "xclbin.h"
+
+#define VIRTUAL_CU(id) (id == (u32)-1)
+
+extern int kds_mode;
+
+static int
+zocl_fpga_mgr_load(struct drm_zocl_dev *zdev, const char *data, int size, u32 flags)
+{
+	struct drm_device *ddev = zdev->ddev;
+	struct device *dev = ddev->dev;
+	struct fpga_manager *fpga_mgr = zdev->fpga_mgr;
+	struct fpga_image_info *info;
+	int err = 0;
+
+	 /* On Non PR platform, it shouldn't never go to this point.
+	  * On PR platform, the fpga_mgr should be alive.
+	  */
+	if (!zdev->fpga_mgr) {
+		DRM_ERROR("FPGA manager is not found\n");
+		return -ENXIO;
+	}
+
+	info = fpga_image_info_alloc(dev);
+	if (!info)
+		return -ENOMEM;
+
+	info->flags = flags;
+	info->buf = data;
+	info->count = size;
+
+	err = fpga_mgr_load(fpga_mgr, info);
+	if (err == 0)
+		DRM_INFO("FPGA Manager load DONE");
+	else
+		DRM_ERROR("FPGA Manager load FAILED: %d", err);
+
+	fpga_image_info_free(info);
+
+	return err;
+}
+
+static int
+zocl_load_partial(struct drm_zocl_dev *zdev, const char *buffer, int length)
+{
+	int err;
+	void __iomem *map = NULL;
+
+	if (!zdev->pr_isolation_addr) {
+		DRM_ERROR("PR isolation address is not set");
+		return -ENODEV;
+	}
+
+	map = ioremap(zdev->pr_isolation_addr, PR_ISO_SIZE);
+	if (IS_ERR_OR_NULL(map)) {
+		DRM_ERROR("ioremap PR isolation address 0x%llx failed",
+		    zdev->pr_isolation_addr);
+		return -EFAULT;
+	}
+
+	/* Freeze PR ISOLATION IP for bitstream download */
+	iowrite32(0x0, map);
+	err = zocl_fpga_mgr_load(zdev, buffer, length, FPGA_MGR_PARTIAL_RECONFIG);
+	/* Unfreeze PR ISOLATION IP */
+	iowrite32(0x3, map);
+
+	iounmap(map);
+	return err;
+}
+
+static int
+zocl_load_bitstream(struct drm_zocl_dev *zdev, char *buffer, int length)
+{
+	struct XHwIcap_Bit_Header bit_header;
+	char *data = NULL;
+	unsigned int i;
+	char temp;
+
+	memset(&bit_header, 0, sizeof(bit_header));
+	if (xrt_xclbin_parse_header(buffer, DMA_HWICAP_BITFILE_BUFFER_SIZE,
+	    &bit_header)) {
+		DRM_ERROR("bitstream header parse failed");
+		return -EINVAL;
+	}
+
+	if ((bit_header.HeaderLength + bit_header.BitstreamLength) > length) {
+		DRM_ERROR("bitstream header+stream length parse failed");
+		return -EINVAL;
+	}
+
+	/*
+	 * Can we do this more efficiently by APIs from byteorder.h?
+	 */
+	data = buffer + bit_header.HeaderLength;
+	for (i = 0; i < bit_header.BitstreamLength ; i = i+4) {
+		temp = data[i];
+		data[i] = data[i+3];
+		data[i+3] = temp;
+
+		temp = data[i+1];
+		data[i+1] = data[i+2];
+		data[i+2] = temp;
+	}
+
+	/* On pr platofrm load partial bitstream and on Flat platform load full bitstream */
+	if (zdev->pr_isolation_addr)
+		return zocl_load_partial(zdev, data, bit_header.BitstreamLength);
+	else {
+		/* 0 is for full bitstream */
+		return zocl_fpga_mgr_load(zdev, buffer, length, 0);
+	}
+}
+
+static int
+zocl_offsetof_sect(enum axlf_section_kind kind, void *sect,
+		struct axlf *axlf_full, char __user *xclbin_ptr)
+{
+	uint64_t offset;
+	uint64_t size;
+	void **sect_tmp = (void *)sect;
+	int err = 0;
+
+	err = xrt_xclbin_section_info(axlf_full, kind, &offset, &size);
+	if (err) {
+		DRM_WARN("get section %s err: %d ",
+		    xrt_xclbin_kind_to_string(kind), err);
+		return 0;
+	}
+
+	*sect_tmp = &xclbin_ptr[offset];
+
+	return size;
+}
+
+/* zocl_read_sect will alloc memory for sect, callers will call vfree */
+static int
+zocl_read_sect(enum axlf_section_kind kind, void *sect,
+		struct axlf *axlf_full, char __user *xclbin_ptr)
+{
+	uint64_t offset;
+	uint64_t size;
+	void **sect_tmp = (void *)sect;
+	int err = 0;
+
+	err = xrt_xclbin_section_info(axlf_full, kind, &offset, &size);
+	if (err) {
+		DRM_WARN("get section %s err: %d ",
+		    xrt_xclbin_kind_to_string(kind), err);
+		return 0;
+	}
+
+	*sect_tmp = vmalloc(size);
+	err = copy_from_user(*sect_tmp, &xclbin_ptr[offset], size);
+	if (err) {
+		DRM_WARN("copy_from_user for section %s err: %d ",
+		    xrt_xclbin_kind_to_string(kind), err);
+		vfree(*sect_tmp);
+		sect = NULL;
+		return 0;
+	}
+
+	return size;
+}
+
+static inline u32 xclbin_protocol(u32 prop)
+{
+	u32 intr_id = prop & IP_CONTROL_MASK;
+
+	return intr_id >> IP_CONTROL_SHIFT;
+}
+
+static inline u32 xclbin_intr_enable(u32 prop)
+{
+	u32 intr_enable = prop & IP_INT_ENABLE_MASK;
+
+	return intr_enable;
+}
+
+static inline u32 xclbin_intr_id(u32 prop)
+{
+	u32 intr_id = prop & IP_INTERRUPT_ID_MASK;
+
+	return intr_id >> IP_INTERRUPT_ID_SHIFT;
+}
+
+/* Record all of the hardware address apertures in the XCLBIN
+ * This could be used to verify if the configure command set wrong CU base
+ * address and allow user map one of the aperture to user space.
+ *
+ * The xclbin doesn't contain IP size. Use hardcoding size for now.
+ */
+static int
+zocl_update_apertures(struct drm_zocl_dev *zdev)
+{
+	struct ip_data *ip;
+	struct debug_ip_data *dbg_ip;
+	struct addr_aperture *apt;
+	int total = 0;
+	int i;
+
+	/* Update aperture should only happen when loading xclbin */
+	kfree(zdev->apertures);
+	zdev->apertures = NULL;
+	zdev->num_apts = 0;
+
+	if (zdev->ip)
+		total += zdev->ip->m_count;
+
+	if (zdev->debug_ip)
+		total += zdev->debug_ip->m_count;
+
+	if (total == 0)
+		return 0;
+
+	/* If this happened, the xclbin is super bad */
+	if (total < 0) {
+		DRM_ERROR("Invalid number of apertures\n");
+		return -EINVAL;
+	}
+
+	apt = kcalloc(total, sizeof(struct addr_aperture), GFP_KERNEL);
+	if (!apt) {
+		DRM_ERROR("Out of memory\n");
+		return -ENOMEM;
+	}
+
+	if (zdev->ip) {
+		for (i = 0; i < zdev->ip->m_count; ++i) {
+			ip = &zdev->ip->m_ip_data[i];
+			apt[zdev->num_apts].addr = ip->m_base_address;
+			apt[zdev->num_apts].size = CU_SIZE;
+			apt[zdev->num_apts].prop = ip->properties;
+			apt[zdev->num_apts].cu_idx = -1;
+			zdev->num_apts++;
+		}
+	}
+
+	if (zdev->debug_ip) {
+		for (i = 0; i < zdev->debug_ip->m_count; ++i) {
+			dbg_ip = &zdev->debug_ip->m_debug_ip_data[i];
+			apt[zdev->num_apts].addr = dbg_ip->m_base_address;
+			if (dbg_ip->m_type == AXI_MONITOR_FIFO_LITE
+			    || dbg_ip->m_type == AXI_MONITOR_FIFO_FULL)
+				/* FIFO_LITE has 4KB and FIFO FULL has 8KB
+				 * address range. Use both 8K is okay.
+				 */
+				apt[zdev->num_apts].size = _8KB;
+			else
+				/* Others debug IPs have 64KB address range*/
+				apt[zdev->num_apts].size = _64KB;
+			zdev->num_apts++;
+		}
+	}
+
+	zdev->apertures = apt;
+
+	return 0;
+}
+
+static int
+zocl_create_cu(struct drm_zocl_dev *zdev)
+{
+	struct ip_data *ip;
+	struct xrt_cu_info info;
+	char kname[64];
+	char *kname_p;
+	int err;
+	int i;
+
+	if (!zdev->ip)
+		return 0;
+
+	for (i = 0; i < zdev->ip->m_count; ++i) {
+		ip = &zdev->ip->m_ip_data[i];
+
+		if (ip->m_type != IP_KERNEL)
+			continue;
+
+		/* Skip streaming kernel */
+		if (ip->m_base_address == -1)
+			continue;
+
+		info.num_res = 1;
+		info.addr = ip->m_base_address;
+		info.intr_enable = xclbin_intr_enable(ip->properties);
+		info.protocol = xclbin_protocol(ip->properties);
+		info.intr_id = xclbin_intr_id(ip->properties);
+
+		switch (info.protocol) {
+		case CTRL_HS:
+		case CTRL_CHAIN:
+			info.model = XCU_HLS;
+			break;
+		case CTRL_FA:
+			info.model = XCU_FA;
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		info.inst_idx = i;
+		/* ip_data->m_name format "<kernel name>:<instance name>",
+		 * where instance name is so called CU name.
+		 */
+		strcpy(kname, ip->m_name);
+		kname_p = &kname[0];
+		strcpy(info.kname, strsep(&kname_p, ":"));
+		strcpy(info.iname, strsep(&kname_p, ":"));
+
+		/* CU sub device is a virtual device, which means there is no
+		 * device tree nodes
+		 */
+		err = subdev_create_cu(zdev, &info);
+		if (err) {
+			DRM_ERROR("cannot create CU subdev");
+			goto err;
+		}
+	}
+
+	return 0;
+err:
+	subdev_destroy_cu(zdev);
+	return err;
+}
+
+static inline bool
+zocl_xclbin_same_uuid(struct drm_zocl_dev *zdev, xuid_t *uuid)
+{
+	return (zocl_xclbin_get_uuid(zdev) != NULL &&
+	    uuid_equal(uuid, zocl_xclbin_get_uuid(zdev)));
+}
+
+/*
+ * This function takes an XCLBIN in kernel buffer and extracts
+ * BITSTREAM_PDI section (or PDI section). Then load the extracted
+ * section through fpga manager.
+ *
+ * Note: this is only used under ert mode so that we do not need to
+ * check context or cache XCLBIN metadata, which are done by host
+ * XRT driver. Only if the same XCLBIN has been loaded, we skip loading.
+ */
+int
+zocl_xclbin_load_pdi(struct drm_zocl_dev *zdev, void *data)
+{
+	struct axlf *axlf = data;
+	struct axlf *axlf_head = axlf;
+	char *xclbin = NULL;
+	char *section_buffer = NULL;
+	size_t size_of_header;
+	size_t num_of_sections;
+	uint64_t size = 0;
+	int ret = 0;
+
+	if (memcmp(axlf_head->m_magic, "xclbin2", 8)) {
+		DRM_INFO("Invalid xclbin magic string");
+		return -EINVAL;
+	}
+
+	mutex_lock(&zdev->zdev_xclbin_lock);
+	/* Check unique ID */
+	if (zocl_xclbin_same_uuid(zdev, &axlf_head->m_header.uuid)) {
+		DRM_INFO("%s The XCLBIN already loaded, uuid: %pUb",
+			 __func__, &axlf_head->m_header.uuid);
+		mutex_unlock(&zdev->zdev_xclbin_lock);
+		return ret;
+	}
+
+	write_lock(&zdev->attr_rwlock);
+
+	/* Get full axlf header */
+	size_of_header = sizeof(struct axlf_section_header);
+	num_of_sections = axlf_head->m_header.m_numSections-1;
+	xclbin = (char __user *)axlf;
+	ret =
+	    !ZOCL_ACCESS_OK(VERIFY_READ, xclbin, axlf_head->m_header.m_length);
+	if (ret) {
+		ret = -EFAULT;
+		goto out;
+	}
+
+	size = zocl_offsetof_sect(BITSTREAM_PARTIAL_PDI, &section_buffer,
+	    axlf, xclbin);
+	if (size > 0)
+		ret = zocl_load_partial(zdev, section_buffer, size);
+
+	size = zocl_offsetof_sect(PDI, &section_buffer, axlf, xclbin);
+	if (size > 0)
+		ret = zocl_load_partial(zdev, section_buffer, size);
+
+	/* preserve uuid, avoid double download */
+	zocl_xclbin_set_uuid(zdev, &axlf_head->m_header.uuid);
+
+	/* reset scheduler */
+	sched_reset_scheduler(zdev->ddev);
+
+out:
+	write_unlock(&zdev->attr_rwlock);
+	DRM_INFO("%s %pUb ret: %d", __func__, zocl_xclbin_get_uuid(zdev), ret);
+	mutex_unlock(&zdev->zdev_xclbin_lock);
+	return ret;
+}
+
+static int
+zocl_load_aie_only_pdi(struct drm_zocl_dev *zdev, struct axlf *axlf,
+			char __user *xclbin)
+{
+	uint64_t size;
+	char *pdi_buf = NULL;
+	int ret;
+
+	size = zocl_read_sect(PDI, &pdi_buf, axlf, xclbin);
+	if (size == 0)
+		return 0;
+
+	ret = zocl_fpga_mgr_load(zdev, pdi_buf, size, FPGA_MGR_PARTIAL_RECONFIG);
+	vfree(pdi_buf);
+
+	/* Mark AIE out of reset state after load PDI */
+	if (zdev->aie) {
+		mutex_lock(&zdev->aie_lock);
+		zdev->aie->aie_reset = false;
+		mutex_unlock(&zdev->aie_lock);
+	}
+
+	return ret;
+}
+
+static int
+zocl_load_sect(struct drm_zocl_dev *zdev, struct axlf *axlf,
+	char __user *xclbin, enum axlf_section_kind kind)
+{
+	uint64_t size = 0;
+	char *section_buffer = NULL;
+	int ret = 0;
+
+	size = zocl_read_sect(kind, &section_buffer, axlf, xclbin);
+	if (size == 0)
+		return 0;
+
+	switch (kind) {
+	case BITSTREAM:
+		ret = zocl_load_bitstream(zdev, section_buffer, size);
+		break;
+	case PDI:
+	case BITSTREAM_PARTIAL_PDI:
+		ret = zocl_load_partial(zdev, section_buffer, size);
+		break;
+	default:
+		DRM_WARN("Unsupported load type %d", kind);
+	}
+	vfree(section_buffer);
+
+	return ret;
+}
+
+static bool
+is_aie_only(struct axlf *axlf)
+{
+	return (axlf->m_header.m_actionMask & AM_LOAD_AIE);
+}
+
+int
+zocl_xclbin_refcount(struct drm_zocl_dev *zdev)
+{
+	BUG_ON(!mutex_is_locked(&zdev->zdev_xclbin_lock));
+
+	return zdev->zdev_xclbin->zx_refcnt;
+}
+
+int
+zocl_xclbin_read_axlf(struct drm_zocl_dev *zdev, struct drm_zocl_axlf *axlf_obj)
+{
+	struct axlf axlf_head;
+	struct axlf *axlf = NULL;
+	long axlf_size;
+	char __user *xclbin = NULL;
+	size_t size_of_header;
+	size_t num_of_sections;
+	void *kernels;
+	uint64_t size = 0;
+	int ret = 0;
+
+	BUG_ON(!mutex_is_locked(&zdev->zdev_xclbin_lock));
+
+	if (copy_from_user(&axlf_head, axlf_obj->za_xclbin_ptr,
+	    sizeof(struct axlf))) {
+		DRM_WARN("copy_from_user failed for za_xclbin_ptr");
+		return -EFAULT;
+	}
+
+	if (memcmp(axlf_head.m_magic, "xclbin2", 8)) {
+		DRM_WARN("xclbin magic is invalid %s", axlf_head.m_magic);
+		return -EINVAL;
+	}
+
+	/* Get full axlf header */
+	size_of_header = sizeof(struct axlf_section_header);
+	num_of_sections = axlf_head.m_header.m_numSections - 1;
+	axlf_size = sizeof(struct axlf) + size_of_header * num_of_sections;
+	axlf = vmalloc(axlf_size);
+	if (!axlf) {
+		DRM_WARN("read xclbin fails: no memory");
+		return -ENOMEM;
+	}
+
+	if (copy_from_user(axlf, axlf_obj->za_xclbin_ptr, axlf_size)) {
+		DRM_WARN("read xclbin: fail copy from user memory");
+		vfree(axlf);
+		return -EFAULT;
+	}
+
+	xclbin = (char __user *)axlf_obj->za_xclbin_ptr;
+	ret = !ZOCL_ACCESS_OK(VERIFY_READ, xclbin, axlf_head.m_header.m_length);
+	if (ret) {
+		DRM_WARN("read xclbin: fail the access check");
+		vfree(axlf);
+		return -EFAULT;
+	}
+
+	write_lock(&zdev->attr_rwlock);
+
+	/* Check unique ID */
+	if (zocl_xclbin_same_uuid(zdev, &axlf_head.m_header.uuid)) {
+		if (is_aie_only(axlf)) {
+			ret = zocl_load_aie_only_pdi(zdev, axlf, xclbin);
+			if (ret)
+				DRM_WARN("read xclbin: fail to load AIE");
+			else
+				zocl_create_aie(zdev, axlf);
+		} else {
+			DRM_INFO("%s The XCLBIN already loaded", __func__);
+		}
+		goto out0;
+	}
+
+	if (kds_mode == 0) {
+		if (sched_live_clients(zdev, NULL) || sched_is_busy(zdev)) {
+			DRM_ERROR("Current xclbin is in-use, can't change");
+			ret = -EBUSY;
+			goto out0;
+		}
+	}
+
+	/* uuid is null means first time load xclbin */
+	if (zocl_xclbin_get_uuid(zdev) != NULL) {
+		/* reset scheduler prior to load new xclbin */
+		if (kds_mode == 0) {
+			ret = sched_reset_exec(zdev->ddev);
+			if (ret)
+				goto out0;
+		}
+	}
+
+	zocl_free_sections(zdev);
+
+	/* For PR support platform, device-tree has configured addr */
+	if (zdev->pr_isolation_addr) {
+		if (axlf_head.m_header.m_mode != XCLBIN_PR &&
+		    axlf_head.m_header.m_mode != XCLBIN_HW_EMU &&
+		    axlf_head.m_header.m_mode != XCLBIN_HW_EMU_PR) {
+			DRM_ERROR("xclbin m_mod %d is not a PR mode",
+			    axlf_head.m_header.m_mode);
+			ret = -EINVAL;
+			goto out0;
+		}
+
+		if (axlf_obj->za_flags != DRM_ZOCL_PLATFORM_PR) {
+			DRM_INFO("disable partial bitstream download, "
+			    "axlf flags is %d", axlf_obj->za_flags);
+		} else {
+			/*
+			 * Make sure we load PL bitstream first,
+			 * if there is one, before loading AIE PDI.
+			 */
+			ret = zocl_load_sect(zdev, axlf, xclbin, BITSTREAM);
+			if (ret)
+				goto out0;
+
+			ret = zocl_load_sect(zdev, axlf, xclbin,
+			    BITSTREAM_PARTIAL_PDI);
+			if (ret)
+				goto out0;
+
+			ret = zocl_load_sect(zdev, axlf, xclbin, PDI);
+			if (ret)
+				goto out0;
+		}
+	} else if (is_aie_only(axlf)) {
+		ret = zocl_load_aie_only_pdi(zdev, axlf, xclbin);
+		if (ret)
+			goto out0;
+	} else if (axlf_obj->za_flags == DRM_ZOCL_PLATFORM_FLAT && 
+		   axlf_head.m_header.m_mode == XCLBIN_FLAT && 
+		   axlf_head.m_header.m_mode != XCLBIN_HW_EMU &&
+		   axlf_head.m_header.m_mode != XCLBIN_HW_EMU_PR) {
+		/* 
+		 * Load full bitstream, enabled in xrt runtime config
+		 * and xclbin has full bitstream and its not hw emulation
+		 */
+		ret = zocl_load_sect(zdev, axlf, xclbin, BITSTREAM);
+		if (ret)
+			goto out0;
+	}
+
+	/* Populating IP_LAYOUT sections */
+	/* zocl_read_sect return size of section when successfully find it */
+	size = zocl_read_sect(IP_LAYOUT, &zdev->ip, axlf, xclbin);
+	if (size <= 0) {
+		if (size != 0)
+			goto out0;
+	} else if (sizeof_section(zdev->ip, m_ip_data) != size) {
+		ret = -EINVAL;
+		goto out0;
+	}
+
+	/* Populating DEBUG_IP_LAYOUT sections */
+	size = zocl_read_sect(DEBUG_IP_LAYOUT, &zdev->debug_ip, axlf, xclbin);
+	if (size <= 0) {
+		if (size != 0)
+			goto out0;
+	} else if (sizeof_section(zdev->debug_ip, m_debug_ip_data) != size) {
+		ret = -EINVAL;
+		goto out0;
+	}
+
+	ret = zocl_update_apertures(zdev);
+	if (ret)
+		goto out0;
+
+	if (zdev->kernels != NULL) {
+		vfree(zdev->kernels);
+		zdev->kernels = NULL;
+	}
+
+	if (axlf_obj->za_ksize > 0) {
+		kernels = vmalloc(axlf_obj->za_ksize);
+		if (!kernels) {
+			ret = -ENOMEM;
+			goto out0;
+		}
+		if (copy_from_user(kernels, axlf_obj->za_kernels,
+		    axlf_obj->za_ksize)) {
+			ret = -EFAULT;
+			goto out0;
+		}
+		zdev->ksize = axlf_obj->za_ksize;
+		zdev->kernels = kernels;
+	}
+
+	if (kds_mode == 1) {
+		subdev_destroy_cu(zdev);
+		ret = zocl_create_cu(zdev);
+		if (ret)
+			goto out0;
+		ret = zocl_kds_update(zdev);
+		if (ret)
+			goto out0;
+	}
+
+	/* Populating AIE_METADATA sections */
+	size = zocl_read_sect(AIE_METADATA, &zdev->aie_data.data, axlf, xclbin);
+	if (size < 0) {
+		goto out0;
+	}
+	zdev->aie_data.size = size;
+
+	/* Populating CONNECTIVITY sections */
+	size = zocl_read_sect(CONNECTIVITY, &zdev->connectivity, axlf, xclbin);
+	if (size <= 0) {
+		if (size != 0)
+			goto out0;
+	} else if (sizeof_section(zdev->connectivity, m_connection) != size) {
+		ret = -EINVAL;
+		goto out0;
+	}
+
+	/* Populating MEM_TOPOLOGY sections */
+	size = zocl_read_sect(MEM_TOPOLOGY, &zdev->topology, axlf, xclbin);
+	if (size <= 0) {
+		if (size != 0)
+			goto out0;
+	} else if (sizeof_section(zdev->topology, m_mem_data) != size) {
+		ret = -EINVAL;
+		goto out0;
+	}
+
+	zocl_clear_mem(zdev);
+	zocl_init_mem(zdev, zdev->topology);
+
+	/* Createing AIE Partition */
+	zocl_create_aie(zdev, axlf);
+
+	/*
+	 * Remember xclbin_uuid for opencontext.
+	 */
+	zdev->zdev_xclbin->zx_refcnt = 0;
+	zocl_xclbin_set_uuid(zdev, &axlf_head.m_header.uuid);
+
+out0:
+	write_unlock(&zdev->attr_rwlock);
+	if (size < 0)
+		ret = size;
+	vfree(axlf);
+	DRM_INFO("%s %pUb ret: %d", __func__, zocl_xclbin_get_uuid(zdev), ret);
+	return ret;
+}
+
+void *
+zocl_xclbin_get_uuid(struct drm_zocl_dev *zdev)
+{
+	BUG_ON(!mutex_is_locked(&zdev->zdev_xclbin_lock));
+
+	return zdev->zdev_xclbin->zx_uuid;
+}
+
+static int
+zocl_xclbin_hold(struct drm_zocl_dev *zdev, const xuid_t *id)
+{
+	xuid_t *xclbin_id = (xuid_t *)zocl_xclbin_get_uuid(zdev);
+
+	WARN_ON(uuid_is_null(id));
+	BUG_ON(!mutex_is_locked(&zdev->zdev_xclbin_lock));
+
+	if (!uuid_equal(id, xclbin_id)) {
+		DRM_ERROR("lock bitstream %pUb failed, on zdev: %pUb",
+		    id, xclbin_id);
+		return -EBUSY;
+	}
+
+	zdev->zdev_xclbin->zx_refcnt++;
+	DRM_INFO("bitstream %pUb locked, ref=%d",
+		 id, zdev->zdev_xclbin->zx_refcnt);
+
+	return 0;
+}
+
+int zocl_lock_bitstream(struct drm_zocl_dev *zdev, const uuid_t *id)
+{
+	int ret;
+
+	mutex_lock(&zdev->zdev_xclbin_lock);
+	ret = zocl_xclbin_hold(zdev, id);
+	mutex_unlock(&zdev->zdev_xclbin_lock);
+
+	return ret;
+}
+
+static int
+zocl_xclbin_release(struct drm_zocl_dev *zdev, const xuid_t *id)
+{
+	xuid_t *xclbin_uuid = (xuid_t *)zocl_xclbin_get_uuid(zdev);
+
+	BUG_ON(!mutex_is_locked(&zdev->zdev_xclbin_lock));
+
+	if (uuid_is_null(id)) /* force unlock all */
+		zdev->zdev_xclbin->zx_refcnt = 0;
+	else if (uuid_equal(xclbin_uuid, id))
+		--zdev->zdev_xclbin->zx_refcnt;
+	else {
+		DRM_WARN("unlock bitstream %pUb failed, on device: %pUb",
+			 id, xclbin_uuid);
+		return -EINVAL;
+	}
+
+	DRM_INFO("bitstream %pUb unlocked, ref=%d",
+		 xclbin_uuid, zdev->zdev_xclbin->zx_refcnt);
+
+	return 0;
+}
+
+int zocl_unlock_bitstream(struct drm_zocl_dev *zdev, const uuid_t *id)
+{
+	int ret;
+
+	mutex_lock(&zdev->zdev_xclbin_lock);
+	ret = zocl_xclbin_release(zdev, id);
+	mutex_unlock(&zdev->zdev_xclbin_lock);
+
+	return ret;
+}
+
+/* TODO: remove this once new KDS is ready */
+int
+zocl_xclbin_ctx(struct drm_zocl_dev *zdev, struct drm_zocl_ctx *ctx,
+	struct sched_client_ctx *client)
+{
+	struct sched_exec_core *exec = zdev->exec;
+	xuid_t *zdev_xuid, *ctx_xuid = NULL;
+	u32 cu_idx = ctx->cu_index;
+	bool shared;
+	int ret = 0;
+
+	BUG_ON(!mutex_is_locked(&zdev->zdev_xclbin_lock));
+
+	ctx_xuid = vmalloc(ctx->uuid_size);
+	if (!ctx_xuid)
+		return -ENOMEM;
+	ret = copy_from_user(ctx_xuid, (void *)(uintptr_t)ctx->uuid_ptr,
+	    ctx->uuid_size);
+	if (ret) {
+		vfree(ctx_xuid);
+		return ret;
+	}
+
+	write_lock(&zdev->attr_rwlock);
+
+	/*
+	 * valid xclbin_id is the same.
+	 * Note: xclbin has been downloaded by read_axlf.
+	 *       user can only open/remove context with same loaded xclbin.
+	 */
+	zdev_xuid = (xuid_t *)zdev->zdev_xclbin->zx_uuid;
+
+	if (!zdev_xuid || !uuid_equal(zdev_xuid, ctx_xuid)) {
+		DRM_ERROR("try to add/remove CTX with wrong xclbin %pUB",
+		    ctx_xuid);
+		ret = -EBUSY;
+		goto out;
+	}
+
+	/* validate cu_idx */
+	if (!VIRTUAL_CU(cu_idx) && cu_idx >= zdev->ip->m_count) {
+		DRM_ERROR("CU Index(%u) >= numcus(%d)\n",
+		    cu_idx, zdev->ip->m_count);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* validate cu */
+	if (!VIRTUAL_CU(cu_idx) && !zocl_exec_valid_cu(exec, cu_idx)) {
+		DRM_ERROR("invalid CU(%d)", cu_idx);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/*
+	 * handle remove or add
+	 * each client ctx can lock bitstream once, multiple ctx will
+	 * lock bitstream n times. clien is responsible releasing the refcnt
+	 */
+	if (ctx->op == ZOCL_CTX_OP_FREE_CTX) {
+		if (zocl_xclbin_refcount(zdev) == 0) {
+			DRM_ERROR("can not remove unused xclbin");
+			ret = -EINVAL;
+			goto out;
+		}
+
+		if (cu_idx != ZOCL_CTX_VIRT_CU_INDEX) {
+			/* Try clear exclusive CU */
+			ret = test_and_clear_bit(cu_idx, client->excus);
+			if (!ret) {
+				/* Maybe it is shared CU */
+				ret = test_and_clear_bit(cu_idx, client->shcus);
+			}
+			if (!ret) {
+				DRM_ERROR("can not remove unreserved cu");
+        			ret = -EINVAL;
+				goto out;
+			}
+		}
+
+		/* revert the meaning of return value. 0 means succesfull */
+		ret = 0;
+
+		--client->num_cus;
+		if (CLIENT_NUM_CU_CTX(client) == 0)
+			ret = zocl_xclbin_release(zdev, ctx_xuid);
+		goto out;
+	}
+
+	if (ctx->op != ZOCL_CTX_OP_ALLOC_CTX) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (cu_idx != ZOCL_CTX_VIRT_CU_INDEX) {
+		shared = (ctx->flags == ZOCL_CTX_SHARED);
+
+		if (!shared)
+			ret = test_and_set_bit(cu_idx, client->excus);
+		else {
+			ret = test_bit(cu_idx, client->excus);
+			if (ret) {
+				DRM_ERROR("cannot share exclusived CU");
+				ret = -EINVAL;
+				goto out;
+			}
+			ret = test_and_set_bit(cu_idx, client->shcus);
+		}
+
+		if (ret) {
+			DRM_ERROR("CTX already added by this process");
+			ret = -EINVAL;
+			goto out;
+		}
+	}
+
+	/* Hold XCLBIN the first time alloc context */
+	if (CLIENT_NUM_CU_CTX(client) == 0) {
+		ret = zocl_xclbin_hold(zdev, zdev_xuid);
+		if (ret)
+			goto out;
+	}
+	++client->num_cus;
+out:
+	write_unlock(&zdev->attr_rwlock);
+	vfree(ctx_xuid);
+	return ret;
+}
+
+int
+zocl_xclbin_set_uuid(struct drm_zocl_dev *zdev, void *uuid)
+{
+	xuid_t *zx_uuid = zdev->zdev_xclbin->zx_uuid;
+
+	if (zx_uuid) {
+		vfree(zx_uuid);
+		zx_uuid = NULL;
+	}
+
+	zx_uuid = vmalloc(UUID_SIZE * sizeof(u8));
+	if (!zx_uuid)
+		return -ENOMEM;
+
+	uuid_copy(zx_uuid, uuid);
+	zdev->zdev_xclbin->zx_uuid = zx_uuid;
+	return 0;
+}
+
+int
+zocl_xclbin_init(struct drm_zocl_dev *zdev)
+{
+	zdev->zdev_xclbin = vmalloc(sizeof(struct zocl_xclbin));
+	if (!zdev->zdev_xclbin) {
+		DRM_ERROR("Alloc zdev_xclbin failed: no memory\n");
+		return -ENOMEM;
+	}
+
+	zdev->zdev_xclbin->zx_refcnt = 0;
+	zdev->zdev_xclbin->zx_uuid = NULL;
+
+	return 0;
+}
+void
+zocl_xclbin_fini(struct drm_zocl_dev *zdev)
+{
+	vfree(zdev->zdev_xclbin->zx_uuid);
+	zdev->zdev_xclbin->zx_uuid = NULL;
+	vfree(zdev->zdev_xclbin);
+	zdev->zdev_xclbin = NULL;
+
+	/* Delete CU devices if exist */
+	subdev_destroy_cu(zdev);
+}
+
+bool
+zocl_xclbin_accel_adapter(int kds_mask)
+{
+	return kds_mask == ACCEL_ADAPTER;
+}
+
+bool
+zocl_xclbin_legacy_intr(struct drm_zocl_dev *zdev)
+{
+	u32 prop;
+	int i, count = 0;
+
+	/* if all of the interrupt id is 0, this xclbin is legacy */
+	for (i = 0; i < zdev->num_apts; i++) {
+		prop = zdev->apertures[i].prop;
+		if ((prop & IP_INTERRUPT_ID_MASK) == 0)
+			count++;
+	}
+
+	if (count < zdev->num_apts && count > 1) {
+		DRM_WARN("%d non-zero interrupt-id CUs out of %d CUs",
+		    count, zdev->num_apts);
+	}
+
+	return (count == zdev->num_apts);
+}
+
+u32
+zocl_xclbin_intr_id(struct drm_zocl_dev *zdev, u32 idx)
+{
+	u32 prop = zdev->apertures[idx].prop;
+
+	return xclbin_intr_id(prop);
+}
+
+/*
+ * returns false if any of the cu doesnt support interrupt
+ */
+bool
+zocl_xclbin_cus_support_intr(struct drm_zocl_dev *zdev)
+{
+	struct ip_data *ip;
+	int i;
+
+	if (!zdev->ip)
+		return false;
+
+	for (i = 0; i < zdev->ip->m_count; ++i) {
+		ip = &zdev->ip->m_ip_data[i];
+		if (!(ip->properties & 0x1)) {
+			return false;
+		}
+	}
+
+	return true;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/drm/zte/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/drm/zte/Kconfig
@@ -3,7 +3,6 @@
 	tristate "DRM Support for ZTE SoCs"
 	depends on DRM && ARCH_ZX
 	select DRM_KMS_CMA_HELPER
-	select DRM_KMS_FB_HELPER
 	select DRM_KMS_HELPER
 	select SND_SOC_HDMI_CODEC if SND_SOC
 	select VIDEOMODE_HELPERS
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/host1x/bus.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/host1x/bus.c
@@ -335,11 +335,6 @@
 	return 0;
 }
 
-static int host1x_dma_configure(struct device *dev)
-{
-	return of_dma_configure(dev, dev->of_node, true);
-}
-
 static const struct dev_pm_ops host1x_device_pm_ops = {
 	.suspend = pm_generic_suspend,
 	.resume = pm_generic_resume,
@@ -353,7 +348,6 @@
 	.name = "host1x",
 	.match = host1x_device_match,
 	.uevent = host1x_device_uevent,
-	.dma_configure = host1x_dma_configure,
 	.pm = &host1x_device_pm_ops,
 };
 
@@ -442,8 +436,6 @@
 	device->dev.bus = &host1x_bus_type;
 	device->dev.parent = host1x->dev;
 
-	of_dma_configure(&device->dev, host1x->dev->of_node, true);
-
 	device->dev.dma_parms = &device->dma_parms;
 	dma_set_max_seg_size(&device->dev, SZ_4M);
 
@@ -686,8 +678,17 @@
  */
 void host1x_driver_unregister(struct host1x_driver *driver)
 {
+	struct host1x *host1x;
+
 	driver_unregister(&driver->driver);
 
+	mutex_lock(&devices_lock);
+
+	list_for_each_entry(host1x, &devices, list)
+		host1x_detach_driver(host1x, driver);
+
+	mutex_unlock(&devices_lock);
+
 	mutex_lock(&drivers_lock);
 	list_del_init(&driver->list);
 	mutex_unlock(&drivers_lock);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/host1x/debug.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/host1x/debug.c
@@ -16,6 +16,8 @@
 #include "debug.h"
 #include "channel.h"
 
+static DEFINE_MUTEX(debug_lock);
+
 unsigned int host1x_debug_trace_cmdbuf;
 
 static pid_t host1x_debug_force_timeout_pid;
@@ -52,12 +54,14 @@
 	struct output *o = data;
 
 	mutex_lock(&ch->cdma.lock);
+	mutex_lock(&debug_lock);
 
 	if (show_fifo)
 		host1x_hw_show_channel_fifo(m, ch, o);
 
 	host1x_hw_show_channel_cdma(m, ch, o);
 
+	mutex_unlock(&debug_lock);
 	mutex_unlock(&ch->cdma.lock);
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/host1x/hw/syncpt_hw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/host1x/hw/syncpt_hw.c
@@ -106,9 +106,6 @@
 #if HOST1X_HW >= 6
 	struct host1x *host = sp->host;
 
-	if (!host->hv_regs)
-		return;
-
 	host1x_sync_writel(host,
 			   HOST1X_SYNC_SYNCPT_CH_APP_CH(ch ? ch->id : 0xff),
 			   HOST1X_SYNC_SYNCPT_CH_APP(sp->id));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/host1x/job.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/host1x/job.c
@@ -436,7 +436,8 @@
 	return err;
 }
 
-static inline int copy_gathers(struct host1x_job *job, struct device *dev)
+static inline int copy_gathers(struct device *host, struct host1x_job *job,
+			       struct device *dev)
 {
 	struct host1x_firewall fw;
 	size_t size = 0;
@@ -459,12 +460,12 @@
 	 * Try a non-blocking allocation from a higher priority pools first,
 	 * as awaiting for the allocation here is a major performance hit.
 	 */
-	job->gather_copy_mapped = dma_alloc_wc(dev, size, &job->gather_copy,
+	job->gather_copy_mapped = dma_alloc_wc(host, size, &job->gather_copy,
 					       GFP_NOWAIT);
 
 	/* the higher priority allocation failed, try the generic-blocking */
 	if (!job->gather_copy_mapped)
-		job->gather_copy_mapped = dma_alloc_wc(dev, size,
+		job->gather_copy_mapped = dma_alloc_wc(host, size,
 						       &job->gather_copy,
 						       GFP_KERNEL);
 	if (!job->gather_copy_mapped)
@@ -512,7 +513,7 @@
 		goto out;
 
 	if (IS_ENABLED(CONFIG_TEGRA_HOST1X_FIREWALL)) {
-		err = copy_gathers(job, dev);
+		err = copy_gathers(host->dev, job, dev);
 		if (err)
 			goto out;
 	}
@@ -573,7 +574,7 @@
 	job->num_unpins = 0;
 
 	if (job->gather_copy_size)
-		dma_free_wc(job->channel->dev, job->gather_copy_size,
+		dma_free_wc(host->dev, job->gather_copy_size,
 			    job->gather_copy_mapped, job->gather_copy);
 }
 EXPORT_SYMBOL(host1x_job_unpin);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/host1x/mipi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/host1x/mipi.c
@@ -206,9 +206,9 @@
 	return 0;
 }
 
-struct tegra_mipi_device *tegra_mipi_request(struct device *device)
+struct tegra_mipi_device *tegra_mipi_request(struct device *device,
+					     struct device_node *np)
 {
-	struct device_node *np = device->of_node;
 	struct tegra_mipi_device *dev;
 	struct of_phandle_args args;
 	int err;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/ipu-v3/ipu-common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/ipu-v3/ipu-common.c
@@ -124,6 +124,8 @@
 	case V4L2_PIX_FMT_RGBX32:
 	case V4L2_PIX_FMT_ARGB32:
 	case V4L2_PIX_FMT_XRGB32:
+	case V4L2_PIX_FMT_RGB32:
+	case V4L2_PIX_FMT_BGR32:
 		return IPUV3_COLORSPACE_RGB;
 	default:
 		return IPUV3_COLORSPACE_UNKNOWN;
@@ -1233,6 +1235,7 @@
 		pdev = platform_device_alloc(reg->name, id++);
 		if (!pdev) {
 			ret = -ENOMEM;
+			of_node_put(of_node);
 			goto err_register;
 		}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/ipu-v3/ipu-cpmem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/ipu-v3/ipu-cpmem.c
@@ -585,21 +585,21 @@
 	.bits_per_pixel = 16,
 };
 
-#define Y_OFFSET(pix, x, y)	((x) + pix->width * (y))
-#define U_OFFSET(pix, x, y)	((pix->width * pix->height) +		\
-				 (pix->width * ((y) / 2) / 2) + (x) / 2)
-#define V_OFFSET(pix, x, y)	((pix->width * pix->height) +		\
-				 (pix->width * pix->height / 4) +	\
-				 (pix->width * ((y) / 2) / 2) + (x) / 2)
-#define U2_OFFSET(pix, x, y)	((pix->width * pix->height) +		\
-				 (pix->width * (y) / 2) + (x) / 2)
-#define V2_OFFSET(pix, x, y)	((pix->width * pix->height) +		\
-				 (pix->width * pix->height / 2) +	\
-				 (pix->width * (y) / 2) + (x) / 2)
-#define UV_OFFSET(pix, x, y)	((pix->width * pix->height) +	\
-				 (pix->width * ((y) / 2)) + (x))
-#define UV2_OFFSET(pix, x, y)	((pix->width * pix->height) +	\
-				 (pix->width * y) + (x))
+#define Y_OFFSET(pix, x, y)	((x) + pix->bytesperline * (y))
+#define U_OFFSET(pix, x, y)	((pix->bytesperline * pix->height) +	 \
+				 (pix->bytesperline * ((y) / 2) / 2) + (x) / 2)
+#define V_OFFSET(pix, x, y)	((pix->bytesperline * pix->height) +	 \
+				 (pix->bytesperline * pix->height / 4) + \
+				 (pix->bytesperline * ((y) / 2) / 2) + (x) / 2)
+#define U2_OFFSET(pix, x, y)	((pix->bytesperline * pix->height) +	 \
+				 (pix->bytesperline * (y) / 2) + (x) / 2)
+#define V2_OFFSET(pix, x, y)	((pix->bytesperline * pix->height) +	 \
+				 (pix->bytesperline * pix->height / 2) + \
+				 (pix->bytesperline * (y) / 2) + (x) / 2)
+#define UV_OFFSET(pix, x, y)	((pix->bytesperline * pix->height) +	 \
+				 (pix->bytesperline * ((y) / 2)) + (x))
+#define UV2_OFFSET(pix, x, y)	((pix->bytesperline * pix->height) +	 \
+				 (pix->bytesperline * y) + (x))
 
 #define NUM_ALPHA_CHANNELS	7
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/ipu-v3/ipu-di.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/ipu-v3/ipu-di.c
@@ -451,8 +451,9 @@
 
 		error = rate / (sig->mode.pixelclock / 1000);
 
-		dev_dbg(di->ipu->dev, "  IPU clock can give %lu with divider %u, error %d.%u%%\n",
-			rate, div, (signed)(error - 1000) / 10, error % 10);
+		dev_dbg(di->ipu->dev, "  IPU clock can give %lu with divider %u, error %c%d.%d%%\n",
+			rate, div, error < 1000 ? '-' : '+',
+			abs(error - 1000) / 10, abs(error - 1000) % 10);
 
 		/* Allow a 1% error */
 		if (error < 1010 && error >= 990) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/gpu/ipu-v3/ipu-image-convert.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/gpu/ipu-v3/ipu-image-convert.c
@@ -137,6 +137,17 @@
 struct ipu_image_convert_chan;
 struct ipu_image_convert_priv;
 
+enum eof_irq_mask {
+	EOF_IRQ_IN      = BIT(0),
+	EOF_IRQ_ROT_IN  = BIT(1),
+	EOF_IRQ_OUT     = BIT(2),
+	EOF_IRQ_ROT_OUT = BIT(3),
+};
+
+#define EOF_IRQ_COMPLETE (EOF_IRQ_IN | EOF_IRQ_OUT)
+#define EOF_IRQ_ROT_COMPLETE (EOF_IRQ_IN | EOF_IRQ_OUT |	\
+			      EOF_IRQ_ROT_IN | EOF_IRQ_ROT_OUT)
+
 struct ipu_image_convert_ctx {
 	struct ipu_image_convert_chan *chan;
 
@@ -173,6 +184,9 @@
 	/* where to place converted tile in dest image */
 	unsigned int out_tile_map[MAX_TILES];
 
+	/* mask of completed EOF irqs at every tile conversion */
+	enum eof_irq_mask eof_mask;
+
 	struct list_head list;
 };
 
@@ -189,6 +203,8 @@
 	struct ipuv3_channel *rotation_out_chan;
 
 	/* the IPU end-of-frame irqs */
+	int in_eof_irq;
+	int rot_in_eof_irq;
 	int out_eof_irq;
 	int rot_out_eof_irq;
 
@@ -1380,6 +1396,9 @@
 	dev_dbg(priv->ipu->dev, "%s: task %u: starting ctx %p run %p tile %u -> %u\n",
 		__func__, chan->ic_task, ctx, run, tile, dst_tile);
 
+	/* clear EOF irq mask */
+	ctx->eof_mask = 0;
+
 	if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
 		/* swap width/height for resizer */
 		dest_width = d_image->tile[dst_tile].height;
@@ -1615,7 +1634,7 @@
 }
 
 /* hold irqlock when calling */
-static irqreturn_t do_irq(struct ipu_image_convert_run *run)
+static irqreturn_t do_tile_complete(struct ipu_image_convert_run *run)
 {
 	struct ipu_image_convert_ctx *ctx = run->ctx;
 	struct ipu_image_convert_chan *chan = ctx->chan;
@@ -1700,6 +1719,7 @@
 		ctx->cur_buf_num ^= 1;
 	}
 
+	ctx->eof_mask = 0; /* clear EOF irq mask for next tile */
 	ctx->next_tile++;
 	return IRQ_HANDLED;
 done:
@@ -1709,13 +1729,15 @@
 	return IRQ_WAKE_THREAD;
 }
 
-static irqreturn_t norotate_irq(int irq, void *data)
+static irqreturn_t eof_irq(int irq, void *data)
 {
 	struct ipu_image_convert_chan *chan = data;
+	struct ipu_image_convert_priv *priv = chan->priv;
 	struct ipu_image_convert_ctx *ctx;
 	struct ipu_image_convert_run *run;
+	irqreturn_t ret = IRQ_HANDLED;
+	bool tile_complete = false;
 	unsigned long flags;
-	irqreturn_t ret;
 
 	spin_lock_irqsave(&chan->irqlock, flags);
 
@@ -1728,46 +1750,33 @@
 
 	ctx = run->ctx;
 
-	if (ipu_rot_mode_is_irt(ctx->rot_mode)) {
-		/* this is a rotation operation, just ignore */
-		spin_unlock_irqrestore(&chan->irqlock, flags);
-		return IRQ_HANDLED;
-	}
-
-	ret = do_irq(run);
-out:
-	spin_unlock_irqrestore(&chan->irqlock, flags);
-	return ret;
-}
-
-static irqreturn_t rotate_irq(int irq, void *data)
-{
-	struct ipu_image_convert_chan *chan = data;
-	struct ipu_image_convert_priv *priv = chan->priv;
-	struct ipu_image_convert_ctx *ctx;
-	struct ipu_image_convert_run *run;
-	unsigned long flags;
-	irqreturn_t ret;
-
-	spin_lock_irqsave(&chan->irqlock, flags);
-
-	/* get current run and its context */
-	run = chan->current_run;
-	if (!run) {
+	if (irq == chan->in_eof_irq) {
+		ctx->eof_mask |= EOF_IRQ_IN;
+	} else if (irq == chan->out_eof_irq) {
+		ctx->eof_mask |= EOF_IRQ_OUT;
+	} else if (irq == chan->rot_in_eof_irq ||
+		   irq == chan->rot_out_eof_irq) {
+		if (!ipu_rot_mode_is_irt(ctx->rot_mode)) {
+			/* this was NOT a rotation op, shouldn't happen */
+			dev_err(priv->ipu->dev,
+				"Unexpected rotation interrupt\n");
+			goto out;
+		}
+		ctx->eof_mask |= (irq == chan->rot_in_eof_irq) ?
+			EOF_IRQ_ROT_IN : EOF_IRQ_ROT_OUT;
+	} else {
+		dev_err(priv->ipu->dev, "Received unknown irq %d\n", irq);
 		ret = IRQ_NONE;
 		goto out;
 	}
 
-	ctx = run->ctx;
-
-	if (!ipu_rot_mode_is_irt(ctx->rot_mode)) {
-		/* this was NOT a rotation operation, shouldn't happen */
-		dev_err(priv->ipu->dev, "Unexpected rotation interrupt\n");
-		spin_unlock_irqrestore(&chan->irqlock, flags);
-		return IRQ_HANDLED;
-	}
+	if (ipu_rot_mode_is_irt(ctx->rot_mode))
+		tile_complete =	(ctx->eof_mask == EOF_IRQ_ROT_COMPLETE);
+	else
+		tile_complete = (ctx->eof_mask == EOF_IRQ_COMPLETE);
 
-	ret = do_irq(run);
+	if (tile_complete)
+		ret = do_tile_complete(run);
 out:
 	spin_unlock_irqrestore(&chan->irqlock, flags);
 	return ret;
@@ -1801,6 +1810,10 @@
 
 static void release_ipu_resources(struct ipu_image_convert_chan *chan)
 {
+	if (chan->in_eof_irq >= 0)
+		free_irq(chan->in_eof_irq, chan);
+	if (chan->rot_in_eof_irq >= 0)
+		free_irq(chan->rot_in_eof_irq, chan);
 	if (chan->out_eof_irq >= 0)
 		free_irq(chan->out_eof_irq, chan);
 	if (chan->rot_out_eof_irq >= 0)
@@ -1819,7 +1832,27 @@
 
 	chan->in_chan = chan->out_chan = chan->rotation_in_chan =
 		chan->rotation_out_chan = NULL;
-	chan->out_eof_irq = chan->rot_out_eof_irq = -1;
+	chan->in_eof_irq = -1;
+	chan->rot_in_eof_irq = -1;
+	chan->out_eof_irq = -1;
+	chan->rot_out_eof_irq = -1;
+}
+
+static int get_eof_irq(struct ipu_image_convert_chan *chan,
+		       struct ipuv3_channel *channel)
+{
+	struct ipu_image_convert_priv *priv = chan->priv;
+	int ret, irq;
+
+	irq = ipu_idmac_channel_irq(priv->ipu, channel, IPU_IRQ_EOF);
+
+	ret = request_threaded_irq(irq, eof_irq, do_bh, 0, "ipu-ic", chan);
+	if (ret < 0) {
+		dev_err(priv->ipu->dev, "could not acquire irq %d\n", irq);
+		return ret;
+	}
+
+	return irq;
 }
 
 static int get_ipu_resources(struct ipu_image_convert_chan *chan)
@@ -1855,31 +1888,33 @@
 	}
 
 	/* acquire the EOF interrupts */
-	chan->out_eof_irq = ipu_idmac_channel_irq(priv->ipu,
-						  chan->out_chan,
-						  IPU_IRQ_EOF);
+	ret = get_eof_irq(chan, chan->in_chan);
+	if (ret < 0) {
+		chan->in_eof_irq = -1;
+		goto err;
+	}
+	chan->in_eof_irq = ret;
 
-	ret = request_threaded_irq(chan->out_eof_irq, norotate_irq, do_bh,
-				   0, "ipu-ic", chan);
+	ret = get_eof_irq(chan, chan->rotation_in_chan);
 	if (ret < 0) {
-		dev_err(priv->ipu->dev, "could not acquire irq %d\n",
-			 chan->out_eof_irq);
-		chan->out_eof_irq = -1;
+		chan->rot_in_eof_irq = -1;
 		goto err;
 	}
+	chan->rot_in_eof_irq = ret;
 
-	chan->rot_out_eof_irq = ipu_idmac_channel_irq(priv->ipu,
-						     chan->rotation_out_chan,
-						     IPU_IRQ_EOF);
+	ret = get_eof_irq(chan, chan->out_chan);
+	if (ret < 0) {
+		chan->out_eof_irq = -1;
+		goto err;
+	}
+	chan->out_eof_irq = ret;
 
-	ret = request_threaded_irq(chan->rot_out_eof_irq, rotate_irq, do_bh,
-				   0, "ipu-ic", chan);
+	ret = get_eof_irq(chan, chan->rotation_out_chan);
 	if (ret < 0) {
-		dev_err(priv->ipu->dev, "could not acquire irq %d\n",
-			chan->rot_out_eof_irq);
 		chan->rot_out_eof_irq = -1;
 		goto err;
 	}
+	chan->rot_out_eof_irq = ret;
 
 	return 0;
 err:
@@ -2458,6 +2493,8 @@
 		chan->ic_task = i;
 		chan->priv = priv;
 		chan->dma_ch = &image_convert_dma_chan[i];
+		chan->in_eof_irq = -1;
+		chan->rot_in_eof_irq = -1;
 		chan->out_eof_irq = -1;
 		chan->rot_out_eof_irq = -1;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/greybus/interface.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/greybus/interface.c
@@ -694,6 +694,7 @@
 
 	trace_gb_interface_release(intf);
 
+	cancel_work_sync(&intf->mode_switch_work);
 	kfree(intf);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/greybus/svc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/greybus/svc.c
@@ -866,8 +866,14 @@
 
 	gb_svc_debugfs_init(svc);
 
-	return gb_svc_queue_deferred_request(op);
+	ret = gb_svc_queue_deferred_request(op);
+	if (ret)
+		goto err_remove_debugfs;
 
+	return 0;
+
+err_remove_debugfs:
+	gb_svc_debugfs_exit(svc);
 err_unregister_device:
 	gb_svc_watchdog_destroy(svc);
 	device_del(&svc->dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/Kconfig
@@ -149,6 +149,7 @@
 
 config HID_ASUS
 	tristate "Asus"
+	depends on USB_HID
 	depends on LEDS_CLASS
 	depends on ASUS_WMI || ASUS_WMI=n
 	select POWER_SUPPLY
@@ -206,14 +207,14 @@
 
 config HID_CHICONY
 	tristate "Chicony devices"
-	depends on HID
+	depends on USB_HID
 	default !EXPERT
 	---help---
 	Support for Chicony Tactical pad and special keys on Chicony keyboards.
 
 config HID_CORSAIR
 	tristate "Corsair devices"
-	depends on HID && USB && LEDS_CLASS
+	depends on USB_HID && LEDS_CLASS
 	---help---
 	Support for Corsair devices that are not fully compliant with the
 	HID standard.
@@ -244,7 +245,7 @@
 
 config HID_PRODIKEYS
 	tristate "Prodikeys PC-MIDI Keyboard support"
-	depends on HID && SND
+	depends on USB_HID && SND
 	select SND_RAWMIDI
 	---help---
 	Support for Prodikeys PC-MIDI Keyboard device support.
@@ -524,7 +525,7 @@
 
 config HID_LOGITECH
 	tristate "Logitech devices"
-	depends on HID
+	depends on USB_HID
 	default !EXPERT
 	---help---
 	Support for Logitech devices that are not fully compliant with HID standard.
@@ -871,7 +872,7 @@
 
 config HID_SAMSUNG
 	tristate "Samsung InfraRed remote control or keyboards"
-	depends on HID
+	depends on USB_HID
 	---help---
 	Support for Samsung InfraRed remote control or keyboards.
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-alps.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-alps.c
@@ -25,6 +25,7 @@
 
 #define U1_MOUSE_REPORT_ID			0x01 /* Mouse data ReportID */
 #define U1_ABSOLUTE_REPORT_ID		0x03 /* Absolute data ReportID */
+#define U1_ABSOLUTE_REPORT_ID_SECD  0x02 /* FW-PTP Absolute data ReportID */
 #define U1_FEATURE_REPORT_ID		0x05 /* Feature ReportID */
 #define U1_SP_ABSOLUTE_REPORT_ID	0x06 /* Feature ReportID */
 
@@ -368,6 +369,7 @@
 	case U1_FEATURE_REPORT_ID:
 		break;
 	case U1_ABSOLUTE_REPORT_ID:
+	case U1_ABSOLUTE_REPORT_ID_SECD:
 		for (i = 0; i < hdata->max_fingers; i++) {
 			u8 *contact = &data[i * 5];
 
@@ -730,7 +732,7 @@
 	if (data->has_sp) {
 		input2 = input_allocate_device();
 		if (!input2) {
-			input_free_device(input2);
+			ret = -ENOMEM;
 			goto exit;
 		}
 
@@ -760,6 +762,7 @@
 
 		if (input_register_device(data->input2)) {
 			input_free_device(input2);
+			ret = -ENOENT;
 			goto exit;
 		}
 	}
@@ -802,6 +805,7 @@
 		break;
 	case HID_DEVICE_ID_ALPS_U1_DUAL:
 	case HID_DEVICE_ID_ALPS_U1:
+	case HID_DEVICE_ID_ALPS_U1_UNICORN_LEGACY:
 		data->dev_type = U1;
 		break;
 	default:
@@ -828,6 +832,8 @@
 	{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY,
 		USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_U1) },
 	{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY,
+		USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_U1_UNICORN_LEGACY) },
+	{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY,
 		USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_T4_BTNLESS) },
 	{ }
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-apple.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-apple.c
@@ -51,9 +51,16 @@
 		"(For people who want to keep Windows PC keyboard muscle memory. "
 		"[0] = as-is, Mac layout. 1 = swapped, Windows layout.)");
 
+static unsigned int swap_fn_leftctrl;
+module_param(swap_fn_leftctrl, uint, 0644);
+MODULE_PARM_DESC(swap_fn_leftctrl, "Swap the Fn and left Control keys. "
+		"(For people who want to keep PC keyboard muscle memory. "
+		"[0] = as-is, Mac layout, 1 = swapped, PC layout)");
+
 struct apple_sc {
 	unsigned long quirks;
 	unsigned int fn_on;
+	unsigned int fn_found;
 	DECLARE_BITMAP(pressed_numlock, KEY_CNT);
 };
 
@@ -63,6 +70,28 @@
 	u8 flags;
 };
 
+static const struct apple_key_translation apple2021_fn_keys[] = {
+	{ KEY_BACKSPACE, KEY_DELETE },
+	{ KEY_ENTER,	KEY_INSERT },
+	{ KEY_F1,	KEY_BRIGHTNESSDOWN, APPLE_FLAG_FKEY },
+	{ KEY_F2,	KEY_BRIGHTNESSUP,   APPLE_FLAG_FKEY },
+	{ KEY_F3,	KEY_SCALE,          APPLE_FLAG_FKEY },
+	{ KEY_F4,	KEY_SEARCH,         APPLE_FLAG_FKEY },
+	{ KEY_F5,	KEY_MICMUTE,        APPLE_FLAG_FKEY },
+	{ KEY_F6,	KEY_SLEEP,          APPLE_FLAG_FKEY },
+	{ KEY_F7,	KEY_PREVIOUSSONG,   APPLE_FLAG_FKEY },
+	{ KEY_F8,	KEY_PLAYPAUSE,      APPLE_FLAG_FKEY },
+	{ KEY_F9,	KEY_NEXTSONG,       APPLE_FLAG_FKEY },
+	{ KEY_F10,	KEY_MUTE,           APPLE_FLAG_FKEY },
+	{ KEY_F11,	KEY_VOLUMEDOWN,     APPLE_FLAG_FKEY },
+	{ KEY_F12,	KEY_VOLUMEUP,       APPLE_FLAG_FKEY },
+	{ KEY_UP,	KEY_PAGEUP },
+	{ KEY_DOWN,	KEY_PAGEDOWN },
+	{ KEY_LEFT,	KEY_HOME },
+	{ KEY_RIGHT,	KEY_END },
+	{ }
+};
+
 static const struct apple_key_translation macbookair_fn_keys[] = {
 	{ KEY_BACKSPACE, KEY_DELETE },
 	{ KEY_ENTER,	KEY_INSERT },
@@ -162,6 +191,11 @@
 	{ }
 };
 
+static const struct apple_key_translation swapped_fn_leftctrl_keys[] = {
+	{ KEY_FN, KEY_LEFTCTRL },
+	{ }
+};
+
 static const struct apple_key_translation *apple_find_translation(
 		const struct apple_key_translation *table, u16 from)
 {
@@ -183,14 +217,18 @@
 	bool do_translate;
 	u16 code = 0;
 
-	if (usage->code == KEY_FN) {
+	u16 fn_keycode = (swap_fn_leftctrl) ? (KEY_LEFTCTRL) : (KEY_FN);
+
+	if (usage->code == fn_keycode) {
 		asc->fn_on = !!value;
-		input_event(input, usage->type, usage->code, value);
+		input_event(input, usage->type, KEY_FN, value);
 		return 1;
 	}
 
 	if (fnmode) {
-		if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI &&
+		if (hid->product == USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021)
+			table = apple2021_fn_keys;
+		else if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI &&
 				hid->product <= USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS)
 			table = macbookair_fn_keys;
 		else if (hid->product < 0x21d || hid->product >= 0x300)
@@ -270,6 +308,14 @@
 		}
 	}
 
+	if (swap_fn_leftctrl) {
+		trans = apple_find_translation(swapped_fn_leftctrl_keys, usage->code);
+		if (trans) {
+			input_event(input, usage->type, trans->to, value);
+			return 1;
+		}
+	}
+
 	return 0;
 }
 
@@ -300,12 +346,19 @@
 
 /*
  * MacBook JIS keyboard has wrong logical maximum
+ * Magic Keyboard JIS has wrong logical maximum
  */
 static __u8 *apple_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 		unsigned int *rsize)
 {
 	struct apple_sc *asc = hid_get_drvdata(hdev);
 
+	if(*rsize >=71 && rdesc[70] == 0x65 && rdesc[64] == 0x65) {
+		hid_info(hdev,
+			 "fixing up Magic Keyboard JIS report descriptor\n");
+		rdesc[64] = rdesc[70] = 0xe7;
+	}
+
 	if ((asc->quirks & APPLE_RDESC_JIS) && *rsize >= 60 &&
 			rdesc[53] == 0x65 && rdesc[59] == 0x65) {
 		hid_info(hdev,
@@ -333,17 +386,29 @@
 
 	for (trans = apple_iso_keyboard; trans->from; trans++)
 		set_bit(trans->to, input->keybit);
+
+	for (trans = apple2021_fn_keys; trans->from; trans++)
+		set_bit(trans->to, input->keybit);
+
+	if (swap_fn_leftctrl) {
+		for (trans = swapped_fn_leftctrl_keys; trans->from; trans++)
+			set_bit(trans->to, input->keybit);
+	}
 }
 
 static int apple_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 		struct hid_field *field, struct hid_usage *usage,
 		unsigned long **bit, int *max)
 {
+	struct apple_sc *asc = hid_get_drvdata(hdev);
+
 	if (usage->hid == (HID_UP_CUSTOM | 0x0003) ||
-			usage->hid == (HID_UP_MSVENDOR | 0x0003)) {
+			usage->hid == (HID_UP_MSVENDOR | 0x0003) ||
+			usage->hid == (HID_UP_HPVENDOR2 | 0x0003)) {
 		/* The fn key on Apple USB keyboards */
 		set_bit(EV_REP, hi->input->evbit);
 		hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_FN);
+		asc->fn_found = true;
 		apple_setup_input(hi->input);
 		return 1;
 	}
@@ -370,6 +435,19 @@
 	return 0;
 }
 
+static int apple_input_configured(struct hid_device *hdev,
+		struct hid_input *hidinput)
+{
+	struct apple_sc *asc = hid_get_drvdata(hdev);
+
+	if ((asc->quirks & APPLE_HAS_FN) && !asc->fn_found) {
+		hid_info(hdev, "Fn key not found (Apple Wireless Keyboard clone?), disabling Fn key handling\n");
+		asc->quirks &= ~APPLE_HAS_FN;
+	}
+
+	return 0;
+}
+
 static int apple_probe(struct hid_device *hdev,
 		const struct hid_device_id *id)
 {
@@ -571,6 +649,10 @@
 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY),
 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021),
+		.driver_data = APPLE_HAS_FN },
+	{ HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021),
+		.driver_data = APPLE_HAS_FN },
 
 	{ }
 };
@@ -584,6 +666,7 @@
 	.event = apple_event,
 	.input_mapping = apple_input_mapping,
 	.input_mapped = apple_input_mapped,
+	.input_configured = apple_input_configured,
 };
 module_hid_driver(apple_driver);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-appleir.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-appleir.c
@@ -188,7 +188,7 @@
 	static const u8 flatbattery[] = { 0x25, 0x87, 0xe0 };
 	unsigned long flags;
 
-	if (len != 5)
+	if (len != 5 || !(hid->claimed & HID_CLAIMED_INPUT))
 		goto out;
 
 	if (!memcmp(data, keydown, sizeof(keydown))) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-asus.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-asus.c
@@ -40,7 +40,9 @@
 MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
 
 #define T100_TPAD_INTF 2
+#define MEDION_E1239T_TPAD_INTF 1
 
+#define E1239T_TP_TOGGLE_REPORT_ID 0x05
 #define T100CHI_MOUSE_REPORT_ID 0x06
 #define FEATURE_REPORT_ID 0x0d
 #define INPUT_REPORT_ID 0x5d
@@ -77,6 +79,7 @@
 #define QUIRK_G752_KEYBOARD		BIT(8)
 #define QUIRK_T101HA_DOCK		BIT(9)
 #define QUIRK_T90CHI			BIT(10)
+#define QUIRK_MEDION_E1239T		BIT(11)
 
 #define I2C_KEYBOARD_QUIRKS			(QUIRK_FIX_NOTEBOOK_REPORT | \
 						 QUIRK_NO_INIT_REPORTS | \
@@ -92,6 +95,7 @@
 	struct hid_device *hdev;
 	struct work_struct work;
 	unsigned int brightness;
+	spinlock_t lock;
 	bool removed;
 };
 
@@ -102,12 +106,14 @@
 	int res_y;
 	int contact_size;
 	int max_contacts;
+	int report_size;
 };
 
 struct asus_drvdata {
 	unsigned long quirks;
 	struct hid_device *hdev;
 	struct input_dev *input;
+	struct input_dev *tp_kbd_input;
 	struct asus_kbd_leds *kbd_backlight;
 	const struct asus_touchpad_info *tp;
 	bool enable_backlight;
@@ -126,6 +132,7 @@
 	.max_y = 1758,
 	.contact_size = 5,
 	.max_contacts = 5,
+	.report_size = 28 /* 2 byte header + 5 * 5 + 1 byte footer */,
 };
 
 static const struct asus_touchpad_info asus_t100ta_tp = {
@@ -135,6 +142,7 @@
 	.res_y = 27, /* units/mm */
 	.contact_size = 5,
 	.max_contacts = 5,
+	.report_size = 28 /* 2 byte header + 5 * 5 + 1 byte footer */,
 };
 
 static const struct asus_touchpad_info asus_t100ha_tp = {
@@ -144,6 +152,7 @@
 	.res_y = 29, /* units/mm */
 	.contact_size = 5,
 	.max_contacts = 5,
+	.report_size = 28 /* 2 byte header + 5 * 5 + 1 byte footer */,
 };
 
 static const struct asus_touchpad_info asus_t200ta_tp = {
@@ -153,6 +162,7 @@
 	.res_y = 28, /* units/mm */
 	.contact_size = 5,
 	.max_contacts = 5,
+	.report_size = 28 /* 2 byte header + 5 * 5 + 1 byte footer */,
 };
 
 static const struct asus_touchpad_info asus_t100chi_tp = {
@@ -162,6 +172,17 @@
 	.res_y = 29, /* units/mm */
 	.contact_size = 3,
 	.max_contacts = 4,
+	.report_size = 15 /* 2 byte header + 3 * 4 + 1 byte footer */,
+};
+
+static const struct asus_touchpad_info medion_e1239t_tp = {
+	.max_x = 2640,
+	.max_y = 1380,
+	.res_x = 29, /* units/mm */
+	.res_y = 28, /* units/mm */
+	.contact_size = 5,
+	.max_contacts = 5,
+	.report_size = 32 /* 2 byte header + 5 * 5 + 5 byte footer */,
 };
 
 static void asus_report_contact_down(struct asus_drvdata *drvdat,
@@ -229,7 +250,7 @@
 	int i, toolType = MT_TOOL_FINGER;
 	u8 *contactData = data + 2;
 
-	if (size != 3 + drvdat->tp->contact_size * drvdat->tp->max_contacts)
+	if (size != drvdat->tp->report_size)
 		return 0;
 
 	for (i = 0; i < drvdat->tp->max_contacts; i++) {
@@ -257,11 +278,40 @@
 	return 1;
 }
 
+static int asus_e1239t_event(struct asus_drvdata *drvdat, u8 *data, int size)
+{
+	if (size != 3)
+		return 0;
+
+	/* Handle broken mute key which only sends press events */
+	if (!drvdat->tp &&
+	    data[0] == 0x02 && data[1] == 0xe2 && data[2] == 0x00) {
+		input_report_key(drvdat->input, KEY_MUTE, 1);
+		input_sync(drvdat->input);
+		input_report_key(drvdat->input, KEY_MUTE, 0);
+		input_sync(drvdat->input);
+		return 1;
+	}
+
+	/* Handle custom touchpad toggle key which only sends press events */
+	if (drvdat->tp_kbd_input &&
+	    data[0] == 0x05 && data[1] == 0x02 && data[2] == 0x28) {
+		input_report_key(drvdat->tp_kbd_input, KEY_F21, 1);
+		input_sync(drvdat->tp_kbd_input);
+		input_report_key(drvdat->tp_kbd_input, KEY_F21, 0);
+		input_sync(drvdat->tp_kbd_input);
+		return 1;
+	}
+
+	return 0;
+}
+
 static int asus_event(struct hid_device *hdev, struct hid_field *field,
 		      struct hid_usage *usage, __s32 value)
 {
 	if ((usage->hid & HID_USAGE_PAGE) == 0xff310000 &&
-	    (usage->hid & HID_USAGE) != 0x00 && !usage->type) {
+	    (usage->hid & HID_USAGE) != 0x00 &&
+	    (usage->hid & HID_USAGE) != 0xff && !usage->type) {
 		hid_warn(hdev, "Unmapped Asus vendor usagepage code 0x%02x\n",
 			 usage->hid & HID_USAGE);
 	}
@@ -280,10 +330,13 @@
 	if (drvdata->tp && data[0] == INPUT_REPORT_ID)
 		return asus_report_input(drvdata, data, size);
 
+	if (drvdata->quirks & QUIRK_MEDION_E1239T)
+		return asus_e1239t_event(drvdata, data, size);
+
 	return 0;
 }
 
-static int asus_kbd_set_report(struct hid_device *hdev, u8 *buf, size_t buf_size)
+static int asus_kbd_set_report(struct hid_device *hdev, const u8 *buf, size_t buf_size)
 {
 	unsigned char *dmabuf;
 	int ret;
@@ -302,7 +355,7 @@
 
 static int asus_kbd_init(struct hid_device *hdev)
 {
-	u8 buf[] = { FEATURE_KBD_REPORT_ID, 0x41, 0x53, 0x55, 0x53, 0x20, 0x54,
+	const u8 buf[] = { FEATURE_KBD_REPORT_ID, 0x41, 0x53, 0x55, 0x53, 0x20, 0x54,
 		     0x65, 0x63, 0x68, 0x2e, 0x49, 0x6e, 0x63, 0x2e, 0x00 };
 	int ret;
 
@@ -316,7 +369,7 @@
 static int asus_kbd_get_functions(struct hid_device *hdev,
 				  unsigned char *kbd_func)
 {
-	u8 buf[] = { FEATURE_KBD_REPORT_ID, 0x05, 0x20, 0x31, 0x00, 0x08 };
+	const u8 buf[] = { FEATURE_KBD_REPORT_ID, 0x05, 0x20, 0x31, 0x00, 0x08 };
 	u8 *readbuf;
 	int ret;
 
@@ -345,24 +398,42 @@
 	return ret;
 }
 
+static void asus_schedule_work(struct asus_kbd_leds *led)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&led->lock, flags);
+	if (!led->removed)
+		schedule_work(&led->work);
+	spin_unlock_irqrestore(&led->lock, flags);
+}
+
 static void asus_kbd_backlight_set(struct led_classdev *led_cdev,
 				   enum led_brightness brightness)
 {
 	struct asus_kbd_leds *led = container_of(led_cdev, struct asus_kbd_leds,
 						 cdev);
-	if (led->brightness == brightness)
-		return;
+	unsigned long flags;
 
+	spin_lock_irqsave(&led->lock, flags);
 	led->brightness = brightness;
-	schedule_work(&led->work);
+	spin_unlock_irqrestore(&led->lock, flags);
+
+	asus_schedule_work(led);
 }
 
 static enum led_brightness asus_kbd_backlight_get(struct led_classdev *led_cdev)
 {
 	struct asus_kbd_leds *led = container_of(led_cdev, struct asus_kbd_leds,
 						 cdev);
+	enum led_brightness brightness;
+	unsigned long flags;
+
+	spin_lock_irqsave(&led->lock, flags);
+	brightness = led->brightness;
+	spin_unlock_irqrestore(&led->lock, flags);
 
-	return led->brightness;
+	return brightness;
 }
 
 static void asus_kbd_backlight_work(struct work_struct *work)
@@ -370,11 +441,11 @@
 	struct asus_kbd_leds *led = container_of(work, struct asus_kbd_leds, work);
 	u8 buf[] = { FEATURE_KBD_REPORT_ID, 0xba, 0xc5, 0xc4, 0x00 };
 	int ret;
+	unsigned long flags;
 
-	if (led->removed)
-		return;
-
+	spin_lock_irqsave(&led->lock, flags);
 	buf[4] = led->brightness;
+	spin_unlock_irqrestore(&led->lock, flags);
 
 	ret = asus_kbd_set_report(led->hdev, buf, sizeof(buf));
 	if (ret < 0)
@@ -436,6 +507,7 @@
 	drvdata->kbd_backlight->cdev.brightness_set = asus_kbd_backlight_set;
 	drvdata->kbd_backlight->cdev.brightness_get = asus_kbd_backlight_get;
 	INIT_WORK(&drvdata->kbd_backlight->work, asus_kbd_backlight_work);
+	spin_lock_init(&drvdata->kbd_backlight->lock);
 
 	ret = devm_led_classdev_register(&hdev->dev, &drvdata->kbd_backlight->cdev);
 	if (ret < 0) {
@@ -614,6 +686,21 @@
 	    hi->report->id != T100CHI_MOUSE_REPORT_ID)
 		return 0;
 
+	/* Handle MULTI_INPUT on E1239T mouse/touchpad USB interface */
+	if (drvdata->tp && (drvdata->quirks & QUIRK_MEDION_E1239T)) {
+		switch (hi->report->id) {
+		case E1239T_TP_TOGGLE_REPORT_ID:
+			input_set_capability(input, EV_KEY, KEY_F21);
+			input->name = "Asus Touchpad Keys";
+			drvdata->tp_kbd_input = input;
+			return 0;
+		case INPUT_REPORT_ID:
+			break; /* Touchpad report, handled below */
+		default:
+			return 0; /* Ignore other reports */
+		}
+	}
+
 	if (drvdata->tp) {
 		int ret;
 
@@ -693,7 +780,6 @@
 
 	/* ASUS-specific keyboard hotkeys */
 	if ((usage->hid & HID_USAGE_PAGE) == 0xff310000) {
-		set_bit(EV_REP, hi->input->evbit);
 		switch (usage->hid & HID_USAGE) {
 		case 0x10: asus_map_key_clear(KEY_BRIGHTNESSDOWN);	break;
 		case 0x20: asus_map_key_clear(KEY_BRIGHTNESSUP);		break;
@@ -736,11 +822,11 @@
 		if (drvdata->quirks & QUIRK_USE_KBD_BACKLIGHT)
 			drvdata->enable_backlight = true;
 
+		set_bit(EV_REP, hi->input->evbit);
 		return 1;
 	}
 
 	if ((usage->hid & HID_USAGE_PAGE) == HID_UP_MSVENDOR) {
-		set_bit(EV_REP, hi->input->evbit);
 		switch (usage->hid & HID_USAGE) {
 		case 0xff01: asus_map_key_clear(BTN_1);	break;
 		case 0xff02: asus_map_key_clear(BTN_2);	break;
@@ -763,6 +849,7 @@
 			return 0;
 		}
 
+		set_bit(EV_REP, hi->input->evbit);
 		return 1;
 	}
 
@@ -781,6 +868,16 @@
 		}
 	}
 
+	/*
+	 * The mute button is broken and only sends press events, we
+	 * deal with this in our raw_event handler, so do not map it.
+	 */
+	if ((drvdata->quirks & QUIRK_MEDION_E1239T) &&
+	    usage->hid == (HID_UP_CONSUMER | 0xe2)) {
+		input_set_capability(hi->input, EV_KEY, KEY_MUTE);
+		return -1;
+	}
+
 	return 0;
 }
 
@@ -811,6 +908,24 @@
 	return 0;
 }
 
+static int __maybe_unused asus_resume(struct hid_device *hdev) {
+	struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
+	int ret = 0;
+
+	if (drvdata->kbd_backlight) {
+		const u8 buf[] = { FEATURE_KBD_REPORT_ID, 0xba, 0xc5, 0xc4,
+				drvdata->kbd_backlight->cdev.brightness };
+		ret = asus_kbd_set_report(hdev, buf, sizeof(buf));
+		if (ret < 0) {
+			hid_err(hdev, "Asus failed to set keyboard backlight: %d\n", ret);
+			goto asus_resume_err;
+		}
+	}
+
+asus_resume_err:
+	return ret;
+}
+
 static int __maybe_unused asus_reset_resume(struct hid_device *hdev)
 {
 	struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
@@ -848,7 +963,7 @@
 	if (drvdata->quirks & QUIRK_IS_MULTITOUCH)
 		drvdata->tp = &asus_i2c_tp;
 
-	if (drvdata->quirks & QUIRK_T100_KEYBOARD) {
+	if ((drvdata->quirks & QUIRK_T100_KEYBOARD) && hid_is_usb(hdev)) {
 		struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
 
 		if (intf->altsetting->desc.bInterfaceNumber == T100_TPAD_INTF) {
@@ -876,6 +991,19 @@
 		drvdata->tp = &asus_t100chi_tp;
 	}
 
+	if ((drvdata->quirks & QUIRK_MEDION_E1239T) &&
+	    hid_is_using_ll_driver(hdev, &usb_hid_driver)) {
+		struct usb_host_interface *alt =
+			to_usb_interface(hdev->dev.parent)->altsetting;
+
+		if (alt->desc.bInterfaceNumber == MEDION_E1239T_TPAD_INTF) {
+			/* For separate input-devs for tp and tp toggle key */
+			hdev->quirks |= HID_QUIRK_MULTI_INPUT;
+			drvdata->quirks |= QUIRK_SKIP_INPUT_MAPPING;
+			drvdata->tp = &medion_e1239t_tp;
+		}
+	}
+
 	if (drvdata->quirks & QUIRK_NO_INIT_REPORTS)
 		hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS;
 
@@ -934,9 +1062,13 @@
 static void asus_remove(struct hid_device *hdev)
 {
 	struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
+	unsigned long flags;
 
 	if (drvdata->kbd_backlight) {
+		spin_lock_irqsave(&drvdata->kbd_backlight->lock, flags);
 		drvdata->kbd_backlight->removed = true;
+		spin_unlock_irqrestore(&drvdata->kbd_backlight->lock, flags);
+
 		cancel_work_sync(&drvdata->kbd_backlight->work);
 	}
 
@@ -1055,7 +1187,8 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_ASUS_MD_5112) },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ASUSTEK,
 		USB_DEVICE_ID_ASUSTEK_T100CHI_KEYBOARD), QUIRK_T100CHI },
-
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE_MEDION_E1239T),
+		QUIRK_MEDION_E1239T },
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, asus_devices);
@@ -1070,6 +1203,7 @@
 	.input_configured       = asus_input_configured,
 #ifdef CONFIG_PM
 	.reset_resume           = asus_reset_resume,
+	.resume					= asus_resume,
 #endif
 	.event			= asus_event,
 	.raw_event		= asus_raw_event
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-betopff.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-betopff.c
@@ -56,15 +56,21 @@
 {
 	struct betopff_device *betopff;
 	struct hid_report *report;
-	struct hid_input *hidinput =
-			list_first_entry(&hid->inputs, struct hid_input, list);
+	struct hid_input *hidinput;
 	struct list_head *report_list =
 			&hid->report_enum[HID_OUTPUT_REPORT].report_list;
-	struct input_dev *dev = hidinput->input;
-	int field_count = 0;
+	struct input_dev *dev;
 	int error;
 	int i, j;
 
+	if (list_empty(&hid->inputs)) {
+		hid_err(hid, "no inputs found\n");
+		return -ENODEV;
+	}
+
+	hidinput = list_first_entry(&hid->inputs, struct hid_input, list);
+	dev = hidinput->input;
+
 	if (list_empty(report_list)) {
 		hid_err(hid, "no output reports found\n");
 		return -ENODEV;
@@ -79,19 +85,21 @@
 	 * -----------------------------------------
 	 * Do init them with default value.
 	 */
+	if (report->maxfield < 4) {
+		hid_err(hid, "not enough fields in the report: %d\n",
+				report->maxfield);
+		return -ENODEV;
+	}
 	for (i = 0; i < report->maxfield; i++) {
+		if (report->field[i]->report_count < 1) {
+			hid_err(hid, "no values in the field\n");
+			return -ENODEV;
+		}
 		for (j = 0; j < report->field[i]->report_count; j++) {
 			report->field[i]->value[j] = 0x00;
-			field_count++;
 		}
 	}
 
-	if (field_count < 4) {
-		hid_err(hid, "not enough fields in the report: %d\n",
-				field_count);
-		return -ENODEV;
-	}
-
 	betopff = kzalloc(sizeof(*betopff), GFP_KERNEL);
 	if (!betopff)
 		return -ENOMEM;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-bigbenff.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-bigbenff.c
@@ -174,6 +174,8 @@
 struct bigben_device {
 	struct hid_device *hid;
 	struct hid_report *report;
+	spinlock_t lock;
+	bool removed;
 	u8 led_state;         /* LED1 = 1 .. LED4 = 8 */
 	u8 right_motor_on;    /* right motor off/on 0/1 */
 	u8 left_motor_force;  /* left motor force 0-255 */
@@ -183,15 +185,39 @@
 	struct work_struct worker;
 };
 
+static inline void bigben_schedule_work(struct bigben_device *bigben)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&bigben->lock, flags);
+	if (!bigben->removed)
+		schedule_work(&bigben->worker);
+	spin_unlock_irqrestore(&bigben->lock, flags);
+}
 
 static void bigben_worker(struct work_struct *work)
 {
 	struct bigben_device *bigben = container_of(work,
 		struct bigben_device, worker);
 	struct hid_field *report_field = bigben->report->field[0];
+	bool do_work_led = false;
+	bool do_work_ff = false;
+	u8 *buf;
+	u32 len;
+	unsigned long flags;
+
+	buf = hid_alloc_report_buf(bigben->report, GFP_KERNEL);
+	if (!buf)
+		return;
+
+	len = hid_report_len(bigben->report);
+
+	/* LED work */
+	spin_lock_irqsave(&bigben->lock, flags);
 
 	if (bigben->work_led) {
 		bigben->work_led = false;
+		do_work_led = true;
 		report_field->value[0] = 0x01; /* 1 = led message */
 		report_field->value[1] = 0x08; /* reserved value, always 8 */
 		report_field->value[2] = bigben->led_state;
@@ -200,11 +226,22 @@
 		report_field->value[5] = 0x00; /* padding */
 		report_field->value[6] = 0x00; /* padding */
 		report_field->value[7] = 0x00; /* padding */
-		hid_hw_request(bigben->hid, bigben->report, HID_REQ_SET_REPORT);
+		hid_output_report(bigben->report, buf);
 	}
 
+	spin_unlock_irqrestore(&bigben->lock, flags);
+
+	if (do_work_led) {
+		hid_hw_raw_request(bigben->hid, bigben->report->id, buf, len,
+				   bigben->report->type, HID_REQ_SET_REPORT);
+	}
+
+	/* FF work */
+	spin_lock_irqsave(&bigben->lock, flags);
+
 	if (bigben->work_ff) {
 		bigben->work_ff = false;
+		do_work_ff = true;
 		report_field->value[0] = 0x02; /* 2 = rumble effect message */
 		report_field->value[1] = 0x08; /* reserved value, always 8 */
 		report_field->value[2] = bigben->right_motor_on;
@@ -213,16 +250,32 @@
 		report_field->value[5] = 0x00; /* padding */
 		report_field->value[6] = 0x00; /* padding */
 		report_field->value[7] = 0x00; /* padding */
-		hid_hw_request(bigben->hid, bigben->report, HID_REQ_SET_REPORT);
+		hid_output_report(bigben->report, buf);
 	}
+
+	spin_unlock_irqrestore(&bigben->lock, flags);
+
+	if (do_work_ff) {
+		hid_hw_raw_request(bigben->hid, bigben->report->id, buf, len,
+				   bigben->report->type, HID_REQ_SET_REPORT);
+	}
+
+	kfree(buf);
 }
 
 static int hid_bigben_play_effect(struct input_dev *dev, void *data,
 			 struct ff_effect *effect)
 {
-	struct bigben_device *bigben = data;
+	struct hid_device *hid = input_get_drvdata(dev);
+	struct bigben_device *bigben = hid_get_drvdata(hid);
 	u8 right_motor_on;
 	u8 left_motor_force;
+	unsigned long flags;
+
+	if (!bigben) {
+		hid_err(hid, "no device data\n");
+		return 0;
+	}
 
 	if (effect->type != FF_RUMBLE)
 		return 0;
@@ -232,10 +285,13 @@
 
 	if (right_motor_on != bigben->right_motor_on ||
 			left_motor_force != bigben->left_motor_force) {
+		spin_lock_irqsave(&bigben->lock, flags);
 		bigben->right_motor_on   = right_motor_on;
 		bigben->left_motor_force = left_motor_force;
 		bigben->work_ff = true;
-		schedule_work(&bigben->worker);
+		spin_unlock_irqrestore(&bigben->lock, flags);
+
+		bigben_schedule_work(bigben);
 	}
 
 	return 0;
@@ -249,6 +305,7 @@
 	struct bigben_device *bigben = hid_get_drvdata(hid);
 	int n;
 	bool work;
+	unsigned long flags;
 
 	if (!bigben) {
 		hid_err(hid, "no device data\n");
@@ -257,6 +314,7 @@
 
 	for (n = 0; n < NUM_LEDS; n++) {
 		if (led == bigben->leds[n]) {
+			spin_lock_irqsave(&bigben->lock, flags);
 			if (value == LED_OFF) {
 				work = (bigben->led_state & BIT(n));
 				bigben->led_state &= ~BIT(n);
@@ -264,10 +322,11 @@
 				work = !(bigben->led_state & BIT(n));
 				bigben->led_state |= BIT(n);
 			}
+			spin_unlock_irqrestore(&bigben->lock, flags);
 
 			if (work) {
 				bigben->work_led = true;
-				schedule_work(&bigben->worker);
+				bigben_schedule_work(bigben);
 			}
 			return;
 		}
@@ -297,9 +356,13 @@
 static void bigben_remove(struct hid_device *hid)
 {
 	struct bigben_device *bigben = hid_get_drvdata(hid);
+	unsigned long flags;
+
+	spin_lock_irqsave(&bigben->lock, flags);
+	bigben->removed = true;
+	spin_unlock_irqrestore(&bigben->lock, flags);
 
 	cancel_work_sync(&bigben->worker);
-	hid_hw_close(hid);
 	hid_hw_stop(hid);
 }
 
@@ -308,7 +371,6 @@
 {
 	struct bigben_device *bigben;
 	struct hid_input *hidinput;
-	struct list_head *report_list;
 	struct led_classdev *led;
 	char *name;
 	size_t name_sz;
@@ -319,6 +381,7 @@
 		return -ENOMEM;
 	hid_set_drvdata(hid, bigben);
 	bigben->hid = hid;
+	bigben->removed = false;
 
 	error = hid_parse(hid);
 	if (error) {
@@ -332,19 +395,29 @@
 		return error;
 	}
 
-	report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
-	bigben->report = list_entry(report_list->next,
-		struct hid_report, list);
+	bigben->report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 8);
+	if (!bigben->report) {
+		hid_err(hid, "no output report found\n");
+		error = -ENODEV;
+		goto error_hw_stop;
+	}
+
+	if (list_empty(&hid->inputs)) {
+		hid_err(hid, "no inputs found\n");
+		error = -ENODEV;
+		goto error_hw_stop;
+	}
 
 	hidinput = list_first_entry(&hid->inputs, struct hid_input, list);
 	set_bit(FF_RUMBLE, hidinput->input->ffbit);
 
 	INIT_WORK(&bigben->worker, bigben_worker);
+	spin_lock_init(&bigben->lock);
 
-	error = input_ff_create_memless(hidinput->input, bigben,
+	error = input_ff_create_memless(hidinput->input, NULL,
 		hid_bigben_play_effect);
 	if (error)
-		return error;
+		goto error_hw_stop;
 
 	name_sz = strlen(dev_name(&hid->dev)) + strlen(":red:bigben#") + 1;
 
@@ -354,8 +427,10 @@
 			sizeof(struct led_classdev) + name_sz,
 			GFP_KERNEL
 		);
-		if (!led)
-			return -ENOMEM;
+		if (!led) {
+			error = -ENOMEM;
+			goto error_hw_stop;
+		}
 		name = (void *)(&led[1]);
 		snprintf(name, name_sz,
 			"%s:red:bigben%d",
@@ -369,7 +444,7 @@
 		bigben->leds[n] = led;
 		error = devm_led_classdev_register(&hid->dev, led);
 		if (error)
-			return error;
+			goto error_hw_stop;
 	}
 
 	/* initial state: LED1 is on, no rumble effect */
@@ -378,11 +453,15 @@
 	bigben->left_motor_force = 0;
 	bigben->work_led = true;
 	bigben->work_ff = true;
-	schedule_work(&bigben->worker);
+	bigben_schedule_work(bigben);
 
 	hid_info(hid, "LED and force feedback support for BigBen gamepad\n");
 
 	return 0;
+
+error_hw_stop:
+	hid_hw_stop(hid);
+	return error;
 }
 
 static __u8 *bigben_report_fixup(struct hid_device *hid, __u8 *rdesc,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-chicony.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-chicony.c
@@ -58,8 +58,12 @@
 static __u8 *ch_switch12_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 		unsigned int *rsize)
 {
-	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
-	
+	struct usb_interface *intf;
+
+	if (!hid_is_usb(hdev))
+		return rdesc;
+
+	intf = to_usb_interface(hdev->dev.parent);
 	if (intf->cur_altsetting->desc.bInterfaceNumber == 1) {
 		/* Change usage maximum and logical maximum from 0x7fff to
 		 * 0x2fff, so they don't exceed HID_MAX_USAGES */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-core.c
@@ -90,7 +90,7 @@
  * Register a new field for this report.
  */
 
-static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values)
+static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages)
 {
 	struct hid_field *field;
 
@@ -101,7 +101,7 @@
 
 	field = kzalloc((sizeof(struct hid_field) +
 			 usages * sizeof(struct hid_usage) +
-			 values * sizeof(unsigned)), GFP_KERNEL);
+			 usages * sizeof(unsigned)), GFP_KERNEL);
 	if (!field)
 		return NULL;
 
@@ -212,6 +212,18 @@
 }
 
 /*
+ * Concatenate usage which defines 16 bits or less with the
+ * currently defined usage page to form a 32 bit usage
+ */
+
+static void complete_usage(struct hid_parser *parser, unsigned int index)
+{
+	parser->local.usage[index] &= 0xFFFF;
+	parser->local.usage[index] |=
+		(parser->global.usage_page & 0xFFFF) << 16;
+}
+
+/*
  * Add a usage to the temporary parser table.
  */
 
@@ -222,6 +234,14 @@
 		return -1;
 	}
 	parser->local.usage[parser->local.usage_index] = usage;
+
+	/*
+	 * If Usage item only includes usage id, concatenate it with
+	 * currently defined usage page
+	 */
+	if (size <= 2)
+		complete_usage(parser, parser->local.usage_index);
+
 	parser->local.usage_size[parser->local.usage_index] = size;
 	parser->local.collection_index[parser->local.usage_index] =
 		parser->collection_stack_ptr ?
@@ -238,6 +258,7 @@
 {
 	struct hid_report *report;
 	struct hid_field *field;
+	unsigned int max_buffer_size = HID_MAX_BUFFER_SIZE;
 	unsigned int usages;
 	unsigned int offset;
 	unsigned int i;
@@ -268,13 +289,22 @@
 	offset = report->size;
 	report->size += parser->global.report_size * parser->global.report_count;
 
+	if (parser->device->ll_driver->max_buffer_size)
+		max_buffer_size = parser->device->ll_driver->max_buffer_size;
+
+	/* Total size check: Allow for possible report index byte */
+	if (report->size > (max_buffer_size - 1) << 3) {
+		hid_err(parser->device, "report is too long\n");
+		return -1;
+	}
+
 	if (!parser->local.usage_index) /* Ignore padding fields */
 		return 0;
 
 	usages = max_t(unsigned, parser->local.usage_index,
 				 parser->global.report_count);
 
-	field = hid_register_field(report, usages, parser->global.report_count);
+	field = hid_register_field(report, usages);
 	if (!field)
 		return 0;
 
@@ -543,13 +573,32 @@
  * usage value."
  */
 
-static void hid_concatenate_usage_page(struct hid_parser *parser)
+static void hid_concatenate_last_usage_page(struct hid_parser *parser)
 {
 	int i;
+	unsigned int usage_page;
+	unsigned int current_page;
+
+	if (!parser->local.usage_index)
+		return;
+
+	usage_page = parser->global.usage_page;
+
+	/*
+	 * Concatenate usage page again only if last declared Usage Page
+	 * has not been already used in previous usages concatenation
+	 */
+	for (i = parser->local.usage_index - 1; i >= 0; i--) {
+		if (parser->local.usage_size[i] > 2)
+			/* Ignore extended usages */
+			continue;
+
+		current_page = parser->local.usage[i] >> 16;
+		if (current_page == usage_page)
+			break;
 
-	for (i = 0; i < parser->local.usage_index; i++)
-		if (parser->local.usage_size[i] <= 2)
-			parser->local.usage[i] += parser->global.usage_page << 16;
+		complete_usage(parser, i);
+	}
 }
 
 /*
@@ -561,7 +610,7 @@
 	__u32 data;
 	int ret;
 
-	hid_concatenate_usage_page(parser);
+	hid_concatenate_last_usage_page(parser);
 
 	data = item_udata(item);
 
@@ -653,15 +702,22 @@
  * Free a device structure, all reports, and all fields.
  */
 
-static void hid_device_release(struct device *dev)
+void hiddev_free(struct kref *ref)
 {
-	struct hid_device *hid = to_hid_device(dev);
+	struct hid_device *hid = container_of(ref, struct hid_device, ref);
 
 	hid_close_report(hid);
 	kfree(hid->dev_rdesc);
 	kfree(hid);
 }
 
+static void hid_device_release(struct device *dev)
+{
+	struct hid_device *hid = to_hid_device(dev);
+
+	kref_put(&hid->ref, hiddev_free);
+}
+
 /*
  * Fetch a report description item from the data stream. We support long
  * items, though they are not used yet.
@@ -742,6 +798,10 @@
 	if (usage == 0xff0000c5 && parser->global.report_count == 256 &&
 	    parser->global.report_size == 8)
 		parser->scan_flags |= HID_SCAN_FLAG_MT_WIN_8;
+
+	if (usage == 0xff0000c6 && parser->global.report_count == 1 &&
+	    parser->global.report_size == 8)
+		parser->scan_flags |= HID_SCAN_FLAG_MT_WIN_8;
 }
 
 static void hid_scan_collection(struct hid_parser *parser, unsigned type)
@@ -772,7 +832,7 @@
 	__u32 data;
 	int i;
 
-	hid_concatenate_usage_page(parser);
+	hid_concatenate_last_usage_page(parser);
 
 	data = item_udata(item);
 
@@ -932,8 +992,8 @@
 		 * Validating on id 0 means we should examine the first
 		 * report in the list.
 		 */
-		report = list_entry(
-				hid->report_enum[type].report_list.next,
+		report = list_first_entry_or_null(
+				&hid->report_enum[type].report_list,
 				struct hid_report, list);
 	} else {
 		report = hid->report_enum[type].report_id_hash[id];
@@ -1057,6 +1117,8 @@
 	while (multiplier_collection->parent_idx != -1 &&
 	       multiplier_collection->type != HID_COLLECTION_LOGICAL)
 		multiplier_collection = &hid->collection[multiplier_collection->parent_idx];
+	if (multiplier_collection->type != HID_COLLECTION_LOGICAL)
+		multiplier_collection = NULL;
 
 	effective_multiplier = hid_calculate_multiplier(hid, multiplier);
 
@@ -1141,6 +1203,7 @@
 	__u8 *end;
 	__u8 *next;
 	int ret;
+	int i;
 	static int (*dispatch_type[])(struct hid_parser *parser,
 				      struct hid_item *item) = {
 		hid_parser_main,
@@ -1191,6 +1254,8 @@
 		goto err;
 	}
 	device->collection_size = HID_DEFAULT_NUM_COLLECTIONS;
+	for (i = 0; i < HID_DEFAULT_NUM_COLLECTIONS; i++)
+		device->collection[i].parent_idx = -1;
 
 	ret = -EINVAL;
 	while ((next = fetch_item(start, end, &item)) != NULL) {
@@ -1251,6 +1316,12 @@
 
 static s32 snto32(__u32 value, unsigned n)
 {
+	if (!value || !n)
+		return 0;
+
+	if (n > 32)
+		n = 32;
+
 	switch (n) {
 	case 8:  return ((__s8)value);
 	case 16: return ((__s16)value);
@@ -1370,7 +1441,6 @@
 			hid_warn(hid,
 				 "%s() called with too large value %d (n: %d)! (%s)\n",
 				 __func__, value, n, current->comm);
-			WARN_ON(1);
 			value &= m;
 		}
 	}
@@ -1549,6 +1619,17 @@
 }
 
 /*
+ * Compute the size of a report.
+ */
+static size_t hid_compute_report_size(struct hid_report *report)
+{
+	if (report->size)
+		return ((report->size - 1) >> 3) + 1;
+
+	return 0;
+}
+
+/*
  * Create a report. 'data' has to be allocated using
  * hid_alloc_report_buf() so that it has proper size.
  */
@@ -1560,7 +1641,7 @@
 	if (report->id > 0)
 		*data++ = report->id;
 
-	memset(data, 0, ((report->size - 1) >> 3) + 1);
+	memset(data, 0, hid_compute_report_size(report));
 	for (n = 0; n < report->maxfield; n++)
 		hid_output_field(report->device, report->field[n], data);
 }
@@ -1578,7 +1659,7 @@
 
 	u32 len = hid_report_len(report) + 7;
 
-	return kmalloc(len, flags);
+	return kzalloc(len, flags);
 }
 EXPORT_SYMBOL_GPL(hid_alloc_report_buf);
 
@@ -1676,6 +1757,7 @@
 	struct hid_report_enum *report_enum = hid->report_enum + type;
 	struct hid_report *report;
 	struct hid_driver *hdrv;
+	int max_buffer_size = HID_MAX_BUFFER_SIZE;
 	unsigned int a;
 	u32 rsize, csize = size;
 	u8 *cdata = data;
@@ -1690,10 +1772,15 @@
 		csize--;
 	}
 
-	rsize = ((report->size - 1) >> 3) + 1;
+	rsize = hid_compute_report_size(report);
 
-	if (rsize > HID_MAX_BUFFER_SIZE)
-		rsize = HID_MAX_BUFFER_SIZE;
+	if (hid->ll_driver->max_buffer_size)
+		max_buffer_size = hid->ll_driver->max_buffer_size;
+
+	if (report_enum->numbered && rsize >= max_buffer_size)
+		rsize = max_buffer_size - 1;
+	else if (rsize > max_buffer_size)
+		rsize = max_buffer_size;
 
 	if (csize < rsize) {
 		dbg_hid("report %d is too short, (%d < %d)\n", report->id,
@@ -1933,6 +2020,9 @@
 	case BUS_I2C:
 		bus = "I2C";
 		break;
+	case BUS_VIRTUAL:
+		bus = "VIRTUAL";
+		break;
 	default:
 		bus = "<UNKNOWN>";
 	}
@@ -2231,12 +2321,8 @@
 {
 	struct hid_device *hdev = to_hid_device(dev);
 	struct hid_driver *hdrv;
-	int ret = 0;
 
-	if (down_interruptible(&hdev->driver_input_lock)) {
-		ret = -EINTR;
-		goto end;
-	}
+	down(&hdev->driver_input_lock);
 	hdev->io_started = false;
 
 	hdrv = hdev->driver;
@@ -2251,8 +2337,8 @@
 
 	if (!hdev->io_started)
 		up(&hdev->driver_input_lock);
-end:
-	return ret;
+
+	return 0;
 }
 
 static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
@@ -2359,10 +2445,12 @@
 			hid_warn(hdev, "bad device descriptor (%d)\n", ret);
 	}
 
+	hdev->id = atomic_inc_return(&id);
+
 	/* XXX hack, any other cleaner solution after the driver core
 	 * is converted to allow more than 20 bytes as the device name? */
 	dev_set_name(&hdev->dev, "%04X:%04X:%04X.%04X", hdev->bus,
-		     hdev->vendor, hdev->product, atomic_inc_return(&id));
+		     hdev->vendor, hdev->product, hdev->id);
 
 	hid_debug_register(hdev, dev_name(&hdev->dev));
 	ret = device_add(&hdev->dev);
@@ -2405,6 +2493,7 @@
 	spin_lock_init(&hdev->debug_list_lock);
 	sema_init(&hdev->driver_input_lock, 1);
 	mutex_init(&hdev->ll_open_lock);
+	kref_init(&hdev->ref);
 
 	return hdev;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-corsair.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-corsair.c
@@ -553,7 +553,12 @@
 	int ret;
 	unsigned long quirks = id->driver_data;
 	struct corsair_drvdata *drvdata;
-	struct usb_interface *usbif = to_usb_interface(dev->dev.parent);
+	struct usb_interface *usbif;
+
+	if (!hid_is_usb(dev))
+		return -EINVAL;
+
+	usbif = to_usb_interface(dev->dev.parent);
 
 	drvdata = devm_kzalloc(&dev->dev, sizeof(struct corsair_drvdata),
 			       GFP_KERNEL);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-cougar.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-cougar.c
@@ -106,7 +106,7 @@
 static __u8 *cougar_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 				 unsigned int *rsize)
 {
-	if (rdesc[2] == 0x09 && rdesc[3] == 0x02 &&
+	if (*rsize >= 117 && rdesc[2] == 0x09 && rdesc[3] == 0x02 &&
 	    (rdesc[115] | rdesc[116] << 8) >= HID_MAX_USAGES) {
 		hid_info(hdev,
 			"usage count exceeds max: fixing up report descriptor\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-cp2112.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-cp2112.c
@@ -787,6 +787,11 @@
 		data->word = le16_to_cpup((__le16 *)buf);
 		break;
 	case I2C_SMBUS_I2C_BLOCK_DATA:
+		if (read_length > I2C_SMBUS_BLOCK_MAX) {
+			ret = -EINVAL;
+			goto power_normal;
+		}
+
 		memcpy(data->block + 1, buf, read_length);
 		break;
 	case I2C_SMBUS_BLOCK_DATA:
@@ -1151,8 +1156,6 @@
 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
 	struct cp2112_device *dev = gpiochip_get_data(gc);
 
-	INIT_DELAYED_WORK(&dev->gpio_poll_worker, cp2112_gpio_poll_callback);
-
 	if (!dev->gpio_poll) {
 		dev->gpio_poll = true;
 		schedule_delayed_work(&dev->gpio_poll_worker, 0);
@@ -1235,6 +1238,7 @@
 	struct cp2112_device *dev;
 	u8 buf[3];
 	struct cp2112_smbus_config_report config;
+	struct gpio_irq_chip *girq;
 	int ret;
 
 	dev = devm_kzalloc(&hdev->dev, sizeof(*dev), GFP_KERNEL);
@@ -1338,6 +1342,17 @@
 	dev->gc.can_sleep		= 1;
 	dev->gc.parent			= &hdev->dev;
 
+	girq = &dev->gc.irq;
+	girq->chip = &cp2112_gpio_irqchip;
+	/* The event comes from the outside so no parent handler */
+	girq->parent_handler = NULL;
+	girq->num_parents = 0;
+	girq->parents = NULL;
+	girq->default_type = IRQ_TYPE_NONE;
+	girq->handler = handle_simple_irq;
+
+	INIT_DELAYED_WORK(&dev->gpio_poll_worker, cp2112_gpio_poll_callback);
+
 	ret = gpiochip_add_data(&dev->gc, dev);
 	if (ret < 0) {
 		hid_err(hdev, "error registering gpio chip\n");
@@ -1353,17 +1368,8 @@
 	chmod_sysfs_attrs(hdev);
 	hid_hw_power(hdev, PM_HINT_NORMAL);
 
-	ret = gpiochip_irqchip_add(&dev->gc, &cp2112_gpio_irqchip, 0,
-				   handle_simple_irq, IRQ_TYPE_NONE);
-	if (ret) {
-		dev_err(dev->gc.parent, "failed to add IRQ chip\n");
-		goto err_sysfs_remove;
-	}
-
 	return ret;
 
-err_sysfs_remove:
-	sysfs_remove_group(&hdev->dev.kobj, &cp2112_attr_group);
 err_gpiochip_remove:
 	gpiochip_remove(&dev->gc);
 err_free_i2c:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-cypress.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-cypress.c
@@ -23,19 +23,17 @@
 #define CP_2WHEEL_MOUSE_HACK		0x02
 #define CP_2WHEEL_MOUSE_HACK_ON		0x04
 
+#define VA_INVAL_LOGICAL_BOUNDARY	0x08
+
 /*
  * Some USB barcode readers from cypress have usage min and usage max in
  * the wrong order
  */
-static __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+static __u8 *cp_rdesc_fixup(struct hid_device *hdev, __u8 *rdesc,
 		unsigned int *rsize)
 {
-	unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
 	unsigned int i;
 
-	if (!(quirks & CP_RDESC_SWAPPED_MIN_MAX))
-		return rdesc;
-
 	if (*rsize < 4)
 		return rdesc;
 
@@ -48,6 +46,40 @@
 	return rdesc;
 }
 
+static __u8 *va_logical_boundary_fixup(struct hid_device *hdev, __u8 *rdesc,
+		unsigned int *rsize)
+{
+	/*
+	 * Varmilo VA104M (with VID Cypress and device ID 07B1) incorrectly
+	 * reports Logical Minimum of its Consumer Control device as 572
+	 * (0x02 0x3c). Fix this by setting its Logical Minimum to zero.
+	 */
+	if (*rsize == 25 &&
+			rdesc[0] == 0x05 && rdesc[1] == 0x0c &&
+			rdesc[2] == 0x09 && rdesc[3] == 0x01 &&
+			rdesc[6] == 0x19 && rdesc[7] == 0x00 &&
+			rdesc[11] == 0x16 && rdesc[12] == 0x3c && rdesc[13] == 0x02) {
+		hid_info(hdev,
+			 "fixing up varmilo VA104M consumer control report descriptor\n");
+		rdesc[12] = 0x00;
+		rdesc[13] = 0x00;
+	}
+	return rdesc;
+}
+
+static __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+		unsigned int *rsize)
+{
+	unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+
+	if (quirks & CP_RDESC_SWAPPED_MIN_MAX)
+		rdesc = cp_rdesc_fixup(hdev, rdesc, rsize);
+	if (quirks & VA_INVAL_LOGICAL_BOUNDARY)
+		rdesc = va_logical_boundary_fixup(hdev, rdesc, rsize);
+
+	return rdesc;
+}
+
 static int cp_input_mapped(struct hid_device *hdev, struct hid_input *hi,
 		struct hid_field *field, struct hid_usage *usage,
 		unsigned long **bit, int *max)
@@ -128,6 +160,8 @@
 		.driver_data = CP_RDESC_SWAPPED_MIN_MAX },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE),
 		.driver_data = CP_2WHEEL_MOUSE_HACK },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_VARMILO_VA104M_07B1),
+		.driver_data = VA_INVAL_LOGICAL_BOUNDARY },
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, cp_devices);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-debug.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-debug.c
@@ -823,7 +823,9 @@
 	[KEY_F22] = "F22",			[KEY_F23] = "F23",
 	[KEY_F24] = "F24",			[KEY_PLAYCD] = "PlayCD",
 	[KEY_PAUSECD] = "PauseCD",		[KEY_PROG3] = "Prog3",
-	[KEY_PROG4] = "Prog4",			[KEY_SUSPEND] = "Suspend",
+	[KEY_PROG4] = "Prog4",
+	[KEY_ALL_APPLICATIONS] = "AllApplications",
+	[KEY_SUSPEND] = "Suspend",
 	[KEY_CLOSE] = "Close",			[KEY_PLAY] = "Play",
 	[KEY_FASTFORWARD] = "FastForward",	[KEY_BASSBOOST] = "BassBoost",
 	[KEY_PRINT] = "Print",			[KEY_HP] = "HP",
@@ -929,6 +931,9 @@
 	[KEY_APPSELECT] = "AppSelect",
 	[KEY_SCREENSAVER] = "ScreenSaver",
 	[KEY_VOICECOMMAND] = "VoiceCommand",
+	[KEY_EMOJI_PICKER] = "EmojiPicker",
+	[KEY_DICTATE] = "Dictate",
+	[KEY_MICMUTE] = "MicrophoneMute",
 	[KEY_BRIGHTNESS_MIN] = "BrightnessMin",
 	[KEY_BRIGHTNESS_MAX] = "BrightnessMax",
 	[KEY_BRIGHTNESS_AUTO] = "BrightnessAuto",
@@ -1077,6 +1082,7 @@
 		goto out;
 	}
 	list->hdev = (struct hid_device *) inode->i_private;
+	kref_get(&list->hdev->ref);
 	file->private_data = list;
 	mutex_init(&list->read_mutex);
 
@@ -1169,6 +1175,8 @@
 	list_del(&list->node);
 	spin_unlock_irqrestore(&list->hdev->debug_list_lock, flags);
 	kfifo_free(&list->hid_debug_fifo);
+
+	kref_put(&list->hdev->ref, hiddev_free);
 	kfree(list);
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-elan.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-elan.c
@@ -50,7 +50,7 @@
 
 static int is_not_elan_touchpad(struct hid_device *hdev)
 {
-	if (hdev->bus == BUS_USB) {
+	if (hid_is_usb(hdev)) {
 		struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
 
 		return (intf->altsetting->desc.bInterfaceNumber !=
@@ -198,7 +198,7 @@
 	if (ret) {
 		hid_err(hdev, "Failed to register elan input device: %d\n",
 			ret);
-		input_free_device(input);
+		input_mt_destroy_slots(input);
 		return ret;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-elo.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-elo.c
@@ -229,6 +229,9 @@
 	struct elo_priv *priv;
 	int ret;
 
+	if (!hid_is_usb(hdev))
+		return -EINVAL;
+
 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-google-hammer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-google-hammer.c
@@ -258,11 +258,13 @@
 	return 0;
 }
 
+#ifdef CONFIG_ACPI
 static const struct acpi_device_id cbas_ec_acpi_ids[] = {
 	{ "GOOG000B", 0 },
 	{ }
 };
 MODULE_DEVICE_TABLE(acpi, cbas_ec_acpi_ids);
+#endif
 
 static struct platform_driver cbas_ec_driver = {
 	.probe = cbas_ec_probe,
@@ -468,12 +470,20 @@
 
 static const struct hid_device_id hammer_devices[] = {
 	{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
+		     USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_DON) },
+	{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
+		     USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_EEL) },
+	{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
 		     USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_HAMMER) },
 	{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
+		     USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_JEWEL) },
+	{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
 		     USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_MAGNEMITE) },
 	{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
 		     USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_MASTERBALL) },
 	{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
+		     USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_MOONBALL) },
+	{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
 		     USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_STAFF) },
 	{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
 		     USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_WAND) },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-gt683r.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-gt683r.c
@@ -54,6 +54,7 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) },
 	{ }
 };
+MODULE_DEVICE_TABLE(hid, gt683r_led_id);
 
 static void gt683r_brightness_set(struct led_classdev *led_cdev,
 				enum led_brightness brightness)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-holtek-kbd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-holtek-kbd.c
@@ -130,6 +130,10 @@
 		return -ENODEV;
 
 	boot_hid = usb_get_intfdata(boot_interface);
+	if (list_empty(&boot_hid->inputs)) {
+		hid_err(hid, "no inputs found\n");
+		return -ENODEV;
+	}
 	boot_hid_input = list_first_entry(&boot_hid->inputs,
 		struct hid_input, list);
 
@@ -140,12 +144,17 @@
 static int holtek_kbd_probe(struct hid_device *hdev,
 		const struct hid_device_id *id)
 {
-	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
-	int ret = hid_parse(hdev);
+	struct usb_interface *intf;
+	int ret;
+
+	if (!hid_is_usb(hdev))
+		return -EINVAL;
 
+	ret = hid_parse(hdev);
 	if (!ret)
 		ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
 
+	intf = to_usb_interface(hdev->dev.parent);
 	if (!ret && intf->cur_altsetting->desc.bInterfaceNumber == 1) {
 		struct hid_input *hidinput;
 		list_for_each_entry(hidinput, &hdev->inputs, list) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-holtek-mouse.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-holtek-mouse.c
@@ -62,6 +62,29 @@
 	return rdesc;
 }
 
+static int holtek_mouse_probe(struct hid_device *hdev,
+			      const struct hid_device_id *id)
+{
+	int ret;
+
+	if (!hid_is_usb(hdev))
+		return -EINVAL;
+
+	ret = hid_parse(hdev);
+	if (ret) {
+		hid_err(hdev, "hid parse failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+	if (ret) {
+		hid_err(hdev, "hw start failed: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
 static const struct hid_device_id holtek_mouse_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT,
 			USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067) },
@@ -83,6 +106,7 @@
 	.name = "holtek_mouse",
 	.id_table = holtek_mouse_devices,
 	.report_fixup = holtek_mouse_report_fixup,
+	.probe = holtek_mouse_probe,
 };
 
 module_hid_driver(holtek_mouse_driver);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-hyperv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-hyperv.c
@@ -492,7 +492,7 @@
 
 	ret = hid_add_device(hid_dev);
 	if (ret)
-		goto probe_err1;
+		goto probe_err2;
 
 
 	ret = hid_parse(hid_dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-ids.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-ids.h
@@ -79,10 +79,10 @@
 #define HID_DEVICE_ID_ALPS_U1_DUAL_PTP	0x121F
 #define HID_DEVICE_ID_ALPS_U1_DUAL_3BTN_PTP	0x1220
 #define HID_DEVICE_ID_ALPS_U1		0x1215
+#define HID_DEVICE_ID_ALPS_U1_UNICORN_LEGACY         0x121E
 #define HID_DEVICE_ID_ALPS_T4_BTNLESS	0x120C
 #define HID_DEVICE_ID_ALPS_1222		0x1222
 
-
 #define USB_VENDOR_ID_AMI		0x046b
 #define USB_DEVICE_ID_AMI_VIRT_KEYBOARD_AND_MOUSE	0xff10
 
@@ -175,6 +175,7 @@
 #define USB_DEVICE_ID_APPLE_IRCONTROL3	0x8241
 #define USB_DEVICE_ID_APPLE_IRCONTROL4	0x8242
 #define USB_DEVICE_ID_APPLE_IRCONTROL5	0x8243
+#define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021   0x029c
 
 #define USB_VENDOR_ID_ASUS		0x0486
 #define USB_DEVICE_ID_ASUS_T91MT	0x0185
@@ -337,6 +338,8 @@
 #define USB_DEVICE_ID_CYPRESS_BARCODE_4	0xed81
 #define USB_DEVICE_ID_CYPRESS_TRUETOUCH	0xc001
 
+#define USB_DEVICE_ID_CYPRESS_VARMILO_VA104M_07B1   0X07b1
+
 #define USB_VENDOR_ID_DATA_MODUL	0x7374
 #define USB_VENDOR_ID_DATA_MODUL_EASYMAXTOUCH	0x1201
 
@@ -348,6 +351,7 @@
 
 #define USB_VENDOR_ID_DELL				0x413c
 #define USB_DEVICE_ID_DELL_PIXART_USB_OPTICAL_MOUSE	0x301a
+#define USB_DEVICE_ID_DELL_PRO_WIRELESS_KM5221W		0x4503
 
 #define USB_VENDOR_ID_DELORME		0x1163
 #define USB_DEVICE_ID_DELORME_EARTHMATE	0x0100
@@ -363,6 +367,7 @@
 #define USB_DEVICE_ID_DRAGONRISE_DOLPHINBAR	0x1803
 #define USB_DEVICE_ID_DRAGONRISE_GAMECUBE1	0x1843
 #define USB_DEVICE_ID_DRAGONRISE_GAMECUBE2	0x1844
+#define USB_DEVICE_ID_DRAGONRISE_GAMECUBE3	0x1846
 
 #define USB_VENDOR_ID_DWAV		0x0eef
 #define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER	0x0001
@@ -385,11 +390,13 @@
 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7349	0x7349
 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_73F7	0x73f7
 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001	0xa001
+#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_C002	0xc002
 
 #define USB_VENDOR_ID_ELAN		0x04f3
 #define USB_DEVICE_ID_TOSHIBA_CLICK_L9W	0x0401
 #define USB_DEVICE_ID_HP_X2		0x074d
 #define USB_DEVICE_ID_HP_X2_10_COVER	0x0755
+#define USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN	0x2706
 
 #define USB_VENDOR_ID_ELECOM		0x056e
 #define USB_DEVICE_ID_ELECOM_BM084	0x0061
@@ -448,6 +455,10 @@
 #define USB_VENDOR_ID_FRUCTEL	0x25B6
 #define USB_DEVICE_ID_GAMETEL_MT_MODE	0x0002
 
+#define USB_VENDOR_ID_GAMEVICE	0x27F8
+#define USB_DEVICE_ID_GAMEVICE_GV186	0x0BBE
+#define USB_DEVICE_ID_GAMEVICE_KISHI	0x0BBF
+
 #define USB_VENDOR_ID_GAMERON		0x0810
 #define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR	0x0001
 #define USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR	0x0002
@@ -478,6 +489,10 @@
 #define USB_DEVICE_ID_GOOGLE_WHISKERS	0x5030
 #define USB_DEVICE_ID_GOOGLE_MASTERBALL	0x503c
 #define USB_DEVICE_ID_GOOGLE_MAGNEMITE	0x503d
+#define USB_DEVICE_ID_GOOGLE_MOONBALL	0x5044
+#define USB_DEVICE_ID_GOOGLE_DON	0x5050
+#define USB_DEVICE_ID_GOOGLE_EEL	0x5057
+#define USB_DEVICE_ID_GOOGLE_JEWEL	0x5061
 
 #define USB_VENDOR_ID_GOTOP		0x08f2
 #define USB_DEVICE_ID_SUPER_Q2		0x007f
@@ -485,6 +500,7 @@
 #define USB_DEVICE_ID_PENPOWER		0x00f4
 
 #define USB_VENDOR_ID_GREENASIA		0x0e8f
+#define USB_DEVICE_ID_GREENASIA_DUAL_SAT_ADAPTOR 0x3010
 #define USB_DEVICE_ID_GREENASIA_DUAL_USB_JOYPAD	0x3013
 
 #define USB_VENDOR_ID_GRETAGMACBETH	0x0971
@@ -567,12 +583,14 @@
 #define USB_DEVICE_ID_UGCI_FIGHTING	0x0030
 
 #define USB_VENDOR_ID_HP		0x03f0
+#define USB_PRODUCT_ID_HP_ELITE_PRESENTER_MOUSE_464A		0x464a
 #define USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0A4A	0x0a4a
 #define USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A	0x0b4a
 #define USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE		0x134a
 #define USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_094A	0x094a
 #define USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_0941	0x0941
 #define USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_0641	0x0641
+#define USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_1f4a	0x1f4a
 
 #define USB_VENDOR_ID_HUION		0x256c
 #define USB_DEVICE_ID_HUION_TABLET	0x006e
@@ -617,6 +635,7 @@
 #define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081	0xa081
 #define USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A0C2	0xa0c2
 #define USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A096	0xa096
+#define USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A293	0xa293
 
 #define USB_VENDOR_ID_IMATION		0x0718
 #define USB_DEVICE_ID_DISC_STAKKA	0xd000
@@ -628,10 +647,14 @@
 #define USB_DEVICE_ID_INNEX_GENESIS_ATARI	0x4745
 
 #define USB_VENDOR_ID_ITE               0x048d
+#define I2C_VENDOR_ID_ITE		0x103c
+#define I2C_DEVICE_ID_ITE_VOYO_WINPAD_A15	0x184f
 #define USB_DEVICE_ID_ITE_LENOVO_YOGA   0x8386
 #define USB_DEVICE_ID_ITE_LENOVO_YOGA2  0x8350
+#define I2C_DEVICE_ID_ITE_LENOVO_LEGION_Y720	0x837a
 #define USB_DEVICE_ID_ITE_LENOVO_YOGA900	0x8396
 #define USB_DEVICE_ID_ITE8595		0x8595
+#define USB_DEVICE_ID_ITE_MEDION_E1239T	0xce50
 
 #define USB_VENDOR_ID_JABRA		0x0b0e
 #define USB_DEVICE_ID_JABRA_SPEAK_410	0x0412
@@ -724,15 +747,22 @@
 #define USB_DEVICE_ID_LENOVO_X1_COVER	0x6085
 #define USB_DEVICE_ID_LENOVO_X1_TAB	0x60a3
 #define USB_DEVICE_ID_LENOVO_X1_TAB3	0x60b5
+#define USB_DEVICE_ID_LENOVO_OPTICAL_USB_MOUSE_600E	0x600e
+#define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_608D	0x608d
+#define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_6019	0x6019
+#define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_602E	0x602e
+#define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_6093	0x6093
 
 #define USB_VENDOR_ID_LG		0x1fd2
 #define USB_DEVICE_ID_LG_MULTITOUCH	0x0064
 #define USB_DEVICE_ID_LG_MELFAS_MT	0x6007
 #define I2C_DEVICE_ID_LG_8001		0x8001
+#define I2C_DEVICE_ID_LG_7010		0x7010
 
 #define USB_VENDOR_ID_LOGITECH		0x046d
 #define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e
 #define USB_DEVICE_ID_LOGITECH_T651	0xb00c
+#define USB_DEVICE_ID_LOGITECH_DINOVO_EDGE_KBD	0xb309
 #define USB_DEVICE_ID_LOGITECH_C007	0xc007
 #define USB_DEVICE_ID_LOGITECH_C077	0xc077
 #define USB_DEVICE_ID_LOGITECH_RECEIVER	0xc101
@@ -764,6 +794,7 @@
 #define USB_DEVICE_ID_LOGITECH_G27_WHEEL	0xc29b
 #define USB_DEVICE_ID_LOGITECH_WII_WHEEL	0xc29c
 #define USB_DEVICE_ID_LOGITECH_ELITE_KBD	0xc30a
+#define USB_DEVICE_ID_LOGITECH_GROUP_AUDIO	0x0882
 #define USB_DEVICE_ID_S510_RECEIVER	0xc50c
 #define USB_DEVICE_ID_S510_RECEIVER_2	0xc517
 #define USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500	0xc512
@@ -792,6 +823,7 @@
 #define USB_DEVICE_ID_MADCATZ_BEATPAD	0x4540
 #define USB_DEVICE_ID_MADCATZ_RAT5	0x1705
 #define USB_DEVICE_ID_MADCATZ_RAT9	0x1709
+#define USB_DEVICE_ID_MADCATZ_MMO7  0x1713
 
 #define USB_VENDOR_ID_MCC		0x09db
 #define USB_DEVICE_ID_MCC_PMD1024LS	0x0076
@@ -833,8 +865,19 @@
 #define USB_DEVICE_ID_MS_TOUCH_COVER_2   0x07a7
 #define USB_DEVICE_ID_MS_TYPE_COVER_2    0x07a9
 #define USB_DEVICE_ID_MS_POWER_COVER     0x07da
-#define USB_DEVICE_ID_MS_XBOX_ONE_S_CONTROLLER	0x02fd
+#define USB_DEVICE_ID_MS_SURFACE3_COVER		0x07de
+/*
+ * For a description of the Xbox controller models, refer to:
+ * https://en.wikipedia.org/wiki/Xbox_Wireless_Controller#Summary
+ */
+#define USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1708	0x02fd
+#define USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1708_BLE	0x0b20
+#define USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1914	0x0b13
+#define USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1797	0x0b05
+#define USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1797_BLE	0x0b22
 #define USB_DEVICE_ID_MS_PIXART_MOUSE    0x00cb
+#define USB_DEVICE_ID_8BITDO_SN30_PRO_PLUS      0x02e0
+#define USB_DEVICE_ID_MS_MOUSE_0783      0x0783
 
 #define USB_VENDOR_ID_MOJO		0x8282
 #define USB_DEVICE_ID_RETRO_ADAPTER	0x3201
@@ -907,6 +950,12 @@
 #define USB_DEVICE_ID_ORTEK_IHOME_IMAC_A210S	0x8003
 
 #define USB_VENDOR_ID_PLANTRONICS	0x047f
+#define USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3210_SERIES	0xc055
+#define USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3220_SERIES	0xc056
+#define USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3215_SERIES	0xc057
+#define USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3225_SERIES	0xc058
+#define USB_DEVICE_ID_PLANTRONICS_BLACKWIRE_3325_SERIES	0x430c
+#define USB_DEVICE_ID_PLANTRONICS_ENCOREPRO_500_SERIES		0x431e
 
 #define USB_VENDOR_ID_PANASONIC		0x04da
 #define USB_DEVICE_ID_PANABOARD_UBT780	0x1044
@@ -956,9 +1005,11 @@
 #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001		0x3001
 #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3003		0x3003
 #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008		0x3008
+#define USB_DEVICE_ID_QUANTA_HP_5MP_CAMERA_5473		0x5473
 
 #define I2C_VENDOR_ID_RAYDIUM		0x2386
 #define I2C_PRODUCT_ID_RAYDIUM_4B33	0x4b33
+#define I2C_PRODUCT_ID_RAYDIUM_3118	0x3118
 
 #define USB_VENDOR_ID_RAZER            0x1532
 #define USB_DEVICE_ID_RAZER_BLADE_14   0x011D
@@ -988,6 +1039,8 @@
 #define USB_DEVICE_ID_ROCCAT_RYOS_MK_PRO	0x3232
 #define USB_DEVICE_ID_ROCCAT_SAVU	0x2d5a
 
+#define USB_VENDOR_ID_SAI		0x17dd
+
 #define USB_VENDOR_ID_SAITEK		0x06a3
 #define USB_DEVICE_ID_SAITEK_RUMBLEPAD	0xff17
 #define USB_DEVICE_ID_SAITEK_PS1000	0x0621
@@ -997,6 +1050,9 @@
 #define USB_DEVICE_ID_SAITEK_RAT9	0x0cfa
 #define USB_DEVICE_ID_SAITEK_MMO7	0x0cd0
 #define USB_DEVICE_ID_SAITEK_X52	0x075c
+#define USB_DEVICE_ID_SAITEK_X52_2	0x0255
+#define USB_DEVICE_ID_SAITEK_X52_PRO	0x0762
+#define USB_DEVICE_ID_SAITEK_X65	0x0b6a
 
 #define USB_VENDOR_ID_SAMSUNG		0x0419
 #define USB_DEVICE_ID_SAMSUNG_IR_REMOTE	0x0001
@@ -1082,6 +1138,9 @@
 #define USB_DEVICE_ID_SYMBOL_SCANNER_2	0x1300
 #define USB_DEVICE_ID_SYMBOL_SCANNER_3	0x1200
 
+#define I2C_VENDOR_ID_SYNAPTICS     0x06cb
+#define I2C_PRODUCT_ID_SYNAPTICS_SYNA2393   0x7a13
+
 #define USB_VENDOR_ID_SYNAPTICS		0x06cb
 #define USB_DEVICE_ID_SYNAPTICS_TP	0x0001
 #define USB_DEVICE_ID_SYNAPTICS_INT_TP	0x0002
@@ -1096,7 +1155,12 @@
 #define USB_DEVICE_ID_SYNAPTICS_LTS2	0x1d10
 #define USB_DEVICE_ID_SYNAPTICS_HD	0x0ac3
 #define USB_DEVICE_ID_SYNAPTICS_QUAD_HD	0x1ac3
+#define USB_DEVICE_ID_SYNAPTICS_DELL_K12A	0x2819
+#define USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012	0x2968
 #define USB_DEVICE_ID_SYNAPTICS_TP_V103	0x5710
+#define USB_DEVICE_ID_SYNAPTICS_ACER_ONE_S1002	0x73f4
+#define USB_DEVICE_ID_SYNAPTICS_ACER_ONE_S1003	0x73f5
+#define USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_017	0x73f6
 #define USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5	0x81a7
 
 #define USB_VENDOR_ID_TEXAS_INSTRUMENTS	0x2047
@@ -1135,6 +1199,9 @@
 #define USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN_8882	0x8882
 #define USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN_8883	0x8883
 
+#define USB_VENDOR_ID_TRUST             0x145f
+#define USB_DEVICE_ID_TRUST_PANORA_TABLET   0x0212
+
 #define USB_VENDOR_ID_TURBOX		0x062a
 #define USB_DEVICE_ID_TURBOX_KEYBOARD	0x0201
 #define USB_DEVICE_ID_ASUS_MD_5110	0x5110
@@ -1247,6 +1314,7 @@
 
 #define USB_VENDOR_ID_PRIMAX	0x0461
 #define USB_DEVICE_ID_PRIMAX_MOUSE_4D22	0x4d22
+#define USB_DEVICE_ID_PRIMAX_MOUSE_4E2A	0x4e2a
 #define USB_DEVICE_ID_PRIMAX_KEYBOARD	0x4e05
 #define USB_DEVICE_ID_PRIMAX_REZEL	0x4e72
 #define USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4D0F	0x4d0f
@@ -1266,6 +1334,8 @@
 
 #define USB_VENDOR_ID_UGTIZER			0x2179
 #define USB_DEVICE_ID_UGTIZER_TABLET_GP0610	0x0053
+#define USB_DEVICE_ID_UGTIZER_TABLET_GT5040	0x0077
+#define USB_DEVICE_ID_UGTIZER_TABLET_WP5540	0x0004
 
 #define USB_VENDOR_ID_VIEWSONIC			0x0543
 #define USB_DEVICE_ID_VIEWSONIC_PD1011		0xe621
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-input.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-input.c
@@ -319,6 +319,11 @@
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ASUSTEK,
 		USB_DEVICE_ID_ASUSTEK_T100CHI_KEYBOARD),
 	  HID_BATTERY_QUIRK_IGNORE },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH,
+		USB_DEVICE_ID_LOGITECH_DINOVO_EDGE_KBD),
+	  HID_BATTERY_QUIRK_IGNORE },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN),
+	  HID_BATTERY_QUIRK_IGNORE },
 	{}
 };
 
@@ -350,13 +355,13 @@
 	u8 *buf;
 	int ret;
 
-	buf = kmalloc(2, GFP_KERNEL);
+	buf = kmalloc(4, GFP_KERNEL);
 	if (!buf)
 		return -ENOMEM;
 
-	ret = hid_hw_raw_request(dev, dev->battery_report_id, buf, 2,
+	ret = hid_hw_raw_request(dev, dev->battery_report_id, buf, 4,
 				 dev->battery_report_type, HID_REQ_GET_REPORT);
-	if (ret != 2) {
+	if (ret < 2) {
 		kfree(buf);
 		return -ENODATA;
 	}
@@ -410,8 +415,6 @@
 
 		if (dev->battery_status == HID_BATTERY_UNKNOWN)
 			val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
-		else if (dev->battery_capacity == 100)
-			val->intval = POWER_SUPPLY_STATUS_FULL;
 		else
 			val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
 		break;
@@ -668,6 +671,14 @@
 			break;
 		}
 
+		if ((usage->hid & 0xf0) == 0xa0) {	/* SystemControl */
+			switch (usage->hid & 0xf) {
+			case 0x9: map_key_clear(KEY_MICMUTE); break;
+			default: goto ignore;
+			}
+			break;
+		}
+
 		if ((usage->hid & 0xf0) == 0xb0) {	/* SC - Display */
 			switch (usage->hid & 0xf) {
 			case 0x05: map_key_clear(KEY_SWITCHVIDEOMODE); break;
@@ -797,7 +808,7 @@
 		case 0x3b: /* Battery Strength */
 			hidinput_setup_battery(device, HID_INPUT_REPORT, field);
 			usage->type = EV_PWR;
-			goto ignore;
+			return;
 
 		case 0x3c: /* Invert */
 			map_key_clear(BTN_TOOL_RUBBER);
@@ -952,6 +963,10 @@
 
 		case 0x0cd: map_key_clear(KEY_PLAYPAUSE);	break;
 		case 0x0cf: map_key_clear(KEY_VOICECOMMAND);	break;
+
+		case 0x0d8: map_key_clear(KEY_DICTATE);		break;
+		case 0x0d9: map_key_clear(KEY_EMOJI_PICKER);	break;
+
 		case 0x0e0: map_abs_clear(ABS_VOLUME);		break;
 		case 0x0e2: map_key_clear(KEY_MUTE);		break;
 		case 0x0e5: map_key_clear(KEY_BASSBOOST);	break;
@@ -1041,6 +1056,8 @@
 
 		case 0x29d: map_key_clear(KEY_KBD_LAYOUT_NEXT);	break;
 
+		case 0x2a2: map_key_clear(KEY_ALL_APPLICATIONS);	break;
+
 		case 0x2c7: map_key_clear(KEY_KBDINPUTASSIST_PREV);		break;
 		case 0x2c8: map_key_clear(KEY_KBDINPUTASSIST_NEXT);		break;
 		case 0x2c9: map_key_clear(KEY_KBDINPUTASSIST_PREVGROUP);		break;
@@ -1059,7 +1076,7 @@
 		case HID_DC_BATTERYSTRENGTH:
 			hidinput_setup_battery(device, HID_INPUT_REPORT, field);
 			usage->type = EV_PWR;
-			goto ignore;
+			return;
 		}
 		goto unknown;
 
@@ -1132,9 +1149,19 @@
 	}
 
 mapped:
-	if (device->driver->input_mapped && device->driver->input_mapped(device,
-				hidinput, field, usage, &bit, &max) < 0)
-		goto ignore;
+	/* Mapping failed, bail out */
+	if (!bit)
+		return;
+
+	if (device->driver->input_mapped &&
+	    device->driver->input_mapped(device, hidinput, field, usage,
+					 &bit, &max) < 0) {
+		/*
+		 * The driver indicated that no further generic handling
+		 * of the usage is desired.
+		 */
+		return;
+	}
 
 	set_bit(usage->type, input->evbit);
 
@@ -1215,9 +1242,11 @@
 		set_bit(MSC_SCAN, input->mscbit);
 	}
 
-ignore:
 	return;
 
+ignore:
+	usage->type = 0;
+	usage->code = 0;
 }
 
 static void hidinput_handle_scroll(struct hid_usage *usage,
@@ -1270,6 +1299,12 @@
 
 	input = field->hidinput->input;
 
+	if (usage->type == EV_ABS &&
+	    (((*quirks & HID_QUIRK_X_INVERT) && usage->code == ABS_X) ||
+	     ((*quirks & HID_QUIRK_Y_INVERT) && usage->code == ABS_Y))) {
+		value = field->logical_maximum - value;
+	}
+
 	if (usage->hat_min < usage->hat_max || usage->hat_dir) {
 		int hat_dir = usage->hat_dir;
 		if (!hat_dir)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-ite.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-ite.c
@@ -11,6 +11,59 @@
 
 #include "hid-ids.h"
 
+#define QUIRK_TOUCHPAD_ON_OFF_REPORT		BIT(0)
+
+static __u8 *ite_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize)
+{
+	unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+
+	if (quirks & QUIRK_TOUCHPAD_ON_OFF_REPORT) {
+		/* For Acer Aspire Switch 10 SW5-012 keyboard-dock */
+		if (*rsize == 188 && rdesc[162] == 0x81 && rdesc[163] == 0x02) {
+			hid_info(hdev, "Fixing up Acer Sw5-012 ITE keyboard report descriptor\n");
+			rdesc[163] = HID_MAIN_ITEM_RELATIVE;
+		}
+		/* For Acer One S1002/S1003 keyboard-dock */
+		if (*rsize == 188 && rdesc[185] == 0x81 && rdesc[186] == 0x02) {
+			hid_info(hdev, "Fixing up Acer S1002/S1003 ITE keyboard report descriptor\n");
+			rdesc[186] = HID_MAIN_ITEM_RELATIVE;
+		}
+		/* For Acer Aspire Switch 10E (SW3-016) keyboard-dock */
+		if (*rsize == 210 && rdesc[184] == 0x81 && rdesc[185] == 0x02) {
+			hid_info(hdev, "Fixing up Acer Aspire Switch 10E (SW3-016) ITE keyboard report descriptor\n");
+			rdesc[185] = HID_MAIN_ITEM_RELATIVE;
+		}
+	}
+
+	return rdesc;
+}
+
+static int ite_input_mapping(struct hid_device *hdev,
+		struct hid_input *hi, struct hid_field *field,
+		struct hid_usage *usage, unsigned long **bit,
+		int *max)
+{
+
+	unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+
+	if ((quirks & QUIRK_TOUCHPAD_ON_OFF_REPORT) &&
+	    (usage->hid & HID_USAGE_PAGE) == 0x00880000) {
+		if (usage->hid == 0x00880078) {
+			/* Touchpad on, userspace expects F22 for this */
+			hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_F22);
+			return 1;
+		}
+		if (usage->hid == 0x00880079) {
+			/* Touchpad off, userspace expects F23 for this */
+			hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_F23);
+			return 1;
+		}
+		return -1;
+	}
+
+	return 0;
+}
+
 static int ite_event(struct hid_device *hdev, struct hid_field *field,
 		     struct hid_usage *usage, __s32 value)
 {
@@ -37,9 +90,42 @@
 	return 0;
 }
 
+static int ite_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+	int ret;
+
+	hid_set_drvdata(hdev, (void *)id->driver_data);
+
+	ret = hid_open_report(hdev);
+	if (ret)
+		return ret;
+
+	return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+}
+
 static const struct hid_device_id ite_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE8595) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_258A, USB_DEVICE_ID_258A_6A88) },
+	/* ITE8595 USB kbd ctlr, with Synaptics touchpad connected to it. */
+	{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
+		     USB_VENDOR_ID_SYNAPTICS,
+		     USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012),
+	  .driver_data = QUIRK_TOUCHPAD_ON_OFF_REPORT },
+	/* ITE8910 USB kbd ctlr, with Synaptics touchpad connected to it. */
+	{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
+		     USB_VENDOR_ID_SYNAPTICS,
+		     USB_DEVICE_ID_SYNAPTICS_ACER_ONE_S1002),
+	  .driver_data = QUIRK_TOUCHPAD_ON_OFF_REPORT },
+	/* ITE8910 USB kbd ctlr, with Synaptics touchpad connected to it. */
+	{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
+		     USB_VENDOR_ID_SYNAPTICS,
+		     USB_DEVICE_ID_SYNAPTICS_ACER_ONE_S1003),
+	  .driver_data = QUIRK_TOUCHPAD_ON_OFF_REPORT },
+	/* ITE8910 USB kbd ctlr, with Synaptics touchpad connected to it. */
+	{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
+		     USB_VENDOR_ID_SYNAPTICS,
+		     USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_017),
+	  .driver_data = QUIRK_TOUCHPAD_ON_OFF_REPORT },
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, ite_devices);
@@ -47,6 +133,9 @@
 static struct hid_driver ite_driver = {
 	.name = "itetech",
 	.id_table = ite_devices,
+	.probe = ite_probe,
+	.report_fixup = ite_report_fixup,
+	.input_mapping = ite_input_mapping,
 	.event = ite_event,
 };
 module_hid_driver(ite_driver);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-led.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-led.c
@@ -366,7 +366,7 @@
 		.type = DREAM_CHEEKY,
 		.name = "Dream Cheeky Webmail Notifier",
 		.short_name = "dream_cheeky",
-		.max_brightness = 31,
+		.max_brightness = 63,
 		.num_leds = 1,
 		.report_size = 9,
 		.report_type = RAW_REQUEST,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-lg.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-lg.c
@@ -769,12 +769,18 @@
 
 static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
-	struct usb_interface *iface = to_usb_interface(hdev->dev.parent);
-	__u8 iface_num = iface->cur_altsetting->desc.bInterfaceNumber;
+	struct usb_interface *iface;
+	__u8 iface_num;
 	unsigned int connect_mask = HID_CONNECT_DEFAULT;
 	struct lg_drv_data *drv_data;
 	int ret;
 
+	if (!hid_is_usb(hdev))
+		return -EINVAL;
+
+	iface = to_usb_interface(hdev->dev.parent);
+	iface_num = iface->cur_altsetting->desc.bInterfaceNumber;
+
 	/* G29 only work with the 1st interface */
 	if ((hdev->product == USB_DEVICE_ID_LOGITECH_G29_WHEEL) &&
 	    (iface_num != 0)) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-lg4ff.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-lg4ff.c
@@ -872,6 +872,12 @@
 		return -ENOMEM;
 
 	i = strlen(lbuf);
+
+	if (i == 0) {
+		kfree(lbuf);
+		return -EINVAL;
+	}
+
 	if (lbuf[i-1] == '\n') {
 		if (i == 1) {
 			kfree(lbuf);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-logitech-dj.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-logitech-dj.c
@@ -328,7 +328,7 @@
 	0x25, 0x01,		/*      LOGICAL_MAX (1)                 */
 	0x75, 0x01,		/*      REPORT_SIZE (1)                 */
 	0x95, 0x04,		/*      REPORT_COUNT (4)                */
-	0x81, 0x06,		/*      INPUT                           */
+	0x81, 0x02,		/*      INPUT (Data,Var,Abs)            */
 	0xC0,			/*    END_COLLECTION                    */
 	0xC0,			/*  END_COLLECTION                      */
 };
@@ -866,11 +866,24 @@
 	schedule_work(&djrcv_dev->work);
 }
 
+/*
+ * Some quad/bluetooth keyboards have a builtin touchpad in this case we see
+ * only 1 paired device with a device_type of REPORT_TYPE_KEYBOARD. For the
+ * touchpad to work we must also forward mouse input reports to the dj_hiddev
+ * created for the keyboard (instead of forwarding them to a second paired
+ * device with a device_type of REPORT_TYPE_MOUSE as we normally would).
+ */
+static const u16 kbd_builtin_touchpad_ids[] = {
+	0xb309, /* Dinovo Edge */
+	0xb30c, /* Dinovo Mini */
+};
+
 static void logi_hidpp_dev_conn_notif_equad(struct hid_device *hdev,
 					    struct hidpp_event *hidpp_report,
 					    struct dj_workitem *workitem)
 {
 	struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
+	int i, id;
 
 	workitem->type = WORKITEM_TYPE_PAIRED;
 	workitem->device_type = hidpp_report->params[HIDPP_PARAM_DEVICE_INFO] &
@@ -882,6 +895,13 @@
 		workitem->reports_supported |= STD_KEYBOARD | MULTIMEDIA |
 					       POWER_KEYS | MEDIA_CENTER |
 					       HIDPP;
+		id = (workitem->quad_id_msb << 8) | workitem->quad_id_lsb;
+		for (i = 0; i < ARRAY_SIZE(kbd_builtin_touchpad_ids); i++) {
+			if (id == kbd_builtin_touchpad_ids[i]) {
+				workitem->reports_supported |= STD_MOUSE;
+				break;
+			}
+		}
 		break;
 	case REPORT_TYPE_MOUSE:
 		workitem->reports_supported |= STD_MOUSE | HIDPP;
@@ -960,6 +980,7 @@
 	case 0x07:
 		device_type = "eQUAD step 4 Gaming";
 		logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem);
+		workitem.reports_supported |= STD_KEYBOARD;
 		break;
 	case 0x08:
 		device_type = "eQUAD step 4 for gamepads";
@@ -974,7 +995,13 @@
 		workitem.reports_supported |= STD_KEYBOARD;
 		break;
 	case 0x0d:
-		device_type = "eQUAD Lightspeed 1_1";
+		device_type = "eQUAD Lightspeed 1.1";
+		logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem);
+		workitem.reports_supported |= STD_KEYBOARD;
+		break;
+	case 0x0f:
+	case 0x11:
+		device_type = "eQUAD Lightspeed 1.2";
 		logi_hidpp_dev_conn_notif_equad(hdev, hidpp_report, &workitem);
 		workitem.reports_supported |= STD_KEYBOARD;
 		break;
@@ -1185,6 +1212,11 @@
 		 * 50 msec should gives enough time to the receiver to be ready.
 		 */
 		msleep(50);
+
+		if (retval) {
+			kfree(dj_report);
+			return retval;
+		}
 	}
 
 	/*
@@ -1206,7 +1238,7 @@
 	buf[5] = 0x09;
 	buf[6] = 0x00;
 
-	hid_hw_raw_request(hdev, REPORT_ID_HIDPP_SHORT, buf,
+	retval = hid_hw_raw_request(hdev, REPORT_ID_HIDPP_SHORT, buf,
 			HIDPP_REPORT_SHORT_LENGTH, HID_OUTPUT_REPORT,
 			HID_REQ_SET_REPORT);
 
@@ -1660,7 +1692,7 @@
 	case recvr_type_27mhz:		no_dj_interfaces = 2; break;
 	case recvr_type_bluetooth:	no_dj_interfaces = 2; break;
 	}
-	if (hid_is_using_ll_driver(hdev, &usb_hid_driver)) {
+	if (hid_is_usb(hdev)) {
 		intf = to_usb_interface(hdev->dev.parent);
 		if (intf && intf->altsetting->desc.bInterfaceNumber >=
 							no_dj_interfaces) {
@@ -1842,6 +1874,10 @@
 	  HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
 		0xc531),
 	 .driver_data = recvr_type_gaming_hidpp},
+	{ /* Logitech G602 receiver (0xc537) */
+	  HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
+		0xc537),
+	 .driver_data = recvr_type_gaming_hidpp},
 	{ /* Logitech lightspeed receiver (0xc539) */
 	  HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
 		USB_DEVICE_ID_LOGITECH_NANO_RECEIVER_LIGHTSPEED_1),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-logitech-hidpp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-logitech-hidpp.c
@@ -88,6 +88,8 @@
 #define HIDPP_CAPABILITY_BATTERY_MILEAGE	BIT(2)
 #define HIDPP_CAPABILITY_BATTERY_LEVEL_STATUS	BIT(3)
 
+#define lg_map_key_clear(c)  hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c))
+
 /*
  * There are two hidpp protocols in use, the first version hidpp10 is known
  * as register access protocol or RAP, the second version hidpp20 is known as
@@ -807,8 +809,7 @@
 	if (ret)
 		return ret;
 
-	snprintf(hdev->uniq, sizeof(hdev->uniq), "%04x-%4phD",
-		 hdev->product, &serial);
+	snprintf(hdev->uniq, sizeof(hdev->uniq), "%4phD", &serial);
 	dbg_hid("HID++ Unifying: Got serial: %s\n", hdev->uniq);
 
 	name = hidpp_unifying_get_name(hidpp);
@@ -902,6 +903,54 @@
 }
 
 /* -------------------------------------------------------------------------- */
+/* 0x0003: Device Information                                                 */
+/* -------------------------------------------------------------------------- */
+
+#define HIDPP_PAGE_DEVICE_INFORMATION			0x0003
+
+#define CMD_GET_DEVICE_INFO				0x00
+
+static int hidpp_get_serial(struct hidpp_device *hidpp, u32 *serial)
+{
+	struct hidpp_report response;
+	u8 feature_type;
+	u8 feature_index;
+	int ret;
+
+	ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_DEVICE_INFORMATION,
+				     &feature_index,
+				     &feature_type);
+	if (ret)
+		return ret;
+
+	ret = hidpp_send_fap_command_sync(hidpp, feature_index,
+					  CMD_GET_DEVICE_INFO,
+					  NULL, 0, &response);
+	if (ret)
+		return ret;
+
+	/* See hidpp_unifying_get_serial() */
+	*serial = *((u32 *)&response.rap.params[1]);
+	return 0;
+}
+
+static int hidpp_serial_init(struct hidpp_device *hidpp)
+{
+	struct hid_device *hdev = hidpp->hid_dev;
+	u32 serial;
+	int ret;
+
+	ret = hidpp_get_serial(hidpp, &serial);
+	if (ret)
+		return ret;
+
+	snprintf(hdev->uniq, sizeof(hdev->uniq), "%4phD", &serial);
+	dbg_hid("HID++ DeviceInformation: Got serial: %s\n", hdev->uniq);
+
+	return 0;
+}
+
+/* -------------------------------------------------------------------------- */
 /* 0x0005: GetDeviceNameType                                                  */
 /* -------------------------------------------------------------------------- */
 
@@ -1102,6 +1151,9 @@
 	ret = hidpp_send_fap_command_sync(hidpp, feature_index,
 					  CMD_BATTERY_LEVEL_STATUS_GET_BATTERY_LEVEL_STATUS,
 					  NULL, 0, &response);
+	/* Ignore these intermittent errors */
+	if (ret == HIDPP_ERROR_RESOURCE_ERROR)
+		return -EIO;
 	if (ret > 0) {
 		hid_err(hidpp->hid_dev, "%s: received protocol error 0x%02x\n",
 			__func__, ret);
@@ -2766,6 +2818,26 @@
 }
 
 /* -------------------------------------------------------------------------- */
+/* Logitech Dinovo Mini keyboard with builtin touchpad                        */
+/* -------------------------------------------------------------------------- */
+#define DINOVO_MINI_PRODUCT_ID		0xb30c
+
+static int lg_dinovo_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+		struct hid_field *field, struct hid_usage *usage,
+		unsigned long **bit, int *max)
+{
+	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
+		return 0;
+
+	switch (usage->hid & HID_USAGE) {
+	case 0x00d: lg_map_key_clear(KEY_MEDIA);	break;
+	default:
+		return 0;
+	}
+	return 1;
+}
+
+/* -------------------------------------------------------------------------- */
 /* HID++1.0 devices which use HID++ reports for their wheels                  */
 /* -------------------------------------------------------------------------- */
 static int hidpp10_wheel_connect(struct hidpp_device *hidpp)
@@ -2961,7 +3033,7 @@
 		multiplier = 1;
 
 	hidpp->vertical_wheel_counter.wheel_multiplier = multiplier;
-	hid_info(hidpp->hid_dev, "multiplier = %d\n", multiplier);
+	hid_dbg(hidpp->hid_dev, "wheel multiplier = %d\n", multiplier);
 	return 0;
 }
 
@@ -3000,6 +3072,9 @@
 			field->application != HID_GD_MOUSE)
 		return m560_input_mapping(hdev, hi, field, usage, bit, max);
 
+	if (hdev->product == DINOVO_MINI_PRODUCT_ID)
+		return lg_dinovo_input_mapping(hdev, hi, field, usage, bit, max);
+
 	return 0;
 }
 
@@ -3623,6 +3698,8 @@
 
 	if (hidpp->quirks & HIDPP_QUIRK_UNIFYING)
 		hidpp_unifying_init(hidpp);
+	else if (hid_is_usb(hidpp->hid_dev))
+		hidpp_serial_init(hidpp);
 
 	connected = hidpp_root_get_protocol_version(hidpp) == 0;
 	atomic_set(&hidpp->connected, connected);
@@ -3646,7 +3723,8 @@
 			goto hid_hw_init_fail;
 	}
 
-	hidpp_connect_event(hidpp);
+	schedule_work(&hidpp->work);
+	flush_work(&hidpp->work);
 
 	/* Reset the HID node state */
 	hid_device_io_stop(hdev);
@@ -3738,6 +3816,7 @@
 	  LDJ_DEVICE(0x405e), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
 	{ /* Mouse Logitech MX Anywhere 2 */
 	  LDJ_DEVICE(0x404a), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
+	{ LDJ_DEVICE(0x4072), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
 	{ LDJ_DEVICE(0xb013), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
 	{ LDJ_DEVICE(0xb018), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
 	{ LDJ_DEVICE(0xb01f), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
@@ -3760,6 +3839,9 @@
 	{ /* Keyboard MX5000 (Bluetooth-receiver in HID proxy mode) */
 	  LDJ_DEVICE(0xb305),
 	  .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS },
+	{ /* Dinovo Edge (Bluetooth-receiver in HID proxy mode) */
+	  LDJ_DEVICE(0xb309),
+	  .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS },
 	{ /* Keyboard MX5500 (Bluetooth-receiver in HID proxy mode) */
 	  LDJ_DEVICE(0xb30b),
 	  .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS },
@@ -3802,6 +3884,9 @@
 	{ /* MX5000 keyboard over Bluetooth */
 	  HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb305),
 	  .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS },
+	{ /* Dinovo Edge keyboard over Bluetooth */
+	  HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb309),
+	  .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS },
 	{ /* MX5500 keyboard over Bluetooth */
 	  HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb30b),
 	  .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-magicmouse.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-magicmouse.c
@@ -387,7 +387,7 @@
 		magicmouse_raw_event(hdev, report, data + 2, data[1]);
 		magicmouse_raw_event(hdev, report, data + 2 + data[1],
 			size - 2 - data[1]);
-		break;
+		return 0;
 	default:
 		return 0;
 	}
@@ -535,6 +535,12 @@
 		__set_bit(MSC_RAW, input->mscbit);
 	}
 
+	/*
+	 * hid-input may mark device as using autorepeat, but neither
+	 * the trackpad, nor the mouse actually want it.
+	 */
+	__clear_bit(EV_REP, input->evbit);
+
 	return 0;
 }
 
@@ -591,7 +597,7 @@
 	if (id->vendor == USB_VENDOR_ID_APPLE &&
 	    id->product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 &&
 	    hdev->type != HID_TYPE_USBMOUSE)
-		return 0;
+		return -ENODEV;
 
 	msc = devm_kzalloc(&hdev->dev, sizeof(*msc), GFP_KERNEL);
 	if (msc == NULL) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-mf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-mf.c
@@ -153,6 +153,8 @@
 		.driver_data = HID_QUIRK_MULTI_INPUT },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE2),
 		.driver_data = 0 }, /* No quirk required */
+	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE3),
+		.driver_data = HID_QUIRK_MULTI_INPUT },
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, mf_devices);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-microsoft.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-microsoft.c
@@ -449,7 +449,18 @@
 		.driver_data = MS_PRESENTER },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, 0x091B),
 		.driver_data = MS_SURFACE_DIAL },
-	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_XBOX_ONE_S_CONTROLLER),
+
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1708),
+		.driver_data = MS_QUIRK_FF },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1708_BLE),
+		.driver_data = MS_QUIRK_FF },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1914),
+		.driver_data = MS_QUIRK_FF },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1797),
+		.driver_data = MS_QUIRK_FF },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_XBOX_CONTROLLER_MODEL_1797_BLE),
+		.driver_data = MS_QUIRK_FF },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_8BITDO_SN30_PRO_PLUS),
 		.driver_data = MS_QUIRK_FF },
 	{ }
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-multitouch.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-multitouch.c
@@ -69,6 +69,7 @@
 #define MT_QUIRK_ASUS_CUSTOM_UP		BIT(17)
 #define MT_QUIRK_WIN8_PTP_BUTTONS	BIT(18)
 #define MT_QUIRK_SEPARATE_APP_REPORT	BIT(19)
+#define MT_QUIRK_FORCE_MULTI_INPUT	BIT(20)
 
 #define MT_INPUTMODE_TOUCHSCREEN	0x02
 #define MT_INPUTMODE_TOUCHPAD		0x03
@@ -189,6 +190,7 @@
 #define MT_CLS_WIN_8				0x0012
 #define MT_CLS_EXPORT_ALL_INPUTS		0x0013
 #define MT_CLS_WIN_8_DUAL			0x0014
+#define MT_CLS_WIN_8_FORCE_MULTI_INPUT		0x0015
 
 /* vendor specific classes */
 #define MT_CLS_3M				0x0101
@@ -279,6 +281,15 @@
 			MT_QUIRK_CONTACT_CNT_ACCURATE |
 			MT_QUIRK_WIN8_PTP_BUTTONS,
 		.export_all_inputs = true },
+	{ .name = MT_CLS_WIN_8_FORCE_MULTI_INPUT,
+		.quirks = MT_QUIRK_ALWAYS_VALID |
+			MT_QUIRK_IGNORE_DUPLICATES |
+			MT_QUIRK_HOVERING |
+			MT_QUIRK_CONTACT_CNT_ACCURATE |
+			MT_QUIRK_STICKY_FINGERS |
+			MT_QUIRK_WIN8_PTP_BUTTONS |
+			MT_QUIRK_FORCE_MULTI_INPUT,
+		.export_all_inputs = true },
 
 	/*
 	 * vendor specific classes
@@ -600,9 +611,13 @@
 		if (!(HID_MAIN_ITEM_VARIABLE & field->flags))
 			continue;
 
-		for (n = 0; n < field->report_count; n++) {
-			if (field->usage[n].hid == HID_DG_CONTACTID)
-				rdata->is_mt_collection = true;
+		if (field->logical == HID_DG_FINGER || td->hdev->group != HID_GROUP_MULTITOUCH_WIN_8) {
+			for (n = 0; n < field->report_count; n++) {
+				if (field->usage[n].hid == HID_DG_CONTACTID) {
+					rdata->is_mt_collection = true;
+					break;
+				}
+			}
 		}
 	}
 
@@ -853,6 +868,8 @@
 			code = BTN_0  + ((usage->hid - 1) & HID_USAGE);
 
 		hid_map_usage(hi, usage, bit, max, EV_KEY, code);
+		if (!*bit)
+			return -1;
 		input_set_capability(hi->input, EV_KEY, code);
 		return 1;
 
@@ -1019,7 +1036,7 @@
 		tool = MT_TOOL_DIAL;
 	else if (unlikely(!confidence_state)) {
 		tool = MT_TOOL_PALM;
-		if (!active &&
+		if (!active && mt &&
 		    input_mt_is_active(&mt->slots[slotnum])) {
 			/*
 			 * The non-confidence was reported for
@@ -1145,7 +1162,7 @@
 	int contact_count = -1;
 
 	/* sticky fingers release in progress, abort */
-	if (test_and_set_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags))
+	if (test_and_set_bit_lock(MT_IO_FLAGS_RUNNING, &td->mt_io_flags))
 		return;
 
 	scantime = *app->scantime;
@@ -1226,7 +1243,7 @@
 			del_timer(&td->release_timer);
 	}
 
-	clear_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags);
+	clear_bit_unlock(MT_IO_FLAGS_RUNNING, &td->mt_io_flags);
 }
 
 static int mt_touch_input_configured(struct hid_device *hdev,
@@ -1531,7 +1548,6 @@
 static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
 {
 	struct mt_device *td = hid_get_drvdata(hdev);
-	char *name;
 	const char *suffix = NULL;
 	struct mt_report_data *rdata;
 	struct mt_application *mt_application = NULL;
@@ -1570,13 +1586,13 @@
 		/* we do not set suffix = "Touchscreen" */
 		hi->input->name = hdev->name;
 		break;
-	case HID_DG_STYLUS:
-		/* force BTN_STYLUS to allow tablet matching in udev */
-		__set_bit(BTN_STYLUS, hi->input->keybit);
-		break;
 	case HID_VD_ASUS_CUSTOM_MEDIA_KEYS:
 		suffix = "Custom Media Keys";
 		break;
+	case HID_DG_STYLUS:
+		/* force BTN_STYLUS to allow tablet matching in udev */
+		__set_bit(BTN_STYLUS, hi->input->keybit);
+		fallthrough;
 	case HID_DG_PEN:
 		suffix = "Stylus";
 		break;
@@ -1586,13 +1602,10 @@
 	}
 
 	if (suffix) {
-		name = devm_kzalloc(&hi->input->dev,
-				    strlen(hdev->name) + strlen(suffix) + 2,
-				    GFP_KERNEL);
-		if (name) {
-			sprintf(name, "%s %s", hdev->name, suffix);
-			hi->input->name = name;
-		}
+		hi->input->name = devm_kasprintf(&hdev->dev, GFP_KERNEL,
+						 "%s %s", hdev->name, suffix);
+		if (!hi->input->name)
+			return -ENOMEM;
 	}
 
 	return 0;
@@ -1663,11 +1676,11 @@
 	 * An input report came in just before we release the sticky fingers,
 	 * it will take care of the sticky fingers.
 	 */
-	if (test_and_set_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags))
+	if (test_and_set_bit_lock(MT_IO_FLAGS_RUNNING, &td->mt_io_flags))
 		return;
 	if (test_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags))
 		mt_release_contacts(hdev);
-	clear_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags);
+	clear_bit_unlock(MT_IO_FLAGS_RUNNING, &td->mt_io_flags);
 }
 
 static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
@@ -1714,6 +1727,11 @@
 	if (id->group != HID_GROUP_MULTITOUCH_WIN_8)
 		hdev->quirks |= HID_QUIRK_MULTI_INPUT;
 
+	if (mtclass->quirks & MT_QUIRK_FORCE_MULTI_INPUT) {
+		hdev->quirks &= ~HID_QUIRK_INPUT_PER_APP;
+		hdev->quirks |= HID_QUIRK_MULTI_INPUT;
+	}
+
 	timer_setup(&td->release_timer, mt_expired_timeout, 0);
 
 	ret = hid_parse(hdev);
@@ -1922,6 +1940,18 @@
 	{ .driver_data = MT_CLS_EGALAX_SERIAL,
 		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
 			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) },
+	{ .driver_data = MT_CLS_EGALAX,
+		MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
+			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_C002) },
+
+	/* Elan devices */
+	{ .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT,
+		HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
+			USB_VENDOR_ID_ELAN, 0x313a) },
+
+	{ .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT,
+		HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
+			USB_VENDOR_ID_ELAN, 0x3148) },
 
 	/* Elitegroup panel */
 	{ .driver_data = MT_CLS_SERIAL,
@@ -1976,6 +2006,16 @@
 		MT_USB_DEVICE(USB_VENDOR_ID_HANVON_ALT,
 			USB_DEVICE_ID_HANVON_ALT_MULTITOUCH) },
 
+	/* HONOR GLO-GXXX panel */
+	{ .driver_data = MT_CLS_VTL,
+		HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
+			0x347d, 0x7853) },
+
+	/* HONOR MagicBook Art 14 touchpad */
+	{ .driver_data = MT_CLS_VTL,
+		HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
+			0x35cc, 0x0104) },
+
 	/* Ilitek dual touch panel */
 	{  .driver_data = MT_CLS_NSMU,
 		MT_USB_DEVICE(USB_VENDOR_ID_ILITEK,
@@ -1985,6 +2025,9 @@
 	{ .driver_data = MT_CLS_LG,
 		HID_USB_DEVICE(USB_VENDOR_ID_LG,
 			USB_DEVICE_ID_LG_MELFAS_MT) },
+	{ .driver_data = MT_CLS_LG,
+		HID_DEVICE(BUS_I2C, HID_GROUP_GENERIC,
+			USB_VENDOR_ID_LG, I2C_DEVICE_ID_LG_7010) },
 
 	/* MosArt panels */
 	{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
@@ -2050,6 +2093,23 @@
 		MT_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM,
 			USB_DEVICE_ID_MTP_STM)},
 
+	/* Synaptics devices */
+	{ .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT,
+		HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
+			USB_VENDOR_ID_SYNAPTICS, 0xcd7e) },
+
+	{ .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT,
+		HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
+			USB_VENDOR_ID_SYNAPTICS, 0xcddc) },
+
+	{ .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT,
+		HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
+			USB_VENDOR_ID_SYNAPTICS, 0xce08) },
+
+	{ .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT,
+		HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
+			USB_VENDOR_ID_SYNAPTICS, 0xce09) },
+
 	/* TopSeed panels */
 	{ .driver_data = MT_CLS_TOPSEED,
 		MT_USB_DEVICE(USB_VENDOR_ID_TOPSEED2,
@@ -2116,6 +2176,9 @@
 	{ .driver_data = MT_CLS_GOOGLE,
 		HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, USB_VENDOR_ID_GOOGLE,
 			USB_DEVICE_ID_GOOGLE_TOUCH_ROSE) },
+	{ .driver_data = MT_CLS_GOOGLE,
+		HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8, USB_VENDOR_ID_GOOGLE,
+			USB_DEVICE_ID_GOOGLE_WHISKERS) },
 
 	/* Generic MT device */
 	{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_MULTITOUCH, HID_ANY_ID, HID_ANY_ID) },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-plantronics.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-plantronics.c
@@ -6,13 +6,11 @@
  *  Copyright (c) 2015-2018 Terry Junge <terry.junge@plantronics.com>
  */
 
-/*
- */
-
 #include "hid-ids.h"
 
 #include <linux/hid.h>
 #include <linux/module.h>
+#include <linux/jiffies.h>
 
 #define PLT_HID_1_0_PAGE	0xffa00000
 #define PLT_HID_2_0_PAGE	0xffa20000
@@ -22,19 +20,29 @@
 
 #define PLT_VOL_UP		0x00b1
 #define PLT_VOL_DOWN		0x00b2
+#define PLT_MIC_MUTE		0x00b5
 
 #define PLT1_VOL_UP		(PLT_HID_1_0_PAGE | PLT_VOL_UP)
 #define PLT1_VOL_DOWN		(PLT_HID_1_0_PAGE | PLT_VOL_DOWN)
+#define PLT1_MIC_MUTE		(PLT_HID_1_0_PAGE | PLT_MIC_MUTE)
 #define PLT2_VOL_UP		(PLT_HID_2_0_PAGE | PLT_VOL_UP)
 #define PLT2_VOL_DOWN		(PLT_HID_2_0_PAGE | PLT_VOL_DOWN)
+#define PLT2_MIC_MUTE		(PLT_HID_2_0_PAGE | PLT_MIC_MUTE)
+#define HID_TELEPHONY_MUTE	(HID_UP_TELEPHONY | 0x2f)
+#define HID_CONSUMER_MUTE	(HID_UP_CONSUMER | 0xe2)
 
 #define PLT_DA60		0xda60
 #define PLT_BT300_MIN		0x0413
 #define PLT_BT300_MAX		0x0418
 
+#define PLT_DOUBLE_KEY_TIMEOUT 5 /* ms */
 
-#define PLT_ALLOW_CONSUMER (field->application == HID_CP_CONSUMERCONTROL && \
-			    (usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER)
+struct plt_drv_data {
+	unsigned long device_type;
+	unsigned long last_key_ts;
+	unsigned long double_key_to;
+	__u16 last_key;
+};
 
 static int plantronics_input_mapping(struct hid_device *hdev,
 				     struct hid_input *hi,
@@ -43,35 +51,45 @@
 				     unsigned long **bit, int *max)
 {
 	unsigned short mapped_key;
-	unsigned long plt_type = (unsigned long)hid_get_drvdata(hdev);
+	struct plt_drv_data *drv_data = hid_get_drvdata(hdev);
+	unsigned long plt_type = drv_data->device_type;
+	int allow_mute = usage->hid == HID_TELEPHONY_MUTE;
+	int allow_consumer = field->application == HID_CP_CONSUMERCONTROL &&
+			(usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER &&
+			usage->hid != HID_CONSUMER_MUTE;
 
 	/* special case for PTT products */
 	if (field->application == HID_GD_JOYSTICK)
 		goto defaulted;
 
-	/* handle volume up/down mapping */
 	/* non-standard types or multi-HID interfaces - plt_type is PID */
 	if (!(plt_type & HID_USAGE_PAGE)) {
 		switch (plt_type) {
 		case PLT_DA60:
-			if (PLT_ALLOW_CONSUMER)
+			if (allow_consumer)
 				goto defaulted;
-			goto ignored;
+			if (usage->hid == HID_CONSUMER_MUTE) {
+				mapped_key = KEY_MICMUTE;
+				goto mapped;
+			}
+			break;
 		default:
-			if (PLT_ALLOW_CONSUMER)
+			if (allow_consumer || allow_mute)
 				goto defaulted;
 		}
+		goto ignored;
 	}
-	/* handle standard types - plt_type is 0xffa0uuuu or 0xffa2uuuu */
-	/* 'basic telephony compliant' - allow default consumer page map */
-	else if ((plt_type & HID_USAGE) >= PLT_BASIC_TELEPHONY &&
-		 (plt_type & HID_USAGE) != PLT_BASIC_EXCEPTION) {
-		if (PLT_ALLOW_CONSUMER)
-			goto defaulted;
-	}
-	/* not 'basic telephony' - apply legacy mapping */
-	/* only map if the field is in the device's primary vendor page */
-	else if (!((field->application ^ plt_type) & HID_USAGE_PAGE)) {
+
+	/* handle standard consumer control mapping */
+	/* and standard telephony mic mute mapping */
+	if (allow_consumer || allow_mute)
+		goto defaulted;
+
+	/* handle vendor unique types - plt_type is 0xffa0uuuu or 0xffa2uuuu */
+	/* if not 'basic telephony compliant' - map vendor unique controls */
+	if (!((plt_type & HID_USAGE) >= PLT_BASIC_TELEPHONY &&
+	      (plt_type & HID_USAGE) != PLT_BASIC_EXCEPTION) &&
+	      !((field->application ^ plt_type) & HID_USAGE_PAGE))
 		switch (usage->hid) {
 		case PLT1_VOL_UP:
 		case PLT2_VOL_UP:
@@ -81,8 +99,11 @@
 		case PLT2_VOL_DOWN:
 			mapped_key = KEY_VOLUMEDOWN;
 			goto mapped;
+		case PLT1_MIC_MUTE:
+		case PLT2_MIC_MUTE:
+			mapped_key = KEY_MICMUTE;
+			goto mapped;
 		}
-	}
 
 /*
  * Future mapping of call control or other usages,
@@ -91,6 +112,8 @@
  */
 
 ignored:
+	hid_dbg(hdev, "usage: %08x (appl: %08x) - ignored\n",
+		usage->hid, field->application);
 	return -1;
 
 defaulted:
@@ -105,6 +128,33 @@
 	return 1;
 }
 
+static int plantronics_event(struct hid_device *hdev, struct hid_field *field,
+			     struct hid_usage *usage, __s32 value)
+{
+	struct plt_drv_data *drv_data = hid_get_drvdata(hdev);
+	unsigned long prev_tsto, cur_ts;
+	__u16 prev_key, cur_key;
+
+	/* Usages are filtered in plantronics_usages. */
+
+	/* HZ too low for ms resolution - double key detection disabled */
+	/* or it is a key release - handle key presses only. */
+	if (!drv_data->double_key_to || !value)
+		return 0;
+
+	prev_tsto = drv_data->last_key_ts + drv_data->double_key_to;
+	cur_ts = drv_data->last_key_ts = jiffies;
+	prev_key = drv_data->last_key;
+	cur_key = drv_data->last_key = usage->code;
+
+	/* If the same key occurs in <= double_key_to -- ignore it */
+	if (prev_key == cur_key && time_before_eq(cur_ts, prev_tsto)) {
+		hid_dbg(hdev, "double key %d ignored\n", cur_key);
+		return 1; /* Ignore the repeated key. */
+	}
+	return 0;
+}
+
 static unsigned long plantronics_device_type(struct hid_device *hdev)
 {
 	unsigned i, col_page;
@@ -133,22 +183,34 @@
 static int plantronics_probe(struct hid_device *hdev,
 			     const struct hid_device_id *id)
 {
+	struct plt_drv_data *drv_data;
 	int ret;
 
+	drv_data = devm_kzalloc(&hdev->dev, sizeof(*drv_data), GFP_KERNEL);
+	if (!drv_data)
+		return -ENOMEM;
+
 	ret = hid_parse(hdev);
 	if (ret) {
 		hid_err(hdev, "parse failed\n");
-		goto err;
+		return ret;
 	}
 
-	hid_set_drvdata(hdev, (void *)plantronics_device_type(hdev));
+	drv_data->device_type = plantronics_device_type(hdev);
+	drv_data->double_key_to = msecs_to_jiffies(PLT_DOUBLE_KEY_TIMEOUT);
+	drv_data->last_key_ts = jiffies - drv_data->double_key_to;
+
+	/* if HZ does not allow ms resolution - disable double key detection */
+	if (drv_data->double_key_to < PLT_DOUBLE_KEY_TIMEOUT)
+		drv_data->double_key_to = 0;
+
+	hid_set_drvdata(hdev, drv_data);
 
 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT |
 		HID_CONNECT_HIDINPUT_FORCE | HID_CONNECT_HIDDEV_FORCE);
 	if (ret)
 		hid_err(hdev, "hw start failed\n");
 
-err:
 	return ret;
 }
 
@@ -158,10 +220,26 @@
 };
 MODULE_DEVICE_TABLE(hid, plantronics_devices);
 
+static const struct hid_usage_id plantronics_usages[] = {
+	{ HID_CP_VOLUMEUP, EV_KEY, HID_ANY_ID },
+	{ HID_CP_VOLUMEDOWN, EV_KEY, HID_ANY_ID },
+	{ HID_TELEPHONY_MUTE, EV_KEY, HID_ANY_ID },
+	{ HID_CONSUMER_MUTE, EV_KEY, HID_ANY_ID },
+	{ PLT2_VOL_UP, EV_KEY, HID_ANY_ID },
+	{ PLT2_VOL_DOWN, EV_KEY, HID_ANY_ID },
+	{ PLT2_MIC_MUTE, EV_KEY, HID_ANY_ID },
+	{ PLT1_VOL_UP, EV_KEY, HID_ANY_ID },
+	{ PLT1_VOL_DOWN, EV_KEY, HID_ANY_ID },
+	{ PLT1_MIC_MUTE, EV_KEY, HID_ANY_ID },
+	{ HID_TERMINATOR, HID_TERMINATOR, HID_TERMINATOR }
+};
+
 static struct hid_driver plantronics_driver = {
 	.name = "plantronics",
 	.id_table = plantronics_devices,
+	.usage_table = plantronics_usages,
 	.input_mapping = plantronics_input_mapping,
+	.event = plantronics_event,
 	.probe = plantronics_probe,
 };
 module_hid_driver(plantronics_driver);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-prodikeys.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-prodikeys.c
@@ -798,12 +798,18 @@
 static int pk_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
 	int ret;
-	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
-	unsigned short ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
+	struct usb_interface *intf;
+	unsigned short ifnum;
 	unsigned long quirks = id->driver_data;
 	struct pk_device *pk;
 	struct pcmidi_snd *pm = NULL;
 
+	if (!hid_is_usb(hdev))
+		return -EINVAL;
+
+	intf = to_usb_interface(hdev->dev.parent);
+	ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
+
 	pk = kzalloc(sizeof(*pk), GFP_KERNEL);
 	if (pk == NULL) {
 		hid_err(hdev, "can't alloc descriptor\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-quirks.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-quirks.c
@@ -33,6 +33,7 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_AKAI, USB_DEVICE_ID_AKAI_MPKMINI2), HID_QUIRK_NO_INIT_REPORTS },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD), HID_QUIRK_BADPAD },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_AMI, USB_DEVICE_ID_AMI_VIRT_KEYBOARD_AND_MOUSE), HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ANSI), HID_QUIRK_ALWAYS_POLL },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM), HID_QUIRK_NOGET },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC), HID_QUIRK_NOGET },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM), HID_QUIRK_NOGET },
@@ -66,12 +67,14 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_STRAFE), HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_CREATIVE_SB_OMNI_SURROUND_51), HID_QUIRK_NOGET },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_PIXART_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_PRO_WIRELESS_KM5221W), HID_QUIRK_ALWAYS_POLL },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC), HID_QUIRK_NOGET },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DRACAL_RAPHNET, USB_DEVICE_ID_RAPHNET_2NES2SNES), HID_QUIRK_MULTI_INPUT },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DRACAL_RAPHNET, USB_DEVICE_ID_RAPHNET_4NES4SNES), HID_QUIRK_MULTI_INPUT },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_REDRAGON_SEYMUR2), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_DOLPHINBAR), HID_QUIRK_MULTI_INPUT },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE1), HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE3), HID_QUIRK_MULTI_INPUT },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_PS3), HID_QUIRK_MULTI_INPUT },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_WIIU), HID_QUIRK_MULTI_INPUT },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER), HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET },
@@ -83,17 +86,25 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER), HID_QUIRK_NO_INIT_REPORTS },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28), HID_QUIRK_NOGET },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_FUTABA, USB_DEVICE_ID_LED_DISPLAY), HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, USB_DEVICE_ID_GREENASIA_DUAL_SAT_ADAPTOR), HID_QUIRK_MULTI_INPUT },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, USB_DEVICE_ID_GREENASIA_DUAL_USB_JOYPAD), HID_QUIRK_MULTI_INPUT },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_GAMEVICE, USB_DEVICE_ID_GAMEVICE_GV186),
+		HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_GAMEVICE, USB_DEVICE_ID_GAMEVICE_KISHI),
+		HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING), HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING), HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING), HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A096), HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A293), HID_QUIRK_ALWAYS_POLL },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0A4A), HID_QUIRK_ALWAYS_POLL },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_ELITE_PRESENTER_MOUSE_464A), HID_QUIRK_MULTI_INPUT },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A), HID_QUIRK_ALWAYS_POLL },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_094A), HID_QUIRK_ALWAYS_POLL },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_0941), HID_QUIRK_ALWAYS_POLL },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_0641), HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_1f4a), HID_QUIRK_ALWAYS_POLL },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM, USB_DEVICE_ID_IDEACOM_IDC6680), HID_QUIRK_MULTI_INPUT },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_INNOMEDIA, USB_DEVICE_ID_INNEX_GENESIS_ATARI), HID_QUIRK_MULTI_INPUT },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X), HID_QUIRK_MULTI_INPUT },
@@ -102,6 +113,11 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_PENSKETCH_M912), HID_QUIRK_MULTI_INPUT },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M406XE), HID_QUIRK_MULTI_INPUT },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_PIXART_USB_OPTICAL_MOUSE_ID2), HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_OPTICAL_USB_MOUSE_600E), HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_608D), HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_6019), HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_602E), HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_6093), HID_QUIRK_ALWAYS_POLL },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_C007), HID_QUIRK_ALWAYS_POLL },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_C077), HID_QUIRK_ALWAYS_POLL },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KEYBOARD_G710_PLUS), HID_QUIRK_NOGET },
@@ -109,8 +125,10 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C05A), HID_QUIRK_ALWAYS_POLL },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C06A), HID_QUIRK_ALWAYS_POLL },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MCS, USB_DEVICE_ID_MCS_GAMEPADBLOCK), HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_MOUSE_0783), HID_QUIRK_ALWAYS_POLL },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PIXART_MOUSE), HID_QUIRK_ALWAYS_POLL },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER), HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE3_COVER), HID_QUIRK_NO_INIT_REPORTS },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_PRO_2), HID_QUIRK_NO_INIT_REPORTS },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2), HID_QUIRK_NO_INIT_REPORTS },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2), HID_QUIRK_NO_INIT_REPORTS },
@@ -132,6 +150,7 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN), HID_QUIRK_NO_INIT_REPORTS },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_MOUSE_4D22), HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_MOUSE_4E2A), HID_QUIRK_ALWAYS_POLL },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4D0F), HID_QUIRK_ALWAYS_POLL },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4D65), HID_QUIRK_ALWAYS_POLL },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4E22), HID_QUIRK_ALWAYS_POLL },
@@ -144,6 +163,9 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_RETROUSB, USB_DEVICE_ID_RETROUSB_SNES_RETROPORT), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD), HID_QUIRK_BADPAD },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_X52), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_X52_2), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_X52_PRO), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_X65), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD2), HID_QUIRK_NO_INIT_REPORTS },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD), HID_QUIRK_NO_INIT_REPORTS },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB), HID_QUIRK_NOGET },
@@ -161,18 +183,23 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS2), HID_QUIRK_NO_INIT_REPORTS },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_QUAD_HD), HID_QUIRK_NO_INIT_REPORTS },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_TP_V103), HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_DELL_K12A), HID_QUIRK_NO_INIT_REPORTS },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD), HID_QUIRK_BADPAD },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_TOUCHPACK, USB_DEVICE_ID_TOUCHPACK_RTS), HID_QUIRK_MULTI_INPUT },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_TPV, USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN_8882), HID_QUIRK_NOGET },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_TPV, USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN_8883), HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_TRUST, USB_DEVICE_ID_TRUST_PANORA_TABLET), HID_QUIRK_MULTI_INPUT | HID_QUIRK_HIDINPUT_FORCE },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD), HID_QUIRK_NOGET },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_KNA5), HID_QUIRK_MULTI_INPUT },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_TWA60), HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER, USB_DEVICE_ID_UGTIZER_TABLET_WP5540), HID_QUIRK_MULTI_INPUT },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH), HID_QUIRK_MULTI_INPUT },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH), HID_QUIRK_MULTI_INPUT },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET), HID_QUIRK_MULTI_INPUT },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD2, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS), HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD), HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_XIN_MO, USB_DEVICE_ID_XIN_MO_DUAL_ARCADE), HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_GROUP_AUDIO), HID_QUIRK_NOGET },
 
 	{ 0 }
 };
@@ -281,6 +308,7 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_ANSI) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021) },
 #endif
 #if IS_ENABLED(CONFIG_HID_APPLEIR)
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL) },
@@ -395,9 +423,6 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A081) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A0C2) },
 #endif
-#if IS_ENABLED(CONFIG_HID_ITE)
-	{ HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE8595) },
-#endif
 #if IS_ENABLED(CONFIG_HID_ICADE)
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
 #endif
@@ -477,6 +502,7 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_DOLPHINBAR) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE1) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE2) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE3) },
 #endif
 #if IS_ENABLED(CONFIG_HID_MICROSOFT)
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500) },
@@ -595,6 +621,7 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_MMO7) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT5) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT9) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_MMO7) },
 #endif
 #if IS_ENABLED(CONFIG_HID_SAMSUNG)
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
@@ -837,6 +864,7 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_PETZL, USB_DEVICE_ID_PETZL_HEADLAMP) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_POWERCOM, USB_DEVICE_ID_POWERCOM_UPS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SAI, USB_DEVICE_ID_CYPRESS_HIDCOM) },
 #if IS_ENABLED(CONFIG_MOUSE_SYNAPTICS_USB)
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_TP) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_INT_TP) },
@@ -848,6 +876,7 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_DPAD) },
 #endif
 	{ HID_USB_DEVICE(USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_HP_5MP_CAMERA_5473) },
 	{ }
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-rmi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-rmi.c
@@ -744,7 +744,8 @@
 {
 	struct rmi_data *hdata = hid_get_drvdata(hdev);
 
-	if (hdata->device_flags & RMI_DEVICE) {
+	if ((hdata->device_flags & RMI_DEVICE)
+	    && test_bit(RMI_STARTED, &hdata->flags)) {
 		clear_bit(RMI_STARTED, &hdata->flags);
 		cancel_work_sync(&hdata->reset_work);
 		rmi_unregister_transport_device(&hdata->xport);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-roccat-arvo.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-roccat-arvo.c
@@ -344,6 +344,9 @@
 {
 	int retval;
 
+	if (!hid_is_usb(hdev))
+		return -EINVAL;
+
 	retval = hid_parse(hdev);
 	if (retval) {
 		hid_err(hdev, "parse failed\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-roccat-isku.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-roccat-isku.c
@@ -324,6 +324,9 @@
 {
 	int retval;
 
+	if (!hid_is_usb(hdev))
+		return -EINVAL;
+
 	retval = hid_parse(hdev);
 	if (retval) {
 		hid_err(hdev, "parse failed\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-roccat-kone.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-roccat-kone.c
@@ -294,31 +294,40 @@
 	struct kone_device *kone = hid_get_drvdata(dev_get_drvdata(dev));
 	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
 	int retval = 0, difference, old_profile;
+	struct kone_settings *settings = (struct kone_settings *)buf;
 
 	/* I need to get my data in one piece */
 	if (off != 0 || count != sizeof(struct kone_settings))
 		return -EINVAL;
 
 	mutex_lock(&kone->kone_lock);
-	difference = memcmp(buf, &kone->settings, sizeof(struct kone_settings));
+	difference = memcmp(settings, &kone->settings,
+			    sizeof(struct kone_settings));
 	if (difference) {
-		retval = kone_set_settings(usb_dev,
-				(struct kone_settings const *)buf);
-		if (retval) {
-			mutex_unlock(&kone->kone_lock);
-			return retval;
+		if (settings->startup_profile < 1 ||
+		    settings->startup_profile > 5) {
+			retval = -EINVAL;
+			goto unlock;
 		}
 
+		retval = kone_set_settings(usb_dev, settings);
+		if (retval)
+			goto unlock;
+
 		old_profile = kone->settings.startup_profile;
-		memcpy(&kone->settings, buf, sizeof(struct kone_settings));
+		memcpy(&kone->settings, settings, sizeof(struct kone_settings));
 
 		kone_profile_activated(kone, kone->settings.startup_profile);
 
 		if (kone->settings.startup_profile != old_profile)
 			kone_profile_report(kone, kone->settings.startup_profile);
 	}
+unlock:
 	mutex_unlock(&kone->kone_lock);
 
+	if (retval)
+		return retval;
+
 	return sizeof(struct kone_settings);
 }
 static BIN_ATTR(settings, 0660, kone_sysfs_read_settings,
@@ -740,6 +749,9 @@
 {
 	int retval;
 
+	if (!hid_is_usb(hdev))
+		return -EINVAL;
+
 	retval = hid_parse(hdev);
 	if (retval) {
 		hid_err(hdev, "parse failed\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-roccat-koneplus.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-roccat-koneplus.c
@@ -431,6 +431,9 @@
 {
 	int retval;
 
+	if (!hid_is_usb(hdev))
+		return -EINVAL;
+
 	retval = hid_parse(hdev);
 	if (retval) {
 		hid_err(hdev, "parse failed\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-roccat-konepure.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-roccat-konepure.c
@@ -133,6 +133,9 @@
 {
 	int retval;
 
+	if (!hid_is_usb(hdev))
+		return -EINVAL;
+
 	retval = hid_parse(hdev);
 	if (retval) {
 		hid_err(hdev, "parse failed\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-roccat-kovaplus.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-roccat-kovaplus.c
@@ -501,6 +501,9 @@
 {
 	int retval;
 
+	if (!hid_is_usb(hdev))
+		return -EINVAL;
+
 	retval = hid_parse(hdev);
 	if (retval) {
 		hid_err(hdev, "parse failed\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-roccat-lua.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-roccat-lua.c
@@ -160,6 +160,9 @@
 {
 	int retval;
 
+	if (!hid_is_usb(hdev))
+		return -EINVAL;
+
 	retval = hid_parse(hdev);
 	if (retval) {
 		hid_err(hdev, "parse failed\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-roccat-pyra.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-roccat-pyra.c
@@ -449,6 +449,9 @@
 {
 	int retval;
 
+	if (!hid_is_usb(hdev))
+		return -EINVAL;
+
 	retval = hid_parse(hdev);
 	if (retval) {
 		hid_err(hdev, "parse failed\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-roccat-ryos.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-roccat-ryos.c
@@ -141,6 +141,9 @@
 {
 	int retval;
 
+	if (!hid_is_usb(hdev))
+		return -EINVAL;
+
 	retval = hid_parse(hdev);
 	if (retval) {
 		hid_err(hdev, "parse failed\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-roccat-savu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-roccat-savu.c
@@ -113,6 +113,9 @@
 {
 	int retval;
 
+	if (!hid_is_usb(hdev))
+		return -EINVAL;
+
 	retval = hid_parse(hdev);
 	if (retval) {
 		hid_err(hdev, "parse failed\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-roccat.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-roccat.c
@@ -257,6 +257,8 @@
 	if (!new_value)
 		return -ENOMEM;
 
+	mutex_lock(&device->cbuf_lock);
+
 	report = &device->cbuf[device->cbuf_end];
 
 	/* passing NULL is safe */
@@ -276,6 +278,8 @@
 			reader->cbuf_start = (reader->cbuf_start + 1) % ROCCAT_CBUF_SIZE;
 	}
 
+	mutex_unlock(&device->cbuf_lock);
+
 	wake_up_interruptible(&device->wait);
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-saitek.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-saitek.c
@@ -187,6 +187,8 @@
 		.driver_data = SAITEK_RELEASE_MODE_RAT7 },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_MMO7),
 		.driver_data = SAITEK_RELEASE_MODE_MMO7 },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_MMO7),
+		.driver_data = SAITEK_RELEASE_MODE_MMO7 },
 	{ }
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-samsung.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-samsung.c
@@ -152,6 +152,9 @@
 	int ret;
 	unsigned int cmask = HID_CONNECT_DEFAULT;
 
+	if (!hid_is_usb(hdev))
+		return -EINVAL;
+
 	ret = hid_parse(hdev);
 	if (ret) {
 		hid_err(hdev, "parse failed\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-sensor-custom.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-sensor-custom.c
@@ -59,7 +59,7 @@
 	u32 raw_len;
 } __packed;
 
-static struct attribute hid_custom_attrs[] = {
+static struct attribute hid_custom_attrs[HID_CUSTOM_TOTAL_ATTRS] = {
 	{.name = "name", .mode = S_IRUGO},
 	{.name = "units", .mode = S_IRUGO},
 	{.name = "unit-expo", .mode = S_IRUGO},
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-sensor-hub.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-sensor-hub.c
@@ -210,16 +210,21 @@
 	buffer_size = buffer_size / sizeof(__s32);
 	if (buffer_size) {
 		for (i = 0; i < buffer_size; ++i) {
-			hid_set_field(report->field[field_index], i,
-				      (__force __s32)cpu_to_le32(*buf32));
+			ret = hid_set_field(report->field[field_index], i,
+					    (__force __s32)cpu_to_le32(*buf32));
+			if (ret)
+				goto done_proc;
+
 			++buf32;
 		}
 	}
 	if (remaining_bytes) {
 		value = 0;
 		memcpy(&value, (u8 *)buf32, remaining_bytes);
-		hid_set_field(report->field[field_index], i,
-			      (__force __s32)cpu_to_le32(value));
+		ret = hid_set_field(report->field[field_index], i,
+				    (__force __s32)cpu_to_le32(value));
+		if (ret)
+			goto done_proc;
 	}
 	hid_hw_request(hsdev->hdev, report, HID_REQ_SET_REPORT);
 	hid_hw_wait(hsdev->hdev);
@@ -483,7 +488,8 @@
 		return 1;
 
 	ptr = raw_data;
-	ptr++; /* Skip report id */
+	if (report->id)
+		ptr++; /* Skip report id */
 
 	spin_lock_irqsave(&pdata->lock, flags);
 
@@ -724,23 +730,30 @@
 	return ret;
 }
 
+static int sensor_hub_finalize_pending_fn(struct device *dev, void *data)
+{
+	struct hid_sensor_hub_device *hsdev = dev->platform_data;
+
+	if (hsdev->pending.status)
+		complete(&hsdev->pending.ready);
+
+	return 0;
+}
+
 static void sensor_hub_remove(struct hid_device *hdev)
 {
 	struct sensor_hub_data *data = hid_get_drvdata(hdev);
 	unsigned long flags;
-	int i;
 
 	hid_dbg(hdev, " hardware removed\n");
 	hid_hw_close(hdev);
 	hid_hw_stop(hdev);
+
 	spin_lock_irqsave(&data->lock, flags);
-	for (i = 0; i < data->hid_sensor_client_cnt; ++i) {
-		struct hid_sensor_hub_device *hsdev =
-			data->hid_sensor_hub_client_devs[i].platform_data;
-		if (hsdev->pending.status)
-			complete(&hsdev->pending.ready);
-	}
+	device_for_each_child(&hdev->dev, NULL,
+			      sensor_hub_finalize_pending_fn);
 	spin_unlock_irqrestore(&data->lock, flags);
+
 	mfd_remove_devices(&hdev->dev);
 	mutex_destroy(&data->mutex);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-sony.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-sony.c
@@ -867,6 +867,23 @@
 	if (sc->quirks & PS3REMOTE)
 		return ps3remote_fixup(hdev, rdesc, rsize);
 
+	/*
+	 * Some knock-off USB dongles incorrectly report their button count
+	 * as 13 instead of 16 causing three non-functional buttons.
+	 */
+	if ((sc->quirks & SIXAXIS_CONTROLLER_USB) && *rsize >= 45 &&
+		/* Report Count (13) */
+		rdesc[23] == 0x95 && rdesc[24] == 0x0D &&
+		/* Usage Maximum (13) */
+		rdesc[37] == 0x29 && rdesc[38] == 0x0D &&
+		/* Report Count (3) */
+		rdesc[43] == 0x95 && rdesc[44] == 0x03) {
+		hid_info(hdev, "Fixing up USB dongle report descriptor\n");
+		rdesc[24] = 0x10;
+		rdesc[38] = 0x10;
+		rdesc[44] = 0x00;
+	}
+
 	return rdesc;
 }
 
@@ -1580,16 +1597,38 @@
 	 * of the controller, so that it sends input reports of type 0x11.
 	 */
 	if (sc->quirks & (DUALSHOCK4_CONTROLLER_USB | DUALSHOCK4_DONGLE)) {
+		int retries;
+
 		buf = kmalloc(DS4_FEATURE_REPORT_0x02_SIZE, GFP_KERNEL);
 		if (!buf)
 			return -ENOMEM;
 
-		ret = hid_hw_raw_request(sc->hdev, 0x02, buf,
-					 DS4_FEATURE_REPORT_0x02_SIZE,
-					 HID_FEATURE_REPORT,
-					 HID_REQ_GET_REPORT);
-		if (ret < 0)
-			goto err_stop;
+		/* We should normally receive the feature report data we asked
+		 * for, but hidraw applications such as Steam can issue feature
+		 * reports as well. In particular for Dongle reconnects, Steam
+		 * and this function are competing resulting in often receiving
+		 * data for a different HID report, so retry a few times.
+		 */
+		for (retries = 0; retries < 3; retries++) {
+			ret = hid_hw_raw_request(sc->hdev, 0x02, buf,
+						 DS4_FEATURE_REPORT_0x02_SIZE,
+						 HID_FEATURE_REPORT,
+						 HID_REQ_GET_REPORT);
+			if (ret < 0)
+				goto err_stop;
+
+			if (buf[0] != 0x02) {
+				if (retries < 2) {
+					hid_warn(sc->hdev, "Retrying DualShock 4 get calibration report (0x02) request\n");
+					continue;
+				} else {
+					ret = -EILSEQ;
+					goto err_stop;
+				}
+			} else {
+				break;
+			}
+		}
 	} else {
 		u8 bthdr = 0xA3;
 		u32 crc;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-steam.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-steam.c
@@ -134,6 +134,11 @@
 	int ret;
 
 	r = steam->hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[0];
+	if (!r) {
+		hid_err(steam->hdev, "No HID_FEATURE_REPORT submitted -  nothing to read\n");
+		return -EINVAL;
+	}
+
 	if (hid_report_len(r) < 64)
 		return -EINVAL;
 
@@ -165,6 +170,11 @@
 	int ret;
 
 	r = steam->hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[0];
+	if (!r) {
+		hid_err(steam->hdev, "No HID_FEATURE_REPORT submitted -  nothing to read\n");
+		return -EINVAL;
+	}
+
 	if (hid_report_len(r) < 64)
 		return -EINVAL;
 
@@ -526,7 +536,8 @@
 			steam_battery_register(steam);
 
 		mutex_lock(&steam_devices_lock);
-		list_add(&steam->list, &steam_devices);
+		if (list_empty(&steam->list))
+			list_add(&steam->list, &steam_devices);
 		mutex_unlock(&steam_devices_lock);
 	}
 
@@ -552,7 +563,7 @@
 		hid_info(steam->hdev, "Steam Controller '%s' disconnected",
 				steam->serial_no);
 		mutex_lock(&steam_devices_lock);
-		list_del(&steam->list);
+		list_del_init(&steam->list);
 		mutex_unlock(&steam_devices_lock);
 		steam->serial_no[0] = 0;
 	}
@@ -738,6 +749,7 @@
 	mutex_init(&steam->mutex);
 	steam->quirks = id->driver_data;
 	INIT_WORK(&steam->work_connect, steam_work_connect_cb);
+	INIT_LIST_HEAD(&steam->list);
 
 	steam->client_hdev = steam_create_client_hid(hdev);
 	if (IS_ERR(steam->client_hdev)) {
@@ -768,8 +780,12 @@
 
 	if (steam->quirks & STEAM_QUIRK_WIRELESS) {
 		hid_info(hdev, "Steam wireless receiver connected");
+		/* If using a wireless adaptor ask for connection status */
+		steam->connected = false;
 		steam_request_conn_status(steam);
 	} else {
+		/* A wired connection is always present */
+		steam->connected = true;
 		ret = steam_register(steam);
 		if (ret) {
 			hid_err(hdev,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-u2fzero.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-u2fzero.c
@@ -132,7 +132,7 @@
 
 	ret = (wait_for_completion_timeout(
 		&ctx.done, msecs_to_jiffies(USB_CTRL_SET_TIMEOUT)));
-	if (ret < 0) {
+	if (ret == 0) {
 		usb_kill_urb(dev->urb);
 		hid_err(hdev, "urb submission timed out");
 	} else {
@@ -191,6 +191,8 @@
 	struct u2f_hid_msg resp;
 	int ret;
 	size_t actual_length;
+	/* valid packets must have a correct header */
+	int min_length = offsetof(struct u2f_hid_msg, init.data);
 
 	if (!dev->present) {
 		hid_dbg(dev->hdev, "device not present");
@@ -198,12 +200,14 @@
 	}
 
 	ret = u2fzero_recv(dev, &req, &resp);
-	if (ret < 0)
+
+	/* ignore errors or packets without data */
+	if (ret < min_length)
 		return 0;
 
 	/* only take the minimum amount of data it is safe to take */
-	actual_length = min3((size_t)ret - offsetof(struct u2f_hid_msg,
-		init.data), U2F_HID_MSG_LEN(resp), max);
+	actual_length = min3((size_t)ret - min_length,
+		U2F_HID_MSG_LEN(resp), max);
 
 	memcpy(data, resp.init.data, actual_length);
 
@@ -286,7 +290,7 @@
 	unsigned int minor;
 	int ret;
 
-	if (!hid_is_using_ll_driver(hdev, &usb_hid_driver))
+	if (!hid_is_usb(hdev))
 		return -EINVAL;
 
 	dev = devm_kzalloc(&hdev->dev, sizeof(*dev), GFP_KERNEL);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-uclogic-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-uclogic-core.c
@@ -164,11 +164,15 @@
 	struct uclogic_drvdata *drvdata = NULL;
 	bool params_initialized = false;
 
+	if (!hid_is_usb(hdev))
+		return -EINVAL;
+
 	/*
 	 * libinput requires the pad interface to be on a different node
 	 * than the pen, so use QUIRK_MULTI_INPUT for all tablets.
 	 */
 	hdev->quirks |= HID_QUIRK_MULTI_INPUT;
+	hdev->quirks |= HID_QUIRK_HIDINPUT_FORCE;
 
 	/* Allocate and assign driver data */
 	drvdata = devm_kzalloc(&hdev->dev, sizeof(*drvdata), GFP_KERNEL);
@@ -385,6 +389,8 @@
 				USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER,
 				USB_DEVICE_ID_UGTIZER_TABLET_GP0610) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER,
+				USB_DEVICE_ID_UGTIZER_TABLET_GT5040) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
 				USB_DEVICE_ID_UGEE_TABLET_G5) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hid-uclogic-params.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hid-uclogic-params.c
@@ -65,7 +65,7 @@
 					__u8 idx, size_t len)
 {
 	int rc;
-	struct usb_device *udev = hid_to_usb_dev(hdev);
+	struct usb_device *udev;
 	__u8 *buf = NULL;
 
 	/* Check arguments */
@@ -74,6 +74,8 @@
 		goto cleanup;
 	}
 
+	udev = hid_to_usb_dev(hdev);
+
 	buf = kmalloc(len, GFP_KERNEL);
 	if (buf == NULL) {
 		rc = -ENOMEM;
@@ -449,7 +451,7 @@
 {
 	int rc;
 	bool found = false;
-	struct usb_device *usb_dev = hid_to_usb_dev(hdev);
+	struct usb_device *usb_dev;
 	char *str_buf = NULL;
 	const size_t str_len = 16;
 
@@ -459,6 +461,8 @@
 		goto cleanup;
 	}
 
+	usb_dev = hid_to_usb_dev(hdev);
+
 	/*
 	 * Enable generic button mode
 	 */
@@ -705,9 +709,9 @@
 				     struct hid_device *hdev)
 {
 	int rc;
-	struct usb_device *udev = hid_to_usb_dev(hdev);
-	struct usb_interface *iface = to_usb_interface(hdev->dev.parent);
-	__u8 bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber;
+	struct usb_device *udev;
+	struct usb_interface *iface;
+	__u8 bInterfaceNumber;
 	bool found;
 	/* The resulting parameters (noop) */
 	struct uclogic_params p = {0, };
@@ -721,6 +725,10 @@
 		goto cleanup;
 	}
 
+	udev = hid_to_usb_dev(hdev);
+	iface = to_usb_interface(hdev->dev.parent);
+	bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber;
+
 	/* If it's not a pen interface */
 	if (bInterfaceNumber != 0) {
 		/* TODO: Consider marking the interface invalid */
@@ -832,21 +840,25 @@
 			struct hid_device *hdev)
 {
 	int rc;
-	struct usb_device *udev = hid_to_usb_dev(hdev);
-	__u8  bNumInterfaces = udev->config->desc.bNumInterfaces;
-	struct usb_interface *iface = to_usb_interface(hdev->dev.parent);
-	__u8 bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber;
+	struct usb_device *udev;
+	__u8  bNumInterfaces;
+	struct usb_interface *iface;
+	__u8 bInterfaceNumber;
 	bool found;
 	/* The resulting parameters (noop) */
 	struct uclogic_params p = {0, };
 
 	/* Check arguments */
-	if (params == NULL || hdev == NULL ||
-	    !hid_is_using_ll_driver(hdev, &usb_hid_driver)) {
+	if (params == NULL || hdev == NULL || !hid_is_usb(hdev)) {
 		rc = -EINVAL;
 		goto cleanup;
 	}
 
+	udev = hid_to_usb_dev(hdev);
+	bNumInterfaces = udev->config->desc.bNumInterfaces;
+	iface = to_usb_interface(hdev->dev.parent);
+	bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber;
+
 	/*
 	 * Set replacement report descriptor if the original matches the
 	 * specified size. Otherwise keep interface unchanged.
@@ -997,6 +1009,8 @@
 		break;
 	case VID_PID(USB_VENDOR_ID_UGTIZER,
 		     USB_DEVICE_ID_UGTIZER_TABLET_GP0610):
+	case VID_PID(USB_VENDOR_ID_UGTIZER,
+		     USB_DEVICE_ID_UGTIZER_TABLET_GT5040):
 	case VID_PID(USB_VENDOR_ID_UGEE,
 		     USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540):
 	case VID_PID(USB_VENDOR_ID_UGEE,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/hidraw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/hidraw.c
@@ -249,13 +249,14 @@
 static __poll_t hidraw_poll(struct file *file, poll_table *wait)
 {
 	struct hidraw_list *list = file->private_data;
+	__poll_t mask = EPOLLOUT | EPOLLWRNORM; /* hidraw is always writable */
 
 	poll_wait(file, &list->hidraw->wait, wait);
 	if (list->head != list->tail)
-		return EPOLLIN | EPOLLRDNORM | EPOLLOUT;
+		mask |= EPOLLIN | EPOLLRDNORM;
 	if (!list->hidraw->exist)
-		return EPOLLERR | EPOLLHUP;
-	return 0;
+		mask |= EPOLLERR | EPOLLHUP;
+	return mask;
 }
 
 static int hidraw_open(struct inode *inode, struct file *file)
@@ -345,10 +346,13 @@
 	unsigned int minor = iminor(inode);
 	struct hidraw_list *list = file->private_data;
 	unsigned long flags;
+	int i;
 
 	mutex_lock(&minors_lock);
 
 	spin_lock_irqsave(&hidraw_table[minor]->list_lock, flags);
+	for (i = list->tail; i < list->head; i++)
+		kfree(list->buffer[i].value);
 	list_del(&list->node);
 	spin_unlock_irqrestore(&hidraw_table[minor]->list_lock, flags);
 	kfree(list);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/i2c-hid/i2c-hid-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/i2c-hid/i2c-hid-core.c
@@ -48,11 +48,14 @@
 #define I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV	BIT(0)
 #define I2C_HID_QUIRK_NO_IRQ_AFTER_RESET	BIT(1)
 #define I2C_HID_QUIRK_BOGUS_IRQ			BIT(4)
+#define I2C_HID_QUIRK_RESET_ON_RESUME		BIT(5)
+#define I2C_HID_QUIRK_BAD_INPUT_SIZE		BIT(6)
+#define I2C_HID_QUIRK_NO_WAKEUP_AFTER_RESET	BIT(7)
+
 
 /* flags */
 #define I2C_HID_STARTED		0
 #define I2C_HID_RESET_PENDING	1
-#define I2C_HID_READ_PENDING	2
 
 #define I2C_HID_PWR_ON		0x00
 #define I2C_HID_PWR_SLEEP	0x01
@@ -170,7 +173,21 @@
 		I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV },
 	{ I2C_VENDOR_ID_HANTICK, I2C_PRODUCT_ID_HANTICK_5288,
 		I2C_HID_QUIRK_NO_IRQ_AFTER_RESET },
+	{ I2C_VENDOR_ID_ITE, I2C_DEVICE_ID_ITE_VOYO_WINPAD_A15,
+		I2C_HID_QUIRK_NO_IRQ_AFTER_RESET },
+	{ I2C_VENDOR_ID_RAYDIUM, I2C_PRODUCT_ID_RAYDIUM_3118,
+		I2C_HID_QUIRK_NO_IRQ_AFTER_RESET },
+	{ USB_VENDOR_ID_ALPS_JP, HID_ANY_ID,
+		 I2C_HID_QUIRK_RESET_ON_RESUME },
+	{ I2C_VENDOR_ID_SYNAPTICS, I2C_PRODUCT_ID_SYNAPTICS_SYNA2393,
+		 I2C_HID_QUIRK_RESET_ON_RESUME },
+	{ USB_VENDOR_ID_ITE, I2C_DEVICE_ID_ITE_LENOVO_LEGION_Y720,
+		I2C_HID_QUIRK_BAD_INPUT_SIZE },
+	/*
+	 * Sending the wakeup after reset actually break ELAN touchscreen controller
+	 */
 	{ USB_VENDOR_ID_ELAN, HID_ANY_ID,
+		 I2C_HID_QUIRK_NO_WAKEUP_AFTER_RESET |
 		 I2C_HID_QUIRK_BOGUS_IRQ },
 	{ 0, 0 }
 };
@@ -240,7 +257,6 @@
 		msg[1].len = data_len;
 		msg[1].buf = buf_recv;
 		msg_num = 2;
-		set_bit(I2C_HID_READ_PENDING, &ihid->flags);
 	}
 
 	if (wait)
@@ -248,9 +264,6 @@
 
 	ret = i2c_transfer(client->adapter, msg, msg_num);
 
-	if (data_len > 0)
-		clear_bit(I2C_HID_READ_PENDING, &ihid->flags);
-
 	if (ret != msg_num)
 		return ret < 0 ? ret : -EIO;
 
@@ -411,6 +424,19 @@
 		dev_err(&client->dev, "failed to change power setting.\n");
 
 set_pwr_exit:
+
+	/*
+	 * The HID over I2C specification states that if a DEVICE needs time
+	 * after the PWR_ON request, it should utilise CLOCK stretching.
+	 * However, it has been observered that the Windows driver provides a
+	 * 1ms sleep between the PWR_ON and RESET requests.
+	 * According to Goodix Windows even waits 60 ms after (other?)
+	 * PWR_ON requests. Testing has confirmed that several devices
+	 * will not work properly without a delay after a PWR_ON request.
+	 */
+	if (!ret && power_state == I2C_HID_PWR_ON)
+		msleep(60);
+
 	return ret;
 }
 
@@ -432,15 +458,6 @@
 	if (ret)
 		goto out_unlock;
 
-	/*
-	 * The HID over I2C specification states that if a DEVICE needs time
-	 * after the PWR_ON request, it should utilise CLOCK stretching.
-	 * However, it has been observered that the Windows driver provides a
-	 * 1ms sleep between the PWR_ON and RESET requests and that some devices
-	 * rely on this.
-	 */
-	usleep_range(1000, 5000);
-
 	i2c_hid_dbg(ihid, "resetting...\n");
 
 	ret = i2c_hid_command(client, &hid_reset_cmd, NULL, 0);
@@ -451,7 +468,8 @@
 	}
 
 	/* At least some SIS devices need this after reset */
-	ret = i2c_hid_set_power(client, I2C_HID_PWR_ON);
+	if (!(ihid->quirks & I2C_HID_QUIRK_NO_WAKEUP_AFTER_RESET))
+		ret = i2c_hid_set_power(client, I2C_HID_PWR_ON);
 
 out_unlock:
 	mutex_unlock(&ihid->reset_lock);
@@ -493,9 +511,15 @@
 	}
 
 	if ((ret_size > size) || (ret_size < 2)) {
-		dev_err(&ihid->client->dev, "%s: incomplete report (%d/%d)\n",
-			__func__, size, ret_size);
-		return;
+		if (ihid->quirks & I2C_HID_QUIRK_BAD_INPUT_SIZE) {
+			ihid->inbuf[0] = size & 0xff;
+			ihid->inbuf[1] = size >> 8;
+			ret_size = size;
+		} else {
+			dev_err(&ihid->client->dev, "%s: incomplete report (%d/%d)\n",
+				__func__, size, ret_size);
+			return;
+		}
 	}
 
 	i2c_hid_dbg(ihid, "input: %*ph\n", ret_size, ihid->inbuf);
@@ -511,9 +535,6 @@
 {
 	struct i2c_hid *ihid = dev_id;
 
-	if (test_bit(I2C_HID_READ_PENDING, &ihid->flags))
-		return IRQ_HANDLED;
-
 	i2c_hid_get_input(ihid);
 
 	return IRQ_HANDLED;
@@ -593,6 +614,17 @@
 	if (report_type == HID_OUTPUT_REPORT)
 		return -EINVAL;
 
+	/*
+	 * In case of unnumbered reports the response from the device will
+	 * not have the report ID that the upper layers expect, so we need
+	 * to stash it the buffer ourselves and adjust the data size.
+	 */
+	if (!report_number) {
+		buf[0] = 0;
+		buf++;
+		count--;
+	}
+
 	/* +2 bytes to include the size of the reply in the query buffer */
 	ask_count = min(count + 2, (size_t)ihid->bufsize);
 
@@ -614,6 +646,9 @@
 	count = min(count, ret_count - 2);
 	memcpy(buf, ihid->rawbuf + 2, count);
 
+	if (!report_number)
+		count++;
+
 	return count;
 }
 
@@ -630,17 +665,19 @@
 
 	mutex_lock(&ihid->reset_lock);
 
-	if (report_id) {
-		buf++;
-		count--;
-	}
-
+	/*
+	 * Note that both numbered and unnumbered reports passed here
+	 * are supposed to have report ID stored in the 1st byte of the
+	 * buffer, so we strip it off unconditionally before passing payload
+	 * to i2c_hid_set_or_send_report which takes care of encoding
+	 * everything properly.
+	 */
 	ret = i2c_hid_set_or_send_report(client,
 				report_type == HID_FEATURE_REPORT ? 0x03 : 0x02,
-				report_id, buf, count, use_data);
+				report_id, buf + 1, count - 1, use_data);
 
-	if (report_id && ret >= 0)
-		ret++; /* add report_id to the number of transfered bytes */
+	if (ret >= 0)
+		ret++; /* add report_id to the number of transferred bytes */
 
 	mutex_unlock(&ihid->reset_lock);
 
@@ -1091,8 +1128,8 @@
 	hid->vendor = le16_to_cpu(ihid->hdesc.wVendorID);
 	hid->product = le16_to_cpu(ihid->hdesc.wProductID);
 
-	snprintf(hid->name, sizeof(hid->name), "%s %04hX:%04hX",
-		 client->name, hid->vendor, hid->product);
+	snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X",
+		 client->name, (u16)hid->vendor, (u16)hid->product);
 	strlcpy(hid->phys, dev_name(&client->dev), sizeof(hid->phys));
 
 	ihid->quirks = i2c_hid_lookup_quirk(hid->vendor, hid->product);
@@ -1212,8 +1249,15 @@
 	 * solves "incomplete reports" on Raydium devices 2386:3118 and
 	 * 2386:4B33 and fixes various SIS touchscreens no longer sending
 	 * data after a suspend/resume.
+	 *
+	 * However some ALPS touchpads generate IRQ storm without reset, so
+	 * let's still reset them here.
 	 */
-	ret = i2c_hid_set_power(client, I2C_HID_PWR_ON);
+	if (ihid->quirks & I2C_HID_QUIRK_RESET_ON_RESUME)
+		ret = i2c_hid_hwreset(client);
+	else
+		ret = i2c_hid_set_power(client, I2C_HID_PWR_ON);
+
 	if (ret)
 		return ret;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c
@@ -342,6 +342,14 @@
 		.driver_data = (void *)&sipodev_desc
 	},
 	{
+		.ident = "Trekstor SURFBOOK E11B",
+		.matches = {
+			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TREKSTOR"),
+			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "SURFBOOK E11B"),
+		},
+		.driver_data = (void *)&sipodev_desc
+	},
+	{
 		.ident = "Direkt-Tek DTLAPY116-2",
 		.matches = {
 			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Direkt-Tek"),
@@ -366,6 +374,14 @@
 		.driver_data = (void *)&sipodev_desc
 	},
 	{
+		.ident = "Mediacom FlexBook edge 13",
+		.matches = {
+			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "MEDIACOM"),
+			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "FlexBook_edge13-M-FBE13"),
+		},
+		.driver_data = (void *)&sipodev_desc
+	},
+	{
 		.ident = "Odys Winbook 13",
 		.matches = {
 			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AXDIA International GmbH"),
@@ -381,6 +397,22 @@
 		},
 		.driver_data = (void *)&sipodev_desc
 	},
+	{
+		.ident = "Schneider SCL142ALM",
+		.matches = {
+			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "SCHNEIDER"),
+			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "SCL142ALM"),
+		},
+		.driver_data = (void *)&sipodev_desc
+	},
+	{
+		.ident = "Vero K147",
+		.matches = {
+			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "VERO"),
+			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "K147"),
+		},
+		.driver_data = (void *)&sipodev_desc
+	},
 	{ }	/* Terminate list */
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/intel-ish-hid/ipc/hw-ish.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/intel-ish-hid/ipc/hw-ish.h
@@ -24,7 +24,10 @@
 #define ICL_MOBILE_DEVICE_ID	0x34FC
 #define SPT_H_DEVICE_ID		0xA135
 #define CML_LP_DEVICE_ID	0x02FC
+#define CMP_H_DEVICE_ID		0x06FC
 #define EHL_Ax_DEVICE_ID	0x4BB3
+#define TGL_LP_DEVICE_ID	0xA0FC
+#define TGL_H_DEVICE_ID		0x43FC
 
 #define	REVISION_ID_CHT_A0	0x6
 #define	REVISION_ID_CHT_Ax_SI	0x0
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/intel-ish-hid/ipc/ipc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/intel-ish-hid/ipc/ipc.c
@@ -549,14 +549,14 @@
 static void _ish_sync_fw_clock(struct ishtp_device *dev)
 {
 	static unsigned long	prev_sync;
-	uint64_t	usec;
+	struct ipc_time_update_msg time = {};
 
 	if (prev_sync && jiffies - prev_sync < 20 * HZ)
 		return;
 
 	prev_sync = jiffies;
-	usec = ktime_to_us(ktime_get_boottime());
-	ipc_send_mng_msg(dev, MNG_SYNC_FW_CLOCK, &usec, sizeof(uint64_t));
+	/* The fields of time would be updated while sending message */
+	ipc_send_mng_msg(dev, MNG_SYNC_FW_CLOCK, &time, sizeof(time));
 }
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/intel-ish-hid/ipc/pci-ish.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/intel-ish-hid/ipc/pci-ish.c
@@ -34,7 +34,10 @@
 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, ICL_MOBILE_DEVICE_ID)},
 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, SPT_H_DEVICE_ID)},
 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, CML_LP_DEVICE_ID)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, CMP_H_DEVICE_ID)},
 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, EHL_Ax_DEVICE_ID)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, TGL_LP_DEVICE_ID)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, TGL_H_DEVICE_ID)},
 	{0, }
 };
 MODULE_DEVICE_TABLE(pci, ish_pci_tbl);
@@ -157,6 +160,11 @@
 
 	/* request and enable interrupt */
 	ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
+	if (ret < 0) {
+		dev_err(dev, "ISH: Failed to allocate IRQ vectors\n");
+		return ret;
+	}
+
 	if (!pdev->msi_enabled && !pdev->msix_enabled)
 		irq_flag = IRQF_SHARED;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/intel-ish-hid/ishtp-fw-loader.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/intel-ish-hid/ishtp-fw-loader.c
@@ -480,6 +480,7 @@
 			    sizeof(ldr_xfer_query_resp));
 	if (rv < 0) {
 		client_data->flag_retry = true;
+		*fw_info = (struct shim_fw_info){};
 		return rv;
 	}
 
@@ -489,6 +490,7 @@
 			"data size %d is not equal to size of loader_xfer_query_response %zu\n",
 			rv, sizeof(struct loader_xfer_query_response));
 		client_data->flag_retry = true;
+		*fw_info = (struct shim_fw_info){};
 		return -EMSGSIZE;
 	}
 
@@ -628,7 +630,7 @@
 				  const struct firmware *fw,
 				  const struct shim_fw_info fw_info)
 {
-	int rv;
+	int rv = 0;
 	void *dma_buf;
 	dma_addr_t dma_buf_phy;
 	u32 fragment_offset, fragment_size, payload_max_size;
@@ -654,21 +656,12 @@
 	 */
 	payload_max_size &= ~(L1_CACHE_BYTES - 1);
 
-	dma_buf = kmalloc(payload_max_size, GFP_KERNEL | GFP_DMA32);
+	dma_buf = dma_alloc_coherent(devc, payload_max_size, &dma_buf_phy, GFP_KERNEL);
 	if (!dma_buf) {
 		client_data->flag_retry = true;
 		return -ENOMEM;
 	}
 
-	dma_buf_phy = dma_map_single(devc, dma_buf, payload_max_size,
-				     DMA_TO_DEVICE);
-	if (dma_mapping_error(devc, dma_buf_phy)) {
-		dev_err(cl_data_to_dev(client_data), "DMA map failed\n");
-		client_data->flag_retry = true;
-		rv = -ENOMEM;
-		goto end_err_dma_buf_release;
-	}
-
 	ldr_xfer_dma_frag.fragment.hdr.command = LOADER_CMD_XFER_FRAGMENT;
 	ldr_xfer_dma_frag.fragment.xfer_mode = LOADER_XFER_MODE_DIRECT_DMA;
 	ldr_xfer_dma_frag.ddr_phys_addr = (u64)dma_buf_phy;
@@ -688,14 +681,7 @@
 		ldr_xfer_dma_frag.fragment.size = fragment_size;
 		memcpy(dma_buf, &fw->data[fragment_offset], fragment_size);
 
-		dma_sync_single_for_device(devc, dma_buf_phy,
-					   payload_max_size,
-					   DMA_TO_DEVICE);
-
-		/*
-		 * Flush cache here because the dma_sync_single_for_device()
-		 * does not do for x86.
-		 */
+		/* Flush cache to be sure the data is in main memory. */
 		clflush_cache_range(dma_buf, payload_max_size);
 
 		dev_dbg(cl_data_to_dev(client_data),
@@ -718,15 +704,8 @@
 		fragment_offset += fragment_size;
 	}
 
-	dma_unmap_single(devc, dma_buf_phy, payload_max_size, DMA_TO_DEVICE);
-	kfree(dma_buf);
-	return 0;
-
 end_err_resp_buf_release:
-	/* Free ISH buffer if not done already, in error case */
-	dma_unmap_single(devc, dma_buf_phy, payload_max_size, DMA_TO_DEVICE);
-end_err_dma_buf_release:
-	kfree(dma_buf);
+	dma_free_coherent(devc, payload_max_size, dma_buf, dma_buf_phy);
 	return rv;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/intel-ish-hid/ishtp-hid.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/intel-ish-hid/ishtp-hid.c
@@ -263,12 +263,14 @@
  */
 void ishtp_hid_remove(struct ishtp_cl_data *client_data)
 {
+	void *data;
 	int i;
 
 	for (i = 0; i < client_data->num_hid_devices; ++i) {
 		if (client_data->hid_sensor_hubs[i]) {
-			kfree(client_data->hid_sensor_hubs[i]->driver_data);
+			data = client_data->hid_sensor_hubs[i]->driver_data;
 			hid_destroy_device(client_data->hid_sensor_hubs[i]);
+			kfree(data);
 			client_data->hid_sensor_hubs[i] = NULL;
 		}
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/intel-ish-hid/ishtp-hid.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/intel-ish-hid/ishtp-hid.h
@@ -110,7 +110,7 @@
  * @multi_packet_cnt:	Count of fragmented packet count
  *
  * This structure is used to store completion flags and per client data like
- * like report description, number of HID devices etc.
+ * report description, number of HID devices etc.
  */
 struct ishtp_cl_data {
 	/* completion flags */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/intel-ish-hid/ishtp/client.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/intel-ish-hid/ishtp/client.c
@@ -626,13 +626,14 @@
 }
 
 /**
- * ipc_tx_callback() - IPC tx callback function
+ * ipc_tx_send() - IPC tx send function
  * @prm: Pointer to client device instance
  *
- * Send message over IPC either first time or on callback on previous message
- * completion
+ * Send message over IPC. Message will be split into fragments
+ * if message size is bigger than IPC FIFO size, and all
+ * fragments will be sent one by one.
  */
-static void ipc_tx_callback(void *prm)
+static void ipc_tx_send(void *prm)
 {
 	struct ishtp_cl	*cl = prm;
 	struct ishtp_cl_tx_ring	*cl_msg;
@@ -677,32 +678,41 @@
 			    list);
 	rem = cl_msg->send_buf.size - cl->tx_offs;
 
-	ishtp_hdr.host_addr = cl->host_client_id;
-	ishtp_hdr.fw_addr = cl->fw_client_id;
-	ishtp_hdr.reserved = 0;
-	pmsg = cl_msg->send_buf.data + cl->tx_offs;
-
-	if (rem <= dev->mtu) {
-		ishtp_hdr.length = rem;
-		ishtp_hdr.msg_complete = 1;
-		cl->sending = 0;
-		list_del_init(&cl_msg->list);	/* Must be before write */
-		spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags);
-		/* Submit to IPC queue with no callback */
-		ishtp_write_message(dev, &ishtp_hdr, pmsg);
-		spin_lock_irqsave(&cl->tx_free_list_spinlock, tx_free_flags);
-		list_add_tail(&cl_msg->list, &cl->tx_free_list.list);
-		++cl->tx_ring_free_size;
-		spin_unlock_irqrestore(&cl->tx_free_list_spinlock,
-			tx_free_flags);
-	} else {
-		/* Send IPC fragment */
-		spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags);
-		cl->tx_offs += dev->mtu;
-		ishtp_hdr.length = dev->mtu;
-		ishtp_hdr.msg_complete = 0;
-		ishtp_send_msg(dev, &ishtp_hdr, pmsg, ipc_tx_callback, cl);
+	while (rem > 0) {
+		ishtp_hdr.host_addr = cl->host_client_id;
+		ishtp_hdr.fw_addr = cl->fw_client_id;
+		ishtp_hdr.reserved = 0;
+		pmsg = cl_msg->send_buf.data + cl->tx_offs;
+
+		if (rem <= dev->mtu) {
+			/* Last fragment or only one packet */
+			ishtp_hdr.length = rem;
+			ishtp_hdr.msg_complete = 1;
+			/* Submit to IPC queue with no callback */
+			ishtp_write_message(dev, &ishtp_hdr, pmsg);
+			cl->tx_offs = 0;
+			cl->sending = 0;
+
+			break;
+		} else {
+			/* Send ipc fragment */
+			ishtp_hdr.length = dev->mtu;
+			ishtp_hdr.msg_complete = 0;
+			/* All fregments submitted to IPC queue with no callback */
+			ishtp_write_message(dev, &ishtp_hdr, pmsg);
+			cl->tx_offs += dev->mtu;
+			rem = cl_msg->send_buf.size - cl->tx_offs;
+		}
 	}
+
+	list_del_init(&cl_msg->list);
+	spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags);
+
+	spin_lock_irqsave(&cl->tx_free_list_spinlock, tx_free_flags);
+	list_add_tail(&cl_msg->list, &cl->tx_free_list.list);
+	++cl->tx_ring_free_size;
+	spin_unlock_irqrestore(&cl->tx_free_list_spinlock,
+		tx_free_flags);
 }
 
 /**
@@ -720,7 +730,7 @@
 		return;
 
 	cl->tx_offs = 0;
-	ipc_tx_callback(cl);
+	ipc_tx_send(cl);
 	++cl->send_msg_cnt_ipc;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/intel-ish-hid/ishtp/dma-if.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/intel-ish-hid/ishtp/dma-if.c
@@ -104,6 +104,11 @@
 	int required_slots = (size / DMA_SLOT_SIZE)
 		+ 1 * (size % DMA_SLOT_SIZE != 0);
 
+	if (!dev->ishtp_dma_tx_map) {
+		dev_err(dev->devc, "Fail to allocate Tx map\n");
+		return NULL;
+	}
+
 	spin_lock_irqsave(&dev->ishtp_dma_tx_lock, flags);
 	for (i = 0; i <= (dev->ishtp_dma_num_slots - required_slots); i++) {
 		free = 1;
@@ -150,6 +155,11 @@
 		return;
 	}
 
+	if (!dev->ishtp_dma_tx_map) {
+		dev_err(dev->devc, "Fail to allocate Tx map\n");
+		return;
+	}
+
 	i = (msg_addr - dev->ishtp_host_dma_tx_buf) / DMA_SLOT_SIZE;
 	spin_lock_irqsave(&dev->ishtp_dma_tx_lock, flags);
 	for (j = 0; j < acked_slots; j++) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/uhid.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/uhid.c
@@ -28,11 +28,22 @@
 
 struct uhid_device {
 	struct mutex devlock;
+
+	/* This flag tracks whether the HID device is usable for commands from
+	 * userspace. The flag is already set before hid_add_device(), which
+	 * runs in workqueue context, to allow hid_add_device() to communicate
+	 * with userspace.
+	 * However, if hid_add_device() fails, the flag is cleared without
+	 * holding devlock.
+	 * We guarantee that if @running changes from true to false while you're
+	 * holding @devlock, it's still fine to access @hid.
+	 */
 	bool running;
 
 	__u8 *rd_data;
 	uint rd_size;
 
+	/* When this is NULL, userspace may use UHID_CREATE/UHID_CREATE2. */
 	struct hid_device *hid;
 	struct uhid_event input_buf;
 
@@ -63,9 +74,18 @@
 	if (ret) {
 		hid_err(uhid->hid, "Cannot register HID device: error %d\n", ret);
 
-		hid_destroy_device(uhid->hid);
-		uhid->hid = NULL;
+		/* We used to call hid_destroy_device() here, but that's really
+		 * messy to get right because we have to coordinate with
+		 * concurrent writes from userspace that might be in the middle
+		 * of using uhid->hid.
+		 * Just leave uhid->hid as-is for now, and clean it up when
+		 * userspace tries to close or reinitialize the uhid instance.
+		 *
+		 * However, we do have to clear the ->running flag and do a
+		 * wakeup to make sure userspace knows that the device is gone.
+		 */
 		uhid->running = false;
+		wake_up_interruptible(&uhid->report_wait);
 	}
 }
 
@@ -375,6 +395,7 @@
 	.parse = uhid_hid_parse,
 	.raw_request = uhid_hid_raw_request,
 	.output_report = uhid_hid_output_report,
+	.max_buffer_size = UHID_DATA_MAX,
 };
 EXPORT_SYMBOL_GPL(uhid_hid_driver);
 
@@ -474,7 +495,7 @@
 	void *rd_data;
 	int ret;
 
-	if (uhid->running)
+	if (uhid->hid)
 		return -EALREADY;
 
 	rd_size = ev->u.create2.rd_size;
@@ -556,7 +577,7 @@
 
 static int uhid_dev_destroy(struct uhid_device *uhid)
 {
-	if (!uhid->running)
+	if (!uhid->hid)
 		return -EINVAL;
 
 	uhid->running = false;
@@ -565,6 +586,7 @@
 	cancel_work_sync(&uhid->worker);
 
 	hid_destroy_device(uhid->hid);
+	uhid->hid = NULL;
 	kfree(uhid->rd_data);
 
 	return 0;
@@ -766,13 +788,14 @@
 static __poll_t uhid_char_poll(struct file *file, poll_table *wait)
 {
 	struct uhid_device *uhid = file->private_data;
+	__poll_t mask = EPOLLOUT | EPOLLWRNORM; /* uhid is always writable */
 
 	poll_wait(file, &uhid->waitq, wait);
 
 	if (uhid->head != uhid->tail)
-		return EPOLLIN | EPOLLRDNORM;
+		mask |= EPOLLIN | EPOLLRDNORM;
 
-	return 0;
+	return mask;
 }
 
 static const struct file_operations uhid_fops = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/usbhid/hid-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/usbhid/hid-core.c
@@ -374,7 +374,7 @@
 	raw_report = usbhid->ctrl[usbhid->ctrltail].raw_report;
 	dir = usbhid->ctrl[usbhid->ctrltail].dir;
 
-	len = ((report->size - 1) >> 3) + 1 + (report->id > 0);
+	len = hid_report_len(report);
 	if (dir == USB_DIR_OUT) {
 		usbhid->urbctrl->pipe = usb_sndctrlpipe(hid_to_usb_dev(hid), 0);
 		usbhid->urbctrl->transfer_buffer_length = len;
@@ -503,7 +503,7 @@
 
 	if (unplug) {
 		usbhid->ctrltail = usbhid->ctrlhead;
-	} else {
+	} else if (usbhid->ctrlhead != usbhid->ctrltail) {
 		usbhid->ctrltail = (usbhid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1);
 
 		if (usbhid->ctrlhead != usbhid->ctrltail &&
@@ -682,16 +682,21 @@
 	struct usbhid_device *usbhid = hid->driver_data;
 	int res;
 
+	mutex_lock(&usbhid->mutex);
+
 	set_bit(HID_OPENED, &usbhid->iofl);
 
-	if (hid->quirks & HID_QUIRK_ALWAYS_POLL)
-		return 0;
+	if (hid->quirks & HID_QUIRK_ALWAYS_POLL) {
+		res = 0;
+		goto Done;
+	}
 
 	res = usb_autopm_get_interface(usbhid->intf);
 	/* the device must be awake to reliably request remote wakeup */
 	if (res < 0) {
 		clear_bit(HID_OPENED, &usbhid->iofl);
-		return -EIO;
+		res = -EIO;
+		goto Done;
 	}
 
 	usbhid->intf->needs_remote_wakeup = 1;
@@ -725,6 +730,9 @@
 		msleep(50);
 
 	clear_bit(HID_RESUME_RUNNING, &usbhid->iofl);
+
+ Done:
+	mutex_unlock(&usbhid->mutex);
 	return res;
 }
 
@@ -732,6 +740,8 @@
 {
 	struct usbhid_device *usbhid = hid->driver_data;
 
+	mutex_lock(&usbhid->mutex);
+
 	/*
 	 * Make sure we don't restart data acquisition due to
 	 * a resumption we no longer care about by avoiding racing
@@ -743,12 +753,13 @@
 		clear_bit(HID_IN_POLLING, &usbhid->iofl);
 	spin_unlock_irq(&usbhid->lock);
 
-	if (hid->quirks & HID_QUIRK_ALWAYS_POLL)
-		return;
+	if (!(hid->quirks & HID_QUIRK_ALWAYS_POLL)) {
+		hid_cancel_delayed_stuff(usbhid);
+		usb_kill_urb(usbhid->urbin);
+		usbhid->intf->needs_remote_wakeup = 0;
+	}
 
-	hid_cancel_delayed_stuff(usbhid);
-	usb_kill_urb(usbhid->urbin);
-	usbhid->intf->needs_remote_wakeup = 0;
+	mutex_unlock(&usbhid->mutex);
 }
 
 /*
@@ -1057,6 +1068,8 @@
 	unsigned int n, insize = 0;
 	int ret;
 
+	mutex_lock(&usbhid->mutex);
+
 	clear_bit(HID_DISCONNECTED, &usbhid->iofl);
 
 	usbhid->bufsize = HID_MIN_BUFFER_SIZE;
@@ -1177,6 +1190,8 @@
 		usbhid_set_leds(hid);
 		device_set_wakeup_enable(&dev->dev, 1);
 	}
+
+	mutex_unlock(&usbhid->mutex);
 	return 0;
 
 fail:
@@ -1187,6 +1202,7 @@
 	usbhid->urbout = NULL;
 	usbhid->urbctrl = NULL;
 	hid_free_buffers(dev, hid);
+	mutex_unlock(&usbhid->mutex);
 	return ret;
 }
 
@@ -1202,10 +1218,23 @@
 		usbhid->intf->needs_remote_wakeup = 0;
 	}
 
+	mutex_lock(&usbhid->mutex);
+
 	clear_bit(HID_STARTED, &usbhid->iofl);
+
 	spin_lock_irq(&usbhid->lock);	/* Sync with error and led handlers */
 	set_bit(HID_DISCONNECTED, &usbhid->iofl);
+	while (usbhid->ctrltail != usbhid->ctrlhead) {
+		if (usbhid->ctrl[usbhid->ctrltail].dir == USB_DIR_OUT) {
+			kfree(usbhid->ctrl[usbhid->ctrltail].raw_report);
+			usbhid->ctrl[usbhid->ctrltail].raw_report = NULL;
+		}
+
+		usbhid->ctrltail = (usbhid->ctrltail + 1) &
+			(HID_CONTROL_FIFO_SIZE - 1);
+	}
 	spin_unlock_irq(&usbhid->lock);
+
 	usb_kill_urb(usbhid->urbin);
 	usb_kill_urb(usbhid->urbout);
 	usb_kill_urb(usbhid->urbctrl);
@@ -1222,6 +1251,8 @@
 	usbhid->urbout = NULL;
 
 	hid_free_buffers(hid_to_usb_dev(hid), hid);
+
+	mutex_unlock(&usbhid->mutex);
 }
 
 static int usbhid_power(struct hid_device *hid, int lvl)
@@ -1382,6 +1413,7 @@
 	INIT_WORK(&usbhid->reset_work, hid_reset);
 	timer_setup(&usbhid->io_retry, hid_retry_timeout, 0);
 	spin_lock_init(&usbhid->lock);
+	mutex_init(&usbhid->mutex);
 
 	ret = hid_add_device(hid);
 	if (ret) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/usbhid/hid-pidff.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/usbhid/hid-pidff.c
@@ -1292,6 +1292,7 @@
 
 	if (pidff->pool[PID_DEVICE_MANAGED_POOL].value &&
 	    pidff->pool[PID_DEVICE_MANAGED_POOL].value[0] == 0) {
+		error = -EPERM;
 		hid_notice(hid,
 			   "device does not support device managed pool\n");
 		goto fail;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/usbhid/hiddev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/usbhid/hiddev.c
@@ -241,12 +241,51 @@
 	return 0;
 }
 
+static int __hiddev_open(struct hiddev *hiddev, struct file *file)
+{
+	struct hiddev_list *list;
+	int error;
+
+	lockdep_assert_held(&hiddev->existancelock);
+
+	list = vzalloc(sizeof(*list));
+	if (!list)
+		return -ENOMEM;
+
+	mutex_init(&list->thread_lock);
+	list->hiddev = hiddev;
+
+	if (!hiddev->open++) {
+		error = hid_hw_power(hiddev->hid, PM_HINT_FULLON);
+		if (error < 0)
+			goto err_drop_count;
+
+		error = hid_hw_open(hiddev->hid);
+		if (error < 0)
+			goto err_normal_power;
+	}
+
+	spin_lock_irq(&hiddev->list_lock);
+	list_add_tail(&list->node, &hiddev->list);
+	spin_unlock_irq(&hiddev->list_lock);
+
+	file->private_data = list;
+
+	return 0;
+
+err_normal_power:
+	hid_hw_power(hiddev->hid, PM_HINT_NORMAL);
+err_drop_count:
+	hiddev->open--;
+	vfree(list);
+	return error;
+}
+
 /*
  * open file op
  */
 static int hiddev_open(struct inode *inode, struct file *file)
 {
-	struct hiddev_list *list;
 	struct usb_interface *intf;
 	struct hid_device *hid;
 	struct hiddev *hiddev;
@@ -255,66 +294,14 @@
 	intf = usbhid_find_interface(iminor(inode));
 	if (!intf)
 		return -ENODEV;
+
 	hid = usb_get_intfdata(intf);
 	hiddev = hid->hiddev;
 
-	if (!(list = vzalloc(sizeof(struct hiddev_list))))
-		return -ENOMEM;
-	mutex_init(&list->thread_lock);
-	list->hiddev = hiddev;
-	file->private_data = list;
-
-	/*
-	 * no need for locking because the USB major number
-	 * is shared which usbcore guards against disconnect
-	 */
-	if (list->hiddev->exist) {
-		if (!list->hiddev->open++) {
-			res = hid_hw_open(hiddev->hid);
-			if (res < 0)
-				goto bail;
-		}
-	} else {
-		res = -ENODEV;
-		goto bail;
-	}
-
-	spin_lock_irq(&list->hiddev->list_lock);
-	list_add_tail(&list->node, &hiddev->list);
-	spin_unlock_irq(&list->hiddev->list_lock);
-
 	mutex_lock(&hiddev->existancelock);
-	/*
-	 * recheck exist with existance lock held to
-	 * avoid opening a disconnected device
-	 */
-	if (!list->hiddev->exist) {
-		res = -ENODEV;
-		goto bail_unlock;
-	}
-	if (!list->hiddev->open++)
-		if (list->hiddev->exist) {
-			struct hid_device *hid = hiddev->hid;
-			res = hid_hw_power(hid, PM_HINT_FULLON);
-			if (res < 0)
-				goto bail_unlock;
-			res = hid_hw_open(hid);
-			if (res < 0)
-				goto bail_normal_power;
-		}
-	mutex_unlock(&hiddev->existancelock);
-	return 0;
-bail_normal_power:
-	hid_hw_power(hid, PM_HINT_NORMAL);
-bail_unlock:
+	res = hiddev->exist ? __hiddev_open(hiddev, file) : -ENODEV;
 	mutex_unlock(&hiddev->existancelock);
 
-	spin_lock_irq(&list->hiddev->list_lock);
-	list_del(&list->node);
-	spin_unlock_irq(&list->hiddev->list_lock);
-bail:
-	file->private_data = NULL;
-	vfree(list);
 	return res;
 }
 
@@ -532,12 +519,16 @@
 
 		switch (cmd) {
 		case HIDIOCGUSAGE:
+			if (uref->usage_index >= field->report_count)
+				goto inval;
 			uref->value = field->value[uref->usage_index];
 			if (copy_to_user(user_arg, uref, sizeof(*uref)))
 				goto fault;
 			goto goodreturn;
 
 		case HIDIOCSUSAGE:
+			if (uref->usage_index >= field->report_count)
+				goto inval;
 			field->value[uref->usage_index] = uref->value;
 			goto goodreturn;
 
@@ -954,9 +945,9 @@
 	hiddev->exist = 0;
 
 	if (hiddev->open) {
-		mutex_unlock(&hiddev->existancelock);
 		hid_hw_close(hiddev->hid);
 		wake_up_interruptible(&hiddev->wait);
+		mutex_unlock(&hiddev->existancelock);
 	} else {
 		mutex_unlock(&hiddev->existancelock);
 		kfree(hiddev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/usbhid/usbhid.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/usbhid/usbhid.h
@@ -80,6 +80,7 @@
 	dma_addr_t outbuf_dma;                                          /* Output buffer dma */
 	unsigned long last_out;							/* record of last output for timeouts */
 
+	struct mutex mutex;						/* start/stop/open/close */
 	spinlock_t lock;						/* fifo spinlock */
 	unsigned long iofl;                                             /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */
 	struct timer_list io_retry;                                     /* Retry timer */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/wacom.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/wacom.h
@@ -91,6 +91,7 @@
 #include <linux/leds.h>
 #include <linux/usb/input.h>
 #include <linux/power_supply.h>
+#include <linux/timer.h>
 #include <asm/unaligned.h>
 
 /*
@@ -152,6 +153,7 @@
 		struct input_dev *input;
 		bool registered;
 		struct wacom_battery battery;
+		ktime_t active_time;
 	} remotes[WACOM_MAX_REMOTES];
 };
 
@@ -167,6 +169,7 @@
 	struct delayed_work init_work;
 	struct wacom_remote *remote;
 	struct work_struct mode_change_work;
+	struct timer_list idleprox_timer;
 	bool generic_has_leds;
 	struct wacom_leds {
 		struct wacom_group_leds *groups;
@@ -239,4 +242,5 @@
 struct wacom_led *wacom_led_next(struct wacom *wacom, struct wacom_led *cur);
 int wacom_equivalent_usage(int usage);
 int wacom_initialize_leds(struct wacom *wacom);
+void wacom_idleprox_timeout(struct timer_list *list);
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/wacom_sys.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/wacom_sys.c
@@ -147,9 +147,9 @@
 	}
 
 	if (flush)
-		wacom_wac_queue_flush(hdev, &wacom_wac->pen_fifo);
+		wacom_wac_queue_flush(hdev, wacom_wac->pen_fifo);
 	else if (insert)
-		wacom_wac_queue_insert(hdev, &wacom_wac->pen_fifo,
+		wacom_wac_queue_insert(hdev, wacom_wac->pen_fifo,
 				       raw_data, report_size);
 
 	return insert && !flush;
@@ -160,6 +160,9 @@
 {
 	struct wacom *wacom = hid_get_drvdata(hdev);
 
+	if (wacom->wacom_wac.features.type == BOOTLOADER)
+		return 0;
+
 	if (size > WACOM_PKGLEN_MAX)
 		return 1;
 
@@ -319,9 +322,11 @@
 			data[0] = field->report->id;
 			ret = wacom_get_report(hdev, HID_FEATURE_REPORT,
 					       data, n, WAC_CMD_RETRIES);
-			if (ret == n) {
+			if (ret == n && features->type == HID_GENERIC) {
 				ret = hid_report_raw_event(hdev,
 					HID_FEATURE_REPORT, data, n, 0);
+			} else if (ret == 2 && features->type != HID_GENERIC) {
+				features->touch_max = data[1];
 			} else {
 				features->touch_max = 16;
 				hid_warn(hdev, "wacom_feature_mapping: "
@@ -724,7 +729,7 @@
 	 * Skip the query for this type and modify defaults based on
 	 * interface number.
 	 */
-	if (features->type == WIRELESS) {
+	if (features->type == WIRELESS && intf) {
 		if (intf->cur_altsetting->desc.bInterfaceNumber == 0)
 			features->device_type = WACOM_DEVICETYPE_WL_MONITOR;
 		else
@@ -1268,6 +1273,38 @@
 					       group);
 }
 
+static void wacom_devm_kfifo_release(struct device *dev, void *res)
+{
+	struct kfifo_rec_ptr_2 *devres = res;
+
+	kfifo_free(devres);
+}
+
+static int wacom_devm_kfifo_alloc(struct wacom *wacom)
+{
+	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+	struct kfifo_rec_ptr_2 *pen_fifo;
+	int error;
+
+	pen_fifo = devres_alloc(wacom_devm_kfifo_release,
+			      sizeof(struct kfifo_rec_ptr_2),
+			      GFP_KERNEL);
+
+	if (!pen_fifo)
+		return -ENOMEM;
+
+	error = kfifo_alloc(pen_fifo, WACOM_PKGLEN_MAX, GFP_KERNEL);
+	if (error) {
+		devres_free(pen_fifo);
+		return error;
+	}
+
+	devres_add(&wacom->hdev->dev, pen_fifo);
+	wacom_wac->pen_fifo = pen_fifo;
+
+	return 0;
+}
+
 enum led_brightness wacom_leds_brightness_get(struct wacom_led *led)
 {
 	struct wacom *wacom = led->wacom;
@@ -2051,7 +2088,7 @@
 	return 0;
 }
 
-static int wacom_register_inputs(struct wacom *wacom)
+static int wacom_setup_inputs(struct wacom *wacom)
 {
 	struct input_dev *pen_input_dev, *touch_input_dev, *pad_input_dev;
 	struct wacom_wac *wacom_wac = &(wacom->wacom_wac);
@@ -2070,10 +2107,6 @@
 		input_free_device(pen_input_dev);
 		wacom_wac->pen_input = NULL;
 		pen_input_dev = NULL;
-	} else {
-		error = input_register_device(pen_input_dev);
-		if (error)
-			goto fail;
 	}
 
 	error = wacom_setup_touch_input_capabilities(touch_input_dev, wacom_wac);
@@ -2082,19 +2115,42 @@
 		input_free_device(touch_input_dev);
 		wacom_wac->touch_input = NULL;
 		touch_input_dev = NULL;
-	} else {
-		error = input_register_device(touch_input_dev);
-		if (error)
-			goto fail;
 	}
 
 	error = wacom_setup_pad_input_capabilities(pad_input_dev, wacom_wac);
 	if (error) {
-		/* no pad in use on this interface */
+		/* no pad events using this interface */
 		input_free_device(pad_input_dev);
 		wacom_wac->pad_input = NULL;
 		pad_input_dev = NULL;
-	} else {
+	}
+
+	return 0;
+}
+
+static int wacom_register_inputs(struct wacom *wacom)
+{
+	struct input_dev *pen_input_dev, *touch_input_dev, *pad_input_dev;
+	struct wacom_wac *wacom_wac = &(wacom->wacom_wac);
+	int error = 0;
+
+	pen_input_dev = wacom_wac->pen_input;
+	touch_input_dev = wacom_wac->touch_input;
+	pad_input_dev = wacom_wac->pad_input;
+
+	if (pen_input_dev) {
+		error = input_register_device(pen_input_dev);
+		if (error)
+			goto fail;
+	}
+
+	if (touch_input_dev) {
+		error = input_register_device(touch_input_dev);
+		if (error)
+			goto fail;
+	}
+
+	if (pad_input_dev) {
 		error = input_register_device(pad_input_dev);
 		if (error)
 			goto fail;
@@ -2183,10 +2239,11 @@
 	if ((features->type == HID_GENERIC) && !strcmp("Wacom HID", features->name)) {
 		char *product_name = wacom->hdev->name;
 
-		if (hid_is_using_ll_driver(wacom->hdev, &usb_hid_driver)) {
+		if (hid_is_usb(wacom->hdev)) {
 			struct usb_interface *intf = to_usb_interface(wacom->hdev->dev.parent);
 			struct usb_device *dev = interface_to_usbdev(intf);
-			product_name = dev->product;
+			if (dev->product != NULL)
+				product_name = dev->product;
 		}
 
 		if (wacom->hdev->bus == BUS_I2C) {
@@ -2344,6 +2401,20 @@
 			goto fail;
 	}
 
+	error = wacom_setup_inputs(wacom);
+	if (error)
+		goto fail;
+
+	if (features->type == HID_GENERIC)
+		connect_mask |= HID_CONNECT_DRIVER;
+
+	/* Regular HID work starts now */
+	error = hid_hw_start(hdev, connect_mask);
+	if (error) {
+		hid_err(hdev, "hw start failed\n");
+		goto fail;
+	}
+
 	error = wacom_register_inputs(wacom);
 	if (error)
 		goto fail;
@@ -2358,16 +2429,6 @@
 			goto fail;
 	}
 
-	if (features->type == HID_GENERIC)
-		connect_mask |= HID_CONNECT_DRIVER;
-
-	/* Regular HID work starts now */
-	error = hid_hw_start(hdev, connect_mask);
-	if (error) {
-		hid_err(hdev, "hw start failed\n");
-		goto fail;
-	}
-
 	if (!wireless) {
 		/* Note that if query fails it is not a hard failure */
 		wacom_query_tablet_data(wacom);
@@ -2382,8 +2443,13 @@
 		goto fail_quirks;
 	}
 
-	if (features->device_type & WACOM_DEVICETYPE_WL_MONITOR)
+	if (features->device_type & WACOM_DEVICETYPE_WL_MONITOR) {
 		error = hid_hw_open(hdev);
+		if (error) {
+			hid_err(hdev, "hw open failed\n");
+			goto fail_quirks;
+		}
+	}
 
 	wacom_set_shared_values(wacom_wac);
 	devres_close_group(&hdev->dev, wacom);
@@ -2414,6 +2480,9 @@
 
 	wacom_destroy_battery(wacom);
 
+	if (!usbdev)
+		return;
+
 	/* Stylus interface */
 	hdev1 = usb_get_intfdata(usbdev->config->interface[1]);
 	wacom1 = hid_get_drvdata(hdev1);
@@ -2484,6 +2553,18 @@
 	return;
 }
 
+static void wacom_remote_destroy_battery(struct wacom *wacom, int index)
+{
+	struct wacom_remote *remote = wacom->remote;
+
+	if (remote->remotes[index].battery.battery) {
+		devres_release_group(&wacom->hdev->dev,
+				     &remote->remotes[index].battery.bat_desc);
+		remote->remotes[index].battery.battery = NULL;
+		remote->remotes[index].active_time = 0;
+	}
+}
+
 static void wacom_remote_destroy_one(struct wacom *wacom, unsigned int index)
 {
 	struct wacom_remote *remote = wacom->remote;
@@ -2498,9 +2579,7 @@
 			remote->remotes[i].registered = false;
 			spin_unlock_irqrestore(&remote->remote_lock, flags);
 
-			if (remote->remotes[i].battery.battery)
-				devres_release_group(&wacom->hdev->dev,
-						     &remote->remotes[i].battery.bat_desc);
+			wacom_remote_destroy_battery(wacom, i);
 
 			if (remote->remotes[i].group.name)
 				devres_release_group(&wacom->hdev->dev,
@@ -2508,7 +2587,6 @@
 
 			remote->remotes[i].serial = 0;
 			remote->remotes[i].group.name = NULL;
-			remote->remotes[i].battery.battery = NULL;
 			wacom->led.groups[i].select = WACOM_STATUS_UNKNOWN;
 		}
 	}
@@ -2593,6 +2671,9 @@
 	if (remote->remotes[index].battery.battery)
 		return 0;
 
+	if (!remote->remotes[index].active_time)
+		return 0;
+
 	if (wacom->led.groups[index].select == WACOM_STATUS_UNKNOWN)
 		return 0;
 
@@ -2608,6 +2689,7 @@
 {
 	struct wacom *wacom = container_of(work, struct wacom, remote_work);
 	struct wacom_remote *remote = wacom->remote;
+	ktime_t kt = ktime_get();
 	struct wacom_remote_data data;
 	unsigned long flags;
 	unsigned int count;
@@ -2634,6 +2716,10 @@
 		serial = data.remote[i].serial;
 		if (data.remote[i].connected) {
 
+			if (kt - remote->remotes[i].active_time > WACOM_REMOTE_BATTERY_TIMEOUT
+			    && remote->remotes[i].active_time != 0)
+				wacom_remote_destroy_battery(wacom, i);
+
 			if (remote->remotes[i].serial == serial) {
 				wacom_remote_attach_battery(wacom, i);
 				continue;
@@ -2693,8 +2779,6 @@
 static int wacom_probe(struct hid_device *hdev,
 		const struct hid_device_id *id)
 {
-	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
-	struct usb_device *dev = interface_to_usbdev(intf);
 	struct wacom *wacom;
 	struct wacom_wac *wacom_wac;
 	struct wacom_features *features;
@@ -2722,21 +2806,28 @@
 	if (features->check_for_hid_type && features->hid_type != hdev->type)
 		return -ENODEV;
 
-	error = kfifo_alloc(&wacom_wac->pen_fifo, WACOM_PKGLEN_MAX, GFP_KERNEL);
+	error = wacom_devm_kfifo_alloc(wacom);
 	if (error)
 		return error;
 
 	wacom_wac->hid_data.inputmode = -1;
 	wacom_wac->mode_report = -1;
 
-	wacom->usbdev = dev;
-	wacom->intf = intf;
+	if (hid_is_usb(hdev)) {
+		struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+		struct usb_device *dev = interface_to_usbdev(intf);
+
+		wacom->usbdev = dev;
+		wacom->intf = intf;
+	}
+
 	mutex_init(&wacom->lock);
 	INIT_DELAYED_WORK(&wacom->init_work, wacom_init_work);
 	INIT_WORK(&wacom->wireless_work, wacom_wireless_work);
 	INIT_WORK(&wacom->battery_work, wacom_battery_work);
 	INIT_WORK(&wacom->remote_work, wacom_remote_work);
 	INIT_WORK(&wacom->mode_change_work, wacom_mode_change_work);
+	timer_setup(&wacom->idleprox_timer, &wacom_idleprox_timeout, TIMER_DEFERRABLE);
 
 	/* ask for the report descriptor to be loaded by HID */
 	error = hid_parse(hdev);
@@ -2745,6 +2836,11 @@
 		return error;
 	}
 
+	if (features->type == BOOTLOADER) {
+		hid_warn(hdev, "Using device in hidraw-only mode");
+		return hid_hw_start(hdev, HID_CONNECT_HIDRAW);
+	}
+
 	error = wacom_parse_and_register(wacom, false);
 	if (error)
 		return error;
@@ -2776,6 +2872,7 @@
 	cancel_work_sync(&wacom->battery_work);
 	cancel_work_sync(&wacom->remote_work);
 	cancel_work_sync(&wacom->mode_change_work);
+	del_timer_sync(&wacom->idleprox_timer);
 	if (hdev->bus == BUS_BLUETOOTH)
 		device_remove_file(&hdev->dev, &dev_attr_speed);
 
@@ -2784,8 +2881,6 @@
 
 	if (wacom->wacom_wac.features.type != REMOTE)
 		wacom_release_resources(wacom);
-
-	kfifo_free(&wacom_wac->pen_fifo);
 }
 
 #ifdef CONFIG_PM
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/wacom_wac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/wacom_wac.c
@@ -11,6 +11,7 @@
 #include "wacom_wac.h"
 #include "wacom.h"
 #include <linux/input/mt.h>
+#include <linux/jiffies.h>
 
 /* resolution for penabled devices */
 #define WACOM_PL_RES		20
@@ -41,6 +42,43 @@
 
 static void wacom_update_led(struct wacom *wacom, int button_count, int mask,
 			     int group);
+
+static void wacom_force_proxout(struct wacom_wac *wacom_wac)
+{
+	struct input_dev *input = wacom_wac->pen_input;
+
+	wacom_wac->shared->stylus_in_proximity = 0;
+
+	input_report_key(input, BTN_TOUCH, 0);
+	input_report_key(input, BTN_STYLUS, 0);
+	input_report_key(input, BTN_STYLUS2, 0);
+	input_report_key(input, BTN_STYLUS3, 0);
+	input_report_key(input, wacom_wac->tool[0], 0);
+	if (wacom_wac->serial[0]) {
+		input_report_abs(input, ABS_MISC, 0);
+	}
+	input_report_abs(input, ABS_PRESSURE, 0);
+
+	wacom_wac->tool[0] = 0;
+	wacom_wac->id[0] = 0;
+	wacom_wac->serial[0] = 0;
+
+	input_sync(input);
+}
+
+void wacom_idleprox_timeout(struct timer_list *list)
+{
+	struct wacom *wacom = from_timer(wacom, list, idleprox_timer);
+	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
+
+	if (!wacom_wac->hid_data.sense_state) {
+		return;
+	}
+
+	hid_warn(wacom->hdev, "%s: tool appears to be hung in-prox. forcing it out.\n", __func__);
+	wacom_force_proxout(wacom_wac);
+}
+
 /*
  * Percent of battery capacity for Graphire.
  * 8th value means AC online and show 100% capacity.
@@ -638,9 +676,26 @@
 	return (tool_id & ~0xFFF) << 4 | (tool_id & 0xFFF);
 }
 
+static bool wacom_is_art_pen(int tool_id)
+{
+	bool is_art_pen = false;
+
+	switch (tool_id) {
+	case 0x885:	/* Intuos3 Marker Pen */
+	case 0x804:	/* Intuos4/5 13HD/24HD Marker Pen */
+	case 0x10804:	/* Intuos4/5 13HD/24HD Art Pen */
+		is_art_pen = true;
+		break;
+	}
+	return is_art_pen;
+}
+
 static int wacom_intuos_get_tool_type(int tool_id)
 {
-	int tool_type;
+	int tool_type = BTN_TOOL_PEN;
+
+	if (wacom_is_art_pen(tool_id))
+		return tool_type;
 
 	switch (tool_id) {
 	case 0x812: /* Inking pen */
@@ -655,17 +710,16 @@
 	case 0x852:
 	case 0x823: /* Intuos3 Grip Pen */
 	case 0x813: /* Intuos3 Classic Pen */
-	case 0x885: /* Intuos3 Marker Pen */
 	case 0x802: /* Intuos4/5 13HD/24HD General Pen */
-	case 0x804: /* Intuos4/5 13HD/24HD Marker Pen */
 	case 0x8e2: /* IntuosHT2 pen */
 	case 0x022:
-	case 0x10804: /* Intuos4/5 13HD/24HD Art Pen */
+	case 0x200: /* Pro Pen 3 */
 	case 0x10842: /* MobileStudio Pro Pro Pen slim */
 	case 0x14802: /* Intuos4/5 13HD/24HD Classic Pen */
 	case 0x16802: /* Cintiq 13HD Pro Pen */
 	case 0x18802: /* DTH2242 Pen */
 	case 0x10802: /* Intuos4/5 13HD/24HD General Pen */
+	case 0x8842: /* Intuos Pro and Cintiq Pro 3D Pen */
 		tool_type = BTN_TOOL_PEN;
 		break;
 
@@ -718,10 +772,6 @@
 	case 0x10902: /* Intuos4/5 13HD/24HD Airbrush */
 		tool_type = BTN_TOOL_AIRBRUSH;
 		break;
-
-	default: /* Unknown tool */
-		tool_type = BTN_TOOL_PEN;
-		break;
 	}
 	return tool_type;
 }
@@ -780,7 +830,7 @@
 	/* Enter report */
 	if ((data[1] & 0xfc) == 0xc0) {
 		/* serial number of the tool */
-		wacom->serial[idx] = ((data[3] & 0x0f) << 28) +
+		wacom->serial[idx] = ((__u64)(data[3] & 0x0f) << 28) +
 			(data[4] << 20) + (data[5] << 12) +
 			(data[6] << 4) + (data[7] >> 4);
 
@@ -1076,6 +1126,7 @@
 	if (index < 0 || !remote->remotes[index].registered)
 		goto out;
 
+	remote->remotes[i].active_time = ktime_get();
 	input = remote->remotes[index].input;
 
 	input_report_key(input, BTN_0, (data[9] & 0x01));
@@ -1255,6 +1306,9 @@
 
 	struct input_dev *pen_input = wacom->pen_input;
 	unsigned char *data = wacom->data;
+	int number_of_valid_frames = 0;
+	ktime_t time_interval = 15000000;
+	ktime_t time_packet_received = ktime_get();
 	int i;
 
 	if (wacom->features.type == INTUOSP2_BT ||
@@ -1275,12 +1329,30 @@
 		wacom->id[0] |= (wacom->serial[0] >> 32) & 0xFFFFF;
 	}
 
+	/* number of valid frames */
 	for (i = 0; i < pen_frames; i++) {
 		unsigned char *frame = &data[i*pen_frame_len + 1];
 		bool valid = frame[0] & 0x80;
+
+		if (valid)
+			number_of_valid_frames++;
+	}
+
+	if (number_of_valid_frames) {
+		if (wacom->hid_data.time_delayed)
+			time_interval = ktime_get() - wacom->hid_data.time_delayed;
+		time_interval = div_u64(time_interval, number_of_valid_frames);
+		wacom->hid_data.time_delayed = time_packet_received;
+	}
+
+	for (i = 0; i < number_of_valid_frames; i++) {
+		unsigned char *frame = &data[i*pen_frame_len + 1];
+		bool valid = frame[0] & 0x80;
 		bool prox = frame[0] & 0x40;
 		bool range = frame[0] & 0x20;
 		bool invert = frame[0] & 0x10;
+		int frames_number_reversed = number_of_valid_frames - i - 1;
+		ktime_t event_timestamp = time_packet_received - frames_number_reversed * time_interval;
 
 		if (!valid)
 			continue;
@@ -1293,6 +1365,7 @@
 			wacom->tool[0] = 0;
 			wacom->id[0] = 0;
 			wacom->serial[0] = 0;
+			wacom->hid_data.time_delayed = 0;
 			return;
 		}
 
@@ -1321,14 +1394,15 @@
 					rotation -= 1800;
 
 				input_report_abs(pen_input, ABS_TILT_X,
-						 (char)frame[7]);
+						 (signed char)frame[7]);
 				input_report_abs(pen_input, ABS_TILT_Y,
-						 (char)frame[8]);
+						 (signed char)frame[8]);
 				input_report_abs(pen_input, ABS_Z, rotation);
 				input_report_abs(pen_input, ABS_WHEEL,
 						 get_unaligned_le16(&frame[11]));
 			}
 		}
+
 		if (wacom->tool[0]) {
 			input_report_abs(pen_input, ABS_PRESSURE, get_unaligned_le16(&frame[5]));
 			if (wacom->features.type == INTUOSP2_BT ||
@@ -1352,6 +1426,9 @@
 
 		wacom->shared->stylus_in_proximity = prox;
 
+		/* add timestamp to unpack the frames */
+		input_set_timestamp(pen_input, event_timestamp);
+
 		input_sync(pen_input);
 	}
 }
@@ -1427,11 +1504,13 @@
 {
 	struct input_dev *pad_input = wacom->pad_input;
 	unsigned char *data = wacom->data;
+	int nbuttons = wacom->features.numbered_buttons;
 
-	int buttons = data[282] | ((data[281] & 0x40) << 2);
+	int expresskeys = data[282];
+	int center = (data[281] & 0x40) >> 6;
 	int ring = data[285] & 0x7F;
 	bool ringstatus = data[285] & 0x80;
-	bool prox = buttons || ringstatus;
+	bool prox = expresskeys || center || ringstatus;
 
 	/* Fix touchring data: userspace expects 0 at left and increasing clockwise */
 	ring = 71 - ring;
@@ -1439,7 +1518,8 @@
 	if (ring > 71)
 		ring -= 72;
 
-	wacom_report_numbered_buttons(pad_input, 9, buttons);
+	wacom_report_numbered_buttons(pad_input, nbuttons,
+                                      expresskeys | (center << (nbuttons - 1)));
 
 	input_report_abs(pad_input, ABS_WHEEL, ringstatus ? ring : 0);
 
@@ -1840,11 +1920,14 @@
 	int fmax = field->logical_maximum;
 	unsigned int equivalent_usage = wacom_equivalent_usage(usage->hid);
 	int resolution_code = code;
+	int resolution;
 
 	if (equivalent_usage == HID_DG_TWIST) {
 		resolution_code = ABS_RZ;
 	}
 
+	resolution = hidinput_calc_abs_res(field, resolution_code);
+
 	if (equivalent_usage == HID_GD_X) {
 		fmin += features->offset_left;
 		fmax -= features->offset_right;
@@ -1862,8 +1945,15 @@
 	switch (type) {
 	case EV_ABS:
 		input_set_abs_params(input, code, fmin, fmax, fuzz, 0);
-		input_abs_set_res(input, code,
-				  hidinput_calc_abs_res(field, resolution_code));
+
+		/* older tablet may miss physical usage */
+		if ((code == ABS_X || code == ABS_Y) && !resolution) {
+			resolution = WACOM_INTUOS_RES;
+			hid_warn(input,
+				 "Wacom usage (%d) missing resolution \n",
+				 code);
+		}
+		input_abs_set_res(input, code, resolution);
 		break;
 	case EV_KEY:
 		input_set_capability(input, EV_KEY, code);
@@ -1880,18 +1970,7 @@
 static void wacom_wac_battery_usage_mapping(struct hid_device *hdev,
 		struct hid_field *field, struct hid_usage *usage)
 {
-	struct wacom *wacom = hid_get_drvdata(hdev);
-	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
-	struct wacom_features *features = &wacom_wac->features;
-	unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
-
-	switch (equivalent_usage) {
-	case HID_DG_BATTERYSTRENGTH:
-	case WACOM_HID_WD_BATTERY_LEVEL:
-	case WACOM_HID_WD_BATTERY_CHARGING:
-		features->quirks |= WACOM_QUIRK_BATTERY;
-		break;
-	}
+	return;
 }
 
 static void wacom_wac_battery_event(struct hid_device *hdev, struct hid_field *field,
@@ -1912,18 +1991,21 @@
 			wacom_wac->hid_data.bat_connected = 1;
 			wacom_wac->hid_data.bat_status = WACOM_POWER_SUPPLY_STATUS_AUTO;
 		}
+		wacom_wac->features.quirks |= WACOM_QUIRK_BATTERY;
 		break;
 	case WACOM_HID_WD_BATTERY_LEVEL:
 		value = value * 100 / (field->logical_maximum - field->logical_minimum);
 		wacom_wac->hid_data.battery_capacity = value;
 		wacom_wac->hid_data.bat_connected = 1;
 		wacom_wac->hid_data.bat_status = WACOM_POWER_SUPPLY_STATUS_AUTO;
+		wacom_wac->features.quirks |= WACOM_QUIRK_BATTERY;
 		break;
 	case WACOM_HID_WD_BATTERY_CHARGING:
 		wacom_wac->hid_data.bat_charging = value;
 		wacom_wac->hid_data.ps_connected = value;
 		wacom_wac->hid_data.bat_connected = 1;
 		wacom_wac->hid_data.bat_status = WACOM_POWER_SUPPLY_STATUS_AUTO;
+		wacom_wac->features.quirks |= WACOM_QUIRK_BATTERY;
 		break;
 	}
 }
@@ -1939,18 +2021,15 @@
 {
 	struct wacom *wacom = hid_get_drvdata(hdev);
 	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
-	struct wacom_features *features = &wacom_wac->features;
 
-	if (features->quirks & WACOM_QUIRK_BATTERY) {
-		int status = wacom_wac->hid_data.bat_status;
-		int capacity = wacom_wac->hid_data.battery_capacity;
-		bool charging = wacom_wac->hid_data.bat_charging;
-		bool connected = wacom_wac->hid_data.bat_connected;
-		bool powered = wacom_wac->hid_data.ps_connected;
+	int status = wacom_wac->hid_data.bat_status;
+	int capacity = wacom_wac->hid_data.battery_capacity;
+	bool charging = wacom_wac->hid_data.bat_charging;
+	bool connected = wacom_wac->hid_data.bat_connected;
+	bool powered = wacom_wac->hid_data.ps_connected;
 
-		wacom_notify_battery(wacom_wac, status, capacity, charging,
-				     connected, powered);
-	}
+	wacom_notify_battery(wacom_wac, status, capacity, charging,
+			     connected, powered);
 }
 
 static void wacom_wac_pad_usage_mapping(struct hid_device *hdev,
@@ -2003,7 +2082,6 @@
 		wacom_wac->has_mute_touch_switch = true;
 		usage->type = EV_SW;
 		usage->code = SW_MUTE_DEVICE;
-		features->device_type |= WACOM_DEVICETYPE_PAD;
 		break;
 	case WACOM_HID_WD_TOUCHSTRIP:
 		wacom_map_usage(input, usage, field, EV_ABS, ABS_RX, 0);
@@ -2083,6 +2161,30 @@
 			wacom_wac->hid_data.inrange_state |= value;
 	}
 
+	/* Process touch switch state first since it is reported through touch interface,
+	 * which is indepentent of pad interface. In the case when there are no other pad
+	 * events, the pad interface will not even be created.
+	 */
+	if ((equivalent_usage == WACOM_HID_WD_MUTE_DEVICE) ||
+	   (equivalent_usage == WACOM_HID_WD_TOUCHONOFF)) {
+		if (wacom_wac->shared->touch_input) {
+			bool *is_touch_on = &wacom_wac->shared->is_touch_on;
+
+			if (equivalent_usage == WACOM_HID_WD_MUTE_DEVICE && value)
+				*is_touch_on = !(*is_touch_on);
+			else if (equivalent_usage == WACOM_HID_WD_TOUCHONOFF)
+				*is_touch_on = value;
+
+			input_report_switch(wacom_wac->shared->touch_input,
+					    SW_MUTE_DEVICE, !(*is_touch_on));
+			input_sync(wacom_wac->shared->touch_input);
+		}
+		return;
+	}
+
+	if (!input)
+		return;
+
 	switch (equivalent_usage) {
 	case WACOM_HID_WD_TOUCHRING:
 		/*
@@ -2096,14 +2198,16 @@
 		    (hdev->product == 0x34d || hdev->product == 0x34e ||  /* MobileStudio Pro */
 		     hdev->product == 0x357 || hdev->product == 0x358 ||  /* Intuos Pro 2 */
 		     hdev->product == 0x392 ||				  /* Intuos Pro 2 */
-		     hdev->product == 0x398 || hdev->product == 0x399)) { /* MobileStudio Pro */
+		     hdev->product == 0x398 || hdev->product == 0x399 ||  /* MobileStudio Pro */
+		     hdev->product == 0x3AA)) {				  /* MobileStudio Pro */
 			value = (field->logical_maximum - value);
 
 			if (hdev->product == 0x357 || hdev->product == 0x358 ||
 			    hdev->product == 0x392)
 				value = wacom_offset_rotation(input, usage, value, 3, 16);
 			else if (hdev->product == 0x34d || hdev->product == 0x34e ||
-				 hdev->product == 0x398 || hdev->product == 0x399)
+				 hdev->product == 0x398 || hdev->product == 0x399 ||
+				 hdev->product == 0x3AA)
 				value = wacom_offset_rotation(input, usage, value, 1, 2);
 		}
 		else {
@@ -2116,22 +2220,6 @@
 			input_event(input, usage->type, usage->code, 0);
 		break;
 
-	case WACOM_HID_WD_MUTE_DEVICE:
-	case WACOM_HID_WD_TOUCHONOFF:
-		if (wacom_wac->shared->touch_input) {
-			bool *is_touch_on = &wacom_wac->shared->is_touch_on;
-
-			if (equivalent_usage == WACOM_HID_WD_MUTE_DEVICE && value)
-				*is_touch_on = !(*is_touch_on);
-			else if (equivalent_usage == WACOM_HID_WD_TOUCHONOFF)
-				*is_touch_on = value;
-
-			input_report_switch(wacom_wac->shared->touch_input,
-					    SW_MUTE_DEVICE, !(*is_touch_on));
-			input_sync(wacom_wac->shared->touch_input);
-		}
-		break;
-
 	case WACOM_HID_WD_MODE_CHANGE:
 		if (wacom_wac->is_direct_mode != value) {
 			wacom_wac->is_direct_mode = value;
@@ -2283,6 +2371,7 @@
 		value = field->logical_maximum - value;
 		break;
 	case HID_DG_INRANGE:
+		mod_timer(&wacom->idleprox_timer, jiffies + msecs_to_jiffies(100));
 		wacom_wac->hid_data.inrange_state = value;
 		if (!(features->quirks & WACOM_QUIRK_SENSE))
 			wacom_wac->hid_data.sense_state = value;
@@ -2307,6 +2396,9 @@
 		}
 		return;
 	case HID_DG_TWIST:
+		/* don't modify the value if the pen doesn't support the feature */
+		if (!wacom_is_art_pen(wacom_wac->id[0])) return;
+
 		/*
 		 * Userspace expects pen twist to have its zero point when
 		 * the buttons/finger is on the tablet's left. HID values
@@ -2449,7 +2541,14 @@
 				wacom_wac->hid_data.tipswitch);
 		input_report_key(input, wacom_wac->tool[0], sense);
 		if (wacom_wac->serial[0]) {
-			input_event(input, EV_MSC, MSC_SERIAL, wacom_wac->serial[0]);
+			/*
+			 * xf86-input-wacom does not accept a serial number
+			 * of '0'. Report the low 32 bits if possible, but
+			 * if they are zero, report the upper ones instead.
+			 */
+			__u32 serial_lo = wacom_wac->serial[0] & 0xFFFFFFFFu;
+			__u32 serial_hi = wacom_wac->serial[0] >> 32;
+			input_event(input, EV_MSC, MSC_SERIAL, (int)(serial_lo ? serial_lo : serial_hi));
 			input_report_abs(input, ABS_MISC, sense ? id : 0);
 		}
 
@@ -2521,14 +2620,14 @@
 {
 	struct hid_data *hid_data = &wacom_wac->hid_data;
 	bool mt = wacom_wac->features.touch_max > 1;
-	bool prox = hid_data->tipswitch &&
-		    report_touch_events(wacom_wac);
+	bool touch_down = hid_data->tipswitch && hid_data->confidence;
+	bool prox = touch_down && report_touch_events(wacom_wac);
 
 	if (wacom_wac->shared->has_mute_touch_switch &&
 	    !wacom_wac->shared->is_touch_on) {
 		if (!wacom_wac->shared->touch_down)
 			return;
-		prox = 0;
+		prox = false;
 	}
 
 	wacom_wac->hid_data.num_received++;
@@ -2573,6 +2672,9 @@
 		return;
 
 	switch (equivalent_usage) {
+	case HID_DG_CONFIDENCE:
+		wacom_wac->hid_data.confidence = value;
+		break;
 	case HID_GD_X:
 		wacom_wac->hid_data.x = value;
 		break;
@@ -2595,7 +2697,12 @@
 		wacom_wac->is_invalid_bt_frame = !value;
 		return;
 	case HID_DG_CONTACTMAX:
-		features->touch_max = value;
+		if (!features->touch_max) {
+			features->touch_max = value;
+		} else {
+			hid_warn(hdev, "%s: ignoring attempt to overwrite non-zero touch_max "
+				 "%d -> %d\n", __func__, features->touch_max, value);
+		}
 		return;
 	}
 
@@ -2615,6 +2722,12 @@
 
 	wacom_wac->is_invalid_bt_frame = false;
 
+	hid_data->confidence = true;
+
+	hid_data->cc_report = 0;
+	hid_data->cc_index = -1;
+	hid_data->cc_value_index = -1;
+
 	for (i = 0; i < report->maxfield; i++) {
 		struct hid_field *field = report->field[i];
 		int j;
@@ -2635,9 +2748,28 @@
 			case HID_DG_TIPSWITCH:
 				hid_data->last_slot_field = equivalent_usage;
 				break;
+			case HID_DG_CONTACTCOUNT:
+				hid_data->cc_report = report->id;
+				hid_data->cc_index = i;
+				hid_data->cc_value_index = j;
+				break;
 			}
 		}
 	}
+
+	if (hid_data->cc_report != 0 &&
+	    hid_data->cc_index >= 0) {
+		struct hid_field *field = report->field[hid_data->cc_index];
+		int value = field->value[hid_data->cc_value_index];
+		if (value) {
+			hid_data->num_expected = value;
+			hid_data->num_received = 0;
+		}
+	}
+	else {
+		hid_data->num_expected = wacom_wac->features.touch_max;
+		hid_data->num_received = 0;
+	}
 }
 
 static void wacom_wac_finger_report(struct hid_device *hdev,
@@ -2647,7 +2779,6 @@
 	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
 	struct input_dev *input = wacom_wac->touch_input;
 	unsigned touch_max = wacom_wac->features.touch_max;
-	struct hid_data *hid_data = &wacom_wac->hid_data;
 
 	/* If more packets of data are expected, give us a chance to
 	 * process them rather than immediately syncing a partial
@@ -2661,7 +2792,7 @@
 
 	input_sync(input);
 	wacom_wac->hid_data.num_received = 0;
-	hid_data->num_expected = 0;
+	wacom_wac->hid_data.num_expected = 0;
 
 	/* keep touch state for pen event */
 	wacom_wac->shared->touch_down = wacom_wac_finger_count_touches(wacom_wac);
@@ -2702,7 +2833,7 @@
 	/* usage tests must precede field tests */
 	if (WACOM_BATTERY_USAGE(usage))
 		wacom_wac_battery_event(hdev, field, usage, value);
-	else if (WACOM_PAD_FIELD(field) && wacom->wacom_wac.pad_input)
+	else if (WACOM_PAD_FIELD(field))
 		wacom_wac_pad_event(hdev, field, usage, value);
 	else if (WACOM_PEN_FIELD(field) && wacom->wacom_wac.pen_input)
 		wacom_wac_pen_event(hdev, field, usage, value);
@@ -2736,73 +2867,12 @@
 	}
 }
 
-static void wacom_set_num_expected(struct hid_device *hdev,
-				   struct hid_report *report,
-				   int collection_index,
-				   struct hid_field *field,
-				   int field_index)
-{
-	struct wacom *wacom = hid_get_drvdata(hdev);
-	struct wacom_wac *wacom_wac = &wacom->wacom_wac;
-	struct hid_data *hid_data = &wacom_wac->hid_data;
-	unsigned int original_collection_level =
-		hdev->collection[collection_index].level;
-	bool end_collection = false;
-	int i;
-
-	if (hid_data->num_expected)
-		return;
-
-	// find the contact count value for this segment
-	for (i = field_index; i < report->maxfield && !end_collection; i++) {
-		struct hid_field *field = report->field[i];
-		unsigned int field_level =
-			hdev->collection[field->usage[0].collection_index].level;
-		unsigned int j;
-
-		if (field_level != original_collection_level)
-			continue;
-
-		for (j = 0; j < field->maxusage; j++) {
-			struct hid_usage *usage = &field->usage[j];
-
-			if (usage->collection_index != collection_index) {
-				end_collection = true;
-				break;
-			}
-			if (wacom_equivalent_usage(usage->hid) == HID_DG_CONTACTCOUNT) {
-				hid_data->cc_report = report->id;
-				hid_data->cc_index = i;
-				hid_data->cc_value_index = j;
-
-				if (hid_data->cc_report != 0 &&
-				    hid_data->cc_index >= 0) {
-
-					struct hid_field *field =
-						report->field[hid_data->cc_index];
-					int value =
-						field->value[hid_data->cc_value_index];
-
-					if (value)
-						hid_data->num_expected = value;
-				}
-			}
-		}
-	}
-
-	if (hid_data->cc_report == 0 || hid_data->cc_index < 0)
-		hid_data->num_expected = wacom_wac->features.touch_max;
-}
-
 static int wacom_wac_collection(struct hid_device *hdev, struct hid_report *report,
 			 int collection_index, struct hid_field *field,
 			 int field_index)
 {
 	struct wacom *wacom = hid_get_drvdata(hdev);
 
-	if (WACOM_FINGER_FIELD(field))
-		wacom_set_num_expected(hdev, report, collection_index, field,
-				       field_index);
 	wacom_report_events(hdev, report, collection_index, field_index);
 
 	/*
@@ -2815,7 +2885,9 @@
 	if (report->type != HID_INPUT_REPORT)
 		return -1;
 
-	if (WACOM_PEN_FIELD(field) && wacom->wacom_wac.pen_input)
+	if (WACOM_PAD_FIELD(field))
+		return 0;
+	else if (WACOM_PEN_FIELD(field) && wacom->wacom_wac.pen_input)
 		wacom_wac_pen_report(hdev, report);
 	else if (WACOM_FINGER_FIELD(field) && wacom->wacom_wac.touch_input)
 		wacom_wac_finger_report(hdev, report);
@@ -3609,8 +3681,6 @@
 {
 	struct wacom_features *features = &wacom_wac->features;
 
-	input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
-
 	if (!(features->device_type & WACOM_DEVICETYPE_PEN))
 		return -ENODEV;
 
@@ -3625,6 +3695,7 @@
 		return 0;
 	}
 
+	input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
 	__set_bit(BTN_TOUCH, input_dev->keybit);
 	__set_bit(ABS_MISC, input_dev->absbit);
 
@@ -3777,8 +3848,6 @@
 {
 	struct wacom_features *features = &wacom_wac->features;
 
-	input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
-
 	if (!(features->device_type & WACOM_DEVICETYPE_TOUCH))
 		return -ENODEV;
 
@@ -3791,6 +3860,7 @@
 		/* setup has already been done */
 		return 0;
 
+	input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
 	__set_bit(BTN_TOUCH, input_dev->keybit);
 
 	if (features->touch_max == 1) {
@@ -3866,7 +3936,7 @@
 		    wacom_wac->shared->touch->product == 0xF6) {
 			input_dev->evbit[0] |= BIT_MASK(EV_SW);
 			__set_bit(SW_MUTE_DEVICE, input_dev->swbit);
-			wacom_wac->shared->has_mute_touch_switch = true;
+			wacom_wac->has_mute_touch_switch = true;
 		}
 		/* fall through */
 
@@ -4752,10 +4822,23 @@
 	{ "Wacom Intuos Pro S", 31920, 19950, 8191, 63,
 	  INTUOSP2S_BT, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 7,
 	  .touch_max = 10 };
+static const struct wacom_features wacom_features_0x3c6 =
+	{ "Wacom Intuos BT S", 15200, 9500, 4095, 63,
+	  INTUOSHT3_BT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4 };
+static const struct wacom_features wacom_features_0x3c8 =
+	{ "Wacom Intuos BT M", 21600, 13500, 4095, 63,
+	  INTUOSHT3_BT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4 };
+static const struct wacom_features wacom_features_0x3dd =
+	{ "Wacom Intuos Pro S", 31920, 19950, 8191, 63,
+	  INTUOSP2S_BT, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 7,
+	  .touch_max = 10 };
 
 static const struct wacom_features wacom_features_HID_ANY_ID =
 	{ "Wacom HID", .type = HID_GENERIC, .oVid = HID_ANY_ID, .oPid = HID_ANY_ID };
 
+static const struct wacom_features wacom_features_0x94 =
+	{ "Wacom Bootloader", .type = BOOTLOADER };
+
 #define USB_DEVICE_WACOM(prod)						\
 	HID_DEVICE(BUS_USB, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\
 	.driver_data = (kernel_ulong_t)&wacom_features_##prod
@@ -4768,6 +4851,10 @@
 	HID_DEVICE(BUS_I2C, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\
 	.driver_data = (kernel_ulong_t)&wacom_features_##prod
 
+#define PCI_DEVICE_WACOM(prod)						\
+	HID_DEVICE(BUS_PCI, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\
+	.driver_data = (kernel_ulong_t)&wacom_features_##prod
+
 #define USB_DEVICE_LENOVO(prod)					\
 	HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, prod),			\
 	.driver_data = (kernel_ulong_t)&wacom_features_##prod
@@ -4829,6 +4916,7 @@
 	{ USB_DEVICE_WACOM(0x84) },
 	{ USB_DEVICE_WACOM(0x90) },
 	{ USB_DEVICE_WACOM(0x93) },
+	{ USB_DEVICE_WACOM(0x94) },
 	{ USB_DEVICE_WACOM(0x97) },
 	{ USB_DEVICE_WACOM(0x9A) },
 	{ USB_DEVICE_WACOM(0x9F) },
@@ -4925,6 +5013,9 @@
 	{ USB_DEVICE_WACOM(0x37A) },
 	{ USB_DEVICE_WACOM(0x37B) },
 	{ BT_DEVICE_WACOM(0x393) },
+	{ BT_DEVICE_WACOM(0x3c6) },
+	{ BT_DEVICE_WACOM(0x3c8) },
+	{ BT_DEVICE_WACOM(0x3dd) },
 	{ USB_DEVICE_WACOM(0x4001) },
 	{ USB_DEVICE_WACOM(0x4004) },
 	{ USB_DEVICE_WACOM(0x5000) },
@@ -4933,6 +5024,7 @@
 
 	{ USB_DEVICE_WACOM(HID_ANY_ID) },
 	{ I2C_DEVICE_WACOM(HID_ANY_ID) },
+	{ PCI_DEVICE_WACOM(HID_ANY_ID) },
 	{ BT_DEVICE_WACOM(HID_ANY_ID) },
 	{ }
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hid/wacom_wac.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/hid/wacom_wac.h
@@ -15,6 +15,7 @@
 #define WACOM_NAME_MAX		64
 #define WACOM_MAX_REMOTES	5
 #define WACOM_STATUS_UNKNOWN	255
+#define WACOM_REMOTE_BATTERY_TIMEOUT	21000000000ll
 
 /* packet length for individual models */
 #define WACOM_PKGLEN_BBFUN	 9
@@ -122,7 +123,7 @@
 #define WACOM_HID_WD_TOUCHONOFF         (WACOM_HID_UP_WACOMDIGITIZER | 0x0454)
 #define WACOM_HID_WD_BATTERY_LEVEL      (WACOM_HID_UP_WACOMDIGITIZER | 0x043b)
 #define WACOM_HID_WD_EXPRESSKEY00       (WACOM_HID_UP_WACOMDIGITIZER | 0x0910)
-#define WACOM_HID_WD_EXPRESSKEYCAP00    (WACOM_HID_UP_WACOMDIGITIZER | 0x0950)
+#define WACOM_HID_WD_EXPRESSKEYCAP00    (WACOM_HID_UP_WACOMDIGITIZER | 0x0940)
 #define WACOM_HID_WD_MODE_CHANGE        (WACOM_HID_UP_WACOMDIGITIZER | 0x0980)
 #define WACOM_HID_WD_MUTE_DEVICE        (WACOM_HID_UP_WACOMDIGITIZER | 0x0981)
 #define WACOM_HID_WD_CONTROLPANEL       (WACOM_HID_UP_WACOMDIGITIZER | 0x0982)
@@ -242,6 +243,7 @@
 	MTTPC,
 	MTTPC_B,
 	HID_GENERIC,
+	BOOTLOADER,
 	MAX_TYPE
 };
 
@@ -300,6 +302,7 @@
 	bool tipswitch;
 	bool barrelswitch;
 	bool barrelswitch2;
+	bool confidence;
 	int x;
 	int y;
 	int pressure;
@@ -318,6 +321,7 @@
 	int bat_connected;
 	int ps_connected;
 	bool pad_input_event_flag;
+	ktime_t time_delayed;
 };
 
 struct wacom_remote_data {
@@ -342,7 +346,7 @@
 	struct input_dev *pen_input;
 	struct input_dev *touch_input;
 	struct input_dev *pad_input;
-	struct kfifo_rec_ptr_2 pen_fifo;
+	struct kfifo_rec_ptr_2 *pen_fifo;
 	int pid;
 	int num_contacts_left;
 	u8 bt_features;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hsi/clients/ssi_protocol.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hsi/clients/ssi_protocol.c
@@ -403,6 +403,7 @@
 	del_timer(&ssi->rx_wd);
 	del_timer(&ssi->tx_wd);
 	del_timer(&ssi->keep_alive);
+	cancel_work_sync(&ssi->work);
 	ssi->main_state = 0;
 	ssi->send_state = 0;
 	ssi->recv_state = 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hsi/controllers/omap_ssi_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hsi/controllers/omap_ssi_core.c
@@ -355,7 +355,7 @@
 
 	err = ida_simple_get(&platform_omap_ssi_ida, 0, 0, GFP_KERNEL);
 	if (err < 0)
-		goto out_err;
+		return err;
 	ssi->id = err;
 
 	ssi->owner = THIS_MODULE;
@@ -424,7 +424,7 @@
 	struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
 	int err;
 
-	err = pm_runtime_get_sync(ssi->device.parent);
+	err = pm_runtime_resume_and_get(ssi->device.parent);
 	if (err < 0) {
 		dev_err(&ssi->device, "runtime PM failed %d\n", err);
 		return err;
@@ -502,8 +502,10 @@
 	platform_set_drvdata(pd, ssi);
 
 	err = ssi_add_controller(ssi, pd);
-	if (err < 0)
+	if (err < 0) {
+		hsi_put_controller(ssi);
 		goto out1;
+	}
 
 	pm_runtime_enable(&pd->dev);
 
@@ -524,6 +526,7 @@
 		if (!childpdev) {
 			err = -ENODEV;
 			dev_err(&pd->dev, "failed to create ssi controller port\n");
+			of_node_put(child);
 			goto out3;
 		}
 	}
@@ -535,9 +538,9 @@
 	device_for_each_child(&pd->dev, NULL, ssi_remove_ports);
 out2:
 	ssi_remove_controller(ssi);
+	pm_runtime_disable(&pd->dev);
 out1:
 	platform_set_drvdata(pd, NULL);
-	pm_runtime_disable(&pd->dev);
 
 	return err;
 }
@@ -628,7 +631,13 @@
 	if (ret)
 		return ret;
 
-	return platform_driver_register(&ssi_port_pdriver);
+	ret = platform_driver_register(&ssi_port_pdriver);
+	if (ret) {
+		platform_driver_unregister(&ssi_pdriver);
+		return ret;
+	}
+
+	return 0;
 }
 module_init(ssi_init);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hsi/controllers/omap_ssi_port.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hsi/controllers/omap_ssi_port.c
@@ -230,10 +230,10 @@
 	if (msg->ttype == HSI_MSG_READ) {
 		err = dma_map_sg(&ssi->device, msg->sgt.sgl, msg->sgt.nents,
 							DMA_FROM_DEVICE);
-		if (err < 0) {
+		if (!err) {
 			dev_dbg(&ssi->device, "DMA map SG failed !\n");
 			pm_runtime_put_autosuspend(omap_port->pdev);
-			return err;
+			return -EIO;
 		}
 		csdp = SSI_DST_BURST_4x32_BIT | SSI_DST_MEMORY_PORT |
 			SSI_SRC_SINGLE_ACCESS0 | SSI_SRC_PERIPHERAL_PORT |
@@ -247,10 +247,10 @@
 	} else {
 		err = dma_map_sg(&ssi->device, msg->sgt.sgl, msg->sgt.nents,
 							DMA_TO_DEVICE);
-		if (err < 0) {
+		if (!err) {
 			dev_dbg(&ssi->device, "DMA map SG failed !\n");
 			pm_runtime_put_autosuspend(omap_port->pdev);
-			return err;
+			return -EIO;
 		}
 		csdp = SSI_SRC_BURST_4x32_BIT | SSI_SRC_MEMORY_PORT |
 			SSI_DST_SINGLE_ACCESS0 | SSI_DST_PERIPHERAL_PORT |
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hsi/hsi_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hsi/hsi_core.c
@@ -102,6 +102,7 @@
 	if (device_register(&cl->device) < 0) {
 		pr_err("hsi: failed to register client: %s\n", info->name);
 		put_device(&cl->device);
+		goto err;
 	}
 
 	return cl;
@@ -210,8 +211,6 @@
 	if (err)
 		goto err;
 
-	dev_set_name(&cl->device, "%s", name);
-
 	err = hsi_of_property_parse_mode(client, "hsi-mode", &mode);
 	if (err) {
 		err = hsi_of_property_parse_mode(client, "hsi-rx-mode",
@@ -293,6 +292,7 @@
 	cl->device.release = hsi_client_release;
 	cl->device.of_node = client;
 
+	dev_set_name(&cl->device, "%s", name);
 	if (device_register(&cl->device) < 0) {
 		pr_err("hsi: failed to register client: %s\n", name);
 		put_device(&cl->device);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hv/channel_mgmt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hv/channel_mgmt.c
@@ -493,13 +493,17 @@
 	 * Add the new device to the bus. This will kick off device-driver
 	 * binding which eventually invokes the device driver's AddDevice()
 	 * method.
+	 *
+	 * If vmbus_device_register() fails, the 'device_obj' is freed in
+	 * vmbus_device_release() as called by device_unregister() in the
+	 * error path of vmbus_device_register(). In the outside error
+	 * path, there's no need to free it.
 	 */
 	ret = vmbus_device_register(newchannel->device_obj);
 
 	if (ret != 0) {
 		pr_err("unable to add child device object (relid %d)\n",
 			newchannel->offermsg.child_relid);
-		kfree(newchannel->device_obj);
 		goto err_deq_chan;
 	}
 
@@ -763,13 +767,19 @@
 	free_cpumask_var(available_mask);
 }
 
+#define UNLOAD_DELAY_UNIT_MS	10		/* 10 milliseconds */
+#define UNLOAD_WAIT_MS		(100*1000)	/* 100 seconds */
+#define UNLOAD_WAIT_LOOPS	(UNLOAD_WAIT_MS/UNLOAD_DELAY_UNIT_MS)
+#define UNLOAD_MSG_MS		(5*1000)	/* Every 5 seconds */
+#define UNLOAD_MSG_LOOPS	(UNLOAD_MSG_MS/UNLOAD_DELAY_UNIT_MS)
+
 static void vmbus_wait_for_unload(void)
 {
 	int cpu;
 	void *page_addr;
 	struct hv_message *msg;
 	struct vmbus_channel_message_header *hdr;
-	u32 message_type;
+	u32 message_type, i;
 
 	/*
 	 * CHANNELMSG_UNLOAD_RESPONSE is always delivered to the CPU which was
@@ -779,16 +789,35 @@
 	 * functional and vmbus_unload_response() will complete
 	 * vmbus_connection.unload_event. If not, the last thing we can do is
 	 * read message pages for all CPUs directly.
+	 *
+	 * Wait up to 100 seconds since an Azure host must writeback any dirty
+	 * data in its disk cache before the VMbus UNLOAD request will
+	 * complete. This flushing has been empirically observed to take up
+	 * to 50 seconds in cases with a lot of dirty data, so allow additional
+	 * leeway and for inaccuracies in mdelay(). But eventually time out so
+	 * that the panic path can't get hung forever in case the response
+	 * message isn't seen.
 	 */
-	while (1) {
+	for (i = 1; i <= UNLOAD_WAIT_LOOPS; i++) {
 		if (completion_done(&vmbus_connection.unload_event))
-			break;
+			goto completed;
 
-		for_each_online_cpu(cpu) {
+		for_each_present_cpu(cpu) {
 			struct hv_per_cpu_context *hv_cpu
 				= per_cpu_ptr(hv_context.cpu_context, cpu);
 
+			/*
+			 * In a CoCo VM the synic_message_page is not allocated
+			 * in hv_synic_alloc(). Instead it is set/cleared in
+			 * hv_synic_enable_regs() and hv_synic_disable_regs()
+			 * such that it is set only when the CPU is online. If
+			 * not all present CPUs are online, the message page
+			 * might be NULL, so skip such CPUs.
+			 */
 			page_addr = hv_cpu->synic_message_page;
+			if (!page_addr)
+				continue;
+
 			msg = (struct hv_message *)page_addr
 				+ VMBUS_MESSAGE_SINT;
 
@@ -805,19 +834,31 @@
 			vmbus_signal_eom(msg, message_type);
 		}
 
-		mdelay(10);
+		/*
+		 * Give a notice periodically so someone watching the
+		 * serial output won't think it is completely hung.
+		 */
+		if (!(i % UNLOAD_MSG_LOOPS))
+			pr_notice("Waiting for VMBus UNLOAD to complete\n");
+
+		mdelay(UNLOAD_DELAY_UNIT_MS);
 	}
+	pr_err("Continuing even though VMBus UNLOAD did not complete\n");
 
+completed:
 	/*
 	 * We're crashing and already got the UNLOAD_RESPONSE, cleanup all
 	 * maybe-pending messages on all CPUs to be able to receive new
 	 * messages after we reconnect.
 	 */
-	for_each_online_cpu(cpu) {
+	for_each_present_cpu(cpu) {
 		struct hv_per_cpu_context *hv_cpu
 			= per_cpu_ptr(hv_context.cpu_context, cpu);
 
 		page_addr = hv_cpu->synic_message_page;
+		if (!page_addr)
+			continue;
+
 		msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT;
 		msg->header.message_type = HVMSG_NONE;
 	}
@@ -831,6 +872,11 @@
 	/*
 	 * This is a global event; just wakeup the waiting thread.
 	 * Once we successfully unload, we can cleanup the monitor state.
+	 *
+	 * NB.  A malicious or compromised Hyper-V could send a spurious
+	 * message of type CHANNELMSG_UNLOAD_RESPONSE, and trigger a call
+	 * of the complete() below.  Make sure that unload_event has been
+	 * initialized by the time this complete() is executed.
 	 */
 	complete(&vmbus_connection.unload_event);
 }
@@ -839,11 +885,14 @@
 {
 	struct vmbus_channel_message_header hdr;
 
+	if (xchg(&vmbus_connection.conn_state, DISCONNECTED) == DISCONNECTED)
+		return;
+
 	/* Pre-Win2012R2 hosts don't support reconnect */
 	if (vmbus_proto_version < VERSION_WIN8_1)
 		return;
 
-	init_completion(&vmbus_connection.unload_event);
+	reinit_completion(&vmbus_connection.unload_event);
 	memset(&hdr, 0, sizeof(struct vmbus_channel_message_header));
 	hdr.msgtype = CHANNELMSG_UNLOAD;
 	vmbus_post_msg(&hdr, sizeof(struct vmbus_channel_message_header),
@@ -1095,8 +1144,7 @@
 			vmbus_device_unregister(channel->device_obj);
 			put_device(dev);
 		}
-	}
-	if (channel->primary_channel != NULL) {
+	} else if (channel->primary_channel != NULL) {
 		/*
 		 * Sub-channel is being rescinded. Following is the channel
 		 * close sequence when initiated from the driveri (refer to
@@ -1351,6 +1399,8 @@
 	{ CHANNELMSG_19,			0, NULL },
 	{ CHANNELMSG_20,			0, NULL },
 	{ CHANNELMSG_TL_CONNECT_REQUEST,	0, NULL },
+	{ CHANNELMSG_22,			0, NULL },
+	{ CHANNELMSG_TL_CONNECT_RESULT,		0, NULL },
 };
 
 /*
@@ -1362,25 +1412,16 @@
 {
 	struct hv_message *msg = context;
 	struct vmbus_channel_message_header *hdr;
-	int size;
 
 	hdr = (struct vmbus_channel_message_header *)msg->u.payload;
-	size = msg->header.payload_size;
 
 	trace_vmbus_on_message(hdr);
 
-	if (hdr->msgtype >= CHANNELMSG_COUNT) {
-		pr_err("Received invalid channel message type %d size %d\n",
-			   hdr->msgtype, size);
-		print_hex_dump_bytes("", DUMP_PREFIX_NONE,
-				     (unsigned char *)msg->u.payload, size);
-		return;
-	}
-
-	if (channel_message_table[hdr->msgtype].message_handler)
-		channel_message_table[hdr->msgtype].message_handler(hdr);
-	else
-		pr_err("Unhandled channel message type %d\n", hdr->msgtype);
+	/*
+	 * vmbus_on_msg_dpc() makes sure the hdr->msgtype here can not go
+	 * out of bound and the message_handler pointer can not be NULL.
+	 */
+	channel_message_table[hdr->msgtype].message_handler(hdr);
 }
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hv/connection.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hv/connection.c
@@ -25,6 +25,8 @@
 
 struct vmbus_connection vmbus_connection = {
 	.conn_state		= DISCONNECTED,
+	.unload_event		= COMPLETION_INITIALIZER(
+				  vmbus_connection.unload_event),
 	.next_gpadl_handle	= ATOMIC_INIT(0xE1E10),
 
 	.ready_for_suspend_event= COMPLETION_INITIALIZER(
@@ -67,7 +69,6 @@
 int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo, u32 version)
 {
 	int ret = 0;
-	unsigned int cur_cpu;
 	struct vmbus_channel_initiate_contact *msg;
 	unsigned long flags;
 
@@ -100,24 +101,7 @@
 
 	msg->monitor_page1 = virt_to_phys(vmbus_connection.monitor_pages[0]);
 	msg->monitor_page2 = virt_to_phys(vmbus_connection.monitor_pages[1]);
-	/*
-	 * We want all channel messages to be delivered on CPU 0.
-	 * This has been the behavior pre-win8. This is not
-	 * perf issue and having all channel messages delivered on CPU 0
-	 * would be ok.
-	 * For post win8 hosts, we support receiving channel messagges on
-	 * all the CPUs. This is needed for kexec to work correctly where
-	 * the CPU attempting to connect may not be CPU 0.
-	 */
-	if (version >= VERSION_WIN8_1) {
-		cur_cpu = get_cpu();
-		msg->target_vcpu = hv_cpu_number_to_vp_number(cur_cpu);
-		vmbus_connection.connect_cpu = cur_cpu;
-		put_cpu();
-	} else {
-		msg->target_vcpu = 0;
-		vmbus_connection.connect_cpu = 0;
-	}
+	msg->target_vcpu = hv_cpu_number_to_vp_number(VMBUS_CONNECT_CPU);
 
 	/*
 	 * Add to list before we send the request since we may
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hv/hv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hv/hv.c
@@ -250,6 +250,17 @@
 	unsigned long flags;
 
 	/*
+	 * Hyper-V does not provide a way to change the connect CPU once
+	 * it is set; we must prevent the connect CPU from going offline
+	 * while the VM is running normally. But in the panic or kexec()
+	 * path where the vmbus is already disconnected, the CPU must be
+	 * allowed to shut down.
+	 */
+	if (cpu == VMBUS_CONNECT_CPU &&
+	    vmbus_connection.conn_state == CONNECTED)
+		return -EBUSY;
+
+	/*
 	 * Search for channels which are bound to the CPU we're about to
 	 * cleanup. In case we find one and vmbus is still connected we need to
 	 * fail, this will effectively prevent CPU offlining. There is no way
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hv/hv_balloon.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hv/hv_balloon.c
@@ -1213,10 +1213,7 @@
 	unsigned int i, j;
 	struct page *pg;
 
-	if (num_pages < alloc_unit)
-		return 0;
-
-	for (i = 0; (i * alloc_unit) < num_pages; i++) {
+	for (i = 0; i < num_pages / alloc_unit; i++) {
 		if (bl_resp->hdr.size + sizeof(union dm_mem_page_range) >
 			PAGE_SIZE)
 			return i * alloc_unit;
@@ -1254,7 +1251,7 @@
 
 	}
 
-	return num_pages;
+	return i * alloc_unit;
 }
 
 static void balloon_up(struct work_struct *dummy)
@@ -1269,9 +1266,6 @@
 	long avail_pages;
 	unsigned long floor;
 
-	/* The host balloons pages in 2M granularity. */
-	WARN_ON_ONCE(num_pages % PAGES_IN_2M != 0);
-
 	/*
 	 * We will attempt 2M allocations. However, if we fail to
 	 * allocate 2M chunks, we will go back to 4k allocations.
@@ -1281,14 +1275,13 @@
 	avail_pages = si_mem_available();
 	floor = compute_balloon_floor();
 
-	/* Refuse to balloon below the floor, keep the 2M granularity. */
+	/* Refuse to balloon below the floor. */
 	if (avail_pages < num_pages || avail_pages - num_pages < floor) {
-		pr_warn("Balloon request will be partially fulfilled. %s\n",
+		pr_info("Balloon request will be partially fulfilled. %s\n",
 			avail_pages < num_pages ? "Not enough memory." :
 			"Balloon floor reached.");
 
 		num_pages = avail_pages > floor ? (avail_pages - floor) : 0;
-		num_pages -= num_pages % PAGES_IN_2M;
 	}
 
 	while (!done) {
@@ -1557,7 +1550,7 @@
 			break;
 
 		default:
-			pr_warn("Unhandled message: type: %d\n", dm_hdr->type);
+			pr_warn_ratelimited("Unhandled message: type: %d\n", dm_hdr->type);
 
 		}
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hv/hv_kvp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hv/hv_kvp.c
@@ -749,6 +749,12 @@
 	 */
 	kvp_transaction.state = HVUTIL_DEVICE_INIT;
 
+	return 0;
+}
+
+int
+hv_kvp_init_transport(void)
+{
 	hvt = hvutil_transport_init(kvp_devname, CN_KVP_IDX, CN_KVP_VAL,
 				    kvp_on_msg, kvp_on_reset);
 	if (!hvt)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hv/hv_snapshot.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hv/hv_snapshot.c
@@ -368,6 +368,12 @@
 	 */
 	vss_transaction.state = HVUTIL_DEVICE_INIT;
 
+	return 0;
+}
+
+int
+hv_vss_init_transport(void)
+{
 	hvt = hvutil_transport_init(vss_devname, CN_VSS_IDX, CN_VSS_VAL,
 				    vss_on_msg, vss_on_reset);
 	if (!hvt) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hv/hv_util.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hv/hv_util.c
@@ -98,12 +98,14 @@
 static struct hv_util_service util_kvp = {
 	.util_cb = hv_kvp_onchannelcallback,
 	.util_init = hv_kvp_init,
+	.util_init_transport = hv_kvp_init_transport,
 	.util_deinit = hv_kvp_deinit,
 };
 
 static struct hv_util_service util_vss = {
 	.util_cb = hv_vss_onchannelcallback,
 	.util_init = hv_vss_init,
+	.util_init_transport = hv_vss_init_transport,
 	.util_deinit = hv_vss_deinit,
 };
 
@@ -283,10 +285,23 @@
 	struct ictimesync_ref_data *refdata;
 	u8 *time_txf_buf = util_timesynch.recv_buffer;
 
-	vmbus_recvpacket(channel, time_txf_buf,
-			 PAGE_SIZE, &recvlen, &requestid);
+	/*
+	 * Drain the ring buffer and use the last packet to update
+	 * host_ts
+	 */
+	while (1) {
+		int ret = vmbus_recvpacket(channel, time_txf_buf,
+					   HV_HYP_PAGE_SIZE, &recvlen,
+					   &requestid);
+		if (ret) {
+			pr_warn_once("TimeSync IC pkt recv failed (Err: %d)\n",
+				     ret);
+			break;
+		}
+
+		if (!recvlen)
+			break;
 
-	if (recvlen > 0) {
 		icmsghdrp = (struct icmsg_hdr *)&time_txf_buf[
 				sizeof(struct vmbuspipe_hdr)];
 
@@ -418,6 +433,13 @@
 	if (ret)
 		goto error;
 
+	if (srv->util_init_transport) {
+		ret = srv->util_init_transport();
+		if (ret) {
+			vmbus_close(dev->channel);
+			goto error;
+		}
+	}
 	return 0;
 
 error:
@@ -537,8 +559,8 @@
 	 */
 	hv_ptp_clock = ptp_clock_register(&ptp_hyperv_info, NULL);
 	if (IS_ERR_OR_NULL(hv_ptp_clock)) {
-		pr_err("cannot register PTP clock: %ld\n",
-		       PTR_ERR(hv_ptp_clock));
+		pr_err("cannot register PTP clock: %d\n",
+		       PTR_ERR_OR_ZERO(hv_ptp_clock));
 		hv_ptp_clock = NULL;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hv/hyperv_vmbus.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/hv/hyperv_vmbus.h
@@ -13,6 +13,7 @@
 #define _HYPERV_VMBUS_H
 
 #include <linux/list.h>
+#include <linux/bitops.h>
 #include <asm/sync_bitops.h>
 #include <asm/hyperv-tlfs.h>
 #include <linux/atomic.h>
@@ -212,12 +213,13 @@
 
 #define MAX_SIZE_CHANNEL_MESSAGE	HV_MESSAGE_PAYLOAD_BYTE_COUNT
 
-struct vmbus_connection {
-	/*
-	 * CPU on which the initial host contact was made.
-	 */
-	int connect_cpu;
+/*
+ * The CPU that Hyper-V will interrupt for VMBUS messages, such as
+ * CHANNELMSG_OFFERCHANNEL and CHANNELMSG_RESCIND_CHANNELOFFER.
+ */
+#define VMBUS_CONNECT_CPU	0
 
+struct vmbus_connection {
 	u32 msg_conn_id;
 
 	atomic_t offer_in_progress;
@@ -351,10 +353,12 @@
 void vmbus_on_msg_dpc(unsigned long data);
 
 int hv_kvp_init(struct hv_util_service *srv);
+int hv_kvp_init_transport(void);
 void hv_kvp_deinit(void);
 void hv_kvp_onchannelcallback(void *context);
 
 int hv_vss_init(struct hv_util_service *srv);
+int hv_vss_init_transport(void);
 void hv_vss_deinit(void);
 void hv_vss_onchannelcallback(void *context);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hv/ring_buffer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hv/ring_buffer.c
@@ -378,7 +378,16 @@
 static u32 hv_pkt_iter_avail(const struct hv_ring_buffer_info *rbi)
 {
 	u32 priv_read_loc = rbi->priv_read_index;
-	u32 write_loc = READ_ONCE(rbi->ring_buffer->write_index);
+	u32 write_loc;
+
+	/*
+	 * The Hyper-V host writes the packet data, then uses
+	 * store_release() to update the write_index.  Use load_acquire()
+	 * here to prevent loads of the packet data from being re-ordered
+	 * before the read of the write_index and potentially getting
+	 * stale data.
+	 */
+	write_loc = virt_load_acquire(&rbi->ring_buffer->write_index);
 
 	if (write_loc >= priv_read_loc)
 		return write_loc - priv_read_loc;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hv/vmbus_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hv/vmbus_drv.c
@@ -31,6 +31,7 @@
 #include <linux/kdebug.h>
 #include <linux/efi.h>
 #include <linux/random.h>
+#include <linux/kernel.h>
 #include <linux/syscore_ops.h>
 #include <clocksource/hyperv_timer.h>
 #include "hyperv_vmbus.h"
@@ -48,14 +49,35 @@
 
 static void *hv_panic_page;
 
+/*
+ * Boolean to control whether to report panic messages over Hyper-V.
+ *
+ * It can be set via /proc/sys/kernel/hyperv/record_panic_msg
+ */
+static int sysctl_record_panic_msg = 1;
+
+static int hyperv_report_reg(void)
+{
+	return !sysctl_record_panic_msg || !hv_panic_page;
+}
+
 static int hyperv_panic_event(struct notifier_block *nb, unsigned long val,
 			      void *args)
 {
 	struct pt_regs *regs;
 
-	regs = current_pt_regs();
+	vmbus_initiate_unload(true);
 
-	hyperv_report_panic(regs, val);
+	/*
+	 * Hyper-V should be notified only once about a panic.  If we will be
+	 * doing hyperv_report_panic_msg() later with kmsg data, don't do
+	 * the notification here.
+	 */
+	if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE
+	    && hyperv_report_reg()) {
+		regs = current_pt_regs();
+		hyperv_report_panic(regs, val, false);
+	}
 	return NOTIFY_DONE;
 }
 
@@ -65,7 +87,13 @@
 	struct die_args *die = (struct die_args *)args;
 	struct pt_regs *regs = die->regs;
 
-	hyperv_report_panic(regs, val);
+	/*
+	 * Hyper-V should be notified only once about a panic.  If we will be
+	 * doing hyperv_report_panic_msg() later with kmsg data, don't do
+	 * the notification here.
+	 */
+	if (hyperv_report_reg())
+		hyperv_report_panic(regs, val, true);
 	return NOTIFY_DONE;
 }
 
@@ -79,7 +107,7 @@
 static const char *fb_mmio_name = "fb_range";
 static struct resource *fb_mmio;
 static struct resource *hyperv_mmio;
-static DEFINE_SEMAPHORE(hyperv_mmio_lock);
+static DEFINE_MUTEX(hyperv_mmio_lock);
 
 static int vmbus_exists(void)
 {
@@ -950,6 +978,9 @@
 
 	return drv->resume(dev);
 }
+#else
+#define vmbus_suspend NULL
+#define vmbus_resume NULL
 #endif /* CONFIG_PM_SLEEP */
 
 /*
@@ -967,11 +998,22 @@
 }
 
 /*
- * Note: we must use SET_NOIRQ_SYSTEM_SLEEP_PM_OPS rather than
- * SET_SYSTEM_SLEEP_PM_OPS: see the comment before vmbus_bus_pm.
+ * Note: we must use the "noirq" ops: see the comment before vmbus_bus_pm.
+ *
+ * suspend_noirq/resume_noirq are set to NULL to support Suspend-to-Idle: we
+ * shouldn't suspend the vmbus devices upon Suspend-to-Idle, otherwise there
+ * is no way to wake up a Generation-2 VM.
+ *
+ * The other 4 ops are for hibernation.
  */
+
 static const struct dev_pm_ops vmbus_pm = {
-	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(vmbus_suspend, vmbus_resume)
+	.suspend_noirq	= NULL,
+	.resume_noirq	= NULL,
+	.freeze_noirq	= vmbus_suspend,
+	.thaw_noirq	= vmbus_resume,
+	.poweroff_noirq	= vmbus_suspend,
+	.restore_noirq	= vmbus_resume,
 };
 
 /* The one and only one */
@@ -1031,6 +1073,10 @@
 	}
 
 	entry = &channel_message_table[hdr->msgtype];
+
+	if (!entry->message_handler)
+		goto msg_handled;
+
 	if (entry->handler_type	== VMHT_BLOCKING) {
 		ctx = kmalloc(sizeof(*ctx), GFP_ATOMIC);
 		if (ctx == NULL)
@@ -1050,14 +1096,28 @@
 			/*
 			 * If we are handling the rescind message;
 			 * schedule the work on the global work queue.
+			 *
+			 * The OFFER message and the RESCIND message should
+			 * not be handled by the same serialized work queue,
+			 * because the OFFER handler may call vmbus_open(),
+			 * which tries to open the channel by sending an
+			 * OPEN_CHANNEL message to the host and waits for
+			 * the host's response; however, if the host has
+			 * rescinded the channel before it receives the
+			 * OPEN_CHANNEL message, the host just silently
+			 * ignores the OPEN_CHANNEL message; as a result,
+			 * the guest's OFFER handler hangs for ever, if we
+			 * handle the RESCIND message in the same serialized
+			 * work queue: the RESCIND handler can not start to
+			 * run before the OFFER handler finishes.
 			 */
-			schedule_work_on(vmbus_connection.connect_cpu,
+			schedule_work_on(VMBUS_CONNECT_CPU,
 					 &ctx->work);
 			break;
 
 		case CHANNELMSG_OFFERCHANNEL:
 			atomic_inc(&vmbus_connection.offer_in_progress);
-			queue_work_on(vmbus_connection.connect_cpu,
+			queue_work_on(VMBUS_CONNECT_CPU,
 				      vmbus_connection.work_queue,
 				      &ctx->work);
 			break;
@@ -1104,7 +1164,7 @@
 
 	INIT_WORK(&ctx->work, vmbus_onmessage_work);
 
-	queue_work_on(vmbus_connection.connect_cpu,
+	queue_work_on(VMBUS_CONNECT_CPU,
 		      vmbus_connection.work_queue,
 		      &ctx->work);
 }
@@ -1243,17 +1303,10 @@
 			tasklet_schedule(&hv_cpu->msg_dpc);
 	}
 
-	add_interrupt_randomness(HYPERVISOR_CALLBACK_VECTOR, 0);
+	add_interrupt_randomness(HYPERVISOR_CALLBACK_VECTOR);
 }
 
 /*
- * Boolean to control whether to report panic messages over Hyper-V.
- *
- * It can be set via /proc/sys/kernel/hyperv/record_panic_msg
- */
-static int sysctl_record_panic_msg = 1;
-
-/*
  * Callback from kmsg_dump. Grab as much as possible from the end of the kmsg
  * buffer and call into Hyper-V to transfer the data.
  */
@@ -1380,19 +1433,29 @@
 			hv_panic_page = (void *)get_zeroed_page(GFP_KERNEL);
 			if (hv_panic_page) {
 				ret = kmsg_dump_register(&hv_kmsg_dumper);
-				if (ret)
+				if (ret) {
 					pr_err("Hyper-V: kmsg dump register "
 						"error 0x%x\n", ret);
+					hv_free_hyperv_page(
+					    (unsigned long)hv_panic_page);
+					hv_panic_page = NULL;
+				}
 			} else
 				pr_err("Hyper-V: panic message page memory "
 					"allocation failed");
 		}
 
 		register_die_notifier(&hyperv_die_block);
-		atomic_notifier_chain_register(&panic_notifier_list,
-					       &hyperv_panic_block);
 	}
 
+	/*
+	 * Always register the panic notifier because we need to unload
+	 * the VMbus channel connection to prevent any VMbus
+	 * activity after the VM panics.
+	 */
+	atomic_notifier_chain_register(&panic_notifier_list,
+			       &hyperv_panic_block);
+
 	vmbus_request_offers();
 
 	return 0;
@@ -1406,7 +1469,6 @@
 	hv_remove_vmbus_irq();
 
 	bus_unregister(&hv_bus);
-	free_page((unsigned long)hv_panic_page);
 	unregister_sysctl_table(hv_ctl_table_hdr);
 	hv_ctl_table_hdr = NULL;
 	return ret;
@@ -1725,8 +1787,10 @@
 	kobj->kset = dev->channels_kset;
 	ret = kobject_init_and_add(kobj, &vmbus_chan_ktype, NULL,
 				   "%u", relid);
-	if (ret)
+	if (ret) {
+		kobject_put(kobj);
 		return ret;
+	}
 
 	ret = sysfs_create_group(kobj, &vmbus_chan_group);
 
@@ -1735,6 +1799,7 @@
 		 * The calling functions' error handling paths will cleanup the
 		 * empty channel directory.
 		 */
+		kobject_put(kobj);
 		dev_err(device, "Unable to set up channel sysfs files\n");
 		return ret;
 	}
@@ -1798,6 +1863,7 @@
 	ret = device_register(&child_device_obj->device);
 	if (ret) {
 		pr_err("Unable to register child device\n");
+		put_device(&child_device_obj->device);
 		return ret;
 	}
 
@@ -1842,6 +1908,7 @@
 	 */
 	device_unregister(&device_obj->device);
 }
+EXPORT_SYMBOL_GPL(vmbus_device_unregister);
 
 
 /*
@@ -2010,12 +2077,12 @@
 			bool fb_overlap_ok)
 {
 	struct resource *iter, *shadow;
-	resource_size_t range_min, range_max, start;
+	resource_size_t range_min, range_max, start, end;
 	const char *dev_n = dev_name(&device_obj->device);
 	int retval;
 
 	retval = -ENXIO;
-	down(&hyperv_mmio_lock);
+	mutex_lock(&hyperv_mmio_lock);
 
 	/*
 	 * If overlaps with frame buffers are allowed, then first attempt to
@@ -2045,6 +2112,14 @@
 		range_max = iter->end;
 		start = (range_min + align - 1) & ~(align - 1);
 		for (; start + size - 1 <= range_max; start += align) {
+			end = start + size - 1;
+
+			/* Skip the whole fb_mmio region if not fb_overlap_ok */
+			if (!fb_overlap_ok && fb_mmio &&
+			    (((start >= fb_mmio->start) && (start <= fb_mmio->end)) ||
+			     ((end >= fb_mmio->start) && (end <= fb_mmio->end))))
+				continue;
+
 			shadow = __request_region(iter, start, size, NULL,
 						  IORESOURCE_BUSY);
 			if (!shadow)
@@ -2062,7 +2137,7 @@
 	}
 
 exit:
-	up(&hyperv_mmio_lock);
+	mutex_unlock(&hyperv_mmio_lock);
 	return retval;
 }
 EXPORT_SYMBOL_GPL(vmbus_allocate_mmio);
@@ -2079,15 +2154,28 @@
 {
 	struct resource *iter;
 
-	down(&hyperv_mmio_lock);
+	mutex_lock(&hyperv_mmio_lock);
+
+	/*
+	 * If all bytes of the MMIO range to be released are within the
+	 * special case fb_mmio shadow region, skip releasing the shadow
+	 * region since no corresponding __request_region() was done
+	 * in vmbus_allocate_mmio().
+	 */
+	if (fb_mmio && start >= fb_mmio->start &&
+	    (start + size - 1 <= fb_mmio->end))
+		goto skip_shadow_release;
+
 	for (iter = hyperv_mmio; iter; iter = iter->sibling) {
 		if ((iter->start >= start + size) || (iter->end <= start))
 			continue;
 
 		__release_region(iter, start, size);
 	}
+
+skip_shadow_release:
 	release_mem_region(start, size);
-	up(&hyperv_mmio_lock);
+	mutex_unlock(&hyperv_mmio_lock);
 
 }
 EXPORT_SYMBOL_GPL(vmbus_free_mmio);
@@ -2169,7 +2257,10 @@
 	if (atomic_read(&vmbus_connection.nr_chan_close_on_suspend) > 0)
 		wait_for_completion(&vmbus_connection.ready_for_suspend_event);
 
-	WARN_ON(atomic_read(&vmbus_connection.nr_chan_fixup_on_resume) != 0);
+	if (atomic_read(&vmbus_connection.nr_chan_fixup_on_resume) != 0) {
+		pr_err("Can not suspend due to a previous failed resuming\n");
+		return -EBUSY;
+	}
 
 	mutex_lock(&vmbus_connection.channel_mutex);
 
@@ -2202,8 +2293,6 @@
 
 	vmbus_initiate_unload(false);
 
-	vmbus_connection.conn_state = DISCONNECTED;
-
 	/* Reset the event for the next resume. */
 	reinit_completion(&vmbus_connection.ready_for_resume_event);
 
@@ -2245,13 +2334,18 @@
 
 	vmbus_request_offers();
 
-	wait_for_completion(&vmbus_connection.ready_for_resume_event);
+	if (wait_for_completion_timeout(
+		&vmbus_connection.ready_for_resume_event, 10 * HZ) == 0)
+		pr_err("Some vmbus device is missing after suspending?\n");
 
 	/* Reset the event for the next suspend. */
 	reinit_completion(&vmbus_connection.ready_for_suspend_event);
 
 	return 0;
 }
+#else
+#define vmbus_bus_suspend NULL
+#define vmbus_bus_resume NULL
 #endif /* CONFIG_PM_SLEEP */
 
 static const struct acpi_device_id vmbus_acpi_device_ids[] = {
@@ -2262,16 +2356,24 @@
 MODULE_DEVICE_TABLE(acpi, vmbus_acpi_device_ids);
 
 /*
- * Note: we must use SET_NOIRQ_SYSTEM_SLEEP_PM_OPS rather than
- * SET_SYSTEM_SLEEP_PM_OPS, otherwise NIC SR-IOV can not work, because the
- * "pci_dev_pm_ops" uses the "noirq" callbacks: in the resume path, the
- * pci "noirq" restore callback runs before "non-noirq" callbacks (see
+ * Note: we must use the "no_irq" ops, otherwise hibernation can not work with
+ * PCI device assignment, because "pci_dev_pm_ops" uses the "noirq" ops: in
+ * the resume path, the pci "noirq" restore op runs before "non-noirq" op (see
  * resume_target_kernel() -> dpm_resume_start(), and hibernation_restore() ->
  * dpm_resume_end()). This means vmbus_bus_resume() and the pci-hyperv's
- * resume callback must also run via the "noirq" callbacks.
+ * resume callback must also run via the "noirq" ops.
+ *
+ * Set suspend_noirq/resume_noirq to NULL for Suspend-to-Idle: see the comment
+ * earlier in this file before vmbus_pm.
  */
+
 static const struct dev_pm_ops vmbus_bus_pm = {
-	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(vmbus_bus_suspend, vmbus_bus_resume)
+	.suspend_noirq	= NULL,
+	.resume_noirq	= NULL,
+	.freeze_noirq	= vmbus_bus_suspend,
+	.thaw_noirq	= vmbus_bus_resume,
+	.poweroff_noirq	= vmbus_bus_suspend,
+	.restore_noirq	= vmbus_bus_resume
 };
 
 static struct acpi_driver vmbus_acpi_driver = {
@@ -2288,7 +2390,6 @@
 {
 	hv_stimer_global_cleanup();
 	vmbus_initiate_unload(false);
-	vmbus_connection.conn_state = DISCONNECTED;
 	/* Make sure conn_state is set as hv_synic_cleanup checks for it */
 	mb();
 	cpuhp_remove_state(hyperv_cpuhp_online);
@@ -2305,10 +2406,9 @@
 	 * doing the cleanup for current CPU only. This should be sufficient
 	 * for kdump.
 	 */
-	vmbus_connection.conn_state = DISCONNECTED;
 	cpu = smp_processor_id();
 	hv_stimer_cleanup(cpu);
-	hv_synic_cleanup(cpu);
+	hv_synic_disable_regs(cpu);
 	hyperv_cleanup();
 };
 
@@ -2416,10 +2516,15 @@
 	if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) {
 		kmsg_dump_unregister(&hv_kmsg_dumper);
 		unregister_die_notifier(&hyperv_die_block);
-		atomic_notifier_chain_unregister(&panic_notifier_list,
-						 &hyperv_panic_block);
 	}
 
+	/*
+	 * The panic notifier is always registered, hence we should
+	 * also unconditionally unregister it here as well.
+	 */
+	atomic_notifier_chain_unregister(&panic_notifier_list,
+					 &hyperv_panic_block);
+
 	free_page((unsigned long)hv_panic_page);
 	unregister_sysctl_table(hv_ctl_table_hdr);
 	hv_ctl_table_hdr = NULL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/Kconfig
@@ -802,7 +802,7 @@
 
 config SENSORS_LTQ_CPUTEMP
 	bool "Lantiq cpu temperature sensor driver"
-	depends on LANTIQ
+	depends on SOC_XWAY
 	help
 	  If you say yes here you get support for the temperature
 	  sensor inside your CPU.
@@ -1132,10 +1132,11 @@
 	help
 	  If you say yes here you get support for National Semiconductor LM90,
 	  LM86, LM89 and LM99, Analog Devices ADM1032, ADT7461, and ADT7461A,
-	  Maxim MAX6646, MAX6647, MAX6648, MAX6649, MAX6657, MAX6658, MAX6659,
-	  MAX6680, MAX6681, MAX6692, MAX6695, MAX6696, ON Semiconductor NCT1008,
-	  Winbond/Nuvoton W83L771W/G/AWG/ASG, Philips SA56004, GMT G781, and
-	  Texas Instruments TMP451 sensor chips.
+	  Maxim MAX6646, MAX6647, MAX6648, MAX6649, MAX6654, MAX6657, MAX6658,
+	  MAX6659, MAX6680, MAX6681, MAX6692, MAX6695, MAX6696,
+	  ON Semiconductor NCT1008, Winbond/Nuvoton W83L771W/G/AWG/ASG,
+	  Philips SA56004, GMT G781, Texas Instruments TMP451 and TMP461
+	  sensor chips.
 
 	  This driver can also be built as a module. If so, the module
 	  will be called lm90.
@@ -1922,6 +1923,17 @@
 	  If you say yes here you get support for the temperature
 	  and power sensors for APM X-Gene SoC.
 
+config SENSORS_AHC1EC0_HWMON
+	tristate "Advantech AHC1EC0 Hardware Monitor Function"
+	depends on MFD_AHC1EC0
+	depends on UBUNTU_ODM_DRIVERS
+	help
+	  This driver provide support for the hardware monitoring functionality
+	  for Advantech AHC1EC0 embedded controller on the board.
+
+	  This driver provides the sysfs attributes for applications to monitor
+	  the system status, including system temperatures, voltages, current.
+
 if ACPI
 
 comment "ACPI drivers"
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/Makefile
@@ -44,6 +44,7 @@
 obj-$(CONFIG_SENSORS_ADT7462)	+= adt7462.o
 obj-$(CONFIG_SENSORS_ADT7470)	+= adt7470.o
 obj-$(CONFIG_SENSORS_ADT7475)	+= adt7475.o
+obj-$(CONFIG_SENSORS_AHC1EC0_HWMON)	+= ahc1ec0-hwmon.o
 obj-$(CONFIG_SENSORS_APPLESMC)	+= applesmc.o
 obj-$(CONFIG_SENSORS_ARM_SCMI)	+= scmi-hwmon.o
 obj-$(CONFIG_SENSORS_ARM_SCPI)	+= scpi-hwmon.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/acpi_power_meter.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/acpi_power_meter.c
@@ -32,6 +32,7 @@
 #define POWER_METER_CAN_NOTIFY	(1 << 3)
 #define POWER_METER_IS_BATTERY	(1 << 8)
 #define UNKNOWN_HYSTERESIS	0xFFFFFFFF
+#define UNKNOWN_POWER		0xFFFFFFFF
 
 #define METER_NOTIFY_CONFIG	0x80
 #define METER_NOTIFY_TRIP	0x81
@@ -343,6 +344,9 @@
 	update_meter(resource);
 	mutex_unlock(&resource->lock);
 
+	if (resource->power == UNKNOWN_POWER)
+		return -ENODATA;
+
 	return sprintf(buf, "%llu\n", resource->power * 1000);
 }
 
@@ -883,7 +887,7 @@
 
 	res = setup_attrs(resource);
 	if (res)
-		goto exit_free;
+		goto exit_free_capability;
 
 	resource->hwmon_dev = hwmon_device_register(&device->dev);
 	if (IS_ERR(resource->hwmon_dev)) {
@@ -896,6 +900,8 @@
 
 exit_remove:
 	remove_attrs(resource);
+exit_free_capability:
+	free_capabilities(resource);
 exit_free:
 	kfree(resource);
 exit:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/ad7314.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/ad7314.c
@@ -22,11 +22,13 @@
  */
 #define AD7314_TEMP_MASK		0x7FE0
 #define AD7314_TEMP_SHIFT		5
+#define AD7314_LEADING_ZEROS_MASK	BIT(15)
 
 /*
  * ADT7301 and ADT7302 temperature masks
  */
 #define ADT7301_TEMP_MASK		0x3FFF
+#define ADT7301_LEADING_ZEROS_MASK	(BIT(15) | BIT(14))
 
 enum ad7314_variant {
 	adt7301,
@@ -65,12 +67,20 @@
 		return ret;
 	switch (spi_get_device_id(chip->spi_dev)->driver_data) {
 	case ad7314:
+		if (ret & AD7314_LEADING_ZEROS_MASK) {
+			/* Invalid read-out, leading zero part is missing */
+			return -EIO;
+		}
 		data = (ret & AD7314_TEMP_MASK) >> AD7314_TEMP_SHIFT;
 		data = sign_extend32(data, 9);
 
 		return sprintf(buf, "%d\n", 250 * data);
 	case adt7301:
 	case adt7302:
+		if (ret & ADT7301_LEADING_ZEROS_MASK) {
+			/* Invalid read-out, leading zero part is missing */
+			return -EIO;
+		}
 		/*
 		 * Documented as a 13 bit twos complement register
 		 * with a sign bit - which is a 14 bit 2's complement
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/adc128d818.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/adc128d818.c
@@ -176,7 +176,7 @@
 
 	mutex_lock(&data->update_lock);
 	/* 10 mV LSB on limit registers */
-	regval = clamp_val(DIV_ROUND_CLOSEST(val, 10), 0, 255);
+	regval = DIV_ROUND_CLOSEST(clamp_val(val, 0, 2550), 10);
 	data->in[index][nr] = regval << 4;
 	reg = index == 1 ? ADC128_REG_IN_MIN(nr) : ADC128_REG_IN_MAX(nr);
 	i2c_smbus_write_byte_data(data->client, reg, regval);
@@ -214,7 +214,7 @@
 		return err;
 
 	mutex_lock(&data->update_lock);
-	regval = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -128, 127);
+	regval = DIV_ROUND_CLOSEST(clamp_val(val, -128000, 127000), 1000);
 	data->temp[index] = regval << 1;
 	i2c_smbus_write_byte_data(data->client,
 				  index == 1 ? ADC128_REG_TEMP_MAX
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/adt7462.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/adt7462.c
@@ -413,7 +413,7 @@
 			return 0x95;
 		break;
 	}
-	return -ENODEV;
+	return 0;
 }
 
 /* Provide labels for sysfs */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/adt7470.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/adt7470.c
@@ -20,6 +20,7 @@
 #include <linux/kthread.h>
 #include <linux/slab.h>
 #include <linux/util_macros.h>
+#include <linux/sched.h>
 
 /* Addresses to scan */
 static const unsigned short normal_i2c[] = { 0x2C, 0x2E, 0x2F, I2C_CLIENT_END };
@@ -260,11 +261,10 @@
 		adt7470_read_temperatures(client, data);
 		mutex_unlock(&data->lock);
 
-		set_current_state(TASK_INTERRUPTIBLE);
 		if (kthread_should_stop())
 			break;
 
-		schedule_timeout(msecs_to_jiffies(data->auto_update_interval));
+		schedule_timeout_interruptible(msecs_to_jiffies(data->auto_update_interval));
 	}
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/adt7475.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/adt7475.c
@@ -294,9 +294,10 @@
 	long reg;
 
 	if (bypass_attn & (1 << channel))
-		reg = (volt * 1024) / 2250;
+		reg = DIV_ROUND_CLOSEST(volt * 1024, 2250);
 	else
-		reg = (volt * r[1] * 1024) / ((r[0] + r[1]) * 2250);
+		reg = DIV_ROUND_CLOSEST(volt * r[1] * 1024,
+					(r[0] + r[1]) * 2250);
 	return clamp_val(reg, 0, 1023) & (0xff << 2);
 }
 
@@ -483,10 +484,10 @@
 		val = (temp - val) / 1000;
 
 		if (sattr->index != 1) {
-			data->temp[HYSTERSIS][sattr->index] &= 0xF0;
+			data->temp[HYSTERSIS][sattr->index] &= 0x0F;
 			data->temp[HYSTERSIS][sattr->index] |= (val & 0xF) << 4;
 		} else {
-			data->temp[HYSTERSIS][sattr->index] &= 0x0F;
+			data->temp[HYSTERSIS][sattr->index] &= 0xF0;
 			data->temp[HYSTERSIS][sattr->index] |= (val & 0xF);
 		}
 
@@ -551,11 +552,11 @@
 		val = data->enh_acoustics[0] & 0xf;
 		break;
 	case 1:
-		val = (data->enh_acoustics[1] >> 4) & 0xf;
+		val = data->enh_acoustics[1] & 0xf;
 		break;
 	case 2:
 	default:
-		val = data->enh_acoustics[1] & 0xf;
+		val = (data->enh_acoustics[1] >> 4) & 0xf;
 		break;
 	}
 
@@ -1680,7 +1681,7 @@
 		data->pwm[CONTROL][index] &= ~0xE0;
 		data->pwm[CONTROL][index] |= (7 << 5);
 
-		i2c_smbus_write_byte_data(client, PWM_CONFIG_REG(index),
+		i2c_smbus_write_byte_data(client, PWM_REG(index),
 					  data->pwm[INPUT][index]);
 
 		i2c_smbus_write_byte_data(client, PWM_CONFIG_REG(index),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/ahc1ec0-hwmon.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/ahc1ec0-hwmon.c
@@ -0,0 +1,660 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * HWMON Driver for Advantech Embedded Controller chip AHC1EC0
+ *
+ * Copyright 2020, Advantech IIoT Group
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/hwmon.h>
+#include <linux/mfd/ahc1ec0.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+struct ec_hwmon_attrs {
+	const char		*name;
+	umode_t			mode;
+	int (*read)(struct device *dev, long *val);
+};
+
+struct adv_hwmon_profile {
+	int offset;
+	unsigned long resolution, resolution_vin, resolution_sys, resolution_curr, resolution_power;
+	unsigned long r1, r1_vin, r1_sys, r1_curr, r1_power;
+	unsigned long r2, r2_vin, r2_sys, r2_curr, r2_power;
+	int hwmon_in_list_cnt;
+	int temp_list_cnt;
+	int *hwmon_in_list;
+	int *temp_list;
+};
+
+struct ec_hwmon_data {
+	struct device *dev;
+	struct device *hwmon_dev;
+	struct adv_ec_platform_data *adv_ec_data;
+	unsigned long temperature[3];
+	unsigned long ec_current[5];
+	unsigned long power[5];
+	unsigned long voltage[7];
+
+	struct ec_hw_pin_table pin_tbl;
+	struct ec_smbuso_em0 ec_smboem0;
+	struct adv_hwmon_profile *profile;
+};
+
+static int get_ec_in_vbat_input(struct device *dev, long *val);
+static int get_ec_in_v5_input(struct device *dev, long *val);
+static int get_ec_in_v12_input(struct device *dev, long *val);
+static int get_ec_in_vcore_input(struct device *dev, long *val);
+static int get_ec_current1_input(struct device *dev, long *val);
+static int get_ec_cpu_temp(struct device *dev, long *val);
+static int get_ec_sys_temp(struct device *dev, long *val);
+
+const struct ec_hwmon_attrs ec_hwmon_in_attr_template[] = {
+	{"VBAT",	0444, get_ec_in_vbat_input},	// in1
+	{"5VSB",	0444, get_ec_in_v5_input},	// in2
+	{"Vin",		0444, get_ec_in_v12_input},	// in3 (== in8)
+	{"VCORE",	0444, get_ec_in_vcore_input},	// in4
+	{"Vin1",	0444, NULL},	// in5
+	{"Vin2",	0444, NULL},	// in6
+	{"System Voltage", 0444, NULL},	// in7
+	{"Current",	0444, get_ec_current1_input},
+};
+
+const struct ec_hwmon_attrs ec_temp_attrs_template[] = {
+	{"CPU Temp",	0444, get_ec_cpu_temp},
+	{"System Temp",	0444, get_ec_sys_temp},
+};
+
+enum ec_hwmon_in_type {
+	EC_HWMON_IN_VBAT,
+	EC_HWMON_IN_5VSB,
+	EC_HWMON_IN_12V,
+	EC_HWMON_IN_VCORE,
+	EC_HWMON_IN_VIN1,
+	EC_HWMON_IN_VIN2,
+	EC_HWMON_IN_SYS_VOL,
+	EC_HWMON_IN_CURRENT,
+};
+
+enum ec_temp_type {
+	EC_TEMP_CPU,
+	EC_TEMP_SYS,
+};
+
+static int hwmon_in_list_0[] = {
+	EC_HWMON_IN_VBAT,
+	EC_HWMON_IN_5VSB,
+	EC_HWMON_IN_12V,
+	EC_HWMON_IN_VCORE,
+	EC_HWMON_IN_CURRENT,
+};
+
+static int hwmon_in_list_1[] = {
+	EC_HWMON_IN_VBAT,
+	EC_HWMON_IN_5VSB,
+	EC_HWMON_IN_12V,
+	EC_HWMON_IN_VCORE,
+};
+
+static int temp_list_0[] = {
+	EC_TEMP_CPU,
+};
+
+static int temp_list_1[] = {
+	EC_TEMP_CPU,
+	EC_TEMP_SYS,
+};
+
+static struct adv_hwmon_profile advec_profile[] = {
+	/*
+	 * TPC-8100TR, TPC-651T-E3AE, TPC-1251T-E3AE, TPC-1551T-E3AE,
+	 * TPC-1751T-E3AE, TPC-1051WP-E3AE, TPC-1551WP-E3AE, TPC-1581WP-433AE,
+	 * TPC-1782H-433AE, UNO-1483G-434AE, UNO-2483G-434AE, UNO-3483G-374AE,
+	 * UNO-2473G, UNO-2484G-6???AE, UNO-2484G-7???AE, UNO-3283G-674AE,
+	 * UNO-3285G-674AE
+	 * [0] AHC1EC0_HWMON_PRO_TEMPLATE
+	 */
+	{
+		.resolution = 2929,
+		.r1 = 1912,
+		.r2 = 1000,
+		.offset = 0,
+		.hwmon_in_list_cnt = ARRAY_SIZE(hwmon_in_list_0),
+		.temp_list_cnt = ARRAY_SIZE(temp_list_0),
+		.hwmon_in_list = hwmon_in_list_0,
+		.temp_list = temp_list_0,
+	},
+	/*
+	 * TPC-B500-6??AE, TPC-5???T-6??AE, TPC-5???W-6??AE, TPC-B200-???AE,
+	 * TPC-2???T-???AE, TPC-2???W-???AE
+	 * [1] AHC1EC0_HWMON_PRO_TPC5XXX
+	 */
+	{
+		.resolution = 2929,
+		.r1 = 1912,
+		.r2 = 1000,
+		.offset = 0,
+		.hwmon_in_list_cnt = ARRAY_SIZE(hwmon_in_list_1),
+		.temp_list_cnt = ARRAY_SIZE(temp_list_0),
+		.hwmon_in_list = hwmon_in_list_1,
+		.temp_list = temp_list_0,
+	},
+	/* PR/VR4
+	 * [2] AHC1EC0_HWMON_PRO_PRVR4
+	 */
+	{
+		.resolution = 2929,
+		.r1 = 1912,
+		.r2 = 1000,
+		.offset = 0,
+		.hwmon_in_list_cnt = ARRAY_SIZE(hwmon_in_list_1),
+		.temp_list_cnt = ARRAY_SIZE(temp_list_1),
+		.hwmon_in_list = hwmon_in_list_1,
+		.temp_list = temp_list_1,
+	},
+	/* UNO-2271G-E22AE/E23AE/E022AE/E023AE,UNO-420
+	 * [3] AHC1EC0_HWMON_PRO_UNO2271G
+	 */
+	{
+		.resolution = 2929,
+		.r1 = 1912,
+		.r2 = 1000,
+		.offset = 0,
+		.hwmon_in_list_cnt = ARRAY_SIZE(hwmon_in_list_1),
+		.temp_list_cnt = ARRAY_SIZE(temp_list_0),
+		.hwmon_in_list = hwmon_in_list_1,
+		.temp_list = temp_list_0,
+	},
+};
+
+static void adv_ec_init_hwmon_profile(u32 profile, struct ec_hwmon_data *lmsensor_data)
+{
+	int i;
+	struct ec_hw_pin_table *ptbl = &lmsensor_data->pin_tbl;
+	struct adv_ec_platform_data *adv_ec_data = lmsensor_data->adv_ec_data;
+	struct ec_dynamic_table *dym_tbl = adv_ec_data->dym_tbl;
+
+	if (profile >= ARRAY_SIZE(advec_profile))
+		return;
+
+	lmsensor_data->profile = &advec_profile[profile];
+
+	for (i = 0; i < EC_MAX_TBL_NUM ; i++) {
+		switch (dym_tbl[i].device_id) {
+		case EC_DID_CMOSBAT:
+			ptbl->vbat[0] = dym_tbl[i].hw_pin_num;
+			ptbl->vbat[1] = 1;
+			break;
+		case EC_DID_CMOSBAT_X2:
+			ptbl->vbat[0] = dym_tbl[i].hw_pin_num;
+			ptbl->vbat[1] = 2;
+			break;
+		case EC_DID_CMOSBAT_X10:
+			ptbl->vbat[0] = dym_tbl[i].hw_pin_num;
+			ptbl->vbat[1] = 10;
+			break;
+		case EC_DID_5VS0:
+		case EC_DID_5VS5:
+			ptbl->v5[0] = dym_tbl[i].hw_pin_num;
+			ptbl->v5[1] = 1;
+			break;
+		case EC_DID_5VS0_X2:
+		case EC_DID_5VS5_X2:
+			ptbl->v5[0] = dym_tbl[i].hw_pin_num;
+			ptbl->v5[1] = 2;
+			break;
+		case EC_DID_5VS0_X10:
+		case EC_DID_5VS5_X10:
+			ptbl->v5[0] = dym_tbl[i].hw_pin_num;
+			ptbl->v5[1] = 10;
+			break;
+		case EC_DID_12VS0:
+			ptbl->v12[0] = dym_tbl[i].hw_pin_num;
+			ptbl->v12[1] = 1;
+			break;
+		case EC_DID_12VS0_X2:
+			ptbl->v12[0] = dym_tbl[i].hw_pin_num;
+			ptbl->v12[1] = 2;
+			break;
+		case EC_DID_12VS0_X10:
+			ptbl->v12[0] = dym_tbl[i].hw_pin_num;
+			ptbl->v12[1] = 10;
+			break;
+		case EC_DID_VCOREA:
+		case EC_DID_VCOREB:
+			ptbl->vcore[0] = dym_tbl[i].hw_pin_num;
+			ptbl->vcore[1] = 1;
+			break;
+		case EC_DID_VCOREA_X2:
+		case EC_DID_VCOREB_X2:
+			ptbl->vcore[0] = dym_tbl[i].hw_pin_num;
+			ptbl->vcore[1] = 2;
+			break;
+		case EC_DID_VCOREA_X10:
+		case EC_DID_VCOREB_X10:
+			ptbl->vcore[0] = dym_tbl[i].hw_pin_num;
+			ptbl->vcore[1] = 10;
+			break;
+		case EC_DID_DC:
+			ptbl->vdc[0] = dym_tbl[i].hw_pin_num;
+			ptbl->vdc[1] = 1;
+			break;
+		case EC_DID_DC_X2:
+			ptbl->vdc[0] = dym_tbl[i].hw_pin_num;
+			ptbl->vdc[1] = 2;
+			break;
+		case EC_DID_DC_X10:
+			ptbl->vdc[0] = dym_tbl[i].hw_pin_num;
+			ptbl->vdc[1] = 10;
+			break;
+		case EC_DID_CURRENT:
+			ptbl->ec_current[0] = dym_tbl[i].hw_pin_num;
+			ptbl->ec_current[1] = 1;
+			break;
+		case EC_DID_SMBOEM0:
+			lmsensor_data->ec_smboem0.hw_pin_num = dym_tbl[i].hw_pin_num;
+			break;
+		default:
+			break;
+		}
+	}
+}
+
+static int get_ec_in_vbat_input(struct device *dev, long *val)
+{
+	unsigned int temp = 0;
+	unsigned long voltage = 0;
+	struct ec_hwmon_data *lmsensor_data = dev_get_drvdata(dev);
+
+	struct ec_hw_pin_table *ptbl = &lmsensor_data->pin_tbl;
+	struct adv_hwmon_profile *profile = lmsensor_data->profile;
+	struct adv_ec_platform_data *adv_ec_data = lmsensor_data->adv_ec_data;
+
+	temp = read_ad_value(adv_ec_data, ptbl->vbat[0], ptbl->vbat[1]);
+
+	if (profile->r2 != 0)
+		voltage = temp * (profile->r1 + profile->r2) / profile->r2;
+
+	if (profile->resolution != 0)
+		voltage =  temp * profile->resolution / 1000 / 1000;
+
+	if (profile->offset != 0)
+		voltage += (int)profile->offset * 100;
+
+	lmsensor_data->voltage[0] = 10 * voltage;
+
+	*val = lmsensor_data->voltage[0];
+	return 0;
+}
+
+static int get_ec_in_v5_input(struct device *dev, long *val)
+{
+	unsigned int temp;
+	unsigned long voltage = 0;
+	struct ec_hwmon_data *lmsensor_data = dev_get_drvdata(dev);
+
+	struct ec_hw_pin_table *ptbl = &lmsensor_data->pin_tbl;
+	struct adv_hwmon_profile *profile = lmsensor_data->profile;
+	struct adv_ec_platform_data *adv_ec_data = lmsensor_data->adv_ec_data;
+
+	temp = read_ad_value(adv_ec_data, ptbl->v5[0], ptbl->v5[1]);
+
+	if (profile->r2 != 0)
+		voltage = temp * (profile->r1 + profile->r2) / profile->r2;
+
+	if (profile->resolution != 0)
+		voltage =  temp * profile->resolution / 1000 / 1000;
+
+	if (profile->offset != 0)
+		voltage += (int)profile->offset * 100;
+
+	lmsensor_data->voltage[1] = 10 * voltage;
+
+	*val = lmsensor_data->voltage[1];
+	return 0;
+}
+
+static int get_ec_in_v12_input(struct device *dev, long *val)
+{
+	int temp;
+	unsigned long voltage = 0;
+	struct ec_hwmon_data *lmsensor_data = dev_get_drvdata(dev);
+
+	struct ec_hw_pin_table *ptbl = &lmsensor_data->pin_tbl;
+	struct adv_hwmon_profile *profile = lmsensor_data->profile;
+	struct adv_ec_platform_data *adv_ec_data = lmsensor_data->adv_ec_data;
+
+	temp = read_ad_value(adv_ec_data, ptbl->v12[0], ptbl->v12[1]);
+	if (temp == -1)
+		temp = read_ad_value(adv_ec_data, ptbl->vdc[0], ptbl->vdc[1]);
+
+	if (profile->r2 != 0)
+		voltage = temp * (profile->r1 + profile->r2) / profile->r2;
+
+	if (profile->resolution != 0)
+		voltage =  temp * profile->resolution / 1000 / 1000;
+
+	if (profile->offset != 0)
+		voltage += profile->offset * 100;
+
+	lmsensor_data->voltage[2] = 10 * voltage;
+
+	*val = lmsensor_data->voltage[2];
+	return 0;
+}
+
+static int get_ec_in_vcore_input(struct device *dev, long *val)
+{
+	int temp;
+	unsigned int voltage = 0;
+	struct ec_hwmon_data *lmsensor_data = dev_get_drvdata(dev);
+
+	struct ec_hw_pin_table *ptbl = &lmsensor_data->pin_tbl;
+	struct adv_hwmon_profile *profile = lmsensor_data->profile;
+	struct adv_ec_platform_data *adv_ec_data = lmsensor_data->adv_ec_data;
+
+	temp = read_ad_value(adv_ec_data, ptbl->vcore[0], ptbl->vcore[1]);
+
+	if (profile->r2 != 0)
+		voltage = temp * (profile->r1 + profile->r2) / profile->r2;
+
+	if (profile->resolution != 0)
+		voltage = temp * profile->resolution / 1000 / 1000;
+
+	if (profile->offset != 0)
+		voltage += profile->offset * 100;
+
+	lmsensor_data->voltage[3] = 10 * voltage;
+
+	*val = lmsensor_data->voltage[3];
+	return 0;
+}
+
+static int get_ec_current1_input(struct device *dev, long *val)
+{
+	int temp;
+	struct ec_hwmon_data *lmsensor_data = dev_get_drvdata(dev);
+
+	struct ec_hw_pin_table *ptbl = &lmsensor_data->pin_tbl;
+	struct adv_hwmon_profile *profile = lmsensor_data->profile;
+	struct adv_ec_platform_data *adv_ec_data = lmsensor_data->adv_ec_data;
+
+	temp = read_ad_value(adv_ec_data, ptbl->ec_current[0], ptbl->ec_current[1]);
+
+	if (profile->r2 != 0)
+		temp = temp * (profile->r1 + profile->r2) / profile->r2;
+
+	if (profile->resolution != 0)
+		temp = temp * profile->resolution / 1000 / 1000;
+
+	if (profile->offset != 0)
+		temp += profile->offset * 100;
+
+	lmsensor_data->ec_current[3] = 10 * temp;
+
+	*val = lmsensor_data->ec_current[3];
+	return 0;
+}
+
+static int get_ec_cpu_temp(struct device *dev, long *val)
+{
+	#define EC_ACPI_THERMAL1_REMOTE_TEMP 0x61
+
+	unsigned char value;
+	struct ec_hwmon_data *lmsensor_data = dev_get_drvdata(dev);
+	struct adv_ec_platform_data *adv_ec_data = lmsensor_data->adv_ec_data;
+
+	read_acpi_value(adv_ec_data, EC_ACPI_THERMAL1_REMOTE_TEMP, &value);
+	*val = 1000 * value;
+	return 0;
+}
+
+static int get_ec_sys_temp(struct device *dev, long *val)
+{
+	#define EC_ACPI_THERMAL1_LOCAL_TEMP 0x60
+
+	unsigned char value;
+	struct ec_hwmon_data *lmsensor_data = dev_get_drvdata(dev);
+	struct adv_ec_platform_data *adv_ec_data = lmsensor_data->adv_ec_data;
+
+	read_acpi_value(adv_ec_data, EC_ACPI_THERMAL1_LOCAL_TEMP, &value);
+	*val = 1000 * value;
+	return 0;
+}
+
+
+static int
+ahc1ec0_read_in(struct device *dev, u32 attr, int channel, long *val)
+{
+	struct ec_hwmon_data *lmsensor_data = dev_get_drvdata(dev);
+
+	if (!(lmsensor_data && lmsensor_data->profile))
+		return -EINVAL;
+
+	if (attr == hwmon_in_input &&
+		lmsensor_data->profile->hwmon_in_list_cnt > channel) {
+		int index = lmsensor_data->profile->hwmon_in_list[channel];
+		const struct ec_hwmon_attrs *ec_hwmon_attr = &ec_hwmon_in_attr_template[index];
+
+		return ec_hwmon_attr->read(dev, val);
+	}
+
+	return -EOPNOTSUPP;
+}
+
+static int
+ahc1ec0_read_temp(struct device *dev, u32 attr, int channel, long *val)
+{
+	struct ec_hwmon_data *lmsensor_data = dev_get_drvdata(dev);
+
+	if (!(lmsensor_data && lmsensor_data->profile))
+		return -EINVAL;
+
+	switch (attr) {
+	case hwmon_temp_input:
+		if (lmsensor_data->profile->temp_list_cnt > channel) {
+			int index = lmsensor_data->profile->temp_list[channel];
+			const struct ec_hwmon_attrs *devec_hwmon_attr =
+				&ec_temp_attrs_template[index];
+
+			return devec_hwmon_attr->read(dev, val);
+		}
+		return -EOPNOTSUPP;
+	case hwmon_temp_crit:
+		// both CPU temp and System temp are all this value
+		*val = 100000;
+		return 0;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static int
+ahc1ec0_read_string(struct device *dev,
+					enum hwmon_sensor_types type,
+					u32 attr,
+					int channel,
+					const char **str)
+{
+	struct ec_hwmon_data *lmsensor_data = dev_get_drvdata(dev);
+
+	if (!(lmsensor_data && lmsensor_data->profile))
+		return -EINVAL;
+
+	if ((type == hwmon_in && attr == hwmon_in_label) &&
+		(lmsensor_data->profile->hwmon_in_list_cnt > channel)) {
+		int index = lmsensor_data->profile->hwmon_in_list[channel];
+		const struct ec_hwmon_attrs *ec_hwmon_attr = &ec_hwmon_in_attr_template[index];
+
+		*str = ec_hwmon_attr->name;
+		return 0;
+	}
+
+	if ((type == hwmon_temp && attr == hwmon_temp_label) &&
+		(lmsensor_data->profile->temp_list_cnt > channel)) {
+		int index = lmsensor_data->profile->temp_list[channel];
+		const struct ec_hwmon_attrs *ec_hwmon_attr = &ec_temp_attrs_template[index];
+
+		*str = ec_hwmon_attr->name;
+		return 0;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+static int
+ahc1ec0_read(struct device *dev,
+			enum hwmon_sensor_types type,
+			u32 attr,
+			int channel,
+			long *val)
+{
+	switch (type) {
+	case hwmon_in:
+		return ahc1ec0_read_in(dev, attr, channel, val);
+	case hwmon_temp:
+		return ahc1ec0_read_temp(dev, attr, channel, val);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static umode_t
+ec_hwmon_in_visible(const void *data, u32 attr, int channel)
+{
+	switch (attr) {
+	case hwmon_in_input:
+	case hwmon_in_label:
+		return 0444;
+	default:
+		return 0;
+	}
+}
+
+static umode_t
+ec_temp_in_visible(const void *data, u32 attr, int channel)
+{
+	switch (attr) {
+	case hwmon_temp_input:
+	case hwmon_temp_crit:
+	case hwmon_temp_label:
+		return 0444;
+	default:
+		return 0;
+	}
+}
+
+static umode_t
+ahc1ec0_is_visible(const void *data,
+					enum hwmon_sensor_types type, u32 attr, int channel)
+{
+	switch (type) {
+	case hwmon_in:
+		return ec_hwmon_in_visible(data, attr, channel);
+	case hwmon_temp:
+		return ec_temp_in_visible(data, attr, channel);
+	default:
+		return 0;
+	}
+}
+
+static const u32 ahc1ec0_in_config[] = {
+	HWMON_I_INPUT | HWMON_I_LABEL,
+	HWMON_I_INPUT | HWMON_I_LABEL,
+	HWMON_I_INPUT | HWMON_I_LABEL,
+	HWMON_I_INPUT | HWMON_I_LABEL,
+	0
+};
+
+static const struct hwmon_channel_info ahc1ec0_in = {
+	.type = hwmon_in,
+	.config = ahc1ec0_in_config,
+};
+
+static const u32 ahc1ec0_temp_config[] = {
+	HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_LABEL,
+	0
+};
+
+static const struct hwmon_channel_info ahc1ec0_temp = {
+	.type = hwmon_temp,
+	.config = ahc1ec0_temp_config,
+};
+
+static const struct hwmon_channel_info *ahc1ec0_info[] = {
+	&ahc1ec0_in,
+	&ahc1ec0_temp,
+	NULL
+};
+
+static const struct hwmon_ops ahc1ec0_hwmon_ops = {
+	.is_visible = ahc1ec0_is_visible,
+	.read = ahc1ec0_read,
+	.read_string = ahc1ec0_read_string,
+};
+
+static const struct hwmon_chip_info ahc1ec0_chip_info = {
+	.ops = &ahc1ec0_hwmon_ops,
+	.info = ahc1ec0_info,
+};
+
+static int adv_ec_hwmon_probe(struct platform_device *pdev)
+{
+	int ret;
+	u32 profile;
+	struct device *dev = &pdev->dev;
+	struct adv_ec_platform_data *adv_ec_data;
+	struct ec_hwmon_data *lmsensor_data;
+
+	adv_ec_data = dev_get_drvdata(dev->parent);
+	if (!adv_ec_data)
+		return -EINVAL;
+
+	ret = device_property_read_u32(dev->parent, "advantech,hwmon-profile", &profile);
+	if (ret < 0) {
+		dev_err(dev, "get hwmon-profile failed! (%d)", ret);
+		return ret;
+	}
+
+	if (!(profile < ARRAY_SIZE(advec_profile))) {
+		dev_err(dev, "not support hwmon profile(%d)!\n", profile);
+		return -EINVAL;
+	}
+
+	lmsensor_data = devm_kzalloc(dev, sizeof(struct ec_hwmon_data), GFP_KERNEL);
+	if (!lmsensor_data)
+		return -ENOMEM;
+
+	lmsensor_data->adv_ec_data = adv_ec_data;
+	lmsensor_data->dev = dev;
+	dev_set_drvdata(dev, lmsensor_data);
+
+	adv_ec_init_hwmon_profile(profile, lmsensor_data);
+
+	lmsensor_data->hwmon_dev  = devm_hwmon_device_register_with_info(dev,
+			"ahc1ec0.hwmon", lmsensor_data, &ahc1ec0_chip_info, NULL);
+
+	return PTR_ERR_OR_ZERO(lmsensor_data->hwmon_dev);
+}
+
+static struct platform_driver adv_hwmon_drv = {
+	.driver = {
+		.name = "ahc1ec0-hwmon",
+	},
+	.probe = adv_ec_hwmon_probe,
+};
+module_platform_driver(adv_hwmon_drv);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS("platform:ahc1ec0-hwmon");
+MODULE_DESCRIPTION("Advantech Embedded Controller HWMON Driver.");
+MODULE_AUTHOR("Campion Kang <campion.kang@advantech.com.tw>");
+MODULE_AUTHOR("Jianfeng Dai <jianfeng.dai@advantech.com.cn>");
+MODULE_VERSION("1.0");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/amc6821.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/amc6821.c
@@ -935,10 +935,21 @@
 
 MODULE_DEVICE_TABLE(i2c, amc6821_id);
 
+static const struct of_device_id __maybe_unused amc6821_of_match[] = {
+	{
+		.compatible = "ti,amc6821",
+		.data = (void *)amc6821,
+	},
+	{ }
+};
+
+MODULE_DEVICE_TABLE(of, amc6821_of_match);
+
 static struct i2c_driver amc6821_driver = {
 	.class = I2C_CLASS_HWMON,
 	.driver = {
 		.name	= "amc6821",
+		.of_match_table = of_match_ptr(amc6821_of_match),
 	},
 	.probe = amc6821_probe,
 	.id_table = amc6821_id,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/applesmc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/applesmc.c
@@ -748,15 +748,18 @@
 	}
 
 	ret = applesmc_read_key(LIGHT_SENSOR_LEFT_KEY, buffer, data_length);
+	if (ret)
+		goto out;
 	/* newer macbooks report a single 10-bit bigendian value */
 	if (data_length == 10) {
 		left = be16_to_cpu(*(__be16 *)(buffer + 6)) >> 2;
 		goto out;
 	}
 	left = buffer[2];
+
+	ret = applesmc_read_key(LIGHT_SENSOR_RIGHT_KEY, buffer, data_length);
 	if (ret)
 		goto out;
-	ret = applesmc_read_key(LIGHT_SENSOR_RIGHT_KEY, buffer, data_length);
 	right = buffer[2];
 
 out:
@@ -805,12 +808,11 @@
 		  to_index(attr));
 
 	ret = applesmc_read_key(newkey, buffer, 2);
-	speed = ((buffer[0] << 8 | buffer[1]) >> 2);
-
 	if (ret)
 		return ret;
-	else
-		return snprintf(sysfsbuf, PAGE_SIZE, "%u\n", speed);
+
+	speed = ((buffer[0] << 8 | buffer[1]) >> 2);
+	return snprintf(sysfsbuf, PAGE_SIZE, "%u\n", speed);
 }
 
 static ssize_t applesmc_store_fan_speed(struct device *dev,
@@ -846,12 +848,11 @@
 	u8 buffer[2];
 
 	ret = applesmc_read_key(FANS_MANUAL, buffer, 2);
-	manual = ((buffer[0] << 8 | buffer[1]) >> to_index(attr)) & 0x01;
-
 	if (ret)
 		return ret;
-	else
-		return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", manual);
+
+	manual = ((buffer[0] << 8 | buffer[1]) >> to_index(attr)) & 0x01;
+	return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", manual);
 }
 
 static ssize_t applesmc_store_fan_manual(struct device *dev,
@@ -867,10 +868,11 @@
 		return -EINVAL;
 
 	ret = applesmc_read_key(FANS_MANUAL, buffer, 2);
-	val = (buffer[0] << 8 | buffer[1]);
 	if (ret)
 		goto out;
 
+	val = (buffer[0] << 8 | buffer[1]);
+
 	if (input)
 		val = val | (0x01 << to_index(attr));
 	else
@@ -946,13 +948,12 @@
 	u32 count;
 
 	ret = applesmc_read_key(KEY_COUNT_KEY, buffer, 4);
-	count = ((u32)buffer[0]<<24) + ((u32)buffer[1]<<16) +
-						((u32)buffer[2]<<8) + buffer[3];
-
 	if (ret)
 		return ret;
-	else
-		return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", count);
+
+	count = ((u32)buffer[0]<<24) + ((u32)buffer[1]<<16) +
+						((u32)buffer[2]<<8) + buffer[3];
+	return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", count);
 }
 
 static ssize_t applesmc_key_at_index_read_show(struct device *dev,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/aspeed-pwm-tacho.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/aspeed-pwm-tacho.c
@@ -194,6 +194,8 @@
 	u8 fan_tach_ch_source[16];
 	struct aspeed_cooling_device *cdev[8];
 	const struct attribute_group *groups[3];
+	/* protects access to shared ASPEED_PTCR_RESULT */
+	struct mutex tach_lock;
 };
 
 enum type { TYPEM, TYPEN, TYPEO };
@@ -528,6 +530,8 @@
 	u8 fan_tach_ch_source, type, mode, both;
 	int ret;
 
+	mutex_lock(&priv->tach_lock);
+
 	regmap_write(priv->regmap, ASPEED_PTCR_TRIGGER, 0);
 	regmap_write(priv->regmap, ASPEED_PTCR_TRIGGER, 0x1 << fan_tach_ch);
 
@@ -545,6 +549,8 @@
 		ASPEED_RPM_STATUS_SLEEP_USEC,
 		usec);
 
+	mutex_unlock(&priv->tach_lock);
+
 	/* return -ETIMEDOUT if we didn't get an answer. */
 	if (ret)
 		return ret;
@@ -851,6 +857,8 @@
 	ret = of_property_read_u32(child, "reg", &pwm_port);
 	if (ret)
 		return ret;
+	if (pwm_port >= ARRAY_SIZE(pwm_port_params))
+		return -EINVAL;
 	aspeed_create_pwm_port(priv, (u8)pwm_port);
 
 	ret = of_property_count_u8_elems(child, "cooling-levels");
@@ -907,6 +915,7 @@
 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
+	mutex_init(&priv->tach_lock);
 	priv->regmap = devm_regmap_init(dev, NULL, (__force void *)regs,
 			&aspeed_pwm_tacho_regmap_config);
 	if (IS_ERR(priv->regmap))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/coretemp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/coretemp.c
@@ -40,15 +40,12 @@
 
 #define PKG_SYSFS_ATTR_NO	1	/* Sysfs attribute for package temp */
 #define BASE_SYSFS_ATTR_NO	2	/* Sysfs Base attr no for coretemp */
-#define NUM_REAL_CORES		128	/* Number of Real cores per cpu */
-#define CORETEMP_NAME_LENGTH	19	/* String Length of attrs */
+#define NUM_REAL_CORES		512	/* Number of Real cores per cpu */
+#define CORETEMP_NAME_LENGTH	28	/* String Length of attrs */
 #define MAX_CORE_ATTRS		4	/* Maximum no of basic attrs */
 #define TOTAL_ATTRS		(MAX_CORE_ATTRS + 1)
 #define MAX_CORE_DATA		(NUM_REAL_CORES + BASE_SYSFS_ATTR_NO)
 
-#define TO_CORE_ID(cpu)		(cpu_data(cpu).cpu_core_id)
-#define TO_ATTR_NO(cpu)		(TO_CORE_ID(cpu) + BASE_SYSFS_ATTR_NO)
-
 #ifdef CONFIG_SMP
 #define for_each_sibling(i, cpu) \
 	for_each_cpu(i, topology_sibling_cpumask(cpu))
@@ -91,6 +88,8 @@
 struct platform_data {
 	struct device		*hwmon_dev;
 	u16			pkg_id;
+	u16			cpu_map[NUM_REAL_CORES];
+	struct ida		ida;
 	struct cpumask		cpumask;
 	struct temp_data	*core_data[MAX_CORE_DATA];
 	struct device_attribute name_attr;
@@ -243,10 +242,13 @@
 	 */
 	if (host_bridge && host_bridge->vendor == PCI_VENDOR_ID_INTEL) {
 		for (i = 0; i < ARRAY_SIZE(tjmax_pci_table); i++) {
-			if (host_bridge->device == tjmax_pci_table[i].device)
+			if (host_bridge->device == tjmax_pci_table[i].device) {
+				pci_dev_put(host_bridge);
 				return tjmax_pci_table[i].tjmax;
+			}
 		}
 	}
+	pci_dev_put(host_bridge);
 
 	for (i = 0; i < ARRAY_SIZE(tjmax_table); i++) {
 		if (strstr(c->x86_model_id, tjmax_table[i].id))
@@ -378,7 +380,7 @@
 }
 
 static int create_core_attrs(struct temp_data *tdata, struct device *dev,
-			     int attr_no)
+			     int index)
 {
 	int i;
 	static ssize_t (*const rd_ptr[TOTAL_ATTRS]) (struct device *dev,
@@ -390,13 +392,20 @@
 	};
 
 	for (i = 0; i < tdata->attr_size; i++) {
+		/*
+		 * We map the attr number to core id of the CPU
+		 * The attr number is always core id + 2
+		 * The Pkgtemp will always show up as temp1_*, if available
+		 */
+		int attr_no = tdata->is_pkg_data ? 1 : tdata->cpu_core_id + 2;
+
 		snprintf(tdata->attr_name[i], CORETEMP_NAME_LENGTH,
 			 "temp%d_%s", attr_no, suffixes[i]);
 		sysfs_attr_init(&tdata->sd_attrs[i].dev_attr.attr);
 		tdata->sd_attrs[i].dev_attr.attr.name = tdata->attr_name[i];
 		tdata->sd_attrs[i].dev_attr.attr.mode = 0444;
 		tdata->sd_attrs[i].dev_attr.show = rd_ptr[i];
-		tdata->sd_attrs[i].index = attr_no;
+		tdata->sd_attrs[i].index = index;
 		tdata->attrs[i] = &tdata->sd_attrs[i].dev_attr.attr;
 	}
 	tdata->attr_group.attrs = tdata->attrs;
@@ -441,7 +450,7 @@
 							MSR_IA32_THERM_STATUS;
 	tdata->is_pkg_data = pkg_flag;
 	tdata->cpu = cpu;
-	tdata->cpu_core_id = TO_CORE_ID(cpu);
+	tdata->cpu_core_id = topology_core_id(cpu);
 	tdata->attr_size = MAX_CORE_ATTRS;
 	mutex_init(&tdata->update_lock);
 	return tdata;
@@ -454,22 +463,29 @@
 	struct platform_data *pdata = platform_get_drvdata(pdev);
 	struct cpuinfo_x86 *c = &cpu_data(cpu);
 	u32 eax, edx;
-	int err, attr_no;
+	int err, index;
 
 	/*
-	 * Find attr number for sysfs:
-	 * We map the attr number to core id of the CPU
-	 * The attr number is always core id + 2
-	 * The Pkgtemp will always show up as temp1_*, if available
+	 * Get the index of tdata in pdata->core_data[]
+	 * tdata for package: pdata->core_data[1]
+	 * tdata for core: pdata->core_data[2] .. pdata->core_data[NUM_REAL_CORES + 1]
 	 */
-	attr_no = pkg_flag ? PKG_SYSFS_ATTR_NO : TO_ATTR_NO(cpu);
+	if (pkg_flag) {
+		index = PKG_SYSFS_ATTR_NO;
+	} else {
+		index = ida_alloc_max(&pdata->ida, NUM_REAL_CORES - 1, GFP_KERNEL);
+		if (index < 0)
+			return index;
 
-	if (attr_no > MAX_CORE_DATA - 1)
-		return -ERANGE;
+		pdata->cpu_map[index] = topology_core_id(cpu);
+		index += BASE_SYSFS_ATTR_NO;
+	}
 
 	tdata = init_temp_data(cpu, pkg_flag);
-	if (!tdata)
-		return -ENOMEM;
+	if (!tdata) {
+		err = -ENOMEM;
+		goto ida_free;
+	}
 
 	/* Test if we can access the status register */
 	err = rdmsr_safe_on_cpu(cpu, tdata->status_reg, &eax, &edx);
@@ -494,17 +510,20 @@
 		}
 	}
 
-	pdata->core_data[attr_no] = tdata;
+	pdata->core_data[index] = tdata;
 
 	/* Create sysfs interfaces */
-	err = create_core_attrs(tdata, pdata->hwmon_dev, attr_no);
+	err = create_core_attrs(tdata, pdata->hwmon_dev, index);
 	if (err)
 		goto exit_free;
 
 	return 0;
 exit_free:
-	pdata->core_data[attr_no] = NULL;
+	pdata->core_data[index] = NULL;
 	kfree(tdata);
+ida_free:
+	if (!pkg_flag)
+		ida_free(&pdata->ida, index - BASE_SYSFS_ATTR_NO);
 	return err;
 }
 
@@ -519,71 +538,63 @@
 {
 	struct temp_data *tdata = pdata->core_data[indx];
 
+	/* if we errored on add then this is already gone */
+	if (!tdata)
+		return;
+
 	/* Remove the sysfs attributes */
 	sysfs_remove_group(&pdata->hwmon_dev->kobj, &tdata->attr_group);
 
 	kfree(pdata->core_data[indx]);
 	pdata->core_data[indx] = NULL;
+
+	if (indx >= BASE_SYSFS_ATTR_NO)
+		ida_free(&pdata->ida, indx - BASE_SYSFS_ATTR_NO);
 }
 
-static int coretemp_probe(struct platform_device *pdev)
+static int coretemp_device_add(int zoneid)
 {
-	struct device *dev = &pdev->dev;
+	struct platform_device *pdev;
 	struct platform_data *pdata;
+	int err;
 
 	/* Initialize the per-zone data structures */
-	pdata = devm_kzalloc(dev, sizeof(struct platform_data), GFP_KERNEL);
+	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
 	if (!pdata)
 		return -ENOMEM;
 
-	pdata->pkg_id = pdev->id;
-	platform_set_drvdata(pdev, pdata);
+	pdata->pkg_id = zoneid;
+	ida_init(&pdata->ida);
 
-	pdata->hwmon_dev = devm_hwmon_device_register_with_groups(dev, DRVNAME,
-								  pdata, NULL);
-	return PTR_ERR_OR_ZERO(pdata->hwmon_dev);
-}
-
-static int coretemp_remove(struct platform_device *pdev)
-{
-	struct platform_data *pdata = platform_get_drvdata(pdev);
-	int i;
+	pdev = platform_device_alloc(DRVNAME, zoneid);
+	if (!pdev) {
+		err = -ENOMEM;
+		goto err_free_pdata;
+	}
 
-	for (i = MAX_CORE_DATA - 1; i >= 0; --i)
-		if (pdata->core_data[i])
-			coretemp_remove_core(pdata, i);
+	err = platform_device_add(pdev);
+	if (err)
+		goto err_put_dev;
 
+	platform_set_drvdata(pdev, pdata);
+	zone_devices[zoneid] = pdev;
 	return 0;
-}
 
-static struct platform_driver coretemp_driver = {
-	.driver = {
-		.name = DRVNAME,
-	},
-	.probe = coretemp_probe,
-	.remove = coretemp_remove,
-};
+err_put_dev:
+	platform_device_put(pdev);
+err_free_pdata:
+	kfree(pdata);
+	return err;
+}
 
-static struct platform_device *coretemp_device_add(unsigned int cpu)
+static void coretemp_device_remove(int zoneid)
 {
-	int err, zoneid = topology_logical_die_id(cpu);
-	struct platform_device *pdev;
-
-	if (zoneid < 0)
-		return ERR_PTR(-ENOMEM);
-
-	pdev = platform_device_alloc(DRVNAME, zoneid);
-	if (!pdev)
-		return ERR_PTR(-ENOMEM);
-
-	err = platform_device_add(pdev);
-	if (err) {
-		platform_device_put(pdev);
-		return ERR_PTR(err);
-	}
+	struct platform_device *pdev = zone_devices[zoneid];
+	struct platform_data *pdata = platform_get_drvdata(pdev);
 
-	zone_devices[zoneid] = pdev;
-	return pdev;
+	ida_destroy(&pdata->ida);
+	kfree(pdata);
+	platform_device_unregister(pdev);
 }
 
 static int coretemp_cpu_online(unsigned int cpu)
@@ -607,7 +618,10 @@
 	if (!cpu_has(c, X86_FEATURE_DTHERM))
 		return -ENODEV;
 
-	if (!pdev) {
+	pdata = platform_get_drvdata(pdev);
+	if (!pdata->hwmon_dev) {
+		struct device *hwmon;
+
 		/* Check the microcode version of the CPU */
 		if (chk_ucode_version(cpu))
 			return -EINVAL;
@@ -618,9 +632,11 @@
 		 * online. So, initialize per-pkg data structures and
 		 * then bring this core online.
 		 */
-		pdev = coretemp_device_add(cpu);
-		if (IS_ERR(pdev))
-			return PTR_ERR(pdev);
+		hwmon = hwmon_device_register_with_groups(&pdev->dev, DRVNAME,
+							  pdata, NULL);
+		if (IS_ERR(hwmon))
+			return PTR_ERR(hwmon);
+		pdata->hwmon_dev = hwmon;
 
 		/*
 		 * Check whether pkgtemp support is available.
@@ -630,7 +646,6 @@
 			coretemp_add_core(pdev, cpu, 1);
 	}
 
-	pdata = platform_get_drvdata(pdev);
 	/*
 	 * Check whether a thread sibling is already online. If not add the
 	 * interface for this CPU core.
@@ -647,25 +662,28 @@
 	struct platform_device *pdev = coretemp_get_pdev(cpu);
 	struct platform_data *pd;
 	struct temp_data *tdata;
-	int indx, target;
+	int i, indx = -1, target;
 
-	/*
-	 * Don't execute this on suspend as the device remove locks
-	 * up the machine.
-	 */
+	/* No need to tear down any interfaces for suspend */
 	if (cpuhp_tasks_frozen)
 		return 0;
 
 	/* If the physical CPU device does not exist, just return */
-	if (!pdev)
+	pd = platform_get_drvdata(pdev);
+	if (!pd->hwmon_dev)
 		return 0;
 
-	/* The core id is too big, just return */
-	indx = TO_ATTR_NO(cpu);
-	if (indx > MAX_CORE_DATA - 1)
+	for (i = 0; i < NUM_REAL_CORES; i++) {
+		if (pd->cpu_map[i] == topology_core_id(cpu)) {
+			indx = i + BASE_SYSFS_ATTR_NO;
+			break;
+		}
+	}
+
+	/* Too many cores and this core is not populated, just return */
+	if (indx < 0)
 		return 0;
 
-	pd = platform_get_drvdata(pdev);
 	tdata = pd->core_data[indx];
 
 	cpumask_clear_cpu(cpu, &pd->cpumask);
@@ -685,13 +703,14 @@
 	}
 
 	/*
-	 * If all cores in this pkg are offline, remove the device. This
-	 * will invoke the platform driver remove function, which cleans up
-	 * the rest.
+	 * If all cores in this pkg are offline, remove the interface.
 	 */
+	tdata = pd->core_data[PKG_SYSFS_ATTR_NO];
 	if (cpumask_empty(&pd->cpumask)) {
-		zone_devices[topology_logical_die_id(cpu)] = NULL;
-		platform_device_unregister(pdev);
+		if (tdata)
+			coretemp_remove_core(pd, PKG_SYSFS_ATTR_NO);
+		hwmon_device_unregister(pd->hwmon_dev);
+		pd->hwmon_dev = NULL;
 		return 0;
 	}
 
@@ -699,7 +718,6 @@
 	 * Check whether this core is the target for the package
 	 * interface. We need to assign it to some other cpu.
 	 */
-	tdata = pd->core_data[PKG_SYSFS_ATTR_NO];
 	if (tdata && tdata->cpu == cpu) {
 		target = cpumask_first(&pd->cpumask);
 		mutex_lock(&tdata->update_lock);
@@ -718,7 +736,7 @@
 
 static int __init coretemp_init(void)
 {
-	int err;
+	int i, err;
 
 	/*
 	 * CPUID.06H.EAX[0] indicates whether the CPU has thermal
@@ -734,20 +752,22 @@
 	if (!zone_devices)
 		return -ENOMEM;
 
-	err = platform_driver_register(&coretemp_driver);
-	if (err)
-		goto outzone;
+	for (i = 0; i < max_zones; i++) {
+		err = coretemp_device_add(i);
+		if (err)
+			goto outzone;
+	}
 
 	err = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "hwmon/coretemp:online",
 				coretemp_cpu_online, coretemp_cpu_offline);
 	if (err < 0)
-		goto outdrv;
+		goto outzone;
 	coretemp_hp_online = err;
 	return 0;
 
-outdrv:
-	platform_driver_unregister(&coretemp_driver);
 outzone:
+	while (i--)
+		coretemp_device_remove(i);
 	kfree(zone_devices);
 	return err;
 }
@@ -755,8 +775,11 @@
 
 static void __exit coretemp_exit(void)
 {
+	int i;
+
 	cpuhp_remove_state(coretemp_hp_online);
-	platform_driver_unregister(&coretemp_driver);
+	for (i = 0; i < max_zones; i++)
+		coretemp_device_remove(i);
 	kfree(zone_devices);
 }
 module_exit(coretemp_exit)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/da9052-hwmon.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/da9052-hwmon.c
@@ -244,9 +244,9 @@
 	int channel = to_sensor_dev_attr(devattr)->index;
 	int ret;
 
-	mutex_lock(&hwmon->hwmon_lock);
+	mutex_lock(&hwmon->da9052->auxadc_lock);
 	ret = __da9052_read_tsi(dev, channel);
-	mutex_unlock(&hwmon->hwmon_lock);
+	mutex_unlock(&hwmon->da9052->auxadc_lock);
 
 	if (ret < 0)
 		return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/dell-smm-hwmon.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/dell-smm-hwmon.c
@@ -301,7 +301,7 @@
 }
 
 /*
- * Set the fan speed (off, low, high). Returns the new fan status.
+ * Set the fan speed (off, low, high, ...).
  */
 static int i8k_set_fan(int fan, int speed)
 {
@@ -313,7 +313,7 @@
 	speed = (speed < 0) ? 0 : ((speed > i8k_fan_max) ? i8k_fan_max : speed);
 	regs.ebx = (fan & 0xff) | (speed << 8);
 
-	return i8k_smm(&regs) ? : i8k_get_fan_status(fan);
+	return i8k_smm(&regs);
 }
 
 static int i8k_get_temp_type(int sensor)
@@ -427,7 +427,7 @@
 i8k_ioctl_unlocked(struct file *fp, unsigned int cmd, unsigned long arg)
 {
 	int val = 0;
-	int speed;
+	int speed, err;
 	unsigned char buff[16];
 	int __user *argp = (int __user *)arg;
 
@@ -488,7 +488,11 @@
 		if (copy_from_user(&speed, argp + 1, sizeof(int)))
 			return -EFAULT;
 
-		val = i8k_set_fan(val, speed);
+		err = i8k_set_fan(val, speed);
+		if (err < 0)
+			return err;
+
+		val = i8k_get_fan_status(val);
 		break;
 
 	default:
@@ -588,15 +592,18 @@
 	.unlocked_ioctl	= i8k_ioctl,
 };
 
+static struct proc_dir_entry *entry;
+
 static void __init i8k_init_procfs(void)
 {
 	/* Register the proc entry */
-	proc_create("i8k", 0, NULL, &i8k_fops);
+	entry = proc_create("i8k", 0, NULL, &i8k_fops);
 }
 
 static void __exit i8k_exit_procfs(void)
 {
-	remove_proc_entry("i8k", NULL);
+	if (entry)
+		remove_proc_entry("i8k", NULL);
 }
 
 #else
@@ -792,10 +799,10 @@
 static umode_t i8k_is_visible(struct kobject *kobj, struct attribute *attr,
 			      int index)
 {
-	if (disallow_fan_support && index >= 8)
+	if (disallow_fan_support && index >= 20)
 		return 0;
 	if (disallow_fan_type_call &&
-	    (index == 9 || index == 12 || index == 15))
+	    (index == 21 || index == 25 || index == 28))
 		return 0;
 	if (index >= 0 && index <= 1 &&
 	    !(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP1))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/emc2103.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/emc2103.c
@@ -443,7 +443,7 @@
 	}
 
 	result = read_u8_from_i2c(client, REG_FAN_CONF1, &conf_reg);
-	if (result) {
+	if (result < 0) {
 		count = result;
 		goto err;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/f71882fg.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/f71882fg.c
@@ -1577,8 +1577,9 @@
 		temp *= 125;
 		if (sign)
 			temp -= 128000;
-	} else
-		temp = data->temp[nr] * 1000;
+	} else {
+		temp = ((s8)data->temp[nr]) * 1000;
+	}
 
 	return sprintf(buf, "%d\n", temp);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/gpio-fan.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/gpio-fan.c
@@ -391,6 +391,9 @@
 	if (!fan_data)
 		return -EINVAL;
 
+	if (state >= fan_data->num_speed)
+		return -EINVAL;
+
 	set_fan_speed(fan_data, state);
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/hwmon.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/hwmon.c
@@ -51,6 +51,7 @@
 
 #define to_hwmon_attr(d) \
 	container_of(d, struct hwmon_device_attribute, dev_attr)
+#define to_dev_attr(a) container_of(a, struct device_attribute, attr)
 
 /*
  * Thermal zone information
@@ -58,7 +59,7 @@
  * also provides the sensor index.
  */
 struct hwmon_thermal_data {
-	struct hwmon_device *hwdev;	/* Reference to hwmon device */
+	struct device *dev;		/* Reference to hwmon device */
 	int index;			/* sensor index */
 };
 
@@ -95,9 +96,27 @@
 	NULL
 };
 
+static void hwmon_free_attrs(struct attribute **attrs)
+{
+	int i;
+
+	for (i = 0; attrs[i]; i++) {
+		struct device_attribute *dattr = to_dev_attr(attrs[i]);
+		struct hwmon_device_attribute *hattr = to_hwmon_attr(dattr);
+
+		kfree(hattr);
+	}
+	kfree(attrs);
+}
+
 static void hwmon_dev_release(struct device *dev)
 {
-	kfree(to_hwmon_device(dev));
+	struct hwmon_device *hwdev = to_hwmon_device(dev);
+
+	if (hwdev->group.attrs)
+		hwmon_free_attrs(hwdev->group.attrs);
+	kfree(hwdev->groups);
+	kfree(hwdev);
 }
 
 static struct class hwmon_class = {
@@ -119,11 +138,11 @@
 static int hwmon_thermal_get_temp(void *data, int *temp)
 {
 	struct hwmon_thermal_data *tdata = data;
-	struct hwmon_device *hwdev = tdata->hwdev;
+	struct hwmon_device *hwdev = to_hwmon_device(tdata->dev);
 	int ret;
 	long t;
 
-	ret = hwdev->chip->ops->read(&hwdev->dev, hwmon_temp, hwmon_temp_input,
+	ret = hwdev->chip->ops->read(tdata->dev, hwmon_temp, hwmon_temp_input,
 				     tdata->index, &t);
 	if (ret < 0)
 		return ret;
@@ -137,8 +156,7 @@
 	.get_temp = hwmon_thermal_get_temp,
 };
 
-static int hwmon_thermal_add_sensor(struct device *dev,
-				    struct hwmon_device *hwdev, int index)
+static int hwmon_thermal_add_sensor(struct device *dev, int index)
 {
 	struct hwmon_thermal_data *tdata;
 	struct thermal_zone_device *tzd;
@@ -147,10 +165,10 @@
 	if (!tdata)
 		return -ENOMEM;
 
-	tdata->hwdev = hwdev;
+	tdata->dev = dev;
 	tdata->index = index;
 
-	tzd = devm_thermal_zone_of_sensor_register(&hwdev->dev, index, tdata,
+	tzd = devm_thermal_zone_of_sensor_register(dev, index, tdata,
 						   &hwmon_thermal_ops);
 	/*
 	 * If CONFIG_THERMAL_OF is disabled, this returns -ENODEV,
@@ -162,8 +180,7 @@
 	return 0;
 }
 #else
-static int hwmon_thermal_add_sensor(struct device *dev,
-				    struct hwmon_device *hwdev, int index)
+static int hwmon_thermal_add_sensor(struct device *dev, int index)
 {
 	return 0;
 }
@@ -250,8 +267,7 @@
 	       (type == hwmon_fan && attr == hwmon_fan_label);
 }
 
-static struct attribute *hwmon_genattr(struct device *dev,
-				       const void *drvdata,
+static struct attribute *hwmon_genattr(const void *drvdata,
 				       enum hwmon_sensor_types type,
 				       u32 attr,
 				       int index,
@@ -279,7 +295,7 @@
 	if ((mode & 0222) && !ops->write)
 		return ERR_PTR(-EINVAL);
 
-	hattr = devm_kzalloc(dev, sizeof(*hattr), GFP_KERNEL);
+	hattr = kzalloc(sizeof(*hattr), GFP_KERNEL);
 	if (!hattr)
 		return ERR_PTR(-ENOMEM);
 
@@ -492,8 +508,7 @@
 	return n;
 }
 
-static int hwmon_genattrs(struct device *dev,
-			  const void *drvdata,
+static int hwmon_genattrs(const void *drvdata,
 			  struct attribute **attrs,
 			  const struct hwmon_ops *ops,
 			  const struct hwmon_channel_info *info)
@@ -519,7 +534,7 @@
 			attr_mask &= ~BIT(attr);
 			if (attr >= template_size)
 				return -EINVAL;
-			a = hwmon_genattr(dev, drvdata, info->type, attr, i,
+			a = hwmon_genattr(drvdata, info->type, attr, i,
 					  templates[attr], ops);
 			if (IS_ERR(a)) {
 				if (PTR_ERR(a) != -ENOENT)
@@ -533,8 +548,7 @@
 }
 
 static struct attribute **
-__hwmon_create_attrs(struct device *dev, const void *drvdata,
-		     const struct hwmon_chip_info *chip)
+__hwmon_create_attrs(const void *drvdata, const struct hwmon_chip_info *chip)
 {
 	int ret, i, aindex = 0, nattrs = 0;
 	struct attribute **attrs;
@@ -545,15 +559,17 @@
 	if (nattrs == 0)
 		return ERR_PTR(-EINVAL);
 
-	attrs = devm_kcalloc(dev, nattrs + 1, sizeof(*attrs), GFP_KERNEL);
+	attrs = kcalloc(nattrs + 1, sizeof(*attrs), GFP_KERNEL);
 	if (!attrs)
 		return ERR_PTR(-ENOMEM);
 
 	for (i = 0; chip->info[i]; i++) {
-		ret = hwmon_genattrs(dev, drvdata, &attrs[aindex], chip->ops,
+		ret = hwmon_genattrs(drvdata, &attrs[aindex], chip->ops,
 				     chip->info[i]);
-		if (ret < 0)
+		if (ret < 0) {
+			hwmon_free_attrs(attrs);
 			return ERR_PTR(ret);
+		}
 		aindex += ret;
 	}
 
@@ -595,14 +611,13 @@
 			for (i = 0; groups[i]; i++)
 				ngroups++;
 
-		hwdev->groups = devm_kcalloc(dev, ngroups, sizeof(*groups),
-					     GFP_KERNEL);
+		hwdev->groups = kcalloc(ngroups, sizeof(*groups), GFP_KERNEL);
 		if (!hwdev->groups) {
 			err = -ENOMEM;
 			goto free_hwmon;
 		}
 
-		attrs = __hwmon_create_attrs(dev, drvdata, chip);
+		attrs = __hwmon_create_attrs(drvdata, chip);
 		if (IS_ERR(attrs)) {
 			err = PTR_ERR(attrs);
 			goto free_hwmon;
@@ -630,8 +645,10 @@
 	dev_set_drvdata(hdev, drvdata);
 	dev_set_name(hdev, HWMON_ID_FORMAT, id);
 	err = device_register(hdev);
-	if (err)
-		goto free_hwmon;
+	if (err) {
+		put_device(hdev);
+		goto ida_remove;
+	}
 
 	if (dev && dev->of_node && chip && chip->ops->read &&
 	    chip->info[0]->type == hwmon_chip &&
@@ -647,8 +664,7 @@
 							   hwmon_temp_input, j))
 					continue;
 				if (info[i]->config[j] & HWMON_T_INPUT) {
-					err = hwmon_thermal_add_sensor(dev,
-								hwdev, j);
+					err = hwmon_thermal_add_sensor(hdev, j);
 					if (err) {
 						device_unregister(hdev);
 						/*
@@ -667,7 +683,7 @@
 	return hdev;
 
 free_hwmon:
-	kfree(hwdev);
+	hwmon_dev_release(hdev);
 ida_remove:
 	ida_simple_remove(&hwmon_ida, id);
 	return ERR_PTR(err);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/i5500_temp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/i5500_temp.c
@@ -108,7 +108,7 @@
 	u32 tstimer;
 	s8 tsfsc;
 
-	err = pci_enable_device(pdev);
+	err = pcim_enable_device(pdev);
 	if (err) {
 		dev_err(&pdev->dev, "Failed to enable device\n");
 		return err;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/ibmaem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/ibmaem.c
@@ -550,7 +550,7 @@
 
 	res = platform_device_add(data->pdev);
 	if (res)
-		goto ipmi_err;
+		goto dev_add_err;
 
 	platform_set_drvdata(data->pdev, data);
 
@@ -598,7 +598,9 @@
 	ipmi_destroy_user(data->ipmi.user);
 ipmi_err:
 	platform_set_drvdata(data->pdev, NULL);
-	platform_device_unregister(data->pdev);
+	platform_device_del(data->pdev);
+dev_add_err:
+	platform_device_put(data->pdev);
 dev_err:
 	ida_simple_remove(&aem_ida, data->id);
 id_err:
@@ -690,7 +692,7 @@
 
 	res = platform_device_add(data->pdev);
 	if (res)
-		goto ipmi_err;
+		goto dev_add_err;
 
 	platform_set_drvdata(data->pdev, data);
 
@@ -738,7 +740,9 @@
 	ipmi_destroy_user(data->ipmi.user);
 ipmi_err:
 	platform_set_drvdata(data->pdev, NULL);
-	platform_device_unregister(data->pdev);
+	platform_device_del(data->pdev);
+dev_add_err:
+	platform_device_put(data->pdev);
 dev_err:
 	ida_simple_remove(&aem_ida, data->id);
 id_err:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/ibmpex.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/ibmpex.c
@@ -502,6 +502,7 @@
 	return;
 
 out_register:
+	list_del(&data->list);
 	hwmon_device_unregister(data->hwmon_dev);
 out_user:
 	ipmi_destroy_user(data->user);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/ina3221.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/ina3221.c
@@ -403,7 +403,7 @@
 
 	/* For enabling routine, increase refcount and resume() at first */
 	if (enable) {
-		ret = pm_runtime_get_sync(ina->pm_dev);
+		ret = pm_runtime_resume_and_get(ina->pm_dev);
 		if (ret < 0) {
 			dev_err(dev, "Failed to get PM runtime\n");
 			return ret;
@@ -672,7 +672,7 @@
 		return ret;
 	} else if (val > INA3221_CHANNEL3) {
 		dev_err(dev, "invalid reg %d of %pOFn\n", val, child);
-		return ret;
+		return -EINVAL;
 	}
 
 	input = &ina->inputs[val];
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/it87.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/it87.c
@@ -486,6 +486,8 @@
 #define has_pwm_freq2(data)	((data)->features & FEAT_PWM_FREQ2)
 #define has_six_temp(data)	((data)->features & FEAT_SIX_TEMP)
 #define has_vin3_5v(data)	((data)->features & FEAT_VIN3_5V)
+#define has_scaling(data)	((data)->features & (FEAT_12MV_ADC | \
+						     FEAT_10_9MV_ADC))
 
 struct it87_sio_data {
 	int sioaddr;
@@ -3098,7 +3100,7 @@
 			 "Detected broken BIOS defaults, disabling PWM interface\n");
 
 	/* Starting with IT8721F, we handle scaling of internal voltages */
-	if (has_12mv_adc(data)) {
+	if (has_scaling(data)) {
 		if (sio_data->internal & BIT(0))
 			data->in_scaled |= BIT(3);	/* in3 is AVCC */
 		if (sio_data->internal & BIT(1))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/jc42.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/jc42.c
@@ -506,7 +506,7 @@
 	}
 	data->config = config;
 
-	hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,
+	hwmon_dev = devm_hwmon_device_register_with_info(dev, "jc42",
 							 data, &jc42_chip_info,
 							 NULL);
 	return PTR_ERR_OR_ZERO(hwmon_dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/k10temp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/k10temp.c
@@ -349,6 +349,7 @@
 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_DF_F3) },
 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_M10H_DF_F3) },
 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_M30H_DF_F3) },
+	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_M60H_DF_F3) },
 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_17H_M70H_DF_F3) },
 	{ PCI_VDEVICE(HYGON, PCI_DEVICE_ID_AMD_17H_DF_F3) },
 	{}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/lm80.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/lm80.c
@@ -597,7 +597,6 @@
 	struct device *dev = &client->dev;
 	struct device *hwmon_dev;
 	struct lm80_data *data;
-	int rv;
 
 	data = devm_kzalloc(dev, sizeof(struct lm80_data), GFP_KERNEL);
 	if (!data)
@@ -610,14 +609,8 @@
 	lm80_init_client(client);
 
 	/* A few vars need to be filled upon startup */
-	rv = lm80_read_value(client, LM80_REG_FAN_MIN(1));
-	if (rv < 0)
-		return rv;
-	data->fan[f_min][0] = rv;
-	rv = lm80_read_value(client, LM80_REG_FAN_MIN(2));
-	if (rv < 0)
-		return rv;
-	data->fan[f_min][1] = rv;
+	data->fan[f_min][0] = lm80_read_value(client, LM80_REG_FAN_MIN(1));
+	data->fan[f_min][1] = lm80_read_value(client, LM80_REG_FAN_MIN(2));
 
 	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
 							   data, lm80_groups);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/lm90.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/lm90.c
@@ -35,6 +35,15 @@
  * explicitly as max6659, or if its address is not 0x4c.
  * These chips lack the remote temperature offset feature.
  *
+ * This driver also supports the MAX6654 chip made by Maxim. This chip can be
+ * at 9 different addresses, similar to MAX6680/MAX6681. The MAX6654 is similar
+ * to MAX6657/MAX6658/MAX6659, but does not support critical temperature
+ * limits. Extended range is available by setting the configuration register
+ * accordingly, and is done during initialization. Extended precision is only
+ * available at conversion rates of 1 Hz and slower. Note that extended
+ * precision is not enabled by default, as this driver initializes all chips
+ * to 2 Hz by design.
+ *
  * This driver also supports the MAX6646, MAX6647, MAX6648, MAX6649 and
  * MAX6692 chips made by Maxim.  These are again similar to the LM86,
  * but they use unsigned temperature values and can report temperatures
@@ -61,10 +70,10 @@
  * This driver also supports the G781 from GMT. This device is compatible
  * with the ADM1032.
  *
- * This driver also supports TMP451 from Texas Instruments. This device is
- * supported in both compatibility and extended mode. It's mostly compatible
- * with ADT7461 except for local temperature low byte register and max
- * conversion rate.
+ * This driver also supports TMP451 and TMP461 from Texas Instruments.
+ * Those devices are supported in both compatibility and extended mode.
+ * They are mostly compatible with ADT7461 except for local temperature
+ * low byte register and max conversion rate.
  *
  * Since the LM90 was the first chipset supported by this driver, most
  * comments will refer to this chipset, but are actually general and
@@ -94,8 +103,8 @@
  * have address 0x4d.
  * MAX6647 has address 0x4e.
  * MAX6659 can have address 0x4c, 0x4d or 0x4e.
- * MAX6680 and MAX6681 can have address 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b,
- * 0x4c, 0x4d or 0x4e.
+ * MAX6654, MAX6680, and MAX6681 can have address 0x18, 0x19, 0x1a, 0x29,
+ * 0x2a, 0x2b, 0x4c, 0x4d or 0x4e.
  * SA56004 can have address 0x48 through 0x4F.
  */
 
@@ -104,7 +113,7 @@
 	0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
 
 enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680,
-	max6646, w83l771, max6696, sa56004, g781, tmp451 };
+	max6646, w83l771, max6696, sa56004, g781, tmp451, tmp461, max6654 };
 
 /*
  * The LM90 registers
@@ -145,7 +154,7 @@
 #define LM90_REG_R_TCRIT_HYST		0x21
 #define LM90_REG_W_TCRIT_HYST		0x21
 
-/* MAX6646/6647/6649/6657/6658/6659/6695/6696 registers */
+/* MAX6646/6647/6649/6654/6657/6658/6659/6695/6696 registers */
 
 #define MAX6657_REG_R_LOCAL_TEMPL	0x11
 #define MAX6696_REG_R_STATUS2		0x12
@@ -160,8 +169,12 @@
 
 #define LM90_MAX_CONVRATE_MS	16000	/* Maximum conversion rate in ms */
 
-/* TMP451 registers */
+/* TMP451/TMP461 registers */
 #define TMP451_REG_R_LOCAL_TEMPL	0x15
+#define TMP451_REG_CONALERT		0x22
+
+#define TMP461_REG_CHEN			0x16
+#define TMP461_REG_DFC			0x24
 
 /*
  * Device flags
@@ -174,7 +187,10 @@
 #define LM90_HAVE_EMERGENCY_ALARM (1 << 5)/* emergency alarm		*/
 #define LM90_HAVE_TEMP3		(1 << 6) /* 3rd temperature sensor	*/
 #define LM90_HAVE_BROKEN_ALERT	(1 << 7) /* Broken alert		*/
-#define LM90_PAUSE_FOR_CONFIG	(1 << 8) /* Pause conversion for config	*/
+#define LM90_HAVE_EXTENDED_TEMP	(1 << 8) /* extended temperature support*/
+#define LM90_PAUSE_FOR_CONFIG	(1 << 9) /* Pause conversion for config	*/
+#define LM90_HAVE_CRIT		(1 << 10)/* Chip supports CRIT/OVERT register	*/
+#define LM90_HAVE_CRIT_ALRM_SWP	(1 << 11)/* critical alarm bits swapped	*/
 
 /* LM90 status */
 #define LM90_STATUS_LTHRM	(1 << 0) /* local THERM limit tripped */
@@ -184,6 +200,7 @@
 #define LM90_STATUS_RHIGH	(1 << 4) /* remote high temp limit tripped */
 #define LM90_STATUS_LLOW	(1 << 5) /* local low temp limit tripped */
 #define LM90_STATUS_LHIGH	(1 << 6) /* local high temp limit tripped */
+#define LM90_STATUS_BUSY	(1 << 7) /* conversion is ongoing */
 
 #define MAX6696_STATUS2_R2THRM	(1 << 1) /* remote2 THERM limit tripped */
 #define MAX6696_STATUS2_R2OPEN	(1 << 2) /* remote2 is an open circuit */
@@ -209,6 +226,7 @@
 	{ "max6646", max6646 },
 	{ "max6647", max6646 },
 	{ "max6649", max6646 },
+	{ "max6654", max6654 },
 	{ "max6657", max6657 },
 	{ "max6658", max6657 },
 	{ "max6659", max6659 },
@@ -220,6 +238,7 @@
 	{ "w83l771", w83l771 },
 	{ "sa56004", sa56004 },
 	{ "tmp451", tmp451 },
+	{ "tmp461", tmp461 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, lm90_id);
@@ -270,6 +289,10 @@
 		.data = (void *)max6646
 	},
 	{
+		.compatible = "dallas,max6654",
+		.data = (void *)max6654
+	},
+	{
 		.compatible = "dallas,max6657",
 		.data = (void *)max6657
 	},
@@ -313,6 +336,10 @@
 		.compatible = "ti,tmp451",
 		.data = (void *)tmp451
 	},
+	{
+		.compatible = "ti,tmp461",
+		.data = (void *)tmp461
+	},
 	{ },
 };
 MODULE_DEVICE_TABLE(of, lm90_of_match);
@@ -331,80 +358,99 @@
 static const struct lm90_params lm90_params[] = {
 	[adm1032] = {
 		.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT
-		  | LM90_HAVE_BROKEN_ALERT,
+		  | LM90_HAVE_BROKEN_ALERT | LM90_HAVE_CRIT,
 		.alert_alarms = 0x7c,
 		.max_convrate = 10,
 	},
 	[adt7461] = {
 		.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT
-		  | LM90_HAVE_BROKEN_ALERT,
+		  | LM90_HAVE_BROKEN_ALERT | LM90_HAVE_EXTENDED_TEMP
+		  | LM90_HAVE_CRIT,
 		.alert_alarms = 0x7c,
 		.max_convrate = 10,
 	},
 	[g781] = {
 		.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT
-		  | LM90_HAVE_BROKEN_ALERT,
+		  | LM90_HAVE_BROKEN_ALERT | LM90_HAVE_CRIT,
 		.alert_alarms = 0x7c,
-		.max_convrate = 8,
+		.max_convrate = 7,
 	},
 	[lm86] = {
-		.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT,
+		.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT
+		  | LM90_HAVE_CRIT,
 		.alert_alarms = 0x7b,
 		.max_convrate = 9,
 	},
 	[lm90] = {
-		.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT,
+		.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT
+		  | LM90_HAVE_CRIT,
 		.alert_alarms = 0x7b,
 		.max_convrate = 9,
 	},
 	[lm99] = {
-		.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT,
+		.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT
+		  | LM90_HAVE_CRIT,
 		.alert_alarms = 0x7b,
 		.max_convrate = 9,
 	},
 	[max6646] = {
+		.flags = LM90_HAVE_CRIT | LM90_HAVE_BROKEN_ALERT,
 		.alert_alarms = 0x7c,
 		.max_convrate = 6,
 		.reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL,
 	},
+	[max6654] = {
+		.flags = LM90_HAVE_BROKEN_ALERT,
+		.alert_alarms = 0x7c,
+		.max_convrate = 7,
+		.reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL,
+	},
 	[max6657] = {
-		.flags = LM90_PAUSE_FOR_CONFIG,
+		.flags = LM90_PAUSE_FOR_CONFIG | LM90_HAVE_CRIT,
 		.alert_alarms = 0x7c,
 		.max_convrate = 8,
 		.reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL,
 	},
 	[max6659] = {
-		.flags = LM90_HAVE_EMERGENCY,
+		.flags = LM90_HAVE_EMERGENCY | LM90_HAVE_CRIT,
 		.alert_alarms = 0x7c,
 		.max_convrate = 8,
 		.reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL,
 	},
 	[max6680] = {
-		.flags = LM90_HAVE_OFFSET,
+		.flags = LM90_HAVE_OFFSET | LM90_HAVE_CRIT
+		  | LM90_HAVE_CRIT_ALRM_SWP | LM90_HAVE_BROKEN_ALERT,
 		.alert_alarms = 0x7c,
 		.max_convrate = 7,
 	},
 	[max6696] = {
 		.flags = LM90_HAVE_EMERGENCY
-		  | LM90_HAVE_EMERGENCY_ALARM | LM90_HAVE_TEMP3,
+		  | LM90_HAVE_EMERGENCY_ALARM | LM90_HAVE_TEMP3 | LM90_HAVE_CRIT,
 		.alert_alarms = 0x1c7c,
 		.max_convrate = 6,
 		.reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL,
 	},
 	[w83l771] = {
-		.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT,
+		.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT | LM90_HAVE_CRIT,
 		.alert_alarms = 0x7c,
 		.max_convrate = 8,
 	},
 	[sa56004] = {
-		.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT,
+		.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT | LM90_HAVE_CRIT,
 		.alert_alarms = 0x7b,
 		.max_convrate = 9,
 		.reg_local_ext = SA56004_REG_R_LOCAL_TEMPL,
 	},
 	[tmp451] = {
 		.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT
-		  | LM90_HAVE_BROKEN_ALERT,
+		  | LM90_HAVE_BROKEN_ALERT | LM90_HAVE_EXTENDED_TEMP | LM90_HAVE_CRIT,
+		.alert_alarms = 0x7c,
+		.max_convrate = 9,
+		.reg_local_ext = TMP451_REG_R_LOCAL_TEMPL,
+	},
+	[tmp461] = {
+		.flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT
+		  | LM90_HAVE_BROKEN_ALERT | LM90_HAVE_EXTENDED_TEMP | LM90_HAVE_CRIT,
 		.alert_alarms = 0x7c,
 		.max_convrate = 9,
 		.reg_local_ext = TMP451_REG_R_LOCAL_TEMPL,
@@ -632,20 +678,22 @@
 	struct i2c_client *client = data->client;
 	int val;
 
-	val = lm90_read_reg(client, LM90_REG_R_LOCAL_CRIT);
-	if (val < 0)
-		return val;
-	data->temp8[LOCAL_CRIT] = val;
+	if (data->flags & LM90_HAVE_CRIT) {
+		val = lm90_read_reg(client, LM90_REG_R_LOCAL_CRIT);
+		if (val < 0)
+			return val;
+		data->temp8[LOCAL_CRIT] = val;
 
-	val = lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT);
-	if (val < 0)
-		return val;
-	data->temp8[REMOTE_CRIT] = val;
+		val = lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT);
+		if (val < 0)
+			return val;
+		data->temp8[REMOTE_CRIT] = val;
 
-	val = lm90_read_reg(client, LM90_REG_R_TCRIT_HYST);
-	if (val < 0)
-		return val;
-	data->temp_hyst = val;
+		val = lm90_read_reg(client, LM90_REG_R_TCRIT_HYST);
+		if (val < 0)
+			return val;
+		data->temp_hyst = val;
+	}
 
 	val = lm90_read_reg(client, LM90_REG_R_REMOTE_LOWH);
 	if (val < 0)
@@ -773,7 +821,7 @@
 		val = lm90_read_reg(client, LM90_REG_R_STATUS);
 		if (val < 0)
 			return val;
-		data->alarms = val;	/* lower 8 bit of alarms */
+		data->alarms = val & ~LM90_STATUS_BUSY;
 
 		if (data->kind == max6696) {
 			val = lm90_select_remote_channel(data, 1);
@@ -979,7 +1027,7 @@
 	s16 temp11 = data->temp11[index];
 	int temp;
 
-	if (data->kind == adt7461 || data->kind == tmp451)
+	if (data->flags & LM90_HAVE_EXTENDED_TEMP)
 		temp = temp_from_u16_adt7461(data, temp11);
 	else if (data->kind == max6646)
 		temp = temp_from_u16(temp11);
@@ -1013,7 +1061,7 @@
 	if (data->kind == lm99 && index <= 2)
 		val -= 16000;
 
-	if (data->kind == adt7461 || data->kind == tmp451)
+	if (data->flags & LM90_HAVE_EXTENDED_TEMP)
 		data->temp11[index] = temp_to_u16_adt7461(data, val);
 	else if (data->kind == max6646)
 		data->temp11[index] = temp_to_u8(val) << 8;
@@ -1040,7 +1088,7 @@
 	s8 temp8 = data->temp8[index];
 	int temp;
 
-	if (data->kind == adt7461 || data->kind == tmp451)
+	if (data->flags & LM90_HAVE_EXTENDED_TEMP)
 		temp = temp_from_u8_adt7461(data, temp8);
 	else if (data->kind == max6646)
 		temp = temp_from_u8(temp8);
@@ -1073,7 +1121,7 @@
 	if (data->kind == lm99 && index == 3)
 		val -= 16000;
 
-	if (data->kind == adt7461 || data->kind == tmp451)
+	if (data->flags & LM90_HAVE_EXTENDED_TEMP)
 		data->temp8[index] = temp_to_u8_adt7461(data, val);
 	else if (data->kind == max6646)
 		data->temp8[index] = temp_to_u8(val);
@@ -1091,7 +1139,7 @@
 {
 	int temp;
 
-	if (data->kind == adt7461 || data->kind == tmp451)
+	if (data->flags & LM90_HAVE_EXTENDED_TEMP)
 		temp = temp_from_u8_adt7461(data, data->temp8[index]);
 	else if (data->kind == max6646)
 		temp = temp_from_u8(data->temp8[index]);
@@ -1111,7 +1159,7 @@
 	int temp;
 	int err;
 
-	if (data->kind == adt7461 || data->kind == tmp451)
+	if (data->flags & LM90_HAVE_EXTENDED_TEMP)
 		temp = temp_from_u8_adt7461(data, data->temp8[LOCAL_CRIT]);
 	else if (data->kind == max6646)
 		temp = temp_from_u8(data->temp8[LOCAL_CRIT]);
@@ -1147,6 +1195,7 @@
 static const u8 lm90_min_alarm_bits[3] = { 5, 3, 11 };
 static const u8 lm90_max_alarm_bits[3] = { 6, 4, 12 };
 static const u8 lm90_crit_alarm_bits[3] = { 0, 1, 9 };
+static const u8 lm90_crit_alarm_bits_swapped[3] = { 1, 0, 9 };
 static const u8 lm90_emergency_alarm_bits[3] = { 15, 13, 14 };
 static const u8 lm90_fault_bits[3] = { 0, 2, 10 };
 
@@ -1172,7 +1221,10 @@
 		*val = (data->alarms >> lm90_max_alarm_bits[channel]) & 1;
 		break;
 	case hwmon_temp_crit_alarm:
-		*val = (data->alarms >> lm90_crit_alarm_bits[channel]) & 1;
+		if (data->flags & LM90_HAVE_CRIT_ALRM_SWP)
+			*val = (data->alarms >> lm90_crit_alarm_bits_swapped[channel]) & 1;
+		else
+			*val = (data->alarms >> lm90_crit_alarm_bits[channel]) & 1;
 		break;
 	case hwmon_temp_emergency_alarm:
 		*val = (data->alarms >> lm90_emergency_alarm_bits[channel]) & 1;
@@ -1420,12 +1472,11 @@
 	if (man_id < 0 || chip_id < 0 || config1 < 0 || convrate < 0)
 		return -ENODEV;
 
-	if (man_id == 0x01 || man_id == 0x5C || man_id == 0x41) {
+	if (man_id == 0x01 || man_id == 0x5C || man_id == 0xA1) {
 		config2 = i2c_smbus_read_byte_data(client, LM90_REG_R_CONFIG2);
 		if (config2 < 0)
 			return -ENODEV;
-	} else
-		config2 = 0;		/* Make compiler happy */
+	}
 
 	if ((address == 0x4C || address == 0x4D)
 	 && man_id == 0x01) { /* National Semiconductor */
@@ -1557,6 +1608,16 @@
 		 && (config1 & 0x3f) == 0x00
 		 && convrate <= 0x07) {
 			name = "max6646";
+		} else
+		/*
+		 * The chip_id of the MAX6654 holds the revision of the chip.
+		 * The lowest 3 bits of the config1 register are unused and
+		 * should return zero when read.
+		 */
+		if (chip_id == 0x08
+		 && (config1 & 0x07) == 0x00
+		 && convrate <= 0x07) {
+			name = "max6654";
 		}
 	} else
 	if (address == 0x4C
@@ -1589,18 +1650,26 @@
 		 && convrate <= 0x08)
 			name = "g781";
 	} else
-	if (address == 0x4C
-	 && man_id == 0x55) { /* Texas Instruments */
-		int local_ext;
+	if (man_id == 0x55 && chip_id == 0x00 &&
+	    (config1 & 0x1B) == 0x00 && convrate <= 0x09) {
+		int local_ext, conalert, chen, dfc;
 
 		local_ext = i2c_smbus_read_byte_data(client,
 						     TMP451_REG_R_LOCAL_TEMPL);
-
-		if (chip_id == 0x00 /* TMP451 */
-		 && (config1 & 0x1B) == 0x00
-		 && convrate <= 0x09
-		 && (local_ext & 0x0F) == 0x00)
-			name = "tmp451";
+		conalert = i2c_smbus_read_byte_data(client,
+						    TMP451_REG_CONALERT);
+		chen = i2c_smbus_read_byte_data(client, TMP461_REG_CHEN);
+		dfc = i2c_smbus_read_byte_data(client, TMP461_REG_DFC);
+
+		if ((local_ext & 0x0F) == 0x00 &&
+		    (conalert & 0xf1) == 0x01 &&
+		    (chen & 0xfc) == 0x00 &&
+		    (dfc & 0xfc) == 0x00) {
+			if (address == 0x4c && !(chen & 0x03))
+				name = "tmp451";
+			else if (address >= 0x48 && address <= 0x4f)
+				name = "tmp461";
+		}
 	}
 
 	if (!name) { /* identification failed */
@@ -1647,7 +1716,7 @@
 	lm90_set_convrate(client, data, 500); /* 500ms; 2Hz conversion rate */
 
 	/* Check Temperature Range Select */
-	if (data->kind == adt7461 || data->kind == tmp451) {
+	if (data->flags & LM90_HAVE_EXTENDED_TEMP) {
 		if (config & 0x04)
 			data->flags |= LM90_FLAG_ADT7461_EXT;
 	}
@@ -1661,6 +1730,15 @@
 		config |= 0x18;
 
 	/*
+	 * Put MAX6654 into extended range (0x20, extend minimum range from
+	 * 0 degrees to -64 degrees). Note that extended resolution is not
+	 * possible on the MAX6654 unless conversion rate is set to 1 Hz or
+	 * slower, which is intentionally not done by default.
+	 */
+	if (data->kind == max6654)
+		config |= 0x20;
+
+	/*
 	 * Select external channel 0 for max6695/96
 	 */
 	if (data->kind == max6696)
@@ -1806,11 +1884,14 @@
 	info->config = data->channel_config;
 
 	data->channel_config[0] = HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX |
-		HWMON_T_CRIT | HWMON_T_CRIT_HYST | HWMON_T_MIN_ALARM |
-		HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM;
+		HWMON_T_MIN_ALARM | HWMON_T_MAX_ALARM;
 	data->channel_config[1] = HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX |
-		HWMON_T_CRIT | HWMON_T_CRIT_HYST | HWMON_T_MIN_ALARM |
-		HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM | HWMON_T_FAULT;
+		HWMON_T_MIN_ALARM | HWMON_T_MAX_ALARM | HWMON_T_FAULT;
+
+	if (data->flags & LM90_HAVE_CRIT) {
+		data->channel_config[0] |= HWMON_T_CRIT | HWMON_T_CRIT_ALARM | HWMON_T_CRIT_HYST;
+		data->channel_config[1] |= HWMON_T_CRIT | HWMON_T_CRIT_ALARM | HWMON_T_CRIT_HYST;
+	}
 
 	if (data->flags & LM90_HAVE_OFFSET)
 		data->channel_config[1] |= HWMON_T_OFFSET;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/lm95234.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/lm95234.c
@@ -301,7 +301,8 @@
 	if (ret < 0)
 		return ret;
 
-	val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, index ? 255 : 127);
+	val = DIV_ROUND_CLOSEST(clamp_val(val, 0, (index ? 255 : 127) * 1000),
+				1000);
 
 	mutex_lock(&data->update_lock);
 	data->tcrit2[index] = val;
@@ -350,7 +351,7 @@
 	if (ret < 0)
 		return ret;
 
-	val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, 255);
+	val = DIV_ROUND_CLOSEST(clamp_val(val, 0, 255000), 1000);
 
 	mutex_lock(&data->update_lock);
 	data->tcrit1[index] = val;
@@ -391,7 +392,7 @@
 	if (ret < 0)
 		return ret;
 
-	val = DIV_ROUND_CLOSEST(val, 1000);
+	val = DIV_ROUND_CLOSEST(clamp_val(val, -255000, 255000), 1000);
 	val = clamp_val((int)data->tcrit1[index] - val, 0, 31);
 
 	mutex_lock(&data->update_lock);
@@ -431,7 +432,7 @@
 		return ret;
 
 	/* Accuracy is 1/2 degrees C */
-	val = clamp_val(DIV_ROUND_CLOSEST(val, 500), -128, 127);
+	val = DIV_ROUND_CLOSEST(clamp_val(val, -64000, 63500), 500);
 
 	mutex_lock(&data->update_lock);
 	data->toffset[index] = val;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/ltc2945.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/ltc2945.c
@@ -248,6 +248,8 @@
 
 	/* convert to register value, then clamp and write result */
 	regval = ltc2945_val_to_reg(dev, reg, val);
+	if (regval < 0)
+		return regval;
 	if (is_power_reg(reg)) {
 		regval = clamp_val(regval, 0, 0xffffff);
 		regbuf[0] = regval >> 16;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/max16065.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/max16065.c
@@ -114,9 +114,10 @@
 	return limit * range / 256;
 }
 
-static inline int MV_TO_LIMIT(int mv, int range)
+static inline int MV_TO_LIMIT(unsigned long mv, int range)
 {
-	return clamp_val(DIV_ROUND_CLOSEST(mv * 256, range), 0, 255);
+	mv = clamp_val(mv, 0, ULONG_MAX / 256);
+	return DIV_ROUND_CLOSEST(clamp_val(mv * 256, 0, range * 255), range);
 }
 
 static inline int ADC_TO_CURR(int adc, int gain)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/max31722.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/max31722.c
@@ -6,7 +6,6 @@
  * Copyright (c) 2016, Intel Corporation.
  */
 
-#include <linux/acpi.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
 #include <linux/kernel.h>
@@ -133,20 +132,12 @@
 	{"max31723", 0},
 	{}
 };
-
-static const struct acpi_device_id __maybe_unused max31722_acpi_id[] = {
-	{"MAX31722", 0},
-	{"MAX31723", 0},
-	{}
-};
-
 MODULE_DEVICE_TABLE(spi, max31722_spi_id);
 
 static struct spi_driver max31722_driver = {
 	.driver = {
 		.name = "max31722",
 		.pm = &max31722_pm_ops,
-		.acpi_match_table = ACPI_PTR(max31722_acpi_id),
 	},
 	.probe =            max31722_probe,
 	.remove =           max31722_remove,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/max31790.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/max31790.c
@@ -27,6 +27,7 @@
 
 /* Fan Config register bits */
 #define MAX31790_FAN_CFG_RPM_MODE	0x80
+#define MAX31790_FAN_CFG_CTRL_MON	0x10
 #define MAX31790_FAN_CFG_TACH_INPUT_EN	0x08
 #define MAX31790_FAN_CFG_TACH_INPUT	0x01
 
@@ -104,7 +105,7 @@
 				data->tach[NR_CHANNEL + i] = rv;
 			} else {
 				rv = i2c_smbus_read_word_swapped(client,
-						MAX31790_REG_PWMOUT(i));
+						MAX31790_REG_PWM_DUTY_CYCLE(i));
 				if (rv < 0)
 					goto abort;
 				data->pwm[i] = rv;
@@ -170,7 +171,7 @@
 
 	switch (attr) {
 	case hwmon_fan_input:
-		sr = get_tach_period(data->fan_dynamics[channel]);
+		sr = get_tach_period(data->fan_dynamics[channel % NR_CHANNEL]);
 		rpm = RPM_FROM_REG(data->tach[channel], sr);
 		*val = rpm;
 		return 0;
@@ -271,12 +272,12 @@
 		*val = data->pwm[channel] >> 8;
 		return 0;
 	case hwmon_pwm_enable:
-		if (fan_config & MAX31790_FAN_CFG_RPM_MODE)
+		if (fan_config & MAX31790_FAN_CFG_CTRL_MON)
+			*val = 0;
+		else if (fan_config & MAX31790_FAN_CFG_RPM_MODE)
 			*val = 2;
-		else if (fan_config & MAX31790_FAN_CFG_TACH_INPUT_EN)
-			*val = 1;
 		else
-			*val = 0;
+			*val = 1;
 		return 0;
 	default:
 		return -EOPNOTSUPP;
@@ -299,31 +300,41 @@
 			err = -EINVAL;
 			break;
 		}
-		data->pwm[channel] = val << 8;
+		data->valid = false;
 		err = i2c_smbus_write_word_swapped(client,
 						   MAX31790_REG_PWMOUT(channel),
-						   data->pwm[channel]);
+						   val << 8);
 		break;
 	case hwmon_pwm_enable:
 		fan_config = data->fan_config[channel];
 		if (val == 0) {
-			fan_config &= ~(MAX31790_FAN_CFG_TACH_INPUT_EN |
-					MAX31790_FAN_CFG_RPM_MODE);
+			fan_config |= MAX31790_FAN_CFG_CTRL_MON;
+			/*
+			 * Disable RPM mode; otherwise disabling fan speed
+			 * monitoring is not possible.
+			 */
+			fan_config &= ~MAX31790_FAN_CFG_RPM_MODE;
 		} else if (val == 1) {
-			fan_config = (fan_config |
-				      MAX31790_FAN_CFG_TACH_INPUT_EN) &
-				     ~MAX31790_FAN_CFG_RPM_MODE;
+			fan_config &= ~(MAX31790_FAN_CFG_CTRL_MON | MAX31790_FAN_CFG_RPM_MODE);
 		} else if (val == 2) {
-			fan_config |= MAX31790_FAN_CFG_TACH_INPUT_EN |
-				      MAX31790_FAN_CFG_RPM_MODE;
+			fan_config &= ~MAX31790_FAN_CFG_CTRL_MON;
+			/*
+			 * The chip sets MAX31790_FAN_CFG_TACH_INPUT_EN on its
+			 * own if MAX31790_FAN_CFG_RPM_MODE is set.
+			 * Do it here as well to reflect the actual register
+			 * value in the cache.
+			 */
+			fan_config |= (MAX31790_FAN_CFG_RPM_MODE | MAX31790_FAN_CFG_TACH_INPUT_EN);
 		} else {
 			err = -EINVAL;
 			break;
 		}
-		data->fan_config[channel] = fan_config;
-		err = i2c_smbus_write_byte_data(client,
-					MAX31790_REG_FAN_CONFIG(channel),
-					fan_config);
+		if (fan_config != data->fan_config[channel]) {
+			err = i2c_smbus_write_byte_data(client, MAX31790_REG_FAN_CONFIG(channel),
+							fan_config);
+			if (!err)
+				data->fan_config[channel] = fan_config;
+		}
 		break;
 	default:
 		err = -EOPNOTSUPP;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/max6697.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/max6697.c
@@ -38,8 +38,9 @@
  * Map device tree / platform data register bit map to chip bit map.
  * Applies to alert register and over-temperature register.
  */
-#define MAX6697_MAP_BITS(reg)	((((reg) & 0x7e) >> 1) | \
+#define MAX6697_ALERT_MAP_BITS(reg)	((((reg) & 0x7e) >> 1) | \
 				 (((reg) & 0x01) << 6) | ((reg) & 0x80))
+#define MAX6697_OVERT_MAP_BITS(reg) (((reg) >> 1) | (((reg) & 0x01) << 7))
 
 #define MAX6697_REG_STAT(n)		(0x44 + (n))
 
@@ -304,6 +305,7 @@
 		return ret;
 
 	mutex_lock(&data->update_lock);
+	temp = clamp_val(temp, -1000000, 1000000);	/* prevent underflow */
 	temp = DIV_ROUND_CLOSEST(temp, 1000) + data->temp_offset;
 	temp = clamp_val(temp, 0, data->type == max6581 ? 255 : 127);
 	data->temp[nr][index] = temp;
@@ -357,14 +359,14 @@
 static SENSOR_DEVICE_ATTR_RO(temp7_max_alarm, alarm, 21);
 static SENSOR_DEVICE_ATTR_RO(temp8_max_alarm, alarm, 23);
 
-static SENSOR_DEVICE_ATTR_RO(temp1_crit_alarm, alarm, 14);
+static SENSOR_DEVICE_ATTR_RO(temp1_crit_alarm, alarm, 15);
 static SENSOR_DEVICE_ATTR_RO(temp2_crit_alarm, alarm, 8);
 static SENSOR_DEVICE_ATTR_RO(temp3_crit_alarm, alarm, 9);
 static SENSOR_DEVICE_ATTR_RO(temp4_crit_alarm, alarm, 10);
 static SENSOR_DEVICE_ATTR_RO(temp5_crit_alarm, alarm, 11);
 static SENSOR_DEVICE_ATTR_RO(temp6_crit_alarm, alarm, 12);
 static SENSOR_DEVICE_ATTR_RO(temp7_crit_alarm, alarm, 13);
-static SENSOR_DEVICE_ATTR_RO(temp8_crit_alarm, alarm, 15);
+static SENSOR_DEVICE_ATTR_RO(temp8_crit_alarm, alarm, 14);
 
 static SENSOR_DEVICE_ATTR_RO(temp2_fault, alarm, 1);
 static SENSOR_DEVICE_ATTR_RO(temp3_fault, alarm, 2);
@@ -562,12 +564,12 @@
 		return ret;
 
 	ret = i2c_smbus_write_byte_data(client, MAX6697_REG_ALERT_MASK,
-					MAX6697_MAP_BITS(pdata->alert_mask));
+				MAX6697_ALERT_MAP_BITS(pdata->alert_mask));
 	if (ret < 0)
 		return ret;
 
 	ret = i2c_smbus_write_byte_data(client, MAX6697_REG_OVERT_MASK,
-				MAX6697_MAP_BITS(pdata->over_temperature_mask));
+			MAX6697_OVERT_MAP_BITS(pdata->over_temperature_mask));
 	if (ret < 0)
 		return ret;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/mlxreg-fan.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/mlxreg-fan.c
@@ -127,6 +127,12 @@
 			if (err)
 				return err;
 
+			if (MLXREG_FAN_GET_FAULT(regval, tacho->mask)) {
+				/* FAN is broken - return zero for FAN speed. */
+				*val = 0;
+				return 0;
+			}
+
 			*val = MLXREG_FAN_GET_RPM(regval, fan->divider,
 						  fan->samples);
 			break;
@@ -291,8 +297,8 @@
 {
 	struct mlxreg_fan *fan = cdev->devdata;
 	unsigned long cur_state;
+	int i, config = 0;
 	u32 regval;
-	int i;
 	int err;
 
 	/*
@@ -305,6 +311,12 @@
 	 * overwritten.
 	 */
 	if (state >= MLXREG_FAN_SPEED_MIN && state <= MLXREG_FAN_SPEED_MAX) {
+		/*
+		 * This is configuration change, which is only supported through sysfs.
+		 * For configuration non-zero value is to be returned to avoid thermal
+		 * statistics update.
+		 */
+		config = 1;
 		state -= MLXREG_FAN_MAX_STATE;
 		for (i = 0; i < state; i++)
 			fan->cooling_levels[i] = state;
@@ -319,7 +331,7 @@
 
 		cur_state = MLXREG_FAN_PWM_DUTY2STATE(regval);
 		if (state < cur_state)
-			return 0;
+			return config;
 
 		state = cur_state;
 	}
@@ -335,7 +347,7 @@
 		dev_err(fan->dev, "Failed to write PWM duty\n");
 		return err;
 	}
-	return 0;
+	return config;
 }
 
 static const struct thermal_cooling_device_ops mlxreg_fan_cooling_ops = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/nct6775.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/nct6775.c
@@ -420,8 +420,8 @@
 static const u16 NCT6776_REG_TOLERANCE_H[] = {
 	0x10c, 0x20c, 0x30c, 0x80c, 0x90c, 0xa0c, 0xb0c };
 
-static const u8 NCT6776_REG_PWM_MODE[] = { 0x04, 0, 0, 0, 0, 0 };
-static const u8 NCT6776_PWM_MODE_MASK[] = { 0x01, 0, 0, 0, 0, 0 };
+static const u8 NCT6776_REG_PWM_MODE[] = { 0x04, 0, 0, 0, 0, 0, 0 };
+static const u8 NCT6776_PWM_MODE_MASK[] = { 0x01, 0, 0, 0, 0, 0, 0 };
 
 static const u16 NCT6776_REG_FAN_MIN[] = {
 	0x63a, 0x63c, 0x63e, 0x640, 0x642, 0x64a, 0x64c };
@@ -786,13 +786,13 @@
 	"Agent1 Dimm1",
 	"BYTE_TEMP0",
 	"BYTE_TEMP1",
-	"",
-	"",
+	"PECI Agent 0 Calibration",	/* undocumented */
+	"PECI Agent 1 Calibration",	/* undocumented */
 	"",
 	"Virtual_TEMP"
 };
 
-#define NCT6798_TEMP_MASK	0x8fff0ffe
+#define NCT6798_TEMP_MASK	0xbfff0ffe
 #define NCT6798_VIRT_TEMP_MASK	0x80000c00
 
 /* NCT6102D/NCT6106D specific data */
@@ -2374,7 +2374,7 @@
 	if (err < 0)
 		return err;
 
-	val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -128, 127);
+	val = DIV_ROUND_CLOSEST(clamp_val(val, -128000, 127000), 1000);
 
 	mutex_lock(&data->update_lock);
 	data->temp_offset[nr] = val;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/nct7802.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/nct7802.c
@@ -23,8 +23,8 @@
 static const u8 REG_VOLTAGE[5] = { 0x09, 0x0a, 0x0c, 0x0d, 0x0e };
 
 static const u8 REG_VOLTAGE_LIMIT_LSB[2][5] = {
-	{ 0x40, 0x00, 0x42, 0x44, 0x46 },
-	{ 0x3f, 0x00, 0x41, 0x43, 0x45 },
+	{ 0x46, 0x00, 0x40, 0x42, 0x44 },
+	{ 0x45, 0x00, 0x3f, 0x41, 0x43 },
 };
 
 static const u8 REG_VOLTAGE_LIMIT_MSB[5] = { 0x48, 0x00, 0x47, 0x47, 0x48 };
@@ -58,6 +58,8 @@
 struct nct7802_data {
 	struct regmap *regmap;
 	struct mutex access_lock; /* for multi-byte read and write operations */
+	u8 in_status;
+	struct mutex in_alarm_lock;
 };
 
 static ssize_t temp_type_show(struct device *dev,
@@ -368,6 +370,66 @@
 	return err ? : count;
 }
 
+static ssize_t in_alarm_show(struct device *dev, struct device_attribute *attr,
+			     char *buf)
+{
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	struct nct7802_data *data = dev_get_drvdata(dev);
+	int volt, min, max, ret;
+	unsigned int val;
+
+	mutex_lock(&data->in_alarm_lock);
+
+	/*
+	 * The SMI Voltage status register is the only register giving a status
+	 * for voltages. A bit is set for each input crossing a threshold, in
+	 * both direction, but the "inside" or "outside" limits info is not
+	 * available. Also this register is cleared on read.
+	 * Note: this is not explicitly spelled out in the datasheet, but
+	 * from experiment.
+	 * To deal with this we use a status cache with one validity bit and
+	 * one status bit for each input. Validity is cleared at startup and
+	 * each time the register reports a change, and the status is processed
+	 * by software based on current input value and limits.
+	 */
+	ret = regmap_read(data->regmap, 0x1e, &val); /* SMI Voltage status */
+	if (ret < 0)
+		goto abort;
+
+	/* invalidate cached status for all inputs crossing a threshold */
+	data->in_status &= ~((val & 0x0f) << 4);
+
+	/* if cached status for requested input is invalid, update it */
+	if (!(data->in_status & (0x10 << sattr->index))) {
+		ret = nct7802_read_voltage(data, sattr->nr, 0);
+		if (ret < 0)
+			goto abort;
+		volt = ret;
+
+		ret = nct7802_read_voltage(data, sattr->nr, 1);
+		if (ret < 0)
+			goto abort;
+		min = ret;
+
+		ret = nct7802_read_voltage(data, sattr->nr, 2);
+		if (ret < 0)
+			goto abort;
+		max = ret;
+
+		if (volt < min || volt > max)
+			data->in_status |= (1 << sattr->index);
+		else
+			data->in_status &= ~(1 << sattr->index);
+
+		data->in_status |= 0x10 << sattr->index;
+	}
+
+	ret = sprintf(buf, "%u\n", !!(data->in_status & (1 << sattr->index)));
+abort:
+	mutex_unlock(&data->in_alarm_lock);
+	return ret;
+}
+
 static ssize_t temp_show(struct device *dev, struct device_attribute *attr,
 			 char *buf)
 {
@@ -646,7 +708,7 @@
 	if (index >= 38 && index < 46 && !(reg & 0x01))		/* PECI 0 */
 		return 0;
 
-	if (index >= 0x46 && (!(reg & 0x02)))			/* PECI 1 */
+	if (index >= 46 && !(reg & 0x02))			/* PECI 1 */
 		return 0;
 
 	return attr->mode;
@@ -660,7 +722,7 @@
 static SENSOR_DEVICE_ATTR_2_RO(in0_input, in, 0, 0);
 static SENSOR_DEVICE_ATTR_2_RW(in0_min, in, 0, 1);
 static SENSOR_DEVICE_ATTR_2_RW(in0_max, in, 0, 2);
-static SENSOR_DEVICE_ATTR_2_RO(in0_alarm, alarm, 0x1e, 3);
+static SENSOR_DEVICE_ATTR_2_RO(in0_alarm, in_alarm, 0, 3);
 static SENSOR_DEVICE_ATTR_2_RW(in0_beep, beep, 0x5a, 3);
 
 static SENSOR_DEVICE_ATTR_2_RO(in1_input, in, 1, 0);
@@ -668,19 +730,19 @@
 static SENSOR_DEVICE_ATTR_2_RO(in2_input, in, 2, 0);
 static SENSOR_DEVICE_ATTR_2_RW(in2_min, in, 2, 1);
 static SENSOR_DEVICE_ATTR_2_RW(in2_max, in, 2, 2);
-static SENSOR_DEVICE_ATTR_2_RO(in2_alarm, alarm, 0x1e, 0);
+static SENSOR_DEVICE_ATTR_2_RO(in2_alarm, in_alarm, 2, 0);
 static SENSOR_DEVICE_ATTR_2_RW(in2_beep, beep, 0x5a, 0);
 
 static SENSOR_DEVICE_ATTR_2_RO(in3_input, in, 3, 0);
 static SENSOR_DEVICE_ATTR_2_RW(in3_min, in, 3, 1);
 static SENSOR_DEVICE_ATTR_2_RW(in3_max, in, 3, 2);
-static SENSOR_DEVICE_ATTR_2_RO(in3_alarm, alarm, 0x1e, 1);
+static SENSOR_DEVICE_ATTR_2_RO(in3_alarm, in_alarm, 3, 1);
 static SENSOR_DEVICE_ATTR_2_RW(in3_beep, beep, 0x5a, 1);
 
 static SENSOR_DEVICE_ATTR_2_RO(in4_input, in, 4, 0);
 static SENSOR_DEVICE_ATTR_2_RW(in4_min, in, 4, 1);
 static SENSOR_DEVICE_ATTR_2_RW(in4_max, in, 4, 2);
-static SENSOR_DEVICE_ATTR_2_RO(in4_alarm, alarm, 0x1e, 2);
+static SENSOR_DEVICE_ATTR_2_RO(in4_alarm, in_alarm, 4, 2);
 static SENSOR_DEVICE_ATTR_2_RW(in4_beep, beep, 0x5a, 2);
 
 static struct attribute *nct7802_in_attrs[] = {
@@ -1011,6 +1073,7 @@
 		return PTR_ERR(data->regmap);
 
 	mutex_init(&data->access_lock);
+	mutex_init(&data->in_alarm_lock);
 
 	ret = nct7802_init_chip(data);
 	if (ret < 0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/nct7904.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/nct7904.c
@@ -197,7 +197,7 @@
 		if (ret < 0)
 			return ret;
 		cnt = ((ret & 0xff00) >> 3) | (ret & 0x1f);
-		if (cnt == 0x1fff)
+		if (cnt == 0 || cnt == 0x1fff)
 			rpm = 0;
 		else
 			rpm = 1350000 / cnt;
@@ -209,7 +209,7 @@
 		if (ret < 0)
 			return ret;
 		cnt = ((ret & 0xff00) >> 3) | (ret & 0x1f);
-		if (cnt == 0x1fff)
+		if (cnt == 0 || cnt == 0x1fff)
 			rpm = 0;
 		else
 			rpm = 1350000 / cnt;
@@ -356,6 +356,7 @@
 	struct nct7904_data *data = dev_get_drvdata(dev);
 	int ret, temp;
 	unsigned int reg1, reg2, reg3;
+	s8 temps;
 
 	switch (attr) {
 	case hwmon_temp_input:
@@ -461,7 +462,8 @@
 
 	if (ret < 0)
 		return ret;
-	*val = ret * 1000;
+	temps = ret;
+	*val = temps * 1000;
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/ntc_thermistor.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/ntc_thermistor.c
@@ -58,6 +58,7 @@
 	[NTC_NCP21WB473]      = { "ncp21wb473",      TYPE_NCPXXWB473 },
 	[NTC_LAST]            = { },
 };
+MODULE_DEVICE_TABLE(platform, ntc_thermistor_id);
 
 /*
  * A compensation table should be sorted by the values of .ohm
@@ -176,40 +177,40 @@
 };
 
 static const struct ntc_compensation ncpXXxh103[] = {
-	{ .temp_c	= -40, .ohm	= 247565 },
-	{ .temp_c	= -35, .ohm	= 181742 },
-	{ .temp_c	= -30, .ohm	= 135128 },
-	{ .temp_c	= -25, .ohm	= 101678 },
-	{ .temp_c	= -20, .ohm	= 77373 },
-	{ .temp_c	= -15, .ohm	= 59504 },
-	{ .temp_c	= -10, .ohm	= 46222 },
-	{ .temp_c	= -5, .ohm	= 36244 },
-	{ .temp_c	= 0, .ohm	= 28674 },
-	{ .temp_c	= 5, .ohm	= 22878 },
-	{ .temp_c	= 10, .ohm	= 18399 },
-	{ .temp_c	= 15, .ohm	= 14910 },
-	{ .temp_c	= 20, .ohm	= 12169 },
+	{ .temp_c	= -40, .ohm	= 195652 },
+	{ .temp_c	= -35, .ohm	= 148171 },
+	{ .temp_c	= -30, .ohm	= 113347 },
+	{ .temp_c	= -25, .ohm	= 87559 },
+	{ .temp_c	= -20, .ohm	= 68237 },
+	{ .temp_c	= -15, .ohm	= 53650 },
+	{ .temp_c	= -10, .ohm	= 42506 },
+	{ .temp_c	= -5, .ohm	= 33892 },
+	{ .temp_c	= 0, .ohm	= 27219 },
+	{ .temp_c	= 5, .ohm	= 22021 },
+	{ .temp_c	= 10, .ohm	= 17926 },
+	{ .temp_c	= 15, .ohm	= 14674 },
+	{ .temp_c	= 20, .ohm	= 12081 },
 	{ .temp_c	= 25, .ohm	= 10000 },
-	{ .temp_c	= 30, .ohm	= 8271 },
-	{ .temp_c	= 35, .ohm	= 6883 },
-	{ .temp_c	= 40, .ohm	= 5762 },
-	{ .temp_c	= 45, .ohm	= 4851 },
-	{ .temp_c	= 50, .ohm	= 4105 },
-	{ .temp_c	= 55, .ohm	= 3492 },
-	{ .temp_c	= 60, .ohm	= 2985 },
-	{ .temp_c	= 65, .ohm	= 2563 },
-	{ .temp_c	= 70, .ohm	= 2211 },
-	{ .temp_c	= 75, .ohm	= 1915 },
-	{ .temp_c	= 80, .ohm	= 1666 },
-	{ .temp_c	= 85, .ohm	= 1454 },
-	{ .temp_c	= 90, .ohm	= 1275 },
-	{ .temp_c	= 95, .ohm	= 1121 },
-	{ .temp_c	= 100, .ohm	= 990 },
-	{ .temp_c	= 105, .ohm	= 876 },
-	{ .temp_c	= 110, .ohm	= 779 },
-	{ .temp_c	= 115, .ohm	= 694 },
-	{ .temp_c	= 120, .ohm	= 620 },
-	{ .temp_c	= 125, .ohm	= 556 },
+	{ .temp_c	= 30, .ohm	= 8315 },
+	{ .temp_c	= 35, .ohm	= 6948 },
+	{ .temp_c	= 40, .ohm	= 5834 },
+	{ .temp_c	= 45, .ohm	= 4917 },
+	{ .temp_c	= 50, .ohm	= 4161 },
+	{ .temp_c	= 55, .ohm	= 3535 },
+	{ .temp_c	= 60, .ohm	= 3014 },
+	{ .temp_c	= 65, .ohm	= 2586 },
+	{ .temp_c	= 70, .ohm	= 2228 },
+	{ .temp_c	= 75, .ohm	= 1925 },
+	{ .temp_c	= 80, .ohm	= 1669 },
+	{ .temp_c	= 85, .ohm	= 1452 },
+	{ .temp_c	= 90, .ohm	= 1268 },
+	{ .temp_c	= 95, .ohm	= 1110 },
+	{ .temp_c	= 100, .ohm	= 974 },
+	{ .temp_c	= 105, .ohm	= 858 },
+	{ .temp_c	= 110, .ohm	= 758 },
+	{ .temp_c	= 115, .ohm	= 672 },
+	{ .temp_c	= 120, .ohm	= 596 },
+	{ .temp_c	= 125, .ohm	= 531 },
 };
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/occ/common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/occ/common.c
@@ -209,9 +209,9 @@
 		return rc;
 
 	/* limit the maximum rate of polling the OCC */
-	if (time_after(jiffies, occ->last_update + OCC_UPDATE_FREQUENCY)) {
+	if (time_after(jiffies, occ->next_update)) {
 		rc = occ_poll(occ);
-		occ->last_update = jiffies;
+		occ->next_update = jiffies + OCC_UPDATE_FREQUENCY;
 	} else {
 		rc = occ->last_error;
 	}
@@ -1089,6 +1089,7 @@
 		return rc;
 	}
 
+	occ->next_update = jiffies + OCC_UPDATE_FREQUENCY;
 	occ_parse_poll_response(occ);
 
 	rc = occ_setup_sensor_attrs(occ);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/occ/common.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/occ/common.h
@@ -99,7 +99,7 @@
 	u8 poll_cmd_data;		/* to perform OCC poll command */
 	int (*send_cmd)(struct occ *occ, u8 *cmd);
 
-	unsigned long last_update;
+	unsigned long next_update;
 	struct mutex lock;		/* lock OCC access */
 
 	struct device *hwmon;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/pmbus/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/pmbus/Kconfig
@@ -199,6 +199,26 @@
 	  This driver can also be built as a module. If so, the module will
 	  be called tps53679.
 
+config SENSORS_TPS544
+	tristate "TI TPS544"
+	help
+	  If you say yes here you get hardware monitoring support for Texas
+	  Instruments TPS544.
+
+	  This driver can also be built as a module. If so, the module will
+	  be called tps544.
+
+config SENSORS_TPS544_REGULATOR
+	bool "Regulator support for TPS544"
+	depends on SENSORS_TPS544
+	select REGULATOR
+	help
+	  If you say yes here you get regulator support for Texas Instruments
+	  TPS544.
+
+	  This driver is dependent on TPS544 sensor and it can also be built
+	  as a module.
+
 config SENSORS_UCD9000
 	tristate "TI UCD90120, UCD90124, UCD90160, UCD9090, UCD90910"
 	help
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/pmbus/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/pmbus/Makefile
@@ -23,6 +23,7 @@
 obj-$(CONFIG_SENSORS_PXE1610)	+= pxe1610.o
 obj-$(CONFIG_SENSORS_TPS40422)	+= tps40422.o
 obj-$(CONFIG_SENSORS_TPS53679)	+= tps53679.o
+obj-$(CONFIG_SENSORS_TPS544)	+= tps544.o
 obj-$(CONFIG_SENSORS_UCD9000)	+= ucd9000.o
 obj-$(CONFIG_SENSORS_UCD9200)	+= ucd9200.o
 obj-$(CONFIG_SENSORS_ZL6100)	+= zl6100.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/pmbus/adm1275.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/pmbus/adm1275.c
@@ -454,6 +454,7 @@
 static int adm1275_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
+	s32 (*config_read_fn)(const struct i2c_client *client, u8 reg);
 	u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1];
 	int config, device_config;
 	int ret;
@@ -499,11 +500,16 @@
 			   "Device mismatch: Configured %s, detected %s\n",
 			   id->name, mid->name);
 
-	config = i2c_smbus_read_byte_data(client, ADM1275_PMON_CONFIG);
+	if (mid->driver_data == adm1272 || mid->driver_data == adm1278 ||
+	    mid->driver_data == adm1293 || mid->driver_data == adm1294)
+		config_read_fn = i2c_smbus_read_word_data;
+	else
+		config_read_fn = i2c_smbus_read_byte_data;
+	config = config_read_fn(client, ADM1275_PMON_CONFIG);
 	if (config < 0)
 		return config;
 
-	device_config = i2c_smbus_read_byte_data(client, ADM1275_DEVICE_CONFIG);
+	device_config = config_read_fn(client, ADM1275_DEVICE_CONFIG);
 	if (device_config < 0)
 		return device_config;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/pmbus/ibm-cffps.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/pmbus/ibm-cffps.c
@@ -39,9 +39,13 @@
 #define CFFPS_MFR_VAUX_FAULT			BIT(6)
 #define CFFPS_MFR_CURRENT_SHARE_WARNING		BIT(7)
 
+/*
+ * LED off state actually relinquishes LED control to PSU firmware, so it can
+ * turn on the LED for faults.
+ */
+#define CFFPS_LED_OFF				0
 #define CFFPS_LED_BLINK				BIT(0)
 #define CFFPS_LED_ON				BIT(1)
-#define CFFPS_LED_OFF				BIT(2)
 #define CFFPS_BLINK_RATE_MS			250
 
 enum {
@@ -292,28 +296,38 @@
 	return rc;
 }
 
-static void ibm_cffps_led_brightness_set(struct led_classdev *led_cdev,
-					 enum led_brightness brightness)
+static int ibm_cffps_led_brightness_set(struct led_classdev *led_cdev,
+					enum led_brightness brightness)
 {
 	int rc;
+	u8 next_led_state;
 	struct ibm_cffps *psu = container_of(led_cdev, struct ibm_cffps, led);
 
 	if (brightness == LED_OFF) {
-		psu->led_state = CFFPS_LED_OFF;
+		next_led_state = CFFPS_LED_OFF;
 	} else {
 		brightness = LED_FULL;
+
 		if (psu->led_state != CFFPS_LED_BLINK)
-			psu->led_state = CFFPS_LED_ON;
+			next_led_state = CFFPS_LED_ON;
+		else
+			next_led_state = CFFPS_LED_BLINK;
 	}
 
+	dev_dbg(&psu->client->dev, "LED brightness set: %d. Command: %d.\n",
+		brightness, next_led_state);
+
 	pmbus_set_page(psu->client, 0);
 
 	rc = i2c_smbus_write_byte_data(psu->client, CFFPS_SYS_CONFIG_CMD,
-				       psu->led_state);
+				       next_led_state);
 	if (rc < 0)
-		return;
+		return rc;
 
+	psu->led_state = next_led_state;
 	led_cdev->brightness = brightness;
+
+	return 0;
 }
 
 static int ibm_cffps_led_blink_set(struct led_classdev *led_cdev,
@@ -323,10 +337,7 @@
 	int rc;
 	struct ibm_cffps *psu = container_of(led_cdev, struct ibm_cffps, led);
 
-	psu->led_state = CFFPS_LED_BLINK;
-
-	if (led_cdev->brightness == LED_OFF)
-		return 0;
+	dev_dbg(&psu->client->dev, "LED blink set.\n");
 
 	pmbus_set_page(psu->client, 0);
 
@@ -335,6 +346,8 @@
 	if (rc < 0)
 		return rc;
 
+	psu->led_state = CFFPS_LED_BLINK;
+	led_cdev->brightness = LED_FULL;
 	*delay_on = CFFPS_BLINK_RATE_MS;
 	*delay_off = CFFPS_BLINK_RATE_MS;
 
@@ -351,7 +364,7 @@
 		 client->addr);
 	psu->led.name = psu->led_name;
 	psu->led.max_brightness = LED_FULL;
-	psu->led.brightness_set = ibm_cffps_led_brightness_set;
+	psu->led.brightness_set_blocking = ibm_cffps_led_brightness_set;
 	psu->led.blink_set = ibm_cffps_led_blink_set;
 
 	rc = devm_led_classdev_register(dev, &psu->led);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/pmbus/lm25066.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/pmbus/lm25066.c
@@ -51,26 +51,31 @@
 #define PSC_CURRENT_IN_L	(PSC_NUM_CLASSES)
 #define PSC_POWER_L		(PSC_NUM_CLASSES + 1)
 
-static struct __coeff lm25066_coeff[6][PSC_NUM_CLASSES + 2] = {
+static struct __coeff lm25066_coeff[][PSC_NUM_CLASSES + 2] = {
 	[lm25056] = {
 		[PSC_VOLTAGE_IN] = {
 			.m = 16296,
+			.b = 1343,
 			.R = -2,
 		},
 		[PSC_CURRENT_IN] = {
 			.m = 13797,
+			.b = -1833,
 			.R = -2,
 		},
 		[PSC_CURRENT_IN_L] = {
 			.m = 6726,
+			.b = -537,
 			.R = -2,
 		},
 		[PSC_POWER] = {
 			.m = 5501,
+			.b = -2908,
 			.R = -3,
 		},
 		[PSC_POWER_L] = {
 			.m = 26882,
+			.b = -5646,
 			.R = -4,
 		},
 		[PSC_TEMPERATURE] = {
@@ -82,26 +87,32 @@
 	[lm25066] = {
 		[PSC_VOLTAGE_IN] = {
 			.m = 22070,
+			.b = -1800,
 			.R = -2,
 		},
 		[PSC_VOLTAGE_OUT] = {
 			.m = 22070,
+			.b = -1800,
 			.R = -2,
 		},
 		[PSC_CURRENT_IN] = {
 			.m = 13661,
+			.b = -5200,
 			.R = -2,
 		},
 		[PSC_CURRENT_IN_L] = {
 			.m = 6852,
+			.b = -3100,
 			.R = -2,
 		},
 		[PSC_POWER] = {
 			.m = 736,
+			.b = -3300,
 			.R = -2,
 		},
 		[PSC_POWER_L] = {
 			.m = 369,
+			.b = -1900,
 			.R = -2,
 		},
 		[PSC_TEMPERATURE] = {
@@ -111,26 +122,32 @@
 	[lm5064] = {
 		[PSC_VOLTAGE_IN] = {
 			.m = 4611,
+			.b = -642,
 			.R = -2,
 		},
 		[PSC_VOLTAGE_OUT] = {
 			.m = 4621,
+			.b = 423,
 			.R = -2,
 		},
 		[PSC_CURRENT_IN] = {
 			.m = 10742,
+			.b = 1552,
 			.R = -2,
 		},
 		[PSC_CURRENT_IN_L] = {
 			.m = 5456,
+			.b = 2118,
 			.R = -2,
 		},
 		[PSC_POWER] = {
 			.m = 1204,
+			.b = 8524,
 			.R = -3,
 		},
 		[PSC_POWER_L] = {
 			.m = 612,
+			.b = 11202,
 			.R = -3,
 		},
 		[PSC_TEMPERATURE] = {
@@ -140,26 +157,32 @@
 	[lm5066] = {
 		[PSC_VOLTAGE_IN] = {
 			.m = 4587,
+			.b = -1200,
 			.R = -2,
 		},
 		[PSC_VOLTAGE_OUT] = {
 			.m = 4587,
+			.b = -2400,
 			.R = -2,
 		},
 		[PSC_CURRENT_IN] = {
 			.m = 10753,
+			.b = -1200,
 			.R = -2,
 		},
 		[PSC_CURRENT_IN_L] = {
 			.m = 5405,
+			.b = -600,
 			.R = -2,
 		},
 		[PSC_POWER] = {
 			.m = 1204,
+			.b = -6000,
 			.R = -3,
 		},
 		[PSC_POWER_L] = {
 			.m = 605,
+			.b = -8000,
 			.R = -3,
 		},
 		[PSC_TEMPERATURE] = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/pmbus/ltc2978.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/pmbus/ltc2978.c
@@ -82,8 +82,8 @@
 
 #define LTC_POLL_TIMEOUT		100	/* in milli-seconds */
 
-#define LTC_NOT_BUSY			BIT(5)
-#define LTC_NOT_PENDING			BIT(4)
+#define LTC_NOT_BUSY			BIT(6)
+#define LTC_NOT_PENDING			BIT(5)
 
 /*
  * LTC2978 clears peak data whenever the CLEAR_FAULTS command is executed, which
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/pmbus/max34440.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/pmbus/max34440.c
@@ -387,7 +387,6 @@
 		.func[18] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
 		.func[19] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
 		.func[20] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
-		.read_byte_data = max34440_read_byte_data,
 		.read_word_data = max34440_read_word_data,
 		.write_word_data = max34440_write_word_data,
 	},
@@ -418,7 +417,6 @@
 		.func[15] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
 		.func[16] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
 		.func[17] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
-		.read_byte_data = max34440_read_byte_data,
 		.read_word_data = max34440_read_word_data,
 		.write_word_data = max34440_write_word_data,
 	},
@@ -454,7 +452,6 @@
 		.func[19] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
 		.func[20] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
 		.func[21] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
-		.read_byte_data = max34440_read_byte_data,
 		.read_word_data = max34440_read_word_data,
 		.write_word_data = max34440_write_word_data,
 	},
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/pmbus/pmbus.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/pmbus/pmbus.c
@@ -101,6 +101,8 @@
 		if (pmbus_check_byte_register(client, 0, PMBUS_PAGE)) {
 			int page;
 
+			info->pages = PMBUS_PAGES;
+
 			for (page = 1; page < PMBUS_PAGES; page++) {
 				if (pmbus_set_page(client, page) < 0)
 					break;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/pmbus/pmbus.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/pmbus/pmbus.h
@@ -292,6 +292,7 @@
 /*
  * STATUS_VOUT, STATUS_INPUT
  */
+#define PB_VOLTAGE_VIN_OFF		BIT(3)
 #define PB_VOLTAGE_UV_FAULT		BIT(4)
 #define PB_VOLTAGE_UV_WARNING		BIT(5)
 #define PB_VOLTAGE_OV_WARNING		BIT(6)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/pmbus/pmbus_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/pmbus/pmbus_core.c
@@ -1324,7 +1324,7 @@
 		.reg = PMBUS_VIN_UV_FAULT_LIMIT,
 		.attr = "lcrit",
 		.alarm = "lcrit_alarm",
-		.sbit = PB_VOLTAGE_UV_FAULT,
+		.sbit = PB_VOLTAGE_UV_FAULT | PB_VOLTAGE_VIN_OFF,
 	}, {
 		.reg = PMBUS_VIN_OV_WARN_LIMIT,
 		.attr = "max",
@@ -2174,10 +2174,14 @@
 {
 	struct device *dev = rdev_get_dev(rdev);
 	struct i2c_client *client = to_i2c_client(dev->parent);
+	struct pmbus_data *data = i2c_get_clientdata(client);
 	u8 page = rdev_get_id(rdev);
 	int ret;
 
+	mutex_lock(&data->update_lock);
 	ret = pmbus_read_byte_data(client, page, PMBUS_OPERATION);
+	mutex_unlock(&data->update_lock);
+
 	if (ret < 0)
 		return ret;
 
@@ -2188,11 +2192,17 @@
 {
 	struct device *dev = rdev_get_dev(rdev);
 	struct i2c_client *client = to_i2c_client(dev->parent);
+	struct pmbus_data *data = i2c_get_clientdata(client);
 	u8 page = rdev_get_id(rdev);
+	int ret;
 
-	return pmbus_update_byte_data(client, page, PMBUS_OPERATION,
-				      PB_OPERATION_CONTROL_ON,
-				      enable ? PB_OPERATION_CONTROL_ON : 0);
+	mutex_lock(&data->update_lock);
+	ret = pmbus_update_byte_data(client, page, PMBUS_OPERATION,
+				     PB_OPERATION_CONTROL_ON,
+				     enable ? PB_OPERATION_CONTROL_ON : 0);
+	mutex_unlock(&data->update_lock);
+
+	return ret;
 }
 
 static int pmbus_regulator_enable(struct regulator_dev *rdev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/pmbus/tps544.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/pmbus/tps544.c
@@ -0,0 +1,364 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * TPS544B25 power regulator driver
+ *
+ * Copyright (C) 2019 Xilinx, Inc.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/regulator/driver.h>
+#include "pmbus.h"
+
+#define TPS544_NUM_PAGES		1
+
+struct tps544_data {
+	struct device *dev;
+	u16 vout_min[TPS544_NUM_PAGES], vout_max[TPS544_NUM_PAGES];
+	struct pmbus_driver_info info;
+};
+
+struct vlut {
+	int vol;
+	u16 vloop;
+	u16 v_ovfault;
+	u16 v_ovwarn;
+	u16 vmax;
+	u16 mfr_vmin;
+	u16 v_uvwarn;
+	u16 v_uvfault;
+};
+
+#if IS_ENABLED(CONFIG_SENSORS_TPS544_REGULATOR)
+#define TPS544_MFR_VOUT_MIN		0xA4
+#define TPS544_MFR_RESTORE_DEF_ALL	0x12
+#define TPS544_MFR_IOUT_CAL_OFFSET	0x39
+
+#define TPS544_VOUTREAD_MULTIPLIER	1950
+#define TPS544_IOUTREAD_MULTIPLIER	62500
+#define TPS544_IOUTREAD_MASK		GENMASK(9, 0)
+
+#define TPS544_VOUT_LIMIT		5300000
+
+#define to_tps544_data(x) container_of(x, struct tps544_data, info)
+
+/*
+ * This currently supports 3 voltage out buckets:
+ * 0.5V to 1.3V
+ * 1.3V to 2.6V
+ * 2.6V to 5.3V
+ * Any requested voltage will be mapped to one of these buckets and
+ * VOUT will be programmed with 0.1V granularity.
+ */
+static const struct vlut tps544_vout[3] = {
+	{500000, 0xF004, 0x0290, 0x0285, 0x0300, 0x0100, 0x00CD, 0x009A},
+	{1300000, 0xF002, 0x059A, 0x0566, 0x0600, 0x0100, 0x0143, 0x0130},
+	{2600000, 0xF001, 0x0B00, 0x0A9A, 0x0A00, 0x0100, 0x0143, 0x0130}
+};
+#endif
+
+static int tps544_read_word_data(struct i2c_client *client, int page, int reg)
+{
+	return pmbus_read_word_data(client, page, reg);
+}
+
+static int tps544_read_byte_data(struct i2c_client *client, int page, int reg)
+{
+	return pmbus_read_byte_data(client, page, reg);
+}
+
+static int tps544_write_byte(struct i2c_client *client, int page, u8 byte)
+{
+	return pmbus_write_byte(client, page, byte);
+}
+
+static int tps544_write_word_data(struct i2c_client *client, int page,
+				  int reg, u16 word)
+{
+	int ret;
+
+	ret = pmbus_write_word_data(client, page, reg, word);
+	/* TODO - Define new PMBUS virtual register entries for these */
+
+	return ret;
+}
+
+#if IS_ENABLED(CONFIG_SENSORS_TPS544_REGULATOR)
+static int tps544_regulator_get_voltage(struct regulator_dev *rdev)
+{
+	struct device *dev = rdev_get_dev(rdev);
+	struct i2c_client *client = to_i2c_client(dev->parent);
+	int page = 0;
+
+	return pmbus_read_word_data(client, page, PMBUS_READ_VOUT);
+}
+
+static int tps544_regulator_set_voltage(struct regulator_dev *rdev, int min_uV,
+					int max_uV, unsigned int *selector)
+{
+	struct device *dev = rdev_get_dev(rdev);
+	struct i2c_client *client = to_i2c_client(dev->parent);
+	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
+	struct tps544_data *data = to_tps544_data(info);
+	int index, page = 0;
+	u16 vout;
+
+	/* voltage will be set close to min value requested */
+	vout = (u16)((min_uV * 512) / 1000000);
+
+	/* Check voltage bucket */
+	if (min_uV >= tps544_vout[2].vol)
+		index = 2;
+	else if (min_uV >= tps544_vout[1].vol)
+		index = 1;
+	else if (min_uV >= tps544_vout[0].vol)
+		index = 0;
+	else
+		return -EINVAL;
+
+	pmbus_write_word_data(client, page, PMBUS_VOUT_SCALE_LOOP,
+			      tps544_vout[index].vloop);
+	/* Use delay after setting scale loop; this is derived from testing */
+	msleep(2000);
+	pmbus_write_word_data(client, page, PMBUS_VOUT_OV_FAULT_LIMIT,
+			      tps544_vout[index].v_ovfault);
+	pmbus_write_word_data(client, page, PMBUS_VOUT_OV_WARN_LIMIT,
+			      tps544_vout[index].v_ovwarn);
+	pmbus_write_word_data(client, page, PMBUS_VOUT_MAX,
+			      tps544_vout[index].vmax);
+	pmbus_write_word_data(client, page, PMBUS_VOUT_COMMAND, vout);
+	tps544_write_word_data(client, page, TPS544_MFR_VOUT_MIN,
+			       tps544_vout[index].mfr_vmin);
+	pmbus_write_word_data(client, page, PMBUS_VOUT_UV_WARN_LIMIT,
+			      tps544_vout[index].v_uvwarn);
+	pmbus_write_word_data(client, page, PMBUS_VOUT_UV_FAULT_LIMIT,
+			      tps544_vout[index].v_uvfault);
+
+	data->vout_min[page] = min_uV;
+	data->vout_max[page] = max_uV;
+
+	return 0;
+}
+
+static ssize_t tps544_setv_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct regulator_dev *rdev = dev_get_drvdata(dev);
+	int vout;
+
+	vout = tps544_regulator_get_voltage(rdev) * TPS544_VOUTREAD_MULTIPLIER;
+	return sprintf(buf, "%d\n", vout);
+}
+
+static ssize_t tps544_setv_store(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	struct regulator_dev *rdev = dev_get_drvdata(dev);
+	int val;
+	int err;
+
+	err = kstrtoint(buf, 0, &val);
+	if (err)
+		return err;
+	if (val > TPS544_VOUT_LIMIT)
+		return -EINVAL;
+
+	err = tps544_regulator_set_voltage(rdev, val, val, NULL);
+	if (err)
+		return err;
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(tps544_setv);
+
+static ssize_t tps544_restorev_store(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev->parent);
+	int err;
+
+	err = pmbus_write_byte(client, 0, TPS544_MFR_RESTORE_DEF_ALL);
+	if (err)
+		return err;
+
+	return count;
+}
+
+static DEVICE_ATTR_WO(tps544_restorev);
+
+static ssize_t tps544_geti_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev->parent);
+	u16 reg_iout;
+
+	reg_iout = pmbus_read_word_data(client, 0, PMBUS_READ_IOUT) &
+			TPS544_IOUTREAD_MASK;
+
+	return sprintf(buf, "%d\n", reg_iout * TPS544_IOUTREAD_MULTIPLIER);
+}
+
+static DEVICE_ATTR_RO(tps544_geti);
+
+static ssize_t tps544_setcali_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev->parent);
+	int reg_cali;
+
+	reg_cali = pmbus_read_word_data(client, 0, TPS544_MFR_IOUT_CAL_OFFSET);
+
+	return sprintf(buf, "Current: 0x%x; Set value in hex to calibrate\n",
+		       reg_cali);
+}
+
+static ssize_t tps544_setcali_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev->parent);
+	u16 val;
+	int err;
+
+	err = kstrtou16(buf, 0x0, &val);
+	if (err)
+		return err;
+
+	err = pmbus_write_word_data(client, 0, TPS544_MFR_IOUT_CAL_OFFSET, val);
+	if (err)
+		return err;
+
+	return (ssize_t)count;
+}
+
+static DEVICE_ATTR_RW(tps544_setcali);
+
+static struct attribute *reg_attrs[] = {
+	&dev_attr_tps544_setv.attr,
+	&dev_attr_tps544_restorev.attr,
+	&dev_attr_tps544_geti.attr,
+	&dev_attr_tps544_setcali.attr,
+	NULL,
+};
+
+ATTRIBUTE_GROUPS(reg);
+
+static const struct regulator_desc tps544_reg_desc[] = {
+	PMBUS_REGULATOR("vout", 0),
+};
+#endif /* CONFIG_SENSORS_TPS544_REGULATOR */
+
+static int tps544_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	unsigned int i;
+	struct device *dev = &client->dev;
+	struct tps544_data *data;
+	struct pmbus_driver_info *info;
+#if IS_ENABLED(CONFIG_SENSORS_TPS544_REGULATOR)
+	int ret;
+	struct regulator_dev *rdev;
+	struct regulator_config rconfig = { };
+#endif
+
+	if (!i2c_check_functionality(client->adapter,
+				     I2C_FUNC_SMBUS_READ_WORD_DATA))
+		return -ENODEV;
+
+	data = devm_kzalloc(dev, sizeof(struct tps544_data),
+			    GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->dev = dev;
+
+	info = &data->info;
+	info->write_word_data = tps544_write_word_data;
+	/* TODO - remove these 3 hooks maybe unnecessary */
+	info->write_byte = tps544_write_byte;
+	info->read_word_data = tps544_read_word_data;
+	info->read_byte_data = tps544_read_byte_data;
+
+	for (i = 0; i < ARRAY_SIZE(data->vout_min); i++)
+		data->vout_min[i] = 0xffff;
+
+	info->pages = TPS544_NUM_PAGES;
+	info->func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;
+
+#if IS_ENABLED(CONFIG_SENSORS_TPS544_REGULATOR)
+	rconfig.dev = dev;
+	rconfig.driver_data = data;
+	info->num_regulators = info->pages;
+	info->reg_desc = tps544_reg_desc;
+	if (info->num_regulators > (int)ARRAY_SIZE(tps544_reg_desc)) {
+		dev_err(&client->dev, "num_regulators too large!");
+		info->num_regulators = ARRAY_SIZE(tps544_reg_desc);
+	}
+
+	rdev = devm_regulator_register(dev, tps544_reg_desc, &rconfig);
+	if (IS_ERR(rdev)) {
+		dev_err(dev, "Failed to register %s regulator\n",
+			info->reg_desc[0].name);
+		return (int)PTR_ERR(rdev);
+	}
+
+	ret = sysfs_create_groups(&rdev->dev.kobj, reg_groups);
+	if (ret)
+		return ret;
+
+	dev_set_drvdata(dev, rdev);
+#endif
+
+	return pmbus_do_probe(client, id, info);
+}
+
+static int tps544_remove(struct i2c_client *client)
+{
+#if IS_ENABLED(CONFIG_SENSORS_TPS544_REGULATOR)
+	struct device *dev = &client->dev;
+	struct regulator_dev *rdev = dev_get_drvdata(dev);
+
+	sysfs_remove_groups(&rdev->dev.kobj, reg_groups);
+#endif
+	pmbus_do_remove(client);
+
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id tps544_of_match[] = {
+	{ .compatible = "ti,tps544" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, tps544_of_match);
+#endif
+
+static const struct i2c_device_id tps544_id[] = {
+	{"tps544", 0},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, tps544_id);
+
+static struct i2c_driver tps544_driver = {
+	.driver = {
+		.name = "tps544",
+		.of_match_table = of_match_ptr(tps544_of_match),
+	},
+	.probe = tps544_probe,
+	.remove = tps544_remove,
+	.id_table = tps544_id,
+};
+
+module_i2c_driver(tps544_driver);
+
+MODULE_AUTHOR("Harini Katakam");
+MODULE_DESCRIPTION("PMBus regulator driver for TPS544");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/pwm-fan.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/pwm-fan.c
@@ -54,16 +54,18 @@
 static void sample_timer(struct timer_list *t)
 {
 	struct pwm_fan_ctx *ctx = from_timer(ctx, t, rpm_timer);
+	unsigned int delta = ktime_ms_delta(ktime_get(), ctx->sample_start);
 	int pulses;
-	u64 tmp;
 
-	pulses = atomic_read(&ctx->pulses);
-	atomic_sub(pulses, &ctx->pulses);
-	tmp = (u64)pulses * ktime_ms_delta(ktime_get(), ctx->sample_start) * 60;
-	do_div(tmp, ctx->pulses_per_revolution * 1000);
-	ctx->rpm = tmp;
+	if (delta) {
+		pulses = atomic_read(&ctx->pulses);
+		atomic_sub(pulses, &ctx->pulses);
+		ctx->rpm = (unsigned int)(pulses * 1000 * 60) /
+			(ctx->pulses_per_revolution * delta);
+
+		ctx->sample_start = ktime_get();
+	}
 
-	ctx->sample_start = ktime_get();
 	mod_timer(&ctx->rpm_timer, jiffies + HZ);
 }
 
@@ -328,8 +330,18 @@
 
 	ctx->pwm_value = MAX_PWM;
 
-	/* Set duty cycle to maximum allowed and enable PWM output */
 	pwm_init_state(ctx->pwm, &state);
+	/*
+	 * __set_pwm assumes that MAX_PWM * (period - 1) fits into an unsigned
+	 * long. Check this here to prevent the fan running at a too low
+	 * frequency.
+	 */
+	if (state.period > ULONG_MAX / MAX_PWM + 1) {
+		dev_err(dev, "Configured period too big\n");
+		return -EINVAL;
+	}
+
+	/* Set duty cycle to maximum allowed and enable PWM output */
 	state.duty_cycle = ctx->pwm->args.period - 1;
 	state.enabled = true;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/sch56xx-common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/sch56xx-common.c
@@ -424,7 +424,7 @@
 	if (nowayout)
 		set_bit(WDOG_NO_WAY_OUT, &data->wddev.status);
 	if (output_enable & SCH56XX_WDOG_OUTPUT_ENABLE)
-		set_bit(WDOG_ACTIVE, &data->wddev.status);
+		set_bit(WDOG_HW_RUNNING, &data->wddev.status);
 
 	/* Since the watchdog uses a downcounter there is no register to read
 	   the BIOS set timeout from (if any was set at all) ->
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/scmi-hwmon.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/scmi-hwmon.c
@@ -147,7 +147,7 @@
 	[ENERGY] = hwmon_energy,
 };
 
-static u32 hwmon_attributes[] = {
+static u32 hwmon_attributes[hwmon_max] = {
 	[hwmon_chip] = HWMON_C_REGISTER_TZ,
 	[hwmon_temp] = HWMON_T_INPUT | HWMON_T_LABEL,
 	[hwmon_in] = HWMON_I_INPUT | HWMON_I_LABEL,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/scpi-hwmon.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/scpi-hwmon.c
@@ -99,6 +99,15 @@
 
 	scpi_scale_reading(&value, sensor);
 
+	/*
+	 * Temperature sensor values are treated as signed values based on
+	 * observation even though that is not explicitly specified, and
+	 * because an unsigned u64 temperature does not really make practical
+	 * sense especially when the temperature is below zero degrees Celsius.
+	 */
+	if (sensor->info.class == TEMPERATURE)
+		return sprintf(buf, "%lld\n", (s64)value);
+
 	return sprintf(buf, "%llu\n", value);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/tmp401.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/tmp401.c
@@ -731,10 +731,21 @@
 	return 0;
 }
 
+static const struct of_device_id __maybe_unused tmp4xx_of_match[] = {
+	{ .compatible = "ti,tmp401", },
+	{ .compatible = "ti,tmp411", },
+	{ .compatible = "ti,tmp431", },
+	{ .compatible = "ti,tmp432", },
+	{ .compatible = "ti,tmp435", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, tmp4xx_of_match);
+
 static struct i2c_driver tmp401_driver = {
 	.class		= I2C_CLASS_HWMON,
 	.driver = {
 		.name	= "tmp401",
+		.of_match_table = of_match_ptr(tmp4xx_of_match),
 	},
 	.probe		= tmp401_probe,
 	.id_table	= tmp401_id,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/tmp421.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/tmp421.c
@@ -100,23 +100,17 @@
 	s16 temp[4];
 };
 
-static int temp_from_s16(s16 reg)
+static int temp_from_raw(u16 reg, bool extended)
 {
 	/* Mask out status bits */
 	int temp = reg & ~0xf;
 
-	return (temp * 1000 + 128) / 256;
-}
+	if (extended)
+		temp = temp - 64 * 256;
+	else
+		temp = (s16)temp;
 
-static int temp_from_u16(u16 reg)
-{
-	/* Mask out status bits */
-	int temp = reg & ~0xf;
-
-	/* Add offset for extended temperature range. */
-	temp -= 64 * 256;
-
-	return (temp * 1000 + 128) / 256;
+	return DIV_ROUND_CLOSEST(temp * 1000, 256);
 }
 
 static struct tmp421_data *tmp421_update_device(struct device *dev)
@@ -153,17 +147,15 @@
 
 	switch (attr) {
 	case hwmon_temp_input:
-		if (tmp421->config & TMP421_CONFIG_RANGE)
-			*val = temp_from_u16(tmp421->temp[channel]);
-		else
-			*val = temp_from_s16(tmp421->temp[channel]);
+		*val = temp_from_raw(tmp421->temp[channel],
+				     tmp421->config & TMP421_CONFIG_RANGE);
 		return 0;
 	case hwmon_temp_fault:
 		/*
-		 * The OPEN bit signals a fault. This is bit 0 of the temperature
-		 * register (low byte).
+		 * Any of OPEN or /PVLD bits indicate a hardware mulfunction
+		 * and the conversion result may be incorrect
 		 */
-		*val = tmp421->temp[channel] & 0x01;
+		*val = !!(tmp421->temp[channel] & 0x03);
 		return 0;
 	default:
 		return -EOPNOTSUPP;
@@ -176,9 +168,6 @@
 {
 	switch (attr) {
 	case hwmon_temp_fault:
-		if (channel == 0)
-			return 0;
-		return 0444;
 	case hwmon_temp_input:
 		return 0444;
 	default:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/w83627ehf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/w83627ehf.c
@@ -1506,7 +1506,7 @@
 	if (err < 0)
 		return err;
 
-	val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, 127);
+	val = DIV_ROUND_CLOSEST(clamp_val(val, 0, 127000), 1000);
 
 	mutex_lock(&data->update_lock);
 	data->target_temp[nr] = val;
@@ -1532,7 +1532,7 @@
 		return err;
 
 	/* Limit the temp to 0C - 15C */
-	val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), 0, 15);
+	val = DIV_ROUND_CLOSEST(clamp_val(val, 0, 15000), 1000);
 
 	mutex_lock(&data->update_lock);
 	if (sio_data->kind == nct6775 || sio_data->kind == nct6776) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/w83791d.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/w83791d.c
@@ -273,9 +273,6 @@
 	char valid;			/* !=0 if following fields are valid */
 	unsigned long last_updated;	/* In jiffies */
 
-	/* array of 2 pointers to subclients */
-	struct i2c_client *lm75[2];
-
 	/* volts */
 	u8 in[NUMBER_OF_VIN];		/* Register value */
 	u8 in_max[NUMBER_OF_VIN];	/* Register value */
@@ -1258,7 +1255,6 @@
 static int w83791d_detect_subclients(struct i2c_client *client)
 {
 	struct i2c_adapter *adapter = client->adapter;
-	struct w83791d_data *data = i2c_get_clientdata(client);
 	int address = client->addr;
 	int i, id;
 	u8 val;
@@ -1281,22 +1277,19 @@
 	}
 
 	val = w83791d_read(client, W83791D_REG_I2C_SUBADDR);
-	if (!(val & 0x08))
-		data->lm75[0] = devm_i2c_new_dummy_device(&client->dev, adapter,
-							  0x48 + (val & 0x7));
-	if (!(val & 0x80)) {
-		if (!IS_ERR(data->lm75[0]) &&
-				((val & 0x7) == ((val >> 4) & 0x7))) {
-			dev_err(&client->dev,
-				"duplicate addresses 0x%x, "
-				"use force_subclient\n",
-				data->lm75[0]->addr);
-			return -ENODEV;
-		}
-		data->lm75[1] = devm_i2c_new_dummy_device(&client->dev, adapter,
-							  0x48 + ((val >> 4) & 0x7));
+
+	if (!(val & 0x88) && (val & 0x7) == ((val >> 4) & 0x7)) {
+		dev_err(&client->dev,
+			"duplicate addresses 0x%x, use force_subclient\n", 0x48 + (val & 0x7));
+		return -ENODEV;
 	}
 
+	if (!(val & 0x08))
+		devm_i2c_new_dummy_device(&client->dev, adapter, 0x48 + (val & 0x7));
+
+	if (!(val & 0x80))
+		devm_i2c_new_dummy_device(&client->dev, adapter, 0x48 + ((val >> 4) & 0x7));
+
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/w83792d.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/w83792d.c
@@ -264,9 +264,6 @@
 	char valid;		/* !=0 if following fields are valid */
 	unsigned long last_updated;	/* In jiffies */
 
-	/* array of 2 pointers to subclients */
-	struct i2c_client *lm75[2];
-
 	u8 in[9];		/* Register value */
 	u8 in_max[9];		/* Register value */
 	u8 in_min[9];		/* Register value */
@@ -928,7 +925,6 @@
 	int address = new_client->addr;
 	u8 val;
 	struct i2c_adapter *adapter = new_client->adapter;
-	struct w83792d_data *data = i2c_get_clientdata(new_client);
 
 	id = i2c_adapter_id(adapter);
 	if (force_subclients[0] == id && force_subclients[1] == address) {
@@ -947,21 +943,19 @@
 	}
 
 	val = w83792d_read_value(new_client, W83792D_REG_I2C_SUBADDR);
-	if (!(val & 0x08))
-		data->lm75[0] = devm_i2c_new_dummy_device(&new_client->dev, adapter,
-							  0x48 + (val & 0x7));
-	if (!(val & 0x80)) {
-		if (!IS_ERR(data->lm75[0]) &&
-			((val & 0x7) == ((val >> 4) & 0x7))) {
-			dev_err(&new_client->dev,
-				"duplicate addresses 0x%x, use force_subclient\n",
-				data->lm75[0]->addr);
-			return -ENODEV;
-		}
-		data->lm75[1] = devm_i2c_new_dummy_device(&new_client->dev, adapter,
-							  0x48 + ((val >> 4) & 0x7));
+
+	if (!(val & 0x88) && (val & 0x7) == ((val >> 4) & 0x7)) {
+		dev_err(&new_client->dev,
+			"duplicate addresses 0x%x, use force_subclient\n", 0x48 + (val & 0x7));
+		return -ENODEV;
 	}
 
+	if (!(val & 0x08))
+		devm_i2c_new_dummy_device(&new_client->dev, adapter, 0x48 + (val & 0x7));
+
+	if (!(val & 0x80))
+		devm_i2c_new_dummy_device(&new_client->dev, adapter, 0x48 + ((val >> 4) & 0x7));
+
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/w83793.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/w83793.c
@@ -202,7 +202,6 @@
 }
 
 struct w83793_data {
-	struct i2c_client *lm75[2];
 	struct device *hwmon_dev;
 	struct mutex update_lock;
 	char valid;			/* !=0 if following fields are valid */
@@ -1566,7 +1565,6 @@
 	int address = client->addr;
 	u8 tmp;
 	struct i2c_adapter *adapter = client->adapter;
-	struct w83793_data *data = i2c_get_clientdata(client);
 
 	id = i2c_adapter_id(adapter);
 	if (force_subclients[0] == id && force_subclients[1] == address) {
@@ -1586,21 +1584,19 @@
 	}
 
 	tmp = w83793_read_value(client, W83793_REG_I2C_SUBADDR);
-	if (!(tmp & 0x08))
-		data->lm75[0] = devm_i2c_new_dummy_device(&client->dev, adapter,
-							  0x48 + (tmp & 0x7));
-	if (!(tmp & 0x80)) {
-		if (!IS_ERR(data->lm75[0])
-		    && ((tmp & 0x7) == ((tmp >> 4) & 0x7))) {
-			dev_err(&client->dev,
-				"duplicate addresses 0x%x, "
-				"use force_subclients\n", data->lm75[0]->addr);
-			return -ENODEV;
-		}
-		data->lm75[1] = devm_i2c_new_dummy_device(&client->dev, adapter,
-							  0x48 + ((tmp >> 4) & 0x7));
+
+	if (!(tmp & 0x88) && (tmp & 0x7) == ((tmp >> 4) & 0x7)) {
+		dev_err(&client->dev,
+			"duplicate addresses 0x%x, use force_subclient\n", 0x48 + (tmp & 0x7));
+		return -ENODEV;
 	}
 
+	if (!(tmp & 0x08))
+		devm_i2c_new_dummy_device(&client->dev, adapter, 0x48 + (tmp & 0x7));
+
+	if (!(tmp & 0x80))
+		devm_i2c_new_dummy_device(&client->dev, adapter, 0x48 + ((tmp >> 4) & 0x7));
+
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwmon/xgene-hwmon.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwmon/xgene-hwmon.c
@@ -719,7 +719,7 @@
 			goto out;
 		}
 
-		if (!ctx->pcc_comm_addr) {
+		if (IS_ERR_OR_NULL(ctx->pcc_comm_addr)) {
 			dev_err(&pdev->dev,
 				"Failed to ioremap PCC comm region\n");
 			rc = -ENOMEM;
@@ -768,6 +768,7 @@
 {
 	struct xgene_hwmon_dev *ctx = platform_get_drvdata(pdev);
 
+	cancel_work_sync(&ctx->workq);
 	hwmon_device_unregister(ctx->hwmon_dev);
 	kfifo_free(&ctx->async_msg_fifo);
 	if (acpi_disabled)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwtracing/coresight/coresight-catu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwtracing/coresight/coresight-catu.c
@@ -267,7 +267,7 @@
 	 * Each table can address upto 1MB and we can have
 	 * CATU_PAGES_PER_SYSPAGE tables in a system page.
 	 */
-	nr_tpages = DIV_ROUND_UP(size, SZ_1M) / CATU_PAGES_PER_SYSPAGE;
+	nr_tpages = DIV_ROUND_UP(size, CATU_PAGES_PER_SYSPAGE * SZ_1M);
 	catu_table = tmc_alloc_sg_table(catu_dev, node, nr_tpages,
 					size >> PAGE_SHIFT, pages);
 	if (IS_ERR(catu_table))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwtracing/coresight/coresight-cpu-debug.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwtracing/coresight/coresight-cpu-debug.c
@@ -379,9 +379,10 @@
 	int cpu;
 	struct debug_drvdata *drvdata;
 
-	mutex_lock(&debug_lock);
+	/* Bail out if we can't acquire the mutex or the functionality is off */
+	if (!mutex_trylock(&debug_lock))
+		return NOTIFY_DONE;
 
-	/* Bail out if the functionality is disabled */
 	if (!debug_enable)
 		goto skip_dump;
 
@@ -400,7 +401,7 @@
 
 skip_dump:
 	mutex_unlock(&debug_lock);
-	return 0;
+	return NOTIFY_DONE;
 }
 
 static struct notifier_block debug_notifier = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwtracing/coresight/coresight-etb10.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwtracing/coresight/coresight-etb10.c
@@ -176,6 +176,7 @@
 	unsigned long flags;
 	struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 	struct perf_output_handle *handle = data;
+	struct cs_buffers *buf = etm_perf_sink_config(handle);
 
 	spin_lock_irqsave(&drvdata->spinlock, flags);
 
@@ -186,7 +187,7 @@
 	}
 
 	/* Get a handle on the pid of the process to monitor */
-	pid = task_pid_nr(handle->event->owner);
+	pid = buf->pid;
 
 	if (drvdata->pid != -1 && drvdata->pid != pid) {
 		ret = -EBUSY;
@@ -383,6 +384,7 @@
 	if (!buf)
 		return NULL;
 
+	buf->pid = task_pid_nr(event->owner);
 	buf->snapshot = overwrite;
 	buf->nr_pages = nr_pages;
 	buf->data_pages = pages;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwtracing/coresight/coresight-etm-perf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwtracing/coresight/coresight-etm-perf.c
@@ -126,10 +126,10 @@
 	cpumask_t *mask = &event_data->mask;
 	struct coresight_device *sink;
 
-	if (WARN_ON(cpumask_empty(mask)))
+	if (!event_data->snk_config)
 		return;
 
-	if (!event_data->snk_config)
+	if (WARN_ON(cpumask_empty(mask)))
 		return;
 
 	cpu = cpumask_first(mask);
@@ -310,6 +310,16 @@
 	if (!event_data)
 		goto fail;
 
+	/*
+	 * Check if this ETM is allowed to trace, as decided
+	 * at etm_setup_aux(). This could be due to an unreachable
+	 * sink from this ETM. We can't do much in this case if
+	 * the sink was specified or hinted to the driver. For
+	 * now, simply don't record anything on this ETM.
+	 */
+	if (!cpumask_test_cpu(cpu, &event_data->mask))
+		goto fail_end_stop;
+
 	path = etm_event_cpu_path(event_data, cpu);
 	/* We need a sink, no need to continue without one */
 	sink = coresight_get_sink(path);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
@@ -364,8 +364,12 @@
 	mode = ETM_MODE_QELEM(config->mode);
 	/* start by clearing QE bits */
 	config->cfg &= ~(BIT(13) | BIT(14));
-	/* if supported, Q elements with instruction counts are enabled */
-	if ((mode & BIT(0)) && (drvdata->q_support & BIT(0)))
+	/*
+	 * if supported, Q elements with instruction counts are enabled.
+	 * Always set the low bit for any requested mode. Valid combos are
+	 * 0b00, 0b01 and 0b11.
+	 */
+	if (mode && drvdata->q_support)
 		config->cfg |= BIT(13);
 	/*
 	 * if supported, Q elements with and without instruction
@@ -652,10 +656,13 @@
 
 	if (kstrtoul(buf, 16, &val))
 		return -EINVAL;
+
+	/* mask off max threshold before checking min value */
+	val &= ETM_CYC_THRESHOLD_MASK;
 	if (val < drvdata->ccitmin)
 		return -EINVAL;
 
-	config->ccctlr = val & ETM_CYC_THRESHOLD_MASK;
+	config->ccctlr = val;
 	return size;
 }
 static DEVICE_ATTR_RW(cyc_threshold);
@@ -686,14 +693,16 @@
 		return -EINVAL;
 	if (!drvdata->nr_addr_cmp)
 		return -EINVAL;
+
 	/*
-	 * Bit[7:0] selects which address range comparator is used for
-	 * branch broadcast control.
+	 * Bit[8] controls include(1) / exclude(0), bits[0-7] select
+	 * individual range comparators. If include then at least 1
+	 * range must be selected.
 	 */
-	if (BMVAL(val, 0, 7) > drvdata->nr_addr_cmp)
+	if ((val & BIT(8)) && (BMVAL(val, 0, 7) == 0))
 		return -EINVAL;
 
-	config->bb_ctrl = val;
+	config->bb_ctrl = val & GENMASK(8, 0);
 	return size;
 }
 static DEVICE_ATTR_RW(bb_ctrl);
@@ -1324,8 +1333,8 @@
 
 	spin_lock(&drvdata->spinlock);
 	idx = config->seq_idx;
-	/* RST, bits[7:0] */
-	config->seq_ctrl[idx] = val & 0xFF;
+	/* Seq control has two masks B[15:8] F[7:0] */
+	config->seq_ctrl[idx] = val & 0xFFFF;
 	spin_unlock(&drvdata->spinlock);
 	return size;
 }
@@ -1580,7 +1589,7 @@
 	if (idx % 2 != 0)
 		/* PAIRINV, bit[21] */
 		val &= ~BIT(21);
-	config->res_ctrl[idx] = val;
+	config->res_ctrl[idx] = val & GENMASK(21, 0);
 	spin_unlock(&drvdata->spinlock);
 	return size;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwtracing/coresight/coresight-etm4x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwtracing/coresight/coresight-etm4x.c
@@ -156,7 +156,7 @@
 		writel_relaxed(config->ss_pe_cmp[i],
 			       drvdata->base + TRCSSPCICRn(i));
 	}
-	for (i = 0; i < drvdata->nr_addr_cmp; i++) {
+	for (i = 0; i < drvdata->nr_addr_cmp * 2; i++) {
 		writeq_relaxed(config->addr_val[i],
 			       drvdata->base + TRCACVRn(i));
 		writeq_relaxed(config->addr_acc[i],
@@ -1184,6 +1184,7 @@
 	return 0;
 
 err_arch_supported:
+	etmdrvdata[drvdata->cpu] = NULL;
 	if (--etm4_count == 0) {
 		cpuhp_remove_state_nocalls(CPUHP_AP_ARM_CORESIGHT_STARTING);
 		if (hp_online)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwtracing/coresight/coresight-etm4x.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwtracing/coresight/coresight-etm4x.h
@@ -361,7 +361,7 @@
 	u8				ctxid_size;
 	u8				vmid_size;
 	u8				ccsize;
-	u8				ccitmin;
+	u16				ccitmin;
 	u8				s_ex_level;
 	u8				ns_ex_level;
 	u8				q_support;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwtracing/coresight/coresight-funnel.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwtracing/coresight/coresight-funnel.c
@@ -38,12 +38,14 @@
  * @atclk:	optional clock for the core parts of the funnel.
  * @csdev:	component vitals needed by the framework.
  * @priority:	port selection order.
+ * @spinlock:	serialize enable/disable operations.
  */
 struct funnel_drvdata {
 	void __iomem		*base;
 	struct clk		*atclk;
 	struct coresight_device	*csdev;
 	unsigned long		priority;
+	spinlock_t		spinlock;
 };
 
 static int dynamic_funnel_enable_hw(struct funnel_drvdata *drvdata, int port)
@@ -76,11 +78,21 @@
 {
 	int rc = 0;
 	struct funnel_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+	unsigned long flags;
+	bool first_enable = false;
 
-	if (drvdata->base)
-		rc = dynamic_funnel_enable_hw(drvdata, inport);
-
+	spin_lock_irqsave(&drvdata->spinlock, flags);
+	if (atomic_read(&csdev->refcnt[inport]) == 0) {
+		if (drvdata->base)
+			rc = dynamic_funnel_enable_hw(drvdata, inport);
+		if (!rc)
+			first_enable = true;
+	}
 	if (!rc)
+		atomic_inc(&csdev->refcnt[inport]);
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+	if (first_enable)
 		dev_dbg(&csdev->dev, "FUNNEL inport %d enabled\n", inport);
 	return rc;
 }
@@ -107,11 +119,19 @@
 			   int outport)
 {
 	struct funnel_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+	unsigned long flags;
+	bool last_disable = false;
 
-	if (drvdata->base)
-		dynamic_funnel_disable_hw(drvdata, inport);
+	spin_lock_irqsave(&drvdata->spinlock, flags);
+	if (atomic_dec_return(&csdev->refcnt[inport]) == 0) {
+		if (drvdata->base)
+			dynamic_funnel_disable_hw(drvdata, inport);
+		last_disable = true;
+	}
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
-	dev_dbg(&csdev->dev, "FUNNEL inport %d disabled\n", inport);
+	if (last_disable)
+		dev_dbg(&csdev->dev, "FUNNEL inport %d disabled\n", inport);
 }
 
 static const struct coresight_ops_link funnel_link_ops = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwtracing/coresight/coresight-priv.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwtracing/coresight/coresight-priv.h
@@ -86,6 +86,7 @@
  * struct cs_buffer - keep track of a recording session' specifics
  * @cur:	index of the current buffer
  * @nr_pages:	max number of pages granted to us
+ * @pid:	PID this cs_buffer belongs to
  * @offset:	offset within the current buffer
  * @data_size:	how much we collected in this run
  * @snapshot:	is this run in snapshot mode
@@ -94,6 +95,7 @@
 struct cs_buffers {
 	unsigned int		cur;
 	unsigned int		nr_pages;
+	pid_t			pid;
 	unsigned long		offset;
 	local_t			data_size;
 	bool			snapshot;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwtracing/coresight/coresight-replicator.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwtracing/coresight/coresight-replicator.c
@@ -31,11 +31,13 @@
  *		whether this one is programmable or not.
  * @atclk:	optional clock for the core parts of the replicator.
  * @csdev:	component vitals needed by the framework
+ * @spinlock:	serialize enable/disable operations.
  */
 struct replicator_drvdata {
 	void __iomem		*base;
 	struct clk		*atclk;
 	struct coresight_device	*csdev;
+	spinlock_t		spinlock;
 };
 
 static void dynamic_replicator_reset(struct replicator_drvdata *drvdata)
@@ -97,10 +99,22 @@
 {
 	int rc = 0;
 	struct replicator_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+	unsigned long flags;
+	bool first_enable = false;
 
-	if (drvdata->base)
-		rc = dynamic_replicator_enable(drvdata, inport, outport);
+	spin_lock_irqsave(&drvdata->spinlock, flags);
+	if (atomic_read(&csdev->refcnt[outport]) == 0) {
+		if (drvdata->base)
+			rc = dynamic_replicator_enable(drvdata, inport,
+						       outport);
+		if (!rc)
+			first_enable = true;
+	}
 	if (!rc)
+		atomic_inc(&csdev->refcnt[outport]);
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+	if (first_enable)
 		dev_dbg(&csdev->dev, "REPLICATOR enabled\n");
 	return rc;
 }
@@ -137,10 +151,19 @@
 			       int outport)
 {
 	struct replicator_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+	unsigned long flags;
+	bool last_disable = false;
 
-	if (drvdata->base)
-		dynamic_replicator_disable(drvdata, inport, outport);
-	dev_dbg(&csdev->dev, "REPLICATOR disabled\n");
+	spin_lock_irqsave(&drvdata->spinlock, flags);
+	if (atomic_dec_return(&csdev->refcnt[outport]) == 0) {
+		if (drvdata->base)
+			dynamic_replicator_disable(drvdata, inport, outport);
+		last_disable = true;
+	}
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+	if (last_disable)
+		dev_dbg(&csdev->dev, "REPLICATOR disabled\n");
 }
 
 static const struct coresight_ops_link replicator_link_ops = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwtracing/coresight/coresight-tmc-etf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwtracing/coresight/coresight-tmc-etf.c
@@ -227,6 +227,7 @@
 	unsigned long flags;
 	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 	struct perf_output_handle *handle = data;
+	struct cs_buffers *buf = etm_perf_sink_config(handle);
 
 	spin_lock_irqsave(&drvdata->spinlock, flags);
 	do {
@@ -243,7 +244,7 @@
 		}
 
 		/* Get a handle on the pid of the process to monitor */
-		pid = task_pid_nr(handle->event->owner);
+		pid = buf->pid;
 
 		if (drvdata->pid != -1 && drvdata->pid != pid) {
 			ret = -EBUSY;
@@ -334,9 +335,10 @@
 static int tmc_enable_etf_link(struct coresight_device *csdev,
 			       int inport, int outport)
 {
-	int ret;
+	int ret = 0;
 	unsigned long flags;
 	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+	bool first_enable = false;
 
 	spin_lock_irqsave(&drvdata->spinlock, flags);
 	if (drvdata->reading) {
@@ -344,12 +346,18 @@
 		return -EBUSY;
 	}
 
-	ret = tmc_etf_enable_hw(drvdata);
+	if (atomic_read(&csdev->refcnt[0]) == 0) {
+		ret = tmc_etf_enable_hw(drvdata);
+		if (!ret) {
+			drvdata->mode = CS_MODE_SYSFS;
+			first_enable = true;
+		}
+	}
 	if (!ret)
-		drvdata->mode = CS_MODE_SYSFS;
+		atomic_inc(&csdev->refcnt[0]);
 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
-	if (!ret)
+	if (first_enable)
 		dev_dbg(&csdev->dev, "TMC-ETF enabled\n");
 	return ret;
 }
@@ -359,6 +367,7 @@
 {
 	unsigned long flags;
 	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+	bool last_disable = false;
 
 	spin_lock_irqsave(&drvdata->spinlock, flags);
 	if (drvdata->reading) {
@@ -366,11 +375,15 @@
 		return;
 	}
 
-	tmc_etf_disable_hw(drvdata);
-	drvdata->mode = CS_MODE_DISABLED;
+	if (atomic_dec_return(&csdev->refcnt[0]) == 0) {
+		tmc_etf_disable_hw(drvdata);
+		drvdata->mode = CS_MODE_DISABLED;
+		last_disable = true;
+	}
 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
-	dev_dbg(&csdev->dev, "TMC-ETF disabled\n");
+	if (last_disable)
+		dev_dbg(&csdev->dev, "TMC-ETF disabled\n");
 }
 
 static void *tmc_alloc_etf_buffer(struct coresight_device *csdev,
@@ -387,6 +400,7 @@
 	if (!buf)
 		return NULL;
 
+	buf->pid = task_pid_nr(event->owner);
 	buf->snapshot = overwrite;
 	buf->nr_pages = nr_pages;
 	buf->data_pages = pages;
@@ -412,7 +426,7 @@
 		return -EINVAL;
 
 	/* wrap head around to the amount of space we have */
-	head = handle->head & ((buf->nr_pages << PAGE_SHIFT) - 1);
+	head = handle->head & (((unsigned long)buf->nr_pages << PAGE_SHIFT) - 1);
 
 	/* find the page to write to */
 	buf->cur = head / PAGE_SIZE;
@@ -514,7 +528,7 @@
 		buf_ptr = buf->data_pages[cur] + offset;
 		*buf_ptr = readl_relaxed(drvdata->base + TMC_RRD);
 
-		if (lost && *barrier) {
+		if (lost && i < CORESIGHT_BARRIER_PKT_SIZE) {
 			*buf_ptr = *barrier;
 			barrier++;
 		}
@@ -584,13 +598,6 @@
 		goto out;
 	}
 
-	/* There is no point in reading a TMC in HW FIFO mode */
-	mode = readl_relaxed(drvdata->base + TMC_MODE);
-	if (mode != TMC_MODE_CIRCULAR_BUFFER) {
-		ret = -EINVAL;
-		goto out;
-	}
-
 	/* Don't interfere if operated from Perf */
 	if (drvdata->mode == CS_MODE_PERF) {
 		ret = -EINVAL;
@@ -604,8 +611,15 @@
 	}
 
 	/* Disable the TMC if need be */
-	if (drvdata->mode == CS_MODE_SYSFS)
+	if (drvdata->mode == CS_MODE_SYSFS) {
+		/* There is no point in reading a TMC in HW FIFO mode */
+		mode = readl_relaxed(drvdata->base + TMC_MODE);
+		if (mode != TMC_MODE_CIRCULAR_BUFFER) {
+			ret = -EINVAL;
+			goto out;
+		}
 		__tmc_etb_disable_hw(drvdata);
+	}
 
 	drvdata->reading = true;
 out:
@@ -627,15 +641,14 @@
 
 	spin_lock_irqsave(&drvdata->spinlock, flags);
 
-	/* There is no point in reading a TMC in HW FIFO mode */
-	mode = readl_relaxed(drvdata->base + TMC_MODE);
-	if (mode != TMC_MODE_CIRCULAR_BUFFER) {
-		spin_unlock_irqrestore(&drvdata->spinlock, flags);
-		return -EINVAL;
-	}
-
 	/* Re-enable the TMC if need be */
 	if (drvdata->mode == CS_MODE_SYSFS) {
+		/* There is no point in reading a TMC in HW FIFO mode */
+		mode = readl_relaxed(drvdata->base + TMC_MODE);
+		if (mode != TMC_MODE_CIRCULAR_BUFFER) {
+			spin_unlock_irqrestore(&drvdata->spinlock, flags);
+			return -EINVAL;
+		}
 		/*
 		 * The trace run will continue with the same allocated trace
 		 * buffer. As such zero-out the buffer so that we don't end
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -47,7 +47,8 @@
 };
 
 /* Convert the perf index to an offset within the ETR buffer */
-#define PERF_IDX2OFF(idx, buf)	((idx) % ((buf)->nr_pages << PAGE_SHIFT))
+#define PERF_IDX2OFF(idx, buf)		\
+		((idx) % ((unsigned long)(buf)->nr_pages << PAGE_SHIFT))
 
 /* Lower limit for ETR hardware buffer */
 #define TMC_ETR_PERF_MIN_BUF_SIZE	SZ_1M
@@ -217,6 +218,8 @@
 		} else {
 			page = alloc_pages_node(node,
 						GFP_KERNEL | __GFP_ZERO, 0);
+			if (!page)
+				goto err;
 		}
 		paddr = dma_map_page(real_dev, page, 0, PAGE_SIZE, dir);
 		if (dma_mapping_error(real_dev, paddr))
@@ -254,6 +257,7 @@
 {
 	tmc_free_table_pages(sg_table);
 	tmc_free_data_pages(sg_table);
+	kfree(sg_table);
 }
 
 /*
@@ -334,7 +338,6 @@
 		rc = tmc_alloc_table_pages(sg_table);
 	if (rc) {
 		tmc_free_sg_table(sg_table);
-		kfree(sg_table);
 		return ERR_PTR(rc);
 	}
 
@@ -907,7 +910,7 @@
 
 	len = tmc_etr_buf_get_data(etr_buf, offset,
 				   CORESIGHT_BARRIER_PKT_SIZE, &bufp);
-	if (WARN_ON(len < CORESIGHT_BARRIER_PKT_SIZE))
+	if (WARN_ON(len < 0 || len < CORESIGHT_BARRIER_PKT_SIZE))
 		return -EINVAL;
 	coresight_insert_barrier_packet(bufp);
 	return offset + CORESIGHT_BARRIER_PKT_SIZE;
@@ -1213,7 +1216,7 @@
 	 * than the size requested via sysfs.
 	 */
 	if ((nr_pages << PAGE_SHIFT) > drvdata->size) {
-		etr_buf = tmc_alloc_etr_buf(drvdata, (nr_pages << PAGE_SHIFT),
+		etr_buf = tmc_alloc_etr_buf(drvdata, ((ssize_t)nr_pages << PAGE_SHIFT),
 					    0, node, NULL);
 		if (!IS_ERR(etr_buf))
 			goto done;
@@ -1533,7 +1536,7 @@
 
 	/* Insert barrier packets at the beginning, if there was an overflow */
 	if (lost)
-		tmc_etr_buf_insert_barrier_packet(etr_buf, etr_buf->offset);
+		tmc_etr_buf_insert_barrier_packet(etr_buf, offset);
 	tmc_etr_sync_perf_buffer(etr_perf, offset, size);
 
 	/*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwtracing/coresight/coresight-tmc.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwtracing/coresight/coresight-tmc.h
@@ -320,7 +320,7 @@
 static inline unsigned long
 tmc_sg_table_buf_size(struct tmc_sg_table *sg_table)
 {
-	return sg_table->data_pages.nr_pages << PAGE_SHIFT;
+	return (unsigned long)sg_table->data_pages.nr_pages << PAGE_SHIFT;
 }
 
 struct coresight_device *tmc_etr_get_catu_device(struct tmc_drvdata *drvdata);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwtracing/coresight/coresight.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwtracing/coresight/coresight.c
@@ -253,9 +253,9 @@
 				 struct coresight_device *parent,
 				 struct coresight_device *child)
 {
-	int ret;
+	int ret = 0;
 	int link_subtype;
-	int refport, inport, outport;
+	int inport, outport;
 
 	if (!parent || !child)
 		return -EINVAL;
@@ -264,29 +264,17 @@
 	outport = coresight_find_link_outport(csdev, child);
 	link_subtype = csdev->subtype.link_subtype;
 
-	if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG)
-		refport = inport;
-	else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT)
-		refport = outport;
-	else
-		refport = 0;
-
-	if (refport < 0)
-		return refport;
-
-	if (atomic_inc_return(&csdev->refcnt[refport]) == 1) {
-		if (link_ops(csdev)->enable) {
-			ret = link_ops(csdev)->enable(csdev, inport, outport);
-			if (ret) {
-				atomic_dec(&csdev->refcnt[refport]);
-				return ret;
-			}
-		}
-	}
-
-	csdev->enable = true;
+	if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG && inport < 0)
+		return inport;
+	if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT && outport < 0)
+		return outport;
+
+	if (link_ops(csdev)->enable)
+		ret = link_ops(csdev)->enable(csdev, inport, outport);
+	if (!ret)
+		csdev->enable = true;
 
-	return 0;
+	return ret;
 }
 
 static void coresight_disable_link(struct coresight_device *csdev,
@@ -295,7 +283,7 @@
 {
 	int i, nr_conns;
 	int link_subtype;
-	int refport, inport, outport;
+	int inport, outport;
 
 	if (!parent || !child)
 		return;
@@ -305,20 +293,15 @@
 	link_subtype = csdev->subtype.link_subtype;
 
 	if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG) {
-		refport = inport;
 		nr_conns = csdev->pdata->nr_inport;
 	} else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT) {
-		refport = outport;
 		nr_conns = csdev->pdata->nr_outport;
 	} else {
-		refport = 0;
 		nr_conns = 1;
 	}
 
-	if (atomic_dec_return(&csdev->refcnt[refport]) == 0) {
-		if (link_ops(csdev)->disable)
-			link_ops(csdev)->disable(csdev, inport, outport);
-	}
+	if (link_ops(csdev)->disable)
+		link_ops(csdev)->disable(csdev, inport, outport);
 
 	for (i = 0; i < nr_conns; i++)
 		if (atomic_read(&csdev->refcnt[i]) != 0)
@@ -1090,6 +1073,7 @@
 			 * platform data.
 			 */
 			fwnode_handle_put(conn->child_fwnode);
+			conn->child_fwnode = NULL;
 			/* No need to continue */
 			break;
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwtracing/intel_th/core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwtracing/intel_th/core.c
@@ -215,6 +215,22 @@
 
 static DEVICE_ATTR_RO(port);
 
+static void intel_th_trace_prepare(struct intel_th_device *thdev)
+{
+	struct intel_th_device *hub = to_intel_th_hub(thdev);
+	struct intel_th_driver *hubdrv = to_intel_th_driver(hub->dev.driver);
+
+	if (hub->type != INTEL_TH_SWITCH)
+		return;
+
+	if (thdev->type != INTEL_TH_OUTPUT)
+		return;
+
+	pm_runtime_get_sync(&thdev->dev);
+	hubdrv->prepare(hub, &thdev->output);
+	pm_runtime_put(&thdev->dev);
+}
+
 static int intel_th_output_activate(struct intel_th_device *thdev)
 {
 	struct intel_th_driver *thdrv =
@@ -235,6 +251,7 @@
 	if (ret)
 		goto fail_put;
 
+	intel_th_trace_prepare(thdev);
 	if (thdrv->activate)
 		ret = thdrv->activate(thdev);
 	else
@@ -649,10 +666,8 @@
 	}
 
 	err = intel_th_device_add_resources(thdev, res, subdev->nres);
-	if (err) {
-		put_device(&thdev->dev);
+	if (err)
 		goto fail_put_device;
-	}
 
 	if (subdev->type == INTEL_TH_OUTPUT) {
 		if (subdev->mknode)
@@ -667,10 +682,8 @@
 	}
 
 	err = device_add(&thdev->dev);
-	if (err) {
-		put_device(&thdev->dev);
+	if (err)
 		goto fail_free_res;
-	}
 
 	/* need switch driver to be loaded to enumerate the rest */
 	if (subdev->type == INTEL_TH_SWITCH && !req) {
@@ -838,9 +851,6 @@
 			ret |= d->irq(th->thdev[i]);
 	}
 
-	if (ret == IRQ_NONE)
-		pr_warn_ratelimited("nobody cared for irq\n");
-
 	return ret;
 }
 
@@ -891,6 +901,7 @@
 
 			if (th->irq == -1)
 				th->irq = devres[r].start;
+			th->num_irqs++;
 			break;
 		default:
 			dev_warn(dev, "Unknown resource type %lx\n",
@@ -944,6 +955,9 @@
 
 	th->num_thdevs = 0;
 
+	for (i = 0; i < th->num_irqs; i++)
+		devm_free_irq(th->dev, th->irq + i, th);
+
 	pm_runtime_get_sync(th->dev);
 	pm_runtime_forbid(th->dev);
 
@@ -1024,15 +1038,30 @@
 {
 	struct intel_th_device *hub = to_intel_th_hub(thdev);
 	struct intel_th_driver *hubdrv = to_intel_th_driver(hub->dev.driver);
+	int ret;
 
 	/* In host mode, this is up to the external debugger, do nothing. */
 	if (hub->host_mode)
 		return 0;
 
-	if (!hubdrv->set_output)
-		return -ENOTSUPP;
+	/*
+	 * hub is instantiated together with the source device that
+	 * calls here, so guaranteed to be present.
+	 */
+	hubdrv = to_intel_th_driver(hub->dev.driver);
+	if (!hubdrv || !try_module_get(hubdrv->driver.owner))
+		return -EINVAL;
+
+	if (!hubdrv->set_output) {
+		ret = -ENOTSUPP;
+		goto out;
+	}
+
+	ret = hubdrv->set_output(hub, master);
 
-	return hubdrv->set_output(hub, master);
+out:
+	module_put(hubdrv->driver.owner);
+	return ret;
 }
 EXPORT_SYMBOL_GPL(intel_th_set_output);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwtracing/intel_th/gth.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwtracing/intel_th/gth.c
@@ -543,7 +543,7 @@
 	output->active = false;
 
 	for_each_set_bit(master, gth->output[output->port].master,
-			 TH_CONFIGURABLE_MASTERS) {
+			 TH_CONFIGURABLE_MASTERS + 1) {
 		gth_master_set(gth, master, -1);
 	}
 	spin_unlock(&gth->gth_lock);
@@ -564,6 +564,21 @@
 	iowrite32(reg, gth->base + REG_TSCU_TSUCTRL);
 }
 
+static void intel_th_gth_prepare(struct intel_th_device *thdev,
+				 struct intel_th_output *output)
+{
+	struct gth_device *gth = dev_get_drvdata(&thdev->dev);
+	int count;
+
+	/*
+	 * Wait until the output port is in reset before we start
+	 * programming it.
+	 */
+	for (count = GTH_PLE_WAITLOOP_DEPTH;
+	     count && !(gth_output_get(gth, output->port) & BIT(5)); count--)
+		cpu_relax();
+}
+
 /**
  * intel_th_gth_enable() - enable tracing to an output device
  * @thdev:	GTH device
@@ -697,7 +712,7 @@
 	othdev->output.port = -1;
 	othdev->output.active = false;
 	gth->output[port].output = NULL;
-	for (master = 0; master <= TH_CONFIGURABLE_MASTERS; master++)
+	for (master = 0; master < TH_CONFIGURABLE_MASTERS + 1; master++)
 		if (gth->master[master] == port)
 			gth->master[master] = -1;
 	spin_unlock(&gth->gth_lock);
@@ -815,6 +830,7 @@
 	.assign		= intel_th_gth_assign,
 	.unassign	= intel_th_gth_unassign,
 	.set_output	= intel_th_gth_set_output,
+	.prepare	= intel_th_gth_prepare,
 	.enable		= intel_th_gth_enable,
 	.trig_switch	= intel_th_gth_switch,
 	.disable	= intel_th_gth_disable,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwtracing/intel_th/intel_th.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwtracing/intel_th/intel_th.h
@@ -47,11 +47,13 @@
 /**
  * struct intel_th_drvdata - describes hardware capabilities and quirks
  * @tscu_enable:	device needs SW to enable time stamping unit
+ * @multi_is_broken:	device has multiblock mode is broken
  * @has_mintctl:	device has interrupt control (MINTCTL) register
  * @host_mode_only:	device can only operate in 'host debugger' mode
  */
 struct intel_th_drvdata {
 	unsigned int	tscu_enable        : 1,
+			multi_is_broken    : 1,
 			has_mintctl        : 1,
 			host_mode_only     : 1;
 };
@@ -141,6 +143,7 @@
  * @remove:	remove method
  * @assign:	match a given output type device against available outputs
  * @unassign:	deassociate an output type device from an output port
+ * @prepare:	prepare output port for tracing
  * @enable:	enable tracing for a given output device
  * @disable:	disable tracing for a given output device
  * @irq:	interrupt callback
@@ -162,6 +165,8 @@
 					  struct intel_th_device *othdev);
 	void			(*unassign)(struct intel_th_device *thdev,
 					    struct intel_th_device *othdev);
+	void			(*prepare)(struct intel_th_device *thdev,
+					   struct intel_th_output *output);
 	void			(*enable)(struct intel_th_device *thdev,
 					  struct intel_th_output *output);
 	void			(*trig_switch)(struct intel_th_device *thdev,
@@ -261,6 +266,7 @@
  * @num_thdevs:	number of devices in the @thdev array
  * @num_resources:	number of resources in the @resource array
  * @irq:	irq number
+ * @num_irqs:	number of IRQs is use
  * @id:		this Intel TH controller's device ID in the system
  * @major:	device node major for output devices
  */
@@ -277,6 +283,7 @@
 	unsigned int		num_thdevs;
 	unsigned int		num_resources;
 	int			irq;
+	int			num_irqs;
 
 	int			id;
 	int			major;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwtracing/intel_th/msu-sink.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwtracing/intel_th/msu-sink.c
@@ -71,6 +71,9 @@
 		block = dma_alloc_coherent(priv->dev->parent->parent,
 					   PAGE_SIZE, &sg_dma_address(sg_ptr),
 					   GFP_KERNEL);
+		if (!block)
+			return -ENOMEM;
+
 		sg_set_buf(sg_ptr, block, PAGE_SIZE);
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwtracing/intel_th/msu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwtracing/intel_th/msu.c
@@ -157,7 +157,8 @@
 	/* config */
 	unsigned int		enabled : 1,
 				wrap	: 1,
-				do_irq	: 1;
+				do_irq	: 1,
+				multi_is_broken : 1;
 	unsigned int		mode;
 	unsigned int		burst_len;
 	unsigned int		index;
@@ -718,9 +719,6 @@
 
 	if (old != expect) {
 		ret = -EINVAL;
-		dev_warn_ratelimited(msc_dev(win->msc),
-				     "expected lockout state %d, got %d\n",
-				     expect, old);
 		goto unlock;
 	}
 
@@ -741,6 +739,10 @@
 		/* from intel_th_msc_window_unlock(), don't warn if not locked */
 		if (expect == WIN_LOCKED && old == new)
 			return 0;
+
+		dev_warn_ratelimited(msc_dev(win->msc),
+				     "expected lockout state %d, got %d\n",
+				     expect, old);
 	}
 
 	return ret;
@@ -760,7 +762,7 @@
 	lockdep_assert_held(&msc->buf_mutex);
 
 	if (msc->mode > MSC_MODE_MULTI)
-		return -ENOTSUPP;
+		return -EINVAL;
 
 	if (msc->mode == MSC_MODE_MULTI) {
 		if (msc_win_set_lockout(msc->cur_win, WIN_READY, WIN_INUSE))
@@ -1048,6 +1050,16 @@
 static inline void msc_buffer_set_wb(struct msc_window *win) {}
 #endif /* CONFIG_X86 */
 
+static struct page *msc_sg_page(struct scatterlist *sg)
+{
+	void *addr = sg_virt(sg);
+
+	if (is_vmalloc_addr(addr))
+		return vmalloc_to_page(addr);
+
+	return sg_page(sg);
+}
+
 /**
  * msc_buffer_win_alloc() - alloc a window for a multiblock mode
  * @msc:	MSC device
@@ -1120,7 +1132,7 @@
 	int i;
 
 	for_each_sg(win->sgt->sgl, sg, win->nr_segs, i) {
-		struct page *page = sg_page(sg);
+		struct page *page = msc_sg_page(sg);
 
 		page->mapping = NULL;
 		dma_free_coherent(msc_dev(win->msc)->parent->parent, PAGE_SIZE,
@@ -1294,7 +1306,7 @@
 	} else if (msc->mode == MSC_MODE_MULTI) {
 		ret = msc_buffer_multi_alloc(msc, nr_pages, nr_wins);
 	} else {
-		ret = -ENOTSUPP;
+		ret = -EINVAL;
 	}
 
 	if (!ret) {
@@ -1382,7 +1394,7 @@
 	pgoff -= win->pgoff;
 
 	for_each_sg(win->sgt->sgl, sg, win->nr_segs, blk) {
-		struct page *page = sg_page(sg);
+		struct page *page = msc_sg_page(sg);
 		size_t pgsz = PFN_DOWN(sg->length);
 
 		if (pgoff < pgsz)
@@ -1530,7 +1542,7 @@
 		if (ret >= 0)
 			*ppos = iter->offset;
 	} else {
-		ret = -ENOTSUPP;
+		ret = -EINVAL;
 	}
 
 put_count:
@@ -1664,7 +1676,7 @@
 {
 	atomic_set(&msc->user_count, -1);
 
-	msc->mode = MSC_MODE_MULTI;
+	msc->mode = msc->multi_is_broken ? MSC_MODE_SINGLE : MSC_MODE_MULTI;
 	mutex_init(&msc->buf_mutex);
 	INIT_LIST_HEAD(&msc->win_list);
 	INIT_LIST_HEAD(&msc->iter_list);
@@ -1676,10 +1688,13 @@
 	return 0;
 }
 
-static void msc_win_switch(struct msc *msc)
+static int msc_win_switch(struct msc *msc)
 {
 	struct msc_window *first;
 
+	if (list_empty(&msc->win_list))
+		return -EINVAL;
+
 	first = list_first_entry(&msc->win_list, struct msc_window, entry);
 
 	if (msc_is_last_win(msc->cur_win))
@@ -1691,6 +1706,8 @@
 	msc->base_addr = msc_win_base_dma(msc->cur_win);
 
 	intel_th_trace_switch(msc->thdev);
+
+	return 0;
 }
 
 /**
@@ -1871,6 +1888,9 @@
 	return -EINVAL;
 
 found:
+	if (i == MSC_MODE_MULTI && msc->multi_is_broken)
+		return -EOPNOTSUPP;
+
 	mutex_lock(&msc->buf_mutex);
 	ret = 0;
 
@@ -2025,16 +2045,15 @@
 	if (val != 1)
 		return -EINVAL;
 
+	ret = -EINVAL;
 	mutex_lock(&msc->buf_mutex);
 	/*
 	 * Window switch can only happen in the "multi" mode.
 	 * If a external buffer is engaged, they have the full
 	 * control over window switching.
 	 */
-	if (msc->mode != MSC_MODE_MULTI || msc->mbuf)
-		ret = -ENOTSUPP;
-	else
-		msc_win_switch(msc);
+	if (msc->mode == MSC_MODE_MULTI && !msc->mbuf)
+		ret = msc_win_switch(msc);
 	mutex_unlock(&msc->buf_mutex);
 
 	return ret ? ret : size;
@@ -2078,6 +2097,9 @@
 	if (!res)
 		msc->do_irq = 1;
 
+	if (INTEL_TH_CAP(to_intel_th(thdev), multi_is_broken))
+		msc->multi_is_broken = 1;
+
 	msc->index = thdev->id;
 
 	msc->thdev = thdev;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwtracing/intel_th/pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwtracing/intel_th/pci.c
@@ -100,8 +100,10 @@
 		}
 
 	th = intel_th_alloc(&pdev->dev, drvdata, resource, r);
-	if (IS_ERR(th))
-		return PTR_ERR(th);
+	if (IS_ERR(th)) {
+		err = PTR_ERR(th);
+		goto err_free_irq;
+	}
 
 	th->activate   = intel_th_pci_activate;
 	th->deactivate = intel_th_pci_deactivate;
@@ -109,6 +111,10 @@
 	pci_set_master(pdev);
 
 	return 0;
+
+err_free_irq:
+	pci_free_irq_vectors(pdev);
+	return err;
 }
 
 static void intel_th_pci_remove(struct pci_dev *pdev)
@@ -120,6 +126,10 @@
 	pci_free_irq_vectors(pdev);
 }
 
+static const struct intel_th_drvdata intel_th_1x_multi_is_broken = {
+	.multi_is_broken	= 1,
+};
+
 static const struct intel_th_drvdata intel_th_2x = {
 	.tscu_enable	= 1,
 	.has_mintctl	= 1,
@@ -152,7 +162,7 @@
 	{
 		/* Kaby Lake PCH-H */
 		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa2a6),
-		.driver_data = (kernel_ulong_t)0,
+		.driver_data = (kernel_ulong_t)&intel_th_1x_multi_is_broken,
 	},
 	{
 		/* Denverton */
@@ -205,20 +215,135 @@
 		.driver_data = (kernel_ulong_t)&intel_th_2x,
 	},
 	{
+		/* Comet Lake PCH-V */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa3a6),
+		.driver_data = (kernel_ulong_t)&intel_th_1x_multi_is_broken,
+	},
+	{
 		/* Ice Lake NNPI */
 		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x45c5),
 		.driver_data = (kernel_ulong_t)&intel_th_2x,
 	},
 	{
+		/* Ice Lake CPU */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8a29),
+		.driver_data = (kernel_ulong_t)&intel_th_2x,
+	},
+	{
+		/* Tiger Lake CPU */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x9a33),
+		.driver_data = (kernel_ulong_t)&intel_th_2x,
+	},
+	{
 		/* Tiger Lake PCH */
 		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa0a6),
 		.driver_data = (kernel_ulong_t)&intel_th_2x,
 	},
 	{
+		/* Tiger Lake PCH-H */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x43a6),
+		.driver_data = (kernel_ulong_t)&intel_th_2x,
+	},
+	{
 		/* Jasper Lake PCH */
 		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4da6),
 		.driver_data = (kernel_ulong_t)&intel_th_2x,
 	},
+	{
+		/* Jasper Lake CPU */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4e29),
+		.driver_data = (kernel_ulong_t)&intel_th_2x,
+	},
+	{
+		/* Elkhart Lake CPU */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4529),
+		.driver_data = (kernel_ulong_t)&intel_th_2x,
+	},
+	{
+		/* Elkhart Lake */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4b26),
+		.driver_data = (kernel_ulong_t)&intel_th_2x,
+	},
+	{
+		/* Alder Lake-P */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x51a6),
+		.driver_data = (kernel_ulong_t)&intel_th_2x,
+	},
+	{
+		/* Emmitsburg PCH */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x1bcc),
+		.driver_data = (kernel_ulong_t)&intel_th_2x,
+	},
+	{
+		/* Alder Lake-M */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x54a6),
+		.driver_data = (kernel_ulong_t)&intel_th_2x,
+	},
+	{
+		/* Raptor Lake-S CPU */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa76f),
+		.driver_data = (kernel_ulong_t)&intel_th_2x,
+	},
+	{
+		/* Meteor Lake-P */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7e24),
+		.driver_data = (kernel_ulong_t)&intel_th_2x,
+	},
+	{
+		/* Meteor Lake-S CPU */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xae24),
+		.driver_data = (kernel_ulong_t)&intel_th_2x,
+	},
+	{
+		/* Meteor Lake-S */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7f26),
+		.driver_data = (kernel_ulong_t)&intel_th_2x,
+	},
+	{
+		/* Raptor Lake-S */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7a26),
+		.driver_data = (kernel_ulong_t)&intel_th_2x,
+	},
+	{
+		/* Granite Rapids */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0963),
+		.driver_data = (kernel_ulong_t)&intel_th_2x,
+	},
+	{
+		/* Granite Rapids SOC */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x3256),
+		.driver_data = (kernel_ulong_t)&intel_th_2x,
+	},
+	{
+		/* Sapphire Rapids SOC */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x3456),
+		.driver_data = (kernel_ulong_t)&intel_th_2x,
+	},
+	{
+		/* Lunar Lake */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa824),
+		.driver_data = (kernel_ulong_t)&intel_th_2x,
+	},
+	{
+		/* Arrow Lake */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7724),
+		.driver_data = (kernel_ulong_t)&intel_th_2x,
+	},
+	{
+		/* Panther Lake-H */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe324),
+		.driver_data = (kernel_ulong_t)&intel_th_2x,
+	},
+	{
+		/* Panther Lake-P/U */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe424),
+		.driver_data = (kernel_ulong_t)&intel_th_2x,
+	},
+	{
+		/* Rocket Lake CPU */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4c19),
+		.driver_data = (kernel_ulong_t)&intel_th_2x,
+	},
 	{ 0 },
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwtracing/intel_th/sth.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwtracing/intel_th/sth.c
@@ -161,9 +161,7 @@
 {
 	struct sth_device *sth = container_of(stm_data, struct sth_device, stm);
 
-	intel_th_set_output(to_intel_th_device(sth->dev), master);
-
-	return 0;
+	return intel_th_set_output(to_intel_th_device(sth->dev), master);
 }
 
 static int intel_th_sw_init(struct sth_device *sth)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwtracing/stm/core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwtracing/stm/core.c
@@ -878,8 +878,11 @@
 		return -ENOMEM;
 
 	stm->major = register_chrdev(0, stm_data->name, &stm_fops);
-	if (stm->major < 0)
-		goto err_free;
+	if (stm->major < 0) {
+		err = stm->major;
+		vfree(stm);
+		return err;
+	}
 
 	device_initialize(&stm->dev);
 	stm->dev.devt = MKDEV(stm->major, 0);
@@ -923,10 +926,8 @@
 err_device:
 	unregister_chrdev(stm->major, stm_data->name);
 
-	/* matches device_initialize() above */
+	/* calls stm_device_release() */
 	put_device(&stm->dev);
-err_free:
-	vfree(stm);
 
 	return err;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwtracing/stm/heartbeat.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwtracing/stm/heartbeat.c
@@ -64,7 +64,7 @@
 
 static int stm_heartbeat_init(void)
 {
-	int i, ret = -ENOMEM;
+	int i, ret;
 
 	if (nr_devs < 0 || nr_devs > STM_HEARTBEAT_MAX)
 		return -EINVAL;
@@ -72,8 +72,10 @@
 	for (i = 0; i < nr_devs; i++) {
 		stm_heartbeat[i].data.name =
 			kasprintf(GFP_KERNEL, "heartbeat.%d", i);
-		if (!stm_heartbeat[i].data.name)
+		if (!stm_heartbeat[i].data.name) {
+			ret = -ENOMEM;
 			goto fail_unregister;
+		}
 
 		stm_heartbeat[i].data.nr_chans	= 1;
 		stm_heartbeat[i].data.link	= stm_heartbeat_link;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwtracing/stm/p_sys-t.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwtracing/stm/p_sys-t.c
@@ -238,7 +238,7 @@
 static inline bool sys_t_need_ts(struct sys_t_output *op)
 {
 	if (op->node.ts_interval &&
-	    time_after(op->ts_jiffies + op->node.ts_interval, jiffies)) {
+	    time_after(jiffies, op->ts_jiffies + op->node.ts_interval)) {
 		op->ts_jiffies = jiffies;
 
 		return true;
@@ -250,8 +250,8 @@
 static bool sys_t_need_clock_sync(struct sys_t_output *op)
 {
 	if (op->node.clocksync_interval &&
-	    time_after(op->clocksync_jiffies + op->node.clocksync_interval,
-		       jiffies)) {
+	    time_after(jiffies,
+		       op->clocksync_jiffies + op->node.clocksync_interval)) {
 		op->clocksync_jiffies = jiffies;
 
 		return true;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/hwtracing/stm/policy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/hwtracing/stm/policy.c
@@ -345,7 +345,11 @@
 	stm->policy = NULL;
 	policy->stm = NULL;
 
+	/*
+	 * Drop the reference on the protocol driver and lose the link.
+	 */
 	stm_put_protocol(stm->pdrv);
+	stm->pdrv = NULL;
 	stm_put_device(stm);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/algos/i2c-algo-pca.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/algos/i2c-algo-pca.c
@@ -41,8 +41,22 @@
 		pca_outw(adap, I2C_PCA_INDPTR, I2C_PCA_IPRESET);
 		pca_outw(adap, I2C_PCA_IND, 0xA5);
 		pca_outw(adap, I2C_PCA_IND, 0x5A);
+
+		/*
+		 * After a reset we need to re-apply any configuration
+		 * (calculated in pca_init) to get the bus in a working state.
+		 */
+		pca_outw(adap, I2C_PCA_INDPTR, I2C_PCA_IMODE);
+		pca_outw(adap, I2C_PCA_IND, adap->bus_settings.mode);
+		pca_outw(adap, I2C_PCA_INDPTR, I2C_PCA_ISCLL);
+		pca_outw(adap, I2C_PCA_IND, adap->bus_settings.tlow);
+		pca_outw(adap, I2C_PCA_INDPTR, I2C_PCA_ISCLH);
+		pca_outw(adap, I2C_PCA_IND, adap->bus_settings.thi);
+
+		pca_set_con(adap, I2C_PCA_CON_ENSIO);
 	} else {
 		adap->reset_chip(adap->data);
+		pca_set_con(adap, I2C_PCA_CON_ENSIO | adap->bus_settings.clock_freq);
 	}
 }
 
@@ -314,7 +328,8 @@
 			DEB2("BUS ERROR - SDA Stuck low\n");
 			pca_reset(adap);
 			goto out;
-		case 0x90: /* Bus error - SCL stuck low */
+		case 0x78: /* Bus error - SCL stuck low (PCA9665) */
+		case 0x90: /* Bus error - SCL stuck low (PCA9564) */
 			DEB2("BUS ERROR - SCL Stuck low\n");
 			pca_reset(adap);
 			goto out;
@@ -422,13 +437,14 @@
 				" Use the nominal frequency.\n", adap->name);
 		}
 
-		pca_reset(pca_data);
-
 		clock = pca_clock(pca_data);
 		printk(KERN_INFO "%s: Clock frequency is %dkHz\n",
 		     adap->name, freqs[clock]);
 
-		pca_set_con(pca_data, I2C_PCA_CON_ENSIO | clock);
+		/* Store settings as these will be needed when the PCA chip is reset */
+		pca_data->bus_settings.clock_freq = clock;
+
+		pca_reset(pca_data);
 	} else {
 		int clock;
 		int mode;
@@ -495,19 +511,15 @@
 			thi = tlow * min_thi / min_tlow;
 		}
 
+		/* Store settings as these will be needed when the PCA chip is reset */
+		pca_data->bus_settings.mode = mode;
+		pca_data->bus_settings.tlow = tlow;
+		pca_data->bus_settings.thi = thi;
+
 		pca_reset(pca_data);
 
 		printk(KERN_INFO
 		     "%s: Clock frequency is %dHz\n", adap->name, clock * 100);
-
-		pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_IMODE);
-		pca_outw(pca_data, I2C_PCA_IND, mode);
-		pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_ISCLL);
-		pca_outw(pca_data, I2C_PCA_IND, tlow);
-		pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_ISCLH);
-		pca_outw(pca_data, I2C_PCA_IND, thi);
-
-		pca_set_con(pca_data, I2C_PCA_CON_ENSIO);
 	}
 	udelay(500); /* 500 us for oscillator to stabilise */
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/Kconfig
@@ -483,7 +483,7 @@
 
 config I2C_CADENCE
 	tristate "Cadence I2C Controller"
-	depends on ARCH_ZYNQ || ARM64 || XTENSA
+	depends on ARCH_ZYNQ || ARM64 || XTENSA || COMPILE_TEST
 	help
 	  Say yes here to select Cadence I2C Host Controller. This controller is
 	  e.g. used by Xilinx Zynq.
@@ -894,7 +894,7 @@
 
 config I2C_QUP
 	tristate "Qualcomm QUP based I2C controller"
-	depends on ARCH_QCOM
+	depends on ARCH_QCOM || COMPILE_TEST
 	help
 	  If you say yes to this option, support will be included for the
 	  built-in I2C interface on the Qualcomm SoCs.
@@ -1162,6 +1162,7 @@
 	tristate "Renesas R-Car I2C Controller"
 	depends on ARCH_RENESAS || COMPILE_TEST
 	select I2C_SLAVE
+	select RESET_CONTROLLER if ARCH_RCAR_GEN3
 	help
 	  If you say yes to this option, support will be included for the
 	  R-Car I2C controller.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-ali1535.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-ali1535.c
@@ -490,6 +490,8 @@
 
 static int ali1535_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
+	int ret;
+
 	if (ali1535_setup(dev)) {
 		dev_warn(&dev->dev,
 			"ALI1535 not detected, module not inserted.\n");
@@ -501,7 +503,15 @@
 
 	snprintf(ali1535_adapter.name, sizeof(ali1535_adapter.name),
 		"SMBus ALI1535 adapter at %04x", ali1535_offset);
-	return i2c_add_adapter(&ali1535_adapter);
+	ret = i2c_add_adapter(&ali1535_adapter);
+	if (ret)
+		goto release_region;
+
+	return 0;
+
+release_region:
+	release_region(ali1535_smba, ALI1535_SMB_IOSIZE);
+	return ret;
 }
 
 static void ali1535_remove(struct pci_dev *dev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-ali15x3.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-ali15x3.c
@@ -473,6 +473,8 @@
 
 static int ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
+	int ret;
+
 	if (ali15x3_setup(dev)) {
 		dev_err(&dev->dev,
 			"ALI15X3 not detected, module not inserted.\n");
@@ -484,7 +486,15 @@
 
 	snprintf(ali15x3_adapter.name, sizeof(ali15x3_adapter.name),
 		"SMBus ALI15X3 adapter at %04x", ali15x3_smba);
-	return i2c_add_adapter(&ali15x3_adapter);
+	ret = i2c_add_adapter(&ali15x3_adapter);
+	if (ret)
+		goto release_region;
+
+	return 0;
+
+release_region:
+	release_region(ali15x3_smba, ALI15X3_SMB_IOSIZE);
+	return ret;
 }
 
 static void ali15x3_remove(struct pci_dev *dev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-altera.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-altera.c
@@ -70,6 +70,7 @@
  * @isr_mask: cached copy of local ISR enables.
  * @isr_status: cached copy of local ISR status.
  * @lock: spinlock for IRQ synchronization.
+ * @isr_mutex: mutex for IRQ thread.
  */
 struct altr_i2c_dev {
 	void __iomem *base;
@@ -86,6 +87,7 @@
 	u32 isr_mask;
 	u32 isr_status;
 	spinlock_t lock;	/* IRQ synchronization */
+	struct mutex isr_mutex;
 };
 
 static void
@@ -171,7 +173,7 @@
 	/* SCL Low Time */
 	writel(t_low, idev->base + ALTR_I2C_SCL_LOW);
 	/* SDA Hold Time, 300ns */
-	writel(div_u64(300 * clk_mhz, 1000), idev->base + ALTR_I2C_SDA_HOLD);
+	writel(3 * clk_mhz / 10, idev->base + ALTR_I2C_SDA_HOLD);
 
 	/* Mask all master interrupt bits */
 	altr_i2c_int_enable(idev, ALTR_I2C_ALL_IRQ, false);
@@ -245,10 +247,11 @@
 	struct altr_i2c_dev *idev = _dev;
 	u32 status = idev->isr_status;
 
+	mutex_lock(&idev->isr_mutex);
 	if (!idev->msg) {
 		dev_warn(idev->dev, "unexpected interrupt\n");
 		altr_i2c_int_clear(idev, ALTR_I2C_ALL_IRQ);
-		return IRQ_HANDLED;
+		goto out;
 	}
 	read = (idev->msg->flags & I2C_M_RD) != 0;
 
@@ -301,6 +304,8 @@
 		complete(&idev->msg_complete);
 		dev_dbg(idev->dev, "Message Complete\n");
 	}
+out:
+	mutex_unlock(&idev->isr_mutex);
 
 	return IRQ_HANDLED;
 }
@@ -312,6 +317,7 @@
 	u32 value;
 	u8 addr = i2c_8bit_addr_from_msg(msg);
 
+	mutex_lock(&idev->isr_mutex);
 	idev->msg = msg;
 	idev->msg_len = msg->len;
 	idev->buf = msg->buf;
@@ -336,6 +342,7 @@
 		altr_i2c_int_enable(idev, imask, true);
 		altr_i2c_fill_tx_fifo(idev);
 	}
+	mutex_unlock(&idev->isr_mutex);
 
 	time_left = wait_for_completion_timeout(&idev->msg_complete,
 						ALTR_I2C_XFER_TIMEOUT);
@@ -384,7 +391,6 @@
 	struct altr_i2c_dev *idev = NULL;
 	struct resource *res;
 	int irq, ret;
-	u32 val;
 
 	idev = devm_kzalloc(&pdev->dev, sizeof(*idev), GFP_KERNEL);
 	if (!idev)
@@ -410,18 +416,19 @@
 	idev->dev = &pdev->dev;
 	init_completion(&idev->msg_complete);
 	spin_lock_init(&idev->lock);
+	mutex_init(&idev->isr_mutex);
 
-	val = device_property_read_u32(idev->dev, "fifo-size",
+	ret = device_property_read_u32(idev->dev, "fifo-size",
 				       &idev->fifo_size);
-	if (val) {
+	if (ret) {
 		dev_err(&pdev->dev, "FIFO size set to default of %d\n",
 			ALTR_I2C_DFLT_FIFO_SZ);
 		idev->fifo_size = ALTR_I2C_DFLT_FIFO_SZ;
 	}
 
-	val = device_property_read_u32(idev->dev, "clock-frequency",
+	ret = device_property_read_u32(idev->dev, "clock-frequency",
 				       &idev->bus_clk_rate);
-	if (val) {
+	if (ret) {
 		dev_err(&pdev->dev, "Default to 100kHz\n");
 		idev->bus_clk_rate = 100000;	/* default clock rate */
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-amd-mp2-pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-amd-mp2-pci.c
@@ -349,12 +349,12 @@
 	if (!privdata)
 		return -ENOMEM;
 
+	privdata->pci_dev = pci_dev;
 	rc = amd_mp2_pci_init(privdata, pci_dev);
 	if (rc)
 		return rc;
 
 	mutex_init(&privdata->c2p_lock);
-	privdata->pci_dev = pci_dev;
 
 	pm_runtime_set_autosuspend_delay(&pci_dev->dev, 1000);
 	pm_runtime_use_autosuspend(&pci_dev->dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-aspeed.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-aspeed.c
@@ -69,6 +69,7 @@
  * These share bit definitions, so use the same values for the enable &
  * status bits.
  */
+#define ASPEED_I2CD_INTR_RECV_MASK			0xf000ffff
 #define ASPEED_I2CD_INTR_SDA_DL_TIMEOUT			BIT(14)
 #define ASPEED_I2CD_INTR_BUS_RECOVER_DONE		BIT(13)
 #define ASPEED_I2CD_INTR_SLAVE_MATCH			BIT(7)
@@ -171,6 +172,13 @@
 
 static int aspeed_i2c_reset(struct aspeed_i2c_bus *bus);
 
+/* precondition: bus.lock has been acquired. */
+static void aspeed_i2c_do_stop(struct aspeed_i2c_bus *bus)
+{
+	bus->master_state = ASPEED_I2C_MASTER_STOP;
+	writel(ASPEED_I2CD_M_STOP_CMD, bus->base + ASPEED_I2C_CMD_REG);
+}
+
 static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus)
 {
 	unsigned long time_left, flags;
@@ -188,7 +196,7 @@
 			command);
 
 		reinit_completion(&bus->cmd_complete);
-		writel(ASPEED_I2CD_M_STOP_CMD, bus->base + ASPEED_I2C_CMD_REG);
+		aspeed_i2c_do_stop(bus);
 		spin_unlock_irqrestore(&bus->lock, flags);
 
 		time_left = wait_for_completion_timeout(
@@ -249,18 +257,46 @@
 	if (!slave)
 		return 0;
 
-	command = readl(bus->base + ASPEED_I2C_CMD_REG);
+	/*
+	 * Handle stop conditions early, prior to SLAVE_MATCH. Some masters may drive
+	 * transfers with low enough latency between the nak/stop phase of the current
+	 * command and the start/address phase of the following command that the
+	 * interrupts are coalesced by the time we process them.
+	 */
+	if (irq_status & ASPEED_I2CD_INTR_NORMAL_STOP) {
+		irq_handled |= ASPEED_I2CD_INTR_NORMAL_STOP;
+		bus->slave_state = ASPEED_I2C_SLAVE_STOP;
+	}
+
+	if (irq_status & ASPEED_I2CD_INTR_TX_NAK &&
+	    bus->slave_state == ASPEED_I2C_SLAVE_READ_PROCESSED) {
+		irq_handled |= ASPEED_I2CD_INTR_TX_NAK;
+		bus->slave_state = ASPEED_I2C_SLAVE_STOP;
+	}
 
-	/* Slave was requested, restart state machine. */
+	/* Propagate any stop conditions to the slave implementation. */
+	if (bus->slave_state == ASPEED_I2C_SLAVE_STOP) {
+		i2c_slave_event(slave, I2C_SLAVE_STOP, &value);
+		bus->slave_state = ASPEED_I2C_SLAVE_INACTIVE;
+	}
+
+	/*
+	 * Now that we've dealt with any potentially coalesced stop conditions,
+	 * address any start conditions.
+	 */
 	if (irq_status & ASPEED_I2CD_INTR_SLAVE_MATCH) {
 		irq_handled |= ASPEED_I2CD_INTR_SLAVE_MATCH;
 		bus->slave_state = ASPEED_I2C_SLAVE_START;
 	}
 
-	/* Slave is not currently active, irq was for someone else. */
+	/*
+	 * If the slave has been stopped and not started then slave interrupt
+	 * handling is complete.
+	 */
 	if (bus->slave_state == ASPEED_I2C_SLAVE_INACTIVE)
 		return irq_handled;
 
+	command = readl(bus->base + ASPEED_I2C_CMD_REG);
 	dev_dbg(bus->dev, "slave irq status 0x%08x, cmd 0x%08x\n",
 		irq_status, command);
 
@@ -279,17 +315,6 @@
 		irq_handled |= ASPEED_I2CD_INTR_RX_DONE;
 	}
 
-	/* Slave was asked to stop. */
-	if (irq_status & ASPEED_I2CD_INTR_NORMAL_STOP) {
-		irq_handled |= ASPEED_I2CD_INTR_NORMAL_STOP;
-		bus->slave_state = ASPEED_I2C_SLAVE_STOP;
-	}
-	if (irq_status & ASPEED_I2CD_INTR_TX_NAK &&
-	    bus->slave_state == ASPEED_I2C_SLAVE_READ_PROCESSED) {
-		irq_handled |= ASPEED_I2CD_INTR_TX_NAK;
-		bus->slave_state = ASPEED_I2C_SLAVE_STOP;
-	}
-
 	switch (bus->slave_state) {
 	case ASPEED_I2C_SLAVE_READ_REQUESTED:
 		if (unlikely(irq_status & ASPEED_I2CD_INTR_TX_ACK))
@@ -318,8 +343,7 @@
 		i2c_slave_event(slave, I2C_SLAVE_WRITE_RECEIVED, &value);
 		break;
 	case ASPEED_I2C_SLAVE_STOP:
-		i2c_slave_event(slave, I2C_SLAVE_STOP, &value);
-		bus->slave_state = ASPEED_I2C_SLAVE_INACTIVE;
+		/* Stop event handling is done early. Unreachable. */
 		break;
 	case ASPEED_I2C_SLAVE_START:
 		/* Slave was just started. Waiting for the next event. */;
@@ -369,13 +393,6 @@
 }
 
 /* precondition: bus.lock has been acquired. */
-static void aspeed_i2c_do_stop(struct aspeed_i2c_bus *bus)
-{
-	bus->master_state = ASPEED_I2C_MASTER_STOP;
-	writel(ASPEED_I2CD_M_STOP_CMD, bus->base + ASPEED_I2C_CMD_REG);
-}
-
-/* precondition: bus.lock has been acquired. */
 static void aspeed_i2c_next_msg_or_stop(struct aspeed_i2c_bus *bus)
 {
 	if (bus->msgs_index + 1 < bus->msgs_count) {
@@ -603,6 +620,8 @@
 	/* Ack all interrupts except for Rx done */
 	writel(irq_received & ~ASPEED_I2CD_INTR_RX_DONE,
 	       bus->base + ASPEED_I2C_INTR_STS_REG);
+	readl(bus->base + ASPEED_I2C_INTR_STS_REG);
+	irq_received &= ASPEED_I2CD_INTR_RECV_MASK;
 	irq_remaining = irq_received;
 
 #if IS_ENABLED(CONFIG_I2C_SLAVE)
@@ -645,9 +664,11 @@
 			irq_received, irq_handled);
 
 	/* Ack Rx done */
-	if (irq_received & ASPEED_I2CD_INTR_RX_DONE)
+	if (irq_received & ASPEED_I2CD_INTR_RX_DONE) {
 		writel(ASPEED_I2CD_INTR_RX_DONE,
 		       bus->base + ASPEED_I2C_INTR_STS_REG);
+		readl(bus->base + ASPEED_I2C_INTR_STS_REG);
+	}
 	spin_unlock(&bus->lock);
 	return irq_remaining ? IRQ_NONE : IRQ_HANDLED;
 }
@@ -688,13 +709,16 @@
 
 	if (time_left == 0) {
 		/*
-		 * If timed out and bus is still busy in a multi master
-		 * environment, attempt recovery at here.
+		 * In a multi-master setup, if a timeout occurs, attempt
+		 * recovery. But if the bus is idle, we still need to reset the
+		 * i2c controller to clear the remaining interrupts.
 		 */
 		if (bus->multi_master &&
 		    (readl(bus->base + ASPEED_I2C_CMD_REG) &
 		     ASPEED_I2CD_BUS_BUSY_STS))
 			aspeed_i2c_recover_bus(bus);
+		else
+			aspeed_i2c_reset(bus);
 
 		/*
 		 * If timed out and the state is still pending, drop the pending
@@ -732,6 +756,8 @@
 	func_ctrl_reg_val = readl(bus->base + ASPEED_I2C_FUN_CTRL_REG);
 	func_ctrl_reg_val |= ASPEED_I2CD_SLAVE_EN;
 	writel(func_ctrl_reg_val, bus->base + ASPEED_I2C_FUN_CTRL_REG);
+
+	bus->slave_state = ASPEED_I2C_SLAVE_INACTIVE;
 }
 
 static int aspeed_i2c_reg_slave(struct i2c_client *client)
@@ -748,7 +774,6 @@
 	__aspeed_i2c_reg_slave(bus, client->addr);
 
 	bus->slave = client;
-	bus->slave_state = ASPEED_I2C_SLAVE_INACTIVE;
 	spin_unlock_irqrestore(&bus->lock, flags);
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-at91-master.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-at91-master.c
@@ -609,6 +609,7 @@
 	unsigned int_addr_flag = 0;
 	struct i2c_msg *m_start = msg;
 	bool is_read;
+	u8 *dma_buf = NULL;
 
 	dev_dbg(&adap->dev, "at91_xfer: processing %d messages:\n", num);
 
@@ -656,7 +657,17 @@
 	dev->msg = m_start;
 	dev->recv_len_abort = false;
 
+	if (dev->use_dma) {
+		dma_buf = i2c_get_dma_safe_msg_buf(m_start, 1);
+		if (!dma_buf) {
+			ret = -ENOMEM;
+			goto out;
+		}
+		dev->buf = dma_buf;
+	}
+
 	ret = at91_do_twi_transfer(dev);
+	i2c_put_dma_safe_msg_buf(dma_buf, m_start, !ret);
 
 	ret = (ret < 0) ? ret : num;
 out:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-at91-slave.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-at91-slave.c
@@ -106,8 +106,7 @@
 
 static u32 at91_twi_func(struct i2c_adapter *adapter)
 {
-	return I2C_FUNC_SLAVE | I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL
-		| I2C_FUNC_SMBUS_READ_BLOCK_DATA;
+	return I2C_FUNC_SLAVE;
 }
 
 static const struct i2c_algorithm at91_twi_algorithm_slave = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-bcm-iproc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-bcm-iproc.c
@@ -157,6 +157,11 @@
 
 #define IE_S_ALL_INTERRUPT_SHIFT     21
 #define IE_S_ALL_INTERRUPT_MASK      0x3f
+/*
+ * It takes ~18us to reading 10bytes of data, hence to keep tasklet
+ * running for less time, max slave read per tasklet is set to 10 bytes.
+ */
+#define MAX_SLAVE_RX_PER_INT         10
 
 enum i2c_slave_read_status {
 	I2C_SLAVE_RX_FIFO_EMPTY = 0,
@@ -203,8 +208,18 @@
 	/* bytes that have been read */
 	unsigned int rx_bytes;
 	unsigned int thld_bytes;
+
+	bool slave_rx_only;
+	bool rx_start_rcvd;
+	bool slave_read_complete;
+	u32 tx_underrun;
+	u32 slave_int_mask;
+	struct tasklet_struct slave_rx_tasklet;
 };
 
+/* tasklet to process slave rx data */
+static void slave_rx_tasklet_fn(unsigned long);
+
 /*
  * Can be expanded in the future if more interrupt status bits are utilized
  */
@@ -213,7 +228,8 @@
 
 #define ISR_MASK_SLAVE (BIT(IS_S_START_BUSY_SHIFT)\
 		| BIT(IS_S_RX_EVENT_SHIFT) | BIT(IS_S_RD_EVENT_SHIFT)\
-		| BIT(IS_S_TX_UNDERRUN_SHIFT))
+		| BIT(IS_S_TX_UNDERRUN_SHIFT) | BIT(IS_S_RX_FIFO_FULL_SHIFT)\
+		| BIT(IS_S_RX_THLD_SHIFT))
 
 static int bcm_iproc_i2c_reg_slave(struct i2c_client *slave);
 static int bcm_iproc_i2c_unreg_slave(struct i2c_client *slave);
@@ -224,13 +240,14 @@
 				   u32 offset)
 {
 	u32 val;
+	unsigned long flags;
 
 	if (iproc_i2c->idm_base) {
-		spin_lock(&iproc_i2c->idm_lock);
+		spin_lock_irqsave(&iproc_i2c->idm_lock, flags);
 		writel(iproc_i2c->ape_addr_mask,
 		       iproc_i2c->idm_base + IDM_CTRL_DIRECT_OFFSET);
 		val = readl(iproc_i2c->base + offset);
-		spin_unlock(&iproc_i2c->idm_lock);
+		spin_unlock_irqrestore(&iproc_i2c->idm_lock, flags);
 	} else {
 		val = readl(iproc_i2c->base + offset);
 	}
@@ -241,12 +258,14 @@
 static inline void iproc_i2c_wr_reg(struct bcm_iproc_i2c_dev *iproc_i2c,
 				    u32 offset, u32 val)
 {
+	unsigned long flags;
+
 	if (iproc_i2c->idm_base) {
-		spin_lock(&iproc_i2c->idm_lock);
+		spin_lock_irqsave(&iproc_i2c->idm_lock, flags);
 		writel(iproc_i2c->ape_addr_mask,
 		       iproc_i2c->idm_base + IDM_CTRL_DIRECT_OFFSET);
 		writel(val, iproc_i2c->base + offset);
-		spin_unlock(&iproc_i2c->idm_lock);
+		spin_unlock_irqrestore(&iproc_i2c->idm_lock, flags);
 	} else {
 		writel(val, iproc_i2c->base + offset);
 	}
@@ -257,6 +276,7 @@
 {
 	u32 val;
 
+	iproc_i2c->tx_underrun = 0;
 	if (need_reset) {
 		/* put controller in reset */
 		val = iproc_i2c_rd_reg(iproc_i2c, CFG_OFFSET);
@@ -293,8 +313,11 @@
 
 	/* Enable interrupt register to indicate a valid byte in receive fifo */
 	val = BIT(IE_S_RX_EVENT_SHIFT);
+	/* Enable interrupt register to indicate a Master read transaction */
+	val |= BIT(IE_S_RD_EVENT_SHIFT);
 	/* Enable interrupt register for the Slave BUSY command */
 	val |= BIT(IE_S_START_BUSY_SHIFT);
+	iproc_i2c->slave_int_mask = val;
 	iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, val);
 }
 
@@ -319,73 +342,176 @@
 	}
 }
 
-static bool bcm_iproc_i2c_slave_isr(struct bcm_iproc_i2c_dev *iproc_i2c,
-				    u32 status)
+static void bcm_iproc_i2c_slave_read(struct bcm_iproc_i2c_dev *iproc_i2c)
 {
+	u8 rx_data, rx_status;
+	u32 rx_bytes = 0;
 	u32 val;
-	u8 value, rx_status;
 
-	/* Slave RX byte receive */
-	if (status & BIT(IS_S_RX_EVENT_SHIFT)) {
+	while (rx_bytes < MAX_SLAVE_RX_PER_INT) {
 		val = iproc_i2c_rd_reg(iproc_i2c, S_RX_OFFSET);
 		rx_status = (val >> S_RX_STATUS_SHIFT) & S_RX_STATUS_MASK;
-		if (rx_status == I2C_SLAVE_RX_START) {
-			/* Start of SMBUS for Master write */
-			i2c_slave_event(iproc_i2c->slave,
-					I2C_SLAVE_WRITE_REQUESTED, &value);
+		rx_data = ((val >> S_RX_DATA_SHIFT) & S_RX_DATA_MASK);
 
-			val = iproc_i2c_rd_reg(iproc_i2c, S_RX_OFFSET);
-			value = (u8)((val >> S_RX_DATA_SHIFT) & S_RX_DATA_MASK);
+		if (rx_status == I2C_SLAVE_RX_START) {
+			/* Start of SMBUS Master write */
 			i2c_slave_event(iproc_i2c->slave,
-					I2C_SLAVE_WRITE_RECEIVED, &value);
-		} else if (status & BIT(IS_S_RD_EVENT_SHIFT)) {
-			/* Start of SMBUS for Master Read */
+					I2C_SLAVE_WRITE_REQUESTED, &rx_data);
+			iproc_i2c->rx_start_rcvd = true;
+			iproc_i2c->slave_read_complete = false;
+		} else if (rx_status == I2C_SLAVE_RX_DATA &&
+			   iproc_i2c->rx_start_rcvd) {
+			/* Middle of SMBUS Master write */
 			i2c_slave_event(iproc_i2c->slave,
-					I2C_SLAVE_READ_REQUESTED, &value);
-			iproc_i2c_wr_reg(iproc_i2c, S_TX_OFFSET, value);
+					I2C_SLAVE_WRITE_RECEIVED, &rx_data);
+		} else if (rx_status == I2C_SLAVE_RX_END &&
+			   iproc_i2c->rx_start_rcvd) {
+			/* End of SMBUS Master write */
+			if (iproc_i2c->slave_rx_only)
+				i2c_slave_event(iproc_i2c->slave,
+						I2C_SLAVE_WRITE_RECEIVED,
+						&rx_data);
+
+			i2c_slave_event(iproc_i2c->slave, I2C_SLAVE_STOP,
+					&rx_data);
+		} else if (rx_status == I2C_SLAVE_RX_FIFO_EMPTY) {
+			iproc_i2c->rx_start_rcvd = false;
+			iproc_i2c->slave_read_complete = true;
+			break;
+		}
 
-			val = BIT(S_CMD_START_BUSY_SHIFT);
-			iproc_i2c_wr_reg(iproc_i2c, S_CMD_OFFSET, val);
+		rx_bytes++;
+	}
+}
 
-			/*
-			 * Enable interrupt for TX FIFO becomes empty and
-			 * less than PKT_LENGTH bytes were output on the SMBUS
-			 */
-			val = iproc_i2c_rd_reg(iproc_i2c, IE_OFFSET);
-			val |= BIT(IE_S_TX_UNDERRUN_SHIFT);
-			iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, val);
-		} else {
-			/* Master write other than start */
-			value = (u8)((val >> S_RX_DATA_SHIFT) & S_RX_DATA_MASK);
+static void slave_rx_tasklet_fn(unsigned long data)
+{
+	struct bcm_iproc_i2c_dev *iproc_i2c = (struct bcm_iproc_i2c_dev *)data;
+	u32 int_clr;
+
+	bcm_iproc_i2c_slave_read(iproc_i2c);
+
+	/* clear pending IS_S_RX_EVENT_SHIFT interrupt */
+	int_clr = BIT(IS_S_RX_EVENT_SHIFT);
+
+	if (!iproc_i2c->slave_rx_only && iproc_i2c->slave_read_complete) {
+		/*
+		 * In case of single byte master-read request,
+		 * IS_S_TX_UNDERRUN_SHIFT event is generated before
+		 * IS_S_START_BUSY_SHIFT event. Hence start slave data send
+		 * from first IS_S_TX_UNDERRUN_SHIFT event.
+		 *
+		 * This means don't send any data from slave when
+		 * IS_S_RD_EVENT_SHIFT event is generated else it will increment
+		 * eeprom or other backend slave driver read pointer twice.
+		 */
+		iproc_i2c->tx_underrun = 0;
+		iproc_i2c->slave_int_mask |= BIT(IE_S_TX_UNDERRUN_SHIFT);
+
+		/* clear IS_S_RD_EVENT_SHIFT interrupt */
+		int_clr |= BIT(IS_S_RD_EVENT_SHIFT);
+	}
+
+	/* clear slave interrupt */
+	iproc_i2c_wr_reg(iproc_i2c, IS_OFFSET, int_clr);
+	/* enable slave interrupts */
+	iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, iproc_i2c->slave_int_mask);
+}
+
+static bool bcm_iproc_i2c_slave_isr(struct bcm_iproc_i2c_dev *iproc_i2c,
+				    u32 status)
+{
+	u32 val;
+	u8 value;
+
+	/*
+	 * Slave events in case of master-write, master-write-read and,
+	 * master-read
+	 *
+	 * Master-write     : only IS_S_RX_EVENT_SHIFT event
+	 * Master-write-read: both IS_S_RX_EVENT_SHIFT and IS_S_RD_EVENT_SHIFT
+	 *                    events
+	 * Master-read      : both IS_S_RX_EVENT_SHIFT and IS_S_RD_EVENT_SHIFT
+	 *                    events or only IS_S_RD_EVENT_SHIFT
+	 */
+	if (status & BIT(IS_S_RX_EVENT_SHIFT) ||
+	    status & BIT(IS_S_RD_EVENT_SHIFT)) {
+		/* disable slave interrupts */
+		val = iproc_i2c_rd_reg(iproc_i2c, IE_OFFSET);
+		val &= ~iproc_i2c->slave_int_mask;
+		iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, val);
+
+		if (status & BIT(IS_S_RD_EVENT_SHIFT))
+			/* Master-write-read request */
+			iproc_i2c->slave_rx_only = false;
+		else
+			/* Master-write request only */
+			iproc_i2c->slave_rx_only = true;
+
+		/* schedule tasklet to read data later */
+		tasklet_schedule(&iproc_i2c->slave_rx_tasklet);
+
+		/* clear only IS_S_RX_EVENT_SHIFT interrupt */
+		iproc_i2c_wr_reg(iproc_i2c, IS_OFFSET,
+				 BIT(IS_S_RX_EVENT_SHIFT));
+	}
+
+	if (status & BIT(IS_S_TX_UNDERRUN_SHIFT)) {
+		iproc_i2c->tx_underrun++;
+		if (iproc_i2c->tx_underrun == 1)
+			/* Start of SMBUS for Master Read */
 			i2c_slave_event(iproc_i2c->slave,
-					I2C_SLAVE_WRITE_RECEIVED, &value);
-		}
-	} else if (status & BIT(IS_S_TX_UNDERRUN_SHIFT)) {
-		/* Master read other than start */
-		i2c_slave_event(iproc_i2c->slave,
-				I2C_SLAVE_READ_PROCESSED, &value);
+					I2C_SLAVE_READ_REQUESTED,
+					&value);
+		else
+			/* Master read other than start */
+			i2c_slave_event(iproc_i2c->slave,
+					I2C_SLAVE_READ_PROCESSED,
+					&value);
 
 		iproc_i2c_wr_reg(iproc_i2c, S_TX_OFFSET, value);
+		/* start transfer */
 		val = BIT(S_CMD_START_BUSY_SHIFT);
 		iproc_i2c_wr_reg(iproc_i2c, S_CMD_OFFSET, val);
+
+		/* clear interrupt */
+		iproc_i2c_wr_reg(iproc_i2c, IS_OFFSET,
+				 BIT(IS_S_TX_UNDERRUN_SHIFT));
 	}
 
-	/* Stop */
+	/* Stop received from master in case of master read transaction */
 	if (status & BIT(IS_S_START_BUSY_SHIFT)) {
-		i2c_slave_event(iproc_i2c->slave, I2C_SLAVE_STOP, &value);
 		/*
 		 * Enable interrupt for TX FIFO becomes empty and
 		 * less than PKT_LENGTH bytes were output on the SMBUS
 		 */
-		val = iproc_i2c_rd_reg(iproc_i2c, IE_OFFSET);
-		val &= ~BIT(IE_S_TX_UNDERRUN_SHIFT);
-		iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, val);
+		iproc_i2c->slave_int_mask &= ~BIT(IE_S_TX_UNDERRUN_SHIFT);
+		iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET,
+				 iproc_i2c->slave_int_mask);
+
+		/* End of SMBUS for Master Read */
+		val = BIT(S_TX_WR_STATUS_SHIFT);
+		iproc_i2c_wr_reg(iproc_i2c, S_TX_OFFSET, val);
+
+		val = BIT(S_CMD_START_BUSY_SHIFT);
+		iproc_i2c_wr_reg(iproc_i2c, S_CMD_OFFSET, val);
+
+		/* flush TX FIFOs */
+		val = iproc_i2c_rd_reg(iproc_i2c, S_FIFO_CTRL_OFFSET);
+		val |= (BIT(S_FIFO_TX_FLUSH_SHIFT));
+		iproc_i2c_wr_reg(iproc_i2c, S_FIFO_CTRL_OFFSET, val);
+
+		i2c_slave_event(iproc_i2c->slave, I2C_SLAVE_STOP, &value);
+
+		/* clear interrupt */
+		iproc_i2c_wr_reg(iproc_i2c, IS_OFFSET,
+				 BIT(IS_S_START_BUSY_SHIFT));
 	}
 
-	/* clear interrupt status */
-	iproc_i2c_wr_reg(iproc_i2c, IS_OFFSET, status);
+	/* check slave transmit status only if slave is transmitting */
+	if (!iproc_i2c->slave_rx_only)
+		bcm_iproc_i2c_check_slave_status(iproc_i2c);
 
-	bcm_iproc_i2c_check_slave_status(iproc_i2c);
 	return true;
 }
 
@@ -500,12 +626,17 @@
 static irqreturn_t bcm_iproc_i2c_isr(int irq, void *data)
 {
 	struct bcm_iproc_i2c_dev *iproc_i2c = data;
-	u32 status = iproc_i2c_rd_reg(iproc_i2c, IS_OFFSET);
+	u32 slave_status;
+	u32 status;
 	bool ret;
-	u32 sl_status = status & ISR_MASK_SLAVE;
 
-	if (sl_status) {
-		ret = bcm_iproc_i2c_slave_isr(iproc_i2c, sl_status);
+	status = iproc_i2c_rd_reg(iproc_i2c, IS_OFFSET);
+	/* process only slave interrupt which are enabled */
+	slave_status = status & iproc_i2c_rd_reg(iproc_i2c, IE_OFFSET) &
+		       ISR_MASK_SLAVE;
+
+	if (slave_status) {
+		ret = bcm_iproc_i2c_slave_isr(iproc_i2c, slave_status);
 		if (ret)
 			return IRQ_HANDLED;
 		else
@@ -1022,6 +1153,10 @@
 		return -EAFNOSUPPORT;
 
 	iproc_i2c->slave = slave;
+
+	tasklet_init(&iproc_i2c->slave_rx_tasklet, slave_rx_tasklet_fn,
+		     (unsigned long)iproc_i2c);
+
 	bcm_iproc_i2c_slave_init(iproc_i2c, false);
 	return 0;
 }
@@ -1034,7 +1169,7 @@
 	if (!iproc_i2c->slave)
 		return -EINVAL;
 
-	iproc_i2c->slave = NULL;
+	disable_irq(iproc_i2c->irq);
 
 	/* disable all slave interrupts */
 	tmp = iproc_i2c_rd_reg(iproc_i2c, IE_OFFSET);
@@ -1042,11 +1177,24 @@
 			IE_S_ALL_INTERRUPT_SHIFT);
 	iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, tmp);
 
+	tasklet_kill(&iproc_i2c->slave_rx_tasklet);
+
 	/* Erase the slave address programmed */
 	tmp = iproc_i2c_rd_reg(iproc_i2c, S_CFG_SMBUS_ADDR_OFFSET);
 	tmp &= ~BIT(S_CFG_EN_NIC_SMB_ADDR3_SHIFT);
 	iproc_i2c_wr_reg(iproc_i2c, S_CFG_SMBUS_ADDR_OFFSET, tmp);
 
+	/* flush TX/RX FIFOs */
+	tmp = (BIT(S_FIFO_RX_FLUSH_SHIFT) | BIT(S_FIFO_TX_FLUSH_SHIFT));
+	iproc_i2c_wr_reg(iproc_i2c, S_FIFO_CTRL_OFFSET, tmp);
+
+	/* clear all pending slave interrupts */
+	iproc_i2c_wr_reg(iproc_i2c, IS_OFFSET, ISR_MASK_SLAVE);
+
+	iproc_i2c->slave = NULL;
+
+	enable_irq(iproc_i2c->irq);
+
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-bcm2835.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-bcm2835.c
@@ -23,6 +23,11 @@
 #define BCM2835_I2C_FIFO	0x10
 #define BCM2835_I2C_DIV		0x14
 #define BCM2835_I2C_DEL		0x18
+/*
+ * 16-bit field for the number of SCL cycles to wait after rising SCL
+ * before deciding the slave is not responding. 0 disables the
+ * timeout detection.
+ */
 #define BCM2835_I2C_CLKT	0x1c
 
 #define BCM2835_I2C_C_READ	BIT(0)
@@ -58,6 +63,7 @@
 	struct i2c_adapter adapter;
 	struct completion completion;
 	struct i2c_msg *curr_msg;
+	struct clk *bus_clk;
 	int num_msgs;
 	u32 msg_err;
 	u8 *msg_buf;
@@ -404,7 +410,6 @@
 	struct resource *mem, *irq;
 	int ret;
 	struct i2c_adapter *adap;
-	struct clk *bus_clk;
 	struct clk *mclk;
 	u32 bus_clk_rate;
 
@@ -427,11 +432,11 @@
 		return PTR_ERR(mclk);
 	}
 
-	bus_clk = bcm2835_i2c_register_div(&pdev->dev, mclk, i2c_dev);
+	i2c_dev->bus_clk = bcm2835_i2c_register_div(&pdev->dev, mclk, i2c_dev);
 
-	if (IS_ERR(bus_clk)) {
+	if (IS_ERR(i2c_dev->bus_clk)) {
 		dev_err(&pdev->dev, "Could not register clock\n");
-		return PTR_ERR(bus_clk);
+		return PTR_ERR(i2c_dev->bus_clk);
 	}
 
 	ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency",
@@ -442,13 +447,13 @@
 		bus_clk_rate = 100000;
 	}
 
-	ret = clk_set_rate_exclusive(bus_clk, bus_clk_rate);
+	ret = clk_set_rate_exclusive(i2c_dev->bus_clk, bus_clk_rate);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "Could not set clock frequency\n");
 		return ret;
 	}
 
-	ret = clk_prepare_enable(bus_clk);
+	ret = clk_prepare_enable(i2c_dev->bus_clk);
 	if (ret) {
 		dev_err(&pdev->dev, "Couldn't prepare clock");
 		return ret;
@@ -479,6 +484,12 @@
 	adap->dev.of_node = pdev->dev.of_node;
 	adap->quirks = of_device_get_match_data(&pdev->dev);
 
+	/*
+	 * Disable the hardware clock stretching timeout. SMBUS
+	 * specifies a limit for how long the device can stretch the
+	 * clock, but core I2C doesn't.
+	 */
+	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_CLKT, 0);
 	bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, 0);
 
 	ret = i2c_add_adapter(adap);
@@ -491,10 +502,9 @@
 static int bcm2835_i2c_remove(struct platform_device *pdev)
 {
 	struct bcm2835_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
-	struct clk *bus_clk = devm_clk_get(i2c_dev->dev, "div");
 
-	clk_rate_exclusive_put(bus_clk);
-	clk_disable_unprepare(bus_clk);
+	clk_rate_exclusive_put(i2c_dev->bus_clk);
+	clk_disable_unprepare(i2c_dev->bus_clk);
 
 	free_irq(i2c_dev->irq, i2c_dev);
 	i2c_del_adapter(&i2c_dev->adapter);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-brcmstb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-brcmstb.c
@@ -316,7 +316,7 @@
 		goto cmd_out;
 	}
 
-	if ((CMD_RD || CMD_WR) &&
+	if ((cmd == CMD_RD || cmd == CMD_WR) &&
 	    bsc_readl(dev, iic_enable) & BSC_IIC_EN_NOACK_MASK) {
 		rc = -EREMOTEIO;
 		dev_dbg(dev->device, "controller received NOACK intr for %s\n",
@@ -640,7 +640,7 @@
 
 	/* set the data in/out register size for compatible SoCs */
 	if (of_device_is_compatible(dev->device->of_node,
-				    "brcmstb,brcmper-i2c"))
+				    "brcm,brcmper-i2c"))
 		dev->data_regsz = sizeof(u8);
 	else
 		dev->data_regsz = sizeof(u32);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-cadence.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-cadence.c
@@ -7,13 +7,16 @@
 
 #include <linux/clk.h>
 #include <linux/delay.h>
+#include <linux/gpio/consumer.h>
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/of.h>
+#include <linux/of_gpio.h>
 #include <linux/pm_runtime.h>
+#include <linux/pinctrl/consumer.h>
 
 /* Register offsets for the I2C device. */
 #define CDNS_I2C_CR_OFFSET		0x00 /* Control Register, RW */
@@ -22,11 +25,14 @@
 #define CDNS_I2C_DATA_OFFSET		0x0C /* I2C Data Register, RW */
 #define CDNS_I2C_ISR_OFFSET		0x10 /* IRQ Status Register, RW */
 #define CDNS_I2C_XFER_SIZE_OFFSET	0x14 /* Transfer Size Register, RW */
+#define CDNS_I2C_SLV_PAUSE_OFFSET	0x18 /* Transfer Size Register, RW */
 #define CDNS_I2C_TIME_OUT_OFFSET	0x1C /* Time Out Register, RW */
+#define CDNS_I2C_IMR_OFFSET		0x20 /* IRQ Mask Register, RO */
 #define CDNS_I2C_IER_OFFSET		0x24 /* IRQ Enable Register, WO */
 #define CDNS_I2C_IDR_OFFSET		0x28 /* IRQ Disable Register, WO */
 
 /* Control Register Bit mask definitions */
+#define CDNS_I2C_CR_SLVMON		BIT(5) /* Slave monitor mode bit */
 #define CDNS_I2C_CR_HOLD		BIT(4) /* Hold Bus bit */
 #define CDNS_I2C_CR_ACK_EN		BIT(3)
 #define CDNS_I2C_CR_NEA			BIT(2)
@@ -42,7 +48,9 @@
 
 /* Status Register Bit mask definitions */
 #define CDNS_I2C_SR_BA		BIT(8)
+#define CDNS_I2C_SR_TXDV	BIT(6)
 #define CDNS_I2C_SR_RXDV	BIT(5)
+#define CDNS_I2C_SR_RXRW	BIT(3)
 
 /*
  * I2C Address Register Bit mask definitions
@@ -91,6 +99,14 @@
 					 CDNS_I2C_IXR_DATA | \
 					 CDNS_I2C_IXR_COMP)
 
+#define CDNS_I2C_IXR_SLAVE_INTR_MASK	(CDNS_I2C_IXR_RX_UNF | \
+					 CDNS_I2C_IXR_TX_OVF | \
+					 CDNS_I2C_IXR_RX_OVF | \
+					 CDNS_I2C_IXR_TO | \
+					 CDNS_I2C_IXR_NACK | \
+					 CDNS_I2C_IXR_DATA | \
+					 CDNS_I2C_IXR_COMP)
+
 #define CDNS_I2C_TIMEOUT		msecs_to_jiffies(1000)
 /* timeout for pm runtime autosuspend */
 #define CNDS_I2C_PM_TIMEOUT		1000	/* ms */
@@ -117,6 +133,32 @@
 #define cdns_i2c_readreg(offset)       readl_relaxed(id->membase + offset)
 #define cdns_i2c_writereg(val, offset) writel_relaxed(val, id->membase + offset)
 
+#if IS_ENABLED(CONFIG_I2C_SLAVE)
+/**
+ * enum cdns_i2c_mode - I2C Controller current operating mode
+ *
+ * @CDNS_I2C_MODE_MASTER:      I2C Controller operating in master mode
+ * @CDNS_I2C_MODE_SLAVE:       I2C controller operating in slave mode
+ */
+enum cdns_i2c_mode {
+	CDNS_I2C_MODE_MASTER,
+	CDNS_I2C_MODE_SLAVE,
+};
+
+/**
+ * enum cdns_i2c_slave_mode - Slave state when I2C is operating in slave mode
+ *
+ * @CDNS_I2C_SLAVE_STATE_IDLE: I2C slave idle
+ * @CDNS_I2C_SLAVE_STATE_SEND: I2C slave sending data to master
+ * @CDNS_I2C_SLAVE_STATE_RECV: I2C slave receiving data from master
+ */
+enum cdns_i2c_slave_state {
+	CDNS_I2C_SLAVE_STATE_IDLE,
+	CDNS_I2C_SLAVE_STATE_SEND,
+	CDNS_I2C_SLAVE_STATE_RECV,
+};
+#endif
+
 /**
  * struct cdns_i2c - I2C device private data structure
  *
@@ -138,6 +180,13 @@
  * @clk:		Pointer to struct clk
  * @clk_rate_change_nb:	Notifier block for clock rate changes
  * @quirks:		flag for broken hold bit usage in r1p10
+ * @ctrl_reg:		Cached value of the control register.
+ * @rinfo:		Structure holding recovery information.
+ * @pinctrl:		Pin control state holder.
+ * @pinctrl_pins_default: Default pin control state.
+ * @pinctrl_pins_gpio:	GPIO pin control state.
+ * @slave:		Registered slave instance.
+ * @slave_state:	I2C Slave state(idle/read/write).
  */
 struct cdns_i2c {
 	struct device		*dev;
@@ -158,6 +207,15 @@
 	struct clk *clk;
 	struct notifier_block clk_rate_change_nb;
 	u32 quirks;
+	u32 ctrl_reg;
+	struct i2c_bus_recovery_info rinfo;
+	struct pinctrl *pinctrl;
+	struct pinctrl_state *pinctrl_pins_default;
+	struct pinctrl_state *pinctrl_pins_gpio;
+#if IS_ENABLED(CONFIG_I2C_SLAVE)
+	struct i2c_client *slave;
+	enum cdns_i2c_slave_state slave_state;
+#endif
 };
 
 struct cdns_platform_data {
@@ -186,21 +244,142 @@
 		(id->curr_recv_count == CDNS_I2C_FIFO_DEPTH + 1));
 }
 
+#if IS_ENABLED(CONFIG_I2C_SLAVE)
+static void cdns_i2c_set_mode(enum cdns_i2c_mode mode, struct cdns_i2c *id)
+{
+	/* Disable all interrupts */
+	cdns_i2c_writereg(CDNS_I2C_IXR_ALL_INTR_MASK, CDNS_I2C_IDR_OFFSET);
+
+	/* Update device state */
+	id->slave_state = CDNS_I2C_SLAVE_STATE_IDLE;
+
+	if (mode == CDNS_I2C_MODE_MASTER) {
+		/* Enable i2c master */
+		id->ctrl_reg = CDNS_I2C_CR_ACK_EN | CDNS_I2C_CR_NEA
+				| CDNS_I2C_CR_MS | CDNS_I2C_CR_CLR_FIFO;
+		return cdns_i2c_writereg(id->ctrl_reg, CDNS_I2C_CR_OFFSET);
+	}
+	/* Enable i2c slave */
+	id->ctrl_reg = CDNS_I2C_CR_ACK_EN | CDNS_I2C_CR_CLR_FIFO;
+	cdns_i2c_writereg(id->ctrl_reg, CDNS_I2C_CR_OFFSET);
+
+	/* Setting slave address */
+	cdns_i2c_writereg(id->slave->addr & CDNS_I2C_ADDR_MASK,
+			  CDNS_I2C_ADDR_OFFSET);
+
+	/* Enable slave send/receive interrupts */
+	cdns_i2c_writereg(CDNS_I2C_IXR_SLAVE_INTR_MASK, CDNS_I2C_IER_OFFSET);
+}
+
+static void cdns_i2c_slave_rcv_data(struct cdns_i2c *id)
+{
+	u8 bytes;
+	unsigned char data;
+
+	/* Prepare backend for data reception */
+	if (id->slave_state == CDNS_I2C_SLAVE_STATE_IDLE) {
+		id->slave_state = CDNS_I2C_SLAVE_STATE_RECV;
+		i2c_slave_event(id->slave, I2C_SLAVE_WRITE_REQUESTED, NULL);
+	}
+
+	/* Fetch number of bytes to receive */
+	bytes = cdns_i2c_readreg(CDNS_I2C_XFER_SIZE_OFFSET);
+
+	/* Read data and send to backend */
+	while (bytes--) {
+		data = cdns_i2c_readreg(CDNS_I2C_DATA_OFFSET);
+		i2c_slave_event(id->slave, I2C_SLAVE_WRITE_RECEIVED, &data);
+	}
+}
+
+static void cdns_i2c_slave_send_data(struct cdns_i2c *id)
+{
+	u8 data;
+
+	/* Prepare backend for data transmission */
+	if (id->slave_state == CDNS_I2C_SLAVE_STATE_IDLE) {
+		id->slave_state = CDNS_I2C_SLAVE_STATE_SEND;
+		i2c_slave_event(id->slave, I2C_SLAVE_READ_REQUESTED, &data);
+	} else {
+		i2c_slave_event(id->slave, I2C_SLAVE_READ_PROCESSED, &data);
+	}
+
+	/* Send data over bus */
+	cdns_i2c_writereg(data, CDNS_I2C_DATA_OFFSET);
+}
+
 /**
- * cdns_i2c_isr - Interrupt handler for the I2C device
- * @irq:	irq number for the I2C device
- * @ptr:	void pointer to cdns_i2c structure
+ * cdns_i2c_slave_isr - Interrupt handler for the I2C device in slave role
+ * @ptr:       Pointer to I2C device private data
+ *
+ * This function handles the data interrupt and transfer complete interrupt of
+ * the I2C device in slave role.
+ *
+ * Return: IRQ_HANDLED always
+ */
+static irqreturn_t cdns_i2c_slave_isr(void *ptr)
+{
+	struct cdns_i2c *id = ptr;
+	unsigned int isr_status, i2c_status;
+
+	/* Fetch the interrupt status */
+	isr_status = cdns_i2c_readreg(CDNS_I2C_ISR_OFFSET);
+	cdns_i2c_writereg(isr_status, CDNS_I2C_ISR_OFFSET);
+
+	/* Ignore masked interrupts */
+	isr_status &= ~cdns_i2c_readreg(CDNS_I2C_IMR_OFFSET);
+
+	/* Fetch transfer mode (send/receive) */
+	i2c_status = cdns_i2c_readreg(CDNS_I2C_SR_OFFSET);
+
+	/* Handle data send/receive */
+	if (i2c_status & CDNS_I2C_SR_RXRW) {
+		/* Send data to master */
+		if (isr_status & CDNS_I2C_IXR_DATA)
+			cdns_i2c_slave_send_data(id);
+
+		if (isr_status & CDNS_I2C_IXR_COMP) {
+			id->slave_state = CDNS_I2C_SLAVE_STATE_IDLE;
+			i2c_slave_event(id->slave, I2C_SLAVE_STOP, NULL);
+		}
+	} else {
+		/* Receive data from master */
+		if (isr_status & CDNS_I2C_IXR_DATA)
+			cdns_i2c_slave_rcv_data(id);
+
+		if (isr_status & CDNS_I2C_IXR_COMP) {
+			cdns_i2c_slave_rcv_data(id);
+			id->slave_state = CDNS_I2C_SLAVE_STATE_IDLE;
+			i2c_slave_event(id->slave, I2C_SLAVE_STOP, NULL);
+		}
+	}
+
+	/* Master indicated xfer stop or fifo underflow/overflow */
+	if (isr_status & (CDNS_I2C_IXR_NACK | CDNS_I2C_IXR_RX_OVF |
+			  CDNS_I2C_IXR_RX_UNF | CDNS_I2C_IXR_TX_OVF)) {
+		id->slave_state = CDNS_I2C_SLAVE_STATE_IDLE;
+		i2c_slave_event(id->slave, I2C_SLAVE_STOP, NULL);
+		cdns_i2c_writereg(CDNS_I2C_CR_CLR_FIFO, CDNS_I2C_CR_OFFSET);
+	}
+
+	return IRQ_HANDLED;
+}
+#endif
+
+/**
+ * cdns_i2c_master_isr - Interrupt handler for the I2C device in master role
+ * @ptr:       Pointer to I2C device private data
  *
  * This function handles the data interrupt, transfer complete interrupt and
- * the error interrupts of the I2C device.
+ * the error interrupts of the I2C device in master role.
  *
  * Return: IRQ_HANDLED always
  */
-static irqreturn_t cdns_i2c_isr(int irq, void *ptr)
+static irqreturn_t cdns_i2c_master_isr(void *ptr)
 {
-	unsigned int isr_status, avail_bytes, updatetx;
+	unsigned int isr_status, avail_bytes;
 	unsigned int bytes_to_send;
-	bool hold_quirk;
+	bool updatetx;
 	struct cdns_i2c *id = ptr;
 	/* Signal completion only after everything is updated */
 	int done_flag = 0;
@@ -208,6 +387,7 @@
 
 	isr_status = cdns_i2c_readreg(CDNS_I2C_ISR_OFFSET);
 	cdns_i2c_writereg(isr_status, CDNS_I2C_ISR_OFFSET);
+	id->err_status = 0;
 
 	/* Handling nack and arbitration lost interrupt */
 	if (isr_status & (CDNS_I2C_IXR_NACK | CDNS_I2C_IXR_ARB_LOST)) {
@@ -219,11 +399,7 @@
 	 * Check if transfer size register needs to be updated again for a
 	 * large data receive operation.
 	 */
-	updatetx = 0;
-	if (id->recv_count > id->curr_recv_count)
-		updatetx = 1;
-
-	hold_quirk = (id->quirks & CDNS_I2C_BROKEN_HOLD_BIT) && updatetx;
+	updatetx = id->recv_count > id->curr_recv_count;
 
 	/* When receiving, handle data interrupt and completion interrupt */
 	if (id->p_recv_buf &&
@@ -232,21 +408,29 @@
 		/* Read data if receive data valid is set */
 		while (cdns_i2c_readreg(CDNS_I2C_SR_OFFSET) &
 		       CDNS_I2C_SR_RXDV) {
-			/*
-			 * Clear hold bit that was set for FIFO control if
-			 * RX data left is less than FIFO depth, unless
-			 * repeated start is selected.
-			 */
-			if ((id->recv_count < CDNS_I2C_FIFO_DEPTH) &&
-			    !id->bus_hold_flag)
-				cdns_i2c_clear_bus_hold(id);
+			if (id->recv_count > 0) {
+				*id->p_recv_buf++ =
+					cdns_i2c_readreg(CDNS_I2C_DATA_OFFSET);
+				id->recv_count--;
+				id->curr_recv_count--;
+
+				/*
+				 * Clear hold bit that was set for FIFO control
+				 * if RX data left is less than or equal to
+				 * FIFO DEPTH unless repeated start is selected
+				 */
+				if (id->recv_count <= CDNS_I2C_FIFO_DEPTH &&
+				    !id->bus_hold_flag)
+					cdns_i2c_clear_bus_hold(id);
 
-			*(id->p_recv_buf)++ =
-				cdns_i2c_readreg(CDNS_I2C_DATA_OFFSET);
-			id->recv_count--;
-			id->curr_recv_count--;
+			} else {
+				dev_err(id->adap.dev.parent,
+					"xfer_size reg rollover. xfer aborted!\n");
+				id->err_status |= CDNS_I2C_IXR_TO;
+				break;
+			}
 
-			if (cdns_is_holdquirk(id, hold_quirk))
+			if (cdns_is_holdquirk(id, updatetx))
 				break;
 		}
 
@@ -257,7 +441,7 @@
 		 * maintain transfer size non-zero while performing a large
 		 * receive operation.
 		 */
-		if (cdns_is_holdquirk(id, hold_quirk)) {
+		if (cdns_is_holdquirk(id, updatetx)) {
 			/* wait while fifo is full */
 			while (cdns_i2c_readreg(CDNS_I2C_XFER_SIZE_OFFSET) !=
 			       (id->curr_recv_count - CDNS_I2C_FIFO_DEPTH))
@@ -279,22 +463,6 @@
 						  CDNS_I2C_XFER_SIZE_OFFSET);
 				id->curr_recv_count = id->recv_count;
 			}
-		} else if (id->recv_count && !hold_quirk &&
-						!id->curr_recv_count) {
-
-			/* Set the slave address in address register*/
-			cdns_i2c_writereg(id->p_msg->addr & CDNS_I2C_ADDR_MASK,
-						CDNS_I2C_ADDR_OFFSET);
-
-			if (id->recv_count > CDNS_I2C_TRANSFER_SIZE) {
-				cdns_i2c_writereg(CDNS_I2C_TRANSFER_SIZE,
-						CDNS_I2C_XFER_SIZE_OFFSET);
-				id->curr_recv_count = CDNS_I2C_TRANSFER_SIZE;
-			} else {
-				cdns_i2c_writereg(id->recv_count,
-						CDNS_I2C_XFER_SIZE_OFFSET);
-				id->curr_recv_count = id->recv_count;
-			}
 		}
 
 		/* Clear hold (if not repeated start) and signal completion */
@@ -341,8 +509,25 @@
 		status = IRQ_HANDLED;
 	}
 
+	/* Handling Slave monitor mode interrupt */
+	if (isr_status & CDNS_I2C_IXR_SLV_RDY) {
+		unsigned int ctrl_reg;
+		/* Read control register */
+		ctrl_reg = cdns_i2c_readreg(CDNS_I2C_CR_OFFSET);
+
+		/* Disable slave monitor mode */
+		ctrl_reg &= ~CDNS_I2C_CR_SLVMON;
+		cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET);
+
+		/* Clear interrupt flag for slvmon mode */
+		cdns_i2c_writereg(CDNS_I2C_IXR_SLV_RDY, CDNS_I2C_IDR_OFFSET);
+
+		done_flag = 1;
+		status = IRQ_HANDLED;
+	}
+
 	/* Update the status for errors */
-	id->err_status = isr_status & CDNS_I2C_IXR_ERR_INTR_MASK;
+	id->err_status |= isr_status & CDNS_I2C_IXR_ERR_INTR_MASK;
 	if (id->err_status)
 		status = IRQ_HANDLED;
 
@@ -353,6 +538,29 @@
 }
 
 /**
+ * cdns_i2c_isr - Interrupt handler for the I2C device
+ * @irq:	irq number for the I2C device
+ * @ptr:	void pointer to cdns_i2c structure
+ *
+ * This function passes the control to slave/master based on current role of
+ * i2c controller.
+ *
+ * Return: IRQ_HANDLED always
+ */
+static irqreturn_t cdns_i2c_isr(int irq, void *ptr)
+{
+#if IS_ENABLED(CONFIG_I2C_SLAVE)
+	struct cdns_i2c *id = ptr;
+
+	if (!(id->ctrl_reg & CDNS_I2C_CR_MS)) {
+		dev_dbg(&id->adap.dev, "slave interrupt\n");
+		return cdns_i2c_slave_isr(ptr);
+	}
+#endif
+	return cdns_i2c_master_isr(ptr);
+}
+
+/**
  * cdns_i2c_mrecv - Prepare and start a master receive operation
  * @id:		pointer to the i2c device structure
  */
@@ -360,6 +568,7 @@
 {
 	unsigned int ctrl_reg;
 	unsigned int isr_status;
+	unsigned long flags;
 
 	id->p_recv_buf = id->p_msg->buf;
 	id->recv_count = id->p_msg->len;
@@ -368,8 +577,13 @@
 	ctrl_reg = cdns_i2c_readreg(CDNS_I2C_CR_OFFSET);
 	ctrl_reg |= CDNS_I2C_CR_RW | CDNS_I2C_CR_CLR_FIFO;
 
+	/*
+	 * Receive up to I2C_SMBUS_BLOCK_MAX data bytes, plus one message length
+	 * byte, plus one checksum byte if PEC is enabled. p_msg->len will be 2 if
+	 * PEC is enabled, otherwise 1.
+	 */
 	if (id->p_msg->flags & I2C_M_RECV_LEN)
-		id->recv_count = I2C_SMBUS_BLOCK_MAX + 1;
+		id->recv_count = I2C_SMBUS_BLOCK_MAX + id->p_msg->len;
 
 	id->curr_recv_count = id->recv_count;
 
@@ -377,10 +591,8 @@
 	 * Check for the message size against FIFO depth and set the
 	 * 'hold bus' bit if it is greater than FIFO depth.
 	 */
-	if ((id->recv_count > CDNS_I2C_FIFO_DEPTH)  || id->bus_hold_flag)
+	if (id->recv_count > CDNS_I2C_FIFO_DEPTH)
 		ctrl_reg |= CDNS_I2C_CR_HOLD;
-	else
-		ctrl_reg = ctrl_reg & ~CDNS_I2C_CR_HOLD;
 
 	cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET);
 
@@ -403,6 +615,7 @@
 	}
 
 	/* Set the slave address in address register - triggers operation */
+	local_irq_save(flags);
 	cdns_i2c_writereg(id->p_msg->addr & CDNS_I2C_ADDR_MASK,
 						CDNS_I2C_ADDR_OFFSET);
 	/* Clear the bus hold flag if bytes to receive is less than FIFO size */
@@ -410,6 +623,7 @@
 		((id->p_msg->flags & I2C_M_RECV_LEN) != I2C_M_RECV_LEN) &&
 		(id->recv_count <= CDNS_I2C_FIFO_DEPTH))
 			cdns_i2c_clear_bus_hold(id);
+	local_irq_restore(flags);
 	cdns_i2c_writereg(CDNS_I2C_ENABLED_INTR_MASK, CDNS_I2C_IER_OFFSET);
 }
 
@@ -437,11 +651,8 @@
 	 * Check for the message size against FIFO depth and set the
 	 * 'hold bus' bit if it is greater than FIFO depth.
 	 */
-	if ((id->send_count > CDNS_I2C_FIFO_DEPTH) || id->bus_hold_flag)
+	if (id->send_count > CDNS_I2C_FIFO_DEPTH)
 		ctrl_reg |= CDNS_I2C_CR_HOLD;
-	else
-		ctrl_reg = ctrl_reg & ~CDNS_I2C_CR_HOLD;
-
 	cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET);
 
 	/* Clear the interrupts in interrupt status register. */
@@ -480,6 +691,40 @@
 }
 
 /**
+ * cdns_i2c_slvmon - Handling Slav monitor mode feature
+ * @id:		pointer to the i2c device
+ */
+static void cdns_i2c_slvmon(struct cdns_i2c *id)
+{
+	unsigned int ctrl_reg;
+	unsigned int isr_status;
+
+	id->p_recv_buf = NULL;
+	id->p_send_buf = id->p_msg->buf;
+	id->send_count = id->p_msg->len;
+
+	/* Clear the interrupts in interrupt status register. */
+	isr_status = cdns_i2c_readreg(CDNS_I2C_ISR_OFFSET);
+	cdns_i2c_writereg(isr_status, CDNS_I2C_ISR_OFFSET);
+
+	/* Enable slvmon control reg */
+	ctrl_reg = cdns_i2c_readreg(CDNS_I2C_CR_OFFSET);
+	ctrl_reg |=  CDNS_I2C_CR_MS | CDNS_I2C_CR_NEA | CDNS_I2C_CR_SLVMON
+			| CDNS_I2C_CR_CLR_FIFO;
+	ctrl_reg &= ~(CDNS_I2C_CR_RW);
+	cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET);
+
+	/* Initialize slvmon reg */
+	cdns_i2c_writereg(0xF, CDNS_I2C_SLV_PAUSE_OFFSET);
+
+	/* Set the slave address to start the slave address transmission */
+	cdns_i2c_writereg(id->p_msg->addr, CDNS_I2C_ADDR_OFFSET);
+
+	/* Setup slvmon interrupt flag */
+	cdns_i2c_writereg(CDNS_I2C_IXR_SLV_RDY, CDNS_I2C_IER_OFFSET);
+}
+
+/**
  * cdns_i2c_master_reset - Reset the interface
  * @adap:	pointer to the i2c adapter driver instance
  *
@@ -495,12 +740,12 @@
 	cdns_i2c_writereg(CDNS_I2C_IXR_ALL_INTR_MASK, CDNS_I2C_IDR_OFFSET);
 	/* Clear the hold bit and fifos */
 	regval = cdns_i2c_readreg(CDNS_I2C_CR_OFFSET);
-	regval &= ~CDNS_I2C_CR_HOLD;
+	regval &= ~(CDNS_I2C_CR_HOLD | CDNS_I2C_CR_SLVMON);
 	regval |= CDNS_I2C_CR_CLR_FIFO;
 	cdns_i2c_writereg(regval, CDNS_I2C_CR_OFFSET);
 	/* Update the transfercount register to zero */
 	cdns_i2c_writereg(0, CDNS_I2C_XFER_SIZE_OFFSET);
-	/* Clear the interupt status register */
+	/* Clear the interrupt status register */
 	regval = cdns_i2c_readreg(CDNS_I2C_ISR_OFFSET);
 	cdns_i2c_writereg(regval, CDNS_I2C_ISR_OFFSET);
 	/* Clear the status register */
@@ -511,7 +756,7 @@
 static int cdns_i2c_process_msg(struct cdns_i2c *id, struct i2c_msg *msg,
 		struct i2c_adapter *adap)
 {
-	unsigned long time_left;
+	unsigned long time_left, msg_timeout;
 	u32 reg;
 
 	id->p_msg = msg;
@@ -529,16 +774,27 @@
 			cdns_i2c_writereg(reg | CDNS_I2C_CR_NEA,
 					CDNS_I2C_CR_OFFSET);
 	}
-
-	/* Check for the R/W flag on each msg */
-	if (msg->flags & I2C_M_RD)
+	/* Check for zero length - Slave monitor mode */
+	if (msg->len == 0)
+		cdns_i2c_slvmon(id);
+	 /* Check for the R/W flag on each msg */
+	else if (msg->flags & I2C_M_RD)
 		cdns_i2c_mrecv(id);
 	else
 		cdns_i2c_msend(id);
 
+	/* Minimal time to execute this message */
+	msg_timeout = msecs_to_jiffies((1000 * msg->len * BITS_PER_BYTE) / id->i2c_clk);
+	/* Plus some wiggle room */
+	msg_timeout += msecs_to_jiffies(500);
+
+	if (msg_timeout < adap->timeout)
+		msg_timeout = adap->timeout;
+
 	/* Wait for the signal of completion */
-	time_left = wait_for_completion_timeout(&id->xfer_done, adap->timeout);
+	time_left = wait_for_completion_timeout(&id->xfer_done, msg_timeout);
 	if (time_left == 0) {
+		i2c_recover_bus(adap);
 		cdns_i2c_master_reset(adap);
 		dev_err(id->adap.dev.parent,
 				"timeout waiting on completion\n");
@@ -552,6 +808,9 @@
 	if (id->err_status & CDNS_I2C_IXR_ARB_LOST)
 		return -EAGAIN;
 
+	if (msg->flags & I2C_M_RECV_LEN)
+		msg->len += min_t(unsigned int, msg->buf[0], I2C_SMBUS_BLOCK_MAX);
+
 	return 0;
 }
 
@@ -576,11 +835,13 @@
 	ret = pm_runtime_get_sync(id->dev);
 	if (ret < 0)
 		return ret;
+
 	/* Check if the bus is free */
-	if (cdns_i2c_readreg(CDNS_I2C_SR_OFFSET) & CDNS_I2C_SR_BA) {
-		ret = -EAGAIN;
-		goto out;
-	}
+	if (msgs->len)
+		if (cdns_i2c_readreg(CDNS_I2C_SR_OFFSET) & CDNS_I2C_SR_BA) {
+			ret = -EAGAIN;
+			goto out;
+		}
 
 	hold_quirk = !!(id->quirks & CDNS_I2C_BROKEN_HOLD_BIT);
 	/*
@@ -634,6 +895,7 @@
 	}
 
 	ret = num;
+
 out:
 	pm_runtime_mark_last_busy(id->dev);
 	pm_runtime_put_autosuspend(id->dev);
@@ -648,14 +910,66 @@
  */
 static u32 cdns_i2c_func(struct i2c_adapter *adap)
 {
-	return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR |
-		(I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK) |
-		I2C_FUNC_SMBUS_BLOCK_DATA;
+	u32 func = I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR |
+			(I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK) |
+			I2C_FUNC_SMBUS_BLOCK_DATA;
+
+#if IS_ENABLED(CONFIG_I2C_SLAVE)
+	func |= I2C_FUNC_SLAVE;
+#endif
+
+	return func;
+}
+
+#if IS_ENABLED(CONFIG_I2C_SLAVE)
+static int cdns_reg_slave(struct i2c_client *slave)
+{
+	int ret;
+	struct cdns_i2c *id = container_of(slave->adapter, struct cdns_i2c,
+									adap);
+
+	if (id->slave)
+		return -EBUSY;
+
+	if (slave->flags & I2C_CLIENT_TEN)
+		return -EAFNOSUPPORT;
+
+	ret = pm_runtime_get_sync(id->dev);
+	if (ret < 0)
+		return ret;
+
+	/* Store slave information */
+	id->slave = slave;
+
+	/* Enable I2C slave */
+	cdns_i2c_set_mode(CDNS_I2C_MODE_SLAVE, id);
+
+	return 0;
+}
+
+static int cdns_unreg_slave(struct i2c_client *slave)
+{
+	struct cdns_i2c *id = container_of(slave->adapter, struct cdns_i2c,
+									adap);
+
+	/* Remove slave information */
+	id->slave = NULL;
+
+	/* Enable I2C master */
+	cdns_i2c_set_mode(CDNS_I2C_MODE_MASTER, id);
+	pm_runtime_put(id->dev);
+
+	return 0;
 }
+#endif
 
 static const struct i2c_algorithm cdns_i2c_algo = {
 	.master_xfer	= cdns_i2c_master_xfer,
 	.functionality	= cdns_i2c_func,
+#if IS_ENABLED(CONFIG_I2C_SLAVE)
+	.reg_slave	= cdns_reg_slave,
+	.unreg_slave	= cdns_unreg_slave,
+#endif
 };
 
 /**
@@ -745,12 +1059,11 @@
 	if (ret)
 		return ret;
 
-	ctrl_reg = cdns_i2c_readreg(CDNS_I2C_CR_OFFSET);
+	ctrl_reg = id->ctrl_reg;
 	ctrl_reg &= ~(CDNS_I2C_CR_DIVA_MASK | CDNS_I2C_CR_DIVB_MASK);
 	ctrl_reg |= ((div_a << CDNS_I2C_CR_DIVA_SHIFT) |
 			(div_b << CDNS_I2C_CR_DIVB_SHIFT));
-	cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET);
-
+	id->ctrl_reg = ctrl_reg;
 	return 0;
 }
 
@@ -834,6 +1147,26 @@
 }
 
 /**
+ * cdns_i2c_init -  Controller initialisation
+ * @id:		Device private data structure
+ *
+ * Initialise the i2c controller.
+ *
+ */
+static void cdns_i2c_init(struct cdns_i2c *id)
+{
+	cdns_i2c_writereg(id->ctrl_reg, CDNS_I2C_CR_OFFSET);
+	/*
+	 * Cadence I2C controller has a bug wherein it generates
+	 * invalid read transaction after HW timeout in master receiver mode.
+	 * HW timeout is not used by this driver and the interrupt is disabled.
+	 * But the feature itself cannot be disabled. Hence maximum value
+	 * is written to this register to reduce the chances of error.
+	 */
+	cdns_i2c_writereg(CDNS_I2C_TIMEOUT_MAX, CDNS_I2C_TIME_OUT_OFFSET);
+}
+
+/**
  * cdns_i2c_runtime_resume - Runtime resume
  * @dev:	Address of the platform_device structure
  *
@@ -851,6 +1184,97 @@
 		dev_err(dev, "Cannot enable clock.\n");
 		return ret;
 	}
+	cdns_i2c_init(xi2c);
+
+	return 0;
+}
+
+/**
+ * cdns_i2c_prepare_recovery - Withhold recovery state
+ * @adapter:    Pointer to i2c adapter
+ *
+ * This function is called to prepare for recovery.
+ * It changes the state of pins from SCL/SDA to GPIO.
+ */
+static void cdns_i2c_prepare_recovery(struct i2c_adapter *adapter)
+{
+	struct cdns_i2c *p_cdns_i2c;
+	int ret;
+
+	p_cdns_i2c = container_of(adapter, struct cdns_i2c, adap);
+
+	/* Setting pin state as gpio */
+	ret = pinctrl_select_state(p_cdns_i2c->pinctrl,
+			     p_cdns_i2c->pinctrl_pins_gpio);
+	if (ret < 0)
+		dev_err(p_cdns_i2c->adap.dev.parent,
+				"pinctrl_select_state failed\n");
+}
+
+/**
+ * cdns_i2c_unprepare_recovery - Release recovery state
+ * @adapter:    Pointer to i2c adapter
+ *
+ * This function is called on exiting recovery. It reverts
+ * the state of pins from GPIO to SCL/SDA.
+ */
+static void cdns_i2c_unprepare_recovery(struct i2c_adapter *adapter)
+{
+	struct cdns_i2c *p_cdns_i2c;
+	int ret;
+
+	p_cdns_i2c = container_of(adapter, struct cdns_i2c, adap);
+
+	/* Setting pin state to default(i2c) */
+	ret = pinctrl_select_state(p_cdns_i2c->pinctrl,
+			     p_cdns_i2c->pinctrl_pins_default);
+	if (ret < 0)
+		dev_err(p_cdns_i2c->adap.dev.parent,
+				"pinctrl_select_state failed\n");
+}
+
+/**
+ * cdns_i2c_init_recovery_info  - Initialize I2C bus recovery
+ * @pid:        Pointer to cdns i2c structure
+ * @pdev:       Handle to the platform device structure
+ *
+ * This function does required initialization for i2c bus
+ * recovery. It registers three functions for prepare,
+ * recover and unprepare
+ *
+ * Return: 0 on Success, negative error otherwise.
+ */
+static int cdns_i2c_init_recovery_info(struct cdns_i2c *pid,
+		struct platform_device *pdev)
+{
+	struct i2c_bus_recovery_info *rinfo = &pid->rinfo;
+
+	pid->pinctrl_pins_default = pinctrl_lookup_state(pid->pinctrl,
+			PINCTRL_STATE_DEFAULT);
+	pid->pinctrl_pins_gpio = pinctrl_lookup_state(pid->pinctrl, "gpio");
+
+	/* Fetches GPIO pins */
+	rinfo->sda_gpiod = devm_gpiod_get(&pdev->dev, "sda-gpios", GPIOD_ASIS);
+	rinfo->scl_gpiod = devm_gpiod_get(&pdev->dev, "scl-gpios", GPIOD_ASIS);
+
+	/* if GPIO driver isn't ready yet, deffer probe */
+	if (PTR_ERR(rinfo->sda_gpiod) == -EPROBE_DEFER ||
+	    PTR_ERR(rinfo->scl_gpiod) == -EPROBE_DEFER)
+		return -EPROBE_DEFER;
+
+	/* Validates fetched information */
+	if (IS_ERR(rinfo->sda_gpiod) ||
+	    IS_ERR(rinfo->scl_gpiod) ||
+			IS_ERR(pid->pinctrl_pins_default) ||
+			IS_ERR(pid->pinctrl_pins_gpio)) {
+		dev_dbg(&pdev->dev, "recovery information incomplete\n");
+		return 0;
+	}
+
+	rinfo->prepare_recovery     = cdns_i2c_prepare_recovery;
+	rinfo->unprepare_recovery   = cdns_i2c_unprepare_recovery;
+	rinfo->recover_bus          = i2c_generic_scl_recovery;
+	pid->adap.bus_recovery_info = rinfo;
 
 	return 0;
 }
@@ -901,12 +1325,22 @@
 		id->quirks = data->quirks;
 	}
 
+	id->pinctrl = devm_pinctrl_get(&pdev->dev);
+	if (!IS_ERR(id->pinctrl)) {
+		ret = cdns_i2c_init_recovery_info(id, pdev);
+		if (ret)
+			return ret;
+	}
+
 	r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	id->membase = devm_ioremap_resource(&pdev->dev, r_mem);
 	if (IS_ERR(id->membase))
 		return PTR_ERR(id->membase);
 
-	id->irq = platform_get_irq(pdev, 0);
+	ret = platform_get_irq(pdev, 0);
+	if (ret < 0)
+		return ret;
+	id->irq = ret;
 
 	id->adap.owner = THIS_MODULE;
 	id->adap.dev.of_node = pdev->dev.of_node;
@@ -921,17 +1355,18 @@
 
 	id->clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(id->clk)) {
-		dev_err(&pdev->dev, "input clock not found.\n");
+		if (PTR_ERR(id->clk) != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "input clock not found.\n");
 		return PTR_ERR(id->clk);
 	}
 	ret = clk_prepare_enable(id->clk);
 	if (ret)
 		dev_err(&pdev->dev, "Unable to enable clock.\n");
 
-	pm_runtime_enable(id->dev);
 	pm_runtime_set_autosuspend_delay(id->dev, CNDS_I2C_PM_TIMEOUT);
 	pm_runtime_use_autosuspend(id->dev);
 	pm_runtime_set_active(id->dev);
+	pm_runtime_enable(id->dev);
 
 	id->clk_rate_change_nb.notifier_call = cdns_i2c_clk_notifier_cb;
 	if (clk_notifier_register(id->clk, &id->clk_rate_change_nb))
@@ -943,8 +1378,7 @@
 	if (ret || (id->i2c_clk > CDNS_I2C_SPEED_MAX))
 		id->i2c_clk = CDNS_I2C_SPEED_DEFAULT;
 
-	cdns_i2c_writereg(CDNS_I2C_CR_ACK_EN | CDNS_I2C_CR_NEA | CDNS_I2C_CR_MS,
-			  CDNS_I2C_CR_OFFSET);
+	id->ctrl_reg = CDNS_I2C_CR_ACK_EN | CDNS_I2C_CR_NEA | CDNS_I2C_CR_MS;
 
 	ret = cdns_i2c_setclk(id->input_clk, id);
 	if (ret) {
@@ -959,15 +1393,7 @@
 		dev_err(&pdev->dev, "cannot get irq %d\n", id->irq);
 		goto err_clk_dis;
 	}
-
-	/*
-	 * Cadence I2C controller has a bug wherein it generates
-	 * invalid read transaction after HW timeout in master receiver mode.
-	 * HW timeout is not used by this driver and the interrupt is disabled.
-	 * But the feature itself cannot be disabled. Hence maximum value
-	 * is written to this register to reduce the chances of error.
-	 */
-	cdns_i2c_writereg(CDNS_I2C_TIMEOUT_MAX, CDNS_I2C_TIME_OUT_OFFSET);
+	cdns_i2c_init(id);
 
 	ret = i2c_add_adapter(&id->adap);
 	if (ret < 0)
@@ -979,9 +1405,10 @@
 	return 0;
 
 err_clk_dis:
+	clk_notifier_unregister(id->clk, &id->clk_rate_change_nb);
 	clk_disable_unprepare(id->clk);
-	pm_runtime_set_suspended(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
 	return ret;
 }
 
@@ -997,10 +1424,13 @@
 {
 	struct cdns_i2c *id = platform_get_drvdata(pdev);
 
+	pm_runtime_disable(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
+	pm_runtime_dont_use_autosuspend(&pdev->dev);
+
 	i2c_del_adapter(&id->adap);
 	clk_notifier_unregister(id->clk, &id->clk_rate_change_nb);
 	clk_disable_unprepare(id->clk);
-	pm_runtime_disable(&pdev->dev);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-cbus-gpio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-cbus-gpio.c
@@ -195,8 +195,9 @@
 }
 
 static const struct i2c_algorithm cbus_i2c_algo = {
-	.smbus_xfer	= cbus_i2c_smbus_xfer,
-	.functionality	= cbus_i2c_func,
+	.smbus_xfer		= cbus_i2c_smbus_xfer,
+	.smbus_xfer_atomic	= cbus_i2c_smbus_xfer,
+	.functionality		= cbus_i2c_func,
 };
 
 static int cbus_i2c_remove(struct platform_device *pdev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-cpm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-cpm.c
@@ -65,6 +65,9 @@
 	char    res1[4];	/* Reserved */
 	ushort  rpbase;		/* Relocation pointer */
 	char    res2[2];	/* Reserved */
+	/* The following elements are only for CPM2 */
+	char    res3[4];	/* Reserved */
+	uint    sdmatmp;	/* Internal */
 };
 
 #define I2COM_START	0x80
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-designware-common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-designware-common.c
@@ -253,9 +253,6 @@
 {
 	int ret;
 
-	if (IS_ERR(dev->clk))
-		return PTR_ERR(dev->clk);
-
 	if (prepare) {
 		/* Optional interface clock */
 		ret = clk_prepare_enable(dev->pclk);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-designware-pcidrv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-designware-pcidrv.c
@@ -37,10 +37,10 @@
 };
 
 struct dw_scl_sda_cfg {
-	u32 ss_hcnt;
-	u32 fs_hcnt;
-	u32 ss_lcnt;
-	u32 fs_lcnt;
+	u16 ss_hcnt;
+	u16 fs_hcnt;
+	u16 ss_lcnt;
+	u16 fs_lcnt;
 	u32 sda_hold;
 };
 
@@ -313,6 +313,7 @@
 	pm_runtime_get_noresume(&pdev->dev);
 
 	i2c_del_adapter(&dev->adapter);
+	devm_free_irq(&pdev->dev, dev->irq, dev);
 	pci_free_irq_vectors(pdev);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-designware-platdrv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -349,8 +349,17 @@
 		goto exit_reset;
 	}
 
-	dev->clk = devm_clk_get(&pdev->dev, NULL);
-	if (!i2c_dw_prepare_clk(dev, true)) {
+	dev->clk = devm_clk_get_optional(&pdev->dev, NULL);
+	if (IS_ERR(dev->clk)) {
+		ret = PTR_ERR(dev->clk);
+		goto exit_reset;
+	}
+
+	ret = i2c_dw_prepare_clk(dev, true);
+	if (ret)
+		goto exit_reset;
+
+	if (dev->clk) {
 		u64 clk_khz;
 
 		dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz;
@@ -370,10 +379,16 @@
 	adap->dev.of_node = pdev->dev.of_node;
 	adap->nr = -1;
 
-	dev_pm_set_driver_flags(&pdev->dev,
-				DPM_FLAG_SMART_PREPARE |
-				DPM_FLAG_SMART_SUSPEND |
-				DPM_FLAG_LEAVE_SUSPENDED);
+	if (dev->flags & ACCESS_NO_IRQ_SUSPEND) {
+		dev_pm_set_driver_flags(&pdev->dev,
+					DPM_FLAG_SMART_PREPARE |
+					DPM_FLAG_LEAVE_SUSPENDED);
+	} else {
+		dev_pm_set_driver_flags(&pdev->dev,
+					DPM_FLAG_SMART_PREPARE |
+					DPM_FLAG_SMART_SUSPEND |
+					DPM_FLAG_LEAVE_SUSPENDED);
+	}
 
 	/* The code below assumes runtime PM to be disabled. */
 	WARN_ON(pm_runtime_enabled(&pdev->dev));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-eg20t.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-eg20t.c
@@ -180,6 +180,7 @@
 	{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7831_I2C), 1, },
 	{0,}
 };
+MODULE_DEVICE_TABLE(pci, pch_pcidev_id);
 
 static irqreturn_t pch_i2c_handler(int irq, void *pData);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-emev2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-emev2.c
@@ -397,7 +397,10 @@
 
 	em_i2c_reset(&priv->adap);
 
-	priv->irq = platform_get_irq(pdev, 0);
+	ret = platform_get_irq(pdev, 0);
+	if (ret < 0)
+		goto err_clk;
+	priv->irq = ret;
 	ret = devm_request_irq(&pdev->dev, priv->irq, em_i2c_irq_handler, 0,
 				"em_i2c", priv);
 	if (ret)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-fsi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-fsi.c
@@ -98,7 +98,7 @@
 #define I2C_STAT_DAT_REQ	BIT(25)
 #define I2C_STAT_CMD_COMP	BIT(24)
 #define I2C_STAT_STOP_ERR	BIT(23)
-#define I2C_STAT_MAX_PORT	GENMASK(19, 16)
+#define I2C_STAT_MAX_PORT	GENMASK(22, 16)
 #define I2C_STAT_ANY_INT	BIT(15)
 #define I2C_STAT_SCL_IN		BIT(11)
 #define I2C_STAT_SDA_IN		BIT(10)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-gpio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-gpio.c
@@ -348,7 +348,7 @@
 	if (ret == -ENOENT)
 		retdesc = ERR_PTR(-EPROBE_DEFER);
 
-	if (ret != -EPROBE_DEFER)
+	if (PTR_ERR(retdesc) != -EPROBE_DEFER)
 		dev_err(dev, "error trying to get descriptor: %d\n", ret);
 
 	return retdesc;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-highlander.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-highlander.c
@@ -379,7 +379,7 @@
 	platform_set_drvdata(pdev, dev);
 
 	dev->irq = platform_get_irq(pdev, 0);
-	if (iic_force_poll)
+	if (dev->irq < 0 || iic_force_poll)
 		dev->irq = 0;
 
 	if (dev->irq) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-hix5hd2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-hix5hd2.c
@@ -477,6 +477,7 @@
 	i2c_del_adapter(&priv->adap);
 	pm_runtime_disable(priv->dev);
 	pm_runtime_set_suspended(priv->dev);
+	clk_disable_unprepare(priv->clk);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-i801.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-i801.c
@@ -64,6 +64,7 @@
  * Cedar Fork (PCH)		0x18df	32	hard	yes	yes	yes
  * Ice Lake-LP (PCH)		0x34a3	32	hard	yes	yes	yes
  * Comet Lake (PCH)		0x02a3	32	hard	yes	yes	yes
+ * Comet Lake-H (PCH)		0x06a3	32	hard	yes	yes	yes
  * Elkhart Lake (PCH)		0x4b23	32	hard	yes	yes	yes
  * Tiger Lake-LP (PCH)		0xa0a3	32	hard	yes	yes	yes
  *
@@ -129,11 +130,6 @@
 #define TCOBASE		0x050
 #define TCOCTL		0x054
 
-#define ACPIBASE		0x040
-#define ACPIBASE_SMI_OFF	0x030
-#define ACPICTRL		0x044
-#define ACPICTRL_EN		0x080
-
 #define SBREG_BAR		0x10
 #define SBREG_SMBCTRL		0xc6000c
 #define SBREG_SMBCTRL_DNV	0xcf000c
@@ -205,6 +201,7 @@
 
 /* Older devices have their ID defined in <linux/pci_ids.h> */
 #define PCI_DEVICE_ID_INTEL_COMETLAKE_SMBUS		0x02a3
+#define PCI_DEVICE_ID_INTEL_COMETLAKE_H_SMBUS		0x06a3
 #define PCI_DEVICE_ID_INTEL_BAYTRAIL_SMBUS		0x0f12
 #define PCI_DEVICE_ID_INTEL_CDF_SMBUS			0x18df
 #define PCI_DEVICE_ID_INTEL_DNV_SMBUS			0x19df
@@ -384,11 +381,9 @@
 		dev_err(&priv->pci_dev->dev, "Transaction timeout\n");
 		/* try to stop the current command */
 		dev_dbg(&priv->pci_dev->dev, "Terminating the current operation\n");
-		outb_p(inb_p(SMBHSTCNT(priv)) | SMBHSTCNT_KILL,
-		       SMBHSTCNT(priv));
+		outb_p(SMBHSTCNT_KILL, SMBHSTCNT(priv));
 		usleep_range(1000, 2000);
-		outb_p(inb_p(SMBHSTCNT(priv)) & (~SMBHSTCNT_KILL),
-		       SMBHSTCNT(priv));
+		outb_p(0, SMBHSTCNT(priv));
 
 		/* Check if it worked */
 		status = inb_p(SMBHSTSTS(priv));
@@ -535,12 +530,13 @@
 		return -EOPNOTSUPP;
 	}
 
-	inb_p(SMBHSTCNT(priv)); /* reset the data buffer index */
+	/* Set block buffer mode */
+	outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_E32B, SMBAUXCTL(priv));
 
-	/* Use 32-byte buffer to process this transaction */
 	if (read_write == I2C_SMBUS_WRITE) {
 		len = data->block[0];
 		outb_p(len, SMBHSTDAT0(priv));
+		inb_p(SMBHSTCNT(priv));	/* reset the data buffer index */
 		for (i = 0; i < len; i++)
 			outb_p(data->block[i+1], SMBBLKDAT(priv));
 	}
@@ -556,6 +552,7 @@
 			return -EPROTO;
 
 		data->block[0] = len;
+		inb_p(SMBHSTCNT(priv));	/* reset the data buffer index */
 		for (i = 0; i < len; i++)
 			data->block[i + 1] = inb_p(SMBBLKDAT(priv));
 	}
@@ -730,15 +727,11 @@
 		return i801_check_post(priv, status);
 	}
 
-	for (i = 1; i <= len; i++) {
-		if (i == len && read_write == I2C_SMBUS_READ)
-			smbcmd |= SMBHSTCNT_LAST_BYTE;
-		outb_p(smbcmd, SMBHSTCNT(priv));
-
-		if (i == 1)
-			outb_p(inb(SMBHSTCNT(priv)) | SMBHSTCNT_START,
-			       SMBHSTCNT(priv));
+	if (len == 1 && read_write == I2C_SMBUS_READ)
+		smbcmd |= SMBHSTCNT_LAST_BYTE;
+	outb_p(smbcmd | SMBHSTCNT_START, SMBHSTCNT(priv));
 
+	for (i = 1; i <= len; i++) {
 		status = i801_wait_byte_done(priv);
 		if (status)
 			goto exit;
@@ -761,9 +754,12 @@
 			data->block[0] = len;
 		}
 
-		/* Retrieve/store value in SMBBLKDAT */
-		if (read_write == I2C_SMBUS_READ)
+		if (read_write == I2C_SMBUS_READ) {
 			data->block[i] = inb_p(SMBBLKDAT(priv));
+			if (i == len - 1)
+				outb_p(smbcmd | SMBHSTCNT_LAST_BYTE, SMBHSTCNT(priv));
+		}
+
 		if (read_write == I2C_SMBUS_WRITE && i+1 <= len)
 			outb_p(data->block[i+1], SMBBLKDAT(priv));
 
@@ -776,14 +772,6 @@
 	return i801_check_post(priv, status);
 }
 
-static int i801_set_block_buffer_mode(struct i801_priv *priv)
-{
-	outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_E32B, SMBAUXCTL(priv));
-	if ((inb_p(SMBAUXCTL(priv)) & SMBAUXCTL_E32B) == 0)
-		return -EIO;
-	return 0;
-}
-
 /* Block transaction function */
 static int i801_block_transaction(struct i801_priv *priv,
 				  union i2c_smbus_data *data, char read_write,
@@ -792,6 +780,11 @@
 	int result = 0;
 	unsigned char hostc;
 
+	if (read_write == I2C_SMBUS_READ && command == I2C_SMBUS_BLOCK_DATA)
+		data->block[0] = I2C_SMBUS_BLOCK_MAX;
+	else if (data->block[0] < 1 || data->block[0] > I2C_SMBUS_BLOCK_MAX)
+		return -EPROTO;
+
 	if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
 		if (read_write == I2C_SMBUS_WRITE) {
 			/* set I2C_EN bit in configuration register */
@@ -805,22 +798,11 @@
 		}
 	}
 
-	if (read_write == I2C_SMBUS_WRITE
-	 || command == I2C_SMBUS_I2C_BLOCK_DATA) {
-		if (data->block[0] < 1)
-			data->block[0] = 1;
-		if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
-			data->block[0] = I2C_SMBUS_BLOCK_MAX;
-	} else {
-		data->block[0] = 32;	/* max for SMBus block reads */
-	}
-
 	/* Experience has shown that the block buffer can only be used for
 	   SMBus (not I2C) block transactions, even though the datasheet
 	   doesn't mention this limitation. */
-	if ((priv->features & FEATURE_BLOCK_BUFFER)
-	 && command != I2C_SMBUS_I2C_BLOCK_DATA
-	 && i801_set_block_buffer_mode(priv) == 0)
+	if ((priv->features & FEATURE_BLOCK_BUFFER) &&
+	    command != I2C_SMBUS_I2C_BLOCK_DATA)
 		result = i801_block_transaction_by_block(priv, data,
 							 read_write,
 							 command, hwpec);
@@ -1069,6 +1051,7 @@
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CANNONLAKE_LP_SMBUS) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICELAKE_LP_SMBUS) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COMETLAKE_SMBUS) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COMETLAKE_H_SMBUS) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ELKHART_LAKE_SMBUS) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TIGERLAKE_LP_SMBUS) },
 	{ 0, }
@@ -1077,7 +1060,7 @@
 MODULE_DEVICE_TABLE(pci, i801_ids);
 
 #if defined CONFIG_X86 && defined CONFIG_DMI
-static unsigned char apanel_addr;
+static unsigned char apanel_addr __ro_after_init;
 
 /* Scan the system ROM for the signature "FJKEYINF" */
 static __init const void __iomem *bios_signature(const void __iomem *bios)
@@ -1265,6 +1248,7 @@
 	 * Additional individual entries were added after verification.
 	 */
 	{ "Vostro V131",        0x1d },
+	{ "Vostro 5568",        0x29 },
 };
 
 static void register_dell_lis3lv02d_i2c_device(struct i801_priv *priv)
@@ -1429,7 +1413,7 @@
 
 	/* Register GPIO descriptor lookup table */
 	lookup = devm_kzalloc(dev,
-			      struct_size(lookup, table, mux_config->n_gpios),
+			      struct_size(lookup, table, mux_config->n_gpios + 1),
 			      GFP_KERNEL);
 	if (!lookup)
 		return -ENOMEM;
@@ -1544,7 +1528,7 @@
 		pci_bus_write_config_byte(pci_dev->bus, devfn, 0xe1, hidden);
 	spin_unlock(&p2sb_spinlock);
 
-	res = &tco_res[ICH_RES_MEM_OFF];
+	res = &tco_res[1];
 	if (pci_dev->device == PCI_DEVICE_ID_INTEL_DNV_SMBUS)
 		res->start = (resource_size_t)base64_addr + SBREG_SMBCTRL_DNV;
 	else
@@ -1554,7 +1538,7 @@
 	res->flags = IORESOURCE_MEM;
 
 	return platform_device_register_resndata(&pci_dev->dev, "iTCO_wdt", -1,
-					tco_res, 3, &spt_tco_platform_data,
+					tco_res, 2, &spt_tco_platform_data,
 					sizeof(spt_tco_platform_data));
 }
 
@@ -1567,17 +1551,16 @@
 i801_add_tco_cnl(struct i801_priv *priv, struct pci_dev *pci_dev,
 		 struct resource *tco_res)
 {
-	return platform_device_register_resndata(&pci_dev->dev, "iTCO_wdt", -1,
-					tco_res, 2, &cnl_tco_platform_data,
-					sizeof(cnl_tco_platform_data));
+	return platform_device_register_resndata(&pci_dev->dev,
+			"iTCO_wdt", -1, tco_res, 1, &cnl_tco_platform_data,
+			sizeof(cnl_tco_platform_data));
 }
 
 static void i801_add_tco(struct i801_priv *priv)
 {
-	u32 base_addr, tco_base, tco_ctl, ctrl_val;
 	struct pci_dev *pci_dev = priv->pci_dev;
-	struct resource tco_res[3], *res;
-	unsigned int devfn;
+	struct resource tco_res[2], *res;
+	u32 tco_base, tco_ctl;
 
 	/* If we have ACPI based watchdog use that instead */
 	if (acpi_has_watchdog())
@@ -1592,30 +1575,15 @@
 		return;
 
 	memset(tco_res, 0, sizeof(tco_res));
-
-	res = &tco_res[ICH_RES_IO_TCO];
-	res->start = tco_base & ~1;
-	res->end = res->start + 32 - 1;
-	res->flags = IORESOURCE_IO;
-
 	/*
-	 * Power Management registers.
+	 * Always populate the main iTCO IO resource here. The second entry
+	 * for NO_REBOOT MMIO is filled by the SPT specific function.
 	 */
-	devfn = PCI_DEVFN(PCI_SLOT(pci_dev->devfn), 2);
-	pci_bus_read_config_dword(pci_dev->bus, devfn, ACPIBASE, &base_addr);
-
-	res = &tco_res[ICH_RES_IO_SMI];
-	res->start = (base_addr & ~1) + ACPIBASE_SMI_OFF;
-	res->end = res->start + 3;
+	res = &tco_res[0];
+	res->start = tco_base & ~1;
+	res->end = res->start + 32 - 1;
 	res->flags = IORESOURCE_IO;
 
-	/*
-	 * Enable the ACPI I/O space.
-	 */
-	pci_bus_read_config_dword(pci_dev->bus, devfn, ACPICTRL, &ctrl_val);
-	ctrl_val |= ACPICTRL_EN;
-	pci_bus_write_config_dword(pci_dev->bus, devfn, ACPICTRL, ctrl_val);
-
 	if (priv->features & FEATURE_TCO_CNL)
 		priv->tco_pdev = i801_add_tco_cnl(priv, pci_dev, tco_res);
 	else
@@ -1709,6 +1677,16 @@
 static inline void i801_acpi_remove(struct i801_priv *priv) { }
 #endif
 
+static unsigned char i801_setup_hstcfg(struct i801_priv *priv)
+{
+	unsigned char hstcfg = priv->original_hstcfg;
+
+	hstcfg &= ~SMBHSTCFG_I2C_EN;	/* SMBus timing */
+	hstcfg |= SMBHSTCFG_HST_EN;
+	pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hstcfg);
+	return hstcfg;
+}
+
 static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
 	unsigned char temp;
@@ -1750,6 +1728,7 @@
 	case PCI_DEVICE_ID_INTEL_CDF_SMBUS:
 	case PCI_DEVICE_ID_INTEL_ICELAKE_LP_SMBUS:
 	case PCI_DEVICE_ID_INTEL_COMETLAKE_SMBUS:
+	case PCI_DEVICE_ID_INTEL_COMETLAKE_H_SMBUS:
 	case PCI_DEVICE_ID_INTEL_ELKHART_LAKE_SMBUS:
 	case PCI_DEVICE_ID_INTEL_TIGERLAKE_LP_SMBUS:
 		priv->features |= FEATURE_BLOCK_PROC;
@@ -1825,14 +1804,10 @@
 		return err;
 	}
 
-	pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &temp);
-	priv->original_hstcfg = temp;
-	temp &= ~SMBHSTCFG_I2C_EN;	/* SMBus timing */
-	if (!(temp & SMBHSTCFG_HST_EN)) {
+	pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &priv->original_hstcfg);
+	temp = i801_setup_hstcfg(priv);
+	if (!(priv->original_hstcfg & SMBHSTCFG_HST_EN))
 		dev_info(&dev->dev, "Enabling SMBus device\n");
-		temp |= SMBHSTCFG_HST_EN;
-	}
-	pci_write_config_byte(priv->pci_dev, SMBHSTCFG, temp);
 
 	if (temp & SMBHSTCFG_SMB_SMI_EN) {
 		dev_dbg(&dev->dev, "SMBus using interrupt SMI#\n");
@@ -1890,10 +1865,18 @@
 
 	i801_add_tco(priv);
 
+	/*
+	 * adapter.name is used by platform code to find the main I801 adapter
+	 * to instantiante i2c_clients, do not change.
+	 */
 	snprintf(priv->adapter.name, sizeof(priv->adapter.name),
-		"SMBus I801 adapter at %04lx", priv->smba);
+		 "SMBus %s adapter at %04lx",
+		 (priv->features & FEATURE_IDF) ? "I801 IDF" : "I801",
+		 priv->smba);
+
 	err = i2c_add_adapter(&priv->adapter);
 	if (err) {
+		platform_device_unregister(priv->tco_pdev);
 		i801_acpi_remove(priv);
 		return err;
 	}
@@ -1906,6 +1889,7 @@
 
 	pci_set_drvdata(dev, priv);
 
+	dev_pm_set_driver_flags(&dev->dev, DPM_FLAG_NEVER_SKIP);
 	pm_runtime_set_autosuspend_delay(&dev->dev, 1000);
 	pm_runtime_use_autosuspend(&dev->dev);
 	pm_runtime_put_autosuspend(&dev->dev);
@@ -1958,6 +1942,7 @@
 {
 	struct i801_priv *priv = dev_get_drvdata(dev);
 
+	i801_setup_hstcfg(priv);
 	i801_enable_host_notify(&priv->adapter);
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-icy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-icy.c
@@ -43,6 +43,7 @@
 #include <linux/i2c.h>
 #include <linux/i2c-algo-pcf.h>
 
+#include <asm/amigahw.h>
 #include <asm/amigaints.h>
 #include <linux/zorro.h>
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-img-scb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-img-scb.c
@@ -1057,7 +1057,7 @@
 			atomic = true;
 	}
 
-	ret = pm_runtime_get_sync(adap->dev.parent);
+	ret = pm_runtime_resume_and_get(adap->dev.parent);
 	if (ret < 0)
 		return ret;
 
@@ -1158,7 +1158,7 @@
 	u32 rev;
 	int ret;
 
-	ret = pm_runtime_get_sync(i2c->adap.dev.parent);
+	ret = pm_runtime_resume_and_get(i2c->adap.dev.parent);
 	if (ret < 0)
 		return ret;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-imx-lpi2c.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-imx-lpi2c.c
@@ -105,6 +105,7 @@
 	__u8			*rx_buf;
 	__u8			*tx_buf;
 	struct completion	complete;
+	unsigned long		rate_per;
 	unsigned int		msglen;
 	unsigned int		delivered;
 	unsigned int		block_data;
@@ -206,14 +207,15 @@
 /* CLKLO = I2C_CLK_RATIO * CLKHI, SETHOLD = CLKHI, DATAVD = CLKHI/2 */
 static int lpi2c_imx_config(struct lpi2c_imx_struct *lpi2c_imx)
 {
-	u8 prescale, filt, sethold, clkhi, clklo, datavd;
-	unsigned int clk_rate, clk_cycle;
+	u8 prescale, filt, sethold, datavd;
+	unsigned int clk_rate, clk_cycle, clkhi, clklo;
 	enum lpi2c_imx_pincfg pincfg;
 	unsigned int temp;
 
 	lpi2c_imx_set_mode(lpi2c_imx);
 
-	clk_rate = clk_get_rate(lpi2c_imx->clk);
+	clk_rate = lpi2c_imx->rate_per;
+
 	if (lpi2c_imx->mode == HS || lpi2c_imx->mode == ULTRA_FAST)
 		filt = 0;
 	else
@@ -265,7 +267,7 @@
 	unsigned int temp;
 	int ret;
 
-	ret = pm_runtime_get_sync(lpi2c_imx->adapter.dev.parent);
+	ret = pm_runtime_resume_and_get(lpi2c_imx->adapter.dev.parent);
 	if (ret < 0)
 		return ret;
 
@@ -468,6 +470,8 @@
 		if (num == 1 && msgs[0].len == 0)
 			goto stop;
 
+		lpi2c_imx->rx_buf = NULL;
+		lpi2c_imx->tx_buf = NULL;
 		lpi2c_imx->delivered = 0;
 		lpi2c_imx->msglen = msgs[i].len;
 		init_completion(&lpi2c_imx->complete);
@@ -508,10 +512,14 @@
 static irqreturn_t lpi2c_imx_isr(int irq, void *dev_id)
 {
 	struct lpi2c_imx_struct *lpi2c_imx = dev_id;
+	unsigned int enabled;
 	unsigned int temp;
 
+	enabled = readl(lpi2c_imx->base + LPI2C_MIER);
+
 	lpi2c_imx_intctrl(lpi2c_imx, 0);
 	temp = readl(lpi2c_imx->base + LPI2C_MSR);
+	temp &= enabled;
 
 	if (temp & MSR_RDF)
 		lpi2c_imx_read_rxfifo(lpi2c_imx);
@@ -596,6 +604,20 @@
 		return ret;
 	}
 
+	/*
+	 * Lock the parent clock rate to avoid getting parent clock upon
+	 * each transfer
+	 */
+	ret = devm_clk_rate_exclusive_get(&pdev->dev, lpi2c_imx->clk);
+	if (ret)
+		return dev_err_probe(&pdev->dev, ret,
+				     "can't lock I2C peripheral clock rate\n");
+
+	lpi2c_imx->rate_per = clk_get_rate(lpi2c_imx->clk);
+	if (!lpi2c_imx->rate_per)
+		return dev_err_probe(&pdev->dev, -EINVAL,
+				     "can't get I2C peripheral clock rate\n");
+
 	pm_runtime_set_autosuspend_delay(&pdev->dev, I2C_PM_TIMEOUT);
 	pm_runtime_use_autosuspend(&pdev->dev);
 	pm_runtime_get_noresume(&pdev->dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-imx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-imx.c
@@ -414,6 +414,19 @@
 	dma->chan_using = NULL;
 }
 
+static void i2c_imx_clear_irq(struct imx_i2c_struct *i2c_imx, unsigned int bits)
+{
+	unsigned int temp;
+
+	/*
+	 * i2sr_clr_opcode is the value to clear all interrupts. Here we want to
+	 * clear only <bits>, so we write ~i2sr_clr_opcode with just <bits>
+	 * toggled. This is required because i.MX needs W0C and Vybrid uses W1C.
+	 */
+	temp = ~i2c_imx->hwdata->i2sr_clr_opcode ^ bits;
+	imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR);
+}
+
 static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy)
 {
 	unsigned long orig_jiffies = jiffies;
@@ -426,8 +439,7 @@
 
 		/* check for arbitration lost */
 		if (temp & I2SR_IAL) {
-			temp &= ~I2SR_IAL;
-			imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR);
+			i2c_imx_clear_irq(i2c_imx, I2SR_IAL);
 			return -EAGAIN;
 		}
 
@@ -458,6 +470,16 @@
 		dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__);
 		return -ETIMEDOUT;
 	}
+
+	/* check for arbitration lost */
+	if (i2c_imx->i2csr & I2SR_IAL) {
+		dev_dbg(&i2c_imx->adapter.dev, "<%s> Arbitration lost\n", __func__);
+		i2c_imx_clear_irq(i2c_imx, I2SR_IAL);
+
+		i2c_imx->i2csr = 0;
+		return -EAGAIN;
+	}
+
 	dev_dbg(&i2c_imx->adapter.dev, "<%s> TRX complete\n", __func__);
 	i2c_imx->i2csr = 0;
 	return 0;
@@ -567,6 +589,8 @@
 		/* Stop I2C transaction */
 		dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
 		temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
+		if (!(temp & I2CR_MSTA))
+			i2c_imx->stopped = 1;
 		temp &= ~(I2CR_MSTA | I2CR_MTX);
 		if (i2c_imx->dma)
 			temp &= ~I2CR_DMAEN;
@@ -597,9 +621,7 @@
 	if (temp & I2SR_IIF) {
 		/* save status register */
 		i2c_imx->i2csr = temp;
-		temp &= ~I2SR_IIF;
-		temp |= (i2c_imx->hwdata->i2sr_clr_opcode & I2SR_IIF);
-		imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR);
+		i2c_imx_clear_irq(i2c_imx, I2SR_IIF);
 		wake_up(&i2c_imx->queue);
 		return IRQ_HANDLED;
 	}
@@ -732,9 +754,12 @@
 		 */
 		dev_dbg(dev, "<%s> clear MSTA\n", __func__);
 		temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
+		if (!(temp & I2CR_MSTA))
+			i2c_imx->stopped = 1;
 		temp &= ~(I2CR_MSTA | I2CR_MTX);
 		imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
-		i2c_imx_bus_busy(i2c_imx, 0);
+		if (!i2c_imx->stopped)
+			i2c_imx_bus_busy(i2c_imx, 0);
 	} else {
 		/*
 		 * For i2c master receiver repeat restart operation like:
@@ -857,9 +882,12 @@
 				dev_dbg(&i2c_imx->adapter.dev,
 					"<%s> clear MSTA\n", __func__);
 				temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
+				if (!(temp & I2CR_MSTA))
+					i2c_imx->stopped =  1;
 				temp &= ~(I2CR_MSTA | I2CR_MTX);
 				imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
-				i2c_imx_bus_busy(i2c_imx, 0);
+				if (!i2c_imx->stopped)
+					i2c_imx_bus_busy(i2c_imx, 0);
 			} else {
 				/*
 				 * For i2c master receiver repeat restart operation like:
@@ -1112,14 +1140,6 @@
 		return ret;
 	}
 
-	/* Request IRQ */
-	ret = devm_request_irq(&pdev->dev, irq, i2c_imx_isr, IRQF_SHARED,
-				pdev->name, i2c_imx);
-	if (ret) {
-		dev_err(&pdev->dev, "can't claim irq %d\n", irq);
-		goto clk_disable;
-	}
-
 	/* Init queue */
 	init_waitqueue_head(&i2c_imx->queue);
 
@@ -1138,6 +1158,14 @@
 	if (ret < 0)
 		goto rpm_disable;
 
+	/* Request IRQ */
+	ret = request_threaded_irq(irq, i2c_imx_isr, NULL, IRQF_SHARED,
+				   pdev->name, i2c_imx);
+	if (ret) {
+		dev_err(&pdev->dev, "can't claim irq %d\n", irq);
+		goto rpm_disable;
+	}
+
 	/* Set up clock divider */
 	i2c_imx->bitrate = IMX_I2C_BIT_RATE;
 	ret = of_property_read_u32(pdev->dev.of_node,
@@ -1180,13 +1208,12 @@
 
 clk_notifier_unregister:
 	clk_notifier_unregister(i2c_imx->clk, &i2c_imx->clk_change_nb);
+	free_irq(irq, i2c_imx);
 rpm_disable:
 	pm_runtime_put_noidle(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_set_suspended(&pdev->dev);
 	pm_runtime_dont_use_autosuspend(&pdev->dev);
-
-clk_disable:
 	clk_disable_unprepare(i2c_imx->clk);
 	return ret;
 }
@@ -1194,7 +1221,7 @@
 static int i2c_imx_remove(struct platform_device *pdev)
 {
 	struct imx_i2c_struct *i2c_imx = platform_get_drvdata(pdev);
-	int ret;
+	int irq, ret;
 
 	ret = pm_runtime_get_sync(&pdev->dev);
 	if (ret < 0)
@@ -1214,6 +1241,9 @@
 	imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2SR);
 
 	clk_notifier_unregister(i2c_imx->clk, &i2c_imx->clk_change_nb);
+	irq = platform_get_irq(pdev, 0);
+	if (irq >= 0)
+		free_irq(irq, i2c_imx);
 	clk_disable_unprepare(i2c_imx->clk);
 
 	pm_runtime_put_noidle(&pdev->dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-iop3xx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-iop3xx.c
@@ -433,13 +433,17 @@
 	adapter_data->gpio_scl = devm_gpiod_get_optional(&pdev->dev,
 							 "scl",
 							 GPIOD_ASIS);
-	if (IS_ERR(adapter_data->gpio_scl))
-		return PTR_ERR(adapter_data->gpio_scl);
+	if (IS_ERR(adapter_data->gpio_scl)) {
+		ret = PTR_ERR(adapter_data->gpio_scl);
+		goto free_both;
+	}
 	adapter_data->gpio_sda = devm_gpiod_get_optional(&pdev->dev,
 							 "sda",
 							 GPIOD_ASIS);
-	if (IS_ERR(adapter_data->gpio_sda))
-		return PTR_ERR(adapter_data->gpio_sda);
+	if (IS_ERR(adapter_data->gpio_sda)) {
+		ret = PTR_ERR(adapter_data->gpio_sda);
+		goto free_both;
+	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
@@ -463,16 +467,14 @@
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
-		ret = -ENXIO;
+		ret = irq;
 		goto unmap;
 	}
 	ret = request_irq(irq, iop3xx_i2c_irq_handler, 0,
 				pdev->name, adapter_data);
 
-	if (ret) {
-		ret = -EIO;
+	if (ret)
 		goto unmap;
-	}
 
 	memcpy(new_adapter->name, pdev->name, strlen(pdev->name));
 	new_adapter->owner = THIS_MODULE;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-isch.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-isch.c
@@ -99,8 +99,7 @@
 	if (retries > MAX_RETRIES) {
 		dev_err(&sch_adapter.dev, "SMBus Timeout!\n");
 		result = -ETIMEDOUT;
-	}
-	if (temp & 0x04) {
+	} else if (temp & 0x04) {
 		result = -EIO;
 		dev_dbg(&sch_adapter.dev, "Bus collision! SMBus may be "
 			"locked until next hard reset. (sorry!)\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-ismt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-ismt.c
@@ -81,6 +81,7 @@
 
 #define ISMT_DESC_ENTRIES	2	/* number of descriptor entries */
 #define ISMT_MAX_RETRIES	3	/* number of SMBus retries to attempt */
+#define ISMT_LOG_ENTRIES	3	/* number of interrupt cause log entries */
 
 /* Hardware Descriptor Constants - Control Field */
 #define ISMT_DESC_CWRL	0x01	/* Command/Write Length */
@@ -174,6 +175,8 @@
 	u8 head;				/* ring buffer head pointer */
 	struct completion cmp;			/* interrupt completion */
 	u8 buffer[I2C_SMBUS_BLOCK_MAX + 16];	/* temp R/W data buffer */
+	dma_addr_t log_dma;
+	u32 *log;
 };
 
 /**
@@ -408,6 +411,9 @@
 	memset(desc, 0, sizeof(struct ismt_desc));
 	desc->tgtaddr_rw = ISMT_DESC_ADDR_RW(addr, read_write);
 
+	/* Always clear the log entries */
+	memset(priv->log, 0, ISMT_LOG_ENTRIES * sizeof(u32));
+
 	/* Initialize common control bits */
 	if (likely(pci_dev_msi_enabled(priv->pci_dev)))
 		desc->control = ISMT_DESC_INT | ISMT_DESC_FAIR;
@@ -500,6 +506,9 @@
 		if (read_write == I2C_SMBUS_WRITE) {
 			/* Block Write */
 			dev_dbg(dev, "I2C_SMBUS_BLOCK_DATA:  WRITE\n");
+			if (data->block[0] < 1 || data->block[0] > I2C_SMBUS_BLOCK_MAX)
+				return -EINVAL;
+
 			dma_size = data->block[0] + 1;
 			dma_direction = DMA_TO_DEVICE;
 			desc->wr_len_cmd = dma_size;
@@ -697,6 +706,8 @@
 	/* initialize the Master Descriptor Base Address (MDBA) */
 	writeq(priv->io_rng_dma, priv->smba + ISMT_MSTR_MDBA);
 
+	writeq(priv->log_dma, priv->smba + ISMT_GR_SMTICL);
+
 	/* initialize the Master Control Register (MCTRL) */
 	writel(ISMT_MCTRL_MEIE, priv->smba + ISMT_MSTR_MCTRL);
 
@@ -784,6 +795,12 @@
 	priv->head = 0;
 	init_completion(&priv->cmp);
 
+	priv->log = dmam_alloc_coherent(&priv->pci_dev->dev,
+					ISMT_LOG_ENTRIES * sizeof(u32),
+					&priv->log_dma, GFP_KERNEL);
+	if (!priv->log)
+		return -ENOMEM;
+
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-jz4780.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-jz4780.c
@@ -73,25 +73,6 @@
 #define JZ4780_I2C_STA_TFNF		BIT(1)
 #define JZ4780_I2C_STA_ACT		BIT(0)
 
-static const char * const jz4780_i2c_abrt_src[] = {
-	"ABRT_7B_ADDR_NOACK",
-	"ABRT_10ADDR1_NOACK",
-	"ABRT_10ADDR2_NOACK",
-	"ABRT_XDATA_NOACK",
-	"ABRT_GCALL_NOACK",
-	"ABRT_GCALL_READ",
-	"ABRT_HS_ACKD",
-	"SBYTE_ACKDET",
-	"ABRT_HS_NORSTRT",
-	"SBYTE_NORSTRT",
-	"ABRT_10B_RD_NORSTRT",
-	"ABRT_MASTER_DIS",
-	"ARB_LOST",
-	"SLVFLUSH_TXFIFO",
-	"SLV_ARBLOST",
-	"SLVRD_INTX",
-};
-
 #define JZ4780_I2C_INTST_IGC		BIT(11)
 #define JZ4780_I2C_INTST_ISTT		BIT(10)
 #define JZ4780_I2C_INTST_ISTP		BIT(9)
@@ -529,21 +510,8 @@
 
 static void jz4780_i2c_txabrt(struct jz4780_i2c *i2c, int src)
 {
-	int i;
-
-	dev_err(&i2c->adap.dev, "txabrt: 0x%08x\n", src);
-	dev_err(&i2c->adap.dev, "device addr=%x\n",
-		jz4780_i2c_readw(i2c, JZ4780_I2C_TAR));
-	dev_err(&i2c->adap.dev, "send cmd count:%d  %d\n",
-		i2c->cmd, i2c->cmd_buf[i2c->cmd]);
-	dev_err(&i2c->adap.dev, "receive data count:%d  %d\n",
-		i2c->cmd, i2c->data_buf[i2c->cmd]);
-
-	for (i = 0; i < 16; i++) {
-		if (src & BIT(i))
-			dev_dbg(&i2c->adap.dev, "I2C TXABRT[%d]=%s\n",
-				i, jz4780_i2c_abrt_src[i]);
-	}
+	dev_dbg(&i2c->adap.dev, "txabrt: 0x%08x, cmd: %d, send: %d, recv: %d\n",
+		src, i2c->cmd, i2c->cmd_buf[i2c->cmd], i2c->data_buf[i2c->cmd]);
 }
 
 static inline int jz4780_i2c_xfer_read(struct jz4780_i2c *i2c,
@@ -783,7 +751,10 @@
 
 	jz4780_i2c_writew(i2c, JZ4780_I2C_INTM, 0x0);
 
-	i2c->irq = platform_get_irq(pdev, 0);
+	ret = platform_get_irq(pdev, 0);
+	if (ret < 0)
+		goto err;
+	i2c->irq = ret;
 	ret = devm_request_irq(&pdev->dev, i2c->irq, jz4780_i2c_irq, 0,
 			       dev_name(&pdev->dev), i2c);
 	if (ret)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-meson.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-meson.c
@@ -5,6 +5,7 @@
  * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com>
  */
 
+#include <linux/bitfield.h>
 #include <linux/clk.h>
 #include <linux/completion.h>
 #include <linux/i2c.h>
@@ -32,12 +33,17 @@
 #define REG_CTRL_ACK_IGNORE	BIT(1)
 #define REG_CTRL_STATUS		BIT(2)
 #define REG_CTRL_ERROR		BIT(3)
-#define REG_CTRL_CLKDIV_SHIFT	12
-#define REG_CTRL_CLKDIV_MASK	GENMASK(21, 12)
-#define REG_CTRL_CLKDIVEXT_SHIFT 28
-#define REG_CTRL_CLKDIVEXT_MASK	GENMASK(29, 28)
+#define REG_CTRL_CLKDIV		GENMASK(21, 12)
+#define REG_CTRL_CLKDIVEXT	GENMASK(29, 28)
+
+#define REG_SLV_ADDR		GENMASK(7, 0)
+#define REG_SLV_SDA_FILTER	GENMASK(10, 8)
+#define REG_SLV_SCL_FILTER	GENMASK(13, 11)
+#define REG_SLV_SCL_LOW		GENMASK(27, 16)
+#define REG_SLV_SCL_LOW_EN	BIT(28)
 
 #define I2C_TIMEOUT_MS		500
+#define FILTER_DELAY		15
 
 enum {
 	TOKEN_END = 0,
@@ -132,19 +138,24 @@
 	unsigned long clk_rate = clk_get_rate(i2c->clk);
 	unsigned int div;
 
-	div = DIV_ROUND_UP(clk_rate, freq * i2c->data->div_factor);
+	div = DIV_ROUND_UP(clk_rate, freq);
+	div -= FILTER_DELAY;
+	div = DIV_ROUND_UP(div, i2c->data->div_factor);
 
 	/* clock divider has 12 bits */
-	if (div >= (1 << 12)) {
+	if (div > GENMASK(11, 0)) {
 		dev_err(i2c->dev, "requested bus frequency too low\n");
-		div = (1 << 12) - 1;
+		div = GENMASK(11, 0);
 	}
 
-	meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_CLKDIV_MASK,
-			   (div & GENMASK(9, 0)) << REG_CTRL_CLKDIV_SHIFT);
+	meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_CLKDIV,
+			   FIELD_PREP(REG_CTRL_CLKDIV, div & GENMASK(9, 0)));
+
+	meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_CLKDIVEXT,
+			   FIELD_PREP(REG_CTRL_CLKDIVEXT, div >> 10));
 
-	meson_i2c_set_mask(i2c, REG_CTRL, REG_CTRL_CLKDIVEXT_MASK,
-			   (div >> 10) << REG_CTRL_CLKDIVEXT_SHIFT);
+	/* Disable HIGH/LOW mode */
+	meson_i2c_set_mask(i2c, REG_SLAVE_ADDR, REG_SLV_SCL_LOW_EN, 0);
 
 	dev_dbg(i2c->dev, "%s: clk %lu, freq %u, div %u\n", __func__,
 		clk_rate, freq, div);
@@ -273,7 +284,10 @@
 	token = (msg->flags & I2C_M_RD) ? TOKEN_SLAVE_ADDR_READ :
 		TOKEN_SLAVE_ADDR_WRITE;
 
-	writel(msg->addr << 1, i2c->regs + REG_SLAVE_ADDR);
+
+	meson_i2c_set_mask(i2c, REG_SLAVE_ADDR, REG_SLV_ADDR,
+			   FIELD_PREP(REG_SLV_ADDR, msg->addr << 1));
+
 	meson_i2c_add_token(i2c, TOKEN_START);
 	meson_i2c_add_token(i2c, token);
 }
@@ -432,6 +446,10 @@
 		return ret;
 	}
 
+	/* Disable filtering */
+	meson_i2c_set_mask(i2c, REG_SLAVE_ADDR,
+			   REG_SLV_SDA_FILTER | REG_SLV_SCL_FILTER, 0);
+
 	meson_i2c_set_clk_div(i2c, timings.bus_freq_hz);
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-mlxcpld.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-mlxcpld.c
@@ -337,9 +337,9 @@
 		if (priv->smbus_block && (val & MLXCPLD_I2C_SMBUS_BLK_BIT)) {
 			mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_NUM_DAT_REG,
 					      &datalen, 1);
-			if (unlikely(datalen > (I2C_SMBUS_BLOCK_MAX + 1))) {
+			if (unlikely(datalen > I2C_SMBUS_BLOCK_MAX)) {
 				dev_err(priv->dev, "Incorrect smbus block read message len\n");
-				return -E2BIG;
+				return -EPROTO;
 			}
 		} else {
 			datalen = priv->xfer.data_len;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-mpc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-mpc.c
@@ -23,6 +23,7 @@
 
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/iopoll.h>
 #include <linux/fsl_devices.h>
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
@@ -49,6 +50,7 @@
 #define CCR_MTX  0x10
 #define CCR_TXAK 0x08
 #define CCR_RSTA 0x04
+#define CCR_RSVD 0x02
 
 #define CSR_MCF  0x80
 #define CSR_MAAS 0x40
@@ -70,6 +72,7 @@
 	u8 fdr, dfsrr;
 #endif
 	struct clk *clk_per;
+	bool has_errata_A004447;
 };
 
 struct mpc_i2c_divider {
@@ -102,23 +105,30 @@
 /* Sometimes 9th clock pulse isn't generated, and slave doesn't release
  * the bus, because it wants to send ACK.
  * Following sequence of enabling/disabling and sending start/stop generates
- * the 9 pulses, so it's all OK.
+ * the 9 pulses, each with a START then ending with STOP, so it's all OK.
  */
 static void mpc_i2c_fixup(struct mpc_i2c *i2c)
 {
 	int k;
-	u32 delay_val = 1000000 / i2c->real_clk + 1;
-
-	if (delay_val < 2)
-		delay_val = 2;
+	unsigned long flags;
 
 	for (k = 9; k; k--) {
 		writeccr(i2c, 0);
-		writeccr(i2c, CCR_MSTA | CCR_MTX | CCR_MEN);
+		writeb(0, i2c->base + MPC_I2C_SR); /* clear any status bits */
+		writeccr(i2c, CCR_MEN | CCR_MSTA); /* START */
+		readb(i2c->base + MPC_I2C_DR); /* init xfer */
+		udelay(15); /* let it hit the bus */
+		local_irq_save(flags); /* should not be delayed further */
+		writeccr(i2c, CCR_MEN | CCR_MSTA | CCR_RSTA); /* delay SDA */
 		readb(i2c->base + MPC_I2C_DR);
-		writeccr(i2c, CCR_MEN);
-		udelay(delay_val << 1);
-	}
+		if (k != 1)
+			udelay(5);
+		local_irq_restore(flags);
+	}
+	writeccr(i2c, CCR_MEN); /* Initiate STOP */
+	readb(i2c->base + MPC_I2C_DR);
+	udelay(15); /* Let STOP propagate */
+	writeccr(i2c, 0);
 }
 
 static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing)
@@ -176,6 +186,75 @@
 	return 0;
 }
 
+static int i2c_mpc_wait_sr(struct mpc_i2c *i2c, int mask)
+{
+	void __iomem *addr = i2c->base + MPC_I2C_SR;
+	u8 val;
+
+	return readb_poll_timeout(addr, val, val & mask, 0, 100);
+}
+
+/*
+ * Workaround for Erratum A004447. From the P2040CE Rev Q
+ *
+ * 1.  Set up the frequency divider and sampling rate.
+ * 2.  I2CCR - a0h
+ * 3.  Poll for I2CSR[MBB] to get set.
+ * 4.  If I2CSR[MAL] is set (an indication that SDA is stuck low), then go to
+ *     step 5. If MAL is not set, then go to step 13.
+ * 5.  I2CCR - 00h
+ * 6.  I2CCR - 22h
+ * 7.  I2CCR - a2h
+ * 8.  Poll for I2CSR[MBB] to get set.
+ * 9.  Issue read to I2CDR.
+ * 10. Poll for I2CSR[MIF] to be set.
+ * 11. I2CCR - 82h
+ * 12. Workaround complete. Skip the next steps.
+ * 13. Issue read to I2CDR.
+ * 14. Poll for I2CSR[MIF] to be set.
+ * 15. I2CCR - 80h
+ */
+static void mpc_i2c_fixup_A004447(struct mpc_i2c *i2c)
+{
+	int ret;
+	u32 val;
+
+	writeccr(i2c, CCR_MEN | CCR_MSTA);
+	ret = i2c_mpc_wait_sr(i2c, CSR_MBB);
+	if (ret) {
+		dev_err(i2c->dev, "timeout waiting for CSR_MBB\n");
+		return;
+	}
+
+	val = readb(i2c->base + MPC_I2C_SR);
+
+	if (val & CSR_MAL) {
+		writeccr(i2c, 0x00);
+		writeccr(i2c, CCR_MSTA | CCR_RSVD);
+		writeccr(i2c, CCR_MEN | CCR_MSTA | CCR_RSVD);
+		ret = i2c_mpc_wait_sr(i2c, CSR_MBB);
+		if (ret) {
+			dev_err(i2c->dev, "timeout waiting for CSR_MBB\n");
+			return;
+		}
+		val = readb(i2c->base + MPC_I2C_DR);
+		ret = i2c_mpc_wait_sr(i2c, CSR_MIF);
+		if (ret) {
+			dev_err(i2c->dev, "timeout waiting for CSR_MIF\n");
+			return;
+		}
+		writeccr(i2c, CCR_MEN | CCR_RSVD);
+	} else {
+		val = readb(i2c->base + MPC_I2C_DR);
+		ret = i2c_mpc_wait_sr(i2c, CSR_MIF);
+		if (ret) {
+			dev_err(i2c->dev, "timeout waiting for CSR_MIF\n");
+			return;
+		}
+		writeccr(i2c, CCR_MEN);
+	}
+}
+
 #if defined(CONFIG_PPC_MPC52xx) || defined(CONFIG_PPC_MPC512x)
 static const struct mpc_i2c_divider mpc_i2c_dividers_52xx[] = {
 	{20, 0x20}, {22, 0x21}, {24, 0x22}, {26, 0x23},
@@ -586,7 +665,7 @@
 			if ((status & (CSR_MCF | CSR_MBB | CSR_RXAK)) != 0) {
 				writeb(status & ~CSR_MAL,
 				       i2c->base + MPC_I2C_SR);
-				mpc_i2c_fixup(i2c);
+				i2c_recover_bus(&i2c->adap);
 			}
 			return -EIO;
 		}
@@ -622,7 +701,7 @@
 			if ((status & (CSR_MCF | CSR_MBB | CSR_RXAK)) != 0) {
 				writeb(status & ~CSR_MAL,
 				       i2c->base + MPC_I2C_SR);
-				mpc_i2c_fixup(i2c);
+				i2c_recover_bus(&i2c->adap);
 			}
 			return -EIO;
 		}
@@ -637,6 +716,18 @@
 	  | I2C_FUNC_SMBUS_READ_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL;
 }
 
+static int fsl_i2c_bus_recovery(struct i2c_adapter *adap)
+{
+	struct mpc_i2c *i2c = i2c_get_adapdata(adap);
+
+	if (i2c->has_errata_A004447)
+		mpc_i2c_fixup_A004447(i2c);
+	else
+		mpc_i2c_fixup(i2c);
+
+	return 0;
+}
+
 static const struct i2c_algorithm mpc_algo = {
 	.master_xfer = mpc_xfer,
 	.functionality = mpc_functionality,
@@ -648,6 +739,10 @@
 	.timeout = HZ,
 };
 
+static struct i2c_bus_recovery_info fsl_i2c_recovery_info = {
+	.recover_bus = fsl_i2c_bus_recovery,
+};
+
 static const struct of_device_id mpc_i2c_of_match[];
 static int fsl_i2c_probe(struct platform_device *op)
 {
@@ -732,6 +827,8 @@
 	dev_info(i2c->dev, "timeout %u us\n", mpc_ops.timeout * 1000000 / HZ);
 
 	platform_set_drvdata(op, i2c);
+	if (of_property_read_bool(op->dev.of_node, "fsl,i2c-erratum-a004447"))
+		i2c->has_errata_A004447 = true;
 
 	i2c->adap = mpc_ops;
 	of_address_to_resource(op->dev.of_node, 0, &res);
@@ -740,6 +837,7 @@
 	i2c_set_adapdata(&i2c->adap, i2c);
 	i2c->adap.dev.parent = &op->dev;
 	i2c->adap.dev.of_node = of_node_get(op->dev.of_node);
+	i2c->adap.bus_recovery_info = &fsl_i2c_recovery_info;
 
 	result = i2c_add_adapter(&i2c->adap);
 	if (result < 0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-mt65xx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-mt65xx.c
@@ -389,6 +389,10 @@
 {
 	u16 control_reg;
 
+	writel(I2C_DMA_HARD_RST, i2c->pdmabase + OFFSET_RST);
+	udelay(50);
+	writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_RST);
+
 	mtk_i2c_writew(i2c, I2C_SOFT_RST, OFFSET_SOFTRESET);
 
 	/* Set ioconfig */
@@ -419,10 +423,6 @@
 
 	mtk_i2c_writew(i2c, control_reg, OFFSET_CONTROL);
 	mtk_i2c_writew(i2c, I2C_DELAY_LEN, OFFSET_DELAY_LEN);
-
-	writel(I2C_DMA_HARD_RST, i2c->pdmabase + OFFSET_RST);
-	udelay(50);
-	writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_RST);
 }
 
 /*
@@ -932,7 +932,7 @@
 		return PTR_ERR(i2c->pdmabase);
 
 	irq = platform_get_irq(pdev, 0);
-	if (irq <= 0)
+	if (irq < 0)
 		return irq;
 
 	init_completion(&i2c->msg_complete);
@@ -1008,7 +1008,8 @@
 	mtk_i2c_clock_disable(i2c);
 
 	ret = devm_request_irq(&pdev->dev, irq, mtk_i2c_irq,
-			       IRQF_TRIGGER_NONE, I2C_DRV_NAME, i2c);
+			       IRQF_NO_SUSPEND | IRQF_TRIGGER_NONE,
+			       I2C_DRV_NAME, i2c);
 	if (ret < 0) {
 		dev_err(&pdev->dev,
 			"Request I2C IRQ %d fail\n", irq);
@@ -1035,7 +1036,16 @@
 }
 
 #ifdef CONFIG_PM_SLEEP
-static int mtk_i2c_resume(struct device *dev)
+static int mtk_i2c_suspend_noirq(struct device *dev)
+{
+	struct mtk_i2c *i2c = dev_get_drvdata(dev);
+
+	i2c_mark_adapter_suspended(&i2c->adap);
+
+	return 0;
+}
+
+static int mtk_i2c_resume_noirq(struct device *dev)
 {
 	int ret;
 	struct mtk_i2c *i2c = dev_get_drvdata(dev);
@@ -1050,12 +1060,15 @@
 
 	mtk_i2c_clock_disable(i2c);
 
+	i2c_mark_adapter_resumed(&i2c->adap);
+
 	return 0;
 }
 #endif
 
 static const struct dev_pm_ops mtk_i2c_pm = {
-	SET_SYSTEM_SLEEP_PM_OPS(NULL, mtk_i2c_resume)
+	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(mtk_i2c_suspend_noirq,
+				      mtk_i2c_resume_noirq)
 };
 
 static struct platform_driver mtk_i2c_driver = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-mt7621.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-mt7621.c
@@ -304,7 +304,8 @@
 
 	if (i2c->bus_freq == 0) {
 		dev_warn(i2c->dev, "clock-frequency 0 not supported\n");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto err_disable_clk;
 	}
 
 	adap = &i2c->adap;
@@ -322,10 +323,15 @@
 
 	ret = i2c_add_adapter(adap);
 	if (ret < 0)
-		return ret;
+		goto err_disable_clk;
 
 	dev_info(&pdev->dev, "clock %u kHz\n", i2c->bus_freq / 1000);
 
+	return 0;
+
+err_disable_clk:
+	clk_disable_unprepare(i2c->clk);
+
 	return ret;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-mxs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-mxs.c
@@ -25,6 +25,7 @@
 #include <linux/of_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
+#include <linux/dma/mxs-dma.h>
 
 #define DRIVER_NAME "mxs-i2c"
 
@@ -200,7 +201,8 @@
 		dma_map_sg(i2c->dev, &i2c->sg_io[0], 1, DMA_TO_DEVICE);
 		desc = dmaengine_prep_slave_sg(i2c->dmach, &i2c->sg_io[0], 1,
 					DMA_MEM_TO_DEV,
-					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+					DMA_PREP_INTERRUPT |
+					MXS_DMA_CTRL_WAIT4END);
 		if (!desc) {
 			dev_err(i2c->dev,
 				"Failed to get DMA data write descriptor.\n");
@@ -228,7 +230,8 @@
 		dma_map_sg(i2c->dev, &i2c->sg_io[1], 1, DMA_FROM_DEVICE);
 		desc = dmaengine_prep_slave_sg(i2c->dmach, &i2c->sg_io[1], 1,
 					DMA_DEV_TO_MEM,
-					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+					DMA_PREP_INTERRUPT |
+					MXS_DMA_CTRL_WAIT4END);
 		if (!desc) {
 			dev_err(i2c->dev,
 				"Failed to get DMA data write descriptor.\n");
@@ -260,7 +263,8 @@
 		dma_map_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE);
 		desc = dmaengine_prep_slave_sg(i2c->dmach, i2c->sg_io, 2,
 					DMA_MEM_TO_DEV,
-					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+					DMA_PREP_INTERRUPT |
+					MXS_DMA_CTRL_WAIT4END);
 		if (!desc) {
 			dev_err(i2c->dev,
 				"Failed to get DMA data write descriptor.\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-nvidia-gpu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-nvidia-gpu.c
@@ -8,6 +8,7 @@
 #include <linux/delay.h>
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
+#include <linux/iopoll.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/platform_device.h>
@@ -75,20 +76,15 @@
 
 static int gpu_i2c_check_status(struct gpu_i2c_dev *i2cd)
 {
-	unsigned long target = jiffies + msecs_to_jiffies(1000);
 	u32 val;
+	int ret;
 
-	do {
-		val = readl(i2cd->regs + I2C_MST_CNTL);
-		if (!(val & I2C_MST_CNTL_CYCLE_TRIGGER))
-			break;
-		if ((val & I2C_MST_CNTL_STATUS) !=
-				I2C_MST_CNTL_STATUS_BUS_BUSY)
-			break;
-		usleep_range(500, 600);
-	} while (time_is_after_jiffies(target));
+	ret = readl_poll_timeout(i2cd->regs + I2C_MST_CNTL, val,
+				 !(val & I2C_MST_CNTL_CYCLE_TRIGGER) ||
+				 (val & I2C_MST_CNTL_STATUS) != I2C_MST_CNTL_STATUS_BUS_BUSY,
+				 500, 1000 * USEC_PER_MSEC);
 
-	if (time_is_before_jiffies(target)) {
+	if (ret) {
 		dev_err(i2cd->dev, "i2c timeout error %x\n", val);
 		return -ETIMEDOUT;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-ocores.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-ocores.c
@@ -343,18 +343,18 @@
  * ocores_isr(), we just add our polling code around it.
  *
  * It can run in atomic context
+ *
+ * Return: 0 on success, -ETIMEDOUT on timeout
  */
-static void ocores_process_polling(struct ocores_i2c *i2c)
+static int ocores_process_polling(struct ocores_i2c *i2c)
 {
-	while (1) {
-		irqreturn_t ret;
-		int err;
+	irqreturn_t ret;
+	int err = 0;
 
+	while (1) {
 		err = ocores_poll_wait(i2c);
-		if (err) {
-			i2c->state = STATE_ERROR;
+		if (err)
 			break; /* timeout */
-		}
 
 		ret = ocores_isr(-1, i2c);
 		if (ret == IRQ_NONE)
@@ -365,13 +365,15 @@
 					break;
 		}
 	}
+
+	return err;
 }
 
 static int ocores_xfer_core(struct ocores_i2c *i2c,
 			    struct i2c_msg *msgs, int num,
 			    bool polling)
 {
-	int ret;
+	int ret = 0;
 	u8 ctrl;
 
 	ctrl = oc_getreg(i2c, OCI2C_CONTROL);
@@ -389,15 +391,16 @@
 	oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START);
 
 	if (polling) {
-		ocores_process_polling(i2c);
+		ret = ocores_process_polling(i2c);
 	} else {
-		ret = wait_event_timeout(i2c->wait,
-					 (i2c->state == STATE_ERROR) ||
-					 (i2c->state == STATE_DONE), HZ);
-		if (ret == 0) {
-			ocores_process_timeout(i2c);
-			return -ETIMEDOUT;
-		}
+		if (wait_event_timeout(i2c->wait,
+				       (i2c->state == STATE_ERROR) ||
+				       (i2c->state == STATE_DONE), HZ) == 0)
+			ret = -ETIMEDOUT;
+	}
+	if (ret) {
+		ocores_process_timeout(i2c);
+		return ret;
 	}
 
 	return (i2c->state == STATE_DONE) ? num : -EIO;
@@ -440,8 +443,8 @@
 	oc_setreg(i2c, OCI2C_PREHIGH, prescale >> 8);
 
 	/* Init the device */
-	oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK);
 	oc_setreg(i2c, OCI2C_CONTROL, ctrl | OCI2C_CTRL_EN);
+	oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-octeon-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-octeon-core.c
@@ -347,7 +347,7 @@
 		if (result)
 			return result;
 		if (recv_len && i == 0) {
-			if (data[i] > I2C_SMBUS_BLOCK_MAX + 1)
+			if (data[i] > I2C_SMBUS_BLOCK_MAX)
 				return -EPROTO;
 			length += data[i];
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-omap.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-omap.c
@@ -1049,23 +1049,6 @@
 	return 0;
 }
 
-static irqreturn_t
-omap_i2c_isr(int irq, void *dev_id)
-{
-	struct omap_i2c_dev *omap = dev_id;
-	irqreturn_t ret = IRQ_HANDLED;
-	u16 mask;
-	u16 stat;
-
-	stat = omap_i2c_read_reg(omap, OMAP_I2C_STAT_REG);
-	mask = omap_i2c_read_reg(omap, OMAP_I2C_IE_REG);
-
-	if (stat & mask)
-		ret = IRQ_WAKE_THREAD;
-
-	return ret;
-}
-
 static int omap_i2c_xfer_data(struct omap_i2c_dev *omap)
 {
 	u16 bits;
@@ -1096,8 +1079,13 @@
 		}
 
 		if (stat & OMAP_I2C_STAT_NACK) {
-			err |= OMAP_I2C_STAT_NACK;
+			omap->cmd_err |= OMAP_I2C_STAT_NACK;
 			omap_i2c_ack_stat(omap, OMAP_I2C_STAT_NACK);
+
+			if (!(stat & ~OMAP_I2C_STAT_NACK)) {
+				err = -EAGAIN;
+				break;
+			}
 		}
 
 		if (stat & OMAP_I2C_STAT_AL) {
@@ -1408,9 +1396,9 @@
 	pm_runtime_set_autosuspend_delay(omap->dev, OMAP_I2C_PM_TIMEOUT);
 	pm_runtime_use_autosuspend(omap->dev);
 
-	r = pm_runtime_get_sync(omap->dev);
+	r = pm_runtime_resume_and_get(omap->dev);
 	if (r < 0)
-		goto err_free_mem;
+		goto err_disable_pm;
 
 	/*
 	 * Read the Rev hi bit-[15:14] ie scheme this is 1 indicates ver2.
@@ -1480,7 +1468,7 @@
 				IRQF_NO_SUSPEND, pdev->name, omap);
 	else
 		r = devm_request_threaded_irq(&pdev->dev, omap->irq,
-				omap_i2c_isr, omap_i2c_isr_thread,
+				NULL, omap_i2c_isr_thread,
 				IRQF_NO_SUSPEND | IRQF_ONESHOT,
 				pdev->name, omap);
 
@@ -1518,8 +1506,8 @@
 	omap_i2c_write_reg(omap, OMAP_I2C_CON_REG, 0);
 	pm_runtime_dont_use_autosuspend(omap->dev);
 	pm_runtime_put_sync(omap->dev);
+err_disable_pm:
 	pm_runtime_disable(&pdev->dev);
-err_free_mem:
 
 	return r;
 }
@@ -1530,7 +1518,7 @@
 	int ret;
 
 	i2c_del_adapter(&omap->adapter);
-	ret = pm_runtime_get_sync(&pdev->dev);
+	ret = pm_runtime_resume_and_get(&pdev->dev);
 	if (ret < 0)
 		return ret;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-owl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-owl.c
@@ -179,6 +179,9 @@
 	fifostat = readl(i2c_dev->base + OWL_I2C_REG_FIFOSTAT);
 	if (fifostat & OWL_I2C_FIFOSTAT_RNB) {
 		i2c_dev->err = -ENXIO;
+		/* Clear NACK error bit by writing "1" */
+		owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_FIFOSTAT,
+				   OWL_I2C_FIFOSTAT_RNB, true);
 		goto stop;
 	}
 
@@ -186,6 +189,9 @@
 	stat = readl(i2c_dev->base + OWL_I2C_REG_STAT);
 	if (stat & OWL_I2C_STAT_BEB) {
 		i2c_dev->err = -EIO;
+		/* Clear BUS error bit by writing "1" */
+		owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_STAT,
+				   OWL_I2C_STAT_BEB, true);
 		goto stop;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-pasemi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-pasemi.c
@@ -137,6 +137,12 @@
 
 		TXFIFO_WR(smbus, msg->buf[msg->len-1] |
 			  (stop ? MTXFIFO_STOP : 0));
+
+		if (stop) {
+			err = pasemi_smb_waitready(smbus);
+			if (err)
+				goto reset_out;
+		}
 	}
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-pca-platform.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-pca-platform.c
@@ -140,7 +140,7 @@
 	int ret = 0;
 	int irq;
 
-	irq = platform_get_irq(pdev, 0);
+	irq = platform_get_irq_optional(pdev, 0);
 	/* If irq is 0, we do polling. */
 	if (irq < 0)
 		irq = 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-piix4.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-piix4.c
@@ -977,7 +977,8 @@
 	}
 
 	if (dev->vendor == PCI_VENDOR_ID_AMD &&
-	    dev->device == PCI_DEVICE_ID_AMD_HUDSON2_SMBUS) {
+	    (dev->device == PCI_DEVICE_ID_AMD_HUDSON2_SMBUS ||
+	     dev->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS)) {
 		retval = piix4_setup_sb800(dev, id, 1);
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-pnx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-pnx.c
@@ -15,7 +15,6 @@
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/i2c.h>
-#include <linux/timer.h>
 #include <linux/completion.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
@@ -32,7 +31,6 @@
 	int			ret;		/* Return value */
 	int			mode;		/* Interface mode */
 	struct completion	complete;	/* I/O completion */
-	struct timer_list	timer;		/* Timeout */
 	u8 *			buf;		/* Data buffer */
 	int			len;		/* Length of data buffer */
 	int			order;		/* RX Bytes to order via TX */
@@ -97,7 +95,7 @@
 
 static inline int wait_timeout(struct i2c_pnx_algo_data *data)
 {
-	long timeout = data->timeout;
+	long timeout = jiffies_to_msecs(data->timeout);
 	while (timeout > 0 &&
 			(ioread32(I2C_REG_STS(data)) & mstatus_active)) {
 		mdelay(1);
@@ -108,7 +106,7 @@
 
 static inline int wait_reset(struct i2c_pnx_algo_data *data)
 {
-	long timeout = data->timeout;
+	long timeout = jiffies_to_msecs(data->timeout);
 	while (timeout > 0 &&
 			(ioread32(I2C_REG_CTL(data)) & mcntrl_reset)) {
 		mdelay(1);
@@ -117,24 +115,6 @@
 	return (timeout <= 0);
 }
 
-static inline void i2c_pnx_arm_timer(struct i2c_pnx_algo_data *alg_data)
-{
-	struct timer_list *timer = &alg_data->mif.timer;
-	unsigned long expires = msecs_to_jiffies(alg_data->timeout);
-
-	if (expires <= 1)
-		expires = 2;
-
-	del_timer_sync(timer);
-
-	dev_dbg(&alg_data->adapter.dev, "Timer armed at %lu plus %lu jiffies.\n",
-		jiffies, expires);
-
-	timer->expires = jiffies + expires;
-
-	add_timer(timer);
-}
-
 /**
  * i2c_pnx_start - start a device
  * @slave_addr:		slave address
@@ -259,8 +239,6 @@
 				~(mcntrl_afie | mcntrl_naie | mcntrl_drmie),
 				  I2C_REG_CTL(alg_data));
 
-			del_timer_sync(&alg_data->mif.timer);
-
 			dev_dbg(&alg_data->adapter.dev,
 				"%s(): Waking up xfer routine.\n",
 				__func__);
@@ -276,8 +254,6 @@
 			~(mcntrl_afie | mcntrl_naie | mcntrl_drmie),
 			  I2C_REG_CTL(alg_data));
 
-		/* Stop timer. */
-		del_timer_sync(&alg_data->mif.timer);
 		dev_dbg(&alg_data->adapter.dev,
 			"%s(): Waking up xfer routine after zero-xfer.\n",
 			__func__);
@@ -364,8 +340,6 @@
 				 mcntrl_drmie | mcntrl_daie);
 			iowrite32(ctl, I2C_REG_CTL(alg_data));
 
-			/* Kill timer. */
-			del_timer_sync(&alg_data->mif.timer);
 			complete(&alg_data->mif.complete);
 		}
 	}
@@ -400,8 +374,6 @@
 			 mcntrl_drmie);
 		iowrite32(ctl, I2C_REG_CTL(alg_data));
 
-		/* Stop timer, to prevent timeout. */
-		del_timer_sync(&alg_data->mif.timer);
 		complete(&alg_data->mif.complete);
 	} else if (stat & mstatus_nai) {
 		/* Slave did not acknowledge, generate a STOP */
@@ -419,8 +391,6 @@
 		/* Our return value. */
 		alg_data->mif.ret = -EIO;
 
-		/* Stop timer, to prevent timeout. */
-		del_timer_sync(&alg_data->mif.timer);
 		complete(&alg_data->mif.complete);
 	} else {
 		/*
@@ -453,9 +423,8 @@
 	return IRQ_HANDLED;
 }
 
-static void i2c_pnx_timeout(struct timer_list *t)
+static void i2c_pnx_timeout(struct i2c_pnx_algo_data *alg_data)
 {
-	struct i2c_pnx_algo_data *alg_data = from_timer(alg_data, t, mif.timer);
 	u32 ctl;
 
 	dev_err(&alg_data->adapter.dev,
@@ -472,7 +441,6 @@
 	iowrite32(ctl, I2C_REG_CTL(alg_data));
 	wait_reset(alg_data);
 	alg_data->mif.ret = -EIO;
-	complete(&alg_data->mif.complete);
 }
 
 static inline void bus_reset_if_active(struct i2c_pnx_algo_data *alg_data)
@@ -514,6 +482,7 @@
 	struct i2c_msg *pmsg;
 	int rc = 0, completed = 0, i;
 	struct i2c_pnx_algo_data *alg_data = adap->algo_data;
+	unsigned long time_left;
 	u32 stat;
 
 	dev_dbg(&alg_data->adapter.dev,
@@ -548,7 +517,6 @@
 		dev_dbg(&alg_data->adapter.dev, "%s(): mode %d, %d bytes\n",
 			__func__, alg_data->mif.mode, alg_data->mif.len);
 
-		i2c_pnx_arm_timer(alg_data);
 
 		/* initialize the completion var */
 		init_completion(&alg_data->mif.complete);
@@ -564,7 +532,10 @@
 			break;
 
 		/* Wait for completion */
-		wait_for_completion(&alg_data->mif.complete);
+		time_left = wait_for_completion_timeout(&alg_data->mif.complete,
+							alg_data->timeout);
+		if (time_left == 0)
+			i2c_pnx_timeout(alg_data);
 
 		if (!(rc = alg_data->mif.ret))
 			completed++;
@@ -657,7 +628,10 @@
 	alg_data->adapter.algo_data = alg_data;
 	alg_data->adapter.nr = pdev->id;
 
-	alg_data->timeout = I2C_PNX_TIMEOUT_DEFAULT;
+	alg_data->timeout = msecs_to_jiffies(I2C_PNX_TIMEOUT_DEFAULT);
+	if (alg_data->timeout <= 1)
+		alg_data->timeout = 2;
+
 #ifdef CONFIG_OF
 	alg_data->adapter.dev.of_node = of_node_get(pdev->dev.of_node);
 	if (pdev->dev.of_node) {
@@ -677,8 +651,6 @@
 	if (IS_ERR(alg_data->clk))
 		return PTR_ERR(alg_data->clk);
 
-	timer_setup(&alg_data->mif.timer, i2c_pnx_timeout, 0);
-
 	snprintf(alg_data->adapter.name, sizeof(alg_data->adapter.name),
 		 "%s", pdev->name);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-pxa-pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-pxa-pci.c
@@ -105,7 +105,7 @@
 	int i;
 	struct ce4100_devices *sds;
 
-	ret = pci_enable_device_mem(dev);
+	ret = pcim_enable_device(dev);
 	if (ret)
 		return ret;
 
@@ -114,10 +114,8 @@
 		return -EINVAL;
 	}
 	sds = kzalloc(sizeof(*sds), GFP_KERNEL);
-	if (!sds) {
-		ret = -ENOMEM;
-		goto err_mem;
-	}
+	if (!sds)
+		return -ENOMEM;
 
 	for (i = 0; i < ARRAY_SIZE(sds->pdev); i++) {
 		sds->pdev[i] = add_i2c_device(dev, i);
@@ -133,8 +131,6 @@
 
 err_dev_add:
 	kfree(sds);
-err_mem:
-	pci_disable_device(dev);
 	return ret;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-pxa.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-pxa.c
@@ -312,11 +312,10 @@
 	dev_err(dev, "IBMR: %08x IDBR: %08x ICR: %08x ISR: %08x\n",
 		readl(_IBMR(i2c)), readl(_IDBR(i2c)), readl(_ICR(i2c)),
 		readl(_ISR(i2c)));
-	dev_dbg(dev, "log: ");
+	dev_err(dev, "log:");
 	for (i = 0; i < i2c->irqlogidx; i++)
-		pr_debug("[%08x:%08x] ", i2c->isrlog[i], i2c->icrlog[i]);
-
-	pr_debug("\n");
+		pr_cont(" [%03x:%05x]", i2c->isrlog[i], i2c->icrlog[i]);
+	pr_cont("\n");
 }
 
 #else /* ifdef DEBUG */
@@ -706,11 +705,9 @@
 {
 	u32 icr;
 
-	/*
-	 * Clear the STOP and ACK flags
-	 */
+	/* Clear the START, STOP, ACK, TB and MA flags */
 	icr = readl(_ICR(i2c));
-	icr &= ~(ICR_STOP | ICR_ACKNAK);
+	icr &= ~(ICR_START | ICR_STOP | ICR_ACKNAK | ICR_TB | ICR_MA);
 	writel(icr, _ICR(i2c));
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-qcom-geni.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-qcom-geni.c
@@ -87,6 +87,9 @@
 	u32 clk_freq_out;
 	const struct geni_i2c_clk_fld *clk_fld;
 	int suspended;
+	void *dma_buf;
+	size_t xfer_len;
+	dma_addr_t dma_addr;
 };
 
 struct geni_i2c_err_log {
@@ -350,14 +353,39 @@
 		dev_err(gi2c->se.dev, "Timeout resetting TX_FSM\n");
 }
 
+static void geni_i2c_rx_msg_cleanup(struct geni_i2c_dev *gi2c,
+				     struct i2c_msg *cur)
+{
+	gi2c->cur_rd = 0;
+	if (gi2c->dma_buf) {
+		if (gi2c->err)
+			geni_i2c_rx_fsm_rst(gi2c);
+		geni_se_rx_dma_unprep(&gi2c->se, gi2c->dma_addr, gi2c->xfer_len);
+		i2c_put_dma_safe_msg_buf(gi2c->dma_buf, cur, !gi2c->err);
+	}
+}
+
+static void geni_i2c_tx_msg_cleanup(struct geni_i2c_dev *gi2c,
+				     struct i2c_msg *cur)
+{
+	gi2c->cur_wr = 0;
+	if (gi2c->dma_buf) {
+		if (gi2c->err)
+			geni_i2c_tx_fsm_rst(gi2c);
+		geni_se_tx_dma_unprep(&gi2c->se, gi2c->dma_addr, gi2c->xfer_len);
+		i2c_put_dma_safe_msg_buf(gi2c->dma_buf, cur, !gi2c->err);
+	}
+}
+
 static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
 				u32 m_param)
 {
-	dma_addr_t rx_dma;
+	dma_addr_t rx_dma = 0;
 	unsigned long time_left;
 	void *dma_buf = NULL;
 	struct geni_se *se = &gi2c->se;
 	size_t len = msg->len;
+	struct i2c_msg *cur;
 
 	if (!of_machine_is_compatible("lenovo,yoga-c630"))
 		dma_buf = i2c_get_dma_safe_msg_buf(msg, 32);
@@ -374,19 +402,18 @@
 		geni_se_select_mode(se, GENI_SE_FIFO);
 		i2c_put_dma_safe_msg_buf(dma_buf, msg, false);
 		dma_buf = NULL;
+	} else {
+		gi2c->xfer_len = len;
+		gi2c->dma_addr = rx_dma;
+		gi2c->dma_buf = dma_buf;
 	}
 
+	cur = gi2c->cur;
 	time_left = wait_for_completion_timeout(&gi2c->done, XFER_TIMEOUT);
 	if (!time_left)
 		geni_i2c_abort_xfer(gi2c);
 
-	gi2c->cur_rd = 0;
-	if (dma_buf) {
-		if (gi2c->err)
-			geni_i2c_rx_fsm_rst(gi2c);
-		geni_se_rx_dma_unprep(se, rx_dma, len);
-		i2c_put_dma_safe_msg_buf(dma_buf, msg, !gi2c->err);
-	}
+	geni_i2c_rx_msg_cleanup(gi2c, cur);
 
 	return gi2c->err;
 }
@@ -394,11 +421,12 @@
 static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
 				u32 m_param)
 {
-	dma_addr_t tx_dma;
+	dma_addr_t tx_dma = 0;
 	unsigned long time_left;
 	void *dma_buf = NULL;
 	struct geni_se *se = &gi2c->se;
 	size_t len = msg->len;
+	struct i2c_msg *cur;
 
 	if (!of_machine_is_compatible("lenovo,yoga-c630"))
 		dma_buf = i2c_get_dma_safe_msg_buf(msg, 32);
@@ -415,22 +443,21 @@
 		geni_se_select_mode(se, GENI_SE_FIFO);
 		i2c_put_dma_safe_msg_buf(dma_buf, msg, false);
 		dma_buf = NULL;
+	} else {
+		gi2c->xfer_len = len;
+		gi2c->dma_addr = tx_dma;
+		gi2c->dma_buf = dma_buf;
 	}
 
 	if (!dma_buf) /* Get FIFO IRQ */
 		writel_relaxed(1, se->base + SE_GENI_TX_WATERMARK_REG);
 
+	cur = gi2c->cur;
 	time_left = wait_for_completion_timeout(&gi2c->done, XFER_TIMEOUT);
 	if (!time_left)
 		geni_i2c_abort_xfer(gi2c);
 
-	gi2c->cur_wr = 0;
-	if (dma_buf) {
-		if (gi2c->err)
-			geni_i2c_tx_fsm_rst(gi2c);
-		geni_se_tx_dma_unprep(se, tx_dma, len);
-		i2c_put_dma_safe_msg_buf(dma_buf, msg, !gi2c->err);
-	}
+	geni_i2c_tx_msg_cleanup(gi2c, cur);
 
 	return gi2c->err;
 }
@@ -502,45 +529,40 @@
 	struct resource *res;
 	u32 proto, tx_depth;
 	int ret;
+	struct device *dev = &pdev->dev;
 
-	gi2c = devm_kzalloc(&pdev->dev, sizeof(*gi2c), GFP_KERNEL);
+	gi2c = devm_kzalloc(dev, sizeof(*gi2c), GFP_KERNEL);
 	if (!gi2c)
 		return -ENOMEM;
 
-	gi2c->se.dev = &pdev->dev;
-	gi2c->se.wrapper = dev_get_drvdata(pdev->dev.parent);
+	gi2c->se.dev = dev;
+	gi2c->se.wrapper = dev_get_drvdata(dev->parent);
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	gi2c->se.base = devm_ioremap_resource(&pdev->dev, res);
+	gi2c->se.base = devm_ioremap_resource(dev, res);
 	if (IS_ERR(gi2c->se.base))
 		return PTR_ERR(gi2c->se.base);
 
-	gi2c->se.clk = devm_clk_get(&pdev->dev, "se");
-	if (IS_ERR(gi2c->se.clk) && !has_acpi_companion(&pdev->dev)) {
-		ret = PTR_ERR(gi2c->se.clk);
-		dev_err(&pdev->dev, "Err getting SE Core clk %d\n", ret);
-		return ret;
-	}
+	gi2c->se.clk = devm_clk_get(dev, "se");
+	if (IS_ERR(gi2c->se.clk) && !has_acpi_companion(dev))
+		return PTR_ERR(gi2c->se.clk);
 
-	ret = device_property_read_u32(&pdev->dev, "clock-frequency",
-							&gi2c->clk_freq_out);
+	ret = device_property_read_u32(dev, "clock-frequency",
+				       &gi2c->clk_freq_out);
 	if (ret) {
-		dev_info(&pdev->dev,
-			"Bus frequency not specified, default to 100kHz.\n");
+		dev_info(dev, "Bus frequency not specified, default to 100kHz.\n");
 		gi2c->clk_freq_out = KHZ(100);
 	}
 
-	if (has_acpi_companion(&pdev->dev))
-		ACPI_COMPANION_SET(&gi2c->adap.dev, ACPI_COMPANION(&pdev->dev));
+	if (has_acpi_companion(dev))
+		ACPI_COMPANION_SET(&gi2c->adap.dev, ACPI_COMPANION(dev));
 
 	gi2c->irq = platform_get_irq(pdev, 0);
-	if (gi2c->irq < 0) {
-		dev_err(&pdev->dev, "IRQ error for i2c-geni\n");
+	if (gi2c->irq < 0)
 		return gi2c->irq;
-	}
 
 	ret = geni_i2c_clk_map_idx(gi2c);
 	if (ret) {
-		dev_err(&pdev->dev, "Invalid clk frequency %d Hz: %d\n",
+		dev_err(dev, "Invalid clk frequency %d Hz: %d\n",
 			gi2c->clk_freq_out, ret);
 		return ret;
 	}
@@ -549,29 +571,27 @@
 	init_completion(&gi2c->done);
 	spin_lock_init(&gi2c->lock);
 	platform_set_drvdata(pdev, gi2c);
-	ret = devm_request_irq(&pdev->dev, gi2c->irq, geni_i2c_irq,
-			       IRQF_TRIGGER_HIGH, "i2c_geni", gi2c);
+	ret = devm_request_irq(dev, gi2c->irq, geni_i2c_irq, IRQF_NO_AUTOEN,
+			       dev_name(dev), gi2c);
 	if (ret) {
-		dev_err(&pdev->dev, "Request_irq failed:%d: err:%d\n",
+		dev_err(dev, "Request_irq failed:%d: err:%d\n",
 			gi2c->irq, ret);
 		return ret;
 	}
-	/* Disable the interrupt so that the system can enter low-power mode */
-	disable_irq(gi2c->irq);
 	i2c_set_adapdata(&gi2c->adap, gi2c);
-	gi2c->adap.dev.parent = &pdev->dev;
-	gi2c->adap.dev.of_node = pdev->dev.of_node;
+	gi2c->adap.dev.parent = dev;
+	gi2c->adap.dev.of_node = dev->of_node;
 	strlcpy(gi2c->adap.name, "Geni-I2C", sizeof(gi2c->adap.name));
 
 	ret = geni_se_resources_on(&gi2c->se);
 	if (ret) {
-		dev_err(&pdev->dev, "Error turning on resources %d\n", ret);
+		dev_err(dev, "Error turning on resources %d\n", ret);
 		return ret;
 	}
 	proto = geni_se_read_proto(&gi2c->se);
 	tx_depth = geni_se_get_tx_fifo_depth(&gi2c->se);
 	if (proto != GENI_SE_I2C) {
-		dev_err(&pdev->dev, "Invalid proto %d\n", proto);
+		dev_err(dev, "Invalid proto %d\n", proto);
 		geni_se_resources_off(&gi2c->se);
 		return -ENXIO;
 	}
@@ -581,11 +601,11 @@
 							true, true, true);
 	ret = geni_se_resources_off(&gi2c->se);
 	if (ret) {
-		dev_err(&pdev->dev, "Error turning off resources %d\n", ret);
+		dev_err(dev, "Error turning off resources %d\n", ret);
 		return ret;
 	}
 
-	dev_dbg(&pdev->dev, "i2c fifo/se-dma mode. fifo depth:%d\n", tx_depth);
+	dev_dbg(dev, "i2c fifo/se-dma mode. fifo depth:%d\n", tx_depth);
 
 	gi2c->suspended = 1;
 	pm_runtime_set_suspended(gi2c->se.dev);
@@ -595,12 +615,12 @@
 
 	ret = i2c_add_adapter(&gi2c->adap);
 	if (ret) {
-		dev_err(&pdev->dev, "Error adding i2c adapter %d\n", ret);
+		dev_err(dev, "Error adding i2c adapter %d\n", ret);
 		pm_runtime_disable(gi2c->se.dev);
 		return ret;
 	}
 
-	dev_dbg(&pdev->dev, "Geni-I2C adaptor successfully added\n");
+	dev_dbg(dev, "Geni-I2C adaptor successfully added\n");
 
 	return 0;
 }
@@ -614,6 +634,14 @@
 	return 0;
 }
 
+static void geni_i2c_shutdown(struct platform_device *pdev)
+{
+	struct geni_i2c_dev *gi2c = platform_get_drvdata(pdev);
+
+	/* Make client i2c transfers start failing */
+	i2c_mark_adapter_suspended(&gi2c->adap);
+}
+
 static int __maybe_unused geni_i2c_runtime_suspend(struct device *dev)
 {
 	int ret;
@@ -650,6 +678,8 @@
 {
 	struct geni_i2c_dev *gi2c = dev_get_drvdata(dev);
 
+	i2c_mark_adapter_suspended(&gi2c->adap);
+
 	if (!gi2c->suspended) {
 		geni_i2c_runtime_suspend(dev);
 		pm_runtime_disable(dev);
@@ -659,8 +689,16 @@
 	return 0;
 }
 
+static int __maybe_unused geni_i2c_resume_noirq(struct device *dev)
+{
+	struct geni_i2c_dev *gi2c = dev_get_drvdata(dev);
+
+	i2c_mark_adapter_resumed(&gi2c->adap);
+	return 0;
+}
+
 static const struct dev_pm_ops geni_i2c_pm_ops = {
-	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(geni_i2c_suspend_noirq, NULL)
+	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(geni_i2c_suspend_noirq, geni_i2c_resume_noirq)
 	SET_RUNTIME_PM_OPS(geni_i2c_runtime_suspend, geni_i2c_runtime_resume,
 									NULL)
 };
@@ -674,6 +712,7 @@
 static struct platform_driver geni_i2c_driver = {
 	.probe  = geni_i2c_probe,
 	.remove = geni_i2c_remove,
+	.shutdown = geni_i2c_shutdown,
 	.driver = {
 		.name = "geni_i2c",
 		.pm = &geni_i2c_pm_ops,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-qup.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-qup.c
@@ -806,7 +806,8 @@
 	if (ret || qup->bus_err || qup->qup_err) {
 		reinit_completion(&qup->xfer);
 
-		if (qup_i2c_change_state(qup, QUP_RUN_STATE)) {
+		ret = qup_i2c_change_state(qup, QUP_RUN_STATE);
+		if (ret) {
 			dev_err(qup->dev, "change to run state timed out");
 			goto desc_err;
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-rcar.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-rcar.c
@@ -89,7 +89,6 @@
 
 #define RCAR_BUS_PHASE_START	(MDBS | MIE | ESG)
 #define RCAR_BUS_PHASE_DATA	(MDBS | MIE)
-#define RCAR_BUS_MASK_DATA	(~(ESG | FSB) & 0xFF)
 #define RCAR_BUS_PHASE_STOP	(MDBS | MIE | FSB)
 
 #define RCAR_IRQ_SEND	(MNR | MAL | MST | MAT | MDE)
@@ -117,6 +116,7 @@
 };
 
 struct rcar_i2c_priv {
+	u32 flags;
 	void __iomem *io;
 	struct i2c_adapter adap;
 	struct i2c_msg *msg;
@@ -127,7 +127,6 @@
 
 	int pos;
 	u32 icccr;
-	u32 flags;
 	u8 recovery_icmcr;	/* protected by adapter lock */
 	enum rcar_i2c_type devtype;
 	struct i2c_client *slave;
@@ -219,6 +218,14 @@
 
 }
 
+static void rcar_i2c_reset_slave(struct rcar_i2c_priv *priv)
+{
+	rcar_i2c_write(priv, ICSIER, 0);
+	rcar_i2c_write(priv, ICSSR, 0);
+	rcar_i2c_write(priv, ICSCR, SDBS);
+	rcar_i2c_write(priv, ICSAR, 0); /* Gen2: must be 0 if not using slave */
+}
+
 static int rcar_i2c_bus_barrier(struct rcar_i2c_priv *priv)
 {
 	int i;
@@ -580,13 +587,15 @@
 			rcar_i2c_write(priv, ICSIER, SDR | SSR | SAR);
 		}
 
-		rcar_i2c_write(priv, ICSSR, ~SAR & 0xff);
+		/* Clear SSR, too, because of old STOPs to other clients than us */
+		rcar_i2c_write(priv, ICSSR, ~(SAR | SSR) & 0xff);
 	}
 
 	/* master sent stop */
 	if (ssr_filtered & SSR) {
 		i2c_slave_event(priv->slave, I2C_SLAVE_STOP, &value);
-		rcar_i2c_write(priv, ICSIER, SAR | SSR);
+		rcar_i2c_write(priv, ICSCR, SIE | SDBS); /* clear our NACK */
+		rcar_i2c_write(priv, ICSIER, SAR);
 		rcar_i2c_write(priv, ICSSR, ~SSR & 0xff);
 	}
 
@@ -614,7 +623,7 @@
 /*
  * This driver has a lock-free design because there are IP cores (at least
  * R-Car Gen2) which have an inherent race condition in their hardware design.
- * There, we need to clear RCAR_BUS_MASK_DATA bits as soon as possible after
+ * There, we need to switch to RCAR_BUS_PHASE_DATA as soon as possible after
  * the interrupt was generated, otherwise an unwanted repeated message gets
  * generated. It turned out that taking a spinlock at the beginning of the ISR
  * was already causing repeated messages. Thus, this driver was converted to
@@ -623,13 +632,11 @@
 static irqreturn_t rcar_i2c_irq(int irq, void *ptr)
 {
 	struct rcar_i2c_priv *priv = ptr;
-	u32 msr, val;
+	u32 msr;
 
 	/* Clear START or STOP immediately, except for REPSTART after read */
-	if (likely(!(priv->flags & ID_P_REP_AFTER_RD))) {
-		val = rcar_i2c_read(priv, ICMCR);
-		rcar_i2c_write(priv, ICMCR, val & RCAR_BUS_MASK_DATA);
-	}
+	if (likely(!(priv->flags & ID_P_REP_AFTER_RD)))
+		rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_DATA);
 
 	msr = rcar_i2c_read(priv, ICMSR);
 
@@ -850,7 +857,7 @@
 	priv->slave = slave;
 	rcar_i2c_write(priv, ICSAR, slave->addr);
 	rcar_i2c_write(priv, ICSSR, 0);
-	rcar_i2c_write(priv, ICSIER, SAR | SSR);
+	rcar_i2c_write(priv, ICSIER, SAR);
 	rcar_i2c_write(priv, ICSCR, SIE | SDBS);
 
 	return 0;
@@ -862,11 +869,11 @@
 
 	WARN_ON(!priv->slave);
 
-	/* disable irqs and ensure none is running before clearing ptr */
-	rcar_i2c_write(priv, ICSIER, 0);
-	rcar_i2c_write(priv, ICSCR, 0);
+	/* ensure no irq is running before clearing ptr */
+	disable_irq(priv->irq);
+	rcar_i2c_reset_slave(priv);
+	enable_irq(priv->irq);
 
-	synchronize_irq(priv->irq);
 	priv->slave = NULL;
 
 	pm_runtime_put(rcar_i2c_priv_to_dev(priv));
@@ -971,6 +978,10 @@
 	if (ret < 0)
 		goto out_pm_put;
 
+	/* Bring hardware to known state */
+	rcar_i2c_init(priv);
+	rcar_i2c_reset_slave(priv);
+
 	if (priv->devtype == I2C_RCAR_GEN3) {
 		priv->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
 		if (!IS_ERR(priv->rstc)) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-riic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-riic.c
@@ -312,7 +312,7 @@
 	 * frequency with only 62 clock ticks max (31 high, 31 low).
 	 * Aim for a duty of 60% LOW, 40% HIGH.
 	 */
-	total_ticks = DIV_ROUND_UP(rate, t->bus_freq_hz);
+	total_ticks = DIV_ROUND_UP(rate, t->bus_freq_hz ?: 1);
 
 	for (cks = 0; cks < 7; cks++) {
 		/*
@@ -323,7 +323,7 @@
 		if (brl <= (0x1F + 3))
 			break;
 
-		total_ticks /= 2;
+		total_ticks = DIV_ROUND_UP(total_ticks, 2);
 		rate /= 2;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-rk3x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-rk3x.c
@@ -79,7 +79,7 @@
 #define DEFAULT_SCL_RATE  (100 * 1000) /* Hz */
 
 /**
- * struct i2c_spec_values:
+ * struct i2c_spec_values - I2C specification values for various modes
  * @min_hold_start_ns: min hold time (repeated) START condition
  * @min_low_ns: min LOW period of the SCL clock
  * @min_high_ns: min HIGH period of the SCL cloc
@@ -135,7 +135,7 @@
 };
 
 /**
- * struct rk3x_i2c_calced_timings:
+ * struct rk3x_i2c_calced_timings - calculated V1 timings
  * @div_low: Divider output for low
  * @div_high: Divider output for high
  * @tuning: Used to adjust setup/hold data time,
@@ -158,7 +158,7 @@
 };
 
 /**
- * struct rk3x_i2c_soc_data:
+ * struct rk3x_i2c_soc_data - SOC-specific data
  * @grf_offset: offset inside the grf regmap for setting the i2c type
  * @calc_timings: Callback function for i2c timing information calculated
  */
@@ -238,7 +238,8 @@
 }
 
 /**
- * Generate a START condition, which triggers a REG_INT_START interrupt.
+ * rk3x_i2c_start - Generate a START condition, which triggers a REG_INT_START interrupt.
+ * @i2c: target controller data
  */
 static void rk3x_i2c_start(struct rk3x_i2c *i2c)
 {
@@ -257,8 +258,8 @@
 }
 
 /**
- * Generate a STOP condition, which triggers a REG_INT_STOP interrupt.
- *
+ * rk3x_i2c_stop - Generate a STOP condition, which triggers a REG_INT_STOP interrupt.
+ * @i2c: target controller data
  * @error: Error code to return in rk3x_i2c_xfer
  */
 static void rk3x_i2c_stop(struct rk3x_i2c *i2c, int error)
@@ -297,7 +298,8 @@
 }
 
 /**
- * Setup a read according to i2c->msg
+ * rk3x_i2c_prepare_read - Setup a read according to i2c->msg
+ * @i2c: target controller data
  */
 static void rk3x_i2c_prepare_read(struct rk3x_i2c *i2c)
 {
@@ -328,7 +330,8 @@
 }
 
 /**
- * Fill the transmit buffer with data from i2c->msg
+ * rk3x_i2c_fill_transmit_buf - Fill the transmit buffer with data from i2c->msg
+ * @i2c: target controller data
  */
 static void rk3x_i2c_fill_transmit_buf(struct rk3x_i2c *i2c)
 {
@@ -415,15 +418,15 @@
 {
 	unsigned int i;
 	unsigned int len = i2c->msg->len - i2c->processed;
-	u32 uninitialized_var(val);
+	u32 val;
 	u8 byte;
 
 	/* we only care for MBRF here. */
 	if (!(ipd & REG_INT_MBRF))
 		return;
 
-	/* ack interrupt */
-	i2c_writel(i2c, REG_INT_MBRF, REG_IPD);
+	/* ack interrupt (read also produces a spurious START flag, clear it too) */
+	i2c_writel(i2c, REG_INT_MBRF | REG_INT_START, REG_IPD);
 
 	/* Can only handle a maximum of 32 bytes at a time */
 	if (len > 32)
@@ -531,11 +534,10 @@
 }
 
 /**
- * Get timing values of I2C specification
- *
+ * rk3x_i2c_get_spec - Get timing values of I2C specification
  * @speed: Desired SCL frequency
  *
- * Returns: Matched i2c spec values.
+ * Return: Matched i2c_spec_values.
  */
 static const struct i2c_spec_values *rk3x_i2c_get_spec(unsigned int speed)
 {
@@ -548,13 +550,12 @@
 }
 
 /**
- * Calculate divider values for desired SCL frequency
- *
+ * rk3x_i2c_v0_calc_timings - Calculate divider values for desired SCL frequency
  * @clk_rate: I2C input clock rate
  * @t: Known I2C timing information
  * @t_calc: Caculated rk3x private timings that would be written into regs
  *
- * Returns: 0 on success, -EINVAL if the goal SCL rate is too slow. In that case
+ * Return: %0 on success, -%EINVAL if the goal SCL rate is too slow. In that case
  * a best-effort divider value is returned in divs. If the target rate is
  * too high, we silently use the highest possible rate.
  */
@@ -709,13 +710,12 @@
 }
 
 /**
- * Calculate timing values for desired SCL frequency
- *
+ * rk3x_i2c_v1_calc_timings - Calculate timing values for desired SCL frequency
  * @clk_rate: I2C input clock rate
  * @t: Known I2C timing information
  * @t_calc: Caculated rk3x private timings that would be written into regs
  *
- * Returns: 0 on success, -EINVAL if the goal SCL rate is too slow. In that case
+ * Return: %0 on success, -%EINVAL if the goal SCL rate is too slow. In that case
  * a best-effort divider value is returned in divs. If the target rate is
  * too high, we silently use the highest possible rate.
  * The following formulas are v1's method to calculate timings.
@@ -959,14 +959,14 @@
 }
 
 /**
- * Setup I2C registers for an I2C operation specified by msgs, num.
- *
- * Must be called with i2c->lock held.
- *
+ * rk3x_i2c_setup - Setup I2C registers for an I2C operation specified by msgs, num.
+ * @i2c: target controller data
  * @msgs: I2C msgs to process
  * @num: Number of msgs
  *
- * returns: Number of I2C msgs processed or negative in case of error
+ * Must be called with i2c->lock held.
+ *
+ * Return: Number of I2C msgs processed or negative in case of error
  */
 static int rk3x_i2c_setup(struct rk3x_i2c *i2c, struct i2c_msg *msgs, int num)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-robotfuzz-osif.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-robotfuzz-osif.c
@@ -83,7 +83,7 @@
 			}
 		}
 
-		ret = osif_usb_read(adapter, OSIFI2C_STOP, 0, 0, NULL, 0);
+		ret = osif_usb_write(adapter, OSIFI2C_STOP, 0, 0, NULL, 0);
 		if (ret) {
 			dev_err(&adapter->dev, "failure sending STOP\n");
 			return -EREMOTEIO;
@@ -153,7 +153,7 @@
 	 * Set bus frequency. The frequency is:
 	 * 120,000,000 / ( 16 + 2 * div * 4^prescale).
 	 * Using dev = 52, prescale = 0 give 100KHz */
-	ret = osif_usb_read(&priv->adapter, OSIFI2C_SET_BIT_RATE, 52, 0,
+	ret = osif_usb_write(&priv->adapter, OSIFI2C_SET_BIT_RATE, 52, 0,
 			    NULL, 0);
 	if (ret) {
 		dev_err(&interface->dev, "failure sending bit rate");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-s3c2410.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-s3c2410.c
@@ -223,8 +223,17 @@
 	int tries;
 
 	for (tries = 50; tries; --tries) {
-		if (readl(i2c->regs + S3C2410_IICCON)
-			& S3C2410_IICCON_IRQPEND) {
+		unsigned long tmp = readl(i2c->regs + S3C2410_IICCON);
+
+		if (!(tmp & S3C2410_IICCON_ACKEN)) {
+			/*
+			 * Wait a bit for the bus to stabilize,
+			 * delay estimated experimentally.
+			 */
+			usleep_range(100, 200);
+			return true;
+		}
+		if (tmp & S3C2410_IICCON_IRQPEND) {
 			if (!(readl(i2c->regs + S3C2410_IICSTAT)
 				& S3C2410_IICSTAT_LASTBIT))
 				return true;
@@ -277,16 +286,6 @@
 
 	stat |= S3C2410_IICSTAT_START;
 	writel(stat, i2c->regs + S3C2410_IICSTAT);
-
-	if (i2c->quirks & QUIRK_POLL) {
-		while ((i2c->msg_num != 0) && is_ack(i2c)) {
-			i2c_s3c_irq_nextbyte(i2c, stat);
-			stat = readl(i2c->regs + S3C2410_IICSTAT);
-
-			if (stat & S3C2410_IICSTAT_ARBITR)
-				dev_err(i2c->dev, "deal with arbitration loss\n");
-		}
-	}
 }
 
 static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret)
@@ -484,7 +483,10 @@
 					 * forces us to send a new START
 					 * when we change direction
 					 */
+					dev_dbg(i2c->dev,
+						"missing START before write->read\n");
 					s3c24xx_i2c_stop(i2c, -EINVAL);
+					break;
 				}
 
 				goto retry_write;
@@ -691,7 +693,7 @@
 static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
 			      struct i2c_msg *msgs, int num)
 {
-	unsigned long timeout;
+	unsigned long timeout = 0;
 	int ret;
 
 	ret = s3c24xx_i2c_set_master(i2c);
@@ -711,16 +713,19 @@
 	s3c24xx_i2c_message_start(i2c, msgs);
 
 	if (i2c->quirks & QUIRK_POLL) {
-		ret = i2c->msg_idx;
+		while ((i2c->msg_num != 0) && is_ack(i2c)) {
+			unsigned long stat = readl(i2c->regs + S3C2410_IICSTAT);
 
-		if (ret != num)
-			dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret);
+			i2c_s3c_irq_nextbyte(i2c, stat);
 
-		goto out;
+			stat = readl(i2c->regs + S3C2410_IICSTAT);
+			if (stat & S3C2410_IICSTAT_ARBITR)
+				dev_err(i2c->dev, "deal with arbitration loss\n");
+		}
+	} else {
+		timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5);
 	}
 
-	timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5);
-
 	ret = i2c->msg_idx;
 
 	/*
@@ -1138,7 +1143,7 @@
 	 */
 	if (!(i2c->quirks & QUIRK_POLL)) {
 		i2c->irq = ret = platform_get_irq(pdev, 0);
-		if (ret <= 0) {
+		if (ret < 0) {
 			dev_err(&pdev->dev, "cannot find IRQ\n");
 			clk_unprepare(i2c->clk);
 			return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-sh7760.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-sh7760.c
@@ -471,7 +471,10 @@
 		goto out2;
 	}
 
-	id->irq = platform_get_irq(pdev, 0);
+	ret = platform_get_irq(pdev, 0);
+	if (ret < 0)
+		goto out3;
+	id->irq = ret;
 
 	id->adap.nr = pdev->id;
 	id->adap.algo = &sh7760_i2c_algo;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-sh_mobile.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-sh_mobile.c
@@ -129,6 +129,7 @@
 	int sr;
 	bool send_stop;
 	bool stop_after_dma;
+	bool atomic_xfer;
 
 	struct resource *res;
 	struct dma_chan *dma_tx;
@@ -333,13 +334,15 @@
 		ret = iic_rd(pd, ICDR);
 		break;
 	case OP_RX_STOP: /* enable DTE interrupt, issue stop */
-		iic_wr(pd, ICIC,
-		       ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE);
+		if (!pd->atomic_xfer)
+			iic_wr(pd, ICIC,
+			       ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE);
 		iic_wr(pd, ICCR, ICCR_ICE | ICCR_RACK);
 		break;
 	case OP_RX_STOP_DATA: /* enable DTE interrupt, read data, issue stop */
-		iic_wr(pd, ICIC,
-		       ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE);
+		if (!pd->atomic_xfer)
+			iic_wr(pd, ICIC,
+			       ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE);
 		ret = iic_rd(pd, ICDR);
 		iic_wr(pd, ICCR, ICCR_ICE | ICCR_RACK);
 		break;
@@ -435,7 +438,8 @@
 
 	if (wakeup) {
 		pd->sr |= SW_DONE;
-		wake_up(&pd->wait);
+		if (!pd->atomic_xfer)
+			wake_up(&pd->wait);
 	}
 
 	/* defeat write posting to avoid spurious WAIT interrupts */
@@ -587,6 +591,9 @@
 	pd->pos = -1;
 	pd->sr = 0;
 
+	if (pd->atomic_xfer)
+		return;
+
 	pd->dma_buf = i2c_get_dma_safe_msg_buf(pd->msg, 8);
 	if (pd->dma_buf)
 		sh_mobile_i2c_xfer_dma(pd);
@@ -643,15 +650,13 @@
 	return i ? 0 : -ETIMEDOUT;
 }
 
-static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter,
-			      struct i2c_msg *msgs,
-			      int num)
+static int sh_mobile_xfer(struct sh_mobile_i2c_data *pd,
+			 struct i2c_msg *msgs, int num)
 {
-	struct sh_mobile_i2c_data *pd = i2c_get_adapdata(adapter);
 	struct i2c_msg	*msg;
 	int err = 0;
 	int i;
-	long timeout;
+	long time_left;
 
 	/* Wake up device and enable clock */
 	pm_runtime_get_sync(pd->dev);
@@ -668,15 +673,35 @@
 		if (do_start)
 			i2c_op(pd, OP_START);
 
-		/* The interrupt handler takes care of the rest... */
-		timeout = wait_event_timeout(pd->wait,
-				       pd->sr & (ICSR_TACK | SW_DONE),
-				       adapter->timeout);
+		if (pd->atomic_xfer) {
+			unsigned long j = jiffies + pd->adap.timeout;
 
-		/* 'stop_after_dma' tells if DMA transfer was complete */
-		i2c_put_dma_safe_msg_buf(pd->dma_buf, pd->msg, pd->stop_after_dma);
+			time_left = time_before_eq(jiffies, j);
+			while (time_left &&
+			       !(pd->sr & (ICSR_TACK | SW_DONE))) {
+				unsigned char sr = iic_rd(pd, ICSR);
+
+				if (sr & (ICSR_AL   | ICSR_TACK |
+					  ICSR_WAIT | ICSR_DTE)) {
+					sh_mobile_i2c_isr(0, pd);
+					udelay(150);
+				} else {
+					cpu_relax();
+				}
+				time_left = time_before_eq(jiffies, j);
+			}
+		} else {
+			/* The interrupt handler takes care of the rest... */
+			time_left = wait_event_timeout(pd->wait,
+					pd->sr & (ICSR_TACK | SW_DONE),
+					pd->adap.timeout);
+
+			/* 'stop_after_dma' tells if DMA xfer was complete */
+			i2c_put_dma_safe_msg_buf(pd->dma_buf, pd->msg,
+						 pd->stop_after_dma);
+		}
 
-		if (!timeout) {
+		if (!time_left) {
 			dev_err(pd->dev, "Transfer request timed out\n");
 			if (pd->dma_direction != DMA_NONE)
 				sh_mobile_i2c_cleanup_dma(pd);
@@ -702,14 +727,35 @@
 	return err ?: num;
 }
 
+static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter,
+			      struct i2c_msg *msgs,
+			      int num)
+{
+	struct sh_mobile_i2c_data *pd = i2c_get_adapdata(adapter);
+
+	pd->atomic_xfer = false;
+	return sh_mobile_xfer(pd, msgs, num);
+}
+
+static int sh_mobile_i2c_xfer_atomic(struct i2c_adapter *adapter,
+				     struct i2c_msg *msgs,
+				     int num)
+{
+	struct sh_mobile_i2c_data *pd = i2c_get_adapdata(adapter);
+
+	pd->atomic_xfer = true;
+	return sh_mobile_xfer(pd, msgs, num);
+}
+
 static u32 sh_mobile_i2c_func(struct i2c_adapter *adapter)
 {
 	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING;
 }
 
 static const struct i2c_algorithm sh_mobile_i2c_algorithm = {
-	.functionality	= sh_mobile_i2c_func,
-	.master_xfer	= sh_mobile_i2c_xfer,
+	.functionality = sh_mobile_i2c_func,
+	.master_xfer = sh_mobile_i2c_xfer,
+	.master_xfer_atomic = sh_mobile_i2c_xfer_atomic,
 };
 
 static const struct i2c_adapter_quirks sh_mobile_i2c_quirks = {
@@ -767,7 +813,7 @@
 static const struct of_device_id sh_mobile_i2c_dt_ids[] = {
 	{ .compatible = "renesas,iic-r8a73a4", .data = &fast_clock_dt_config },
 	{ .compatible = "renesas,iic-r8a7740", .data = &r8a7740_dt_config },
-	{ .compatible = "renesas,iic-r8a774c0", .data = &fast_clock_dt_config },
+	{ .compatible = "renesas,iic-r8a774c0", .data = &v2_freq_calc_dt_config },
 	{ .compatible = "renesas,iic-r8a7790", .data = &v2_freq_calc_dt_config },
 	{ .compatible = "renesas,iic-r8a7791", .data = &v2_freq_calc_dt_config },
 	{ .compatible = "renesas,iic-r8a7792", .data = &v2_freq_calc_dt_config },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-sis630.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-sis630.c
@@ -509,6 +509,8 @@
 
 static int sis630_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
+	int ret;
+
 	if (sis630_setup(dev)) {
 		dev_err(&dev->dev,
 			"SIS630 compatible bus not detected, "
@@ -522,7 +524,15 @@
 	snprintf(sis630_adapter.name, sizeof(sis630_adapter.name),
 		 "SMBus SIS630 adapter at %04x", smbus_base + SMB_STS);
 
-	return i2c_add_adapter(&sis630_adapter);
+	ret = i2c_add_adapter(&sis630_adapter);
+	if (ret)
+		goto release_region;
+
+	return 0;
+
+release_region:
+	release_region(smbus_base + SMB_STS, SIS630_SMB_IOREGION);
+	return ret;
 }
 
 static void sis630_remove(struct pci_dev *dev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-sprd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-sprd.c
@@ -72,6 +72,8 @@
 
 /* timeout (ms) for pm runtime autosuspend */
 #define SPRD_I2C_PM_TIMEOUT	1000
+/* timeout (ms) for transfer message */
+#define I2C_XFER_TIMEOUT	1000
 
 /* SPRD i2c data structure */
 struct sprd_i2c {
@@ -244,6 +246,7 @@
 			       struct i2c_msg *msg, bool is_last_msg)
 {
 	struct sprd_i2c *i2c_dev = i2c_adap->algo_data;
+	unsigned long time_left;
 
 	i2c_dev->msg = msg;
 	i2c_dev->buf = msg->buf;
@@ -273,7 +276,10 @@
 
 	sprd_i2c_opt_start(i2c_dev);
 
-	wait_for_completion(&i2c_dev->complete);
+	time_left = wait_for_completion_timeout(&i2c_dev->complete,
+				msecs_to_jiffies(I2C_XFER_TIMEOUT));
+	if (!time_left)
+		return -ETIMEDOUT;
 
 	return i2c_dev->err;
 }
@@ -284,7 +290,7 @@
 	struct sprd_i2c *i2c_dev = i2c_adap->algo_data;
 	int im, ret;
 
-	ret = pm_runtime_get_sync(i2c_dev->dev);
+	ret = pm_runtime_resume_and_get(i2c_dev->dev);
 	if (ret < 0)
 		return ret;
 
@@ -573,10 +579,12 @@
 
 	ret = pm_runtime_get_sync(i2c_dev->dev);
 	if (ret < 0)
-		return ret;
+		dev_err(&pdev->dev, "Failed to resume device (%pe)\n", ERR_PTR(ret));
 
 	i2c_del_adapter(&i2c_dev->adap);
-	clk_disable_unprepare(i2c_dev->clk);
+
+	if (ret >= 0)
+		clk_disable_unprepare(i2c_dev->clk);
 
 	pm_runtime_put_noidle(i2c_dev->dev);
 	pm_runtime_disable(i2c_dev->dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-st.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-st.c
@@ -434,6 +434,7 @@
 /**
  * st_i2c_rd_fill_tx_fifo() - Fill the Tx FIFO in read mode
  * @i2c_dev: Controller's private data
+ * @max: Maximum amount of data to fill into the Tx FIFO
  *
  * This functions fills the Tx FIFO with fixed pattern when
  * in read mode to trigger clock.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-stm32.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-stm32.c
@@ -20,13 +20,13 @@
 
 	dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL);
 	if (!dma)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 
 	/* Request and configure I2C TX dma channel */
-	dma->chan_tx = dma_request_slave_channel(dev, "tx");
-	if (!dma->chan_tx) {
+	dma->chan_tx = dma_request_chan(dev, "tx");
+	if (IS_ERR(dma->chan_tx)) {
 		dev_dbg(dev, "can't request DMA tx channel\n");
-		ret = -EINVAL;
+		ret = PTR_ERR(dma->chan_tx);
 		goto fail_al;
 	}
 
@@ -42,10 +42,10 @@
 	}
 
 	/* Request and configure I2C RX dma channel */
-	dma->chan_rx = dma_request_slave_channel(dev, "rx");
-	if (!dma->chan_rx) {
+	dma->chan_rx = dma_request_chan(dev, "rx");
+	if (IS_ERR(dma->chan_rx)) {
 		dev_err(dev, "can't request DMA rx channel\n");
-		ret = -EINVAL;
+		ret = PTR_ERR(dma->chan_rx);
 		goto fail_tx;
 	}
 
@@ -75,7 +75,7 @@
 	devm_kfree(dev, dma);
 	dev_info(dev, "can't use DMA\n");
 
-	return NULL;
+	return ERR_PTR(ret);
 }
 
 void stm32_i2c_dma_free(struct stm32_i2c_dma *dma)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-stm32f7.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-stm32f7.c
@@ -53,6 +53,8 @@
 #define STM32F7_I2C_CR1_RXDMAEN			BIT(15)
 #define STM32F7_I2C_CR1_TXDMAEN			BIT(14)
 #define STM32F7_I2C_CR1_ANFOFF			BIT(12)
+#define STM32F7_I2C_CR1_DNF_MASK		GENMASK(11, 8)
+#define STM32F7_I2C_CR1_DNF(n)			(((n) & 0xf) << 8)
 #define STM32F7_I2C_CR1_ERRIE			BIT(7)
 #define STM32F7_I2C_CR1_TCIE			BIT(6)
 #define STM32F7_I2C_CR1_STOPIE			BIT(5)
@@ -151,7 +153,7 @@
 #define STM32F7_I2C_MAX_SLAVE			0x2
 
 #define STM32F7_I2C_DNF_DEFAULT			0
-#define STM32F7_I2C_DNF_MAX			16
+#define STM32F7_I2C_DNF_MAX			15
 
 #define STM32F7_I2C_ANALOG_FILTER_ENABLE	1
 #define STM32F7_I2C_ANALOG_FILTER_DELAY_MIN	50	/* ns */
@@ -657,6 +659,13 @@
 	else
 		stm32f7_i2c_set_bits(i2c_dev->base + STM32F7_I2C_CR1,
 				     STM32F7_I2C_CR1_ANFOFF);
+
+	/* Program the Digital Filter */
+	stm32f7_i2c_clr_bits(i2c_dev->base + STM32F7_I2C_CR1,
+			     STM32F7_I2C_CR1_DNF_MASK);
+	stm32f7_i2c_set_bits(i2c_dev->base + STM32F7_I2C_CR1,
+			     STM32F7_I2C_CR1_DNF(i2c_dev->setup.dnf));
+
 	stm32f7_i2c_set_bits(i2c_dev->base + STM32F7_I2C_CR1,
 			     STM32F7_I2C_CR1_PE);
 }
@@ -965,9 +974,10 @@
 	/* Configure PEC */
 	if ((flags & I2C_CLIENT_PEC) && f7_msg->size != I2C_SMBUS_QUICK) {
 		cr1 |= STM32F7_I2C_CR1_PECEN;
-		cr2 |= STM32F7_I2C_CR2_PECBYTE;
-		if (!f7_msg->read_write)
+		if (!f7_msg->read_write) {
+			cr2 |= STM32F7_I2C_CR2_PECBYTE;
 			f7_msg->count++;
+		}
 	} else {
 		cr1 &= ~STM32F7_I2C_CR1_PECEN;
 		cr2 &= ~STM32F7_I2C_CR2_PECBYTE;
@@ -1055,8 +1065,10 @@
 	f7_msg->stop = true;
 
 	/* Add one byte for PEC if needed */
-	if (cr1 & STM32F7_I2C_CR1_PECEN)
+	if (cr1 & STM32F7_I2C_CR1_PECEN) {
+		cr2 |= STM32F7_I2C_CR2_PECBYTE;
 		f7_msg->count++;
+	}
 
 	/* Set number of bytes to be transferred */
 	cr2 &= ~(STM32F7_I2C_CR2_NBYTES_MASK);
@@ -1267,8 +1279,8 @@
 	 * slave[0] supports 7-bit and 10-bit slave address
 	 * slave[1] supports 7-bit slave address only
 	 */
-	for (i = 0; i < STM32F7_I2C_MAX_SLAVE; i++) {
-		if (i == 1 && (slave->flags & I2C_CLIENT_PEC))
+	for (i = STM32F7_I2C_MAX_SLAVE - 1; i >= 0; i--) {
+		if (i == 1 && (slave->flags & I2C_CLIENT_TEN))
 			continue;
 		if (!i2c_dev->slave[i]) {
 			*id = i;
@@ -1385,6 +1397,7 @@
 {
 	struct stm32f7_i2c_dev *i2c_dev = data;
 	struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
+	struct stm32_i2c_dma *dma = i2c_dev->dma;
 	void __iomem *base = i2c_dev->base;
 	u32 status, mask;
 	int ret = IRQ_HANDLED;
@@ -1409,6 +1422,10 @@
 	if (status & STM32F7_I2C_ISR_NACKF) {
 		dev_dbg(i2c_dev->dev, "<%s>: Receive NACK\n", __func__);
 		writel_relaxed(STM32F7_I2C_ICR_NACKCF, base + STM32F7_I2C_ICR);
+		if (i2c_dev->use_dma) {
+			stm32f7_i2c_disable_dma_req(i2c_dev);
+			dmaengine_terminate_all(dma->chan_using);
+		}
 		f7_msg->result = -ENXIO;
 	}
 
@@ -1424,7 +1441,7 @@
 		/* Clear STOP flag */
 		writel_relaxed(STM32F7_I2C_ICR_STOPCF, base + STM32F7_I2C_ICR);
 
-		if (i2c_dev->use_dma) {
+		if (i2c_dev->use_dma && !f7_msg->result) {
 			ret = IRQ_WAKE_THREAD;
 		} else {
 			i2c_dev->master_mode = false;
@@ -1437,7 +1454,7 @@
 		if (f7_msg->stop) {
 			mask = STM32F7_I2C_CR2_STOP;
 			stm32f7_i2c_set_bits(base + STM32F7_I2C_CR2, mask);
-		} else if (i2c_dev->use_dma) {
+		} else if (i2c_dev->use_dma && !f7_msg->result) {
 			ret = IRQ_WAKE_THREAD;
 		} else if (f7_msg->smbus) {
 			stm32f7_i2c_smbus_rep_start(i2c_dev);
@@ -1577,12 +1594,23 @@
 	time_left = wait_for_completion_timeout(&i2c_dev->complete,
 						i2c_dev->adap.timeout);
 	ret = f7_msg->result;
+	if (ret) {
+		/*
+		 * It is possible that some unsent data have already been
+		 * written into TXDR. To avoid sending old data in a
+		 * further transfer, flush TXDR in case of any error
+		 */
+		writel_relaxed(STM32F7_I2C_ISR_TXE,
+			       i2c_dev->base + STM32F7_I2C_ISR);
+		goto pm_free;
+	}
 
 	if (!time_left) {
 		dev_dbg(i2c_dev->dev, "Access to slave 0x%x timed out\n",
 			i2c_dev->msg->addr);
 		if (i2c_dev->use_dma)
 			dmaengine_terminate_all(dma->chan_using);
+		stm32f7_i2c_wait_free_bus(i2c_dev);
 		ret = -ETIMEDOUT;
 	}
 
@@ -1625,13 +1653,22 @@
 	timeout = wait_for_completion_timeout(&i2c_dev->complete,
 					      i2c_dev->adap.timeout);
 	ret = f7_msg->result;
-	if (ret)
+	if (ret) {
+		/*
+		 * It is possible that some unsent data have already been
+		 * written into TXDR. To avoid sending old data in a
+		 * further transfer, flush TXDR in case of any error
+		 */
+		writel_relaxed(STM32F7_I2C_ISR_TXE,
+			       i2c_dev->base + STM32F7_I2C_ISR);
 		goto pm_free;
+	}
 
 	if (!timeout) {
 		dev_dbg(dev, "Access to slave 0x%x timed out\n", f7_msg->addr);
 		if (i2c_dev->use_dma)
 			dmaengine_terminate_all(dma->chan_using);
+		stm32f7_i2c_wait_free_bus(i2c_dev);
 		ret = -ETIMEDOUT;
 		goto pm_free;
 	}
@@ -1955,6 +1992,15 @@
 	i2c_dev->dma = stm32_i2c_dma_request(i2c_dev->dev, phy_addr,
 					     STM32F7_I2C_TXDR,
 					     STM32F7_I2C_RXDR);
+	if (PTR_ERR(i2c_dev->dma) == -ENODEV)
+		i2c_dev->dma = NULL;
+	else if (IS_ERR(i2c_dev->dma)) {
+		ret = PTR_ERR(i2c_dev->dma);
+		if (ret != -EPROBE_DEFER)
+			dev_err(&pdev->dev,
+				"Failed to request dma error %i\n", ret);
+		goto clk_free;
+	}
 
 	platform_set_drvdata(pdev, i2c_dev);
 
@@ -1985,6 +2031,11 @@
 	pm_runtime_set_suspended(i2c_dev->dev);
 	pm_runtime_dont_use_autosuspend(i2c_dev->dev);
 
+	if (i2c_dev->dma) {
+		stm32_i2c_dma_free(i2c_dev->dma);
+		i2c_dev->dma = NULL;
+	}
+
 clk_free:
 	clk_disable_unprepare(i2c_dev->clk);
 
@@ -1995,21 +2046,21 @@
 {
 	struct stm32f7_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
 
-	if (i2c_dev->dma) {
-		stm32_i2c_dma_free(i2c_dev->dma);
-		i2c_dev->dma = NULL;
-	}
-
 	i2c_del_adapter(&i2c_dev->adap);
 	pm_runtime_get_sync(i2c_dev->dev);
 
-	clk_disable_unprepare(i2c_dev->clk);
-
 	pm_runtime_put_noidle(i2c_dev->dev);
 	pm_runtime_disable(i2c_dev->dev);
 	pm_runtime_set_suspended(i2c_dev->dev);
 	pm_runtime_dont_use_autosuspend(i2c_dev->dev);
 
+	if (i2c_dev->dma) {
+		stm32_i2c_dma_free(i2c_dev->dma);
+		i2c_dev->dma = NULL;
+	}
+
+	clk_disable_unprepare(i2c_dev->clk);
+
 	return 0;
 }
 
@@ -2019,7 +2070,7 @@
 	struct stm32f7_i2c_dev *i2c_dev = dev_get_drvdata(dev);
 
 	if (!stm32f7_i2c_is_slave_registered(i2c_dev))
-		clk_disable_unprepare(i2c_dev->clk);
+		clk_disable(i2c_dev->clk);
 
 	return 0;
 }
@@ -2030,9 +2081,9 @@
 	int ret;
 
 	if (!stm32f7_i2c_is_slave_registered(i2c_dev)) {
-		ret = clk_prepare_enable(i2c_dev->clk);
+		ret = clk_enable(i2c_dev->clk);
 		if (ret) {
-			dev_err(dev, "failed to prepare_enable clock\n");
+			dev_err(dev, "failed to enable clock\n");
 			return ret;
 		}
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-sun6i-p2wi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-sun6i-p2wi.c
@@ -202,6 +202,11 @@
 		return -EINVAL;
 	}
 
+	if (clk_freq == 0) {
+		dev_err(dev, "clock-frequency is set to 0 in DT\n");
+		return -EINVAL;
+	}
+
 	if (of_get_child_count(np) > 1) {
 		dev_err(dev, "P2WI only supports one slave device\n");
 		return -EINVAL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-tegra-bpmp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-tegra-bpmp.c
@@ -80,7 +80,7 @@
 		flags &= ~I2C_M_RECV_LEN;
 	}
 
-	return (flags != 0) ? -EINVAL : 0;
+	return 0;
 }
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-tegra.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-tegra.c
@@ -16,6 +16,7 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
+#include <linux/irq.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
@@ -230,7 +231,6 @@
  * @base_phys: physical base address of the I2C controller
  * @cont_id: I2C controller ID, used for packet header
  * @irq: IRQ number of transfer complete interrupt
- * @irq_disabled: used to track whether or not the interrupt is enabled
  * @is_dvc: identifies the DVC I2C controller, has a different register layout
  * @msg_complete: transfer completion notifier
  * @msg_err: error code for completed message
@@ -240,7 +240,6 @@
  * @bus_clk_rate: current I2C bus clock rate
  * @clk_divisor_non_hs_mode: clock divider for non-high-speed modes
  * @is_multimaster_mode: track if I2C controller is in multi-master mode
- * @xfer_lock: lock to serialize transfer submission and processing
  * @tx_dma_chan: DMA transmit channel
  * @rx_dma_chan: DMA receive channel
  * @dma_phys: handle to DMA resources
@@ -260,7 +259,6 @@
 	phys_addr_t base_phys;
 	int cont_id;
 	int irq;
-	bool irq_disabled;
 	int is_dvc;
 	struct completion msg_complete;
 	int msg_err;
@@ -270,8 +268,6 @@
 	u32 bus_clk_rate;
 	u16 clk_divisor_non_hs_mode;
 	bool is_multimaster_mode;
-	/* xfer_lock: lock to serialize transfer submission and processing */
-	spinlock_t xfer_lock;
 	struct dma_chan *tx_dma_chan;
 	struct dma_chan *rx_dma_chan;
 	dma_addr_t dma_phys;
@@ -790,11 +786,6 @@
 	if (err)
 		return err;
 
-	if (i2c_dev->irq_disabled) {
-		i2c_dev->irq_disabled = false;
-		enable_irq(i2c_dev->irq);
-	}
-
 	return 0;
 }
 
@@ -825,18 +816,12 @@
 
 	status = i2c_readl(i2c_dev, I2C_INT_STATUS);
 
-	spin_lock(&i2c_dev->xfer_lock);
 	if (status == 0) {
 		dev_warn(i2c_dev->dev, "irq status 0 %08x %08x %08x\n",
 			 i2c_readl(i2c_dev, I2C_PACKET_TRANSFER_STATUS),
 			 i2c_readl(i2c_dev, I2C_STATUS),
 			 i2c_readl(i2c_dev, I2C_CNFG));
 		i2c_dev->msg_err |= I2C_ERR_UNKNOWN_INTERRUPT;
-
-		if (!i2c_dev->irq_disabled) {
-			disable_irq_nosync(i2c_dev->irq);
-			i2c_dev->irq_disabled = true;
-		}
 		goto err;
 	}
 
@@ -925,7 +910,6 @@
 
 	complete(&i2c_dev->msg_complete);
 done:
-	spin_unlock(&i2c_dev->xfer_lock);
 	return IRQ_HANDLED;
 }
 
@@ -999,6 +983,30 @@
 	i2c_writel(i2c_dev, val, reg);
 }
 
+static unsigned long
+tegra_i2c_wait_completion_timeout(struct tegra_i2c_dev *i2c_dev,
+				  struct completion *complete,
+				  unsigned int timeout_ms)
+{
+	unsigned long ret;
+
+	enable_irq(i2c_dev->irq);
+	ret = wait_for_completion_timeout(complete,
+					  msecs_to_jiffies(timeout_ms));
+	disable_irq(i2c_dev->irq);
+
+	/*
+	 * There is a chance that completion may happen after IRQ
+	 * synchronization, which is done by disable_irq().
+	 */
+	if (ret == 0 && completion_done(complete)) {
+		dev_warn(i2c_dev->dev, "completion done after timeout\n");
+		ret = 1;
+	}
+
+	return ret;
+}
+
 static int tegra_i2c_issue_bus_clear(struct i2c_adapter *adap)
 {
 	struct tegra_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
@@ -1020,8 +1028,8 @@
 	i2c_writel(i2c_dev, reg, I2C_BUS_CLEAR_CNFG);
 	tegra_i2c_unmask_irq(i2c_dev, I2C_INT_BUS_CLR_DONE);
 
-	time_left = wait_for_completion_timeout(&i2c_dev->msg_complete,
-						msecs_to_jiffies(50));
+	time_left = tegra_i2c_wait_completion_timeout(
+			i2c_dev, &i2c_dev->msg_complete, 50);
 	if (time_left == 0) {
 		dev_err(i2c_dev->dev, "timed out for bus clear\n");
 		return -ETIMEDOUT;
@@ -1044,7 +1052,6 @@
 	u32 packet_header;
 	u32 int_mask;
 	unsigned long time_left;
-	unsigned long flags;
 	size_t xfer_size;
 	u32 *buffer = NULL;
 	int err = 0;
@@ -1075,7 +1082,6 @@
 	 */
 	xfer_time += DIV_ROUND_CLOSEST(((xfer_size * 9) + 2) * MSEC_PER_SEC,
 					i2c_dev->bus_clk_rate);
-	spin_lock_irqsave(&i2c_dev->xfer_lock, flags);
 
 	int_mask = I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST;
 	tegra_i2c_unmask_irq(i2c_dev, int_mask);
@@ -1090,7 +1096,7 @@
 				dev_err(i2c_dev->dev,
 					"starting RX DMA failed, err %d\n",
 					err);
-				goto unlock;
+				return err;
 			}
 
 		} else {
@@ -1149,7 +1155,7 @@
 				dev_err(i2c_dev->dev,
 					"starting TX DMA failed, err %d\n",
 					err);
-				goto unlock;
+				return err;
 			}
 		} else {
 			tegra_i2c_fill_tx_fifo(i2c_dev);
@@ -1169,15 +1175,10 @@
 	dev_dbg(i2c_dev->dev, "unmasked irq: %02x\n",
 		i2c_readl(i2c_dev, I2C_INT_MASK));
 
-unlock:
-	spin_unlock_irqrestore(&i2c_dev->xfer_lock, flags);
-
 	if (dma) {
-		if (err)
-			return err;
+		time_left = tegra_i2c_wait_completion_timeout(
+				i2c_dev, &i2c_dev->dma_complete, xfer_time);
 
-		time_left = wait_for_completion_timeout(&i2c_dev->dma_complete,
-							msecs_to_jiffies(xfer_time));
 		if (time_left == 0) {
 			dev_err(i2c_dev->dev, "DMA transfer timeout\n");
 			dmaengine_terminate_sync(i2c_dev->msg_read ?
@@ -1202,13 +1203,13 @@
 					      i2c_dev->tx_dma_chan);
 	}
 
-	time_left = wait_for_completion_timeout(&i2c_dev->msg_complete,
-						msecs_to_jiffies(xfer_time));
+	time_left = tegra_i2c_wait_completion_timeout(
+			i2c_dev, &i2c_dev->msg_complete, xfer_time);
+
 	tegra_i2c_mask_irq(i2c_dev, int_mask);
 
 	if (time_left == 0) {
 		dev_err(i2c_dev->dev, "i2c transfer timed out\n");
-
 		tegra_i2c_init(i2c_dev, true);
 		return -ETIMEDOUT;
 	}
@@ -1568,7 +1569,6 @@
 				I2C_PACKET_HEADER_SIZE;
 	init_completion(&i2c_dev->msg_complete);
 	init_completion(&i2c_dev->dma_complete);
-	spin_lock_init(&i2c_dev->xfer_lock);
 
 	if (!i2c_dev->hw->has_single_clk_source) {
 		fast_clk = devm_clk_get(&pdev->dev, "fast-clk");
@@ -1608,14 +1608,18 @@
 	}
 
 	pm_runtime_enable(&pdev->dev);
-	if (!pm_runtime_enabled(&pdev->dev))
+	if (!pm_runtime_enabled(&pdev->dev)) {
 		ret = tegra_i2c_runtime_resume(&pdev->dev);
-	else
+		if (ret < 0) {
+			dev_err(&pdev->dev, "runtime resume failed\n");
+			goto unprepare_div_clk;
+		}
+	} else {
 		ret = pm_runtime_get_sync(i2c_dev->dev);
-
-	if (ret < 0) {
-		dev_err(&pdev->dev, "runtime resume failed\n");
-		goto unprepare_div_clk;
+		if (ret < 0) {
+			dev_err(&pdev->dev, "runtime resume failed\n");
+			goto disable_rpm;
+		}
 	}
 
 	if (i2c_dev->is_multimaster_mode) {
@@ -1623,7 +1627,7 @@
 		if (ret < 0) {
 			dev_err(i2c_dev->dev, "div_clk enable failed %d\n",
 				ret);
-			goto disable_rpm;
+			goto put_rpm;
 		}
 	}
 
@@ -1640,6 +1644,8 @@
 		goto release_dma;
 	}
 
+	irq_set_status_flags(i2c_dev->irq, IRQ_NOAUTOEN);
+
 	ret = devm_request_irq(&pdev->dev, i2c_dev->irq,
 			       tegra_i2c_isr, 0, dev_name(&pdev->dev), i2c_dev);
 	if (ret) {
@@ -1671,11 +1677,16 @@
 	if (i2c_dev->is_multimaster_mode)
 		clk_disable(i2c_dev->div_clk);
 
-disable_rpm:
-	pm_runtime_disable(&pdev->dev);
-	if (!pm_runtime_status_suspended(&pdev->dev))
+put_rpm:
+	if (pm_runtime_enabled(&pdev->dev))
+		pm_runtime_put_sync(&pdev->dev);
+	else
 		tegra_i2c_runtime_suspend(&pdev->dev);
 
+disable_rpm:
+	if (pm_runtime_enabled(&pdev->dev))
+		pm_runtime_disable(&pdev->dev);
+
 unprepare_div_clk:
 	clk_unprepare(i2c_dev->div_clk);
 
@@ -1710,10 +1721,14 @@
 static int __maybe_unused tegra_i2c_suspend(struct device *dev)
 {
 	struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
+	int err = 0;
 
 	i2c_mark_adapter_suspended(&i2c_dev->adapter);
 
-	return 0;
+	if (!pm_runtime_status_suspended(dev))
+		err = tegra_i2c_runtime_suspend(dev);
+
+	return err;
 }
 
 static int __maybe_unused tegra_i2c_resume(struct device *dev)
@@ -1721,6 +1736,10 @@
 	struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
 	int err;
 
+	/*
+	 * We need to ensure that clocks are enabled so that registers can be
+	 * restored in tegra_i2c_init().
+	 */
 	err = tegra_i2c_runtime_resume(dev);
 	if (err)
 		return err;
@@ -1729,9 +1748,16 @@
 	if (err)
 		return err;
 
-	err = tegra_i2c_runtime_suspend(dev);
-	if (err)
-		return err;
+	/*
+	 * In case we are runtime suspended, disable clocks again so that we
+	 * don't unbalance the clock reference counts during the next runtime
+	 * resume transition.
+	 */
+	if (pm_runtime_status_suspended(dev)) {
+		err = tegra_i2c_runtime_suspend(dev);
+		if (err)
+			return err;
+	}
 
 	i2c_mark_adapter_resumed(&i2c_dev->adapter);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-thunderx-pcidrv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-thunderx-pcidrv.c
@@ -208,6 +208,7 @@
 	i2c->adap.bus_recovery_info = &octeon_i2c_recovery_info;
 	i2c->adap.dev.parent = dev;
 	i2c->adap.dev.of_node = pdev->dev.of_node;
+	i2c->adap.dev.fwnode = dev->fwnode;
 	snprintf(i2c->adap.name, sizeof(i2c->adap.name),
 		 "Cavium ThunderX i2c adapter at %s", dev_name(dev));
 	i2c_set_adapdata(&i2c->adap, i2c);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-xgene-slimpro.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-xgene-slimpro.c
@@ -308,6 +308,9 @@
 	u32 msg[3];
 	int rc;
 
+	if (writelen > I2C_SMBUS_BLOCK_MAX)
+		return -EINVAL;
+
 	memcpy(ctx->dma_buffer, data, writelen);
 	paddr = dma_map_single(ctx->dev, ctx->dma_buffer, writelen,
 			       DMA_TO_DEVICE);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-xiic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-xiic.c
@@ -46,6 +46,7 @@
 
 /**
  * struct xiic_i2c - Internal representation of the XIIC I2C bus
+ * @dev:	Pointer to device structure
  * @base:	Memory base of the HW registers
  * @wait:	Wait queue for callers
  * @adap:	Kernel adapter representation
@@ -57,6 +58,10 @@
  * @rx_msg:	Current RX message
  * @rx_pos:	Position within current RX message
  * @endianness: big/little-endian byte order
+ * @clk:	Pointer to struct clk
+ * @dynamic: Mode of controller
+ * @prev_msg_tx: Previous message is Tx
+ * @smbus_block_read: Flag to handle block read
  */
 struct xiic_i2c {
 	struct device		*dev;
@@ -72,26 +77,28 @@
 	int			rx_pos;
 	enum xiic_endian	endianness;
 	struct clk *clk;
+	bool dynamic;
+	bool prev_msg_tx;
+	bool smbus_block_read;
 };
 
-
 #define XIIC_MSB_OFFSET 0
-#define XIIC_REG_OFFSET (0x100+XIIC_MSB_OFFSET)
+#define XIIC_REG_OFFSET (0x100 + XIIC_MSB_OFFSET)
 
 /*
  * Register offsets in bytes from RegisterBase. Three is added to the
  * base offset to access LSB (IBM style) of the word
  */
-#define XIIC_CR_REG_OFFSET   (0x00+XIIC_REG_OFFSET)	/* Control Register   */
-#define XIIC_SR_REG_OFFSET   (0x04+XIIC_REG_OFFSET)	/* Status Register    */
-#define XIIC_DTR_REG_OFFSET  (0x08+XIIC_REG_OFFSET)	/* Data Tx Register   */
-#define XIIC_DRR_REG_OFFSET  (0x0C+XIIC_REG_OFFSET)	/* Data Rx Register   */
-#define XIIC_ADR_REG_OFFSET  (0x10+XIIC_REG_OFFSET)	/* Address Register   */
-#define XIIC_TFO_REG_OFFSET  (0x14+XIIC_REG_OFFSET)	/* Tx FIFO Occupancy  */
-#define XIIC_RFO_REG_OFFSET  (0x18+XIIC_REG_OFFSET)	/* Rx FIFO Occupancy  */
-#define XIIC_TBA_REG_OFFSET  (0x1C+XIIC_REG_OFFSET)	/* 10 Bit Address reg */
-#define XIIC_RFD_REG_OFFSET  (0x20+XIIC_REG_OFFSET)	/* Rx FIFO Depth reg  */
-#define XIIC_GPO_REG_OFFSET  (0x24+XIIC_REG_OFFSET)	/* Output Register    */
+#define XIIC_CR_REG_OFFSET   (0x00 + XIIC_REG_OFFSET)	/* Control Register   */
+#define XIIC_SR_REG_OFFSET   (0x04 + XIIC_REG_OFFSET)	/* Status Register    */
+#define XIIC_DTR_REG_OFFSET  (0x08 + XIIC_REG_OFFSET)	/* Data Tx Register   */
+#define XIIC_DRR_REG_OFFSET  (0x0C + XIIC_REG_OFFSET)	/* Data Rx Register   */
+#define XIIC_ADR_REG_OFFSET  (0x10 + XIIC_REG_OFFSET)	/* Address Register   */
+#define XIIC_TFO_REG_OFFSET  (0x14 + XIIC_REG_OFFSET)	/* Tx FIFO Occupancy  */
+#define XIIC_RFO_REG_OFFSET  (0x18 + XIIC_REG_OFFSET)	/* Rx FIFO Occupancy  */
+#define XIIC_TBA_REG_OFFSET  (0x1C + XIIC_REG_OFFSET)	/* 10 Bit Address reg */
+#define XIIC_RFD_REG_OFFSET  (0x20 + XIIC_REG_OFFSET)	/* Rx FIFO Depth reg  */
+#define XIIC_GPO_REG_OFFSET  (0x24 + XIIC_REG_OFFSET)	/* Output Register    */
 
 /* Control Register masks */
 #define XIIC_CR_ENABLE_DEVICE_MASK        0x01	/* Device enable = 1      */
@@ -140,6 +147,9 @@
 #define XIIC_TX_DYN_START_MASK            0x0100 /* 1 = Set dynamic start */
 #define XIIC_TX_DYN_STOP_MASK             0x0200 /* 1 = Set dynamic stop */
 
+/* Dynamic mode constants */
+#define MAX_READ_LENGTH_DYNAMIC		255 /* Max length for dynamic read */
+
 /*
  * The following constants define the register offsets for the Interrupt
  * registers. There are some holes in the memory map for reserved addresses
@@ -154,6 +164,8 @@
 #define XIIC_RESET_MASK             0xAUL
 
 #define XIIC_PM_TIMEOUT		1000	/* ms */
+/* timeout waiting for the controller to respond */
+#define XIIC_I2C_TIMEOUT	(msecs_to_jiffies(1000))
 /*
  * The following constant is used for the device global interrupt enable
  * register, to enable all interrupts for the device, this is the only bit
@@ -164,7 +176,7 @@
 #define xiic_tx_space(i2c) ((i2c)->tx_msg->len - (i2c)->tx_pos)
 #define xiic_rx_space(i2c) ((i2c)->rx_msg->len - (i2c)->rx_pos)
 
-static void xiic_start_xfer(struct xiic_i2c *i2c);
+static int xiic_start_xfer(struct xiic_i2c *i2c);
 static void __xiic_start_xfer(struct xiic_i2c *i2c);
 
 /*
@@ -224,18 +236,21 @@
 static inline void xiic_irq_dis(struct xiic_i2c *i2c, u32 mask)
 {
 	u32 ier = xiic_getreg32(i2c, XIIC_IIER_OFFSET);
+
 	xiic_setreg32(i2c, XIIC_IIER_OFFSET, ier & ~mask);
 }
 
 static inline void xiic_irq_en(struct xiic_i2c *i2c, u32 mask)
 {
 	u32 ier = xiic_getreg32(i2c, XIIC_IIER_OFFSET);
+
 	xiic_setreg32(i2c, XIIC_IIER_OFFSET, ier | mask);
 }
 
 static inline void xiic_irq_clr(struct xiic_i2c *i2c, u32 mask)
 {
 	u32 isr = xiic_getreg32(i2c, XIIC_IISR_OFFSET);
+
 	xiic_setreg32(i2c, XIIC_IISR_OFFSET, isr & mask);
 }
 
@@ -245,17 +260,47 @@
 	xiic_irq_en(i2c, mask);
 }
 
-static void xiic_clear_rx_fifo(struct xiic_i2c *i2c)
+static int xiic_clear_rx_fifo(struct xiic_i2c *i2c)
 {
 	u8 sr;
+	unsigned long timeout;
+
+	timeout = jiffies + XIIC_I2C_TIMEOUT;
 	for (sr = xiic_getreg8(i2c, XIIC_SR_REG_OFFSET);
 		!(sr & XIIC_SR_RX_FIFO_EMPTY_MASK);
-		sr = xiic_getreg8(i2c, XIIC_SR_REG_OFFSET))
+		sr = xiic_getreg8(i2c, XIIC_SR_REG_OFFSET)) {
 		xiic_getreg8(i2c, XIIC_DRR_REG_OFFSET);
+		if (time_after(jiffies, timeout)) {
+			dev_err(i2c->dev, "Failed to clear rx fifo\n");
+			return -ETIMEDOUT;
+		}
+	}
+
+	return 0;
 }
 
-static void xiic_reinit(struct xiic_i2c *i2c)
+static int xiic_wait_tx_empty(struct xiic_i2c *i2c)
 {
+	u8 isr;
+	unsigned long timeout;
+
+	timeout = jiffies + XIIC_I2C_TIMEOUT;
+	for (isr = xiic_getreg32(i2c, XIIC_IISR_OFFSET);
+			!(isr & XIIC_INTR_TX_EMPTY_MASK);
+			isr = xiic_getreg32(i2c, XIIC_IISR_OFFSET)) {
+		if (time_after(jiffies, timeout)) {
+			dev_err(i2c->dev, "Timeout waiting at Tx empty\n");
+			return -ETIMEDOUT;
+		}
+	}
+
+	return 0;
+}
+
+static int xiic_reinit(struct xiic_i2c *i2c)
+{
+	int ret;
+
 	xiic_setreg32(i2c, XIIC_RESETR_OFFSET, XIIC_RESET_MASK);
 
 	/* Set receive Fifo depth to maximum (zero based). */
@@ -268,12 +313,16 @@
 	xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, XIIC_CR_ENABLE_DEVICE_MASK);
 
 	/* make sure RX fifo is empty */
-	xiic_clear_rx_fifo(i2c);
+	ret = xiic_clear_rx_fifo(i2c);
+	if (ret)
+		return ret;
 
 	/* Enable interrupts */
 	xiic_setreg32(i2c, XIIC_DGIER_OFFSET, XIIC_GINTR_ENABLE_MASK);
 
 	xiic_irq_clr_en(i2c, XIIC_INTR_ARB_LOST_MASK);
+
+	return 0;
 }
 
 static void xiic_deinit(struct xiic_i2c *i2c)
@@ -287,15 +336,64 @@
 	xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, cr & ~XIIC_CR_ENABLE_DEVICE_MASK);
 }
 
+static void xiic_smbus_block_read_setup(struct xiic_i2c *i2c)
+{
+	u8 rxmsg_len;
+	u8 rfd_set = 0;
+
+	/*
+	 * Clear the I2C_M_RECV_LEN flag to avoid setting
+	 * message length again
+	 */
+	i2c->rx_msg->flags &= ~I2C_M_RECV_LEN;
+
+	/* Set smbus_block_read flag to identify in isr */
+	i2c->smbus_block_read = true;
+
+	/* Read byte from rx fifo and set message length */
+	rxmsg_len  = xiic_getreg8(i2c, XIIC_DRR_REG_OFFSET);
+
+	i2c->rx_msg->buf[i2c->rx_pos++] = rxmsg_len;
+
+	/* Check if received length is valid */
+	if (rxmsg_len <= I2C_SMBUS_BLOCK_MAX) {
+		/* Set Receive fifo depth */
+		if (rxmsg_len > IIC_RX_FIFO_DEPTH) {
+			rfd_set = IIC_RX_FIFO_DEPTH - 1;
+			i2c->rx_msg->len = rxmsg_len + 1;
+		} else if ((rxmsg_len == 1) ||
+			   (rxmsg_len == 0)) {
+			/*
+			 * Minimum of 3 bytes required to exit cleanly. 1 byte
+			 * already received, Second byte is being received. Have
+			 * to set NACK in read_rx before receiving the last byte
+			 */
+			i2c->rx_msg->len = 3;
+		} else {
+			rfd_set = rxmsg_len - 2;
+			i2c->rx_msg->len = rxmsg_len + 1;
+		}
+		xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, rfd_set);
+
+		return;
+	}
+
+	/* Invalid message length, trigger STATE_ERROR with tx_msg_len in ISR */
+	i2c->tx_msg->len = 3;
+	i2c->smbus_block_read = false;
+	dev_err(i2c->adap.dev.parent, "smbus_block_read Invalid msg length\n");
+}
+
 static void xiic_read_rx(struct xiic_i2c *i2c)
 {
-	u8 bytes_in_fifo;
+	u8 bytes_in_fifo, cr = 0, bytes_to_read = 0;
+	u32 bytes_rem = 0;
 	int i;
 
 	bytes_in_fifo = xiic_getreg8(i2c, XIIC_RFO_REG_OFFSET) + 1;
 
 	dev_dbg(i2c->adap.dev.parent,
-		"%s entry, bytes in fifo: %d, msg: %d, SR: 0x%x, CR: 0x%x\n",
+		"%s entry, bytes in fifo: %d, rem: %d, SR: 0x%x, CR: 0x%x\n",
 		__func__, bytes_in_fifo, xiic_rx_space(i2c),
 		xiic_getreg8(i2c, XIIC_SR_REG_OFFSET),
 		xiic_getreg8(i2c, XIIC_CR_REG_OFFSET));
@@ -303,13 +401,59 @@
 	if (bytes_in_fifo > xiic_rx_space(i2c))
 		bytes_in_fifo = xiic_rx_space(i2c);
 
-	for (i = 0; i < bytes_in_fifo; i++)
+	bytes_to_read = bytes_in_fifo;
+
+	if (!i2c->dynamic) {
+		bytes_rem = xiic_rx_space(i2c) - bytes_in_fifo;
+
+		/* Set msg length if smbus_block_read */
+		if (i2c->rx_msg->flags & I2C_M_RECV_LEN) {
+			xiic_smbus_block_read_setup(i2c);
+			return;
+		}
+
+		if (bytes_rem > IIC_RX_FIFO_DEPTH) {
+			bytes_to_read = bytes_in_fifo;
+		} else if (bytes_rem > 1) {
+			bytes_to_read = bytes_rem - 1;
+		} else if (bytes_rem == 1) {
+			bytes_to_read = 1;
+			/* Set NACK in CR to indicate slave transmitter */
+			cr = xiic_getreg8(i2c, XIIC_CR_REG_OFFSET);
+			xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, cr |
+				     XIIC_CR_NO_ACK_MASK);
+		} else if (bytes_rem == 0) {
+			bytes_to_read = bytes_in_fifo;
+
+			/* Generate stop on the bus if it is last message */
+			if (i2c->nmsgs == 1) {
+				cr = xiic_getreg8(i2c, XIIC_CR_REG_OFFSET);
+				xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, cr &
+					     ~XIIC_CR_MSMS_MASK);
+			}
+
+			/* Make TXACK=0, clean up for next transaction */
+			cr = xiic_getreg8(i2c, XIIC_CR_REG_OFFSET);
+			xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, cr &
+				     ~XIIC_CR_NO_ACK_MASK);
+		}
+	}
+
+	/* Read the fifo */
+	for (i = 0; i < bytes_to_read; i++) {
 		i2c->rx_msg->buf[i2c->rx_pos++] =
 			xiic_getreg8(i2c, XIIC_DRR_REG_OFFSET);
+	}
+
+	if (i2c->dynamic) {
+		u8 bytes;
 
-	xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET,
-		(xiic_rx_space(i2c) > IIC_RX_FIFO_DEPTH) ?
-		IIC_RX_FIFO_DEPTH - 1 :  xiic_rx_space(i2c) - 1);
+		/* Receive remaining bytes if less than fifo depth */
+		bytes = min_t(u8, xiic_rx_space(i2c), IIC_RX_FIFO_DEPTH);
+		bytes--;
+
+		xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, bytes);
+	}
 }
 
 static int xiic_tx_fifo_space(struct xiic_i2c *i2c)
@@ -330,7 +474,8 @@
 
 	while (len--) {
 		u16 data = i2c->tx_msg->buf[i2c->tx_pos++];
-		if ((xiic_tx_space(i2c) == 0) && (i2c->nmsgs == 1)) {
+
+		if (!xiic_tx_space(i2c) && i2c->nmsgs == 1) {
 			/* last message in transfer -> STOP */
 			data |= XIIC_TX_DYN_STOP_MASK;
 			dev_dbg(i2c->adap.dev.parent, "%s TX STOP\n", __func__);
@@ -339,6 +484,62 @@
 	}
 }
 
+static void xiic_std_fill_tx_fifo(struct xiic_i2c *i2c)
+{
+	u8 fifo_space = xiic_tx_fifo_space(i2c);
+	u16 data = 0;
+	int len = xiic_tx_space(i2c);
+
+	dev_dbg(i2c->adap.dev.parent, "%s entry, len: %d, fifo space: %d\n",
+		__func__, len, fifo_space);
+
+	if (len > fifo_space)
+		len = fifo_space;
+	else if (len && !(i2c->nmsgs > 1))
+		len--;
+
+	while (len--) {
+		data = i2c->tx_msg->buf[i2c->tx_pos++];
+		xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, data);
+	}
+}
+
+static void xiic_send_tx(struct xiic_i2c *i2c)
+{
+	dev_dbg(i2c->adap.dev.parent,
+		"%s entry, rem: %d, SR: 0x%x, CR: 0x%x\n",
+		__func__, xiic_tx_space(i2c),
+		xiic_getreg8(i2c, XIIC_SR_REG_OFFSET),
+		xiic_getreg8(i2c, XIIC_CR_REG_OFFSET));
+
+	if (xiic_tx_space(i2c) > 1) {
+		xiic_std_fill_tx_fifo(i2c);
+		return;
+	}
+
+	if ((xiic_tx_space(i2c) == 1)) {
+		u16 data;
+
+		if (i2c->nmsgs == 1) {
+			u8 cr;
+			int status;
+
+			/* Wait till FIFO is empty so STOP is sent last */
+			status = xiic_wait_tx_empty(i2c);
+			if (status)
+				return;
+
+			/* Write to CR to stop */
+			cr = xiic_getreg8(i2c, XIIC_CR_REG_OFFSET);
+			xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, cr &
+				     ~XIIC_CR_MSMS_MASK);
+		}
+		/* Send last byte */
+		data = i2c->tx_msg->buf[i2c->tx_pos++];
+		xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, data);
+	}
+}
+
 static void xiic_wakeup(struct xiic_i2c *i2c, int code)
 {
 	i2c->tx_msg = NULL;
@@ -353,6 +554,10 @@
 	struct xiic_i2c *i2c = dev_id;
 	u32 pend, isr, ier;
 	u32 clr = 0;
+	int xfer_more = 0;
+	int wakeup_req = 0;
+	int wakeup_code = 0;
+	int ret;
 
 	/* Get the interrupt Status from the IPIF. There is no clearing of
 	 * interrupts in the IPIF. Interrupts must be cleared at the source.
@@ -369,12 +574,14 @@
 	dev_dbg(i2c->adap.dev.parent, "%s: SR: 0x%x, msg: %p, nmsgs: %d\n",
 		__func__, xiic_getreg8(i2c, XIIC_SR_REG_OFFSET),
 		i2c->tx_msg, i2c->nmsgs);
-
+	dev_dbg(i2c->adap.dev.parent, "%s, ISR: 0x%x, CR: 0x%x\n",
+		__func__, xiic_getreg32(i2c, XIIC_IISR_OFFSET),
+		xiic_getreg8(i2c, XIIC_CR_REG_OFFSET));
 
 	/* Service requesting interrupt */
 	if ((pend & XIIC_INTR_ARB_LOST_MASK) ||
-		((pend & XIIC_INTR_TX_ERROR_MASK) &&
-		!(pend & XIIC_INTR_RX_FULL_MASK))) {
+	    ((pend & XIIC_INTR_TX_ERROR_MASK) &&
+	    !(pend & XIIC_INTR_RX_FULL_MASK))) {
 		/* bus arbritration lost, or...
 		 * Transmit error _OR_ RX completed
 		 * if this happens when RX_FULL is not set
@@ -387,12 +594,20 @@
 		 * fifos and the next message is a TX with len 0 (only addr)
 		 * reset the IP instead of just flush fifos
 		 */
-		xiic_reinit(i2c);
-
-		if (i2c->rx_msg)
-			xiic_wakeup(i2c, STATE_ERROR);
-		if (i2c->tx_msg)
-			xiic_wakeup(i2c, STATE_ERROR);
+		ret = xiic_reinit(i2c);
+		if (!ret)
+			dev_dbg(i2c->adap.dev.parent, "reinit failed\n");
+
+		if (i2c->rx_msg) {
+			wakeup_req = 1;
+			wakeup_code = STATE_ERROR;
+		}
+		if (i2c->tx_msg) {
+			wakeup_req = 1;
+			wakeup_code = STATE_ERROR;
+		}
+		/* don't try to handle other events */
+		goto out;
 	}
 	if (pend & XIIC_INTR_RX_FULL_MASK) {
 		/* Receive register/FIFO is full */
@@ -426,27 +641,10 @@
 				i2c->tx_msg++;
 				dev_dbg(i2c->adap.dev.parent,
 					"%s will start next...\n", __func__);
-
-				__xiic_start_xfer(i2c);
+				xfer_more = 1;
 			}
 		}
 	}
-	if (pend & XIIC_INTR_BNB_MASK) {
-		/* IIC bus has transitioned to not busy */
-		clr |= XIIC_INTR_BNB_MASK;
-
-		/* The bus is not busy, disable BusNotBusy interrupt */
-		xiic_irq_dis(i2c, XIIC_INTR_BNB_MASK);
-
-		if (!i2c->tx_msg)
-			goto out;
-
-		if ((i2c->nmsgs == 1) && !i2c->rx_msg &&
-			xiic_tx_space(i2c) == 0)
-			xiic_wakeup(i2c, STATE_DONE);
-		else
-			xiic_wakeup(i2c, STATE_ERROR);
-	}
 	if (pend & (XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_HALF_MASK)) {
 		/* Transmit register/FIFO is empty or ½ empty */
 
@@ -459,17 +657,23 @@
 			goto out;
 		}
 
-		xiic_fill_tx_fifo(i2c);
-
-		/* current message sent and there is space in the fifo */
-		if (!xiic_tx_space(i2c) && xiic_tx_fifo_space(i2c) >= 2) {
+		if (xiic_tx_space(i2c)) {
+			if (i2c->dynamic)
+				xiic_fill_tx_fifo(i2c);
+			else
+				xiic_send_tx(i2c);
+		} else {
+			/* current message fully written */
 			dev_dbg(i2c->adap.dev.parent,
 				"%s end of message sent, nmsgs: %d\n",
 				__func__, i2c->nmsgs);
-			if (i2c->nmsgs > 1) {
+			/* Don't move onto the next message until the TX FIFO empties,
+			 * to ensure that a NAK is not missed.
+			 */
+			if (i2c->nmsgs > 1 && (pend & XIIC_INTR_TX_EMPTY_MASK)) {
 				i2c->nmsgs--;
 				i2c->tx_msg++;
-				__xiic_start_xfer(i2c);
+				xfer_more = 1;
 			} else {
 				xiic_irq_dis(i2c, XIIC_INTR_TX_HALF_MASK);
 
@@ -477,16 +681,45 @@
 					"%s Got TX IRQ but no more to do...\n",
 					__func__);
 			}
-		} else if (!xiic_tx_space(i2c) && (i2c->nmsgs == 1))
-			/* current frame is sent and is last,
-			 * make sure to disable tx half
-			 */
-			xiic_irq_dis(i2c, XIIC_INTR_TX_HALF_MASK);
+		}
 	}
+
+	if (pend & XIIC_INTR_BNB_MASK) {
+		/* IIC bus has transitioned to not busy */
+		clr |= XIIC_INTR_BNB_MASK;
+
+		/* The bus is not busy, disable BusNotBusy interrupt */
+		xiic_irq_dis(i2c, XIIC_INTR_BNB_MASK);
+
+		if (i2c->tx_msg && i2c->smbus_block_read) {
+			i2c->smbus_block_read = false;
+			/* Set requested message len=1 to indicate STATE_DONE */
+			i2c->tx_msg->len = 1;
+		}
+
+		if (!i2c->tx_msg)
+			goto out;
+
+		wakeup_req = 1;
+
+		if (i2c->nmsgs == 1 && !i2c->rx_msg &&
+		    xiic_tx_space(i2c) == 0)
+			wakeup_code = STATE_DONE;
+		else
+			wakeup_code = STATE_ERROR;
+	}
+
 out:
 	dev_dbg(i2c->adap.dev.parent, "%s clr: 0x%x\n", __func__, clr);
 
 	xiic_setreg32(i2c, XIIC_IISR_OFFSET, clr);
+	if (xfer_more)
+		__xiic_start_xfer(i2c);
+	if (wakeup_req)
+		xiic_wakeup(i2c, wakeup_code);
+
+	WARN_ON(xfer_more && wakeup_req);
+
 	mutex_unlock(&i2c->lock);
 	return IRQ_HANDLED;
 }
@@ -521,35 +754,117 @@
 
 static void xiic_start_recv(struct xiic_i2c *i2c)
 {
-	u8 rx_watermark;
+	u16 rx_watermark;
+	u8 cr = 0, rfd_set = 0;
 	struct i2c_msg *msg = i2c->rx_msg = i2c->tx_msg;
 	unsigned long flags;
 
-	/* Clear and enable Rx full interrupt. */
-	xiic_irq_clr_en(i2c, XIIC_INTR_RX_FULL_MASK | XIIC_INTR_TX_ERROR_MASK);
+	dev_dbg(i2c->adap.dev.parent, "%s entry, ISR: 0x%x, CR: 0x%x\n",
+		__func__, xiic_getreg32(i2c, XIIC_IISR_OFFSET),
+		xiic_getreg8(i2c, XIIC_CR_REG_OFFSET));
 
-	/* we want to get all but last byte, because the TX_ERROR IRQ is used
-	 * to inidicate error ACK on the address, and negative ack on the last
-	 * received byte, so to not mix them receive all but last.
-	 * In the case where there is only one byte to receive
-	 * we can check if ERROR and RX full is set at the same time
-	 */
-	rx_watermark = msg->len;
-	if (rx_watermark > IIC_RX_FIFO_DEPTH)
-		rx_watermark = IIC_RX_FIFO_DEPTH;
-	xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, rx_watermark - 1);
-
-	local_irq_save(flags);
-	if (!(msg->flags & I2C_M_NOSTART))
-		/* write the address */
+	/* Disable Tx interrupts */
+	xiic_irq_dis(i2c, XIIC_INTR_TX_HALF_MASK | XIIC_INTR_TX_EMPTY_MASK);
+
+	if (i2c->dynamic) {
+		u8 bytes;
+		u16 val;
+
+		/* Clear and enable Rx full interrupt. */
+		xiic_irq_clr_en(i2c, XIIC_INTR_RX_FULL_MASK |
+				XIIC_INTR_TX_ERROR_MASK);
+
+		/*
+		 * We want to get all but last byte, because the TX_ERROR IRQ
+		 * is used to indicate error ACK on the address, and
+		 * negative ack on the last received byte, so to not mix
+		 * them receive all but last.
+		 * In the case where there is only one byte to receive
+		 * we can check if ERROR and RX full is set at the same time
+		 */
+		rx_watermark = msg->len;
+		bytes = min_t(u8, rx_watermark, IIC_RX_FIFO_DEPTH);
+		bytes--;
+
+		xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, bytes);
+
+		local_irq_save(flags);
+		if (!(msg->flags & I2C_M_NOSTART))
+			/* write the address */
+			xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET,
+				      i2c_8bit_addr_from_msg(msg) |
+				      XIIC_TX_DYN_START_MASK);
+
+		xiic_irq_clr_en(i2c, XIIC_INTR_BNB_MASK);
+
+		/* If last message, include dynamic stop bit with length */
+		val = (i2c->nmsgs == 1) ? XIIC_TX_DYN_STOP_MASK : 0;
+		val |= msg->len;
+
+		xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, val);
+		local_irq_restore(flags);
+	} else {
+		/*
+		 * If previous message is Tx, make sure that Tx FIFO is empty
+		 * before starting a new transfer as the repeated start in
+		 * standard mode can corrupt the transaction if there are
+		 * still bytes to be transmitted in FIFO
+		 */
+		if (i2c->prev_msg_tx) {
+			int status;
+
+			status = xiic_wait_tx_empty(i2c);
+			if (status)
+				return;
+		}
+
+		cr = xiic_getreg8(i2c, XIIC_CR_REG_OFFSET);
+
+		/* Set Receive fifo depth */
+		rx_watermark = msg->len;
+		if (rx_watermark > IIC_RX_FIFO_DEPTH) {
+			rfd_set = IIC_RX_FIFO_DEPTH - 1;
+		} else if ((rx_watermark == 1) || (rx_watermark == 0)) {
+			rfd_set = rx_watermark - 1;
+
+			/* Set No_ACK, except for smbus_block_read */
+			if (!(i2c->rx_msg->flags & I2C_M_RECV_LEN)) {
+				/* Handle single byte transfer separately */
+				cr |= XIIC_CR_NO_ACK_MASK;
+			}
+		} else {
+			rfd_set = rx_watermark - 2;
+		}
+
+		/* Check if RSTA should be set */
+		if (cr & XIIC_CR_MSMS_MASK) {
+			/* Already a master, RSTA should be set */
+			xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, (cr |
+				     XIIC_CR_REPEATED_START_MASK) &
+				     ~(XIIC_CR_DIR_IS_TX_MASK));
+		}
+
+		xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, rfd_set);
+
+		/* Clear and enable Rx full and transmit complete interrupts */
+		xiic_irq_clr_en(i2c, XIIC_INTR_RX_FULL_MASK |
+				XIIC_INTR_TX_ERROR_MASK);
+
+		/* Write the address */
 		xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET,
-			i2c_8bit_addr_from_msg(msg) | XIIC_TX_DYN_START_MASK);
+			      i2c_8bit_addr_from_msg(msg));
 
-	xiic_irq_clr_en(i2c, XIIC_INTR_BNB_MASK);
+		/* Write to Control Register,to start transaction in Rx mode */
+		if ((cr & XIIC_CR_MSMS_MASK) == 0) {
+			xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, (cr |
+				     XIIC_CR_MSMS_MASK)
+				     & ~(XIIC_CR_DIR_IS_TX_MASK));
+		}
 
-	xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET,
-		msg->len | ((i2c->nmsgs == 1) ? XIIC_TX_DYN_STOP_MASK : 0));
-	local_irq_restore(flags);
+		dev_dbg(i2c->adap.dev.parent, "%s end, ISR: 0x%x, CR: 0x%x\n",
+			__func__, xiic_getreg32(i2c, XIIC_IISR_OFFSET),
+			xiic_getreg8(i2c, XIIC_CR_REG_OFFSET));
+	}
 
 	if (i2c->nmsgs == 1)
 		/* very last, enable bus not busy as well */
@@ -557,10 +872,17 @@
 
 	/* the message is tx:ed */
 	i2c->tx_pos = msg->len;
+
+	/* Enable interrupts */
+	xiic_setreg32(i2c, XIIC_DGIER_OFFSET, XIIC_GINTR_ENABLE_MASK);
+
+	i2c->prev_msg_tx = false;
 }
 
 static void xiic_start_send(struct xiic_i2c *i2c)
 {
+	u8 cr = 0;
+	u16 data;
 	struct i2c_msg *msg = i2c->tx_msg;
 
 	xiic_irq_clr(i2c, XIIC_INTR_TX_ERROR_MASK);
@@ -571,22 +893,71 @@
 		__func__, xiic_getreg32(i2c, XIIC_IISR_OFFSET),
 		xiic_getreg8(i2c, XIIC_CR_REG_OFFSET));
 
-	if (!(msg->flags & I2C_M_NOSTART)) {
-		/* write the address */
-		u16 data = i2c_8bit_addr_from_msg(msg) |
-			XIIC_TX_DYN_START_MASK;
-		if ((i2c->nmsgs == 1) && msg->len == 0)
-			/* no data and last message -> add STOP */
-			data |= XIIC_TX_DYN_STOP_MASK;
+	if (i2c->dynamic) {
+		if (!(msg->flags & I2C_M_NOSTART)) {
+			/* write the address */
+			data = i2c_8bit_addr_from_msg(msg) |
+				XIIC_TX_DYN_START_MASK;
+
+			if (i2c->nmsgs == 1 && msg->len == 0)
+				/* no data and last message -> add STOP */
+				data |= XIIC_TX_DYN_STOP_MASK;
+
+			xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, data);
+		}
+
+		xiic_fill_tx_fifo(i2c);
+
+		/* Clear any pending Tx empty, Tx Error and then enable them */
+		xiic_irq_clr_en(i2c, (XIIC_INTR_TX_EMPTY_MASK |
+				      XIIC_INTR_TX_ERROR_MASK |
+				      XIIC_INTR_BNB_MASK));
+	} else {
+		/*
+		 * If previous message is Tx, make sure that Tx FIFO is empty
+		 * before starting a new transfer as the repeated start in
+		 * standard mode can corrupt the transaction if there are
+		 * still bytes to be transmitted in FIFO
+		 */
+		if (i2c->prev_msg_tx) {
+			int status;
+
+			status = xiic_wait_tx_empty(i2c);
+			if (status)
+				return;
+		}
+
+		/* Check if RSTA should be set */
+		cr = xiic_getreg8(i2c, XIIC_CR_REG_OFFSET);
+		if (cr & XIIC_CR_MSMS_MASK) {
+			/* Already a master, RSTA should be set */
+			xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, (cr |
+				     XIIC_CR_REPEATED_START_MASK |
+				     XIIC_CR_DIR_IS_TX_MASK) &
+				     ~(XIIC_CR_NO_ACK_MASK));
+		}
 
+		/* Write address to FIFO */
+		data = i2c_8bit_addr_from_msg(msg);
 		xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, data);
-	}
+		/* Fill fifo */
+		xiic_std_fill_tx_fifo(i2c);
 
-	xiic_fill_tx_fifo(i2c);
+		if ((cr & XIIC_CR_MSMS_MASK) == 0) {
 
-	/* Clear any pending Tx empty, Tx Error and then enable them. */
-	xiic_irq_clr_en(i2c, XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_ERROR_MASK |
-		XIIC_INTR_BNB_MASK);
+			/* Start Tx by writing to CR */
+			cr = xiic_getreg8(i2c, XIIC_CR_REG_OFFSET);
+			xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, cr |
+				     XIIC_CR_MSMS_MASK |
+				     XIIC_CR_DIR_IS_TX_MASK);
+		}
+
+		/* Clear any pending Tx empty, Tx Error and then enable them */
+		xiic_irq_clr_en(i2c, XIIC_INTR_TX_EMPTY_MASK |
+				XIIC_INTR_TX_ERROR_MASK |
+				XIIC_INTR_BNB_MASK);
+	}
+	i2c->prev_msg_tx = true;
 }
 
 static irqreturn_t xiic_isr(int irq, void *dev_id)
@@ -613,6 +984,7 @@
 {
 	int first = 1;
 	int fifo_space = xiic_tx_fifo_space(i2c);
+
 	dev_dbg(i2c->adap.dev.parent, "%s entry, msg: %p, fifos space: %d\n",
 		__func__, i2c->tx_msg, fifo_space);
 
@@ -627,19 +999,20 @@
 			i2c->nmsgs--;
 			i2c->tx_msg++;
 			i2c->tx_pos = 0;
-		} else
+		} else {
 			first = 0;
+		}
 
 		if (i2c->tx_msg->flags & I2C_M_RD) {
 			/* we dont date putting several reads in the FIFO */
 			xiic_start_recv(i2c);
 			return;
-		} else {
-			xiic_start_send(i2c);
-			if (xiic_tx_space(i2c) != 0) {
-				/* the message could not be completely sent */
-				break;
-			}
+		}
+
+		xiic_start_send(i2c);
+		if (xiic_tx_space(i2c) != 0) {
+			/* the message could not be completely sent */
+			break;
 		}
 
 		fifo_space = xiic_tx_fifo_space(i2c);
@@ -650,21 +1023,27 @@
 	 */
 	if (i2c->nmsgs > 1 || xiic_tx_space(i2c))
 		xiic_irq_clr_en(i2c, XIIC_INTR_TX_HALF_MASK);
-
 }
 
-static void xiic_start_xfer(struct xiic_i2c *i2c)
+static int xiic_start_xfer(struct xiic_i2c *i2c)
 {
+	int ret;
+
 	mutex_lock(&i2c->lock);
-	xiic_reinit(i2c);
-	__xiic_start_xfer(i2c);
+
+	ret = xiic_reinit(i2c);
+	if (!ret)
+		__xiic_start_xfer(i2c);
+
 	mutex_unlock(&i2c->lock);
+
+	return ret;
 }
 
 static int xiic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
 {
 	struct xiic_i2c *i2c = i2c_get_adapdata(adap);
-	int err;
+	int err, count;
 
 	dev_dbg(adap->dev.parent, "%s entry SR: 0x%x\n", __func__,
 		xiic_getreg8(i2c, XIIC_SR_REG_OFFSET));
@@ -680,10 +1059,33 @@
 	i2c->tx_msg = msgs;
 	i2c->nmsgs = num;
 
-	xiic_start_xfer(i2c);
+	/* Decide standard mode or Dynamic mode */
+	i2c->dynamic = true;
 
-	if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) ||
-		(i2c->state == STATE_DONE), HZ)) {
+	/* Initialize prev message type */
+	i2c->prev_msg_tx = false;
+
+	/*
+	 * Enter standard mode only when read length is > 255 bytes or
+	 * for smbus_block_read transaction
+	 */
+	for (count = 0; count < i2c->nmsgs; count++) {
+		if (((i2c->tx_msg[count].flags & I2C_M_RD) &&
+		     i2c->tx_msg[count].len > MAX_READ_LENGTH_DYNAMIC) ||
+		    (i2c->tx_msg[count].flags & I2C_M_RECV_LEN)) {
+			i2c->dynamic = false;
+			break;
+		}
+	}
+
+	err = xiic_start_xfer(i2c);
+	if (err < 0) {
+		dev_err(adap->dev.parent, "Error xiic_start_xfer\n");
+		goto out;
+	}
+
+	if (wait_event_timeout(i2c->wait, i2c->state == STATE_ERROR ||
+			       i2c->state == STATE_DONE, HZ)) {
 		err = (i2c->state == STATE_DONE) ? num : -EIO;
 		goto out;
 	} else {
@@ -701,7 +1103,7 @@
 
 static u32 xiic_func(struct i2c_adapter *adap)
 {
-	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_BLOCK_DATA;
 }
 
 static const struct i2c_algorithm xiic_algorithm = {
@@ -709,19 +1111,12 @@
 	.functionality = xiic_func,
 };
 
-static const struct i2c_adapter_quirks xiic_quirks = {
-	.max_read_len = 255,
-};
-
 static const struct i2c_adapter xiic_adapter = {
 	.owner = THIS_MODULE,
-	.name = DRIVER_NAME,
 	.class = I2C_CLASS_DEPRECATED,
 	.algo = &xiic_algorithm,
-	.quirks = &xiic_quirks,
 };
 
-
 static int xiic_i2c_probe(struct platform_device *pdev)
 {
 	struct xiic_i2c *i2c;
@@ -752,13 +1147,16 @@
 	i2c_set_adapdata(&i2c->adap, i2c);
 	i2c->adap.dev.parent = &pdev->dev;
 	i2c->adap.dev.of_node = pdev->dev.of_node;
+	snprintf(i2c->adap.name, sizeof(i2c->adap.name),
+		 DRIVER_NAME " %s", pdev->name);
 
 	mutex_init(&i2c->lock);
 	init_waitqueue_head(&i2c->wait);
 
 	i2c->clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(i2c->clk)) {
-		dev_err(&pdev->dev, "input clock not found.\n");
+		if (PTR_ERR(i2c->clk) != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "input clock not found.\n");
 		return PTR_ERR(i2c->clk);
 	}
 	ret = clk_prepare_enable(i2c->clk);
@@ -767,10 +1165,10 @@
 		return ret;
 	}
 	i2c->dev = &pdev->dev;
-	pm_runtime_enable(i2c->dev);
 	pm_runtime_set_autosuspend_delay(i2c->dev, XIIC_PM_TIMEOUT);
 	pm_runtime_use_autosuspend(i2c->dev);
 	pm_runtime_set_active(i2c->dev);
+	pm_runtime_enable(i2c->dev);
 	ret = devm_request_threaded_irq(&pdev->dev, irq, xiic_isr,
 					xiic_process, IRQF_ONESHOT,
 					pdev->name, i2c);
@@ -792,7 +1190,11 @@
 	if (!(sr & XIIC_SR_TX_FIFO_EMPTY_MASK))
 		i2c->endianness = BIG;
 
-	xiic_reinit(i2c);
+	ret = xiic_reinit(i2c);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Cannot xiic_reinit\n");
+		goto err_clk_dis;
+	}
 
 	/* add i2c adapter to i2c tree */
 	ret = i2c_add_adapter(&i2c->adap);
@@ -824,14 +1226,16 @@
 	/* remove adapter & data */
 	i2c_del_adapter(&i2c->adap);
 
-	ret = clk_prepare_enable(i2c->clk);
-	if (ret) {
-		dev_err(&pdev->dev, "Unable to enable clock.\n");
+	ret = pm_runtime_get_sync(i2c->dev);
+	if (ret < 0)
 		return ret;
-	}
+
 	xiic_deinit(i2c);
+	pm_runtime_put_sync(i2c->dev);
 	clk_disable_unprepare(i2c->clk);
 	pm_runtime_disable(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
+	pm_runtime_dont_use_autosuspend(&pdev->dev);
 
 	return 0;
 }
@@ -871,6 +1275,7 @@
 	SET_RUNTIME_PM_OPS(xiic_i2c_runtime_suspend,
 			   xiic_i2c_runtime_resume, NULL)
 };
+
 static struct platform_driver xiic_i2c_driver = {
 	.probe   = xiic_i2c_probe,
 	.remove  = xiic_i2c_remove,
@@ -883,7 +1288,7 @@
 
 module_platform_driver(xiic_i2c_driver);
 
+MODULE_ALIAS("platform:" DRIVER_NAME);
 MODULE_AUTHOR("info@mocean-labs.com");
 MODULE_DESCRIPTION("Xilinx I2C bus driver");
 MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:"DRIVER_NAME);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/busses/i2c-xlr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/busses/i2c-xlr.c
@@ -433,11 +433,15 @@
 	i2c_set_adapdata(&priv->adap, priv);
 	ret = i2c_add_numbered_adapter(&priv->adap);
 	if (ret < 0)
-		return ret;
+		goto err_unprepare_clk;
 
 	platform_set_drvdata(pdev, priv);
 	dev_info(&priv->adap.dev, "Added I2C Bus.\n");
 	return 0;
+
+err_unprepare_clk:
+	clk_unprepare(clk);
+	return ret;
 }
 
 static int xlr_i2c_remove(struct platform_device *pdev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/i2c-core-acpi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/i2c-core-acpi.c
@@ -264,6 +264,7 @@
 void i2c_acpi_register_devices(struct i2c_adapter *adap)
 {
 	acpi_status status;
+	acpi_handle handle;
 
 	if (!has_acpi_companion(&adap->dev))
 		return;
@@ -274,6 +275,15 @@
 				     adap, NULL);
 	if (ACPI_FAILURE(status))
 		dev_warn(&adap->dev, "failed to enumerate I2C slaves\n");
+
+	if (!adap->dev.parent)
+		return;
+
+	handle = ACPI_HANDLE(adap->dev.parent);
+	if (!handle)
+		return;
+
+	acpi_walk_dep_device_list(handle);
 }
 
 const struct acpi_device_id *
@@ -394,9 +404,17 @@
 static struct i2c_client *i2c_acpi_find_client_by_adev(struct acpi_device *adev)
 {
 	struct device *dev;
+	struct i2c_client *client;
 
 	dev = bus_find_device_by_acpi_dev(&i2c_bus_type, adev);
-	return dev ? i2c_verify_client(dev) : NULL;
+	if (!dev)
+		return NULL;
+
+	client = i2c_verify_client(dev);
+	if (!client)
+		put_device(dev);
+
+	return client;
 }
 
 static int i2c_acpi_notify(struct notifier_block *nb, unsigned long value,
@@ -418,6 +436,7 @@
 			break;
 
 		i2c_acpi_register_device(adapter, adev, &info);
+		put_device(&adapter->dev);
 		break;
 	case ACPI_RECONFIG_DEVICE_REMOVE:
 		if (!acpi_device_enumerated(adev))
@@ -729,7 +748,6 @@
 		return -ENOMEM;
 	}
 
-	acpi_walk_dep_device_list(handle);
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/i2c-core-base.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/i2c-core-base.c
@@ -24,6 +24,7 @@
 #include <linux/i2c-smbus.h>
 #include <linux/idr.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/irqflags.h>
 #include <linux/jump_label.h>
 #include <linux/kernel.h>
@@ -186,10 +187,11 @@
 	 * If we can set SDA, we will always create a STOP to ensure additional
 	 * pulses will do no harm. This is achieved by letting SDA follow SCL
 	 * half a cycle later. Check the 'incomplete_write_byte' fault injector
-	 * for details.
+	 * for details. Note that we must honour tsu:sto, 4us, but lets use 5us
+	 * here for simplicity.
 	 */
 	bri->set_scl(adap, scl);
-	ndelay(RECOVERY_NDELAY / 2);
+	ndelay(RECOVERY_NDELAY);
 	if (bri->set_sda)
 		bri->set_sda(adap, scl);
 	ndelay(RECOVERY_NDELAY / 2);
@@ -211,7 +213,13 @@
 		scl = !scl;
 		bri->set_scl(adap, scl);
 		/* Creating STOP again, see above */
-		ndelay(RECOVERY_NDELAY / 2);
+		if (scl)  {
+			/* Honour minimum tsu:sto */
+			ndelay(RECOVERY_NDELAY);
+		} else {
+			/* Honour minimum tf and thd:dat */
+			ndelay(RECOVERY_NDELAY / 2);
+		}
 		if (bri->set_sda)
 			bri->set_sda(adap, scl);
 		ndelay(RECOVERY_NDELAY / 2);
@@ -247,13 +255,14 @@
 static void i2c_init_recovery(struct i2c_adapter *adap)
 {
 	struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
-	char *err_str;
+	char *err_str, *err_level = KERN_ERR;
 
 	if (!bri)
 		return;
 
 	if (!bri->recover_bus) {
-		err_str = "no recover_bus() found";
+		err_str = "no suitable method provided";
+		err_level = KERN_DEBUG;
 		goto err;
 	}
 
@@ -283,7 +292,7 @@
 
 	return;
  err:
-	dev_err(&adap->dev, "Not using recovery: %s\n", err_str);
+	dev_printk(err_level, &adap->dev, "Not using recovery: %s\n", err_str);
 	adap->bus_recovery_info = NULL;
 }
 
@@ -331,8 +340,10 @@
 		} else if (ACPI_COMPANION(dev)) {
 			irq = i2c_acpi_get_irq(client);
 		}
-		if (irq == -EPROBE_DEFER)
-			return irq;
+		if (irq == -EPROBE_DEFER) {
+			status = irq;
+			goto put_sync_adapter;
+		}
 
 		if (irq < 0)
 			irq = 0;
@@ -345,16 +356,20 @@
 	 * or ACPI ID table is supplied for the probing device.
 	 */
 	if (!driver->id_table &&
-	    !i2c_acpi_match_device(dev->driver->acpi_match_table, client) &&
-	    !i2c_of_match_device(dev->driver->of_match_table, client))
-		return -ENODEV;
+	    !acpi_driver_match_device(dev, dev->driver) &&
+	    !i2c_of_match_device(dev->driver->of_match_table, client)) {
+		status = -ENODEV;
+		goto put_sync_adapter;
+	}
 
 	if (client->flags & I2C_CLIENT_WAKE) {
 		int wakeirq;
 
 		wakeirq = of_irq_get_byname(dev->of_node, "wakeup");
-		if (wakeirq == -EPROBE_DEFER)
-			return wakeirq;
+		if (wakeirq == -EPROBE_DEFER) {
+			status = wakeirq;
+			goto put_sync_adapter;
+		}
 
 		device_init_wakeup(&client->dev, true);
 
@@ -401,6 +416,10 @@
 err_clear_wakeup_irq:
 	dev_pm_clear_wake_irq(&client->dev);
 	device_init_wakeup(&client->dev, false);
+put_sync_adapter:
+	if (client->flags & I2C_CLIENT_HOST_NOTIFY)
+		pm_runtime_put_sync(&client->adapter->dev);
+
 	return status;
 }
 
@@ -441,6 +460,8 @@
 	driver = to_i2c_driver(dev->driver);
 	if (driver->shutdown)
 		driver->shutdown(client);
+	else if (client->irq > 0)
+		disable_irq(client->irq);
 }
 
 static void i2c_client_dev_release(struct device *dev)
@@ -1368,8 +1389,8 @@
 
 	/* create pre-declared device nodes */
 	of_i2c_register_devices(adap);
-	i2c_acpi_register_devices(adap);
 	i2c_acpi_install_space_handler(adap);
+	i2c_acpi_register_devices(adap);
 
 	if (adap->nr < __i2c_first_dynamic_bus_num)
 		i2c_scan_static_board_info(adap);
@@ -1944,13 +1965,18 @@
  * Returns negative errno, else the number of messages executed.
  *
  * Adapter lock must be held when calling this function. No debug logging
- * takes place. adap->algo->master_xfer existence isn't checked.
+ * takes place.
  */
 int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
 {
 	unsigned long orig_jiffies;
 	int ret, try;
 
+	if (!adap->algo->master_xfer) {
+		dev_dbg(&adap->dev, "I2C level transfers not supported\n");
+		return -EOPNOTSUPP;
+	}
+
 	if (WARN_ON(!msgs || num < 1))
 		return -EINVAL;
 
@@ -2017,11 +2043,6 @@
 {
 	int ret;
 
-	if (!adap->algo->master_xfer) {
-		dev_dbg(&adap->dev, "I2C level transfers not supported\n");
-		return -EOPNOTSUPP;
-	}
-
 	/* REVISIT the fault reporting model here is weak:
 	 *
 	 *  - When we get an error after receiving N bytes from a slave,
@@ -2337,8 +2358,9 @@
 	if (!adap)
 		return;
 
-	put_device(&adap->dev);
 	module_put(adap->owner);
+	/* Should be last, otherwise we risk use-after-free with 'adap' */
+	put_device(&adap->dev);
 }
 EXPORT_SYMBOL(i2c_put_adapter);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/i2c-core-slave.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/i2c-core-slave.c
@@ -18,10 +18,8 @@
 {
 	int ret;
 
-	if (!client || !slave_cb) {
-		WARN(1, "insufficient data\n");
+	if (WARN(IS_ERR_OR_NULL(client) || !slave_cb, "insufficient data\n"))
 		return -EINVAL;
-	}
 
 	if (!(client->flags & I2C_CLIENT_SLAVE))
 		dev_warn(&client->dev, "%s: client slave flag not set. You might see address collisions\n",
@@ -60,6 +58,9 @@
 {
 	int ret;
 
+	if (IS_ERR_OR_NULL(client))
+		return -EINVAL;
+
 	if (!client->adapter->algo->unreg_slave) {
 		dev_err(&client->dev, "%s: not supported by adapter\n", __func__);
 		return -EOPNOTSUPP;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/i2c-core-smbus.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/i2c-core-smbus.c
@@ -495,6 +495,13 @@
 			break;
 		case I2C_SMBUS_BLOCK_DATA:
 		case I2C_SMBUS_BLOCK_PROC_CALL:
+			if (msg[1].buf[0] > I2C_SMBUS_BLOCK_MAX) {
+				dev_err(&adapter->dev,
+					"Invalid block size returned: %d\n",
+					msg[1].buf[0]);
+				status = -EPROTO;
+				goto cleanup;
+			}
 			for (i = 0; i < msg[1].buf[0] + 1; i++)
 				data->block[i] = msg[1].buf[i];
 			break;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/i2c-core.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/i2c-core.h
@@ -3,6 +3,7 @@
  * i2c-core.h - interfaces internal to the I2C framework
  */
 
+#include <linux/kconfig.h>
 #include <linux/rwsem.h>
 
 struct i2c_devinfo {
@@ -29,7 +30,8 @@
  */
 static inline bool i2c_in_atomic_xfer_mode(void)
 {
-	return system_state > SYSTEM_RUNNING && irqs_disabled();
+	return system_state > SYSTEM_RUNNING &&
+	       (IS_ENABLED(CONFIG_PREEMPT_COUNT) ? !preemptible() : irqs_disabled());
 }
 
 static inline int __i2c_lock_bus_helper(struct i2c_adapter *adap)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/i2c-dev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/i2c-dev.c
@@ -40,7 +40,7 @@
 struct i2c_dev {
 	struct list_head list;
 	struct i2c_adapter *adap;
-	struct device *dev;
+	struct device dev;
 	struct cdev cdev;
 };
 
@@ -84,12 +84,14 @@
 	return i2c_dev;
 }
 
-static void put_i2c_dev(struct i2c_dev *i2c_dev)
+static void put_i2c_dev(struct i2c_dev *i2c_dev, bool del_cdev)
 {
 	spin_lock(&i2c_dev_list_lock);
 	list_del(&i2c_dev->list);
 	spin_unlock(&i2c_dev_list_lock);
-	kfree(i2c_dev);
+	if (del_cdev)
+		cdev_device_del(&i2c_dev->cdev, &i2c_dev->dev);
+	put_device(&i2c_dev->dev);
 }
 
 static ssize_t name_show(struct device *dev,
@@ -139,7 +141,7 @@
 	if (count > 8192)
 		count = 8192;
 
-	tmp = kmalloc(count, GFP_KERNEL);
+	tmp = kzalloc(count, GFP_KERNEL);
 	if (tmp == NULL)
 		return -ENOMEM;
 
@@ -148,7 +150,8 @@
 
 	ret = i2c_master_recv(client, tmp, count);
 	if (ret >= 0)
-		ret = copy_to_user(buf, tmp, count) ? -EFAULT : ret;
+		if (copy_to_user(buf, tmp, ret))
+			ret = -EFAULT;
 	kfree(tmp);
 	return ret;
 }
@@ -438,8 +441,13 @@
 				   sizeof(rdwr_arg)))
 			return -EFAULT;
 
-		/* Put an arbitrary limit on the number of messages that can
-		 * be sent at once */
+		if (!rdwr_arg.msgs || rdwr_arg.nmsgs == 0)
+			return -EINVAL;
+
+		/*
+		 * Put an arbitrary limit on the number of messages that can
+		 * be sent at once
+		 */
 		if (rdwr_arg.nmsgs > I2C_RDWR_IOCTL_MAX_MSGS)
 			return -EINVAL;
 
@@ -528,6 +536,9 @@
 				   sizeof(rdwr_arg)))
 			return -EFAULT;
 
+		if (!rdwr_arg.msgs || rdwr_arg.nmsgs == 0)
+			return -EINVAL;
+
 		if (rdwr_arg.nmsgs > I2C_RDWR_IOCTL_MAX_MSGS)
 			return -EINVAL;
 
@@ -628,6 +639,14 @@
 
 static struct class *i2c_dev_class;
 
+static void i2cdev_dev_release(struct device *dev)
+{
+	struct i2c_dev *i2c_dev;
+
+	i2c_dev = container_of(dev, struct i2c_dev, dev);
+	kfree(i2c_dev);
+}
+
 static int i2cdev_attach_adapter(struct device *dev, void *dummy)
 {
 	struct i2c_adapter *adap;
@@ -644,26 +663,27 @@
 
 	cdev_init(&i2c_dev->cdev, &i2cdev_fops);
 	i2c_dev->cdev.owner = THIS_MODULE;
-	res = cdev_add(&i2c_dev->cdev, MKDEV(I2C_MAJOR, adap->nr), 1);
+
+	device_initialize(&i2c_dev->dev);
+	i2c_dev->dev.devt = MKDEV(I2C_MAJOR, adap->nr);
+	i2c_dev->dev.class = i2c_dev_class;
+	i2c_dev->dev.parent = &adap->dev;
+	i2c_dev->dev.release = i2cdev_dev_release;
+
+	res = dev_set_name(&i2c_dev->dev, "i2c-%d", adap->nr);
 	if (res)
-		goto error_cdev;
+		goto err_put_i2c_dev;
 
-	/* register this i2c device with the driver core */
-	i2c_dev->dev = device_create(i2c_dev_class, &adap->dev,
-				     MKDEV(I2C_MAJOR, adap->nr), NULL,
-				     "i2c-%d", adap->nr);
-	if (IS_ERR(i2c_dev->dev)) {
-		res = PTR_ERR(i2c_dev->dev);
-		goto error;
-	}
+	res = cdev_device_add(&i2c_dev->cdev, &i2c_dev->dev);
+	if (res)
+		goto err_put_i2c_dev;
 
 	pr_debug("i2c-dev: adapter [%s] registered as minor %d\n",
 		 adap->name, adap->nr);
 	return 0;
-error:
-	cdev_del(&i2c_dev->cdev);
-error_cdev:
-	put_i2c_dev(i2c_dev);
+
+err_put_i2c_dev:
+	put_i2c_dev(i2c_dev, false);
 	return res;
 }
 
@@ -680,9 +700,7 @@
 	if (!i2c_dev) /* attach_adapter must have failed */
 		return 0;
 
-	cdev_del(&i2c_dev->cdev);
-	put_i2c_dev(i2c_dev);
-	device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
+	put_i2c_dev(i2c_dev, true);
 
 	pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name);
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/i2c-mux.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/i2c-mux.c
@@ -340,7 +340,7 @@
 		priv->adap.lock_ops = &i2c_parent_lock_ops;
 
 	/* Sanity check on class */
-	if (i2c_mux_parent_classes(parent) & class)
+	if (i2c_mux_parent_classes(parent) & class & ~I2C_CLASS_DEPRECATED)
 		dev_err(&parent->dev,
 			"Segment %d behind mux can't share classes with ancestors\n",
 			chan_id);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/i2c-smbus.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/i2c-smbus.c
@@ -33,6 +33,7 @@
 	struct i2c_client *client = i2c_verify_client(dev);
 	struct alert_data *data = addrp;
 	struct i2c_driver *driver;
+	int ret;
 
 	if (!client || client->addr != data->addr)
 		return 0;
@@ -46,16 +47,47 @@
 	device_lock(dev);
 	if (client->dev.driver) {
 		driver = to_i2c_driver(client->dev.driver);
-		if (driver->alert)
+		if (driver->alert) {
+			/* Stop iterating after we find the device */
 			driver->alert(client, data->type, data->data);
-		else
+			ret = -EBUSY;
+		} else {
 			dev_warn(&client->dev, "no driver alert()!\n");
-	} else
+			ret = -EOPNOTSUPP;
+		}
+	} else {
 		dev_dbg(&client->dev, "alert with no driver\n");
+		ret = -ENODEV;
+	}
+	device_unlock(dev);
+
+	return ret;
+}
+
+/* Same as above, but call back all drivers with alert handler */
+
+static int smbus_do_alert_force(struct device *dev, void *addrp)
+{
+	struct i2c_client *client = i2c_verify_client(dev);
+	struct alert_data *data = addrp;
+	struct i2c_driver *driver;
+
+	if (!client || (client->flags & I2C_CLIENT_TEN))
+		return 0;
+
+	/*
+	 * Drivers should either disable alerts, or provide at least
+	 * a minimal handler. Lock so the driver won't change.
+	 */
+	device_lock(dev);
+	if (client->dev.driver) {
+		driver = to_i2c_driver(client->dev.driver);
+		if (driver->alert)
+			driver->alert(client, data->type, data->data);
+	}
 	device_unlock(dev);
 
-	/* Stop iterating after we find the device */
-	return -EBUSY;
+	return 0;
 }
 
 /*
@@ -66,7 +98,7 @@
 {
 	struct i2c_smbus_alert *alert = d;
 	struct i2c_client *ara;
-	unsigned short prev_addr = 0;	/* Not a valid address */
+	unsigned short prev_addr = I2C_CLIENT_END; /* Not a valid address */
 
 	ara = alert->ara;
 
@@ -90,17 +122,28 @@
 		data.addr = status >> 1;
 		data.type = I2C_PROTOCOL_SMBUS_ALERT;
 
-		if (data.addr == prev_addr) {
-			dev_warn(&ara->dev, "Duplicate SMBALERT# from dev "
-				"0x%02x, skipping\n", data.addr);
-			break;
-		}
 		dev_dbg(&ara->dev, "SMBALERT# from dev 0x%02x, flag %d\n",
 			data.addr, data.data);
 
 		/* Notify driver for the device which issued the alert */
-		device_for_each_child(&ara->adapter->dev, &data,
-				      smbus_do_alert);
+		status = device_for_each_child(&ara->adapter->dev, &data,
+					       smbus_do_alert);
+		/*
+		 * If we read the same address more than once, and the alert
+		 * was not handled by a driver, it won't do any good to repeat
+		 * the loop because it will never terminate. Try again, this
+		 * time calling the alert handlers of all devices connected to
+		 * the bus, and abort the loop afterwards. If this helps, we
+		 * are all set. If it doesn't, there is nothing else we can do,
+		 * so we might as well abort the loop.
+		 * Note: This assumes that a driver with alert handler handles
+		 * the alert properly and clears it if necessary.
+		 */
+		if (data.addr == prev_addr && status != -EBUSY) {
+			device_for_each_child(&ara->adapter->dev, &data,
+					      smbus_do_alert_force);
+			break;
+		}
 		prev_addr = data.addr;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/muxes/i2c-demux-pinctrl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/muxes/i2c-demux-pinctrl.c
@@ -61,7 +61,7 @@
 	if (ret)
 		goto err;
 
-	adap = of_find_i2c_adapter_by_node(priv->chan[new_chan].parent_np);
+	adap = of_get_i2c_adapter_by_node(priv->chan[new_chan].parent_np);
 	if (!adap) {
 		ret = -ENODEV;
 		goto err_with_revert;
@@ -243,6 +243,10 @@
 
 		props[i].name = devm_kstrdup(&pdev->dev, "status", GFP_KERNEL);
 		props[i].value = devm_kstrdup(&pdev->dev, "ok", GFP_KERNEL);
+		if (!props[i].name || !props[i].value) {
+			err = -ENOMEM;
+			goto err_rollback;
+		}
 		props[i].length = 3;
 
 		of_changeset_init(&priv->chan[i].chgset);
@@ -257,11 +261,13 @@
 	pm_runtime_no_callbacks(&pdev->dev);
 
 	/* switch to first parent as active master */
-	i2c_demux_activate_master(priv, 0);
+	err = i2c_demux_activate_master(priv, 0);
+	if (err)
+		goto err_rollback;
 
 	err = device_create_file(&pdev->dev, &dev_attr_available_masters);
 	if (err)
-		goto err_rollback;
+		goto err_rollback_activation;
 
 	err = device_create_file(&pdev->dev, &dev_attr_current_master);
 	if (err)
@@ -271,6 +277,8 @@
 
 err_rollback_available:
 	device_remove_file(&pdev->dev, &dev_attr_available_masters);
+err_rollback_activation:
+	i2c_demux_deactivate_master(priv);
 err_rollback:
 	for (j = 0; j < i; j++) {
 		of_node_put(priv->chan[j].parent_np);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/muxes/i2c-mux-gpmux.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/muxes/i2c-mux-gpmux.c
@@ -52,7 +52,7 @@
 		dev_err(dev, "Cannot parse i2c-parent\n");
 		return ERR_PTR(-ENODEV);
 	}
-	parent = of_find_i2c_adapter_by_node(parent_np);
+	parent = of_get_i2c_adapter_by_node(parent_np);
 	of_node_put(parent_np);
 	if (!parent)
 		return ERR_PTR(-EPROBE_DEFER);
@@ -138,6 +138,7 @@
 	return 0;
 
 err_children:
+	of_node_put(child);
 	i2c_mux_del_adapters(muxc);
 err_parent:
 	i2c_put_adapter(parent);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/muxes/i2c-mux-pca954x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/muxes/i2c-mux-pca954x.c
@@ -243,11 +243,8 @@
 	else
 		regval = 1 << chan;
 
-	/* Only select the channel if its different from the last channel */
-	if (data->last_chan != regval) {
-		ret = pca954x_reg_write(muxc->parent, client, regval);
-		data->last_chan = ret < 0 ? 0 : regval;
-	}
+	ret = pca954x_reg_write(muxc->parent, client, regval);
+	data->last_chan = ret < 0 ? 0 : regval;
 
 	return ret;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i2c/muxes/i2c-mux-pinctrl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i2c/muxes/i2c-mux-pinctrl.c
@@ -62,7 +62,7 @@
 		dev_err(dev, "Cannot parse i2c-parent\n");
 		return ERR_PTR(-ENODEV);
 	}
-	parent = of_find_i2c_adapter_by_node(parent_np);
+	parent = of_get_i2c_adapter_by_node(parent_np);
 	of_node_put(parent_np);
 	if (!parent)
 		return ERR_PTR(-EPROBE_DEFER);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i3c/master.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i3c/master.c
@@ -257,7 +257,8 @@
 	struct i3c_device_info devinfo;
 	u16 manuf, part, ext;
 
-	i3c_device_get_info(i3cdev, &devinfo);
+	if (i3cdev->desc)
+		devinfo = i3cdev->desc->info;
 	manuf = I3C_PID_MANUF_ID(devinfo.pid);
 	part = I3C_PID_PART_ID(devinfo.pid);
 	ext = I3C_PID_EXTRA_INFO(devinfo.pid);
@@ -1263,7 +1264,7 @@
 					     I3C_ADDR_SLOT_FREE);
 
 	if (dev->boardinfo && dev->boardinfo->init_dyn_addr)
-		i3c_bus_set_addr_slot_status(&master->bus, dev->info.dyn_addr,
+		i3c_bus_set_addr_slot_status(&master->bus, dev->boardinfo->init_dyn_addr,
 					     I3C_ADDR_SLOT_FREE);
 }
 
@@ -1469,9 +1470,11 @@
 			desc->dev->dev.of_node = desc->boardinfo->of_node;
 
 		ret = device_register(&desc->dev->dev);
-		if (ret)
+		if (ret) {
 			dev_err(&master->dev,
 				"Failed to add I3C device (err = %d)\n", ret);
+			put_device(&desc->dev->dev);
+		}
 	}
 }
 
@@ -1760,6 +1763,21 @@
 	i3c_master_detach_free_devs(master);
 }
 
+static void i3c_master_attach_boardinfo(struct i3c_dev_desc *i3cdev)
+{
+	struct i3c_master_controller *master = i3cdev->common.master;
+	struct i3c_dev_boardinfo *i3cboardinfo;
+
+	list_for_each_entry(i3cboardinfo, &master->boardinfo.i3c, node) {
+		if (i3cdev->info.pid != i3cboardinfo->pid)
+			continue;
+
+		i3cdev->boardinfo = i3cboardinfo;
+		i3cdev->info.static_addr = i3cboardinfo->static_addr;
+		return;
+	}
+}
+
 static struct i3c_dev_desc *
 i3c_master_search_i3c_dev_duplicate(struct i3c_dev_desc *refdev)
 {
@@ -1815,10 +1833,10 @@
 	if (ret)
 		goto err_detach_dev;
 
+	i3c_master_attach_boardinfo(newdev);
+
 	olddev = i3c_master_search_i3c_dev_duplicate(newdev);
 	if (olddev) {
-		newdev->boardinfo = olddev->boardinfo;
-		newdev->info.static_addr = olddev->info.static_addr;
 		newdev->dev = olddev->dev;
 		if (newdev->dev)
 			newdev->dev->desc = newdev;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/i3c/master/i3c-master-cdns.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/i3c/master/i3c-master-cdns.c
@@ -74,7 +74,8 @@
 #define PRESCL_CTRL0			0x14
 #define PRESCL_CTRL0_I2C(x)		((x) << 16)
 #define PRESCL_CTRL0_I3C(x)		(x)
-#define PRESCL_CTRL0_MAX		GENMASK(9, 0)
+#define PRESCL_CTRL0_I3C_MAX		GENMASK(9, 0)
+#define PRESCL_CTRL0_I2C_MAX		GENMASK(15, 0)
 
 #define PRESCL_CTRL1			0x18
 #define PRESCL_CTRL1_PP_LOW_MASK	GENMASK(15, 8)
@@ -189,7 +190,7 @@
 #define SLV_STATUS1_HJ_DIS		BIT(18)
 #define SLV_STATUS1_MR_DIS		BIT(17)
 #define SLV_STATUS1_PROT_ERR		BIT(16)
-#define SLV_STATUS1_DA(x)		(((s) & GENMASK(15, 9)) >> 9)
+#define SLV_STATUS1_DA(s)		(((s) & GENMASK(15, 9)) >> 9)
 #define SLV_STATUS1_HAS_DA		BIT(8)
 #define SLV_STATUS1_DDR_RX_FULL		BIT(7)
 #define SLV_STATUS1_DDR_TX_FULL		BIT(6)
@@ -1212,7 +1213,7 @@
 		return -EINVAL;
 
 	pres = DIV_ROUND_UP(sysclk_rate, (bus->scl_rate.i3c * 4)) - 1;
-	if (pres > PRESCL_CTRL0_MAX)
+	if (pres > PRESCL_CTRL0_I3C_MAX)
 		return -ERANGE;
 
 	bus->scl_rate.i3c = sysclk_rate / ((pres + 1) * 4);
@@ -1225,7 +1226,7 @@
 	max_i2cfreq = bus->scl_rate.i2c;
 
 	pres = (sysclk_rate / (max_i2cfreq * 5)) - 1;
-	if (pres > PRESCL_CTRL0_MAX)
+	if (pres > PRESCL_CTRL0_I2C_MAX)
 		return -ERANGE;
 
 	bus->scl_rate.i2c = sysclk_rate / ((pres + 1) * 5);
@@ -1580,21 +1581,23 @@
 	/* Device ID0 is reserved to describe this master. */
 	master->maxdevs = CONF_STATUS0_DEVS_NUM(val);
 	master->free_rr_slots = GENMASK(master->maxdevs, 1);
+	master->caps.ibirfifodepth = CONF_STATUS0_IBIR_DEPTH(val);
+	master->caps.cmdrfifodepth = CONF_STATUS0_CMDR_DEPTH(val);
 
 	val = readl(master->regs + CONF_STATUS1);
 	master->caps.cmdfifodepth = CONF_STATUS1_CMD_DEPTH(val);
 	master->caps.rxfifodepth = CONF_STATUS1_RX_DEPTH(val);
 	master->caps.txfifodepth = CONF_STATUS1_TX_DEPTH(val);
-	master->caps.ibirfifodepth = CONF_STATUS0_IBIR_DEPTH(val);
-	master->caps.cmdrfifodepth = CONF_STATUS0_CMDR_DEPTH(val);
 
 	spin_lock_init(&master->ibi.lock);
 	master->ibi.num_slots = CONF_STATUS1_IBI_HW_RES(val);
 	master->ibi.slots = devm_kcalloc(&pdev->dev, master->ibi.num_slots,
 					 sizeof(*master->ibi.slots),
 					 GFP_KERNEL);
-	if (!master->ibi.slots)
+	if (!master->ibi.slots) {
+		ret = -ENOMEM;
 		goto err_disable_sysclk;
+	}
 
 	writel(IBIR_THR(1), master->regs + CMD_IBI_THR_CTRL);
 	writel(MST_INT_IBIR_THR, master->regs + MST_IER);
@@ -1621,6 +1624,7 @@
 	struct cdns_i3c_master *master = platform_get_drvdata(pdev);
 	int ret;
 
+	cancel_work_sync(&master->hj_work);
 	ret = i3c_master_unregister(&master->base);
 	if (ret)
 		return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ide/cmd64x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ide/cmd64x.c
@@ -66,6 +66,9 @@
 	struct ide_timing t;
 	u8 arttim = 0;
 
+	if (drive->dn >= ARRAY_SIZE(drwtim_regs))
+		return;
+
 	ide_timing_compute(drive, mode, &t, T, 0);
 
 	/*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ide/ide-acpi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ide/ide-acpi.c
@@ -180,7 +180,7 @@
 static acpi_handle ide_acpi_hwif_get_handle(ide_hwif_t *hwif)
 {
 	struct device		*dev = hwif->gendev.parent;
-	acpi_handle		uninitialized_var(dev_handle);
+	acpi_handle		dev_handle;
 	u64			pcidevfn;
 	acpi_handle		chan_handle;
 	int			err;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ide/ide-atapi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ide/ide-atapi.c
@@ -223,7 +223,6 @@
 	sense_rq->rq_disk = rq->rq_disk;
 	sense_rq->cmd_flags = REQ_OP_DRV_IN;
 	ide_req(sense_rq)->type = ATA_PRIV_SENSE;
-	sense_rq->rq_flags |= RQF_PREEMPT;
 
 	req->cmd[0] = GPCMD_REQUEST_SENSE;
 	req->cmd[4] = cmd_len;
@@ -609,7 +608,7 @@
 
 static ide_startstop_t ide_transfer_pc(ide_drive_t *drive)
 {
-	struct ide_atapi_pc *uninitialized_var(pc);
+	struct ide_atapi_pc *pc;
 	ide_hwif_t *hwif = drive->hwif;
 	struct request *rq = hwif->rq;
 	ide_expiry_t *expiry;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ide/ide-io-std.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ide/ide-io-std.c
@@ -173,7 +173,7 @@
 	u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
 
 	if (io_32bit) {
-		unsigned long uninitialized_var(flags);
+		unsigned long flags;
 
 		if ((io_32bit & 2) && !mmio) {
 			local_irq_save(flags);
@@ -217,7 +217,7 @@
 	u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
 
 	if (io_32bit) {
-		unsigned long uninitialized_var(flags);
+		unsigned long flags;
 
 		if ((io_32bit & 2) && !mmio) {
 			local_irq_save(flags);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ide/ide-io.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ide/ide-io.c
@@ -512,11 +512,6 @@
 		 * above to return us whatever is in the queue. Since we call
 		 * ide_do_request() ourselves, we end up taking requests while
 		 * the queue is blocked...
-		 * 
-		 * We let requests forced at head of queue with ide-preempt
-		 * though. I hope that doesn't happen too much, hopefully not
-		 * unless the subdriver triggers such a thing in its own PM
-		 * state machine.
 		 */
 		if ((drive->dev_flags & IDE_DFLAG_BLOCKED) &&
 		    ata_pm_request(rq) == 0 &&
@@ -619,12 +614,12 @@
 void ide_timer_expiry (struct timer_list *t)
 {
 	ide_hwif_t	*hwif = from_timer(hwif, t, timer);
-	ide_drive_t	*uninitialized_var(drive);
+	ide_drive_t	*drive;
 	ide_handler_t	*handler;
 	unsigned long	flags;
 	int		wait = -1;
 	int		plug_device = 0;
-	struct request	*uninitialized_var(rq_in_flight);
+	struct request	*rq_in_flight;
 
 	spin_lock_irqsave(&hwif->lock, flags);
 
@@ -777,13 +772,13 @@
 {
 	ide_hwif_t *hwif = (ide_hwif_t *)dev_id;
 	struct ide_host *host = hwif->host;
-	ide_drive_t *uninitialized_var(drive);
+	ide_drive_t *drive;
 	ide_handler_t *handler;
 	unsigned long flags;
 	ide_startstop_t startstop;
 	irqreturn_t irq_ret = IRQ_NONE;
 	int plug_device = 0;
-	struct request *uninitialized_var(rq_in_flight);
+	struct request *rq_in_flight;
 
 	if (host->host_flags & IDE_HFLAG_SERIALIZE) {
 		if (hwif != host->cur_port)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ide/ide-sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ide/ide-sysfs.c
@@ -131,7 +131,7 @@
 
 int ide_sysfs_register_port(ide_hwif_t *hwif)
 {
-	int i, uninitialized_var(rc);
+	int i, rc;
 
 	for (i = 0; ide_port_attrs[i]; i++) {
 		rc = device_create_file(hwif->portdev, ide_port_attrs[i]);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ide/serverworks.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ide/serverworks.c
@@ -115,6 +115,9 @@
 	struct pci_dev *dev = to_pci_dev(hwif->dev);
 	const u8 pio = drive->pio_mode - XFER_PIO_0;
 
+	if (drive->dn >= ARRAY_SIZE(drive_pci))
+		return;
+
 	pci_write_config_byte(dev, drive_pci[drive->dn], pio_modes[pio]);
 
 	if (svwks_csb_check(dev)) {
@@ -141,6 +144,9 @@
 
 	u8 ultra_enable	 = 0, ultra_timing = 0, dma_timing = 0;
 
+	if (drive->dn >= ARRAY_SIZE(drive_pci2))
+		return;
+
 	pci_read_config_byte(dev, (0x56|hwif->channel), &ultra_timing);
 	pci_read_config_byte(dev, 0x54, &ultra_enable);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ide/umc8672.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ide/umc8672.c
@@ -108,7 +108,7 @@
 static void umc_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
 	ide_hwif_t *mate = hwif->mate;
-	unsigned long uninitialized_var(flags);
+	unsigned long flags;
 	const u8 pio = drive->pio_mode - XFER_PIO_0;
 
 	printk("%s: setting umc8672 to PIO mode%d (speed %d)\n",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/idle/intel_idle.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/idle/intel_idle.c
@@ -46,11 +46,13 @@
 #include <linux/tick.h>
 #include <trace/events/power.h>
 #include <linux/sched.h>
+#include <linux/sched/smt.h>
 #include <linux/notifier.h>
 #include <linux/cpu.h>
 #include <linux/moduleparam.h>
 #include <asm/cpu_device_id.h>
 #include <asm/intel-family.h>
+#include <asm/nospec-branch.h>
 #include <asm/mwait.h>
 #include <asm/msr.h>
 
@@ -98,6 +100,12 @@
 #define CPUIDLE_FLAG_TLB_FLUSHED	0x10000
 
 /*
+ * Disable IBRS across idle (when KERNEL_IBRS), is exclusive vs IRQ_ENABLE
+ * above.
+ */
+#define CPUIDLE_FLAG_IBRS		BIT(16)
+
+/*
  * MWAIT takes an 8-bit "hint" in EAX "suggesting"
  * the C-state (top nibble) and sub-state (bottom nibble)
  * 0x00 means "MWAIT(C1)", 0x10 means "MWAIT(C2)" etc.
@@ -107,6 +115,24 @@
 #define flg2MWAIT(flags) (((flags) >> 24) & 0xFF)
 #define MWAIT2flg(eax) ((eax & 0xFF) << 24)
 
+static __cpuidle int intel_idle_ibrs(struct cpuidle_device *dev,
+				     struct cpuidle_driver *drv, int index)
+{
+	bool smt_active = sched_smt_active();
+	u64 spec_ctrl = spec_ctrl_current();
+	int ret;
+
+	if (smt_active)
+		wrmsrl(MSR_IA32_SPEC_CTRL, 0);
+
+	ret = intel_idle(dev, drv, index);
+
+	if (smt_active)
+		wrmsrl(MSR_IA32_SPEC_CTRL, spec_ctrl);
+
+	return ret;
+}
+
 /*
  * States are indexed by the cstate number,
  * which is also the index into the MWAIT hint array.
@@ -605,7 +631,7 @@
 	{
 		.name = "C6",
 		.desc = "MWAIT 0x20",
-		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
+		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
 		.exit_latency = 85,
 		.target_residency = 200,
 		.enter = &intel_idle,
@@ -613,7 +639,7 @@
 	{
 		.name = "C7s",
 		.desc = "MWAIT 0x33",
-		.flags = MWAIT2flg(0x33) | CPUIDLE_FLAG_TLB_FLUSHED,
+		.flags = MWAIT2flg(0x33) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
 		.exit_latency = 124,
 		.target_residency = 800,
 		.enter = &intel_idle,
@@ -621,7 +647,7 @@
 	{
 		.name = "C8",
 		.desc = "MWAIT 0x40",
-		.flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
+		.flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
 		.exit_latency = 200,
 		.target_residency = 800,
 		.enter = &intel_idle,
@@ -629,7 +655,7 @@
 	{
 		.name = "C9",
 		.desc = "MWAIT 0x50",
-		.flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED,
+		.flags = MWAIT2flg(0x50) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
 		.exit_latency = 480,
 		.target_residency = 5000,
 		.enter = &intel_idle,
@@ -637,7 +663,7 @@
 	{
 		.name = "C10",
 		.desc = "MWAIT 0x60",
-		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED,
+		.flags = MWAIT2flg(0x60) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
 		.exit_latency = 890,
 		.target_residency = 5000,
 		.enter = &intel_idle,
@@ -666,7 +692,7 @@
 	{
 		.name = "C6",
 		.desc = "MWAIT 0x20",
-		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
+		.flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED | CPUIDLE_FLAG_IBRS,
 		.exit_latency = 133,
 		.target_residency = 600,
 		.enter = &intel_idle,
@@ -1370,6 +1396,11 @@
 		drv->states[drv->state_count] =	/* structure copy */
 			cpuidle_state_table[cstate];
 
+		if (cpu_feature_enabled(X86_FEATURE_KERNEL_IBRS) &&
+		    cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_IBRS) {
+			drv->states[drv->state_count].enter = intel_idle_ibrs;
+		}
+
 		drv->state_count += 1;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/Kconfig
@@ -70,6 +70,7 @@
 
 source "drivers/iio/accel/Kconfig"
 source "drivers/iio/adc/Kconfig"
+source "drivers/iio/addac/Kconfig"
 source "drivers/iio/afe/Kconfig"
 source "drivers/iio/amplifiers/Kconfig"
 source "drivers/iio/chemical/Kconfig"
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/Makefile
@@ -15,6 +15,7 @@
 
 obj-y += accel/
 obj-y += adc/
+obj-y += addac/
 obj-y += afe/
 obj-y += amplifiers/
 obj-y += buffer/
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/accel/adis16201.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/accel/adis16201.c
@@ -215,7 +215,7 @@
 	ADIS_AUX_ADC_CHAN(ADIS16201_AUX_ADC_REG, ADIS16201_SCAN_AUX_ADC, 0, 12),
 	ADIS_INCLI_CHAN(X, ADIS16201_XINCL_OUT_REG, ADIS16201_SCAN_INCLI_X,
 			BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
-	ADIS_INCLI_CHAN(X, ADIS16201_YINCL_OUT_REG, ADIS16201_SCAN_INCLI_Y,
+	ADIS_INCLI_CHAN(Y, ADIS16201_YINCL_OUT_REG, ADIS16201_SCAN_INCLI_Y,
 			BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
 	IIO_CHAN_SOFT_TIMESTAMP(7)
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/accel/adxl372.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/accel/adxl372.c
@@ -237,6 +237,7 @@
 		.realbits = 12,						\
 		.storagebits = 16,					\
 		.shift = 4,						\
+		.endianness = IIO_BE,					\
 	},								\
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/accel/bma180.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/accel/bma180.c
@@ -47,7 +47,7 @@
 
 	u8 int_reset_reg, int_reset_mask;
 	u8 sleep_reg, sleep_mask;
-	u8 bw_reg, bw_mask;
+	u8 bw_reg, bw_mask, bw_offset;
 	u8 scale_reg, scale_mask;
 	u8 power_reg, power_mask, lowpower_val;
 	u8 int_enable_reg, int_enable_mask;
@@ -103,6 +103,7 @@
 
 #define BMA250_RANGE_MASK	GENMASK(3, 0) /* Range of accel values */
 #define BMA250_BW_MASK		GENMASK(4, 0) /* Accel bandwidth */
+#define BMA250_BW_OFFSET	8
 #define BMA250_SUSPEND_MASK	BIT(7) /* chip will sleep */
 #define BMA250_LOWPOWER_MASK	BIT(6)
 #define BMA250_DATA_INTEN_MASK	BIT(4)
@@ -119,7 +120,11 @@
 	int scale;
 	int bw;
 	bool pmode;
-	u8 buff[16]; /* 3x 16-bit + 8-bit + padding + timestamp */
+	/* Ensure timestamp is naturally aligned */
+	struct {
+		s16 chan[4];
+		s64 timestamp __aligned(8);
+	} scan;
 };
 
 enum bma180_chan {
@@ -237,7 +242,8 @@
 	for (i = 0; i < data->part_info->num_bw; ++i) {
 		if (data->part_info->bw_table[i] == val) {
 			ret = bma180_set_bits(data, data->part_info->bw_reg,
-				data->part_info->bw_mask, i);
+				data->part_info->bw_mask,
+				i + data->part_info->bw_offset);
 			if (ret) {
 				dev_err(&data->client->dev,
 					"failed to set bandwidth\n");
@@ -629,32 +635,53 @@
 
 static const struct bma180_part_info bma180_part_info[] = {
 	[BMA180] = {
-		bma180_channels, ARRAY_SIZE(bma180_channels),
-		bma180_scale_table, ARRAY_SIZE(bma180_scale_table),
-		bma180_bw_table, ARRAY_SIZE(bma180_bw_table),
-		BMA180_CTRL_REG0, BMA180_RESET_INT,
-		BMA180_CTRL_REG0, BMA180_SLEEP,
-		BMA180_BW_TCS, BMA180_BW,
-		BMA180_OFFSET_LSB1, BMA180_RANGE,
-		BMA180_TCO_Z, BMA180_MODE_CONFIG, BMA180_LOW_POWER,
-		BMA180_CTRL_REG3, BMA180_NEW_DATA_INT,
-		BMA180_RESET,
-		bma180_chip_config,
-		bma180_chip_disable,
+		.channels = bma180_channels,
+		.num_channels = ARRAY_SIZE(bma180_channels),
+		.scale_table = bma180_scale_table,
+		.num_scales = ARRAY_SIZE(bma180_scale_table),
+		.bw_table = bma180_bw_table,
+		.num_bw = ARRAY_SIZE(bma180_bw_table),
+		.int_reset_reg = BMA180_CTRL_REG0,
+		.int_reset_mask = BMA180_RESET_INT,
+		.sleep_reg = BMA180_CTRL_REG0,
+		.sleep_mask = BMA180_SLEEP,
+		.bw_reg = BMA180_BW_TCS,
+		.bw_mask = BMA180_BW,
+		.scale_reg = BMA180_OFFSET_LSB1,
+		.scale_mask = BMA180_RANGE,
+		.power_reg = BMA180_TCO_Z,
+		.power_mask = BMA180_MODE_CONFIG,
+		.lowpower_val = BMA180_LOW_POWER,
+		.int_enable_reg = BMA180_CTRL_REG3,
+		.int_enable_mask = BMA180_NEW_DATA_INT,
+		.softreset_reg = BMA180_RESET,
+		.chip_config = bma180_chip_config,
+		.chip_disable = bma180_chip_disable,
 	},
 	[BMA250] = {
-		bma250_channels, ARRAY_SIZE(bma250_channels),
-		bma250_scale_table, ARRAY_SIZE(bma250_scale_table),
-		bma250_bw_table, ARRAY_SIZE(bma250_bw_table),
-		BMA250_INT_RESET_REG, BMA250_INT_RESET_MASK,
-		BMA250_POWER_REG, BMA250_SUSPEND_MASK,
-		BMA250_BW_REG, BMA250_BW_MASK,
-		BMA250_RANGE_REG, BMA250_RANGE_MASK,
-		BMA250_POWER_REG, BMA250_LOWPOWER_MASK, 1,
-		BMA250_INT_ENABLE_REG, BMA250_DATA_INTEN_MASK,
-		BMA250_RESET_REG,
-		bma250_chip_config,
-		bma250_chip_disable,
+		.channels = bma250_channels,
+		.num_channels = ARRAY_SIZE(bma250_channels),
+		.scale_table = bma250_scale_table,
+		.num_scales = ARRAY_SIZE(bma250_scale_table),
+		.bw_table = bma250_bw_table,
+		.num_bw = ARRAY_SIZE(bma250_bw_table),
+		.int_reset_reg = BMA250_INT_RESET_REG,
+		.int_reset_mask = BMA250_INT_RESET_MASK,
+		.sleep_reg = BMA250_POWER_REG,
+		.sleep_mask = BMA250_SUSPEND_MASK,
+		.bw_reg = BMA250_BW_REG,
+		.bw_mask = BMA250_BW_MASK,
+		.bw_offset = BMA250_BW_OFFSET,
+		.scale_reg = BMA250_RANGE_REG,
+		.scale_mask = BMA250_RANGE_MASK,
+		.power_reg = BMA250_POWER_REG,
+		.power_mask = BMA250_LOWPOWER_MASK,
+		.lowpower_val = 1,
+		.int_enable_reg = BMA250_INT_ENABLE_REG,
+		.int_enable_mask = BMA250_DATA_INTEN_MASK,
+		.softreset_reg = BMA250_RESET_REG,
+		.chip_config = bma250_chip_config,
+		.chip_disable = bma250_chip_disable,
 	},
 };
 
@@ -675,12 +702,12 @@
 			mutex_unlock(&data->mutex);
 			goto err;
 		}
-		((s16 *)data->buff)[i++] = ret;
+		data->scan.chan[i++] = ret;
 	}
 
 	mutex_unlock(&data->mutex);
 
-	iio_push_to_buffers_with_timestamp(indio_dev, data->buff, time_ns);
+	iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, time_ns);
 err:
 	iio_trigger_notify_done(indio_dev->trig);
 
@@ -766,11 +793,12 @@
 		data->trig->dev.parent = &client->dev;
 		data->trig->ops = &bma180_trigger_ops;
 		iio_trigger_set_drvdata(data->trig, indio_dev);
-		indio_dev->trig = iio_trigger_get(data->trig);
 
 		ret = iio_trigger_register(data->trig);
 		if (ret)
 			goto err_trigger_free;
+
+		indio_dev->trig = iio_trigger_get(data->trig);
 	}
 
 	ret = iio_triggered_buffer_setup(indio_dev, NULL,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/accel/bma220_spi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/accel/bma220_spi.c
@@ -73,7 +73,11 @@
 struct bma220_data {
 	struct spi_device *spi_device;
 	struct mutex lock;
-	s8 buffer[16]; /* 3x8-bit channels + 5x8 padding + 8x8 timestamp */
+	struct {
+		s8 chans[3];
+		/* Ensure timestamp is naturally aligned. */
+		s64 timestamp __aligned(8);
+	} scan;
 	u8 tx_buf[2] ____cacheline_aligned;
 };
 
@@ -104,12 +108,12 @@
 
 	mutex_lock(&data->lock);
 	data->tx_buf[0] = BMA220_REG_ACCEL_X | BMA220_READ_MASK;
-	ret = spi_write_then_read(spi, data->tx_buf, 1, data->buffer,
+	ret = spi_write_then_read(spi, data->tx_buf, 1, &data->scan.chans,
 				  ARRAY_SIZE(bma220_channels) - 1);
 	if (ret < 0)
 		goto err;
 
-	iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+	iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
 					   pf->timestamp);
 err:
 	mutex_unlock(&data->lock);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/accel/bmc150-accel-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/accel/bmc150-accel-core.c
@@ -189,6 +189,14 @@
 	struct mutex mutex;
 	u8 fifo_mode, watermark;
 	s16 buffer[8];
+	/*
+	 * Ensure there is sufficient space and correct alignment for
+	 * the timestamp if enabled
+	 */
+	struct {
+		__le16 channels[3];
+		s64 ts __aligned(8);
+	} scan;
 	u8 bw_bits;
 	u32 slope_dur;
 	u32 slope_thres;
@@ -922,15 +930,16 @@
 	 * now.
 	 */
 	for (i = 0; i < count; i++) {
-		u16 sample[8];
 		int j, bit;
 
 		j = 0;
 		for_each_set_bit(bit, indio_dev->active_scan_mask,
 				 indio_dev->masklength)
-			memcpy(&sample[j++], &buffer[i * 3 + bit], 2);
+			memcpy(&data->scan.channels[j++], &buffer[i * 3 + bit],
+			       sizeof(data->scan.channels[0]));
 
-		iio_push_to_buffers_with_timestamp(indio_dev, sample, tstamp);
+		iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
+						   tstamp);
 
 		tstamp += sample_period;
 	}
@@ -1640,11 +1649,14 @@
 	ret = iio_device_register(indio_dev);
 	if (ret < 0) {
 		dev_err(dev, "Unable to register iio device\n");
-		goto err_trigger_unregister;
+		goto err_pm_cleanup;
 	}
 
 	return 0;
 
+err_pm_cleanup:
+	pm_runtime_dont_use_autosuspend(dev);
+	pm_runtime_disable(dev);
 err_trigger_unregister:
 	bmc150_accel_unregister_triggers(data, BMC150_ACCEL_TRIGGERS - 1);
 err_buffer_cleanup:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/accel/hid-sensor-accel-3d.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/accel/hid-sensor-accel-3d.c
@@ -29,8 +29,11 @@
 	struct hid_sensor_hub_callbacks callbacks;
 	struct hid_sensor_common common_attributes;
 	struct hid_sensor_hub_attribute_info accel[ACCEL_3D_CHANNEL_MAX];
-	/* Reserve for 3 channels + padding + timestamp */
-	u32 accel_val[ACCEL_3D_CHANNEL_MAX + 3];
+	/* Ensure timestamp is naturally aligned */
+	struct {
+		u32 accel_val[3];
+		s64 timestamp __aligned(8);
+	} scan;
 	int scale_pre_decml;
 	int scale_post_decml;
 	int scale_precision;
@@ -241,8 +244,8 @@
 			accel_state->timestamp = iio_get_time_ns(indio_dev);
 
 		hid_sensor_push_data(indio_dev,
-				     accel_state->accel_val,
-				     sizeof(accel_state->accel_val),
+				     &accel_state->scan,
+				     sizeof(accel_state->scan),
 				     accel_state->timestamp);
 
 		accel_state->timestamp = 0;
@@ -267,7 +270,7 @@
 	case HID_USAGE_SENSOR_ACCEL_Y_AXIS:
 	case HID_USAGE_SENSOR_ACCEL_Z_AXIS:
 		offset = usage_id - HID_USAGE_SENSOR_ACCEL_X_AXIS;
-		accel_state->accel_val[CHANNEL_SCAN_INDEX_X + offset] =
+		accel_state->scan.accel_val[CHANNEL_SCAN_INDEX_X + offset] =
 						*(u32 *)raw_data;
 		ret = 0;
 	break;
@@ -276,6 +279,7 @@
 			hid_sensor_convert_timestamp(
 					&accel_state->common_attributes,
 					*(int64_t *)raw_data);
+		ret = 0;
 	break;
 	default:
 		break;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/accel/kxcjk-1013.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/accel/kxcjk-1013.c
@@ -126,12 +126,29 @@
 	KX_MAX_CHIPS /* this must be last */
 };
 
+enum kx_acpi_type {
+	ACPI_GENERIC,
+	ACPI_SMO8500,
+	ACPI_KIOX010A,
+};
+
+enum kxcjk1013_axis {
+	AXIS_X,
+	AXIS_Y,
+	AXIS_Z,
+	AXIS_MAX
+};
+
 struct kxcjk1013_data {
 	struct i2c_client *client;
 	struct iio_trigger *dready_trig;
 	struct iio_trigger *motion_trig;
 	struct mutex mutex;
-	s16 buffer[8];
+	/* Ensure timestamp naturally aligned */
+	struct {
+		s16 chans[AXIS_MAX];
+		s64 timestamp __aligned(8);
+	} scan;
 	u8 odr_bits;
 	u8 range;
 	int wake_thres;
@@ -142,14 +159,7 @@
 	bool motion_trigger_on;
 	int64_t timestamp;
 	enum kx_chipset chipset;
-	bool is_smo8500_device;
-};
-
-enum kxcjk1013_axis {
-	AXIS_X,
-	AXIS_Y,
-	AXIS_Z,
-	AXIS_MAX,
+	enum kx_acpi_type acpi_type;
 };
 
 enum kxcjk1013_mode {
@@ -269,6 +279,32 @@
 			      {19163, 1, 0},
 			      {38326, 0, 1} };
 
+#ifdef CONFIG_ACPI
+enum kiox010a_fn_index {
+	KIOX010A_SET_LAPTOP_MODE = 1,
+	KIOX010A_SET_TABLET_MODE = 2,
+};
+
+static int kiox010a_dsm(struct device *dev, int fn_index)
+{
+	acpi_handle handle = ACPI_HANDLE(dev);
+	guid_t kiox010a_dsm_guid;
+	union acpi_object *obj;
+
+	if (!handle)
+		return -ENODEV;
+
+	guid_parse("1f339696-d475-4e26-8cad-2e9f8e6d7a91", &kiox010a_dsm_guid);
+
+	obj = acpi_evaluate_dsm(handle, &kiox010a_dsm_guid, 1, fn_index, NULL);
+	if (!obj)
+		return -EIO;
+
+	ACPI_FREE(obj);
+	return 0;
+}
+#endif
+
 static int kxcjk1013_set_mode(struct kxcjk1013_data *data,
 			      enum kxcjk1013_mode mode)
 {
@@ -346,6 +382,13 @@
 {
 	int ret;
 
+#ifdef CONFIG_ACPI
+	if (data->acpi_type == ACPI_KIOX010A) {
+		/* Make sure the kbd and touchpad on 2-in-1s using 2 KXCJ91008-s work */
+		kiox010a_dsm(&data->client->dev, KIOX010A_SET_LAPTOP_MODE);
+	}
+#endif
+
 	ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_WHO_AM_I);
 	if (ret < 0) {
 		dev_err(&data->client->dev, "Error reading who_am_i\n");
@@ -1039,12 +1082,12 @@
 	ret = i2c_smbus_read_i2c_block_data_or_emulated(data->client,
 							KXCJK1013_REG_XOUT_L,
 							AXIS_MAX * 2,
-							(u8 *)data->buffer);
+							(u8 *)data->scan.chans);
 	mutex_unlock(&data->mutex);
 	if (ret < 0)
 		goto err;
 
-	iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+	iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
 					   data->timestamp);
 err:
 	iio_trigger_notify_done(indio_dev->trig);
@@ -1233,7 +1276,7 @@
 
 static const char *kxcjk1013_match_acpi_device(struct device *dev,
 					       enum kx_chipset *chipset,
-					       bool *is_smo8500_device)
+					       enum kx_acpi_type *acpi_type)
 {
 	const struct acpi_device_id *id;
 
@@ -1242,7 +1285,9 @@
 		return NULL;
 
 	if (strcmp(id->id, "SMO8500") == 0)
-		*is_smo8500_device = true;
+		*acpi_type = ACPI_SMO8500;
+	else if (strcmp(id->id, "KIOX010A") == 0)
+		*acpi_type = ACPI_KIOX010A;
 
 	*chipset = (enum kx_chipset)id->driver_data;
 
@@ -1278,7 +1323,7 @@
 	} else if (ACPI_HANDLE(&client->dev)) {
 		name = kxcjk1013_match_acpi_device(&client->dev,
 						   &data->chipset,
-						   &data->is_smo8500_device);
+						   &data->acpi_type);
 	} else
 		return -ENODEV;
 
@@ -1296,7 +1341,7 @@
 	indio_dev->modes = INDIO_DIRECT_MODE;
 	indio_dev->info = &kxcjk1013_info;
 
-	if (client->irq > 0 && !data->is_smo8500_device) {
+	if (client->irq > 0 && data->acpi_type != ACPI_SMO8500) {
 		ret = devm_request_threaded_irq(&client->dev, client->irq,
 						kxcjk1013_data_rdy_trig_poll,
 						kxcjk1013_event_handler,
@@ -1364,14 +1409,16 @@
 	ret = iio_device_register(indio_dev);
 	if (ret < 0) {
 		dev_err(&client->dev, "unable to register iio device\n");
-		goto err_buffer_cleanup;
+		goto err_pm_cleanup;
 	}
 
 	return 0;
 
+err_pm_cleanup:
+	pm_runtime_dont_use_autosuspend(&client->dev);
+	pm_runtime_disable(&client->dev);
 err_buffer_cleanup:
-	if (data->dready_trig)
-		iio_triggered_buffer_cleanup(indio_dev);
+	iio_triggered_buffer_cleanup(indio_dev);
 err_trigger_unregister:
 	if (data->dready_trig)
 		iio_trigger_unregister(data->dready_trig);
@@ -1394,8 +1441,8 @@
 	pm_runtime_set_suspended(&client->dev);
 	pm_runtime_put_noidle(&client->dev);
 
+	iio_triggered_buffer_cleanup(indio_dev);
 	if (data->dready_trig) {
-		iio_triggered_buffer_cleanup(indio_dev);
 		iio_trigger_unregister(data->dready_trig);
 		iio_trigger_unregister(data->motion_trig);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/accel/kxsd9.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/accel/kxsd9.c
@@ -209,23 +209,29 @@
 	const struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct kxsd9_state *st = iio_priv(indio_dev);
+	/*
+	 * Ensure correct positioning and alignment of timestamp.
+	 * No need to zero initialize as all elements written.
+	 */
+	struct {
+		__be16 chan[4];
+		s64 ts __aligned(8);
+	} hw_values;
 	int ret;
-	/* 4 * 16bit values AND timestamp */
-	__be16 hw_values[8];
 
 	ret = regmap_bulk_read(st->map,
 			       KXSD9_REG_X,
-			       &hw_values,
-			       8);
+			       hw_values.chan,
+			       sizeof(hw_values.chan));
 	if (ret) {
-		dev_err(st->dev,
-			"error reading data\n");
-		return ret;
+		dev_err(st->dev, "error reading data: %d\n", ret);
+		goto out;
 	}
 
 	iio_push_to_buffers_with_timestamp(indio_dev,
-					   hw_values,
+					   &hw_values,
 					   iio_get_time_ns(indio_dev));
+out:
 	iio_trigger_notify_done(indio_dev->trig);
 
 	return IRQ_HANDLED;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/accel/mma7455_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/accel/mma7455_core.c
@@ -52,6 +52,14 @@
 
 struct mma7455_data {
 	struct regmap *regmap;
+	/*
+	 * Used to reorganize data.  Will ensure correct alignment of
+	 * the timestamp if present
+	 */
+	struct {
+		__le16 channels[3];
+		s64 ts __aligned(8);
+	} scan;
 };
 
 static int mma7455_drdy(struct mma7455_data *mma7455)
@@ -82,19 +90,19 @@
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct mma7455_data *mma7455 = iio_priv(indio_dev);
-	u8 buf[16]; /* 3 x 16-bit channels + padding + ts */
 	int ret;
 
 	ret = mma7455_drdy(mma7455);
 	if (ret)
 		goto done;
 
-	ret = regmap_bulk_read(mma7455->regmap, MMA7455_REG_XOUTL, buf,
-			       sizeof(__le16) * 3);
+	ret = regmap_bulk_read(mma7455->regmap, MMA7455_REG_XOUTL,
+			       mma7455->scan.channels,
+			       sizeof(mma7455->scan.channels));
 	if (ret)
 		goto done;
 
-	iio_push_to_buffers_with_timestamp(indio_dev, buf,
+	iio_push_to_buffers_with_timestamp(indio_dev, &mma7455->scan,
 					   iio_get_time_ns(indio_dev));
 
 done:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/accel/mma8452.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/accel/mma8452.c
@@ -110,6 +110,12 @@
 	int sleep_val;
 	struct regulator *vdd_reg;
 	struct regulator *vddio_reg;
+
+	/* Ensure correct alignment of time stamp when present */
+	struct {
+		__be16 channels[3];
+		s64 ts __aligned(8);
+	} buffer;
 };
 
  /**
@@ -704,7 +710,7 @@
 			     int val, int val2, long mask)
 {
 	struct mma8452_data *data = iio_priv(indio_dev);
-	int i, ret;
+	int i, j, ret;
 
 	ret = iio_device_claim_direct_mode(indio_dev);
 	if (ret)
@@ -764,14 +770,18 @@
 		break;
 
 	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
-		ret = mma8452_get_odr_index(data);
+		j = mma8452_get_odr_index(data);
 
 		for (i = 0; i < ARRAY_SIZE(mma8452_os_ratio); i++) {
-			if (mma8452_os_ratio[i][ret] == val) {
+			if (mma8452_os_ratio[i][j] == val) {
 				ret = mma8452_set_power_mode(data, i);
 				break;
 			}
 		}
+		if (i == ARRAY_SIZE(mma8452_os_ratio)) {
+			ret = -EINVAL;
+			break;
+		}
 		break;
 	default:
 		ret = -EINVAL;
@@ -1091,14 +1101,13 @@
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct mma8452_data *data = iio_priv(indio_dev);
-	u8 buffer[16]; /* 3 16-bit channels + padding + ts */
 	int ret;
 
-	ret = mma8452_read(data, (__be16 *)buffer);
+	ret = mma8452_read(data, data->buffer.channels);
 	if (ret < 0)
 		goto done;
 
-	iio_push_to_buffers_with_timestamp(indio_dev, buffer,
+	iio_push_to_buffers_with_timestamp(indio_dev, &data->buffer,
 					   iio_get_time_ns(indio_dev));
 
 done:
@@ -1468,7 +1477,7 @@
 	if (ret)
 		return ret;
 
-	indio_dev->trig = trig;
+	indio_dev->trig = iio_trigger_get(trig);
 
 	return 0;
 }
@@ -1484,10 +1493,14 @@
 	int i;
 	int ret;
 
-	ret = i2c_smbus_write_byte_data(client,	MMA8452_CTRL_REG2,
+	/*
+	 * Find on fxls8471, after config reset bit, it reset immediately,
+	 * and will not give ACK, so here do not check the return value.
+	 * The following code will read the reset register, and check whether
+	 * this reset works.
+	 */
+	i2c_smbus_write_byte_data(client, MMA8452_CTRL_REG2,
 					MMA8452_CTRL_REG2_RST);
-	if (ret < 0)
-		return ret;
 
 	for (i = 0; i < 10; i++) {
 		usleep_range(100, 200);
@@ -1685,10 +1698,13 @@
 
 	ret = mma8452_set_freefall_mode(data, false);
 	if (ret < 0)
-		goto buffer_cleanup;
+		goto unregister_device;
 
 	return 0;
 
+unregister_device:
+	iio_device_unregister(indio_dev);
+
 buffer_cleanup:
 	iio_triggered_buffer_cleanup(indio_dev);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/accel/mma9551.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/accel/mma9551.c
@@ -496,11 +496,14 @@
 	ret = iio_device_register(indio_dev);
 	if (ret < 0) {
 		dev_err(&client->dev, "unable to register iio device\n");
-		goto out_poweroff;
+		goto err_pm_cleanup;
 	}
 
 	return 0;
 
+err_pm_cleanup:
+	pm_runtime_dont_use_autosuspend(&client->dev);
+	pm_runtime_disable(&client->dev);
 out_poweroff:
 	mma9551_set_device_state(client, false);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/accel/mma9551_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/accel/mma9551_core.c
@@ -296,9 +296,12 @@
 
 	ret = mma9551_transfer(client, app_id, MMA9551_CMD_READ_CONFIG,
 			       reg, NULL, 0, (u8 *)&v, 2);
+	if (ret < 0)
+		return ret;
+
 	*val = be16_to_cpu(v);
 
-	return ret;
+	return 0;
 }
 EXPORT_SYMBOL(mma9551_read_config_word);
 
@@ -354,9 +357,12 @@
 
 	ret = mma9551_transfer(client, app_id, MMA9551_CMD_READ_STATUS,
 			       reg, NULL, 0, (u8 *)&v, 2);
+	if (ret < 0)
+		return ret;
+
 	*val = be16_to_cpu(v);
 
-	return ret;
+	return 0;
 }
 EXPORT_SYMBOL(mma9551_read_status_word);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/accel/mma9553.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/accel/mma9553.c
@@ -1135,12 +1135,15 @@
 	ret = iio_device_register(indio_dev);
 	if (ret < 0) {
 		dev_err(&client->dev, "unable to register iio device\n");
-		goto out_poweroff;
+		goto err_pm_cleanup;
 	}
 
 	dev_dbg(&indio_dev->dev, "Registered device %s\n", name);
 	return 0;
 
+err_pm_cleanup:
+	pm_runtime_dont_use_autosuspend(&client->dev);
+	pm_runtime_disable(&client->dev);
 out_poweroff:
 	mma9551_set_device_state(client, false);
 	return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/accel/mxc4005.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/accel/mxc4005.c
@@ -56,7 +56,11 @@
 	struct mutex mutex;
 	struct regmap *regmap;
 	struct iio_trigger *dready_trig;
-	__be16 buffer[8];
+	/* Ensure timestamp is naturally aligned */
+	struct {
+		__be16 chans[3];
+		s64 timestamp __aligned(8);
+	} scan;
 	bool trigger_enabled;
 };
 
@@ -135,7 +139,7 @@
 	int ret;
 
 	ret = regmap_bulk_read(data->regmap, MXC4005_REG_XOUT_UPPER,
-			       (u8 *) data->buffer, sizeof(data->buffer));
+			       data->scan.chans, sizeof(data->scan.chans));
 	if (ret < 0) {
 		dev_err(data->dev, "failed to read axes\n");
 		return ret;
@@ -150,7 +154,7 @@
 	__be16 reg;
 	int ret;
 
-	ret = regmap_bulk_read(data->regmap, addr, (u8 *) &reg, sizeof(reg));
+	ret = regmap_bulk_read(data->regmap, addr, &reg, sizeof(reg));
 	if (ret < 0) {
 		dev_err(data->dev, "failed to read reg %02x\n", addr);
 		return ret;
@@ -301,7 +305,7 @@
 	if (ret < 0)
 		goto err;
 
-	iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+	iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
 					   pf->timestamp);
 
 err:
@@ -458,8 +462,6 @@
 		data->dready_trig->dev.parent = &client->dev;
 		data->dready_trig->ops = &mxc4005_trigger_ops;
 		iio_trigger_set_drvdata(data->dready_trig, indio_dev);
-		indio_dev->trig = data->dready_trig;
-		iio_trigger_get(indio_dev->trig);
 		ret = devm_iio_trigger_register(&client->dev,
 						data->dready_trig);
 		if (ret) {
@@ -467,6 +469,8 @@
 				"failed to register trigger\n");
 			return ret;
 		}
+
+		indio_dev->trig = iio_trigger_get(data->dready_trig);
 	}
 
 	return devm_iio_device_register(&client->dev, indio_dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/accel/sca3000.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/accel/sca3000.c
@@ -980,7 +980,7 @@
 	st->tx[0] = SCA3000_READ_REG(reg_address_high);
 	ret = spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer));
 	if (ret) {
-		dev_err(get_device(&st->us->dev), "problem reading register");
+		dev_err(&st->us->dev, "problem reading register\n");
 		return ret;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/accel/st_accel_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/accel/st_accel_core.c
@@ -993,6 +993,7 @@
 #define ST_ACCEL_TRIGGER_OPS NULL
 #endif
 
+#ifdef CONFIG_ACPI
 static const struct iio_mount_matrix *
 get_mount_matrix(const struct iio_dev *indio_dev,
 		 const struct iio_chan_spec *chan)
@@ -1013,7 +1014,6 @@
 static int apply_acpi_orientation(struct iio_dev *indio_dev,
 				  struct iio_chan_spec *channels)
 {
-#ifdef CONFIG_ACPI
 	struct st_sensor_data *adata = iio_priv(indio_dev);
 	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
 	struct acpi_device *adev;
@@ -1141,10 +1141,14 @@
 out:
 	kfree(buffer.pointer);
 	return ret;
+}
 #else /* !CONFIG_ACPI */
+static int apply_acpi_orientation(struct iio_dev *indio_dev,
+				  struct iio_chan_spec *channels)
+{
 	return 0;
-#endif
 }
+#endif
 
 /*
  * st_accel_get_settings() - get sensor settings from device name
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/accel/st_accel_i2c.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/accel/st_accel_i2c.c
@@ -114,7 +114,7 @@
 
 #ifdef CONFIG_ACPI
 static const struct acpi_device_id st_accel_acpi_match[] = {
-	{"SMO8840", (kernel_ulong_t)LNG2DM_ACCEL_DEV_NAME},
+	{"SMO8840", (kernel_ulong_t)LIS2DH12_ACCEL_DEV_NAME},
 	{"SMO8A90", (kernel_ulong_t)LNG2DM_ACCEL_DEV_NAME},
 	{ },
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/accel/stk8312.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/accel/stk8312.c
@@ -103,7 +103,11 @@
 	u8 mode;
 	struct iio_trigger *dready_trig;
 	bool dready_trigger_on;
-	s8 buffer[16]; /* 3x8-bit channels + 5x8 padding + 64-bit timestamp */
+	/* Ensure timestamp is naturally aligned */
+	struct {
+		s8 chans[3];
+		s64 timestamp __aligned(8);
+	} scan;
 };
 
 static IIO_CONST_ATTR(in_accel_scale_available, STK8312_SCALE_AVAIL);
@@ -438,7 +442,7 @@
 		ret = i2c_smbus_read_i2c_block_data(data->client,
 						    STK8312_REG_XOUT,
 						    STK8312_ALL_CHANNEL_SIZE,
-						    data->buffer);
+						    data->scan.chans);
 		if (ret < STK8312_ALL_CHANNEL_SIZE) {
 			dev_err(&data->client->dev, "register read failed\n");
 			mutex_unlock(&data->lock);
@@ -452,12 +456,12 @@
 				mutex_unlock(&data->lock);
 				goto err;
 			}
-			data->buffer[i++] = ret;
+			data->scan.chans[i++] = ret;
 		}
 	}
 	mutex_unlock(&data->lock);
 
-	iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+	iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
 					   pf->timestamp);
 err:
 	iio_trigger_notify_done(indio_dev->trig);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/accel/stk8ba50.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/accel/stk8ba50.c
@@ -91,12 +91,11 @@
 	u8 sample_rate_idx;
 	struct iio_trigger *dready_trig;
 	bool dready_trigger_on;
-	/*
-	 * 3 x 16-bit channels (10-bit data, 6-bit padding) +
-	 * 1 x 16 padding +
-	 * 4 x 16 64-bit timestamp
-	 */
-	s16 buffer[8];
+	/* Ensure timestamp is naturally aligned */
+	struct {
+		s16 chans[3];
+		s64 timetamp __aligned(8);
+	} scan;
 };
 
 #define STK8BA50_ACCEL_CHANNEL(index, reg, axis) {			\
@@ -324,7 +323,7 @@
 		ret = i2c_smbus_read_i2c_block_data(data->client,
 						    STK8BA50_REG_XOUT,
 						    STK8BA50_ALL_CHANNEL_SIZE,
-						    (u8 *)data->buffer);
+						    (u8 *)data->scan.chans);
 		if (ret < STK8BA50_ALL_CHANNEL_SIZE) {
 			dev_err(&data->client->dev, "register read failed\n");
 			goto err;
@@ -337,10 +336,10 @@
 			if (ret < 0)
 				goto err;
 
-			data->buffer[i++] = ret;
+			data->scan.chans[i++] = ret;
 		}
 	}
-	iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+	iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
 					   pf->timestamp);
 err:
 	mutex_unlock(&data->lock);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/Kconfig
@@ -423,6 +423,18 @@
 	  Say yes here to build support for TI INA2xx family of Power Monitors.
 	  This driver is mutually exclusive with the HWMON version.
 
+config INA260_ADC
+	tristate "Texas Instruments INA260 Power Monitors IIO driver"
+	depends on I2C && !SENSORS_INA2XX
+	select REGMAP_I2C
+	select IIO_BUFFER
+	select IIO_KFIFO_BUF
+	help
+	  Say yes here to build support for TI INA260 power monitor.
+	  This driver can also be built as a module. It supports software buffer
+	  mode and raw reads of ina260 iio channels. Up to 4 channels are
+	  supported including timestamp.
+
 config INGENIC_ADC
 	tristate "Ingenic JZ47xx SoCs ADC driver"
 	depends on MIPS || COMPILE_TEST
@@ -784,6 +796,7 @@
 	depends on ARCH_STM32 || COMPILE_TEST
 	depends on OF
 	depends on REGULATOR
+	depends on HAS_IOMEM
 	select IIO_BUFFER
 	select MFD_STM32_TIMERS
 	select IIO_STM32_TIMER_TRIGGER
@@ -839,22 +852,6 @@
 	  Say yes here to build support for ST Microelectronics STMPE
 	  built-in ADC block (stmpe811).
 
-config STX104
-	tristate "Apex Embedded Systems STX104 driver"
-	depends on PC104 && X86
-	select ISA_BUS_API
-	select GPIOLIB
-	help
-	  Say yes here to build support for the Apex Embedded Systems STX104
-	  integrated analog PC/104 card.
-
-	  This driver supports the 16 channels of single-ended (8 channels of
-	  differential) analog inputs, 2 channels of analog output, 4 digital
-	  inputs, and 4 digital outputs provided by the STX104.
-
-	  The base port addresses for the devices may be configured via the base
-	  array module parameter.
-
 config SUN4I_GPADC
 	tristate "Support for the Allwinner SoCs GPADC"
 	depends on IIO
@@ -995,6 +992,8 @@
 config TI_ADS8688
 	tristate "Texas Instruments ADS8688"
 	depends on SPI && OF
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
 	help
 	  If you say yes here you get support for Texas Instruments ADS8684 and
 	  and ADS8688 ADC chips
@@ -1005,6 +1004,8 @@
 config TI_ADS124S08
 	tristate "Texas Instruments ADS124S08"
 	depends on SPI && OF
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
 	help
 	  If you say yes here you get support for Texas Instruments ADS124S08
 	  and ADS124S06 ADC chips
@@ -1095,4 +1096,25 @@
 	  The driver can also be build as a module. If so, the module will be called
 	  xilinx-xadc.
 
+config XILINX_AMS
+       tristate "Xilinx AMS driver"
+       depends on ARCH_ZYNQMP || COMPILE_TEST
+       depends on HAS_IOMEM
+       help
+         Say yes here to have support for the Xilinx AMS.
+
+         The driver can also be build as a module. If so, the module will be called
+         xilinx-ams.
+
+config VERSAL_SYSMON
+	tristate "Xilinx Sysmon driver for Versal"
+	depends on HAS_IOMEM
+	help
+	  Say yes here to have support for the Xilinx Sysmon.
+	  The driver will enable users to monitor temperature and voltage on the
+	  Xilinx Versal platform.
+	  The HW also supports I2C access but it is not supported by the driver.
+
+	  The driver can also be build as a module. If so, the module will be called
+	  versal-sysmon.
 endmenu
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/Makefile
@@ -41,6 +41,7 @@
 obj-$(CONFIG_HX711) += hx711.o
 obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o
 obj-$(CONFIG_INA2XX_ADC) += ina2xx-adc.o
+obj-$(CONFIG_INA260_ADC) += ina260-adc.o
 obj-$(CONFIG_INGENIC_ADC) += ingenic-adc.o
 obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
 obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o
@@ -72,7 +73,6 @@
 obj-$(CONFIG_ROCKCHIP_SARADC) += rockchip_saradc.o
 obj-$(CONFIG_SC27XX_ADC) += sc27xx_adc.o
 obj-$(CONFIG_SPEAR_ADC) += spear_adc.o
-obj-$(CONFIG_STX104) += stx104.o
 obj-$(CONFIG_SUN4I_GPADC) += sun4i-gpadc-iio.o
 obj-$(CONFIG_STM32_ADC_CORE) += stm32-adc-core.o
 obj-$(CONFIG_STM32_ADC) += stm32-adc.o
@@ -99,4 +99,6 @@
 obj-$(CONFIG_VIPERBOARD_ADC) += viperboard_adc.o
 xilinx-xadc-y := xilinx-xadc-core.o xilinx-xadc-events.o
 obj-$(CONFIG_XILINX_XADC) += xilinx-xadc.o
+obj-$(CONFIG_XILINX_AMS) += xilinx-ams.o
 obj-$(CONFIG_SD_ADC_MODULATOR) += sd_adc_modulator.o
+obj-$(CONFIG_VERSAL_SYSMON) += versal-sysmon.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/ad7124.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/ad7124.c
@@ -39,6 +39,8 @@
 #define AD7124_STATUS_POR_FLAG_MSK	BIT(4)
 
 /* AD7124_ADC_CONTROL */
+#define AD7124_ADC_CTRL_REF_EN_MSK	BIT(8)
+#define AD7124_ADC_CTRL_REF_EN(x)	FIELD_PREP(AD7124_ADC_CTRL_REF_EN_MSK, x)
 #define AD7124_ADC_CTRL_PWR_MSK	GENMASK(7, 6)
 #define AD7124_ADC_CTRL_PWR(x)		FIELD_PREP(AD7124_ADC_CTRL_PWR_MSK, x)
 #define AD7124_ADC_CTRL_MODE_MSK	GENMASK(5, 2)
@@ -61,7 +63,7 @@
 #define AD7124_CONFIG_REF_SEL(x)	FIELD_PREP(AD7124_CONFIG_REF_SEL_MSK, x)
 #define AD7124_CONFIG_PGA_MSK		GENMASK(2, 0)
 #define AD7124_CONFIG_PGA(x)		FIELD_PREP(AD7124_CONFIG_PGA_MSK, x)
-#define AD7124_CONFIG_IN_BUFF_MSK	GENMASK(7, 6)
+#define AD7124_CONFIG_IN_BUFF_MSK	GENMASK(6, 5)
 #define AD7124_CONFIG_IN_BUFF(x)	FIELD_PREP(AD7124_CONFIG_IN_BUFF_MSK, x)
 
 /* AD7124_FILTER_X */
@@ -140,7 +142,6 @@
 		.sign = 'u',
 		.realbits = 24,
 		.storagebits = 32,
-		.shift = 8,
 		.endianness = IIO_BE,
 	},
 };
@@ -424,7 +425,10 @@
 		break;
 	case AD7124_INT_REF:
 		st->channel_config[channel_number].vref_mv = 2500;
-		break;
+		st->adc_control &= ~AD7124_ADC_CTRL_REF_EN_MSK;
+		st->adc_control |= AD7124_ADC_CTRL_REF_EN(1);
+		return ad_sd_write_reg(&st->sd, AD7124_ADC_CONTROL,
+				      2, st->adc_control);
 	default:
 		dev_err(&st->sd.spi->dev, "Invalid reference %d\n", refsel);
 		return -EINVAL;
@@ -468,6 +472,13 @@
 		if (ret)
 			goto err;
 
+		if (channel >= indio_dev->num_channels) {
+			dev_err(indio_dev->dev.parent,
+				"Channel index >= number of channels\n");
+			ret = -EINVAL;
+			goto err;
+		}
+
 		ret = of_property_read_u32_array(child, "diff-channels",
 						 ain, 2);
 		if (ret)
@@ -489,13 +500,11 @@
 		st->channel_config[channel].buf_negative =
 			of_property_read_bool(child, "adi,buffered-negative");
 
-		*chan = ad7124_channel_template;
-		chan->address = channel;
-		chan->scan_index = channel;
-		chan->channel = ain[0];
-		chan->channel2 = ain[1];
-
-		chan++;
+		chan[channel] = ad7124_channel_template;
+		chan[channel].address = channel;
+		chan[channel].scan_index = channel;
+		chan[channel].channel = ain[0];
+		chan[channel].channel2 = ain[1];
 	}
 
 	return 0;
@@ -561,6 +570,11 @@
 	return ret;
 }
 
+static void ad7124_reg_disable(void *r)
+{
+	regulator_disable(r);
+}
+
 static int ad7124_probe(struct spi_device *spi)
 {
 	const struct spi_device_id *id;
@@ -604,17 +618,20 @@
 		ret = regulator_enable(st->vref[i]);
 		if (ret)
 			return ret;
+
+		ret = devm_add_action_or_reset(&spi->dev, ad7124_reg_disable,
+					       st->vref[i]);
+		if (ret)
+			return ret;
 	}
 
 	st->mclk = devm_clk_get(&spi->dev, "mclk");
-	if (IS_ERR(st->mclk)) {
-		ret = PTR_ERR(st->mclk);
-		goto error_regulator_disable;
-	}
+	if (IS_ERR(st->mclk))
+		return PTR_ERR(st->mclk);
 
 	ret = clk_prepare_enable(st->mclk);
 	if (ret < 0)
-		goto error_regulator_disable;
+		return ret;
 
 	ret = ad7124_soft_reset(st);
 	if (ret < 0)
@@ -640,11 +657,6 @@
 	ad_sd_cleanup_buffer_and_trigger(indio_dev);
 error_clk_disable_unprepare:
 	clk_disable_unprepare(st->mclk);
-error_regulator_disable:
-	for (i = ARRAY_SIZE(st->vref) - 1; i >= 0; i--) {
-		if (!IS_ERR_OR_NULL(st->vref[i]))
-			regulator_disable(st->vref[i]);
-	}
 
 	return ret;
 }
@@ -653,17 +665,11 @@
 {
 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
 	struct ad7124_state *st = iio_priv(indio_dev);
-	int i;
 
 	iio_device_unregister(indio_dev);
 	ad_sd_cleanup_buffer_and_trigger(indio_dev);
 	clk_disable_unprepare(st->mclk);
 
-	for (i = ARRAY_SIZE(st->vref) - 1; i >= 0; i--) {
-		if (!IS_ERR_OR_NULL(st->vref[i]))
-			regulator_disable(st->vref[i]);
-	}
-
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/ad7266.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/ad7266.c
@@ -159,6 +159,8 @@
 		ret = ad7266_read_single(st, val, chan->address);
 		iio_device_release_direct_mode(indio_dev);
 
+		if (ret < 0)
+			return ret;
 		*val = (*val >> 2) & 0xfff;
 		if (chan->scan_type.sign == 's')
 			*val = sign_extend32(*val, 11);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/ad7606.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/ad7606.c
@@ -85,7 +85,7 @@
 
 static int ad7606_read_samples(struct ad7606_state *st)
 {
-	unsigned int num = st->chip_info->num_channels;
+	unsigned int num = st->chip_info->num_channels - 1;
 	u16 *data = st->data;
 	int ret;
 
@@ -238,9 +238,9 @@
 	struct ad7606_state *st = iio_priv(indio_dev);
 	DECLARE_BITMAP(values, 3);
 
-	values[0] = val;
+	values[0] = val & GENMASK(2, 0);
 
-	gpiod_set_array_value(ARRAY_SIZE(values), st->gpio_os->desc,
+	gpiod_set_array_value(st->gpio_os->ndescs, st->gpio_os->desc,
 			      st->gpio_os->info, values);
 
 	/* AD7616 requires a reset to update value */
@@ -445,7 +445,7 @@
 		return PTR_ERR(st->gpio_range);
 
 	st->gpio_standby = devm_gpiod_get_optional(dev, "standby",
-						   GPIOD_OUT_HIGH);
+						   GPIOD_OUT_LOW);
 	if (IS_ERR(st->gpio_standby))
 		return PTR_ERR(st->gpio_standby);
 
@@ -706,7 +706,7 @@
 
 	if (st->gpio_standby) {
 		gpiod_set_value(st->gpio_range, 1);
-		gpiod_set_value(st->gpio_standby, 0);
+		gpiod_set_value(st->gpio_standby, 1);
 	}
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/ad7606_spi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/ad7606_spi.c
@@ -249,8 +249,9 @@
 static int ad7606B_sw_mode_config(struct iio_dev *indio_dev)
 {
 	struct ad7606_state *st = iio_priv(indio_dev);
-	unsigned long os[3] = {1};
+	DECLARE_BITMAP(os, 3);
 
+	bitmap_fill(os, 3);
 	/*
 	 * Software mode is enabled when all three oversampling
 	 * pins are set to high. If oversampling gpios are defined
@@ -258,7 +259,7 @@
 	 * otherwise, they must be hardwired to VDD
 	 */
 	if (st->gpio_os) {
-		gpiod_set_array_value(ARRAY_SIZE(os),
+		gpiod_set_array_value(st->gpio_os->ndescs,
 				      st->gpio_os->desc, st->gpio_os->info, os);
 	}
 	/* OS of 128 and 256 are available only in software mode */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/ad7768-1.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/ad7768-1.c
@@ -166,6 +166,10 @@
 	 * transfer buffers to live in their own cache lines.
 	 */
 	union {
+		struct {
+			__be32 chan;
+			s64 timestamp;
+		} scan;
 		__be32 d32;
 		u8 d8[2];
 	} data ____cacheline_aligned;
@@ -459,15 +463,15 @@
 
 	mutex_lock(&st->lock);
 
-	ret = spi_read(st->spi, &st->data.d32, 3);
+	ret = spi_read(st->spi, &st->data.scan.chan, 3);
 	if (ret < 0)
 		goto err_unlock;
 
-	iio_push_to_buffers_with_timestamp(indio_dev, &st->data.d32,
+	iio_push_to_buffers_with_timestamp(indio_dev, &st->data.scan,
 					   iio_get_time_ns(indio_dev));
 
-	iio_trigger_notify_done(indio_dev->trig);
 err_unlock:
+	iio_trigger_notify_done(indio_dev->trig);
 	mutex_unlock(&st->lock);
 
 	return IRQ_HANDLED;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/ad7780.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/ad7780.c
@@ -152,7 +152,7 @@
 
 	switch (m) {
 	case IIO_CHAN_INFO_SCALE:
-		if (val != 0)
+		if (val != 0 || val2 == 0)
 			return -EINVAL;
 
 		vref = st->int_vref_mv * 1000000LL;
@@ -309,7 +309,7 @@
 
 	ret = ad7780_init_gpios(&spi->dev, st);
 	if (ret)
-		goto error_cleanup_buffer_and_trigger;
+		return ret;
 
 	st->reg = devm_regulator_get(&spi->dev, "avdd");
 	if (IS_ERR(st->reg))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/ad7793.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/ad7793.c
@@ -278,6 +278,7 @@
 	id &= AD7793_ID_MASK;
 
 	if (id != st->chip_info->id) {
+		ret = -ENODEV;
 		dev_err(&st->sd.spi->dev, "device ID query failed\n");
 		goto out;
 	}
@@ -541,7 +542,7 @@
 	.read_raw = &ad7793_read_raw,
 	.write_raw = &ad7793_write_raw,
 	.write_raw_get_fmt = &ad7793_write_raw_get_fmt,
-	.attrs = &ad7793_attribute_group,
+	.attrs = &ad7797_attribute_group,
 	.validate_trigger = ad_sd_validate_trigger,
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/ad7949.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/ad7949.c
@@ -57,29 +57,11 @@
 	u32 buffer ____cacheline_aligned;
 };
 
-static bool ad7949_spi_cfg_is_read_back(struct ad7949_adc_chip *ad7949_adc)
-{
-	if (!(ad7949_adc->cfg & AD7949_CFG_READ_BACK))
-		return true;
-
-	return false;
-}
-
-static int ad7949_spi_bits_per_word(struct ad7949_adc_chip *ad7949_adc)
-{
-	int ret = ad7949_adc->resolution;
-
-	if (ad7949_spi_cfg_is_read_back(ad7949_adc))
-		ret += AD7949_CFG_REG_SIZE_BITS;
-
-	return ret;
-}
-
 static int ad7949_spi_write_cfg(struct ad7949_adc_chip *ad7949_adc, u16 val,
 				u16 mask)
 {
 	int ret;
-	int bits_per_word = ad7949_spi_bits_per_word(ad7949_adc);
+	int bits_per_word = ad7949_adc->resolution;
 	int shift = bits_per_word - AD7949_CFG_REG_SIZE_BITS;
 	struct spi_message msg;
 	struct spi_transfer tx[] = {
@@ -107,8 +89,9 @@
 				   unsigned int channel)
 {
 	int ret;
-	int bits_per_word = ad7949_spi_bits_per_word(ad7949_adc);
-	int mask = GENMASK(ad7949_adc->resolution, 0);
+	int i;
+	int bits_per_word = ad7949_adc->resolution;
+	int mask = GENMASK(ad7949_adc->resolution - 1, 0);
 	struct spi_message msg;
 	struct spi_transfer tx[] = {
 		{
@@ -118,12 +101,23 @@
 		},
 	};
 
-	ret = ad7949_spi_write_cfg(ad7949_adc,
-				   channel << AD7949_OFFSET_CHANNEL_SEL,
-				   AD7949_MASK_CHANNEL_SEL);
-	if (ret)
-		return ret;
+	/*
+	 * 1: write CFG for sample N and read old data (sample N-2)
+	 * 2: if CFG was not changed since sample N-1 then we'll get good data
+	 *    at the next xfer, so we bail out now, otherwise we write something
+	 *    and we read garbage (sample N-1 configuration).
+	 */
+	for (i = 0; i < 2; i++) {
+		ret = ad7949_spi_write_cfg(ad7949_adc,
+					   channel << AD7949_OFFSET_CHANNEL_SEL,
+					   AD7949_MASK_CHANNEL_SEL);
+		if (ret)
+			return ret;
+		if (channel == ad7949_adc->current_channel)
+			break;
+	}
 
+	/* 3: write something and read actual data */
 	ad7949_adc->buffer = 0;
 	spi_message_init_with_transfers(&msg, tx, 1);
 	ret = spi_sync(ad7949_adc->spi, &msg);
@@ -138,10 +132,7 @@
 
 	ad7949_adc->current_channel = channel;
 
-	if (ad7949_spi_cfg_is_read_back(ad7949_adc))
-		*val = (ad7949_adc->buffer >> AD7949_CFG_REG_SIZE_BITS) & mask;
-	else
-		*val = ad7949_adc->buffer & mask;
+	*val = ad7949_adc->buffer & mask;
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/ad_sigma_delta.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/ad_sigma_delta.c
@@ -283,10 +283,10 @@
 	unsigned int data_reg;
 	int ret = 0;
 
-	if (iio_buffer_enabled(indio_dev))
-		return -EBUSY;
+	ret = iio_device_claim_direct_mode(indio_dev);
+	if (ret)
+		return ret;
 
-	mutex_lock(&indio_dev->mlock);
 	ad_sigma_delta_set_channel(sigma_delta, chan->address);
 
 	spi_bus_lock(sigma_delta->spi->master);
@@ -325,7 +325,7 @@
 	ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);
 	sigma_delta->bus_locked = false;
 	spi_bus_unlock(sigma_delta->spi->master);
-	mutex_unlock(&indio_dev->mlock);
+	iio_device_release_direct_mode(indio_dev);
 
 	if (ret)
 		return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/aspeed_adc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/aspeed_adc.c
@@ -184,6 +184,7 @@
 
 	data = iio_priv(indio_dev);
 	data->dev = &pdev->dev;
+	platform_set_drvdata(pdev, indio_dev);
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	data->base = devm_ioremap_resource(&pdev->dev, res);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/at91-sama5d2_adc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/at91-sama5d2_adc.c
@@ -73,7 +73,7 @@
 #define	AT91_SAMA5D2_MR_ANACH		BIT(23)
 /* Tracking Time */
 #define	AT91_SAMA5D2_MR_TRACKTIM(v)	((v) << 24)
-#define	AT91_SAMA5D2_MR_TRACKTIM_MAX	0xff
+#define	AT91_SAMA5D2_MR_TRACKTIM_MAX	0xf
 /* Transfer Time */
 #define	AT91_SAMA5D2_MR_TRANSFER(v)	((v) << 28)
 #define	AT91_SAMA5D2_MR_TRANSFER_MAX	0x3
@@ -399,7 +399,9 @@
 	wait_queue_head_t		wq_data_available;
 	struct at91_adc_dma		dma_st;
 	struct at91_adc_touch		touch_st;
-	u16				buffer[AT91_BUFFER_MAX_HWORDS];
+	struct iio_dev			*indio_dev;
+	/* Ensure naturally aligned timestamp */
+	u16				buffer[AT91_BUFFER_MAX_HWORDS] __aligned(8);
 	/*
 	 * lock to prevent concurrent 'single conversion' requests through
 	 * sysfs.
@@ -624,13 +626,13 @@
 	/* first half of register is the x or y, second half is the scale */
 	val = at91_adc_readl(st, reg);
 	if (!val)
-		dev_dbg(&iio_priv_to_dev(st)->dev, "pos is 0\n");
+		dev_dbg(&st->indio_dev->dev, "pos is 0\n");
 
 	pos = val & AT91_SAMA5D2_XYZ_MASK;
 	result = (pos << AT91_SAMA5D2_MAX_POS_BITS) - pos;
 	scale = (val >> 16) & AT91_SAMA5D2_XYZ_MASK;
 	if (scale == 0) {
-		dev_err(&iio_priv_to_dev(st)->dev, "scale is 0\n");
+		dev_err(&st->indio_dev->dev, "scale is 0\n");
 		return 0;
 	}
 	result /= scale;
@@ -723,6 +725,7 @@
 
 	for_each_set_bit(bit, indio->active_scan_mask, indio->num_channels) {
 		struct iio_chan_spec const *chan = at91_adc_chan_get(indio, bit);
+		u32 cor;
 
 		if (!chan)
 			continue;
@@ -732,6 +735,20 @@
 			continue;
 
 		if (state) {
+			cor = at91_adc_readl(st, AT91_SAMA5D2_COR);
+
+			if (chan->differential)
+				cor |= (BIT(chan->channel) |
+					BIT(chan->channel2)) <<
+					AT91_SAMA5D2_COR_DIFF_OFFSET;
+			else
+				cor &= ~(BIT(chan->channel) <<
+				       AT91_SAMA5D2_COR_DIFF_OFFSET);
+
+			at91_adc_writel(st, AT91_SAMA5D2_COR, cor);
+		}
+
+		if (state) {
 			at91_adc_writel(st, AT91_SAMA5D2_CHER,
 					BIT(chan->channel));
 			/* enable irq only if not using DMA */
@@ -966,7 +983,7 @@
 	trig = devm_iio_trigger_alloc(&indio->dev, "%s-dev%d-%s", indio->name,
 				      indio->id, trigger_name);
 	if (!trig)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 
 	trig->dev.parent = indio->dev.parent;
 	iio_trigger_set_drvdata(trig, indio);
@@ -1139,9 +1156,9 @@
 	return i;
 }
 
-static void at91_adc_setup_samp_freq(struct at91_adc_state *st, unsigned freq)
+static void at91_adc_setup_samp_freq(struct iio_dev *indio_dev, unsigned freq)
 {
-	struct iio_dev *indio_dev = iio_priv_to_dev(st);
+	struct at91_adc_state *st = iio_priv(indio_dev);
 	unsigned f_per, prescal, startup, mr;
 
 	f_per = clk_get_rate(st->per_clk);
@@ -1210,9 +1227,9 @@
 	st->touch_st.touching = true;
 }
 
-static void at91_adc_no_pen_detect_interrupt(struct at91_adc_state *st)
+static void at91_adc_no_pen_detect_interrupt(struct iio_dev *indio_dev)
 {
-	struct iio_dev *indio_dev = iio_priv_to_dev(st);
+	struct at91_adc_state *st = iio_priv(indio_dev);
 
 	at91_adc_writel(st, AT91_SAMA5D2_TRGR,
 			AT91_SAMA5D2_TRGR_TRGMOD_NO_TRIGGER);
@@ -1232,7 +1249,7 @@
 					struct at91_adc_touch, workq);
 	struct at91_adc_state *st = container_of(touch_st,
 					struct at91_adc_state, touch_st);
-	struct iio_dev *indio_dev = iio_priv_to_dev(st);
+	struct iio_dev *indio_dev = st->indio_dev;
 
 	iio_push_to_buffers(indio_dev, st->buffer);
 }
@@ -1253,7 +1270,7 @@
 		at91_adc_pen_detect_interrupt(st);
 	} else if ((status & AT91_SAMA5D2_IER_NOPEN)) {
 		/* nopen detected IRQ */
-		at91_adc_no_pen_detect_interrupt(st);
+		at91_adc_no_pen_detect_interrupt(indio);
 	} else if ((status & AT91_SAMA5D2_ISR_PENS) &&
 		   ((status & rdy_mask) == rdy_mask)) {
 		/* periodic trigger IRQ - during pen sense */
@@ -1304,10 +1321,12 @@
 		ret = at91_adc_read_position(st, chan->channel,
 					     &tmp_val);
 		*val = tmp_val;
+		if (ret > 0)
+			ret = at91_adc_adjust_val_osr(st, val);
 		mutex_unlock(&st->lock);
 		iio_device_release_direct_mode(indio_dev);
 
-		return at91_adc_adjust_val_osr(st, val);
+		return ret;
 	}
 	if (chan->type == IIO_PRESSURE) {
 		ret = iio_device_claim_direct_mode(indio_dev);
@@ -1318,10 +1337,12 @@
 		ret = at91_adc_read_pressure(st, chan->channel,
 					     &tmp_val);
 		*val = tmp_val;
+		if (ret > 0)
+			ret = at91_adc_adjust_val_osr(st, val);
 		mutex_unlock(&st->lock);
 		iio_device_release_direct_mode(indio_dev);
 
-		return at91_adc_adjust_val_osr(st, val);
+		return ret;
 	}
 
 	/* in this case we have a voltage channel */
@@ -1352,7 +1373,8 @@
 		*val = st->conversion_value;
 		ret = at91_adc_adjust_val_osr(st, val);
 		if (chan->scan_type.sign == 's')
-			*val = sign_extend32(*val, 11);
+			*val = sign_extend32(*val,
+					     chan->scan_type.realbits - 1);
 		st->conversion_done = false;
 	}
 
@@ -1411,16 +1433,20 @@
 		/* if no change, optimize out */
 		if (val == st->oversampling_ratio)
 			return 0;
+		mutex_lock(&st->lock);
 		st->oversampling_ratio = val;
 		/* update ratio */
 		at91_adc_config_emr(st);
+		mutex_unlock(&st->lock);
 		return 0;
 	case IIO_CHAN_INFO_SAMP_FREQ:
 		if (val < st->soc_info.min_sample_rate ||
 		    val > st->soc_info.max_sample_rate)
 			return -EINVAL;
 
-		at91_adc_setup_samp_freq(st, val);
+		mutex_lock(&st->lock);
+		at91_adc_setup_samp_freq(indio_dev, val);
+		mutex_unlock(&st->lock);
 		return 0;
 	default:
 		return -EINVAL;
@@ -1558,8 +1584,10 @@
 	return 0;
 }
 
-static void at91_adc_hw_init(struct at91_adc_state *st)
+static void at91_adc_hw_init(struct iio_dev *indio_dev)
 {
+	struct at91_adc_state *st = iio_priv(indio_dev);
+
 	at91_adc_writel(st, AT91_SAMA5D2_CR, AT91_SAMA5D2_CR_SWRST);
 	at91_adc_writel(st, AT91_SAMA5D2_IDR, 0xffffffff);
 	/*
@@ -1569,7 +1597,7 @@
 	at91_adc_writel(st, AT91_SAMA5D2_MR,
 			AT91_SAMA5D2_MR_TRANSFER(2) | AT91_SAMA5D2_MR_ANACH);
 
-	at91_adc_setup_samp_freq(st, st->soc_info.min_sample_rate);
+	at91_adc_setup_samp_freq(indio_dev, st->soc_info.min_sample_rate);
 
 	/* configure extended mode register */
 	at91_adc_config_emr(st);
@@ -1652,6 +1680,7 @@
 	indio_dev->num_channels = ARRAY_SIZE(at91_adc_channels);
 
 	st = iio_priv(indio_dev);
+	st->indio_dev = indio_dev;
 
 	bitmap_set(&st->touch_st.channels_bitmask,
 		   AT91_SAMA5D2_TOUCH_X_CHAN_IDX, 1);
@@ -1763,7 +1792,7 @@
 		goto vref_disable;
 	}
 
-	at91_adc_hw_init(st);
+	at91_adc_hw_init(indio_dev);
 
 	ret = clk_prepare_enable(st->per_clk);
 	if (ret)
@@ -1879,7 +1908,7 @@
 	if (ret)
 		goto vref_disable_resume;
 
-	at91_adc_hw_init(st);
+	at91_adc_hw_init(indio_dev);
 
 	/* reconfiguring trigger hardware state */
 	if (!iio_buffer_enabled(indio_dev))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/at91_adc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/at91_adc.c
@@ -616,8 +616,10 @@
 	trig->ops = &at91_adc_trigger_ops;
 
 	ret = iio_trigger_register(trig);
-	if (ret)
+	if (ret) {
+		iio_trigger_free(trig);
 		return NULL;
+	}
 
 	return trig;
 }
@@ -1137,7 +1139,7 @@
 	return ret;
 
 err:
-	input_free_device(st->ts_input);
+	input_free_device(input);
 	return ret;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/axp20x_adc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/axp20x_adc.c
@@ -251,19 +251,8 @@
 			  struct iio_chan_spec const *chan, int *val)
 {
 	struct axp20x_adc_iio *info = iio_priv(indio_dev);
-	int size;
 
-	/*
-	 * N.B.: Unlike the Chinese datasheets tell, the charging current is
-	 * stored on 12 bits, not 13 bits. Only discharging current is on 13
-	 * bits.
-	 */
-	if (chan->type == IIO_CURRENT && chan->channel == AXP22X_BATT_DISCHRG_I)
-		size = 13;
-	else
-		size = 12;
-
-	*val = axp20x_read_variable_width(info->regmap, chan->address, size);
+	*val = axp20x_read_variable_width(info->regmap, chan->address, 12);
 	if (*val < 0)
 		return *val;
 
@@ -386,9 +375,8 @@
 		return IIO_VAL_INT_PLUS_MICRO;
 
 	case IIO_CURRENT:
-		*val = 0;
-		*val2 = 500000;
-		return IIO_VAL_INT_PLUS_MICRO;
+		*val = 1;
+		return IIO_VAL_INT;
 
 	case IIO_TEMP:
 		*val = 100;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/axp288_adc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/axp288_adc.c
@@ -196,6 +196,14 @@
 		},
 		.driver_data = (void *)(uintptr_t)AXP288_ADC_TS_BIAS_80UA,
 	},
+	{
+		/* Nuvision Solo 10 Draw */
+		.matches = {
+		  DMI_MATCH(DMI_SYS_VENDOR, "TMAX"),
+		  DMI_MATCH(DMI_PRODUCT_NAME, "TM101W610L"),
+		},
+		.driver_data = (void *)(uintptr_t)AXP288_ADC_TS_BIAS_80UA,
+	},
 	{}
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/berlin2-adc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/berlin2-adc.c
@@ -289,8 +289,10 @@
 	int ret;
 
 	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
-	if (!indio_dev)
+	if (!indio_dev) {
+		of_node_put(parent_np);
 		return -ENOMEM;
+	}
 
 	priv = iio_priv(indio_dev);
 	platform_set_drvdata(pdev, indio_dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/dln2-adc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/dln2-adc.c
@@ -248,7 +248,6 @@
 static int dln2_adc_read(struct dln2_adc *dln2, unsigned int channel)
 {
 	int ret, i;
-	struct iio_dev *indio_dev = platform_get_drvdata(dln2->pdev);
 	u16 conflict;
 	__le16 value;
 	int olen = sizeof(value);
@@ -257,13 +256,9 @@
 		.chan = channel,
 	};
 
-	ret = iio_device_claim_direct_mode(indio_dev);
-	if (ret < 0)
-		return ret;
-
 	ret = dln2_adc_set_chan_enabled(dln2, channel, true);
 	if (ret < 0)
-		goto release_direct;
+		return ret;
 
 	ret = dln2_adc_set_port_enabled(dln2, true, &conflict);
 	if (ret < 0) {
@@ -300,8 +295,6 @@
 	dln2_adc_set_port_enabled(dln2, false, NULL);
 disable_chan:
 	dln2_adc_set_chan_enabled(dln2, channel, false);
-release_direct:
-	iio_device_release_direct_mode(indio_dev);
 
 	return ret;
 }
@@ -337,10 +330,16 @@
 
 	switch (mask) {
 	case IIO_CHAN_INFO_RAW:
+		ret = iio_device_claim_direct_mode(indio_dev);
+		if (ret < 0)
+			return ret;
+
 		mutex_lock(&dln2->mutex);
 		ret = dln2_adc_read(dln2, chan->channel);
 		mutex_unlock(&dln2->mutex);
 
+		iio_device_release_direct_mode(indio_dev);
+
 		if (ret < 0)
 			return ret;
 
@@ -524,6 +523,10 @@
 	u16 conflict;
 	unsigned int trigger_chan;
 
+	ret = iio_triggered_buffer_postenable(indio_dev);
+	if (ret)
+		return ret;
+
 	mutex_lock(&dln2->mutex);
 
 	/* Enable ADC */
@@ -537,6 +540,7 @@
 				(int)conflict);
 			ret = -EBUSY;
 		}
+		iio_triggered_buffer_predisable(indio_dev);
 		return ret;
 	}
 
@@ -550,6 +554,7 @@
 		mutex_unlock(&dln2->mutex);
 		if (ret < 0) {
 			dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__);
+			iio_triggered_buffer_predisable(indio_dev);
 			return ret;
 		}
 	} else {
@@ -557,12 +562,12 @@
 		mutex_unlock(&dln2->mutex);
 	}
 
-	return iio_triggered_buffer_postenable(indio_dev);
+	return 0;
 }
 
 static int dln2_adc_triggered_buffer_predisable(struct iio_dev *indio_dev)
 {
-	int ret;
+	int ret, ret2;
 	struct dln2_adc *dln2 = iio_priv(indio_dev);
 
 	mutex_lock(&dln2->mutex);
@@ -577,12 +582,14 @@
 	ret = dln2_adc_set_port_enabled(dln2, false, NULL);
 
 	mutex_unlock(&dln2->mutex);
-	if (ret < 0) {
+	if (ret < 0)
 		dev_dbg(&dln2->pdev->dev, "Problem in %s\n", __func__);
-		return ret;
-	}
 
-	return iio_triggered_buffer_predisable(indio_dev);
+	ret2 = iio_triggered_buffer_predisable(indio_dev);
+	if (ret == 0)
+		ret = ret2;
+
+	return ret;
 }
 
 static const struct iio_buffer_setup_ops dln2_adc_buffer_setup_ops = {
@@ -658,7 +665,11 @@
 		return -ENOMEM;
 	}
 	iio_trigger_set_drvdata(dln2->trig, dln2);
-	devm_iio_trigger_register(dev, dln2->trig);
+	ret = devm_iio_trigger_register(dev, dln2->trig);
+	if (ret) {
+		dev_err(dev, "failed to register trigger: %d\n", ret);
+		return ret;
+	}
 	iio_trigger_set_immutable(indio_dev, dln2->trig);
 
 	ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/exynos_adc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/exynos_adc.c
@@ -804,16 +804,26 @@
 		}
 	}
 
+	/* leave out any TS related code if unreachable */
+	if (IS_REACHABLE(CONFIG_INPUT)) {
+		has_ts = of_property_read_bool(pdev->dev.of_node,
+					       "has-touchscreen") || pdata;
+	}
+
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0)
 		return irq;
 	info->irq = irq;
 
-	irq = platform_get_irq(pdev, 1);
-	if (irq == -EPROBE_DEFER)
-		return irq;
-
-	info->tsirq = irq;
+	if (has_ts) {
+		irq = platform_get_irq(pdev, 1);
+		if (irq == -EPROBE_DEFER)
+			return irq;
+
+		info->tsirq = irq;
+	} else {
+		info->tsirq = -1;
+	}
 
 	info->dev = &pdev->dev;
 
@@ -880,12 +890,6 @@
 	if (info->data->init_hw)
 		info->data->init_hw(info);
 
-	/* leave out any TS related code if unreachable */
-	if (IS_REACHABLE(CONFIG_INPUT)) {
-		has_ts = of_property_read_bool(pdev->dev.of_node,
-					       "has-touchscreen") || pdata;
-	}
-
 	if (pdata)
 		info->delay = pdata->delay;
 	else
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/hx711.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/hx711.c
@@ -85,9 +85,9 @@
 	struct mutex		lock;
 	/*
 	 * triggered buffer
-	 * 2x32-bit channel + 64-bit timestamp
+	 * 2x32-bit channel + 64-bit naturally aligned timestamp
 	 */
-	u32			buffer[4];
+	u32			buffer[4] __aligned(8);
 	/*
 	 * delay after a rising edge on SCK until the data is ready DOUT
 	 * this is dependent on the hx711 where the datasheet tells a
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/ina260-adc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/ina260-adc.c
@@ -0,0 +1,556 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * INA260 power monitor driver
+ * Based on drivers/iio/adc/ina2xx-adc.c
+ *
+ * Copyright (C) 2021 Xilinx, Inc.
+ */
+
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/kfifo_buf.h>
+#include <linux/iio/sysfs.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/sched/task.h>
+#include <linux/util_macros.h>
+
+/* INA260 registers definition */
+#define INA260_CONFIG		0x00
+#define INA260_CURRENT		0x01
+#define INA260_VOLTAGE		0x02
+#define INA260_POWER		0x03
+#define INA260_MASK_ENABLE	0x06
+#define INA260_ALERT_LIMIT	0x07
+#define INA260_MANF_ID		0xFE
+#define INA260_DIE_ID		0xFF
+
+#define INA260_CONFIG_DEFAULT	0x6327
+
+#define INA260_CURRENT_LSB	1250
+#define INA260_VOLTAGE_LSB	1250
+#define INA260_POWER_LSB	10
+
+/* Bits */
+#define INA260_CVRF		BIT(3)
+
+#define INA260_MODE_MASK	GENMASK(2, 0)
+#define INA260_VOLT_MASK	GENMASK(8, 6)
+#define INA260_SHIFT_VOLT(val)	((val) << 6)
+#define INA260_CURR_MASK	GENMASK(5, 3)
+#define INA260_SHIFT_CURR(val)	((val) << 3)
+#define INA260_AVG_MASK		GENMASK(11, 9)
+#define INA260_SHIFT_AVG(val)	((val) << 9)
+
+#define SAMPLING_PERIOD(x) ({		\
+	typeof(x) _x = (x);		\
+	(_x->config->volt_conv_time	\
+	+ _x->config->curr_conv_time)	\
+	* _x->config->avgs; })
+
+static bool ina260_is_writeable_reg(struct device *dev, unsigned int reg)
+{
+	return (reg == INA260_CONFIG) || (reg == INA260_MASK_ENABLE) ||
+		(reg == INA260_ALERT_LIMIT);
+}
+
+static bool ina260_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+	return (reg != INA260_CONFIG);
+}
+
+static inline bool is_signed_reg(unsigned int reg)
+{
+	return (reg == INA260_CURRENT);
+}
+
+static const struct regmap_config ina260_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 16,
+	.max_register = 8,
+	.writeable_reg = ina260_is_writeable_reg,
+	.volatile_reg = ina260_is_volatile_reg,
+};
+
+enum ina260_ids {ina260 = 0};
+
+/**
+ * struct ina260_config - For configurable parameters
+ * @config_default: Default configuration
+ * @volt_conv_time: Bus voltage conversion time
+ * @curr_conv_time: Shunt current conversion time
+ * @avgs: Number of samples collected and averaged
+ */
+struct ina260_config {
+	u16 config_default;
+	int volt_conv_time;
+	int curr_conv_time;
+	int avgs;
+};
+
+/**
+ * struct ina260_chip - For device specific data
+ * @regmap: Regmap pointer to device registers
+ * @task: Pointer to task created by buffer mode
+ * @lock: Mutex to enable use of multiple user apps
+ * @chip_id: Id to determine chip
+ * @config: Pointer to config structure
+ */
+struct ina260_chip {
+	struct regmap *regmap;
+	struct task_struct *task;
+	struct mutex lock; /* Lock for device writes */
+	enum ina260_ids chip_id;
+	struct ina260_config *config;
+};
+
+static struct ina260_config ina260_config[] = {
+	[ina260] = {
+		.config_default = INA260_CONFIG_DEFAULT,
+		.volt_conv_time = 1100,
+		.curr_conv_time = 1100,
+		.avgs = 4,
+	},
+};
+
+static int ina260_read_raw(struct iio_dev *indio_dev,
+			   struct iio_chan_spec const *chan,
+			   int *val, int *val2, long mask)
+{
+	struct ina260_chip *chip = iio_priv(indio_dev);
+	unsigned int regval;
+	int ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		if (iio_buffer_enabled(indio_dev))
+			return -EBUSY;
+
+		ret = regmap_read(chip->regmap, chan->address, &regval);
+		if (ret)
+			return ret;
+
+		if (is_signed_reg(chan->address))
+			*val = (s16)regval;
+		else
+			*val = regval;
+		return IIO_VAL_INT;
+
+	case IIO_CHAN_INFO_SCALE:
+		switch (chan->address) {
+		case INA260_CURRENT:
+			*val = INA260_CURRENT_LSB;
+			*val2 = 1000;
+			return IIO_VAL_FRACTIONAL;
+
+		case INA260_VOLTAGE:
+			*val = INA260_VOLTAGE_LSB;
+			*val2 = 1000;
+			return IIO_VAL_FRACTIONAL;
+
+		case INA260_POWER:
+			*val = INA260_POWER_LSB;
+			return IIO_VAL_INT;
+		}
+		return -EINVAL;
+
+	case IIO_CHAN_INFO_INT_TIME:
+		*val = 0;
+		if (chan->address == INA260_VOLTAGE)
+			*val2 = chip->config->volt_conv_time;
+		else
+			*val2 = chip->config->curr_conv_time;
+
+		return IIO_VAL_INT_PLUS_MICRO;
+
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		*val = DIV_ROUND_CLOSEST(1000000, SAMPLING_PERIOD(chip));
+		return IIO_VAL_INT;
+
+	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
+		*val = chip->config->avgs;
+		return IIO_VAL_INT;
+	}
+
+	return -EINVAL;
+}
+
+static const int ina260_avg_tab[] = { 1, 4, 16, 64, 128, 256, 512, 1024 };
+
+/* Conversion times in uS */
+static const int ina260_conv_time_tab[] = { 140, 204, 332, 588, 1100, 2116, 4156, 8244 };
+
+static int ina260_write_raw(struct iio_dev *indio_dev,
+			    struct iio_chan_spec const *chan,
+			    int val, int val2, long mask)
+{
+	struct ina260_chip *chip = iio_priv(indio_dev);
+	unsigned int config;
+	int ret, bits;
+
+	if (iio_buffer_enabled(indio_dev))
+		return -EBUSY;
+
+	mutex_lock(&chip->lock);
+
+	ret = regmap_read(chip->regmap, INA260_CONFIG, &config);
+	if (ret)
+		goto err;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_INT_TIME:
+		if (val2 > 8244 || val2 < 140) {
+			ret = -EINVAL;
+			goto err;
+		}
+
+		bits = find_closest(val2, ina260_conv_time_tab,
+				    ARRAY_SIZE(ina260_conv_time_tab));
+
+		if (chan->address == INA260_VOLTAGE) {
+			chip->config->volt_conv_time = ina260_conv_time_tab[bits];
+			config &= ~INA260_VOLT_MASK;
+			config |= INA260_SHIFT_VOLT(bits) & INA260_VOLT_MASK;
+		} else {
+			chip->config->curr_conv_time = ina260_conv_time_tab[bits];
+			config &= ~INA260_CURR_MASK;
+			config |= INA260_SHIFT_CURR(bits) & INA260_CURR_MASK;
+		}
+		break;
+
+	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
+		bits = find_closest(val, ina260_avg_tab, ARRAY_SIZE(ina260_avg_tab));
+		chip->config->avgs = ina260_avg_tab[bits];
+		config &= ~INA260_AVG_MASK;
+		config |= INA260_SHIFT_AVG(bits) & INA260_AVG_MASK;
+		break;
+
+	default:
+		ret = -EINVAL;
+	}
+	if (!ret)
+		ret = regmap_write(chip->regmap, INA260_CONFIG, config);
+err:
+	mutex_unlock(&chip->lock);
+
+	return ret;
+}
+
+static int ina260_debug_reg(struct iio_dev *indio_dev,
+			    unsigned int reg, unsigned int writeval, unsigned int *readval)
+{
+	struct ina260_chip *chip = iio_priv(indio_dev);
+
+	if (!readval)
+		return regmap_write(chip->regmap, reg, writeval);
+
+	return regmap_read(chip->regmap, reg, readval);
+}
+
+#define INA260_CHAN_VOLTAGE(_index, _address) { \
+	.type = IIO_VOLTAGE, \
+	.address = (_address), \
+	.indexed = 1, \
+	.channel = (_index), \
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+	BIT(IIO_CHAN_INFO_SCALE) | \
+	BIT(IIO_CHAN_INFO_INT_TIME), \
+	.info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
+	BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
+	.scan_index = (_index), \
+	.scan_type = { \
+		.sign = 'u', \
+		.realbits = 16, \
+		.storagebits = 16, \
+		.endianness = IIO_CPU, \
+	} \
+}
+
+#define INA260_CHAN_CURRENT(_index, _address) { \
+	.type = IIO_CURRENT, \
+	.address = (_address), \
+	.indexed = 1, \
+	.channel = (_index), \
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+	BIT(IIO_CHAN_INFO_SCALE) | \
+	BIT(IIO_CHAN_INFO_INT_TIME), \
+	.info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
+	BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
+	.scan_index = (_index), \
+	.scan_type = { \
+		.sign = 's', \
+		.realbits = 16, \
+		.storagebits = 16, \
+		.endianness = IIO_CPU, \
+	} \
+}
+
+#define INA260_CHAN_POWER(_index, _address) { \
+	.type = IIO_POWER, \
+	.address = (_address), \
+	.indexed = 1, \
+	.channel = (_index), \
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+	BIT(IIO_CHAN_INFO_SCALE), \
+	.info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
+	BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
+	.scan_index = (_index), \
+	.scan_type = { \
+		.sign = 'u', \
+		.realbits = 16, \
+		.storagebits = 16, \
+		.endianness = IIO_CPU, \
+	} \
+}
+
+static const struct iio_chan_spec ina260_channels[] = {
+	INA260_CHAN_CURRENT(0, INA260_CURRENT),
+	INA260_CHAN_VOLTAGE(1, INA260_VOLTAGE),
+	INA260_CHAN_POWER(2, INA260_POWER),
+	IIO_CHAN_SOFT_TIMESTAMP(3),
+};
+
+/* Possible integration times for current and voltage */
+static IIO_CONST_ATTR_NAMED(ina260_integration_time_available,
+			    integration_time_available,
+			    "0.000140 0.000204 0.000332 0.000588 0.001100 0.002116 0.004156 0.008244");
+
+static struct attribute *ina260_attributes[] = {
+	&iio_const_attr_ina260_integration_time_available.dev_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group ina260_attribute_group = {
+	.attrs = ina260_attributes,
+};
+
+static const struct iio_info ina260_info = {
+	.attrs = &ina260_attribute_group,
+	.read_raw = ina260_read_raw,
+	.write_raw = ina260_write_raw,
+	.debugfs_reg_access = ina260_debug_reg,
+};
+
+static int ina260_conversion_ready(struct iio_dev *indio_dev)
+{
+	struct ina260_chip *chip = iio_priv(indio_dev);
+	unsigned int alert;
+	int ret;
+
+	ret = regmap_read(chip->regmap, INA260_MASK_ENABLE, &alert);
+	if (ret < 0)
+		return ret;
+
+	return (alert & INA260_CVRF);
+}
+
+static int ina260_work_buffer(struct iio_dev *indio_dev)
+{
+	/* data buffer needs space for channel data and timestap */
+	unsigned short data[3 + sizeof(s64) / sizeof(short)];
+	struct ina260_chip *chip = iio_priv(indio_dev);
+	int bit, ret, i = 0;
+	s64 time;
+
+	time = iio_get_time_ns(indio_dev);
+
+	/*
+	 * Read current, voltage and power from device
+	 */
+	for_each_set_bit(bit, indio_dev->active_scan_mask,
+			 indio_dev->masklength) {
+		unsigned int val;
+
+		ret = regmap_read(chip->regmap, INA260_CURRENT + bit, &val);
+		if (ret < 0)
+			return ret;
+
+		data[i++] = val;
+	}
+
+	iio_push_to_buffers_with_timestamp(indio_dev, data, time);
+
+	return 0;
+}
+
+static int ina260_capture_thread(void *data)
+{
+	struct iio_dev *indio_dev = data;
+	struct ina260_chip *chip = iio_priv(indio_dev);
+	int sampling_us = SAMPLING_PERIOD(chip);
+	struct timespec64 next, now, delta;
+	s64 delay_us;
+	int ret;
+
+	ktime_get_ts64(&next);
+
+	do {
+		while (1) {
+			/* Check if conversion is ready */
+			ret = ina260_conversion_ready(indio_dev);
+			if (ret < 0)
+				return ret;
+
+			/*
+			 * If the conversion was not yet finished,
+			 * reset the reference timestamp.
+			 */
+			if (ret == 0)
+				ktime_get_ts64(&next);
+			else
+				break;
+		}
+		/* Read the data from sensor and push it to buffers */
+		ret = ina260_work_buffer(indio_dev);
+		if (ret < 0)
+			return ret;
+
+		ktime_get_ts64(&now);
+		/*
+		 * Advance the timestamp for the next poll by one sampling
+		 * interval, and sleep for the remainder (next - now)
+		 * In case "next" has already passed, the interval is added
+		 * multiple times, i.e. samples are dropped.
+		 */
+		do {
+			timespec64_add_ns(&next, 1000 * sampling_us);
+			delta = timespec64_sub(next, now);
+			delay_us = div_s64(timespec64_to_ns(&delta), 1000);
+		} while (delay_us <= 0);
+
+		usleep_range(delay_us, (delay_us * 3) >> 1);
+
+	} while (!kthread_should_stop());
+
+	return 0;
+}
+
+static int ina260_buffer_enable(struct iio_dev *indio_dev)
+{
+	struct ina260_chip *chip = iio_priv(indio_dev);
+	unsigned int sampling_us = SAMPLING_PERIOD(chip);
+	struct task_struct *task;
+
+	task = kthread_create(ina260_capture_thread, (void *)indio_dev,
+			      "%s:%d-%uus", indio_dev->name, indio_dev->id,
+			      sampling_us);
+
+	if (IS_ERR(task))
+		return PTR_ERR(task);
+
+	get_task_struct(task);
+	wake_up_process(task);
+	chip->task = task;
+
+	return 0;
+}
+
+static int ina260_buffer_disable(struct iio_dev *indio_dev)
+{
+	struct ina260_chip *chip = iio_priv(indio_dev);
+
+	if (chip->task) {
+		kthread_stop(chip->task);
+		put_task_struct(chip->task);
+		chip->task = NULL;
+	}
+
+	return 0;
+}
+
+static const struct iio_buffer_setup_ops ina260_setup_ops = {
+	.postenable = &ina260_buffer_enable,
+	.predisable = &ina260_buffer_disable,
+};
+
+static int ina260_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+	struct iio_dev *indio_dev;
+	struct iio_buffer *buffer;
+	struct ina260_chip *chip;
+	enum ina260_ids type = 0;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	chip = iio_priv(indio_dev);
+	i2c_set_clientdata(client, indio_dev);
+
+	chip->regmap = devm_regmap_init_i2c(client, &ina260_regmap_config);
+	if (IS_ERR(chip->regmap)) {
+		dev_err(&client->dev, "failed to allocate register map\n");
+		return PTR_ERR(chip->regmap);
+	}
+
+	mutex_init(&chip->lock);
+
+	indio_dev->modes = INDIO_DIRECT_MODE | INDIO_BUFFER_SOFTWARE;
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->dev.of_node = client->dev.of_node;
+
+	chip->config = &ina260_config[type];
+	ret = regmap_write(chip->regmap, INA260_CONFIG,
+			   chip->config->config_default);
+	if (ret) {
+		dev_err(&client->dev, "Error configuring the device\n");
+		return ret;
+	}
+	indio_dev->channels = ina260_channels;
+	indio_dev->num_channels = ARRAY_SIZE(ina260_channels);
+	indio_dev->info = &ina260_info;
+	indio_dev->name = id->name;
+	indio_dev->setup_ops = &ina260_setup_ops;
+
+	buffer = devm_iio_kfifo_allocate(&indio_dev->dev);
+	if (!buffer)
+		return -ENOMEM;
+
+	iio_device_attach_buffer(indio_dev, buffer);
+
+	return iio_device_register(indio_dev);
+}
+
+static int ina260_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+	struct ina260_chip *chip = iio_priv(indio_dev);
+
+	iio_device_unregister(indio_dev);
+	/* Power down */
+	return regmap_update_bits(chip->regmap, INA260_CONFIG, INA260_MODE_MASK, 0);
+}
+
+static const struct i2c_device_id ina260_id[] = {
+	{"ina260", ina260},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, ina260_id);
+
+static const struct of_device_id ina260_of_match[] = {
+	{
+		.compatible = "ti,ina260",
+		.data = (void *)ina260
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, ina260_of_match);
+
+static struct i2c_driver ina260_driver = {
+	.driver = {
+		.name = "ina260-adc",
+		.of_match_table = ina260_of_match,
+	},
+	.probe = ina260_probe,
+	.remove = ina260_remove,
+	.id_table = ina260_id,
+};
+module_i2c_driver(ina260_driver);
+
+MODULE_AUTHOR("Raviteja Narayanam <raviteja.narayanam@xilinx.com>");
+MODULE_DESCRIPTION("Texas Instruments INA 260 ADC driver");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/ina2xx-adc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/ina2xx-adc.c
@@ -146,6 +146,11 @@
 	int range_vbus; /* Bus voltage maximum in V */
 	int pga_gain_vshunt; /* Shunt voltage PGA gain */
 	bool allow_async_readout;
+	/* data buffer needs space for channel data and timestamp */
+	struct {
+		u16 chan[4];
+		u64 ts __aligned(8);
+	} scan;
 };
 
 static const struct ina2xx_config ina2xx_config[] = {
@@ -738,8 +743,6 @@
 static int ina2xx_work_buffer(struct iio_dev *indio_dev)
 {
 	struct ina2xx_chip_info *chip = iio_priv(indio_dev);
-	/* data buffer needs space for channel data and timestap */
-	unsigned short data[4 + sizeof(s64)/sizeof(short)];
 	int bit, ret, i = 0;
 	s64 time;
 
@@ -758,10 +761,10 @@
 		if (ret < 0)
 			return ret;
 
-		data[i++] = val;
+		chip->scan.chan[i++] = val;
 	}
 
-	iio_push_to_buffers_with_timestamp(indio_dev, data, time);
+	iio_push_to_buffers_with_timestamp(indio_dev, &chip->scan, time);
 
 	return 0;
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/max1027.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/max1027.c
@@ -458,6 +458,14 @@
 		return ret;
 	}
 
+	/* Internal reset */
+	st->reg = MAX1027_RST_REG;
+	ret = spi_write(st->spi, &st->reg, 1);
+	if (ret < 0) {
+		dev_err(&indio_dev->dev, "Failed to reset the ADC\n");
+		return ret;
+	}
+
 	/* Disable averaging */
 	st->reg = MAX1027_AVG_REG;
 	ret = spi_write(st->spi, &st->reg, 1);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/max1118.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/max1118.c
@@ -35,6 +35,11 @@
 	struct spi_device *spi;
 	struct mutex lock;
 	struct regulator *reg;
+	/* Ensure natural alignment of buffer elements */
+	struct {
+		u8 channels[2];
+		s64 ts __aligned(8);
+	} scan;
 
 	u8 data ____cacheline_aligned;
 };
@@ -159,7 +164,6 @@
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct max1118 *adc = iio_priv(indio_dev);
-	u8 data[16] = { }; /* 2x 8-bit ADC data + padding + 8 bytes timestamp */
 	int scan_index;
 	int i = 0;
 
@@ -177,10 +181,10 @@
 			goto out;
 		}
 
-		data[i] = ret;
+		adc->scan.channels[i] = ret;
 		i++;
 	}
-	iio_push_to_buffers_with_timestamp(indio_dev, data,
+	iio_push_to_buffers_with_timestamp(indio_dev, &adc->scan,
 					   iio_get_time_ns(indio_dev));
 out:
 	mutex_unlock(&adc->lock);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/max9611.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/max9611.c
@@ -89,6 +89,12 @@
 #define MAX9611_TEMP_SCALE_NUM		1000000
 #define MAX9611_TEMP_SCALE_DIV		2083
 
+/*
+ * Conversion time is 2 ms (typically) at Ta=25 degreeC
+ * No maximum value is known, so play it safe.
+ */
+#define MAX9611_CONV_TIME_US_RANGE	3000, 3300
+
 struct max9611_dev {
 	struct device *dev;
 	struct i2c_client *i2c_client;
@@ -236,11 +242,9 @@
 		return ret;
 	}
 
-	/*
-	 * need a delay here to make register configuration
-	 * stabilize. 1 msec at least, from empirical testing.
-	 */
-	usleep_range(1000, 2000);
+	/* need a delay here to make register configuration stabilize. */
+
+	usleep_range(MAX9611_CONV_TIME_US_RANGE);
 
 	ret = i2c_smbus_read_word_swapped(max9611->i2c_client, reg_addr);
 	if (ret < 0) {
@@ -507,7 +511,7 @@
 			MAX9611_REG_CTRL2, 0);
 		return ret;
 	}
-	usleep_range(1000, 2000);
+	usleep_range(MAX9611_CONV_TIME_US_RANGE);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/mcp3422.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/mcp3422.c
@@ -95,16 +95,12 @@
 {
 	int ret;
 
-	mutex_lock(&adc->lock);
-
 	ret = i2c_master_send(adc->i2c, &newconfig, 1);
 	if (ret > 0) {
 		adc->config = newconfig;
 		ret = 0;
 	}
 
-	mutex_unlock(&adc->lock);
-
 	return ret;
 }
 
@@ -137,6 +133,8 @@
 	u8 config;
 	u8 req_channel = channel->channel;
 
+	mutex_lock(&adc->lock);
+
 	if (req_channel != MCP3422_CHANNEL(adc->config)) {
 		config = adc->config;
 		config &= ~MCP3422_CHANNEL_MASK;
@@ -144,12 +142,18 @@
 		config &= ~MCP3422_PGA_MASK;
 		config |= MCP3422_PGA_VALUE(adc->pga[req_channel]);
 		ret = mcp3422_update_config(adc, config);
-		if (ret < 0)
+		if (ret < 0) {
+			mutex_unlock(&adc->lock);
 			return ret;
+		}
 		msleep(mcp3422_read_times[MCP3422_SAMPLE_RATE(adc->config)]);
 	}
 
-	return mcp3422_read(adc, value, &config);
+	ret = mcp3422_read(adc, value, &config);
+
+	mutex_unlock(&adc->lock);
+
+	return ret;
 }
 
 static int mcp3422_read_raw(struct iio_dev *iio,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/mcp3911.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/mcp3911.c
@@ -38,8 +38,8 @@
 #define MCP3911_CHANNEL(x)		(MCP3911_REG_CHANNEL0 + x * 3)
 #define MCP3911_OFFCAL(x)		(MCP3911_REG_OFFCAL_CH0 + x * 6)
 
-/* Internal voltage reference in uV */
-#define MCP3911_INT_VREF_UV		1200000
+/* Internal voltage reference in mV */
+#define MCP3911_INT_VREF_MV		1200
 
 #define MCP3911_REG_READ(reg, id)	((((reg) << 1) | ((id) << 5) | (1 << 0)) & 0xff)
 #define MCP3911_REG_WRITE(reg, id)	((((reg) << 1) | ((id) << 5) | (0 << 0)) & 0xff)
@@ -111,6 +111,8 @@
 		if (ret)
 			goto out;
 
+		*val = sign_extend32(*val, 23);
+
 		ret = IIO_VAL_INT;
 		break;
 
@@ -135,11 +137,18 @@
 
 			*val = ret / 1000;
 		} else {
-			*val = MCP3911_INT_VREF_UV;
+			*val = MCP3911_INT_VREF_MV;
 		}
 
-		*val2 = 24;
-		ret = IIO_VAL_FRACTIONAL_LOG2;
+		/*
+		 * For 24bit Conversion
+		 * Raw = ((Voltage)/(Vref) * 2^23 * Gain * 1.5
+		 * Voltage = Raw * (Vref)/(2^23 * Gain * 1.5)
+		 */
+
+		/* val2 = (2^23 * 1.5) */
+		*val2 = 12582912;
+		ret = IIO_VAL_FRACTIONAL;
 		break;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/men_z188_adc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/men_z188_adc.c
@@ -103,6 +103,7 @@
 	struct z188_adc *adc;
 	struct iio_dev *indio_dev;
 	struct resource *mem;
+	int ret;
 
 	indio_dev = devm_iio_device_alloc(&dev->dev, sizeof(struct z188_adc));
 	if (!indio_dev)
@@ -129,8 +130,14 @@
 	adc->mem = mem;
 	mcb_set_drvdata(dev, indio_dev);
 
-	return iio_device_register(indio_dev);
+	ret = iio_device_register(indio_dev);
+	if (ret)
+		goto err_unmap;
 
+	return 0;
+
+err_unmap:
+	iounmap(adc->base);
 err:
 	mcb_release_mem(mem);
 	return -ENXIO;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/meson_saradc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/meson_saradc.c
@@ -71,7 +71,7 @@
 	#define MESON_SAR_ADC_REG3_PANEL_DETECT_COUNT_MASK	GENMASK(20, 18)
 	#define MESON_SAR_ADC_REG3_PANEL_DETECT_FILTER_TB_MASK	GENMASK(17, 16)
 	#define MESON_SAR_ADC_REG3_ADC_CLK_DIV_SHIFT		10
-	#define MESON_SAR_ADC_REG3_ADC_CLK_DIV_WIDTH		5
+	#define MESON_SAR_ADC_REG3_ADC_CLK_DIV_WIDTH		6
 	#define MESON_SAR_ADC_REG3_BLOCK_DLY_SEL_MASK		GENMASK(9, 8)
 	#define MESON_SAR_ADC_REG3_BLOCK_DLY_MASK		GENMASK(7, 0)
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/mt6577_auxadc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/mt6577_auxadc.c
@@ -9,9 +9,9 @@
 #include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
+#include <linux/mod_devicetable.h>
 #include <linux/platform_device.h>
+#include <linux/property.h>
 #include <linux/iopoll.h>
 #include <linux/io.h>
 #include <linux/iio/iio.h>
@@ -82,6 +82,10 @@
 	MT6577_AUXADC_CHANNEL(15),
 };
 
+/* For Voltage calculation */
+#define VOLTAGE_FULL_RANGE  1500	/* VA voltage */
+#define AUXADC_PRECISE      4096	/* 12 bits */
+
 static int mt_auxadc_get_cali_data(int rawdata, bool enable_cali)
 {
 	return rawdata;
@@ -191,6 +195,10 @@
 		}
 		if (adc_dev->dev_comp->sample_data_cali)
 			*val = mt_auxadc_get_cali_data(*val, true);
+
+		/* Convert adc raw data to voltage: 0 - 1500 mV */
+		*val = *val * VOLTAGE_FULL_RANGE / AUXADC_PRECISE;
+
 		return IIO_VAL_INT;
 
 	default:
@@ -279,6 +287,8 @@
 		goto err_disable_clk;
 	}
 
+	adc_dev->dev_comp = device_get_match_data(&pdev->dev);
+
 	mutex_init(&adc_dev->lock);
 
 	mt6577_auxadc_mod_reg(adc_dev->reg_base + MT6577_AUXADC_MISC,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/mxs-lradc-adc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/mxs-lradc-adc.c
@@ -115,7 +115,8 @@
 	struct device		*dev;
 
 	void __iomem		*base;
-	u32			buffer[10];
+	/* Maximum of 8 channels + 8 byte ts */
+	u32			buffer[10] __aligned(8);
 	struct iio_trigger	*trig;
 	struct completion	completion;
 	spinlock_t		lock;
@@ -759,13 +760,13 @@
 
 	ret = mxs_lradc_adc_trigger_init(iio);
 	if (ret)
-		goto err_trig;
+		return ret;
 
 	ret = iio_triggered_buffer_setup(iio, &iio_pollfunc_store_time,
 					 &mxs_lradc_adc_trigger_handler,
 					 &mxs_lradc_adc_buffer_ops);
 	if (ret)
-		return ret;
+		goto err_trig;
 
 	adc->vref_mv = mxs_lradc_adc_vref_mv[lradc->soc];
 
@@ -803,9 +804,9 @@
 
 err_dev:
 	mxs_lradc_adc_hw_stop(adc);
-	mxs_lradc_adc_trigger_remove(iio);
-err_trig:
 	iio_triggered_buffer_cleanup(iio);
+err_trig:
+	mxs_lradc_adc_trigger_remove(iio);
 	return ret;
 }
 
@@ -816,8 +817,8 @@
 
 	iio_device_unregister(iio);
 	mxs_lradc_adc_hw_stop(adc);
-	mxs_lradc_adc_trigger_remove(iio);
 	iio_triggered_buffer_cleanup(iio);
+	mxs_lradc_adc_trigger_remove(iio);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/palmas_gpadc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/palmas_gpadc.c
@@ -630,7 +630,7 @@
 
 static int palmas_gpadc_remove(struct platform_device *pdev)
 {
-	struct iio_dev *indio_dev = dev_to_iio_dev(&pdev->dev);
+	struct iio_dev *indio_dev = dev_get_drvdata(&pdev->dev);
 	struct palmas_gpadc *adc = iio_priv(indio_dev);
 
 	if (adc->wakeup1_enable || adc->wakeup2_enable)
@@ -656,8 +656,8 @@
 
 	adc_period = adc->auto_conversion_period;
 	for (i = 0; i < 16; ++i) {
-		if (((1000 * (1 << i)) / 32) < adc_period)
-			continue;
+		if (((1000 * (1 << i)) / 32) >= adc_period)
+			break;
 	}
 	if (i > 0)
 		i--;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/qcom-spmi-adc5.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/qcom-spmi-adc5.c
@@ -786,7 +786,7 @@
 
 static struct platform_driver adc5_driver = {
 	.driver = {
-		.name = "qcom-spmi-adc5.c",
+		.name = "qcom-spmi-adc5",
 		.of_match_table = adc5_match_table,
 	},
 	.probe = adc5_probe,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/qcom-spmi-vadc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/qcom-spmi-vadc.c
@@ -598,7 +598,7 @@
 	VADC_CHAN_NO_SCALE(P_MUX16_1_3, 1)
 
 	VADC_CHAN_NO_SCALE(LR_MUX1_BAT_THERM, 0)
-	VADC_CHAN_NO_SCALE(LR_MUX2_BAT_ID, 0)
+	VADC_CHAN_VOLT(LR_MUX2_BAT_ID, 0, SCALE_DEFAULT)
 	VADC_CHAN_NO_SCALE(LR_MUX3_XO_THERM, 0)
 	VADC_CHAN_NO_SCALE(LR_MUX4_AMUX_THM1, 0)
 	VADC_CHAN_NO_SCALE(LR_MUX5_AMUX_THM2, 0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/rcar-gyroadc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/rcar-gyroadc.c
@@ -357,7 +357,7 @@
 			num_channels = ARRAY_SIZE(rcar_gyroadc_iio_channels_3);
 			break;
 		default:
-			return -EINVAL;
+			goto err_e_inval;
 		}
 
 		/*
@@ -374,7 +374,7 @@
 				dev_err(dev,
 					"Failed to get child reg property of ADC \"%pOFn\".\n",
 					child);
-				return ret;
+				goto err_of_node_put;
 			}
 
 			/* Channel number is too high. */
@@ -382,7 +382,7 @@
 				dev_err(dev,
 					"Only %i channels supported with %pOFn, but reg = <%i>.\n",
 					num_channels, child, reg);
-				return -EINVAL;
+				goto err_e_inval;
 			}
 		}
 
@@ -391,7 +391,7 @@
 			dev_err(dev,
 				"Channel %i uses different ADC mode than the rest.\n",
 				reg);
-			return -EINVAL;
+			goto err_e_inval;
 		}
 
 		/* Channel is valid, grab the regulator. */
@@ -401,7 +401,8 @@
 		if (IS_ERR(vref)) {
 			dev_dbg(dev, "Channel %i 'vref' supply not connected.\n",
 				reg);
-			return PTR_ERR(vref);
+			ret = PTR_ERR(vref);
+			goto err_of_node_put;
 		}
 
 		priv->vref[reg] = vref;
@@ -425,8 +426,10 @@
 		 * attached to the GyroADC at a time, so if we found it,
 		 * we can stop parsing here.
 		 */
-		if (childmode == RCAR_GYROADC_MODE_SELECT_1_MB88101A)
+		if (childmode == RCAR_GYROADC_MODE_SELECT_1_MB88101A) {
+			of_node_put(child);
 			break;
+		}
 	}
 
 	if (first) {
@@ -435,6 +438,12 @@
 	}
 
 	return 0;
+
+err_e_inval:
+	ret = -EINVAL;
+err_of_node_put:
+	of_node_put(child);
+	return ret;
 }
 
 static void rcar_gyroadc_deinit_supplies(struct iio_dev *indio_dev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/rockchip_saradc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/rockchip_saradc.c
@@ -372,7 +372,7 @@
 
 	ret = clk_prepare_enable(info->clk);
 	if (ret)
-		return ret;
+		clk_disable_unprepare(info->pclk);
 
 	return ret;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/sc27xx_adc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/sc27xx_adc.c
@@ -36,8 +36,8 @@
 
 /* Bits and mask definition for SC27XX_ADC_CH_CFG register */
 #define SC27XX_ADC_CHN_ID_MASK		GENMASK(4, 0)
-#define SC27XX_ADC_SCALE_MASK		GENMASK(10, 8)
-#define SC27XX_ADC_SCALE_SHIFT		8
+#define SC27XX_ADC_SCALE_MASK		GENMASK(10, 9)
+#define SC27XX_ADC_SCALE_SHIFT		9
 
 /* Bits definitions for SC27XX_ADC_INT_EN registers */
 #define SC27XX_ADC_IRQ_EN		BIT(0)
@@ -103,14 +103,14 @@
 	100, 341,
 };
 
-static const struct sc27xx_adc_linear_graph big_scale_graph_calib = {
-	4200, 856,
-	3600, 733,
+static const struct sc27xx_adc_linear_graph sc2731_big_scale_graph_calib = {
+	4200, 850,
+	3600, 728,
 };
 
-static const struct sc27xx_adc_linear_graph small_scale_graph_calib = {
-	1000, 833,
-	100, 80,
+static const struct sc27xx_adc_linear_graph sc2731_small_scale_graph_calib = {
+	1000, 838,
+	100, 84,
 };
 
 static int sc27xx_adc_get_calib_data(u32 calib_data, int calib_adc)
@@ -130,11 +130,11 @@
 	size_t len;
 
 	if (big_scale) {
-		calib_graph = &big_scale_graph_calib;
+		calib_graph = &sc2731_big_scale_graph_calib;
 		graph = &big_scale_graph;
 		cell_name = "big_scale_calib";
 	} else {
-		calib_graph = &small_scale_graph_calib;
+		calib_graph = &sc2731_small_scale_graph_calib;
 		graph = &small_scale_graph;
 		cell_name = "small_scale_calib";
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/stm32-adc-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/stm32-adc-core.c
@@ -65,12 +65,14 @@
  * @clk_sel:	clock selection routine
  * @max_clk_rate_hz: maximum analog clock rate (Hz, from datasheet)
  * @has_syscfg: SYSCFG capability flags
+ * @num_irqs:	number of interrupt lines
  */
 struct stm32_adc_priv_cfg {
 	const struct stm32_adc_common_regs *regs;
 	int (*clk_sel)(struct platform_device *, struct stm32_adc_priv *);
 	u32 max_clk_rate_hz;
 	unsigned int has_syscfg;
+	unsigned int num_irqs;
 };
 
 /**
@@ -372,21 +374,15 @@
 	struct device_node *np = pdev->dev.of_node;
 	unsigned int i;
 
-	for (i = 0; i < STM32_ADC_MAX_ADCS; i++) {
+	/*
+	 * Interrupt(s) must be provided, depending on the compatible:
+	 * - stm32f4/h7 shares a common interrupt line.
+	 * - stm32mp1, has one line per ADC
+	 */
+	for (i = 0; i < priv->cfg->num_irqs; i++) {
 		priv->irq[i] = platform_get_irq(pdev, i);
-		if (priv->irq[i] < 0) {
-			/*
-			 * At least one interrupt must be provided, make others
-			 * optional:
-			 * - stm32f4/h7 shares a common interrupt.
-			 * - stm32mp1, has one line per ADC (either for ADC1,
-			 *   ADC2 or both).
-			 */
-			if (i && priv->irq[i] == -ENXIO)
-				continue;
-
+		if (priv->irq[i] < 0)
 			return priv->irq[i];
-		}
 	}
 
 	priv->domain = irq_domain_add_simple(np, STM32_ADC_MAX_ADCS, 0,
@@ -397,9 +393,7 @@
 		return -ENOMEM;
 	}
 
-	for (i = 0; i < STM32_ADC_MAX_ADCS; i++) {
-		if (priv->irq[i] < 0)
-			continue;
+	for (i = 0; i < priv->cfg->num_irqs; i++) {
 		irq_set_chained_handler(priv->irq[i], stm32_adc_irq_handler);
 		irq_set_handler_data(priv->irq[i], priv);
 	}
@@ -417,11 +411,8 @@
 		irq_dispose_mapping(irq_find_mapping(priv->domain, hwirq));
 	irq_domain_remove(priv->domain);
 
-	for (i = 0; i < STM32_ADC_MAX_ADCS; i++) {
-		if (priv->irq[i] < 0)
-			continue;
+	for (i = 0; i < priv->cfg->num_irqs; i++)
 		irq_set_chained_handler(priv->irq[i], NULL);
-	}
 }
 
 static int stm32_adc_core_switches_supply_en(struct stm32_adc_priv *priv,
@@ -789,6 +780,13 @@
 {
 	return stm32_adc_core_hw_start(dev);
 }
+
+static int stm32_adc_core_runtime_idle(struct device *dev)
+{
+	pm_runtime_mark_last_busy(dev);
+
+	return 0;
+}
 #endif
 
 static const struct dev_pm_ops stm32_adc_core_pm_ops = {
@@ -796,13 +794,14 @@
 				pm_runtime_force_resume)
 	SET_RUNTIME_PM_OPS(stm32_adc_core_runtime_suspend,
 			   stm32_adc_core_runtime_resume,
-			   NULL)
+			   stm32_adc_core_runtime_idle)
 };
 
 static const struct stm32_adc_priv_cfg stm32f4_adc_priv_cfg = {
 	.regs = &stm32f4_adc_common_regs,
 	.clk_sel = stm32f4_adc_clk_sel,
 	.max_clk_rate_hz = 36000000,
+	.num_irqs = 1,
 };
 
 static const struct stm32_adc_priv_cfg stm32h7_adc_priv_cfg = {
@@ -810,13 +809,15 @@
 	.clk_sel = stm32h7_adc_clk_sel,
 	.max_clk_rate_hz = 36000000,
 	.has_syscfg = HAS_VBOOSTER,
+	.num_irqs = 1,
 };
 
 static const struct stm32_adc_priv_cfg stm32mp1_adc_priv_cfg = {
 	.regs = &stm32h7_adc_common_regs,
 	.clk_sel = stm32h7_adc_clk_sel,
-	.max_clk_rate_hz = 40000000,
+	.max_clk_rate_hz = 36000000,
 	.has_syscfg = HAS_VBOOSTER | HAS_ANASWVDD,
+	.num_irqs = 2,
 };
 
 static const struct of_device_id stm32_adc_of_match[] = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/stm32-adc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/stm32-adc.c
@@ -933,6 +933,7 @@
 
 static void stm32h7_adc_unprepare(struct stm32_adc *adc)
 {
+	stm32_adc_writel(adc, STM32H7_ADC_PCSEL, 0);
 	stm32h7_adc_disable(adc);
 	stm32h7_adc_enter_pwr_down(adc);
 }
@@ -1367,8 +1368,30 @@
 static void stm32_adc_dma_buffer_done(void *data)
 {
 	struct iio_dev *indio_dev = data;
+	struct stm32_adc *adc = iio_priv(indio_dev);
+	int residue = stm32_adc_dma_residue(adc);
+
+	/*
+	 * In DMA mode the trigger services of IIO are not used
+	 * (e.g. no call to iio_trigger_poll).
+	 * Calling irq handler associated to the hardware trigger is not
+	 * relevant as the conversions have already been done. Data
+	 * transfers are performed directly in DMA callback instead.
+	 * This implementation avoids to call trigger irq handler that
+	 * may sleep, in an atomic context (DMA irq handler context).
+	 */
+	dev_dbg(&indio_dev->dev, "%s bufi=%d\n", __func__, adc->bufi);
+
+	while (residue >= indio_dev->scan_bytes) {
+		u16 *buffer = (u16 *)&adc->rx_buf[adc->bufi];
 
-	iio_trigger_poll_chained(indio_dev->trig);
+		iio_push_to_buffers(indio_dev, buffer);
+
+		residue -= indio_dev->scan_bytes;
+		adc->bufi += indio_dev->scan_bytes;
+		if (adc->bufi >= adc->rx_buf_sz)
+			adc->bufi = 0;
+	}
 }
 
 static int stm32_adc_dma_start(struct iio_dev *indio_dev)
@@ -1735,15 +1758,27 @@
 	return 0;
 }
 
-static int stm32_adc_dma_request(struct iio_dev *indio_dev)
+static int stm32_adc_dma_request(struct device *dev, struct iio_dev *indio_dev)
 {
 	struct stm32_adc *adc = iio_priv(indio_dev);
 	struct dma_slave_config config;
 	int ret;
 
-	adc->dma_chan = dma_request_slave_channel(&indio_dev->dev, "rx");
-	if (!adc->dma_chan)
+	adc->dma_chan = dma_request_chan(dev, "rx");
+	if (IS_ERR(adc->dma_chan)) {
+		ret = PTR_ERR(adc->dma_chan);
+		if (ret != -ENODEV) {
+			if (ret != -EPROBE_DEFER)
+				dev_err(dev,
+					"DMA channel request failed with %d\n",
+					ret);
+			return ret;
+		}
+
+		/* DMA is optional: fall back to IRQ mode */
+		adc->dma_chan = NULL;
 		return 0;
+	}
 
 	adc->rx_buf = dma_alloc_coherent(adc->dma_chan->device->dev,
 					 STM32_DMA_BUFFER_SIZE,
@@ -1778,6 +1813,7 @@
 {
 	struct iio_dev *indio_dev;
 	struct device *dev = &pdev->dev;
+	irqreturn_t (*handler)(int irq, void *p) = NULL;
 	struct stm32_adc *adc;
 	int ret;
 
@@ -1839,13 +1875,15 @@
 	if (ret < 0)
 		return ret;
 
-	ret = stm32_adc_dma_request(indio_dev);
+	ret = stm32_adc_dma_request(dev, indio_dev);
 	if (ret < 0)
 		return ret;
 
+	if (!adc->dma_chan)
+		handler = &stm32_adc_trigger_handler;
+
 	ret = iio_triggered_buffer_setup(indio_dev,
-					 &iio_pollfunc_store_time,
-					 &stm32_adc_trigger_handler,
+					 &iio_pollfunc_store_time, handler,
 					 &stm32_adc_buffer_setup_ops);
 	if (ret) {
 		dev_err(&pdev->dev, "buffer setup failed\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/stm32-dfsdm-adc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/stm32-dfsdm-adc.c
@@ -62,7 +62,7 @@
 
 struct stm32_dfsdm_dev_data {
 	int type;
-	int (*init)(struct iio_dev *indio_dev);
+	int (*init)(struct device *dev, struct iio_dev *indio_dev);
 	unsigned int num_channels;
 	const struct regmap_config *regmap_cfg;
 };
@@ -842,31 +842,6 @@
 	}
 }
 
-static irqreturn_t stm32_dfsdm_adc_trigger_handler(int irq, void *p)
-{
-	struct iio_poll_func *pf = p;
-	struct iio_dev *indio_dev = pf->indio_dev;
-	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
-	int available = stm32_dfsdm_adc_dma_residue(adc);
-
-	while (available >= indio_dev->scan_bytes) {
-		s32 *buffer = (s32 *)&adc->rx_buf[adc->bufi];
-
-		stm32_dfsdm_process_data(adc, buffer);
-
-		iio_push_to_buffers_with_timestamp(indio_dev, buffer,
-						   pf->timestamp);
-		available -= indio_dev->scan_bytes;
-		adc->bufi += indio_dev->scan_bytes;
-		if (adc->bufi >= adc->buf_sz)
-			adc->bufi = 0;
-	}
-
-	iio_trigger_notify_done(indio_dev->trig);
-
-	return IRQ_HANDLED;
-}
-
 static void stm32_dfsdm_dma_buffer_done(void *data)
 {
 	struct iio_dev *indio_dev = data;
@@ -874,11 +849,6 @@
 	int available = stm32_dfsdm_adc_dma_residue(adc);
 	size_t old_pos;
 
-	if (indio_dev->currentmode & INDIO_BUFFER_TRIGGERED) {
-		iio_trigger_poll_chained(indio_dev->trig);
-		return;
-	}
-
 	/*
 	 * FIXME: In Kernel interface does not support cyclic DMA buffer,and
 	 * offers only an interface to push data samples per samples.
@@ -906,7 +876,15 @@
 			adc->bufi = 0;
 			old_pos = 0;
 		}
-		/* regular iio buffer without trigger */
+		/*
+		 * In DMA mode the trigger services of IIO are not used
+		 * (e.g. no call to iio_trigger_poll).
+		 * Calling irq handler associated to the hardware trigger is not
+		 * relevant as the conversions have already been done. Data
+		 * transfers are performed directly in DMA callback instead.
+		 * This implementation avoids to call trigger irq handler that
+		 * may sleep, in an atomic context (DMA irq handler context).
+		 */
 		if (adc->dev_data->type == DFSDM_IIO)
 			iio_push_to_buffers(indio_dev, buffer);
 	}
@@ -1204,6 +1182,8 @@
 
 	stm32_dfsdm_stop_conv(adc);
 
+	stm32_dfsdm_process_data(adc, res);
+
 stop_dfsdm:
 	stm32_dfsdm_stop_dfsdm(adc->dfsdm);
 
@@ -1379,13 +1359,18 @@
 	}
 }
 
-static int stm32_dfsdm_dma_request(struct iio_dev *indio_dev)
+static int stm32_dfsdm_dma_request(struct device *dev,
+				   struct iio_dev *indio_dev)
 {
 	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
 
-	adc->dma_chan = dma_request_slave_channel(&indio_dev->dev, "rx");
-	if (!adc->dma_chan)
-		return -EINVAL;
+	adc->dma_chan = dma_request_chan(dev, "rx");
+	if (IS_ERR(adc->dma_chan)) {
+		int ret = PTR_ERR(adc->dma_chan);
+
+		adc->dma_chan = NULL;
+		return ret;
+	}
 
 	adc->rx_buf = dma_alloc_coherent(adc->dma_chan->device->dev,
 					 DFSDM_DMA_BUFFER_SIZE,
@@ -1435,7 +1420,7 @@
 					  &adc->dfsdm->ch_list[ch->channel]);
 }
 
-static int stm32_dfsdm_audio_init(struct iio_dev *indio_dev)
+static int stm32_dfsdm_audio_init(struct device *dev, struct iio_dev *indio_dev)
 {
 	struct iio_chan_spec *ch;
 	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
@@ -1462,10 +1447,10 @@
 	indio_dev->num_channels = 1;
 	indio_dev->channels = ch;
 
-	return stm32_dfsdm_dma_request(indio_dev);
+	return stm32_dfsdm_dma_request(dev, indio_dev);
 }
 
-static int stm32_dfsdm_adc_init(struct iio_dev *indio_dev)
+static int stm32_dfsdm_adc_init(struct device *dev, struct iio_dev *indio_dev)
 {
 	struct iio_chan_spec *ch;
 	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
@@ -1509,14 +1494,22 @@
 	init_completion(&adc->completion);
 
 	/* Optionally request DMA */
-	if (stm32_dfsdm_dma_request(indio_dev)) {
-		dev_dbg(&indio_dev->dev, "No DMA support\n");
+	ret = stm32_dfsdm_dma_request(dev, indio_dev);
+	if (ret) {
+		if (ret != -ENODEV) {
+			if (ret != -EPROBE_DEFER)
+				dev_err(dev,
+					"DMA channel request failed with %d\n",
+					ret);
+			return ret;
+		}
+
+		dev_dbg(dev, "No DMA support\n");
 		return 0;
 	}
 
 	ret = iio_triggered_buffer_setup(indio_dev,
-					 &iio_pollfunc_store_time,
-					 &stm32_dfsdm_adc_trigger_handler,
+					 &iio_pollfunc_store_time, NULL,
 					 &stm32_dfsdm_buffer_setup_ops);
 	if (ret) {
 		stm32_dfsdm_dma_release(indio_dev);
@@ -1551,6 +1544,7 @@
 	},
 	{}
 };
+MODULE_DEVICE_TABLE(of, stm32_dfsdm_adc_match);
 
 static int stm32_dfsdm_adc_probe(struct platform_device *pdev)
 {
@@ -1624,7 +1618,7 @@
 		adc->dfsdm->fl_list[adc->fl_id].sync_mode = val;
 
 	adc->dev_data = dev_data;
-	ret = dev_data->init(iio);
+	ret = dev_data->init(dev, iio);
 	if (ret < 0)
 		return ret;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/stmpe-adc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/stmpe-adc.c
@@ -61,7 +61,7 @@
 static int stmpe_read_voltage(struct stmpe_adc *info,
 		struct iio_chan_spec const *chan, int *val)
 {
-	long ret;
+	unsigned long ret;
 
 	mutex_lock(&info->lock);
 
@@ -79,7 +79,7 @@
 
 	ret = wait_for_completion_timeout(&info->completion, STMPE_ADC_TIMEOUT);
 
-	if (ret <= 0) {
+	if (ret == 0) {
 		stmpe_reg_write(info->stmpe, STMPE_REG_ADC_INT_STA,
 				STMPE_ADC_CH(info->channel));
 		mutex_unlock(&info->lock);
@@ -96,7 +96,7 @@
 static int stmpe_read_temp(struct stmpe_adc *info,
 		struct iio_chan_spec const *chan, int *val)
 {
-	long ret;
+	unsigned long ret;
 
 	mutex_lock(&info->lock);
 
@@ -114,7 +114,7 @@
 
 	ret = wait_for_completion_timeout(&info->completion, STMPE_ADC_TIMEOUT);
 
-	if (ret <= 0) {
+	if (ret == 0) {
 		mutex_unlock(&info->lock);
 		return -ETIMEDOUT;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/ti-adc081c.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/ti-adc081c.c
@@ -33,6 +33,12 @@
 
 	/* 8, 10 or 12 */
 	int bits;
+
+	/* Ensure natural alignment of buffer elements */
+	struct {
+		u16 channel;
+		s64 ts __aligned(8);
+	} scan;
 };
 
 #define REG_CONV_RES 0x00
@@ -128,14 +134,13 @@
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct adc081c *data = iio_priv(indio_dev);
-	u16 buf[8]; /* 2 bytes data + 6 bytes padding + 8 bytes timestamp */
 	int ret;
 
 	ret = i2c_smbus_read_word_swapped(data->i2c, REG_CONV_RES);
 	if (ret < 0)
 		goto out;
-	buf[0] = ret;
-	iio_push_to_buffers_with_timestamp(indio_dev, buf,
+	data->scan.channel = ret;
+	iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
 					   iio_get_time_ns(indio_dev));
 out:
 	iio_trigger_notify_done(indio_dev->trig);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/ti-adc0832.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/ti-adc0832.c
@@ -28,6 +28,12 @@
 	struct regulator *reg;
 	struct mutex lock;
 	u8 mux_bits;
+	/*
+	 * Max size needed: 16x 1 byte ADC data + 8 bytes timestamp
+	 * May be shorter if not all channels are enabled subject
+	 * to the timestamp remaining 8 byte aligned.
+	 */
+	u8 data[24] __aligned(8);
 
 	u8 tx_buf[2] ____cacheline_aligned;
 	u8 rx_buf[2];
@@ -199,7 +205,6 @@
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct adc0832 *adc = iio_priv(indio_dev);
-	u8 data[24] = { }; /* 16x 1 byte ADC data + 8 bytes timestamp */
 	int scan_index;
 	int i = 0;
 
@@ -217,10 +222,10 @@
 			goto out;
 		}
 
-		data[i] = ret;
+		adc->data[i] = ret;
 		i++;
 	}
-	iio_push_to_buffers_with_timestamp(indio_dev, data,
+	iio_push_to_buffers_with_timestamp(indio_dev, adc->data,
 					   iio_get_time_ns(indio_dev));
 out:
 	mutex_unlock(&adc->lock);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/ti-adc084s021.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/ti-adc084s021.c
@@ -25,6 +25,11 @@
 	struct spi_transfer spi_trans;
 	struct regulator *reg;
 	struct mutex lock;
+	/* Buffer used to align data */
+	struct {
+		__be16 channels[4];
+		s64 ts __aligned(8);
+	} scan;
 	/*
 	 * DMA (thus cache coherency maintenance) requires the
 	 * transfer buffers to live in their own cache line.
@@ -140,14 +145,13 @@
 	struct iio_poll_func *pf = pollfunc;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct adc084s021 *adc = iio_priv(indio_dev);
-	__be16 data[8] = {0}; /* 4 * 16-bit words of data + 8 bytes timestamp */
 
 	mutex_lock(&adc->lock);
 
-	if (adc084s021_adc_conversion(adc, &data) < 0)
+	if (adc084s021_adc_conversion(adc, adc->scan.channels) < 0)
 		dev_err(&adc->spi->dev, "Failed to read data\n");
 
-	iio_push_to_buffers_with_timestamp(indio_dev, data,
+	iio_push_to_buffers_with_timestamp(indio_dev, &adc->scan,
 					   iio_get_time_ns(indio_dev));
 	mutex_unlock(&adc->lock);
 	iio_trigger_notify_done(indio_dev->trig);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/ti-adc12138.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/ti-adc12138.c
@@ -47,6 +47,12 @@
 	struct completion complete;
 	/* The number of cclk periods for the S/H's acquisition time */
 	unsigned int acquisition_time;
+	/*
+	 * Maximum size needed: 16x 2 bytes ADC data + 8 bytes timestamp.
+	 * Less may be need if not all channels are enabled, as long as
+	 * the 8 byte alignment of the timestamp is maintained.
+	 */
+	__be16 data[20] __aligned(8);
 
 	u8 tx_buf[2] ____cacheline_aligned;
 	u8 rx_buf[2];
@@ -329,7 +335,6 @@
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct adc12138 *adc = iio_priv(indio_dev);
-	__be16 data[20] = { }; /* 16x 2 bytes ADC data + 8 bytes timestamp */
 	__be16 trash;
 	int ret;
 	int scan_index;
@@ -345,7 +350,7 @@
 		reinit_completion(&adc->complete);
 
 		ret = adc12138_start_and_read_conv(adc, scan_chan,
-						   i ? &data[i - 1] : &trash);
+					i ? &adc->data[i - 1] : &trash);
 		if (ret) {
 			dev_warn(&adc->spi->dev,
 				 "failed to start conversion\n");
@@ -362,7 +367,7 @@
 	}
 
 	if (i) {
-		ret = adc12138_read_conv_data(adc, &data[i - 1]);
+		ret = adc12138_read_conv_data(adc, &adc->data[i - 1]);
 		if (ret) {
 			dev_warn(&adc->spi->dev,
 				 "failed to get conversion data\n");
@@ -370,7 +375,7 @@
 		}
 	}
 
-	iio_push_to_buffers_with_timestamp(indio_dev, data,
+	iio_push_to_buffers_with_timestamp(indio_dev, adc->data,
 					   iio_get_time_ns(indio_dev));
 out:
 	mutex_unlock(&adc->lock);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/ti-adc128s052.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/ti-adc128s052.c
@@ -172,7 +172,13 @@
 	mutex_init(&adc->lock);
 
 	ret = iio_device_register(indio_dev);
+	if (ret)
+		goto err_disable_regulator;
 
+	return 0;
+
+err_disable_regulator:
+	regulator_disable(adc->reg);
 	return ret;
 }
 
@@ -188,13 +194,13 @@
 }
 
 static const struct of_device_id adc128_of_match[] = {
-	{ .compatible = "ti,adc128s052", },
-	{ .compatible = "ti,adc122s021", },
-	{ .compatible = "ti,adc122s051", },
-	{ .compatible = "ti,adc122s101", },
-	{ .compatible = "ti,adc124s021", },
-	{ .compatible = "ti,adc124s051", },
-	{ .compatible = "ti,adc124s101", },
+	{ .compatible = "ti,adc128s052", .data = (void*)0L, },
+	{ .compatible = "ti,adc122s021", .data = (void*)1L, },
+	{ .compatible = "ti,adc122s051", .data = (void*)1L, },
+	{ .compatible = "ti,adc122s101", .data = (void*)1L, },
+	{ .compatible = "ti,adc124s021", .data = (void*)2L, },
+	{ .compatible = "ti,adc124s051", .data = (void*)2L, },
+	{ .compatible = "ti,adc124s101", .data = (void*)2L, },
 	{ /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, adc128_of_match);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/ti-ads1015.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/ti-ads1015.c
@@ -309,6 +309,7 @@
 	IIO_CHAN_SOFT_TIMESTAMP(ADS1015_TIMESTAMP),
 };
 
+#ifdef CONFIG_PM
 static int ads1015_set_power_state(struct ads1015_data *data, bool on)
 {
 	int ret;
@@ -326,6 +327,15 @@
 	return ret < 0 ? ret : 0;
 }
 
+#else /* !CONFIG_PM */
+
+static int ads1015_set_power_state(struct ads1015_data *data, bool on)
+{
+	return 0;
+}
+
+#endif /* !CONFIG_PM */
+
 static
 int ads1015_get_adc_result(struct ads1015_data *data, int chan, int *val)
 {
@@ -378,10 +388,14 @@
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct ads1015_data *data = iio_priv(indio_dev);
-	s16 buf[8]; /* 1x s16 ADC val + 3x s16 padding +  4x s16 timestamp */
+	/* Ensure natural alignment of timestamp */
+	struct {
+		s16 chan;
+		s64 timestamp __aligned(8);
+	} scan;
 	int chan, ret, res;
 
-	memset(buf, 0, sizeof(buf));
+	memset(&scan, 0, sizeof(scan));
 
 	mutex_lock(&data->lock);
 	chan = find_first_bit(indio_dev->active_scan_mask,
@@ -392,10 +406,10 @@
 		goto err;
 	}
 
-	buf[0] = res;
+	scan.chan = res;
 	mutex_unlock(&data->lock);
 
-	iio_push_to_buffers_with_timestamp(indio_dev, buf,
+	iio_push_to_buffers_with_timestamp(indio_dev, &scan,
 					   iio_get_time_ns(indio_dev));
 
 err:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/ti-ads124s08.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/ti-ads124s08.c
@@ -97,6 +97,14 @@
 	struct gpio_desc *reset_gpio;
 	struct spi_device *spi;
 	struct mutex lock;
+	/*
+	 * Used to correctly align data.
+	 * Ensure timestamp is naturally aligned.
+	 * Note that the full buffer length may not be needed if not
+	 * all channels are enabled, as long as the alignment of the
+	 * timestamp is maintained.
+	 */
+	u32 buffer[ADS124S08_MAX_CHANNELS + sizeof(s64)/sizeof(u32)] __aligned(8);
 	u8 data[5] ____cacheline_aligned;
 };
 
@@ -174,9 +182,9 @@
 	struct ads124s_private *priv = iio_priv(indio_dev);
 
 	if (priv->reset_gpio) {
-		gpiod_set_value(priv->reset_gpio, 0);
+		gpiod_set_value_cansleep(priv->reset_gpio, 0);
 		udelay(200);
-		gpiod_set_value(priv->reset_gpio, 1);
+		gpiod_set_value_cansleep(priv->reset_gpio, 1);
 	} else {
 		return ads124s_write_cmd(indio_dev, ADS124S08_CMD_RESET);
 	}
@@ -270,7 +278,6 @@
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct ads124s_private *priv = iio_priv(indio_dev);
-	u32 buffer[ADS124S08_MAX_CHANNELS + sizeof(s64)/sizeof(u16)];
 	int scan_index, j = 0;
 	int ret;
 
@@ -285,7 +292,7 @@
 		if (ret)
 			dev_err(&priv->spi->dev, "Start ADC conversions failed\n");
 
-		buffer[j] = ads124s_read(indio_dev, scan_index);
+		priv->buffer[j] = ads124s_read(indio_dev, scan_index);
 		ret = ads124s_write_cmd(indio_dev, ADS124S08_STOP_CONV);
 		if (ret)
 			dev_err(&priv->spi->dev, "Stop ADC conversions failed\n");
@@ -293,7 +300,7 @@
 		j++;
 	}
 
-	iio_push_to_buffers_with_timestamp(indio_dev, buffer,
+	iio_push_to_buffers_with_timestamp(indio_dev, priv->buffer,
 			pf->timestamp);
 
 	iio_trigger_notify_done(indio_dev->trig);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/ti-ads7950.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/ti-ads7950.c
@@ -569,7 +569,6 @@
 	st->ring_xfer.tx_buf = &st->tx_buf[0];
 	st->ring_xfer.rx_buf = &st->rx_buf[0];
 	/* len will be set later */
-	st->ring_xfer.cs_change = true;
 
 	spi_message_add_tail(&st->ring_xfer, &st->ring_msg);
 
@@ -636,6 +635,7 @@
 	st->chip.label = dev_name(&st->spi->dev);
 	st->chip.parent = &st->spi->dev;
 	st->chip.owner = THIS_MODULE;
+	st->chip.can_sleep = true;
 	st->chip.base = -1;
 	st->chip.ngpio = TI_ADS7950_NUM_GPIOS;
 	st->chip.get_direction = ti_ads7950_get_direction;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/ti-ads8344.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/ti-ads8344.c
@@ -29,19 +29,20 @@
 	struct mutex lock;
 
 	u8 tx_buf ____cacheline_aligned;
-	u16 rx_buf;
+	u8 rx_buf[3];
 };
 
-#define ADS8344_VOLTAGE_CHANNEL(chan, si)				\
+#define ADS8344_VOLTAGE_CHANNEL(chan, addr)				\
 	{								\
 		.type = IIO_VOLTAGE,					\
 		.indexed = 1,						\
 		.channel = chan,					\
 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
 		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
+		.address = addr,					\
 	}
 
-#define ADS8344_VOLTAGE_CHANNEL_DIFF(chan1, chan2, si)			\
+#define ADS8344_VOLTAGE_CHANNEL_DIFF(chan1, chan2, addr)		\
 	{								\
 		.type = IIO_VOLTAGE,					\
 		.indexed = 1,						\
@@ -50,6 +51,7 @@
 		.differential = 1,					\
 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
 		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
+		.address = addr,					\
 	}
 
 static const struct iio_chan_spec ads8344_channels[] = {
@@ -89,11 +91,11 @@
 
 	udelay(9);
 
-	ret = spi_read(spi, &adc->rx_buf, 2);
+	ret = spi_read(spi, adc->rx_buf, sizeof(adc->rx_buf));
 	if (ret)
 		return ret;
 
-	return adc->rx_buf;
+	return adc->rx_buf[0] << 9 | adc->rx_buf[1] << 1 | adc->rx_buf[2] >> 7;
 }
 
 static int ads8344_read_raw(struct iio_dev *iio,
@@ -105,7 +107,7 @@
 	switch (mask) {
 	case IIO_CHAN_INFO_RAW:
 		mutex_lock(&adc->lock);
-		*value = ads8344_adc_conversion(adc, channel->scan_index,
+		*value = ads8344_adc_conversion(adc, channel->address,
 						channel->differential);
 		mutex_unlock(&adc->lock);
 		if (*value < 0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/ti-ads8688.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/ti-ads8688.c
@@ -383,7 +383,8 @@
 {
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
-	u16 buffer[ADS8688_MAX_CHANNELS + sizeof(s64)/sizeof(u16)];
+	/* Ensure naturally aligned timestamp */
+	u16 buffer[ADS8688_MAX_CHANNELS + sizeof(s64)/sizeof(u16)] __aligned(8) = { };
 	int i, j = 0;
 
 	for (i = 0; i < indio_dev->masklength; i++) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/ti_am335x_adc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/ti_am335x_adc.c
@@ -656,8 +656,10 @@
 	platform_set_drvdata(pdev, indio_dev);
 
 	err = tiadc_request_dma(pdev, adc_dev);
-	if (err && err == -EPROBE_DEFER)
+	if (err && err != -ENODEV) {
+		dev_err_probe(&pdev->dev, err, "DMA request failed\n");
 		goto err_dma;
+	}
 
 	return 0;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/twl6030-gpadc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/twl6030-gpadc.c
@@ -57,6 +57,18 @@
 #define TWL6030_GPADCS				BIT(1)
 #define TWL6030_GPADCR				BIT(0)
 
+#define USB_VBUS_CTRL_SET			0x04
+#define USB_ID_CTRL_SET				0x06
+
+#define TWL6030_MISC1				0xE4
+#define VBUS_MEAS				0x01
+#define ID_MEAS					0x01
+
+#define VAC_MEAS                0x04
+#define VBAT_MEAS               0x02
+#define BB_MEAS                 0x01
+
+
 /**
  * struct twl6030_chnl_calib - channel calibration
  * @gain:		slope coefficient for ideal curve
@@ -911,6 +923,8 @@
 	ret = devm_request_threaded_irq(dev, irq, NULL,
 				twl6030_gpadc_irq_handler,
 				IRQF_ONESHOT, "twl6030_gpadc", indio_dev);
+	if (ret)
+		return ret;
 
 	ret = twl6030_gpadc_enable_irq(TWL6030_GPADC_RT_SW1_EOC_MASK);
 	if (ret < 0) {
@@ -925,6 +939,26 @@
 		return ret;
 	}
 
+	ret = twl_i2c_write_u8(TWL_MODULE_USB, VBUS_MEAS, USB_VBUS_CTRL_SET);
+	if (ret < 0) {
+		dev_err(dev, "failed to wire up inputs\n");
+		return ret;
+	}
+
+	ret = twl_i2c_write_u8(TWL_MODULE_USB, ID_MEAS, USB_ID_CTRL_SET);
+	if (ret < 0) {
+		dev_err(dev, "failed to wire up inputs\n");
+		return ret;
+	}
+
+	ret = twl_i2c_write_u8(TWL6030_MODULE_ID0,
+				VBAT_MEAS | BB_MEAS | VAC_MEAS,
+				TWL6030_MISC1);
+	if (ret < 0) {
+		dev_err(dev, "failed to wire up inputs\n");
+		return ret;
+	}
+
 	indio_dev->name = DRIVER_NAME;
 	indio_dev->dev.parent = dev;
 	indio_dev->info = &twl6030_gpadc_iio_info;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/versal-sysmon.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/versal-sysmon.c
@@ -0,0 +1,825 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx SYSMON for Versal
+ *
+ * Copyright (C) 2019 - 2020 Xilinx, Inc.
+ *
+ * Description:
+ * This driver is developed for SYSMON on Versal. The driver supports INDIO Mode
+ * and supports voltage and temperature monitoring via IIO sysfs interface.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/events.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/of_address.h>
+
+/* Channel IDs for Temp Channels */
+/* TEMP_MAX gives the current temperature for Production
+ * silicon.
+ * TEMP_MAX gives the current maximum temperature for ES1
+ * silicon.
+ */
+#define TEMP_MAX	160
+
+/* TEMP_MIN is not applicable for Production silicon.
+ * TEMP_MIN gives the current minimum temperature for ES1 silicon.
+ */
+#define TEMP_MIN	161
+
+#define TEMP_MAX_MAX	162
+#define TEMP_MIN_MIN	163
+#define TEMP_EVENT	164
+#define OT_EVENT	165
+
+/* Register Unlock Code */
+#define NPI_UNLOCK	0xF9E8D7C6
+
+/* Register Offsets */
+#define SYSMON_NPI_LOCK		0x000C
+#define SYSMON_ISR		0x0044
+#define SYSMON_IMR		0x0048
+#define SYSMON_IER		0x004C
+#define SYSMON_IDR		0x0050
+#define SYSMON_ALARM_FLAG	0x1018
+#define SYSMON_TEMP_MAX		0x1030
+#define SYSMON_TEMP_MIN		0x1034
+#define SYSMON_SUPPLY_BASE	0x1040
+#define SYSMON_ALARM_REG	0x1940
+#define SYSMON_TEMP_TH_LOW	0x1970
+#define SYSMON_TEMP_TH_UP	0x1974
+#define SYSMON_OT_TH_LOW	0x1978
+#define SYSMON_OT_TH_UP		0x197C
+#define SYSMON_SUPPLY_TH_LOW	0x1980
+#define SYSMON_SUPPLY_TH_UP	0x1C80
+#define SYSMON_TEMP_MAX_MAX	0x1F90
+#define SYSMON_TEMP_MIN_MIN	0x1F8C
+#define SYSMON_TEMP_EV_CFG	0x1F84
+
+#define SYSMON_NO_OF_EVENTS	32
+
+/* Supply Voltage Conversion macros */
+#define SYSMON_MANTISSA_MASK		0xFFFF
+#define SYSMON_FMT_MASK			0x10000
+#define SYSMON_FMT_SHIFT		16
+#define SYSMON_MODE_MASK		0x60000
+#define SYSMON_MODE_SHIFT		17
+#define SYSMON_MANTISSA_SIGN_SHIFT	15
+#define SYSMON_UPPER_SATURATION_SIGNED	32767
+#define SYSMON_LOWER_SATURATION_SIGNED	-32768
+#define SYSMON_UPPER_SATURATION		65535
+#define SYSMON_LOWER_SATURATION		0
+
+#define SYSMON_CHAN_TEMP_EVENT(_address, _ext, _events) { \
+	.type = IIO_TEMP, \
+	.indexed = 1, \
+	.address = _address, \
+	.channel = _address, \
+	.event_spec = _events, \
+	.num_event_specs = ARRAY_SIZE(_events), \
+	.scan_type = { \
+		.sign = 's', \
+		.realbits = 15, \
+		.storagebits = 16, \
+		.endianness = IIO_CPU, \
+	}, \
+	.extend_name = _ext, \
+	}
+
+#define SYSMON_CHAN_TEMP(_address, _ext) { \
+	.type = IIO_TEMP, \
+	.indexed = 1, \
+	.address = _address, \
+	.channel = _address, \
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+		BIT(IIO_CHAN_INFO_PROCESSED), \
+	.scan_type = { \
+		.sign = 's', \
+		.realbits = 15, \
+		.storagebits = 16, \
+		.endianness = IIO_CPU, \
+	}, \
+	.extend_name = _ext, \
+}
+
+#define twoscomp(val) ((((val) ^ 0xFFFF) + 1) & 0x0000FFFF)
+#define ALARM_REG(address) ((address) / 32)
+#define ALARM_SHIFT(address) ((address) % 32)
+
+enum sysmon_alarm_bit {
+	SYSMON_BIT_ALARM0 = 0,
+	SYSMON_BIT_ALARM1 = 1,
+	SYSMON_BIT_ALARM2 = 2,
+	SYSMON_BIT_ALARM3 = 3,
+	SYSMON_BIT_ALARM4 = 4,
+	SYSMON_BIT_ALARM5 = 5,
+	SYSMON_BIT_ALARM6 = 6,
+	SYSMON_BIT_ALARM7 = 7,
+	SYSMON_BIT_OT = 8,
+	SYSMON_BIT_TEMP = 9,
+};
+
+/**
+ * struct sysmon - Driver data for Sysmon
+ * @base: physical base address of device
+ * @dev: pointer to device struct
+ * @mutex: to handle multiple user interaction
+ * @lock: to help manage interrupt registers correctly
+ * @irq: interrupt number of the sysmon
+ *
+ * This structure contains necessary state for Sysmon driver to operate
+ */
+struct sysmon {
+	void __iomem *base;
+	struct device *dev;
+	/* kernel doc above */
+	struct mutex mutex;
+	/* kernel doc above*/
+	spinlock_t lock;
+	int irq;
+};
+
+/* This structure describes temperature events */
+static const struct iio_event_spec sysmon_temp_events[] = {
+	{
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_RISING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE),
+	},
+	{
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_FALLING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE),
+	},
+	{
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_EITHER,
+		.mask_separate =
+			BIT(IIO_EV_INFO_ENABLE) | BIT(IIO_EV_INFO_HYSTERESIS),
+	},
+};
+
+/* This structure describes voltage events */
+static const struct iio_event_spec sysmon_supply_events[] = {
+	{
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_RISING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE),
+	},
+	{
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_FALLING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE),
+	},
+	{
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_EITHER,
+		.mask_separate = BIT(IIO_EV_INFO_ENABLE),
+	},
+};
+
+/* Temperature channel attributes */
+static const struct iio_chan_spec temp_channels[] = {
+	SYSMON_CHAN_TEMP(TEMP_MAX, "temp"),
+	SYSMON_CHAN_TEMP(TEMP_MIN, "min"),
+	SYSMON_CHAN_TEMP(TEMP_MAX_MAX, "max_max"),
+	SYSMON_CHAN_TEMP(TEMP_MIN_MIN, "min_min"),
+	SYSMON_CHAN_TEMP_EVENT(TEMP_EVENT, "temp", sysmon_temp_events),
+	SYSMON_CHAN_TEMP_EVENT(OT_EVENT, "ot", sysmon_temp_events),
+};
+
+static inline void sysmon_read_reg(struct sysmon *sysmon, u32 offset, u32 *data)
+{
+	*data = readl(sysmon->base + offset);
+}
+
+static inline void sysmon_write_reg(struct sysmon *sysmon, u32 offset, u32 data)
+{
+	writel(data, sysmon->base + offset);
+}
+
+static inline void sysmon_update_reg(struct sysmon *sysmon, u32 offset,
+				     u32 mask, u32 data)
+{
+	u32 val;
+
+	sysmon_read_reg(sysmon, offset, &val);
+	sysmon_write_reg(sysmon, offset, (val & ~mask) | (mask & data));
+}
+
+static u32 sysmon_temp_offset(int address)
+{
+	switch (address) {
+	case TEMP_MAX:
+		return SYSMON_TEMP_MAX;
+	case TEMP_MIN:
+		return SYSMON_TEMP_MIN;
+	case TEMP_MAX_MAX:
+		return SYSMON_TEMP_MAX_MAX;
+	case TEMP_MIN_MIN:
+		return SYSMON_TEMP_MIN_MIN;
+	default:
+		return -EINVAL;
+	}
+	return -EINVAL;
+}
+
+static u32 sysmon_temp_thresh_offset(int address, enum iio_event_direction dir)
+{
+	switch (address) {
+	case TEMP_EVENT:
+		return (dir == IIO_EV_DIR_RISING) ? SYSMON_TEMP_TH_UP :
+						    SYSMON_TEMP_TH_LOW;
+	case OT_EVENT:
+		return (dir == IIO_EV_DIR_RISING) ? SYSMON_OT_TH_UP :
+						    SYSMON_OT_TH_LOW;
+	default:
+		return -EINVAL;
+	}
+	return -EINVAL;
+}
+
+static u32 sysmon_supply_offset(int address)
+{
+	return (address * 4) + SYSMON_SUPPLY_BASE;
+}
+
+static u32 sysmon_supply_thresh_offset(int address,
+				       enum iio_event_direction dir)
+{
+	if (dir == IIO_EV_DIR_RISING)
+		return (address * 4) + SYSMON_SUPPLY_TH_UP;
+	else if (dir == IIO_EV_DIR_FALLING)
+		return (address * 4) + SYSMON_SUPPLY_TH_LOW;
+
+	return -EINVAL;
+}
+
+/**
+ * sysmon_q8p7_to_celsius() - converts fixed point Q8.7 format to a fraction.
+ * @raw_data: Raw ADC value
+ * @val: The numerator of the fraction needed by IIO_VAL_PROCESSED
+ * @val2: Denominator of the fraction needed by IIO_VAL_PROCESSED
+ *
+ * The function returns a fraction which returns celsius
+ */
+static void sysmon_q8p7_to_celsius(int raw_data, int *val, int *val2)
+{
+	*val = (raw_data & 0x8000) ? -(twoscomp(raw_data)) : raw_data;
+	*val2 = 128;
+}
+
+/**
+ * sysmon_celsius_to_q8p7() - converts value from IIO Framework to ADC Raw data
+ * @raw_data: Raw ADC value
+ * @val: The numerator of the fraction provided by the IIO Framework
+ * @val2: Denominator of the fraction provided by the IIO Framework
+ *
+ * The function takes in exponent and mantissa as val and val2 respectively
+ * of temperature value in Deg Celsius and returns raw adc value for the
+ * given temperature.
+ */
+static void sysmon_celsius_to_q8p7(u32 *raw_data, int val, int val2)
+{
+	int scale = 1 << 7;
+
+	/* The value is scaled by 10^6 in the IIO framework
+	 * dividing by 1000 twice to avoid overflow
+	 */
+	val2 = val2 / 1000;
+	*raw_data = (val * scale) + ((val2 * scale) / 1000);
+}
+
+static void sysmon_supply_rawtoprocessed(int raw_data, int *val, int *val2)
+{
+	int mantissa, format, exponent;
+
+	mantissa = raw_data & SYSMON_MANTISSA_MASK;
+	exponent = (raw_data & SYSMON_MODE_MASK) >> SYSMON_MODE_SHIFT;
+	format = (raw_data & SYSMON_FMT_MASK) >> SYSMON_FMT_SHIFT;
+
+	*val2 = 1 << (16 - exponent);
+	*val = mantissa;
+	if (format && (mantissa >> SYSMON_MANTISSA_SIGN_SHIFT))
+		*val = (~(mantissa) & SYSMON_MANTISSA_MASK) * -1;
+}
+
+static void sysmon_supply_processedtoraw(int val, int val2, u32 reg_val,
+					 u32 *raw_data)
+{
+	int exponent = (reg_val & SYSMON_MODE_MASK) >> SYSMON_MODE_SHIFT;
+	int format = (reg_val & SYSMON_FMT_MASK) >> SYSMON_FMT_SHIFT;
+	int scale = 1 << (16 - exponent);
+	int tmp;
+
+	/**
+	 * The value is scaled by 10^6 in the IIO framework
+	 * dividing by 1000 twice to avoid overflow
+	 */
+	val2 = val2 / 1000;
+	tmp = (val * scale) + ((val2 * scale) / 1000);
+
+	/* Set out of bound values to saturation levels */
+	if (format) {
+		if (tmp > SYSMON_UPPER_SATURATION_SIGNED)
+			tmp = 0x7fff;
+		else if (tmp < SYSMON_LOWER_SATURATION_SIGNED)
+			tmp = 0x8000;
+
+	} else {
+		if (tmp > SYSMON_UPPER_SATURATION)
+			tmp = 0xffff;
+		else if (tmp < SYSMON_LOWER_SATURATION)
+			tmp = 0x0000;
+	}
+
+	*raw_data = tmp & 0xffff;
+}
+
+static int sysmon_read_raw(struct iio_dev *indio_dev,
+			   struct iio_chan_spec const *chan, int *val,
+			   int *val2, long mask)
+{
+	struct sysmon *sysmon = iio_priv(indio_dev);
+	u32 offset, regval;
+	u32 ret = -EINVAL;
+
+	mutex_lock(&sysmon->mutex);
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		switch (chan->type) {
+		case IIO_TEMP:
+			offset = sysmon_temp_offset(chan->address);
+			sysmon_read_reg(sysmon, offset, val);
+			*val2 = 0;
+			ret = IIO_VAL_INT;
+			break;
+
+		case IIO_VOLTAGE:
+			offset = sysmon_supply_offset(chan->address);
+			sysmon_read_reg(sysmon, offset, val);
+			*val2 = 0;
+			ret = IIO_VAL_INT;
+			break;
+
+		default:
+			break;
+		}
+		break;
+
+	case IIO_CHAN_INFO_PROCESSED:
+		switch (chan->type) {
+		case IIO_TEMP:
+			/* In Deg C */
+			offset = sysmon_temp_offset(chan->address);
+			sysmon_read_reg(sysmon, offset, &regval);
+			sysmon_q8p7_to_celsius(regval, val, val2);
+			ret = IIO_VAL_FRACTIONAL;
+			break;
+
+		case IIO_VOLTAGE:
+			/* In Volts */
+			offset = sysmon_supply_offset(chan->address);
+			sysmon_read_reg(sysmon, offset, &regval);
+			sysmon_supply_rawtoprocessed(regval, val, val2);
+			ret = IIO_VAL_FRACTIONAL;
+			break;
+
+		default:
+			break;
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	mutex_unlock(&sysmon->mutex);
+	return ret;
+}
+
+static int sysmon_get_event_mask(unsigned long address)
+{
+	if (address == TEMP_EVENT)
+		return BIT(SYSMON_BIT_TEMP);
+	else if (address == OT_EVENT)
+		return BIT(SYSMON_BIT_OT);
+
+	/* return supply */
+	return BIT(address / 32);
+}
+
+static int sysmon_read_alarm_config(struct sysmon *sysmon,
+				    unsigned long address)
+{
+	u32 reg_val;
+	u32 alarm_reg_num = ALARM_REG(address);
+	u32 shift = ALARM_SHIFT(address);
+	u32 offset = SYSMON_ALARM_REG + (4 * alarm_reg_num);
+
+	sysmon_read_reg(sysmon, offset, &reg_val);
+
+	return reg_val & BIT(shift);
+}
+
+static void sysmon_write_alarm_config(struct sysmon *sysmon,
+				      unsigned long address, u32 val)
+{
+	u32 alarm_reg_num = ALARM_REG(address);
+	u32 shift = ALARM_SHIFT(address);
+	u32 offset = SYSMON_ALARM_REG + (4 * alarm_reg_num);
+
+	sysmon_update_reg(sysmon, offset, BIT(shift), (val << shift));
+}
+
+static int sysmon_read_event_config(struct iio_dev *indio_dev,
+				    const struct iio_chan_spec *chan,
+				    enum iio_event_type type,
+				    enum iio_event_direction dir)
+{
+	struct sysmon *sysmon = iio_priv(indio_dev);
+	u32 config_value, imr;
+	u32 alarm_event_mask = sysmon_get_event_mask(chan->address);
+
+	sysmon_read_reg(sysmon, SYSMON_IMR, &imr);
+
+	/* Getting the unmasked interrupts */
+	imr = ~imr;
+
+	if (chan->type == IIO_VOLTAGE) {
+		config_value = sysmon_read_alarm_config(sysmon, chan->address);
+
+		return (config_value && (imr & alarm_event_mask));
+	}
+
+	return (imr & sysmon_get_event_mask(chan->address)) ? 1 : 0;
+}
+
+static int sysmon_write_event_config(struct iio_dev *indio_dev,
+				     const struct iio_chan_spec *chan,
+				     enum iio_event_type type,
+				     enum iio_event_direction dir, int state)
+{
+	struct sysmon *sysmon = iio_priv(indio_dev);
+	u32 alarm_reg_num = ALARM_REG(chan->address);
+	u32 offset = SYSMON_ALARM_REG + (4 * alarm_reg_num);
+	u32 ier = sysmon_get_event_mask(chan->address);
+	u32 alarm_config;
+	unsigned long flags;
+
+	mutex_lock(&sysmon->mutex);
+	spin_lock_irqsave(&sysmon->lock, flags);
+
+	if (chan->type == IIO_VOLTAGE) {
+		sysmon_write_alarm_config(sysmon, chan->address, state);
+
+		sysmon_read_reg(sysmon, offset, &alarm_config);
+
+		if (alarm_config)
+			sysmon_write_reg(sysmon, SYSMON_IER, ier);
+		else
+			sysmon_write_reg(sysmon, SYSMON_IDR, ier);
+
+	} else {
+		if (state)
+			sysmon_write_reg(sysmon, SYSMON_IER, ier);
+		else
+			sysmon_write_reg(sysmon, SYSMON_IDR, ier);
+	}
+
+	spin_unlock_irqrestore(&sysmon->lock, flags);
+	mutex_unlock(&sysmon->mutex);
+
+	return 0;
+}
+
+static int sysmon_read_event_value(struct iio_dev *indio_dev,
+				   const struct iio_chan_spec *chan,
+				   enum iio_event_type type,
+				   enum iio_event_direction dir,
+				   enum iio_event_info info, int *val,
+				   int *val2)
+{
+	struct sysmon *sysmon = iio_priv(indio_dev);
+	u32 offset, reg_val;
+	u32 mask, shift;
+	u32 ret = -EINVAL;
+
+	mutex_lock(&sysmon->mutex);
+	if (chan->type == IIO_TEMP) {
+		if (info == IIO_EV_INFO_VALUE) {
+			offset = sysmon_temp_thresh_offset(chan->address, dir);
+			sysmon_read_reg(sysmon, offset, &reg_val);
+			sysmon_q8p7_to_celsius(reg_val, val, val2);
+			ret = IIO_VAL_FRACTIONAL;
+		} else if (info == IIO_EV_INFO_HYSTERESIS) {
+			mask = (chan->address == OT_EVENT) ? 0x1 : 0x2;
+			shift = mask - 1;
+			sysmon_read_reg(sysmon, SYSMON_TEMP_EV_CFG, &reg_val);
+			*val = (reg_val & mask) >> shift;
+			*val2 = 0;
+			ret = IIO_VAL_INT;
+		}
+	} else if (chan->type == IIO_VOLTAGE) {
+		offset = sysmon_supply_thresh_offset(chan->address, dir);
+		sysmon_read_reg(sysmon, offset, &reg_val);
+		sysmon_supply_rawtoprocessed(reg_val, val, val2);
+		ret = IIO_VAL_FRACTIONAL;
+	}
+
+	mutex_unlock(&sysmon->mutex);
+	return ret;
+}
+
+static int sysmon_write_event_value(struct iio_dev *indio_dev,
+				    const struct iio_chan_spec *chan,
+				    enum iio_event_type type,
+				    enum iio_event_direction dir,
+				    enum iio_event_info info, int val, int val2)
+{
+	struct sysmon *sysmon = iio_priv(indio_dev);
+	u32 offset, raw_val, reg_val;
+	u32 mask, shift;
+
+	mutex_lock(&sysmon->mutex);
+	if (chan->type == IIO_TEMP) {
+		if (info == IIO_EV_INFO_VALUE) {
+			offset = sysmon_temp_thresh_offset(chan->address, dir);
+			sysmon_celsius_to_q8p7(&reg_val, val, val2);
+			sysmon_write_reg(sysmon, offset, reg_val);
+		} else if (info == IIO_EV_INFO_HYSTERESIS) {
+			/* calculating the mask value for OT and TEMP Alarms */
+			mask = (chan->address == OT_EVENT) ? 1 : 2;
+			shift = mask - 1;
+			sysmon_update_reg(sysmon, SYSMON_TEMP_EV_CFG, mask,
+					  (val << shift));
+		}
+	} else if (chan->type == IIO_VOLTAGE) {
+		offset = sysmon_supply_thresh_offset(chan->address, dir);
+		sysmon_read_reg(sysmon, offset, &reg_val);
+		sysmon_supply_processedtoraw(val, val2, reg_val, &raw_val);
+		sysmon_write_reg(sysmon, offset, raw_val);
+	}
+
+	mutex_unlock(&sysmon->mutex);
+	return 0;
+}
+
+static const struct iio_info iio_dev_info = {
+	.read_raw = sysmon_read_raw,
+	.read_event_config = sysmon_read_event_config,
+	.write_event_config = sysmon_write_event_config,
+	.read_event_value = sysmon_read_event_value,
+	.write_event_value = sysmon_write_event_value,
+};
+
+static void sysmon_push_event(struct iio_dev *indio_dev, u32 address)
+{
+	u32 i;
+	const struct iio_chan_spec *chan;
+
+	for (i = 0; i < indio_dev->num_channels; i++) {
+		if (indio_dev->channels[i].address == address) {
+			chan = &indio_dev->channels[i];
+			iio_push_event(indio_dev,
+				       IIO_UNMOD_EVENT_CODE(chan->type,
+							    chan->channel,
+							    IIO_EV_TYPE_THRESH,
+							    IIO_EV_DIR_EITHER),
+				       iio_get_time_ns(indio_dev));
+		}
+	}
+}
+
+static void sysmon_handle_event(struct iio_dev *indio_dev, u32 event)
+{
+	struct sysmon *sysmon = iio_priv(indio_dev);
+	unsigned long alarm_flag_reg;
+	u32 address, bit, reg_val;
+	u32 alarm_flag_offset = SYSMON_ALARM_FLAG + (event * 4);
+	u32 alarm_reg_offset = SYSMON_ALARM_REG + (event * 4);
+
+	switch (event) {
+	case SYSMON_BIT_TEMP:
+		address = TEMP_EVENT;
+		sysmon_push_event(indio_dev, address);
+		sysmon_write_reg(sysmon, SYSMON_IDR, BIT(SYSMON_BIT_TEMP));
+		break;
+
+	case SYSMON_BIT_OT:
+		address = OT_EVENT;
+		sysmon_push_event(indio_dev, address);
+		sysmon_write_reg(sysmon, SYSMON_IDR, BIT(SYSMON_BIT_TEMP));
+		break;
+
+	case SYSMON_BIT_ALARM4:
+	case SYSMON_BIT_ALARM3:
+	case SYSMON_BIT_ALARM2:
+	case SYSMON_BIT_ALARM1:
+	case SYSMON_BIT_ALARM0:
+		/* Read enabled alarms */
+		sysmon_read_reg(sysmon, alarm_flag_offset, &reg_val);
+		alarm_flag_reg = (unsigned long)reg_val;
+
+		for_each_set_bit(bit, &alarm_flag_reg, 32) {
+			address = bit + (32 * event);
+			sysmon_push_event(indio_dev, address);
+			/* disable alarm */
+			sysmon_update_reg(sysmon, alarm_reg_offset, BIT(bit),
+					  0);
+		}
+		/* clear alarms */
+		sysmon_write_reg(sysmon, alarm_flag_offset, alarm_flag_reg);
+		break;
+
+	default:
+		break;
+	}
+}
+
+static void sysmon_handle_events(struct iio_dev *indio_dev,
+				 unsigned long events)
+{
+	unsigned int bit;
+
+	for_each_set_bit(bit, &events, SYSMON_NO_OF_EVENTS)
+		sysmon_handle_event(indio_dev, bit);
+}
+
+static irqreturn_t sysmon_iio_irq(int irq, void *data)
+{
+	u32 isr, imr;
+	struct iio_dev *indio_dev = data;
+	struct sysmon *sysmon = iio_priv(indio_dev);
+
+	spin_lock(&sysmon->lock);
+
+	sysmon_read_reg(sysmon, SYSMON_ISR, &isr);
+	sysmon_read_reg(sysmon, SYSMON_IMR, &imr);
+
+	/* only process alarm that are not masked */
+	isr &= ~imr;
+
+	/* clear interrupt */
+	sysmon_write_reg(sysmon, SYSMON_ISR, isr);
+
+	if (isr) {
+		/* Clear the interrupts*/
+		sysmon_handle_events(indio_dev, isr);
+	}
+
+	spin_unlock(&sysmon->lock);
+
+	return IRQ_HANDLED;
+}
+
+static int sysmon_parse_dt(struct iio_dev *indio_dev,
+			   struct platform_device *pdev)
+{
+	struct iio_chan_spec *sysmon_channels;
+	struct device_node *child_node = NULL, *np = pdev->dev.of_node;
+	int ret, i = 0;
+	u8 num_supply_chan = 0;
+	u32 reg = 0;
+	const char *name;
+	u32 chan_size = sizeof(struct iio_chan_spec);
+
+	ret = of_property_read_u8(np, "xlnx,numchannels", &num_supply_chan);
+	if (ret < 0)
+		return ret;
+
+	/* Initialize buffer for channel specification */
+	sysmon_channels = devm_kzalloc(&pdev->dev,
+				       (chan_size * num_supply_chan) +
+				       sizeof(temp_channels),
+				       GFP_KERNEL);
+
+	for_each_child_of_node(np, child_node) {
+		ret = of_property_read_u32(child_node, "reg", &reg);
+		if (ret < 0)
+			return ret;
+
+		ret = of_property_read_string(child_node, "xlnx,name", &name);
+		if (ret < 0)
+			return ret;
+
+		sysmon_channels[i].type = IIO_VOLTAGE;
+		sysmon_channels[i].indexed = 1;
+		sysmon_channels[i].address = reg;
+		sysmon_channels[i].channel = reg;
+		sysmon_channels[i].info_mask_separate =
+			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_PROCESSED);
+		sysmon_channels[i].event_spec = sysmon_supply_events;
+		sysmon_channels[i].num_event_specs =
+			ARRAY_SIZE(sysmon_supply_events);
+		sysmon_channels[i].scan_index = i;
+		sysmon_channels[i].scan_type.realbits = 19;
+		sysmon_channels[i].scan_type.storagebits = 32;
+
+		sysmon_channels[i].scan_type.endianness = IIO_CPU;
+		sysmon_channels[i].extend_name = name;
+
+		if (of_property_read_bool(child_node, "xlnx,bipolar"))
+			sysmon_channels[i].scan_type.sign = 's';
+		else
+			sysmon_channels[i].scan_type.sign = 'u';
+
+		i++;
+	}
+
+	/* Append static temperature channels to the channel list */
+	memcpy(sysmon_channels + num_supply_chan, temp_channels,
+	       sizeof(temp_channels));
+
+	indio_dev->channels = sysmon_channels;
+	indio_dev->num_channels = num_supply_chan + ARRAY_SIZE(temp_channels);
+
+	return 0;
+}
+
+static int sysmon_probe(struct platform_device *pdev)
+{
+	struct iio_dev *indio_dev;
+	struct sysmon *sysmon;
+	struct resource *mem;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*sysmon));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	sysmon = iio_priv(indio_dev);
+
+	sysmon->irq = platform_get_irq(pdev, 0);
+	if (sysmon->irq <= 0)
+		return -ENXIO;
+
+	mutex_init(&sysmon->mutex);
+	spin_lock_init(&sysmon->lock);
+
+	indio_dev->dev.parent = &pdev->dev;
+	indio_dev->dev.of_node = pdev->dev.of_node;
+	indio_dev->name = "xlnx,versal-sysmon";
+	indio_dev->info = &iio_dev_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	sysmon->base = devm_ioremap_resource(&pdev->dev, mem);
+	if (IS_ERR(sysmon->base))
+		return PTR_ERR(sysmon->base);
+
+	sysmon_write_reg(sysmon, SYSMON_NPI_LOCK, NPI_UNLOCK);
+
+	ret = sysmon_parse_dt(indio_dev, pdev);
+	if (ret)
+		return ret;
+
+	ret = devm_request_irq(&pdev->dev, sysmon->irq, &sysmon_iio_irq, 0,
+			       "sysmon-irq", indio_dev);
+	if (ret < 0)
+		return ret;
+
+	platform_set_drvdata(pdev, indio_dev);
+
+	dev_info(&pdev->dev, "Successfully registered Versal Sysmon");
+
+	return iio_device_register(indio_dev);
+}
+
+static int sysmon_remove(struct platform_device *pdev)
+{
+	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+
+	/* Unregister the device */
+	iio_device_unregister(indio_dev);
+	return 0;
+}
+
+static const struct of_device_id sysmon_of_match_table[] = {
+	{ .compatible = "xlnx,versal-sysmon" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, sysmon_of_match_table);
+
+static struct platform_driver sysmon_driver = {
+	.probe = sysmon_probe,
+	.remove = sysmon_remove,
+	.driver = {
+		.name = "sysmon",
+		.of_match_table = sysmon_of_match_table,
+	},
+};
+module_platform_driver(sysmon_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Xilinx Versal SysMon Driver");
+MODULE_AUTHOR("Anand Ashok Dumbre <anand.ashok.dumbre@xilinx.com>");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/vf610_adc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/vf610_adc.c
@@ -167,7 +167,11 @@
 	u32 sample_freq_avail[5];
 
 	struct completion completion;
-	u16 buffer[8];
+	/* Ensure the timestamp is naturally aligned */
+	struct {
+		u16 chan;
+		s64 timestamp __aligned(8);
+	} scan;
 };
 
 static const u32 vf610_hw_avgs[] = { 1, 4, 8, 16, 32 };
@@ -579,9 +583,9 @@
 	if (coco & VF610_ADC_HS_COCO0) {
 		info->value = vf610_adc_read_data(info);
 		if (iio_buffer_enabled(indio_dev)) {
-			info->buffer[0] = info->value;
+			info->scan.chan = info->value;
 			iio_push_to_buffers_with_timestamp(indio_dev,
-					info->buffer,
+					&info->scan,
 					iio_get_time_ns(indio_dev));
 			iio_trigger_notify_done(indio_dev->trig);
 		} else
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/xilinx-ams.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/xilinx-ams.c
@@ -0,0 +1,1109 @@
+/*
+ * Xilinx AMS driver
+ *
+ * Licensed under the GPL-2
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/of_address.h>
+#include <linux/iopoll.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/events.h>
+#include <linux/iio/buffer.h>
+#include <linux/io.h>
+
+#include "xilinx-ams.h"
+#include <linux/delay.h>
+
+static const unsigned int AMS_UNMASK_TIMEOUT = 500;
+
+static inline void ams_read_reg(struct ams *ams, unsigned int offset, u32 *data)
+{
+	*data = readl(ams->base + offset);
+}
+
+static inline void ams_write_reg(struct ams *ams, unsigned int offset, u32 data)
+{
+	writel(data, ams->base + offset);
+}
+
+static inline void ams_update_reg(struct ams *ams, unsigned int offset,
+				  u32 mask, u32 data)
+{
+	u32 val;
+
+	ams_read_reg(ams, offset, &val);
+	ams_write_reg(ams, offset, (val & ~mask) | (mask & data));
+}
+
+static inline void ams_ps_read_reg(struct ams *ams, unsigned int offset,
+				   u32 *data)
+{
+	*data = readl(ams->ps_base + offset);
+}
+
+static inline void ams_ps_write_reg(struct ams *ams, unsigned int offset,
+				    u32 data)
+{
+	writel(data, ams->ps_base + offset);
+}
+
+static inline void ams_ps_update_reg(struct ams *ams, unsigned int offset,
+				     u32 mask, u32 data)
+{
+	u32 val;
+
+	ams_ps_read_reg(ams, offset, &val);
+	ams_ps_write_reg(ams, offset, (val & ~mask) | (data & mask));
+}
+
+static inline void ams_apb_pl_read_reg(struct ams *ams, unsigned int offset,
+				       u32 *data)
+{
+	*data = readl(ams->pl_base + offset);
+}
+
+static inline void ams_apb_pl_write_reg(struct ams *ams, unsigned int offset,
+					u32 data)
+{
+	writel(data, ams->pl_base + offset);
+}
+
+static inline void ams_apb_pl_update_reg(struct ams *ams, unsigned int offset,
+					 u32 mask, u32 data)
+{
+	u32 val;
+
+	ams_apb_pl_read_reg(ams, offset, &val);
+	ams_apb_pl_write_reg(ams, offset, (val & ~mask) | (data & mask));
+}
+
+static void ams_update_intrmask(struct ams *ams, u64 mask, u64 val)
+{
+	/* intr_mask variable in ams represent bit in AMS regisetr IDR0 and IDR1
+	 * first 32 biit will be of IDR0, next one are of IDR1 register.
+	 */
+	ams->intr_mask &= ~mask;
+	ams->intr_mask |= (val & mask);
+
+	ams_write_reg(ams, AMS_IER_0, ~(ams->intr_mask | ams->masked_alarm));
+	ams_write_reg(ams, AMS_IER_1,
+		      ~(ams->intr_mask >> AMS_ISR1_INTR_MASK_SHIFT));
+	ams_write_reg(ams, AMS_IDR_0, ams->intr_mask | ams->masked_alarm);
+	ams_write_reg(ams, AMS_IDR_1,
+		      ams->intr_mask >> AMS_ISR1_INTR_MASK_SHIFT);
+}
+
+static void iio_ams_disable_all_alarm(struct ams *ams)
+{
+	/* disable PS module alarm */
+	if (ams->ps_base) {
+		ams_ps_update_reg(ams, AMS_REG_CONFIG1, AMS_REGCFG1_ALARM_MASK,
+				  AMS_REGCFG1_ALARM_MASK);
+		ams_ps_update_reg(ams, AMS_REG_CONFIG3, AMS_REGCFG3_ALARM_MASK,
+				  AMS_REGCFG3_ALARM_MASK);
+	}
+
+	/* disable PL module alarm */
+	if (ams->pl_base) {
+		ams->pl_bus->update(ams, AMS_REG_CONFIG1,
+				    AMS_REGCFG1_ALARM_MASK,
+				    AMS_REGCFG1_ALARM_MASK);
+		ams->pl_bus->update(ams, AMS_REG_CONFIG3,
+				    AMS_REGCFG3_ALARM_MASK,
+				    AMS_REGCFG3_ALARM_MASK);
+	}
+}
+
+static void iio_ams_update_alarm(struct ams *ams, unsigned long alarm_mask)
+{
+	u32 cfg;
+	unsigned long flags;
+	unsigned long pl_alarm_mask;
+
+	if (ams->ps_base) {
+		/* Configuring PS alarm enable */
+		cfg = ~((alarm_mask & AMS_ISR0_ALARM_2_TO_0_MASK) <<
+			       AMS_CONF1_ALARM_2_TO_0_SHIFT);
+		cfg &= ~((alarm_mask & AMS_ISR0_ALARM_6_TO_3_MASK) <<
+				AMS_CONF1_ALARM_6_TO_3_SHIFT);
+		ams_ps_update_reg(ams, AMS_REG_CONFIG1, AMS_REGCFG1_ALARM_MASK,
+				  cfg);
+
+		cfg = ~((alarm_mask >> AMS_CONF3_ALARM_12_TO_7_SHIFT) &
+				AMS_ISR0_ALARM_12_TO_7_MASK);
+		ams_ps_update_reg(ams, AMS_REG_CONFIG3, AMS_REGCFG3_ALARM_MASK,
+				  cfg);
+	}
+
+	if (ams->pl_base) {
+		pl_alarm_mask = (alarm_mask >> AMS_PL_ALARM_START);
+		/* Configuring PL alarm enable */
+		cfg = ~((pl_alarm_mask & AMS_ISR0_ALARM_2_TO_0_MASK) <<
+			       AMS_CONF1_ALARM_2_TO_0_SHIFT);
+		cfg &= ~((pl_alarm_mask & AMS_ISR0_ALARM_6_TO_3_MASK) <<
+				AMS_CONF1_ALARM_6_TO_3_SHIFT);
+		ams->pl_bus->update(ams, AMS_REG_CONFIG1,
+				AMS_REGCFG1_ALARM_MASK, cfg);
+
+		cfg = ~((pl_alarm_mask >> AMS_CONF3_ALARM_12_TO_7_SHIFT) &
+				AMS_ISR0_ALARM_12_TO_7_MASK);
+		ams->pl_bus->update(ams, AMS_REG_CONFIG3,
+				AMS_REGCFG3_ALARM_MASK, cfg);
+	}
+
+	spin_lock_irqsave(&ams->lock, flags);
+	ams_update_intrmask(ams, AMS_ISR0_ALARM_MASK, ~alarm_mask);
+	spin_unlock_irqrestore(&ams->lock, flags);
+}
+
+static void ams_enable_channel_sequence(struct ams *ams)
+{
+	int i;
+	unsigned long long scan_mask;
+	struct iio_dev *indio_dev = iio_priv_to_dev(ams);
+
+	/* Enable channel sequence. First 22 bit of scan_mask represent
+	 * PS channels, and  next remaining bit represents PL channels.
+	 */
+
+	/* Run calibration of PS & PL as part of the sequence */
+	scan_mask = 1 | (1 << PS_SEQ_MAX);
+	for (i = 0; i < indio_dev->num_channels; i++)
+		scan_mask |= BIT(indio_dev->channels[i].scan_index);
+
+	if (ams->ps_base) {
+		/* put sysmon in a soft reset to change the sequence */
+		ams_ps_update_reg(ams, AMS_REG_CONFIG1, AMS_CONF1_SEQ_MASK,
+				  AMS_CONF1_SEQ_DEFAULT);
+
+		/* configure basic channels */
+		ams_ps_write_reg(ams, AMS_REG_SEQ_CH0,
+				 scan_mask & AMS_REG_SEQ0_MASK);
+		ams_ps_write_reg(ams, AMS_REG_SEQ_CH2, AMS_REG_SEQ2_MASK &
+				(scan_mask >> AMS_REG_SEQ2_MASK_SHIFT));
+
+		/* set continuous sequence mode */
+		ams_ps_update_reg(ams, AMS_REG_CONFIG1, AMS_CONF1_SEQ_MASK,
+				  AMS_CONF1_SEQ_CONTINUOUS);
+	}
+
+	if (ams->pl_base) {
+		/* put sysmon in a soft reset to change the sequence */
+		ams->pl_bus->update(ams, AMS_REG_CONFIG1, AMS_CONF1_SEQ_MASK,
+				    AMS_CONF1_SEQ_DEFAULT);
+
+		/* configure basic channels */
+		scan_mask = (scan_mask >> PS_SEQ_MAX);
+		ams->pl_bus->write(ams, AMS_REG_SEQ_CH0,
+				scan_mask & AMS_REG_SEQ0_MASK);
+		ams->pl_bus->write(ams, AMS_REG_SEQ_CH2, AMS_REG_SEQ2_MASK &
+				(scan_mask >> AMS_REG_SEQ2_MASK_SHIFT));
+		ams->pl_bus->write(ams, AMS_REG_SEQ_CH1, AMS_REG_SEQ1_MASK &
+				(scan_mask >> AMS_REG_SEQ1_MASK_SHIFT));
+
+		/* set continuous sequence mode */
+		ams->pl_bus->update(ams, AMS_REG_CONFIG1, AMS_CONF1_SEQ_MASK,
+				AMS_CONF1_SEQ_CONTINUOUS);
+	}
+}
+
+static int iio_ams_init_device(struct ams *ams)
+{
+	int ret = 0;
+	u32 reg;
+
+	/* reset AMS */
+	if (ams->ps_base) {
+		ams_ps_write_reg(ams, AMS_VP_VN, AMS_PS_RESET_VALUE);
+
+		ret = readl_poll_timeout(ams->base + AMS_PS_CSTS, reg,
+					 (reg & AMS_PS_CSTS_PS_READY) ==
+					 AMS_PS_CSTS_PS_READY, 0,
+					 AMS_INIT_TIMEOUT);
+		if (ret)
+			return ret;
+
+		/* put sysmon in a default state */
+		ams_ps_update_reg(ams, AMS_REG_CONFIG1, AMS_CONF1_SEQ_MASK,
+				  AMS_CONF1_SEQ_DEFAULT);
+	}
+
+	if (ams->pl_base) {
+		ams->pl_bus->write(ams, AMS_VP_VN, AMS_PL_RESET_VALUE);
+
+		ret = readl_poll_timeout(ams->base + AMS_PL_CSTS, reg,
+					 (reg & AMS_PL_CSTS_ACCESS_MASK) ==
+					 AMS_PL_CSTS_ACCESS_MASK, 0,
+					 AMS_INIT_TIMEOUT);
+		if (ret)
+			return ret;
+
+		/* put sysmon in a default state */
+		ams->pl_bus->update(ams, AMS_REG_CONFIG1, AMS_CONF1_SEQ_MASK,
+				    AMS_CONF1_SEQ_DEFAULT);
+	}
+
+	iio_ams_disable_all_alarm(ams);
+
+	/* Disable interrupt */
+	ams_update_intrmask(ams, ~0, ~0);
+
+	/* Clear any pending interrupt */
+	ams_write_reg(ams, AMS_ISR_0, AMS_ISR0_ALARM_MASK);
+	ams_write_reg(ams, AMS_ISR_1, AMS_ISR1_ALARM_MASK);
+
+	return ret;
+}
+
+static void ams_enable_single_channel(struct ams *ams, unsigned int offset)
+{
+	u8 channel_num = 0;
+
+	switch (offset) {
+	case AMS_VCC_PSPLL0:
+		channel_num = AMS_VCC_PSPLL0_CH;
+		break;
+	case AMS_VCC_PSPLL3:
+		channel_num = AMS_VCC_PSPLL3_CH;
+		break;
+	case AMS_VCCINT:
+		channel_num = AMS_VCCINT_CH;
+		break;
+	case AMS_VCCBRAM:
+		channel_num = AMS_VCCBRAM_CH;
+		break;
+	case AMS_VCCAUX:
+		channel_num = AMS_VCCAUX_CH;
+		break;
+	case AMS_PSDDRPLL:
+		channel_num = AMS_PSDDRPLL_CH;
+		break;
+	case AMS_PSINTFPDDR:
+		channel_num = AMS_PSINTFPDDR_CH;
+		break;
+	default:
+		break;
+	}
+
+	/* set single channel, sequencer off mode */
+	ams_ps_update_reg(ams, AMS_REG_CONFIG1, AMS_CONF1_SEQ_MASK,
+			AMS_CONF1_SEQ_SINGLE_CHANNEL);
+
+	/* write the channel number */
+	ams_ps_update_reg(ams, AMS_REG_CONFIG0, AMS_CONF0_CHANNEL_NUM_MASK,
+			channel_num);
+	mdelay(1);
+}
+
+static void ams_read_vcc_reg(struct ams *ams, unsigned int offset, u32 *data)
+{
+	ams_enable_single_channel(ams, offset);
+	ams_read_reg(ams, offset, data);
+	ams_enable_channel_sequence(ams);
+}
+
+static int ams_read_raw(struct iio_dev *indio_dev,
+			struct iio_chan_spec const *chan,
+			int *val, int *val2, long mask)
+{
+	struct ams *ams = iio_priv(indio_dev);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		mutex_lock(&ams->mutex);
+		if (chan->scan_index >= (PS_SEQ_MAX * 3))
+			ams_read_vcc_reg(ams, chan->address, val);
+		else if (chan->scan_index >= PS_SEQ_MAX)
+			ams->pl_bus->read(ams, chan->address, val);
+		else
+			ams_ps_read_reg(ams, chan->address, val);
+		mutex_unlock(&ams->mutex);
+
+		*val2 = 0;
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SCALE:
+		switch (chan->type) {
+		case IIO_VOLTAGE:
+			switch (chan->address) {
+			case AMS_SUPPLY1:
+			case AMS_SUPPLY2:
+			case AMS_SUPPLY3:
+			case AMS_SUPPLY4:
+				*val = AMS_SUPPLY_SCALE_3VOLT;
+				break;
+			case AMS_SUPPLY5:
+			case AMS_SUPPLY6:
+				if (chan->scan_index < PS_SEQ_MAX)
+					*val = AMS_SUPPLY_SCALE_6VOLT;
+				else
+					*val = AMS_SUPPLY_SCALE_3VOLT;
+				break;
+			case AMS_SUPPLY7:
+			case AMS_SUPPLY8:
+				*val = AMS_SUPPLY_SCALE_6VOLT;
+				break;
+			case AMS_SUPPLY9:
+			case AMS_SUPPLY10:
+				if (chan->scan_index < PS_SEQ_MAX)
+					*val = AMS_SUPPLY_SCALE_3VOLT;
+				else
+					*val = AMS_SUPPLY_SCALE_6VOLT;
+				break;
+			default:
+				if (chan->scan_index >= (PS_SEQ_MAX * 3))
+					*val = AMS_SUPPLY_SCALE_3VOLT;
+				else
+					*val = AMS_SUPPLY_SCALE_1VOLT;
+				break;
+			}
+			*val2 = AMS_SUPPLY_SCALE_DIV_BIT;
+			return IIO_VAL_FRACTIONAL_LOG2;
+		case IIO_TEMP:
+			*val = AMS_TEMP_SCALE;
+			*val2 = AMS_TEMP_SCALE_DIV_BIT;
+			return IIO_VAL_FRACTIONAL_LOG2;
+		default:
+			return -EINVAL;
+		}
+	case IIO_CHAN_INFO_OFFSET:
+		/* Only the temperature channel has an offset */
+		*val = AMS_TEMP_OFFSET;
+		*val2 = 0;
+		return IIO_VAL_INT;
+	}
+
+	return -EINVAL;
+}
+
+static int ams_get_alarm_offset(int scan_index, enum iio_event_direction dir)
+{
+	int offset = 0;
+
+	if (scan_index >= PS_SEQ_MAX)
+		scan_index -= PS_SEQ_MAX;
+
+	if (dir == IIO_EV_DIR_FALLING) {
+		if (scan_index < AMS_SEQ_SUPPLY7)
+			offset = AMS_ALARM_THRESOLD_OFF_10;
+		else
+			offset = AMS_ALARM_THRESOLD_OFF_20;
+	}
+
+	switch (scan_index) {
+	case AMS_SEQ_TEMP:
+		return (AMS_ALARM_TEMP + offset);
+	case AMS_SEQ_SUPPLY1:
+		return (AMS_ALARM_SUPPLY1 + offset);
+	case AMS_SEQ_SUPPLY2:
+		return (AMS_ALARM_SUPPLY2 + offset);
+	case AMS_SEQ_SUPPLY3:
+		return (AMS_ALARM_SUPPLY3 + offset);
+	case AMS_SEQ_SUPPLY4:
+		return (AMS_ALARM_SUPPLY4 + offset);
+	case AMS_SEQ_SUPPLY5:
+		return (AMS_ALARM_SUPPLY5 + offset);
+	case AMS_SEQ_SUPPLY6:
+		return (AMS_ALARM_SUPPLY6 + offset);
+	case AMS_SEQ_SUPPLY7:
+		return (AMS_ALARM_SUPPLY7 + offset);
+	case AMS_SEQ_SUPPLY8:
+		return (AMS_ALARM_SUPPLY8 + offset);
+	case AMS_SEQ_SUPPLY9:
+		return (AMS_ALARM_SUPPLY9 + offset);
+	case AMS_SEQ_SUPPLY10:
+		return (AMS_ALARM_SUPPLY10 + offset);
+	case AMS_SEQ_VCCAMS:
+		return (AMS_ALARM_VCCAMS + offset);
+	case AMS_SEQ_TEMP_REMOTE:
+		return (AMS_ALARM_TEMP_REMOTE + offset);
+	}
+
+	return 0;
+}
+
+static const struct iio_chan_spec *ams_event_to_channel(
+		struct iio_dev *indio_dev, u32 event)
+{
+	int scan_index = 0, i;
+
+	if (event >= AMS_PL_ALARM_START) {
+		event -= AMS_PL_ALARM_START;
+		scan_index = PS_SEQ_MAX;
+	}
+
+	switch (event) {
+	case AMS_ALARM_BIT_TEMP:
+		scan_index += AMS_SEQ_TEMP;
+		break;
+	case AMS_ALARM_BIT_SUPPLY1:
+		scan_index += AMS_SEQ_SUPPLY1;
+		break;
+	case AMS_ALARM_BIT_SUPPLY2:
+		scan_index += AMS_SEQ_SUPPLY2;
+		break;
+	case AMS_ALARM_BIT_SUPPLY3:
+		scan_index += AMS_SEQ_SUPPLY3;
+		break;
+	case AMS_ALARM_BIT_SUPPLY4:
+		scan_index += AMS_SEQ_SUPPLY4;
+		break;
+	case AMS_ALARM_BIT_SUPPLY5:
+		scan_index += AMS_SEQ_SUPPLY5;
+		break;
+	case AMS_ALARM_BIT_SUPPLY6:
+		scan_index += AMS_SEQ_SUPPLY6;
+		break;
+	case AMS_ALARM_BIT_SUPPLY7:
+		scan_index += AMS_SEQ_SUPPLY7;
+		break;
+	case AMS_ALARM_BIT_SUPPLY8:
+		scan_index += AMS_SEQ_SUPPLY8;
+		break;
+	case AMS_ALARM_BIT_SUPPLY9:
+		scan_index += AMS_SEQ_SUPPLY9;
+		break;
+	case AMS_ALARM_BIT_SUPPLY10:
+		scan_index += AMS_SEQ_SUPPLY10;
+		break;
+	case AMS_ALARM_BIT_VCCAMS:
+		scan_index += AMS_SEQ_VCCAMS;
+		break;
+	case AMS_ALARM_BIT_TEMP_REMOTE:
+		scan_index += AMS_SEQ_TEMP_REMOTE;
+		break;
+	}
+
+	for (i = 0; i < indio_dev->num_channels; i++)
+		if (indio_dev->channels[i].scan_index == scan_index)
+			break;
+
+	return &indio_dev->channels[i];
+}
+
+static int ams_get_alarm_mask(int scan_index)
+{
+	int bit = 0;
+
+	if (scan_index >= PS_SEQ_MAX) {
+		bit = AMS_PL_ALARM_START;
+		scan_index -= PS_SEQ_MAX;
+	}
+
+	switch (scan_index) {
+	case AMS_SEQ_TEMP:
+		return BIT(AMS_ALARM_BIT_TEMP + bit);
+	case AMS_SEQ_SUPPLY1:
+		return BIT(AMS_ALARM_BIT_SUPPLY1 + bit);
+	case AMS_SEQ_SUPPLY2:
+		return BIT(AMS_ALARM_BIT_SUPPLY2 + bit);
+	case AMS_SEQ_SUPPLY3:
+		return BIT(AMS_ALARM_BIT_SUPPLY3 + bit);
+	case AMS_SEQ_SUPPLY4:
+		return BIT(AMS_ALARM_BIT_SUPPLY4 + bit);
+	case AMS_SEQ_SUPPLY5:
+		return BIT(AMS_ALARM_BIT_SUPPLY5 + bit);
+	case AMS_SEQ_SUPPLY6:
+		return BIT(AMS_ALARM_BIT_SUPPLY6 + bit);
+	case AMS_SEQ_SUPPLY7:
+		return BIT(AMS_ALARM_BIT_SUPPLY7 + bit);
+	case AMS_SEQ_SUPPLY8:
+		return BIT(AMS_ALARM_BIT_SUPPLY8 + bit);
+	case AMS_SEQ_SUPPLY9:
+		return BIT(AMS_ALARM_BIT_SUPPLY9 + bit);
+	case AMS_SEQ_SUPPLY10:
+		return BIT(AMS_ALARM_BIT_SUPPLY10 + bit);
+	case AMS_SEQ_VCCAMS:
+		return BIT(AMS_ALARM_BIT_VCCAMS + bit);
+	case AMS_SEQ_TEMP_REMOTE:
+		return BIT(AMS_ALARM_BIT_TEMP_REMOTE + bit);
+	}
+
+	return 0;
+}
+
+static int ams_read_event_config(struct iio_dev *indio_dev,
+				 const struct iio_chan_spec *chan,
+				 enum iio_event_type type,
+				 enum iio_event_direction dir)
+{
+	struct ams *ams = iio_priv(indio_dev);
+
+	return (ams->alarm_mask & ams_get_alarm_mask(chan->scan_index)) ? 1 : 0;
+}
+
+static int ams_write_event_config(struct iio_dev *indio_dev,
+				  const struct iio_chan_spec *chan,
+				  enum iio_event_type type,
+				  enum iio_event_direction dir,
+				  int state)
+{
+	struct ams *ams = iio_priv(indio_dev);
+	unsigned int alarm;
+
+	alarm = ams_get_alarm_mask(chan->scan_index);
+
+	mutex_lock(&ams->mutex);
+
+	if (state)
+		ams->alarm_mask |= alarm;
+	else
+		ams->alarm_mask &= ~alarm;
+
+	iio_ams_update_alarm(ams, ams->alarm_mask);
+
+	mutex_unlock(&ams->mutex);
+
+	return 0;
+}
+
+static int ams_read_event_value(struct iio_dev *indio_dev,
+				const struct iio_chan_spec *chan,
+				enum iio_event_type type,
+				enum iio_event_direction dir,
+				enum iio_event_info info, int *val, int *val2)
+{
+	struct ams *ams = iio_priv(indio_dev);
+	unsigned int offset = ams_get_alarm_offset(chan->scan_index, dir);
+
+	mutex_lock(&ams->mutex);
+
+	if (chan->scan_index >= PS_SEQ_MAX)
+		ams->pl_bus->read(ams, offset, val);
+	else
+		ams_ps_read_reg(ams, offset, val);
+
+	mutex_unlock(&ams->mutex);
+
+	*val2 = 0;
+	return IIO_VAL_INT;
+}
+
+static int ams_write_event_value(struct iio_dev *indio_dev,
+				 const struct iio_chan_spec *chan,
+				 enum iio_event_type type,
+				 enum iio_event_direction dir,
+				 enum iio_event_info info, int val, int val2)
+{
+	struct ams *ams = iio_priv(indio_dev);
+	unsigned int offset;
+
+	mutex_lock(&ams->mutex);
+
+	/* Set temperature channel threshold to direct threshold */
+	if (chan->type == IIO_TEMP) {
+		offset = ams_get_alarm_offset(chan->scan_index,
+					      IIO_EV_DIR_FALLING);
+
+		if (chan->scan_index >= PS_SEQ_MAX)
+			ams->pl_bus->update(ams, offset,
+					    AMS_ALARM_THR_DIRECT_MASK,
+					    AMS_ALARM_THR_DIRECT_MASK);
+		else
+			ams_ps_update_reg(ams, offset,
+					  AMS_ALARM_THR_DIRECT_MASK,
+					  AMS_ALARM_THR_DIRECT_MASK);
+	}
+
+	offset = ams_get_alarm_offset(chan->scan_index, dir);
+	if (chan->scan_index >= PS_SEQ_MAX)
+		ams->pl_bus->write(ams, offset, val);
+	else
+		ams_ps_write_reg(ams, offset, val);
+
+	mutex_unlock(&ams->mutex);
+
+	return 0;
+}
+
+static void ams_handle_event(struct iio_dev *indio_dev, u32 event)
+{
+	const struct iio_chan_spec *chan;
+
+	chan = ams_event_to_channel(indio_dev, event);
+
+	if (chan->type == IIO_TEMP) {
+		/* The temperature channel only supports over-temperature
+		 * events
+		 */
+		iio_push_event(indio_dev,
+			       IIO_UNMOD_EVENT_CODE(chan->type, chan->channel,
+						    IIO_EV_TYPE_THRESH,
+						    IIO_EV_DIR_RISING),
+			iio_get_time_ns(indio_dev));
+	} else {
+		/* For other channels we don't know whether it is a upper or
+		 * lower threshold event. Userspace will have to check the
+		 * channel value if it wants to know.
+		 */
+		iio_push_event(indio_dev,
+			       IIO_UNMOD_EVENT_CODE(chan->type, chan->channel,
+						    IIO_EV_TYPE_THRESH,
+						    IIO_EV_DIR_EITHER),
+			iio_get_time_ns(indio_dev));
+	}
+}
+
+static void ams_handle_events(struct iio_dev *indio_dev, unsigned long events)
+{
+	unsigned int bit;
+
+	for_each_set_bit(bit, &events, AMS_NO_OF_ALARMS)
+		ams_handle_event(indio_dev, bit);
+}
+
+/**
+ * ams_unmask_worker - ams alarm interrupt unmask worker
+ * @work :		work to be done
+ *
+ * The ZynqMP threshold interrupts are level sensitive. Since we can't make the
+ * threshold condition go way from within the interrupt handler, this means as
+ * soon as a threshold condition is present we would enter the interrupt handler
+ * again and again. To work around this we mask all active thresholds interrupts
+ * in the interrupt handler and start a timer. In this timer we poll the
+ * interrupt status and only if the interrupt is inactive we unmask it again.
+ */
+static void ams_unmask_worker(struct work_struct *work)
+{
+	struct ams *ams = container_of(work, struct ams, ams_unmask_work.work);
+	unsigned int status, unmask;
+
+	spin_lock_irq(&ams->lock);
+
+	ams_read_reg(ams, AMS_ISR_0, &status);
+
+	/* Clear those bits which are not active anymore */
+	unmask = (ams->masked_alarm ^ status) & ams->masked_alarm;
+
+	/* clear status of disabled alarm */
+	unmask |= ams->intr_mask;
+
+	ams->masked_alarm &= status;
+
+	/* Also clear those which are masked out anyway */
+	ams->masked_alarm &= ~ams->intr_mask;
+
+	/* Clear the interrupts before we unmask them */
+	ams_write_reg(ams, AMS_ISR_0, unmask);
+
+	ams_update_intrmask(ams, 0, 0);
+
+	spin_unlock_irq(&ams->lock);
+
+	/* if still pending some alarm re-trigger the timer */
+	if (ams->masked_alarm)
+		schedule_delayed_work(&ams->ams_unmask_work,
+				      msecs_to_jiffies(AMS_UNMASK_TIMEOUT));
+}
+
+static irqreturn_t ams_iio_irq(int irq, void *data)
+{
+	unsigned int isr0, isr1;
+	struct iio_dev *indio_dev = data;
+	struct ams *ams = iio_priv(indio_dev);
+
+	spin_lock(&ams->lock);
+
+	ams_read_reg(ams, AMS_ISR_0, &isr0);
+	ams_read_reg(ams, AMS_ISR_1, &isr1);
+
+	/* only process alarm that are not masked */
+	isr0 &= ~((ams->intr_mask & AMS_ISR0_ALARM_MASK) | ams->masked_alarm);
+	isr1 &= ~(ams->intr_mask >> AMS_ISR1_INTR_MASK_SHIFT);
+
+	/* clear interrupt */
+	ams_write_reg(ams, AMS_ISR_0, isr0);
+	ams_write_reg(ams, AMS_ISR_1, isr1);
+
+	if (isr0) {
+		/* Once the alarm interrupt occurred, mask until get cleared */
+		ams->masked_alarm |= isr0;
+		ams_update_intrmask(ams, 0, 0);
+
+		ams_handle_events(indio_dev, isr0);
+
+		schedule_delayed_work(&ams->ams_unmask_work,
+				      msecs_to_jiffies(AMS_UNMASK_TIMEOUT));
+	}
+
+	spin_unlock(&ams->lock);
+
+	return IRQ_HANDLED;
+}
+
+static const struct iio_event_spec ams_temp_events[] = {
+	{
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_RISING,
+		.mask_separate = BIT(IIO_EV_INFO_ENABLE) |
+				BIT(IIO_EV_INFO_VALUE),
+	},
+};
+
+static const struct iio_event_spec ams_voltage_events[] = {
+	{
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_RISING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE),
+	}, {
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_FALLING,
+		.mask_separate = BIT(IIO_EV_INFO_VALUE),
+	}, {
+		.type = IIO_EV_TYPE_THRESH,
+		.dir = IIO_EV_DIR_EITHER,
+		.mask_separate = BIT(IIO_EV_INFO_ENABLE),
+	},
+};
+
+static const struct iio_chan_spec ams_ps_channels[] = {
+	AMS_PS_CHAN_TEMP(AMS_SEQ_TEMP, AMS_TEMP, "ps_temp"),
+	AMS_PS_CHAN_TEMP(AMS_SEQ_TEMP_REMOTE, AMS_TEMP_REMOTE, "remote_temp"),
+	AMS_PS_CHAN_VOLTAGE(AMS_SEQ_SUPPLY1, AMS_SUPPLY1, "vccpsintlp"),
+	AMS_PS_CHAN_VOLTAGE(AMS_SEQ_SUPPLY2, AMS_SUPPLY2, "vccpsintfp"),
+	AMS_PS_CHAN_VOLTAGE(AMS_SEQ_SUPPLY3, AMS_SUPPLY3, "vccpsaux"),
+	AMS_PS_CHAN_VOLTAGE(AMS_SEQ_SUPPLY4, AMS_SUPPLY4, "vccpsddr"),
+	AMS_PS_CHAN_VOLTAGE(AMS_SEQ_SUPPLY5, AMS_SUPPLY5, "vccpsio3"),
+	AMS_PS_CHAN_VOLTAGE(AMS_SEQ_SUPPLY6, AMS_SUPPLY6, "vccpsio0"),
+	AMS_PS_CHAN_VOLTAGE(AMS_SEQ_SUPPLY7, AMS_SUPPLY7, "vccpsio1"),
+	AMS_PS_CHAN_VOLTAGE(AMS_SEQ_SUPPLY8, AMS_SUPPLY8, "vccpsio2"),
+	AMS_PS_CHAN_VOLTAGE(AMS_SEQ_SUPPLY9, AMS_SUPPLY9, "psmgtravcc"),
+	AMS_PS_CHAN_VOLTAGE(AMS_SEQ_SUPPLY10, AMS_SUPPLY10, "psmgtravtt"),
+	AMS_PS_CHAN_VOLTAGE(AMS_SEQ_VCCAMS, AMS_VCCAMS, "vccams"),
+};
+
+static const struct iio_chan_spec ams_pl_channels[] = {
+	AMS_PL_CHAN_TEMP(AMS_SEQ_TEMP, AMS_TEMP, "pl_temp"),
+	AMS_PL_CHAN_VOLTAGE(AMS_SEQ_SUPPLY1, AMS_SUPPLY1, "vccint", true),
+	AMS_PL_CHAN_VOLTAGE(AMS_SEQ_SUPPLY2, AMS_SUPPLY2, "vccaux", true),
+	AMS_PL_CHAN_VOLTAGE(AMS_SEQ_VREFP, AMS_VREFP, "vccvrefp", false),
+	AMS_PL_CHAN_VOLTAGE(AMS_SEQ_VREFN, AMS_VREFN, "vccvrefn", false),
+	AMS_PL_CHAN_VOLTAGE(AMS_SEQ_SUPPLY3, AMS_SUPPLY3, "vccbram", true),
+	AMS_PL_CHAN_VOLTAGE(AMS_SEQ_SUPPLY4, AMS_SUPPLY4, "vccplintlp", true),
+	AMS_PL_CHAN_VOLTAGE(AMS_SEQ_SUPPLY5, AMS_SUPPLY5, "vccplintfp", true),
+	AMS_PL_CHAN_VOLTAGE(AMS_SEQ_SUPPLY6, AMS_SUPPLY6, "vccplaux", true),
+	AMS_PL_CHAN_VOLTAGE(AMS_SEQ_VCCAMS, AMS_VCCAMS, "vccams", true),
+	AMS_PL_CHAN_VOLTAGE(AMS_SEQ_VP_VN, AMS_VP_VN, "vccvpvn", false),
+	AMS_PL_CHAN_VOLTAGE(AMS_SEQ_SUPPLY7, AMS_SUPPLY7, "vuser0", true),
+	AMS_PL_CHAN_VOLTAGE(AMS_SEQ_SUPPLY8, AMS_SUPPLY8, "vuser1", true),
+	AMS_PL_CHAN_VOLTAGE(AMS_SEQ_SUPPLY9, AMS_SUPPLY9, "vuser2", true),
+	AMS_PL_CHAN_VOLTAGE(AMS_SEQ_SUPPLY10, AMS_SUPPLY10, "vuser3", true),
+	AMS_PL_AUX_CHAN_VOLTAGE(0, "vccaux0"),
+	AMS_PL_AUX_CHAN_VOLTAGE(1, "vccaux1"),
+	AMS_PL_AUX_CHAN_VOLTAGE(2, "vccaux2"),
+	AMS_PL_AUX_CHAN_VOLTAGE(3, "vccaux3"),
+	AMS_PL_AUX_CHAN_VOLTAGE(4, "vccaux4"),
+	AMS_PL_AUX_CHAN_VOLTAGE(5, "vccaux5"),
+	AMS_PL_AUX_CHAN_VOLTAGE(6, "vccaux6"),
+	AMS_PL_AUX_CHAN_VOLTAGE(7, "vccaux7"),
+	AMS_PL_AUX_CHAN_VOLTAGE(8, "vccaux8"),
+	AMS_PL_AUX_CHAN_VOLTAGE(9, "vccaux9"),
+	AMS_PL_AUX_CHAN_VOLTAGE(10, "vccaux10"),
+	AMS_PL_AUX_CHAN_VOLTAGE(11, "vccaux11"),
+	AMS_PL_AUX_CHAN_VOLTAGE(12, "vccaux12"),
+	AMS_PL_AUX_CHAN_VOLTAGE(13, "vccaux13"),
+	AMS_PL_AUX_CHAN_VOLTAGE(14, "vccaux14"),
+	AMS_PL_AUX_CHAN_VOLTAGE(15, "vccaux15"),
+};
+
+static const struct iio_chan_spec ams_ctrl_channels[] = {
+	AMS_CTRL_CHAN_VOLTAGE(AMS_SEQ_VCC_PSPLL, AMS_VCC_PSPLL0, "vcc_pspll0"),
+	AMS_CTRL_CHAN_VOLTAGE(AMS_SEQ_VCC_PSBATT, AMS_VCC_PSPLL3, "vcc_psbatt"),
+	AMS_CTRL_CHAN_VOLTAGE(AMS_SEQ_VCCINT, AMS_VCCINT, "vccint"),
+	AMS_CTRL_CHAN_VOLTAGE(AMS_SEQ_VCCBRAM, AMS_VCCBRAM, "vccbram"),
+	AMS_CTRL_CHAN_VOLTAGE(AMS_SEQ_VCCAUX, AMS_VCCAUX, "vccaux"),
+	AMS_CTRL_CHAN_VOLTAGE(AMS_SEQ_PSDDRPLL, AMS_PSDDRPLL, "vcc_psddrpll"),
+	AMS_CTRL_CHAN_VOLTAGE(AMS_SEQ_INTDDR, AMS_PSINTFPDDR, "vccpsintfpddr"),
+};
+
+static int ams_init_module(struct iio_dev *indio_dev, struct device_node *np,
+			   struct iio_chan_spec *channels)
+{
+	struct ams *ams = iio_priv(indio_dev);
+	struct device_node *chan_node, *child;
+	int ret, num_channels = 0;
+	unsigned int reg;
+
+	if (of_device_is_compatible(np, "xlnx,zynqmp-ams-ps")) {
+		ams->ps_base = of_iomap(np, 0);
+		if (!ams->ps_base)
+			return -ENXIO;
+
+		/* add PS channels to iio device channels */
+		memcpy(channels + num_channels, ams_ps_channels,
+		       sizeof(ams_ps_channels));
+		num_channels += ARRAY_SIZE(ams_ps_channels);
+	} else if (of_device_is_compatible(np, "xlnx,zynqmp-ams-pl")) {
+		ams->pl_base = of_iomap(np, 0);
+		if (!ams->pl_base)
+			return -ENXIO;
+
+		/* Copy only first 10 fix channels */
+		memcpy(channels + num_channels, ams_pl_channels,
+		       AMS_PL_MAX_FIXED_CHANNEL * sizeof(*channels));
+		num_channels += AMS_PL_MAX_FIXED_CHANNEL;
+
+		chan_node = of_get_child_by_name(np, "xlnx,ext-channels");
+		if (chan_node) {
+			for_each_child_of_node(chan_node, child) {
+				ret = of_property_read_u32(child, "reg", &reg);
+				if (ret || reg > AMS_PL_MAX_EXT_CHANNEL)
+					continue;
+
+				memcpy(&channels[num_channels],
+				       &ams_pl_channels[reg +
+				       AMS_PL_MAX_FIXED_CHANNEL],
+				       sizeof(*channels));
+
+				if (of_property_read_bool(child,
+							  "xlnx,bipolar"))
+					channels[num_channels].
+						scan_type.sign = 's';
+
+				num_channels += 1;
+			}
+		}
+		of_node_put(chan_node);
+	} else if (of_device_is_compatible(np, "xlnx,zynqmp-ams")) {
+		/* add AMS channels to iio device channels */
+		memcpy(channels + num_channels, ams_ctrl_channels,
+				sizeof(ams_ctrl_channels));
+		num_channels += ARRAY_SIZE(ams_ctrl_channels);
+	} else {
+		return -EINVAL;
+	}
+
+	return num_channels;
+}
+
+static int ams_parse_dt(struct iio_dev *indio_dev, struct platform_device *pdev)
+{
+	struct ams *ams = iio_priv(indio_dev);
+	struct iio_chan_spec *ams_channels, *dev_channels;
+	struct device_node *child_node = NULL, *np = pdev->dev.of_node;
+	int ret, chan_vol = 0, chan_temp = 0, i, rising_off, falling_off;
+	unsigned int num_channels = 0;
+
+	/* Initialize buffer for channel specification */
+	ams_channels = kzalloc(sizeof(ams_ps_channels) +
+			       sizeof(ams_pl_channels) +
+			       sizeof(ams_ctrl_channels), GFP_KERNEL);
+	if (!ams_channels)
+		return -ENOMEM;
+
+	if (of_device_is_available(np)) {
+		ret = ams_init_module(indio_dev, np, ams_channels);
+		if (ret < 0) {
+			kfree(ams_channels);
+			return ret;
+		}
+
+		num_channels += ret;
+	}
+
+	for_each_child_of_node(np, child_node) {
+		if (of_device_is_available(child_node)) {
+			ret = ams_init_module(indio_dev, child_node,
+					      ams_channels + num_channels);
+			if (ret < 0) {
+				kfree(ams_channels);
+				return ret;
+			}
+
+			num_channels += ret;
+		}
+	}
+
+	for (i = 0; i < num_channels; i++) {
+		if (ams_channels[i].type == IIO_VOLTAGE)
+			ams_channels[i].channel = chan_vol++;
+		else
+			ams_channels[i].channel = chan_temp++;
+
+		if (ams_channels[i].scan_index < (PS_SEQ_MAX * 3)) {
+			/* set threshold to max and min for each channel */
+			falling_off = ams_get_alarm_offset(
+					ams_channels[i].scan_index,
+					IIO_EV_DIR_FALLING);
+			rising_off = ams_get_alarm_offset(
+					ams_channels[i].scan_index,
+					IIO_EV_DIR_RISING);
+			if (ams_channels[i].scan_index >= PS_SEQ_MAX) {
+				ams->pl_bus->write(ams, falling_off,
+						AMS_ALARM_THR_MIN);
+				ams->pl_bus->write(ams, rising_off,
+						AMS_ALARM_THR_MAX);
+			} else {
+				ams_ps_write_reg(ams, falling_off,
+						AMS_ALARM_THR_MIN);
+				ams_ps_write_reg(ams, rising_off,
+						AMS_ALARM_THR_MAX);
+			}
+		}
+	}
+
+	dev_channels = devm_kzalloc(&pdev->dev, sizeof(*dev_channels) *
+				    num_channels, GFP_KERNEL);
+	if (!dev_channels) {
+		kfree(ams_channels);
+		return -ENOMEM;
+	}
+
+	memcpy(dev_channels, ams_channels,
+	       sizeof(*ams_channels) * num_channels);
+	kfree(ams_channels);
+	indio_dev->channels = dev_channels;
+	indio_dev->num_channels = num_channels;
+
+	return 0;
+}
+
+static const struct iio_info iio_pl_info = {
+	.read_raw = &ams_read_raw,
+	.read_event_config = &ams_read_event_config,
+	.write_event_config = &ams_write_event_config,
+	.read_event_value = &ams_read_event_value,
+	.write_event_value = &ams_write_event_value,
+};
+
+static const struct ams_pl_bus_ops ams_pl_apb = {
+	.read = ams_apb_pl_read_reg,
+	.write = ams_apb_pl_write_reg,
+	.update = ams_apb_pl_update_reg,
+};
+
+static const struct of_device_id ams_of_match_table[] = {
+	{ .compatible = "xlnx,zynqmp-ams", &ams_pl_apb },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, ams_of_match_table);
+
+static int ams_probe(struct platform_device *pdev)
+{
+	struct iio_dev *indio_dev;
+	struct ams *ams;
+	struct resource *res;
+	const struct of_device_id *id;
+	int ret;
+
+	if (!pdev->dev.of_node)
+		return -ENODEV;
+
+	id = of_match_node(ams_of_match_table, pdev->dev.of_node);
+	if (!id)
+		return -ENODEV;
+
+	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*ams));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	ams = iio_priv(indio_dev);
+	ams->pl_bus = id->data;
+	mutex_init(&ams->mutex);
+	spin_lock_init(&ams->lock);
+
+	indio_dev->dev.parent = &pdev->dev;
+	indio_dev->dev.of_node = pdev->dev.of_node;
+	indio_dev->name = "ams";
+
+	indio_dev->info = &iio_pl_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ams-base");
+	ams->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(ams->base))
+		return PTR_ERR(ams->base);
+
+	INIT_DELAYED_WORK(&ams->ams_unmask_work, ams_unmask_worker);
+
+	ams->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(ams->clk))
+		return PTR_ERR(ams->clk);
+	clk_prepare_enable(ams->clk);
+
+	ret = iio_ams_init_device(ams);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to initialize AMS\n");
+		goto clk_disable;
+	}
+
+	ret = ams_parse_dt(indio_dev, pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "failure in parsing DT\n");
+		goto clk_disable;
+	}
+
+	ams_enable_channel_sequence(ams);
+
+	ams->irq = platform_get_irq_byname(pdev, "ams-irq");
+	ret = devm_request_irq(&pdev->dev, ams->irq, &ams_iio_irq, 0, "ams-irq",
+			       indio_dev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to register interrupt\n");
+		goto clk_disable;
+	}
+
+	platform_set_drvdata(pdev, indio_dev);
+
+	return iio_device_register(indio_dev);
+
+clk_disable:
+	clk_disable_unprepare(ams->clk);
+	return ret;
+}
+
+static int ams_remove(struct platform_device *pdev)
+{
+	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+	struct ams *ams = iio_priv(indio_dev);
+
+	cancel_delayed_work(&ams->ams_unmask_work);
+
+	/* Unregister the device */
+	iio_device_unregister(indio_dev);
+	clk_disable_unprepare(ams->clk);
+	return 0;
+}
+
+static int __maybe_unused ams_suspend(struct device *dev)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct ams *ams = iio_priv(indio_dev);
+
+	clk_disable_unprepare(ams->clk);
+
+	return 0;
+}
+
+static int __maybe_unused ams_resume(struct device *dev)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct ams *ams = iio_priv(indio_dev);
+
+	clk_prepare_enable(ams->clk);
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(ams_pm_ops, ams_suspend, ams_resume);
+
+static struct platform_driver ams_driver = {
+	.probe = ams_probe,
+	.remove = ams_remove,
+	.driver = {
+		.name = "ams",
+		.pm	= &ams_pm_ops,
+		.of_match_table = ams_of_match_table,
+	},
+};
+module_platform_driver(ams_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Rajnikant Bhojani <rajnikant.bhojani@xilinx.com>");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/xilinx-ams.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/xilinx-ams.h
@@ -0,0 +1,278 @@
+#ifndef __XILINX_AMS_H__
+#define __XILINX_AMS_H__
+
+#define AMS_MISC_CTRL     0x000
+#define AMS_ISR_0         0x010
+#define AMS_ISR_1         0x014
+#define AMS_IMR_0         0x018
+#define AMS_IMR_1         0x01c
+#define AMS_IER_0         0x020
+#define AMS_IER_1         0x024
+#define AMS_IDR_0         0x028
+#define AMS_IDR_1         0x02c
+#define AMS_PS_CSTS       0x040
+#define AMS_PL_CSTS       0x044
+#define AMS_MON_CSTS      0x050
+
+#define AMS_VCC_PSPLL0    0x060
+#define AMS_VCC_PSPLL3    0x06C
+#define AMS_VCCINT        0x078
+#define AMS_VCCBRAM       0x07C
+#define AMS_VCCAUX        0x080
+#define AMS_PSDDRPLL      0x084
+#define AMS_PSINTFPDDR    0x09C
+
+#define AMS_VCC_PSPLL0_CH 48
+#define AMS_VCC_PSPLL3_CH 51
+#define AMS_VCCINT_CH     54
+#define AMS_VCCBRAM_CH    55
+#define AMS_VCCAUX_CH     56
+#define AMS_PSDDRPLL_CH   57
+#define AMS_PSINTFPDDR_CH 63
+
+#define AMS_REG_CONFIG0   0x100
+#define AMS_REG_CONFIG1   0x104
+#define AMS_REG_CONFIG2   0x108
+#define AMS_REG_CONFIG3   0x10C
+#define AMS_REG_CONFIG4   0x110
+#define AMS_REG_SEQ_CH0   0x120
+#define AMS_REG_SEQ_CH1   0x124
+#define AMS_REG_SEQ_CH2   0x118
+
+#define AMS_TEMP          0x000
+#define AMS_SUPPLY1       0x004
+#define AMS_SUPPLY2       0x008
+#define AMS_VP_VN         0x00c
+#define AMS_VREFP         0x010
+#define AMS_VREFN         0x014
+#define AMS_SUPPLY3       0x018
+#define AMS_SUPPLY4       0x034
+#define AMS_SUPPLY5       0x038
+#define AMS_SUPPLY6       0x03c
+#define AMS_SUPPLY7       0x200
+#define AMS_SUPPLY8       0x204
+#define AMS_SUPPLY9       0x208
+#define AMS_SUPPLY10      0x20c
+#define AMS_VCCAMS        0x210
+#define AMS_TEMP_REMOTE   0x214
+
+#define AMS_REG_VAUX(x)   (0x40 + (4*(x)))
+#define AMS_REG_VUSER(x)  (0x200 + (4*(x)))
+
+#define AMS_PS_RESET_VALUE   0xFFFFU
+#define AMS_PL_RESET_VALUE   0xFFFFU
+
+#define AMS_CONF0_CHANNEL_NUM_MASK      (0x3f << 0)
+
+#define AMS_CONF1_SEQ_MASK              (0xf << 12)
+#define AMS_CONF1_SEQ_DEFAULT           (0 << 12)
+#define AMS_CONF1_SEQ_SINGLE_PASS       (1 << 12)
+#define AMS_CONF1_SEQ_CONTINUOUS        (2 << 12)
+#define AMS_CONF1_SEQ_SINGLE_CHANNEL    (3 << 12)
+
+#define AMS_REG_SEQ0_MASK        0xFFFF
+#define AMS_REG_SEQ2_MASK        0x3F
+#define AMS_REG_SEQ1_MASK        0xFFFF
+#define AMS_REG_SEQ2_MASK_SHIFT  16
+#define AMS_REG_SEQ1_MASK_SHIFT  22
+
+#define AMS_REGCFG1_ALARM_MASK   0xF0F
+#define AMS_REGCFG3_ALARM_MASK   0x3F
+
+#define AMS_ALARM_TEMP            0x140
+#define AMS_ALARM_SUPPLY1         0x144
+#define AMS_ALARM_SUPPLY2         0x148
+#define AMS_ALARM_OT              0x14c
+
+#define AMS_ALARM_SUPPLY3         0x160
+#define AMS_ALARM_SUPPLY4         0x164
+#define AMS_ALARM_SUPPLY5         0x168
+#define AMS_ALARM_SUPPLY6         0x16c
+#define AMS_ALARM_SUPPLY7         0x180
+#define AMS_ALARM_SUPPLY8         0x184
+#define AMS_ALARM_SUPPLY9         0x188
+#define AMS_ALARM_SUPPLY10        0x18c
+#define AMS_ALARM_VCCAMS          0x190
+#define AMS_ALARM_TEMP_REMOTE     0x194
+#define AMS_ALARM_THRESOLD_OFF_10 0x10
+#define AMS_ALARM_THRESOLD_OFF_20 0x20
+
+#define AMS_ALARM_THR_DIRECT_MASK 0x01
+#define AMS_ALARM_THR_MIN         0x0000
+#define AMS_ALARM_THR_MAX         0xffff
+
+#define AMS_NO_OF_ALARMS             32
+#define AMS_PL_ALARM_START           16
+#define AMS_ISR0_ALARM_MASK          0xFFFFFFFFU
+#define AMS_ISR1_ALARM_MASK          0xE000001FU
+#define AMS_ISR1_INTR_MASK_SHIFT     32
+#define AMS_ISR0_ALARM_2_TO_0_MASK     0x07
+#define AMS_ISR0_ALARM_6_TO_3_MASK     0x78
+#define AMS_ISR0_ALARM_12_TO_7_MASK    0x3F
+#define AMS_CONF1_ALARM_2_TO_0_SHIFT   1
+#define AMS_CONF1_ALARM_6_TO_3_SHIFT   5
+#define AMS_CONF3_ALARM_12_TO_7_SHIFT  8
+
+#define AMS_PS_CSTS_PS_READY       0x08010000U
+#define AMS_PL_CSTS_ACCESS_MASK    0x00000001U
+
+#define AMS_PL_MAX_FIXED_CHANNEL   10
+#define AMS_PL_MAX_EXT_CHANNEL     20
+
+#define AMS_INIT_TIMEOUT	10000
+
+/* Following scale and offset value is derivef from
+ * UG580 (v1.7) December 20, 2016
+ */
+#define AMS_SUPPLY_SCALE_1VOLT     1000
+#define AMS_SUPPLY_SCALE_3VOLT     3000
+#define AMS_SUPPLY_SCALE_6VOLT     6000
+#define AMS_SUPPLY_SCALE_DIV_BIT   16
+
+#define AMS_TEMP_SCALE             509314
+#define AMS_TEMP_SCALE_DIV_BIT     16
+#define AMS_TEMP_OFFSET            -((280230L << 16) / 509314)
+
+enum ams_alarm_bit {
+	AMS_ALARM_BIT_TEMP,
+	AMS_ALARM_BIT_SUPPLY1,
+	AMS_ALARM_BIT_SUPPLY2,
+	AMS_ALARM_BIT_SUPPLY3,
+	AMS_ALARM_BIT_SUPPLY4,
+	AMS_ALARM_BIT_SUPPLY5,
+	AMS_ALARM_BIT_SUPPLY6,
+	AMS_ALARM_BIT_RESERVED,
+	AMS_ALARM_BIT_SUPPLY7,
+	AMS_ALARM_BIT_SUPPLY8,
+	AMS_ALARM_BIT_SUPPLY9,
+	AMS_ALARM_BIT_SUPPLY10,
+	AMS_ALARM_BIT_VCCAMS,
+	AMS_ALARM_BIT_TEMP_REMOTE
+};
+
+enum ams_seq {
+	AMS_SEQ_VCC_PSPLL,
+	AMS_SEQ_VCC_PSBATT,
+	AMS_SEQ_VCCINT,
+	AMS_SEQ_VCCBRAM,
+	AMS_SEQ_VCCAUX,
+	AMS_SEQ_PSDDRPLL,
+	AMS_SEQ_INTDDR
+};
+
+enum ams_ps_pl_seq {
+	AMS_SEQ_CALIB,
+	AMS_SEQ_RSVD_1,
+	AMS_SEQ_RSVD_2,
+	AMS_SEQ_TEST,
+	AMS_SEQ_RSVD_4,
+	AMS_SEQ_SUPPLY4,
+	AMS_SEQ_SUPPLY5,
+	AMS_SEQ_SUPPLY6,
+	AMS_SEQ_TEMP,
+	AMS_SEQ_SUPPLY2,
+	AMS_SEQ_SUPPLY1,
+	AMS_SEQ_VP_VN,
+	AMS_SEQ_VREFP,
+	AMS_SEQ_VREFN,
+	AMS_SEQ_SUPPLY3,
+	AMS_SEQ_CURRENT_MON,
+	AMS_SEQ_SUPPLY7,
+	AMS_SEQ_SUPPLY8,
+	AMS_SEQ_SUPPLY9,
+	AMS_SEQ_SUPPLY10,
+	AMS_SEQ_VCCAMS,
+	AMS_SEQ_TEMP_REMOTE,
+	AMS_SEQ_MAX
+};
+
+#define AMS_SEQ(x)          (AMS_SEQ_MAX + (x))
+#define AMS_VAUX_SEQ(x)     (AMS_SEQ_MAX + (x))
+
+#define PS_SEQ_MAX          AMS_SEQ_MAX
+#define PS_SEQ(x)           (x)
+#define PL_SEQ(x)           (PS_SEQ_MAX + x)
+
+#define AMS_CHAN_TEMP(_scan_index, _addr, _ext) { \
+	.type = IIO_TEMP, \
+	.indexed = 1, \
+	.address = (_addr), \
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+		BIT(IIO_CHAN_INFO_SCALE) | \
+		BIT(IIO_CHAN_INFO_OFFSET), \
+	.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+	.event_spec = ams_temp_events, \
+	.num_event_specs = ARRAY_SIZE(ams_temp_events), \
+	.scan_index = (_scan_index), \
+	.scan_type = { \
+		.sign = 'u', \
+		.realbits = 12, \
+		.storagebits = 16, \
+		.shift = 4, \
+		.endianness = IIO_CPU, \
+	}, \
+	.extend_name = _ext, \
+}
+
+#define AMS_CHAN_VOLTAGE(_scan_index, _addr, _ext, _alarm) { \
+	.type = IIO_VOLTAGE, \
+	.indexed = 1, \
+	.address = (_addr), \
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+		BIT(IIO_CHAN_INFO_SCALE), \
+	.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+	.event_spec = (_alarm) ? ams_voltage_events : NULL, \
+	.num_event_specs = (_alarm) ? ARRAY_SIZE(ams_voltage_events) : 0, \
+	.scan_index = (_scan_index), \
+	.scan_type = { \
+		.realbits = 10, \
+		.storagebits = 16, \
+		.shift = 6, \
+		.endianness = IIO_CPU, \
+	}, \
+	.extend_name = _ext, \
+}
+
+#define AMS_PS_CHAN_TEMP(_scan_index, _addr, _ext) \
+	AMS_CHAN_TEMP(PS_SEQ(_scan_index), _addr, _ext)
+#define AMS_PS_CHAN_VOLTAGE(_scan_index, _addr, _ext) \
+	AMS_CHAN_VOLTAGE(PS_SEQ(_scan_index), _addr, _ext, true)
+
+#define AMS_PL_CHAN_TEMP(_scan_index, _addr, _ext) \
+	AMS_CHAN_TEMP(PL_SEQ(_scan_index), _addr, _ext)
+#define AMS_PL_CHAN_VOLTAGE(_scan_index, _addr, _ext, _alarm) \
+	AMS_CHAN_VOLTAGE(PL_SEQ(_scan_index), _addr, _ext, _alarm)
+#define AMS_PL_AUX_CHAN_VOLTAGE(_auxno, _ext) \
+	AMS_CHAN_VOLTAGE(PL_SEQ(AMS_VAUX_SEQ(_auxno)), \
+			AMS_REG_VAUX(_auxno), _ext, false)
+#define AMS_CTRL_CHAN_VOLTAGE(_scan_index, _addr, _ext) \
+	AMS_CHAN_VOLTAGE(PL_SEQ(AMS_VAUX_SEQ(AMS_SEQ(_scan_index))), \
+			_addr, _ext, false)
+
+struct ams {
+	void __iomem *base;
+	void __iomem *ps_base;
+	void __iomem *pl_base;
+	struct clk *clk;
+	struct device *dev;
+
+	struct mutex mutex;
+	spinlock_t lock;
+
+	unsigned int alarm_mask;
+	unsigned int masked_alarm;
+	u64 intr_mask;
+	int irq;
+
+	struct delayed_work ams_unmask_work;
+	const struct ams_pl_bus_ops *pl_bus;
+};
+
+struct ams_pl_bus_ops {
+	void (*read)(struct ams *ams, unsigned int offset, unsigned int *data);
+	void (*write)(struct ams *ams, unsigned int offset, unsigned int data);
+	void (*update)(struct ams *ams, unsigned int offset, u32 mask,
+			u32 data);
+};
+
+#endif /* __XILINX_AMS_H__ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/adc/xilinx-xadc-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/adc/xilinx-xadc-core.c
@@ -94,6 +94,9 @@
 #define XADC_AXI_REG_IPIER		0x68
 #define XADC_AXI_ADC_REG_OFFSET		0x200
 
+/* AXI sysmon offset */
+#define XADC_AXI_SYSMON_REG_OFFSET	0x400
+
 #define XADC_AXI_RESET_MAGIC		0xa
 #define XADC_AXI_GIER_ENABLE		BIT(31)
 
@@ -102,6 +105,16 @@
 
 #define XADC_FLAGS_BUFFERED BIT(0)
 
+/*
+ * The XADC hardware supports a samplerate of up to 1MSPS. Unfortunately it does
+ * not have a hardware FIFO. Which means an interrupt is generated for each
+ * conversion sequence. At 1MSPS sample rate the CPU in ZYNQ7000 is completely
+ * overloaded by the interrupts that it soft-lockups. For this reason the driver
+ * limits the maximum samplerate 150kSPS. At this rate the CPU is fairly busy,
+ * but still responsive.
+ */
+#define XADC_MAX_SAMPLERATE 150000
+
 static void xadc_write_reg(struct xadc *xadc, unsigned int reg,
 	uint32_t val)
 {
@@ -458,6 +471,26 @@
 	return 0;
 }
 
+/* AXI sysmon read/write methods */
+static int xadc_axi_read_sysmon_reg(struct xadc *xadc, unsigned int reg,
+	uint16_t *val)
+{
+	uint32_t val32;
+
+	xadc_read_reg(xadc, XADC_AXI_SYSMON_REG_OFFSET + reg * 4, &val32);
+	*val = val32 & 0xffff;
+
+	return 0;
+}
+
+static int xadc_axi_write_sysmon_reg(struct xadc *xadc, unsigned int reg,
+	uint16_t val)
+{
+	xadc_write_reg(xadc, XADC_AXI_SYSMON_REG_OFFSET + reg * 4, val);
+
+	return 0;
+}
+
 static int xadc_axi_setup(struct platform_device *pdev,
 	struct iio_dev *indio_dev, int irq)
 {
@@ -541,6 +574,17 @@
 	.flags = XADC_FLAGS_BUFFERED,
 };
 
+/* AXI sysmon */
+static const struct xadc_ops sysmon_axi_ops = {
+	.read = xadc_axi_read_sysmon_reg,
+	.write = xadc_axi_write_sysmon_reg,
+	.setup = xadc_axi_setup,
+	.get_dclk_rate = xadc_axi_get_dclk,
+	.update_alarm = xadc_axi_update_alarm,
+	.interrupt_handler = xadc_axi_interrupt_handler,
+	.flags = XADC_FLAGS_BUFFERED,
+};
+
 static int _xadc_update_adc_reg(struct xadc *xadc, unsigned int reg,
 	uint16_t mask, uint16_t val)
 {
@@ -674,7 +718,7 @@
 
 	spin_lock_irqsave(&xadc->lock, flags);
 	xadc_read_reg(xadc, XADC_AXI_REG_IPIER, &val);
-	xadc_write_reg(xadc, XADC_AXI_REG_IPISR, val & XADC_AXI_INT_EOS);
+	xadc_write_reg(xadc, XADC_AXI_REG_IPISR, XADC_AXI_INT_EOS);
 	if (state)
 		val |= XADC_AXI_INT_EOS;
 	else
@@ -722,13 +766,14 @@
 {
 	uint16_t val;
 
+	/* Powerdown the ADC-B when it is not needed. */
 	switch (seq_mode) {
 	case XADC_CONF1_SEQ_SIMULTANEOUS:
 	case XADC_CONF1_SEQ_INDEPENDENT:
-		val = XADC_CONF2_PD_ADC_B;
+		val = 0;
 		break;
 	default:
-		val = 0;
+		val = XADC_CONF2_PD_ADC_B;
 		break;
 	}
 
@@ -797,6 +842,16 @@
 	if (ret)
 		goto err;
 
+	/*
+	 * In simultaneous mode the upper and lower aux channels are samples at
+	 * the same time. In this mode the upper 8 bits in the sequencer
+	 * register are don't care and the lower 8 bits control two channels
+	 * each. As such we must set the bit if either the channel in the lower
+	 * group or the upper group is enabled.
+	 */
+	if (seq_mode == XADC_CONF1_SEQ_SIMULTANEOUS)
+		scan_mask = ((scan_mask >> 8) | scan_mask) & 0xff0000;
+
 	ret = xadc_write_adc_reg(xadc, XADC_REG_SEQ(1), scan_mask >> 16);
 	if (ret)
 		goto err;
@@ -823,11 +878,27 @@
 	.postdisable = &xadc_postdisable,
 };
 
+static int xadc_read_samplerate(struct xadc *xadc)
+{
+	unsigned int div;
+	uint16_t val16;
+	int ret;
+
+	ret = xadc_read_adc_reg(xadc, XADC_REG_CONF2, &val16);
+	if (ret)
+		return ret;
+
+	div = (val16 & XADC_CONF2_DIV_MASK) >> XADC_CONF2_DIV_OFFSET;
+	if (div < 2)
+		div = 2;
+
+	return xadc_get_dclk_rate(xadc) / div / 26;
+}
+
 static int xadc_read_raw(struct iio_dev *indio_dev,
 	struct iio_chan_spec const *chan, int *val, int *val2, long info)
 {
 	struct xadc *xadc = iio_priv(indio_dev);
-	unsigned int div;
 	uint16_t val16;
 	int ret;
 
@@ -880,41 +951,31 @@
 		*val = -((273150 << 12) / 503975);
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SAMP_FREQ:
-		ret = xadc_read_adc_reg(xadc, XADC_REG_CONF2, &val16);
-		if (ret)
+		ret = xadc_read_samplerate(xadc);
+		if (ret < 0)
 			return ret;
 
-		div = (val16 & XADC_CONF2_DIV_MASK) >> XADC_CONF2_DIV_OFFSET;
-		if (div < 2)
-			div = 2;
-
-		*val = xadc_get_dclk_rate(xadc) / div / 26;
-
+		*val = ret;
 		return IIO_VAL_INT;
 	default:
 		return -EINVAL;
 	}
 }
 
-static int xadc_write_raw(struct iio_dev *indio_dev,
-	struct iio_chan_spec const *chan, int val, int val2, long info)
+static int xadc_write_samplerate(struct xadc *xadc, int val)
 {
-	struct xadc *xadc = iio_priv(indio_dev);
 	unsigned long clk_rate = xadc_get_dclk_rate(xadc);
 	unsigned int div;
 
 	if (!clk_rate)
 		return -EINVAL;
 
-	if (info != IIO_CHAN_INFO_SAMP_FREQ)
-		return -EINVAL;
-
 	if (val <= 0)
 		return -EINVAL;
 
 	/* Max. 150 kSPS */
-	if (val > 150000)
-		val = 150000;
+	if (val > XADC_MAX_SAMPLERATE)
+		val = XADC_MAX_SAMPLERATE;
 
 	val *= 26;
 
@@ -927,7 +988,7 @@
 	 * limit.
 	 */
 	div = clk_rate / val;
-	if (clk_rate / div / 26 > 150000)
+	if (clk_rate / div / 26 > XADC_MAX_SAMPLERATE)
 		div++;
 	if (div < 2)
 		div = 2;
@@ -938,6 +999,17 @@
 		div << XADC_CONF2_DIV_OFFSET);
 }
 
+static int xadc_write_raw(struct iio_dev *indio_dev,
+	struct iio_chan_spec const *chan, int val, int val2, long info)
+{
+	struct xadc *xadc = iio_priv(indio_dev);
+
+	if (info != IIO_CHAN_INFO_SAMP_FREQ)
+		return -EINVAL;
+
+	return xadc_write_samplerate(xadc, val);
+}
+
 static const struct iio_event_spec xadc_temp_events[] = {
 	{
 		.type = IIO_EV_TYPE_THRESH,
@@ -1017,23 +1089,23 @@
 	XADC_CHAN_VOLTAGE(5, 7, XADC_REG_VCCO_DDR, "vccoddr", true),
 	XADC_CHAN_VOLTAGE(6, 12, XADC_REG_VREFP, "vrefp", false),
 	XADC_CHAN_VOLTAGE(7, 13, XADC_REG_VREFN, "vrefn", false),
-	XADC_CHAN_VOLTAGE(8, 11, XADC_REG_VPVN, NULL, false),
-	XADC_CHAN_VOLTAGE(9, 16, XADC_REG_VAUX(0), NULL, false),
-	XADC_CHAN_VOLTAGE(10, 17, XADC_REG_VAUX(1), NULL, false),
-	XADC_CHAN_VOLTAGE(11, 18, XADC_REG_VAUX(2), NULL, false),
-	XADC_CHAN_VOLTAGE(12, 19, XADC_REG_VAUX(3), NULL, false),
-	XADC_CHAN_VOLTAGE(13, 20, XADC_REG_VAUX(4), NULL, false),
-	XADC_CHAN_VOLTAGE(14, 21, XADC_REG_VAUX(5), NULL, false),
-	XADC_CHAN_VOLTAGE(15, 22, XADC_REG_VAUX(6), NULL, false),
-	XADC_CHAN_VOLTAGE(16, 23, XADC_REG_VAUX(7), NULL, false),
-	XADC_CHAN_VOLTAGE(17, 24, XADC_REG_VAUX(8), NULL, false),
-	XADC_CHAN_VOLTAGE(18, 25, XADC_REG_VAUX(9), NULL, false),
-	XADC_CHAN_VOLTAGE(19, 26, XADC_REG_VAUX(10), NULL, false),
-	XADC_CHAN_VOLTAGE(20, 27, XADC_REG_VAUX(11), NULL, false),
-	XADC_CHAN_VOLTAGE(21, 28, XADC_REG_VAUX(12), NULL, false),
-	XADC_CHAN_VOLTAGE(22, 29, XADC_REG_VAUX(13), NULL, false),
-	XADC_CHAN_VOLTAGE(23, 30, XADC_REG_VAUX(14), NULL, false),
-	XADC_CHAN_VOLTAGE(24, 31, XADC_REG_VAUX(15), NULL, false),
+	XADC_CHAN_VOLTAGE(8, 11, XADC_REG_VPVN, "vpvn", false),
+	XADC_CHAN_VOLTAGE(9, 16, XADC_REG_VAUX(0), "vaux0", false),
+	XADC_CHAN_VOLTAGE(10, 17, XADC_REG_VAUX(1), "vaux1", false),
+	XADC_CHAN_VOLTAGE(11, 18, XADC_REG_VAUX(2), "vaux2", false),
+	XADC_CHAN_VOLTAGE(12, 19, XADC_REG_VAUX(3), "vaux3", false),
+	XADC_CHAN_VOLTAGE(13, 20, XADC_REG_VAUX(4), "vaux4", false),
+	XADC_CHAN_VOLTAGE(14, 21, XADC_REG_VAUX(5), "vaux5", false),
+	XADC_CHAN_VOLTAGE(15, 22, XADC_REG_VAUX(6), "vaux6", false),
+	XADC_CHAN_VOLTAGE(16, 23, XADC_REG_VAUX(7), "vaux7", false),
+	XADC_CHAN_VOLTAGE(17, 24, XADC_REG_VAUX(8), "vaux8", false),
+	XADC_CHAN_VOLTAGE(18, 25, XADC_REG_VAUX(9), "vaux9", false),
+	XADC_CHAN_VOLTAGE(19, 26, XADC_REG_VAUX(10), "vaux10", false),
+	XADC_CHAN_VOLTAGE(20, 27, XADC_REG_VAUX(11), "vaux11", false),
+	XADC_CHAN_VOLTAGE(21, 28, XADC_REG_VAUX(12), "vaux12", false),
+	XADC_CHAN_VOLTAGE(22, 29, XADC_REG_VAUX(13), "vaux13", false),
+	XADC_CHAN_VOLTAGE(23, 30, XADC_REG_VAUX(14), "vaux14", false),
+	XADC_CHAN_VOLTAGE(24, 31, XADC_REG_VAUX(15), "vaux15", false),
 };
 
 static const struct iio_info xadc_info = {
@@ -1049,6 +1121,7 @@
 static const struct of_device_id xadc_of_match_table[] = {
 	{ .compatible = "xlnx,zynq-xadc-1.00.a", (void *)&xadc_zynq_ops },
 	{ .compatible = "xlnx,axi-xadc-1.00.a", (void *)&xadc_axi_ops },
+	{ .compatible = "xlnx,axi-sysmon-1.3", (void *)&sysmon_axi_ops},
 	{ },
 };
 MODULE_DEVICE_TABLE(of, xadc_of_match_table);
@@ -1057,7 +1130,7 @@
 	unsigned int *conf)
 {
 	struct xadc *xadc = iio_priv(indio_dev);
-	struct iio_chan_spec *channels, *chan;
+	struct iio_chan_spec *iio_xadc_channels;
 	struct device_node *chan_node, *child;
 	unsigned int num_channels;
 	const char *external_mux;
@@ -1100,12 +1173,12 @@
 		*conf |= XADC_CONF0_MUX | XADC_CONF0_CHAN(ext_mux_chan);
 	}
 
-	channels = kmemdup(xadc_channels, sizeof(xadc_channels), GFP_KERNEL);
-	if (!channels)
+	iio_xadc_channels = kmemdup(xadc_channels, sizeof(xadc_channels),
+				    GFP_KERNEL);
+	if (!iio_xadc_channels)
 		return -ENOMEM;
 
 	num_channels = 9;
-	chan = &channels[9];
 
 	chan_node = of_get_child_by_name(np, "xlnx,channels");
 	if (chan_node) {
@@ -1119,28 +1192,24 @@
 			if (ret || reg > 16)
 				continue;
 
+			iio_xadc_channels[num_channels] = xadc_channels[reg + 9];
+			iio_xadc_channels[num_channels].channel = num_channels - 1;
+
 			if (of_property_read_bool(child, "xlnx,bipolar"))
-				chan->scan_type.sign = 's';
+				iio_xadc_channels[num_channels].scan_type.sign = 's';
 
-			if (reg == 0) {
-				chan->scan_index = 11;
-				chan->address = XADC_REG_VPVN;
-			} else {
-				chan->scan_index = 15 + reg;
-				chan->address = XADC_REG_VAUX(reg - 1);
-			}
 			num_channels++;
-			chan++;
 		}
 	}
 	of_node_put(chan_node);
 
 	indio_dev->num_channels = num_channels;
-	indio_dev->channels = krealloc(channels, sizeof(*channels) *
-					num_channels, GFP_KERNEL);
+	indio_dev->channels = krealloc(iio_xadc_channels,
+				       sizeof(*iio_xadc_channels) *
+				       num_channels, GFP_KERNEL);
 	/* If we can't resize the channels array, just use the original */
 	if (!indio_dev->channels)
-		indio_dev->channels = channels;
+		indio_dev->channels = iio_xadc_channels;
 
 	return 0;
 }
@@ -1225,6 +1294,21 @@
 	if (ret)
 		goto err_free_samplerate_trigger;
 
+	/*
+	 * Make sure not to exceed the maximum samplerate since otherwise the
+	 * resulting interrupt storm will soft-lock the system.
+	 */
+	if (xadc->ops->flags & XADC_FLAGS_BUFFERED) {
+		ret = xadc_read_samplerate(xadc);
+		if (ret < 0)
+			goto err_free_samplerate_trigger;
+		if (ret > XADC_MAX_SAMPLERATE) {
+			ret = xadc_write_samplerate(xadc, XADC_MAX_SAMPLERATE);
+			if (ret < 0)
+				goto err_free_samplerate_trigger;
+		}
+	}
+
 	ret = request_irq(xadc->irq, xadc->ops->interrupt_handler, 0,
 			dev_name(&pdev->dev), indio_dev);
 	if (ret)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/addac/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/addac/Kconfig
@@ -0,0 +1,24 @@
+#
+# ADC DAC drivers
+#
+# When adding new entries keep the list in alphabetical order
+
+menu "Analog to digital and digital to analog converters"
+
+config STX104
+	tristate "Apex Embedded Systems STX104 driver"
+	depends on PC104 && X86
+	select ISA_BUS_API
+	select GPIOLIB
+	help
+	  Say yes here to build support for the Apex Embedded Systems STX104
+	  integrated analog PC/104 card.
+
+	  This driver supports the 16 channels of single-ended (8 channels of
+	  differential) analog inputs, 2 channels of analog output, 4 digital
+	  inputs, and 4 digital outputs provided by the STX104.
+
+	  The base port addresses for the devices may be configured via the base
+	  array module parameter.
+
+endmenu
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/addac/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/addac/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for industrial I/O ADDAC drivers
+#
+
+# When adding new entries keep the list in alphabetical order
+obj-$(CONFIG_STX104) += stx104.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/addac/stx104.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/addac/stx104.c
@@ -0,0 +1,415 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * IIO driver for the Apex Embedded Systems STX104
+ * Copyright (C) 2016 William Breathitt Gray
+ */
+#include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/gpio/driver.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/types.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/isa.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#define STX104_OUT_CHAN(chan) {				\
+	.type = IIO_VOLTAGE,				\
+	.channel = chan,				\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
+	.indexed = 1,					\
+	.output = 1					\
+}
+#define STX104_IN_CHAN(chan, diff) {					\
+	.type = IIO_VOLTAGE,						\
+	.channel = chan,						\
+	.channel2 = chan,						\
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_HARDWAREGAIN) |	\
+		BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SCALE),	\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),			\
+	.indexed = 1,							\
+	.differential = diff						\
+}
+
+#define STX104_NUM_OUT_CHAN 2
+
+#define STX104_EXTENT 16
+
+static unsigned int base[max_num_isa_dev(STX104_EXTENT)];
+static unsigned int num_stx104;
+module_param_hw_array(base, uint, ioport, &num_stx104, 0);
+MODULE_PARM_DESC(base, "Apex Embedded Systems STX104 base addresses");
+
+/**
+ * struct stx104_reg - device register structure
+ * @ssr_ad:	Software Strobe Register and ADC Data
+ * @achan:	ADC Channel
+ * @dio:	Digital I/O
+ * @dac:	DAC Channels
+ * @cir_asr:	Clear Interrupts and ADC Status
+ * @acr:	ADC Control
+ * @pccr_fsh:	Pacer Clock Control and FIFO Status MSB
+ * @acfg:	ADC Configuration
+ */
+struct stx104_reg {
+	u16 ssr_ad;
+	u8 achan;
+	u8 dio;
+	u16 dac[2];
+	u8 cir_asr;
+	u8 acr;
+	u8 pccr_fsh;
+	u8 acfg;
+};
+
+/**
+ * struct stx104_iio - IIO device private data structure
+ * @lock: synchronization lock to prevent I/O race conditions
+ * @chan_out_states:	channels' output states
+ * @reg:		I/O address offset for the device registers
+ */
+struct stx104_iio {
+	struct mutex lock;
+	unsigned int chan_out_states[STX104_NUM_OUT_CHAN];
+	struct stx104_reg __iomem *reg;
+};
+
+/**
+ * struct stx104_gpio - GPIO device private data structure
+ * @chip:	instance of the gpio_chip
+ * @lock:	synchronization lock to prevent I/O race conditions
+ * @base:	base port address of the GPIO device
+ * @out_state:	output bits state
+ */
+struct stx104_gpio {
+	struct gpio_chip chip;
+	spinlock_t lock;
+	u8 __iomem *base;
+	unsigned int out_state;
+};
+
+static int stx104_read_raw(struct iio_dev *indio_dev,
+	struct iio_chan_spec const *chan, int *val, int *val2, long mask)
+{
+	struct stx104_iio *const priv = iio_priv(indio_dev);
+	struct stx104_reg __iomem *const reg = priv->reg;
+	unsigned int adc_config;
+	int adbu;
+	int gain;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_HARDWAREGAIN:
+		/* get gain configuration */
+		adc_config = ioread8(&reg->acfg);
+		gain = adc_config & 0x3;
+
+		*val = 1 << gain;
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_RAW:
+		if (chan->output) {
+			*val = priv->chan_out_states[chan->channel];
+			return IIO_VAL_INT;
+		}
+
+		mutex_lock(&priv->lock);
+
+		/* select ADC channel */
+		iowrite8(chan->channel | (chan->channel << 4), &reg->achan);
+
+		/* trigger ADC sample capture by writing to the 8-bit
+		 * Software Strobe Register and wait for completion
+		 */
+		iowrite8(0, &reg->ssr_ad);
+		while (ioread8(&reg->cir_asr) & BIT(7));
+
+		*val = ioread16(&reg->ssr_ad);
+
+		mutex_unlock(&priv->lock);
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_OFFSET:
+		/* get ADC bipolar/unipolar configuration */
+		adc_config = ioread8(&reg->acfg);
+		adbu = !(adc_config & BIT(2));
+
+		*val = -32768 * adbu;
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SCALE:
+		/* get ADC bipolar/unipolar and gain configuration */
+		adc_config = ioread8(&reg->acfg);
+		adbu = !(adc_config & BIT(2));
+		gain = adc_config & 0x3;
+
+		*val = 5;
+		*val2 = 15 - adbu + gain;
+		return IIO_VAL_FRACTIONAL_LOG2;
+	}
+
+	return -EINVAL;
+}
+
+static int stx104_write_raw(struct iio_dev *indio_dev,
+	struct iio_chan_spec const *chan, int val, int val2, long mask)
+{
+	struct stx104_iio *const priv = iio_priv(indio_dev);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_HARDWAREGAIN:
+		/* Only four gain states (x1, x2, x4, x8) */
+		switch (val) {
+		case 1:
+			iowrite8(0, &priv->reg->acfg);
+			break;
+		case 2:
+			iowrite8(1, &priv->reg->acfg);
+			break;
+		case 4:
+			iowrite8(2, &priv->reg->acfg);
+			break;
+		case 8:
+			iowrite8(3, &priv->reg->acfg);
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		return 0;
+	case IIO_CHAN_INFO_RAW:
+		if (chan->output) {
+			/* DAC can only accept up to a 16-bit value */
+			if ((unsigned int)val > 65535)
+				return -EINVAL;
+
+			mutex_lock(&priv->lock);
+
+			priv->chan_out_states[chan->channel] = val;
+			iowrite16(val, &priv->reg->dac[chan->channel]);
+
+			mutex_unlock(&priv->lock);
+			return 0;
+		}
+		return -EINVAL;
+	}
+
+	return -EINVAL;
+}
+
+static const struct iio_info stx104_info = {
+	.read_raw = stx104_read_raw,
+	.write_raw = stx104_write_raw
+};
+
+/* single-ended input channels configuration */
+static const struct iio_chan_spec stx104_channels_sing[] = {
+	STX104_OUT_CHAN(0), STX104_OUT_CHAN(1),
+	STX104_IN_CHAN(0, 0), STX104_IN_CHAN(1, 0), STX104_IN_CHAN(2, 0),
+	STX104_IN_CHAN(3, 0), STX104_IN_CHAN(4, 0), STX104_IN_CHAN(5, 0),
+	STX104_IN_CHAN(6, 0), STX104_IN_CHAN(7, 0), STX104_IN_CHAN(8, 0),
+	STX104_IN_CHAN(9, 0), STX104_IN_CHAN(10, 0), STX104_IN_CHAN(11, 0),
+	STX104_IN_CHAN(12, 0), STX104_IN_CHAN(13, 0), STX104_IN_CHAN(14, 0),
+	STX104_IN_CHAN(15, 0)
+};
+/* differential input channels configuration */
+static const struct iio_chan_spec stx104_channels_diff[] = {
+	STX104_OUT_CHAN(0), STX104_OUT_CHAN(1),
+	STX104_IN_CHAN(0, 1), STX104_IN_CHAN(1, 1), STX104_IN_CHAN(2, 1),
+	STX104_IN_CHAN(3, 1), STX104_IN_CHAN(4, 1), STX104_IN_CHAN(5, 1),
+	STX104_IN_CHAN(6, 1), STX104_IN_CHAN(7, 1)
+};
+
+static int stx104_gpio_get_direction(struct gpio_chip *chip,
+	unsigned int offset)
+{
+	/* GPIO 0-3 are input only, while the rest are output only */
+	if (offset < 4)
+		return 1;
+
+	return 0;
+}
+
+static int stx104_gpio_direction_input(struct gpio_chip *chip,
+	unsigned int offset)
+{
+	if (offset >= 4)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int stx104_gpio_direction_output(struct gpio_chip *chip,
+	unsigned int offset, int value)
+{
+	if (offset < 4)
+		return -EINVAL;
+
+	chip->set(chip, offset, value);
+	return 0;
+}
+
+static int stx104_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+	struct stx104_gpio *const stx104gpio = gpiochip_get_data(chip);
+
+	if (offset >= 4)
+		return -EINVAL;
+
+	return !!(ioread8(stx104gpio->base) & BIT(offset));
+}
+
+static int stx104_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask,
+	unsigned long *bits)
+{
+	struct stx104_gpio *const stx104gpio = gpiochip_get_data(chip);
+
+	*bits = ioread8(stx104gpio->base);
+
+	return 0;
+}
+
+static void stx104_gpio_set(struct gpio_chip *chip, unsigned int offset,
+	int value)
+{
+	struct stx104_gpio *const stx104gpio = gpiochip_get_data(chip);
+	const unsigned int mask = BIT(offset) >> 4;
+	unsigned long flags;
+
+	if (offset < 4)
+		return;
+
+	spin_lock_irqsave(&stx104gpio->lock, flags);
+
+	if (value)
+		stx104gpio->out_state |= mask;
+	else
+		stx104gpio->out_state &= ~mask;
+
+	iowrite8(stx104gpio->out_state, stx104gpio->base);
+
+	spin_unlock_irqrestore(&stx104gpio->lock, flags);
+}
+
+#define STX104_NGPIO 8
+static const char *stx104_names[STX104_NGPIO] = {
+	"DIN0", "DIN1", "DIN2", "DIN3", "DOUT0", "DOUT1", "DOUT2", "DOUT3"
+};
+
+static void stx104_gpio_set_multiple(struct gpio_chip *chip,
+	unsigned long *mask, unsigned long *bits)
+{
+	struct stx104_gpio *const stx104gpio = gpiochip_get_data(chip);
+	unsigned long flags;
+
+	/* verify masked GPIO are output */
+	if (!(*mask & 0xF0))
+		return;
+
+	*mask >>= 4;
+	*bits >>= 4;
+
+	spin_lock_irqsave(&stx104gpio->lock, flags);
+
+	stx104gpio->out_state &= ~*mask;
+	stx104gpio->out_state |= *mask & *bits;
+	iowrite8(stx104gpio->out_state, stx104gpio->base);
+
+	spin_unlock_irqrestore(&stx104gpio->lock, flags);
+}
+
+static int stx104_probe(struct device *dev, unsigned int id)
+{
+	struct iio_dev *indio_dev;
+	struct stx104_iio *priv;
+	struct stx104_gpio *stx104gpio;
+	int err;
+
+	indio_dev = devm_iio_device_alloc(dev, sizeof(*priv));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	stx104gpio = devm_kzalloc(dev, sizeof(*stx104gpio), GFP_KERNEL);
+	if (!stx104gpio)
+		return -ENOMEM;
+
+	if (!devm_request_region(dev, base[id], STX104_EXTENT,
+		dev_name(dev))) {
+		dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n",
+			base[id], base[id] + STX104_EXTENT);
+		return -EBUSY;
+	}
+
+	priv = iio_priv(indio_dev);
+	priv->reg = devm_ioport_map(dev, base[id], STX104_EXTENT);
+	if (!priv->reg)
+		return -ENOMEM;
+
+	indio_dev->info = &stx104_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+
+	/* determine if differential inputs */
+	if (ioread8(&priv->reg->cir_asr) & BIT(5)) {
+		indio_dev->num_channels = ARRAY_SIZE(stx104_channels_diff);
+		indio_dev->channels = stx104_channels_diff;
+	} else {
+		indio_dev->num_channels = ARRAY_SIZE(stx104_channels_sing);
+		indio_dev->channels = stx104_channels_sing;
+	}
+
+	indio_dev->name = dev_name(dev);
+	indio_dev->dev.parent = dev;
+
+	mutex_init(&priv->lock);
+
+	/* configure device for software trigger operation */
+	iowrite8(0, &priv->reg->acr);
+
+	/* initialize gain setting to x1 */
+	iowrite8(0, &priv->reg->acfg);
+
+	/* initialize DAC output to 0V */
+	iowrite16(0, &priv->reg->dac[0]);
+	iowrite16(0, &priv->reg->dac[1]);
+
+	stx104gpio->chip.label = dev_name(dev);
+	stx104gpio->chip.parent = dev;
+	stx104gpio->chip.owner = THIS_MODULE;
+	stx104gpio->chip.base = -1;
+	stx104gpio->chip.ngpio = STX104_NGPIO;
+	stx104gpio->chip.names = stx104_names;
+	stx104gpio->chip.get_direction = stx104_gpio_get_direction;
+	stx104gpio->chip.direction_input = stx104_gpio_direction_input;
+	stx104gpio->chip.direction_output = stx104_gpio_direction_output;
+	stx104gpio->chip.get = stx104_gpio_get;
+	stx104gpio->chip.get_multiple = stx104_gpio_get_multiple;
+	stx104gpio->chip.set = stx104_gpio_set;
+	stx104gpio->chip.set_multiple = stx104_gpio_set_multiple;
+	stx104gpio->base = &priv->reg->dio;
+	stx104gpio->out_state = 0x0;
+
+	spin_lock_init(&stx104gpio->lock);
+
+	err = devm_gpiochip_add_data(dev, &stx104gpio->chip, stx104gpio);
+	if (err) {
+		dev_err(dev, "GPIO registering failed (%d)\n", err);
+		return err;
+	}
+
+	return devm_iio_device_register(dev, indio_dev);
+}
+
+static struct isa_driver stx104_driver = {
+	.probe = stx104_probe,
+	.driver = {
+		.name = "stx104"
+	},
+};
+
+module_isa_driver(stx104_driver, num_stx104);
+
+MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
+MODULE_DESCRIPTION("Apex Embedded Systems STX104 IIO driver");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/afe/iio-rescale.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/afe/iio-rescale.c
@@ -38,7 +38,7 @@
 			    int *val, int *val2, long mask)
 {
 	struct rescale *rescale = iio_priv(indio_dev);
-	unsigned long long tmp;
+	s64 tmp;
 	int ret;
 
 	switch (mask) {
@@ -59,10 +59,10 @@
 			*val2 = rescale->denominator;
 			return IIO_VAL_FRACTIONAL;
 		case IIO_VAL_FRACTIONAL_LOG2:
-			tmp = *val * 1000000000LL;
-			do_div(tmp, rescale->denominator);
+			tmp = (s64)*val * 1000000000LL;
+			tmp = div_s64(tmp, rescale->denominator);
 			tmp *= rescale->numerator;
-			do_div(tmp, 1000000000LL);
+			tmp = div_s64(tmp, 1000000000LL);
 			*val = tmp;
 			return ret;
 		default:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/buffer/industrialio-buffer-dmaengine.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/buffer/industrialio-buffer-dmaengine.c
@@ -158,7 +158,7 @@
 
 	ret = dma_get_slave_caps(chan, &caps);
 	if (ret < 0)
-		goto err_free;
+		goto err_release;
 
 	/* Needs to be aligned to the maximum of the minimums */
 	if (caps.src_addr_widths)
@@ -183,6 +183,8 @@
 
 	return &dmaengine_buffer->queue.buffer;
 
+err_release:
+	dma_release_channel(chan);
 err_free:
 	kfree(dmaengine_buffer);
 	return ERR_PTR(ret);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/chemical/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/chemical/Kconfig
@@ -65,6 +65,7 @@
 config PMS7003
 	tristate "Plantower PMS7003 particulate matter sensor"
 	depends on SERIAL_DEV_BUS
+	select IIO_BUFFER
 	select IIO_TRIGGERED_BUFFER
 	help
 	  Say Y here to build support for the Plantower PMS7003 particulate
@@ -90,6 +91,8 @@
 	tristate "SPS30 particulate matter sensor"
 	depends on I2C
 	select CRC8
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
 	help
 	  Say Y here to build support for the Sensirion SPS30 particulate
 	  matter sensor.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/chemical/bme680.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/chemical/bme680.h
@@ -54,7 +54,9 @@
 #define   BME680_NB_CONV_MASK			GENMASK(3, 0)
 
 #define BME680_REG_MEAS_STAT_0			0x1D
+#define   BME680_NEW_DATA_BIT			BIT(7)
 #define   BME680_GAS_MEAS_BIT			BIT(6)
+#define   BME680_MEAS_BIT			BIT(5)
 
 /* Calibration Parameters */
 #define BME680_T2_LSB_REG	0x8A
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/chemical/bme680_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/chemical/bme680_core.c
@@ -10,6 +10,7 @@
  */
 #include <linux/acpi.h>
 #include <linux/bitfield.h>
+#include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/log2.h>
@@ -38,7 +39,7 @@
 	s8  par_h3;
 	s8  par_h4;
 	s8  par_h5;
-	s8  par_h6;
+	u8  par_h6;
 	s8  par_h7;
 	s8  par_gh1;
 	s16 par_gh2;
@@ -334,10 +335,10 @@
 	if (!calib->par_t2)
 		bme680_read_calib(data, calib);
 
-	var1 = (adc_temp >> 3) - (calib->par_t1 << 1);
+	var1 = (adc_temp >> 3) - ((s32)calib->par_t1 << 1);
 	var2 = (var1 * calib->par_t2) >> 11;
 	var3 = ((var1 >> 1) * (var1 >> 1)) >> 12;
-	var3 = (var3 * (calib->par_t3 << 4)) >> 14;
+	var3 = (var3 * ((s32)calib->par_t3 << 4)) >> 14;
 	data->t_fine = var2 + var3;
 	calc_temp = (data->t_fine * 5 + 128) >> 8;
 
@@ -360,9 +361,9 @@
 	var1 = (data->t_fine >> 1) - 64000;
 	var2 = ((((var1 >> 2) * (var1 >> 2)) >> 11) * calib->par_p6) >> 2;
 	var2 = var2 + (var1 * calib->par_p5 << 1);
-	var2 = (var2 >> 2) + (calib->par_p4 << 16);
+	var2 = (var2 >> 2) + ((s32)calib->par_p4 << 16);
 	var1 = (((((var1 >> 2) * (var1 >> 2)) >> 13) *
-			(calib->par_p3 << 5)) >> 3) +
+			((s32)calib->par_p3 << 5)) >> 3) +
 			((calib->par_p2 * var1) >> 1);
 	var1 = var1 >> 18;
 	var1 = ((32768 + var1) * calib->par_p1) >> 15;
@@ -380,7 +381,7 @@
 	var3 = ((press_comp >> 8) * (press_comp >> 8) *
 			(press_comp >> 8) * calib->par_p10) >> 17;
 
-	press_comp += (var1 + var2 + var3 + (calib->par_p7 << 7)) >> 4;
+	press_comp += (var1 + var2 + var3 + ((s32)calib->par_p7 << 7)) >> 4;
 
 	return press_comp;
 }
@@ -406,7 +407,7 @@
 		 (((temp_scaled * ((temp_scaled * calib->par_h5) / 100))
 		   >> 6) / 100) + (1 << 14))) >> 10;
 	var3 = var1 * var2;
-	var4 = calib->par_h6 << 7;
+	var4 = (s32)calib->par_h6 << 7;
 	var4 = (var4 + ((temp_scaled * calib->par_h7) / 100)) >> 4;
 	var5 = ((var3 >> 14) * (var3 >> 14)) >> 10;
 	var6 = (var4 * var5) >> 1;
@@ -524,6 +525,43 @@
 	return ilog2(val) + 1;
 }
 
+/*
+ * Taken from Bosch BME680 API:
+ * https://github.com/boschsensortec/BME68x_SensorAPI/blob/v4.4.8/bme68x.c#L490
+ */
+static int bme680_wait_for_eoc(struct bme680_data *data)
+{
+	struct device *dev = regmap_get_device(data->regmap);
+	unsigned int check;
+	int ret;
+	/*
+	 * (Sum of oversampling ratios * time per oversampling) +
+	 * TPH measurement + gas measurement + wait transition from forced mode
+	 * + heater duration
+	 */
+	int wait_eoc_us = ((data->oversampling_temp + data->oversampling_press +
+			   data->oversampling_humid) * 1936) + (477 * 4) +
+			   (477 * 5) + 1000 + (data->heater_dur * 1000);
+
+	usleep_range(wait_eoc_us, wait_eoc_us + 100);
+
+	ret = regmap_read(data->regmap, BME680_REG_MEAS_STAT_0, &check);
+	if (ret) {
+		dev_err(dev, "failed to read measurement status register.\n");
+		return ret;
+	}
+	if (check & BME680_MEAS_BIT) {
+		dev_err(dev, "Device measurement cycle incomplete.\n");
+		return -EBUSY;
+	}
+	if (!(check & BME680_NEW_DATA_BIT)) {
+		dev_err(dev, "No new data available from the device.\n");
+		return -ENODATA;
+	}
+
+	return 0;
+}
+
 static int bme680_chip_config(struct bme680_data *data)
 {
 	struct device *dev = regmap_get_device(data->regmap);
@@ -614,6 +652,10 @@
 	if (ret < 0)
 		return ret;
 
+	ret = bme680_wait_for_eoc(data);
+	if (ret)
+		return ret;
+
 	ret = regmap_bulk_read(data->regmap, BME680_REG_TEMP_MSB,
 			       (u8 *) &tmp, 3);
 	if (ret < 0) {
@@ -670,7 +712,7 @@
 	}
 
 	*val = bme680_compensate_press(data, adc_press);
-	*val2 = 100;
+	*val2 = 1000;
 	return IIO_VAL_FRACTIONAL;
 }
 
@@ -730,6 +772,10 @@
 	if (ret < 0)
 		return ret;
 
+	ret = bme680_wait_for_eoc(data);
+	if (ret)
+		return ret;
+
 	ret = regmap_read(data->regmap, BME680_REG_MEAS_STAT_0, &check);
 	if (check & BME680_GAS_MEAS_BIT) {
 		dev_err(dev, "gas measurement incomplete\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/chemical/ccs811.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/chemical/ccs811.c
@@ -75,6 +75,11 @@
 	struct ccs811_reading buffer;
 	struct iio_trigger *drdy_trig;
 	bool drdy_trig_on;
+	/* Ensures correct alignment of timestamp if present */
+	struct {
+		s16 channels[2];
+		s64 ts __aligned(8);
+	} scan;
 };
 
 static const struct iio_chan_spec ccs811_channels[] = {
@@ -306,17 +311,17 @@
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct ccs811_data *data = iio_priv(indio_dev);
 	struct i2c_client *client = data->client;
-	s16 buf[8]; /* s16 eCO2 + s16 TVOC + padding + 8 byte timestamp */
 	int ret;
 
-	ret = i2c_smbus_read_i2c_block_data(client, CCS811_ALG_RESULT_DATA, 4,
-					    (u8 *)&buf);
+	ret = i2c_smbus_read_i2c_block_data(client, CCS811_ALG_RESULT_DATA,
+					    sizeof(data->scan.channels),
+					    (u8 *)data->scan.channels);
 	if (ret != 4) {
 		dev_err(&client->dev, "cannot read sensor data\n");
 		goto err;
 	}
 
-	iio_push_to_buffers_with_timestamp(indio_dev, buf,
+	iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
 					   iio_get_time_ns(indio_dev));
 
 err:
@@ -413,11 +418,11 @@
 		data->drdy_trig->dev.parent = &client->dev;
 		data->drdy_trig->ops = &ccs811_trigger_ops;
 		iio_trigger_set_drvdata(data->drdy_trig, indio_dev);
-		indio_dev->trig = data->drdy_trig;
-		iio_trigger_get(indio_dev->trig);
 		ret = iio_trigger_register(data->drdy_trig);
 		if (ret)
 			goto err_poweroff;
+
+		indio_dev->trig = iio_trigger_get(data->drdy_trig);
 	}
 
 	ret = iio_triggered_buffer_setup(indio_dev, NULL,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/chemical/pms7003.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/chemical/pms7003.c
@@ -73,6 +73,11 @@
 	struct pms7003_frame frame;
 	struct completion frame_ready;
 	struct mutex lock; /* must be held whenever state gets touched */
+	/* Used to construct scan to push to the IIO buffer */
+	struct {
+		u16 data[3]; /* PM1, PM2P5, PM10 */
+		s64 ts;
+	} scan;
 };
 
 static int pms7003_do_cmd(struct pms7003_state *state, enum pms7003_cmd cmd)
@@ -104,7 +109,6 @@
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct pms7003_state *state = iio_priv(indio_dev);
 	struct pms7003_frame *frame = &state->frame;
-	u16 data[3 + 1 + 4]; /* PM1, PM2P5, PM10, padding, timestamp */
 	int ret;
 
 	mutex_lock(&state->lock);
@@ -114,12 +118,15 @@
 		goto err;
 	}
 
-	data[PM1] = pms7003_get_pm(frame->data + PMS7003_PM1_OFFSET);
-	data[PM2P5] = pms7003_get_pm(frame->data + PMS7003_PM2P5_OFFSET);
-	data[PM10] = pms7003_get_pm(frame->data + PMS7003_PM10_OFFSET);
+	state->scan.data[PM1] =
+		pms7003_get_pm(frame->data + PMS7003_PM1_OFFSET);
+	state->scan.data[PM2P5] =
+		pms7003_get_pm(frame->data + PMS7003_PM2P5_OFFSET);
+	state->scan.data[PM10] =
+		pms7003_get_pm(frame->data + PMS7003_PM10_OFFSET);
 	mutex_unlock(&state->lock);
 
-	iio_push_to_buffers_with_timestamp(indio_dev, data,
+	iio_push_to_buffers_with_timestamp(indio_dev, &state->scan,
 					   iio_get_time_ns(indio_dev));
 err:
 	iio_trigger_notify_done(indio_dev->trig);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/chemical/sps30.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/chemical/sps30.c
@@ -230,15 +230,18 @@
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct sps30_state *state = iio_priv(indio_dev);
 	int ret;
-	s32 data[4 + 2]; /* PM1, PM2P5, PM4, PM10, timestamp */
+	struct {
+		s32 data[4]; /* PM1, PM2P5, PM4, PM10 */
+		s64 ts;
+	} scan;
 
 	mutex_lock(&state->lock);
-	ret = sps30_do_meas(state, data, 4);
+	ret = sps30_do_meas(state, scan.data, ARRAY_SIZE(scan.data));
 	mutex_unlock(&state->lock);
 	if (ret)
 		goto err;
 
-	iio_push_to_buffers_with_timestamp(indio_dev, data,
+	iio_push_to_buffers_with_timestamp(indio_dev, &scan,
 					   iio_get_time_ns(indio_dev));
 err:
 	iio_trigger_notify_done(indio_dev->trig);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
@@ -57,10 +57,13 @@
 {
 	switch (type) {
 	case MOTIONSENSE_TYPE_ACCEL:
-	case MOTIONSENSE_TYPE_GYRO:
 		*min_freq = 12500;
 		*max_freq = 100000;
 		break;
+	case MOTIONSENSE_TYPE_GYRO:
+		*min_freq = 25000;
+		*max_freq = 100000;
+		break;
 	case MOTIONSENSE_TYPE_MAG:
 		*min_freq = 5000;
 		*max_freq = 25000;
@@ -96,7 +99,7 @@
 	platform_set_drvdata(pdev, indio_dev);
 
 	state->ec = ec->ec_dev;
-	state->msg = devm_kzalloc(&pdev->dev,
+	state->msg = devm_kzalloc(&pdev->dev, sizeof(*state->msg) +
 				max((u16)sizeof(struct ec_params_motion_sense),
 				state->ec->max_response), GFP_KERNEL);
 	if (!state->msg)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
@@ -33,7 +33,7 @@
 	latency = integer * 1000 + fract / 1000;
 	ret = hid_sensor_set_report_latency(attrb, latency);
 	if (ret < 0)
-		return len;
+		return ret;
 
 	attrb->latency_ms = hid_sensor_get_report_latency(attrb);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/common/ms_sensors/ms_sensors_i2c.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/common/ms_sensors/ms_sensors_i2c.c
@@ -15,8 +15,8 @@
 /* Conversion times in us */
 static const u16 ms_sensors_ht_t_conversion_time[] = { 50000, 25000,
 						       13000, 7000 };
-static const u16 ms_sensors_ht_h_conversion_time[] = { 16000, 3000,
-						       5000, 8000 };
+static const u16 ms_sensors_ht_h_conversion_time[] = { 16000, 5000,
+						       3000, 8000 };
 static const u16 ms_sensors_tp_conversion_time[] = { 500, 1100, 2100,
 						     4100, 8220, 16440 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/common/ssp_sensors/ssp_spi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/common/ssp_sensors/ssp_spi.c
@@ -137,7 +137,7 @@
 	if (length > received_len - *data_index || length <= 0) {
 		ssp_dbg("[SSP]: MSG From MCU-invalid debug length(%d/%d)\n",
 			length, received_len);
-		return length ? length : -EPROTO;
+		return -EPROTO;
 	}
 
 	ssp_dbg("[SSP]: MSG From MCU - %s\n", &data_frame[*data_index]);
@@ -273,6 +273,8 @@
 	for (idx = 0; idx < len;) {
 		switch (dataframe[idx++]) {
 		case SSP_MSG2AP_INST_BYPASS_DATA:
+			if (idx >= len)
+				return -EPROTO;
 			sd = dataframe[idx++];
 			if (sd < 0 || sd >= SSP_SENSOR_MAX) {
 				dev_err(SSP_DEV,
@@ -282,10 +284,13 @@
 
 			if (indio_devs[sd]) {
 				spd = iio_priv(indio_devs[sd]);
-				if (spd->process_data)
+				if (spd->process_data) {
+					if (idx >= len)
+						return -EPROTO;
 					spd->process_data(indio_devs[sd],
 							  &dataframe[idx],
 							  data->timestamp);
+				}
 			} else {
 				dev_err(SSP_DEV, "no client for frame\n");
 			}
@@ -293,6 +298,8 @@
 			idx += ssp_offset_map[sd];
 			break;
 		case SSP_MSG2AP_INST_DEBUG_DATA:
+			if (idx >= len)
+				return -EPROTO;
 			sd = ssp_print_mcu_debug(dataframe, &idx, len);
 			if (sd) {
 				dev_err(SSP_DEV,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/common/st_sensors/st_sensors_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/common/st_sensors/st_sensors_core.c
@@ -76,16 +76,18 @@
 
 int st_sensors_set_odr(struct iio_dev *indio_dev, unsigned int odr)
 {
-	int err;
+	int err = 0;
 	struct st_sensor_odr_avl odr_out = {0, 0};
 	struct st_sensor_data *sdata = iio_priv(indio_dev);
 
-	if (!sdata->sensor_settings->odr.addr)
-		return 0;
+	mutex_lock(&sdata->odr_lock);
+
+	if (!sdata->sensor_settings->odr.mask)
+		goto unlock_mutex;
 
 	err = st_sensors_match_odr(sdata->sensor_settings, odr, &odr_out);
 	if (err < 0)
-		goto st_sensors_match_odr_error;
+		goto unlock_mutex;
 
 	if ((sdata->sensor_settings->odr.addr ==
 					sdata->sensor_settings->pw.addr) &&
@@ -108,7 +110,9 @@
 	if (err >= 0)
 		sdata->odr = odr_out.hz;
 
-st_sensors_match_odr_error:
+unlock_mutex:
+	mutex_unlock(&sdata->odr_lock);
+
 	return err;
 }
 EXPORT_SYMBOL(st_sensors_set_odr);
@@ -384,6 +388,8 @@
 	struct st_sensors_platform_data *of_pdata;
 	int err = 0;
 
+	mutex_init(&sdata->odr_lock);
+
 	/* If OF/DT pdata exists, it will take precedence of anything else */
 	of_pdata = st_sensors_of_probe(indio_dev->dev.parent, pdata);
 	if (of_pdata)
@@ -575,18 +581,24 @@
 		err = -EBUSY;
 		goto out;
 	} else {
+		mutex_lock(&sdata->odr_lock);
 		err = st_sensors_set_enable(indio_dev, true);
-		if (err < 0)
+		if (err < 0) {
+			mutex_unlock(&sdata->odr_lock);
 			goto out;
+		}
 
 		msleep((sdata->sensor_settings->bootime * 1000) / sdata->odr);
 		err = st_sensors_read_axis_data(indio_dev, ch, val);
-		if (err < 0)
+		if (err < 0) {
+			mutex_unlock(&sdata->odr_lock);
 			goto out;
+		}
 
 		*val = *val >> ch->scan_type.shift;
 
 		err = st_sensors_set_enable(indio_dev, false);
+		mutex_unlock(&sdata->odr_lock);
 	}
 out:
 	mutex_unlock(&indio_dev->mlock);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/dac/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/dac/Kconfig
@@ -60,8 +60,8 @@
 	help
 	  Say yes here to build support for Analog Devices AD5300, AD5301, AD5310,
 	  AD5311, AD5320, AD5321, AD5444, AD5446, AD5450, AD5451, AD5452, AD5453,
-	  AD5512A, AD5541A, AD5542A, AD5543, AD5553, AD5601, AD5602, AD5611, AD5612,
-	  AD5620, AD5621, AD5622, AD5640, AD5641, AD5660, AD5662 DACs
+	  AD5512A, AD5541A, AD5542A, AD5543, AD5553, AD5600, AD5601, AD5602, AD5611,
+	  AD5612, AD5620, AD5621, AD5622, AD5640, AD5641, AD5660, AD5662 DACs
 	  as well as Texas Instruments DAC081S101, DAC101S101, DAC121S101.
 
 	  To compile this driver as a module, choose M here: the
@@ -124,6 +124,7 @@
 config LTC1660
 	tristate "Linear Technology LTC1660/LTC1665 DAC SPI driver"
 	depends on SPI
+	select REGMAP_SPI
 	help
 	  Say yes here to build support for Linear Technology
 	  LTC1660 and LTC1665 Digital to Analog Converters.
@@ -346,6 +347,7 @@
 
 config STM32_DAC_CORE
 	tristate
+	select REGMAP_MMIO
 
 config TI_DAC082S085
 	tristate "Texas Instruments 8/10/12-bit 2/4-channel DAC driver"
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/dac/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/dac/Makefile
@@ -16,7 +16,7 @@
 obj-$(CONFIG_AD5592R) += ad5592r.o
 obj-$(CONFIG_AD5593R) += ad5593r.o
 obj-$(CONFIG_AD5755) += ad5755.o
-obj-$(CONFIG_AD5755) += ad5758.o
+obj-$(CONFIG_AD5758) += ad5758.o
 obj-$(CONFIG_AD5761) += ad5761.o
 obj-$(CONFIG_AD5764) += ad5764.o
 obj-$(CONFIG_AD5791) += ad5791.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/dac/ad5446.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/dac/ad5446.c
@@ -170,7 +170,7 @@
 
 	switch (m) {
 	case IIO_CHAN_INFO_RAW:
-		*val = st->cached_val;
+		*val = st->cached_val >> chan->scan_type.shift;
 		return IIO_VAL_INT;
 	case IIO_CHAN_INFO_SCALE:
 		*val = st->vref_mv;
@@ -327,6 +327,7 @@
 	ID_AD5541A,
 	ID_AD5512A,
 	ID_AD5553,
+	ID_AD5600,
 	ID_AD5601,
 	ID_AD5611,
 	ID_AD5621,
@@ -381,6 +382,10 @@
 		.channel = AD5446_CHANNEL(14, 16, 0),
 		.write = ad5446_write,
 	},
+	[ID_AD5600] = {
+		.channel = AD5446_CHANNEL(16, 16, 0),
+		.write = ad5446_write,
+	},
 	[ID_AD5601] = {
 		.channel = AD5446_CHANNEL_POWERDOWN(8, 16, 6),
 		.write = ad5446_write,
@@ -448,6 +453,7 @@
 	{"ad5542a", ID_AD5541A}, /* ad5541a and ad5542a are compatible */
 	{"ad5543", ID_AD5541A}, /* ad5541a and ad5543 are compatible */
 	{"ad5553", ID_AD5553},
+	{"ad5600", ID_AD5600},
 	{"ad5601", ID_AD5601},
 	{"ad5611", ID_AD5611},
 	{"ad5621", ID_AD5621},
@@ -521,8 +527,15 @@
 {
 	struct i2c_client *client = to_i2c_client(st->dev);
 	__be16 data = cpu_to_be16(val);
+	int ret;
 
-	return i2c_master_send(client, (char *)&data, sizeof(data));
+	ret = i2c_master_send(client, (char *)&data, sizeof(data));
+	if (ret < 0)
+		return ret;
+	if (ret != sizeof(data))
+		return -EIO;
+
+	return 0;
 }
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/dac/ad5504.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/dac/ad5504.c
@@ -188,9 +188,9 @@
 		return ret;
 
 	if (pwr_down)
-		st->pwr_down_mask |= (1 << chan->channel);
-	else
 		st->pwr_down_mask &= ~(1 << chan->channel);
+	else
+		st->pwr_down_mask |= (1 << chan->channel);
 
 	ret = ad5504_spi_write(st, AD5504_ADDR_CTRL,
 				AD5504_DAC_PWRDWN_MODE(st->pwr_down_mode) |
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/dac/ad5592r-base.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/dac/ad5592r-base.c
@@ -157,7 +157,6 @@
 static int ad5592r_reset(struct ad5592r_state *st)
 {
 	struct gpio_desc *gpio;
-	struct iio_dev *iio_dev = iio_priv_to_dev(st);
 
 	gpio = devm_gpiod_get_optional(st->dev, "reset", GPIOD_OUT_LOW);
 	if (IS_ERR(gpio))
@@ -167,10 +166,10 @@
 		udelay(1);
 		gpiod_set_value(gpio, 1);
 	} else {
-		mutex_lock(&iio_dev->mlock);
+		mutex_lock(&st->lock);
 		/* Writing this magic value resets the device */
 		st->ops->reg_write(st, AD5592R_REG_RESET, 0xdac);
-		mutex_unlock(&iio_dev->mlock);
+		mutex_unlock(&st->lock);
 	}
 
 	udelay(250);
@@ -198,7 +197,6 @@
 	const struct ad5592r_rw_ops *ops = st->ops;
 	int ret;
 	unsigned i;
-	struct iio_dev *iio_dev = iio_priv_to_dev(st);
 	u8 pulldown = 0, tristate = 0, dac = 0, adc = 0;
 	u16 read_back;
 
@@ -248,7 +246,7 @@
 		}
 	}
 
-	mutex_lock(&iio_dev->mlock);
+	mutex_lock(&st->lock);
 
 	/* Pull down unused pins to GND */
 	ret = ops->reg_write(st, AD5592R_REG_PULLDOWN, pulldown);
@@ -286,7 +284,7 @@
 		ret = -EIO;
 
 err_unlock:
-	mutex_unlock(&iio_dev->mlock);
+	mutex_unlock(&st->lock);
 	return ret;
 }
 
@@ -315,11 +313,11 @@
 		if (!chan->output)
 			return -EINVAL;
 
-		mutex_lock(&iio_dev->mlock);
+		mutex_lock(&st->lock);
 		ret = st->ops->write_dac(st, chan->channel, val);
 		if (!ret)
 			st->cached_dac[chan->channel] = val;
-		mutex_unlock(&iio_dev->mlock);
+		mutex_unlock(&st->lock);
 		return ret;
 	case IIO_CHAN_INFO_SCALE:
 		if (chan->type == IIO_VOLTAGE) {
@@ -334,12 +332,12 @@
 			else
 				return -EINVAL;
 
-			mutex_lock(&iio_dev->mlock);
+			mutex_lock(&st->lock);
 
 			ret = st->ops->reg_read(st, AD5592R_REG_CTRL,
 						&st->cached_gp_ctrl);
 			if (ret < 0) {
-				mutex_unlock(&iio_dev->mlock);
+				mutex_unlock(&st->lock);
 				return ret;
 			}
 
@@ -361,7 +359,7 @@
 
 			ret = st->ops->reg_write(st, AD5592R_REG_CTRL,
 						 st->cached_gp_ctrl);
-			mutex_unlock(&iio_dev->mlock);
+			mutex_unlock(&st->lock);
 
 			return ret;
 		}
@@ -379,11 +377,11 @@
 {
 	struct ad5592r_state *st = iio_priv(iio_dev);
 	u16 read_val;
-	int ret;
+	int ret, mult;
 
 	switch (m) {
 	case IIO_CHAN_INFO_RAW:
-		mutex_lock(&iio_dev->mlock);
+		mutex_lock(&st->lock);
 
 		if (!chan->output) {
 			ret = st->ops->read_adc(st, chan->channel, &read_val);
@@ -416,29 +414,27 @@
 			s64 tmp = *val * (3767897513LL / 25LL);
 			*val = div_s64_rem(tmp, 1000000000LL, val2);
 
-			ret = IIO_VAL_INT_PLUS_MICRO;
-		} else {
-			int mult;
+			return IIO_VAL_INT_PLUS_NANO;
+		}
 
-			mutex_lock(&iio_dev->mlock);
+		mutex_lock(&st->lock);
 
-			if (chan->output)
-				mult = !!(st->cached_gp_ctrl &
-					AD5592R_REG_CTRL_DAC_RANGE);
-			else
-				mult = !!(st->cached_gp_ctrl &
-					AD5592R_REG_CTRL_ADC_RANGE);
+		if (chan->output)
+			mult = !!(st->cached_gp_ctrl &
+				AD5592R_REG_CTRL_DAC_RANGE);
+		else
+			mult = !!(st->cached_gp_ctrl &
+				AD5592R_REG_CTRL_ADC_RANGE);
 
-			*val *= ++mult;
+		*val *= ++mult;
 
-			*val2 = chan->scan_type.realbits;
-			ret = IIO_VAL_FRACTIONAL_LOG2;
-		}
+		*val2 = chan->scan_type.realbits;
+		ret = IIO_VAL_FRACTIONAL_LOG2;
 		break;
 	case IIO_CHAN_INFO_OFFSET:
 		ret = ad5592r_get_vref(st);
 
-		mutex_lock(&iio_dev->mlock);
+		mutex_lock(&st->lock);
 
 		if (st->cached_gp_ctrl & AD5592R_REG_CTRL_ADC_RANGE)
 			*val = (-34365 * 25) / ret;
@@ -447,11 +443,11 @@
 		ret =  IIO_VAL_INT;
 		break;
 	default:
-		ret = -EINVAL;
+		return -EINVAL;
 	}
 
 unlock:
-	mutex_unlock(&iio_dev->mlock);
+	mutex_unlock(&st->lock);
 	return ret;
 }
 
@@ -530,7 +526,7 @@
 		if (!ret)
 			st->channel_modes[reg] = tmp;
 
-		fwnode_property_read_u32(child, "adi,off-state", &tmp);
+		ret = fwnode_property_read_u32(child, "adi,off-state", &tmp);
 		if (!ret)
 			st->channel_offstate[reg] = tmp;
 	}
@@ -626,6 +622,8 @@
 	iio_dev->info = &ad5592r_info;
 	iio_dev->modes = INDIO_DIRECT_MODE;
 
+	mutex_init(&st->lock);
+
 	ad5592r_init_scales(st, ad5592r_get_vref(st));
 
 	ret = ad5592r_reset(st);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/dac/ad5592r-base.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/dac/ad5592r-base.h
@@ -52,6 +52,7 @@
 	struct regulator *reg;
 	struct gpio_chip gpiochip;
 	struct mutex gpio_lock;	/* Protect cached gpio_out, gpio_val, etc. */
+	struct mutex lock;
 	unsigned int num_channels;
 	const struct ad5592r_rw_ops *ops;
 	int scale_avail[2][2];
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/dac/ad5593r.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/dac/ad5593r.c
@@ -14,6 +14,8 @@
 #include <linux/of.h>
 #include <linux/acpi.h>
 
+#include <asm/unaligned.h>
+
 #define AD5593R_MODE_CONF		(0 << 4)
 #define AD5593R_MODE_DAC_WRITE		(1 << 4)
 #define AD5593R_MODE_ADC_READBACK	(4 << 4)
@@ -21,6 +23,24 @@
 #define AD5593R_MODE_GPIO_READBACK	(6 << 4)
 #define AD5593R_MODE_REG_READBACK	(7 << 4)
 
+static int ad5593r_read_word(struct i2c_client *i2c, u8 reg, u16 *value)
+{
+	int ret;
+	u8 buf[2];
+
+	ret = i2c_smbus_write_byte(i2c, reg);
+	if (ret < 0)
+		return ret;
+
+	ret = i2c_master_recv(i2c, buf, sizeof(buf));
+	if (ret < 0)
+		return ret;
+
+	*value = get_unaligned_be16(buf);
+
+	return 0;
+}
+
 static int ad5593r_write_dac(struct ad5592r_state *st, unsigned chan, u16 value)
 {
 	struct i2c_client *i2c = to_i2c_client(st->dev);
@@ -39,13 +59,7 @@
 	if (val < 0)
 		return (int) val;
 
-	val = i2c_smbus_read_word_swapped(i2c, AD5593R_MODE_ADC_READBACK);
-	if (val < 0)
-		return (int) val;
-
-	*value = (u16) val;
-
-	return 0;
+	return ad5593r_read_word(i2c, AD5593R_MODE_ADC_READBACK, value);
 }
 
 static int ad5593r_reg_write(struct ad5592r_state *st, u8 reg, u16 value)
@@ -59,25 +73,19 @@
 static int ad5593r_reg_read(struct ad5592r_state *st, u8 reg, u16 *value)
 {
 	struct i2c_client *i2c = to_i2c_client(st->dev);
-	s32 val;
-
-	val = i2c_smbus_read_word_swapped(i2c, AD5593R_MODE_REG_READBACK | reg);
-	if (val < 0)
-		return (int) val;
 
-	*value = (u16) val;
-
-	return 0;
+	return ad5593r_read_word(i2c, AD5593R_MODE_REG_READBACK | reg, value);
 }
 
 static int ad5593r_gpio_read(struct ad5592r_state *st, u8 *value)
 {
 	struct i2c_client *i2c = to_i2c_client(st->dev);
-	s32 val;
+	u16 val;
+	int ret;
 
-	val = i2c_smbus_read_word_swapped(i2c, AD5593R_MODE_GPIO_READBACK);
-	if (val < 0)
-		return (int) val;
+	ret = ad5593r_read_word(i2c, AD5593R_MODE_GPIO_READBACK, &val);
+	if (ret)
+		return ret;
 
 	*value = (u8) val;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/dac/ad5624r_spi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/dac/ad5624r_spi.c
@@ -229,7 +229,7 @@
 	if (!indio_dev)
 		return -ENOMEM;
 	st = iio_priv(indio_dev);
-	st->reg = devm_regulator_get(&spi->dev, "vcc");
+	st->reg = devm_regulator_get_optional(&spi->dev, "vref");
 	if (!IS_ERR(st->reg)) {
 		ret = regulator_enable(st->reg);
 		if (ret)
@@ -240,6 +240,22 @@
 			goto error_disable_reg;
 
 		voltage_uv = ret;
+	} else {
+		if (PTR_ERR(st->reg) != -ENODEV)
+			return PTR_ERR(st->reg);
+		/* Backwards compatibility. This naming is not correct */
+		st->reg = devm_regulator_get_optional(&spi->dev, "vcc");
+		if (!IS_ERR(st->reg)) {
+			ret = regulator_enable(st->reg);
+			if (ret)
+				return ret;
+
+			ret = regulator_get_voltage(st->reg);
+			if (ret < 0)
+				goto error_disable_reg;
+
+			voltage_uv = ret;
+		}
 	}
 
 	spi_set_drvdata(spi, indio_dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/dac/cio-dac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/dac/cio-dac.c
@@ -66,8 +66,8 @@
 	if (mask != IIO_CHAN_INFO_RAW)
 		return -EINVAL;
 
-	/* DAC can only accept up to a 16-bit value */
-	if ((unsigned int)val > 65535)
+	/* DAC can only accept up to a 12-bit value */
+	if ((unsigned int)val > 4095)
 		return -EINVAL;
 
 	priv->chan_out_states[chan->channel] = val;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/dac/mcp4725.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/dac/mcp4725.c
@@ -47,12 +47,18 @@
 	struct mcp4725_data *data = iio_priv(i2c_get_clientdata(
 		to_i2c_client(dev)));
 	u8 outbuf[2];
+	int ret;
 
 	outbuf[0] = (data->powerdown_mode + 1) << 4;
 	outbuf[1] = 0;
 	data->powerdown = true;
 
-	return i2c_master_send(data->client, outbuf, 2);
+	ret = i2c_master_send(data->client, outbuf, 2);
+	if (ret < 0)
+		return ret;
+	else if (ret != 2)
+		return -EIO;
+	return 0;
 }
 
 static int __maybe_unused mcp4725_resume(struct device *dev)
@@ -60,13 +66,19 @@
 	struct mcp4725_data *data = iio_priv(i2c_get_clientdata(
 		to_i2c_client(dev)));
 	u8 outbuf[2];
+	int ret;
 
 	/* restore previous DAC value */
 	outbuf[0] = (data->dac_value >> 8) & 0xf;
 	outbuf[1] = data->dac_value & 0xff;
 	data->powerdown = false;
 
-	return i2c_master_send(data->client, outbuf, 2);
+	ret = i2c_master_send(data->client, outbuf, 2);
+	if (ret < 0)
+		return ret;
+	else if (ret != 2)
+		return -EIO;
+	return 0;
 }
 static SIMPLE_DEV_PM_OPS(mcp4725_pm_ops, mcp4725_suspend, mcp4725_resume);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/dac/ti-dac5571.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/dac/ti-dac5571.c
@@ -352,6 +352,7 @@
 		data->dac5571_pwrdwn = dac5571_pwrdwn_quad;
 		break;
 	default:
+		ret = -EINVAL;
 		goto err;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/dac/vf610_dac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/dac/vf610_dac.c
@@ -225,6 +225,7 @@
 	return 0;
 
 error_iio_device_register:
+	vf610_dac_exit(info);
 	clk_disable_unprepare(info->clk);
 
 	return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/dummy/iio_simple_dummy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/dummy/iio_simple_dummy.c
@@ -568,10 +568,9 @@
 	struct iio_sw_device *swd;
 
 	swd = kzalloc(sizeof(*swd), GFP_KERNEL);
-	if (!swd) {
-		ret = -ENOMEM;
-		goto error_kzalloc;
-	}
+	if (!swd)
+		return ERR_PTR(-ENOMEM);
+
 	/*
 	 * Allocate an IIO device.
 	 *
@@ -583,7 +582,7 @@
 	indio_dev = iio_device_alloc(sizeof(*st));
 	if (!indio_dev) {
 		ret = -ENOMEM;
-		goto error_ret;
+		goto error_free_swd;
 	}
 
 	st = iio_priv(indio_dev);
@@ -614,6 +613,10 @@
 	 *    indio_dev->name = spi_get_device_id(spi)->name;
 	 */
 	indio_dev->name = kstrdup(name, GFP_KERNEL);
+	if (!indio_dev->name) {
+		ret = -ENOMEM;
+		goto error_free_device;
+	}
 
 	/* Provide description of available channels */
 	indio_dev->channels = iio_dummy_channels;
@@ -630,7 +633,7 @@
 
 	ret = iio_simple_dummy_events_register(indio_dev);
 	if (ret < 0)
-		goto error_free_device;
+		goto error_free_name;
 
 	ret = iio_simple_dummy_configure_buffer(indio_dev);
 	if (ret < 0)
@@ -647,11 +650,12 @@
 	iio_simple_dummy_unconfigure_buffer(indio_dev);
 error_unregister_events:
 	iio_simple_dummy_events_unregister(indio_dev);
+error_free_name:
+	kfree(indio_dev->name);
 error_free_device:
 	iio_device_free(indio_dev);
-error_ret:
+error_free_swd:
 	kfree(swd);
-error_kzalloc:
 	return ERR_PTR(ret);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/dummy/iio_simple_dummy_buffer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/dummy/iio_simple_dummy_buffer.c
@@ -48,7 +48,7 @@
 	int len = 0;
 	u16 *data;
 
-	data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL);
+	data = kzalloc(indio_dev->scan_bytes, GFP_KERNEL);
 	if (!data)
 		goto done;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/gyro/bmg160_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/gyro/bmg160_core.c
@@ -96,7 +96,11 @@
 	struct iio_trigger *motion_trig;
 	struct iio_mount_matrix orientation;
 	struct mutex mutex;
-	s16 buffer[8];
+	/* Ensure naturally aligned timestamp */
+	struct {
+		s16 chans[3];
+		s64 timestamp __aligned(8);
+	} scan;
 	u32 dps_range;
 	int ev_enable_state;
 	int slope_thres;
@@ -880,12 +884,12 @@
 
 	mutex_lock(&data->mutex);
 	ret = regmap_bulk_read(data->regmap, BMG160_REG_XOUT_L,
-			       data->buffer, AXIS_MAX * 2);
+			       data->scan.chans, AXIS_MAX * 2);
 	mutex_unlock(&data->mutex);
 	if (ret < 0)
 		goto err;
 
-	iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+	iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
 					   pf->timestamp);
 err:
 	iio_trigger_notify_done(indio_dev->trig);
@@ -1169,11 +1173,14 @@
 	ret = iio_device_register(indio_dev);
 	if (ret < 0) {
 		dev_err(dev, "unable to register iio device\n");
-		goto err_buffer_cleanup;
+		goto err_pm_cleanup;
 	}
 
 	return 0;
 
+err_pm_cleanup:
+	pm_runtime_dont_use_autosuspend(dev);
+	pm_runtime_disable(dev);
 err_buffer_cleanup:
 	iio_triggered_buffer_cleanup(indio_dev);
 err_trigger_unregister:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/gyro/fxas21002c_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/gyro/fxas21002c_core.c
@@ -300,14 +300,7 @@
 
 static int  fxas21002c_pm_get(struct fxas21002c_data *data)
 {
-	struct device *dev = regmap_get_device(data->regmap);
-	int ret;
-
-	ret = pm_runtime_get_sync(dev);
-	if (ret < 0)
-		pm_runtime_put_noidle(dev);
-
-	return ret;
+	return pm_runtime_resume_and_get(regmap_get_device(data->regmap));
 }
 
 static int  fxas21002c_pm_put(struct fxas21002c_data *data)
@@ -333,6 +326,7 @@
 	ret = regmap_field_read(data->regmap_fields[F_TEMP], &temp);
 	if (ret < 0) {
 		dev_err(dev, "failed to read temp: %d\n", ret);
+		fxas21002c_pm_put(data);
 		goto data_unlock;
 	}
 
@@ -366,6 +360,7 @@
 			       &axis_be, sizeof(axis_be));
 	if (ret < 0) {
 		dev_err(dev, "failed to read axis: %d: %d\n", index, ret);
+		fxas21002c_pm_put(data);
 		goto data_unlock;
 	}
 
@@ -669,14 +664,21 @@
 	int ret;
 
 	mutex_lock(&data->lock);
+	ret = fxas21002c_pm_get(data);
+	if (ret < 0)
+		goto out_unlock;
+
 	ret = regmap_bulk_read(data->regmap, FXAS21002C_REG_OUT_X_MSB,
 			       data->buffer, CHANNEL_SCAN_MAX * sizeof(s16));
 	if (ret < 0)
-		goto out_unlock;
+		goto out_pm_put;
 
 	iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
 					   data->timestamp);
 
+out_pm_put:
+	fxas21002c_pm_put(data);
+
 out_unlock:
 	mutex_unlock(&data->lock);
 
@@ -938,7 +940,6 @@
 pm_disable:
 	pm_runtime_disable(dev);
 	pm_runtime_set_suspended(dev);
-	pm_runtime_put_noidle(dev);
 
 	return ret;
 }
@@ -952,7 +953,6 @@
 
 	pm_runtime_disable(dev);
 	pm_runtime_set_suspended(dev);
-	pm_runtime_put_noidle(dev);
 }
 EXPORT_SYMBOL_GPL(fxas21002c_core_remove);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/gyro/itg3200_buffer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/gyro/itg3200_buffer.c
@@ -46,17 +46,24 @@
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct itg3200 *st = iio_priv(indio_dev);
-	__be16 buf[ITG3200_SCAN_ELEMENTS + sizeof(s64)/sizeof(u16)];
+	/*
+	 * Ensure correct alignment and padding including for the
+	 * timestamp that may be inserted.
+	 */
+	struct {
+		__be16 buf[ITG3200_SCAN_ELEMENTS];
+		s64 ts __aligned(8);
+	} scan;
 
-	int ret = itg3200_read_all_channels(st->i2c, buf);
+	int ret = itg3200_read_all_channels(st->i2c, scan.buf);
 	if (ret < 0)
 		goto error_ret;
 
-	iio_push_to_buffers_with_timestamp(indio_dev, buf, pf->timestamp);
+	iio_push_to_buffers_with_timestamp(indio_dev, &scan, pf->timestamp);
 
+error_ret:
 	iio_trigger_notify_done(indio_dev->trig);
 
-error_ret:
 	return IRQ_HANDLED;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/gyro/mpu3050-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/gyro/mpu3050-core.c
@@ -271,7 +271,16 @@
 	case IIO_CHAN_INFO_OFFSET:
 		switch (chan->type) {
 		case IIO_TEMP:
-			/* The temperature scaling is (x+23000)/280 Celsius */
+			/*
+			 * The temperature scaling is (x+23000)/280 Celsius
+			 * for the "best fit straight line" temperature range
+			 * of -30C..85C.  The 23000 includes room temperature
+			 * offset of +35C, 280 is the precision scale and x is
+			 * the 16-bit signed integer reported by hardware.
+			 *
+			 * Temperature value itself represents temperature of
+			 * the sensor die.
+			 */
 			*val = 23000;
 			return IIO_VAL_INT;
 		default:
@@ -328,7 +337,7 @@
 				goto out_read_raw_unlock;
 			}
 
-			*val = be16_to_cpu(raw_val);
+			*val = (s16)be16_to_cpu(raw_val);
 			ret = IIO_VAL_INT;
 
 			goto out_read_raw_unlock;
@@ -550,6 +559,8 @@
 					       MPU3050_FIFO_R,
 					       &fifo_values[offset],
 					       toread);
+			if (ret)
+				goto out_trigger_unlock;
 
 			dev_dbg(mpu3050->dev,
 				"%04x %04x %04x %04x %04x\n",
@@ -863,6 +874,7 @@
 	ret = regmap_update_bits(mpu3050->map, MPU3050_PWR_MGM,
 				 MPU3050_PWR_MGM_SLEEP, 0);
 	if (ret) {
+		regulator_bulk_disable(ARRAY_SIZE(mpu3050->regs), mpu3050->regs);
 		dev_err(mpu3050->dev, "error setting power mode\n");
 		return ret;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/gyro/st_gyro_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/gyro/st_gyro_core.c
@@ -139,7 +139,6 @@
 			[2] = LSM330DLC_GYRO_DEV_NAME,
 			[3] = L3G4IS_GYRO_DEV_NAME,
 			[4] = LSM330_GYRO_DEV_NAME,
-			[5] = LSM9DS0_GYRO_DEV_NAME,
 		},
 		.ch = (struct iio_chan_spec *)st_gyro_16bit_channels,
 		.odr = {
@@ -203,6 +202,80 @@
 			},
 		},
 		.sim = {
+			.addr = 0x23,
+			.value = BIT(0),
+		},
+		.multi_read_bit = true,
+		.bootime = 2,
+	},
+	{
+		.wai = 0xd4,
+		.wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
+		.sensors_supported = {
+			[0] = LSM9DS0_GYRO_DEV_NAME,
+		},
+		.ch = (struct iio_chan_spec *)st_gyro_16bit_channels,
+		.odr = {
+			.addr = 0x20,
+			.mask = GENMASK(7, 6),
+			.odr_avl = {
+				{ .hz = 95, .value = 0x00, },
+				{ .hz = 190, .value = 0x01, },
+				{ .hz = 380, .value = 0x02, },
+				{ .hz = 760, .value = 0x03, },
+			},
+		},
+		.pw = {
+			.addr = 0x20,
+			.mask = BIT(3),
+			.value_on = ST_SENSORS_DEFAULT_POWER_ON_VALUE,
+			.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
+		},
+		.enable_axis = {
+			.addr = ST_SENSORS_DEFAULT_AXIS_ADDR,
+			.mask = ST_SENSORS_DEFAULT_AXIS_MASK,
+		},
+		.fs = {
+			.addr = 0x23,
+			.mask = GENMASK(5, 4),
+			.fs_avl = {
+				[0] = {
+					.num = ST_GYRO_FS_AVL_245DPS,
+					.value = 0x00,
+					.gain = IIO_DEGREE_TO_RAD(8750),
+				},
+				[1] = {
+					.num = ST_GYRO_FS_AVL_500DPS,
+					.value = 0x01,
+					.gain = IIO_DEGREE_TO_RAD(17500),
+				},
+				[2] = {
+					.num = ST_GYRO_FS_AVL_2000DPS,
+					.value = 0x02,
+					.gain = IIO_DEGREE_TO_RAD(70000),
+				},
+			},
+		},
+		.bdu = {
+			.addr = 0x23,
+			.mask = BIT(7),
+		},
+		.drdy_irq = {
+			.int2 = {
+				.addr = 0x22,
+				.mask = BIT(3),
+			},
+			/*
+			 * The sensor has IHL (active low) and open
+			 * drain settings, but only for INT1 and not
+			 * for the DRDY line on INT2.
+			 */
+			.stat_drdy = {
+				.addr = ST_SENSORS_DEFAULT_STAT_ADDR,
+				.mask = GENMASK(2, 0),
+			},
+		},
+		.sim = {
 			.addr = 0x23,
 			.value = BIT(0),
 		},
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/health/afe4403.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/health/afe4403.c
@@ -63,6 +63,7 @@
  * @regulator: Pointer to the regulator for the IC
  * @trig: IIO trigger for this device
  * @irq: ADC_RDY line interrupt number
+ * @buffer: Used to construct data layout to push into IIO buffer.
  */
 struct afe4403_data {
 	struct device *dev;
@@ -72,6 +73,8 @@
 	struct regulator *regulator;
 	struct iio_trigger *trig;
 	int irq;
+	/* Ensure suitable alignment for timestamp */
+	s32 buffer[8] __aligned(8);
 };
 
 enum afe4403_chan_id {
@@ -242,14 +245,14 @@
 			    int *val, int *val2, long mask)
 {
 	struct afe4403_data *afe = iio_priv(indio_dev);
-	unsigned int reg = afe4403_channel_values[chan->address];
-	unsigned int field = afe4403_channel_leds[chan->address];
+	unsigned int reg, field;
 	int ret;
 
 	switch (chan->type) {
 	case IIO_INTENSITY:
 		switch (mask) {
 		case IIO_CHAN_INFO_RAW:
+			reg = afe4403_channel_values[chan->address];
 			ret = afe4403_read(afe, reg, val);
 			if (ret)
 				return ret;
@@ -259,6 +262,7 @@
 	case IIO_CURRENT:
 		switch (mask) {
 		case IIO_CHAN_INFO_RAW:
+			field = afe4403_channel_leds[chan->address];
 			ret = regmap_field_read(afe->fields[field], val);
 			if (ret)
 				return ret;
@@ -309,7 +313,6 @@
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct afe4403_data *afe = iio_priv(indio_dev);
 	int ret, bit, i = 0;
-	s32 buffer[8];
 	u8 tx[4] = {AFE440X_CONTROL0, 0x0, 0x0, AFE440X_CONTROL0_READ};
 	u8 rx[3];
 
@@ -326,9 +329,9 @@
 		if (ret)
 			goto err;
 
-		buffer[i++] = (rx[0] << 16) |
-				(rx[1] << 8) |
-				(rx[2]);
+		afe->buffer[i++] = (rx[0] << 16) |
+				   (rx[1] << 8) |
+				   (rx[2]);
 	}
 
 	/* Disable reading from the device */
@@ -337,7 +340,8 @@
 	if (ret)
 		goto err;
 
-	iio_push_to_buffers_with_timestamp(indio_dev, buffer, pf->timestamp);
+	iio_push_to_buffers_with_timestamp(indio_dev, afe->buffer,
+					   pf->timestamp);
 err:
 	iio_trigger_notify_done(indio_dev->trig);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/health/afe4404.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/health/afe4404.c
@@ -83,6 +83,7 @@
  * @regulator: Pointer to the regulator for the IC
  * @trig: IIO trigger for this device
  * @irq: ADC_RDY line interrupt number
+ * @buffer: Used to construct a scan to push to the iio buffer.
  */
 struct afe4404_data {
 	struct device *dev;
@@ -91,6 +92,7 @@
 	struct regulator *regulator;
 	struct iio_trigger *trig;
 	int irq;
+	s32 buffer[10] __aligned(8);
 };
 
 enum afe4404_chan_id {
@@ -248,20 +250,20 @@
 			    int *val, int *val2, long mask)
 {
 	struct afe4404_data *afe = iio_priv(indio_dev);
-	unsigned int value_reg = afe4404_channel_values[chan->address];
-	unsigned int led_field = afe4404_channel_leds[chan->address];
-	unsigned int offdac_field = afe4404_channel_offdacs[chan->address];
+	unsigned int value_reg, led_field, offdac_field;
 	int ret;
 
 	switch (chan->type) {
 	case IIO_INTENSITY:
 		switch (mask) {
 		case IIO_CHAN_INFO_RAW:
+			value_reg = afe4404_channel_values[chan->address];
 			ret = regmap_read(afe->regmap, value_reg, val);
 			if (ret)
 				return ret;
 			return IIO_VAL_INT;
 		case IIO_CHAN_INFO_OFFSET:
+			offdac_field = afe4404_channel_offdacs[chan->address];
 			ret = regmap_field_read(afe->fields[offdac_field], val);
 			if (ret)
 				return ret;
@@ -271,6 +273,7 @@
 	case IIO_CURRENT:
 		switch (mask) {
 		case IIO_CHAN_INFO_RAW:
+			led_field = afe4404_channel_leds[chan->address];
 			ret = regmap_field_read(afe->fields[led_field], val);
 			if (ret)
 				return ret;
@@ -293,19 +296,20 @@
 			     int val, int val2, long mask)
 {
 	struct afe4404_data *afe = iio_priv(indio_dev);
-	unsigned int led_field = afe4404_channel_leds[chan->address];
-	unsigned int offdac_field = afe4404_channel_offdacs[chan->address];
+	unsigned int led_field, offdac_field;
 
 	switch (chan->type) {
 	case IIO_INTENSITY:
 		switch (mask) {
 		case IIO_CHAN_INFO_OFFSET:
+			offdac_field = afe4404_channel_offdacs[chan->address];
 			return regmap_field_write(afe->fields[offdac_field], val);
 		}
 		break;
 	case IIO_CURRENT:
 		switch (mask) {
 		case IIO_CHAN_INFO_RAW:
+			led_field = afe4404_channel_leds[chan->address];
 			return regmap_field_write(afe->fields[led_field], val);
 		}
 		break;
@@ -328,17 +332,17 @@
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct afe4404_data *afe = iio_priv(indio_dev);
 	int ret, bit, i = 0;
-	s32 buffer[10];
 
 	for_each_set_bit(bit, indio_dev->active_scan_mask,
 			 indio_dev->masklength) {
 		ret = regmap_read(afe->regmap, afe4404_channel_values[bit],
-				  &buffer[i++]);
+				  &afe->buffer[i++]);
 		if (ret)
 			goto err;
 	}
 
-	iio_push_to_buffers_with_timestamp(indio_dev, buffer, pf->timestamp);
+	iio_push_to_buffers_with_timestamp(indio_dev, afe->buffer,
+					   pf->timestamp);
 err:
 	iio_trigger_notify_done(indio_dev->trig);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/humidity/am2315.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/humidity/am2315.c
@@ -33,7 +33,11 @@
 struct am2315_data {
 	struct i2c_client *client;
 	struct mutex lock;
-	s16 buffer[8]; /* 2x16-bit channels + 2x16 padding + 4x16 timestamp */
+	/* Ensure timestamp is naturally aligned */
+	struct {
+		s16 chans[2];
+		s64 timestamp __aligned(8);
+	} scan;
 };
 
 struct am2315_sensor_data {
@@ -167,20 +171,20 @@
 
 	mutex_lock(&data->lock);
 	if (*(indio_dev->active_scan_mask) == AM2315_ALL_CHANNEL_MASK) {
-		data->buffer[0] = sensor_data.hum_data;
-		data->buffer[1] = sensor_data.temp_data;
+		data->scan.chans[0] = sensor_data.hum_data;
+		data->scan.chans[1] = sensor_data.temp_data;
 	} else {
 		i = 0;
 		for_each_set_bit(bit, indio_dev->active_scan_mask,
 				 indio_dev->masklength) {
-			data->buffer[i] = (bit ? sensor_data.temp_data :
-						 sensor_data.hum_data);
+			data->scan.chans[i] = (bit ? sensor_data.temp_data :
+					       sensor_data.hum_data);
 			i++;
 		}
 	}
 	mutex_unlock(&data->lock);
 
-	iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+	iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
 					   pf->timestamp);
 err:
 	iio_trigger_notify_done(indio_dev->trig);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/humidity/hdc100x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/humidity/hdc100x.c
@@ -24,6 +24,8 @@
 #include <linux/iio/trigger_consumer.h>
 #include <linux/iio/triggered_buffer.h>
 
+#include <linux/time.h>
+
 #define HDC100X_REG_TEMP			0x00
 #define HDC100X_REG_HUMIDITY			0x01
 
@@ -38,6 +40,11 @@
 
 	/* integration time of the sensor */
 	int adc_int_us[2];
+	/* Ensure natural alignment of timestamp */
+	struct {
+		__be16 channels[2];
+		s64 ts __aligned(8);
+	} scan;
 };
 
 /* integration time in us */
@@ -160,7 +167,7 @@
 				   struct iio_chan_spec const *chan)
 {
 	struct i2c_client *client = data->client;
-	int delay = data->adc_int_us[chan->address];
+	int delay = data->adc_int_us[chan->address] + 1*USEC_PER_MSEC;
 	int ret;
 	__be16 val;
 
@@ -229,7 +236,7 @@
 			*val2 = 65536;
 			return IIO_VAL_FRACTIONAL;
 		} else {
-			*val = 100;
+			*val = 100000;
 			*val2 = 65536;
 			return IIO_VAL_FRACTIONAL;
 		}
@@ -317,9 +324,8 @@
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct hdc100x_data *data = iio_priv(indio_dev);
 	struct i2c_client *client = data->client;
-	int delay = data->adc_int_us[0] + data->adc_int_us[1];
+	int delay = data->adc_int_us[0] + data->adc_int_us[1] + 2*USEC_PER_MSEC;
 	int ret;
-	s16 buf[8];  /* 2x s16 + padding + 8 byte timestamp */
 
 	/* dual read starts at temp register */
 	mutex_lock(&data->lock);
@@ -330,13 +336,13 @@
 	}
 	usleep_range(delay, delay + 1000);
 
-	ret = i2c_master_recv(client, (u8 *)buf, 4);
+	ret = i2c_master_recv(client, (u8 *)data->scan.channels, 4);
 	if (ret < 0) {
 		dev_err(&client->dev, "cannot read sensor data\n");
 		goto err;
 	}
 
-	iio_push_to_buffers_with_timestamp(indio_dev, buf,
+	iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
 					   iio_get_time_ns(indio_dev));
 err:
 	mutex_unlock(&data->lock);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/humidity/hid-sensor-humidity.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/humidity/hid-sensor-humidity.c
@@ -17,7 +17,10 @@
 struct hid_humidity_state {
 	struct hid_sensor_common common_attributes;
 	struct hid_sensor_hub_attribute_info humidity_attr;
-	s32 humidity_data;
+	struct {
+		s32 humidity_data;
+		u64 timestamp __aligned(8);
+	} scan;
 	int scale_pre_decml;
 	int scale_post_decml;
 	int scale_precision;
@@ -127,9 +130,8 @@
 	struct hid_humidity_state *humid_st = iio_priv(indio_dev);
 
 	if (atomic_read(&humid_st->common_attributes.data_ready))
-		iio_push_to_buffers_with_timestamp(indio_dev,
-					&humid_st->humidity_data,
-					iio_get_time_ns(indio_dev));
+		iio_push_to_buffers_with_timestamp(indio_dev, &humid_st->scan,
+						   iio_get_time_ns(indio_dev));
 
 	return 0;
 }
@@ -144,7 +146,7 @@
 
 	switch (usage_id) {
 	case HID_USAGE_SENSOR_ATMOSPHERIC_HUMIDITY:
-		humid_st->humidity_data = *(s32 *)raw_data;
+		humid_st->scan.humidity_data = *(s32 *)raw_data;
 
 		return 0;
 	default:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/humidity/hts221.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/humidity/hts221.h
@@ -14,8 +14,6 @@
 
 #include <linux/iio/iio.h>
 
-#define HTS221_DATA_SIZE	2
-
 enum hts221_sensor_type {
 	HTS221_SENSOR_H,
 	HTS221_SENSOR_T,
@@ -39,6 +37,11 @@
 
 	bool enabled;
 	u8 odr;
+	/* Ensure natural alignment of timestamp */
+	struct {
+		__le16 channels[2];
+		s64 ts __aligned(8);
+	} scan;
 };
 
 extern const struct dev_pm_ops hts221_pm_ops;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/humidity/hts221_buffer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/humidity/hts221_buffer.c
@@ -162,7 +162,6 @@
 
 static irqreturn_t hts221_buffer_handler_thread(int irq, void *p)
 {
-	u8 buffer[ALIGN(2 * HTS221_DATA_SIZE, sizeof(s64)) + sizeof(s64)];
 	struct iio_poll_func *pf = p;
 	struct iio_dev *iio_dev = pf->indio_dev;
 	struct hts221_hw *hw = iio_priv(iio_dev);
@@ -172,18 +171,20 @@
 	/* humidity data */
 	ch = &iio_dev->channels[HTS221_SENSOR_H];
 	err = regmap_bulk_read(hw->regmap, ch->address,
-			       buffer, HTS221_DATA_SIZE);
+			       &hw->scan.channels[0],
+			       sizeof(hw->scan.channels[0]));
 	if (err < 0)
 		goto out;
 
 	/* temperature data */
 	ch = &iio_dev->channels[HTS221_SENSOR_T];
 	err = regmap_bulk_read(hw->regmap, ch->address,
-			       buffer + HTS221_DATA_SIZE, HTS221_DATA_SIZE);
+			       &hw->scan.channels[1],
+			       sizeof(hw->scan.channels[1]));
 	if (err < 0)
 		goto out;
 
-	iio_push_to_buffers_with_timestamp(iio_dev, buffer,
+	iio_push_to_buffers_with_timestamp(iio_dev, &hw->scan,
 					   iio_get_time_ns(iio_dev));
 
 out:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/imu/adis16400.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/imu/adis16400.c
@@ -464,8 +464,7 @@
 		if (ret)
 			goto err_ret;
 
-		ret = sscanf(indio_dev->name, "adis%u\n", &device_id);
-		if (ret != 1) {
+		if (sscanf(indio_dev->name, "adis%u\n", &device_id) != 1) {
 			ret = -EINVAL;
 			goto err_ret;
 		}
@@ -652,9 +651,6 @@
 	void *buffer;
 	int ret;
 
-	if (!adis->buffer)
-		return -ENOMEM;
-
 	if (!(st->variant->flags & ADIS16400_NO_BURST) &&
 		st->adis.spi->max_speed_hz > ADIS16400_SPI_BURST) {
 		st->adis.spi->max_speed_hz = ADIS16400_SPI_BURST;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/imu/adis16480.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/imu/adis16480.c
@@ -454,12 +454,14 @@
 	case IIO_MAGN:
 	case IIO_PRESSURE:
 		ret = adis_read_reg_16(&st->adis, reg, &val16);
-		*bias = sign_extend32(val16, 15);
+		if (ret == 0)
+			*bias = sign_extend32(val16, 15);
 		break;
 	case IIO_ANGL_VEL:
 	case IIO_ACCEL:
 		ret = adis_read_reg_32(&st->adis, reg, &val32);
-		*bias = sign_extend32(val32, 31);
+		if (ret == 0)
+			*bias = sign_extend32(val32, 31);
 		break;
 	default:
 			ret = -EINVAL;
@@ -623,9 +625,13 @@
 			*val2 = (st->chip_info->temp_scale % 1000) * 1000;
 			return IIO_VAL_INT_PLUS_MICRO;
 		case IIO_PRESSURE:
-			*val = 0;
-			*val2 = 4000; /* 40ubar = 0.004 kPa */
-			return IIO_VAL_INT_PLUS_MICRO;
+			/*
+			 * max scale is 1310 mbar
+			 * max raw value is 32767 shifted for 32bits
+			 */
+			*val = 131; /* 1310mbar = 131 kPa */
+			*val2 = 32767 << 16;
+			return IIO_VAL_FRACTIONAL;
 		default:
 			return -EINVAL;
 		}
@@ -786,13 +792,14 @@
 		.channels = adis16485_channels,
 		.num_channels = ARRAY_SIZE(adis16485_channels),
 		/*
-		 * storing the value in rad/degree and the scale in degree
-		 * gives us the result in rad and better precession than
-		 * storing the scale directly in rad.
+		 * Typically we do IIO_RAD_TO_DEGREE in the denominator, which
+		 * is exactly the same as IIO_DEGREE_TO_RAD in numerator, since
+		 * it gives better approximation. However, in this case we
+		 * cannot do it since it would not fit in a 32bit variable.
 		 */
-		.gyro_max_val = IIO_RAD_TO_DEGREE(22887),
-		.gyro_max_scale = 300,
-		.accel_max_val = IIO_M_S_2_TO_G(21973),
+		.gyro_max_val = 22887 << 16,
+		.gyro_max_scale = IIO_DEGREE_TO_RAD(300),
+		.accel_max_val = IIO_M_S_2_TO_G(21973 << 16),
 		.accel_max_scale = 18,
 		.temp_scale = 5650, /* 5.65 milli degree Celsius */
 		.int_clk = 2460000,
@@ -802,9 +809,9 @@
 	[ADIS16480] = {
 		.channels = adis16480_channels,
 		.num_channels = ARRAY_SIZE(adis16480_channels),
-		.gyro_max_val = IIO_RAD_TO_DEGREE(22500),
-		.gyro_max_scale = 450,
-		.accel_max_val = IIO_M_S_2_TO_G(12500),
+		.gyro_max_val = 22500 << 16,
+		.gyro_max_scale = IIO_DEGREE_TO_RAD(450),
+		.accel_max_val = IIO_M_S_2_TO_G(12500 << 16),
 		.accel_max_scale = 10,
 		.temp_scale = 5650, /* 5.65 milli degree Celsius */
 		.int_clk = 2460000,
@@ -814,9 +821,9 @@
 	[ADIS16485] = {
 		.channels = adis16485_channels,
 		.num_channels = ARRAY_SIZE(adis16485_channels),
-		.gyro_max_val = IIO_RAD_TO_DEGREE(22500),
-		.gyro_max_scale = 450,
-		.accel_max_val = IIO_M_S_2_TO_G(20000),
+		.gyro_max_val = 22500 << 16,
+		.gyro_max_scale = IIO_DEGREE_TO_RAD(450),
+		.accel_max_val = IIO_M_S_2_TO_G(20000 << 16),
 		.accel_max_scale = 5,
 		.temp_scale = 5650, /* 5.65 milli degree Celsius */
 		.int_clk = 2460000,
@@ -826,9 +833,9 @@
 	[ADIS16488] = {
 		.channels = adis16480_channels,
 		.num_channels = ARRAY_SIZE(adis16480_channels),
-		.gyro_max_val = IIO_RAD_TO_DEGREE(22500),
-		.gyro_max_scale = 450,
-		.accel_max_val = IIO_M_S_2_TO_G(22500),
+		.gyro_max_val = 22500 << 16,
+		.gyro_max_scale = IIO_DEGREE_TO_RAD(450),
+		.accel_max_val = IIO_M_S_2_TO_G(22500 << 16),
 		.accel_max_scale = 18,
 		.temp_scale = 5650, /* 5.65 milli degree Celsius */
 		.int_clk = 2460000,
@@ -838,9 +845,9 @@
 	[ADIS16495_1] = {
 		.channels = adis16485_channels,
 		.num_channels = ARRAY_SIZE(adis16485_channels),
-		.gyro_max_val = IIO_RAD_TO_DEGREE(20000),
-		.gyro_max_scale = 125,
-		.accel_max_val = IIO_M_S_2_TO_G(32000),
+		.gyro_max_val = 20000 << 16,
+		.gyro_max_scale = IIO_DEGREE_TO_RAD(125),
+		.accel_max_val = IIO_M_S_2_TO_G(32000 << 16),
 		.accel_max_scale = 8,
 		.temp_scale = 12500, /* 12.5 milli degree Celsius */
 		.int_clk = 4250000,
@@ -851,9 +858,9 @@
 	[ADIS16495_2] = {
 		.channels = adis16485_channels,
 		.num_channels = ARRAY_SIZE(adis16485_channels),
-		.gyro_max_val = IIO_RAD_TO_DEGREE(18000),
-		.gyro_max_scale = 450,
-		.accel_max_val = IIO_M_S_2_TO_G(32000),
+		.gyro_max_val = 18000 << 16,
+		.gyro_max_scale = IIO_DEGREE_TO_RAD(450),
+		.accel_max_val = IIO_M_S_2_TO_G(32000 << 16),
 		.accel_max_scale = 8,
 		.temp_scale = 12500, /* 12.5 milli degree Celsius */
 		.int_clk = 4250000,
@@ -864,9 +871,9 @@
 	[ADIS16495_3] = {
 		.channels = adis16485_channels,
 		.num_channels = ARRAY_SIZE(adis16485_channels),
-		.gyro_max_val = IIO_RAD_TO_DEGREE(20000),
-		.gyro_max_scale = 2000,
-		.accel_max_val = IIO_M_S_2_TO_G(32000),
+		.gyro_max_val = 20000 << 16,
+		.gyro_max_scale = IIO_DEGREE_TO_RAD(2000),
+		.accel_max_val = IIO_M_S_2_TO_G(32000 << 16),
 		.accel_max_scale = 8,
 		.temp_scale = 12500, /* 12.5 milli degree Celsius */
 		.int_clk = 4250000,
@@ -877,9 +884,9 @@
 	[ADIS16497_1] = {
 		.channels = adis16485_channels,
 		.num_channels = ARRAY_SIZE(adis16485_channels),
-		.gyro_max_val = IIO_RAD_TO_DEGREE(20000),
-		.gyro_max_scale = 125,
-		.accel_max_val = IIO_M_S_2_TO_G(32000),
+		.gyro_max_val = 20000 << 16,
+		.gyro_max_scale = IIO_DEGREE_TO_RAD(125),
+		.accel_max_val = IIO_M_S_2_TO_G(32000 << 16),
 		.accel_max_scale = 40,
 		.temp_scale = 12500, /* 12.5 milli degree Celsius */
 		.int_clk = 4250000,
@@ -890,9 +897,9 @@
 	[ADIS16497_2] = {
 		.channels = adis16485_channels,
 		.num_channels = ARRAY_SIZE(adis16485_channels),
-		.gyro_max_val = IIO_RAD_TO_DEGREE(18000),
-		.gyro_max_scale = 450,
-		.accel_max_val = IIO_M_S_2_TO_G(32000),
+		.gyro_max_val = 18000 << 16,
+		.gyro_max_scale = IIO_DEGREE_TO_RAD(450),
+		.accel_max_val = IIO_M_S_2_TO_G(32000 << 16),
 		.accel_max_scale = 40,
 		.temp_scale = 12500, /* 12.5 milli degree Celsius */
 		.int_clk = 4250000,
@@ -903,9 +910,9 @@
 	[ADIS16497_3] = {
 		.channels = adis16485_channels,
 		.num_channels = ARRAY_SIZE(adis16485_channels),
-		.gyro_max_val = IIO_RAD_TO_DEGREE(20000),
-		.gyro_max_scale = 2000,
-		.accel_max_val = IIO_M_S_2_TO_G(32000),
+		.gyro_max_val = 20000 << 16,
+		.gyro_max_scale = IIO_DEGREE_TO_RAD(2000),
+		.accel_max_val = IIO_M_S_2_TO_G(32000 << 16),
 		.accel_max_scale = 40,
 		.temp_scale = 12500, /* 12.5 milli degree Celsius */
 		.int_clk = 4250000,
@@ -919,6 +926,7 @@
 	.read_raw = &adis16480_read_raw,
 	.write_raw = &adis16480_write_raw,
 	.update_scan_mode = adis_update_scan_mode,
+	.debugfs_reg_access = adis_debugfs_reg_access,
 };
 
 static int adis16480_stop_device(struct iio_dev *indio_dev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/imu/adis_buffer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/imu/adis_buffer.c
@@ -125,9 +125,6 @@
 	struct adis *adis = iio_device_get_drvdata(indio_dev);
 	int ret;
 
-	if (!adis->buffer)
-		return -ENOMEM;
-
 	if (adis->data->has_paging) {
 		mutex_lock(&adis->txrx_lock);
 		if (adis->current_page != 0) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/imu/bmi160/bmi160.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/imu/bmi160/bmi160.h
@@ -7,6 +7,13 @@
 struct bmi160_data {
 	struct regmap *regmap;
 	struct iio_trigger *trig;
+	/*
+	 * Ensure natural alignment for timestamp if present.
+	 * Max length needed: 2 * 3 channels + 4 bytes padding + 8 byte ts.
+	 * If fewer channels are enabled, less space may be needed, as
+	 * long as the timestamp is still aligned to 8 bytes.
+	 */
+	__le16 buf[12] __aligned(8);
 };
 
 extern const struct regmap_config bmi160_regmap_config;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/imu/bmi160/bmi160_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/imu/bmi160/bmi160_core.c
@@ -411,8 +411,6 @@
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct bmi160_data *data = iio_priv(indio_dev);
-	__le16 buf[16];
-	/* 3 sens x 3 axis x __le16 + 3 x __le16 pad + 4 x __le16 tstamp */
 	int i, ret, j = 0, base = BMI160_REG_DATA_MAGN_XOUT_L;
 	__le16 sample;
 
@@ -422,10 +420,10 @@
 				       &sample, sizeof(sample));
 		if (ret)
 			goto done;
-		buf[j++] = sample;
+		data->buf[j++] = sample;
 	}
 
-	iio_push_to_buffers_with_timestamp(indio_dev, buf, pf->timestamp);
+	iio_push_to_buffers_with_timestamp(indio_dev, data->buf, pf->timestamp);
 done:
 	iio_trigger_notify_done(indio_dev->trig);
 	return IRQ_HANDLED;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -115,6 +115,7 @@
 		.reg = &reg_set_6050,
 		.config = &chip_config_6050,
 		.fifo_size = 1024,
+		.temp = {INV_MPU6050_TEMP_OFFSET, INV_MPU6050_TEMP_SCALE},
 	},
 	{
 		.whoami = INV_MPU6500_WHOAMI_VALUE,
@@ -122,6 +123,7 @@
 		.reg = &reg_set_6500,
 		.config = &chip_config_6050,
 		.fifo_size = 512,
+		.temp = {INV_MPU6500_TEMP_OFFSET, INV_MPU6500_TEMP_SCALE},
 	},
 	{
 		.whoami = INV_MPU6515_WHOAMI_VALUE,
@@ -129,6 +131,7 @@
 		.reg = &reg_set_6500,
 		.config = &chip_config_6050,
 		.fifo_size = 512,
+		.temp = {INV_MPU6500_TEMP_OFFSET, INV_MPU6500_TEMP_SCALE},
 	},
 	{
 		.whoami = INV_MPU6000_WHOAMI_VALUE,
@@ -136,6 +139,7 @@
 		.reg = &reg_set_6050,
 		.config = &chip_config_6050,
 		.fifo_size = 1024,
+		.temp = {INV_MPU6050_TEMP_OFFSET, INV_MPU6050_TEMP_SCALE},
 	},
 	{
 		.whoami = INV_MPU9150_WHOAMI_VALUE,
@@ -143,6 +147,7 @@
 		.reg = &reg_set_6050,
 		.config = &chip_config_6050,
 		.fifo_size = 1024,
+		.temp = {INV_MPU6050_TEMP_OFFSET, INV_MPU6050_TEMP_SCALE},
 	},
 	{
 		.whoami = INV_MPU9250_WHOAMI_VALUE,
@@ -150,6 +155,7 @@
 		.reg = &reg_set_6500,
 		.config = &chip_config_6050,
 		.fifo_size = 512,
+		.temp = {INV_MPU6500_TEMP_OFFSET, INV_MPU6500_TEMP_SCALE},
 	},
 	{
 		.whoami = INV_MPU9255_WHOAMI_VALUE,
@@ -157,6 +163,7 @@
 		.reg = &reg_set_6500,
 		.config = &chip_config_6050,
 		.fifo_size = 512,
+		.temp = {INV_MPU6500_TEMP_OFFSET, INV_MPU6500_TEMP_SCALE},
 	},
 	{
 		.whoami = INV_ICM20608_WHOAMI_VALUE,
@@ -164,6 +171,7 @@
 		.reg = &reg_set_6500,
 		.config = &chip_config_6050,
 		.fifo_size = 512,
+		.temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE},
 	},
 	{
 		.whoami = INV_ICM20602_WHOAMI_VALUE,
@@ -171,6 +179,7 @@
 		.reg = &reg_set_icm20602,
 		.config = &chip_config_6050,
 		.fifo_size = 1008,
+		.temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE},
 	},
 };
 
@@ -471,12 +480,8 @@
 
 			return IIO_VAL_INT_PLUS_MICRO;
 		case IIO_TEMP:
-			*val = 0;
-			if (st->chip_type == INV_ICM20602)
-				*val2 = INV_ICM20602_TEMP_SCALE;
-			else
-				*val2 = INV_MPU6050_TEMP_SCALE;
-
+			*val = st->hw->temp.scale / 1000000;
+			*val2 = st->hw->temp.scale % 1000000;
 			return IIO_VAL_INT_PLUS_MICRO;
 		default:
 			return -EINVAL;
@@ -484,11 +489,7 @@
 	case IIO_CHAN_INFO_OFFSET:
 		switch (chan->type) {
 		case IIO_TEMP:
-			if (st->chip_type == INV_ICM20602)
-				*val = INV_ICM20602_TEMP_OFFSET;
-			else
-				*val = INV_MPU6050_TEMP_OFFSET;
-
+			*val = st->hw->temp.offset;
 			return IIO_VAL_INT;
 		default:
 			return -EINVAL;
@@ -500,13 +501,13 @@
 			ret = inv_mpu6050_sensor_show(st, st->reg->gyro_offset,
 						chan->channel2, val);
 			mutex_unlock(&st->lock);
-			return IIO_VAL_INT;
+			return ret;
 		case IIO_ACCEL:
 			mutex_lock(&st->lock);
 			ret = inv_mpu6050_sensor_show(st, st->reg->accl_offset,
 						chan->channel2, val);
 			mutex_unlock(&st->lock);
-			return IIO_VAL_INT;
+			return ret;
 
 		default:
 			return -EINVAL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
@@ -101,6 +101,7 @@
  *  @reg:   register map of the chip.
  *  @config:    configuration of the chip.
  *  @fifo_size:	size of the FIFO in bytes.
+ *  @temp:	offset and scale to apply to raw temperature.
  */
 struct inv_mpu6050_hw {
 	u8 whoami;
@@ -108,6 +109,10 @@
 	const struct inv_mpu6050_reg_map *reg;
 	const struct inv_mpu6050_chip_config *config;
 	size_t fifo_size;
+	struct {
+		int offset;
+		int scale;
+	} temp;
 };
 
 /*
@@ -218,16 +223,19 @@
 #define INV_MPU6050_REG_UP_TIME_MIN          5000
 #define INV_MPU6050_REG_UP_TIME_MAX          10000
 
-#define INV_MPU6050_TEMP_OFFSET	             12421
-#define INV_MPU6050_TEMP_SCALE               2941
+#define INV_MPU6050_TEMP_OFFSET	             12420
+#define INV_MPU6050_TEMP_SCALE               2941176
 #define INV_MPU6050_MAX_GYRO_FS_PARAM        3
 #define INV_MPU6050_MAX_ACCL_FS_PARAM        3
 #define INV_MPU6050_THREE_AXIS               3
 #define INV_MPU6050_GYRO_CONFIG_FSR_SHIFT    3
 #define INV_MPU6050_ACCL_CONFIG_FSR_SHIFT    3
 
-#define INV_ICM20602_TEMP_OFFSET	     8170
-#define INV_ICM20602_TEMP_SCALE		     3060
+#define INV_MPU6500_TEMP_OFFSET              7011
+#define INV_MPU6500_TEMP_SCALE               2995178
+
+#define INV_ICM20608_TEMP_OFFSET	     8170
+#define INV_ICM20608_TEMP_SCALE		     3059976
 
 /* 6 + 6 round up and plus 8 */
 #define INV_MPU6050_OUTPUT_DATA_SIZE         24
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/imu/kmx61.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/imu/kmx61.c
@@ -1198,7 +1198,7 @@
 	struct kmx61_data *data = kmx61_get_data(indio_dev);
 	int bit, ret, i = 0;
 	u8 base;
-	s16 buffer[8];
+	s16 buffer[8] = { };
 
 	if (indio_dev == data->acc_indio_dev)
 		base = KMX61_ACC_XOUT_L;
@@ -1393,7 +1393,7 @@
 	ret = iio_device_register(data->acc_indio_dev);
 	if (ret < 0) {
 		dev_err(&client->dev, "Failed to register acc iio device\n");
-		goto err_buffer_cleanup_mag;
+		goto err_pm_cleanup;
 	}
 
 	ret = iio_device_register(data->mag_indio_dev);
@@ -1406,6 +1406,9 @@
 
 err_iio_unregister_acc:
 	iio_device_unregister(data->acc_indio_dev);
+err_pm_cleanup:
+	pm_runtime_dont_use_autosuspend(&client->dev);
+	pm_runtime_disable(&client->dev);
 err_buffer_cleanup_mag:
 	if (client->irq > 0)
 		iio_triggered_buffer_cleanup(data->mag_indio_dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
@@ -664,13 +664,29 @@
 static irqreturn_t st_lsm6dsx_handler_thread(int irq, void *private)
 {
 	struct st_lsm6dsx_hw *hw = private;
-	int count;
+	int fifo_len = 0, len;
 
-	mutex_lock(&hw->fifo_lock);
-	count = hw->settings->fifo_ops.read_fifo(hw);
-	mutex_unlock(&hw->fifo_lock);
+	/*
+	 * If we are using edge IRQs, new samples can arrive while
+	 * processing current interrupt since there are no hw
+	 * guarantees the irq line stays "low" long enough to properly
+	 * detect the new interrupt. In this case the new sample will
+	 * be missed.
+	 * Polling FIFO status register allow us to read new
+	 * samples even if the interrupt arrives while processing
+	 * previous data and the timeslot where the line is "low" is
+	 * too short to be properly detected.
+	 */
+	do {
+		mutex_lock(&hw->fifo_lock);
+		len = hw->settings->fifo_ops.read_fifo(hw);
+		mutex_unlock(&hw->fifo_lock);
 
-	return count ? IRQ_HANDLED : IRQ_NONE;
+		if (len > 0)
+			fifo_len += len;
+	} while (len > 0);
+
+	return fifo_len ? IRQ_HANDLED : IRQ_NONE;
 }
 
 static int st_lsm6dsx_buffer_preenable(struct iio_dev *iio_dev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
@@ -152,9 +152,10 @@
 					.addr = 0x10,
 					.mask = GENMASK(4, 3),
 				},
-				.fs_avl[0] = {  IIO_DEGREE_TO_RAD(245), 0x0 },
-				.fs_avl[1] = {  IIO_DEGREE_TO_RAD(500), 0x1 },
-				.fs_avl[2] = { IIO_DEGREE_TO_RAD(2000), 0x3 },
+
+				.fs_avl[0] = {  IIO_DEGREE_TO_RAD(8750), 0x0 },
+				.fs_avl[1] = { IIO_DEGREE_TO_RAD(17500), 0x1 },
+				.fs_avl[2] = { IIO_DEGREE_TO_RAD(70000), 0x3 },
 				.fs_len = 3,
 			},
 		},
@@ -910,7 +911,8 @@
 
 	for (i = 0; i < ARRAY_SIZE(st_lsm6dsx_sensor_settings); i++) {
 		for (j = 0; j < ST_LSM6DSX_MAX_ID; j++) {
-			if (id == st_lsm6dsx_sensor_settings[i].id[j].hw_id)
+			if (st_lsm6dsx_sensor_settings[i].id[j].name &&
+			    id == st_lsm6dsx_sensor_settings[i].id[j].hw_id)
 				break;
 		}
 		if (j < ST_LSM6DSX_MAX_ID)
@@ -985,8 +987,7 @@
 		return -EINVAL;
 
 	*val = odr_table->odr_avl[i].val;
-
-	return 0;
+	return odr_table->odr_avl[i].hz;
 }
 
 static u16 st_lsm6dsx_check_odr_dependency(struct st_lsm6dsx_hw *hw, u16 odr,
@@ -1014,6 +1015,8 @@
 	int err;
 
 	switch (sensor->id) {
+	case ST_LSM6DSX_ID_GYRO:
+		break;
 	case ST_LSM6DSX_ID_EXT0:
 	case ST_LSM6DSX_ID_EXT1:
 	case ST_LSM6DSX_ID_EXT2:
@@ -1039,8 +1042,8 @@
 		}
 		break;
 	}
-	default:
-		break;
+	default: /* should never occur */
+		return -EINVAL;
 	}
 
 	if (req_odr > 0) {
@@ -1149,8 +1152,10 @@
 	case IIO_CHAN_INFO_SAMP_FREQ: {
 		u8 data;
 
-		err = st_lsm6dsx_check_odr(sensor, val, &data);
-		if (!err)
+		val = st_lsm6dsx_check_odr(sensor, val, &data);
+		if (val < 0)
+			err = val;
+		else
 			sensor->odr = val;
 		break;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/industrialio-buffer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/industrialio-buffer.c
@@ -566,7 +566,7 @@
 				const unsigned long *mask, bool timestamp)
 {
 	unsigned bytes = 0;
-	int length, i;
+	int length, i, largest = 0;
 
 	/* How much space will the demuxed element take? */
 	for_each_set_bit(i, mask,
@@ -574,13 +574,17 @@
 		length = iio_storage_bytes_for_si(indio_dev, i);
 		bytes = ALIGN(bytes, length);
 		bytes += length;
+		largest = max(largest, length);
 	}
 
 	if (timestamp) {
 		length = iio_storage_bytes_for_timestamp(indio_dev);
 		bytes = ALIGN(bytes, length);
 		bytes += length;
+		largest = max(largest, length);
 	}
+
+	bytes = ALIGN(bytes, largest);
 	return bytes;
 }
 
@@ -841,12 +845,12 @@
 				       indio_dev->masklength,
 				       in_ind + 1);
 		while (in_ind != out_ind) {
-			in_ind = find_next_bit(indio_dev->active_scan_mask,
-					       indio_dev->masklength,
-					       in_ind + 1);
 			length = iio_storage_bytes_for_si(indio_dev, in_ind);
 			/* Make sure we are aligned */
 			in_loc = roundup(in_loc, length) + length;
+			in_ind = find_next_bit(indio_dev->active_scan_mask,
+					       indio_dev->masklength,
+					       in_ind + 1);
 		}
 		length = iio_storage_bytes_for_si(indio_dev, in_ind);
 		out_loc = roundup(out_loc, length);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/industrialio-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/industrialio-core.c
@@ -130,6 +130,8 @@
 	[IIO_MOD_PM2P5] = "pm2p5",
 	[IIO_MOD_PM4] = "pm4",
 	[IIO_MOD_PM10] = "pm10",
+	[IIO_MOD_ETHANOL] = "ethanol",
+	[IIO_MOD_H2] = "h2",
 };
 
 /* relies on pairs of these shared then separate */
@@ -554,6 +556,7 @@
 {
 	unsigned long long tmp;
 	int tmp0, tmp1;
+	s64 tmp2;
 	bool scale_db = false;
 
 	switch (type) {
@@ -576,10 +579,13 @@
 		else
 			return snprintf(buf, len, "%d.%09u", vals[0], vals[1]);
 	case IIO_VAL_FRACTIONAL:
-		tmp = div_s64((s64)vals[0] * 1000000000LL, vals[1]);
+		tmp2 = div_s64((s64)vals[0] * 1000000000LL, vals[1]);
 		tmp1 = vals[1];
-		tmp0 = (int)div_s64_rem(tmp, 1000000000, &tmp1);
-		return snprintf(buf, len, "%d.%09u", tmp0, abs(tmp1));
+		tmp0 = (int)div_s64_rem(tmp2, 1000000000, &tmp1);
+		if ((tmp2 < 0) && (tmp0 == 0))
+			return snprintf(buf, len, "-%d.%09u", tmp0, abs(tmp1));
+		else
+			return snprintf(buf, len, "%d.%09u", tmp0, abs(tmp1));
 	case IIO_VAL_FRACTIONAL_LOG2:
 		tmp = shift_right((s64)vals[0] * 1000000000LL, vals[1]);
 		tmp0 = (int)div_s64_rem(tmp, 1000000000LL, &tmp1);
@@ -1238,6 +1244,16 @@
 
 static DEVICE_ATTR(name, S_IRUGO, iio_show_dev_name, NULL);
 
+static ssize_t iio_show_dev_label(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	return snprintf(buf, PAGE_SIZE, "%s\n", indio_dev->label);
+}
+
+static DEVICE_ATTR(label, S_IRUGO, iio_show_dev_label, NULL);
+
 static ssize_t iio_show_timestamp_clock(struct device *dev,
 					struct device_attribute *attr,
 					char *buf)
@@ -1354,6 +1370,8 @@
 
 	if (indio_dev->name)
 		attrcount++;
+	if (indio_dev->label)
+		attrcount++;
 	if (clk)
 		attrcount++;
 
@@ -1376,6 +1394,8 @@
 		indio_dev->chan_attr_group.attrs[attrn++] = &p->dev_attr.attr;
 	if (indio_dev->name)
 		indio_dev->chan_attr_group.attrs[attrn++] = &dev_attr_name.attr;
+	if (indio_dev->label)
+		indio_dev->chan_attr_group.attrs[attrn++] = &dev_attr_label.attr;
 	if (clk)
 		indio_dev->chan_attr_group.attrs[attrn++] = clk;
 
@@ -1647,6 +1667,9 @@
 	if (!indio_dev->dev.of_node && indio_dev->dev.parent)
 		indio_dev->dev.of_node = indio_dev->dev.parent->of_node;
 
+	indio_dev->label = of_get_property(indio_dev->dev.of_node, "label",
+					   NULL);
+
 	ret = iio_check_unique_scan_index(indio_dev);
 	if (ret < 0)
 		return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/industrialio-sw-trigger.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/industrialio-sw-trigger.c
@@ -58,8 +58,12 @@
 
 	t->group = configfs_register_default_group(iio_triggers_group, t->name,
 						&iio_trigger_type_group_type);
-	if (IS_ERR(t->group))
+	if (IS_ERR(t->group)) {
+		mutex_lock(&iio_trigger_types_lock);
+		list_del(&t->list);
+		mutex_unlock(&iio_trigger_types_lock);
 		ret = PTR_ERR(t->group);
+	}
 
 	return ret;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/industrialio-trigger.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/industrialio-trigger.c
@@ -549,7 +549,6 @@
 		irq_modify_status(trig->subirq_base + i,
 				  IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE);
 	}
-	get_device(&trig->dev);
 
 	return trig;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/inkern.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/inkern.c
@@ -136,9 +136,10 @@
 
 	idev = bus_find_device(&iio_bus_type, NULL, iiospec.np,
 			       iio_dev_node_match);
-	of_node_put(iiospec.np);
-	if (idev == NULL)
+	if (idev == NULL) {
+		of_node_put(iiospec.np);
 		return -EPROBE_DEFER;
+	}
 
 	indio_dev = dev_to_iio_dev(idev);
 	channel->indio_dev = indio_dev;
@@ -146,6 +147,7 @@
 		index = indio_dev->info->of_xlate(indio_dev, &iiospec);
 	else
 		index = __of_iio_simple_xlate(indio_dev, &iiospec);
+	of_node_put(iiospec.np);
 	if (index < 0)
 		goto err_put;
 	channel->channel = &indio_dev->channels[index];
@@ -464,7 +466,7 @@
 	return chans;
 
 error_free_chans:
-	for (i = 0; i < nummaps; i++)
+	for (i = 0; i < mapind; i++)
 		iio_device_put(chans[i].indio_dev);
 	kfree(chans);
 error_ret:
@@ -588,42 +590,64 @@
 static int iio_convert_raw_to_processed_unlocked(struct iio_channel *chan,
 	int raw, int *processed, unsigned int scale)
 {
-	int scale_type, scale_val, scale_val2, offset;
+	int scale_type, scale_val, scale_val2;
+	int offset_type, offset_val, offset_val2;
 	s64 raw64 = raw;
-	int ret;
 
-	ret = iio_channel_read(chan, &offset, NULL, IIO_CHAN_INFO_OFFSET);
-	if (ret >= 0)
-		raw64 += offset;
+	offset_type = iio_channel_read(chan, &offset_val, &offset_val2,
+				       IIO_CHAN_INFO_OFFSET);
+	if (offset_type >= 0) {
+		switch (offset_type) {
+		case IIO_VAL_INT:
+			break;
+		case IIO_VAL_INT_PLUS_MICRO:
+		case IIO_VAL_INT_PLUS_NANO:
+			/*
+			 * Both IIO_VAL_INT_PLUS_MICRO and IIO_VAL_INT_PLUS_NANO
+			 * implicitely truncate the offset to it's integer form.
+			 */
+			break;
+		case IIO_VAL_FRACTIONAL:
+			offset_val /= offset_val2;
+			break;
+		case IIO_VAL_FRACTIONAL_LOG2:
+			offset_val >>= offset_val2;
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		raw64 += offset_val;
+	}
 
 	scale_type = iio_channel_read(chan, &scale_val, &scale_val2,
 					IIO_CHAN_INFO_SCALE);
 	if (scale_type < 0) {
 		/*
-		 * Just pass raw values as processed if no scaling is
-		 * available.
+		 * If no channel scaling is available apply consumer scale to
+		 * raw value and return.
 		 */
-		*processed = raw;
+		*processed = raw * scale;
 		return 0;
 	}
 
 	switch (scale_type) {
 	case IIO_VAL_INT:
-		*processed = raw64 * scale_val;
+		*processed = raw64 * scale_val * scale;
 		break;
 	case IIO_VAL_INT_PLUS_MICRO:
 		if (scale_val2 < 0)
-			*processed = -raw64 * scale_val;
+			*processed = -raw64 * scale_val * scale;
 		else
-			*processed = raw64 * scale_val;
+			*processed = raw64 * scale_val * scale;
 		*processed += div_s64(raw64 * (s64)scale_val2 * scale,
 				      1000000LL);
 		break;
 	case IIO_VAL_INT_PLUS_NANO:
 		if (scale_val2 < 0)
-			*processed = -raw64 * scale_val;
+			*processed = -raw64 * scale_val * scale;
 		else
-			*processed = raw64 * scale_val;
+			*processed = raw64 * scale_val * scale;
 		*processed += div_s64(raw64 * (s64)scale_val2 * scale,
 				      1000000000LL);
 		break;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/light/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/light/Kconfig
@@ -239,6 +239,8 @@
 	tristate "ROHM RPR0521 ALS and proximity sensor driver"
 	depends on I2C
 	select REGMAP_I2C
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
 	help
 	  Say Y here if you want to build support for ROHM's RPR0521
 	  ambient light and proximity sensor device.
@@ -485,6 +487,7 @@
 
 config VCNL4035
 	tristate "VCNL4035 combined ALS and proximity sensor"
+	select IIO_BUFFER
 	select IIO_TRIGGERED_BUFFER
 	select REGMAP_I2C
 	depends on I2C
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/light/apds9960.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/light/apds9960.c
@@ -55,9 +55,6 @@
 #define APDS9960_REG_CONTROL_PGAIN_MASK_SHIFT	2
 
 #define APDS9960_REG_CONFIG_2	0x90
-#define APDS9960_REG_CONFIG_2_GGAIN_MASK	0x60
-#define APDS9960_REG_CONFIG_2_GGAIN_MASK_SHIFT	5
-
 #define APDS9960_REG_ID		0x92
 
 #define APDS9960_REG_STATUS	0x93
@@ -78,6 +75,9 @@
 #define APDS9960_REG_GCONF_1_GFIFO_THRES_MASK_SHIFT	6
 
 #define APDS9960_REG_GCONF_2	0xa3
+#define APDS9960_REG_GCONF_2_GGAIN_MASK			0x60
+#define APDS9960_REG_GCONF_2_GGAIN_MASK_SHIFT		5
+
 #define APDS9960_REG_GOFFSET_U	0xa4
 #define APDS9960_REG_GOFFSET_D	0xa5
 #define APDS9960_REG_GPULSE	0xa6
@@ -397,9 +397,9 @@
 			}
 
 			ret = regmap_update_bits(data->regmap,
-				APDS9960_REG_CONFIG_2,
-				APDS9960_REG_CONFIG_2_GGAIN_MASK,
-				idx << APDS9960_REG_CONFIG_2_GGAIN_MASK_SHIFT);
+				APDS9960_REG_GCONF_2,
+				APDS9960_REG_GCONF_2_GGAIN_MASK,
+				idx << APDS9960_REG_GCONF_2_GGAIN_MASK_SHIFT);
 			if (!ret)
 				data->pxs_gain = idx;
 			mutex_unlock(&data->lock);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/light/bh1750.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/light/bh1750.c
@@ -59,9 +59,9 @@
 
 	u16 int_time_low_mask;
 	u16 int_time_high_mask;
-}
+};
 
-static const bh1750_chip_info_tbl[] = {
+static const struct bh1750_chip_info bh1750_chip_info_tbl[] = {
 	[BH1710] = { 140, 1022, 300, 400,  250000000, 2, 0x001F, 0x03E0 },
 	[BH1721] = { 140, 1020, 300, 400,  250000000, 2, 0x0010, 0x03E0 },
 	[BH1750] = { 31,  254,  69,  1740, 57500000,  1, 0x001F, 0x00E0 },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/light/hid-sensor-prox.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/light/hid-sensor-prox.c
@@ -25,6 +25,9 @@
 	struct hid_sensor_common common_attributes;
 	struct hid_sensor_hub_attribute_info prox_attr;
 	u32 human_presence;
+	int scale_pre_decml;
+	int scale_post_decml;
+	int scale_precision;
 };
 
 /* Channel definitions */
@@ -95,8 +98,9 @@
 		ret_type = IIO_VAL_INT;
 		break;
 	case IIO_CHAN_INFO_SCALE:
-		*val = prox_state->prox_attr.units;
-		ret_type = IIO_VAL_INT;
+		*val = prox_state->scale_pre_decml;
+		*val2 = prox_state->scale_post_decml;
+		ret_type = prox_state->scale_precision;
 		break;
 	case IIO_CHAN_INFO_OFFSET:
 		*val = hid_sensor_convert_exponent(
@@ -236,6 +240,11 @@
 			HID_USAGE_SENSOR_HUMAN_PRESENCE,
 			&st->common_attributes.sensitivity);
 
+	st->scale_precision = hid_sensor_format_scale(
+				hsdev->usage,
+				&st->prox_attr,
+				&st->scale_pre_decml, &st->scale_post_decml);
+
 	return ret;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/light/isl29028.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/light/isl29028.c
@@ -628,7 +628,7 @@
 					 ISL29028_POWER_OFF_DELAY_MS);
 	pm_runtime_use_autosuspend(&client->dev);
 
-	ret = devm_iio_device_register(indio_dev->dev.parent, indio_dev);
+	ret = iio_device_register(indio_dev);
 	if (ret < 0) {
 		dev_err(&client->dev,
 			"%s(): iio registration failed with error %d\n",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/light/isl29125.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/light/isl29125.c
@@ -51,7 +51,11 @@
 struct isl29125_data {
 	struct i2c_client *client;
 	u8 conf1;
-	u16 buffer[8]; /* 3x 16-bit, padding, 8 bytes timestamp */
+	/* Ensure timestamp is naturally aligned */
+	struct {
+		u16 chans[3];
+		s64 timestamp __aligned(8);
+	} scan;
 };
 
 #define ISL29125_CHANNEL(_color, _si) { \
@@ -184,10 +188,10 @@
 		if (ret < 0)
 			goto done;
 
-		data->buffer[j++] = ret;
+		data->scan.chans[j++] = ret;
 	}
 
-	iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+	iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
 		iio_get_time_ns(indio_dev));
 
 done:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/light/ltr501.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/light/ltr501.c
@@ -32,9 +32,12 @@
 #define LTR501_PART_ID 0x86
 #define LTR501_MANUFAC_ID 0x87
 #define LTR501_ALS_DATA1 0x88 /* 16-bit, little endian */
+#define LTR501_ALS_DATA1_UPPER 0x89 /* upper 8 bits of LTR501_ALS_DATA1 */
 #define LTR501_ALS_DATA0 0x8a /* 16-bit, little endian */
+#define LTR501_ALS_DATA0_UPPER 0x8b /* upper 8 bits of LTR501_ALS_DATA0 */
 #define LTR501_ALS_PS_STATUS 0x8c
 #define LTR501_PS_DATA 0x8d /* 16-bit, little endian */
+#define LTR501_PS_DATA_UPPER 0x8e /* upper 8 bits of LTR501_PS_DATA */
 #define LTR501_INTR 0x8f /* output mode, polarity, mode */
 #define LTR501_PS_THRESH_UP 0x90 /* 11 bit, ps upper threshold */
 #define LTR501_PS_THRESH_LOW 0x92 /* 11 bit, ps lower threshold */
@@ -405,18 +408,19 @@
 
 static int ltr501_read_ps(struct ltr501_data *data)
 {
-	int ret, status;
+	__le16 status;
+	int ret;
 
 	ret = ltr501_drdy(data, LTR501_STATUS_PS_RDY);
 	if (ret < 0)
 		return ret;
 
 	ret = regmap_bulk_read(data->regmap, LTR501_PS_DATA,
-			       &status, 2);
+			       &status, sizeof(status));
 	if (ret < 0)
 		return ret;
 
-	return status;
+	return le16_to_cpu(status);
 }
 
 static int ltr501_read_intr_prst(struct ltr501_data *data,
@@ -1204,7 +1208,7 @@
 		.als_gain_tbl_size = ARRAY_SIZE(ltr559_als_gain_tbl),
 		.ps_gain = ltr559_ps_gain_tbl,
 		.ps_gain_tbl_size = ARRAY_SIZE(ltr559_ps_gain_tbl),
-		.als_mode_active = BIT(1),
+		.als_mode_active = BIT(0),
 		.als_gain_mask = BIT(2) | BIT(3) | BIT(4),
 		.als_gain_shift = 2,
 		.info = &ltr501_info,
@@ -1242,13 +1246,16 @@
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct ltr501_data *data = iio_priv(indio_dev);
-	u16 buf[8];
+	struct {
+		u16 channels[3];
+		s64 ts __aligned(8);
+	} scan;
 	__le16 als_buf[2];
 	u8 mask = 0;
 	int j = 0;
 	int ret, psdata;
 
-	memset(buf, 0, sizeof(buf));
+	memset(&scan, 0, sizeof(scan));
 
 	/* figure out which data needs to be ready */
 	if (test_bit(0, indio_dev->active_scan_mask) ||
@@ -1265,11 +1272,11 @@
 		ret = regmap_bulk_read(data->regmap, LTR501_ALS_DATA1,
 				       (u8 *)als_buf, sizeof(als_buf));
 		if (ret < 0)
-			return ret;
+			goto done;
 		if (test_bit(0, indio_dev->active_scan_mask))
-			buf[j++] = le16_to_cpu(als_buf[1]);
+			scan.channels[j++] = le16_to_cpu(als_buf[1]);
 		if (test_bit(1, indio_dev->active_scan_mask))
-			buf[j++] = le16_to_cpu(als_buf[0]);
+			scan.channels[j++] = le16_to_cpu(als_buf[0]);
 	}
 
 	if (mask & LTR501_STATUS_PS_RDY) {
@@ -1277,10 +1284,10 @@
 				       &psdata, 2);
 		if (ret < 0)
 			goto done;
-		buf[j++] = psdata & LTR501_PS_DATA_MASK;
+		scan.channels[j++] = psdata & LTR501_PS_DATA_MASK;
 	}
 
-	iio_push_to_buffers_with_timestamp(indio_dev, buf,
+	iio_push_to_buffers_with_timestamp(indio_dev, &scan,
 					   iio_get_time_ns(indio_dev));
 
 done:
@@ -1350,9 +1357,12 @@
 {
 	switch (reg) {
 	case LTR501_ALS_DATA1:
+	case LTR501_ALS_DATA1_UPPER:
 	case LTR501_ALS_DATA0:
+	case LTR501_ALS_DATA0_UPPER:
 	case LTR501_ALS_PS_STATUS:
 	case LTR501_PS_DATA:
+	case LTR501_PS_DATA_UPPER:
 		return true;
 	default:
 		return false;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/light/max44000.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/light/max44000.c
@@ -75,6 +75,11 @@
 struct max44000_data {
 	struct mutex lock;
 	struct regmap *regmap;
+	/* Ensure naturally aligned timestamp */
+	struct {
+		u16 channels[2];
+		s64 ts __aligned(8);
+	} scan;
 };
 
 /* Default scale is set to the minimum of 0.03125 or 1 / (1 << 5) lux */
@@ -488,7 +493,6 @@
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct max44000_data *data = iio_priv(indio_dev);
-	u16 buf[8]; /* 2x u16 + padding + 8 bytes timestamp */
 	int index = 0;
 	unsigned int regval;
 	int ret;
@@ -498,17 +502,17 @@
 		ret = max44000_read_alsval(data);
 		if (ret < 0)
 			goto out_unlock;
-		buf[index++] = ret;
+		data->scan.channels[index++] = ret;
 	}
 	if (test_bit(MAX44000_SCAN_INDEX_PRX, indio_dev->active_scan_mask)) {
 		ret = regmap_read(data->regmap, MAX44000_REG_PRX_DATA, &regval);
 		if (ret < 0)
 			goto out_unlock;
-		buf[index] = regval;
+		data->scan.channels[index] = regval;
 	}
 	mutex_unlock(&data->lock);
 
-	iio_push_to_buffers_with_timestamp(indio_dev, buf,
+	iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
 					   iio_get_time_ns(indio_dev));
 	iio_trigger_notify_done(indio_dev->trig);
 	return IRQ_HANDLED;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/light/max44009.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/light/max44009.c
@@ -529,6 +529,12 @@
 	return devm_iio_device_register(&client->dev, indio_dev);
 }
 
+static const struct of_device_id max44009_of_match[] = {
+	{ .compatible = "maxim,max44009" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, max44009_of_match);
+
 static const struct i2c_device_id max44009_id[] = {
 	{ "max44009", 0 },
 	{ }
@@ -538,18 +544,13 @@
 static struct i2c_driver max44009_driver = {
 	.driver = {
 		.name = MAX44009_DRV_NAME,
+		.of_match_table = max44009_of_match,
 	},
 	.probe = max44009_probe,
 	.id_table = max44009_id,
 };
 module_i2c_driver(max44009_driver);
 
-static const struct of_device_id max44009_of_match[] = {
-	{ .compatible = "maxim,max44009" },
-	{ }
-};
-MODULE_DEVICE_TABLE(of, max44009_of_match);
-
 MODULE_AUTHOR("Robert Eshleman <bobbyeshleman@gmail.com>");
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("MAX44009 ambient light sensor driver");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/light/opt3001.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/light/opt3001.c
@@ -138,6 +138,10 @@
 		.val2 = 400000,
 	},
 	{
+		.val = 41932,
+		.val2 = 800000,
+	},
+	{
 		.val = 83865,
 		.val2 = 600000,
 	},
@@ -275,6 +279,8 @@
 		ret = wait_event_timeout(opt->result_ready_queue,
 				opt->result_ready,
 				msecs_to_jiffies(OPT3001_RESULT_READY_LONG));
+		if (ret == 0)
+			return -ETIMEDOUT;
 	} else {
 		/* Sleep for result ready time */
 		timeout = (opt->int_time == OPT3001_INT_TIME_SHORT) ?
@@ -311,9 +317,7 @@
 		/* Disallow IRQ to access the device while lock is active */
 		opt->ok_to_ignore_lock = false;
 
-	if (ret == 0)
-		return -ETIMEDOUT;
-	else if (ret < 0)
+	if (ret < 0)
 		return ret;
 
 	if (opt->use_irq) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/light/rpr0521.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/light/rpr0521.c
@@ -194,6 +194,17 @@
 	bool pxs_need_dis;
 
 	struct regmap *regmap;
+
+	/*
+	 * Ensure correct naturally aligned timestamp.
+	 * Note that the read will put garbage data into
+	 * the padding but this should not be a problem
+	 */
+	struct {
+		__le16 channels[3];
+		u8 garbage;
+		s64 ts __aligned(8);
+	} scan;
 };
 
 static IIO_CONST_ATTR(in_intensity_scale_available, RPR0521_ALS_SCALE_AVAIL);
@@ -449,8 +460,6 @@
 	struct rpr0521_data *data = iio_priv(indio_dev);
 	int err;
 
-	u8 buffer[16]; /* 3 16-bit channels + padding + ts */
-
 	/* Use irq timestamp when reasonable. */
 	if (iio_trigger_using_own(indio_dev) && data->irq_timestamp) {
 		pf->timestamp = data->irq_timestamp;
@@ -461,11 +470,11 @@
 		pf->timestamp = iio_get_time_ns(indio_dev);
 
 	err = regmap_bulk_read(data->regmap, RPR0521_REG_PXS_DATA,
-		&buffer,
+		data->scan.channels,
 		(3 * 2) + 1);	/* 3 * 16-bit + (discarded) int clear reg. */
 	if (!err)
 		iio_push_to_buffers_with_timestamp(indio_dev,
-						   buffer, pf->timestamp);
+						   &data->scan, pf->timestamp);
 	else
 		dev_err(&data->client->dev,
 			"Trigger consumer can't read from sensor.\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/light/si1133.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/light/si1133.c
@@ -102,6 +102,9 @@
 #define SI1133_INPUT_FRACTION_LOW	15
 #define SI1133_LUX_OUTPUT_FRACTION	12
 #define SI1133_LUX_BUFFER_SIZE		9
+#define SI1133_MEASURE_BUFFER_SIZE	3
+
+#define SI1133_SIGN_BIT_INDEX 23
 
 static const int si1133_scale_available[] = {
 	1, 2, 4, 8, 16, 32, 64, 128};
@@ -234,13 +237,13 @@
 	}
 };
 
-static int si1133_calculate_polynomial_inner(u32 input, u8 fraction, u16 mag,
+static int si1133_calculate_polynomial_inner(s32 input, u8 fraction, u16 mag,
 					     s8 shift)
 {
 	return ((input << fraction) / mag) << shift;
 }
 
-static int si1133_calculate_output(u32 x, u32 y, u8 x_order, u8 y_order,
+static int si1133_calculate_output(s32 x, s32 y, u8 x_order, u8 y_order,
 				   u8 input_fraction, s8 sign,
 				   const struct si1133_coeff *coeffs)
 {
@@ -276,7 +279,7 @@
  * The algorithm is from:
  * https://siliconlabs.github.io/Gecko_SDK_Doc/efm32zg/html/si1133_8c_source.html#l00716
  */
-static int si1133_calc_polynomial(u32 x, u32 y, u8 input_fraction, u8 num_coeff,
+static int si1133_calc_polynomial(s32 x, s32 y, u8 input_fraction, u8 num_coeff,
 				  const struct si1133_coeff *coeffs)
 {
 	u8 x_order, y_order;
@@ -614,7 +617,7 @@
 {
 	int err;
 
-	__be16 resp;
+	u8 buffer[SI1133_MEASURE_BUFFER_SIZE];
 
 	err = si1133_set_adcmux(data, 0, chan->channel);
 	if (err)
@@ -625,12 +628,13 @@
 	if (err)
 		return err;
 
-	err = si1133_bulk_read(data, SI1133_REG_HOSTOUT(0), sizeof(resp),
-			       (u8 *)&resp);
+	err = si1133_bulk_read(data, SI1133_REG_HOSTOUT(0), sizeof(buffer),
+			       buffer);
 	if (err)
 		return err;
 
-	*val = be16_to_cpu(resp);
+	*val = sign_extend32((buffer[0] << 16) | (buffer[1] << 8) | buffer[2],
+			     SI1133_SIGN_BIT_INDEX);
 
 	return err;
 }
@@ -704,9 +708,9 @@
 {
 	int err;
 	int lux;
-	u32 high_vis;
-	u32 low_vis;
-	u32 ir;
+	s32 high_vis;
+	s32 low_vis;
+	s32 ir;
 	u8 buffer[SI1133_LUX_BUFFER_SIZE];
 
 	/* Activate lux channels */
@@ -719,9 +723,16 @@
 	if (err)
 		return err;
 
-	high_vis = (buffer[0] << 16) | (buffer[1] << 8) | buffer[2];
-	low_vis = (buffer[3] << 16) | (buffer[4] << 8) | buffer[5];
-	ir = (buffer[6] << 16) | (buffer[7] << 8) | buffer[8];
+	high_vis =
+		sign_extend32((buffer[0] << 16) | (buffer[1] << 8) | buffer[2],
+			      SI1133_SIGN_BIT_INDEX);
+
+	low_vis =
+		sign_extend32((buffer[3] << 16) | (buffer[4] << 8) | buffer[5],
+			      SI1133_SIGN_BIT_INDEX);
+
+	ir = sign_extend32((buffer[6] << 16) | (buffer[7] << 8) | buffer[8],
+			   SI1133_SIGN_BIT_INDEX);
 
 	if (high_vis > SI1133_ADC_THRESHOLD || ir > SI1133_ADC_THRESHOLD)
 		lux = si1133_calc_polynomial(high_vis, ir,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/light/si1145.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/light/si1145.c
@@ -169,6 +169,7 @@
  * @part_info:	Part information
  * @trig:	Pointer to iio trigger
  * @meas_rate:	Value of MEAS_RATE register. Only set in HW in auto mode
+ * @buffer:	Used to pack data read from sensor.
  */
 struct si1145_data {
 	struct i2c_client *client;
@@ -180,6 +181,14 @@
 	bool autonomous;
 	struct iio_trigger *trig;
 	int meas_rate;
+	/*
+	 * Ensure timestamp will be naturally aligned if present.
+	 * Maximum buffer size (may be only partly used if not all
+	 * channels are enabled):
+	 *   6*2 bytes channels data + 4 bytes alignment +
+	 *   8 bytes timestamp
+	 */
+	u8 buffer[24] __aligned(8);
 };
 
 /**
@@ -441,12 +450,6 @@
 	struct iio_poll_func *pf = private;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct si1145_data *data = iio_priv(indio_dev);
-	/*
-	 * Maximum buffer size:
-	 *   6*2 bytes channels data + 4 bytes alignment +
-	 *   8 bytes timestamp
-	 */
-	u8 buffer[24];
 	int i, j = 0;
 	int ret;
 	u8 irq_status = 0;
@@ -479,7 +482,7 @@
 
 		ret = i2c_smbus_read_i2c_block_data_or_emulated(
 				data->client, indio_dev->channels[i].address,
-				sizeof(u16) * run, &buffer[j]);
+				sizeof(u16) * run, &data->buffer[j]);
 		if (ret < 0)
 			goto done;
 		j += run * sizeof(u16);
@@ -494,7 +497,7 @@
 			goto done;
 	}
 
-	iio_push_to_buffers_with_timestamp(indio_dev, buffer,
+	iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
 		iio_get_time_ns(indio_dev));
 
 done:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/light/st_uvis25.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/light/st_uvis25.h
@@ -27,6 +27,11 @@
 	struct iio_trigger *trig;
 	bool enabled;
 	int irq;
+	/* Ensure timestamp is naturally aligned */
+	struct {
+		u8 chan;
+		s64 ts __aligned(8);
+	} scan;
 };
 
 extern const struct dev_pm_ops st_uvis25_pm_ops;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/light/st_uvis25_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/light/st_uvis25_core.c
@@ -234,17 +234,19 @@
 
 static irqreturn_t st_uvis25_buffer_handler_thread(int irq, void *p)
 {
-	u8 buffer[ALIGN(sizeof(u8), sizeof(s64)) + sizeof(s64)];
 	struct iio_poll_func *pf = p;
 	struct iio_dev *iio_dev = pf->indio_dev;
 	struct st_uvis25_hw *hw = iio_priv(iio_dev);
+	unsigned int val;
 	int err;
 
-	err = regmap_read(hw->regmap, ST_UVIS25_REG_OUT_ADDR, (int *)buffer);
+	err = regmap_read(hw->regmap, ST_UVIS25_REG_OUT_ADDR, &val);
 	if (err < 0)
 		goto out;
 
-	iio_push_to_buffers_with_timestamp(iio_dev, buffer,
+	hw->scan.chan = val;
+
+	iio_push_to_buffers_with_timestamp(iio_dev, &hw->scan,
 					   iio_get_time_ns(iio_dev));
 
 out:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/light/stk3310.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/light/stk3310.c
@@ -544,9 +544,8 @@
 	mutex_lock(&data->lock);
 	ret = regmap_field_read(data->reg_flag_nf, &dir);
 	if (ret < 0) {
-		dev_err(&data->client->dev, "register read failed\n");
-		mutex_unlock(&data->lock);
-		return ret;
+		dev_err(&data->client->dev, "register read failed: %d\n", ret);
+		goto out;
 	}
 	event = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 1,
 				     IIO_EV_TYPE_THRESH,
@@ -558,6 +557,7 @@
 	ret = regmap_field_write(data->reg_flag_psint, 0);
 	if (ret < 0)
 		dev_err(&data->client->dev, "failed to reset interrupts\n");
+out:
 	mutex_unlock(&data->lock);
 
 	return IRQ_HANDLED;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/light/tcs3414.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/light/tcs3414.c
@@ -53,7 +53,11 @@
 	u8 control;
 	u8 gain;
 	u8 timing;
-	u16 buffer[8]; /* 4x 16-bit + 8 bytes timestamp */
+	/* Ensure timestamp is naturally aligned */
+	struct {
+		u16 chans[4];
+		s64 timestamp __aligned(8);
+	} scan;
 };
 
 #define TCS3414_CHANNEL(_color, _si, _addr) { \
@@ -209,10 +213,10 @@
 		if (ret < 0)
 			goto done;
 
-		data->buffer[j++] = ret;
+		data->scan.chans[j++] = ret;
 	}
 
-	iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+	iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
 		iio_get_time_ns(indio_dev));
 
 done:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/light/tcs3472.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/light/tcs3472.c
@@ -64,7 +64,11 @@
 	u8 control;
 	u8 atime;
 	u8 apers;
-	u16 buffer[8]; /* 4 16-bit channels + 64-bit timestamp */
+	/* Ensure timestamp is naturally aligned */
+	struct {
+		u16 chans[4];
+		s64 timestamp __aligned(8);
+	} scan;
 };
 
 static const struct iio_event_spec tcs3472_events[] = {
@@ -386,10 +390,10 @@
 		if (ret < 0)
 			goto done;
 
-		data->buffer[j++] = ret;
+		data->scan.chans[j++] = ret;
 	}
 
-	iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+	iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
 		iio_get_time_ns(indio_dev));
 
 done:
@@ -532,7 +536,8 @@
 	return 0;
 
 free_irq:
-	free_irq(client->irq, indio_dev);
+	if (client->irq)
+		free_irq(client->irq, indio_dev);
 buffer_cleanup:
 	iio_triggered_buffer_cleanup(indio_dev);
 	return ret;
@@ -560,7 +565,8 @@
 	struct iio_dev *indio_dev = i2c_get_clientdata(client);
 
 	iio_device_unregister(indio_dev);
-	free_irq(client->irq, indio_dev);
+	if (client->irq)
+		free_irq(client->irq, indio_dev);
 	iio_triggered_buffer_cleanup(indio_dev);
 	tcs3472_powerdown(iio_priv(indio_dev));
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/light/tsl2583.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/light/tsl2583.c
@@ -341,6 +341,14 @@
 		return lux_val;
 	}
 
+	/* Avoid division by zero of lux_value later on */
+	if (lux_val == 0) {
+		dev_err(&chip->client->dev,
+			"%s: lux_val of 0 will produce out of range trim_value\n",
+			__func__);
+		return -ENODATA;
+	}
+
 	gain_trim_val = (unsigned int)(((chip->als_settings.als_cal_target)
 			* chip->als_settings.als_gain_trim) / lux_val);
 	if ((gain_trim_val < 250) || (gain_trim_val > 4000)) {
@@ -849,7 +857,7 @@
 					 TSL2583_POWER_OFF_DELAY_MS);
 	pm_runtime_use_autosuspend(&clientp->dev);
 
-	ret = devm_iio_device_register(indio_dev->dev.parent, indio_dev);
+	ret = iio_device_register(indio_dev);
 	if (ret) {
 		dev_err(&clientp->dev, "%s: iio registration failed\n",
 			__func__);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/light/tsl2772.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/light/tsl2772.c
@@ -606,6 +606,7 @@
 			return -EINVAL;
 		}
 	}
+	chip->settings.prox_diode = prox_diode_mask;
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/light/vcnl4000.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/light/vcnl4000.c
@@ -163,20 +163,22 @@
 	if (ret < 0)
 		return ret;
 
-	data->al_scale = 24000;
 	data->vcnl4200_al.reg = VCNL4200_AL_DATA;
 	data->vcnl4200_ps.reg = VCNL4200_PS_DATA;
 	switch (id) {
 	case VCNL4200_PROD_ID:
-		/* Integration time is 50ms, but the experiments */
-		/* show 54ms in total. */
-		data->vcnl4200_al.sampling_rate = ktime_set(0, 54000 * 1000);
-		data->vcnl4200_ps.sampling_rate = ktime_set(0, 4200 * 1000);
+		/* Default wait time is 50ms, add 20% tolerance. */
+		data->vcnl4200_al.sampling_rate = ktime_set(0, 60000 * 1000);
+		/* Default wait time is 4.8ms, add 20% tolerance. */
+		data->vcnl4200_ps.sampling_rate = ktime_set(0, 5760 * 1000);
+		data->al_scale = 24000;
 		break;
 	case VCNL4040_PROD_ID:
-		/* Integration time is 80ms, add 10ms. */
-		data->vcnl4200_al.sampling_rate = ktime_set(0, 100000 * 1000);
-		data->vcnl4200_ps.sampling_rate = ktime_set(0, 100000 * 1000);
+		/* Default wait time is 80ms, add 20% tolerance. */
+		data->vcnl4200_al.sampling_rate = ktime_set(0, 96000 * 1000);
+		/* Default wait time is 5ms, add 20% tolerance. */
+		data->vcnl4200_ps.sampling_rate = ktime_set(0, 6000 * 1000);
+		data->al_scale = 120000;
 		break;
 	}
 	data->vcnl4200_al.last_measurement = ktime_set(0, 0);
@@ -191,7 +193,6 @@
 				u8 rdy_mask, u8 data_reg, int *val)
 {
 	int tries = 20;
-	__be16 buf;
 	int ret;
 
 	mutex_lock(&data->vcnl4000_lock);
@@ -218,13 +219,12 @@
 		goto fail;
 	}
 
-	ret = i2c_smbus_read_i2c_block_data(data->client,
-		data_reg, sizeof(buf), (u8 *) &buf);
+	ret = i2c_smbus_read_word_swapped(data->client, data_reg);
 	if (ret < 0)
 		goto fail;
 
 	mutex_unlock(&data->vcnl4000_lock);
-	*val = be16_to_cpu(buf);
+	*val = ret;
 
 	return 0;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/light/vcnl4035.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/light/vcnl4035.c
@@ -8,6 +8,7 @@
  * TODO: Proximity
  */
 #include <linux/bitops.h>
+#include <linux/bitfield.h>
 #include <linux/i2c.h>
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
@@ -42,6 +43,7 @@
 #define VCNL4035_ALS_PERS_MASK		GENMASK(3, 2)
 #define VCNL4035_INT_ALS_IF_H_MASK	BIT(12)
 #define VCNL4035_INT_ALS_IF_L_MASK	BIT(13)
+#define VCNL4035_DEV_ID_MASK		GENMASK(7, 0)
 
 /* Default values */
 #define VCNL4035_MODE_ALS_ENABLE	BIT(0)
@@ -102,7 +104,8 @@
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct vcnl4035_data *data = iio_priv(indio_dev);
-	u8 buffer[ALIGN(sizeof(u16), sizeof(s64)) + sizeof(s64)];
+	/* Ensure naturally aligned timestamp */
+	u8 buffer[ALIGN(sizeof(u16), sizeof(s64)) + sizeof(s64)]  __aligned(8) = { };
 	int ret;
 
 	ret = regmap_read(data->regmap, VCNL4035_ALS_DATA, (int *)buffer);
@@ -414,6 +417,7 @@
 		return ret;
 	}
 
+	id = FIELD_GET(VCNL4035_DEV_ID_MASK, id);
 	if (id != VCNL4035_DEV_ID_VAL) {
 		dev_err(&data->client->dev, "Wrong id, got %x, expected %x\n",
 			id, VCNL4035_DEV_ID_VAL);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/magnetometer/ak8974.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/magnetometer/ak8974.c
@@ -185,6 +185,11 @@
 	bool drdy_irq;
 	struct completion drdy_complete;
 	bool drdy_active_low;
+	/* Ensure timestamp is naturally aligned */
+	struct {
+		__le16 channels[3];
+		s64 ts __aligned(8);
+	} scan;
 };
 
 static const char ak8974_reg_avdd[] = "avdd";
@@ -564,7 +569,7 @@
 		 * We read all axes and discard all but one, for optimized
 		 * reading, use the triggered buffer.
 		 */
-		*val = le16_to_cpu(hw_values[chan->address]);
+		*val = (s16)le16_to_cpu(hw_values[chan->address]);
 
 		ret = IIO_VAL_INT;
 	}
@@ -581,7 +586,6 @@
 {
 	struct ak8974 *ak8974 = iio_priv(indio_dev);
 	int ret;
-	__le16 hw_values[8]; /* Three axes + 64bit padding */
 
 	pm_runtime_get_sync(&ak8974->i2c->dev);
 	mutex_lock(&ak8974->lock);
@@ -591,13 +595,13 @@
 		dev_err(&ak8974->i2c->dev, "error triggering measure\n");
 		goto out_unlock;
 	}
-	ret = ak8974_getresult(ak8974, hw_values);
+	ret = ak8974_getresult(ak8974, ak8974->scan.channels);
 	if (ret) {
 		dev_err(&ak8974->i2c->dev, "error getting measures\n");
 		goto out_unlock;
 	}
 
-	iio_push_to_buffers_with_timestamp(indio_dev, hw_values,
+	iio_push_to_buffers_with_timestamp(indio_dev, &ak8974->scan,
 					   iio_get_time_ns(indio_dev));
 
  out_unlock:
@@ -764,19 +768,21 @@
 	ak8974->map = devm_regmap_init_i2c(i2c, &ak8974_regmap_config);
 	if (IS_ERR(ak8974->map)) {
 		dev_err(&i2c->dev, "failed to allocate register map\n");
+		pm_runtime_put_noidle(&i2c->dev);
+		pm_runtime_disable(&i2c->dev);
 		return PTR_ERR(ak8974->map);
 	}
 
 	ret = ak8974_set_power(ak8974, AK8974_PWR_ON);
 	if (ret) {
 		dev_err(&i2c->dev, "could not power on\n");
-		goto power_off;
+		goto disable_pm;
 	}
 
 	ret = ak8974_detect(ak8974);
 	if (ret) {
 		dev_err(&i2c->dev, "neither AK8974 nor AMI30x found\n");
-		goto power_off;
+		goto disable_pm;
 	}
 
 	ret = ak8974_selftest(ak8974);
@@ -786,14 +792,9 @@
 	ret = ak8974_reset(ak8974);
 	if (ret) {
 		dev_err(&i2c->dev, "AK8974 reset failed\n");
-		goto power_off;
+		goto disable_pm;
 	}
 
-	pm_runtime_set_autosuspend_delay(&i2c->dev,
-					 AK8974_AUTOSUSPEND_DELAY);
-	pm_runtime_use_autosuspend(&i2c->dev);
-	pm_runtime_put(&i2c->dev);
-
 	indio_dev->dev.parent = &i2c->dev;
 	indio_dev->channels = ak8974_channels;
 	indio_dev->num_channels = ARRAY_SIZE(ak8974_channels);
@@ -846,6 +847,11 @@
 		goto cleanup_buffer;
 	}
 
+	pm_runtime_set_autosuspend_delay(&i2c->dev,
+					 AK8974_AUTOSUSPEND_DELAY);
+	pm_runtime_use_autosuspend(&i2c->dev);
+	pm_runtime_put(&i2c->dev);
+
 	return 0;
 
 cleanup_buffer:
@@ -854,7 +860,6 @@
 	pm_runtime_put_noidle(&i2c->dev);
 	pm_runtime_disable(&i2c->dev);
 	ak8974_set_power(ak8974, AK8974_PWR_OFF);
-power_off:
 	regulator_bulk_disable(ARRAY_SIZE(ak8974->regs), ak8974->regs);
 
 	return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/magnetometer/ak8975.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/magnetometer/ak8975.c
@@ -368,6 +368,12 @@
 	struct iio_mount_matrix orientation;
 	struct regulator	*vdd;
 	struct regulator	*vid;
+
+	/* Ensure natural alignment of timestamp */
+	struct {
+		s16 channels[3];
+		s64 ts __aligned(8);
+	} scan;
 };
 
 /* Enable attached power regulator if any. */
@@ -385,6 +391,7 @@
 	if (ret) {
 		dev_warn(&data->client->dev,
 			 "Failed to enable specified Vid supply\n");
+		regulator_disable(data->vdd);
 		return ret;
 	}
 	/*
@@ -653,22 +660,8 @@
 	if (ret < 0)
 		return ret;
 
-	/* This will be executed only for non-interrupt based waiting case */
-	if (ret & data->def->ctrl_masks[ST1_DRDY]) {
-		ret = i2c_smbus_read_byte_data(client,
-					       data->def->ctrl_regs[ST2]);
-		if (ret < 0) {
-			dev_err(&client->dev, "Error in reading ST2\n");
-			return ret;
-		}
-		if (ret & (data->def->ctrl_masks[ST2_DERR] |
-			   data->def->ctrl_masks[ST2_HOFL])) {
-			dev_err(&client->dev, "ST2 status error 0x%x\n", ret);
-			return -EINVAL;
-		}
-	}
-
-	return 0;
+	/* Return with zero if the data is ready. */
+	return !data->def->ctrl_regs[ST1_DRDY];
 }
 
 /* Retrieve raw flux value for one of the x, y, or z axis.  */
@@ -695,6 +688,20 @@
 	if (ret < 0)
 		goto exit;
 
+	/* Read out ST2 for release lock on measurment data. */
+	ret = i2c_smbus_read_byte_data(client, data->def->ctrl_regs[ST2]);
+	if (ret < 0) {
+		dev_err(&client->dev, "Error in reading ST2\n");
+		goto exit;
+	}
+
+	if (ret & (data->def->ctrl_masks[ST2_DERR] |
+		   data->def->ctrl_masks[ST2_HOFL])) {
+		dev_err(&client->dev, "ST2 status error 0x%x\n", ret);
+		ret = -EINVAL;
+		goto exit;
+	}
+
 	mutex_unlock(&data->lock);
 
 	pm_runtime_mark_last_busy(&data->client->dev);
@@ -805,7 +812,6 @@
 	const struct i2c_client *client = data->client;
 	const struct ak_def *def = data->def;
 	int ret;
-	s16 buff[8]; /* 3 x 16 bits axis values + 1 aligned 64 bits timestamp */
 	__le16 fval[3];
 
 	mutex_lock(&data->lock);
@@ -828,12 +834,13 @@
 	mutex_unlock(&data->lock);
 
 	/* Clamp to valid range. */
-	buff[0] = clamp_t(s16, le16_to_cpu(fval[0]), -def->range, def->range);
-	buff[1] = clamp_t(s16, le16_to_cpu(fval[1]), -def->range, def->range);
-	buff[2] = clamp_t(s16, le16_to_cpu(fval[2]), -def->range, def->range);
+	data->scan.channels[0] = clamp_t(s16, le16_to_cpu(fval[0]), -def->range, def->range);
+	data->scan.channels[1] = clamp_t(s16, le16_to_cpu(fval[1]), -def->range, def->range);
+	data->scan.channels[2] = clamp_t(s16, le16_to_cpu(fval[2]), -def->range, def->range);
 
-	iio_push_to_buffers_with_timestamp(indio_dev, buff,
+	iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
 					   iio_get_time_ns(indio_dev));
+
 	return;
 
 unlock:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/magnetometer/bmc150_magn.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/magnetometer/bmc150_magn.c
@@ -136,8 +136,11 @@
 	struct mutex mutex;
 	struct regmap *regmap;
 	struct iio_mount_matrix orientation;
-	/* 4 x 32 bits for x, y z, 4 bytes align, 64 bits timestamp */
-	s32 buffer[6];
+	/* Ensure timestamp is naturally aligned */
+	struct {
+		s32 chans[3];
+		s64 timestamp __aligned(8);
+	} scan;
 	struct iio_trigger *dready_trig;
 	bool dready_trigger_on;
 	int max_odr;
@@ -260,7 +263,7 @@
 	int ret;
 
 	if (on) {
-		ret = pm_runtime_get_sync(data->dev);
+		ret = pm_runtime_resume_and_get(data->dev);
 	} else {
 		pm_runtime_mark_last_busy(data->dev);
 		ret = pm_runtime_put_autosuspend(data->dev);
@@ -269,9 +272,6 @@
 	if (ret < 0) {
 		dev_err(data->dev,
 			"failed to change power state to %d\n", on);
-		if (on)
-			pm_runtime_put_noidle(data->dev);
-
 		return ret;
 	}
 #endif
@@ -673,11 +673,11 @@
 	int ret;
 
 	mutex_lock(&data->mutex);
-	ret = bmc150_magn_read_xyz(data, data->buffer);
+	ret = bmc150_magn_read_xyz(data, data->scan.chans);
 	if (ret < 0)
 		goto err;
 
-	iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+	iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
 					   pf->timestamp);
 
 err:
@@ -944,12 +944,15 @@
 	ret = iio_device_register(indio_dev);
 	if (ret < 0) {
 		dev_err(dev, "unable to register iio device\n");
-		goto err_buffer_cleanup;
+		goto err_pm_cleanup;
 	}
 
 	dev_dbg(dev, "Registered device %s\n", name);
 	return 0;
 
+err_pm_cleanup:
+	pm_runtime_dont_use_autosuspend(dev);
+	pm_runtime_disable(dev);
 err_buffer_cleanup:
 	iio_triggered_buffer_cleanup(indio_dev);
 err_free_irq:
@@ -973,7 +976,6 @@
 
 	pm_runtime_disable(dev);
 	pm_runtime_set_suspended(dev);
-	pm_runtime_put_noidle(dev);
 
 	iio_triggered_buffer_cleanup(indio_dev);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/magnetometer/hmc5843.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/magnetometer/hmc5843.h
@@ -33,7 +33,8 @@
  * @lock:		update and read regmap data
  * @regmap:		hardware access register maps
  * @variant:		describe chip variants
- * @buffer:		3x 16-bit channels + padding + 64-bit timestamp
+ * @scan:		buffer to pack data for passing to
+ *			iio_push_to_buffers_with_timestamp()
  */
 struct hmc5843_data {
 	struct device *dev;
@@ -41,7 +42,10 @@
 	struct regmap *regmap;
 	const struct hmc5843_chip_info *variant;
 	struct iio_mount_matrix orientation;
-	__be16 buffer[8];
+	struct {
+		__be16 chans[3];
+		s64 timestamp __aligned(8);
+	} scan;
 };
 
 int hmc5843_common_probe(struct device *dev, struct regmap *regmap,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/magnetometer/hmc5843_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/magnetometer/hmc5843_core.c
@@ -446,13 +446,13 @@
 	}
 
 	ret = regmap_bulk_read(data->regmap, HMC5843_DATA_OUT_MSB_REGS,
-			       data->buffer, 3 * sizeof(__be16));
+			       data->scan.chans, sizeof(data->scan.chans));
 
 	mutex_unlock(&data->lock);
 	if (ret < 0)
 		goto done;
 
-	iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+	iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
 					   iio_get_time_ns(indio_dev));
 
 done:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/magnetometer/mag3110.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/magnetometer/mag3110.c
@@ -56,6 +56,12 @@
 	int sleep_val;
 	struct regulator *vdd_reg;
 	struct regulator *vddio_reg;
+	/* Ensure natural alignment of timestamp */
+	struct {
+		__be16 channels[3];
+		u8 temperature;
+		s64 ts __aligned(8);
+	} scan;
 };
 
 static int mag3110_request(struct mag3110_data *data)
@@ -387,10 +393,9 @@
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct mag3110_data *data = iio_priv(indio_dev);
-	u8 buffer[16]; /* 3 16-bit channels + 1 byte temp + padding + ts */
 	int ret;
 
-	ret = mag3110_read(data, (__be16 *) buffer);
+	ret = mag3110_read(data, data->scan.channels);
 	if (ret < 0)
 		goto done;
 
@@ -399,10 +404,10 @@
 			MAG3110_DIE_TEMP);
 		if (ret < 0)
 			goto done;
-		buffer[6] = ret;
+		data->scan.temperature = ret;
 	}
 
-	iio_push_to_buffers_with_timestamp(indio_dev, buffer,
+	iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
 		iio_get_time_ns(indio_dev));
 
 done:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/magnetometer/rm3100-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/magnetometer/rm3100-core.c
@@ -76,7 +76,8 @@
 	bool use_interrupt;
 	int conversion_time;
 	int scale;
-	u8 buffer[RM3100_SCAN_BYTES];
+	/* Ensure naturally aligned timestamp */
+	u8 buffer[RM3100_SCAN_BYTES] __aligned(8);
 	struct iio_trigger *drdy_trig;
 
 	/*
@@ -538,6 +539,7 @@
 	struct rm3100_data *data;
 	unsigned int tmp;
 	int ret;
+	int samp_rate_index;
 
 	indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
 	if (!indio_dev)
@@ -597,9 +599,14 @@
 	ret = regmap_read(regmap, RM3100_REG_TMRC, &tmp);
 	if (ret < 0)
 		return ret;
+
+	samp_rate_index = tmp - RM3100_TMRC_OFFSET;
+	if (samp_rate_index < 0 || samp_rate_index >=  RM3100_SAMP_NUM) {
+		dev_err(dev, "The value read from RM3100_REG_TMRC is invalid!\n");
+		return -EINVAL;
+	}
 	/* Initializing max wait time, which is double conversion time. */
-	data->conversion_time = rm3100_samp_rates[tmp - RM3100_TMRC_OFFSET][2]
-				* 2;
+	data->conversion_time = rm3100_samp_rates[samp_rate_index][2] * 2;
 
 	/* Cycle count values may not be what we want. */
 	if ((tmp - RM3100_TMRC_OFFSET) == 0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/potentiostat/lmp91000.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/potentiostat/lmp91000.c
@@ -71,8 +71,8 @@
 
 	struct completion completion;
 	u8 chan_select;
-
-	u32 buffer[4]; /* 64-bit data + 64-bit timestamp */
+	/* 64-bit data + 64-bit naturally aligned timestamp */
+	u32 buffer[4] __aligned(8);
 };
 
 static const struct iio_chan_spec lmp91000_channels[] = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/pressure/bmp280-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/pressure/bmp280-core.c
@@ -264,6 +264,8 @@
 		+ (s32)2097152) * calib->H2 + 8192) >> 14);
 	var -= ((((var >> 15) * (var >> 15)) >> 7) * (s32)calib->H1) >> 4;
 
+	var = clamp_val(var, 0, 419430400);
+
 	return var >> 12;
 };
 
@@ -706,7 +708,7 @@
 	unsigned int ctrl;
 
 	if (data->use_eoc)
-		init_completion(&data->done);
+		reinit_completion(&data->done);
 
 	ret = regmap_write(data->regmap, BMP280_REG_CTRL_MEAS, ctrl_meas);
 	if (ret)
@@ -962,6 +964,9 @@
 			"trying to enforce it\n");
 		irq_trig = IRQF_TRIGGER_RISING;
 	}
+
+	init_completion(&data->done);
+
 	ret = devm_request_threaded_irq(dev,
 			irq,
 			bmp085_eoc_irq,
@@ -1108,7 +1113,7 @@
 	 * however as it happens, the BMP085 shares the chip ID of BMP180
 	 * so we look for an IRQ if we have that.
 	 */
-	if (irq > 0 || (chip_id  == BMP180_CHIP_ID)) {
+	if (irq > 0 && (chip_id  == BMP180_CHIP_ID)) {
 		ret = bmp085_fetch_eoc_irq(dev, name, irq, data);
 		if (ret)
 			goto out_disable_vdda;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/pressure/cros_ec_baro.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/pressure/cros_ec_baro.c
@@ -114,6 +114,7 @@
 static const struct iio_info cros_ec_baro_info = {
 	.read_raw = &cros_ec_baro_read,
 	.write_raw = &cros_ec_baro_write,
+	.read_avail = &cros_ec_sensors_core_read_avail,
 };
 
 static int cros_ec_baro_probe(struct platform_device *pdev)
@@ -149,6 +150,8 @@
 		BIT(IIO_CHAN_INFO_SCALE) |
 		BIT(IIO_CHAN_INFO_SAMP_FREQ) |
 		BIT(IIO_CHAN_INFO_FREQUENCY);
+	channel->info_mask_shared_by_all_available =
+		BIT(IIO_CHAN_INFO_SAMP_FREQ);
 	channel->scan_type.realbits = CROS_EC_SENSOR_BITS;
 	channel->scan_type.storagebits = CROS_EC_SENSOR_BITS;
 	channel->scan_type.shift = 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/pressure/dps310.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/pressure/dps310.c
@@ -57,8 +57,8 @@
 #define  DPS310_RESET_MAGIC	0x09
 #define DPS310_COEF_BASE	0x10
 
-/* Make sure sleep time is <= 20ms for usleep_range */
-#define DPS310_POLL_SLEEP_US(t)		min(20000, (t) / 8)
+/* Make sure sleep time is <= 30ms for usleep_range */
+#define DPS310_POLL_SLEEP_US(t)		min(30000, (t) / 8)
 /* Silently handle error in rate value here */
 #define DPS310_POLL_TIMEOUT_US(rc)	((rc) <= 0 ? 1000000 : 1000000 / (rc))
 
@@ -89,6 +89,7 @@
 	s32 c00, c10, c20, c30, c01, c11, c21;
 	s32 pressure_raw;
 	s32 temp_raw;
+	bool timeout_recovery_failed;
 };
 
 static const struct iio_chan_spec dps310_channels[] = {
@@ -159,6 +160,102 @@
 	return 0;
 }
 
+/*
+ * Some versions of the chip will read temperatures in the ~60C range when
+ * it's actually ~20C. This is the manufacturer recommended workaround
+ * to correct the issue. The registers used below are undocumented.
+ */
+static int dps310_temp_workaround(struct dps310_data *data)
+{
+	int rc;
+	int reg;
+
+	rc = regmap_read(data->regmap, 0x32, &reg);
+	if (rc)
+		return rc;
+
+	/*
+	 * If bit 1 is set then the device is okay, and the workaround does not
+	 * need to be applied
+	 */
+	if (reg & BIT(1))
+		return 0;
+
+	rc = regmap_write(data->regmap, 0x0e, 0xA5);
+	if (rc)
+		return rc;
+
+	rc = regmap_write(data->regmap, 0x0f, 0x96);
+	if (rc)
+		return rc;
+
+	rc = regmap_write(data->regmap, 0x62, 0x02);
+	if (rc)
+		return rc;
+
+	rc = regmap_write(data->regmap, 0x0e, 0x00);
+	if (rc)
+		return rc;
+
+	return regmap_write(data->regmap, 0x0f, 0x00);
+}
+
+static int dps310_startup(struct dps310_data *data)
+{
+	int rc;
+	int ready;
+
+	/*
+	 * Set up pressure sensor in single sample, one measurement per second
+	 * mode
+	 */
+	rc = regmap_write(data->regmap, DPS310_PRS_CFG, 0);
+	if (rc)
+		return rc;
+
+	/*
+	 * Set up external (MEMS) temperature sensor in single sample, one
+	 * measurement per second mode
+	 */
+	rc = regmap_write(data->regmap, DPS310_TMP_CFG, DPS310_TMP_EXT);
+	if (rc)
+		return rc;
+
+	/* Temp and pressure shifts are disabled when PRC <= 8 */
+	rc = regmap_write_bits(data->regmap, DPS310_CFG_REG,
+			       DPS310_PRS_SHIFT_EN | DPS310_TMP_SHIFT_EN, 0);
+	if (rc)
+		return rc;
+
+	/* MEAS_CFG doesn't update correctly unless first written with 0 */
+	rc = regmap_write_bits(data->regmap, DPS310_MEAS_CFG,
+			       DPS310_MEAS_CTRL_BITS, 0);
+	if (rc)
+		return rc;
+
+	/* Turn on temperature and pressure measurement in the background */
+	rc = regmap_write_bits(data->regmap, DPS310_MEAS_CFG,
+			       DPS310_MEAS_CTRL_BITS, DPS310_PRS_EN |
+			       DPS310_TEMP_EN | DPS310_BACKGROUND);
+	if (rc)
+		return rc;
+
+	/*
+	 * Calibration coefficients required for reporting temperature.
+	 * They are available 40ms after the device has started
+	 */
+	rc = regmap_read_poll_timeout(data->regmap, DPS310_MEAS_CFG, ready,
+				      ready & DPS310_COEF_RDY, 10000, 40000);
+	if (rc)
+		return rc;
+
+	rc = dps310_get_coefs(data);
+	if (rc)
+		return rc;
+
+	return dps310_temp_workaround(data);
+}
+
 static int dps310_get_pres_precision(struct dps310_data *data)
 {
 	int rc;
@@ -297,11 +394,69 @@
 	return scale_factors[ilog2(rc)];
 }
 
+static int dps310_reset_wait(struct dps310_data *data)
+{
+	int rc;
+
+	rc = regmap_write(data->regmap, DPS310_RESET, DPS310_RESET_MAGIC);
+	if (rc)
+		return rc;
+
+	/* Wait for device chip access: 15ms in specification */
+	usleep_range(15000, 55000);
+	return 0;
+}
+
+static int dps310_reset_reinit(struct dps310_data *data)
+{
+	int rc;
+
+	rc = dps310_reset_wait(data);
+	if (rc)
+		return rc;
+
+	return dps310_startup(data);
+}
+
+static int dps310_ready_status(struct dps310_data *data, int ready_bit, int timeout)
+{
+	int sleep = DPS310_POLL_SLEEP_US(timeout);
+	int ready;
+
+	return regmap_read_poll_timeout(data->regmap, DPS310_MEAS_CFG, ready, ready & ready_bit,
+					sleep, timeout);
+}
+
+static int dps310_ready(struct dps310_data *data, int ready_bit, int timeout)
+{
+	int rc;
+
+	rc = dps310_ready_status(data, ready_bit, timeout);
+	if (rc) {
+		if (rc == -ETIMEDOUT && !data->timeout_recovery_failed) {
+			/* Reset and reinitialize the chip. */
+			if (dps310_reset_reinit(data)) {
+				data->timeout_recovery_failed = true;
+			} else {
+				/* Try again to get sensor ready status. */
+				if (dps310_ready_status(data, ready_bit, timeout))
+					data->timeout_recovery_failed = true;
+				else
+					return 0;
+			}
+		}
+
+		return rc;
+	}
+
+	data->timeout_recovery_failed = false;
+	return 0;
+}
+
 static int dps310_read_pres_raw(struct dps310_data *data)
 {
 	int rc;
 	int rate;
-	int ready;
 	int timeout;
 	s32 raw;
 	u8 val[3];
@@ -313,9 +468,7 @@
 	timeout = DPS310_POLL_TIMEOUT_US(rate);
 
 	/* Poll for sensor readiness; base the timeout upon the sample rate. */
-	rc = regmap_read_poll_timeout(data->regmap, DPS310_MEAS_CFG, ready,
-				      ready & DPS310_PRS_RDY,
-				      DPS310_POLL_SLEEP_US(timeout), timeout);
+	rc = dps310_ready(data, DPS310_PRS_RDY, timeout);
 	if (rc)
 		goto done;
 
@@ -352,7 +505,6 @@
 {
 	int rc;
 	int rate;
-	int ready;
 	int timeout;
 
 	if (mutex_lock_interruptible(&data->lock))
@@ -362,10 +514,8 @@
 	timeout = DPS310_POLL_TIMEOUT_US(rate);
 
 	/* Poll for sensor readiness; base the timeout upon the sample rate. */
-	rc = regmap_read_poll_timeout(data->regmap, DPS310_MEAS_CFG, ready,
-				      ready & DPS310_TMP_RDY,
-				      DPS310_POLL_SLEEP_US(timeout), timeout);
-	if (rc < 0)
+	rc = dps310_ready(data, DPS310_TMP_RDY, timeout);
+	if (rc)
 		goto done;
 
 	rc = dps310_read_temp_ready(data);
@@ -580,7 +730,7 @@
 	}
 }
 
-static int dps310_calculate_temp(struct dps310_data *data)
+static int dps310_calculate_temp(struct dps310_data *data, int *val)
 {
 	s64 c0;
 	s64 t;
@@ -596,7 +746,9 @@
 	t = c0 + ((s64)data->temp_raw * (s64)data->c1);
 
 	/* Convert to milliCelsius and scale the temperature */
-	return (int)div_s64(t * 1000LL, kt);
+	*val = (int)div_s64(t * 1000LL, kt);
+
+	return 0;
 }
 
 static int dps310_read_temp(struct dps310_data *data, int *val, int *val2,
@@ -618,11 +770,10 @@
 		if (rc)
 			return rc;
 
-		rc = dps310_calculate_temp(data);
-		if (rc < 0)
+		rc = dps310_calculate_temp(data, val);
+		if (rc)
 			return rc;
 
-		*val = rc;
 		return IIO_VAL_INT;
 
 	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
@@ -660,7 +811,7 @@
 {
 	struct dps310_data *data = action_data;
 
-	regmap_write(data->regmap, DPS310_RESET, DPS310_RESET_MAGIC);
+	dps310_reset_wait(data);
 }
 
 static const struct regmap_config dps310_regmap_config = {
@@ -677,52 +828,12 @@
 	.write_raw = dps310_write_raw,
 };
 
-/*
- * Some verions of chip will read temperatures in the ~60C range when
- * its actually ~20C. This is the manufacturer recommended workaround
- * to correct the issue. The registers used below are undocumented.
- */
-static int dps310_temp_workaround(struct dps310_data *data)
-{
-	int rc;
-	int reg;
-
-	rc = regmap_read(data->regmap, 0x32, &reg);
-	if (rc < 0)
-		return rc;
-
-	/*
-	 * If bit 1 is set then the device is okay, and the workaround does not
-	 * need to be applied
-	 */
-	if (reg & BIT(1))
-		return 0;
-
-	rc = regmap_write(data->regmap, 0x0e, 0xA5);
-	if (rc < 0)
-		return rc;
-
-	rc = regmap_write(data->regmap, 0x0f, 0x96);
-	if (rc < 0)
-		return rc;
-
-	rc = regmap_write(data->regmap, 0x62, 0x02);
-	if (rc < 0)
-		return rc;
-
-	rc = regmap_write(data->regmap, 0x0e, 0x00);
-	if (rc < 0)
-		return rc;
-
-	return regmap_write(data->regmap, 0x0f, 0x00);
-}
-
 static int dps310_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
 	struct dps310_data *data;
 	struct iio_dev *iio;
-	int rc, ready;
+	int rc;
 
 	iio = devm_iio_device_alloc(&client->dev,  sizeof(*data));
 	if (!iio)
@@ -748,54 +859,8 @@
 	if (rc)
 		return rc;
 
-	/*
-	 * Set up pressure sensor in single sample, one measurement per second
-	 * mode
-	 */
-	rc = regmap_write(data->regmap, DPS310_PRS_CFG, 0);
-
-	/*
-	 * Set up external (MEMS) temperature sensor in single sample, one
-	 * measurement per second mode
-	 */
-	rc = regmap_write(data->regmap, DPS310_TMP_CFG, DPS310_TMP_EXT);
-	if (rc < 0)
-		return rc;
-
-	/* Temp and pressure shifts are disabled when PRC <= 8 */
-	rc = regmap_write_bits(data->regmap, DPS310_CFG_REG,
-			       DPS310_PRS_SHIFT_EN | DPS310_TMP_SHIFT_EN, 0);
-	if (rc < 0)
-		return rc;
-
-	/* MEAS_CFG doesn't update correctly unless first written with 0 */
-	rc = regmap_write_bits(data->regmap, DPS310_MEAS_CFG,
-			       DPS310_MEAS_CTRL_BITS, 0);
-	if (rc < 0)
-		return rc;
-
-	/* Turn on temperature and pressure measurement in the background */
-	rc = regmap_write_bits(data->regmap, DPS310_MEAS_CFG,
-			       DPS310_MEAS_CTRL_BITS, DPS310_PRS_EN |
-			       DPS310_TEMP_EN | DPS310_BACKGROUND);
-	if (rc < 0)
-		return rc;
-
-	/*
-	 * Calibration coefficients required for reporting temperature.
-	 * They are available 40ms after the device has started
-	 */
-	rc = regmap_read_poll_timeout(data->regmap, DPS310_MEAS_CFG, ready,
-				      ready & DPS310_COEF_RDY, 10000, 40000);
-	if (rc < 0)
-		return rc;
-
-	rc = dps310_get_coefs(data);
-	if (rc < 0)
-		return rc;
-
-	rc = dps310_temp_workaround(data);
-	if (rc < 0)
+	rc = dps310_startup(data);
+	if (rc)
 		return rc;
 
 	rc = devm_iio_device_register(&client->dev, iio);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/pressure/mpl3115.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/pressure/mpl3115.c
@@ -144,7 +144,14 @@
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct mpl3115_data *data = iio_priv(indio_dev);
-	u8 buffer[16]; /* 32-bit channel + 16-bit channel + padding + ts */
+	/*
+	 * 32-bit channel + 16-bit channel + padding + ts
+	 * Note that it is possible for only one of the first 2
+	 * channels to be enabled. If that happens, the first element
+	 * of the buffer may be either 16 or 32-bits.  As such we cannot
+	 * use a simple structure definition to express this data layout.
+	 */
+	u8 buffer[16] __aligned(8);
 	int ret, pos = 0;
 
 	mutex_lock(&data->lock);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/pressure/ms5611.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/pressure/ms5611.h
@@ -25,13 +25,6 @@
 	MS5607,
 };
 
-struct ms5611_chip_info {
-	u16 prom[MS5611_PROM_WORDS_NB];
-
-	int (*temp_and_pressure_compensate)(struct ms5611_chip_info *chip_info,
-					    s32 *temp, s32 *pressure);
-};
-
 /*
  * OverSampling Rate descriptor.
  * Warning: cmd MUST be kept aligned on a word boundary (see
@@ -50,12 +43,15 @@
 	const struct ms5611_osr *pressure_osr;
 	const struct ms5611_osr *temp_osr;
 
-	int (*reset)(struct device *dev);
-	int (*read_prom_word)(struct device *dev, int index, u16 *word);
-	int (*read_adc_temp_and_pressure)(struct device *dev,
+	u16 prom[MS5611_PROM_WORDS_NB];
+
+	int (*reset)(struct ms5611_state *st);
+	int (*read_prom_word)(struct ms5611_state *st, int index, u16 *word);
+	int (*read_adc_temp_and_pressure)(struct ms5611_state *st,
 					  s32 *temp, s32 *pressure);
 
-	struct ms5611_chip_info *chip_info;
+	int (*compensate_temp_and_pressure)(struct ms5611_state *st, s32 *temp,
+					  s32 *pressure);
 	struct regulator *vdd;
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/pressure/ms5611_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/pressure/ms5611_core.c
@@ -76,7 +76,7 @@
 
 	crc = (crc >> 12) & 0x000F;
 
-	return crc_orig != 0x0000 && crc == crc_orig;
+	return crc == crc_orig;
 }
 
 static int ms5611_read_prom(struct iio_dev *indio_dev)
@@ -85,8 +85,7 @@
 	struct ms5611_state *st = iio_priv(indio_dev);
 
 	for (i = 0; i < MS5611_PROM_WORDS_NB; i++) {
-		ret = st->read_prom_word(&indio_dev->dev,
-					 i, &st->chip_info->prom[i]);
+		ret = st->read_prom_word(st, i, &st->prom[i]);
 		if (ret < 0) {
 			dev_err(&indio_dev->dev,
 				"failed to read prom at %d\n", i);
@@ -94,7 +93,7 @@
 		}
 	}
 
-	if (!ms5611_prom_is_valid(st->chip_info->prom, MS5611_PROM_WORDS_NB)) {
+	if (!ms5611_prom_is_valid(st->prom, MS5611_PROM_WORDS_NB)) {
 		dev_err(&indio_dev->dev, "PROM integrity check failed\n");
 		return -ENODEV;
 	}
@@ -108,28 +107,27 @@
 	int ret;
 	struct ms5611_state *st = iio_priv(indio_dev);
 
-	ret = st->read_adc_temp_and_pressure(&indio_dev->dev, temp, pressure);
+	ret = st->read_adc_temp_and_pressure(st, temp, pressure);
 	if (ret < 0) {
 		dev_err(&indio_dev->dev,
 			"failed to read temperature and pressure\n");
 		return ret;
 	}
 
-	return st->chip_info->temp_and_pressure_compensate(st->chip_info,
-							   temp, pressure);
+	return st->compensate_temp_and_pressure(st, temp, pressure);
 }
 
-static int ms5611_temp_and_pressure_compensate(struct ms5611_chip_info *chip_info,
+static int ms5611_temp_and_pressure_compensate(struct ms5611_state *st,
 					       s32 *temp, s32 *pressure)
 {
 	s32 t = *temp, p = *pressure;
 	s64 off, sens, dt;
 
-	dt = t - (chip_info->prom[5] << 8);
-	off = ((s64)chip_info->prom[2] << 16) + ((chip_info->prom[4] * dt) >> 7);
-	sens = ((s64)chip_info->prom[1] << 15) + ((chip_info->prom[3] * dt) >> 8);
+	dt = t - (st->prom[5] << 8);
+	off = ((s64)st->prom[2] << 16) + ((st->prom[4] * dt) >> 7);
+	sens = ((s64)st->prom[1] << 15) + ((st->prom[3] * dt) >> 8);
 
-	t = 2000 + ((chip_info->prom[6] * dt) >> 23);
+	t = 2000 + ((st->prom[6] * dt) >> 23);
 	if (t < 2000) {
 		s64 off2, sens2, t2;
 
@@ -155,17 +153,17 @@
 	return 0;
 }
 
-static int ms5607_temp_and_pressure_compensate(struct ms5611_chip_info *chip_info,
+static int ms5607_temp_and_pressure_compensate(struct ms5611_state *st,
 					       s32 *temp, s32 *pressure)
 {
 	s32 t = *temp, p = *pressure;
 	s64 off, sens, dt;
 
-	dt = t - (chip_info->prom[5] << 8);
-	off = ((s64)chip_info->prom[2] << 17) + ((chip_info->prom[4] * dt) >> 6);
-	sens = ((s64)chip_info->prom[1] << 16) + ((chip_info->prom[3] * dt) >> 7);
+	dt = t - (st->prom[5] << 8);
+	off = ((s64)st->prom[2] << 17) + ((st->prom[4] * dt) >> 6);
+	sens = ((s64)st->prom[1] << 16) + ((st->prom[3] * dt) >> 7);
 
-	t = 2000 + ((chip_info->prom[6] * dt) >> 23);
+	t = 2000 + ((st->prom[6] * dt) >> 23);
 	if (t < 2000) {
 		s64 off2, sens2, t2, tmp;
 
@@ -196,7 +194,7 @@
 	int ret;
 	struct ms5611_state *st = iio_priv(indio_dev);
 
-	ret = st->reset(&indio_dev->dev);
+	ret = st->reset(st);
 	if (ret < 0) {
 		dev_err(&indio_dev->dev, "failed to reset device\n");
 		return ret;
@@ -212,16 +210,21 @@
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct ms5611_state *st = iio_priv(indio_dev);
-	s32 buf[4]; /* s32 (pressure) + s32 (temp) + 2 * s32 (timestamp) */
+	/* Ensure buffer elements are naturally aligned */
+	struct {
+		s32 channels[2];
+		s64 ts __aligned(8);
+	} scan;
 	int ret;
 
 	mutex_lock(&st->lock);
-	ret = ms5611_read_temp_and_pressure(indio_dev, &buf[1], &buf[0]);
+	ret = ms5611_read_temp_and_pressure(indio_dev, &scan.channels[1],
+					    &scan.channels[0]);
 	mutex_unlock(&st->lock);
 	if (ret < 0)
 		goto err;
 
-	iio_push_to_buffers_with_timestamp(indio_dev, buf,
+	iio_push_to_buffers_with_timestamp(indio_dev, &scan,
 					   iio_get_time_ns(indio_dev));
 
 err:
@@ -338,15 +341,6 @@
 
 static const unsigned long ms5611_scan_masks[] = {0x3, 0};
 
-static struct ms5611_chip_info chip_info_tbl[] = {
-	[MS5611] = {
-		.temp_and_pressure_compensate = ms5611_temp_and_pressure_compensate,
-	},
-	[MS5607] = {
-		.temp_and_pressure_compensate = ms5607_temp_and_pressure_compensate,
-	}
-};
-
 static const struct iio_chan_spec ms5611_channels[] = {
 	{
 		.type = IIO_PRESSURE,
@@ -429,7 +423,20 @@
 	struct ms5611_state *st = iio_priv(indio_dev);
 
 	mutex_init(&st->lock);
-	st->chip_info = &chip_info_tbl[type];
+
+	switch (type) {
+	case MS5611:
+		st->compensate_temp_and_pressure =
+			ms5611_temp_and_pressure_compensate;
+		break;
+	case MS5607:
+		st->compensate_temp_and_pressure =
+			ms5607_temp_and_pressure_compensate;
+		break;
+	default:
+		return -EINVAL;
+	}
+
 	st->temp_osr =
 		&ms5611_avail_temp_osr[ARRAY_SIZE(ms5611_avail_temp_osr) - 1];
 	st->pressure_osr =
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/pressure/ms5611_i2c.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/pressure/ms5611_i2c.c
@@ -18,17 +18,15 @@
 
 #include "ms5611.h"
 
-static int ms5611_i2c_reset(struct device *dev)
+static int ms5611_i2c_reset(struct ms5611_state *st)
 {
-	struct ms5611_state *st = iio_priv(dev_to_iio_dev(dev));
-
 	return i2c_smbus_write_byte(st->client, MS5611_RESET);
 }
 
-static int ms5611_i2c_read_prom_word(struct device *dev, int index, u16 *word)
+static int ms5611_i2c_read_prom_word(struct ms5611_state *st, int index,
+				     u16 *word)
 {
 	int ret;
-	struct ms5611_state *st = iio_priv(dev_to_iio_dev(dev));
 
 	ret = i2c_smbus_read_word_swapped(st->client,
 			MS5611_READ_PROM_WORD + (index << 1));
@@ -55,11 +53,10 @@
 	return 0;
 }
 
-static int ms5611_i2c_read_adc_temp_and_pressure(struct device *dev,
+static int ms5611_i2c_read_adc_temp_and_pressure(struct ms5611_state *st,
 						 s32 *temp, s32 *pressure)
 {
 	int ret;
-	struct ms5611_state *st = iio_priv(dev_to_iio_dev(dev));
 	const struct ms5611_osr *osr = st->temp_osr;
 
 	ret = i2c_smbus_write_byte(st->client, osr->cmd);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/pressure/ms5611_spi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/pressure/ms5611_spi.c
@@ -13,18 +13,17 @@
 
 #include "ms5611.h"
 
-static int ms5611_spi_reset(struct device *dev)
+static int ms5611_spi_reset(struct ms5611_state *st)
 {
 	u8 cmd = MS5611_RESET;
-	struct ms5611_state *st = iio_priv(dev_to_iio_dev(dev));
 
 	return spi_write_then_read(st->client, &cmd, 1, NULL, 0);
 }
 
-static int ms5611_spi_read_prom_word(struct device *dev, int index, u16 *word)
+static int ms5611_spi_read_prom_word(struct ms5611_state *st, int index,
+				     u16 *word)
 {
 	int ret;
-	struct ms5611_state *st = iio_priv(dev_to_iio_dev(dev));
 
 	ret = spi_w8r16be(st->client, MS5611_READ_PROM_WORD + (index << 1));
 	if (ret < 0)
@@ -35,11 +34,10 @@
 	return 0;
 }
 
-static int ms5611_spi_read_adc(struct device *dev, s32 *val)
+static int ms5611_spi_read_adc(struct ms5611_state *st, s32 *val)
 {
 	int ret;
 	u8 buf[3] = { MS5611_READ_ADC };
-	struct ms5611_state *st = iio_priv(dev_to_iio_dev(dev));
 
 	ret = spi_write_then_read(st->client, buf, 1, buf, 3);
 	if (ret < 0)
@@ -50,11 +48,10 @@
 	return 0;
 }
 
-static int ms5611_spi_read_adc_temp_and_pressure(struct device *dev,
+static int ms5611_spi_read_adc_temp_and_pressure(struct ms5611_state *st,
 						 s32 *temp, s32 *pressure)
 {
 	int ret;
-	struct ms5611_state *st = iio_priv(dev_to_iio_dev(dev));
 	const struct ms5611_osr *osr = st->temp_osr;
 
 	/*
@@ -66,7 +63,7 @@
 		return ret;
 
 	usleep_range(osr->conv_usec, osr->conv_usec + (osr->conv_usec / 10UL));
-	ret = ms5611_spi_read_adc(dev, temp);
+	ret = ms5611_spi_read_adc(st, temp);
 	if (ret < 0)
 		return ret;
 
@@ -76,7 +73,7 @@
 		return ret;
 
 	usleep_range(osr->conv_usec, osr->conv_usec + (osr->conv_usec / 10UL));
-	return ms5611_spi_read_adc(dev, pressure);
+	return ms5611_spi_read_adc(st, pressure);
 }
 
 static int ms5611_spi_probe(struct spi_device *spi)
@@ -92,7 +89,7 @@
 	spi_set_drvdata(spi, indio_dev);
 
 	spi->mode = SPI_MODE_0;
-	spi->max_speed_hz = 20000000;
+	spi->max_speed_hz = min(spi->max_speed_hz, 20000000U);
 	spi->bits_per_word = 8;
 	ret = spi_setup(spi);
 	if (ret < 0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/pressure/zpa2326.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/pressure/zpa2326.c
@@ -585,6 +585,8 @@
 	}   sample;
 	int err;
 
+	memset(&sample, 0, sizeof(sample));
+
 	if (test_bit(0, indio_dev->active_scan_mask)) {
 		/* Get current pressure from hardware FIFO. */
 		err = zpa2326_dequeue_pressure(indio_dev, &sample.pressure);
@@ -664,8 +666,10 @@
 	int err;
 
 	err = pm_runtime_get_sync(indio_dev->dev.parent);
-	if (err < 0)
+	if (err < 0) {
+		pm_runtime_put(indio_dev->dev.parent);
 		return err;
+	}
 
 	if (err > 0) {
 		/*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/proximity/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/proximity/Kconfig
@@ -49,6 +49,8 @@
 config MB1232
 	tristate "MaxSonar I2CXL family ultrasonic sensors"
 	depends on I2C
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
 	help
 	  Say Y to build a driver for the ultrasonic sensors I2CXL of
 	  MaxBotix which have an i2c interface. It can be used to measure
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/proximity/as3935.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/proximity/as3935.c
@@ -61,7 +61,11 @@
 	unsigned long noise_tripped;
 	u32 tune_cap;
 	u32 nflwdth_reg;
-	u8 buffer[16]; /* 8-bit data + 56-bit padding + 64-bit timestamp */
+	/* Ensure timestamp is naturally aligned */
+	struct {
+		u8 chan;
+		s64 timestamp __aligned(8);
+	} scan;
 	u8 buf[2] ____cacheline_aligned;
 };
 
@@ -227,8 +231,8 @@
 	if (ret)
 		goto err_read;
 
-	st->buffer[0] = val & AS3935_DATA_MASK;
-	iio_push_to_buffers_with_timestamp(indio_dev, &st->buffer,
+	st->scan.chan = val & AS3935_DATA_MASK;
+	iio_push_to_buffers_with_timestamp(indio_dev, &st->scan,
 					   iio_get_time_ns(indio_dev));
 err_read:
 	iio_trigger_notify_done(indio_dev->trig);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/proximity/isl29501.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/proximity/isl29501.c
@@ -938,7 +938,7 @@
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct isl29501_private *isl29501 = iio_priv(indio_dev);
 	const unsigned long *active_mask = indio_dev->active_scan_mask;
-	u32 buffer[4] = {}; /* 1x16-bit + ts */
+	u32 buffer[4] __aligned(8) = {}; /* 1x16-bit + naturally aligned ts */
 
 	if (test_bit(ISL29501_DISTANCE_SCAN_INDEX, active_mask))
 		isl29501_register_read(isl29501, REG_DISTANCE, buffer);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/proximity/mb1232.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/proximity/mb1232.c
@@ -40,6 +40,11 @@
 	 */
 	struct completion	ranging;
 	int			irqnr;
+	/* Ensure correct alignment of data to push to IIO buffer */
+	struct {
+		s16 distance;
+		s64 ts __aligned(8);
+	} scan;
 };
 
 static irqreturn_t mb1232_handle_irq(int irq, void *dev_id)
@@ -113,17 +118,13 @@
 	struct iio_poll_func *pf = p;
 	struct iio_dev *indio_dev = pf->indio_dev;
 	struct mb1232_data *data = iio_priv(indio_dev);
-	/*
-	 * triggered buffer
-	 * 16-bit channel + 48-bit padding + 64-bit timestamp
-	 */
-	s16 buffer[8] = { 0 };
 
-	buffer[0] = mb1232_read_distance(data);
-	if (buffer[0] < 0)
+	data->scan.distance = mb1232_read_distance(data);
+	if (data->scan.distance < 0)
 		goto err;
 
-	iio_push_to_buffers_with_timestamp(indio_dev, buffer, pf->timestamp);
+	iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
+					   pf->timestamp);
 
 err:
 	iio_trigger_notify_done(indio_dev->trig);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c
@@ -43,7 +43,11 @@
 	int (*xfer)(struct lidar_data *data, u8 reg, u8 *val, int len);
 	int i2c_enabled;
 
-	u16 buffer[8]; /* 2 byte distance + 8 byte timestamp */
+	/* Ensure timestamp is naturally aligned */
+	struct {
+		u16 chan;
+		s64 timestamp __aligned(8);
+	} scan;
 };
 
 static const struct iio_chan_spec lidar_channels[] = {
@@ -158,6 +162,7 @@
 	ret = lidar_write_control(data, LIDAR_REG_CONTROL_ACQUIRE);
 	if (ret < 0) {
 		dev_err(&client->dev, "cannot send start measurement command");
+		pm_runtime_put_noidle(&client->dev);
 		return ret;
 	}
 
@@ -227,9 +232,9 @@
 	struct lidar_data *data = iio_priv(indio_dev);
 	int ret;
 
-	ret = lidar_get_measurement(data, data->buffer);
+	ret = lidar_get_measurement(data, &data->scan.chan);
 	if (!ret) {
-		iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+		iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
 						   iio_get_time_ns(indio_dev));
 	} else if (ret != -EINVAL) {
 		dev_err(&data->client->dev, "cannot read LIDAR measurement");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/proximity/srf08.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/proximity/srf08.c
@@ -63,11 +63,11 @@
 	int			range_mm;
 	struct mutex		lock;
 
-	/*
-	 * triggered buffer
-	 * 1x16-bit channel + 3x16 padding + 4x16 timestamp
-	 */
-	s16			buffer[8];
+	/* Ensure timestamp is naturally aligned */
+	struct {
+		s16 chan;
+		s64 timestamp __aligned(8);
+	} scan;
 
 	/* Sensor-Type */
 	enum srf08_sensor_type	sensor_type;
@@ -190,9 +190,9 @@
 
 	mutex_lock(&data->lock);
 
-	data->buffer[0] = sensor_data;
+	data->scan.chan = sensor_data;
 	iio_push_to_buffers_with_timestamp(indio_dev,
-						data->buffer, pf->timestamp);
+					   &data->scan, pf->timestamp);
 
 	mutex_unlock(&data->lock);
 err:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/temperature/hid-sensor-temperature.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/temperature/hid-sensor-temperature.c
@@ -17,7 +17,10 @@
 struct temperature_state {
 	struct hid_sensor_common common_attributes;
 	struct hid_sensor_hub_attribute_info temperature_attr;
-	s32 temperature_data;
+	struct {
+		s32 temperature_data;
+		u64 timestamp __aligned(8);
+	} scan;
 	int scale_pre_decml;
 	int scale_post_decml;
 	int scale_precision;
@@ -34,7 +37,7 @@
 			BIT(IIO_CHAN_INFO_SAMP_FREQ) |
 			BIT(IIO_CHAN_INFO_HYSTERESIS),
 	},
-	IIO_CHAN_SOFT_TIMESTAMP(3),
+	IIO_CHAN_SOFT_TIMESTAMP(1),
 };
 
 /* Adjust channel real bits based on report descriptor */
@@ -125,9 +128,8 @@
 	struct temperature_state *temp_st = iio_priv(indio_dev);
 
 	if (atomic_read(&temp_st->common_attributes.data_ready))
-		iio_push_to_buffers_with_timestamp(indio_dev,
-				&temp_st->temperature_data,
-				iio_get_time_ns(indio_dev));
+		iio_push_to_buffers_with_timestamp(indio_dev, &temp_st->scan,
+						   iio_get_time_ns(indio_dev));
 
 	return 0;
 }
@@ -142,7 +144,7 @@
 
 	switch (usage_id) {
 	case HID_USAGE_SENSOR_DATA_ENVIRONMENTAL_TEMPERATURE:
-		temp_st->temperature_data = *(s32 *)raw_data;
+		temp_st->scan.temperature_data = *(s32 *)raw_data;
 		return 0;
 	default:
 		return -EINVAL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/temperature/max31856.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/temperature/max31856.c
@@ -284,6 +284,8 @@
 	spi_set_drvdata(spi, indio_dev);
 
 	indio_dev->info = &max31856_info;
+	indio_dev->dev.parent = &spi->dev;
+	indio_dev->dev.of_node = spi->dev.of_node;
 	indio_dev->name = id->name;
 	indio_dev->modes = INDIO_DIRECT_MODE;
 	indio_dev->channels = max31856_channels;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/trigger/iio-trig-hrtimer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/trigger/iio-trig-hrtimer.c
@@ -102,7 +102,7 @@
 
 	if (state)
 		hrtimer_start(&trig_info->timer, trig_info->period,
-			      HRTIMER_MODE_REL);
+			      HRTIMER_MODE_REL_HARD);
 	else
 		hrtimer_cancel(&trig_info->timer);
 
@@ -132,7 +132,7 @@
 	trig_info->swt.trigger->ops = &iio_hrtimer_trigger_ops;
 	trig_info->swt.trigger->dev.groups = iio_hrtimer_attr_groups;
 
-	hrtimer_init(&trig_info->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+	hrtimer_init(&trig_info->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD);
 	trig_info->timer.function = iio_hrtimer_trig_handler;
 
 	trig_info->sampling_frequency = HRTIMER_DEFAULT_SAMPLING_FREQUENCY;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/trigger/iio-trig-sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/trigger/iio-trig-sysfs.c
@@ -196,6 +196,7 @@
 	}
 
 	iio_trigger_unregister(t->trig);
+	irq_work_sync(&t->work);
 	iio_trigger_free(t->trig);
 
 	list_del(&t->l);
@@ -208,9 +209,13 @@
 
 static int __init iio_sysfs_trig_init(void)
 {
+	int ret;
 	device_initialize(&iio_sysfs_trig_dev);
 	dev_set_name(&iio_sysfs_trig_dev, "iio_sysfs_trigger");
-	return device_add(&iio_sysfs_trig_dev);
+	ret = device_add(&iio_sysfs_trig_dev);
+	if (ret)
+		put_device(&iio_sysfs_trig_dev);
+	return ret;
 }
 module_init(iio_sysfs_trig_init);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iio/trigger/stm32-timer-trigger.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iio/trigger/stm32-timer-trigger.c
@@ -161,7 +161,8 @@
 	return 0;
 }
 
-static void stm32_timer_stop(struct stm32_timer_trigger *priv)
+static void stm32_timer_stop(struct stm32_timer_trigger *priv,
+			     struct iio_trigger *trig)
 {
 	u32 ccer, cr1;
 
@@ -179,6 +180,12 @@
 	regmap_write(priv->regmap, TIM_PSC, 0);
 	regmap_write(priv->regmap, TIM_ARR, 0);
 
+	/* Force disable master mode */
+	if (stm32_timer_is_trgo2_name(trig->name))
+		regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS2, 0);
+	else
+		regmap_update_bits(priv->regmap, TIM_CR2, TIM_CR2_MMS, 0);
+
 	/* Make sure that registers are updated */
 	regmap_update_bits(priv->regmap, TIM_EGR, TIM_EGR_UG, TIM_EGR_UG);
 }
@@ -197,7 +204,7 @@
 		return ret;
 
 	if (freq == 0) {
-		stm32_timer_stop(priv);
+		stm32_timer_stop(priv, trig);
 	} else {
 		ret = stm32_timer_start(priv, trig, freq);
 		if (ret)
@@ -793,6 +800,6 @@
 };
 module_platform_driver(stm32_timer_trigger_driver);
 
-MODULE_ALIAS("platform: stm32-timer-trigger");
+MODULE_ALIAS("platform:stm32-timer-trigger");
 MODULE_DESCRIPTION("STMicroelectronics STM32 Timer Trigger driver");
 MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/Kconfig
@@ -80,6 +80,9 @@
 	  This allows the user to config the default GID type that the CM
 	  uses for each device, when initiaing new connections.
 
+config INFINIBAND_VIRT_DMA
+	def_bool !HIGHMEM
+
 if INFINIBAND_USER_ACCESS || !INFINIBAND_USER_ACCESS
 source "drivers/infiniband/hw/mthca/Kconfig"
 source "drivers/infiniband/hw/qib/Kconfig"
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/core/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/core/Makefile
@@ -11,7 +11,7 @@
 				device.o fmr_pool.o cache.o netlink.o \
 				roce_gid_mgmt.o mr_pool.o addr.o sa_query.o \
 				multicast.o mad.o smi.o agent.o mad_rmpp.o \
-				nldev.o restrack.o counters.o
+				nldev.o restrack.o counters.o ib_core_uverbs.o
 
 ib_core-$(CONFIG_SECURITY_INFINIBAND) += security.o
 ib_core-$(CONFIG_CGROUP_RDMA) += cgroup.o
@@ -34,5 +34,5 @@
 				uverbs_std_types_flow_action.o uverbs_std_types_dm.o \
 				uverbs_std_types_mr.o uverbs_std_types_counters.o \
 				uverbs_uapi.o uverbs_std_types_device.o
-ib_uverbs-$(CONFIG_INFINIBAND_USER_MEM) += umem.o
+ib_uverbs-$(CONFIG_INFINIBAND_USER_MEM) += umem.o peer_mem.o
 ib_uverbs-$(CONFIG_INFINIBAND_ON_DEMAND_PAGING) += umem_odp.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/core/addr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/core/addr.c
@@ -76,7 +76,9 @@
 
 static const struct nla_policy ib_nl_addr_policy[LS_NLA_TYPE_MAX] = {
 	[LS_NLA_TYPE_DGID] = {.type = NLA_BINARY,
-		.len = sizeof(struct rdma_nla_ls_gid)},
+		.len = sizeof(struct rdma_nla_ls_gid),
+		.validation_type = NLA_VALIDATE_MIN,
+		.min = sizeof(struct rdma_nla_ls_gid)},
 };
 
 static inline bool ib_nl_is_good_ip_resp(const struct nlmsghdr *nlh)
@@ -139,7 +141,7 @@
 	if (ib_nl_is_good_ip_resp(nlh))
 		ib_nl_process_good_ip_rsep(nlh);
 
-	return skb->len;
+	return 0;
 }
 
 static int ib_nl_ip_send_msg(struct rdma_dev_addr *dev_addr,
@@ -421,16 +423,15 @@
 				(const struct sockaddr_in6 *)dst_sock;
 	struct flowi6 fl6;
 	struct dst_entry *dst;
-	int ret;
 
 	memset(&fl6, 0, sizeof fl6);
 	fl6.daddr = dst_in->sin6_addr;
 	fl6.saddr = src_in->sin6_addr;
 	fl6.flowi6_oif = addr->bound_dev_if;
 
-	ret = ipv6_stub->ipv6_dst_lookup(addr->net, NULL, &dst, &fl6);
-	if (ret < 0)
-		return ret;
+	dst = ipv6_stub->ipv6_dst_lookup_flow(addr->net, NULL, &fl6, NULL);
+	if (IS_ERR(dst))
+		return PTR_ERR(dst);
 
 	if (ipv6_addr_any(&src_in->sin6_addr))
 		src_in->sin6_addr = fl6.saddr;
@@ -646,13 +647,12 @@
 	req->callback = NULL;
 
 	spin_lock_bh(&lock);
+	/*
+	 * Although the work will normally have been canceled by the workqueue,
+	 * it can still be requeued as long as it is on the req_list.
+	 */
+	cancel_delayed_work(&req->work);
 	if (!list_empty(&req->list)) {
-		/*
-		 * Although the work will normally have been canceled by the
-		 * workqueue, it can still be requeued as long as it is on the
-		 * req_list.
-		 */
-		cancel_delayed_work(&req->work);
 		list_del_init(&req->list);
 		kfree(req);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/core/cache.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/core/cache.c
@@ -51,9 +51,8 @@
 
 struct ib_update_work {
 	struct work_struct work;
-	struct ib_device  *device;
-	u8                 port_num;
-	bool		   enforce_security;
+	struct ib_event event;
+	bool enforce_security;
 };
 
 union ib_gid zgid;
@@ -130,7 +129,7 @@
 	event.element.port_num	= port;
 	event.event		= IB_EVENT_GID_CHANGE;
 
-	ib_dispatch_event(&event);
+	ib_dispatch_event_clients(&event);
 }
 
 static const char * const gid_type_str[] = {
@@ -1387,9 +1386,8 @@
 	return ret;
 }
 
-static void ib_cache_update(struct ib_device *device,
-			    u8                port,
-			    bool	      enforce_security)
+static int
+ib_cache_update(struct ib_device *device, u8 port, bool enforce_security)
 {
 	struct ib_port_attr       *tprops = NULL;
 	struct ib_pkey_cache      *pkey_cache = NULL, *old_pkey_cache;
@@ -1397,11 +1395,11 @@
 	int                        ret;
 
 	if (!rdma_is_port_valid(device, port))
-		return;
+		return -EINVAL;
 
 	tprops = kmalloc(sizeof *tprops, GFP_KERNEL);
 	if (!tprops)
-		return;
+		return -ENOMEM;
 
 	ret = ib_query_port(device, port, tprops);
 	if (ret) {
@@ -1419,8 +1417,10 @@
 	pkey_cache = kmalloc(struct_size(pkey_cache, table,
 					 tprops->pkey_tbl_len),
 			     GFP_KERNEL);
-	if (!pkey_cache)
+	if (!pkey_cache) {
+		ret = -ENOMEM;
 		goto err;
+	}
 
 	pkey_cache->table_len = tprops->pkey_tbl_len;
 
@@ -1452,50 +1452,84 @@
 
 	kfree(old_pkey_cache);
 	kfree(tprops);
-	return;
+	return 0;
 
 err:
 	kfree(pkey_cache);
 	kfree(tprops);
+	return ret;
 }
 
-static void ib_cache_task(struct work_struct *_work)
+static void ib_cache_event_task(struct work_struct *_work)
 {
 	struct ib_update_work *work =
 		container_of(_work, struct ib_update_work, work);
+	int ret;
+
+	/* Before distributing the cache update event, first sync
+	 * the cache.
+	 */
+	ret = ib_cache_update(work->event.device, work->event.element.port_num,
+			      work->enforce_security);
+
+	/* GID event is notified already for individual GID entries by
+	 * dispatch_gid_change_event(). Hence, notifiy for rest of the
+	 * events.
+	 */
+	if (!ret && work->event.event != IB_EVENT_GID_CHANGE)
+		ib_dispatch_event_clients(&work->event);
 
-	ib_cache_update(work->device,
-			work->port_num,
-			work->enforce_security);
 	kfree(work);
 }
 
-static void ib_cache_event(struct ib_event_handler *handler,
-			   struct ib_event *event)
+static void ib_generic_event_task(struct work_struct *_work)
+{
+	struct ib_update_work *work =
+		container_of(_work, struct ib_update_work, work);
+
+	ib_dispatch_event_clients(&work->event);
+	kfree(work);
+}
+
+static bool is_cache_update_event(const struct ib_event *event)
+{
+	return (event->event == IB_EVENT_PORT_ERR    ||
+		event->event == IB_EVENT_PORT_ACTIVE ||
+		event->event == IB_EVENT_LID_CHANGE  ||
+		event->event == IB_EVENT_PKEY_CHANGE ||
+		event->event == IB_EVENT_CLIENT_REREGISTER ||
+		event->event == IB_EVENT_GID_CHANGE);
+}
+
+/**
+ * ib_dispatch_event - Dispatch an asynchronous event
+ * @event:Event to dispatch
+ *
+ * Low-level drivers must call ib_dispatch_event() to dispatch the
+ * event to all registered event handlers when an asynchronous event
+ * occurs.
+ */
+void ib_dispatch_event(const struct ib_event *event)
 {
 	struct ib_update_work *work;
 
-	if (event->event == IB_EVENT_PORT_ERR    ||
-	    event->event == IB_EVENT_PORT_ACTIVE ||
-	    event->event == IB_EVENT_LID_CHANGE  ||
-	    event->event == IB_EVENT_PKEY_CHANGE ||
-	    event->event == IB_EVENT_CLIENT_REREGISTER ||
-	    event->event == IB_EVENT_GID_CHANGE) {
-		work = kmalloc(sizeof *work, GFP_ATOMIC);
-		if (work) {
-			INIT_WORK(&work->work, ib_cache_task);
-			work->device   = event->device;
-			work->port_num = event->element.port_num;
-			if (event->event == IB_EVENT_PKEY_CHANGE ||
-			    event->event == IB_EVENT_GID_CHANGE)
-				work->enforce_security = true;
-			else
-				work->enforce_security = false;
+	work = kzalloc(sizeof(*work), GFP_ATOMIC);
+	if (!work)
+		return;
 
-			queue_work(ib_wq, &work->work);
-		}
-	}
+	if (is_cache_update_event(event))
+		INIT_WORK(&work->work, ib_cache_event_task);
+	else
+		INIT_WORK(&work->work, ib_generic_event_task);
+
+	work->event = *event;
+	if (event->event == IB_EVENT_PKEY_CHANGE ||
+	    event->event == IB_EVENT_GID_CHANGE)
+		work->enforce_security = true;
+
+	queue_work(ib_wq, &work->work);
 }
+EXPORT_SYMBOL(ib_dispatch_event);
 
 int ib_cache_setup_one(struct ib_device *device)
 {
@@ -1508,12 +1542,12 @@
 	if (err)
 		return err;
 
-	rdma_for_each_port (device, p)
-		ib_cache_update(device, p, true);
+	rdma_for_each_port (device, p) {
+		err = ib_cache_update(device, p, true);
+		if (err)
+			return err;
+	}
 
-	INIT_IB_EVENT_HANDLER(&device->cache.event_handler,
-			      device, ib_cache_event);
-	ib_register_event_handler(&device->cache.event_handler);
 	return 0;
 }
 
@@ -1535,14 +1569,12 @@
 
 void ib_cache_cleanup_one(struct ib_device *device)
 {
-	/* The cleanup function unregisters the event handler,
-	 * waits for all in-progress workqueue elements and cleans
-	 * up the GID cache. This function should be called after
-	 * the device was removed from the devices list and all
-	 * clients were removed, so the cache exists but is
+	/* The cleanup function waits for all in-progress workqueue
+	 * elements and cleans up the GID cache. This function should be
+	 * called after the device was removed from the devices list and
+	 * all clients were removed, so the cache exists but is
 	 * non-functional and shouldn't be updated anymore.
 	 */
-	ib_unregister_event_handler(&device->cache.event_handler);
 	flush_workqueue(ib_wq);
 	gid_table_cleanup_one(device);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/core/cm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/core/cm.c
@@ -597,18 +597,6 @@
 	return 0;
 }
 
-static int cm_alloc_id(struct cm_id_private *cm_id_priv)
-{
-	int err;
-	u32 id;
-
-	err = xa_alloc_cyclic_irq(&cm.local_id_table, &id, cm_id_priv,
-			xa_limit_32b, &cm.local_id_next, GFP_KERNEL);
-
-	cm_id_priv->id.local_id = (__force __be32)id ^ cm.random_id_operand;
-	return err;
-}
-
 static u32 cm_local_id(__be32 local_id)
 {
 	return (__force u32) (local_id ^ cm.random_id_operand);
@@ -862,6 +850,7 @@
 				 void *context)
 {
 	struct cm_id_private *cm_id_priv;
+	u32 id;
 	int ret;
 
 	cm_id_priv = kzalloc(sizeof *cm_id_priv, GFP_KERNEL);
@@ -873,9 +862,6 @@
 	cm_id_priv->id.cm_handler = cm_handler;
 	cm_id_priv->id.context = context;
 	cm_id_priv->id.remote_cm_qpn = 1;
-	ret = cm_alloc_id(cm_id_priv);
-	if (ret)
-		goto error;
 
 	spin_lock_init(&cm_id_priv->lock);
 	init_completion(&cm_id_priv->comp);
@@ -884,11 +870,20 @@
 	INIT_LIST_HEAD(&cm_id_priv->altr_list);
 	atomic_set(&cm_id_priv->work_count, -1);
 	atomic_set(&cm_id_priv->refcount, 1);
+
+	ret = xa_alloc_cyclic_irq(&cm.local_id_table, &id, NULL, xa_limit_32b,
+				  &cm.local_id_next, GFP_KERNEL);
+	if (ret < 0)
+		goto error;
+	cm_id_priv->id.local_id = (__force __be32)id ^ cm.random_id_operand;
+	xa_store_irq(&cm.local_id_table, cm_local_id(cm_id_priv->id.local_id),
+		     cm_id_priv, GFP_KERNEL);
+
 	return &cm_id_priv->id;
 
 error:
 	kfree(cm_id_priv);
-	return ERR_PTR(-ENOMEM);
+	return ERR_PTR(ret);
 }
 EXPORT_SYMBOL(ib_create_cm_id);
 
@@ -1097,14 +1092,22 @@
 		break;
 	}
 
-	spin_lock_irq(&cm.lock);
+	spin_lock_irq(&cm_id_priv->lock);
+	spin_lock(&cm.lock);
+	/* Required for cleanup paths related cm_req_handler() */
+	if (cm_id_priv->timewait_info) {
+		cm_cleanup_timewait(cm_id_priv->timewait_info);
+		kfree(cm_id_priv->timewait_info);
+		cm_id_priv->timewait_info = NULL;
+	}
 	if (!list_empty(&cm_id_priv->altr_list) &&
 	    (!cm_id_priv->altr_send_port_not_ready))
 		list_del(&cm_id_priv->altr_list);
 	if (!list_empty(&cm_id_priv->prim_list) &&
 	    (!cm_id_priv->prim_send_port_not_ready))
 		list_del(&cm_id_priv->prim_list);
-	spin_unlock_irq(&cm.lock);
+	spin_unlock(&cm.lock);
+	spin_unlock_irq(&cm_id_priv->lock);
 
 	cm_free_id(cm_id->local_id);
 	cm_deref_id(cm_id_priv);
@@ -1228,6 +1231,7 @@
 			/* Sharing an ib_cm_id with different handlers is not
 			 * supported */
 			spin_unlock_irqrestore(&cm.lock, flags);
+			ib_destroy_cm_id(cm_id);
 			return ERR_PTR(-EINVAL);
 		}
 		atomic_inc(&cm_id_priv->refcount);
@@ -1420,7 +1424,7 @@
 	/* Verify that we're not in timewait. */
 	cm_id_priv = container_of(cm_id, struct cm_id_private, id);
 	spin_lock_irqsave(&cm_id_priv->lock, flags);
-	if (cm_id->state != IB_CM_IDLE) {
+	if (cm_id->state != IB_CM_IDLE || WARN_ON(cm_id_priv->timewait_info)) {
 		spin_unlock_irqrestore(&cm_id_priv->lock, flags);
 		ret = -EINVAL;
 		goto out;
@@ -1431,6 +1435,7 @@
 							    id.local_id);
 	if (IS_ERR(cm_id_priv->timewait_info)) {
 		ret = PTR_ERR(cm_id_priv->timewait_info);
+		cm_id_priv->timewait_info = NULL;
 		goto out;
 	}
 
@@ -1438,12 +1443,12 @@
 				 param->ppath_sgid_attr, &cm_id_priv->av,
 				 cm_id_priv);
 	if (ret)
-		goto error1;
+		goto out;
 	if (param->alternate_path) {
 		ret = cm_init_av_by_path(param->alternate_path, NULL,
 					 &cm_id_priv->alt_av, cm_id_priv);
 		if (ret)
-			goto error1;
+			goto out;
 	}
 	cm_id->service_id = param->service_id;
 	cm_id->service_mask = ~cpu_to_be64(0);
@@ -1461,7 +1466,7 @@
 
 	ret = cm_alloc_msg(cm_id_priv, &cm_id_priv->msg);
 	if (ret)
-		goto error1;
+		goto out;
 
 	req_msg = (struct cm_req_msg *) cm_id_priv->msg->mad;
 	cm_format_req(req_msg, cm_id_priv, param);
@@ -1484,7 +1489,6 @@
 	return 0;
 
 error2:	cm_free_msg(cm_id_priv->msg);
-error1:	kfree(cm_id_priv->timewait_info);
 out:	return ret;
 }
 EXPORT_SYMBOL(ib_send_cm_req);
@@ -1958,6 +1962,7 @@
 							    id.local_id);
 	if (IS_ERR(cm_id_priv->timewait_info)) {
 		ret = PTR_ERR(cm_id_priv->timewait_info);
+		cm_id_priv->timewait_info = NULL;
 		goto destroy;
 	}
 	cm_id_priv->timewait_info->work.remote_id = req_msg->local_comm_id;
@@ -1969,7 +1974,7 @@
 		pr_debug("%s: local_id %d, no listen_cm_id_priv\n", __func__,
 			 be32_to_cpu(cm_id->local_id));
 		ret = -EINVAL;
-		goto free_timeinfo;
+		goto destroy;
 	}
 
 	cm_id_priv->id.cm_handler = listen_cm_id_priv->id.cm_handler;
@@ -2054,8 +2059,6 @@
 rejected:
 	atomic_dec(&cm_id_priv->refcount);
 	cm_deref_id(listen_cm_id_priv);
-free_timeinfo:
-	kfree(cm_id_priv->timewait_info);
 destroy:
 	ib_destroy_cm_id(cm_id);
 	return ret;
@@ -4333,7 +4336,7 @@
 	unsigned long flags;
 	int ret;
 	int count = 0;
-	u8 i;
+	unsigned int i;
 
 	cm_dev = kzalloc(struct_size(cm_dev, port, ib_device->phys_port_cnt),
 			 GFP_KERNEL);
@@ -4345,7 +4348,7 @@
 	cm_dev->going_down = 0;
 
 	set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask);
-	for (i = 1; i <= ib_device->phys_port_cnt; i++) {
+	rdma_for_each_port (ib_device, i) {
 		if (!rdma_cap_ib_cm(ib_device, i))
 			continue;
 
@@ -4424,7 +4427,7 @@
 		.clr_port_cap_mask = IB_PORT_CM_SUP
 	};
 	unsigned long flags;
-	int i;
+	unsigned int i;
 
 	if (!cm_dev)
 		return;
@@ -4437,7 +4440,7 @@
 	cm_dev->going_down = 1;
 	spin_unlock_irq(&cm.lock);
 
-	for (i = 1; i <= ib_device->phys_port_cnt; i++) {
+	rdma_for_each_port (ib_device, i) {
 		if (!rdma_cap_ib_cm(ib_device, i))
 			continue;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/core/cma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/core/cma.c
@@ -530,6 +530,11 @@
 	list_del(&id_priv->list);
 	cma_deref_dev(id_priv->cma_dev);
 	id_priv->cma_dev = NULL;
+	id_priv->id.device = NULL;
+	if (id_priv->id.route.addr.dev_addr.sgid_attr) {
+		rdma_put_gid_attr(id_priv->id.route.addr.dev_addr.sgid_attr);
+		id_priv->id.route.addr.dev_addr.sgid_attr = NULL;
+	}
 	mutex_unlock(&lock);
 }
 
@@ -815,6 +820,7 @@
 	u16 pkey, index;
 	u8 p;
 	enum ib_port_state port_state;
+	int ret;
 	int i;
 
 	cma_dev = NULL;
@@ -833,9 +839,14 @@
 
 			if (ib_get_cached_port_state(cur_dev->device, p, &port_state))
 				continue;
-			for (i = 0; !rdma_query_gid(cur_dev->device,
-						    p, i, &gid);
-			     i++) {
+
+			for (i = 0; i < cur_dev->device->port_data[p].immutable.gid_tbl_len;
+			     ++i) {
+				ret = rdma_query_gid(cur_dev->device, p, i,
+						     &gid);
+				if (ret)
+					continue;
+
 				if (!memcmp(&gid, dgid, sizeof(gid))) {
 					cma_dev = cur_dev;
 					sgid = gid;
@@ -1423,7 +1434,7 @@
 		return false;
 
 	memset(&fl4, 0, sizeof(fl4));
-	fl4.flowi4_iif = net_dev->ifindex;
+	fl4.flowi4_oif = net_dev->ifindex;
 	fl4.daddr = daddr;
 	fl4.saddr = saddr;
 
@@ -1631,6 +1642,8 @@
 {
 	struct rdma_id_private *id_priv, *id_priv_dev;
 
+	lockdep_assert_held(&lock);
+
 	if (!bind_list)
 		return ERR_PTR(-EINVAL);
 
@@ -1677,6 +1690,7 @@
 		}
 	}
 
+	mutex_lock(&lock);
 	/*
 	 * Net namespace might be getting deleted while route lookup,
 	 * cm_id lookup is in progress. Therefore, perform netdevice
@@ -1705,8 +1719,8 @@
 		}
 
 		if (!validate_net_dev(*net_dev,
-				 (struct sockaddr *)&req->listen_addr_storage,
-				 (struct sockaddr *)&req->src_addr_storage)) {
+				 (struct sockaddr *)&req->src_addr_storage,
+				 (struct sockaddr *)&req->listen_addr_storage)) {
 			id_priv = ERR_PTR(-EHOSTUNREACH);
 			goto err;
 		}
@@ -1718,6 +1732,7 @@
 	id_priv = cma_find_listener(bind_list, cm_id, ib_event, req, *net_dev);
 err:
 	rcu_read_unlock();
+	mutex_unlock(&lock);
 	if (IS_ERR(id_priv) && *net_dev) {
 		dev_put(*net_dev);
 		*net_dev = NULL;
@@ -1799,19 +1814,30 @@
 	mutex_unlock(&lock);
 }
 
-static void cma_leave_roce_mc_group(struct rdma_id_private *id_priv,
-				    struct cma_multicast *mc)
+static void destroy_mc(struct rdma_id_private *id_priv,
+		       struct cma_multicast *mc)
 {
-	struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
-	struct net_device *ndev = NULL;
+	if (rdma_cap_ib_mcast(id_priv->id.device, id_priv->id.port_num)) {
+		ib_sa_free_multicast(mc->multicast.ib);
+		kfree(mc);
+		return;
+	}
 
-	if (dev_addr->bound_dev_if)
-		ndev = dev_get_by_index(dev_addr->net, dev_addr->bound_dev_if);
-	if (ndev) {
-		cma_igmp_send(ndev, &mc->multicast.ib->rec.mgid, false);
-		dev_put(ndev);
+	if (rdma_protocol_roce(id_priv->id.device,
+				      id_priv->id.port_num)) {
+		struct rdma_dev_addr *dev_addr =
+			&id_priv->id.route.addr.dev_addr;
+		struct net_device *ndev = NULL;
+
+		if (dev_addr->bound_dev_if)
+			ndev = dev_get_by_index(dev_addr->net,
+						dev_addr->bound_dev_if);
+		if (ndev) {
+			cma_igmp_send(ndev, &mc->multicast.ib->rec.mgid, false);
+			dev_put(ndev);
+		}
+		kref_put(&mc->mcref, release_mc);
 	}
-	kref_put(&mc->mcref, release_mc);
 }
 
 static void cma_leave_mc_groups(struct rdma_id_private *id_priv)
@@ -1819,16 +1845,10 @@
 	struct cma_multicast *mc;
 
 	while (!list_empty(&id_priv->mc_list)) {
-		mc = container_of(id_priv->mc_list.next,
-				  struct cma_multicast, list);
+		mc = list_first_entry(&id_priv->mc_list, struct cma_multicast,
+				      list);
 		list_del(&mc->list);
-		if (rdma_cap_ib_mcast(id_priv->cma_dev->device,
-				      id_priv->id.port_num)) {
-			ib_sa_free_multicast(mc->multicast.ib);
-			kfree(mc);
-		} else {
-			cma_leave_roce_mc_group(id_priv, mc);
-		}
+		destroy_mc(id_priv, mc);
 	}
 }
 
@@ -1858,6 +1878,7 @@
 				iw_destroy_cm_id(id_priv->cm_id.iw);
 		}
 		cma_leave_mc_groups(id_priv);
+		rdma_restrack_del(&id_priv->res);
 		cma_release_dev(id_priv);
 	}
 
@@ -1870,9 +1891,6 @@
 
 	kfree(id_priv->id.route.path_rec);
 
-	if (id_priv->id.route.addr.dev_addr.sgid_attr)
-		rdma_put_gid_attr(id_priv->id.route.addr.dev_addr.sgid_attr);
-
 	put_net(id_priv->id.route.addr.dev_addr.net);
 	kfree(id_priv);
 }
@@ -2473,6 +2491,8 @@
 	struct net *net = id_priv->id.route.addr.dev_addr.net;
 	int ret;
 
+	lockdep_assert_held(&lock);
+
 	if (cma_family(id_priv) == AF_IB && !rdma_cap_ib_cm(cma_dev->device, 1))
 		return;
 
@@ -2539,7 +2559,7 @@
 {
 	struct rdma_id_private *id_priv;
 
-	if (id->qp_type != IB_QPT_RC)
+	if (id->qp_type != IB_QPT_RC && id->qp_type != IB_QPT_XRC_INI)
 		return -EINVAL;
 
 	id_priv = container_of(id, struct rdma_id_private, id);
@@ -2705,7 +2725,8 @@
 
 	cma_init_resolve_route_work(work, id_priv);
 
-	route->path_rec = kmalloc(sizeof *route->path_rec, GFP_KERNEL);
+	if (!route->path_rec)
+		route->path_rec = kmalloc(sizeof *route->path_rec, GFP_KERNEL);
 	if (!route->path_rec) {
 		ret = -ENOMEM;
 		goto err1;
@@ -2911,6 +2932,7 @@
 err2:
 	kfree(route->path_rec);
 	route->path_rec = NULL;
+	route->num_paths = 0;
 err1:
 	kfree(work);
 	return ret;
@@ -3091,6 +3113,7 @@
 	rdma_addr_get_sgid(&id_priv->id.route.addr.dev_addr, &gid);
 	rdma_addr_set_dgid(&id_priv->id.route.addr.dev_addr, &gid);
 
+	atomic_inc(&id_priv->refcount);
 	cma_init_resolve_addr_work(work, id_priv);
 	queue_work(cma_wq, &work->work);
 	return 0;
@@ -3117,6 +3140,7 @@
 	rdma_addr_set_dgid(&id_priv->id.route.addr.dev_addr, (union ib_gid *)
 		&(((struct sockaddr_ib *) &id_priv->id.route.addr.dst_addr)->sib_addr));
 
+	atomic_inc(&id_priv->refcount);
 	cma_init_resolve_addr_work(work, id_priv);
 	queue_work(cma_wq, &work->work);
 	return 0;
@@ -3153,19 +3177,26 @@
 	int ret;
 
 	id_priv = container_of(id, struct rdma_id_private, id);
+	memcpy(cma_dst_addr(id_priv), dst_addr, rdma_addr_size(dst_addr));
 	if (id_priv->state == RDMA_CM_IDLE) {
 		ret = cma_bind_addr(id, src_addr, dst_addr);
-		if (ret)
+		if (ret) {
+			memset(cma_dst_addr(id_priv), 0,
+			       rdma_addr_size(dst_addr));
 			return ret;
+		}
 	}
 
-	if (cma_family(id_priv) != dst_addr->sa_family)
+	if (cma_family(id_priv) != dst_addr->sa_family) {
+		memset(cma_dst_addr(id_priv), 0, rdma_addr_size(dst_addr));
 		return -EINVAL;
+	}
 
-	if (!cma_comp_exch(id_priv, RDMA_CM_ADDR_BOUND, RDMA_CM_ADDR_QUERY))
+	if (!cma_comp_exch(id_priv, RDMA_CM_ADDR_BOUND, RDMA_CM_ADDR_QUERY)) {
+		memset(cma_dst_addr(id_priv), 0, rdma_addr_size(dst_addr));
 		return -EINVAL;
+	}
 
-	memcpy(cma_dst_addr(id_priv), dst_addr, rdma_addr_size(dst_addr));
 	if (cma_any_addr(dst_addr)) {
 		ret = cma_resolve_loopback(id_priv);
 	} else {
@@ -3235,6 +3266,8 @@
 	u64 sid, mask;
 	__be16 port;
 
+	lockdep_assert_held(&lock);
+
 	addr = cma_src_addr(id_priv);
 	port = htons(bind_list->port);
 
@@ -3263,6 +3296,8 @@
 	struct rdma_bind_list *bind_list;
 	int ret;
 
+	lockdep_assert_held(&lock);
+
 	bind_list = kzalloc(sizeof *bind_list, GFP_KERNEL);
 	if (!bind_list)
 		return -ENOMEM;
@@ -3289,6 +3324,8 @@
 	struct sockaddr  *saddr = cma_src_addr(id_priv);
 	__be16 dport = cma_port(daddr);
 
+	lockdep_assert_held(&lock);
+
 	hlist_for_each_entry(cur_id, &bind_list->owners, node) {
 		struct sockaddr  *cur_daddr = cma_dst_addr(cur_id);
 		struct sockaddr  *cur_saddr = cma_src_addr(cur_id);
@@ -3328,6 +3365,8 @@
 	unsigned int rover;
 	struct net *net = id_priv->id.route.addr.dev_addr.net;
 
+	lockdep_assert_held(&lock);
+
 	inet_get_local_port_range(net, &low, &high);
 	remaining = (high - low) + 1;
 	rover = prandom_u32() % remaining + low;
@@ -3375,6 +3414,8 @@
 	struct rdma_id_private *cur_id;
 	struct sockaddr *addr, *cur_addr;
 
+	lockdep_assert_held(&lock);
+
 	addr = cma_src_addr(id_priv);
 	hlist_for_each_entry(cur_id, &bind_list->owners, node) {
 		if (id_priv == cur_id)
@@ -3405,6 +3446,8 @@
 	unsigned short snum;
 	int ret;
 
+	lockdep_assert_held(&lock);
+
 	snum = ntohs(cma_port(cma_src_addr(id_priv)));
 	if (snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
 		return -EACCES;
@@ -3546,7 +3589,7 @@
 	}
 
 	id_priv->backlog = backlog;
-	if (id->device) {
+	if (id_priv->cma_dev) {
 		if (rdma_cap_ib_cm(id->device, 1)) {
 			ret = cma_ib_listen(id_priv);
 			if (ret)
@@ -4014,14 +4057,15 @@
 int __rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param,
 		  const char *caller)
 {
-	struct rdma_id_private *id_priv;
+	struct rdma_id_private *id_priv =
+		container_of(id, struct rdma_id_private, id);
 	int ret;
 
-	id_priv = container_of(id, struct rdma_id_private, id);
+	lockdep_assert_held(&id_priv->handler_mutex);
 
 	rdma_restrack_set_task(&id_priv->res, caller);
 
-	if (!cma_comp(id_priv, RDMA_CM_CONNECT))
+	if (READ_ONCE(id_priv->state) != RDMA_CM_CONNECT)
 		return -EINVAL;
 
 	if (!id->qp && conn_param) {
@@ -4061,6 +4105,24 @@
 }
 EXPORT_SYMBOL(__rdma_accept);
 
+void rdma_lock_handler(struct rdma_cm_id *id)
+{
+	struct rdma_id_private *id_priv =
+		container_of(id, struct rdma_id_private, id);
+
+	mutex_lock(&id_priv->handler_mutex);
+}
+EXPORT_SYMBOL(rdma_lock_handler);
+
+void rdma_unlock_handler(struct rdma_cm_id *id)
+{
+	struct rdma_id_private *id_priv =
+		container_of(id, struct rdma_id_private, id);
+
+	mutex_unlock(&id_priv->handler_mutex);
+}
+EXPORT_SYMBOL(rdma_unlock_handler);
+
 int rdma_notify(struct rdma_cm_id *id, enum ib_event_type event)
 {
 	struct rdma_id_private *id_priv;
@@ -4154,16 +4216,6 @@
 	else
 		pr_debug_ratelimited("RDMA CM: MULTICAST_ERROR: failed to join multicast. status %d\n",
 				     status);
-	mutex_lock(&id_priv->qp_mutex);
-	if (!status && id_priv->id.qp) {
-		status = ib_attach_mcast(id_priv->id.qp, &multicast->rec.mgid,
-					 be16_to_cpu(multicast->rec.mlid));
-		if (status)
-			pr_debug_ratelimited("RDMA CM: MULTICAST_ERROR: failed to attach QP. status %d\n",
-					     status);
-	}
-	mutex_unlock(&id_priv->qp_mutex);
-
 	event.status = status;
 	event.param.ud.private_data = mc->context;
 	if (!status) {
@@ -4418,6 +4470,10 @@
 	struct cma_multicast *mc;
 	int ret;
 
+	/* Not supported for kernel QPs */
+	if (WARN_ON(id->qp))
+		return -EINVAL;
+
 	if (!id->device)
 		return -EINVAL;
 
@@ -4468,25 +4524,14 @@
 	id_priv = container_of(id, struct rdma_id_private, id);
 	spin_lock_irq(&id_priv->lock);
 	list_for_each_entry(mc, &id_priv->mc_list, list) {
-		if (!memcmp(&mc->addr, addr, rdma_addr_size(addr))) {
-			list_del(&mc->list);
-			spin_unlock_irq(&id_priv->lock);
-
-			if (id->qp)
-				ib_detach_mcast(id->qp,
-						&mc->multicast.ib->rec.mgid,
-						be16_to_cpu(mc->multicast.ib->rec.mlid));
-
-			BUG_ON(id_priv->cma_dev->device != id->device);
-
-			if (rdma_cap_ib_mcast(id->device, id->port_num)) {
-				ib_sa_free_multicast(mc->multicast.ib);
-				kfree(mc);
-			} else if (rdma_protocol_roce(id->device, id->port_num)) {
-				cma_leave_roce_mc_group(id_priv, mc);
-			}
-			return;
-		}
+		if (memcmp(&mc->addr, addr, rdma_addr_size(addr)) != 0)
+			continue;
+		list_del(&mc->list);
+		spin_unlock_irq(&id_priv->lock);
+
+		WARN_ON(id_priv->cma_dev->device != id->device);
+		destroy_mc(id_priv, mc);
+		return;
 	}
 	spin_unlock_irq(&id_priv->lock);
 }
@@ -4710,6 +4755,19 @@
 {
 	int ret;
 
+	/*
+	 * There is a rare lock ordering dependency in cma_netdev_callback()
+	 * that only happens when bonding is enabled. Teach lockdep that rtnl
+	 * must never be nested under lock so it can find these without having
+	 * to test with bonding.
+	 */
+	if (IS_ENABLED(CONFIG_LOCKDEP)) {
+		rtnl_lock();
+		mutex_lock(&lock);
+		mutex_unlock(&lock);
+		rtnl_unlock();
+	}
+
 	cma_wq = alloc_ordered_workqueue("rdma_cm", WQ_MEM_RECLAIM);
 	if (!cma_wq)
 		return -ENOMEM;
@@ -4736,6 +4794,7 @@
 err:
 	unregister_netdevice_notifier(&cma_nb);
 	ib_sa_unregister_client(&sa_client);
+	unregister_pernet_subsys(&cma_pernet_operations);
 err_wq:
 	destroy_workqueue(cma_wq);
 	return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/core/cma_configfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/core/cma_configfs.c
@@ -218,7 +218,7 @@
 	}
 
 	for (i = 0; i < ports_num; i++) {
-		char port_str[10];
+		char port_str[11];
 
 		ports[i].port_num = i + 1;
 		snprintf(port_str, sizeof(port_str), "%u", i + 1);
@@ -322,8 +322,21 @@
 	return ERR_PTR(err);
 }
 
+static void drop_cma_dev(struct config_group *cgroup, struct config_item *item)
+{
+	struct config_group *group =
+		container_of(item, struct config_group, cg_item);
+	struct cma_dev_group *cma_dev_group =
+		container_of(group, struct cma_dev_group, device_group);
+
+	configfs_remove_default_groups(&cma_dev_group->ports_group);
+	configfs_remove_default_groups(&cma_dev_group->device_group);
+	config_item_put(item);
+}
+
 static struct configfs_group_operations cma_subsys_group_ops = {
 	.make_group	= make_cma_dev,
+	.drop_item	= drop_cma_dev,
 };
 
 static const struct config_item_type cma_subsys_type = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/core/core_priv.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/core/core_priv.h
@@ -149,6 +149,7 @@
 int ib_cache_setup_one(struct ib_device *device);
 void ib_cache_cleanup_one(struct ib_device *device);
 void ib_cache_release_one(struct ib_device *device);
+void ib_dispatch_event_clients(struct ib_event *event);
 
 #ifdef CONFIG_CGROUP_RDMA
 void ib_device_register_rdmacg(struct ib_device *device);
@@ -337,6 +338,21 @@
 	qp->pd = pd;
 	qp->uobject = uobj;
 	qp->real_qp = qp;
+
+	qp->qp_type = attr->qp_type;
+	qp->qp_context = attr->qp_context;
+	qp->rwq_ind_tbl = attr->rwq_ind_tbl;
+	qp->send_cq = attr->send_cq;
+	qp->recv_cq = attr->recv_cq;
+	qp->srq = attr->srq;
+	qp->rwq_ind_tbl = attr->rwq_ind_tbl;
+	qp->event_handler = attr->event_handler;
+
+	atomic_set(&qp->usecnt, 0);
+	spin_lock_init(&qp->mr_lock);
+	INIT_LIST_HEAD(&qp->rdma_mrs);
+	INIT_LIST_HEAD(&qp->sig_mrs);
+
 	/*
 	 * We don't track XRC QPs for now, because they don't have PD
 	 * and more importantly they are created internaly by driver,
@@ -388,4 +404,15 @@
 
 int rdma_nl_net_init(struct rdma_dev_net *rnet);
 void rdma_nl_net_exit(struct rdma_dev_net *rnet);
+
+struct rdma_umap_priv {
+	struct vm_area_struct *vma;
+	struct list_head list;
+	struct rdma_user_mmap_entry *entry;
+};
+
+void rdma_umap_priv_init(struct rdma_umap_priv *priv,
+			 struct vm_area_struct *vma,
+			 struct rdma_user_mmap_entry *entry);
+
 #endif /* _CORE_PRIV_H */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/core/counters.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/core/counters.c
@@ -195,7 +195,7 @@
 	return ret;
 }
 
-static void counter_history_stat_update(const struct rdma_counter *counter)
+static void counter_history_stat_update(struct rdma_counter *counter)
 {
 	struct ib_device *dev = counter->device;
 	struct rdma_port_counter *port_counter;
@@ -205,6 +205,8 @@
 	if (!port_counter->hstats)
 		return;
 
+	rdma_counter_query_stats(counter);
+
 	for (i = 0; i < counter->stats->num_counters; i++)
 		port_counter->hstats->value[i] += counter->stats->value[i];
 }
@@ -282,6 +284,9 @@
 	struct rdma_counter *counter;
 	int ret;
 
+	if (!qp->res.valid || rdma_is_kernel_res(&qp->res))
+		return 0;
+
 	if (!rdma_is_port_valid(dev, port))
 		return -EINVAL;
 
@@ -463,10 +468,15 @@
 int rdma_counter_bind_qpn(struct ib_device *dev, u8 port,
 			  u32 qp_num, u32 counter_id)
 {
+	struct rdma_port_counter *port_counter;
 	struct rdma_counter *counter;
 	struct ib_qp *qp;
 	int ret;
 
+	port_counter = &dev->port_data[port].port_counter;
+	if (port_counter->mode.mode == RDMA_COUNTER_MODE_AUTO)
+		return -EINVAL;
+
 	qp = rdma_counter_get_qp(dev, qp_num);
 	if (!qp)
 		return -ENOENT;
@@ -477,7 +487,7 @@
 		goto err;
 	}
 
-	if (counter->res.task != qp->res.task) {
+	if (rdma_is_kernel_res(&counter->res) != rdma_is_kernel_res(&qp->res)) {
 		ret = -EINVAL;
 		goto err_task;
 	}
@@ -503,6 +513,7 @@
 int rdma_counter_bind_qpn_alloc(struct ib_device *dev, u8 port,
 				u32 qp_num, u32 *counter_id)
 {
+	struct rdma_port_counter *port_counter;
 	struct rdma_counter *counter;
 	struct ib_qp *qp;
 	int ret;
@@ -510,9 +521,13 @@
 	if (!rdma_is_port_valid(dev, port))
 		return -EINVAL;
 
-	if (!dev->port_data[port].port_counter.hstats)
+	port_counter = &dev->port_data[port].port_counter;
+	if (!port_counter->hstats)
 		return -EOPNOTSUPP;
 
+	if (port_counter->mode.mode == RDMA_COUNTER_MODE_AUTO)
+		return -EINVAL;
+
 	qp = rdma_counter_get_qp(dev, qp_num);
 	if (!qp)
 		return -ENOENT;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/core/device.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/core/device.c
@@ -591,6 +591,7 @@
 
 	INIT_LIST_HEAD(&device->event_handler_list);
 	spin_lock_init(&device->event_handler_lock);
+	init_rwsem(&device->event_handler_rwsem);
 	mutex_init(&device->unregistration_lock);
 	/*
 	 * client_data needs to be alloc because we don't want our mark to be
@@ -898,7 +899,9 @@
 	cdev->dev.parent = device->dev.parent;
 	rdma_init_coredev(cdev, device, read_pnet(&rnet->net));
 	cdev->dev.release = compatdev_release;
-	dev_set_name(&cdev->dev, "%s", dev_name(&device->dev));
+	ret = dev_set_name(&cdev->dev, "%s", dev_name(&device->dev));
+	if (ret)
+		goto add_err;
 
 	ret = device_add(&cdev->dev);
 	if (ret)
@@ -1199,9 +1202,21 @@
 		WARN_ON_ONCE(!parent);
 		device->dma_device = parent;
 	}
-	/* Setup default max segment size for all IB devices */
-	dma_set_max_seg_size(device->dma_device, SZ_2G);
 
+	if (!device->dev.dma_parms) {
+		if (parent) {
+			/*
+			 * The caller did not provide DMA parameters, so
+			 * 'parent' probably represents a PCI device. The PCI
+			 * core sets the maximum segment size to 64
+			 * KB. Increase this parameter to 2 GB.
+			 */
+			device->dev.dma_parms = parent->dma_parms;
+			dma_set_max_seg_size(device->dma_device, SZ_2G);
+		} else {
+			WARN_ON_ONCE(true);
+		}
+	}
 }
 
 /*
@@ -1315,6 +1330,10 @@
 	return ret;
 }
 
+static void prevent_dealloc_device(struct ib_device *ib_dev)
+{
+}
+
 /**
  * ib_register_device - Register an IB device with IB core
  * @device:Device to register
@@ -1368,9 +1387,6 @@
 	}
 
 	ret = enable_device_and_get(device);
-	dev_set_uevent_suppress(&device->dev, false);
-	/* Mark for userspace that device is ready */
-	kobject_uevent(&device->dev.kobj, KOBJ_ADD);
 	if (ret) {
 		void (*dealloc_fn)(struct ib_device *);
 
@@ -1382,16 +1398,20 @@
 		 * possibility for a parallel unregistration along with this
 		 * error flow. Since we have a refcount here we know any
 		 * parallel flow is stopped in disable_device and will see the
-		 * NULL pointers, causing the responsibility to
+		 * special dealloc_driver pointer, causing the responsibility to
 		 * ib_dealloc_device() to revert back to this thread.
 		 */
 		dealloc_fn = device->ops.dealloc_driver;
-		device->ops.dealloc_driver = NULL;
+		device->ops.dealloc_driver = prevent_dealloc_device;
 		ib_device_put(device);
 		__ib_unregister_device(device);
 		device->ops.dealloc_driver = dealloc_fn;
+		dev_set_uevent_suppress(&device->dev, false);
 		return ret;
 	}
+	dev_set_uevent_suppress(&device->dev, false);
+	/* Mark for userspace that device is ready */
+	kobject_uevent(&device->dev.kobj, KOBJ_ADD);
 	ib_device_put(device);
 
 	return 0;
@@ -1434,7 +1454,8 @@
 	 * Drivers using the new flow may not call ib_dealloc_device except
 	 * in error unwind prior to registration success.
 	 */
-	if (ib_dev->ops.dealloc_driver) {
+	if (ib_dev->ops.dealloc_driver &&
+	    ib_dev->ops.dealloc_driver != prevent_dealloc_device) {
 		WARN_ON(kref_read(&ib_dev->dev.kobj.kref) <= 1);
 		ib_dealloc_device(ib_dev);
 	}
@@ -1679,7 +1700,7 @@
 {
 	int ret;
 
-	down_write(&clients_rwsem);
+	lockdep_assert_held(&clients_rwsem);
 	/*
 	 * The add/remove callbacks must be called in FIFO/LIFO order. To
 	 * achieve this we assign client_ids so they are sorted in
@@ -1688,14 +1709,11 @@
 	client->client_id = highest_client_id;
 	ret = xa_insert(&clients, client->client_id, client, GFP_KERNEL);
 	if (ret)
-		goto out;
+		return ret;
 
 	highest_client_id++;
 	xa_set_mark(&clients, client->client_id, CLIENT_REGISTERED);
-
-out:
-	up_write(&clients_rwsem);
-	return ret;
+	return 0;
 }
 
 static void remove_client_id(struct ib_client *client)
@@ -1725,25 +1743,35 @@
 {
 	struct ib_device *device;
 	unsigned long index;
+	bool need_unreg = false;
 	int ret;
 
 	refcount_set(&client->uses, 1);
 	init_completion(&client->uses_zero);
+
+	/*
+	 * The devices_rwsem is held in write mode to ensure that a racing
+	 * ib_register_device() sees a consisent view of clients and devices.
+	 */
+	down_write(&devices_rwsem);
+	down_write(&clients_rwsem);
 	ret = assign_client_id(client);
 	if (ret)
-		return ret;
+		goto out;
 
-	down_read(&devices_rwsem);
+	need_unreg = true;
 	xa_for_each_marked (&devices, index, device, DEVICE_REGISTERED) {
 		ret = add_client_context(device, client);
-		if (ret) {
-			up_read(&devices_rwsem);
-			ib_unregister_client(client);
-			return ret;
-		}
+		if (ret)
+			goto out;
 	}
-	up_read(&devices_rwsem);
-	return 0;
+	ret = 0;
+out:
+	up_write(&clients_rwsem);
+	up_write(&devices_rwsem);
+	if (need_unreg && ret)
+		ib_unregister_client(client);
+	return ret;
 }
 EXPORT_SYMBOL(ib_register_client);
 
@@ -1920,17 +1948,15 @@
  *
  * ib_register_event_handler() registers an event handler that will be
  * called back when asynchronous IB events occur (as defined in
- * chapter 11 of the InfiniBand Architecture Specification).  This
- * callback may occur in interrupt context.
+ * chapter 11 of the InfiniBand Architecture Specification). This
+ * callback occurs in workqueue context.
  */
 void ib_register_event_handler(struct ib_event_handler *event_handler)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&event_handler->device->event_handler_lock, flags);
+	down_write(&event_handler->device->event_handler_rwsem);
 	list_add_tail(&event_handler->list,
 		      &event_handler->device->event_handler_list);
-	spin_unlock_irqrestore(&event_handler->device->event_handler_lock, flags);
+	up_write(&event_handler->device->event_handler_rwsem);
 }
 EXPORT_SYMBOL(ib_register_event_handler);
 
@@ -1943,35 +1969,23 @@
  */
 void ib_unregister_event_handler(struct ib_event_handler *event_handler)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&event_handler->device->event_handler_lock, flags);
+	down_write(&event_handler->device->event_handler_rwsem);
 	list_del(&event_handler->list);
-	spin_unlock_irqrestore(&event_handler->device->event_handler_lock, flags);
+	up_write(&event_handler->device->event_handler_rwsem);
 }
 EXPORT_SYMBOL(ib_unregister_event_handler);
 
-/**
- * ib_dispatch_event - Dispatch an asynchronous event
- * @event:Event to dispatch
- *
- * Low-level drivers must call ib_dispatch_event() to dispatch the
- * event to all registered event handlers when an asynchronous event
- * occurs.
- */
-void ib_dispatch_event(struct ib_event *event)
+void ib_dispatch_event_clients(struct ib_event *event)
 {
-	unsigned long flags;
 	struct ib_event_handler *handler;
 
-	spin_lock_irqsave(&event->device->event_handler_lock, flags);
+	down_read(&event->device->event_handler_rwsem);
 
 	list_for_each_entry(handler, &event->device->event_handler_list, list)
 		handler->handler(handler, event);
 
-	spin_unlock_irqrestore(&event->device->event_handler_lock, flags);
+	up_read(&event->device->event_handler_rwsem);
 }
-EXPORT_SYMBOL(ib_dispatch_event);
 
 static int iw_query_port(struct ib_device *device,
 			   u8 port_num,
@@ -2111,6 +2125,9 @@
 	unsigned long flags;
 	int ret;
 
+	if (!rdma_is_port_valid(ib_dev, port))
+		return -EINVAL;
+
 	/*
 	 * Drivers wish to call this before ib_register_driver, so we have to
 	 * setup the port data early.
@@ -2119,9 +2136,6 @@
 	if (ret)
 		return ret;
 
-	if (!rdma_is_port_valid(ib_dev, port))
-		return -EINVAL;
-
 	pdata = &ib_dev->port_data[port];
 	spin_lock_irqsave(&pdata->netdev_lock, flags);
 	old_ndev = rcu_dereference_protected(
@@ -2397,8 +2411,12 @@
 		rc = device->ops.modify_port(device, port_num,
 					     port_modify_mask,
 					     port_modify);
+	else if (rdma_protocol_roce(device, port_num) &&
+		 ((port_modify->set_port_cap_mask & ~IB_PORT_CM_SUP) == 0 ||
+		  (port_modify->clr_port_cap_mask & ~IB_PORT_CM_SUP) == 0))
+		rc = 0;
 	else
-		rc = rdma_protocol_roce(device, port_num) ? 0 : -ENOSYS;
+		rc = -EOPNOTSUPP;
 	return rc;
 }
 EXPORT_SYMBOL(ib_modify_port);
@@ -2427,7 +2445,8 @@
 		     ++i) {
 			ret = rdma_query_gid(device, port, i, &tmp_gid);
 			if (ret)
-				return ret;
+				continue;
+
 			if (!memcmp(&tmp_gid, gid, sizeof *gid)) {
 				*port_num = port;
 				if (index)
@@ -2630,6 +2649,7 @@
 	SET_DEVICE_OP(dev_ops, map_mr_sg_pi);
 	SET_DEVICE_OP(dev_ops, map_phys_fmr);
 	SET_DEVICE_OP(dev_ops, mmap);
+	SET_DEVICE_OP(dev_ops, mmap_free);
 	SET_DEVICE_OP(dev_ops, modify_ah);
 	SET_DEVICE_OP(dev_ops, modify_cq);
 	SET_DEVICE_OP(dev_ops, modify_device);
@@ -2750,10 +2770,18 @@
 
 	nldev_init();
 	rdma_nl_register(RDMA_NL_LS, ibnl_ls_cb_table);
-	roce_gid_mgmt_init();
+	ret = roce_gid_mgmt_init();
+	if (ret) {
+		pr_warn("Couldn't init RoCE GID management\n");
+		goto err_parent;
+	}
 
 	return 0;
 
+err_parent:
+	rdma_nl_unregister(RDMA_NL_LS);
+	nldev_exit();
+	unregister_pernet_device(&rdma_dev_net_ops);
 err_compat:
 	unregister_blocking_lsm_notifier(&ibdev_lsm_nb);
 err_sa:
@@ -2776,8 +2804,8 @@
 static void __exit ib_core_cleanup(void)
 {
 	roce_gid_mgmt_cleanup();
-	nldev_exit();
 	rdma_nl_unregister(RDMA_NL_LS);
+	nldev_exit();
 	unregister_pernet_device(&rdma_dev_net_ops);
 	unregister_blocking_lsm_notifier(&ibdev_lsm_nb);
 	ib_sa_cleanup();
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/core/ib_core_uverbs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/core/ib_core_uverbs.c
@@ -0,0 +1,335 @@
+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+/*
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All rights reserved.
+ * Copyright 2019 Marvell. All rights reserved.
+ */
+#include <linux/xarray.h>
+#include "uverbs.h"
+#include "core_priv.h"
+
+/**
+ * rdma_umap_priv_init() - Initialize the private data of a vma
+ *
+ * @priv: The already allocated private data
+ * @vma: The vm area struct that needs private data
+ * @entry: entry into the mmap_xa that needs to be linked with
+ *       this vma
+ *
+ * Each time we map IO memory into user space this keeps track of the
+ * mapping. When the device is hot-unplugged we 'zap' the mmaps in user space
+ * to point to the zero page and allow the hot unplug to proceed.
+ *
+ * This is necessary for cases like PCI physical hot unplug as the actual BAR
+ * memory may vanish after this and access to it from userspace could MCE.
+ *
+ * RDMA drivers supporting disassociation must have their user space designed
+ * to cope in some way with their IO pages going to the zero page.
+ *
+ */
+void rdma_umap_priv_init(struct rdma_umap_priv *priv,
+			 struct vm_area_struct *vma,
+			 struct rdma_user_mmap_entry *entry)
+{
+	struct ib_uverbs_file *ufile = vma->vm_file->private_data;
+
+	priv->vma = vma;
+	if (entry) {
+		kref_get(&entry->ref);
+		priv->entry = entry;
+	}
+	vma->vm_private_data = priv;
+	/* vm_ops is setup in ib_uverbs_mmap() to avoid module dependencies */
+
+	mutex_lock(&ufile->umap_lock);
+	list_add(&priv->list, &ufile->umaps);
+	mutex_unlock(&ufile->umap_lock);
+}
+EXPORT_SYMBOL(rdma_umap_priv_init);
+
+/**
+ * rdma_user_mmap_io() - Map IO memory into a process
+ *
+ * @ucontext: associated user context
+ * @vma: the vma related to the current mmap call
+ * @pfn: pfn to map
+ * @size: size to map
+ * @prot: pgprot to use in remap call
+ * @entry: mmap_entry retrieved from rdma_user_mmap_entry_get(), or NULL
+ *         if mmap_entry is not used by the driver
+ *
+ * This is to be called by drivers as part of their mmap() functions if they
+ * wish to send something like PCI-E BAR memory to userspace.
+ *
+ * Return -EINVAL on wrong flags or size, -EAGAIN on failure to map. 0 on
+ * success.
+ */
+int rdma_user_mmap_io(struct ib_ucontext *ucontext, struct vm_area_struct *vma,
+		      unsigned long pfn, unsigned long size, pgprot_t prot,
+		      struct rdma_user_mmap_entry *entry)
+{
+	struct ib_uverbs_file *ufile = ucontext->ufile;
+	struct rdma_umap_priv *priv;
+
+	if (!(vma->vm_flags & VM_SHARED))
+		return -EINVAL;
+
+	if (vma->vm_end - vma->vm_start != size)
+		return -EINVAL;
+
+	/* Driver is using this wrong, must be called by ib_uverbs_mmap */
+	if (WARN_ON(!vma->vm_file ||
+		    vma->vm_file->private_data != ufile))
+		return -EINVAL;
+	lockdep_assert_held(&ufile->device->disassociate_srcu);
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	vma->vm_page_prot = prot;
+	if (io_remap_pfn_range(vma, vma->vm_start, pfn, size, prot)) {
+		kfree(priv);
+		return -EAGAIN;
+	}
+
+	rdma_umap_priv_init(priv, vma, entry);
+	return 0;
+}
+EXPORT_SYMBOL(rdma_user_mmap_io);
+
+/**
+ * rdma_user_mmap_entry_get_pgoff() - Get an entry from the mmap_xa
+ *
+ * @ucontext: associated user context
+ * @pgoff: The mmap offset >> PAGE_SHIFT
+ *
+ * This function is called when a user tries to mmap with an offset (returned
+ * by rdma_user_mmap_get_offset()) it initially received from the driver. The
+ * rdma_user_mmap_entry was created by the function
+ * rdma_user_mmap_entry_insert().  This function increases the refcnt of the
+ * entry so that it won't be deleted from the xarray in the meantime.
+ *
+ * Return an reference to an entry if exists or NULL if there is no
+ * match. rdma_user_mmap_entry_put() must be called to put the reference.
+ */
+struct rdma_user_mmap_entry *
+rdma_user_mmap_entry_get_pgoff(struct ib_ucontext *ucontext,
+			       unsigned long pgoff)
+{
+	struct rdma_user_mmap_entry *entry;
+
+	if (pgoff > U32_MAX)
+		return NULL;
+
+	xa_lock(&ucontext->mmap_xa);
+
+	entry = xa_load(&ucontext->mmap_xa, pgoff);
+
+	/*
+	 * If refcount is zero, entry is already being deleted, driver_removed
+	 * indicates that the no further mmaps are possible and we waiting for
+	 * the active VMAs to be closed.
+	 */
+	if (!entry || entry->start_pgoff != pgoff || entry->driver_removed ||
+	    !kref_get_unless_zero(&entry->ref))
+		goto err;
+
+	xa_unlock(&ucontext->mmap_xa);
+
+	ibdev_dbg(ucontext->device, "mmap: pgoff[%#lx] npages[%#zx] returned\n",
+		  pgoff, entry->npages);
+
+	return entry;
+
+err:
+	xa_unlock(&ucontext->mmap_xa);
+	return NULL;
+}
+EXPORT_SYMBOL(rdma_user_mmap_entry_get_pgoff);
+
+/**
+ * rdma_user_mmap_entry_get() - Get an entry from the mmap_xa
+ *
+ * @ucontext: associated user context
+ * @vma: the vma being mmap'd into
+ *
+ * This function is like rdma_user_mmap_entry_get_pgoff() except that it also
+ * checks that the VMA is correct.
+ */
+struct rdma_user_mmap_entry *
+rdma_user_mmap_entry_get(struct ib_ucontext *ucontext,
+			 struct vm_area_struct *vma)
+{
+	struct rdma_user_mmap_entry *entry;
+
+	if (!(vma->vm_flags & VM_SHARED))
+		return NULL;
+	entry = rdma_user_mmap_entry_get_pgoff(ucontext, vma->vm_pgoff);
+	if (!entry)
+		return NULL;
+	if (entry->npages * PAGE_SIZE != vma->vm_end - vma->vm_start) {
+		rdma_user_mmap_entry_put(entry);
+		return NULL;
+	}
+	return entry;
+}
+EXPORT_SYMBOL(rdma_user_mmap_entry_get);
+
+static void rdma_user_mmap_entry_free(struct kref *kref)
+{
+	struct rdma_user_mmap_entry *entry =
+		container_of(kref, struct rdma_user_mmap_entry, ref);
+	struct ib_ucontext *ucontext = entry->ucontext;
+	unsigned long i;
+
+	/*
+	 * Erase all entries occupied by this single entry, this is deferred
+	 * until all VMA are closed so that the mmap offsets remain unique.
+	 */
+	xa_lock(&ucontext->mmap_xa);
+	for (i = 0; i < entry->npages; i++)
+		__xa_erase(&ucontext->mmap_xa, entry->start_pgoff + i);
+	xa_unlock(&ucontext->mmap_xa);
+
+	ibdev_dbg(ucontext->device, "mmap: pgoff[%#lx] npages[%#zx] removed\n",
+		  entry->start_pgoff, entry->npages);
+
+	if (ucontext->device->ops.mmap_free)
+		ucontext->device->ops.mmap_free(entry);
+}
+
+/**
+ * rdma_user_mmap_entry_put() - Drop reference to the mmap entry
+ *
+ * @entry: an entry in the mmap_xa
+ *
+ * This function is called when the mapping is closed if it was
+ * an io mapping or when the driver is done with the entry for
+ * some other reason.
+ * Should be called after rdma_user_mmap_entry_get was called
+ * and entry is no longer needed. This function will erase the
+ * entry and free it if its refcnt reaches zero.
+ */
+void rdma_user_mmap_entry_put(struct rdma_user_mmap_entry *entry)
+{
+	kref_put(&entry->ref, rdma_user_mmap_entry_free);
+}
+EXPORT_SYMBOL(rdma_user_mmap_entry_put);
+
+/**
+ * rdma_user_mmap_entry_remove() - Drop reference to entry and
+ *				   mark it as unmmapable
+ *
+ * @entry: the entry to insert into the mmap_xa
+ *
+ * Drivers can call this to prevent userspace from creating more mappings for
+ * entry, however existing mmaps continue to exist and ops->mmap_free() will
+ * not be called until all user mmaps are destroyed.
+ */
+void rdma_user_mmap_entry_remove(struct rdma_user_mmap_entry *entry)
+{
+	if (!entry)
+		return;
+
+	entry->driver_removed = true;
+	kref_put(&entry->ref, rdma_user_mmap_entry_free);
+}
+EXPORT_SYMBOL(rdma_user_mmap_entry_remove);
+
+/**
+ * rdma_user_mmap_entry_insert() - Insert an entry to the mmap_xa
+ *
+ * @ucontext: associated user context.
+ * @entry: the entry to insert into the mmap_xa
+ * @length: length of the address that will be mmapped
+ *
+ * This function should be called by drivers that use the rdma_user_mmap
+ * interface for implementing their mmap syscall A database of mmap offsets is
+ * handled in the core and helper functions are provided to insert entries
+ * into the database and extract entries when the user calls mmap with the
+ * given offset.  The function allocates a unique page offset that should be
+ * provided to user, the user will use the offset to retrieve information such
+ * as address to be mapped and how.
+ *
+ * Return: 0 on success and -ENOMEM on failure
+ */
+int rdma_user_mmap_entry_insert(struct ib_ucontext *ucontext,
+				struct rdma_user_mmap_entry *entry,
+				size_t length)
+{
+	struct ib_uverbs_file *ufile = ucontext->ufile;
+	XA_STATE(xas, &ucontext->mmap_xa, 0);
+	u32 xa_first, xa_last, npages;
+	int err;
+	u32 i;
+
+	if (!entry)
+		return -EINVAL;
+
+	kref_init(&entry->ref);
+	entry->ucontext = ucontext;
+
+	/*
+	 * We want the whole allocation to be done without interruption from a
+	 * different thread. The allocation requires finding a free range and
+	 * storing. During the xa_insert the lock could be released, possibly
+	 * allowing another thread to choose the same range.
+	 */
+	mutex_lock(&ufile->umap_lock);
+
+	xa_lock(&ucontext->mmap_xa);
+
+	/* We want to find an empty range */
+	npages = (u32)DIV_ROUND_UP(length, PAGE_SIZE);
+	entry->npages = npages;
+	while (true) {
+		/* First find an empty index */
+		xas_find_marked(&xas, U32_MAX, XA_FREE_MARK);
+		if (xas.xa_node == XAS_RESTART)
+			goto err_unlock;
+
+		xa_first = xas.xa_index;
+
+		/* Is there enough room to have the range? */
+		if (check_add_overflow(xa_first, npages, &xa_last))
+			goto err_unlock;
+
+		/*
+		 * Now look for the next present entry. If an entry doesn't
+		 * exist, we found an empty range and can proceed.
+		 */
+		xas_next_entry(&xas, xa_last - 1);
+		if (xas.xa_node == XAS_BOUNDS || xas.xa_index >= xa_last)
+			break;
+	}
+
+	for (i = xa_first; i < xa_last; i++) {
+		err = __xa_insert(&ucontext->mmap_xa, i, entry, GFP_KERNEL);
+		if (err)
+			goto err_undo;
+	}
+
+	/*
+	 * Internally the kernel uses a page offset, in libc this is a byte
+	 * offset. Drivers should not return pgoff to userspace.
+	 */
+	entry->start_pgoff = xa_first;
+	xa_unlock(&ucontext->mmap_xa);
+	mutex_unlock(&ufile->umap_lock);
+
+	ibdev_dbg(ucontext->device, "mmap: pgoff[%#lx] npages[%#x] inserted\n",
+		  entry->start_pgoff, npages);
+
+	return 0;
+
+err_undo:
+	for (; i > xa_first; i--)
+		__xa_erase(&ucontext->mmap_xa, i - 1);
+
+err_unlock:
+	xa_unlock(&ucontext->mmap_xa);
+	mutex_unlock(&ufile->umap_lock);
+	return -ENOMEM;
+}
+EXPORT_SYMBOL(rdma_user_mmap_entry_insert);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/core/ib_peer_mem.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/core/ib_peer_mem.h
@@ -0,0 +1,58 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
+/*
+ * Copyright (c) 2014-2020,  Mellanox Technologies. All rights reserved.
+ */
+#ifndef RDMA_IB_PEER_MEM_H
+#define RDMA_IB_PEER_MEM_H
+
+#include <rdma/peer_mem.h>
+#include <linux/kobject.h>
+#include <linux/xarray.h>
+#include <rdma/ib_umem.h>
+
+struct ib_peer_memory_statistics {
+	atomic64_t num_alloc_mrs;
+	atomic64_t num_dealloc_mrs;
+	atomic64_t num_reg_pages;
+	atomic64_t num_dereg_pages;
+	atomic64_t num_reg_bytes;
+	atomic64_t num_dereg_bytes;
+	unsigned long num_free_callbacks;
+};
+
+struct ib_peer_memory_client {
+	struct kobject kobj;
+	refcount_t usecnt;
+	struct completion usecnt_zero;
+	const struct peer_memory_client *peer_mem;
+	struct list_head core_peer_list;
+	struct ib_peer_memory_statistics stats;
+	struct xarray umem_xa;
+	u32 xa_cyclic_next;
+	bool invalidation_required;
+};
+
+enum ib_umem_mapped_state {
+	UMEM_PEER_UNMAPPED,
+	UMEM_PEER_MAPPED,
+	UMEM_PEER_INVALIDATED,
+};
+
+struct ib_umem_peer {
+	struct ib_umem umem;
+	struct kref kref;
+	/* peer memory that manages this umem */
+	struct ib_peer_memory_client *ib_peer_client;
+	void *peer_client_context;
+	umem_invalidate_func_t invalidation_func;
+	void *invalidation_private;
+	struct mutex mapping_lock;
+	enum ib_umem_mapped_state mapped_state;
+	u32 xa_id;
+};
+
+struct ib_umem *ib_peer_umem_get(struct ib_umem *old_umem, int old_ret,
+				 unsigned long peer_mem_flags);
+void ib_peer_umem_release(struct ib_umem *umem);
+
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/core/iwcm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/core/iwcm.c
@@ -159,8 +159,10 @@
 {
 	struct list_head *e, *tmp;
 
-	list_for_each_safe(e, tmp, &cm_id_priv->work_free_list)
+	list_for_each_safe(e, tmp, &cm_id_priv->work_free_list) {
+		list_del(e);
 		kfree(list_entry(e, struct iwcm_work, free_list));
+	}
 }
 
 static int alloc_work_entries(struct iwcm_id_private *cm_id_priv, int count)
@@ -368,8 +370,10 @@
  *
  * Clean up all resources associated with the connection and release
  * the initial reference taken by iw_create_cm_id.
+ *
+ * Returns true if and only if the last cm_id_priv reference has been dropped.
  */
-static void destroy_cm_id(struct iw_cm_id *cm_id)
+static bool destroy_cm_id(struct iw_cm_id *cm_id)
 {
 	struct iwcm_id_private *cm_id_priv;
 	struct ib_qp *qp;
@@ -439,7 +443,7 @@
 		iwpm_remove_mapping(&cm_id->local_addr, RDMA_NL_IWCM);
 	}
 
-	(void)iwcm_deref_id(cm_id_priv);
+	return iwcm_deref_id(cm_id_priv);
 }
 
 /*
@@ -450,7 +454,8 @@
  */
 void iw_destroy_cm_id(struct iw_cm_id *cm_id)
 {
-	destroy_cm_id(cm_id);
+	if (!destroy_cm_id(cm_id))
+		flush_workqueue(iwcm_wq);
 }
 EXPORT_SYMBOL(iw_destroy_cm_id);
 
@@ -1034,7 +1039,7 @@
 		if (!test_bit(IWCM_F_DROP_EVENTS, &cm_id_priv->flags)) {
 			ret = process_event(cm_id_priv, &levent);
 			if (ret)
-				destroy_cm_id(&cm_id_priv->id);
+				WARN_ON_ONCE(destroy_cm_id(&cm_id_priv->id));
 		} else
 			pr_debug("dropping event %d\n", levent.event);
 		if (iwcm_deref_id(cm_id_priv))
@@ -1185,29 +1190,34 @@
 
 	ret = iwpm_init(RDMA_NL_IWCM);
 	if (ret)
-		pr_err("iw_cm: couldn't init iwpm\n");
-	else
-		rdma_nl_register(RDMA_NL_IWCM, iwcm_nl_cb_table);
-	iwcm_wq = alloc_ordered_workqueue("iw_cm_wq", 0);
+		return ret;
+
+	iwcm_wq = alloc_ordered_workqueue("iw_cm_wq", WQ_MEM_RECLAIM);
 	if (!iwcm_wq)
-		return -ENOMEM;
+		goto err_alloc;
 
 	iwcm_ctl_table_hdr = register_net_sysctl(&init_net, "net/iw_cm",
 						 iwcm_ctl_table);
 	if (!iwcm_ctl_table_hdr) {
 		pr_err("iw_cm: couldn't register sysctl paths\n");
-		destroy_workqueue(iwcm_wq);
-		return -ENOMEM;
+		goto err_sysctl;
 	}
 
+	rdma_nl_register(RDMA_NL_IWCM, iwcm_nl_cb_table);
 	return 0;
+
+err_sysctl:
+	destroy_workqueue(iwcm_wq);
+err_alloc:
+	iwpm_exit(RDMA_NL_IWCM);
+	return -ENOMEM;
 }
 
 static void __exit iw_cm_cleanup(void)
 {
+	rdma_nl_unregister(RDMA_NL_IWCM);
 	unregister_net_sysctl_table(iwcm_ctl_table_hdr);
 	destroy_workqueue(iwcm_wq);
-	rdma_nl_unregister(RDMA_NL_IWCM);
 	iwpm_exit(RDMA_NL_IWCM);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/core/mad.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/core/mad.c
@@ -639,10 +639,10 @@
 	xa_erase(&ib_mad_clients, mad_agent_priv->agent.hi_tid);
 
 	flush_workqueue(port_priv->wq);
-	ib_cancel_rmpp_recvs(mad_agent_priv);
 
 	deref_mad_agent(mad_agent_priv);
 	wait_for_completion(&mad_agent_priv->comp);
+	ib_cancel_rmpp_recvs(mad_agent_priv);
 
 	ib_mad_agent_security_cleanup(&mad_agent_priv->agent);
 
@@ -1357,7 +1357,7 @@
 			spin_lock_irqsave(&mad_agent_priv->lock, flags);
 			list_del(&mad_send_wr->agent_list);
 			spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
-			atomic_dec(&mad_agent_priv->refcount);
+			deref_mad_agent(mad_agent_priv);
 			goto error;
 		}
 	}
@@ -2059,7 +2059,7 @@
 				mad_agent_priv->agent.recv_handler(
 						&mad_agent_priv->agent, NULL,
 						mad_recv_wc);
-				atomic_dec(&mad_agent_priv->refcount);
+				deref_mad_agent(mad_agent_priv);
 			} else {
 				/* not user rmpp, revert to normal behavior and
 				 * drop the mad */
@@ -2076,7 +2076,7 @@
 					&mad_agent_priv->agent,
 					&mad_send_wr->send_buf,
 					mad_recv_wc);
-			atomic_dec(&mad_agent_priv->refcount);
+			deref_mad_agent(mad_agent_priv);
 
 			mad_send_wc.status = IB_WC_SUCCESS;
 			mad_send_wc.vendor_err = 0;
@@ -2672,7 +2672,7 @@
 		list_del(&mad_send_wr->agent_list);
 		mad_agent_priv->agent.send_handler(&mad_agent_priv->agent,
 						   &mad_send_wc);
-		atomic_dec(&mad_agent_priv->refcount);
+		deref_mad_agent(mad_agent_priv);
 	}
 }
 
@@ -2810,7 +2810,7 @@
 						&local->mad_send_wr->send_buf,
 						&local->mad_priv->header.recv_wc);
 			spin_lock_irqsave(&recv_mad_agent->lock, flags);
-			atomic_dec(&recv_mad_agent->refcount);
+			deref_mad_agent(recv_mad_agent);
 			spin_unlock_irqrestore(&recv_mad_agent->lock, flags);
 		}
 
@@ -2827,7 +2827,7 @@
 						   &mad_send_wc);
 
 		spin_lock_irqsave(&mad_agent_priv->lock, flags);
-		atomic_dec(&mad_agent_priv->refcount);
+		deref_mad_agent(mad_agent_priv);
 		if (free_mad)
 			kfree(local->mad_priv);
 		kfree(local);
@@ -2873,14 +2873,16 @@
 
 static void timeout_sends(struct work_struct *work)
 {
+	struct ib_mad_send_wr_private *mad_send_wr, *n;
 	struct ib_mad_agent_private *mad_agent_priv;
-	struct ib_mad_send_wr_private *mad_send_wr;
 	struct ib_mad_send_wc mad_send_wc;
+	struct list_head local_list;
 	unsigned long flags, delay;
 
 	mad_agent_priv = container_of(work, struct ib_mad_agent_private,
 				      timed_work.work);
 	mad_send_wc.vendor_err = 0;
+	INIT_LIST_HEAD(&local_list);
 
 	spin_lock_irqsave(&mad_agent_priv->lock, flags);
 	while (!list_empty(&mad_agent_priv->wait_list)) {
@@ -2898,13 +2900,16 @@
 			break;
 		}
 
-		list_del(&mad_send_wr->agent_list);
+		list_del_init(&mad_send_wr->agent_list);
 		if (mad_send_wr->status == IB_WC_SUCCESS &&
 		    !retry_send(mad_send_wr))
 			continue;
 
-		spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
+		list_add_tail(&mad_send_wr->agent_list, &local_list);
+	}
+	spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
 
+	list_for_each_entry_safe(mad_send_wr, n, &local_list, agent_list) {
 		if (mad_send_wr->status == IB_WC_SUCCESS)
 			mad_send_wc.status = IB_WC_RESP_TIMEOUT_ERR;
 		else
@@ -2912,11 +2917,8 @@
 		mad_send_wc.send_buf = &mad_send_wr->send_buf;
 		mad_agent_priv->agent.send_handler(&mad_agent_priv->agent,
 						   &mad_send_wc);
-
-		atomic_dec(&mad_agent_priv->refcount);
-		spin_lock_irqsave(&mad_agent_priv->lock, flags);
+		deref_mad_agent(mad_agent_priv);
 	}
-	spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
 }
 
 /*
@@ -2926,11 +2928,11 @@
 				    struct ib_mad_private *mad)
 {
 	unsigned long flags;
-	int post, ret;
 	struct ib_mad_private *mad_priv;
 	struct ib_sge sg_list;
 	struct ib_recv_wr recv_wr;
 	struct ib_mad_queue *recv_queue = &qp_info->recv_queue;
+	int ret = 0;
 
 	/* Initialize common scatter list fields */
 	sg_list.lkey = qp_info->port_priv->pd->local_dma_lkey;
@@ -2940,7 +2942,7 @@
 	recv_wr.sg_list = &sg_list;
 	recv_wr.num_sge = 1;
 
-	do {
+	while (true) {
 		/* Allocate and map receive buffer */
 		if (mad) {
 			mad_priv = mad;
@@ -2948,10 +2950,8 @@
 		} else {
 			mad_priv = alloc_mad_private(port_mad_size(qp_info->port_priv),
 						     GFP_ATOMIC);
-			if (!mad_priv) {
-				ret = -ENOMEM;
-				break;
-			}
+			if (!mad_priv)
+				return -ENOMEM;
 		}
 		sg_list.length = mad_priv_dma_size(mad_priv);
 		sg_list.addr = ib_dma_map_single(qp_info->port_priv->device,
@@ -2961,35 +2961,40 @@
 		if (unlikely(ib_dma_mapping_error(qp_info->port_priv->device,
 						  sg_list.addr))) {
 			ret = -ENOMEM;
-			break;
+			goto free_mad_priv;
 		}
 		mad_priv->header.mapping = sg_list.addr;
 		mad_priv->header.mad_list.mad_queue = recv_queue;
 		mad_priv->header.mad_list.cqe.done = ib_mad_recv_done;
 		recv_wr.wr_cqe = &mad_priv->header.mad_list.cqe;
-
-		/* Post receive WR */
 		spin_lock_irqsave(&recv_queue->lock, flags);
-		post = (++recv_queue->count < recv_queue->max_active);
-		list_add_tail(&mad_priv->header.mad_list.list, &recv_queue->list);
+		if (recv_queue->count >= recv_queue->max_active) {
+			/* Fully populated the receive queue */
+			spin_unlock_irqrestore(&recv_queue->lock, flags);
+			break;
+		}
+		recv_queue->count++;
+		list_add_tail(&mad_priv->header.mad_list.list,
+			      &recv_queue->list);
 		spin_unlock_irqrestore(&recv_queue->lock, flags);
+
 		ret = ib_post_recv(qp_info->qp, &recv_wr, NULL);
 		if (ret) {
 			spin_lock_irqsave(&recv_queue->lock, flags);
 			list_del(&mad_priv->header.mad_list.list);
 			recv_queue->count--;
 			spin_unlock_irqrestore(&recv_queue->lock, flags);
-			ib_dma_unmap_single(qp_info->port_priv->device,
-					    mad_priv->header.mapping,
-					    mad_priv_dma_size(mad_priv),
-					    DMA_FROM_DEVICE);
-			kfree(mad_priv);
 			dev_err(&qp_info->port_priv->device->dev,
 				"ib_post_recv failed: %d\n", ret);
 			break;
 		}
-	} while (post);
+	}
 
+	ib_dma_unmap_single(qp_info->port_priv->device,
+			    mad_priv->header.mapping,
+			    mad_priv_dma_size(mad_priv), DMA_FROM_DEVICE);
+free_mad_priv:
+	kfree(mad_priv);
 	return ret;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/core/nldev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/core/nldev.c
@@ -493,7 +493,7 @@
 	struct rdma_cm_id *cm_id = &id_priv->id;
 
 	if (port && port != cm_id->port_num)
-		return 0;
+		return -EAGAIN;
 
 	if (cm_id->port_num &&
 	    nla_put_u32(msg, RDMA_NLDEV_ATTR_PORT_INDEX, cm_id->port_num))
@@ -694,6 +694,8 @@
 	int ret = 0;
 
 	table_attr = nla_nest_start(msg, RDMA_NLDEV_ATTR_RES_QP);
+	if (!table_attr)
+		return -EMSGSIZE;
 
 	rt = &counter->device->res[RDMA_RESTRACK_QP];
 	xa_lock(&rt->xa);
@@ -702,9 +704,6 @@
 			continue;
 
 		qp = container_of(res, struct ib_qp, res);
-		if (qp->qp_type == IB_QPT_RAW_PACKET && !capable(CAP_NET_RAW))
-			continue;
-
 		if (!qp->counter || (qp->counter->id != counter->id))
 			continue;
 
@@ -863,6 +862,10 @@
 
 		nla_strlcpy(name, tb[RDMA_NLDEV_ATTR_DEV_NAME],
 			    IB_DEVICE_NAME_MAX);
+		if (strlen(name) == 0) {
+			err = -EINVAL;
+			goto done;
+		}
 		err = ib_device_rename(device, name);
 		goto done;
 	}
@@ -1244,10 +1247,10 @@
 
 	has_cap_net_admin = netlink_capable(skb, CAP_NET_ADMIN);
 	ret = fe->fill_res_func(msg, has_cap_net_admin, res, port);
-	rdma_restrack_put(res);
 	if (ret)
 		goto err_free;
 
+	rdma_restrack_put(res);
 	nlmsg_end(msg, nlh);
 	ib_device_put(device);
 	return rdma_nl_unicast(sock_net(skb->sk), msg, NETLINK_CB(skb).portid);
@@ -1468,7 +1471,7 @@
 
 	nla_strlcpy(ibdev_name, tb[RDMA_NLDEV_ATTR_DEV_NAME],
 		    sizeof(ibdev_name));
-	if (strchr(ibdev_name, '%'))
+	if (strchr(ibdev_name, '%') || strlen(ibdev_name) == 0)
 		return -EINVAL;
 
 	nla_strlcpy(type, tb[RDMA_NLDEV_ATTR_LINK_TYPE], sizeof(type));
@@ -1711,6 +1714,8 @@
 		if (ret)
 			goto err_msg;
 	} else {
+		if (!tb[RDMA_NLDEV_ATTR_RES_LQPN])
+			goto err_msg;
 		qpn = nla_get_u32(tb[RDMA_NLDEV_ATTR_RES_LQPN]);
 		if (tb[RDMA_NLDEV_ATTR_STAT_COUNTER_ID]) {
 			cntn = nla_get_u32(tb[RDMA_NLDEV_ATTR_STAT_COUNTER_ID]);
@@ -2075,6 +2080,7 @@
 	},
 	[RDMA_NLDEV_CMD_SYS_SET] = {
 		.doit = nldev_set_sys_set_doit,
+		.flags = RDMA_NL_ADMIN_PERM,
 	},
 	[RDMA_NLDEV_CMD_STAT_SET] = {
 		.doit = nldev_stat_set_doit,
@@ -2095,7 +2101,7 @@
 	rdma_nl_register(RDMA_NL_NLDEV, nldev_cb_table);
 }
 
-void __exit nldev_exit(void)
+void nldev_exit(void)
 {
 	rdma_nl_unregister(RDMA_NL_NLDEV);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/core/peer_mem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/core/peer_mem.c
@@ -0,0 +1,559 @@
+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+/*
+ * Copyright (c) 2014-2020,  Mellanox Technologies. All rights reserved.
+ */
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_umem.h>
+#include <linux/sched/mm.h>
+#include "ib_peer_mem.h"
+static DEFINE_MUTEX(peer_memory_mutex);
+static LIST_HEAD(peer_memory_list);
+static struct kobject *peers_kobj;
+#define PEER_NO_INVALIDATION_ID U32_MAX
+static int ib_invalidate_peer_memory(void *reg_handle, u64 core_context);
+struct peer_mem_attribute {
+	struct attribute attr;
+	ssize_t (*show)(struct ib_peer_memory_client *ib_peer_client,
+			struct peer_mem_attribute *attr, char *buf);
+	ssize_t (*store)(struct ib_peer_memory_client *ib_peer_client,
+			 struct peer_mem_attribute *attr, const char *buf,
+			 size_t count);
+};
+
+#define PEER_ATTR_RO(_name)                                                    \
+	struct peer_mem_attribute peer_attr_ ## _name = __ATTR_RO(_name)
+
+static ssize_t version_show(struct ib_peer_memory_client *ib_peer_client,
+			    struct peer_mem_attribute *attr, char *buf)
+{
+	return scnprintf(buf, PAGE_SIZE, "%s\n",
+			 ib_peer_client->peer_mem->version);
+}
+
+static PEER_ATTR_RO(version);
+static ssize_t num_alloc_mrs_show(struct ib_peer_memory_client *ib_peer_client,
+				  struct peer_mem_attribute *attr, char *buf)
+{
+	return scnprintf(
+		buf, PAGE_SIZE, "%llu\n",
+		(u64)atomic64_read(&ib_peer_client->stats.num_alloc_mrs));
+}
+
+static PEER_ATTR_RO(num_alloc_mrs);
+static ssize_t
+num_dealloc_mrs_show(struct ib_peer_memory_client *ib_peer_client,
+		     struct peer_mem_attribute *attr, char *buf)
+{
+	return scnprintf(
+		buf, PAGE_SIZE, "%llu\n",
+		(u64)atomic64_read(&ib_peer_client->stats.num_dealloc_mrs));
+}
+
+static PEER_ATTR_RO(num_dealloc_mrs);
+static ssize_t num_reg_pages_show(struct ib_peer_memory_client *ib_peer_client,
+				  struct peer_mem_attribute *attr, char *buf)
+{
+	return scnprintf(
+		buf, PAGE_SIZE, "%llu\n",
+		(u64)atomic64_read(&ib_peer_client->stats.num_reg_pages));
+}
+
+static PEER_ATTR_RO(num_reg_pages);
+static ssize_t
+num_dereg_pages_show(struct ib_peer_memory_client *ib_peer_client,
+		     struct peer_mem_attribute *attr, char *buf)
+{
+	return scnprintf(
+		buf, PAGE_SIZE, "%llu\n",
+		(u64)atomic64_read(&ib_peer_client->stats.num_dereg_pages));
+}
+
+static PEER_ATTR_RO(num_dereg_pages);
+static ssize_t num_reg_bytes_show(struct ib_peer_memory_client *ib_peer_client,
+				  struct peer_mem_attribute *attr, char *buf)
+{
+	return scnprintf(
+		buf, PAGE_SIZE, "%llu\n",
+		(u64)atomic64_read(&ib_peer_client->stats.num_reg_bytes));
+}
+
+static PEER_ATTR_RO(num_reg_bytes);
+static ssize_t
+num_dereg_bytes_show(struct ib_peer_memory_client *ib_peer_client,
+		     struct peer_mem_attribute *attr, char *buf)
+{
+	return scnprintf(
+		buf, PAGE_SIZE, "%llu\n",
+		(u64)atomic64_read(&ib_peer_client->stats.num_dereg_bytes));
+}
+
+static PEER_ATTR_RO(num_dereg_bytes);
+static ssize_t
+num_free_callbacks_show(struct ib_peer_memory_client *ib_peer_client,
+			struct peer_mem_attribute *attr, char *buf)
+{
+	return scnprintf(buf, PAGE_SIZE, "%lu\n",
+			 ib_peer_client->stats.num_free_callbacks);
+}
+
+static PEER_ATTR_RO(num_free_callbacks);
+static struct attribute *peer_mem_attrs[] = {
+			&peer_attr_version.attr,
+			&peer_attr_num_alloc_mrs.attr,
+			&peer_attr_num_dealloc_mrs.attr,
+			&peer_attr_num_reg_pages.attr,
+			&peer_attr_num_dereg_pages.attr,
+			&peer_attr_num_reg_bytes.attr,
+			&peer_attr_num_dereg_bytes.attr,
+			&peer_attr_num_free_callbacks.attr,
+			NULL,
+};
+
+static const struct attribute_group peer_mem_attr_group = {
+	.attrs = peer_mem_attrs,
+};
+
+static ssize_t peer_attr_show(struct kobject *kobj, struct attribute *attr,
+			      char *buf)
+{
+	struct peer_mem_attribute *peer_attr =
+		container_of(attr, struct peer_mem_attribute, attr);
+	if (!peer_attr->show)
+		return -EIO;
+	return peer_attr->show(container_of(kobj, struct ib_peer_memory_client,
+					    kobj),
+			       peer_attr, buf);
+}
+
+static const struct sysfs_ops peer_mem_sysfs_ops = {
+	.show = peer_attr_show,
+};
+
+static void ib_peer_memory_client_release(struct kobject *kobj)
+{
+	struct ib_peer_memory_client *ib_peer_client =
+		container_of(kobj, struct ib_peer_memory_client, kobj);
+	kfree(ib_peer_client);
+}
+
+static struct kobj_type peer_mem_type = {
+	.sysfs_ops = &peer_mem_sysfs_ops,
+	.release = ib_peer_memory_client_release,
+};
+
+static int ib_memory_peer_check_mandatory(const struct peer_memory_client
+						     *peer_client)
+{
+#define PEER_MEM_MANDATORY_FUNC(x) {offsetof(struct peer_memory_client, x), #x}
+	int i;
+	static const struct {
+		size_t offset;
+		char *name;
+	} mandatory_table[] = {
+		PEER_MEM_MANDATORY_FUNC(acquire),
+		PEER_MEM_MANDATORY_FUNC(get_pages),
+		PEER_MEM_MANDATORY_FUNC(put_pages),
+		PEER_MEM_MANDATORY_FUNC(dma_map),
+		PEER_MEM_MANDATORY_FUNC(dma_unmap),
+	};
+	for (i = 0; i < ARRAY_SIZE(mandatory_table); ++i) {
+		if (!*(void **)((void *)peer_client +
+				mandatory_table[i].offset)) {
+			pr_err("Peer memory %s is missing mandatory function %s\n",
+			       peer_client->name, mandatory_table[i].name);
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
+void *
+ib_register_peer_memory_client(const struct peer_memory_client *peer_client,
+			       invalidate_peer_memory *invalidate_callback)
+{
+	struct ib_peer_memory_client *ib_peer_client;
+	int ret;
+	if (ib_memory_peer_check_mandatory(peer_client))
+		return NULL;
+	ib_peer_client = kzalloc(sizeof(*ib_peer_client), GFP_KERNEL);
+	if (!ib_peer_client)
+		return NULL;
+	kobject_init(&ib_peer_client->kobj, &peer_mem_type);
+	refcount_set(&ib_peer_client->usecnt, 1);
+	init_completion(&ib_peer_client->usecnt_zero);
+	ib_peer_client->peer_mem = peer_client;
+	xa_init_flags(&ib_peer_client->umem_xa, XA_FLAGS_ALLOC);
+	/*
+	 * If the peer wants the invalidation_callback then all memory users
+	 * linked to that peer must support invalidation.
+	 */
+	if (invalidate_callback) {
+		*invalidate_callback = ib_invalidate_peer_memory;
+		ib_peer_client->invalidation_required = true;
+	}
+	mutex_lock(&peer_memory_mutex);
+	if (!peers_kobj) {
+		/* Created under /sys/kernel/mm */
+		peers_kobj = kobject_create_and_add("memory_peers", mm_kobj);
+		if (!peers_kobj)
+			goto err_unlock;
+	}
+	ret = kobject_add(&ib_peer_client->kobj, peers_kobj, peer_client->name);
+	if (ret)
+		goto err_parent;
+	ret = sysfs_create_group(&ib_peer_client->kobj,
+				 &peer_mem_attr_group);
+	if (ret)
+		goto err_parent;
+	list_add_tail(&ib_peer_client->core_peer_list, &peer_memory_list);
+	mutex_unlock(&peer_memory_mutex);
+	return ib_peer_client;
+err_parent:
+	if (list_empty(&peer_memory_list)) {
+		kobject_put(peers_kobj);
+		peers_kobj = NULL;
+	}
+err_unlock:
+	mutex_unlock(&peer_memory_mutex);
+	kobject_put(&ib_peer_client->kobj);
+	return NULL;
+}
+EXPORT_SYMBOL(ib_register_peer_memory_client);
+
+void ib_unregister_peer_memory_client(void *reg_handle)
+{
+	struct ib_peer_memory_client *ib_peer_client = reg_handle;
+	mutex_lock(&peer_memory_mutex);
+	list_del(&ib_peer_client->core_peer_list);
+	if (list_empty(&peer_memory_list)) {
+		kobject_put(peers_kobj);
+		peers_kobj = NULL;
+	}
+	mutex_unlock(&peer_memory_mutex);
+	/*
+	 * Wait for all umems to be destroyed before returning. Once
+	 * ib_unregister_peer_memory_client() returns no umems will call any
+	 * peer_mem ops.
+	 */
+	if (refcount_dec_and_test(&ib_peer_client->usecnt))
+		complete(&ib_peer_client->usecnt_zero);
+	wait_for_completion(&ib_peer_client->usecnt_zero);
+	kobject_put(&ib_peer_client->kobj);
+}
+EXPORT_SYMBOL(ib_unregister_peer_memory_client);
+
+static struct ib_peer_memory_client *
+ib_get_peer_client(unsigned long addr, size_t size,
+		   unsigned long peer_mem_flags, void **peer_client_context)
+{
+	struct ib_peer_memory_client *ib_peer_client;
+	int ret = 0;
+	mutex_lock(&peer_memory_mutex);
+	list_for_each_entry(ib_peer_client, &peer_memory_list,
+			    core_peer_list) {
+		if (ib_peer_client->invalidation_required &&
+		    (!(peer_mem_flags & IB_PEER_MEM_INVAL_SUPP)))
+			continue;
+		ret = ib_peer_client->peer_mem->acquire(addr, size, NULL, NULL,
+							peer_client_context);
+		if (ret > 0) {
+			refcount_inc(&ib_peer_client->usecnt);
+			mutex_unlock(&peer_memory_mutex);
+			return ib_peer_client;
+		}
+	}
+	mutex_unlock(&peer_memory_mutex);
+	return NULL;
+}
+
+static void ib_put_peer_client(struct ib_peer_memory_client *ib_peer_client,
+			       void *peer_client_context)
+{
+	if (ib_peer_client->peer_mem->release)
+		ib_peer_client->peer_mem->release(peer_client_context);
+	if (refcount_dec_and_test(&ib_peer_client->usecnt))
+		complete(&ib_peer_client->usecnt_zero);
+}
+
+static void ib_peer_umem_kref_release(struct kref *kref)
+{
+	struct ib_umem_peer *umem_p =
+		container_of(kref, struct ib_umem_peer, kref);
+
+	mutex_destroy(&umem_p->mapping_lock);
+	kfree(umem_p);
+}
+
+static void ib_unmap_peer_client(struct ib_umem_peer *umem_p,
+				 enum ib_umem_mapped_state cur_state,
+				 enum ib_umem_mapped_state to_state)
+{
+	struct ib_peer_memory_client *ib_peer_client = umem_p->ib_peer_client;
+	const struct peer_memory_client *peer_mem = ib_peer_client->peer_mem;
+	struct ib_umem *umem = &umem_p->umem;
+
+	if (cur_state == UMEM_PEER_MAPPED &&
+	    (to_state == UMEM_PEER_UNMAPPED ||
+	     to_state == UMEM_PEER_INVALIDATED)) {
+		if (to_state == UMEM_PEER_UNMAPPED) {
+			peer_mem->dma_unmap(&umem_p->umem.sg_head, umem_p->peer_client_context,
+			    umem_p->umem.ibdev->dma_device);
+			peer_mem->put_pages(&umem_p->umem.sg_head, umem_p->peer_client_context);
+		}
+		memset(&umem->sg_head, 0, sizeof(umem->sg_head));
+		atomic64_inc(&ib_peer_client->stats.num_dealloc_mrs);
+	}
+
+	if ((cur_state == UMEM_PEER_MAPPED && to_state == UMEM_PEER_UNMAPPED) ||
+	    (cur_state == UMEM_PEER_INVALIDATED &&
+	     to_state == UMEM_PEER_UNMAPPED)) {
+		atomic64_add(umem->nmap, &ib_peer_client->stats.num_dereg_pages);
+		atomic64_add(umem->length, &ib_peer_client->stats.num_dereg_bytes);
+	}
+
+	umem_p->mapped_state = to_state;
+}
+
+static bool ib_peer_unmap_on_invalidate(struct ib_umem_peer *umem_p)
+{
+	const struct peer_memory_client *peer_mem =
+		umem_p->ib_peer_client->peer_mem;
+	const struct peer_memory_client_ex *peer_mem_ex;
+
+	if (peer_mem->version[IB_PEER_MEMORY_VER_MAX - 1] == 0)
+		return false;
+	peer_mem_ex = container_of(peer_mem, const struct peer_memory_client_ex,
+				   client);
+	if (peer_mem_ex->ex_size <
+	    offsetofend(struct peer_memory_client_ex, flags))
+		return false;
+	return peer_mem_ex->flags & PEER_MEM_INVALIDATE_UNMAPS;
+}
+
+
+static int ib_invalidate_peer_memory(void *reg_handle, u64 core_context)
+{
+	struct ib_peer_memory_client *ib_peer_client = reg_handle;
+	struct ib_umem_peer *umem_p;
+
+	/*
+	 * The client is not required to fence against invalidation during
+	 * put_pages() as that would deadlock when we call put_pages() here.
+	 * Thus the core_context cannot be a umem pointer as we have no control
+	 * over the lifetime. Since we won't change the kABI for this to add a
+	 * proper kref, an xarray is used.
+	 */
+	xa_lock(&ib_peer_client->umem_xa);
+	ib_peer_client->stats.num_free_callbacks += 1;
+	umem_p = xa_load(&ib_peer_client->umem_xa, core_context);
+	if (!umem_p)
+		goto out_unlock;
+	kref_get(&umem_p->kref);
+	xa_unlock(&ib_peer_client->umem_xa);
+	mutex_lock(&umem_p->mapping_lock);
+	/*
+	 * For flows that require invalidation the invalidation_func should not
+	 * be NULL while the device can be doing DMA. The mapping_lock ensures
+	 * that the device is ready to receive an invalidation before one is
+	 * triggered here.
+	 */
+	if (umem_p->mapped_state == UMEM_PEER_MAPPED &&
+	    umem_p->invalidation_func)
+		umem_p->invalidation_func(&umem_p->umem,
+					  umem_p->invalidation_private);
+	if (ib_peer_unmap_on_invalidate(umem_p))
+		ib_unmap_peer_client(umem_p, umem_p->mapped_state,
+				     UMEM_PEER_INVALIDATED);
+	else
+		ib_unmap_peer_client(umem_p, umem_p->mapped_state,
+				     UMEM_PEER_UNMAPPED);
+	mutex_unlock(&umem_p->mapping_lock);
+	kref_put(&umem_p->kref, ib_peer_umem_kref_release);
+	return 0;
+out_unlock:
+	xa_unlock(&ib_peer_client->umem_xa);
+	return 0;
+}
+
+void ib_umem_activate_invalidation_notifier(struct ib_umem *umem,
+					    umem_invalidate_func_t func,
+					    void *priv)
+{
+	struct ib_umem_peer *umem_p =
+		container_of(umem, struct ib_umem_peer, umem);
+
+	if (WARN_ON(!umem->is_peer))
+		return;
+	if (umem_p->xa_id == PEER_NO_INVALIDATION_ID)
+		return;
+
+	umem_p->invalidation_func = func;
+	umem_p->invalidation_private = priv;
+	/* Pairs with the lock in ib_peer_umem_get() */
+	mutex_unlock(&umem_p->mapping_lock);
+
+	/* At this point func can be called asynchronously */
+}
+EXPORT_SYMBOL(ib_umem_activate_invalidation_notifier);
+
+/*
+ * Caller has blocked DMA and will no longer be able to handle invalidate
+ * callbacks. Callers using invalidation must call this function before calling
+ * ib_peer_umem_release(). ib_umem_activate_invalidation_notifier() is optional
+ * before doing this.
+ */
+void ib_umem_stop_invalidation_notifier(struct ib_umem *umem)
+{
+	struct ib_umem_peer *umem_p =
+		container_of(umem, struct ib_umem_peer, umem);
+	bool unmap_on_invalidate = ib_peer_unmap_on_invalidate(umem_p);
+	enum ib_umem_mapped_state cur_state;
+
+	if (umem_p->invalidation_func) {
+		mutex_lock(&umem_p->mapping_lock);
+		umem_p->invalidation_func = NULL;
+	} else if (umem_p->xa_id != PEER_NO_INVALIDATION_ID) {
+		mutex_lock(&umem_p->mapping_lock);
+	} else {
+		/*
+		 * Haven't called ib_umem_activate_invalidation_notifier() yet,
+		 * still have the lock
+		 */
+	}
+
+	if (!unmap_on_invalidate) {
+		ib_unmap_peer_client(umem_p, umem_p->mapped_state,
+				     UMEM_PEER_UNMAPPED);
+	} else {
+		/* Block ib_invalidate_peer_memory() */
+		cur_state = umem_p->mapped_state;
+		umem_p->mapped_state = UMEM_PEER_UNMAPPED;
+	}
+	mutex_unlock(&umem_p->mapping_lock);
+
+	if (unmap_on_invalidate)
+		ib_unmap_peer_client(umem_p, cur_state, UMEM_PEER_UNMAPPED);
+
+}
+EXPORT_SYMBOL(ib_umem_stop_invalidation_notifier);
+
+struct ib_umem *ib_peer_umem_get(struct ib_umem *old_umem, int old_ret,
+				 unsigned long peer_mem_flags)
+{
+	struct ib_peer_memory_client *ib_peer_client;
+	void *peer_client_context;
+	struct ib_umem_peer *umem_p;
+	int ret;
+	ib_peer_client =
+		ib_get_peer_client(old_umem->address, old_umem->length,
+				   peer_mem_flags, &peer_client_context);
+	if (!ib_peer_client)
+		return ERR_PTR(old_ret);
+	umem_p = kzalloc(sizeof(*umem_p), GFP_KERNEL);
+	if (!umem_p) {
+		ret = -ENOMEM;
+		goto err_client;
+	}
+
+	kref_init(&umem_p->kref);
+	umem_p->umem = *old_umem;
+	memset(&umem_p->umem.sg_head, 0, sizeof(umem_p->umem.sg_head));
+	umem_p->umem.is_peer = 1;
+	umem_p->ib_peer_client = ib_peer_client;
+	umem_p->peer_client_context = peer_client_context;
+	mutex_init(&umem_p->mapping_lock);
+	umem_p->xa_id = PEER_NO_INVALIDATION_ID;
+
+	mutex_lock(&umem_p->mapping_lock);
+	if (ib_peer_client->invalidation_required) {
+		ret = xa_alloc_cyclic(&ib_peer_client->umem_xa, &umem_p->xa_id,
+				      umem_p,
+				      XA_LIMIT(0, PEER_NO_INVALIDATION_ID - 1),
+				      &ib_peer_client->xa_cyclic_next,
+				      GFP_KERNEL);
+		if (ret < 0)
+			goto err_umem;
+	}
+
+	/*
+	 * We always request write permissions to the pages, to force breaking
+	 * of any CoW during the registration of the MR. For read-only MRs we
+	 * use the "force" flag to indicate that CoW breaking is required but
+	 * the registration should not fail if referencing read-only areas.
+	 */
+	ret = ib_peer_client->peer_mem->get_pages(umem_p->umem.address,
+						  umem_p->umem.length, 1,
+						  !umem_p->umem.writable, NULL,
+						  peer_client_context,
+						  umem_p->xa_id);
+	if (ret)
+		goto err_xa;
+
+	umem_p->umem.page_shift =
+		ilog2(ib_peer_client->peer_mem->get_page_size(peer_client_context));
+
+	ret = ib_peer_client->peer_mem->dma_map(&umem_p->umem.sg_head,
+						peer_client_context,
+						umem_p->umem.ibdev->dma_device,
+						0, &umem_p->umem.nmap);
+	if (ret)
+		goto err_pages;
+
+	umem_p->mapped_state = UMEM_PEER_MAPPED;
+	atomic64_add(umem_p->umem.nmap, &ib_peer_client->stats.num_reg_pages);
+	atomic64_add(umem_p->umem.length, &ib_peer_client->stats.num_reg_bytes);
+	atomic64_inc(&ib_peer_client->stats.num_alloc_mrs);
+
+	/*
+	 * If invalidation is allowed then the caller must call
+	 * ib_umem_activate_invalidation_notifier() or ib_peer_umem_release() to
+	 * unlock this mutex. The call to  should be done after the last
+	 * read to sg_head, once the caller is ready for the invalidation
+	 * function to be called.
+	 */
+	if (umem_p->xa_id == PEER_NO_INVALIDATION_ID)
+		mutex_unlock(&umem_p->mapping_lock);
+	/*
+	 * On success the old umem is replaced with the new, larger, allocation
+	 */
+	kfree(old_umem);
+	return &umem_p->umem;
+err_pages:
+	ib_peer_client->peer_mem->put_pages(&umem_p->umem.sg_head,
+					    umem_p->peer_client_context);
+err_xa:
+	if (umem_p->xa_id != PEER_NO_INVALIDATION_ID)
+		xa_erase(&umem_p->ib_peer_client->umem_xa, umem_p->xa_id);
+err_umem:
+	mutex_unlock(&umem_p->mapping_lock);
+	kref_put(&umem_p->kref, ib_peer_umem_kref_release);
+err_client:
+	ib_put_peer_client(ib_peer_client, peer_client_context);
+	return ERR_PTR(ret);
+}
+
+void ib_peer_umem_release(struct ib_umem *umem)
+{
+	struct ib_umem_peer *umem_p =
+		container_of(umem, struct ib_umem_peer, umem);
+	/*
+	 * If ib_umem_activate_invalidation_notifier() is called then
+	 * ib_umem_stop_invalidation_notifier() must be called before release.
+	 */
+	WARN_ON(umem_p->invalidation_func);
+
+	/* For no invalidation cases, make sure it is unmapped */
+	ib_unmap_peer_client(umem_p, umem_p->mapped_state, UMEM_PEER_UNMAPPED);
+
+	if (umem_p->xa_id != PEER_NO_INVALIDATION_ID)
+		xa_erase(&umem_p->ib_peer_client->umem_xa, umem_p->xa_id);
+	ib_put_peer_client(umem_p->ib_peer_client, umem_p->peer_client_context);
+	umem_p->ib_peer_client = NULL;
+
+	/* Must match ib_umem_release() */
+	atomic64_sub(ib_umem_num_pages(umem), &umem->owning_mm->pinned_vm);
+	mmdrop(umem->owning_mm);
+
+	kref_put(&umem_p->kref, ib_peer_umem_kref_release);
+}
+
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/core/rdma_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/core/rdma_core.c
@@ -160,9 +160,9 @@
 	uobj->context = NULL;
 
 	/*
-	 * For DESTROY the usecnt is held write locked, the caller is expected
-	 * to put it unlock and put the object when done with it. Only DESTROY
-	 * can remove the IDR handle.
+	 * For DESTROY the usecnt is not changed, the caller is expected to
+	 * manage it via uobj_put_destroy(). Only DESTROY can remove the IDR
+	 * handle.
 	 */
 	if (reason != RDMA_REMOVE_DESTROY)
 		atomic_set(&uobj->usecnt, 0);
@@ -194,7 +194,7 @@
 /*
  * This calls uverbs_destroy_uobject() using the RDMA_REMOVE_DESTROY
  * sequence. It should only be used from command callbacks. On success the
- * caller must pair this with rdma_lookup_put_uobject(LOOKUP_WRITE). This
+ * caller must pair this with uobj_put_destroy(). This
  * version requires the caller to have already obtained an
  * LOOKUP_DESTROY uobject kref.
  */
@@ -205,6 +205,13 @@
 
 	down_read(&ufile->hw_destroy_rwsem);
 
+	/*
+	 * Once the uobject is destroyed by RDMA_REMOVE_DESTROY then it is left
+	 * write locked as the callers put it back with UVERBS_LOOKUP_DESTROY.
+	 * This is because any other concurrent thread can still see the object
+	 * in the xarray due to RCU. Leaving it locked ensures nothing else will
+	 * touch it.
+	 */
 	ret = uverbs_try_lock_object(uobj, UVERBS_LOOKUP_WRITE);
 	if (ret)
 		goto out_unlock;
@@ -223,7 +230,7 @@
 /*
  * uobj_get_destroy destroys the HW object and returns a handle to the uobj
  * with a NULL object pointer. The caller must pair this with
- * uverbs_put_destroy.
+ * uobj_put_destroy().
  */
 struct ib_uobject *__uobj_get_destroy(const struct uverbs_api_object *obj,
 				      u32 id, struct uverbs_attr_bundle *attrs)
@@ -257,8 +264,7 @@
 	uobj = __uobj_get_destroy(obj, id, attrs);
 	if (IS_ERR(uobj))
 		return PTR_ERR(uobj);
-
-	rdma_lookup_put_uobject(uobj, UVERBS_LOOKUP_WRITE);
+	uobj_put_destroy(uobj);
 	return 0;
 }
 
@@ -362,7 +368,7 @@
 	 * and the caller is expected to ensure that uverbs_close_fd is never
 	 * done while a call top lookup is possible.
 	 */
-	if (f->f_op != fd_type->fops) {
+	if (f->f_op != fd_type->fops || uobject->ufile != ufile) {
 		fput(f);
 		return ERR_PTR(-EBADF);
 	}
@@ -689,7 +695,6 @@
 			     enum rdma_lookup_mode mode)
 {
 	assert_uverbs_usecnt(uobj, mode);
-	uobj->uapi_object->type_class->lookup_put(uobj, mode);
 	/*
 	 * In order to unlock an object, either decrease its usecnt for
 	 * read access or zero it in case of exclusive access. See
@@ -706,6 +711,7 @@
 		break;
 	}
 
+	uobj->uapi_object->type_class->lookup_put(uobj, mode);
 	/* Pairs with the kref obtained by type->lookup_get */
 	uverbs_uobject_put(uobj);
 }
@@ -817,6 +823,7 @@
 	rdma_restrack_del(&ucontext->res);
 
 	ib_dev->ops.dealloc_ucontext(ucontext);
+	WARN_ON(!xa_empty(&ucontext->mmap_xa));
 	kfree(ucontext);
 
 	ufile->ucontext = NULL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/core/restrack.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/core/restrack.c
@@ -234,6 +234,7 @@
 	} else {
 		ret = xa_alloc_cyclic(&rt->xa, &res->id, res, xa_limit_32b,
 				      &rt->next_id, GFP_KERNEL);
+		ret = (ret < 0) ? ret : 0;
 	}
 
 	if (!ret)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/core/rw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/core/rw.c
@@ -268,6 +268,23 @@
 	return 1;
 }
 
+static void rdma_rw_unmap_sg(struct ib_device *dev, struct scatterlist *sg,
+			     u32 sg_cnt, enum dma_data_direction dir)
+{
+	if (is_pci_p2pdma_page(sg_page(sg)))
+		pci_p2pdma_unmap_sg(dev->dma_device, sg, sg_cnt, dir);
+	else
+		ib_dma_unmap_sg(dev, sg, sg_cnt, dir);
+}
+
+static int rdma_rw_map_sg(struct ib_device *dev, struct scatterlist *sg,
+			  u32 sg_cnt, enum dma_data_direction dir)
+{
+	if (is_pci_p2pdma_page(sg_page(sg)))
+		return pci_p2pdma_map_sg(dev->dma_device, sg, sg_cnt, dir);
+	return ib_dma_map_sg(dev, sg, sg_cnt, dir);
+}
+
 /**
  * rdma_rw_ctx_init - initialize a RDMA READ/WRITE context
  * @ctx:	context to initialize
@@ -290,11 +307,7 @@
 	struct ib_device *dev = qp->pd->device;
 	int ret;
 
-	if (is_pci_p2pdma_page(sg_page(sg)))
-		ret = pci_p2pdma_map_sg(dev->dma_device, sg, sg_cnt, dir);
-	else
-		ret = ib_dma_map_sg(dev, sg, sg_cnt, dir);
-
+	ret = rdma_rw_map_sg(dev, sg, sg_cnt, dir);
 	if (!ret)
 		return -ENOMEM;
 	sg_cnt = ret;
@@ -333,7 +346,7 @@
 	return ret;
 
 out_unmap_sg:
-	ib_dma_unmap_sg(dev, sg, sg_cnt, dir);
+	rdma_rw_unmap_sg(dev, sg, sg_cnt, dir);
 	return ret;
 }
 EXPORT_SYMBOL(rdma_rw_ctx_init);
@@ -583,11 +596,7 @@
 		break;
 	}
 
-	if (is_pci_p2pdma_page(sg_page(sg)))
-		pci_p2pdma_unmap_sg(qp->pd->device->dma_device, sg,
-				    sg_cnt, dir);
-	else
-		ib_dma_unmap_sg(qp->pd->device, sg, sg_cnt, dir);
+	rdma_rw_unmap_sg(qp->pd->device, sg, sg_cnt, dir);
 }
 EXPORT_SYMBOL(rdma_rw_ctx_destroy);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/core/sa_query.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/core/sa_query.c
@@ -760,8 +760,9 @@
 
 	/* Construct the family header first */
 	header = skb_put(skb, NLMSG_ALIGN(sizeof(*header)));
-	memcpy(header->device_name, dev_name(&query->port->agent->device->dev),
-	       LS_DEVICE_NAME_MAX);
+	strscpy_pad(header->device_name,
+		    dev_name(&query->port->agent->device->dev),
+		    LS_DEVICE_NAME_MAX);
 	header->port_num = query->port->port_num;
 
 	if ((comp_mask & IB_SA_PATH_REC_REVERSIBLE) &&
@@ -829,13 +830,20 @@
 	return len;
 }
 
-static int ib_nl_send_msg(struct ib_sa_query *query, gfp_t gfp_mask)
+static int ib_nl_make_request(struct ib_sa_query *query, gfp_t gfp_mask)
 {
 	struct sk_buff *skb = NULL;
 	struct nlmsghdr *nlh;
 	void *data;
 	struct ib_sa_mad *mad;
 	int len;
+	unsigned long flags;
+	unsigned long delay;
+	gfp_t gfp_flag;
+	int ret;
+
+	INIT_LIST_HEAD(&query->list);
+	query->seq = (u32)atomic_inc_return(&ib_nl_sa_request_seq);
 
 	mad = query->mad_buf->mad;
 	len = ib_nl_get_path_rec_attrs_len(mad->sa_hdr.comp_mask);
@@ -860,36 +868,25 @@
 	/* Repair the nlmsg header length */
 	nlmsg_end(skb, nlh);
 
-	return rdma_nl_multicast(&init_net, skb, RDMA_NL_GROUP_LS, gfp_mask);
-}
+	gfp_flag = ((gfp_mask & GFP_ATOMIC) == GFP_ATOMIC) ? GFP_ATOMIC :
+		GFP_NOWAIT;
 
-static int ib_nl_make_request(struct ib_sa_query *query, gfp_t gfp_mask)
-{
-	unsigned long flags;
-	unsigned long delay;
-	int ret;
+	spin_lock_irqsave(&ib_nl_request_lock, flags);
+	ret = rdma_nl_multicast(&init_net, skb, RDMA_NL_GROUP_LS, gfp_flag);
 
-	INIT_LIST_HEAD(&query->list);
-	query->seq = (u32)atomic_inc_return(&ib_nl_sa_request_seq);
+	if (ret)
+		goto out;
 
-	/* Put the request on the list first.*/
-	spin_lock_irqsave(&ib_nl_request_lock, flags);
+	/* Put the request on the list.*/
 	delay = msecs_to_jiffies(sa_local_svc_timeout_ms);
 	query->timeout = delay + jiffies;
 	list_add_tail(&query->list, &ib_nl_request_list);
 	/* Start the timeout if this is the only request */
 	if (ib_nl_request_list.next == &query->list)
 		queue_delayed_work(ib_nl_wq, &ib_nl_timed_work, delay);
-	spin_unlock_irqrestore(&ib_nl_request_lock, flags);
 
-	ret = ib_nl_send_msg(query, gfp_mask);
-	if (ret) {
-		ret = -EIO;
-		/* Remove the request */
-		spin_lock_irqsave(&ib_nl_request_lock, flags);
-		list_del(&query->list);
-		spin_unlock_irqrestore(&ib_nl_request_lock, flags);
-	}
+out:
+	spin_unlock_irqrestore(&ib_nl_request_lock, flags);
 
 	return ret;
 }
@@ -1068,7 +1065,7 @@
 	}
 
 settimeout_out:
-	return skb->len;
+	return 0;
 }
 
 static inline int ib_nl_is_good_resolve_resp(const struct nlmsghdr *nlh)
@@ -1139,7 +1136,7 @@
 	}
 
 resp_out:
-	return skb->len;
+	return 0;
 }
 
 static void free_sm_ah(struct kref *kref)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/core/security.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/core/security.c
@@ -339,27 +339,20 @@
 	if (!new_pps)
 		return NULL;
 
-	if (qp_attr_mask & (IB_QP_PKEY_INDEX | IB_QP_PORT)) {
-		if (!qp_pps) {
-			new_pps->main.port_num = qp_attr->port_num;
-			new_pps->main.pkey_index = qp_attr->pkey_index;
-		} else {
-			new_pps->main.port_num = (qp_attr_mask & IB_QP_PORT) ?
-						  qp_attr->port_num :
-						  qp_pps->main.port_num;
-
-			new_pps->main.pkey_index =
-					(qp_attr_mask & IB_QP_PKEY_INDEX) ?
-					 qp_attr->pkey_index :
-					 qp_pps->main.pkey_index;
-		}
-		new_pps->main.state = IB_PORT_PKEY_VALID;
-	} else if (qp_pps) {
+	if (qp_attr_mask & IB_QP_PORT)
+		new_pps->main.port_num = qp_attr->port_num;
+	else if (qp_pps)
 		new_pps->main.port_num = qp_pps->main.port_num;
+
+	if (qp_attr_mask & IB_QP_PKEY_INDEX)
+		new_pps->main.pkey_index = qp_attr->pkey_index;
+	else if (qp_pps)
 		new_pps->main.pkey_index = qp_pps->main.pkey_index;
-		if (qp_pps->main.state != IB_PORT_PKEY_NOT_VALID)
-			new_pps->main.state = IB_PORT_PKEY_VALID;
-	}
+
+	if (((qp_attr_mask & IB_QP_PKEY_INDEX) &&
+	     (qp_attr_mask & IB_QP_PORT)) ||
+	    (qp_pps && qp_pps->main.state != IB_PORT_PKEY_NOT_VALID))
+		new_pps->main.state = IB_PORT_PKEY_VALID;
 
 	if (qp_attr_mask & IB_QP_ALT_PATH) {
 		new_pps->alt.port_num = qp_attr->alt_port_num;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/core/sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/core/sysfs.c
@@ -1060,8 +1060,7 @@
 				   coredev->ports_kobj,
 				   "%d", port_num);
 	if (ret) {
-		kfree(p);
-		return ret;
+		goto err_put;
 	}
 
 	p->gid_attr_group = kzalloc(sizeof(*p->gid_attr_group), GFP_KERNEL);
@@ -1074,8 +1073,7 @@
 	ret = kobject_init_and_add(&p->gid_attr_group->kobj, &gid_attr_type,
 				   &p->kobj, "gid_attrs");
 	if (ret) {
-		kfree(p->gid_attr_group);
-		goto err_put;
+		goto err_put_gid_attrs;
 	}
 
 	if (device->ops.process_mad && is_full_dev) {
@@ -1406,8 +1404,10 @@
 
 		ret = kobject_init_and_add(kobj, ktype, &port->kobj, "%s",
 					   name);
-		if (ret)
+		if (ret) {
+			kobject_put(kobj);
 			return ret;
+		}
 	}
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/core/ucma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/core/ucma.c
@@ -91,6 +91,7 @@
 
 	struct ucma_file	*file;
 	struct rdma_cm_id	*cm_id;
+	struct mutex		mutex;
 	u64			uid;
 
 	struct list_head	list;
@@ -216,6 +217,7 @@
 	init_completion(&ctx->comp);
 	INIT_LIST_HEAD(&ctx->mc_list);
 	ctx->file = file;
+	mutex_init(&ctx->mutex);
 
 	if (xa_alloc(&ctx_table, &ctx->id, ctx, xa_limit_32b, GFP_KERNEL))
 		goto error;
@@ -543,6 +545,7 @@
 {
 	struct ucma_event *uevent, *tmp;
 
+	rdma_lock_handler(mc->ctx->cm_id);
 	list_for_each_entry_safe(uevent, tmp, &mc->ctx->file->event_list, list) {
 		if (uevent->mc != mc)
 			continue;
@@ -550,6 +553,7 @@
 		list_del(&uevent->list);
 		kfree(uevent);
 	}
+	rdma_unlock_handler(mc->ctx->cm_id);
 }
 
 /*
@@ -579,6 +583,7 @@
 			list_move_tail(&uevent->list, &list);
 	}
 	list_del(&ctx->list);
+	events_reported = ctx->events_reported;
 	mutex_unlock(&ctx->file->mut);
 
 	list_for_each_entry_safe(uevent, tmp, &list, list) {
@@ -588,7 +593,7 @@
 		kfree(uevent);
 	}
 
-	events_reported = ctx->events_reported;
+	mutex_destroy(&ctx->mutex);
 	kfree(ctx);
 	return events_reported;
 }
@@ -658,7 +663,10 @@
 	if (IS_ERR(ctx))
 		return PTR_ERR(ctx);
 
+	mutex_lock(&ctx->mutex);
 	ret = rdma_bind_addr(ctx->cm_id, (struct sockaddr *) &cmd.addr);
+	mutex_unlock(&ctx->mutex);
+
 	ucma_put_ctx(ctx);
 	return ret;
 }
@@ -681,7 +689,9 @@
 	if (IS_ERR(ctx))
 		return PTR_ERR(ctx);
 
+	mutex_lock(&ctx->mutex);
 	ret = rdma_bind_addr(ctx->cm_id, (struct sockaddr *) &cmd.addr);
+	mutex_unlock(&ctx->mutex);
 	ucma_put_ctx(ctx);
 	return ret;
 }
@@ -705,8 +715,10 @@
 	if (IS_ERR(ctx))
 		return PTR_ERR(ctx);
 
+	mutex_lock(&ctx->mutex);
 	ret = rdma_resolve_addr(ctx->cm_id, (struct sockaddr *) &cmd.src_addr,
 				(struct sockaddr *) &cmd.dst_addr, cmd.timeout_ms);
+	mutex_unlock(&ctx->mutex);
 	ucma_put_ctx(ctx);
 	return ret;
 }
@@ -731,8 +743,10 @@
 	if (IS_ERR(ctx))
 		return PTR_ERR(ctx);
 
+	mutex_lock(&ctx->mutex);
 	ret = rdma_resolve_addr(ctx->cm_id, (struct sockaddr *) &cmd.src_addr,
 				(struct sockaddr *) &cmd.dst_addr, cmd.timeout_ms);
+	mutex_unlock(&ctx->mutex);
 	ucma_put_ctx(ctx);
 	return ret;
 }
@@ -752,7 +766,9 @@
 	if (IS_ERR(ctx))
 		return PTR_ERR(ctx);
 
+	mutex_lock(&ctx->mutex);
 	ret = rdma_resolve_route(ctx->cm_id, cmd.timeout_ms);
+	mutex_unlock(&ctx->mutex);
 	ucma_put_ctx(ctx);
 	return ret;
 }
@@ -841,6 +857,7 @@
 	if (IS_ERR(ctx))
 		return PTR_ERR(ctx);
 
+	mutex_lock(&ctx->mutex);
 	memset(&resp, 0, sizeof resp);
 	addr = (struct sockaddr *) &ctx->cm_id->route.addr.src_addr;
 	memcpy(&resp.src_addr, addr, addr->sa_family == AF_INET ?
@@ -864,6 +881,7 @@
 		ucma_copy_iw_route(&resp, &ctx->cm_id->route);
 
 out:
+	mutex_unlock(&ctx->mutex);
 	if (copy_to_user(u64_to_user_ptr(cmd.response),
 			 &resp, sizeof(resp)))
 		ret = -EFAULT;
@@ -1014,6 +1032,7 @@
 	if (IS_ERR(ctx))
 		return PTR_ERR(ctx);
 
+	mutex_lock(&ctx->mutex);
 	switch (cmd.option) {
 	case RDMA_USER_CM_QUERY_ADDR:
 		ret = ucma_query_addr(ctx, response, out_len);
@@ -1028,6 +1047,7 @@
 		ret = -ENOSYS;
 		break;
 	}
+	mutex_unlock(&ctx->mutex);
 
 	ucma_put_ctx(ctx);
 	return ret;
@@ -1068,7 +1088,9 @@
 		return PTR_ERR(ctx);
 
 	ucma_copy_conn_param(ctx->cm_id, &conn_param, &cmd.conn_param);
+	mutex_lock(&ctx->mutex);
 	ret = rdma_connect(ctx->cm_id, &conn_param);
+	mutex_unlock(&ctx->mutex);
 	ucma_put_ctx(ctx);
 	return ret;
 }
@@ -1089,7 +1111,9 @@
 
 	ctx->backlog = cmd.backlog > 0 && cmd.backlog < max_backlog ?
 		       cmd.backlog : max_backlog;
+	mutex_lock(&ctx->mutex);
 	ret = rdma_listen(ctx->cm_id, ctx->backlog);
+	mutex_unlock(&ctx->mutex);
 	ucma_put_ctx(ctx);
 	return ret;
 }
@@ -1111,14 +1135,22 @@
 
 	if (cmd.conn_param.valid) {
 		ucma_copy_conn_param(ctx->cm_id, &conn_param, &cmd.conn_param);
-		mutex_lock(&file->mut);
+		mutex_lock(&ctx->mutex);
+		rdma_lock_handler(ctx->cm_id);
 		ret = __rdma_accept(ctx->cm_id, &conn_param, NULL);
-		if (!ret)
+		if (!ret) {
+			/* The uid must be set atomically with the handler */
 			ctx->uid = cmd.uid;
-		mutex_unlock(&file->mut);
-	} else
+		}
+		rdma_unlock_handler(ctx->cm_id);
+		mutex_unlock(&ctx->mutex);
+	} else {
+		mutex_lock(&ctx->mutex);
+		rdma_lock_handler(ctx->cm_id);
 		ret = __rdma_accept(ctx->cm_id, NULL, NULL);
-
+		rdma_unlock_handler(ctx->cm_id);
+		mutex_unlock(&ctx->mutex);
+	}
 	ucma_put_ctx(ctx);
 	return ret;
 }
@@ -1137,7 +1169,9 @@
 	if (IS_ERR(ctx))
 		return PTR_ERR(ctx);
 
+	mutex_lock(&ctx->mutex);
 	ret = rdma_reject(ctx->cm_id, cmd.private_data, cmd.private_data_len);
+	mutex_unlock(&ctx->mutex);
 	ucma_put_ctx(ctx);
 	return ret;
 }
@@ -1156,7 +1190,9 @@
 	if (IS_ERR(ctx))
 		return PTR_ERR(ctx);
 
+	mutex_lock(&ctx->mutex);
 	ret = rdma_disconnect(ctx->cm_id);
+	mutex_unlock(&ctx->mutex);
 	ucma_put_ctx(ctx);
 	return ret;
 }
@@ -1187,7 +1223,9 @@
 	resp.qp_attr_mask = 0;
 	memset(&qp_attr, 0, sizeof qp_attr);
 	qp_attr.qp_state = cmd.qp_state;
+	mutex_lock(&ctx->mutex);
 	ret = rdma_init_qp_attr(ctx->cm_id, &qp_attr, &resp.qp_attr_mask);
+	mutex_unlock(&ctx->mutex);
 	if (ret)
 		goto out;
 
@@ -1273,9 +1311,13 @@
 		struct sa_path_rec opa;
 
 		sa_convert_path_ib_to_opa(&opa, &sa_path);
+		mutex_lock(&ctx->mutex);
 		ret = rdma_set_ib_path(ctx->cm_id, &opa);
+		mutex_unlock(&ctx->mutex);
 	} else {
+		mutex_lock(&ctx->mutex);
 		ret = rdma_set_ib_path(ctx->cm_id, &sa_path);
+		mutex_unlock(&ctx->mutex);
 	}
 	if (ret)
 		return ret;
@@ -1308,7 +1350,9 @@
 
 	switch (level) {
 	case RDMA_OPTION_ID:
+		mutex_lock(&ctx->mutex);
 		ret = ucma_set_option_id(ctx, optname, optval, optlen);
+		mutex_unlock(&ctx->mutex);
 		break;
 	case RDMA_OPTION_IB:
 		ret = ucma_set_option_ib(ctx, optname, optval, optlen);
@@ -1368,8 +1412,10 @@
 	if (IS_ERR(ctx))
 		return PTR_ERR(ctx);
 
+	mutex_lock(&ctx->mutex);
 	if (ctx->cm_id->device)
 		ret = rdma_notify(ctx->cm_id, (enum ib_event_type)cmd.event);
+	mutex_unlock(&ctx->mutex);
 
 	ucma_put_ctx(ctx);
 	return ret;
@@ -1412,8 +1458,10 @@
 	mc->join_state = join_state;
 	mc->uid = cmd->uid;
 	memcpy(&mc->addr, addr, cmd->addr_size);
+	mutex_lock(&ctx->mutex);
 	ret = rdma_join_multicast(ctx->cm_id, (struct sockaddr *)&mc->addr,
 				  join_state, mc);
+	mutex_unlock(&ctx->mutex);
 	if (ret)
 		goto err2;
 
@@ -1431,7 +1479,9 @@
 	return 0;
 
 err3:
+	mutex_lock(&ctx->mutex);
 	rdma_leave_multicast(ctx->cm_id, (struct sockaddr *) &mc->addr);
+	mutex_unlock(&ctx->mutex);
 	ucma_cleanup_mc_events(mc);
 err2:
 	xa_erase(&multicast_table, mc->id);
@@ -1500,7 +1550,7 @@
 	mc = xa_load(&multicast_table, cmd.id);
 	if (!mc)
 		mc = ERR_PTR(-ENOENT);
-	else if (mc->ctx->file != file)
+	else if (READ_ONCE(mc->ctx->file) != file)
 		mc = ERR_PTR(-EINVAL);
 	else if (!atomic_inc_not_zero(&mc->ctx->ref))
 		mc = ERR_PTR(-ENXIO);
@@ -1513,7 +1563,10 @@
 		goto out;
 	}
 
+	mutex_lock(&mc->ctx->mutex);
 	rdma_leave_multicast(mc->ctx->cm_id, (struct sockaddr *) &mc->addr);
+	mutex_unlock(&mc->ctx->mutex);
+
 	mutex_lock(&mc->ctx->file->mut);
 	ucma_cleanup_mc_events(mc);
 	list_del(&mc->list);
@@ -1530,45 +1583,15 @@
 	return ret;
 }
 
-static void ucma_lock_files(struct ucma_file *file1, struct ucma_file *file2)
-{
-	/* Acquire mutex's based on pointer comparison to prevent deadlock. */
-	if (file1 < file2) {
-		mutex_lock(&file1->mut);
-		mutex_lock_nested(&file2->mut, SINGLE_DEPTH_NESTING);
-	} else {
-		mutex_lock(&file2->mut);
-		mutex_lock_nested(&file1->mut, SINGLE_DEPTH_NESTING);
-	}
-}
-
-static void ucma_unlock_files(struct ucma_file *file1, struct ucma_file *file2)
-{
-	if (file1 < file2) {
-		mutex_unlock(&file2->mut);
-		mutex_unlock(&file1->mut);
-	} else {
-		mutex_unlock(&file1->mut);
-		mutex_unlock(&file2->mut);
-	}
-}
-
-static void ucma_move_events(struct ucma_context *ctx, struct ucma_file *file)
-{
-	struct ucma_event *uevent, *tmp;
-
-	list_for_each_entry_safe(uevent, tmp, &ctx->file->event_list, list)
-		if (uevent->ctx == ctx)
-			list_move_tail(&uevent->list, &file->event_list);
-}
-
 static ssize_t ucma_migrate_id(struct ucma_file *new_file,
 			       const char __user *inbuf,
 			       int in_len, int out_len)
 {
 	struct rdma_ucm_migrate_id cmd;
 	struct rdma_ucm_migrate_resp resp;
+	struct ucma_event *uevent, *tmp;
 	struct ucma_context *ctx;
+	LIST_HEAD(event_list);
 	struct fd f;
 	struct ucma_file *cur_file;
 	int ret = 0;
@@ -1584,40 +1607,53 @@
 		ret = -EINVAL;
 		goto file_put;
 	}
+	cur_file = f.file->private_data;
 
 	/* Validate current fd and prevent destruction of id. */
-	ctx = ucma_get_ctx(f.file->private_data, cmd.id);
+	ctx = ucma_get_ctx(cur_file, cmd.id);
 	if (IS_ERR(ctx)) {
 		ret = PTR_ERR(ctx);
 		goto file_put;
 	}
 
-	cur_file = ctx->file;
-	if (cur_file == new_file) {
-		resp.events_reported = ctx->events_reported;
-		goto response;
-	}
-
+	rdma_lock_handler(ctx->cm_id);
 	/*
-	 * Migrate events between fd's, maintaining order, and avoiding new
-	 * events being added before existing events.
+	 * ctx->file can only be changed under the handler & xa_lock. xa_load()
+	 * must be checked again to ensure the ctx hasn't begun destruction
+	 * since the ucma_get_ctx().
 	 */
-	ucma_lock_files(cur_file, new_file);
 	xa_lock(&ctx_table);
-
-	list_move_tail(&ctx->list, &new_file->ctx_list);
-	ucma_move_events(ctx, new_file);
+	if (_ucma_find_context(cmd.id, cur_file) != ctx) {
+		xa_unlock(&ctx_table);
+		ret = -ENOENT;
+		goto err_unlock;
+	}
 	ctx->file = new_file;
+	xa_unlock(&ctx_table);
+
+	mutex_lock(&cur_file->mut);
+	list_del(&ctx->list);
+	/*
+	 * At this point lock_handler() prevents addition of new uevents for
+	 * this ctx.
+	 */
+	list_for_each_entry_safe(uevent, tmp, &cur_file->event_list, list)
+		if (uevent->ctx == ctx)
+			list_move_tail(&uevent->list, &event_list);
 	resp.events_reported = ctx->events_reported;
+	mutex_unlock(&cur_file->mut);
 
-	xa_unlock(&ctx_table);
-	ucma_unlock_files(cur_file, new_file);
+	mutex_lock(&new_file->mut);
+	list_add_tail(&ctx->list, &new_file->ctx_list);
+	list_splice_tail(&event_list, &new_file->event_list);
+	mutex_unlock(&new_file->mut);
 
-response:
 	if (copy_to_user(u64_to_user_ptr(cmd.response),
 			 &resp, sizeof(resp)))
 		ret = -EFAULT;
 
+err_unlock:
+	rdma_unlock_handler(ctx->cm_id);
 	ucma_put_ctx(ctx);
 file_put:
 	fdput(f);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/core/umem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/core/umem.c
@@ -42,6 +42,7 @@
 #include <rdma/ib_umem_odp.h>
 
 #include "uverbs.h"
+#include "ib_peer_mem.h"
 
 static void __ib_umem_release(struct ib_device *dev, struct ib_umem *umem, int dirty)
 {
@@ -151,13 +152,24 @@
 	dma_addr_t mask;
 	int i;
 
+	/* rdma_for_each_block() has a bug if the page size is smaller than the
+	 * page size used to build the umem. For now prevent smaller page sizes
+	 * from being returned.
+	 */
+	pgsz_bitmap &= GENMASK(BITS_PER_LONG - 1, PAGE_SHIFT);
+
 	/* At minimum, drivers must support PAGE_SIZE or smaller */
 	if (WARN_ON(!(pgsz_bitmap & GENMASK(PAGE_SHIFT, 0))))
 		return 0;
 
 	va = virt;
-	/* max page size not to exceed MR length */
-	mask = roundup_pow_of_two(umem->length);
+	/* The best result is the smallest page size that results in the minimum
+	 * number of required pages. Compute the largest page size that could
+	 * work based on VA address bits that don't change.
+	 */
+	mask = pgsz_bitmap &
+	       GENMASK(BITS_PER_LONG - 1,
+		       bits_per((umem->length - 1 + virt) ^ virt));
 	/* offset into first SGL */
 	pgoff = umem->address & ~PAGE_MASK;
 
@@ -166,10 +178,13 @@
 		 * for any address.
 		 */
 		mask |= (sg_dma_address(sg) + pgoff) ^ va;
-		if (i && i != (umem->nmap - 1))
-			/* restrict by length as well for interior SGEs */
-			mask |= sg_dma_len(sg);
 		va += sg_dma_len(sg) - pgoff;
+		/* Except for the last entry, the ending iova alignment sets
+		 * the maximum possible page size as the low bits of the iova
+		 * must be zero when starting the next chunk.
+		 */
+		if (i != (umem->nmap - 1))
+			mask |= va;
 		pgoff = 0;
 	}
 	best_pg_bit = rdma_find_pg_bit(mask, pgsz_bitmap);
@@ -179,18 +194,18 @@
 EXPORT_SYMBOL(ib_umem_find_best_pgsz);
 
 /**
- * ib_umem_get - Pin and DMA map userspace memory.
+ * __ib_umem_get - Pin and DMA map userspace memory.
  *
- * @udata: userspace context to pin memory for
+ * @device: IB device to connect UMEM
  * @addr: userspace virtual address to start at
  * @size: length of region to pin
  * @access: IB_ACCESS_xxx flags for memory being pinned
- * @dmasync: flush in-flight DMA when the memory region is written
+ * @peer_mem_flags: IB_PEER_MEM_xxx flags for memory being used
  */
-struct ib_umem *ib_umem_get(struct ib_udata *udata, unsigned long addr,
-			    size_t size, int access, int dmasync)
+struct ib_umem *__ib_umem_get(struct ib_device *device,
+			      unsigned long addr, size_t size, int access,
+			      unsigned long peer_mem_flags)
 {
-	struct ib_ucontext *context;
 	struct ib_umem *umem;
 	struct page **page_list;
 	unsigned long lock_limit;
@@ -199,21 +214,9 @@
 	struct mm_struct *mm;
 	unsigned long npages;
 	int ret;
-	unsigned long dma_attrs = 0;
 	struct scatterlist *sg;
 	unsigned int gup_flags = FOLL_WRITE;
 
-	if (!udata)
-		return ERR_PTR(-EIO);
-
-	context = container_of(udata, struct uverbs_attr_bundle, driver_udata)
-			  ->context;
-	if (!context)
-		return ERR_PTR(-EIO);
-
-	if (dmasync)
-		dma_attrs |= DMA_ATTR_WRITE_BARRIER;
-
 	/*
 	 * If the combination of the addr and size requested for this memory
 	 * region causes an integer overflow, return error.
@@ -231,7 +234,7 @@
 	umem = kzalloc(sizeof(*umem), GFP_KERNEL);
 	if (!umem)
 		return ERR_PTR(-ENOMEM);
-	umem->ibdev = context->device;
+	umem->ibdev      = device;
 	umem->length     = size;
 	umem->address    = addr;
 	umem->writable   = ib_access_writable(access);
@@ -286,7 +289,7 @@
 		npages   -= ret;
 
 		sg = ib_umem_add_sg_table(sg, page_list, ret,
-			dma_get_max_seg_size(context->device->dma_device),
+			dma_get_max_seg_size(device->dma_device),
 			&umem->sg_nents);
 
 		up_read(&mm->mmap_sem);
@@ -294,11 +297,10 @@
 
 	sg_mark_end(sg);
 
-	umem->nmap = ib_dma_map_sg_attrs(context->device,
-				  umem->sg_head.sgl,
-				  umem->sg_nents,
-				  DMA_BIDIRECTIONAL,
-				  dma_attrs);
+	umem->nmap = ib_dma_map_sg(device,
+				   umem->sg_head.sgl,
+				   umem->sg_nents,
+				   DMA_BIDIRECTIONAL);
 
 	if (!umem->nmap) {
 		ret = -ENOMEM;
@@ -309,7 +311,25 @@
 	goto out;
 
 umem_release:
-	__ib_umem_release(context->device, umem, 0);
+	__ib_umem_release(device, umem, 0);
+	/*
+	 * If the address belongs to peer memory client, then the first
+	 * call to get_user_pages will fail. In this case, try to get
+	 * these pages from the peers.
+	 */
+	//FIXME: this placement is horrible
+	if (ret < 0 && peer_mem_flags & IB_PEER_MEM_ALLOW) {
+		struct ib_umem *new_umem;
+
+		new_umem = ib_peer_umem_get(umem, ret, peer_mem_flags);
+		if (IS_ERR(new_umem)) {
+			ret = PTR_ERR(new_umem);
+			goto vma;
+		}
+		umem = new_umem;
+		ret = 0;
+		goto out;
+	}
 vma:
 	atomic64_sub(ib_umem_num_pages(umem), &mm->pinned_vm);
 out:
@@ -321,8 +341,23 @@
 	}
 	return ret ? ERR_PTR(ret) : umem;
 }
+
+struct ib_umem *ib_umem_get(struct ib_device *device, unsigned long addr,
+			    size_t size, int access)
+{
+	return __ib_umem_get(device, addr, size, access, 0);
+}
 EXPORT_SYMBOL(ib_umem_get);
 
+struct ib_umem *ib_umem_get_peer(struct ib_device *device, unsigned long addr,
+				 size_t size, int access,
+				 unsigned long peer_mem_flags)
+{
+	return __ib_umem_get(device, addr, size, access,
+			     IB_PEER_MEM_ALLOW | peer_mem_flags);
+}
+EXPORT_SYMBOL(ib_umem_get_peer);
+
 /**
  * ib_umem_release - release memory pinned with ib_umem_get
  * @umem: umem struct to release
@@ -334,6 +369,8 @@
 	if (umem->is_odp)
 		return ib_umem_odp_release(to_ib_umem_odp(umem));
 
+	if (umem->is_peer)
+		return ib_peer_umem_release(umem);
 	__ib_umem_release(umem->ibdev, umem, 1);
 
 	atomic64_sub(ib_umem_num_pages(umem), &umem->owning_mm->pinned_vm);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/core/umem_odp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/core/umem_odp.c
@@ -287,15 +287,12 @@
  * They exist only to hold the per_mm reference to help the driver create
  * children umems.
  *
- * @udata: udata from the syscall being used to create the umem
+ * @device: IB device to create UMEM
  * @access: ib_reg_mr access flags
  */
-struct ib_umem_odp *ib_umem_odp_alloc_implicit(struct ib_udata *udata,
+struct ib_umem_odp *ib_umem_odp_alloc_implicit(struct ib_device *device,
 					       int access)
 {
-	struct ib_ucontext *context =
-		container_of(udata, struct uverbs_attr_bundle, driver_udata)
-			->context;
 	struct ib_umem *umem;
 	struct ib_umem_odp *umem_odp;
 	int ret;
@@ -303,16 +300,14 @@
 	if (access & IB_ACCESS_HUGETLB)
 		return ERR_PTR(-EINVAL);
 
-	if (!context)
-		return ERR_PTR(-EIO);
-	if (WARN_ON_ONCE(!context->device->ops.invalidate_range))
+	if (WARN_ON_ONCE(!device->ops.invalidate_range))
 		return ERR_PTR(-EINVAL);
 
 	umem_odp = kzalloc(sizeof(*umem_odp), GFP_KERNEL);
 	if (!umem_odp)
 		return ERR_PTR(-ENOMEM);
 	umem = &umem_odp->umem;
-	umem->ibdev = context->device;
+	umem->ibdev = device;
 	umem->writable = ib_access_writable(access);
 	umem->owning_mm = current->mm;
 	umem_odp->is_implicit_odp = 1;
@@ -361,19 +356,33 @@
 	umem->owning_mm  = root->umem.owning_mm;
 	odp_data->page_shift = PAGE_SHIFT;
 
-	ret = ib_init_umem_odp(odp_data);
-	if (ret) {
-		kfree(odp_data);
-		return ERR_PTR(ret);
+	/*
+	 * A mmget must be held when registering a notifier, the owming_mm only
+	 * has a mm_grab at this point.
+	 */
+	if (!mmget_not_zero(umem->owning_mm)) {
+		ret = -EFAULT;
+		goto out_free;
 	}
+
+	ret = ib_init_umem_odp(odp_data);
+	if (ret)
+		goto out_mmput;
+	mmput(umem->owning_mm);
 	return odp_data;
+
+out_mmput:
+	mmput(umem->owning_mm);
+out_free:
+	kfree(odp_data);
+	return ERR_PTR(ret);
 }
 EXPORT_SYMBOL(ib_umem_odp_alloc_child);
 
 /**
  * ib_umem_odp_get - Create a umem_odp for a userspace va
  *
- * @udata: userspace context to pin memory for
+ * @device: IB device struct to get UMEM
  * @addr: userspace virtual address to start at
  * @size: length of region to pin
  * @access: IB_ACCESS_xxx flags for memory being pinned
@@ -382,31 +391,23 @@
  * pinning, instead, stores the mm for future page fault handling in
  * conjunction with MMU notifiers.
  */
-struct ib_umem_odp *ib_umem_odp_get(struct ib_udata *udata, unsigned long addr,
-				    size_t size, int access)
+struct ib_umem_odp *ib_umem_odp_get(struct ib_device *device,
+				    unsigned long addr, size_t size,
+				    int access)
 {
 	struct ib_umem_odp *umem_odp;
-	struct ib_ucontext *context;
 	struct mm_struct *mm;
 	int ret;
 
-	if (!udata)
-		return ERR_PTR(-EIO);
-
-	context = container_of(udata, struct uverbs_attr_bundle, driver_udata)
-			  ->context;
-	if (!context)
-		return ERR_PTR(-EIO);
-
 	if (WARN_ON_ONCE(!(access & IB_ACCESS_ON_DEMAND)) ||
-	    WARN_ON_ONCE(!context->device->ops.invalidate_range))
+	    WARN_ON_ONCE(!device->ops.invalidate_range))
 		return ERR_PTR(-EINVAL);
 
 	umem_odp = kzalloc(sizeof(struct ib_umem_odp), GFP_KERNEL);
 	if (!umem_odp)
 		return ERR_PTR(-ENOMEM);
 
-	umem_odp->umem.ibdev = context->device;
+	umem_odp->umem.ibdev = device;
 	umem_odp->umem.length = size;
 	umem_odp->umem.address = addr;
 	umem_odp->umem.writable = ib_access_writable(access);
@@ -632,7 +633,7 @@
 
 	while (bcnt > 0) {
 		const size_t gup_num_pages = min_t(size_t,
-				(bcnt + BIT(page_shift) - 1) >> page_shift,
+				ALIGN(bcnt, PAGE_SIZE) / PAGE_SIZE,
 				PAGE_SIZE / sizeof(struct page *));
 
 		down_read(&owning_mm->mmap_sem);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/core/user_mad.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/core/user_mad.c
@@ -63,6 +63,8 @@
 MODULE_DESCRIPTION("InfiniBand userspace MAD packet access");
 MODULE_LICENSE("Dual BSD/GPL");
 
+#define MAX_UMAD_RECV_LIST_SIZE 200000
+
 enum {
 	IB_UMAD_MAX_PORTS  = RDMA_MAX_PORTS,
 	IB_UMAD_MAX_AGENTS = 32,
@@ -113,6 +115,7 @@
 	struct mutex		mutex;
 	struct ib_umad_port    *port;
 	struct list_head	recv_list;
+	atomic_t		recv_list_size;
 	struct list_head	send_list;
 	struct list_head	port_list;
 	spinlock_t		send_lock;
@@ -131,6 +134,11 @@
 	struct ib_user_mad mad;
 };
 
+struct ib_rmpp_mad_hdr {
+	struct ib_mad_hdr	mad_hdr;
+	struct ib_rmpp_hdr      rmpp_hdr;
+} __packed;
+
 #define CREATE_TRACE_POINTS
 #include <trace/events/ib_umad.h>
 
@@ -175,24 +183,28 @@
 	return file->agents_dead ? NULL : file->agent[id];
 }
 
-static int queue_packet(struct ib_umad_file *file,
-			struct ib_mad_agent *agent,
-			struct ib_umad_packet *packet)
+static int queue_packet(struct ib_umad_file *file, struct ib_mad_agent *agent,
+			struct ib_umad_packet *packet, bool is_recv_mad)
 {
 	int ret = 1;
 
 	mutex_lock(&file->mutex);
 
+	if (is_recv_mad &&
+	    atomic_read(&file->recv_list_size) > MAX_UMAD_RECV_LIST_SIZE)
+		goto unlock;
+
 	for (packet->mad.hdr.id = 0;
 	     packet->mad.hdr.id < IB_UMAD_MAX_AGENTS;
 	     packet->mad.hdr.id++)
 		if (agent == __get_agent(file, packet->mad.hdr.id)) {
 			list_add_tail(&packet->list, &file->recv_list);
+			atomic_inc(&file->recv_list_size);
 			wake_up_interruptible(&file->recv_wait);
 			ret = 0;
 			break;
 		}
-
+unlock:
 	mutex_unlock(&file->mutex);
 
 	return ret;
@@ -219,7 +231,7 @@
 	if (send_wc->status == IB_WC_RESP_TIMEOUT_ERR) {
 		packet->length = IB_MGMT_MAD_HDR;
 		packet->mad.hdr.status = ETIMEDOUT;
-		if (!queue_packet(file, agent, packet))
+		if (!queue_packet(file, agent, packet, false))
 			return;
 	}
 	kfree(packet);
@@ -279,7 +291,7 @@
 		rdma_destroy_ah_attr(&ah_attr);
 	}
 
-	if (queue_packet(file, agent, packet))
+	if (queue_packet(file, agent, packet, true))
 		goto err2;
 	return;
 
@@ -379,6 +391,11 @@
 
 	mutex_lock(&file->mutex);
 
+	if (file->agents_dead) {
+		mutex_unlock(&file->mutex);
+		return -EIO;
+	}
+
 	while (list_empty(&file->recv_list)) {
 		mutex_unlock(&file->mutex);
 
@@ -392,8 +409,14 @@
 		mutex_lock(&file->mutex);
 	}
 
+	if (file->agents_dead) {
+		mutex_unlock(&file->mutex);
+		return -EIO;
+	}
+
 	packet = list_entry(file->recv_list.next, struct ib_umad_packet, list);
 	list_del(&packet->list);
+	atomic_dec(&file->recv_list_size);
 
 	mutex_unlock(&file->mutex);
 
@@ -406,6 +429,7 @@
 		/* Requeue packet */
 		mutex_lock(&file->mutex);
 		list_add(&packet->list, &file->recv_list);
+		atomic_inc(&file->recv_list_size);
 		mutex_unlock(&file->mutex);
 	} else {
 		if (packet->recv_wc)
@@ -484,11 +508,11 @@
 			     size_t count, loff_t *pos)
 {
 	struct ib_umad_file *file = filp->private_data;
+	struct ib_rmpp_mad_hdr *rmpp_mad_hdr;
 	struct ib_umad_packet *packet;
 	struct ib_mad_agent *agent;
 	struct rdma_ah_attr ah_attr;
 	struct ib_ah *ah;
-	struct ib_rmpp_mad *rmpp_mad;
 	__be64 *tid;
 	int ret, data_len, hdr_len, copy_offset, rmpp_active;
 	u8 base_version;
@@ -496,7 +520,7 @@
 	if (count < hdr_size(file) + IB_MGMT_RMPP_HDR)
 		return -EINVAL;
 
-	packet = kzalloc(sizeof *packet + IB_MGMT_RMPP_HDR, GFP_KERNEL);
+	packet = kzalloc(sizeof(*packet) + IB_MGMT_RMPP_HDR, GFP_KERNEL);
 	if (!packet)
 		return -ENOMEM;
 
@@ -524,7 +548,7 @@
 
 	agent = __get_agent(file, packet->mad.hdr.id);
 	if (!agent) {
-		ret = -EINVAL;
+		ret = -EIO;
 		goto err_up;
 	}
 
@@ -550,13 +574,13 @@
 		goto err_up;
 	}
 
-	rmpp_mad = (struct ib_rmpp_mad *) packet->mad.data;
-	hdr_len = ib_get_mad_data_offset(rmpp_mad->mad_hdr.mgmt_class);
+	rmpp_mad_hdr = (struct ib_rmpp_mad_hdr *)packet->mad.data;
+	hdr_len = ib_get_mad_data_offset(rmpp_mad_hdr->mad_hdr.mgmt_class);
 
-	if (ib_is_mad_class_rmpp(rmpp_mad->mad_hdr.mgmt_class)
+	if (ib_is_mad_class_rmpp(rmpp_mad_hdr->mad_hdr.mgmt_class)
 	    && ib_mad_kernel_rmpp_agent(agent)) {
 		copy_offset = IB_MGMT_RMPP_HDR;
-		rmpp_active = ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) &
+		rmpp_active = ib_get_rmpp_flags(&rmpp_mad_hdr->rmpp_hdr) &
 						IB_MGMT_RMPP_FLAG_ACTIVE;
 	} else {
 		copy_offset = IB_MGMT_MAD_HDR;
@@ -605,12 +629,12 @@
 		tid = &((struct ib_mad_hdr *) packet->msg->mad)->tid;
 		*tid = cpu_to_be64(((u64) agent->hi_tid) << 32 |
 				   (be64_to_cpup(tid) & 0xffffffff));
-		rmpp_mad->mad_hdr.tid = *tid;
+		rmpp_mad_hdr->mad_hdr.tid = *tid;
 	}
 
 	if (!ib_mad_kernel_rmpp_agent(agent)
-	   && ib_is_mad_class_rmpp(rmpp_mad->mad_hdr.mgmt_class)
-	   && (ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & IB_MGMT_RMPP_FLAG_ACTIVE)) {
+	    && ib_is_mad_class_rmpp(rmpp_mad_hdr->mad_hdr.mgmt_class)
+	    && (ib_get_rmpp_flags(&rmpp_mad_hdr->rmpp_hdr) & IB_MGMT_RMPP_FLAG_ACTIVE)) {
 		spin_lock_irq(&file->send_lock);
 		list_add_tail(&packet->list, &file->send_list);
 		spin_unlock_irq(&file->send_lock);
@@ -653,10 +677,14 @@
 	/* we will always be able to post a MAD send */
 	__poll_t mask = EPOLLOUT | EPOLLWRNORM;
 
+	mutex_lock(&file->mutex);
 	poll_wait(filp, &file->recv_wait, wait);
 
 	if (!list_empty(&file->recv_list))
 		mask |= EPOLLIN | EPOLLRDNORM;
+	if (file->agents_dead)
+		mask = EPOLLERR;
+	mutex_unlock(&file->mutex);
 
 	return mask;
 }
@@ -1129,17 +1157,30 @@
 	.llseek	 = no_llseek,
 };
 
+static struct ib_umad_port *get_port(struct ib_device *ibdev,
+				     struct ib_umad_device *umad_dev,
+				     unsigned int port)
+{
+	if (!umad_dev)
+		return ERR_PTR(-EOPNOTSUPP);
+	if (!rdma_is_port_valid(ibdev, port))
+		return ERR_PTR(-EINVAL);
+	if (!rdma_cap_ib_mad(ibdev, port))
+		return ERR_PTR(-EOPNOTSUPP);
+
+	return &umad_dev->ports[port - rdma_start_port(ibdev)];
+}
+
 static int ib_umad_get_nl_info(struct ib_device *ibdev, void *client_data,
 			       struct ib_client_nl_info *res)
 {
-	struct ib_umad_device *umad_dev = client_data;
+	struct ib_umad_port *port = get_port(ibdev, client_data, res->port);
 
-	if (!rdma_is_port_valid(ibdev, res->port))
-		return -EINVAL;
+	if (IS_ERR(port))
+		return PTR_ERR(port);
 
 	res->abi = IB_USER_MAD_ABI_VERSION;
-	res->cdev = &umad_dev->ports[res->port - rdma_start_port(ibdev)].dev;
-
+	res->cdev = &port->dev;
 	return 0;
 }
 
@@ -1154,15 +1195,13 @@
 static int ib_issm_get_nl_info(struct ib_device *ibdev, void *client_data,
 			       struct ib_client_nl_info *res)
 {
-	struct ib_umad_device *umad_dev =
-		ib_get_client_data(ibdev, &umad_client);
+	struct ib_umad_port *port = get_port(ibdev, client_data, res->port);
 
-	if (!rdma_is_port_valid(ibdev, res->port))
-		return -EINVAL;
+	if (IS_ERR(port))
+		return PTR_ERR(port);
 
 	res->abi = IB_USER_MAD_ABI_VERSION;
-	res->cdev = &umad_dev->ports[res->port - rdma_start_port(ibdev)].sm_dev;
-
+	res->cdev = &port->sm_dev;
 	return 0;
 }
 
@@ -1312,6 +1351,9 @@
 	struct ib_umad_file *file;
 	int id;
 
+	cdev_device_del(&port->sm_cdev, &port->sm_dev);
+	cdev_device_del(&port->cdev, &port->dev);
+
 	mutex_lock(&port->file_mutex);
 
 	/* Mark ib_dev NULL and block ioctl or other file ops to progress
@@ -1322,6 +1364,7 @@
 	list_for_each_entry(file, &port->file_list, port_list) {
 		mutex_lock(&file->mutex);
 		file->agents_dead = 1;
+		wake_up_interruptible(&file->recv_wait);
 		mutex_unlock(&file->mutex);
 
 		for (id = 0; id < IB_UMAD_MAX_AGENTS; ++id)
@@ -1331,8 +1374,6 @@
 
 	mutex_unlock(&port->file_mutex);
 
-	cdev_device_del(&port->sm_cdev, &port->sm_dev);
-	cdev_device_del(&port->cdev, &port->dev);
 	ida_free(&umad_ida, port->dev_num);
 
 	/* balances device_initialize() */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/core/uverbs_cmd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/core/uverbs_cmd.c
@@ -161,7 +161,7 @@
 {
 	const void __user *res = iter->cur;
 
-	if (iter->cur + len > iter->end)
+	if (len > iter->end - iter->cur)
 		return (void __force __user *)ERR_PTR(-ENOSPC);
 	iter->cur += len;
 	return res;
@@ -252,6 +252,8 @@
 	ucontext->closing = false;
 	ucontext->cleanup_retryable = false;
 
+	xa_init_flags(&ucontext->mmap_xa, XA_FLAGS_ALLOC);
+
 	ret = get_unused_fd_flags(O_CLOEXEC);
 	if (ret < 0)
 		goto err_free;
@@ -757,6 +759,7 @@
 	mr->uobject = uobj;
 	atomic_inc(&pd->usecnt);
 	mr->res.type = RDMA_RESTRACK_MR;
+	mr->iova = cmd.hca_va;
 	rdma_restrack_uadd(&mr->res);
 
 	uobj->object = mr;
@@ -847,6 +850,9 @@
 		atomic_dec(&old_pd->usecnt);
 	}
 
+	if (cmd.flags & IB_MR_REREG_TRANS)
+		mr->iova = cmd.hca_va;
+
 	memset(&resp, 0, sizeof(resp));
 	resp.lkey      = mr->lkey;
 	resp.rkey      = mr->rkey;
@@ -1431,17 +1437,7 @@
 		if (ret)
 			goto err_cb;
 
-		qp->pd		  = pd;
-		qp->send_cq	  = attr.send_cq;
-		qp->recv_cq	  = attr.recv_cq;
-		qp->srq		  = attr.srq;
-		qp->rwq_ind_tbl	  = ind_tbl;
-		qp->event_handler = attr.event_handler;
-		qp->qp_context	  = attr.qp_context;
-		qp->qp_type	  = attr.qp_type;
-		atomic_set(&qp->usecnt, 0);
 		atomic_inc(&pd->usecnt);
-		qp->port = 0;
 		if (attr.send_cq)
 			atomic_inc(&attr.send_cq->usecnt);
 		if (attr.recv_cq)
@@ -1563,7 +1559,7 @@
 	struct ib_uverbs_create_qp_resp resp;
 	struct ib_uqp_object           *obj;
 	struct ib_xrcd		       *xrcd;
-	struct ib_uobject	       *uninitialized_var(xrcd_uobj);
+	struct ib_uobject	       *xrcd_uobj;
 	struct ib_qp                   *qp;
 	struct ib_qp_open_attr          attr;
 	int ret;
@@ -1869,8 +1865,13 @@
 		attr->path_mtu = cmd->base.path_mtu;
 	if (cmd->base.attr_mask & IB_QP_PATH_MIG_STATE)
 		attr->path_mig_state = cmd->base.path_mig_state;
-	if (cmd->base.attr_mask & IB_QP_QKEY)
+	if (cmd->base.attr_mask & IB_QP_QKEY) {
+		if (cmd->base.qkey & IB_QP_SET_QKEY && !capable(CAP_NET_RAW)) {
+			ret = -EPERM;
+			goto release_qp;
+		}
 		attr->qkey = cmd->base.qkey;
+	}
 	if (cmd->base.attr_mask & IB_QP_RQ_PSN)
 		attr->rq_psn = cmd->base.rq_psn;
 	if (cmd->base.attr_mask & IB_QP_SQ_PSN)
@@ -1958,7 +1959,7 @@
 	 * Last bit is reserved for extending the attr_mask by
 	 * using another field.
 	 */
-	BUILD_BUG_ON(IB_USER_LAST_QP_ATTR_MASK == (1 << 31));
+	BUILD_BUG_ON(IB_USER_LAST_QP_ATTR_MASK == (1ULL << 31));
 
 	if (cmd.base.attr_mask &
 	    ~((IB_USER_LAST_QP_ATTR_MASK << 1) - 1))
@@ -2025,11 +2026,13 @@
 	ret = uverbs_request_start(attrs, &iter, &cmd, sizeof(cmd));
 	if (ret)
 		return ret;
-	wqes = uverbs_request_next_ptr(&iter, cmd.wqe_size * cmd.wr_count);
+	wqes = uverbs_request_next_ptr(&iter, size_mul(cmd.wqe_size,
+						       cmd.wr_count));
 	if (IS_ERR(wqes))
 		return PTR_ERR(wqes);
-	sgls = uverbs_request_next_ptr(
-		&iter, cmd.sge_count * sizeof(struct ib_uverbs_sge));
+	sgls = uverbs_request_next_ptr(&iter,
+				       size_mul(cmd.sge_count,
+						sizeof(struct ib_uverbs_sge)));
 	if (IS_ERR(sgls))
 		return PTR_ERR(sgls);
 	ret = uverbs_request_finish(&iter);
@@ -2214,11 +2217,11 @@
 	if (wqe_size < sizeof (struct ib_uverbs_recv_wr))
 		return ERR_PTR(-EINVAL);
 
-	wqes = uverbs_request_next_ptr(iter, wqe_size * wr_count);
+	wqes = uverbs_request_next_ptr(iter, size_mul(wqe_size, wr_count));
 	if (IS_ERR(wqes))
 		return ERR_CAST(wqes);
-	sgls = uverbs_request_next_ptr(
-		iter, sge_count * sizeof(struct ib_uverbs_sge));
+	sgls = uverbs_request_next_ptr(iter, size_mul(sge_count,
+						      sizeof(struct ib_uverbs_sge)));
 	if (IS_ERR(sgls))
 		return ERR_CAST(sgls);
 	ret = uverbs_request_finish(iter);
@@ -2718,12 +2721,6 @@
 	return 0;
 }
 
-static size_t kern_spec_filter_sz(const struct ib_uverbs_flow_spec_hdr *spec)
-{
-	/* Returns user space filter size, includes padding */
-	return (spec->size - sizeof(struct ib_uverbs_flow_spec_hdr)) / 2;
-}
-
 static ssize_t spec_filter_size(const void *kern_spec_filter, u16 kern_filter_size,
 				u16 ib_real_filter_sz)
 {
@@ -2867,11 +2864,16 @@
 static int kern_spec_to_ib_spec_filter(struct ib_uverbs_flow_spec *kern_spec,
 				       union ib_flow_spec *ib_spec)
 {
-	ssize_t kern_filter_sz;
+	size_t kern_filter_sz;
 	void *kern_spec_mask;
 	void *kern_spec_val;
 
-	kern_filter_sz = kern_spec_filter_sz(&kern_spec->hdr);
+	if (check_sub_overflow((size_t)kern_spec->hdr.size,
+			       sizeof(struct ib_uverbs_flow_spec_hdr),
+			       &kern_filter_sz))
+		return -EINVAL;
+
+	kern_filter_sz /= 2;
 
 	kern_spec_val = (void *)kern_spec +
 		sizeof(struct ib_uverbs_flow_spec_hdr);
@@ -3038,12 +3040,29 @@
 	if (!wq)
 		return -EINVAL;
 
-	wq_attr.curr_wq_state = cmd.curr_wq_state;
-	wq_attr.wq_state = cmd.wq_state;
 	if (cmd.attr_mask & IB_WQ_FLAGS) {
 		wq_attr.flags = cmd.flags;
 		wq_attr.flags_mask = cmd.flags_mask;
 	}
+
+	if (cmd.attr_mask & IB_WQ_CUR_STATE) {
+		if (cmd.curr_wq_state > IB_WQS_ERR)
+			return -EINVAL;
+
+		wq_attr.curr_wq_state = cmd.curr_wq_state;
+	} else {
+		wq_attr.curr_wq_state = wq->state;
+	}
+
+	if (cmd.attr_mask & IB_WQ_STATE) {
+		if (cmd.wq_state > IB_WQS_ERR)
+			return -EINVAL;
+
+		wq_attr.wq_state = cmd.wq_state;
+	} else {
+		wq_attr.wq_state = wq_attr.curr_wq_state;
+	}
+
 	ret = wq->device->ops.modify_wq(wq, &wq_attr, cmd.attr_mask,
 					&attrs->driver_udata);
 	uobj_put_obj_read(wq);
@@ -3368,7 +3387,7 @@
 	struct ib_usrq_object           *obj;
 	struct ib_pd                    *pd;
 	struct ib_srq                   *srq;
-	struct ib_uobject               *uninitialized_var(xrcd_uobj);
+	struct ib_uobject               *xrcd_uobj;
 	struct ib_srq_init_attr          attr;
 	int ret;
 	struct ib_device *ib_dev;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/core/uverbs_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/core/uverbs_main.c
@@ -220,7 +220,6 @@
 }
 
 static ssize_t ib_uverbs_event_read(struct ib_uverbs_event_queue *ev_queue,
-				    struct ib_uverbs_file *uverbs_file,
 				    struct file *filp, char __user *buf,
 				    size_t count, loff_t *pos,
 				    size_t eventsz)
@@ -231,25 +230,20 @@
 	spin_lock_irq(&ev_queue->lock);
 
 	while (list_empty(&ev_queue->event_list)) {
-		spin_unlock_irq(&ev_queue->lock);
+		if (ev_queue->is_closed) {
+			spin_unlock_irq(&ev_queue->lock);
+			return -EIO;
+		}
 
+		spin_unlock_irq(&ev_queue->lock);
 		if (filp->f_flags & O_NONBLOCK)
 			return -EAGAIN;
 
 		if (wait_event_interruptible(ev_queue->poll_wait,
 					     (!list_empty(&ev_queue->event_list) ||
-			/* The barriers built into wait_event_interruptible()
-			 * and wake_up() guarentee this will see the null set
-			 * without using RCU
-			 */
-					     !uverbs_file->device->ib_dev)))
+					      ev_queue->is_closed)))
 			return -ERESTARTSYS;
 
-		/* If device was disassociated and no event exists set an error */
-		if (list_empty(&ev_queue->event_list) &&
-		    !uverbs_file->device->ib_dev)
-			return -EIO;
-
 		spin_lock_irq(&ev_queue->lock);
 	}
 
@@ -285,8 +279,7 @@
 {
 	struct ib_uverbs_async_event_file *file = filp->private_data;
 
-	return ib_uverbs_event_read(&file->ev_queue, file->uverbs_file, filp,
-				    buf, count, pos,
+	return ib_uverbs_event_read(&file->ev_queue, filp, buf, count, pos,
 				    sizeof(struct ib_uverbs_async_event_desc));
 }
 
@@ -296,9 +289,8 @@
 	struct ib_uverbs_completion_event_file *comp_ev_file =
 		filp->private_data;
 
-	return ib_uverbs_event_read(&comp_ev_file->ev_queue,
-				    comp_ev_file->uobj.ufile, filp,
-				    buf, count, pos,
+	return ib_uverbs_event_read(&comp_ev_file->ev_queue, filp, buf, count,
+				    pos,
 				    sizeof(struct ib_uverbs_comp_event_desc));
 }
 
@@ -313,6 +305,8 @@
 	spin_lock_irq(&ev_queue->lock);
 	if (!list_empty(&ev_queue->event_list))
 		pollflags = EPOLLIN | EPOLLRDNORM;
+	else if (ev_queue->is_closed)
+		pollflags = EPOLLERR;
 	spin_unlock_irq(&ev_queue->lock);
 
 	return pollflags;
@@ -321,7 +315,9 @@
 static __poll_t ib_uverbs_async_event_poll(struct file *filp,
 					       struct poll_table_struct *wait)
 {
-	return ib_uverbs_event_poll(filp->private_data, filp, wait);
+	struct ib_uverbs_async_event_file *file = filp->private_data;
+
+	return ib_uverbs_event_poll(&file->ev_queue, filp, wait);
 }
 
 static __poll_t ib_uverbs_comp_event_poll(struct file *filp,
@@ -335,9 +331,9 @@
 
 static int ib_uverbs_async_event_fasync(int fd, struct file *filp, int on)
 {
-	struct ib_uverbs_event_queue *ev_queue = filp->private_data;
+	struct ib_uverbs_async_event_file *file = filp->private_data;
 
-	return fasync_helper(fd, filp, on, &ev_queue->async_queue);
+	return fasync_helper(fd, filp, on, &file->ev_queue.async_queue);
 }
 
 static int ib_uverbs_comp_event_fasync(int fd, struct file *filp, int on)
@@ -637,7 +633,7 @@
 	if (hdr->in_words * 4 != count)
 		return -EINVAL;
 
-	if (count < method_elm->req_size + sizeof(hdr)) {
+	if (count < method_elm->req_size + sizeof(*hdr)) {
 		/*
 		 * rdma-core v18 and v19 have a bug where they send DESTROY_CQ
 		 * with a 16 byte write instead of 24. Old kernels didn't
@@ -772,6 +768,8 @@
 	return (ret) ? : count;
 }
 
+static const struct vm_operations_struct rdma_umap_ops;
+
 static int ib_uverbs_mmap(struct file *filp, struct vm_area_struct *vma)
 {
 	struct ib_uverbs_file *file = filp->private_data;
@@ -785,7 +783,7 @@
 		ret = PTR_ERR(ucontext);
 		goto out;
 	}
-
+	vma->vm_ops = &rdma_umap_ops;
 	ret = ucontext->device->ops.mmap(ucontext, vma);
 out:
 	srcu_read_unlock(&file->device->disassociate_srcu, srcu_key);
@@ -793,38 +791,6 @@
 }
 
 /*
- * Each time we map IO memory into user space this keeps track of the mapping.
- * When the device is hot-unplugged we 'zap' the mmaps in user space to point
- * to the zero page and allow the hot unplug to proceed.
- *
- * This is necessary for cases like PCI physical hot unplug as the actual BAR
- * memory may vanish after this and access to it from userspace could MCE.
- *
- * RDMA drivers supporting disassociation must have their user space designed
- * to cope in some way with their IO pages going to the zero page.
- */
-struct rdma_umap_priv {
-	struct vm_area_struct *vma;
-	struct list_head list;
-};
-
-static const struct vm_operations_struct rdma_umap_ops;
-
-static void rdma_umap_priv_init(struct rdma_umap_priv *priv,
-				struct vm_area_struct *vma)
-{
-	struct ib_uverbs_file *ufile = vma->vm_file->private_data;
-
-	priv->vma = vma;
-	vma->vm_private_data = priv;
-	vma->vm_ops = &rdma_umap_ops;
-
-	mutex_lock(&ufile->umap_lock);
-	list_add(&priv->list, &ufile->umaps);
-	mutex_unlock(&ufile->umap_lock);
-}
-
-/*
  * The VMA has been dup'd, initialize the vm_private_data with a new tracking
  * struct
  */
@@ -849,7 +815,7 @@
 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 		goto out_unlock;
-	rdma_umap_priv_init(priv, vma);
+	rdma_umap_priv_init(priv, vma, opriv->entry);
 
 	up_read(&ufile->hw_destroy_rwsem);
 	return;
@@ -880,6 +846,9 @@
 	 * this point.
 	 */
 	mutex_lock(&ufile->umap_lock);
+	if (priv->entry)
+		rdma_user_mmap_entry_put(priv->entry);
+
 	list_del(&priv->list);
 	mutex_unlock(&ufile->umap_lock);
 	kfree(priv);
@@ -931,44 +900,6 @@
 	.fault = rdma_umap_fault,
 };
 
-/*
- * Map IO memory into a process. This is to be called by drivers as part of
- * their mmap() functions if they wish to send something like PCI-E BAR memory
- * to userspace.
- */
-int rdma_user_mmap_io(struct ib_ucontext *ucontext, struct vm_area_struct *vma,
-		      unsigned long pfn, unsigned long size, pgprot_t prot)
-{
-	struct ib_uverbs_file *ufile = ucontext->ufile;
-	struct rdma_umap_priv *priv;
-
-	if (!(vma->vm_flags & VM_SHARED))
-		return -EINVAL;
-
-	if (vma->vm_end - vma->vm_start != size)
-		return -EINVAL;
-
-	/* Driver is using this wrong, must be called by ib_uverbs_mmap */
-	if (WARN_ON(!vma->vm_file ||
-		    vma->vm_file->private_data != ufile))
-		return -EINVAL;
-	lockdep_assert_held(&ufile->device->disassociate_srcu);
-
-	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-	if (!priv)
-		return -ENOMEM;
-
-	vma->vm_page_prot = prot;
-	if (io_remap_pfn_range(vma, vma->vm_start, pfn, size, prot)) {
-		kfree(priv);
-		return -EAGAIN;
-	}
-
-	rdma_umap_priv_init(priv, vma);
-	return 0;
-}
-EXPORT_SYMBOL(rdma_user_mmap_io);
-
 void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile)
 {
 	struct rdma_umap_priv *priv, *next_priv;
@@ -1018,6 +949,11 @@
 
 			zap_vma_ptes(vma, vma->vm_start,
 				     vma->vm_end - vma->vm_start);
+
+			if (priv->entry) {
+				rdma_user_mmap_entry_put(priv->entry);
+				priv->entry = NULL;
+			}
 		}
 		mutex_unlock(&ufile->umap_lock);
 	skip_mm:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/core/uverbs_marshall.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/core/uverbs_marshall.c
@@ -66,7 +66,7 @@
 	struct rdma_ah_attr *src = ah_attr;
 	struct rdma_ah_attr conv_ah;
 
-	memset(&dst->grh.reserved, 0, sizeof(dst->grh.reserved));
+	memset(&dst->grh, 0, sizeof(dst->grh));
 
 	if ((ah_attr->type == RDMA_AH_ATTR_TYPE_OPA) &&
 	    (rdma_ah_get_dlid(ah_attr) > be16_to_cpu(IB_LID_PERMISSIVE)) &&
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/core/uverbs_std_types_counters.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/core/uverbs_std_types_counters.c
@@ -105,6 +105,8 @@
 		return ret;
 
 	uattr = uverbs_attr_get(attrs, UVERBS_ATTR_READ_COUNTERS_BUFF);
+	if (IS_ERR(uattr))
+		return PTR_ERR(uattr);
 	read_attr.ncounters = uattr->ptr_attr.len / sizeof(u64);
 	read_attr.counters_buff = uverbs_zalloc(
 		attrs, array_size(read_attr.ncounters, sizeof(u64)));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/core/uverbs_std_types_device.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/core/uverbs_std_types_device.c
@@ -110,8 +110,8 @@
 		return ret;
 
 	uapi_object = uapi_get_object(attrs->ufile->device->uapi, object_id);
-	if (!uapi_object)
-		return -EINVAL;
+	if (IS_ERR(uapi_object))
+		return PTR_ERR(uapi_object);
 
 	handles = gather_objects_handle(attrs->ufile, uapi_object, attrs,
 					out_len, &total);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/core/uverbs_uapi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/core/uverbs_uapi.c
@@ -450,6 +450,9 @@
 	uapi->num_write_ex = max_write_ex + 1;
 	data = kmalloc_array(uapi->num_write + uapi->num_write_ex,
 			     sizeof(*uapi->write_methods), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
 	for (i = 0; i != uapi->num_write + uapi->num_write_ex; i++)
 		data[i] = &uapi->notsupp_method;
 	uapi->write_methods = data;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/core/verbs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/core/verbs.c
@@ -521,6 +521,8 @@
 
 	ret = device->ops.create_ah(ah, ah_attr, flags, udata);
 	if (ret) {
+		if (ah->sgid_attr)
+			rdma_put_gid_attr(ah->sgid_attr);
 		kfree(ah);
 		return ERR_PTR(ret);
 	}
@@ -1180,16 +1182,6 @@
 	if (ret)
 		goto err;
 
-	qp->qp_type    = qp_init_attr->qp_type;
-	qp->rwq_ind_tbl = qp_init_attr->rwq_ind_tbl;
-
-	atomic_set(&qp->usecnt, 0);
-	qp->mrs_used = 0;
-	spin_lock_init(&qp->mr_lock);
-	INIT_LIST_HEAD(&qp->rdma_mrs);
-	INIT_LIST_HEAD(&qp->sig_mrs);
-	qp->port = 0;
-
 	if (qp_init_attr->qp_type == IB_QPT_XRC_TGT) {
 		struct ib_qp *xrc_qp =
 			create_xrc_qp_user(qp, qp_init_attr, udata);
@@ -1658,7 +1650,7 @@
 		if (!(rdma_protocol_ib(qp->device,
 				       attr->alt_ah_attr.port_num) &&
 		      rdma_protocol_ib(qp->device, port))) {
-			ret = EINVAL;
+			ret = -EINVAL;
 			goto out;
 		}
 	}
@@ -1759,7 +1751,7 @@
 
 	dev_put(netdev);
 
-	if (!rc) {
+	if (!rc && lksettings.base.speed != (u32)SPEED_UNKNOWN) {
 		netdev_speed = lksettings.base.speed;
 	} else {
 		netdev_speed = SPEED_1000;
@@ -2850,15 +2842,18 @@
 bool __rdma_block_iter_next(struct ib_block_iter *biter)
 {
 	unsigned int block_offset;
+	unsigned int sg_delta;
 
 	if (!biter->__sg_nents || !biter->__sg)
 		return false;
 
 	biter->__dma_addr = sg_dma_address(biter->__sg) + biter->__sg_advance;
 	block_offset = biter->__dma_addr & (BIT_ULL(biter->__pg_bit) - 1);
-	biter->__sg_advance += BIT_ULL(biter->__pg_bit) - block_offset;
+	sg_delta = BIT_ULL(biter->__pg_bit) - block_offset;
 
-	if (biter->__sg_advance >= sg_dma_len(biter->__sg)) {
+	if (sg_dma_len(biter->__sg) - biter->__sg_advance > sg_delta) {
+		biter->__sg_advance += sg_delta;
+	} else {
 		biter->__sg_advance = 0;
 		biter->__sg = sg_next(biter->__sg);
 		biter->__sg_nents--;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/bnxt_re/bnxt_re.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/bnxt_re/bnxt_re.h
@@ -104,10 +104,19 @@
 	struct bnxt_re_qp *qp1_qp;
 };
 
+#define BNXT_RE_MAX_GSI_SQP_ENTRIES	1024
+struct bnxt_re_gsi_context {
+	struct	bnxt_re_qp *gsi_qp;
+	struct	bnxt_re_qp *gsi_sqp;
+	struct	bnxt_re_ah *gsi_sah;
+	struct	bnxt_re_sqp_entries *sqp_tbl;
+};
+
 #define BNXT_RE_MIN_MSIX		2
 #define BNXT_RE_MAX_MSIX		9
 #define BNXT_RE_AEQ_IDX			0
 #define BNXT_RE_NQ_IDX			1
+#define BNXT_RE_GEN_P5_MAX_VF		64
 
 struct bnxt_re_dev {
 	struct ib_device		ibdev;
@@ -164,10 +173,7 @@
 	u16				cosq[2];
 
 	/* QP for for handling QP1 packets */
-	u32				sqp_id;
-	struct bnxt_re_qp		*qp1_sqp;
-	struct bnxt_re_ah		*sqp_ah;
-	struct bnxt_re_sqp_entries sqp_tbl[1024];
+	struct bnxt_re_gsi_context	gsi_ctx;
 	atomic_t nq_alloc_cnt;
 	u32 is_virtfn;
 	u32 num_vfs;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/bnxt_re/ib_verbs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/bnxt_re/ib_verbs.c
@@ -137,7 +137,7 @@
 
 	ib_attr->vendor_id = rdev->en_dev->pdev->vendor;
 	ib_attr->vendor_part_id = rdev->en_dev->pdev->device;
-	ib_attr->hw_ver = rdev->en_dev->pdev->subsystem_device;
+	ib_attr->hw_ver = rdev->en_dev->pdev->revision;
 	ib_attr->max_qp = dev_attr->max_qp;
 	ib_attr->max_qp_wr = dev_attr->max_qp_wqes;
 	ib_attr->device_cap_flags =
@@ -330,7 +330,7 @@
 		 */
 		if (ctx->idx == 0 &&
 		    rdma_link_local_addr((struct in6_addr *)gid_to_del) &&
-		    ctx->refcnt == 1 && rdev->qp1_sqp) {
+		    ctx->refcnt == 1 && rdev->gsi_ctx.gsi_sqp) {
 			dev_dbg(rdev_to_dev(rdev),
 				"Trying to delete GID0 while QP1 is alive\n");
 			return -EFAULT;
@@ -760,6 +760,49 @@
 	spin_unlock_irqrestore(&qp->scq->cq_lock, flags);
 }
 
+static int bnxt_re_destroy_gsi_sqp(struct bnxt_re_qp *qp)
+{
+	struct bnxt_re_qp *gsi_sqp;
+	struct bnxt_re_ah *gsi_sah;
+	struct bnxt_re_dev *rdev;
+	int rc = 0;
+
+	rdev = qp->rdev;
+	gsi_sqp = rdev->gsi_ctx.gsi_sqp;
+	gsi_sah = rdev->gsi_ctx.gsi_sah;
+
+	dev_dbg(rdev_to_dev(rdev), "Destroy the shadow AH\n");
+	bnxt_qplib_destroy_ah(&rdev->qplib_res,
+			      &gsi_sah->qplib_ah,
+			      true);
+	bnxt_qplib_clean_qp(&qp->qplib_qp);
+
+	dev_dbg(rdev_to_dev(rdev), "Destroy the shadow QP\n");
+	rc = bnxt_qplib_destroy_qp(&rdev->qplib_res, &gsi_sqp->qplib_qp);
+	if (rc) {
+		dev_err(rdev_to_dev(rdev), "Destroy Shadow QP failed");
+		goto fail;
+	}
+	bnxt_qplib_free_qp_res(&rdev->qplib_res, &gsi_sqp->qplib_qp);
+
+	/* remove from active qp list */
+	mutex_lock(&rdev->qp_lock);
+	list_del(&gsi_sqp->list);
+	mutex_unlock(&rdev->qp_lock);
+	atomic_dec(&rdev->qp_count);
+
+	kfree(rdev->gsi_ctx.sqp_tbl);
+	kfree(gsi_sah);
+	kfree(gsi_sqp);
+	rdev->gsi_ctx.gsi_sqp = NULL;
+	rdev->gsi_ctx.gsi_sah = NULL;
+	rdev->gsi_ctx.sqp_tbl = NULL;
+
+	return 0;
+fail:
+	return rc;
+}
+
 /* Queue Pairs */
 int bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata)
 {
@@ -769,6 +812,7 @@
 	int rc;
 
 	bnxt_qplib_flush_cqn_wq(&qp->qplib_qp);
+
 	rc = bnxt_qplib_destroy_qp(&rdev->qplib_res, &qp->qplib_qp);
 	if (rc) {
 		dev_err(rdev_to_dev(rdev), "Failed to destroy HW QP");
@@ -783,40 +827,24 @@
 
 	bnxt_qplib_free_qp_res(&rdev->qplib_res, &qp->qplib_qp);
 
-	if (ib_qp->qp_type == IB_QPT_GSI && rdev->qp1_sqp) {
-		bnxt_qplib_destroy_ah(&rdev->qplib_res, &rdev->sqp_ah->qplib_ah,
-				      false);
-
-		bnxt_qplib_clean_qp(&qp->qplib_qp);
-		rc = bnxt_qplib_destroy_qp(&rdev->qplib_res,
-					   &rdev->qp1_sqp->qplib_qp);
-		if (rc) {
-			dev_err(rdev_to_dev(rdev),
-				"Failed to destroy Shadow QP");
-			return rc;
-		}
-		bnxt_qplib_free_qp_res(&rdev->qplib_res,
-				       &rdev->qp1_sqp->qplib_qp);
-		mutex_lock(&rdev->qp_lock);
-		list_del(&rdev->qp1_sqp->list);
-		atomic_dec(&rdev->qp_count);
-		mutex_unlock(&rdev->qp_lock);
-
-		kfree(rdev->sqp_ah);
-		kfree(rdev->qp1_sqp);
-		rdev->qp1_sqp = NULL;
-		rdev->sqp_ah = NULL;
+	if (ib_qp->qp_type == IB_QPT_GSI && rdev->gsi_ctx.gsi_sqp) {
+		rc = bnxt_re_destroy_gsi_sqp(qp);
+		if (rc)
+			goto sh_fail;
 	}
 
-	ib_umem_release(qp->rumem);
-	ib_umem_release(qp->sumem);
-
 	mutex_lock(&rdev->qp_lock);
 	list_del(&qp->list);
-	atomic_dec(&rdev->qp_count);
 	mutex_unlock(&rdev->qp_lock);
+	atomic_dec(&rdev->qp_count);
+
+	ib_umem_release(qp->rumem);
+	ib_umem_release(qp->sumem);
+
 	kfree(qp);
 	return 0;
+sh_fail:
+	return rc;
 }
 
 static u8 __from_ib_qp_type(enum ib_qp_type type)
@@ -855,7 +883,8 @@
 		bytes += (qplib_qp->sq.max_wqe * psn_sz);
 	}
 	bytes = PAGE_ALIGN(bytes);
-	umem = ib_umem_get(udata, ureq.qpsva, bytes, IB_ACCESS_LOCAL_WRITE, 1);
+	umem = ib_umem_get(&rdev->ibdev, ureq.qpsva, bytes,
+			   IB_ACCESS_LOCAL_WRITE);
 	if (IS_ERR(umem))
 		return PTR_ERR(umem);
 
@@ -868,8 +897,8 @@
 	if (!qp->qplib_qp.srq) {
 		bytes = (qplib_qp->rq.max_wqe * BNXT_QPLIB_MAX_RQE_ENTRY_SIZE);
 		bytes = PAGE_ALIGN(bytes);
-		umem = ib_umem_get(udata, ureq.qprva, bytes,
-				   IB_ACCESS_LOCAL_WRITE, 1);
+		umem = ib_umem_get(&rdev->ibdev, ureq.qprva, bytes,
+				   IB_ACCESS_LOCAL_WRITE);
 		if (IS_ERR(umem))
 			goto rqfail;
 		qp->rumem = umem;
@@ -984,8 +1013,6 @@
 	if (rc)
 		goto fail;
 
-	rdev->sqp_id = qp->qplib_qp.id;
-
 	spin_lock_init(&qp->sq_lock);
 	INIT_LIST_HEAD(&qp->list);
 	mutex_lock(&rdev->qp_lock);
@@ -998,205 +1025,375 @@
 	return NULL;
 }
 
-struct ib_qp *bnxt_re_create_qp(struct ib_pd *ib_pd,
-				struct ib_qp_init_attr *qp_init_attr,
-				struct ib_udata *udata)
+static int bnxt_re_init_rq_attr(struct bnxt_re_qp *qp,
+				struct ib_qp_init_attr *init_attr)
 {
-	struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
-	struct bnxt_re_dev *rdev = pd->rdev;
-	struct bnxt_qplib_dev_attr *dev_attr = &rdev->dev_attr;
-	struct bnxt_re_qp *qp;
-	struct bnxt_re_cq *cq;
-	struct bnxt_re_srq *srq;
-	int rc, entries;
+	struct bnxt_qplib_dev_attr *dev_attr;
+	struct bnxt_qplib_qp *qplqp;
+	struct bnxt_re_dev *rdev;
+	int entries;
 
-	if ((qp_init_attr->cap.max_send_wr > dev_attr->max_qp_wqes) ||
-	    (qp_init_attr->cap.max_recv_wr > dev_attr->max_qp_wqes) ||
-	    (qp_init_attr->cap.max_send_sge > dev_attr->max_qp_sges) ||
-	    (qp_init_attr->cap.max_recv_sge > dev_attr->max_qp_sges) ||
-	    (qp_init_attr->cap.max_inline_data > dev_attr->max_inline_data))
-		return ERR_PTR(-EINVAL);
+	rdev = qp->rdev;
+	qplqp = &qp->qplib_qp;
+	dev_attr = &rdev->dev_attr;
 
-	qp = kzalloc(sizeof(*qp), GFP_KERNEL);
-	if (!qp)
-		return ERR_PTR(-ENOMEM);
+	if (init_attr->srq) {
+		struct bnxt_re_srq *srq;
 
-	qp->rdev = rdev;
-	ether_addr_copy(qp->qplib_qp.smac, rdev->netdev->dev_addr);
-	qp->qplib_qp.pd = &pd->qplib_pd;
-	qp->qplib_qp.qp_handle = (u64)(unsigned long)(&qp->qplib_qp);
-	qp->qplib_qp.type = __from_ib_qp_type(qp_init_attr->qp_type);
+		srq = container_of(init_attr->srq, struct bnxt_re_srq, ib_srq);
+		if (!srq) {
+			dev_err(rdev_to_dev(rdev), "SRQ not found");
+			return -EINVAL;
+		}
+		qplqp->srq = &srq->qplib_srq;
+		qplqp->rq.max_wqe = 0;
+	} else {
+		/* Allocate 1 more than what's provided so posting max doesn't
+		 * mean empty.
+		 */
+		entries = roundup_pow_of_two(init_attr->cap.max_recv_wr + 1);
+		qplqp->rq.max_wqe = min_t(u32, entries,
+					  dev_attr->max_qp_wqes + 1);
 
-	if (qp_init_attr->qp_type == IB_QPT_GSI &&
-	    bnxt_qplib_is_chip_gen_p5(&rdev->chip_ctx))
-		qp->qplib_qp.type = CMDQ_CREATE_QP_TYPE_GSI;
-	if (qp->qplib_qp.type == IB_QPT_MAX) {
+		qplqp->rq.q_full_delta = qplqp->rq.max_wqe -
+					 init_attr->cap.max_recv_wr;
+		qplqp->rq.max_sge = init_attr->cap.max_recv_sge;
+		if (qplqp->rq.max_sge > dev_attr->max_qp_sges)
+			qplqp->rq.max_sge = dev_attr->max_qp_sges;
+	}
+
+	return 0;
+}
+
+static void bnxt_re_adjust_gsi_rq_attr(struct bnxt_re_qp *qp)
+{
+	struct bnxt_qplib_dev_attr *dev_attr;
+	struct bnxt_qplib_qp *qplqp;
+	struct bnxt_re_dev *rdev;
+
+	rdev = qp->rdev;
+	qplqp = &qp->qplib_qp;
+	dev_attr = &rdev->dev_attr;
+
+	qplqp->rq.max_sge = dev_attr->max_qp_sges;
+	if (qplqp->rq.max_sge > dev_attr->max_qp_sges)
+		qplqp->rq.max_sge = dev_attr->max_qp_sges;
+}
+
+static void bnxt_re_init_sq_attr(struct bnxt_re_qp *qp,
+				 struct ib_qp_init_attr *init_attr,
+				 struct ib_udata *udata)
+{
+	struct bnxt_qplib_dev_attr *dev_attr;
+	struct bnxt_qplib_qp *qplqp;
+	struct bnxt_re_dev *rdev;
+	int entries;
+
+	rdev = qp->rdev;
+	qplqp = &qp->qplib_qp;
+	dev_attr = &rdev->dev_attr;
+
+	qplqp->sq.max_sge = init_attr->cap.max_send_sge;
+	if (qplqp->sq.max_sge > dev_attr->max_qp_sges)
+		qplqp->sq.max_sge = dev_attr->max_qp_sges;
+	/*
+	 * Change the SQ depth if user has requested minimum using
+	 * configfs. Only supported for kernel consumers
+	 */
+	entries = init_attr->cap.max_send_wr;
+	/* Allocate 128 + 1 more than what's provided */
+	entries = roundup_pow_of_two(entries + BNXT_QPLIB_RESERVED_QP_WRS + 1);
+	qplqp->sq.max_wqe = min_t(u32, entries, dev_attr->max_qp_wqes +
+			BNXT_QPLIB_RESERVED_QP_WRS + 1);
+	qplqp->sq.q_full_delta = BNXT_QPLIB_RESERVED_QP_WRS + 1;
+	/*
+	 * Reserving one slot for Phantom WQE. Application can
+	 * post one extra entry in this case. But allowing this to avoid
+	 * unexpected Queue full condition
+	 */
+	qplqp->sq.q_full_delta -= 1;
+}
+
+static void bnxt_re_adjust_gsi_sq_attr(struct bnxt_re_qp *qp,
+				       struct ib_qp_init_attr *init_attr)
+{
+	struct bnxt_qplib_dev_attr *dev_attr;
+	struct bnxt_qplib_qp *qplqp;
+	struct bnxt_re_dev *rdev;
+	int entries;
+
+	rdev = qp->rdev;
+	qplqp = &qp->qplib_qp;
+	dev_attr = &rdev->dev_attr;
+
+	entries = roundup_pow_of_two(init_attr->cap.max_send_wr + 1);
+	qplqp->sq.max_wqe = min_t(u32, entries, dev_attr->max_qp_wqes + 1);
+	qplqp->sq.q_full_delta = qplqp->sq.max_wqe -
+				 init_attr->cap.max_send_wr;
+	qplqp->sq.max_sge++; /* Need one extra sge to put UD header */
+	if (qplqp->sq.max_sge > dev_attr->max_qp_sges)
+		qplqp->sq.max_sge = dev_attr->max_qp_sges;
+}
+
+static int bnxt_re_init_qp_type(struct bnxt_re_dev *rdev,
+				struct ib_qp_init_attr *init_attr)
+{
+	struct bnxt_qplib_chip_ctx *chip_ctx;
+	int qptype;
+
+	chip_ctx = &rdev->chip_ctx;
+
+	qptype = __from_ib_qp_type(init_attr->qp_type);
+	if (qptype == IB_QPT_MAX) {
 		dev_err(rdev_to_dev(rdev), "QP type 0x%x not supported",
-			qp->qplib_qp.type);
-		rc = -EINVAL;
-		goto fail;
+			qptype);
+		qptype = -EINVAL;
+		goto out;
 	}
 
-	qp->qplib_qp.max_inline_data = qp_init_attr->cap.max_inline_data;
-	qp->qplib_qp.sig_type = ((qp_init_attr->sq_sig_type ==
-				  IB_SIGNAL_ALL_WR) ? true : false);
-
-	qp->qplib_qp.sq.max_sge = qp_init_attr->cap.max_send_sge;
-	if (qp->qplib_qp.sq.max_sge > dev_attr->max_qp_sges)
-		qp->qplib_qp.sq.max_sge = dev_attr->max_qp_sges;
-
-	if (qp_init_attr->send_cq) {
-		cq = container_of(qp_init_attr->send_cq, struct bnxt_re_cq,
-				  ib_cq);
+	if (bnxt_qplib_is_chip_gen_p5(chip_ctx) &&
+	    init_attr->qp_type == IB_QPT_GSI)
+		qptype = CMDQ_CREATE_QP_TYPE_GSI;
+out:
+	return qptype;
+}
+
+static int bnxt_re_init_qp_attr(struct bnxt_re_qp *qp, struct bnxt_re_pd *pd,
+				struct ib_qp_init_attr *init_attr,
+				struct ib_udata *udata)
+{
+	struct bnxt_qplib_dev_attr *dev_attr;
+	struct bnxt_qplib_qp *qplqp;
+	struct bnxt_re_dev *rdev;
+	struct bnxt_re_cq *cq;
+	int rc = 0, qptype;
+
+	rdev = qp->rdev;
+	qplqp = &qp->qplib_qp;
+	dev_attr = &rdev->dev_attr;
+
+	/* Setup misc params */
+	ether_addr_copy(qplqp->smac, rdev->netdev->dev_addr);
+	qplqp->pd = &pd->qplib_pd;
+	qplqp->qp_handle = (u64)qplqp;
+	qplqp->max_inline_data = init_attr->cap.max_inline_data;
+	qplqp->sig_type = ((init_attr->sq_sig_type == IB_SIGNAL_ALL_WR) ?
+			    true : false);
+	qptype = bnxt_re_init_qp_type(rdev, init_attr);
+	if (qptype < 0) {
+		rc = qptype;
+		goto out;
+	}
+	qplqp->type = (u8)qptype;
+
+	if (init_attr->qp_type == IB_QPT_RC) {
+		qplqp->max_rd_atomic = dev_attr->max_qp_rd_atom;
+		qplqp->max_dest_rd_atomic = dev_attr->max_qp_init_rd_atom;
+	}
+	qplqp->mtu = ib_mtu_enum_to_int(iboe_get_mtu(rdev->netdev->mtu));
+	qplqp->dpi = &rdev->dpi_privileged; /* Doorbell page */
+	if (init_attr->create_flags)
+		dev_dbg(rdev_to_dev(rdev),
+			"QP create flags 0x%x not supported",
+			init_attr->create_flags);
+
+	/* Setup CQs */
+	if (init_attr->send_cq) {
+		cq = container_of(init_attr->send_cq, struct bnxt_re_cq, ib_cq);
 		if (!cq) {
 			dev_err(rdev_to_dev(rdev), "Send CQ not found");
 			rc = -EINVAL;
-			goto fail;
+			goto out;
 		}
-		qp->qplib_qp.scq = &cq->qplib_cq;
+		qplqp->scq = &cq->qplib_cq;
 		qp->scq = cq;
 	}
 
-	if (qp_init_attr->recv_cq) {
-		cq = container_of(qp_init_attr->recv_cq, struct bnxt_re_cq,
-				  ib_cq);
+	if (init_attr->recv_cq) {
+		cq = container_of(init_attr->recv_cq, struct bnxt_re_cq, ib_cq);
 		if (!cq) {
 			dev_err(rdev_to_dev(rdev), "Receive CQ not found");
 			rc = -EINVAL;
-			goto fail;
+			goto out;
 		}
-		qp->qplib_qp.rcq = &cq->qplib_cq;
+		qplqp->rcq = &cq->qplib_cq;
 		qp->rcq = cq;
 	}
 
-	if (qp_init_attr->srq) {
-		srq = container_of(qp_init_attr->srq, struct bnxt_re_srq,
-				   ib_srq);
-		if (!srq) {
-			dev_err(rdev_to_dev(rdev), "SRQ not found");
-			rc = -EINVAL;
-			goto fail;
-		}
-		qp->qplib_qp.srq = &srq->qplib_srq;
-		qp->qplib_qp.rq.max_wqe = 0;
-	} else {
-		/* Allocate 1 more than what's provided so posting max doesn't
-		 * mean empty
-		 */
-		entries = roundup_pow_of_two(qp_init_attr->cap.max_recv_wr + 1);
-		qp->qplib_qp.rq.max_wqe = min_t(u32, entries,
-						dev_attr->max_qp_wqes + 1);
+	/* Setup RQ/SRQ */
+	rc = bnxt_re_init_rq_attr(qp, init_attr);
+	if (rc)
+		goto out;
+	if (init_attr->qp_type == IB_QPT_GSI)
+		bnxt_re_adjust_gsi_rq_attr(qp);
 
-		qp->qplib_qp.rq.q_full_delta = qp->qplib_qp.rq.max_wqe -
-						qp_init_attr->cap.max_recv_wr;
+	/* Setup SQ */
+	bnxt_re_init_sq_attr(qp, init_attr, udata);
+	if (init_attr->qp_type == IB_QPT_GSI)
+		bnxt_re_adjust_gsi_sq_attr(qp, init_attr);
+
+	if (udata) /* This will update DPI and qp_handle */
+		rc = bnxt_re_init_user_qp(rdev, pd, qp, udata);
+out:
+	return rc;
+}
+
+static int bnxt_re_create_shadow_gsi(struct bnxt_re_qp *qp,
+				     struct bnxt_re_pd *pd)
+{
+	struct bnxt_re_sqp_entries *sqp_tbl = NULL;
+	struct bnxt_re_dev *rdev;
+	struct bnxt_re_qp *sqp;
+	struct bnxt_re_ah *sah;
+	int rc = 0;
 
-		qp->qplib_qp.rq.max_sge = qp_init_attr->cap.max_recv_sge;
-		if (qp->qplib_qp.rq.max_sge > dev_attr->max_qp_sges)
-			qp->qplib_qp.rq.max_sge = dev_attr->max_qp_sges;
+	rdev = qp->rdev;
+	/* Create a shadow QP to handle the QP1 traffic */
+	sqp_tbl = kzalloc(sizeof(*sqp_tbl) * BNXT_RE_MAX_GSI_SQP_ENTRIES,
+			  GFP_KERNEL);
+	if (!sqp_tbl)
+		return -ENOMEM;
+	rdev->gsi_ctx.sqp_tbl = sqp_tbl;
+
+	sqp = bnxt_re_create_shadow_qp(pd, &rdev->qplib_res, &qp->qplib_qp);
+	if (!sqp) {
+		rc = -ENODEV;
+		dev_err(rdev_to_dev(rdev),
+			"Failed to create Shadow QP for QP1");
+		goto out;
 	}
+	rdev->gsi_ctx.gsi_sqp = sqp;
 
-	qp->qplib_qp.mtu = ib_mtu_enum_to_int(iboe_get_mtu(rdev->netdev->mtu));
+	sqp->rcq = qp->rcq;
+	sqp->scq = qp->scq;
+	sah = bnxt_re_create_shadow_qp_ah(pd, &rdev->qplib_res,
+					  &qp->qplib_qp);
+	if (!sah) {
+		bnxt_qplib_destroy_qp(&rdev->qplib_res,
+				      &sqp->qplib_qp);
+		rc = -ENODEV;
+		dev_err(rdev_to_dev(rdev),
+			"Failed to create AH entry for ShadowQP");
+		goto out;
+	}
+	rdev->gsi_ctx.gsi_sah = sah;
 
-	if (qp_init_attr->qp_type == IB_QPT_GSI &&
-	    !(bnxt_qplib_is_chip_gen_p5(&rdev->chip_ctx))) {
-		/* Allocate 1 more than what's provided */
-		entries = roundup_pow_of_two(qp_init_attr->cap.max_send_wr + 1);
-		qp->qplib_qp.sq.max_wqe = min_t(u32, entries,
-						dev_attr->max_qp_wqes + 1);
-		qp->qplib_qp.sq.q_full_delta = qp->qplib_qp.sq.max_wqe -
-						qp_init_attr->cap.max_send_wr;
-		qp->qplib_qp.rq.max_sge = dev_attr->max_qp_sges;
-		if (qp->qplib_qp.rq.max_sge > dev_attr->max_qp_sges)
-			qp->qplib_qp.rq.max_sge = dev_attr->max_qp_sges;
-		qp->qplib_qp.sq.max_sge++;
-		if (qp->qplib_qp.sq.max_sge > dev_attr->max_qp_sges)
-			qp->qplib_qp.sq.max_sge = dev_attr->max_qp_sges;
-
-		qp->qplib_qp.rq_hdr_buf_size =
-					BNXT_QPLIB_MAX_QP1_RQ_HDR_SIZE_V2;
-
-		qp->qplib_qp.sq_hdr_buf_size =
-					BNXT_QPLIB_MAX_QP1_SQ_HDR_SIZE_V2;
-		qp->qplib_qp.dpi = &rdev->dpi_privileged;
-		rc = bnxt_qplib_create_qp1(&rdev->qplib_res, &qp->qplib_qp);
-		if (rc) {
-			dev_err(rdev_to_dev(rdev), "Failed to create HW QP1");
-			goto fail;
-		}
-		/* Create a shadow QP to handle the QP1 traffic */
-		rdev->qp1_sqp = bnxt_re_create_shadow_qp(pd, &rdev->qplib_res,
-							 &qp->qplib_qp);
-		if (!rdev->qp1_sqp) {
-			rc = -EINVAL;
-			dev_err(rdev_to_dev(rdev),
-				"Failed to create Shadow QP for QP1");
-			goto qp_destroy;
-		}
-		rdev->sqp_ah = bnxt_re_create_shadow_qp_ah(pd, &rdev->qplib_res,
-							   &qp->qplib_qp);
-		if (!rdev->sqp_ah) {
-			bnxt_qplib_destroy_qp(&rdev->qplib_res,
-					      &rdev->qp1_sqp->qplib_qp);
-			rc = -EINVAL;
-			dev_err(rdev_to_dev(rdev),
-				"Failed to create AH entry for ShadowQP");
-			goto qp_destroy;
-		}
+	return 0;
+out:
+	kfree(sqp_tbl);
+	return rc;
+}
 
-	} else {
-		/* Allocate 128 + 1 more than what's provided */
-		entries = roundup_pow_of_two(qp_init_attr->cap.max_send_wr +
-					     BNXT_QPLIB_RESERVED_QP_WRS + 1);
-		qp->qplib_qp.sq.max_wqe = min_t(u32, entries,
-						dev_attr->max_qp_wqes +
-						BNXT_QPLIB_RESERVED_QP_WRS + 1);
-		qp->qplib_qp.sq.q_full_delta = BNXT_QPLIB_RESERVED_QP_WRS + 1;
+static int bnxt_re_create_gsi_qp(struct bnxt_re_qp *qp, struct bnxt_re_pd *pd,
+				 struct ib_qp_init_attr *init_attr)
+{
+	struct bnxt_re_dev *rdev;
+	struct bnxt_qplib_qp *qplqp;
+	int rc = 0;
 
-		/*
-		 * Reserving one slot for Phantom WQE. Application can
-		 * post one extra entry in this case. But allowing this to avoid
-		 * unexpected Queue full condition
-		 */
+	rdev = qp->rdev;
+	qplqp = &qp->qplib_qp;
 
-		qp->qplib_qp.sq.q_full_delta -= 1;
+	qplqp->rq_hdr_buf_size = BNXT_QPLIB_MAX_QP1_RQ_HDR_SIZE_V2;
+	qplqp->sq_hdr_buf_size = BNXT_QPLIB_MAX_QP1_SQ_HDR_SIZE_V2;
 
-		qp->qplib_qp.max_rd_atomic = dev_attr->max_qp_rd_atom;
-		qp->qplib_qp.max_dest_rd_atomic = dev_attr->max_qp_init_rd_atom;
-		if (udata) {
-			rc = bnxt_re_init_user_qp(rdev, pd, qp, udata);
-			if (rc)
-				goto fail;
-		} else {
-			qp->qplib_qp.dpi = &rdev->dpi_privileged;
-		}
+	rc = bnxt_qplib_create_qp1(&rdev->qplib_res, qplqp);
+	if (rc) {
+		dev_err(rdev_to_dev(rdev), "create HW QP1 failed!");
+		goto out;
+	}
+
+	rc = bnxt_re_create_shadow_gsi(qp, pd);
+out:
+	return rc;
+}
+
+static bool bnxt_re_test_qp_limits(struct bnxt_re_dev *rdev,
+				   struct ib_qp_init_attr *init_attr,
+				   struct bnxt_qplib_dev_attr *dev_attr)
+{
+	bool rc = true;
+
+	if (init_attr->cap.max_send_wr > dev_attr->max_qp_wqes ||
+	    init_attr->cap.max_recv_wr > dev_attr->max_qp_wqes ||
+	    init_attr->cap.max_send_sge > dev_attr->max_qp_sges ||
+	    init_attr->cap.max_recv_sge > dev_attr->max_qp_sges ||
+	    init_attr->cap.max_inline_data > dev_attr->max_inline_data) {
+		dev_err(rdev_to_dev(rdev),
+			"Create QP failed - max exceeded! 0x%x/0x%x 0x%x/0x%x 0x%x/0x%x 0x%x/0x%x 0x%x/0x%x",
+			init_attr->cap.max_send_wr, dev_attr->max_qp_wqes,
+			init_attr->cap.max_recv_wr, dev_attr->max_qp_wqes,
+			init_attr->cap.max_send_sge, dev_attr->max_qp_sges,
+			init_attr->cap.max_recv_sge, dev_attr->max_qp_sges,
+			init_attr->cap.max_inline_data,
+			dev_attr->max_inline_data);
+		rc = false;
+	}
+	return rc;
+}
+
+struct ib_qp *bnxt_re_create_qp(struct ib_pd *ib_pd,
+				struct ib_qp_init_attr *qp_init_attr,
+				struct ib_udata *udata)
+{
+	struct bnxt_re_pd *pd = container_of(ib_pd, struct bnxt_re_pd, ib_pd);
+	struct bnxt_re_dev *rdev = pd->rdev;
+	struct bnxt_qplib_dev_attr *dev_attr = &rdev->dev_attr;
+	struct bnxt_re_qp *qp;
+	int rc;
+
+	rc = bnxt_re_test_qp_limits(rdev, qp_init_attr, dev_attr);
+	if (!rc) {
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	qp = kzalloc(sizeof(*qp), GFP_KERNEL);
+	if (!qp) {
+		rc = -ENOMEM;
+		goto exit;
+	}
+	qp->rdev = rdev;
+	rc = bnxt_re_init_qp_attr(qp, pd, qp_init_attr, udata);
+	if (rc)
+		goto fail;
 
+	if (qp_init_attr->qp_type == IB_QPT_GSI &&
+	    !(bnxt_qplib_is_chip_gen_p5(&rdev->chip_ctx))) {
+		rc = bnxt_re_create_gsi_qp(qp, pd, qp_init_attr);
+		if (rc == -ENODEV)
+			goto qp_destroy;
+		if (rc)
+			goto fail;
+	} else {
 		rc = bnxt_qplib_create_qp(&rdev->qplib_res, &qp->qplib_qp);
 		if (rc) {
 			dev_err(rdev_to_dev(rdev), "Failed to create HW QP");
 			goto free_umem;
 		}
+		if (udata) {
+			struct bnxt_re_qp_resp resp;
+
+			resp.qpid = qp->qplib_qp.id;
+			resp.rsvd = 0;
+			rc = ib_copy_to_udata(udata, &resp, sizeof(resp));
+			if (rc) {
+				dev_err(rdev_to_dev(rdev), "Failed to copy QP udata");
+				goto qp_destroy;
+			}
+		}
 	}
 
 	qp->ib_qp.qp_num = qp->qplib_qp.id;
+	if (qp_init_attr->qp_type == IB_QPT_GSI)
+		rdev->gsi_ctx.gsi_qp = qp;
 	spin_lock_init(&qp->sq_lock);
 	spin_lock_init(&qp->rq_lock);
-
-	if (udata) {
-		struct bnxt_re_qp_resp resp;
-
-		resp.qpid = qp->ib_qp.qp_num;
-		resp.rsvd = 0;
-		rc = ib_copy_to_udata(udata, &resp, sizeof(resp));
-		if (rc) {
-			dev_err(rdev_to_dev(rdev), "Failed to copy QP udata");
-			goto qp_destroy;
-		}
-	}
 	INIT_LIST_HEAD(&qp->list);
 	mutex_lock(&rdev->qp_lock);
 	list_add_tail(&qp->list, &rdev->qp_list);
-	atomic_inc(&rdev->qp_count);
 	mutex_unlock(&rdev->qp_lock);
+	atomic_inc(&rdev->qp_count);
 
 	return &qp->ib_qp;
 qp_destroy:
@@ -1206,6 +1403,7 @@
 	ib_umem_release(qp->sumem);
 fail:
 	kfree(qp);
+exit:
 	return ERR_PTR(rc);
 }
 
@@ -1322,7 +1520,8 @@
 
 	bytes = (qplib_srq->max_wqe * BNXT_QPLIB_MAX_RQE_ENTRY_SIZE);
 	bytes = PAGE_ALIGN(bytes);
-	umem = ib_umem_get(udata, ureq.srqva, bytes, IB_ACCESS_LOCAL_WRITE, 1);
+	umem = ib_umem_get(&rdev->ibdev, ureq.srqva, bytes,
+			   IB_ACCESS_LOCAL_WRITE);
 	if (IS_ERR(umem))
 		return PTR_ERR(umem);
 
@@ -1404,6 +1603,7 @@
 	if (nq)
 		nq->budget++;
 	atomic_inc(&rdev->srq_count);
+	spin_lock_init(&srq->lock);
 
 	return 0;
 
@@ -1425,7 +1625,7 @@
 	switch (srq_attr_mask) {
 	case IB_SRQ_MAX_WR:
 		/* SRQ resize is not supported */
-		break;
+		return -EINVAL;
 	case IB_SRQ_LIMIT:
 		/* Change the SRQ threshold */
 		if (srq_attr->srq_limit > srq->qplib_srq.max_wqe)
@@ -1440,13 +1640,12 @@
 		/* On success, update the shadow */
 		srq->srq_limit = srq_attr->srq_limit;
 		/* No need to Build and send response back to udata */
-		break;
+		return 0;
 	default:
 		dev_err(rdev_to_dev(rdev),
 			"Unsupported srq_attr_mask 0x%x", srq_attr_mask);
 		return -EINVAL;
 	}
-	return 0;
 }
 
 int bnxt_re_query_srq(struct ib_srq *ib_srq, struct ib_srq_attr *srq_attr)
@@ -1503,7 +1702,7 @@
 				    struct bnxt_re_qp *qp1_qp,
 				    int qp_attr_mask)
 {
-	struct bnxt_re_qp *qp = rdev->qp1_sqp;
+	struct bnxt_re_qp *qp = rdev->gsi_ctx.gsi_sqp;
 	int rc = 0;
 
 	if (qp_attr_mask & IB_QP_STATE) {
@@ -1655,18 +1854,20 @@
 		}
 	}
 
-	if (qp_attr_mask & IB_QP_PATH_MTU) {
-		qp->qplib_qp.modify_flags |=
-				CMDQ_MODIFY_QP_MODIFY_MASK_PATH_MTU;
-		qp->qplib_qp.path_mtu = __from_ib_mtu(qp_attr->path_mtu);
-		qp->qplib_qp.mtu = ib_mtu_enum_to_int(qp_attr->path_mtu);
-	} else if (qp_attr->qp_state == IB_QPS_RTR) {
-		qp->qplib_qp.modify_flags |=
-			CMDQ_MODIFY_QP_MODIFY_MASK_PATH_MTU;
-		qp->qplib_qp.path_mtu =
-			__from_ib_mtu(iboe_get_mtu(rdev->netdev->mtu));
-		qp->qplib_qp.mtu =
-			ib_mtu_enum_to_int(iboe_get_mtu(rdev->netdev->mtu));
+	if (qp_attr->qp_state == IB_QPS_RTR) {
+		enum ib_mtu qpmtu;
+
+		qpmtu = iboe_get_mtu(rdev->netdev->mtu);
+		if (qp_attr_mask & IB_QP_PATH_MTU) {
+			if (ib_mtu_enum_to_int(qp_attr->path_mtu) >
+			    ib_mtu_enum_to_int(qpmtu))
+				return -EINVAL;
+			qpmtu = qp_attr->path_mtu;
+		}
+
+		qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_PATH_MTU;
+		qp->qplib_qp.path_mtu = __from_ib_mtu(qpmtu);
+		qp->qplib_qp.mtu = ib_mtu_enum_to_int(qpmtu);
 	}
 
 	if (qp_attr_mask & IB_QP_TIMEOUT) {
@@ -1767,7 +1968,7 @@
 		dev_err(rdev_to_dev(rdev), "Failed to modify HW QP");
 		return rc;
 	}
-	if (ib_qp->qp_type == IB_QPT_GSI && rdev->qp1_sqp)
+	if (ib_qp->qp_type == IB_QPT_GSI && rdev->gsi_ctx.gsi_sqp)
 		rc = bnxt_re_modify_shadow_qp(rdev, qp, qp_attr_mask);
 	return rc;
 }
@@ -1793,6 +1994,7 @@
 		goto out;
 	}
 	qp_attr->qp_state = __to_ib_qp_state(qplib_qp->state);
+	qp_attr->cur_qp_state = __to_ib_qp_state(qplib_qp->cur_qp_state);
 	qp_attr->en_sqd_async_notify = qplib_qp->en_sqd_async_notify ? 1 : 0;
 	qp_attr->qp_access_flags = __to_ib_access_flags(qplib_qp->access);
 	qp_attr->pkey_index = qplib_qp->pkey_index;
@@ -2011,9 +2213,12 @@
 					    struct bnxt_qplib_swqe *wqe,
 					    int payload_size)
 {
+	struct bnxt_re_sqp_entries *sqp_entry;
 	struct bnxt_qplib_sge ref, sge;
+	struct bnxt_re_dev *rdev;
 	u32 rq_prod_index;
-	struct bnxt_re_sqp_entries *sqp_entry;
+
+	rdev = qp->rdev;
 
 	rq_prod_index = bnxt_qplib_get_rq_prod_index(&qp->qplib_qp);
 
@@ -2028,7 +2233,7 @@
 	ref.lkey = wqe->sg_list[0].lkey;
 	ref.size = wqe->sg_list[0].size;
 
-	sqp_entry = &qp->rdev->sqp_tbl[rq_prod_index];
+	sqp_entry = &rdev->gsi_ctx.sqp_tbl[rq_prod_index];
 
 	/* SGE 1 */
 	wqe->sg_list[0].addr = sge.addr;
@@ -2070,7 +2275,7 @@
 		break;
 	case IB_WR_SEND_WITH_IMM:
 		wqe->type = BNXT_QPLIB_SWQE_TYPE_SEND_WITH_IMM;
-		wqe->send.imm_data = wr->ex.imm_data;
+		wqe->send.imm_data = be32_to_cpu(wr->ex.imm_data);
 		break;
 	case IB_WR_SEND_WITH_INV:
 		wqe->type = BNXT_QPLIB_SWQE_TYPE_SEND_WITH_INV;
@@ -2100,7 +2305,7 @@
 		break;
 	case IB_WR_RDMA_WRITE_WITH_IMM:
 		wqe->type = BNXT_QPLIB_SWQE_TYPE_RDMA_WRITE_WITH_IMM;
-		wqe->rdma.imm_data = wr->ex.imm_data;
+		wqe->rdma.imm_data = be32_to_cpu(wr->ex.imm_data);
 		break;
 	case IB_WR_RDMA_READ:
 		wqe->type = BNXT_QPLIB_SWQE_TYPE_RDMA_READ;
@@ -2563,9 +2768,9 @@
 			goto fail;
 		}
 
-		cq->umem = ib_umem_get(udata, req.cq_va,
+		cq->umem = ib_umem_get(&rdev->ibdev, req.cq_va,
 				       entries * sizeof(struct cq_base),
-				       IB_ACCESS_LOCAL_WRITE, 1);
+				       IB_ACCESS_LOCAL_WRITE);
 		if (IS_ERR(cq->umem)) {
 			rc = PTR_ERR(cq->umem);
 			goto fail;
@@ -2848,12 +3053,13 @@
 	return rc;
 }
 
-static int bnxt_re_process_raw_qp_pkt_rx(struct bnxt_re_qp *qp1_qp,
+static int bnxt_re_process_raw_qp_pkt_rx(struct bnxt_re_qp *gsi_qp,
 					 struct bnxt_qplib_cqe *cqe)
 {
-	struct bnxt_re_dev *rdev = qp1_qp->rdev;
+	struct bnxt_re_dev *rdev = gsi_qp->rdev;
 	struct bnxt_re_sqp_entries *sqp_entry = NULL;
-	struct bnxt_re_qp *qp = rdev->qp1_sqp;
+	struct bnxt_re_qp *gsi_sqp = rdev->gsi_ctx.gsi_sqp;
+	struct bnxt_re_ah *gsi_sah;
 	struct ib_send_wr *swr;
 	struct ib_ud_wr udwr;
 	struct ib_recv_wr rwr;
@@ -2876,19 +3082,19 @@
 	swr = &udwr.wr;
 	tbl_idx = cqe->wr_id;
 
-	rq_hdr_buf = qp1_qp->qplib_qp.rq_hdr_buf +
-			(tbl_idx * qp1_qp->qplib_qp.rq_hdr_buf_size);
-	rq_hdr_buf_map = bnxt_qplib_get_qp_buf_from_index(&qp1_qp->qplib_qp,
+	rq_hdr_buf = gsi_qp->qplib_qp.rq_hdr_buf +
+			(tbl_idx * gsi_qp->qplib_qp.rq_hdr_buf_size);
+	rq_hdr_buf_map = bnxt_qplib_get_qp_buf_from_index(&gsi_qp->qplib_qp,
 							  tbl_idx);
 
 	/* Shadow QP header buffer */
-	shrq_hdr_buf_map = bnxt_qplib_get_qp_buf_from_index(&qp->qplib_qp,
+	shrq_hdr_buf_map = bnxt_qplib_get_qp_buf_from_index(&gsi_qp->qplib_qp,
 							    tbl_idx);
-	sqp_entry = &rdev->sqp_tbl[tbl_idx];
+	sqp_entry = &rdev->gsi_ctx.sqp_tbl[tbl_idx];
 
 	/* Store this cqe */
 	memcpy(&sqp_entry->cqe, cqe, sizeof(struct bnxt_qplib_cqe));
-	sqp_entry->qp1_qp = qp1_qp;
+	sqp_entry->qp1_qp = gsi_qp;
 
 	/* Find packet type from the cqe */
 
@@ -2942,7 +3148,7 @@
 	rwr.wr_id = tbl_idx;
 	rwr.next = NULL;
 
-	rc = bnxt_re_post_recv_shadow_qp(rdev, qp, &rwr);
+	rc = bnxt_re_post_recv_shadow_qp(rdev, gsi_sqp, &rwr);
 	if (rc) {
 		dev_err(rdev_to_dev(rdev),
 			"Failed to post Rx buffers to shadow QP");
@@ -2954,15 +3160,13 @@
 	swr->wr_id = tbl_idx;
 	swr->opcode = IB_WR_SEND;
 	swr->next = NULL;
-
-	udwr.ah = &rdev->sqp_ah->ib_ah;
-	udwr.remote_qpn = rdev->qp1_sqp->qplib_qp.id;
-	udwr.remote_qkey = rdev->qp1_sqp->qplib_qp.qkey;
+	gsi_sah = rdev->gsi_ctx.gsi_sah;
+	udwr.ah = &gsi_sah->ib_ah;
+	udwr.remote_qpn = gsi_sqp->qplib_qp.id;
+	udwr.remote_qkey = gsi_sqp->qplib_qp.qkey;
 
 	/* post data received  in the send queue */
-	rc = bnxt_re_post_send_shadow_qp(rdev, qp, swr);
-
-	return 0;
+	return bnxt_re_post_send_shadow_qp(rdev, gsi_sqp, swr);
 }
 
 static void bnxt_re_process_res_rawqp1_wc(struct ib_wc *wc,
@@ -2973,6 +3177,19 @@
 	wc->wc_flags |= IB_WC_GRH;
 }
 
+static bool bnxt_re_check_if_vlan_valid(struct bnxt_re_dev *rdev,
+					u16 vlan_id)
+{
+	/*
+	 * Check if the vlan is configured in the host.  If not configured, it
+	 * can be a transparent VLAN. So dont report the vlan id.
+	 */
+	if (!__vlan_find_dev_deep_rcu(rdev->netdev,
+				      htons(ETH_P_8021Q), vlan_id))
+		return false;
+	return true;
+}
+
 static bool bnxt_re_is_vlan_pkt(struct bnxt_qplib_cqe *orig_cqe,
 				u16 *vid, u8 *sl)
 {
@@ -3014,12 +3231,12 @@
 		wc->opcode = IB_WC_RECV_RDMA_WITH_IMM;
 }
 
-static void bnxt_re_process_res_shadow_qp_wc(struct bnxt_re_qp *qp,
+static void bnxt_re_process_res_shadow_qp_wc(struct bnxt_re_qp *gsi_sqp,
 					     struct ib_wc *wc,
 					     struct bnxt_qplib_cqe *cqe)
 {
-	struct bnxt_re_dev *rdev = qp->rdev;
-	struct bnxt_re_qp *qp1_qp = NULL;
+	struct bnxt_re_dev *rdev = gsi_sqp->rdev;
+	struct bnxt_re_qp *gsi_qp = NULL;
 	struct bnxt_qplib_cqe *orig_cqe = NULL;
 	struct bnxt_re_sqp_entries *sqp_entry = NULL;
 	int nw_type;
@@ -3029,21 +3246,23 @@
 
 	tbl_idx = cqe->wr_id;
 
-	sqp_entry = &rdev->sqp_tbl[tbl_idx];
-	qp1_qp = sqp_entry->qp1_qp;
+	sqp_entry = &rdev->gsi_ctx.sqp_tbl[tbl_idx];
+	gsi_qp = sqp_entry->qp1_qp;
 	orig_cqe = &sqp_entry->cqe;
 
 	wc->wr_id = sqp_entry->wrid;
 	wc->byte_len = orig_cqe->length;
-	wc->qp = &qp1_qp->ib_qp;
+	wc->qp = &gsi_qp->ib_qp;
 
-	wc->ex.imm_data = orig_cqe->immdata;
+	wc->ex.imm_data = cpu_to_be32(orig_cqe->immdata);
 	wc->src_qp = orig_cqe->src_qp;
 	memcpy(wc->smac, orig_cqe->smac, ETH_ALEN);
 	if (bnxt_re_is_vlan_pkt(orig_cqe, &vlan_id, &sl)) {
-		wc->vlan_id = vlan_id;
-		wc->sl = sl;
-		wc->wc_flags |= IB_WC_WITH_VLAN;
+		if (bnxt_re_check_if_vlan_valid(rdev, vlan_id)) {
+			wc->vlan_id = vlan_id;
+			wc->sl = sl;
+			wc->wc_flags |= IB_WC_WITH_VLAN;
+		}
 	}
 	wc->port_num = 1;
 	wc->vendor_err = orig_cqe->status;
@@ -3064,8 +3283,11 @@
 				      struct ib_wc *wc,
 				      struct bnxt_qplib_cqe *cqe)
 {
+	struct bnxt_re_dev *rdev;
+	u16 vlan_id = 0;
 	u8 nw_type;
 
+	rdev = qp->rdev;
 	wc->opcode = IB_WC_RECV;
 	wc->status = __rc_to_ib_wc_status(cqe->status);
 
@@ -3077,9 +3299,12 @@
 		memcpy(wc->smac, cqe->smac, ETH_ALEN);
 		wc->wc_flags |= IB_WC_WITH_SMAC;
 		if (cqe->flags & CQ_RES_UD_FLAGS_META_FORMAT_VLAN) {
-			wc->vlan_id = (cqe->cfa_meta & 0xFFF);
-			if (wc->vlan_id < 0x1000)
-				wc->wc_flags |= IB_WC_WITH_VLAN;
+			vlan_id = (cqe->cfa_meta & 0xFFF);
+		}
+		/* Mark only if vlan_id is non zero */
+		if (vlan_id && bnxt_re_check_if_vlan_valid(rdev, vlan_id)) {
+			wc->vlan_id = vlan_id;
+			wc->wc_flags |= IB_WC_WITH_VLAN;
 		}
 		nw_type = (cqe->flags & CQ_RES_UD_FLAGS_ROCE_IP_VER_MASK) >>
 			   CQ_RES_UD_FLAGS_ROCE_IP_VER_SFT;
@@ -3114,7 +3339,7 @@
 int bnxt_re_poll_cq(struct ib_cq *ib_cq, int num_entries, struct ib_wc *wc)
 {
 	struct bnxt_re_cq *cq = container_of(ib_cq, struct bnxt_re_cq, ib_cq);
-	struct bnxt_re_qp *qp;
+	struct bnxt_re_qp *qp, *sh_qp;
 	struct bnxt_qplib_cqe *cqe;
 	int i, ncqe, budget;
 	struct bnxt_qplib_q *sq;
@@ -3170,7 +3395,10 @@
 				continue;
 			}
 			wc->qp = &qp->ib_qp;
-			wc->ex.imm_data = cqe->immdata;
+			if (cqe->flags & CQ_RES_RC_FLAGS_IMM)
+				wc->ex.imm_data = cpu_to_be32(cqe->immdata);
+			else
+				wc->ex.invalidate_rkey = cqe->invrkey;
 			wc->src_qp = cqe->src_qp;
 			memcpy(wc->smac, cqe->smac, ETH_ALEN);
 			wc->port_num = 1;
@@ -3178,8 +3406,9 @@
 
 			switch (cqe->opcode) {
 			case CQ_BASE_CQE_TYPE_REQ:
-				if (qp->rdev->qp1_sqp && qp->qplib_qp.id ==
-				    qp->rdev->qp1_sqp->qplib_qp.id) {
+				sh_qp = qp->rdev->gsi_ctx.gsi_sqp;
+				if (sh_qp &&
+				    qp->qplib_qp.id == sh_qp->qplib_qp.id) {
 					/* Handle this completion with
 					 * the stored completion
 					 */
@@ -3205,7 +3434,7 @@
 				 * stored in the table
 				 */
 				tbl_idx = cqe->wr_id;
-				sqp_entry = &cq->rdev->sqp_tbl[tbl_idx];
+				sqp_entry = &cq->rdev->gsi_ctx.sqp_tbl[tbl_idx];
 				wc->wr_id = sqp_entry->wrid;
 				bnxt_re_process_res_rawqp1_wc(wc, cqe);
 				break;
@@ -3213,8 +3442,9 @@
 				bnxt_re_process_res_rc_wc(wc, cqe);
 				break;
 			case CQ_BASE_CQE_TYPE_RES_UD:
-				if (qp->rdev->qp1_sqp && qp->qplib_qp.id ==
-				    qp->rdev->qp1_sqp->qplib_qp.id) {
+				sh_qp = qp->rdev->gsi_ctx.gsi_sqp;
+				if (sh_qp &&
+				    qp->qplib_qp.id == sh_qp->qplib_qp.id) {
 					/* Handle this completion with
 					 * the stored completion
 					 */
@@ -3323,8 +3553,10 @@
 	int rc;
 
 	rc = bnxt_qplib_free_mrw(&rdev->qplib_res, &mr->qplib_mr);
-	if (rc)
+	if (rc) {
 		dev_err(rdev_to_dev(rdev), "Dereg MR failed: %#x\n", rc);
+		return rc;
+	}
 
 	if (mr->pages) {
 		rc = bnxt_qplib_free_fast_reg_page_list(&rdev->qplib_res,
@@ -3530,7 +3762,7 @@
 	/* The fixed portion of the rkey is the same as the lkey */
 	mr->ib_mr.rkey = mr->qplib_mr.rkey;
 
-	umem = ib_umem_get(udata, start, length, mr_access_flags, 0);
+	umem = ib_umem_get(&rdev->ibdev, start, length, mr_access_flags);
 	if (IS_ERR(umem)) {
 		dev_err(rdev_to_dev(rdev), "Failed to get umem");
 		rc = -EFAULT;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/bnxt_re/main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/bnxt_re/main.c
@@ -70,7 +70,7 @@
 		BNXT_RE_DESC "\n";
 
 MODULE_AUTHOR("Eddie Wai <eddie.wai@broadcom.com>");
-MODULE_DESCRIPTION(BNXT_RE_DESC " Driver");
+MODULE_DESCRIPTION(BNXT_RE_DESC);
 MODULE_LICENSE("Dual BSD/GPL");
 
 /* globals */
@@ -119,61 +119,76 @@
  * reserved for the function. The driver may choose to allocate fewer
  * resources than the firmware maximum.
  */
-static void bnxt_re_set_resource_limits(struct bnxt_re_dev *rdev)
+static void bnxt_re_limit_pf_res(struct bnxt_re_dev *rdev)
 {
-	u32 vf_qps = 0, vf_srqs = 0, vf_cqs = 0, vf_mrws = 0, vf_gids = 0;
-	u32 i;
+	struct bnxt_qplib_dev_attr *attr;
+	struct bnxt_qplib_ctx *ctx;
+	int i;
+
+	attr = &rdev->dev_attr;
+	ctx = &rdev->qplib_ctx;
+
+	ctx->qpc_count = min_t(u32, BNXT_RE_MAX_QPC_COUNT,
+			       attr->max_qp);
+	ctx->mrw_count = BNXT_RE_MAX_MRW_COUNT_256K;
+	/* Use max_mr from fw since max_mrw does not get set */
+	ctx->mrw_count = min_t(u32, ctx->mrw_count, attr->max_mr);
+	ctx->srqc_count = min_t(u32, BNXT_RE_MAX_SRQC_COUNT,
+				attr->max_srq);
+	ctx->cq_count = min_t(u32, BNXT_RE_MAX_CQ_COUNT, attr->max_cq);
+	if (!bnxt_qplib_is_chip_gen_p5(&rdev->chip_ctx))
+		for (i = 0; i < MAX_TQM_ALLOC_REQ; i++)
+			rdev->qplib_ctx.tqm_count[i] =
+			rdev->dev_attr.tqm_alloc_reqs[i];
+}
+
+static void bnxt_re_limit_vf_res(struct bnxt_qplib_ctx *qplib_ctx, u32 num_vf)
+{
+	struct bnxt_qplib_vf_res *vf_res;
+	u32 mrws = 0;
 	u32 vf_pct;
+	u32 nvfs;
+
+	vf_res = &qplib_ctx->vf_res;
+	/*
+	 * Reserve a set of resources for the PF. Divide the remaining
+	 * resources among the VFs
+	 */
+	vf_pct = 100 - BNXT_RE_PCT_RSVD_FOR_PF;
+	nvfs = num_vf;
+	num_vf = 100 * num_vf;
+	vf_res->max_qp_per_vf = (qplib_ctx->qpc_count * vf_pct) / num_vf;
+	vf_res->max_srq_per_vf = (qplib_ctx->srqc_count * vf_pct) / num_vf;
+	vf_res->max_cq_per_vf = (qplib_ctx->cq_count * vf_pct) / num_vf;
+	/*
+	 * The driver allows many more MRs than other resources. If the
+	 * firmware does also, then reserve a fixed amount for the PF and
+	 * divide the rest among VFs. VFs may use many MRs for NFS
+	 * mounts, ISER, NVME applications, etc. If the firmware severely
+	 * restricts the number of MRs, then let PF have half and divide
+	 * the rest among VFs, as for the other resource types.
+	 */
+	if (qplib_ctx->mrw_count < BNXT_RE_MAX_MRW_COUNT_64K) {
+		mrws = qplib_ctx->mrw_count * vf_pct;
+		nvfs = num_vf;
+	} else {
+		mrws = qplib_ctx->mrw_count - BNXT_RE_RESVD_MR_FOR_PF;
+	}
+	vf_res->max_mrw_per_vf = (mrws / nvfs);
+	vf_res->max_gid_per_vf = BNXT_RE_MAX_GID_PER_VF;
+}
+
+static void bnxt_re_set_resource_limits(struct bnxt_re_dev *rdev)
+{
 	u32 num_vfs;
-	struct bnxt_qplib_dev_attr *dev_attr = &rdev->dev_attr;
 
-	rdev->qplib_ctx.qpc_count = min_t(u32, BNXT_RE_MAX_QPC_COUNT,
-					  dev_attr->max_qp);
+	memset(&rdev->qplib_ctx.vf_res, 0, sizeof(struct bnxt_qplib_vf_res));
+	bnxt_re_limit_pf_res(rdev);
 
-	rdev->qplib_ctx.mrw_count = BNXT_RE_MAX_MRW_COUNT_256K;
-	/* Use max_mr from fw since max_mrw does not get set */
-	rdev->qplib_ctx.mrw_count = min_t(u32, rdev->qplib_ctx.mrw_count,
-					  dev_attr->max_mr);
-	rdev->qplib_ctx.srqc_count = min_t(u32, BNXT_RE_MAX_SRQC_COUNT,
-					   dev_attr->max_srq);
-	rdev->qplib_ctx.cq_count = min_t(u32, BNXT_RE_MAX_CQ_COUNT,
-					 dev_attr->max_cq);
-
-	for (i = 0; i < MAX_TQM_ALLOC_REQ; i++)
-		rdev->qplib_ctx.tqm_count[i] =
-		rdev->dev_attr.tqm_alloc_reqs[i];
-
-	if (rdev->num_vfs) {
-		/*
-		 * Reserve a set of resources for the PF. Divide the remaining
-		 * resources among the VFs
-		 */
-		vf_pct = 100 - BNXT_RE_PCT_RSVD_FOR_PF;
-		num_vfs = 100 * rdev->num_vfs;
-		vf_qps = (rdev->qplib_ctx.qpc_count * vf_pct) / num_vfs;
-		vf_srqs = (rdev->qplib_ctx.srqc_count * vf_pct) / num_vfs;
-		vf_cqs = (rdev->qplib_ctx.cq_count * vf_pct) / num_vfs;
-		/*
-		 * The driver allows many more MRs than other resources. If the
-		 * firmware does also, then reserve a fixed amount for the PF
-		 * and divide the rest among VFs. VFs may use many MRs for NFS
-		 * mounts, ISER, NVME applications, etc. If the firmware
-		 * severely restricts the number of MRs, then let PF have
-		 * half and divide the rest among VFs, as for the other
-		 * resource types.
-		 */
-		if (rdev->qplib_ctx.mrw_count < BNXT_RE_MAX_MRW_COUNT_64K)
-			vf_mrws = rdev->qplib_ctx.mrw_count * vf_pct / num_vfs;
-		else
-			vf_mrws = (rdev->qplib_ctx.mrw_count -
-				   BNXT_RE_RESVD_MR_FOR_PF) / rdev->num_vfs;
-		vf_gids = BNXT_RE_MAX_GID_PER_VF;
-	}
-	rdev->qplib_ctx.vf_res.max_mrw_per_vf = vf_mrws;
-	rdev->qplib_ctx.vf_res.max_gid_per_vf = vf_gids;
-	rdev->qplib_ctx.vf_res.max_qp_per_vf = vf_qps;
-	rdev->qplib_ctx.vf_res.max_srq_per_vf = vf_srqs;
-	rdev->qplib_ctx.vf_res.max_cq_per_vf = vf_cqs;
+	num_vfs =  bnxt_qplib_is_chip_gen_p5(&rdev->chip_ctx) ?
+			BNXT_RE_GEN_P5_MAX_VF : rdev->num_vfs;
+	if (num_vfs)
+		bnxt_re_limit_vf_res(&rdev->qplib_ctx, num_vfs);
 }
 
 /* for handling bnxt_en callbacks later */
@@ -193,9 +208,11 @@
 		return;
 
 	rdev->num_vfs = num_vfs;
-	bnxt_re_set_resource_limits(rdev);
-	bnxt_qplib_set_func_resources(&rdev->qplib_res, &rdev->rcfw,
-				      &rdev->qplib_ctx);
+	if (!bnxt_qplib_is_chip_gen_p5(&rdev->chip_ctx)) {
+		bnxt_re_set_resource_limits(rdev);
+		bnxt_qplib_set_func_resources(&rdev->qplib_res, &rdev->rcfw,
+					      &rdev->qplib_ctx);
+	}
 }
 
 static void bnxt_re_shutdown(void *p)
@@ -477,6 +494,7 @@
 	bnxt_re_init_hwrm_hdr(rdev, (void *)&req, HWRM_STAT_CTX_ALLOC, -1, -1);
 	req.update_period_ms = cpu_to_le32(1000);
 	req.stats_dma_addr = cpu_to_le64(dma_map);
+	req.stats_dma_length = cpu_to_le16(sizeof(struct ctx_hw_stats_ext));
 	req.stat_ctx_flags = STAT_CTX_ALLOC_REQ_STAT_CTX_FLAGS_ROCE;
 	bnxt_re_fill_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp,
 			    sizeof(resp), DFLT_HWRM_CMD_TIMEOUT);
@@ -788,7 +806,8 @@
 	struct ib_event event;
 	unsigned int flags;
 
-	if (qp->qplib_qp.state == CMDQ_MODIFY_QP_NEW_STATE_ERR) {
+	if (qp->qplib_qp.state == CMDQ_MODIFY_QP_NEW_STATE_ERR &&
+	    rdma_is_kernel_res(&qp->ib_qp.res)) {
 		flags = bnxt_re_lock_cqs(qp);
 		bnxt_qplib_add_flush_qp(&qp->qplib_qp);
 		bnxt_re_unlock_cqs(qp, flags);
@@ -895,10 +914,14 @@
 	return 0;
 }
 
+#define BNXT_RE_GEN_P5_PF_NQ_DB		0x10000
+#define BNXT_RE_GEN_P5_VF_NQ_DB		0x4000
 static u32 bnxt_re_get_nqdb_offset(struct bnxt_re_dev *rdev, u16 indx)
 {
 	return bnxt_qplib_is_chip_gen_p5(&rdev->chip_ctx) ?
-				0x10000 : rdev->msix_entries[indx].db_offset;
+		(rdev->is_virtfn ? BNXT_RE_GEN_P5_VF_NQ_DB :
+				   BNXT_RE_GEN_P5_PF_NQ_DB) :
+				   rdev->msix_entries[indx].db_offset;
 }
 
 static void bnxt_re_cleanup_res(struct bnxt_re_dev *rdev)
@@ -1104,7 +1127,8 @@
 static bool bnxt_re_is_qp1_or_shadow_qp(struct bnxt_re_dev *rdev,
 					struct bnxt_re_qp *qp)
 {
-	return (qp->ib_qp.qp_type == IB_QPT_GSI) || (qp == rdev->qp1_sqp);
+	return (qp->ib_qp.qp_type == IB_QPT_GSI) ||
+	       (qp == rdev->gsi_ctx.gsi_sqp);
 }
 
 static void bnxt_re_dev_stop(struct bnxt_re_dev *rdev)
@@ -1270,10 +1294,10 @@
 		return;
 	}
 	rdev->qplib_ctx.hwrm_intf_ver =
-		(u64)resp.hwrm_intf_major << 48 |
-		(u64)resp.hwrm_intf_minor << 32 |
-		(u64)resp.hwrm_intf_build << 16 |
-		resp.hwrm_intf_patch;
+		(u64)le16_to_cpu(resp.hwrm_intf_major) << 48 |
+		(u64)le16_to_cpu(resp.hwrm_intf_minor) << 32 |
+		(u64)le16_to_cpu(resp.hwrm_intf_build) << 16 |
+		le16_to_cpu(resp.hwrm_intf_patch);
 }
 
 static void bnxt_re_ib_unreg(struct bnxt_re_dev *rdev)
@@ -1408,8 +1432,8 @@
 				     rdev->is_virtfn);
 	if (rc)
 		goto disable_rcfw;
-	if (!rdev->is_virtfn)
-		bnxt_re_set_resource_limits(rdev);
+
+	bnxt_re_set_resource_limits(rdev);
 
 	rc = bnxt_qplib_alloc_ctx(rdev->en_dev->pdev, &rdev->qplib_ctx, 0,
 				  bnxt_qplib_is_chip_gen_p5(&rdev->chip_ctx));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/bnxt_re/qplib_fp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/bnxt_re/qplib_fp.c
@@ -642,12 +642,13 @@
 	int rc = 0;
 
 	RCFW_CMD_PREP(req, QUERY_SRQ, cmd_flags);
-	req.srq_cid = cpu_to_le32(srq->id);
 
 	/* Configure the request */
 	sbuf = bnxt_qplib_rcfw_alloc_sbuf(rcfw, sizeof(*sb));
 	if (!sbuf)
 		return -ENOMEM;
+	req.resp_size = sizeof(*sb) / BNXT_QPLIB_CMDQE_UNITS;
+	req.srq_cid = cpu_to_le32(srq->id);
 	sb = sbuf->sb;
 	rc = bnxt_qplib_rcfw_send_message(rcfw, (void *)&req, (void *)&resp,
 					  (void *)sbuf, 0);
@@ -1104,8 +1105,6 @@
 			qp->path_mtu =
 				CMDQ_MODIFY_QP_PATH_MTU_MTU_2048;
 		}
-		qp->modify_flags &=
-			~CMDQ_MODIFY_QP_MODIFY_MASK_VLAN_ID;
 		/* Bono FW require the max_dest_rd_atomic to be >= 1 */
 		if (qp->max_dest_rd_atomic < 1)
 			qp->max_dest_rd_atomic = 1;
@@ -2283,13 +2282,13 @@
 			/* Add qp to flush list of the CQ */
 			bnxt_qplib_add_flush_qp(qp);
 		} else {
+			/* Before we complete, do WA 9060 */
+			if (do_wa9060(qp, cq, cq_cons, sw_sq_cons,
+				      cqe_sq_cons)) {
+				*lib_qp = qp;
+				goto out;
+			}
 			if (swq->flags & SQ_SEND_FLAGS_SIGNAL_COMP) {
-				/* Before we complete, do WA 9060 */
-				if (do_wa9060(qp, cq, cq_cons, sw_sq_cons,
-					      cqe_sq_cons)) {
-					*lib_qp = qp;
-					goto out;
-				}
 				cqe->status = CQ_REQ_STATUS_OK;
 				cqe++;
 				(*budget)--;
@@ -2605,11 +2604,8 @@
 
 	qp = (struct bnxt_qplib_qp *)((unsigned long)
 				      le64_to_cpu(hwcqe->qp_handle));
-	if (!qp) {
-		dev_err(&cq->hwq.pdev->dev,
-			"FP: CQ Process terminal qp is NULL\n");
+	if (!qp)
 		return -EINVAL;
-	}
 
 	/* Must block new posting of SQ and RQ */
 	qp->state = CMDQ_MODIFY_QP_NEW_STATE_ERR;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/bnxt_re/qplib_fp.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/bnxt_re/qplib_fp.h
@@ -145,12 +145,12 @@
 		/* Send, with imm, inval key */
 		struct {
 			union {
-				__be32	imm_data;
+				u32	imm_data;
 				u32	inv_key;
 			};
 			u32		q_key;
 			u32		dst_qp;
-			u16		avid;
+			u32		avid;
 		} send;
 
 		/* Send Raw Ethernet and QP1 */
@@ -163,7 +163,7 @@
 		/* RDMA write, with imm, read */
 		struct {
 			union {
-				__be32	imm_data;
+				u32	imm_data;
 				u32	inv_key;
 			};
 			u64		remote_va;
@@ -350,7 +350,7 @@
 	u16				cfa_meta;
 	u64				wr_id;
 	union {
-		__be32			immdata;
+		u32			immdata;
 		u32			invrkey;
 	};
 	u64				qp_handle;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
@@ -244,7 +244,7 @@
 		/* failed with status */
 		dev_err(&rcfw->pdev->dev, "cmdq[%#x]=%#x status %#x\n",
 			cookie, opcode, evnt->status);
-		rc = -EFAULT;
+		rc = -EIO;
 	}
 
 	return rc;
@@ -494,8 +494,10 @@
 	 * shall setup this area for VF. Skipping the
 	 * HW programming
 	 */
-	if (is_virtfn || bnxt_qplib_is_chip_gen_p5(rcfw->res->cctx))
+	if (is_virtfn)
 		goto skip_ctx_setup;
+	if (bnxt_qplib_is_chip_gen_p5(rcfw->res->cctx))
+		goto config_vf_res;
 
 	level = ctx->qpc_tbl.level;
 	req.qpc_pg_size_qpc_lvl = (level << CMDQ_INITIALIZE_FW_QPC_LVL_SFT) |
@@ -540,6 +542,7 @@
 	req.number_of_srq = cpu_to_le32(ctx->srqc_tbl.max_elements);
 	req.number_of_cq = cpu_to_le32(ctx->cq_tbl.max_elements);
 
+config_vf_res:
 	req.max_qp_per_vf = cpu_to_le32(ctx->vf_res.max_qp_per_vf);
 	req.max_mrw_per_vf = cpu_to_le32(ctx->vf_res.max_mrw_per_vf);
 	req.max_srq_per_vf = cpu_to_le32(ctx->vf_res.max_srq_per_vf);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/bnxt_re/qplib_res.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/bnxt_re/qplib_res.c
@@ -736,6 +736,7 @@
 
 unmap_io:
 	pci_iounmap(res->pdev, dpit->dbr_bar_reg_iomem);
+	dpit->dbr_bar_reg_iomem = NULL;
 	return -ENOMEM;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/bnxt_re/qplib_res.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/bnxt_re/qplib_res.h
@@ -186,7 +186,9 @@
 	u8	chip_metal;
 };
 
-#define CHIP_NUM_57500          0x1750
+#define CHIP_NUM_57508		0x1750
+#define CHIP_NUM_57504		0x1751
+#define CHIP_NUM_57502		0x1752
 
 struct bnxt_qplib_res {
 	struct pci_dev			*pdev;
@@ -203,7 +205,9 @@
 
 static inline bool bnxt_qplib_is_chip_gen_p5(struct bnxt_qplib_chip_ctx *cctx)
 {
-	return (cctx->chip_num == CHIP_NUM_57500);
+	return (cctx->chip_num == CHIP_NUM_57508 ||
+		cctx->chip_num == CHIP_NUM_57504 ||
+		cctx->chip_num == CHIP_NUM_57502);
 }
 
 static inline u8 bnxt_qplib_get_hwq_type(struct bnxt_qplib_res *res)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/bnxt_re/qplib_sp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/bnxt_re/qplib_sp.c
@@ -118,7 +118,7 @@
 	 * 128 WQEs needs to be reserved for the HW (8916). Prevent
 	 * reporting the max number
 	 */
-	attr->max_qp_wqes -= BNXT_QPLIB_RESERVED_QP_WRS;
+	attr->max_qp_wqes -= BNXT_QPLIB_RESERVED_QP_WRS + 1;
 	attr->max_qp_sges = bnxt_qplib_is_chip_gen_p5(rcfw->res->cctx) ?
 			    6 : sb->max_sge;
 	attr->max_cq = le32_to_cpu(sb->max_cq);
@@ -152,7 +152,7 @@
 	attr->max_inline_data = le32_to_cpu(sb->max_inline_data);
 	attr->l2_db_size = (sb->l2_db_space_size + 1) *
 			    (0x01 << RCFW_DBR_BASE_PAGE_SHIFT);
-	attr->max_sgid = le32_to_cpu(sb->max_gid);
+	attr->max_sgid = BNXT_QPLIB_NUM_GIDS_SUPPORTED;
 
 	bnxt_qplib_query_version(rcfw, attr->fw_ver);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/bnxt_re/qplib_sp.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/bnxt_re/qplib_sp.h
@@ -47,6 +47,7 @@
 struct bnxt_qplib_dev_attr {
 #define FW_VER_ARR_LEN			4
 	u8				fw_ver[FW_VER_ARR_LEN];
+#define BNXT_QPLIB_NUM_GIDS_SUPPORTED	256
 	u16				max_sgid;
 	u16				max_mrw;
 	u32				max_qp;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/cxgb3/iwch_provider.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/cxgb3/iwch_provider.c
@@ -451,7 +451,7 @@
 
 	mhp->rhp = rhp;
 
-	mhp->umem = ib_umem_get(udata, start, length, acc, 0);
+	mhp->umem = ib_umem_get(pd->device, start, length, acc);
 	if (IS_ERR(mhp->umem)) {
 		err = PTR_ERR(mhp->umem);
 		kfree(mhp);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/cxgb4/cm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/cxgb4/cm.c
@@ -1222,6 +1222,8 @@
 	int ret;
 
 	ep = lookup_atid(t, atid);
+	if (!ep)
+		return -EINVAL;
 
 	pr_debug("ep %p tid %u snd_isn %u rcv_isn %u\n", ep, tid,
 		 be32_to_cpu(req->snd_isn), be32_to_cpu(req->rcv_isn));
@@ -1965,6 +1967,9 @@
 	int win;
 
 	skb = get_skb(NULL, sizeof(*req), GFP_KERNEL);
+	if (!skb)
+		return -ENOMEM;
+
 	req = __skb_put_zero(skb, sizeof(*req));
 	req->op_compl = htonl(WR_OP_V(FW_OFLD_CONNECTION_WR));
 	req->len16_pkd = htonl(FW_WR_LEN16_V(DIV_ROUND_UP(sizeof(*req), 16)));
@@ -2081,7 +2086,7 @@
 	err = -ENOMEM;
 	if (n->dev->flags & IFF_LOOPBACK) {
 		if (iptype == 4)
-			pdev = ip_dev_find(&init_net, *(__be32 *)peer_ip);
+			pdev = __ip_dev_find(&init_net, *(__be32 *)peer_ip, false);
 		else if (IS_ENABLED(CONFIG_IPV6))
 			for_each_netdev(&init_net, pdev) {
 				if (ipv6_chk_addr(&init_net,
@@ -2096,12 +2101,12 @@
 			err = -ENODEV;
 			goto out;
 		}
+		if (is_vlan_dev(pdev))
+			pdev = vlan_dev_real_dev(pdev);
 		ep->l2t = cxgb4_l2t_get(cdev->rdev.lldi.l2t,
 					n, pdev, rt_tos2priority(tos));
-		if (!ep->l2t) {
-			dev_put(pdev);
+		if (!ep->l2t)
 			goto out;
-		}
 		ep->mtu = pdev->mtu;
 		ep->tx_chan = cxgb4_port_chan(pdev);
 		ep->smac_idx = ((struct port_info *)netdev_priv(pdev))->smt_idx;
@@ -2114,7 +2119,6 @@
 		ep->rss_qid = cdev->rdev.lldi.rxq_ids[
 			cxgb4_port_idx(pdev) * step];
 		set_tcp_window(ep, (struct port_info *)netdev_priv(pdev));
-		dev_put(pdev);
 	} else {
 		pdev = get_real_dev(n->dev);
 		ep->l2t = cxgb4_l2t_get(cdev->rdev.lldi.l2t,
@@ -2276,6 +2280,9 @@
 	int ret = 0;
 
 	ep = lookup_atid(t, atid);
+	if (!ep)
+		return -EINVAL;
+
 	la = (struct sockaddr_in *)&ep->com.local_addr;
 	ra = (struct sockaddr_in *)&ep->com.remote_addr;
 	la6 = (struct sockaddr_in6 *)&ep->com.local_addr;
@@ -2891,8 +2898,7 @@
 			srqidx = ABORT_RSS_SRQIDX_G(
 					be32_to_cpu(req->srqidx_status));
 			if (srqidx) {
-				complete_cached_srq_buffers(ep,
-							    req->srqidx_status);
+				complete_cached_srq_buffers(ep, srqidx);
 			} else {
 				/* Hold ep ref until finish_peer_abort() */
 				c4iw_get_ep(&ep->com);
@@ -3036,6 +3042,10 @@
 				       C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
 		}
 
+		/* As per draft-hilland-iwarp-verbs-v1.0, sec 6.2.3,
+		 * when entering the TERM state the RNIC MUST initiate a CLOSE.
+		 */
+		c4iw_ep_disconnect(ep, 1, GFP_KERNEL);
 		c4iw_put_ep(&ep->com);
 	} else
 		pr_warn("TERM received tid %u no ep/qp\n", tid);
@@ -3279,7 +3289,7 @@
 
 static int pick_local_ip6addrs(struct c4iw_dev *dev, struct iw_cm_id *cm_id)
 {
-	struct in6_addr uninitialized_var(addr);
+	struct in6_addr addr;
 	struct sockaddr_in6 *la6 = (struct sockaddr_in6 *)&cm_id->m_local_addr;
 	struct sockaddr_in6 *ra6 = (struct sockaddr_in6 *)&cm_id->m_remote_addr;
 
@@ -3379,7 +3389,7 @@
 		if (raddr->sin_addr.s_addr == htonl(INADDR_ANY)) {
 			err = pick_local_ipaddrs(dev, cm_id);
 			if (err)
-				goto fail2;
+				goto fail3;
 		}
 
 		/* find a route */
@@ -3401,7 +3411,7 @@
 		if (ipv6_addr_type(&raddr6->sin6_addr) == IPV6_ADDR_ANY) {
 			err = pick_local_ip6addrs(dev, cm_id);
 			if (err)
-				goto fail2;
+				goto fail3;
 		}
 
 		/* find a route */
@@ -3607,13 +3617,14 @@
 	    ep->com.local_addr.ss_family == AF_INET) {
 		err = cxgb4_remove_server_filter(
 			ep->com.dev->rdev.lldi.ports[0], ep->stid,
-			ep->com.dev->rdev.lldi.rxq_ids[0], 0);
+			ep->com.dev->rdev.lldi.rxq_ids[0], false);
 	} else {
 		struct sockaddr_in6 *sin6;
 		c4iw_init_wr_wait(ep->com.wr_waitp);
 		err = cxgb4_remove_server(
 				ep->com.dev->rdev.lldi.ports[0], ep->stid,
-				ep->com.dev->rdev.lldi.rxq_ids[0], 0);
+				ep->com.dev->rdev.lldi.rxq_ids[0],
+				ep->com.local_addr.ss_family == AF_INET6);
 		if (err)
 			goto done;
 		err = c4iw_wait_for_reply(&ep->com.dev->rdev, ep->com.wr_waitp,
@@ -3874,8 +3885,8 @@
 		return 0;
 	}
 
-	ep->srqe_idx = t4_tcb_get_field32(tcb, TCB_RQ_START_W, TCB_RQ_START_W,
-			TCB_RQ_START_S);
+	ep->srqe_idx = t4_tcb_get_field32(tcb, TCB_RQ_START_W, TCB_RQ_START_M,
+					  TCB_RQ_START_S);
 cleanup:
 	pr_debug("ep %p tid %u %016x\n", ep, ep->hwtid, ep->srqe_idx);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/cxgb4/cq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/cxgb4/cq.c
@@ -754,7 +754,7 @@
 static int __c4iw_poll_cq_one(struct c4iw_cq *chp, struct c4iw_qp *qhp,
 			      struct ib_wc *wc, struct c4iw_srq *srq)
 {
-	struct t4_cqe uninitialized_var(cqe);
+	struct t4_cqe cqe;
 	struct t4_wq *wq = qhp ? &qhp->wq : NULL;
 	u32 credit = 0;
 	u8 cqe_flushed;
@@ -1007,6 +1007,9 @@
 	if (attr->flags)
 		return -EINVAL;
 
+	if (entries < 1 || entries > ibdev->attrs.max_cqe)
+		return -EINVAL;
+
 	if (vector >= rhp->rdev.lldi.nciq)
 		return -EINVAL;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/cxgb4/device.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/cxgb4/device.c
@@ -953,6 +953,7 @@
 static void c4iw_remove(struct uld_ctx *ctx)
 {
 	pr_debug("c4iw_dev %p\n", ctx->dev);
+	debugfs_remove_recursive(ctx->dev->debugfs_root);
 	c4iw_unregister_device(ctx->dev);
 	c4iw_dealloc(ctx);
 }
@@ -1113,8 +1114,10 @@
 	 * The math here assumes sizeof cpl_pass_accept_req >= sizeof
 	 * cpl_rx_pkt.
 	 */
-	skb = alloc_skb(gl->tot_len + sizeof(struct cpl_pass_accept_req) +
-			sizeof(struct rss_header) - pktshift, GFP_ATOMIC);
+	skb = alloc_skb(size_add(gl->tot_len,
+				 sizeof(struct cpl_pass_accept_req) +
+				 sizeof(struct rss_header)) - pktshift,
+			GFP_ATOMIC);
 	if (unlikely(!skb))
 		return NULL;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/cxgb4/mem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/cxgb4/mem.c
@@ -399,7 +399,6 @@
 	mmid = stag >> 8;
 	mhp->ibmr.rkey = mhp->ibmr.lkey = stag;
 	mhp->ibmr.length = mhp->attr.len;
-	mhp->ibmr.iova = mhp->attr.va_fbo;
 	mhp->ibmr.page_size = 1U << (mhp->attr.page_size + 12);
 	pr_debug("mmid 0x%x mhp %p\n", mmid, mhp);
 	return xa_insert_irq(&mhp->rhp->mrs, mmid, mhp, GFP_KERNEL);
@@ -543,7 +542,7 @@
 
 	mhp->rhp = rhp;
 
-	mhp->umem = ib_umem_get(udata, start, length, acc, 0);
+	mhp->umem = ib_umem_get(pd->device, start, length, acc);
 	if (IS_ERR(mhp->umem))
 		goto err_free_skb;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/cxgb4/qp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/cxgb4/qp.c
@@ -295,6 +295,7 @@
 	if (user && (!wq->sq.bar2_pa || (need_rq && !wq->rq.bar2_pa))) {
 		pr_warn("%s: sqid %u or rqid %u not in BAR2 range\n",
 			pci_name(rdev->lldi.pdev), wq->sq.qid, wq->rq.qid);
+		ret = -EINVAL;
 		goto free_dma;
 	}
 
@@ -1948,10 +1949,10 @@
 			qhp->attr.layer_etype = attrs->layer_etype;
 			qhp->attr.ecode = attrs->ecode;
 			ep = qhp->ep;
-			c4iw_get_ep(&ep->com);
-			disconnect = 1;
 			if (!internal) {
+				c4iw_get_ep(&ep->com);
 				terminate = 1;
+				disconnect = 1;
 			} else {
 				terminate = qhp->attr.send_term;
 				ret = rdma_fini(rhp, qhp, ep);
@@ -2468,10 +2469,11 @@
 	memset(attr, 0, sizeof(*attr));
 	memset(init_attr, 0, sizeof(*init_attr));
 	attr->qp_state = to_ib_qp_state(qhp->attr.state);
+	attr->cur_qp_state = to_ib_qp_state(qhp->attr.state);
 	init_attr->cap.max_send_wr = qhp->attr.sq_num_entries;
 	init_attr->cap.max_recv_wr = qhp->attr.rq_num_entries;
 	init_attr->cap.max_send_sge = qhp->attr.sq_max_sges;
-	init_attr->cap.max_recv_sge = qhp->attr.sq_max_sges;
+	init_attr->cap.max_recv_sge = qhp->attr.rq_max_sges;
 	init_attr->cap.max_inline_data = T4_MAX_SEND_INLINE;
 	init_attr->sq_sig_type = qhp->sq_sig_all ? IB_SIGNAL_ALL_WR : 0;
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/cxgb4/resource.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/cxgb4/resource.c
@@ -216,7 +216,7 @@
 			goto out;
 		entry->qid = qid;
 		list_add_tail(&entry->entry, &uctx->cqids);
-		for (i = qid; i & rdev->qpmask; i++) {
+		for (i = qid + 1; i & rdev->qpmask; i++) {
 			entry = kmalloc(sizeof(*entry), GFP_KERNEL);
 			if (!entry)
 				goto out;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/efa/efa_admin_cmds_defs.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/efa/efa_admin_cmds_defs.h
@@ -579,7 +579,8 @@
 	/* Number of sub-CQs to be created for each CQ */
 	u16 sub_cqs_per_cq;
 
-	u16 reserved;
+	/* Minimum number of WQEs per SQ */
+	u16 min_sq_depth;
 
 	/*
 	 * Maximum number of SGEs (buffs) allowed for a single send work
@@ -604,6 +605,20 @@
 
 	/* The maximum size of LLQ in bytes */
 	u32 max_llq_size;
+
+	/* Maximum number of SGEs for a single RDMA read WQE */
+	u16 max_wr_rdma_sges;
+
+	/*
+	 * Maximum number of bytes that can be written to SQ between two
+	 * consecutive doorbells (in units of 64B). Driver must ensure that only
+	 * complete WQEs are written to queue before issuing a doorbell.
+	 * Examples: max_tx_batch=16 and WQE size = 64B, means up to 16 WQEs can
+	 * be written to SQ between two consecutive doorbells. max_tx_batch=11
+	 * and WQE size = 128B, means up to 5 WQEs can be written to SQ between
+	 * two consecutive doorbells. Zero means unlimited.
+	 */
+	u16 max_tx_batch;
 };
 
 struct efa_admin_feature_aenq_desc {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/efa/efa_com.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/efa/efa_com.c
@@ -317,6 +317,7 @@
 						       struct efa_admin_acq_entry *comp,
 						       size_t comp_size_in_bytes)
 {
+	struct efa_admin_aq_entry *aqe;
 	struct efa_comp_ctx *comp_ctx;
 	u16 queue_size_mask;
 	u16 cmd_id;
@@ -350,7 +351,9 @@
 
 	reinit_completion(&comp_ctx->wait_event);
 
-	memcpy(&aq->sq.entries[pi], cmd, cmd_size_in_bytes);
+	aqe = &aq->sq.entries[pi];
+	memset(aqe, 0, sizeof(*aqe));
+	memcpy(aqe, cmd, cmd_size_in_bytes);
 
 	aq->sq.pc++;
 	atomic64_inc(&aq->stats.submitted_cmd);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/efa/efa_com_cmd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/efa/efa_com_cmd.c
@@ -500,6 +500,8 @@
 	result->max_ah = resp.u.queue_attr.max_ah;
 	result->max_llq_size = resp.u.queue_attr.max_llq_size;
 	result->sub_cqs_per_cq = resp.u.queue_attr.sub_cqs_per_cq;
+	result->max_tx_batch = resp.u.queue_attr.max_tx_batch;
+	result->min_sq_depth = resp.u.queue_attr.min_sq_depth;
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/efa/efa_com_cmd.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/efa/efa_com_cmd.h
@@ -127,6 +127,8 @@
 	u16 sub_cqs_per_cq;
 	u16 max_sq_sge;
 	u16 max_rq_sge;
+	u16 max_tx_batch;
+	u16 min_sq_depth;
 	u8 db_bar;
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/efa/efa_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/efa/efa_main.c
@@ -10,10 +10,12 @@
 
 #include "efa.h"
 
-#define PCI_DEV_ID_EFA_VF 0xefa0
+#define PCI_DEV_ID_EFA0_VF 0xefa0
+#define PCI_DEV_ID_EFA1_VF 0xefa1
 
 static const struct pci_device_id efa_pci_tbl[] = {
-	{ PCI_VDEVICE(AMAZON, PCI_DEV_ID_EFA_VF) },
+	{ PCI_VDEVICE(AMAZON, PCI_DEV_ID_EFA0_VF) },
+	{ PCI_VDEVICE(AMAZON, PCI_DEV_ID_EFA1_VF) },
 	{ }
 };
 
@@ -340,6 +342,7 @@
 	}
 
 	if (irq_num != msix_vecs) {
+		efa_disable_msix(dev);
 		dev_err(&dev->pdev->dev,
 			"Allocated %d MSI-X (out of %d requested)\n",
 			irq_num, msix_vecs);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/efa/efa_verbs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/efa/efa_verbs.c
@@ -745,7 +745,6 @@
 	rq_entry_inserted = true;
 	qp->qp_handle = create_qp_resp.qp_handle;
 	qp->ibqp.qp_num = create_qp_resp.qp_num;
-	qp->ibqp.qp_type = init_attr->qp_type;
 	qp->max_send_wr = init_attr->cap.max_send_wr;
 	qp->max_recv_wr = init_attr->cap.max_recv_wr;
 	qp->max_send_sge = init_attr->cap.max_send_sge;
@@ -1232,7 +1231,7 @@
  */
 static int pbl_indirect_initialize(struct efa_dev *dev, struct pbl_context *pbl)
 {
-	u32 size_in_pages = DIV_ROUND_UP(pbl->pbl_buf_size_in_bytes, PAGE_SIZE);
+	u32 size_in_pages = DIV_ROUND_UP(pbl->pbl_buf_size_in_bytes, EFA_CHUNK_PAYLOAD_SIZE);
 	struct scatterlist *sgl;
 	int sg_dma_cnt, err;
 
@@ -1423,7 +1422,7 @@
 		goto err_out;
 	}
 
-	mr->umem = ib_umem_get(udata, start, length, access_flags, 0);
+	mr->umem = ib_umem_get(ibpd->device, start, length, access_flags);
 	if (IS_ERR(mr->umem)) {
 		err = PTR_ERR(mr->umem);
 		ibdev_dbg(&dev->ibdev,
@@ -1538,11 +1537,39 @@
 	return efa_com_dealloc_uar(&dev->edev, &params);
 }
 
+#define EFA_CHECK_USER_COMP(_dev, _comp_mask, _attr, _mask, _attr_str) \
+	(_attr_str = (!(_dev)->dev_attr._attr || ((_comp_mask) & (_mask))) ? \
+		     NULL : #_attr)
+
+static int efa_user_comp_handshake(const struct ib_ucontext *ibucontext,
+				   const struct efa_ibv_alloc_ucontext_cmd *cmd)
+{
+	struct efa_dev *dev = to_edev(ibucontext->device);
+	char *attr_str;
+
+	if (EFA_CHECK_USER_COMP(dev, cmd->comp_mask, max_tx_batch,
+				EFA_ALLOC_UCONTEXT_CMD_COMP_TX_BATCH, attr_str))
+		goto err;
+
+	if (EFA_CHECK_USER_COMP(dev, cmd->comp_mask, min_sq_depth,
+				EFA_ALLOC_UCONTEXT_CMD_COMP_MIN_SQ_WR,
+				attr_str))
+		goto err;
+
+	return 0;
+
+err:
+	ibdev_dbg(&dev->ibdev, "Userspace handshake failed for %s attribute\n",
+		  attr_str);
+	return -EOPNOTSUPP;
+}
+
 int efa_alloc_ucontext(struct ib_ucontext *ibucontext, struct ib_udata *udata)
 {
 	struct efa_ucontext *ucontext = to_eucontext(ibucontext);
 	struct efa_dev *dev = to_edev(ibucontext->device);
 	struct efa_ibv_alloc_ucontext_resp resp = {};
+	struct efa_ibv_alloc_ucontext_cmd cmd = {};
 	struct efa_com_alloc_uar_result result;
 	int err;
 
@@ -1551,6 +1578,18 @@
 	 * we will ack input fields in our response.
 	 */
 
+	err = ib_copy_from_udata(&cmd, udata,
+				 min(sizeof(cmd), udata->inlen));
+	if (err) {
+		ibdev_dbg(&dev->ibdev,
+			  "Cannot copy udata for alloc_ucontext\n");
+		goto err_out;
+	}
+
+	err = efa_user_comp_handshake(ibucontext, &cmd);
+	if (err)
+		goto err_out;
+
 	err = efa_com_alloc_uar(&dev->edev, &result);
 	if (err)
 		goto err_out;
@@ -1563,6 +1602,8 @@
 	resp.sub_cqs_per_cq = dev->dev_attr.sub_cqs_per_cq;
 	resp.inline_buf_size = dev->dev_attr.inline_buf_size;
 	resp.max_llq_size = dev->dev_attr.max_llq_size;
+	resp.max_tx_batch = dev->dev_attr.max_tx_batch;
+	resp.min_sq_wr = dev->dev_attr.min_sq_depth;
 
 	if (udata && udata->outlen) {
 		err = ib_copy_to_udata(udata, &resp,
@@ -1612,11 +1653,13 @@
 	switch (entry->mmap_flag) {
 	case EFA_MMAP_IO_NC:
 		err = rdma_user_mmap_io(&ucontext->ibucontext, vma, pfn, length,
-					pgprot_noncached(vma->vm_page_prot));
+					pgprot_noncached(vma->vm_page_prot),
+					NULL);
 		break;
 	case EFA_MMAP_IO_WC:
 		err = rdma_user_mmap_io(&ucontext->ibucontext, vma, pfn, length,
-					pgprot_writecombine(vma->vm_page_prot));
+					pgprot_writecombine(vma->vm_page_prot),
+					NULL);
 		break;
 	case EFA_MMAP_DMA_PAGE:
 		for (va = vma->vm_start; va < vma->vm_end;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hfi1/affinity.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hfi1/affinity.c
@@ -218,6 +218,8 @@
 	for (node = 0; node < node_affinity.num_possible_nodes; node++)
 		hfi1_per_node_cntr[node] = 1;
 
+	pci_dev_put(dev);
+
 	return 0;
 }
 
@@ -479,6 +481,8 @@
 			  rvt_get_ibdev_name(&(dd)->verbs_dev.rdi), i, cpu);
 	}
 
+	free_cpumask_var(available_cpus);
+	free_cpumask_var(non_intr_cpus);
 	return 0;
 
 fail:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hfi1/chip.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hfi1/chip.c
@@ -1685,6 +1685,14 @@
 	return dd->verbs_dev.n_piodrain;
 }
 
+static u64 access_sw_ctx0_seq_drop(const struct cntr_entry *entry,
+				   void *context, int vl, int mode, u64 data)
+{
+	struct hfi1_devdata *dd = context;
+
+	return dd->ctx0_seq_drop;
+}
+
 static u64 access_sw_vtx_wait(const struct cntr_entry *entry,
 			      void *context, int vl, int mode, u64 data)
 {
@@ -4106,6 +4114,7 @@
 static struct cntr_entry dev_cntrs[DEV_CNTR_LAST] = {
 [C_RCV_OVF] = RXE32_DEV_CNTR_ELEM(RcvOverflow, RCV_BUF_OVFL_CNT, CNTR_SYNTH),
 [C_RX_LEN_ERR] = RXE32_DEV_CNTR_ELEM(RxLenErr, RCV_LENGTH_ERR_CNT, CNTR_SYNTH),
+[C_RX_SHORT_ERR] = RXE32_DEV_CNTR_ELEM(RxShrErr, RCV_SHORT_ERR_CNT, CNTR_SYNTH),
 [C_RX_ICRC_ERR] = RXE32_DEV_CNTR_ELEM(RxICrcErr, RCV_ICRC_ERR_CNT, CNTR_SYNTH),
 [C_RX_EBP] = RXE32_DEV_CNTR_ELEM(RxEbpCnt, RCV_EBP_CNT, CNTR_SYNTH),
 [C_RX_TID_FULL] = RXE32_DEV_CNTR_ELEM(RxTIDFullEr, RCV_TID_FULL_ERR_CNT,
@@ -4249,6 +4258,8 @@
 			    access_sw_cpu_intr),
 [C_SW_CPU_RCV_LIM] = CNTR_ELEM("RcvLimit", 0, 0, CNTR_NORMAL,
 			    access_sw_cpu_rcv_limit),
+[C_SW_CTX0_SEQ_DROP] = CNTR_ELEM("SeqDrop0", 0, 0, CNTR_NORMAL,
+			    access_sw_ctx0_seq_drop),
 [C_SW_VTX_WAIT] = CNTR_ELEM("vTxWait", 0, 0, CNTR_NORMAL,
 			    access_sw_vtx_wait),
 [C_SW_PIO_WAIT] = CNTR_ELEM("PioWait", 0, 0, CNTR_NORMAL,
@@ -12180,6 +12191,7 @@
 
 	if (dd->synth_stats_timer.function)
 		del_timer_sync(&dd->synth_stats_timer);
+	cancel_work_sync(&dd->update_cntr_work);
 	ppd = (struct hfi1_pportdata *)(dd + 1);
 	for (i = 0; i < dd->num_pports; i++, ppd++) {
 		kfree(ppd->cntrs);
@@ -13055,15 +13067,16 @@
 {
 	u64 reg;
 	u16 idx = src / BITS_PER_REGISTER;
+	unsigned long flags;
 
-	spin_lock(&dd->irq_src_lock);
+	spin_lock_irqsave(&dd->irq_src_lock, flags);
 	reg = read_csr(dd, CCE_INT_MASK + (8 * idx));
 	if (set)
 		reg |= bits;
 	else
 		reg &= ~bits;
 	write_csr(dd, CCE_INT_MASK + (8 * idx), reg);
-	spin_unlock(&dd->irq_src_lock);
+	spin_unlock_irqrestore(&dd->irq_src_lock, flags);
 }
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hfi1/chip.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hfi1/chip.h
@@ -859,6 +859,7 @@
 enum {
 	C_RCV_OVF = 0,
 	C_RX_LEN_ERR,
+	C_RX_SHORT_ERR,
 	C_RX_ICRC_ERR,
 	C_RX_EBP,
 	C_RX_TID_FULL,
@@ -926,6 +927,7 @@
 	C_DC_PG_STS_TX_MBE_CNT,
 	C_SW_CPU_INTR,
 	C_SW_CPU_RCV_LIM,
+	C_SW_CTX0_SEQ_DROP,
 	C_SW_VTX_WAIT,
 	C_SW_PIO_WAIT,
 	C_SW_PIO_DRAIN,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hfi1/chip_registers.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hfi1/chip_registers.h
@@ -381,6 +381,7 @@
 #define DC_LCB_STS_LINK_TRANSFER_ACTIVE (DC_LCB_CSRS + 0x000000000468)
 #define DC_LCB_STS_ROUND_TRIP_LTP_CNT (DC_LCB_CSRS + 0x0000000004B0)
 #define RCV_LENGTH_ERR_CNT 0
+#define RCV_SHORT_ERR_CNT 2
 #define RCV_ICRC_ERR_CNT 6
 #define RCV_EBP_CNT 9
 #define RCV_BUF_OVFL_CNT 10
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hfi1/debugfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hfi1/debugfs.c
@@ -985,15 +985,10 @@
 static int __i2c_debugfs_open(struct inode *in, struct file *fp, u32 target)
 {
 	struct hfi1_pportdata *ppd;
-	int ret;
 
 	ppd = private2ppd(fp);
 
-	ret = acquire_chip_resource(ppd->dd, i2c_target(target), 0);
-	if (ret) /* failed - release the module */
-		module_put(THIS_MODULE);
-
-	return ret;
+	return acquire_chip_resource(ppd->dd, i2c_target(target), 0);
 }
 
 static int i2c1_debugfs_open(struct inode *in, struct file *fp)
@@ -1013,7 +1008,6 @@
 	ppd = private2ppd(fp);
 
 	release_chip_resource(ppd->dd, i2c_target(target));
-	module_put(THIS_MODULE);
 
 	return 0;
 }
@@ -1031,18 +1025,10 @@
 static int __qsfp_debugfs_open(struct inode *in, struct file *fp, u32 target)
 {
 	struct hfi1_pportdata *ppd;
-	int ret;
-
-	if (!try_module_get(THIS_MODULE))
-		return -ENODEV;
 
 	ppd = private2ppd(fp);
 
-	ret = acquire_chip_resource(ppd->dd, i2c_target(target), 0);
-	if (ret) /* failed - release the module */
-		module_put(THIS_MODULE);
-
-	return ret;
+	return acquire_chip_resource(ppd->dd, i2c_target(target), 0);
 }
 
 static int qsfp1_debugfs_open(struct inode *in, struct file *fp)
@@ -1062,7 +1048,6 @@
 	ppd = private2ppd(fp);
 
 	release_chip_resource(ppd->dd, i2c_target(target));
-	module_put(THIS_MODULE);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hfi1/driver.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hfi1/driver.c
@@ -734,6 +734,7 @@
 {
 	int ret;
 
+	packet->rcd->dd->ctx0_seq_drop++;
 	/* Set up for the next packet */
 	packet->rhqoff += packet->rsize;
 	if (packet->rhqoff >= packet->maxcnt)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hfi1/efivar.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hfi1/efivar.c
@@ -152,7 +152,7 @@
 		      unsigned long *size, void **return_data)
 {
 	char prefix_name[64];
-	char name[64];
+	char name[128];
 	int result;
 	int i;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hfi1/file_ops.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hfi1/file_ops.c
@@ -200,23 +200,24 @@
 
 	fd = kzalloc(sizeof(*fd), GFP_KERNEL);
 
-	if (fd) {
-		fd->rec_cpu_num = -1; /* no cpu affinity by default */
-		fd->mm = current->mm;
-		mmgrab(fd->mm);
-		fd->dd = dd;
-		kobject_get(&fd->dd->kobj);
-		fp->private_data = fd;
-	} else {
-		fp->private_data = NULL;
-
-		if (atomic_dec_and_test(&dd->user_refcount))
-			complete(&dd->user_comp);
-
-		return -ENOMEM;
-	}
-
+	if (!fd || init_srcu_struct(&fd->pq_srcu))
+		goto nomem;
+	spin_lock_init(&fd->pq_rcu_lock);
+	spin_lock_init(&fd->tid_lock);
+	spin_lock_init(&fd->invalid_lock);
+	fd->rec_cpu_num = -1; /* no cpu affinity by default */
+	fd->mm = current->mm;
+	mmgrab(fd->mm);
+	fd->dd = dd;
+	kobject_get(&fd->dd->kobj);
+	fp->private_data = fd;
 	return 0;
+nomem:
+	kfree(fd);
+	fp->private_data = NULL;
+	if (atomic_dec_and_test(&dd->user_refcount))
+		complete(&dd->user_comp);
+	return -ENOMEM;
 }
 
 static long hfi1_file_ioctl(struct file *fp, unsigned int cmd,
@@ -301,21 +302,32 @@
 static ssize_t hfi1_write_iter(struct kiocb *kiocb, struct iov_iter *from)
 {
 	struct hfi1_filedata *fd = kiocb->ki_filp->private_data;
-	struct hfi1_user_sdma_pkt_q *pq = fd->pq;
+	struct hfi1_user_sdma_pkt_q *pq;
 	struct hfi1_user_sdma_comp_q *cq = fd->cq;
 	int done = 0, reqs = 0;
 	unsigned long dim = from->nr_segs;
+	int idx;
 
-	if (!cq || !pq)
+	if (!HFI1_CAP_IS_KSET(SDMA))
+		return -EINVAL;
+	idx = srcu_read_lock(&fd->pq_srcu);
+	pq = srcu_dereference(fd->pq, &fd->pq_srcu);
+	if (!cq || !pq) {
+		srcu_read_unlock(&fd->pq_srcu, idx);
 		return -EIO;
+	}
 
-	if (!iter_is_iovec(from) || !dim)
+	if (!iter_is_iovec(from) || !dim) {
+		srcu_read_unlock(&fd->pq_srcu, idx);
 		return -EINVAL;
+	}
 
 	trace_hfi1_sdma_request(fd->dd, fd->uctxt->ctxt, fd->subctxt, dim);
 
-	if (atomic_read(&pq->n_reqs) == pq->n_max_reqs)
+	if (atomic_read(&pq->n_reqs) == pq->n_max_reqs) {
+		srcu_read_unlock(&fd->pq_srcu, idx);
 		return -ENOSPC;
+	}
 
 	while (dim) {
 		int ret;
@@ -333,6 +345,7 @@
 		reqs++;
 	}
 
+	srcu_read_unlock(&fd->pq_srcu, idx);
 	return reqs;
 }
 
@@ -707,6 +720,7 @@
 	if (atomic_dec_and_test(&dd->user_refcount))
 		complete(&dd->user_comp);
 
+	cleanup_srcu_struct(&fdata->pq_srcu);
 	kfree(fdata);
 	return 0;
 }
@@ -1210,8 +1224,10 @@
 		goto done;
 
 	ret = init_user_ctxt(fd, uctxt);
-	if (ret)
+	if (ret) {
+		hfi1_free_ctxt_rcv_groups(uctxt);
 		goto done;
+	}
 
 	user_init(uctxt);
 
@@ -1347,12 +1363,15 @@
 		addr = arg + offsetof(struct hfi1_tid_info, tidcnt);
 		if (copy_to_user((void __user *)addr, &tinfo.tidcnt,
 				 sizeof(tinfo.tidcnt)))
-			return -EFAULT;
+			ret = -EFAULT;
 
 		addr = arg + offsetof(struct hfi1_tid_info, length);
-		if (copy_to_user((void __user *)addr, &tinfo.length,
+		if (!ret && copy_to_user((void __user *)addr, &tinfo.length,
 				 sizeof(tinfo.length)))
 			ret = -EFAULT;
+
+		if (ret)
+			hfi1_user_exp_rcv_invalid(fd, &tinfo);
 	}
 
 	return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hfi1/firmware.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hfi1/firmware.c
@@ -1786,6 +1786,7 @@
 
 	if (!dd->platform_config.data) {
 		dd_dev_err(dd, "%s: Missing config file\n", __func__);
+		ret = -EINVAL;
 		goto bail;
 	}
 	ptr = (u32 *)dd->platform_config.data;
@@ -1794,6 +1795,7 @@
 	ptr++;
 	if (magic_num != PLATFORM_CONFIG_MAGIC_NUM) {
 		dd_dev_err(dd, "%s: Bad config file\n", __func__);
+		ret = -EINVAL;
 		goto bail;
 	}
 
@@ -1817,6 +1819,7 @@
 	if (file_length > dd->platform_config.size) {
 		dd_dev_info(dd, "%s:File claims to be larger than read size\n",
 			    __func__);
+		ret = -EINVAL;
 		goto bail;
 	} else if (file_length < dd->platform_config.size) {
 		dd_dev_info(dd,
@@ -1837,6 +1840,7 @@
 			dd_dev_err(dd, "%s: Failed validation at offset %ld\n",
 				   __func__, (ptr - (u32 *)
 					      dd->platform_config.data));
+			ret = -EINVAL;
 			goto bail;
 		}
 
@@ -1883,6 +1887,7 @@
 					   __func__, table_type,
 					   (ptr - (u32 *)
 					    dd->platform_config.data));
+				ret = -EINVAL;
 				goto bail; /* We don't trust this file now */
 			}
 			pcfgcache->config_tables[table_type].table = ptr;
@@ -1907,6 +1912,7 @@
 					   __func__, table_type,
 					   (ptr -
 					    (u32 *)dd->platform_config.data));
+				ret = -EINVAL;
 				goto bail; /* We don't trust this file now */
 			}
 			pcfgcache->config_tables[table_type].table_metadata =
@@ -1924,6 +1930,7 @@
 			dd_dev_err(dd, "%s: Failed CRC check at offset %ld\n",
 				   __func__, (ptr -
 				   (u32 *)dd->platform_config.data));
+			ret = -EINVAL;
 			goto bail;
 		}
 		/* Jump the CRC DWORD */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hfi1/hfi.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hfi1/hfi.h
@@ -1153,6 +1153,8 @@
 
 	char *boardname; /* human readable board info */
 
+	u64 ctx0_seq_drop;
+
 	/* reset value */
 	u64 z_int_counter;
 	u64 z_rcv_limit;
@@ -1436,10 +1438,13 @@
 
 /* Private data for file operations */
 struct hfi1_filedata {
+	struct srcu_struct pq_srcu;
 	struct hfi1_devdata *dd;
 	struct hfi1_ctxtdata *uctxt;
 	struct hfi1_user_sdma_comp_q *cq;
-	struct hfi1_user_sdma_pkt_q *pq;
+	/* update side lock for SRCU */
+	spinlock_t pq_rcu_lock;
+	struct hfi1_user_sdma_pkt_q __rcu *pq;
 	u16 subctxt;
 	/* for cpu affinity; -1 if none */
 	int rec_cpu_num;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hfi1/init.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hfi1/init.c
@@ -543,7 +543,7 @@
 	u16 shift, mult;
 	u64 src;
 	u32 current_egress_rate; /* Mbits /sec */
-	u32 max_pkt_time;
+	u64 max_pkt_time;
 	/*
 	 * max_pkt_time is the maximum packet egress time in units
 	 * of the fabric clock period 1/(805 MHz).
@@ -664,12 +664,7 @@
 
 	ppd->pkeys[default_pkey_idx] = DEFAULT_P_KEY;
 	ppd->part_enforce |= HFI1_PART_ENFORCE_IN;
-
-	if (loopback) {
-		dd_dev_err(dd, "Faking data partition 0x8001 in idx %u\n",
-			   !default_pkey_idx);
-		ppd->pkeys[!default_pkey_idx] = 0x8001;
-	}
+	ppd->pkeys[0] = 0x8001;
 
 	INIT_WORK(&ppd->link_vc_work, handle_verify_cap);
 	INIT_WORK(&ppd->link_up_work, handle_link_up);
@@ -845,6 +840,29 @@
 }
 
 /**
+ * destroy_workqueues - destroy per port workqueues
+ * @dd: the hfi1_ib device
+ */
+static void destroy_workqueues(struct hfi1_devdata *dd)
+{
+	int pidx;
+	struct hfi1_pportdata *ppd;
+
+	for (pidx = 0; pidx < dd->num_pports; ++pidx) {
+		ppd = dd->pport + pidx;
+
+		if (ppd->hfi1_wq) {
+			destroy_workqueue(ppd->hfi1_wq);
+			ppd->hfi1_wq = NULL;
+		}
+		if (ppd->link_wq) {
+			destroy_workqueue(ppd->link_wq);
+			ppd->link_wq = NULL;
+		}
+	}
+}
+
+/**
  * enable_general_intr() - Enable the IRQs that will be handled by the
  * general interrupt handler.
  * @dd: valid devdata
@@ -1117,15 +1135,10 @@
 		 * We can't count on interrupts since we are stopping.
 		 */
 		hfi1_quiet_serdes(ppd);
-
-		if (ppd->hfi1_wq) {
-			destroy_workqueue(ppd->hfi1_wq);
-			ppd->hfi1_wq = NULL;
-		}
-		if (ppd->link_wq) {
-			destroy_workqueue(ppd->link_wq);
-			ppd->link_wq = NULL;
-		}
+		if (ppd->hfi1_wq)
+			flush_workqueue(ppd->hfi1_wq);
+		if (ppd->link_wq)
+			flush_workqueue(ppd->link_wq);
 	}
 	sdma_exit(dd);
 }
@@ -1162,7 +1175,7 @@
 	rcd->egrbufs.rcvtids = NULL;
 
 	for (e = 0; e < rcd->egrbufs.alloced; e++) {
-		if (rcd->egrbufs.buffers[e].dma)
+		if (rcd->egrbufs.buffers[e].addr)
 			dma_free_coherent(&dd->pcidev->dev,
 					  rcd->egrbufs.buffers[e].len,
 					  rcd->egrbufs.buffers[e].addr,
@@ -1814,6 +1827,7 @@
 	 * clear dma engines, etc.
 	 */
 	shutdown_device(dd);
+	destroy_workqueues(dd);
 
 	stop_timers(dd);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hfi1/iowait.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hfi1/iowait.c
@@ -81,7 +81,9 @@
 void iowait_cancel_work(struct iowait *w)
 {
 	cancel_work_sync(&iowait_get_ib_work(w)->iowork);
-	cancel_work_sync(&iowait_get_tid_work(w)->iowork);
+	/* Make sure that the iowork for TID RDMA is used */
+	if (iowait_get_tid_work(w)->iowork.func)
+		cancel_work_sync(&iowait_get_tid_work(w)->iowork);
 }
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hfi1/mmu_rb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hfi1/mmu_rb.c
@@ -173,7 +173,7 @@
 		goto unlock;
 	}
 	__mmu_int_rb_insert(mnode, &handler->root);
-	list_add(&mnode->list, &handler->lru_list);
+	list_add_tail(&mnode->list, &handler->lru_list);
 
 	ret = handler->ops->insert(handler->ops_arg, mnode);
 	if (ret) {
@@ -220,8 +220,10 @@
 	spin_lock_irqsave(&handler->lock, flags);
 	node = __mmu_rb_search(handler, addr, len);
 	if (node) {
-		if (node->addr == addr && node->len == len)
+		if (node->addr == addr && node->len == len) {
+			list_move_tail(&node->list, &handler->lru_list);
 			goto unlock;
+		}
 		__mmu_int_rb_remove(node, &handler->root);
 		list_del(&node->list); /* remove from LRU list */
 		ret = true;
@@ -242,8 +244,7 @@
 	INIT_LIST_HEAD(&del_list);
 
 	spin_lock_irqsave(&handler->lock, flags);
-	list_for_each_entry_safe_reverse(rbnode, ptr, &handler->lru_list,
-					 list) {
+	list_for_each_entry_safe(rbnode, ptr, &handler->lru_list, list) {
 		if (handler->ops->evict(handler->ops_arg, rbnode, evict_arg,
 					&stop)) {
 			__mmu_int_rb_remove(rbnode, &handler->root);
@@ -255,9 +256,7 @@
 	}
 	spin_unlock_irqrestore(&handler->lock, flags);
 
-	while (!list_empty(&del_list)) {
-		rbnode = list_first_entry(&del_list, struct mmu_rb_node, list);
-		list_del(&rbnode->list);
+	list_for_each_entry_safe(rbnode, ptr, &del_list, list) {
 		handler->ops->remove(handler->ops_arg, rbnode);
 	}
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hfi1/pcie.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hfi1/pcie.c
@@ -45,6 +45,7 @@
  *
  */
 
+#include <linux/bitfield.h>
 #include <linux/pci.h>
 #include <linux/io.h>
 #include <linux/delay.h>
@@ -261,12 +262,6 @@
 	return speed;
 }
 
-/* return the PCIe link speed from the given link status */
-static u32 extract_width(u16 linkstat)
-{
-	return (linkstat & PCI_EXP_LNKSTA_NLW) >> PCI_EXP_LNKSTA_NLW_SHIFT;
-}
-
 /* read the link status and set dd->{lbus_width,lbus_speed,lbus_info} */
 static void update_lbus_info(struct hfi1_devdata *dd)
 {
@@ -279,7 +274,7 @@
 		return;
 	}
 
-	dd->lbus_width = extract_width(linkstat);
+	dd->lbus_width = FIELD_GET(PCI_EXP_LNKSTA_NLW, linkstat);
 	dd->lbus_speed = extract_speed(linkstat);
 	snprintf(dd->lbus_info, sizeof(dd->lbus_info),
 		 "PCIe,%uMHz,x%u", dd->lbus_speed, dd->lbus_width);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hfi1/pio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hfi1/pio.c
@@ -920,6 +920,7 @@
 {
 	u64 reg;
 	struct pio_buf *pbuf;
+	LIST_HEAD(wake_list);
 
 	if (!sc)
 		return;
@@ -954,19 +955,20 @@
 	spin_unlock(&sc->release_lock);
 
 	write_seqlock(&sc->waitlock);
-	while (!list_empty(&sc->piowait)) {
+	list_splice_init(&sc->piowait, &wake_list);
+	write_sequnlock(&sc->waitlock);
+	while (!list_empty(&wake_list)) {
 		struct iowait *wait;
 		struct rvt_qp *qp;
 		struct hfi1_qp_priv *priv;
 
-		wait = list_first_entry(&sc->piowait, struct iowait, list);
+		wait = list_first_entry(&wake_list, struct iowait, list);
 		qp = iowait_to_qp(wait);
 		priv = qp->priv;
 		list_del_init(&priv->s_iowait.list);
 		priv->s_iowait.lock = NULL;
 		hfi1_qp_wakeup(qp, RVT_S_WAIT_PIO | HFI1_S_WAIT_PIO_DRAIN);
 	}
-	write_sequnlock(&sc->waitlock);
 
 	spin_unlock_irq(&sc->alloc_lock);
 }
@@ -2129,7 +2131,7 @@
 				   "Unable to allocate credit return DMA range for NUMA %d\n",
 				   i);
 			ret = -ENOMEM;
-			goto done;
+			goto free_cr_base;
 		}
 	}
 	set_dev_node(&dd->pcidev->dev, dd->node);
@@ -2137,6 +2139,10 @@
 	ret = 0;
 done:
 	return ret;
+
+free_cr_base:
+	free_credit_return(dd);
+	goto done;
 }
 
 void free_credit_return(struct hfi1_devdata *dd)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hfi1/qp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hfi1/qp.c
@@ -381,7 +381,10 @@
 	struct hfi1_ibport *ibp =
 		to_iport(qp->ibqp.device, qp->port_num);
 	struct hfi1_pportdata *ppd = ppd_from_ibp(ibp);
-	struct hfi1_devdata *dd = dd_from_ibdev(qp->ibqp.device);
+	struct hfi1_devdata *dd = ppd->dd;
+
+	if (dd->flags & HFI1_SHUTDOWN)
+		return true;
 
 	return iowait_schedule(&priv->s_iowait, ppd->hfi1_wq,
 			       priv->s_sde ?
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hfi1/sdma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hfi1/sdma.c
@@ -1329,11 +1329,13 @@
 		kvfree(sde->tx_ring);
 		sde->tx_ring = NULL;
 	}
-	spin_lock_irq(&dd->sde_map_lock);
-	sdma_map_free(rcu_access_pointer(dd->sdma_map));
-	RCU_INIT_POINTER(dd->sdma_map, NULL);
-	spin_unlock_irq(&dd->sde_map_lock);
-	synchronize_rcu();
+	if (rcu_access_pointer(dd->sdma_map)) {
+		spin_lock_irq(&dd->sde_map_lock);
+		sdma_map_free(rcu_access_pointer(dd->sdma_map));
+		RCU_INIT_POINTER(dd->sdma_map, NULL);
+		spin_unlock_irq(&dd->sde_map_lock);
+		synchronize_rcu();
+	}
 	kfree(dd->per_sdma);
 	dd->per_sdma = NULL;
 
@@ -3056,6 +3058,7 @@
 static int _extend_sdma_tx_descs(struct hfi1_devdata *dd, struct sdma_txreq *tx)
 {
 	int i;
+	struct sdma_desc *descp;
 
 	/* Handle last descriptor */
 	if (unlikely((tx->num_desc == (MAX_DESC - 1)))) {
@@ -3076,12 +3079,10 @@
 	if (unlikely(tx->num_desc == MAX_DESC))
 		goto enomem;
 
-	tx->descp = kmalloc_array(
-			MAX_DESC,
-			sizeof(struct sdma_desc),
-			GFP_ATOMIC);
-	if (!tx->descp)
+	descp = kmalloc_array(MAX_DESC, sizeof(struct sdma_desc), GFP_ATOMIC);
+	if (!descp)
 		goto enomem;
+	tx->descp = descp;
 
 	/* reserve last descriptor for coalescing */
 	tx->desc_limit = MAX_DESC - 1;
@@ -3202,7 +3203,6 @@
 {
 	int rval = 0;
 
-	tx->num_desc++;
 	if ((unlikely(tx->num_desc == tx->desc_limit))) {
 		rval = _extend_sdma_tx_descs(dd, tx);
 		if (rval) {
@@ -3216,6 +3216,7 @@
 		SDMA_MAP_NONE,
 		dd->sdma_pad_phys,
 		sizeof(u32) - (tx->packet_len & (sizeof(u32) - 1)));
+	tx->num_desc++;
 	_sdma_close_tx(dd, tx);
 	return rval;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hfi1/sdma.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hfi1/sdma.h
@@ -672,14 +672,13 @@
 static inline void _sdma_close_tx(struct hfi1_devdata *dd,
 				  struct sdma_txreq *tx)
 {
-	tx->descp[tx->num_desc].qw[0] |=
-		SDMA_DESC0_LAST_DESC_FLAG;
-	tx->descp[tx->num_desc].qw[1] |=
-		dd->default_desc1;
+	u16 last_desc = tx->num_desc - 1;
+
+	tx->descp[last_desc].qw[0] |= SDMA_DESC0_LAST_DESC_FLAG;
+	tx->descp[last_desc].qw[1] |= dd->default_desc1;
 	if (tx->flags & SDMA_TXREQ_F_URGENT)
-		tx->descp[tx->num_desc].qw[1] |=
-			(SDMA_DESC1_HEAD_TO_HOST_FLAG |
-			 SDMA_DESC1_INT_REQ_FLAG);
+		tx->descp[last_desc].qw[1] |= (SDMA_DESC1_HEAD_TO_HOST_FLAG |
+					       SDMA_DESC1_INT_REQ_FLAG);
 }
 
 static inline int _sdma_txadd_daddr(
@@ -696,6 +695,7 @@
 		type,
 		addr, len);
 	WARN_ON(len > tx->tlen);
+	tx->num_desc++;
 	tx->tlen -= len;
 	/* special cases for last */
 	if (!tx->tlen) {
@@ -707,7 +707,6 @@
 			_sdma_close_tx(dd, tx);
 		}
 	}
-	tx->num_desc++;
 	return rval;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hfi1/sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hfi1/sysfs.c
@@ -674,7 +674,11 @@
 		dd_dev_err(dd,
 			   "Skipping sc2vl sysfs info, (err %d) port %u\n",
 			   ret, port_num);
-		goto bail;
+		/*
+		 * Based on the documentation for kobject_init_and_add(), the
+		 * caller should call kobject_put even if this call fails.
+		 */
+		goto bail_sc2vl;
 	}
 	kobject_uevent(&ppd->sc2vl_kobj, KOBJ_ADD);
 
@@ -684,7 +688,7 @@
 		dd_dev_err(dd,
 			   "Skipping sl2sc sysfs info, (err %d) port %u\n",
 			   ret, port_num);
-		goto bail_sc2vl;
+		goto bail_sl2sc;
 	}
 	kobject_uevent(&ppd->sl2sc_kobj, KOBJ_ADD);
 
@@ -694,7 +698,7 @@
 		dd_dev_err(dd,
 			   "Skipping vl2mtu sysfs info, (err %d) port %u\n",
 			   ret, port_num);
-		goto bail_sl2sc;
+		goto bail_vl2mtu;
 	}
 	kobject_uevent(&ppd->vl2mtu_kobj, KOBJ_ADD);
 
@@ -704,7 +708,7 @@
 		dd_dev_err(dd,
 			   "Skipping Congestion Control sysfs info, (err %d) port %u\n",
 			   ret, port_num);
-		goto bail_vl2mtu;
+		goto bail_cc;
 	}
 
 	kobject_uevent(&ppd->pport_cc_kobj, KOBJ_ADD);
@@ -742,7 +746,6 @@
 	kobject_put(&ppd->sl2sc_kobj);
 bail_sc2vl:
 	kobject_put(&ppd->sc2vl_kobj);
-bail:
 	return ret;
 }
 
@@ -853,8 +856,13 @@
 
 	return 0;
 bail:
-	for (i = 0; i < dd->num_sdma; i++)
-		kobject_del(&dd->per_sdma[i].kobj);
+	/*
+	 * The function kobject_put() will call kobject_del() if the kobject
+	 * has been added successfully. The sysfs files created under the
+	 * kobject directory will also be removed during the process.
+	 */
+	for (; i >= 0; i--)
+		kobject_put(&dd->per_sdma[i].kobj);
 
 	return ret;
 }
@@ -867,6 +875,10 @@
 	struct hfi1_pportdata *ppd;
 	int i;
 
+	/* Unwind operations in hfi1_verbs_register_sysfs() */
+	for (i = 0; i < dd->num_sdma; i++)
+		kobject_put(&dd->per_sdma[i].kobj);
+
 	for (i = 0; i < dd->num_pports; i++) {
 		ppd = &dd->pport[i];
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hfi1/tid_rdma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hfi1/tid_rdma.c
@@ -3215,6 +3215,7 @@
 	case IB_WR_ATOMIC_CMP_AND_SWP:
 	case IB_WR_ATOMIC_FETCH_AND_ADD:
 	case IB_WR_RDMA_WRITE:
+	case IB_WR_RDMA_WRITE_WITH_IMM:
 		switch (prev->wr.opcode) {
 		case IB_WR_TID_RDMA_WRITE:
 			req = wqe_to_tid_req(prev);
@@ -4633,6 +4634,15 @@
 			 */
 			fpsn = full_flow_psn(flow, flow->flow_state.spsn);
 			req->r_ack_psn = psn;
+			/*
+			 * If resync_psn points to the last flow PSN for a
+			 * segment and the new segment (likely from a new
+			 * request) starts with a new generation number, we
+			 * need to adjust resync_psn accordingly.
+			 */
+			if (flow->flow_state.generation !=
+			    (resync_psn >> HFI1_KDETH_BTH_SEQ_SHIFT))
+				resync_psn = mask_psn(fpsn - 1);
 			flow->resync_npkts +=
 				delta_psn(mask_psn(resync_psn + 1), fpsn);
 			/*
@@ -5397,7 +5407,10 @@
 	struct hfi1_ibport *ibp =
 		to_iport(qp->ibqp.device, qp->port_num);
 	struct hfi1_pportdata *ppd = ppd_from_ibp(ibp);
-	struct hfi1_devdata *dd = dd_from_ibdev(qp->ibqp.device);
+	struct hfi1_devdata *dd = ppd->dd;
+
+	if ((dd->flags & HFI1_SHUTDOWN))
+		return true;
 
 	return iowait_tid_schedule(&priv->s_iowait, ppd->hfi1_wq,
 				   priv->s_sde ?
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hfi1/user_exp_rcv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hfi1/user_exp_rcv.c
@@ -90,9 +90,6 @@
 	struct hfi1_devdata *dd = uctxt->dd;
 	int ret = 0;
 
-	spin_lock_init(&fd->tid_lock);
-	spin_lock_init(&fd->invalid_lock);
-
 	fd->entry_to_rb = kcalloc(uctxt->expected_count,
 				  sizeof(struct rb_node *),
 				  GFP_KERNEL);
@@ -165,10 +162,12 @@
 	if (fd->handler) {
 		hfi1_mmu_rb_unregister(fd->handler);
 	} else {
+		mutex_lock(&uctxt->exp_mutex);
 		if (!EXP_TID_SET_EMPTY(uctxt->tid_full_list))
 			unlock_exp_tids(uctxt, &uctxt->tid_full_list, fd);
 		if (!EXP_TID_SET_EMPTY(uctxt->tid_used_list))
 			unlock_exp_tids(uctxt, &uctxt->tid_used_list, fd);
+		mutex_unlock(&uctxt->exp_mutex);
 	}
 
 	kfree(fd->invalid_tids);
@@ -216,16 +215,11 @@
 static int pin_rcv_pages(struct hfi1_filedata *fd, struct tid_user_buf *tidbuf)
 {
 	int pinned;
-	unsigned int npages;
+	unsigned int npages = tidbuf->npages;
 	unsigned long vaddr = tidbuf->vaddr;
 	struct page **pages = NULL;
 	struct hfi1_devdata *dd = fd->uctxt->dd;
 
-	/* Get the number of pages the user buffer spans */
-	npages = num_user_pages(vaddr, tidbuf->length);
-	if (!npages)
-		return -EINVAL;
-
 	if (npages > fd->uctxt->expected_count) {
 		dd_dev_err(dd, "Expected buffer too big\n");
 		return -EINVAL;
@@ -259,7 +253,6 @@
 		return pinned;
 	}
 	tidbuf->pages = pages;
-	tidbuf->npages = npages;
 	fd->tid_n_pinned += pinned;
 	return pinned;
 }
@@ -326,6 +319,8 @@
 
 	if (!PAGE_ALIGNED(tinfo->vaddr))
 		return -EINVAL;
+	if (tinfo->length == 0)
+		return -EINVAL;
 
 	tidbuf = kzalloc(sizeof(*tidbuf), GFP_KERNEL);
 	if (!tidbuf)
@@ -333,43 +328,42 @@
 
 	tidbuf->vaddr = tinfo->vaddr;
 	tidbuf->length = tinfo->length;
+	tidbuf->npages = num_user_pages(tidbuf->vaddr, tidbuf->length);
 	tidbuf->psets = kcalloc(uctxt->expected_count, sizeof(*tidbuf->psets),
 				GFP_KERNEL);
 	if (!tidbuf->psets) {
-		kfree(tidbuf);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto fail_release_mem;
 	}
 
 	pinned = pin_rcv_pages(fd, tidbuf);
 	if (pinned <= 0) {
-		kfree(tidbuf->psets);
-		kfree(tidbuf);
-		return pinned;
+		ret = (pinned < 0) ? pinned : -ENOSPC;
+		goto fail_unpin;
 	}
 
 	/* Find sets of physically contiguous pages */
 	tidbuf->n_psets = find_phys_blocks(tidbuf, pinned);
 
-	/*
-	 * We don't need to access this under a lock since tid_used is per
-	 * process and the same process cannot be in hfi1_user_exp_rcv_clear()
-	 * and hfi1_user_exp_rcv_setup() at the same time.
-	 */
+	/* Reserve the number of expected tids to be used. */
 	spin_lock(&fd->tid_lock);
 	if (fd->tid_used + tidbuf->n_psets > fd->tid_limit)
 		pageset_count = fd->tid_limit - fd->tid_used;
 	else
 		pageset_count = tidbuf->n_psets;
+	fd->tid_used += pageset_count;
 	spin_unlock(&fd->tid_lock);
 
-	if (!pageset_count)
-		goto bail;
+	if (!pageset_count) {
+		ret = -ENOSPC;
+		goto fail_unreserve;
+	}
 
 	ngroups = pageset_count / dd->rcv_entries.group_size;
 	tidlist = kcalloc(pageset_count, sizeof(*tidlist), GFP_KERNEL);
 	if (!tidlist) {
 		ret = -ENOMEM;
-		goto nomem;
+		goto fail_unreserve;
 	}
 
 	tididx = 0;
@@ -465,43 +459,60 @@
 	}
 unlock:
 	mutex_unlock(&uctxt->exp_mutex);
-nomem:
 	hfi1_cdbg(TID, "total mapped: tidpairs:%u pages:%u (%d)", tididx,
 		  mapped_pages, ret);
-	if (tididx) {
-		spin_lock(&fd->tid_lock);
-		fd->tid_used += tididx;
-		spin_unlock(&fd->tid_lock);
-		tinfo->tidcnt = tididx;
-		tinfo->length = mapped_pages * PAGE_SIZE;
-
-		if (copy_to_user(u64_to_user_ptr(tinfo->tidlist),
-				 tidlist, sizeof(tidlist[0]) * tididx)) {
-			/*
-			 * On failure to copy to the user level, we need to undo
-			 * everything done so far so we don't leak resources.
-			 */
-			tinfo->tidlist = (unsigned long)&tidlist;
-			hfi1_user_exp_rcv_clear(fd, tinfo);
-			tinfo->tidlist = 0;
-			ret = -EFAULT;
-			goto bail;
-		}
+
+	/* fail if nothing was programmed, set error if none provided */
+	if (tididx == 0) {
+		if (ret >= 0)
+			ret = -ENOSPC;
+		goto fail_unreserve;
 	}
 
-	/*
-	 * If not everything was mapped (due to insufficient RcvArray entries,
-	 * for example), unpin all unmapped pages so we can pin them nex time.
-	 */
-	if (mapped_pages != pinned)
-		unpin_rcv_pages(fd, tidbuf, NULL, mapped_pages,
-				(pinned - mapped_pages), false);
-bail:
+	/* adjust reserved tid_used to actual count */
+	spin_lock(&fd->tid_lock);
+	fd->tid_used -= pageset_count - tididx;
+	spin_unlock(&fd->tid_lock);
+
+	/* unpin all pages not covered by a TID */
+	unpin_rcv_pages(fd, tidbuf, NULL, mapped_pages, pinned - mapped_pages,
+			false);
+
+	tinfo->tidcnt = tididx;
+	tinfo->length = mapped_pages * PAGE_SIZE;
+
+	if (copy_to_user(u64_to_user_ptr(tinfo->tidlist),
+			 tidlist, sizeof(tidlist[0]) * tididx)) {
+		ret = -EFAULT;
+		goto fail_unprogram;
+	}
+
+	kfree(tidbuf->pages);
 	kfree(tidbuf->psets);
+	kfree(tidbuf);
 	kfree(tidlist);
+	return 0;
+
+fail_unprogram:
+	/* unprogram, unmap, and unpin all allocated TIDs */
+	tinfo->tidlist = (unsigned long)tidlist;
+	hfi1_user_exp_rcv_clear(fd, tinfo);
+	tinfo->tidlist = 0;
+	pinned = 0;		/* nothing left to unpin */
+	pageset_count = 0;	/* nothing left reserved */
+fail_unreserve:
+	spin_lock(&fd->tid_lock);
+	fd->tid_used -= pageset_count;
+	spin_unlock(&fd->tid_lock);
+fail_unpin:
+	if (pinned > 0)
+		unpin_rcv_pages(fd, tidbuf, NULL, 0, pinned, false);
+fail_release_mem:
 	kfree(tidbuf->pages);
+	kfree(tidbuf->psets);
 	kfree(tidbuf);
-	return ret > 0 ? 0 : ret;
+	kfree(tidlist);
+	return ret;
 }
 
 int hfi1_user_exp_rcv_clear(struct hfi1_filedata *fd,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hfi1/user_sdma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hfi1/user_sdma.c
@@ -141,6 +141,7 @@
 	 */
 	xchg(&pq->state, SDMA_PKT_Q_DEFERRED);
 	if (list_empty(&pq->busy.list)) {
+		pq->busy.lock = &sde->waitlock;
 		iowait_get_priority(&pq->busy);
 		iowait_queue(pkts_sent, &pq->busy, &sde->dmawait);
 	}
@@ -155,6 +156,7 @@
 {
 	struct hfi1_user_sdma_pkt_q *pq =
 		container_of(wait, struct hfi1_user_sdma_pkt_q, busy);
+	pq->busy.lock = NULL;
 	xchg(&pq->state, SDMA_PKT_Q_ACTIVE);
 	wake_up(&wait->wait_dma);
 };
@@ -179,7 +181,6 @@
 	pq = kzalloc(sizeof(*pq), GFP_KERNEL);
 	if (!pq)
 		return -ENOMEM;
-
 	pq->dd = dd;
 	pq->ctxt = uctxt->ctxt;
 	pq->subctxt = fd->subctxt;
@@ -236,7 +237,7 @@
 		goto pq_mmu_fail;
 	}
 
-	fd->pq = pq;
+	rcu_assign_pointer(fd->pq, pq);
 	fd->cq = cq;
 
 	return 0;
@@ -257,6 +258,21 @@
 	return ret;
 }
 
+static void flush_pq_iowait(struct hfi1_user_sdma_pkt_q *pq)
+{
+	unsigned long flags;
+	seqlock_t *lock = pq->busy.lock;
+
+	if (!lock)
+		return;
+	write_seqlock_irqsave(lock, flags);
+	if (!list_empty(&pq->busy.list)) {
+		list_del_init(&pq->busy.list);
+		pq->busy.lock = NULL;
+	}
+	write_sequnlock_irqrestore(lock, flags);
+}
+
 int hfi1_user_sdma_free_queues(struct hfi1_filedata *fd,
 			       struct hfi1_ctxtdata *uctxt)
 {
@@ -264,8 +280,14 @@
 
 	trace_hfi1_sdma_user_free_queues(uctxt->dd, uctxt->ctxt, fd->subctxt);
 
-	pq = fd->pq;
+	spin_lock(&fd->pq_rcu_lock);
+	pq = srcu_dereference_check(fd->pq, &fd->pq_srcu,
+				    lockdep_is_held(&fd->pq_rcu_lock));
 	if (pq) {
+		rcu_assign_pointer(fd->pq, NULL);
+		spin_unlock(&fd->pq_rcu_lock);
+		synchronize_srcu(&fd->pq_srcu);
+		/* at this point there can be no more new requests */
 		if (pq->handler)
 			hfi1_mmu_rb_unregister(pq->handler);
 		iowait_sdma_drain(&pq->busy);
@@ -276,8 +298,10 @@
 		kfree(pq->reqs);
 		kfree(pq->req_in_use);
 		kmem_cache_destroy(pq->txreq_cache);
+		flush_pq_iowait(pq);
 		kfree(pq);
-		fd->pq = NULL;
+	} else {
+		spin_unlock(&fd->pq_rcu_lock);
 	}
 	if (fd->cq) {
 		vfree(fd->cq->comps);
@@ -321,7 +345,8 @@
 {
 	int ret = 0, i;
 	struct hfi1_ctxtdata *uctxt = fd->uctxt;
-	struct hfi1_user_sdma_pkt_q *pq = fd->pq;
+	struct hfi1_user_sdma_pkt_q *pq =
+		srcu_dereference(fd->pq, &fd->pq_srcu);
 	struct hfi1_user_sdma_comp_q *cq = fd->cq;
 	struct hfi1_devdata *dd = pq->dd;
 	unsigned long idx = 0;
@@ -564,10 +589,6 @@
 
 	set_comp_state(pq, cq, info.comp_idx, QUEUED, 0);
 	pq->state = SDMA_PKT_Q_ACTIVE;
-	/* Send the first N packets in the request to buy us some time */
-	ret = user_sdma_send_pkts(req, pcount);
-	if (unlikely(ret < 0 && ret != -EBUSY))
-		goto free_req;
 
 	/*
 	 * This is a somewhat blocking send implementation.
@@ -580,11 +601,12 @@
 		if (ret < 0) {
 			if (ret != -EBUSY)
 				goto free_req;
-			wait_event_interruptible_timeout(
+			if (wait_event_interruptible_timeout(
 				pq->busy.wait_dma,
-				(pq->state == SDMA_PKT_Q_ACTIVE),
+				pq->state == SDMA_PKT_Q_ACTIVE,
 				msecs_to_jiffies(
-					SDMA_IOWAIT_TIMEOUT));
+					SDMA_IOWAIT_TIMEOUT)) <= 0)
+				flush_pq_iowait(pq);
 		}
 	}
 	*count += idx;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hfi1/verbs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hfi1/verbs.c
@@ -515,10 +515,11 @@
 				       opa_get_lid(packet->dlid, 9B));
 		if (!mcast)
 			goto drop;
+		rcu_read_lock();
 		list_for_each_entry_rcu(p, &mcast->qp_list, list) {
 			packet->qp = p->qp;
 			if (hfi1_do_pkey_check(packet))
-				goto drop;
+				goto unlock_drop;
 			spin_lock_irqsave(&packet->qp->r_lock, flags);
 			packet_handler = qp_ok(packet);
 			if (likely(packet_handler))
@@ -527,6 +528,7 @@
 				ibp->rvp.n_pkt_drops++;
 			spin_unlock_irqrestore(&packet->qp->r_lock, flags);
 		}
+		rcu_read_unlock();
 		/*
 		 * Notify rvt_multicast_detach() if it is waiting for us
 		 * to finish.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hns/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hns/Kconfig
@@ -1,23 +1,34 @@
 # SPDX-License-Identifier: GPL-2.0-only
 config INFINIBAND_HNS
-	bool "HNS RoCE Driver"
+	tristate "HNS RoCE Driver"
 	depends on NET_VENDOR_HISILICON
 	depends on ARM64 || (COMPILE_TEST && 64BIT)
+	depends on (HNS_DSAF && HNS_ENET) || HNS3
 	---help---
 	  This is a RoCE/RDMA driver for the Hisilicon RoCE engine. The engine
 	  is used in Hisilicon Hip06 and more further ICT SoC based on
 	  platform device.
 
+	  To compile HIP06 or HIP08 driver as module, choose M here.
+
 config INFINIBAND_HNS_HIP06
-	tristate "Hisilicon Hip06 Family RoCE support"
+	bool "Hisilicon Hip06 Family RoCE support"
 	depends on INFINIBAND_HNS && HNS && HNS_DSAF && HNS_ENET
+	depends on INFINIBAND_HNS=m || (HNS_DSAF=y && HNS_ENET=y)
 	---help---
 	  RoCE driver support for Hisilicon RoCE engine in Hisilicon Hip06 and
 	  Hip07 SoC. These RoCE engines are platform devices.
 
+	  To compile this driver, choose Y here: if INFINIBAND_HNS is m, this
+	  module will be called hns-roce-hw-v1
+
 config INFINIBAND_HNS_HIP08
-	tristate "Hisilicon Hip08 Family RoCE support"
+	bool "Hisilicon Hip08 Family RoCE support"
 	depends on INFINIBAND_HNS && PCI && HNS3
+	depends on INFINIBAND_HNS=m || HNS3=y
 	---help---
 	  RoCE driver support for Hisilicon RoCE engine in Hisilicon Hip08 SoC.
 	  The RoCE engine is a PCI device.
+
+	  To compile this driver, choose Y here: if INFINIBAND_HNS is m, this
+	  module will be called hns-roce-hw-v2.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hns/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hns/Makefile
@@ -9,8 +9,12 @@
 	hns_roce_ah.o hns_roce_hem.o hns_roce_mr.o hns_roce_qp.o \
 	hns_roce_cq.o hns_roce_alloc.o hns_roce_db.o hns_roce_srq.o hns_roce_restrack.o
 
+ifdef CONFIG_INFINIBAND_HNS_HIP06
 hns-roce-hw-v1-objs := hns_roce_hw_v1.o $(hns-roce-objs)
-obj-$(CONFIG_INFINIBAND_HNS_HIP06) += hns-roce-hw-v1.o
+obj-$(CONFIG_INFINIBAND_HNS) += hns-roce-hw-v1.o
+endif
 
+ifdef CONFIG_INFINIBAND_HNS_HIP08
 hns-roce-hw-v2-objs := hns_roce_hw_v2.o hns_roce_hw_v2_dfx.o $(hns-roce-objs)
-obj-$(CONFIG_INFINIBAND_HNS_HIP08) += hns-roce-hw-v2.o
+obj-$(CONFIG_INFINIBAND_HNS) += hns-roce-hw-v2.o
+endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hns/hns_roce_ah.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hns/hns_roce_ah.c
@@ -46,32 +46,32 @@
 	const struct ib_gid_attr *gid_attr;
 	struct device *dev = hr_dev->dev;
 	struct hns_roce_ah *ah = to_hr_ah(ibah);
-	u16 vlan_tag = 0xffff;
 	const struct ib_global_route *grh = rdma_ah_read_grh(ah_attr);
+	u16 vlan_id = 0xffff;
 	bool vlan_en = false;
 	int ret;
 
 	gid_attr = ah_attr->grh.sgid_attr;
-	ret = rdma_read_gid_l2_fields(gid_attr, &vlan_tag, NULL);
+	ret = rdma_read_gid_l2_fields(gid_attr, &vlan_id, NULL);
 	if (ret)
 		return ret;
 
 	/* Get mac address */
 	memcpy(ah->av.mac, ah_attr->roce.dmac, ETH_ALEN);
 
-	if (vlan_tag < VLAN_CFI_MASK) {
+	if (vlan_id < VLAN_N_VID) {
 		vlan_en = true;
-		vlan_tag |= (rdma_ah_get_sl(ah_attr) &
+		vlan_id |= (rdma_ah_get_sl(ah_attr) &
 			     HNS_ROCE_VLAN_SL_BIT_MASK) <<
 			     HNS_ROCE_VLAN_SL_SHIFT;
 	}
 
 	ah->av.port = rdma_ah_get_port_num(ah_attr);
 	ah->av.gid_index = grh->sgid_index;
-	ah->av.vlan = vlan_tag;
+	ah->av.vlan_id = vlan_id;
 	ah->av.vlan_en = vlan_en;
-	dev_dbg(dev, "gid_index = 0x%x,vlan = 0x%x\n", ah->av.gid_index,
-		ah->av.vlan);
+	dev_dbg(dev, "gid_index = 0x%x,vlan_id = 0x%x\n", ah->av.gid_index,
+		ah->av.vlan_id);
 
 	if (rdma_ah_get_static_rate(ah_attr))
 		ah->av.stat_rate = IB_RATE_10_GBPS;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hns/hns_roce_alloc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hns/hns_roce_alloc.c
@@ -55,7 +55,7 @@
 			bitmap->last = 0;
 		*obj |= bitmap->top;
 	} else {
-		ret = -1;
+		ret = -EINVAL;
 	}
 
 	spin_unlock(&bitmap->lock);
@@ -100,7 +100,7 @@
 		}
 		*obj |= bitmap->top;
 	} else {
-		ret = -1;
+		ret = -EINVAL;
 	}
 
 	spin_unlock(&bitmap->lock);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hns/hns_roce_cmd.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hns/hns_roce_cmd.h
@@ -115,12 +115,12 @@
 
 enum {
 	/* TPT commands */
-	HNS_ROCE_CMD_SW2HW_MPT		= 0xd,
-	HNS_ROCE_CMD_HW2SW_MPT		= 0xf,
+	HNS_ROCE_CMD_CREATE_MPT		= 0xd,
+	HNS_ROCE_CMD_DESTROY_MPT	= 0xf,
 
 	/* CQ commands */
-	HNS_ROCE_CMD_SW2HW_CQ		= 0x16,
-	HNS_ROCE_CMD_HW2SW_CQ		= 0x17,
+	HNS_ROCE_CMD_CREATE_CQC		= 0x16,
+	HNS_ROCE_CMD_DESTROY_CQC	= 0x17,
 
 	/* QP/EE commands */
 	HNS_ROCE_CMD_RST2INIT_QP	= 0x19,
@@ -129,14 +129,14 @@
 	HNS_ROCE_CMD_RTS2RTS_QP		= 0x1c,
 	HNS_ROCE_CMD_2ERR_QP		= 0x1e,
 	HNS_ROCE_CMD_RTS2SQD_QP		= 0x1f,
-	HNS_ROCE_CMD_SQD2SQD_QP		= 0x38,
 	HNS_ROCE_CMD_SQD2RTS_QP		= 0x20,
 	HNS_ROCE_CMD_2RST_QP		= 0x21,
 	HNS_ROCE_CMD_QUERY_QP		= 0x22,
-	HNS_ROCE_CMD_SW2HW_SRQ		= 0x70,
+	HNS_ROCE_CMD_SQD2SQD_QP		= 0x38,
+	HNS_ROCE_CMD_CREATE_SRQ		= 0x70,
 	HNS_ROCE_CMD_MODIFY_SRQC	= 0x72,
 	HNS_ROCE_CMD_QUERY_SRQC		= 0x73,
-	HNS_ROCE_CMD_HW2SW_SRQ		= 0x74,
+	HNS_ROCE_CMD_DESTROY_SRQ	= 0x74,
 };
 
 int hns_roce_cmd_mbox(struct hns_roce_dev *hr_dev, u64 in_param, u64 out_param,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hns/hns_roce_cq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hns/hns_roce_cq.c
@@ -39,51 +39,8 @@
 #include <rdma/hns-abi.h>
 #include "hns_roce_common.h"
 
-static void hns_roce_ib_cq_comp(struct hns_roce_cq *hr_cq)
-{
-	struct ib_cq *ibcq = &hr_cq->ib_cq;
-
-	ibcq->comp_handler(ibcq, ibcq->cq_context);
-}
-
-static void hns_roce_ib_cq_event(struct hns_roce_cq *hr_cq,
-				 enum hns_roce_event event_type)
-{
-	struct hns_roce_dev *hr_dev;
-	struct ib_event event;
-	struct ib_cq *ibcq;
-
-	ibcq = &hr_cq->ib_cq;
-	hr_dev = to_hr_dev(ibcq->device);
-
-	if (event_type != HNS_ROCE_EVENT_TYPE_CQ_ID_INVALID &&
-	    event_type != HNS_ROCE_EVENT_TYPE_CQ_ACCESS_ERROR &&
-	    event_type != HNS_ROCE_EVENT_TYPE_CQ_OVERFLOW) {
-		dev_err(hr_dev->dev,
-			"hns_roce_ib: Unexpected event type 0x%x on CQ %06lx\n",
-			event_type, hr_cq->cqn);
-		return;
-	}
-
-	if (ibcq->event_handler) {
-		event.device = ibcq->device;
-		event.event = IB_EVENT_CQ_ERR;
-		event.element.cq = ibcq;
-		ibcq->event_handler(&event, ibcq->cq_context);
-	}
-}
-
-static int hns_roce_sw2hw_cq(struct hns_roce_dev *dev,
-			     struct hns_roce_cmd_mailbox *mailbox,
-			     unsigned long cq_num)
-{
-	return hns_roce_cmd_mbox(dev, mailbox->dma, 0, cq_num, 0,
-			    HNS_ROCE_CMD_SW2HW_CQ, HNS_ROCE_CMD_TIMEOUT_MSECS);
-}
-
-static int hns_roce_cq_alloc(struct hns_roce_dev *hr_dev, int nent,
-			     struct hns_roce_mtt *hr_mtt,
-			     struct hns_roce_cq *hr_cq, int vector)
+static int hns_roce_alloc_cqc(struct hns_roce_dev *hr_dev,
+			      struct hns_roce_cq *hr_cq)
 {
 	struct hns_roce_cmd_mailbox *mailbox;
 	struct hns_roce_hem_table *mtt_table;
@@ -101,35 +58,32 @@
 	else
 		mtt_table = &hr_dev->mr_table.mtt_table;
 
-	mtts = hns_roce_table_find(hr_dev, mtt_table,
-				   hr_mtt->first_seg, &dma_handle);
-	if (!mtts) {
-		dev_err(dev, "CQ alloc.Failed to find cq buf addr.\n");
-		return -EINVAL;
-	}
+	mtts = hns_roce_table_find(hr_dev, mtt_table, hr_cq->mtt.first_seg,
+				   &dma_handle);
 
-	if (vector >= hr_dev->caps.num_comp_vectors) {
-		dev_err(dev, "CQ alloc.Invalid vector.\n");
+	if (!mtts) {
+		dev_err(dev, "Failed to find mtt for CQ buf.\n");
 		return -EINVAL;
 	}
-	hr_cq->vector = vector;
 
 	ret = hns_roce_bitmap_alloc(&cq_table->bitmap, &hr_cq->cqn);
-	if (ret == -1) {
-		dev_err(dev, "CQ alloc.Failed to alloc index.\n");
-		return -ENOMEM;
+	if (ret) {
+		dev_err(dev, "Num of CQ out of range.\n");
+		return ret;
 	}
 
 	/* Get CQC memory HEM(Hardware Entry Memory) table */
 	ret = hns_roce_table_get(hr_dev, &cq_table->table, hr_cq->cqn);
 	if (ret) {
-		dev_err(dev, "CQ alloc.Failed to get context mem.\n");
+		dev_err(dev,
+			"Get context mem failed(%d) when CQ(0x%lx) alloc.\n",
+			ret, hr_cq->cqn);
 		goto err_out;
 	}
 
 	ret = xa_err(xa_store(&cq_table->array, hr_cq->cqn, hr_cq, GFP_KERNEL));
 	if (ret) {
-		dev_err(dev, "CQ alloc failed xa_store.\n");
+		dev_err(dev, "Failed to xa_store CQ.\n");
 		goto err_put;
 	}
 
@@ -140,14 +94,16 @@
 		goto err_xa;
 	}
 
-	hr_dev->hw->write_cqc(hr_dev, hr_cq, mailbox->buf, mtts, dma_handle,
-			      nent, vector);
+	hr_dev->hw->write_cqc(hr_dev, hr_cq, mailbox->buf, mtts, dma_handle);
 
 	/* Send mailbox to hw */
-	ret = hns_roce_sw2hw_cq(hr_dev, mailbox, hr_cq->cqn);
+	ret = hns_roce_cmd_mbox(hr_dev, mailbox->dma, 0, hr_cq->cqn, 0,
+			HNS_ROCE_CMD_CREATE_CQC, HNS_ROCE_CMD_TIMEOUT_MSECS);
 	hns_roce_free_cmd_mailbox(hr_dev, mailbox);
 	if (ret) {
-		dev_err(dev, "CQ alloc.Failed to cmd mailbox.\n");
+		dev_err(dev,
+			"Send cmd mailbox failed(%d) when CQ(0x%lx) alloc.\n",
+			ret, hr_cq->cqn);
 		goto err_xa;
 	}
 
@@ -170,24 +126,17 @@
 	return ret;
 }
 
-static int hns_roce_hw2sw_cq(struct hns_roce_dev *dev,
-			     struct hns_roce_cmd_mailbox *mailbox,
-			     unsigned long cq_num)
-{
-	return hns_roce_cmd_mbox(dev, 0, mailbox ? mailbox->dma : 0, cq_num,
-				 mailbox ? 0 : 1, HNS_ROCE_CMD_HW2SW_CQ,
-				 HNS_ROCE_CMD_TIMEOUT_MSECS);
-}
-
-void hns_roce_free_cq(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq)
+void hns_roce_free_cqc(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq)
 {
 	struct hns_roce_cq_table *cq_table = &hr_dev->cq_table;
 	struct device *dev = hr_dev->dev;
 	int ret;
 
-	ret = hns_roce_hw2sw_cq(hr_dev, NULL, hr_cq->cqn);
+	ret = hns_roce_cmd_mbox(hr_dev, 0, 0, hr_cq->cqn, 1,
+				HNS_ROCE_CMD_DESTROY_CQC,
+				HNS_ROCE_CMD_TIMEOUT_MSECS);
 	if (ret)
-		dev_err(dev, "HW2SW_CQ failed (%d) for CQN %06lx\n", ret,
+		dev_err(dev, "DESTROY_CQ failed (%d) for CQN %06lx\n", ret,
 			hr_cq->cqn);
 
 	xa_erase(&cq_table->array, hr_cq->cqn);
@@ -204,103 +153,91 @@
 	hns_roce_bitmap_free(&cq_table->bitmap, hr_cq->cqn, BITMAP_NO_RR);
 }
 
-static int hns_roce_ib_get_cq_umem(struct hns_roce_dev *hr_dev,
-				   struct ib_udata *udata,
-				   struct hns_roce_cq_buf *buf,
-				   struct ib_umem **umem, u64 buf_addr, int cqe)
-{
-	int ret;
-	u32 page_shift;
+static int get_cq_umem(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq,
+		       struct hns_roce_ib_create_cq ucmd,
+		       struct ib_udata *udata)
+{
+	struct hns_roce_buf *buf = &hr_cq->buf;
+	struct hns_roce_mtt *mtt = &hr_cq->mtt;
+	struct ib_umem **umem = &hr_cq->umem;
 	u32 npages;
+	int ret;
 
-	*umem = ib_umem_get(udata, buf_addr, cqe * hr_dev->caps.cq_entry_sz,
-			    IB_ACCESS_LOCAL_WRITE, 1);
+	*umem = ib_umem_get(&hr_dev->ib_dev, ucmd.buf_addr, buf->size,
+			    IB_ACCESS_LOCAL_WRITE);
 	if (IS_ERR(*umem))
 		return PTR_ERR(*umem);
 
 	if (hns_roce_check_whether_mhop(hr_dev, HEM_TYPE_CQE))
-		buf->hr_mtt.mtt_type = MTT_TYPE_CQE;
+		mtt->mtt_type = MTT_TYPE_CQE;
 	else
-		buf->hr_mtt.mtt_type = MTT_TYPE_WQE;
+		mtt->mtt_type = MTT_TYPE_WQE;
 
-	if (hr_dev->caps.cqe_buf_pg_sz) {
-		npages = (ib_umem_page_count(*umem) +
-			(1 << hr_dev->caps.cqe_buf_pg_sz) - 1) /
-			(1 << hr_dev->caps.cqe_buf_pg_sz);
-		page_shift = PAGE_SHIFT + hr_dev->caps.cqe_buf_pg_sz;
-		ret = hns_roce_mtt_init(hr_dev, npages, page_shift,
-					&buf->hr_mtt);
-	} else {
-		ret = hns_roce_mtt_init(hr_dev, ib_umem_page_count(*umem),
-					PAGE_SHIFT, &buf->hr_mtt);
-	}
+	npages = DIV_ROUND_UP(ib_umem_page_count(*umem),
+			      1 << hr_dev->caps.cqe_buf_pg_sz);
+	ret = hns_roce_mtt_init(hr_dev, npages, buf->page_shift, mtt);
 	if (ret)
 		goto err_buf;
 
-	ret = hns_roce_ib_umem_write_mtt(hr_dev, &buf->hr_mtt, *umem);
+	ret = hns_roce_ib_umem_write_mtt(hr_dev, mtt, *umem);
 	if (ret)
 		goto err_mtt;
 
 	return 0;
 
 err_mtt:
-	hns_roce_mtt_cleanup(hr_dev, &buf->hr_mtt);
+	hns_roce_mtt_cleanup(hr_dev, mtt);
 
 err_buf:
 	ib_umem_release(*umem);
 	return ret;
 }
 
-static int hns_roce_ib_alloc_cq_buf(struct hns_roce_dev *hr_dev,
-				    struct hns_roce_cq_buf *buf, u32 nent)
+static int alloc_cq_buf(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq)
 {
+	struct hns_roce_buf *buf = &hr_cq->buf;
+	struct hns_roce_mtt *mtt = &hr_cq->mtt;
 	int ret;
-	u32 page_shift = PAGE_SHIFT + hr_dev->caps.cqe_buf_pg_sz;
 
-	ret = hns_roce_buf_alloc(hr_dev, nent * hr_dev->caps.cq_entry_sz,
-				 (1 << page_shift) * 2, &buf->hr_buf,
-				 page_shift);
+	ret = hns_roce_buf_alloc(hr_dev, buf->size, (1 << buf->page_shift) * 2,
+				 buf, buf->page_shift);
 	if (ret)
 		goto out;
 
 	if (hns_roce_check_whether_mhop(hr_dev, HEM_TYPE_CQE))
-		buf->hr_mtt.mtt_type = MTT_TYPE_CQE;
+		mtt->mtt_type = MTT_TYPE_CQE;
 	else
-		buf->hr_mtt.mtt_type = MTT_TYPE_WQE;
+		mtt->mtt_type = MTT_TYPE_WQE;
 
-	ret = hns_roce_mtt_init(hr_dev, buf->hr_buf.npages,
-				buf->hr_buf.page_shift, &buf->hr_mtt);
+	ret = hns_roce_mtt_init(hr_dev, buf->npages, buf->page_shift, mtt);
 	if (ret)
 		goto err_buf;
 
-	ret = hns_roce_buf_write_mtt(hr_dev, &buf->hr_mtt, &buf->hr_buf);
+	ret = hns_roce_buf_write_mtt(hr_dev, mtt, buf);
 	if (ret)
 		goto err_mtt;
 
 	return 0;
 
 err_mtt:
-	hns_roce_mtt_cleanup(hr_dev, &buf->hr_mtt);
+	hns_roce_mtt_cleanup(hr_dev, mtt);
 
 err_buf:
-	hns_roce_buf_free(hr_dev, nent * hr_dev->caps.cq_entry_sz,
-			  &buf->hr_buf);
+	hns_roce_buf_free(hr_dev, buf->size, buf);
+
 out:
 	return ret;
 }
 
-static void hns_roce_ib_free_cq_buf(struct hns_roce_dev *hr_dev,
-				    struct hns_roce_cq_buf *buf, int cqe)
+static void free_cq_buf(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq)
 {
-	hns_roce_buf_free(hr_dev, (cqe + 1) * hr_dev->caps.cq_entry_sz,
-			  &buf->hr_buf);
+	hns_roce_buf_free(hr_dev, hr_cq->buf.size, &hr_cq->buf);
 }
 
 static int create_user_cq(struct hns_roce_dev *hr_dev,
 			  struct hns_roce_cq *hr_cq,
 			  struct ib_udata *udata,
-			  struct hns_roce_ib_create_cq_resp *resp,
-			  int cq_entries)
+			  struct hns_roce_ib_create_cq_resp *resp)
 {
 	struct hns_roce_ib_create_cq ucmd;
 	struct device *dev = hr_dev->dev;
@@ -314,9 +251,7 @@
 	}
 
 	/* Get user space address, write it into mtt table */
-	ret = hns_roce_ib_get_cq_umem(hr_dev, udata, &hr_cq->hr_buf,
-				      &hr_cq->umem, ucmd.buf_addr,
-				      cq_entries);
+	ret = get_cq_umem(hr_dev, hr_cq, ucmd, udata);
 	if (ret) {
 		dev_err(dev, "Failed to get_cq_umem.\n");
 		return ret;
@@ -337,17 +272,16 @@
 	return 0;
 
 err_mtt:
-	hns_roce_mtt_cleanup(hr_dev, &hr_cq->hr_buf.hr_mtt);
+	hns_roce_mtt_cleanup(hr_dev, &hr_cq->mtt);
 	ib_umem_release(hr_cq->umem);
 
 	return ret;
 }
 
 static int create_kernel_cq(struct hns_roce_dev *hr_dev,
-			    struct hns_roce_cq *hr_cq, int cq_entries)
+			    struct hns_roce_cq *hr_cq)
 {
 	struct device *dev = hr_dev->dev;
-	struct hns_roce_uar *uar;
 	int ret;
 
 	if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_RECORD_DB) {
@@ -361,15 +295,14 @@
 	}
 
 	/* Init mtt table and write buff address to mtt table */
-	ret = hns_roce_ib_alloc_cq_buf(hr_dev, &hr_cq->hr_buf, cq_entries);
+	ret = alloc_cq_buf(hr_dev, hr_cq);
 	if (ret) {
 		dev_err(dev, "Failed to alloc_cq_buf.\n");
 		goto err_db;
 	}
 
-	uar = &hr_dev->priv_uar;
 	hr_cq->cq_db_l = hr_dev->reg_base + hr_dev->odb_offset +
-			 DB_REG_OFFSET * uar->index;
+			 DB_REG_OFFSET * hr_dev->priv_uar.index;
 
 	return 0;
 
@@ -392,64 +325,71 @@
 	    (udata->outlen >= sizeof(*resp)))
 		hns_roce_db_unmap_user(context, &hr_cq->db);
 
-	hns_roce_mtt_cleanup(hr_dev, &hr_cq->hr_buf.hr_mtt);
+	hns_roce_mtt_cleanup(hr_dev, &hr_cq->mtt);
 	ib_umem_release(hr_cq->umem);
 }
 
 static void destroy_kernel_cq(struct hns_roce_dev *hr_dev,
 			      struct hns_roce_cq *hr_cq)
 {
-	hns_roce_mtt_cleanup(hr_dev, &hr_cq->hr_buf.hr_mtt);
-	hns_roce_ib_free_cq_buf(hr_dev, &hr_cq->hr_buf, hr_cq->ib_cq.cqe);
+	hns_roce_mtt_cleanup(hr_dev, &hr_cq->mtt);
+	free_cq_buf(hr_dev, hr_cq);
 
 	if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_RECORD_DB)
 		hns_roce_free_db(hr_dev, &hr_cq->db);
 }
 
-int hns_roce_ib_create_cq(struct ib_cq *ib_cq,
-			  const struct ib_cq_init_attr *attr,
-			  struct ib_udata *udata)
+int hns_roce_create_cq(struct ib_cq *ib_cq, const struct ib_cq_init_attr *attr,
+		       struct ib_udata *udata)
 {
 	struct hns_roce_dev *hr_dev = to_hr_dev(ib_cq->device);
-	struct device *dev = hr_dev->dev;
 	struct hns_roce_ib_create_cq_resp resp = {};
 	struct hns_roce_cq *hr_cq = to_hr_cq(ib_cq);
+	struct device *dev = hr_dev->dev;
 	int vector = attr->comp_vector;
-	int cq_entries = attr->cqe;
+	u32 cq_entries = attr->cqe;
 	int ret;
 
 	if (cq_entries < 1 || cq_entries > hr_dev->caps.max_cqes) {
-		dev_err(dev, "Creat CQ failed. entries=%d, max=%d\n",
+		dev_err(dev, "Create CQ failed. entries=%d, max=%d\n",
 			cq_entries, hr_dev->caps.max_cqes);
 		return -EINVAL;
 	}
 
-	if (hr_dev->caps.min_cqes)
-		cq_entries = max(cq_entries, hr_dev->caps.min_cqes);
+	if (vector >= hr_dev->caps.num_comp_vectors) {
+		dev_err(dev, "Create CQ failed, vector=%d, max=%d\n",
+			vector, hr_dev->caps.num_comp_vectors);
+		return -EINVAL;
+	}
 
-	cq_entries = roundup_pow_of_two((unsigned int)cq_entries);
-	hr_cq->ib_cq.cqe = cq_entries - 1;
+	cq_entries = max(cq_entries, hr_dev->caps.min_cqes);
+	cq_entries = roundup_pow_of_two(cq_entries);
+	hr_cq->ib_cq.cqe = cq_entries - 1; /* used as cqe index */
+	hr_cq->cq_depth = cq_entries;
+	hr_cq->vector = vector;
+	hr_cq->buf.size = hr_cq->cq_depth * hr_dev->caps.cq_entry_sz;
+	hr_cq->buf.page_shift = PAGE_SHIFT + hr_dev->caps.cqe_buf_pg_sz;
 	spin_lock_init(&hr_cq->lock);
+	INIT_LIST_HEAD(&hr_cq->sq_list);
+	INIT_LIST_HEAD(&hr_cq->rq_list);
 
 	if (udata) {
-		ret = create_user_cq(hr_dev, hr_cq, udata, &resp, cq_entries);
+		ret = create_user_cq(hr_dev, hr_cq, udata, &resp);
 		if (ret) {
 			dev_err(dev, "Create cq failed in user mode!\n");
 			goto err_cq;
 		}
 	} else {
-		ret = create_kernel_cq(hr_dev, hr_cq, cq_entries);
+		ret = create_kernel_cq(hr_dev, hr_cq);
 		if (ret) {
 			dev_err(dev, "Create cq failed in kernel mode!\n");
 			goto err_cq;
 		}
 	}
 
-	/* Allocate cq index, fill cq_context */
-	ret = hns_roce_cq_alloc(hr_dev, cq_entries, &hr_cq->hr_buf.hr_mtt,
-				hr_cq, vector);
+	ret = hns_roce_alloc_cqc(hr_dev, hr_cq);
 	if (ret) {
-		dev_err(dev, "Creat CQ .Failed to cq_alloc.\n");
+		dev_err(dev, "Alloc CQ failed(%d).\n", ret);
 		goto err_dbmap;
 	}
 
@@ -462,11 +402,6 @@
 	if (!udata && hr_cq->tptr_addr)
 		*hr_cq->tptr_addr = 0;
 
-	/* Get created cq handler and carry out event */
-	hr_cq->comp = hns_roce_ib_cq_comp;
-	hr_cq->event = hns_roce_ib_cq_event;
-	hr_cq->cq_depth = cq_entries;
-
 	if (udata) {
 		resp.cqn = hr_cq->cqn;
 		ret = ib_copy_to_udata(udata, &resp, sizeof(resp));
@@ -477,7 +412,7 @@
 	return 0;
 
 err_cqc:
-	hns_roce_free_cq(hr_dev, hr_cq);
+	hns_roce_free_cqc(hr_dev, hr_cq);
 
 err_dbmap:
 	if (udata)
@@ -489,7 +424,7 @@
 	return ret;
 }
 
-void hns_roce_ib_destroy_cq(struct ib_cq *ib_cq, struct ib_udata *udata)
+void hns_roce_destroy_cq(struct ib_cq *ib_cq, struct ib_udata *udata)
 {
 	struct hns_roce_dev *hr_dev = to_hr_dev(ib_cq->device);
 	struct hns_roce_cq *hr_cq = to_hr_cq(ib_cq);
@@ -499,8 +434,8 @@
 		return;
 	}
 
-	hns_roce_free_cq(hr_dev, hr_cq);
-	hns_roce_mtt_cleanup(hr_dev, &hr_cq->hr_buf.hr_mtt);
+	hns_roce_free_cqc(hr_dev, hr_cq);
+	hns_roce_mtt_cleanup(hr_dev, &hr_cq->mtt);
 
 	ib_umem_release(hr_cq->umem);
 	if (udata) {
@@ -512,7 +447,7 @@
 					       &hr_cq->db);
 	} else {
 		/* Free the buff of stored cq */
-		hns_roce_ib_free_cq_buf(hr_dev, &hr_cq->hr_buf, ib_cq->cqe);
+		free_cq_buf(hr_dev, hr_cq);
 		if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_RECORD_DB)
 			hns_roce_free_db(hr_dev, &hr_cq->db);
 	}
@@ -520,38 +455,57 @@
 
 void hns_roce_cq_completion(struct hns_roce_dev *hr_dev, u32 cqn)
 {
-	struct device *dev = hr_dev->dev;
-	struct hns_roce_cq *cq;
+	struct hns_roce_cq *hr_cq;
+	struct ib_cq *ibcq;
 
-	cq = xa_load(&hr_dev->cq_table.array, cqn & (hr_dev->caps.num_cqs - 1));
-	if (!cq) {
-		dev_warn(dev, "Completion event for bogus CQ 0x%08x\n", cqn);
+	hr_cq = xa_load(&hr_dev->cq_table.array,
+			cqn & (hr_dev->caps.num_cqs - 1));
+	if (!hr_cq) {
+		dev_warn(hr_dev->dev, "Completion event for bogus CQ 0x%06x\n",
+			 cqn);
 		return;
 	}
 
-	++cq->arm_sn;
-	cq->comp(cq);
+	++hr_cq->arm_sn;
+	ibcq = &hr_cq->ib_cq;
+	if (ibcq->comp_handler)
+		ibcq->comp_handler(ibcq, ibcq->cq_context);
 }
 
 void hns_roce_cq_event(struct hns_roce_dev *hr_dev, u32 cqn, int event_type)
 {
-	struct hns_roce_cq_table *cq_table = &hr_dev->cq_table;
 	struct device *dev = hr_dev->dev;
-	struct hns_roce_cq *cq;
+	struct hns_roce_cq *hr_cq;
+	struct ib_event event;
+	struct ib_cq *ibcq;
 
-	cq = xa_load(&cq_table->array, cqn & (hr_dev->caps.num_cqs - 1));
-	if (cq)
-		atomic_inc(&cq->refcount);
+	hr_cq = xa_load(&hr_dev->cq_table.array,
+			cqn & (hr_dev->caps.num_cqs - 1));
+	if (!hr_cq) {
+		dev_warn(dev, "Async event for bogus CQ 0x%06x\n", cqn);
+		return;
+	}
 
-	if (!cq) {
-		dev_warn(dev, "Async event for bogus CQ %08x\n", cqn);
+	if (event_type != HNS_ROCE_EVENT_TYPE_CQ_ID_INVALID &&
+	    event_type != HNS_ROCE_EVENT_TYPE_CQ_ACCESS_ERROR &&
+	    event_type != HNS_ROCE_EVENT_TYPE_CQ_OVERFLOW) {
+		dev_err(dev, "Unexpected event type 0x%x on CQ 0x%06x\n",
+			event_type, cqn);
 		return;
 	}
 
-	cq->event(cq, (enum hns_roce_event)event_type);
+	atomic_inc(&hr_cq->refcount);
+
+	ibcq = &hr_cq->ib_cq;
+	if (ibcq->event_handler) {
+		event.device = ibcq->device;
+		event.element.cq = ibcq;
+		event.event = IB_EVENT_CQ_ERR;
+		ibcq->event_handler(&event, ibcq->cq_context);
+	}
 
-	if (atomic_dec_and_test(&cq->refcount))
-		complete(&cq->free);
+	if (atomic_dec_and_test(&hr_cq->refcount))
+		complete(&hr_cq->free);
 }
 
 int hns_roce_init_cq_table(struct hns_roce_dev *hr_dev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hns/hns_roce_db.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hns/hns_roce_db.c
@@ -31,7 +31,8 @@
 
 	refcount_set(&page->refcount, 1);
 	page->user_virt = page_addr;
-	page->umem = ib_umem_get(udata, page_addr, PAGE_SIZE, 0, 0);
+	page->umem = ib_umem_get(context->ibucontext.device, page_addr,
+				 PAGE_SIZE, 0);
 	if (IS_ERR(page->umem)) {
 		ret = PTR_ERR(page->umem);
 		kfree(page);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hns/hns_roce_device.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hns/hns_roce_device.h
@@ -45,16 +45,12 @@
 
 #define HNS_ROCE_MAX_MSG_LEN			0x80000000
 
-#define HNS_ROCE_ALOGN_UP(a, b) ((((a) + (b) - 1) / (b)) * (b))
-
 #define HNS_ROCE_IB_MIN_SQ_STRIDE		6
 
 #define HNS_ROCE_BA_SIZE			(32 * 4096)
 
 #define BA_BYTE_LEN				8
 
-#define BITS_PER_BYTE				8
-
 /* Hardware specification only for v1 engine */
 #define HNS_ROCE_MIN_CQE_NUM			0x40
 #define HNS_ROCE_MIN_WQE_NUM			0x20
@@ -109,11 +105,6 @@
 #define NODE_DESC_SIZE				64
 #define DB_REG_OFFSET				0x1000
 
-#define SERV_TYPE_RC				0
-#define SERV_TYPE_RD				1
-#define SERV_TYPE_UC				2
-#define SERV_TYPE_UD				3
-
 /* Configure to HW for PAGE_SIZE larger than 4KB */
 #define PG_SHIFT_OFFSET				(PAGE_SHIFT - 12)
 
@@ -133,6 +124,13 @@
 #define EQ_DEPTH_COEFF				2
 
 enum {
+	SERV_TYPE_RC,
+	SERV_TYPE_UC,
+	SERV_TYPE_RD,
+	SERV_TYPE_UD,
+};
+
+enum {
 	HNS_ROCE_SUPPORT_RQ_RECORD_DB = 1 << 0,
 	HNS_ROCE_SUPPORT_SQ_RECORD_DB = 1 << 1,
 };
@@ -425,8 +423,7 @@
 struct hns_roce_wq {
 	u64		*wrid;     /* Work request ID */
 	spinlock_t	lock;
-	int		wqe_cnt;  /* WQE num */
-	u32		max_post;
+	u32		wqe_cnt;  /* WQE num */
 	int		max_gs;
 	int		offset;
 	int		wqe_shift;	/* WQE size */
@@ -451,6 +448,7 @@
 	struct hns_roce_buf_list	*page_list;
 	int				nbufs;
 	u32				npages;
+	u32				size;
 	int				page_shift;
 };
 
@@ -482,22 +480,14 @@
 	int		order;
 };
 
-struct hns_roce_cq_buf {
-	struct hns_roce_buf hr_buf;
-	struct hns_roce_mtt hr_mtt;
-};
-
 struct hns_roce_cq {
 	struct ib_cq			ib_cq;
-	struct hns_roce_cq_buf		hr_buf;
+	struct hns_roce_buf		buf;
+	struct hns_roce_mtt		mtt;
 	struct hns_roce_db		db;
 	u8				db_en;
 	spinlock_t			lock;
 	struct ib_umem			*umem;
-	void (*comp)(struct hns_roce_cq *cq);
-	void (*event)(struct hns_roce_cq *cq, enum hns_roce_event event_type);
-
-	struct hns_roce_uar		*uar;
 	u32				cq_depth;
 	u32				cons_index;
 	u32				*set_ci_db;
@@ -508,6 +498,10 @@
 	u32				vector;
 	atomic_t			refcount;
 	struct completion		free;
+	struct list_head		sq_list; /* all qps on this send cq */
+	struct list_head		rq_list; /* all qps on this recv cq */
+	int				is_armed; /* cq is armed */
+	struct list_head		node; /* all armed cqs are on a list */
 };
 
 struct hns_roce_idx_que {
@@ -521,9 +515,8 @@
 
 struct hns_roce_srq {
 	struct ib_srq		ibsrq;
-	void (*event)(struct hns_roce_srq *srq, enum hns_roce_event event);
 	unsigned long		srqn;
-	int			max;
+	u32			wqe_cnt;
 	int			max_gs;
 	int			wqe_shift;
 	void __iomem		*db_reg_l;
@@ -539,8 +532,8 @@
 	spinlock_t		lock;
 	int			head;
 	int			tail;
-	u16			wqe_ctr;
 	struct mutex		mutex;
+	void (*event)(struct hns_roce_srq *srq, enum hns_roce_event event);
 };
 
 struct hns_roce_uar_table {
@@ -582,7 +575,7 @@
 	u8          tclass;
 	u8          dgid[HNS_ROCE_GID_SIZE];
 	u8          mac[ETH_ALEN];
-	u16         vlan;
+	u16         vlan_id;
 	bool	    vlan_en;
 };
 
@@ -648,6 +641,19 @@
 	u32			 wqe_cnt;
 };
 
+enum {
+	HNS_ROCE_FLUSH_FLAG = 0,
+};
+
+struct hns_roce_work {
+	struct hns_roce_dev *hr_dev;
+	struct work_struct work;
+	u32 qpn;
+	u32 cqn;
+	int event_type;
+	int sub_type;
+};
+
 struct hns_roce_qp {
 	struct ib_qp		ibqp;
 	struct hns_roce_buf	hr_buf;
@@ -657,8 +663,7 @@
 	u8			rdb_en;
 	u8			sdb_en;
 	u32			doorbell_qpn;
-	u32			sq_signal_bits;
-	u32			sq_next_wqe;
+	enum ib_sig_type	sq_signal_bits;
 	struct hns_roce_wq	sq;
 
 	struct ib_umem		*umem;
@@ -668,7 +673,6 @@
 	/* this define must less than HNS_ROCE_MAX_BT_REGION */
 #define HNS_ROCE_WQE_REGION_MAX	 3
 	struct hns_roce_buf_region regions[HNS_ROCE_WQE_REGION_MAX];
-	int			region_cnt;
 	int                     wqe_bt_pg_shift;
 
 	u32			buff_size;
@@ -692,11 +696,13 @@
 	struct hns_roce_sge	sge;
 	u32			next_sge;
 
+	/* 0: flush needed, 1: unneeded */
+	unsigned long		flush_flag;
+	struct hns_roce_work	flush_work;
 	struct hns_roce_rinl_buf rq_inl_buf;
-};
-
-struct hns_roce_sqp {
-	struct hns_roce_qp	hr_qp;
+	struct list_head	node;		/* all qps are on a list */
+	struct list_head	rq_node;	/* all recv qps are on a list */
+	struct list_head	sq_node;	/* all send qps are on a list */
 };
 
 struct hns_roce_ib_iboe {
@@ -771,14 +777,8 @@
 	int				eqe_ba_pg_sz;
 	int				eqe_buf_pg_sz;
 	int				hop_num;
-	u64				*bt_l0;	/* Base address table for L0 */
-	u64				**bt_l1; /* Base address table for L1 */
-	u64				**buf;
-	dma_addr_t			l0_dma;
-	dma_addr_t			*l1_dma;
-	dma_addr_t			*buf_dma;
-	u32				l0_last_num; /* L0 last chunk num */
-	u32				l1_last_num; /* L1 last chunk num */
+	struct hns_roce_mtr		mtr;
+	struct hns_roce_buf		buf;
 	int				eq_max_cnt;
 	int				eq_period;
 	int				shift;
@@ -809,10 +809,8 @@
 	int             reserved_qps;
 	int		num_qpc_timer;
 	int		num_cqc_timer;
-	u32		max_srq_sg;
 	int		num_srqs;
 	u32		max_wqes;
-	u32		max_srqs;
 	u32		max_srq_wrs;
 	u32		max_srq_sges;
 	u32		max_sq_desc_sz;
@@ -821,12 +819,11 @@
 	int		max_qp_init_rdma;
 	int		max_qp_dest_rdma;
 	int		num_cqs;
-	int		max_cqes;
-	int		min_cqes;
+	u32		max_cqes;
+	u32		min_cqes;
 	u32		min_wqes;
 	int		reserved_cqs;
 	int		reserved_srqs;
-	u32		max_srqwqes;
 	int		num_aeq_vectors;
 	int		num_comp_vectors;
 	int		num_other_vectors;
@@ -893,7 +890,7 @@
 	u32		cqc_timer_ba_pg_sz;
 	u32		cqc_timer_buf_pg_sz;
 	u32		cqc_timer_hop_num;
-	u32		cqe_ba_pg_sz;
+	u32             cqe_ba_pg_sz;	/* page_size = 4K*(2^cqe_ba_pg_sz) */
 	u32		cqe_buf_pg_sz;
 	u32		cqe_hop_num;
 	u32		srqwqe_ba_pg_sz;
@@ -910,15 +907,12 @@
 	u32		tpq_buf_pg_sz;
 	u32		chunk_sz;	/* chunk size in non multihop mode */
 	u64		flags;
-};
-
-struct hns_roce_work {
-	struct hns_roce_dev *hr_dev;
-	struct work_struct work;
-	u32 qpn;
-	u32 cqn;
-	int event_type;
-	int sub_type;
+	u16		default_ceq_max_cnt;
+	u16		default_ceq_period;
+	u16		default_aeq_max_cnt;
+	u16		default_aeq_period;
+	u16		default_aeq_arm_st;
+	u16		default_ceq_arm_st;
 };
 
 struct hns_roce_dfx_hw {
@@ -926,6 +920,12 @@
 			      int *buffer);
 };
 
+enum hns_roce_device_state {
+	HNS_ROCE_DEVICE_STATE_INITED,
+	HNS_ROCE_DEVICE_STATE_RST_DOWN,
+	HNS_ROCE_DEVICE_STATE_UNINIT,
+};
+
 struct hns_roce_hw {
 	int (*reset)(struct hns_roce_dev *hr_dev, bool enable);
 	int (*cmq_init)(struct hns_roce_dev *hr_dev);
@@ -953,7 +953,7 @@
 	int (*mw_write_mtpt)(void *mb_buf, struct hns_roce_mw *mw);
 	void (*write_cqc)(struct hns_roce_dev *hr_dev,
 			  struct hns_roce_cq *hr_cq, void *mb_buf, u64 *mtts,
-			  dma_addr_t dma_handle, int nent, u32 vector);
+			  dma_addr_t dma_handle);
 	int (*set_hem)(struct hns_roce_dev *hr_dev,
 		       struct hns_roce_hem_table *table, int obj, int step_idx);
 	int (*clear_hem)(struct hns_roce_dev *hr_dev,
@@ -1008,6 +1008,9 @@
 	bool			dis_db;
 	unsigned long		reset_cnt;
 	struct hns_roce_ib_iboe iboe;
+	enum hns_roce_device_state state;
+	struct list_head	qp_list; /* list of all qps on this dev */
+	spinlock_t		qp_list_lock; /* protect qp_list */
 
 	struct list_head        pgdir_list;
 	struct mutex            pgdir_mutex;
@@ -1092,11 +1095,6 @@
 	return container_of(ibsrq, struct hns_roce_srq, ibsrq);
 }
 
-static inline struct hns_roce_sqp *hr_to_hr_sqp(struct hns_roce_qp *hr_qp)
-{
-	return container_of(hr_qp, struct hns_roce_sqp, hr_qp);
-}
-
 static inline void hns_roce_write64_k(__le32 val[2], void __iomem *dest)
 {
 	__raw_writeq(*(u64 *) val, dest);
@@ -1153,7 +1151,6 @@
 
 int hns_roce_init_pd_table(struct hns_roce_dev *hr_dev);
 int hns_roce_init_mr_table(struct hns_roce_dev *hr_dev);
-int hns_roce_init_eq_table(struct hns_roce_dev *hr_dev);
 int hns_roce_init_cq_table(struct hns_roce_dev *hr_dev);
 int hns_roce_init_qp_table(struct hns_roce_dev *hr_dev);
 int hns_roce_init_srq_table(struct hns_roce_dev *hr_dev);
@@ -1198,9 +1195,9 @@
 int hns_roce_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents,
 		       unsigned int *sg_offset);
 int hns_roce_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata);
-int hns_roce_hw2sw_mpt(struct hns_roce_dev *hr_dev,
-		       struct hns_roce_cmd_mailbox *mailbox,
-		       unsigned long mpt_index);
+int hns_roce_hw_destroy_mpt(struct hns_roce_dev *hr_dev,
+			    struct hns_roce_cmd_mailbox *mailbox,
+			    unsigned long mpt_index);
 unsigned long key_to_hw_index(u32 key);
 
 struct ib_mw *hns_roce_alloc_mw(struct ib_pd *pd, enum ib_mw_type,
@@ -1240,6 +1237,7 @@
 				 struct ib_udata *udata);
 int hns_roce_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
 		       int attr_mask, struct ib_udata *udata);
+void init_flush_work(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp);
 void *get_recv_wqe(struct hns_roce_qp *hr_qp, int n);
 void *get_send_wqe(struct hns_roce_qp *hr_qp, int n);
 void *get_send_extend_sge(struct hns_roce_qp *hr_qp, int n);
@@ -1251,18 +1249,16 @@
 void hns_roce_unlock_cqs(struct hns_roce_cq *send_cq,
 			 struct hns_roce_cq *recv_cq);
 void hns_roce_qp_remove(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp);
-void hns_roce_qp_free(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp);
-void hns_roce_release_range_qp(struct hns_roce_dev *hr_dev, int base_qpn,
-			       int cnt);
+void hns_roce_qp_destroy(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp,
+			 struct ib_udata *udata);
 __be32 send_ieth(const struct ib_send_wr *wr);
 int to_hr_qp_type(int qp_type);
 
-int hns_roce_ib_create_cq(struct ib_cq *ib_cq,
-			  const struct ib_cq_init_attr *attr,
-			  struct ib_udata *udata);
+int hns_roce_create_cq(struct ib_cq *ib_cq, const struct ib_cq_init_attr *attr,
+		       struct ib_udata *udata);
 
-void hns_roce_ib_destroy_cq(struct ib_cq *ib_cq, struct ib_udata *udata);
-void hns_roce_free_cq(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq);
+void hns_roce_destroy_cq(struct ib_cq *ib_cq, struct ib_udata *udata);
+void hns_roce_free_cqc(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq);
 
 int hns_roce_db_map_user(struct hns_roce_ucontext *context,
 			 struct ib_udata *udata, unsigned long virt,
@@ -1278,6 +1274,7 @@
 void hns_roce_qp_event(struct hns_roce_dev *hr_dev, u32 qpn, int event_type);
 void hns_roce_srq_event(struct hns_roce_dev *hr_dev, u32 srqn, int event_type);
 int hns_get_gid_index(struct hns_roce_dev *hr_dev, u8 port, int gid_index);
+void hns_roce_handle_device_err(struct hns_roce_dev *hr_dev);
 int hns_roce_init(struct hns_roce_dev *hr_dev);
 void hns_roce_exit(struct hns_roce_dev *hr_dev);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hns/hns_roce_hem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hns/hns_roce_hem.c
@@ -1323,10 +1323,12 @@
 
 	/* config L1 bt to last bt and link them to corresponding parent */
 	for (level = 1; level < hopnum; level++) {
-		cur = hem_list_search_item(&mid_bt[level], offset);
-		if (cur) {
-			hem_ptrs[level] = cur;
-			continue;
+		if (!hem_list_is_bottom_bt(hopnum, level)) {
+			cur = hem_list_search_item(&mid_bt[level], offset);
+			if (cur) {
+				hem_ptrs[level] = cur;
+				continue;
+			}
 		}
 
 		step = hem_list_calc_ba_range(hopnum, level, unit);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hns/hns_roce_hem.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hns/hns_roce_hem.h
@@ -62,16 +62,16 @@
 	 (sizeof(struct scatterlist) + sizeof(void *)))
 
 #define check_whether_bt_num_3(type, hop_num) \
-	(type < HEM_TYPE_MTT && hop_num == 2)
+	((type) < HEM_TYPE_MTT && (hop_num) == 2)
 
 #define check_whether_bt_num_2(type, hop_num) \
-	((type < HEM_TYPE_MTT && hop_num == 1) || \
-	(type >= HEM_TYPE_MTT && hop_num == 2))
+	(((type) < HEM_TYPE_MTT && (hop_num) == 1) || \
+	((type) >= HEM_TYPE_MTT && (hop_num) == 2))
 
 #define check_whether_bt_num_1(type, hop_num) \
-	((type < HEM_TYPE_MTT && hop_num == HNS_ROCE_HOP_NUM_0) || \
-	(type >= HEM_TYPE_MTT && hop_num == 1) || \
-	(type >= HEM_TYPE_MTT && hop_num == HNS_ROCE_HOP_NUM_0))
+	(((type) < HEM_TYPE_MTT && (hop_num) == HNS_ROCE_HOP_NUM_0) || \
+	((type) >= HEM_TYPE_MTT && (hop_num) == 1) || \
+	((type) >= HEM_TYPE_MTT && (hop_num) == HNS_ROCE_HOP_NUM_0))
 
 enum {
 	 HNS_ROCE_HEM_PAGE_SHIFT = 12,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hns/hns_roce_hw_v1.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hns/hns_roce_hw_v1.c
@@ -69,13 +69,13 @@
 	struct hns_roce_wqe_data_seg *dseg = NULL;
 	struct hns_roce_qp *qp = to_hr_qp(ibqp);
 	struct device *dev = &hr_dev->pdev->dev;
-	struct hns_roce_sq_db sq_db;
+	struct hns_roce_sq_db sq_db = {};
 	int ps_opcode = 0, i = 0;
 	unsigned long flags = 0;
 	void *wqe = NULL;
 	__le32 doorbell[2];
+	u32 wqe_idx = 0;
 	int nreq = 0;
-	u32 ind = 0;
 	int ret = 0;
 	u8 *smac;
 	int loopback;
@@ -88,7 +88,7 @@
 	}
 
 	spin_lock_irqsave(&qp->sq.lock, flags);
-	ind = qp->sq_next_wqe;
+
 	for (nreq = 0; wr; ++nreq, wr = wr->next) {
 		if (hns_roce_wq_overflow(&qp->sq, nreq, qp->ibqp.send_cq)) {
 			ret = -ENOMEM;
@@ -96,6 +96,8 @@
 			goto out;
 		}
 
+		wqe_idx = (qp->sq.head + nreq) & (qp->sq.wqe_cnt - 1);
+
 		if (unlikely(wr->num_sge > qp->sq.max_gs)) {
 			dev_err(dev, "num_sge=%d > qp->sq.max_gs=%d\n",
 				wr->num_sge, qp->sq.max_gs);
@@ -104,9 +106,8 @@
 			goto out;
 		}
 
-		wqe = get_send_wqe(qp, ind & (qp->sq.wqe_cnt - 1));
-		qp->sq.wrid[(qp->sq.head + nreq) & (qp->sq.wqe_cnt - 1)] =
-								      wr->wr_id;
+		wqe = get_send_wqe(qp, wqe_idx);
+		qp->sq.wrid[wqe_idx] = wr->wr_id;
 
 		/* Corresponding to the RC and RD type wqe process separately */
 		if (ibqp->qp_type == IB_QPT_GSI) {
@@ -210,7 +211,6 @@
 				       cpu_to_le32((wr->sg_list[1].addr) >> 32);
 			ud_sq_wqe->l_key1 =
 				       cpu_to_le32(wr->sg_list[1].lkey);
-			ind++;
 		} else if (ibqp->qp_type == IB_QPT_RC) {
 			u32 tmp_len = 0;
 
@@ -271,7 +271,6 @@
 				ps_opcode = HNS_ROCE_WQE_OPCODE_SEND;
 				break;
 			case IB_WR_LOCAL_INV:
-				break;
 			case IB_WR_ATOMIC_CMP_AND_SWP:
 			case IB_WR_ATOMIC_FETCH_AND_ADD:
 			case IB_WR_LSO:
@@ -308,7 +307,6 @@
 				ctrl->flag |= cpu_to_le32(wr->num_sge <<
 					      HNS_ROCE_WQE_SGE_NUM_BIT);
 			}
-			ind++;
 		}
 	}
 
@@ -319,8 +317,6 @@
 		/* Memory barrier */
 		wmb();
 
-		sq_db.u32_4 = 0;
-		sq_db.u32_8 = 0;
 		roce_set_field(sq_db.u32_4, SQ_DOORBELL_U32_4_SQ_HEAD_M,
 			       SQ_DOORBELL_U32_4_SQ_HEAD_S,
 			      (qp->sq.head & ((qp->sq.wqe_cnt << 1) - 1)));
@@ -336,7 +332,6 @@
 		doorbell[1] = sq_db.u32_8;
 
 		hns_roce_write64_k(doorbell, qp->sq.db_reg_l);
-		qp->sq_next_wqe = ind;
 	}
 
 	spin_unlock_irqrestore(&qp->sq.lock, flags);
@@ -348,22 +343,21 @@
 				 const struct ib_recv_wr *wr,
 				 const struct ib_recv_wr **bad_wr)
 {
-	int ret = 0;
-	int nreq = 0;
-	int ind = 0;
-	int i = 0;
-	u32 reg_val;
-	unsigned long flags = 0;
 	struct hns_roce_rq_wqe_ctrl *ctrl = NULL;
 	struct hns_roce_wqe_data_seg *scat = NULL;
 	struct hns_roce_qp *hr_qp = to_hr_qp(ibqp);
 	struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device);
 	struct device *dev = &hr_dev->pdev->dev;
-	struct hns_roce_rq_db rq_db;
+	struct hns_roce_rq_db rq_db = {};
 	__le32 doorbell[2] = {0};
+	unsigned long flags = 0;
+	unsigned int wqe_idx;
+	int ret = 0;
+	int nreq = 0;
+	int i = 0;
+	u32 reg_val;
 
 	spin_lock_irqsave(&hr_qp->rq.lock, flags);
-	ind = hr_qp->rq.head & (hr_qp->rq.wqe_cnt - 1);
 
 	for (nreq = 0; wr; ++nreq, wr = wr->next) {
 		if (hns_roce_wq_overflow(&hr_qp->rq, nreq,
@@ -373,6 +367,8 @@
 			goto out;
 		}
 
+		wqe_idx = (hr_qp->rq.head + nreq) & (hr_qp->rq.wqe_cnt - 1);
+
 		if (unlikely(wr->num_sge > hr_qp->rq.max_gs)) {
 			dev_err(dev, "rq:num_sge=%d > qp->sq.max_gs=%d\n",
 				wr->num_sge, hr_qp->rq.max_gs);
@@ -381,7 +377,7 @@
 			goto out;
 		}
 
-		ctrl = get_recv_wqe(hr_qp, ind);
+		ctrl = get_recv_wqe(hr_qp, wqe_idx);
 
 		roce_set_field(ctrl->rwqe_byte_12,
 			       RQ_WQE_CTRL_RWQE_BYTE_12_RWQE_SGE_NUM_M,
@@ -393,9 +389,7 @@
 		for (i = 0; i < wr->num_sge; i++)
 			set_data_seg(scat + i, wr->sg_list + i);
 
-		hr_qp->rq.wrid[ind] = wr->wr_id;
-
-		ind = (ind + 1) & (hr_qp->rq.wqe_cnt - 1);
+		hr_qp->rq.wrid[wqe_idx] = wr->wr_id;
 	}
 
 out:
@@ -421,9 +415,6 @@
 				   ROCEE_QP1C_CFG3_0_REG +
 				   QP1C_CFGN_OFFSET * hr_qp->phy_port, reg_val);
 		} else {
-			rq_db.u32_4 = 0;
-			rq_db.u32_8 = 0;
-
 			roce_set_field(rq_db.u32_4, RQ_DOORBELL_U32_4_RQ_HEAD_M,
 				       RQ_DOORBELL_U32_4_RQ_HEAD_S,
 				       hr_qp->rq.head);
@@ -732,7 +723,7 @@
 	if (!cq)
 		return -ENOMEM;
 
-	ret = hns_roce_ib_create_cq(cq, &cq_init_attr, NULL);
+	ret = hns_roce_create_cq(cq, &cq_init_attr, NULL);
 	if (ret) {
 		dev_err(dev, "Create cq for reserved loop qp failed!");
 		goto alloc_cq_failed;
@@ -868,7 +859,7 @@
 	kfree(pd);
 
 alloc_mem_failed:
-	hns_roce_ib_destroy_cq(cq, NULL);
+	hns_roce_destroy_cq(cq, NULL);
 alloc_cq_failed:
 	kfree(cq);
 	return ret;
@@ -897,7 +888,7 @@
 				i, ret);
 	}
 
-	hns_roce_ib_destroy_cq(&free_mr->mr_free_cq->ib_cq, NULL);
+	hns_roce_destroy_cq(&free_mr->mr_free_cq->ib_cq, NULL);
 	kfree(&free_mr->mr_free_cq->ib_cq);
 	hns_roce_dealloc_pd(&free_mr->mr_free_pd->ibpd, NULL);
 	kfree(&free_mr->mr_free_pd->ibpd);
@@ -1114,9 +1105,10 @@
 	free_mr = &priv->free_mr;
 
 	if (mr->enabled) {
-		if (hns_roce_hw2sw_mpt(hr_dev, NULL, key_to_hw_index(mr->key)
-				       & (hr_dev->caps.num_mtpts - 1)))
-			dev_warn(dev, "HW2SW_MPT failed!\n");
+		if (hns_roce_hw_destroy_mpt(hr_dev, NULL,
+					    key_to_hw_index(mr->key) &
+					    (hr_dev->caps.num_mtpts - 1)))
+			dev_warn(dev, "DESTROY_MPT failed!\n");
 	}
 
 	mr_work = kzalloc(sizeof(*mr_work), GFP_KERNEL);
@@ -1979,8 +1971,7 @@
 
 static void *get_cqe(struct hns_roce_cq *hr_cq, int n)
 {
-	return hns_roce_buf_offset(&hr_cq->hr_buf.hr_buf,
-				   n * HNS_ROCE_V1_CQE_ENTRY_SIZE);
+	return hns_roce_buf_offset(&hr_cq->buf, n * HNS_ROCE_V1_CQE_ENTRY_SIZE);
 }
 
 static void *get_sw_cqe(struct hns_roce_cq *hr_cq, int n)
@@ -1989,7 +1980,7 @@
 
 	/* Get cqe when Owner bit is Conversely with the MSB of cons_idx */
 	return (roce_get_bit(hr_cqe->cqe_byte_4, CQE_BYTE_4_OWNER_S) ^
-		!!(n & (hr_cq->ib_cq.cqe + 1))) ? hr_cqe : NULL;
+		!!(n & hr_cq->cq_depth)) ? hr_cqe : NULL;
 }
 
 static struct hns_roce_cqe *next_cqe_sw(struct hns_roce_cq *hr_cq)
@@ -2072,8 +2063,7 @@
 
 static void hns_roce_v1_write_cqc(struct hns_roce_dev *hr_dev,
 				  struct hns_roce_cq *hr_cq, void *mb_buf,
-				  u64 *mtts, dma_addr_t dma_handle, int nent,
-				  u32 vector)
+				  u64 *mtts, dma_addr_t dma_handle)
 {
 	struct hns_roce_cq_context *cq_context = NULL;
 	struct hns_roce_buf_list *tptr_buf;
@@ -2108,9 +2098,9 @@
 	roce_set_field(cq_context->cqc_byte_12,
 		       CQ_CONTEXT_CQC_BYTE_12_CQ_CQE_SHIFT_M,
 		       CQ_CONTEXT_CQC_BYTE_12_CQ_CQE_SHIFT_S,
-		       ilog2((unsigned int)nent));
+		       ilog2(hr_cq->cq_depth));
 	roce_set_field(cq_context->cqc_byte_12, CQ_CONTEXT_CQC_BYTE_12_CEQN_M,
-		       CQ_CONTEXT_CQC_BYTE_12_CEQN_S, vector);
+		       CQ_CONTEXT_CQC_BYTE_12_CEQN_S, hr_cq->vector);
 
 	cq_context->cur_cqe_ba0_l = cpu_to_le32((u32)(mtts[0]));
 
@@ -2702,7 +2692,6 @@
 		hr_qp->rq.tail = 0;
 		hr_qp->sq.head = 0;
 		hr_qp->sq.tail = 0;
-		hr_qp->sq_next_wqe = 0;
 	}
 
 	kfree(context);
@@ -3316,7 +3305,6 @@
 		hr_qp->rq.tail = 0;
 		hr_qp->sq.head = 0;
 		hr_qp->sq.tail = 0;
-		hr_qp->sq_next_wqe = 0;
 	}
 out:
 	kfree(context);
@@ -3615,39 +3603,25 @@
 	if (ret)
 		return ret;
 
-	send_cq = to_hr_cq(hr_qp->ibqp.send_cq);
-	recv_cq = to_hr_cq(hr_qp->ibqp.recv_cq);
+	send_cq = hr_qp->ibqp.send_cq ? to_hr_cq(hr_qp->ibqp.send_cq) : NULL;
+	recv_cq = hr_qp->ibqp.recv_cq ? to_hr_cq(hr_qp->ibqp.recv_cq) : NULL;
 
 	hns_roce_lock_cqs(send_cq, recv_cq);
 	if (!udata) {
-		__hns_roce_v1_cq_clean(recv_cq, hr_qp->qpn, hr_qp->ibqp.srq ?
-				       to_hr_srq(hr_qp->ibqp.srq) : NULL);
-		if (send_cq != recv_cq)
+		if (recv_cq)
+			__hns_roce_v1_cq_clean(recv_cq, hr_qp->qpn,
+					       (hr_qp->ibqp.srq ?
+						to_hr_srq(hr_qp->ibqp.srq) :
+						NULL));
+
+		if (send_cq && send_cq != recv_cq)
 			__hns_roce_v1_cq_clean(send_cq, hr_qp->qpn, NULL);
 	}
-	hns_roce_unlock_cqs(send_cq, recv_cq);
-
 	hns_roce_qp_remove(hr_dev, hr_qp);
-	hns_roce_qp_free(hr_dev, hr_qp);
-
-	/* RC QP, release QPN */
-	if (hr_qp->ibqp.qp_type == IB_QPT_RC)
-		hns_roce_release_range_qp(hr_dev, hr_qp->qpn, 1);
-
-	hns_roce_mtt_cleanup(hr_dev, &hr_qp->mtt);
-
-	ib_umem_release(hr_qp->umem);
-	if (!udata) {
-		kfree(hr_qp->sq.wrid);
-		kfree(hr_qp->rq.wrid);
+	hns_roce_unlock_cqs(send_cq, recv_cq);
 
-		hns_roce_buf_free(hr_dev, hr_qp->buff_size, &hr_qp->hr_buf);
-	}
+	hns_roce_qp_destroy(hr_dev, hr_qp, udata);
 
-	if (hr_qp->ibqp.qp_type == IB_QPT_RC)
-		kfree(hr_qp);
-	else
-		kfree(hr_to_hr_sqp(hr_qp));
 	return 0;
 }
 
@@ -3658,10 +3632,9 @@
 	struct device *dev = &hr_dev->pdev->dev;
 	u32 cqe_cnt_ori;
 	u32 cqe_cnt_cur;
-	u32 cq_buf_size;
 	int wait_time = 0;
 
-	hns_roce_free_cq(hr_dev, hr_cq);
+	hns_roce_free_cqc(hr_dev, hr_cq);
 
 	/*
 	 * Before freeing cq buffer, we need to ensure that the outstanding CQE
@@ -3686,13 +3659,12 @@
 		wait_time++;
 	}
 
-	hns_roce_mtt_cleanup(hr_dev, &hr_cq->hr_buf.hr_mtt);
+	hns_roce_mtt_cleanup(hr_dev, &hr_cq->mtt);
 
 	ib_umem_release(hr_cq->umem);
 	if (!udata) {
 		/* Free the buff of stored cq */
-		cq_buf_size = (ibcq->cqe + 1) * hr_dev->caps.cq_entry_sz;
-		hns_roce_buf_free(hr_dev, cq_buf_size, &hr_cq->hr_buf.hr_buf);
+		hns_roce_buf_free(hr_dev, hr_cq->buf.size, &hr_cq->buf);
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
@@ -63,20 +63,15 @@
 	struct hns_roce_mr *mr = to_hr_mr(wr->mr);
 
 	/* use ib_access_flags */
-	roce_set_bit(rc_sq_wqe->byte_4,
-		     V2_RC_FRMR_WQE_BYTE_4_BIND_EN_S,
+	roce_set_bit(rc_sq_wqe->byte_4, V2_RC_FRMR_WQE_BYTE_4_BIND_EN_S,
 		     wr->access & IB_ACCESS_MW_BIND ? 1 : 0);
-	roce_set_bit(rc_sq_wqe->byte_4,
-		     V2_RC_FRMR_WQE_BYTE_4_ATOMIC_S,
+	roce_set_bit(rc_sq_wqe->byte_4, V2_RC_FRMR_WQE_BYTE_4_ATOMIC_S,
 		     wr->access & IB_ACCESS_REMOTE_ATOMIC ? 1 : 0);
-	roce_set_bit(rc_sq_wqe->byte_4,
-		     V2_RC_FRMR_WQE_BYTE_4_RR_S,
+	roce_set_bit(rc_sq_wqe->byte_4, V2_RC_FRMR_WQE_BYTE_4_RR_S,
 		     wr->access & IB_ACCESS_REMOTE_READ ? 1 : 0);
-	roce_set_bit(rc_sq_wqe->byte_4,
-		     V2_RC_FRMR_WQE_BYTE_4_RW_S,
+	roce_set_bit(rc_sq_wqe->byte_4, V2_RC_FRMR_WQE_BYTE_4_RW_S,
 		     wr->access & IB_ACCESS_REMOTE_WRITE ? 1 : 0);
-	roce_set_bit(rc_sq_wqe->byte_4,
-		     V2_RC_FRMR_WQE_BYTE_4_LW_S,
+	roce_set_bit(rc_sq_wqe->byte_4, V2_RC_FRMR_WQE_BYTE_4_LW_S,
 		     wr->access & IB_ACCESS_LOCAL_WRITE ? 1 : 0);
 
 	/* Data structure reuse may lead to confusion */
@@ -110,7 +105,7 @@
 }
 
 static void set_extend_sge(struct hns_roce_qp *qp, const struct ib_send_wr *wr,
-			   unsigned int *sge_ind)
+			   unsigned int *sge_ind, int valid_num_sge)
 {
 	struct hns_roce_v2_wqe_data_seg *dseg;
 	struct ib_sge *sg;
@@ -123,7 +118,7 @@
 
 	if (qp->ibqp.qp_type == IB_QPT_RC || qp->ibqp.qp_type == IB_QPT_UC)
 		num_in_wqe = HNS_ROCE_V2_UC_RC_SGE_NUM_IN_WQE;
-	extend_sge_num = wr->num_sge - num_in_wqe;
+	extend_sge_num = valid_num_sge - num_in_wqe;
 	sg = wr->sg_list + num_in_wqe;
 	shift = qp->hr_buf.page_shift;
 
@@ -159,14 +154,16 @@
 static int set_rwqe_data_seg(struct ib_qp *ibqp, const struct ib_send_wr *wr,
 			     struct hns_roce_v2_rc_send_wqe *rc_sq_wqe,
 			     void *wqe, unsigned int *sge_ind,
+			     int valid_num_sge,
 			     const struct ib_send_wr **bad_wr)
 {
 	struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device);
 	struct hns_roce_v2_wqe_data_seg *dseg = wqe;
 	struct hns_roce_qp *qp = to_hr_qp(ibqp);
+	int j = 0;
 	int i;
 
-	if (wr->send_flags & IB_SEND_INLINE && wr->num_sge) {
+	if (wr->send_flags & IB_SEND_INLINE && valid_num_sge) {
 		if (le32_to_cpu(rc_sq_wqe->msg_len) >
 		    hr_dev->caps.max_sq_inline) {
 			*bad_wr = wr;
@@ -190,7 +187,7 @@
 		roce_set_bit(rc_sq_wqe->byte_4, V2_RC_SEND_WQE_BYTE_4_INLINE_S,
 			     1);
 	} else {
-		if (wr->num_sge <= HNS_ROCE_V2_UC_RC_SGE_NUM_IN_WQE) {
+		if (valid_num_sge <= HNS_ROCE_V2_UC_RC_SGE_NUM_IN_WQE) {
 			for (i = 0; i < wr->num_sge; i++) {
 				if (likely(wr->sg_list[i].length)) {
 					set_data_seg_v2(dseg, wr->sg_list + i);
@@ -203,28 +200,81 @@
 				     V2_RC_SEND_WQE_BYTE_20_MSG_START_SGE_IDX_S,
 				     (*sge_ind) & (qp->sge.sge_cnt - 1));
 
-			for (i = 0; i < HNS_ROCE_V2_UC_RC_SGE_NUM_IN_WQE; i++) {
+			for (i = 0; i < wr->num_sge &&
+			     j < HNS_ROCE_V2_UC_RC_SGE_NUM_IN_WQE; i++) {
 				if (likely(wr->sg_list[i].length)) {
 					set_data_seg_v2(dseg, wr->sg_list + i);
 					dseg++;
+					j++;
 				}
 			}
 
-			set_extend_sge(qp, wr, sge_ind);
+			set_extend_sge(qp, wr, sge_ind, valid_num_sge);
 		}
 
 		roce_set_field(rc_sq_wqe->byte_16,
 			       V2_RC_SEND_WQE_BYTE_16_SGE_NUM_M,
-			       V2_RC_SEND_WQE_BYTE_16_SGE_NUM_S, wr->num_sge);
+			       V2_RC_SEND_WQE_BYTE_16_SGE_NUM_S, valid_num_sge);
 	}
 
 	return 0;
 }
 
-static int hns_roce_v2_modify_qp(struct ib_qp *ibqp,
-				 const struct ib_qp_attr *attr,
-				 int attr_mask, enum ib_qp_state cur_state,
-				 enum ib_qp_state new_state);
+static int check_send_valid(struct hns_roce_dev *hr_dev,
+			    struct hns_roce_qp *hr_qp)
+{
+	struct ib_qp *ibqp = &hr_qp->ibqp;
+	struct device *dev = hr_dev->dev;
+
+	if (unlikely(ibqp->qp_type != IB_QPT_RC &&
+		     ibqp->qp_type != IB_QPT_GSI &&
+		     ibqp->qp_type != IB_QPT_UD)) {
+		dev_err(dev, "Not supported QP(0x%x)type!\n", ibqp->qp_type);
+		return -EOPNOTSUPP;
+	} else if (unlikely(hr_qp->state == IB_QPS_RESET ||
+		   hr_qp->state == IB_QPS_INIT ||
+		   hr_qp->state == IB_QPS_RTR)) {
+		dev_err(dev, "Post WQE fail, QP state %d!\n", hr_qp->state);
+		return -EINVAL;
+	} else if (unlikely(hr_dev->state >= HNS_ROCE_DEVICE_STATE_RST_DOWN)) {
+		dev_err(dev, "Post WQE fail, dev state %d!\n", hr_dev->state);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static inline void update_sq_db(struct hns_roce_dev *hr_dev,
+				struct hns_roce_qp *qp)
+{
+	/*
+	 * Hip08 hardware cannot flush the WQEs in SQ if the QP state
+	 * gets into errored mode. Hence, as a workaround to this
+	 * hardware limitation, driver needs to assist in flushing. But
+	 * the flushing operation uses mailbox to convey the QP state to
+	 * the hardware and which can sleep due to the mutex protection
+	 * around the mailbox calls. Hence, use the deferred flush for
+	 * now.
+	 */
+	if (qp->state == IB_QPS_ERR) {
+		if (!test_and_set_bit(HNS_ROCE_FLUSH_FLAG, &qp->flush_flag))
+			init_flush_work(hr_dev, qp);
+	} else {
+		struct hns_roce_v2_db sq_db = {};
+
+		roce_set_field(sq_db.byte_4, V2_DB_BYTE_4_TAG_M,
+			       V2_DB_BYTE_4_TAG_S, qp->doorbell_qpn);
+		roce_set_field(sq_db.byte_4, V2_DB_BYTE_4_CMD_M,
+			       V2_DB_BYTE_4_CMD_S, HNS_ROCE_V2_SQ_DB);
+		roce_set_field(sq_db.parameter, V2_DB_PARAMETER_IDX_M,
+			       V2_DB_PARAMETER_IDX_S,
+			       qp->sq.head & ((qp->sq.wqe_cnt << 1) - 1));
+		roce_set_field(sq_db.parameter, V2_DB_PARAMETER_SL_M,
+			       V2_DB_PARAMETER_SL_S, qp->sl);
+
+		hns_roce_write64(hr_dev, (__le32 *)&sq_db, qp->sq.db_reg_l);
+	}
+}
 
 static int hns_roce_v2_post_send(struct ib_qp *ibqp,
 				 const struct ib_send_wr *wr,
@@ -237,40 +287,30 @@
 	struct hns_roce_qp *qp = to_hr_qp(ibqp);
 	struct hns_roce_wqe_frmr_seg *fseg;
 	struct device *dev = hr_dev->dev;
-	struct hns_roce_v2_db sq_db;
-	struct ib_qp_attr attr;
-	unsigned int sge_ind;
 	unsigned int owner_bit;
+	unsigned int sge_idx;
+	unsigned int wqe_idx;
 	unsigned long flags;
-	unsigned int ind;
+	int valid_num_sge;
 	void *wqe = NULL;
 	bool loopback;
-	int attr_mask;
 	u32 tmp_len;
-	int ret = 0;
 	u32 hr_op;
 	u8 *smac;
 	int nreq;
+	int ret;
 	int i;
 
-	if (unlikely(ibqp->qp_type != IB_QPT_RC &&
-		     ibqp->qp_type != IB_QPT_GSI &&
-		     ibqp->qp_type != IB_QPT_UD)) {
-		dev_err(dev, "Not supported QP(0x%x)type!\n", ibqp->qp_type);
-		*bad_wr = wr;
-		return -EOPNOTSUPP;
-	}
+	spin_lock_irqsave(&qp->sq.lock, flags);
 
-	if (unlikely(qp->state == IB_QPS_RESET || qp->state == IB_QPS_INIT ||
-		     qp->state == IB_QPS_RTR)) {
-		dev_err(dev, "Post WQE fail, QP state %d err!\n", qp->state);
+	ret = check_send_valid(hr_dev, qp);
+	if (ret) {
 		*bad_wr = wr;
-		return -EINVAL;
+		nreq = 0;
+		goto out;
 	}
 
-	spin_lock_irqsave(&qp->sq.lock, flags);
-	ind = qp->sq_next_wqe;
-	sge_ind = qp->next_sge;
+	sge_idx = qp->next_sge;
 
 	for (nreq = 0; wr; ++nreq, wr = wr->next) {
 		if (hns_roce_wq_overflow(&qp->sq, nreq, qp->ibqp.send_cq)) {
@@ -279,6 +319,8 @@
 			goto out;
 		}
 
+		wqe_idx = (qp->sq.head + nreq) & (qp->sq.wqe_cnt - 1);
+
 		if (unlikely(wr->num_sge > qp->sq.max_gs)) {
 			dev_err(dev, "num_sge=%d > qp->sq.max_gs=%d\n",
 				wr->num_sge, qp->sq.max_gs);
@@ -287,14 +329,20 @@
 			goto out;
 		}
 
-		wqe = get_send_wqe(qp, ind & (qp->sq.wqe_cnt - 1));
-		qp->sq.wrid[(qp->sq.head + nreq) & (qp->sq.wqe_cnt - 1)] =
-								      wr->wr_id;
-
+		wqe = get_send_wqe(qp, wqe_idx);
+		qp->sq.wrid[wqe_idx] = wr->wr_id;
 		owner_bit =
 		       ~(((qp->sq.head + nreq) >> ilog2(qp->sq.wqe_cnt)) & 0x1);
+		valid_num_sge = 0;
 		tmp_len = 0;
 
+		for (i = 0; i < wr->num_sge; i++) {
+			if (likely(wr->sg_list[i].length)) {
+				tmp_len += wr->sg_list[i].length;
+				valid_num_sge++;
+			}
+		}
+
 		/* Corresponding to the QP type, wqe process separately */
 		if (ibqp->qp_type == IB_QPT_GSI) {
 			ud_sq_wqe = wqe;
@@ -330,9 +378,6 @@
 				       V2_UD_SEND_WQE_BYTE_4_OPCODE_S,
 				       HNS_ROCE_V2_WQE_OP_SEND);
 
-			for (i = 0; i < wr->num_sge; i++)
-				tmp_len += wr->sg_list[i].length;
-
 			ud_sq_wqe->msg_len =
 			 cpu_to_le32(le32_to_cpu(ud_sq_wqe->msg_len) + tmp_len);
 
@@ -368,12 +413,12 @@
 			roce_set_field(ud_sq_wqe->byte_16,
 				       V2_UD_SEND_WQE_BYTE_16_SGE_NUM_M,
 				       V2_UD_SEND_WQE_BYTE_16_SGE_NUM_S,
-				       wr->num_sge);
+				       valid_num_sge);
 
 			roce_set_field(ud_sq_wqe->byte_20,
 				     V2_UD_SEND_WQE_BYTE_20_MSG_START_SGE_IDX_M,
 				     V2_UD_SEND_WQE_BYTE_20_MSG_START_SGE_IDX_S,
-				     sge_ind & (qp->sge.sge_cnt - 1));
+				     sge_idx & (qp->sge.sge_cnt - 1));
 
 			roce_set_field(ud_sq_wqe->byte_24,
 				       V2_UD_SEND_WQE_BYTE_24_UDPSPN_M,
@@ -389,7 +434,7 @@
 			roce_set_field(ud_sq_wqe->byte_36,
 				       V2_UD_SEND_WQE_BYTE_36_VLAN_M,
 				       V2_UD_SEND_WQE_BYTE_36_VLAN_S,
-				       le16_to_cpu(ah->av.vlan));
+				       ah->av.vlan_id);
 			roce_set_field(ud_sq_wqe->byte_36,
 				       V2_UD_SEND_WQE_BYTE_36_HOPLIMIT_M,
 				       V2_UD_SEND_WQE_BYTE_36_HOPLIMIT_S,
@@ -423,13 +468,10 @@
 			memcpy(&ud_sq_wqe->dgid[0], &ah->av.dgid[0],
 			       GID_LEN_V2);
 
-			set_extend_sge(qp, wr, &sge_ind);
-			ind++;
+			set_extend_sge(qp, wr, &sge_idx, valid_num_sge);
 		} else if (ibqp->qp_type == IB_QPT_RC) {
 			rc_sq_wqe = wqe;
 			memset(rc_sq_wqe, 0, sizeof(*rc_sq_wqe));
-			for (i = 0; i < wr->num_sge; i++)
-				tmp_len += wr->sg_list[i].length;
 
 			rc_sq_wqe->msg_len =
 			 cpu_to_le32(le32_to_cpu(rc_sq_wqe->msg_len) + tmp_len);
@@ -550,15 +592,14 @@
 				roce_set_field(rc_sq_wqe->byte_16,
 					       V2_RC_SEND_WQE_BYTE_16_SGE_NUM_M,
 					       V2_RC_SEND_WQE_BYTE_16_SGE_NUM_S,
-					       wr->num_sge);
+					       valid_num_sge);
 			} else if (wr->opcode != IB_WR_REG_MR) {
 				ret = set_rwqe_data_seg(ibqp, wr, rc_sq_wqe,
-							wqe, &sge_ind, bad_wr);
+							wqe, &sge_idx,
+							valid_num_sge, bad_wr);
 				if (ret)
 					goto out;
 			}
-
-			ind++;
 		} else {
 			dev_err(dev, "Illegal qp_type(0x%x)\n", ibqp->qp_type);
 			spin_unlock_irqrestore(&qp->sq.lock, flags);
@@ -570,39 +611,10 @@
 out:
 	if (likely(nreq)) {
 		qp->sq.head += nreq;
+		qp->next_sge = sge_idx;
 		/* Memory barrier */
 		wmb();
-
-		sq_db.byte_4 = 0;
-		sq_db.parameter = 0;
-
-		roce_set_field(sq_db.byte_4, V2_DB_BYTE_4_TAG_M,
-			       V2_DB_BYTE_4_TAG_S, qp->doorbell_qpn);
-		roce_set_field(sq_db.byte_4, V2_DB_BYTE_4_CMD_M,
-			       V2_DB_BYTE_4_CMD_S, HNS_ROCE_V2_SQ_DB);
-		roce_set_field(sq_db.parameter, V2_DB_PARAMETER_IDX_M,
-			       V2_DB_PARAMETER_IDX_S,
-			       qp->sq.head & ((qp->sq.wqe_cnt << 1) - 1));
-		roce_set_field(sq_db.parameter, V2_DB_PARAMETER_SL_M,
-			       V2_DB_PARAMETER_SL_S, qp->sl);
-
-		hns_roce_write64(hr_dev, (__le32 *)&sq_db, qp->sq.db_reg_l);
-
-		qp->sq_next_wqe = ind;
-		qp->next_sge = sge_ind;
-
-		if (qp->state == IB_QPS_ERR) {
-			attr_mask = IB_QP_STATE;
-			attr.qp_state = IB_QPS_ERR;
-
-			ret = hns_roce_v2_modify_qp(&qp->ibqp, &attr, attr_mask,
-						    qp->state, IB_QPS_ERR);
-			if (ret) {
-				spin_unlock_irqrestore(&qp->sq.lock, flags);
-				*bad_wr = wr;
-				return ret;
-			}
-		}
+		update_sq_db(hr_dev, qp);
 	}
 
 	spin_unlock_irqrestore(&qp->sq.lock, flags);
@@ -610,6 +622,17 @@
 	return ret;
 }
 
+static int check_recv_valid(struct hns_roce_dev *hr_dev,
+			    struct hns_roce_qp *hr_qp)
+{
+	if (unlikely(hr_dev->state >= HNS_ROCE_DEVICE_STATE_RST_DOWN))
+		return -EIO;
+	else if (hr_qp->state == IB_QPS_RESET)
+		return -EINVAL;
+
+	return 0;
+}
+
 static int hns_roce_v2_post_recv(struct ib_qp *ibqp,
 				 const struct ib_recv_wr *wr,
 				 const struct ib_recv_wr **bad_wr)
@@ -619,22 +642,20 @@
 	struct hns_roce_v2_wqe_data_seg *dseg;
 	struct hns_roce_rinl_sge *sge_list;
 	struct device *dev = hr_dev->dev;
-	struct ib_qp_attr attr;
 	unsigned long flags;
 	void *wqe = NULL;
-	int attr_mask;
-	int ret = 0;
+	u32 wqe_idx;
 	int nreq;
-	int ind;
+	int ret;
 	int i;
 
 	spin_lock_irqsave(&hr_qp->rq.lock, flags);
-	ind = hr_qp->rq.head & (hr_qp->rq.wqe_cnt - 1);
 
-	if (hr_qp->state == IB_QPS_RESET) {
-		spin_unlock_irqrestore(&hr_qp->rq.lock, flags);
+	ret = check_recv_valid(hr_dev, hr_qp);
+	if (ret) {
 		*bad_wr = wr;
-		return -EINVAL;
+		nreq = 0;
+		goto out;
 	}
 
 	for (nreq = 0; wr; ++nreq, wr = wr->next) {
@@ -645,6 +666,8 @@
 			goto out;
 		}
 
+		wqe_idx = (hr_qp->rq.head + nreq) & (hr_qp->rq.wqe_cnt - 1);
+
 		if (unlikely(wr->num_sge > hr_qp->rq.max_gs)) {
 			dev_err(dev, "rq:num_sge=%d > qp->sq.max_gs=%d\n",
 				wr->num_sge, hr_qp->rq.max_gs);
@@ -653,7 +676,7 @@
 			goto out;
 		}
 
-		wqe = get_recv_wqe(hr_qp, ind);
+		wqe = get_recv_wqe(hr_qp, wqe_idx);
 		dseg = (struct hns_roce_v2_wqe_data_seg *)wqe;
 		for (i = 0; i < wr->num_sge; i++) {
 			if (!wr->sg_list[i].length)
@@ -669,8 +692,8 @@
 
 		/* rq support inline data */
 		if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_RQ_INLINE) {
-			sge_list = hr_qp->rq_inl_buf.wqe_list[ind].sg_list;
-			hr_qp->rq_inl_buf.wqe_list[ind].sge_cnt =
+			sge_list = hr_qp->rq_inl_buf.wqe_list[wqe_idx].sg_list;
+			hr_qp->rq_inl_buf.wqe_list[wqe_idx].sge_cnt =
 							       (u32)wr->num_sge;
 			for (i = 0; i < wr->num_sge; i++) {
 				sge_list[i].addr =
@@ -679,9 +702,7 @@
 			}
 		}
 
-		hr_qp->rq.wrid[ind] = wr->wr_id;
-
-		ind = (ind + 1) & (hr_qp->rq.wqe_cnt - 1);
+		hr_qp->rq.wrid[wqe_idx] = wr->wr_id;
 	}
 
 out:
@@ -690,20 +711,21 @@
 		/* Memory barrier */
 		wmb();
 
-		*hr_qp->rdb.db_record = hr_qp->rq.head & 0xffff;
-
+		/*
+		 * Hip08 hardware cannot flush the WQEs in RQ if the QP state
+		 * gets into errored mode. Hence, as a workaround to this
+		 * hardware limitation, driver needs to assist in flushing. But
+		 * the flushing operation uses mailbox to convey the QP state to
+		 * the hardware and which can sleep due to the mutex protection
+		 * around the mailbox calls. Hence, use the deferred flush for
+		 * now.
+		 */
 		if (hr_qp->state == IB_QPS_ERR) {
-			attr_mask = IB_QP_STATE;
-			attr.qp_state = IB_QPS_ERR;
-
-			ret = hns_roce_v2_modify_qp(&hr_qp->ibqp, &attr,
-						    attr_mask, hr_qp->state,
-						    IB_QPS_ERR);
-			if (ret) {
-				spin_unlock_irqrestore(&hr_qp->rq.lock, flags);
-				*bad_wr = wr;
-				return ret;
-			}
+			if (!test_and_set_bit(HNS_ROCE_FLUSH_FLAG,
+					      &hr_qp->flush_flag))
+				init_flush_work(hr_dev, hr_qp);
+		} else {
+			*hr_qp->rdb.db_record = hr_qp->rq.head & 0xffff;
 		}
 	}
 	spin_unlock_irqrestore(&hr_qp->rq.lock, flags);
@@ -1006,7 +1028,7 @@
 	u32 timeout = 0;
 	int handle = 0;
 	u16 desc_ret;
-	int ret = 0;
+	int ret;
 	int ntc;
 
 	spin_lock_bh(&csq->lock);
@@ -1051,15 +1073,14 @@
 	if (hns_roce_cmq_csq_done(hr_dev)) {
 		complete = true;
 		handle = 0;
+		ret = 0;
 		while (handle < num) {
 			/* get the result of hardware write back */
 			desc_to_use = &csq->desc[ntc];
 			desc[handle] = *desc_to_use;
 			dev_dbg(hr_dev->dev, "Get cmq desc:\n");
 			desc_ret = le16_to_cpu(desc[handle].retval);
-			if (desc_ret == CMD_EXEC_SUCCESS)
-				ret = 0;
-			else
+			if (unlikely(desc_ret != CMD_EXEC_SUCCESS))
 				ret = -EIO;
 			priv->cmq.last_status = desc_ret;
 			ntc++;
@@ -1254,7 +1275,6 @@
 	}
 
 out:
-	dev_err(hr_dev->dev, "Func clear fail.\n");
 	hns_roce_func_clr_rst_prc(hr_dev, ret, fclr_write_fail_flag);
 }
 
@@ -1346,40 +1366,31 @@
 static int hns_roce_query_pf_timer_resource(struct hns_roce_dev *hr_dev)
 {
 	struct hns_roce_pf_timer_res_a *req_a;
-	struct hns_roce_cmq_desc desc[2];
-	int ret, i;
-
-	for (i = 0; i < 2; i++) {
-		hns_roce_cmq_setup_basic_desc(&desc[i],
-					      HNS_ROCE_OPC_QUERY_PF_TIMER_RES,
-					      true);
+	struct hns_roce_cmq_desc desc;
+	int ret;
 
-		if (i == 0)
-			desc[i].flag |= cpu_to_le16(HNS_ROCE_CMD_FLAG_NEXT);
-		else
-			desc[i].flag &= ~cpu_to_le16(HNS_ROCE_CMD_FLAG_NEXT);
-	}
+	hns_roce_cmq_setup_basic_desc(&desc, HNS_ROCE_OPC_QUERY_PF_TIMER_RES,
+				      true);
 
-	ret = hns_roce_cmq_send(hr_dev, desc, 2);
+	ret = hns_roce_cmq_send(hr_dev, &desc, 1);
 	if (ret)
 		return ret;
 
-	req_a = (struct hns_roce_pf_timer_res_a *)desc[0].data;
+	req_a = (struct hns_roce_pf_timer_res_a *)desc.data;
 
 	hr_dev->caps.qpc_timer_bt_num =
-				roce_get_field(req_a->qpc_timer_bt_idx_num,
-					PF_RES_DATA_1_PF_QPC_TIMER_BT_NUM_M,
-					PF_RES_DATA_1_PF_QPC_TIMER_BT_NUM_S);
+		roce_get_field(req_a->qpc_timer_bt_idx_num,
+			       PF_RES_DATA_1_PF_QPC_TIMER_BT_NUM_M,
+			       PF_RES_DATA_1_PF_QPC_TIMER_BT_NUM_S);
 	hr_dev->caps.cqc_timer_bt_num =
-				roce_get_field(req_a->cqc_timer_bt_idx_num,
-					PF_RES_DATA_2_PF_CQC_TIMER_BT_NUM_M,
-					PF_RES_DATA_2_PF_CQC_TIMER_BT_NUM_S);
+		roce_get_field(req_a->cqc_timer_bt_idx_num,
+			       PF_RES_DATA_2_PF_CQC_TIMER_BT_NUM_M,
+			       PF_RES_DATA_2_PF_CQC_TIMER_BT_NUM_S);
 
 	return 0;
 }
 
-static int hns_roce_set_vf_switch_param(struct hns_roce_dev *hr_dev,
-						  int vf_id)
+static int hns_roce_set_vf_switch_param(struct hns_roce_dev *hr_dev, int vf_id)
 {
 	struct hns_roce_cmq_desc desc;
 	struct hns_roce_vf_switch *swt;
@@ -1388,13 +1399,12 @@
 	swt = (struct hns_roce_vf_switch *)desc.data;
 	hns_roce_cmq_setup_basic_desc(&desc, HNS_SWITCH_PARAMETER_CFG, true);
 	swt->rocee_sel |= cpu_to_le32(HNS_ICL_SWITCH_CMD_ROCEE_SEL);
-	roce_set_field(swt->fun_id,
-			VF_SWITCH_DATA_FUN_ID_VF_ID_M,
-			VF_SWITCH_DATA_FUN_ID_VF_ID_S,
-			vf_id);
+	roce_set_field(swt->fun_id, VF_SWITCH_DATA_FUN_ID_VF_ID_M,
+		       VF_SWITCH_DATA_FUN_ID_VF_ID_S, vf_id);
 	ret = hns_roce_cmq_send(hr_dev, &desc, 1);
 	if (ret)
 		return ret;
+
 	desc.flag =
 		cpu_to_le16(HNS_ROCE_CMD_FLAG_NO_INTR | HNS_ROCE_CMD_FLAG_IN);
 	desc.flag &= cpu_to_le16(~HNS_ROCE_CMD_FLAG_WR);
@@ -1574,69 +1584,9 @@
 	return hns_roce_cmq_send(hr_dev, &desc, 1);
 }
 
-static int hns_roce_v2_profile(struct hns_roce_dev *hr_dev)
+static void set_default_caps(struct hns_roce_dev *hr_dev)
 {
 	struct hns_roce_caps *caps = &hr_dev->caps;
-	int ret;
-
-	ret = hns_roce_cmq_query_hw_info(hr_dev);
-	if (ret) {
-		dev_err(hr_dev->dev, "Query hardware version fail, ret = %d.\n",
-			ret);
-		return ret;
-	}
-
-	ret = hns_roce_query_fw_ver(hr_dev);
-	if (ret) {
-		dev_err(hr_dev->dev, "Query firmware version fail, ret = %d.\n",
-			ret);
-		return ret;
-	}
-
-	ret = hns_roce_config_global_param(hr_dev);
-	if (ret) {
-		dev_err(hr_dev->dev, "Configure global param fail, ret = %d.\n",
-			ret);
-		return ret;
-	}
-
-	/* Get pf resource owned by every pf */
-	ret = hns_roce_query_pf_resource(hr_dev);
-	if (ret) {
-		dev_err(hr_dev->dev, "Query pf resource fail, ret = %d.\n",
-			ret);
-		return ret;
-	}
-
-	if (hr_dev->pci_dev->revision == 0x21) {
-		ret = hns_roce_query_pf_timer_resource(hr_dev);
-		if (ret) {
-			dev_err(hr_dev->dev,
-				"Query pf timer resource fail, ret = %d.\n",
-				ret);
-			return ret;
-		}
-	}
-
-	ret = hns_roce_alloc_vf_resource(hr_dev);
-	if (ret) {
-		dev_err(hr_dev->dev, "Allocate vf resource fail, ret = %d.\n",
-			ret);
-		return ret;
-	}
-
-	if (hr_dev->pci_dev->revision == 0x21) {
-		ret = hns_roce_set_vf_switch_param(hr_dev, 0);
-		if (ret) {
-			dev_err(hr_dev->dev,
-				"Set function switch param fail, ret = %d.\n",
-				ret);
-			return ret;
-		}
-	}
-
-	hr_dev->vendor_part_id = hr_dev->pci_dev->device;
-	hr_dev->sys_image_guid = be64_to_cpu(hr_dev->ib_dev.node_guid);
 
 	caps->num_qps		= HNS_ROCE_V2_MAX_QP_NUM;
 	caps->max_wqes		= HNS_ROCE_V2_MAX_WQE_NUM;
@@ -1644,17 +1594,15 @@
 	caps->num_srqs		= HNS_ROCE_V2_MAX_SRQ_NUM;
 	caps->min_cqes		= HNS_ROCE_MIN_CQE_NUM;
 	caps->max_cqes		= HNS_ROCE_V2_MAX_CQE_NUM;
-	caps->max_srqwqes	= HNS_ROCE_V2_MAX_SRQWQE_NUM;
 	caps->max_sq_sg		= HNS_ROCE_V2_MAX_SQ_SGE_NUM;
 	caps->max_extend_sg	= HNS_ROCE_V2_MAX_EXTEND_SGE_NUM;
 	caps->max_rq_sg		= HNS_ROCE_V2_MAX_RQ_SGE_NUM;
 	caps->max_sq_inline	= HNS_ROCE_V2_MAX_SQ_INLINE;
-	caps->max_srq_sg	= HNS_ROCE_V2_MAX_SRQ_SGE_NUM;
 	caps->num_uars		= HNS_ROCE_V2_UAR_NUM;
 	caps->phy_num_uars	= HNS_ROCE_V2_PHY_UAR_NUM;
 	caps->num_aeq_vectors	= HNS_ROCE_V2_AEQE_VEC_NUM;
 	caps->num_comp_vectors	= HNS_ROCE_V2_COMP_VEC_NUM;
-	caps->num_other_vectors	= HNS_ROCE_V2_ABNORMAL_VEC_NUM;
+	caps->num_other_vectors = HNS_ROCE_V2_ABNORMAL_VEC_NUM;
 	caps->num_mtpts		= HNS_ROCE_V2_MAX_MTPT_NUM;
 	caps->num_mtt_segs	= HNS_ROCE_V2_MAX_MTT_SEGS;
 	caps->num_cqe_segs	= HNS_ROCE_V2_MAX_CQE_SEGS;
@@ -1668,12 +1616,12 @@
 	caps->max_srq_desc_sz	= HNS_ROCE_V2_MAX_SRQ_DESC_SZ;
 	caps->qpc_entry_sz	= HNS_ROCE_V2_QPC_ENTRY_SZ;
 	caps->irrl_entry_sz	= HNS_ROCE_V2_IRRL_ENTRY_SZ;
-	caps->trrl_entry_sz	= HNS_ROCE_V2_TRRL_ENTRY_SZ;
+	caps->trrl_entry_sz	= HNS_ROCE_V2_EXT_ATOMIC_TRRL_ENTRY_SZ;
 	caps->cqc_entry_sz	= HNS_ROCE_V2_CQC_ENTRY_SZ;
 	caps->srqc_entry_sz	= HNS_ROCE_V2_SRQC_ENTRY_SZ;
 	caps->mtpt_entry_sz	= HNS_ROCE_V2_MTPT_ENTRY_SZ;
 	caps->mtt_entry_sz	= HNS_ROCE_V2_MTT_ENTRY_SZ;
-	caps->idx_entry_sz	= 4;
+	caps->idx_entry_sz	= HNS_ROCE_V2_IDX_ENTRY_SZ;
 	caps->cq_entry_sz	= HNS_ROCE_V2_CQE_ENTRY_SIZE;
 	caps->page_size_cap	= HNS_ROCE_V2_PAGE_SIZE_SUPPORTED;
 	caps->reserved_lkey	= 0;
@@ -1696,16 +1644,13 @@
 	caps->mpt_ba_pg_sz	= 0;
 	caps->mpt_buf_pg_sz	= 0;
 	caps->mpt_hop_num	= HNS_ROCE_CONTEXT_HOP_NUM;
-	caps->pbl_ba_pg_sz	= 2;
-	caps->pbl_buf_pg_sz	= 0;
-	caps->pbl_hop_num	= HNS_ROCE_PBL_HOP_NUM;
 	caps->mtt_ba_pg_sz	= 0;
 	caps->mtt_buf_pg_sz	= 0;
 	caps->mtt_hop_num	= HNS_ROCE_MTT_HOP_NUM;
-	caps->wqe_sq_hop_num	= 2;
-	caps->wqe_sge_hop_num	= 1;
-	caps->wqe_rq_hop_num	= 2;
-	caps->cqe_ba_pg_sz	= 6;
+	caps->wqe_sq_hop_num	= HNS_ROCE_SQWQE_HOP_NUM;
+	caps->wqe_sge_hop_num	= HNS_ROCE_EXT_SGE_HOP_NUM;
+	caps->wqe_rq_hop_num	= HNS_ROCE_RQWQE_HOP_NUM;
+	caps->cqe_ba_pg_sz	= HNS_ROCE_BA_PG_SZ_SUPPORTED_256K;
 	caps->cqe_buf_pg_sz	= 0;
 	caps->cqe_hop_num	= HNS_ROCE_CQE_HOP_NUM;
 	caps->srqwqe_ba_pg_sz	= 0;
@@ -1714,10 +1659,6 @@
 	caps->idx_ba_pg_sz	= 0;
 	caps->idx_buf_pg_sz	= 0;
 	caps->idx_hop_num	= HNS_ROCE_IDX_HOP_NUM;
-	caps->eqe_ba_pg_sz	= 0;
-	caps->eqe_buf_pg_sz	= 0;
-	caps->eqe_hop_num	= HNS_ROCE_EQE_HOP_NUM;
-	caps->tsq_buf_pg_sz	= 0;
 	caps->chunk_sz		= HNS_ROCE_V2_TABLE_CHUNK_SIZE;
 
 	caps->flags		= HNS_ROCE_CAP_FLAG_REREG_MR |
@@ -1726,24 +1667,19 @@
 				  HNS_ROCE_CAP_FLAG_RECORD_DB |
 				  HNS_ROCE_CAP_FLAG_SQ_RECORD_DB;
 
-	if (hr_dev->pci_dev->revision == 0x21)
-		caps->flags |= HNS_ROCE_CAP_FLAG_MW |
-			       HNS_ROCE_CAP_FLAG_FRMR;
-
 	caps->pkey_table_len[0] = 1;
-	caps->gid_table_len[0] = HNS_ROCE_V2_GID_INDEX_NUM;
+	caps->gid_table_len[0]	= HNS_ROCE_V2_GID_INDEX_NUM;
 	caps->ceqe_depth	= HNS_ROCE_V2_COMP_EQE_NUM;
 	caps->aeqe_depth	= HNS_ROCE_V2_ASYNC_EQE_NUM;
 	caps->local_ca_ack_delay = 0;
 	caps->max_mtu = IB_MTU_4096;
 
-	caps->max_srqs		= HNS_ROCE_V2_MAX_SRQ;
 	caps->max_srq_wrs	= HNS_ROCE_V2_MAX_SRQ_WR;
 	caps->max_srq_sges	= HNS_ROCE_V2_MAX_SRQ_SGE;
 
-	if (hr_dev->pci_dev->revision == 0x21) {
-		caps->flags |= HNS_ROCE_CAP_FLAG_ATOMIC |
-			       HNS_ROCE_CAP_FLAG_SRQ |
+	if (hr_dev->pci_dev->revision >= PCI_REVISION_ID_HIP08_B) {
+		caps->flags |= HNS_ROCE_CAP_FLAG_ATOMIC | HNS_ROCE_CAP_FLAG_MW |
+			       HNS_ROCE_CAP_FLAG_SRQ | HNS_ROCE_CAP_FLAG_FRMR |
 			       HNS_ROCE_CAP_FLAG_QP_FLOW_CTRL;
 
 		caps->num_qpc_timer	  = HNS_ROCE_V2_MAX_QPC_TIMER_NUM;
@@ -1757,12 +1693,343 @@
 		caps->cqc_timer_buf_pg_sz = 0;
 		caps->cqc_timer_hop_num   = HNS_ROCE_HOP_NUM_0;
 
-		caps->sccc_entry_sz	= HNS_ROCE_V2_SCCC_ENTRY_SZ;
-		caps->sccc_ba_pg_sz	= 0;
-		caps->sccc_buf_pg_sz    = 0;
-		caps->sccc_hop_num	= HNS_ROCE_SCCC_HOP_NUM;
+		caps->sccc_entry_sz	  = HNS_ROCE_V2_SCCC_ENTRY_SZ;
+		caps->sccc_ba_pg_sz	  = 0;
+		caps->sccc_buf_pg_sz	  = 0;
+		caps->sccc_hop_num	  = HNS_ROCE_SCCC_HOP_NUM;
+	}
+}
+
+static void calc_pg_sz(int obj_num, int obj_size, int hop_num, int ctx_bt_num,
+		       int *buf_page_size, int *bt_page_size, u32 hem_type)
+{
+	u64 obj_per_chunk;
+	int bt_chunk_size = 1 << PAGE_SHIFT;
+	int buf_chunk_size = 1 << PAGE_SHIFT;
+	int obj_per_chunk_default = buf_chunk_size / obj_size;
+
+	*buf_page_size = 0;
+	*bt_page_size = 0;
+
+	switch (hop_num) {
+	case 3:
+		obj_per_chunk = ctx_bt_num * (bt_chunk_size / BA_BYTE_LEN) *
+				(bt_chunk_size / BA_BYTE_LEN) *
+				(bt_chunk_size / BA_BYTE_LEN) *
+				 obj_per_chunk_default;
+		break;
+	case 2:
+		obj_per_chunk = ctx_bt_num * (bt_chunk_size / BA_BYTE_LEN) *
+				(bt_chunk_size / BA_BYTE_LEN) *
+				 obj_per_chunk_default;
+		break;
+	case 1:
+		obj_per_chunk = ctx_bt_num * (bt_chunk_size / BA_BYTE_LEN) *
+				obj_per_chunk_default;
+		break;
+	case HNS_ROCE_HOP_NUM_0:
+		obj_per_chunk = ctx_bt_num * obj_per_chunk_default;
+		break;
+	default:
+		pr_err("Table %d not support hop_num = %d!\n", hem_type,
+			hop_num);
+		return;
+	}
+
+	if (hem_type >= HEM_TYPE_MTT)
+		*bt_page_size = ilog2(DIV_ROUND_UP(obj_num, obj_per_chunk));
+	else
+		*buf_page_size = ilog2(DIV_ROUND_UP(obj_num, obj_per_chunk));
+}
+
+static int hns_roce_query_pf_caps(struct hns_roce_dev *hr_dev)
+{
+	struct hns_roce_cmq_desc desc[HNS_ROCE_QUERY_PF_CAPS_CMD_NUM];
+	struct hns_roce_caps *caps = &hr_dev->caps;
+	struct hns_roce_query_pf_caps_a *resp_a;
+	struct hns_roce_query_pf_caps_b *resp_b;
+	struct hns_roce_query_pf_caps_c *resp_c;
+	struct hns_roce_query_pf_caps_d *resp_d;
+	struct hns_roce_query_pf_caps_e *resp_e;
+	int ctx_hop_num;
+	int pbl_hop_num;
+	int ret;
+	int i;
+
+	for (i = 0; i < HNS_ROCE_QUERY_PF_CAPS_CMD_NUM; i++) {
+		hns_roce_cmq_setup_basic_desc(&desc[i],
+					      HNS_ROCE_OPC_QUERY_PF_CAPS_NUM,
+					      true);
+		if (i < (HNS_ROCE_QUERY_PF_CAPS_CMD_NUM - 1))
+			desc[i].flag |= cpu_to_le16(HNS_ROCE_CMD_FLAG_NEXT);
+		else
+			desc[i].flag &= ~cpu_to_le16(HNS_ROCE_CMD_FLAG_NEXT);
+	}
+
+	ret = hns_roce_cmq_send(hr_dev, desc, HNS_ROCE_QUERY_PF_CAPS_CMD_NUM);
+	if (ret)
+		return ret;
+
+	resp_a = (struct hns_roce_query_pf_caps_a *)desc[0].data;
+	resp_b = (struct hns_roce_query_pf_caps_b *)desc[1].data;
+	resp_c = (struct hns_roce_query_pf_caps_c *)desc[2].data;
+	resp_d = (struct hns_roce_query_pf_caps_d *)desc[3].data;
+	resp_e = (struct hns_roce_query_pf_caps_e *)desc[4].data;
+
+	caps->local_ca_ack_delay     = resp_a->local_ca_ack_delay;
+	caps->max_sq_sg		     = le16_to_cpu(resp_a->max_sq_sg);
+	caps->max_sq_inline	     = le16_to_cpu(resp_a->max_sq_inline);
+	caps->max_rq_sg		     = le16_to_cpu(resp_a->max_rq_sg);
+	caps->max_extend_sg	     = le32_to_cpu(resp_a->max_extend_sg);
+	caps->num_qpc_timer	     = le16_to_cpu(resp_a->num_qpc_timer);
+	caps->num_cqc_timer	     = le16_to_cpu(resp_a->num_cqc_timer);
+	caps->max_srq_sges	     = le16_to_cpu(resp_a->max_srq_sges);
+	caps->num_aeq_vectors	     = resp_a->num_aeq_vectors;
+	caps->num_other_vectors	     = resp_a->num_other_vectors;
+	caps->max_sq_desc_sz	     = resp_a->max_sq_desc_sz;
+	caps->max_rq_desc_sz	     = resp_a->max_rq_desc_sz;
+	caps->max_srq_desc_sz	     = resp_a->max_srq_desc_sz;
+	caps->cq_entry_sz	     = resp_a->cq_entry_sz;
+
+	caps->mtpt_entry_sz	     = resp_b->mtpt_entry_sz;
+	caps->irrl_entry_sz	     = resp_b->irrl_entry_sz;
+	caps->trrl_entry_sz	     = resp_b->trrl_entry_sz;
+	caps->cqc_entry_sz	     = resp_b->cqc_entry_sz;
+	caps->srqc_entry_sz	     = resp_b->srqc_entry_sz;
+	caps->idx_entry_sz	     = resp_b->idx_entry_sz;
+	caps->sccc_entry_sz	     = resp_b->scc_ctx_entry_sz;
+	caps->max_mtu		     = resp_b->max_mtu;
+	caps->qpc_entry_sz	     = le16_to_cpu(resp_b->qpc_entry_sz);
+	caps->min_cqes		     = resp_b->min_cqes;
+	caps->min_wqes		     = resp_b->min_wqes;
+	caps->page_size_cap	     = le32_to_cpu(resp_b->page_size_cap);
+	caps->pkey_table_len[0]	     = resp_b->pkey_table_len;
+	caps->phy_num_uars	     = resp_b->phy_num_uars;
+	ctx_hop_num		     = resp_b->ctx_hop_num;
+	pbl_hop_num		     = resp_b->pbl_hop_num;
+
+	caps->num_pds = 1 << roce_get_field(resp_c->cap_flags_num_pds,
+					    V2_QUERY_PF_CAPS_C_NUM_PDS_M,
+					    V2_QUERY_PF_CAPS_C_NUM_PDS_S);
+	caps->flags = roce_get_field(resp_c->cap_flags_num_pds,
+				     V2_QUERY_PF_CAPS_C_CAP_FLAGS_M,
+				     V2_QUERY_PF_CAPS_C_CAP_FLAGS_S);
+	caps->num_cqs = 1 << roce_get_field(resp_c->max_gid_num_cqs,
+					    V2_QUERY_PF_CAPS_C_NUM_CQS_M,
+					    V2_QUERY_PF_CAPS_C_NUM_CQS_S);
+	caps->gid_table_len[0] = roce_get_field(resp_c->max_gid_num_cqs,
+						V2_QUERY_PF_CAPS_C_MAX_GID_M,
+						V2_QUERY_PF_CAPS_C_MAX_GID_S);
+	caps->max_cqes = 1 << roce_get_field(resp_c->cq_depth,
+					     V2_QUERY_PF_CAPS_C_CQ_DEPTH_M,
+					     V2_QUERY_PF_CAPS_C_CQ_DEPTH_S);
+	caps->num_mtpts = 1 << roce_get_field(resp_c->num_mrws,
+					      V2_QUERY_PF_CAPS_C_NUM_MRWS_M,
+					      V2_QUERY_PF_CAPS_C_NUM_MRWS_S);
+	caps->num_qps = 1 << roce_get_field(resp_c->ord_num_qps,
+					    V2_QUERY_PF_CAPS_C_NUM_QPS_M,
+					    V2_QUERY_PF_CAPS_C_NUM_QPS_S);
+	caps->max_qp_init_rdma = roce_get_field(resp_c->ord_num_qps,
+						V2_QUERY_PF_CAPS_C_MAX_ORD_M,
+						V2_QUERY_PF_CAPS_C_MAX_ORD_S);
+	caps->max_qp_dest_rdma = caps->max_qp_init_rdma;
+	caps->max_wqes = 1 << le16_to_cpu(resp_c->sq_depth);
+	caps->num_srqs = 1 << roce_get_field(resp_d->wq_hop_num_max_srqs,
+					     V2_QUERY_PF_CAPS_D_NUM_SRQS_M,
+					     V2_QUERY_PF_CAPS_D_NUM_SRQS_S);
+	caps->max_srq_wrs = 1 << le16_to_cpu(resp_d->srq_depth);
+	caps->ceqe_depth = 1 << roce_get_field(resp_d->num_ceqs_ceq_depth,
+					       V2_QUERY_PF_CAPS_D_CEQ_DEPTH_M,
+					       V2_QUERY_PF_CAPS_D_CEQ_DEPTH_S);
+	caps->num_comp_vectors = roce_get_field(resp_d->num_ceqs_ceq_depth,
+						V2_QUERY_PF_CAPS_D_NUM_CEQS_M,
+						V2_QUERY_PF_CAPS_D_NUM_CEQS_S);
+	caps->aeqe_depth = 1 << roce_get_field(resp_d->arm_st_aeq_depth,
+					       V2_QUERY_PF_CAPS_D_AEQ_DEPTH_M,
+					       V2_QUERY_PF_CAPS_D_AEQ_DEPTH_S);
+	caps->default_aeq_arm_st = roce_get_field(resp_d->arm_st_aeq_depth,
+					    V2_QUERY_PF_CAPS_D_AEQ_ARM_ST_M,
+					    V2_QUERY_PF_CAPS_D_AEQ_ARM_ST_S);
+	caps->default_ceq_arm_st = roce_get_field(resp_d->arm_st_aeq_depth,
+					    V2_QUERY_PF_CAPS_D_CEQ_ARM_ST_M,
+					    V2_QUERY_PF_CAPS_D_CEQ_ARM_ST_S);
+	caps->reserved_pds = roce_get_field(resp_d->num_uars_rsv_pds,
+					    V2_QUERY_PF_CAPS_D_RSV_PDS_M,
+					    V2_QUERY_PF_CAPS_D_RSV_PDS_S);
+	caps->num_uars = 1 << roce_get_field(resp_d->num_uars_rsv_pds,
+					     V2_QUERY_PF_CAPS_D_NUM_UARS_M,
+					     V2_QUERY_PF_CAPS_D_NUM_UARS_S);
+	caps->reserved_qps = roce_get_field(resp_d->rsv_uars_rsv_qps,
+					    V2_QUERY_PF_CAPS_D_RSV_QPS_M,
+					    V2_QUERY_PF_CAPS_D_RSV_QPS_S);
+	caps->reserved_uars = roce_get_field(resp_d->rsv_uars_rsv_qps,
+					     V2_QUERY_PF_CAPS_D_RSV_UARS_M,
+					     V2_QUERY_PF_CAPS_D_RSV_UARS_S);
+	caps->reserved_mrws = roce_get_field(resp_e->chunk_size_shift_rsv_mrws,
+					     V2_QUERY_PF_CAPS_E_RSV_MRWS_M,
+					     V2_QUERY_PF_CAPS_E_RSV_MRWS_S);
+	caps->chunk_sz = 1 << roce_get_field(resp_e->chunk_size_shift_rsv_mrws,
+					 V2_QUERY_PF_CAPS_E_CHUNK_SIZE_SHIFT_M,
+					 V2_QUERY_PF_CAPS_E_CHUNK_SIZE_SHIFT_S);
+	caps->reserved_cqs = roce_get_field(resp_e->rsv_cqs,
+					    V2_QUERY_PF_CAPS_E_RSV_CQS_M,
+					    V2_QUERY_PF_CAPS_E_RSV_CQS_S);
+	caps->reserved_srqs = roce_get_field(resp_e->rsv_srqs,
+					     V2_QUERY_PF_CAPS_E_RSV_SRQS_M,
+					     V2_QUERY_PF_CAPS_E_RSV_SRQS_S);
+	caps->reserved_lkey = roce_get_field(resp_e->rsv_lkey,
+					     V2_QUERY_PF_CAPS_E_RSV_LKEYS_M,
+					     V2_QUERY_PF_CAPS_E_RSV_LKEYS_S);
+	caps->default_ceq_max_cnt = le16_to_cpu(resp_e->ceq_max_cnt);
+	caps->default_ceq_period = le16_to_cpu(resp_e->ceq_period);
+	caps->default_aeq_max_cnt = le16_to_cpu(resp_e->aeq_max_cnt);
+	caps->default_aeq_period = le16_to_cpu(resp_e->aeq_period);
+
+	caps->qpc_timer_entry_sz = HNS_ROCE_V2_QPC_TIMER_ENTRY_SZ;
+	caps->cqc_timer_entry_sz = HNS_ROCE_V2_CQC_TIMER_ENTRY_SZ;
+	caps->mtt_entry_sz = HNS_ROCE_V2_MTT_ENTRY_SZ;
+	caps->num_mtt_segs = HNS_ROCE_V2_MAX_MTT_SEGS;
+	caps->mtt_ba_pg_sz = 0;
+	caps->num_cqe_segs = HNS_ROCE_V2_MAX_CQE_SEGS;
+	caps->num_srqwqe_segs = HNS_ROCE_V2_MAX_SRQWQE_SEGS;
+	caps->num_idx_segs = HNS_ROCE_V2_MAX_IDX_SEGS;
+
+	caps->qpc_hop_num = ctx_hop_num;
+	caps->srqc_hop_num = ctx_hop_num;
+	caps->cqc_hop_num = ctx_hop_num;
+	caps->mpt_hop_num = ctx_hop_num;
+	caps->mtt_hop_num = pbl_hop_num;
+	caps->cqe_hop_num = pbl_hop_num;
+	caps->srqwqe_hop_num = pbl_hop_num;
+	caps->idx_hop_num = pbl_hop_num;
+	caps->wqe_sq_hop_num = roce_get_field(resp_d->wq_hop_num_max_srqs,
+					  V2_QUERY_PF_CAPS_D_SQWQE_HOP_NUM_M,
+					  V2_QUERY_PF_CAPS_D_SQWQE_HOP_NUM_S);
+	caps->wqe_sge_hop_num = roce_get_field(resp_d->wq_hop_num_max_srqs,
+					  V2_QUERY_PF_CAPS_D_EX_SGE_HOP_NUM_M,
+					  V2_QUERY_PF_CAPS_D_EX_SGE_HOP_NUM_S);
+	caps->wqe_rq_hop_num = roce_get_field(resp_d->wq_hop_num_max_srqs,
+					  V2_QUERY_PF_CAPS_D_RQWQE_HOP_NUM_M,
+					  V2_QUERY_PF_CAPS_D_RQWQE_HOP_NUM_S);
+
+	calc_pg_sz(caps->num_qps, caps->qpc_entry_sz, caps->qpc_hop_num,
+		   caps->qpc_bt_num, &caps->qpc_buf_pg_sz, &caps->qpc_ba_pg_sz,
+		   HEM_TYPE_QPC);
+	calc_pg_sz(caps->num_mtpts, caps->mtpt_entry_sz, caps->mpt_hop_num,
+		   caps->mpt_bt_num, &caps->mpt_buf_pg_sz, &caps->mpt_ba_pg_sz,
+		   HEM_TYPE_MTPT);
+	calc_pg_sz(caps->num_cqs, caps->cqc_entry_sz, caps->cqc_hop_num,
+		   caps->cqc_bt_num, &caps->cqc_buf_pg_sz, &caps->cqc_ba_pg_sz,
+		   HEM_TYPE_CQC);
+	calc_pg_sz(caps->num_srqs, caps->srqc_entry_sz, caps->srqc_hop_num,
+		   caps->srqc_bt_num, &caps->srqc_buf_pg_sz,
+		   &caps->srqc_ba_pg_sz, HEM_TYPE_SRQC);
+
+	if (hr_dev->pci_dev->revision >= PCI_REVISION_ID_HIP08_B) {
+		caps->sccc_hop_num = ctx_hop_num;
+		caps->qpc_timer_hop_num = HNS_ROCE_HOP_NUM_0;
+		caps->cqc_timer_hop_num = HNS_ROCE_HOP_NUM_0;
+
+		calc_pg_sz(caps->num_qps, caps->sccc_entry_sz,
+			   caps->sccc_hop_num, caps->sccc_bt_num,
+			   &caps->sccc_buf_pg_sz, &caps->sccc_ba_pg_sz,
+			   HEM_TYPE_SCCC);
+		calc_pg_sz(caps->num_cqc_timer, caps->cqc_timer_entry_sz,
+			   caps->cqc_timer_hop_num, caps->cqc_timer_bt_num,
+			   &caps->cqc_timer_buf_pg_sz,
+			   &caps->cqc_timer_ba_pg_sz, HEM_TYPE_CQC_TIMER);
+	}
+
+	calc_pg_sz(caps->num_cqe_segs, caps->mtt_entry_sz, caps->cqe_hop_num,
+		   1, &caps->cqe_buf_pg_sz, &caps->cqe_ba_pg_sz, HEM_TYPE_CQE);
+	calc_pg_sz(caps->num_srqwqe_segs, caps->mtt_entry_sz,
+		   caps->srqwqe_hop_num, 1, &caps->srqwqe_buf_pg_sz,
+		   &caps->srqwqe_ba_pg_sz, HEM_TYPE_SRQWQE);
+	calc_pg_sz(caps->num_idx_segs, caps->idx_entry_sz, caps->idx_hop_num,
+		   1, &caps->idx_buf_pg_sz, &caps->idx_ba_pg_sz, HEM_TYPE_IDX);
+
+	return 0;
+}
+
+static int hns_roce_v2_profile(struct hns_roce_dev *hr_dev)
+{
+	struct hns_roce_caps *caps = &hr_dev->caps;
+	int ret;
+
+	ret = hns_roce_cmq_query_hw_info(hr_dev);
+	if (ret) {
+		dev_err(hr_dev->dev, "Query hardware version fail, ret = %d.\n",
+			ret);
+		return ret;
+	}
+
+	ret = hns_roce_query_fw_ver(hr_dev);
+	if (ret) {
+		dev_err(hr_dev->dev, "Query firmware version fail, ret = %d.\n",
+			ret);
+		return ret;
+	}
+
+	ret = hns_roce_config_global_param(hr_dev);
+	if (ret) {
+		dev_err(hr_dev->dev, "Configure global param fail, ret = %d.\n",
+			ret);
+		return ret;
+	}
+
+	/* Get pf resource owned by every pf */
+	ret = hns_roce_query_pf_resource(hr_dev);
+	if (ret) {
+		dev_err(hr_dev->dev, "Query pf resource fail, ret = %d.\n",
+			ret);
+		return ret;
+	}
+
+	if (hr_dev->pci_dev->revision >= PCI_REVISION_ID_HIP08_B) {
+		ret = hns_roce_query_pf_timer_resource(hr_dev);
+		if (ret) {
+			dev_err(hr_dev->dev,
+				"Query pf timer resource fail, ret = %d.\n",
+				ret);
+			return ret;
+		}
+
+		ret = hns_roce_set_vf_switch_param(hr_dev, 0);
+		if (ret) {
+			dev_err(hr_dev->dev,
+				"Set function switch param fail, ret = %d.\n",
+				ret);
+			return ret;
+		}
+	}
+
+	ret = hns_roce_alloc_vf_resource(hr_dev);
+	if (ret) {
+		dev_err(hr_dev->dev, "Allocate vf resource fail, ret = %d.\n",
+			ret);
+		return ret;
 	}
 
+	hr_dev->vendor_part_id = hr_dev->pci_dev->device;
+	hr_dev->sys_image_guid = be64_to_cpu(hr_dev->ib_dev.node_guid);
+
+	caps->num_mtt_segs	= HNS_ROCE_V2_MAX_MTT_SEGS;
+	caps->num_cqe_segs	= HNS_ROCE_V2_MAX_CQE_SEGS;
+	caps->num_srqwqe_segs	= HNS_ROCE_V2_MAX_SRQWQE_SEGS;
+	caps->num_idx_segs	= HNS_ROCE_V2_MAX_IDX_SEGS;
+
+	caps->pbl_ba_pg_sz	= HNS_ROCE_BA_PG_SZ_SUPPORTED_16K;
+	caps->pbl_buf_pg_sz	= 0;
+	caps->pbl_hop_num	= HNS_ROCE_PBL_HOP_NUM;
+	caps->eqe_ba_pg_sz	= 0;
+	caps->eqe_buf_pg_sz	= 0;
+	caps->eqe_hop_num	= HNS_ROCE_EQE_HOP_NUM;
+	caps->tsq_buf_pg_sz	= 0;
+
+	ret = hns_roce_query_pf_caps(hr_dev);
+	if (ret)
+		set_default_caps(hr_dev);
+
 	ret = hns_roce_v2_set_bt(hr_dev);
 	if (ret)
 		dev_err(hr_dev->dev, "Configure bt attribute fail, ret = %d.\n",
@@ -1818,37 +2085,32 @@
 			req_a->base_addr_h =
 				cpu_to_le32(link_tbl->table.map >> 32);
 			roce_set_field(req_a->depth_pgsz_init_en,
-				       CFG_LLM_QUE_DEPTH_M,
-				       CFG_LLM_QUE_DEPTH_S,
+				       CFG_LLM_QUE_DEPTH_M, CFG_LLM_QUE_DEPTH_S,
 				       link_tbl->npages);
 			roce_set_field(req_a->depth_pgsz_init_en,
-				       CFG_LLM_QUE_PGSZ_M,
-				       CFG_LLM_QUE_PGSZ_S,
+				       CFG_LLM_QUE_PGSZ_M, CFG_LLM_QUE_PGSZ_S,
 				       link_tbl->pg_sz);
 			req_a->head_ba_l = cpu_to_le32(entry[0].blk_ba0);
 			req_a->head_ba_h_nxtptr =
 				cpu_to_le32(entry[0].blk_ba1_nxt_ptr);
-			roce_set_field(req_a->head_ptr,
-				       CFG_LLM_HEAD_PTR_M,
+			roce_set_field(req_a->head_ptr, CFG_LLM_HEAD_PTR_M,
 				       CFG_LLM_HEAD_PTR_S, 0);
 		} else {
 			req_b->tail_ba_l =
 				cpu_to_le32(entry[page_num - 1].blk_ba0);
-			roce_set_field(req_b->tail_ba_h,
-				       CFG_LLM_TAIL_BA_H_M,
+			roce_set_field(req_b->tail_ba_h, CFG_LLM_TAIL_BA_H_M,
 				       CFG_LLM_TAIL_BA_H_S,
 				       entry[page_num - 1].blk_ba1_nxt_ptr &
-				       HNS_ROCE_LINK_TABLE_BA1_M);
-			roce_set_field(req_b->tail_ptr,
-				       CFG_LLM_TAIL_PTR_M,
+					       HNS_ROCE_LINK_TABLE_BA1_M);
+			roce_set_field(req_b->tail_ptr, CFG_LLM_TAIL_PTR_M,
 				       CFG_LLM_TAIL_PTR_S,
 				       (entry[page_num - 2].blk_ba1_nxt_ptr &
-				       HNS_ROCE_LINK_TABLE_NXT_PTR_M) >>
-				       HNS_ROCE_LINK_TABLE_NXT_PTR_S);
+					HNS_ROCE_LINK_TABLE_NXT_PTR_M) >>
+					       HNS_ROCE_LINK_TABLE_NXT_PTR_S);
 		}
 	}
-	roce_set_field(req_a->depth_pgsz_init_en,
-		       CFG_LLM_INIT_EN_M, CFG_LLM_INIT_EN_S, 1);
+	roce_set_field(req_a->depth_pgsz_init_en, CFG_LLM_INIT_EN_M,
+		       CFG_LLM_INIT_EN_S, 1);
 
 	return hns_roce_cmq_send(hr_dev, desc, 2);
 }
@@ -2020,7 +2282,7 @@
 {
 	struct hns_roce_v2_priv *priv = hr_dev->priv;
 
-	if (hr_dev->pci_dev->revision == 0x21)
+	if (hr_dev->pci_dev->revision >= PCI_REVISION_ID_HIP08_B)
 		hns_roce_function_clear(hr_dev);
 
 	hns_roce_free_link_table(hr_dev, &priv->tpq);
@@ -2141,11 +2403,9 @@
 
 	hns_roce_cmq_setup_basic_desc(&desc, HNS_ROCE_OPC_CFG_SGID_TB, false);
 
-	roce_set_field(sgid_tb->table_idx_rsv,
-		       CFG_SGID_TB_TABLE_IDX_M,
+	roce_set_field(sgid_tb->table_idx_rsv, CFG_SGID_TB_TABLE_IDX_M,
 		       CFG_SGID_TB_TABLE_IDX_S, gid_index);
-	roce_set_field(sgid_tb->vf_sgid_type_rsv,
-		       CFG_SGID_TB_VF_SGID_TYPE_M,
+	roce_set_field(sgid_tb->vf_sgid_type_rsv, CFG_SGID_TB_VF_SGID_TYPE_M,
 		       CFG_SGID_TB_VF_SGID_TYPE_S, sgid_type);
 
 	p = (u32 *)&gid->raw[0];
@@ -2416,11 +2676,10 @@
 		       V2_MPT_BYTE_4_MPT_ST_S, V2_MPT_ST_FREE);
 	roce_set_field(mpt_entry->byte_4_pd_hop_st, V2_MPT_BYTE_4_PD_M,
 		       V2_MPT_BYTE_4_PD_S, mw->pdn);
-	roce_set_field(mpt_entry->byte_4_pd_hop_st,
-		       V2_MPT_BYTE_4_PBL_HOP_NUM_M,
+	roce_set_field(mpt_entry->byte_4_pd_hop_st, V2_MPT_BYTE_4_PBL_HOP_NUM_M,
 		       V2_MPT_BYTE_4_PBL_HOP_NUM_S,
-		       mw->pbl_hop_num == HNS_ROCE_HOP_NUM_0 ?
-		       0 : mw->pbl_hop_num);
+		       mw->pbl_hop_num == HNS_ROCE_HOP_NUM_0 ? 0 :
+							       mw->pbl_hop_num);
 	roce_set_field(mpt_entry->byte_4_pd_hop_st,
 		       V2_MPT_BYTE_4_PBL_BA_PG_SZ_M,
 		       V2_MPT_BYTE_4_PBL_BA_PG_SZ_S,
@@ -2428,6 +2687,7 @@
 
 	roce_set_bit(mpt_entry->byte_8_mw_cnt_en, V2_MPT_BYTE_8_R_INV_EN_S, 1);
 	roce_set_bit(mpt_entry->byte_8_mw_cnt_en, V2_MPT_BYTE_8_L_INV_EN_S, 1);
+	roce_set_bit(mpt_entry->byte_8_mw_cnt_en, V2_MPT_BYTE_8_LW_EN_S, 1);
 
 	roce_set_bit(mpt_entry->byte_12_mw_pa, V2_MPT_BYTE_12_PA_S, 0);
 	roce_set_bit(mpt_entry->byte_12_mw_pa, V2_MPT_BYTE_12_MR_MW_S, 1);
@@ -2447,8 +2707,7 @@
 
 static void *get_cqe_v2(struct hns_roce_cq *hr_cq, int n)
 {
-	return hns_roce_buf_offset(&hr_cq->hr_buf.hr_buf,
-				   n * HNS_ROCE_V2_CQE_ENTRY_SIZE);
+	return hns_roce_buf_offset(&hr_cq->buf, n * HNS_ROCE_V2_CQE_ENTRY_SIZE);
 }
 
 static void *get_sw_cqe_v2(struct hns_roce_cq *hr_cq, int n)
@@ -2457,7 +2716,7 @@
 
 	/* Get cqe when Owner bit is Conversely with the MSB of cons_idx */
 	return (roce_get_bit(cqe->byte_4, V2_CQE_BYTE_4_OWNER_S) ^
-		!!(n & (hr_cq->ib_cq.cqe + 1))) ? cqe : NULL;
+		!!(n & hr_cq->cq_depth)) ? cqe : NULL;
 }
 
 static struct hns_roce_v2_cqe *next_cqe_sw_v2(struct hns_roce_cq *hr_cq)
@@ -2483,7 +2742,7 @@
 
 static void hns_roce_v2_cq_set_ci(struct hns_roce_cq *hr_cq, u32 cons_index)
 {
-	*hr_cq->set_ci_db = cons_index & 0xffffff;
+	*hr_cq->set_ci_db = cons_index & V2_CQ_DB_PARAMETER_CONS_IDX_M;
 }
 
 static void __hns_roce_v2_cq_clean(struct hns_roce_cq *hr_cq, u32 qpn,
@@ -2550,8 +2809,7 @@
 
 static void hns_roce_v2_write_cqc(struct hns_roce_dev *hr_dev,
 				  struct hns_roce_cq *hr_cq, void *mb_buf,
-				  u64 *mtts, dma_addr_t dma_handle, int nent,
-				  u32 vector)
+				  u64 *mtts, dma_addr_t dma_handle)
 {
 	struct hns_roce_v2_cq_context *cq_context;
 
@@ -2563,9 +2821,9 @@
 	roce_set_field(cq_context->byte_4_pg_ceqn, V2_CQC_BYTE_4_ARM_ST_M,
 		       V2_CQC_BYTE_4_ARM_ST_S, REG_NXT_CEQE);
 	roce_set_field(cq_context->byte_4_pg_ceqn, V2_CQC_BYTE_4_SHIFT_M,
-		       V2_CQC_BYTE_4_SHIFT_S, ilog2((unsigned int)nent));
+		       V2_CQC_BYTE_4_SHIFT_S, ilog2(hr_cq->cq_depth));
 	roce_set_field(cq_context->byte_4_pg_ceqn, V2_CQC_BYTE_4_CEQN_M,
-		       V2_CQC_BYTE_4_CEQN_S, vector);
+		       V2_CQC_BYTE_4_CEQN_S, hr_cq->vector);
 
 	roce_set_field(cq_context->byte_8_cqn, V2_CQC_BYTE_8_CQN_M,
 		       V2_CQC_BYTE_8_CQN_S, hr_cq->cqn);
@@ -2688,16 +2946,63 @@
 	return 0;
 }
 
+static int sw_comp(struct hns_roce_qp *hr_qp, struct hns_roce_wq *wq,
+		   int num_entries, struct ib_wc *wc)
+{
+	unsigned int left;
+	int npolled = 0;
+
+	left = wq->head - wq->tail;
+	if (left == 0)
+		return 0;
+
+	left = min_t(unsigned int, (unsigned int)num_entries, left);
+	while (npolled < left) {
+		wc->wr_id = wq->wrid[wq->tail & (wq->wqe_cnt - 1)];
+		wc->status = IB_WC_WR_FLUSH_ERR;
+		wc->vendor_err = 0;
+		wc->qp = &hr_qp->ibqp;
+
+		wq->tail++;
+		wc++;
+		npolled++;
+	}
+
+	return npolled;
+}
+
+static int hns_roce_v2_sw_poll_cq(struct hns_roce_cq *hr_cq, int num_entries,
+				  struct ib_wc *wc)
+{
+	struct hns_roce_qp *hr_qp;
+	int npolled = 0;
+
+	list_for_each_entry(hr_qp, &hr_cq->sq_list, sq_node) {
+		npolled += sw_comp(hr_qp, &hr_qp->sq,
+				   num_entries - npolled, wc + npolled);
+		if (npolled >= num_entries)
+			goto out;
+	}
+
+	list_for_each_entry(hr_qp, &hr_cq->rq_list, rq_node) {
+		npolled += sw_comp(hr_qp, &hr_qp->rq,
+				   num_entries - npolled, wc + npolled);
+		if (npolled >= num_entries)
+			goto out;
+	}
+
+out:
+	return npolled;
+}
+
 static int hns_roce_v2_poll_one(struct hns_roce_cq *hr_cq,
 				struct hns_roce_qp **cur_qp, struct ib_wc *wc)
 {
+	struct hns_roce_dev *hr_dev = to_hr_dev(hr_cq->ib_cq.device);
 	struct hns_roce_srq *srq = NULL;
-	struct hns_roce_dev *hr_dev;
 	struct hns_roce_v2_cqe *cqe;
 	struct hns_roce_qp *hr_qp;
 	struct hns_roce_wq *wq;
-	struct ib_qp_attr attr;
-	int attr_mask;
 	int is_send;
 	u16 wqe_ctr;
 	u32 opcode;
@@ -2721,7 +3026,6 @@
 				V2_CQE_BYTE_16_LCL_QPN_S);
 
 	if (!*cur_qp || (qpn & HNS_ROCE_V2_CQE_QPN_MASK) != (*cur_qp)->qpn) {
-		hr_dev = to_hr_dev(hr_cq->ib_cq.device);
 		hr_qp = __hns_roce_qp_lookup(hr_dev, qpn);
 		if (unlikely(!hr_qp)) {
 			dev_err(hr_dev->dev, "CQ %06lx with entry for unknown QPN %06x\n",
@@ -2731,6 +3035,7 @@
 		*cur_qp = hr_qp;
 	}
 
+	hr_qp = *cur_qp;
 	wc->qp = &(*cur_qp)->ibqp;
 	wc->vendor_err = 0;
 
@@ -2815,14 +3120,24 @@
 		break;
 	}
 
-	/* flush cqe if wc status is error, excluding flush error */
-	if ((wc->status != IB_WC_SUCCESS) &&
-	    (wc->status != IB_WC_WR_FLUSH_ERR)) {
-		attr_mask = IB_QP_STATE;
-		attr.qp_state = IB_QPS_ERR;
-		return hns_roce_v2_modify_qp(&(*cur_qp)->ibqp,
-					     &attr, attr_mask,
-					     (*cur_qp)->state, IB_QPS_ERR);
+	/*
+	 * Hip08 hardware cannot flush the WQEs in SQ/RQ if the QP state gets
+	 * into errored mode. Hence, as a workaround to this hardware
+	 * limitation, driver needs to assist in flushing. But the flushing
+	 * operation uses mailbox to convey the QP state to the hardware and
+	 * which can sleep due to the mutex protection around the mailbox calls.
+	 * Hence, use the deferred flush for now. Once wc error detected, the
+	 * flushing operation is needed.
+	 */
+	if (wc->status != IB_WC_SUCCESS &&
+	    wc->status != IB_WC_WR_FLUSH_ERR) {
+		dev_err(hr_dev->dev, "error cqe status is: 0x%x\n",
+			status & HNS_ROCE_V2_CQE_STATUS_MASK);
+
+		if (!test_and_set_bit(HNS_ROCE_FLUSH_FLAG, &hr_qp->flush_flag))
+			init_flush_work(hr_dev, hr_qp);
+
+		return 0;
 	}
 
 	if (wc->status == IB_WC_WR_FLUSH_ERR)
@@ -2968,6 +3283,7 @@
 static int hns_roce_v2_poll_cq(struct ib_cq *ibcq, int num_entries,
 			       struct ib_wc *wc)
 {
+	struct hns_roce_dev *hr_dev = to_hr_dev(ibcq->device);
 	struct hns_roce_cq *hr_cq = to_hr_cq(ibcq);
 	struct hns_roce_qp *cur_qp = NULL;
 	unsigned long flags;
@@ -2975,6 +3291,18 @@
 
 	spin_lock_irqsave(&hr_cq->lock, flags);
 
+	/*
+	 * When the device starts to reset, the state is RST_DOWN. At this time,
+	 * there may still be some valid CQEs in the hardware that are not
+	 * polled. Therefore, it is not allowed to switch to the software mode
+	 * immediately. When the state changes to UNINIT, CQE no longer exists
+	 * in the hardware, and then switch to software mode.
+	 */
+	if (hr_dev->state == HNS_ROCE_DEVICE_STATE_UNINIT) {
+		npolled = hns_roce_v2_sw_poll_cq(hr_cq, num_entries, wc);
+		goto out;
+	}
+
 	for (npolled = 0; npolled < num_entries; ++npolled) {
 		if (hns_roce_v2_poll_one(hr_cq, &cur_qp, wc + npolled))
 			break;
@@ -2986,6 +3314,7 @@
 		hns_roce_v2_cq_set_ci(hr_cq, hr_cq->cons_index);
 	}
 
+out:
 	spin_unlock_irqrestore(&hr_cq->lock, flags);
 
 	return npolled;
@@ -3160,8 +3489,6 @@
 }
 
 static int hns_roce_v2_qp_modify(struct hns_roce_dev *hr_dev,
-				 enum ib_qp_state cur_state,
-				 enum ib_qp_state new_state,
 				 struct hns_roce_v2_qp_context *context,
 				 struct hns_roce_qp *hr_qp)
 {
@@ -3211,6 +3538,9 @@
 	roce_set_bit(context->byte_76_srqn_op_en, V2_QPC_BYTE_76_ATE_S,
 		     !!(access_flags & IB_ACCESS_REMOTE_ATOMIC));
 	roce_set_bit(qpc_mask->byte_76_srqn_op_en, V2_QPC_BYTE_76_ATE_S, 0);
+	roce_set_bit(context->byte_76_srqn_op_en, V2_QPC_BYTE_76_EXT_ATE_S,
+		     !!(access_flags & IB_ACCESS_REMOTE_ATOMIC));
+	roce_set_bit(qpc_mask->byte_76_srqn_op_en, V2_QPC_BYTE_76_EXT_ATE_S, 0);
 }
 
 static void set_qpc_wqe_cnt(struct hns_roce_qp *hr_qp,
@@ -3578,6 +3908,12 @@
 			     IB_ACCESS_REMOTE_ATOMIC));
 		roce_set_bit(qpc_mask->byte_76_srqn_op_en, V2_QPC_BYTE_76_ATE_S,
 			     0);
+		roce_set_bit(context->byte_76_srqn_op_en,
+			     V2_QPC_BYTE_76_EXT_ATE_S,
+			     !!(attr->qp_access_flags &
+				IB_ACCESS_REMOTE_ATOMIC));
+		roce_set_bit(qpc_mask->byte_76_srqn_op_en,
+			     V2_QPC_BYTE_76_EXT_ATE_S, 0);
 	} else {
 		roce_set_bit(context->byte_76_srqn_op_en, V2_QPC_BYTE_76_RRE_S,
 			     !!(hr_qp->access_flags & IB_ACCESS_REMOTE_READ));
@@ -3593,6 +3929,11 @@
 			     !!(hr_qp->access_flags & IB_ACCESS_REMOTE_ATOMIC));
 		roce_set_bit(qpc_mask->byte_76_srqn_op_en, V2_QPC_BYTE_76_ATE_S,
 			     0);
+		roce_set_bit(context->byte_76_srqn_op_en,
+			     V2_QPC_BYTE_76_EXT_ATE_S,
+			     !!(hr_qp->access_flags & IB_ACCESS_REMOTE_ATOMIC));
+		roce_set_bit(qpc_mask->byte_76_srqn_op_en,
+			     V2_QPC_BYTE_76_EXT_ATE_S, 0);
 	}
 
 	roce_set_field(context->byte_16_buf_ba_pg_sz, V2_QPC_BYTE_16_PD_M,
@@ -3839,13 +4180,11 @@
 	/* Configure GID index */
 	port_num = rdma_ah_get_port_num(&attr->ah_attr);
 	roce_set_field(context->byte_20_smac_sgid_idx,
-		       V2_QPC_BYTE_20_SGID_IDX_M,
-		       V2_QPC_BYTE_20_SGID_IDX_S,
+		       V2_QPC_BYTE_20_SGID_IDX_M, V2_QPC_BYTE_20_SGID_IDX_S,
 		       hns_get_gid_index(hr_dev, port_num - 1,
 					 grh->sgid_index));
 	roce_set_field(qpc_mask->byte_20_smac_sgid_idx,
-		       V2_QPC_BYTE_20_SGID_IDX_M,
-		       V2_QPC_BYTE_20_SGID_IDX_S, 0);
+		       V2_QPC_BYTE_20_SGID_IDX_M, V2_QPC_BYTE_20_SGID_IDX_S, 0);
 	memcpy(&(context->dmac), dmac, sizeof(u32));
 	roce_set_field(context->byte_52_udpspn_dmac, V2_QPC_BYTE_52_DMAC_M,
 		       V2_QPC_BYTE_52_DMAC_S, *((u16 *)(&dmac[4])));
@@ -4061,8 +4400,8 @@
 	struct hns_roce_qp *hr_qp = to_hr_qp(ibqp);
 	const struct ib_gid_attr *gid_attr = NULL;
 	int is_roce_protocol;
+	u16 vlan_id = 0xffff;
 	bool is_udp = false;
-	u16 vlan = 0xffff;
 	u8 ib_port;
 	u8 hr_port;
 	int ret;
@@ -4074,7 +4413,7 @@
 
 	if (is_roce_protocol) {
 		gid_attr = attr->ah_attr.grh.sgid_attr;
-		ret = rdma_read_gid_l2_fields(gid_attr, &vlan, NULL);
+		ret = rdma_read_gid_l2_fields(gid_attr, &vlan_id, NULL);
 		if (ret)
 			return ret;
 
@@ -4083,7 +4422,7 @@
 				 IB_GID_TYPE_ROCE_UDP_ENCAP);
 	}
 
-	if (vlan < VLAN_CFI_MASK) {
+	if (vlan_id < VLAN_N_VID) {
 		roce_set_bit(context->byte_76_srqn_op_en,
 			     V2_QPC_BYTE_76_RQ_VLAN_EN_S, 1);
 		roce_set_bit(qpc_mask->byte_76_srqn_op_en,
@@ -4095,7 +4434,7 @@
 	}
 
 	roce_set_field(context->byte_24_mtu_tc, V2_QPC_BYTE_24_VLAN_ID_M,
-		       V2_QPC_BYTE_24_VLAN_ID_S, vlan);
+		       V2_QPC_BYTE_24_VLAN_ID_S, vlan_id);
 	roce_set_field(qpc_mask->byte_24_mtu_tc, V2_QPC_BYTE_24_VLAN_ID_M,
 		       V2_QPC_BYTE_24_VLAN_ID_S, 0);
 
@@ -4129,7 +4468,7 @@
 	roce_set_field(qpc_mask->byte_24_mtu_tc, V2_QPC_BYTE_24_HOP_LIMIT_M,
 		       V2_QPC_BYTE_24_HOP_LIMIT_S, 0);
 
-	if (hr_dev->pci_dev->revision == 0x21 && is_udp)
+	if (hr_dev->pci_dev->revision >= PCI_REVISION_ID_HIP08_B && is_udp)
 		roce_set_field(context->byte_24_mtu_tc, V2_QPC_BYTE_24_TC_M,
 			       V2_QPC_BYTE_24_TC_S, grh->traffic_class >> 2);
 	else
@@ -4235,8 +4574,7 @@
 
 		roce_set_field(context->byte_212_lsn,
 			       V2_QPC_BYTE_212_RETRY_CNT_M,
-			       V2_QPC_BYTE_212_RETRY_CNT_S,
-			       attr->retry_cnt);
+			       V2_QPC_BYTE_212_RETRY_CNT_S, attr->retry_cnt);
 		roce_set_field(qpc_mask->byte_212_lsn,
 			       V2_QPC_BYTE_212_RETRY_CNT_M,
 			       V2_QPC_BYTE_212_RETRY_CNT_S, 0);
@@ -4390,6 +4728,8 @@
 	struct hns_roce_v2_qp_context *context = ctx;
 	struct hns_roce_v2_qp_context *qpc_mask = ctx + 1;
 	struct device *dev = hr_dev->dev;
+	unsigned long sq_flag = 0;
+	unsigned long rq_flag = 0;
 	int ret;
 
 	/*
@@ -4407,6 +4747,8 @@
 
 	/* When QP state is err, SQ and RQ WQE should be flushed */
 	if (new_state == IB_QPS_ERR) {
+		spin_lock_irqsave(&hr_qp->sq.lock, sq_flag);
+		hr_qp->state = IB_QPS_ERR;
 		roce_set_field(context->byte_160_sq_ci_pi,
 			       V2_QPC_BYTE_160_SQ_PRODUCER_IDX_M,
 			       V2_QPC_BYTE_160_SQ_PRODUCER_IDX_S,
@@ -4414,8 +4756,10 @@
 		roce_set_field(qpc_mask->byte_160_sq_ci_pi,
 			       V2_QPC_BYTE_160_SQ_PRODUCER_IDX_M,
 			       V2_QPC_BYTE_160_SQ_PRODUCER_IDX_S, 0);
+		spin_unlock_irqrestore(&hr_qp->sq.lock, sq_flag);
 
 		if (!ibqp->srq) {
+			spin_lock_irqsave(&hr_qp->rq.lock, rq_flag);
 			roce_set_field(context->byte_84_rq_ci_pi,
 			       V2_QPC_BYTE_84_RQ_PRODUCER_IDX_M,
 			       V2_QPC_BYTE_84_RQ_PRODUCER_IDX_S,
@@ -4423,6 +4767,7 @@
 			roce_set_field(qpc_mask->byte_84_rq_ci_pi,
 			       V2_QPC_BYTE_84_RQ_PRODUCER_IDX_M,
 			       V2_QPC_BYTE_84_RQ_PRODUCER_IDX_S, 0);
+			spin_unlock_irqrestore(&hr_qp->rq.lock, rq_flag);
 		}
 	}
 
@@ -4444,7 +4789,7 @@
 		       V2_QPC_BYTE_60_QP_ST_S, 0);
 
 	/* SW pass context to HW */
-	ret = hns_roce_v2_qp_modify(hr_dev, cur_state, new_state, ctx, hr_qp);
+	ret = hns_roce_v2_qp_modify(hr_dev, ctx, hr_qp);
 	if (ret) {
 		dev_err(dev, "hns_roce_qp_modify failed(%d)\n", ret);
 		goto out;
@@ -4465,7 +4810,6 @@
 		hr_qp->rq.tail = 0;
 		hr_qp->sq.head = 0;
 		hr_qp->sq.tail = 0;
-		hr_qp->sq_next_wqe = 0;
 		hr_qp->next_sge = 0;
 		if (hr_qp->rq.wqe_cnt)
 			*hr_qp->rdb.db_record = 0;
@@ -4562,7 +4906,7 @@
 	qp_attr->path_mig_state = IB_MIG_ARMED;
 	qp_attr->ah_attr.type   = RDMA_AH_ATTR_TYPE_ROCE;
 	if (hr_qp->ibqp.qp_type == IB_QPT_UD)
-		qp_attr->qkey = V2_QKEY_VAL;
+		qp_attr->qkey = le32_to_cpu(context.qkey_xrcd);
 
 	qp_attr->rq_psn = roce_get_field(context.byte_108_rx_reqepsn,
 					 V2_QPC_BYTE_108_RX_REQ_EPSN_M,
@@ -4620,9 +4964,11 @@
 					      V2_QPC_BYTE_28_AT_M,
 					      V2_QPC_BYTE_28_AT_S);
 	qp_attr->retry_cnt = roce_get_field(context.byte_212_lsn,
-					    V2_QPC_BYTE_212_RETRY_CNT_M,
-					    V2_QPC_BYTE_212_RETRY_CNT_S);
-	qp_attr->rnr_retry = le32_to_cpu(context.rq_rnr_timer);
+					    V2_QPC_BYTE_212_RETRY_NUM_INIT_M,
+					    V2_QPC_BYTE_212_RETRY_NUM_INIT_S);
+	qp_attr->rnr_retry = roce_get_field(context.byte_244_rnr_rxack,
+					    V2_QPC_BYTE_244_RNR_NUM_INIT_M,
+					    V2_QPC_BYTE_244_RNR_NUM_INIT_S);
 
 done:
 	qp_attr->cur_qp_state = qp_attr->qp_state;
@@ -4638,6 +4984,7 @@
 	}
 
 	qp_init_attr->cap = qp_attr->cap;
+	qp_init_attr->sq_sig_type = hr_qp->sq_signal_bits;
 
 out:
 	mutex_unlock(&hr_qp->mutex);
@@ -4650,72 +4997,41 @@
 {
 	struct hns_roce_cq *send_cq, *recv_cq;
 	struct ib_device *ibdev = &hr_dev->ib_dev;
-	int ret;
+	unsigned long flags;
+	int ret = 0;
 
 	if (hr_qp->ibqp.qp_type == IB_QPT_RC && hr_qp->state != IB_QPS_RESET) {
 		/* Modify qp to reset before destroying qp */
 		ret = hns_roce_v2_modify_qp(&hr_qp->ibqp, NULL, 0,
 					    hr_qp->state, IB_QPS_RESET);
-		if (ret) {
+		if (ret)
 			ibdev_err(ibdev, "modify QP to Reset failed.\n");
-			return ret;
-		}
 	}
 
-	send_cq = to_hr_cq(hr_qp->ibqp.send_cq);
-	recv_cq = to_hr_cq(hr_qp->ibqp.recv_cq);
+	send_cq = hr_qp->ibqp.send_cq ? to_hr_cq(hr_qp->ibqp.send_cq) : NULL;
+	recv_cq = hr_qp->ibqp.recv_cq ? to_hr_cq(hr_qp->ibqp.recv_cq) : NULL;
 
+	spin_lock_irqsave(&hr_dev->qp_list_lock, flags);
 	hns_roce_lock_cqs(send_cq, recv_cq);
 
 	if (!udata) {
-		__hns_roce_v2_cq_clean(recv_cq, hr_qp->qpn, hr_qp->ibqp.srq ?
-				       to_hr_srq(hr_qp->ibqp.srq) : NULL);
-		if (send_cq != recv_cq)
+		if (recv_cq)
+			__hns_roce_v2_cq_clean(recv_cq, hr_qp->qpn,
+					       (hr_qp->ibqp.srq ?
+						to_hr_srq(hr_qp->ibqp.srq) :
+						NULL));
+
+		if (send_cq && send_cq != recv_cq)
 			__hns_roce_v2_cq_clean(send_cq, hr_qp->qpn, NULL);
+
 	}
 
 	hns_roce_qp_remove(hr_dev, hr_qp);
 
 	hns_roce_unlock_cqs(send_cq, recv_cq);
+	spin_unlock_irqrestore(&hr_dev->qp_list_lock, flags);
 
-	hns_roce_qp_free(hr_dev, hr_qp);
-
-	/* Not special_QP, free their QPN */
-	if ((hr_qp->ibqp.qp_type == IB_QPT_RC) ||
-	    (hr_qp->ibqp.qp_type == IB_QPT_UC) ||
-	    (hr_qp->ibqp.qp_type == IB_QPT_UD))
-		hns_roce_release_range_qp(hr_dev, hr_qp->qpn, 1);
-
-	hns_roce_mtr_cleanup(hr_dev, &hr_qp->mtr);
-
-	if (udata) {
-		struct hns_roce_ucontext *context =
-			rdma_udata_to_drv_context(
-				udata,
-				struct hns_roce_ucontext,
-				ibucontext);
-
-		if (hr_qp->sq.wqe_cnt && (hr_qp->sdb_en == 1))
-			hns_roce_db_unmap_user(context, &hr_qp->sdb);
-
-		if (hr_qp->rq.wqe_cnt && (hr_qp->rdb_en == 1))
-			hns_roce_db_unmap_user(context, &hr_qp->rdb);
-	} else {
-		kfree(hr_qp->sq.wrid);
-		kfree(hr_qp->rq.wrid);
-		hns_roce_buf_free(hr_dev, hr_qp->buff_size, &hr_qp->hr_buf);
-		if (hr_qp->rq.wqe_cnt)
-			hns_roce_free_db(hr_dev, &hr_qp->rdb);
-	}
-	ib_umem_release(hr_qp->umem);
-
-	if ((hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_RQ_INLINE) &&
-	     hr_qp->rq.wqe_cnt) {
-		kfree(hr_qp->rq_inl_buf.wqe_list[0].sg_list);
-		kfree(hr_qp->rq_inl_buf.wqe_list);
-	}
-
-	return 0;
+	return ret;
 }
 
 static int hns_roce_v2_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
@@ -4725,16 +5041,11 @@
 	int ret;
 
 	ret = hns_roce_v2_destroy_qp_common(hr_dev, hr_qp, udata);
-	if (ret) {
+	if (ret)
 		ibdev_err(&hr_dev->ib_dev, "Destroy qp 0x%06lx failed(%d)\n",
 			  hr_qp->qpn, ret);
-		return ret;
-	}
 
-	if (hr_qp->ibqp.qp_type == IB_QPT_GSI)
-		kfree(hr_to_hr_sqp(hr_qp));
-	else
-		kfree(hr_qp);
+	hns_roce_qp_destroy(hr_dev, hr_qp, udata);
 
 	return 0;
 }
@@ -4833,39 +5144,6 @@
 	return ret;
 }
 
-static void hns_roce_set_qps_to_err(struct hns_roce_dev *hr_dev, u32 qpn)
-{
-	struct hns_roce_qp *hr_qp;
-	struct ib_qp_attr attr;
-	int attr_mask;
-	int ret;
-
-	hr_qp = __hns_roce_qp_lookup(hr_dev, qpn);
-	if (!hr_qp) {
-		dev_warn(hr_dev->dev, "no hr_qp can be found!\n");
-		return;
-	}
-
-	if (hr_qp->ibqp.uobject) {
-		if (hr_qp->sdb_en == 1) {
-			hr_qp->sq.head = *(int *)(hr_qp->sdb.virt_addr);
-			if (hr_qp->rdb_en == 1)
-				hr_qp->rq.head = *(int *)(hr_qp->rdb.virt_addr);
-		} else {
-			dev_warn(hr_dev->dev, "flush cqe is unsupported in userspace!\n");
-			return;
-		}
-	}
-
-	attr_mask = IB_QP_STATE;
-	attr.qp_state = IB_QPS_ERR;
-	ret = hns_roce_v2_modify_qp(&hr_qp->ibqp, &attr, attr_mask,
-				    hr_qp->state, IB_QPS_ERR);
-	if (ret)
-		dev_err(hr_dev->dev, "failed to modify qp %d to err state.\n",
-			qpn);
-}
-
 static void hns_roce_irq_work_handle(struct work_struct *work)
 {
 	struct hns_roce_work *irq_work =
@@ -4889,17 +5167,14 @@
 	case HNS_ROCE_EVENT_TYPE_WQ_CATAS_ERROR:
 		dev_err(dev, "Local work queue 0x%x catas error, sub_type:%d\n",
 			qpn, irq_work->sub_type);
-		hns_roce_set_qps_to_err(irq_work->hr_dev, qpn);
 		break;
 	case HNS_ROCE_EVENT_TYPE_INV_REQ_LOCAL_WQ_ERROR:
 		dev_err(dev, "Invalid request local work queue 0x%x error.\n",
 			qpn);
-		hns_roce_set_qps_to_err(irq_work->hr_dev, qpn);
 		break;
 	case HNS_ROCE_EVENT_TYPE_LOCAL_WQ_ACCESS_ERROR:
 		dev_err(dev, "Local access violation work queue 0x%x error, sub_type:%d\n",
 			qpn, irq_work->sub_type);
-		hns_roce_set_qps_to_err(irq_work->hr_dev, qpn);
 		break;
 	case HNS_ROCE_EVENT_TYPE_SRQ_LIMIT_REACH:
 		dev_warn(dev, "SRQ limit reach.\n");
@@ -4951,10 +5226,7 @@
 static void set_eq_cons_index_v2(struct hns_roce_eq *eq)
 {
 	struct hns_roce_dev *hr_dev = eq->hr_dev;
-	__le32 doorbell[2];
-
-	doorbell[0] = 0;
-	doorbell[1] = 0;
+	__le32 doorbell[2] = {};
 
 	if (eq->type_flag == HNS_ROCE_AEQ) {
 		roce_set_field(doorbell[0], HNS_ROCE_V2_EQ_DB_CMD_M,
@@ -4980,44 +5252,24 @@
 	hns_roce_write64(hr_dev, doorbell, eq->doorbell);
 }
 
-static struct hns_roce_aeqe *get_aeqe_v2(struct hns_roce_eq *eq, u32 entry)
-{
-	u32 buf_chk_sz;
-	unsigned long off;
-
-	buf_chk_sz = 1 << (eq->eqe_buf_pg_sz + PAGE_SHIFT);
-	off = (entry & (eq->entries - 1)) * HNS_ROCE_AEQ_ENTRY_SIZE;
-
-	return (struct hns_roce_aeqe *)((char *)(eq->buf_list->buf) +
-		off % buf_chk_sz);
-}
-
-static struct hns_roce_aeqe *mhop_get_aeqe(struct hns_roce_eq *eq, u32 entry)
+static inline void *get_eqe_buf(struct hns_roce_eq *eq, unsigned long offset)
 {
 	u32 buf_chk_sz;
-	unsigned long off;
 
 	buf_chk_sz = 1 << (eq->eqe_buf_pg_sz + PAGE_SHIFT);
-
-	off = (entry & (eq->entries - 1)) * HNS_ROCE_AEQ_ENTRY_SIZE;
-
-	if (eq->hop_num == HNS_ROCE_HOP_NUM_0)
-		return (struct hns_roce_aeqe *)((u8 *)(eq->bt_l0) +
-			off % buf_chk_sz);
+	if (eq->buf.nbufs == 1)
+		return eq->buf.direct.buf + offset % buf_chk_sz;
 	else
-		return (struct hns_roce_aeqe *)((u8 *)
-			(eq->buf[off / buf_chk_sz]) + off % buf_chk_sz);
+		return eq->buf.page_list[offset / buf_chk_sz].buf +
+		       offset % buf_chk_sz;
 }
 
 static struct hns_roce_aeqe *next_aeqe_sw_v2(struct hns_roce_eq *eq)
 {
 	struct hns_roce_aeqe *aeqe;
 
-	if (!eq->hop_num)
-		aeqe = get_aeqe_v2(eq, eq->cons_index);
-	else
-		aeqe = mhop_get_aeqe(eq, eq->cons_index);
-
+	aeqe = get_eqe_buf(eq, (eq->cons_index & (eq->entries - 1)) *
+			   HNS_ROCE_AEQ_ENTRY_SIZE);
 	return (roce_get_bit(aeqe->asyn, HNS_ROCE_V2_AEQ_AEQE_OWNER_S) ^
 		!!(eq->cons_index & eq->entries)) ? aeqe : NULL;
 }
@@ -5110,44 +5362,12 @@
 	return aeqe_found;
 }
 
-static struct hns_roce_ceqe *get_ceqe_v2(struct hns_roce_eq *eq, u32 entry)
-{
-	u32 buf_chk_sz;
-	unsigned long off;
-
-	buf_chk_sz = 1 << (eq->eqe_buf_pg_sz + PAGE_SHIFT);
-	off = (entry & (eq->entries - 1)) * HNS_ROCE_CEQ_ENTRY_SIZE;
-
-	return (struct hns_roce_ceqe *)((char *)(eq->buf_list->buf) +
-		off % buf_chk_sz);
-}
-
-static struct hns_roce_ceqe *mhop_get_ceqe(struct hns_roce_eq *eq, u32 entry)
-{
-	u32 buf_chk_sz;
-	unsigned long off;
-
-	buf_chk_sz = 1 << (eq->eqe_buf_pg_sz + PAGE_SHIFT);
-
-	off = (entry & (eq->entries - 1)) * HNS_ROCE_CEQ_ENTRY_SIZE;
-
-	if (eq->hop_num == HNS_ROCE_HOP_NUM_0)
-		return (struct hns_roce_ceqe *)((u8 *)(eq->bt_l0) +
-			off % buf_chk_sz);
-	else
-		return (struct hns_roce_ceqe *)((u8 *)(eq->buf[off /
-			buf_chk_sz]) + off % buf_chk_sz);
-}
-
 static struct hns_roce_ceqe *next_ceqe_sw_v2(struct hns_roce_eq *eq)
 {
 	struct hns_roce_ceqe *ceqe;
 
-	if (!eq->hop_num)
-		ceqe = get_ceqe_v2(eq, eq->cons_index);
-	else
-		ceqe = mhop_get_ceqe(eq, eq->cons_index);
-
+	ceqe = get_eqe_buf(eq, (eq->cons_index & (eq->entries - 1)) *
+			   HNS_ROCE_CEQ_ENTRY_SIZE);
 	return (!!(roce_get_bit(ceqe->comp, HNS_ROCE_V2_CEQ_CEQE_OWNER_S))) ^
 		(!!(eq->cons_index & eq->entries)) ? ceqe : NULL;
 }
@@ -5166,8 +5386,7 @@
 		 */
 		dma_rmb();
 
-		cqn = roce_get_field(ceqe->comp,
-				     HNS_ROCE_V2_CEQE_COMP_CQN_M,
+		cqn = roce_get_field(ceqe->comp, HNS_ROCE_V2_CEQE_COMP_CQN_M,
 				     HNS_ROCE_V2_CEQE_COMP_CQN_S);
 
 		hns_roce_cq_completion(hr_dev, cqn);
@@ -5223,8 +5442,8 @@
 
 		dev_err(dev, "AEQ overflow!\n");
 
-		int_st |= 1 << HNS_ROCE_V2_VF_INT_ST_AEQ_OVERFLOW_S;
-		roce_write(hr_dev, ROCEE_VF_ABN_INT_ST_REG, int_st);
+		roce_write(hr_dev, ROCEE_VF_ABN_INT_ST_REG,
+			   1 << HNS_ROCE_V2_VF_INT_ST_AEQ_OVERFLOW_S);
 
 		/* Set reset level for reset_event() */
 		if (ops->set_default_reset_request)
@@ -5308,90 +5527,11 @@
 		dev_err(dev, "[mailbox cmd] destroy eqc(%d) failed.\n", eqn);
 }
 
-static void hns_roce_mhop_free_eq(struct hns_roce_dev *hr_dev,
-				  struct hns_roce_eq *eq)
-{
-	struct device *dev = hr_dev->dev;
-	u64 idx;
-	u64 size;
-	u32 buf_chk_sz;
-	u32 bt_chk_sz;
-	u32 mhop_num;
-	int eqe_alloc;
-	int i = 0;
-	int j = 0;
-
-	mhop_num = hr_dev->caps.eqe_hop_num;
-	buf_chk_sz = 1 << (hr_dev->caps.eqe_buf_pg_sz + PAGE_SHIFT);
-	bt_chk_sz = 1 << (hr_dev->caps.eqe_ba_pg_sz + PAGE_SHIFT);
-
-	if (mhop_num == HNS_ROCE_HOP_NUM_0) {
-		dma_free_coherent(dev, (unsigned int)(eq->entries *
-				  eq->eqe_size), eq->bt_l0, eq->l0_dma);
-		return;
-	}
-
-	dma_free_coherent(dev, bt_chk_sz, eq->bt_l0, eq->l0_dma);
-	if (mhop_num == 1) {
-		for (i = 0; i < eq->l0_last_num; i++) {
-			if (i == eq->l0_last_num - 1) {
-				eqe_alloc = i * (buf_chk_sz / eq->eqe_size);
-				size = (eq->entries - eqe_alloc) * eq->eqe_size;
-				dma_free_coherent(dev, size, eq->buf[i],
-						  eq->buf_dma[i]);
-				break;
-			}
-			dma_free_coherent(dev, buf_chk_sz, eq->buf[i],
-					  eq->buf_dma[i]);
-		}
-	} else if (mhop_num == 2) {
-		for (i = 0; i < eq->l0_last_num; i++) {
-			dma_free_coherent(dev, bt_chk_sz, eq->bt_l1[i],
-					  eq->l1_dma[i]);
-
-			for (j = 0; j < bt_chk_sz / BA_BYTE_LEN; j++) {
-				idx = i * (bt_chk_sz / BA_BYTE_LEN) + j;
-				if ((i == eq->l0_last_num - 1)
-				     && j == eq->l1_last_num - 1) {
-					eqe_alloc = (buf_chk_sz / eq->eqe_size)
-						    * idx;
-					size = (eq->entries - eqe_alloc)
-						* eq->eqe_size;
-					dma_free_coherent(dev, size,
-							  eq->buf[idx],
-							  eq->buf_dma[idx]);
-					break;
-				}
-				dma_free_coherent(dev, buf_chk_sz, eq->buf[idx],
-						  eq->buf_dma[idx]);
-			}
-		}
-	}
-	kfree(eq->buf_dma);
-	kfree(eq->buf);
-	kfree(eq->l1_dma);
-	kfree(eq->bt_l1);
-	eq->buf_dma = NULL;
-	eq->buf = NULL;
-	eq->l1_dma = NULL;
-	eq->bt_l1 = NULL;
-}
-
-static void hns_roce_v2_free_eq(struct hns_roce_dev *hr_dev,
-				struct hns_roce_eq *eq)
+static void free_eq_buf(struct hns_roce_dev *hr_dev, struct hns_roce_eq *eq)
 {
-	u32 buf_chk_sz;
-
-	buf_chk_sz = 1 << (eq->eqe_buf_pg_sz + PAGE_SHIFT);
-
-	if (hr_dev->caps.eqe_hop_num) {
-		hns_roce_mhop_free_eq(hr_dev, eq);
-		return;
-	}
-
-	dma_free_coherent(hr_dev->dev, buf_chk_sz, eq->buf_list->buf,
-			  eq->buf_list->map);
-	kfree(eq->buf_list);
+	if (!eq->hop_num || eq->hop_num == HNS_ROCE_HOP_NUM_0)
+		hns_roce_mtr_cleanup(hr_dev, &eq->mtr);
+	hns_roce_buf_free(hr_dev, eq->buf.size, &eq->buf);
 }
 
 static void hns_roce_config_eqc(struct hns_roce_dev *hr_dev,
@@ -5399,6 +5539,8 @@
 				void *mb_buf)
 {
 	struct hns_roce_eq_context *eqc;
+	u64 ba[MTT_MIN_COUNT] = { 0 };
+	int count;
 
 	eqc = mb_buf;
 	memset(eqc, 0, sizeof(struct hns_roce_eq_context));
@@ -5414,349 +5556,211 @@
 	eq->eqe_buf_pg_sz = hr_dev->caps.eqe_buf_pg_sz;
 	eq->shift = ilog2((unsigned int)eq->entries);
 
-	if (!eq->hop_num)
-		eq->eqe_ba = eq->buf_list->map;
-	else
-		eq->eqe_ba = eq->l0_dma;
+	/* if not muti-hop, eqe buffer only use one trunk */
+	if (!eq->hop_num || eq->hop_num == HNS_ROCE_HOP_NUM_0) {
+		eq->eqe_ba = eq->buf.direct.map;
+		eq->cur_eqe_ba = eq->eqe_ba;
+		if (eq->buf.npages > 1)
+			eq->nxt_eqe_ba = eq->eqe_ba + (1 << eq->eqe_buf_pg_sz);
+		else
+			eq->nxt_eqe_ba = eq->eqe_ba;
+	} else {
+		count = hns_roce_mtr_find(hr_dev, &eq->mtr, 0, ba,
+					  MTT_MIN_COUNT, &eq->eqe_ba);
+		eq->cur_eqe_ba = ba[0];
+		if (count > 1)
+			eq->nxt_eqe_ba = ba[1];
+		else
+			eq->nxt_eqe_ba = ba[0];
+	}
 
 	/* set eqc state */
-	roce_set_field(eqc->byte_4,
-		       HNS_ROCE_EQC_EQ_ST_M,
-		       HNS_ROCE_EQC_EQ_ST_S,
+	roce_set_field(eqc->byte_4, HNS_ROCE_EQC_EQ_ST_M, HNS_ROCE_EQC_EQ_ST_S,
 		       HNS_ROCE_V2_EQ_STATE_VALID);
 
 	/* set eqe hop num */
-	roce_set_field(eqc->byte_4,
-		       HNS_ROCE_EQC_HOP_NUM_M,
+	roce_set_field(eqc->byte_4, HNS_ROCE_EQC_HOP_NUM_M,
 		       HNS_ROCE_EQC_HOP_NUM_S, eq->hop_num);
 
 	/* set eqc over_ignore */
-	roce_set_field(eqc->byte_4,
-		       HNS_ROCE_EQC_OVER_IGNORE_M,
+	roce_set_field(eqc->byte_4, HNS_ROCE_EQC_OVER_IGNORE_M,
 		       HNS_ROCE_EQC_OVER_IGNORE_S, eq->over_ignore);
 
 	/* set eqc coalesce */
-	roce_set_field(eqc->byte_4,
-		       HNS_ROCE_EQC_COALESCE_M,
+	roce_set_field(eqc->byte_4, HNS_ROCE_EQC_COALESCE_M,
 		       HNS_ROCE_EQC_COALESCE_S, eq->coalesce);
 
 	/* set eqc arm_state */
-	roce_set_field(eqc->byte_4,
-		       HNS_ROCE_EQC_ARM_ST_M,
+	roce_set_field(eqc->byte_4, HNS_ROCE_EQC_ARM_ST_M,
 		       HNS_ROCE_EQC_ARM_ST_S, eq->arm_st);
 
 	/* set eqn */
-	roce_set_field(eqc->byte_4,
-		       HNS_ROCE_EQC_EQN_M,
-		       HNS_ROCE_EQC_EQN_S, eq->eqn);
+	roce_set_field(eqc->byte_4, HNS_ROCE_EQC_EQN_M, HNS_ROCE_EQC_EQN_S,
+		       eq->eqn);
 
 	/* set eqe_cnt */
-	roce_set_field(eqc->byte_4,
-		       HNS_ROCE_EQC_EQE_CNT_M,
-		       HNS_ROCE_EQC_EQE_CNT_S,
-		       HNS_ROCE_EQ_INIT_EQE_CNT);
+	roce_set_field(eqc->byte_4, HNS_ROCE_EQC_EQE_CNT_M,
+		       HNS_ROCE_EQC_EQE_CNT_S, HNS_ROCE_EQ_INIT_EQE_CNT);
 
 	/* set eqe_ba_pg_sz */
-	roce_set_field(eqc->byte_8,
-		       HNS_ROCE_EQC_BA_PG_SZ_M,
+	roce_set_field(eqc->byte_8, HNS_ROCE_EQC_BA_PG_SZ_M,
 		       HNS_ROCE_EQC_BA_PG_SZ_S,
 		       eq->eqe_ba_pg_sz + PG_SHIFT_OFFSET);
 
 	/* set eqe_buf_pg_sz */
-	roce_set_field(eqc->byte_8,
-		       HNS_ROCE_EQC_BUF_PG_SZ_M,
+	roce_set_field(eqc->byte_8, HNS_ROCE_EQC_BUF_PG_SZ_M,
 		       HNS_ROCE_EQC_BUF_PG_SZ_S,
 		       eq->eqe_buf_pg_sz + PG_SHIFT_OFFSET);
 
 	/* set eq_producer_idx */
-	roce_set_field(eqc->byte_8,
-		       HNS_ROCE_EQC_PROD_INDX_M,
-		       HNS_ROCE_EQC_PROD_INDX_S,
-		       HNS_ROCE_EQ_INIT_PROD_IDX);
+	roce_set_field(eqc->byte_8, HNS_ROCE_EQC_PROD_INDX_M,
+		       HNS_ROCE_EQC_PROD_INDX_S, HNS_ROCE_EQ_INIT_PROD_IDX);
 
 	/* set eq_max_cnt */
-	roce_set_field(eqc->byte_12,
-		       HNS_ROCE_EQC_MAX_CNT_M,
+	roce_set_field(eqc->byte_12, HNS_ROCE_EQC_MAX_CNT_M,
 		       HNS_ROCE_EQC_MAX_CNT_S, eq->eq_max_cnt);
 
 	/* set eq_period */
-	roce_set_field(eqc->byte_12,
-		       HNS_ROCE_EQC_PERIOD_M,
+	roce_set_field(eqc->byte_12, HNS_ROCE_EQC_PERIOD_M,
 		       HNS_ROCE_EQC_PERIOD_S, eq->eq_period);
 
 	/* set eqe_report_timer */
-	roce_set_field(eqc->eqe_report_timer,
-		       HNS_ROCE_EQC_REPORT_TIMER_M,
+	roce_set_field(eqc->eqe_report_timer, HNS_ROCE_EQC_REPORT_TIMER_M,
 		       HNS_ROCE_EQC_REPORT_TIMER_S,
 		       HNS_ROCE_EQ_INIT_REPORT_TIMER);
 
 	/* set eqe_ba [34:3] */
-	roce_set_field(eqc->eqe_ba0,
-		       HNS_ROCE_EQC_EQE_BA_L_M,
+	roce_set_field(eqc->eqe_ba0, HNS_ROCE_EQC_EQE_BA_L_M,
 		       HNS_ROCE_EQC_EQE_BA_L_S, eq->eqe_ba >> 3);
 
 	/* set eqe_ba [64:35] */
-	roce_set_field(eqc->eqe_ba1,
-		       HNS_ROCE_EQC_EQE_BA_H_M,
+	roce_set_field(eqc->eqe_ba1, HNS_ROCE_EQC_EQE_BA_H_M,
 		       HNS_ROCE_EQC_EQE_BA_H_S, eq->eqe_ba >> 35);
 
 	/* set eq shift */
-	roce_set_field(eqc->byte_28,
-		       HNS_ROCE_EQC_SHIFT_M,
-		       HNS_ROCE_EQC_SHIFT_S, eq->shift);
+	roce_set_field(eqc->byte_28, HNS_ROCE_EQC_SHIFT_M, HNS_ROCE_EQC_SHIFT_S,
+		       eq->shift);
 
 	/* set eq MSI_IDX */
-	roce_set_field(eqc->byte_28,
-		       HNS_ROCE_EQC_MSI_INDX_M,
-		       HNS_ROCE_EQC_MSI_INDX_S,
-		       HNS_ROCE_EQ_INIT_MSI_IDX);
+	roce_set_field(eqc->byte_28, HNS_ROCE_EQC_MSI_INDX_M,
+		       HNS_ROCE_EQC_MSI_INDX_S, HNS_ROCE_EQ_INIT_MSI_IDX);
 
 	/* set cur_eqe_ba [27:12] */
-	roce_set_field(eqc->byte_28,
-		       HNS_ROCE_EQC_CUR_EQE_BA_L_M,
+	roce_set_field(eqc->byte_28, HNS_ROCE_EQC_CUR_EQE_BA_L_M,
 		       HNS_ROCE_EQC_CUR_EQE_BA_L_S, eq->cur_eqe_ba >> 12);
 
 	/* set cur_eqe_ba [59:28] */
-	roce_set_field(eqc->byte_32,
-		       HNS_ROCE_EQC_CUR_EQE_BA_M_M,
+	roce_set_field(eqc->byte_32, HNS_ROCE_EQC_CUR_EQE_BA_M_M,
 		       HNS_ROCE_EQC_CUR_EQE_BA_M_S, eq->cur_eqe_ba >> 28);
 
 	/* set cur_eqe_ba [63:60] */
-	roce_set_field(eqc->byte_36,
-		       HNS_ROCE_EQC_CUR_EQE_BA_H_M,
+	roce_set_field(eqc->byte_36, HNS_ROCE_EQC_CUR_EQE_BA_H_M,
 		       HNS_ROCE_EQC_CUR_EQE_BA_H_S, eq->cur_eqe_ba >> 60);
 
 	/* set eq consumer idx */
-	roce_set_field(eqc->byte_36,
-		       HNS_ROCE_EQC_CONS_INDX_M,
-		       HNS_ROCE_EQC_CONS_INDX_S,
-		       HNS_ROCE_EQ_INIT_CONS_IDX);
+	roce_set_field(eqc->byte_36, HNS_ROCE_EQC_CONS_INDX_M,
+		       HNS_ROCE_EQC_CONS_INDX_S, HNS_ROCE_EQ_INIT_CONS_IDX);
 
 	/* set nex_eqe_ba[43:12] */
-	roce_set_field(eqc->nxt_eqe_ba0,
-		       HNS_ROCE_EQC_NXT_EQE_BA_L_M,
+	roce_set_field(eqc->nxt_eqe_ba0, HNS_ROCE_EQC_NXT_EQE_BA_L_M,
 		       HNS_ROCE_EQC_NXT_EQE_BA_L_S, eq->nxt_eqe_ba >> 12);
 
 	/* set nex_eqe_ba[63:44] */
-	roce_set_field(eqc->nxt_eqe_ba1,
-		       HNS_ROCE_EQC_NXT_EQE_BA_H_M,
+	roce_set_field(eqc->nxt_eqe_ba1, HNS_ROCE_EQC_NXT_EQE_BA_H_M,
 		       HNS_ROCE_EQC_NXT_EQE_BA_H_S, eq->nxt_eqe_ba >> 44);
 }
 
-static int hns_roce_mhop_alloc_eq(struct hns_roce_dev *hr_dev,
-				  struct hns_roce_eq *eq)
+static int map_eq_buf(struct hns_roce_dev *hr_dev, struct hns_roce_eq *eq,
+		      u32 page_shift)
 {
-	struct device *dev = hr_dev->dev;
-	int eq_alloc_done = 0;
-	int eq_buf_cnt = 0;
-	int eqe_alloc;
-	u32 buf_chk_sz;
-	u32 bt_chk_sz;
-	u32 mhop_num;
-	u64 size;
-	u64 idx;
+	struct hns_roce_buf_region region = {};
+	dma_addr_t *buf_list = NULL;
 	int ba_num;
-	int bt_num;
-	int record_i;
-	int record_j;
-	int i = 0;
-	int j = 0;
-
-	mhop_num = hr_dev->caps.eqe_hop_num;
-	buf_chk_sz = 1 << (hr_dev->caps.eqe_buf_pg_sz + PAGE_SHIFT);
-	bt_chk_sz = 1 << (hr_dev->caps.eqe_ba_pg_sz + PAGE_SHIFT);
+	int ret;
 
 	ba_num = DIV_ROUND_UP(PAGE_ALIGN(eq->entries * eq->eqe_size),
-			      buf_chk_sz);
-	bt_num = DIV_ROUND_UP(ba_num, bt_chk_sz / BA_BYTE_LEN);
-
-	if (mhop_num == HNS_ROCE_HOP_NUM_0) {
-		if (eq->entries > buf_chk_sz / eq->eqe_size) {
-			dev_err(dev, "eq entries %d is larger than buf_pg_sz!",
-				eq->entries);
-			return -EINVAL;
-		}
-		eq->bt_l0 = dma_alloc_coherent(dev, eq->entries * eq->eqe_size,
-					       &(eq->l0_dma), GFP_KERNEL);
-		if (!eq->bt_l0)
-			return -ENOMEM;
+			      1 << page_shift);
+	hns_roce_init_buf_region(&region, hr_dev->caps.eqe_hop_num, 0, ba_num);
 
-		eq->cur_eqe_ba = eq->l0_dma;
-		eq->nxt_eqe_ba = 0;
+	/* alloc a tmp list for storing eq buf address */
+	ret = hns_roce_alloc_buf_list(&region, &buf_list, 1);
+	if (ret) {
+		dev_err(hr_dev->dev, "alloc eq buf_list error\n");
+		return ret;
+	}
 
-		return 0;
+	ba_num = hns_roce_get_kmem_bufs(hr_dev, buf_list, region.count,
+					region.offset, &eq->buf);
+	if (ba_num != region.count) {
+		dev_err(hr_dev->dev, "get eqe buf err,expect %d,ret %d.\n",
+			region.count, ba_num);
+		ret = -ENOBUFS;
+		goto done;
 	}
 
-	eq->buf_dma = kcalloc(ba_num, sizeof(*eq->buf_dma), GFP_KERNEL);
-	if (!eq->buf_dma)
-		return -ENOMEM;
-	eq->buf = kcalloc(ba_num, sizeof(*eq->buf), GFP_KERNEL);
-	if (!eq->buf)
-		goto err_kcalloc_buf;
-
-	if (mhop_num == 2) {
-		eq->l1_dma = kcalloc(bt_num, sizeof(*eq->l1_dma), GFP_KERNEL);
-		if (!eq->l1_dma)
-			goto err_kcalloc_l1_dma;
-
-		eq->bt_l1 = kcalloc(bt_num, sizeof(*eq->bt_l1), GFP_KERNEL);
-		if (!eq->bt_l1)
-			goto err_kcalloc_bt_l1;
-	}
-
-	/* alloc L0 BT */
-	eq->bt_l0 = dma_alloc_coherent(dev, bt_chk_sz, &eq->l0_dma, GFP_KERNEL);
-	if (!eq->bt_l0)
-		goto err_dma_alloc_l0;
-
-	if (mhop_num == 1) {
-		if (ba_num > (bt_chk_sz / BA_BYTE_LEN))
-			dev_err(dev, "ba_num %d is too large for 1 hop\n",
-				ba_num);
-
-		/* alloc buf */
-		for (i = 0; i < bt_chk_sz / BA_BYTE_LEN; i++) {
-			if (eq_buf_cnt + 1 < ba_num) {
-				size = buf_chk_sz;
-			} else {
-				eqe_alloc = i * (buf_chk_sz / eq->eqe_size);
-				size = (eq->entries - eqe_alloc) * eq->eqe_size;
-			}
-			eq->buf[i] = dma_alloc_coherent(dev, size,
-							&(eq->buf_dma[i]),
-							GFP_KERNEL);
-			if (!eq->buf[i])
-				goto err_dma_alloc_buf;
+	hns_roce_mtr_init(&eq->mtr, PAGE_SHIFT + hr_dev->caps.eqe_ba_pg_sz,
+			  page_shift);
+	ret = hns_roce_mtr_attach(hr_dev, &eq->mtr, &buf_list, &region, 1);
+	if (ret)
+		dev_err(hr_dev->dev, "mtr attach error for eqe\n");
 
-			*(eq->bt_l0 + i) = eq->buf_dma[i];
+	goto done;
 
-			eq_buf_cnt++;
-			if (eq_buf_cnt >= ba_num)
-				break;
-		}
-		eq->cur_eqe_ba = eq->buf_dma[0];
-		if (ba_num > 1)
-			eq->nxt_eqe_ba = eq->buf_dma[1];
-
-	} else if (mhop_num == 2) {
-		/* alloc L1 BT and buf */
-		for (i = 0; i < bt_chk_sz / BA_BYTE_LEN; i++) {
-			eq->bt_l1[i] = dma_alloc_coherent(dev, bt_chk_sz,
-							  &(eq->l1_dma[i]),
-							  GFP_KERNEL);
-			if (!eq->bt_l1[i])
-				goto err_dma_alloc_l1;
-			*(eq->bt_l0 + i) = eq->l1_dma[i];
-
-			for (j = 0; j < bt_chk_sz / BA_BYTE_LEN; j++) {
-				idx = i * bt_chk_sz / BA_BYTE_LEN + j;
-				if (eq_buf_cnt + 1 < ba_num) {
-					size = buf_chk_sz;
-				} else {
-					eqe_alloc = (buf_chk_sz / eq->eqe_size)
-						    * idx;
-					size = (eq->entries - eqe_alloc)
-						* eq->eqe_size;
-				}
-				eq->buf[idx] = dma_alloc_coherent(dev, size,
-								  &(eq->buf_dma[idx]),
-								  GFP_KERNEL);
-				if (!eq->buf[idx])
-					goto err_dma_alloc_buf;
-
-				*(eq->bt_l1[i] + j) = eq->buf_dma[idx];
-
-				eq_buf_cnt++;
-				if (eq_buf_cnt >= ba_num) {
-					eq_alloc_done = 1;
-					break;
-				}
-			}
+	hns_roce_mtr_cleanup(hr_dev, &eq->mtr);
+done:
+	hns_roce_free_buf_list(&buf_list, 1);
 
-			if (eq_alloc_done)
-				break;
-		}
-		eq->cur_eqe_ba = eq->buf_dma[0];
-		if (ba_num > 1)
-			eq->nxt_eqe_ba = eq->buf_dma[1];
-	}
+	return ret;
+}
 
-	eq->l0_last_num = i + 1;
-	if (mhop_num == 2)
-		eq->l1_last_num = j + 1;
+static int alloc_eq_buf(struct hns_roce_dev *hr_dev, struct hns_roce_eq *eq)
+{
+	struct hns_roce_buf *buf = &eq->buf;
+	bool is_mhop = false;
+	u32 page_shift;
+	u32 mhop_num;
+	u32 max_size;
+	int ret;
 
-	return 0;
+	page_shift = PAGE_SHIFT + hr_dev->caps.eqe_buf_pg_sz;
+	mhop_num = hr_dev->caps.eqe_hop_num;
+	if (!mhop_num) {
+		max_size = 1 << page_shift;
+		buf->size = max_size;
+	} else if (mhop_num == HNS_ROCE_HOP_NUM_0) {
+		max_size = eq->entries * eq->eqe_size;
+		buf->size = max_size;
+	} else {
+		max_size = 1 << page_shift;
+		buf->size = PAGE_ALIGN(eq->entries * eq->eqe_size);
+		is_mhop = true;
+	}
 
-err_dma_alloc_l1:
-	dma_free_coherent(dev, bt_chk_sz, eq->bt_l0, eq->l0_dma);
-	eq->bt_l0 = NULL;
-	eq->l0_dma = 0;
-	for (i -= 1; i >= 0; i--) {
-		dma_free_coherent(dev, bt_chk_sz, eq->bt_l1[i],
-				  eq->l1_dma[i]);
-
-		for (j = 0; j < bt_chk_sz / BA_BYTE_LEN; j++) {
-			idx = i * bt_chk_sz / BA_BYTE_LEN + j;
-			dma_free_coherent(dev, buf_chk_sz, eq->buf[idx],
-					  eq->buf_dma[idx]);
-		}
-	}
-	goto err_dma_alloc_l0;
-
-err_dma_alloc_buf:
-	dma_free_coherent(dev, bt_chk_sz, eq->bt_l0, eq->l0_dma);
-	eq->bt_l0 = NULL;
-	eq->l0_dma = 0;
-
-	if (mhop_num == 1)
-		for (i -= 1; i >= 0; i--)
-			dma_free_coherent(dev, buf_chk_sz, eq->buf[i],
-					  eq->buf_dma[i]);
-	else if (mhop_num == 2) {
-		record_i = i;
-		record_j = j;
-		for (; i >= 0; i--) {
-			dma_free_coherent(dev, bt_chk_sz, eq->bt_l1[i],
-					  eq->l1_dma[i]);
-
-			for (j = 0; j < bt_chk_sz / BA_BYTE_LEN; j++) {
-				if (i == record_i && j >= record_j)
-					break;
-
-				idx = i * bt_chk_sz / BA_BYTE_LEN + j;
-				dma_free_coherent(dev, buf_chk_sz,
-						  eq->buf[idx],
-						  eq->buf_dma[idx]);
-			}
-		}
+	ret = hns_roce_buf_alloc(hr_dev, buf->size, max_size, buf, page_shift);
+	if (ret) {
+		dev_err(hr_dev->dev, "alloc eq buf error\n");
+		return ret;
 	}
 
-err_dma_alloc_l0:
-	kfree(eq->bt_l1);
-	eq->bt_l1 = NULL;
-
-err_kcalloc_bt_l1:
-	kfree(eq->l1_dma);
-	eq->l1_dma = NULL;
-
-err_kcalloc_l1_dma:
-	kfree(eq->buf);
-	eq->buf = NULL;
-
-err_kcalloc_buf:
-	kfree(eq->buf_dma);
-	eq->buf_dma = NULL;
+	if (is_mhop) {
+		ret = map_eq_buf(hr_dev, eq, page_shift);
+		if (ret) {
+			dev_err(hr_dev->dev, "map roce buf error\n");
+			goto err_alloc;
+		}
+	}
 
-	return -ENOMEM;
+	return 0;
+err_alloc:
+	hns_roce_buf_free(hr_dev, buf->size, buf);
+	return ret;
 }
 
 static int hns_roce_v2_create_eq(struct hns_roce_dev *hr_dev,
 				 struct hns_roce_eq *eq,
 				 unsigned int eq_cmd)
 {
-	struct device *dev = hr_dev->dev;
 	struct hns_roce_cmd_mailbox *mailbox;
-	u32 buf_chk_sz = 0;
 	int ret;
 
 	/* Allocate mailbox memory */
@@ -5764,38 +5768,17 @@
 	if (IS_ERR(mailbox))
 		return PTR_ERR(mailbox);
 
-	if (!hr_dev->caps.eqe_hop_num) {
-		buf_chk_sz = 1 << (hr_dev->caps.eqe_buf_pg_sz + PAGE_SHIFT);
-
-		eq->buf_list = kzalloc(sizeof(struct hns_roce_buf_list),
-				       GFP_KERNEL);
-		if (!eq->buf_list) {
-			ret = -ENOMEM;
-			goto free_cmd_mbox;
-		}
-
-		eq->buf_list->buf = dma_alloc_coherent(dev, buf_chk_sz,
-						       &(eq->buf_list->map),
-						       GFP_KERNEL);
-		if (!eq->buf_list->buf) {
-			ret = -ENOMEM;
-			goto err_alloc_buf;
-		}
-
-	} else {
-		ret = hns_roce_mhop_alloc_eq(hr_dev, eq);
-		if (ret) {
-			ret = -ENOMEM;
-			goto free_cmd_mbox;
-		}
+	ret = alloc_eq_buf(hr_dev, eq);
+	if (ret) {
+		ret = -ENOMEM;
+		goto free_cmd_mbox;
 	}
-
 	hns_roce_config_eqc(hr_dev, eq, mailbox->buf);
 
 	ret = hns_roce_cmd_mbox(hr_dev, mailbox->dma, 0, eq->eqn, 0,
 				eq_cmd, HNS_ROCE_CMD_TIMEOUT_MSECS);
 	if (ret) {
-		dev_err(dev, "[mailbox cmd] create eqc failed.\n");
+		dev_err(hr_dev->dev, "[mailbox cmd] create eqc failed.\n");
 		goto err_cmd_mbox;
 	}
 
@@ -5804,16 +5787,7 @@
 	return 0;
 
 err_cmd_mbox:
-	if (!hr_dev->caps.eqe_hop_num)
-		dma_free_coherent(dev, buf_chk_sz, eq->buf_list->buf,
-				  eq->buf_list->map);
-	else {
-		hns_roce_mhop_free_eq(hr_dev, eq);
-		goto free_cmd_mbox;
-	}
-
-err_alloc_buf:
-	kfree(eq->buf_list);
+	free_eq_buf(hr_dev, eq);
 
 free_cmd_mbox:
 	hns_roce_free_cmd_mailbox(hr_dev, mailbox);
@@ -5839,18 +5813,16 @@
 
 	/* irq contains: abnormal + AEQ + CEQ */
 	for (j = 0; j < other_num; j++)
-		snprintf((char *)hr_dev->irq_names[j],
-			 HNS_ROCE_INT_NAME_LEN, "hns-abn-%d", j);
+		snprintf((char *)hr_dev->irq_names[j], HNS_ROCE_INT_NAME_LEN,
+			 "hns-abn-%d", j);
 
 	for (j = other_num; j < (other_num + aeq_num); j++)
-		snprintf((char *)hr_dev->irq_names[j],
-			 HNS_ROCE_INT_NAME_LEN, "hns-aeq-%d",
-			 j - other_num);
+		snprintf((char *)hr_dev->irq_names[j], HNS_ROCE_INT_NAME_LEN,
+			 "hns-aeq-%d", j - other_num);
 
 	for (j = (other_num + aeq_num); j < irq_num; j++)
-		snprintf((char *)hr_dev->irq_names[j],
-			 HNS_ROCE_INT_NAME_LEN, "hns-ceq-%d",
-			 j - other_num - aeq_num);
+		snprintf((char *)hr_dev->irq_names[j], HNS_ROCE_INT_NAME_LEN,
+			 "hns-ceq-%d", j - other_num - aeq_num);
 
 	for (j = 0; j < irq_num; j++) {
 		if (j < other_num)
@@ -5977,8 +5949,7 @@
 		goto err_request_irq_fail;
 	}
 
-	hr_dev->irq_workq =
-		create_singlethread_workqueue("hns_roce_irq_workqueue");
+	hr_dev->irq_workq = alloc_ordered_workqueue("hns_roce_irq_workq", 0);
 	if (!hr_dev->irq_workq) {
 		dev_err(dev, "Create irq workqueue failed!\n");
 		ret = -ENOMEM;
@@ -5995,7 +5966,7 @@
 
 err_create_eq_fail:
 	for (i -= 1; i >= 0; i--)
-		hns_roce_v2_free_eq(hr_dev, &eq_table->eq[i]);
+		free_eq_buf(hr_dev, &eq_table->eq[i]);
 	kfree(eq_table->eq);
 
 	return ret;
@@ -6017,7 +5988,7 @@
 	for (i = 0; i < eq_num; i++) {
 		hns_roce_v2_destroy_eqc(hr_dev, i);
 
-		hns_roce_v2_free_eq(hr_dev, &eq_table->eq[i]);
+		free_eq_buf(hr_dev, &eq_table->eq[i]);
 	}
 
 	kfree(eq_table->eq);
@@ -6047,7 +6018,7 @@
 		       hr_dev->caps.srqwqe_hop_num));
 	roce_set_field(srq_context->byte_4_srqn_srqst,
 		       SRQC_BYTE_4_SRQ_SHIFT_M, SRQC_BYTE_4_SRQ_SHIFT_S,
-		       ilog2(srq->max));
+		       ilog2(srq->wqe_cnt));
 
 	roce_set_field(srq_context->byte_4_srqn_srqst, SRQC_BYTE_4_SRQN_M,
 		       SRQC_BYTE_4_SRQN_S, srq->srqn);
@@ -6092,11 +6063,11 @@
 	roce_set_field(srq_context->byte_44_idxbufpgsz_addr,
 		       SRQC_BYTE_44_SRQ_IDX_BA_PG_SZ_M,
 		       SRQC_BYTE_44_SRQ_IDX_BA_PG_SZ_S,
-		       hr_dev->caps.idx_ba_pg_sz);
+		       hr_dev->caps.idx_ba_pg_sz + PG_SHIFT_OFFSET);
 	roce_set_field(srq_context->byte_44_idxbufpgsz_addr,
 		       SRQC_BYTE_44_SRQ_IDX_BUF_PG_SZ_M,
 		       SRQC_BYTE_44_SRQ_IDX_BUF_PG_SZ_S,
-		       hr_dev->caps.idx_buf_pg_sz);
+		       hr_dev->caps.idx_buf_pg_sz + PG_SHIFT_OFFSET);
 
 	srq_context->idx_nxt_blk_addr =
 		cpu_to_le32(mtts_idx[1] >> PAGE_ADDR_SHIFT);
@@ -6133,7 +6104,7 @@
 	int ret;
 
 	if (srq_attr_mask & IB_SRQ_LIMIT) {
-		if (srq_attr->srq_limit >= srq->max)
+		if (srq_attr->srq_limit >= srq->wqe_cnt)
 			return -EINVAL;
 
 		mailbox = hns_roce_alloc_cmd_mailbox(hr_dev);
@@ -6193,7 +6164,7 @@
 				  SRQC_BYTE_8_SRQ_LIMIT_WL_S);
 
 	attr->srq_limit = limit_wl;
-	attr->max_wr    = srq->max - 1;
+	attr->max_wr    = srq->wqe_cnt - 1;
 	attr->max_sge   = srq->max_gs;
 
 	memcpy(srq_context, mailbox->buf, sizeof(*srq_context));
@@ -6246,7 +6217,7 @@
 
 	spin_lock_irqsave(&srq->lock, flags);
 
-	ind = srq->head & (srq->max - 1);
+	ind = srq->head & (srq->wqe_cnt - 1);
 
 	for (nreq = 0; wr; ++nreq, wr = wr->next) {
 		if (unlikely(wr->num_sge > srq->max_gs)) {
@@ -6261,7 +6232,7 @@
 			break;
 		}
 
-		wqe_idx = find_empty_entry(&srq->idx_que, srq->max);
+		wqe_idx = find_empty_entry(&srq->idx_que, srq->wqe_cnt);
 		if (wqe_idx < 0) {
 			ret = -ENOMEM;
 			*bad_wr = wr;
@@ -6285,7 +6256,7 @@
 		}
 
 		srq->wrid[wqe_idx] = wr->wr_id;
-		ind = (ind + 1) & (srq->max - 1);
+		ind = (ind + 1) & (srq->wqe_cnt - 1);
 	}
 
 	if (likely(nreq)) {
@@ -6380,12 +6351,14 @@
 
 MODULE_DEVICE_TABLE(pci, hns_roce_hw_v2_pci_tbl);
 
-static int hns_roce_hw_v2_get_cfg(struct hns_roce_dev *hr_dev,
+static void hns_roce_hw_v2_get_cfg(struct hns_roce_dev *hr_dev,
 				  struct hnae3_handle *handle)
 {
 	struct hns_roce_v2_priv *priv = hr_dev->priv;
 	int i;
 
+	hr_dev->pci_dev = handle->pdev;
+	hr_dev->dev = &handle->pdev->dev;
 	hr_dev->hw = &hns_roce_hw_v2;
 	hr_dev->dfx = &hns_roce_dfx_hw_v2;
 	hr_dev->sdb_offset = ROCEE_DB_SQ_L_0_REG;
@@ -6410,8 +6383,6 @@
 
 	hr_dev->reset_cnt = handle->ae_algo->ops->ae_dev_reset_cnt(handle);
 	priv->handle = handle;
-
-	return 0;
 }
 
 static int __hns_roce_hw_v2_init_instance(struct hnae3_handle *handle)
@@ -6429,14 +6400,7 @@
 		goto error_failed_kzalloc;
 	}
 
-	hr_dev->pci_dev = handle->pdev;
-	hr_dev->dev = &handle->pdev->dev;
-
-	ret = hns_roce_hw_v2_get_cfg(hr_dev, handle);
-	if (ret) {
-		dev_err(hr_dev->dev, "Get Configuration failed!\n");
-		goto error_failed_get_cfg;
-	}
+	hns_roce_hw_v2_get_cfg(hr_dev, handle);
 
 	ret = hns_roce_init(hr_dev);
 	if (ret) {
@@ -6466,6 +6430,10 @@
 		return;
 
 	handle->priv = NULL;
+
+	hr_dev->state = HNS_ROCE_DEVICE_STATE_UNINIT;
+	hns_roce_handle_device_err(hr_dev);
+
 	hns_roce_exit(hr_dev);
 	kfree(hr_dev->priv);
 	ib_dealloc_device(&hr_dev->ib_dev);
@@ -6527,7 +6495,6 @@
 static int hns_roce_hw_v2_reset_notify_down(struct hnae3_handle *handle)
 {
 	struct hns_roce_dev *hr_dev;
-	struct ib_event event;
 
 	if (handle->rinfo.instance_state != HNS_ROCE_STATE_INITED) {
 		set_bit(HNS_ROCE_RST_DIRECT_RETURN, &handle->rinfo.state);
@@ -6545,10 +6512,7 @@
 	hr_dev->active = false;
 	hr_dev->dis_db = true;
 
-	event.event = IB_EVENT_DEVICE_FATAL;
-	event.device = &hr_dev->ib_dev;
-	event.element.port_num = 1;
-	ib_dispatch_event(&event);
+	hr_dev->state = HNS_ROCE_DEVICE_STATE_RST_DOWN;
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hns/hns_roce_hw_v2.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hns/hns_roce_hw_v2.h
@@ -81,15 +81,17 @@
 #define HNS_ROCE_V2_QPC_ENTRY_SZ		256
 #define HNS_ROCE_V2_IRRL_ENTRY_SZ		64
 #define HNS_ROCE_V2_TRRL_ENTRY_SZ		48
+#define HNS_ROCE_V2_EXT_ATOMIC_TRRL_ENTRY_SZ	100
 #define HNS_ROCE_V2_CQC_ENTRY_SZ		64
 #define HNS_ROCE_V2_SRQC_ENTRY_SZ		64
 #define HNS_ROCE_V2_MTPT_ENTRY_SZ		64
 #define HNS_ROCE_V2_MTT_ENTRY_SZ		64
+#define HNS_ROCE_V2_IDX_ENTRY_SZ		4
 #define HNS_ROCE_V2_CQE_ENTRY_SIZE		32
 #define HNS_ROCE_V2_SCCC_ENTRY_SZ		32
-#define HNS_ROCE_V2_QPC_TIMER_ENTRY_SZ		4096
-#define HNS_ROCE_V2_CQC_TIMER_ENTRY_SZ		4096
-#define HNS_ROCE_V2_PAGE_SIZE_SUPPORTED		0xFFFFF000
+#define HNS_ROCE_V2_QPC_TIMER_ENTRY_SZ		PAGE_SIZE
+#define HNS_ROCE_V2_CQC_TIMER_ENTRY_SZ		PAGE_SIZE
+#define HNS_ROCE_V2_PAGE_SIZE_SUPPORTED		0xFFFF000
 #define HNS_ROCE_V2_MAX_INNER_MTPT_NUM		2
 #define HNS_ROCE_INVALID_LKEY			0x100
 #define HNS_ROCE_CMQ_TX_TIMEOUT			30000
@@ -109,7 +111,12 @@
 #define HNS_ROCE_PBL_HOP_NUM			2
 #define HNS_ROCE_EQE_HOP_NUM			2
 #define HNS_ROCE_IDX_HOP_NUM			1
+#define HNS_ROCE_SQWQE_HOP_NUM			2
+#define HNS_ROCE_EXT_SGE_HOP_NUM		1
+#define HNS_ROCE_RQWQE_HOP_NUM			2
 
+#define HNS_ROCE_BA_PG_SZ_SUPPORTED_256K	6
+#define HNS_ROCE_BA_PG_SZ_SUPPORTED_16K		2
 #define HNS_ROCE_V2_GID_INDEX_NUM		256
 
 #define HNS_ROCE_V2_TABLE_CHUNK_SIZE		(1 << 18)
@@ -237,6 +244,7 @@
 	HNS_ROCE_OPC_CFG_EXT_LLM			= 0x8403,
 	HNS_ROCE_OPC_CFG_TMOUT_LLM			= 0x8404,
 	HNS_ROCE_OPC_QUERY_PF_TIMER_RES			= 0x8406,
+	HNS_ROCE_OPC_QUERY_PF_CAPS_NUM                  = 0x8408,
 	HNS_ROCE_OPC_CFG_SGID_TB			= 0x8500,
 	HNS_ROCE_OPC_CFG_SMAC_TB			= 0x8501,
 	HNS_ROCE_OPC_POST_MB				= 0x8504,
@@ -643,7 +651,7 @@
 #define	V2_QPC_BYTE_76_ATE_S 27
 
 #define	V2_QPC_BYTE_76_RQIE_S 28
-
+#define	V2_QPC_BYTE_76_EXT_ATE_S 29
 #define	V2_QPC_BYTE_76_RQ_VLAN_EN_S 30
 #define	V2_QPC_BYTE_80_RX_CQN_S 0
 #define V2_QPC_BYTE_80_RX_CQN_M GENMASK(23, 0)
@@ -1569,6 +1577,155 @@
 #define CFG_SMAC_TB_VF_SMAC_H_S 0
 #define CFG_SMAC_TB_VF_SMAC_H_M GENMASK(15, 0)
 
+#define HNS_ROCE_QUERY_PF_CAPS_CMD_NUM 5
+struct hns_roce_query_pf_caps_a {
+	u8 number_ports;
+	u8 local_ca_ack_delay;
+	__le16 max_sq_sg;
+	__le16 max_sq_inline;
+	__le16 max_rq_sg;
+	__le32 max_extend_sg;
+	__le16 num_qpc_timer;
+	__le16 num_cqc_timer;
+	__le16 max_srq_sges;
+	u8 num_aeq_vectors;
+	u8 num_other_vectors;
+	u8 max_sq_desc_sz;
+	u8 max_rq_desc_sz;
+	u8 max_srq_desc_sz;
+	u8 cq_entry_sz;
+};
+
+struct hns_roce_query_pf_caps_b {
+	u8 mtpt_entry_sz;
+	u8 irrl_entry_sz;
+	u8 trrl_entry_sz;
+	u8 cqc_entry_sz;
+	u8 srqc_entry_sz;
+	u8 idx_entry_sz;
+	u8 scc_ctx_entry_sz;
+	u8 max_mtu;
+	__le16 qpc_entry_sz;
+	__le16 qpc_timer_entry_sz;
+	__le16 cqc_timer_entry_sz;
+	u8 min_cqes;
+	u8 min_wqes;
+	__le32 page_size_cap;
+	u8 pkey_table_len;
+	u8 phy_num_uars;
+	u8 ctx_hop_num;
+	u8 pbl_hop_num;
+};
+
+struct hns_roce_query_pf_caps_c {
+	__le32 cap_flags_num_pds;
+	__le32 max_gid_num_cqs;
+	__le32 cq_depth;
+	__le32 num_mrws;
+	__le32 ord_num_qps;
+	__le16 sq_depth;
+	__le16 rq_depth;
+};
+
+#define V2_QUERY_PF_CAPS_C_NUM_PDS_S 0
+#define V2_QUERY_PF_CAPS_C_NUM_PDS_M GENMASK(19, 0)
+
+#define V2_QUERY_PF_CAPS_C_CAP_FLAGS_S 20
+#define V2_QUERY_PF_CAPS_C_CAP_FLAGS_M GENMASK(31, 20)
+
+#define V2_QUERY_PF_CAPS_C_NUM_CQS_S 0
+#define V2_QUERY_PF_CAPS_C_NUM_CQS_M GENMASK(19, 0)
+
+#define V2_QUERY_PF_CAPS_C_MAX_GID_S 20
+#define V2_QUERY_PF_CAPS_C_MAX_GID_M GENMASK(28, 20)
+
+#define V2_QUERY_PF_CAPS_C_CQ_DEPTH_S 0
+#define V2_QUERY_PF_CAPS_C_CQ_DEPTH_M GENMASK(22, 0)
+
+#define V2_QUERY_PF_CAPS_C_NUM_MRWS_S 0
+#define V2_QUERY_PF_CAPS_C_NUM_MRWS_M GENMASK(19, 0)
+
+#define V2_QUERY_PF_CAPS_C_NUM_QPS_S 0
+#define V2_QUERY_PF_CAPS_C_NUM_QPS_M GENMASK(19, 0)
+
+#define V2_QUERY_PF_CAPS_C_MAX_ORD_S 20
+#define V2_QUERY_PF_CAPS_C_MAX_ORD_M GENMASK(27, 20)
+
+struct hns_roce_query_pf_caps_d {
+	__le32 wq_hop_num_max_srqs;
+	__le16 srq_depth;
+	__le16 rsv;
+	__le32 num_ceqs_ceq_depth;
+	__le32 arm_st_aeq_depth;
+	__le32 num_uars_rsv_pds;
+	__le32 rsv_uars_rsv_qps;
+};
+#define V2_QUERY_PF_CAPS_D_NUM_SRQS_S 0
+#define V2_QUERY_PF_CAPS_D_NUM_SRQS_M GENMASK(20, 0)
+
+#define V2_QUERY_PF_CAPS_D_RQWQE_HOP_NUM_S 20
+#define V2_QUERY_PF_CAPS_D_RQWQE_HOP_NUM_M GENMASK(21, 20)
+
+#define V2_QUERY_PF_CAPS_D_EX_SGE_HOP_NUM_S 22
+#define V2_QUERY_PF_CAPS_D_EX_SGE_HOP_NUM_M GENMASK(23, 22)
+
+#define V2_QUERY_PF_CAPS_D_SQWQE_HOP_NUM_S 24
+#define V2_QUERY_PF_CAPS_D_SQWQE_HOP_NUM_M GENMASK(25, 24)
+
+
+#define V2_QUERY_PF_CAPS_D_CEQ_DEPTH_S 0
+#define V2_QUERY_PF_CAPS_D_CEQ_DEPTH_M GENMASK(21, 0)
+
+#define V2_QUERY_PF_CAPS_D_NUM_CEQS_S 22
+#define V2_QUERY_PF_CAPS_D_NUM_CEQS_M GENMASK(31, 22)
+
+#define V2_QUERY_PF_CAPS_D_AEQ_DEPTH_S 0
+#define V2_QUERY_PF_CAPS_D_AEQ_DEPTH_M GENMASK(21, 0)
+
+#define V2_QUERY_PF_CAPS_D_AEQ_ARM_ST_S 22
+#define V2_QUERY_PF_CAPS_D_AEQ_ARM_ST_M GENMASK(23, 22)
+
+#define V2_QUERY_PF_CAPS_D_CEQ_ARM_ST_S 24
+#define V2_QUERY_PF_CAPS_D_CEQ_ARM_ST_M GENMASK(25, 24)
+
+#define V2_QUERY_PF_CAPS_D_RSV_PDS_S 0
+#define V2_QUERY_PF_CAPS_D_RSV_PDS_M GENMASK(19, 0)
+
+#define V2_QUERY_PF_CAPS_D_NUM_UARS_S 20
+#define V2_QUERY_PF_CAPS_D_NUM_UARS_M GENMASK(27, 20)
+
+#define V2_QUERY_PF_CAPS_D_RSV_QPS_S 0
+#define V2_QUERY_PF_CAPS_D_RSV_QPS_M GENMASK(19, 0)
+
+#define V2_QUERY_PF_CAPS_D_RSV_UARS_S 20
+#define V2_QUERY_PF_CAPS_D_RSV_UARS_M GENMASK(27, 20)
+
+struct hns_roce_query_pf_caps_e {
+	__le32 chunk_size_shift_rsv_mrws;
+	__le32 rsv_cqs;
+	__le32 rsv_srqs;
+	__le32 rsv_lkey;
+	__le16 ceq_max_cnt;
+	__le16 ceq_period;
+	__le16 aeq_max_cnt;
+	__le16 aeq_period;
+};
+
+#define V2_QUERY_PF_CAPS_E_RSV_MRWS_S 0
+#define V2_QUERY_PF_CAPS_E_RSV_MRWS_M GENMASK(19, 0)
+
+#define V2_QUERY_PF_CAPS_E_CHUNK_SIZE_SHIFT_S 20
+#define V2_QUERY_PF_CAPS_E_CHUNK_SIZE_SHIFT_M GENMASK(31, 20)
+
+#define V2_QUERY_PF_CAPS_E_RSV_CQS_S 0
+#define V2_QUERY_PF_CAPS_E_RSV_CQS_M GENMASK(19, 0)
+
+#define V2_QUERY_PF_CAPS_E_RSV_SRQS_S 0
+#define V2_QUERY_PF_CAPS_E_RSV_SRQS_M GENMASK(19, 0)
+
+#define V2_QUERY_PF_CAPS_E_RSV_LKEYS_S 0
+#define V2_QUERY_PF_CAPS_E_RSV_LKEYS_M GENMASK(19, 0)
+
 struct hns_roce_cmq_desc {
 	__le16 opcode;
 	__le16 flag;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hns/hns_roce_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hns/hns_roce_main.c
@@ -90,7 +90,7 @@
 static int hns_roce_del_gid(const struct ib_gid_attr *attr, void **context)
 {
 	struct hns_roce_dev *hr_dev = to_hr_dev(attr->device);
-	struct ib_gid_attr zattr = { };
+	struct ib_gid_attr zattr = {};
 	u8 port = attr->port_num - 1;
 	int ret;
 
@@ -111,7 +111,7 @@
 
 	netdev = hr_dev->iboe.netdevs[port];
 	if (!netdev) {
-		dev_err(dev, "port(%d) can't find netdev\n", port);
+		dev_err(dev, "Can't find netdev on port(%u)!\n", port);
 		return -ENODEV;
 	}
 
@@ -198,7 +198,7 @@
 				  IB_DEVICE_RC_RNR_NAK_GEN;
 	props->max_send_sge = hr_dev->caps.max_sq_sg;
 	props->max_recv_sge = hr_dev->caps.max_rq_sg;
-	props->max_sge_rd = 1;
+	props->max_sge_rd = hr_dev->caps.max_sq_sg;
 	props->max_cq = hr_dev->caps.num_cqs;
 	props->max_cqe = hr_dev->caps.max_cqes;
 	props->max_mr = hr_dev->caps.num_mtpts;
@@ -210,7 +210,7 @@
 	props->max_pkeys = 1;
 	props->local_ca_ack_delay = hr_dev->caps.local_ca_ack_delay;
 	if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_SRQ) {
-		props->max_srq = hr_dev->caps.max_srqs;
+		props->max_srq = hr_dev->caps.num_srqs;
 		props->max_srq_wr = hr_dev->caps.max_srq_wrs;
 		props->max_srq_sge = hr_dev->caps.max_srq_sges;
 	}
@@ -253,17 +253,18 @@
 	net_dev = hr_dev->iboe.netdevs[port];
 	if (!net_dev) {
 		spin_unlock_irqrestore(&hr_dev->iboe.lock, flags);
-		dev_err(dev, "find netdev %d failed!\r\n", port);
+		dev_err(dev, "Find netdev %u failed!\n", port);
 		return -EINVAL;
 	}
 
 	mtu = iboe_get_mtu(net_dev->mtu);
 	props->active_mtu = mtu ? min(props->max_mtu, mtu) : IB_MTU_256;
-	props->state = (netif_running(net_dev) && netif_carrier_ok(net_dev)) ?
-			IB_PORT_ACTIVE : IB_PORT_DOWN;
-	props->phys_state = (props->state == IB_PORT_ACTIVE) ?
-			     IB_PORT_PHYS_STATE_LINK_UP :
-			     IB_PORT_PHYS_STATE_DISABLED;
+	props->state = netif_running(net_dev) && netif_carrier_ok(net_dev) ?
+			       IB_PORT_ACTIVE :
+			       IB_PORT_DOWN;
+	props->phys_state = props->state == IB_PORT_ACTIVE ?
+				    IB_PORT_PHYS_STATE_LINK_UP :
+				    IB_PORT_PHYS_STATE_DISABLED;
 
 	spin_unlock_irqrestore(&hr_dev->iboe.lock, flags);
 
@@ -279,6 +280,9 @@
 static int hns_roce_query_pkey(struct ib_device *ib_dev, u8 port, u16 index,
 			       u16 *pkey)
 {
+	if (index > 0)
+		return -EINVAL;
+
 	*pkey = PKEY_ID;
 
 	return 0;
@@ -301,12 +305,6 @@
 	return 0;
 }
 
-static int hns_roce_modify_port(struct ib_device *ib_dev, u8 port_num, int mask,
-				struct ib_port_modify *props)
-{
-	return 0;
-}
-
 static int hns_roce_alloc_ucontext(struct ib_ucontext *uctx,
 				   struct ib_udata *udata)
 {
@@ -359,7 +357,8 @@
 		return rdma_user_mmap_io(context, vma,
 					 to_hr_ucontext(context)->uar.pfn,
 					 PAGE_SIZE,
-					 pgprot_noncached(vma->vm_page_prot));
+					 pgprot_device(vma->vm_page_prot),
+					 NULL);
 
 	/* vm_pgoff: 1 -- TPTR */
 	case 1:
@@ -372,7 +371,8 @@
 		return rdma_user_mmap_io(context, vma,
 					 hr_dev->tptr_dma_addr >> PAGE_SHIFT,
 					 hr_dev->tptr_size,
-					 vma->vm_page_prot);
+					 vma->vm_page_prot,
+					 NULL);
 
 	default:
 		return -EINVAL;
@@ -423,14 +423,14 @@
 	.alloc_pd = hns_roce_alloc_pd,
 	.alloc_ucontext = hns_roce_alloc_ucontext,
 	.create_ah = hns_roce_create_ah,
-	.create_cq = hns_roce_ib_create_cq,
+	.create_cq = hns_roce_create_cq,
 	.create_qp = hns_roce_create_qp,
 	.dealloc_pd = hns_roce_dealloc_pd,
 	.dealloc_ucontext = hns_roce_dealloc_ucontext,
 	.del_gid = hns_roce_del_gid,
 	.dereg_mr = hns_roce_dereg_mr,
 	.destroy_ah = hns_roce_destroy_ah,
-	.destroy_cq = hns_roce_ib_destroy_cq,
+	.destroy_cq = hns_roce_destroy_cq,
 	.disassociate_ucontext = hns_roce_disassociate_ucontext,
 	.fill_res_entry = hns_roce_fill_res_entry,
 	.get_dma_mr = hns_roce_get_dma_mr,
@@ -438,7 +438,6 @@
 	.get_port_immutable = hns_roce_port_immutable,
 	.mmap = hns_roce_mmap,
 	.modify_device = hns_roce_modify_device,
-	.modify_port = hns_roce_modify_port,
 	.modify_qp = hns_roce_modify_qp,
 	.query_ah = hns_roce_query_ah,
 	.query_device = hns_roce_query_device,
@@ -486,13 +485,13 @@
 
 	ib_dev = &hr_dev->ib_dev;
 
-	ib_dev->node_type		= RDMA_NODE_IB_CA;
-	ib_dev->dev.parent		= dev;
+	ib_dev->node_type = RDMA_NODE_IB_CA;
+	ib_dev->dev.parent = dev;
 
-	ib_dev->phys_port_cnt		= hr_dev->caps.num_ports;
-	ib_dev->local_dma_lkey		= hr_dev->caps.reserved_lkey;
-	ib_dev->num_comp_vectors	= hr_dev->caps.num_comp_vectors;
-	ib_dev->uverbs_cmd_mask		=
+	ib_dev->phys_port_cnt = hr_dev->caps.num_ports;
+	ib_dev->local_dma_lkey = hr_dev->caps.reserved_lkey;
+	ib_dev->num_comp_vectors = hr_dev->caps.num_comp_vectors;
+	ib_dev->uverbs_cmd_mask =
 		(1ULL << IB_USER_VERBS_CMD_GET_CONTEXT) |
 		(1ULL << IB_USER_VERBS_CMD_QUERY_DEVICE) |
 		(1ULL << IB_USER_VERBS_CMD_QUERY_PORT) |
@@ -508,8 +507,7 @@
 		(1ULL << IB_USER_VERBS_CMD_QUERY_QP) |
 		(1ULL << IB_USER_VERBS_CMD_DESTROY_QP);
 
-	ib_dev->uverbs_ex_cmd_mask |=
-		(1ULL << IB_USER_VERBS_EX_CMD_MODIFY_CQ);
+	ib_dev->uverbs_ex_cmd_mask |= (1ULL << IB_USER_VERBS_EX_CMD_MODIFY_CQ);
 
 	if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_REREG_MR) {
 		ib_dev->uverbs_cmd_mask |= (1ULL << IB_USER_VERBS_CMD_REREG_MR);
@@ -594,11 +592,13 @@
 
 	if (hns_roce_check_whether_mhop(hr_dev, HEM_TYPE_CQE)) {
 		ret = hns_roce_init_hem_table(hr_dev,
-				      &hr_dev->mr_table.mtt_cqe_table,
-				      HEM_TYPE_CQE, hr_dev->caps.mtt_entry_sz,
-				      hr_dev->caps.num_cqe_segs, 1);
+					      &hr_dev->mr_table.mtt_cqe_table,
+					      HEM_TYPE_CQE,
+					      hr_dev->caps.mtt_entry_sz,
+					      hr_dev->caps.num_cqe_segs, 1);
 		if (ret) {
-			dev_err(dev, "Failed to init MTT CQE context memory, aborting.\n");
+			dev_err(dev,
+				"Failed to init CQE context memory, aborting.\n");
 			goto err_unmap_cqe;
 		}
 	}
@@ -638,7 +638,7 @@
 					      hr_dev->caps.num_qps, 1);
 		if (ret) {
 			dev_err(dev,
-			       "Failed to init trrl_table memory, aborting.\n");
+				"Failed to init trrl_table memory, aborting.\n");
 			goto err_unmap_irrl;
 		}
 	}
@@ -658,7 +658,7 @@
 					      hr_dev->caps.num_srqs, 1);
 		if (ret) {
 			dev_err(dev,
-			      "Failed to init SRQ context memory, aborting.\n");
+				"Failed to init SRQ context memory, aborting.\n");
 			goto err_unmap_cq;
 		}
 	}
@@ -697,33 +697,31 @@
 					      hr_dev->caps.num_qps, 1);
 		if (ret) {
 			dev_err(dev,
-			      "Failed to init SCC context memory, aborting.\n");
+				"Failed to init SCC context memory, aborting.\n");
 			goto err_unmap_idx;
 		}
 	}
 
 	if (hr_dev->caps.qpc_timer_entry_sz) {
-		ret = hns_roce_init_hem_table(hr_dev,
-					      &hr_dev->qpc_timer_table,
+		ret = hns_roce_init_hem_table(hr_dev, &hr_dev->qpc_timer_table,
 					      HEM_TYPE_QPC_TIMER,
 					      hr_dev->caps.qpc_timer_entry_sz,
 					      hr_dev->caps.num_qpc_timer, 1);
 		if (ret) {
 			dev_err(dev,
-			      "Failed to init QPC timer memory, aborting.\n");
+				"Failed to init QPC timer memory, aborting.\n");
 			goto err_unmap_ctx;
 		}
 	}
 
 	if (hr_dev->caps.cqc_timer_entry_sz) {
-		ret = hns_roce_init_hem_table(hr_dev,
-					      &hr_dev->cqc_timer_table,
+		ret = hns_roce_init_hem_table(hr_dev, &hr_dev->cqc_timer_table,
 					      HEM_TYPE_CQC_TIMER,
 					      hr_dev->caps.cqc_timer_entry_sz,
 					      hr_dev->caps.num_cqc_timer, 1);
 		if (ret) {
 			dev_err(dev,
-			      "Failed to init CQC timer memory, aborting.\n");
+				"Failed to init CQC timer memory, aborting.\n");
 			goto err_unmap_qpc_timer;
 		}
 	}
@@ -732,8 +730,7 @@
 
 err_unmap_qpc_timer:
 	if (hr_dev->caps.qpc_timer_entry_sz)
-		hns_roce_cleanup_hem_table(hr_dev,
-					   &hr_dev->qpc_timer_table);
+		hns_roce_cleanup_hem_table(hr_dev, &hr_dev->qpc_timer_table);
 
 err_unmap_ctx:
 	if (hr_dev->caps.sccc_entry_sz)
@@ -848,8 +845,7 @@
 	return 0;
 
 err_qp_table_free:
-	if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_SRQ)
-		hns_roce_cleanup_qp_table(hr_dev);
+	hns_roce_cleanup_qp_table(hr_dev);
 
 err_cq_table_free:
 	hns_roce_cleanup_cq_table(hr_dev);
@@ -868,6 +864,50 @@
 	return ret;
 }
 
+static void check_and_get_armed_cq(struct list_head *cq_list, struct ib_cq *cq)
+{
+	struct hns_roce_cq *hr_cq = to_hr_cq(cq);
+	unsigned long flags;
+
+	spin_lock_irqsave(&hr_cq->lock, flags);
+	if (cq->comp_handler) {
+		if (!hr_cq->is_armed) {
+			hr_cq->is_armed = 1;
+			list_add_tail(&hr_cq->node, cq_list);
+		}
+	}
+	spin_unlock_irqrestore(&hr_cq->lock, flags);
+}
+
+void hns_roce_handle_device_err(struct hns_roce_dev *hr_dev)
+{
+	struct hns_roce_qp *hr_qp;
+	struct hns_roce_cq *hr_cq;
+	struct list_head cq_list;
+	unsigned long flags_qp;
+	unsigned long flags;
+
+	INIT_LIST_HEAD(&cq_list);
+
+	spin_lock_irqsave(&hr_dev->qp_list_lock, flags);
+	list_for_each_entry(hr_qp, &hr_dev->qp_list, node) {
+		spin_lock_irqsave(&hr_qp->sq.lock, flags_qp);
+		if (hr_qp->sq.tail != hr_qp->sq.head)
+			check_and_get_armed_cq(&cq_list, hr_qp->ibqp.send_cq);
+		spin_unlock_irqrestore(&hr_qp->sq.lock, flags_qp);
+
+		spin_lock_irqsave(&hr_qp->rq.lock, flags_qp);
+		if ((!hr_qp->ibqp.srq) && (hr_qp->rq.tail != hr_qp->rq.head))
+			check_and_get_armed_cq(&cq_list, hr_qp->ibqp.recv_cq);
+		spin_unlock_irqrestore(&hr_qp->rq.lock, flags_qp);
+	}
+
+	list_for_each_entry(hr_cq, &cq_list, node)
+		hns_roce_cq_completion(hr_dev, hr_cq->cqn);
+
+	spin_unlock_irqrestore(&hr_dev->qp_list_lock, flags);
+}
+
 int hns_roce_init(struct hns_roce_dev *hr_dev)
 {
 	int ret;
@@ -938,6 +978,9 @@
 		}
 	}
 
+	INIT_LIST_HEAD(&hr_dev->qp_list);
+	spin_lock_init(&hr_dev->qp_list_lock);
+
 	ret = hns_roce_register_device(hr_dev);
 	if (ret)
 		goto error_failed_register_device;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hns/hns_roce_mr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hns/hns_roce_mr.c
@@ -48,21 +48,21 @@
 	return (key << 24) | (key >> 8);
 }
 
-static int hns_roce_sw2hw_mpt(struct hns_roce_dev *hr_dev,
-			      struct hns_roce_cmd_mailbox *mailbox,
-			      unsigned long mpt_index)
+static int hns_roce_hw_create_mpt(struct hns_roce_dev *hr_dev,
+				  struct hns_roce_cmd_mailbox *mailbox,
+				  unsigned long mpt_index)
 {
 	return hns_roce_cmd_mbox(hr_dev, mailbox->dma, 0, mpt_index, 0,
-				 HNS_ROCE_CMD_SW2HW_MPT,
+				 HNS_ROCE_CMD_CREATE_MPT,
 				 HNS_ROCE_CMD_TIMEOUT_MSECS);
 }
 
-int hns_roce_hw2sw_mpt(struct hns_roce_dev *hr_dev,
-			      struct hns_roce_cmd_mailbox *mailbox,
-			      unsigned long mpt_index)
+int hns_roce_hw_destroy_mpt(struct hns_roce_dev *hr_dev,
+			    struct hns_roce_cmd_mailbox *mailbox,
+			    unsigned long mpt_index)
 {
 	return hns_roce_cmd_mbox(hr_dev, 0, mailbox ? mailbox->dma : 0,
-				 mpt_index, !mailbox, HNS_ROCE_CMD_HW2SW_MPT,
+				 mpt_index, !mailbox, HNS_ROCE_CMD_DESTROY_MPT,
 				 HNS_ROCE_CMD_TIMEOUT_MSECS);
 }
 
@@ -83,7 +83,7 @@
 		}
 	}
 	spin_unlock(&buddy->lock);
-	return -1;
+	return -EINVAL;
 
  found:
 	clear_bit(*seg, buddy->bits[o]);
@@ -206,13 +206,14 @@
 	}
 
 	ret = hns_roce_buddy_alloc(buddy, order, seg);
-	if (ret == -1)
-		return -1;
+	if (ret)
+		return ret;
 
-	if (hns_roce_table_get_range(hr_dev, table, *seg,
-				     *seg + (1 << order) - 1)) {
+	ret = hns_roce_table_get_range(hr_dev, table, *seg,
+				       *seg + (1 << order) - 1);
+	if (ret) {
 		hns_roce_buddy_free(buddy, *seg, order);
-		return -1;
+		return ret;
 	}
 
 	return 0;
@@ -578,7 +579,7 @@
 
 	/* Allocate a key for mr from mr_table */
 	ret = hns_roce_bitmap_alloc(&hr_dev->mr_table.mtpt_bitmap, &index);
-	if (ret == -1)
+	if (ret)
 		return -ENOMEM;
 
 	mr->iova = iova;			/* MR va starting addr */
@@ -707,10 +708,11 @@
 	int ret;
 
 	if (mr->enabled) {
-		ret = hns_roce_hw2sw_mpt(hr_dev, NULL, key_to_hw_index(mr->key)
-					 & (hr_dev->caps.num_mtpts - 1));
+		ret = hns_roce_hw_destroy_mpt(hr_dev, NULL,
+					      key_to_hw_index(mr->key) &
+					      (hr_dev->caps.num_mtpts - 1));
 		if (ret)
-			dev_warn(dev, "HW2SW_MPT failed (%d)\n", ret);
+			dev_warn(dev, "DESTROY_MPT failed (%d)\n", ret);
 	}
 
 	if (mr->size != ~0ULL) {
@@ -763,10 +765,10 @@
 		goto err_page;
 	}
 
-	ret = hns_roce_sw2hw_mpt(hr_dev, mailbox,
-				 mtpt_idx & (hr_dev->caps.num_mtpts - 1));
+	ret = hns_roce_hw_create_mpt(hr_dev, mailbox,
+				     mtpt_idx & (hr_dev->caps.num_mtpts - 1));
 	if (ret) {
-		dev_err(dev, "SW2HW_MPT failed (%d)\n", ret);
+		dev_err(dev, "CREATE_MPT failed (%d)\n", ret);
 		goto err_page;
 	}
 
@@ -1062,8 +1064,8 @@
 		if (!(npage % (1 << (mtt->page_shift - PAGE_SHIFT)))) {
 			if (page_addr & ((1 << mtt->page_shift) - 1)) {
 				dev_err(dev,
-					"page_addr 0x%llx is not page_shift %d alignment!\n",
-					page_addr, mtt->page_shift);
+					"page_addr is not page_shift %d alignment!\n",
+					mtt->page_shift);
 				ret = -EINVAL;
 				goto out;
 			}
@@ -1143,7 +1145,7 @@
 	if (!mr)
 		return ERR_PTR(-ENOMEM);
 
-	mr->umem = ib_umem_get(udata, start, length, access_flags, 0);
+	mr->umem = ib_umem_get(pd->device, start, length, access_flags);
 	if (IS_ERR(mr->umem)) {
 		ret = PTR_ERR(mr->umem);
 		goto err_free;
@@ -1228,7 +1230,7 @@
 	}
 	ib_umem_release(mr->umem);
 
-	mr->umem = ib_umem_get(udata, start, length, mr_access_flags, 0);
+	mr->umem = ib_umem_get(ibmr->device, start, length, mr_access_flags);
 	if (IS_ERR(mr->umem)) {
 		ret = PTR_ERR(mr->umem);
 		mr->umem = NULL;
@@ -1308,9 +1310,9 @@
 	if (ret)
 		goto free_cmd_mbox;
 
-	ret = hns_roce_hw2sw_mpt(hr_dev, NULL, mtpt_idx);
+	ret = hns_roce_hw_destroy_mpt(hr_dev, NULL, mtpt_idx);
 	if (ret)
-		dev_warn(dev, "HW2SW_MPT failed (%d)\n", ret);
+		dev_warn(dev, "DESTROY_MPT failed (%d)\n", ret);
 
 	mr->enabled = 0;
 
@@ -1332,9 +1334,9 @@
 			goto free_cmd_mbox;
 	}
 
-	ret = hns_roce_sw2hw_mpt(hr_dev, mailbox, mtpt_idx);
+	ret = hns_roce_hw_create_mpt(hr_dev, mailbox, mtpt_idx);
 	if (ret) {
-		dev_err(dev, "SW2HW_MPT failed (%d)\n", ret);
+		dev_err(dev, "CREATE_MPT failed (%d)\n", ret);
 		ib_umem_release(mr->umem);
 		goto free_cmd_mbox;
 	}
@@ -1448,10 +1450,11 @@
 	int ret;
 
 	if (mw->enabled) {
-		ret = hns_roce_hw2sw_mpt(hr_dev, NULL, key_to_hw_index(mw->rkey)
-					 & (hr_dev->caps.num_mtpts - 1));
+		ret = hns_roce_hw_destroy_mpt(hr_dev, NULL,
+					      key_to_hw_index(mw->rkey) &
+					      (hr_dev->caps.num_mtpts - 1));
 		if (ret)
-			dev_warn(dev, "MW HW2SW_MPT failed (%d)\n", ret);
+			dev_warn(dev, "MW DESTROY_MPT failed (%d)\n", ret);
 
 		hns_roce_table_put(hr_dev, &hr_dev->mr_table.mtpt_table,
 				   key_to_hw_index(mw->rkey));
@@ -1487,10 +1490,10 @@
 		goto err_page;
 	}
 
-	ret = hns_roce_sw2hw_mpt(hr_dev, mailbox,
-				 mtpt_idx & (hr_dev->caps.num_mtpts - 1));
+	ret = hns_roce_hw_create_mpt(hr_dev, mailbox,
+				     mtpt_idx & (hr_dev->caps.num_mtpts - 1));
 	if (ret) {
-		dev_err(dev, "MW sw2hw_mpt failed (%d)\n", ret);
+		dev_err(dev, "MW CREATE_MPT failed (%d)\n", ret);
 		goto err_page;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hns/hns_roce_pd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hns/hns_roce_pd.c
@@ -96,7 +96,7 @@
 
 	/* Using bitmap to manager UAR index */
 	ret = hns_roce_bitmap_alloc(&hr_dev->uar_table.bitmap, &uar->logic_idx);
-	if (ret == -1)
+	if (ret)
 		return -ENOMEM;
 
 	if (uar->logic_idx > 0 && hr_dev->caps.phy_num_uars > 1)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hns/hns_roce_qp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hns/hns_roce_qp.c
@@ -43,6 +43,45 @@
 
 #define SQP_NUM				(2 * HNS_ROCE_MAX_PORTS)
 
+static void flush_work_handle(struct work_struct *work)
+{
+	struct hns_roce_work *flush_work = container_of(work,
+					struct hns_roce_work, work);
+	struct hns_roce_qp *hr_qp = container_of(flush_work,
+					struct hns_roce_qp, flush_work);
+	struct device *dev = flush_work->hr_dev->dev;
+	struct ib_qp_attr attr;
+	int attr_mask;
+	int ret;
+
+	attr_mask = IB_QP_STATE;
+	attr.qp_state = IB_QPS_ERR;
+
+	if (test_and_clear_bit(HNS_ROCE_FLUSH_FLAG, &hr_qp->flush_flag)) {
+		ret = hns_roce_modify_qp(&hr_qp->ibqp, &attr, attr_mask, NULL);
+		if (ret)
+			dev_err(dev, "Modify QP to error state failed(%d) during CQE flush\n",
+				ret);
+	}
+
+	/*
+	 * make sure we signal QP destroy leg that flush QP was completed
+	 * so that it can safely proceed ahead now and destroy QP
+	 */
+	if (atomic_dec_and_test(&hr_qp->refcount))
+		complete(&hr_qp->free);
+}
+
+void init_flush_work(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp)
+{
+	struct hns_roce_work *flush_work = &hr_qp->flush_work;
+
+	flush_work->hr_dev = hr_dev;
+	INIT_WORK(&flush_work->work, flush_work_handle);
+	atomic_inc(&hr_qp->refcount);
+	queue_work(hr_dev->irq_workq, &flush_work->work);
+}
+
 void hns_roce_qp_event(struct hns_roce_dev *hr_dev, u32 qpn, int event_type)
 {
 	struct device *dev = hr_dev->dev;
@@ -59,6 +98,15 @@
 		return;
 	}
 
+	if (hr_dev->hw_rev != HNS_ROCE_HW_VER1 &&
+	    (event_type == HNS_ROCE_EVENT_TYPE_WQ_CATAS_ERROR ||
+	     event_type == HNS_ROCE_EVENT_TYPE_INV_REQ_LOCAL_WQ_ERROR ||
+	     event_type == HNS_ROCE_EVENT_TYPE_LOCAL_WQ_ACCESS_ERROR)) {
+		qp->state = IB_QPS_ERR;
+		if (!test_and_set_bit(HNS_ROCE_FLUSH_FLAG, &qp->flush_flag))
+			init_flush_work(hr_dev, qp);
+	}
+
 	qp->event(qp, (enum hns_roce_event)event_type);
 
 	if (atomic_dec_and_test(&qp->refcount))
@@ -108,15 +156,34 @@
 	}
 }
 
-static int hns_roce_reserve_range_qp(struct hns_roce_dev *hr_dev, int cnt,
-				     int align, unsigned long *base)
+static int alloc_qpn(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp)
 {
-	struct hns_roce_qp_table *qp_table = &hr_dev->qp_table;
+	unsigned long num = 0;
+	int ret;
 
-	return hns_roce_bitmap_alloc_range(&qp_table->bitmap, cnt, align,
-					   base) ?
-		       -ENOMEM :
-		       0;
+	if (hr_qp->ibqp.qp_type == IB_QPT_GSI) {
+		/* when hw version is v1, the sqpn is allocated */
+		if (hr_dev->hw_rev == HNS_ROCE_HW_VER1)
+			num = HNS_ROCE_MAX_PORTS +
+			      hr_dev->iboe.phy_port[hr_qp->port];
+		else
+			num = 1;
+
+		hr_qp->doorbell_qpn = 1;
+	} else {
+		ret = hns_roce_bitmap_alloc_range(&hr_dev->qp_table.bitmap,
+						  1, 1, &num);
+		if (ret) {
+			ibdev_err(&hr_dev->ib_dev, "Failed to alloc bitmap\n");
+			return -ENOMEM;
+		}
+
+		hr_qp->doorbell_qpn = (u32)num;
+	}
+
+	hr_qp->qpn = num;
+
+	return 0;
 }
 
 enum hns_roce_qp_state to_hns_roce_state(enum ib_qp_state state)
@@ -139,50 +206,75 @@
 	}
 }
 
-static int hns_roce_gsi_qp_alloc(struct hns_roce_dev *hr_dev, unsigned long qpn,
-				 struct hns_roce_qp *hr_qp)
+static void add_qp_to_list(struct hns_roce_dev *hr_dev,
+			   struct hns_roce_qp *hr_qp,
+			   struct ib_cq *send_cq, struct ib_cq *recv_cq)
+{
+	struct hns_roce_cq *hr_send_cq, *hr_recv_cq;
+	unsigned long flags;
+
+	hr_send_cq = send_cq ? to_hr_cq(send_cq) : NULL;
+	hr_recv_cq = recv_cq ? to_hr_cq(recv_cq) : NULL;
+
+	spin_lock_irqsave(&hr_dev->qp_list_lock, flags);
+	hns_roce_lock_cqs(hr_send_cq, hr_recv_cq);
+
+	list_add_tail(&hr_qp->node, &hr_dev->qp_list);
+	if (hr_send_cq)
+		list_add_tail(&hr_qp->sq_node, &hr_send_cq->sq_list);
+	if (hr_recv_cq)
+		list_add_tail(&hr_qp->rq_node, &hr_recv_cq->rq_list);
+
+	hns_roce_unlock_cqs(hr_send_cq, hr_recv_cq);
+	spin_unlock_irqrestore(&hr_dev->qp_list_lock, flags);
+}
+
+static int hns_roce_qp_store(struct hns_roce_dev *hr_dev,
+			     struct hns_roce_qp *hr_qp,
+			     struct ib_qp_init_attr *init_attr)
 {
 	struct xarray *xa = &hr_dev->qp_table_xa;
 	int ret;
 
-	if (!qpn)
+	if (!hr_qp->qpn)
 		return -EINVAL;
 
-	hr_qp->qpn = qpn;
-	atomic_set(&hr_qp->refcount, 1);
-	init_completion(&hr_qp->free);
-
-	ret = xa_err(xa_store_irq(xa, hr_qp->qpn & (hr_dev->caps.num_qps - 1),
-				hr_qp, GFP_KERNEL));
+	ret = xa_err(xa_store_irq(xa, hr_qp->qpn, hr_qp, GFP_KERNEL));
 	if (ret)
-		dev_err(hr_dev->dev, "QPC xa_store failed\n");
+		dev_err(hr_dev->dev, "Failed to xa store for QPC\n");
+	else
+		/* add QP to device's QP list for softwc */
+		add_qp_to_list(hr_dev, hr_qp, init_attr->send_cq,
+			       init_attr->recv_cq);
 
 	return ret;
 }
 
-static int hns_roce_qp_alloc(struct hns_roce_dev *hr_dev, unsigned long qpn,
-			     struct hns_roce_qp *hr_qp)
+static int alloc_qpc(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp)
 {
 	struct hns_roce_qp_table *qp_table = &hr_dev->qp_table;
 	struct device *dev = hr_dev->dev;
 	int ret;
 
-	if (!qpn)
+	if (!hr_qp->qpn)
 		return -EINVAL;
 
-	hr_qp->qpn = qpn;
+	/* In v1 engine, GSI QP context is saved in the RoCE hw's register */
+	if (hr_qp->ibqp.qp_type == IB_QPT_GSI &&
+	    hr_dev->hw_rev == HNS_ROCE_HW_VER1)
+		return 0;
 
 	/* Alloc memory for QPC */
 	ret = hns_roce_table_get(hr_dev, &qp_table->qp_table, hr_qp->qpn);
 	if (ret) {
-		dev_err(dev, "QPC table get failed\n");
+		dev_err(dev, "Failed to get QPC table\n");
 		goto err_out;
 	}
 
 	/* Alloc memory for IRRL */
 	ret = hns_roce_table_get(hr_dev, &qp_table->irrl_table, hr_qp->qpn);
 	if (ret) {
-		dev_err(dev, "IRRL table get failed\n");
+		dev_err(dev, "Failed to get IRRL table\n");
 		goto err_put_qp;
 	}
 
@@ -191,7 +283,7 @@
 		ret = hns_roce_table_get(hr_dev, &qp_table->trrl_table,
 					 hr_qp->qpn);
 		if (ret) {
-			dev_err(dev, "TRRL table get failed\n");
+			dev_err(dev, "Failed to get TRRL table\n");
 			goto err_put_irrl;
 		}
 	}
@@ -201,22 +293,13 @@
 		ret = hns_roce_table_get(hr_dev, &qp_table->sccc_table,
 					 hr_qp->qpn);
 		if (ret) {
-			dev_err(dev, "SCC CTX table get failed\n");
+			dev_err(dev, "Failed to get SCC CTX table\n");
 			goto err_put_trrl;
 		}
 	}
 
-	ret = hns_roce_gsi_qp_alloc(hr_dev, qpn, hr_qp);
-	if (ret)
-		goto err_put_sccc;
-
 	return 0;
 
-err_put_sccc:
-	if (hr_dev->caps.sccc_entry_sz)
-		hns_roce_table_put(hr_dev, &qp_table->sccc_table,
-				   hr_qp->qpn);
-
 err_put_trrl:
 	if (hr_dev->caps.trrl_entry_sz)
 		hns_roce_table_put(hr_dev, &qp_table->trrl_table, hr_qp->qpn);
@@ -236,89 +319,85 @@
 	struct xarray *xa = &hr_dev->qp_table_xa;
 	unsigned long flags;
 
+	list_del(&hr_qp->node);
+	list_del(&hr_qp->sq_node);
+	list_del(&hr_qp->rq_node);
+
 	xa_lock_irqsave(xa, flags);
 	__xa_erase(xa, hr_qp->qpn & (hr_dev->caps.num_qps - 1));
 	xa_unlock_irqrestore(xa, flags);
 }
 
-void hns_roce_qp_free(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp)
+static void free_qpc(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp)
 {
 	struct hns_roce_qp_table *qp_table = &hr_dev->qp_table;
 
-	if (atomic_dec_and_test(&hr_qp->refcount))
-		complete(&hr_qp->free);
-	wait_for_completion(&hr_qp->free);
+	/* In v1 engine, GSI QP context is saved in the RoCE hw's register */
+	if (hr_qp->ibqp.qp_type == IB_QPT_GSI &&
+	    hr_dev->hw_rev == HNS_ROCE_HW_VER1)
+		return;
 
-	if ((hr_qp->ibqp.qp_type) != IB_QPT_GSI) {
-		if (hr_dev->caps.trrl_entry_sz)
-			hns_roce_table_put(hr_dev, &qp_table->trrl_table,
-					   hr_qp->qpn);
-		hns_roce_table_put(hr_dev, &qp_table->irrl_table, hr_qp->qpn);
-	}
+	if (hr_dev->caps.trrl_entry_sz)
+		hns_roce_table_put(hr_dev, &qp_table->trrl_table, hr_qp->qpn);
+	hns_roce_table_put(hr_dev, &qp_table->irrl_table, hr_qp->qpn);
 }
 
-void hns_roce_release_range_qp(struct hns_roce_dev *hr_dev, int base_qpn,
-			       int cnt)
+static void free_qpn(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp)
 {
 	struct hns_roce_qp_table *qp_table = &hr_dev->qp_table;
 
-	if (base_qpn < hr_dev->caps.reserved_qps)
+	if (hr_qp->ibqp.qp_type == IB_QPT_GSI)
 		return;
 
-	hns_roce_bitmap_free_range(&qp_table->bitmap, base_qpn, cnt, BITMAP_RR);
+	if (hr_qp->qpn < hr_dev->caps.reserved_qps)
+		return;
+
+	hns_roce_bitmap_free_range(&qp_table->bitmap, hr_qp->qpn, 1, BITMAP_RR);
 }
 
-static int hns_roce_set_rq_size(struct hns_roce_dev *hr_dev,
+static int set_rq_size(struct hns_roce_dev *hr_dev,
 				struct ib_qp_cap *cap, bool is_user, int has_rq,
 				struct hns_roce_qp *hr_qp)
 {
-	struct device *dev = hr_dev->dev;
 	u32 max_cnt;
 
-	/* Check the validity of QP support capacity */
-	if (cap->max_recv_wr > hr_dev->caps.max_wqes ||
-	    cap->max_recv_sge > hr_dev->caps.max_rq_sg) {
-		dev_err(dev, "RQ WR or sge error!max_recv_wr=%d max_recv_sge=%d\n",
-			cap->max_recv_wr, cap->max_recv_sge);
-		return -EINVAL;
-	}
-
 	/* If srq exist, set zero for relative number of rq */
 	if (!has_rq) {
 		hr_qp->rq.wqe_cnt = 0;
 		hr_qp->rq.max_gs = 0;
 		cap->max_recv_wr = 0;
 		cap->max_recv_sge = 0;
-	} else {
-		if (is_user && (!cap->max_recv_wr || !cap->max_recv_sge)) {
-			dev_err(dev, "user space no need config max_recv_wr max_recv_sge\n");
-			return -EINVAL;
-		}
 
-		if (hr_dev->caps.min_wqes)
-			max_cnt = max(cap->max_recv_wr, hr_dev->caps.min_wqes);
-		else
-			max_cnt = cap->max_recv_wr;
+		return 0;
+	}
 
-		hr_qp->rq.wqe_cnt = roundup_pow_of_two(max_cnt);
+	/* Check the validity of QP support capacity */
+	if (!cap->max_recv_wr || cap->max_recv_wr > hr_dev->caps.max_wqes ||
+	    cap->max_recv_sge > hr_dev->caps.max_rq_sg) {
+		ibdev_err(&hr_dev->ib_dev, "RQ config error, depth=%u, sge=%d\n",
+			  cap->max_recv_wr, cap->max_recv_sge);
+		return -EINVAL;
+	}
 
-		if ((u32)hr_qp->rq.wqe_cnt > hr_dev->caps.max_wqes) {
-			dev_err(dev, "while setting rq size, rq.wqe_cnt too large\n");
-			return -EINVAL;
-		}
+	max_cnt = max(cap->max_recv_wr, hr_dev->caps.min_wqes);
 
-		max_cnt = max(1U, cap->max_recv_sge);
-		hr_qp->rq.max_gs = roundup_pow_of_two(max_cnt);
-		if (hr_dev->caps.max_rq_sg <= 2)
-			hr_qp->rq.wqe_shift =
-					ilog2(hr_dev->caps.max_rq_desc_sz);
-		else
-			hr_qp->rq.wqe_shift =
-					ilog2(hr_dev->caps.max_rq_desc_sz
-					      * hr_qp->rq.max_gs);
+	hr_qp->rq.wqe_cnt = roundup_pow_of_two(max_cnt);
+	if ((u32)hr_qp->rq.wqe_cnt > hr_dev->caps.max_wqes) {
+		ibdev_err(&hr_dev->ib_dev, "rq depth %u too large\n",
+			  cap->max_recv_wr);
+		return -EINVAL;
 	}
 
-	cap->max_recv_wr = hr_qp->rq.max_post = hr_qp->rq.wqe_cnt;
+	max_cnt = max(1U, cap->max_recv_sge);
+	hr_qp->rq.max_gs = roundup_pow_of_two(max_cnt);
+
+	if (hr_dev->caps.max_rq_sg <= HNS_ROCE_SGE_IN_WQE)
+		hr_qp->rq.wqe_shift = ilog2(hr_dev->caps.max_rq_desc_sz);
+	else
+		hr_qp->rq.wqe_shift = ilog2(hr_dev->caps.max_rq_desc_sz *
+					    hr_qp->rq.max_gs);
+
+	cap->max_recv_wr = hr_qp->rq.wqe_cnt;
 	cap->max_recv_sge = hr_qp->rq.max_gs;
 
 	return 0;
@@ -332,15 +411,14 @@
 	u8 max_sq_stride = ilog2(roundup_sq_stride);
 
 	/* Sanity check SQ size before proceeding */
-	if ((u32)(1 << ucmd->log_sq_bb_count) > hr_dev->caps.max_wqes ||
-	     ucmd->log_sq_stride > max_sq_stride ||
-	     ucmd->log_sq_stride < HNS_ROCE_IB_MIN_SQ_STRIDE) {
-		ibdev_err(&hr_dev->ib_dev, "check SQ size error!\n");
+	if (ucmd->log_sq_stride > max_sq_stride ||
+	    ucmd->log_sq_stride < HNS_ROCE_IB_MIN_SQ_STRIDE) {
+		ibdev_err(&hr_dev->ib_dev, "Failed to check SQ stride size\n");
 		return -EINVAL;
 	}
 
 	if (cap->max_send_sge > hr_dev->caps.max_sq_sg) {
-		ibdev_err(&hr_dev->ib_dev, "SQ sge error! max_send_sge=%d\n",
+		ibdev_err(&hr_dev->ib_dev, "Failed to check SQ SGE size %d\n",
 			  cap->max_send_sge);
 		return -EINVAL;
 	}
@@ -348,40 +426,43 @@
 	return 0;
 }
 
-static int hns_roce_set_user_sq_size(struct hns_roce_dev *hr_dev,
-				     struct ib_qp_cap *cap,
-				     struct hns_roce_qp *hr_qp,
-				     struct hns_roce_ib_create_qp *ucmd)
+static int set_user_sq_size(struct hns_roce_dev *hr_dev,
+			    struct ib_qp_cap *cap, struct hns_roce_qp *hr_qp,
+			    struct hns_roce_ib_create_qp *ucmd)
 {
 	u32 ex_sge_num;
 	u32 page_size;
 	u32 max_cnt;
 	int ret;
 
+	if (check_shl_overflow(1, ucmd->log_sq_bb_count, &hr_qp->sq.wqe_cnt) ||
+	    hr_qp->sq.wqe_cnt > hr_dev->caps.max_wqes)
+		return -EINVAL;
+
 	ret = check_sq_size_with_integrity(hr_dev, cap, ucmd);
 	if (ret) {
-		ibdev_err(&hr_dev->ib_dev, "Sanity check sq size failed\n");
+		ibdev_err(&hr_dev->ib_dev, "Failed to check user SQ size limit\n");
 		return ret;
 	}
 
-	hr_qp->sq.wqe_cnt = 1 << ucmd->log_sq_bb_count;
 	hr_qp->sq.wqe_shift = ucmd->log_sq_stride;
 
 	max_cnt = max(1U, cap->max_send_sge);
-	if (hr_dev->caps.max_sq_sg <= 2)
+	if (hr_dev->hw_rev == HNS_ROCE_HW_VER1)
 		hr_qp->sq.max_gs = roundup_pow_of_two(max_cnt);
 	else
 		hr_qp->sq.max_gs = max_cnt;
 
-	if (hr_qp->sq.max_gs > 2)
+	if (hr_qp->sq.max_gs > HNS_ROCE_SGE_IN_WQE)
 		hr_qp->sge.sge_cnt = roundup_pow_of_two(hr_qp->sq.wqe_cnt *
 							(hr_qp->sq.max_gs - 2));
 
-	if ((hr_qp->sq.max_gs > 2) && (hr_dev->pci_dev->revision == 0x20)) {
+	if (hr_qp->sq.max_gs > HNS_ROCE_SGE_IN_WQE &&
+	    hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP08_A) {
 		if (hr_qp->sge.sge_cnt > hr_dev->caps.max_extend_sg) {
-			dev_err(hr_dev->dev,
-				"The extended sge cnt error! sge_cnt=%d\n",
-				hr_qp->sge.sge_cnt);
+			ibdev_err(&hr_dev->ib_dev,
+				  "Failed to check extended SGE size limit %d\n",
+				  hr_qp->sge.sge_cnt);
 			return -EINVAL;
 		}
 	}
@@ -390,41 +471,39 @@
 	ex_sge_num = hr_qp->sge.sge_cnt;
 
 	/* Get buf size, SQ and RQ  are aligned to page_szie */
-	if (hr_dev->caps.max_sq_sg <= 2) {
-		hr_qp->buff_size = HNS_ROCE_ALOGN_UP((hr_qp->rq.wqe_cnt <<
+	if (hr_dev->hw_rev == HNS_ROCE_HW_VER1) {
+		hr_qp->buff_size = round_up((hr_qp->rq.wqe_cnt <<
 					     hr_qp->rq.wqe_shift), PAGE_SIZE) +
-				   HNS_ROCE_ALOGN_UP((hr_qp->sq.wqe_cnt <<
+				   round_up((hr_qp->sq.wqe_cnt <<
 					     hr_qp->sq.wqe_shift), PAGE_SIZE);
 
 		hr_qp->sq.offset = 0;
-		hr_qp->rq.offset = HNS_ROCE_ALOGN_UP((hr_qp->sq.wqe_cnt <<
+		hr_qp->rq.offset = round_up((hr_qp->sq.wqe_cnt <<
 					     hr_qp->sq.wqe_shift), PAGE_SIZE);
 	} else {
 		page_size = 1 << (hr_dev->caps.mtt_buf_pg_sz + PAGE_SHIFT);
 		hr_qp->sge.sge_cnt = ex_sge_num ?
 		   max(page_size / (1 << hr_qp->sge.sge_shift), ex_sge_num) : 0;
-		hr_qp->buff_size = HNS_ROCE_ALOGN_UP((hr_qp->rq.wqe_cnt <<
+		hr_qp->buff_size = round_up((hr_qp->rq.wqe_cnt <<
 					     hr_qp->rq.wqe_shift), page_size) +
-				   HNS_ROCE_ALOGN_UP((hr_qp->sge.sge_cnt <<
+				   round_up((hr_qp->sge.sge_cnt <<
 					     hr_qp->sge.sge_shift), page_size) +
-				   HNS_ROCE_ALOGN_UP((hr_qp->sq.wqe_cnt <<
+				   round_up((hr_qp->sq.wqe_cnt <<
 					     hr_qp->sq.wqe_shift), page_size);
 
 		hr_qp->sq.offset = 0;
 		if (ex_sge_num) {
-			hr_qp->sge.offset = HNS_ROCE_ALOGN_UP(
-							(hr_qp->sq.wqe_cnt <<
-							hr_qp->sq.wqe_shift),
-							page_size);
+			hr_qp->sge.offset = round_up((hr_qp->sq.wqe_cnt <<
+						      hr_qp->sq.wqe_shift),
+						     page_size);
 			hr_qp->rq.offset = hr_qp->sge.offset +
-					HNS_ROCE_ALOGN_UP((hr_qp->sge.sge_cnt <<
-						hr_qp->sge.sge_shift),
-						page_size);
+					   round_up((hr_qp->sge.sge_cnt <<
+						     hr_qp->sge.sge_shift),
+						    page_size);
 		} else {
-			hr_qp->rq.offset = HNS_ROCE_ALOGN_UP(
-							(hr_qp->sq.wqe_cnt <<
-							hr_qp->sq.wqe_shift),
-							page_size);
+			hr_qp->rq.offset = round_up((hr_qp->sq.wqe_cnt <<
+						     hr_qp->sq.wqe_shift),
+						    page_size);
 		}
 	}
 
@@ -528,13 +607,15 @@
 	}
 
 	/* ud sqwqe's sge use extend sge */
-	if (hr_dev->caps.max_sq_sg > 2 && hr_qp->ibqp.qp_type == IB_QPT_GSI) {
+	if (hr_dev->hw_rev != HNS_ROCE_HW_VER1 &&
+	    hr_qp->ibqp.qp_type == IB_QPT_GSI) {
 		hr_qp->sge.sge_cnt = roundup_pow_of_two(hr_qp->sq.wqe_cnt *
 				     hr_qp->sq.max_gs);
 		hr_qp->sge.sge_shift = 4;
 	}
 
-	if ((hr_qp->sq.max_gs > 2) && hr_dev->pci_dev->revision == 0x20) {
+	if (hr_qp->sq.max_gs > 2 &&
+	    hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP08_A) {
 		if (hr_qp->sge.sge_cnt > hr_dev->caps.max_extend_sg) {
 			dev_err(dev, "The extended sge cnt error! sge_cnt=%d\n",
 				hr_qp->sge.sge_cnt);
@@ -545,70 +626,65 @@
 	return 0;
 }
 
-static int hns_roce_set_kernel_sq_size(struct hns_roce_dev *hr_dev,
-				       struct ib_qp_cap *cap,
-				       struct hns_roce_qp *hr_qp)
+static int set_kernel_sq_size(struct hns_roce_dev *hr_dev,
+			      struct ib_qp_cap *cap, struct hns_roce_qp *hr_qp)
 {
-	struct device *dev = hr_dev->dev;
 	u32 page_size;
 	u32 max_cnt;
 	int size;
 	int ret;
 
-	if (cap->max_send_wr  > hr_dev->caps.max_wqes  ||
+	if (!cap->max_send_wr || cap->max_send_wr > hr_dev->caps.max_wqes ||
 	    cap->max_send_sge > hr_dev->caps.max_sq_sg ||
 	    cap->max_inline_data > hr_dev->caps.max_sq_inline) {
-		dev_err(dev, "SQ WR or sge or inline data error!\n");
+		ibdev_err(&hr_dev->ib_dev,
+			  "SQ WR or sge or inline data error!\n");
 		return -EINVAL;
 	}
 
 	hr_qp->sq.wqe_shift = ilog2(hr_dev->caps.max_sq_desc_sz);
 
-	if (hr_dev->caps.min_wqes)
-		max_cnt = max(cap->max_send_wr, hr_dev->caps.min_wqes);
-	else
-		max_cnt = cap->max_send_wr;
+	max_cnt = max(cap->max_send_wr, hr_dev->caps.min_wqes);
 
 	hr_qp->sq.wqe_cnt = roundup_pow_of_two(max_cnt);
 	if ((u32)hr_qp->sq.wqe_cnt > hr_dev->caps.max_wqes) {
-		dev_err(dev, "while setting kernel sq size, sq.wqe_cnt too large\n");
+		ibdev_err(&hr_dev->ib_dev,
+			  "while setting kernel sq size, sq.wqe_cnt too large\n");
 		return -EINVAL;
 	}
 
 	/* Get data_seg numbers */
 	max_cnt = max(1U, cap->max_send_sge);
-	if (hr_dev->caps.max_sq_sg <= 2)
+	if (hr_dev->hw_rev == HNS_ROCE_HW_VER1)
 		hr_qp->sq.max_gs = roundup_pow_of_two(max_cnt);
 	else
 		hr_qp->sq.max_gs = max_cnt;
 
 	ret = set_extend_sge_param(hr_dev, hr_qp);
 	if (ret) {
-		dev_err(dev, "set extend sge parameters fail\n");
+		ibdev_err(&hr_dev->ib_dev, "set extend sge parameters fail\n");
 		return ret;
 	}
 
 	/* Get buf size, SQ and RQ are aligned to PAGE_SIZE */
 	page_size = 1 << (hr_dev->caps.mtt_buf_pg_sz + PAGE_SHIFT);
 	hr_qp->sq.offset = 0;
-	size = HNS_ROCE_ALOGN_UP(hr_qp->sq.wqe_cnt << hr_qp->sq.wqe_shift,
-				 page_size);
+	size = round_up(hr_qp->sq.wqe_cnt << hr_qp->sq.wqe_shift, page_size);
 
-	if (hr_dev->caps.max_sq_sg > 2 && hr_qp->sge.sge_cnt) {
+	if (hr_dev->hw_rev != HNS_ROCE_HW_VER1 && hr_qp->sge.sge_cnt) {
 		hr_qp->sge.sge_cnt = max(page_size/(1 << hr_qp->sge.sge_shift),
-					(u32)hr_qp->sge.sge_cnt);
+					 (u32)hr_qp->sge.sge_cnt);
 		hr_qp->sge.offset = size;
-		size += HNS_ROCE_ALOGN_UP(hr_qp->sge.sge_cnt <<
-					  hr_qp->sge.sge_shift, page_size);
+		size += round_up(hr_qp->sge.sge_cnt << hr_qp->sge.sge_shift,
+				 page_size);
 	}
 
 	hr_qp->rq.offset = size;
-	size += HNS_ROCE_ALOGN_UP((hr_qp->rq.wqe_cnt << hr_qp->rq.wqe_shift),
-				  page_size);
+	size += round_up((hr_qp->rq.wqe_cnt << hr_qp->rq.wqe_shift), page_size);
 	hr_qp->buff_size = size;
 
 	/* Get wr and sge number which send */
-	cap->max_send_wr = hr_qp->sq.max_post = hr_qp->sq.wqe_cnt;
+	cap->max_send_wr = hr_qp->sq.wqe_cnt;
 	cap->max_send_sge = hr_qp->sq.max_gs;
 
 	/* We don't support inline sends for kernel QPs (yet) */
@@ -679,336 +755,447 @@
 	kfree(hr_qp->rq_inl_buf.wqe_list);
 }
 
-static int hns_roce_create_qp_common(struct hns_roce_dev *hr_dev,
-				     struct ib_pd *ib_pd,
-				     struct ib_qp_init_attr *init_attr,
-				     struct ib_udata *udata, unsigned long sqpn,
-				     struct hns_roce_qp *hr_qp)
+static int map_wqe_buf(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp,
+		       u32 page_shift, bool is_user)
 {
 	dma_addr_t *buf_list[ARRAY_SIZE(hr_qp->regions)] = { NULL };
-	struct device *dev = hr_dev->dev;
-	struct hns_roce_ib_create_qp ucmd;
-	struct hns_roce_ib_create_qp_resp resp = {};
-	struct hns_roce_ucontext *uctx = rdma_udata_to_drv_context(
-		udata, struct hns_roce_ucontext, ibucontext);
+	struct ib_device *ibdev = &hr_dev->ib_dev;
 	struct hns_roce_buf_region *r;
-	unsigned long qpn = 0;
-	u32 page_shift;
+	int region_count;
 	int buf_count;
 	int ret;
 	int i;
 
-	mutex_init(&hr_qp->mutex);
-	spin_lock_init(&hr_qp->sq.lock);
-	spin_lock_init(&hr_qp->rq.lock);
+	region_count = split_wqe_buf_region(hr_dev, hr_qp, hr_qp->regions,
+					ARRAY_SIZE(hr_qp->regions), page_shift);
 
-	hr_qp->state = IB_QPS_RESET;
-
-	hr_qp->ibqp.qp_type = init_attr->qp_type;
-
-	if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR)
-		hr_qp->sq_signal_bits = IB_SIGNAL_ALL_WR;
-	else
-		hr_qp->sq_signal_bits = IB_SIGNAL_REQ_WR;
-
-	ret = hns_roce_set_rq_size(hr_dev, &init_attr->cap, udata,
-				   hns_roce_qp_has_rq(init_attr), hr_qp);
+	/* alloc a tmp list to store WQE buffers address */
+	ret = hns_roce_alloc_buf_list(hr_qp->regions, buf_list, region_count);
 	if (ret) {
-		dev_err(dev, "hns_roce_set_rq_size failed\n");
-		goto err_out;
+		ibdev_err(ibdev, "Failed to alloc WQE buffer list\n");
+		return ret;
 	}
 
-	if ((hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_RQ_INLINE) &&
-	    hns_roce_qp_has_rq(init_attr)) {
-		ret = alloc_rq_inline_buf(hr_qp, init_attr);
-		if (ret) {
-			dev_err(dev, "allocate receive inline buffer failed\n");
-			goto err_out;
+	for (i = 0; i < region_count; i++) {
+		r = &hr_qp->regions[i];
+		if (is_user)
+			buf_count = hns_roce_get_umem_bufs(hr_dev, buf_list[i],
+					r->count, r->offset, hr_qp->umem,
+					page_shift);
+		else
+			buf_count = hns_roce_get_kmem_bufs(hr_dev, buf_list[i],
+					r->count, r->offset, &hr_qp->hr_buf);
+
+		if (buf_count != r->count) {
+			ibdev_err(ibdev, "Failed to get %s WQE buf, expect %d = %d.\n",
+				  is_user ? "user" : "kernel",
+				  r->count, buf_count);
+			ret = -ENOBUFS;
+			goto done;
 		}
 	}
 
-	page_shift = PAGE_SHIFT + hr_dev->caps.mtt_buf_pg_sz;
-	if (udata) {
-		if (ib_copy_from_udata(&ucmd, udata, sizeof(ucmd))) {
-			dev_err(dev, "ib_copy_from_udata error for create qp\n");
-			ret = -EFAULT;
-			goto err_alloc_rq_inline_buf;
-		}
+	hr_qp->wqe_bt_pg_shift = calc_wqe_bt_page_shift(hr_dev, hr_qp->regions,
+							region_count);
+	hns_roce_mtr_init(&hr_qp->mtr, PAGE_SHIFT + hr_qp->wqe_bt_pg_shift,
+			  page_shift);
+	ret = hns_roce_mtr_attach(hr_dev, &hr_qp->mtr, buf_list, hr_qp->regions,
+				  region_count);
+	if (ret)
+		ibdev_err(ibdev, "Failed to attatch WQE's mtr\n");
+
+	goto done;
+
+	hns_roce_mtr_cleanup(hr_dev, &hr_qp->mtr);
+done:
+	hns_roce_free_buf_list(buf_list, region_count);
 
-		ret = hns_roce_set_user_sq_size(hr_dev, &init_attr->cap, hr_qp,
-						&ucmd);
+	return ret;
+}
+
+static int alloc_qp_buf(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp,
+			struct ib_qp_init_attr *init_attr,
+			struct ib_udata *udata, unsigned long addr)
+{
+	u32 page_shift = PAGE_SHIFT + hr_dev->caps.mtt_buf_pg_sz;
+	struct ib_device *ibdev = &hr_dev->ib_dev;
+	bool is_rq_buf_inline;
+	int ret;
+
+	is_rq_buf_inline = (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_RQ_INLINE) &&
+			   hns_roce_qp_has_rq(init_attr);
+	if (is_rq_buf_inline) {
+		ret = alloc_rq_inline_buf(hr_qp, init_attr);
 		if (ret) {
-			dev_err(dev, "hns_roce_set_user_sq_size error for create qp\n");
-			goto err_alloc_rq_inline_buf;
+			ibdev_err(ibdev, "Failed to alloc inline RQ buffer\n");
+			return ret;
 		}
+	}
 
-		hr_qp->umem = ib_umem_get(udata, ucmd.buf_addr,
-					  hr_qp->buff_size, 0, 0);
+	if (udata) {
+		hr_qp->umem = ib_umem_get(ibdev, addr, hr_qp->buff_size, 0);
 		if (IS_ERR(hr_qp->umem)) {
-			dev_err(dev, "ib_umem_get error for create qp\n");
 			ret = PTR_ERR(hr_qp->umem);
-			goto err_alloc_rq_inline_buf;
-		}
-		hr_qp->region_cnt = split_wqe_buf_region(hr_dev, hr_qp,
-				hr_qp->regions, ARRAY_SIZE(hr_qp->regions),
-				page_shift);
-		ret = hns_roce_alloc_buf_list(hr_qp->regions, buf_list,
-					      hr_qp->region_cnt);
-		if (ret) {
-			dev_err(dev, "alloc buf_list error for create qp\n");
-			goto err_alloc_list;
+			goto err_inline;
 		}
+	} else {
+		ret = hns_roce_buf_alloc(hr_dev, hr_qp->buff_size,
+					 (1 << page_shift) * 2,
+					 &hr_qp->hr_buf, page_shift);
+		if (ret)
+			goto err_inline;
+	}
 
-		for (i = 0; i < hr_qp->region_cnt; i++) {
-			r = &hr_qp->regions[i];
-			buf_count = hns_roce_get_umem_bufs(hr_dev,
-					buf_list[i], r->count, r->offset,
-					hr_qp->umem, page_shift);
-			if (buf_count != r->count) {
-				dev_err(dev,
-					"get umem buf err, expect %d,ret %d.\n",
-					r->count, buf_count);
-				ret = -ENOBUFS;
-				goto err_get_bufs;
-			}
-		}
+	ret = map_wqe_buf(hr_dev, hr_qp, page_shift, udata);
+	if (ret)
+		goto err_alloc;
+
+	return 0;
+
+err_inline:
+	if (is_rq_buf_inline)
+		free_rq_inline_buf(hr_qp);
+
+err_alloc:
+	if (udata) {
+		ib_umem_release(hr_qp->umem);
+		hr_qp->umem = NULL;
+	} else {
+		hns_roce_buf_free(hr_dev, hr_qp->buff_size, &hr_qp->hr_buf);
+	}
 
-		if ((hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_SQ_RECORD_DB) &&
-		    (udata->inlen >= sizeof(ucmd)) &&
-		    (udata->outlen >= sizeof(resp)) &&
-		    hns_roce_qp_has_sq(init_attr)) {
-			ret = hns_roce_db_map_user(uctx, udata, ucmd.sdb_addr,
+	ibdev_err(ibdev, "Failed to alloc WQE buffer, ret %d.\n", ret);
+
+	return ret;
+}
+
+static void free_qp_buf(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp)
+{
+	hns_roce_mtr_cleanup(hr_dev, &hr_qp->mtr);
+	if (hr_qp->umem) {
+		ib_umem_release(hr_qp->umem);
+		hr_qp->umem = NULL;
+	}
+
+	if (hr_qp->hr_buf.nbufs > 0)
+		hns_roce_buf_free(hr_dev, hr_qp->buff_size, &hr_qp->hr_buf);
+
+	if ((hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_RQ_INLINE) &&
+	     hr_qp->rq.wqe_cnt)
+		free_rq_inline_buf(hr_qp);
+}
+
+static inline bool user_qp_has_sdb(struct hns_roce_dev *hr_dev,
+				   struct ib_qp_init_attr *init_attr,
+				   struct ib_udata *udata,
+				   struct hns_roce_ib_create_qp_resp *resp,
+				   struct hns_roce_ib_create_qp *ucmd)
+{
+	return ((hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_SQ_RECORD_DB) &&
+		udata->outlen >= offsetofend(typeof(*resp), cap_flags) &&
+		hns_roce_qp_has_sq(init_attr) &&
+		udata->inlen >= offsetofend(typeof(*ucmd), sdb_addr));
+}
+
+static inline bool user_qp_has_rdb(struct hns_roce_dev *hr_dev,
+				   struct ib_qp_init_attr *init_attr,
+				   struct ib_udata *udata,
+				   struct hns_roce_ib_create_qp_resp *resp)
+{
+	return ((hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_RECORD_DB) &&
+		udata->outlen >= offsetofend(typeof(*resp), cap_flags) &&
+		hns_roce_qp_has_rq(init_attr));
+}
+
+static inline bool kernel_qp_has_rdb(struct hns_roce_dev *hr_dev,
+				     struct ib_qp_init_attr *init_attr)
+{
+	return ((hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_RECORD_DB) &&
+		hns_roce_qp_has_rq(init_attr));
+}
+
+static int alloc_qp_db(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp,
+		       struct ib_qp_init_attr *init_attr,
+		       struct ib_udata *udata,
+		       struct hns_roce_ib_create_qp *ucmd,
+		       struct hns_roce_ib_create_qp_resp *resp)
+{
+	struct hns_roce_ucontext *uctx = rdma_udata_to_drv_context(
+		udata, struct hns_roce_ucontext, ibucontext);
+	struct ib_device *ibdev = &hr_dev->ib_dev;
+	int ret;
+
+	if (udata) {
+		if (user_qp_has_sdb(hr_dev, init_attr, udata, resp, ucmd)) {
+			ret = hns_roce_db_map_user(uctx, udata, ucmd->sdb_addr,
 						   &hr_qp->sdb);
 			if (ret) {
-				dev_err(dev, "sq record doorbell map failed!\n");
-				goto err_get_bufs;
+				ibdev_err(ibdev,
+					  "Failed to map user SQ doorbell\n");
+				goto err_out;
 			}
-
-			/* indicate kernel supports sq record db */
-			resp.cap_flags |= HNS_ROCE_SUPPORT_SQ_RECORD_DB;
 			hr_qp->sdb_en = 1;
+			resp->cap_flags |= HNS_ROCE_SUPPORT_SQ_RECORD_DB;
 		}
 
-		if ((hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_RECORD_DB) &&
-		    (udata->outlen >= sizeof(resp)) &&
-		    hns_roce_qp_has_rq(init_attr)) {
-			ret = hns_roce_db_map_user(uctx, udata, ucmd.db_addr,
+		if (user_qp_has_rdb(hr_dev, init_attr, udata, resp)) {
+			ret = hns_roce_db_map_user(uctx, udata, ucmd->db_addr,
 						   &hr_qp->rdb);
 			if (ret) {
-				dev_err(dev, "rq record doorbell map failed!\n");
-				goto err_sq_dbmap;
+				ibdev_err(ibdev,
+					  "Failed to map user RQ doorbell\n");
+				goto err_sdb;
 			}
-
-			/* indicate kernel supports rq record db */
-			resp.cap_flags |= HNS_ROCE_SUPPORT_RQ_RECORD_DB;
 			hr_qp->rdb_en = 1;
+			resp->cap_flags |= HNS_ROCE_SUPPORT_RQ_RECORD_DB;
 		}
 	} else {
-		if (init_attr->create_flags &
-		    IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK) {
-			dev_err(dev, "init_attr->create_flags error!\n");
-			ret = -EINVAL;
-			goto err_alloc_rq_inline_buf;
-		}
-
-		if (init_attr->create_flags & IB_QP_CREATE_IPOIB_UD_LSO) {
-			dev_err(dev, "init_attr->create_flags error!\n");
-			ret = -EINVAL;
-			goto err_alloc_rq_inline_buf;
-		}
-
-		/* Set SQ size */
-		ret = hns_roce_set_kernel_sq_size(hr_dev, &init_attr->cap,
-						  hr_qp);
-		if (ret) {
-			dev_err(dev, "hns_roce_set_kernel_sq_size error!\n");
-			goto err_alloc_rq_inline_buf;
-		}
-
 		/* QP doorbell register address */
 		hr_qp->sq.db_reg_l = hr_dev->reg_base + hr_dev->sdb_offset +
 				     DB_REG_OFFSET * hr_dev->priv_uar.index;
 		hr_qp->rq.db_reg_l = hr_dev->reg_base + hr_dev->odb_offset +
 				     DB_REG_OFFSET * hr_dev->priv_uar.index;
 
-		if ((hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_RECORD_DB) &&
-		    hns_roce_qp_has_rq(init_attr)) {
+		if (kernel_qp_has_rdb(hr_dev, init_attr)) {
 			ret = hns_roce_alloc_db(hr_dev, &hr_qp->rdb, 0);
 			if (ret) {
-				dev_err(dev, "rq record doorbell alloc failed!\n");
-				goto err_alloc_rq_inline_buf;
+				ibdev_err(ibdev,
+					  "Failed to alloc kernel RQ doorbell\n");
+				goto err_out;
 			}
 			*hr_qp->rdb.db_record = 0;
 			hr_qp->rdb_en = 1;
 		}
+	}
 
-		/* Allocate QP buf */
-		if (hns_roce_buf_alloc(hr_dev, hr_qp->buff_size,
-				       (1 << page_shift) * 2,
-				       &hr_qp->hr_buf, page_shift)) {
-			dev_err(dev, "hns_roce_buf_alloc error!\n");
+	return 0;
+err_sdb:
+	if (udata && hr_qp->sdb_en)
+		hns_roce_db_unmap_user(uctx, &hr_qp->sdb);
+err_out:
+	return ret;
+}
+
+static void free_qp_db(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp,
+		       struct ib_udata *udata)
+{
+	struct hns_roce_ucontext *uctx = rdma_udata_to_drv_context(
+		udata, struct hns_roce_ucontext, ibucontext);
+
+	if (udata) {
+		if (hr_qp->rdb_en)
+			hns_roce_db_unmap_user(uctx, &hr_qp->rdb);
+		if (hr_qp->sdb_en)
+			hns_roce_db_unmap_user(uctx, &hr_qp->sdb);
+	} else {
+		if (hr_qp->rdb_en)
+			hns_roce_free_db(hr_dev, &hr_qp->rdb);
+	}
+}
+
+static int alloc_kernel_wrid(struct hns_roce_dev *hr_dev,
+			     struct hns_roce_qp *hr_qp)
+{
+	struct ib_device *ibdev = &hr_dev->ib_dev;
+	u64 *sq_wrid = NULL;
+	u64 *rq_wrid = NULL;
+	int ret;
+
+	sq_wrid = kcalloc(hr_qp->sq.wqe_cnt, sizeof(u64), GFP_KERNEL);
+	if (ZERO_OR_NULL_PTR(sq_wrid)) {
+		ibdev_err(ibdev, "Failed to alloc SQ wrid\n");
+		return -ENOMEM;
+	}
+
+	if (hr_qp->rq.wqe_cnt) {
+		rq_wrid = kcalloc(hr_qp->rq.wqe_cnt, sizeof(u64), GFP_KERNEL);
+		if (ZERO_OR_NULL_PTR(rq_wrid)) {
+			ibdev_err(ibdev, "Failed to alloc RQ wrid\n");
 			ret = -ENOMEM;
-			goto err_db;
-		}
-		hr_qp->region_cnt = split_wqe_buf_region(hr_dev, hr_qp,
-				hr_qp->regions, ARRAY_SIZE(hr_qp->regions),
-				page_shift);
-		ret = hns_roce_alloc_buf_list(hr_qp->regions, buf_list,
-					      hr_qp->region_cnt);
-		if (ret) {
-			dev_err(dev, "alloc buf_list error for create qp!\n");
-			goto err_alloc_list;
+			goto err_sq;
 		}
+	}
 
-		for (i = 0; i < hr_qp->region_cnt; i++) {
-			r = &hr_qp->regions[i];
-			buf_count = hns_roce_get_kmem_bufs(hr_dev,
-					buf_list[i], r->count, r->offset,
-					&hr_qp->hr_buf);
-			if (buf_count != r->count) {
-				dev_err(dev,
-					"get kmem buf err, expect %d,ret %d.\n",
-					r->count, buf_count);
-				ret = -ENOBUFS;
-				goto err_get_bufs;
-			}
+	hr_qp->sq.wrid = sq_wrid;
+	hr_qp->rq.wrid = rq_wrid;
+	return 0;
+err_sq:
+	kfree(sq_wrid);
+
+	return ret;
+}
+
+static void free_kernel_wrid(struct hns_roce_dev *hr_dev,
+			     struct hns_roce_qp *hr_qp)
+{
+	kfree(hr_qp->rq.wrid);
+	kfree(hr_qp->sq.wrid);
+}
+
+static int set_qp_param(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp,
+			struct ib_qp_init_attr *init_attr,
+			struct ib_udata *udata,
+			struct hns_roce_ib_create_qp *ucmd)
+{
+	struct ib_device *ibdev = &hr_dev->ib_dev;
+	int ret;
+
+	hr_qp->ibqp.qp_type = init_attr->qp_type;
+
+	if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR)
+		hr_qp->sq_signal_bits = IB_SIGNAL_ALL_WR;
+	else
+		hr_qp->sq_signal_bits = IB_SIGNAL_REQ_WR;
+
+	ret = set_rq_size(hr_dev, &init_attr->cap, udata,
+			  hns_roce_qp_has_rq(init_attr), hr_qp);
+	if (ret) {
+		ibdev_err(ibdev, "Failed to set user RQ size\n");
+		return ret;
+	}
+
+	if (udata) {
+		if (ib_copy_from_udata(ucmd, udata, sizeof(*ucmd))) {
+			ibdev_err(ibdev, "Failed to copy QP ucmd\n");
+			return -EFAULT;
 		}
 
-		hr_qp->sq.wrid = kcalloc(hr_qp->sq.wqe_cnt, sizeof(u64),
-					 GFP_KERNEL);
-		if (ZERO_OR_NULL_PTR(hr_qp->sq.wrid)) {
-			ret = -ENOMEM;
-			goto err_get_bufs;
+		ret = set_user_sq_size(hr_dev, &init_attr->cap, hr_qp, ucmd);
+		if (ret)
+			ibdev_err(ibdev, "Failed to set user SQ size\n");
+	} else {
+		if (init_attr->create_flags &
+		    IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK) {
+			ibdev_err(ibdev, "Failed to check multicast loopback\n");
+			return -EINVAL;
 		}
 
-		if (hr_qp->rq.wqe_cnt) {
-			hr_qp->rq.wrid = kcalloc(hr_qp->rq.wqe_cnt, sizeof(u64),
-						 GFP_KERNEL);
-			if (ZERO_OR_NULL_PTR(hr_qp->rq.wrid)) {
-				ret = -ENOMEM;
-				goto err_sq_wrid;
-			}
+		if (init_attr->create_flags & IB_QP_CREATE_IPOIB_UD_LSO) {
+			ibdev_err(ibdev, "Failed to check ipoib ud lso\n");
+			return -EINVAL;
 		}
+
+		ret = set_kernel_sq_size(hr_dev, &init_attr->cap, hr_qp);
+		if (ret)
+			ibdev_err(ibdev, "Failed to set kernel SQ size\n");
 	}
 
-	if (sqpn) {
-		qpn = sqpn;
-	} else {
-		/* Get QPN */
-		ret = hns_roce_reserve_range_qp(hr_dev, 1, 1, &qpn);
+	return ret;
+}
+
+static int hns_roce_create_qp_common(struct hns_roce_dev *hr_dev,
+				     struct ib_pd *ib_pd,
+				     struct ib_qp_init_attr *init_attr,
+				     struct ib_udata *udata,
+				     struct hns_roce_qp *hr_qp)
+{
+	struct hns_roce_ib_create_qp_resp resp = {};
+	struct ib_device *ibdev = &hr_dev->ib_dev;
+	struct hns_roce_ib_create_qp ucmd;
+	int ret;
+
+	mutex_init(&hr_qp->mutex);
+	spin_lock_init(&hr_qp->sq.lock);
+	spin_lock_init(&hr_qp->rq.lock);
+
+	hr_qp->state = IB_QPS_RESET;
+	hr_qp->flush_flag = 0;
+
+	ret = set_qp_param(hr_dev, hr_qp, init_attr, udata, &ucmd);
+	if (ret) {
+		ibdev_err(ibdev, "Failed to set QP param\n");
+		return ret;
+	}
+
+	if (!udata) {
+		ret = alloc_kernel_wrid(hr_dev, hr_qp);
 		if (ret) {
-			dev_err(dev, "hns_roce_reserve_range_qp alloc qpn error\n");
-			goto err_wrid;
+			ibdev_err(ibdev, "Failed to alloc wrid\n");
+			return ret;
 		}
 	}
 
-	hr_qp->wqe_bt_pg_shift = calc_wqe_bt_page_shift(hr_dev, hr_qp->regions,
-							hr_qp->region_cnt);
-	hns_roce_mtr_init(&hr_qp->mtr, PAGE_SHIFT + hr_qp->wqe_bt_pg_shift,
-			  page_shift);
-	ret = hns_roce_mtr_attach(hr_dev, &hr_qp->mtr, buf_list,
-				  hr_qp->regions, hr_qp->region_cnt);
+	ret = alloc_qp_db(hr_dev, hr_qp, init_attr, udata, &ucmd, &resp);
 	if (ret) {
-		dev_err(dev, "mtr attach error for create qp\n");
-		goto err_mtr;
+		ibdev_err(ibdev, "Failed to alloc QP doorbell\n");
+		goto err_wrid;
 	}
 
-	if (init_attr->qp_type == IB_QPT_GSI &&
-	    hr_dev->hw_rev == HNS_ROCE_HW_VER1) {
-		/* In v1 engine, GSI QP context in RoCE engine's register */
-		ret = hns_roce_gsi_qp_alloc(hr_dev, qpn, hr_qp);
-		if (ret) {
-			dev_err(dev, "hns_roce_qp_alloc failed!\n");
-			goto err_qpn;
-		}
-	} else {
-		ret = hns_roce_qp_alloc(hr_dev, qpn, hr_qp);
-		if (ret) {
-			dev_err(dev, "hns_roce_qp_alloc failed!\n");
-			goto err_qpn;
-		}
+	ret = alloc_qp_buf(hr_dev, hr_qp, init_attr, udata, ucmd.buf_addr);
+	if (ret) {
+		ibdev_err(ibdev, "Failed to alloc QP buffer\n");
+		goto err_db;
 	}
 
-	if (sqpn)
-		hr_qp->doorbell_qpn = 1;
-	else
-		hr_qp->doorbell_qpn = (u32)hr_qp->qpn;
+	ret = alloc_qpn(hr_dev, hr_qp);
+	if (ret) {
+		ibdev_err(ibdev, "Failed to alloc QPN\n");
+		goto err_buf;
+	}
+
+	ret = alloc_qpc(hr_dev, hr_qp);
+	if (ret) {
+		ibdev_err(ibdev, "Failed to alloc QP context\n");
+		goto err_qpn;
+	}
+
+	ret = hns_roce_qp_store(hr_dev, hr_qp, init_attr);
+	if (ret) {
+		ibdev_err(ibdev, "Failed to store QP\n");
+		goto err_qpc;
+	}
 
 	if (udata) {
 		ret = ib_copy_to_udata(udata, &resp,
 				       min(udata->outlen, sizeof(resp)));
-		if (ret)
-			goto err_qp;
+		if (ret) {
+			ibdev_err(ibdev, "copy qp resp failed!\n");
+			goto err_store;
+		}
 	}
 
 	if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_QP_FLOW_CTRL) {
 		ret = hr_dev->hw->qp_flow_control_init(hr_dev, hr_qp);
 		if (ret)
-			goto err_qp;
+			goto err_store;
 	}
 
+	hr_qp->ibqp.qp_num = hr_qp->qpn;
 	hr_qp->event = hns_roce_ib_qp_event;
-	hns_roce_free_buf_list(buf_list, hr_qp->region_cnt);
+	atomic_set(&hr_qp->refcount, 1);
+	init_completion(&hr_qp->free);
 
 	return 0;
 
-err_qp:
-	if (init_attr->qp_type == IB_QPT_GSI &&
-		hr_dev->hw_rev == HNS_ROCE_HW_VER1)
-		hns_roce_qp_remove(hr_dev, hr_qp);
-	else
-		hns_roce_qp_free(hr_dev, hr_qp);
-
+err_store:
+	hns_roce_qp_remove(hr_dev, hr_qp);
+err_qpc:
+	free_qpc(hr_dev, hr_qp);
 err_qpn:
-	if (!sqpn)
-		hns_roce_release_range_qp(hr_dev, qpn, 1);
-
-err_mtr:
-	hns_roce_mtr_cleanup(hr_dev, &hr_qp->mtr);
-
+	free_qpn(hr_dev, hr_qp);
+err_buf:
+	free_qp_buf(hr_dev, hr_qp);
+err_db:
+	free_qp_db(hr_dev, hr_qp, udata);
 err_wrid:
-	if (udata) {
-		if ((hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_RECORD_DB) &&
-		    (udata->outlen >= sizeof(resp)) &&
-		    hns_roce_qp_has_rq(init_attr))
-			hns_roce_db_unmap_user(uctx, &hr_qp->rdb);
-	} else {
-		if (hr_qp->rq.wqe_cnt)
-			kfree(hr_qp->rq.wrid);
-	}
-
-err_sq_dbmap:
-	if (udata)
-		if ((hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_SQ_RECORD_DB) &&
-		    (udata->inlen >= sizeof(ucmd)) &&
-		    (udata->outlen >= sizeof(resp)) &&
-		    hns_roce_qp_has_sq(init_attr))
-			hns_roce_db_unmap_user(uctx, &hr_qp->sdb);
-
-err_sq_wrid:
-	if (!udata)
-		kfree(hr_qp->sq.wrid);
-
-err_get_bufs:
-	hns_roce_free_buf_list(buf_list, hr_qp->region_cnt);
-
-err_alloc_list:
-	if (!hr_qp->umem)
-		hns_roce_buf_free(hr_dev, hr_qp->buff_size, &hr_qp->hr_buf);
-	ib_umem_release(hr_qp->umem);
+	free_kernel_wrid(hr_dev, hr_qp);
+	return ret;
+}
 
-err_db:
-	if (!udata && hns_roce_qp_has_rq(init_attr) &&
-	    (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_RECORD_DB))
-		hns_roce_free_db(hr_dev, &hr_qp->rdb);
+void hns_roce_qp_destroy(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp,
+			 struct ib_udata *udata)
+{
+	if (atomic_dec_and_test(&hr_qp->refcount))
+		complete(&hr_qp->free);
+	wait_for_completion(&hr_qp->free);
 
-err_alloc_rq_inline_buf:
-	if ((hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_RQ_INLINE) &&
-	     hns_roce_qp_has_rq(init_attr))
-		free_rq_inline_buf(hr_qp);
+	free_qpc(hr_dev, hr_qp);
+	free_qpn(hr_dev, hr_qp);
+	free_qp_buf(hr_dev, hr_qp);
+	free_kernel_wrid(hr_dev, hr_qp);
+	free_qp_db(hr_dev, hr_qp, udata);
 
-err_out:
-	return ret;
+	kfree(hr_qp);
 }
 
 struct ib_qp *hns_roce_create_qp(struct ib_pd *pd,
@@ -1017,7 +1204,6 @@
 {
 	struct hns_roce_dev *hr_dev = to_hr_dev(pd->device);
 	struct ib_device *ibdev = &hr_dev->ib_dev;
-	struct hns_roce_sqp *hr_sqp;
 	struct hns_roce_qp *hr_qp;
 	int ret;
 
@@ -1027,17 +1213,15 @@
 		if (!hr_qp)
 			return ERR_PTR(-ENOMEM);
 
-		ret = hns_roce_create_qp_common(hr_dev, pd, init_attr, udata, 0,
+		ret = hns_roce_create_qp_common(hr_dev, pd, init_attr, udata,
 						hr_qp);
 		if (ret) {
-			ibdev_err(ibdev, "Create RC QP 0x%06lx failed(%d)\n",
+			ibdev_err(ibdev, "Create QP 0x%06lx failed(%d)\n",
 				  hr_qp->qpn, ret);
 			kfree(hr_qp);
 			return ERR_PTR(ret);
 		}
 
-		hr_qp->ibqp.qp_num = hr_qp->qpn;
-
 		break;
 	}
 	case IB_QPT_GSI: {
@@ -1047,26 +1231,18 @@
 			return ERR_PTR(-EINVAL);
 		}
 
-		hr_sqp = kzalloc(sizeof(*hr_sqp), GFP_KERNEL);
-		if (!hr_sqp)
+		hr_qp = kzalloc(sizeof(*hr_qp), GFP_KERNEL);
+		if (!hr_qp)
 			return ERR_PTR(-ENOMEM);
 
-		hr_qp = &hr_sqp->hr_qp;
 		hr_qp->port = init_attr->port_num - 1;
 		hr_qp->phy_port = hr_dev->iboe.phy_port[hr_qp->port];
 
-		/* when hw version is v1, the sqpn is allocated */
-		if (hr_dev->caps.max_sq_sg <= 2)
-			hr_qp->ibqp.qp_num = HNS_ROCE_MAX_PORTS +
-					     hr_dev->iboe.phy_port[hr_qp->port];
-		else
-			hr_qp->ibqp.qp_num = 1;
-
 		ret = hns_roce_create_qp_common(hr_dev, pd, init_attr, udata,
-						hr_qp->ibqp.qp_num, hr_qp);
+						hr_qp);
 		if (ret) {
 			ibdev_err(ibdev, "Create GSI QP failed!\n");
-			kfree(hr_sqp);
+			kfree(hr_qp);
 			return ERR_PTR(ret);
 		}
 
@@ -1179,8 +1355,10 @@
 
 	mutex_lock(&hr_qp->mutex);
 
-	cur_state = attr_mask & IB_QP_CUR_STATE ?
-		    attr->cur_qp_state : (enum ib_qp_state)hr_qp->state;
+	if (attr_mask & IB_QP_CUR_STATE && attr->cur_qp_state != hr_qp->state)
+		goto out;
+
+	cur_state = hr_qp->state;
 	new_state = attr_mask & IB_QP_STATE ? attr->qp_state : cur_state;
 
 	if (ibqp->uobject &&
@@ -1208,11 +1386,10 @@
 		goto out;
 
 	if (cur_state == new_state && cur_state == IB_QPS_RESET) {
-		if (hr_dev->caps.min_wqes) {
+		if (hr_dev->hw_rev == HNS_ROCE_HW_VER1) {
 			ret = -EPERM;
 			ibdev_err(&hr_dev->ib_dev,
-				"cur_state=%d new_state=%d\n", cur_state,
-				new_state);
+				  "RST2RST state is not supported\n");
 		} else {
 			ret = 0;
 		}
@@ -1232,7 +1409,16 @@
 void hns_roce_lock_cqs(struct hns_roce_cq *send_cq, struct hns_roce_cq *recv_cq)
 		       __acquires(&send_cq->lock) __acquires(&recv_cq->lock)
 {
-	if (send_cq == recv_cq) {
+	if (unlikely(send_cq == NULL && recv_cq == NULL)) {
+		__acquire(&send_cq->lock);
+		__acquire(&recv_cq->lock);
+	} else if (unlikely(send_cq != NULL && recv_cq == NULL)) {
+		spin_lock_irq(&send_cq->lock);
+		__acquire(&recv_cq->lock);
+	} else if (unlikely(send_cq == NULL && recv_cq != NULL)) {
+		spin_lock_irq(&recv_cq->lock);
+		__acquire(&send_cq->lock);
+	} else if (send_cq == recv_cq) {
 		spin_lock_irq(&send_cq->lock);
 		__acquire(&recv_cq->lock);
 	} else if (send_cq->cqn < recv_cq->cqn) {
@@ -1248,7 +1434,16 @@
 			 struct hns_roce_cq *recv_cq) __releases(&send_cq->lock)
 			 __releases(&recv_cq->lock)
 {
-	if (send_cq == recv_cq) {
+	if (unlikely(send_cq == NULL && recv_cq == NULL)) {
+		__release(&recv_cq->lock);
+		__release(&send_cq->lock);
+	} else if (unlikely(send_cq != NULL && recv_cq == NULL)) {
+		__release(&recv_cq->lock);
+		spin_unlock(&send_cq->lock);
+	} else if (unlikely(send_cq == NULL && recv_cq != NULL)) {
+		__release(&send_cq->lock);
+		spin_unlock(&recv_cq->lock);
+	} else if (send_cq == recv_cq) {
 		__release(&recv_cq->lock);
 		spin_unlock_irq(&send_cq->lock);
 	} else if (send_cq->cqn < recv_cq->cqn) {
@@ -1289,7 +1484,7 @@
 	u32 cur;
 
 	cur = hr_wq->head - hr_wq->tail;
-	if (likely(cur + nreq < hr_wq->max_post))
+	if (likely(cur + nreq < hr_wq->wqe_cnt))
 		return false;
 
 	hr_cq = to_hr_cq(ib_cq);
@@ -1297,7 +1492,7 @@
 	cur = hr_wq->head - hr_wq->tail;
 	spin_unlock(&hr_cq->lock);
 
-	return cur + nreq >= hr_wq->max_post;
+	return cur + nreq >= hr_wq->wqe_cnt;
 }
 
 int hns_roce_init_qp_table(struct hns_roce_dev *hr_dev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hns/hns_roce_restrack.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hns/hns_roce_restrack.c
@@ -95,14 +95,18 @@
 
 	ret = hr_dev->dfx->query_cqc_info(hr_dev, hr_cq->cqn, (int *)context);
 	if (ret)
-		goto err;
+		return -EINVAL;
 
 	table_attr = nla_nest_start(msg, RDMA_NLDEV_ATTR_DRIVER);
-	if (!table_attr)
+	if (!table_attr) {
+		ret = -EMSGSIZE;
 		goto err;
+	}
 
-	if (hns_roce_fill_cq(msg, context))
+	if (hns_roce_fill_cq(msg, context)) {
+		ret = -EMSGSIZE;
 		goto err_cancel_table;
+	}
 
 	nla_nest_end(msg, table_attr);
 	kfree(context);
@@ -113,7 +117,7 @@
 	nla_nest_cancel(msg, table_attr);
 err:
 	kfree(context);
-	return -EMSGSIZE;
+	return ret;
 }
 
 int hns_roce_fill_res_entry(struct sk_buff *msg,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/hns/hns_roce_srq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/hns/hns_roce_srq.c
@@ -59,21 +59,21 @@
 	}
 }
 
-static int hns_roce_sw2hw_srq(struct hns_roce_dev *dev,
-			      struct hns_roce_cmd_mailbox *mailbox,
-			      unsigned long srq_num)
+static int hns_roce_hw_create_srq(struct hns_roce_dev *dev,
+				  struct hns_roce_cmd_mailbox *mailbox,
+				  unsigned long srq_num)
 {
 	return hns_roce_cmd_mbox(dev, mailbox->dma, 0, srq_num, 0,
-				 HNS_ROCE_CMD_SW2HW_SRQ,
+				 HNS_ROCE_CMD_CREATE_SRQ,
 				 HNS_ROCE_CMD_TIMEOUT_MSECS);
 }
 
-static int hns_roce_hw2sw_srq(struct hns_roce_dev *dev,
-			     struct hns_roce_cmd_mailbox *mailbox,
-			     unsigned long srq_num)
+static int hns_roce_hw_destroy_srq(struct hns_roce_dev *dev,
+				   struct hns_roce_cmd_mailbox *mailbox,
+				   unsigned long srq_num)
 {
 	return hns_roce_cmd_mbox(dev, 0, mailbox ? mailbox->dma : 0, srq_num,
-				 mailbox ? 0 : 1, HNS_ROCE_CMD_HW2SW_SRQ,
+				 mailbox ? 0 : 1, HNS_ROCE_CMD_DESTROY_SRQ,
 				 HNS_ROCE_CMD_TIMEOUT_MSECS);
 }
 
@@ -95,8 +95,7 @@
 				       srq->mtt.first_seg,
 				       &dma_handle_wqe);
 	if (!mtts_wqe) {
-		dev_err(hr_dev->dev,
-			"SRQ alloc.Failed to find srq buf addr.\n");
+		dev_err(hr_dev->dev, "Failed to find mtt for srq buf.\n");
 		return -EINVAL;
 	}
 
@@ -106,13 +105,14 @@
 				       &dma_handle_idx);
 	if (!mtts_idx) {
 		dev_err(hr_dev->dev,
-			"SRQ alloc.Failed to find idx que buf addr.\n");
+			"Failed to find mtt for srq idx queue buf.\n");
 		return -EINVAL;
 	}
 
 	ret = hns_roce_bitmap_alloc(&srq_table->bitmap, &srq->srqn);
-	if (ret == -1) {
-		dev_err(hr_dev->dev, "SRQ alloc.Failed to alloc index.\n");
+	if (ret) {
+		dev_err(hr_dev->dev,
+			"Failed to alloc a bit from srq bitmap.\n");
 		return -ENOMEM;
 	}
 
@@ -134,7 +134,7 @@
 			       mtts_wqe, mtts_idx, dma_handle_wqe,
 			       dma_handle_idx);
 
-	ret = hns_roce_sw2hw_srq(hr_dev, mailbox, srq->srqn);
+	ret = hns_roce_hw_create_srq(hr_dev, mailbox, srq->srqn);
 	hns_roce_free_cmd_mailbox(hr_dev, mailbox);
 	if (ret)
 		goto err_xa;
@@ -160,9 +160,9 @@
 	struct hns_roce_srq_table *srq_table = &hr_dev->srq_table;
 	int ret;
 
-	ret = hns_roce_hw2sw_srq(hr_dev, NULL, srq->srqn);
+	ret = hns_roce_hw_destroy_srq(hr_dev, NULL, srq->srqn);
 	if (ret)
-		dev_err(hr_dev->dev, "HW2SW_SRQ failed (%d) for CQN %06lx\n",
+		dev_err(hr_dev->dev, "DESTROY_SRQ failed (%d) for SRQN %06lx\n",
 			ret, srq->srqn);
 
 	xa_erase(&srq_table->xa, srq->srqn);
@@ -180,22 +180,24 @@
 {
 	struct hns_roce_dev *hr_dev = to_hr_dev(srq->ibsrq.device);
 	struct hns_roce_ib_create_srq  ucmd;
-	u32 page_shift;
-	u32 npages;
+	struct hns_roce_buf *buf;
 	int ret;
 
 	if (ib_copy_from_udata(&ucmd, udata, sizeof(ucmd)))
 		return -EFAULT;
 
-	srq->umem = ib_umem_get(udata, ucmd.buf_addr, srq_buf_size, 0, 0);
+	srq->umem =
+		ib_umem_get(srq->ibsrq.device, ucmd.buf_addr, srq_buf_size, 0);
 	if (IS_ERR(srq->umem))
 		return PTR_ERR(srq->umem);
 
-	npages = (ib_umem_page_count(srq->umem) +
-		(1 << hr_dev->caps.srqwqe_buf_pg_sz) - 1) /
-		(1 << hr_dev->caps.srqwqe_buf_pg_sz);
-	page_shift = PAGE_SHIFT + hr_dev->caps.srqwqe_buf_pg_sz;
-	ret = hns_roce_mtt_init(hr_dev, npages, page_shift, &srq->mtt);
+	buf = &srq->buf;
+	buf->npages = (ib_umem_page_count(srq->umem) +
+		       (1 << hr_dev->caps.srqwqe_buf_pg_sz) - 1) /
+		      (1 << hr_dev->caps.srqwqe_buf_pg_sz);
+	buf->page_shift = PAGE_SHIFT + hr_dev->caps.srqwqe_buf_pg_sz;
+	ret = hns_roce_mtt_init(hr_dev, buf->npages, buf->page_shift,
+				&srq->mtt);
 	if (ret)
 		goto err_user_buf;
 
@@ -204,17 +206,20 @@
 		goto err_user_srq_mtt;
 
 	/* config index queue BA */
-	srq->idx_que.umem = ib_umem_get(udata, ucmd.que_addr,
-					srq->idx_que.buf_size, 0, 0);
+	srq->idx_que.umem = ib_umem_get(srq->ibsrq.device, ucmd.que_addr,
+					srq->idx_que.buf_size, 0);
 	if (IS_ERR(srq->idx_que.umem)) {
 		dev_err(hr_dev->dev, "ib_umem_get error for index queue\n");
 		ret = PTR_ERR(srq->idx_que.umem);
 		goto err_user_srq_mtt;
 	}
 
-	ret = hns_roce_mtt_init(hr_dev, ib_umem_page_count(srq->idx_que.umem),
-				PAGE_SHIFT, &srq->idx_que.mtt);
-
+	buf = &srq->idx_que.idx_buf;
+	buf->npages = DIV_ROUND_UP(ib_umem_page_count(srq->idx_que.umem),
+				   1 << hr_dev->caps.idx_buf_pg_sz);
+	buf->page_shift = PAGE_SHIFT + hr_dev->caps.idx_buf_pg_sz;
+	ret = hns_roce_mtt_init(hr_dev, buf->npages, buf->page_shift,
+				&srq->idx_que.mtt);
 	if (ret) {
 		dev_err(hr_dev->dev, "hns_roce_mtt_init error for idx que\n");
 		goto err_user_idx_mtt;
@@ -251,7 +256,7 @@
 	struct hns_roce_dev *hr_dev = to_hr_dev(pd->device);
 	struct hns_roce_idx_que *idx_que = &srq->idx_que;
 
-	idx_que->bitmap = bitmap_zalloc(srq->max, GFP_KERNEL);
+	idx_que->bitmap = bitmap_zalloc(srq->wqe_cnt, GFP_KERNEL);
 	if (!idx_que->bitmap)
 		return -ENOMEM;
 
@@ -277,7 +282,7 @@
 		return -ENOMEM;
 
 	srq->head = 0;
-	srq->tail = srq->max - 1;
+	srq->tail = srq->wqe_cnt - 1;
 
 	ret = hns_roce_mtt_init(hr_dev, srq->buf.npages, srq->buf.page_shift,
 				&srq->mtt);
@@ -308,7 +313,7 @@
 	if (ret)
 		goto err_kernel_idx_buf;
 
-	srq->wrid = kvmalloc_array(srq->max, sizeof(u64), GFP_KERNEL);
+	srq->wrid = kvmalloc_array(srq->wqe_cnt, sizeof(u64), GFP_KERNEL);
 	if (!srq->wrid) {
 		ret = -ENOMEM;
 		goto err_kernel_idx_buf;
@@ -354,7 +359,7 @@
 }
 
 int hns_roce_create_srq(struct ib_srq *ib_srq,
-			struct ib_srq_init_attr *srq_init_attr,
+			struct ib_srq_init_attr *init_attr,
 			struct ib_udata *udata)
 {
 	struct hns_roce_dev *hr_dev = to_hr_dev(ib_srq->device);
@@ -366,24 +371,25 @@
 	u32 cqn;
 
 	/* Check the actual SRQ wqe and SRQ sge num */
-	if (srq_init_attr->attr.max_wr >= hr_dev->caps.max_srq_wrs ||
-	    srq_init_attr->attr.max_sge > hr_dev->caps.max_srq_sges)
+	if (init_attr->attr.max_wr >= hr_dev->caps.max_srq_wrs ||
+	    init_attr->attr.max_sge > hr_dev->caps.max_srq_sges)
 		return -EINVAL;
 
 	mutex_init(&srq->mutex);
 	spin_lock_init(&srq->lock);
 
-	srq->max = roundup_pow_of_two(srq_init_attr->attr.max_wr + 1);
-	srq->max_gs = srq_init_attr->attr.max_sge;
+	srq->wqe_cnt = roundup_pow_of_two(init_attr->attr.max_wr + 1);
+	srq->max_gs = init_attr->attr.max_sge;
 
-	srq_desc_size = roundup_pow_of_two(max(16, 16 * srq->max_gs));
+	srq_desc_size = roundup_pow_of_two(max(HNS_ROCE_SGE_SIZE,
+					HNS_ROCE_SGE_SIZE * srq->max_gs));
 
 	srq->wqe_shift = ilog2(srq_desc_size);
 
-	srq_buf_size = srq->max * srq_desc_size;
+	srq_buf_size = srq->wqe_cnt * srq_desc_size;
 
 	srq->idx_que.entry_sz = HNS_ROCE_IDX_QUE_ENTRY_SZ;
-	srq->idx_que.buf_size = srq->max * srq->idx_que.entry_sz;
+	srq->idx_que.buf_size = srq->wqe_cnt * srq->idx_que.entry_sz;
 	srq->mtt.mtt_type = MTT_TYPE_SRQWQE;
 	srq->idx_que.mtt.mtt_type = MTT_TYPE_IDX;
 
@@ -401,8 +407,8 @@
 		}
 	}
 
-	cqn = ib_srq_has_cq(srq_init_attr->srq_type) ?
-	      to_hr_cq(srq_init_attr->ext.cq)->cqn : 0;
+	cqn = ib_srq_has_cq(init_attr->srq_type) ?
+	      to_hr_cq(init_attr->ext.cq)->cqn : 0;
 
 	srq->db_reg_l = hr_dev->reg_base + SRQ_DB_REG;
 
@@ -449,7 +455,7 @@
 		hns_roce_mtt_cleanup(hr_dev, &srq->idx_que.mtt);
 	} else {
 		kvfree(srq->wrid);
-		hns_roce_buf_free(hr_dev, srq->max << srq->wqe_shift,
+		hns_roce_buf_free(hr_dev, srq->wqe_cnt << srq->wqe_shift,
 				  &srq->buf);
 	}
 	ib_umem_release(srq->idx_que.umem);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/i40iw/i40iw.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/i40iw/i40iw.h
@@ -398,8 +398,8 @@
 }
 
 /* i40iw.c */
-void i40iw_add_ref(struct ib_qp *);
-void i40iw_rem_ref(struct ib_qp *);
+void i40iw_qp_add_ref(struct ib_qp *ibqp);
+void i40iw_qp_rem_ref(struct ib_qp *ibqp);
 struct ib_qp *i40iw_get_qp(struct ib_device *, int);
 
 void i40iw_flush_wqes(struct i40iw_device *iwdev,
@@ -411,9 +411,8 @@
 			    bool ipv4,
 			    u32 action);
 
-int i40iw_manage_apbvt(struct i40iw_device *iwdev,
-		       u16 accel_local_port,
-		       bool add_port);
+enum i40iw_status_code i40iw_manage_apbvt(struct i40iw_device *iwdev,
+					  u16 accel_local_port, bool add_port);
 
 struct i40iw_cqp_request *i40iw_get_cqp_request(struct i40iw_cqp *cqp, bool wait);
 void i40iw_free_cqp_request(struct i40iw_cqp *cqp, struct i40iw_cqp_request *cqp_request);
@@ -543,9 +542,8 @@
 					  bool wait);
 void i40iw_receive_ilq(struct i40iw_sc_vsi *vsi, struct i40iw_puda_buf *rbuf);
 void i40iw_free_sqbuf(struct i40iw_sc_vsi *vsi, void *bufp);
-void i40iw_free_qp_resources(struct i40iw_device *iwdev,
-			     struct i40iw_qp *iwqp,
-			     u32 qp_num);
+void i40iw_free_qp_resources(struct i40iw_qp *iwqp);
+
 enum i40iw_status_code i40iw_obj_aligned_mem(struct i40iw_device *iwdev,
 					     struct i40iw_dma_mem *memptr,
 					     u32 size, u32 mask);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/i40iw/i40iw_cm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/i40iw/i40iw_cm.c
@@ -1987,7 +1987,6 @@
 	struct rtable *rt;
 	struct neighbour *neigh;
 	int rc = arpindex;
-	struct net_device *netdev = iwdev->netdev;
 	__be32 dst_ipaddr = htonl(dst_ip);
 	__be32 src_ipaddr = htonl(src_ip);
 
@@ -1997,9 +1996,6 @@
 		return rc;
 	}
 
-	if (netif_is_bond_slave(netdev))
-		netdev = netdev_master_upper_dev_get(netdev);
-
 	neigh = dst_neigh_lookup(&rt->dst, &dst_ipaddr);
 
 	rcu_read_lock();
@@ -2065,7 +2061,6 @@
 {
 	struct neighbour *neigh;
 	int rc = arpindex;
-	struct net_device *netdev = iwdev->netdev;
 	struct dst_entry *dst;
 	struct sockaddr_in6 dst_addr;
 	struct sockaddr_in6 src_addr;
@@ -2079,16 +2074,13 @@
 	dst = i40iw_get_dst_ipv6(&src_addr, &dst_addr);
 	if (!dst || dst->error) {
 		if (dst) {
-			dst_release(dst);
 			i40iw_pr_err("ip6_route_output returned dst->error = %d\n",
 				     dst->error);
+			dst_release(dst);
 		}
 		return rc;
 	}
 
-	if (netif_is_bond_slave(netdev))
-		netdev = netdev_master_upper_dev_get(netdev);
-
 	neigh = dst_neigh_lookup(dst, dst_addr.sin6_addr.in6_u.u6_addr32);
 
 	rcu_read_lock();
@@ -2330,7 +2322,7 @@
 	iwqp = cm_node->iwqp;
 	if (iwqp) {
 		iwqp->cm_node = NULL;
-		i40iw_rem_ref(&iwqp->ibqp);
+		i40iw_qp_rem_ref(&iwqp->ibqp);
 		cm_node->iwqp = NULL;
 	} else if (cm_node->qhash_set) {
 		i40iw_get_addr_info(cm_node, &nfo);
@@ -3460,7 +3452,7 @@
 		kfree(work);
 		return;
 	}
-	i40iw_add_ref(&iwqp->ibqp);
+	i40iw_qp_add_ref(&iwqp->ibqp);
 	spin_unlock_irqrestore(&iwdev->qptable_lock, flags);
 
 	work->iwqp = iwqp;
@@ -3631,7 +3623,7 @@
 
 	kfree(dwork);
 	i40iw_cm_disconn_true(iwqp);
-	i40iw_rem_ref(&iwqp->ibqp);
+	i40iw_qp_rem_ref(&iwqp->ibqp);
 }
 
 /**
@@ -3753,7 +3745,7 @@
 	cm_node->lsmm_size = accept.size + conn_param->private_data_len;
 	i40iw_cm_init_tsa_conn(iwqp, cm_node);
 	cm_id->add_ref(cm_id);
-	i40iw_add_ref(&iwqp->ibqp);
+	i40iw_qp_add_ref(&iwqp->ibqp);
 
 	attr.qp_state = IB_QPS_RTS;
 	cm_node->qhash_set = false;
@@ -3916,7 +3908,7 @@
 	iwqp->cm_node = cm_node;
 	cm_node->iwqp = iwqp;
 	iwqp->cm_id = cm_id;
-	i40iw_add_ref(&iwqp->ibqp);
+	i40iw_qp_add_ref(&iwqp->ibqp);
 
 	if (cm_node->state != I40IW_CM_STATE_OFFLOADED) {
 		cm_node->state = I40IW_CM_STATE_SYN_SENT;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/i40iw/i40iw_ctrl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/i40iw/i40iw_ctrl.c
@@ -2945,6 +2945,9 @@
 	u64 header;
 	enum i40iw_page_size page_size;
 
+	if (!info->total_len && !info->all_memory)
+		return -EINVAL;
+
 	page_size = (info->page_size == 0x200000) ? I40IW_PAGE_SIZE_2M : I40IW_PAGE_SIZE_4K;
 	cqp = dev->cqp;
 	wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
@@ -3003,6 +3006,9 @@
 	u8 addr_type;
 	enum i40iw_page_size page_size;
 
+	if (!info->total_len && !info->all_memory)
+		return -EINVAL;
+
 	page_size = (info->page_size == 0x200000) ? I40IW_PAGE_SIZE_2M : I40IW_PAGE_SIZE_4K;
 	if (info->access_rights & (I40IW_ACCESS_FLAGS_REMOTEREAD_ONLY |
 				   I40IW_ACCESS_FLAGS_REMOTEWRITE_ONLY))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/i40iw/i40iw_hw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/i40iw/i40iw_hw.c
@@ -313,7 +313,7 @@
 					    __func__, info->qp_cq_id);
 				continue;
 			}
-			i40iw_add_ref(&iwqp->ibqp);
+			i40iw_qp_add_ref(&iwqp->ibqp);
 			spin_unlock_irqrestore(&iwdev->qptable_lock, flags);
 			qp = &iwqp->sc_qp;
 			spin_lock_irqsave(&iwqp->lock, flags);
@@ -427,7 +427,7 @@
 			break;
 		}
 		if (info->qp)
-			i40iw_rem_ref(&iwqp->ibqp);
+			i40iw_qp_rem_ref(&iwqp->ibqp);
 	} while (1);
 
 	if (aeqcnt)
@@ -534,7 +534,7 @@
 	int arp_index;
 
 	arp_index = i40iw_arp_table(iwdev, ip_addr, ipv4, mac_addr, action);
-	if (arp_index == -1)
+	if (arp_index < 0)
 		return;
 	cqp_request = i40iw_get_cqp_request(&iwdev->cqp, false);
 	if (!cqp_request)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/i40iw/i40iw_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/i40iw/i40iw_main.c
@@ -54,10 +54,6 @@
 #define DRV_VERSION	__stringify(DRV_VERSION_MAJOR) "."		\
 	__stringify(DRV_VERSION_MINOR) "." __stringify(DRV_VERSION_BUILD)
 
-static int push_mode;
-module_param(push_mode, int, 0644);
-MODULE_PARM_DESC(push_mode, "Low latency mode: 0=disabled (default), 1=enabled)");
-
 static int debug;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "debug flags: 0=disabled (default), 0x7fffffff=all");
@@ -1225,6 +1221,8 @@
 			const struct in_ifaddr *ifa;
 
 			idev = in_dev_get(dev);
+			if (!idev)
+				continue;
 			in_dev_for_each_ifa_rtnl(ifa, idev) {
 				i40iw_debug(&iwdev->sc_dev, I40IW_DEBUG_CM,
 					    "IP=%pI4, vlan_id=%d, MAC=%pM\n", &ifa->ifa_address,
@@ -1586,7 +1584,6 @@
 	if (status)
 		goto exit;
 	iwdev->obj_next = iwdev->obj_mem;
-	iwdev->push_mode = push_mode;
 
 	init_waitqueue_head(&iwdev->vchnl_waitq);
 	init_waitqueue_head(&dev->vf_reqs);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/i40iw/i40iw_pble.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/i40iw/i40iw_pble.c
@@ -392,12 +392,9 @@
 	i40iw_debug(dev, I40IW_DEBUG_PBLE, "next_fpm_addr = %llx chunk_size[%u] = 0x%x\n",
 		    pble_rsrc->next_fpm_addr, chunk->size, chunk->size);
 	pble_rsrc->unallocated_pble -= (chunk->size >> 3);
-	list_add(&chunk->list, &pble_rsrc->pinfo.clist);
 	sd_reg_val = (sd_entry_type == I40IW_SD_TYPE_PAGED) ?
 			sd_entry->u.pd_table.pd_page_addr.pa : sd_entry->u.bp.addr.pa;
-	if (sd_entry->valid)
-		return 0;
-	if (dev->is_pf) {
+	if (dev->is_pf && !sd_entry->valid) {
 		ret_code = i40iw_hmc_sd_one(dev, hmc_info->hmc_fn_id,
 					    sd_reg_val, idx->sd_idx,
 					    sd_entry->entry_type, true);
@@ -408,6 +405,7 @@
 	}
 
 	sd_entry->valid = true;
+	list_add(&chunk->list, &pble_rsrc->pinfo.clist);
 	return 0;
  error:
 	kfree(chunk);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/i40iw/i40iw_type.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/i40iw/i40iw_type.h
@@ -779,6 +779,7 @@
 	bool use_hmc_fcn_index;
 	u8 hmc_fcn_index;
 	bool use_pf_rid;
+	bool all_memory;
 };
 
 struct i40iw_reg_ns_stag_info {
@@ -797,6 +798,7 @@
 	bool use_hmc_fcn_index;
 	u8 hmc_fcn_index;
 	bool use_pf_rid;
+	bool all_memory;
 };
 
 struct i40iw_fast_reg_stag_info {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/i40iw/i40iw_utils.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/i40iw/i40iw_utils.c
@@ -480,25 +480,6 @@
 }
 
 /**
- * i40iw_free_qp - callback after destroy cqp completes
- * @cqp_request: cqp request for destroy qp
- * @num: not used
- */
-static void i40iw_free_qp(struct i40iw_cqp_request *cqp_request, u32 num)
-{
-	struct i40iw_sc_qp *qp = (struct i40iw_sc_qp *)cqp_request->param;
-	struct i40iw_qp *iwqp = (struct i40iw_qp *)qp->back_qp;
-	struct i40iw_device *iwdev;
-	u32 qp_num = iwqp->ibqp.qp_num;
-
-	iwdev = iwqp->iwdev;
-
-	i40iw_rem_pdusecount(iwqp->iwpd, iwdev);
-	i40iw_free_qp_resources(iwdev, iwqp, qp_num);
-	i40iw_rem_devusecount(iwdev);
-}
-
-/**
  * i40iw_wait_event - wait for completion
  * @iwdev: iwarp device
  * @cqp_request: cqp request to wait
@@ -618,26 +599,23 @@
 }
 
 /**
- * i40iw_add_ref - add refcount for qp
+ * i40iw_qp_add_ref - add refcount for qp
  * @ibqp: iqarp qp
  */
-void i40iw_add_ref(struct ib_qp *ibqp)
+void i40iw_qp_add_ref(struct ib_qp *ibqp)
 {
 	struct i40iw_qp *iwqp = (struct i40iw_qp *)ibqp;
 
-	atomic_inc(&iwqp->refcount);
+	refcount_inc(&iwqp->refcount);
 }
 
 /**
- * i40iw_rem_ref - rem refcount for qp and free if 0
+ * i40iw_qp_rem_ref - rem refcount for qp and free if 0
  * @ibqp: iqarp qp
  */
-void i40iw_rem_ref(struct ib_qp *ibqp)
+void i40iw_qp_rem_ref(struct ib_qp *ibqp)
 {
 	struct i40iw_qp *iwqp;
-	enum i40iw_status_code status;
-	struct i40iw_cqp_request *cqp_request;
-	struct cqp_commands_info *cqp_info;
 	struct i40iw_device *iwdev;
 	u32 qp_num;
 	unsigned long flags;
@@ -645,7 +623,7 @@
 	iwqp = to_iwqp(ibqp);
 	iwdev = iwqp->iwdev;
 	spin_lock_irqsave(&iwdev->qptable_lock, flags);
-	if (!atomic_dec_and_test(&iwqp->refcount)) {
+	if (!refcount_dec_and_test(&iwqp->refcount)) {
 		spin_unlock_irqrestore(&iwdev->qptable_lock, flags);
 		return;
 	}
@@ -653,25 +631,8 @@
 	qp_num = iwqp->ibqp.qp_num;
 	iwdev->qp_table[qp_num] = NULL;
 	spin_unlock_irqrestore(&iwdev->qptable_lock, flags);
-	cqp_request = i40iw_get_cqp_request(&iwdev->cqp, false);
-	if (!cqp_request)
-		return;
-
-	cqp_request->callback_fcn = i40iw_free_qp;
-	cqp_request->param = (void *)&iwqp->sc_qp;
-	cqp_info = &cqp_request->info;
-	cqp_info->cqp_cmd = OP_QP_DESTROY;
-	cqp_info->post_sq = 1;
-	cqp_info->in.u.qp_destroy.qp = &iwqp->sc_qp;
-	cqp_info->in.u.qp_destroy.scratch = (uintptr_t)cqp_request;
-	cqp_info->in.u.qp_destroy.remove_hash_idx = true;
-	status = i40iw_handle_cqp_op(iwdev, cqp_request);
-	if (!status)
-		return;
+	complete(&iwqp->free_qp);
 
-	i40iw_rem_pdusecount(iwqp->iwpd, iwdev);
-	i40iw_free_qp_resources(iwdev, iwqp, qp_num);
-	i40iw_rem_devusecount(iwdev);
 }
 
 /**
@@ -938,7 +899,7 @@
 	struct i40iw_sc_qp *qp = (struct i40iw_sc_qp *)&iwqp->sc_qp;
 
 	i40iw_terminate_done(qp, 1);
-	i40iw_rem_ref(&iwqp->ibqp);
+	i40iw_qp_rem_ref(&iwqp->ibqp);
 }
 
 /**
@@ -950,7 +911,7 @@
 	struct i40iw_qp *iwqp;
 
 	iwqp = (struct i40iw_qp *)qp->back_qp;
-	i40iw_add_ref(&iwqp->ibqp);
+	i40iw_qp_add_ref(&iwqp->ibqp);
 	timer_setup(&iwqp->terminate_timer, i40iw_terminate_timeout, 0);
 	iwqp->terminate_timer.expires = jiffies + HZ;
 	add_timer(&iwqp->terminate_timer);
@@ -966,7 +927,7 @@
 
 	iwqp = (struct i40iw_qp *)qp->back_qp;
 	if (del_timer(&iwqp->terminate_timer))
-		i40iw_rem_ref(&iwqp->ibqp);
+		i40iw_qp_rem_ref(&iwqp->ibqp);
 }
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/i40iw/i40iw_verbs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/i40iw/i40iw_verbs.c
@@ -168,38 +168,16 @@
  */
 static int i40iw_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
 {
-	struct i40iw_ucontext *ucontext;
-	u64 db_addr_offset;
-	u64 push_offset;
-
-	ucontext = to_ucontext(context);
-	if (ucontext->iwdev->sc_dev.is_pf) {
-		db_addr_offset = I40IW_DB_ADDR_OFFSET;
-		push_offset = I40IW_PUSH_OFFSET;
-		if (vma->vm_pgoff)
-			vma->vm_pgoff += I40IW_PF_FIRST_PUSH_PAGE_INDEX - 1;
-	} else {
-		db_addr_offset = I40IW_VF_DB_ADDR_OFFSET;
-		push_offset = I40IW_VF_PUSH_OFFSET;
-		if (vma->vm_pgoff)
-			vma->vm_pgoff += I40IW_VF_FIRST_PUSH_PAGE_INDEX - 1;
-	}
+	struct i40iw_ucontext *ucontext = to_ucontext(context);
+	u64 dbaddr;
 
-	vma->vm_pgoff += db_addr_offset >> PAGE_SHIFT;
+	if (vma->vm_pgoff || vma->vm_end - vma->vm_start != PAGE_SIZE)
+		return -EINVAL;
 
-	if (vma->vm_pgoff == (db_addr_offset >> PAGE_SHIFT)) {
-		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-		vma->vm_private_data = ucontext;
-	} else {
-		if ((vma->vm_pgoff - (push_offset >> PAGE_SHIFT)) % 2)
-			vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-		else
-			vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
-	}
+	dbaddr = I40IW_DB_ADDR_OFFSET + pci_resource_start(ucontext->iwdev->ldev->pcidev, 0);
 
-	if (io_remap_pfn_range(vma, vma->vm_start,
-			       vma->vm_pgoff + (pci_resource_start(ucontext->iwdev->ldev->pcidev, 0) >> PAGE_SHIFT),
-			       PAGE_SIZE, vma->vm_page_prot))
+	if (io_remap_pfn_range(vma, vma->vm_start, dbaddr >> PAGE_SHIFT, PAGE_SIZE,
+			       pgprot_noncached(vma->vm_page_prot)))
 		return -EAGAIN;
 
 	return 0;
@@ -366,11 +344,11 @@
  * @iwqp: qp ptr (user or kernel)
  * @qp_num: qp number assigned
  */
-void i40iw_free_qp_resources(struct i40iw_device *iwdev,
-			     struct i40iw_qp *iwqp,
-			     u32 qp_num)
+void i40iw_free_qp_resources(struct i40iw_qp *iwqp)
 {
 	struct i40iw_pbl *iwpbl = &iwqp->iwpbl;
+	struct i40iw_device *iwdev = iwqp->iwdev;
+	u32 qp_num = iwqp->ibqp.qp_num;
 
 	i40iw_ieq_cleanup_qp(iwdev->vsi.ieq, &iwqp->sc_qp);
 	i40iw_dealloc_push_page(iwdev, &iwqp->sc_qp);
@@ -404,6 +382,10 @@
 static int i40iw_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata)
 {
 	struct i40iw_qp *iwqp = to_iwqp(ibqp);
+	struct ib_qp_attr attr;
+	struct i40iw_device *iwdev = iwqp->iwdev;
+
+	memset(&attr, 0, sizeof(attr));
 
 	iwqp->destroyed = 1;
 
@@ -418,7 +400,15 @@
 		}
 	}
 
-	i40iw_rem_ref(&iwqp->ibqp);
+	attr.qp_state = IB_QPS_ERR;
+	i40iw_modify_qp(&iwqp->ibqp, &attr, IB_QP_STATE, NULL);
+	i40iw_qp_rem_ref(&iwqp->ibqp);
+	wait_for_completion(&iwqp->free_qp);
+	i40iw_cqp_qp_destroy_cmd(&iwdev->sc_dev, &iwqp->sc_qp);
+	i40iw_rem_pdusecount(iwqp->iwpd, iwdev);
+	i40iw_free_qp_resources(iwqp);
+	i40iw_rem_devusecount(iwdev);
+
 	return 0;
 }
 
@@ -579,6 +569,7 @@
 	qp->back_qp = (void *)iwqp;
 	qp->push_idx = I40IW_INVALID_PUSH_PAGE_INDEX;
 
+	iwqp->iwdev = iwdev;
 	iwqp->ctx_info.iwarp_info = &iwqp->iwarp_info;
 
 	if (i40iw_allocate_dma_mem(dev->hw,
@@ -603,7 +594,6 @@
 		goto error;
 	}
 
-	iwqp->iwdev = iwdev;
 	iwqp->iwpd = iwpd;
 	iwqp->ibqp.qp_num = qp_num;
 	qp = &iwqp->sc_qp;
@@ -717,7 +707,7 @@
 		goto error;
 	}
 
-	i40iw_add_ref(&iwqp->ibqp);
+	refcount_set(&iwqp->refcount, 1);
 	spin_lock_init(&iwqp->lock);
 	iwqp->sig_all = (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR) ? 1 : 0;
 	iwdev->qp_table[qp_num] = iwqp;
@@ -739,10 +729,11 @@
 	}
 	init_completion(&iwqp->sq_drained);
 	init_completion(&iwqp->rq_drained);
+	init_completion(&iwqp->free_qp);
 
 	return &iwqp->ibqp;
 error:
-	i40iw_free_qp_resources(iwdev, iwqp, qp_num);
+	i40iw_free_qp_resources(iwqp);
 	return ERR_PTR(err_code);
 }
 
@@ -1509,7 +1500,8 @@
 static int i40iw_hw_alloc_stag(struct i40iw_device *iwdev, struct i40iw_mr *iwmr)
 {
 	struct i40iw_allocate_stag_info *info;
-	struct i40iw_pd *iwpd = to_iwpd(iwmr->ibmr.pd);
+	struct ib_pd *pd = iwmr->ibmr.pd;
+	struct i40iw_pd *iwpd = to_iwpd(pd);
 	enum i40iw_status_code status;
 	int err = 0;
 	struct i40iw_cqp_request *cqp_request;
@@ -1526,6 +1518,7 @@
 	info->stag_idx = iwmr->stag >> I40IW_CQPSQ_STAG_IDX_SHIFT;
 	info->pd_id = iwpd->sc_pd.pd_id;
 	info->total_len = iwmr->length;
+	info->all_memory = pd->flags & IB_PD_UNSAFE_GLOBAL_RKEY;
 	info->remote_access = true;
 	cqp_info->cqp_cmd = OP_ALLOC_STAG;
 	cqp_info->post_sq = 1;
@@ -1579,6 +1572,8 @@
 	iwmr->type = IW_MEMREG_TYPE_MEM;
 	palloc = &iwpbl->pble_alloc;
 	iwmr->page_cnt = max_num_sg;
+	/* Use system PAGE_SIZE as the sg page sizes are unknown at this point */
+	iwmr->length = max_num_sg * PAGE_SIZE;
 	mutex_lock(&iwdev->pbl_mutex);
 	status = i40iw_get_pble(&iwdev->sc_dev, iwdev->pble_rsrc, palloc, iwmr->page_cnt);
 	mutex_unlock(&iwdev->pbl_mutex);
@@ -1675,7 +1670,8 @@
 {
 	struct i40iw_pbl *iwpbl = &iwmr->iwpbl;
 	struct i40iw_reg_ns_stag_info *stag_info;
-	struct i40iw_pd *iwpd = to_iwpd(iwmr->ibmr.pd);
+	struct ib_pd *pd = iwmr->ibmr.pd;
+	struct i40iw_pd *iwpd = to_iwpd(pd);
 	struct i40iw_pble_alloc *palloc = &iwpbl->pble_alloc;
 	enum i40iw_status_code status;
 	int err = 0;
@@ -1695,6 +1691,7 @@
 	stag_info->total_len = iwmr->length;
 	stag_info->access_rights = access;
 	stag_info->pd_id = iwpd->sc_pd.pd_id;
+	stag_info->all_memory = pd->flags & IB_PD_UNSAFE_GLOBAL_RKEY;
 	stag_info->addr_type = I40IW_ADDR_TYPE_VA_BASED;
 	stag_info->page_size = iwmr->page_size;
 
@@ -1763,7 +1760,7 @@
 
 	if (length > I40IW_MAX_MR_SIZE)
 		return ERR_PTR(-EINVAL);
-	region = ib_umem_get(udata, start, length, acc, 0);
+	region = ib_umem_get(pd->device, start, length, acc);
 	if (IS_ERR(region))
 		return (struct ib_mr *)region;
 
@@ -2654,13 +2651,13 @@
 	.get_hw_stats = i40iw_get_hw_stats,
 	.get_port_immutable = i40iw_port_immutable,
 	.iw_accept = i40iw_accept,
-	.iw_add_ref = i40iw_add_ref,
+	.iw_add_ref = i40iw_qp_add_ref,
 	.iw_connect = i40iw_connect,
 	.iw_create_listen = i40iw_create_listen,
 	.iw_destroy_listen = i40iw_destroy_listen,
 	.iw_get_qp = i40iw_get_qp,
 	.iw_reject = i40iw_reject,
-	.iw_rem_ref = i40iw_rem_ref,
+	.iw_rem_ref = i40iw_qp_rem_ref,
 	.map_mr_sg = i40iw_map_mr_sg,
 	.mmap = i40iw_mmap,
 	.modify_qp = i40iw_modify_qp,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/i40iw/i40iw_verbs.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/i40iw/i40iw_verbs.h
@@ -140,7 +140,7 @@
 	struct i40iw_qp_host_ctx_info ctx_info;
 	struct i40iwarp_offload_info iwarp_info;
 	void *allocated_buffer;
-	atomic_t refcount;
+	refcount_t refcount;
 	struct iw_cm_id *cm_id;
 	void *cm_node;
 	struct ib_mr *lsmm_mr;
@@ -175,5 +175,6 @@
 	struct i40iw_dma_mem ietf_mem;
 	struct completion sq_drained;
 	struct completion rq_drained;
+	struct completion free_qp;
 };
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/mlx4/alias_GUID.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/mlx4/alias_GUID.c
@@ -832,7 +832,7 @@
 
 int mlx4_ib_init_alias_guid_service(struct mlx4_ib_dev *dev)
 {
-	char alias_wq_name[15];
+	char alias_wq_name[22];
 	int ret = 0;
 	int i, j;
 	union ib_gid gid;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/mlx4/cm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/mlx4/cm.c
@@ -186,23 +186,6 @@
 	kfree(ent);
 }
 
-static void id_map_find_del(struct ib_device *ibdev, int pv_cm_id)
-{
-	struct mlx4_ib_sriov *sriov = &to_mdev(ibdev)->sriov;
-	struct rb_root *sl_id_map = &sriov->sl_id_map;
-	struct id_map_entry *ent, *found_ent;
-
-	spin_lock(&sriov->id_map_lock);
-	ent = xa_erase(&sriov->pv_id_table, pv_cm_id);
-	if (!ent)
-		goto out;
-	found_ent = id_map_find_by_sl_id(ibdev, ent->slave_id, ent->sl_cm_id);
-	if (found_ent && found_ent == ent)
-		rb_erase(&found_ent->node, sl_id_map);
-out:
-	spin_unlock(&sriov->id_map_lock);
-}
-
 static void sl_id_map_add(struct ib_device *ibdev, struct id_map_entry *new)
 {
 	struct rb_root *sl_id_map = &to_mdev(ibdev)->sriov.sl_id_map;
@@ -294,9 +277,12 @@
 	spin_lock(&sriov->id_map_lock);
 	spin_lock_irqsave(&sriov->going_down_lock, flags);
 	/*make sure that there is no schedule inside the scheduled work.*/
-	if (!sriov->is_going_down) {
+	if (!sriov->is_going_down && !id->scheduled_delete) {
 		id->scheduled_delete = 1;
 		schedule_delayed_work(&id->timeout, CM_CLEANUP_CACHE_TIMEOUT);
+	} else if (id->scheduled_delete) {
+		/* Adjust timeout if already scheduled */
+		mod_delayed_work(system_wq, &id->timeout, CM_CLEANUP_CACHE_TIMEOUT);
 	}
 	spin_unlock_irqrestore(&sriov->going_down_lock, flags);
 	spin_unlock(&sriov->id_map_lock);
@@ -341,9 +327,6 @@
 
 	if (mad->mad_hdr.attr_id == CM_DREQ_ATTR_ID)
 		schedule_delayed(ibdev, id);
-	else if (mad->mad_hdr.attr_id == CM_DREP_ATTR_ID)
-		id_map_find_del(ibdev, pv_cm_id);
-
 	return 0;
 }
 
@@ -382,12 +365,9 @@
 		*slave = id->slave_id;
 	set_remote_comm_id(mad, id->sl_cm_id);
 
-	if (mad->mad_hdr.attr_id == CM_DREQ_ATTR_ID)
+	if (mad->mad_hdr.attr_id == CM_DREQ_ATTR_ID ||
+	    mad->mad_hdr.attr_id == CM_REJ_ATTR_ID)
 		schedule_delayed(ibdev, id);
-	else if (mad->mad_hdr.attr_id == CM_REJ_ATTR_ID ||
-			mad->mad_hdr.attr_id == CM_DREP_ATTR_ID) {
-		id_map_find_del(ibdev, (int) pv_cm_id);
-	}
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/mlx4/cq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/mlx4/cq.c
@@ -144,8 +144,8 @@
 	int shift;
 	int n;
 
-	*umem = ib_umem_get(udata, buf_addr, cqe * cqe_size,
-			    IB_ACCESS_LOCAL_WRITE, 1);
+	*umem = ib_umem_get(&dev->ib_dev, buf_addr, cqe * cqe_size,
+			    IB_ACCESS_LOCAL_WRITE);
 	if (IS_ERR(*umem))
 		return PTR_ERR(*umem);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/mlx4/doorbell.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/mlx4/doorbell.c
@@ -64,7 +64,8 @@
 
 	page->user_virt = (virt & PAGE_MASK);
 	page->refcnt    = 0;
-	page->umem = ib_umem_get(udata, virt & PAGE_MASK, PAGE_SIZE, 0, 0);
+	page->umem = ib_umem_get(context->ibucontext.device, virt & PAGE_MASK,
+				 PAGE_SIZE, 0);
 	if (IS_ERR(page->umem)) {
 		err = PTR_ERR(page->umem);
 		kfree(page);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/mlx4/mad.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/mlx4/mad.c
@@ -1307,6 +1307,18 @@
 	spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags);
 }
 
+static void mlx4_ib_wire_comp_handler(struct ib_cq *cq, void *arg)
+{
+	unsigned long flags;
+	struct mlx4_ib_demux_pv_ctx *ctx = cq->cq_context;
+	struct mlx4_ib_dev *dev = to_mdev(ctx->ib_dev);
+
+	spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
+	if (!dev->sriov.is_going_down && ctx->state == DEMUX_PV_STATE_ACTIVE)
+		queue_work(ctx->wi_wq, &ctx->work);
+	spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags);
+}
+
 static int mlx4_ib_post_pv_qp_buf(struct mlx4_ib_demux_pv_ctx *ctx,
 				  struct mlx4_ib_demux_pv_qp *tun_qp,
 				  int index)
@@ -2009,7 +2021,8 @@
 		cq_size *= 2;
 
 	cq_attr.cqe = cq_size;
-	ctx->cq = ib_create_cq(ctx->ib_dev, mlx4_ib_tunnel_comp_handler,
+	ctx->cq = ib_create_cq(ctx->ib_dev,
+			       create_tun ? mlx4_ib_tunnel_comp_handler : mlx4_ib_wire_comp_handler,
 			       NULL, ctx, &cq_attr);
 	if (IS_ERR(ctx->cq)) {
 		ret = PTR_ERR(ctx->cq);
@@ -2046,6 +2059,7 @@
 		INIT_WORK(&ctx->work, mlx4_ib_sqp_comp_worker);
 
 	ctx->wq = to_mdev(ibdev)->sriov.demux[port - 1].wq;
+	ctx->wi_wq = to_mdev(ibdev)->sriov.demux[port - 1].wi_wq;
 
 	ret = ib_req_notify_cq(ctx->cq, IB_CQ_NEXT_COMP);
 	if (ret) {
@@ -2153,7 +2167,7 @@
 				       struct mlx4_ib_demux_ctx *ctx,
 				       int port)
 {
-	char name[12];
+	char name[21];
 	int ret = 0;
 	int i;
 
@@ -2189,7 +2203,7 @@
 		goto err_mcg;
 	}
 
-	snprintf(name, sizeof name, "mlx4_ibt%d", port);
+	snprintf(name, sizeof(name), "mlx4_ibt%d", port);
 	ctx->wq = alloc_ordered_workqueue(name, WQ_MEM_RECLAIM);
 	if (!ctx->wq) {
 		pr_err("Failed to create tunnelling WQ for port %d\n", port);
@@ -2197,7 +2211,15 @@
 		goto err_wq;
 	}
 
-	snprintf(name, sizeof name, "mlx4_ibud%d", port);
+	snprintf(name, sizeof(name), "mlx4_ibwi%d", port);
+	ctx->wi_wq = alloc_ordered_workqueue(name, WQ_MEM_RECLAIM);
+	if (!ctx->wi_wq) {
+		pr_err("Failed to create wire WQ for port %d\n", port);
+		ret = -ENOMEM;
+		goto err_wiwq;
+	}
+
+	snprintf(name, sizeof(name), "mlx4_ibud%d", port);
 	ctx->ud_wq = alloc_ordered_workqueue(name, WQ_MEM_RECLAIM);
 	if (!ctx->ud_wq) {
 		pr_err("Failed to create up/down WQ for port %d\n", port);
@@ -2208,6 +2230,10 @@
 	return 0;
 
 err_udwq:
+	destroy_workqueue(ctx->wi_wq);
+	ctx->wi_wq = NULL;
+
+err_wiwq:
 	destroy_workqueue(ctx->wq);
 	ctx->wq = NULL;
 
@@ -2255,12 +2281,14 @@
 				ctx->tun[i]->state = DEMUX_PV_STATE_DOWNING;
 		}
 		flush_workqueue(ctx->wq);
+		flush_workqueue(ctx->wi_wq);
 		for (i = 0; i < dev->dev->caps.sqp_demux; i++) {
 			destroy_pv_resources(dev, i, ctx->port, ctx->tun[i], 0);
 			free_pv_object(dev, i, ctx->port);
 		}
 		kfree(ctx->tun);
 		destroy_workqueue(ctx->ud_wq);
+		destroy_workqueue(ctx->wi_wq);
 		destroy_workqueue(ctx->wq);
 	}
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/mlx4/main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/mlx4/main.c
@@ -246,6 +246,13 @@
 	return mlx4_ib_update_gids_v1(gids, ibdev, port_num);
 }
 
+static void free_gid_entry(struct gid_entry *entry)
+{
+	memset(&entry->gid, 0, sizeof(entry->gid));
+	kfree(entry->ctx);
+	entry->ctx = NULL;
+}
+
 static int mlx4_ib_add_gid(const struct ib_gid_attr *attr, void **context)
 {
 	struct mlx4_ib_dev *ibdev = to_mdev(attr->device);
@@ -306,6 +313,8 @@
 				     GFP_ATOMIC);
 		if (!gids) {
 			ret = -ENOMEM;
+			*context = NULL;
+			free_gid_entry(&port_gid_table->gids[free]);
 		} else {
 			for (i = 0; i < MLX4_MAX_PORT_GIDS; i++) {
 				memcpy(&gids[i].gid, &port_gid_table->gids[i].gid, sizeof(union ib_gid));
@@ -317,6 +326,12 @@
 
 	if (!ret && hw_update) {
 		ret = mlx4_ib_update_gids(gids, ibdev, attr->port_num);
+		if (ret) {
+			spin_lock_bh(&iboe->lock);
+			*context = NULL;
+			free_gid_entry(&port_gid_table->gids[free]);
+			spin_unlock_bh(&iboe->lock);
+		}
 		kfree(gids);
 	}
 
@@ -346,10 +361,7 @@
 		if (!ctx->refcount) {
 			unsigned int real_index = ctx->real_index;
 
-			memset(&port_gid_table->gids[real_index].gid, 0,
-			       sizeof(port_gid_table->gids[real_index].gid));
-			kfree(port_gid_table->gids[real_index].ctx);
-			port_gid_table->gids[real_index].ctx = NULL;
+			free_gid_entry(&port_gid_table->gids[real_index]);
 			hw_update = 1;
 		}
 	}
@@ -372,10 +384,10 @@
 	}
 	spin_unlock_bh(&iboe->lock);
 
-	if (!ret && hw_update) {
+	if (gids)
 		ret = mlx4_ib_update_gids(gids, ibdev, attr->port_num);
-		kfree(gids);
-	}
+
+	kfree(gids);
 	return ret;
 }
 
@@ -565,12 +577,9 @@
 	props->cq_caps.max_cq_moderation_count = MLX4_MAX_CQ_COUNT;
 	props->cq_caps.max_cq_moderation_period = MLX4_MAX_CQ_PERIOD;
 
-	if (!mlx4_is_slave(dev->dev))
-		err = mlx4_get_internal_clock_params(dev->dev, &clock_params);
-
 	if (uhw->outlen >= resp.response_length + sizeof(resp.hca_core_clock_offset)) {
 		resp.response_length += sizeof(resp.hca_core_clock_offset);
-		if (!err && !mlx4_is_slave(dev->dev)) {
+		if (!mlx4_get_internal_clock_params(dev->dev, &clock_params)) {
 			resp.comp_mask |= MLX4_IB_QUERY_DEV_RESP_MASK_CORE_CLOCK_OFFSET;
 			resp.hca_core_clock_offset = clock_params.offset % PAGE_SIZE;
 		}
@@ -769,7 +778,8 @@
 	props->ip_gids = true;
 	props->gid_tbl_len	= mdev->dev->caps.gid_table_len[port];
 	props->max_msg_sz	= mdev->dev->caps.max_msg_sz;
-	props->pkey_tbl_len	= 1;
+	if (mdev->dev->caps.pkey_table_len[port])
+		props->pkey_tbl_len = 1;
 	props->max_mtu		= IB_MTU_4096;
 	props->max_vl_num	= 2;
 	props->state		= IB_PORT_DOWN;
@@ -1146,7 +1156,8 @@
 		return rdma_user_mmap_io(context, vma,
 					 to_mucontext(context)->uar.pfn,
 					 PAGE_SIZE,
-					 pgprot_noncached(vma->vm_page_prot));
+					 pgprot_noncached(vma->vm_page_prot),
+					 NULL);
 
 	case 1:
 		if (dev->dev->caps.bf_reg_size == 0)
@@ -1155,7 +1166,8 @@
 			context, vma,
 			to_mucontext(context)->uar.pfn +
 				dev->dev->caps.num_uars,
-			PAGE_SIZE, pgprot_writecombine(vma->vm_page_prot));
+			PAGE_SIZE, pgprot_writecombine(vma->vm_page_prot),
+			NULL);
 
 	case 3: {
 		struct mlx4_clock_params params;
@@ -1171,7 +1183,8 @@
 					    params.bar) +
 			 params.offset) >>
 				PAGE_SHIFT,
-			PAGE_SIZE, pgprot_noncached(vma->vm_page_prot));
+			PAGE_SIZE, pgprot_noncached(vma->vm_page_prot),
+			NULL);
 	}
 
 	default:
@@ -1480,8 +1493,9 @@
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(pdefault_rules->rules_create_list); i++) {
+		union ib_flow_spec ib_spec = {};
 		int ret;
-		union ib_flow_spec ib_spec;
+
 		switch (pdefault_rules->rules_create_list[i]) {
 		case 0:
 			/* no rule */
@@ -3008,16 +3022,17 @@
 	ibdev->ib_active = false;
 	flush_workqueue(wq);
 
-	mlx4_ib_close_sriov(ibdev);
-	mlx4_ib_mad_cleanup(ibdev);
-	ib_unregister_device(&ibdev->ib_dev);
-	mlx4_ib_diag_cleanup(ibdev);
 	if (ibdev->iboe.nb.notifier_call) {
 		if (unregister_netdevice_notifier(&ibdev->iboe.nb))
 			pr_warn("failure unregistering notifier\n");
 		ibdev->iboe.nb.notifier_call = NULL;
 	}
 
+	mlx4_ib_close_sriov(ibdev);
+	mlx4_ib_mad_cleanup(ibdev);
+	ib_unregister_device(&ibdev->ib_dev);
+	mlx4_ib_diag_cleanup(ibdev);
+
 	mlx4_qp_release_range(dev, ibdev->steer_qpn_base,
 			      ibdev->steer_qpn_count);
 	kfree(ibdev->ib_uc_qpns_bitmap);
@@ -3279,7 +3294,7 @@
 	case MLX4_DEV_EVENT_PORT_MGMT_CHANGE:
 		ew = kmalloc(sizeof *ew, GFP_ATOMIC);
 		if (!ew)
-			break;
+			return;
 
 		INIT_WORK(&ew->work, handle_port_mgmt_change_event);
 		memcpy(&ew->ib_eqe, eqe, sizeof *eqe);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/mlx4/mlx4_ib.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/mlx4/mlx4_ib.h
@@ -459,6 +459,7 @@
 	struct ib_pd *pd;
 	struct work_struct work;
 	struct workqueue_struct *wq;
+	struct workqueue_struct *wi_wq;
 	struct mlx4_ib_demux_pv_qp qp[2];
 };
 
@@ -466,6 +467,7 @@
 	struct ib_device *ib_dev;
 	int port;
 	struct workqueue_struct *wq;
+	struct workqueue_struct *wi_wq;
 	struct workqueue_struct *ud_wq;
 	spinlock_t ud_lock;
 	atomic64_t subnet_prefix;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/mlx4/mr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/mlx4/mr.c
@@ -367,7 +367,7 @@
 	return block_shift;
 }
 
-static struct ib_umem *mlx4_get_umem_mr(struct ib_udata *udata, u64 start,
+static struct ib_umem *mlx4_get_umem_mr(struct ib_device *device, u64 start,
 					u64 length, int access_flags)
 {
 	/*
@@ -398,7 +398,7 @@
 		up_read(&current->mm->mmap_sem);
 	}
 
-	return ib_umem_get(udata, start, length, access_flags, 0);
+	return ib_umem_get(device, start, length, access_flags);
 }
 
 struct ib_mr *mlx4_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
@@ -415,7 +415,7 @@
 	if (!mr)
 		return ERR_PTR(-ENOMEM);
 
-	mr->umem = mlx4_get_umem_mr(udata, start, length, access_flags);
+	mr->umem = mlx4_get_umem_mr(pd->device, start, length, access_flags);
 	if (IS_ERR(mr->umem)) {
 		err = PTR_ERR(mr->umem);
 		goto err_free;
@@ -439,7 +439,6 @@
 
 	mr->ibmr.rkey = mr->ibmr.lkey = mr->mmr.key;
 	mr->ibmr.length = length;
-	mr->ibmr.iova = virt_addr;
 	mr->ibmr.page_size = 1U << shift;
 
 	return &mr->ibmr;
@@ -504,7 +503,7 @@
 
 		mlx4_mr_rereg_mem_cleanup(dev->dev, &mmr->mmr);
 		ib_umem_release(mmr->umem);
-		mmr->umem = mlx4_get_umem_mr(udata, start, length,
+		mmr->umem = mlx4_get_umem_mr(mr->device, start, length,
 					     mr_access_flags);
 		if (IS_ERR(mmr->umem)) {
 			err = PTR_ERR(mmr->umem);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/mlx4/qp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/mlx4/qp.c
@@ -438,9 +438,13 @@
 			    struct mlx4_ib_qp *qp,
 			    struct mlx4_ib_create_qp *ucmd)
 {
+	u32 cnt;
+
 	/* Sanity check SQ size before proceeding */
-	if ((1 << ucmd->log_sq_bb_count) > dev->dev->caps.max_wqes	 ||
-	    ucmd->log_sq_stride >
+	if (check_shl_overflow(1, ucmd->log_sq_bb_count, &cnt) ||
+	    cnt > dev->dev->caps.max_wqes)
+		return -EINVAL;
+	if (ucmd->log_sq_stride >
 		ilog2(roundup_pow_of_two(dev->dev->caps.max_sq_desc_sz)) ||
 	    ucmd->log_sq_stride < MLX4_IB_MIN_SQ_STRIDE)
 		return -EINVAL;
@@ -552,15 +556,15 @@
 		return (-EOPNOTSUPP);
 	}
 
-	if (ucmd->rx_hash_fields_mask & ~(MLX4_IB_RX_HASH_SRC_IPV4	|
-					  MLX4_IB_RX_HASH_DST_IPV4	|
-					  MLX4_IB_RX_HASH_SRC_IPV6	|
-					  MLX4_IB_RX_HASH_DST_IPV6	|
-					  MLX4_IB_RX_HASH_SRC_PORT_TCP	|
-					  MLX4_IB_RX_HASH_DST_PORT_TCP	|
-					  MLX4_IB_RX_HASH_SRC_PORT_UDP	|
-					  MLX4_IB_RX_HASH_DST_PORT_UDP  |
-					  MLX4_IB_RX_HASH_INNER)) {
+	if (ucmd->rx_hash_fields_mask & ~(u64)(MLX4_IB_RX_HASH_SRC_IPV4	|
+					       MLX4_IB_RX_HASH_DST_IPV4	|
+					       MLX4_IB_RX_HASH_SRC_IPV6	|
+					       MLX4_IB_RX_HASH_DST_IPV6	|
+					       MLX4_IB_RX_HASH_SRC_PORT_TCP |
+					       MLX4_IB_RX_HASH_DST_PORT_TCP |
+					       MLX4_IB_RX_HASH_SRC_PORT_UDP |
+					       MLX4_IB_RX_HASH_DST_PORT_UDP |
+					       MLX4_IB_RX_HASH_INNER)) {
 		pr_debug("RX Hash fields_mask has unsupported mask (0x%llx)\n",
 			 ucmd->rx_hash_fields_mask);
 		return (-EOPNOTSUPP);
@@ -916,7 +920,7 @@
 	qp->buf_size = (qp->rq.wqe_cnt << qp->rq.wqe_shift) +
 		       (qp->sq.wqe_cnt << qp->sq.wqe_shift);
 
-	qp->umem = ib_umem_get(udata, wq.buf_addr, qp->buf_size, 0, 0);
+	qp->umem = ib_umem_get(pd->device, wq.buf_addr, qp->buf_size, 0);
 	if (IS_ERR(qp->umem)) {
 		err = PTR_ERR(qp->umem);
 		goto err;
@@ -1111,7 +1115,7 @@
 			goto err;
 
 		qp->umem =
-			ib_umem_get(udata, ucmd.buf_addr, qp->buf_size, 0, 0);
+			ib_umem_get(pd->device, ucmd.buf_addr, qp->buf_size, 0);
 		if (IS_ERR(qp->umem)) {
 			err = PTR_ERR(qp->umem);
 			goto err;
@@ -1149,8 +1153,10 @@
 			if (dev->steering_support ==
 			    MLX4_STEERING_MODE_DEVICE_MANAGED)
 				qp->flags |= MLX4_IB_QP_NETIF;
-			else
+			else {
+				err = -EINVAL;
 				goto err;
+			}
 		}
 
 		err = set_kernel_sq_size(dev, &init_attr->cap, qp_type, qp);
@@ -2891,6 +2897,7 @@
 	int send_size;
 	int header_size;
 	int spc;
+	int err;
 	int i;
 
 	if (wr->wr.opcode != IB_WR_SEND)
@@ -2925,7 +2932,9 @@
 
 	sqp->ud_header.lrh.virtual_lane    = 0;
 	sqp->ud_header.bth.solicited_event = !!(wr->wr.send_flags & IB_SEND_SOLICITED);
-	ib_get_cached_pkey(ib_dev, sqp->qp.port, 0, &pkey);
+	err = ib_get_cached_pkey(ib_dev, sqp->qp.port, 0, &pkey);
+	if (err)
+		return err;
 	sqp->ud_header.bth.pkey = cpu_to_be16(pkey);
 	if (sqp->qp.mlx4_ib_qp_type == MLX4_IB_QPT_TUN_SMI_OWNER)
 		sqp->ud_header.bth.destination_qpn = cpu_to_be32(wr->remote_qpn);
@@ -3212,9 +3221,14 @@
 	}
 	sqp->ud_header.bth.solicited_event = !!(wr->wr.send_flags & IB_SEND_SOLICITED);
 	if (!sqp->qp.ibqp.qp_num)
-		ib_get_cached_pkey(ib_dev, sqp->qp.port, sqp->pkey_index, &pkey);
+		err = ib_get_cached_pkey(ib_dev, sqp->qp.port, sqp->pkey_index,
+					 &pkey);
 	else
-		ib_get_cached_pkey(ib_dev, sqp->qp.port, wr->pkey_index, &pkey);
+		err = ib_get_cached_pkey(ib_dev, sqp->qp.port, wr->pkey_index,
+					 &pkey);
+	if (err)
+		return err;
+
 	sqp->ud_header.bth.pkey = cpu_to_be16(pkey);
 	sqp->ud_header.bth.destination_qpn = cpu_to_be32(wr->remote_qpn);
 	sqp->ud_header.bth.psn = cpu_to_be32((sqp->send_psn++) & ((1 << 24) - 1));
@@ -3533,11 +3547,11 @@
 	int nreq;
 	int err = 0;
 	unsigned ind;
-	int uninitialized_var(size);
-	unsigned uninitialized_var(seglen);
+	int size;
+	unsigned seglen;
 	__be32 dummy;
 	__be32 *lso_wqe;
-	__be32 uninitialized_var(lso_hdr_sz);
+	__be32 lso_hdr_sz;
 	__be32 blh;
 	int i;
 	struct mlx4_ib_dev *mdev = to_mdev(ibqp->device);
@@ -4286,13 +4300,8 @@
 	if (wq_attr_mask & IB_WQ_FLAGS)
 		return -EOPNOTSUPP;
 
-	cur_state = wq_attr_mask & IB_WQ_CUR_STATE ? wq_attr->curr_wq_state :
-						     ibwq->state;
-	new_state = wq_attr_mask & IB_WQ_STATE ? wq_attr->wq_state : cur_state;
-
-	if (cur_state  < IB_WQS_RESET || cur_state  > IB_WQS_ERR ||
-	    new_state < IB_WQS_RESET || new_state > IB_WQS_ERR)
-		return -EINVAL;
+	cur_state = wq_attr->curr_wq_state;
+	new_state = wq_attr->wq_state;
 
 	if ((new_state == IB_WQS_RDY) && (cur_state == IB_WQS_ERR))
 		return -EINVAL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/mlx4/srq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/mlx4/srq.c
@@ -110,7 +110,8 @@
 		if (ib_copy_from_udata(&ucmd, udata, sizeof(ucmd)))
 			return -EFAULT;
 
-		srq->umem = ib_umem_get(udata, ucmd.buf_addr, buf_size, 0, 0);
+		srq->umem =
+			ib_umem_get(ib_srq->device, ucmd.buf_addr, buf_size, 0);
 		if (IS_ERR(srq->umem))
 			return PTR_ERR(srq->umem);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/mlx4/sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/mlx4/sysfs.c
@@ -221,7 +221,7 @@
 static int add_port_entries(struct mlx4_ib_dev *device, int port_num)
 {
 	int i;
-	char buff[11];
+	char buff[12];
 	struct mlx4_ib_iov_port *port = NULL;
 	int ret = 0 ;
 	struct ib_port_attr attr;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/mlx5/cq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/mlx5/cq.c
@@ -167,7 +167,7 @@
 {
 	enum rdma_link_layer ll = rdma_port_get_link_layer(qp->ibqp.device, 1);
 	struct mlx5_ib_dev *dev = to_mdev(qp->ibqp.device);
-	struct mlx5_ib_srq *srq;
+	struct mlx5_ib_srq *srq = NULL;
 	struct mlx5_ib_wq *wq;
 	u16 wqe_ctr;
 	u8  roce_packet_type;
@@ -179,7 +179,8 @@
 
 		if (qp->ibqp.xrcd) {
 			msrq = mlx5_cmd_get_srq(dev, be32_to_cpu(cqe->srqn));
-			srq = to_mibsrq(msrq);
+			if (msrq)
+				srq = to_mibsrq(msrq);
 		} else {
 			srq = to_msrq(qp->ibqp.srq);
 		}
@@ -330,6 +331,22 @@
 		dump_cqe(dev, cqe);
 }
 
+static void handle_atomics(struct mlx5_ib_qp *qp, struct mlx5_cqe64 *cqe64,
+			   u16 tail, u16 head)
+{
+	u16 idx;
+
+	do {
+		idx = tail & (qp->sq.wqe_cnt - 1);
+		if (idx == head)
+			break;
+
+		tail = qp->sq.w_list[idx].next;
+	} while (1);
+	tail = qp->sq.w_list[idx].next;
+	qp->sq.last_poll = tail;
+}
+
 static void free_cq_buf(struct mlx5_ib_dev *dev, struct mlx5_ib_cq_buf *buf)
 {
 	mlx5_frag_buf_free(dev->mdev, &buf->frag_buf);
@@ -368,7 +385,7 @@
 }
 
 static void sw_comp(struct mlx5_ib_qp *qp, int num_entries, struct ib_wc *wc,
-		    int *npolled, int is_send)
+		    int *npolled, bool is_send)
 {
 	struct mlx5_ib_wq *wq;
 	unsigned int cur;
@@ -383,10 +400,16 @@
 		return;
 
 	for (i = 0;  i < cur && np < num_entries; i++) {
-		wc->wr_id = wq->wrid[wq->tail & (wq->wqe_cnt - 1)];
+		unsigned int idx;
+
+		idx = (is_send) ? wq->last_poll : wq->tail;
+		idx &= (wq->wqe_cnt - 1);
+		wc->wr_id = wq->wrid[idx];
 		wc->status = IB_WC_WR_FLUSH_ERR;
 		wc->vendor_err = MLX5_CQE_SYNDROME_WR_FLUSH_ERR;
 		wq->tail++;
+		if (is_send)
+			wq->last_poll = wq->w_list[idx].next;
 		np++;
 		wc->qp = &qp->ibqp;
 		wc++;
@@ -460,7 +483,7 @@
 	}
 
 	qpn = ntohl(cqe64->sop_drop_qpn) & 0xffffff;
-	if (!*cur_qp || (qpn != (*cur_qp)->ibqp.qp_num)) {
+	if (!*cur_qp || (qpn != (*cur_qp)->trans_qp.base.mqp.qpn)) {
 		/* We do not have to take the QP table lock here,
 		 * because CQs will be locked while QPs are removed
 		 * from the table.
@@ -476,6 +499,7 @@
 		wqe_ctr = be16_to_cpu(cqe64->wqe_counter);
 		idx = wqe_ctr & (wq->wqe_cnt - 1);
 		handle_good_req(wc, cqe64, wq, idx);
+		handle_atomics(*cur_qp, cqe64, wq->last_poll, idx);
 		wc->wr_id = wq->wrid[idx];
 		wq->tail = wq->wqe_head[idx] + 1;
 		wc->status = IB_WC_SUCCESS;
@@ -709,8 +733,9 @@
 	*cqe_size = ucmd.cqe_size;
 
 	cq->buf.umem =
-		ib_umem_get(udata, ucmd.buf_addr, entries * ucmd.cqe_size,
-			    IB_ACCESS_LOCAL_WRITE, 1);
+		ib_umem_get_peer(&dev->ib_dev, ucmd.buf_addr,
+				 entries * ucmd.cqe_size,
+				 IB_ACCESS_LOCAL_WRITE, 0);
 	if (IS_ERR(cq->buf.umem)) {
 		err = PTR_ERR(cq->buf.umem);
 		return err;
@@ -805,15 +830,14 @@
 	ib_umem_release(cq->buf.umem);
 }
 
-static void init_cq_frag_buf(struct mlx5_ib_cq *cq,
-			     struct mlx5_ib_cq_buf *buf)
+static void init_cq_frag_buf(struct mlx5_ib_cq_buf *buf)
 {
 	int i;
 	void *cqe;
 	struct mlx5_cqe64 *cqe64;
 
 	for (i = 0; i < buf->nent; i++) {
-		cqe = get_cqe(cq, i);
+		cqe = mlx5_frag_buf_get_wqe(&buf->fbc, i);
 		cqe64 = buf->cqe_size == 64 ? cqe : cqe + 64;
 		cqe64->op_own = MLX5_CQE_INVALID << 4;
 	}
@@ -839,7 +863,7 @@
 	if (err)
 		goto err_db;
 
-	init_cq_frag_buf(cq, &cq->buf);
+	init_cq_frag_buf(&cq->buf);
 
 	*inlen = MLX5_ST_SZ_BYTES(create_cq_in) +
 		 MLX5_FLD_SZ_BYTES(create_cq_in, pas[0]) *
@@ -893,8 +917,8 @@
 	struct mlx5_ib_dev *dev = to_mdev(ibdev);
 	struct mlx5_ib_cq *cq = to_mcq(ibcq);
 	u32 out[MLX5_ST_SZ_DW(create_cq_out)];
-	int uninitialized_var(index);
-	int uninitialized_var(inlen);
+	int index;
+	int inlen;
 	u32 *cqb = NULL;
 	void *cqc;
 	int cqe_size;
@@ -1109,9 +1133,9 @@
 	if (ucmd.cqe_size && SIZE_MAX / ucmd.cqe_size <= entries - 1)
 		return -EINVAL;
 
-	umem = ib_umem_get(udata, ucmd.buf_addr,
-			   (size_t)ucmd.cqe_size * entries,
-			   IB_ACCESS_LOCAL_WRITE, 1);
+	umem = ib_umem_get_peer(&dev->ib_dev, ucmd.buf_addr,
+				(size_t)ucmd.cqe_size * entries,
+				IB_ACCESS_LOCAL_WRITE, 0);
 	if (IS_ERR(umem)) {
 		err = PTR_ERR(umem);
 		return err;
@@ -1139,7 +1163,7 @@
 	if (err)
 		goto ex;
 
-	init_cq_frag_buf(cq, cq->resize_buf);
+	init_cq_frag_buf(cq->resize_buf);
 
 	return 0;
 
@@ -1214,7 +1238,7 @@
 	__be64 *pas;
 	int page_shift;
 	int inlen;
-	int uninitialized_var(cqe_size);
+	int cqe_size;
 	unsigned long flags;
 
 	if (!MLX5_CAP_GEN(dev->mdev, cq_resize)) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/mlx5/devx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/mlx5/devx.c
@@ -100,6 +100,7 @@
 		struct mlx5_ib_devx_mr	devx_mr;
 		struct mlx5_core_dct	core_dct;
 		struct mlx5_core_cq	core_cq;
+		u32			flow_counter_bulk_size;
 	};
 	struct list_head event_sub; /* holds devx_event_subscription entries */
 };
@@ -192,15 +193,20 @@
 	}
 }
 
-bool mlx5_ib_devx_is_flow_counter(void *obj, u32 *counter_id)
+bool mlx5_ib_devx_is_flow_counter(void *obj, u32 offset, u32 *counter_id)
 {
 	struct devx_obj *devx_obj = obj;
 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, devx_obj->dinbox, opcode);
 
 	if (opcode == MLX5_CMD_OP_DEALLOC_FLOW_COUNTER) {
+
+		if (offset && offset >= devx_obj->flow_counter_bulk_size)
+			return false;
+
 		*counter_id = MLX5_GET(dealloc_flow_counter_in,
 				       devx_obj->dinbox,
 				       flow_counter_id);
+		*counter_id += offset;
 		return true;
 	}
 
@@ -489,6 +495,10 @@
 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
 					MLX5_GET(rst2init_qp_in, in, qpn));
 		break;
+	case MLX5_CMD_OP_INIT2INIT_QP:
+		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
+					MLX5_GET(init2init_qp_in, in, qpn));
+		break;
 	case MLX5_CMD_OP_INIT2RTR_QP:
 		obj_id = get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
 					MLX5_GET(init2rtr_qp_in, in, qpn));
@@ -814,6 +824,7 @@
 	case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
 	case MLX5_CMD_OP_RST2INIT_QP:
 	case MLX5_CMD_OP_INIT2RTR_QP:
+	case MLX5_CMD_OP_INIT2INIT_QP:
 	case MLX5_CMD_OP_RTR2RTS_QP:
 	case MLX5_CMD_OP_RTS2RTS_QP:
 	case MLX5_CMD_OP_SQERR2RTS_QP:
@@ -1113,7 +1124,9 @@
 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_RQT);
 		break;
 	case MLX5_CMD_OP_CREATE_TIR:
-		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_TIR);
+		*obj_id = MLX5_GET(create_tir_out, out, tirn);
+		MLX5_SET(destroy_tir_in, din, opcode, MLX5_CMD_OP_DESTROY_TIR);
+		MLX5_SET(destroy_tir_in, din, tirn, *obj_id);
 		break;
 	case MLX5_CMD_OP_CREATE_TIS:
 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_TIS);
@@ -1463,6 +1476,13 @@
 	if (err)
 		goto obj_free;
 
+	if (opcode == MLX5_CMD_OP_ALLOC_FLOW_COUNTER) {
+		u8 bulk = MLX5_GET(alloc_flow_counter_in,
+				   cmd_in,
+				   flow_counter_bulk);
+		obj->flow_counter_bulk_size = 128UL * bulk;
+	}
+
 	uobj->object = obj;
 	INIT_LIST_HEAD(&obj->event_sub);
 	obj->ib_dev = dev;
@@ -1837,8 +1857,10 @@
 				key_level2,
 				obj_event,
 				GFP_KERNEL);
-		if (err)
+		if (err) {
+			kfree(obj_event);
 			return err;
+		}
 		INIT_LIST_HEAD(&obj_event->obj_sub_list);
 	}
 
@@ -2015,8 +2037,10 @@
 
 		num_alloc_xa_entries++;
 		event_sub = kzalloc(sizeof(*event_sub), GFP_KERNEL);
-		if (!event_sub)
+		if (!event_sub) {
+			err = -ENOMEM;
 			goto err;
+		}
 
 		list_add_tail(&event_sub->event_list, &sub_list);
 		if (use_eventfd) {
@@ -2121,7 +2145,7 @@
 	if (err)
 		return err;
 
-	obj->umem = ib_umem_get(&attrs->driver_udata, addr, size, access, 0);
+	obj->umem = ib_umem_get_peer(&dev->ib_dev, addr, size, access, 0);
 	if (IS_ERR(obj->umem))
 		return PTR_ERR(obj->umem);
 
@@ -2168,6 +2192,8 @@
 	mlx5_ib_populate_pas(dev, obj->umem, obj->page_shift, mtt,
 			     (obj->umem->writable ? MLX5_IB_MTT_WRITE : 0) |
 			     MLX5_IB_MTT_READ);
+	if (obj->umem->is_peer && MLX5_CAP_GEN(dev->mdev, ats))
+		MLX5_SET(umem, umem, ats, 1);
 }
 
 static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_UMEM_REG)(
@@ -2545,7 +2571,7 @@
 {
 	struct devx_async_event_file *ev_file = filp->private_data;
 	struct devx_event_subscription *event_sub;
-	struct devx_async_event_data *uninitialized_var(event);
+	struct devx_async_event_data *event;
 	int ret = 0;
 	size_t eventsz;
 	bool omit_data;
@@ -2800,7 +2826,7 @@
 	MLX5_IB_METHOD_DEVX_OBJ_MODIFY,
 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_MODIFY_HANDLE,
 			UVERBS_IDR_ANY_OBJECT,
-			UVERBS_ACCESS_WRITE,
+			UVERBS_ACCESS_READ,
 			UA_MANDATORY),
 	UVERBS_ATTR_PTR_IN(
 		MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/mlx5/doorbell.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/mlx5/doorbell.c
@@ -64,7 +64,8 @@
 
 	page->user_virt = (virt & PAGE_MASK);
 	page->refcnt    = 0;
-	page->umem = ib_umem_get(udata, virt & PAGE_MASK, PAGE_SIZE, 0, 0);
+	page->umem = ib_umem_get_peer(context->ibucontext.device, virt & PAGE_MASK,
+				      PAGE_SIZE, 0, 0);
 	if (IS_ERR(page->umem)) {
 		err = PTR_ERR(page->umem);
 		kfree(page);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/mlx5/flow.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/mlx5/flow.c
@@ -13,6 +13,7 @@
 #include <rdma/ib_umem.h>
 #include <linux/mlx5/driver.h>
 #include <linux/mlx5/fs.h>
+#include <linux/mlx5/eswitch.h>
 #include "mlx5_ib.h"
 
 #define UVERBS_MODULE_NAME mlx5_ib
@@ -85,6 +86,8 @@
 	struct mlx5_ib_dev *dev = mlx5_udata_to_mdev(&attrs->driver_udata);
 	int len, ret, i;
 	u32 counter_id = 0;
+	u32 *offset_attr;
+	u32 offset = 0;
 
 	if (!capable(CAP_NET_RAW))
 		return -EPERM;
@@ -151,8 +154,27 @@
 	if (len) {
 		devx_obj = arr_flow_actions[0]->object;
 
-		if (!mlx5_ib_devx_is_flow_counter(devx_obj, &counter_id))
+		if (uverbs_attr_is_valid(attrs,
+					 MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX_OFFSET)) {
+
+			int num_offsets = uverbs_attr_ptr_get_array_size(
+				attrs,
+				MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX_OFFSET,
+				sizeof(u32));
+
+			if (num_offsets != 1)
+				return -EINVAL;
+
+			offset_attr = uverbs_attr_get_alloced_ptr(
+				attrs,
+				MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX_OFFSET);
+			offset = *offset_attr;
+		}
+
+		if (!mlx5_ib_devx_is_flow_counter(devx_obj, offset,
+						  &counter_id))
 			return -EINVAL;
+
 		flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
 	}
 
@@ -316,6 +338,13 @@
 	if (err)
 		goto end;
 
+	if (obj->ns_type == MLX5_FLOW_NAMESPACE_FDB &&
+	    mlx5_eswitch_mode(dev->mdev->priv.eswitch) !=
+			      MLX5_ESWITCH_OFFLOADS) {
+		err = -EINVAL;
+		goto end;
+	}
+
 	uobj->object = obj;
 	obj->mdev = dev->mdev;
 	atomic_set(&obj->usecnt, 0);
@@ -598,7 +627,11 @@
 	UVERBS_ATTR_IDRS_ARR(MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX,
 			     MLX5_IB_OBJECT_DEVX_OBJ,
 			     UVERBS_ACCESS_READ, 1, 1,
-			     UA_OPTIONAL));
+			     UA_OPTIONAL),
+	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX_OFFSET,
+			   UVERBS_ATTR_MIN_SIZE(sizeof(u32)),
+			   UA_OPTIONAL,
+			   UA_ALLOC_AND_COPY));
 
 DECLARE_UVERBS_NAMED_METHOD_DESTROY(
 	MLX5_IB_METHOD_DESTROY_FLOW,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/mlx5/gsi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/mlx5/gsi.c
@@ -507,8 +507,7 @@
 		ret = ib_post_send(tx_qp, &cur_wr.wr, bad_wr);
 		if (ret) {
 			/* Undo the effect of adding the outstanding wr */
-			gsi->outstanding_pi = (gsi->outstanding_pi - 1) %
-					      gsi->cap.max_send_wr;
+			gsi->outstanding_pi--;
 			goto err;
 		}
 		spin_unlock_irqrestore(&gsi->lock, flags);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/mlx5/ib_rep.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/mlx5/ib_rep.c
@@ -35,7 +35,7 @@
 	int vport_index;
 
 	if (rep->vport == MLX5_VPORT_UPLINK)
-		profile = &uplink_rep_profile;
+		profile = &raw_eth_profile;
 	else
 		return mlx5_ib_set_vport_rep(dev, rep);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/mlx5/ib_rep.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/mlx5/ib_rep.h
@@ -10,7 +10,7 @@
 #include "mlx5_ib.h"
 
 #ifdef CONFIG_MLX5_ESWITCH
-extern const struct mlx5_ib_profile uplink_rep_profile;
+extern const struct mlx5_ib_profile raw_eth_profile;
 
 u8 mlx5_ib_eswitch_mode(struct mlx5_eswitch *esw);
 struct mlx5_ib_dev *mlx5_ib_get_rep_ibdev(struct mlx5_eswitch *esw,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/mlx5/mad.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/mlx5/mad.c
@@ -219,6 +219,13 @@
 		mdev = dev->mdev;
 		mdev_port_num = 1;
 	}
+	if (MLX5_CAP_GEN(dev->mdev, num_ports) == 1 &&
+	    !mlx5_core_mp_enabled(mdev)) {
+		/* set local port to one for Function-Per-Port HCA. */
+		mdev = dev->mdev;
+		mdev_port_num = 1;
+	}
+
 	/* Declaring support of extended counters */
 	if (in_mad->mad_hdr.attr_id == IB_PMA_CLASS_PORT_INFO) {
 		struct ib_class_port_info cpi = {};
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/mlx5/main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/mlx5/main.c
@@ -517,7 +517,7 @@
 					   mdev_port_num);
 	if (err)
 		goto out;
-	ext = MLX5_CAP_PCAM_FEATURE(dev->mdev, ptys_extended_ethernet);
+	ext = !!MLX5_GET_ETH_PROTO(ptys_reg, out, true, eth_proto_capability);
 	eth_prot_oper = MLX5_GET_ETH_PROTO(ptys_reg, out, ext, eth_proto_oper);
 
 	props->active_width     = IB_WIDTH_4X;
@@ -829,6 +829,7 @@
 				struct ib_device_attr *props,
 				struct ib_udata *uhw)
 {
+	size_t uhw_outlen = (uhw) ? uhw->outlen : 0;
 	struct mlx5_ib_dev *dev = to_mdev(ibdev);
 	struct mlx5_core_dev *mdev = dev->mdev;
 	int err = -ENOMEM;
@@ -842,12 +843,12 @@
 	u64 max_tso;
 
 	resp_len = sizeof(resp.comp_mask) + sizeof(resp.response_length);
-	if (uhw->outlen && uhw->outlen < resp_len)
+	if (uhw_outlen && uhw_outlen < resp_len)
 		return -EINVAL;
 	else
 		resp.response_length = resp_len;
 
-	if (uhw->inlen && !ib_is_udata_cleared(uhw, 0, uhw->inlen))
+	if (uhw && uhw->inlen && !ib_is_udata_cleared(uhw, 0, uhw->inlen))
 		return -EINVAL;
 
 	memset(props, 0, sizeof(*props));
@@ -887,7 +888,9 @@
 		/* We support 'Gappy' memory registration too */
 		props->device_cap_flags |= IB_DEVICE_SG_GAPS_REG;
 	}
-	props->device_cap_flags |= IB_DEVICE_MEM_MGT_EXTENSIONS;
+	/* IB_WR_REG_MR always requires changing the entity size with UMR */
+	if (!MLX5_CAP_GEN(dev->mdev, umr_modify_entity_size_disabled))
+		props->device_cap_flags |= IB_DEVICE_MEM_MGT_EXTENSIONS;
 	if (MLX5_CAP_GEN(mdev, sho)) {
 		props->device_cap_flags |= IB_DEVICE_INTEGRITY_HANDOVER;
 		/* At this stage no support for signature handover */
@@ -911,7 +914,7 @@
 			props->raw_packet_caps |=
 				IB_RAW_PACKET_CAP_CVLAN_STRIPPING;
 
-		if (field_avail(typeof(resp), tso_caps, uhw->outlen)) {
+		if (field_avail(typeof(resp), tso_caps, uhw_outlen)) {
 			max_tso = MLX5_CAP_ETH(mdev, max_lso_cap);
 			if (max_tso) {
 				resp.tso_caps.max_tso = 1 << max_tso;
@@ -921,7 +924,7 @@
 			}
 		}
 
-		if (field_avail(typeof(resp), rss_caps, uhw->outlen)) {
+		if (field_avail(typeof(resp), rss_caps, uhw_outlen)) {
 			resp.rss_caps.rx_hash_function =
 						MLX5_RX_HASH_FUNC_TOEPLITZ;
 			resp.rss_caps.rx_hash_fields_mask =
@@ -941,9 +944,9 @@
 			resp.response_length += sizeof(resp.rss_caps);
 		}
 	} else {
-		if (field_avail(typeof(resp), tso_caps, uhw->outlen))
+		if (field_avail(typeof(resp), tso_caps, uhw_outlen))
 			resp.response_length += sizeof(resp.tso_caps);
-		if (field_avail(typeof(resp), rss_caps, uhw->outlen))
+		if (field_avail(typeof(resp), rss_caps, uhw_outlen))
 			resp.response_length += sizeof(resp.rss_caps);
 	}
 
@@ -1031,7 +1034,7 @@
 	if (MLX5_CAP_GEN(mdev, cd))
 		props->device_cap_flags |= IB_DEVICE_CROSS_CHANNEL;
 
-	if (!mlx5_core_is_pf(mdev))
+	if (mlx5_core_is_vf(mdev))
 		props->device_cap_flags |= IB_DEVICE_VIRTUAL_FUNCTION;
 
 	if (mlx5_ib_port_link_layer(ibdev, 1) ==
@@ -1066,7 +1069,7 @@
 						MLX5_MAX_CQ_PERIOD;
 	}
 
-	if (field_avail(typeof(resp), cqe_comp_caps, uhw->outlen)) {
+	if (field_avail(typeof(resp), cqe_comp_caps, uhw_outlen)) {
 		resp.response_length += sizeof(resp.cqe_comp_caps);
 
 		if (MLX5_CAP_GEN(dev->mdev, cqe_compression)) {
@@ -1084,7 +1087,7 @@
 		}
 	}
 
-	if (field_avail(typeof(resp), packet_pacing_caps, uhw->outlen) &&
+	if (field_avail(typeof(resp), packet_pacing_caps, uhw_outlen) &&
 	    raw_support) {
 		if (MLX5_CAP_QOS(mdev, packet_pacing) &&
 		    MLX5_CAP_GEN(mdev, qos)) {
@@ -1103,7 +1106,7 @@
 	}
 
 	if (field_avail(typeof(resp), mlx5_ib_support_multi_pkt_send_wqes,
-			uhw->outlen)) {
+			uhw_outlen)) {
 		if (MLX5_CAP_ETH(mdev, multi_pkt_send_wqe))
 			resp.mlx5_ib_support_multi_pkt_send_wqes =
 				MLX5_IB_ALLOW_MPW;
@@ -1116,7 +1119,7 @@
 			sizeof(resp.mlx5_ib_support_multi_pkt_send_wqes);
 	}
 
-	if (field_avail(typeof(resp), flags, uhw->outlen)) {
+	if (field_avail(typeof(resp), flags, uhw_outlen)) {
 		resp.response_length += sizeof(resp.flags);
 
 		if (MLX5_CAP_GEN(mdev, cqe_compression_128))
@@ -1132,8 +1135,7 @@
 		resp.flags |= MLX5_IB_QUERY_DEV_RESP_FLAGS_SCAT2CQE_DCT;
 	}
 
-	if (field_avail(typeof(resp), sw_parsing_caps,
-			uhw->outlen)) {
+	if (field_avail(typeof(resp), sw_parsing_caps, uhw_outlen)) {
 		resp.response_length += sizeof(resp.sw_parsing_caps);
 		if (MLX5_CAP_ETH(mdev, swp)) {
 			resp.sw_parsing_caps.sw_parsing_offloads |=
@@ -1153,7 +1155,7 @@
 		}
 	}
 
-	if (field_avail(typeof(resp), striding_rq_caps, uhw->outlen) &&
+	if (field_avail(typeof(resp), striding_rq_caps, uhw_outlen) &&
 	    raw_support) {
 		resp.response_length += sizeof(resp.striding_rq_caps);
 		if (MLX5_CAP_GEN(mdev, striding_rq)) {
@@ -1170,8 +1172,7 @@
 		}
 	}
 
-	if (field_avail(typeof(resp), tunnel_offloads_caps,
-			uhw->outlen)) {
+	if (field_avail(typeof(resp), tunnel_offloads_caps, uhw_outlen)) {
 		resp.response_length += sizeof(resp.tunnel_offloads_caps);
 		if (MLX5_CAP_ETH(mdev, tunnel_stateless_vxlan))
 			resp.tunnel_offloads_caps |=
@@ -1182,17 +1183,15 @@
 		if (MLX5_CAP_ETH(mdev, tunnel_stateless_gre))
 			resp.tunnel_offloads_caps |=
 				MLX5_IB_TUNNELED_OFFLOADS_GRE;
-		if (MLX5_CAP_GEN(mdev, flex_parser_protocols) &
-		    MLX5_FLEX_PROTO_CW_MPLS_GRE)
+		if (MLX5_CAP_ETH(mdev, tunnel_stateless_mpls_over_gre))
 			resp.tunnel_offloads_caps |=
 				MLX5_IB_TUNNELED_OFFLOADS_MPLS_GRE;
-		if (MLX5_CAP_GEN(mdev, flex_parser_protocols) &
-		    MLX5_FLEX_PROTO_CW_MPLS_UDP)
+		if (MLX5_CAP_ETH(mdev, tunnel_stateless_mpls_over_udp))
 			resp.tunnel_offloads_caps |=
 				MLX5_IB_TUNNELED_OFFLOADS_MPLS_UDP;
 	}
 
-	if (uhw->outlen) {
+	if (uhw_outlen) {
 		err = ib_copy_to_udata(uhw, &resp, resp.response_length);
 
 		if (err)
@@ -2054,7 +2053,7 @@
 	case MLX5_IB_MMAP_DEVICE_MEM:
 		return "Device Memory";
 	default:
-		return NULL;
+		return "Unknown";
 	}
 }
 
@@ -2168,7 +2167,7 @@
 	mlx5_ib_dbg(dev, "uar idx 0x%lx, pfn %pa\n", idx, &pfn);
 
 	err = rdma_user_mmap_io(&context->ibucontext, vma, pfn, PAGE_SIZE,
-				prot);
+				prot, NULL);
 	if (err) {
 		mlx5_ib_err(dev,
 			    "rdma_user_mmap_io failed with error=%d, mmap_cmd=%s\n",
@@ -2210,7 +2209,8 @@
 	      PAGE_SHIFT) +
 	      page_idx;
 	return rdma_user_mmap_io(context, vma, pfn, map_size,
-				 pgprot_writecombine(vma->vm_page_prot));
+				 pgprot_writecombine(vma->vm_page_prot),
+				 NULL);
 }
 
 static int mlx5_ib_mmap(struct ib_ucontext *ibcontext, struct vm_area_struct *vma)
@@ -2248,7 +2248,8 @@
 			PAGE_SHIFT;
 		return rdma_user_mmap_io(&context->ibucontext, vma, pfn,
 					 PAGE_SIZE,
-					 pgprot_noncached(vma->vm_page_prot));
+					 pgprot_noncached(vma->vm_page_prot),
+					 NULL);
 	case MLX5_IB_MMAP_CLOCK_INFO:
 		return mlx5_ib_mmap_clock_info_page(dev, vma, context);
 
@@ -3548,10 +3549,6 @@
 	}
 
 	INIT_LIST_HEAD(&handler->list);
-	if (dst) {
-		memcpy(&dest_arr[0], dst, sizeof(*dst));
-		dest_num++;
-	}
 
 	for (spec_index = 0; spec_index < flow_attr->num_of_specs; spec_index++) {
 		err = parse_flow_attr(dev->mdev, spec,
@@ -3564,6 +3561,11 @@
 		ib_flow += ((union ib_flow_spec *)ib_flow)->size;
 	}
 
+	if (dst && !(flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DROP)) {
+		memcpy(&dest_arr[0], dst, sizeof(*dst));
+		dest_num++;
+	}
+
 	if (!flow_is_multicast_only(flow_attr))
 		set_underlay_qp(dev, spec, underlay_qpn);
 
@@ -3604,10 +3606,8 @@
 	}
 
 	if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DROP) {
-		if (!(flow_act.action & MLX5_FLOW_CONTEXT_ACTION_COUNT)) {
+		if (!dest_num)
 			rule_dst = NULL;
-			dest_num = 0;
-		}
 	} else {
 		if (is_egress)
 			flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_ALLOW;
@@ -4739,7 +4739,6 @@
 	struct ib_device_attr *dprops = NULL;
 	struct ib_port_attr *pprops = NULL;
 	int err = -ENOMEM;
-	struct ib_udata uhw = {.inlen = 0, .outlen = 0};
 
 	pprops = kzalloc(sizeof(*pprops), GFP_KERNEL);
 	if (!pprops)
@@ -4749,7 +4748,7 @@
 	if (!dprops)
 		goto out;
 
-	err = mlx5_ib_query_device(&dev->ib_dev, dprops, &uhw);
+	err = mlx5_ib_query_device(&dev->ib_dev, dprops, NULL);
 	if (err) {
 		mlx5_ib_warn(dev, "query_device failed %d\n", err);
 		goto out;
@@ -5145,8 +5144,7 @@
 	immutable->pkey_tbl_len = attr.pkey_tbl_len;
 	immutable->gid_tbl_len = attr.gid_tbl_len;
 	immutable->core_cap_flags = get_core_cap_flags(ibdev, &rep);
-	if ((ll == IB_LINK_LAYER_INFINIBAND) || MLX5_CAP_GEN(dev->mdev, roce))
-		immutable->max_mad_size = IB_MGMT_MAD_SIZE;
+	immutable->max_mad_size = IB_MGMT_MAD_SIZE;
 
 	return 0;
 }
@@ -5249,11 +5247,9 @@
 {
 	int err;
 
-	if (MLX5_CAP_GEN(dev->mdev, roce)) {
-		err = mlx5_nic_vport_enable_roce(dev->mdev);
-		if (err)
-			return err;
-	}
+	err = mlx5_nic_vport_enable_roce(dev->mdev);
+	if (err)
+		return err;
 
 	err = mlx5_eth_lag_init(dev);
 	if (err)
@@ -5262,8 +5258,7 @@
 	return 0;
 
 err_disable_roce:
-	if (MLX5_CAP_GEN(dev->mdev, roce))
-		mlx5_nic_vport_disable_roce(dev->mdev);
+	mlx5_nic_vport_disable_roce(dev->mdev);
 
 	return err;
 }
@@ -5271,8 +5266,7 @@
 static void mlx5_disable_eth(struct mlx5_ib_dev *dev)
 {
 	mlx5_eth_lag_cleanup(dev);
-	if (MLX5_CAP_GEN(dev->mdev, roce))
-		mlx5_nic_vport_disable_roce(dev->mdev);
+	mlx5_nic_vport_disable_roce(dev->mdev);
 }
 
 struct mlx5_ib_counter {
@@ -5641,9 +5635,10 @@
 	const struct mlx5_ib_counters *cnts =
 		get_counters(dev, counter->port - 1);
 
-	/* Q counters are in the beginning of all counters */
 	return rdma_alloc_hw_stats_struct(cnts->names,
-					  cnts->num_q_counters,
+					  cnts->num_q_counters +
+					  cnts->num_cong_counters +
+					  cnts->num_ext_ppcnt_counters,
 					  RDMA_HW_STATS_DEFAULT_LIFESPAN);
 }
 
@@ -5873,8 +5868,6 @@
 
 	port->mp.mpi = NULL;
 
-	list_add_tail(&mpi->list, &mlx5_ib_unaffiliated_port_list);
-
 	spin_unlock(&port->mp.mpi_lock);
 
 	err = mlx5_nic_vport_unaffiliate_multiport(mpi->mdev);
@@ -5984,7 +5977,8 @@
 		list_for_each_entry(mpi, &mlx5_ib_unaffiliated_port_list,
 				    list) {
 			if (dev->sys_image_guid == mpi->sys_image_guid &&
-			    (mlx5_core_native_port_num(mpi->mdev) - 1) == i) {
+			    (mlx5_core_native_port_num(mpi->mdev) - 1) == i &&
+			    mlx5_core_same_coredev_type(dev->mdev, mpi->mdev)) {
 				bound = mlx5_ib_bind_slave_port(dev, mpi);
 			}
 
@@ -6027,6 +6021,8 @@
 				dev->port[i].mp.mpi = NULL;
 			} else {
 				mlx5_ib_dbg(dev, "unbinding port_num: %d\n", i + 1);
+				list_add_tail(&dev->port[i].mp.mpi->list,
+					      &mlx5_ib_unaffiliated_port_list);
 				mlx5_ib_unbind_slave_port(dev, dev->port[i].mp.mpi);
 			}
 		}
@@ -6175,7 +6171,7 @@
 
 	err = set_has_smi_cap(dev);
 	if (err)
-		return err;
+		goto err_mp;
 
 	if (!mlx5_core_mp_enabled(mdev)) {
 		for (i = 1; i <= dev->num_ports; i++) {
@@ -6215,8 +6211,7 @@
 
 err_mp:
 	mlx5_ib_cleanup_multiport_master(dev);
-
-	return -ENOMEM;
+	return err;
 }
 
 static int mlx5_ib_stage_flow_db_init(struct mlx5_ib_dev *dev)
@@ -6444,7 +6439,7 @@
 	.query_port = mlx5_ib_rep_query_port,
 };
 
-static int mlx5_ib_stage_rep_non_default_cb(struct mlx5_ib_dev *dev)
+static int mlx5_ib_stage_raw_eth_non_default_cb(struct mlx5_ib_dev *dev)
 {
 	ib_set_device_ops(&dev->ib_dev, &mlx5_ib_dev_port_rep_ops);
 	return 0;
@@ -6484,7 +6479,7 @@
 	mlx5_remove_netdev_notifier(dev, port_num);
 }
 
-static int mlx5_ib_stage_rep_roce_init(struct mlx5_ib_dev *dev)
+static int mlx5_ib_stage_raw_eth_roce_init(struct mlx5_ib_dev *dev)
 {
 	struct mlx5_core_dev *mdev = dev->mdev;
 	enum rdma_link_layer ll;
@@ -6500,7 +6495,7 @@
 	return err;
 }
 
-static void mlx5_ib_stage_rep_roce_cleanup(struct mlx5_ib_dev *dev)
+static void mlx5_ib_stage_raw_eth_roce_cleanup(struct mlx5_ib_dev *dev)
 {
 	mlx5_ib_stage_common_roce_cleanup(dev);
 }
@@ -6628,7 +6623,7 @@
 
 	err = mlx5_alloc_bfreg(dev->mdev, &dev->fp_bfreg, false, true);
 	if (err)
-		mlx5_free_bfreg(dev->mdev, &dev->fp_bfreg);
+		mlx5_free_bfreg(dev->mdev, &dev->bfreg);
 
 	return err;
 }
@@ -6714,6 +6709,8 @@
 		      const struct mlx5_ib_profile *profile,
 		      int stage)
 {
+	dev->ib_active = false;
+
 	/* Number of stages to cleanup */
 	while (stage) {
 		stage--;
@@ -6807,7 +6804,7 @@
 		     mlx5_ib_stage_delay_drop_cleanup),
 };
 
-const struct mlx5_ib_profile uplink_rep_profile = {
+const struct mlx5_ib_profile raw_eth_profile = {
 	STAGE_CREATE(MLX5_IB_STAGE_INIT,
 		     mlx5_ib_stage_init_init,
 		     mlx5_ib_stage_init_cleanup),
@@ -6818,11 +6815,11 @@
 		     mlx5_ib_stage_caps_init,
 		     NULL),
 	STAGE_CREATE(MLX5_IB_STAGE_NON_DEFAULT_CB,
-		     mlx5_ib_stage_rep_non_default_cb,
+		     mlx5_ib_stage_raw_eth_non_default_cb,
 		     NULL),
 	STAGE_CREATE(MLX5_IB_STAGE_ROCE,
-		     mlx5_ib_stage_rep_roce_init,
-		     mlx5_ib_stage_rep_roce_cleanup),
+		     mlx5_ib_stage_raw_eth_roce_init,
+		     mlx5_ib_stage_raw_eth_roce_cleanup),
 	STAGE_CREATE(MLX5_IB_STAGE_SRQ,
 		     mlx5_init_srq_table,
 		     mlx5_cleanup_srq_table),
@@ -6877,11 +6874,13 @@
 
 	mutex_lock(&mlx5_ib_multiport_mutex);
 	list_for_each_entry(dev, &mlx5_ib_dev_list, ib_dev_list) {
-		if (dev->sys_image_guid == mpi->sys_image_guid)
+		if (dev->sys_image_guid == mpi->sys_image_guid &&
+		    mlx5_core_same_coredev_type(dev->mdev, mpi->mdev))
 			bound = mlx5_ib_bind_slave_port(dev, mpi);
 
 		if (bound) {
 			rdma_roce_rescan_device(&dev->ib_dev);
+			mpi->ibdev->ib_active = true;
 			break;
 		}
 	}
@@ -6898,6 +6897,7 @@
 
 static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
 {
+	const struct mlx5_ib_profile *profile;
 	enum rdma_link_layer ll;
 	struct mlx5_ib_dev *dev;
 	int port_type_cap;
@@ -6933,7 +6933,12 @@
 	dev->mdev = mdev;
 	dev->num_ports = num_ports;
 
-	return __mlx5_ib_add(dev, &pf_profile);
+	if (ll == IB_LINK_LAYER_ETHERNET && !mlx5_is_roce_enabled(mdev))
+		profile = &raw_eth_profile;
+	else
+		profile = &pf_profile;
+
+	return __mlx5_ib_add(dev, profile);
 }
 
 static void mlx5_ib_remove(struct mlx5_core_dev *mdev, void *context)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/mlx5/mem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/mlx5/mem.c
@@ -55,16 +55,17 @@
 	int i = 0;
 	struct scatterlist *sg;
 	int entry;
+	int page_shift = umem->is_peer ? umem->page_shift : PAGE_SHIFT;
 
-	addr = addr >> PAGE_SHIFT;
+	addr = addr >> page_shift;
 	tmp = (unsigned long)addr;
 	m = find_first_bit(&tmp, BITS_PER_LONG);
 	if (max_page_shift)
-		m = min_t(unsigned long, max_page_shift - PAGE_SHIFT, m);
+		m = min_t(unsigned long, max_page_shift - page_shift, m);
 
 	for_each_sg(umem->sg_head.sgl, sg, umem->nmap, entry) {
-		len = sg_dma_len(sg) >> PAGE_SHIFT;
-		pfn = sg_dma_address(sg) >> PAGE_SHIFT;
+		len = sg_dma_len(sg) >> page_shift;
+		pfn = sg_dma_address(sg) >> page_shift;
 		if (base + p != pfn) {
 			/* If either the offset or the new
 			 * base are unaligned update m
@@ -96,7 +97,7 @@
 
 		*ncont = 0;
 	}
-	*shift = PAGE_SHIFT + m;
+	*shift = page_shift + m;
 	*count = i;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/mlx5/mlx5_ib.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/mlx5/mlx5_ib.h
@@ -283,6 +283,7 @@
 	unsigned		head;
 	unsigned		tail;
 	u16			cur_post;
+	u16			last_poll;
 	void			*cur_edge;
 };
 
@@ -1349,7 +1350,7 @@
 	struct mlx5_flow_act *flow_act, u32 counter_id,
 	void *cmd_in, int inlen, int dest_id, int dest_type);
 bool mlx5_ib_devx_is_flow_dest(void *obj, int *dest_id, int *dest_type);
-bool mlx5_ib_devx_is_flow_counter(void *obj, u32 *counter_id);
+bool mlx5_ib_devx_is_flow_counter(void *obj, u32 offset, u32 *counter_id);
 int mlx5_ib_get_flow_trees(const struct uverbs_object_tree_def **root);
 void mlx5_ib_destroy_flow_action_raw(struct mlx5_ib_flow_action *maction);
 #else
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/mlx5/mr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/mlx5/mr.c
@@ -41,6 +41,8 @@
 #include <rdma/ib_verbs.h>
 #include "mlx5_ib.h"
 
+static void mlx5_invalidate_umem(struct ib_umem *umem, void *priv);
+
 enum {
 	MAX_PENDING_REG_MR = 8,
 };
@@ -428,7 +430,7 @@
 
 	if (entry < 0 || entry >= MAX_MR_CACHE_ENTRIES) {
 		mlx5_ib_err(dev, "cache entry %d is out of range\n", entry);
-		return NULL;
+		return ERR_PTR(-EINVAL);
 	}
 
 	ent = &cache->ent[entry];
@@ -752,10 +754,9 @@
 	return MLX5_MAX_UMR_SHIFT;
 }
 
-static int mr_umem_get(struct mlx5_ib_dev *dev, struct ib_udata *udata,
-		       u64 start, u64 length, int access_flags,
-		       struct ib_umem **umem, int *npages, int *page_shift,
-		       int *ncont, int *order)
+static int mr_umem_get(struct mlx5_ib_dev *dev, u64 start, u64 length,
+		       int access_flags, struct ib_umem **umem, int *npages,
+		       int *page_shift, int *ncont, int *order, bool allow_peer)
 {
 	struct ib_umem *u;
 
@@ -764,7 +765,8 @@
 	if (access_flags & IB_ACCESS_ON_DEMAND) {
 		struct ib_umem_odp *odp;
 
-		odp = ib_umem_odp_get(udata, start, length, access_flags);
+		odp = ib_umem_odp_get(&dev->ib_dev, start, length,
+				      access_flags);
 		if (IS_ERR(odp)) {
 			mlx5_ib_dbg(dev, "umem get failed (%ld)\n",
 				    PTR_ERR(odp));
@@ -779,7 +781,13 @@
 		if (order)
 			*order = ilog2(roundup_pow_of_two(*ncont));
 	} else {
-		u = ib_umem_get(udata, start, length, access_flags, 0);
+		if (allow_peer)
+			u = ib_umem_get_peer(&dev->ib_dev, start, length,
+					     access_flags,
+					     IB_PEER_MEM_INVAL_SUPP);
+		else
+			u = ib_umem_get(&dev->ib_dev, start, length,
+					access_flags);
 		if (IS_ERR(u)) {
 			mlx5_ib_dbg(dev, "umem get failed (%ld)\n", PTR_ERR(u));
 			return PTR_ERR(u);
@@ -1109,6 +1117,9 @@
 			 get_octo_len(virt_addr, length, page_shift));
 	}
 
+	if (umem->is_peer && MLX5_CAP_GEN(dev->mdev, ats))
+		MLX5_SET(mkc, mkc, ma_tranlation_mode, 1);
+
 	err = mlx5_core_create_mkey(dev->mdev, &mr->mmkey, in, inlen);
 	if (err) {
 		mlx5_ib_warn(dev, "create mkey failed\n");
@@ -1279,15 +1290,17 @@
 		return &mr->ibmr;
 	}
 
-	err = mr_umem_get(dev, udata, start, length, access_flags, &umem,
-			  &npages, &page_shift, &ncont, &order);
+	err = mr_umem_get(dev, start, length, access_flags, &umem,
+			  &npages, &page_shift, &ncont, &order, true);
 
 	if (err < 0)
 		return ERR_PTR(err);
 
 	use_umr = mlx5_ib_can_use_umr(dev, true);
 
-	if (order <= mr_cache_max_order(dev) && use_umr) {
+	if (umem->is_peer && MLX5_CAP_GEN(dev->mdev, ats)) {
+		use_umr = false;
+	} else if (order <= mr_cache_max_order(dev) && use_umr) {
 		mr = alloc_mr_from_cache(pd, umem, virt_addr, length, ncont,
 					 page_shift, order, access_flags);
 		if (PTR_ERR(mr) == -EAGAIN) {
@@ -1312,6 +1325,8 @@
 
 	if (IS_ERR(mr)) {
 		err = PTR_ERR(mr);
+		if (umem->is_peer)
+			ib_umem_stop_invalidation_notifier(umem);
 		goto error;
 	}
 
@@ -1335,6 +1350,12 @@
 		}
 	}
 
+	if (umem->is_peer) {
+		ib_umem_activate_invalidation_notifier(
+			umem, mlx5_invalidate_umem, mr);
+		/* After this point the MR can be invalidated */
+	}
+
 	if (is_odp_mr(mr)) {
 		to_ib_umem_odp(mr->umem)->private = mr;
 		atomic_set(&mr->num_pending_prefetch, 0);
@@ -1412,6 +1433,10 @@
 
 	atomic_sub(mr->npages, &dev->mdev->priv.reg_pages);
 
+	/* Peer memory isn't supported */
+	if (mr->umem->is_peer)
+		return -EOPNOTSUPP;
+
 	if (!mr->umem)
 		return -EINVAL;
 
@@ -1434,9 +1459,8 @@
 		flags |= IB_MR_REREG_TRANS;
 		ib_umem_release(mr->umem);
 		mr->umem = NULL;
-		err = mr_umem_get(dev, udata, addr, len, access_flags,
-				  &mr->umem, &npages, &page_shift, &ncont,
-				  &order);
+		err = mr_umem_get(dev, addr, len, access_flags, &mr->umem,
+				  &npages, &page_shift, &ncont, &order, false);
 		if (err)
 			goto err;
 	}
@@ -1609,6 +1633,17 @@
 		/* Avoid double-freeing the umem. */
 		umem = NULL;
 	}
+	else {
+		/*
+		 * For peers, need to disable the invalidation notifier
+		 * before calling destroy_mkey().
+		 */
+		if (umem && umem->is_peer) {
+			if (unreg_umr(mr->dev ,mr))
+				return;
+			ib_umem_stop_invalidation_notifier(umem);
+		}
+	}
 
 	clean_mr(dev, mr);
 
@@ -1616,13 +1651,14 @@
 	 * We should unregister the DMA address from the HCA before
 	 * remove the DMA mapping.
 	 */
-	mlx5_mr_cache_free(dev, mr);
+	if (mr->allocated_from_cache)
+		mlx5_mr_cache_free(dev, mr);
+	else
+		kfree(mr);
+
 	ib_umem_release(umem);
 	if (umem)
 		atomic_sub(npages, &dev->mdev->priv.reg_pages);
-
-	if (!mr->allocated_from_cache)
-		kfree(mr);
 }
 
 int mlx5_ib_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata)
@@ -2332,3 +2368,15 @@
 
 	return n;
 }
+
+static void mlx5_invalidate_umem(struct ib_umem *umem, void *priv)
+{
+	struct mlx5_ib_mr *mr = priv;
+
+	/*
+	 * DMA is turned off for the mkey, but the mkey remains otherwise
+	 * untouched until the normal flow of dereg_mr happens. Any access to
+	 * this mkey will generate CQEs.
+	 */
+	unreg_umr(mr->dev ,mr);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/mlx5/odp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/mlx5/odp.c
@@ -553,7 +553,7 @@
 	struct mlx5_ib_mr *imr;
 	struct ib_umem_odp *umem_odp;
 
-	umem_odp = ib_umem_odp_alloc_implicit(udata, access_flags);
+	umem_odp = ib_umem_odp_alloc_implicit(pd->ibpd.device, access_flags);
 	if (IS_ERR(umem_odp))
 		return ERR_CAST(umem_odp);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/mlx5/qp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/mlx5/qp.c
@@ -749,7 +749,7 @@
 {
 	int err;
 
-	*umem = ib_umem_get(udata, addr, size, 0, 0);
+	*umem = ib_umem_get_peer(&dev->ib_dev, addr, size, 0, 0);
 	if (IS_ERR(*umem)) {
 		mlx5_ib_dbg(dev, "umem_get failed\n");
 		return PTR_ERR(*umem);
@@ -806,7 +806,7 @@
 	if (!ucmd->buf_addr)
 		return -EINVAL;
 
-	rwq->umem = ib_umem_get(udata, ucmd->buf_addr, rwq->buf_size, 0, 0);
+	rwq->umem = ib_umem_get(&dev->ib_dev, ucmd->buf_addr, rwq->buf_size, 0);
 	if (IS_ERR(rwq->umem)) {
 		mlx5_ib_dbg(dev, "umem_get failed\n");
 		err = PTR_ERR(rwq->umem);
@@ -1463,6 +1463,8 @@
 	u16 uid = to_mpd(pd)->uid;
 	u32 out[MLX5_ST_SZ_DW(create_tir_out)] = {};
 
+	if (!qp->sq.wqe_cnt && !qp->rq.wqe_cnt)
+		return -EINVAL;
 	if (qp->sq.wqe_cnt) {
 		err = create_raw_packet_qp_tis(dev, qp, sq, tdn, pd);
 		if (err)
@@ -3391,9 +3393,6 @@
 	struct mlx5_ib_qp_base *base;
 	u32 set_id;
 
-	if (!MLX5_CAP_GEN(dev->mdev, rts2rts_qp_counters_set_id))
-		return 0;
-
 	if (counter)
 		set_id = counter->id;
 	else
@@ -3728,6 +3727,7 @@
 		qp->sq.cur_post = 0;
 		if (qp->sq.wqe_cnt)
 			qp->sq.cur_edge = get_sq_edge(&qp->sq, 0);
+		qp->sq.last_poll = 0;
 		qp->db.db[MLX5_RCV_DBR] = 0;
 		qp->db.db[MLX5_SND_DBR] = 0;
 	}
@@ -3821,7 +3821,7 @@
 			return -EINVAL;
 
 		if (attr->port_num == 0 ||
-		    attr->port_num > MLX5_CAP_GEN(dev->mdev, num_ports)) {
+		    attr->port_num > dev->num_ports) {
 			mlx5_ib_dbg(dev, "invalid port number %d. number of ports is %d\n",
 				    attr->port_num, dev->num_ports);
 			return -EINVAL;
@@ -3865,6 +3865,8 @@
 		MLX5_SET(dctc, dctc, mtu, attr->path_mtu);
 		MLX5_SET(dctc, dctc, my_addr_index, attr->ah_attr.grh.sgid_index);
 		MLX5_SET(dctc, dctc, hop_limit, attr->ah_attr.grh.hop_limit);
+		if (attr->ah_attr.type == RDMA_AH_ATTR_TYPE_ROCE)
+			MLX5_SET(dctc, dctc, eth_prio, attr->ah_attr.sl & 0x7);
 
 		err = mlx5_core_create_dct(dev->mdev, &qp->dct.mdct, qp->dct.in,
 					   MLX5_ST_SZ_BYTES(create_dct_in), out,
@@ -3888,6 +3890,40 @@
 	return err;
 }
 
+static int validate_rd_atomic(struct mlx5_ib_dev *dev, struct ib_qp_attr *attr,
+			      int attr_mask, enum ib_qp_type qp_type)
+{
+	int log_max_ra_res;
+	int log_max_ra_req;
+
+	if (qp_type == MLX5_IB_QPT_DCI) {
+		log_max_ra_res = 1 << MLX5_CAP_GEN(dev->mdev,
+						   log_max_ra_res_dc);
+		log_max_ra_req = 1 << MLX5_CAP_GEN(dev->mdev,
+						   log_max_ra_req_dc);
+	} else {
+		log_max_ra_res = 1 << MLX5_CAP_GEN(dev->mdev,
+						   log_max_ra_res_qp);
+		log_max_ra_req = 1 << MLX5_CAP_GEN(dev->mdev,
+						   log_max_ra_req_qp);
+	}
+
+	if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC &&
+	    attr->max_rd_atomic > log_max_ra_res) {
+		mlx5_ib_dbg(dev, "invalid max_rd_atomic value %d\n",
+			    attr->max_rd_atomic);
+		return false;
+	}
+
+	if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC &&
+	    attr->max_dest_rd_atomic > log_max_ra_req) {
+		mlx5_ib_dbg(dev, "invalid max_dest_rd_atomic value %d\n",
+			    attr->max_dest_rd_atomic);
+		return false;
+	}
+	return true;
+}
+
 int mlx5_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
 		      int attr_mask, struct ib_udata *udata)
 {
@@ -3984,21 +4020,8 @@
 		}
 	}
 
-	if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC &&
-	    attr->max_rd_atomic >
-	    (1 << MLX5_CAP_GEN(dev->mdev, log_max_ra_res_qp))) {
-		mlx5_ib_dbg(dev, "invalid max_rd_atomic value %d\n",
-			    attr->max_rd_atomic);
+	if (!validate_rd_atomic(dev, attr, attr_mask, qp_type))
 		goto out;
-	}
-
-	if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC &&
-	    attr->max_dest_rd_atomic >
-	    (1 << MLX5_CAP_GEN(dev->mdev, log_max_ra_req_qp))) {
-		mlx5_ib_dbg(dev, "invalid max_dest_rd_atomic value %d\n",
-			    attr->max_dest_rd_atomic);
-		goto out;
-	}
 
 	if (cur_state == new_state && cur_state == IB_QPS_RESET) {
 		err = 0;
@@ -4121,7 +4144,7 @@
 		 */
 		copysz = min_t(u64, *cur_edge - (void *)eseg->inline_hdr.start,
 			       left);
-		memcpy(eseg->inline_hdr.start, pdata, copysz);
+		memcpy(eseg->inline_hdr.data, pdata, copysz);
 		stride = ALIGN(sizeof(struct mlx5_wqe_eth_seg) -
 			       sizeof(eseg->inline_hdr.start) + copysz, 16);
 		*size += stride / 16;
@@ -5498,7 +5521,9 @@
 	rdma_ah_set_path_bits(ah_attr, path->grh_mlid & 0x7f);
 	rdma_ah_set_static_rate(ah_attr,
 				path->static_rate ? path->static_rate - 5 : 0);
-	if (path->grh_mlid & (1 << 7)) {
+
+	if (path->grh_mlid & (1 << 7) ||
+	    ah_attr->type == RDMA_AH_ATTR_TYPE_ROCE) {
 		u32 tc_fl = be32_to_cpu(path->tclass_flowlabel);
 
 		rdma_ah_set_grh(ah_attr, NULL,
@@ -6134,6 +6159,10 @@
 	if (udata->outlen && udata->outlen < min_resp_len)
 		return ERR_PTR(-EINVAL);
 
+	if (!capable(CAP_SYS_RAWIO) &&
+	    init_attr->create_flags & IB_WQ_FLAGS_DELAY_DROP)
+		return ERR_PTR(-EPERM);
+
 	dev = to_mdev(pd->device);
 	switch (init_attr->wq_type) {
 	case IB_WQT_RQ:
@@ -6311,10 +6340,8 @@
 
 	rqc = MLX5_ADDR_OF(modify_rq_in, in, ctx);
 
-	curr_wq_state = (wq_attr_mask & IB_WQ_CUR_STATE) ?
-		wq_attr->curr_wq_state : wq->state;
-	wq_state = (wq_attr_mask & IB_WQ_STATE) ?
-		wq_attr->wq_state : curr_wq_state;
+	curr_wq_state = wq_attr->curr_wq_state;
+	wq_state = wq_attr->wq_state;
 	if (curr_wq_state == IB_WQS_ERR)
 		curr_wq_state = MLX5_RQC_STATE_ERR;
 	if (wq_state == IB_WQS_ERR)
@@ -6503,6 +6530,7 @@
  */
 int mlx5_ib_qp_set_counter(struct ib_qp *qp, struct rdma_counter *counter)
 {
+	struct mlx5_ib_dev *dev = to_mdev(qp->device);
 	struct mlx5_ib_qp *mqp = to_mqp(qp);
 	int err = 0;
 
@@ -6512,6 +6540,11 @@
 		goto out;
 	}
 
+	if (!MLX5_CAP_GEN(dev->mdev, rts2rts_qp_counters_set_id)) {
+		err = -EOPNOTSUPP;
+		goto out;
+	}
+
 	if (mqp->state == IB_QPS_RTS) {
 		err = __mlx5_ib_qp_set_counter(qp, counter);
 		if (!err)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/mlx5/srq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/mlx5/srq.c
@@ -80,7 +80,7 @@
 
 	srq->wq_sig = !!(ucmd.flags & MLX5_SRQ_FLAG_SIGNATURE);
 
-	srq->umem = ib_umem_get(udata, ucmd.buf_addr, buf_size, 0, 0);
+	srq->umem = ib_umem_get_peer(pd->device, ucmd.buf_addr, buf_size, 0, 0);
 	if (IS_ERR(srq->umem)) {
 		mlx5_ib_dbg(dev, "failed umem get, size %d\n", buf_size);
 		err = PTR_ERR(srq->umem);
@@ -310,12 +310,18 @@
 	srq->msrq.event = mlx5_ib_srq_event;
 	srq->ibsrq.ext.xrc.srq_num = srq->msrq.srqn;
 
-	if (udata)
-		if (ib_copy_to_udata(udata, &srq->msrq.srqn, sizeof(__u32))) {
+	if (udata) {
+		struct mlx5_ib_create_srq_resp resp = {
+			.srqn = srq->msrq.srqn,
+		};
+
+		if (ib_copy_to_udata(udata, &resp, min(udata->outlen,
+				     sizeof(resp)))) {
 			mlx5_ib_dbg(dev, "copy to user failed\n");
 			err = -EFAULT;
 			goto err_core;
 		}
+	}
 
 	init_attr->attr.max_wr = srq->msrq.max - 1;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/mlx5/srq_cmd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/mlx5/srq_cmd.c
@@ -83,11 +83,11 @@
 	struct mlx5_srq_table *table = &dev->srq_table;
 	struct mlx5_core_srq *srq;
 
-	xa_lock(&table->array);
+	xa_lock_irq(&table->array);
 	srq = xa_load(&table->array, srqn);
 	if (srq)
 		refcount_inc(&srq->common.refcount);
-	xa_unlock(&table->array);
+	xa_unlock_irq(&table->array);
 
 	return srq;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/mthca/mthca_cmd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/mthca/mthca_cmd.c
@@ -635,7 +635,7 @@
 
 int mthca_SYS_EN(struct mthca_dev *dev)
 {
-	u64 out;
+	u64 out = 0;
 	int ret;
 
 	ret = mthca_cmd_imm(dev, 0, &out, 0, 0, CMD_SYS_EN, CMD_TIME_CLASS_D);
@@ -1955,7 +1955,7 @@
 int mthca_MGID_HASH(struct mthca_dev *dev, struct mthca_mailbox *mailbox,
 		    u16 *hash)
 {
-	u64 imm;
+	u64 imm = 0;
 	int err;
 
 	err = mthca_cmd_imm(dev, mailbox->dma, &imm, 0, 0, CMD_MGID_HASH,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/mthca/mthca_cq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/mthca/mthca_cq.c
@@ -604,7 +604,7 @@
 			entry->byte_len  = MTHCA_ATOMIC_BYTE_LEN;
 			break;
 		default:
-			entry->opcode    = MTHCA_OPCODE_INVALID;
+			entry->opcode = 0xFF;
 			break;
 		}
 	} else {
@@ -803,8 +803,10 @@
 	}
 
 	mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
-	if (IS_ERR(mailbox))
+	if (IS_ERR(mailbox)) {
+		err = PTR_ERR(mailbox);
 		goto err_out_arm;
+	}
 
 	cq_context = mailbox->buf;
 
@@ -846,9 +848,9 @@
 	}
 
 	spin_lock_irq(&dev->cq_table.lock);
-	if (mthca_array_set(&dev->cq_table.cq,
-			    cq->cqn & (dev->limits.num_cqs - 1),
-			    cq)) {
+	err = mthca_array_set(&dev->cq_table.cq,
+			      cq->cqn & (dev->limits.num_cqs - 1), cq);
+	if (err) {
 		spin_unlock_irq(&dev->cq_table.lock);
 		goto err_out_free_mr;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/mthca/mthca_dev.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/mthca/mthca_dev.h
@@ -105,7 +105,6 @@
 	MTHCA_OPCODE_ATOMIC_CS      = 0x11,
 	MTHCA_OPCODE_ATOMIC_FA      = 0x12,
 	MTHCA_OPCODE_BIND_MW        = 0x18,
-	MTHCA_OPCODE_INVALID        = 0xff
 };
 
 enum {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/mthca/mthca_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/mthca/mthca_main.c
@@ -382,7 +382,7 @@
 			  struct mthca_init_hca_param *init_hca,
 			  u64 icm_size)
 {
-	u64 aux_pages;
+	u64 aux_pages = 0;
 	int err;
 
 	err = mthca_SET_ICM_SIZE(mdev, icm_size, &aux_pages);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/mthca/mthca_provider.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -880,9 +880,7 @@
 	if (!mr)
 		return ERR_PTR(-ENOMEM);
 
-	mr->umem = ib_umem_get(udata, start, length, acc,
-			       ucmd.mr_attrs & MTHCA_MR_DMASYNC);
-
+	mr->umem = ib_umem_get(pd->device, start, length, acc);
 	if (IS_ERR(mr->umem)) {
 		err = PTR_ERR(mr->umem);
 		goto err;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/mthca/mthca_qp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -1639,8 +1639,8 @@
 	 * without initializing f0 and size0, and they are in fact
 	 * never used uninitialized.
 	 */
-	int uninitialized_var(size0);
-	u32 uninitialized_var(f0);
+	int size0;
+	u32 f0;
 	int ind;
 	u8 op0 = 0;
 
@@ -1835,7 +1835,7 @@
 	 * without initializing size0, and it is in fact never used
 	 * uninitialized.
 	 */
-	int uninitialized_var(size0);
+	int size0;
 	int ind;
 	void *wqe;
 	void *prev_wqe;
@@ -1943,8 +1943,8 @@
 	 * without initializing f0 and size0, and they are in fact
 	 * never used uninitialized.
 	 */
-	int uninitialized_var(size0);
-	u32 uninitialized_var(f0);
+	int size0;
+	u32 f0;
 	int ind;
 	u8 op0 = 0;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
@@ -442,9 +442,9 @@
 		pr_err("%s(%d) Freeing in use pdid=0x%x.\n",
 		       __func__, dev->id, pd->id);
 	}
-	kfree(uctx->cntxt_pd);
 	uctx->cntxt_pd = NULL;
 	_ocrdma_dealloc_pd(dev, pd);
+	kfree(pd);
 }
 
 static struct ocrdma_pd *ocrdma_get_ucontext_pd(struct ocrdma_ucontext *uctx)
@@ -875,7 +875,7 @@
 	mr = kzalloc(sizeof(*mr), GFP_KERNEL);
 	if (!mr)
 		return ERR_PTR(status);
-	mr->umem = ib_umem_get(udata, start, len, acc, 0);
+	mr->umem = ib_umem_get(ibpd->device, start, len, acc);
 	if (IS_ERR(mr->umem)) {
 		status = -EFAULT;
 		goto umem_err;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/qedr/main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/qedr/main.c
@@ -357,10 +357,15 @@
 		return -ENOMEM;
 
 	spin_lock_init(&dev->sgid_lock);
+	xa_init_flags(&dev->srqs, XA_FLAGS_LOCK_IRQ);
 
 	if (IS_IWARP(dev)) {
-		xa_init_flags(&dev->qps, XA_FLAGS_LOCK_IRQ);
+		xa_init(&dev->qps);
 		dev->iwarp_wq = create_singlethread_workqueue("qedr_iwarpq");
+		if (!dev->iwarp_wq) {
+			rc = -ENOMEM;
+			goto err1;
+		}
 	}
 
 	/* Allocate Status blocks for CNQ */
@@ -368,7 +373,7 @@
 				GFP_KERNEL);
 	if (!dev->sb_array) {
 		rc = -ENOMEM;
-		goto err1;
+		goto err_destroy_wq;
 	}
 
 	dev->cnq_array = kcalloc(dev->num_cnq,
@@ -422,6 +427,9 @@
 	kfree(dev->cnq_array);
 err2:
 	kfree(dev->sb_array);
+err_destroy_wq:
+	if (IS_IWARP(dev))
+		destroy_workqueue(dev->iwarp_wq);
 err1:
 	kfree(dev->sgid_tbl);
 	return rc;
@@ -600,7 +608,7 @@
 	qed_attr = dev->ops->rdma_query_device(dev->rdma_ctx);
 
 	/* Part 2 - check capabilities */
-	page_size = ~dev->attr.page_size_caps + 1;
+	page_size = ~qed_attr->page_size_caps + 1;
 	if (page_size > PAGE_SIZE) {
 		DP_ERR(dev,
 		       "Kernel PAGE_SIZE is %ld which is smaller than minimum page size (%d) required by qedr\n",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/qedr/qedr.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/qedr/qedr.h
@@ -40,6 +40,7 @@
 #include <linux/qed/qed_rdma_if.h>
 #include <linux/qed/qede_rdma.h>
 #include <linux/qed/roce_common.h>
+#include <linux/completion.h>
 #include "qedr_hsi_rdma.h"
 
 #define QEDR_NODE_DESC "QLogic 579xx RoCE HCA"
@@ -348,10 +349,10 @@
 	u32 wqe_prod;
 	u32 sge_prod;
 	u32 wr_prod_cnt;
-	u32 wr_cons_cnt;
+	atomic_t wr_cons_cnt;
 	u32 num_elems;
 
-	u32 *virt_prod_pair_addr;
+	struct rdma_srq_producers *virt_prod_pair_addr;
 	dma_addr_t phy_prod_pair_addr;
 };
 
@@ -377,10 +378,20 @@
 	QEDR_QP_ERR_RQ_PBL_FULL = 32,
 };
 
+enum qedr_qp_create_type {
+	QEDR_QP_CREATE_NONE,
+	QEDR_QP_CREATE_USER,
+	QEDR_QP_CREATE_KERNEL,
+};
+
+enum qedr_iwarp_cm_flags {
+	QEDR_IWARP_CM_WAIT_FOR_CONNECT    = BIT(0),
+	QEDR_IWARP_CM_WAIT_FOR_DISCONNECT = BIT(1),
+};
+
 struct qedr_qp {
 	struct ib_qp ibqp;	/* must be first */
 	struct qedr_dev *dev;
-	struct qedr_iw_ep *ep;
 	struct qedr_qp_hwq_info sq;
 	struct qedr_qp_hwq_info rq;
 
@@ -395,6 +406,7 @@
 	u32 id;
 	struct qedr_pd *pd;
 	enum ib_qp_type qp_type;
+	enum qedr_qp_create_type create_type;
 	struct qed_rdma_qp *qed_qp;
 	u32 qp_id;
 	u16 icid;
@@ -404,6 +416,7 @@
 	u32 sq_psn;
 	u32 qkey;
 	u32 dest_qp_num;
+	u8 timeout;
 
 	/* Relevant to qps created from kernel space only (ULPs) */
 	u8 prev_wqe_size;
@@ -437,8 +450,11 @@
 	/* Relevant to qps created from user space only (applications) */
 	struct qedr_userq usq;
 	struct qedr_userq urq;
-	atomic_t refcnt;
-	bool destroyed;
+
+	/* synchronization objects used with iwarp ep */
+	struct kref refcnt;
+	struct completion iwarp_cm_comp;
+	unsigned long iwarp_cm_flags; /* enum iwarp_cm_flags */
 };
 
 struct qedr_ah {
@@ -531,7 +547,7 @@
 	struct iw_cm_id	*cm_id;
 	struct qedr_qp	*qp;
 	void		*qed_context;
-	u8		during_connect;
+	struct kref	refcnt;
 };
 
 static inline
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/qedr/qedr_iw_cm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/qedr/qedr_iw_cm.c
@@ -79,6 +79,27 @@
 	}
 }
 
+static void qedr_iw_free_qp(struct kref *ref)
+{
+	struct qedr_qp *qp = container_of(ref, struct qedr_qp, refcnt);
+
+	kfree(qp);
+}
+
+static void
+qedr_iw_free_ep(struct kref *ref)
+{
+	struct qedr_iw_ep *ep = container_of(ref, struct qedr_iw_ep, refcnt);
+
+	if (ep->qp)
+		kref_put(&ep->qp->refcnt, qedr_iw_free_qp);
+
+	if (ep->cm_id)
+		ep->cm_id->rem_ref(ep->cm_id);
+
+	kfree(ep);
+}
+
 static void
 qedr_iw_mpa_request(void *context, struct qed_iwarp_cm_event_params *params)
 {
@@ -93,6 +114,7 @@
 
 	ep->dev = dev;
 	ep->qed_context = params->ep_context;
+	kref_init(&ep->refcnt);
 
 	memset(&event, 0, sizeof(event));
 	event.event = IW_CM_EVENT_CONNECT_REQUEST;
@@ -128,8 +150,17 @@
 	if (params->cm_info) {
 		event.ird = params->cm_info->ird;
 		event.ord = params->cm_info->ord;
-		event.private_data_len = params->cm_info->private_data_len;
-		event.private_data = (void *)params->cm_info->private_data;
+		/* Only connect_request and reply have valid private data
+		 * the rest of the events this may be left overs from
+		 * connection establishment. CONNECT_REQUEST is issued via
+		 * qedr_iw_mpa_request
+		 */
+		if (event_type == IW_CM_EVENT_CONNECT_REPLY) {
+			event.private_data_len =
+				params->cm_info->private_data_len;
+			event.private_data =
+				(void *)params->cm_info->private_data;
+		}
 	}
 
 	if (ep->cm_id)
@@ -141,12 +172,10 @@
 {
 	struct qedr_iw_ep *ep = (struct qedr_iw_ep *)context;
 
-	if (ep->cm_id) {
+	if (ep->cm_id)
 		qedr_iw_issue_event(context, params, IW_CM_EVENT_CLOSE);
 
-		ep->cm_id->rem_ref(ep->cm_id);
-		ep->cm_id = NULL;
-	}
+	kref_put(&ep->refcnt, qedr_iw_free_ep);
 }
 
 static void
@@ -186,11 +215,13 @@
 	struct qedr_qp *qp = ep->qp;
 	struct iw_cm_event event;
 
-	if (qp->destroyed) {
-		kfree(dwork);
-		qedr_iw_qp_rem_ref(&qp->ibqp);
-		return;
-	}
+	/* The qp won't be released until we release the ep.
+	 * the ep's refcnt was increased before calling this
+	 * function, therefore it is safe to access qp
+	 */
+	if (test_and_set_bit(QEDR_IWARP_CM_WAIT_FOR_DISCONNECT,
+			     &qp->iwarp_cm_flags))
+		goto out;
 
 	memset(&event, 0, sizeof(event));
 	event.status = dwork->status;
@@ -204,7 +235,6 @@
 	else
 		qp_params.new_state = QED_ROCE_QP_STATE_SQD;
 
-	kfree(dwork);
 
 	if (ep->cm_id)
 		ep->cm_id->event_handler(ep->cm_id, &event);
@@ -214,7 +244,10 @@
 
 	dev->ops->rdma_modify_qp(dev->rdma_ctx, qp->qed_qp, &qp_params);
 
-	qedr_iw_qp_rem_ref(&qp->ibqp);
+	complete(&ep->qp->iwarp_cm_comp);
+out:
+	kfree(dwork);
+	kref_put(&ep->refcnt, qedr_iw_free_ep);
 }
 
 static void
@@ -224,13 +257,17 @@
 	struct qedr_discon_work *work;
 	struct qedr_iw_ep *ep = (struct qedr_iw_ep *)context;
 	struct qedr_dev *dev = ep->dev;
-	struct qedr_qp *qp = ep->qp;
 
 	work = kzalloc(sizeof(*work), GFP_ATOMIC);
 	if (!work)
 		return;
 
-	qedr_iw_qp_add_ref(&qp->ibqp);
+	/* We can't get a close event before disconnect, but since
+	 * we're scheduling a work queue we need to make sure close
+	 * won't delete the ep, so we increase the refcnt
+	 */
+	kref_get(&ep->refcnt);
+
 	work->ep = ep;
 	work->event = params->event;
 	work->status = params->status;
@@ -252,16 +289,30 @@
 	if ((params->status == -ECONNREFUSED) && (!ep->qp)) {
 		DP_DEBUG(dev, QEDR_MSG_IWARP,
 			 "PASSIVE connection refused releasing ep...\n");
-		kfree(ep);
+		kref_put(&ep->refcnt, qedr_iw_free_ep);
 		return;
 	}
 
+	complete(&ep->qp->iwarp_cm_comp);
 	qedr_iw_issue_event(context, params, IW_CM_EVENT_ESTABLISHED);
 
 	if (params->status < 0)
 		qedr_iw_close_event(context, params);
 }
 
+static void
+qedr_iw_active_complete(void *context,
+			struct qed_iwarp_cm_event_params *params)
+{
+	struct qedr_iw_ep *ep = (struct qedr_iw_ep *)context;
+
+	complete(&ep->qp->iwarp_cm_comp);
+	qedr_iw_issue_event(context, params, IW_CM_EVENT_CONNECT_REPLY);
+
+	if (params->status < 0)
+		kref_put(&ep->refcnt, qedr_iw_free_ep);
+}
+
 static int
 qedr_iw_mpa_reply(void *context, struct qed_iwarp_cm_event_params *params)
 {
@@ -288,27 +339,15 @@
 		qedr_iw_mpa_reply(context, params);
 		break;
 	case QED_IWARP_EVENT_PASSIVE_COMPLETE:
-		ep->during_connect = 0;
 		qedr_iw_passive_complete(context, params);
 		break;
-
 	case QED_IWARP_EVENT_ACTIVE_COMPLETE:
-		ep->during_connect = 0;
-		qedr_iw_issue_event(context,
-				    params,
-				    IW_CM_EVENT_CONNECT_REPLY);
-		if (params->status < 0) {
-			struct qedr_iw_ep *ep = (struct qedr_iw_ep *)context;
-
-			ep->cm_id->rem_ref(ep->cm_id);
-			ep->cm_id = NULL;
-		}
+		qedr_iw_active_complete(context, params);
 		break;
 	case QED_IWARP_EVENT_DISCONNECT:
 		qedr_iw_disconnect_event(context, params);
 		break;
 	case QED_IWARP_EVENT_CLOSE:
-		ep->during_connect = 0;
 		qedr_iw_close_event(context, params);
 		break;
 	case QED_IWARP_EVENT_RQ_EMPTY:
@@ -451,10 +490,10 @@
 
 	if ((!dst) || dst->error) {
 		if (dst) {
-			dst_release(dst);
 			DP_ERR(dev,
 			       "ip6_route_output returned dst->error = %d\n",
 			       dst->error);
+			dst_release(dst);
 		}
 		return -EINVAL;
 	}
@@ -476,6 +515,19 @@
 	return rc;
 }
 
+struct qedr_qp *qedr_iw_load_qp(struct qedr_dev *dev, u32 qpn)
+{
+	struct qedr_qp *qp;
+
+	xa_lock(&dev->qps);
+	qp = xa_load(&dev->qps, qpn);
+	if (qp)
+		kref_get(&qp->refcnt);
+	xa_unlock(&dev->qps);
+
+	return qp;
+}
+
 int qedr_iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
 {
 	struct qedr_dev *dev = get_qedr_dev(cm_id->device);
@@ -491,10 +543,6 @@
 	int rc = 0;
 	int i;
 
-	qp = xa_load(&dev->qps, conn_param->qpn);
-	if (unlikely(!qp))
-		return -EINVAL;
-
 	laddr = (struct sockaddr_in *)&cm_id->m_local_addr;
 	raddr = (struct sockaddr_in *)&cm_id->m_remote_addr;
 	laddr6 = (struct sockaddr_in6 *)&cm_id->m_local_addr;
@@ -516,8 +564,15 @@
 		return -ENOMEM;
 
 	ep->dev = dev;
+	kref_init(&ep->refcnt);
+
+	qp = qedr_iw_load_qp(dev, conn_param->qpn);
+	if (!qp) {
+		rc = -EINVAL;
+		goto err;
+	}
+
 	ep->qp = qp;
-	qp->ep = ep;
 	cm_id->add_ref(cm_id);
 	ep->cm_id = cm_id;
 
@@ -580,16 +635,22 @@
 	in_params.qp = qp->qed_qp;
 	memcpy(in_params.local_mac_addr, dev->ndev->dev_addr, ETH_ALEN);
 
-	ep->during_connect = 1;
+	if (test_and_set_bit(QEDR_IWARP_CM_WAIT_FOR_CONNECT,
+			     &qp->iwarp_cm_flags)) {
+		rc = -ENODEV;
+		goto err; /* QP already being destroyed */
+	}
+
 	rc = dev->ops->iwarp_connect(dev->rdma_ctx, &in_params, &out_params);
-	if (rc)
+	if (rc) {
+		complete(&qp->iwarp_cm_comp);
 		goto err;
+	}
 
 	return rc;
 
 err:
-	cm_id->rem_ref(cm_id);
-	kfree(ep);
+	kref_put(&ep->refcnt, qedr_iw_free_ep);
 	return rc;
 }
 
@@ -668,6 +729,7 @@
 						    listener->qed_handle);
 
 	cm_id->rem_ref(cm_id);
+	kfree(listener);
 	return rc;
 }
 
@@ -681,14 +743,13 @@
 
 	DP_DEBUG(dev, QEDR_MSG_IWARP, "Accept on qpid=%d\n", conn_param->qpn);
 
-	qp = xa_load(&dev->qps, conn_param->qpn);
+	qp = qedr_iw_load_qp(dev, conn_param->qpn);
 	if (!qp) {
 		DP_ERR(dev, "Invalid QP number %d\n", conn_param->qpn);
 		return -EINVAL;
 	}
 
 	ep->qp = qp;
-	qp->ep = ep;
 	cm_id->add_ref(cm_id);
 	ep->cm_id = cm_id;
 
@@ -700,15 +761,23 @@
 	params.ird = conn_param->ird;
 	params.ord = conn_param->ord;
 
-	ep->during_connect = 1;
+	if (test_and_set_bit(QEDR_IWARP_CM_WAIT_FOR_CONNECT,
+			     &qp->iwarp_cm_flags)) {
+		rc = -EINVAL;
+		goto err; /* QP already destroyed */
+	}
+
 	rc = dev->ops->iwarp_accept(dev->rdma_ctx, &params);
-	if (rc)
+	if (rc) {
+		complete(&qp->iwarp_cm_comp);
 		goto err;
+	}
 
 	return rc;
+
 err:
-	ep->during_connect = 0;
-	cm_id->rem_ref(cm_id);
+	kref_put(&ep->refcnt, qedr_iw_free_ep);
+
 	return rc;
 }
 
@@ -731,17 +800,14 @@
 {
 	struct qedr_qp *qp = get_qedr_qp(ibqp);
 
-	atomic_inc(&qp->refcnt);
+	kref_get(&qp->refcnt);
 }
 
 void qedr_iw_qp_rem_ref(struct ib_qp *ibqp)
 {
 	struct qedr_qp *qp = get_qedr_qp(ibqp);
 
-	if (atomic_dec_and_test(&qp->refcnt)) {
-		xa_erase_irq(&qp->dev->qps, qp->qp_id);
-		kfree(qp);
-	}
+	kref_put(&qp->refcnt, qedr_iw_free_qp);
 }
 
 struct ib_qp *qedr_iw_get_qp(struct ib_device *ibdev, int qpn)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/qedr/verbs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/qedr/verbs.c
@@ -51,6 +51,7 @@
 #include "verbs.h"
 #include <rdma/qedr-abi.h>
 #include "qedr_roce_cm.h"
+#include "qedr_iw_cm.h"
 
 #define QEDR_SRQ_WQE_ELEM_SIZE	sizeof(union rdma_srq_elm)
 #define	RDMA_MAX_SGE_PER_SRQ	(4)
@@ -697,7 +698,7 @@
 static inline int qedr_init_user_queue(struct ib_udata *udata,
 				       struct qedr_dev *dev,
 				       struct qedr_userq *q, u64 buf_addr,
-				       size_t buf_len, int access, int dmasync,
+				       size_t buf_len, int access,
 				       int alloc_and_init)
 {
 	u32 fw_pages;
@@ -705,7 +706,7 @@
 
 	q->buf_addr = buf_addr;
 	q->buf_len = buf_len;
-	q->umem = ib_umem_get(udata, q->buf_addr, q->buf_len, access, dmasync);
+	q->umem = ib_umem_get(&dev->ibdev, q->buf_addr, q->buf_len, access);
 	if (IS_ERR(q->umem)) {
 		DP_ERR(dev, "create user queue: failed ib_umem_get, got %ld\n",
 		       PTR_ERR(q->umem));
@@ -856,8 +857,7 @@
 		cq->cq_type = QEDR_CQ_TYPE_USER;
 
 		rc = qedr_init_user_queue(udata, dev, &cq->q, ureq.addr,
-					  ureq.len, IB_ACCESS_LOCAL_WRITE, 1,
-					  1);
+					  ureq.len, IB_ACCESS_LOCAL_WRITE, 1);
 		if (rc)
 			goto err0;
 
@@ -1193,7 +1193,10 @@
 				      struct ib_qp_init_attr *attrs)
 {
 	spin_lock_init(&qp->q_lock);
-	atomic_set(&qp->refcnt, 1);
+	if (rdma_protocol_iwarp(&dev->ibdev, 1)) {
+		kref_init(&qp->refcnt);
+		init_completion(&qp->iwarp_cm_comp);
+	}
 	qp->pd = pd;
 	qp->qp_type = attrs->qp_type;
 	qp->max_inline_data = attrs->cap.max_inline_data;
@@ -1279,19 +1282,18 @@
 static int qedr_init_srq_user_params(struct ib_udata *udata,
 				     struct qedr_srq *srq,
 				     struct qedr_create_srq_ureq *ureq,
-				     int access, int dmasync)
+				     int access)
 {
 	struct scatterlist *sg;
 	int rc;
 
 	rc = qedr_init_user_queue(udata, srq->dev, &srq->usrq, ureq->srq_addr,
-				  ureq->srq_len, access, dmasync, 1);
+				  ureq->srq_len, access, 1);
 	if (rc)
 		return rc;
 
-	srq->prod_umem =
-		ib_umem_get(udata, ureq->prod_pair_addr,
-			    sizeof(struct rdma_srq_producers), access, dmasync);
+	srq->prod_umem = ib_umem_get(srq->ibsrq.device, ureq->prod_pair_addr,
+				     sizeof(struct rdma_srq_producers), access);
 	if (IS_ERR(srq->prod_umem)) {
 		qedr_free_pbl(srq->dev, &srq->usrq.pbl_info, srq->usrq.pbl_tbl);
 		ib_umem_release(srq->usrq.umem);
@@ -1387,7 +1389,7 @@
 			goto err0;
 		}
 
-		rc = qedr_init_srq_user_params(udata, srq, &ureq, 0, 0);
+		rc = qedr_init_srq_user_params(udata, srq, &ureq, 0);
 		if (rc)
 			goto err0;
 
@@ -1577,6 +1579,14 @@
 
 	ib_umem_release(qp->urq.umem);
 	qp->urq.umem = NULL;
+
+	if (rdma_protocol_roce(&dev->ibdev, 1)) {
+		qedr_free_pbl(dev, &qp->usq.pbl_info, qp->usq.pbl_tbl);
+		qedr_free_pbl(dev, &qp->urq.pbl_info, qp->urq.pbl_tbl);
+	} else {
+		kfree(qp->usq.pbl_tbl);
+		kfree(qp->urq.pbl_tbl);
+	}
 }
 
 static int qedr_create_user_qp(struct qedr_dev *dev,
@@ -1592,6 +1602,7 @@
 	int alloc_and_init = rdma_protocol_roce(&dev->ibdev, 1);
 	int rc = -EINVAL;
 
+	qp->create_type = QEDR_QP_CREATE_USER;
 	memset(&ureq, 0, sizeof(ureq));
 	rc = ib_copy_from_udata(&ureq, udata, sizeof(ureq));
 	if (rc) {
@@ -1599,16 +1610,16 @@
 		return rc;
 	}
 
-	/* SQ - read access only (0), dma sync not required (0) */
+	/* SQ - read access only (0) */
 	rc = qedr_init_user_queue(udata, dev, &qp->usq, ureq.sq_addr,
-				  ureq.sq_len, 0, 0, alloc_and_init);
+				  ureq.sq_len, 0, alloc_and_init);
 	if (rc)
 		return rc;
 
 	if (!qp->srq) {
-		/* RQ - read access only (0), dma sync not required (0) */
+		/* RQ - read access only (0) */
 		rc = qedr_init_user_queue(udata, dev, &qp->urq, ureq.rq_addr,
-					  ureq.rq_len, 0, 0, alloc_and_init);
+					  ureq.rq_len, 0, alloc_and_init);
 		if (rc)
 			return rc;
 	}
@@ -1805,6 +1816,7 @@
 	u32 n_sq_entries;
 
 	memset(&in_params, 0, sizeof(in_params));
+	qp->create_type = QEDR_QP_CREATE_KERNEL;
 
 	/* A single work request may take up to QEDR_MAX_SQ_WQE_SIZE elements in
 	 * the ring. The ring should allow at least a single WR, even if the
@@ -1918,7 +1930,7 @@
 	qp->ibqp.qp_num = qp->qp_id;
 
 	if (rdma_protocol_iwarp(&dev->ibdev, 1)) {
-		rc = xa_insert_irq(&dev->qps, qp->qp_id, qp, GFP_KERNEL);
+		rc = xa_insert(&dev->qps, qp->qp_id, qp, GFP_KERNEL);
 		if (rc)
 			goto err;
 	}
@@ -2245,6 +2257,8 @@
 					1 << max_t(int, attr->timeout - 8, 0);
 		else
 			qp_params.ack_timeout = 0;
+
+		qp->timeout = attr->timeout;
 	}
 
 	if (attr_mask & IB_QP_RETRY_CNT) {
@@ -2369,15 +2383,18 @@
 	int rc = 0;
 
 	memset(&params, 0, sizeof(params));
-
-	rc = dev->ops->rdma_query_qp(dev->rdma_ctx, qp->qed_qp, &params);
-	if (rc)
-		goto err;
-
 	memset(qp_attr, 0, sizeof(*qp_attr));
 	memset(qp_init_attr, 0, sizeof(*qp_init_attr));
 
-	qp_attr->qp_state = qedr_get_ibqp_state(params.state);
+	if (qp->qp_type != IB_QPT_GSI) {
+		rc = dev->ops->rdma_query_qp(dev->rdma_ctx, qp->qed_qp, &params);
+		if (rc)
+			goto err;
+		qp_attr->qp_state = qedr_get_ibqp_state(params.state);
+	} else {
+		qp_attr->qp_state = qedr_get_ibqp_state(QED_ROCE_QP_STATE_RTS);
+	}
+
 	qp_attr->cur_qp_state = qedr_get_ibqp_state(params.state);
 	qp_attr->path_mtu = ib_mtu_int_to_enum(params.mtu);
 	qp_attr->path_mig_state = IB_MIG_MIGRATED;
@@ -2391,7 +2408,7 @@
 	qp_attr->cap.max_recv_wr = qp->rq.max_wr;
 	qp_attr->cap.max_send_sge = qp->sq.max_sges;
 	qp_attr->cap.max_recv_sge = qp->rq.max_sges;
-	qp_attr->cap.max_inline_data = ROCE_REQ_MAX_INLINE_DATA_SIZE;
+	qp_attr->cap.max_inline_data = dev->attr.max_inline;
 	qp_init_attr->cap = qp_attr->cap;
 
 	qp_attr->ah_attr.type = RDMA_AH_ATTR_TYPE_ROCE;
@@ -2401,7 +2418,7 @@
 	rdma_ah_set_dgid_raw(&qp_attr->ah_attr, &params.dgid.bytes[0]);
 	rdma_ah_set_port_num(&qp_attr->ah_attr, 1);
 	rdma_ah_set_sl(&qp_attr->ah_attr, 0);
-	qp_attr->timeout = params.timeout;
+	qp_attr->timeout = qp->timeout;
 	qp_attr->rnr_retry = params.rnr_retry;
 	qp_attr->retry_cnt = params.retry_cnt;
 	qp_attr->min_rnr_timer = params.min_rnr_nak_timer;
@@ -2437,7 +2454,7 @@
 			return rc;
 	}
 
-	if (udata)
+	if (qp->create_type == QEDR_QP_CREATE_USER)
 		qedr_cleanup_user(dev, qp);
 	else
 		qedr_cleanup_kernel(dev, qp);
@@ -2467,34 +2484,46 @@
 			qedr_modify_qp(ibqp, &attr, attr_mask, NULL);
 		}
 	} else {
-		/* Wait for the connect/accept to complete */
-		if (qp->ep) {
-			int wait_count = 1;
-
-			while (qp->ep->during_connect) {
-				DP_DEBUG(dev, QEDR_MSG_QP,
-					 "Still in during connect/accept\n");
-
-				msleep(100);
-				if (wait_count++ > 200) {
-					DP_NOTICE(dev,
-						  "during connect timeout\n");
-					break;
-				}
-			}
-		}
+		/* If connection establishment started the WAIT_FOR_CONNECT
+		 * bit will be on and we need to Wait for the establishment
+		 * to complete before destroying the qp.
+		 */
+		if (test_and_set_bit(QEDR_IWARP_CM_WAIT_FOR_CONNECT,
+				     &qp->iwarp_cm_flags))
+			wait_for_completion(&qp->iwarp_cm_comp);
+
+		/* If graceful disconnect started, the WAIT_FOR_DISCONNECT
+		 * bit will be on, and we need to wait for the disconnect to
+		 * complete before continuing. We can use the same completion,
+		 * iwarp_cm_comp, since this is the only place that waits for
+		 * this completion and it is sequential. In addition,
+		 * disconnect can't occur before the connection is fully
+		 * established, therefore if WAIT_FOR_DISCONNECT is on it
+		 * means WAIT_FOR_CONNECT is also on and the completion for
+		 * CONNECT already occurred.
+		 */
+		if (test_and_set_bit(QEDR_IWARP_CM_WAIT_FOR_DISCONNECT,
+				     &qp->iwarp_cm_flags))
+			wait_for_completion(&qp->iwarp_cm_comp);
 	}
 
 	if (qp->qp_type == IB_QPT_GSI)
 		qedr_destroy_gsi_qp(dev);
 
+	/* We need to remove the entry from the xarray before we release the
+	 * qp_id to avoid a race of the qp_id being reallocated and failing
+	 * on xa_insert
+	 */
+	if (rdma_protocol_iwarp(&dev->ibdev, 1))
+		xa_erase(&dev->qps, qp->qp_id);
+
 	qedr_free_qp_resources(dev, qp, udata);
 
-	if (atomic_dec_and_test(&qp->refcnt) &&
-	    rdma_protocol_iwarp(&dev->ibdev, 1)) {
-		xa_erase_irq(&dev->qps, qp->qp_id);
+	if (rdma_protocol_iwarp(&dev->ibdev, 1))
+		qedr_iw_qp_rem_ref(&qp->ibqp);
+	else
 		kfree(qp);
-	}
+
 	return 0;
 }
 
@@ -2597,7 +2626,7 @@
 
 	mr->type = QEDR_MR_USER;
 
-	mr->umem = ib_umem_get(udata, start, len, acc, 0);
+	mr->umem = ib_umem_get(ibpd->device, start, len, acc);
 	if (IS_ERR(mr->umem)) {
 		rc = -EFAULT;
 		goto err0;
@@ -2673,8 +2702,8 @@
 
 	dev->ops->rdma_free_tid(dev->rdma_ctx, mr->hw_mr.itid);
 
-	if ((mr->type != QEDR_MR_DMA) && (mr->type != QEDR_MR_FRMR))
-		qedr_free_pbl(dev, &mr->info.pbl_info, mr->info.pbl_table);
+	if (mr->type != QEDR_MR_DMA)
+		free_mr_info(dev, &mr->info);
 
 	/* it could be user registered memory. */
 	ib_umem_release(mr->umem);
@@ -3436,7 +3465,7 @@
 	 * count and consumer count and subtract it from max
 	 * work request supported so that we get elements left.
 	 */
-	used = hw_srq->wr_prod_cnt - hw_srq->wr_cons_cnt;
+	used = hw_srq->wr_prod_cnt - (u32)atomic_read(&hw_srq->wr_cons_cnt);
 
 	return hw_srq->max_wr - used;
 }
@@ -3451,7 +3480,6 @@
 	unsigned long flags;
 	int status = 0;
 	u32 num_sge;
-	u32 offset;
 
 	spin_lock_irqsave(&srq->lock, flags);
 
@@ -3464,7 +3492,8 @@
 		if (!qedr_srq_elem_left(hw_srq) ||
 		    wr->num_sge > srq->hw_srq.max_sges) {
 			DP_ERR(dev, "Can't post WR  (%d,%d) || (%d > %d)\n",
-			       hw_srq->wr_prod_cnt, hw_srq->wr_cons_cnt,
+			       hw_srq->wr_prod_cnt,
+			       atomic_read(&hw_srq->wr_cons_cnt),
 			       wr->num_sge, srq->hw_srq.max_sges);
 			status = -ENOMEM;
 			*bad_wr = wr;
@@ -3498,22 +3527,20 @@
 			hw_srq->sge_prod++;
 		}
 
-		/* Flush WQE and SGE information before
+		/* Update WQE and SGE information before
 		 * updating producer.
 		 */
-		wmb();
+		dma_wmb();
 
 		/* SRQ producer is 8 bytes. Need to update SGE producer index
 		 * in first 4 bytes and need to update WQE producer in
 		 * next 4 bytes.
 		 */
-		*srq->hw_srq.virt_prod_pair_addr = hw_srq->sge_prod;
-		offset = offsetof(struct rdma_srq_producers, wqe_prod);
-		*((u8 *)srq->hw_srq.virt_prod_pair_addr + offset) =
-			hw_srq->wqe_prod;
+		srq->hw_srq.virt_prod_pair_addr->sge_prod = hw_srq->sge_prod;
+		/* Make sure sge producer is updated first */
+		dma_wmb();
+		srq->hw_srq.virt_prod_pair_addr->wqe_prod = hw_srq->wqe_prod;
 
-		/* Flush producer after updating it. */
-		wmb();
 		wr = wr->next;
 	}
 
@@ -3932,7 +3959,7 @@
 	} else {
 		__process_resp_one(dev, qp, cq, wc, resp, wr_id);
 	}
-	srq->hw_srq.wr_cons_cnt++;
+	atomic_inc(&srq->hw_srq.wr_cons_cnt);
 
 	return 1;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/qib/qib_sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/qib/qib_sysfs.c
@@ -301,6 +301,9 @@
 	struct qib_pportdata *ppd =
 		container_of(kobj, struct qib_pportdata, pport_kobj);
 
+	if (!pattr->show)
+		return -EIO;
+
 	return pattr->show(ppd, buf);
 }
 
@@ -312,6 +315,9 @@
 	struct qib_pportdata *ppd =
 		container_of(kobj, struct qib_pportdata, pport_kobj);
 
+	if (!pattr->store)
+		return -EIO;
+
 	return pattr->store(ppd, buf, len);
 }
 
@@ -754,7 +760,7 @@
 		qib_dev_err(dd,
 			"Skipping linkcontrol sysfs info, (err %d) port %u\n",
 			ret, port_num);
-		goto bail;
+		goto bail_link;
 	}
 	kobject_uevent(&ppd->pport_kobj, KOBJ_ADD);
 
@@ -764,7 +770,7 @@
 		qib_dev_err(dd,
 			"Skipping sl2vl sysfs info, (err %d) port %u\n",
 			ret, port_num);
-		goto bail_link;
+		goto bail_sl;
 	}
 	kobject_uevent(&ppd->sl2vl_kobj, KOBJ_ADD);
 
@@ -774,7 +780,7 @@
 		qib_dev_err(dd,
 			"Skipping diag_counters sysfs info, (err %d) port %u\n",
 			ret, port_num);
-		goto bail_sl;
+		goto bail_diagc;
 	}
 	kobject_uevent(&ppd->diagc_kobj, KOBJ_ADD);
 
@@ -787,7 +793,7 @@
 		qib_dev_err(dd,
 		 "Skipping Congestion Control sysfs info, (err %d) port %u\n",
 		 ret, port_num);
-		goto bail_diagc;
+		goto bail_cc;
 	}
 
 	kobject_uevent(&ppd->pport_cc_kobj, KOBJ_ADD);
@@ -848,6 +854,7 @@
 				&cc_table_bin_attr);
 			kobject_put(&ppd->pport_cc_kobj);
 		}
+		kobject_put(&ppd->diagc_kobj);
 		kobject_put(&ppd->sl2vl_kobj);
 		kobject_put(&ppd->pport_kobj);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/qib/qib_user_sdma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/qib/qib_user_sdma.c
@@ -602,7 +602,7 @@
 /*
  * How many pages in this iovec element?
  */
-static int qib_user_sdma_num_pages(const struct iovec *iov)
+static size_t qib_user_sdma_num_pages(const struct iovec *iov)
 {
 	const unsigned long addr  = (unsigned long) iov->iov_base;
 	const unsigned long  len  = iov->iov_len;
@@ -658,7 +658,7 @@
 static int qib_user_sdma_pin_pages(const struct qib_devdata *dd,
 				   struct qib_user_sdma_queue *pq,
 				   struct qib_user_sdma_pkt *pkt,
-				   unsigned long addr, int tlen, int npages)
+				   unsigned long addr, int tlen, size_t npages)
 {
 	struct page *pages[8];
 	int i, j;
@@ -722,7 +722,7 @@
 	unsigned long idx;
 
 	for (idx = 0; idx < niov; idx++) {
-		const int npages = qib_user_sdma_num_pages(iov + idx);
+		const size_t npages = qib_user_sdma_num_pages(iov + idx);
 		const unsigned long addr = (unsigned long) iov[idx].iov_base;
 
 		ret = qib_user_sdma_pin_pages(dd, pq, pkt, addr,
@@ -824,8 +824,8 @@
 		unsigned pktnw;
 		unsigned pktnwc;
 		int nfrags = 0;
-		int npages = 0;
-		int bytes_togo = 0;
+		size_t npages = 0;
+		size_t bytes_togo = 0;
 		int tiddma = 0;
 		int cfur;
 
@@ -885,7 +885,11 @@
 
 			npages += qib_user_sdma_num_pages(&iov[idx]);
 
-			bytes_togo += slen;
+			if (check_add_overflow(bytes_togo, slen, &bytes_togo) ||
+			    bytes_togo > type_max(typeof(pkt->bytes_togo))) {
+				ret = -EINVAL;
+				goto free_pbc;
+			}
 			pktnwc += slen >> 2;
 			idx++;
 			nfrags++;
@@ -904,8 +908,7 @@
 		}
 
 		if (frag_size) {
-			int tidsmsize, n;
-			size_t pktsize;
+			size_t tidsmsize, n, pktsize, sz, addrlimit;
 
 			n = npages*((2*PAGE_SIZE/frag_size)+1);
 			pktsize = struct_size(pkt, addr, n);
@@ -923,14 +926,24 @@
 			else
 				tidsmsize = 0;
 
-			pkt = kmalloc(pktsize+tidsmsize, GFP_KERNEL);
+			if (check_add_overflow(pktsize, tidsmsize, &sz)) {
+				ret = -EINVAL;
+				goto free_pbc;
+			}
+			pkt = kmalloc(sz, GFP_KERNEL);
 			if (!pkt) {
 				ret = -ENOMEM;
 				goto free_pbc;
 			}
 			pkt->largepkt = 1;
 			pkt->frag_size = frag_size;
-			pkt->addrlimit = n + ARRAY_SIZE(pkt->addr);
+			if (check_add_overflow(n, ARRAY_SIZE(pkt->addr),
+					       &addrlimit) ||
+			    addrlimit > type_max(typeof(pkt->addrlimit))) {
+				ret = -EINVAL;
+				goto free_pkt;
+			}
+			pkt->addrlimit = addrlimit;
 
 			if (tiddma) {
 				char *tidsm = (char *)pkt + pktsize;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/qib/qib_verbs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/qib/qib_verbs.c
@@ -329,8 +329,10 @@
 		if (mcast == NULL)
 			goto drop;
 		this_cpu_inc(ibp->pmastats->n_multicast_rcv);
+		rcu_read_lock();
 		list_for_each_entry_rcu(p, &mcast->qp_list, list)
 			qib_qp_rcv(rcd, hdr, 1, data, tlen, p->qp);
+		rcu_read_unlock();
 		/*
 		 * Notify rvt_multicast_detach() if it is waiting for us
 		 * to finish.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/usnic/usnic_ib_verbs.c
@@ -214,6 +214,7 @@
 
 		}
 		usnic_uiom_free_dev_list(dev_list);
+		dev_list = NULL;
 	}
 
 	/* Try to find resources on an unused vf */
@@ -239,6 +240,8 @@
 qp_grp_check:
 	if (IS_ERR_OR_NULL(qp_grp)) {
 		usnic_err("Failed to allocate qp_grp\n");
+		if (usnic_ib_share_vf)
+			usnic_uiom_free_dev_list(dev_list);
 		return ERR_PTR(qp_grp ? PTR_ERR(qp_grp) : -ENOMEM);
 	}
 	return qp_grp;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/usnic/usnic_uiom.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/usnic/usnic_uiom.c
@@ -281,8 +281,8 @@
 				size = pa_end - pa_start + PAGE_SIZE;
 				usnic_dbg("va 0x%lx pa %pa size 0x%zx flags 0x%x",
 					va_start, &pa_start, size, flags);
-				err = iommu_map(pd->domain, va_start, pa_start,
-							size, flags);
+				err = iommu_map_atomic(pd->domain, va_start,
+						       pa_start, size, flags);
 				if (err) {
 					usnic_err("Failed to map va 0x%lx pa %pa size 0x%zx with err %d\n",
 						va_start, &pa_start, size, err);
@@ -298,8 +298,8 @@
 				size = pa - pa_start + PAGE_SIZE;
 				usnic_dbg("va 0x%lx pa %pa size 0x%zx flags 0x%x\n",
 					va_start, &pa_start, size, flags);
-				err = iommu_map(pd->domain, va_start, pa_start,
-						size, flags);
+				err = iommu_map_atomic(pd->domain, va_start,
+						       pa_start, size, flags);
 				if (err) {
 					usnic_err("Failed to map va 0x%lx pa %pa size 0x%zx with err %d\n",
 						va_start, &pa_start, size, err);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/vmw_pvrdma/pvrdma_cq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/vmw_pvrdma/pvrdma_cq.c
@@ -135,8 +135,8 @@
 			goto err_cq;
 		}
 
-		cq->umem = ib_umem_get(udata, ucmd.buf_addr, ucmd.buf_size,
-				       IB_ACCESS_LOCAL_WRITE, 1);
+		cq->umem = ib_umem_get(ibdev, ucmd.buf_addr, ucmd.buf_size,
+				       IB_ACCESS_LOCAL_WRITE);
 		if (IS_ERR(cq->umem)) {
 			ret = PTR_ERR(cq->umem);
 			goto err_cq;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/vmw_pvrdma/pvrdma_main.c
@@ -266,7 +266,7 @@
 	}
 	ret = ib_device_set_netdev(&dev->ib_dev, dev->netdev, 1);
 	if (ret)
-		return ret;
+		goto err_srq_free;
 	spin_lock_init(&dev->srq_tbl_lock);
 	rdma_set_device_sysfs_group(&dev->ib_dev, &pvrdma_attr_group);
 
@@ -829,7 +829,7 @@
 	    !(pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) {
 		dev_err(&pdev->dev, "PCI BAR region not MMIO\n");
 		ret = -ENOMEM;
-		goto err_free_device;
+		goto err_disable_pdev;
 	}
 
 	ret = pci_request_regions(pdev, DRV_NAME);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/vmw_pvrdma/pvrdma_mr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/vmw_pvrdma/pvrdma_mr.c
@@ -126,7 +126,7 @@
 		return ERR_PTR(-EINVAL);
 	}
 
-	umem = ib_umem_get(udata, start, length, access_flags, 0);
+	umem = ib_umem_get(pd->device, start, length, access_flags);
 	if (IS_ERR(umem)) {
 		dev_warn(&dev->pdev->dev,
 			 "could not get umem for mem region\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c
@@ -262,8 +262,9 @@
 
 			if (!is_srq) {
 				/* set qp->sq.wqe_cnt, shift, buf_size.. */
-				qp->rumem = ib_umem_get(udata, ucmd.rbuf_addr,
-							ucmd.rbuf_size, 0, 0);
+				qp->rumem =
+					ib_umem_get(pd->device, ucmd.rbuf_addr,
+						    ucmd.rbuf_size, 0);
 				if (IS_ERR(qp->rumem)) {
 					ret = PTR_ERR(qp->rumem);
 					goto err_qp;
@@ -274,8 +275,8 @@
 				qp->srq = to_vsrq(init_attr->srq);
 			}
 
-			qp->sumem = ib_umem_get(udata, ucmd.sbuf_addr,
-						ucmd.sbuf_size, 0, 0);
+			qp->sumem = ib_umem_get(pd->device, ucmd.sbuf_addr,
+						ucmd.sbuf_size, 0);
 			if (IS_ERR(qp->sumem)) {
 				if (!is_srq)
 					ib_umem_release(qp->rumem);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/hw/vmw_pvrdma/pvrdma_srq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/hw/vmw_pvrdma/pvrdma_srq.c
@@ -146,7 +146,7 @@
 		goto err_srq;
 	}
 
-	srq->umem = ib_umem_get(udata, ucmd.buf_addr, ucmd.buf_size, 0, 0);
+	srq->umem = ib_umem_get(ibsrq->device, ucmd.buf_addr, ucmd.buf_size, 0);
 	if (IS_ERR(srq->umem)) {
 		ret = PTR_ERR(srq->umem);
 		goto err_srq;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/rdmavt/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/rdmavt/Kconfig
@@ -1,7 +1,8 @@
 # SPDX-License-Identifier: GPL-2.0-only
 config INFINIBAND_RDMAVT
 	tristate "RDMA verbs transport library"
-	depends on X86_64 && ARCH_DMA_ADDR_T_64BIT
+	depends on INFINIBAND_VIRT_DMA
+	depends on X86_64
 	depends on PCI
 	select DMA_VIRT_OPS
 	---help---
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/rdmavt/cq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/rdmavt/cq.c
@@ -248,8 +248,8 @@
 	 */
 	if (udata && udata->outlen >= sizeof(__u64)) {
 		cq->ip = rvt_create_mmap_info(rdi, sz, udata, u_wc);
-		if (!cq->ip) {
-			err = -ENOMEM;
+		if (IS_ERR(cq->ip)) {
+			err = PTR_ERR(cq->ip);
 			goto bail_wc;
 		}
 
@@ -327,7 +327,7 @@
 	if (cq->ip)
 		kref_put(&cq->ip->ref, rvt_release_mmap_info);
 	else
-		vfree(cq->queue);
+		vfree(cq->kqueue);
 }
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/rdmavt/mmap.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/rdmavt/mmap.c
@@ -154,7 +154,7 @@
  * @udata: user data (must be valid!)
  * @obj: opaque pointer to a cq, wq etc
  *
- * Return: rvt_mmap struct on success
+ * Return: rvt_mmap struct on success, ERR_PTR on failure
  */
 struct rvt_mmap_info *rvt_create_mmap_info(struct rvt_dev_info *rdi, u32 size,
 					   struct ib_udata *udata, void *obj)
@@ -166,7 +166,7 @@
 
 	ip = kmalloc_node(sizeof(*ip), GFP_KERNEL, rdi->dparms.node);
 	if (!ip)
-		return ip;
+		return ERR_PTR(-ENOMEM);
 
 	size = PAGE_ALIGN(size);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/rdmavt/mr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/rdmavt/mr.c
@@ -390,7 +390,7 @@
 	if (length == 0)
 		return ERR_PTR(-EINVAL);
 
-	umem = ib_umem_get(udata, start, length, mr_access_flags, 0);
+	umem = ib_umem_get(pd->device, start, length, mr_access_flags);
 	if (IS_ERR(umem))
 		return (void *)umem;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/rdmavt/qp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/rdmavt/qp.c
@@ -61,6 +61,8 @@
 #define RVT_RWQ_COUNT_THRESHOLD 16
 
 static void rvt_rc_timeout(struct timer_list *t);
+static void rvt_reset_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp,
+			 enum ib_qp_type type);
 
 /*
  * Convert the AETH RNR timeout code into the number of microseconds.
@@ -452,40 +454,41 @@
 }
 
 /**
- * free_all_qps - check for QPs still in use
+ * rvt_free_qp_cb - callback function to reset a qp
+ * @qp: the qp to reset
+ * @v: a 64-bit value
+ *
+ * This function resets the qp and removes it from the
+ * qp hash table.
+ */
+static void rvt_free_qp_cb(struct rvt_qp *qp, u64 v)
+{
+	unsigned int *qp_inuse = (unsigned int *)v;
+	struct rvt_dev_info *rdi = ib_to_rvt(qp->ibqp.device);
+
+	/* Reset the qp and remove it from the qp hash list */
+	rvt_reset_qp(rdi, qp, qp->ibqp.qp_type);
+
+	/* Increment the qp_inuse count */
+	(*qp_inuse)++;
+}
+
+/**
+ * rvt_free_all_qps - check for QPs still in use
  * @rdi: rvt device info structure
  *
  * There should not be any QPs still in use.
  * Free memory for table.
+ * Return the number of QPs still in use.
  */
 static unsigned rvt_free_all_qps(struct rvt_dev_info *rdi)
 {
-	unsigned long flags;
-	struct rvt_qp *qp;
-	unsigned n, qp_inuse = 0;
-	spinlock_t *ql; /* work around too long line below */
-
-	if (rdi->driver_f.free_all_qps)
-		qp_inuse = rdi->driver_f.free_all_qps(rdi);
+	unsigned int qp_inuse = 0;
 
 	qp_inuse += rvt_mcast_tree_empty(rdi);
 
-	if (!rdi->qp_dev)
-		return qp_inuse;
+	rvt_qp_iter(rdi, (u64)&qp_inuse, rvt_free_qp_cb);
 
-	ql = &rdi->qp_dev->qpt_lock;
-	spin_lock_irqsave(ql, flags);
-	for (n = 0; n < rdi->qp_dev->qp_table_size; n++) {
-		qp = rcu_dereference_protected(rdi->qp_dev->qp_table[n],
-					       lockdep_is_held(ql));
-		RCU_INIT_POINTER(rdi->qp_dev->qp_table[n], NULL);
-
-		for (; qp; qp = rcu_dereference_protected(qp->next,
-							  lockdep_is_held(ql)))
-			qp_inuse++;
-	}
-	spin_unlock_irqrestore(ql, flags);
-	synchronize_rcu();
 	return qp_inuse;
 }
 
@@ -502,8 +505,6 @@
 	if (qps_inuse)
 		rvt_pr_err(rdi, "QP memory leak! %u still in use\n",
 			   qps_inuse);
-	if (!rdi->qp_dev)
-		return;
 
 	kfree(rdi->qp_dev->qp_table);
 	free_qpn_table(&rdi->qp_dev->qpn_table);
@@ -895,21 +896,19 @@
 	qp->s_tail_ack_queue = 0;
 	qp->s_acked_ack_queue = 0;
 	qp->s_num_rd_atomic = 0;
-	if (qp->r_rq.kwq)
-		qp->r_rq.kwq->count = qp->r_rq.size;
 	qp->r_sge.num_sge = 0;
 	atomic_set(&qp->s_reserved_used, 0);
 }
 
 /**
- * rvt_reset_qp - initialize the QP state to the reset state
+ * _rvt_reset_qp - initialize the QP state to the reset state
  * @qp: the QP to reset
  * @type: the QP type
  *
  * r_lock, s_hlock, and s_lock are required to be held by the caller
  */
-static void rvt_reset_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp,
-			 enum ib_qp_type type)
+static void _rvt_reset_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp,
+			  enum ib_qp_type type)
 	__must_hold(&qp->s_lock)
 	__must_hold(&qp->s_hlock)
 	__must_hold(&qp->r_lock)
@@ -955,6 +954,27 @@
 	lockdep_assert_held(&qp->s_lock);
 }
 
+/**
+ * rvt_reset_qp - initialize the QP state to the reset state
+ * @rdi: the device info
+ * @qp: the QP to reset
+ * @type: the QP type
+ *
+ * This is the wrapper function to acquire the r_lock, s_hlock, and s_lock
+ * before calling _rvt_reset_qp().
+ */
+static void rvt_reset_qp(struct rvt_dev_info *rdi, struct rvt_qp *qp,
+			 enum ib_qp_type type)
+{
+	spin_lock_irq(&qp->r_lock);
+	spin_lock(&qp->s_hlock);
+	spin_lock(&qp->s_lock);
+	_rvt_reset_qp(rdi, qp, type);
+	spin_unlock(&qp->s_lock);
+	spin_unlock(&qp->s_hlock);
+	spin_unlock_irq(&qp->r_lock);
+}
+
 /** rvt_free_qpn - Free a qpn from the bit map
  * @qpt: QP table
  * @qpn: queue pair number to free
@@ -1172,7 +1192,7 @@
 		err = alloc_ud_wq_attr(qp, rdi->dparms.node);
 		if (err) {
 			ret = (ERR_PTR(err));
-			goto bail_driver_priv;
+			goto bail_rq_rvt;
 		}
 
 		err = alloc_qpn(rdi, &rdi->qp_dev->qpn_table,
@@ -1220,8 +1240,8 @@
 
 			qp->ip = rvt_create_mmap_info(rdi, s, udata,
 						      qp->r_rq.wq);
-			if (!qp->ip) {
-				ret = ERR_PTR(-ENOMEM);
+			if (IS_ERR(qp->ip)) {
+				ret = ERR_CAST(qp->ip);
 				goto bail_qpn;
 			}
 
@@ -1276,9 +1296,11 @@
 	rvt_free_qpn(&rdi->qp_dev->qpn_table, qp->ibqp.qp_num);
 
 bail_rq_wq:
-	rvt_free_rq(&qp->r_rq);
 	free_ud_wq_attr(qp);
 
+bail_rq_rvt:
+	rvt_free_rq(&qp->r_rq);
+
 bail_driver_priv:
 	rdi->driver_f.qp_priv_free(rdi, qp);
 
@@ -1546,7 +1568,7 @@
 	switch (new_state) {
 	case IB_QPS_RESET:
 		if (qp->state != IB_QPS_RESET)
-			rvt_reset_qp(rdi, qp, ibqp->qp_type);
+			_rvt_reset_qp(rdi, qp, ibqp->qp_type);
 		break;
 
 	case IB_QPS_RTR:
@@ -1695,13 +1717,7 @@
 	struct rvt_qp *qp = ibqp_to_rvtqp(ibqp);
 	struct rvt_dev_info *rdi = ib_to_rvt(ibqp->device);
 
-	spin_lock_irq(&qp->r_lock);
-	spin_lock(&qp->s_hlock);
-	spin_lock(&qp->s_lock);
 	rvt_reset_qp(rdi, qp, ibqp->qp_type);
-	spin_unlock(&qp->s_lock);
-	spin_unlock(&qp->s_hlock);
-	spin_unlock_irq(&qp->r_lock);
 
 	wait_event(qp->wait, !atomic_read(&qp->refcount));
 	/* qpn is now available for use again */
@@ -2333,31 +2349,6 @@
 }
 
 /**
- * get_count - count numbers of request work queue entries
- * in circular buffer
- * @rq: data structure for request queue entry
- * @tail: tail indices of the circular buffer
- * @head: head indices of the circular buffer
- *
- * Return - total number of entries in the circular buffer
- */
-static u32 get_count(struct rvt_rq *rq, u32 tail, u32 head)
-{
-	u32 count;
-
-	count = head;
-
-	if (count >= rq->size)
-		count = 0;
-	if (count < tail)
-		count += rq->size - tail;
-	else
-		count -= tail;
-
-	return count;
-}
-
-/**
  * get_rvt_head - get head indices of the circular buffer
  * @rq: data structure for request queue entry
  * @ip: the QP
@@ -2431,7 +2422,7 @@
 
 	if (kwq->count < RVT_RWQ_COUNT_THRESHOLD) {
 		head = get_rvt_head(rq, ip);
-		kwq->count = get_count(rq, tail, head);
+		kwq->count = rvt_get_rq_count(rq, head, tail);
 	}
 	if (unlikely(kwq->count == 0)) {
 		ret = 0;
@@ -2466,7 +2457,9 @@
 		 * the number of remaining WQEs.
 		 */
 		if (kwq->count < srq->limit) {
-			kwq->count = get_count(rq, tail, get_rvt_head(rq, ip));
+			kwq->count =
+				rvt_get_rq_count(rq,
+						 get_rvt_head(rq, ip), tail);
 			if (kwq->count < srq->limit) {
 				struct ib_event ev;
 
@@ -2817,7 +2810,7 @@
 EXPORT_SYMBOL(rvt_qp_iter);
 
 /*
- * This should be called with s_lock held.
+ * This should be called with s_lock and r_lock held.
  */
 void rvt_send_complete(struct rvt_qp *qp, struct rvt_swqe *wqe,
 		       enum ib_wc_status status)
@@ -3115,6 +3108,8 @@
 	case IB_WR_ATOMIC_FETCH_AND_ADD:
 		if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_ATOMIC)))
 			goto inv_err;
+		if (unlikely(wqe->atomic_wr.remote_addr & (sizeof(u64) - 1)))
+			goto inv_err;
 		if (unlikely(!rvt_rkey_ok(qp, &qp->r_sge.sge, sizeof(u64),
 					  wqe->atomic_wr.remote_addr,
 					  wqe->atomic_wr.rkey,
@@ -3174,7 +3169,9 @@
 	rvp->n_loop_pkts++;
 flush_send:
 	sqp->s_rnr_retry = sqp->s_rnr_retry_cnt;
+	spin_lock(&sqp->r_lock);
 	rvt_send_complete(sqp, wqe, send_status);
+	spin_unlock(&sqp->r_lock);
 	if (local_ops) {
 		atomic_dec(&sqp->local_ops_pending);
 		local_ops = 0;
@@ -3228,9 +3225,15 @@
 	spin_unlock_irqrestore(&qp->r_lock, flags);
 serr_no_r_lock:
 	spin_lock_irqsave(&sqp->s_lock, flags);
+	spin_lock(&sqp->r_lock);
 	rvt_send_complete(sqp, wqe, send_status);
+	spin_unlock(&sqp->r_lock);
 	if (sqp->ibqp.qp_type == IB_QPT_RC) {
-		int lastwqe = rvt_error_qp(sqp, IB_WC_WR_FLUSH_ERR);
+		int lastwqe;
+
+		spin_lock(&sqp->r_lock);
+		lastwqe = rvt_error_qp(sqp, IB_WC_WR_FLUSH_ERR);
+		spin_unlock(&sqp->r_lock);
 
 		sqp->s_flags &= ~RVT_S_BUSY;
 		spin_unlock_irqrestore(&sqp->s_lock, flags);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/rdmavt/rc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/rdmavt/rc.c
@@ -127,9 +127,7 @@
 			 * not atomic, which is OK, since the fuzziness is
 			 * resolved as further ACKs go out.
 			 */
-			credits = head - tail;
-			if ((int)credits < 0)
-				credits += qp->r_rq.size;
+			credits = rvt_get_rq_count(&qp->r_rq, head, tail);
 		}
 		/*
 		 * Binary search the credit table to find the code to
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/rdmavt/srq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/rdmavt/srq.c
@@ -111,8 +111,8 @@
 		u32 s = sizeof(struct rvt_rwq) + srq->rq.size * sz;
 
 		srq->ip = rvt_create_mmap_info(dev, s, udata, srq->rq.wq);
-		if (!srq->ip) {
-			ret = -ENOMEM;
+		if (IS_ERR(srq->ip)) {
+			ret = PTR_ERR(srq->ip);
 			goto bail_wq;
 		}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/rdmavt/vt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/rdmavt/vt.c
@@ -95,9 +95,7 @@
 	if (!rdi)
 		return rdi;
 
-	rdi->ports = kcalloc(nports,
-			     sizeof(struct rvt_ibport **),
-			     GFP_KERNEL);
+	rdi->ports = kcalloc(nports, sizeof(*rdi->ports), GFP_KERNEL);
 	if (!rdi->ports)
 		ib_dealloc_device(&rdi->ibdev);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/rxe/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/rxe/Kconfig
@@ -2,8 +2,9 @@
 config RDMA_RXE
 	tristate "Software RDMA over Ethernet (RoCE) driver"
 	depends on INET && PCI && INFINIBAND
-	depends on !64BIT || ARCH_DMA_ADDR_T_64BIT
+	depends on INFINIBAND_VIRT_DMA
 	select NET_UDP_TUNNEL
+	select CRYPTO
 	select CRYPTO_CRC32
 	select DMA_VIRT_OPS
 	---help---
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/rxe/rxe.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/rxe/rxe.c
@@ -48,6 +48,8 @@
 
 }
 
+bool rxe_initialized;
+
 /* free resources for a rxe device all objects created for this device must
  * have been destroyed
  */
@@ -70,6 +72,8 @@
 
 	if (rxe->tfm)
 		crypto_free_shash(rxe->tfm);
+
+	mutex_destroy(&rxe->usdev_lock);
 }
 
 /* initialize rxe device parameters */
@@ -116,6 +120,8 @@
 	rxe->attr.max_fast_reg_page_list_len	= RXE_MAX_FMR_PAGE_LIST_LEN;
 	rxe->attr.max_pkeys			= RXE_MAX_PKEYS;
 	rxe->attr.local_ca_ack_delay		= RXE_LOCAL_CA_ACK_DELAY;
+	addrconf_addr_eui48((unsigned char *)&rxe->attr.sys_image_guid,
+			rxe->ndev->dev_addr);
 
 	rxe->max_ucontext			= RXE_MAX_UCONTEXT;
 }
@@ -157,9 +163,6 @@
 
 	rxe_init_port_param(port);
 
-	if (!port->attr.pkey_tbl_len || !port->attr.gid_tbl_len)
-		return -EINVAL;
-
 	port->pkey_tbl = kcalloc(port->attr.pkey_tbl_len,
 			sizeof(*port->pkey_tbl), GFP_KERNEL);
 
@@ -358,6 +361,7 @@
 		return err;
 
 	rdma_link_register(&rxe_link_ops);
+	rxe_initialized = true;
 	pr_info("loaded\n");
 	return 0;
 }
@@ -369,6 +373,7 @@
 	rxe_net_exit();
 	rxe_cache_exit();
 
+	rxe_initialized = false;
 	pr_info("unloaded\n");
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/rxe/rxe.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/rxe/rxe.h
@@ -67,6 +67,8 @@
 
 #define RXE_ROCE_V2_SPORT		(0xc000)
 
+extern bool rxe_initialized;
+
 static inline u32 rxe_crc32(struct rxe_dev *rxe,
 			    u32 crc, void *next, size_t len)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/rxe/rxe_comp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/rxe/rxe_comp.c
@@ -150,12 +150,12 @@
 {
 	int must_sched;
 
-	skb_queue_tail(&qp->resp_pkts, skb);
-
-	must_sched = skb_queue_len(&qp->resp_pkts) > 1;
+	must_sched = skb_queue_len(&qp->resp_pkts) > 0;
 	if (must_sched != 0)
 		rxe_counter_inc(SKB_TO_PKT(skb)->rxe, RXE_CNT_COMPLETER_SCHED);
 
+	skb_queue_tail(&qp->resp_pkts, skb);
+
 	rxe_run_task(&qp->comp.task, must_sched);
 }
 
@@ -329,7 +329,7 @@
 					qp->comp.psn = pkt->psn;
 					if (qp->req.wait_psn) {
 						qp->req.wait_psn = 0;
-						rxe_run_task(&qp->req.task, 1);
+						rxe_run_task(&qp->req.task, 0);
 					}
 				}
 				return COMPST_ERROR_RETRY;
@@ -373,13 +373,15 @@
 	ret = copy_data(qp->pd, IB_ACCESS_LOCAL_WRITE,
 			&wqe->dma, payload_addr(pkt),
 			payload_size(pkt), to_mem_obj, NULL);
-	if (ret)
+	if (ret) {
+		wqe->status = IB_WC_LOC_PROT_ERR;
 		return COMPST_ERROR;
+	}
 
 	if (wqe->dma.resid == 0 && (pkt->mask & RXE_END_MASK))
 		return COMPST_COMP_ACK;
-	else
-		return COMPST_UPDATE_COMP;
+
+	return COMPST_UPDATE_COMP;
 }
 
 static inline enum comp_state do_atomic(struct rxe_qp *qp,
@@ -393,10 +395,12 @@
 	ret = copy_data(qp->pd, IB_ACCESS_LOCAL_WRITE,
 			&wqe->dma, &atomic_orig,
 			sizeof(u64), to_mem_obj, NULL);
-	if (ret)
+	if (ret) {
+		wqe->status = IB_WC_LOC_PROT_ERR;
 		return COMPST_ERROR;
-	else
-		return COMPST_COMP_ACK;
+	}
+
+	return COMPST_COMP_ACK;
 }
 
 static void make_send_cqe(struct rxe_qp *qp, struct rxe_send_wqe *wqe,
@@ -463,7 +467,7 @@
 	 */
 	if (qp->req.wait_fence) {
 		qp->req.wait_fence = 0;
-		rxe_run_task(&qp->req.task, 1);
+		rxe_run_task(&qp->req.task, 0);
 	}
 }
 
@@ -479,7 +483,7 @@
 		if (qp->req.need_rd_atomic) {
 			qp->comp.timeout_retry = 0;
 			qp->req.need_rd_atomic = 0;
-			rxe_run_task(&qp->req.task, 1);
+			rxe_run_task(&qp->req.task, 0);
 		}
 	}
 
@@ -725,7 +729,7 @@
 							RXE_CNT_COMP_RETRY);
 					qp->req.need_retry = 1;
 					qp->comp.started_retry = 1;
-					rxe_run_task(&qp->req.task, 1);
+					rxe_run_task(&qp->req.task, 0);
 				}
 
 				if (pkt) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/rxe/rxe_mmap.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/rxe/rxe_mmap.c
@@ -151,7 +151,7 @@
 
 	ip = kmalloc(sizeof(*ip), GFP_KERNEL);
 	if (!ip)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 
 	size = PAGE_ALIGN(size);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/rxe/rxe_mr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/rxe/rxe_mr.c
@@ -169,11 +169,11 @@
 	void			*vaddr;
 	int err;
 
-	umem = ib_umem_get(udata, start, length, access, 0);
+	umem = ib_umem_get(pd->ibpd.device, start, length, access);
 	if (IS_ERR(umem)) {
 		pr_warn("err %d from rxe_umem_get\n",
 			(int)PTR_ERR(umem));
-		err = -EINVAL;
+		err = PTR_ERR(umem);
 		goto err1;
 	}
 
@@ -207,6 +207,7 @@
 			vaddr = page_address(sg_page_iter_page(&sg_iter));
 			if (!vaddr) {
 				pr_warn("null vaddr\n");
+				ib_umem_release(umem);
 				err = -ENOMEM;
 				goto err1;
 			}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/rxe/rxe_net.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/rxe/rxe_net.c
@@ -117,10 +117,12 @@
 	memcpy(&fl6.daddr, daddr, sizeof(*daddr));
 	fl6.flowi6_proto = IPPROTO_UDP;
 
-	if (unlikely(ipv6_stub->ipv6_dst_lookup(sock_net(recv_sockets.sk6->sk),
-						recv_sockets.sk6->sk, &ndst, &fl6))) {
+	ndst = ipv6_stub->ipv6_dst_lookup_flow(sock_net(recv_sockets.sk6->sk),
+					       recv_sockets.sk6->sk, &fl6,
+					       NULL);
+	if (unlikely(IS_ERR(ndst))) {
 		pr_err_ratelimited("no route to %pI6\n", daddr);
-		goto put;
+		return NULL;
 	}
 
 	if (unlikely(ndst->error)) {
@@ -249,10 +251,8 @@
 
 	/* Create UDP socket */
 	err = udp_sock_create(net, &udp_cfg, &sock);
-	if (err < 0) {
-		pr_err("failed to create udp socket. err = %d\n", err);
+	if (err < 0)
 		return ERR_PTR(err);
-	}
 
 	tnl_cfg.encap_type = 1;
 	tnl_cfg.encap_rcv = rxe_udp_encap_recv;
@@ -451,6 +451,11 @@
 
 void rxe_loopback(struct sk_buff *skb)
 {
+	if (skb->protocol == htons(ETH_P_IP))
+		skb_pull(skb, sizeof(struct iphdr));
+	else
+		skb_pull(skb, sizeof(struct ipv6hdr));
+
 	rxe_rcv(skb);
 }
 
@@ -653,6 +658,12 @@
 
 	recv_sockets.sk6 = rxe_setup_udp_tunnel(&init_net,
 						htons(ROCE_V2_UDP_DPORT), true);
+	if (PTR_ERR(recv_sockets.sk6) == -EAFNOSUPPORT) {
+		recv_sockets.sk6 = NULL;
+		pr_warn("IPv6 is not supported, can not create a UDPv6 socket\n");
+		return 0;
+	}
+
 	if (IS_ERR(recv_sockets.sk6)) {
 		recv_sockets.sk6 = NULL;
 		pr_err("Failed to create IPv6 UDP tunnel\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/rxe/rxe_opcode.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/rxe/rxe_opcode.c
@@ -137,7 +137,7 @@
 		}
 	},
 	[IB_OPCODE_RC_SEND_MIDDLE]		= {
-		.name	= "IB_OPCODE_RC_SEND_MIDDLE]",
+		.name	= "IB_OPCODE_RC_SEND_MIDDLE",
 		.mask	= RXE_PAYLOAD_MASK | RXE_REQ_MASK | RXE_SEND_MASK
 				| RXE_MIDDLE_MASK,
 		.length = RXE_BTH_BYTES,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/rxe/rxe_param.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/rxe/rxe_param.h
@@ -140,7 +140,7 @@
 /* default/initial rxe port parameters */
 enum rxe_port_param {
 	RXE_PORT_GID_TBL_LEN		= 1024,
-	RXE_PORT_PORT_CAP_FLAGS		= RDMA_CORE_CAP_PROT_ROCE_UDP_ENCAP,
+	RXE_PORT_PORT_CAP_FLAGS		= IB_PORT_CM_SUP,
 	RXE_PORT_MAX_MSG_SZ		= 0x800000,
 	RXE_PORT_BAD_PKEY_CNTR		= 0,
 	RXE_PORT_QKEY_VIOL_CNTR		= 0,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/rxe/rxe_qp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/rxe/rxe_qp.c
@@ -152,7 +152,6 @@
 void free_rd_atomic_resource(struct rxe_qp *qp, struct resp_res *res)
 {
 	if (res->type == RXE_ATOMIC_MASK) {
-		rxe_drop_ref(qp);
 		kfree_skb(res->atomic.skb);
 	} else if (res->type == RXE_READ_MASK) {
 		if (res->read.mr)
@@ -212,6 +211,17 @@
 	spin_lock_init(&qp->grp_lock);
 	spin_lock_init(&qp->state_lock);
 
+	spin_lock_init(&qp->req.task.state_lock);
+	spin_lock_init(&qp->resp.task.state_lock);
+	spin_lock_init(&qp->comp.task.state_lock);
+
+	spin_lock_init(&qp->sq.sq_lock);
+	spin_lock_init(&qp->rq.producer_lock);
+	spin_lock_init(&qp->rq.consumer_lock);
+
+	skb_queue_head_init(&qp->req_pkts);
+	skb_queue_head_init(&qp->resp_pkts);
+
 	atomic_set(&qp->ssn, 0);
 	atomic_set(&qp->skb_out, 0);
 }
@@ -260,6 +270,7 @@
 	if (err) {
 		vfree(qp->sq.queue->buf);
 		kfree(qp->sq.queue);
+		qp->sq.queue = NULL;
 		return err;
 	}
 
@@ -268,13 +279,8 @@
 	qp->req.opcode		= -1;
 	qp->comp.opcode		= -1;
 
-	spin_lock_init(&qp->sq.sq_lock);
-	skb_queue_head_init(&qp->req_pkts);
-
-	rxe_init_task(rxe, &qp->req.task, qp,
-		      rxe_requester, "req");
-	rxe_init_task(rxe, &qp->comp.task, qp,
-		      rxe_completer, "comp");
+	rxe_init_task(&qp->req.task, qp, rxe_requester);
+	rxe_init_task(&qp->comp.task, qp, rxe_completer);
 
 	qp->qp_timeout_jiffies = 0; /* Can't be set for UD/UC in modify_qp */
 	if (init->qp_type == IB_QPT_RC) {
@@ -313,17 +319,12 @@
 		if (err) {
 			vfree(qp->rq.queue->buf);
 			kfree(qp->rq.queue);
+			qp->rq.queue = NULL;
 			return err;
 		}
 	}
 
-	spin_lock_init(&qp->rq.producer_lock);
-	spin_lock_init(&qp->rq.consumer_lock);
-
-	skb_queue_head_init(&qp->resp_pkts);
-
-	rxe_init_task(rxe, &qp->resp.task, qp,
-		      rxe_responder, "resp");
+	rxe_init_task(&qp->resp.task, qp, rxe_responder);
 
 	qp->resp.opcode		= OPCODE_NONE;
 	qp->resp.msn		= 0;
@@ -373,6 +374,11 @@
 err2:
 	rxe_queue_cleanup(qp->sq.queue);
 err1:
+	qp->pd = NULL;
+	qp->rcq = NULL;
+	qp->scq = NULL;
+	qp->srq = NULL;
+
 	if (srq)
 		rxe_drop_ref(srq);
 	rxe_drop_ref(scq);
@@ -592,15 +598,16 @@
 	int err;
 
 	if (mask & IB_QP_MAX_QP_RD_ATOMIC) {
-		int max_rd_atomic = __roundup_pow_of_two(attr->max_rd_atomic);
+		int max_rd_atomic = attr->max_rd_atomic ?
+			roundup_pow_of_two(attr->max_rd_atomic) : 0;
 
 		qp->attr.max_rd_atomic = max_rd_atomic;
 		atomic_set(&qp->req.rd_atomic, max_rd_atomic);
 	}
 
 	if (mask & IB_QP_MAX_DEST_RD_ATOMIC) {
-		int max_dest_rd_atomic =
-			__roundup_pow_of_two(attr->max_dest_rd_atomic);
+		int max_dest_rd_atomic = attr->max_dest_rd_atomic ?
+			roundup_pow_of_two(attr->max_dest_rd_atomic) : 0;
 
 		qp->attr.max_dest_rd_atomic = max_dest_rd_atomic;
 
@@ -794,7 +801,9 @@
 	rxe_cleanup_task(&qp->comp.task);
 
 	/* flush out any receive wr's or pending requests */
-	__rxe_do_task(&qp->req.task);
+	if (qp->req.task.func)
+		__rxe_do_task(&qp->req.task);
+
 	if (qp->sq.queue) {
 		__rxe_do_task(&qp->comp.task);
 		__rxe_do_task(&qp->req.task);
@@ -829,13 +838,15 @@
 		qp->resp.mr = NULL;
 	}
 
-	if (qp_type(qp) == IB_QPT_RC)
-		sk_dst_reset(qp->sk->sk);
-
 	free_rd_atomic_resources(qp);
 
-	kernel_sock_shutdown(qp->sk, SHUT_RDWR);
-	sock_release(qp->sk);
+	if (qp->sk) {
+		if (qp_type(qp) == IB_QPT_RC)
+			sk_dst_reset(qp->sk->sk);
+
+		kernel_sock_shutdown(qp->sk, SHUT_RDWR);
+		sock_release(qp->sk);
+	}
 }
 
 /* called when the last reference to the qp is dropped */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/rxe/rxe_queue.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/rxe/rxe_queue.c
@@ -45,12 +45,15 @@
 
 	if (outbuf) {
 		ip = rxe_create_mmap_info(rxe, buf_size, udata, buf);
-		if (!ip)
+		if (IS_ERR(ip)) {
+			err = PTR_ERR(ip);
 			goto err1;
+		}
 
-		err = copy_to_user(outbuf, &ip->info, sizeof(ip->info));
-		if (err)
+		if (copy_to_user(outbuf, &ip->info, sizeof(ip->info))) {
+			err = -EFAULT;
 			goto err2;
+		}
 
 		spin_lock_bh(&rxe->pending_lock);
 		list_add(&ip->pending_mmaps, &rxe->pending_mmaps);
@@ -64,7 +67,7 @@
 err2:
 	kfree(ip);
 err1:
-	return -EINVAL;
+	return err;
 }
 
 inline void rxe_queue_reset(struct rxe_queue *q)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/rxe/rxe_recv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/rxe/rxe_recv.c
@@ -36,21 +36,26 @@
 #include "rxe.h"
 #include "rxe_loc.h"
 
+/* check that QP matches packet opcode type and is in a valid state */
 static int check_type_state(struct rxe_dev *rxe, struct rxe_pkt_info *pkt,
 			    struct rxe_qp *qp)
 {
+	unsigned int pkt_type;
+
 	if (unlikely(!qp->valid))
 		goto err1;
 
+	pkt_type = pkt->opcode & 0xe0;
+
 	switch (qp_type(qp)) {
 	case IB_QPT_RC:
-		if (unlikely((pkt->opcode & IB_OPCODE_RC) != 0)) {
+		if (unlikely(pkt_type != IB_OPCODE_RC)) {
 			pr_warn_ratelimited("bad qp type\n");
 			goto err1;
 		}
 		break;
 	case IB_QPT_UC:
-		if (unlikely(!(pkt->opcode & IB_OPCODE_UC))) {
+		if (unlikely(pkt_type != IB_OPCODE_UC)) {
 			pr_warn_ratelimited("bad qp type\n");
 			goto err1;
 		}
@@ -58,7 +63,7 @@
 	case IB_QPT_UD:
 	case IB_QPT_SMI:
 	case IB_QPT_GSI:
-		if (unlikely(!(pkt->opcode & IB_OPCODE_UD))) {
+		if (unlikely(pkt_type != IB_OPCODE_UD)) {
 			pr_warn_ratelimited("bad qp type\n");
 			goto err1;
 		}
@@ -281,6 +286,8 @@
 	struct rxe_mc_elem *mce;
 	struct rxe_qp *qp;
 	union ib_gid dgid;
+	struct sk_buff *per_qp_skb;
+	struct rxe_pkt_info *per_qp_pkt;
 	int err;
 
 	if (skb->protocol == htons(ETH_P_IP))
@@ -298,7 +305,6 @@
 
 	list_for_each_entry(mce, &mcg->qp_list, qp_list) {
 		qp = mce->qp;
-		pkt = SKB_TO_PKT(skb);
 
 		/* validate qp for incoming packet */
 		err = check_type_state(rxe, pkt, qp);
@@ -309,15 +315,27 @@
 		if (err)
 			continue;
 
-		/* if *not* the last qp in the list
-		 * increase the users of the skb then post to the next qp
+		/* for all but the last qp create a new clone of the
+		 * skb and pass to the qp. If an error occurs in the
+		 * checks for the last qp in the list we need to
+		 * free the skb since it hasn't been passed on to
+		 * rxe_rcv_pkt() which would free it later.
 		 */
-		if (mce->qp_list.next != &mcg->qp_list)
-			skb_get(skb);
+		if (mce->qp_list.next != &mcg->qp_list) {
+			per_qp_skb = skb_clone(skb, GFP_ATOMIC);
+		} else {
+			per_qp_skb = skb;
+			/* show we have consumed the skb */
+			skb = NULL;
+		}
 
-		pkt->qp = qp;
+		if (unlikely(!per_qp_skb))
+			continue;
+
+		per_qp_pkt = SKB_TO_PKT(per_qp_skb);
+		per_qp_pkt->qp = qp;
 		rxe_add_ref(qp);
-		rxe_rcv_pkt(pkt, skb);
+		rxe_rcv_pkt(per_qp_pkt, per_qp_skb);
 	}
 
 	spin_unlock_bh(&mcg->mcg_lock);
@@ -325,15 +343,20 @@
 	rxe_drop_ref(mcg);	/* drop ref from rxe_pool_get_key. */
 
 err1:
+	/* free skb if not consumed */
 	kfree_skb(skb);
 }
 
 static int rxe_match_dgid(struct rxe_dev *rxe, struct sk_buff *skb)
 {
+	struct rxe_pkt_info *pkt = SKB_TO_PKT(skb);
 	const struct ib_gid_attr *gid_attr;
 	union ib_gid dgid;
 	union ib_gid *pdgid;
 
+	if (pkt->mask & RXE_LOOPBACK_MASK)
+		return 0;
+
 	if (skb->protocol == htons(ETH_P_IP)) {
 		ipv6_addr_set_v4mapped(ip_hdr(skb)->daddr,
 				       (struct in6_addr *)&dgid);
@@ -366,7 +389,7 @@
 	if (unlikely(skb->len < pkt->offset + RXE_BTH_BYTES))
 		goto drop;
 
-	if (unlikely(rxe_match_dgid(rxe, skb) < 0)) {
+	if (rxe_match_dgid(rxe, skb) < 0) {
 		pr_warn_ratelimited("failed matching dgid\n");
 		goto drop;
 	}
@@ -389,7 +412,7 @@
 
 	calc_icrc = rxe_icrc_hdr(pkt, skb);
 	calc_icrc = rxe_crc32(rxe, calc_icrc, (u8 *)payload_addr(pkt),
-			      payload_size(pkt));
+			      payload_size(pkt) + bth_pad(pkt));
 	calc_icrc = (__force u32)cpu_to_be32(~calc_icrc);
 	if (unlikely(calc_icrc != pack_icrc)) {
 		if (skb->protocol == htons(ETH_P_IPV6))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/rxe/rxe_req.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/rxe/rxe_req.c
@@ -390,7 +390,7 @@
 	int			solicited;
 	u16			pkey;
 	u32			qp_num;
-	int			ack_req;
+	int			ack_req = 0;
 
 	/* length from start of bth to end of icrc */
 	paylen = rxe_opcode[opcode].length + payload + pad + RXE_ICRC_SIZE;
@@ -426,8 +426,9 @@
 	qp_num = (pkt->mask & RXE_DETH_MASK) ? ibwr->wr.ud.remote_qpn :
 					 qp->attr.dest_qp_num;
 
-	ack_req = ((pkt->mask & RXE_END_MASK) ||
-		(qp->req.noack_pkts++ > RXE_MAX_PKT_PER_ACK));
+	if (qp_type(qp) != IB_QPT_UD && qp_type(qp) != IB_QPT_UC)
+		ack_req = ((pkt->mask & RXE_END_MASK) ||
+			   (qp->req.noack_pkts++ > RXE_MAX_PKT_PER_ACK));
 	if (ack_req)
 		qp->req.noack_pkts = 0;
 
@@ -500,6 +501,12 @@
 			if (err)
 				return err;
 		}
+		if (bth_pad(pkt)) {
+			u8 *pad = payload_addr(pkt) + paylen;
+
+			memset(pad, 0, bth_pad(pkt));
+			crc = rxe_crc32(rxe, crc, pad, bth_pad(pkt));
+		}
 	}
 	p = payload_addr(pkt) + paylen + bth_pad(pkt);
 
@@ -658,7 +665,8 @@
 	}
 
 	if (unlikely(qp_type(qp) == IB_QPT_RC &&
-		     qp->req.psn > (qp->comp.psn + RXE_MAX_UNACKED_PSNS))) {
+		psn_compare(qp->req.psn, (qp->comp.psn +
+				RXE_MAX_UNACKED_PSNS)) > 0)) {
 		qp->req.wait_psn = 1;
 		goto exit;
 	}
@@ -673,7 +681,7 @@
 	opcode = next_opcode(qp, wqe, wqe->wr.opcode);
 	if (unlikely(opcode < 0)) {
 		wqe->status = IB_WC_LOC_QP_OP_ERR;
-		goto exit;
+		goto err;
 	}
 
 	mask = rxe_opcode[opcode].mask;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/rxe/rxe_resp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/rxe/rxe_resp.c
@@ -732,6 +732,13 @@
 	if (err)
 		pr_err("Failed copying memory\n");
 
+	if (bth_pad(&ack_pkt)) {
+		struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
+		u8 *pad = payload_addr(&ack_pkt) + payload;
+
+		memset(pad, 0, bth_pad(&ack_pkt));
+		icrc = rxe_crc32(rxe, icrc, pad, bth_pad(&ack_pkt));
+	}
 	p = payload_addr(&ack_pkt) + payload + bth_pad(&ack_pkt);
 	*p = ~icrc;
 
@@ -986,8 +993,6 @@
 		goto out;
 	}
 
-	rxe_add_ref(qp);
-
 	res = &qp->resp.resources[qp->resp.res_head];
 	free_rd_atomic_resource(qp, res);
 	rxe_advance_resp_resource(qp);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/rxe/rxe_sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/rxe/rxe_sysfs.c
@@ -61,6 +61,11 @@
 	struct net_device *ndev;
 	struct rxe_dev *exists;
 
+	if (!rxe_initialized) {
+		pr_err("Module parameters are not supported, use rdma link add or rxe_cfg\n");
+		return -EAGAIN;
+	}
+
 	len = sanitize_arg(val, intf, sizeof(intf));
 	if (!len) {
 		pr_err("add: invalid interface name\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/rxe/rxe_task.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/rxe/rxe_task.c
@@ -114,13 +114,10 @@
 	task->ret = ret;
 }
 
-int rxe_init_task(void *obj, struct rxe_task *task,
-		  void *arg, int (*func)(void *), char *name)
+int rxe_init_task(struct rxe_task *task, void *arg, int (*func)(void *))
 {
-	task->obj	= obj;
 	task->arg	= arg;
 	task->func	= func;
-	snprintf(task->name, sizeof(task->name), "%s", name);
 	task->destroyed	= false;
 
 	tasklet_init(&task->tasklet, rxe_do_task, (unsigned long)task);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/rxe/rxe_task.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/rxe/rxe_task.h
@@ -46,14 +46,12 @@
  * called again.
  */
 struct rxe_task {
-	void			*obj;
 	struct tasklet_struct	tasklet;
 	int			state;
 	spinlock_t		state_lock; /* spinlock for task state */
 	void			*arg;
 	int			(*func)(void *arg);
 	int			ret;
-	char			name[16];
 	bool			destroyed;
 };
 
@@ -62,8 +60,7 @@
  *	arg  => parameter to pass to fcn
  *	fcn  => function to call until it returns != 0
  */
-int rxe_init_task(void *obj, struct rxe_task *task,
-		  void *arg, int (*func)(void *), char *name);
+int rxe_init_task(struct rxe_task *task, void *arg, int (*func)(void *));
 
 /* cleanup task */
 void rxe_cleanup_task(struct rxe_task *task);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/rxe/rxe_verbs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/rxe/rxe_verbs.c
@@ -679,6 +679,7 @@
 	unsigned int mask;
 	unsigned int length = 0;
 	int i;
+	struct ib_send_wr *next;
 
 	while (wr) {
 		mask = wr_opcode_mask(wr->opcode, qp);
@@ -695,6 +696,8 @@
 			break;
 		}
 
+		next = wr->next;
+
 		length = 0;
 		for (i = 0; i < wr->num_sge; i++)
 			length += wr->sg_list[i].length;
@@ -705,7 +708,7 @@
 			*bad_wr = wr;
 			break;
 		}
-		wr = wr->next;
+		wr = next;
 	}
 
 	rxe_run_task(&qp->req.task, 1);
@@ -1075,7 +1078,7 @@
 	struct rxe_dev *rxe =
 		rdma_device_to_drv_device(device, struct rxe_dev, ib_dev);
 
-	return snprintf(buf, 16, "%s\n", rxe_parent_name(rxe, 1));
+	return scnprintf(buf, PAGE_SIZE, "%s\n", rxe_parent_name(rxe, 1));
 }
 
 static DEVICE_ATTR_RO(parent);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/rxe/rxe_verbs.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/rxe/rxe_verbs.h
@@ -407,7 +407,7 @@
 	struct list_head	pending_mmaps;
 
 	spinlock_t		mmap_offset_lock; /* guard mmap_offset */
-	int			mmap_offset;
+	u64			mmap_offset;
 
 	atomic64_t		stats_counters[RXE_NUM_OF_COUNTERS];
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/siw/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/siw/Kconfig
@@ -1,6 +1,7 @@
 config RDMA_SIW
 	tristate "Software RDMA over TCP/IP (iWARP) driver"
 	depends on INET && INFINIBAND && LIBCRC32C
+	depends on INFINIBAND_VIRT_DMA
 	select DMA_VIRT_OPS
 	help
 	This driver implements the iWARP RDMA transport over
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/siw/siw.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/siw/siw.h
@@ -658,16 +658,11 @@
 	return &qp->orq[qp->orq_get % qp->attrs.orq_size];
 }
 
-static inline struct siw_sqe *orq_get_tail(struct siw_qp *qp)
-{
-	return &qp->orq[qp->orq_put % qp->attrs.orq_size];
-}
-
 static inline struct siw_sqe *orq_get_free(struct siw_qp *qp)
 {
-	struct siw_sqe *orq_e = orq_get_tail(qp);
+	struct siw_sqe *orq_e = &qp->orq[qp->orq_put % qp->attrs.orq_size];
 
-	if (orq_e && READ_ONCE(orq_e->flags) == 0)
+	if (READ_ONCE(orq_e->flags) == 0)
 		return orq_e;
 
 	return NULL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/siw/siw_cm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/siw/siw_cm.c
@@ -725,11 +725,11 @@
 	enum mpa_v2_ctrl mpa_p2p_mode = MPA_V2_RDMA_NO_RTR;
 
 	rv = siw_recv_mpa_rr(cep);
-	if (rv != -EAGAIN)
-		siw_cancel_mpatimer(cep);
 	if (rv)
 		goto out_err;
 
+	siw_cancel_mpatimer(cep);
+
 	rep = &cep->mpa.hdr;
 
 	if (__mpa_rr_revision(rep->params.bits) > MPA_REVISION_2) {
@@ -895,7 +895,8 @@
 	}
 
 out_err:
-	siw_cm_upcall(cep, IW_CM_EVENT_CONNECT_REPLY, -EINVAL);
+	if (rv != -EAGAIN)
+		siw_cm_upcall(cep, IW_CM_EVENT_CONNECT_REPLY, -EINVAL);
 
 	return rv;
 }
@@ -976,14 +977,16 @@
 
 		siw_cep_set_inuse(new_cep);
 		rv = siw_proc_mpareq(new_cep);
-		siw_cep_set_free(new_cep);
-
 		if (rv != -EAGAIN) {
 			siw_cep_put(cep);
 			new_cep->listen_cep = NULL;
-			if (rv)
+			if (rv) {
+				siw_cancel_mpatimer(new_cep);
+				siw_cep_set_free(new_cep);
 				goto error;
+			}
 		}
+		siw_cep_set_free(new_cep);
 	}
 	return;
 
@@ -1103,9 +1106,12 @@
 				/*
 				 * Socket close before MPA request received.
 				 */
-				siw_dbg_cep(cep, "no mpareq: drop listener\n");
-				siw_cep_put(cep->listen_cep);
-				cep->listen_cep = NULL;
+				if (cep->listen_cep) {
+					siw_dbg_cep(cep,
+						"no mpareq: drop listener\n");
+					siw_cep_put(cep->listen_cep);
+					cep->listen_cep = NULL;
+				}
 			}
 		}
 		release_cep = 1;
@@ -1225,11 +1231,14 @@
 	read_lock(&sk->sk_callback_lock);
 
 	cep = sk_to_cep(sk);
-	if (!cep) {
-		WARN_ON(1);
+	if (!cep)
+		goto out;
+
+	siw_dbg_cep(cep, "cep state: %d, socket state %d\n",
+		    cep->state, sk->sk_state);
+
+	if (sk->sk_state != TCP_ESTABLISHED)
 		goto out;
-	}
-	siw_dbg_cep(cep, "state: %d\n", cep->state);
 
 	switch (cep->state) {
 	case SIW_EPSTATE_RDMA_MODE:
@@ -1524,7 +1533,6 @@
 
 		cep->cm_id = NULL;
 		id->rem_ref(id);
-		siw_cep_put(cep);
 
 		qp->cep = NULL;
 		siw_cep_put(cep);
@@ -1784,14 +1792,23 @@
 	return 0;
 }
 
-static int siw_listen_address(struct iw_cm_id *id, int backlog,
-			      struct sockaddr *laddr, int addr_family)
+/*
+ * siw_create_listen - Create resources for a listener's IWCM ID @id
+ *
+ * Starts listen on the socket address id->local_addr.
+ *
+ */
+int siw_create_listen(struct iw_cm_id *id, int backlog)
 {
 	struct socket *s;
 	struct siw_cep *cep = NULL;
 	struct siw_device *sdev = to_siw_dev(id->device);
+	int addr_family = id->local_addr.ss_family;
 	int rv = 0, s_val;
 
+	if (addr_family != AF_INET && addr_family != AF_INET6)
+		return -EAFNOSUPPORT;
+
 	rv = sock_create(addr_family, SOCK_STREAM, IPPROTO_TCP, &s);
 	if (rv < 0)
 		return rv;
@@ -1806,9 +1823,25 @@
 		siw_dbg(id->device, "setsockopt error: %d\n", rv);
 		goto error;
 	}
-	rv = s->ops->bind(s, laddr, addr_family == AF_INET ?
-				    sizeof(struct sockaddr_in) :
-				    sizeof(struct sockaddr_in6));
+	if (addr_family == AF_INET) {
+		struct sockaddr_in *laddr = &to_sockaddr_in(id->local_addr);
+
+		/* For wildcard addr, limit binding to current device only */
+		if (ipv4_is_zeronet(laddr->sin_addr.s_addr))
+			s->sk->sk_bound_dev_if = sdev->netdev->ifindex;
+
+		rv = s->ops->bind(s, (struct sockaddr *)laddr,
+				  sizeof(struct sockaddr_in));
+	} else {
+		struct sockaddr_in6 *laddr = &to_sockaddr_in6(id->local_addr);
+
+		/* For wildcard addr, limit binding to current device only */
+		if (ipv6_addr_any(&laddr->sin6_addr))
+			s->sk->sk_bound_dev_if = sdev->netdev->ifindex;
+
+		rv = s->ops->bind(s, (struct sockaddr *)laddr,
+				  sizeof(struct sockaddr_in6));
+	}
 	if (rv) {
 		siw_dbg(id->device, "socket bind error: %d\n", rv);
 		goto error;
@@ -1867,14 +1900,7 @@
 	list_add_tail(&cep->listenq, (struct list_head *)id->provider_data);
 	cep->state = SIW_EPSTATE_LISTENING;
 
-	if (addr_family == AF_INET)
-		siw_dbg(id->device, "Listen at laddr %pI4 %u\n",
-			&(((struct sockaddr_in *)laddr)->sin_addr),
-			((struct sockaddr_in *)laddr)->sin_port);
-	else
-		siw_dbg(id->device, "Listen at laddr %pI6 %u\n",
-			&(((struct sockaddr_in6 *)laddr)->sin6_addr),
-			((struct sockaddr_in6 *)laddr)->sin6_port);
+	siw_dbg(id->device, "Listen at laddr %pISp\n", &id->local_addr);
 
 	return 0;
 
@@ -1932,114 +1958,6 @@
 	}
 }
 
-/*
- * siw_create_listen - Create resources for a listener's IWCM ID @id
- *
- * Listens on the socket addresses id->local_addr and id->remote_addr.
- *
- * If the listener's @id provides a specific local IP address, at most one
- * listening socket is created and associated with @id.
- *
- * If the listener's @id provides the wildcard (zero) local IP address,
- * a separate listen is performed for each local IP address of the device
- * by creating a listening socket and binding to that local IP address.
- *
- */
-int siw_create_listen(struct iw_cm_id *id, int backlog)
-{
-	struct net_device *dev = to_siw_dev(id->device)->netdev;
-	int rv = 0, listeners = 0;
-
-	siw_dbg(id->device, "backlog %d\n", backlog);
-
-	/*
-	 * For each attached address of the interface, create a
-	 * listening socket, if id->local_addr is the wildcard
-	 * IP address or matches the IP address.
-	 */
-	if (id->local_addr.ss_family == AF_INET) {
-		struct in_device *in_dev = in_dev_get(dev);
-		struct sockaddr_in s_laddr, *s_raddr;
-		const struct in_ifaddr *ifa;
-
-		if (!in_dev) {
-			rv = -ENODEV;
-			goto out;
-		}
-		memcpy(&s_laddr, &id->local_addr, sizeof(s_laddr));
-		s_raddr = (struct sockaddr_in *)&id->remote_addr;
-
-		siw_dbg(id->device,
-			"laddr %pI4:%d, raddr %pI4:%d\n",
-			&s_laddr.sin_addr, ntohs(s_laddr.sin_port),
-			&s_raddr->sin_addr, ntohs(s_raddr->sin_port));
-
-		rtnl_lock();
-		in_dev_for_each_ifa_rtnl(ifa, in_dev) {
-			if (ipv4_is_zeronet(s_laddr.sin_addr.s_addr) ||
-			    s_laddr.sin_addr.s_addr == ifa->ifa_address) {
-				s_laddr.sin_addr.s_addr = ifa->ifa_address;
-
-				rv = siw_listen_address(id, backlog,
-						(struct sockaddr *)&s_laddr,
-						AF_INET);
-				if (!rv)
-					listeners++;
-			}
-		}
-		rtnl_unlock();
-		in_dev_put(in_dev);
-	} else if (id->local_addr.ss_family == AF_INET6) {
-		struct inet6_dev *in6_dev = in6_dev_get(dev);
-		struct inet6_ifaddr *ifp;
-		struct sockaddr_in6 *s_laddr = &to_sockaddr_in6(id->local_addr),
-			*s_raddr = &to_sockaddr_in6(id->remote_addr);
-
-		if (!in6_dev) {
-			rv = -ENODEV;
-			goto out;
-		}
-		siw_dbg(id->device,
-			"laddr %pI6:%d, raddr %pI6:%d\n",
-			&s_laddr->sin6_addr, ntohs(s_laddr->sin6_port),
-			&s_raddr->sin6_addr, ntohs(s_raddr->sin6_port));
-
-		rtnl_lock();
-		list_for_each_entry(ifp, &in6_dev->addr_list, if_list) {
-			if (ifp->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED))
-				continue;
-			if (ipv6_addr_any(&s_laddr->sin6_addr) ||
-			    ipv6_addr_equal(&s_laddr->sin6_addr, &ifp->addr)) {
-				struct sockaddr_in6 bind_addr  = {
-					.sin6_family = AF_INET6,
-					.sin6_port = s_laddr->sin6_port,
-					.sin6_flowinfo = 0,
-					.sin6_addr = ifp->addr,
-					.sin6_scope_id = dev->ifindex };
-
-				rv = siw_listen_address(id, backlog,
-						(struct sockaddr *)&bind_addr,
-						AF_INET6);
-				if (!rv)
-					listeners++;
-			}
-		}
-		rtnl_unlock();
-		in6_dev_put(in6_dev);
-	} else {
-		rv = -EAFNOSUPPORT;
-	}
-out:
-	if (listeners)
-		rv = 0;
-	else if (!rv)
-		rv = -EINVAL;
-
-	siw_dbg(id->device, "%s\n", rv ? "FAIL" : "OK");
-
-	return rv;
-}
-
 int siw_destroy_listen(struct iw_cm_id *id)
 {
 	if (!id->provider_data) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/siw/siw_cq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/siw/siw_cq.c
@@ -56,8 +56,6 @@
 	if (READ_ONCE(cqe->flags) & SIW_WQE_VALID) {
 		memset(wc, 0, sizeof(*wc));
 		wc->wr_id = cqe->id;
-		wc->status = map_cqe_status[cqe->status].ib;
-		wc->opcode = map_wc_opcode[cqe->opcode];
 		wc->byte_len = cqe->bytes;
 
 		/*
@@ -71,10 +69,32 @@
 				wc->wc_flags = IB_WC_WITH_INVALIDATE;
 			}
 			wc->qp = cqe->base_qp;
+			wc->opcode = map_wc_opcode[cqe->opcode];
+			wc->status = map_cqe_status[cqe->status].ib;
 			siw_dbg_cq(cq,
 				   "idx %u, type %d, flags %2x, id 0x%pK\n",
 				   cq->cq_get % cq->num_cqe, cqe->opcode,
 				   cqe->flags, (void *)(uintptr_t)cqe->id);
+		} else {
+			/*
+			 * A malicious user may set invalid opcode or
+			 * status in the user mmapped CQE array.
+			 * Sanity check and correct values in that case
+			 * to avoid out-of-bounds access to global arrays
+			 * for opcode and status mapping.
+			 */
+			u8 opcode = cqe->opcode;
+			u16 status = cqe->status;
+
+			if (opcode >= SIW_NUM_OPCODES) {
+				opcode = 0;
+				status = SIW_WC_GENERAL_ERR;
+			} else if (status >= SIW_NUM_WC_STATUS) {
+				status = SIW_WC_GENERAL_ERR;
+			}
+			wc->opcode = map_wc_opcode[opcode];
+			wc->status = map_cqe_status[status].ib;
+
 		}
 		WRITE_ONCE(cqe->flags, 0);
 		cq->cq_get++;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/siw/siw_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/siw/siw_main.c
@@ -66,12 +66,13 @@
 	static int dev_id = 1;
 	int rv;
 
+	sdev->vendor_part_id = dev_id++;
+
 	rv = ib_register_device(base_dev, name);
 	if (rv) {
 		pr_warn("siw: device registration error %d\n", rv);
 		return rv;
 	}
-	sdev->vendor_part_id = dev_id++;
 
 	siw_dbg(base_dev, "HWaddr=%pM\n", sdev->netdev->dev_addr);
 
@@ -133,7 +134,7 @@
 
 static int siw_init_cpulist(void)
 {
-	int i, num_nodes = num_possible_nodes();
+	int i, num_nodes = nr_node_ids;
 
 	memset(siw_tx_thread, 0, sizeof(siw_tx_thread));
 
@@ -248,24 +249,6 @@
 	return NULL;
 }
 
-static void siw_verbs_sq_flush(struct ib_qp *base_qp)
-{
-	struct siw_qp *qp = to_siw_qp(base_qp);
-
-	down_write(&qp->state_lock);
-	siw_sq_flush(qp);
-	up_write(&qp->state_lock);
-}
-
-static void siw_verbs_rq_flush(struct ib_qp *base_qp)
-{
-	struct siw_qp *qp = to_siw_qp(base_qp);
-
-	down_write(&qp->state_lock);
-	siw_rq_flush(qp);
-	up_write(&qp->state_lock);
-}
-
 static const struct ib_device_ops siw_device_ops = {
 	.owner = THIS_MODULE,
 	.uverbs_abi_ver = SIW_ABI_VERSION,
@@ -284,8 +267,6 @@
 	.destroy_cq = siw_destroy_cq,
 	.destroy_qp = siw_destroy_qp,
 	.destroy_srq = siw_destroy_srq,
-	.drain_rq = siw_verbs_rq_flush,
-	.drain_sq = siw_verbs_sq_flush,
 	.get_dma_mr = siw_get_dma_mr,
 	.get_port_immutable = siw_get_port_immutable,
 	.iw_accept = siw_accept,
@@ -399,6 +380,9 @@
 	base_dev->dev.dma_ops = &dma_virt_ops;
 	base_dev->num_comp_vectors = num_possible_cpus();
 
+	xa_init_flags(&sdev->qp_xa, XA_FLAGS_ALLOC1);
+	xa_init_flags(&sdev->mem_xa, XA_FLAGS_ALLOC1);
+
 	ib_set_device_ops(base_dev, &siw_device_ops);
 	rv = ib_device_set_netdev(base_dev, netdev, 1);
 	if (rv)
@@ -426,9 +410,6 @@
 	sdev->attrs.max_srq_wr = SIW_MAX_SRQ_WR;
 	sdev->attrs.max_srq_sge = SIW_MAX_SGE;
 
-	xa_init_flags(&sdev->qp_xa, XA_FLAGS_ALLOC1);
-	xa_init_flags(&sdev->mem_xa, XA_FLAGS_ALLOC1);
-
 	INIT_LIST_HEAD(&sdev->cep_list);
 	INIT_LIST_HEAD(&sdev->qp_list);
 
@@ -491,9 +472,6 @@
 
 	dev_dbg(&netdev->dev, "siw: event %lu\n", event);
 
-	if (dev_net(netdev) != &init_net)
-		return NOTIFY_OK;
-
 	base_dev = ib_device_get_by_netdev(netdev, RDMA_DRIVER_SIW);
 	if (!base_dev)
 		return NOTIFY_OK;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/siw/siw_mem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/siw/siw_mem.c
@@ -106,8 +106,6 @@
 	mem->perms = rights & IWARP_ACCESS_MASK;
 	kref_init(&mem->ref);
 
-	mr->mem = mem;
-
 	get_random_bytes(&next, 4);
 	next &= 0x00ffffff;
 
@@ -116,6 +114,8 @@
 		kfree(mem);
 		return -ENOMEM;
 	}
+
+	mr->mem = mem;
 	/* Set the STag index part */
 	mem->stag = id << 8;
 	mr->base_mr.lkey = mr->base_mr.rkey = mem->stag;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/siw/siw_qp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/siw/siw_qp.c
@@ -199,26 +199,26 @@
 
 static int siw_qp_readq_init(struct siw_qp *qp, int irq_size, int orq_size)
 {
-	irq_size = roundup_pow_of_two(irq_size);
-	orq_size = roundup_pow_of_two(orq_size);
-
+	if (irq_size) {
+		irq_size = roundup_pow_of_two(irq_size);
+		qp->irq = vzalloc(irq_size * sizeof(struct siw_sqe));
+		if (!qp->irq) {
+			qp->attrs.irq_size = 0;
+			return -ENOMEM;
+		}
+	}
+	if (orq_size) {
+		orq_size = roundup_pow_of_two(orq_size);
+		qp->orq = vzalloc(orq_size * sizeof(struct siw_sqe));
+		if (!qp->orq) {
+			qp->attrs.orq_size = 0;
+			qp->attrs.irq_size = 0;
+			vfree(qp->irq);
+			return -ENOMEM;
+		}
+	}
 	qp->attrs.irq_size = irq_size;
 	qp->attrs.orq_size = orq_size;
-
-	qp->irq = vzalloc(irq_size * sizeof(struct siw_sqe));
-	if (!qp->irq) {
-		siw_dbg_qp(qp, "irq malloc for %d failed\n", irq_size);
-		qp->attrs.irq_size = 0;
-		return -ENOMEM;
-	}
-	qp->orq = vzalloc(orq_size * sizeof(struct siw_sqe));
-	if (!qp->orq) {
-		siw_dbg_qp(qp, "orq malloc for %d failed\n", orq_size);
-		qp->attrs.orq_size = 0;
-		qp->attrs.irq_size = 0;
-		vfree(qp->irq);
-		return -ENOMEM;
-	}
 	siw_dbg_qp(qp, "ORD %d, IRD %d\n", orq_size, irq_size);
 	return 0;
 }
@@ -288,13 +288,14 @@
 	if (ctrl & MPA_V2_RDMA_WRITE_RTR)
 		wqe->sqe.opcode = SIW_OP_WRITE;
 	else if (ctrl & MPA_V2_RDMA_READ_RTR) {
-		struct siw_sqe *rreq;
+		struct siw_sqe *rreq = NULL;
 
 		wqe->sqe.opcode = SIW_OP_READ;
 
 		spin_lock(&qp->orq_lock);
 
-		rreq = orq_get_free(qp);
+		if (qp->attrs.orq_size)
+			rreq = orq_get_free(qp);
 		if (rreq) {
 			siw_read_to_orq(rreq, &wqe->sqe);
 			qp->orq_put++;
@@ -877,135 +878,88 @@
 	rreq->num_sge = 1;
 }
 
-/*
- * Must be called with SQ locked.
- * To avoid complete SQ starvation by constant inbound READ requests,
- * the active IRQ will not be served after qp->irq_burst, if the
- * SQ has pending work.
- */
-int siw_activate_tx(struct siw_qp *qp)
+static int siw_activate_tx_from_sq(struct siw_qp *qp)
 {
-	struct siw_sqe *irqe, *sqe;
+	struct siw_sqe *sqe;
 	struct siw_wqe *wqe = tx_wqe(qp);
 	int rv = 1;
 
-	irqe = &qp->irq[qp->irq_get % qp->attrs.irq_size];
-
-	if (irqe->flags & SIW_WQE_VALID) {
-		sqe = sq_get_next(qp);
-
-		/*
-		 * Avoid local WQE processing starvation in case
-		 * of constant inbound READ request stream
-		 */
-		if (sqe && ++qp->irq_burst >= SIW_IRQ_MAXBURST_SQ_ACTIVE) {
-			qp->irq_burst = 0;
-			goto skip_irq;
-		}
-		memset(wqe->mem, 0, sizeof(*wqe->mem) * SIW_MAX_SGE);
-		wqe->wr_status = SIW_WR_QUEUED;
-
-		/* start READ RESPONSE */
-		wqe->sqe.opcode = SIW_OP_READ_RESPONSE;
-		wqe->sqe.flags = 0;
-		if (irqe->num_sge) {
-			wqe->sqe.num_sge = 1;
-			wqe->sqe.sge[0].length = irqe->sge[0].length;
-			wqe->sqe.sge[0].laddr = irqe->sge[0].laddr;
-			wqe->sqe.sge[0].lkey = irqe->sge[0].lkey;
-		} else {
-			wqe->sqe.num_sge = 0;
-		}
-
-		/* Retain original RREQ's message sequence number for
-		 * potential error reporting cases.
-		 */
-		wqe->sqe.sge[1].length = irqe->sge[1].length;
-
-		wqe->sqe.rkey = irqe->rkey;
-		wqe->sqe.raddr = irqe->raddr;
+	sqe = sq_get_next(qp);
+	if (!sqe)
+		return 0;
 
-		wqe->processed = 0;
-		qp->irq_get++;
+	memset(wqe->mem, 0, sizeof(*wqe->mem) * SIW_MAX_SGE);
+	wqe->wr_status = SIW_WR_QUEUED;
 
-		/* mark current IRQ entry free */
-		smp_store_mb(irqe->flags, 0);
+	/* First copy SQE to kernel private memory */
+	memcpy(&wqe->sqe, sqe, sizeof(*sqe));
 
+	if (wqe->sqe.opcode >= SIW_NUM_OPCODES) {
+		rv = -EINVAL;
 		goto out;
 	}
-	sqe = sq_get_next(qp);
-	if (sqe) {
-skip_irq:
-		memset(wqe->mem, 0, sizeof(*wqe->mem) * SIW_MAX_SGE);
-		wqe->wr_status = SIW_WR_QUEUED;
-
-		/* First copy SQE to kernel private memory */
-		memcpy(&wqe->sqe, sqe, sizeof(*sqe));
-
-		if (wqe->sqe.opcode >= SIW_NUM_OPCODES) {
+	if (wqe->sqe.flags & SIW_WQE_INLINE) {
+		if (wqe->sqe.opcode != SIW_OP_SEND &&
+		    wqe->sqe.opcode != SIW_OP_WRITE) {
 			rv = -EINVAL;
 			goto out;
 		}
-		if (wqe->sqe.flags & SIW_WQE_INLINE) {
-			if (wqe->sqe.opcode != SIW_OP_SEND &&
-			    wqe->sqe.opcode != SIW_OP_WRITE) {
-				rv = -EINVAL;
-				goto out;
-			}
-			if (wqe->sqe.sge[0].length > SIW_MAX_INLINE) {
-				rv = -EINVAL;
-				goto out;
-			}
-			wqe->sqe.sge[0].laddr = (uintptr_t)&wqe->sqe.sge[1];
-			wqe->sqe.sge[0].lkey = 0;
-			wqe->sqe.num_sge = 1;
-		}
-		if (wqe->sqe.flags & SIW_WQE_READ_FENCE) {
-			/* A READ cannot be fenced */
-			if (unlikely(wqe->sqe.opcode == SIW_OP_READ ||
-				     wqe->sqe.opcode ==
-					     SIW_OP_READ_LOCAL_INV)) {
-				siw_dbg_qp(qp, "cannot fence read\n");
-				rv = -EINVAL;
-				goto out;
-			}
-			spin_lock(&qp->orq_lock);
+		if (wqe->sqe.sge[0].length > SIW_MAX_INLINE) {
+			rv = -EINVAL;
+			goto out;
+		}
+		wqe->sqe.sge[0].laddr = (uintptr_t)&wqe->sqe.sge[1];
+		wqe->sqe.sge[0].lkey = 0;
+		wqe->sqe.num_sge = 1;
+	}
+	if (wqe->sqe.flags & SIW_WQE_READ_FENCE) {
+		/* A READ cannot be fenced */
+		if (unlikely(wqe->sqe.opcode == SIW_OP_READ ||
+			     wqe->sqe.opcode ==
+				     SIW_OP_READ_LOCAL_INV)) {
+			siw_dbg_qp(qp, "cannot fence read\n");
+			rv = -EINVAL;
+			goto out;
+		}
+		spin_lock(&qp->orq_lock);
 
-			if (!siw_orq_empty(qp)) {
-				qp->tx_ctx.orq_fence = 1;
-				rv = 0;
-			}
-			spin_unlock(&qp->orq_lock);
+		if (qp->attrs.orq_size && !siw_orq_empty(qp)) {
+			qp->tx_ctx.orq_fence = 1;
+			rv = 0;
+		}
+		spin_unlock(&qp->orq_lock);
 
-		} else if (wqe->sqe.opcode == SIW_OP_READ ||
-			   wqe->sqe.opcode == SIW_OP_READ_LOCAL_INV) {
-			struct siw_sqe *rreq;
+	} else if (wqe->sqe.opcode == SIW_OP_READ ||
+		   wqe->sqe.opcode == SIW_OP_READ_LOCAL_INV) {
+		struct siw_sqe *rreq;
 
-			wqe->sqe.num_sge = 1;
+		if (unlikely(!qp->attrs.orq_size)) {
+			/* We negotiated not to send READ req's */
+			rv = -EINVAL;
+			goto out;
+		}
+		wqe->sqe.num_sge = 1;
 
-			spin_lock(&qp->orq_lock);
+		spin_lock(&qp->orq_lock);
 
-			rreq = orq_get_free(qp);
-			if (rreq) {
-				/*
-				 * Make an immediate copy in ORQ to be ready
-				 * to process loopback READ reply
-				 */
-				siw_read_to_orq(rreq, &wqe->sqe);
-				qp->orq_put++;
-			} else {
-				qp->tx_ctx.orq_fence = 1;
-				rv = 0;
-			}
-			spin_unlock(&qp->orq_lock);
+		rreq = orq_get_free(qp);
+		if (rreq) {
+			/*
+			 * Make an immediate copy in ORQ to be ready
+			 * to process loopback READ reply
+			 */
+			siw_read_to_orq(rreq, &wqe->sqe);
+			qp->orq_put++;
+		} else {
+			qp->tx_ctx.orq_fence = 1;
+			rv = 0;
 		}
-
-		/* Clear SQE, can be re-used by application */
-		smp_store_mb(sqe->flags, 0);
-		qp->sq_get++;
-	} else {
-		rv = 0;
+		spin_unlock(&qp->orq_lock);
 	}
+
+	/* Clear SQE, can be re-used by application */
+	smp_store_mb(sqe->flags, 0);
+	qp->sq_get++;
 out:
 	if (unlikely(rv < 0)) {
 		siw_dbg_qp(qp, "error %d\n", rv);
@@ -1015,6 +969,65 @@
 }
 
 /*
+ * Must be called with SQ locked.
+ * To avoid complete SQ starvation by constant inbound READ requests,
+ * the active IRQ will not be served after qp->irq_burst, if the
+ * SQ has pending work.
+ */
+int siw_activate_tx(struct siw_qp *qp)
+{
+	struct siw_sqe *irqe;
+	struct siw_wqe *wqe = tx_wqe(qp);
+
+	if (!qp->attrs.irq_size)
+		return siw_activate_tx_from_sq(qp);
+
+	irqe = &qp->irq[qp->irq_get % qp->attrs.irq_size];
+
+	if (!(irqe->flags & SIW_WQE_VALID))
+		return siw_activate_tx_from_sq(qp);
+
+	/*
+	 * Avoid local WQE processing starvation in case
+	 * of constant inbound READ request stream
+	 */
+	if (sq_get_next(qp) && ++qp->irq_burst >= SIW_IRQ_MAXBURST_SQ_ACTIVE) {
+		qp->irq_burst = 0;
+		return siw_activate_tx_from_sq(qp);
+	}
+	memset(wqe->mem, 0, sizeof(*wqe->mem) * SIW_MAX_SGE);
+	wqe->wr_status = SIW_WR_QUEUED;
+
+	/* start READ RESPONSE */
+	wqe->sqe.opcode = SIW_OP_READ_RESPONSE;
+	wqe->sqe.flags = 0;
+	if (irqe->num_sge) {
+		wqe->sqe.num_sge = 1;
+		wqe->sqe.sge[0].length = irqe->sge[0].length;
+		wqe->sqe.sge[0].laddr = irqe->sge[0].laddr;
+		wqe->sqe.sge[0].lkey = irqe->sge[0].lkey;
+	} else {
+		wqe->sqe.num_sge = 0;
+	}
+
+	/* Retain original RREQ's message sequence number for
+	 * potential error reporting cases.
+	 */
+	wqe->sqe.sge[1].length = irqe->sge[1].length;
+
+	wqe->sqe.rkey = irqe->rkey;
+	wqe->sqe.raddr = irqe->raddr;
+
+	wqe->processed = 0;
+	qp->irq_get++;
+
+	/* mark current IRQ entry free */
+	smp_store_mb(irqe->flags, 0);
+
+	return 1;
+}
+
+/*
  * Check if current CQ state qualifies for calling CQ completion
  * handler. Must be called with CQ lock held.
  */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/siw/siw_qp_rx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/siw/siw_qp_rx.c
@@ -139,7 +139,8 @@
 			break;
 
 		bytes = min(bytes, len);
-		if (siw_rx_kva(srx, (void *)buf_addr, bytes) == bytes) {
+		if (siw_rx_kva(srx, (void *)(uintptr_t)buf_addr, bytes) ==
+		    bytes) {
 			copied += bytes;
 			offset += bytes;
 			len -= bytes;
@@ -679,6 +680,10 @@
 	}
 	spin_lock_irqsave(&qp->sq_lock, flags);
 
+	if (unlikely(!qp->attrs.irq_size)) {
+		run_sq = 0;
+		goto error_irq;
+	}
 	if (tx_work->wr_status == SIW_WR_IDLE) {
 		/*
 		 * immediately schedule READ response w/o
@@ -711,8 +716,9 @@
 		/* RRESP now valid as current TX wqe or placed into IRQ */
 		smp_store_mb(resp->flags, SIW_WQE_VALID);
 	} else {
-		pr_warn("siw: [QP %u]: irq %d exceeded %d\n", qp_id(qp),
-			qp->irq_put % qp->attrs.irq_size, qp->attrs.irq_size);
+error_irq:
+		pr_warn("siw: [QP %u]: IRQ exceeded or null, size %d\n",
+			qp_id(qp), qp->attrs.irq_size);
 
 		siw_init_terminate(qp, TERM_ERROR_LAYER_RDMAP,
 				   RDMAP_ETYPE_REMOTE_OPERATION,
@@ -739,6 +745,9 @@
 	struct siw_sqe *orqe;
 	struct siw_wqe *wqe = NULL;
 
+	if (unlikely(!qp->attrs.orq_size))
+		return -EPROTO;
+
 	/* make sure ORQ indices are current */
 	smp_mb();
 
@@ -795,8 +804,8 @@
 		 */
 		rv = siw_orqe_start_rx(qp);
 		if (rv) {
-			pr_warn("siw: [QP %u]: ORQ empty at idx %d\n",
-				qp_id(qp), qp->orq_get % qp->attrs.orq_size);
+			pr_warn("siw: [QP %u]: ORQ empty, size %d\n",
+				qp_id(qp), qp->attrs.orq_size);
 			goto error_term;
 		}
 		rv = siw_rresp_check_ntoh(srx, frx);
@@ -952,27 +961,28 @@
 static int siw_get_trailer(struct siw_qp *qp, struct siw_rx_stream *srx)
 {
 	struct sk_buff *skb = srx->skb;
+	int avail = min(srx->skb_new, srx->fpdu_part_rem);
 	u8 *tbuf = (u8 *)&srx->trailer.crc - srx->pad;
 	__wsum crc_in, crc_own = 0;
 
 	siw_dbg_qp(qp, "expected %d, available %d, pad %u\n",
 		   srx->fpdu_part_rem, srx->skb_new, srx->pad);
 
-	if (srx->skb_new < srx->fpdu_part_rem)
-		return -EAGAIN;
-
-	skb_copy_bits(skb, srx->skb_offset, tbuf, srx->fpdu_part_rem);
+	skb_copy_bits(skb, srx->skb_offset, tbuf, avail);
 
-	if (srx->mpa_crc_hd && srx->pad)
-		crypto_shash_update(srx->mpa_crc_hd, tbuf, srx->pad);
+	srx->skb_new -= avail;
+	srx->skb_offset += avail;
+	srx->skb_copied += avail;
+	srx->fpdu_part_rem -= avail;
 
-	srx->skb_new -= srx->fpdu_part_rem;
-	srx->skb_offset += srx->fpdu_part_rem;
-	srx->skb_copied += srx->fpdu_part_rem;
+	if (srx->fpdu_part_rem)
+		return -EAGAIN;
 
 	if (!srx->mpa_crc_hd)
 		return 0;
 
+	if (srx->pad)
+		crypto_shash_update(srx->mpa_crc_hd, tbuf, srx->pad);
 	/*
 	 * CRC32 is computed, transmitted and received directly in NBO,
 	 * so there's never a reason to convert byte order.
@@ -1074,10 +1084,9 @@
 	 * completely received.
 	 */
 	if (iwarp_pktinfo[opcode].hdr_len > sizeof(struct iwarp_ctrl_tagged)) {
-		bytes = iwarp_pktinfo[opcode].hdr_len - MIN_DDP_HDR;
+		int hdrlen = iwarp_pktinfo[opcode].hdr_len;
 
-		if (srx->skb_new < bytes)
-			return -EAGAIN;
+		bytes = min_t(int, hdrlen - MIN_DDP_HDR, srx->skb_new);
 
 		skb_copy_bits(skb, srx->skb_offset,
 			      (char *)c_hdr + srx->fpdu_part_rcvd, bytes);
@@ -1087,6 +1096,9 @@
 		srx->skb_new -= bytes;
 		srx->skb_offset += bytes;
 		srx->skb_copied += bytes;
+
+		if (srx->fpdu_part_rcvd < hdrlen)
+			return -EAGAIN;
 	}
 
 	/*
@@ -1144,11 +1156,12 @@
 
 	spin_lock_irqsave(&qp->orq_lock, flags);
 
-	rreq = orq_get_current(qp);
-
 	/* free current orq entry */
+	rreq = orq_get_current(qp);
 	WRITE_ONCE(rreq->flags, 0);
 
+	qp->orq_get++;
+
 	if (qp->tx_ctx.orq_fence) {
 		if (unlikely(tx_waiting->wr_status != SIW_WR_QUEUED)) {
 			pr_warn("siw: [QP %u]: fence resume: bad status %d\n",
@@ -1156,10 +1169,12 @@
 			rv = -EPROTO;
 			goto out;
 		}
-		/* resume SQ processing */
+		/* resume SQ processing, if possible */
 		if (tx_waiting->sqe.opcode == SIW_OP_READ ||
 		    tx_waiting->sqe.opcode == SIW_OP_READ_LOCAL_INV) {
-			rreq = orq_get_tail(qp);
+
+			/* SQ processing was stopped because of a full ORQ */
+			rreq = orq_get_free(qp);
 			if (unlikely(!rreq)) {
 				pr_warn("siw: [QP %u]: no ORQE\n", qp_id(qp));
 				rv = -EPROTO;
@@ -1172,15 +1187,14 @@
 			resume_tx = 1;
 
 		} else if (siw_orq_empty(qp)) {
+			/*
+			 * SQ processing was stopped by fenced work request.
+			 * Resume since all previous Read's are now completed.
+			 */
 			qp->tx_ctx.orq_fence = 0;
 			resume_tx = 1;
-		} else {
-			pr_warn("siw: [QP %u]: fence resume: orq idx: %d:%d\n",
-				qp_id(qp), qp->orq_get, qp->orq_put);
-			rv = -EPROTO;
 		}
 	}
-	qp->orq_get++;
 out:
 	spin_unlock_irqrestore(&qp->orq_lock, flags);
 
@@ -1289,11 +1303,13 @@
 					      wc_status);
 		siw_wqe_put_mem(wqe, SIW_OP_READ);
 
-		if (!error)
+		if (!error) {
 			rv = siw_check_tx_fence(qp);
-		else
-			/* Disable current ORQ eleement */
-			WRITE_ONCE(orq_get_current(qp)->flags, 0);
+		} else {
+			/* Disable current ORQ element */
+			if (qp->attrs.orq_size)
+				WRITE_ONCE(orq_get_current(qp)->flags, 0);
+		}
 		break;
 
 	case RDMAP_RDMA_READ_REQ:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/siw/siw_qp_tx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/siw/siw_qp_tx.c
@@ -29,7 +29,7 @@
 	dma_addr_t paddr = siw_pbl_get_buffer(pbl, offset, NULL, idx);
 
 	if (paddr)
-		return virt_to_page(paddr);
+		return virt_to_page((void *)(uintptr_t)paddr);
 
 	return NULL;
 }
@@ -523,13 +523,23 @@
 					kunmap(p);
 				}
 			} else {
-				u64 va = sge->laddr + sge_off;
+				/*
+				 * Cast to an uintptr_t to preserve all 64 bits
+				 * in sge->laddr.
+				 */
+				uintptr_t va = (uintptr_t)(sge->laddr + sge_off);
 
-				page_array[seg] = virt_to_page(va & PAGE_MASK);
+				/*
+				 * virt_to_page() takes a (void *) pointer
+				 * so cast to a (void *) meaning it will be 64
+				 * bits on a 64 bit platform and 32 bits on a
+				 * 32 bit platform.
+				 */
+				page_array[seg] = virt_to_page((void *)(va & PAGE_MASK));
 				if (do_crc)
 					crypto_shash_update(
 						c_tx->mpa_crc_hd,
-						(void *)(uintptr_t)va,
+						(void *)va,
 						plen);
 			}
 
@@ -538,7 +548,7 @@
 			data_len -= plen;
 			fp_off = 0;
 
-			if (++seg > (int)MAX_ARRAY) {
+			if (++seg >= (int)MAX_ARRAY) {
 				siw_dbg_qp(tx_qp(c_tx), "to many fragments\n");
 				siw_unmap_pages(page_array, kmap_mask);
 				wqe->processed -= c_tx->bytes_unsent;
@@ -920,20 +930,27 @@
 {
 	struct ib_mr *base_mr = (struct ib_mr *)(uintptr_t)sqe->base_mr;
 	struct siw_device *sdev = to_siw_dev(pd->device);
-	struct siw_mem *mem = siw_mem_id2obj(sdev, sqe->rkey  >> 8);
+	struct siw_mem *mem;
 	int rv = 0;
 
 	siw_dbg_pd(pd, "STag 0x%08x\n", sqe->rkey);
 
-	if (unlikely(!mem || !base_mr)) {
+	if (unlikely(!base_mr)) {
 		pr_warn("siw: fastreg: STag 0x%08x unknown\n", sqe->rkey);
 		return -EINVAL;
 	}
+
 	if (unlikely(base_mr->rkey >> 8 != sqe->rkey  >> 8)) {
 		pr_warn("siw: fastreg: STag 0x%08x: bad MR\n", sqe->rkey);
-		rv = -EINVAL;
-		goto out;
+		return -EINVAL;
+	}
+
+	mem = siw_mem_id2obj(sdev, sqe->rkey  >> 8);
+	if (unlikely(!mem)) {
+		pr_warn("siw: fastreg: STag 0x%08x unknown\n", sqe->rkey);
+		return -EINVAL;
 	}
+
 	if (unlikely(mem->pd != pd)) {
 		pr_warn("siw: fastreg: PD mismatch\n");
 		rv = -EINVAL;
@@ -1100,8 +1117,8 @@
 		/*
 		 * RREQ may have already been completed by inbound RRESP!
 		 */
-		if (tx_type == SIW_OP_READ ||
-		    tx_type == SIW_OP_READ_LOCAL_INV) {
+		if ((tx_type == SIW_OP_READ ||
+		     tx_type == SIW_OP_READ_LOCAL_INV) && qp->attrs.orq_size) {
 			/* Cleanup pending entry in ORQ */
 			qp->orq_put--;
 			qp->orq[qp->orq_put % qp->attrs.orq_size].flags = 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/sw/siw/siw_verbs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/sw/siw/siw_verbs.c
@@ -314,7 +314,6 @@
 	struct siw_ucontext *uctx =
 		rdma_udata_to_drv_context(udata, struct siw_ucontext,
 					  base_ucontext);
-	struct siw_cq *scq = NULL, *rcq = NULL;
 	unsigned long flags;
 	int num_sqe, num_rqe, rv = 0;
 
@@ -353,10 +352,8 @@
 		rv = -EINVAL;
 		goto err_out;
 	}
-	scq = to_siw_cq(attrs->send_cq);
-	rcq = to_siw_cq(attrs->recv_cq);
 
-	if (!scq || (!rcq && !attrs->srq)) {
+	if (!attrs->send_cq || (!attrs->recv_cq && !attrs->srq)) {
 		siw_dbg(base_dev, "send CQ or receive CQ invalid\n");
 		rv = -EINVAL;
 		goto err_out;
@@ -387,13 +384,23 @@
 	if (rv)
 		goto err_out;
 
+	num_sqe = attrs->cap.max_send_wr;
+	num_rqe = attrs->cap.max_recv_wr;
+
 	/* All queue indices are derived from modulo operations
 	 * on a free running 'get' (consumer) and 'put' (producer)
 	 * unsigned counter. Having queue sizes at power of two
 	 * avoids handling counter wrap around.
 	 */
-	num_sqe = roundup_pow_of_two(attrs->cap.max_send_wr);
-	num_rqe = roundup_pow_of_two(attrs->cap.max_recv_wr);
+	if (num_sqe)
+		num_sqe = roundup_pow_of_two(num_sqe);
+	else {
+		/* Zero sized SQ is not supported */
+		rv = -EINVAL;
+		goto err_out_xa;
+	}
+	if (num_rqe)
+		num_rqe = roundup_pow_of_two(num_rqe);
 
 	if (qp->kernel_verbs)
 		qp->sendq = vzalloc(num_sqe * sizeof(struct siw_sqe));
@@ -401,7 +408,6 @@
 		qp->sendq = vmalloc_user(num_sqe * sizeof(struct siw_sqe));
 
 	if (qp->sendq == NULL) {
-		siw_dbg(base_dev, "SQ size %d alloc failed\n", num_sqe);
 		rv = -ENOMEM;
 		goto err_out_xa;
 	}
@@ -414,8 +420,8 @@
 		}
 	}
 	qp->pd = pd;
-	qp->scq = scq;
-	qp->rcq = rcq;
+	qp->scq = to_siw_cq(attrs->send_cq);
+	qp->rcq = to_siw_cq(attrs->recv_cq);
 
 	if (attrs->srq) {
 		/*
@@ -434,7 +440,6 @@
 				vmalloc_user(num_rqe * sizeof(struct siw_rqe));
 
 		if (qp->recvq == NULL) {
-			siw_dbg(base_dev, "RQ size %d alloc failed\n", num_rqe);
 			rv = -ENOMEM;
 			goto err_out_xa;
 		}
@@ -685,6 +690,79 @@
 	return bytes;
 }
 
+/* Complete SQ WR's without processing */
+static int siw_sq_flush_wr(struct siw_qp *qp, const struct ib_send_wr *wr,
+			   const struct ib_send_wr **bad_wr)
+{
+	int rv = 0;
+
+	while (wr) {
+		struct siw_sqe sqe = {};
+
+		switch (wr->opcode) {
+		case IB_WR_RDMA_WRITE:
+			sqe.opcode = SIW_OP_WRITE;
+			break;
+		case IB_WR_RDMA_READ:
+			sqe.opcode = SIW_OP_READ;
+			break;
+		case IB_WR_RDMA_READ_WITH_INV:
+			sqe.opcode = SIW_OP_READ_LOCAL_INV;
+			break;
+		case IB_WR_SEND:
+			sqe.opcode = SIW_OP_SEND;
+			break;
+		case IB_WR_SEND_WITH_IMM:
+			sqe.opcode = SIW_OP_SEND_WITH_IMM;
+			break;
+		case IB_WR_SEND_WITH_INV:
+			sqe.opcode = SIW_OP_SEND_REMOTE_INV;
+			break;
+		case IB_WR_LOCAL_INV:
+			sqe.opcode = SIW_OP_INVAL_STAG;
+			break;
+		case IB_WR_REG_MR:
+			sqe.opcode = SIW_OP_REG_MR;
+			break;
+		default:
+			rv = -EINVAL;
+			break;
+		}
+		if (!rv) {
+			sqe.id = wr->wr_id;
+			rv = siw_sqe_complete(qp, &sqe, 0,
+					      SIW_WC_WR_FLUSH_ERR);
+		}
+		if (rv) {
+			if (bad_wr)
+				*bad_wr = wr;
+			break;
+		}
+		wr = wr->next;
+	}
+	return rv;
+}
+
+/* Complete RQ WR's without processing */
+static int siw_rq_flush_wr(struct siw_qp *qp, const struct ib_recv_wr *wr,
+			   const struct ib_recv_wr **bad_wr)
+{
+	struct siw_rqe rqe = {};
+	int rv = 0;
+
+	while (wr) {
+		rqe.id = wr->wr_id;
+		rv = siw_rqe_complete(qp, &rqe, 0, 0, SIW_WC_WR_FLUSH_ERR);
+		if (rv) {
+			if (bad_wr)
+				*bad_wr = wr;
+			break;
+		}
+		wr = wr->next;
+	}
+	return rv;
+}
+
 /*
  * siw_post_send()
  *
@@ -703,26 +781,54 @@
 	unsigned long flags;
 	int rv = 0;
 
+	if (wr && !qp->kernel_verbs) {
+		siw_dbg_qp(qp, "wr must be empty for user mapped sq\n");
+		*bad_wr = wr;
+		return -EINVAL;
+	}
+
 	/*
 	 * Try to acquire QP state lock. Must be non-blocking
 	 * to accommodate kernel clients needs.
 	 */
 	if (!down_read_trylock(&qp->state_lock)) {
-		*bad_wr = wr;
-		siw_dbg_qp(qp, "QP locked, state %d\n", qp->attrs.state);
-		return -ENOTCONN;
+		if (qp->attrs.state == SIW_QP_STATE_ERROR) {
+			/*
+			 * ERROR state is final, so we can be sure
+			 * this state will not change as long as the QP
+			 * exists.
+			 *
+			 * This handles an ib_drain_sq() call with
+			 * a concurrent request to set the QP state
+			 * to ERROR.
+			 */
+			rv = siw_sq_flush_wr(qp, wr, bad_wr);
+		} else {
+			siw_dbg_qp(qp, "QP locked, state %d\n",
+				   qp->attrs.state);
+			*bad_wr = wr;
+			rv = -ENOTCONN;
+		}
+		return rv;
 	}
 	if (unlikely(qp->attrs.state != SIW_QP_STATE_RTS)) {
+		if (qp->attrs.state == SIW_QP_STATE_ERROR) {
+			/*
+			 * Immediately flush this WR to CQ, if QP
+			 * is in ERROR state. SQ is guaranteed to
+			 * be empty, so WR complets in-order.
+			 *
+			 * Typically triggered by ib_drain_sq().
+			 */
+			rv = siw_sq_flush_wr(qp, wr, bad_wr);
+		} else {
+			siw_dbg_qp(qp, "QP out of state %d\n",
+				   qp->attrs.state);
+			*bad_wr = wr;
+			rv = -ENOTCONN;
+		}
 		up_read(&qp->state_lock);
-		*bad_wr = wr;
-		siw_dbg_qp(qp, "QP out of state %d\n", qp->attrs.state);
-		return -ENOTCONN;
-	}
-	if (wr && !qp->kernel_verbs) {
-		siw_dbg_qp(qp, "wr must be empty for user mapped sq\n");
-		up_read(&qp->state_lock);
-		*bad_wr = wr;
-		return -EINVAL;
+		return rv;
 	}
 	spin_lock_irqsave(&qp->sq_lock, flags);
 
@@ -913,28 +1019,58 @@
 	unsigned long flags;
 	int rv = 0;
 
-	if (qp->srq) {
+	if (qp->srq || qp->attrs.rq_size == 0) {
 		*bad_wr = wr;
-		return -EOPNOTSUPP; /* what else from errno.h? */
+		return -EINVAL;
+	}
+	if (!qp->kernel_verbs) {
+		siw_dbg_qp(qp, "no kernel post_recv for user mapped sq\n");
+		*bad_wr = wr;
+		return -EINVAL;
 	}
+
 	/*
 	 * Try to acquire QP state lock. Must be non-blocking
 	 * to accommodate kernel clients needs.
 	 */
 	if (!down_read_trylock(&qp->state_lock)) {
-		*bad_wr = wr;
-		return -ENOTCONN;
-	}
-	if (!qp->kernel_verbs) {
-		siw_dbg_qp(qp, "no kernel post_recv for user mapped sq\n");
-		up_read(&qp->state_lock);
-		*bad_wr = wr;
-		return -EINVAL;
+		if (qp->attrs.state == SIW_QP_STATE_ERROR) {
+			/*
+			 * ERROR state is final, so we can be sure
+			 * this state will not change as long as the QP
+			 * exists.
+			 *
+			 * This handles an ib_drain_rq() call with
+			 * a concurrent request to set the QP state
+			 * to ERROR.
+			 */
+			rv = siw_rq_flush_wr(qp, wr, bad_wr);
+		} else {
+			siw_dbg_qp(qp, "QP locked, state %d\n",
+				   qp->attrs.state);
+			*bad_wr = wr;
+			rv = -ENOTCONN;
+		}
+		return rv;
 	}
 	if (qp->attrs.state > SIW_QP_STATE_RTS) {
+		if (qp->attrs.state == SIW_QP_STATE_ERROR) {
+			/*
+			 * Immediately flush this WR to CQ, if QP
+			 * is in ERROR state. RQ is guaranteed to
+			 * be empty, so WR complets in-order.
+			 *
+			 * Typically triggered by ib_drain_rq().
+			 */
+			rv = siw_rq_flush_wr(qp, wr, bad_wr);
+		} else {
+			siw_dbg_qp(qp, "QP out of state %d\n",
+				   qp->attrs.state);
+			*bad_wr = wr;
+			rv = -ENOTCONN;
+		}
 		up_read(&qp->state_lock);
-		*bad_wr = wr;
-		return -EINVAL;
+		return rv;
 	}
 	/*
 	 * Serialize potentially multiple producers.
@@ -1373,7 +1509,7 @@
 
 	if (pbl->max_buf < num_sle) {
 		siw_dbg_mem(mem, "too many SGE's: %d > %d\n",
-			    mem->pbl->max_buf, num_sle);
+			    num_sle, pbl->max_buf);
 		return -ENOMEM;
 	}
 	for_each_sg(sl, slp, num_sle, i) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/ulp/ipoib/ipoib.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -377,8 +377,12 @@
 	struct ipoib_rx_buf *rx_ring;
 
 	struct ipoib_tx_buf *tx_ring;
+	/* cyclic ring variables for managing tx_ring, for UD only */
 	unsigned int	     tx_head;
 	unsigned int	     tx_tail;
+	/* cyclic ring variables for counting overall outstanding send WRs */
+	unsigned int	     global_tx_head;
+	unsigned int	     global_tx_tail;
 	struct ib_sge	     tx_sge[MAX_SKB_FRAGS + 1];
 	struct ib_ud_wr      tx_wr;
 	struct ib_wc	     send_wc[MAX_SEND_CQE];
@@ -511,7 +515,7 @@
 
 int ipoib_ib_dev_open_default(struct net_device *dev);
 int ipoib_ib_dev_open(struct net_device *dev);
-int ipoib_ib_dev_stop(struct net_device *dev);
+void ipoib_ib_dev_stop(struct net_device *dev);
 void ipoib_ib_dev_up(struct net_device *dev);
 void ipoib_ib_dev_down(struct net_device *dev);
 int ipoib_ib_dev_stop_default(struct net_device *dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -756,7 +756,8 @@
 		return;
 	}
 
-	if ((priv->tx_head - priv->tx_tail) == ipoib_sendq_size - 1) {
+	if ((priv->global_tx_head - priv->global_tx_tail) ==
+	    ipoib_sendq_size - 1) {
 		ipoib_dbg(priv, "TX ring 0x%x full, stopping kernel net queue\n",
 			  tx->qp->qp_num);
 		netif_stop_queue(dev);
@@ -786,7 +787,7 @@
 	} else {
 		netif_trans_update(dev);
 		++tx->tx_head;
-		++priv->tx_head;
+		++priv->global_tx_head;
 	}
 }
 
@@ -820,10 +821,11 @@
 	netif_tx_lock(dev);
 
 	++tx->tx_tail;
-	++priv->tx_tail;
+	++priv->global_tx_tail;
 
 	if (unlikely(netif_queue_stopped(dev) &&
-		     (priv->tx_head - priv->tx_tail) <= ipoib_sendq_size >> 1 &&
+		     ((priv->global_tx_head - priv->global_tx_tail) <=
+		      ipoib_sendq_size >> 1) &&
 		     test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)))
 		netif_wake_queue(dev);
 
@@ -1232,8 +1234,9 @@
 		dev_kfree_skb_any(tx_req->skb);
 		netif_tx_lock_bh(p->dev);
 		++p->tx_tail;
-		++priv->tx_tail;
-		if (unlikely(priv->tx_head - priv->tx_tail == ipoib_sendq_size >> 1) &&
+		++priv->global_tx_tail;
+		if (unlikely((priv->global_tx_head - priv->global_tx_tail) <=
+			     ipoib_sendq_size >> 1) &&
 		    netif_queue_stopped(p->dev) &&
 		    test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags))
 			netif_wake_queue(p->dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -407,9 +407,11 @@
 	dev_kfree_skb_any(tx_req->skb);
 
 	++priv->tx_tail;
+	++priv->global_tx_tail;
 
 	if (unlikely(netif_queue_stopped(dev) &&
-		     ((priv->tx_head - priv->tx_tail) <= ipoib_sendq_size >> 1) &&
+		     ((priv->global_tx_head - priv->global_tx_tail) <=
+		      ipoib_sendq_size >> 1) &&
 		     test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)))
 		netif_wake_queue(dev);
 
@@ -634,7 +636,8 @@
 	else
 		priv->tx_wr.wr.send_flags &= ~IB_SEND_IP_CSUM;
 	/* increase the tx_head after send success, but use it for queue state */
-	if (priv->tx_head - priv->tx_tail == ipoib_sendq_size - 1) {
+	if ((priv->global_tx_head - priv->global_tx_tail) ==
+	    ipoib_sendq_size - 1) {
 		ipoib_dbg(priv, "TX ring full, stopping kernel net queue\n");
 		netif_stop_queue(dev);
 	}
@@ -662,17 +665,17 @@
 
 		rc = priv->tx_head;
 		++priv->tx_head;
+		++priv->global_tx_head;
 	}
 	return rc;
 }
 
-static void __ipoib_reap_ah(struct net_device *dev)
+static void ipoib_reap_dead_ahs(struct ipoib_dev_priv *priv)
 {
-	struct ipoib_dev_priv *priv = ipoib_priv(dev);
 	struct ipoib_ah *ah, *tah;
 	unsigned long flags;
 
-	netif_tx_lock_bh(dev);
+	netif_tx_lock_bh(priv->dev);
 	spin_lock_irqsave(&priv->lock, flags);
 
 	list_for_each_entry_safe(ah, tah, &priv->dead_ahs, list)
@@ -683,37 +686,37 @@
 		}
 
 	spin_unlock_irqrestore(&priv->lock, flags);
-	netif_tx_unlock_bh(dev);
+	netif_tx_unlock_bh(priv->dev);
 }
 
 void ipoib_reap_ah(struct work_struct *work)
 {
 	struct ipoib_dev_priv *priv =
 		container_of(work, struct ipoib_dev_priv, ah_reap_task.work);
-	struct net_device *dev = priv->dev;
 
-	__ipoib_reap_ah(dev);
+	ipoib_reap_dead_ahs(priv);
 
 	if (!test_bit(IPOIB_STOP_REAPER, &priv->flags))
 		queue_delayed_work(priv->wq, &priv->ah_reap_task,
 				   round_jiffies_relative(HZ));
 }
 
-static void ipoib_flush_ah(struct net_device *dev)
+static void ipoib_start_ah_reaper(struct ipoib_dev_priv *priv)
 {
-	struct ipoib_dev_priv *priv = ipoib_priv(dev);
-
-	cancel_delayed_work(&priv->ah_reap_task);
-	flush_workqueue(priv->wq);
-	ipoib_reap_ah(&priv->ah_reap_task.work);
+	clear_bit(IPOIB_STOP_REAPER, &priv->flags);
+	queue_delayed_work(priv->wq, &priv->ah_reap_task,
+			   round_jiffies_relative(HZ));
 }
 
-static void ipoib_stop_ah(struct net_device *dev)
+static void ipoib_stop_ah_reaper(struct ipoib_dev_priv *priv)
 {
-	struct ipoib_dev_priv *priv = ipoib_priv(dev);
-
 	set_bit(IPOIB_STOP_REAPER, &priv->flags);
-	ipoib_flush_ah(dev);
+	cancel_delayed_work(&priv->ah_reap_task);
+	/*
+	 * After ipoib_stop_ah_reaper() we always go through
+	 * ipoib_reap_dead_ahs() which ensures the work is really stopped and
+	 * does a final flush out of the dead_ah's list
+	 */
 }
 
 static int recvs_pending(struct net_device *dev)
@@ -807,6 +810,7 @@
 				ipoib_dma_unmap_tx(priv, tx_req);
 				dev_kfree_skb_any(tx_req->skb);
 				++priv->tx_tail;
+				++priv->global_tx_tail;
 			}
 
 			for (i = 0; i < ipoib_recvq_size; ++i) {
@@ -841,18 +845,6 @@
 	return 0;
 }
 
-int ipoib_ib_dev_stop(struct net_device *dev)
-{
-	struct ipoib_dev_priv *priv = ipoib_priv(dev);
-
-	priv->rn_ops->ndo_stop(dev);
-
-	clear_bit(IPOIB_FLAG_INITIALIZED, &priv->flags);
-	ipoib_flush_ah(dev);
-
-	return 0;
-}
-
 int ipoib_ib_dev_open_default(struct net_device *dev)
 {
 	struct ipoib_dev_priv *priv = ipoib_priv(dev);
@@ -896,10 +888,7 @@
 		return -1;
 	}
 
-	clear_bit(IPOIB_STOP_REAPER, &priv->flags);
-	queue_delayed_work(priv->wq, &priv->ah_reap_task,
-			   round_jiffies_relative(HZ));
-
+	ipoib_start_ah_reaper(priv);
 	if (priv->rn_ops->ndo_open(dev)) {
 		pr_warn("%s: Failed to open dev\n", dev->name);
 		goto dev_stop;
@@ -910,13 +899,20 @@
 	return 0;
 
 dev_stop:
-	set_bit(IPOIB_STOP_REAPER, &priv->flags);
-	cancel_delayed_work(&priv->ah_reap_task);
-	set_bit(IPOIB_FLAG_INITIALIZED, &priv->flags);
-	ipoib_ib_dev_stop(dev);
+	ipoib_stop_ah_reaper(priv);
 	return -1;
 }
 
+void ipoib_ib_dev_stop(struct net_device *dev)
+{
+	struct ipoib_dev_priv *priv = ipoib_priv(dev);
+
+	priv->rn_ops->ndo_stop(dev);
+
+	clear_bit(IPOIB_FLAG_INITIALIZED, &priv->flags);
+	ipoib_stop_ah_reaper(priv);
+}
+
 void ipoib_pkey_dev_check_presence(struct net_device *dev)
 {
 	struct ipoib_dev_priv *priv = ipoib_priv(dev);
@@ -1227,7 +1223,7 @@
 		ipoib_mcast_dev_flush(dev);
 		if (oper_up)
 			set_bit(IPOIB_FLAG_OPER_UP, &priv->flags);
-		ipoib_flush_ah(dev);
+		ipoib_reap_dead_ahs(priv);
 	}
 
 	if (level >= IPOIB_FLUSH_NORMAL)
@@ -1302,7 +1298,7 @@
 	 * the neighbor garbage collection is stopped and reaped.
 	 * That should all be done now, so make a final ah flush.
 	 */
-	ipoib_stop_ah(dev);
+	ipoib_reap_dead_ahs(priv);
 
 	clear_bit(IPOIB_PKEY_ASSIGNED, &priv->flags);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -1188,9 +1188,11 @@
 
 	ipoib_warn(priv, "transmit timeout: latency %d msecs\n",
 		   jiffies_to_msecs(jiffies - dev_trans_start(dev)));
-	ipoib_warn(priv, "queue stopped %d, tx_head %u, tx_tail %u\n",
-		   netif_queue_stopped(dev),
-		   priv->tx_head, priv->tx_tail);
+	ipoib_warn(priv,
+		   "queue stopped %d, tx_head %u, tx_tail %u, global_tx_head %u, global_tx_tail %u\n",
+		   netif_queue_stopped(dev), priv->tx_head, priv->tx_tail,
+		   priv->global_tx_head, priv->global_tx_tail);
+
 	/* XXX reset QP, etc. */
 }
 
@@ -1705,7 +1707,7 @@
 		goto out_rx_ring_cleanup;
 	}
 
-	/* priv->tx_head, tx_tail & tx_outstanding are already 0 */
+	/* priv->tx_head, tx_tail and global_tx_tail/head are already 0 */
 
 	if (ipoib_transport_dev_init(dev, priv->ca)) {
 		pr_warn("%s: ipoib_transport_dev_init failed\n",
@@ -1977,6 +1979,8 @@
 
 	/* no more works over the priv->wq */
 	if (priv->wq) {
+		/* See ipoib_mcast_carrier_on_task() */
+		WARN_ON(test_bit(IPOIB_FLAG_OPER_UP, &priv->flags));
 		flush_workqueue(priv->wq);
 		destroy_workqueue(priv->wq);
 		priv->wq = NULL;
@@ -2167,6 +2171,14 @@
 		rn->attach_mcast = ipoib_mcast_attach;
 		rn->detach_mcast = ipoib_mcast_detach;
 		rn->hca = hca;
+
+		rc = netif_set_real_num_tx_queues(dev, 1);
+		if (rc)
+			goto out;
+
+		rc = netif_set_real_num_rx_queues(dev, 1);
+		if (rc)
+			goto out;
 	}
 
 	priv->rn_ops = dev->netdev_ops;
@@ -2459,6 +2471,8 @@
 	/* call event handler to ensure pkey in sync */
 	queue_work(ipoib_workqueue, &priv->flush_heavy);
 
+	ndev->rtnl_link_ops = ipoib_get_link_ops();
+
 	result = register_netdev(ndev);
 	if (result) {
 		pr_warn("%s: couldn't register ipoib port %d; error %d\n",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -543,21 +543,18 @@
 			/* SM supports sendonly-fullmember, otherwise fallback to full-member */
 			rec.join_state = SENDONLY_FULLMEMBER_JOIN;
 	}
-	spin_unlock_irq(&priv->lock);
 
 	multicast = ib_sa_join_multicast(&ipoib_sa_client, priv->ca, priv->port,
-					 &rec, comp_mask, GFP_KERNEL,
+					 &rec, comp_mask, GFP_ATOMIC,
 					 ipoib_mcast_join_complete, mcast);
-	spin_lock_irq(&priv->lock);
 	if (IS_ERR(multicast)) {
 		ret = PTR_ERR(multicast);
 		ipoib_warn(priv, "ib_sa_join_multicast failed, status %d\n", ret);
 		/* Requeue this join task with a backoff delay */
 		__ipoib_mcast_schedule_join_thread(priv, mcast, 1);
 		clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
-		spin_unlock_irq(&priv->lock);
 		complete(&mcast->done);
-		spin_lock_irq(&priv->lock);
+		return ret;
 	}
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/ulp/ipoib/ipoib_netlink.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/ulp/ipoib/ipoib_netlink.c
@@ -42,6 +42,11 @@
 	[IFLA_IPOIB_UMCAST]	= { .type = NLA_U16 },
 };
 
+static unsigned int ipoib_get_max_num_queues(void)
+{
+	return min_t(unsigned int, num_possible_cpus(), 128);
+}
+
 static int ipoib_fill_info(struct sk_buff *skb, const struct net_device *dev)
 {
 	struct ipoib_dev_priv *priv = ipoib_priv(dev);
@@ -144,6 +149,16 @@
 	return 0;
 }
 
+static void ipoib_del_child_link(struct net_device *dev, struct list_head *head)
+{
+	struct ipoib_dev_priv *priv = ipoib_priv(dev);
+
+	if (!priv->parent)
+		return;
+
+	unregister_netdevice_queue(dev, head);
+}
+
 static size_t ipoib_get_size(const struct net_device *dev)
 {
 	return nla_total_size(2) +	/* IFLA_IPOIB_PKEY   */
@@ -153,14 +168,18 @@
 
 static struct rtnl_link_ops ipoib_link_ops __read_mostly = {
 	.kind		= "ipoib",
+	.netns_refund   = true,
 	.maxtype	= IFLA_IPOIB_MAX,
 	.policy		= ipoib_policy,
 	.priv_size	= sizeof(struct ipoib_dev_priv),
 	.setup		= ipoib_setup_common,
 	.newlink	= ipoib_new_child_link,
+	.dellink	= ipoib_del_child_link,
 	.changelink	= ipoib_changelink,
 	.get_size	= ipoib_get_size,
 	.fill_info	= ipoib_fill_info,
+	.get_num_rx_queues = ipoib_get_max_num_queues,
+	.get_num_tx_queues = ipoib_get_max_num_queues,
 };
 
 struct rtnl_link_ops *ipoib_get_link_ops(void)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
@@ -182,8 +182,12 @@
 
 	ppriv = ipoib_priv(pdev);
 
-	snprintf(intf_name, sizeof(intf_name), "%s.%04x",
-		 ppriv->dev->name, pkey);
+	/* If you increase IFNAMSIZ, update snprintf below
+	 * to allow longer names.
+	 */
+	BUILD_BUG_ON(IFNAMSIZ != 16);
+	snprintf(intf_name, sizeof(intf_name), "%.10s.%04x", ppriv->dev->name,
+		 pkey);
 
 	ndev = ipoib_intf_alloc(ppriv->ca, ppriv->port, intf_name);
 	if (IS_ERR(ndev)) {
@@ -192,6 +196,8 @@
 	}
 	priv = ipoib_priv(ndev);
 
+	ndev->rtnl_link_ops = ipoib_get_link_ops();
+
 	result = __ipoib_vlan_add(ppriv, priv, pkey, IPOIB_LEGACY_CHILD);
 
 	if (result && ndev->reg_state == NETREG_UNINITIALIZED)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -646,6 +646,7 @@
 		if (ib_conn->pi_support) {
 			u32 sig_caps = ib_dev->attrs.sig_prot_cap;
 
+			shost->sg_prot_tablesize = shost->sg_tablesize;
 			scsi_host_set_prot(shost, iser_dif_prot_caps(sig_caps));
 			scsi_host_set_guard(shost, SHOST_DIX_GUARD_IP |
 						   SHOST_DIX_GUARD_CRC);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/ulp/iser/iser_memory.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/ulp/iser/iser_memory.c
@@ -292,12 +292,27 @@
 {
 	struct iser_device *device = iser_task->iser_conn->ib_conn.device;
 	struct iser_mem_reg *reg = &iser_task->rdma_reg[cmd_dir];
+	struct iser_fr_desc *desc;
+	struct ib_mr_status mr_status;
 
-	if (!reg->mem_h)
+	desc = reg->mem_h;
+	if (!desc)
 		return;
 
-	device->reg_ops->reg_desc_put(&iser_task->iser_conn->ib_conn,
-				     reg->mem_h);
+	/*
+	 * The signature MR cannot be invalidated and reused without checking.
+	 * libiscsi calls the check_protection transport handler only if
+	 * SCSI-Response is received. And the signature MR is not checked if
+	 * the task is completed for some other reason like a timeout or error
+	 * handling. That's why we must check the signature MR here before
+	 * putting it to the free pool.
+	 */
+	if (unlikely(desc->sig_protected)) {
+		desc->sig_protected = false;
+		ib_check_mr_status(desc->rsc.sig_mr, IB_MR_CHECK_SIG_STATUS,
+				   &mr_status);
+	}
+	device->reg_ops->reg_desc_put(&iser_task->iser_conn->ib_conn, desc);
 	reg->mem_h = NULL;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/ulp/isert/ib_isert.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/ulp/isert/ib_isert.c
@@ -182,15 +182,15 @@
 	rx_desc = isert_conn->rx_descs;
 
 	for (i = 0; i < ISERT_QP_MAX_RECV_DTOS; i++, rx_desc++)  {
-		dma_addr = ib_dma_map_single(ib_dev, (void *)rx_desc,
-					ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
+		dma_addr = ib_dma_map_single(ib_dev, rx_desc->buf,
+					ISER_RX_SIZE, DMA_FROM_DEVICE);
 		if (ib_dma_mapping_error(ib_dev, dma_addr))
 			goto dma_map_fail;
 
 		rx_desc->dma_addr = dma_addr;
 
 		rx_sg = &rx_desc->rx_sg;
-		rx_sg->addr = rx_desc->dma_addr;
+		rx_sg->addr = rx_desc->dma_addr + isert_get_hdr_offset(rx_desc);
 		rx_sg->length = ISER_RX_PAYLOAD_SIZE;
 		rx_sg->lkey = device->pd->local_dma_lkey;
 		rx_desc->rx_cqe.done = isert_recv_done;
@@ -202,7 +202,7 @@
 	rx_desc = isert_conn->rx_descs;
 	for (j = 0; j < i; j++, rx_desc++) {
 		ib_dma_unmap_single(ib_dev, rx_desc->dma_addr,
-				    ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
+				    ISER_RX_SIZE, DMA_FROM_DEVICE);
 	}
 	kfree(isert_conn->rx_descs);
 	isert_conn->rx_descs = NULL;
@@ -223,7 +223,7 @@
 	rx_desc = isert_conn->rx_descs;
 	for (i = 0; i < ISERT_QP_MAX_RECV_DTOS; i++, rx_desc++)  {
 		ib_dma_unmap_single(ib_dev, rx_desc->dma_addr,
-				    ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
+				    ISER_RX_SIZE, DMA_FROM_DEVICE);
 	}
 
 	kfree(isert_conn->rx_descs);
@@ -408,10 +408,9 @@
 			    ISER_RX_PAYLOAD_SIZE, DMA_TO_DEVICE);
 	kfree(isert_conn->login_rsp_buf);
 
-	ib_dma_unmap_single(ib_dev, isert_conn->login_req_dma,
-			    ISER_RX_PAYLOAD_SIZE,
-			    DMA_FROM_DEVICE);
-	kfree(isert_conn->login_req_buf);
+	ib_dma_unmap_single(ib_dev, isert_conn->login_desc->dma_addr,
+			    ISER_RX_SIZE, DMA_FROM_DEVICE);
+	kfree(isert_conn->login_desc);
 }
 
 static int
@@ -420,25 +419,25 @@
 {
 	int ret;
 
-	isert_conn->login_req_buf = kzalloc(sizeof(*isert_conn->login_req_buf),
+	isert_conn->login_desc = kzalloc(sizeof(*isert_conn->login_desc),
 			GFP_KERNEL);
-	if (!isert_conn->login_req_buf)
+	if (!isert_conn->login_desc)
 		return -ENOMEM;
 
-	isert_conn->login_req_dma = ib_dma_map_single(ib_dev,
-				isert_conn->login_req_buf,
-				ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
-	ret = ib_dma_mapping_error(ib_dev, isert_conn->login_req_dma);
+	isert_conn->login_desc->dma_addr = ib_dma_map_single(ib_dev,
+				isert_conn->login_desc->buf,
+				ISER_RX_SIZE, DMA_FROM_DEVICE);
+	ret = ib_dma_mapping_error(ib_dev, isert_conn->login_desc->dma_addr);
 	if (ret) {
-		isert_err("login_req_dma mapping error: %d\n", ret);
-		isert_conn->login_req_dma = 0;
-		goto out_free_login_req_buf;
+		isert_err("login_desc dma mapping error: %d\n", ret);
+		isert_conn->login_desc->dma_addr = 0;
+		goto out_free_login_desc;
 	}
 
 	isert_conn->login_rsp_buf = kzalloc(ISER_RX_PAYLOAD_SIZE, GFP_KERNEL);
 	if (!isert_conn->login_rsp_buf) {
 		ret = -ENOMEM;
-		goto out_unmap_login_req_buf;
+		goto out_unmap_login_desc;
 	}
 
 	isert_conn->login_rsp_dma = ib_dma_map_single(ib_dev,
@@ -455,11 +454,11 @@
 
 out_free_login_rsp_buf:
 	kfree(isert_conn->login_rsp_buf);
-out_unmap_login_req_buf:
-	ib_dma_unmap_single(ib_dev, isert_conn->login_req_dma,
-			    ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
-out_free_login_req_buf:
-	kfree(isert_conn->login_req_buf);
+out_unmap_login_desc:
+	ib_dma_unmap_single(ib_dev, isert_conn->login_desc->dma_addr,
+			    ISER_RX_SIZE, DMA_FROM_DEVICE);
+out_free_login_desc:
+	kfree(isert_conn->login_desc);
 	return ret;
 }
 
@@ -578,7 +577,7 @@
 		ib_destroy_qp(isert_conn->qp);
 	}
 
-	if (isert_conn->login_req_buf)
+	if (isert_conn->login_desc)
 		isert_free_login_buf(isert_conn);
 
 	isert_device_put(device);
@@ -734,9 +733,13 @@
 isert_connect_error(struct rdma_cm_id *cma_id)
 {
 	struct isert_conn *isert_conn = cma_id->qp->qp_context;
+	struct isert_np *isert_np = cma_id->context;
 
 	ib_drain_qp(isert_conn->qp);
+
+	mutex_lock(&isert_np->mutex);
 	list_del_init(&isert_conn->node);
+	mutex_unlock(&isert_np->mutex);
 	isert_conn->cm_id = NULL;
 	isert_put_conn(isert_conn);
 
@@ -964,17 +967,18 @@
 	int ret;
 
 	memset(&sge, 0, sizeof(struct ib_sge));
-	sge.addr = isert_conn->login_req_dma;
+	sge.addr = isert_conn->login_desc->dma_addr +
+		isert_get_hdr_offset(isert_conn->login_desc);
 	sge.length = ISER_RX_PAYLOAD_SIZE;
 	sge.lkey = isert_conn->device->pd->local_dma_lkey;
 
 	isert_dbg("Setup sge: addr: %llx length: %d 0x%08x\n",
 		sge.addr, sge.length, sge.lkey);
 
-	isert_conn->login_req_buf->rx_cqe.done = isert_login_recv_done;
+	isert_conn->login_desc->rx_cqe.done = isert_login_recv_done;
 
 	memset(&rx_wr, 0, sizeof(struct ib_recv_wr));
-	rx_wr.wr_cqe = &isert_conn->login_req_buf->rx_cqe;
+	rx_wr.wr_cqe = &isert_conn->login_desc->rx_cqe;
 	rx_wr.sg_list = &sge;
 	rx_wr.num_sge = 1;
 
@@ -1051,7 +1055,7 @@
 static void
 isert_rx_login_req(struct isert_conn *isert_conn)
 {
-	struct iser_rx_desc *rx_desc = isert_conn->login_req_buf;
+	struct iser_rx_desc *rx_desc = isert_conn->login_desc;
 	int rx_buflen = isert_conn->login_req_len;
 	struct iscsi_conn *conn = isert_conn->conn;
 	struct iscsi_login *login = conn->conn_login;
@@ -1063,7 +1067,7 @@
 
 	if (login->first_request) {
 		struct iscsi_login_req *login_req =
-			(struct iscsi_login_req *)&rx_desc->iscsi_header;
+			(struct iscsi_login_req *)isert_get_iscsi_hdr(rx_desc);
 		/*
 		 * Setup the initial iscsi_login values from the leading
 		 * login request PDU.
@@ -1082,13 +1086,13 @@
 		login->tsih		= be16_to_cpu(login_req->tsih);
 	}
 
-	memcpy(&login->req[0], (void *)&rx_desc->iscsi_header, ISCSI_HDR_LEN);
+	memcpy(&login->req[0], isert_get_iscsi_hdr(rx_desc), ISCSI_HDR_LEN);
 
 	size = min(rx_buflen, MAX_KEY_VALUE_PAIRS);
 	isert_dbg("Using login payload size: %d, rx_buflen: %d "
 		  "MAX_KEY_VALUE_PAIRS: %d\n", size, rx_buflen,
 		  MAX_KEY_VALUE_PAIRS);
-	memcpy(login->req_buf, &rx_desc->data[0], size);
+	memcpy(login->req_buf, isert_get_data(rx_desc), size);
 
 	if (login->first_request) {
 		complete(&isert_conn->login_comp);
@@ -1153,14 +1157,15 @@
 	if (imm_data_len != data_len) {
 		sg_nents = max(1UL, DIV_ROUND_UP(imm_data_len, PAGE_SIZE));
 		sg_copy_from_buffer(cmd->se_cmd.t_data_sg, sg_nents,
-				    &rx_desc->data[0], imm_data_len);
+				    isert_get_data(rx_desc), imm_data_len);
 		isert_dbg("Copy Immediate sg_nents: %u imm_data_len: %d\n",
 			  sg_nents, imm_data_len);
 	} else {
 		sg_init_table(&isert_cmd->sg, 1);
 		cmd->se_cmd.t_data_sg = &isert_cmd->sg;
 		cmd->se_cmd.t_data_nents = 1;
-		sg_set_buf(&isert_cmd->sg, &rx_desc->data[0], imm_data_len);
+		sg_set_buf(&isert_cmd->sg, isert_get_data(rx_desc),
+				imm_data_len);
 		isert_dbg("Transfer Immediate imm_data_len: %d\n",
 			  imm_data_len);
 	}
@@ -1229,9 +1234,9 @@
 	}
 	isert_dbg("Copying DataOut: sg_start: %p, sg_off: %u "
 		  "sg_nents: %u from %p %u\n", sg_start, sg_off,
-		  sg_nents, &rx_desc->data[0], unsol_data_len);
+		  sg_nents, isert_get_data(rx_desc), unsol_data_len);
 
-	sg_copy_from_buffer(sg_start, sg_nents, &rx_desc->data[0],
+	sg_copy_from_buffer(sg_start, sg_nents, isert_get_data(rx_desc),
 			    unsol_data_len);
 
 	rc = iscsit_check_dataout_payload(cmd, hdr, false);
@@ -1290,7 +1295,7 @@
 	}
 	cmd->text_in_ptr = text_in;
 
-	memcpy(cmd->text_in_ptr, &rx_desc->data[0], payload_length);
+	memcpy(cmd->text_in_ptr, isert_get_data(rx_desc), payload_length);
 
 	return iscsit_process_text_cmd(conn, cmd, hdr);
 }
@@ -1300,7 +1305,7 @@
 		uint32_t read_stag, uint64_t read_va,
 		uint32_t write_stag, uint64_t write_va)
 {
-	struct iscsi_hdr *hdr = &rx_desc->iscsi_header;
+	struct iscsi_hdr *hdr = isert_get_iscsi_hdr(rx_desc);
 	struct iscsi_conn *conn = isert_conn->conn;
 	struct iscsi_cmd *cmd;
 	struct isert_cmd *isert_cmd;
@@ -1398,8 +1403,8 @@
 	struct isert_conn *isert_conn = wc->qp->qp_context;
 	struct ib_device *ib_dev = isert_conn->cm_id->device;
 	struct iser_rx_desc *rx_desc = cqe_to_rx_desc(wc->wr_cqe);
-	struct iscsi_hdr *hdr = &rx_desc->iscsi_header;
-	struct iser_ctrl *iser_ctrl = &rx_desc->iser_header;
+	struct iscsi_hdr *hdr = isert_get_iscsi_hdr(rx_desc);
+	struct iser_ctrl *iser_ctrl = isert_get_iser_hdr(rx_desc);
 	uint64_t read_va = 0, write_va = 0;
 	uint32_t read_stag = 0, write_stag = 0;
 
@@ -1413,7 +1418,7 @@
 	rx_desc->in_use = true;
 
 	ib_dma_sync_single_for_cpu(ib_dev, rx_desc->dma_addr,
-			ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
+			ISER_RX_SIZE, DMA_FROM_DEVICE);
 
 	isert_dbg("DMA: 0x%llx, iSCSI opcode: 0x%02x, ITT: 0x%08x, flags: 0x%02x dlen: %d\n",
 		 rx_desc->dma_addr, hdr->opcode, hdr->itt, hdr->flags,
@@ -1448,7 +1453,7 @@
 			read_stag, read_va, write_stag, write_va);
 
 	ib_dma_sync_single_for_device(ib_dev, rx_desc->dma_addr,
-			ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
+			ISER_RX_SIZE, DMA_FROM_DEVICE);
 }
 
 static void
@@ -1462,8 +1467,8 @@
 		return;
 	}
 
-	ib_dma_sync_single_for_cpu(ib_dev, isert_conn->login_req_dma,
-			ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
+	ib_dma_sync_single_for_cpu(ib_dev, isert_conn->login_desc->dma_addr,
+			ISER_RX_SIZE, DMA_FROM_DEVICE);
 
 	isert_conn->login_req_len = wc->byte_len - ISER_HEADERS_LEN;
 
@@ -1478,8 +1483,8 @@
 	complete(&isert_conn->login_req_comp);
 	mutex_unlock(&isert_conn->mutex);
 
-	ib_dma_sync_single_for_device(ib_dev, isert_conn->login_req_dma,
-				ISER_RX_PAYLOAD_SIZE, DMA_FROM_DEVICE);
+	ib_dma_sync_single_for_device(ib_dev, isert_conn->login_desc->dma_addr,
+				ISER_RX_SIZE, DMA_FROM_DEVICE);
 }
 
 static void
@@ -2506,6 +2511,7 @@
 {
 	struct isert_np *isert_np = np->np_context;
 	struct isert_conn *isert_conn, *n;
+	LIST_HEAD(drop_conn_list);
 
 	if (isert_np->cm_id)
 		rdma_destroy_id(isert_np->cm_id);
@@ -2525,7 +2531,7 @@
 					 node) {
 			isert_info("cleaning isert_conn %p state (%d)\n",
 				   isert_conn, isert_conn->state);
-			isert_connect_release(isert_conn);
+			list_move_tail(&isert_conn->node, &drop_conn_list);
 		}
 	}
 
@@ -2536,11 +2542,16 @@
 					 node) {
 			isert_info("cleaning isert_conn %p state (%d)\n",
 				   isert_conn, isert_conn->state);
-			isert_connect_release(isert_conn);
+			list_move_tail(&isert_conn->node, &drop_conn_list);
 		}
 	}
 	mutex_unlock(&isert_np->mutex);
 
+	list_for_each_entry_safe(isert_conn, n, &drop_conn_list, node) {
+		list_del_init(&isert_conn->node);
+		isert_connect_release(isert_conn);
+	}
+
 	np->np_context = NULL;
 	kfree(isert_np);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/ulp/isert/ib_isert.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/ulp/isert/ib_isert.h
@@ -59,9 +59,11 @@
 				ISERT_MAX_TX_MISC_PDUS	+ \
 				ISERT_MAX_RX_MISC_PDUS)
 
-#define ISER_RX_PAD_SIZE	(ISCSI_DEF_MAX_RECV_SEG_LEN + 4096 - \
-		(ISER_RX_PAYLOAD_SIZE + sizeof(u64) + sizeof(struct ib_sge) + \
-		 sizeof(struct ib_cqe) + sizeof(bool)))
+/*
+ * RX size is default of 8k plus headers, but data needs to align to
+ * 512 boundary, so use 1024 to have the extra space for alignment.
+ */
+#define ISER_RX_SIZE		(ISCSI_DEF_MAX_RECV_SEG_LEN + 1024)
 
 #define ISCSI_ISER_SG_TABLESIZE		256
 
@@ -80,21 +82,41 @@
 };
 
 struct iser_rx_desc {
-	struct iser_ctrl iser_header;
-	struct iscsi_hdr iscsi_header;
-	char		data[ISCSI_DEF_MAX_RECV_SEG_LEN];
+	char		buf[ISER_RX_SIZE];
 	u64		dma_addr;
 	struct ib_sge	rx_sg;
 	struct ib_cqe	rx_cqe;
 	bool		in_use;
-	char		pad[ISER_RX_PAD_SIZE];
-} __packed;
+};
 
 static inline struct iser_rx_desc *cqe_to_rx_desc(struct ib_cqe *cqe)
 {
 	return container_of(cqe, struct iser_rx_desc, rx_cqe);
 }
 
+static void *isert_get_iser_hdr(struct iser_rx_desc *desc)
+{
+	return PTR_ALIGN(desc->buf + ISER_HEADERS_LEN, 512) - ISER_HEADERS_LEN;
+}
+
+static size_t isert_get_hdr_offset(struct iser_rx_desc *desc)
+{
+	return isert_get_iser_hdr(desc) - (void *)desc->buf;
+}
+
+static void *isert_get_iscsi_hdr(struct iser_rx_desc *desc)
+{
+	return isert_get_iser_hdr(desc) + sizeof(struct iser_ctrl);
+}
+
+static void *isert_get_data(struct iser_rx_desc *desc)
+{
+	void *data = isert_get_iser_hdr(desc) + ISER_HEADERS_LEN;
+
+	WARN_ON((uintptr_t)data & 511);
+	return data;
+}
+
 struct iser_tx_desc {
 	struct iser_ctrl iser_header;
 	struct iscsi_hdr iscsi_header;
@@ -141,9 +163,8 @@
 	u32			responder_resources;
 	u32			initiator_depth;
 	bool			pi_support;
-	struct iser_rx_desc	*login_req_buf;
+	struct iser_rx_desc	*login_desc;
 	char			*login_rsp_buf;
-	u64			login_req_dma;
 	int			login_req_len;
 	u64			login_rsp_dma;
 	struct iser_rx_desc	*rx_descs;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/ulp/srp/ib_srp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/ulp/srp/ib_srp.c
@@ -2536,7 +2536,8 @@
 	if (lrsp->opcode == SRP_LOGIN_RSP) {
 		ch->max_ti_iu_len = be32_to_cpu(lrsp->max_ti_iu_len);
 		ch->req_lim       = be32_to_cpu(lrsp->req_lim_delta);
-		ch->use_imm_data  = lrsp->rsp_flags & SRP_LOGIN_RSP_IMMED_SUPP;
+		ch->use_imm_data  = srp_use_imm_data &&
+			(lrsp->rsp_flags & SRP_LOGIN_RSP_IMMED_SUPP);
 		ch->max_it_iu_len = srp_max_it_iu_len(target->cmd_sg_cnt,
 						      ch->use_imm_data);
 		WARN_ON_ONCE(ch->max_it_iu_len >
@@ -4221,9 +4222,11 @@
 		spin_unlock(&host->target_lock);
 
 		/*
-		 * Wait for tl_err and target port removal tasks.
+		 * srp_queue_remove_work() queues a call to
+		 * srp_remove_target(). The latter function cancels
+		 * target->tl_err_work so waiting for the remove works to
+		 * finish is sufficient.
 		 */
-		flush_workqueue(system_long_wq);
 		flush_workqueue(srp_remove_wq);
 
 		kfree(host);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/ulp/srp/ib_srp.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/ulp/srp/ib_srp.h
@@ -63,9 +63,6 @@
 	SRP_DEFAULT_CMD_SQ_SIZE = SRP_DEFAULT_QUEUE_SIZE - SRP_RSP_SQ_SIZE -
 				  SRP_TSK_MGMT_SQ_SIZE,
 
-	SRP_TAG_NO_REQ		= ~0U,
-	SRP_TAG_TSK_MGMT	= 1U << 31,
-
 	SRP_MAX_PAGES_PER_MR	= 512,
 
 	SRP_MAX_ADD_CDB_LEN	= 16,
@@ -80,6 +77,11 @@
 				  sizeof(struct srp_imm_buf),
 };
 
+enum {
+	SRP_TAG_NO_REQ		= ~0U,
+	SRP_TAG_TSK_MGMT	= BIT(31),
+};
+
 enum srp_target_state {
 	SRP_TARGET_SCANNING,
 	SRP_TARGET_LIVE,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/infiniband/ulp/srpt/ib_srpt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/infiniband/ulp/srpt/ib_srpt.c
@@ -213,12 +213,15 @@
 /**
  * srpt_qp_event - QP event callback function
  * @event: Description of the event that occurred.
- * @ch: SRPT RDMA channel.
+ * @ptr: SRPT RDMA channel.
  */
-static void srpt_qp_event(struct ib_event *event, struct srpt_rdma_ch *ch)
+static void srpt_qp_event(struct ib_event *event, void *ptr)
 {
-	pr_debug("QP event %d on ch=%p sess_name=%s state=%d\n",
-		 event->event, ch, ch->sess_name, ch->state);
+	struct srpt_rdma_ch *ch = ptr;
+
+	pr_debug("QP event %d on ch=%p sess_name=%s-%d state=%s\n",
+		 event->event, ch, ch->sess_name, ch->qp->qp_num,
+		 get_ch_state_name(ch->state));
 
 	switch (event->event) {
 	case IB_EVENT_COMM_EST:
@@ -1364,9 +1367,11 @@
 			      struct srpt_send_ioctx *ioctx, u64 tag,
 			      int status)
 {
+	struct se_cmd *cmd = &ioctx->cmd;
 	struct srp_rsp *srp_rsp;
 	const u8 *sense_data;
 	int sense_data_len, max_sense_len;
+	u32 resid = cmd->residual_count;
 
 	/*
 	 * The lowest bit of all SAM-3 status codes is zero (see also
@@ -1388,6 +1393,28 @@
 	srp_rsp->tag = tag;
 	srp_rsp->status = status;
 
+	if (cmd->se_cmd_flags & SCF_UNDERFLOW_BIT) {
+		if (cmd->data_direction == DMA_TO_DEVICE) {
+			/* residual data from an underflow write */
+			srp_rsp->flags = SRP_RSP_FLAG_DOUNDER;
+			srp_rsp->data_out_res_cnt = cpu_to_be32(resid);
+		} else if (cmd->data_direction == DMA_FROM_DEVICE) {
+			/* residual data from an underflow read */
+			srp_rsp->flags = SRP_RSP_FLAG_DIUNDER;
+			srp_rsp->data_in_res_cnt = cpu_to_be32(resid);
+		}
+	} else if (cmd->se_cmd_flags & SCF_OVERFLOW_BIT) {
+		if (cmd->data_direction == DMA_TO_DEVICE) {
+			/* residual data from an overflow write */
+			srp_rsp->flags = SRP_RSP_FLAG_DOOVER;
+			srp_rsp->data_out_res_cnt = cpu_to_be32(resid);
+		} else if (cmd->data_direction == DMA_FROM_DEVICE) {
+			/* residual data from an overflow read */
+			srp_rsp->flags = SRP_RSP_FLAG_DIOVER;
+			srp_rsp->data_in_res_cnt = cpu_to_be32(resid);
+		}
+	}
+
 	if (sense_data_len) {
 		BUILD_BUG_ON(MIN_MAX_RSP_SIZE <= sizeof(*srp_rsp));
 		max_sense_len = ch->max_ti_iu_len - sizeof(*srp_rsp);
@@ -1777,8 +1804,7 @@
 	}
 
 	qp_init->qp_context = (void *)ch;
-	qp_init->event_handler
-		= (void(*)(struct ib_event *, void*))srpt_qp_event;
+	qp_init->event_handler = srpt_qp_event;
 	qp_init->send_cq = ch->cq;
 	qp_init->recv_cq = ch->cq;
 	qp_init->sq_sig_type = IB_SIGNAL_REQ_WR;
@@ -1981,8 +2007,8 @@
 	list_for_each_entry(nexus, &sport->nexus_list, entry) {
 		list_for_each_entry(ch, &nexus->ch_list, list) {
 			if (srpt_disconnect_ch(ch) >= 0)
-				pr_info("Closing channel %s because target %s_%d has been disabled\n",
-					ch->sess_name,
+				pr_info("Closing channel %s-%d because target %s_%d has been disabled\n",
+					ch->sess_name, ch->qp->qp_num,
 					dev_name(&sport->sdev->device->dev),
 					sport->port);
 			srpt_close_ch(ch);
@@ -2349,6 +2375,7 @@
 		pr_info("rejected SRP_LOGIN_REQ because target %s_%d is not enabled\n",
 			dev_name(&sdev->device->dev), port_num);
 		mutex_unlock(&sport->mutex);
+		ret = -EINVAL;
 		goto reject;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/evdev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/evdev.c
@@ -224,13 +224,13 @@
 		 */
 		client->tail = (client->head - 2) & (client->bufsize - 1);
 
-		client->buffer[client->tail].input_event_sec =
-						event->input_event_sec;
-		client->buffer[client->tail].input_event_usec =
-						event->input_event_usec;
-		client->buffer[client->tail].type = EV_SYN;
-		client->buffer[client->tail].code = SYN_DROPPED;
-		client->buffer[client->tail].value = 0;
+		client->buffer[client->tail] = (struct input_event) {
+			.input_event_sec = event->input_event_sec,
+			.input_event_usec = event->input_event_usec,
+			.type = EV_SYN,
+			.code = SYN_DROPPED,
+			.value = 0,
+		};
 
 		client->packet_head = client->tail;
 	}
@@ -326,20 +326,6 @@
 	return fasync_helper(fd, file, on, &client->fasync);
 }
 
-static int evdev_flush(struct file *file, fl_owner_t id)
-{
-	struct evdev_client *client = file->private_data;
-	struct evdev *evdev = client->evdev;
-
-	mutex_lock(&evdev->mutex);
-
-	if (evdev->exist && !client->revoked)
-		input_flush_device(&evdev->handle, file);
-
-	mutex_unlock(&evdev->mutex);
-	return 0;
-}
-
 static void evdev_free(struct device *dev)
 {
 	struct evdev *evdev = container_of(dev, struct evdev, dev);
@@ -453,6 +439,10 @@
 	unsigned int i;
 
 	mutex_lock(&evdev->mutex);
+
+	if (evdev->exist && !client->revoked)
+		input_flush_device(&evdev->handle, file);
+
 	evdev_ungrab(evdev, client);
 	mutex_unlock(&evdev->mutex);
 
@@ -484,10 +474,7 @@
 	struct evdev_client *client;
 	int error;
 
-	client = kzalloc(struct_size(client, buffer, bufsize),
-			 GFP_KERNEL | __GFP_NOWARN);
-	if (!client)
-		client = vzalloc(struct_size(client, buffer, bufsize));
+	client = kvzalloc(struct_size(client, buffer, bufsize), GFP_KERNEL);
 	if (!client)
 		return -ENOMEM;
 
@@ -1313,7 +1300,6 @@
 	.compat_ioctl	= evdev_ioctl_compat,
 #endif
 	.fasync		= evdev_fasync,
-	.flush		= evdev_flush,
 	.llseek		= no_llseek,
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/ff-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/ff-core.c
@@ -12,8 +12,10 @@
 /* #define DEBUG */
 
 #include <linux/input.h>
+#include <linux/limits.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/overflow.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 
@@ -318,9 +320,8 @@
 		return -EINVAL;
 	}
 
-	ff_dev_size = sizeof(struct ff_device) +
-				max_effects * sizeof(struct file *);
-	if (ff_dev_size < max_effects) /* overflow */
+	ff_dev_size = struct_size(ff, effect_owners, max_effects);
+	if (ff_dev_size == SIZE_MAX) /* overflow */
 		return -EINVAL;
 
 	ff = kzalloc(ff_dev_size, GFP_KERNEL);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/input-mt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/input-mt.c
@@ -45,6 +45,9 @@
 		return 0;
 	if (mt)
 		return mt->num_slots != num_slots ? -EINVAL : 0;
+	/* Arbitrary limit for avoiding too large memory allocation. */
+	if (num_slots > 1024)
+		return -EINVAL;
 
 	mt = kzalloc(struct_size(mt, slots, num_slots), GFP_KERNEL);
 	if (!mt)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/input.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/input.c
@@ -47,6 +47,17 @@
 
 static const struct input_value input_value_sync = { EV_SYN, SYN_REPORT, 1 };
 
+static const unsigned int input_max_code[EV_CNT] = {
+	[EV_KEY] = KEY_MAX,
+	[EV_REL] = REL_MAX,
+	[EV_ABS] = ABS_MAX,
+	[EV_MSC] = MSC_MAX,
+	[EV_SW] = SW_MAX,
+	[EV_LED] = LED_MAX,
+	[EV_SND] = SND_MAX,
+	[EV_FF] = FF_MAX,
+};
+
 static inline int is_event_supported(unsigned int code,
 				     unsigned long *bm, unsigned int max)
 {
@@ -190,6 +201,7 @@
 			input_value_sync
 		};
 
+		input_set_timestamp(dev, ktime_get());
 		input_pass_values(dev, vals, ARRAY_SIZE(vals));
 
 		if (dev->rep[REP_PERIOD])
@@ -878,16 +890,18 @@
 		}
 	}
 
-	__clear_bit(*old_keycode, dev->keybit);
-	__set_bit(ke->keycode, dev->keybit);
-
-	for (i = 0; i < dev->keycodemax; i++) {
-		if (input_fetch_keycode(dev, i) == *old_keycode) {
-			__set_bit(*old_keycode, dev->keybit);
-			break; /* Setting the bit twice is useless, so break */
+	if (*old_keycode <= KEY_MAX) {
+		__clear_bit(*old_keycode, dev->keybit);
+		for (i = 0; i < dev->keycodemax; i++) {
+			if (input_fetch_keycode(dev, i) == *old_keycode) {
+				__set_bit(*old_keycode, dev->keybit);
+				/* Setting the bit twice is useless, so break */
+				break;
+			}
 		}
 	}
 
+	__set_bit(ke->keycode, dev->keybit);
 	return 0;
 }
 
@@ -943,9 +957,13 @@
 	 * Simulate keyup event if keycode is not present
 	 * in the keymap anymore
 	 */
-	if (test_bit(EV_KEY, dev->evbit) &&
-	    !is_event_supported(old_keycode, dev->keybit, KEY_MAX) &&
-	    __test_and_clear_bit(old_keycode, dev->key)) {
+	if (old_keycode > KEY_MAX) {
+		dev_warn(dev->dev.parent ?: &dev->dev,
+			 "%s: got too big old keycode %#x\n",
+			 __func__, old_keycode);
+	} else if (test_bit(EV_KEY, dev->evbit) &&
+		   !is_event_supported(old_keycode, dev->keybit, KEY_MAX) &&
+		   __test_and_clear_bit(old_keycode, dev->key)) {
 		struct input_value vals[] =  {
 			{ EV_KEY, old_keycode, 0 },
 			input_value_sync
@@ -1340,19 +1358,19 @@
 				     char name, unsigned long *bm,
 				     unsigned int min_bit, unsigned int max_bit)
 {
-	int len = 0, i;
+	int bit = min_bit;
+	int len = 0;
 
 	len += snprintf(buf, max(size, 0), "%c", name);
-	for (i = min_bit; i < max_bit; i++)
-		if (bm[BIT_WORD(i)] & BIT_MASK(i))
-			len += snprintf(buf + len, max(size - len, 0), "%X,", i);
+	for_each_set_bit_from(bit, bm, max_bit)
+		len += snprintf(buf + len, max(size - len, 0), "%X,", bit);
 	return len;
 }
 
-static int input_print_modalias(char *buf, int size, struct input_dev *id,
-				int add_cr)
+static int input_print_modalias_parts(char *buf, int size, int full_len,
+				      struct input_dev *id)
 {
-	int len;
+	int len, klen, remainder, space;
 
 	len = snprintf(buf, max(size, 0),
 		       "input:b%04Xv%04Xp%04Xe%04X-",
@@ -1361,8 +1379,49 @@
 
 	len += input_print_modalias_bits(buf + len, size - len,
 				'e', id->evbit, 0, EV_MAX);
-	len += input_print_modalias_bits(buf + len, size - len,
+
+	/*
+	 * Calculate the remaining space in the buffer making sure we
+	 * have place for the terminating 0.
+	 */
+	space = max(size - (len + 1), 0);
+
+	klen = input_print_modalias_bits(buf + len, size - len,
 				'k', id->keybit, KEY_MIN_INTERESTING, KEY_MAX);
+	len += klen;
+
+	/*
+	 * If we have more data than we can fit in the buffer, check
+	 * if we can trim key data to fit in the rest. We will indicate
+	 * that key data is incomplete by adding "+" sign at the end, like
+	 * this: * "k1,2,3,45,+,".
+	 *
+	 * Note that we shortest key info (if present) is "k+," so we
+	 * can only try to trim if key data is longer than that.
+	 */
+	if (full_len && size < full_len + 1 && klen > 3) {
+		remainder = full_len - len;
+		/*
+		 * We can only trim if we have space for the remainder
+		 * and also for at least "k+," which is 3 more characters.
+		 */
+		if (remainder <= space - 3) {
+			int i;
+			/*
+			 * We are guaranteed to have 'k' in the buffer, so
+			 * we need at least 3 additional bytes for storing
+			 * "+," in addition to the remainder.
+			 */
+			for (i = size - 1 - remainder - 3; i >= 0; i--) {
+				if (buf[i] == 'k' || buf[i] == ',') {
+					strcpy(buf + i + 1, "+,");
+					len = i + 3; /* Not counting '\0' */
+					break;
+				}
+			}
+		}
+	}
+
 	len += input_print_modalias_bits(buf + len, size - len,
 				'r', id->relbit, 0, REL_MAX);
 	len += input_print_modalias_bits(buf + len, size - len,
@@ -1378,12 +1437,25 @@
 	len += input_print_modalias_bits(buf + len, size - len,
 				'w', id->swbit, 0, SW_MAX);
 
-	if (add_cr)
-		len += snprintf(buf + len, max(size - len, 0), "\n");
-
 	return len;
 }
 
+static int input_print_modalias(char *buf, int size, struct input_dev *id)
+{
+	int full_len;
+
+	/*
+	 * Printing is done in 2 passes: first one figures out total length
+	 * needed for the modalias string, second one will try to trim key
+	 * data in case when buffer is too small for the entire modalias.
+	 * If the buffer is too small regardless, it will fill as much as it
+	 * can (without trimming key data) into the buffer and leave it to
+	 * the caller to figure out what to do with the result.
+	 */
+	full_len = input_print_modalias_parts(NULL, 0, 0, id);
+	return input_print_modalias_parts(buf, size, full_len, id);
+}
+
 static ssize_t input_dev_show_modalias(struct device *dev,
 				       struct device_attribute *attr,
 				       char *buf)
@@ -1391,7 +1463,9 @@
 	struct input_dev *id = to_input_dev(dev);
 	ssize_t len;
 
-	len = input_print_modalias(buf, PAGE_SIZE, id, 1);
+	len = input_print_modalias(buf, PAGE_SIZE, id);
+	if (len < PAGE_SIZE - 2)
+		len += snprintf(buf + len, PAGE_SIZE - len, "\n");
 
 	return min_t(int, len, PAGE_SIZE);
 }
@@ -1566,6 +1640,23 @@
 	return 0;
 }
 
+/*
+ * This is a pretty gross hack. When building uevent data the driver core
+ * may try adding more environment variables to kobj_uevent_env without
+ * telling us, so we have no idea how much of the buffer we can use to
+ * avoid overflows/-ENOMEM elsewhere. To work around this let's artificially
+ * reduce amount of memory we will use for the modalias environment variable.
+ *
+ * The potential additions are:
+ *
+ * SEQNUM=18446744073709551615 - (%llu - 28 bytes)
+ * HOME=/ (6 bytes)
+ * PATH=/sbin:/bin:/usr/sbin:/usr/bin (34 bytes)
+ *
+ * 68 bytes total. Allow extra buffer - 96 bytes
+ */
+#define UEVENT_ENV_EXTRA_LEN	96
+
 static int input_add_uevent_modalias_var(struct kobj_uevent_env *env,
 					 struct input_dev *dev)
 {
@@ -1575,9 +1666,11 @@
 		return -ENOMEM;
 
 	len = input_print_modalias(&env->buf[env->buflen - 1],
-				   sizeof(env->buf) - env->buflen,
-				   dev, 0);
-	if (len >= (sizeof(env->buf) - env->buflen))
+				   (int)sizeof(env->buf) - env->buflen -
+					UEVENT_ENV_EXTRA_LEN,
+				   dev);
+	if (len >= ((int)sizeof(env->buf) - env->buflen -
+					UEVENT_ENV_EXTRA_LEN))
 		return -ENOMEM;
 
 	env->buflen += len;
@@ -1971,6 +2064,14 @@
  */
 void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code)
 {
+	if (type < EV_CNT && input_max_code[type] &&
+	    code > input_max_code[type]) {
+		pr_err("%s: invalid code %u for type %u\n", __func__, code,
+		       type);
+		dump_stack();
+		return;
+	}
+
 	switch (type) {
 	case EV_KEY:
 		__set_bit(code, dev->keybit);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/joydev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/joydev.c
@@ -456,7 +456,7 @@
 	if (IS_ERR(abspam))
 		return PTR_ERR(abspam);
 
-	for (i = 0; i < joydev->nabs; i++) {
+	for (i = 0; i < len && i < joydev->nabs; i++) {
 		if (abspam[i] > ABS_MAX) {
 			retval = -EINVAL;
 			goto out;
@@ -480,6 +480,9 @@
 	int i;
 	int retval = 0;
 
+	if (len % sizeof(*keypam))
+		return -EINVAL;
+
 	len = min(len, sizeof(joydev->keypam));
 
 	/* Validate the map. */
@@ -487,7 +490,7 @@
 	if (IS_ERR(keypam))
 		return PTR_ERR(keypam);
 
-	for (i = 0; i < joydev->nkey; i++) {
+	for (i = 0; i < (len / 2) && i < joydev->nkey; i++) {
 		if (keypam[i] > KEY_MAX || keypam[i] < BTN_MISC) {
 			retval = -EINVAL;
 			goto out;
@@ -497,7 +500,7 @@
 	memcpy(joydev->keypam, keypam, len);
 
 	for (i = 0; i < joydev->nkey; i++)
-		joydev->keymap[keypam[i] - BTN_MISC] = i;
+		joydev->keymap[joydev->keypam[i] - BTN_MISC] = i;
 
  out:
 	kfree(keypam);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/joystick/iforce/iforce-main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/joystick/iforce/iforce-main.c
@@ -50,6 +50,7 @@
 	{ 0x046d, 0xc291, "Logitech WingMan Formula Force",		btn_wheel, abs_wheel, ff_iforce },
 	{ 0x05ef, 0x020a, "AVB Top Shot Pegasus",			btn_joystick_avb, abs_avb_pegasus, ff_iforce },
 	{ 0x05ef, 0x8884, "AVB Mag Turbo Force",			btn_wheel, abs_wheel, ff_iforce },
+	{ 0x05ef, 0x8886, "Boeder Force Feedback Wheel",		btn_wheel, abs_wheel, ff_iforce },
 	{ 0x05ef, 0x8888, "AVB Top Shot Force Feedback Racing Wheel",	btn_wheel, abs_wheel, ff_iforce }, //?
 	{ 0x061c, 0xc0a4, "ACT LABS Force RS",                          btn_wheel, abs_wheel, ff_iforce }, //?
 	{ 0x061c, 0xc084, "ACT LABS Force RS",				btn_wheel, abs_wheel, ff_iforce },
@@ -272,22 +273,22 @@
  * Get device info.
  */
 
-	if (!iforce_get_id_packet(iforce, 'M', buf, &len) || len < 3)
+	if (!iforce_get_id_packet(iforce, 'M', buf, &len) && len >= 3)
 		input_dev->id.vendor = get_unaligned_le16(buf + 1);
 	else
 		dev_warn(&iforce->dev->dev, "Device does not respond to id packet M\n");
 
-	if (!iforce_get_id_packet(iforce, 'P', buf, &len) || len < 3)
+	if (!iforce_get_id_packet(iforce, 'P', buf, &len) && len >= 3)
 		input_dev->id.product = get_unaligned_le16(buf + 1);
 	else
 		dev_warn(&iforce->dev->dev, "Device does not respond to id packet P\n");
 
-	if (!iforce_get_id_packet(iforce, 'B', buf, &len) || len < 3)
+	if (!iforce_get_id_packet(iforce, 'B', buf, &len) && len >= 3)
 		iforce->device_memory.end = get_unaligned_le16(buf + 1);
 	else
 		dev_warn(&iforce->dev->dev, "Device does not respond to id packet B\n");
 
-	if (!iforce_get_id_packet(iforce, 'N', buf, &len) || len < 2)
+	if (!iforce_get_id_packet(iforce, 'N', buf, &len) && len >= 2)
 		ff_effects = buf[1];
 	else
 		dev_warn(&iforce->dev->dev, "Device does not respond to id packet N\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/joystick/iforce/iforce-serio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/joystick/iforce/iforce-serio.c
@@ -39,7 +39,7 @@
 
 again:
 	if (iforce->xmit.head == iforce->xmit.tail) {
-		clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags);
+		iforce_clear_xmit_and_wake(iforce);
 		spin_unlock_irqrestore(&iforce->xmit_lock, flags);
 		return;
 	}
@@ -64,7 +64,7 @@
 	if (test_and_clear_bit(IFORCE_XMIT_AGAIN, iforce->xmit_flags))
 		goto again;
 
-	clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags);
+	iforce_clear_xmit_and_wake(iforce);
 
 	spin_unlock_irqrestore(&iforce->xmit_lock, flags);
 }
@@ -169,7 +169,7 @@
 			iforce_serio->cmd_response_len = iforce_serio->len;
 
 			/* Signal that command is done */
-			wake_up(&iforce->wait);
+			wake_up_all(&iforce->wait);
 		} else if (likely(iforce->type)) {
 			iforce_process_packet(iforce, iforce_serio->id,
 					      iforce_serio->data_in,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/joystick/iforce/iforce-usb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/joystick/iforce/iforce-usb.c
@@ -30,7 +30,7 @@
 	spin_lock_irqsave(&iforce->xmit_lock, flags);
 
 	if (iforce->xmit.head == iforce->xmit.tail) {
-		clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags);
+		iforce_clear_xmit_and_wake(iforce);
 		spin_unlock_irqrestore(&iforce->xmit_lock, flags);
 		return;
 	}
@@ -58,9 +58,9 @@
 	XMIT_INC(iforce->xmit.tail, n);
 
 	if ( (n=usb_submit_urb(iforce_usb->out, GFP_ATOMIC)) ) {
-		clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags);
 		dev_warn(&iforce_usb->intf->dev,
 			 "usb_submit_urb failed %d\n", n);
+		iforce_clear_xmit_and_wake(iforce);
 	}
 
 	/* The IFORCE_XMIT_RUNNING bit is not cleared here. That's intended.
@@ -92,7 +92,7 @@
 				 id,
 				 USB_TYPE_VENDOR | USB_DIR_IN |
 					USB_RECIP_INTERFACE,
-				 0, 0, buf, IFORCE_MAX_LENGTH, HZ);
+				 0, 0, buf, IFORCE_MAX_LENGTH, 1000);
 	if (status < 0) {
 		dev_err(&iforce_usb->intf->dev,
 			"usb_submit_urb failed: %d\n", status);
@@ -175,15 +175,15 @@
 	struct iforce *iforce = &iforce_usb->iforce;
 
 	if (urb->status) {
-		clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags);
 		dev_dbg(&iforce_usb->intf->dev, "urb->status %d, exiting\n",
 			urb->status);
+		iforce_clear_xmit_and_wake(iforce);
 		return;
 	}
 
 	__iforce_usb_xmit(iforce);
 
-	wake_up(&iforce->wait);
+	wake_up_all(&iforce->wait);
 }
 
 static int iforce_usb_probe(struct usb_interface *intf,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/joystick/iforce/iforce.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/joystick/iforce/iforce.h
@@ -119,6 +119,12 @@
 					 response_data, response_len);
 }
 
+static inline void iforce_clear_xmit_and_wake(struct iforce *iforce)
+{
+	clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags);
+	wake_up_all(&iforce->wait);
+}
+
 /* Public functions */
 /* iforce-main.c */
 int iforce_init_device(struct device *parent, u16 bustype,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/joystick/psxpad-spi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/joystick/psxpad-spi.c
@@ -292,7 +292,7 @@
 	if (!pad)
 		return -ENOMEM;
 
-	pdev = input_allocate_polled_device();
+	pdev = devm_input_allocate_polled_device(&spi->dev);
 	if (!pdev) {
 		dev_err(&spi->dev, "failed to allocate input device\n");
 		return -ENOMEM;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/joystick/spaceball.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/joystick/spaceball.c
@@ -19,6 +19,7 @@
 #include <linux/module.h>
 #include <linux/input.h>
 #include <linux/serio.h>
+#include <asm/unaligned.h>
 
 #define DRIVER_DESC	"SpaceTec SpaceBall 2003/3003/4000 FLX driver"
 
@@ -75,9 +76,15 @@
 
 		case 'D':					/* Ball data */
 			if (spaceball->idx != 15) return;
-			for (i = 0; i < 6; i++)
+			/*
+			 * Skip first three bytes; read six axes worth of data.
+			 * Axis values are signed 16-bit big-endian.
+			 */
+			data += 3;
+			for (i = 0; i < ARRAY_SIZE(spaceball_axes); i++) {
 				input_report_abs(dev, spaceball_axes[i],
-					(__s16)((data[2 * i + 3] << 8) | data[2 * i + 2]));
+					(__s16)get_unaligned_be16(&data[i * 2]));
+			}
 			break;
 
 		case 'K':					/* Button data */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/joystick/xpad.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/joystick/xpad.c
@@ -112,11 +112,14 @@
 	u8 xtype;
 } xpad_device[] = {
 	{ 0x0079, 0x18d4, "GPD Win 2 X-Box Controller", 0, XTYPE_XBOX360 },
+	{ 0x03eb, 0xff01, "Wooting One (Legacy)", 0, XTYPE_XBOX360 },
+	{ 0x03eb, 0xff02, "Wooting Two (Legacy)", 0, XTYPE_XBOX360 },
 	{ 0x044f, 0x0f00, "Thrustmaster Wheel", 0, XTYPE_XBOX },
 	{ 0x044f, 0x0f03, "Thrustmaster Wheel", 0, XTYPE_XBOX },
 	{ 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX },
 	{ 0x044f, 0x0f10, "Thrustmaster Modena GT Wheel", 0, XTYPE_XBOX },
 	{ 0x044f, 0xb326, "Thrustmaster Gamepad GP XID", 0, XTYPE_XBOX360 },
+	{ 0x03f0, 0x0495, "HyperX Clutch Gladiate", 0, XTYPE_XBOXONE },
 	{ 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", 0, XTYPE_XBOX },
 	{ 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", 0, XTYPE_XBOX },
 	{ 0x045e, 0x0287, "Microsoft Xbox Controller S", 0, XTYPE_XBOX },
@@ -125,6 +128,7 @@
 	{ 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 },
 	{ 0x045e, 0x028f, "Microsoft X-Box 360 pad v2", 0, XTYPE_XBOX360 },
 	{ 0x045e, 0x0291, "Xbox 360 Wireless Receiver (XBOX)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W },
+	{ 0x045e, 0x02a9, "Xbox 360 Wireless Receiver (Unofficial)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W },
 	{ 0x045e, 0x02d1, "Microsoft X-Box One pad", 0, XTYPE_XBOXONE },
 	{ 0x045e, 0x02dd, "Microsoft X-Box One pad (Firmware 2015)", 0, XTYPE_XBOXONE },
 	{ 0x045e, 0x02e3, "Microsoft X-Box One Elite pad", 0, XTYPE_XBOXONE },
@@ -215,9 +219,17 @@
 	{ 0x0e6f, 0x0213, "Afterglow Gamepad for Xbox 360", 0, XTYPE_XBOX360 },
 	{ 0x0e6f, 0x021f, "Rock Candy Gamepad for Xbox 360", 0, XTYPE_XBOX360 },
 	{ 0x0e6f, 0x0246, "Rock Candy Gamepad for Xbox One 2015", 0, XTYPE_XBOXONE },
-	{ 0x0e6f, 0x02ab, "PDP Controller for Xbox One", 0, XTYPE_XBOXONE },
+	{ 0x0e6f, 0x02a0, "PDP Xbox One Controller", 0, XTYPE_XBOXONE },
+	{ 0x0e6f, 0x02a1, "PDP Xbox One Controller", 0, XTYPE_XBOXONE },
+	{ 0x0e6f, 0x02a2, "PDP Wired Controller for Xbox One - Crimson Red", 0, XTYPE_XBOXONE },
 	{ 0x0e6f, 0x02a4, "PDP Wired Controller for Xbox One - Stealth Series", 0, XTYPE_XBOXONE },
 	{ 0x0e6f, 0x02a6, "PDP Wired Controller for Xbox One - Camo Series", 0, XTYPE_XBOXONE },
+	{ 0x0e6f, 0x02a7, "PDP Xbox One Controller", 0, XTYPE_XBOXONE },
+	{ 0x0e6f, 0x02a8, "PDP Xbox One Controller", 0, XTYPE_XBOXONE },
+	{ 0x0e6f, 0x02ab, "PDP Controller for Xbox One", 0, XTYPE_XBOXONE },
+	{ 0x0e6f, 0x02ad, "PDP Wired Controller for Xbox One - Stealth Series", 0, XTYPE_XBOXONE },
+	{ 0x0e6f, 0x02b3, "Afterglow Prismatic Wired Controller", 0, XTYPE_XBOXONE },
+	{ 0x0e6f, 0x02b8, "Afterglow Prismatic Wired Controller", 0, XTYPE_XBOXONE },
 	{ 0x0e6f, 0x0301, "Logic3 Controller", 0, XTYPE_XBOX360 },
 	{ 0x0e6f, 0x0346, "Rock Candy Gamepad for Xbox One 2016", 0, XTYPE_XBOXONE },
 	{ 0x0e6f, 0x0401, "Logic3 Controller", 0, XTYPE_XBOX360 },
@@ -234,6 +246,7 @@
 	{ 0x0f0d, 0x0063, "Hori Real Arcade Pro Hayabusa (USA) Xbox One", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE },
 	{ 0x0f0d, 0x0067, "HORIPAD ONE", 0, XTYPE_XBOXONE },
 	{ 0x0f0d, 0x0078, "Hori Real Arcade Pro V Kai Xbox One", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE },
+	{ 0x0f0d, 0x00c5, "Hori Fighting Commander ONE", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE },
 	{ 0x0f30, 0x010b, "Philips Recoil", 0, XTYPE_XBOX },
 	{ 0x0f30, 0x0202, "Joytech Advanced Controller", 0, XTYPE_XBOX },
 	{ 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX },
@@ -241,6 +254,8 @@
 	{ 0x1038, 0x1430, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 },
 	{ 0x1038, 0x1431, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 },
 	{ 0x11c9, 0x55f0, "Nacon GC-100XF", 0, XTYPE_XBOX360 },
+	{ 0x11ff, 0x0511, "PXN V900", 0, XTYPE_XBOX360 },
+	{ 0x1209, 0x2882, "Ardwiino Controller", 0, XTYPE_XBOX360 },
 	{ 0x12ab, 0x0004, "Honey Bee Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
 	{ 0x12ab, 0x0301, "PDP AFTERGLOW AX.1", 0, XTYPE_XBOX360 },
 	{ 0x12ab, 0x0303, "Mortal Kombat Klassic FightStick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
@@ -249,9 +264,10 @@
 	{ 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX },
 	{ 0x1430, 0xf801, "RedOctane Controller", 0, XTYPE_XBOX360 },
 	{ 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", 0, XTYPE_XBOX360 },
-	{ 0x1532, 0x0037, "Razer Sabertooth", 0, XTYPE_XBOX360 },
+	{ 0x146b, 0x0604, "Bigben Interactive DAIJA Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
 	{ 0x1532, 0x0a00, "Razer Atrox Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE },
 	{ 0x1532, 0x0a03, "Razer Wildcat", 0, XTYPE_XBOXONE },
+	{ 0x1532, 0x0a29, "Razer Wolverine V2", 0, XTYPE_XBOXONE },
 	{ 0x15e4, 0x3f00, "Power A Mini Pro Elite", 0, XTYPE_XBOX360 },
 	{ 0x15e4, 0x3f0a, "Xbox Airflo wired controller", 0, XTYPE_XBOX360 },
 	{ 0x15e4, 0x3f10, "Batarang Xbox 360 controller", 0, XTYPE_XBOX360 },
@@ -295,6 +311,10 @@
 	{ 0x1bad, 0xfa01, "MadCatz GamePad", 0, XTYPE_XBOX360 },
 	{ 0x1bad, 0xfd00, "Razer Onza TE", 0, XTYPE_XBOX360 },
 	{ 0x1bad, 0xfd01, "Razer Onza", 0, XTYPE_XBOX360 },
+	{ 0x20d6, 0x2001, "BDA Xbox Series X Wired Controller", 0, XTYPE_XBOXONE },
+	{ 0x20d6, 0x2009, "PowerA Enhanced Wired Controller for Xbox Series X|S", 0, XTYPE_XBOXONE },
+	{ 0x20d6, 0x281f, "PowerA Wired Controller For Xbox 360", 0, XTYPE_XBOX360 },
+	{ 0x2e24, 0x0652, "Hyperkin Duke X-Box One pad", 0, XTYPE_XBOXONE },
 	{ 0x24c6, 0x5000, "Razer Atrox Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
 	{ 0x24c6, 0x5300, "PowerA MINI PROEX Controller", 0, XTYPE_XBOX360 },
 	{ 0x24c6, 0x5303, "Xbox Airflo wired controller", 0, XTYPE_XBOX360 },
@@ -309,6 +329,7 @@
 	{ 0x24c6, 0x5502, "Hori Fighting Stick VX Alt", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
 	{ 0x24c6, 0x5503, "Hori Fighting Edge", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
 	{ 0x24c6, 0x5506, "Hori SOULCALIBUR V Stick", 0, XTYPE_XBOX360 },
+	{ 0x24c6, 0x5510, "Hori Fighting Commander ONE (Xbox 360/PC Mode)", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
 	{ 0x24c6, 0x550d, "Hori GEM Xbox controller", 0, XTYPE_XBOX360 },
 	{ 0x24c6, 0x550e, "Hori Real Arcade Pro V Kai 360", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
 	{ 0x24c6, 0x551a, "PowerA FUSION Pro Controller", 0, XTYPE_XBOXONE },
@@ -318,6 +339,16 @@
 	{ 0x24c6, 0x5b03, "Thrustmaster Ferrari 458 Racing Wheel", 0, XTYPE_XBOX360 },
 	{ 0x24c6, 0x5d04, "Razer Sabertooth", 0, XTYPE_XBOX360 },
 	{ 0x24c6, 0xfafe, "Rock Candy Gamepad for Xbox 360", 0, XTYPE_XBOX360 },
+	{ 0x2563, 0x058d, "OneXPlayer Gamepad", 0, XTYPE_XBOX360 },
+	{ 0x2dc8, 0x2000, "8BitDo Pro 2 Wired Controller fox Xbox", 0, XTYPE_XBOXONE },
+	{ 0x31e3, 0x1100, "Wooting One", 0, XTYPE_XBOX360 },
+	{ 0x31e3, 0x1200, "Wooting Two", 0, XTYPE_XBOX360 },
+	{ 0x31e3, 0x1210, "Wooting Lekker", 0, XTYPE_XBOX360 },
+	{ 0x31e3, 0x1220, "Wooting Two HE", 0, XTYPE_XBOX360 },
+	{ 0x31e3, 0x1230, "Wooting Two HE (ARM)", 0, XTYPE_XBOX360 },
+	{ 0x31e3, 0x1300, "Wooting 60HE (AVR)", 0, XTYPE_XBOX360 },
+	{ 0x31e3, 0x1310, "Wooting 60HE (ARM)", 0, XTYPE_XBOX360 },
+	{ 0x3285, 0x0607, "Nacon GC-100", 0, XTYPE_XBOX360 },
 	{ 0x3767, 0x0101, "Fanatec Speedster 3 Forceshock Wheel", 0, XTYPE_XBOX },
 	{ 0xffff, 0xffff, "Chinese-made Xbox Controller", 0, XTYPE_XBOX },
 	{ 0x0000, 0x0000, "Generic X-Box pad", 0, XTYPE_UNKNOWN }
@@ -402,7 +433,9 @@
 static const struct usb_device_id xpad_table[] = {
 	{ USB_INTERFACE_INFO('X', 'B', 0) },	/* X-Box USB-IF not approved class */
 	XPAD_XBOX360_VENDOR(0x0079),		/* GPD Win 2 Controller */
+	XPAD_XBOX360_VENDOR(0x03eb),		/* Wooting Keyboards (Legacy) */
 	XPAD_XBOX360_VENDOR(0x044f),		/* Thrustmaster X-Box 360 controllers */
+	XPAD_XBOXONE_VENDOR(0x03f0),		/* HP HyperX Xbox One Controllers */
 	XPAD_XBOX360_VENDOR(0x045e),		/* Microsoft X-Box 360 controllers */
 	XPAD_XBOXONE_VENDOR(0x045e),		/* Microsoft X-Box One controllers */
 	XPAD_XBOX360_VENDOR(0x046d),		/* Logitech X-Box 360 style controllers */
@@ -412,12 +445,15 @@
 	{ USB_DEVICE(0x0738, 0x4540) },		/* Mad Catz Beat Pad */
 	XPAD_XBOXONE_VENDOR(0x0738),		/* Mad Catz FightStick TE 2 */
 	XPAD_XBOX360_VENDOR(0x07ff),		/* Mad Catz GamePad */
+	XPAD_XBOX360_VENDOR(0x0c12),		/* Zeroplus X-Box 360 controllers */
 	XPAD_XBOX360_VENDOR(0x0e6f),		/* 0x0e6f X-Box 360 controllers */
 	XPAD_XBOXONE_VENDOR(0x0e6f),		/* 0x0e6f X-Box One controllers */
 	XPAD_XBOX360_VENDOR(0x0f0d),		/* Hori Controllers */
 	XPAD_XBOXONE_VENDOR(0x0f0d),		/* Hori Controllers */
 	XPAD_XBOX360_VENDOR(0x1038),		/* SteelSeries Controllers */
 	XPAD_XBOX360_VENDOR(0x11c9),		/* Nacon GC100XF */
+	XPAD_XBOX360_VENDOR(0x11ff),		/* PXN V900 */
+	XPAD_XBOX360_VENDOR(0x1209),		/* Ardwiino Controllers */
 	XPAD_XBOX360_VENDOR(0x12ab),		/* X-Box 360 dance pads */
 	XPAD_XBOX360_VENDOR(0x1430),		/* RedOctane X-Box 360 controllers */
 	XPAD_XBOX360_VENDOR(0x146b),		/* BigBen Interactive Controllers */
@@ -427,8 +463,17 @@
 	XPAD_XBOX360_VENDOR(0x162e),		/* Joytech X-Box 360 controllers */
 	XPAD_XBOX360_VENDOR(0x1689),		/* Razer Onza */
 	XPAD_XBOX360_VENDOR(0x1bad),		/* Harminix Rock Band Guitar and Drums */
+	XPAD_XBOX360_VENDOR(0x20d6),		/* PowerA Controllers */
+	XPAD_XBOXONE_VENDOR(0x20d6),		/* PowerA Controllers */
 	XPAD_XBOX360_VENDOR(0x24c6),		/* PowerA Controllers */
 	XPAD_XBOXONE_VENDOR(0x24c6),		/* PowerA Controllers */
+	XPAD_XBOX360_VENDOR(0x2563),		/* OneXPlayer Gamepad */
+	XPAD_XBOX360_VENDOR(0x260d),		/* Dareu H101 */
+	XPAD_XBOXONE_VENDOR(0x2dc8),		/* 8BitDo Pro 2 Wired Controller for Xbox */
+	XPAD_XBOXONE_VENDOR(0x2e24),		/* Hyperkin Duke X-Box One pad */
+	XPAD_XBOX360_VENDOR(0x2f24),		/* GameSir Controllers */
+	XPAD_XBOX360_VENDOR(0x31e3),		/* Wooting Keyboards */
+	XPAD_XBOX360_VENDOR(0x3285),		/* Nacon GC-100 */
 	{ }
 };
 
@@ -450,6 +495,9 @@
 	}
 
 
+#define GIP_WIRED_INTF_DATA 0
+#define GIP_WIRED_INTF_AUDIO 1
+
 /*
  * This packet is required for all Xbox One pads with 2015
  * or later firmware installed (or present from the factory).
@@ -459,6 +507,16 @@
 };
 
 /*
+ * This packet is required for Xbox One S (0x045e:0x02ea)
+ * and Xbox One Elite Series 2 (0x045e:0x0b00) pads to
+ * initialize the controller that was previously used in
+ * Bluetooth mode.
+ */
+static const u8 xboxone_s_init[] = {
+	0x05, 0x20, 0x00, 0x0f, 0x06
+};
+
+/*
  * This packet is required for the Titanfall 2 Xbox One pads
  * (0x0e6f:0x0165) to finish initialization and for Hori pads
  * (0x0f0d:0x0067) to make the analog sticks work.
@@ -516,6 +574,8 @@
 	XBOXONE_INIT_PKT(0x0e6f, 0x0165, xboxone_hori_init),
 	XBOXONE_INIT_PKT(0x0f0d, 0x0067, xboxone_hori_init),
 	XBOXONE_INIT_PKT(0x0000, 0x0000, xboxone_fw2015_init),
+	XBOXONE_INIT_PKT(0x045e, 0x02ea, xboxone_s_init),
+	XBOXONE_INIT_PKT(0x045e, 0x0b00, xboxone_s_init),
 	XBOXONE_INIT_PKT(0x0e6f, 0x0000, xboxone_pdp_init1),
 	XBOXONE_INIT_PKT(0x0e6f, 0x0000, xboxone_pdp_init2),
 	XBOXONE_INIT_PKT(0x24c6, 0x541a, xboxone_rumblebegin_init),
@@ -1762,7 +1822,7 @@
 	}
 
 	if (xpad->xtype == XTYPE_XBOXONE &&
-	    intf->cur_altsetting->desc.bInterfaceNumber != 0) {
+	    intf->cur_altsetting->desc.bInterfaceNumber != GIP_WIRED_INTF_DATA) {
 		/*
 		 * The Xbox One controller lists three interfaces all with the
 		 * same interface class, subclass and protocol. Differentiate by
@@ -1932,7 +1992,6 @@
 	.disconnect	= xpad_disconnect,
 	.suspend	= xpad_suspend,
 	.resume		= xpad_resume,
-	.reset_resume	= xpad_resume,
 	.id_table	= xpad_table,
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/keyboard/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/keyboard/Kconfig
@@ -68,9 +68,6 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called amikbd.
 
-config ATARI_KBD_CORE
-	bool
-
 config KEYBOARD_APPLESPI
 	tristate "Apple SPI keyboard and trackpad"
 	depends on ACPI && EFI
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/keyboard/adp5589-keys.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/keyboard/adp5589-keys.c
@@ -390,10 +390,17 @@
 	struct adp5589_kpad *kpad = gpiochip_get_data(chip);
 	unsigned int bank = kpad->var->bank(kpad->gpiomap[off]);
 	unsigned int bit = kpad->var->bit(kpad->gpiomap[off]);
+	int val;
 
-	return !!(adp5589_read(kpad->client,
-			       kpad->var->reg(ADP5589_GPI_STATUS_A) + bank) &
-			       bit);
+	mutex_lock(&kpad->gpio_lock);
+	if (kpad->dir[bank] & bit)
+		val = kpad->dat_out[bank];
+	else
+		val = adp5589_read(kpad->client,
+				   kpad->var->reg(ADP5589_GPI_STATUS_A) + bank);
+	mutex_unlock(&kpad->gpio_lock);
+
+	return !!(val & bit);
 }
 
 static void adp5589_gpio_set_value(struct gpio_chip *chip,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/keyboard/applespi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/keyboard/applespi.c
@@ -48,6 +48,7 @@
 #include <linux/efi.h>
 #include <linux/input.h>
 #include <linux/input/mt.h>
+#include <linux/ktime.h>
 #include <linux/leds.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
@@ -400,7 +401,7 @@
 	unsigned int			cmd_msg_cntr;
 	/* lock to protect the above parameters and flags below */
 	spinlock_t			cmd_msg_lock;
-	bool				cmd_msg_queued;
+	ktime_t				cmd_msg_queued;
 	enum applespi_evt_type		cmd_evt_type;
 
 	struct led_classdev		backlight_info;
@@ -716,7 +717,7 @@
 		wake_up_all(&applespi->drain_complete);
 
 	if (is_write_msg) {
-		applespi->cmd_msg_queued = false;
+		applespi->cmd_msg_queued = 0;
 		applespi_send_cmd_msg(applespi);
 	}
 
@@ -758,8 +759,16 @@
 		return 0;
 
 	/* check whether send is in progress */
-	if (applespi->cmd_msg_queued)
-		return 0;
+	if (applespi->cmd_msg_queued) {
+		if (ktime_ms_delta(ktime_get(), applespi->cmd_msg_queued) < 1000)
+			return 0;
+
+		dev_warn(&applespi->spi->dev, "Command %d timed out\n",
+			 applespi->cmd_evt_type);
+
+		applespi->cmd_msg_queued = 0;
+		applespi->write_active = false;
+	}
 
 	/* set up packet */
 	memset(packet, 0, APPLESPI_PACKET_SIZE);
@@ -856,7 +865,7 @@
 		return sts;
 	}
 
-	applespi->cmd_msg_queued = true;
+	applespi->cmd_msg_queued = ktime_get_coarse();
 	applespi->write_active = true;
 
 	return 0;
@@ -1908,7 +1917,7 @@
 	applespi->drain = false;
 	applespi->have_cl_led_on = false;
 	applespi->have_bl_level = 0;
-	applespi->cmd_msg_queued = false;
+	applespi->cmd_msg_queued = 0;
 	applespi->read_active = false;
 	applespi->write_active = false;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/keyboard/atkbd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/keyboard/atkbd.c
@@ -84,7 +84,7 @@
 	  0, 46, 45, 32, 18,  5,  4, 95,  0, 57, 47, 33, 20, 19,  6,183,
 	  0, 49, 48, 35, 34, 21,  7,184,  0,  0, 50, 36, 22,  8,  9,185,
 	  0, 51, 37, 23, 24, 11, 10,  0,  0, 52, 53, 38, 39, 25, 12,  0,
-	  0, 89, 40,  0, 26, 13,  0,  0, 58, 54, 28, 27,  0, 43,  0, 85,
+	  0, 89, 40,  0, 26, 13,  0,193, 58, 54, 28, 27,  0, 43,  0, 85,
 	  0, 86, 91, 90, 92,  0, 14, 94,  0, 79,124, 75, 71,121,  0,  0,
 	 82, 83, 80, 76, 77, 72,  1, 69, 87, 78, 81, 74, 55, 73, 70, 99,
 
@@ -715,6 +715,44 @@
 			ps2dev->serio->phys);
 }
 
+#ifdef CONFIG_X86
+static bool atkbd_is_portable_device(void)
+{
+	static const char * const chassis_types[] = {
+		"8",	/* Portable */
+		"9",	/* Laptop */
+		"10",	/* Notebook */
+		"14",	/* Sub-Notebook */
+		"31",	/* Convertible */
+		"32",	/* Detachable */
+	};
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(chassis_types); i++)
+		if (dmi_match(DMI_CHASSIS_TYPE, chassis_types[i]))
+			return true;
+
+	return false;
+}
+
+/*
+ * On many modern laptops ATKBD_CMD_GETID may cause problems, on these laptops
+ * the controller is always in translated mode. In this mode mice/touchpads will
+ * not work. So in this case simply assume a keyboard is connected to avoid
+ * confusing some laptop keyboards.
+ *
+ * Skipping ATKBD_CMD_GETID ends up using a fake keyboard id. Using the standard
+ * 0xab83 id is ok in translated mode, only atkbd_select_set() checks atkbd->id
+ * and in translated mode that is a no-op.
+ */
+static bool atkbd_skip_getid(struct atkbd *atkbd)
+{
+	return atkbd->translated && atkbd_is_portable_device();
+}
+#else
+static inline bool atkbd_skip_getid(struct atkbd *atkbd) { return false; }
+#endif
+
 /*
  * atkbd_probe() probes for an AT keyboard on a serio port.
  */
@@ -736,6 +774,11 @@
 				 "keyboard reset failed on %s\n",
 				 ps2dev->serio->phys);
 
+	if (atkbd_skip_getid(atkbd)) {
+		atkbd->id = 0xab83;
+		return 0;
+	}
+
 /*
  * Then we check the keyboard ID. We should get 0xab83 under normal conditions.
  * Some keyboards report different values, but the first byte is always 0xab or
@@ -747,9 +790,9 @@
 	if (ps2_command(ps2dev, param, ATKBD_CMD_GETID)) {
 
 /*
- * If the get ID command failed, we check if we can at least set the LEDs on
- * the keyboard. This should work on every keyboard out there. It also turns
- * the LEDs off, which we want anyway.
+ * If the get ID command failed, we check if we can at least set
+ * the LEDs on the keyboard. This should work on every keyboard out there.
+ * It also turns the LEDs off, which we want anyway.
  */
 		param[0] = 0;
 		if (ps2_command(ps2dev, param, ATKBD_CMD_SETLEDS))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/keyboard/cros_ec_keyb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/keyboard/cros_ec_keyb.c
@@ -183,6 +183,7 @@
 					"changed: [r%d c%d]: byte %02x\n",
 					row, col, new_state);
 
+				input_event(idev, EV_MSC, MSC_SCAN, pos);
 				input_report_key(idev, keycodes[pos],
 						 new_state);
 			}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/keyboard/dlink-dir685-touchkeys.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/keyboard/dlink-dir685-touchkeys.c
@@ -143,7 +143,7 @@
 
 static struct i2c_driver dir685_tk_i2c_driver = {
 	.driver = {
-		.name	= "dlin-dir685-touchkeys",
+		.name	= "dlink-dir685-touchkeys",
 		.of_match_table = of_match_ptr(dir685_tk_of_match),
 	},
 	.probe		= dir685_tk_probe,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/keyboard/ep93xx_keypad.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/keyboard/ep93xx_keypad.c
@@ -250,8 +250,8 @@
 	}
 
 	keypad->irq = platform_get_irq(pdev, 0);
-	if (!keypad->irq) {
-		err = -ENXIO;
+	if (keypad->irq < 0) {
+		err = keypad->irq;
 		goto failed_free;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/keyboard/gpio_keys_polled.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/keyboard/gpio_keys_polled.c
@@ -325,12 +325,10 @@
 
 			error = devm_gpio_request_one(dev, button->gpio,
 					flags, button->desc ? : DRV_NAME);
-			if (error) {
-				dev_err(dev,
-					"unable to claim gpio %u, err=%d\n",
-					button->gpio, error);
-				return error;
-			}
+			if (error)
+				return dev_err_probe(dev, error,
+						     "unable to claim gpio %u\n",
+						     button->gpio);
 
 			bdata->gpiod = gpio_to_desc(button->gpio);
 			if (!bdata->gpiod) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/keyboard/hil_kbd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/keyboard/hil_kbd.c
@@ -512,6 +512,7 @@
 		    HIL_IDD_NUM_AXES_PER_SET(*idd)) {
 			printk(KERN_INFO PREFIX
 				"combo devices are not supported.\n");
+			error = -EINVAL;
 			goto bail1;
 		}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/keyboard/ipaq-micro-keys.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/keyboard/ipaq-micro-keys.c
@@ -105,6 +105,9 @@
 	keys->codes = devm_kmemdup(&pdev->dev, micro_keycodes,
 			   keys->input->keycodesize * keys->input->keycodemax,
 			   GFP_KERNEL);
+	if (!keys->codes)
+		return -ENOMEM;
+
 	keys->input->keycode = keys->codes;
 
 	__set_bit(EV_KEY, keys->input->evbit);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/keyboard/nspire-keypad.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/keyboard/nspire-keypad.c
@@ -93,9 +93,15 @@
 	return IRQ_HANDLED;
 }
 
-static int nspire_keypad_chip_init(struct nspire_keypad *keypad)
+static int nspire_keypad_open(struct input_dev *input)
 {
+	struct nspire_keypad *keypad = input_get_drvdata(input);
 	unsigned long val = 0, cycles_per_us, delay_cycles, row_delay_cycles;
+	int error;
+
+	error = clk_prepare_enable(keypad->clk);
+	if (error)
+		return error;
 
 	cycles_per_us = (clk_get_rate(keypad->clk) / 1000000);
 	if (cycles_per_us == 0)
@@ -121,30 +127,6 @@
 	keypad->int_mask = 1 << 1;
 	writel(keypad->int_mask, keypad->reg_base + KEYPAD_INTMSK);
 
-	/* Disable GPIO interrupts to prevent hanging on touchpad */
-	/* Possibly used to detect touchpad events */
-	writel(0, keypad->reg_base + KEYPAD_UNKNOWN_INT);
-	/* Acknowledge existing interrupts */
-	writel(~0, keypad->reg_base + KEYPAD_UNKNOWN_INT_STS);
-
-	return 0;
-}
-
-static int nspire_keypad_open(struct input_dev *input)
-{
-	struct nspire_keypad *keypad = input_get_drvdata(input);
-	int error;
-
-	error = clk_prepare_enable(keypad->clk);
-	if (error)
-		return error;
-
-	error = nspire_keypad_chip_init(keypad);
-	if (error) {
-		clk_disable_unprepare(keypad->clk);
-		return error;
-	}
-
 	return 0;
 }
 
@@ -152,6 +134,11 @@
 {
 	struct nspire_keypad *keypad = input_get_drvdata(input);
 
+	/* Disable interrupts */
+	writel(0, keypad->reg_base + KEYPAD_INTMSK);
+	/* Acknowledge existing interrupts */
+	writel(~0, keypad->reg_base + KEYPAD_INT);
+
 	clk_disable_unprepare(keypad->clk);
 }
 
@@ -210,6 +197,25 @@
 		return -ENOMEM;
 	}
 
+	error = clk_prepare_enable(keypad->clk);
+	if (error) {
+		dev_err(&pdev->dev, "failed to enable clock\n");
+		return error;
+	}
+
+	/* Disable interrupts */
+	writel(0, keypad->reg_base + KEYPAD_INTMSK);
+	/* Acknowledge existing interrupts */
+	writel(~0, keypad->reg_base + KEYPAD_INT);
+
+	/* Disable GPIO interrupts to prevent hanging on touchpad */
+	/* Possibly used to detect touchpad events */
+	writel(0, keypad->reg_base + KEYPAD_UNKNOWN_INT);
+	/* Acknowledge existing GPIO interrupts */
+	writel(~0, keypad->reg_base + KEYPAD_UNKNOWN_INT_STS);
+
+	clk_disable_unprepare(keypad->clk);
+
 	input_set_drvdata(input, keypad);
 
 	input->id.bustype = BUS_HOST;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/keyboard/omap-keypad.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/keyboard/omap-keypad.c
@@ -46,7 +46,7 @@
 	unsigned short keymap[];
 };
 
-static DECLARE_TASKLET_DISABLED(kp_tasklet, omap_kp_tasklet, 0);
+static DECLARE_TASKLET_DISABLED_OLD(kp_tasklet, omap_kp_tasklet);
 
 static unsigned int *row_gpios;
 static unsigned int *col_gpios;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/keyboard/omap4-keypad.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/keyboard/omap4-keypad.c
@@ -186,12 +186,8 @@
 	return 0;
 }
 
-static void omap4_keypad_close(struct input_dev *input)
+static void omap4_keypad_stop(struct omap4_keypad *keypad_data)
 {
-	struct omap4_keypad *keypad_data = input_get_drvdata(input);
-
-	disable_irq(keypad_data->irq);
-
 	/* Disable interrupts and wake-up events */
 	kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE,
 			 OMAP4_VAL_IRQDISABLE);
@@ -200,7 +196,15 @@
 	/* clear pending interrupts */
 	kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,
 			 kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS));
+}
+
+static void omap4_keypad_close(struct input_dev *input)
+{
+	struct omap4_keypad *keypad_data;
 
+	keypad_data = input_get_drvdata(input);
+	disable_irq(keypad_data->irq);
+	omap4_keypad_stop(keypad_data);
 	enable_irq(keypad_data->irq);
 
 	pm_runtime_put_sync(input->dev.parent);
@@ -223,13 +227,37 @@
 	return 0;
 }
 
+static int omap4_keypad_check_revision(struct device *dev,
+				       struct omap4_keypad *keypad_data)
+{
+	unsigned int rev;
+
+	rev = __raw_readl(keypad_data->base + OMAP4_KBD_REVISION);
+	rev &= 0x03 << 30;
+	rev >>= 30;
+	switch (rev) {
+	case KBD_REVISION_OMAP4:
+		keypad_data->reg_offset = 0x00;
+		keypad_data->irqreg_offset = 0x00;
+		break;
+	case KBD_REVISION_OMAP5:
+		keypad_data->reg_offset = 0x10;
+		keypad_data->irqreg_offset = 0x0c;
+		break;
+	default:
+		dev_err(dev, "Keypad reports unsupported revision %d", rev);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static int omap4_keypad_probe(struct platform_device *pdev)
 {
 	struct omap4_keypad *keypad_data;
 	struct input_dev *input_dev;
 	struct resource *res;
 	unsigned int max_keys;
-	int rev;
 	int irq;
 	int error;
 
@@ -240,10 +268,8 @@
 	}
 
 	irq = platform_get_irq(pdev, 0);
-	if (!irq) {
-		dev_err(&pdev->dev, "no keyboard irq assigned\n");
-		return -EINVAL;
-	}
+	if (irq < 0)
+		return irq;
 
 	keypad_data = kzalloc(sizeof(struct omap4_keypad), GFP_KERNEL);
 	if (!keypad_data) {
@@ -271,41 +297,33 @@
 		goto err_release_mem;
 	}
 
+	pm_runtime_enable(&pdev->dev);
 
 	/*
 	 * Enable clocks for the keypad module so that we can read
 	 * revision register.
 	 */
-	pm_runtime_enable(&pdev->dev);
 	error = pm_runtime_get_sync(&pdev->dev);
 	if (error) {
 		dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n");
-		goto err_unmap;
-	}
-	rev = __raw_readl(keypad_data->base + OMAP4_KBD_REVISION);
-	rev &= 0x03 << 30;
-	rev >>= 30;
-	switch (rev) {
-	case KBD_REVISION_OMAP4:
-		keypad_data->reg_offset = 0x00;
-		keypad_data->irqreg_offset = 0x00;
-		break;
-	case KBD_REVISION_OMAP5:
-		keypad_data->reg_offset = 0x10;
-		keypad_data->irqreg_offset = 0x0c;
-		break;
-	default:
-		dev_err(&pdev->dev,
-			"Keypad reports unsupported revision %d", rev);
-		error = -EINVAL;
-		goto err_pm_put_sync;
+		pm_runtime_put_noidle(&pdev->dev);
+	} else {
+		error = omap4_keypad_check_revision(&pdev->dev,
+						    keypad_data);
+		if (!error) {
+			/* Ensure device does not raise interrupts */
+			omap4_keypad_stop(keypad_data);
+		}
+		pm_runtime_put_sync(&pdev->dev);
 	}
+	if (error)
+		goto err_pm_disable;
 
 	/* input device allocation */
 	keypad_data->input = input_dev = input_allocate_device();
 	if (!input_dev) {
 		error = -ENOMEM;
-		goto err_pm_put_sync;
+		goto err_pm_disable;
 	}
 
 	input_dev->name = pdev->name;
@@ -351,28 +369,25 @@
 		goto err_free_keymap;
 	}
 
-	device_init_wakeup(&pdev->dev, true);
-	pm_runtime_put_sync(&pdev->dev);
-
 	error = input_register_device(keypad_data->input);
 	if (error < 0) {
 		dev_err(&pdev->dev, "failed to register input device\n");
-		goto err_pm_disable;
+		goto err_free_irq;
 	}
 
+	device_init_wakeup(&pdev->dev, true);
 	platform_set_drvdata(pdev, keypad_data);
+
 	return 0;
 
-err_pm_disable:
-	pm_runtime_disable(&pdev->dev);
+err_free_irq:
 	free_irq(keypad_data->irq, keypad_data);
 err_free_keymap:
 	kfree(keypad_data->keymap);
 err_free_input:
 	input_free_device(input_dev);
-err_pm_put_sync:
-	pm_runtime_put_sync(&pdev->dev);
-err_unmap:
+err_pm_disable:
+	pm_runtime_disable(&pdev->dev);
 	iounmap(keypad_data->base);
 err_release_mem:
 	release_mem_region(res->start, resource_size(res));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/keyboard/qt1050.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/keyboard/qt1050.c
@@ -226,7 +226,12 @@
 	int err;
 
 	/* Read Chip ID */
-	regmap_read(ts->regmap, QT1050_CHIP_ID, &val);
+	err = regmap_read(ts->regmap, QT1050_CHIP_ID, &val);
+	if (err) {
+		dev_err(&ts->client->dev, "Failed to read chip ID: %d\n", err);
+		return false;
+	}
+
 	if (val != QT1050_CHIP_ID_VER) {
 		dev_err(&ts->client->dev, "ID %d not supported\n", val);
 		return false;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/keyboard/snvs_pwrkey.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/keyboard/snvs_pwrkey.c
@@ -3,6 +3,7 @@
 // Driver for the IMX SNVS ON/OFF Power Key
 // Copyright (C) 2015 Freescale Semiconductor, Inc. All Rights Reserved.
 
+#include <linux/clk.h>
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/init.h>
@@ -81,6 +82,11 @@
 	return IRQ_HANDLED;
 }
 
+static void imx_snvs_pwrkey_disable_clk(void *data)
+{
+	clk_disable_unprepare(data);
+}
+
 static void imx_snvs_pwrkey_act(void *pdata)
 {
 	struct pwrkey_drv_data *pd = pdata;
@@ -93,6 +99,7 @@
 	struct pwrkey_drv_data *pdata = NULL;
 	struct input_dev *input = NULL;
 	struct device_node *np;
+	struct clk *clk;
 	int error;
 
 	/* Get SNVS register Page */
@@ -115,6 +122,28 @@
 		dev_warn(&pdev->dev, "KEY_POWER without setting in dts\n");
 	}
 
+	clk = devm_clk_get_optional(&pdev->dev, NULL);
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "Failed to get snvs clock (%pe)\n", clk);
+		return PTR_ERR(clk);
+	}
+
+	error = clk_prepare_enable(clk);
+	if (error) {
+		dev_err(&pdev->dev, "Failed to enable snvs clock (%pe)\n",
+			ERR_PTR(error));
+		return error;
+	}
+
+	error = devm_add_action_or_reset(&pdev->dev,
+					 imx_snvs_pwrkey_disable_clk, clk);
+	if (error) {
+		dev_err(&pdev->dev,
+			"Failed to register clock cleanup handler (%pe)\n",
+			ERR_PTR(error));
+		return error;
+	}
+
 	pdata->wakeup = of_property_read_bool(np, "wakeup-source");
 
 	pdata->irq = platform_get_irq(pdev, 0);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/keyboard/sunkbd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/keyboard/sunkbd.c
@@ -99,7 +99,8 @@
 	switch (data) {
 
 	case SUNKBD_RET_RESET:
-		schedule_work(&sunkbd->tq);
+		if (sunkbd->enabled)
+			schedule_work(&sunkbd->tq);
 		sunkbd->reset = -1;
 		break;
 
@@ -200,16 +201,12 @@
 }
 
 /*
- * sunkbd_reinit() sets leds and beeps to a state the computer remembers they
- * were in.
+ * sunkbd_set_leds_beeps() sets leds and beeps to a state the computer remembers
+ * they were in.
  */
 
-static void sunkbd_reinit(struct work_struct *work)
+static void sunkbd_set_leds_beeps(struct sunkbd *sunkbd)
 {
-	struct sunkbd *sunkbd = container_of(work, struct sunkbd, tq);
-
-	wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ);
-
 	serio_write(sunkbd->serio, SUNKBD_CMD_SETLED);
 	serio_write(sunkbd->serio,
 		(!!test_bit(LED_CAPSL,   sunkbd->dev->led) << 3) |
@@ -222,11 +219,39 @@
 		SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev->snd));
 }
 
+
+/*
+ * sunkbd_reinit() wait for the keyboard reset to complete and restores state
+ * of leds and beeps.
+ */
+
+static void sunkbd_reinit(struct work_struct *work)
+{
+	struct sunkbd *sunkbd = container_of(work, struct sunkbd, tq);
+
+	/*
+	 * It is OK that we check sunkbd->enabled without pausing serio,
+	 * as we only want to catch true->false transition that will
+	 * happen once and we will be woken up for it.
+	 */
+	wait_event_interruptible_timeout(sunkbd->wait,
+					 sunkbd->reset >= 0 || !sunkbd->enabled,
+					 HZ);
+
+	if (sunkbd->reset >= 0 && sunkbd->enabled)
+		sunkbd_set_leds_beeps(sunkbd);
+}
+
 static void sunkbd_enable(struct sunkbd *sunkbd, bool enable)
 {
 	serio_pause_rx(sunkbd->serio);
 	sunkbd->enabled = enable;
 	serio_continue_rx(sunkbd->serio);
+
+	if (!enable) {
+		wake_up_interruptible(&sunkbd->wait);
+		cancel_work_sync(&sunkbd->tq);
+	}
 }
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/keyboard/tm2-touchkey.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/keyboard/tm2-touchkey.c
@@ -75,6 +75,14 @@
 	.cmd_led_off = ARIES_TOUCHKEY_CMD_LED_OFF,
 };
 
+static const struct touchkey_variant tc360_touchkey_variant = {
+	.keycode_reg = 0x00,
+	.base_reg = 0x00,
+	.fixed_regulator = true,
+	.cmd_led_on = TM2_TOUCHKEY_CMD_LED_ON,
+	.cmd_led_off = TM2_TOUCHKEY_CMD_LED_OFF,
+};
+
 static int tm2_touchkey_led_brightness_set(struct led_classdev *led_dev,
 					    enum led_brightness brightness)
 {
@@ -327,6 +335,9 @@
 	}, {
 		.compatible = "cypress,aries-touchkey",
 		.data = &aries_touchkey_variant,
+	}, {
+		.compatible = "coreriver,tc360-touchkey",
+		.data = &tc360_touchkey_variant,
 	},
 	{ },
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/keyboard/twl4030_keypad.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/keyboard/twl4030_keypad.c
@@ -50,7 +50,7 @@
 	bool		autorepeat;
 	unsigned int	n_rows;
 	unsigned int	n_cols;
-	unsigned int	irq;
+	int		irq;
 
 	struct device *dbg_dev;
 	struct input_dev *input;
@@ -376,10 +376,8 @@
 	}
 
 	kp->irq = platform_get_irq(pdev, 0);
-	if (!kp->irq) {
-		dev_err(&pdev->dev, "no keyboard irq assigned\n");
-		return -EINVAL;
-	}
+	if (kp->irq < 0)
+		return kp->irq;
 
 	error = matrix_keypad_build_keymap(keymap_data, NULL,
 					   TWL4030_MAX_ROWS,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/misc/adxl34x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/misc/adxl34x.c
@@ -696,7 +696,7 @@
 	struct input_dev *input_dev;
 	const struct adxl34x_platform_data *pdata;
 	int err, range, i;
-	unsigned char revid;
+	int revid;
 
 	if (!irq) {
 		dev_err(dev, "no IRQ?\n");
@@ -811,8 +811,7 @@
 	AC_WRITE(ac, POWER_CTL, 0);
 
 	err = request_threaded_irq(ac->irq, NULL, adxl34x_irq,
-				   IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
-				   dev_name(dev), ac);
+				   IRQF_ONESHOT, dev_name(dev), ac);
 	if (err) {
 		dev_err(dev, "irq %d busy?\n", ac->irq);
 		goto err_free_mem;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/misc/ati_remote2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/misc/ati_remote2.c
@@ -68,7 +68,7 @@
 {
 	pr_debug("%s()\n", __func__);
 
-	return sprintf(buffer, "0x%04x", *(unsigned int *)kp->arg);
+	return sprintf(buffer, "0x%04x\n", *(unsigned int *)kp->arg);
 }
 
 static int ati_remote2_set_mode_mask(const char *val,
@@ -84,7 +84,7 @@
 {
 	pr_debug("%s()\n", __func__);
 
-	return sprintf(buffer, "0x%02x", *(unsigned int *)kp->arg);
+	return sprintf(buffer, "0x%02x\n", *(unsigned int *)kp->arg);
 }
 
 static unsigned int channel_mask = ATI_REMOTE2_MAX_CHANNEL_MASK;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/misc/cm109.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/misc/cm109.c
@@ -568,12 +568,15 @@
 	dev->ctl_data->byte[HID_OR2] = dev->keybit;
 	dev->ctl_data->byte[HID_OR3] = 0x00;
 
+	dev->ctl_urb_pending = 1;
 	error = usb_submit_urb(dev->urb_ctl, GFP_KERNEL);
-	if (error)
+	if (error) {
+		dev->ctl_urb_pending = 0;
 		dev_err(&dev->intf->dev, "%s: usb_submit_urb (urb_ctl) failed %d\n",
 			__func__, error);
-	else
+	} else {
 		dev->open = 1;
+	}
 
 	mutex_unlock(&dev->pm_mutex);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/misc/drv260x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/misc/drv260x.c
@@ -435,6 +435,7 @@
 	}
 
 	do {
+		usleep_range(15000, 15500);
 		error = regmap_read(haptics->regmap, DRV260X_GO, &cal_buf);
 		if (error) {
 			dev_err(&haptics->client->dev,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/misc/ims-pcu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/misc/ims-pcu.c
@@ -42,8 +42,8 @@
 #define IMS_PCU_PART_NUMBER_LEN		15
 #define IMS_PCU_SERIAL_NUMBER_LEN	8
 #define IMS_PCU_DOM_LEN			8
-#define IMS_PCU_FW_VERSION_LEN		(9 + 1)
-#define IMS_PCU_BL_VERSION_LEN		(9 + 1)
+#define IMS_PCU_FW_VERSION_LEN		16
+#define IMS_PCU_BL_VERSION_LEN		16
 #define IMS_PCU_BL_RESET_REASON_LEN	(2 + 1)
 
 #define IMS_PCU_PCU_B_DEVICE_ID		5
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/misc/keyspan_remote.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/misc/keyspan_remote.c
@@ -336,7 +336,8 @@
 	int retval = 0;
 
 	retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-				 0x11, 0x40, 0x5601, 0x0, NULL, 0, 0);
+				 0x11, 0x40, 0x5601, 0x0, NULL, 0,
+				 USB_CTRL_SET_TIMEOUT);
 	if (retval) {
 		dev_dbg(&dev->dev, "%s - failed to set bit rate due to error: %d\n",
 			__func__, retval);
@@ -344,7 +345,8 @@
 	}
 
 	retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-				 0x44, 0x40, 0x0, 0x0, NULL, 0, 0);
+				 0x44, 0x40, 0x0, 0x0, NULL, 0,
+				 USB_CTRL_SET_TIMEOUT);
 	if (retval) {
 		dev_dbg(&dev->dev, "%s - failed to set resume sensitivity due to error: %d\n",
 			__func__, retval);
@@ -352,7 +354,8 @@
 	}
 
 	retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-				 0x22, 0x40, 0x0, 0x0, NULL, 0, 0);
+				 0x22, 0x40, 0x0, 0x0, NULL, 0,
+				 USB_CTRL_SET_TIMEOUT);
 	if (retval) {
 		dev_dbg(&dev->dev, "%s - failed to turn receive on due to error: %d\n",
 			__func__, retval);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/misc/max77650-onkey.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/misc/max77650-onkey.c
@@ -108,9 +108,16 @@
 	return input_register_device(onkey->input);
 }
 
+static const struct of_device_id max77650_onkey_of_match[] = {
+	{ .compatible = "maxim,max77650-onkey" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, max77650_onkey_of_match);
+
 static struct platform_driver max77650_onkey_driver = {
 	.driver = {
 		.name = "max77650-onkey",
+		.of_match_table = max77650_onkey_of_match,
 	},
 	.probe = max77650_onkey_probe,
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/misc/pm8xxx-vibrator.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/misc/pm8xxx-vibrator.c
@@ -14,7 +14,8 @@
 
 #define VIB_MAX_LEVEL_mV	(3100)
 #define VIB_MIN_LEVEL_mV	(1200)
-#define VIB_MAX_LEVELS		(VIB_MAX_LEVEL_mV - VIB_MIN_LEVEL_mV)
+#define VIB_PER_STEP_mV		(100)
+#define VIB_MAX_LEVELS		(VIB_MAX_LEVEL_mV - VIB_MIN_LEVEL_mV + VIB_PER_STEP_mV)
 
 #define MAX_FF_SPEED		0xff
 
@@ -90,7 +91,7 @@
 
 	if (regs->enable_mask)
 		rc = regmap_update_bits(vib->regmap, regs->enable_addr,
-					on ? regs->enable_mask : 0, val);
+					regs->enable_mask, on ? ~0 : 0);
 
 	return rc;
 }
@@ -118,10 +119,10 @@
 		vib->active = true;
 		vib->level = ((VIB_MAX_LEVELS * vib->speed) / MAX_FF_SPEED) +
 						VIB_MIN_LEVEL_mV;
-		vib->level /= 100;
+		vib->level /= VIB_PER_STEP_mV;
 	} else {
 		vib->active = false;
-		vib->level = VIB_MIN_LEVEL_mV / 100;
+		vib->level = VIB_MIN_LEVEL_mV / VIB_PER_STEP_mV;
 	}
 
 	pm8xxx_vib_set(vib, vib->active);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/misc/powermate.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/misc/powermate.c
@@ -425,6 +425,7 @@
 		pm->requires_update = 0;
 		usb_kill_urb(pm->irq);
 		input_unregister_device(pm->input);
+		usb_kill_urb(pm->config);
 		usb_free_urb(pm->irq);
 		usb_free_urb(pm->config);
 		powermate_free_buffers(interface_to_usbdev(intf), pm);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/misc/rk805-pwrkey.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/misc/rk805-pwrkey.c
@@ -98,6 +98,7 @@
 };
 module_platform_driver(rk805_pwrkey_driver);
 
+MODULE_ALIAS("platform:rk805-pwrkey");
 MODULE_AUTHOR("Joseph Chen <chenjh@rock-chips.com>");
 MODULE_DESCRIPTION("RK805 PMIC Power Key driver");
 MODULE_LICENSE("GPL");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/misc/sparcspkr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/misc/sparcspkr.c
@@ -205,6 +205,7 @@
 
 	info = &state->u.bbc;
 	info->clock_freq = of_getintprop_default(dp, "clock-frequency", 0);
+	of_node_put(dp);
 	if (!info->clock_freq)
 		goto out_free;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/misc/uinput.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/misc/uinput.c
@@ -74,12 +74,16 @@
 	struct uinput_device	*udev = input_get_drvdata(dev);
 	struct timespec64	ts;
 
-	udev->buff[udev->head].type = type;
-	udev->buff[udev->head].code = code;
-	udev->buff[udev->head].value = value;
 	ktime_get_ts64(&ts);
-	udev->buff[udev->head].input_event_sec = ts.tv_sec;
-	udev->buff[udev->head].input_event_usec = ts.tv_nsec / NSEC_PER_USEC;
+
+	udev->buff[udev->head] = (struct input_event) {
+		.input_event_sec = ts.tv_sec,
+		.input_event_usec = ts.tv_nsec / NSEC_PER_USEC,
+		.type = type,
+		.code = code,
+		.value = value,
+	};
+
 	udev->head = (udev->head + 1) % UINPUT_BUFFER_SIZE;
 
 	wake_up_interruptible(&udev->waitq);
@@ -412,6 +416,20 @@
 		return -EINVAL;
 	}
 
+	/*
+	 * Limit number of contacts to a reasonable value (100). This
+	 * ensures that we need less than 2 pages for struct input_mt
+	 * (we are not using in-kernel slot assignment so not going to
+	 * allocate memory for the "red" table), and we should have no
+	 * trouble getting this much memory.
+	 */
+	if (code == ABS_MT_SLOT && max > 99) {
+		printk(KERN_DEBUG
+		       "%s: unreasonably large number of slots requested: %d\n",
+		       UINPUT_NAME, max);
+		return -EINVAL;
+	}
+
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/mouse/alps.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/mouse/alps.c
@@ -852,8 +852,8 @@
 			x = y = z = 0;
 
 		/* Divide 4 since trackpoint's speed is too fast */
-		input_report_rel(dev2, REL_X, (char)x / 4);
-		input_report_rel(dev2, REL_Y, -((char)y / 4));
+		input_report_rel(dev2, REL_X, (s8)x / 4);
+		input_report_rel(dev2, REL_Y, -((s8)y / 4));
 
 		psmouse_report_standard_buttons(dev2, packet[3]);
 
@@ -1104,8 +1104,8 @@
 	    ((packet[3] & 0x20) << 1);
 	z = (packet[5] & 0x3f) | ((packet[3] & 0x80) >> 1);
 
-	input_report_rel(dev2, REL_X, (char)x);
-	input_report_rel(dev2, REL_Y, -((char)y));
+	input_report_rel(dev2, REL_X, (s8)x);
+	input_report_rel(dev2, REL_Y, -((s8)y));
 	input_report_abs(dev2, ABS_PRESSURE, z);
 
 	psmouse_report_standard_buttons(dev2, packet[1]);
@@ -2294,20 +2294,20 @@
 	if (reg < 0)
 		return reg;
 
-	x_pitch = (char)(reg << 4) >> 4; /* sign extend lower 4 bits */
+	x_pitch = (s8)(reg << 4) >> 4; /* sign extend lower 4 bits */
 	x_pitch = 50 + 2 * x_pitch; /* In 0.1 mm units */
 
-	y_pitch = (char)reg >> 4; /* sign extend upper 4 bits */
+	y_pitch = (s8)reg >> 4; /* sign extend upper 4 bits */
 	y_pitch = 36 + 2 * y_pitch; /* In 0.1 mm units */
 
 	reg = alps_command_mode_read_reg(psmouse, reg_pitch + 1);
 	if (reg < 0)
 		return reg;
 
-	x_electrode = (char)(reg << 4) >> 4; /* sign extend lower 4 bits */
+	x_electrode = (s8)(reg << 4) >> 4; /* sign extend lower 4 bits */
 	x_electrode = 17 + x_electrode;
 
-	y_electrode = (char)reg >> 4; /* sign extend upper 4 bits */
+	y_electrode = (s8)reg >> 4; /* sign extend upper 4 bits */
 	y_electrode = 13 + y_electrode;
 
 	x_phys = x_pitch * (x_electrode - 1); /* In 0.1 mm units */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/mouse/appletouch.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/mouse/appletouch.c
@@ -916,6 +916,8 @@
 	set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
 	set_bit(BTN_LEFT, input_dev->keybit);
 
+	INIT_WORK(&dev->work, atp_reinit);
+
 	error = input_register_device(dev->input);
 	if (error)
 		goto err_free_buffer;
@@ -923,8 +925,6 @@
 	/* save our data pointer in this interface device */
 	usb_set_intfdata(iface, dev);
 
-	INIT_WORK(&dev->work, atp_reinit);
-
 	return 0;
 
  err_free_buffer:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/mouse/bcm5974.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/mouse/bcm5974.c
@@ -942,17 +942,22 @@
 	if (!dev->tp_data)
 		goto err_free_bt_buffer;
 
-	if (dev->bt_urb)
+	if (dev->bt_urb) {
 		usb_fill_int_urb(dev->bt_urb, udev,
 				 usb_rcvintpipe(udev, cfg->bt_ep),
 				 dev->bt_data, dev->cfg.bt_datalen,
 				 bcm5974_irq_button, dev, 1);
 
+		dev->bt_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+	}
+
 	usb_fill_int_urb(dev->tp_urb, udev,
 			 usb_rcvintpipe(udev, cfg->tp_ep),
 			 dev->tp_data, dev->cfg.tp_datalen,
 			 bcm5974_irq_trackpad, dev, 1);
 
+	dev->tp_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
 	/* create bcm5974 device */
 	usb_make_path(udev, dev->phys, sizeof(dev->phys));
 	strlcat(dev->phys, "/input0", sizeof(dev->phys));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/mouse/cyapa_gen6.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/mouse/cyapa_gen6.c
@@ -573,7 +573,7 @@
 
 	memset(&cmd, 0, sizeof(cmd));
 	put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR, &cmd.head.addr);
-	put_unaligned_le16(sizeof(cmd), &cmd.head.length - 2);
+	put_unaligned_le16(sizeof(cmd) - 2, &cmd.head.length);
 	cmd.head.report_id = PIP_APP_CMD_REPORT_ID;
 	cmd.head.cmd_code = PIP_RETRIEVE_DATA_STRUCTURE;
 	put_unaligned_le16(read_offset, &cmd.read_offset);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/mouse/cypress_ps2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/mouse/cypress_ps2.c
@@ -387,7 +387,9 @@
 	if (ret < 0)
 		return ret;
 
+#if ( CYPRESS_SIMULATED_MT != 1 )
 	__set_bit(INPUT_PROP_SEMI_MT, input->propbit);
+#endif
 
 	input_abs_set_res(input, ABS_X, cytp->tp_res_x);
 	input_abs_set_res(input, ABS_Y, cytp->tp_res_y);
@@ -473,6 +475,22 @@
 			((packet[5] & 0x0f) << 8) | packet[7];
 		if (cytp->mode & CYTP_BIT_ABS_PRESSURE)
 			report_data->contacts[1].z = report_data->contacts[0].z;
+#if ( CYPRESS_SIMULATED_MT == 1 )
+		/* simulate contact positions for >2 fingers */
+		if ( report_data->contact_cnt >= 3 ) {
+			int i;
+			for ( i=1; i<report_data->contact_cnt; i++ ) {
+			    report_data->contacts[i].x =
+					    report_data->contacts[0].x
+					    + 100*(i)*((i%2)?-1:1);
+			    report_data->contacts[i].y =
+					    report_data->contacts[0].y;
+			    if (cytp->mode & CYTP_BIT_ABS_PRESSURE)
+				    report_data->contacts[i].z =
+					    report_data->contacts[0].z;
+			}
+		}
+#endif
 	}
 
 	report_data->left = (header_byte & BTN_LEFT_BIT) ? 1 : 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/mouse/cypress_ps2.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/mouse/cypress_ps2.h
@@ -131,7 +131,18 @@
 #define RESP_REMOTE_BIT     0x40
 #define RESP_SMBUS_BIT      0x80
 
-#define CYTP_MAX_MT_SLOTS 2
+/*
+ * CYPRESS_SIMULATED_MT
+ *   set to 1 for simulated multitouch (up to 5 contact points)
+ *   set to 0 for SEMI_MT (only 2 corner points, and count of fingers)
+ */
+#define CYPRESS_SIMULATED_MT 1
+
+#if ( CYPRESS_SIMULATED_MT == 1 )
+# define CYTP_MAX_MT_SLOTS 5
+#else
+# define CYTP_MAX_MT_SLOTS 2
+#endif
 
 struct cytp_contact {
 	int x;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/mouse/elan_i2c.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/mouse/elan_i2c.h
@@ -26,6 +26,24 @@
 
 #define ETP_CALIBRATE_MAX_LEN	3
 
+#define ETP_FEATURE_REPORT_MK	BIT(0)
+
+#define ETP_REPORT_ID		0x5D
+#define ETP_TP_REPORT_ID	0x5E
+#define ETP_TP_REPORT_ID2	0x5F
+#define ETP_REPORT_ID2		0x60	/* High precision report */
+
+#define ETP_REPORT_ID_OFFSET	2
+#define ETP_TOUCH_INFO_OFFSET	3
+#define ETP_FINGER_DATA_OFFSET	4
+#define ETP_HOVER_INFO_OFFSET	30
+#define ETP_MK_DATA_OFFSET	33	/* For high precision reports */
+
+#define ETP_MAX_REPORT_LEN	39
+
+#define ETP_MAX_FINGERS		5
+#define ETP_FINGER_DATA_LEN	5
+
 /* IAP Firmware handling */
 #define ETP_PRODUCT_ID_FORMAT_STRING	"%d.0"
 #define ETP_FW_NAME		"elan_i2c_" ETP_PRODUCT_ID_FORMAT_STRING ".bin"
@@ -78,7 +96,11 @@
 	int (*finish_fw_update)(struct i2c_client *client,
 				struct completion *reset_done);
 
-	int (*get_report)(struct i2c_client *client, u8 *report);
+	int (*get_report_features)(struct i2c_client *client, u8 pattern,
+				   unsigned int *features,
+				   unsigned int *report_len);
+	int (*get_report)(struct i2c_client *client, u8 *report,
+			  unsigned int report_len);
 	int (*get_pressure_adjustment)(struct i2c_client *client,
 				       int *adjustment);
 	int (*get_pattern)(struct i2c_client *client, u8 *pattern);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/mouse/elan_i2c_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/mouse/elan_i2c_core.c
@@ -47,16 +47,6 @@
 #define ETP_FINGER_WIDTH	15
 #define ETP_RETRY_COUNT		3
 
-#define ETP_MAX_FINGERS		5
-#define ETP_FINGER_DATA_LEN	5
-#define ETP_REPORT_ID		0x5D
-#define ETP_TP_REPORT_ID	0x5E
-#define ETP_REPORT_ID_OFFSET	2
-#define ETP_TOUCH_INFO_OFFSET	3
-#define ETP_FINGER_DATA_OFFSET	4
-#define ETP_HOVER_INFO_OFFSET	30
-#define ETP_MAX_REPORT_LEN	34
-
 /* The main device structure */
 struct elan_tp_data {
 	struct i2c_client	*client;
@@ -85,6 +75,8 @@
 	u8			sm_version;
 	u8			iap_version;
 	u16			fw_checksum;
+	unsigned int		report_features;
+	unsigned int		report_len;
 	int			pressure_adjustment;
 	u8			mode;
 	u16			ic_type;
@@ -139,55 +131,21 @@
 	return 0;
 }
 
-static int elan_enable_power(struct elan_tp_data *data)
+static int elan_set_power(struct elan_tp_data *data, bool on)
 {
 	int repeat = ETP_RETRY_COUNT;
 	int error;
 
-	error = regulator_enable(data->vcc);
-	if (error) {
-		dev_err(&data->client->dev,
-			"failed to enable regulator: %d\n", error);
-		return error;
-	}
-
 	do {
-		error = data->ops->power_control(data->client, true);
+		error = data->ops->power_control(data->client, on);
 		if (error >= 0)
 			return 0;
 
 		msleep(30);
 	} while (--repeat > 0);
 
-	dev_err(&data->client->dev, "failed to enable power: %d\n", error);
-	return error;
-}
-
-static int elan_disable_power(struct elan_tp_data *data)
-{
-	int repeat = ETP_RETRY_COUNT;
-	int error;
-
-	do {
-		error = data->ops->power_control(data->client, false);
-		if (!error) {
-			error = regulator_disable(data->vcc);
-			if (error) {
-				dev_err(&data->client->dev,
-					"failed to disable regulator: %d\n",
-					error);
-				/* Attempt to power the chip back up */
-				data->ops->power_control(data->client, true);
-				break;
-			}
-
-			return 0;
-		}
-
-		msleep(30);
-	} while (--repeat > 0);
-
-	dev_err(&data->client->dev, "failed to disable power: %d\n", error);
+	dev_err(&data->client->dev, "failed to set power %s: %d\n",
+		on ? "on" : "off", error);
 	return error;
 }
 
@@ -341,6 +299,12 @@
 	else
 		ic_type = data->iap_version;
 
+	error = data->ops->get_report_features(data->client, data->pattern,
+					       &data->report_features,
+					       &data->report_len);
+	if (error)
+		return error;
+
 	error = elan_get_fwinfo(ic_type, &data->fw_validpage_count,
 				&data->fw_signature_address);
 	if (error)
@@ -351,16 +315,21 @@
 	return 0;
 }
 
-static unsigned int elan_convert_resolution(u8 val)
+static unsigned int elan_convert_resolution(u8 val, u8 pattern)
 {
 	/*
-	 * (value from firmware) * 10 + 790 = dpi
-	 *
+	 * pattern <= 0x01:
+	 *	(value from firmware) * 10 + 790 = dpi
+	 * else
+	 *	((value from firmware) + 3) * 100 = dpi
+	 */
+	int res = pattern <= 0x01 ?
+		(int)(char)val * 10 + 790 : ((int)(char)val + 3) * 100;
+	/*
 	 * We also have to convert dpi to dots/mm (*10/254 to avoid floating
 	 * point).
 	 */
-
-	return ((int)(char)val * 10 + 790) * 10 / 254;
+	return res * 10 / 254;
 }
 
 static int elan_query_device_parameters(struct elan_tp_data *data)
@@ -409,8 +378,8 @@
 		if (error)
 			return error;
 
-		data->x_res = elan_convert_resolution(hw_x_res);
-		data->y_res = elan_convert_resolution(hw_y_res);
+		data->x_res = elan_convert_resolution(hw_x_res, data->pattern);
+		data->y_res = elan_convert_resolution(hw_y_res, data->pattern);
 	} else {
 		data->x_res = (data->max_x + 1) / x_mm;
 		data->y_res = (data->max_y + 1) / y_mm;
@@ -886,24 +855,22 @@
  * Elan isr functions
  ******************************************************************
  */
-static void elan_report_contact(struct elan_tp_data *data,
-				int contact_num, bool contact_valid,
-				u8 *finger_data)
+static void elan_report_contact(struct elan_tp_data *data, int contact_num,
+				bool contact_valid, bool high_precision,
+				u8 *packet, u8 *finger_data)
 {
 	struct input_dev *input = data->input;
 	unsigned int pos_x, pos_y;
-	unsigned int pressure, mk_x, mk_y;
-	unsigned int area_x, area_y, major, minor;
-	unsigned int scaled_pressure;
+	unsigned int pressure, scaled_pressure;
 
 	if (contact_valid) {
-		pos_x = ((finger_data[0] & 0xf0) << 4) |
-						finger_data[1];
-		pos_y = ((finger_data[0] & 0x0f) << 8) |
-						finger_data[2];
-		mk_x = (finger_data[3] & 0x0f);
-		mk_y = (finger_data[3] >> 4);
-		pressure = finger_data[4];
+		if (high_precision) {
+			pos_x = get_unaligned_be16(&finger_data[0]);
+			pos_y = get_unaligned_be16(&finger_data[2]);
+		} else {
+			pos_x = ((finger_data[0] & 0xf0) << 4) | finger_data[1];
+			pos_y = ((finger_data[0] & 0x0f) << 8) | finger_data[2];
+		}
 
 		if (pos_x > data->max_x || pos_y > data->max_y) {
 			dev_dbg(input->dev.parent,
@@ -913,18 +880,8 @@
 			return;
 		}
 
-		/*
-		 * To avoid treating large finger as palm, let's reduce the
-		 * width x and y per trace.
-		 */
-		area_x = mk_x * (data->width_x - ETP_FWIDTH_REDUCE);
-		area_y = mk_y * (data->width_y - ETP_FWIDTH_REDUCE);
-
-		major = max(area_x, area_y);
-		minor = min(area_x, area_y);
-
+		pressure = finger_data[4];
 		scaled_pressure = pressure + data->pressure_adjustment;
-
 		if (scaled_pressure > ETP_MAX_PRESSURE)
 			scaled_pressure = ETP_MAX_PRESSURE;
 
@@ -933,16 +890,37 @@
 		input_report_abs(input, ABS_MT_POSITION_X, pos_x);
 		input_report_abs(input, ABS_MT_POSITION_Y, data->max_y - pos_y);
 		input_report_abs(input, ABS_MT_PRESSURE, scaled_pressure);
-		input_report_abs(input, ABS_TOOL_WIDTH, mk_x);
-		input_report_abs(input, ABS_MT_TOUCH_MAJOR, major);
-		input_report_abs(input, ABS_MT_TOUCH_MINOR, minor);
+
+		if (data->report_features & ETP_FEATURE_REPORT_MK) {
+			unsigned int mk_x, mk_y, area_x, area_y;
+			u8 mk_data = high_precision ?
+				packet[ETP_MK_DATA_OFFSET + contact_num] :
+				finger_data[3];
+
+			mk_x = mk_data & 0x0f;
+			mk_y = mk_data >> 4;
+
+			/*
+			 * To avoid treating large finger as palm, let's reduce
+			 * the width x and y per trace.
+			 */
+			area_x = mk_x * (data->width_x - ETP_FWIDTH_REDUCE);
+			area_y = mk_y * (data->width_y - ETP_FWIDTH_REDUCE);
+
+			input_report_abs(input, ABS_TOOL_WIDTH, mk_x);
+			input_report_abs(input, ABS_MT_TOUCH_MAJOR,
+					 max(area_x, area_y));
+			input_report_abs(input, ABS_MT_TOUCH_MINOR,
+					 min(area_x, area_y));
+		}
 	} else {
 		input_mt_slot(input, contact_num);
 		input_mt_report_slot_state(input, MT_TOOL_FINGER, false);
 	}
 }
 
-static void elan_report_absolute(struct elan_tp_data *data, u8 *packet)
+static void elan_report_absolute(struct elan_tp_data *data, u8 *packet,
+				 bool high_precision)
 {
 	struct input_dev *input = data->input;
 	u8 *finger_data = &packet[ETP_FINGER_DATA_OFFSET];
@@ -951,11 +929,14 @@
 	u8 hover_info = packet[ETP_HOVER_INFO_OFFSET];
 	bool contact_valid, hover_event;
 
-	hover_event = hover_info & 0x40;
-	for (i = 0; i < ETP_MAX_FINGERS; i++) {
-		contact_valid = tp_info & (1U << (3 + i));
-		elan_report_contact(data, i, contact_valid, finger_data);
+	pm_wakeup_event(&data->client->dev, 0);
 
+	hover_event = hover_info & BIT(6);
+
+	for (i = 0; i < ETP_MAX_FINGERS; i++) {
+		contact_valid = tp_info & BIT(3 + i);
+		elan_report_contact(data, i, contact_valid, high_precision,
+				    packet, finger_data);
 		if (contact_valid)
 			finger_data += ETP_FINGER_DATA_LEN;
 	}
@@ -974,6 +955,8 @@
 	u8 *packet = &report[ETP_REPORT_ID_OFFSET + 1];
 	int x, y;
 
+	pm_wakeup_event(&data->client->dev, 0);
+
 	if (!data->tp_input) {
 		dev_warn_once(&data->client->dev,
 			      "received a trackpoint report while no trackpoint device has been created. Please report upstream.\n");
@@ -998,7 +981,6 @@
 static irqreturn_t elan_isr(int irq, void *dev_id)
 {
 	struct elan_tp_data *data = dev_id;
-	struct device *dev = &data->client->dev;
 	int error;
 	u8 report[ETP_MAX_REPORT_LEN];
 
@@ -1012,21 +994,23 @@
 		goto out;
 	}
 
-	error = data->ops->get_report(data->client, report);
+	error = data->ops->get_report(data->client, report, data->report_len);
 	if (error)
 		goto out;
 
-	pm_wakeup_event(dev, 0);
-
 	switch (report[ETP_REPORT_ID_OFFSET]) {
 	case ETP_REPORT_ID:
-		elan_report_absolute(data, report);
+		elan_report_absolute(data, report, false);
+		break;
+	case ETP_REPORT_ID2:
+		elan_report_absolute(data, report, true);
 		break;
 	case ETP_TP_REPORT_ID:
+	case ETP_TP_REPORT_ID2:
 		elan_report_trackpoint(data, report);
 		break;
 	default:
-		dev_err(dev, "invalid report id data (%x)\n",
+		dev_err(&data->client->dev, "invalid report id data (%x)\n",
 			report[ETP_REPORT_ID_OFFSET]);
 	}
 
@@ -1111,7 +1095,9 @@
 	input_abs_set_res(input, ABS_X, data->x_res);
 	input_abs_set_res(input, ABS_Y, data->y_res);
 	input_set_abs_params(input, ABS_PRESSURE, 0, ETP_MAX_PRESSURE, 0, 0);
-	input_set_abs_params(input, ABS_TOOL_WIDTH, 0, ETP_FINGER_WIDTH, 0, 0);
+	if (data->report_features & ETP_FEATURE_REPORT_MK)
+		input_set_abs_params(input, ABS_TOOL_WIDTH,
+				     0, ETP_FINGER_WIDTH, 0, 0);
 	input_set_abs_params(input, ABS_DISTANCE, 0, 1, 0, 0);
 
 	/* And MT parameters */
@@ -1121,10 +1107,12 @@
 	input_abs_set_res(input, ABS_MT_POSITION_Y, data->y_res);
 	input_set_abs_params(input, ABS_MT_PRESSURE, 0,
 			     ETP_MAX_PRESSURE, 0, 0);
-	input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0,
-			     ETP_FINGER_WIDTH * max_width, 0, 0);
-	input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0,
-			     ETP_FINGER_WIDTH * min_width, 0, 0);
+	if (data->report_features & ETP_FEATURE_REPORT_MK) {
+		input_set_abs_params(input, ABS_MT_TOUCH_MAJOR,
+				     0, ETP_FINGER_WIDTH * max_width, 0, 0);
+		input_set_abs_params(input, ABS_MT_TOUCH_MINOR,
+				     0, ETP_FINGER_WIDTH * min_width, 0, 0);
+	}
 
 	data->input = input;
 
@@ -1315,9 +1303,21 @@
 		/* Enable wake from IRQ */
 		data->irq_wake = (enable_irq_wake(client->irq) == 0);
 	} else {
-		ret = elan_disable_power(data);
+		ret = elan_set_power(data, false);
+		if (ret)
+			goto err;
+
+		ret = regulator_disable(data->vcc);
+		if (ret) {
+			dev_err(dev, "error %d disabling regulator\n", ret);
+			/* Attempt to power the chip back up */
+			elan_set_power(data, true);
+		}
 	}
 
+err:
+	if (ret)
+		enable_irq(client->irq);
 	mutex_unlock(&data->sysfs_mutex);
 	return ret;
 }
@@ -1328,12 +1328,18 @@
 	struct elan_tp_data *data = i2c_get_clientdata(client);
 	int error;
 
-	if (device_may_wakeup(dev) && data->irq_wake) {
+	if (!device_may_wakeup(dev)) {
+		error = regulator_enable(data->vcc);
+		if (error) {
+			dev_err(dev, "error %d enabling regulator\n", error);
+			goto err;
+		}
+	} else if (data->irq_wake) {
 		disable_irq_wake(client->irq);
 		data->irq_wake = false;
 	}
 
-	error = elan_enable_power(data);
+	error = elan_set_power(data, true);
 	if (error) {
 		dev_err(dev, "power up when resuming failed: %d\n", error);
 		goto err;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/mouse/elan_i2c_i2c.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/mouse/elan_i2c_i2c.c
@@ -55,6 +55,8 @@
 #define ETP_I2C_MIN_BASELINE_CMD	0x0318
 
 #define ETP_I2C_REPORT_LEN		34
+#define ETP_I2C_REPORT_LEN_ID2		39
+#define ETP_I2C_REPORT_MAX_LEN		39
 #define ETP_I2C_DESC_LENGTH		30
 #define ETP_I2C_REPORT_DESC_LENGTH	158
 #define ETP_I2C_INF_LENGTH		2
@@ -386,7 +388,7 @@
 		return error;
 	}
 
-	*max_x = le16_to_cpup((__le16 *)val) & 0x0fff;
+	*max_x = le16_to_cpup((__le16 *)val);
 
 	error = elan_i2c_read_cmd(client, ETP_I2C_MAX_Y_AXIS_CMD, val);
 	if (error) {
@@ -394,7 +396,7 @@
 		return error;
 	}
 
-	*max_y = le16_to_cpup((__le16 *)val) & 0x0fff;
+	*max_y = le16_to_cpup((__le16 *)val);
 
 	return 0;
 }
@@ -617,12 +619,12 @@
 				     struct completion *completion)
 {
 	struct device *dev = &client->dev;
-	int error;
+	int error = 0;
 	int len;
-	u8 buffer[ETP_I2C_REPORT_LEN];
+	u8 buffer[ETP_I2C_REPORT_MAX_LEN];
 
-	len = i2c_master_recv(client, buffer, ETP_I2C_REPORT_LEN);
-	if (len != ETP_I2C_REPORT_LEN) {
+	len = i2c_master_recv(client, buffer, ETP_I2C_REPORT_MAX_LEN);
+	if (len <= 0) {
 		error = len < 0 ? len : -EIO;
 		dev_warn(dev, "failed to read I2C data after FW WDT reset: %d (%d)\n",
 			error, len);
@@ -656,20 +658,31 @@
 	return 0;
 }
 
-static int elan_i2c_get_report(struct i2c_client *client, u8 *report)
+static int elan_i2c_get_report_features(struct i2c_client *client, u8 pattern,
+					unsigned int *features,
+					unsigned int *report_len)
+{
+	*features = ETP_FEATURE_REPORT_MK;
+	*report_len = pattern <= 0x01 ?
+			ETP_I2C_REPORT_LEN : ETP_I2C_REPORT_LEN_ID2;
+	return 0;
+}
+
+static int elan_i2c_get_report(struct i2c_client *client,
+			       u8 *report, unsigned int report_len)
 {
 	int len;
 
-	len = i2c_master_recv(client, report, ETP_I2C_REPORT_LEN);
+	len = i2c_master_recv(client, report, report_len);
 	if (len < 0) {
 		dev_err(&client->dev, "failed to read report data: %d\n", len);
 		return len;
 	}
 
-	if (len != ETP_I2C_REPORT_LEN) {
+	if (len != report_len) {
 		dev_err(&client->dev,
 			"wrong report length (%d vs %d expected)\n",
-			len, ETP_I2C_REPORT_LEN);
+			len, report_len);
 		return -EIO;
 	}
 
@@ -706,5 +719,6 @@
 
 	.get_pattern		= elan_i2c_get_pattern,
 
+	.get_report_features	= elan_i2c_get_report_features,
 	.get_report		= elan_i2c_get_report,
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/mouse/elan_i2c_smbus.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/mouse/elan_i2c_smbus.c
@@ -45,6 +45,7 @@
 #define ETP_SMBUS_CALIBRATE_QUERY	0xC5
 
 #define ETP_SMBUS_REPORT_LEN		32
+#define ETP_SMBUS_REPORT_LEN2		7
 #define ETP_SMBUS_REPORT_OFFSET		2
 #define ETP_SMBUS_HELLOPACKET_LEN	5
 #define ETP_SMBUS_IAP_PASSWORD		0x1234
@@ -469,7 +470,21 @@
 	return 0;
 }
 
-static int elan_smbus_get_report(struct i2c_client *client, u8 *report)
+static int elan_smbus_get_report_features(struct i2c_client *client, u8 pattern,
+					  unsigned int *features,
+					  unsigned int *report_len)
+{
+	/*
+	 * SMBus controllers with pattern 2 lack area info, as newer
+	 * high-precision packets use that space for coordinates.
+	 */
+	*features = pattern <= 0x01 ? ETP_FEATURE_REPORT_MK : 0;
+	*report_len = ETP_SMBUS_REPORT_LEN;
+	return 0;
+}
+
+static int elan_smbus_get_report(struct i2c_client *client,
+				 u8 *report, unsigned int report_len)
 {
 	int len;
 
@@ -483,10 +498,13 @@
 		return len;
 	}
 
-	if (len != ETP_SMBUS_REPORT_LEN) {
+	if (report[ETP_REPORT_ID_OFFSET] == ETP_TP_REPORT_ID2)
+		report_len = ETP_SMBUS_REPORT_LEN2;
+
+	if (len != report_len) {
 		dev_err(&client->dev,
 			"wrong report length (%d vs %d expected)\n",
-			len, ETP_SMBUS_REPORT_LEN);
+			len, report_len);
 		return -EIO;
 	}
 
@@ -534,6 +552,7 @@
 	.write_fw_block		= elan_smbus_write_fw_block,
 	.finish_fw_update	= elan_smbus_finish_fw_update,
 
+	.get_report_features	= elan_smbus_get_report_features,
 	.get_report		= elan_smbus_get_report,
 	.get_pattern		= elan_smbus_get_pattern,
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/mouse/elantech.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/mouse/elantech.c
@@ -90,6 +90,47 @@
 }
 
 /*
+ * Send an Elantech style special command to read 3 bytes from a register
+ */
+static int elantech_read_reg_params(struct psmouse *psmouse, u8 reg, u8 *param)
+{
+	if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+	    elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
+	    elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+	    elantech_ps2_command(psmouse, NULL, reg) ||
+	    elantech_ps2_command(psmouse, param, PSMOUSE_CMD_GETINFO)) {
+		psmouse_err(psmouse,
+			    "failed to read register %#02x\n", reg);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+/*
+ * Send an Elantech style special command to write a register with a parameter
+ */
+static int elantech_write_reg_params(struct psmouse *psmouse, u8 reg, u8 *param)
+{
+	if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+	    elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) ||
+	    elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+	    elantech_ps2_command(psmouse, NULL, reg) ||
+	    elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+	    elantech_ps2_command(psmouse, NULL, param[0]) ||
+	    elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) ||
+	    elantech_ps2_command(psmouse, NULL, param[1]) ||
+	    elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) {
+		psmouse_err(psmouse,
+			    "failed to write register %#02x with value %#02x%#02x\n",
+			    reg, param[0], param[1]);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+/*
  * Send an Elantech style special command to read a value from a register
  */
 static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg,
@@ -476,6 +517,19 @@
 	case 0x16008020U:
 	case 0x26800010U:
 	case 0x36808000U:
+
+		/*
+		 * This firmware misreport coordinates for trackpoint
+		 * occasionally. Discard packets outside of [-127, 127] range
+		 * to prevent cursor jumps.
+		 */
+		if (packet[4] == 0x80 || packet[5] == 0x80 ||
+		    packet[1] >> 7 == packet[4] >> 7 ||
+		    packet[2] >> 7 == packet[5] >> 7) {
+			elantech_debug("discarding packet [%6ph]\n", packet);
+			break;
+
+		}
 		x = packet[4] - (int)((packet[1]^0x80) << 1);
 		y = (int)((packet[2]^0x80) << 1) - packet[5];
 
@@ -620,10 +674,11 @@
 	struct input_dev *dev = psmouse->dev;
 	struct elantech_data *etd = psmouse->private;
 	unsigned char *packet = psmouse->packet;
-	int id = ((packet[3] & 0xe0) >> 5) - 1;
+	int id;
 	int pres, traces;
 
-	if (id < 0)
+	id = ((packet[3] & 0xe0) >> 5) - 1;
+	if (id < 0 || id >= ETP_MAX_FINGERS)
 		return;
 
 	etd->mt[id].x = ((packet[1] & 0x0f) << 8) | packet[2];
@@ -653,7 +708,7 @@
 	int id, sid;
 
 	id = ((packet[0] & 0xe0) >> 5) - 1;
-	if (id < 0)
+	if (id < 0 || id >= ETP_MAX_FINGERS)
 		return;
 
 	sid = ((packet[3] & 0xe0) >> 5) - 1;
@@ -674,7 +729,7 @@
 	input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[id].x);
 	input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[id].y);
 
-	if (sid >= 0) {
+	if (sid >= 0 && sid < ETP_MAX_FINGERS) {
 		etd->mt[sid].x += delta_x2 * weight;
 		etd->mt[sid].y -= delta_y2 * weight;
 		input_mt_slot(dev, sid);
@@ -1422,15 +1477,46 @@
 }
 
 /*
+ * Some hw_version 4 models fail to properly activate absolute mode on
+ * resume without going through disable/enable cycle.
+ */
+static const struct dmi_system_id elantech_needs_reenable[] = {
+#if defined(CONFIG_DMI) && defined(CONFIG_X86)
+	{
+		/* Lenovo N24 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "81AF"),
+		},
+	},
+#endif
+	{ }
+};
+
+/*
  * Put the touchpad back into absolute mode when reconnecting
  */
 static int elantech_reconnect(struct psmouse *psmouse)
 {
+	int err;
+
 	psmouse_reset(psmouse);
 
 	if (elantech_detect(psmouse, 0))
 		return -1;
 
+	if (dmi_check_system(elantech_needs_reenable)) {
+		err = ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_DISABLE);
+		if (err)
+			psmouse_warn(psmouse, "failed to deactivate mouse on %s: %d\n",
+				     psmouse->ps2dev.serio->phys, err);
+
+		err = ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE);
+		if (err)
+			psmouse_warn(psmouse, "failed to reactivate mouse on %s: %d\n",
+				     psmouse->ps2dev.serio->phys, err);
+	}
+
 	if (elantech_set_absolute_mode(psmouse)) {
 		psmouse_err(psmouse,
 			    "failed to put touchpad back into absolute mode.\n");
@@ -1530,18 +1616,40 @@
 };
 
 /*
+ * Change Report id 0x5E to 0x5F.
+ */
+static int elantech_change_report_id(struct psmouse *psmouse)
+{
+	/*
+	 * NOTE: the code is expecting to receive param[] as an array of 3
+	 * items (see __ps2_command()), even if in this case only 2 are
+	 * actually needed. Make sure the array size is 3 to avoid potential
+	 * stack out-of-bound accesses.
+	 */
+	unsigned char param[3] = { 0x10, 0x03 };
+
+	if (elantech_write_reg_params(psmouse, 0x7, param) ||
+	    elantech_read_reg_params(psmouse, 0x7, param) ||
+	    param[0] != 0x10 || param[1] != 0x03) {
+		psmouse_err(psmouse, "Unable to change report ID to 0x5f.\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+/*
  * determine hardware version and set some properties according to it.
  */
 static int elantech_set_properties(struct elantech_device_info *info)
 {
 	/* This represents the version of IC body. */
-	int ver = (info->fw_version & 0x0f0000) >> 16;
+	info->ic_version = (info->fw_version & 0x0f0000) >> 16;
 
 	/* Early version of Elan touchpads doesn't obey the rule. */
 	if (info->fw_version < 0x020030 || info->fw_version == 0x020600)
 		info->hw_version = 1;
 	else {
-		switch (ver) {
+		switch (info->ic_version) {
 		case 2:
 		case 4:
 			info->hw_version = 2;
@@ -1557,6 +1665,11 @@
 		}
 	}
 
+	/* Get information pattern for hw_version 4 */
+	info->pattern = 0x00;
+	if (info->ic_version == 0x0f && (info->fw_version & 0xff) <= 0x02)
+		info->pattern = info->fw_version & 0xff;
+
 	/* decide which send_cmd we're gonna use early */
 	info->send_cmd = info->hw_version >= 3 ? elantech_send_cmd :
 						 synaptics_send_cmd;
@@ -1598,6 +1711,7 @@
 {
 	unsigned char param[3];
 	unsigned char traces;
+	unsigned char ic_body[3];
 
 	memset(info, 0, sizeof(*info));
 
@@ -1640,6 +1754,21 @@
 			     info->samples[2]);
 	}
 
+	if (info->pattern > 0x00 && info->ic_version == 0xf) {
+		if (info->send_cmd(psmouse, ETP_ICBODY_QUERY, ic_body)) {
+			psmouse_err(psmouse, "failed to query ic body\n");
+			return -EINVAL;
+		}
+		info->ic_version = be16_to_cpup((__be16 *)ic_body);
+		psmouse_info(psmouse,
+			     "Elan ic body: %#04x, current fw version: %#02x\n",
+			     info->ic_version, ic_body[2]);
+	}
+
+	info->product_id = be16_to_cpup((__be16 *)info->samples);
+	if (info->pattern == 0x00)
+		info->product_id &= 0xff;
+
 	if (info->samples[1] == 0x74 && info->hw_version == 0x03) {
 		/*
 		 * This module has a bug which makes absolute mode
@@ -1654,6 +1783,23 @@
 	/* The MSB indicates the presence of the trackpoint */
 	info->has_trackpoint = (info->capabilities[0] & 0x80) == 0x80;
 
+	if (info->has_trackpoint && info->ic_version == 0x0011 &&
+	    (info->product_id == 0x08 || info->product_id == 0x09 ||
+	     info->product_id == 0x0d || info->product_id == 0x0e)) {
+		/*
+		 * This module has a bug which makes trackpoint in SMBus
+		 * mode return invalid data unless trackpoint is switched
+		 * from using 0x5e reports to 0x5f. If we are not able to
+		 * make the switch, let's abort initialization so we'll be
+		 * using standard PS/2 protocol.
+		 */
+		if (elantech_change_report_id(psmouse)) {
+			psmouse_info(psmouse,
+				     "Trackpoint report is broken, forcing standard PS/2 protocol\n");
+			return -ENODEV;
+		}
+	}
+
 	info->x_res = 31;
 	info->y_res = 31;
 	if (info->hw_version == 4) {
@@ -1999,6 +2145,7 @@
 	psmouse->protocol_handler = elantech_process_byte;
 	psmouse->disconnect = elantech_disconnect;
 	psmouse->reconnect = elantech_reconnect;
+	psmouse->fast_reconnect = NULL;
 	psmouse->pktsize = info->hw_version > 1 ? 6 : 4;
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/mouse/elantech.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/mouse/elantech.h
@@ -18,6 +18,7 @@
 #define ETP_CAPABILITIES_QUERY		0x02
 #define ETP_SAMPLE_QUERY		0x03
 #define ETP_RESOLUTION_QUERY		0x04
+#define ETP_ICBODY_QUERY		0x05
 
 /*
  * Command values for register reading or writing
@@ -140,7 +141,10 @@
 	unsigned char samples[3];
 	unsigned char debug;
 	unsigned char hw_version;
+	unsigned char pattern;
 	unsigned int fw_version;
+	unsigned int ic_version;
+	unsigned int product_id;
 	unsigned int x_min;
 	unsigned int y_min;
 	unsigned int x_max;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/mouse/focaltech.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/mouse/focaltech.c
@@ -202,8 +202,8 @@
 	state->pressed = packet[0] >> 7;
 	finger1 = ((packet[0] >> 4) & 0x7) - 1;
 	if (finger1 < FOC_MAX_FINGERS) {
-		state->fingers[finger1].x += (char)packet[1];
-		state->fingers[finger1].y += (char)packet[2];
+		state->fingers[finger1].x += (s8)packet[1];
+		state->fingers[finger1].y += (s8)packet[2];
 	} else {
 		psmouse_err(psmouse, "First finger in rel packet invalid: %d\n",
 			    finger1);
@@ -218,8 +218,8 @@
 	 */
 	finger2 = ((packet[3] >> 4) & 0x7) - 1;
 	if (finger2 < FOC_MAX_FINGERS) {
-		state->fingers[finger2].x += (char)packet[4];
-		state->fingers[finger2].y += (char)packet[5];
+		state->fingers[finger2].x += (s8)packet[4];
+		state->fingers[finger2].y += (s8)packet[5];
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/mouse/psmouse-base.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/mouse/psmouse-base.c
@@ -2042,7 +2042,7 @@
 {
 	int type = *((unsigned int *)kp->arg);
 
-	return sprintf(buffer, "%s", psmouse_protocol_by_type(type)->name);
+	return sprintf(buffer, "%s\n", psmouse_protocol_by_type(type)->name);
 }
 
 static int __init psmouse_init(void)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/mouse/sentelic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/mouse/sentelic.c
@@ -441,7 +441,7 @@
 
 	fsp_reg_write_enable(psmouse, false);
 
-	return count;
+	return retval;
 }
 
 PSMOUSE_DEFINE_WO_ATTR(setreg, S_IWUSR, NULL, fsp_attr_set_setreg);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/mouse/synaptics.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/mouse/synaptics.c
@@ -146,7 +146,6 @@
 	"LEN0042", /* Yoga */
 	"LEN0045",
 	"LEN0047",
-	"LEN0049",
 	"LEN2000", /* S540 */
 	"LEN2001", /* Edge E431 */
 	"LEN2002", /* Edge E531 */
@@ -166,23 +165,30 @@
 	/* all of the topbuttonpad_pnp_ids are valid, we just add some extras */
 	"LEN0048", /* X1 Carbon 3 */
 	"LEN0046", /* X250 */
+	"LEN0049", /* Yoga 11e */
 	"LEN004a", /* W541 */
 	"LEN005b", /* P50 */
 	"LEN005e", /* T560 */
+	"LEN006c", /* T470s */
+	"LEN007a", /* T470s */
 	"LEN0071", /* T480 */
 	"LEN0072", /* X1 Carbon Gen 5 (2017) - Elan/ALPS trackpoint */
 	"LEN0073", /* X1 Carbon G5 (Elantech) */
+	"LEN0091", /* X1 Carbon 6 */
 	"LEN0092", /* X1 Carbon 6 */
 	"LEN0093", /* T480 */
 	"LEN0096", /* X280 */
 	"LEN0097", /* X280 -> ALPS trackpoint */
+	"LEN0099", /* X1 Extreme 1st */
 	"LEN009b", /* T580 */
 	"LEN200f", /* T450s */
+	"LEN2044", /* L470  */
 	"LEN2054", /* E480 */
 	"LEN2055", /* E580 */
 	"SYN3052", /* HP EliteBook 840 G4 */
 	"SYN3221", /* HP 15-ay000 */
 	"SYN323d", /* HP Spectre X360 13-w013dx */
+	"SYN3257", /* HP Envy 13-ad105ng */
 	NULL
 };
 
@@ -1611,6 +1617,7 @@
 	psmouse->set_rate = synaptics_set_rate;
 	psmouse->disconnect = synaptics_disconnect;
 	psmouse->reconnect = synaptics_reconnect;
+	psmouse->fast_reconnect = NULL;
 	psmouse->cleanup = synaptics_reset;
 	/* Synaptics can usually stay in sync without extra help */
 	psmouse->resync_time = 0;
@@ -1740,6 +1747,7 @@
 		psmouse_matches_pnp_id(psmouse, topbuttonpad_pnp_ids) &&
 		!SYN_CAP_EXT_BUTTONS_STICK(info->ext_cap_10);
 	const struct rmi_device_platform_data pdata = {
+		.reset_delay_ms = 30,
 		.sensor_pdata = {
 			.sensor_type = rmi_sensor_touchpad,
 			.axis_align.flip_y = true,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/mouse/trackpoint.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/mouse/trackpoint.c
@@ -17,10 +17,12 @@
 #include "trackpoint.h"
 
 static const char * const trackpoint_variants[] = {
-	[TP_VARIANT_IBM]	= "IBM",
-	[TP_VARIANT_ALPS]	= "ALPS",
-	[TP_VARIANT_ELAN]	= "Elan",
-	[TP_VARIANT_NXP]	= "NXP",
+	[TP_VARIANT_IBM]		= "IBM",
+	[TP_VARIANT_ALPS]		= "ALPS",
+	[TP_VARIANT_ELAN]		= "Elan",
+	[TP_VARIANT_NXP]		= "NXP",
+	[TP_VARIANT_JYT_SYNAPTICS]	= "JYT_Synaptics",
+	[TP_VARIANT_SYNAPTICS]		= "Synaptics",
 };
 
 /*
@@ -280,6 +282,8 @@
 	case TP_VARIANT_ALPS:
 	case TP_VARIANT_ELAN:
 	case TP_VARIANT_NXP:
+	case TP_VARIANT_JYT_SYNAPTICS:
+	case TP_VARIANT_SYNAPTICS:
 		if (variant_id)
 			*variant_id = param[0];
 		if (firmware_id)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/mouse/trackpoint.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/mouse/trackpoint.h
@@ -24,10 +24,12 @@
  * 0x01 was the original IBM trackpoint, others implement very limited
  * subset of trackpoint features.
  */
-#define TP_VARIANT_IBM		0x01
-#define TP_VARIANT_ALPS		0x02
-#define TP_VARIANT_ELAN		0x03
-#define TP_VARIANT_NXP		0x04
+#define TP_VARIANT_IBM			0x01
+#define TP_VARIANT_ALPS			0x02
+#define TP_VARIANT_ELAN			0x03
+#define TP_VARIANT_NXP			0x04
+#define TP_VARIANT_JYT_SYNAPTICS	0x05
+#define TP_VARIANT_SYNAPTICS		0x06
 
 /*
  * Commands
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/rmi4/rmi_bus.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/rmi4/rmi_bus.c
@@ -276,11 +276,11 @@
 
 	device_del(&fn->dev);
 	of_node_put(fn->dev.of_node);
-	put_device(&fn->dev);
 
 	for (i = 0; i < fn->num_of_irqs; i++)
 		irq_dispose_mapping(fn->irq[i]);
 
+	put_device(&fn->dev);
 }
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/rmi4/rmi_driver.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/rmi4/rmi_driver.c
@@ -205,7 +205,7 @@
 
 	if (count) {
 		kfree(attn_data.data);
-		attn_data.data = NULL;
+		drvdata->attn_data.data = NULL;
 	}
 
 	if (!kfifo_is_empty(&drvdata->attn_fifo))
@@ -978,12 +978,12 @@
 
 	rmi_disable_irq(rmi_dev, false);
 
-	irq_domain_remove(data->irqdomain);
-	data->irqdomain = NULL;
-
 	rmi_f34_remove_sysfs(rmi_dev);
 	rmi_free_function_list(rmi_dev);
 
+	irq_domain_remove(data->irqdomain);
+	data->irqdomain = NULL;
+
 	return 0;
 }
 
@@ -1196,7 +1196,11 @@
 		}
 		rmi_driver_set_input_params(rmi_dev, data->input);
 		data->input->phys = devm_kasprintf(dev, GFP_KERNEL,
-						"%s/input0", dev_name(dev));
+						   "%s/input0", dev_name(dev));
+		if (!data->input->phys) {
+			retval = -ENOMEM;
+			goto err;
+		}
 	}
 
 	retval = rmi_init_functions(data);
@@ -1210,7 +1214,8 @@
 	if (data->input) {
 		rmi_driver_set_input_name(rmi_dev, data->input);
 		if (!rmi_dev->xport->input) {
-			if (input_register_device(data->input)) {
+			retval = input_register_device(data->input);
+			if (retval) {
 				dev_err(dev, "%s: Failed to register input device.\n",
 					__func__);
 				goto err_destroy_functions;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/rmi4/rmi_f34v7.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/rmi4/rmi_f34v7.c
@@ -1189,6 +1189,9 @@
 {
 	int ret;
 
+	f34->fn->rmi_dev->driver->set_irq_bits(f34->fn->rmi_dev,
+					       f34->fn->irq_mask);
+
 	rmi_f34v7_read_queries_bl_version(f34);
 
 	f34->v7.image = fw->data;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/rmi4/rmi_smbus.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/rmi4/rmi_smbus.c
@@ -235,12 +235,29 @@
 
 static int rmi_smb_enable_smbus_mode(struct rmi_smb_xport *rmi_smb)
 {
-	int retval;
+	struct i2c_client *client = rmi_smb->client;
+	int smbus_version;
+
+	/*
+	 * psmouse driver resets the controller, we only need to wait
+	 * to give the firmware chance to fully reinitialize.
+	 */
+	if (rmi_smb->xport.pdata.reset_delay_ms)
+		msleep(rmi_smb->xport.pdata.reset_delay_ms);
 
 	/* we need to get the smbus version to activate the touchpad */
-	retval = rmi_smb_get_version(rmi_smb);
-	if (retval < 0)
-		return retval;
+	smbus_version = rmi_smb_get_version(rmi_smb);
+	if (smbus_version < 0)
+		return smbus_version;
+
+	rmi_dbg(RMI_DEBUG_XPORT, &client->dev, "Smbus version is %d",
+		smbus_version);
+
+	if (smbus_version != 2 && smbus_version != 3) {
+		dev_err(&client->dev, "Unrecognized SMB version %d\n",
+				smbus_version);
+		return -ENODEV;
+	}
 
 	return 0;
 }
@@ -253,11 +270,10 @@
 	rmi_smb_clear_state(rmi_smb);
 
 	/*
-	 * we do not call the actual reset command, it has to be handled in
-	 * PS/2 or there will be races between PS/2 and SMBus.
-	 * PS/2 should ensure that a psmouse_reset is called before
-	 * intializing the device and after it has been removed to be in a known
-	 * state.
+	 * We do not call the actual reset command, it has to be handled in
+	 * PS/2 or there will be races between PS/2 and SMBus. PS/2 should
+	 * ensure that a psmouse_reset is called before initializing the
+	 * device and after it has been removed to be in a known state.
 	 */
 	return rmi_smb_enable_smbus_mode(rmi_smb);
 }
@@ -273,7 +289,6 @@
 {
 	struct rmi_device_platform_data *pdata = dev_get_platdata(&client->dev);
 	struct rmi_smb_xport *rmi_smb;
-	int smbus_version;
 	int error;
 
 	if (!pdata) {
@@ -312,18 +327,9 @@
 	rmi_smb->xport.proto_name = "smb";
 	rmi_smb->xport.ops = &rmi_smb_ops;
 
-	smbus_version = rmi_smb_get_version(rmi_smb);
-	if (smbus_version < 0)
-		return smbus_version;
-
-	rmi_dbg(RMI_DEBUG_XPORT, &client->dev, "Smbus version is %d",
-		smbus_version);
-
-	if (smbus_version != 2 && smbus_version != 3) {
-		dev_err(&client->dev, "Unrecognized SMB version %d\n",
-				smbus_version);
-		return -ENODEV;
-	}
+	error = rmi_smb_enable_smbus_mode(rmi_smb);
+	if (error)
+		return error;
 
 	i2c_set_clientdata(client, rmi_smb);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/serio/hil_mlc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/serio/hil_mlc.c
@@ -74,10 +74,10 @@
 static LIST_HEAD(hil_mlcs);
 static DEFINE_RWLOCK(hil_mlcs_lock);
 static struct timer_list	hil_mlcs_kicker;
-static int			hil_mlcs_probe;
+static int			hil_mlcs_probe, hil_mlc_stop;
 
 static void hil_mlcs_process(unsigned long unused);
-static DECLARE_TASKLET_DISABLED(hil_mlcs_tasklet, hil_mlcs_process, 0);
+static DECLARE_TASKLET_DISABLED_OLD(hil_mlcs_tasklet, hil_mlcs_process);
 
 
 /* #define HIL_MLC_DEBUG */
@@ -702,9 +702,13 @@
 		if (!mlc->ostarted) {
 			mlc->ostarted = 1;
 			mlc->opacket = pack;
-			mlc->out(mlc);
+			rc = mlc->out(mlc);
 			nextidx = HILSEN_DOZE;
 			write_unlock_irqrestore(&mlc->lock, flags);
+			if (rc) {
+				hil_mlc_stop = 1;
+				return 1;
+			}
 			break;
 		}
 		mlc->ostarted = 0;
@@ -715,8 +719,13 @@
 
 	case HILSE_CTS:
 		write_lock_irqsave(&mlc->lock, flags);
-		nextidx = mlc->cts(mlc) ? node->bad : node->good;
+		rc = mlc->cts(mlc);
+		nextidx = rc ? node->bad : node->good;
 		write_unlock_irqrestore(&mlc->lock, flags);
+		if (rc) {
+			hil_mlc_stop = 1;
+			return 1;
+		}
 		break;
 
 	default:
@@ -780,6 +789,12 @@
 
 static void hil_mlcs_timer(struct timer_list *unused)
 {
+	if (hil_mlc_stop) {
+		/* could not send packet - stop immediately. */
+		pr_warn(PREFIX "HIL seems stuck - Disabling HIL MLC.\n");
+		return;
+	}
+
 	hil_mlcs_probe = 1;
 	tasklet_schedule(&hil_mlcs_tasklet);
 	/* Re-insert the periodic task. */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/serio/hp_sdc_mlc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/serio/hp_sdc_mlc.c
@@ -210,7 +210,7 @@
 	priv->tseq[2] = 1;
 	priv->tseq[3] = 0;
 	priv->tseq[4] = 0;
-	__hp_sdc_enqueue_transaction(&priv->trans);
+	return __hp_sdc_enqueue_transaction(&priv->trans);
  busy:
 	return 1;
  done:
@@ -219,7 +219,7 @@
 	return 0;
 }
 
-static void hp_sdc_mlc_out(hil_mlc *mlc)
+static int hp_sdc_mlc_out(hil_mlc *mlc)
 {
 	struct hp_sdc_mlc_priv_s *priv;
 
@@ -234,7 +234,7 @@
  do_data:
 	if (priv->emtestmode) {
 		up(&mlc->osem);
-		return;
+		return 0;
 	}
 	/* Shouldn't be sending commands when loop may be busy */
 	BUG_ON(down_trylock(&mlc->csem));
@@ -296,7 +296,7 @@
 		BUG_ON(down_trylock(&mlc->csem));
 	}
  enqueue:
-	hp_sdc_enqueue_transaction(&priv->trans);
+	return hp_sdc_enqueue_transaction(&priv->trans);
 }
 
 static int __init hp_sdc_mlc_init(void)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/serio/i8042-x86ia64io.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/serio/i8042-x86ia64io.h
@@ -67,25 +67,84 @@
 
 #include <linux/dmi.h>
 
-static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = {
+#define SERIO_QUIRK_NOKBD		BIT(0)
+#define SERIO_QUIRK_NOAUX		BIT(1)
+#define SERIO_QUIRK_NOMUX		BIT(2)
+#define SERIO_QUIRK_FORCEMUX		BIT(3)
+#define SERIO_QUIRK_UNLOCK		BIT(4)
+#define SERIO_QUIRK_PROBE_DEFER		BIT(5)
+#define SERIO_QUIRK_RESET_ALWAYS	BIT(6)
+#define SERIO_QUIRK_RESET_NEVER		BIT(7)
+#define SERIO_QUIRK_DIECT		BIT(8)
+#define SERIO_QUIRK_DUMBKBD		BIT(9)
+#define SERIO_QUIRK_NOLOOP		BIT(10)
+#define SERIO_QUIRK_NOTIMEOUT		BIT(11)
+#define SERIO_QUIRK_KBDRESET		BIT(12)
+#define SERIO_QUIRK_DRITEK		BIT(13)
+#define SERIO_QUIRK_NOPNP		BIT(14)
+
+/* Quirk table for different mainboards. Options similar or identical to i8042
+ * module parameters.
+ * ORDERING IS IMPORTANT! The first match will be apllied and the rest ignored.
+ * This allows entries to overwrite vendor wide quirks on a per device basis.
+ * Where this is irrelevant, entries are sorted case sensitive by DMI_SYS_VENDOR
+ * and/or DMI_BOARD_VENDOR to make it easier to avoid dublicate entries.
+ */
+static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = {
 	{
-		/*
-		 * Arima-Rioworks HDAMB -
-		 * AUX LOOP command does not raise AUX IRQ
-		 */
 		.matches = {
-			DMI_MATCH(DMI_BOARD_VENDOR, "RIOWORKS"),
-			DMI_MATCH(DMI_BOARD_NAME, "HDAMB"),
-			DMI_MATCH(DMI_BOARD_VERSION, "Rev E"),
+			DMI_MATCH(DMI_SYS_VENDOR, "ALIENWARE"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Sentia"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
 	},
 	{
-		/* ASUS G1S */
 		.matches = {
-			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."),
-			DMI_MATCH(DMI_BOARD_NAME, "G1S"),
-			DMI_MATCH(DMI_BOARD_VERSION, "1.0"),
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "X750LN"),
+		},
+		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)
+	},
+	{
+		/* Asus X450LCP */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "X450LCP"),
+		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_NEVER)
+	},
+	{
+		/* ASUS ZenBook UX425UA */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "ZenBook UX425UA"),
+		},
+		.driver_data = (void *)(SERIO_QUIRK_PROBE_DEFER | SERIO_QUIRK_RESET_NEVER)
+	},
+	{
+		/* ASUS ZenBook UM325UA */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "ZenBook UX325UA_UM325UA"),
+		},
+		.driver_data = (void *)(SERIO_QUIRK_PROBE_DEFER | SERIO_QUIRK_RESET_NEVER)
+	},
+	/*
+	 * On some Asus laptops, just running self tests cause problems.
+	 */
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /* Notebook */
 		},
+		.driver_data = (void *)(SERIO_QUIRK_RESET_NEVER)
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_CHASSIS_TYPE, "31"), /* Convertible Notebook */
+		},
+		.driver_data = (void *)(SERIO_QUIRK_RESET_NEVER)
 	},
 	{
 		/* ASUS P65UP5 - AUX LOOP command does not raise AUX IRQ */
@@ -94,156 +153,338 @@
 			DMI_MATCH(DMI_BOARD_NAME, "P/I-P65UP5"),
 			DMI_MATCH(DMI_BOARD_VERSION, "REV 2.X"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)
 	},
 	{
+		/* ASUS G1S */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "X750LN"),
+			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."),
+			DMI_MATCH(DMI_BOARD_NAME, "G1S"),
+			DMI_MATCH(DMI_BOARD_VERSION, "1.0"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)
 	},
 	{
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
-			DMI_MATCH(DMI_PRODUCT_NAME , "ProLiant"),
-			DMI_MATCH(DMI_PRODUCT_VERSION, "8500"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1360"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
 	},
 	{
+		/* Acer Aspire 5710 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
-			DMI_MATCH(DMI_PRODUCT_NAME , "ProLiant"),
-			DMI_MATCH(DMI_PRODUCT_VERSION, "DL760"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5710"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
 	},
 	{
-		/* Dell Embedded Box PC 3000 */
+		/* Acer Aspire 7738 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Embedded Box PC 3000"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7738"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
 	},
 	{
-		/* OQO Model 01 */
+		/* Acer Aspire 5536 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "OQO"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "ZEPTO"),
-			DMI_MATCH(DMI_PRODUCT_VERSION, "00"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5536"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
 	},
 	{
-		/* ULI EV4873 - AUX LOOP does not work properly */
+		/*
+		 * Acer Aspire 5738z
+		 * Touchpad stops working in mux mode when dis- + re-enabled
+		 * with the touchpad enable/disable toggle hotkey
+		 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "ULI"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "EV4873"),
-			DMI_MATCH(DMI_PRODUCT_VERSION, "5a"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5738"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
 	},
 	{
-		/* Microsoft Virtual Machine */
+		/* Acer Aspire One 150 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"),
-			DMI_MATCH(DMI_PRODUCT_VERSION, "VS2005R2"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "AOA150"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
 	},
 	{
-		/* Medion MAM 2070 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Notebook"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "MAM 2070"),
-			DMI_MATCH(DMI_PRODUCT_VERSION, "5a"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire A114-31"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
 	},
 	{
-		/* Medion Akoya E7225 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Medion"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Akoya E7225"),
-			DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire A314-31"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
 	},
 	{
-		/* Blue FB5601 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "blue"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "FB5601"),
-			DMI_MATCH(DMI_PRODUCT_VERSION, "M606"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire A315-31"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
 	},
 	{
-		/* Gigabyte M912 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "M912"),
-			DMI_MATCH(DMI_PRODUCT_VERSION, "01"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire ES1-132"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
 	},
 	{
-		/* Gigabyte M1022M netbook */
 		.matches = {
-			DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co.,Ltd."),
-			DMI_MATCH(DMI_BOARD_NAME, "M1022E"),
-			DMI_MATCH(DMI_BOARD_VERSION, "1.02"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire ES1-332"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
 	},
 	{
-		/* Gigabyte Spring Peak - defines wrong chassis type */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Spring Peak"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire ES1-432"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
 	},
 	{
-		/* Gigabyte T1005 - defines wrong chassis type ("Other") */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "T1005"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate Spin B118-RN"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
 	},
+	/*
+	 * Some Wistron based laptops need us to explicitly enable the 'Dritek
+	 * keyboard extension' to make their extra keys start generating scancodes.
+	 * Originally, this was just confined to older laptops, but a few Acer laptops
+	 * have turned up in 2007 that also need this again.
+	 */
 	{
-		/* Gigabyte T1005M/P - defines wrong chassis type ("Other") */
+		/* Acer Aspire 5100 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "T1005M/P"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5100"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_DRITEK)
 	},
 	{
+		/* Acer Aspire 5610 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv9700"),
-			DMI_MATCH(DMI_PRODUCT_VERSION, "Rev 1"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5610"),
+		},
+		.driver_data = (void *)(SERIO_QUIRK_DRITEK)
+	},
+	{
+		/* Acer Aspire 5630 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5630"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_DRITEK)
 	},
 	{
+		/* Acer Aspire 5650 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "PEGATRON CORPORATION"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "C15B"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5650"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_DRITEK)
 	},
-	{ }
-};
-
-/*
- * Some Fujitsu notebooks are having trouble with touchpads if
- * active multiplexing mode is activated. Luckily they don't have
- * external PS/2 ports so we can safely disable it.
- * ... apparently some Toshibas don't like MUX mode either and
- * die horrible death on reboot.
- */
-static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = {
 	{
-		/* Fujitsu Lifebook P7010/P7010D */
+		/* Acer Aspire 5680 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "P7010"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5680"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_DRITEK)
 	},
 	{
-		/* Fujitsu Lifebook P7010 */
+		/* Acer Aspire 5720 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "0000000000"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5720"),
+		},
+		.driver_data = (void *)(SERIO_QUIRK_DRITEK)
+	},
+	{
+		/* Acer Aspire 9110 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 9110"),
+		},
+		.driver_data = (void *)(SERIO_QUIRK_DRITEK)
+	},
+	{
+		/* Acer TravelMate 660 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 660"),
+		},
+		.driver_data = (void *)(SERIO_QUIRK_DRITEK)
+	},
+	{
+		/* Acer TravelMate 2490 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2490"),
+		},
+		.driver_data = (void *)(SERIO_QUIRK_DRITEK)
+	},
+	{
+		/* Acer TravelMate 4280 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 4280"),
+		},
+		.driver_data = (void *)(SERIO_QUIRK_DRITEK)
+	},
+	{
+		/* Acer TravelMate P459-G2-M */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate P459-G2-M"),
+		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
+	},
+	{
+		/* Amoi M636/A737 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Amoi Electronics CO.,LTD."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "M636/A737 platform"),
+		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ByteSpeed LLC"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "ByteSpeed Laptop C15B"),
+		},
+		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)
+	},
+	{
+		/* Compal HEL80I */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "COMPAL"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "HEL80I"),
+		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "8500"),
+		},
+		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "DL760"),
+		},
+		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)
+	},
+	{
+		/* Advent 4211 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "DIXONSXP"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Advent 4211"),
+		},
+		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
+	},
+	{
+		/* Dell Embedded Box PC 3000 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Embedded Box PC 3000"),
+		},
+		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)
+	},
+	{
+		/* Dell XPS M1530 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "XPS M1530"),
+		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
+	},
+	{
+		/* Dell Vostro 1510 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro1510"),
+		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
+	},
+	{
+		/* Dell Vostro V13 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"),
+		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_NOTIMEOUT)
+	},
+	{
+		/* Dell Vostro 1320 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1320"),
+		},
+		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
+	},
+	{
+		/* Dell Vostro 1520 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1520"),
+		},
+		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
+	},
+	{
+		/* Dell Vostro 1720 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1720"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
+	},
+	{
+		/* Entroware Proteus */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Entroware"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Proteus"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "EL07R4"),
+		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS)
+	},
+	/*
+	 * Some Fujitsu notebooks are having trouble with touchpads if
+	 * active multiplexing mode is activated. Luckily they don't have
+	 * external PS/2 ports so we can safely disable it.
+	 * ... apparently some Toshibas don't like MUX mode either and
+	 * die horrible death on reboot.
+	 */
+	{
+		/* Fujitsu Lifebook P7010/P7010D */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "P7010"),
+		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
 	},
 	{
 		/* Fujitsu Lifebook P5020D */
@@ -251,6 +492,7 @@
 			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook P Series"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
 	},
 	{
 		/* Fujitsu Lifebook S2000 */
@@ -258,6 +500,7 @@
 			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook S Series"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
 	},
 	{
 		/* Fujitsu Lifebook S6230 */
@@ -265,6 +508,15 @@
 			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook S6230"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
+	},
+	{
+		/* Fujitsu Lifebook T725 laptop */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK T725"),
+		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_NOTIMEOUT)
 	},
 	{
 		/* Fujitsu Lifebook U745 */
@@ -272,6 +524,7 @@
 			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK U745"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
 	},
 	{
 		/* Fujitsu T70H */
@@ -279,6 +532,50 @@
 			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "FMVLT70H"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
+	},
+	{
+		/* Fujitsu A544 laptop */
+		/* https://bugzilla.redhat.com/show_bug.cgi?id=1111138 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK A544"),
+		},
+		.driver_data = (void *)(SERIO_QUIRK_NOTIMEOUT)
+	},
+	{
+		/* Fujitsu AH544 laptop */
+		/* https://bugzilla.kernel.org/show_bug.cgi?id=69731 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK AH544"),
+		},
+		.driver_data = (void *)(SERIO_QUIRK_NOTIMEOUT)
+	},
+	{
+		/* Fujitsu U574 laptop */
+		/* https://bugzilla.kernel.org/show_bug.cgi?id=69731 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK U574"),
+		},
+		.driver_data = (void *)(SERIO_QUIRK_NOTIMEOUT)
+	},
+	{
+		/* Fujitsu UH554 laptop */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK UH544"),
+		},
+		.driver_data = (void *)(SERIO_QUIRK_NOTIMEOUT)
+	},
+	{
+		/* Fujitsu Lifebook P7010 */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "0000000000"),
+		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
 	},
 	{
 		/* Fujitsu-Siemens Lifebook T3010 */
@@ -286,6 +583,7 @@
 			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK T3010"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
 	},
 	{
 		/* Fujitsu-Siemens Lifebook E4010 */
@@ -293,6 +591,7 @@
 			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E4010"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
 	},
 	{
 		/* Fujitsu-Siemens Amilo Pro 2010 */
@@ -300,6 +599,7 @@
 			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro V2010"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
 	},
 	{
 		/* Fujitsu-Siemens Amilo Pro 2030 */
@@ -307,578 +607,654 @@
 			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "AMILO PRO V2030"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
 	},
 	{
-		/*
-		 * No data is coming from the touchscreen unless KBC
-		 * is in legacy mode.
-		 */
-		/* Panasonic CF-29 */
+		/* Fujitsu Lifebook A574/H */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "CF-29"),
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "FMVA0501PZ"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
 	},
 	{
-		/*
-		 * HP Pavilion DV4017EA -
-		 * errors on MUX ports are reported without raising AUXDATA
-		 * causing "spurious NAK" messages.
-		 */
+		/* Fujitsu Lifebook E5411 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion dv4000 (EA032EA#ABF)"),
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU CLIENT COMPUTING LIMITED"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E5411"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOAUX)
 	},
 	{
-		/*
-		 * HP Pavilion ZT1000 -
-		 * like DV4017EA does not raise AUXERR for errors on MUX ports.
-		 */
+		/* Gigabyte M912 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Notebook PC"),
-			DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook ZT1000"),
+			DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "M912"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "01"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)
 	},
 	{
-		/*
-		 * HP Pavilion DV4270ca -
-		 * like DV4017EA does not raise AUXERR for errors on MUX ports.
-		 */
+		/* Gigabyte Spring Peak - defines wrong chassis type */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion dv4000 (EH476UA#ABL)"),
+			DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Spring Peak"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)
 	},
 	{
+		/* Gigabyte T1005 - defines wrong chassis type ("Other") */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P10"),
+			DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "T1005"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)
 	},
 	{
+		/* Gigabyte T1005M/P - defines wrong chassis type ("Other") */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "EQUIUM A110"),
+			DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "T1005M/P"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)
 	},
+	/*
+	 * Some laptops need keyboard reset before probing for the trackpad to get
+	 * it detected, initialised & finally work.
+	 */
 	{
+		/* Gigabyte P35 v2 - Elantech touchpad */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE C850D"),
+			DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "P35V2"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_KBDRESET)
+	},
+		{
+		/* Aorus branded Gigabyte X3 Plus - Elantech touchpad */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "X3"),
+		},
+		.driver_data = (void *)(SERIO_QUIRK_KBDRESET)
 	},
 	{
+		/* Gigabyte P34 - Elantech touchpad */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "ALIENWARE"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Sentia"),
+			DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "P34"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_KBDRESET)
 	},
 	{
-		/* Sharp Actius MM20 */
+		/* Gigabyte P57 - Elantech touchpad */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "SHARP"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "PC-MM20 Series"),
+			DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "P57"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_KBDRESET)
 	},
 	{
-		/* Sony Vaio FS-115b */
+		/* Gericom Bellagio */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FS115B"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Gericom"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "N34AS6"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
 	},
 	{
-		/*
-		 * Sony Vaio FZ-240E -
-		 * reset and GET ID commands issued via KBD port are
-		 * sometimes being delivered to AUX3.
-		 */
+		/* Gigabyte M1022M netbook */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ240E"),
+			DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co.,Ltd."),
+			DMI_MATCH(DMI_BOARD_NAME, "M1022E"),
+			DMI_MATCH(DMI_BOARD_VERSION, "1.02"),
+		},
+		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv9700"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "Rev 1"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)
 	},
 	{
 		/*
-		 * Most (all?) VAIOs do not have external PS/2 ports nor
-		 * they implement active multiplexing properly, and
-		 * MUX discovery usually messes up keyboard/touchpad.
+		 * HP Pavilion DV4017EA -
+		 * errors on MUX ports are reported without raising AUXDATA
+		 * causing "spurious NAK" messages.
 		 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
-			DMI_MATCH(DMI_BOARD_NAME, "VAIO"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion dv4000 (EA032EA#ABF)"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
 	},
 	{
-		/* Amoi M636/A737 */
+		/*
+		 * HP Pavilion ZT1000 -
+		 * like DV4017EA does not raise AUXERR for errors on MUX ports.
+		 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Amoi Electronics CO.,LTD."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "M636/A737 platform"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Notebook PC"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook ZT1000"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
 	},
 	{
-		/* Lenovo 3000 n100 */
+		/*
+		 * HP Pavilion DV4270ca -
+		 * like DV4017EA does not raise AUXERR for errors on MUX ports.
+		 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "076804U"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion dv4000 (EH476UA#ABL)"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
 	},
 	{
+		/* Newer HP Pavilion dv4 models */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1360"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_NOTIMEOUT)
 	},
 	{
-		/* Acer Aspire 5710 */
+		/* IBM 2656 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5710"),
+			DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "2656"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
 	},
 	{
-		/* Acer Aspire 7738 */
+		/* Avatar AVIU-145A6 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7738"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Intel"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "IC4I"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
 	},
 	{
-		/* Gericom Bellagio */
+		/* Intel MBO Desktop D845PESV */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Gericom"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "N34AS6"),
+			DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
+			DMI_MATCH(DMI_BOARD_NAME, "D845PESV"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOPNP)
 	},
 	{
-		/* IBM 2656 */
+		/*
+		 * Intel NUC D54250WYK - does not have i8042 controller but
+		 * declares PS/2 devices in DSDT.
+		 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "2656"),
+			DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
+			DMI_MATCH(DMI_BOARD_NAME, "D54250WYK"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOPNP)
 	},
 	{
-		/* Dell XPS M1530 */
+		/* Lenovo 3000 n100 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "XPS M1530"),
+			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "076804U"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
 	},
 	{
-		/* Compal HEL80I */
+		/* Lenovo XiaoXin Air 12 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "COMPAL"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "HEL80I"),
+			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "80UN"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
 	},
 	{
-		/* Dell Vostro 1510 */
+		/* Lenovo LaVie Z */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro1510"),
+			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo LaVie Z"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
 	},
 	{
-		/* Acer Aspire 5536 */
+		/* Lenovo Ideapad U455 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5536"),
-			DMI_MATCH(DMI_PRODUCT_VERSION, "0100"),
+			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "20046"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
 	},
 	{
-		/* Dell Vostro V13 */
+		/* Lenovo ThinkPad L460 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"),
+			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L460"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
 	},
 	{
-		/* Newer HP Pavilion dv4 models */
+		/* Lenovo ThinkPad Twist S230u */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"),
+			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "33474HU"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
 	},
 	{
-		/* Asus X450LCP */
+		/* LG Electronics X110 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "X450LCP"),
+			DMI_MATCH(DMI_BOARD_VENDOR, "LG Electronics Inc."),
+			DMI_MATCH(DMI_BOARD_NAME, "X110"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
 	},
 	{
-		/* Avatar AVIU-145A6 */
+		/* Medion Akoya Mini E1210 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Intel"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "IC4I"),
+			DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "E1210"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
 	},
 	{
-		/* TUXEDO BU1406 */
+		/* Medion Akoya E1222 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Notebook"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "N24_25BU"),
+			DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "E122X"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
 	},
 	{
-		/* Lenovo LaVie Z */
+		/* MSI Wind U-100 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-			DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo LaVie Z"),
+			DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
+			DMI_MATCH(DMI_BOARD_NAME, "U-100"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS | SERIO_QUIRK_NOPNP)
 	},
-	{ }
-};
-
-static const struct dmi_system_id i8042_dmi_forcemux_table[] __initconst = {
 	{
 		/*
-		 * Sony Vaio VGN-CS series require MUX or the touch sensor
-		 * buttons will disturb touchpad operation
+		 * No data is coming from the touchscreen unless KBC
+		 * is in legacy mode.
 		 */
+		/* Panasonic CF-29 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "VGN-CS"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "CF-29"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
 	},
-	{ }
-};
-
-/*
- * On some Asus laptops, just running self tests cause problems.
- */
-static const struct dmi_system_id i8042_dmi_noselftest_table[] = {
 	{
+		/* Medion Akoya E7225 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
-			DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /* Notebook */
+			DMI_MATCH(DMI_SYS_VENDOR, "Medion"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Akoya E7225"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)
 	},
-	{ }
-};
-static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = {
 	{
-		/* MSI Wind U-100 */
+		/* Microsoft Virtual Machine */
 		.matches = {
-			DMI_MATCH(DMI_BOARD_NAME, "U-100"),
-			DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "VS2005R2"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)
 	},
 	{
-		/* LG Electronics X110 */
+		/* Medion MAM 2070 */
 		.matches = {
-			DMI_MATCH(DMI_BOARD_NAME, "X110"),
-			DMI_MATCH(DMI_BOARD_VENDOR, "LG Electronics Inc."),
+			DMI_MATCH(DMI_SYS_VENDOR, "Notebook"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "MAM 2070"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "5a"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)
 	},
 	{
-		/* Acer Aspire One 150 */
+		/* TUXEDO BU1406 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "AOA150"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Notebook"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "N24_25BU"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
 	},
 	{
-		/* Advent 4211 */
+		/* Clevo P650RS, 650RP6, Sager NP8152-S, and others */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "DIXONSXP"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Advent 4211"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Notebook"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "P65xRP"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
 	},
 	{
-		/* Medion Akoya Mini E1210 */
+		/* OQO Model 01 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "E1210"),
+			DMI_MATCH(DMI_SYS_VENDOR, "OQO"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "ZEPTO"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "00"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)
 	},
 	{
-		/* Medion Akoya E1222 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "E122X"),
+			DMI_MATCH(DMI_SYS_VENDOR, "PEGATRON CORPORATION"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "C15B"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)
 	},
 	{
-		/* Mivvy M310 */
+		/* Acer Aspire 5 A515 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "VIOOO"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "N10"),
+			DMI_MATCH(DMI_BOARD_VENDOR, "PK"),
+			DMI_MATCH(DMI_BOARD_NAME, "Grumpy_PK"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOPNP)
 	},
 	{
-		/* Dell Vostro 1320 */
+		/* ULI EV4873 - AUX LOOP does not work properly */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1320"),
+			DMI_MATCH(DMI_SYS_VENDOR, "ULI"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "EV4873"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "5a"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)
 	},
 	{
-		/* Dell Vostro 1520 */
+		/*
+		 * Arima-Rioworks HDAMB -
+		 * AUX LOOP command does not raise AUX IRQ
+		 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1520"),
+			DMI_MATCH(DMI_BOARD_VENDOR, "RIOWORKS"),
+			DMI_MATCH(DMI_BOARD_NAME, "HDAMB"),
+			DMI_MATCH(DMI_BOARD_VERSION, "Rev E"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)
 	},
 	{
-		/* Dell Vostro 1720 */
+		/* Sharp Actius MM20 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1720"),
+			DMI_MATCH(DMI_SYS_VENDOR, "SHARP"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "PC-MM20 Series"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
 	},
 	{
-		/* Lenovo Ideapad U455 */
+		/*
+		 * Sony Vaio FZ-240E -
+		 * reset and GET ID commands issued via KBD port are
+		 * sometimes being delivered to AUX3.
+		 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "20046"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ240E"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
 	},
 	{
-		/* Lenovo ThinkPad L460 */
+		/*
+		 * Most (all?) VAIOs do not have external PS/2 ports nor
+		 * they implement active multiplexing properly, and
+		 * MUX discovery usually messes up keyboard/touchpad.
+		 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-			DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L460"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+			DMI_MATCH(DMI_BOARD_NAME, "VAIO"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
 	},
 	{
-		/* Clevo P650RS, 650RP6, Sager NP8152-S, and others */
+		/* Sony Vaio FS-115b */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Notebook"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "P65xRP"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FS115B"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
 	},
-	{ }
-};
-
-#ifdef CONFIG_PNP
-static const struct dmi_system_id __initconst i8042_dmi_nopnp_table[] = {
 	{
-		/* Intel MBO Desktop D845PESV */
+		/*
+		 * Sony Vaio VGN-CS series require MUX or the touch sensor
+		 * buttons will disturb touchpad operation
+		 */
 		.matches = {
-			DMI_MATCH(DMI_BOARD_NAME, "D845PESV"),
-			DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "VGN-CS"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_FORCEMUX)
 	},
 	{
-		/*
-		 * Intel NUC D54250WYK - does not have i8042 controller but
-		 * declares PS/2 devices in DSDT.
-		 */
 		.matches = {
-			DMI_MATCH(DMI_BOARD_NAME, "D54250WYK"),
-			DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P10"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
 	},
 	{
-		/* MSI Wind U-100 */
 		.matches = {
-			DMI_MATCH(DMI_BOARD_NAME, "U-100"),
-			DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "EQUIUM A110"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
 	},
-	{ }
-};
-
-static const struct dmi_system_id __initconst i8042_dmi_laptop_table[] = {
 	{
 		.matches = {
-			DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE C850D"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX)
 	},
+	/*
+	 * A lot of modern Clevo barebones have touchpad and/or keyboard issues
+	 * after suspend fixable with nomux + reset + noloop + nopnp. Luckily,
+	 * none of them have an external PS/2 port so this can safely be set for
+	 * all of them. These two are based on a Clevo design, but have the
+	 * board_name changed.
+	 */
 	{
 		.matches = {
-			DMI_MATCH(DMI_CHASSIS_TYPE, "9"), /* Laptop */
+			DMI_MATCH(DMI_BOARD_VENDOR, "TUXEDO"),
+			DMI_MATCH(DMI_BOARD_NAME, "AURA1501"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+					SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
 	},
 	{
 		.matches = {
-			DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /* Notebook */
+			DMI_MATCH(DMI_BOARD_VENDOR, "TUXEDO"),
+			DMI_MATCH(DMI_BOARD_NAME, "EDUBOOK1502"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+					SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
 	},
 	{
+		/* Mivvy M310 */
 		.matches = {
-			DMI_MATCH(DMI_CHASSIS_TYPE, "14"), /* Sub-Notebook */
+			DMI_MATCH(DMI_SYS_VENDOR, "VIOOO"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "N10"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_RESET_ALWAYS)
 	},
-	{ }
-};
-#endif
-
-static const struct dmi_system_id __initconst i8042_dmi_notimeout_table[] = {
+	/*
+	 * Some laptops need keyboard reset before probing for the trackpad to get
+	 * it detected, initialised & finally work.
+	 */
 	{
-		/* Dell Vostro V13 */
+		/* Schenker XMG C504 - Elantech touchpad */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"),
+			DMI_MATCH(DMI_SYS_VENDOR, "XMG"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "C504"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_KBDRESET)
 	},
 	{
-		/* Newer HP Pavilion dv4 models */
+		/* Blue FB5601 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"),
+			DMI_MATCH(DMI_SYS_VENDOR, "blue"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "FB5601"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "M606"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOLOOP)
 	},
+	/*
+	 * A lot of modern Clevo barebones have touchpad and/or keyboard issues
+	 * after suspend fixable with nomux + reset + noloop + nopnp. Luckily,
+	 * none of them have an external PS/2 port so this can safely be set for
+	 * all of them.
+	 * Clevo barebones come with board_vendor and/or system_vendor set to
+	 * either the very generic string "Notebook" and/or a different value
+	 * for each individual reseller. The only somewhat universal way to
+	 * identify them is by board_name.
+	 */
 	{
-		/* Fujitsu A544 laptop */
-		/* https://bugzilla.redhat.com/show_bug.cgi?id=1111138 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK A544"),
+			DMI_MATCH(DMI_BOARD_NAME, "LAPQC71A"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+					SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
 	},
 	{
-		/* Fujitsu AH544 laptop */
-		/* https://bugzilla.kernel.org/show_bug.cgi?id=69731 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK AH544"),
+			DMI_MATCH(DMI_BOARD_NAME, "LAPQC71B"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+					SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
 	},
 	{
-		/* Fujitsu U574 laptop */
-		/* https://bugzilla.kernel.org/show_bug.cgi?id=69731 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK U574"),
+			DMI_MATCH(DMI_BOARD_NAME, "N140CU"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+					SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
 	},
 	{
-		/* Fujitsu UH554 laptop */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK UH544"),
+			DMI_MATCH(DMI_BOARD_NAME, "N141CU"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+					SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
 	},
-	{ }
-};
-
-/*
- * Some Wistron based laptops need us to explicitly enable the 'Dritek
- * keyboard extension' to make their extra keys start generating scancodes.
- * Originally, this was just confined to older laptops, but a few Acer laptops
- * have turned up in 2007 that also need this again.
- */
-static const struct dmi_system_id __initconst i8042_dmi_dritek_table[] = {
 	{
-		/* Acer Aspire 5100 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5100"),
+			DMI_MATCH(DMI_BOARD_NAME, "NH5xAx"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+					SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
 	},
 	{
-		/* Acer Aspire 5610 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5610"),
+			DMI_MATCH(DMI_BOARD_NAME, "NL5xRU"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+					SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
 	},
+	/*
+	 * At least one modern Clevo barebone has the touchpad connected both
+	 * via PS/2 and i2c interface. This causes a race condition between the
+	 * psmouse and i2c-hid driver. Since the full capability of the touchpad
+	 * is available via the i2c interface and the device has no external
+	 * PS/2 port, it is safe to just ignore all ps2 mouses here to avoid
+	 * this issue. The known affected device is the
+	 * TUXEDO InfinityBook S17 Gen6 / Clevo NS70MU which comes with one of
+	 * the two different dmi strings below. NS50MU is not a typo!
+	 */
 	{
-		/* Acer Aspire 5630 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5630"),
+			DMI_MATCH(DMI_BOARD_NAME, "NS50MU"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOAUX | SERIO_QUIRK_NOMUX |
+					SERIO_QUIRK_RESET_ALWAYS | SERIO_QUIRK_NOLOOP |
+					SERIO_QUIRK_NOPNP)
 	},
 	{
-		/* Acer Aspire 5650 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5650"),
+			DMI_MATCH(DMI_BOARD_NAME, "NS50_70MU"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOAUX | SERIO_QUIRK_NOMUX |
+					SERIO_QUIRK_RESET_ALWAYS | SERIO_QUIRK_NOLOOP |
+					SERIO_QUIRK_NOPNP)
 	},
 	{
-		/* Acer Aspire 5680 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5680"),
+			DMI_MATCH(DMI_BOARD_NAME, "NS5x_7xPU"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOAUX)
 	},
 	{
-		/* Acer Aspire 5720 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5720"),
+			DMI_MATCH(DMI_BOARD_NAME, "NJ50_70CU"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+					SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
 	},
 	{
-		/* Acer Aspire 9110 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 9110"),
+			DMI_MATCH(DMI_BOARD_NAME, "PB50_70DFx,DDx"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+					SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
 	},
 	{
-		/* Acer TravelMate 660 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 660"),
+			DMI_MATCH(DMI_BOARD_NAME, "PCX0DX"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+					SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
 	},
+	/* See comment on TUXEDO InfinityBook S17 Gen6 / Clevo NS70MU above */
 	{
-		/* Acer TravelMate 2490 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2490"),
+			DMI_MATCH(DMI_BOARD_NAME, "PD5x_7xPNP_PNR_PNN_PNT"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOAUX)
 	},
 	{
-		/* Acer TravelMate 4280 */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 4280"),
+			DMI_MATCH(DMI_BOARD_NAME, "X170SM"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+					SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
 	},
-	{ }
-};
-
-/*
- * Some laptops need keyboard reset before probing for the trackpad to get
- * it detected, initialised & finally work.
- */
-static const struct dmi_system_id __initconst i8042_dmi_kbdreset_table[] = {
 	{
-		/* Gigabyte P35 v2 - Elantech touchpad */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "P35V2"),
+			DMI_MATCH(DMI_BOARD_NAME, "X170KM-G"),
 		},
+		.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+					SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
 	},
-		{
-		/* Aorus branded Gigabyte X3 Plus - Elantech touchpad */
+	{ }
+};
+
+#ifdef CONFIG_PNP
+static const struct dmi_system_id i8042_dmi_laptop_table[] __initconst = {
+	{
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "X3"),
+			DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */
 		},
 	},
 	{
-		/* Gigabyte P34 - Elantech touchpad */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "P34"),
+			DMI_MATCH(DMI_CHASSIS_TYPE, "9"), /* Laptop */
 		},
 	},
 	{
-		/* Gigabyte P57 - Elantech touchpad */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "P57"),
+			DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /* Notebook */
 		},
 	},
 	{
-		/* Schenker XMG C504 - Elantech touchpad */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "XMG"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "C504"),
+			DMI_MATCH(DMI_CHASSIS_TYPE, "14"), /* Sub-Notebook */
 		},
 	},
 	{ }
 };
+#endif
 
 #endif /* CONFIG_X86 */
 
@@ -1033,11 +1409,6 @@
 	bool pnp_data_busted = false;
 	int err;
 
-#ifdef CONFIG_X86
-	if (dmi_check_system(i8042_dmi_nopnp_table))
-		i8042_nopnp = true;
-#endif
-
 	if (i8042_nopnp) {
 		pr_info("PNP detection disabled\n");
 		return 0;
@@ -1141,6 +1512,59 @@
 static inline void i8042_pnp_exit(void) { }
 #endif /* CONFIG_PNP */
 
+
+#ifdef CONFIG_X86
+static void __init i8042_check_quirks(void)
+{
+	const struct dmi_system_id *device_quirk_info;
+	uintptr_t quirks;
+
+	device_quirk_info = dmi_first_match(i8042_dmi_quirk_table);
+	if (!device_quirk_info)
+		return;
+
+	quirks = (uintptr_t)device_quirk_info->driver_data;
+
+	if (quirks & SERIO_QUIRK_NOKBD)
+		i8042_nokbd = true;
+	if (quirks & SERIO_QUIRK_NOAUX)
+		i8042_noaux = true;
+	if (quirks & SERIO_QUIRK_NOMUX)
+		i8042_nomux = true;
+	if (quirks & SERIO_QUIRK_FORCEMUX)
+		i8042_nomux = false;
+	if (quirks & SERIO_QUIRK_UNLOCK)
+		i8042_unlock = true;
+	if (quirks & SERIO_QUIRK_PROBE_DEFER)
+		i8042_probe_defer = true;
+	/* Honor module parameter when value is not default */
+	if (i8042_reset == I8042_RESET_DEFAULT) {
+		if (quirks & SERIO_QUIRK_RESET_ALWAYS)
+			i8042_reset = I8042_RESET_ALWAYS;
+		if (quirks & SERIO_QUIRK_RESET_NEVER)
+			i8042_reset = I8042_RESET_NEVER;
+	}
+	if (quirks & SERIO_QUIRK_DIECT)
+		i8042_direct = true;
+	if (quirks & SERIO_QUIRK_DUMBKBD)
+		i8042_dumbkbd = true;
+	if (quirks & SERIO_QUIRK_NOLOOP)
+		i8042_noloop = true;
+	if (quirks & SERIO_QUIRK_NOTIMEOUT)
+		i8042_notimeout = true;
+	if (quirks & SERIO_QUIRK_KBDRESET)
+		i8042_kbdreset = true;
+	if (quirks & SERIO_QUIRK_DRITEK)
+		i8042_dritek = true;
+#ifdef CONFIG_PNP
+	if (quirks & SERIO_QUIRK_NOPNP)
+		i8042_nopnp = true;
+#endif
+}
+#else
+static inline void i8042_check_quirks(void) {}
+#endif
+
 static int __init i8042_platform_init(void)
 {
 	int retval;
@@ -1163,42 +1587,17 @@
 	i8042_kbd_irq = I8042_MAP_IRQ(1);
 	i8042_aux_irq = I8042_MAP_IRQ(12);
 
-	retval = i8042_pnp_init();
-	if (retval)
-		return retval;
-
 #if defined(__ia64__)
-        i8042_reset = I8042_RESET_ALWAYS;
+	i8042_reset = I8042_RESET_ALWAYS;
 #endif
 
-#ifdef CONFIG_X86
-	/* Honor module parameter when value is not default */
-	if (i8042_reset == I8042_RESET_DEFAULT) {
-		if (dmi_check_system(i8042_dmi_reset_table))
-			i8042_reset = I8042_RESET_ALWAYS;
-
-		if (dmi_check_system(i8042_dmi_noselftest_table))
-			i8042_reset = I8042_RESET_NEVER;
-	}
-
-	if (dmi_check_system(i8042_dmi_noloop_table))
-		i8042_noloop = true;
-
-	if (dmi_check_system(i8042_dmi_nomux_table))
-		i8042_nomux = true;
-
-	if (dmi_check_system(i8042_dmi_forcemux_table))
-		i8042_nomux = false;
+	i8042_check_quirks();
 
-	if (dmi_check_system(i8042_dmi_notimeout_table))
-		i8042_notimeout = true;
-
-	if (dmi_check_system(i8042_dmi_dritek_table))
-		i8042_dritek = true;
-
-	if (dmi_check_system(i8042_dmi_kbdreset_table))
-		i8042_kbdreset = true;
+	retval = i8042_pnp_init();
+	if (retval)
+		return retval;
 
+#ifdef CONFIG_X86
 	/*
 	 * A20 was already enabled during early kernel init. But some buggy
 	 * BIOSes (in MSI Laptops) require A20 to be enabled using 8042 to
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/serio/i8042.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/serio/i8042.c
@@ -44,6 +44,10 @@
 module_param_named(unlock, i8042_unlock, bool, 0);
 MODULE_PARM_DESC(unlock, "Ignore keyboard lock.");
 
+static bool i8042_probe_defer;
+module_param_named(probe_defer, i8042_probe_defer, bool, 0);
+MODULE_PARM_DESC(probe_defer, "Allow deferred probing.");
+
 enum i8042_controller_reset_mode {
 	I8042_RESET_NEVER,
 	I8042_RESET_ALWAYS,
@@ -121,6 +125,7 @@
 MODULE_PARM_DESC(unmask_kbd_data, "Unconditional enable (may reveal sensitive data) of normally sanitize-filtered kbd data traffic debug log [pre-condition: i8042.debug=1 enabled]");
 #endif
 
+static bool i8042_present;
 static bool i8042_bypass_aux_irq_test;
 static char i8042_kbd_firmware_id[128];
 static char i8042_aux_firmware_id[128];
@@ -341,6 +346,9 @@
 	unsigned long flags;
 	int retval;
 
+	if (!i8042_present)
+		return -1;
+
 	spin_lock_irqsave(&i8042_lock, flags);
 	retval = __i8042_command(param, command);
 	spin_unlock_irqrestore(&i8042_lock, flags);
@@ -611,7 +619,7 @@
 	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
 		i8042_ctr &= ~I8042_CTR_KBDINT;
 		i8042_ctr |= I8042_CTR_KBDDIS;
-		pr_err("Failed to enable KBD port\n");
+		pr_info("Failed to enable KBD port\n");
 		return -EIO;
 	}
 
@@ -630,7 +638,7 @@
 	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
 		i8042_ctr &= ~I8042_CTR_AUXINT;
 		i8042_ctr |= I8042_CTR_AUXDIS;
-		pr_err("Failed to enable AUX port\n");
+		pr_info("Failed to enable AUX port\n");
 		return -EIO;
 	}
 
@@ -705,7 +713,7 @@
  * LCS/Telegraphics.
  */
 
-static int __init i8042_check_mux(void)
+static int i8042_check_mux(void)
 {
 	unsigned char mux_version;
 
@@ -722,7 +730,7 @@
 	i8042_ctr &= ~I8042_CTR_AUXINT;
 
 	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
-		pr_err("Failed to disable AUX port, can't use MUX\n");
+		pr_info("Failed to disable AUX port, can't use MUX\n");
 		return -EIO;
 	}
 
@@ -734,10 +742,10 @@
 /*
  * The following is used to test AUX IRQ delivery.
  */
-static struct completion i8042_aux_irq_delivered __initdata;
-static bool i8042_irq_being_tested __initdata;
+static struct completion i8042_aux_irq_delivered;
+static bool i8042_irq_being_tested;
 
-static irqreturn_t __init i8042_aux_test_irq(int irq, void *dev_id)
+static irqreturn_t i8042_aux_test_irq(int irq, void *dev_id)
 {
 	unsigned long flags;
 	unsigned char str, data;
@@ -764,7 +772,7 @@
  * verifies success by readinng CTR. Used when testing for presence of AUX
  * port.
  */
-static int __init i8042_toggle_aux(bool on)
+static int i8042_toggle_aux(bool on)
 {
 	unsigned char param;
 	int i;
@@ -792,7 +800,7 @@
  * the presence of an AUX interface.
  */
 
-static int __init i8042_check_aux(void)
+static int i8042_check_aux(void)
 {
 	int retval = -1;
 	bool irq_registered = false;
@@ -937,25 +945,28 @@
 {
 	unsigned char param;
 	int i = 0;
+	int ret;
 
 	/*
 	 * We try this 5 times; on some really fragile systems this does not
 	 * take the first time...
 	 */
-	do {
-
-		if (i8042_command(&param, I8042_CMD_CTL_TEST)) {
-			pr_err("i8042 controller selftest timeout\n");
-			return -ENODEV;
-		}
+	while (i++ < 5) {
 
-		if (param == I8042_RET_CTL_TEST)
+		ret = i8042_command(&param, I8042_CMD_CTL_TEST);
+		if (ret)
+			pr_info("i8042 controller selftest timeout (%d/5)\n", i);
+		else if (param == I8042_RET_CTL_TEST)
 			return 0;
+		else
+			dbg("i8042 controller selftest: %#x != %#x\n",
+			    param, I8042_RET_CTL_TEST);
 
-		dbg("i8042 controller selftest: %#x != %#x\n",
-		    param, I8042_RET_CTL_TEST);
 		msleep(50);
-	} while (i++ < 5);
+	}
+
+	if (ret)
+		return -ENODEV;
 
 #ifdef CONFIG_X86
 	/*
@@ -967,7 +978,7 @@
 	pr_info("giving up on controller selftest, continuing anyway...\n");
 	return 0;
 #else
-	pr_err("i8042 controller selftest failed\n");
+	pr_info("i8042 controller selftest failed\n");
 	return -EIO;
 #endif
 }
@@ -999,7 +1010,7 @@
 
 		if (i8042_command(&ctr[n++ % 2], I8042_CMD_CTL_RCTR)) {
 			pr_err("Can't read CTR while initializing i8042\n");
-			return -EIO;
+			return i8042_probe_defer ? -EPROBE_DEFER : -EIO;
 		}
 
 	} while (n < 2 || ctr[0] != ctr[1]);
@@ -1314,7 +1325,7 @@
 	i8042_controller_reset(false);
 }
 
-static int __init i8042_create_kbd_port(void)
+static int i8042_create_kbd_port(void)
 {
 	struct serio *serio;
 	struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO];
@@ -1342,7 +1353,7 @@
 	return 0;
 }
 
-static int __init i8042_create_aux_port(int idx)
+static int i8042_create_aux_port(int idx)
 {
 	struct serio *serio;
 	int port_no = idx < 0 ? I8042_AUX_PORT_NO : I8042_MUX_PORT_NO + idx;
@@ -1379,13 +1390,13 @@
 	return 0;
 }
 
-static void __init i8042_free_kbd_port(void)
+static void i8042_free_kbd_port(void)
 {
 	kfree(i8042_ports[I8042_KBD_PORT_NO].serio);
 	i8042_ports[I8042_KBD_PORT_NO].serio = NULL;
 }
 
-static void __init i8042_free_aux_ports(void)
+static void i8042_free_aux_ports(void)
 {
 	int i;
 
@@ -1395,7 +1406,7 @@
 	}
 }
 
-static void __init i8042_register_ports(void)
+static void i8042_register_ports(void)
 {
 	int i;
 
@@ -1436,7 +1447,7 @@
 	i8042_aux_irq_registered = i8042_kbd_irq_registered = false;
 }
 
-static int __init i8042_setup_aux(void)
+static int i8042_setup_aux(void)
 {
 	int (*aux_enable)(void);
 	int error;
@@ -1464,7 +1475,8 @@
 	if (error)
 		goto err_free_ports;
 
-	if (aux_enable())
+	error = aux_enable();
+	if (error)
 		goto err_free_irq;
 
 	i8042_aux_irq_registered = true;
@@ -1477,7 +1489,7 @@
 	return error;
 }
 
-static int __init i8042_setup_kbd(void)
+static int i8042_setup_kbd(void)
 {
 	int error;
 
@@ -1527,12 +1539,10 @@
 	return 0;
 }
 
-static int __init i8042_probe(struct platform_device *dev)
+static int i8042_probe(struct platform_device *dev)
 {
 	int error;
 
-	i8042_platform_device = dev;
-
 	if (i8042_reset == I8042_RESET_ALWAYS) {
 		error = i8042_controller_selftest();
 		if (error)
@@ -1570,7 +1580,6 @@
 	i8042_free_aux_ports();	/* in case KBD failed but AUX not */
 	i8042_free_irqs();
 	i8042_controller_reset(false);
-	i8042_platform_device = NULL;
 
 	return error;
 }
@@ -1580,7 +1589,6 @@
 	i8042_unregister_ports();
 	i8042_free_irqs();
 	i8042_controller_reset(false);
-	i8042_platform_device = NULL;
 
 	return 0;
 }
@@ -1592,6 +1600,7 @@
 		.pm	= &i8042_pm_ops,
 #endif
 	},
+	.probe		= i8042_probe,
 	.remove		= i8042_remove,
 	.shutdown	= i8042_shutdown,
 };
@@ -1602,30 +1611,44 @@
 
 static int __init i8042_init(void)
 {
-	struct platform_device *pdev;
 	int err;
 
 	dbg_init();
 
 	err = i8042_platform_init();
 	if (err)
-		return err;
+		return (err == -ENODEV) ? 0 : err;
 
 	err = i8042_controller_check();
 	if (err)
 		goto err_platform_exit;
 
-	pdev = platform_create_bundle(&i8042_driver, i8042_probe, NULL, 0, NULL, 0);
-	if (IS_ERR(pdev)) {
-		err = PTR_ERR(pdev);
+	/* Set this before creating the dev to allow i8042_command to work right away */
+	i8042_present = true;
+
+	err = platform_driver_register(&i8042_driver);
+	if (err)
 		goto err_platform_exit;
+
+	i8042_platform_device = platform_device_alloc("i8042", -1);
+	if (!i8042_platform_device) {
+		err = -ENOMEM;
+		goto err_unregister_driver;
 	}
 
+	err = platform_device_add(i8042_platform_device);
+	if (err)
+		goto err_free_device;
+
 	bus_register_notifier(&serio_bus, &i8042_kbd_bind_notifier_block);
 	panic_blink = i8042_panic_blink;
 
 	return 0;
 
+err_free_device:
+	platform_device_put(i8042_platform_device);
+err_unregister_driver:
+	platform_driver_unregister(&i8042_driver);
  err_platform_exit:
 	i8042_platform_exit();
 	return err;
@@ -1633,6 +1656,9 @@
 
 static void __exit i8042_exit(void)
 {
+	if (!i8042_present)
+		return;
+
 	platform_device_unregister(i8042_platform_device);
 	platform_driver_unregister(&i8042_driver);
 	i8042_platform_exit();
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/serio/i8042.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/serio/i8042.h
@@ -17,8 +17,6 @@
 #include "i8042-ip22io.h"
 #elif defined(CONFIG_SNI_RM)
 #include "i8042-snirm.h"
-#elif defined(CONFIG_PPC)
-#include "i8042-ppcio.h"
 #elif defined(CONFIG_SPARC)
 #include "i8042-sparcio.h"
 #elif defined(CONFIG_X86) || defined(CONFIG_IA64)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/serio/serio_raw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/serio/serio_raw.c
@@ -159,7 +159,7 @@
 {
 	struct serio_raw_client *client = file->private_data;
 	struct serio_raw *serio_raw = client->serio_raw;
-	char uninitialized_var(c);
+	char c;
 	ssize_t read = 0;
 	int error;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/serio/sun4i-ps2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/serio/sun4i-ps2.c
@@ -211,7 +211,6 @@
 	struct sun4i_ps2data *drvdata;
 	struct serio *serio;
 	struct device *dev = &pdev->dev;
-	unsigned int irq;
 	int error;
 
 	drvdata = kzalloc(sizeof(struct sun4i_ps2data), GFP_KERNEL);
@@ -264,14 +263,12 @@
 	writel(0, drvdata->reg_base + PS2_REG_GCTL);
 
 	/* Get IRQ for the device */
-	irq = platform_get_irq(pdev, 0);
-	if (!irq) {
-		dev_err(dev, "no IRQ found\n");
-		error = -ENXIO;
+	drvdata->irq = platform_get_irq(pdev, 0);
+	if (drvdata->irq < 0) {
+		error = drvdata->irq;
 		goto err_disable_clk;
 	}
 
-	drvdata->irq = irq;
 	drvdata->serio = serio;
 	drvdata->dev = dev;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/tablet/aiptek.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/tablet/aiptek.c
@@ -1801,15 +1801,13 @@
 	input_set_abs_params(inputdev, ABS_TILT_Y, AIPTEK_TILT_MIN, AIPTEK_TILT_MAX, 0, 0);
 	input_set_abs_params(inputdev, ABS_WHEEL, AIPTEK_WHEEL_MIN, AIPTEK_WHEEL_MAX - 1, 0, 0);
 
-	/* Verify that a device really has an endpoint */
-	if (intf->altsetting[0].desc.bNumEndpoints < 1) {
+	err = usb_find_common_endpoints(intf->cur_altsetting,
+					NULL, NULL, &endpoint, NULL);
+	if (err) {
 		dev_err(&intf->dev,
-			"interface has %d endpoints, but must have minimum 1\n",
-			intf->altsetting[0].desc.bNumEndpoints);
-		err = -EINVAL;
+			"interface has no int in endpoints, but must have minimum 1\n");
 		goto fail3;
 	}
-	endpoint = &intf->altsetting[0].endpoint[0].desc;
 
 	/* Go set up our URB, which is called when the tablet receives
 	 * input.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/tablet/gtco.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/tablet/gtco.c
@@ -875,18 +875,14 @@
 	}
 
 	/* Sanity check that a device has an endpoint */
-	if (usbinterface->altsetting[0].desc.bNumEndpoints < 1) {
+	if (usbinterface->cur_altsetting->desc.bNumEndpoints < 1) {
 		dev_err(&usbinterface->dev,
 			"Invalid number of endpoints\n");
 		error = -EINVAL;
 		goto err_free_urb;
 	}
 
-	/*
-	 * The endpoint is always altsetting 0, we know this since we know
-	 * this device only has one interrupt endpoint
-	 */
-	endpoint = &usbinterface->altsetting[0].endpoint[0].desc;
+	endpoint = &usbinterface->cur_altsetting->endpoint[0].desc;
 
 	/* Some debug */
 	dev_dbg(&usbinterface->dev, "gtco # interfaces: %d\n", usbinterface->num_altsetting);
@@ -973,7 +969,7 @@
 	input_dev->dev.parent = &usbinterface->dev;
 
 	/* Setup the URB, it will be posted later on open of input device */
-	endpoint = &usbinterface->altsetting[0].endpoint[0].desc;
+	endpoint = &usbinterface->cur_altsetting->endpoint[0].desc;
 
 	usb_fill_int_urb(gtco->urbinfo,
 			 udev,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/tablet/pegasus_notetaker.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/tablet/pegasus_notetaker.c
@@ -275,7 +275,7 @@
 		return -ENODEV;
 
 	/* Sanity check that the device has an endpoint */
-	if (intf->altsetting[0].desc.bNumEndpoints < 1) {
+	if (intf->cur_altsetting->desc.bNumEndpoints < 1) {
 		dev_err(&intf->dev, "Invalid number of endpoints\n");
 		return -EINVAL;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/touchscreen/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/touchscreen/Kconfig
@@ -96,6 +96,7 @@
 config TOUCHSCREEN_ADC
 	tristate "Generic ADC based resistive touchscreen"
 	depends on IIO
+	select IIO_BUFFER
 	select IIO_BUFFER_CB
 	help
 	  Say Y here if you want to use the generic ADC
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/touchscreen/ads7846.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/touchscreen/ads7846.c
@@ -33,6 +33,7 @@
 #include <linux/regulator/consumer.h>
 #include <linux/module.h>
 #include <asm/irq.h>
+#include <asm/unaligned.h>
 
 /*
  * This code has been heavily tested on a Nokia 770, and lightly
@@ -199,6 +200,26 @@
 #define	REF_ON	(READ_12BIT_DFR(x, 1, 1))
 #define	REF_OFF	(READ_12BIT_DFR(y, 0, 0))
 
+static int get_pendown_state(struct ads7846 *ts)
+{
+	if (ts->get_pendown_state)
+		return ts->get_pendown_state();
+
+	return !gpio_get_value(ts->gpio_pendown);
+}
+
+static void ads7846_report_pen_up(struct ads7846 *ts)
+{
+	struct input_dev *input = ts->input;
+
+	input_report_key(input, BTN_TOUCH, 0);
+	input_report_abs(input, ABS_PRESSURE, 0);
+	input_sync(input);
+
+	ts->pendown = false;
+	dev_vdbg(&ts->spi->dev, "UP\n");
+}
+
 /* Must be called with ts->lock held */
 static void ads7846_stop(struct ads7846 *ts)
 {
@@ -215,6 +236,10 @@
 static void ads7846_restart(struct ads7846 *ts)
 {
 	if (!ts->disabled && !ts->suspended) {
+		/* Check if pen was released since last stop */
+		if (ts->pendown && !get_pendown_state(ts))
+			ads7846_report_pen_up(ts);
+
 		/* Tell IRQ thread that it may poll the device. */
 		ts->stopped = false;
 		mb();
@@ -410,7 +435,7 @@
 
 	if (status == 0) {
 		/* BE12 value, then padding */
-		status = be16_to_cpu(*((u16 *)&req->sample[1]));
+		status = get_unaligned_be16(&req->sample[1]);
 		status = status >> 3;
 		status &= 0x0fff;
 	}
@@ -605,14 +630,6 @@
 
 /*--------------------------------------------------------------------------*/
 
-static int get_pendown_state(struct ads7846 *ts)
-{
-	if (ts->get_pendown_state)
-		return ts->get_pendown_state();
-
-	return !gpio_get_value(ts->gpio_pendown);
-}
-
 static void null_wait_for_sync(void)
 {
 }
@@ -773,22 +790,17 @@
 	if (x == MAX_12BIT)
 		x = 0;
 
-	if (ts->model == 7843) {
+	if (ts->model == 7843 || ts->model == 7845) {
 		Rt = ts->pressure_max / 2;
-	} else if (ts->model == 7845) {
-		if (get_pendown_state(ts))
-			Rt = ts->pressure_max / 2;
-		else
-			Rt = 0;
-		dev_vdbg(&ts->spi->dev, "x/y: %d/%d, PD %d\n", x, y, Rt);
 	} else if (likely(x && z1)) {
 		/* compute touch pressure resistance using equation #2 */
 		Rt = z2;
 		Rt -= z1;
-		Rt *= x;
 		Rt *= ts->x_plate_ohms;
+		Rt = DIV_ROUND_CLOSEST(Rt, 16);
+		Rt *= x;
 		Rt /= z1;
-		Rt = (Rt + 2047) >> 12;
+		Rt = DIV_ROUND_CLOSEST(Rt, 256);
 	} else {
 		Rt = 0;
 	}
@@ -867,16 +879,8 @@
 				   msecs_to_jiffies(TS_POLL_PERIOD));
 	}
 
-	if (ts->pendown && !ts->stopped) {
-		struct input_dev *input = ts->input;
-
-		input_report_key(input, BTN_TOUCH, 0);
-		input_report_abs(input, ABS_PRESSURE, 0);
-		input_sync(input);
-
-		ts->pendown = false;
-		dev_vdbg(&ts->spi->dev, "UP\n");
-	}
+	if (ts->pendown && !ts->stopped)
+		ads7846_report_pen_up(ts);
 
 	return IRQ_HANDLED;
 }
@@ -1366,8 +1370,9 @@
 			pdata->y_min ? : 0,
 			pdata->y_max ? : MAX_12BIT,
 			0, 0);
-	input_set_abs_params(input_dev, ABS_PRESSURE,
-			pdata->pressure_min, pdata->pressure_max, 0, 0);
+	if (ts->model != 7845)
+		input_set_abs_params(input_dev, ABS_PRESSURE,
+				pdata->pressure_min, pdata->pressure_max, 0, 0);
 
 	/*
 	 * Parse common framework properties. Must be done here to ensure the
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/touchscreen/atmel_mxt_ts.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -1794,7 +1794,7 @@
 	if (error) {
 		dev_err(&client->dev, "Error %d parsing object table\n", error);
 		mxt_free_object_table(data);
-		goto err_free_mem;
+		return error;
 	}
 
 	data->object_table = (struct mxt_object *)(id_buf + MXT_OBJECT_START);
@@ -3156,6 +3156,8 @@
 
 	mutex_unlock(&input_dev->mutex);
 
+	disable_irq(data->irq);
+
 	return 0;
 }
 
@@ -3168,6 +3170,8 @@
 	if (!input_dev)
 		return 0;
 
+	enable_irq(data->irq);
+
 	mutex_lock(&input_dev->mutex);
 
 	if (input_dev->users)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/touchscreen/edt-ft5x06.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/touchscreen/edt-ft5x06.c
@@ -935,19 +935,25 @@
 
 	error = device_property_read_u32(dev, "offset", &val);
 	if (!error) {
-		edt_ft5x06_register_write(tsdata, reg_addr->reg_offset, val);
+		if (reg_addr->reg_offset != NO_REGISTER)
+			edt_ft5x06_register_write(tsdata,
+						  reg_addr->reg_offset, val);
 		tsdata->offset = val;
 	}
 
 	error = device_property_read_u32(dev, "offset-x", &val);
 	if (!error) {
-		edt_ft5x06_register_write(tsdata, reg_addr->reg_offset_x, val);
+		if (reg_addr->reg_offset_x != NO_REGISTER)
+			edt_ft5x06_register_write(tsdata,
+						  reg_addr->reg_offset_x, val);
 		tsdata->offset_x = val;
 	}
 
 	error = device_property_read_u32(dev, "offset-y", &val);
 	if (!error) {
-		edt_ft5x06_register_write(tsdata, reg_addr->reg_offset_y, val);
+		if (reg_addr->reg_offset_y != NO_REGISTER)
+			edt_ft5x06_register_write(tsdata,
+						  reg_addr->reg_offset_y, val);
 		tsdata->offset_y = val;
 	}
 }
@@ -1041,6 +1047,7 @@
 {
 	const struct edt_i2c_chip_data *chip_data;
 	struct edt_ft5x06_ts_data *tsdata;
+	u8 buf[2] = { 0xfc, 0x00 };
 	struct input_dev *input;
 	unsigned long irq_flags;
 	int error;
@@ -1110,6 +1117,12 @@
 		return error;
 	}
 
+	/*
+	 * Dummy read access. EP0700MLP1 returns bogus data on the first
+	 * register read access and ignores writes.
+	 */
+	edt_ft5x06_ts_readwrite(tsdata->client, 2, buf, 2, buf);
+
 	edt_ft5x06_ts_set_regs(tsdata);
 	edt_ft5x06_ts_get_defaults(&client->dev, tsdata);
 	edt_ft5x06_ts_get_parameters(tsdata);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/touchscreen/elants_i2c.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/touchscreen/elants_i2c.c
@@ -36,6 +36,7 @@
 #include <linux/of.h>
 #include <linux/gpio/consumer.h>
 #include <linux/regulator/consumer.h>
+#include <linux/uuid.h>
 #include <asm/unaligned.h>
 
 /* Device, Driver information */
@@ -1077,14 +1078,12 @@
 	if (IS_ERR_OR_NULL(ts->reset_gpio))
 		return 0;
 
-	gpiod_set_value_cansleep(ts->reset_gpio, 1);
-
 	error = regulator_enable(ts->vcc33);
 	if (error) {
 		dev_err(&ts->client->dev,
 			"failed to enable vcc33 regulator: %d\n",
 			error);
-		goto release_reset_gpio;
+		return error;
 	}
 
 	error = regulator_enable(ts->vccio);
@@ -1093,7 +1092,7 @@
 			"failed to enable vccio regulator: %d\n",
 			error);
 		regulator_disable(ts->vcc33);
-		goto release_reset_gpio;
+		return error;
 	}
 
 	/*
@@ -1102,7 +1101,6 @@
 	 */
 	udelay(ELAN_POWERON_DELAY_USEC);
 
-release_reset_gpio:
 	gpiod_set_value_cansleep(ts->reset_gpio, 0);
 	if (error)
 		return error;
@@ -1127,6 +1125,40 @@
 	}
 }
 
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id i2c_hid_ids[] = {
+	{"ACPI0C50", 0 },
+	{"PNP0C50", 0 },
+	{ },
+};
+
+static const guid_t i2c_hid_guid =
+	GUID_INIT(0x3CDFF6F7, 0x4267, 0x4555,
+		  0xAD, 0x05, 0xB3, 0x0A, 0x3D, 0x89, 0x38, 0xDE);
+
+static bool elants_acpi_is_hid_device(struct device *dev)
+{
+	acpi_handle handle = ACPI_HANDLE(dev);
+	union acpi_object *obj;
+
+	if (acpi_match_device_ids(ACPI_COMPANION(dev), i2c_hid_ids))
+		return false;
+
+	obj = acpi_evaluate_dsm_typed(handle, &i2c_hid_guid, 1, 1, NULL, ACPI_TYPE_INTEGER);
+	if (obj) {
+		ACPI_FREE(obj);
+		return true;
+	}
+
+	return false;
+}
+#else
+static bool elants_acpi_is_hid_device(struct device *dev)
+{
+	return false;
+}
+#endif
+
 static int elants_i2c_probe(struct i2c_client *client,
 			    const struct i2c_device_id *id)
 {
@@ -1135,9 +1167,14 @@
 	unsigned long irqflags;
 	int error;
 
+	/* Don't bind to i2c-hid compatible devices, these are handled by the i2c-hid drv. */
+	if (elants_acpi_is_hid_device(&client->dev)) {
+		dev_warn(&client->dev, "This device appears to be an I2C-HID device, not binding\n");
+		return -ENODEV;
+	}
+
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
-		dev_err(&client->dev,
-			"%s: i2c check functionality error\n", DEVICE_NAME);
+		dev_err(&client->dev, "I2C check functionality error\n");
 		return -ENXIO;
 	}
 
@@ -1171,7 +1208,7 @@
 		return error;
 	}
 
-	ts->reset_gpio = devm_gpiod_get(&client->dev, "reset", GPIOD_OUT_LOW);
+	ts->reset_gpio = devm_gpiod_get(&client->dev, "reset", GPIOD_OUT_HIGH);
 	if (IS_ERR(ts->reset_gpio)) {
 		error = PTR_ERR(ts->reset_gpio);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/touchscreen/elo.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/touchscreen/elo.c
@@ -341,8 +341,10 @@
 	switch (elo->id) {
 
 	case 0: /* 10-byte protocol */
-		if (elo_setup_10(elo))
+		if (elo_setup_10(elo)) {
+			err = -EIO;
 			goto fail3;
+		}
 
 		break;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/touchscreen/goodix.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/touchscreen/goodix.c
@@ -129,6 +129,27 @@
 static const struct dmi_system_id rotated_screen[] = {
 #if defined(CONFIG_DMI) && defined(CONFIG_X86)
 	{
+		.ident = "Teclast X89",
+		.matches = {
+			/* tPAD is too generic, also match on bios date */
+			DMI_MATCH(DMI_BOARD_VENDOR, "TECLAST"),
+			DMI_MATCH(DMI_BOARD_NAME, "tPAD"),
+			DMI_MATCH(DMI_BIOS_DATE, "12/19/2014"),
+		},
+	},
+	{
+		.ident = "Teclast X98 Pro",
+		.matches = {
+			/*
+			 * Only match BIOS date, because the manufacturers
+			 * BIOS does not report the board name at all
+			 * (sometimes)...
+			 */
+			DMI_MATCH(DMI_BOARD_VENDOR, "TECLAST"),
+			DMI_MATCH(DMI_BIOS_DATE, "10/28/2015"),
+		},
+	},
+	{
 		.ident = "WinBook TW100",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "WinBook"),
@@ -149,16 +170,40 @@
 static const struct dmi_system_id nine_bytes_report[] = {
 #if defined(CONFIG_DMI) && defined(CONFIG_X86)
 	{
-		.ident = "Lenovo YogaBook",
-		/* YB1-X91L/F and YB1-X90L/F */
+		/* Lenovo Yoga Book X90F / X90L */
 		.matches = {
-			DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X9")
+			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
+			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"),
+			DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "YETI-11"),
+		}
+	},
+	{
+		/* Lenovo Yoga Book X91F / X91L */
+		.matches = {
+			/* Non exact match to match F + L versions */
+			DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X91"),
 		}
 	},
 #endif
 	{}
 };
 
+/*
+ * Those tablets have their x coordinate inverted
+ */
+static const struct dmi_system_id inverted_x_screen[] = {
+#if defined(CONFIG_DMI) && defined(CONFIG_X86)
+	{
+		.ident = "Cube I15-TC",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Cube"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "I15-TC")
+		},
+	},
+#endif
+	{}
+};
+
 /**
  * goodix_i2c_read - read data from a register of the i2c slave device.
  *
@@ -298,7 +343,7 @@
 	 * The Goodix panel will send spurious interrupts after a
 	 * 'finger up' event, which will always cause a timeout.
 	 */
-	return 0;
+	return -ENOMSG;
 }
 
 static void goodix_ts_report_touch_8b(struct goodix_ts_data *ts, u8 *coor_data)
@@ -771,6 +816,12 @@
 			"Non-standard 9-bytes report format quirk\n");
 	}
 
+	if (dmi_check_system(inverted_x_screen)) {
+		ts->prop.invert_x = true;
+		dev_dbg(&ts->client->dev,
+			"Applying 'inverted x screen' quirk\n");
+	}
+
 	error = input_mt_init_slots(ts->input_dev, ts->max_touch_num,
 				    INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
 	if (error) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/touchscreen/hideep.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/touchscreen/hideep.c
@@ -361,13 +361,16 @@
 	return -EIO;
 }
 
-static void hideep_nvm_unlock(struct hideep_ts *ts)
+static int hideep_nvm_unlock(struct hideep_ts *ts)
 {
 	u32 unmask_code;
+	int error;
 
 	hideep_pgm_w_reg(ts, HIDEEP_FLASH_CFG, HIDEEP_NVM_SFR_RPAGE);
-	hideep_pgm_r_reg(ts, 0x0000000C, &unmask_code);
+	error = hideep_pgm_r_reg(ts, 0x0000000C, &unmask_code);
 	hideep_pgm_w_reg(ts, HIDEEP_FLASH_CFG, HIDEEP_NVM_DEFAULT_PAGE);
+	if (error)
+		return error;
 
 	/* make it unprotected code */
 	unmask_code &= ~HIDEEP_PROT_MODE;
@@ -384,6 +387,8 @@
 	NVM_W_SFR(HIDEEP_NVM_MASK_OFS, ts->nvm_mask);
 	SET_FLASH_HWCONTROL();
 	hideep_pgm_w_reg(ts, HIDEEP_FLASH_CFG, HIDEEP_NVM_DEFAULT_PAGE);
+
+	return 0;
 }
 
 static int hideep_check_status(struct hideep_ts *ts)
@@ -462,7 +467,9 @@
 	u32 addr = 0;
 	int error;
 
-	hideep_nvm_unlock(ts);
+       error = hideep_nvm_unlock(ts);
+       if (error)
+               return error;
 
 	while (ucode_len > 0) {
 		xfer_len = min_t(size_t, ucode_len, HIDEEP_NVM_PAGE_SIZE);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/touchscreen/ili210x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/touchscreen/ili210x.c
@@ -109,7 +109,7 @@
 	if (finger >= ILI210X_TOUCHES)
 		return false;
 
-	if (touchdata[0] & BIT(finger))
+	if (!(touchdata[0] & BIT(finger)))
 		return false;
 
 	*x = get_unaligned_be16(touchdata + 1 + (finger * 4) + 0);
@@ -290,9 +290,9 @@
 		if (error)
 			return error;
 
-		usleep_range(50, 100);
+		usleep_range(12000, 15000);
 		gpiod_set_value_cansleep(reset_gpio, 0);
-		msleep(100);
+		msleep(160);
 	}
 
 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@@ -334,7 +334,12 @@
 	input_set_abs_params(input, ABS_MT_POSITION_X, 0, 0xffff, 0, 0);
 	input_set_abs_params(input, ABS_MT_POSITION_Y, 0, 0xffff, 0, 0);
 	touchscreen_parse_properties(input, true, &priv->prop);
-	input_mt_init_slots(input, priv->max_touches, INPUT_MT_DIRECT);
+
+	error = input_mt_init_slots(input, priv->max_touches, INPUT_MT_DIRECT);
+	if (error) {
+		dev_err(dev, "Unable to set up slots, err: %d\n", error);
+		return error;
+	}
 
 	error = devm_add_action(dev, ili210x_cancel_work, priv);
 	if (error)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/touchscreen/imx6ul_tsc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/touchscreen/imx6ul_tsc.c
@@ -530,20 +530,25 @@
 
 	mutex_lock(&input_dev->mutex);
 
-	if (input_dev->users) {
-		retval = clk_prepare_enable(tsc->adc_clk);
-		if (retval)
-			goto out;
+	if (!input_dev->users)
+		goto out;
 
-		retval = clk_prepare_enable(tsc->tsc_clk);
-		if (retval) {
-			clk_disable_unprepare(tsc->adc_clk);
-			goto out;
-		}
+	retval = clk_prepare_enable(tsc->adc_clk);
+	if (retval)
+		goto out;
 
-		retval = imx6ul_tsc_init(tsc);
+	retval = clk_prepare_enable(tsc->tsc_clk);
+	if (retval) {
+		clk_disable_unprepare(tsc->adc_clk);
+		goto out;
 	}
 
+	retval = imx6ul_tsc_init(tsc);
+	if (retval) {
+		clk_disable_unprepare(tsc->tsc_clk);
+		clk_disable_unprepare(tsc->adc_clk);
+		goto out;
+	}
 out:
 	mutex_unlock(&input_dev->mutex);
 	return retval;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/touchscreen/melfas_mip4.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/touchscreen/melfas_mip4.c
@@ -1453,7 +1453,7 @@
 					      "ce", GPIOD_OUT_LOW);
 	if (IS_ERR(ts->gpio_ce)) {
 		error = PTR_ERR(ts->gpio_ce);
-		if (error != EPROBE_DEFER)
+		if (error != -EPROBE_DEFER)
 			dev_err(&client->dev,
 				"Failed to get gpio: %d\n", error);
 		return error;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/touchscreen/mms114.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/touchscreen/mms114.c
@@ -54,6 +54,7 @@
 enum mms_type {
 	TYPE_MMS114	= 114,
 	TYPE_MMS152	= 152,
+	TYPE_MMS345L	= 345,
 };
 
 struct mms114_data {
@@ -91,15 +92,15 @@
 	if (reg <= MMS114_MODE_CONTROL && reg + len > MMS114_MODE_CONTROL)
 		BUG();
 
-	/* Write register: use repeated start */
+	/* Write register */
 	xfer[0].addr = client->addr;
-	xfer[0].flags = I2C_M_TEN | I2C_M_NOSTART;
+	xfer[0].flags = client->flags & I2C_M_TEN;
 	xfer[0].len = 1;
 	xfer[0].buf = &buf;
 
 	/* Read data */
 	xfer[1].addr = client->addr;
-	xfer[1].flags = I2C_M_RD;
+	xfer[1].flags = (client->flags & I2C_M_TEN) | I2C_M_RD;
 	xfer[1].len = len;
 	xfer[1].buf = val;
 
@@ -250,6 +251,15 @@
 	int error;
 
 	switch (data->type) {
+	case TYPE_MMS345L:
+		error = __mms114_read_reg(data, MMS152_FW_REV, 3, buf);
+		if (error)
+			return error;
+
+		dev_info(dev, "TSP FW Rev: bootloader 0x%x / core 0x%x / config 0x%x\n",
+			 buf[0], buf[1], buf[2]);
+		break;
+
 	case TYPE_MMS152:
 		error = __mms114_read_reg(data, MMS152_FW_REV, 3, buf);
 		if (error)
@@ -287,8 +297,8 @@
 	if (error < 0)
 		return error;
 
-	/* MMS152 has no configuration or power on registers */
-	if (data->type == TYPE_MMS152)
+	/* Only MMS114 has configuration and power on registers */
+	if (data->type != TYPE_MMS114)
 		return 0;
 
 	error = mms114_set_active(data, true);
@@ -428,10 +438,8 @@
 	const void *match_data;
 	int error;
 
-	if (!i2c_check_functionality(client->adapter,
-				I2C_FUNC_PROTOCOL_MANGLING)) {
-		dev_err(&client->dev,
-			"Need i2c bus that supports protocol mangling\n");
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		dev_err(&client->dev, "Not supported I2C adapter\n");
 		return -ENODEV;
 	}
 
@@ -600,6 +608,9 @@
 	}, {
 		.compatible = "melfas,mms152",
 		.data = (void *)TYPE_MMS152,
+	}, {
+		.compatible = "melfas,mms345l",
+		.data = (void *)TYPE_MMS345L,
 	},
 	{ }
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/touchscreen/of_touchscreen.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/touchscreen/of_touchscreen.c
@@ -77,12 +77,12 @@
 	axis = multitouch ? ABS_MT_POSITION_X : ABS_X;
 	data_present = touchscreen_get_prop_u32(dev, "touchscreen-min-x",
 						input_abs_get_min(input, axis),
-						&minimum) |
-		       touchscreen_get_prop_u32(dev, "touchscreen-size-x",
+						&minimum);
+	data_present |= touchscreen_get_prop_u32(dev, "touchscreen-size-x",
 						input_abs_get_max(input,
 								  axis) + 1,
-						&maximum) |
-		       touchscreen_get_prop_u32(dev, "touchscreen-fuzz-x",
+						&maximum);
+	data_present |= touchscreen_get_prop_u32(dev, "touchscreen-fuzz-x",
 						input_abs_get_fuzz(input, axis),
 						&fuzz);
 	if (data_present)
@@ -91,12 +91,12 @@
 	axis = multitouch ? ABS_MT_POSITION_Y : ABS_Y;
 	data_present = touchscreen_get_prop_u32(dev, "touchscreen-min-y",
 						input_abs_get_min(input, axis),
-						&minimum) |
-		       touchscreen_get_prop_u32(dev, "touchscreen-size-y",
+						&minimum);
+	data_present |= touchscreen_get_prop_u32(dev, "touchscreen-size-y",
 						input_abs_get_max(input,
 								  axis) + 1,
-						&maximum) |
-		       touchscreen_get_prop_u32(dev, "touchscreen-fuzz-y",
+						&maximum);
+	data_present |= touchscreen_get_prop_u32(dev, "touchscreen-fuzz-y",
 						input_abs_get_fuzz(input, axis),
 						&fuzz);
 	if (data_present)
@@ -106,11 +106,11 @@
 	data_present = touchscreen_get_prop_u32(dev,
 						"touchscreen-max-pressure",
 						input_abs_get_max(input, axis),
-						&maximum) |
-		       touchscreen_get_prop_u32(dev,
-						"touchscreen-fuzz-pressure",
-						input_abs_get_fuzz(input, axis),
-						&fuzz);
+						&maximum);
+	data_present |= touchscreen_get_prop_u32(dev,
+						 "touchscreen-fuzz-pressure",
+						 input_abs_get_fuzz(input, axis),
+						 &fuzz);
 	if (data_present)
 		touchscreen_set_params(input, axis, 0, maximum, fuzz);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/touchscreen/raspberrypi-ts.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/touchscreen/raspberrypi-ts.c
@@ -137,7 +137,7 @@
 		return -ENOENT;
 	}
 
-	fw = rpi_firmware_get(fw_node);
+	fw = devm_rpi_firmware_get(&pdev->dev, fw_node);
 	of_node_put(fw_node);
 	if (!fw)
 		return -EPROBE_DEFER;
@@ -164,7 +164,6 @@
 	touchbuf = (u32)ts->fw_regs_phys;
 	error = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF,
 				      &touchbuf, sizeof(touchbuf));
-
 	if (error || touchbuf != 0) {
 		dev_warn(dev, "Failed to set touchbuf, %d\n", error);
 		return error;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/touchscreen/raydium_i2c_ts.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/touchscreen/raydium_i2c_ts.c
@@ -410,6 +410,7 @@
 				    enum raydium_bl_ack state)
 {
 	int error;
+	static const u8 cmd[] = { 0xFF, 0x39 };
 
 	error = raydium_i2c_send(client, RM_CMD_BOOT_WRT, data, len);
 	if (error) {
@@ -418,7 +419,7 @@
 		return error;
 	}
 
-	error = raydium_i2c_send(client, RM_CMD_BOOT_ACK, NULL, 0);
+	error = raydium_i2c_send(client, RM_CMD_BOOT_ACK, cmd, sizeof(cmd));
 	if (error) {
 		dev_err(&client->dev, "Ack obj command failed: %d\n", error);
 		return error;
@@ -432,7 +433,7 @@
 	return 0;
 }
 
-static bool raydium_i2c_boot_trigger(struct i2c_client *client)
+static int raydium_i2c_boot_trigger(struct i2c_client *client)
 {
 	static const u8 cmd[7][6] = {
 		{ 0x08, 0x0C, 0x09, 0x00, 0x50, 0xD7 },
@@ -457,10 +458,10 @@
 		}
 	}
 
-	return false;
+	return 0;
 }
 
-static bool raydium_i2c_fw_trigger(struct i2c_client *client)
+static int raydium_i2c_fw_trigger(struct i2c_client *client)
 {
 	static const u8 cmd[5][11] = {
 		{ 0, 0x09, 0x71, 0x0C, 0x09, 0x00, 0x50, 0xD7, 0, 0, 0 },
@@ -483,7 +484,7 @@
 		}
 	}
 
-	return false;
+	return 0;
 }
 
 static int raydium_i2c_check_path(struct i2c_client *client)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/touchscreen/s6sy761.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/touchscreen/s6sy761.c
@@ -145,8 +145,8 @@
 	u8 major = event[4];
 	u8 minor = event[5];
 	u8 z = event[6] & S6SY761_MASK_Z;
-	u16 x = (event[1] << 3) | ((event[3] & S6SY761_MASK_X) >> 4);
-	u16 y = (event[2] << 3) | (event[3] & S6SY761_MASK_Y);
+	u16 x = (event[1] << 4) | ((event[3] & S6SY761_MASK_X) >> 4);
+	u16 y = (event[2] << 4) | (event[3] & S6SY761_MASK_Y);
 
 	input_mt_slot(sdata->input, tid);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/touchscreen/silead.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/touchscreen/silead.c
@@ -20,6 +20,7 @@
 #include <linux/input/mt.h>
 #include <linux/input/touchscreen.h>
 #include <linux/pm.h>
+#include <linux/pm_runtime.h>
 #include <linux/irq.h>
 #include <linux/regulator/consumer.h>
 
@@ -69,7 +70,6 @@
 	struct regulator_bulk_data regulators[2];
 	char fw_name[64];
 	struct touchscreen_properties prop;
-	u32 max_fingers;
 	u32 chip_id;
 	struct input_mt_pos pos[SILEAD_MAX_FINGERS];
 	int slots[SILEAD_MAX_FINGERS];
@@ -97,7 +97,7 @@
 	input_set_abs_params(data->input, ABS_MT_POSITION_Y, 0, 4095, 0, 0);
 	touchscreen_parse_properties(data->input, true, &data->prop);
 
-	input_mt_init_slots(data->input, data->max_fingers,
+	input_mt_init_slots(data->input, SILEAD_MAX_FINGERS,
 			    INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED |
 			    INPUT_MT_TRACK);
 
@@ -144,10 +144,10 @@
 		return;
 	}
 
-	if (buf[0] > data->max_fingers) {
+	if (buf[0] > SILEAD_MAX_FINGERS) {
 		dev_warn(dev, "More touches reported then supported %d > %d\n",
-			 buf[0], data->max_fingers);
-		buf[0] = data->max_fingers;
+			 buf[0], SILEAD_MAX_FINGERS);
+		buf[0] = SILEAD_MAX_FINGERS;
 	}
 
 	touch_nr = 0;
@@ -199,7 +199,6 @@
 
 static int silead_ts_init(struct i2c_client *client)
 {
-	struct silead_ts_data *data = i2c_get_clientdata(client);
 	int error;
 
 	error = i2c_smbus_write_byte_data(client, SILEAD_REG_RESET,
@@ -209,7 +208,7 @@
 	usleep_range(SILEAD_CMD_SLEEP_MIN, SILEAD_CMD_SLEEP_MAX);
 
 	error = i2c_smbus_write_byte_data(client, SILEAD_REG_TOUCH_NR,
-					data->max_fingers);
+					  SILEAD_MAX_FINGERS);
 	if (error)
 		goto i2c_write_err;
 	usleep_range(SILEAD_CMD_SLEEP_MIN, SILEAD_CMD_SLEEP_MAX);
@@ -335,10 +334,8 @@
 
 	error = i2c_smbus_read_i2c_block_data(client, SILEAD_REG_ID,
 					      sizeof(chip_id), (u8 *)&chip_id);
-	if (error < 0) {
-		dev_err(&client->dev, "Chip ID read error %d\n", error);
+	if (error < 0)
 		return error;
-	}
 
 	data->chip_id = le32_to_cpu(chip_id);
 	dev_info(&client->dev, "Silead chip ID: 0x%8X", data->chip_id);
@@ -351,12 +348,49 @@
 	int error;
 	u32 status;
 
+	/*
+	 * Some buggy BIOS-es bring up the chip in a stuck state where it
+	 * blocks the I2C bus. The following steps are necessary to
+	 * unstuck the chip / bus:
+	 * 1. Turn off the Silead chip.
+	 * 2. Try to do an I2C transfer with the chip, this will fail in
+	 *    response to which the I2C-bus-driver will call:
+	 *    i2c_recover_bus() which will unstuck the I2C-bus. Note the
+	 *    unstuck-ing of the I2C bus only works if we first drop the
+	 *    chip off the bus by turning it off.
+	 * 3. Turn the chip back on.
+	 *
+	 * On the x86/ACPI systems were this problem is seen, step 1. and
+	 * 3. require making ACPI calls and dealing with ACPI Power
+	 * Resources. The workaround below runtime-suspends the chip to
+	 * turn it off, leaving it up to the ACPI subsystem to deal with
+	 * this.
+	 */
+
+	if (device_property_read_bool(&client->dev,
+				      "silead,stuck-controller-bug")) {
+		pm_runtime_set_active(&client->dev);
+		pm_runtime_enable(&client->dev);
+		pm_runtime_allow(&client->dev);
+
+		pm_runtime_suspend(&client->dev);
+
+		dev_warn(&client->dev, FW_BUG "Stuck I2C bus: please ignore the next 'controller timed out' error\n");
+		silead_ts_get_id(client);
+
+		/* The forbid will also resume the device */
+		pm_runtime_forbid(&client->dev);
+		pm_runtime_disable(&client->dev);
+	}
+
 	silead_ts_set_power(client, SILEAD_POWER_OFF);
 	silead_ts_set_power(client, SILEAD_POWER_ON);
 
 	error = silead_ts_get_id(client);
-	if (error)
+	if (error) {
+		dev_err(&client->dev, "Chip ID read error %d\n", error);
 		return error;
+	}
 
 	error = silead_ts_init(client);
 	if (error)
@@ -401,13 +435,6 @@
 	const char *str;
 	int error;
 
-	error = device_property_read_u32(dev, "silead,max-fingers",
-					 &data->max_fingers);
-	if (error) {
-		dev_dbg(dev, "Max fingers read error %d\n", error);
-		data->max_fingers = 5; /* Most devices handle up-to 5 fingers */
-	}
-
 	error = device_property_read_string(dev, "firmware-name", &str);
 	if (!error)
 		snprintf(data->fw_name, sizeof(data->fw_name),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/touchscreen/st1232.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/touchscreen/st1232.c
@@ -149,6 +149,11 @@
 		gpiod_set_value_cansleep(ts->reset_gpio, !poweron);
 }
 
+static void st1232_ts_power_off(void *data)
+{
+	st1232_ts_power(data, false);
+}
+
 static const struct st_chip_info st1232_chip_info = {
 	.have_z		= true,
 	.max_x		= 0x31f, /* 800 - 1 */
@@ -229,6 +234,13 @@
 
 	st1232_ts_power(ts, true);
 
+	error = devm_add_action_or_reset(&client->dev, st1232_ts_power_off, ts);
+	if (error) {
+		dev_err(&client->dev,
+			"Failed to install power off action: %d\n", error);
+		return error;
+	}
+
 	input_dev->name = "st1232-touchscreen";
 	input_dev->id.bustype = BUS_I2C;
 	input_dev->dev.parent = &client->dev;
@@ -271,15 +283,6 @@
 	return 0;
 }
 
-static int st1232_ts_remove(struct i2c_client *client)
-{
-	struct st1232_ts_data *ts = i2c_get_clientdata(client);
-
-	st1232_ts_power(ts, false);
-
-	return 0;
-}
-
 static int __maybe_unused st1232_ts_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
@@ -329,7 +332,6 @@
 
 static struct i2c_driver st1232_ts_driver = {
 	.probe		= st1232_ts_probe,
-	.remove		= st1232_ts_remove,
 	.id_table	= st1232_ts_id,
 	.driver = {
 		.name	= ST1232_TS_NAME,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/touchscreen/stmfts.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/touchscreen/stmfts.c
@@ -337,13 +337,15 @@
 	struct stmfts_data *sdata = input_get_drvdata(dev);
 	int err;
 
-	err = pm_runtime_get_sync(&sdata->client->dev);
-	if (err < 0)
+	err = pm_runtime_resume_and_get(&sdata->client->dev);
+	if (err)
 		return err;
 
 	err = i2c_smbus_write_byte(sdata->client, STMFTS_MS_MT_SENSE_ON);
-	if (err)
+	if (err) {
+		pm_runtime_put_sync(&sdata->client->dev);
 		return err;
+	}
 
 	mutex_lock(&sdata->mutex);
 	sdata->running = true;
@@ -479,7 +481,7 @@
 
 	mutex_lock(&sdata->mutex);
 
-	if (value & sdata->hover_enabled)
+	if (value && sdata->hover_enabled)
 		goto out;
 
 	if (sdata->running)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/touchscreen/sun4i-ts.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/touchscreen/sun4i-ts.c
@@ -237,6 +237,7 @@
 	struct device *dev = &pdev->dev;
 	struct device_node *np = dev->of_node;
 	struct device *hwmon;
+	struct thermal_zone_device *thermal;
 	int error;
 	u32 reg;
 	bool ts_attached;
@@ -355,7 +356,10 @@
 	if (IS_ERR(hwmon))
 		return PTR_ERR(hwmon);
 
-	devm_thermal_zone_of_sensor_register(ts->dev, 0, ts, &sun4i_ts_tz_ops);
+	thermal = devm_thermal_zone_of_sensor_register(ts->dev, 0, ts,
+						       &sun4i_ts_tz_ops);
+	if (IS_ERR(thermal))
+		return PTR_ERR(thermal);
 
 	writel(TEMP_IRQ_EN(1), ts->base + TP_INT_FIFOC);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/touchscreen/sur40.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/touchscreen/sur40.c
@@ -653,7 +653,7 @@
 	int error;
 
 	/* Check if we really have the right interface. */
-	iface_desc = &interface->altsetting[0];
+	iface_desc = interface->cur_altsetting;
 	if (iface_desc->desc.bInterfaceClass != 0xFF)
 		return -ENODEV;
 
@@ -774,6 +774,7 @@
 		dev_err(&interface->dev,
 			"Unable to register video controls.");
 		v4l2_ctrl_handler_free(&sur40->hdl);
+		error = sur40->hdl.error;
 		goto err_unreg_v4l2;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/input/touchscreen/usbtouchscreen.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/input/touchscreen/usbtouchscreen.c
@@ -182,6 +182,7 @@
 #endif
 
 #ifdef CONFIG_TOUCHSCREEN_USB_IRTOUCH
+	{USB_DEVICE(0x255e, 0x0001), .driver_info = DEVTYPE_IRTOUCH},
 	{USB_DEVICE(0x595a, 0x0001), .driver_info = DEVTYPE_IRTOUCH},
 	{USB_DEVICE(0x6615, 0x0001), .driver_info = DEVTYPE_IRTOUCH},
 	{USB_DEVICE(0x6615, 0x0012), .driver_info = DEVTYPE_IRTOUCH_HIRES},
@@ -250,7 +251,7 @@
 	int ret;
 	struct usb_device *udev = interface_to_usbdev(usbtouch->interface);
 
-	ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+	ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
 	                      0x01, 0x02, 0x0000, 0x0081,
 	                      NULL, 0, USB_CTRL_SET_TIMEOUT);
 
@@ -530,7 +531,7 @@
 	if (ret)
 		return ret;
 
-	ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+	ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
 	                      MTOUCHUSB_RESET,
 	                      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 	                      1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
@@ -542,7 +543,7 @@
 	msleep(150);
 
 	for (i = 0; i < 3; i++) {
-		ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+		ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
 				      MTOUCHUSB_ASYNC_REPORT,
 				      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 				      1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT);
@@ -721,7 +722,7 @@
 	}
 
 	/* start sending data */
-	ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0),
+	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 	                      TSC10_CMD_DATA1,
 	                      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 	                      0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/interconnect/core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/interconnect/core.c
@@ -19,39 +19,13 @@
 #include <linux/of.h>
 #include <linux/overflow.h>
 
+#include "internal.h"
+
 static DEFINE_IDR(icc_idr);
 static LIST_HEAD(icc_providers);
 static DEFINE_MUTEX(icc_lock);
 static struct dentry *icc_debugfs_dir;
 
-/**
- * struct icc_req - constraints that are attached to each node
- * @req_node: entry in list of requests for the particular @node
- * @node: the interconnect node to which this constraint applies
- * @dev: reference to the device that sets the constraints
- * @tag: path tag (optional)
- * @avg_bw: an integer describing the average bandwidth in kBps
- * @peak_bw: an integer describing the peak bandwidth in kBps
- */
-struct icc_req {
-	struct hlist_node req_node;
-	struct icc_node *node;
-	struct device *dev;
-	u32 tag;
-	u32 avg_bw;
-	u32 peak_bw;
-};
-
-/**
- * struct icc_path - interconnect path structure
- * @num_nodes: number of hops (nodes)
- * @reqs: array of the requests applicable to this path of nodes
- */
-struct icc_path {
-	size_t num_nodes;
-	struct icc_req reqs[];
-};
-
 static void icc_summary_show_one(struct seq_file *s, struct icc_node *n)
 {
 	if (!n)
@@ -117,6 +91,7 @@
 		hlist_add_head(&path->reqs[i].req_node, &node->req_list);
 		path->reqs[i].node = node;
 		path->reqs[i].dev = dev;
+		path->reqs[i].enabled = true;
 		/* reference to previous node was saved during path traversal */
 		node = node->reverse;
 	}
@@ -201,6 +176,7 @@
 {
 	struct icc_provider *p = node->provider;
 	struct icc_req *r;
+	u32 avg_bw, peak_bw;
 
 	node->avg_bw = 0;
 	node->peak_bw = 0;
@@ -208,9 +184,17 @@
 	if (p->pre_aggregate)
 		p->pre_aggregate(node);
 
-	hlist_for_each_entry(r, &node->req_list, req_node)
-		p->aggregate(node, r->tag, r->avg_bw, r->peak_bw,
+	hlist_for_each_entry(r, &node->req_list, req_node) {
+		if (r->enabled) {
+			avg_bw = r->avg_bw;
+			peak_bw = r->peak_bw;
+		} else {
+			avg_bw = 0;
+			peak_bw = 0;
+		}
+		p->aggregate(node, r->tag, avg_bw, peak_bw,
 			     &node->avg_bw, &node->peak_bw);
+	}
 
 	return 0;
 }
@@ -296,6 +280,9 @@
 	}
 	mutex_unlock(&icc_lock);
 
+	if (!node)
+		return ERR_PTR(-EINVAL);
+
 	return node;
 }
 
@@ -475,6 +462,39 @@
 }
 EXPORT_SYMBOL_GPL(icc_set_bw);
 
+static int __icc_enable(struct icc_path *path, bool enable)
+{
+	int i;
+
+	if (!path)
+		return 0;
+
+	if (WARN_ON(IS_ERR(path) || !path->num_nodes))
+		return -EINVAL;
+
+	mutex_lock(&icc_lock);
+
+	for (i = 0; i < path->num_nodes; i++)
+		path->reqs[i].enabled = enable;
+
+	mutex_unlock(&icc_lock);
+
+	return icc_set_bw(path, path->reqs[0].avg_bw,
+			  path->reqs[0].peak_bw);
+}
+
+int icc_enable(struct icc_path *path)
+{
+	return __icc_enable(path, true);
+}
+EXPORT_SYMBOL_GPL(icc_enable);
+
+int icc_disable(struct icc_path *path)
+{
+	return __icc_enable(path, false);
+}
+EXPORT_SYMBOL_GPL(icc_disable);
+
 /**
  * icc_get() - return a handle for path between two endpoints
  * @dev: the device requesting the path
@@ -612,6 +632,10 @@
 
 	mutex_unlock(&icc_lock);
 
+	if (!node)
+		return;
+
+	kfree(node->links);
 	kfree(node);
 }
 EXPORT_SYMBOL_GPL(icc_node_destroy);
@@ -704,6 +728,8 @@
 		       GFP_KERNEL);
 	if (new)
 		src->links = new;
+	else
+		ret = -ENOMEM;
 
 out:
 	mutex_unlock(&icc_lock);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/interconnect/internal.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/interconnect/internal.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Interconnect framework internal structs
+ *
+ * Copyright (c) 2019, Linaro Ltd.
+ * Author: Georgi Djakov <georgi.djakov@linaro.org>
+ */
+
+#ifndef __DRIVERS_INTERCONNECT_INTERNAL_H
+#define __DRIVERS_INTERCONNECT_INTERNAL_H
+
+/**
+ * struct icc_req - constraints that are attached to each node
+ * @req_node: entry in list of requests for the particular @node
+ * @node: the interconnect node to which this constraint applies
+ * @dev: reference to the device that sets the constraints
+ * @enabled: indicates whether the path with this request is enabled
+ * @tag: path tag (optional)
+ * @avg_bw: an integer describing the average bandwidth in kBps
+ * @peak_bw: an integer describing the peak bandwidth in kBps
+ */
+struct icc_req {
+	struct hlist_node req_node;
+	struct icc_node *node;
+	struct device *dev;
+	bool enabled;
+	u32 tag;
+	u32 avg_bw;
+	u32 peak_bw;
+};
+
+/**
+ * struct icc_path - interconnect path structure
+ * @num_nodes: number of hops (nodes)
+ * @reqs: array of the requests applicable to this path of nodes
+ */
+struct icc_path {
+	size_t num_nodes;
+	struct icc_req reqs[];
+};
+
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/interconnect/qcom/qcs404.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/interconnect/qcom/qcs404.c
@@ -157,8 +157,8 @@
 	}
 
 DEFINE_QNODE(mas_apps_proc, QCS404_MASTER_AMPSS_M0, 8, 0, -1, QCS404_SLAVE_EBI_CH0, QCS404_BIMC_SNOC_SLV);
-DEFINE_QNODE(mas_oxili, QCS404_MASTER_GRAPHICS_3D, 8, 6, -1, QCS404_SLAVE_EBI_CH0, QCS404_BIMC_SNOC_SLV);
-DEFINE_QNODE(mas_mdp, QCS404_MASTER_MDP_PORT0, 8, 8, -1, QCS404_SLAVE_EBI_CH0, QCS404_BIMC_SNOC_SLV);
+DEFINE_QNODE(mas_oxili, QCS404_MASTER_GRAPHICS_3D, 8, -1, -1, QCS404_SLAVE_EBI_CH0, QCS404_BIMC_SNOC_SLV);
+DEFINE_QNODE(mas_mdp, QCS404_MASTER_MDP_PORT0, 8, -1, -1, QCS404_SLAVE_EBI_CH0, QCS404_BIMC_SNOC_SLV);
 DEFINE_QNODE(mas_snoc_bimc_1, QCS404_SNOC_BIMC_1_MAS, 8, 76, -1, QCS404_SLAVE_EBI_CH0);
 DEFINE_QNODE(mas_tcu_0, QCS404_MASTER_TCU_0, 8, -1, -1, QCS404_SLAVE_EBI_CH0, QCS404_BIMC_SNOC_SLV);
 DEFINE_QNODE(mas_spdm, QCS404_MASTER_SPDM, 4, -1, -1, QCS404_PNOC_INT_3);
@@ -414,7 +414,7 @@
 	struct icc_provider *provider;
 	struct qcom_icc_node **qnodes;
 	struct qcom_icc_provider *qp;
-	struct icc_node *node;
+	struct icc_node *node, *tmp;
 	size_t num_nodes, i;
 	int ret;
 
@@ -494,7 +494,7 @@
 
 	return 0;
 err:
-	list_for_each_entry(node, &provider->nodes, node_list) {
+	list_for_each_entry_safe(node, tmp, &provider->nodes, node_list) {
 		icc_node_del(node);
 		icc_node_destroy(node->id);
 	}
@@ -508,9 +508,9 @@
 {
 	struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
 	struct icc_provider *provider = &qp->provider;
-	struct icc_node *n;
+	struct icc_node *n, *tmp;
 
-	list_for_each_entry(n, &provider->nodes, node_list) {
+	list_for_each_entry_safe(n, tmp, &provider->nodes, node_list) {
 		icc_node_del(n);
 		icc_node_destroy(n->id);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/interconnect/qcom/sdm845.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/interconnect/qcom/sdm845.c
@@ -868,9 +868,9 @@
 {
 	struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
 	struct icc_provider *provider = &qp->provider;
-	struct icc_node *n;
+	struct icc_node *n, *tmp;
 
-	list_for_each_entry(n, &provider->nodes, node_list) {
+	list_for_each_entry_safe(n, tmp, &provider->nodes, node_list) {
 		icc_node_del(n);
 		icc_node_destroy(n->id);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iommu/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/iommu/Kconfig
@@ -138,7 +138,7 @@
 	select PCI_PASID
 	select IOMMU_API
 	select IOMMU_IOVA
-	depends on X86_64 && PCI && ACPI
+	depends on X86_64 && PCI && ACPI && HAVE_CMPXCHG_DOUBLE
 	---help---
 	  With this option you can enable support for AMD IOMMU hardware in
 	  your system. An IOMMU is a hardware component which provides
@@ -205,7 +205,7 @@
 
 config INTEL_IOMMU_SVM
 	bool "Support for Shared Virtual Memory with Intel IOMMU"
-	depends on INTEL_IOMMU && X86
+	depends on INTEL_IOMMU && X86_64
 	select PCI_PASID
 	select MMU_NOTIFIER
 	help
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iommu/amd_iommu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iommu/amd_iommu.c
@@ -226,71 +226,58 @@
 	return NULL;
 }
 
-static int __last_alias(struct pci_dev *pdev, u16 alias, void *data)
+static int clone_alias(struct pci_dev *pdev, u16 alias, void *data)
 {
-	*(u16 *)data = alias;
-	return 0;
-}
-
-static u16 get_alias(struct device *dev)
-{
-	struct pci_dev *pdev = to_pci_dev(dev);
-	u16 devid, ivrs_alias, pci_alias;
+	u16 devid = pci_dev_id(pdev);
 
-	/* The callers make sure that get_device_id() does not fail here */
-	devid = get_device_id(dev);
-
-	/* For ACPI HID devices, we simply return the devid as such */
-	if (!dev_is_pci(dev))
-		return devid;
+	if (devid == alias)
+		return 0;
 
-	ivrs_alias = amd_iommu_alias_table[devid];
+	amd_iommu_rlookup_table[alias] =
+		amd_iommu_rlookup_table[devid];
+	memcpy(amd_iommu_dev_table[alias].data,
+	       amd_iommu_dev_table[devid].data,
+	       sizeof(amd_iommu_dev_table[alias].data));
 
-	pci_for_each_dma_alias(pdev, __last_alias, &pci_alias);
+	return 0;
+}
 
-	if (ivrs_alias == pci_alias)
-		return ivrs_alias;
+static void clone_aliases(struct pci_dev *pdev)
+{
+	if (!pdev)
+		return;
 
 	/*
-	 * DMA alias showdown
-	 *
-	 * The IVRS is fairly reliable in telling us about aliases, but it
-	 * can't know about every screwy device.  If we don't have an IVRS
-	 * reported alias, use the PCI reported alias.  In that case we may
-	 * still need to initialize the rlookup and dev_table entries if the
-	 * alias is to a non-existent device.
+	 * The IVRS alias stored in the alias table may not be
+	 * part of the PCI DMA aliases if it's bus differs
+	 * from the original device.
 	 */
-	if (ivrs_alias == devid) {
-		if (!amd_iommu_rlookup_table[pci_alias]) {
-			amd_iommu_rlookup_table[pci_alias] =
-				amd_iommu_rlookup_table[devid];
-			memcpy(amd_iommu_dev_table[pci_alias].data,
-			       amd_iommu_dev_table[devid].data,
-			       sizeof(amd_iommu_dev_table[pci_alias].data));
-		}
+	clone_alias(pdev, amd_iommu_alias_table[pci_dev_id(pdev)], NULL);
 
-		return pci_alias;
-	}
+	pci_for_each_dma_alias(pdev, clone_alias, NULL);
+}
 
-	pci_info(pdev, "Using IVRS reported alias %02x:%02x.%d "
-		"for device [%04x:%04x], kernel reported alias "
-		"%02x:%02x.%d\n", PCI_BUS_NUM(ivrs_alias), PCI_SLOT(ivrs_alias),
-		PCI_FUNC(ivrs_alias), pdev->vendor, pdev->device,
-		PCI_BUS_NUM(pci_alias), PCI_SLOT(pci_alias),
-		PCI_FUNC(pci_alias));
+static struct pci_dev *setup_aliases(struct device *dev)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	u16 ivrs_alias;
+
+	/* For ACPI HID devices, there are no aliases */
+	if (!dev_is_pci(dev))
+		return NULL;
 
 	/*
-	 * If we don't have a PCI DMA alias and the IVRS alias is on the same
-	 * bus, then the IVRS table may know about a quirk that we don't.
+	 * Add the IVRS alias to the pci aliases if it is on the same
+	 * bus. The IVRS table may know about a quirk that we don't.
 	 */
-	if (pci_alias == devid &&
-	    PCI_BUS_NUM(ivrs_alias) == pdev->bus->number) {
-		pci_add_dma_alias(pdev, ivrs_alias & 0xff);
-		pci_info(pdev, "Added PCI DMA alias %02x.%d\n",
-			PCI_SLOT(ivrs_alias), PCI_FUNC(ivrs_alias));
-	}
+	ivrs_alias = amd_iommu_alias_table[pci_dev_id(pdev)];
+	if (ivrs_alias != pci_dev_id(pdev) &&
+	    PCI_BUS_NUM(ivrs_alias) == pdev->bus->number)
+		pci_add_dma_alias(pdev, ivrs_alias & 0xff, 1);
+
+	clone_aliases(pdev);
 
-	return ivrs_alias;
+	return pdev;
 }
 
 static struct iommu_dev_data *find_dev_data(u16 devid)
@@ -428,7 +415,7 @@
 	if (!dev_data)
 		return -ENOMEM;
 
-	dev_data->alias = get_alias(dev);
+	dev_data->pdev = setup_aliases(dev);
 
 	/*
 	 * By default we use passthrough mode for IOMMUv2 capable device.
@@ -453,20 +440,16 @@
 
 static void iommu_ignore_device(struct device *dev)
 {
-	u16 alias;
 	int devid;
 
 	devid = get_device_id(dev);
 	if (devid < 0)
 		return;
 
-	alias = get_alias(dev);
-
+	amd_iommu_rlookup_table[devid] = NULL;
 	memset(&amd_iommu_dev_table[devid], 0, sizeof(struct dev_table_entry));
-	memset(&amd_iommu_dev_table[alias], 0, sizeof(struct dev_table_entry));
 
-	amd_iommu_rlookup_table[devid] = NULL;
-	amd_iommu_rlookup_table[alias] = NULL;
+	setup_aliases(dev);
 }
 
 static void iommu_uninit_device(struct device *dev)
@@ -1236,6 +1219,13 @@
 	return iommu_queue_command(iommu, &cmd);
 }
 
+static int device_flush_dte_alias(struct pci_dev *pdev, u16 alias, void *data)
+{
+	struct amd_iommu *iommu = data;
+
+	return iommu_flush_dte(iommu, alias);
+}
+
 /*
  * Command send function for invalidating a device table entry
  */
@@ -1246,14 +1236,22 @@
 	int ret;
 
 	iommu = amd_iommu_rlookup_table[dev_data->devid];
-	alias = dev_data->alias;
 
-	ret = iommu_flush_dte(iommu, dev_data->devid);
-	if (!ret && alias != dev_data->devid)
-		ret = iommu_flush_dte(iommu, alias);
+	if (dev_data->pdev)
+		ret = pci_for_each_dma_alias(dev_data->pdev,
+					     device_flush_dte_alias, iommu);
+	else
+		ret = iommu_flush_dte(iommu, dev_data->devid);
 	if (ret)
 		return ret;
 
+	alias = amd_iommu_alias_table[dev_data->devid];
+	if (alias != dev_data->devid) {
+		ret = iommu_flush_dte(iommu, alias);
+		if (ret)
+			return ret;
+	}
+
 	if (dev_data->ats.enabled)
 		ret = device_flush_iotlb(dev_data, 0, ~0UL);
 
@@ -1471,25 +1469,27 @@
 	bool ret = false;
 	u64 *pte;
 
+	pte = (void *)get_zeroed_page(gfp);
+	if (!pte)
+		return false;
+
 	spin_lock_irqsave(&domain->lock, flags);
 
 	if (address <= PM_LEVEL_SIZE(domain->mode) ||
 	    WARN_ON_ONCE(domain->mode == PAGE_MODE_6_LEVEL))
 		goto out;
 
-	pte = (void *)get_zeroed_page(gfp);
-	if (!pte)
-		goto out;
-
 	*pte             = PM_LEVEL_PDE(domain->mode,
 					iommu_virt_to_phys(domain->pt_root));
 	domain->pt_root  = pte;
 	domain->mode    += 1;
 
+	pte = NULL;
 	ret = true;
 
 out:
 	spin_unlock_irqrestore(&domain->lock, flags);
+	free_page((unsigned long)pte);
 
 	return ret;
 }
@@ -2035,11 +2035,9 @@
 		      struct protection_domain *domain)
 {
 	struct amd_iommu *iommu;
-	u16 alias;
 	bool ats;
 
 	iommu = amd_iommu_rlookup_table[dev_data->devid];
-	alias = dev_data->alias;
 	ats   = dev_data->ats.enabled;
 
 	/* Update data structures */
@@ -2052,8 +2050,7 @@
 
 	/* Update device table */
 	set_dte_entry(dev_data->devid, domain, ats, dev_data->iommu_v2);
-	if (alias != dev_data->devid)
-		set_dte_entry(alias, domain, ats, dev_data->iommu_v2);
+	clone_aliases(dev_data->pdev);
 
 	device_flush_dte(dev_data);
 }
@@ -2062,17 +2059,14 @@
 {
 	struct protection_domain *domain = dev_data->domain;
 	struct amd_iommu *iommu;
-	u16 alias;
 
 	iommu = amd_iommu_rlookup_table[dev_data->devid];
-	alias = dev_data->alias;
 
 	/* Update data structures */
 	dev_data->domain = NULL;
 	list_del(&dev_data->list);
 	clear_dte_entry(dev_data->devid);
-	if (alias != dev_data->devid)
-		clear_dte_entry(alias);
+	clone_aliases(dev_data->pdev);
 
 	/* Flush the DTE entry */
 	device_flush_dte(dev_data);
@@ -2384,13 +2378,7 @@
 	list_for_each_entry(dev_data, &domain->dev_list, list) {
 		set_dte_entry(dev_data->devid, domain, dev_data->ats.enabled,
 			      dev_data->iommu_v2);
-
-		if (dev_data->devid == dev_data->alias)
-			continue;
-
-		/* There is an alias, update device table entry for it */
-		set_dte_entry(dev_data->alias, domain, dev_data->ats.enabled,
-			      dev_data->iommu_v2);
+		clone_aliases(dev_data->pdev);
 	}
 }
 
@@ -2400,6 +2388,7 @@
 
 	domain_flush_devices(domain);
 	domain_flush_tlb_pde(domain);
+	domain_flush_complete(domain);
 }
 
 static int dir2prot(enum dma_data_direction direction)
@@ -3109,7 +3098,8 @@
 }
 
 static int amd_iommu_map(struct iommu_domain *dom, unsigned long iova,
-			 phys_addr_t paddr, size_t page_size, int iommu_prot)
+			 phys_addr_t paddr, size_t page_size, int iommu_prot,
+			 gfp_t gfp)
 {
 	struct protection_domain *domain = to_pdomain(dom);
 	int prot = 0;
@@ -3124,7 +3114,7 @@
 		prot |= IOMMU_PROT_IW;
 
 	mutex_lock(&domain->api_lock);
-	ret = iommu_map_page(domain, iova, paddr, page_size, prot, GFP_KERNEL);
+	ret = iommu_map_page(domain, iova, paddr, page_size, prot, gfp);
 	mutex_unlock(&domain->api_lock);
 
 	domain_flush_np_cache(domain, iova, page_size);
@@ -3752,7 +3742,20 @@
 	iommu_flush_dte(iommu, devid);
 }
 
-static struct irq_remap_table *alloc_irq_table(u16 devid)
+static int set_remap_table_entry_alias(struct pci_dev *pdev, u16 alias,
+				       void *data)
+{
+	struct irq_remap_table *table = data;
+
+	irq_lookup_table[alias] = table;
+	set_dte_irq_entry(alias, table);
+
+	iommu_flush_dte(amd_iommu_rlookup_table[alias], alias);
+
+	return 0;
+}
+
+static struct irq_remap_table *alloc_irq_table(u16 devid, struct pci_dev *pdev)
 {
 	struct irq_remap_table *table = NULL;
 	struct irq_remap_table *new_table = NULL;
@@ -3798,7 +3801,12 @@
 	table = new_table;
 	new_table = NULL;
 
-	set_remap_table_entry(iommu, devid, table);
+	if (pdev)
+		pci_for_each_dma_alias(pdev, set_remap_table_entry_alias,
+				       table);
+	else
+		set_remap_table_entry(iommu, devid, table);
+
 	if (devid != alias)
 		set_remap_table_entry(iommu, alias, table);
 
@@ -3815,7 +3823,8 @@
 	return table;
 }
 
-static int alloc_irq_index(u16 devid, int count, bool align)
+static int alloc_irq_index(u16 devid, int count, bool align,
+			   struct pci_dev *pdev)
 {
 	struct irq_remap_table *table;
 	int index, c, alignment = 1;
@@ -3825,7 +3834,7 @@
 	if (!iommu)
 		return -ENODEV;
 
-	table = alloc_irq_table(devid);
+	table = alloc_irq_table(devid, pdev);
 	if (!table)
 		return -ENODEV;
 
@@ -3867,6 +3876,7 @@
 static int modify_irte_ga(u16 devid, int index, struct irte_ga *irte,
 			  struct amd_ir_data *data)
 {
+	bool ret;
 	struct irq_remap_table *table;
 	struct amd_iommu *iommu;
 	unsigned long flags;
@@ -3884,10 +3894,18 @@
 
 	entry = (struct irte_ga *)table->table;
 	entry = &entry[index];
-	entry->lo.fields_remap.valid = 0;
-	entry->hi.val = irte->hi.val;
-	entry->lo.val = irte->lo.val;
-	entry->lo.fields_remap.valid = 1;
+
+	ret = cmpxchg_double(&entry->lo.val, &entry->hi.val,
+			     entry->lo.val, entry->hi.val,
+			     irte->lo.val, irte->hi.val);
+	/*
+	 * We use cmpxchg16 to atomically update the 128-bit IRTE,
+	 * and it cannot be updated by the hardware or other processors
+	 * behind us, so the return value of cmpxchg16 should be the
+	 * same as the old value.
+	 */
+	WARN_ON(!ret);
+
 	if (data)
 		data->ref = entry;
 
@@ -4258,7 +4276,7 @@
 		struct irq_remap_table *table;
 		struct amd_iommu *iommu;
 
-		table = alloc_irq_table(devid);
+		table = alloc_irq_table(devid, NULL);
 		if (table) {
 			if (!table->min_index) {
 				/*
@@ -4275,11 +4293,15 @@
 		} else {
 			index = -ENOMEM;
 		}
-	} else {
+	} else if (info->type == X86_IRQ_ALLOC_TYPE_MSI ||
+		   info->type == X86_IRQ_ALLOC_TYPE_MSIX) {
 		bool align = (info->type == X86_IRQ_ALLOC_TYPE_MSI);
 
-		index = alloc_irq_index(devid, nr_irqs, align);
+		index = alloc_irq_index(devid, nr_irqs, align, info->msi_dev);
+	} else {
+		index = alloc_irq_index(devid, nr_irqs, false, NULL);
 	}
+
 	if (index < 0) {
 		pr_warn("Failed to allocate IRTE\n");
 		ret = index;
@@ -4398,8 +4420,7 @@
 	struct amd_ir_data *ir_data = (struct amd_ir_data *)data;
 	struct irte_ga *entry = (struct irte_ga *) ir_data->entry;
 
-	if (!AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir) ||
-	    !entry || entry->lo.fields_vapic.guest_mode)
+	if (!AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir) || !entry)
 		return 0;
 
 	entry->lo.val = 0;
@@ -4412,7 +4433,7 @@
 	entry->lo.fields_vapic.ga_tag      = ir_data->ga_tag;
 
 	return modify_irte_ga(ir_data->irq_2_irte.devid,
-			      ir_data->irq_2_irte.index, entry, NULL);
+			      ir_data->irq_2_irte.index, entry, ir_data);
 }
 EXPORT_SYMBOL(amd_iommu_activate_guest_mode);
 
@@ -4421,14 +4442,18 @@
 	struct amd_ir_data *ir_data = (struct amd_ir_data *)data;
 	struct irte_ga *entry = (struct irte_ga *) ir_data->entry;
 	struct irq_cfg *cfg = ir_data->cfg;
+	u64 valid;
 
 	if (!AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir) ||
 	    !entry || !entry->lo.fields_vapic.guest_mode)
 		return 0;
 
+	valid = entry->lo.fields_remap.valid;
+
 	entry->lo.val = 0;
 	entry->hi.val = 0;
 
+	entry->lo.fields_remap.valid       = valid;
 	entry->lo.fields_remap.dm          = apic->irq_dest_mode;
 	entry->lo.fields_remap.int_type    = apic->irq_delivery_mode;
 	entry->hi.fields.vector            = cfg->vector;
@@ -4438,7 +4463,7 @@
 				APICID_TO_IRTE_DEST_HI(cfg->dest_apicid);
 
 	return modify_irte_ga(ir_data->irq_2_irte.devid,
-			      ir_data->irq_2_irte.index, entry, NULL);
+			      ir_data->irq_2_irte.index, entry, ir_data);
 }
 EXPORT_SYMBOL(amd_iommu_deactivate_guest_mode);
 
@@ -4565,9 +4590,10 @@
 	if (!fn)
 		return -ENOMEM;
 	iommu->ir_domain = irq_domain_create_tree(fn, &amd_ir_domain_ops, iommu);
-	irq_domain_free_fwnode(fn);
-	if (!iommu->ir_domain)
+	if (!iommu->ir_domain) {
+		irq_domain_free_fwnode(fn);
 		return -ENOMEM;
+	}
 
 	iommu->ir_domain->parent = arch_get_ir_parent_domain();
 	iommu->msi_domain = arch_create_remap_msi_irq_domain(iommu->ir_domain,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iommu/amd_iommu_init.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iommu/amd_iommu_init.c
@@ -21,6 +21,7 @@
 #include <linux/iommu.h>
 #include <linux/kmemleak.h>
 #include <linux/mem_encrypt.h>
+#include <linux/iopoll.h>
 #include <asm/pci-direct.h>
 #include <asm/iommu.h>
 #include <asm/apic.h>
@@ -82,7 +83,11 @@
 #define ACPI_DEVFLAG_LINT1              0x80
 #define ACPI_DEVFLAG_ATSDIS             0x10000000
 
-#define LOOP_TIMEOUT	100000
+#define LOOP_TIMEOUT	2000000
+
+#define IVRS_GET_SBDF_ID(seg, bus, dev, fd)	(((seg & 0xffff) << 16) | ((bus & 0xff) << 8) \
+						 | ((dev & 0x1f) << 3) | (fn & 0x7))
+
 /*
  * ACPI table definitions
  *
@@ -147,7 +152,7 @@
 bool amd_iommu_irq_remap __read_mostly;
 
 int amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_VAPIC;
-static int amd_iommu_xt_mode = IRQ_REMAP_X2APIC_MODE;
+static int amd_iommu_xt_mode = IRQ_REMAP_XAPIC_MODE;
 
 static bool amd_iommu_detected;
 static bool __initdata amd_iommu_disabled;
@@ -759,6 +764,7 @@
 		status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET);
 		if (status & (MMIO_STATUS_GALOG_RUN_MASK))
 			break;
+		udelay(10);
 	}
 
 	if (i >= LOOP_TIMEOUT)
@@ -1331,8 +1337,8 @@
 		}
 		case IVHD_DEV_ACPI_HID: {
 			u16 devid;
-			u8 hid[ACPIHID_HID_LEN] = {0};
-			u8 uid[ACPIHID_UID_LEN] = {0};
+			u8 hid[ACPIHID_HID_LEN];
+			u8 uid[ACPIHID_UID_LEN];
 			int ret;
 
 			if (h->type != 0x40) {
@@ -1349,6 +1355,7 @@
 				break;
 			}
 
+			uid[0] = '\0';
 			switch (e->uidf) {
 			case UID_NOT_PRESENT:
 
@@ -1363,8 +1370,8 @@
 				break;
 			case UID_IS_CHARACTER:
 
-				memcpy(uid, (u8 *)(&e->uid), ACPIHID_UID_LEN - 1);
-				uid[ACPIHID_UID_LEN - 1] = '\0';
+				memcpy(uid, &e->uid, e->uidl);
+				uid[e->uidl] = '\0';
 
 				break;
 			default:
@@ -1403,8 +1410,17 @@
 	return 0;
 }
 
+static void __init free_sysfs(struct amd_iommu *iommu)
+{
+	if (iommu->iommu.dev) {
+		iommu_device_unregister(&iommu->iommu);
+		iommu_device_sysfs_remove(&iommu->iommu);
+	}
+}
+
 static void __init free_iommu_one(struct amd_iommu *iommu)
 {
+	free_sysfs(iommu);
 	free_command_buffer(iommu);
 	free_event_buffer(iommu);
 	free_ppr_log(iommu);
@@ -1521,10 +1537,15 @@
 			iommu->mmio_phys_end = MMIO_REG_END_OFFSET;
 		else
 			iommu->mmio_phys_end = MMIO_CNTR_CONF_OFFSET;
-		if (((h->efr_attr & (0x1 << IOMMU_FEAT_GASUP_SHIFT)) == 0))
+
+		/*
+		 * Note: GA (128-bit IRTE) mode requires cmpxchg16b supports.
+		 * GAM also requires GA mode. Therefore, we need to
+		 * check cmpxchg16b support before enabling it.
+		 */
+		if (!boot_cpu_has(X86_FEATURE_CX16) ||
+		    ((h->efr_attr & (0x1 << IOMMU_FEAT_GASUP_SHIFT)) == 0))
 			amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY;
-		if (((h->efr_attr & (0x1 << IOMMU_FEAT_XTSUP_SHIFT)) == 0))
-			amd_iommu_xt_mode = IRQ_REMAP_XAPIC_MODE;
 		break;
 	case 0x11:
 	case 0x40:
@@ -1532,10 +1553,27 @@
 			iommu->mmio_phys_end = MMIO_REG_END_OFFSET;
 		else
 			iommu->mmio_phys_end = MMIO_CNTR_CONF_OFFSET;
-		if (((h->efr_reg & (0x1 << IOMMU_EFR_GASUP_SHIFT)) == 0))
+
+		/*
+		 * Note: GA (128-bit IRTE) mode requires cmpxchg16b supports.
+		 * XT, GAM also requires GA mode. Therefore, we need to
+		 * check cmpxchg16b support before enabling them.
+		 */
+		if (!boot_cpu_has(X86_FEATURE_CX16) ||
+		    ((h->efr_reg & (0x1 << IOMMU_EFR_GASUP_SHIFT)) == 0)) {
 			amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY;
-		if (((h->efr_reg & (0x1 << IOMMU_EFR_XTSUP_SHIFT)) == 0))
-			amd_iommu_xt_mode = IRQ_REMAP_XAPIC_MODE;
+			break;
+		}
+
+		/*
+		 * Note: Since iommu_update_intcapxt() leverages
+		 * the IOMMU MMIO access to MSI capability block registers
+		 * for MSI address lo/hi/data, we need to check both
+		 * EFR[XtSup] and EFR[MsiCapMmioSup] for x2APIC support.
+		 */
+		if ((h->efr_reg & BIT(IOMMU_EFR_XTSUP_SHIFT)) &&
+		    (h->efr_reg & BIT(IOMMU_EFR_MSICAPMMIOSUP_SHIFT)))
+			amd_iommu_xt_mode = IRQ_REMAP_X2APIC_MODE;
 		break;
 	default:
 		return -EINVAL;
@@ -1649,33 +1687,23 @@
 	return 0;
 }
 
-static int iommu_pc_get_set_reg(struct amd_iommu *iommu, u8 bank, u8 cntr,
-				u8 fxn, u64 *value, bool is_write);
-
 static void init_iommu_perf_ctr(struct amd_iommu *iommu)
 {
+	u64 val;
 	struct pci_dev *pdev = iommu->dev;
-	u64 val = 0xabcd, val2 = 0;
 
 	if (!iommu_feature(iommu, FEATURE_PC))
 		return;
 
 	amd_iommu_pc_present = true;
 
-	/* Check if the performance counters can be written to */
-	if ((iommu_pc_get_set_reg(iommu, 0, 0, 0, &val, true)) ||
-	    (iommu_pc_get_set_reg(iommu, 0, 0, 0, &val2, false)) ||
-	    (val != val2)) {
-		pci_err(pdev, "Unable to write to IOMMU perf counter.\n");
-		amd_iommu_pc_present = false;
-		return;
-	}
-
 	pci_info(pdev, "IOMMU performance counters supported\n");
 
 	val = readl(iommu->mmio_base + MMIO_CNTR_CONF_OFFSET);
 	iommu->max_banks = (u8) ((val >> 12) & 0x3f);
 	iommu->max_counters = (u8) ((val >> 7) & 0xf);
+
+	return;
 }
 
 static ssize_t amd_iommu_show_cap(struct device *dev,
@@ -1726,6 +1754,9 @@
 	/* Prevent binding other PCI device drivers to IOMMU devices */
 	iommu->dev->match_driver = false;
 
+	/* ACPI _PRT won't have an IRQ for IOMMU */
+	iommu->dev->irq_managed = 1;
+
 	pci_read_config_dword(iommu->dev, cap_ptr + MMIO_CAP_HDR_OFFSET,
 			      &iommu->cap);
 	pci_read_config_dword(iommu->dev, cap_ptr + MMIO_RANGE_OFFSET,
@@ -1984,8 +2015,8 @@
 	struct irq_affinity_notify *notify = &iommu->intcapxt_notify;
 
 	/**
-	 * IntCapXT requires XTSup=1, which can be inferred
-	 * amd_iommu_xt_mode.
+	 * IntCapXT requires XTSup=1 and MsiCapMmioSup=1,
+	 * which can be inferred from amd_iommu_xt_mode.
 	 */
 	if (amd_iommu_xt_mode != IRQ_REMAP_X2APIC_MODE)
 		return 0;
@@ -2516,6 +2547,7 @@
 	struct acpi_table_header *ivrs_base;
 	acpi_status status;
 	int i, remap_cache_sz, ret = 0;
+	u32 pci_id;
 
 	if (!amd_iommu_detected)
 		return -ENODEV;
@@ -2603,6 +2635,16 @@
 	if (ret)
 		goto out;
 
+	/* Disable IOMMU if there's Stoney Ridge graphics */
+	for (i = 0; i < 32; i++) {
+		pci_id = read_pci_config(0, i, 0, 0);
+		if ((pci_id & 0xffff) == 0x1002 && (pci_id >> 16) == 0x98e4) {
+			pr_info("Disable IOMMU on Stoney Ridge\n");
+			amd_iommu_disabled = true;
+			break;
+		}
+	}
+
 	/* Disable any previously enabled IOMMUs */
 	if (!is_kdump_kernel() || amd_iommu_disabled)
 		disable_iommus();
@@ -2711,7 +2753,7 @@
 		ret = early_amd_iommu_init();
 		init_state = ret ? IOMMU_INIT_ERROR : IOMMU_ACPI_FINISHED;
 		if (init_state == IOMMU_ACPI_FINISHED && amd_iommu_disabled) {
-			pr_info("AMD IOMMU disabled on kernel command-line\n");
+			pr_info("AMD IOMMU disabled\n");
 			init_state = IOMMU_CMDLINE_DISABLED;
 			ret = -EINVAL;
 		}
@@ -2918,7 +2960,7 @@
 {
 	for (; *str; ++str) {
 		if (strncmp(str, "legacy", 6) == 0) {
-			amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY;
+			amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY_GA;
 			break;
 		}
 		if (strncmp(str, "vapic", 5) == 0) {
@@ -2945,24 +2987,32 @@
 
 static int __init parse_ivrs_ioapic(char *str)
 {
-	unsigned int bus, dev, fn;
-	int ret, id, i;
-	u16 devid;
-
-	ret = sscanf(str, "[%d]=%x:%x.%x", &id, &bus, &dev, &fn);
+	u32 seg = 0, bus, dev, fn;
+	int id, i;
+	u32 devid;
 
-	if (ret != 4) {
-		pr_err("Invalid command line: ivrs_ioapic%s\n", str);
-		return 1;
+	if (sscanf(str, "=%d@%x:%x.%x", &id, &bus, &dev, &fn) == 4 ||
+	    sscanf(str, "=%d@%x:%x:%x.%x", &id, &seg, &bus, &dev, &fn) == 5)
+		goto found;
+
+	if (sscanf(str, "[%d]=%x:%x.%x", &id, &bus, &dev, &fn) == 4 ||
+	    sscanf(str, "[%d]=%x:%x:%x.%x", &id, &seg, &bus, &dev, &fn) == 5) {
+		pr_warn("ivrs_ioapic%s option format deprecated; use ivrs_ioapic=%d@%04x:%02x:%02x.%d instead\n",
+			str, id, seg, bus, dev, fn);
+		goto found;
 	}
 
+	pr_err("Invalid command line: ivrs_ioapic%s\n", str);
+	return 1;
+
+found:
 	if (early_ioapic_map_size == EARLY_MAP_SIZE) {
 		pr_err("Early IOAPIC map overflow - ignoring ivrs_ioapic%s\n",
 			str);
 		return 1;
 	}
 
-	devid = ((bus & 0xff) << 8) | ((dev & 0x1f) << 3) | (fn & 0x7);
+	devid = IVRS_GET_SBDF_ID(seg, bus, dev, fn);
 
 	cmdline_maps			= true;
 	i				= early_ioapic_map_size++;
@@ -2975,24 +3025,32 @@
 
 static int __init parse_ivrs_hpet(char *str)
 {
-	unsigned int bus, dev, fn;
-	int ret, id, i;
-	u16 devid;
-
-	ret = sscanf(str, "[%d]=%x:%x.%x", &id, &bus, &dev, &fn);
+	u32 seg = 0, bus, dev, fn;
+	int id, i;
+	u32 devid;
 
-	if (ret != 4) {
-		pr_err("Invalid command line: ivrs_hpet%s\n", str);
-		return 1;
+	if (sscanf(str, "=%d@%x:%x.%x", &id, &bus, &dev, &fn) == 4 ||
+	    sscanf(str, "=%d@%x:%x:%x.%x", &id, &seg, &bus, &dev, &fn) == 5)
+		goto found;
+
+	if (sscanf(str, "[%d]=%x:%x.%x", &id, &bus, &dev, &fn) == 4 ||
+	    sscanf(str, "[%d]=%x:%x:%x.%x", &id, &seg, &bus, &dev, &fn) == 5) {
+		pr_warn("ivrs_hpet%s option format deprecated; use ivrs_hpet=%d@%04x:%02x:%02x.%d instead\n",
+			str, id, seg, bus, dev, fn);
+		goto found;
 	}
 
+	pr_err("Invalid command line: ivrs_hpet%s\n", str);
+	return 1;
+
+found:
 	if (early_hpet_map_size == EARLY_MAP_SIZE) {
 		pr_err("Early HPET map overflow - ignoring ivrs_hpet%s\n",
 			str);
 		return 1;
 	}
 
-	devid = ((bus & 0xff) << 8) | ((dev & 0x1f) << 3) | (fn & 0x7);
+	devid = IVRS_GET_SBDF_ID(seg, bus, dev, fn);
 
 	cmdline_maps			= true;
 	i				= early_hpet_map_size++;
@@ -3003,19 +3061,53 @@
 	return 1;
 }
 
+#define ACPIID_LEN (ACPIHID_UID_LEN + ACPIHID_HID_LEN)
+
 static int __init parse_ivrs_acpihid(char *str)
 {
-	u32 bus, dev, fn;
-	char *hid, *uid, *p;
-	char acpiid[ACPIHID_UID_LEN + ACPIHID_HID_LEN] = {0};
-	int ret, i;
-
-	ret = sscanf(str, "[%x:%x.%x]=%s", &bus, &dev, &fn, acpiid);
-	if (ret != 4) {
-		pr_err("Invalid command line: ivrs_acpihid(%s)\n", str);
-		return 1;
+	u32 seg = 0, bus, dev, fn;
+	char *hid, *uid, *p, *addr;
+	char acpiid[ACPIID_LEN] = {0};
+	int i;
+
+	addr = strchr(str, '@');
+	if (!addr) {
+		addr = strchr(str, '=');
+		if (!addr)
+			goto not_found;
+
+		++addr;
+
+		if (strlen(addr) > ACPIID_LEN)
+			goto not_found;
+
+		if (sscanf(str, "[%x:%x.%x]=%s", &bus, &dev, &fn, acpiid) == 4 ||
+		    sscanf(str, "[%x:%x:%x.%x]=%s", &seg, &bus, &dev, &fn, acpiid) == 5) {
+			pr_warn("ivrs_acpihid%s option format deprecated; use ivrs_acpihid=%s@%04x:%02x:%02x.%d instead\n",
+				str, acpiid, seg, bus, dev, fn);
+			goto found;
+		}
+		goto not_found;
 	}
 
+	/* We have the '@', make it the terminator to get just the acpiid */
+	*addr++ = 0;
+
+	if (strlen(str) > ACPIID_LEN + 1)
+		goto not_found;
+
+	if (sscanf(str, "=%s", acpiid) != 1)
+		goto not_found;
+
+	if (sscanf(addr, "%x:%x.%x", &bus, &dev, &fn) == 3 ||
+	    sscanf(addr, "%x:%x:%x.%x", &seg, &bus, &dev, &fn) == 4)
+		goto found;
+
+not_found:
+	pr_err("Invalid command line: ivrs_acpihid%s\n", str);
+	return 1;
+
+found:
 	p = acpiid;
 	hid = strsep(&p, ":");
 	uid = p;
@@ -3025,11 +3117,17 @@
 		return 1;
 	}
 
+	/*
+	 * Ignore leading zeroes after ':', so e.g., AMDI0095:00
+	 * will match AMDI0095:0 in the second strcmp in acpi_dev_hid_uid_match
+	 */
+	while (*uid == '0' && *(uid + 1))
+		uid++;
+
 	i = early_acpihid_map_size++;
 	memcpy(early_acpihid_map[i].hid, hid, strlen(hid));
 	memcpy(early_acpihid_map[i].uid, uid, strlen(uid));
-	early_acpihid_map[i].devid =
-		((bus & 0xff) << 8) | ((dev & 0x1f) << 3) | (fn & 0x7);
+	early_acpihid_map[i].devid = IVRS_GET_SBDF_ID(seg, bus, dev, fn);
 	early_acpihid_map[i].cmd_line	= true;
 
 	return 1;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iommu/amd_iommu_types.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/iommu/amd_iommu_types.h
@@ -254,7 +254,7 @@
 #define DTE_IRQ_REMAP_INTCTL_MASK	(0x3ULL << 60)
 #define DTE_IRQ_TABLE_LEN_MASK	(0xfULL << 1)
 #define DTE_IRQ_REMAP_INTCTL    (2ULL << 60)
-#define DTE_IRQ_TABLE_LEN       (8ULL << 1)
+#define DTE_IRQ_TABLE_LEN       (9ULL << 1)
 #define DTE_IRQ_REMAP_ENABLE    1ULL
 
 #define PAGE_MODE_NONE    0x00
@@ -348,7 +348,7 @@
 
 #define DTE_GCR3_VAL_A(x)	(((x) >> 12) & 0x00007ULL)
 #define DTE_GCR3_VAL_B(x)	(((x) >> 15) & 0x0ffffULL)
-#define DTE_GCR3_VAL_C(x)	(((x) >> 31) & 0xfffffULL)
+#define DTE_GCR3_VAL_C(x)	(((x) >> 31) & 0x1fffffULL)
 
 #define DTE_GCR3_INDEX_A	0
 #define DTE_GCR3_INDEX_B	1
@@ -377,12 +377,12 @@
 #define IOMMU_CAP_EFR     27
 
 /* IOMMU Feature Reporting Field (for IVHD type 10h */
-#define IOMMU_FEAT_XTSUP_SHIFT	0
 #define IOMMU_FEAT_GASUP_SHIFT	6
 
 /* IOMMU Extended Feature Register (EFR) */
 #define IOMMU_EFR_XTSUP_SHIFT	2
 #define IOMMU_EFR_GASUP_SHIFT	7
+#define IOMMU_EFR_MSICAPMMIOSUP_SHIFT	46
 
 #define MAX_DOMAIN_ID 65536
 
@@ -406,7 +406,11 @@
 /* Only true if all IOMMUs support device IOTLBs */
 extern bool amd_iommu_iotlb_sup;
 
-#define MAX_IRQS_PER_TABLE	256
+/*
+ * AMD IOMMU hardware only support 512 IRTEs despite
+ * the architectural limitation of 2048 entries.
+ */
+#define MAX_IRQS_PER_TABLE	512
 #define IRQ_TABLE_ALIGNMENT	128
 
 struct irq_remap_table {
@@ -639,8 +643,8 @@
 	struct list_head list;		  /* For domain->dev_list */
 	struct llist_node dev_data_list;  /* For global dev_data_list */
 	struct protection_domain *domain; /* Domain the device is bound to */
+	struct pci_dev *pdev;
 	u16 devid;			  /* PCI Device ID */
-	u16 alias;			  /* Alias Device ID */
 	bool iommu_v2;			  /* Device can make use of IOMMUv2 */
 	bool passthrough;		  /* Device is identity mapped */
 	struct {
@@ -882,8 +886,8 @@
 	 */
 	struct irq_cfg *cfg;
 	int ga_vector;
-	int ga_root_ptr;
-	int ga_tag;
+	u64 ga_root_ptr;
+	u32 ga_tag;
 };
 
 struct amd_irte_ops {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iommu/amd_iommu_v2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iommu/amd_iommu_v2.c
@@ -591,6 +591,7 @@
 	put_device_state(dev_state);
 
 out:
+	pci_dev_put(pdev);
 	return ret;
 }
 
@@ -741,6 +742,13 @@
 
 	might_sleep();
 
+	/*
+	 * When memory encryption is active the device is likely not in a
+	 * direct-mapped domain. Forbid using IOMMUv2 functionality for now.
+	 */
+	if (mem_encrypt_active())
+		return -ENODEV;
+
 	if (!amd_iommu_v2_supported())
 		return -ENODEV;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iommu/arm-smmu-v3.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iommu/arm-smmu-v3.c
@@ -169,6 +169,8 @@
 #define ARM_SMMU_PRIQ_IRQ_CFG1		0xd8
 #define ARM_SMMU_PRIQ_IRQ_CFG2		0xdc
 
+#define ARM_SMMU_REG_SZ			0xe00
+
 /* Common MSI config fields */
 #define MSI_CFG0_ADDR_MASK		GENMASK_ULL(51, 2)
 #define MSI_CFG2_SH			GENMASK(5, 4)
@@ -579,6 +581,7 @@
 struct arm_smmu_device {
 	struct device			*dev;
 	void __iomem			*base;
+	void __iomem			*page1;
 
 #define ARM_SMMU_FEAT_2_LVL_STRTAB	(1 << 0)
 #define ARM_SMMU_FEAT_2_LVL_CDTAB	(1 << 1)
@@ -682,9 +685,8 @@
 static inline void __iomem *arm_smmu_page1_fixup(unsigned long offset,
 						 struct arm_smmu_device *smmu)
 {
-	if ((offset > SZ_64K) &&
-	    (smmu->options & ARM_SMMU_OPT_PAGE0_REGS_ONLY))
-		offset -= SZ_64K;
+	if (offset > SZ_64K)
+		return smmu->page1 + offset - SZ_64K;
 
 	return smmu->base + offset;
 }
@@ -760,6 +762,18 @@
 	q->cons = Q_OVF(q->cons) | Q_WRP(q, cons) | Q_IDX(q, cons);
 }
 
+static void queue_sync_cons_ovf(struct arm_smmu_queue *q)
+{
+	struct arm_smmu_ll_queue *llq = &q->llq;
+
+	if (likely(Q_OVF(llq->prod) == Q_OVF(llq->cons)))
+		return;
+
+	llq->cons = Q_OVF(llq->prod) | Q_WRP(llq, llq->cons) |
+		      Q_IDX(llq, llq->cons);
+	queue_sync_cons_out(q);
+}
+
 static int queue_sync_prod_in(struct arm_smmu_queue *q)
 {
 	int ret = 0;
@@ -856,6 +870,7 @@
 		cmd[1] |= FIELD_PREP(CMDQ_CFGI_1_RANGE, 31);
 		break;
 	case CMDQ_OP_TLBI_NH_VA:
+		cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_VMID, ent->tlbi.vmid);
 		cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_ASID, ent->tlbi.asid);
 		cmd[1] |= FIELD_PREP(CMDQ_TLBI_1_LEAF, ent->tlbi.leaf);
 		cmd[1] |= ent->tlbi.addr & CMDQ_TLBI_1_VA_MASK;
@@ -1642,7 +1657,8 @@
 						 STRTAB_STE_1_EATS_TRANS));
 
 	arm_smmu_sync_ste_for_sid(smmu, sid);
-	dst[0] = cpu_to_le64(val);
+	/* See comment in arm_smmu_write_ctx_desc() */
+	WRITE_ONCE(dst[0], cpu_to_le64(val));
 	arm_smmu_sync_ste_for_sid(smmu, sid);
 
 	/* It's likely that we'll want to use the new STE soon */
@@ -1706,6 +1722,7 @@
 				dev_info(smmu->dev, "\t0x%016llx\n",
 					 (unsigned long long)evt[i]);
 
+			cond_resched();
 		}
 
 		/*
@@ -1717,8 +1734,7 @@
 	} while (!queue_empty(llq));
 
 	/* Sync our overflow flag, as we believe we're up to speed */
-	llq->cons = Q_OVF(llq->prod) | Q_WRP(llq, llq->cons) |
-		    Q_IDX(llq, llq->cons);
+	queue_sync_cons_ovf(q);
 	return IRQ_HANDLED;
 }
 
@@ -1776,9 +1792,7 @@
 	} while (!queue_empty(llq));
 
 	/* Sync our overflow flag, as we believe we're up to speed */
-	llq->cons = Q_OVF(llq->prod) | Q_WRP(llq, llq->cons) |
-		      Q_IDX(llq, llq->cons);
-	queue_sync_cons_out(q);
+	queue_sync_cons_ovf(q);
 	return IRQ_HANDLED;
 }
 
@@ -2448,7 +2462,7 @@
 }
 
 static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova,
-			phys_addr_t paddr, size_t size, int prot)
+			phys_addr_t paddr, size_t size, int prot, gfp_t gfp)
 {
 	struct io_pgtable_ops *ops = to_smmu_domain(domain)->pgtbl_ops;
 
@@ -3570,6 +3584,18 @@
 		return SZ_128K;
 }
 
+static void __iomem *arm_smmu_ioremap(struct device *dev, resource_size_t start,
+				      resource_size_t size)
+{
+	struct resource res = {
+		.flags = IORESOURCE_MEM,
+		.start = start,
+		.end = start + size - 1,
+	};
+
+	return devm_ioremap_resource(dev, &res);
+}
+
 static int arm_smmu_device_probe(struct platform_device *pdev)
 {
 	int irq, ret;
@@ -3605,25 +3631,38 @@
 	}
 	ioaddr = res->start;
 
-	smmu->base = devm_ioremap_resource(dev, res);
+	/*
+	 * Don't map the IMPLEMENTATION DEFINED regions, since they may contain
+	 * the PMCG registers which are reserved by the PMU driver.
+	 */
+	smmu->base = arm_smmu_ioremap(dev, ioaddr, ARM_SMMU_REG_SZ);
 	if (IS_ERR(smmu->base))
 		return PTR_ERR(smmu->base);
 
+	if (arm_smmu_resource_size(smmu) > SZ_64K) {
+		smmu->page1 = arm_smmu_ioremap(dev, ioaddr + SZ_64K,
+					       ARM_SMMU_REG_SZ);
+		if (IS_ERR(smmu->page1))
+			return PTR_ERR(smmu->page1);
+	} else {
+		smmu->page1 = smmu->base;
+	}
+
 	/* Interrupt lines */
 
-	irq = platform_get_irq_byname(pdev, "combined");
+	irq = platform_get_irq_byname_optional(pdev, "combined");
 	if (irq > 0)
 		smmu->combined_irq = irq;
 	else {
-		irq = platform_get_irq_byname(pdev, "eventq");
+		irq = platform_get_irq_byname_optional(pdev, "eventq");
 		if (irq > 0)
 			smmu->evtq.q.irq = irq;
 
-		irq = platform_get_irq_byname(pdev, "priq");
+		irq = platform_get_irq_byname_optional(pdev, "priq");
 		if (irq > 0)
 			smmu->priq.q.irq = irq;
 
-		irq = platform_get_irq_byname(pdev, "gerror");
+		irq = platform_get_irq_byname_optional(pdev, "gerror");
 		if (irq > 0)
 			smmu->gerr_irq = irq;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iommu/arm-smmu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iommu/arm-smmu.c
@@ -114,7 +114,7 @@
 static inline int arm_smmu_rpm_get(struct arm_smmu_device *smmu)
 {
 	if (pm_runtime_enabled(smmu->dev))
-		return pm_runtime_get_sync(smmu->dev);
+		return pm_runtime_resume_and_get(smmu->dev);
 
 	return 0;
 }
@@ -1160,7 +1160,7 @@
 }
 
 static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova,
-			phys_addr_t paddr, size_t size, int prot)
+			phys_addr_t paddr, size_t size, int prot, gfp_t gfp)
 {
 	struct io_pgtable_ops *ops = to_smmu_domain(domain)->pgtbl_ops;
 	struct arm_smmu_device *smmu = to_smmu_domain(domain)->smmu;
@@ -1231,6 +1231,7 @@
 	u64 phys;
 	unsigned long va, flags;
 	int ret, idx = cfg->cbndx;
+	phys_addr_t addr = 0;
 
 	ret = arm_smmu_rpm_get(smmu);
 	if (ret < 0)
@@ -1249,6 +1250,7 @@
 		dev_err(dev,
 			"iova to phys timed out on %pad. Falling back to software table walk.\n",
 			&iova);
+		arm_smmu_rpm_put(smmu);
 		return ops->iova_to_phys(ops, iova);
 	}
 
@@ -1257,12 +1259,14 @@
 	if (phys & CB_PAR_F) {
 		dev_err(dev, "translation fault!\n");
 		dev_err(dev, "PAR = 0x%llx\n", phys);
-		return 0;
+		goto out;
 	}
 
+	addr = (phys & GENMASK_ULL(39, 12)) | (iova & 0xfff);
+out:
 	arm_smmu_rpm_put(smmu);
 
-	return (phys & GENMASK_ULL(39, 12)) | (iova & 0xfff);
+	return addr;
 }
 
 static phys_addr_t arm_smmu_iova_to_phys(struct iommu_domain *domain,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iommu/dma-iommu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iommu/dma-iommu.c
@@ -19,6 +19,7 @@
 #include <linux/iova.h>
 #include <linux/irq.h>
 #include <linux/mm.h>
+#include <linux/mutex.h>
 #include <linux/pci.h>
 #include <linux/scatterlist.h>
 #include <linux/vmalloc.h>
@@ -43,7 +44,6 @@
 		dma_addr_t		msi_iova;
 	};
 	struct list_head		msi_page_list;
-	spinlock_t			msi_lock;
 
 	/* Domain for flush queue callback; NULL if flush queue not in use */
 	struct iommu_domain		*fq_domain;
@@ -62,7 +62,6 @@
 
 	cookie = kzalloc(sizeof(*cookie), GFP_KERNEL);
 	if (cookie) {
-		spin_lock_init(&cookie->msi_lock);
 		INIT_LIST_HEAD(&cookie->msi_page_list);
 		cookie->type = type;
 	}
@@ -177,15 +176,15 @@
 	start -= iova_offset(iovad, start);
 	num_pages = iova_align(iovad, end - start) >> iova_shift(iovad);
 
-	msi_page = kcalloc(num_pages, sizeof(*msi_page), GFP_KERNEL);
-	if (!msi_page)
-		return -ENOMEM;
-
 	for (i = 0; i < num_pages; i++) {
-		msi_page[i].phys = start;
-		msi_page[i].iova = start;
-		INIT_LIST_HEAD(&msi_page[i].list);
-		list_add(&msi_page[i].list, &cookie->msi_page_list);
+		msi_page = kmalloc(sizeof(*msi_page), GFP_KERNEL);
+		if (!msi_page)
+			return -ENOMEM;
+
+		msi_page->phys = start;
+		msi_page->iova = start;
+		INIT_LIST_HEAD(&msi_page->list);
+		list_add(&msi_page->list, &cookie->msi_page_list);
 		start += iovad->granule;
 	}
 
@@ -217,9 +216,11 @@
 			lo = iova_pfn(iovad, start);
 			hi = iova_pfn(iovad, end);
 			reserve_iova(iovad, lo, hi);
-		} else {
+		} else if (end < start) {
 			/* dma_ranges list should be sorted */
-			dev_err(&dev->dev, "Failed to reserve IOVA\n");
+			dev_err(&dev->dev,
+				"Failed to reserve IOVA [%pa-%pa]\n",
+				&start, &end);
 			return -EINVAL;
 		}
 
@@ -476,7 +477,7 @@
 	if (!iova)
 		return DMA_MAPPING_ERROR;
 
-	if (iommu_map(domain, iova, phys - iova_off, size, prot)) {
+	if (iommu_map_atomic(domain, iova, phys - iova_off, size, prot)) {
 		iommu_dma_free_iova(cookie, iova, size);
 		return DMA_MAPPING_ERROR;
 	}
@@ -611,7 +612,7 @@
 			arch_dma_prep_coherent(sg_page(sg), sg->length);
 	}
 
-	if (iommu_map_sg(domain, iova, sgt.sgl, sgt.orig_nents, ioprot)
+	if (iommu_map_sg_atomic(domain, iova, sgt.sgl, sgt.orig_nents, ioprot)
 			< size)
 		goto out_free_sg;
 
@@ -659,7 +660,7 @@
 		return;
 
 	phys = iommu_iova_to_phys(iommu_get_dma_domain(dev), dma_handle);
-	arch_sync_dma_for_cpu(dev, phys, size, dir);
+	arch_sync_dma_for_cpu(phys, size, dir);
 }
 
 static void iommu_dma_sync_single_for_device(struct device *dev,
@@ -671,7 +672,7 @@
 		return;
 
 	phys = iommu_iova_to_phys(iommu_get_dma_domain(dev), dma_handle);
-	arch_sync_dma_for_device(dev, phys, size, dir);
+	arch_sync_dma_for_device(phys, size, dir);
 }
 
 static void iommu_dma_sync_sg_for_cpu(struct device *dev,
@@ -685,7 +686,7 @@
 		return;
 
 	for_each_sg(sgl, sg, nelems, i)
-		arch_sync_dma_for_cpu(dev, sg_phys(sg), sg->length, dir);
+		arch_sync_dma_for_cpu(sg_phys(sg), sg->length, dir);
 }
 
 static void iommu_dma_sync_sg_for_device(struct device *dev,
@@ -699,7 +700,7 @@
 		return;
 
 	for_each_sg(sgl, sg, nelems, i)
-		arch_sync_dma_for_device(dev, sg_phys(sg), sg->length, dir);
+		arch_sync_dma_for_device(sg_phys(sg), sg->length, dir);
 }
 
 static dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page,
@@ -714,7 +715,7 @@
 	dma_handle =__iommu_dma_map(dev, phys, size, prot);
 	if (!coherent && !(attrs & DMA_ATTR_SKIP_CPU_SYNC) &&
 	    dma_handle != DMA_MAPPING_ERROR)
-		arch_sync_dma_for_device(dev, phys, size, dir);
+		arch_sync_dma_for_device(phys, size, dir);
 	return dma_handle;
 }
 
@@ -871,7 +872,7 @@
 	 * We'll leave any physical concatenation to the IOMMU driver's
 	 * implementation - it knows better than we do.
 	 */
-	if (iommu_map_sg(domain, iova, sg, nents, prot) < iova_len)
+	if (iommu_map_sg_atomic(domain, iova, sg, nents, prot) < iova_len)
 		goto out_free_iova;
 
 	return __finalise_sg(dev, sg, nents, iova);
@@ -1150,7 +1151,7 @@
 		if (msi_page->phys == msi_addr)
 			return msi_page;
 
-	msi_page = kzalloc(sizeof(*msi_page), GFP_ATOMIC);
+	msi_page = kzalloc(sizeof(*msi_page), GFP_KERNEL);
 	if (!msi_page)
 		return NULL;
 
@@ -1178,25 +1179,22 @@
 {
 	struct device *dev = msi_desc_to_dev(desc);
 	struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
-	struct iommu_dma_cookie *cookie;
 	struct iommu_dma_msi_page *msi_page;
-	unsigned long flags;
+	static DEFINE_MUTEX(msi_prepare_lock); /* see below */
 
 	if (!domain || !domain->iova_cookie) {
 		desc->iommu_cookie = NULL;
 		return 0;
 	}
 
-	cookie = domain->iova_cookie;
-
 	/*
-	 * We disable IRQs to rule out a possible inversion against
-	 * irq_desc_lock if, say, someone tries to retarget the affinity
-	 * of an MSI from within an IPI handler.
+	 * In fact the whole prepare operation should already be serialised by
+	 * irq_domain_mutex further up the callchain, but that's pretty subtle
+	 * on its own, so consider this locking as failsafe documentation...
 	 */
-	spin_lock_irqsave(&cookie->msi_lock, flags);
+	mutex_lock(&msi_prepare_lock);
 	msi_page = iommu_dma_get_msi_page(dev, msi_addr, domain);
-	spin_unlock_irqrestore(&cookie->msi_lock, flags);
+	mutex_unlock(&msi_prepare_lock);
 
 	msi_desc_set_iommu_cookie(desc, msi_page);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iommu/dmar.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iommu/dmar.c
@@ -28,6 +28,7 @@
 #include <linux/slab.h>
 #include <linux/iommu.h>
 #include <linux/numa.h>
+#include <linux/limits.h>
 #include <asm/irq_remapping.h>
 #include <asm/iommu_table.h>
 
@@ -128,6 +129,13 @@
 
 	BUG_ON(dev->is_virtfn);
 
+	/*
+	 * Ignore devices that have a domain number higher than what can
+	 * be looked up in DMAR, e.g. VMD subdevices with domain 0x10000
+	 */
+	if (pci_domain_nr(dev->bus) > U16_MAX)
+		return NULL;
+
 	/* Only generate path[] for device addition event */
 	if (event == BUS_NOTIFY_ADD_DEVICE)
 		for (tmp = dev; tmp; tmp = tmp->bus->self)
@@ -355,7 +363,7 @@
 
 static struct notifier_block dmar_pci_bus_nb = {
 	.notifier_call = dmar_pci_bus_notifier,
-	.priority = INT_MIN,
+	.priority = 1,
 };
 
 static struct dmar_drhd_unit *
@@ -363,7 +371,8 @@
 {
 	struct dmar_drhd_unit *dmaru;
 
-	list_for_each_entry_rcu(dmaru, &dmar_drhd_units, list)
+	list_for_each_entry_rcu(dmaru, &dmar_drhd_units, list,
+				dmar_rcu_check())
 		if (dmaru->segment == drhd->segment &&
 		    dmaru->reg_base_addr == drhd->address)
 			return dmaru;
@@ -440,12 +449,13 @@
 
 	/* Check for NUL termination within the designated length */
 	if (strnlen(andd->device_name, header->length - 8) == header->length - 8) {
-		WARN_TAINT(1, TAINT_FIRMWARE_WORKAROUND,
+		pr_warn(FW_BUG
 			   "Your BIOS is broken; ANDD object name is not NUL-terminated\n"
 			   "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
 			   dmi_get_system_info(DMI_BIOS_VENDOR),
 			   dmi_get_system_info(DMI_BIOS_VERSION),
 			   dmi_get_system_info(DMI_PRODUCT_VERSION));
+		add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
 		return -EINVAL;
 	}
 	pr_info("ANDD device: %x name: %s\n", andd->device_number,
@@ -465,20 +475,20 @@
 		if (drhd->reg_base_addr == rhsa->base_address) {
 			int node = acpi_map_pxm_to_node(rhsa->proximity_domain);
 
-			if (!node_online(node))
+			if (node != NUMA_NO_NODE && !node_online(node))
 				node = NUMA_NO_NODE;
 			drhd->iommu->node = node;
 			return 0;
 		}
 	}
-	WARN_TAINT(
-		1, TAINT_FIRMWARE_WORKAROUND,
+	pr_warn(FW_BUG
 		"Your BIOS is broken; RHSA refers to non-existent DMAR unit at %llx\n"
 		"BIOS vendor: %s; Ver: %s; Product Version: %s\n",
-		drhd->reg_base_addr,
+		rhsa->base_address,
 		dmi_get_system_info(DMI_BIOS_VENDOR),
 		dmi_get_system_info(DMI_BIOS_VERSION),
 		dmi_get_system_info(DMI_PRODUCT_VERSION));
+	add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
 
 	return 0;
 }
@@ -784,6 +794,7 @@
 			info = dmar_alloc_pci_notify_info(dev,
 					BUS_NOTIFY_ADD_DEVICE);
 			if (!info) {
+				pci_dev_put(dev);
 				return dmar_dev_scope_status;
 			} else {
 				dmar_pci_bus_add_dev(info);
@@ -827,14 +838,14 @@
 
 static void warn_invalid_dmar(u64 addr, const char *message)
 {
-	WARN_TAINT_ONCE(
-		1, TAINT_FIRMWARE_WORKAROUND,
+	pr_warn_once(FW_BUG
 		"Your BIOS is broken; DMAR reported at address %llx%s!\n"
 		"BIOS vendor: %s; Ver: %s; Product Version: %s\n",
 		addr, message,
 		dmi_get_system_info(DMI_BIOS_VENDOR),
 		dmi_get_system_info(DMI_BIOS_VERSION),
 		dmi_get_system_info(DMI_PRODUCT_VERSION));
+	add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
 }
 
 static int __ref
@@ -888,7 +899,8 @@
 	if (!ret)
 		ret = dmar_walk_dmar_table((struct acpi_table_dmar *)dmar_tbl,
 					   &validate_drhd_cb);
-	if (!ret && !no_iommu && !iommu_detected && !dmar_disabled) {
+	if (!ret && !no_iommu && !iommu_detected &&
+	    (!dmar_disabled || dmar_platform_optin())) {
 		iommu_detected = 1;
 		/* Make sure ACS will be enabled */
 		pci_request_acs();
@@ -1009,8 +1021,8 @@
 {
 	struct intel_iommu *iommu;
 	u32 ver, sts;
-	int agaw = 0;
-	int msagaw = 0;
+	int agaw = -1;
+	int msagaw = -1;
 	int err;
 
 	if (!drhd->reg_base_addr) {
@@ -1035,17 +1047,28 @@
 	}
 
 	err = -EINVAL;
-	agaw = iommu_calculate_agaw(iommu);
-	if (agaw < 0) {
-		pr_err("Cannot get a valid agaw for iommu (seq_id = %d)\n",
-			iommu->seq_id);
-		goto err_unmap;
-	}
-	msagaw = iommu_calculate_max_sagaw(iommu);
-	if (msagaw < 0) {
-		pr_err("Cannot get a valid max agaw for iommu (seq_id = %d)\n",
-			iommu->seq_id);
-		goto err_unmap;
+	if (cap_sagaw(iommu->cap) == 0) {
+		pr_info("%s: No supported address widths. Not attempting DMA translation.\n",
+			iommu->name);
+		drhd->ignored = 1;
+	}
+
+	if (!drhd->ignored) {
+		agaw = iommu_calculate_agaw(iommu);
+		if (agaw < 0) {
+			pr_err("Cannot get a valid agaw for iommu (seq_id = %d)\n",
+			       iommu->seq_id);
+			drhd->ignored = 1;
+		}
+	}
+	if (!drhd->ignored) {
+		msagaw = iommu_calculate_max_sagaw(iommu);
+		if (msagaw < 0) {
+			pr_err("Cannot get a valid max agaw for iommu (seq_id = %d)\n",
+			       iommu->seq_id);
+			drhd->ignored = 1;
+			agaw = -1;
+		}
 	}
 	iommu->agaw = agaw;
 	iommu->msagaw = msagaw;
@@ -1072,7 +1095,12 @@
 
 	raw_spin_lock_init(&iommu->register_lock);
 
-	if (intel_iommu_enabled) {
+	/*
+	 * This is only for hotplug; at boot time intel_iommu_enabled won't
+	 * be set yet. When intel_iommu_init() runs, it registers the units
+	 * present at boot time, then sets intel_iommu_enabled.
+	 */
+	if (intel_iommu_enabled && !drhd->ignored) {
 		err = iommu_device_sysfs_add(&iommu->iommu, NULL,
 					     intel_iommu_groups,
 					     "%s", iommu->name);
@@ -1083,13 +1111,16 @@
 
 		err = iommu_device_register(&iommu->iommu);
 		if (err)
-			goto err_unmap;
+			goto err_sysfs;
 	}
 
 	drhd->iommu = iommu;
+	iommu->drhd = drhd;
 
 	return 0;
 
+err_sysfs:
+	iommu_device_sysfs_remove(&iommu->iommu);
 err_unmap:
 	unmap_iommu(iommu);
 error_free_seq_id:
@@ -1101,7 +1132,7 @@
 
 static void free_iommu(struct intel_iommu *iommu)
 {
-	if (intel_iommu_enabled) {
+	if (intel_iommu_enabled && !iommu->drhd->ignored) {
 		iommu_device_unregister(&iommu->iommu);
 		iommu_device_sysfs_remove(&iommu->iommu);
 	}
@@ -1263,7 +1294,7 @@
 	 */
 	writel(qi->free_head << shift, iommu->reg + DMAR_IQT_REG);
 
-	while (qi->desc_status[wait_index] != QI_DONE) {
+	while (READ_ONCE(qi->desc_status[wait_index]) != QI_DONE) {
 		/*
 		 * We will leave the interrupts disabled, to prevent interrupt
 		 * context to queue another cmd while a cmd is already submitted
@@ -1351,7 +1382,6 @@
 	struct qi_desc desc;
 
 	if (mask) {
-		WARN_ON_ONCE(addr & ((1ULL << (VTD_PAGE_SHIFT + mask)) - 1));
 		addr |= (1ULL << (VTD_PAGE_SHIFT + mask - 1)) - 1;
 		desc.qw1 = QI_DEV_IOTLB_ADDR(addr) | QI_DEV_IOTLB_SIZE;
 	} else
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iommu/exynos-iommu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iommu/exynos-iommu.c
@@ -635,7 +635,7 @@
 
 	ret = iommu_device_register(&data->iommu);
 	if (ret)
-		return ret;
+		goto err_iommu_register;
 
 	platform_set_drvdata(pdev, data);
 
@@ -662,6 +662,10 @@
 	pm_runtime_enable(dev);
 
 	return 0;
+
+err_iommu_register:
+	iommu_device_sysfs_remove(&data->iommu);
+	return ret;
 }
 
 static int __maybe_unused exynos_sysmmu_suspend(struct device *dev)
@@ -1073,7 +1077,7 @@
  */
 static int exynos_iommu_map(struct iommu_domain *iommu_domain,
 			    unsigned long l_iova, phys_addr_t paddr, size_t size,
-			    int prot)
+			    int prot, gfp_t gfp)
 {
 	struct exynos_iommu_domain *domain = to_exynos_domain(iommu_domain);
 	sysmmu_pte_t *entry;
@@ -1299,13 +1303,17 @@
 		return -ENODEV;
 
 	data = platform_get_drvdata(sysmmu);
-	if (!data)
+	if (!data) {
+		put_device(&sysmmu->dev);
 		return -ENODEV;
+	}
 
 	if (!owner) {
 		owner = kzalloc(sizeof(*owner), GFP_KERNEL);
-		if (!owner)
+		if (!owner) {
+			put_device(&sysmmu->dev);
 			return -ENOMEM;
+		}
 
 		INIT_LIST_HEAD(&owner->controllers);
 		mutex_init(&owner->rpm_lock);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iommu/fsl_pamu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iommu/fsl_pamu.c
@@ -1122,7 +1122,7 @@
 		ret = create_csd(ppaact_phys, mem_size, csd_port_id);
 		if (ret) {
 			dev_err(dev, "could not create coherence subdomain\n");
-			return ret;
+			goto error;
 		}
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iommu/hyperv-iommu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iommu/hyperv-iommu.c
@@ -155,7 +155,10 @@
 				0, IOAPIC_REMAPPING_ENTRY, fn,
 				&hyperv_ir_domain_ops, NULL);
 
-	irq_domain_free_fwnode(fn);
+	if (!ioapic_ir_domain) {
+		irq_domain_free_fwnode(fn);
+		return -ENOMEM;
+	}
 
 	/*
 	 * Hyper-V doesn't provide irq remapping function for
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iommu/intel-iommu-debugfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iommu/intel-iommu-debugfs.c
@@ -32,38 +32,42 @@
 
 #define IOMMU_REGSET_ENTRY(_reg_)					\
 	{ DMAR_##_reg_##_REG, __stringify(_reg_) }
-static const struct iommu_regset iommu_regs[] = {
+
+static const struct iommu_regset iommu_regs_32[] = {
 	IOMMU_REGSET_ENTRY(VER),
-	IOMMU_REGSET_ENTRY(CAP),
-	IOMMU_REGSET_ENTRY(ECAP),
 	IOMMU_REGSET_ENTRY(GCMD),
 	IOMMU_REGSET_ENTRY(GSTS),
-	IOMMU_REGSET_ENTRY(RTADDR),
-	IOMMU_REGSET_ENTRY(CCMD),
 	IOMMU_REGSET_ENTRY(FSTS),
 	IOMMU_REGSET_ENTRY(FECTL),
 	IOMMU_REGSET_ENTRY(FEDATA),
 	IOMMU_REGSET_ENTRY(FEADDR),
 	IOMMU_REGSET_ENTRY(FEUADDR),
-	IOMMU_REGSET_ENTRY(AFLOG),
 	IOMMU_REGSET_ENTRY(PMEN),
 	IOMMU_REGSET_ENTRY(PLMBASE),
 	IOMMU_REGSET_ENTRY(PLMLIMIT),
+	IOMMU_REGSET_ENTRY(ICS),
+	IOMMU_REGSET_ENTRY(PRS),
+	IOMMU_REGSET_ENTRY(PECTL),
+	IOMMU_REGSET_ENTRY(PEDATA),
+	IOMMU_REGSET_ENTRY(PEADDR),
+	IOMMU_REGSET_ENTRY(PEUADDR),
+};
+
+static const struct iommu_regset iommu_regs_64[] = {
+	IOMMU_REGSET_ENTRY(CAP),
+	IOMMU_REGSET_ENTRY(ECAP),
+	IOMMU_REGSET_ENTRY(RTADDR),
+	IOMMU_REGSET_ENTRY(CCMD),
+	IOMMU_REGSET_ENTRY(AFLOG),
 	IOMMU_REGSET_ENTRY(PHMBASE),
 	IOMMU_REGSET_ENTRY(PHMLIMIT),
 	IOMMU_REGSET_ENTRY(IQH),
 	IOMMU_REGSET_ENTRY(IQT),
 	IOMMU_REGSET_ENTRY(IQA),
-	IOMMU_REGSET_ENTRY(ICS),
 	IOMMU_REGSET_ENTRY(IRTA),
 	IOMMU_REGSET_ENTRY(PQH),
 	IOMMU_REGSET_ENTRY(PQT),
 	IOMMU_REGSET_ENTRY(PQA),
-	IOMMU_REGSET_ENTRY(PRS),
-	IOMMU_REGSET_ENTRY(PECTL),
-	IOMMU_REGSET_ENTRY(PEDATA),
-	IOMMU_REGSET_ENTRY(PEADDR),
-	IOMMU_REGSET_ENTRY(PEUADDR),
 	IOMMU_REGSET_ENTRY(MTRRCAP),
 	IOMMU_REGSET_ENTRY(MTRRDEF),
 	IOMMU_REGSET_ENTRY(MTRR_FIX64K_00000),
@@ -126,10 +130,16 @@
 		 * by adding the offset to the pointer (virtual address).
 		 */
 		raw_spin_lock_irqsave(&iommu->register_lock, flag);
-		for (i = 0 ; i < ARRAY_SIZE(iommu_regs); i++) {
-			value = dmar_readq(iommu->reg + iommu_regs[i].offset);
+		for (i = 0 ; i < ARRAY_SIZE(iommu_regs_32); i++) {
+			value = dmar_readl(iommu->reg + iommu_regs_32[i].offset);
 			seq_printf(m, "%-16s\t0x%02x\t\t0x%016llx\n",
-				   iommu_regs[i].regs, iommu_regs[i].offset,
+				   iommu_regs_32[i].regs, iommu_regs_32[i].offset,
+				   value);
+		}
+		for (i = 0 ; i < ARRAY_SIZE(iommu_regs_64); i++) {
+			value = dmar_readq(iommu->reg + iommu_regs_64[i].offset);
+			seq_printf(m, "%-16s\t0x%02x\t\t0x%016llx\n",
+				   iommu_regs_64[i].regs, iommu_regs_64[i].offset,
 				   value);
 		}
 		raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
@@ -271,9 +281,16 @@
 {
 	struct dmar_drhd_unit *drhd;
 	struct intel_iommu *iommu;
+	u32 sts;
 
 	rcu_read_lock();
 	for_each_active_iommu(iommu, drhd) {
+		sts = dmar_readl(iommu->reg + DMAR_GSTS_REG);
+		if (!(sts & DMA_GSTS_TES)) {
+			seq_printf(m, "DMA Remapping is not enabled on %s\n",
+				   iommu->name);
+			continue;
+		}
 		root_tbl_walk(m, iommu);
 		seq_putc(m, '\n');
 	}
@@ -343,6 +360,7 @@
 	struct dmar_drhd_unit *drhd;
 	struct intel_iommu *iommu;
 	u64 irta;
+	u32 sts;
 
 	rcu_read_lock();
 	for_each_active_iommu(iommu, drhd) {
@@ -352,7 +370,8 @@
 		seq_printf(m, "Remapped Interrupt supported on IOMMU: %s\n",
 			   iommu->name);
 
-		if (iommu->ir_table) {
+		sts = dmar_readl(iommu->reg + DMAR_GSTS_REG);
+		if (iommu->ir_table && (sts & DMA_GSTS_IRES)) {
 			irta = virt_to_phys(iommu->ir_table->base);
 			seq_printf(m, " IR table address:%llx\n", irta);
 			ir_tbl_remap_entry_show(m, iommu);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iommu/intel-iommu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iommu/intel-iommu.c
@@ -123,29 +123,29 @@
 	return (level - 1) * LEVEL_STRIDE;
 }
 
-static inline int pfn_level_offset(unsigned long pfn, int level)
+static inline int pfn_level_offset(u64 pfn, int level)
 {
 	return (pfn >> level_to_offset_bits(level)) & LEVEL_MASK;
 }
 
-static inline unsigned long level_mask(int level)
+static inline u64 level_mask(int level)
 {
-	return -1UL << level_to_offset_bits(level);
+	return -1ULL << level_to_offset_bits(level);
 }
 
-static inline unsigned long level_size(int level)
+static inline u64 level_size(int level)
 {
-	return 1UL << level_to_offset_bits(level);
+	return 1ULL << level_to_offset_bits(level);
 }
 
-static inline unsigned long align_to_level(unsigned long pfn, int level)
+static inline u64 align_to_level(u64 pfn, int level)
 {
 	return (pfn + level_size(level) - 1) & level_mask(level);
 }
 
 static inline unsigned long lvl_to_nr_pages(unsigned int lvl)
 {
-	return  1 << min_t(int, (lvl - 1) * LEVEL_STRIDE, MAX_AGAW_PFN_WIDTH);
+	return 1UL << min_t(int, (lvl - 1) * LEVEL_STRIDE, MAX_AGAW_PFN_WIDTH);
 }
 
 /* VT-d pages must always be _smaller_ than MM pages. Otherwise things
@@ -179,7 +179,7 @@
  * (used when kernel is launched w/ TXT)
  */
 static int force_on = 0;
-int intel_iommu_tboot_noforce;
+static int intel_iommu_tboot_noforce;
 static int no_platform_optin;
 
 #define ROOT_ENTRY_NR (VTD_PAGE_SIZE/sizeof(struct root_entry))
@@ -611,6 +611,12 @@
 	return g_iommus[iommu_id];
 }
 
+static inline bool iommu_paging_structure_coherency(struct intel_iommu *iommu)
+{
+	return sm_supported(iommu) ?
+			ecap_smpwc(iommu->ecap) : ecap_coherent(iommu->ecap);
+}
+
 static void domain_update_iommu_coherency(struct dmar_domain *domain)
 {
 	struct dmar_drhd_unit *drhd;
@@ -622,7 +628,7 @@
 
 	for_each_domain_iommu(i, domain) {
 		found = true;
-		if (!ecap_coherent(g_iommus[i]->ecap)) {
+		if (!iommu_paging_structure_coherency(g_iommus[i])) {
 			domain->iommu_coherency = 0;
 			break;
 		}
@@ -633,7 +639,7 @@
 	/* No hardware attached; use lowest common denominator */
 	rcu_read_lock();
 	for_each_active_iommu(iommu, drhd) {
-		if (!ecap_coherent(iommu->ecap)) {
+		if (!iommu_paging_structure_coherency(iommu)) {
 			domain->iommu_coherency = 0;
 			break;
 		}
@@ -732,6 +738,11 @@
 	return dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO;
 }
 
+static bool attach_deferred(struct device *dev)
+{
+	return dev->archdata.iommu == DEFER_DEVICE_DOMAIN_INFO;
+}
+
 /**
  * is_downstream_to_pci_bridge - test if a device belongs to the PCI
  *				 sub-hierarchy of a candidate PCI-PCI bridge
@@ -1847,7 +1858,7 @@
 static int domain_init(struct dmar_domain *domain, struct intel_iommu *iommu,
 		       int guest_width)
 {
-	int adjust_width, agaw;
+	int adjust_width, agaw, cap_width;
 	unsigned long sagaw;
 	int err;
 
@@ -1861,8 +1872,9 @@
 	domain_reserve_special_ranges(domain);
 
 	/* calculate AGAW */
-	if (guest_width > cap_mgaw(iommu->cap))
-		guest_width = cap_mgaw(iommu->cap);
+	cap_width = min_t(int, cap_mgaw(iommu->cap), agaw_to_width(iommu->agaw));
+	if (guest_width > cap_width)
+		guest_width = cap_width;
 	domain->gaw = guest_width;
 	adjust_width = guestwidth_to_adjustwidth(guest_width);
 	agaw = width_to_agaw(adjust_width);
@@ -2090,7 +2102,8 @@
 
 	context_set_fault_enable(context);
 	context_set_present(context);
-	domain_flush_cache(domain, context, sizeof(*context));
+	if (!ecap_coherent(iommu->ecap))
+		clflush_cache_range(context, sizeof(*context));
 
 	/*
 	 * It's a non-present to present mapping. If hardware doesn't cache
@@ -2420,31 +2433,31 @@
 	spin_unlock_irqrestore(&device_domain_lock, flags);
 }
 
-/*
- * find_domain
- * Note: we use struct device->archdata.iommu stores the info
- */
 static struct dmar_domain *find_domain(struct device *dev)
 {
 	struct device_domain_info *info;
 
-	if (unlikely(dev->archdata.iommu == DEFER_DEVICE_DOMAIN_INFO)) {
-		struct iommu_domain *domain;
-
-		dev->archdata.iommu = NULL;
-		domain = iommu_get_domain_for_dev(dev);
-		if (domain)
-			intel_iommu_attach_device(domain, dev);
-	}
+	if (unlikely(attach_deferred(dev) || iommu_dummy(dev)))
+		return NULL;
 
 	/* No lock here, assumes no domain exit in normal case */
 	info = dev->archdata.iommu;
-
 	if (likely(info))
 		return info->domain;
+
 	return NULL;
 }
 
+static void do_deferred_attach(struct device *dev)
+{
+	struct iommu_domain *domain;
+
+	dev->archdata.iommu = NULL;
+	domain = iommu_get_domain_for_dev(dev);
+	if (domain)
+		intel_iommu_attach_device(domain, dev);
+}
+
 static inline struct device_domain_info *
 dmar_search_domain_by_dev_info(int segment, int bus, int devfn)
 {
@@ -2553,14 +2566,14 @@
 		}
 
 		/* Setup the PASID entry for requests without PASID: */
-		spin_lock(&iommu->lock);
+		spin_lock_irqsave(&iommu->lock, flags);
 		if (hw_pass_through && domain_type_is_si(domain))
 			ret = intel_pasid_setup_pass_through(iommu, domain,
 					dev, PASID_RID2PASID);
 		else
 			ret = intel_pasid_setup_second_level(iommu, domain,
 					dev, PASID_RID2PASID);
-		spin_unlock(&iommu->lock);
+		spin_unlock_irqrestore(&iommu->lock, flags);
 		if (ret) {
 			dev_err(dev, "Setup RID2PASID failed\n");
 			dmar_remove_one_dev_info(dev);
@@ -2743,6 +2756,7 @@
 
 	if (md_domain_init(si_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
 		domain_exit(si_domain);
+		si_domain = NULL;
 		return -EFAULT;
 	}
 
@@ -2762,10 +2776,8 @@
 	}
 
 	/*
-	 * Normally we use DMA domains for devices which have RMRRs. But we
-	 * loose this requirement for graphic and usb devices. Identity map
-	 * the RMRRs for graphic and USB devices so that they could use the
-	 * si_domain.
+	 * Identity map the RMRRs so that devices with RMRRs could also use
+	 * the si_domain.
 	 */
 	for_each_rmrr_units(rmrr) {
 		for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt,
@@ -2773,9 +2785,6 @@
 			unsigned long long start = rmrr->base_address;
 			unsigned long long end = rmrr->end_address;
 
-			if (device_is_rmrr_locked(dev))
-				continue;
-
 			if (WARN_ON(end < start ||
 				    end >> agaw_to_width(si_domain->agaw)))
 				continue;
@@ -2794,7 +2803,7 @@
 	struct device_domain_info *info;
 
 	info = dev->archdata.iommu;
-	if (info && info != DUMMY_DEVICE_DOMAIN_INFO && info != DEFER_DEVICE_DOMAIN_INFO)
+	if (info)
 		return (info->domain == si_domain);
 
 	return 0;
@@ -2914,9 +2923,6 @@
 	if (dev_is_pci(dev)) {
 		struct pci_dev *pdev = to_pci_dev(dev);
 
-		if (device_is_rmrr_locked(dev))
-			return IOMMU_DOMAIN_DMA;
-
 		/*
 		 * Prevent any device marked as untrusted from getting
 		 * placed into the statically identity mapping domain.
@@ -2954,9 +2960,6 @@
 				return IOMMU_DOMAIN_DMA;
 		} else if (pci_pcie_type(pdev) == PCI_EXP_TYPE_PCI_BRIDGE)
 			return IOMMU_DOMAIN_DMA;
-	} else {
-		if (device_has_rmrr(dev))
-			return IOMMU_DOMAIN_DMA;
 	}
 
 	return (iommu_identity_mapping & IDENTMAP_ALL) ?
@@ -3289,6 +3292,12 @@
 
 		if (!ecap_pass_through(iommu->ecap))
 			hw_pass_through = 0;
+
+		if (!intel_iommu_strict && cap_caching_mode(iommu->cap)) {
+			pr_info("Disable batched IOTLB flush due to virtualization");
+			intel_iommu_strict = 1;
+		}
+
 #ifdef CONFIG_INTEL_IOMMU_SVM
 		if (pasid_supported(iommu))
 			intel_svm_init(iommu);
@@ -3368,6 +3377,10 @@
 		disable_dmar_iommu(iommu);
 		free_dmar_iommu(iommu);
 	}
+	if (si_domain) {
+		domain_exit(si_domain);
+		si_domain = NULL;
+	}
 
 	kfree(g_iommus);
 
@@ -3401,7 +3414,8 @@
 	iova_pfn = alloc_iova_fast(&domain->iovad, nrpages,
 				   IOVA_PFN(dma_mask), true);
 	if (unlikely(!iova_pfn)) {
-		dev_err(dev, "Allocating %ld-page iova failed", nrpages);
+		dev_err_once(dev, "Allocating %ld-page iova failed\n",
+			     nrpages);
 		return 0;
 	}
 
@@ -3464,6 +3478,9 @@
 	if (iommu_dummy(dev))
 		return false;
 
+	if (unlikely(attach_deferred(dev)))
+		do_deferred_attach(dev);
+
 	ret = identity_mapping(dev);
 	if (ret) {
 		u64 dma_mask = *dev->dma_mask;
@@ -3827,7 +3844,11 @@
 	int prot = 0;
 	int ret;
 
+	if (unlikely(attach_deferred(dev)))
+		do_deferred_attach(dev);
+
 	domain = find_domain(dev);
+
 	if (WARN_ON(dir == DMA_NONE || !domain))
 		return DMA_MAPPING_ERROR;
 
@@ -4128,10 +4149,11 @@
 
 	/* we know that the this iommu should be at offset 0xa000 from vtbar */
 	drhd = dmar_find_matched_drhd_unit(pdev);
-	if (WARN_TAINT_ONCE(!drhd || drhd->reg_base_addr - vtbar != 0xa000,
-			    TAINT_FIRMWARE_WORKAROUND,
-			    "BIOS assigned incorrect VT-d unit for Intel(R) QuickData Technology device\n"))
+	if (!drhd || drhd->reg_base_addr - vtbar != 0xa000) {
+		pr_warn_once(FW_BUG "BIOS assigned incorrect VT-d unit for Intel(R) QuickData Technology device\n");
+		add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
 		pdev->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
+	}
 }
 DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB, quirk_ioat_snb_local_iommu);
 
@@ -4344,7 +4366,8 @@
 	struct dmar_atsr_unit *atsru;
 	struct acpi_dmar_atsr *tmp;
 
-	list_for_each_entry_rcu(atsru, &dmar_atsr_units, list) {
+	list_for_each_entry_rcu(atsru, &dmar_atsr_units, list,
+				dmar_rcu_check()) {
 		tmp = (struct acpi_dmar_atsr *)atsru->hdr;
 		if (atsr->segment != tmp->segment)
 			continue;
@@ -4928,7 +4951,8 @@
 	 * Intel IOMMU is required for a TXT/tboot launch or platform
 	 * opt in, so enforce that.
 	 */
-	force_on = tboot_force_iommu() || platform_optin_force_iommu();
+	force_on = (!intel_iommu_tboot_noforce && tboot_force_iommu()) ||
+		    platform_optin_force_iommu();
 
 	if (iommu_init_mempool()) {
 		if (force_on)
@@ -4959,6 +4983,9 @@
 
 	down_write(&dmar_global_lock);
 
+	if (!no_iommu)
+		intel_iommu_debugfs_init();
+
 	if (no_iommu || dmar_disabled) {
 		/*
 		 * We exit the function here to ensure IOMMU's remapping and
@@ -5022,6 +5049,7 @@
 
 	init_iommu_pm_ops();
 
+	down_read(&dmar_global_lock);
 	for_each_active_iommu(iommu, drhd) {
 		iommu_device_sysfs_add(&iommu->iommu, NULL,
 				       intel_iommu_groups,
@@ -5029,6 +5057,7 @@
 		iommu_device_set_ops(&iommu->iommu, &intel_iommu_ops);
 		iommu_device_register(&iommu->iommu);
 	}
+	up_read(&dmar_global_lock);
 
 	bus_set_iommu(&pci_bus_type, &intel_iommu_ops);
 	if (si_domain && !hw_pass_through)
@@ -5039,7 +5068,6 @@
 	down_read(&dmar_global_lock);
 	if (probe_acpi_namespace_devices())
 		pr_warn("ACPI name space devices didn't probe correctly\n");
-	up_read(&dmar_global_lock);
 
 	/* Finally, we enable the DMA remapping hardware. */
 	for_each_iommu(iommu, drhd) {
@@ -5048,10 +5076,11 @@
 
 		iommu_disable_protect_mem_regions(iommu);
 	}
+	up_read(&dmar_global_lock);
+
 	pr_info("Intel(R) Virtualization Technology for Directed I/O\n");
 
 	intel_iommu_enabled = 1;
-	intel_iommu_debugfs_init();
 
 	return 0;
 
@@ -5132,7 +5161,8 @@
 
 	spin_lock_irqsave(&device_domain_lock, flags);
 	info = dev->archdata.iommu;
-	if (info)
+	if (info && info != DEFER_DEVICE_DOMAIN_INFO
+	    && info != DUMMY_DEVICE_DOMAIN_INFO)
 		__dmar_remove_one_dev_info(info);
 	spin_unlock_irqrestore(&device_domain_lock, flags);
 }
@@ -5440,16 +5470,13 @@
 
 static int intel_iommu_map(struct iommu_domain *domain,
 			   unsigned long iova, phys_addr_t hpa,
-			   size_t size, int iommu_prot)
+			   size_t size, int iommu_prot, gfp_t gfp)
 {
 	struct dmar_domain *dmar_domain = to_dmar_domain(domain);
 	u64 max_addr;
 	int prot = 0;
 	int ret;
 
-	if (dmar_domain->flags & DOMAIN_FLAG_LOSE_CHILDREN)
-		return -EINVAL;
-
 	if (iommu_prot & IOMMU_READ)
 		prot |= DMA_PTE_READ;
 	if (iommu_prot & IOMMU_WRITE)
@@ -5492,8 +5519,6 @@
 	/* Cope with horrid API which requires us to unmap more than the
 	   size argument if it happens to be a large-page mapping. */
 	BUG_ON(!pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level));
-	if (dmar_domain->flags & DOMAIN_FLAG_LOSE_CHILDREN)
-		return 0;
 
 	if (size < VTD_PAGE_SIZE << level_to_offset_bits(level))
 		size = VTD_PAGE_SIZE << level_to_offset_bits(level);
@@ -5525,12 +5550,11 @@
 	int level = 0;
 	u64 phys = 0;
 
-	if (dmar_domain->flags & DOMAIN_FLAG_LOSE_CHILDREN)
-		return 0;
-
 	pte = pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level);
-	if (pte)
-		phys = dma_pte_addr(pte);
+	if (pte && dma_pte_present(pte))
+		phys = dma_pte_addr(pte) +
+			(iova & (BIT_MASK(level_to_offset_bits(level) +
+						VTD_PAGE_SHIFT) - 1));
 
 	return phys;
 }
@@ -5601,8 +5625,10 @@
 
 	group = iommu_group_get_for_dev(dev);
 
-	if (IS_ERR(group))
-		return PTR_ERR(group);
+	if (IS_ERR(group)) {
+		ret = PTR_ERR(group);
+		goto unlink;
+	}
 
 	iommu_group_put(group);
 
@@ -5628,7 +5654,8 @@
 				if (!get_private_domain_for_dev(dev)) {
 					dev_warn(dev,
 						 "Failed to get a private domain.\n");
-					return -ENOMEM;
+					ret = -ENOMEM;
+					goto unlink;
 				}
 
 				dev_info(dev,
@@ -5643,6 +5670,10 @@
 	}
 
 	return 0;
+
+unlink:
+	iommu_device_unlink(&iommu->iommu, dev);
+	return ret;
 }
 
 static void intel_iommu_remove_device(struct device *dev)
@@ -5705,8 +5736,8 @@
 		struct pci_dev *pdev = to_pci_dev(device);
 
 		if ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA) {
-			reg = iommu_alloc_resv_region(0, 1UL << 24, 0,
-						      IOMMU_RESV_DIRECT);
+			reg = iommu_alloc_resv_region(0, 1UL << 24, prot,
+						   IOMMU_RESV_DIRECT_RELAXABLE);
 			if (reg)
 				list_add_tail(&reg->list, head);
 		}
@@ -5794,6 +5825,13 @@
 	WARN_ON_ONCE(!reserve_iova(&dmar_domain->iovad, start, end));
 }
 
+static struct iommu_group *intel_iommu_device_group(struct device *dev)
+{
+	if (dev_is_pci(dev))
+		return pci_device_group(dev);
+	return generic_device_group(dev);
+}
+
 #ifdef CONFIG_INTEL_IOMMU_SVM
 struct intel_iommu *intel_svm_device_to_iommu(struct device *dev)
 {
@@ -5946,7 +5984,24 @@
 static bool intel_iommu_is_attach_deferred(struct iommu_domain *domain,
 					   struct device *dev)
 {
-	return dev->archdata.iommu == DEFER_DEVICE_DOMAIN_INFO;
+	return attach_deferred(dev);
+}
+
+/*
+ * Check that the device does not live on an external facing PCI port that is
+ * marked as untrusted. Such devices should not be able to apply quirks and
+ * thus not be able to bypass the IOMMU restrictions.
+ */
+static bool risky_device(struct pci_dev *pdev)
+{
+	if (pdev->untrusted) {
+		pci_info(pdev,
+			 "Skipping IOMMU quirk for dev [%04X:%04X] on untrusted PCI link\n",
+			 pdev->vendor, pdev->device);
+		pci_info(pdev, "Please check with your BIOS/Platform vendor about this\n");
+		return true;
+	}
+	return false;
 }
 
 const struct iommu_ops intel_iommu_ops = {
@@ -5966,7 +6021,7 @@
 	.get_resv_regions	= intel_iommu_get_resv_regions,
 	.put_resv_regions	= intel_iommu_put_resv_regions,
 	.apply_resv_region	= intel_iommu_apply_resv_region,
-	.device_group		= pci_device_group,
+	.device_group		= intel_iommu_device_group,
 	.dev_has_feat		= intel_iommu_dev_has_feat,
 	.dev_feat_enabled	= intel_iommu_dev_feat_enabled,
 	.dev_enable_feat	= intel_iommu_dev_enable_feat,
@@ -5977,6 +6032,9 @@
 
 static void quirk_iommu_igfx(struct pci_dev *dev)
 {
+	if (risky_device(dev))
+		return;
+
 	pci_info(dev, "Disabling IOMMU for graphics on this chipset\n");
 	dmar_map_gfx = 0;
 }
@@ -6018,6 +6076,9 @@
 
 static void quirk_iommu_rwbf(struct pci_dev *dev)
 {
+	if (risky_device(dev))
+		return;
+
 	/*
 	 * Mobile 4 Series Chipset neglects to set RWBF capability,
 	 * but needs it. Same seems to hold for the desktop versions.
@@ -6048,6 +6109,9 @@
 {
 	unsigned short ggc;
 
+	if (risky_device(dev))
+		return;
+
 	if (pci_read_config_word(dev, GGC, &ggc))
 		return;
 
@@ -6081,6 +6145,12 @@
 	pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x3a3e, NULL);
 	if (!pdev)
 		return;
+
+	if (risky_device(pdev)) {
+		pci_dev_put(pdev);
+		return;
+	}
+
 	pci_dev_put(pdev);
 
 	/* System Management Registers. Might be hidden, in which case
@@ -6090,6 +6160,11 @@
 	if (!pdev)
 		return;
 
+	if (risky_device(pdev)) {
+		pci_dev_put(pdev);
+		return;
+	}
+
 	if (pci_read_config_dword(pdev, 0x188, &vtisochctrl)) {
 		pci_dev_put(pdev);
 		return;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iommu/intel-pasid.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iommu/intel-pasid.c
@@ -166,6 +166,9 @@
 attach_out:
 	device_attach_pasid_table(info, pasid_table);
 
+	if (!ecap_coherent(info->iommu->ecap))
+		clflush_cache_range(pasid_table->table, (1 << order) * PAGE_SIZE);
+
 	return 0;
 }
 
@@ -250,6 +253,10 @@
 
 		WRITE_ONCE(dir[dir_index].val,
 			   (u64)virt_to_phys(entries) | PASID_PTE_PRESENT);
+		if (!ecap_coherent(info->iommu->ecap)) {
+			clflush_cache_range(entries, VTD_PAGE_SIZE);
+			clflush_cache_range(&dir[dir_index].val, sizeof(*dir));
+		}
 	}
 	spin_unlock(&pasid_lock);
 
@@ -434,6 +441,9 @@
 	if (!info || !info->ats_enabled)
 		return;
 
+	if (pci_dev_is_disconnected(to_pci_dev(dev)))
+		return;
+
 	sid = info->bus << 8 | info->devfn;
 	qdep = info->ats_qdep;
 	pfsid = info->pfsid;
@@ -499,8 +509,16 @@
 	}
 
 #ifdef CONFIG_X86
-	if (cpu_feature_enabled(X86_FEATURE_LA57))
-		pasid_set_flpm(pte, 1);
+	/* Both CPU and IOMMU paging mode need to match */
+	if (cpu_feature_enabled(X86_FEATURE_LA57)) {
+		if (cap_5lp_support(iommu->cap)) {
+			pasid_set_flpm(pte, 1);
+		} else {
+			pr_err("VT-d has no 5-level paging support for CPU\n");
+			pasid_clear_entry(pte);
+			return -EINVAL;
+		}
+	}
 #endif /* CONFIG_X86 */
 
 	pasid_set_domain_id(pte, did);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iommu/intel-svm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iommu/intel-svm.c
@@ -99,16 +99,14 @@
 	return 0;
 }
 
-static void intel_flush_svm_range_dev (struct intel_svm *svm, struct intel_svm_dev *sdev,
-				unsigned long address, unsigned long pages, int ih)
+static void __flush_svm_range_dev(struct intel_svm *svm,
+				  struct intel_svm_dev *sdev,
+				  unsigned long address,
+				  unsigned long pages, int ih)
 {
 	struct qi_desc desc;
 
-	/*
-	 * Do PASID granu IOTLB invalidation if page selective capability is
-	 * not available.
-	 */
-	if (pages == -1 || !cap_pgsel_inv(svm->iommu->cap)) {
+	if (pages == -1) {
 		desc.qw0 = QI_EIOTLB_PASID(svm->pasid) |
 			QI_EIOTLB_DID(sdev->did) |
 			QI_EIOTLB_GRAN(QI_GRAN_NONG_PASID) |
@@ -155,6 +153,22 @@
 	}
 }
 
+static void intel_flush_svm_range_dev(struct intel_svm *svm,
+				      struct intel_svm_dev *sdev,
+				      unsigned long address,
+				      unsigned long pages, int ih)
+{
+	unsigned long shift = ilog2(__roundup_pow_of_two(pages));
+	unsigned long align = (1ULL << (VTD_PAGE_SHIFT + shift));
+	unsigned long start = ALIGN_DOWN(address, align);
+	unsigned long end = ALIGN(address + (pages << VTD_PAGE_SHIFT), align);
+
+	while (start < end) {
+		__flush_svm_range_dev(svm, sdev, start, align >> VTD_PAGE_SHIFT, ih);
+		start += align;
+	}
+}
+
 static void intel_flush_svm_range(struct intel_svm *svm, unsigned long address,
 				unsigned long pages, int ih)
 {
@@ -321,7 +335,7 @@
 		/* Do not use PASID 0 in caching mode (virtualised IOMMU) */
 		ret = intel_pasid_alloc_id(svm,
 					   !!cap_caching_mode(iommu->cap),
-					   pasid_max - 1, GFP_KERNEL);
+					   pasid_max, GFP_KERNEL);
 		if (ret < 0) {
 			kfree(svm);
 			kfree(sdev);
@@ -506,7 +520,7 @@
 	u64 priv_data[2];
 };
 
-#define PRQ_RING_MASK ((0x1000 << PRQ_ORDER) - 0x10)
+#define PRQ_RING_MASK	((0x1000 << PRQ_ORDER) - 0x20)
 
 static bool access_error(struct vm_area_struct *vma, struct page_req_dsc *req)
 {
@@ -587,14 +601,15 @@
 		 * any faults on kernel addresses. */
 		if (!svm->mm)
 			goto bad_req;
-		/* If the mm is already defunct, don't handle faults. */
-		if (!mmget_not_zero(svm->mm))
-			goto bad_req;
 
 		/* If address is not canonical, return invalid response */
 		if (!is_canonical_address(address))
 			goto bad_req;
 
+		/* If the mm is already defunct, don't handle faults. */
+		if (!mmget_not_zero(svm->mm))
+			goto bad_req;
+
 		down_read(&svm->mm->mmap_sem);
 		vma = find_extend_vma(svm->mm, address);
 		if (!vma || address < vma->vm_start)
@@ -649,7 +664,7 @@
 			resp.qw0 = QI_PGRP_PASID(req->pasid) |
 				QI_PGRP_DID(req->rid) |
 				QI_PGRP_PASID_P(req->pasid_present) |
-				QI_PGRP_PDP(req->pasid_present) |
+				QI_PGRP_PDP(req->priv_data_present) |
 				QI_PGRP_RESP_CODE(result) |
 				QI_PGRP_RESP_TYPE;
 			resp.qw1 = QI_PGRP_IDX(req->prg_index) |
@@ -658,11 +673,10 @@
 			if (req->priv_data_present)
 				memcpy(&resp.qw2, req->priv_data,
 				       sizeof(req->priv_data));
+			resp.qw2 = 0;
+			resp.qw3 = 0;
+			qi_submit_sync(&resp, iommu);
 		}
-		resp.qw2 = 0;
-		resp.qw3 = 0;
-		qi_submit_sync(&resp, iommu);
-
 		head = (head + sizeof(*req)) & PRQ_RING_MASK;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iommu/intel_irq_remapping.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iommu/intel_irq_remapping.c
@@ -507,12 +507,18 @@
 
 	/* Enable interrupt-remapping */
 	iommu->gcmd |= DMA_GCMD_IRE;
-	iommu->gcmd &= ~DMA_GCMD_CFI;  /* Block compatibility-format MSIs */
 	writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
-
 	IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
 		      readl, (sts & DMA_GSTS_IRES), sts);
 
+	/* Block compatibility-format MSIs */
+	if (sts & DMA_GSTS_CFIS) {
+		iommu->gcmd &= ~DMA_GCMD_CFI;
+		writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
+		IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
+			      readl, !(sts & DMA_GSTS_CFIS), sts);
+	}
+
 	/*
 	 * With CFI clear in the Global Command register, we should be
 	 * protected from dangerous (i.e. compatibility) interrupts
@@ -563,10 +569,9 @@
 					    0, INTR_REMAP_TABLE_ENTRIES,
 					    fn, &intel_ir_domain_ops,
 					    iommu);
-	irq_domain_free_fwnode(fn);
 	if (!iommu->ir_domain) {
 		pr_err("IR%d: failed to allocate irqdomain\n", iommu->seq_id);
-		goto out_free_bitmap;
+		goto out_free_fwnode;
 	}
 	iommu->ir_msi_domain =
 		arch_create_remap_msi_irq_domain(iommu->ir_domain,
@@ -590,7 +595,7 @@
 
 		if (dmar_enable_qi(iommu)) {
 			pr_err("Failed to enable queued invalidation\n");
-			goto out_free_bitmap;
+			goto out_free_ir_domain;
 		}
 	}
 
@@ -614,6 +619,14 @@
 
 	return 0;
 
+out_free_ir_domain:
+	if (iommu->ir_msi_domain)
+		irq_domain_remove(iommu->ir_msi_domain);
+	iommu->ir_msi_domain = NULL;
+	irq_domain_remove(iommu->ir_domain);
+	iommu->ir_domain = NULL;
+out_free_fwnode:
+	irq_domain_free_fwnode(fn);
 out_free_bitmap:
 	bitmap_free(bitmap);
 out_free_pages:
@@ -628,13 +641,21 @@
 
 static void intel_teardown_irq_remapping(struct intel_iommu *iommu)
 {
+	struct fwnode_handle *fn;
+
 	if (iommu && iommu->ir_table) {
 		if (iommu->ir_msi_domain) {
+			fn = iommu->ir_msi_domain->fwnode;
+
 			irq_domain_remove(iommu->ir_msi_domain);
+			irq_domain_free_fwnode(fn);
 			iommu->ir_msi_domain = NULL;
 		}
 		if (iommu->ir_domain) {
+			fn = iommu->ir_domain->fwnode;
+
 			irq_domain_remove(iommu->ir_domain);
+			irq_domain_free_fwnode(fn);
 			iommu->ir_domain = NULL;
 		}
 		free_pages((unsigned long)iommu->ir_table->base,
@@ -1386,6 +1407,8 @@
 		irq_data = irq_domain_get_irq_data(domain, virq + i);
 		irq_cfg = irqd_cfg(irq_data);
 		if (!irq_data || !irq_cfg) {
+			if (!i)
+				kfree(data);
 			ret = -EINVAL;
 			goto out_free_data;
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iommu/io-pgtable-arm-v7s.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iommu/io-pgtable-arm-v7s.c
@@ -244,13 +244,17 @@
 			__GFP_ZERO | ARM_V7S_TABLE_GFP_DMA, get_order(size));
 	else if (lvl == 2)
 		table = kmem_cache_zalloc(data->l2_tables, gfp);
+
+	if (!table)
+		return NULL;
+
 	phys = virt_to_phys(table);
 	if (phys != (arm_v7s_iopte)phys) {
 		/* Doesn't fit in PTE */
 		dev_err(dev, "Page table does not fit in PTE: %pa", &phys);
 		goto out_free;
 	}
-	if (table && !cfg->coherent_walk) {
+	if (!cfg->coherent_walk) {
 		dma = dma_map_single(dev, table, size, DMA_TO_DEVICE);
 		if (dma_mapping_error(dev, dma))
 			goto out_free;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iommu/io-pgtable-arm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iommu/io-pgtable-arm.c
@@ -351,11 +351,12 @@
 static arm_lpae_iopte arm_lpae_install_table(arm_lpae_iopte *table,
 					     arm_lpae_iopte *ptep,
 					     arm_lpae_iopte curr,
-					     struct io_pgtable_cfg *cfg)
+					     struct arm_lpae_io_pgtable *data)
 {
 	arm_lpae_iopte old, new;
+	struct io_pgtable_cfg *cfg = &data->iop.cfg;
 
-	new = __pa(table) | ARM_LPAE_PTE_TYPE_TABLE;
+	new = paddr_to_iopte(__pa(table), data) | ARM_LPAE_PTE_TYPE_TABLE;
 	if (cfg->quirks & IO_PGTABLE_QUIRK_ARM_NS)
 		new |= ARM_LPAE_PTE_NSTABLE;
 
@@ -406,7 +407,7 @@
 		if (!cptep)
 			return -ENOMEM;
 
-		pte = arm_lpae_install_table(cptep, ptep, 0, cfg);
+		pte = arm_lpae_install_table(cptep, ptep, 0, data);
 		if (pte)
 			__arm_lpae_free_pages(cptep, tblsz, cfg);
 	} else if (!cfg->coherent_walk && !(pte & ARM_LPAE_PTE_SW_SYNC)) {
@@ -575,7 +576,7 @@
 		__arm_lpae_init_pte(data, blk_paddr, pte, lvl, &tablep[i]);
 	}
 
-	pte = arm_lpae_install_table(tablep, ptep, blk_pte, cfg);
+	pte = arm_lpae_install_table(tablep, ptep, blk_pte, data);
 	if (pte != blk_pte) {
 		__arm_lpae_free_pages(tablep, tablesz, cfg);
 		/*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iommu/iommu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iommu/iommu.c
@@ -312,8 +312,8 @@
 	list_for_each_entry_safe(iter, tmp, regions, list) {
 		phys_addr_t top_end, iter_end = iter->start + iter->length - 1;
 
-		/* no merge needed on elements of different types than @nr */
-		if (iter->type != nr->type) {
+		/* no merge needed on elements of different types than @new */
+		if (iter->type != new->type) {
 			list_move_tail(&iter->list, &stack);
 			continue;
 		}
@@ -492,7 +492,7 @@
 				   NULL, "%d", group->id);
 	if (ret) {
 		ida_simple_remove(&iommu_group_ida, group->id);
-		kfree(group);
+		kobject_put(&group->kobj);
 		return ERR_PTR(ret);
 	}
 
@@ -751,6 +751,7 @@
 	mutex_unlock(&group->mutex);
 	dev->iommu_group = NULL;
 	kobject_put(group->devices_kobj);
+	sysfs_remove_link(group->devices_kobj, device->name);
 err_free_name:
 	kfree(device->name);
 err_remove_link:
@@ -774,6 +775,9 @@
 	struct iommu_group *group = dev->iommu_group;
 	struct group_device *tmp_device, *device = NULL;
 
+	if (!group)
+		return;
+
 	dev_info(dev, "Removing from iommu group %d\n", group->id);
 
 	/* Pre-notify listeners that a device is being removed. */
@@ -1854,8 +1858,8 @@
 	return pgsize;
 }
 
-int iommu_map(struct iommu_domain *domain, unsigned long iova,
-	      phys_addr_t paddr, size_t size, int prot)
+int __iommu_map(struct iommu_domain *domain, unsigned long iova,
+	      phys_addr_t paddr, size_t size, int prot, gfp_t gfp)
 {
 	const struct iommu_ops *ops = domain->ops;
 	unsigned long orig_iova = iova;
@@ -1892,8 +1896,8 @@
 
 		pr_debug("mapping: iova 0x%lx pa %pa pgsize 0x%zx\n",
 			 iova, &paddr, pgsize);
+		ret = ops->map(domain, iova, paddr, pgsize, prot, gfp);
 
-		ret = ops->map(domain, iova, paddr, pgsize, prot);
 		if (ret)
 			break;
 
@@ -1913,8 +1917,22 @@
 
 	return ret;
 }
+
+int iommu_map(struct iommu_domain *domain, unsigned long iova,
+	      phys_addr_t paddr, size_t size, int prot)
+{
+	might_sleep();
+	return __iommu_map(domain, iova, paddr, size, prot, GFP_KERNEL);
+}
 EXPORT_SYMBOL_GPL(iommu_map);
 
+int iommu_map_atomic(struct iommu_domain *domain, unsigned long iova,
+	      phys_addr_t paddr, size_t size, int prot)
+{
+	return __iommu_map(domain, iova, paddr, size, prot, GFP_ATOMIC);
+}
+EXPORT_SYMBOL_GPL(iommu_map_atomic);
+
 static size_t __iommu_unmap(struct iommu_domain *domain,
 			    unsigned long iova, size_t size,
 			    struct iommu_iotlb_gather *iotlb_gather)
@@ -1991,8 +2009,9 @@
 }
 EXPORT_SYMBOL_GPL(iommu_unmap_fast);
 
-size_t iommu_map_sg(struct iommu_domain *domain, unsigned long iova,
-		    struct scatterlist *sg, unsigned int nents, int prot)
+size_t __iommu_map_sg(struct iommu_domain *domain, unsigned long iova,
+		    struct scatterlist *sg, unsigned int nents, int prot,
+		    gfp_t gfp)
 {
 	size_t len = 0, mapped = 0;
 	phys_addr_t start;
@@ -2003,7 +2022,9 @@
 		phys_addr_t s_phys = sg_phys(sg);
 
 		if (len && s_phys != start + len) {
-			ret = iommu_map(domain, iova + mapped, start, len, prot);
+			ret = __iommu_map(domain, iova + mapped, start,
+					len, prot, gfp);
+
 			if (ret)
 				goto out_err;
 
@@ -2031,8 +2052,22 @@
 	return 0;
 
 }
+
+size_t iommu_map_sg(struct iommu_domain *domain, unsigned long iova,
+		    struct scatterlist *sg, unsigned int nents, int prot)
+{
+	might_sleep();
+	return __iommu_map_sg(domain, iova, sg, nents, prot, GFP_KERNEL);
+}
 EXPORT_SYMBOL_GPL(iommu_map_sg);
 
+size_t iommu_map_sg_atomic(struct iommu_domain *domain, unsigned long iova,
+		    struct scatterlist *sg, unsigned int nents, int prot)
+{
+	return __iommu_map_sg(domain, iova, sg, nents, prot, GFP_ATOMIC);
+}
+EXPORT_SYMBOL_GPL(iommu_map_sg_atomic);
+
 int iommu_domain_window_enable(struct iommu_domain *domain, u32 wnd_nr,
 			       phys_addr_t paddr, u64 size, int prot)
 {
@@ -2221,13 +2256,13 @@
 		goto out;
 	}
 
-	iommu_group_create_direct_mappings(group, dev);
-
 	/* Make the domain the default for this group */
 	if (group->default_domain)
 		iommu_domain_free(group->default_domain);
 	group->default_domain = domain;
 
+	iommu_group_create_direct_mappings(group, dev);
+
 	dev_info(dev, "Using iommu %s mapping\n",
 		 type == IOMMU_DOMAIN_DMA ? "dma" : "direct");
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iommu/iova.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iommu/iova.c
@@ -64,8 +64,7 @@
 	if (!has_iova_flush_queue(iovad))
 		return;
 
-	if (timer_pending(&iovad->fq_timer))
-		del_timer(&iovad->fq_timer);
+	del_timer_sync(&iovad->fq_timer);
 
 	fq_destroy_all_entries(iovad);
 
@@ -139,10 +138,11 @@
 	cached_iova = rb_entry(iovad->cached32_node, struct iova, node);
 	if (free == cached_iova ||
 	    (free->pfn_hi < iovad->dma_32bit_pfn &&
-	     free->pfn_lo >= cached_iova->pfn_lo)) {
+	     free->pfn_lo >= cached_iova->pfn_lo))
 		iovad->cached32_node = rb_next(&free->node);
+
+	if (free->pfn_lo < iovad->dma_32bit_pfn)
 		iovad->max32_alloc_size = iovad->dma_32bit_pfn;
-	}
 
 	cached_iova = rb_entry(iovad->cached_node, struct iova, node);
 	if (free->pfn_lo >= cached_iova->pfn_lo)
@@ -233,7 +233,7 @@
 
 struct iova *alloc_iova_mem(void)
 {
-	return kmem_cache_alloc(iova_cache, GFP_ATOMIC);
+	return kmem_cache_zalloc(iova_cache, GFP_ATOMIC | __GFP_NOWARN);
 }
 EXPORT_SYMBOL(alloc_iova_mem);
 
@@ -811,7 +811,9 @@
 	for (i = 0 ; i < mag->size; ++i) {
 		struct iova *iova = private_find_iova(iovad, mag->pfns[i]);
 
-		BUG_ON(!iova);
+		if (WARN_ON(!iova))
+			continue;
+
 		private_free_iova(iovad, iova);
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iommu/ipmmu-vmsa.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iommu/ipmmu-vmsa.c
@@ -724,7 +724,7 @@
 }
 
 static int ipmmu_map(struct iommu_domain *io_domain, unsigned long iova,
-		     phys_addr_t paddr, size_t size, int prot)
+		     phys_addr_t paddr, size_t size, int prot, gfp_t gfp)
 {
 	struct ipmmu_vmsa_domain *domain = to_vmsa_domain(io_domain);
 
@@ -1061,7 +1061,9 @@
 	bitmap_zero(mmu->ctx, IPMMU_CTX_MAX);
 	mmu->features = of_device_get_match_data(&pdev->dev);
 	memset(mmu->utlb_ctx, IPMMU_CTX_INVALID, mmu->features->num_utlbs);
-	dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(40));
+	ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(40));
+	if (ret)
+		return ret;
 
 	/* Map I/O memory and request IRQ. */
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iommu/msm_iommu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iommu/msm_iommu.c
@@ -504,7 +504,7 @@
 }
 
 static int msm_iommu_map(struct iommu_domain *domain, unsigned long iova,
-			 phys_addr_t pa, size_t len, int prot)
+			 phys_addr_t pa, size_t len, int prot, gfp_t gfp)
 {
 	struct msm_priv *priv = to_msm_priv(domain);
 	unsigned long flags;
@@ -636,16 +636,19 @@
 static int qcom_iommu_of_xlate(struct device *dev,
 			       struct of_phandle_args *spec)
 {
-	struct msm_iommu_dev *iommu;
+	struct msm_iommu_dev *iommu = NULL, *iter;
 	unsigned long flags;
 	int ret = 0;
 
 	spin_lock_irqsave(&msm_iommu_lock, flags);
-	list_for_each_entry(iommu, &qcom_iommu_devices, dev_node)
-		if (iommu->dev->of_node == spec->np)
+	list_for_each_entry(iter, &qcom_iommu_devices, dev_node) {
+		if (iter->dev->of_node == spec->np) {
+			iommu = iter;
 			break;
+		}
+	}
 
-	if (!iommu || iommu->dev->of_node != spec->np) {
+	if (!iommu) {
 		ret = -ENODEV;
 		goto fail;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iommu/mtk_iommu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iommu/mtk_iommu.c
@@ -219,22 +219,37 @@
 static void mtk_iommu_tlb_flush_walk(unsigned long iova, size_t size,
 				     size_t granule, void *cookie)
 {
+	struct mtk_iommu_data *data = cookie;
+	unsigned long flags;
+
+	spin_lock_irqsave(&data->tlb_lock, flags);
 	mtk_iommu_tlb_add_flush_nosync(iova, size, granule, false, cookie);
 	mtk_iommu_tlb_sync(cookie);
+	spin_unlock_irqrestore(&data->tlb_lock, flags);
 }
 
 static void mtk_iommu_tlb_flush_leaf(unsigned long iova, size_t size,
 				     size_t granule, void *cookie)
 {
+	struct mtk_iommu_data *data = cookie;
+	unsigned long flags;
+
+	spin_lock_irqsave(&data->tlb_lock, flags);
 	mtk_iommu_tlb_add_flush_nosync(iova, size, granule, true, cookie);
 	mtk_iommu_tlb_sync(cookie);
+	spin_unlock_irqrestore(&data->tlb_lock, flags);
 }
 
 static void mtk_iommu_tlb_flush_page_nosync(struct iommu_iotlb_gather *gather,
 					    unsigned long iova, size_t granule,
 					    void *cookie)
 {
+	struct mtk_iommu_data *data = cookie;
+	unsigned long flags;
+
+	spin_lock_irqsave(&data->tlb_lock, flags);
 	mtk_iommu_tlb_add_flush_nosync(iova, granule, granule, true, cookie);
+	spin_unlock_irqrestore(&data->tlb_lock, flags);
 }
 
 static const struct iommu_flush_ops mtk_iommu_flush_ops = {
@@ -412,7 +427,7 @@
 }
 
 static int mtk_iommu_map(struct iommu_domain *domain, unsigned long iova,
-			 phys_addr_t paddr, size_t size, int prot)
+			 phys_addr_t paddr, size_t size, int prot, gfp_t gfp)
 {
 	struct mtk_iommu_domain *dom = to_mtk_domain(domain);
 	struct mtk_iommu_data *data = mtk_iommu_get_m4u_data();
@@ -447,13 +462,18 @@
 
 static void mtk_iommu_flush_iotlb_all(struct iommu_domain *domain)
 {
-	mtk_iommu_tlb_sync(mtk_iommu_get_m4u_data());
+	mtk_iommu_tlb_flush_all(mtk_iommu_get_m4u_data());
 }
 
 static void mtk_iommu_iotlb_sync(struct iommu_domain *domain,
 				 struct iommu_iotlb_gather *gather)
 {
-	mtk_iommu_tlb_sync(mtk_iommu_get_m4u_data());
+	struct mtk_iommu_data *data = mtk_iommu_get_m4u_data();
+	unsigned long flags;
+
+	spin_lock_irqsave(&data->tlb_lock, flags);
+	mtk_iommu_tlb_sync(data);
+	spin_unlock_irqrestore(&data->tlb_lock, flags);
 }
 
 static phys_addr_t mtk_iommu_iova_to_phys(struct iommu_domain *domain,
@@ -733,6 +753,7 @@
 	if (ret)
 		return ret;
 
+	spin_lock_init(&data->tlb_lock);
 	list_add_tail(&data->list, &m4ulist);
 
 	if (!iommu_present(&platform_bus_type))
@@ -748,8 +769,7 @@
 	iommu_device_sysfs_remove(&data->iommu);
 	iommu_device_unregister(&data->iommu);
 
-	if (iommu_present(&platform_bus_type))
-		bus_set_iommu(&platform_bus_type, NULL);
+	list_del(&data->list);
 
 	clk_disable_unprepare(data->bclk);
 	devm_free_irq(&pdev->dev, data->irq, data);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iommu/mtk_iommu.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/iommu/mtk_iommu.h
@@ -58,6 +58,7 @@
 	struct iommu_group		*m4u_group;
 	bool                            enable_4GB;
 	bool				tlb_flush_active;
+	spinlock_t			tlb_lock; /* lock for tlb range flush */
 
 	struct iommu_device		iommu;
 	const struct mtk_iommu_plat_data *plat_data;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iommu/mtk_iommu_v1.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iommu/mtk_iommu_v1.c
@@ -295,7 +295,7 @@
 }
 
 static int mtk_iommu_map(struct iommu_domain *domain, unsigned long iova,
-			 phys_addr_t paddr, size_t size, int prot)
+			 phys_addr_t paddr, size_t size, int prot, gfp_t gfp)
 {
 	struct mtk_iommu_domain *dom = to_mtk_domain(domain);
 	unsigned int page_num = size >> MT2701_IOMMU_PAGE_SHIFT;
@@ -626,18 +626,34 @@
 	ret = iommu_device_sysfs_add(&data->iommu, &pdev->dev, NULL,
 				     dev_name(&pdev->dev));
 	if (ret)
-		return ret;
+		goto out_clk_unprepare;
 
 	iommu_device_set_ops(&data->iommu, &mtk_iommu_ops);
 
 	ret = iommu_device_register(&data->iommu);
 	if (ret)
-		return ret;
+		goto out_sysfs_remove;
+
+	if (!iommu_present(&platform_bus_type)) {
+		ret = bus_set_iommu(&platform_bus_type,  &mtk_iommu_ops);
+		if (ret)
+			goto out_dev_unreg;
+	}
 
-	if (!iommu_present(&platform_bus_type))
-		bus_set_iommu(&platform_bus_type,  &mtk_iommu_ops);
+	ret = component_master_add_with_match(dev, &mtk_iommu_com_ops, match);
+	if (ret)
+		goto out_bus_set_null;
+	return ret;
 
-	return component_master_add_with_match(dev, &mtk_iommu_com_ops, match);
+out_bus_set_null:
+	bus_set_iommu(&platform_bus_type, NULL);
+out_dev_unreg:
+	iommu_device_unregister(&data->iommu);
+out_sysfs_remove:
+	iommu_device_sysfs_remove(&data->iommu);
+out_clk_unprepare:
+	clk_disable_unprepare(data->bclk);
+	return ret;
 }
 
 static int mtk_iommu_remove(struct platform_device *pdev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iommu/of_iommu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iommu/of_iommu.c
@@ -121,7 +121,7 @@
 	struct of_phandle_args iommu_spec = { .args_count = 1 };
 	int err;
 
-	err = of_map_rid(info->np, alias, "iommu-map", "iommu-map-mask",
+	err = of_map_id(info->np, alias, "iommu-map", "iommu-map-mask",
 			 &iommu_spec.np, iommu_spec.args);
 	if (err)
 		return err == -ENODEV ? NO_IOMMU : err;
@@ -137,7 +137,7 @@
 	struct of_phandle_args iommu_spec = { .args_count = 1 };
 	int err;
 
-	err = of_map_rid(master_np, mc_dev->icid, "iommu-map",
+	err = of_map_id(master_np, mc_dev->icid, "iommu-map",
 			 "iommu-map-mask", &iommu_spec.np,
 			 iommu_spec.args);
 	if (err)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iommu/omap-iommu-debug.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iommu/omap-iommu-debug.c
@@ -32,12 +32,12 @@
 		ssize_t bytes;						\
 		const char *str = "%20s: %08x\n";			\
 		const int maxcol = 32;					\
-		bytes = snprintf(p, maxcol, str, __stringify(name),	\
+		if (len < maxcol)					\
+			goto out;					\
+		bytes = scnprintf(p, maxcol, str, __stringify(name),	\
 				 iommu_read_reg(obj, MMU_##name));	\
 		p += bytes;						\
 		len -= bytes;						\
-		if (len < maxcol)					\
-			goto out;					\
 	} while (0)
 
 static ssize_t
@@ -98,8 +98,11 @@
 	mutex_lock(&iommu_debug_lock);
 
 	bytes = omap_iommu_dump_ctx(obj, p, count);
+	if (bytes < 0)
+		goto err;
 	bytes = simple_read_from_buffer(userbuf, count, ppos, buf, bytes);
 
+err:
 	mutex_unlock(&iommu_debug_lock);
 	kfree(buf);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iommu/omap-iommu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iommu/omap-iommu.c
@@ -1339,7 +1339,7 @@
 }
 
 static int omap_iommu_map(struct iommu_domain *domain, unsigned long da,
-			  phys_addr_t pa, size_t bytes, int prot)
+			  phys_addr_t pa, size_t bytes, int prot, gfp_t gfp)
 {
 	struct omap_iommu_domain *omap_domain = to_omap_domain(domain);
 	struct device *dev = omap_domain->dev;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iommu/qcom_iommu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iommu/qcom_iommu.c
@@ -345,21 +345,19 @@
 {
 	struct qcom_iommu_domain *qcom_domain = to_qcom_iommu_domain(domain);
 
-	if (WARN_ON(qcom_domain->iommu))    /* forgot to detach? */
-		return;
-
 	iommu_put_dma_cookie(domain);
 
-	/* NOTE: unmap can be called after client device is powered off,
-	 * for example, with GPUs or anything involving dma-buf.  So we
-	 * cannot rely on the device_link.  Make sure the IOMMU is on to
-	 * avoid unclocked accesses in the TLB inv path:
-	 */
-	pm_runtime_get_sync(qcom_domain->iommu->dev);
-
-	free_io_pgtable_ops(qcom_domain->pgtbl_ops);
-
-	pm_runtime_put_sync(qcom_domain->iommu->dev);
+	if (qcom_domain->iommu) {
+		/*
+		 * NOTE: unmap can be called after client device is powered
+		 * off, for example, with GPUs or anything involving dma-buf.
+		 * So we cannot rely on the device_link.  Make sure the IOMMU
+		 * is on to avoid unclocked accesses in the TLB inv path:
+		 */
+		pm_runtime_get_sync(qcom_domain->iommu->dev);
+		free_io_pgtable_ops(qcom_domain->pgtbl_ops);
+		pm_runtime_put_sync(qcom_domain->iommu->dev);
+	}
 
 	kfree(qcom_domain);
 }
@@ -405,7 +403,7 @@
 	struct qcom_iommu_domain *qcom_domain = to_qcom_iommu_domain(domain);
 	unsigned i;
 
-	if (!qcom_domain->iommu)
+	if (WARN_ON(!qcom_domain->iommu))
 		return;
 
 	pm_runtime_get_sync(qcom_iommu->dev);
@@ -418,12 +416,10 @@
 		ctx->domain = NULL;
 	}
 	pm_runtime_put_sync(qcom_iommu->dev);
-
-	qcom_domain->iommu = NULL;
 }
 
 static int qcom_iommu_map(struct iommu_domain *domain, unsigned long iova,
-			  phys_addr_t paddr, size_t size, int prot)
+			  phys_addr_t paddr, size_t size, int prot, gfp_t gfp)
 {
 	int ret;
 	unsigned long flags;
@@ -789,9 +785,12 @@
 {
 	struct device_node *child;
 
-	for_each_child_of_node(qcom_iommu->dev->of_node, child)
-		if (of_device_is_compatible(child, "qcom,msm-iommu-v1-sec"))
+	for_each_child_of_node(qcom_iommu->dev->of_node, child) {
+		if (of_device_is_compatible(child, "qcom,msm-iommu-v1-sec")) {
+			of_node_put(child);
 			return true;
+		}
+	}
 
 	return false;
 }
@@ -818,8 +817,11 @@
 	qcom_iommu->dev = dev;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (res)
+	if (res) {
 		qcom_iommu->local_base = devm_ioremap_resource(dev, res);
+		if (IS_ERR(qcom_iommu->local_base))
+			return PTR_ERR(qcom_iommu->local_base);
+	}
 
 	qcom_iommu->iface_clk = devm_clk_get(dev, "iface");
 	if (IS_ERR(qcom_iommu->iface_clk)) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iommu/rockchip-iommu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iommu/rockchip-iommu.c
@@ -758,7 +758,7 @@
 }
 
 static int rk_iommu_map(struct iommu_domain *domain, unsigned long _iova,
-			phys_addr_t paddr, size_t size, int prot)
+			phys_addr_t paddr, size_t size, int prot, gfp_t gfp)
 {
 	struct rk_iommu_domain *rk_domain = to_rk_domain(domain);
 	unsigned long flags;
@@ -980,13 +980,13 @@
 	if (!dma_dev)
 		return NULL;
 
-	rk_domain = devm_kzalloc(dma_dev, sizeof(*rk_domain), GFP_KERNEL);
+	rk_domain = kzalloc(sizeof(*rk_domain), GFP_KERNEL);
 	if (!rk_domain)
 		return NULL;
 
 	if (type == IOMMU_DOMAIN_DMA &&
 	    iommu_get_dma_cookie(&rk_domain->domain))
-		return NULL;
+		goto err_free_domain;
 
 	/*
 	 * rk32xx iommus use a 2 level pagetable.
@@ -1021,6 +1021,8 @@
 err_put_cookie:
 	if (type == IOMMU_DOMAIN_DMA)
 		iommu_put_dma_cookie(&rk_domain->domain);
+err_free_domain:
+	kfree(rk_domain);
 
 	return NULL;
 }
@@ -1049,6 +1051,7 @@
 
 	if (domain->type == IOMMU_DOMAIN_DMA)
 		iommu_put_dma_cookie(&rk_domain->domain);
+	kfree(rk_domain);
 }
 
 static int rk_iommu_add_device(struct device *dev)
@@ -1227,18 +1230,20 @@
 	for (i = 0; i < iommu->num_irq; i++) {
 		int irq = platform_get_irq(pdev, i);
 
-		if (irq < 0)
-			return irq;
+		if (irq < 0) {
+			err = irq;
+			goto err_pm_disable;
+		}
 
 		err = devm_request_irq(iommu->dev, irq, rk_iommu_irq,
 				       IRQF_SHARED, dev_name(dev), iommu);
-		if (err) {
-			pm_runtime_disable(dev);
-			goto err_remove_sysfs;
-		}
+		if (err)
+			goto err_pm_disable;
 	}
 
 	return 0;
+err_pm_disable:
+	pm_runtime_disable(dev);
 err_remove_sysfs:
 	iommu_device_sysfs_remove(&iommu->iommu);
 err_put_group:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iommu/s390-iommu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iommu/s390-iommu.c
@@ -87,7 +87,7 @@
 				    struct device *dev)
 {
 	struct s390_domain *s390_domain = to_s390_domain(domain);
-	struct zpci_dev *zdev = to_pci_dev(dev)->sysdata;
+	struct zpci_dev *zdev = to_zpci_dev(dev);
 	struct s390_domain_device *domain_device;
 	unsigned long flags;
 	int rc;
@@ -139,7 +139,7 @@
 				     struct device *dev)
 {
 	struct s390_domain *s390_domain = to_s390_domain(domain);
-	struct zpci_dev *zdev = to_pci_dev(dev)->sysdata;
+	struct zpci_dev *zdev = to_zpci_dev(dev);
 	struct s390_domain_device *domain_device, *tmp;
 	unsigned long flags;
 	int found = 0;
@@ -169,7 +169,7 @@
 static int s390_iommu_add_device(struct device *dev)
 {
 	struct iommu_group *group = iommu_group_get_for_dev(dev);
-	struct zpci_dev *zdev = to_pci_dev(dev)->sysdata;
+	struct zpci_dev *zdev = to_zpci_dev(dev);
 
 	if (IS_ERR(group))
 		return PTR_ERR(group);
@@ -182,7 +182,7 @@
 
 static void s390_iommu_remove_device(struct device *dev)
 {
-	struct zpci_dev *zdev = to_pci_dev(dev)->sysdata;
+	struct zpci_dev *zdev = to_zpci_dev(dev);
 	struct iommu_domain *domain;
 
 	/*
@@ -265,7 +265,7 @@
 }
 
 static int s390_iommu_map(struct iommu_domain *domain, unsigned long iova,
-			  phys_addr_t paddr, size_t size, int prot)
+			  phys_addr_t paddr, size_t size, int prot, gfp_t gfp)
 {
 	struct s390_domain *s390_domain = to_s390_domain(domain);
 	int flags = ZPCI_PTE_VALID, rc = 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iommu/tegra-gart.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iommu/tegra-gart.c
@@ -178,7 +178,7 @@
 }
 
 static int gart_iommu_map(struct iommu_domain *domain, unsigned long iova,
-			  phys_addr_t pa, size_t bytes, int prot)
+			  phys_addr_t pa, size_t bytes, int prot, gfp_t gfp)
 {
 	struct gart_device *gart = gart_handle;
 	int ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iommu/tegra-smmu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iommu/tegra-smmu.c
@@ -159,9 +159,9 @@
 	return (addr & smmu->pfn_mask) == addr;
 }
 
-static dma_addr_t smmu_pde_to_dma(u32 pde)
+static dma_addr_t smmu_pde_to_dma(struct tegra_smmu *smmu, u32 pde)
 {
-	return pde << 12;
+	return (dma_addr_t)(pde & smmu->pfn_mask) << 12;
 }
 
 static void smmu_flush_ptc_all(struct tegra_smmu *smmu)
@@ -549,6 +549,7 @@
 				  dma_addr_t *dmap)
 {
 	unsigned int pd_index = iova_pd_index(iova);
+	struct tegra_smmu *smmu = as->smmu;
 	struct page *pt_page;
 	u32 *pd;
 
@@ -557,7 +558,7 @@
 		return NULL;
 
 	pd = page_address(as->pd);
-	*dmap = smmu_pde_to_dma(pd[pd_index]);
+	*dmap = smmu_pde_to_dma(smmu, pd[pd_index]);
 
 	return tegra_smmu_pte_offset(pt_page, iova);
 }
@@ -599,7 +600,7 @@
 	} else {
 		u32 *pd = page_address(as->pd);
 
-		*dmap = smmu_pde_to_dma(pd[pde]);
+		*dmap = smmu_pde_to_dma(smmu, pd[pde]);
 	}
 
 	return tegra_smmu_pte_offset(as->pts[pde], iova);
@@ -624,7 +625,7 @@
 	if (--as->count[pde] == 0) {
 		struct tegra_smmu *smmu = as->smmu;
 		u32 *pd = page_address(as->pd);
-		dma_addr_t pte_dma = smmu_pde_to_dma(pd[pde]);
+		dma_addr_t pte_dma = smmu_pde_to_dma(smmu, pd[pde]);
 
 		tegra_smmu_set_pde(as, iova, 0);
 
@@ -650,7 +651,7 @@
 }
 
 static int tegra_smmu_map(struct iommu_domain *domain, unsigned long iova,
-			  phys_addr_t paddr, size_t size, int prot)
+			  phys_addr_t paddr, size_t size, int prot, gfp_t gfp)
 {
 	struct tegra_smmu_as *as = to_smmu_as(domain);
 	dma_addr_t pte_dma;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/iommu/virtio-iommu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/iommu/virtio-iommu.c
@@ -454,7 +454,7 @@
 	if (!region)
 		return -ENOMEM;
 
-	list_add(&vdev->resv_regions, &region->list);
+	list_add(&region->list, &vdev->resv_regions);
 	return 0;
 }
 
@@ -614,18 +614,20 @@
 	int ret;
 	struct viommu_domain *vdomain = to_viommu_domain(domain);
 
-	vdomain->viommu		= viommu;
-	vdomain->map_flags	= viommu->map_flags;
+	ret = ida_alloc_range(&viommu->domain_ids, viommu->first_domain,
+			      viommu->last_domain, GFP_KERNEL);
+	if (ret < 0)
+		return ret;
+
+	vdomain->id		= (unsigned int)ret;
 
 	domain->pgsize_bitmap	= viommu->pgsize_bitmap;
 	domain->geometry	= viommu->geometry;
 
-	ret = ida_alloc_range(&viommu->domain_ids, viommu->first_domain,
-			      viommu->last_domain, GFP_KERNEL);
-	if (ret >= 0)
-		vdomain->id = (unsigned int)ret;
+	vdomain->map_flags	= viommu->map_flags;
+	vdomain->viommu		= viommu;
 
-	return ret > 0 ? 0 : ret;
+	return 0;
 }
 
 static void viommu_domain_free(struct iommu_domain *domain)
@@ -713,7 +715,7 @@
 }
 
 static int viommu_map(struct iommu_domain *domain, unsigned long iova,
-		      phys_addr_t paddr, size_t size, int prot)
+		      phys_addr_t paddr, size_t size, int prot, gfp_t gfp)
 {
 	int ret;
 	u32 flags;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ipack/carriers/tpci200.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ipack/carriers/tpci200.c
@@ -91,16 +91,13 @@
 	free_irq(tpci200->info->pdev->irq, (void *) tpci200);
 
 	pci_iounmap(tpci200->info->pdev, tpci200->info->interface_regs);
-	pci_iounmap(tpci200->info->pdev, tpci200->info->cfg_regs);
 
 	pci_release_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR);
 	pci_release_region(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR);
 	pci_release_region(tpci200->info->pdev, TPCI200_MEM16_SPACE_BAR);
 	pci_release_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR);
-	pci_release_region(tpci200->info->pdev, TPCI200_CFG_MEM_BAR);
 
 	pci_disable_device(tpci200->info->pdev);
-	pci_dev_put(tpci200->info->pdev);
 }
 
 static void tpci200_enable_irq(struct tpci200_board *tpci200,
@@ -259,7 +256,7 @@
 			"(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 2 !",
 			tpci200->info->pdev->bus->number,
 			tpci200->info->pdev->devfn);
-		goto out_disable_pci;
+		goto err_disable_device;
 	}
 
 	/* Request IO ID INT space (Bar 3) */
@@ -271,7 +268,7 @@
 			"(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 3 !",
 			tpci200->info->pdev->bus->number,
 			tpci200->info->pdev->devfn);
-		goto out_release_ip_space;
+		goto err_ip_interface_bar;
 	}
 
 	/* Request MEM8 space (Bar 5) */
@@ -282,7 +279,7 @@
 			"(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 5!",
 			tpci200->info->pdev->bus->number,
 			tpci200->info->pdev->devfn);
-		goto out_release_ioid_int_space;
+		goto err_io_id_int_spaces_bar;
 	}
 
 	/* Request MEM16 space (Bar 4) */
@@ -293,7 +290,7 @@
 			"(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 4!",
 			tpci200->info->pdev->bus->number,
 			tpci200->info->pdev->devfn);
-		goto out_release_mem8_space;
+		goto err_mem8_space_bar;
 	}
 
 	/* Map internal tpci200 driver user space */
@@ -306,7 +303,8 @@
 			"(bn 0x%X, sn 0x%X) failed to map driver user space!",
 			tpci200->info->pdev->bus->number,
 			tpci200->info->pdev->devfn);
-		goto out_release_mem8_space;
+		res = -ENOMEM;
+		goto err_mem16_space_bar;
 	}
 
 	/* Initialize lock that protects interface_regs */
@@ -345,18 +343,22 @@
 			"(bn 0x%X, sn 0x%X) unable to register IRQ !",
 			tpci200->info->pdev->bus->number,
 			tpci200->info->pdev->devfn);
-		goto out_release_ioid_int_space;
+		goto err_interface_regs;
 	}
 
 	return 0;
 
-out_release_mem8_space:
+err_interface_regs:
+	pci_iounmap(tpci200->info->pdev, tpci200->info->interface_regs);
+err_mem16_space_bar:
+	pci_release_region(tpci200->info->pdev, TPCI200_MEM16_SPACE_BAR);
+err_mem8_space_bar:
 	pci_release_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR);
-out_release_ioid_int_space:
+err_io_id_int_spaces_bar:
 	pci_release_region(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR);
-out_release_ip_space:
+err_ip_interface_bar:
 	pci_release_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR);
-out_disable_pci:
+err_disable_device:
 	pci_disable_device(tpci200->info->pdev);
 	return res;
 }
@@ -528,7 +530,7 @@
 	tpci200->info = kzalloc(sizeof(struct tpci200_infos), GFP_KERNEL);
 	if (!tpci200->info) {
 		ret = -ENOMEM;
-		goto out_err_info;
+		goto err_tpci200;
 	}
 
 	pci_dev_get(pdev);
@@ -539,7 +541,7 @@
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to allocate PCI Configuration Memory");
 		ret = -EBUSY;
-		goto out_err_pci_request;
+		goto err_tpci200_info;
 	}
 	tpci200->info->cfg_regs = ioremap_nocache(
 			pci_resource_start(pdev, TPCI200_CFG_MEM_BAR),
@@ -547,7 +549,7 @@
 	if (!tpci200->info->cfg_regs) {
 		dev_err(&pdev->dev, "Failed to map PCI Configuration Memory");
 		ret = -EFAULT;
-		goto out_err_ioremap;
+		goto err_request_region;
 	}
 
 	/* Disable byte swapping for 16 bit IP module access. This will ensure
@@ -570,7 +572,7 @@
 	if (ret) {
 		dev_err(&pdev->dev, "error during tpci200 install\n");
 		ret = -ENODEV;
-		goto out_err_install;
+		goto err_cfg_regs;
 	}
 
 	/* Register the carrier in the industry pack bus driver */
@@ -582,7 +584,7 @@
 		dev_err(&pdev->dev,
 			"error registering the carrier on ipack driver\n");
 		ret = -EFAULT;
-		goto out_err_bus_register;
+		goto err_tpci200_install;
 	}
 
 	/* save the bus number given by ipack to logging purpose */
@@ -593,16 +595,16 @@
 		tpci200_create_device(tpci200, i);
 	return 0;
 
-out_err_bus_register:
+err_tpci200_install:
 	tpci200_uninstall(tpci200);
-out_err_install:
-	iounmap(tpci200->info->cfg_regs);
-out_err_ioremap:
+err_cfg_regs:
+	pci_iounmap(tpci200->info->pdev, tpci200->info->cfg_regs);
+err_request_region:
 	pci_release_region(pdev, TPCI200_CFG_MEM_BAR);
-out_err_pci_request:
-	pci_dev_put(pdev);
+err_tpci200_info:
 	kfree(tpci200->info);
-out_err_info:
+	pci_dev_put(pdev);
+err_tpci200:
 	kfree(tpci200);
 	return ret;
 }
@@ -612,6 +614,12 @@
 	ipack_bus_unregister(tpci200->info->ipack_bus);
 	tpci200_uninstall(tpci200);
 
+	pci_iounmap(tpci200->info->pdev, tpci200->info->cfg_regs);
+
+	pci_release_region(tpci200->info->pdev, TPCI200_CFG_MEM_BAR);
+
+	pci_dev_put(tpci200->info->pdev);
+
 	kfree(tpci200->info);
 	kfree(tpci200);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ipack/devices/ipoctal.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ipack/devices/ipoctal.c
@@ -35,6 +35,7 @@
 	unsigned int			pointer_read;
 	unsigned int			pointer_write;
 	struct tty_port			tty_port;
+	bool				tty_registered;
 	union scc2698_channel __iomem	*regs;
 	union scc2698_block __iomem	*block_regs;
 	unsigned int			board_id;
@@ -83,22 +84,34 @@
 	return 0;
 }
 
-static int ipoctal_open(struct tty_struct *tty, struct file *file)
+static int ipoctal_install(struct tty_driver *driver, struct tty_struct *tty)
 {
 	struct ipoctal_channel *channel = dev_get_drvdata(tty->dev);
 	struct ipoctal *ipoctal = chan_to_ipoctal(channel, tty->index);
-	int err;
-
-	tty->driver_data = channel;
+	int res;
 
 	if (!ipack_get_carrier(ipoctal->dev))
 		return -EBUSY;
 
-	err = tty_port_open(&channel->tty_port, tty, file);
-	if (err)
-		ipack_put_carrier(ipoctal->dev);
+	res = tty_standard_install(driver, tty);
+	if (res)
+		goto err_put_carrier;
+
+	tty->driver_data = channel;
+
+	return 0;
+
+err_put_carrier:
+	ipack_put_carrier(ipoctal->dev);
+
+	return res;
+}
+
+static int ipoctal_open(struct tty_struct *tty, struct file *file)
+{
+	struct ipoctal_channel *channel = tty->driver_data;
 
-	return err;
+	return tty_port_open(&channel->tty_port, tty, file);
 }
 
 static void ipoctal_reset_stats(struct ipoctal_stats *stats)
@@ -266,7 +279,6 @@
 	int res;
 	int i;
 	struct tty_driver *tty;
-	char name[20];
 	struct ipoctal_channel *channel;
 	struct ipack_region *region;
 	void __iomem *addr;
@@ -357,8 +369,11 @@
 	/* Fill struct tty_driver with ipoctal data */
 	tty->owner = THIS_MODULE;
 	tty->driver_name = KBUILD_MODNAME;
-	sprintf(name, KBUILD_MODNAME ".%d.%d.", bus_nr, slot);
-	tty->name = name;
+	tty->name = kasprintf(GFP_KERNEL, KBUILD_MODNAME ".%d.%d.", bus_nr, slot);
+	if (!tty->name) {
+		res = -ENOMEM;
+		goto err_put_driver;
+	}
 	tty->major = 0;
 
 	tty->minor_start = 0;
@@ -374,8 +389,7 @@
 	res = tty_register_driver(tty);
 	if (res) {
 		dev_err(&ipoctal->dev->dev, "Can't register tty driver.\n");
-		put_tty_driver(tty);
-		return res;
+		goto err_free_name;
 	}
 
 	/* Save struct tty_driver for use it when uninstalling the device */
@@ -386,7 +400,9 @@
 
 		channel = &ipoctal->channel[i];
 		tty_port_init(&channel->tty_port);
-		tty_port_alloc_xmit_buf(&channel->tty_port);
+		res = tty_port_alloc_xmit_buf(&channel->tty_port);
+		if (res)
+			continue;
 		channel->tty_port.ops = &ipoctal_tty_port_ops;
 
 		ipoctal_reset_stats(&channel->stats);
@@ -394,13 +410,15 @@
 		spin_lock_init(&channel->lock);
 		channel->pointer_read = 0;
 		channel->pointer_write = 0;
-		tty_dev = tty_port_register_device(&channel->tty_port, tty, i, NULL);
+		tty_dev = tty_port_register_device_attr(&channel->tty_port, tty,
+							i, NULL, channel, NULL);
 		if (IS_ERR(tty_dev)) {
 			dev_err(&ipoctal->dev->dev, "Failed to register tty device.\n");
+			tty_port_free_xmit_buf(&channel->tty_port);
 			tty_port_destroy(&channel->tty_port);
 			continue;
 		}
-		dev_set_drvdata(tty_dev, channel);
+		channel->tty_registered = true;
 	}
 
 	/*
@@ -412,6 +430,13 @@
 				       ipoctal_irq_handler, ipoctal);
 
 	return 0;
+
+err_free_name:
+	kfree(tty->name);
+err_put_driver:
+	put_tty_driver(tty);
+
+	return res;
 }
 
 static inline int ipoctal_copy_write_buffer(struct ipoctal_channel *channel,
@@ -652,6 +677,7 @@
 
 static const struct tty_operations ipoctal_fops = {
 	.ioctl =		NULL,
+	.install =		ipoctal_install,
 	.open =			ipoctal_open,
 	.close =		ipoctal_close,
 	.write =		ipoctal_write_tty,
@@ -694,12 +720,17 @@
 
 	for (i = 0; i < NR_CHANNELS; i++) {
 		struct ipoctal_channel *channel = &ipoctal->channel[i];
+
+		if (!channel->tty_registered)
+			continue;
+
 		tty_unregister_device(ipoctal->tty_drv, i);
 		tty_port_free_xmit_buf(&channel->tty_port);
 		tty_port_destroy(&channel->tty_port);
 	}
 
 	tty_unregister_driver(ipoctal->tty_drv);
+	kfree(ipoctal->tty_drv->name);
 	put_tty_driver(ipoctal->tty_drv);
 	kfree(ipoctal);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/Kconfig
@@ -286,8 +286,12 @@
 	select GENERIC_IRQ_EFFECTIVE_AFF_MASK
 
 config XILINX_INTC
-	bool
+	bool "Xilinx Interrupt Controller (IP core)"
 	select IRQ_DOMAIN
+	help
+	  Support for the Xilinx Interrupt Controller which can be used
+	  with MicroBlaze and Zynq. It is a secondary chained controller when
+	  used with Zynq.
 
 config IRQ_CROSSBAR
 	bool
@@ -415,6 +419,7 @@
 config GOLDFISH_PIC
        bool "Goldfish programmable interrupt controller"
        depends on MIPS && (GOLDFISH || COMPILE_TEST)
+       select GENERIC_IRQ_CHIP
        select IRQ_DOMAIN
        help
          Say yes here to enable Goldfish interrupt controller driver used
@@ -483,8 +488,6 @@
 	  If you wish to use interrupt aggregator irq resources managed by the
 	  TI System Controller, say Y here. Otherwise, say N.
 
-endmenu
-
 config SIFIVE_PLIC
 	bool "SiFive Platform-Level Interrupt Controller"
 	depends on RISCV
@@ -496,3 +499,5 @@
 	   interrupt sources are subordinate to the PLIC.
 
 	   If you don't know what to do here, say Y.
+
+endmenu
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-alpine-msi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-alpine-msi.c
@@ -165,8 +165,7 @@
 	return 0;
 
 err_sgi:
-	while (--i >= 0)
-		irq_domain_free_irqs_parent(domain, virq, i);
+	irq_domain_free_irqs_parent(domain, virq, i);
 	alpine_msix_free_sgi(priv, sgi, nr_irqs);
 	return err;
 }
@@ -200,6 +199,7 @@
 	}
 
 	gic_domain = irq_find_host(gic_node);
+	of_node_put(gic_node);
 	if (!gic_domain) {
 		pr_err("Failed to find the GIC domain\n");
 		return -ENXIO;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-armada-370-xp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-armada-370-xp.c
@@ -232,16 +232,12 @@
 	int hwirq, i;
 
 	mutex_lock(&msi_used_lock);
+	hwirq = bitmap_find_free_region(msi_used, PCI_MSI_DOORBELL_NR,
+					order_base_2(nr_irqs));
+	mutex_unlock(&msi_used_lock);
 
-	hwirq = bitmap_find_next_zero_area(msi_used, PCI_MSI_DOORBELL_NR,
-					   0, nr_irqs, 0);
-	if (hwirq >= PCI_MSI_DOORBELL_NR) {
-		mutex_unlock(&msi_used_lock);
+	if (hwirq < 0)
 		return -ENOSPC;
-	}
-
-	bitmap_set(msi_used, hwirq, nr_irqs);
-	mutex_unlock(&msi_used_lock);
 
 	for (i = 0; i < nr_irqs; i++) {
 		irq_domain_set_info(domain, virq + i, hwirq + i,
@@ -250,7 +246,7 @@
 				    NULL, NULL);
 	}
 
-	return hwirq;
+	return 0;
 }
 
 static void armada_370_xp_msi_free(struct irq_domain *domain,
@@ -259,7 +255,7 @@
 	struct irq_data *d = irq_domain_get_irq_data(domain, virq);
 
 	mutex_lock(&msi_used_lock);
-	bitmap_clear(msi_used, d->hwirq, nr_irqs);
+	bitmap_release_region(msi_used, d->hwirq, order_base_2(nr_irqs));
 	mutex_unlock(&msi_used_lock);
 }
 
@@ -350,6 +346,10 @@
 static int armada_370_xp_mpic_irq_map(struct irq_domain *h,
 				      unsigned int virq, irq_hw_number_t hw)
 {
+	/* IRQs 0 and 1 cannot be mapped, they are handled internally */
+	if (hw <= 1)
+		return -EINVAL;
+
 	armada_370_xp_irq_mask(irq_get_irq_data(virq));
 	if (!is_percpu_irq(hw))
 		writel(hw, per_cpu_int_base +
@@ -396,7 +396,16 @@
 
 static void armada_xp_mpic_perf_init(void)
 {
-	unsigned long cpuid = cpu_logical_map(smp_processor_id());
+	unsigned long cpuid;
+
+	/*
+	 * This Performance Counter Overflow interrupt is specific for
+	 * Armada 370 and XP. It is not available on Armada 375, 38x and 39x.
+	 */
+	if (!of_machine_is_compatible("marvell,armada-370-xp"))
+		return;
+
+	cpuid = cpu_logical_map(smp_processor_id());
 
 	/* Enable Performance Counter Overflow interrupts */
 	writel(ARMADA_370_XP_INT_CAUSE_PERF(cpuid),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-aspeed-i2c-ic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-aspeed-i2c-ic.c
@@ -79,8 +79,8 @@
 	}
 
 	i2c_ic->parent_irq = irq_of_parse_and_map(node, 0);
-	if (i2c_ic->parent_irq < 0) {
-		ret = i2c_ic->parent_irq;
+	if (!i2c_ic->parent_irq) {
+		ret = -EINVAL;
 		goto err_iounmap;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-bcm6345-l1.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-bcm6345-l1.c
@@ -82,6 +82,7 @@
 };
 
 struct bcm6345_l1_cpu {
+	struct bcm6345_l1_chip	*intc;
 	void __iomem		*map_base;
 	unsigned int		parent_irq;
 	u32			enable_cache[];
@@ -115,17 +116,11 @@
 
 static void bcm6345_l1_irq_handle(struct irq_desc *desc)
 {
-	struct bcm6345_l1_chip *intc = irq_desc_get_handler_data(desc);
-	struct bcm6345_l1_cpu *cpu;
+	struct bcm6345_l1_cpu *cpu = irq_desc_get_handler_data(desc);
+	struct bcm6345_l1_chip *intc = cpu->intc;
 	struct irq_chip *chip = irq_desc_get_chip(desc);
 	unsigned int idx;
 
-#ifdef CONFIG_SMP
-	cpu = intc->cpus[cpu_logical_map(smp_processor_id())];
-#else
-	cpu = intc->cpus[0];
-#endif
-
 	chained_irq_enter(chip, desc);
 
 	for (idx = 0; idx < intc->n_words; idx++) {
@@ -140,7 +135,7 @@
 		for_each_set_bit(hwirq, &pending, IRQS_PER_WORD) {
 			irq = irq_linear_revmap(intc->domain, base + hwirq);
 			if (irq)
-				do_IRQ(irq);
+				generic_handle_irq(irq);
 			else
 				spurious_interrupt();
 		}
@@ -257,6 +252,7 @@
 	if (!cpu)
 		return -ENOMEM;
 
+	cpu->intc = intc;
 	cpu->map_base = ioremap(res.start, sz);
 	if (!cpu->map_base)
 		return -ENOMEM;
@@ -272,7 +268,7 @@
 		return -EINVAL;
 	}
 	irq_set_chained_handler_and_data(cpu->parent_irq,
-						bcm6345_l1_irq_handle, intc);
+						bcm6345_l1_irq_handle, cpu);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-bcm7038-l1.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-bcm7038-l1.c
@@ -281,6 +281,10 @@
 		pr_err("failed to map parent interrupt %d\n", parent_irq);
 		return -EINVAL;
 	}
+
+	if (of_property_read_bool(dn, "brcm,irq-can-wake"))
+		enable_irq_wake(parent_irq);
+
 	irq_set_chained_handler_and_data(parent_irq, bcm7038_l1_irq_handle,
 					 intc);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-bcm7120-l2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-bcm7120-l2.c
@@ -268,7 +268,8 @@
 		flags |= IRQ_GC_BE_IO;
 
 	ret = irq_alloc_domain_generic_chips(data->domain, IRQS_PER_WORD, 1,
-				dn->full_name, handle_level_irq, clr, 0, flags);
+				dn->full_name, handle_level_irq, clr,
+				IRQ_LEVEL, flags);
 	if (ret) {
 		pr_err("failed to allocate generic irq chip\n");
 		goto out_free_domain;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-brcmstb-l2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-brcmstb-l2.c
@@ -2,7 +2,7 @@
 /*
  * Generic Broadcom Set Top Box Level 2 Interrupt controller driver
  *
- * Copyright (C) 2014-2017 Broadcom
+ * Copyright (C) 2014-2024 Broadcom
  */
 
 #define pr_fmt(fmt)	KBUILD_MODNAME	": " fmt
@@ -113,6 +113,9 @@
 		generic_handle_irq(irq_linear_revmap(b->domain, irq));
 	} while (status);
 out:
+	/* Don't ack parent before all device writes are done */
+	wmb();
+
 	chained_irq_exit(chip, desc);
 }
 
@@ -161,6 +164,7 @@
 					  *init_params)
 {
 	unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
+	unsigned int set = 0;
 	struct brcmstb_l2_intc_data *data;
 	struct irq_chip_type *ct;
 	int ret;
@@ -208,9 +212,12 @@
 	if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
 		flags |= IRQ_GC_BE_IO;
 
+	if (init_params->handler == handle_level_irq)
+		set |= IRQ_LEVEL;
+
 	/* Allocate a single Generic IRQ chip for this node */
 	ret = irq_alloc_domain_generic_chips(data->domain, 32, 1,
-			np->full_name, init_params->handler, clr, 0, flags);
+			np->full_name, init_params->handler, clr, set, flags);
 	if (ret) {
 		pr_err("failed to allocate generic irq chip\n");
 		goto out_free_domain;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-gic-pm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-gic-pm.c
@@ -104,7 +104,7 @@
 
 	pm_runtime_enable(dev);
 
-	ret = pm_runtime_get_sync(dev);
+	ret = pm_runtime_resume_and_get(dev);
 	if (ret < 0)
 		goto rpm_disable;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-gic-realview.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-gic-realview.c
@@ -57,6 +57,7 @@
 
 	/* The PB11MPCore GIC needs to be configured in the syscon */
 	map = syscon_node_to_regmap(np);
+	of_node_put(np);
 	if (!IS_ERR(map)) {
 		/* new irq mode with no DCC */
 		regmap_write(map, REALVIEW_SYS_LOCK_OFFSET,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-gic-v2m.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-gic-v2m.c
@@ -441,12 +441,12 @@
 
 		ret = gicv2m_init_one(&child->fwnode, spi_start, nr_spis,
 				      &res, 0);
-		if (ret) {
-			of_node_put(child);
+		if (ret)
 			break;
-		}
 	}
 
+	if (ret && child)
+		of_node_put(child);
 	if (!ret)
 		ret = gicv2m_allocate_domains(parent);
 	if (ret)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-gic-v3-its.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-gic-v3-its.c
@@ -40,7 +40,6 @@
 #define ITS_FLAGS_CMDQ_NEEDS_FLUSHING		(1ULL << 0)
 #define ITS_FLAGS_WORKAROUND_CAVIUM_22375	(1ULL << 1)
 #define ITS_FLAGS_WORKAROUND_CAVIUM_23144	(1ULL << 2)
-#define ITS_FLAGS_SAVE_SUSPEND_STATE		(1ULL << 3)
 
 #define RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING	(1 << 0)
 #define RDIST_FLAGS_RD_TABLES_PREALLOCATED	(1 << 1)
@@ -571,11 +570,11 @@
 						   struct its_cmd_desc *desc)
 {
 	its_encode_cmd(cmd, GITS_CMD_INVALL);
-	its_encode_collection(cmd, desc->its_mapc_cmd.col->col_id);
+	its_encode_collection(cmd, desc->its_invall_cmd.col->col_id);
 
 	its_fixup_cmd(cmd);
 
-	return NULL;
+	return desc->its_invall_cmd.col;
 }
 
 static struct its_vpe *its_build_vinvall_cmd(struct its_node *its,
@@ -2581,6 +2580,7 @@
 	msi_alloc_info_t *info = args;
 	struct its_device *its_dev = info->scratchpad[0].ptr;
 	struct its_node *its = its_dev->its;
+	struct irq_data *irqd;
 	irq_hw_number_t hwirq;
 	int err;
 	int i;
@@ -2600,7 +2600,9 @@
 
 		irq_domain_set_hwirq_and_chip(domain, virq + i,
 					      hwirq + i, &its_irq_chip, its_dev);
-		irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(virq + i)));
+		irqd = irq_get_irq_data(virq + i);
+		irqd_set_single_target(irqd);
+		irqd_set_affinity_on_activate(irqd);
 		pr_debug("ID:%d pID:%d vID:%d\n",
 			 (int)(hwirq + i - its_dev->event_map.lpi_base),
 			 (int)(hwirq + i), virq + i);
@@ -2985,12 +2987,18 @@
 	return 0;
 }
 
+static int its_vpe_retrigger(struct irq_data *d)
+{
+	return !its_vpe_set_irqchip_state(d, IRQCHIP_STATE_PENDING, true);
+}
+
 static struct irq_chip its_vpe_irq_chip = {
 	.name			= "GICv4-vpe",
 	.irq_mask		= its_vpe_mask_irq,
 	.irq_unmask		= its_vpe_unmask_irq,
 	.irq_eoi		= irq_chip_eoi_parent,
 	.irq_set_affinity	= its_vpe_set_affinity,
+	.irq_retrigger		= its_vpe_retrigger,
 	.irq_set_irqchip_state	= its_vpe_set_irqchip_state,
 	.irq_set_vcpu_affinity	= its_vpe_set_vcpu_affinity,
 };
@@ -3077,8 +3085,6 @@
 	struct page *vprop_page;
 	int base, nr_ids, i, err = 0;
 
-	BUG_ON(!vm);
-
 	bitmap = its_lpi_alloc(roundup_pow_of_two(nr_irqs), &base, &nr_ids);
 	if (!bitmap)
 		return -ENOMEM;
@@ -3113,13 +3119,8 @@
 		set_bit(i, bitmap);
 	}
 
-	if (err) {
-		if (i > 0)
-			its_vpe_irq_domain_free(domain, virq, i - 1);
-
-		its_lpi_free(bitmap, base, nr_ids);
-		its_free_prop_table(vprop_page);
-	}
+	if (err)
+		its_vpe_irq_domain_free(domain, virq, i);
 
 	return err;
 }
@@ -3358,9 +3359,6 @@
 	list_for_each_entry(its, &its_nodes, entry) {
 		void __iomem *base;
 
-		if (!(its->flags & ITS_FLAGS_SAVE_SUSPEND_STATE))
-			continue;
-
 		base = its->base;
 		its->ctlr_save = readl_relaxed(base + GITS_CTLR);
 		err = its_force_quiescent(base);
@@ -3379,9 +3377,6 @@
 		list_for_each_entry_continue_reverse(its, &its_nodes, entry) {
 			void __iomem *base;
 
-			if (!(its->flags & ITS_FLAGS_SAVE_SUSPEND_STATE))
-				continue;
-
 			base = its->base;
 			writel_relaxed(its->ctlr_save, base + GITS_CTLR);
 		}
@@ -3401,9 +3396,6 @@
 		void __iomem *base;
 		int i;
 
-		if (!(its->flags & ITS_FLAGS_SAVE_SUSPEND_STATE))
-			continue;
-
 		base = its->base;
 
 		/*
@@ -3411,7 +3403,10 @@
 		 * don't restore it since writing to CBASER or BASER<n>
 		 * registers is undefined according to the GIC v3 ITS
 		 * Specification.
+		 *
+		 * Firmware resuming with the ITS enabled is terminally broken.
 		 */
+		WARN_ON(readl_relaxed(base + GITS_CTLR) & GITS_CTLR_ENABLE);
 		ret = its_force_quiescent(base);
 		if (ret) {
 			pr_err("ITS@%pa: failed to quiesce on resume: %d\n",
@@ -3678,9 +3673,6 @@
 		ctlr |= GITS_CTLR_ImDe;
 	writel_relaxed(ctlr, its->base + GITS_CTLR);
 
-	if (GITS_TYPER_HCC(typer))
-		its->flags |= ITS_FLAGS_SAVE_SUSPEND_STATE;
-
 	err = its_init_domain(handle, its);
 	if (err)
 		goto out_free_tables;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-gic-v3-mbi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-gic-v3-mbi.c
@@ -303,7 +303,7 @@
 	reg = of_get_property(np, "mbi-alias", NULL);
 	if (reg) {
 		mbi_phys_base = of_translate_address(np, reg);
-		if (mbi_phys_base == OF_BAD_ADDR) {
+		if (mbi_phys_base == (phys_addr_t)OF_BAD_ADDR) {
 			ret = -ENXIO;
 			goto err_free_mbi;
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-gic-v3.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-gic-v3.c
@@ -162,11 +162,11 @@
 	}
 }
 
-static void gic_do_wait_for_rwp(void __iomem *base)
+static void gic_do_wait_for_rwp(void __iomem *base, u32 bit)
 {
 	u32 count = 1000000;	/* 1s! */
 
-	while (readl_relaxed(base + GICD_CTLR) & GICD_CTLR_RWP) {
+	while (readl_relaxed(base + GICD_CTLR) & bit) {
 		count--;
 		if (!count) {
 			pr_err_ratelimited("RWP timeout, gone fishing\n");
@@ -180,13 +180,13 @@
 /* Wait for completion of a distributor change */
 static void gic_dist_wait_for_rwp(void)
 {
-	gic_do_wait_for_rwp(gic_data.dist_base);
+	gic_do_wait_for_rwp(gic_data.dist_base, GICD_CTLR_RWP);
 }
 
 /* Wait for completion of a redistributor change */
 static void gic_redist_wait_for_rwp(void)
 {
-	gic_do_wait_for_rwp(gic_data_rdist_rd_base());
+	gic_do_wait_for_rwp(gic_data_rdist_rd_base(), GICR_CTLR_RWP);
 }
 
 #ifdef CONFIG_ARM64
@@ -383,6 +383,13 @@
 	}
 
 	gic_poke_irq(d, reg);
+
+	/*
+	 * Force read-back to guarantee that the active state has taken
+	 * effect, and won't race with a guest-driven deactivation.
+	 */
+	if (reg == GICD_ISACTIVER)
+		gic_peek_irq(d, reg);
 	return 0;
 }
 
@@ -621,6 +628,10 @@
 
 	irqnr = gic_read_iar();
 
+	/* Check for special IDs first */
+	if ((irqnr >= 1020 && irqnr <= 1023))
+		return;
+
 	if (gic_supports_nmi() &&
 	    unlikely(gic_read_rpr() == GICD_INT_NMI_PRI)) {
 		gic_handle_nmi(irqnr, regs);
@@ -632,10 +643,6 @@
 		gic_arch_enable_irqs();
 	}
 
-	/* Check for special IDs first */
-	if ((irqnr >= 1020 && irqnr <= 1023))
-		return;
-
 	/* Treat anything but SGIs in a uniform way */
 	if (likely(irqnr > 15)) {
 		int err;
@@ -1178,7 +1185,7 @@
 static int gic_cpu_pm_notifier(struct notifier_block *self,
 			       unsigned long cmd, void *v)
 {
-	if (cmd == CPU_PM_EXIT) {
+	if (cmd == CPU_PM_EXIT || cmd == CPU_PM_ENTER_FAILED) {
 		if (gic_dist_security_disabled())
 			gic_enable_redist(true);
 		gic_cpu_sys_reg_init();
@@ -1616,7 +1623,7 @@
 
 	gic_data.ppi_descs = kcalloc(gic_data.ppi_nr, sizeof(*gic_data.ppi_descs), GFP_KERNEL);
 	if (!gic_data.ppi_descs)
-		return;
+		goto out_put_node;
 
 	nr_parts = of_get_child_count(parts_node);
 
@@ -1657,12 +1664,15 @@
 				continue;
 
 			cpu = of_cpu_node_to_id(cpu_node);
-			if (WARN_ON(cpu < 0))
+			if (WARN_ON(cpu < 0)) {
+				of_node_put(cpu_node);
 				continue;
+			}
 
 			pr_cont("%pOF[%d] ", cpu_node, cpu);
 
 			cpumask_set_cpu(cpu, &part->mask);
+			of_node_put(cpu_node);
 		}
 
 		pr_cont("}\n");
@@ -1801,6 +1811,7 @@
 	struct redist_region *redist_regs;
 	u32 nr_redist_regions;
 	bool single_redist;
+	int enabled_rdists;
 	u32 maint_irq;
 	int maint_irq_mode;
 	phys_addr_t vcpu_base;
@@ -1895,8 +1906,10 @@
 	 * If GICC is enabled and has valid gicr base address, then it means
 	 * GICR base is presented via GICC
 	 */
-	if ((gicc->flags & ACPI_MADT_ENABLED) && gicc->gicr_base_address)
+	if ((gicc->flags & ACPI_MADT_ENABLED) && gicc->gicr_base_address) {
+		acpi_data.enabled_rdists++;
 		return 0;
+	}
 
 	/*
 	 * It's perfectly valid firmware can pass disabled GICC entry, driver
@@ -1926,8 +1939,10 @@
 
 	count = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT,
 				      gic_acpi_match_gicc, 0);
-	if (count > 0)
+	if (count > 0) {
 		acpi_data.single_redist = true;
+		count = acpi_data.enabled_rdists;
+	}
 
 	return count;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-gic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-gic.c
@@ -62,7 +62,7 @@
 
 union gic_base {
 	void __iomem *common_base;
-	void __percpu * __iomem *percpu_base;
+	void __iomem * __percpu *percpu_base;
 };
 
 struct gic_chip_data {
@@ -329,10 +329,8 @@
 static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
 			    bool force)
 {
-	void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3);
-	unsigned int cpu, shift = (gic_irq(d) % 4) * 8;
-	u32 val, mask, bit;
-	unsigned long flags;
+	void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + gic_irq(d);
+	unsigned int cpu;
 
 	if (!force)
 		cpu = cpumask_any_and(mask_val, cpu_online_mask);
@@ -342,17 +340,22 @@
 	if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids)
 		return -EINVAL;
 
-	gic_lock_irqsave(flags);
-	mask = 0xff << shift;
-	bit = gic_cpu_map[cpu] << shift;
-	val = readl_relaxed(reg) & ~mask;
-	writel_relaxed(val | bit, reg);
-	gic_unlock_irqrestore(flags);
-
+	writeb_relaxed(gic_cpu_map[cpu], reg);
 	irq_data_update_effective_affinity(d, cpumask_of(cpu));
 
 	return IRQ_SET_MASK_OK_DONE;
 }
+
+void gic_set_cpu(unsigned int cpu, unsigned int irq)
+{
+	struct irq_data *d = irq_get_irq_data(irq);
+	struct cpumask mask;
+
+	cpumask_clear(&mask);
+	cpumask_set_cpu(cpu, &mask);
+	gic_set_affinity(d, &mask, true);
+}
+EXPORT_SYMBOL(gic_set_cpu);
 #endif
 
 static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
@@ -803,18 +806,19 @@
 #endif
 
 #ifdef CONFIG_SMP
-static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
+void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
 {
 	int cpu;
 	unsigned long flags, map = 0;
 
+#if 0
 	if (unlikely(nr_cpu_ids == 1)) {
 		/* Only one CPU? let's do a self-IPI... */
 		writel_relaxed(2 << 24 | irq,
 			       gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
 		return;
 	}
-
+#endif
 	gic_lock_irqsave(flags);
 
 	/* Convert our logical CPU mask into a physical one. */
@@ -832,6 +836,7 @@
 
 	gic_unlock_irqrestore(flags);
 }
+EXPORT_SYMBOL(gic_raise_softirq);
 #endif
 
 #ifdef CONFIG_BL_SWITCHER
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-imx-irqsteer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-imx-irqsteer.c
@@ -12,6 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
+#include <linux/pm_runtime.h>
 #include <linux/spinlock.h>
 
 #define CTRL_STRIDE_OFF(_t, _r)	(_t * 4 * _r)
@@ -34,6 +35,7 @@
 	int			channel;
 	struct irq_domain	*domain;
 	u32			*saved_reg;
+	struct device		*dev;
 };
 
 static int imx_irqsteer_get_reg_index(struct irqsteer_data *data,
@@ -70,10 +72,26 @@
 	raw_spin_unlock_irqrestore(&data->lock, flags);
 }
 
-static struct irq_chip imx_irqsteer_irq_chip = {
-	.name		= "irqsteer",
-	.irq_mask	= imx_irqsteer_irq_mask,
-	.irq_unmask	= imx_irqsteer_irq_unmask,
+static void imx_irqsteer_irq_bus_lock(struct irq_data *d)
+{
+	struct irqsteer_data *data = d->chip_data;
+
+	pm_runtime_get_sync(data->dev);
+}
+
+static void imx_irqsteer_irq_bus_sync_unlock(struct irq_data *d)
+{
+	struct irqsteer_data *data = d->chip_data;
+
+	pm_runtime_put_autosuspend(data->dev);
+}
+
+static const struct irq_chip imx_irqsteer_irq_chip = {
+	.name			= "irqsteer",
+	.irq_mask		= imx_irqsteer_irq_mask,
+	.irq_unmask		= imx_irqsteer_irq_unmask,
+	.irq_bus_lock		= imx_irqsteer_irq_bus_lock,
+	.irq_bus_sync_unlock	= imx_irqsteer_irq_bus_sync_unlock,
 };
 
 static int imx_irqsteer_irq_map(struct irq_domain *h, unsigned int irq,
@@ -151,6 +169,7 @@
 	if (!data)
 		return -ENOMEM;
 
+	data->dev = &pdev->dev;
 	data->regs = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(data->regs)) {
 		dev_err(&pdev->dev, "failed to initialize reg\n");
@@ -181,7 +200,7 @@
 	data->irq_count = DIV_ROUND_UP(irqs_num, 64);
 	data->reg_num = irqs_num / 32;
 
-	if (IS_ENABLED(CONFIG_PM_SLEEP)) {
+	if (IS_ENABLED(CONFIG_PM)) {
 		data->saved_reg = devm_kzalloc(&pdev->dev,
 					sizeof(u32) * data->reg_num,
 					GFP_KERNEL);
@@ -205,6 +224,7 @@
 		ret = -ENOMEM;
 		goto out;
 	}
+	irq_domain_set_pm_device(data->domain, &pdev->dev);
 
 	if (!data->irq_count || data->irq_count > CHAN_MAX_OUTPUT_INT) {
 		ret = -EINVAL;
@@ -225,6 +245,9 @@
 
 	platform_set_drvdata(pdev, data);
 
+	pm_runtime_set_active(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
+
 	return 0;
 out:
 	clk_disable_unprepare(data->ipg_clk);
@@ -247,7 +270,7 @@
 	return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
 static void imx_irqsteer_save_regs(struct irqsteer_data *data)
 {
 	int i;
@@ -294,7 +317,10 @@
 #endif
 
 static const struct dev_pm_ops imx_irqsteer_pm_ops = {
-	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(imx_irqsteer_suspend, imx_irqsteer_resume)
+	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+				      pm_runtime_force_resume)
+	SET_RUNTIME_PM_OPS(imx_irqsteer_suspend,
+			   imx_irqsteer_resume, NULL)
 };
 
 static const struct of_device_id imx_irqsteer_dt_ids[] = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-ingenic-tcu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-ingenic-tcu.c
@@ -179,4 +179,5 @@
 }
 IRQCHIP_DECLARE(jz4740_tcu_irq, "ingenic,jz4740-tcu", ingenic_tcu_irq_init);
 IRQCHIP_DECLARE(jz4725b_tcu_irq, "ingenic,jz4725b-tcu", ingenic_tcu_irq_init);
+IRQCHIP_DECLARE(jz4760_tcu_irq, "ingenic,jz4760-tcu", ingenic_tcu_irq_init);
 IRQCHIP_DECLARE(jz4770_tcu_irq, "ingenic,jz4770-tcu", ingenic_tcu_irq_init);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-ingenic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-ingenic.c
@@ -108,6 +108,14 @@
 		goto out_unmap_irq;
 	}
 
+	domain = irq_domain_add_legacy(node, num_chips * 32,
+				       JZ4740_IRQ_BASE, 0,
+				       &irq_domain_simple_ops, NULL);
+	if (!domain) {
+		err = -ENOMEM;
+		goto out_unmap_base;
+	}
+
 	for (i = 0; i < num_chips; i++) {
 		/* Mask all irqs */
 		writel(0xffffffff, intc->base + (i * CHIP_SIZE) +
@@ -134,14 +142,11 @@
 				       IRQ_NOPROBE | IRQ_LEVEL);
 	}
 
-	domain = irq_domain_add_legacy(node, num_chips * 32, JZ4740_IRQ_BASE, 0,
-				       &irq_domain_simple_ops, NULL);
-	if (!domain)
-		pr_warn("unable to register IRQ domain\n");
-
 	setup_irq(parent_irq, &intc_cascade_action);
 	return 0;
 
+out_unmap_base:
+	iounmap(intc->base);
 out_unmap_irq:
 	irq_dispose_mapping(parent_irq);
 out_free:
@@ -163,6 +168,7 @@
 {
 	return ingenic_intc_of_init(node, 2);
 }
+IRQCHIP_DECLARE(jz4760_intc, "ingenic,jz4760-intc", intc_2chip_of_init);
 IRQCHIP_DECLARE(jz4770_intc, "ingenic,jz4770-intc", intc_2chip_of_init);
 IRQCHIP_DECLARE(jz4775_intc, "ingenic,jz4775-intc", intc_2chip_of_init);
 IRQCHIP_DECLARE(jz4780_intc, "ingenic,jz4780-intc", intc_2chip_of_init);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-jcore-aic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-jcore-aic.c
@@ -68,6 +68,7 @@
 	unsigned min_irq = JCORE_AIC2_MIN_HWIRQ;
 	unsigned dom_sz = JCORE_AIC_MAX_HWIRQ+1;
 	struct irq_domain *domain;
+	int ret;
 
 	pr_info("Initializing J-Core AIC\n");
 
@@ -100,11 +101,17 @@
 	jcore_aic.irq_unmask = noop;
 	jcore_aic.name = "AIC";
 
-	domain = irq_domain_add_linear(node, dom_sz, &jcore_aic_irqdomain_ops,
+	ret = irq_alloc_descs(-1, min_irq, dom_sz - min_irq,
+			      of_node_to_nid(node));
+
+	if (ret < 0)
+		return ret;
+
+	domain = irq_domain_add_legacy(node, dom_sz - min_irq, min_irq, min_irq,
+				       &jcore_aic_irqdomain_ops,
 				       &jcore_aic);
 	if (!domain)
 		return -ENOMEM;
-	irq_create_strict_mappings(domain, min_irq, min_irq, dom_sz - min_irq);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-mbigen.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-mbigen.c
@@ -64,6 +64,20 @@
 	void __iomem		*base;
 };
 
+static inline unsigned int get_mbigen_node_offset(unsigned int nid)
+{
+	unsigned int offset = nid * MBIGEN_NODE_OFFSET;
+
+	/*
+	 * To avoid touched clear register in unexpected way, we need to directly
+	 * skip clear register when access to more than 10 mbigen nodes.
+	 */
+	if (nid >= (REG_MBIGEN_CLEAR_OFFSET / MBIGEN_NODE_OFFSET))
+		offset += MBIGEN_NODE_OFFSET;
+
+	return offset;
+}
+
 static inline unsigned int get_mbigen_vec_reg(irq_hw_number_t hwirq)
 {
 	unsigned int nid, pin;
@@ -72,8 +86,7 @@
 	nid = hwirq / IRQS_PER_MBIGEN_NODE + 1;
 	pin = hwirq % IRQS_PER_MBIGEN_NODE;
 
-	return pin * 4 + nid * MBIGEN_NODE_OFFSET
-			+ REG_MBIGEN_VEC_OFFSET;
+	return pin * 4 + get_mbigen_node_offset(nid) + REG_MBIGEN_VEC_OFFSET;
 }
 
 static inline void get_mbigen_type_reg(irq_hw_number_t hwirq,
@@ -88,8 +101,7 @@
 	*mask = 1 << (irq_ofst % 32);
 	ofst = irq_ofst / 32 * 4;
 
-	*addr = ofst + nid * MBIGEN_NODE_OFFSET
-		+ REG_MBIGEN_TYPE_OFFSET;
+	*addr = ofst + get_mbigen_node_offset(nid) + REG_MBIGEN_TYPE_OFFSET;
 }
 
 static inline void get_mbigen_clear_reg(irq_hw_number_t hwirq,
@@ -220,10 +232,16 @@
 	return 0;
 }
 
+static void mbigen_irq_domain_free(struct irq_domain *domain, unsigned int virq,
+				   unsigned int nr_irqs)
+{
+	platform_msi_domain_free(domain, virq, nr_irqs);
+}
+
 static const struct irq_domain_ops mbigen_domain_ops = {
 	.translate	= mbigen_domain_translate,
 	.alloc		= mbigen_irq_domain_alloc,
-	.free		= irq_domain_free_irqs_common,
+	.free		= mbigen_irq_domain_free,
 };
 
 static int mbigen_of_create_domain(struct platform_device *pdev,
@@ -374,6 +392,7 @@
 		.name		= "Hisilicon MBIGEN-V2",
 		.of_match_table	= mbigen_of_match,
 		.acpi_match_table = ACPI_PTR(mbigen_acpi_match),
+		.suppress_bind_attrs = true,
 	},
 	.probe			= mbigen_device_probe,
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-meson-gpio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-meson-gpio.c
@@ -70,7 +70,7 @@
 	.support_edge_both = true,
 };
 
-static const struct of_device_id meson_irq_gpio_matches[] = {
+static const struct of_device_id meson_irq_gpio_matches[] __maybe_unused = {
 	{ .compatible = "amlogic,meson8-gpio-intc", .data = &meson8_params },
 	{ .compatible = "amlogic,meson8b-gpio-intc", .data = &meson8b_params },
 	{ .compatible = "amlogic,meson-gxbb-gpio-intc", .data = &gxbb_params },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-mips-cpu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-mips-cpu.c
@@ -197,6 +197,13 @@
 		if (ret)
 			return ret;
 
+		ret = irq_domain_set_hwirq_and_chip(domain->parent, virq + i, hwirq,
+						    &mips_mt_cpu_irq_controller,
+						    NULL);
+
+		if (ret)
+			return ret;
+
 		ret = irq_set_irq_type(virq + i, IRQ_TYPE_LEVEL_HIGH);
 		if (ret)
 			return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-mips-gic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-mips-gic.c
@@ -48,7 +48,7 @@
 
 DEFINE_PER_CPU_READ_MOSTLY(unsigned long[GIC_MAX_LONGS], pcpu_masks);
 
-static DEFINE_SPINLOCK(gic_lock);
+static DEFINE_RAW_SPINLOCK(gic_lock);
 static struct irq_domain *gic_irq_domain;
 static struct irq_domain *gic_ipi_domain;
 static int gic_shared_intrs;
@@ -207,7 +207,7 @@
 
 	irq = GIC_HWIRQ_TO_SHARED(d->hwirq);
 
-	spin_lock_irqsave(&gic_lock, flags);
+	raw_spin_lock_irqsave(&gic_lock, flags);
 	switch (type & IRQ_TYPE_SENSE_MASK) {
 	case IRQ_TYPE_EDGE_FALLING:
 		pol = GIC_POL_FALLING_EDGE;
@@ -247,7 +247,7 @@
 	else
 		irq_set_chip_handler_name_locked(d, &gic_level_irq_controller,
 						 handle_level_irq, NULL);
-	spin_unlock_irqrestore(&gic_lock, flags);
+	raw_spin_unlock_irqrestore(&gic_lock, flags);
 
 	return 0;
 }
@@ -265,7 +265,7 @@
 		return -EINVAL;
 
 	/* Assumption : cpumask refers to a single CPU */
-	spin_lock_irqsave(&gic_lock, flags);
+	raw_spin_lock_irqsave(&gic_lock, flags);
 
 	/* Re-route this IRQ */
 	write_gic_map_vp(irq, BIT(mips_cm_vp_id(cpu)));
@@ -276,7 +276,7 @@
 		set_bit(irq, per_cpu_ptr(pcpu_masks, cpu));
 
 	irq_data_update_effective_affinity(d, cpumask_of(cpu));
-	spin_unlock_irqrestore(&gic_lock, flags);
+	raw_spin_unlock_irqrestore(&gic_lock, flags);
 
 	return IRQ_SET_MASK_OK;
 }
@@ -354,12 +354,12 @@
 	cd = irq_data_get_irq_chip_data(d);
 	cd->mask = false;
 
-	spin_lock_irqsave(&gic_lock, flags);
+	raw_spin_lock_irqsave(&gic_lock, flags);
 	for_each_online_cpu(cpu) {
 		write_gic_vl_other(mips_cm_vp_id(cpu));
 		write_gic_vo_rmask(BIT(intr));
 	}
-	spin_unlock_irqrestore(&gic_lock, flags);
+	raw_spin_unlock_irqrestore(&gic_lock, flags);
 }
 
 static void gic_unmask_local_irq_all_vpes(struct irq_data *d)
@@ -372,32 +372,45 @@
 	cd = irq_data_get_irq_chip_data(d);
 	cd->mask = true;
 
-	spin_lock_irqsave(&gic_lock, flags);
+	raw_spin_lock_irqsave(&gic_lock, flags);
 	for_each_online_cpu(cpu) {
 		write_gic_vl_other(mips_cm_vp_id(cpu));
 		write_gic_vo_smask(BIT(intr));
 	}
-	spin_unlock_irqrestore(&gic_lock, flags);
+	raw_spin_unlock_irqrestore(&gic_lock, flags);
 }
 
-static void gic_all_vpes_irq_cpu_online(struct irq_data *d)
+static void gic_all_vpes_irq_cpu_online(void)
 {
-	struct gic_all_vpes_chip_data *cd;
-	unsigned int intr;
+	static const unsigned int local_intrs[] = {
+		GIC_LOCAL_INT_TIMER,
+		GIC_LOCAL_INT_PERFCTR,
+		GIC_LOCAL_INT_FDC,
+	};
+	unsigned long flags;
+	int i;
 
-	intr = GIC_HWIRQ_TO_LOCAL(d->hwirq);
-	cd = irq_data_get_irq_chip_data(d);
+	raw_spin_lock_irqsave(&gic_lock, flags);
 
-	write_gic_vl_map(mips_gic_vx_map_reg(intr), cd->map);
-	if (cd->mask)
-		write_gic_vl_smask(BIT(intr));
+	for (i = 0; i < ARRAY_SIZE(local_intrs); i++) {
+		unsigned int intr = local_intrs[i];
+		struct gic_all_vpes_chip_data *cd;
+
+		if (!gic_local_irq_is_routable(intr))
+			continue;
+		cd = &gic_all_vpes_chip_data[intr];
+		write_gic_vl_map(mips_gic_vx_map_reg(intr), cd->map);
+		if (cd->mask)
+			write_gic_vl_smask(BIT(intr));
+	}
+
+	raw_spin_unlock_irqrestore(&gic_lock, flags);
 }
 
 static struct irq_chip gic_all_vpes_local_irq_controller = {
 	.name			= "MIPS GIC Local",
 	.irq_mask		= gic_mask_local_irq_all_vpes,
 	.irq_unmask		= gic_unmask_local_irq_all_vpes,
-	.irq_cpu_online		= gic_all_vpes_irq_cpu_online,
 };
 
 static void __gic_irq_dispatch(void)
@@ -421,11 +434,11 @@
 
 	data = irq_get_irq_data(virq);
 
-	spin_lock_irqsave(&gic_lock, flags);
+	raw_spin_lock_irqsave(&gic_lock, flags);
 	write_gic_map_pin(intr, GIC_MAP_PIN_MAP_TO_PIN | gic_cpu_pin);
 	write_gic_map_vp(intr, BIT(mips_cm_vp_id(cpu)));
 	irq_data_update_effective_affinity(data, cpumask_of(cpu));
-	spin_unlock_irqrestore(&gic_lock, flags);
+	raw_spin_unlock_irqrestore(&gic_lock, flags);
 
 	return 0;
 }
@@ -476,6 +489,10 @@
 	intr = GIC_HWIRQ_TO_LOCAL(hwirq);
 	map = GIC_MAP_PIN_MAP_TO_PIN | gic_cpu_pin;
 
+	/*
+	 * If adding support for more per-cpu interrupts, keep the the
+	 * array in gic_all_vpes_irq_cpu_online() in sync.
+	 */
 	switch (intr) {
 	case GIC_LOCAL_INT_TIMER:
 		/* CONFIG_MIPS_CMP workaround (see __gic_init) */
@@ -514,12 +531,12 @@
 	if (!gic_local_irq_is_routable(intr))
 		return -EPERM;
 
-	spin_lock_irqsave(&gic_lock, flags);
+	raw_spin_lock_irqsave(&gic_lock, flags);
 	for_each_online_cpu(cpu) {
 		write_gic_vl_other(mips_cm_vp_id(cpu));
 		write_gic_vo_map(mips_gic_vx_map_reg(intr), map);
 	}
-	spin_unlock_irqrestore(&gic_lock, flags);
+	raw_spin_unlock_irqrestore(&gic_lock, flags);
 
 	return 0;
 }
@@ -662,8 +679,8 @@
 	/* Clear all local IRQ masks (ie. disable all local interrupts) */
 	write_gic_vl_rmask(~0);
 
-	/* Invoke irq_cpu_online callbacks to enable desired interrupts */
-	irq_cpu_online();
+	/* Enable desired interrupts */
+	gic_all_vpes_irq_cpu_online();
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-mtk-sysirq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-mtk-sysirq.c
@@ -15,7 +15,7 @@
 #include <linux/spinlock.h>
 
 struct mtk_sysirq_chip_data {
-	spinlock_t lock;
+	raw_spinlock_t lock;
 	u32 nr_intpol_bases;
 	void __iomem **intpol_bases;
 	u32 *intpol_words;
@@ -37,7 +37,7 @@
 	reg_index = chip_data->which_word[hwirq];
 	offset = hwirq & 0x1f;
 
-	spin_lock_irqsave(&chip_data->lock, flags);
+	raw_spin_lock_irqsave(&chip_data->lock, flags);
 	value = readl_relaxed(base + reg_index * 4);
 	if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_EDGE_FALLING) {
 		if (type == IRQ_TYPE_LEVEL_LOW)
@@ -53,7 +53,7 @@
 
 	data = data->parent_data;
 	ret = data->chip->irq_set_type(data, type);
-	spin_unlock_irqrestore(&chip_data->lock, flags);
+	raw_spin_unlock_irqrestore(&chip_data->lock, flags);
 	return ret;
 }
 
@@ -212,7 +212,7 @@
 		ret = -ENOMEM;
 		goto out_free_which_word;
 	}
-	spin_lock_init(&chip_data->lock);
+	raw_spin_lock_init(&chip_data->lock);
 
 	return 0;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-mvebu-gicp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-mvebu-gicp.c
@@ -223,6 +223,7 @@
 	}
 
 	parent_domain = irq_find_host(irq_parent_dn);
+	of_node_put(irq_parent_dn);
 	if (!parent_domain) {
 		dev_err(&pdev->dev, "failed to find parent IRQ domain\n");
 		return -ENODEV;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-nvic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-nvic.c
@@ -26,7 +26,7 @@
 
 #define NVIC_ISER		0x000
 #define NVIC_ICER		0x080
-#define NVIC_IPR		0x300
+#define NVIC_IPR		0x400
 
 #define NVIC_MAX_BANKS		16
 /*
@@ -105,6 +105,7 @@
 
 	if (!nvic_irq_domain) {
 		pr_warn("Failed to allocate irq domain\n");
+		iounmap(nvic_base);
 		return -ENOMEM;
 	}
 
@@ -114,6 +115,7 @@
 	if (ret) {
 		pr_warn("Failed to allocate irq chips\n");
 		irq_domain_remove(nvic_irq_domain);
+		iounmap(nvic_base);
 		return ret;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-or1k-pic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-or1k-pic.c
@@ -66,7 +66,6 @@
 		.name = "or1k-PIC-level",
 		.irq_unmask = or1k_pic_unmask,
 		.irq_mask = or1k_pic_mask,
-		.irq_mask_ack = or1k_pic_mask_ack,
 	},
 	.handle = handle_level_irq,
 	.flags = IRQ_LEVEL | IRQ_NOPROBE,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-s3c24xx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-s3c24xx.c
@@ -359,11 +359,25 @@
 asmlinkage void __exception_irq_entry s3c24xx_handle_irq(struct pt_regs *regs)
 {
 	do {
-		if (likely(s3c_intc[0]))
-			if (s3c24xx_handle_intc(s3c_intc[0], regs, 0))
-				continue;
+		/*
+		 * For platform based machines, neither ERR nor NULL can happen here.
+		 * The s3c24xx_handle_irq() will be set as IRQ handler iff this succeeds:
+		 *
+		 *    s3c_intc[0] = s3c24xx_init_intc()
+		 *
+		 * If this fails, the next calls to s3c24xx_init_intc() won't be executed.
+		 *
+		 * For DT machine, s3c_init_intc_of() could set the IRQ handler without
+		 * setting s3c_intc[0] only if it was called with num_ctrl=0. There is no
+		 * such code path, so again the s3c_intc[0] will have a valid pointer if
+		 * set_handle_irq() is called.
+		 *
+		 * Therefore in s3c24xx_handle_irq(), the s3c_intc[0] is always something.
+		 */
+		if (s3c24xx_handle_intc(s3c_intc[0], regs, 0))
+			continue;
 
-		if (s3c_intc[2])
+		if (!IS_ERR_OR_NULL(s3c_intc[2]))
 			if (s3c24xx_handle_intc(s3c_intc[2], regs, 64))
 				continue;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-sifive-plic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-sifive-plic.c
@@ -138,7 +138,13 @@
 {
 	struct plic_handler *handler = this_cpu_ptr(&plic_handlers);
 
-	writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM);
+	if (irqd_irq_masked(d)) {
+		plic_irq_unmask(d);
+		writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM);
+		plic_irq_mask(d);
+	} else {
+		writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM);
+	}
 }
 
 static struct irq_chip plic_chip = {
@@ -307,3 +313,4 @@
 
 IRQCHIP_DECLARE(sifive_plic, "sifive,plic-1.0.0", plic_init);
 IRQCHIP_DECLARE(riscv_plic0, "riscv,plic0", plic_init); /* for legacy systems */
+IRQCHIP_DECLARE(thead_c900_plic, "thead,c900-plic", plic_init); /* for firmware driver */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-sni-exiu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-sni-exiu.c
@@ -37,11 +37,26 @@
 	u32		spi_base;
 };
 
-static void exiu_irq_eoi(struct irq_data *d)
+static void exiu_irq_ack(struct irq_data *d)
 {
 	struct exiu_irq_data *data = irq_data_get_irq_chip_data(d);
 
 	writel(BIT(d->hwirq), data->base + EIREQCLR);
+}
+
+static void exiu_irq_eoi(struct irq_data *d)
+{
+	struct exiu_irq_data *data = irq_data_get_irq_chip_data(d);
+
+	/*
+	 * Level triggered interrupts are latched and must be cleared during
+	 * EOI or the interrupt will be jammed on. Of course if a level
+	 * triggered interrupt is still asserted then the write will not clear
+	 * the interrupt.
+	 */
+	if (irqd_is_level_type(d))
+		writel(BIT(d->hwirq), data->base + EIREQCLR);
+
 	irq_chip_eoi_parent(d);
 }
 
@@ -91,10 +106,13 @@
 	writel_relaxed(val, data->base + EILVL);
 
 	val = readl_relaxed(data->base + EIEDG);
-	if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_LEVEL_HIGH)
+	if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_LEVEL_HIGH) {
 		val &= ~BIT(d->hwirq);
-	else
+		irq_set_handler_locked(d, handle_fasteoi_irq);
+	} else {
 		val |= BIT(d->hwirq);
+		irq_set_handler_locked(d, handle_fasteoi_ack_irq);
+	}
 	writel_relaxed(val, data->base + EIEDG);
 
 	writel_relaxed(BIT(d->hwirq), data->base + EIREQCLR);
@@ -104,6 +122,7 @@
 
 static struct irq_chip exiu_irq_chip = {
 	.name			= "EXIU",
+	.irq_ack		= exiu_irq_ack,
 	.irq_eoi		= exiu_irq_eoi,
 	.irq_enable		= exiu_irq_enable,
 	.irq_mask		= exiu_irq_mask,
@@ -136,7 +155,7 @@
 		if (fwspec->param_count != 2)
 			return -EINVAL;
 		*hwirq = fwspec->param[0];
-		*type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
+		*type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
 	}
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-stm32-exti.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-stm32-exti.c
@@ -414,6 +414,7 @@
 	.map	= irq_map_generic_chip,
 	.alloc  = stm32_exti_alloc,
 	.free	= stm32_exti_free,
+	.xlate	= irq_domain_xlate_twocell,
 };
 
 static void stm32_irq_ack(struct irq_data *d)
@@ -431,6 +432,16 @@
 	irq_gc_unlock(gc);
 }
 
+/* directly set the target bit without reading first. */
+static inline void stm32_exti_write_bit(struct irq_data *d, u32 reg)
+{
+	struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d);
+	void __iomem *base = chip_data->host_data->base;
+	u32 val = BIT(d->hwirq % IRQS_PER_BANK);
+
+	writel_relaxed(val, base + reg);
+}
+
 static inline u32 stm32_exti_set_bit(struct irq_data *d, u32 reg)
 {
 	struct stm32_exti_chip_data *chip_data = irq_data_get_irq_chip_data(d);
@@ -464,9 +475,9 @@
 
 	raw_spin_lock(&chip_data->rlock);
 
-	stm32_exti_set_bit(d, stm32_bank->rpr_ofst);
+	stm32_exti_write_bit(d, stm32_bank->rpr_ofst);
 	if (stm32_bank->fpr_ofst != UNDEF_REG)
-		stm32_exti_set_bit(d, stm32_bank->fpr_ofst);
+		stm32_exti_write_bit(d, stm32_bank->fpr_ofst);
 
 	raw_spin_unlock(&chip_data->rlock);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-sunxi-nmi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-sunxi-nmi.c
@@ -200,7 +200,8 @@
 	gc->chip_types[0].chip.irq_unmask	= irq_gc_mask_set_bit;
 	gc->chip_types[0].chip.irq_eoi		= irq_gc_ack_set_bit;
 	gc->chip_types[0].chip.irq_set_type	= sunxi_sc_nmi_set_type;
-	gc->chip_types[0].chip.flags		= IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED;
+	gc->chip_types[0].chip.flags		= IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED |
+						  IRQCHIP_SKIP_SET_WAKE;
 	gc->chip_types[0].regs.ack		= reg_offs->pend;
 	gc->chip_types[0].regs.mask		= reg_offs->enable;
 	gc->chip_types[0].regs.type		= reg_offs->ctrl;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-tegra.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-tegra.c
@@ -148,10 +148,10 @@
 		lic->cop_iep[i] = readl_relaxed(ictlr + ICTLR_COP_IEP_CLASS);
 
 		/* Disable COP interrupts */
-		writel_relaxed(~0ul, ictlr + ICTLR_COP_IER_CLR);
+		writel_relaxed(GENMASK(31, 0), ictlr + ICTLR_COP_IER_CLR);
 
 		/* Disable CPU interrupts */
-		writel_relaxed(~0ul, ictlr + ICTLR_CPU_IER_CLR);
+		writel_relaxed(GENMASK(31, 0), ictlr + ICTLR_CPU_IER_CLR);
 
 		/* Enable the wakeup sources of ictlr */
 		writel_relaxed(lic->ictlr_wake_mask[i], ictlr + ICTLR_CPU_IER_SET);
@@ -172,12 +172,12 @@
 
 		writel_relaxed(lic->cpu_iep[i],
 			       ictlr + ICTLR_CPU_IEP_CLASS);
-		writel_relaxed(~0ul, ictlr + ICTLR_CPU_IER_CLR);
+		writel_relaxed(GENMASK(31, 0), ictlr + ICTLR_CPU_IER_CLR);
 		writel_relaxed(lic->cpu_ier[i],
 			       ictlr + ICTLR_CPU_IER_SET);
 		writel_relaxed(lic->cop_iep[i],
 			       ictlr + ICTLR_COP_IEP_CLASS);
-		writel_relaxed(~0ul, ictlr + ICTLR_COP_IER_CLR);
+		writel_relaxed(GENMASK(31, 0), ictlr + ICTLR_COP_IER_CLR);
 		writel_relaxed(lic->cop_ier[i],
 			       ictlr + ICTLR_COP_IER_SET);
 	}
@@ -312,7 +312,7 @@
 		lic->base[i] = base;
 
 		/* Disable all interrupts */
-		writel_relaxed(~0UL, base + ICTLR_CPU_IER_CLR);
+		writel_relaxed(GENMASK(31, 0), base + ICTLR_CPU_IER_CLR);
 		/* All interrupts target IRQ */
 		writel_relaxed(0, base + ICTLR_CPU_IEP_CLASS);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-ti-sci-inta.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-ti-sci-inta.c
@@ -2,7 +2,7 @@
 /*
  * Texas Instruments' K3 Interrupt Aggregator irqchip driver
  *
- * Copyright (C) 2018-2019 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2018-2019 Texas Instruments Incorporated - https://www.ti.com/
  *	Lokesh Vutla <lokeshvutla@ti.com>
  */
 
@@ -37,6 +37,7 @@
 #define VINT_ENABLE_SET_OFFSET	0x0
 #define VINT_ENABLE_CLR_OFFSET	0x8
 #define VINT_STATUS_OFFSET	0x18
+#define VINT_STATUS_MASKED_OFFSET	0x20
 
 /**
  * struct ti_sci_inta_event_desc - Description of an event coming to
@@ -116,7 +117,7 @@
 	chained_irq_enter(irq_desc_get_chip(desc), desc);
 
 	val = readq_relaxed(inta->base + vint_desc->vint_id * 0x1000 +
-			    VINT_STATUS_OFFSET);
+			    VINT_STATUS_MASKED_OFFSET);
 
 	for_each_set_bit(bit, &val, MAX_EVENTS_PER_VINT) {
 		virq = irq_find_mapping(domain, vint_desc->events[bit].hwirq);
@@ -570,7 +571,7 @@
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	inta->base = devm_ioremap_resource(dev, res);
 	if (IS_ERR(inta->base))
-		return -ENODEV;
+		return PTR_ERR(inta->base);
 
 	domain = irq_domain_add_linear(dev_of_node(dev),
 				       ti_sci_get_num_resources(inta->vint),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-ti-sci-intr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-ti-sci-intr.c
@@ -2,7 +2,7 @@
 /*
  * Texas Instruments' K3 Interrupt Router irqchip driver
  *
- * Copyright (C) 2018-2019 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2018-2019 Texas Instruments Incorporated - https://www.ti.com/
  *	Lokesh Vutla <lokeshvutla@ti.com>
  */
 
@@ -205,6 +205,7 @@
 	}
 
 	parent_domain = irq_find_host(parent_node);
+	of_node_put(parent_node);
 	if (!parent_domain) {
 		dev_err(dev, "Failed to find IRQ parent domain\n");
 		return -ENODEV;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-versatile-fpga.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-versatile-fpga.c
@@ -6,6 +6,7 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/irqchip.h>
+#include <linux/irqchip/chained_irq.h>
 #include <linux/irqchip/versatile-fpga.h>
 #include <linux/irqdomain.h>
 #include <linux/module.h>
@@ -68,12 +69,16 @@
 
 static void fpga_irq_handle(struct irq_desc *desc)
 {
+	struct irq_chip *chip = irq_desc_get_chip(desc);
 	struct fpga_irq_data *f = irq_desc_get_handler_data(desc);
-	u32 status = readl(f->base + IRQ_STATUS);
+	u32 status;
+
+	chained_irq_enter(chip, desc);
 
+	status = readl(f->base + IRQ_STATUS);
 	if (status == 0) {
 		do_bad_IRQ(desc);
-		return;
+		goto out;
 	}
 
 	do {
@@ -82,6 +87,9 @@
 		status &= ~(1 << irq);
 		generic_handle_irq(irq_find_mapping(f->domain, irq));
 	} while (status);
+
+out:
+	chained_irq_exit(chip, desc);
 }
 
 /*
@@ -204,6 +212,9 @@
 	if (of_property_read_u32(node, "valid-mask", &valid_mask))
 		valid_mask = 0;
 
+	writel(clear_mask, base + IRQ_ENABLE_CLEAR);
+	writel(clear_mask, base + FIQ_ENABLE_CLEAR);
+
 	/* Some chips are cascaded from a parent IRQ */
 	parent_irq = irq_of_parse_and_map(node, 0);
 	if (!parent_irq) {
@@ -213,9 +224,6 @@
 
 	fpga_irq_init(base, node->name, 0, parent_irq, valid_mask, node);
 
-	writel(clear_mask, base + IRQ_ENABLE_CLEAR);
-	writel(clear_mask, base + FIQ_ENABLE_CLEAR);
-
 	/*
 	 * On Versatile AB/PB, some secondary interrupts have a direct
 	 * pass-thru to the primary controller for IRQs 20 and 22-31 which need
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-xilinx-intc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-xilinx-intc.c
@@ -18,6 +18,8 @@
 #include <linux/jump_label.h>
 #include <linux/bug.h>
 #include <linux/of_irq.h>
+#include <linux/cpuhotplug.h>
+#include <linux/smp.h>
 
 /* No one else should require these constants, so define them locally here. */
 #define ISR 0x00			/* Interrupt Status Register */
@@ -32,35 +34,62 @@
 #define MER_ME (1<<0)
 #define MER_HIE (1<<1)
 
-static DEFINE_STATIC_KEY_FALSE(xintc_is_be);
-
 struct xintc_irq_chip {
 	void		__iomem *base;
-	struct		irq_domain *root_domain;
+	struct		irq_domain *domain;
 	u32		intr_mask;
+	struct			irq_chip *intc_dev;
+	u32				nr_irq;
+	u32				sw_irq;
 };
 
-static struct xintc_irq_chip *xintc_irqc;
+static DEFINE_STATIC_KEY_FALSE(xintc_is_be);
+
+static DEFINE_PER_CPU(struct xintc_irq_chip, primary_intc);
 
-static void xintc_write(int reg, u32 data)
+static void xintc_write(struct xintc_irq_chip *irqc, int reg, u32 data)
 {
+	if (!irqc)
+		irqc = per_cpu_ptr(&primary_intc, smp_processor_id());
+
 	if (static_branch_unlikely(&xintc_is_be))
-		iowrite32be(data, xintc_irqc->base + reg);
+		iowrite32be(data, irqc->base + reg);
 	else
-		iowrite32(data, xintc_irqc->base + reg);
+		iowrite32(data, irqc->base + reg);
 }
 
-static unsigned int xintc_read(int reg)
+static unsigned int xintc_read(struct xintc_irq_chip *irqc, int reg)
 {
 	if (static_branch_unlikely(&xintc_is_be))
-		return ioread32be(xintc_irqc->base + reg);
+		return ioread32be(irqc->base + reg);
 	else
-		return ioread32(xintc_irqc->base + reg);
+		return ioread32(irqc->base + reg);
+}
+
+#if defined(CONFIG_SMP) && defined(CONFIG_MICROBLAZE)
+static DEFINE_RAW_SPINLOCK(ipi_lock);
+
+static void send_ipi(unsigned int cpu, unsigned int ipi_number)
+{
+	unsigned long flags;
+	struct xintc_irq_chip *irqc = per_cpu_ptr(&primary_intc, cpu);
+	u32 sw_irq = 1 << (ipi_number + irqc->nr_irq);
+
+	pr_debug("%s: cpu: %u, sends IPI: %d to cpu: %u, sw_irq %x\n",
+		 __func__, smp_processor_id(), ipi_number, cpu, sw_irq);
+
+	raw_spin_lock_irqsave(&ipi_lock, flags);
+
+	xintc_write(irqc, ISR, sw_irq);
+
+	raw_spin_unlock_irqrestore(&ipi_lock, flags);
 }
+#endif
 
 static void intc_enable_or_unmask(struct irq_data *d)
 {
 	unsigned long mask = 1 << d->hwirq;
+	struct xintc_irq_chip *local_intc = irq_data_get_irq_chip_data(d);
 
 	pr_debug("irq-xilinx: enable_or_unmask: %ld\n", d->hwirq);
 
@@ -69,47 +98,44 @@
 	 * acks the irq before calling the interrupt handler
 	 */
 	if (irqd_is_level_type(d))
-		xintc_write(IAR, mask);
+		xintc_write(local_intc, IAR, mask);
 
-	xintc_write(SIE, mask);
+	xintc_write(local_intc, SIE, mask);
 }
 
 static void intc_disable_or_mask(struct irq_data *d)
 {
+	struct xintc_irq_chip *local_intc = irq_data_get_irq_chip_data(d);
+
 	pr_debug("irq-xilinx: disable: %ld\n", d->hwirq);
-	xintc_write(CIE, 1 << d->hwirq);
+	xintc_write(local_intc, CIE, 1 << d->hwirq);
 }
 
 static void intc_ack(struct irq_data *d)
 {
+	struct xintc_irq_chip *local_intc = irq_data_get_irq_chip_data(d);
+
 	pr_debug("irq-xilinx: ack: %ld\n", d->hwirq);
-	xintc_write(IAR, 1 << d->hwirq);
+	xintc_write(local_intc, IAR, 1 << d->hwirq);
 }
 
 static void intc_mask_ack(struct irq_data *d)
 {
 	unsigned long mask = 1 << d->hwirq;
+	struct xintc_irq_chip *local_intc = irq_data_get_irq_chip_data(d);
 
 	pr_debug("irq-xilinx: disable_and_ack: %ld\n", d->hwirq);
-	xintc_write(CIE, mask);
-	xintc_write(IAR, mask);
+	xintc_write(local_intc, CIE, mask);
+	xintc_write(local_intc, IAR, mask);
 }
 
-static struct irq_chip intc_dev = {
-	.name = "Xilinx INTC",
-	.irq_unmask = intc_enable_or_unmask,
-	.irq_mask = intc_disable_or_mask,
-	.irq_ack = intc_ack,
-	.irq_mask_ack = intc_mask_ack,
-};
-
-unsigned int xintc_get_irq(void)
+static unsigned int xintc_get_irq_local(struct xintc_irq_chip *local_intc)
 {
-	unsigned int hwirq, irq = -1;
+	int hwirq, irq = -1;
 
-	hwirq = xintc_read(IVR);
+	hwirq = xintc_read(local_intc, IVR);
 	if (hwirq != -1U)
-		irq = irq_find_mapping(xintc_irqc->root_domain, hwirq);
+		irq = irq_find_mapping(local_intc->domain, hwirq);
 
 	pr_debug("irq-xilinx: hwirq=%d, irq=%d\n", hwirq, irq);
 
@@ -118,15 +144,50 @@
 
 static int xintc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
 {
-	if (xintc_irqc->intr_mask & (1 << hw)) {
-		irq_set_chip_and_handler_name(irq, &intc_dev,
+	struct xintc_irq_chip *local_intc = d->host_data;
+	u32 edge = local_intc->intr_mask & (1 << hw);
+
+	/*
+	 * Find out which irq_domain this IRQ is assigned to. If it is assigned
+	 * to root domain then do not fill chip_data and set it up in the code
+	 */
+	if (irq_get_default_host() != d)
+		irq_set_chip_data(irq, local_intc);
+	else {
+		local_intc = per_cpu_ptr(&primary_intc, 0);
+		irq_set_chip_data(irq, NULL);
+	}
+
+	if (edge) {
+#if defined(CONFIG_SMP) && defined(CONFIG_MICROBLAZE)
+		irq_set_chip_and_handler_name(irq, local_intc->intc_dev,
+			handle_percpu_irq, "percpu");
+#else
+		irq_set_chip_and_handler_name(irq, local_intc->intc_dev,
 						handle_edge_irq, "edge");
+#endif
 		irq_clear_status_flags(irq, IRQ_LEVEL);
 	} else {
-		irq_set_chip_and_handler_name(irq, &intc_dev,
+#if defined(CONFIG_SMP) && defined(CONFIG_MICROBLAZE)
+		irq_set_chip_and_handler_name(irq, local_intc->intc_dev,
+			handle_percpu_irq, "percpu");
+#else
+		irq_set_chip_and_handler_name(irq, local_intc->intc_dev,
 						handle_level_irq, "level");
+#endif
 		irq_set_status_flags(irq, IRQ_LEVEL);
 	}
+
+	/*
+	 * Setup all IRQs to be per CPU because servicing it by different
+	 * cpu is not implemented yet. And for uniprocessor system this flag
+	 * is nop all time time.
+	 */
+	irq_set_status_flags(irq, IRQ_PER_CPU);
+
+	pr_debug("cpu: %u, xintc_map: hwirq=%u, irq=%u, edge=%u\n",
+		 smp_processor_id(), (u32)hw, irq, edge);
+
 	return 0;
 }
 
@@ -135,14 +196,45 @@
 	.map = xintc_map,
 };
 
+static void xil_intc_initial_setup(struct xintc_irq_chip *irqc)
+{
+	int i;
+	u32 mask;
+
+	/*
+	 * Disable all external interrupts until they are
+	 * explicity requested.
+	 */
+	xintc_write(irqc, IER, 0);
+
+	/* Acknowledge any pending interrupts just in case. */
+	xintc_write(irqc, IAR, 0xffffffff);
+
+	/* Turn on the Master Enable. */
+	xintc_write(irqc, MER, MER_HIE | MER_ME);
+	if (!(xintc_read(irqc, MER) & (MER_HIE | MER_ME))) {
+		static_branch_enable(&xintc_is_be);
+		xintc_write(irqc, MER, MER_HIE | MER_ME);
+	}
+
+	/* Enable all SW IRQs */
+	for (i = 0; i < irqc->sw_irq; i++) {
+		mask = 1 << (i + irqc->nr_irq);
+		xintc_write(irqc, IAR, mask);
+		xintc_write(irqc, SIE, mask);
+	}
+}
+
 static void xil_intc_irq_handler(struct irq_desc *desc)
 {
 	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct xintc_irq_chip *local_intc =
+		irq_data_get_irq_handler_data(&desc->irq_data);
 	u32 pending;
 
 	chained_irq_enter(chip, desc);
 	do {
-		pending = xintc_get_irq();
+		pending = xintc_get_irq_local(local_intc);
 		if (pending == -1U)
 			break;
 		generic_handle_irq(pending);
@@ -150,31 +242,88 @@
 	chained_irq_exit(chip, desc);
 }
 
+static int xil_intc_start(unsigned int cpu)
+{
+	struct xintc_irq_chip *irqc = per_cpu_ptr(&primary_intc, cpu);
+
+	pr_debug("%s: intc cpu %d\n", __func__, cpu);
+
+	xil_intc_initial_setup(irqc);
+
+	return 0;
+}
+
+static int xil_intc_stop(unsigned int cpu)
+{
+	pr_debug("%s: intc cpu %d\n", __func__, cpu);
+
+	return 0;
+}
+
+static void xil_intc_handle_irq(struct pt_regs *regs)
+{
+	int ret;
+	unsigned int hwirq, cpu_id = smp_processor_id();
+	struct xintc_irq_chip *irqc = per_cpu_ptr(&primary_intc, cpu_id);
+
+	do {
+		hwirq = xintc_read(irqc, IVR);
+		if (hwirq != -1U) {
+			if (hwirq >= irqc->nr_irq) {
+#if defined(CONFIG_SMP) && defined(CONFIG_MICROBLAZE)
+				handle_IPI(hwirq - irqc->nr_irq, regs);
+#else
+				WARN_ONCE(1, "SW interrupt not handled\n");
+#endif
+				/* ACK is necessary */
+				xintc_write(irqc, IAR, 1 << hwirq);
+				continue;
+			} else {
+				ret = handle_domain_irq(irqc->domain,
+							hwirq, regs);
+				WARN_ONCE(ret, "cpu %d: Unhandled HWIRQ %d\n",
+					  cpu_id, hwirq);
+				continue;
+			}
+		}
+
+		break;
+	} while (1);
+}
+
 static int __init xilinx_intc_of_init(struct device_node *intc,
 					     struct device_node *parent)
 {
-	u32 nr_irq;
 	int ret, irq;
 	struct xintc_irq_chip *irqc;
+	struct irq_chip *intc_dev;
+	u32 cpu_id = 0;
 
-	if (xintc_irqc) {
-		pr_err("irq-xilinx: Multiple instances aren't supported\n");
-		return -EINVAL;
+	ret = of_property_read_u32(intc, "cpu-id", &cpu_id);
+	if (ret < 0)
+		pr_debug("%s: %pOF: cpu_id not found\n", __func__, intc);
+
+	/* No parent means it is primary intc */
+	if (!parent) {
+		irqc = per_cpu_ptr(&primary_intc, cpu_id);
+		if (irqc->base) {
+			pr_err("%pOF: %s: cpu %d has already irq controller\n",
+				intc, __func__, cpu_id);
+			return -EINVAL;
+		}
+	} else {
+		irqc = kzalloc(sizeof(*irqc), GFP_KERNEL);
+		if (!irqc)
+			return -ENOMEM;
 	}
 
-	irqc = kzalloc(sizeof(*irqc), GFP_KERNEL);
-	if (!irqc)
-		return -ENOMEM;
-
-	xintc_irqc = irqc;
-
 	irqc->base = of_iomap(intc, 0);
 	BUG_ON(!irqc->base);
 
-	ret = of_property_read_u32(intc, "xlnx,num-intr-inputs", &nr_irq);
+	ret = of_property_read_u32(intc, "xlnx,num-intr-inputs", &irqc->nr_irq);
 	if (ret < 0) {
 		pr_err("irq-xilinx: unable to read xlnx,num-intr-inputs\n");
-		goto err_alloc;
+		goto error;
 	}
 
 	ret = of_property_read_u32(intc, "xlnx,kind-of-intr", &irqc->intr_mask);
@@ -183,33 +332,39 @@
 		irqc->intr_mask = 0;
 	}
 
-	if (irqc->intr_mask >> nr_irq)
+	if (irqc->intr_mask >> irqc->nr_irq)
 		pr_warn("irq-xilinx: mismatch in kind-of-intr param\n");
 
-	pr_info("irq-xilinx: %pOF: num_irq=%d, edge=0x%x\n",
-		intc, nr_irq, irqc->intr_mask);
+	/* sw irqs are optinal */
+	of_property_read_u32(intc, "xlnx,num-sw-intr", &irqc->sw_irq);
 
+	pr_info("irq-xilinx: %pOF: num_irq=%d, sw_irq=%d, edge=0x%x\n",
+		intc, irqc->nr_irq, irqc->sw_irq, irqc->intr_mask);
 
-	/*
-	 * Disable all external interrupts until they are
-	 * explicity requested.
-	 */
-	xintc_write(IER, 0);
-
-	/* Acknowledge any pending interrupts just in case. */
-	xintc_write(IAR, 0xffffffff);
+	/* Right now enable only SW IRQs on that IP and wait */
+	if (cpu_id) {
+		xil_intc_initial_setup(irqc);
+		return 0;
+	}
 
-	/* Turn on the Master Enable. */
-	xintc_write(MER, MER_HIE | MER_ME);
-	if (!(xintc_read(MER) & (MER_HIE | MER_ME))) {
-		static_branch_enable(&xintc_is_be);
-		xintc_write(MER, MER_HIE | MER_ME);
+	intc_dev = kzalloc(sizeof(*intc_dev), GFP_KERNEL);
+	if (!intc_dev) {
+		ret = -ENOMEM;
+		goto error;
 	}
 
-	irqc->root_domain = irq_domain_add_linear(intc, nr_irq,
+	intc_dev->name = intc->full_name;
+	intc_dev->irq_unmask = intc_enable_or_unmask,
+	intc_dev->irq_mask = intc_disable_or_mask,
+	intc_dev->irq_ack = intc_ack,
+	intc_dev->irq_mask_ack = intc_mask_ack,
+	irqc->intc_dev = intc_dev;
+
+	irqc->domain = irq_domain_add_linear(intc, irqc->nr_irq,
 						  &xintc_irq_domain_ops, irqc);
-	if (!irqc->root_domain) {
+	if (!irqc->domain) {
 		pr_err("irq-xilinx: Unable to create IRQ domain\n");
+		ret = -EINVAL;
 		goto err_alloc;
 	}
 
@@ -224,17 +379,34 @@
 			ret = -EINVAL;
 			goto err_alloc;
 		}
-	} else {
-		irq_set_default_host(irqc->root_domain);
+		xil_intc_initial_setup(irqc);
+		return 0;
 	}
 
-	return 0;
+	/*
+	 * Set default domain here because for other root intc
+	 * irq_find_mapping() will use irq_default_domain as fallback
+	 */
+	irq_set_default_host(irqc->domain);
+	set_handle_irq(xil_intc_handle_irq);
+
+	ret = cpuhp_setup_state(CPUHP_AP_IRQ_XILINX_STARTING,
+				"microblaze/arch_intc:starting",
+				xil_intc_start, xil_intc_stop);
+
+#if defined(CONFIG_SMP) && defined(CONFIG_MICROBLAZE)
+	set_smp_cross_call(send_ipi);
+#endif
 
-err_alloc:
-	xintc_irqc = NULL;
-	kfree(irqc);
 	return ret;
 
+err_alloc:
+	kfree(intc_dev);
+error:
+	iounmap(irqc->base);
+	if (parent)
+		kfree(irqc);
+	return ret;
 }
 
 IRQCHIP_DECLARE(xilinx_intc_xps, "xlnx,xps-intc-1.00.a", xilinx_intc_of_init);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/irq-xtensa-mx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/irq-xtensa-mx.c
@@ -151,14 +151,25 @@
 	.irq_set_affinity = xtensa_mx_irq_set_affinity,
 };
 
+static void __init xtensa_mx_init_common(struct irq_domain *root_domain)
+{
+	unsigned int i;
+
+	irq_set_default_host(root_domain);
+	secondary_init_irq();
+
+	/* Initialize default IRQ routing to CPU 0 */
+	for (i = 0; i < XCHAL_NUM_EXTINTERRUPTS; ++i)
+		set_er(1, MIROUT(i));
+}
+
 int __init xtensa_mx_init_legacy(struct device_node *interrupt_parent)
 {
 	struct irq_domain *root_domain =
 		irq_domain_add_legacy(NULL, NR_IRQS - 1, 1, 0,
 				&xtensa_mx_irq_domain_ops,
 				&xtensa_mx_irq_chip);
-	irq_set_default_host(root_domain);
-	secondary_init_irq();
+	xtensa_mx_init_common(root_domain);
 	return 0;
 }
 
@@ -168,8 +179,7 @@
 	struct irq_domain *root_domain =
 		irq_domain_add_linear(np, NR_IRQS, &xtensa_mx_irq_domain_ops,
 				&xtensa_mx_irq_chip);
-	irq_set_default_host(root_domain);
-	secondary_init_irq();
+	xtensa_mx_init_common(root_domain);
 	return 0;
 }
 IRQCHIP_DECLARE(xtensa_mx_irq_chip, "cdns,xtensa-mx", xtensa_mx_init);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/irqchip/qcom-pdc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/irqchip/qcom-pdc.c
@@ -50,17 +50,18 @@
 static void pdc_enable_intr(struct irq_data *d, bool on)
 {
 	int pin_out = d->hwirq;
+	unsigned long flags;
 	u32 index, mask;
 	u32 enable;
 
 	index = pin_out / 32;
 	mask = pin_out % 32;
 
-	raw_spin_lock(&pdc_lock);
+	raw_spin_lock_irqsave(&pdc_lock, flags);
 	enable = pdc_reg_read(IRQ_ENABLE_BANK, index);
 	enable = on ? ENABLE_INTR(enable, mask) : CLEAR_INTR(enable, mask);
 	pdc_reg_write(IRQ_ENABLE_BANK, index, enable);
-	raw_spin_unlock(&pdc_lock);
+	raw_spin_unlock_irqrestore(&pdc_lock, flags);
 }
 
 static void qcom_pdc_gic_mask(struct irq_data *d)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/isdn/capi/kcapi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/isdn/capi/kcapi.c
@@ -565,6 +565,11 @@
 
 	ctr_down(ctr, CAPI_CTR_DETACHED);
 
+	if (ctr->cnr < 1 || ctr->cnr - 1 >= CAPI_MAXCONTR) {
+		err = -EINVAL;
+		goto unlock_out;
+	}
+
 	if (capi_controller[ctr->cnr - 1] != ctr) {
 		err = -EINVAL;
 		goto unlock_out;
@@ -846,7 +851,7 @@
  * Return value: CAPI result code
  */
 
-u16 capi20_get_manufacturer(u32 contr, u8 *buf)
+u16 capi20_get_manufacturer(u32 contr, u8 buf[CAPI_MANUFACTURER_LEN])
 {
 	struct capi_ctr *ctr;
 	u16 ret;
@@ -916,7 +921,7 @@
  * Return value: CAPI result code
  */
 
-u16 capi20_get_serial(u32 contr, u8 *serial)
+u16 capi20_get_serial(u32 contr, u8 serial[CAPI_SERIAL_LEN])
 {
 	struct capi_ctr *ctr;
 	u16 ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/isdn/hardware/mISDN/hfcmulti.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/isdn/hardware/mISDN/hfcmulti.c
@@ -1931,7 +1931,7 @@
 static void
 hfcmulti_tx(struct hfc_multi *hc, int ch)
 {
-	int i, ii, temp, len = 0;
+	int i, ii, temp, tmp_len, len = 0;
 	int Zspace, z1, z2; /* must be int for calculation */
 	int Fspace, f1, f2;
 	u_char *d;
@@ -2152,14 +2152,15 @@
 		HFC_wait_nodebug(hc);
 	}
 
+	tmp_len = (*sp)->len;
 	dev_kfree_skb(*sp);
 	/* check for next frame */
 	if (bch && get_next_bframe(bch)) {
-		len = (*sp)->len;
+		len = tmp_len;
 		goto next_frame;
 	}
 	if (dch && get_next_dframe(dch)) {
-		len = (*sp)->len;
+		len = tmp_len;
 		goto next_frame;
 	}
 
@@ -3219,6 +3220,7 @@
 hfcm_l1callback(struct dchannel *dch, u_int cmd)
 {
 	struct hfc_multi	*hc = dch->hw;
+	struct sk_buff_head	free_queue;
 	u_long	flags;
 
 	switch (cmd) {
@@ -3247,6 +3249,7 @@
 		l1_event(dch->l1, HW_POWERUP_IND);
 		break;
 	case HW_DEACT_REQ:
+		__skb_queue_head_init(&free_queue);
 		/* start deactivation */
 		spin_lock_irqsave(&hc->lock, flags);
 		if (hc->ctype == HFC_TYPE_E1) {
@@ -3266,20 +3269,21 @@
 				plxsd_checksync(hc, 0);
 			}
 		}
-		skb_queue_purge(&dch->squeue);
+		skb_queue_splice_init(&dch->squeue, &free_queue);
 		if (dch->tx_skb) {
-			dev_kfree_skb(dch->tx_skb);
+			__skb_queue_tail(&free_queue, dch->tx_skb);
 			dch->tx_skb = NULL;
 		}
 		dch->tx_idx = 0;
 		if (dch->rx_skb) {
-			dev_kfree_skb(dch->rx_skb);
+			__skb_queue_tail(&free_queue, dch->rx_skb);
 			dch->rx_skb = NULL;
 		}
 		test_and_clear_bit(FLG_TX_BUSY, &dch->Flags);
 		if (test_and_clear_bit(FLG_BUSY_TIMER, &dch->Flags))
 			del_timer(&dch->timer);
 		spin_unlock_irqrestore(&hc->lock, flags);
+		__skb_queue_purge(&free_queue);
 		break;
 	case HW_POWERUP_REQ:
 		spin_lock_irqsave(&hc->lock, flags);
@@ -3386,6 +3390,9 @@
 	case PH_DEACTIVATE_REQ:
 		test_and_clear_bit(FLG_L2_ACTIVATED, &dch->Flags);
 		if (dch->dev.D.protocol != ISDN_P_TE_S0) {
+			struct sk_buff_head free_queue;
+
+			__skb_queue_head_init(&free_queue);
 			spin_lock_irqsave(&hc->lock, flags);
 			if (debug & DEBUG_HFCMULTI_MSG)
 				printk(KERN_DEBUG
@@ -3407,14 +3414,14 @@
 				/* deactivate */
 				dch->state = 1;
 			}
-			skb_queue_purge(&dch->squeue);
+			skb_queue_splice_init(&dch->squeue, &free_queue);
 			if (dch->tx_skb) {
-				dev_kfree_skb(dch->tx_skb);
+				__skb_queue_tail(&free_queue, dch->tx_skb);
 				dch->tx_skb = NULL;
 			}
 			dch->tx_idx = 0;
 			if (dch->rx_skb) {
-				dev_kfree_skb(dch->rx_skb);
+				__skb_queue_tail(&free_queue, dch->rx_skb);
 				dch->rx_skb = NULL;
 			}
 			test_and_clear_bit(FLG_TX_BUSY, &dch->Flags);
@@ -3426,6 +3433,7 @@
 #endif
 			ret = 0;
 			spin_unlock_irqrestore(&hc->lock, flags);
+			__skb_queue_purge(&free_queue);
 		} else
 			ret = l1_event(dch->l1, hh->prim);
 		break;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/isdn/hardware/mISDN/hfcpci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/isdn/hardware/mISDN/hfcpci.c
@@ -839,7 +839,7 @@
 		*z1t = cpu_to_le16(new_z1);	/* now send data */
 		if (bch->tx_idx < bch->tx_skb->len)
 			return;
-		dev_kfree_skb(bch->tx_skb);
+		dev_kfree_skb_any(bch->tx_skb);
 		if (get_next_bframe(bch))
 			goto next_t_frame;
 		return;
@@ -895,7 +895,7 @@
 	}
 	bz->za[new_f1].z1 = cpu_to_le16(new_z1);	/* for next buffer */
 	bz->f1 = new_f1;	/* next frame */
-	dev_kfree_skb(bch->tx_skb);
+	dev_kfree_skb_any(bch->tx_skb);
 	get_next_bframe(bch);
 }
 
@@ -1119,7 +1119,7 @@
 	if (bch->tx_skb && bch->tx_idx < bch->tx_skb->len)
 		hfcpci_fill_fifo(bch);
 	else {
-		dev_kfree_skb(bch->tx_skb);
+		dev_kfree_skb_any(bch->tx_skb);
 		if (get_next_bframe(bch))
 			hfcpci_fill_fifo(bch);
 	}
@@ -1617,16 +1617,19 @@
 		test_and_clear_bit(FLG_L2_ACTIVATED, &dch->Flags);
 		spin_lock_irqsave(&hc->lock, flags);
 		if (hc->hw.protocol == ISDN_P_NT_S0) {
+			struct sk_buff_head free_queue;
+
+			__skb_queue_head_init(&free_queue);
 			/* prepare deactivation */
 			Write_hfc(hc, HFCPCI_STATES, 0x40);
-			skb_queue_purge(&dch->squeue);
+			skb_queue_splice_init(&dch->squeue, &free_queue);
 			if (dch->tx_skb) {
-				dev_kfree_skb(dch->tx_skb);
+				__skb_queue_tail(&free_queue, dch->tx_skb);
 				dch->tx_skb = NULL;
 			}
 			dch->tx_idx = 0;
 			if (dch->rx_skb) {
-				dev_kfree_skb(dch->rx_skb);
+				__skb_queue_tail(&free_queue, dch->rx_skb);
 				dch->rx_skb = NULL;
 			}
 			test_and_clear_bit(FLG_TX_BUSY, &dch->Flags);
@@ -1639,10 +1642,12 @@
 			hc->hw.mst_m &= ~HFCPCI_MASTER;
 			Write_hfc(hc, HFCPCI_MST_MODE, hc->hw.mst_m);
 			ret = 0;
+			spin_unlock_irqrestore(&hc->lock, flags);
+			__skb_queue_purge(&free_queue);
 		} else {
 			ret = l1_event(dch->l1, hh->prim);
+			spin_unlock_irqrestore(&hc->lock, flags);
 		}
-		spin_unlock_irqrestore(&hc->lock, flags);
 		break;
 	}
 	if (!ret)
@@ -2267,7 +2272,7 @@
 		return 0;
 
 	if (hc->hw.int_m2 & HFCPCI_IRQ_ENABLE) {
-		spin_lock(&hc->lock);
+		spin_lock_irq(&hc->lock);
 		bch = Sel_BCS(hc, hc->hw.bswapped ? 2 : 1);
 		if (bch && bch->state == ISDN_P_B_RAW) { /* B1 rx&tx */
 			main_rec_hfcpci(bch);
@@ -2278,7 +2283,7 @@
 			main_rec_hfcpci(bch);
 			tx_birq(bch);
 		}
-		spin_unlock(&hc->lock);
+		spin_unlock_irq(&hc->lock);
 	}
 	return 0;
 }
@@ -2341,7 +2346,7 @@
 HFC_cleanup(void)
 {
 	if (timer_pending(&hfc_tl))
-		del_timer(&hfc_tl);
+		del_timer_sync(&hfc_tl);
 
 	pci_unregister_driver(&hfc_driver);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/isdn/hardware/mISDN/hfcsusb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/isdn/hardware/mISDN/hfcsusb.c
@@ -46,7 +46,7 @@
 static void hfcsusb_stop_endpoint(struct hfcsusb *hw, int channel);
 static int  hfcsusb_setup_bch(struct bchannel *bch, int protocol);
 static void deactivate_bchannel(struct bchannel *bch);
-static void hfcsusb_ph_info(struct hfcsusb *hw);
+static int  hfcsusb_ph_info(struct hfcsusb *hw);
 
 /* start next background transfer for control channel */
 static void
@@ -241,7 +241,7 @@
  * send full D/B channel status information
  * as MPH_INFORMATION_IND
  */
-static void
+static int
 hfcsusb_ph_info(struct hfcsusb *hw)
 {
 	struct ph_info *phi;
@@ -250,7 +250,7 @@
 
 	phi = kzalloc(struct_size(phi, bch, dch->dev.nrbchan), GFP_ATOMIC);
 	if (!phi)
-		return;
+		return -ENOMEM;
 
 	phi->dch.ch.protocol = hw->protocol;
 	phi->dch.ch.Flags = dch->Flags;
@@ -264,6 +264,8 @@
 		    sizeof(struct ph_info_dch) + dch->dev.nrbchan *
 		    sizeof(struct ph_info_ch), phi, GFP_ATOMIC);
 	kfree(phi);
+
+	return 0;
 }
 
 /*
@@ -325,20 +327,24 @@
 		test_and_clear_bit(FLG_L2_ACTIVATED, &dch->Flags);
 
 		if (hw->protocol == ISDN_P_NT_S0) {
+			struct sk_buff_head free_queue;
+
+			__skb_queue_head_init(&free_queue);
 			hfcsusb_ph_command(hw, HFC_L1_DEACTIVATE_NT);
 			spin_lock_irqsave(&hw->lock, flags);
-			skb_queue_purge(&dch->squeue);
+			skb_queue_splice_init(&dch->squeue, &free_queue);
 			if (dch->tx_skb) {
-				dev_kfree_skb(dch->tx_skb);
+				__skb_queue_tail(&free_queue, dch->tx_skb);
 				dch->tx_skb = NULL;
 			}
 			dch->tx_idx = 0;
 			if (dch->rx_skb) {
-				dev_kfree_skb(dch->rx_skb);
+				__skb_queue_tail(&free_queue, dch->rx_skb);
 				dch->rx_skb = NULL;
 			}
 			test_and_clear_bit(FLG_TX_BUSY, &dch->Flags);
 			spin_unlock_irqrestore(&hw->lock, flags);
+			__skb_queue_purge(&free_queue);
 #ifdef FIXME
 			if (test_and_clear_bit(FLG_L1_BUSY, &dch->Flags))
 				dchannel_sched_event(&hc->dch, D_CLEARBUSY);
@@ -348,8 +354,7 @@
 			ret = l1_event(dch->l1, hh->prim);
 		break;
 	case MPH_INFORMATION_REQ:
-		hfcsusb_ph_info(hw);
-		ret = 0;
+		ret = hfcsusb_ph_info(hw);
 		break;
 	}
 
@@ -404,8 +409,7 @@
 			       hw->name, __func__, cmd);
 		return -1;
 	}
-	hfcsusb_ph_info(hw);
-	return 0;
+	return hfcsusb_ph_info(hw);
 }
 
 static int
@@ -747,8 +751,7 @@
 			handle_led(hw, (bch->nr == 1) ? LED_B1_OFF :
 				   LED_B2_OFF);
 	}
-	hfcsusb_ph_info(hw);
-	return 0;
+	return hfcsusb_ph_info(hw);
 }
 
 static void
@@ -1332,7 +1335,7 @@
 					printk("\n");
 				}
 
-				dev_kfree_skb(tx_skb);
+				dev_consume_skb_irq(tx_skb);
 				tx_skb = NULL;
 				if (fifo->dch && get_next_dframe(fifo->dch))
 					tx_skb = fifo->dch->tx_skb;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/isdn/hardware/mISDN/mISDNinfineon.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/isdn/hardware/mISDN/mISDNinfineon.c
@@ -630,17 +630,19 @@
 release_io(struct inf_hw *hw)
 {
 	if (hw->cfg.mode) {
-		if (hw->cfg.p) {
+		if (hw->cfg.mode == AM_MEMIO) {
 			release_mem_region(hw->cfg.start, hw->cfg.size);
-			iounmap(hw->cfg.p);
+			if (hw->cfg.p)
+				iounmap(hw->cfg.p);
 		} else
 			release_region(hw->cfg.start, hw->cfg.size);
 		hw->cfg.mode = AM_NONE;
 	}
 	if (hw->addr.mode) {
-		if (hw->addr.p) {
+		if (hw->addr.mode == AM_MEMIO) {
 			release_mem_region(hw->addr.start, hw->addr.size);
-			iounmap(hw->addr.p);
+			if (hw->addr.p)
+				iounmap(hw->addr.p);
 		} else
 			release_region(hw->addr.start, hw->addr.size);
 		hw->addr.mode = AM_NONE;
@@ -670,9 +672,12 @@
 				(ulong)hw->cfg.start, (ulong)hw->cfg.size);
 			return err;
 		}
-		if (hw->ci->cfg_mode == AM_MEMIO)
-			hw->cfg.p = ioremap(hw->cfg.start, hw->cfg.size);
 		hw->cfg.mode = hw->ci->cfg_mode;
+		if (hw->ci->cfg_mode == AM_MEMIO) {
+			hw->cfg.p = ioremap(hw->cfg.start, hw->cfg.size);
+			if (!hw->cfg.p)
+				return -ENOMEM;
+		}
 		if (debug & DEBUG_HW)
 			pr_notice("%s: IO cfg %lx (%lu bytes) mode%d\n",
 				  hw->name, (ulong)hw->cfg.start,
@@ -697,12 +702,12 @@
 				(ulong)hw->addr.start, (ulong)hw->addr.size);
 			return err;
 		}
+		hw->addr.mode = hw->ci->addr_mode;
 		if (hw->ci->addr_mode == AM_MEMIO) {
 			hw->addr.p = ioremap(hw->addr.start, hw->addr.size);
-			if (unlikely(!hw->addr.p))
+			if (!hw->addr.p)
 				return -ENOMEM;
 		}
-		hw->addr.mode = hw->ci->addr_mode;
 		if (debug & DEBUG_HW)
 			pr_notice("%s: IO addr %lx (%lu bytes) mode%d\n",
 				  hw->name, (ulong)hw->addr.start,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/isdn/hardware/mISDN/mISDNipac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/isdn/hardware/mISDN/mISDNipac.c
@@ -694,7 +694,7 @@
 {
 	if (isac->type & IPAC_TYPE_ISACX)
 		WriteISAC(isac, ISACX_MASK, 0xff);
-	else
+	else if (isac->type != 0)
 		WriteISAC(isac, ISAC_MASK, 0xff);
 	if (isac->dch.timer.function != NULL) {
 		del_timer(&isac->dch.timer);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/isdn/hardware/mISDN/netjet.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/isdn/hardware/mISDN/netjet.c
@@ -949,14 +949,14 @@
 		nj_disable_hwirq(card);
 		mode_tiger(&card->bc[0], ISDN_P_NONE);
 		mode_tiger(&card->bc[1], ISDN_P_NONE);
-		card->isac.release(&card->isac);
 		spin_unlock_irqrestore(&card->lock, flags);
+		card->isac.release(&card->isac);
 		release_region(card->base, card->base_s);
 		card->base_s = 0;
 	}
 	if (card->irq > 0)
 		free_irq(card->irq, card);
-	if (card->isac.dch.dev.dev.class)
+	if (device_is_registered(&card->isac.dch.dev.dev))
 		mISDN_unregister_device(&card->isac.dch.dev);
 
 	for (i = 0; i < 2; i++) {
@@ -1100,7 +1100,6 @@
 		card->typ = NETJET_S_TJ300;
 
 	card->base = pci_resource_start(pdev, 0);
-	card->irq = pdev->irq;
 	pci_set_drvdata(pdev, card);
 	err = setup_instance(card);
 	if (err)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/isdn/mISDN/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/isdn/mISDN/Kconfig
@@ -13,6 +13,7 @@
 config MISDN_DSP
 	tristate "Digital Audio Processing of transparent data"
 	depends on MISDN
+	select BITREVERSE
 	help
 	  Enable support for digital audio processing capability.
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/isdn/mISDN/core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/isdn/mISDN/core.c
@@ -222,7 +222,7 @@
 
 	err = get_free_devid();
 	if (err < 0)
-		goto error1;
+		return err;
 	dev->id = err;
 
 	device_initialize(&dev->dev);
@@ -233,11 +233,12 @@
 	if (debug & DEBUG_CORE)
 		printk(KERN_DEBUG "mISDN_register %s %d\n",
 		       dev_name(&dev->dev), dev->id);
+	dev->dev.class = &mISDN_class;
+
 	err = create_stack(dev);
 	if (err)
 		goto error1;
 
-	dev->dev.class = &mISDN_class;
 	dev->dev.platform_data = dev;
 	dev->dev.parent = parent;
 	dev_set_drvdata(&dev->dev, dev);
@@ -249,8 +250,8 @@
 
 error3:
 	delete_stack(dev);
-	return err;
 error1:
+	put_device(&dev->dev);
 	return err;
 
 }
@@ -381,7 +382,7 @@
 	err = mISDN_inittimer(&debug);
 	if (err)
 		goto error2;
-	err = l1_init(&debug);
+	err = Isdnl1_Init(&debug);
 	if (err)
 		goto error3;
 	err = Isdnl2_Init(&debug);
@@ -395,7 +396,7 @@
 error5:
 	Isdnl2_cleanup();
 error4:
-	l1_cleanup();
+	Isdnl1_cleanup();
 error3:
 	mISDN_timer_cleanup();
 error2:
@@ -408,7 +409,7 @@
 {
 	misdn_sock_cleanup();
 	Isdnl2_cleanup();
-	l1_cleanup();
+	Isdnl1_cleanup();
 	mISDN_timer_cleanup();
 	class_unregister(&mISDN_class);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/isdn/mISDN/core.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/isdn/mISDN/core.h
@@ -60,8 +60,8 @@
 extern int	mISDN_inittimer(u_int *);
 extern void	mISDN_timer_cleanup(void);
 
-extern int	l1_init(u_int *);
-extern void	l1_cleanup(void);
+extern int	Isdnl1_Init(u_int *);
+extern void	Isdnl1_cleanup(void);
 extern int	Isdnl2_Init(u_int *);
 extern void	Isdnl2_cleanup(void);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/isdn/mISDN/dsp.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/isdn/mISDN/dsp.h
@@ -247,7 +247,7 @@
 extern int dsp_cmx_conf(struct dsp *dsp, u32 conf_id);
 extern void dsp_cmx_receive(struct dsp *dsp, struct sk_buff *skb);
 extern void dsp_cmx_hdlc(struct dsp *dsp, struct sk_buff *skb);
-extern void dsp_cmx_send(void *arg);
+extern void dsp_cmx_send(struct timer_list *arg);
 extern void dsp_cmx_transmit(struct dsp *dsp, struct sk_buff *skb);
 extern int dsp_cmx_del_conf_member(struct dsp *dsp);
 extern int dsp_cmx_del_conf(struct dsp_conf *conf);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/isdn/mISDN/dsp_cmx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/isdn/mISDN/dsp_cmx.c
@@ -1625,7 +1625,7 @@
 static int	dsp_count_valid; /* if we have last sample count */
 
 void
-dsp_cmx_send(void *arg)
+dsp_cmx_send(struct timer_list *arg)
 {
 	struct dsp_conf *conf;
 	struct dsp_conf_member *member;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/isdn/mISDN/dsp_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/isdn/mISDN/dsp_core.c
@@ -1200,7 +1200,7 @@
 	}
 
 	/* set sample timer */
-	timer_setup(&dsp_spl_tl, (void *)dsp_cmx_send, 0);
+	timer_setup(&dsp_spl_tl, dsp_cmx_send, 0);
 	dsp_spl_tl.expires = jiffies + dsp_tics;
 	dsp_spl_jiffies = dsp_spl_tl.expires;
 	add_timer(&dsp_spl_tl);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/isdn/mISDN/dsp_pipeline.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/isdn/mISDN/dsp_pipeline.c
@@ -80,6 +80,7 @@
 	if (!entry)
 		return -ENOMEM;
 
+	INIT_LIST_HEAD(&entry->list);
 	entry->elem = elem;
 
 	entry->dev.class = elements_class;
@@ -114,7 +115,7 @@
 	device_unregister(&entry->dev);
 	return ret;
 err1:
-	kfree(entry);
+	put_device(&entry->dev);
 	return ret;
 }
 EXPORT_SYMBOL(mISDN_dsp_element_register);
@@ -219,7 +220,7 @@
 int dsp_pipeline_build(struct dsp_pipeline *pipeline, const char *cfg)
 {
 	int incomplete = 0, found = 0;
-	char *dup, *tok, *name, *args;
+	char *dup, *next, *tok, *name, *args;
 	struct dsp_element_entry *entry, *n;
 	struct dsp_pipeline_entry *pipeline_entry;
 	struct mISDN_dsp_element *elem;
@@ -230,10 +231,10 @@
 	if (!list_empty(&pipeline->list))
 		_dsp_pipeline_destroy(pipeline);
 
-	dup = kstrdup(cfg, GFP_ATOMIC);
+	dup = next = kstrdup(cfg, GFP_ATOMIC);
 	if (!dup)
 		return 0;
-	while ((tok = strsep(&dup, "|"))) {
+	while ((tok = strsep(&next, "|"))) {
 		if (!strlen(tok))
 			continue;
 		name = strsep(&tok, "(");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/isdn/mISDN/l1oip.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/isdn/mISDN/l1oip.h
@@ -59,6 +59,7 @@
 	int			bundle;		/* bundle channels in one frm */
 	int			codec;		/* codec to use for transmis. */
 	int			limit;		/* limit number of bchannels */
+	bool			shutdown;	/* if card is released */
 
 	/* timer */
 	struct timer_list	keep_tl;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/isdn/mISDN/l1oip_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/isdn/mISDN/l1oip_core.c
@@ -275,7 +275,7 @@
 	p = frame;
 
 	/* restart timer */
-	if (time_before(hc->keep_tl.expires, jiffies + 5 * HZ))
+	if (time_before(hc->keep_tl.expires, jiffies + 5 * HZ) && !hc->shutdown)
 		mod_timer(&hc->keep_tl, jiffies + L1OIP_KEEPALIVE * HZ);
 	else
 		hc->keep_tl.expires = jiffies + L1OIP_KEEPALIVE * HZ;
@@ -601,7 +601,9 @@
 		goto multiframe;
 
 	/* restart timer */
-	if (time_before(hc->timeout_tl.expires, jiffies + 5 * HZ) || !hc->timeout_on) {
+	if ((time_before(hc->timeout_tl.expires, jiffies + 5 * HZ) ||
+	     !hc->timeout_on) &&
+	    !hc->shutdown) {
 		hc->timeout_on = 1;
 		mod_timer(&hc->timeout_tl, jiffies + L1OIP_TIMEOUT * HZ);
 	} else /* only adjust timer */
@@ -1232,11 +1234,10 @@
 {
 	int	ch;
 
-	if (timer_pending(&hc->keep_tl))
-		del_timer(&hc->keep_tl);
+	hc->shutdown = true;
 
-	if (timer_pending(&hc->timeout_tl))
-		del_timer(&hc->timeout_tl);
+	del_timer_sync(&hc->keep_tl);
+	del_timer_sync(&hc->timeout_tl);
 
 	cancel_work_sync(&hc->workq);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/isdn/mISDN/layer1.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/isdn/mISDN/layer1.c
@@ -398,7 +398,7 @@
 EXPORT_SYMBOL(create_l1);
 
 int
-l1_init(u_int *deb)
+Isdnl1_Init(u_int *deb)
 {
 	debug = deb;
 	l1fsm_s.state_count = L1S_STATE_COUNT;
@@ -409,7 +409,7 @@
 }
 
 void
-l1_cleanup(void)
+Isdnl1_cleanup(void)
 {
 	mISDN_FsmFree(&l1fsm_s);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/leds/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/leds/Kconfig
@@ -144,6 +144,7 @@
 
 config LEDS_LM3532
 	tristate "LCD Backlight driver for LM3532"
+	select REGMAP_I2C
 	depends on LEDS_CLASS
 	depends on I2C
 	help
@@ -344,7 +345,6 @@
 	tristate "Common Driver for TI/National LP5521/5523/55231/5562/8501"
 	depends on LEDS_LP5521 || LEDS_LP5523 || LEDS_LP5562 || LEDS_LP8501
 	select FW_LOADER
-	select FW_LOADER_USER_HELPER
 	help
 	  This option supports common operations for LP5521/5523/55231/5562/8501
 	  devices.
@@ -801,7 +801,7 @@
 config LEDS_TI_LMU_COMMON
 	tristate "LED driver for TI LMU"
 	depends on LEDS_CLASS
-	depends on REGMAP
+	select REGMAP
 	help
 	  Say Y to enable the LED driver for TI LMU devices.
 	  This supports common features between the TI LM3532, LM3631, LM3632,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/leds/led-class.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/leds/led-class.c
@@ -27,11 +27,14 @@
 		struct device_attribute *attr, char *buf)
 {
 	struct led_classdev *led_cdev = dev_get_drvdata(dev);
+	unsigned int brightness;
 
-	/* no lock needed for this */
+	mutex_lock(&led_cdev->led_access);
 	led_update_brightness(led_cdev);
+	brightness = led_cdev->brightness;
+	mutex_unlock(&led_cdev->led_access);
 
-	return sprintf(buf, "%u\n", led_cdev->brightness);
+	return sprintf(buf, "%u\n", brightness);
 }
 
 static ssize_t brightness_store(struct device *dev,
@@ -68,8 +71,13 @@
 		struct device_attribute *attr, char *buf)
 {
 	struct led_classdev *led_cdev = dev_get_drvdata(dev);
+	unsigned int max_brightness;
+
+	mutex_lock(&led_cdev->led_access);
+	max_brightness = led_cdev->max_brightness;
+	mutex_unlock(&led_cdev->led_access);
 
-	return sprintf(buf, "%u\n", led_cdev->max_brightness);
+	return sprintf(buf, "%u\n", max_brightness);
 }
 static DEVICE_ATTR_RO(max_brightness);
 
@@ -172,6 +180,7 @@
 {
 	led_cdev->flags |= LED_SUSPENDED;
 	led_set_brightness_nopm(led_cdev, 0);
+	flush_work(&led_cdev->set_brightness_work);
 }
 EXPORT_SYMBOL_GPL(led_classdev_suspend);
 
@@ -281,7 +290,7 @@
 
 	if (ret)
 		dev_warn(parent, "Led %s renamed to %s due to name collision",
-				led_cdev->name, dev_name(led_cdev->dev));
+				proposed_name, dev_name(led_cdev->dev));
 
 	if (led_cdev->flags & LED_BRIGHT_HW_CHANGED) {
 		ret = led_add_brightness_hw_changed(led_cdev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/leds/led-triggers.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/leds/led-triggers.c
@@ -121,9 +121,9 @@
 			flags);
 		cancel_work_sync(&led_cdev->set_brightness_work);
 		led_stop_software_blink(led_cdev);
+		device_remove_groups(led_cdev->dev, led_cdev->trigger->groups);
 		if (led_cdev->trigger->deactivate)
 			led_cdev->trigger->deactivate(led_cdev);
-		device_remove_groups(led_cdev->dev, led_cdev->trigger->groups);
 		led_cdev->trigger = NULL;
 		led_cdev->trigger_data = NULL;
 		led_cdev->activated = false;
@@ -318,14 +318,15 @@
 			enum led_brightness brightness)
 {
 	struct led_classdev *led_cdev;
+	unsigned long flags;
 
 	if (!trig)
 		return;
 
-	read_lock(&trig->leddev_list_lock);
+	read_lock_irqsave(&trig->leddev_list_lock, flags);
 	list_for_each_entry(led_cdev, &trig->led_cdevs, trig_list)
 		led_set_brightness(led_cdev, brightness);
-	read_unlock(&trig->leddev_list_lock);
+	read_unlock_irqrestore(&trig->leddev_list_lock, flags);
 }
 EXPORT_SYMBOL_GPL(led_trigger_event);
 
@@ -336,11 +337,12 @@
 			     int invert)
 {
 	struct led_classdev *led_cdev;
+	unsigned long flags;
 
 	if (!trig)
 		return;
 
-	read_lock(&trig->leddev_list_lock);
+	read_lock_irqsave(&trig->leddev_list_lock, flags);
 	list_for_each_entry(led_cdev, &trig->led_cdevs, trig_list) {
 		if (oneshot)
 			led_blink_set_oneshot(led_cdev, delay_on, delay_off,
@@ -348,7 +350,7 @@
 		else
 			led_blink_set(led_cdev, delay_on, delay_off);
 	}
-	read_unlock(&trig->leddev_list_lock);
+	read_unlock_irqrestore(&trig->leddev_list_lock, flags);
 }
 
 void led_trigger_blink(struct led_trigger *trig,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/leds/leds-88pm860x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/leds/leds-88pm860x.c
@@ -203,21 +203,33 @@
 	data->cdev.brightness_set_blocking = pm860x_led_set;
 	mutex_init(&data->lock);
 
-	ret = devm_led_classdev_register(chip->dev, &data->cdev);
+	ret = led_classdev_register(chip->dev, &data->cdev);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "Failed to register LED: %d\n", ret);
 		return ret;
 	}
 	pm860x_led_set(&data->cdev, 0);
+
+	platform_set_drvdata(pdev, data);
+
 	return 0;
 }
 
+static int pm860x_led_remove(struct platform_device *pdev)
+{
+	struct pm860x_led *data = platform_get_drvdata(pdev);
+
+	led_classdev_unregister(&data->cdev);
+
+	return 0;
+}
 
 static struct platform_driver pm860x_led_driver = {
 	.driver	= {
 		.name	= "88pm860x-led",
 	},
 	.probe	= pm860x_led_probe,
+	.remove	= pm860x_led_remove,
 };
 
 module_platform_driver(pm860x_led_driver);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/leds/leds-an30259a.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/leds/leds-an30259a.c
@@ -305,6 +305,13 @@
 
 	chip->regmap = devm_regmap_init_i2c(client, &an30259a_regmap_config);
 
+	if (IS_ERR(chip->regmap)) {
+		err = PTR_ERR(chip->regmap);
+		dev_err(&client->dev, "Failed to allocate register map: %d\n",
+			err);
+		goto exit;
+	}
+
 	for (i = 0; i < chip->num_leds; i++) {
 		struct led_init_data init_data = {};
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/leds/leds-as3645a.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/leds/leds-as3645a.c
@@ -544,6 +544,7 @@
 	if (!flash->indicator_node) {
 		dev_warn(&flash->client->dev,
 			 "can't find indicator node\n");
+		rval = -ENODEV;
 		goto out_err;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/leds/leds-bcm6328.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/leds/leds-bcm6328.c
@@ -332,7 +332,7 @@
 	led->cdev.brightness_set = bcm6328_led_set;
 	led->cdev.blink_set = bcm6328_blink_set;
 
-	rc = led_classdev_register(dev, &led->cdev);
+	rc = devm_led_classdev_register(dev, &led->cdev);
 	if (rc < 0)
 		return rc;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/leds/leds-bcm6358.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/leds/leds-bcm6358.c
@@ -137,7 +137,7 @@
 
 	led->cdev.brightness_set = bcm6358_led_set;
 
-	rc = led_classdev_register(dev, &led->cdev);
+	rc = devm_led_classdev_register(dev, &led->cdev);
 	if (rc < 0)
 		return rc;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/leds/leds-da903x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/leds/leds-da903x.c
@@ -110,12 +110,23 @@
 	led->flags = pdata->flags;
 	led->master = pdev->dev.parent;
 
-	ret = devm_led_classdev_register(led->master, &led->cdev);
+	ret = led_classdev_register(led->master, &led->cdev);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to register LED %d\n", id);
 		return ret;
 	}
 
+	platform_set_drvdata(pdev, led);
+
+	return 0;
+}
+
+static int da903x_led_remove(struct platform_device *pdev)
+{
+	struct da903x_led *led = platform_get_drvdata(pdev);
+
+	led_classdev_unregister(&led->cdev);
+
 	return 0;
 }
 
@@ -124,6 +135,7 @@
 		.name	= "da903x-led",
 	},
 	.probe		= da903x_led_probe,
+	.remove		= da903x_led_remove,
 };
 
 module_platform_driver(da903x_led_driver);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/leds/leds-gpio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/leds/leds-gpio.c
@@ -151,9 +151,14 @@
 		struct gpio_led led = {};
 		const char *state = NULL;
 
+		/*
+		 * Acquire gpiod from DT with uninitialized label, which
+		 * will be updated after LED class device is registered,
+		 * Only then the final LED name is known.
+		 */
 		led.gpiod = devm_fwnode_get_gpiod_from_child(dev, NULL, child,
 							     GPIOD_ASIS,
-							     led.name);
+							     NULL);
 		if (IS_ERR(led.gpiod)) {
 			fwnode_handle_put(child);
 			return ERR_CAST(led.gpiod);
@@ -186,6 +191,9 @@
 			fwnode_handle_put(child);
 			return ERR_PTR(ret);
 		}
+		/* Set gpiod label to match the corresponding LED name. */
+		gpiod_set_consumer_name(led_dat->gpiod,
+					led_dat->cdev.dev->kobj.name);
 		priv->num_leds++;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/leds/leds-ktd2692.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/leds/leds-ktd2692.c
@@ -256,6 +256,17 @@
 				 | KTD2692_REG_FLASH_CURRENT_BASE);
 }
 
+static void regulator_disable_action(void *_data)
+{
+	struct device *dev = _data;
+	struct ktd2692_context *led = dev_get_drvdata(dev);
+	int ret;
+
+	ret = regulator_disable(led->regulator);
+	if (ret)
+		dev_err(dev, "Failed to disable supply: %d\n", ret);
+}
+
 static int ktd2692_parse_dt(struct ktd2692_context *led, struct device *dev,
 			    struct ktd2692_led_config_data *cfg)
 {
@@ -286,8 +297,14 @@
 
 	if (led->regulator) {
 		ret = regulator_enable(led->regulator);
-		if (ret)
+		if (ret) {
 			dev_err(dev, "Failed to enable supply: %d\n", ret);
+		} else {
+			ret = devm_add_action_or_reset(dev,
+						regulator_disable_action, dev);
+			if (ret)
+				return ret;
+		}
 	}
 
 	child_node = of_get_next_available_child(np, NULL);
@@ -377,17 +394,9 @@
 static int ktd2692_remove(struct platform_device *pdev)
 {
 	struct ktd2692_context *led = platform_get_drvdata(pdev);
-	int ret;
 
 	led_classdev_flash_unregister(&led->fled_cdev);
 
-	if (led->regulator) {
-		ret = regulator_disable(led->regulator);
-		if (ret)
-			dev_err(&pdev->dev,
-				"Failed to disable supply: %d\n", ret);
-	}
-
 	mutex_destroy(&led->lock);
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/leds/leds-lm3533.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/leds/leds-lm3533.c
@@ -694,7 +694,7 @@
 
 	platform_set_drvdata(pdev, led);
 
-	ret = devm_led_classdev_register(pdev->dev.parent, &led->cdev);
+	ret = led_classdev_register(pdev->dev.parent, &led->cdev);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to register LED %d\n", pdev->id);
 		return ret;
@@ -704,13 +704,18 @@
 
 	ret = lm3533_led_setup(led, pdata);
 	if (ret)
-		return ret;
+		goto err_deregister;
 
 	ret = lm3533_ctrlbank_enable(&led->cb);
 	if (ret)
-		return ret;
+		goto err_deregister;
 
 	return 0;
+
+err_deregister:
+	led_classdev_unregister(&led->cdev);
+
+	return ret;
 }
 
 static int lm3533_led_remove(struct platform_device *pdev)
@@ -720,6 +725,7 @@
 	dev_dbg(&pdev->dev, "%s\n", __func__);
 
 	lm3533_ctrlbank_disable(&led->cb);
+	led_classdev_unregister(&led->cdev);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/leds/leds-lm355x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/leds/leds-lm355x.c
@@ -165,18 +165,19 @@
 	/* input and output pins configuration */
 	switch (chip->type) {
 	case CHIP_LM3554:
-		reg_val = pdata->pin_tx2 | pdata->ntc_pin;
+		reg_val = (u32)pdata->pin_tx2 | (u32)pdata->ntc_pin;
 		ret = regmap_update_bits(chip->regmap, 0xE0, 0x28, reg_val);
 		if (ret < 0)
 			goto out;
-		reg_val = pdata->pass_mode;
+		reg_val = (u32)pdata->pass_mode;
 		ret = regmap_update_bits(chip->regmap, 0xA0, 0x04, reg_val);
 		if (ret < 0)
 			goto out;
 		break;
 
 	case CHIP_LM3556:
-		reg_val = pdata->pin_tx2 | pdata->ntc_pin | pdata->pass_mode;
+		reg_val = (u32)pdata->pin_tx2 | (u32)pdata->ntc_pin |
+		          (u32)pdata->pass_mode;
 		ret = regmap_update_bits(chip->regmap, 0x0A, 0xC4, reg_val);
 		if (ret < 0)
 			goto out;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/leds/leds-lm36274.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/leds/leds-lm36274.c
@@ -41,37 +41,36 @@
 };
 
 static int lm36274_brightness_set(struct led_classdev *led_cdev,
-				enum led_brightness brt_val)
+				  enum led_brightness brt_val)
 {
-	struct lm36274 *led = container_of(led_cdev, struct lm36274, led_dev);
+	struct lm36274 *chip = container_of(led_cdev, struct lm36274, led_dev);
 
-	return ti_lmu_common_set_brightness(&led->lmu_data, brt_val);
+	return ti_lmu_common_set_brightness(&chip->lmu_data, brt_val);
 }
 
-static int lm36274_init(struct lm36274 *lm36274_data)
+static int lm36274_init(struct lm36274 *chip)
 {
 	int enable_val = 0;
 	int i;
 
-	for (i = 0; i < lm36274_data->num_leds; i++)
-		enable_val |= (1 << lm36274_data->led_sources[i]);
+	for (i = 0; i < chip->num_leds; i++)
+		enable_val |= (1 << chip->led_sources[i]);
 
 	if (!enable_val) {
-		dev_err(lm36274_data->dev, "No LEDs were enabled\n");
+		dev_err(chip->dev, "No LEDs were enabled\n");
 		return -EINVAL;
 	}
 
 	enable_val |= LM36274_BL_EN;
 
-	return regmap_write(lm36274_data->regmap, LM36274_REG_BL_EN,
-			    enable_val);
+	return regmap_write(chip->regmap, LM36274_REG_BL_EN, enable_val);
 }
 
-static int lm36274_parse_dt(struct lm36274 *lm36274_data)
+static int lm36274_parse_dt(struct lm36274 *chip)
 {
 	struct fwnode_handle *child = NULL;
 	char label[LED_MAX_NAME_SIZE];
-	struct device *dev = &lm36274_data->pdev->dev;
+	struct device *dev = &chip->pdev->dev;
 	const char *name;
 	int child_cnt;
 	int ret = -EINVAL;
@@ -84,37 +83,37 @@
 	device_for_each_child_node(dev, child) {
 		ret = fwnode_property_read_string(child, "label", &name);
 		if (ret)
-			snprintf(label, sizeof(label),
-				"%s::", lm36274_data->pdev->name);
+			snprintf(label, sizeof(label), "%s::",
+				 chip->pdev->name);
 		else
-			snprintf(label, sizeof(label),
-				 "%s:%s", lm36274_data->pdev->name, name);
+			snprintf(label, sizeof(label), "%s:%s",
+				 chip->pdev->name, name);
 
-		lm36274_data->num_leds = fwnode_property_count_u32(child, "led-sources");
-		if (lm36274_data->num_leds <= 0)
+		chip->num_leds = fwnode_property_count_u32(child, "led-sources");
+		if (chip->num_leds <= 0)
 			return -ENODEV;
 
 		ret = fwnode_property_read_u32_array(child, "led-sources",
-						     lm36274_data->led_sources,
-						     lm36274_data->num_leds);
+						     chip->led_sources,
+						     chip->num_leds);
 		if (ret) {
 			dev_err(dev, "led-sources property missing\n");
 			return ret;
 		}
 
 		fwnode_property_read_string(child, "linux,default-trigger",
-					&lm36274_data->led_dev.default_trigger);
+					    &chip->led_dev.default_trigger);
 
 	}
 
-	lm36274_data->lmu_data.regmap = lm36274_data->regmap;
-	lm36274_data->lmu_data.max_brightness = MAX_BRIGHTNESS_11BIT;
-	lm36274_data->lmu_data.msb_brightness_reg = LM36274_REG_BRT_MSB;
-	lm36274_data->lmu_data.lsb_brightness_reg = LM36274_REG_BRT_LSB;
-
-	lm36274_data->led_dev.name = label;
-	lm36274_data->led_dev.max_brightness = MAX_BRIGHTNESS_11BIT;
-	lm36274_data->led_dev.brightness_set_blocking = lm36274_brightness_set;
+	chip->lmu_data.regmap = chip->regmap;
+	chip->lmu_data.max_brightness = MAX_BRIGHTNESS_11BIT;
+	chip->lmu_data.msb_brightness_reg = LM36274_REG_BRT_MSB;
+	chip->lmu_data.lsb_brightness_reg = LM36274_REG_BRT_LSB;
+
+	chip->led_dev.name = label;
+	chip->led_dev.max_brightness = MAX_BRIGHTNESS_11BIT;
+	chip->led_dev.brightness_set_blocking = lm36274_brightness_set;
 
 	return 0;
 }
@@ -122,33 +121,40 @@
 static int lm36274_probe(struct platform_device *pdev)
 {
 	struct ti_lmu *lmu = dev_get_drvdata(pdev->dev.parent);
-	struct lm36274 *lm36274_data;
+	struct lm36274 *chip;
 	int ret;
 
-	lm36274_data = devm_kzalloc(&pdev->dev, sizeof(*lm36274_data),
-				    GFP_KERNEL);
-	if (!lm36274_data)
+	chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
+	if (!chip)
 		return -ENOMEM;
 
-	lm36274_data->pdev = pdev;
-	lm36274_data->dev = lmu->dev;
-	lm36274_data->regmap = lmu->regmap;
-	dev_set_drvdata(&pdev->dev, lm36274_data);
+	chip->pdev = pdev;
+	chip->dev = lmu->dev;
+	chip->regmap = lmu->regmap;
+	platform_set_drvdata(pdev, chip);
 
-	ret = lm36274_parse_dt(lm36274_data);
+	ret = lm36274_parse_dt(chip);
 	if (ret) {
-		dev_err(lm36274_data->dev, "Failed to parse DT node\n");
+		dev_err(chip->dev, "Failed to parse DT node\n");
 		return ret;
 	}
 
-	ret = lm36274_init(lm36274_data);
+	ret = lm36274_init(chip);
 	if (ret) {
-		dev_err(lm36274_data->dev, "Failed to init the device\n");
+		dev_err(chip->dev, "Failed to init the device\n");
 		return ret;
 	}
 
-	return devm_led_classdev_register(lm36274_data->dev,
-					 &lm36274_data->led_dev);
+	return led_classdev_register(chip->dev, &chip->led_dev);
+}
+
+static int lm36274_remove(struct platform_device *pdev)
+{
+	struct lm36274 *chip = platform_get_drvdata(pdev);
+
+	led_classdev_unregister(&chip->led_dev);
+
+	return 0;
 }
 
 static const struct of_device_id of_lm36274_leds_match[] = {
@@ -159,6 +165,7 @@
 
 static struct platform_driver lm36274_driver = {
 	.probe  = lm36274_probe,
+	.remove = lm36274_remove,
 	.driver = {
 		.name = "lm36274-leds",
 	},
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/leds/leds-lm3692x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/leds/leds-lm3692x.c
@@ -334,9 +334,18 @@
 		return ret;
 	}
 
-	led->regulator = devm_regulator_get(&led->client->dev, "vled");
-	if (IS_ERR(led->regulator))
+	led->regulator = devm_regulator_get_optional(&led->client->dev, "vled");
+	if (IS_ERR(led->regulator)) {
+		ret = PTR_ERR(led->regulator);
+		if (ret != -ENODEV) {
+			if (ret != -EPROBE_DEFER)
+				dev_err(&led->client->dev,
+					"Failed to get vled regulator: %d\n",
+					ret);
+			return ret;
+		}
 		led->regulator = NULL;
+	}
 
 	child = device_get_next_child_node(&led->client->dev, child);
 	if (!child) {
@@ -349,6 +358,7 @@
 
 	ret = fwnode_property_read_u32(child, "reg", &led->led_enable);
 	if (ret) {
+		fwnode_handle_put(child);
 		dev_err(&led->client->dev, "reg DT property missing\n");
 		return ret;
 	}
@@ -359,12 +369,11 @@
 
 	ret = devm_led_classdev_register_ext(&led->client->dev, &led->led_dev,
 					     &init_data);
-	if (ret) {
+	if (ret)
 		dev_err(&led->client->dev, "led register err: %d\n", ret);
-		return ret;
-	}
 
-	return 0;
+	fwnode_handle_put(init_data.fwnode);
+	return ret;
 }
 
 static int lm3692x_probe(struct i2c_client *client,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/leds/leds-lp5523.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/leds/leds-lp5523.c
@@ -307,7 +307,7 @@
 	usleep_range(3000, 6000);
 	ret = lp55xx_read(chip, LP5523_REG_STATUS, &status);
 	if (ret)
-		return ret;
+		goto out;
 	status &= LP5523_ENG_STATUS_MASK;
 
 	if (status != LP5523_ENG_STATUS_MASK) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/leds/leds-lp8860.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/leds/leds-lp8860.c
@@ -267,7 +267,7 @@
 		goto out;
 	}
 
-	reg_count = ARRAY_SIZE(lp8860_eeprom_disp_regs) / sizeof(lp8860_eeprom_disp_regs[0]);
+	reg_count = ARRAY_SIZE(lp8860_eeprom_disp_regs);
 	for (i = 0; i < reg_count; i++) {
 		ret = regmap_write(led->eeprom_regmap,
 				lp8860_eeprom_disp_regs[i].reg,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/leds/leds-lt3593.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/leds/leds-lt3593.c
@@ -103,10 +103,9 @@
 	init_data.default_label = ":";
 
 	ret = devm_led_classdev_register_ext(dev, &led_data->cdev, &init_data);
-	if (ret < 0) {
-		fwnode_handle_put(child);
+	fwnode_handle_put(child);
+	if (ret < 0)
 		return ret;
-	}
 
 	led_data->cdev.dev->of_node = dev->of_node;
 	platform_set_drvdata(pdev, led_data);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/leds/leds-max77650.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/leds/leds-max77650.c
@@ -135,9 +135,16 @@
 	return rv;
 }
 
+static const struct of_device_id max77650_led_of_match[] = {
+	{ .compatible = "maxim,max77650-led" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, max77650_led_of_match);
+
 static struct platform_driver max77650_led_driver = {
 	.driver = {
 		.name = "max77650-led",
+		.of_match_table = max77650_led_of_match,
 	},
 	.probe = max77650_led_probe,
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/leds/leds-mlxreg.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/leds/leds-mlxreg.c
@@ -228,8 +228,8 @@
 			brightness = LED_OFF;
 			led_data->base_color = MLXREG_LED_GREEN_SOLID;
 		}
-		sprintf(led_data->led_cdev_name, "%s:%s", "mlxreg",
-			data->label);
+		snprintf(led_data->led_cdev_name, sizeof(led_data->led_cdev_name),
+			 "mlxreg:%s", data->label);
 		led_cdev->name = led_data->led_cdev_name;
 		led_cdev->brightness = brightness;
 		led_cdev->max_brightness = LED_ON;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/leds/leds-pca963x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/leds/leds-pca963x.c
@@ -40,6 +40,8 @@
 #define PCA963X_LED_PWM		0x2	/* Controlled through PWM */
 #define PCA963X_LED_GRP_PWM	0x3	/* Controlled through PWM/GRPPWM */
 
+#define PCA963X_MODE2_OUTDRV	0x04	/* Open-drain or totem pole */
+#define PCA963X_MODE2_INVRT	0x10	/* Normal or inverted direction */
 #define PCA963X_MODE2_DMBLNK	0x20	/* Enable blinking */
 
 #define PCA963X_MODE1		0x00
@@ -438,12 +440,12 @@
 						    PCA963X_MODE2);
 		/* Configure output: open-drain or totem pole (push-pull) */
 		if (pdata->outdrv == PCA963X_OPEN_DRAIN)
-			mode2 |= 0x01;
+			mode2 &= ~PCA963X_MODE2_OUTDRV;
 		else
-			mode2 |= 0x05;
+			mode2 |= PCA963X_MODE2_OUTDRV;
 		/* Configure direction: normal or inverted */
 		if (pdata->dir == PCA963X_INVERTED)
-			mode2 |= 0x10;
+			mode2 |= PCA963X_MODE2_INVRT;
 		i2c_smbus_write_byte_data(pca963x->chip->client, PCA963X_MODE2,
 					  mode2);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/leds/leds-pwm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/leds/leds-pwm.c
@@ -22,9 +22,8 @@
 struct led_pwm_data {
 	struct led_classdev	cdev;
 	struct pwm_device	*pwm;
+	struct pwm_state	pwmstate;
 	unsigned int		active_low;
-	unsigned int		period;
-	int			duty;
 };
 
 struct led_pwm_priv {
@@ -32,44 +31,29 @@
 	struct led_pwm_data leds[0];
 };
 
-static void __led_pwm_set(struct led_pwm_data *led_dat)
-{
-	int new_duty = led_dat->duty;
-
-	pwm_config(led_dat->pwm, new_duty, led_dat->period);
-
-	if (new_duty == 0)
-		pwm_disable(led_dat->pwm);
-	else
-		pwm_enable(led_dat->pwm);
-}
-
 static int led_pwm_set(struct led_classdev *led_cdev,
 		       enum led_brightness brightness)
 {
 	struct led_pwm_data *led_dat =
 		container_of(led_cdev, struct led_pwm_data, cdev);
 	unsigned int max = led_dat->cdev.max_brightness;
-	unsigned long long duty =  led_dat->period;
+	unsigned long long duty = led_dat->pwmstate.period;
 
 	duty *= brightness;
 	do_div(duty, max);
 
 	if (led_dat->active_low)
-		duty = led_dat->period - duty;
-
-	led_dat->duty = duty;
+		duty = led_dat->pwmstate.period - duty;
 
-	__led_pwm_set(led_dat);
-
-	return 0;
+	led_dat->pwmstate.duty_cycle = duty;
+	led_dat->pwmstate.enabled = true;
+	return pwm_apply_state(led_dat->pwm, &led_dat->pwmstate);
 }
 
 static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv,
 		       struct led_pwm *led, struct fwnode_handle *fwnode)
 {
 	struct led_pwm_data *led_data = &priv->leds[priv->num_leds];
-	struct pwm_args pargs;
 	int ret;
 
 	led_data->active_low = led->active_low;
@@ -93,17 +77,10 @@
 
 	led_data->cdev.brightness_set_blocking = led_pwm_set;
 
-	/*
-	 * FIXME: pwm_apply_args() should be removed when switching to the
-	 * atomic PWM API.
-	 */
-	pwm_apply_args(led_data->pwm);
-
-	pwm_get_args(led_data->pwm, &pargs);
-
-	led_data->period = pargs.period;
-	if (!led_data->period && (led->pwm_period_ns > 0))
-		led_data->period = led->pwm_period_ns;
+	pwm_init_state(led_data->pwm, &led_data->pwmstate);
+
+	if (!led_data->pwmstate.period)
+		led_data->pwmstate.period = led->pwm_period_ns;
 
 	ret = devm_led_classdev_register(dev, &led_data->cdev);
 	if (ret == 0) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/leds/leds-ss4200.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/leds/leds-ss4200.c
@@ -356,8 +356,10 @@
 
 	nas_gpio_pci_dev = dev;
 	status = pci_read_config_dword(dev, PMBASE, &g_pm_io_base);
-	if (status)
+	if (status) {
+		status = pcibios_err_to_errno(status);
 		goto out;
+	}
 	g_pm_io_base &= 0x00000ff80;
 
 	status = pci_read_config_dword(dev, GPIO_CTRL, &gc);
@@ -369,8 +371,9 @@
 	}
 
 	status = pci_read_config_dword(dev, GPIO_BASE, &nas_gpio_io_base);
-	if (0 > status) {
+	if (status) {
 		dev_info(&dev->dev, "Unable to read GPIOBASE.\n");
+		status = pcibios_err_to_errno(status);
 		goto out;
 	}
 	dev_dbg(&dev->dev, ": GPIOBASE = 0x%08x\n", nas_gpio_io_base);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/leds/leds-tlc591xx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/leds/leds-tlc591xx.c
@@ -13,6 +13,7 @@
 #include <linux/slab.h>
 
 #define TLC591XX_MAX_LEDS	16
+#define TLC591XX_MAX_BRIGHTNESS	256
 
 #define TLC591XX_REG_MODE1	0x00
 #define MODE1_RESPON_ADDR_MASK	0xF0
@@ -112,11 +113,11 @@
 	struct tlc591xx_priv *priv = led->priv;
 	int err;
 
-	switch (brightness) {
+	switch ((int)brightness) {
 	case 0:
 		err = tlc591xx_set_ledout(priv, led, LEDOUT_OFF);
 		break;
-	case LED_FULL:
+	case TLC591XX_MAX_BRIGHTNESS:
 		err = tlc591xx_set_ledout(priv, led, LEDOUT_ON);
 		break;
 	default:
@@ -157,7 +158,7 @@
 		led->priv = priv;
 		led->led_no = i;
 		led->ldev.brightness_set_blocking = tlc591xx_brightness_set;
-		led->ldev.max_brightness = LED_FULL;
+		led->ldev.max_brightness = TLC591XX_MAX_BRIGHTNESS;
 		err = led_classdev_register(dev, &led->ldev);
 		if (err < 0) {
 			dev_err(dev, "couldn't register LED %s\n",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/leds/leds-wm831x-status.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/leds/leds-wm831x-status.c
@@ -269,12 +269,23 @@
 	drvdata->cdev.blink_set = wm831x_status_blink_set;
 	drvdata->cdev.groups = wm831x_status_groups;
 
-	ret = devm_led_classdev_register(wm831x->dev, &drvdata->cdev);
+	ret = led_classdev_register(wm831x->dev, &drvdata->cdev);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "Failed to register LED: %d\n", ret);
 		return ret;
 	}
 
+	platform_set_drvdata(pdev, drvdata);
+
+	return 0;
+}
+
+static int wm831x_status_remove(struct platform_device *pdev)
+{
+	struct wm831x_status *drvdata = platform_get_drvdata(pdev);
+
+	led_classdev_unregister(&drvdata->cdev);
+
 	return 0;
 }
 
@@ -283,6 +294,7 @@
 		   .name = "wm831x-status",
 		   },
 	.probe = wm831x_status_probe,
+	.remove = wm831x_status_remove,
 };
 
 module_platform_driver(wm831x_status_driver);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/leds/trigger/ledtrig-audio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/leds/trigger/ledtrig-audio.c
@@ -6,10 +6,33 @@
 #include <linux/kernel.h>
 #include <linux/leds.h>
 #include <linux/module.h>
+#include "../leds.h"
 
-static struct led_trigger *ledtrig_audio[NUM_AUDIO_LEDS];
 static enum led_brightness audio_state[NUM_AUDIO_LEDS];
 
+static int ledtrig_audio_mute_activate(struct led_classdev *led_cdev)
+{
+	led_set_brightness_nosleep(led_cdev, audio_state[LED_AUDIO_MUTE]);
+	return 0;
+}
+
+static int ledtrig_audio_micmute_activate(struct led_classdev *led_cdev)
+{
+	led_set_brightness_nosleep(led_cdev, audio_state[LED_AUDIO_MICMUTE]);
+	return 0;
+}
+
+static struct led_trigger ledtrig_audio[NUM_AUDIO_LEDS] = {
+	[LED_AUDIO_MUTE] = {
+		.name     = "audio-mute",
+		.activate = ledtrig_audio_mute_activate,
+	},
+	[LED_AUDIO_MICMUTE] = {
+		.name     = "audio-micmute",
+		.activate = ledtrig_audio_micmute_activate,
+	},
+};
+
 enum led_brightness ledtrig_audio_get(enum led_audio type)
 {
 	return audio_state[type];
@@ -19,24 +42,22 @@
 void ledtrig_audio_set(enum led_audio type, enum led_brightness state)
 {
 	audio_state[type] = state;
-	led_trigger_event(ledtrig_audio[type], state);
+	led_trigger_event(&ledtrig_audio[type], state);
 }
 EXPORT_SYMBOL_GPL(ledtrig_audio_set);
 
 static int __init ledtrig_audio_init(void)
 {
-	led_trigger_register_simple("audio-mute",
-				    &ledtrig_audio[LED_AUDIO_MUTE]);
-	led_trigger_register_simple("audio-micmute",
-				    &ledtrig_audio[LED_AUDIO_MICMUTE]);
+	led_trigger_register(&ledtrig_audio[LED_AUDIO_MUTE]);
+	led_trigger_register(&ledtrig_audio[LED_AUDIO_MICMUTE]);
 	return 0;
 }
 module_init(ledtrig_audio_init);
 
 static void __exit ledtrig_audio_exit(void)
 {
-	led_trigger_unregister_simple(ledtrig_audio[LED_AUDIO_MUTE]);
-	led_trigger_unregister_simple(ledtrig_audio[LED_AUDIO_MICMUTE]);
+	led_trigger_unregister(&ledtrig_audio[LED_AUDIO_MUTE]);
+	led_trigger_unregister(&ledtrig_audio[LED_AUDIO_MICMUTE]);
 }
 module_exit(ledtrig_audio_exit);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/leds/trigger/ledtrig-cpu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/leds/trigger/ledtrig-cpu.c
@@ -2,14 +2,18 @@
 /*
  * ledtrig-cpu.c - LED trigger based on CPU activity
  *
- * This LED trigger will be registered for each possible CPU and named as
- * cpu0, cpu1, cpu2, cpu3, etc.
+ * This LED trigger will be registered for first 8 CPUs and named
+ * as cpu0..cpu7. There's additional trigger called cpu that
+ * is on when any CPU is active.
+ *
+ * If you want support for arbitrary number of CPUs, make it one trigger,
+ * with additional sysfs file selecting which CPU to watch.
  *
  * It can be bound to any LED just like other triggers using either a
  * board file or via sysfs interface.
  *
  * An API named ledtrig_cpu is exported for any user, who want to add CPU
- * activity indication in their code
+ * activity indication in their code.
  *
  * Copyright 2011 Linus Walleij <linus.walleij@linaro.org>
  * Copyright 2011 - 2012 Bryan Wu <bryan.wu@canonical.com>
@@ -126,7 +130,7 @@
 
 static int __init ledtrig_cpu_init(void)
 {
-	int cpu;
+	unsigned int cpu;
 	int ret;
 
 	/* Supports up to 9999 cpu cores */
@@ -145,7 +149,10 @@
 	for_each_possible_cpu(cpu) {
 		struct led_trigger_cpu *trig = &per_cpu(cpu_trig, cpu);
 
-		snprintf(trig->name, MAX_NAME_LEN, "cpu%d", cpu);
+		if (cpu >= 8)
+			continue;
+
+		snprintf(trig->name, MAX_NAME_LEN, "cpu%u", cpu);
 
 		led_trigger_register_simple(trig->name, &trig->_trig);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/leds/trigger/ledtrig-netdev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/leds/trigger/ledtrig-netdev.c
@@ -302,10 +302,12 @@
 		container_of(nb, struct led_netdev_data, notifier);
 
 	if (evt != NETDEV_UP && evt != NETDEV_DOWN && evt != NETDEV_CHANGE
-	    && evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER)
+	    && evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER
+	    && evt != NETDEV_CHANGENAME)
 		return NOTIFY_DONE;
 
 	if (!(dev == trigger_data->net_dev ||
+	      (evt == NETDEV_CHANGENAME && !strcmp(dev->name, trigger_data->device_name)) ||
 	      (evt == NETDEV_REGISTER && !strcmp(dev->name, trigger_data->device_name))))
 		return NOTIFY_DONE;
 
@@ -315,6 +317,10 @@
 
 	clear_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode);
 	switch (evt) {
+	case NETDEV_CHANGENAME:
+		if (netif_carrier_ok(dev))
+			set_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode);
+		fallthrough;
 	case NETDEV_REGISTER:
 		if (trigger_data->net_dev)
 			dev_put(trigger_data->net_dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/leds/trigger/ledtrig-panic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/leds/trigger/ledtrig-panic.c
@@ -63,10 +63,13 @@
 
 static int __init ledtrig_panic_init(void)
 {
+	led_trigger_register_simple("panic", &trigger);
+	if (!trigger)
+		return -ENOMEM;
+
 	atomic_notifier_chain_register(&panic_notifier_list,
 				       &led_trigger_panic_nb);
 
-	led_trigger_register_simple("panic", &trigger);
 	panic_blink = led_panic_blink;
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/lightnvm/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/lightnvm/Kconfig
@@ -5,7 +5,7 @@
 
 menuconfig NVM
 	bool "Open-Channel SSD target support"
-	depends on BLOCK
+	depends on BLOCK && BROKEN
 	help
 	  Say Y here to get to enable Open-channel SSDs.
 
@@ -19,6 +19,7 @@
 
 config NVM_PBLK
 	tristate "Physical Block Device Open-Channel SSD target"
+	select CRC32
 	help
 	  Allows an open-channel SSD to be exposed as a block device to the
 	  host. The target assumes the device exposes raw flash and must be
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/lightnvm/core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/lightnvm/core.c
@@ -849,11 +849,10 @@
 	rqd.ppa_addr = generic_to_dev_addr(dev, ppa);
 
 	ret = nvm_submit_io_sync_raw(dev, &rqd);
+	__free_page(page);
 	if (ret)
 		return ret;
 
-	__free_page(page);
-
 	return rqd.error;
 }
 
@@ -1316,8 +1315,9 @@
 		strlcpy(info->bmname, "gennvm", sizeof(info->bmname));
 		i++;
 
-		if (i > 31) {
-			pr_err("max 31 devices can be reported.\n");
+		if (i >= ARRAY_SIZE(devices->info)) {
+			pr_err("max %zd devices can be reported.\n",
+			       ARRAY_SIZE(devices->info));
 			break;
 		}
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/macintosh/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/macintosh/Kconfig
@@ -44,6 +44,7 @@
 config ADB_CUDA
 	bool "Support for Cuda/Egret based Macs and PowerMacs"
 	depends on (ADB || PPC_PMAC) && !PPC_PMAC64
+	select RTC_LIB
 	help
 	  This provides support for Cuda/Egret based Macintosh and
 	  Power Macintosh systems. This includes most m68k based Macs,
@@ -57,6 +58,7 @@
 config ADB_PMU
 	bool "Support for PMU based PowerMacs and PowerBooks"
 	depends on PPC_PMAC || MAC
+	select RTC_LIB
 	help
 	  On PowerBooks, iBooks, and recent iMacs and Power Macintoshes, the
 	  PMU is an embedded microprocessor whose primary function is to
@@ -67,6 +69,10 @@
 	  this device; you should do so if your machine is one of those
 	  mentioned above.
 
+config ADB_PMU_EVENT
+	def_bool y
+	depends on ADB_PMU && INPUT=y
+
 config ADB_PMU_LED
 	bool "Support for the Power/iBook front LED"
 	depends on PPC_PMAC && ADB_PMU
@@ -80,6 +86,7 @@
 
 config ADB_PMU_LED_DISK
 	bool "Use front LED as DISK LED by default"
+	depends on ATA
 	depends on ADB_PMU_LED
 	depends on LEDS_CLASS
 	select LEDS_TRIGGERS
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/macintosh/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/macintosh/Makefile
@@ -12,7 +12,8 @@
 obj-$(CONFIG_INPUT_ADBHID)	+= adbhid.o
 obj-$(CONFIG_ANSLCD)		+= ans-lcd.o
 
-obj-$(CONFIG_ADB_PMU)		+= via-pmu.o via-pmu-event.o
+obj-$(CONFIG_ADB_PMU)		+= via-pmu.o
+obj-$(CONFIG_ADB_PMU_EVENT)	+= via-pmu-event.o
 obj-$(CONFIG_ADB_PMU_LED)	+= via-pmu-led.o
 obj-$(CONFIG_PMAC_BACKLIGHT)	+= via-pmu-backlight.o
 obj-$(CONFIG_ADB_CUDA)		+= via-cuda.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/macintosh/adb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/macintosh/adb.c
@@ -647,7 +647,7 @@
 
 	switch(req->data[1]) {
 	case ADB_QUERY_GETDEVINFO:
-		if (req->nbytes < 3)
+		if (req->nbytes < 3 || req->data[2] >= 16)
 			break;
 		mutex_lock(&adb_handler_mutex);
 		req->reply[0] = adb_handler[req->data[2]].original_address;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/macintosh/macio-adb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/macintosh/macio-adb.c
@@ -106,6 +106,10 @@
 		return -ENXIO;
 	}
 	adb = ioremap(r.start, sizeof(struct adb_regs));
+	if (!adb) {
+		of_node_put(adbs);
+		return -ENOMEM;
+	}
 
 	out_8(&adb->ctrl.r, 0);
 	out_8(&adb->intr.r, 0);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/macintosh/macio_asic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/macintosh/macio_asic.c
@@ -425,7 +425,7 @@
 	if (of_device_register(&dev->ofdev) != 0) {
 		printk(KERN_DEBUG"macio: device registration error for %s!\n",
 		       dev_name(&dev->ofdev.dev));
-		kfree(dev);
+		put_device(&dev->ofdev.dev);
 		return NULL;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/macintosh/therm_windtunnel.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/macintosh/therm_windtunnel.c
@@ -300,9 +300,11 @@
 /*	i2c probing and setup						*/
 /************************************************************************/
 
-static int
-do_attach( struct i2c_adapter *adapter )
+static void do_attach(struct i2c_adapter *adapter)
 {
+	struct i2c_board_info info = { };
+	struct device_node *np;
+
 	/* scan 0x48-0x4f (DS1775) and 0x2c-2x2f (ADM1030) */
 	static const unsigned short scan_ds1775[] = {
 		0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
@@ -313,25 +315,24 @@
 		I2C_CLIENT_END
 	};
 
-	if( strncmp(adapter->name, "uni-n", 5) )
-		return 0;
-
-	if( !x.running ) {
-		struct i2c_board_info info;
+	if (x.running || strncmp(adapter->name, "uni-n", 5))
+		return;
 
-		memset(&info, 0, sizeof(struct i2c_board_info));
-		strlcpy(info.type, "therm_ds1775", I2C_NAME_SIZE);
+	np = of_find_compatible_node(adapter->dev.of_node, NULL, "MAC,ds1775");
+	if (np) {
+		of_node_put(np);
+	} else {
+		strlcpy(info.type, "MAC,ds1775", I2C_NAME_SIZE);
 		i2c_new_probed_device(adapter, &info, scan_ds1775, NULL);
+	}
 
-		strlcpy(info.type, "therm_adm1030", I2C_NAME_SIZE);
+	np = of_find_compatible_node(adapter->dev.of_node, NULL, "MAC,adm1030");
+	if (np) {
+		of_node_put(np);
+	} else {
+		strlcpy(info.type, "MAC,adm1030", I2C_NAME_SIZE);
 		i2c_new_probed_device(adapter, &info, scan_adm1030, NULL);
-
-		if( x.thermostat && x.fan ) {
-			x.running = 1;
-			x.poll_task = kthread_run(control_loop, NULL, "g4fand");
-		}
 	}
-	return 0;
 }
 
 static int
@@ -404,8 +405,8 @@
 enum chip { ds1775, adm1030 };
 
 static const struct i2c_device_id therm_windtunnel_id[] = {
-	{ "therm_ds1775", ds1775 },
-	{ "therm_adm1030", adm1030 },
+	{ "MAC,ds1775", ds1775 },
+	{ "MAC,adm1030", adm1030 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, therm_windtunnel_id);
@@ -414,6 +415,7 @@
 do_probe(struct i2c_client *cl, const struct i2c_device_id *id)
 {
 	struct i2c_adapter *adapter = cl->adapter;
+	int ret = 0;
 
 	if( !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA
 				     | I2C_FUNC_SMBUS_WRITE_BYTE) )
@@ -421,11 +423,19 @@
 
 	switch (id->driver_data) {
 	case adm1030:
-		return attach_fan( cl );
+		ret = attach_fan(cl);
+		break;
 	case ds1775:
-		return attach_thermostat(cl);
+		ret = attach_thermostat(cl);
+		break;
 	}
-	return 0;
+
+	if (!x.running && x.thermostat && x.fan) {
+		x.running = 1;
+		x.poll_task = kthread_run(control_loop, NULL, "g4fand");
+	}
+
+	return ret;
 }
 
 static struct i2c_driver g4fan_driver = {
@@ -539,7 +549,7 @@
 	platform_driver_unregister( &therm_of_driver );
 
 	if( x.of_dev )
-		of_device_unregister( x.of_dev );
+		of_platform_device_destroy(&x.of_dev->dev, NULL);
 }
 
 module_init(g4fan_init);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/macintosh/via-macii.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/macintosh/via-macii.c
@@ -135,24 +135,19 @@
 /* Initialize the driver */
 int macii_init(void)
 {
-	unsigned long flags;
 	int err;
 
-	local_irq_save(flags);
-
 	err = macii_init_via();
 	if (err)
-		goto out;
+		return err;
 
 	err = request_irq(IRQ_MAC_ADB, macii_interrupt, 0, "ADB",
 			  macii_interrupt);
 	if (err)
-		goto out;
+		return err;
 
 	macii_state = idle;
-out:
-	local_irq_restore(flags);
-	return err;
+	return 0;
 }
 
 /* initialize the hardware */
@@ -270,15 +265,12 @@
 	unsigned long flags;
 	int err = 0;
 
+	local_irq_save(flags);
+
 	/* bit 1 == device 1, and so on. */
 	autopoll_devs = devs & 0xFFFE;
 
-	if (!autopoll_devs)
-		return 0;
-
-	local_irq_save(flags);
-
-	if (current_req == NULL) {
+	if (autopoll_devs && !current_req) {
 		/* Send a Talk Reg 0. The controller will repeatedly transmit
 		 * this as long as it is idle.
 		 */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/macintosh/via-pmu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/macintosh/via-pmu.c
@@ -1464,7 +1464,7 @@
 		pmu_pass_intr(data, len);
 		/* len == 6 is probably a bad check. But how do I
 		 * know what PMU versions send what events here? */
-		if (len == 6) {
+		if (IS_ENABLED(CONFIG_ADB_PMU_EVENT) && len == 6) {
 			via_pmu_event(PMU_EVT_POWER, !!(data[1]&8));
 			via_pmu_event(PMU_EVT_LID, data[1]&1);
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/macintosh/windfarm_ad7417_sensor.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/macintosh/windfarm_ad7417_sensor.c
@@ -312,9 +312,16 @@
 };
 MODULE_DEVICE_TABLE(i2c, wf_ad7417_id);
 
+static const struct of_device_id wf_ad7417_of_id[] = {
+	{ .compatible = "ad7417", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, wf_ad7417_of_id);
+
 static struct i2c_driver wf_ad7417_driver = {
 	.driver = {
 		.name	= "wf_ad7417",
+		.of_match_table = wf_ad7417_of_id,
 	},
 	.probe		= wf_ad7417_probe,
 	.remove		= wf_ad7417_remove,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/macintosh/windfarm_fcu_controls.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/macintosh/windfarm_fcu_controls.c
@@ -582,9 +582,16 @@
 };
 MODULE_DEVICE_TABLE(i2c, wf_fcu_id);
 
+static const struct of_device_id wf_fcu_of_id[] = {
+	{ .compatible = "fcu", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, wf_fcu_of_id);
+
 static struct i2c_driver wf_fcu_driver = {
 	.driver = {
 		.name	= "wf_fcu",
+		.of_match_table = wf_fcu_of_id,
 	},
 	.probe		= wf_fcu_probe,
 	.remove		= wf_fcu_remove,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/macintosh/windfarm_lm75_sensor.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/macintosh/windfarm_lm75_sensor.c
@@ -14,6 +14,7 @@
 #include <linux/init.h>
 #include <linux/wait.h>
 #include <linux/i2c.h>
+#include <linux/of_device.h>
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
@@ -33,8 +34,8 @@
 #endif
 
 struct wf_lm75_sensor {
-	int			ds1775 : 1;
-	int			inited : 1;
+	unsigned int		ds1775 : 1;
+	unsigned int		inited : 1;
 	struct i2c_client	*i2c;
 	struct wf_sensor	sens;
 };
@@ -91,9 +92,14 @@
 			 const struct i2c_device_id *id)
 {	
 	struct wf_lm75_sensor *lm;
-	int rc, ds1775 = id->driver_data;
+	int rc, ds1775;
 	const char *name, *loc;
 
+	if (id)
+		ds1775 = id->driver_data;
+	else
+		ds1775 = !!of_device_get_match_data(&client->dev);
+
 	DBG("wf_lm75: creating  %s device at address 0x%02x\n",
 	    ds1775 ? "ds1775" : "lm75", client->addr);
 
@@ -164,9 +170,17 @@
 };
 MODULE_DEVICE_TABLE(i2c, wf_lm75_id);
 
+static const struct of_device_id wf_lm75_of_id[] = {
+	{ .compatible = "lm75", .data = (void *)0},
+	{ .compatible = "ds1775", .data = (void *)1 },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, wf_lm75_of_id);
+
 static struct i2c_driver wf_lm75_driver = {
 	.driver = {
 		.name	= "wf_lm75",
+		.of_match_table = wf_lm75_of_id,
 	},
 	.probe		= wf_lm75_probe,
 	.remove		= wf_lm75_remove,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/macintosh/windfarm_lm87_sensor.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/macintosh/windfarm_lm87_sensor.c
@@ -166,9 +166,16 @@
 };
 MODULE_DEVICE_TABLE(i2c, wf_lm87_id);
 
+static const struct of_device_id wf_lm87_of_id[] = {
+	{ .compatible = "lm87cimt", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, wf_lm87_of_id);
+
 static struct i2c_driver wf_lm87_driver = {
 	.driver = {
 		.name	= "wf_lm87",
+		.of_match_table = wf_lm87_of_id,
 	},
 	.probe		= wf_lm87_probe,
 	.remove		= wf_lm87_remove,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/macintosh/windfarm_max6690_sensor.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/macintosh/windfarm_max6690_sensor.c
@@ -120,9 +120,16 @@
 };
 MODULE_DEVICE_TABLE(i2c, wf_max6690_id);
 
+static const struct of_device_id wf_max6690_of_id[] = {
+	{ .compatible = "max6690", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, wf_max6690_of_id);
+
 static struct i2c_driver wf_max6690_driver = {
 	.driver = {
 		.name		= "wf_max6690",
+		.of_match_table = wf_max6690_of_id,
 	},
 	.probe		= wf_max6690_probe,
 	.remove		= wf_max6690_remove,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/macintosh/windfarm_pm112.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/macintosh/windfarm_pm112.c
@@ -132,14 +132,6 @@
 	s32 tmax;
 	int fmin;
 
-	/* Get PID params from the appropriate SAT */
-	hdr = smu_sat_get_sdb_partition(chip, 0xC8 + core, NULL);
-	if (hdr == NULL) {
-		printk(KERN_WARNING"windfarm: can't get CPU PID fan config\n");
-		return -EINVAL;
-	}
-	piddata = (struct smu_sdbp_cpupiddata *)&hdr[1];
-
 	/* Get FVT params to get Tmax; if not found, assume default */
 	hdr = smu_sat_get_sdb_partition(chip, 0xC4 + core, NULL);
 	if (hdr) {
@@ -152,6 +144,16 @@
 	if (tmax < cpu_all_tmax)
 		cpu_all_tmax = tmax;
 
+	kfree(hdr);
+
+	/* Get PID params from the appropriate SAT */
+	hdr = smu_sat_get_sdb_partition(chip, 0xC8 + core, NULL);
+	if (hdr == NULL) {
+		printk(KERN_WARNING"windfarm: can't get CPU PID fan config\n");
+		return -EINVAL;
+	}
+	piddata = (struct smu_sdbp_cpupiddata *)&hdr[1];
+
 	/*
 	 * Darwin has a minimum fan speed of 1000 rpm for the 4-way and
 	 * 515 for the 2-way.  That appears to be overkill, so for now,
@@ -174,6 +176,9 @@
 		pid.min = fmin;
 
 	wf_cpu_pid_init(&cpu_pid[cpu], &pid);
+
+	kfree(hdr);
+
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/macintosh/windfarm_smu_sat.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/macintosh/windfarm_smu_sat.c
@@ -171,6 +171,7 @@
 
 	if (sat->nr >= 0)
 		sats[sat->nr] = NULL;
+	of_node_put(sat->node);
 	kfree(sat);
 }
 
@@ -341,9 +342,16 @@
 };
 MODULE_DEVICE_TABLE(i2c, wf_sat_id);
 
+static const struct of_device_id wf_sat_of_id[] = {
+	{ .compatible = "smu-sat", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, wf_sat_of_id);
+
 static struct i2c_driver wf_sat_driver = {
 	.driver = {
 		.name		= "wf_smu_sat",
+		.of_match_table = wf_sat_of_id,
 	},
 	.probe		= wf_sat_probe,
 	.remove		= wf_sat_remove,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/macintosh/windfarm_smu_sensors.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/macintosh/windfarm_smu_sensors.c
@@ -273,8 +273,8 @@
 	struct list_head	link;
 	struct wf_sensor	*volts;
 	struct wf_sensor	*amps;
-	int			fake_volts : 1;
-	int			quadratic : 1;
+	unsigned int		fake_volts : 1;
+	unsigned int		quadratic : 1;
 	struct wf_sensor	sens;
 };
 #define to_smu_cpu_power(c) container_of(c, struct smu_cpu_power_sensor, sens)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mailbox/bcm-flexrm-mailbox.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mailbox/bcm-flexrm-mailbox.c
@@ -632,15 +632,15 @@
 
 	rc = dma_map_sg(dev, msg->spu.src, sg_nents(msg->spu.src),
 			DMA_TO_DEVICE);
-	if (rc < 0)
-		return rc;
+	if (!rc)
+		return -EIO;
 
 	rc = dma_map_sg(dev, msg->spu.dst, sg_nents(msg->spu.dst),
 			DMA_FROM_DEVICE);
-	if (rc < 0) {
+	if (!rc) {
 		dma_unmap_sg(dev, msg->spu.src, sg_nents(msg->spu.src),
 			     DMA_TO_DEVICE);
-		return rc;
+		return -EIO;
 	}
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mailbox/bcm2835-mailbox.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mailbox/bcm2835-mailbox.c
@@ -146,7 +146,8 @@
 	spin_lock_init(&mbox->lock);
 
 	ret = devm_request_irq(dev, irq_of_parse_and_map(dev->of_node, 0),
-			       bcm2835_mbox_irq, 0, dev_name(dev), mbox);
+			       bcm2835_mbox_irq, IRQF_NO_SUSPEND, dev_name(dev),
+			       mbox);
 	if (ret) {
 		dev_err(dev, "Failed to register a mailbox IRQ handler: %d\n",
 			ret);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mailbox/imx-mailbox.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mailbox/imx-mailbox.c
@@ -214,11 +214,24 @@
 	struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
 	struct imx_mu_con_priv *cp = chan->con_priv;
 
-	if (cp->type == IMX_MU_TYPE_TXDB)
+	if (cp->type == IMX_MU_TYPE_TXDB) {
 		tasklet_kill(&cp->txdb_tasklet);
+		return;
+	}
 
-	imx_mu_xcr_rmw(priv, 0, IMX_MU_xCR_TIEn(cp->idx) |
-		       IMX_MU_xCR_RIEn(cp->idx) | IMX_MU_xCR_GIEn(cp->idx));
+	switch (cp->type) {
+	case IMX_MU_TYPE_TX:
+		imx_mu_xcr_rmw(priv, 0, IMX_MU_xCR_TIEn(cp->idx));
+		break;
+	case IMX_MU_TYPE_RX:
+		imx_mu_xcr_rmw(priv, 0, IMX_MU_xCR_RIEn(cp->idx));
+		break;
+	case IMX_MU_TYPE_RXDB:
+		imx_mu_xcr_rmw(priv, 0, IMX_MU_xCR_GIEn(cp->idx));
+		break;
+	default:
+		break;
+	}
 
 	free_irq(priv->irq, chan);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mailbox/mailbox-test.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mailbox/mailbox-test.c
@@ -12,6 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/mailbox_client.h>
 #include <linux/module.h>
+#include <linux/mutex.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/poll.h>
@@ -38,6 +39,7 @@
 	char			*signal;
 	char			*message;
 	spinlock_t		lock;
+	struct mutex		mutex;
 	wait_queue_head_t	waitq;
 	struct fasync_struct	*async_queue;
 	struct dentry		*root_debugfs_dir;
@@ -95,6 +97,7 @@
 				       size_t count, loff_t *ppos)
 {
 	struct mbox_test_device *tdev = filp->private_data;
+	char *message;
 	void *data;
 	int ret;
 
@@ -110,10 +113,13 @@
 		return -EINVAL;
 	}
 
-	tdev->message = kzalloc(MBOX_MAX_MSG_LEN, GFP_KERNEL);
-	if (!tdev->message)
+	message = kzalloc(MBOX_MAX_MSG_LEN, GFP_KERNEL);
+	if (!message)
 		return -ENOMEM;
 
+	mutex_lock(&tdev->mutex);
+
+	tdev->message = message;
 	ret = copy_from_user(tdev->message, userbuf, count);
 	if (ret) {
 		ret = -EFAULT;
@@ -144,6 +150,8 @@
 	kfree(tdev->message);
 	tdev->signal = NULL;
 
+	mutex_unlock(&tdev->mutex);
+
 	return ret < 0 ? ret : count;
 }
 
@@ -392,6 +400,7 @@
 	platform_set_drvdata(pdev, tdev);
 
 	spin_lock_init(&tdev->lock);
+	mutex_init(&tdev->mutex);
 
 	if (tdev->rx_channel) {
 		tdev->rx_buffer = devm_kzalloc(&pdev->dev,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mailbox/mailbox.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mailbox/mailbox.c
@@ -82,9 +82,12 @@
 exit:
 	spin_unlock_irqrestore(&chan->lock, flags);
 
-	if (!err && (chan->txdone_method & TXDONE_BY_POLL))
+	if (!err && (chan->txdone_method & TXDONE_BY_POLL)) {
 		/* kick start the timer immediately to avoid delays */
+		spin_lock_irqsave(&chan->mbox->poll_hrt_lock, flags);
 		hrtimer_start(&chan->mbox->poll_hrt, 0, HRTIMER_MODE_REL);
+		spin_unlock_irqrestore(&chan->mbox->poll_hrt_lock, flags);
+	}
 }
 
 static void tx_tick(struct mbox_chan *chan, int r)
@@ -117,6 +120,7 @@
 		container_of(hrtimer, struct mbox_controller, poll_hrt);
 	bool txdone, resched = false;
 	int i;
+	unsigned long flags;
 
 	for (i = 0; i < mbox->num_chans; i++) {
 		struct mbox_chan *chan = &mbox->chans[i];
@@ -131,7 +135,11 @@
 	}
 
 	if (resched) {
-		hrtimer_forward_now(hrtimer, ms_to_ktime(mbox->txpoll_period));
+		spin_lock_irqsave(&mbox->poll_hrt_lock, flags);
+		if (!hrtimer_is_queued(hrtimer))
+			hrtimer_forward_now(hrtimer, ms_to_ktime(mbox->txpoll_period));
+		spin_unlock_irqrestore(&mbox->poll_hrt_lock, flags);
+
 		return HRTIMER_RESTART;
 	}
 	return HRTIMER_NORESTART;
@@ -498,6 +506,7 @@
 		hrtimer_init(&mbox->poll_hrt, CLOCK_MONOTONIC,
 			     HRTIMER_MODE_REL);
 		mbox->poll_hrt.function = txdone_hrtimer;
+		spin_lock_init(&mbox->poll_hrt_lock);
 	}
 
 	for (i = 0; i < mbox->num_chans; i++) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mailbox/mtk-cmdq-mailbox.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mailbox/mtk-cmdq-mailbox.c
@@ -70,7 +70,7 @@
 struct cmdq {
 	struct mbox_controller	mbox;
 	void __iomem		*base;
-	u32			irq;
+	int			irq;
 	u32			thread_nr;
 	u32			irq_mask;
 	struct cmdq_thread	*thread;
@@ -474,10 +474,8 @@
 	}
 
 	cmdq->irq = platform_get_irq(pdev, 0);
-	if (!cmdq->irq) {
-		dev_err(dev, "failed to get irq\n");
-		return -EINVAL;
-	}
+	if (cmdq->irq < 0)
+		return cmdq->irq;
 
 	cmdq->thread_nr = (u32)(unsigned long)of_device_get_match_data(dev);
 	cmdq->irq_mask = GENMASK(cmdq->thread_nr - 1, 0);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mailbox/rockchip-mailbox.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mailbox/rockchip-mailbox.c
@@ -159,7 +159,7 @@
 	{ .compatible = "rockchip,rk3368-mailbox", .data = &rk3368_drv_data},
 	{ },
 };
-MODULE_DEVICE_TABLE(of, rockchp_mbox_of_match);
+MODULE_DEVICE_TABLE(of, rockchip_mbox_of_match);
 
 static int rockchip_mbox_probe(struct platform_device *pdev)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mailbox/tegra-hsp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mailbox/tegra-hsp.c
@@ -403,6 +403,11 @@
 		value = tegra_hsp_channel_readl(ch, HSP_SM_SHRD_MBOX);
 		if ((value & HSP_SM_SHRD_MBOX_FULL) == 0) {
 			mbox_chan_txdone(chan, 0);
+
+			/* Wait until channel is empty */
+			if (chan->active_req != NULL)
+				continue;
+
 			return 0;
 		}
 
@@ -657,7 +662,7 @@
 	hsp->num_db = (value >> HSP_nDB_SHIFT) & HSP_nINT_MASK;
 	hsp->num_si = (value >> HSP_nSI_SHIFT) & HSP_nINT_MASK;
 
-	err = platform_get_irq_byname(pdev, "doorbell");
+	err = platform_get_irq_byname_optional(pdev, "doorbell");
 	if (err >= 0)
 		hsp->doorbell_irq = err;
 
@@ -677,7 +682,7 @@
 			if (!name)
 				return -ENOMEM;
 
-			err = platform_get_irq_byname(pdev, name);
+			err = platform_get_irq_byname_optional(pdev, name);
 			if (err >= 0) {
 				hsp->shared_irqs[i] = err;
 				count++;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mailbox/ti-msgmgr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mailbox/ti-msgmgr.c
@@ -385,14 +385,20 @@
 		/* Ensure all unused data is 0 */
 		data_trail &= 0xFFFFFFFF >> (8 * (sizeof(u32) - trail_bytes));
 		writel(data_trail, data_reg);
-		data_reg++;
+		data_reg += sizeof(u32);
 	}
+
 	/*
 	 * 'data_reg' indicates next register to write. If we did not already
 	 * write on tx complete reg(last reg), we must do so for transmit
+	 * In addition, we also need to make sure all intermediate data
+	 * registers(if any required), are reset to 0 for TISCI backward
+	 * compatibility to be maintained.
 	 */
-	if (data_reg <= qinst->queue_buff_end)
-		writel(0, qinst->queue_buff_end);
+	while (data_reg <= qinst->queue_buff_end) {
+		writel(0, data_reg);
+		data_reg += sizeof(u32);
+	}
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mailbox/zynqmp-ipi-mailbox.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mailbox/zynqmp-ipi-mailbox.c
@@ -110,7 +110,7 @@
 	unsigned int method;
 	u32 local_id;
 	int num_mboxes;
-	struct zynqmp_ipi_mbox *ipi_mboxes;
+	struct zynqmp_ipi_mbox ipi_mboxes[];
 };
 
 static struct device_driver zynqmp_ipi_mbox_driver = {
@@ -152,7 +152,7 @@
 	struct zynqmp_ipi_message *msg;
 	u64 arg0, arg3;
 	struct arm_smccc_res res;
-	int ret, i;
+	int ret, i, status = IRQ_NONE;
 
 	(void)irq;
 	arg0 = SMC_IPI_MAILBOX_STATUS_ENQUIRY;
@@ -170,11 +170,11 @@
 				memcpy_fromio(msg->data, mchan->req_buf,
 					      msg->len);
 				mbox_chan_received_data(chan, (void *)msg);
-				return IRQ_HANDLED;
+				status = IRQ_HANDLED;
 			}
 		}
 	}
-	return IRQ_NONE;
+	return status;
 }
 
 /**
@@ -493,6 +493,7 @@
 	ret = device_register(&ipi_mbox->dev);
 	if (ret) {
 		dev_err(dev, "Failed to register ipi mbox dev.\n");
+		put_device(&ipi_mbox->dev);
 		return ret;
 	}
 	mdev = &ipi_mbox->dev;
@@ -504,10 +505,9 @@
 		mchan->req_buf_size = resource_size(&res);
 		mchan->req_buf = devm_ioremap(mdev, res.start,
 					      mchan->req_buf_size);
-		if (IS_ERR(mchan->req_buf)) {
+		if (!mchan->req_buf) {
 			dev_err(mdev, "Unable to map IPI buffer I/O memory\n");
-			ret = PTR_ERR(mchan->req_buf);
-			return ret;
+			return -ENOMEM;
 		}
 	} else if (ret != -ENODEV) {
 		dev_err(mdev, "Unmatched resource %s, %d.\n", name, ret);
@@ -520,10 +520,9 @@
 		mchan->resp_buf_size = resource_size(&res);
 		mchan->resp_buf = devm_ioremap(mdev, res.start,
 					       mchan->resp_buf_size);
-		if (IS_ERR(mchan->resp_buf)) {
+		if (!mchan->resp_buf) {
 			dev_err(mdev, "Unable to map IPI buffer I/O memory\n");
-			ret = PTR_ERR(mchan->resp_buf);
-			return ret;
+			return -ENOMEM;
 		}
 	} else if (ret != -ENODEV) {
 		dev_err(mdev, "Unmatched resource %s.\n", name);
@@ -543,10 +542,9 @@
 		mchan->req_buf_size = resource_size(&res);
 		mchan->req_buf = devm_ioremap(mdev, res.start,
 					      mchan->req_buf_size);
-		if (IS_ERR(mchan->req_buf)) {
+		if (!mchan->req_buf) {
 			dev_err(mdev, "Unable to map IPI buffer I/O memory\n");
-			ret = PTR_ERR(mchan->req_buf);
-			return ret;
+			return -ENOMEM;
 		}
 	} else if (ret != -ENODEV) {
 		dev_err(mdev, "Unmatched resource %s.\n", name);
@@ -559,10 +557,9 @@
 		mchan->resp_buf_size = resource_size(&res);
 		mchan->resp_buf = devm_ioremap(mdev, res.start,
 					       mchan->resp_buf_size);
-		if (IS_ERR(mchan->resp_buf)) {
+		if (!mchan->resp_buf) {
 			dev_err(mdev, "Unable to map IPI buffer I/O memory\n");
-			ret = PTR_ERR(mchan->resp_buf);
-			return ret;
+			return -ENOMEM;
 		}
 	} else if (ret != -ENODEV) {
 		dev_err(mdev, "Unmatched resource %s.\n", name);
@@ -623,7 +620,8 @@
 		ipi_mbox = &pdata->ipi_mboxes[i];
 		if (ipi_mbox->dev.parent) {
 			mbox_controller_unregister(&ipi_mbox->mbox);
-			device_unregister(&ipi_mbox->dev);
+			if (device_is_registered(&ipi_mbox->dev))
+				device_unregister(&ipi_mbox->dev);
 		}
 	}
 }
@@ -636,8 +634,13 @@
 	struct zynqmp_ipi_mbox *mbox;
 	int num_mboxes, ret = -EINVAL;
 
-	num_mboxes = of_get_child_count(np);
-	pdata = devm_kzalloc(dev, sizeof(*pdata) + (num_mboxes * sizeof(*mbox)),
+	num_mboxes = of_get_available_child_count(np);
+	if (num_mboxes == 0) {
+		dev_err(dev, "mailbox nodes not available\n");
+		return -EINVAL;
+	}
+
+	pdata = devm_kzalloc(dev, struct_size(pdata, ipi_mboxes, num_mboxes),
 			     GFP_KERNEL);
 	if (!pdata)
 		return -ENOMEM;
@@ -651,8 +654,6 @@
 	}
 
 	pdata->num_mboxes = num_mboxes;
-	pdata->ipi_mboxes = (struct zynqmp_ipi_mbox *)
-			    ((char *)pdata + sizeof(*pdata));
 
 	mbox = pdata->ipi_mboxes;
 	for_each_available_child_of_node(np, nc) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mcb/mcb-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mcb/mcb-core.c
@@ -71,8 +71,10 @@
 
 	get_device(dev);
 	ret = mdrv->probe(mdev, found_id);
-	if (ret)
+	if (ret) {
 		module_put(carrier_mod);
+		put_device(dev);
+	}
 
 	return ret;
 }
@@ -246,6 +248,7 @@
 	return 0;
 
 out:
+	put_device(&dev->dev);
 
 	return ret;
 }
@@ -277,8 +280,8 @@
 
 	bus_nr = ida_simple_get(&mcb_ida, 0, 0, GFP_KERNEL);
 	if (bus_nr < 0) {
-		rc = bus_nr;
-		goto err_free;
+		kfree(bus);
+		return ERR_PTR(bus_nr);
 	}
 
 	bus->bus_nr = bus_nr;
@@ -293,12 +296,12 @@
 	dev_set_name(&bus->dev, "mcb:%d", bus_nr);
 	rc = device_add(&bus->dev);
 	if (rc)
-		goto err_free;
+		goto err_put;
 
 	return bus;
-err_free:
-	put_device(carrier);
-	kfree(bus);
+
+err_put:
+	put_device(&bus->dev);
 	return ERR_PTR(rc);
 }
 EXPORT_SYMBOL_GPL(mcb_alloc_bus);
@@ -387,17 +390,13 @@
 
 static int __mcb_bus_add_devices(struct device *dev, void *data)
 {
-	struct mcb_device *mdev = to_mcb_device(dev);
 	int retval;
 
-	if (mdev->is_added)
-		return 0;
-
 	retval = device_attach(dev);
-	if (retval < 0)
+	if (retval < 0) {
 		dev_err(dev, "Error adding device (%d)\n", retval);
-
-	mdev->is_added = true;
+		return retval;
+	}
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mcb/mcb-lpc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mcb/mcb-lpc.c
@@ -23,7 +23,7 @@
 {
 	struct resource *res;
 	struct priv *priv;
-	int ret = 0;
+	int ret = 0, table_size;
 
 	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
 	if (!priv)
@@ -58,16 +58,43 @@
 
 	ret = chameleon_parse_cells(priv->bus, priv->mem->start, priv->base);
 	if (ret < 0) {
-		mcb_release_bus(priv->bus);
-		return ret;
+		goto out_mcb_bus;
 	}
 
-	dev_dbg(&pdev->dev, "Found %d cells\n", ret);
+	table_size = ret;
+
+	if (table_size < CHAM_HEADER_SIZE) {
+		/* Release the previous resources */
+		devm_iounmap(&pdev->dev, priv->base);
+		devm_release_mem_region(&pdev->dev, priv->mem->start, resource_size(priv->mem));
+
+		/* Then, allocate it again with the actual chameleon table size */
+		res = devm_request_mem_region(&pdev->dev, priv->mem->start,
+					      table_size,
+					      KBUILD_MODNAME);
+		if (!res) {
+			dev_err(&pdev->dev, "Failed to request PCI memory\n");
+			ret = -EBUSY;
+			goto out_mcb_bus;
+		}
+
+		priv->base = devm_ioremap(&pdev->dev, priv->mem->start, table_size);
+		if (!priv->base) {
+			dev_err(&pdev->dev, "Cannot ioremap\n");
+			ret = -ENOMEM;
+			goto out_mcb_bus;
+		}
+
+		platform_set_drvdata(pdev, priv);
+	}
 
 	mcb_bus_add_devices(priv->bus);
 
 	return 0;
 
+out_mcb_bus:
+	mcb_release_bus(priv->bus);
+	return ret;
 }
 
 static int mcb_lpc_remove(struct platform_device *pdev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mcb/mcb-parse.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mcb/mcb-parse.c
@@ -99,8 +99,6 @@
 	mdev->mem.end = mdev->mem.start + size - 1;
 	mdev->mem.flags = IORESOURCE_MEM;
 
-	mdev->is_added = false;
-
 	ret = mcb_device_register(bus, mdev);
 	if (ret < 0)
 		goto err;
@@ -130,7 +128,7 @@
 	}
 }
 
-static int chameleon_get_bar(char __iomem **base, phys_addr_t mapbase,
+static int chameleon_get_bar(void __iomem **base, phys_addr_t mapbase,
 			     struct chameleon_bar **cb)
 {
 	struct chameleon_bar *c;
@@ -179,12 +177,13 @@
 {
 	struct chameleon_fpga_header *header;
 	struct chameleon_bar *cb;
-	char __iomem *p = base;
+	void __iomem *p = base;
 	int num_cells = 0;
 	uint32_t dtype;
 	int bar_count;
 	int ret;
 	u32 hsize;
+	u32 table_size;
 
 	hsize = sizeof(struct chameleon_fpga_header);
 
@@ -239,12 +238,16 @@
 		num_cells++;
 	}
 
-	if (num_cells == 0)
-		num_cells = -EINVAL;
+	if (num_cells == 0) {
+		ret = -EINVAL;
+		goto free_bar;
+	}
 
+	table_size = p - base;
+	pr_debug("%d cell(s) found. Chameleon table size: 0x%04x bytes\n", num_cells, table_size);
 	kfree(cb);
 	kfree(header);
-	return num_cells;
+	return table_size;
 
 free_bar:
 	kfree(cb);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mcb/mcb-pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mcb/mcb-pci.c
@@ -31,7 +31,7 @@
 {
 	struct resource *res;
 	struct priv *priv;
-	int ret;
+	int ret, table_size;
 	unsigned long flags;
 
 	priv = devm_kzalloc(&pdev->dev, sizeof(struct priv), GFP_KERNEL);
@@ -90,7 +90,30 @@
 	if (ret < 0)
 		goto out_mcb_bus;
 
-	dev_dbg(&pdev->dev, "Found %d cells\n", ret);
+	table_size = ret;
+
+	if (table_size < CHAM_HEADER_SIZE) {
+		/* Release the previous resources */
+		devm_iounmap(&pdev->dev, priv->base);
+		devm_release_mem_region(&pdev->dev, priv->mapbase, CHAM_HEADER_SIZE);
+
+		/* Then, allocate it again with the actual chameleon table size */
+		res = devm_request_mem_region(&pdev->dev, priv->mapbase,
+						table_size,
+						KBUILD_MODNAME);
+		if (!res) {
+			dev_err(&pdev->dev, "Failed to request PCI memory\n");
+			ret = -EBUSY;
+			goto out_mcb_bus;
+		}
+
+		priv->base = devm_ioremap(&pdev->dev, priv->mapbase, table_size);
+		if (!priv->base) {
+			dev_err(&pdev->dev, "Cannot ioremap\n");
+			ret = -ENOMEM;
+			goto out_mcb_bus;
+		}
+	}
 
 	mcb_bus_add_devices(priv->bus);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/Kconfig
@@ -565,6 +565,7 @@
 	select BLK_DEV_INTEGRITY
 	select DM_BUFIO
 	select CRYPTO
+	select CRYPTO_SKCIPHER
 	select ASYNC_XOR
 	---help---
 	  This device-mapper target emulates a block device that has
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/bcache/alloc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/bcache/alloc.c
@@ -49,7 +49,7 @@
  *
  * bch_bucket_alloc() allocates a single bucket from a specific cache.
  *
- * bch_bucket_alloc_set() allocates one or more buckets from different caches
+ * bch_bucket_alloc_set() allocates one  bucket from different caches
  * out of a cache set.
  *
  * free_some_buckets() drives all the processes described above. It's called
@@ -377,7 +377,10 @@
 			if (!fifo_full(&ca->free_inc))
 				goto retry_invalidate;
 
-			bch_prio_write(ca);
+			if (bch_prio_write(ca, false) < 0) {
+				ca->invalidate_needs_gc = 1;
+				wake_up_gc(ca->set);
+			}
 		}
 	}
 out:
@@ -485,34 +488,29 @@
 }
 
 int __bch_bucket_alloc_set(struct cache_set *c, unsigned int reserve,
-			   struct bkey *k, int n, bool wait)
+			   struct bkey *k, bool wait)
 {
-	int i;
+	struct cache *ca;
+	long b;
 
 	/* No allocation if CACHE_SET_IO_DISABLE bit is set */
 	if (unlikely(test_bit(CACHE_SET_IO_DISABLE, &c->flags)))
 		return -1;
 
 	lockdep_assert_held(&c->bucket_lock);
-	BUG_ON(!n || n > c->caches_loaded || n > MAX_CACHES_PER_SET);
 
 	bkey_init(k);
 
-	/* sort by free space/prio of oldest data in caches */
-
-	for (i = 0; i < n; i++) {
-		struct cache *ca = c->cache_by_alloc[i];
-		long b = bch_bucket_alloc(ca, reserve, wait);
+	ca = c->cache_by_alloc[0];
+	b = bch_bucket_alloc(ca, reserve, wait);
+	if (b == -1)
+		goto err;
+
+	k->ptr[0] = MAKE_PTR(ca->buckets[b].gen,
+			     bucket_to_sector(c, b),
+			     ca->sb.nr_this_dev);
 
-		if (b == -1)
-			goto err;
-
-		k->ptr[i] = MAKE_PTR(ca->buckets[b].gen,
-				bucket_to_sector(c, b),
-				ca->sb.nr_this_dev);
-
-		SET_KEY_PTRS(k, i + 1);
-	}
+	SET_KEY_PTRS(k, 1);
 
 	return 0;
 err:
@@ -522,12 +520,12 @@
 }
 
 int bch_bucket_alloc_set(struct cache_set *c, unsigned int reserve,
-			 struct bkey *k, int n, bool wait)
+			 struct bkey *k, bool wait)
 {
 	int ret;
 
 	mutex_lock(&c->bucket_lock);
-	ret = __bch_bucket_alloc_set(c, reserve, k, n, wait);
+	ret = __bch_bucket_alloc_set(c, reserve, k, wait);
 	mutex_unlock(&c->bucket_lock);
 	return ret;
 }
@@ -635,7 +633,7 @@
 
 		spin_unlock(&c->data_bucket_lock);
 
-		if (bch_bucket_alloc_set(c, watermark, &alloc.key, 1, wait))
+		if (bch_bucket_alloc_set(c, watermark, &alloc.key, wait))
 			return false;
 
 		spin_lock(&c->data_bucket_lock);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/bcache/bcache.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/bcache/bcache.h
@@ -264,7 +264,8 @@
 #define BCACHE_DEV_UNLINK_DONE		2
 #define BCACHE_DEV_WB_RUNNING		3
 #define BCACHE_DEV_RATE_DW_RUNNING	4
-	unsigned int		nr_stripes;
+	int			nr_stripes;
+#define BCH_MIN_STRIPE_SZ		((4 << 20) >> SECTOR_SHIFT)
 	unsigned int		stripe_size;
 	atomic_t		*stripe_sectors_dirty;
 	unsigned long		*full_dirty_stripes;
@@ -329,6 +330,9 @@
 	 */
 	atomic_t		has_dirty;
 
+#define BCH_CACHE_READA_ALL		0
+#define BCH_CACHE_READA_META_ONLY	1
+	unsigned int		cache_readahead_policy;
 	struct bch_ratelimit	writeback_rate;
 	struct delayed_work	writeback_rate_update;
 
@@ -369,6 +373,7 @@
 	unsigned int		partial_stripes_expensive:1;
 	unsigned int		writeback_metadata:1;
 	unsigned int		writeback_running:1;
+	unsigned int		writeback_consider_fragment:1;
 	unsigned char		writeback_percent;
 	unsigned int		writeback_delay;
 
@@ -381,6 +386,9 @@
 	unsigned int		writeback_rate_update_seconds;
 	unsigned int		writeback_rate_i_term_inverse;
 	unsigned int		writeback_rate_p_term_inverse;
+	unsigned int		writeback_rate_fp_term_low;
+	unsigned int		writeback_rate_fp_term_mid;
+	unsigned int		writeback_rate_fp_term_high;
 	unsigned int		writeback_rate_minimum;
 
 	enum stop_on_failure	stop_when_cache_set_failed;
@@ -582,6 +590,7 @@
 	 */
 	wait_queue_head_t	btree_cache_wait;
 	struct task_struct	*btree_cache_alloc_lock;
+	spinlock_t		btree_cannibalize_lock;
 
 	/*
 	 * When we free a btree node, we increment the gen of the bucket the
@@ -966,9 +975,9 @@
 
 long bch_bucket_alloc(struct cache *ca, unsigned int reserve, bool wait);
 int __bch_bucket_alloc_set(struct cache_set *c, unsigned int reserve,
-			   struct bkey *k, int n, bool wait);
+			   struct bkey *k, bool wait);
 int bch_bucket_alloc_set(struct cache_set *c, unsigned int reserve,
-			 struct bkey *k, int n, bool wait);
+			 struct bkey *k, bool wait);
 bool bch_alloc_sectors(struct cache_set *c, struct bkey *k,
 		       unsigned int sectors, unsigned int write_point,
 		       unsigned int write_prio, bool wait);
@@ -977,11 +986,12 @@
 __printf(2, 3)
 bool bch_cache_set_error(struct cache_set *c, const char *fmt, ...);
 
-void bch_prio_write(struct cache *ca);
+int bch_prio_write(struct cache *ca, bool wait);
 void bch_write_bdev_super(struct cached_dev *dc, struct closure *parent);
 
 extern struct workqueue_struct *bcache_wq;
 extern struct workqueue_struct *bch_journal_wq;
+extern struct workqueue_struct *bch_flush_wq;
 extern struct mutex bch_register_lock;
 extern struct list_head bch_cache_sets;
 
@@ -1004,6 +1014,7 @@
 int bch_cached_dev_attach(struct cached_dev *dc, struct cache_set *c,
 			  uint8_t *set_uuid);
 void bch_cached_dev_detach(struct cached_dev *dc);
+void bch_cached_dev_emit_change(struct cached_dev *);
 int bch_cached_dev_run(struct cached_dev *dc);
 void bcache_device_stop(struct bcache_device *d);
 
@@ -1023,5 +1034,7 @@
 void bch_debug_init(void);
 void bch_request_exit(void);
 int bch_request_init(void);
+void bch_btree_exit(void);
+int bch_btree_init(void);
 
 #endif /* _BCACHE_H */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/bcache/bset.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/bcache/bset.c
@@ -321,7 +321,7 @@
 
 	b->page_order = page_order;
 
-	t->data = (void *) __get_free_pages(gfp, b->page_order);
+	t->data = (void *) __get_free_pages(__GFP_COMP|gfp, b->page_order);
 	if (!t->data)
 		goto err;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/bcache/bset.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/bcache/bset.h
@@ -397,7 +397,8 @@
 
 /* Bkey utility code */
 
-#define bset_bkey_last(i)	bkey_idx((struct bkey *) (i)->d, (i)->keys)
+#define bset_bkey_last(i)	bkey_idx((struct bkey *) (i)->d, \
+					 (unsigned int)(i)->keys)
 
 static inline struct bkey *bset_bkey_idx(struct bset *i, unsigned int idx)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/bcache/btree.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/bcache/btree.c
@@ -99,6 +99,8 @@
 #define PTR_HASH(c, k)							\
 	(((k)->ptr[0] >> c->bucket_bits) | PTR_GEN(k, 0))
 
+static struct workqueue_struct *btree_io_wq;
+
 #define insert_lock(s, b)	((b)->level <= (s)->lock)
 
 /*
@@ -366,7 +368,7 @@
 	btree_complete_write(b, w);
 
 	if (btree_node_dirty(b))
-		schedule_delayed_work(&b->work, 30 * HZ);
+		queue_delayed_work(btree_io_wq, &b->work, 30 * HZ);
 
 	closure_return_with_destructor(cl, btree_node_write_unlock);
 }
@@ -539,7 +541,7 @@
 	BUG_ON(!i->keys);
 
 	if (!btree_node_dirty(b))
-		schedule_delayed_work(&b->work, 30 * HZ);
+		queue_delayed_work(btree_io_wq, &b->work, 30 * HZ);
 
 	set_btree_node_dirty(b);
 
@@ -723,38 +725,38 @@
 	 * IO can always make forward progress:
 	 */
 	nr /= c->btree_pages;
+	if (nr == 0)
+		nr = 1;
 	nr = min_t(unsigned long, nr, mca_can_free(c));
 
 	i = 0;
 	btree_cache_used = c->btree_cache_used;
-	list_for_each_entry_safe(b, t, &c->btree_cache_freeable, list) {
+	list_for_each_entry_safe_reverse(b, t, &c->btree_cache_freeable, list) {
 		if (nr <= 0)
 			goto out;
 
-		if (++i > 3 &&
-		    !mca_reap(b, 0, false)) {
+		if (!mca_reap(b, 0, false)) {
 			mca_data_free(b);
 			rw_unlock(true, b);
 			freed++;
 		}
 		nr--;
+		i++;
 	}
 
-	for (;  (nr--) && i < btree_cache_used; i++) {
-		if (list_empty(&c->btree_cache))
+	list_for_each_entry_safe_reverse(b, t, &c->btree_cache, list) {
+		if (nr <= 0 || i >= btree_cache_used)
 			goto out;
 
-		b = list_first_entry(&c->btree_cache, struct btree, list);
-		list_rotate_left(&c->btree_cache);
-
-		if (!b->accessed &&
-		    !mca_reap(b, 0, false)) {
+		if (!mca_reap(b, 0, false)) {
 			mca_bucket_free(b);
 			mca_data_free(b);
 			rw_unlock(true, b);
 			freed++;
-		} else
-			b->accessed = 0;
+		}
+
+		nr--;
+		i++;
 	}
 out:
 	mutex_unlock(&c->bucket_lock);
@@ -838,7 +840,7 @@
 	mutex_init(&c->verify_lock);
 
 	c->verify_ondisk = (void *)
-		__get_free_pages(GFP_KERNEL, ilog2(bucket_pages(c)));
+		__get_free_pages(GFP_KERNEL|__GFP_COMP, ilog2(bucket_pages(c)));
 
 	c->verify_data = mca_bucket_alloc(c, &ZERO_KEY, GFP_KERNEL);
 
@@ -884,15 +886,17 @@
 
 static int mca_cannibalize_lock(struct cache_set *c, struct btree_op *op)
 {
-	struct task_struct *old;
-
-	old = cmpxchg(&c->btree_cache_alloc_lock, NULL, current);
-	if (old && old != current) {
+	spin_lock(&c->btree_cannibalize_lock);
+	if (likely(c->btree_cache_alloc_lock == NULL)) {
+		c->btree_cache_alloc_lock = current;
+	} else if (c->btree_cache_alloc_lock != current) {
 		if (op)
 			prepare_to_wait(&c->btree_cache_wait, &op->wait,
 					TASK_UNINTERRUPTIBLE);
+		spin_unlock(&c->btree_cannibalize_lock);
 		return -EINTR;
 	}
+	spin_unlock(&c->btree_cannibalize_lock);
 
 	return 0;
 }
@@ -927,10 +931,12 @@
  */
 static void bch_cannibalize_unlock(struct cache_set *c)
 {
+	spin_lock(&c->btree_cannibalize_lock);
 	if (c->btree_cache_alloc_lock == current) {
 		c->btree_cache_alloc_lock = NULL;
 		wake_up(&c->btree_cache_wait);
 	}
+	spin_unlock(&c->btree_cannibalize_lock);
 }
 
 static struct btree *mca_alloc(struct cache_set *c, struct btree_op *op,
@@ -1012,6 +1018,9 @@
  *
  * The btree node will have either a read or a write lock held, depending on
  * level and op->lock.
+ *
+ * Note: Only error code or btree pointer will be returned, it is unncessary
+ *       for callers to check NULL pointer.
  */
 struct btree *bch_btree_node_get(struct cache_set *c, struct btree_op *op,
 				 struct bkey *k, int level, bool write,
@@ -1058,7 +1067,6 @@
 	BUG_ON(!b->written);
 
 	b->parent = parent;
-	b->accessed = 1;
 
 	for (; i <= b->keys.nsets && b->keys.set[i].size; i++) {
 		prefetch(b->keys.set[i].tree);
@@ -1124,16 +1132,22 @@
 	mutex_unlock(&b->c->bucket_lock);
 }
 
+/*
+ * Only error code or btree pointer will be returned, it is unncessary for
+ * callers to check NULL pointer.
+ */
 struct btree *__bch_btree_node_alloc(struct cache_set *c, struct btree_op *op,
 				     int level, bool wait,
 				     struct btree *parent)
 {
 	BKEY_PADDED(key) k;
-	struct btree *b = ERR_PTR(-EAGAIN);
+	struct btree *b;
 
 	mutex_lock(&c->bucket_lock);
 retry:
-	if (__bch_bucket_alloc_set(c, RESERVE_BTREE, &k.key, 1, wait))
+	/* return ERR_PTR(-EAGAIN) when it fails */
+	b = ERR_PTR(-EAGAIN);
+	if (__bch_bucket_alloc_set(c, RESERVE_BTREE, &k.key, wait))
 		goto err;
 
 	bkey_put(c, &k.key);
@@ -1149,7 +1163,6 @@
 		goto retry;
 	}
 
-	b->accessed = 1;
 	b->parent = parent;
 	bch_bset_init_next(&b->keys, b->keys.set->data, bset_magic(&b->c->sb));
 
@@ -1178,7 +1191,7 @@
 {
 	struct btree *n = bch_btree_node_alloc(b->c, op, b->level, b->parent);
 
-	if (!IS_ERR_OR_NULL(n)) {
+	if (!IS_ERR(n)) {
 		mutex_lock(&n->write_lock);
 		bch_btree_sort_into(&b->keys, &n->keys, &b->c->sort);
 		bkey_copy_key(&n->key, &b->key);
@@ -1393,7 +1406,7 @@
 
 	for (i = 0; i < nodes; i++) {
 		new_nodes[i] = btree_node_alloc_replacement(r[i].b, NULL);
-		if (IS_ERR_OR_NULL(new_nodes[i]))
+		if (IS_ERR(new_nodes[i]))
 			goto out_nocoalesce;
 	}
 
@@ -1440,7 +1453,7 @@
 			if (__set_blocks(n1, n1->keys + n2->keys,
 					 block_bytes(b->c)) >
 			    btree_blocks(new_nodes[i]))
-				goto out_nocoalesce;
+				goto out_unlock_nocoalesce;
 
 			keys = n2->keys;
 			/* Take the key of the node we're getting rid of */
@@ -1469,7 +1482,7 @@
 
 		if (__bch_keylist_realloc(&keylist,
 					  bkey_u64s(&new_nodes[i]->key)))
-			goto out_nocoalesce;
+			goto out_unlock_nocoalesce;
 
 		bch_btree_node_write(new_nodes[i], &cl);
 		bch_keylist_add(&keylist, &new_nodes[i]->key);
@@ -1515,6 +1528,10 @@
 	/* Invalidated our iterator */
 	return -EINTR;
 
+out_unlock_nocoalesce:
+	for (i = 0; i < nodes; i++)
+		mutex_unlock(&new_nodes[i]->write_lock);
+
 out_nocoalesce:
 	closure_sync(&cl);
 
@@ -1541,6 +1558,8 @@
 		return 0;
 
 	n = btree_node_alloc_replacement(replace, NULL);
+	if (IS_ERR(n))
+		return 0;
 
 	/* recheck reserve after allocating replacement node */
 	if (btree_check_reserve(b, NULL)) {
@@ -1706,7 +1725,7 @@
 	if (should_rewrite) {
 		n = btree_node_alloc_replacement(b, NULL);
 
-		if (!IS_ERR_OR_NULL(n)) {
+		if (!IS_ERR(n)) {
 			bch_btree_node_write_sync(n);
 
 			bch_btree_set_root(n);
@@ -2649,3 +2668,18 @@
 	spin_lock_init(&buf->lock);
 	array_allocator_init(&buf->freelist);
 }
+
+void bch_btree_exit(void)
+{
+	if (btree_io_wq)
+		destroy_workqueue(btree_io_wq);
+}
+
+int __init bch_btree_init(void)
+{
+	btree_io_wq = alloc_workqueue("bch_btree_io", WQ_MEM_RECLAIM, 0);
+	if (!btree_io_wq)
+		return -ENOMEM;
+
+	return 0;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/bcache/btree.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/bcache/btree.h
@@ -121,8 +121,6 @@
 	/* Key/pointer for this btree node */
 	BKEY_PADDED(key);
 
-	/* Single bit - set when accessed, cleared by shrinker */
-	unsigned long		accessed;
 	unsigned long		seq;
 	struct rw_semaphore	lock;
 	struct cache_set	*c;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/bcache/closure.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/bcache/closure.c
@@ -17,10 +17,16 @@
 {
 	int r = flags & CLOSURE_REMAINING_MASK;
 
-	BUG_ON(flags & CLOSURE_GUARD_MASK);
-	BUG_ON(!r && (flags & ~CLOSURE_DESTRUCTOR));
+	if (WARN(flags & CLOSURE_GUARD_MASK,
+		 "closure has guard bits set: %x (%u)",
+		 flags & CLOSURE_GUARD_MASK, (unsigned) __fls(r)))
+		r &= ~CLOSURE_GUARD_MASK;
 
 	if (!r) {
+		WARN(flags & ~CLOSURE_DESTRUCTOR,
+		     "closure ref hit 0 with incorrect flags set: %x (%u)",
+		     flags & ~CLOSURE_DESTRUCTOR, (unsigned) __fls(flags));
+
 		if (cl->fn && !(flags & CLOSURE_DESTRUCTOR)) {
 			atomic_set(&cl->remaining,
 				   CLOSURE_REMAINING_INITIALIZER);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/bcache/journal.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/bcache/journal.c
@@ -417,10 +417,15 @@
 
 /* Journalling */
 
+#define nr_to_fifo_front(p, front_p, mask)	(((p) - (front_p)) & (mask))
+
 static void btree_flush_write(struct cache_set *c)
 {
 	struct btree *b, *t, *btree_nodes[BTREE_FLUSH_NR];
-	unsigned int i, n;
+	unsigned int i, nr;
+	int ref_nr;
+	atomic_t *fifo_front_p, *now_fifo_front_p;
+	size_t mask;
 
 	if (c->journal.btree_flushing)
 		return;
@@ -433,12 +438,50 @@
 	c->journal.btree_flushing = true;
 	spin_unlock(&c->journal.flush_write_lock);
 
+	/* get the oldest journal entry and check its refcount */
+	spin_lock(&c->journal.lock);
+	fifo_front_p = &fifo_front(&c->journal.pin);
+	ref_nr = atomic_read(fifo_front_p);
+	if (ref_nr <= 0) {
+		/*
+		 * do nothing if no btree node references
+		 * the oldest journal entry
+		 */
+		spin_unlock(&c->journal.lock);
+		goto out;
+	}
+	spin_unlock(&c->journal.lock);
+
+	mask = c->journal.pin.mask;
+	nr = 0;
 	atomic_long_inc(&c->flush_write);
 	memset(btree_nodes, 0, sizeof(btree_nodes));
-	n = 0;
 
 	mutex_lock(&c->bucket_lock);
 	list_for_each_entry_safe_reverse(b, t, &c->btree_cache, list) {
+		/*
+		 * It is safe to get now_fifo_front_p without holding
+		 * c->journal.lock here, because we don't need to know
+		 * the exactly accurate value, just check whether the
+		 * front pointer of c->journal.pin is changed.
+		 */
+		now_fifo_front_p = &fifo_front(&c->journal.pin);
+		/*
+		 * If the oldest journal entry is reclaimed and front
+		 * pointer of c->journal.pin changes, it is unnecessary
+		 * to scan c->btree_cache anymore, just quit the loop and
+		 * flush out what we have already.
+		 */
+		if (now_fifo_front_p != fifo_front_p)
+			break;
+		/*
+		 * quit this loop if all matching btree nodes are
+		 * scanned and record in btree_nodes[] already.
+		 */
+		ref_nr = atomic_read(fifo_front_p);
+		if (nr >= ref_nr)
+			break;
+
 		if (btree_node_journal_flush(b))
 			pr_err("BUG: flush_write bit should not be set here!");
 
@@ -454,17 +497,44 @@
 			continue;
 		}
 
+		/*
+		 * Only select the btree node which exactly references
+		 * the oldest journal entry.
+		 *
+		 * If the journal entry pointed by fifo_front_p is
+		 * reclaimed in parallel, don't worry:
+		 * - the list_for_each_xxx loop will quit when checking
+		 *   next now_fifo_front_p.
+		 * - If there are matched nodes recorded in btree_nodes[],
+		 *   they are clean now (this is why and how the oldest
+		 *   journal entry can be reclaimed). These selected nodes
+		 *   will be ignored and skipped in the folowing for-loop.
+		 */
+		if (nr_to_fifo_front(btree_current_write(b)->journal,
+				     fifo_front_p,
+				     mask) != 0) {
+			mutex_unlock(&b->write_lock);
+			continue;
+		}
+
 		set_btree_node_journal_flush(b);
 
 		mutex_unlock(&b->write_lock);
 
-		btree_nodes[n++] = b;
-		if (n == BTREE_FLUSH_NR)
+		btree_nodes[nr++] = b;
+		/*
+		 * To avoid holding c->bucket_lock too long time,
+		 * only scan for BTREE_FLUSH_NR matched btree nodes
+		 * at most. If there are more btree nodes reference
+		 * the oldest journal entry, try to flush them next
+		 * time when btree_flush_write() is called.
+		 */
+		if (nr == BTREE_FLUSH_NR)
 			break;
 	}
 	mutex_unlock(&c->bucket_lock);
 
-	for (i = 0; i < n; i++) {
+	for (i = 0; i < nr; i++) {
 		b = btree_nodes[i];
 		if (!b) {
 			pr_err("BUG: btree_nodes[%d] is NULL", i);
@@ -497,6 +567,7 @@
 		mutex_unlock(&b->write_lock);
 	}
 
+out:
 	spin_lock(&c->journal.flush_write_lock);
 	c->journal.btree_flushing = false;
 	spin_unlock(&c->journal.flush_write_lock);
@@ -887,8 +958,8 @@
 		journal_try_write(c);
 	} else if (!w->dirty) {
 		w->dirty = true;
-		schedule_delayed_work(&c->journal.work,
-				      msecs_to_jiffies(c->journal_delay_ms));
+		queue_delayed_work(bch_flush_wq, &c->journal.work,
+				   msecs_to_jiffies(c->journal_delay_ms));
 		spin_unlock(&c->journal.lock);
 	} else {
 		spin_unlock(&c->journal.lock);
@@ -931,8 +1002,8 @@
 	j->w[1].c = c;
 
 	if (!(init_fifo(&j->pin, JOURNAL_PIN, GFP_KERNEL)) ||
-	    !(j->w[0].data = (void *) __get_free_pages(GFP_KERNEL, JSET_BITS)) ||
-	    !(j->w[1].data = (void *) __get_free_pages(GFP_KERNEL, JSET_BITS)))
+	    !(j->w[0].data = (void *) __get_free_pages(GFP_KERNEL|__GFP_COMP, JSET_BITS)) ||
+	    !(j->w[1].data = (void *) __get_free_pages(GFP_KERNEL|__GFP_COMP, JSET_BITS)))
 		return -ENOMEM;
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/bcache/request.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/bcache/request.c
@@ -391,13 +391,20 @@
 		goto skip;
 
 	/*
-	 * Flag for bypass if the IO is for read-ahead or background,
-	 * unless the read-ahead request is for metadata
+	 * If the bio is for read-ahead or background IO, bypass it or
+	 * not depends on the following situations,
+	 * - If the IO is for meta data, always cache it and no bypass
+	 * - If the IO is not meta data, check dc->cache_reada_policy,
+	 *      BCH_CACHE_READA_ALL: cache it and not bypass
+	 *      BCH_CACHE_READA_META_ONLY: not cache it and bypass
+	 * That is, read-ahead request for metadata always get cached
 	 * (eg, for gfs2 or xfs).
 	 */
-	if (bio->bi_opf & (REQ_RAHEAD|REQ_BACKGROUND) &&
-	    !(bio->bi_opf & (REQ_META|REQ_PRIO)))
-		goto skip;
+	if ((bio->bi_opf & (REQ_RAHEAD|REQ_BACKGROUND))) {
+		if (!(bio->bi_opf & (REQ_META|REQ_PRIO)) &&
+		    (dc->cache_readahead_policy != BCH_CACHE_READA_ALL))
+			goto skip;
+	}
 
 	if (bio->bi_iter.bi_sector & (c->sb.block_size - 1) ||
 	    bio_sectors(bio) & (c->sb.block_size - 1)) {
@@ -1112,6 +1119,12 @@
 	 * which would call closure_get(&dc->disk.cl)
 	 */
 	ddip = kzalloc(sizeof(struct detached_dev_io_private), GFP_NOIO);
+	if (!ddip) {
+		bio->bi_status = BLK_STS_RESOURCE;
+		bio->bi_end_io(bio);
+		return;
+	}
+
 	ddip->d = d;
 	ddip->start_time = jiffies;
 	ddip->bi_end_io = bio->bi_end_io;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/bcache/stats.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/bcache/stats.c
@@ -109,9 +109,13 @@
 
 void bch_cache_accounting_clear(struct cache_accounting *acc)
 {
-	memset(&acc->total.cache_hits,
-	       0,
-	       sizeof(struct cache_stats));
+	acc->total.cache_hits = 0;
+	acc->total.cache_misses = 0;
+	acc->total.cache_bypass_hits = 0;
+	acc->total.cache_bypass_misses = 0;
+	acc->total.cache_readaheads = 0;
+	acc->total.cache_miss_collisions = 0;
+	acc->total.sectors_bypassed = 0;
 }
 
 void bch_cache_accounting_destroy(struct cache_accounting *acc)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/bcache/super.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/bcache/super.c
@@ -48,6 +48,7 @@
 static DEFINE_IDA(bcache_device_idx);
 static wait_queue_head_t unregister_wait;
 struct workqueue_struct *bcache_wq;
+struct workqueue_struct *bch_flush_wq;
 struct workqueue_struct *bch_journal_wq;
 
 
@@ -427,7 +428,7 @@
 	closure_init_stack(&cl);
 	lockdep_assert_held(&bch_register_lock);
 
-	if (bch_bucket_alloc_set(c, RESERVE_BTREE, &k.key, 1, true))
+	if (bch_bucket_alloc_set(c, RESERVE_BTREE, &k.key, true))
 		return 1;
 
 	SET_KEY_SIZE(&k.key, c->sb.bucket_size);
@@ -529,12 +530,29 @@
 	closure_sync(cl);
 }
 
-void bch_prio_write(struct cache *ca)
+int bch_prio_write(struct cache *ca, bool wait)
 {
 	int i;
 	struct bucket *b;
 	struct closure cl;
 
+	pr_debug("free_prio=%zu, free_none=%zu, free_inc=%zu",
+		 fifo_used(&ca->free[RESERVE_PRIO]),
+		 fifo_used(&ca->free[RESERVE_NONE]),
+		 fifo_used(&ca->free_inc));
+
+	/*
+	 * Pre-check if there are enough free buckets. In the non-blocking
+	 * scenario it's better to fail early rather than starting to allocate
+	 * buckets and do a cleanup later in case of failure.
+	 */
+	if (!wait) {
+		size_t avail = fifo_used(&ca->free[RESERVE_PRIO]) +
+			       fifo_used(&ca->free[RESERVE_NONE]);
+		if (prio_buckets(ca) > avail)
+			return -ENOMEM;
+	}
+
 	closure_init_stack(&cl);
 
 	lockdep_assert_held(&ca->set->bucket_lock);
@@ -544,9 +562,6 @@
 	atomic_long_add(ca->sb.bucket_size * prio_buckets(ca),
 			&ca->meta_sectors_written);
 
-	//pr_debug("free %zu, free_inc %zu, unused %zu", fifo_used(&ca->free),
-	//	 fifo_used(&ca->free_inc), fifo_used(&ca->unused));
-
 	for (i = prio_buckets(ca) - 1; i >= 0; --i) {
 		long bucket;
 		struct prio_set *p = ca->disk_buckets;
@@ -564,7 +579,7 @@
 		p->magic	= pset_magic(&ca->sb);
 		p->csum		= bch_crc64(&p->magic, bucket_bytes(ca) - 8);
 
-		bucket = bch_bucket_alloc(ca, RESERVE_PRIO, true);
+		bucket = bch_bucket_alloc(ca, RESERVE_PRIO, wait);
 		BUG_ON(bucket == -1);
 
 		mutex_unlock(&ca->set->bucket_lock);
@@ -593,6 +608,7 @@
 
 		ca->prio_last_buckets[i] = ca->prio_buckets[i];
 	}
+	return 0;
 }
 
 static void prio_read(struct cache *ca, uint64_t bucket)
@@ -761,20 +777,31 @@
 
 static void bcache_device_free(struct bcache_device *d)
 {
+	struct gendisk *disk = d->disk;
+
 	lockdep_assert_held(&bch_register_lock);
 
-	pr_info("%s stopped", d->disk->disk_name);
+	if (disk)
+		pr_info("%s stopped", disk->disk_name);
+	else
+		pr_err("bcache device (NULL gendisk) stopped");
 
 	if (d->c)
 		bcache_device_detach(d);
-	if (d->disk && d->disk->flags & GENHD_FL_UP)
-		del_gendisk(d->disk);
-	if (d->disk && d->disk->queue)
-		blk_cleanup_queue(d->disk->queue);
-	if (d->disk) {
+
+	if (disk) {
+		bool disk_added = (disk->flags & GENHD_FL_UP) != 0;
+
+		if (disk_added)
+			del_gendisk(disk);
+
+		if (disk->queue)
+			blk_cleanup_queue(disk->queue);
+
 		ida_simple_remove(&bcache_device_idx,
-				  first_minor_to_idx(d->disk->first_minor));
-		put_disk(d->disk);
+				  first_minor_to_idx(disk->first_minor));
+		if (disk_added)
+			put_disk(disk);
 	}
 
 	bioset_exit(&d->bio_split);
@@ -785,24 +812,26 @@
 }
 
 static int bcache_device_init(struct bcache_device *d, unsigned int block_size,
-			      sector_t sectors)
+			      sector_t sectors, struct block_device *cached_bdev)
 {
 	struct request_queue *q;
 	const size_t max_stripes = min_t(size_t, INT_MAX,
 					 SIZE_MAX / sizeof(atomic_t));
-	size_t n;
+	uint64_t n;
 	int idx;
 
 	if (!d->stripe_size)
 		d->stripe_size = 1 << 31;
+	else if (d->stripe_size < BCH_MIN_STRIPE_SZ)
+		d->stripe_size = roundup(BCH_MIN_STRIPE_SZ, d->stripe_size);
 
-	d->nr_stripes = DIV_ROUND_UP_ULL(sectors, d->stripe_size);
-
-	if (!d->nr_stripes || d->nr_stripes > max_stripes) {
-		pr_err("nr_stripes too large or invalid: %u (start sector beyond end of disk?)",
-			(unsigned int)d->nr_stripes);
+	n = DIV_ROUND_UP_ULL(sectors, d->stripe_size);
+	if (!n || n > max_stripes) {
+		pr_err("nr_stripes too large or invalid: %llu (start sector beyond end of disk?)\n",
+			n);
 		return -ENOMEM;
 	}
+	d->nr_stripes = n;
 
 	n = d->nr_stripes * sizeof(atomic_t);
 	d->stripe_sectors_dirty = kvzalloc(n, GFP_KERNEL);
@@ -812,20 +841,20 @@
 	n = BITS_TO_LONGS(d->nr_stripes) * sizeof(unsigned long);
 	d->full_dirty_stripes = kvzalloc(n, GFP_KERNEL);
 	if (!d->full_dirty_stripes)
-		return -ENOMEM;
+		goto out_free_stripe_sectors_dirty;
 
 	idx = ida_simple_get(&bcache_device_idx, 0,
 				BCACHE_DEVICE_IDX_MAX, GFP_KERNEL);
 	if (idx < 0)
-		return idx;
+		goto out_free_full_dirty_stripes;
 
 	if (bioset_init(&d->bio_split, 4, offsetof(struct bbio, bio),
 			BIOSET_NEED_BVECS|BIOSET_NEED_RESCUER))
-		goto err;
+		goto out_ida_remove;
 
 	d->disk = alloc_disk(BCACHE_MINORS);
 	if (!d->disk)
-		goto err;
+		goto out_bioset_exit;
 
 	set_capacity(d->disk, sectors);
 	snprintf(d->disk->disk_name, DISK_NAME_LEN, "bcache%i", idx);
@@ -852,6 +881,21 @@
 	q->limits.io_min		= block_size;
 	q->limits.logical_block_size	= block_size;
 	q->limits.physical_block_size	= block_size;
+
+	if (q->limits.logical_block_size > PAGE_SIZE && cached_bdev) {
+		/*
+		 * This should only happen with BCACHE_SB_VERSION_BDEV.
+		 * Block/page size is checked for BCACHE_SB_VERSION_CDEV.
+		 */
+		pr_info("%s: sb/logical block size (%u) greater than page size "
+			"(%lu) falling back to device logical block size (%u)",
+			d->disk->disk_name, q->limits.logical_block_size,
+			PAGE_SIZE, bdev_logical_block_size(cached_bdev));
+
+		/* This also adjusts physical block size/min io size if needed */
+		blk_queue_logical_block_size(q, bdev_logical_block_size(cached_bdev));
+	}
+
 	blk_queue_flag_set(QUEUE_FLAG_NONROT, d->disk->queue);
 	blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, d->disk->queue);
 	blk_queue_flag_set(QUEUE_FLAG_DISCARD, d->disk->queue);
@@ -860,8 +904,14 @@
 
 	return 0;
 
-err:
+out_bioset_exit:
+	bioset_exit(&d->bio_split);
+out_ida_remove:
 	ida_simple_remove(&bcache_device_idx, idx);
+out_free_full_dirty_stripes:
+	kvfree(d->full_dirty_stripes);
+out_free_stripe_sectors_dirty:
+	kvfree(d->stripe_sectors_dirty);
 	return -ENOMEM;
 
 }
@@ -917,7 +967,7 @@
 }
 
 
-int bch_cached_dev_run(struct cached_dev *dc)
+void bch_cached_dev_emit_change(struct cached_dev *dc)
 {
 	struct bcache_device *d = &dc->disk;
 	char *buf = kmemdup_nul(dc->sb.label, SB_LABEL_SIZE, GFP_KERNEL);
@@ -928,19 +978,26 @@
 		NULL,
 	};
 
+	/*
+	 * won't show up in the uevent file, use udevadm monitor -e instead
+	 * only class / kset properties are persistent
+	 */
+	kobject_uevent_env(&disk_to_dev(d->disk)->kobj, KOBJ_CHANGE, env);
+	kfree(env[1]);
+	kfree(env[2]);
+	kfree(buf);
+}
+
+int bch_cached_dev_run(struct cached_dev *dc)
+{
+	struct bcache_device *d = &dc->disk;
 	if (dc->io_disable) {
 		pr_err("I/O disabled on cached dev %s",
 		       dc->backing_dev_name);
-		kfree(env[1]);
-		kfree(env[2]);
-		kfree(buf);
 		return -EIO;
 	}
 
 	if (atomic_xchg(&dc->running, 1)) {
-		kfree(env[1]);
-		kfree(env[2]);
-		kfree(buf);
 		pr_info("cached dev %s is running already",
 		       dc->backing_dev_name);
 		return -EBUSY;
@@ -959,14 +1016,9 @@
 
 	add_disk(d->disk);
 	bd_link_disk_holder(dc->bdev, dc->disk.disk);
-	/*
-	 * won't show up in the uevent file, use udevadm monitor -e instead
-	 * only class / kset properties are persistent
-	 */
-	kobject_uevent_env(&disk_to_dev(d->disk)->kobj, KOBJ_CHANGE, env);
-	kfree(env[1]);
-	kfree(env[2]);
-	kfree(buf);
+
+	/* emit change event */
+	bch_cached_dev_emit_change(dc);
 
 	if (sysfs_create_link(&d->kobj, &disk_to_dev(d->disk)->kobj, "dev") ||
 	    sysfs_create_link(&disk_to_dev(d->disk)->kobj,
@@ -1251,6 +1303,9 @@
 
 	mutex_unlock(&bch_register_lock);
 
+	if (dc->sb_bio.bi_inline_vecs[0].bv_page)
+		put_page(bio_first_page_all(&dc->sb_bio));
+
 	if (!IS_ERR_OR_NULL(dc->bdev))
 		blkdev_put(dc->bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
 
@@ -1305,7 +1360,7 @@
 			q->limits.raid_partial_stripes_expensive;
 
 	ret = bcache_device_init(&dc->disk, block_size,
-			 dc->bdev->bd_part->nr_sects - dc->sb.data_offset);
+			 dc->bdev->bd_part->nr_sects - dc->sb.data_offset, dc->bdev);
 	if (ret)
 		return ret;
 
@@ -1421,7 +1476,7 @@
 
 	kobject_init(&d->kobj, &bch_flash_dev_ktype);
 
-	if (bcache_device_init(d, block_bytes(c), u->sectors))
+	if (bcache_device_init(d, block_bytes(c), u->sectors, NULL))
 		goto err;
 
 	bcache_device_attach(d, c, u - c->uuids);
@@ -1725,7 +1780,7 @@
 }
 
 #define alloc_bucket_pages(gfp, c)			\
-	((void *) __get_free_pages(__GFP_ZERO|gfp, ilog2(bucket_pages(c))))
+	((void *) __get_free_pages(__GFP_ZERO|__GFP_COMP|gfp, ilog2(bucket_pages(c))))
 
 struct cache_set *bch_cache_set_alloc(struct cache_sb *sb)
 {
@@ -1769,6 +1824,7 @@
 	sema_init(&c->sb_write_mutex, 1);
 	mutex_init(&c->bucket_lock);
 	init_waitqueue_head(&c->btree_cache_wait);
+	spin_lock_init(&c->btree_cannibalize_lock);
 	init_waitqueue_head(&c->bucket_wait);
 	init_waitqueue_head(&c->gc_wait);
 	sema_init(&c->uuid_write_mutex, 1);
@@ -1869,7 +1925,7 @@
 		c->root = bch_btree_node_get(c, NULL, k,
 					     j->btree_level,
 					     true, NULL);
-		if (IS_ERR_OR_NULL(c->root))
+		if (IS_ERR(c->root))
 			goto err;
 
 		list_del_init(&c->root->list);
@@ -1954,7 +2010,7 @@
 
 		mutex_lock(&c->bucket_lock);
 		for_each_cache(ca, c, i)
-			bch_prio_write(ca);
+			bch_prio_write(ca, true);
 		mutex_unlock(&c->bucket_lock);
 
 		err = "cannot allocate new UUID bucket";
@@ -1963,7 +2019,7 @@
 
 		err = "cannot allocate new btree root";
 		c->root = __bch_btree_node_alloc(c, NULL, 0, true, NULL);
-		if (IS_ERR_OR_NULL(c->root))
+		if (IS_ERR(c->root))
 			goto err;
 
 		mutex_lock(&c->root->write_lock);
@@ -2062,7 +2118,14 @@
 	    sysfs_create_link(&c->kobj, &ca->kobj, buf))
 		goto err;
 
-	if (ca->sb.seq > c->sb.seq) {
+	/*
+	 * A special case is both ca->sb.seq and c->sb.seq are 0,
+	 * such condition happens on a new created cache device whose
+	 * super block is never flushed yet. In this case c->sb.version
+	 * and other members should be updated too, otherwise we will
+	 * have a mistaken super block version in cache set.
+	 */
+	if (ca->sb.seq > c->sb.seq || c->sb.seq == 0) {
 		c->sb.version		= ca->sb.version;
 		memcpy(c->sb.set_uuid, ca->sb.set_uuid, 16);
 		c->sb.flags             = ca->sb.flags;
@@ -2325,6 +2388,21 @@
 	return false;
 }
 
+static struct cached_dev *bch_find_cached_dev(struct block_device *bdev) {
+	struct cache_set *c, *tc;
+	struct cached_dev *dc, *t;
+
+	list_for_each_entry_safe(c, tc, &bch_cache_sets, list)
+		list_for_each_entry_safe(dc, t, &c->cached_devs, list)
+			if (dc->bdev == bdev)
+				return dc;
+	list_for_each_entry_safe(dc, t, &uncached_devices, list)
+		if (dc->bdev == bdev)
+			return dc;
+
+	return NULL;
+}
+
 static bool bch_is_open_cache(struct block_device *bdev)
 {
 	struct cache_set *c, *tc;
@@ -2346,29 +2424,36 @@
 static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr,
 			       const char *buffer, size_t size)
 {
-	ssize_t ret = -EINVAL;
-	const char *err = "cannot allocate memory";
+	const char *err;
 	char *path = NULL;
-	struct cache_sb *sb = NULL;
+	struct cache_sb *sb;
 	struct block_device *bdev = NULL;
-	struct page *sb_page = NULL;
+	struct cached_dev *dc = NULL;
+	struct page *sb_page;
+	ssize_t ret;
 
+	ret = -EBUSY;
+	err = "failed to reference bcache module";
 	if (!try_module_get(THIS_MODULE))
-		return -EBUSY;
+		goto out;
 
 	/* For latest state of bcache_is_reboot */
 	smp_mb();
+	err = "bcache is in reboot";
 	if (bcache_is_reboot)
-		return -EBUSY;
+		goto out_module_put;
 
+	ret = -ENOMEM;
+	err = "cannot allocate memory";
 	path = kstrndup(buffer, size, GFP_KERNEL);
 	if (!path)
-		goto err;
+		goto out_module_put;
 
 	sb = kmalloc(sizeof(struct cache_sb), GFP_KERNEL);
 	if (!sb)
-		goto err;
+		goto out_free_path;
 
+	ret = -EINVAL;
 	err = "failed to open device";
 	bdev = blkdev_get_by_path(strim(path),
 				  FMODE_READ|FMODE_WRITE|FMODE_EXCL,
@@ -2377,65 +2462,87 @@
 		if (bdev == ERR_PTR(-EBUSY)) {
 			bdev = lookup_bdev(strim(path));
 			mutex_lock(&bch_register_lock);
-			if (!IS_ERR(bdev) && bch_is_open(bdev))
+			if (!IS_ERR(bdev) && bch_is_open(bdev)) {
 				err = "device already registered";
-			else
+				/* emit CHANGE event for backing devices to export
+				 * CACHED_{UUID/LABEL} values to udev */
+				if (bch_is_open_backing(bdev)) {
+					dc = bch_find_cached_dev(bdev);
+					if (dc) {
+						bch_cached_dev_emit_change(dc);
+						err = "device already registered (emitting change event)";
+					}
+				}
+			} else {
 				err = "device busy";
+			}
 			mutex_unlock(&bch_register_lock);
 			if (!IS_ERR(bdev))
 				bdput(bdev);
 			if (attr == &ksysfs_register_quiet)
-				goto quiet_out;
+				goto done;
 		}
-		goto err;
+		goto out_free_sb;
 	}
 
 	err = "failed to set blocksize";
 	if (set_blocksize(bdev, 4096))
-		goto err_close;
+		goto out_blkdev_put;
 
 	err = read_super(sb, bdev, &sb_page);
 	if (err)
-		goto err_close;
+		goto out_blkdev_put;
 
 	err = "failed to register device";
 	if (SB_IS_BDEV(sb)) {
 		struct cached_dev *dc = kzalloc(sizeof(*dc), GFP_KERNEL);
 
 		if (!dc)
-			goto err_close;
+			goto out_put_sb_page;
 
 		mutex_lock(&bch_register_lock);
 		ret = register_bdev(sb, sb_page, bdev, dc);
 		mutex_unlock(&bch_register_lock);
 		/* blkdev_put() will be called in cached_dev_free() */
-		if (ret < 0)
-			goto err;
+		if (ret < 0) {
+			bdev = NULL;
+			goto out_put_sb_page;
+		}
 	} else {
 		struct cache *ca = kzalloc(sizeof(*ca), GFP_KERNEL);
 
 		if (!ca)
-			goto err_close;
+			goto out_put_sb_page;
 
 		/* blkdev_put() will be called in bch_cache_release() */
-		if (register_cache(sb, sb_page, bdev, ca) != 0)
-			goto err;
+		if (register_cache(sb, sb_page, bdev, ca) != 0) {
+			bdev = NULL;
+			goto out_put_sb_page;
+		}
 	}
-quiet_out:
-	ret = size;
-out:
-	if (sb_page)
-		put_page(sb_page);
+
+	put_page(sb_page);
+done:
 	kfree(sb);
 	kfree(path);
 	module_put(THIS_MODULE);
-	return ret;
+	return size;
 
-err_close:
-	blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
-err:
-	pr_info("error %s: %s", path, err);
-	goto out;
+out_put_sb_page:
+	put_page(sb_page);
+out_blkdev_put:
+	if (bdev)
+		blkdev_put(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
+out_free_sb:
+	kfree(sb);
+out_free_path:
+	kfree(path);
+	path = NULL;
+out_module_put:
+	module_put(THIS_MODULE);
+out:
+	pr_info("error %s: %s", path?path:"", err);
+	return ret;
 }
 
 
@@ -2597,6 +2704,9 @@
 		destroy_workqueue(bcache_wq);
 	if (bch_journal_wq)
 		destroy_workqueue(bch_journal_wq);
+	if (bch_flush_wq)
+		destroy_workqueue(bch_flush_wq);
+	bch_btree_exit();
 
 	if (bcache_major)
 		unregister_blkdev(bcache_major, "bcache");
@@ -2652,10 +2762,26 @@
 		return bcache_major;
 	}
 
+	if (bch_btree_init())
+		goto err;
+
 	bcache_wq = alloc_workqueue("bcache", WQ_MEM_RECLAIM, 0);
 	if (!bcache_wq)
 		goto err;
 
+	/*
+	 * Let's not make this `WQ_MEM_RECLAIM` for the following reasons:
+	 *
+	 * 1. It used `system_wq` before which also does no memory reclaim.
+	 * 2. With `WQ_MEM_RECLAIM` desktop stalls, increased boot times, and
+	 *    reduced throughput can be observed.
+	 *
+	 * We still want to user our own queue to not congest the `system_wq`.
+	 */
+	bch_flush_wq = alloc_workqueue("bch_flush", 0, 0);
+	if (!bch_flush_wq)
+		goto err;
+
 	bch_journal_wq = alloc_workqueue("bch_journal", WQ_MEM_RECLAIM, 0);
 	if (!bch_journal_wq)
 		goto err;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/bcache/sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/bcache/sysfs.c
@@ -27,6 +27,12 @@
 	NULL
 };
 
+static const char * const bch_reada_cache_policies[] = {
+	"all",
+	"meta-only",
+	NULL
+};
+
 /* Default is 0 ("auto") */
 static const char * const bch_stop_on_failure_modes[] = {
 	"auto",
@@ -100,16 +106,21 @@
 rw_attribute(sequential_cutoff);
 rw_attribute(data_csum);
 rw_attribute(cache_mode);
+rw_attribute(readahead_cache_policy);
 rw_attribute(stop_when_cache_set_failed);
 rw_attribute(writeback_metadata);
 rw_attribute(writeback_running);
 rw_attribute(writeback_percent);
 rw_attribute(writeback_delay);
 rw_attribute(writeback_rate);
+rw_attribute(writeback_consider_fragment);
 
 rw_attribute(writeback_rate_update_seconds);
 rw_attribute(writeback_rate_i_term_inverse);
 rw_attribute(writeback_rate_p_term_inverse);
+rw_attribute(writeback_rate_fp_term_low);
+rw_attribute(writeback_rate_fp_term_mid);
+rw_attribute(writeback_rate_fp_term_high);
 rw_attribute(writeback_rate_minimum);
 read_attribute(writeback_rate_debug);
 
@@ -167,6 +178,11 @@
 					       bch_cache_modes,
 					       BDEV_CACHE_MODE(&dc->sb));
 
+	if (attr == &sysfs_readahead_cache_policy)
+		return bch_snprint_string_list(buf, PAGE_SIZE,
+					      bch_reada_cache_policies,
+					      dc->cache_readahead_policy);
+
 	if (attr == &sysfs_stop_when_cache_set_failed)
 		return bch_snprint_string_list(buf, PAGE_SIZE,
 					       bch_stop_on_failure_modes,
@@ -178,6 +194,7 @@
 	var_printf(bypass_torture_test,	"%i");
 	var_printf(writeback_metadata,	"%i");
 	var_printf(writeback_running,	"%i");
+	var_printf(writeback_consider_fragment,	"%i");
 	var_print(writeback_delay);
 	var_print(writeback_percent);
 	sysfs_hprint(writeback_rate,
@@ -188,6 +205,9 @@
 	var_print(writeback_rate_update_seconds);
 	var_print(writeback_rate_i_term_inverse);
 	var_print(writeback_rate_p_term_inverse);
+	var_print(writeback_rate_fp_term_low);
+	var_print(writeback_rate_fp_term_mid);
+	var_print(writeback_rate_fp_term_high);
 	var_print(writeback_rate_minimum);
 
 	if (attr == &sysfs_writeback_rate_debug) {
@@ -286,6 +306,7 @@
 	sysfs_strtoul_bool(bypass_torture_test, dc->bypass_torture_test);
 	sysfs_strtoul_bool(writeback_metadata, dc->writeback_metadata);
 	sysfs_strtoul_bool(writeback_running, dc->writeback_running);
+	sysfs_strtoul_bool(writeback_consider_fragment, dc->writeback_consider_fragment);
 	sysfs_strtoul_clamp(writeback_delay, dc->writeback_delay, 0, UINT_MAX);
 
 	sysfs_strtoul_clamp(writeback_percent, dc->writeback_percent,
@@ -314,6 +335,16 @@
 	sysfs_strtoul_clamp(writeback_rate_p_term_inverse,
 			    dc->writeback_rate_p_term_inverse,
 			    1, UINT_MAX);
+	sysfs_strtoul_clamp(writeback_rate_fp_term_low,
+			    dc->writeback_rate_fp_term_low,
+			    1, dc->writeback_rate_fp_term_mid - 1);
+	sysfs_strtoul_clamp(writeback_rate_fp_term_mid,
+			    dc->writeback_rate_fp_term_mid,
+			    dc->writeback_rate_fp_term_low + 1,
+			    dc->writeback_rate_fp_term_high - 1);
+	sysfs_strtoul_clamp(writeback_rate_fp_term_high,
+			    dc->writeback_rate_fp_term_high,
+			    dc->writeback_rate_fp_term_mid + 1, UINT_MAX);
 	sysfs_strtoul_clamp(writeback_rate_minimum,
 			    dc->writeback_rate_minimum,
 			    1, UINT_MAX);
@@ -352,6 +383,15 @@
 		}
 	}
 
+	if (attr == &sysfs_readahead_cache_policy) {
+		v = __sysfs_match_string(bch_reada_cache_policies, -1, buf);
+		if (v < 0)
+			return v;
+
+		if ((unsigned int) v != dc->cache_readahead_policy)
+			dc->cache_readahead_policy = v;
+	}
+
 	if (attr == &sysfs_stop_when_cache_set_failed) {
 		v = __sysfs_match_string(bch_stop_on_failure_modes, -1, buf);
 		if (v < 0)
@@ -466,15 +506,20 @@
 	&sysfs_data_csum,
 #endif
 	&sysfs_cache_mode,
+	&sysfs_readahead_cache_policy,
 	&sysfs_stop_when_cache_set_failed,
 	&sysfs_writeback_metadata,
 	&sysfs_writeback_running,
 	&sysfs_writeback_delay,
 	&sysfs_writeback_percent,
 	&sysfs_writeback_rate,
+	&sysfs_writeback_consider_fragment,
 	&sysfs_writeback_rate_update_seconds,
 	&sysfs_writeback_rate_i_term_inverse,
 	&sysfs_writeback_rate_p_term_inverse,
+	&sysfs_writeback_rate_fp_term_low,
+	&sysfs_writeback_rate_fp_term_mid,
+	&sysfs_writeback_rate_fp_term_high,
 	&sysfs_writeback_rate_minimum,
 	&sysfs_writeback_rate_debug,
 	&sysfs_io_errors,
@@ -1035,7 +1080,7 @@
 			sum += INITIAL_PRIO - cached[i];
 
 		if (n)
-			do_div(sum, n);
+			sum = div64_u64(sum, n);
 
 		for (i = 0; i < ARRAY_SIZE(q); i++)
 			q[i] = INITIAL_PRIO - cached[n * (i + 1) /
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/bcache/writeback.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/bcache/writeback.c
@@ -88,6 +88,44 @@
 	int64_t integral_scaled;
 	uint32_t new_rate;
 
+	/*
+	 * We need to consider the number of dirty buckets as well
+	 * when calculating the proportional_scaled, Otherwise we might
+	 * have an unreasonable small writeback rate at a highly fragmented situation
+	 * when very few dirty sectors consumed a lot dirty buckets, the
+	 * worst case is when dirty buckets reached cutoff_writeback_sync and
+	 * dirty data is still not even reached to writeback percent, so the rate
+	 * still will be at the minimum value, which will cause the write
+	 * stuck at a non-writeback mode.
+	 */
+	struct cache_set *c = dc->disk.c;
+
+	int64_t dirty_buckets = c->nbuckets - c->avail_nbuckets;
+
+	if (dc->writeback_consider_fragment &&
+		c->gc_stats.in_use > BCH_WRITEBACK_FRAGMENT_THRESHOLD_LOW && dirty > 0) {
+		int64_t fragment =
+			div_s64((dirty_buckets *  c->sb.bucket_size), dirty);
+		int64_t fp_term;
+		int64_t fps;
+
+		if (c->gc_stats.in_use <= BCH_WRITEBACK_FRAGMENT_THRESHOLD_MID) {
+			fp_term = dc->writeback_rate_fp_term_low *
+			(c->gc_stats.in_use - BCH_WRITEBACK_FRAGMENT_THRESHOLD_LOW);
+		} else if (c->gc_stats.in_use <= BCH_WRITEBACK_FRAGMENT_THRESHOLD_HIGH) {
+			fp_term = dc->writeback_rate_fp_term_mid *
+			(c->gc_stats.in_use - BCH_WRITEBACK_FRAGMENT_THRESHOLD_MID);
+		} else {
+			fp_term = dc->writeback_rate_fp_term_high *
+			(c->gc_stats.in_use - BCH_WRITEBACK_FRAGMENT_THRESHOLD_HIGH);
+		}
+		fps = div_s64(dirty, dirty_buckets) * fp_term;
+		if (fragment > 3 && fps > proportional_scaled) {
+			/* Only overrite the p when fragment > 3 */
+			proportional_scaled = fps;
+		}
+	}
+
 	if ((error < 0 && dc->writeback_rate_integral > 0) ||
 	    (error > 0 && time_before64(local_clock(),
 			 dc->writeback_rate.next + NSEC_PER_MSEC))) {
@@ -119,27 +157,61 @@
 	dc->writeback_rate_target = target;
 }
 
+static bool idle_counter_exceeded(struct cache_set *c)
+{
+	int counter, dev_nr;
+
+	/*
+	 * If c->idle_counter is overflow (idel for really long time),
+	 * reset as 0 and not set maximum rate this time for code
+	 * simplicity.
+	 */
+	counter = atomic_inc_return(&c->idle_counter);
+	if (counter <= 0) {
+		atomic_set(&c->idle_counter, 0);
+		return false;
+	}
+
+	dev_nr = atomic_read(&c->attached_dev_nr);
+	if (dev_nr == 0)
+		return false;
+
+	/*
+	 * c->idle_counter is increased by writeback thread of all
+	 * attached backing devices, in order to represent a rough
+	 * time period, counter should be divided by dev_nr.
+	 * Otherwise the idle time cannot be larger with more backing
+	 * device attached.
+	 * The following calculation equals to checking
+	 *	(counter / dev_nr) < (dev_nr * 6)
+	 */
+	if (counter < (dev_nr * dev_nr * 6))
+		return false;
+
+	return true;
+}
+
+/*
+ * Idle_counter is increased every time when update_writeback_rate() is
+ * called. If all backing devices attached to the same cache set have
+ * identical dc->writeback_rate_update_seconds values, it is about 6
+ * rounds of update_writeback_rate() on each backing device before
+ * c->at_max_writeback_rate is set to 1, and then max wrteback rate set
+ * to each dc->writeback_rate.rate.
+ * In order to avoid extra locking cost for counting exact dirty cached
+ * devices number, c->attached_dev_nr is used to calculate the idle
+ * throushold. It might be bigger if not all cached device are in write-
+ * back mode, but it still works well with limited extra rounds of
+ * update_writeback_rate().
+ */
 static bool set_at_max_writeback_rate(struct cache_set *c,
 				       struct cached_dev *dc)
 {
 	/* Don't set max writeback rate if gc is running */
 	if (!c->gc_mark_valid)
 		return false;
-	/*
-	 * Idle_counter is increased everytime when update_writeback_rate() is
-	 * called. If all backing devices attached to the same cache set have
-	 * identical dc->writeback_rate_update_seconds values, it is about 6
-	 * rounds of update_writeback_rate() on each backing device before
-	 * c->at_max_writeback_rate is set to 1, and then max wrteback rate set
-	 * to each dc->writeback_rate.rate.
-	 * In order to avoid extra locking cost for counting exact dirty cached
-	 * devices number, c->attached_dev_nr is used to calculate the idle
-	 * throushold. It might be bigger if not all cached device are in write-
-	 * back mode, but it still works well with limited extra rounds of
-	 * update_writeback_rate().
-	 */
-	if (atomic_inc_return(&c->idle_counter) <
-	    atomic_read(&c->attached_dev_nr) * 6)
+
+	if (!idle_counter_exceeded(c))
 		return false;
 
 	if (atomic_read(&c->at_max_writeback_rate) != 1)
@@ -153,13 +225,10 @@
 	dc->writeback_rate_change = 0;
 
 	/*
-	 * Check c->idle_counter and c->at_max_writeback_rate agagain in case
-	 * new I/O arrives during before set_at_max_writeback_rate() returns.
-	 * Then the writeback rate is set to 1, and its new value should be
-	 * decided via __update_writeback_rate().
+	 * In case new I/O arrives during before
+	 * set_at_max_writeback_rate() returns.
 	 */
-	if ((atomic_read(&c->idle_counter) <
-	     atomic_read(&c->attached_dev_nr) * 6) ||
+	if (!idle_counter_exceeded(c) ||
 	    !atomic_read(&c->at_max_writeback_rate))
 		return false;
 
@@ -519,15 +588,19 @@
 				  uint64_t offset, int nr_sectors)
 {
 	struct bcache_device *d = c->devices[inode];
-	unsigned int stripe_offset, stripe, sectors_dirty;
+	unsigned int stripe_offset, sectors_dirty;
+	int stripe;
 
 	if (!d)
 		return;
 
+	stripe = offset_to_stripe(d, offset);
+	if (stripe < 0)
+		return;
+
 	if (UUID_FLASH_ONLY(&c->uuids[inode]))
 		atomic_long_add(nr_sectors, &c->flash_dev_dirty_sectors);
 
-	stripe = offset_to_stripe(d, offset);
 	stripe_offset = offset & (d->stripe_size - 1);
 
 	while (nr_sectors) {
@@ -567,12 +640,12 @@
 static void refill_full_stripes(struct cached_dev *dc)
 {
 	struct keybuf *buf = &dc->writeback_keys;
-	unsigned int start_stripe, stripe, next_stripe;
+	unsigned int start_stripe, next_stripe;
+	int stripe;
 	bool wrapped = false;
 
 	stripe = offset_to_stripe(&dc->disk, KEY_OFFSET(&buf->last_scanned));
-
-	if (stripe >= dc->disk.nr_stripes)
+	if (stripe < 0)
 		stripe = 0;
 
 	start_stripe = stripe;
@@ -812,6 +885,7 @@
 
 	dc->writeback_metadata		= true;
 	dc->writeback_running		= false;
+	dc->writeback_consider_fragment = true;
 	dc->writeback_percent		= 10;
 	dc->writeback_delay		= 30;
 	atomic_long_set(&dc->writeback_rate.rate, 1024);
@@ -819,6 +893,9 @@
 
 	dc->writeback_rate_update_seconds = WRITEBACK_RATE_UPDATE_SECS_DEFAULT;
 	dc->writeback_rate_p_term_inverse = 40;
+	dc->writeback_rate_fp_term_low = 1;
+	dc->writeback_rate_fp_term_mid = 10;
+	dc->writeback_rate_fp_term_high = 1000;
 	dc->writeback_rate_i_term_inverse = 10000;
 
 	WARN_ON(test_and_clear_bit(BCACHE_DEV_WB_RUNNING, &dc->disk.flags));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/bcache/writeback.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/bcache/writeback.h
@@ -16,6 +16,10 @@
 
 #define BCH_AUTO_GC_DIRTY_THRESHOLD	50
 
+#define BCH_WRITEBACK_FRAGMENT_THRESHOLD_LOW 50
+#define BCH_WRITEBACK_FRAGMENT_THRESHOLD_MID 57
+#define BCH_WRITEBACK_FRAGMENT_THRESHOLD_HIGH 64
+
 /*
  * 14 (16384ths) is chosen here as something that each backing device
  * should be a reasonable fraction of the share, and not to blow up
@@ -33,10 +37,22 @@
 	return ret;
 }
 
-static inline unsigned int offset_to_stripe(struct bcache_device *d,
+static inline int offset_to_stripe(struct bcache_device *d,
 					uint64_t offset)
 {
 	do_div(offset, d->stripe_size);
+
+	/* d->nr_stripes is in range [1, INT_MAX] */
+	if (unlikely(offset >= d->nr_stripes)) {
+		pr_err("Invalid stripe %llu (>= nr_stripes %d).\n",
+			offset, d->nr_stripes);
+		return -EINVAL;
+	}
+
+	/*
+	 * Here offset is definitly smaller than INT_MAX,
+	 * return it as int will never overflow.
+	 */
 	return offset;
 }
 
@@ -44,7 +60,10 @@
 					   uint64_t offset,
 					   unsigned int nr_sectors)
 {
-	unsigned int stripe = offset_to_stripe(&dc->disk, offset);
+	int stripe = offset_to_stripe(&dc->disk, offset);
+
+	if (stripe < 0)
+		return false;
 
 	while (1) {
 		if (atomic_read(dc->disk.stripe_sectors_dirty + stripe))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-bio-record.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-bio-record.h
@@ -20,8 +20,13 @@
 struct dm_bio_details {
 	struct gendisk *bi_disk;
 	u8 bi_partno;
+	int __bi_remaining;
 	unsigned long bi_flags;
 	struct bvec_iter bi_iter;
+	bio_end_io_t *bi_end_io;
+#if defined(CONFIG_BLK_DEV_INTEGRITY)
+	struct bio_integrity_payload *bi_integrity;
+#endif
 };
 
 static inline void dm_bio_record(struct dm_bio_details *bd, struct bio *bio)
@@ -30,6 +35,11 @@
 	bd->bi_partno = bio->bi_partno;
 	bd->bi_flags = bio->bi_flags;
 	bd->bi_iter = bio->bi_iter;
+	bd->__bi_remaining = atomic_read(&bio->__bi_remaining);
+	bd->bi_end_io = bio->bi_end_io;
+#if defined(CONFIG_BLK_DEV_INTEGRITY)
+	bd->bi_integrity = bio_integrity(bio);
+#endif
 }
 
 static inline void dm_bio_restore(struct dm_bio_details *bd, struct bio *bio)
@@ -38,6 +48,11 @@
 	bio->bi_partno = bd->bi_partno;
 	bio->bi_flags = bd->bi_flags;
 	bio->bi_iter = bd->bi_iter;
+	atomic_set(&bio->__bi_remaining, bd->__bi_remaining);
+	bio->bi_end_io = bd->bi_end_io;
+#if defined(CONFIG_BLK_DEV_INTEGRITY)
+	bio->bi_integrity = bd->bi_integrity;
+#endif
 }
 
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-bufio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-bufio.c
@@ -1438,6 +1438,10 @@
 sector_t dm_bufio_get_device_size(struct dm_bufio_client *c)
 {
 	sector_t s = i_size_read(c->bdev->bd_inode) >> SECTOR_SHIFT;
+	if (s >= c->start)
+		s -= c->start;
+	else
+		s = 0;
 	if (likely(c->sectors_per_block_bits >= 0))
 		s >>= c->sectors_per_block_bits;
 	else
@@ -1446,6 +1450,12 @@
 }
 EXPORT_SYMBOL_GPL(dm_bufio_get_device_size);
 
+struct dm_io_client *dm_bufio_get_dm_io_client(struct dm_bufio_client *c)
+{
+	return c->dm_io;
+}
+EXPORT_SYMBOL_GPL(dm_bufio_get_dm_io_client);
+
 sector_t dm_bufio_get_block_number(struct dm_buffer *b)
 {
 	return b->block;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-cache-metadata.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-cache-metadata.c
@@ -537,21 +537,27 @@
 					  CACHE_MAX_CONCURRENT_LOCKS);
 	if (IS_ERR(cmd->bm)) {
 		DMERR("could not create block manager");
-		return PTR_ERR(cmd->bm);
+		r = PTR_ERR(cmd->bm);
+		cmd->bm = NULL;
+		return r;
 	}
 
 	r = __open_or_format_metadata(cmd, may_format_device);
-	if (r)
+	if (r) {
 		dm_block_manager_destroy(cmd->bm);
+		cmd->bm = NULL;
+	}
 
 	return r;
 }
 
-static void __destroy_persistent_data_objects(struct dm_cache_metadata *cmd)
+static void __destroy_persistent_data_objects(struct dm_cache_metadata *cmd,
+					      bool destroy_bm)
 {
 	dm_sm_destroy(cmd->metadata_sm);
 	dm_tm_destroy(cmd->tm);
-	dm_block_manager_destroy(cmd->bm);
+	if (destroy_bm)
+		dm_block_manager_destroy(cmd->bm);
 }
 
 typedef unsigned long (*flags_mutator)(unsigned long);
@@ -822,7 +828,7 @@
 		cmd2 = lookup(bdev);
 		if (cmd2) {
 			mutex_unlock(&table_lock);
-			__destroy_persistent_data_objects(cmd);
+			__destroy_persistent_data_objects(cmd, true);
 			kfree(cmd);
 			return cmd2;
 		}
@@ -870,7 +876,7 @@
 		mutex_unlock(&table_lock);
 
 		if (!cmd->fail_io)
-			__destroy_persistent_data_objects(cmd);
+			__destroy_persistent_data_objects(cmd, true);
 		kfree(cmd);
 	}
 }
@@ -1804,14 +1810,52 @@
 
 int dm_cache_metadata_abort(struct dm_cache_metadata *cmd)
 {
-	int r;
+	int r = -EINVAL;
+	struct dm_block_manager *old_bm = NULL, *new_bm = NULL;
+
+	/* fail_io is double-checked with cmd->root_lock held below */
+	if (unlikely(cmd->fail_io))
+		return r;
+
+	/*
+	 * Replacement block manager (new_bm) is created and old_bm destroyed outside of
+	 * cmd root_lock to avoid ABBA deadlock that would result (due to life-cycle of
+	 * shrinker associated with the block manager's bufio client vs cmd root_lock).
+	 * - must take shrinker_rwsem without holding cmd->root_lock
+	 */
+	new_bm = dm_block_manager_create(cmd->bdev, DM_CACHE_METADATA_BLOCK_SIZE << SECTOR_SHIFT,
+					 CACHE_MAX_CONCURRENT_LOCKS);
 
 	WRITE_LOCK(cmd);
-	__destroy_persistent_data_objects(cmd);
-	r = __create_persistent_data_objects(cmd, false);
+	if (cmd->fail_io) {
+		WRITE_UNLOCK(cmd);
+		goto out;
+	}
+
+	__destroy_persistent_data_objects(cmd, false);
+	old_bm = cmd->bm;
+	if (IS_ERR(new_bm)) {
+		DMERR("could not create block manager during abort");
+		cmd->bm = NULL;
+		r = PTR_ERR(new_bm);
+		goto out_unlock;
+	}
+
+	cmd->bm = new_bm;
+	r = __open_or_format_metadata(cmd, false);
+	if (r) {
+		cmd->bm = NULL;
+		goto out_unlock;
+	}
+	new_bm = NULL;
+out_unlock:
 	if (r)
 		cmd->fail_io = true;
 	WRITE_UNLOCK(cmd);
+	dm_block_manager_destroy(old_bm);
+out:
+	if (new_bm && !IS_ERR(new_bm))
+		dm_block_manager_destroy(new_bm);
 
 	return r;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-cache-policy-smq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-cache-policy-smq.c
@@ -854,7 +854,13 @@
 
 	struct background_tracker *bg_work;
 
-	bool migrations_allowed;
+	bool migrations_allowed:1;
+
+	/*
+	 * If this is set the policy will try and clean the whole cache
+	 * even if the device is not idle.
+	 */
+	bool cleaner:1;
 };
 
 /*----------------------------------------------------------------*/
@@ -1133,7 +1139,7 @@
 	 * Cache entries may not be populated.  So we cannot rely on the
 	 * size of the clean queue.
 	 */
-	if (idle) {
+	if (idle || mq->cleaner) {
 		/*
 		 * We'd like to clean everything.
 		 */
@@ -1716,11 +1722,9 @@
 		*hotspot_block_size /= 2u;
 }
 
-static struct dm_cache_policy *__smq_create(dm_cblock_t cache_size,
-					    sector_t origin_size,
-					    sector_t cache_block_size,
-					    bool mimic_mq,
-					    bool migrations_allowed)
+static struct dm_cache_policy *
+__smq_create(dm_cblock_t cache_size, sector_t origin_size, sector_t cache_block_size,
+	     bool mimic_mq, bool migrations_allowed, bool cleaner)
 {
 	unsigned i;
 	unsigned nr_sentinels_per_queue = 2u * NR_CACHE_LEVELS;
@@ -1807,6 +1811,7 @@
 		goto bad_btracker;
 
 	mq->migrations_allowed = migrations_allowed;
+	mq->cleaner = cleaner;
 
 	return &mq->policy;
 
@@ -1830,21 +1835,24 @@
 					  sector_t origin_size,
 					  sector_t cache_block_size)
 {
-	return __smq_create(cache_size, origin_size, cache_block_size, false, true);
+	return __smq_create(cache_size, origin_size, cache_block_size,
+			    false, true, false);
 }
 
 static struct dm_cache_policy *mq_create(dm_cblock_t cache_size,
 					 sector_t origin_size,
 					 sector_t cache_block_size)
 {
-	return __smq_create(cache_size, origin_size, cache_block_size, true, true);
+	return __smq_create(cache_size, origin_size, cache_block_size,
+			    true, true, false);
 }
 
 static struct dm_cache_policy *cleaner_create(dm_cblock_t cache_size,
 					      sector_t origin_size,
 					      sector_t cache_block_size)
 {
-	return __smq_create(cache_size, origin_size, cache_block_size, false, false);
+	return __smq_create(cache_size, origin_size, cache_block_size,
+			    false, false, true);
 }
 
 /*----------------------------------------------------------------*/
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-cache-target.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-cache-target.c
@@ -1011,16 +1011,16 @@
 	if (get_cache_mode(cache) >= CM_READ_ONLY)
 		return;
 
-	if (dm_cache_metadata_set_needs_check(cache->cmd)) {
-		DMERR("%s: failed to set 'needs_check' flag in metadata", dev_name);
-		set_cache_mode(cache, CM_FAIL);
-	}
-
 	DMERR_LIMIT("%s: aborting current metadata transaction", dev_name);
 	if (dm_cache_metadata_abort(cache->cmd)) {
 		DMERR("%s: failed to abort metadata transaction", dev_name);
 		set_cache_mode(cache, CM_FAIL);
 	}
+
+	if (dm_cache_metadata_set_needs_check(cache->cmd)) {
+		DMERR("%s: failed to set 'needs_check' flag in metadata", dev_name);
+		set_cache_mode(cache, CM_FAIL);
+	}
 }
 
 static void metadata_operation_failed(struct cache *cache, const char *op, int r)
@@ -1910,6 +1910,7 @@
 
 		else
 			commit_needed = process_bio(cache, bio) || commit_needed;
+		cond_resched();
 	}
 
 	if (commit_needed)
@@ -1932,6 +1933,7 @@
 	while ((bio = bio_list_pop(&bios))) {
 		bio->bi_status = BLK_STS_DM_REQUEUE;
 		bio_endio(bio);
+		cond_resched();
 	}
 }
 
@@ -1972,6 +1974,8 @@
 		r = mg_start(cache, op, NULL);
 		if (r)
 			break;
+
+		cond_resched();
 	}
 }
 
@@ -1992,6 +1996,7 @@
 	if (cache->prison)
 		dm_bio_prison_destroy_v2(cache->prison);
 
+	cancel_delayed_work_sync(&cache->waker);
 	if (cache->wq)
 		destroy_workqueue(cache->wq);
 
@@ -2080,7 +2085,6 @@
 	sector_t cache_sectors;
 
 	struct dm_dev *origin_dev;
-	sector_t origin_sectors;
 
 	uint32_t block_size;
 
@@ -2162,6 +2166,7 @@
 static int parse_origin_dev(struct cache_args *ca, struct dm_arg_set *as,
 			    char **error)
 {
+	sector_t origin_sectors;
 	int r;
 
 	if (!at_least_one_arg(as, error))
@@ -2174,8 +2179,8 @@
 		return r;
 	}
 
-	ca->origin_sectors = get_dev_size(ca->origin_dev);
-	if (ca->ti->len > ca->origin_sectors) {
+	origin_sectors = get_dev_size(ca->origin_dev);
+	if (ca->ti->len > origin_sectors) {
 		*error = "Device size larger than cached device";
 		return -EINVAL;
 	}
@@ -2501,7 +2506,7 @@
 
 	ca->metadata_dev = ca->origin_dev = ca->cache_dev = NULL;
 
-	origin_blocks = cache->origin_sectors = ca->origin_sectors;
+	origin_blocks = cache->origin_sectors = ti->len;
 	origin_blocks = block_div(origin_blocks, ca->block_size);
 	cache->origin_blocks = to_oblock(origin_blocks);
 
@@ -2867,8 +2872,8 @@
 	prevent_background_work(cache);
 	BUG_ON(atomic_read(&cache->nr_io_migrations));
 
-	cancel_delayed_work(&cache->waker);
-	flush_workqueue(cache->wq);
+	cancel_delayed_work_sync(&cache->waker);
+	drain_workqueue(cache->wq);
 	WARN_ON(cache->tracker.in_flight);
 
 	/*
@@ -2994,19 +2999,19 @@
 static bool can_resize(struct cache *cache, dm_cblock_t new_size)
 {
 	if (from_cblock(new_size) > from_cblock(cache->cache_size)) {
-		if (cache->sized) {
-			DMERR("%s: unable to extend cache due to missing cache table reload",
-			      cache_device_name(cache));
-			return false;
-		}
+		DMERR("%s: unable to extend cache due to missing cache table reload",
+		      cache_device_name(cache));
+		return false;
 	}
 
 	/*
 	 * We can't drop a dirty block when shrinking the cache.
 	 */
-	while (from_cblock(new_size) < from_cblock(cache->cache_size)) {
-		new_size = to_cblock(from_cblock(new_size) + 1);
-		if (is_dirty(cache, new_size)) {
+	if (cache->loaded_mappings) {
+		new_size = to_cblock(find_next_bit(cache->dirty_bitset,
+						   from_cblock(cache->cache_size),
+						   from_cblock(new_size)));
+		if (new_size != cache->cache_size) {
 			DMERR("%s: unable to shrink cache; cache block %llu is dirty",
 			      cache_device_name(cache),
 			      (unsigned long long) from_cblock(new_size));
@@ -3042,20 +3047,15 @@
 	/*
 	 * Check to see if the cache has resized.
 	 */
-	if (!cache->sized) {
-		r = resize_cache_dev(cache, csize);
-		if (r)
-			return r;
-
-		cache->sized = true;
-
-	} else if (csize != cache->cache_size) {
+	if (!cache->sized || csize != cache->cache_size) {
 		if (!can_resize(cache, csize))
 			return -EINVAL;
 
 		r = resize_cache_dev(cache, csize);
 		if (r)
 			return r;
+
+		cache->sized = true;
 	}
 
 	if (!cache->loaded_mappings) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-clone-metadata.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-clone-metadata.c
@@ -67,23 +67,34 @@
  * To save constantly doing look ups on disk we keep an in core copy of the
  * on-disk bitmap, the region_map.
  *
- * To further reduce metadata I/O overhead we use a second bitmap, the dmap
- * (dirty bitmap), which tracks the dirty words, i.e. longs, of the region_map.
+ * In order to track which regions are hydrated during a metadata transaction,
+ * we use a second set of bitmaps, the dmap (dirty bitmap), which includes two
+ * bitmaps, namely dirty_regions and dirty_words. The dirty_regions bitmap
+ * tracks the regions that got hydrated during the current metadata
+ * transaction. The dirty_words bitmap tracks the dirty words, i.e. longs, of
+ * the dirty_regions bitmap.
+ *
+ * This allows us to precisely track the regions that were hydrated during the
+ * current metadata transaction and update the metadata accordingly, when we
+ * commit the current transaction. This is important because dm-clone should
+ * only commit the metadata of regions that were properly flushed to the
+ * destination device beforehand. Otherwise, in case of a crash, we could end
+ * up with a corrupted dm-clone device.
  *
  * When a region finishes hydrating dm-clone calls
  * dm_clone_set_region_hydrated(), or for discard requests
  * dm_clone_cond_set_range(), which sets the corresponding bits in region_map
  * and dmap.
  *
- * During a metadata commit we scan the dmap for dirty region_map words (longs)
- * and update accordingly the on-disk metadata. Thus, we don't have to flush to
- * disk the whole region_map. We can just flush the dirty region_map words.
+ * During a metadata commit we scan dmap->dirty_words and dmap->dirty_regions
+ * and update the on-disk metadata accordingly. Thus, we don't have to flush to
+ * disk the whole region_map. We can just flush the dirty region_map bits.
  *
- * We use a dirty bitmap, which is smaller than the original region_map, to
- * reduce the amount of memory accesses during a metadata commit. As dm-bitset
- * accesses the on-disk bitmap in 64-bit word granularity, there is no
- * significant benefit in tracking the dirty region_map bits with a smaller
- * granularity.
+ * We use the helper dmap->dirty_words bitmap, which is smaller than the
+ * original region_map, to reduce the amount of memory accesses during a
+ * metadata commit. Moreover, as dm-bitset also accesses the on-disk bitmap in
+ * 64-bit word granularity, the dirty_words bitmap helps us avoid useless disk
+ * accesses.
  *
  * We could update directly the on-disk bitmap, when dm-clone calls either
  * dm_clone_set_region_hydrated() or dm_clone_cond_set_range(), buts this
@@ -92,12 +103,13 @@
  * e.g., in a hooked overwrite bio's completion routine, and further reduce the
  * I/O completion latency.
  *
- * We maintain two dirty bitmaps. During a metadata commit we atomically swap
- * the currently used dmap with the unused one. This allows the metadata update
- * functions to run concurrently with an ongoing commit.
+ * We maintain two dirty bitmap sets. During a metadata commit we atomically
+ * swap the currently used dmap with the unused one. This allows the metadata
+ * update functions to run concurrently with an ongoing commit.
  */
 struct dirty_map {
 	unsigned long *dirty_words;
+	unsigned long *dirty_regions;
 	unsigned int changed;
 };
 
@@ -115,6 +127,9 @@
 	struct dirty_map dmap[2];
 	struct dirty_map *current_dmap;
 
+	/* Protected by lock */
+	struct dirty_map *committing_dmap;
+
 	/*
 	 * In core copy of the on-disk bitmap to save constantly doing look ups
 	 * on disk.
@@ -456,39 +471,53 @@
 
 /*---------------------------------------------------------------------------*/
 
-static size_t bitmap_size(unsigned long nr_bits)
+static int __dirty_map_init(struct dirty_map *dmap, unsigned long nr_words,
+			    unsigned long nr_regions)
 {
-	return BITS_TO_LONGS(nr_bits) * sizeof(long);
+	dmap->changed = 0;
+
+	dmap->dirty_words = kvzalloc(bitmap_size(nr_words), GFP_KERNEL);
+	if (!dmap->dirty_words)
+		return -ENOMEM;
+
+	dmap->dirty_regions = kvzalloc(bitmap_size(nr_regions), GFP_KERNEL);
+	if (!dmap->dirty_regions) {
+		kvfree(dmap->dirty_words);
+		return -ENOMEM;
+	}
+
+	return 0;
 }
 
-static int dirty_map_init(struct dm_clone_metadata *cmd)
+static void __dirty_map_exit(struct dirty_map *dmap)
 {
-	cmd->dmap[0].changed = 0;
-	cmd->dmap[0].dirty_words = kvzalloc(bitmap_size(cmd->nr_words), GFP_KERNEL);
+	kvfree(dmap->dirty_words);
+	kvfree(dmap->dirty_regions);
+}
 
-	if (!cmd->dmap[0].dirty_words) {
+static int dirty_map_init(struct dm_clone_metadata *cmd)
+{
+	if (__dirty_map_init(&cmd->dmap[0], cmd->nr_words, cmd->nr_regions)) {
 		DMERR("Failed to allocate dirty bitmap");
 		return -ENOMEM;
 	}
 
-	cmd->dmap[1].changed = 0;
-	cmd->dmap[1].dirty_words = kvzalloc(bitmap_size(cmd->nr_words), GFP_KERNEL);
-
-	if (!cmd->dmap[1].dirty_words) {
+	if (__dirty_map_init(&cmd->dmap[1], cmd->nr_words, cmd->nr_regions)) {
 		DMERR("Failed to allocate dirty bitmap");
-		kvfree(cmd->dmap[0].dirty_words);
+		__dirty_map_exit(&cmd->dmap[0]);
 		return -ENOMEM;
 	}
 
 	cmd->current_dmap = &cmd->dmap[0];
+	cmd->committing_dmap = NULL;
 
 	return 0;
 }
 
 static void dirty_map_exit(struct dm_clone_metadata *cmd)
 {
-	kvfree(cmd->dmap[0].dirty_words);
-	kvfree(cmd->dmap[1].dirty_words);
+	__dirty_map_exit(&cmd->dmap[0]);
+	__dirty_map_exit(&cmd->dmap[1]);
 }
 
 static int __load_bitset_in_core(struct dm_clone_metadata *cmd)
@@ -622,7 +651,7 @@
 	return (bit >= (start + nr_regions));
 }
 
-unsigned long dm_clone_nr_of_hydrated_regions(struct dm_clone_metadata *cmd)
+unsigned int dm_clone_nr_of_hydrated_regions(struct dm_clone_metadata *cmd)
 {
 	return bitmap_weight(cmd->region_map, cmd->nr_regions);
 }
@@ -633,21 +662,23 @@
 	return find_next_zero_bit(cmd->region_map, cmd->nr_regions, start);
 }
 
-static int __update_metadata_word(struct dm_clone_metadata *cmd, unsigned long word)
+static int __update_metadata_word(struct dm_clone_metadata *cmd,
+				  unsigned long *dirty_regions,
+				  unsigned long word)
 {
 	int r;
 	unsigned long index = word * BITS_PER_LONG;
 	unsigned long max_index = min(cmd->nr_regions, (word + 1) * BITS_PER_LONG);
 
 	while (index < max_index) {
-		if (test_bit(index, cmd->region_map)) {
+		if (test_bit(index, dirty_regions)) {
 			r = dm_bitset_set_bit(&cmd->bitset_info, cmd->bitset_root,
 					      index, &cmd->bitset_root);
-
 			if (r) {
 				DMERR("dm_bitset_set_bit failed");
 				return r;
 			}
+			__clear_bit(index, dirty_regions);
 		}
 		index++;
 	}
@@ -712,7 +743,7 @@
 static int __flush_dmap(struct dm_clone_metadata *cmd, struct dirty_map *dmap)
 {
 	int r;
-	unsigned long word, flags;
+	unsigned long word;
 
 	word = 0;
 	do {
@@ -721,7 +752,7 @@
 		if (word == cmd->nr_words)
 			break;
 
-		r = __update_metadata_word(cmd, word);
+		r = __update_metadata_word(cmd, dmap->dirty_regions, word);
 
 		if (r)
 			return r;
@@ -736,23 +767,24 @@
 		return r;
 
 	/* Update the changed flag */
-	spin_lock_irqsave(&cmd->bitmap_lock, flags);
+	spin_lock_irq(&cmd->bitmap_lock);
 	dmap->changed = 0;
-	spin_unlock_irqrestore(&cmd->bitmap_lock, flags);
+	spin_unlock_irq(&cmd->bitmap_lock);
 
 	return 0;
 }
 
-int dm_clone_metadata_commit(struct dm_clone_metadata *cmd)
+int dm_clone_metadata_pre_commit(struct dm_clone_metadata *cmd)
 {
-	int r = -EPERM;
-	unsigned long flags;
+	int r = 0;
 	struct dirty_map *dmap, *next_dmap;
 
 	down_write(&cmd->lock);
 
-	if (cmd->fail_io || dm_bm_is_read_only(cmd->bm))
+	if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) {
+		r = -EPERM;
 		goto out;
+	}
 
 	/* Get current dirty bitmap */
 	dmap = cmd->current_dmap;
@@ -764,21 +796,43 @@
 	 * The last commit failed, so we don't have a clean dirty-bitmap to
 	 * use.
 	 */
-	if (WARN_ON(next_dmap->changed)) {
+	if (WARN_ON(next_dmap->changed || cmd->committing_dmap)) {
 		r = -EINVAL;
 		goto out;
 	}
 
 	/* Swap dirty bitmaps */
-	spin_lock_irqsave(&cmd->bitmap_lock, flags);
+	spin_lock_irq(&cmd->bitmap_lock);
 	cmd->current_dmap = next_dmap;
-	spin_unlock_irqrestore(&cmd->bitmap_lock, flags);
+	spin_unlock_irq(&cmd->bitmap_lock);
 
-	/*
-	 * No one is accessing the old dirty bitmap anymore, so we can flush
-	 * it.
-	 */
-	r = __flush_dmap(cmd, dmap);
+	/* Set old dirty bitmap as currently committing */
+	cmd->committing_dmap = dmap;
+out:
+	up_write(&cmd->lock);
+
+	return r;
+}
+
+int dm_clone_metadata_commit(struct dm_clone_metadata *cmd)
+{
+	int r = -EPERM;
+
+	down_write(&cmd->lock);
+
+	if (cmd->fail_io || dm_bm_is_read_only(cmd->bm))
+		goto out;
+
+	if (WARN_ON(!cmd->committing_dmap)) {
+		r = -EINVAL;
+		goto out;
+	}
+
+	r = __flush_dmap(cmd, cmd->committing_dmap);
+	if (!r) {
+		/* Clear committing dmap */
+		cmd->committing_dmap = NULL;
+	}
 out:
 	up_write(&cmd->lock);
 
@@ -791,6 +845,12 @@
 	struct dirty_map *dmap;
 	unsigned long word, flags;
 
+	if (unlikely(region_nr >= cmd->nr_regions)) {
+		DMERR("Region %lu out of range (total number of regions %lu)",
+		      region_nr, cmd->nr_regions);
+		return -ERANGE;
+	}
+
 	word = region_nr / BITS_PER_LONG;
 
 	spin_lock_irqsave(&cmd->bitmap_lock, flags);
@@ -803,6 +863,7 @@
 	dmap = cmd->current_dmap;
 
 	__set_bit(word, dmap->dirty_words);
+	__set_bit(region_nr, dmap->dirty_regions);
 	__set_bit(region_nr, cmd->region_map);
 	dmap->changed = 1;
 
@@ -817,9 +878,16 @@
 {
 	int r = 0;
 	struct dirty_map *dmap;
-	unsigned long word, region_nr, flags;
+	unsigned long word, region_nr;
 
-	spin_lock_irqsave(&cmd->bitmap_lock, flags);
+	if (unlikely(start >= cmd->nr_regions || (start + nr_regions) < start ||
+		     (start + nr_regions) > cmd->nr_regions)) {
+		DMERR("Invalid region range: start %lu, nr_regions %lu (total number of regions %lu)",
+		      start, nr_regions, cmd->nr_regions);
+		return -ERANGE;
+	}
+
+	spin_lock_irq(&cmd->bitmap_lock);
 
 	if (cmd->read_only) {
 		r = -EPERM;
@@ -831,12 +899,13 @@
 		if (!test_bit(region_nr, cmd->region_map)) {
 			word = region_nr / BITS_PER_LONG;
 			__set_bit(word, dmap->dirty_words);
+			__set_bit(region_nr, dmap->dirty_regions);
 			__set_bit(region_nr, cmd->region_map);
 			dmap->changed = 1;
 		}
 	}
 out:
-	spin_unlock_irqrestore(&cmd->bitmap_lock, flags);
+	spin_unlock_irq(&cmd->bitmap_lock);
 
 	return r;
 }
@@ -903,13 +972,11 @@
 
 void dm_clone_metadata_set_read_only(struct dm_clone_metadata *cmd)
 {
-	unsigned long flags;
-
 	down_write(&cmd->lock);
 
-	spin_lock_irqsave(&cmd->bitmap_lock, flags);
+	spin_lock_irq(&cmd->bitmap_lock);
 	cmd->read_only = 1;
-	spin_unlock_irqrestore(&cmd->bitmap_lock, flags);
+	spin_unlock_irq(&cmd->bitmap_lock);
 
 	if (!cmd->fail_io)
 		dm_bm_set_read_only(cmd->bm);
@@ -919,13 +986,11 @@
 
 void dm_clone_metadata_set_read_write(struct dm_clone_metadata *cmd)
 {
-	unsigned long flags;
-
 	down_write(&cmd->lock);
 
-	spin_lock_irqsave(&cmd->bitmap_lock, flags);
+	spin_lock_irq(&cmd->bitmap_lock);
 	cmd->read_only = 0;
-	spin_unlock_irqrestore(&cmd->bitmap_lock, flags);
+	spin_unlock_irq(&cmd->bitmap_lock);
 
 	if (!cmd->fail_io)
 		dm_bm_set_read_write(cmd->bm);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-clone-metadata.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-clone-metadata.h
@@ -44,7 +44,9 @@
  * @start: Starting region number
  * @nr_regions: Number of regions in the range
  *
- * This function doesn't block, so it's safe to call it from interrupt context.
+ * This function doesn't block, but since it uses spin_lock_irq()/spin_unlock_irq()
+ * it's NOT safe to call it from any context where interrupts are disabled, e.g.,
+ * from interrupt context.
  */
 int dm_clone_cond_set_range(struct dm_clone_metadata *cmd, unsigned long start,
 			    unsigned long nr_regions);
@@ -73,7 +75,23 @@
 
 /*
  * Commit dm-clone metadata to disk.
+ *
+ * We use a two phase commit:
+ *
+ * 1. dm_clone_metadata_pre_commit(): Prepare the current transaction for
+ *    committing. After this is called, all subsequent metadata updates, done
+ *    through either dm_clone_set_region_hydrated() or
+ *    dm_clone_cond_set_range(), will be part of the **next** transaction.
+ *
+ * 2. dm_clone_metadata_commit(): Actually commit the current transaction to
+ *    disk and start a new transaction.
+ *
+ * This allows dm-clone to flush the destination device after step (1) to
+ * ensure that all freshly hydrated regions, for which we are updating the
+ * metadata, are properly written to non-volatile storage and won't be lost in
+ * case of a crash.
  */
+int dm_clone_metadata_pre_commit(struct dm_clone_metadata *cmd);
 int dm_clone_metadata_commit(struct dm_clone_metadata *cmd);
 
 /*
@@ -110,6 +128,7 @@
  * Switches metadata to a read only mode. Once read-only mode has been entered
  * the following functions will return -EPERM:
  *
+ *   dm_clone_metadata_pre_commit()
  *   dm_clone_metadata_commit()
  *   dm_clone_set_region_hydrated()
  *   dm_clone_cond_set_range()
@@ -137,7 +156,7 @@
 /*
  * Returns the number of hydrated regions.
  */
-unsigned long dm_clone_nr_of_hydrated_regions(struct dm_clone_metadata *cmd);
+unsigned int dm_clone_nr_of_hydrated_regions(struct dm_clone_metadata *cmd);
 
 /*
  * Returns the first unhydrated region with region_nr >= @start
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-clone-target.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-clone-target.c
@@ -86,6 +86,12 @@
 
 	struct dm_clone_metadata *cmd;
 
+	/*
+	 * bio used to flush the destination device, before committing the
+	 * metadata.
+	 */
+	struct bio flush_bio;
+
 	/* Region hydration hash table */
 	struct hash_table_bucket *ht;
 
@@ -276,7 +282,7 @@
 /* Get the address of the region in sectors */
 static inline sector_t region_to_sector(struct clone *clone, unsigned long region_nr)
 {
-	return (region_nr << clone->region_shift);
+	return ((sector_t)region_nr << clone->region_shift);
 }
 
 /* Get the region number of the bio */
@@ -287,10 +293,17 @@
 
 /* Get the region range covered by the bio */
 static void bio_region_range(struct clone *clone, struct bio *bio,
-			     unsigned long *rs, unsigned long *re)
+			     unsigned long *rs, unsigned long *nr_regions)
 {
+	unsigned long end;
+
 	*rs = dm_sector_div_up(bio->bi_iter.bi_sector, clone->region_size);
-	*re = bio_end_sector(bio) >> clone->region_shift;
+	end = bio_end_sector(bio) >> clone->region_shift;
+
+	if (*rs >= end)
+		*nr_regions = 0;
+	else
+		*nr_regions = end - *rs;
 }
 
 /* Check whether a bio overwrites a region */
@@ -332,8 +345,6 @@
  */
 static void issue_bio(struct clone *clone, struct bio *bio)
 {
-	unsigned long flags;
-
 	if (!bio_triggers_commit(clone, bio)) {
 		generic_make_request(bio);
 		return;
@@ -352,9 +363,9 @@
 	 * Batch together any bios that trigger commits and then issue a single
 	 * commit for them in process_deferred_flush_bios().
 	 */
-	spin_lock_irqsave(&clone->lock, flags);
+	spin_lock_irq(&clone->lock);
 	bio_list_add(&clone->deferred_flush_bios, bio);
-	spin_unlock_irqrestore(&clone->lock, flags);
+	spin_unlock_irq(&clone->lock);
 
 	wake_worker(clone);
 }
@@ -450,7 +461,7 @@
 
 static void complete_discard_bio(struct clone *clone, struct bio *bio, bool success)
 {
-	unsigned long rs, re;
+	unsigned long rs, nr_regions;
 
 	/*
 	 * If the destination device supports discards, remap and trim the
@@ -459,9 +470,9 @@
 	 */
 	if (test_bit(DM_CLONE_DISCARD_PASSDOWN, &clone->flags) && success) {
 		remap_to_dest(clone, bio);
-		bio_region_range(clone, bio, &rs, &re);
-		trim_bio(bio, rs << clone->region_shift,
-			 (re - rs) << clone->region_shift);
+		bio_region_range(clone, bio, &rs, &nr_regions);
+		trim_bio(bio, region_to_sector(clone, rs),
+			 nr_regions << clone->region_shift);
 		generic_make_request(bio);
 	} else
 		bio_endio(bio);
@@ -469,12 +480,21 @@
 
 static void process_discard_bio(struct clone *clone, struct bio *bio)
 {
-	unsigned long rs, re, flags;
+	unsigned long rs, nr_regions;
 
-	bio_region_range(clone, bio, &rs, &re);
-	BUG_ON(re > clone->nr_regions);
+	bio_region_range(clone, bio, &rs, &nr_regions);
+	if (!nr_regions) {
+		bio_endio(bio);
+		return;
+	}
 
-	if (unlikely(rs == re)) {
+	if (WARN_ON(rs >= clone->nr_regions || (rs + nr_regions) < rs ||
+		    (rs + nr_regions) > clone->nr_regions)) {
+		DMERR("%s: Invalid range (%lu + %lu, total regions %lu) for discard (%llu + %u)",
+		      clone_device_name(clone), rs, nr_regions,
+		      clone->nr_regions,
+		      (unsigned long long)bio->bi_iter.bi_sector,
+		      bio_sectors(bio));
 		bio_endio(bio);
 		return;
 	}
@@ -483,7 +503,7 @@
 	 * The covered regions are already hydrated so we just need to pass
 	 * down the discard.
 	 */
-	if (dm_clone_is_range_hydrated(clone->cmd, rs, re - rs)) {
+	if (dm_clone_is_range_hydrated(clone->cmd, rs, nr_regions)) {
 		complete_discard_bio(clone, bio, true);
 		return;
 	}
@@ -501,9 +521,9 @@
 	/*
 	 * Defer discard processing.
 	 */
-	spin_lock_irqsave(&clone->lock, flags);
+	spin_lock_irq(&clone->lock);
 	bio_list_add(&clone->deferred_discard_bios, bio);
-	spin_unlock_irqrestore(&clone->lock, flags);
+	spin_unlock_irq(&clone->lock);
 
 	wake_worker(clone);
 }
@@ -778,11 +798,14 @@
 	struct dm_io_region from, to;
 	struct clone *clone = hd->clone;
 
+	if (WARN_ON(!nr_regions))
+		return;
+
 	region_size = clone->region_size;
 	region_start = hd->region_nr;
 	region_end = region_start + nr_regions - 1;
 
-	total_size = (nr_regions - 1) << clone->region_shift;
+	total_size = region_to_sector(clone, nr_regions - 1);
 
 	if (region_end == clone->nr_regions - 1) {
 		/*
@@ -1106,10 +1129,13 @@
 /*
  * A non-zero return indicates read-only or fail mode.
  */
-static int commit_metadata(struct clone *clone)
+static int commit_metadata(struct clone *clone, bool *dest_dev_flushed)
 {
 	int r = 0;
 
+	if (dest_dev_flushed)
+		*dest_dev_flushed = false;
+
 	mutex_lock(&clone->commit_lock);
 
 	if (!dm_clone_changed_this_transaction(clone->cmd))
@@ -1120,8 +1146,26 @@
 		goto out;
 	}
 
-	r = dm_clone_metadata_commit(clone->cmd);
+	r = dm_clone_metadata_pre_commit(clone->cmd);
+	if (unlikely(r)) {
+		__metadata_operation_failed(clone, "dm_clone_metadata_pre_commit", r);
+		goto out;
+	}
+
+	bio_reset(&clone->flush_bio);
+	bio_set_dev(&clone->flush_bio, clone->dest_dev->bdev);
+	clone->flush_bio.bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
+
+	r = submit_bio_wait(&clone->flush_bio);
+	if (unlikely(r)) {
+		__metadata_operation_failed(clone, "flush destination device", r);
+		goto out;
+	}
 
+	if (dest_dev_flushed)
+		*dest_dev_flushed = true;
+
+	r = dm_clone_metadata_commit(clone->cmd);
 	if (unlikely(r)) {
 		__metadata_operation_failed(clone, "dm_clone_metadata_commit", r);
 		goto out;
@@ -1140,13 +1184,13 @@
 	int r = -EPERM;
 	struct bio *bio;
 	struct blk_plug plug;
-	unsigned long rs, re, flags;
+	unsigned long rs, nr_regions;
 	struct bio_list discards = BIO_EMPTY_LIST;
 
-	spin_lock_irqsave(&clone->lock, flags);
+	spin_lock_irq(&clone->lock);
 	bio_list_merge(&discards, &clone->deferred_discard_bios);
 	bio_list_init(&clone->deferred_discard_bios);
-	spin_unlock_irqrestore(&clone->lock, flags);
+	spin_unlock_irq(&clone->lock);
 
 	if (bio_list_empty(&discards))
 		return;
@@ -1156,14 +1200,13 @@
 
 	/* Update the metadata */
 	bio_list_for_each(bio, &discards) {
-		bio_region_range(clone, bio, &rs, &re);
+		bio_region_range(clone, bio, &rs, &nr_regions);
 		/*
 		 * A discard request might cover regions that have been already
 		 * hydrated. There is no need to update the metadata for these
 		 * regions.
 		 */
-		r = dm_clone_cond_set_range(clone->cmd, rs, re - rs);
-
+		r = dm_clone_cond_set_range(clone->cmd, rs, nr_regions);
 		if (unlikely(r))
 			break;
 	}
@@ -1176,13 +1219,12 @@
 
 static void process_deferred_bios(struct clone *clone)
 {
-	unsigned long flags;
 	struct bio_list bios = BIO_EMPTY_LIST;
 
-	spin_lock_irqsave(&clone->lock, flags);
+	spin_lock_irq(&clone->lock);
 	bio_list_merge(&bios, &clone->deferred_bios);
 	bio_list_init(&clone->deferred_bios);
-	spin_unlock_irqrestore(&clone->lock, flags);
+	spin_unlock_irq(&clone->lock);
 
 	if (bio_list_empty(&bios))
 		return;
@@ -1193,7 +1235,7 @@
 static void process_deferred_flush_bios(struct clone *clone)
 {
 	struct bio *bio;
-	unsigned long flags;
+	bool dest_dev_flushed;
 	struct bio_list bios = BIO_EMPTY_LIST;
 	struct bio_list bio_completions = BIO_EMPTY_LIST;
 
@@ -1201,19 +1243,19 @@
 	 * If there are any deferred flush bios, we must commit the metadata
 	 * before issuing them or signaling their completion.
 	 */
-	spin_lock_irqsave(&clone->lock, flags);
+	spin_lock_irq(&clone->lock);
 	bio_list_merge(&bios, &clone->deferred_flush_bios);
 	bio_list_init(&clone->deferred_flush_bios);
 
 	bio_list_merge(&bio_completions, &clone->deferred_flush_completions);
 	bio_list_init(&clone->deferred_flush_completions);
-	spin_unlock_irqrestore(&clone->lock, flags);
+	spin_unlock_irq(&clone->lock);
 
 	if (bio_list_empty(&bios) && bio_list_empty(&bio_completions) &&
 	    !(dm_clone_changed_this_transaction(clone->cmd) && need_commit_due_to_time(clone)))
 		return;
 
-	if (commit_metadata(clone)) {
+	if (commit_metadata(clone, &dest_dev_flushed)) {
 		bio_list_merge(&bios, &bio_completions);
 
 		while ((bio = bio_list_pop(&bios)))
@@ -1227,8 +1269,17 @@
 	while ((bio = bio_list_pop(&bio_completions)))
 		bio_endio(bio);
 
-	while ((bio = bio_list_pop(&bios)))
-		generic_make_request(bio);
+	while ((bio = bio_list_pop(&bios))) {
+		if ((bio->bi_opf & REQ_PREFLUSH) && dest_dev_flushed) {
+			/* We just flushed the destination device as part of
+			 * the metadata commit, so there is no reason to send
+			 * another flush.
+			 */
+			bio_endio(bio);
+		} else {
+			generic_make_request(bio);
+		}
+	}
 }
 
 static void do_worker(struct work_struct *work)
@@ -1400,7 +1451,7 @@
 
 		/* Commit to ensure statistics aren't out-of-date */
 		if (!(status_flags & DM_STATUS_NOFLUSH_FLAG) && !dm_suspended(ti))
-			(void) commit_metadata(clone);
+			(void) commit_metadata(clone, NULL);
 
 		r = dm_clone_get_free_metadata_block_count(clone->cmd, &nr_free_metadata_blocks);
 
@@ -1418,7 +1469,7 @@
 			goto error;
 		}
 
-		DMEMIT("%u %llu/%llu %llu %lu/%lu %u ",
+		DMEMIT("%u %llu/%llu %llu %u/%lu %u ",
 		       DM_CLONE_METADATA_BLOCK_SIZE,
 		       (unsigned long long)(nr_metadata_blocks - nr_free_metadata_blocks),
 		       (unsigned long long)nr_metadata_blocks,
@@ -1738,6 +1789,7 @@
 static int clone_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 {
 	int r;
+	sector_t nr_regions;
 	struct clone *clone;
 	struct dm_arg_set as;
 
@@ -1779,7 +1831,16 @@
 		goto out_with_source_dev;
 
 	clone->region_shift = __ffs(clone->region_size);
-	clone->nr_regions = dm_sector_div_up(ti->len, clone->region_size);
+	nr_regions = dm_sector_div_up(ti->len, clone->region_size);
+
+	/* Check for overflow */
+	if (nr_regions != (unsigned long)nr_regions) {
+		ti->error = "Too many regions. Consider increasing the region size";
+		r = -EOVERFLOW;
+		goto out_with_source_dev;
+	}
+
+	clone->nr_regions = nr_regions;
 
 	r = validate_nr_regions(clone->nr_regions, &ti->error);
 	if (r)
@@ -1834,6 +1895,7 @@
 	bio_list_init(&clone->deferred_flush_completions);
 	clone->hydration_offset = 0;
 	atomic_set(&clone->hydrations_in_flight, 0);
+	bio_init(&clone->flush_bio, NULL, 0);
 
 	clone->wq = alloc_workqueue("dm-" DM_MSG_PREFIX, WQ_MEM_RECLAIM, 0);
 	if (!clone->wq) {
@@ -1907,6 +1969,7 @@
 	struct clone *clone = ti->private;
 
 	mutex_destroy(&clone->commit_lock);
+	bio_uninit(&clone->flush_bio);
 
 	for (i = 0; i < clone->nr_ctr_args; i++)
 		kfree(clone->ctr_args[i]);
@@ -1914,6 +1977,7 @@
 
 	mempool_exit(&clone->hydration_pool);
 	dm_kcopyd_client_destroy(clone->kcopyd_client);
+	cancel_delayed_work_sync(&clone->waker);
 	destroy_workqueue(clone->wq);
 	hash_table_exit(clone);
 	dm_clone_metadata_close(clone->cmd);
@@ -1961,7 +2025,7 @@
 	wait_event(clone->hydration_stopped, !atomic_read(&clone->hydrations_in_flight));
 	flush_workqueue(clone->wq);
 
-	(void) commit_metadata(clone);
+	(void) commit_metadata(clone, NULL);
 }
 
 static void clone_resume(struct dm_target *ti)
@@ -2168,6 +2232,7 @@
 	r = dm_register_target(&clone_target);
 	if (r < 0) {
 		DMERR("Failed to register clone target");
+		kmem_cache_destroy(_hydration_cache);
 		return r;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-core.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-core.h
@@ -18,6 +18,8 @@
 #include "dm.h"
 
 #define DM_RESERVED_MAX_IOS		1024
+#define DM_MAX_TARGETS			1048576
+#define DM_MAX_TARGET_PARAMS		1024
 
 struct dm_kobject_holder {
 	struct kobject kobj;
@@ -106,6 +108,10 @@
 
 	struct block_device *bdev;
 
+	int swap_bios;
+	struct semaphore swap_bios_semaphore;
+	struct mutex swap_bios_lock;
+
 	struct dm_stats stats;
 
 	/* for blk-mq request-based DM support */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-crypt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-crypt.c
@@ -46,11 +46,11 @@
 struct convert_context {
 	struct completion restart;
 	struct bio *bio_in;
-	struct bio *bio_out;
 	struct bvec_iter iter_in;
+	struct bio *bio_out;
 	struct bvec_iter iter_out;
-	u64 cc_sector;
 	atomic_t cc_pending;
+	u64 cc_sector;
 	union {
 		struct skcipher_request *req;
 		struct aead_request *req_aead;
@@ -331,8 +331,14 @@
 static int crypt_iv_benbi_ctr(struct crypt_config *cc, struct dm_target *ti,
 			      const char *opts)
 {
-	unsigned bs = crypto_skcipher_blocksize(any_tfm(cc));
-	int log = ilog2(bs);
+	unsigned bs;
+	int log;
+
+	if (test_bit(CRYPT_MODE_INTEGRITY_AEAD, &cc->cipher_flags))
+		bs = crypto_aead_blocksize(any_tfm_aead(cc));
+	else
+		bs = crypto_skcipher_blocksize(any_tfm(cc));
+	log = ilog2(bs);
 
 	/* we need to calculate how far we must shift the sector count
 	 * to get the cipher block count, we use this shift in _gen */
@@ -714,10 +720,10 @@
 	u8 buf[MAX_CIPHER_BLOCKSIZE] __aligned(__alignof__(__le64));
 	struct skcipher_request *req;
 	struct scatterlist src, dst;
-	struct crypto_wait wait;
+	DECLARE_CRYPTO_WAIT(wait);
 	int err;
 
-	req = skcipher_request_alloc(any_tfm(cc), GFP_KERNEL | GFP_NOFS);
+	req = skcipher_request_alloc(any_tfm(cc), GFP_NOIO);
 	if (!req)
 		return -ENOMEM;
 
@@ -1548,6 +1554,7 @@
 			io = crypt_io_from_node(rb_first(&write_tree));
 			rb_erase(&io->rb_node, &write_tree);
 			kcryptd_io_write(io);
+			cond_resched();
 		} while (!RB_EMPTY_ROOT(&write_tree));
 		blk_finish_plug(&plug);
 	}
@@ -1620,6 +1627,12 @@
 	io->ctx.bio_out = clone;
 	io->ctx.iter_out = clone->bi_iter;
 
+	if (crypt_integrity_aead(cc)) {
+		bio_copy_data(clone, io->base_bio);
+		io->ctx.bio_in = clone;
+		io->ctx.iter_in = clone->bi_iter;
+	}
+
 	sector += bio_sectors(clone);
 
 	crypt_inc_pending(io);
@@ -2004,7 +2017,7 @@
 
 static int get_key_size(char **key_string)
 {
-	return (*key_string[0] == ':') ? -EINVAL : strlen(*key_string) >> 1;
+	return (*key_string[0] == ':') ? -EINVAL : (int)(strlen(*key_string) >> 1);
 }
 
 #endif
@@ -2086,7 +2099,12 @@
 	struct crypt_config *cc = pool_data;
 	struct page *page;
 
-	if (unlikely(percpu_counter_compare(&cc->n_allocated_pages, dm_crypt_pages_per_client) >= 0) &&
+	/*
+	 * Note, percpu_counter_read_positive() may over (and under) estimate
+	 * the current usage by at most (batch - 1) * num_online_cpus() pages,
+	 * but avoids potential spinlock contention of an exact result.
+	 */
+	if (unlikely(percpu_counter_read_positive(&cc->n_allocated_pages) >= dm_crypt_pages_per_client) &&
 	    likely(gfp_mask & __GFP_NORETRY))
 		return NULL;
 
@@ -2700,21 +2718,18 @@
 	}
 
 	ret = -ENOMEM;
-	cc->io_queue = alloc_workqueue("kcryptd_io/%s",
-				       WQ_HIGHPRI | WQ_CPU_INTENSIVE | WQ_MEM_RECLAIM,
-				       1, devname);
+	cc->io_queue = alloc_workqueue("kcryptd_io/%s", WQ_MEM_RECLAIM, 1, devname);
 	if (!cc->io_queue) {
 		ti->error = "Couldn't create kcryptd io queue";
 		goto bad;
 	}
 
 	if (test_bit(DM_CRYPT_SAME_CPU, &cc->flags))
-		cc->crypt_queue = alloc_workqueue("kcryptd/%s",
-						  WQ_HIGHPRI | WQ_CPU_INTENSIVE | WQ_MEM_RECLAIM,
+		cc->crypt_queue = alloc_workqueue("kcryptd/%s", WQ_CPU_INTENSIVE | WQ_MEM_RECLAIM,
 						  1, devname);
 	else
 		cc->crypt_queue = alloc_workqueue("kcryptd/%s",
-						  WQ_HIGHPRI | WQ_CPU_INTENSIVE | WQ_MEM_RECLAIM | WQ_UNBOUND,
+						  WQ_CPU_INTENSIVE | WQ_MEM_RECLAIM | WQ_UNBOUND,
 						  num_online_cpus(), devname);
 	if (!cc->crypt_queue) {
 		ti->error = "Couldn't create kcryptd queue";
@@ -2734,6 +2749,7 @@
 	wake_up_process(cc->write_thread);
 
 	ti->num_flush_bios = 1;
+	ti->limit_swap_bios = true;
 
 	return 0;
 
@@ -2808,6 +2824,11 @@
 	return DM_MAPIO_SUBMITTED;
 }
 
+static char hex2asc(unsigned char c)
+{
+	return c + '0' + ((unsigned)(9 - c) >> 4 & 0x27);
+}
+
 static void crypt_status(struct dm_target *ti, status_type_t type,
 			 unsigned status_flags, char *result, unsigned maxlen)
 {
@@ -2826,9 +2847,12 @@
 		if (cc->key_size > 0) {
 			if (cc->key_string)
 				DMEMIT(":%u:%s", cc->key_size, cc->key_string);
-			else
-				for (i = 0; i < cc->key_size; i++)
-					DMEMIT("%02x", cc->key[i]);
+			else {
+				for (i = 0; i < cc->key_size; i++) {
+					DMEMIT("%c%c", hex2asc(cc->key[i] >> 4),
+					       hex2asc(cc->key[i] & 0xf));
+				}
+			}
 		} else
 			DMEMIT("-");
 
@@ -2954,7 +2978,7 @@
 	limits->max_segment_size = PAGE_SIZE;
 
 	limits->logical_block_size =
-		max_t(unsigned short, limits->logical_block_size, cc->sector_size);
+		max_t(unsigned, limits->logical_block_size, cc->sector_size);
 	limits->physical_block_size =
 		max_t(unsigned, limits->physical_block_size, cc->sector_size);
 	limits->io_min = max_t(unsigned, limits->io_min, cc->sector_size);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-delay.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-delay.c
@@ -30,7 +30,7 @@
 	struct workqueue_struct *kdelayd_wq;
 	struct work_struct flush_expired_bios;
 	struct list_head delayed_bios;
-	atomic_t may_delay;
+	bool may_delay;
 
 	struct delay_class read;
 	struct delay_class write;
@@ -191,7 +191,7 @@
 	INIT_WORK(&dc->flush_expired_bios, flush_expired_bios);
 	INIT_LIST_HEAD(&dc->delayed_bios);
 	mutex_init(&dc->timer_lock);
-	atomic_set(&dc->may_delay, 1);
+	dc->may_delay = true;
 	dc->argc = argc;
 
 	ret = delay_class_ctr(ti, &dc->read, argv);
@@ -245,7 +245,7 @@
 	struct dm_delay_info *delayed;
 	unsigned long expires = 0;
 
-	if (!c->delay || !atomic_read(&dc->may_delay))
+	if (!c->delay)
 		return DM_MAPIO_REMAPPED;
 
 	delayed = dm_per_bio_data(bio, sizeof(struct dm_delay_info));
@@ -254,6 +254,10 @@
 	delayed->expires = expires = jiffies + msecs_to_jiffies(c->delay);
 
 	mutex_lock(&delayed_bios_lock);
+	if (unlikely(!dc->may_delay)) {
+		mutex_unlock(&delayed_bios_lock);
+		return DM_MAPIO_REMAPPED;
+	}
 	c->ops++;
 	list_add_tail(&delayed->list, &dc->delayed_bios);
 	mutex_unlock(&delayed_bios_lock);
@@ -267,7 +271,10 @@
 {
 	struct delay_c *dc = ti->private;
 
-	atomic_set(&dc->may_delay, 0);
+	mutex_lock(&delayed_bios_lock);
+	dc->may_delay = false;
+	mutex_unlock(&delayed_bios_lock);
+
 	del_timer_sync(&dc->delay_timer);
 	flush_bios(flush_delayed_bios(dc, 1));
 }
@@ -276,7 +283,7 @@
 {
 	struct delay_c *dc = ti->private;
 
-	atomic_set(&dc->may_delay, 1);
+	dc->may_delay = true;
 }
 
 static int delay_map(struct dm_target *ti, struct bio *bio)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-era-target.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-era-target.c
@@ -47,6 +47,7 @@
 static void writeset_free(struct writeset *ws)
 {
 	vfree(ws->bits);
+	ws->bits = NULL;
 }
 
 static int setup_on_disk_bitset(struct dm_disk_bitset *info,
@@ -71,8 +72,6 @@
  */
 static int writeset_alloc(struct writeset *ws, dm_block_t nr_blocks)
 {
-	ws->md.nr_bits = nr_blocks;
-	ws->md.root = INVALID_WRITESET_ROOT;
 	ws->bits = vzalloc(bitset_size(nr_blocks));
 	if (!ws->bits) {
 		DMERR("%s: couldn't allocate in memory bitset", __func__);
@@ -85,12 +84,14 @@
 /*
  * Wipes the in-core bitset, and creates a new on disk bitset.
  */
-static int writeset_init(struct dm_disk_bitset *info, struct writeset *ws)
+static int writeset_init(struct dm_disk_bitset *info, struct writeset *ws,
+			 dm_block_t nr_blocks)
 {
 	int r;
 
-	memset(ws->bits, 0, bitset_size(ws->md.nr_bits));
+	memset(ws->bits, 0, bitset_size(nr_blocks));
 
+	ws->md.nr_bits = nr_blocks;
 	r = setup_on_disk_bitset(info, ws->md.nr_bits, &ws->md.root);
 	if (r) {
 		DMERR("%s: setup_on_disk_bitset failed", __func__);
@@ -134,7 +135,7 @@
 {
 	int r;
 
-	if (!test_and_set_bit(block, ws->bits)) {
+	if (!test_bit(block, ws->bits)) {
 		r = dm_bitset_set_bit(info, ws->md.root, block, &ws->md.root);
 		if (r) {
 			/* FIXME: fail mode */
@@ -388,7 +389,7 @@
 
 static int ws_eq(void *context, const void *value1, const void *value2)
 {
-	return !memcmp(value1, value2, sizeof(struct writeset_metadata));
+	return !memcmp(value1, value2, sizeof(struct writeset_disk));
 }
 
 /*----------------------------------------------------------------*/
@@ -564,6 +565,15 @@
 	}
 
 	disk = dm_block_data(sblock);
+
+	/* Verify the data block size hasn't changed */
+	if (le32_to_cpu(disk->data_block_size) != md->block_size) {
+		DMERR("changing the data block size (from %u to %llu) is not supported",
+		      le32_to_cpu(disk->data_block_size), md->block_size);
+		r = -EINVAL;
+		goto bad;
+	}
+
 	r = dm_tm_open_with_sm(md->bm, SUPERBLOCK_LOCATION,
 			       disk->metadata_space_map_root,
 			       sizeof(disk->metadata_space_map_root),
@@ -575,10 +585,10 @@
 
 	setup_infos(md);
 
-	md->block_size = le32_to_cpu(disk->data_block_size);
 	md->nr_blocks = le32_to_cpu(disk->nr_blocks);
 	md->current_era = le32_to_cpu(disk->current_era);
 
+	ws_unpack(&disk->current_writeset, &md->current_writeset->md);
 	md->writeset_tree_root = le64_to_cpu(disk->writeset_tree_root);
 	md->era_array_root = le64_to_cpu(disk->era_array_root);
 	md->metadata_snap = le64_to_cpu(disk->metadata_snap);
@@ -746,6 +756,12 @@
 	ws_unpack(&disk, &d->writeset);
 	d->value = cpu_to_le32(key);
 
+	/*
+	 * We initialise another bitset info to avoid any caching side effects
+	 * with the previous one.
+	 */
+	dm_disk_bitset_init(md->tm, &d->info);
+
 	d->nr_bits = min(d->writeset.nr_bits, md->nr_blocks);
 	d->current_bit = 0;
 	d->step = metadata_digest_transcribe_writeset;
@@ -759,12 +775,6 @@
 		return 0;
 
 	memset(d, 0, sizeof(*d));
-
-	/*
-	 * We initialise another bitset info to avoid any caching side
-	 * effects with the previous one.
-	 */
-	dm_disk_bitset_init(md->tm, &d->info);
 	d->step = metadata_digest_lookup_writeset;
 
 	return 0;
@@ -802,6 +812,8 @@
 
 static void metadata_close(struct era_metadata *md)
 {
+	writeset_free(&md->writesets[0]);
+	writeset_free(&md->writesets[1]);
 	destroy_persistent_data_objects(md);
 	kfree(md);
 }
@@ -839,6 +851,7 @@
 	r = writeset_alloc(&md->writesets[1], *new_size);
 	if (r) {
 		DMERR("%s: writeset_alloc failed for writeset 1", __func__);
+		writeset_free(&md->writesets[0]);
 		return r;
 	}
 
@@ -849,6 +862,8 @@
 			    &value, &md->era_array_root);
 	if (r) {
 		DMERR("%s: dm_array_resize failed", __func__);
+		writeset_free(&md->writesets[0]);
+		writeset_free(&md->writesets[1]);
 		return r;
 	}
 
@@ -870,7 +885,6 @@
 	}
 
 	ws_pack(&md->current_writeset->md, &value);
-	md->current_writeset->md.root = INVALID_WRITESET_ROOT;
 
 	keys[0] = md->current_era;
 	__dm_bless_for_disk(&value);
@@ -882,6 +896,7 @@
 		return r;
 	}
 
+	md->current_writeset->md.root = INVALID_WRITESET_ROOT;
 	md->archived_writesets = true;
 
 	return 0;
@@ -898,7 +913,7 @@
 	int r;
 	struct writeset *new_writeset = next_writeset(md);
 
-	r = writeset_init(&md->bitset_info, new_writeset);
+	r = writeset_init(&md->bitset_info, new_writeset, md->nr_blocks);
 	if (r) {
 		DMERR("%s: writeset_init failed", __func__);
 		return r;
@@ -951,7 +966,7 @@
 	int r;
 	struct dm_block *sblock;
 
-	if (md->current_writeset->md.root != SUPERBLOCK_LOCATION) {
+	if (md->current_writeset->md.root != INVALID_WRITESET_ROOT) {
 		r = dm_bitset_flush(&md->bitset_info, md->current_writeset->md.root,
 				    &md->current_writeset->md.root);
 		if (r) {
@@ -1226,8 +1241,10 @@
 	int r;
 	struct bio_list deferred_bios, marked_bios;
 	struct bio *bio;
+	struct blk_plug plug;
 	bool commit_needed = false;
 	bool failed = false;
+	struct writeset *ws = era->md->current_writeset;
 
 	bio_list_init(&deferred_bios);
 	bio_list_init(&marked_bios);
@@ -1237,9 +1254,11 @@
 	bio_list_init(&era->deferred_bios);
 	spin_unlock(&era->deferred_lock);
 
+	if (bio_list_empty(&deferred_bios))
+		return;
+
 	while ((bio = bio_list_pop(&deferred_bios))) {
-		r = writeset_test_and_set(&era->md->bitset_info,
-					  era->md->current_writeset,
+		r = writeset_test_and_set(&era->md->bitset_info, ws,
 					  get_block(era, bio));
 		if (r < 0) {
 			/*
@@ -1247,7 +1266,6 @@
 			 * FIXME: finish.
 			 */
 			failed = true;
-
 		} else if (r == 0)
 			commit_needed = true;
 
@@ -1263,9 +1281,19 @@
 	if (failed)
 		while ((bio = bio_list_pop(&marked_bios)))
 			bio_io_error(bio);
-	else
-		while ((bio = bio_list_pop(&marked_bios)))
+	else {
+		blk_start_plug(&plug);
+		while ((bio = bio_list_pop(&marked_bios))) {
+			/*
+			 * Only update the in-core writeset if the on-disk one
+			 * was updated too.
+			 */
+			if (commit_needed)
+				set_bit(get_block(era, bio), ws->bits);
 			generic_make_request(bio);
+		}
+		blk_finish_plug(&plug);
+	}
 }
 
 static void process_rpc_calls(struct era *era)
@@ -1369,7 +1397,7 @@
 static void stop_worker(struct era *era)
 {
 	atomic_set(&era->suspended, 1);
-	flush_workqueue(era->wq);
+	drain_workqueue(era->wq);
 }
 
 /*----------------------------------------------------------------
@@ -1486,15 +1514,6 @@
 	}
 	era->md = md;
 
-	era->nr_blocks = calc_nr_blocks(era);
-
-	r = metadata_resize(era->md, &era->nr_blocks);
-	if (r) {
-		ti->error = "couldn't resize metadata";
-		era_destroy(era);
-		return -ENOMEM;
-	}
-
 	era->wq = alloc_ordered_workqueue("dm-" DM_MSG_PREFIX, WQ_MEM_RECLAIM);
 	if (!era->wq) {
 		ti->error = "could not create workqueue for metadata object";
@@ -1562,6 +1581,12 @@
 	}
 
 	stop_worker(era);
+
+	r = metadata_commit(era->md);
+	if (r) {
+		DMERR("%s: metadata_commit failed", __func__);
+		/* FIXME: fail mode */
+	}
 }
 
 static int era_preresume(struct dm_target *ti)
@@ -1571,16 +1596,24 @@
 	dm_block_t new_size = calc_nr_blocks(era);
 
 	if (era->nr_blocks != new_size) {
-		r = in_worker1(era, metadata_resize, &new_size);
-		if (r)
+		r = metadata_resize(era->md, &new_size);
+		if (r) {
+			DMERR("%s: metadata_resize failed", __func__);
 			return r;
+		}
+
+		r = metadata_commit(era->md);
+		if (r) {
+			DMERR("%s: metadata_commit failed", __func__);
+			return r;
+		}
 
 		era->nr_blocks = new_size;
 	}
 
 	start_worker(era);
 
-	r = in_worker0(era, metadata_new_era);
+	r = in_worker0(era, metadata_era_rollover);
 	if (r) {
 		DMERR("%s: metadata_era_rollover failed", __func__);
 		return r;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-flakey.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-flakey.c
@@ -124,9 +124,9 @@
 			 * Direction r or w?
 			 */
 			arg_name = dm_shift_arg(as);
-			if (!strcasecmp(arg_name, "w"))
+			if (arg_name && !strcasecmp(arg_name, "w"))
 				fc->corrupt_bio_rw = WRITE;
-			else if (!strcasecmp(arg_name, "r"))
+			else if (arg_name && !strcasecmp(arg_name, "r"))
 				fc->corrupt_bio_rw = READ;
 			else {
 				ti->error = "Invalid corrupt bio direction (r or w)";
@@ -301,8 +301,11 @@
 	 */
 	bio_for_each_segment(bvec, bio, iter) {
 		if (bio_iter_len(bio, iter) > corrupt_bio_byte) {
-			char *segment = (page_address(bio_iter_page(bio, iter))
-					 + bio_iter_offset(bio, iter));
+			char *segment;
+			struct page *page = bio_iter_page(bio, iter);
+			if (unlikely(page == ZERO_PAGE(0)))
+				break;
+			segment = (page_address(page) + bio_iter_offset(bio, iter));
 			segment[corrupt_bio_byte] = fc->corrupt_bio_value;
 			DMDEBUG("Corrupting data bio=%p by writing %u to byte %u "
 				"(rw=%c bi_opf=%u bi_sector=%llu size=%u)\n",
@@ -360,9 +363,11 @@
 		/*
 		 * Corrupt matching writes.
 		 */
-		if (fc->corrupt_bio_byte && (fc->corrupt_bio_rw == WRITE)) {
-			if (all_corrupt_bio_flags_match(bio, fc))
-				corrupt_bio_data(bio, fc);
+		if (fc->corrupt_bio_byte) {
+			if (fc->corrupt_bio_rw == WRITE) {
+				if (all_corrupt_bio_flags_match(bio, fc))
+					corrupt_bio_data(bio, fc);
+			}
 			goto map_bio;
 		}
 
@@ -388,13 +393,14 @@
 		return DM_ENDIO_DONE;
 
 	if (!*error && pb->bio_submitted && (bio_data_dir(bio) == READ)) {
-		if (fc->corrupt_bio_byte && (fc->corrupt_bio_rw == READ) &&
-		    all_corrupt_bio_flags_match(bio, fc)) {
-			/*
-			 * Corrupt successful matching READs while in down state.
-			 */
-			corrupt_bio_data(bio, fc);
-
+		if (fc->corrupt_bio_byte) {
+			if ((fc->corrupt_bio_rw == READ) &&
+			    all_corrupt_bio_flags_match(bio, fc)) {
+				/*
+				 * Corrupt successful matching READs while in down state.
+				 */
+				corrupt_bio_data(bio, fc);
+			}
 		} else if (!test_bit(DROP_WRITES, &fc->flags) &&
 			   !test_bit(ERROR_WRITES, &fc->flags)) {
 			/*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-init.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-init.c
@@ -207,8 +207,10 @@
 	strscpy(dev->dmi.uuid, field[1], sizeof(dev->dmi.uuid));
 	/* minor */
 	if (strlen(field[2])) {
-		if (kstrtoull(field[2], 0, &dev->dmi.dev))
+		if (kstrtoull(field[2], 0, &dev->dmi.dev) ||
+		    dev->dmi.dev >= (1 << MINORBITS))
 			return ERR_PTR(-EINVAL);
+		dev->dmi.dev = huge_encode_dev((dev_t)dev->dmi.dev);
 		dev->dmi.flags |= DM_PERSISTENT_DEV_FLAG;
 	}
 	/* flags */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-integrity.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-integrity.c
@@ -6,6 +6,8 @@
  * This file is released under the GPL.
  */
 
+#include "dm-bio-record.h"
+
 #include <linux/compiler.h>
 #include <linux/module.h>
 #include <linux/device-mapper.h>
@@ -29,11 +31,11 @@
 #define DEFAULT_BUFFER_SECTORS		128
 #define DEFAULT_JOURNAL_WATERMARK	50
 #define DEFAULT_SYNC_MSEC		10000
-#define DEFAULT_MAX_JOURNAL_SECTORS	131072
+#define DEFAULT_MAX_JOURNAL_SECTORS	(IS_ENABLED(CONFIG_64BIT) ? 131072 : 8192)
 #define MIN_LOG2_INTERLEAVE_SECTORS	3
 #define MAX_LOG2_INTERLEAVE_SECTORS	31
 #define METADATA_WORKQUEUE_MAX_ACTIVE	16
-#define RECALC_SECTORS			8192
+#define RECALC_SECTORS			(IS_ENABLED(CONFIG_64BIT) ? 32768 : 2048)
 #define RECALC_WRITE_SUPER		16
 #define BITMAP_BLOCK_SIZE		4096	/* don't change it */
 #define BITMAP_FLUSH_INTERVAL		(10 * HZ)
@@ -199,17 +201,19 @@
 	__u8 log2_blocks_per_bitmap_bit;
 
 	unsigned char mode;
-	int suspending;
 
 	int failed;
 
 	struct crypto_shash *internal_hash;
 
+	struct dm_target *ti;
+
 	/* these variables are locked with endio_wait.lock */
 	struct rb_root in_progress;
 	struct list_head wait_list;
 	wait_queue_head_t endio_wait;
 	struct workqueue_struct *wait_wq;
+	struct workqueue_struct *offload_wq;
 
 	unsigned char commit_seq;
 	commit_id_t commit_ids[N_COMMIT_IDS];
@@ -250,6 +254,7 @@
 	bool journal_uptodate;
 	bool just_formatted;
 	bool recalculate_flag;
+	bool legacy_recalculate;
 
 	struct alg_spec internal_hash_alg;
 	struct alg_spec journal_crypt_alg;
@@ -290,11 +295,7 @@
 
 	struct completion *completion;
 
-	struct gendisk *orig_bi_disk;
-	u8 orig_bi_partno;
-	bio_end_io_t *orig_bi_end_io;
-	struct bio_integrity_payload *orig_bi_integrity;
-	struct bvec_iter orig_bi_iter;
+	struct dm_bio_details bio_details;
 };
 
 struct journal_completion {
@@ -381,6 +382,14 @@
 	return READ_ONCE(ic->failed);
 }
 
+static bool dm_integrity_disable_recalculate(struct dm_integrity_c *ic)
+{
+	if ((ic->internal_hash_alg.key || ic->journal_mac_alg.key) &&
+	    !ic->legacy_recalculate)
+		return true;
+	return false;
+}
+
 static commit_id_t dm_integrity_commit_id(struct dm_integrity_c *ic, unsigned i,
 					  unsigned j, unsigned char seq)
 {
@@ -1343,12 +1352,52 @@
 	return 0;
 }
 
-static void dm_integrity_flush_buffers(struct dm_integrity_c *ic)
+struct flush_request {
+	struct dm_io_request io_req;
+	struct dm_io_region io_reg;
+	struct dm_integrity_c *ic;
+	struct completion comp;
+};
+
+static void flush_notify(unsigned long error, void *fr_)
+{
+	struct flush_request *fr = fr_;
+	if (unlikely(error != 0))
+		dm_integrity_io_error(fr->ic, "flusing disk cache", -EIO);
+	complete(&fr->comp);
+}
+
+static void dm_integrity_flush_buffers(struct dm_integrity_c *ic, bool flush_data)
 {
 	int r;
+
+	struct flush_request fr;
+
+	if (!ic->meta_dev)
+		flush_data = false;
+	if (flush_data) {
+		fr.io_req.bi_op = REQ_OP_WRITE,
+		fr.io_req.bi_op_flags = REQ_PREFLUSH | REQ_SYNC,
+		fr.io_req.mem.type = DM_IO_KMEM,
+		fr.io_req.mem.ptr.addr = NULL,
+		fr.io_req.notify.fn = flush_notify,
+		fr.io_req.notify.context = &fr;
+		fr.io_req.client = dm_bufio_get_dm_io_client(ic->bufio),
+		fr.io_reg.bdev = ic->dev->bdev,
+		fr.io_reg.sector = 0,
+		fr.io_reg.count = 0,
+		fr.ic = ic;
+		init_completion(&fr.comp);
+		r = dm_io(&fr.io_req, 1, &fr.io_reg, NULL);
+		BUG_ON(r);
+	}
+
 	r = dm_bufio_write_dirty_buffers(ic->bufio);
 	if (unlikely(r))
 		dm_integrity_io_error(ic, "writing tags", r);
+
+	if (flush_data)
+		wait_for_completion(&fr.comp);
 }
 
 static void sleep_on_endio_wait(struct dm_integrity_c *ic)
@@ -1434,7 +1483,7 @@
 			dio->range.logical_sector += dio->range.n_sectors;
 			bio_advance(bio, dio->range.n_sectors << SECTOR_SHIFT);
 			INIT_WORK(&dio->work, integrity_bio_wait);
-			queue_work(ic->wait_wq, &dio->work);
+			queue_work(ic->offload_wq, &dio->work);
 			return;
 		}
 		do_endio_flush(ic, dio);
@@ -1445,14 +1494,9 @@
 {
 	struct dm_integrity_io *dio = dm_per_bio_data(bio, sizeof(struct dm_integrity_io));
 
-	bio->bi_iter = dio->orig_bi_iter;
-	bio->bi_disk = dio->orig_bi_disk;
-	bio->bi_partno = dio->orig_bi_partno;
-	if (dio->orig_bi_integrity) {
-		bio->bi_integrity = dio->orig_bi_integrity;
+	dm_bio_restore(&dio->bio_details, bio);
+	if (bio->bi_integrity)
 		bio->bi_opf |= REQ_INTEGRITY;
-	}
-	bio->bi_end_io = dio->orig_bi_end_io;
 
 	if (dio->completion)
 		complete(dio->completion);
@@ -1519,7 +1563,7 @@
 		struct bio *bio = dm_bio_from_per_bio_data(dio, sizeof(struct dm_integrity_io));
 		char *checksums;
 		unsigned extra_space = unlikely(digest_size > ic->tag_size) ? digest_size - ic->tag_size : 0;
-		char checksums_onstack[HASH_MAX_DIGESTSIZE];
+		char checksums_onstack[max((size_t)HASH_MAX_DIGESTSIZE, MAX_TAG_SIZE)];
 		unsigned sectors_to_process = dio->range.n_sectors;
 		sector_t sector = dio->range.logical_sector;
 
@@ -1537,12 +1581,13 @@
 			}
 		}
 
-		__bio_for_each_segment(bv, bio, iter, dio->orig_bi_iter) {
+		__bio_for_each_segment(bv, bio, iter, dio->bio_details.bi_iter) {
+			struct bio_vec bv_copy = bv;
 			unsigned pos;
 			char *mem, *checksums_ptr;
 
 again:
-			mem = (char *)kmap_atomic(bv.bv_page) + bv.bv_offset;
+			mem = (char *)kmap_atomic(bv_copy.bv_page) + bv_copy.bv_offset;
 			pos = 0;
 			checksums_ptr = checksums;
 			do {
@@ -1551,7 +1596,7 @@
 				sectors_to_process -= ic->sectors_per_block;
 				pos += ic->sectors_per_block << SECTOR_SHIFT;
 				sector += ic->sectors_per_block;
-			} while (pos < bv.bv_len && sectors_to_process && checksums != checksums_onstack);
+			} while (pos < bv_copy.bv_len && sectors_to_process && checksums != checksums_onstack);
 			kunmap_atomic(mem);
 
 			r = dm_integrity_rw_tag(ic, checksums, &dio->metadata_block, &dio->metadata_offset,
@@ -1571,9 +1616,9 @@
 			if (!sectors_to_process)
 				break;
 
-			if (unlikely(pos < bv.bv_len)) {
-				bv.bv_offset += pos;
-				bv.bv_len -= pos;
+			if (unlikely(pos < bv_copy.bv_len)) {
+				bv_copy.bv_offset += pos;
+				bv_copy.bv_len -= pos;
 				goto again;
 			}
 		}
@@ -1581,7 +1626,7 @@
 		if (likely(checksums != checksums_onstack))
 			kfree(checksums);
 	} else {
-		struct bio_integrity_payload *bip = dio->orig_bi_integrity;
+		struct bio_integrity_payload *bip = dio->bio_details.bi_integrity;
 
 		if (bip) {
 			struct bio_vec biv;
@@ -1748,7 +1793,7 @@
 				} while (++s < ic->sectors_per_block);
 #ifdef INTERNAL_VERIFY
 				if (ic->internal_hash) {
-					char checksums_onstack[max(HASH_MAX_DIGESTSIZE, MAX_TAG_SIZE)];
+					char checksums_onstack[max((size_t)HASH_MAX_DIGESTSIZE, MAX_TAG_SIZE)];
 
 					integrity_sector_checksum(ic, logical_sector, mem + bv.bv_offset, checksums_onstack);
 					if (unlikely(memcmp(checksums_onstack, journal_entry_tag(ic, je), ic->tag_size))) {
@@ -1860,7 +1905,7 @@
 
 	if (need_sync_io && from_map) {
 		INIT_WORK(&dio->work, integrity_bio_wait);
-		queue_work(ic->metadata_wq, &dio->work);
+		queue_work(ic->offload_wq, &dio->work);
 		return;
 	}
 
@@ -2000,20 +2045,13 @@
 	} else
 		dio->completion = NULL;
 
-	dio->orig_bi_iter = bio->bi_iter;
-
-	dio->orig_bi_disk = bio->bi_disk;
-	dio->orig_bi_partno = bio->bi_partno;
+	dm_bio_record(&dio->bio_details, bio);
 	bio_set_dev(bio, ic->dev->bdev);
-
-	dio->orig_bi_integrity = bio_integrity(bio);
 	bio->bi_integrity = NULL;
 	bio->bi_opf &= ~REQ_INTEGRITY;
-
-	dio->orig_bi_end_io = bio->bi_end_io;
 	bio->bi_end_io = integrity_end_io;
-
 	bio->bi_iter.bi_size = dio->range.n_sectors << SECTOR_SHIFT;
+
 	generic_make_request(bio);
 
 	if (need_sync_io) {
@@ -2089,7 +2127,7 @@
 	flushes = bio_list_get(&ic->flush_bio_list);
 	if (unlikely(ic->mode != 'J')) {
 		spin_unlock_irq(&ic->endio_wait.lock);
-		dm_integrity_flush_buffers(ic);
+		dm_integrity_flush_buffers(ic, true);
 		goto release_flush_bios;
 	}
 
@@ -2299,7 +2337,7 @@
 	complete_journal_op(&comp);
 	wait_for_completion_io(&comp.comp);
 
-	dm_integrity_flush_buffers(ic);
+	dm_integrity_flush_buffers(ic, true);
 }
 
 static void integrity_writer(struct work_struct *w)
@@ -2309,10 +2347,6 @@
 
 	unsigned prev_free_sectors;
 
-	/* the following test is not needed, but it tests the replay code */
-	if (READ_ONCE(ic->suspending) && !ic->meta_dev)
-		return;
-
 	spin_lock_irq(&ic->endio_wait.lock);
 	write_start = ic->committed_section;
 	write_sections = ic->n_committed_sections;
@@ -2341,7 +2375,7 @@
 {
 	int r;
 
-	dm_integrity_flush_buffers(ic);
+	dm_integrity_flush_buffers(ic, false);
 	if (dm_integrity_failed(ic))
 		return;
 
@@ -2371,12 +2405,13 @@
 
 next_chunk:
 
-	if (unlikely(READ_ONCE(ic->suspending)))
+	if (unlikely(dm_post_suspending(ic->ti)))
 		goto unlock_ret;
 
 	range.logical_sector = le64_to_cpu(ic->sb->recalc_sector);
 	if (unlikely(range.logical_sector >= ic->provided_data_sectors)) {
 		if (ic->mode == 'B') {
+			block_bitmap_op(ic, ic->recalc_bitmap, 0, ic->provided_data_sectors, BITMAP_OP_CLEAR);
 			DEBUG_print("queue_delayed_work: bitmap_flush_work\n");
 			queue_delayed_work(ic->commit_wq, &ic->bitmap_flush_work, 0);
 		}
@@ -2454,6 +2489,17 @@
 		goto err;
 	}
 
+	if (ic->mode == 'B') {
+		sector_t start, end;
+		start = (range.logical_sector >>
+			 (ic->sb->log2_sectors_per_block + ic->log2_blocks_per_bitmap_bit)) <<
+			(ic->sb->log2_sectors_per_block + ic->log2_blocks_per_bitmap_bit);
+		end = ((range.logical_sector + range.n_sectors) >>
+		       (ic->sb->log2_sectors_per_block + ic->log2_blocks_per_bitmap_bit)) <<
+			(ic->sb->log2_sectors_per_block + ic->log2_blocks_per_bitmap_bit);
+		block_bitmap_op(ic, ic->recalc_bitmap, start, end - start, BITMAP_OP_CLEAR);
+	}
+
 advance_and_next:
 	cond_resched();
 
@@ -2496,7 +2542,7 @@
 				    dio->range.n_sectors, BITMAP_OP_TEST_ALL_SET)) {
 			remove_range(ic, &dio->range);
 			INIT_WORK(&dio->work, integrity_bio_wait);
-			queue_work(ic->wait_wq, &dio->work);
+			queue_work(ic->offload_wq, &dio->work);
 		} else {
 			block_bitmap_op(ic, ic->journal, dio->range.logical_sector,
 					dio->range.n_sectors, BITMAP_OP_SET);
@@ -2519,7 +2565,7 @@
 
 		remove_range(ic, &dio->range);
 		INIT_WORK(&dio->work, integrity_bio_wait);
-		queue_work(ic->wait_wq, &dio->work);
+		queue_work(ic->offload_wq, &dio->work);
 	}
 
 	queue_delayed_work(ic->commit_wq, &ic->bitmap_flush_work, ic->bitmap_flush_interval);
@@ -2532,7 +2578,7 @@
 	unsigned long limit;
 	struct bio *bio;
 
-	dm_integrity_flush_buffers(ic);
+	dm_integrity_flush_buffers(ic, false);
 
 	range.logical_sector = 0;
 	range.n_sectors = ic->provided_data_sectors;
@@ -2541,7 +2587,7 @@
 	add_new_range_and_wait(ic, &range);
 	spin_unlock_irq(&ic->endio_wait.lock);
 
-	dm_integrity_flush_buffers(ic);
+	dm_integrity_flush_buffers(ic, true);
 	if (ic->meta_dev)
 		blkdev_issue_flush(ic->dev->bdev, GFP_NOIO, NULL);
 
@@ -2799,8 +2845,6 @@
 
 	del_timer_sync(&ic->autocommit_timer);
 
-	WRITE_ONCE(ic->suspending, 1);
-
 	if (ic->recalc_wq)
 		drain_workqueue(ic->recalc_wq);
 
@@ -2811,14 +2855,13 @@
 	drain_workqueue(ic->commit_wq);
 
 	if (ic->mode == 'J') {
-		if (ic->meta_dev)
-			queue_work(ic->writer_wq, &ic->writer_work);
+		queue_work(ic->writer_wq, &ic->writer_work);
 		drain_workqueue(ic->writer_wq);
-		dm_integrity_flush_buffers(ic);
+		dm_integrity_flush_buffers(ic, true);
 	}
 
 	if (ic->mode == 'B') {
-		dm_integrity_flush_buffers(ic);
+		dm_integrity_flush_buffers(ic, true);
 #if 1
 		/* set to 0 to test bitmap replay code */
 		init_journal(ic, 0, ic->journal_sections, 0);
@@ -2829,8 +2872,6 @@
 #endif
 	}
 
-	WRITE_ONCE(ic->suspending, 0);
-
 	BUG_ON(!RB_EMPTY_ROOT(&ic->in_progress));
 
 	ic->journal_uptodate = true;
@@ -2883,17 +2924,24 @@
 	} else {
 		replay_journal(ic);
 		if (ic->mode == 'B') {
-			int mode;
 			ic->sb->flags |= cpu_to_le32(SB_FLAG_DIRTY_BITMAP);
 			ic->sb->log2_blocks_per_bitmap_bit = ic->log2_blocks_per_bitmap_bit;
 			r = sync_rw_sb(ic, REQ_OP_WRITE, REQ_FUA);
 			if (unlikely(r))
 				dm_integrity_io_error(ic, "writing superblock", r);
 
-			mode = ic->recalculate_flag ? BITMAP_OP_SET : BITMAP_OP_CLEAR;
-			block_bitmap_op(ic, ic->journal, 0, ic->provided_data_sectors, mode);
-			block_bitmap_op(ic, ic->recalc_bitmap, 0, ic->provided_data_sectors, mode);
-			block_bitmap_op(ic, ic->may_write_bitmap, 0, ic->provided_data_sectors, mode);
+			block_bitmap_op(ic, ic->journal, 0, ic->provided_data_sectors, BITMAP_OP_CLEAR);
+			block_bitmap_op(ic, ic->recalc_bitmap, 0, ic->provided_data_sectors, BITMAP_OP_CLEAR);
+			block_bitmap_op(ic, ic->may_write_bitmap, 0, ic->provided_data_sectors, BITMAP_OP_CLEAR);
+			if (ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING) &&
+			    le64_to_cpu(ic->sb->recalc_sector) < ic->provided_data_sectors) {
+				block_bitmap_op(ic, ic->journal, le64_to_cpu(ic->sb->recalc_sector),
+						ic->provided_data_sectors - le64_to_cpu(ic->sb->recalc_sector), BITMAP_OP_SET);
+				block_bitmap_op(ic, ic->recalc_bitmap, le64_to_cpu(ic->sb->recalc_sector),
+						ic->provided_data_sectors - le64_to_cpu(ic->sb->recalc_sector), BITMAP_OP_SET);
+				block_bitmap_op(ic, ic->may_write_bitmap, le64_to_cpu(ic->sb->recalc_sector),
+						ic->provided_data_sectors - le64_to_cpu(ic->sb->recalc_sector), BITMAP_OP_SET);
+			}
 			rw_journal_sectors(ic, REQ_OP_WRITE, REQ_FUA | REQ_SYNC, 0,
 					   ic->n_bitmap_blocks * (BITMAP_BLOCK_SIZE >> SECTOR_SHIFT), NULL);
 		}
@@ -2955,13 +3003,14 @@
 		arg_count += !!ic->internal_hash_alg.alg_string;
 		arg_count += !!ic->journal_crypt_alg.alg_string;
 		arg_count += !!ic->journal_mac_alg.alg_string;
+		arg_count += ic->legacy_recalculate;
 		DMEMIT("%s %llu %u %c %u", ic->dev->name, (unsigned long long)ic->start,
 		       ic->tag_size, ic->mode, arg_count);
 		if (ic->meta_dev)
 			DMEMIT(" meta_device:%s", ic->meta_dev->name);
 		if (ic->sectors_per_block != 1)
 			DMEMIT(" block_size:%u", ic->sectors_per_block << SECTOR_SHIFT);
-		if (ic->recalculate_flag)
+		if (ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING))
 			DMEMIT(" recalculate");
 		DMEMIT(" journal_sectors:%u", ic->initial_sectors - SB_SECTORS);
 		DMEMIT(" interleave_sectors:%u", 1U << ic->sb->log2_interleave_sectors);
@@ -2974,6 +3023,8 @@
 			DMEMIT(" sectors_per_bit:%llu", (unsigned long long)ic->sectors_per_block << ic->log2_blocks_per_bitmap_bit);
 			DMEMIT(" bitmap_flush_interval:%u", jiffies_to_msecs(ic->bitmap_flush_interval));
 		}
+		if (ic->legacy_recalculate)
+			DMEMIT(" legacy_recalculate");
 
 #define EMIT_ALG(a, n)							\
 		do {							\
@@ -3582,7 +3633,7 @@
 	unsigned extra_args;
 	struct dm_arg_set as;
 	static const struct dm_arg _args[] = {
-		{0, 9, "Invalid number of feature args"},
+		{0, 14, "Invalid number of feature args"},
 	};
 	unsigned journal_sectors, interleave_sectors, buffer_sectors, journal_watermark, sync_msec;
 	bool should_write_sb;
@@ -3607,6 +3658,7 @@
 	}
 	ti->private = ic;
 	ti->per_io_data_size = sizeof(struct dm_integrity_io);
+	ic->ti = ti;
 
 	ic->in_progress = RB_ROOT;
 	INIT_LIST_HEAD(&ic->wait_list);
@@ -3703,9 +3755,10 @@
 		} else if (sscanf(opt_string, "sectors_per_bit:%llu%c", &llval, &dummy) == 1) {
 			log2_sectors_per_bitmap_bit = !llval ? 0 : __ilog2_u64(llval);
 		} else if (sscanf(opt_string, "bitmap_flush_interval:%u%c", &val, &dummy) == 1) {
-			if (val >= (uint64_t)UINT_MAX * 1000 / HZ) {
+			if ((uint64_t)val >= (uint64_t)UINT_MAX * 1000 / HZ) {
 				r = -EINVAL;
 				ti->error = "Invalid bitmap_flush_interval argument";
+				goto bad;
 			}
 			ic->bitmap_flush_interval = msecs_to_jiffies(val);
 		} else if (!strncmp(opt_string, "internal_hash:", strlen("internal_hash:"))) {
@@ -3725,6 +3778,8 @@
 				goto bad;
 		} else if (!strcmp(opt_string, "recalculate")) {
 			ic->recalculate_flag = true;
+		} else if (!strcmp(opt_string, "legacy_recalculate")) {
+			ic->legacy_recalculate = true;
 		} else {
 			r = -EINVAL;
 			ti->error = "Invalid argument";
@@ -3818,6 +3873,14 @@
 		goto bad;
 	}
 
+	ic->offload_wq = alloc_workqueue("dm-integrity-offload", WQ_MEM_RECLAIM,
+					  METADATA_WORKQUEUE_MAX_ACTIVE);
+	if (!ic->offload_wq) {
+		ti->error = "Cannot allocate workqueue";
+		r = -ENOMEM;
+		goto bad;
+	}
+
 	ic->commit_wq = alloc_workqueue("dm-integrity-commit", WQ_MEM_RECLAIM, 1);
 	if (!ic->commit_wq) {
 		ti->error = "Cannot allocate workqueue";
@@ -3987,6 +4050,7 @@
 	}
 
 	if (ic->internal_hash) {
+		size_t recalc_tags_size;
 		ic->recalc_wq = alloc_workqueue("dm-integrity-recalc", WQ_MEM_RECLAIM, 1);
 		if (!ic->recalc_wq ) {
 			ti->error = "Cannot allocate workqueue";
@@ -4000,13 +4064,29 @@
 			r = -ENOMEM;
 			goto bad;
 		}
-		ic->recalc_tags = kvmalloc_array(RECALC_SECTORS >> ic->sb->log2_sectors_per_block,
-						 ic->tag_size, GFP_KERNEL);
+		recalc_tags_size = (RECALC_SECTORS >> ic->sb->log2_sectors_per_block) * ic->tag_size;
+		if (crypto_shash_digestsize(ic->internal_hash) > ic->tag_size)
+			recalc_tags_size += crypto_shash_digestsize(ic->internal_hash) - ic->tag_size;
+		ic->recalc_tags = kvmalloc(recalc_tags_size, GFP_KERNEL);
 		if (!ic->recalc_tags) {
 			ti->error = "Cannot allocate tags for recalculating";
 			r = -ENOMEM;
 			goto bad;
 		}
+	} else {
+		if (ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING)) {
+			ti->error = "Recalculate can only be specified with internal_hash";
+			r = -EINVAL;
+			goto bad;
+		}
+	}
+
+	if (ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING) &&
+	    le64_to_cpu(ic->sb->recalc_sector) < ic->provided_data_sectors &&
+	    dm_integrity_disable_recalculate(ic)) {
+		ti->error = "Recalculating with HMAC is disabled for security reasons - if you really need it, use the argument \"legacy_recalculate\"";
+		r = -EOPNOTSUPP;
+		goto bad;
 	}
 
 	ic->bufio = dm_bufio_client_create(ic->meta_dev ? ic->meta_dev->bdev : ic->dev->bdev,
@@ -4065,8 +4145,6 @@
 	}
 
 	if (should_write_sb) {
-		int r;
-
 		init_journal(ic, 0, ic->journal_sections, 0);
 		r = dm_integrity_failed(ic);
 		if (unlikely(r)) {
@@ -4118,10 +4196,14 @@
 	BUG_ON(!RB_EMPTY_ROOT(&ic->in_progress));
 	BUG_ON(!list_empty(&ic->wait_list));
 
+	if (ic->mode == 'B')
+		cancel_delayed_work_sync(&ic->bitmap_flush_work);
 	if (ic->metadata_wq)
 		destroy_workqueue(ic->metadata_wq);
 	if (ic->wait_wq)
 		destroy_workqueue(ic->wait_wq);
+	if (ic->offload_wq)
+		destroy_workqueue(ic->offload_wq);
 	if (ic->commit_wq)
 		destroy_workqueue(ic->commit_wq);
 	if (ic->writer_wq)
@@ -4207,11 +4289,13 @@
 	}
 
 	r = dm_register_target(&integrity_target);
-
-	if (r < 0)
+	if (r < 0) {
 		DMERR("register failed %d", r);
+		kmem_cache_destroy(journal_io_cache);
+		return r;
+	}
 
-	return r;
+	return 0;
 }
 
 static void __exit dm_integrity_exit(void)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-io.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-io.c
@@ -306,7 +306,7 @@
 	struct request_queue *q = bdev_get_queue(where->bdev);
 	unsigned short logical_block_size = queue_logical_block_size(q);
 	sector_t num_sectors;
-	unsigned int uninitialized_var(special_cmd_max_sectors);
+	unsigned int special_cmd_max_sectors;
 
 	/*
 	 * Reject unsupported discard and write same requests.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-ioctl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-ioctl.c
@@ -17,6 +17,7 @@
 #include <linux/dm-ioctl.h>
 #include <linux/hdreg.h>
 #include <linux/compat.h>
+#include <linux/nospec.h>
 
 #include <linux/uaccess.h>
 
@@ -529,7 +530,7 @@
 	 * Grab our output buffer.
 	 */
 	nl = orig_nl = get_result_buffer(param, param_size, &len);
-	if (len < needed) {
+	if (len < needed || len < sizeof(nl->dev)) {
 		param->flags |= DM_BUFFER_FULL_FLAG;
 		goto out;
 	}
@@ -572,7 +573,7 @@
     size_t *needed = needed_param;
 
     *needed += sizeof(struct dm_target_versions);
-    *needed += strlen(tt->name);
+    *needed += strlen(tt->name) + 1;
     *needed += ALIGN_MASK;
 }
 
@@ -637,7 +638,7 @@
 	iter_info.old_vers = NULL;
 	iter_info.vers = vers;
 	iter_info.flags = 0;
-	iter_info.end = (char *)vers+len;
+	iter_info.end = (char *)vers + needed;
 
 	/*
 	 * Now loop through filling out the names & versions.
@@ -808,15 +809,21 @@
 	struct hash_cell *hc = NULL;
 
 	if (*param->uuid) {
-		if (*param->name || param->dev)
+		if (*param->name || param->dev) {
+			DMERR("Invalid ioctl structure: uuid %s, name %s, dev %llx",
+			      param->uuid, param->name, (unsigned long long)param->dev);
 			return NULL;
+		}
 
 		hc = __get_uuid_cell(param->uuid);
 		if (!hc)
 			return NULL;
 	} else if (*param->name) {
-		if (param->dev)
+		if (param->dev) {
+			DMERR("Invalid ioctl structure: name %s, dev %llx",
+			      param->name, (unsigned long long)param->dev);
 			return NULL;
+		}
 
 		hc = __get_name_cell(param->name);
 		if (!hc)
@@ -1063,8 +1070,26 @@
 			suspend_flags &= ~DM_SUSPEND_LOCKFS_FLAG;
 		if (param->flags & DM_NOFLUSH_FLAG)
 			suspend_flags |= DM_SUSPEND_NOFLUSH_FLAG;
-		if (!dm_suspended_md(md))
-			dm_suspend(md, suspend_flags);
+		if (!dm_suspended_md(md)) {
+			r = dm_suspend(md, suspend_flags);
+			if (r) {
+				down_write(&_hash_lock);
+				hc = dm_get_mdptr(md);
+				if (hc && !hc->new_map) {
+					hc->new_map = new_map;
+					new_map = NULL;
+				} else {
+					r = -ENXIO;
+				}
+				up_write(&_hash_lock);
+				if (new_map) {
+					dm_sync_table(md);
+					dm_table_destroy(new_map);
+				}
+				dm_put(md);
+				return r;
+			}
+		}
 
 		old_map = dm_swap_table(md, new_map);
 		if (IS_ERR(old_map)) {
@@ -1434,11 +1459,12 @@
 		hc->new_map = NULL;
 	}
 
-	param->flags &= ~DM_INACTIVE_PRESENT_FLAG;
-
-	__dev_status(hc->md, param);
 	md = hc->md;
 	up_write(&_hash_lock);
+
+	param->flags &= ~DM_INACTIVE_PRESENT_FLAG;
+	__dev_status(md, param);
+
 	if (old_map) {
 		dm_sync_table(md);
 		dm_table_destroy(old_map);
@@ -1600,6 +1626,7 @@
 
 	if (!argc) {
 		DMWARN("Empty message received.");
+		r = -EINVAL;
 		goto out_argv;
 	}
 
@@ -1695,6 +1722,7 @@
 	if (unlikely(cmd >= ARRAY_SIZE(_ioctls)))
 		return NULL;
 
+	cmd = array_index_nospec(cmd, ARRAY_SIZE(_ioctls));
 	*ioctl_flags = _ioctls[cmd].flags;
 	return _ioctls[cmd].fn;
 }
@@ -1756,8 +1784,12 @@
 	if (copy_from_user(param_kernel, user, minimum_data_size))
 		return -EFAULT;
 
-	if (param_kernel->data_size < minimum_data_size)
+	if (unlikely(param_kernel->data_size < minimum_data_size) ||
+	    unlikely(param_kernel->data_size > DM_MAX_TARGETS * DM_MAX_TARGET_PARAMS)) {
+		DMERR("Invalid data size in the ioctl structure: %u",
+		      param_kernel->data_size);
 		return -EINVAL;
+	}
 
 	secure_data = param_kernel->flags & DM_SECURE_DATA_FLAG;
 
@@ -1844,7 +1876,7 @@
 	int ioctl_flags;
 	int param_flags;
 	unsigned int cmd;
-	struct dm_ioctl *uninitialized_var(param);
+	struct dm_ioctl *param;
 	ioctl_fn fn = NULL;
 	size_t input_param_size;
 	struct dm_ioctl param_kernel;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-log.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-log.c
@@ -415,8 +415,7 @@
 	/*
 	 * Work out how many "unsigned long"s we need to hold the bitset.
 	 */
-	bitset_size = dm_round_up(region_count,
-				  sizeof(*lc->clean_bits) << BYTE_SHIFT);
+	bitset_size = dm_round_up(region_count, BITS_PER_LONG);
 	bitset_size >>= BYTE_SHIFT;
 
 	lc->bitset_uint32_count = bitset_size / sizeof(*lc->clean_bits);
@@ -616,7 +615,7 @@
 			log_clear_bit(lc, lc->clean_bits, i);
 
 	/* clear any old bits -- device has shrunk */
-	for (i = lc->region_count; i % (sizeof(*lc->clean_bits) << BYTE_SHIFT); i++)
+	for (i = lc->region_count; i % BITS_PER_LONG; i++)
 		log_clear_bit(lc, lc->clean_bits, i);
 
 	/* copy clean across to sync */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-mpath.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-mpath.c
@@ -558,7 +558,8 @@
 		if (pgpath && pgpath->pg->ps.type->end_io)
 			pgpath->pg->ps.type->end_io(&pgpath->pg->ps,
 						    &pgpath->path,
-						    mpio->nr_bytes);
+						    mpio->nr_bytes,
+						    clone->io_start_time_ns);
 	}
 
 	blk_put_request(clone);
@@ -576,10 +577,12 @@
 
 	/* Do we need to select a new pgpath? */
 	pgpath = READ_ONCE(m->current_pgpath);
-	queue_io = test_bit(MPATHF_QUEUE_IO, &m->flags);
-	if (!pgpath || !queue_io)
+	if (!pgpath || !test_bit(MPATHF_QUEUE_IO, &m->flags))
 		pgpath = choose_pgpath(m, bio->bi_iter.bi_size);
 
+	/* MPATHF_QUEUE_IO might have been cleared by choose_pgpath. */
+	queue_io = test_bit(MPATHF_QUEUE_IO, &m->flags);
+
 	if ((pgpath && queue_io) ||
 	    (!pgpath && test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags))) {
 		/* Queue for the daemon to resubmit */
@@ -599,45 +602,10 @@
 	return pgpath;
 }
 
-static struct pgpath *__map_bio_fast(struct multipath *m, struct bio *bio)
-{
-	struct pgpath *pgpath;
-	unsigned long flags;
-
-	/* Do we need to select a new pgpath? */
-	/*
-	 * FIXME: currently only switching path if no path (due to failure, etc)
-	 * - which negates the point of using a path selector
-	 */
-	pgpath = READ_ONCE(m->current_pgpath);
-	if (!pgpath)
-		pgpath = choose_pgpath(m, bio->bi_iter.bi_size);
-
-	if (!pgpath) {
-		if (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) {
-			/* Queue for the daemon to resubmit */
-			spin_lock_irqsave(&m->lock, flags);
-			bio_list_add(&m->queued_bios, bio);
-			spin_unlock_irqrestore(&m->lock, flags);
-			queue_work(kmultipathd, &m->process_queued_bios);
-
-			return ERR_PTR(-EAGAIN);
-		}
-		return NULL;
-	}
-
-	return pgpath;
-}
-
 static int __multipath_map_bio(struct multipath *m, struct bio *bio,
 			       struct dm_mpath_io *mpio)
 {
-	struct pgpath *pgpath;
-
-	if (!m->hw_handler_name)
-		pgpath = __map_bio_fast(m, bio);
-	else
-		pgpath = __map_bio(m, bio);
+	struct pgpath *pgpath = __map_bio(m, bio);
 
 	if (IS_ERR(pgpath))
 		return DM_MAPIO_SUBMITTED;
@@ -1223,17 +1191,25 @@
 static void flush_multipath_work(struct multipath *m)
 {
 	if (m->hw_handler_name) {
-		set_bit(MPATHF_PG_INIT_DISABLED, &m->flags);
-		smp_mb__after_atomic();
+		unsigned long flags;
+
+		if (!atomic_read(&m->pg_init_in_progress))
+			goto skip;
+
+		spin_lock_irqsave(&m->lock, flags);
+		if (atomic_read(&m->pg_init_in_progress) &&
+		    !test_and_set_bit(MPATHF_PG_INIT_DISABLED, &m->flags)) {
+			spin_unlock_irqrestore(&m->lock, flags);
 
-		if (atomic_read(&m->pg_init_in_progress))
 			flush_workqueue(kmpath_handlerd);
-		multipath_wait_for_pg_init_completion(m);
+			multipath_wait_for_pg_init_completion(m);
 
-		clear_bit(MPATHF_PG_INIT_DISABLED, &m->flags);
-		smp_mb__after_atomic();
+			spin_lock_irqsave(&m->lock, flags);
+			clear_bit(MPATHF_PG_INIT_DISABLED, &m->flags);
+		}
+		spin_unlock_irqrestore(&m->lock, flags);
 	}
-
+skip:
 	if (m->queue_mode == DM_TYPE_BIO_BASED)
 		flush_work(&m->process_queued_bios);
 	flush_work(&m->trigger_event);
@@ -1593,7 +1569,8 @@
 		struct path_selector *ps = &pgpath->pg->ps;
 
 		if (ps->type->end_io)
-			ps->type->end_io(ps, &pgpath->path, mpio->nr_bytes);
+			ps->type->end_io(ps, &pgpath->path, mpio->nr_bytes,
+					 clone->io_start_time_ns);
 	}
 
 	return r;
@@ -1637,7 +1614,8 @@
 		struct path_selector *ps = &pgpath->pg->ps;
 
 		if (ps->type->end_io)
-			ps->type->end_io(ps, &pgpath->path, mpio->nr_bytes);
+			ps->type->end_io(ps, &pgpath->path, mpio->nr_bytes,
+					 dm_start_time_ns_from_clone(clone));
 	}
 
 	return r;
@@ -1889,7 +1867,7 @@
 	int r;
 
 	current_pgpath = READ_ONCE(m->current_pgpath);
-	if (!current_pgpath)
+	if (!current_pgpath || !test_bit(MPATHF_QUEUE_IO, &m->flags))
 		current_pgpath = choose_pgpath(m, 0);
 
 	if (current_pgpath) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-path-selector.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-path-selector.h
@@ -74,7 +74,7 @@
 	int (*start_io) (struct path_selector *ps, struct dm_path *path,
 			 size_t nr_bytes);
 	int (*end_io) (struct path_selector *ps, struct dm_path *path,
-		       size_t nr_bytes);
+		       size_t nr_bytes, u64 start_time);
 };
 
 /* Register a path selector */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-queue-length.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-queue-length.c
@@ -227,7 +227,7 @@
 }
 
 static int ql_end_io(struct path_selector *ps, struct dm_path *path,
-		     size_t nr_bytes)
+		     size_t nr_bytes, u64 start_time)
 {
 	struct path_info *pi = path->pscontext;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-raid.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-raid.c
@@ -998,12 +998,13 @@
 static int validate_raid_redundancy(struct raid_set *rs)
 {
 	unsigned int i, rebuild_cnt = 0;
-	unsigned int rebuilds_per_group = 0, copies;
+	unsigned int rebuilds_per_group = 0, copies, raid_disks;
 	unsigned int group_size, last_group_start;
 
-	for (i = 0; i < rs->md.raid_disks; i++)
-		if (!test_bit(In_sync, &rs->dev[i].rdev.flags) ||
-		    !rs->dev[i].rdev.sb_page)
+	for (i = 0; i < rs->raid_disks; i++)
+		if (!test_bit(FirstUse, &rs->dev[i].rdev.flags) &&
+		    ((!test_bit(In_sync, &rs->dev[i].rdev.flags) ||
+		      !rs->dev[i].rdev.sb_page)))
 			rebuild_cnt++;
 
 	switch (rs->md.level) {
@@ -1043,8 +1044,9 @@
 		 *	    A	 A    B	   B	C
 		 *	    C	 D    D	   E	E
 		 */
+		raid_disks = min(rs->raid_disks, rs->md.raid_disks);
 		if (__is_raid10_near(rs->md.new_layout)) {
-			for (i = 0; i < rs->md.raid_disks; i++) {
+			for (i = 0; i < raid_disks; i++) {
 				if (!(i % copies))
 					rebuilds_per_group = 0;
 				if ((!rs->dev[i].rdev.sb_page ||
@@ -1067,10 +1069,10 @@
 		 * results in the need to treat the last (potentially larger)
 		 * set differently.
 		 */
-		group_size = (rs->md.raid_disks / copies);
-		last_group_start = (rs->md.raid_disks / group_size) - 1;
+		group_size = (raid_disks / copies);
+		last_group_start = (raid_disks / group_size) - 1;
 		last_group_start *= group_size;
-		for (i = 0; i < rs->md.raid_disks; i++) {
+		for (i = 0; i < raid_disks; i++) {
 			if (!(i % copies) && !(i > last_group_start))
 				rebuilds_per_group = 0;
 			if ((!rs->dev[i].rdev.sb_page ||
@@ -1585,7 +1587,7 @@
 {
 	int i;
 
-	for (i = 0; i < rs->md.raid_disks; i++) {
+	for (i = 0; i < rs->raid_disks; i++) {
 		struct md_rdev *rdev = &rs->dev[i].rdev;
 
 		if (!test_bit(Journal, &rdev->flags) &&
@@ -1892,6 +1894,14 @@
 	return rs->md.new_level != rs->md.level;
 }
 
+/* True if layout is set to reshape. */
+static bool rs_is_layout_change(struct raid_set *rs, bool use_mddev)
+{
+	return (use_mddev ? rs->md.delta_disks : rs->delta_disks) ||
+	       rs->md.new_layout != rs->md.layout ||
+	       rs->md.new_chunk_sectors != rs->md.chunk_sectors;
+}
+
 /* True if @rs is requested to reshape by ctr */
 static bool rs_reshape_requested(struct raid_set *rs)
 {
@@ -1904,9 +1914,7 @@
 	if (rs_is_raid0(rs))
 		return false;
 
-	change = mddev->new_layout != mddev->layout ||
-		 mddev->new_chunk_sectors != mddev->chunk_sectors ||
-		 rs->delta_disks;
+	change = rs_is_layout_change(rs, false);
 
 	/* Historical case to support raid1 reshape without delta disks */
 	if (rs_is_raid1(rs)) {
@@ -2843,7 +2851,7 @@
 }
 
 /*
- *
+ * Reshape:
  * - change raid layout
  * - change chunk size
  * - add disks
@@ -2953,6 +2961,20 @@
 }
 
 /*
+ * If the md resync thread has updated superblock with max reshape position
+ * at the end of a reshape but not (yet) reset the layout configuration
+ * changes -> reset the latter.
+ */
+static void rs_reset_inconclusive_reshape(struct raid_set *rs)
+{
+	if (!rs_is_reshaping(rs) && rs_is_layout_change(rs, true)) {
+		rs_set_cur(rs);
+		rs->md.delta_disks = 0;
+		rs->md.reshape_backwards = 0;
+	}
+}
+
+/*
  * Enable/disable discard support on RAID set depending on
  * RAID level and discard properties of underlying RAID members.
  */
@@ -3216,11 +3238,14 @@
 	if (r)
 		goto bad;
 
+	/* Catch any inconclusive reshape superblock content. */
+	rs_reset_inconclusive_reshape(rs);
+
 	/* Start raid set read-only and assumed clean to change in raid_resume() */
 	rs->md.ro = 1;
 	rs->md.in_sync = 1;
 
-	/* Keep array frozen */
+	/* Keep array frozen until resume. */
 	set_bit(MD_RECOVERY_FROZEN, &rs->md.recovery);
 
 	/* Has to be held on running the array */
@@ -3234,7 +3259,6 @@
 	}
 
 	r = md_start(&rs->md);
-
 	if (r) {
 		ti->error = "Failed to start raid array";
 		mddev_unlock(&rs->md);
@@ -3260,15 +3284,19 @@
 	/* Try to adjust the raid4/5/6 stripe cache size to the stripe size */
 	if (rs_is_raid456(rs)) {
 		r = rs_set_raid456_stripe_cache(rs);
-		if (r)
+		if (r) {
+			mddev_unlock(&rs->md);
 			goto bad_stripe_cache;
+		}
 	}
 
 	/* Now do an early reshape check */
 	if (test_bit(RT_FLAG_RESHAPE_RS, &rs->runtime_flags)) {
 		r = rs_check_reshape(rs);
-		if (r)
+		if (r) {
+			mddev_unlock(&rs->md);
 			goto bad_check_reshape;
+		}
 
 		/* Restore new, ctr requested layout to perform check */
 		rs_config_restore(rs, &rs_layout);
@@ -3277,6 +3305,7 @@
 			r = rs->md.pers->check_reshape(&rs->md);
 			if (r) {
 				ti->error = "Reshape check failed";
+				mddev_unlock(&rs->md);
 				goto bad_check_reshape;
 			}
 		}
@@ -3314,14 +3343,14 @@
 	struct mddev *mddev = &rs->md;
 
 	/*
-	 * If we're reshaping to add disk(s)), ti->len and
+	 * If we're reshaping to add disk(s), ti->len and
 	 * mddev->array_sectors will differ during the process
 	 * (ti->len > mddev->array_sectors), so we have to requeue
 	 * bios with addresses > mddev->array_sectors here or
 	 * there will occur accesses past EOD of the component
 	 * data images thus erroring the raid set.
 	 */
-	if (unlikely(bio_end_sector(bio) > mddev->array_sectors))
+	if (unlikely(bio_has_data(bio) && bio_end_sector(bio) > mddev->array_sectors))
 		return DM_MAPIO_REQUEUE;
 
 	md_handle_request(mddev, bio);
@@ -3504,7 +3533,7 @@
 {
 	struct raid_set *rs = ti->private;
 	struct mddev *mddev = &rs->md;
-	struct r5conf *conf = mddev->private;
+	struct r5conf *conf = rs_is_raid456(rs) ? mddev->private : NULL;
 	int i, max_nr_stripes = conf ? conf->max_nr_stripes : 0;
 	unsigned long recovery;
 	unsigned int raid_param_cnt = 1; /* at least 1 for chunksize */
@@ -3724,13 +3753,13 @@
 	unsigned int i;
 	int r = 0;
 
-	for (i = 0; !r && i < rs->md.raid_disks; i++)
-		if (rs->dev[i].data_dev)
-			r = fn(ti,
-				 rs->dev[i].data_dev,
-				 0, /* No offset on data devs */
-				 rs->md.dev_sectors,
-				 data);
+	for (i = 0; !r && i < rs->raid_disks; i++) {
+		if (rs->dev[i].data_dev) {
+			r = fn(ti, rs->dev[i].data_dev,
+			       0, /* No offset on data devs */
+			       rs->md.dev_sectors, data);
+		}
+	}
 
 	return r;
 }
@@ -3742,15 +3771,6 @@
 
 	blk_limits_io_min(limits, chunk_size_bytes);
 	blk_limits_io_opt(limits, chunk_size_bytes * mddev_data_stripes(rs));
-
-	/*
-	 * RAID1 and RAID10 personalities require bio splitting,
-	 * RAID0/4/5/6 don't and process large discard bios properly.
-	 */
-	if (rs_is_raid1(rs) || rs_is_raid10(rs)) {
-		limits->discard_granularity = chunk_size_bytes;
-		limits->max_discard_sectors = rs->md.chunk_sectors;
-	}
 }
 
 static void raid_postsuspend(struct dm_target *ti)
@@ -3784,7 +3804,7 @@
 
 	memset(cleared_failed_devices, 0, sizeof(cleared_failed_devices));
 
-	for (i = 0; i < mddev->raid_disks; i++) {
+	for (i = 0; i < rs->raid_disks; i++) {
 		r = &rs->dev[i].rdev;
 		/* HM FIXME: enhance journal device recovery processing */
 		if (test_bit(Journal, &r->flags))
@@ -3998,7 +4018,9 @@
 		 * Take this opportunity to check whether any failed
 		 * devices are reachable again.
 		 */
+		mddev_lock_nointr(mddev);
 		attempt_restore_of_faulty_devices(rs);
+		mddev_unlock(mddev);
 	}
 
 	if (test_and_clear_bit(RT_FLAG_RS_SUSPENDED, &rs->runtime_flags)) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-rq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-rq.c
@@ -70,9 +70,6 @@
 
 void dm_stop_queue(struct request_queue *q)
 {
-	if (blk_mq_queue_stopped(q))
-		return;
-
 	blk_mq_quiesce_queue(q);
 }
 
@@ -146,10 +143,6 @@
  */
 static void rq_completed(struct mapped_device *md)
 {
-	/* nudge anyone waiting on suspend queue */
-	if (unlikely(wq_has_sleeper(&md->wait)))
-		wake_up(&md->wait);
-
 	/*
 	 * dm_put() must be at the end of this function. See the comment above
 	 */
@@ -288,7 +281,8 @@
 	struct dm_rq_target_io *tio = tio_from_request(rq);
 
 	tio->error = error;
-	blk_mq_complete_request(rq);
+	if (likely(!blk_should_fake_timeout(rq->q)))
+		blk_mq_complete_request(rq);
 }
 
 /*
@@ -575,6 +569,7 @@
 	blk_mq_free_tag_set(md->tag_set);
 out_kfree_tag_set:
 	kfree(md->tag_set);
+	md->tag_set = NULL;
 
 	return err;
 }
@@ -584,6 +579,7 @@
 	if (md->tag_set) {
 		blk_mq_free_tag_set(md->tag_set);
 		kfree(md->tag_set);
+		md->tag_set = NULL;
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-service-time.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-service-time.c
@@ -309,7 +309,7 @@
 }
 
 static int st_end_io(struct path_selector *ps, struct dm_path *path,
-		     size_t nr_bytes)
+		     size_t nr_bytes, u64 start_time)
 {
 	struct path_info *pi = path->pscontext;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-snap-persistent.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-snap-persistent.c
@@ -17,7 +17,7 @@
 #include <linux/dm-bufio.h>
 
 #define DM_MSG_PREFIX "persistent snapshot"
-#define DM_CHUNK_SIZE_DEFAULT_SECTORS 32	/* 16KB */
+#define DM_CHUNK_SIZE_DEFAULT_SECTORS 32U	/* 16KB */
 
 #define DM_PREFETCH_CHUNKS		12
 
@@ -613,7 +613,7 @@
 						    chunk_t old, chunk_t new),
 				    void *callback_context)
 {
-	int r, uninitialized_var(new_snapshot);
+	int r, new_snapshot;
 	struct pstore *ps = get_info(store);
 
 	/*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-snap.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-snap.c
@@ -141,6 +141,11 @@
 	 * for them to be committed.
 	 */
 	struct bio_list bios_queued_during_merge;
+
+	/*
+	 * Flush data after merge.
+	 */
+	struct bio flush_bio;
 };
 
 /*
@@ -680,8 +685,10 @@
 	for (i = 0; i < size; i++) {
 		slot = et->table + i;
 
-		hlist_bl_for_each_entry_safe(ex, pos, n, slot, hash_list)
+		hlist_bl_for_each_entry_safe(ex, pos, n, slot, hash_list) {
 			kmem_cache_free(mem, ex);
+			cond_resched();
+		}
 	}
 
 	vfree(et->table);
@@ -849,7 +856,7 @@
 static uint32_t __minimum_chunk_size(struct origin *o)
 {
 	struct dm_snapshot *snap;
-	unsigned chunk_size = 0;
+	unsigned chunk_size = rounddown_pow_of_two(UINT_MAX);
 
 	if (o)
 		list_for_each_entry(snap, &o->snapshots, list)
@@ -1121,6 +1128,17 @@
 
 static void error_bios(struct bio *bio);
 
+static int flush_data(struct dm_snapshot *s)
+{
+	struct bio *flush_bio = &s->flush_bio;
+
+	bio_reset(flush_bio);
+	bio_set_dev(flush_bio, s->origin->bdev);
+	flush_bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
+
+	return submit_bio_wait(flush_bio);
+}
+
 static void merge_callback(int read_err, unsigned long write_err, void *context)
 {
 	struct dm_snapshot *s = context;
@@ -1134,6 +1152,11 @@
 		goto shut;
 	}
 
+	if (flush_data(s) < 0) {
+		DMERR("Flush after merge failed: shutting down merge");
+		goto shut;
+	}
+
 	if (s->store->type->commit_merge(s->store,
 					 s->num_merging_chunks) < 0) {
 		DMERR("Write error in exception store: shutting down merge");
@@ -1318,6 +1341,7 @@
 	s->first_merging_chunk = 0;
 	s->num_merging_chunks = 0;
 	bio_list_init(&s->bios_queued_during_merge);
+	bio_init(&s->flush_bio, NULL, 0);
 
 	/* Allocate hash table for COW data */
 	if (init_hash_tables(s)) {
@@ -1386,6 +1410,7 @@
 
 	if (!s->store->chunk_size) {
 		ti->error = "Chunk size not set";
+		r = -EINVAL;
 		goto bad_read_metadata;
 	}
 
@@ -1504,6 +1529,8 @@
 
 	dm_exception_store_destroy(s->store);
 
+	bio_uninit(&s->flush_bio);
+
 	dm_put_device(ti, s->cow);
 
 	dm_put_device(ti, s->origin);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-stats.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-stats.c
@@ -188,7 +188,7 @@
 	       atomic_read(&shared->in_flight[WRITE]);
 }
 
-void dm_stats_init(struct dm_stats *stats)
+int dm_stats_init(struct dm_stats *stats)
 {
 	int cpu;
 	struct dm_stats_last_position *last;
@@ -196,11 +196,16 @@
 	mutex_init(&stats->mutex);
 	INIT_LIST_HEAD(&stats->list);
 	stats->last = alloc_percpu(struct dm_stats_last_position);
+	if (!stats->last)
+		return -ENOMEM;
+
 	for_each_possible_cpu(cpu) {
 		last = per_cpu_ptr(stats->last, cpu);
 		last->last_sector = (sector_t)ULLONG_MAX;
 		last->last_rw = UINT_MAX;
 	}
+
+	return 0;
 }
 
 void dm_stats_cleanup(struct dm_stats *stats)
@@ -224,6 +229,7 @@
 				       atomic_read(&shared->in_flight[READ]),
 				       atomic_read(&shared->in_flight[WRITE]));
 			}
+			cond_resched();
 		}
 		dm_stat_free(&s->rcu_head);
 	}
@@ -313,6 +319,7 @@
 	for (ni = 0; ni < n_entries; ni++) {
 		atomic_set(&s->stat_shared[ni].in_flight[READ], 0);
 		atomic_set(&s->stat_shared[ni].in_flight[WRITE], 0);
+		cond_resched();
 	}
 
 	if (s->n_histogram_entries) {
@@ -325,6 +332,7 @@
 		for (ni = 0; ni < n_entries; ni++) {
 			s->stat_shared[ni].tmp.histogram = hi;
 			hi += s->n_histogram_entries + 1;
+			cond_resched();
 		}
 	}
 
@@ -345,6 +353,7 @@
 			for (ni = 0; ni < n_entries; ni++) {
 				p[ni].histogram = hi;
 				hi += s->n_histogram_entries + 1;
+				cond_resched();
 			}
 		}
 	}
@@ -474,6 +483,7 @@
 			}
 			DMEMIT("\n");
 		}
+		cond_resched();
 	}
 	mutex_unlock(&stats->mutex);
 
@@ -750,6 +760,7 @@
 				local_irq_enable();
 			}
 		}
+		cond_resched();
 	}
 }
 
@@ -865,6 +876,8 @@
 
 		if (unlikely(sz + 1 >= maxlen))
 			goto buffer_overflow;
+
+		cond_resched();
 	}
 
 	if (clear)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-stats.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-stats.h
@@ -22,7 +22,7 @@
 	unsigned long long duration_ns;
 };
 
-void dm_stats_init(struct dm_stats *st);
+int dm_stats_init(struct dm_stats *st);
 void dm_stats_cleanup(struct dm_stats *st);
 
 struct mapped_device;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-table.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-table.c
@@ -184,7 +184,12 @@
 int dm_table_create(struct dm_table **result, fmode_t mode,
 		    unsigned num_targets, struct mapped_device *md)
 {
-	struct dm_table *t = kzalloc(sizeof(*t), GFP_KERNEL);
+	struct dm_table *t;
+
+	if (num_targets > DM_MAX_TARGETS)
+		return -EOVERFLOW;
+
+	t = kzalloc(sizeof(*t), GFP_KERNEL);
 
 	if (!t)
 		return -ENOMEM;
@@ -199,7 +204,7 @@
 
 	if (!num_targets) {
 		kfree(t);
-		return -ENOMEM;
+		return -EOVERFLOW;
 	}
 
 	if (alloc_targets(t, num_targets)) {
@@ -428,14 +433,23 @@
 {
 	int r;
 	dev_t dev;
+	unsigned int major, minor;
+	char dummy;
 	struct dm_dev_internal *dd;
 	struct dm_table *t = ti->table;
 
 	BUG_ON(!t);
 
-	dev = dm_get_dev_t(path);
-	if (!dev)
-		return -ENODEV;
+	if (sscanf(path, "%u:%u%c", &major, &minor, &dummy) == 2) {
+		/* Extract the major/minor numbers */
+		dev = MKDEV(major, minor);
+		if (MAJOR(dev) != major || MINOR(dev) != minor)
+			return -EOVERFLOW;
+	} else {
+		dev = dm_get_dev_t(path);
+		if (!dev)
+			return -ENODEV;
+	}
 
 	dd = find_device(&t->devices, dev);
 	if (!dd) {
@@ -659,7 +673,7 @@
 	 */
 	unsigned short remaining = 0;
 
-	struct dm_target *uninitialized_var(ti);
+	struct dm_target *ti;
 	struct queue_limits ti_limits;
 	unsigned i;
 
@@ -863,8 +877,7 @@
 static bool __table_type_bio_based(enum dm_queue_mode table_type)
 {
 	return (table_type == DM_TYPE_BIO_BASED ||
-		table_type == DM_TYPE_DAX_BIO_BASED ||
-		table_type == DM_TYPE_NVME_BIO_BASED);
+		table_type == DM_TYPE_DAX_BIO_BASED);
 }
 
 static bool __table_type_request_based(enum dm_queue_mode table_type)
@@ -879,20 +892,24 @@
 EXPORT_SYMBOL_GPL(dm_table_set_type);
 
 /* validate the dax capability of the target device span */
-int device_supports_dax(struct dm_target *ti, struct dm_dev *dev,
+int device_not_dax_capable(struct dm_target *ti, struct dm_dev *dev,
 			sector_t start, sector_t len, void *data)
 {
-	int blocksize = *(int *) data;
+	int blocksize = *(int *) data, id;
+	bool rc;
+
+	id = dax_read_lock();
+	rc = !dax_supported(dev->dax_dev, dev->bdev, blocksize, start, len);
+	dax_read_unlock(id);
 
-	return generic_fsdax_supported(dev->dax_dev, dev->bdev, blocksize,
-				       start, len);
+	return rc;
 }
 
 /* Check devices support synchronous DAX */
-static int device_dax_synchronous(struct dm_target *ti, struct dm_dev *dev,
-				  sector_t start, sector_t len, void *data)
+static int device_not_dax_synchronous_capable(struct dm_target *ti, struct dm_dev *dev,
+					      sector_t start, sector_t len, void *data)
 {
-	return dev->dax_dev && dax_synchronous(dev->dax_dev);
+	return !dev->dax_dev || !dax_synchronous(dev->dax_dev);
 }
 
 bool dm_table_supports_dax(struct dm_table *t,
@@ -909,30 +926,22 @@
 			return false;
 
 		if (!ti->type->iterate_devices ||
-		    !ti->type->iterate_devices(ti, iterate_fn, blocksize))
+		    ti->type->iterate_devices(ti, iterate_fn, blocksize))
 			return false;
 	}
 
 	return true;
 }
 
-static bool dm_table_does_not_support_partial_completion(struct dm_table *t);
-
-struct verify_rq_based_data {
-	unsigned sq_count;
-	unsigned mq_count;
-};
-
-static int device_is_rq_based(struct dm_target *ti, struct dm_dev *dev,
-			      sector_t start, sector_t len, void *data)
+static int device_is_rq_stackable(struct dm_target *ti, struct dm_dev *dev,
+				  sector_t start, sector_t len, void *data)
 {
-	struct request_queue *q = bdev_get_queue(dev->bdev);
-	struct verify_rq_based_data *v = data;
+	struct block_device *bdev = dev->bdev;
+	struct request_queue *q = bdev_get_queue(bdev);
 
-	if (queue_is_mq(q))
-		v->mq_count++;
-	else
-		v->sq_count++;
+	/* request-based cannot stack on partitions! */
+	if (bdev != bdev->bd_contains)
+		return false;
 
 	return queue_is_mq(q);
 }
@@ -941,7 +950,6 @@
 {
 	unsigned i;
 	unsigned bio_based = 0, request_based = 0, hybrid = 0;
-	struct verify_rq_based_data v = {.sq_count = 0, .mq_count = 0};
 	struct dm_target *tgt;
 	struct list_head *devices = dm_table_get_devices(t);
 	enum dm_queue_mode live_md_type = dm_get_md_type(t->md);
@@ -954,7 +962,6 @@
 			goto verify_bio_based;
 		}
 		BUG_ON(t->type == DM_TYPE_DAX_BIO_BASED);
-		BUG_ON(t->type == DM_TYPE_NVME_BIO_BASED);
 		goto verify_rq_based;
 	}
 
@@ -990,18 +997,9 @@
 verify_bio_based:
 		/* We must use this table as bio-based */
 		t->type = DM_TYPE_BIO_BASED;
-		if (dm_table_supports_dax(t, device_supports_dax, &page_size) ||
+		if (dm_table_supports_dax(t, device_not_dax_capable, &page_size) ||
 		    (list_empty(devices) && live_md_type == DM_TYPE_DAX_BIO_BASED)) {
 			t->type = DM_TYPE_DAX_BIO_BASED;
-		} else {
-			/* Check if upgrading to NVMe bio-based is valid or required */
-			tgt = dm_table_get_immutable_target(t);
-			if (tgt && !tgt->max_io_len && dm_table_does_not_support_partial_completion(t)) {
-				t->type = DM_TYPE_NVME_BIO_BASED;
-				goto verify_rq_based; /* must be stacked directly on NVMe (blk-mq) */
-			} else if (list_empty(devices) && live_md_type == DM_TYPE_NVME_BIO_BASED) {
-				t->type = DM_TYPE_NVME_BIO_BASED;
-			}
 		}
 		return 0;
 	}
@@ -1018,8 +1016,7 @@
 	 * (e.g. request completion process for partial completion.)
 	 */
 	if (t->num_targets > 1) {
-		DMERR("%s DM doesn't support multiple targets",
-		      t->type == DM_TYPE_NVME_BIO_BASED ? "nvme bio-based" : "request-based");
+		DMERR("request-based DM doesn't support multiple targets");
 		return -EINVAL;
 	}
 
@@ -1045,14 +1042,10 @@
 
 	/* Non-request-stackable devices can't be used for request-based dm */
 	if (!tgt->type->iterate_devices ||
-	    !tgt->type->iterate_devices(tgt, device_is_rq_based, &v)) {
+	    !tgt->type->iterate_devices(tgt, device_is_rq_stackable, NULL)) {
 		DMERR("table load rejected: including non-request-stackable devices");
 		return -EINVAL;
 	}
-	if (v.sq_count > 0) {
-		DMERR("table load rejected: not all devices are blk-mq request-stackable");
-		return -EINVAL;
-	}
 
 	return 0;
 }
@@ -1327,12 +1320,6 @@
 
 void dm_table_event(struct dm_table *t)
 {
-	/*
-	 * You can no longer call dm_table_event() from interrupt
-	 * context, use a bottom half instead.
-	 */
-	BUG_ON(in_interrupt());
-
 	mutex_lock(&_event_lock);
 	if (t->event_fn)
 		t->event_fn(t->event_context);
@@ -1380,6 +1367,46 @@
 	return &t->targets[(KEYS_PER_NODE * n) + k];
 }
 
+/*
+ * type->iterate_devices() should be called when the sanity check needs to
+ * iterate and check all underlying data devices. iterate_devices() will
+ * iterate all underlying data devices until it encounters a non-zero return
+ * code, returned by whether the input iterate_devices_callout_fn, or
+ * iterate_devices() itself internally.
+ *
+ * For some target type (e.g. dm-stripe), one call of iterate_devices() may
+ * iterate multiple underlying devices internally, in which case a non-zero
+ * return code returned by iterate_devices_callout_fn will stop the iteration
+ * in advance.
+ *
+ * Cases requiring _any_ underlying device supporting some kind of attribute,
+ * should use the iteration structure like dm_table_any_dev_attr(), or call
+ * it directly. @func should handle semantics of positive examples, e.g.
+ * capable of something.
+ *
+ * Cases requiring _all_ underlying devices supporting some kind of attribute,
+ * should use the iteration structure like dm_table_supports_nowait() or
+ * dm_table_supports_discards(). Or introduce dm_table_all_devs_attr() that
+ * uses an @anti_func that handle semantics of counter examples, e.g. not
+ * capable of something. So: return !dm_table_any_dev_attr(t, anti_func, data);
+ */
+static bool dm_table_any_dev_attr(struct dm_table *t,
+				  iterate_devices_callout_fn func, void *data)
+{
+	struct dm_target *ti;
+	unsigned int i;
+
+	for (i = 0; i < dm_table_get_num_targets(t); i++) {
+		ti = dm_table_get_target(t, i);
+
+		if (ti->type->iterate_devices &&
+		    ti->type->iterate_devices(ti, func, data))
+			return true;
+        }
+
+	return false;
+}
+
 static int count_device(struct dm_target *ti, struct dm_dev *dev,
 			sector_t start, sector_t len, void *data)
 {
@@ -1416,13 +1443,13 @@
 	return true;
 }
 
-static int device_is_zoned_model(struct dm_target *ti, struct dm_dev *dev,
-				 sector_t start, sector_t len, void *data)
+static int device_not_zoned_model(struct dm_target *ti, struct dm_dev *dev,
+				  sector_t start, sector_t len, void *data)
 {
 	struct request_queue *q = bdev_get_queue(dev->bdev);
 	enum blk_zoned_model *zoned_model = data;
 
-	return q && blk_queue_zoned_model(q) == *zoned_model;
+	return !q || blk_queue_zoned_model(q) != *zoned_model;
 }
 
 static bool dm_table_supports_zoned_model(struct dm_table *t,
@@ -1439,37 +1466,20 @@
 			return false;
 
 		if (!ti->type->iterate_devices ||
-		    !ti->type->iterate_devices(ti, device_is_zoned_model, &zoned_model))
+		    ti->type->iterate_devices(ti, device_not_zoned_model, &zoned_model))
 			return false;
 	}
 
 	return true;
 }
 
-static int device_matches_zone_sectors(struct dm_target *ti, struct dm_dev *dev,
-				       sector_t start, sector_t len, void *data)
+static int device_not_matches_zone_sectors(struct dm_target *ti, struct dm_dev *dev,
+					   sector_t start, sector_t len, void *data)
 {
 	struct request_queue *q = bdev_get_queue(dev->bdev);
 	unsigned int *zone_sectors = data;
 
-	return q && blk_queue_zone_sectors(q) == *zone_sectors;
-}
-
-static bool dm_table_matches_zone_sectors(struct dm_table *t,
-					  unsigned int zone_sectors)
-{
-	struct dm_target *ti;
-	unsigned i;
-
-	for (i = 0; i < dm_table_get_num_targets(t); i++) {
-		ti = dm_table_get_target(t, i);
-
-		if (!ti->type->iterate_devices ||
-		    !ti->type->iterate_devices(ti, device_matches_zone_sectors, &zone_sectors))
-			return false;
-	}
-
-	return true;
+	return !q || blk_queue_zone_sectors(q) != *zone_sectors;
 }
 
 static int validate_hardware_zoned_model(struct dm_table *table,
@@ -1489,7 +1499,7 @@
 	if (!zone_sectors || !is_power_of_2(zone_sectors))
 		return -EINVAL;
 
-	if (!dm_table_matches_zone_sectors(table, zone_sectors)) {
+	if (dm_table_any_dev_attr(table, device_not_matches_zone_sectors, &zone_sectors)) {
 		DMERR("%s: zone sectors is not consistent across all devices",
 		      dm_device_name(table->md));
 		return -EINVAL;
@@ -1679,29 +1689,12 @@
 	return false;
 }
 
-static int dm_table_supports_dax_write_cache(struct dm_table *t)
-{
-	struct dm_target *ti;
-	unsigned i;
-
-	for (i = 0; i < dm_table_get_num_targets(t); i++) {
-		ti = dm_table_get_target(t, i);
-
-		if (ti->type->iterate_devices &&
-		    ti->type->iterate_devices(ti,
-				device_dax_write_cache_enabled, NULL))
-			return true;
-	}
-
-	return false;
-}
-
-static int device_is_nonrot(struct dm_target *ti, struct dm_dev *dev,
-			    sector_t start, sector_t len, void *data)
+static int device_is_rotational(struct dm_target *ti, struct dm_dev *dev,
+				sector_t start, sector_t len, void *data)
 {
 	struct request_queue *q = bdev_get_queue(dev->bdev);
 
-	return q && blk_queue_nonrot(q);
+	return q && !blk_queue_nonrot(q);
 }
 
 static int device_is_not_random(struct dm_target *ti, struct dm_dev *dev,
@@ -1712,37 +1705,6 @@
 	return q && !blk_queue_add_random(q);
 }
 
-static bool dm_table_all_devices_attribute(struct dm_table *t,
-					   iterate_devices_callout_fn func)
-{
-	struct dm_target *ti;
-	unsigned i;
-
-	for (i = 0; i < dm_table_get_num_targets(t); i++) {
-		ti = dm_table_get_target(t, i);
-
-		if (!ti->type->iterate_devices ||
-		    !ti->type->iterate_devices(ti, func, NULL))
-			return false;
-	}
-
-	return true;
-}
-
-static int device_no_partial_completion(struct dm_target *ti, struct dm_dev *dev,
-					sector_t start, sector_t len, void *data)
-{
-	char b[BDEVNAME_SIZE];
-
-	/* For now, NVMe devices are the only devices of this class */
-	return (strncmp(bdevname(dev->bdev, b), "nvme", 4) == 0);
-}
-
-static bool dm_table_does_not_support_partial_completion(struct dm_table *t)
-{
-	return dm_table_all_devices_attribute(t, device_no_partial_completion);
-}
-
 static int device_not_write_same_capable(struct dm_target *ti, struct dm_dev *dev,
 					 sector_t start, sector_t len, void *data)
 {
@@ -1867,27 +1829,6 @@
 	return q && bdi_cap_stable_pages_required(q->backing_dev_info);
 }
 
-/*
- * If any underlying device requires stable pages, a table must require
- * them as well.  Only targets that support iterate_devices are considered:
- * don't want error, zero, etc to require stable pages.
- */
-static bool dm_table_requires_stable_pages(struct dm_table *t)
-{
-	struct dm_target *ti;
-	unsigned i;
-
-	for (i = 0; i < dm_table_get_num_targets(t); i++) {
-		ti = dm_table_get_target(t, i);
-
-		if (ti->type->iterate_devices &&
-		    ti->type->iterate_devices(ti, device_requires_stable_pages, NULL))
-			return true;
-	}
-
-	return false;
-}
-
 void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
 			       struct queue_limits *limits)
 {
@@ -1920,22 +1861,22 @@
 	}
 	blk_queue_write_cache(q, wc, fua);
 
-	if (dm_table_supports_dax(t, device_supports_dax, &page_size)) {
+	if (dm_table_supports_dax(t, device_not_dax_capable, &page_size)) {
 		blk_queue_flag_set(QUEUE_FLAG_DAX, q);
-		if (dm_table_supports_dax(t, device_dax_synchronous, NULL))
+		if (dm_table_supports_dax(t, device_not_dax_synchronous_capable, NULL))
 			set_dax_synchronous(t->md->dax_dev);
 	}
 	else
 		blk_queue_flag_clear(QUEUE_FLAG_DAX, q);
 
-	if (dm_table_supports_dax_write_cache(t))
+	if (dm_table_any_dev_attr(t, device_dax_write_cache_enabled, NULL))
 		dax_write_cache(t->md->dax_dev, true);
 
 	/* Ensure that all underlying devices are non-rotational. */
-	if (dm_table_all_devices_attribute(t, device_is_nonrot))
-		blk_queue_flag_set(QUEUE_FLAG_NONROT, q);
-	else
+	if (dm_table_any_dev_attr(t, device_is_rotational, NULL))
 		blk_queue_flag_clear(QUEUE_FLAG_NONROT, q);
+	else
+		blk_queue_flag_set(QUEUE_FLAG_NONROT, q);
 
 	if (!dm_table_supports_write_same(t))
 		q->limits.max_write_same_sectors = 0;
@@ -1947,8 +1888,11 @@
 	/*
 	 * Some devices don't use blk_integrity but still want stable pages
 	 * because they do their own checksumming.
+	 * If any underlying device requires stable pages, a table must require
+	 * them as well.  Only targets that support iterate_devices are considered:
+	 * don't want error, zero, etc to require stable pages.
 	 */
-	if (dm_table_requires_stable_pages(t))
+	if (dm_table_any_dev_attr(t, device_requires_stable_pages, NULL))
 		q->backing_dev_info->capabilities |= BDI_CAP_STABLE_WRITES;
 	else
 		q->backing_dev_info->capabilities &= ~BDI_CAP_STABLE_WRITES;
@@ -1959,7 +1903,8 @@
 	 * Clear QUEUE_FLAG_ADD_RANDOM if any underlying device does not
 	 * have it set.
 	 */
-	if (blk_queue_add_random(q) && dm_table_all_devices_attribute(t, device_is_not_random))
+	if (blk_queue_add_random(q) &&
+	    dm_table_any_dev_attr(t, device_is_not_random, NULL))
 		blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, q);
 
 	/*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-thin-metadata.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-thin-metadata.c
@@ -189,6 +189,15 @@
 	sector_t data_block_size;
 
 	/*
+	 * Pre-commit callback.
+	 *
+	 * This allows the thin provisioning target to run a callback before
+	 * the metadata are committed.
+	 */
+	dm_pool_pre_commit_fn pre_commit_fn;
+	void *pre_commit_context;
+
+	/*
 	 * We reserve a section of the metadata for commit overhead.
 	 * All reported space does *not* include this.
 	 */
@@ -378,16 +387,15 @@
  * Variant that is used for in-core only changes or code that
  * shouldn't put the pool in service on its own (e.g. commit).
  */
-static inline void __pmd_write_lock(struct dm_pool_metadata *pmd)
+static inline void pmd_write_lock_in_core(struct dm_pool_metadata *pmd)
 	__acquires(pmd->root_lock)
 {
 	down_write(&pmd->root_lock);
 }
-#define pmd_write_lock_in_core(pmd) __pmd_write_lock((pmd))
 
 static inline void pmd_write_lock(struct dm_pool_metadata *pmd)
 {
-	__pmd_write_lock(pmd);
+	pmd_write_lock_in_core(pmd);
 	if (unlikely(!pmd->in_service))
 		pmd->in_service = true;
 }
@@ -693,6 +701,15 @@
 		goto bad_cleanup_data_sm;
 	}
 
+	/*
+	 * For pool metadata opening process, root setting is redundant
+	 * because it will be set again in __begin_transaction(). But dm
+	 * pool aborting process really needs to get last transaction's
+	 * root to avoid accessing broken btree.
+	 */
+	pmd->root = le64_to_cpu(disk_super->data_mapping_root);
+	pmd->details_root = le64_to_cpu(disk_super->device_details_root);
+
 	__setup_btree_details(pmd);
 	dm_bm_unlock(sblock);
 
@@ -731,23 +748,29 @@
 					  THIN_MAX_CONCURRENT_LOCKS);
 	if (IS_ERR(pmd->bm)) {
 		DMERR("could not create block manager");
-		return PTR_ERR(pmd->bm);
+		r = PTR_ERR(pmd->bm);
+		pmd->bm = NULL;
+		return r;
 	}
 
 	r = __open_or_format_metadata(pmd, format_device);
-	if (r)
+	if (r) {
 		dm_block_manager_destroy(pmd->bm);
+		pmd->bm = NULL;
+	}
 
 	return r;
 }
 
-static void __destroy_persistent_data_objects(struct dm_pool_metadata *pmd)
+static void __destroy_persistent_data_objects(struct dm_pool_metadata *pmd,
+					      bool destroy_bm)
 {
 	dm_sm_destroy(pmd->data_sm);
 	dm_sm_destroy(pmd->metadata_sm);
 	dm_tm_destroy(pmd->nb_tm);
 	dm_tm_destroy(pmd->tm);
-	dm_block_manager_destroy(pmd->bm);
+	if (destroy_bm)
+		dm_block_manager_destroy(pmd->bm);
 }
 
 static int __begin_transaction(struct dm_pool_metadata *pmd)
@@ -822,10 +845,19 @@
 	 * We need to know if the thin_disk_superblock exceeds a 512-byte sector.
 	 */
 	BUILD_BUG_ON(sizeof(struct thin_disk_superblock) > 512);
+	BUG_ON(!rwsem_is_locked(&pmd->root_lock));
 
 	if (unlikely(!pmd->in_service))
 		return 0;
 
+	if (pmd->pre_commit_fn) {
+		r = pmd->pre_commit_fn(pmd->pre_commit_context);
+		if (r < 0) {
+			DMERR("pre-commit callback failed");
+			return r;
+		}
+	}
+
 	r = __write_changed_details(pmd);
 	if (r < 0)
 		return r;
@@ -892,6 +924,8 @@
 	pmd->in_service = false;
 	pmd->bdev = bdev;
 	pmd->data_block_size = data_block_size;
+	pmd->pre_commit_fn = NULL;
+	pmd->pre_commit_context = NULL;
 
 	r = __create_persistent_data_objects(pmd, format_device);
 	if (r) {
@@ -934,14 +968,16 @@
 		return -EBUSY;
 	}
 
-	if (!dm_bm_is_read_only(pmd->bm) && !pmd->fail_io) {
+	pmd_write_lock_in_core(pmd);
+	if (!pmd->fail_io && !dm_bm_is_read_only(pmd->bm)) {
 		r = __commit_transaction(pmd);
 		if (r < 0)
 			DMWARN("%s: __commit_transaction() failed, error = %d",
 			       __func__, r);
 	}
+	pmd_write_unlock(pmd);
 	if (!pmd->fail_io)
-		__destroy_persistent_data_objects(pmd);
+		__destroy_persistent_data_objects(pmd, true);
 
 	kfree(pmd);
 	return 0;
@@ -1822,7 +1858,7 @@
 	 * Care is taken to not have commit be what
 	 * triggers putting the thin-pool in-service.
 	 */
-	__pmd_write_lock(pmd);
+	pmd_write_lock_in_core(pmd);
 	if (pmd->fail_io)
 		goto out;
 
@@ -1850,19 +1886,52 @@
 int dm_pool_abort_metadata(struct dm_pool_metadata *pmd)
 {
 	int r = -EINVAL;
+	struct dm_block_manager *old_bm = NULL, *new_bm = NULL;
+
+	/* fail_io is double-checked with pmd->root_lock held below */
+	if (unlikely(pmd->fail_io))
+		return r;
+
+	/*
+	 * Replacement block manager (new_bm) is created and old_bm destroyed outside of
+	 * pmd root_lock to avoid ABBA deadlock that would result (due to life-cycle of
+	 * shrinker associated with the block manager's bufio client vs pmd root_lock).
+	 * - must take shrinker_rwsem without holding pmd->root_lock
+	 */
+	new_bm = dm_block_manager_create(pmd->bdev, THIN_METADATA_BLOCK_SIZE << SECTOR_SHIFT,
+					 THIN_MAX_CONCURRENT_LOCKS);
 
 	pmd_write_lock(pmd);
-	if (pmd->fail_io)
+	if (pmd->fail_io) {
+		pmd_write_unlock(pmd);
 		goto out;
+	}
 
 	__set_abort_with_changes_flags(pmd);
-	__destroy_persistent_data_objects(pmd);
-	r = __create_persistent_data_objects(pmd, false);
+	__destroy_persistent_data_objects(pmd, false);
+	old_bm = pmd->bm;
+	if (IS_ERR(new_bm)) {
+		DMERR("could not create block manager during abort");
+		pmd->bm = NULL;
+		r = PTR_ERR(new_bm);
+		goto out_unlock;
+	}
+
+	pmd->bm = new_bm;
+	r = __open_or_format_metadata(pmd, false);
+	if (r) {
+		pmd->bm = NULL;
+		goto out_unlock;
+	}
+	new_bm = NULL;
+out_unlock:
 	if (r)
 		pmd->fail_io = true;
-
-out:
 	pmd_write_unlock(pmd);
+	dm_block_manager_destroy(old_bm);
+out:
+	if (new_bm && !IS_ERR(new_bm))
+		dm_block_manager_destroy(new_bm);
 
 	return r;
 }
@@ -2035,15 +2104,28 @@
 					dm_sm_threshold_fn fn,
 					void *context)
 {
-	int r;
+	int r = -EINVAL;
 
 	pmd_write_lock_in_core(pmd);
-	r = dm_sm_register_threshold_callback(pmd->metadata_sm, threshold, fn, context);
+	if (!pmd->fail_io) {
+		r = dm_sm_register_threshold_callback(pmd->metadata_sm,
+						      threshold, fn, context);
+	}
 	pmd_write_unlock(pmd);
 
 	return r;
 }
 
+void dm_pool_register_pre_commit_callback(struct dm_pool_metadata *pmd,
+					  dm_pool_pre_commit_fn fn,
+					  void *context)
+{
+	pmd_write_lock_in_core(pmd);
+	pmd->pre_commit_fn = fn;
+	pmd->pre_commit_context = context;
+	pmd_write_unlock(pmd);
+}
+
 int dm_pool_metadata_set_needs_check(struct dm_pool_metadata *pmd)
 {
 	int r = -EINVAL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-thin-metadata.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-thin-metadata.h
@@ -230,6 +230,13 @@
  */
 void dm_pool_issue_prefetches(struct dm_pool_metadata *pmd);
 
+/* Pre-commit callback */
+typedef int (*dm_pool_pre_commit_fn)(void *context);
+
+void dm_pool_register_pre_commit_callback(struct dm_pool_metadata *pmd,
+					  dm_pool_pre_commit_fn fn,
+					  void *context);
+
 /*----------------------------------------------------------------*/
 
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-thin.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-thin.c
@@ -231,6 +231,7 @@
 	struct dm_target *ti;	/* Only set if a pool target is bound */
 
 	struct mapped_device *pool_md;
+	struct block_device *data_dev;
 	struct block_device *md_dev;
 	struct dm_pool_metadata *pmd;
 
@@ -328,6 +329,7 @@
 	dm_block_t low_water_blocks;
 	struct pool_features requested_pf; /* Features requested during table load */
 	struct pool_features adjusted_pf;  /* Features used after adjusting for constituent devices */
+	struct bio flush_bio;
 };
 
 /*
@@ -2222,6 +2224,7 @@
 			throttle_work_update(&pool->throttle);
 			dm_pool_issue_prefetches(pool->pmd);
 		}
+		cond_resched();
 	}
 	blk_finish_plug(&plug);
 }
@@ -2305,6 +2308,7 @@
 			else
 				pool->process_cell(tc, cell);
 		}
+		cond_resched();
 	} while (!list_empty(&cells));
 }
 
@@ -2321,10 +2325,9 @@
 	struct thin_c *tc = NULL;
 
 	rcu_read_lock();
-	if (!list_empty(&pool->active_thins)) {
-		tc = list_entry_rcu(pool->active_thins.next, struct thin_c, list);
+	tc = list_first_or_null_rcu(&pool->active_thins, struct thin_c, list);
+	if (tc)
 		thin_get(tc);
-	}
 	rcu_read_unlock();
 
 	return tc;
@@ -2392,8 +2395,16 @@
 	while ((bio = bio_list_pop(&bio_completions)))
 		bio_endio(bio);
 
-	while ((bio = bio_list_pop(&bios)))
-		generic_make_request(bio);
+	while ((bio = bio_list_pop(&bios))) {
+		/*
+		 * The data device was flushed as part of metadata commit,
+		 * so complete redundant flushes immediately.
+		 */
+		if (bio->bi_opf & REQ_PREFLUSH)
+			bio_endio(bio);
+		else
+			generic_make_request(bio);
+	}
 }
 
 static void do_worker(struct work_struct *ws)
@@ -2465,6 +2476,7 @@
 	init_completion(&pw->complete);
 	queue_work(pool->wq, &pw->worker);
 	wait_for_completion(&pw->complete);
+	destroy_work_on_stack(&pw->worker);
 }
 
 /*----------------------------------------------------------------*/
@@ -2921,6 +2933,8 @@
 	dm_bio_prison_destroy(pool->prison);
 	dm_kcopyd_client_destroy(pool->copier);
 
+	cancel_delayed_work_sync(&pool->waker);
+	cancel_delayed_work_sync(&pool->no_space_timeout);
 	if (pool->wq)
 		destroy_workqueue(pool->wq);
 
@@ -2936,6 +2950,7 @@
 
 static struct pool *pool_create(struct mapped_device *pool_md,
 				struct block_device *metadata_dev,
+				struct block_device *data_dev,
 				unsigned long block_size,
 				int read_only, char **error)
 {
@@ -3043,6 +3058,7 @@
 	pool->last_commit_jiffies = jiffies;
 	pool->pool_md = pool_md;
 	pool->md_dev = metadata_dev;
+	pool->data_dev = data_dev;
 	__pool_table_insert(pool);
 
 	return pool;
@@ -3084,6 +3100,7 @@
 
 static struct pool *__pool_find(struct mapped_device *pool_md,
 				struct block_device *metadata_dev,
+				struct block_device *data_dev,
 				unsigned long block_size, int read_only,
 				char **error, int *created)
 {
@@ -3094,19 +3111,23 @@
 			*error = "metadata device already in use by a pool";
 			return ERR_PTR(-EBUSY);
 		}
+		if (pool->data_dev != data_dev) {
+			*error = "data device already in use by a pool";
+			return ERR_PTR(-EBUSY);
+		}
 		__pool_inc(pool);
 
 	} else {
 		pool = __pool_table_lookup(pool_md);
 		if (pool) {
-			if (pool->md_dev != metadata_dev) {
+			if (pool->md_dev != metadata_dev || pool->data_dev != data_dev) {
 				*error = "different pool cannot replace a pool";
 				return ERR_PTR(-EINVAL);
 			}
 			__pool_inc(pool);
 
 		} else {
-			pool = pool_create(pool_md, metadata_dev, block_size, read_only, error);
+			pool = pool_create(pool_md, metadata_dev, data_dev, block_size, read_only, error);
 			*created = 1;
 		}
 	}
@@ -3127,6 +3148,7 @@
 	__pool_dec(pt->pool);
 	dm_put_device(ti, pt->metadata_dev);
 	dm_put_device(ti, pt->data_dev);
+	bio_uninit(&pt->flush_bio);
 	kfree(pt);
 
 	mutex_unlock(&dm_thin_pool_table.mutex);
@@ -3192,6 +3214,29 @@
 	dm_table_event(pool->ti->table);
 }
 
+/*
+ * We need to flush the data device **before** committing the metadata.
+ *
+ * This ensures that the data blocks of any newly inserted mappings are
+ * properly written to non-volatile storage and won't be lost in case of a
+ * crash.
+ *
+ * Failure to do so can result in data corruption in the case of internal or
+ * external snapshots and in the case of newly provisioned blocks, when block
+ * zeroing is enabled.
+ */
+static int metadata_pre_commit_callback(void *context)
+{
+	struct pool_c *pt = context;
+	struct bio *flush_bio = &pt->flush_bio;
+
+	bio_reset(flush_bio);
+	bio_set_dev(flush_bio, pt->data_dev->bdev);
+	flush_bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
+
+	return submit_bio_wait(flush_bio);
+}
+
 static sector_t get_dev_size(struct block_device *bdev)
 {
 	return i_size_read(bdev->bd_inode) >> SECTOR_SHIFT;
@@ -3335,7 +3380,7 @@
 		goto out;
 	}
 
-	pool = __pool_find(dm_table_get_md(ti->table), metadata_dev->bdev,
+	pool = __pool_find(dm_table_get_md(ti->table), metadata_dev->bdev, data_dev->bdev,
 			   block_size, pf.mode == PM_READ_ONLY, &ti->error, &pool_created);
 	if (IS_ERR(pool)) {
 		r = PTR_ERR(pool);
@@ -3360,7 +3405,9 @@
 	pt->data_dev = data_dev;
 	pt->low_water_blocks = low_water_blocks;
 	pt->adjusted_pf = pt->requested_pf = pf;
+	bio_init(&pt->flush_bio, NULL, 0);
 	ti->num_flush_bios = 1;
+	ti->limit_swap_bios = true;
 
 	/*
 	 * Only need to enable discards if the pool should pass
@@ -3383,8 +3430,10 @@
 						calc_metadata_threshold(pt),
 						metadata_low_callback,
 						pool);
-	if (r)
+	if (r) {
+		ti->error = "Error registering metadata threshold";
 		goto out_flags_changed;
+	}
 
 	pt->callbacks.congested_fn = pool_is_congested;
 	dm_table_add_target_callbacks(ti->table, &pt->callbacks);
@@ -3547,20 +3596,31 @@
 	 */
 	r = bind_control_target(pool, ti);
 	if (r)
-		return r;
+		goto out;
+
+	dm_pool_register_pre_commit_callback(pool->pmd,
+					     metadata_pre_commit_callback, pt);
 
 	r = maybe_resize_data_dev(ti, &need_commit1);
 	if (r)
-		return r;
+		goto out;
 
 	r = maybe_resize_metadata_dev(ti, &need_commit2);
 	if (r)
-		return r;
+		goto out;
 
 	if (need_commit1 || need_commit2)
 		(void) commit(pool);
+out:
+	/*
+	 * When a thin-pool is PM_FAIL, it cannot be rebuilt if
+	 * bio is in deferred list. Therefore need to return 0
+	 * to allow pool_resume() to flush IO.
+	 */
+	if (r && get_pool_mode(pool) == PM_FAIL)
+		r = 0;
 
-	return 0;
+	return r;
 }
 
 static void pool_suspend_active_thins(struct pool *pool)
@@ -4077,7 +4137,7 @@
 	.name = "thin-pool",
 	.features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE |
 		    DM_TARGET_IMMUTABLE,
-	.version = {1, 21, 0},
+	.version = {1, 22, 0},
 	.module = THIS_MODULE,
 	.ctr = pool_ctr,
 	.dtr = pool_dtr,
@@ -4233,6 +4293,7 @@
 		goto bad;
 
 	ti->num_flush_bios = 1;
+	ti->limit_swap_bios = true;
 	ti->flush_supported = true;
 	ti->per_io_data_size = sizeof(struct dm_thin_endio_hook);
 
@@ -4456,7 +4517,7 @@
 
 static struct target_type thin_target = {
 	.name = "thin",
-	.version = {1, 21, 0},
+	.version = {1, 22, 0},
 	.module	= THIS_MODULE,
 	.ctr = thin_ctr,
 	.dtr = thin_dtr,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-unstripe.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-unstripe.c
@@ -84,8 +84,8 @@
 	}
 	uc->physical_start = start;
 
-	uc->unstripe_offset = uc->unstripe * uc->chunk_size;
-	uc->unstripe_width = (uc->stripes - 1) * uc->chunk_size;
+	uc->unstripe_offset = (sector_t)uc->unstripe * uc->chunk_size;
+	uc->unstripe_width = (sector_t)(uc->stripes - 1) * uc->chunk_size;
 	uc->chunk_shift = is_power_of_2(uc->chunk_size) ? fls(uc->chunk_size) - 1 : 0;
 
 	tmp_len = ti->len;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-verity-fec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-verity-fec.c
@@ -24,7 +24,8 @@
  */
 static inline struct dm_verity_fec_io *fec_io(struct dm_verity_io *io)
 {
-	return (struct dm_verity_fec_io *) verity_io_digest_end(io->v, io);
+	return (struct dm_verity_fec_io *)
+		((char *)io + io->v->ti->per_io_data_size - sizeof(struct dm_verity_fec_io));
 }
 
 /*
@@ -61,19 +62,18 @@
 static u8 *fec_read_parity(struct dm_verity *v, u64 rsb, int index,
 			   unsigned *offset, struct dm_buffer **buf)
 {
-	u64 position, block;
+	u64 position, block, rem;
 	u8 *res;
 
 	position = (index + rsb) * v->fec->roots;
-	block = position >> v->data_dev_block_bits;
-	*offset = (unsigned)(position - (block << v->data_dev_block_bits));
+	block = div64_u64_rem(position, v->fec->io_size, &rem);
+	*offset = (unsigned)rem;
 
-	res = dm_bufio_read(v->fec->bufio, v->fec->start + block, buf);
+	res = dm_bufio_read(v->fec->bufio, block, buf);
 	if (IS_ERR(res)) {
 		DMERR("%s: FEC %llu: parity read failed (block %llu): %ld",
 		      v->data_dev->name, (unsigned long long)rsb,
-		      (unsigned long long)(v->fec->start + block),
-		      PTR_ERR(res));
+		      (unsigned long long)block, PTR_ERR(res));
 		*buf = NULL;
 	}
 
@@ -155,7 +155,7 @@
 
 		/* read the next block when we run out of parity bytes */
 		offset += v->fec->roots;
-		if (offset >= 1 << v->data_dev_block_bits) {
+		if (offset >= v->fec->io_size) {
 			dm_bufio_release(buf);
 
 			par = fec_read_parity(v, rsb, block_offset, &offset, &buf);
@@ -435,7 +435,7 @@
 	fio->level++;
 
 	if (type == DM_VERITY_BLOCK_TYPE_METADATA)
-		block += v->data_blocks;
+		block = block - v->hash_start + v->data_blocks;
 
 	/*
 	 * For RS(M, N), the continuous FEC data is divided into blocks of N
@@ -551,6 +551,7 @@
 	mempool_exit(&f->rs_pool);
 	mempool_exit(&f->prealloc_pool);
 	mempool_exit(&f->extra_pool);
+	mempool_exit(&f->output_pool);
 	kmem_cache_destroy(f->cache);
 
 	if (f->data_bufio)
@@ -673,7 +674,7 @@
 {
 	struct dm_verity_fec *f = v->fec;
 	struct dm_target *ti = v->ti;
-	u64 hash_blocks;
+	u64 hash_blocks, fec_blocks;
 	int ret;
 
 	if (!verity_fec_is_enabled(v)) {
@@ -742,16 +743,23 @@
 		return -E2BIG;
 	}
 
+	if ((f->roots << SECTOR_SHIFT) & ((1 << v->data_dev_block_bits) - 1))
+		f->io_size = 1 << v->data_dev_block_bits;
+	else
+		f->io_size = v->fec->roots << SECTOR_SHIFT;
+
 	f->bufio = dm_bufio_client_create(f->dev->bdev,
-					  1 << v->data_dev_block_bits,
+					  f->io_size,
 					  1, 0, NULL, NULL);
 	if (IS_ERR(f->bufio)) {
 		ti->error = "Cannot initialize FEC bufio client";
 		return PTR_ERR(f->bufio);
 	}
 
-	if (dm_bufio_get_device_size(f->bufio) <
-	    ((f->start + f->rounds * f->roots) >> v->data_dev_block_bits)) {
+	dm_bufio_set_sector_offset(f->bufio, f->start << (v->data_dev_block_bits - SECTOR_SHIFT));
+
+	fec_blocks = div64_u64(f->rounds * f->roots, v->fec->roots << SECTOR_SHIFT);
+	if (dm_bufio_get_device_size(f->bufio) < fec_blocks) {
 		ti->error = "FEC device is too small";
 		return -E2BIG;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-verity-fec.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-verity-fec.h
@@ -36,6 +36,7 @@
 	struct dm_dev *dev;	/* parity data device */
 	struct dm_bufio_client *data_bufio;	/* for data dev access */
 	struct dm_bufio_client *bufio;		/* for parity data access */
+	size_t io_size;		/* IO size for roots */
 	sector_t start;		/* parity data start in blocks */
 	sector_t blocks;	/* number of blocks covered */
 	sector_t rounds;	/* number of interleaving rounds */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-verity-target.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-verity-target.c
@@ -33,7 +33,7 @@
 #define DM_VERITY_OPT_IGN_ZEROES	"ignore_zero_blocks"
 #define DM_VERITY_OPT_AT_MOST_ONCE	"check_at_most_once"
 
-#define DM_VERITY_OPTS_MAX		(2 + DM_VERITY_OPTS_FEC + \
+#define DM_VERITY_OPTS_MAX		(3 + DM_VERITY_OPTS_FEC + \
 					 DM_VERITY_ROOT_HASH_VERIFICATION_OPTS)
 
 static unsigned dm_verity_prefetch_cluster = DM_VERITY_DEFAULT_PREFETCH_SIZE;
@@ -471,13 +471,14 @@
 	struct bvec_iter start;
 	unsigned b;
 	struct crypto_wait wait;
+	struct bio *bio = dm_bio_from_per_bio_data(io, v->ti->per_io_data_size);
 
 	for (b = 0; b < io->n_blocks; b++) {
 		int r;
 		sector_t cur_block = io->block + b;
 		struct ahash_request *req = verity_io_hash_req(v, io);
 
-		if (v->validated_blocks &&
+		if (v->validated_blocks && bio->bi_status == BLK_STS_OK &&
 		    likely(test_bit(cur_block, v->validated_blocks))) {
 			verity_bv_skip_block(v, io, &io->iter);
 			continue;
@@ -525,15 +526,32 @@
 		else if (verity_fec_decode(v, io, DM_VERITY_BLOCK_TYPE_DATA,
 					   cur_block, NULL, &start) == 0)
 			continue;
-		else if (verity_handle_err(v, DM_VERITY_BLOCK_TYPE_DATA,
-					   cur_block))
-			return -EIO;
+		else {
+			if (bio->bi_status) {
+				/*
+				 * Error correction failed; Just return error
+				 */
+				return -EIO;
+			}
+			if (verity_handle_err(v, DM_VERITY_BLOCK_TYPE_DATA,
+					      cur_block))
+				return -EIO;
+		}
 	}
 
 	return 0;
 }
 
 /*
+ * Skip verity work in response to I/O error when system is shutting down.
+ */
+static inline bool verity_is_system_shutting_down(void)
+{
+	return system_state == SYSTEM_HALT || system_state == SYSTEM_POWER_OFF
+		|| system_state == SYSTEM_RESTART;
+}
+
+/*
  * End one "io" structure with a given error.
  */
 static void verity_finish_io(struct dm_verity_io *io, blk_status_t status)
@@ -560,7 +578,10 @@
 {
 	struct dm_verity_io *io = bio->bi_private;
 
-	if (bio->bi_status && !verity_fec_is_enabled(io->v)) {
+	if (bio->bi_status &&
+	    (!verity_fec_is_enabled(io->v) ||
+	     verity_is_system_shutting_down() ||
+	     (bio->bi_opf & REQ_RAHEAD))) {
 		verity_finish_io(io, bio->bi_status);
 		return;
 	}
@@ -1207,6 +1228,7 @@
 
 static struct target_type verity_target = {
 	.name		= "verity",
+	.features	= DM_TARGET_IMMUTABLE,
 	.version	= {1, 5, 0},
 	.module		= THIS_MODULE,
 	.ctr		= verity_ctr,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-verity-verify-sig.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-verity-verify-sig.c
@@ -15,7 +15,7 @@
 #define DM_VERITY_VERIFY_ERR(s) DM_VERITY_ROOT_HASH_VERIFICATION " " s
 
 static bool require_signatures;
-module_param(require_signatures, bool, false);
+module_param(require_signatures, bool, 0444);
 MODULE_PARM_DESC(require_signatures,
 		"Verify the roothash of dm-verity hash tree");
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-verity.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-verity.h
@@ -73,11 +73,11 @@
 	/* original value of bio->bi_end_io */
 	bio_end_io_t *orig_bi_end_io;
 
+	struct bvec_iter iter;
+
 	sector_t block;
 	unsigned n_blocks;
 
-	struct bvec_iter iter;
-
 	struct work_struct work;
 
 	/*
@@ -110,12 +110,6 @@
 	return (u8 *)(io + 1) + v->ahash_reqsize + v->digest_size;
 }
 
-static inline u8 *verity_io_digest_end(struct dm_verity *v,
-				       struct dm_verity_io *io)
-{
-	return verity_io_want_digest(v, io) + v->digest_size;
-}
-
 extern int verity_for_bv_block(struct dm_verity *v, struct dm_verity_io *io,
 			       struct bvec_iter *iter,
 			       int (*process)(struct dm_verity *v,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-writecache.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-writecache.c
@@ -20,7 +20,7 @@
 
 #define HIGH_WATERMARK			50
 #define LOW_WATERMARK			45
-#define MAX_WRITEBACK_JOBS		0
+#define MAX_WRITEBACK_JOBS		min(0x10000000 / PAGE_SIZE, totalram_pages() / 16)
 #define ENDIO_LATENCY			16
 #define WRITEBACK_LATENCY		64
 #define AUTOCOMMIT_BLOCKS_SSD		65536
@@ -142,6 +142,7 @@
 	size_t metadata_sectors;
 	size_t n_blocks;
 	uint64_t seq_count;
+	sector_t data_device_sectors;
 	void *block_start;
 	struct wc_entry *entries;
 	unsigned block_size;
@@ -153,6 +154,7 @@
 	bool overwrote_committed:1;
 	bool memory_vmapped:1;
 
+	bool start_sector_set:1;
 	bool high_wm_percent_set:1;
 	bool low_wm_percent_set:1;
 	bool max_writeback_jobs_set:1;
@@ -161,6 +163,10 @@
 	bool writeback_fua_set:1;
 	bool flush_on_suspend:1;
 
+	unsigned high_wm_percent_value;
+	unsigned low_wm_percent_value;
+	unsigned autocommit_time_value;
+
 	unsigned writeback_all;
 	struct workqueue_struct *writeback_wq;
 	struct work_struct writeback_work;
@@ -224,6 +230,7 @@
 	pfn_t pfn;
 	int id;
 	struct page **pages;
+	sector_t offset;
 
 	wc->memory_vmapped = false;
 
@@ -242,9 +249,16 @@
 		goto err1;
 	}
 
+	offset = get_start_sect(wc->ssd_dev->bdev);
+	if (offset & (PAGE_SIZE / 512 - 1)) {
+		r = -EINVAL;
+		goto err1;
+	}
+	offset >>= PAGE_SHIFT - 9;
+
 	id = dax_read_lock();
 
-	da = dax_direct_access(wc->ssd_dev->dax_dev, 0, p, &wc->memory_map, &pfn);
+	da = dax_direct_access(wc->ssd_dev->dax_dev, offset, p, &wc->memory_map, &pfn);
 	if (da < 0) {
 		wc->memory_map = NULL;
 		r = da;
@@ -266,7 +280,7 @@
 		i = 0;
 		do {
 			long daa;
-			daa = dax_direct_access(wc->ssd_dev->dax_dev, i, p - i,
+			daa = dax_direct_access(wc->ssd_dev->dax_dev, offset + i, p - i,
 						NULL, &pfn);
 			if (daa <= 0) {
 				r = daa ? daa : -EINVAL;
@@ -279,6 +293,8 @@
 			while (daa-- && i < p) {
 				pages[i++] = pfn_t_to_page(pfn);
 				pfn.val++;
+				if (!(i & 15))
+					cond_resched();
 			}
 		} while (i < p);
 		wc->memory_map = vmap(pages, p, VM_MAP, PAGE_KERNEL);
@@ -306,7 +322,7 @@
 #else
 static int persistent_memory_claim(struct dm_writecache *wc)
 {
-	BUG();
+	return -EOPNOTSUPP;
 }
 #endif
 
@@ -442,7 +458,13 @@
 		complete(&endio->c);
 }
 
-static void ssd_commit_flushed(struct dm_writecache *wc)
+static void writecache_wait_for_ios(struct dm_writecache *wc, int direction)
+{
+	wait_event(wc->bio_in_progress_wait[direction],
+		   !atomic_read(&wc->bio_in_progress[direction]));
+}
+
+static void ssd_commit_flushed(struct dm_writecache *wc, bool wait_for_ios)
 {
 	struct dm_io_region region;
 	struct dm_io_request req;
@@ -488,17 +510,20 @@
 	writecache_notify_io(0, &endio);
 	wait_for_completion_io(&endio.c);
 
+	if (wait_for_ios)
+		writecache_wait_for_ios(wc, WRITE);
+
 	writecache_disk_flush(wc, wc->ssd_dev);
 
 	memset(wc->dirty_bitmap, 0, wc->dirty_bitmap_size);
 }
 
-static void writecache_commit_flushed(struct dm_writecache *wc)
+static void writecache_commit_flushed(struct dm_writecache *wc, bool wait_for_ios)
 {
 	if (WC_MODE_PMEM(wc))
 		wmb();
 	else
-		ssd_commit_flushed(wc);
+		ssd_commit_flushed(wc, wait_for_ios);
 }
 
 static void writecache_disk_flush(struct dm_writecache *wc, struct dm_dev *dev)
@@ -522,12 +547,6 @@
 		writecache_error(wc, r, "error flushing metadata: %d", r);
 }
 
-static void writecache_wait_for_ios(struct dm_writecache *wc, int direction)
-{
-	wait_event(wc->bio_in_progress_wait[direction],
-		   !atomic_read(&wc->bio_in_progress[direction]));
-}
-
 #define WFE_RETURN_FOLLOWING	1
 #define WFE_LOWEST_SEQ		2
 
@@ -622,6 +641,12 @@
 	wc->freelist_size++;
 }
 
+static inline void writecache_verify_watermark(struct dm_writecache *wc)
+{
+	if (unlikely(wc->freelist_size + wc->writeback_size <= wc->freelist_high_watermark))
+		queue_work(wc->writeback_wq, &wc->writeback_work);
+}
+
 static struct wc_entry *writecache_pop_from_freelist(struct dm_writecache *wc)
 {
 	struct wc_entry *e;
@@ -643,8 +668,8 @@
 		list_del(&e->lru);
 	}
 	wc->freelist_size--;
-	if (unlikely(wc->freelist_size + wc->writeback_size <= wc->freelist_high_watermark))
-		queue_work(wc->writeback_wq, &wc->writeback_work);
+
+	writecache_verify_watermark(wc);
 
 	return e;
 }
@@ -724,15 +749,12 @@
 		e = e2;
 		cond_resched();
 	}
-	writecache_commit_flushed(wc);
-
-	if (!WC_MODE_PMEM(wc))
-		writecache_wait_for_ios(wc, WRITE);
+	writecache_commit_flushed(wc, true);
 
 	wc->seq_count++;
 	pmem_assign(sb(wc)->seq_count, cpu_to_le64(wc->seq_count));
 	writecache_flush_region(wc, &sb(wc)->seq_count, sizeof sb(wc)->seq_count);
-	writecache_commit_flushed(wc);
+	writecache_commit_flushed(wc, false);
 
 	wc->overwrote_committed = false;
 
@@ -756,7 +778,7 @@
 	}
 
 	if (need_flush_after_free)
-		writecache_commit_flushed(wc);
+		writecache_commit_flushed(wc, false);
 }
 
 static void writecache_flush_work(struct work_struct *work)
@@ -799,6 +821,8 @@
 				writecache_wait_for_ios(wc, WRITE);
 				discarded_something = true;
 			}
+			if (!writecache_entry_is_committed(wc, e))
+				wc->uncommitted_blocks--;
 			writecache_free_entry(wc, e);
 		}
 
@@ -809,7 +833,7 @@
 	}
 
 	if (discarded_something)
-		writecache_commit_flushed(wc);
+		writecache_commit_flushed(wc, false);
 }
 
 static bool writecache_wait_for_writeback(struct dm_writecache *wc)
@@ -838,7 +862,7 @@
 	}
 	wc_unlock(wc);
 
-	flush_workqueue(wc->writeback_wq);
+	drain_workqueue(wc->writeback_wq);
 
 	wc_lock(wc);
 	if (flush_on_suspend)
@@ -866,11 +890,30 @@
 		struct wc_entry *e = &wc->entries[b];
 		e->index = b;
 		e->write_in_progress = false;
+		cond_resched();
 	}
 
 	return 0;
 }
 
+static int writecache_read_metadata(struct dm_writecache *wc, sector_t n_sectors)
+{
+	struct dm_io_region region;
+	struct dm_io_request req;
+
+	region.bdev = wc->ssd_dev->bdev;
+	region.sector = wc->start_sector;
+	region.count = n_sectors;
+	req.bi_op = REQ_OP_READ;
+	req.bi_op_flags = REQ_SYNC;
+	req.mem.type = DM_IO_VMA;
+	req.mem.ptr.vma = (char *)wc->memory_map;
+	req.client = wc->dm_io;
+	req.notify.fn = NULL;
+
+	return dm_io(&req, 1, &region, NULL);
+}
+
 static void writecache_resume(struct dm_target *ti)
 {
 	struct dm_writecache *wc = ti->private;
@@ -881,8 +924,20 @@
 
 	wc_lock(wc);
 
-	if (WC_MODE_PMEM(wc))
+	wc->data_device_sectors = i_size_read(wc->dev->bdev->bd_inode) >> SECTOR_SHIFT;
+
+	if (WC_MODE_PMEM(wc)) {
 		persistent_memory_invalidate_cache(wc->memory_map, wc->memory_map_size);
+	} else {
+		r = writecache_read_metadata(wc, wc->metadata_sectors);
+		if (r) {
+			size_t sb_entries_offset;
+			writecache_error(wc, r, "unable to read metadata: %d", r);
+			sb_entries_offset = offsetof(struct wc_memory_superblock, entries);
+			memset((char *)wc->memory_map + sb_entries_offset, -1,
+			       (wc->metadata_sectors << SECTOR_SHIFT) - sb_entries_offset);
+		}
+	}
 
 	wc->tree = RB_ROOT;
 	INIT_LIST_HEAD(&wc->lru);
@@ -920,6 +975,7 @@
 			e->original_sector = le64_to_cpu(wme.original_sector);
 			e->seq_count = le64_to_cpu(wme.seq_count);
 		}
+		cond_resched();
 	}
 #endif
 	for (b = 0; b < wc->n_blocks; b++) {
@@ -958,9 +1014,11 @@
 
 	if (need_flush) {
 		writecache_flush_all_metadata(wc);
-		writecache_commit_flushed(wc);
+		writecache_commit_flushed(wc, false);
 	}
 
+	writecache_verify_watermark(wc);
+
 	wc_unlock(wc);
 }
 
@@ -1218,7 +1276,8 @@
 			}
 		} while (bio->bi_iter.bi_size);
 
-		if (unlikely(wc->uncommitted_blocks >= wc->autocommit_blocks))
+		if (unlikely(bio->bi_opf & REQ_FUA ||
+			     wc->uncommitted_blocks >= wc->autocommit_blocks))
 			writecache_flush(wc);
 		else
 			writecache_schedule_autocommit(wc);
@@ -1341,7 +1400,7 @@
 			wc->writeback_size--;
 			n_walked++;
 			if (unlikely(n_walked >= ENDIO_LATENCY)) {
-				writecache_commit_flushed(wc);
+				writecache_commit_flushed(wc, false);
 				wc_unlock(wc);
 				wc_lock(wc);
 				n_walked = 0;
@@ -1422,7 +1481,7 @@
 			writecache_wait_for_ios(wc, READ);
 		}
 
-		writecache_commit_flushed(wc);
+		writecache_commit_flushed(wc, false);
 
 		wc_unlock(wc);
 	}
@@ -1437,6 +1496,10 @@
 	void *address = memory_data(wc, e);
 
 	persistent_memory_flush_cache(address, block_size);
+
+	if (unlikely(bio_end_sector(&wb->bio) >= wc->data_device_sectors))
+		return true;
+
 	return bio_add_page(&wb->bio, persistent_memory_page(address),
 			    block_size, persistent_memory_page_offset(address)) != 0;
 }
@@ -1508,6 +1571,9 @@
 		if (writecache_has_error(wc)) {
 			bio->bi_status = BLK_STS_IOERR;
 			bio_endio(bio);
+		} else if (unlikely(!bio_sectors(bio))) {
+			bio->bi_status = BLK_STS_OK;
+			bio_endio(bio);
 		} else {
 			submit_bio(bio);
 		}
@@ -1551,6 +1617,14 @@
 			e = f;
 		}
 
+		if (unlikely(to.sector + to.count > wc->data_device_sectors)) {
+			if (to.sector >= wc->data_device_sectors) {
+				writecache_copy_endio(0, 0, c);
+				continue;
+			}
+			from.count = to.count = wc->data_device_sectors - to.sector;
+		}
+
 		dm_kcopyd_copy(wc->dm_kcopyd, &from, 1, &to, 0, writecache_copy_endio, c);
 
 		__writeback_throttle(wc, wbl);
@@ -1761,14 +1835,16 @@
 	pmem_assign(sb(wc)->n_blocks, cpu_to_le64(wc->n_blocks));
 	pmem_assign(sb(wc)->seq_count, cpu_to_le64(0));
 
-	for (b = 0; b < wc->n_blocks; b++)
+	for (b = 0; b < wc->n_blocks; b++) {
 		write_original_sector_seq_count(wc, &wc->entries[b], -1, -1);
+		cond_resched();
+	}
 
 	writecache_flush_all_metadata(wc);
-	writecache_commit_flushed(wc);
+	writecache_commit_flushed(wc, false);
 	pmem_assign(sb(wc)->magic, cpu_to_le32(MEMORY_SUPERBLOCK_MAGIC));
 	writecache_flush_region(wc, &sb(wc)->magic, sizeof sb(wc)->magic);
-	writecache_commit_flushed(wc);
+	writecache_commit_flushed(wc, false);
 
 	return 0;
 }
@@ -1836,7 +1912,7 @@
 	struct wc_memory_superblock s;
 
 	static struct dm_arg _args[] = {
-		{0, 10, "Invalid number of feature args"},
+		{0, 16, "Invalid number of feature args"},
 	};
 
 	as.argc = argc;
@@ -1971,6 +2047,12 @@
 		ti->error = "Invalid block size";
 		goto bad;
 	}
+	if (wc->block_size < bdev_logical_block_size(wc->dev->bdev) ||
+	    wc->block_size < bdev_logical_block_size(wc->ssd_dev->bdev)) {
+		r = -EINVAL;
+		ti->error = "Block size is smaller than device logical block size";
+		goto bad;
+	}
 	wc->block_size_bits = __ffs(wc->block_size);
 
 	wc->max_writeback_jobs = MAX_WRITEBACK_JOBS;
@@ -1992,6 +2074,7 @@
 			if (sscanf(string, "%llu%c", &start_sector, &dummy) != 1)
 				goto invalid_optional;
 			wc->start_sector = start_sector;
+			wc->start_sector_set = true;
 			if (wc->start_sector != start_sector ||
 			    wc->start_sector >= wc->memory_map_size >> SECTOR_SHIFT)
 				goto invalid_optional;
@@ -2001,6 +2084,7 @@
 				goto invalid_optional;
 			if (high_wm_percent < 0 || high_wm_percent > 100)
 				goto invalid_optional;
+			wc->high_wm_percent_value = high_wm_percent;
 			wc->high_wm_percent_set = true;
 		} else if (!strcasecmp(string, "low_watermark") && opt_params >= 1) {
 			string = dm_shift_arg(&as), opt_params--;
@@ -2008,6 +2092,7 @@
 				goto invalid_optional;
 			if (low_wm_percent < 0 || low_wm_percent > 100)
 				goto invalid_optional;
+			wc->low_wm_percent_value = low_wm_percent;
 			wc->low_wm_percent_set = true;
 		} else if (!strcasecmp(string, "writeback_jobs") && opt_params >= 1) {
 			string = dm_shift_arg(&as), opt_params--;
@@ -2027,6 +2112,7 @@
 			if (autocommit_msecs > 3600000)
 				goto invalid_optional;
 			wc->autocommit_jiffies = msecs_to_jiffies(autocommit_msecs);
+			wc->autocommit_time_value = autocommit_msecs;
 			wc->autocommit_time_set = true;
 		} else if (!strcasecmp(string, "fua")) {
 			if (WC_MODE_PMEM(wc)) {
@@ -2053,14 +2139,18 @@
 	}
 
 	if (WC_MODE_PMEM(wc)) {
+		if (!dax_synchronous(wc->ssd_dev->dax_dev)) {
+			r = -EOPNOTSUPP;
+			ti->error = "Asynchronous persistent memory not supported as pmem cache";
+			goto bad;
+		}
+
 		r = persistent_memory_claim(wc);
 		if (r) {
 			ti->error = "Unable to map persistent memory for cache";
 			goto bad;
 		}
 	} else {
-		struct dm_io_region region;
-		struct dm_io_request req;
 		size_t n_blocks, n_metadata_blocks;
 		uint64_t n_bitmap_bits;
 
@@ -2117,19 +2207,9 @@
 			goto bad;
 		}
 
-		region.bdev = wc->ssd_dev->bdev;
-		region.sector = wc->start_sector;
-		region.count = wc->metadata_sectors;
-		req.bi_op = REQ_OP_READ;
-		req.bi_op_flags = REQ_SYNC;
-		req.mem.type = DM_IO_VMA;
-		req.mem.ptr.vma = (char *)wc->memory_map;
-		req.client = wc->dm_io;
-		req.notify.fn = NULL;
-
-		r = dm_io(&req, 1, &region, NULL);
+		r = writecache_read_metadata(wc, wc->block_size >> SECTOR_SHIFT);
 		if (r) {
-			ti->error = "Unable to read metadata";
+			ti->error = "Unable to read first block of metadata";
 			goto bad;
 		}
 	}
@@ -2234,7 +2314,6 @@
 	struct dm_writecache *wc = ti->private;
 	unsigned extra_args;
 	unsigned sz = 0;
-	uint64_t x;
 
 	switch (type) {
 	case STATUSTYPE_INFO:
@@ -2246,7 +2325,7 @@
 		DMEMIT("%c %s %s %u ", WC_MODE_PMEM(wc) ? 'p' : 's',
 				wc->dev->name, wc->ssd_dev->name, wc->block_size);
 		extra_args = 0;
-		if (wc->start_sector)
+		if (wc->start_sector_set)
 			extra_args += 2;
 		if (wc->high_wm_percent_set)
 			extra_args += 2;
@@ -2262,26 +2341,18 @@
 			extra_args++;
 
 		DMEMIT("%u", extra_args);
-		if (wc->start_sector)
+		if (wc->start_sector_set)
 			DMEMIT(" start_sector %llu", (unsigned long long)wc->start_sector);
-		if (wc->high_wm_percent_set) {
-			x = (uint64_t)wc->freelist_high_watermark * 100;
-			x += wc->n_blocks / 2;
-			do_div(x, (size_t)wc->n_blocks);
-			DMEMIT(" high_watermark %u", 100 - (unsigned)x);
-		}
-		if (wc->low_wm_percent_set) {
-			x = (uint64_t)wc->freelist_low_watermark * 100;
-			x += wc->n_blocks / 2;
-			do_div(x, (size_t)wc->n_blocks);
-			DMEMIT(" low_watermark %u", 100 - (unsigned)x);
-		}
+		if (wc->high_wm_percent_set)
+			DMEMIT(" high_watermark %u", wc->high_wm_percent_value);
+		if (wc->low_wm_percent_set)
+			DMEMIT(" low_watermark %u", wc->low_wm_percent_value);
 		if (wc->max_writeback_jobs_set)
 			DMEMIT(" writeback_jobs %u", wc->max_writeback_jobs);
 		if (wc->autocommit_blocks_set)
 			DMEMIT(" autocommit_blocks %u", wc->autocommit_blocks);
 		if (wc->autocommit_time_set)
-			DMEMIT(" autocommit_time %u", jiffies_to_msecs(wc->autocommit_jiffies));
+			DMEMIT(" autocommit_time %u", wc->autocommit_time_value);
 		if (wc->writeback_fua_set)
 			DMEMIT(" %sfua", wc->writeback_fua ? "" : "no");
 		break;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-zoned-metadata.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-zoned-metadata.c
@@ -134,6 +134,7 @@
 
 	sector_t		zone_bitmap_size;
 	unsigned int		zone_nr_bitmap_blocks;
+	unsigned int		zone_bits_per_mblk;
 
 	unsigned int		nr_bitmap_blocks;
 	unsigned int		nr_map_blocks;
@@ -554,6 +555,7 @@
 		       TASK_UNINTERRUPTIBLE);
 	if (test_bit(DMZ_META_ERROR, &mblk->state)) {
 		dmz_release_mblock(zmd, mblk);
+		dmz_check_bdev(zmd->dev);
 		return ERR_PTR(-EIO);
 	}
 
@@ -625,6 +627,8 @@
 	ret = submit_bio_wait(bio);
 	bio_put(bio);
 
+	if (ret)
+		dmz_check_bdev(zmd->dev);
 	return ret;
 }
 
@@ -691,6 +695,7 @@
 			       TASK_UNINTERRUPTIBLE);
 		if (test_bit(DMZ_META_ERROR, &mblk->state)) {
 			clear_bit(DMZ_META_ERROR, &mblk->state);
+			dmz_check_bdev(zmd->dev);
 			ret = -EIO;
 		}
 		nr_mblks_submitted--;
@@ -768,7 +773,7 @@
 	/* If there are no dirty metadata blocks, just flush the device cache */
 	if (list_empty(&write_list)) {
 		ret = blkdev_issue_flush(zmd->dev->bdev, GFP_NOIO, NULL);
-		goto out;
+		goto err;
 	}
 
 	/*
@@ -778,7 +783,7 @@
 	 */
 	ret = dmz_log_dirty_mblocks(zmd, &write_list);
 	if (ret)
-		goto out;
+		goto err;
 
 	/*
 	 * The log is on disk. It is now safe to update in place
@@ -786,11 +791,11 @@
 	 */
 	ret = dmz_write_dirty_mblocks(zmd, &write_list, zmd->mblk_primary);
 	if (ret)
-		goto out;
+		goto err;
 
 	ret = dmz_write_sb(zmd, zmd->mblk_primary);
 	if (ret)
-		goto out;
+		goto err;
 
 	while (!list_empty(&write_list)) {
 		mblk = list_first_entry(&write_list, struct dmz_mblock, link);
@@ -805,16 +810,20 @@
 
 	zmd->sb_gen++;
 out:
-	if (ret && !list_empty(&write_list)) {
-		spin_lock(&zmd->mblk_lock);
-		list_splice(&write_list, &zmd->mblk_dirty_list);
-		spin_unlock(&zmd->mblk_lock);
-	}
-
 	dmz_unlock_flush(zmd);
 	up_write(&zmd->mblk_sem);
 
 	return ret;
+
+err:
+	if (!list_empty(&write_list)) {
+		spin_lock(&zmd->mblk_lock);
+		list_splice(&write_list, &zmd->mblk_dirty_list);
+		spin_unlock(&zmd->mblk_lock);
+	}
+	if (!dmz_check_bdev(zmd->dev))
+		ret = -EIO;
+	goto out;
 }
 
 /*
@@ -1098,7 +1107,6 @@
 
 	if (blkz->type == BLK_ZONE_TYPE_CONVENTIONAL) {
 		set_bit(DMZ_RND, &zone->flags);
-		zmd->nr_rnd_zones++;
 	} else if (blkz->type == BLK_ZONE_TYPE_SEQWRITE_REQ ||
 		   blkz->type == BLK_ZONE_TYPE_SEQWRITE_PREF) {
 		set_bit(DMZ_SEQ, &zone->flags);
@@ -1159,7 +1167,10 @@
 
 	/* Init */
 	zmd->zone_bitmap_size = dev->zone_nr_blocks >> 3;
-	zmd->zone_nr_bitmap_blocks = zmd->zone_bitmap_size >> DMZ_BLOCK_SHIFT;
+	zmd->zone_nr_bitmap_blocks =
+		max_t(sector_t, 1, zmd->zone_bitmap_size >> DMZ_BLOCK_SHIFT);
+	zmd->zone_bits_per_mblk = min_t(sector_t, dev->zone_nr_blocks,
+					DMZ_BLOCK_SIZE_BITS);
 
 	/* Allocate zone array */
 	zmd->zones = kcalloc(dev->nr_zones, sizeof(struct dm_zone), GFP_KERNEL);
@@ -1244,6 +1255,7 @@
 	if (ret) {
 		dmz_dev_err(zmd->dev, "Get zone %u report failed",
 			    dmz_id(zmd, zone));
+		dmz_check_bdev(zmd->dev);
 		return ret;
 	}
 
@@ -1577,7 +1589,7 @@
 			return dzone;
 	}
 
-	return ERR_PTR(-EBUSY);
+	return NULL;
 }
 
 /*
@@ -1597,7 +1609,7 @@
 			return zone;
 	}
 
-	return ERR_PTR(-EBUSY);
+	return NULL;
 }
 
 /*
@@ -1982,7 +1994,7 @@
 		dmz_release_mblock(zmd, to_mblk);
 		dmz_release_mblock(zmd, from_mblk);
 
-		chunk_block += DMZ_BLOCK_SIZE_BITS;
+		chunk_block += zmd->zone_bits_per_mblk;
 	}
 
 	to_zone->weight = from_zone->weight;
@@ -2043,7 +2055,7 @@
 
 		/* Set bits */
 		bit = chunk_block & DMZ_BLOCK_MASK_BITS;
-		nr_bits = min(nr_blocks, DMZ_BLOCK_SIZE_BITS - bit);
+		nr_bits = min(nr_blocks, zmd->zone_bits_per_mblk - bit);
 
 		count = dmz_set_bits((unsigned long *)mblk->data, bit, nr_bits);
 		if (count) {
@@ -2122,7 +2134,7 @@
 
 		/* Clear bits */
 		bit = chunk_block & DMZ_BLOCK_MASK_BITS;
-		nr_bits = min(nr_blocks, DMZ_BLOCK_SIZE_BITS - bit);
+		nr_bits = min(nr_blocks, zmd->zone_bits_per_mblk - bit);
 
 		count = dmz_clear_bits((unsigned long *)mblk->data,
 				       bit, nr_bits);
@@ -2182,6 +2194,7 @@
 {
 	struct dmz_mblock *mblk;
 	unsigned int bit, set_bit, nr_bits;
+	unsigned int zone_bits = zmd->zone_bits_per_mblk;
 	unsigned long *bitmap;
 	int n = 0;
 
@@ -2196,15 +2209,15 @@
 		/* Get offset */
 		bitmap = (unsigned long *) mblk->data;
 		bit = chunk_block & DMZ_BLOCK_MASK_BITS;
-		nr_bits = min(nr_blocks, DMZ_BLOCK_SIZE_BITS - bit);
+		nr_bits = min(nr_blocks, zone_bits - bit);
 		if (set)
-			set_bit = find_next_bit(bitmap, DMZ_BLOCK_SIZE_BITS, bit);
+			set_bit = find_next_bit(bitmap, zone_bits, bit);
 		else
-			set_bit = find_next_zero_bit(bitmap, DMZ_BLOCK_SIZE_BITS, bit);
+			set_bit = find_next_zero_bit(bitmap, zone_bits, bit);
 		dmz_release_mblock(zmd, mblk);
 
 		n += set_bit - bit;
-		if (set_bit < DMZ_BLOCK_SIZE_BITS)
+		if (set_bit < zone_bits)
 			break;
 
 		nr_blocks -= nr_bits;
@@ -2307,7 +2320,7 @@
 		/* Count bits in this block */
 		bitmap = mblk->data;
 		bit = chunk_block & DMZ_BLOCK_MASK_BITS;
-		nr_bits = min(nr_blocks, DMZ_BLOCK_SIZE_BITS - bit);
+		nr_bits = min(nr_blocks, zmd->zone_bits_per_mblk - bit);
 		n += dmz_count_bits(bitmap, bit, nr_bits);
 
 		dmz_release_mblock(zmd, mblk);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-zoned-reclaim.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-zoned-reclaim.c
@@ -82,6 +82,7 @@
 			    "Align zone %u wp %llu to %llu (wp+%u) blocks failed %d",
 			    dmz_id(zmd, zone), (unsigned long long)wp_block,
 			    (unsigned long long)block, nr_blocks, ret);
+		dmz_check_bdev(zrc->dev);
 		return ret;
 	}
 
@@ -348,8 +349,8 @@
 
 	/* Get a data zone */
 	dzone = dmz_get_zone_for_reclaim(zmd);
-	if (IS_ERR(dzone))
-		return PTR_ERR(dzone);
+	if (!dzone)
+		return -EBUSY;
 
 	start = jiffies;
 
@@ -489,12 +490,7 @@
 	ret = dmz_do_reclaim(zrc);
 	if (ret) {
 		dmz_dev_debug(zrc->dev, "Reclaim error %d\n", ret);
-		if (ret == -EIO)
-			/*
-			 * LLD might be performing some error handling sequence
-			 * at the underlying device. To not interfere, do not
-			 * attempt to schedule the next reclaim run immediately.
-			 */
+		if (!dmz_check_bdev(zrc->dev))
 			return;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-zoned-target.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-zoned-target.c
@@ -80,6 +80,8 @@
 
 	if (status != BLK_STS_OK && bio->bi_status == BLK_STS_OK)
 		bio->bi_status = status;
+	if (bio->bi_status != BLK_STS_OK)
+		bioctx->target->dev->flags |= DMZ_CHECK_BDEV;
 
 	if (refcount_dec_and_test(&bioctx->ref)) {
 		struct dm_zone *zone = bioctx->zone;
@@ -531,8 +533,9 @@
 
 	/* Get the BIO chunk work. If one is not active yet, create one */
 	cw = radix_tree_lookup(&dmz->chunk_rxtree, chunk);
-	if (!cw) {
-
+	if (cw) {
+		dmz_get_chunk_work(cw);
+	} else {
 		/* Create a new chunk work */
 		cw = kmalloc(sizeof(struct dm_chunk_work), GFP_NOIO);
 		if (unlikely(!cw)) {
@@ -541,7 +544,7 @@
 		}
 
 		INIT_WORK(&cw->work, dmz_chunk_work);
-		refcount_set(&cw->refcount, 0);
+		refcount_set(&cw->refcount, 1);
 		cw->target = dmz;
 		cw->chunk = chunk;
 		bio_list_init(&cw->bio_list);
@@ -554,7 +557,6 @@
 	}
 
 	bio_list_add(&cw->bio_list, bio);
-	dmz_get_chunk_work(cw);
 
 	dmz_reclaim_bio_acc(dmz->reclaim);
 	if (queue_work(dmz->chunk_wq, &cw->work))
@@ -565,32 +567,52 @@
 }
 
 /*
- * Check the backing device availability. If it's on the way out,
+ * Check if the backing device is being removed. If it's on the way out,
  * start failing I/O. Reclaim and metadata components also call this
  * function to cleanly abort operation in the event of such failure.
  */
 bool dmz_bdev_is_dying(struct dmz_dev *dmz_dev)
 {
-	struct gendisk *disk;
+	if (dmz_dev->flags & DMZ_BDEV_DYING)
+		return true;
 
-	if (!(dmz_dev->flags & DMZ_BDEV_DYING)) {
-		disk = dmz_dev->bdev->bd_disk;
-		if (blk_queue_dying(bdev_get_queue(dmz_dev->bdev))) {
-			dmz_dev_warn(dmz_dev, "Backing device queue dying");
-			dmz_dev->flags |= DMZ_BDEV_DYING;
-		} else if (disk->fops->check_events) {
-			if (disk->fops->check_events(disk, 0) &
-					DISK_EVENT_MEDIA_CHANGE) {
-				dmz_dev_warn(dmz_dev, "Backing device offline");
-				dmz_dev->flags |= DMZ_BDEV_DYING;
-			}
-		}
+	if (dmz_dev->flags & DMZ_CHECK_BDEV)
+		return !dmz_check_bdev(dmz_dev);
+
+	if (blk_queue_dying(bdev_get_queue(dmz_dev->bdev))) {
+		dmz_dev_warn(dmz_dev, "Backing device queue dying");
+		dmz_dev->flags |= DMZ_BDEV_DYING;
 	}
 
 	return dmz_dev->flags & DMZ_BDEV_DYING;
 }
 
 /*
+ * Check the backing device availability. This detects such events as
+ * backing device going offline due to errors, media removals, etc.
+ * This check is less efficient than dmz_bdev_is_dying() and should
+ * only be performed as a part of error handling.
+ */
+bool dmz_check_bdev(struct dmz_dev *dmz_dev)
+{
+	struct gendisk *disk;
+
+	dmz_dev->flags &= ~DMZ_CHECK_BDEV;
+
+	if (dmz_bdev_is_dying(dmz_dev))
+		return false;
+
+	disk = dmz_dev->bdev->bd_disk;
+	if (disk->fops->check_events &&
+	    disk->fops->check_events(disk, 0) & DISK_EVENT_MEDIA_CHANGE) {
+		dmz_dev_warn(dmz_dev, "Backing device offline");
+		dmz_dev->flags |= DMZ_BDEV_DYING;
+	}
+
+	return !(dmz_dev->flags & DMZ_BDEV_DYING);
+}
+
+/*
  * Process a new BIO.
  */
 static int dmz_map(struct dm_target *ti, struct bio *bio)
@@ -768,7 +790,7 @@
 	}
 
 	/* Set target (no write same support) */
-	ti->max_io_len = dev->zone_nr_sectors << 9;
+	ti->max_io_len = dev->zone_nr_sectors;
 	ti->num_flush_bios = 1;
 	ti->num_discard_bios = 1;
 	ti->num_write_zeroes_bios = 1;
@@ -902,8 +924,8 @@
 {
 	struct dmz_target *dmz = ti->private;
 
-	if (dmz_bdev_is_dying(dmz->dev))
-		return -ENODEV;
+	if (!dmz_check_bdev(dmz->dev))
+		return -EIO;
 
 	*bdev = dmz->dev->bdev;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm-zoned.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm-zoned.h
@@ -72,6 +72,7 @@
 
 /* Device flags. */
 #define DMZ_BDEV_DYING		(1 << 0)
+#define DMZ_CHECK_BDEV		(2 << 0)
 
 /*
  * Zone descriptor.
@@ -255,5 +256,6 @@
  * Functions defined in dm-zoned-target.c
  */
 bool dmz_bdev_is_dying(struct dmz_dev *dmz_dev);
+bool dmz_check_bdev(struct dmz_dev *dmz_dev);
 
 #endif /* DM_ZONED_H */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm.c
@@ -12,6 +12,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/sched/mm.h>
 #include <linux/sched/signal.h>
 #include <linux/blkpg.h>
 #include <linux/bio.h>
@@ -140,10 +141,21 @@
 #define DMF_NOFLUSH_SUSPENDING 5
 #define DMF_DEFERRED_REMOVE 6
 #define DMF_SUSPENDED_INTERNALLY 7
+#define DMF_POST_SUSPENDING 8
 
 #define DM_NUMA_NODE NUMA_NO_NODE
 static int dm_numa_node = DM_NUMA_NODE;
 
+#define DEFAULT_SWAP_BIOS	(8 * 1048576 / PAGE_SIZE)
+static int swap_bios = DEFAULT_SWAP_BIOS;
+static int get_swap_bios(void)
+{
+	int latch = READ_ONCE(swap_bios);
+	if (unlikely(latch <= 0))
+		latch = DEFAULT_SWAP_BIOS;
+	return latch;
+}
+
 /*
  * For mempools pre-allocation at the table loading time.
  */
@@ -251,7 +263,6 @@
 
 static void local_exit(void)
 {
-	flush_scheduled_work();
 	destroy_workqueue(deferred_remove_workqueue);
 
 	unregister_blkdev(_major, _name);
@@ -453,8 +464,10 @@
 		return -EAGAIN;
 
 	map = dm_get_live_table(md, &srcu_idx);
-	if (!map)
-		return -EIO;
+	if (!map) {
+		ret = -EIO;
+		goto out;
+	}
 
 	tgt = dm_table_find_target(map, sector);
 	if (!tgt) {
@@ -491,7 +504,6 @@
 
 static int dm_prepare_ioctl(struct mapped_device *md, int *srcu_idx,
 			    struct block_device **bdev)
-	__acquires(md->io_barrier)
 {
 	struct dm_target *tgt;
 	struct dm_table *map;
@@ -525,7 +537,6 @@
 }
 
 static void dm_unprepare_ioctl(struct mapped_device *md, int srcu_idx)
-	__releases(md->io_barrier)
 {
 	dm_put_live_table(md, srcu_idx);
 }
@@ -546,7 +557,7 @@
 		 * subset of the parent bdev; require extra privileges.
 		 */
 		if (!capable(CAP_SYS_RAWIO)) {
-			DMWARN_LIMIT(
+			DMDEBUG_LIMIT(
 	"%s: sending ioctl %x to DM device without required privilege.",
 				current->comm, cmd);
 			r = -ENOIOCTLCMD;
@@ -626,27 +637,14 @@
 	bio_put(&tio->clone);
 }
 
-static bool md_in_flight_bios(struct mapped_device *md)
+u64 dm_start_time_ns_from_clone(struct bio *bio)
 {
-	int cpu;
-	struct hd_struct *part = &dm_disk(md)->part0;
-	long sum = 0;
-
-	for_each_possible_cpu(cpu) {
-		sum += part_stat_local_read_cpu(part, in_flight[0], cpu);
-		sum += part_stat_local_read_cpu(part, in_flight[1], cpu);
-	}
+	struct dm_target_io *tio = container_of(bio, struct dm_target_io, clone);
+	struct dm_io *io = tio->io;
 
-	return sum != 0;
-}
-
-static bool md_in_flight(struct mapped_device *md)
-{
-	if (queue_is_mq(md->queue))
-		return blk_mq_queue_inflight(md->queue);
-	else
-		return md_in_flight_bios(md);
+	return jiffies_to_nsecs(io->start_time);
 }
+EXPORT_SYMBOL_GPL(dm_start_time_ns_from_clone);
 
 static void start_io_acct(struct dm_io *io)
 {
@@ -664,19 +662,20 @@
 				    false, 0, &io->stats_aux);
 }
 
-static void end_io_acct(struct dm_io *io)
+static void end_io_acct(struct mapped_device *md, struct bio *bio,
+			unsigned long start_time, struct dm_stats_aux *stats_aux)
 {
-	struct mapped_device *md = io->md;
-	struct bio *bio = io->orig_bio;
-	unsigned long duration = jiffies - io->start_time;
-
-	generic_end_io_acct(md->queue, bio_op(bio), &dm_disk(md)->part0,
-			    io->start_time);
+	unsigned long duration = jiffies - start_time;
 
 	if (unlikely(dm_stats_used(&md->stats)))
 		dm_stats_account_io(&md->stats, bio_data_dir(bio),
 				    bio->bi_iter.bi_sector, bio_sectors(bio),
-				    true, duration, &io->stats_aux);
+				    true, duration, stats_aux);
+
+	smp_wmb();
+
+	generic_end_io_acct(md->queue, bio_op(bio), &dm_disk(md)->part0,
+			    start_time);
 
 	/* nudge anyone waiting on suspend queue */
 	if (unlikely(wq_has_sleeper(&md->wait)))
@@ -897,6 +896,8 @@
 	blk_status_t io_error;
 	struct bio *bio;
 	struct mapped_device *md = io->md;
+	unsigned long start_time = 0;
+	struct dm_stats_aux stats_aux;
 
 	/* Push-back supersedes any I/O errors */
 	if (unlikely(error)) {
@@ -923,8 +924,10 @@
 
 		io_error = io->status;
 		bio = io->orig_bio;
-		end_io_acct(io);
+		start_time = io->start_time;
+		stats_aux = io->stats_aux;
 		free_io(md, io);
+		end_io_acct(md, bio, start_time, &stats_aux);
 
 		if (io_error == BLK_STS_DM_REQUEUE)
 			return;
@@ -970,6 +973,11 @@
 	limits->max_write_zeroes_sectors = 0;
 }
 
+static bool swap_bios_limit(struct dm_target *ti, struct bio *bio)
+{
+	return unlikely((bio->bi_opf & REQ_SWAP) != 0) && unlikely(ti->limit_swap_bios);
+}
+
 static void clone_endio(struct bio *bio)
 {
 	blk_status_t error = bio->bi_status;
@@ -978,7 +986,7 @@
 	struct mapped_device *md = tio->io->md;
 	dm_endio_fn endio = tio->ti->type->end_io;
 
-	if (unlikely(error == BLK_STS_TARGET) && md->type != DM_TYPE_NVME_BIO_BASED) {
+	if (unlikely(error == BLK_STS_TARGET)) {
 		if (bio_op(bio) == REQ_OP_DISCARD &&
 		    !bio->bi_disk->queue->limits.max_discard_sectors)
 			disable_discard(md);
@@ -1007,6 +1015,11 @@
 		}
 	}
 
+	if (unlikely(swap_bios_limit(tio->ti, bio))) {
+		struct mapped_device *md = io->md;
+		up(&md->swap_bios_semaphore);
+	}
+
 	free_tio(tio);
 	dec_pending(io, error);
 }
@@ -1110,15 +1123,16 @@
 {
 	struct mapped_device *md = dax_get_private(dax_dev);
 	struct dm_table *map;
+	bool ret = false;
 	int srcu_idx;
-	bool ret;
 
 	map = dm_get_live_table(md, &srcu_idx);
 	if (!map)
-		return false;
+		goto out;
 
-	ret = dm_table_supports_dax(map, device_supports_dax, &blocksize);
+	ret = dm_table_supports_dax(map, device_not_dax_capable, &blocksize);
 
+out:
 	dm_put_live_table(md, srcu_idx);
 
 	return ret;
@@ -1260,6 +1274,22 @@
 }
 EXPORT_SYMBOL_GPL(dm_remap_zone_report);
 
+static noinline void __set_swap_bios_limit(struct mapped_device *md, int latch)
+{
+	mutex_lock(&md->swap_bios_lock);
+	while (latch < md->swap_bios) {
+		cond_resched();
+		down(&md->swap_bios_semaphore);
+		md->swap_bios--;
+	}
+	while (latch > md->swap_bios) {
+		cond_resched();
+		up(&md->swap_bios_semaphore);
+		md->swap_bios++;
+	}
+	mutex_unlock(&md->swap_bios_lock);
+}
+
 static blk_qc_t __map_bio(struct dm_target_io *tio)
 {
 	int r;
@@ -1280,6 +1310,13 @@
 	atomic_inc(&io->io_count);
 	sector = clone->bi_iter.bi_sector;
 
+	if (unlikely(swap_bios_limit(ti, clone))) {
+		int latch = get_swap_bios();
+		if (unlikely(latch != md->swap_bios))
+			__set_swap_bios_limit(md, latch);
+		down(&md->swap_bios_semaphore);
+	}
+
 	r = ti->type->map(ti, clone);
 	switch (r) {
 	case DM_MAPIO_SUBMITTED:
@@ -1288,16 +1325,17 @@
 		/* the bio has been remapped so dispatch it */
 		trace_block_bio_remap(clone->bi_disk->queue, clone,
 				      bio_dev(io->orig_bio), sector);
-		if (md->type == DM_TYPE_NVME_BIO_BASED)
-			ret = direct_make_request(clone);
-		else
-			ret = generic_make_request(clone);
+		ret = generic_make_request(clone);
 		break;
 	case DM_MAPIO_KILL:
+		if (unlikely(swap_bios_limit(ti, clone)))
+			up(&md->swap_bios_semaphore);
 		free_tio(tio);
 		dec_pending(io, BLK_STS_IOERR);
 		break;
 	case DM_MAPIO_REQUEUE:
+		if (unlikely(swap_bios_limit(ti, clone)))
+			up(&md->swap_bios_semaphore);
 		free_tio(tio);
 		dec_pending(io, BLK_STS_DM_REQUEUE);
 		break;
@@ -1436,9 +1474,6 @@
 	BUG_ON(bio_has_data(ci->bio));
 	while ((ti = dm_table_get_target(ci->map, target_nr++)))
 		__send_duplicate_bios(ci, ti, ti->num_flush_bios, NULL);
-
-	bio_disassociate_blkg(ci->bio);
-
 	return 0;
 }
 
@@ -1626,6 +1661,7 @@
 		ci.bio = &flush_bio;
 		ci.sector_count = 0;
 		error = __send_empty_flush(&ci);
+		bio_uninit(ci.bio);
 		/* dec_pending submits any data associated with flush */
 	} else if (bio_op(bio) == REQ_OP_ZONE_RESET) {
 		ci.bio = bio;
@@ -1674,67 +1710,6 @@
 	return ret;
 }
 
-/*
- * Optimized variant of __split_and_process_bio that leverages the
- * fact that targets that use it do _not_ have a need to split bios.
- */
-static blk_qc_t __process_bio(struct mapped_device *md, struct dm_table *map,
-			      struct bio *bio, struct dm_target *ti)
-{
-	struct clone_info ci;
-	blk_qc_t ret = BLK_QC_T_NONE;
-	int error = 0;
-
-	init_clone_info(&ci, md, map, bio);
-
-	if (bio->bi_opf & REQ_PREFLUSH) {
-		struct bio flush_bio;
-
-		/*
-		 * Use an on-stack bio for this, it's safe since we don't
-		 * need to reference it after submit. It's just used as
-		 * the basis for the clone(s).
-		 */
-		bio_init(&flush_bio, NULL, 0);
-		flush_bio.bi_opf = REQ_OP_WRITE | REQ_PREFLUSH | REQ_SYNC;
-		ci.bio = &flush_bio;
-		ci.sector_count = 0;
-		error = __send_empty_flush(&ci);
-		/* dec_pending submits any data associated with flush */
-	} else {
-		struct dm_target_io *tio;
-
-		ci.bio = bio;
-		ci.sector_count = bio_sectors(bio);
-		if (__process_abnormal_io(&ci, ti, &error))
-			goto out;
-
-		tio = alloc_tio(&ci, ti, 0, GFP_NOIO);
-		ret = __clone_and_map_simple_bio(&ci, tio, NULL);
-	}
-out:
-	/* drop the extra reference count */
-	dec_pending(ci.io, errno_to_blk_status(error));
-	return ret;
-}
-
-static void dm_queue_split(struct mapped_device *md, struct dm_target *ti, struct bio **bio)
-{
-	unsigned len, sector_count;
-
-	sector_count = bio_sectors(*bio);
-	len = min_t(sector_t, max_io_len((*bio)->bi_iter.bi_sector, ti), sector_count);
-
-	if (sector_count > len) {
-		struct bio *split = bio_split(*bio, len, GFP_NOIO, &md->queue->bio_split);
-
-		bio_chain(split, *bio);
-		trace_block_split(md->queue, split, (*bio)->bi_iter.bi_sector);
-		generic_make_request(*bio);
-		*bio = split;
-	}
-}
-
 static blk_qc_t dm_process_bio(struct mapped_device *md,
 			       struct dm_table *map, struct bio *bio)
 {
@@ -1760,15 +1735,12 @@
 	 * won't be imposed.
 	 */
 	if (current->bio_list) {
-		blk_queue_split(md->queue, &bio);
-		if (!is_abnormal_io(bio))
-			dm_queue_split(md, ti, &bio);
+		if (is_abnormal_io(bio))
+			blk_queue_split(md->queue, &bio);
+		/* regular IO is split by __split_and_process_bio */
 	}
 
-	if (dm_get_md_type(md) == DM_TYPE_NVME_BIO_BASED)
-		return __process_bio(md, map, bio, ti);
-	else
-		return __split_and_process_bio(md, map, bio);
+	return __split_and_process_bio(md, map, bio);
 }
 
 static blk_qc_t dm_make_request(struct request_queue *q, struct bio *bio)
@@ -1809,7 +1781,8 @@
 			 * With request-based DM we only need to check the
 			 * top-level queue for congestion.
 			 */
-			r = md->queue->backing_dev_info->wb.state & bdi_bits;
+			struct backing_dev_info *bdi = md->queue->backing_dev_info;
+			r = bdi->wb.congested->state & bdi_bits;
 		} else {
 			map = dm_get_live_table_fast(md);
 			if (map)
@@ -1875,14 +1848,6 @@
 
 static void dm_wq_work(struct work_struct *work);
 
-static void dm_init_normal_md_queue(struct mapped_device *md)
-{
-	/*
-	 * Initialize aspects of queue that aren't relevant for blk-mq
-	 */
-	md->queue->backing_dev_info->congested_fn = dm_any_congested;
-}
-
 static void cleanup_mapped_device(struct mapped_device *md)
 {
 	if (md->wq)
@@ -1917,6 +1882,7 @@
 	mutex_destroy(&md->suspend_lock);
 	mutex_destroy(&md->type_lock);
 	mutex_destroy(&md->table_devices_lock);
+	mutex_destroy(&md->swap_bios_lock);
 
 	dm_mq_cleanup_mapped_device(md);
 }
@@ -1970,7 +1936,12 @@
 	if (!md->queue)
 		goto bad;
 	md->queue->queuedata = md;
-	md->queue->backing_dev_info->congested_data = md;
+	/*
+	 * default to bio-based required ->make_request_fn until DM
+	 * table is loaded and md->type established. If request-based
+	 * table is loaded: blk-mq will override accordingly.
+	 */
+	blk_queue_make_request(md->queue, dm_make_request);
 
 	md->disk = alloc_disk_node(1, md->numa_node_id);
 	if (!md->disk)
@@ -1981,6 +1952,10 @@
 	init_waitqueue_head(&md->eventq);
 	init_completion(&md->kobj_holder.completion);
 
+	md->swap_bios = get_swap_bios();
+	sema_init(&md->swap_bios_semaphore, md->swap_bios);
+	mutex_init(&md->swap_bios_lock);
+
 	md->disk->major = _major;
 	md->disk->first_minor = minor;
 	md->disk->fops = &dm_blk_dops;
@@ -2006,7 +1981,9 @@
 	if (!md->bdev)
 		goto bad;
 
-	dm_stats_init(&md->stats);
+	r = dm_stats_init(&md->stats);
+	if (r < 0)
+		goto bad;
 
 	/* Populate the mapping, nobody knows we exist yet */
 	spin_lock(&_minor_lock);
@@ -2156,12 +2133,10 @@
 	if (request_based)
 		dm_stop_queue(q);
 
-	if (request_based || md->type == DM_TYPE_NVME_BIO_BASED) {
+	if (request_based) {
 		/*
-		 * Leverage the fact that request-based DM targets and
-		 * NVMe bio based targets are immutable singletons
-		 * - used to optimize both dm_request_fn and dm_mq_queue_rq;
-		 *   and __process_bio.
+		 * Leverage the fact that request-based DM targets are
+		 * immutable singletons - used to optimize dm_mq_queue_rq.
 		 */
 		md->immutable_target = dm_table_get_immutable_target(t);
 	}
@@ -2264,6 +2239,12 @@
 }
 EXPORT_SYMBOL_GPL(dm_get_queue_limits);
 
+static void dm_init_congested_fn(struct mapped_device *md)
+{
+	md->queue->backing_dev_info->congested_data = md;
+	md->queue->backing_dev_info->congested_fn = dm_any_congested;
+}
+
 /*
  * Setup the DM device's queue based on md's type
  */
@@ -2280,12 +2261,11 @@
 			DMERR("Cannot initialize queue for request-based dm-mq mapped device");
 			return r;
 		}
+		dm_init_congested_fn(md);
 		break;
 	case DM_TYPE_BIO_BASED:
 	case DM_TYPE_DAX_BIO_BASED:
-	case DM_TYPE_NVME_BIO_BASED:
-		dm_init_normal_md_queue(md);
-		blk_queue_make_request(md->queue, dm_make_request);
+		dm_init_congested_fn(md);
 		break;
 	case DM_TYPE_NONE:
 		WARN_ON_ONCE(true);
@@ -2384,6 +2364,8 @@
 	map = dm_get_live_table(md, &srcu_idx);
 	if (!dm_suspended_md(md)) {
 		dm_table_presuspend_targets(map);
+		set_bit(DMF_SUSPENDED, &md->flags);
+		set_bit(DMF_POST_SUSPENDING, &md->flags);
 		dm_table_postsuspend_targets(map);
 	}
 	/* dm_put_live_table must be before msleep, otherwise deadlock is possible */
@@ -2424,19 +2406,33 @@
 }
 EXPORT_SYMBOL_GPL(dm_put);
 
-static int dm_wait_for_completion(struct mapped_device *md, long task_state)
+static bool md_in_flight_bios(struct mapped_device *md)
+{
+	int cpu;
+	struct hd_struct *part = &dm_disk(md)->part0;
+	long sum = 0;
+
+	for_each_possible_cpu(cpu) {
+		sum += part_stat_local_read_cpu(part, in_flight[0], cpu);
+		sum += part_stat_local_read_cpu(part, in_flight[1], cpu);
+	}
+
+	return sum != 0;
+}
+
+static int dm_wait_for_bios_completion(struct mapped_device *md, long task_state)
 {
 	int r = 0;
 	DEFINE_WAIT(wait);
 
-	while (1) {
+	while (true) {
 		prepare_to_wait(&md->wait, &wait, task_state);
 
-		if (!md_in_flight(md))
+		if (!md_in_flight_bios(md))
 			break;
 
 		if (signal_pending_state(task_state, current)) {
-			r = -EINTR;
+			r = -ERESTARTSYS;
 			break;
 		}
 
@@ -2444,6 +2440,30 @@
 	}
 	finish_wait(&md->wait, &wait);
 
+	smp_rmb();
+
+	return r;
+}
+
+static int dm_wait_for_completion(struct mapped_device *md, long task_state)
+{
+	int r = 0;
+
+	if (!queue_is_mq(md->queue))
+		return dm_wait_for_bios_completion(md, task_state);
+
+	while (true) {
+		if (!blk_mq_queue_inflight(md->queue))
+			break;
+
+		if (signal_pending_state(task_state, current)) {
+			r = -ERESTARTSYS;
+			break;
+		}
+
+		msleep(5);
+	}
+
 	return r;
 }
 
@@ -2706,7 +2726,9 @@
 	if (r)
 		goto out_unlock;
 
+	set_bit(DMF_POST_SUSPENDING, &md->flags);
 	dm_table_postsuspend_targets(map);
+	clear_bit(DMF_POST_SUSPENDING, &md->flags);
 
 out_unlock:
 	mutex_unlock(&md->suspend_lock);
@@ -2803,11 +2825,16 @@
 	(void) __dm_suspend(md, map, suspend_flags, TASK_UNINTERRUPTIBLE,
 			    DMF_SUSPENDED_INTERNALLY);
 
+	set_bit(DMF_POST_SUSPENDING, &md->flags);
 	dm_table_postsuspend_targets(map);
+	clear_bit(DMF_POST_SUSPENDING, &md->flags);
 }
 
 static void __dm_internal_resume(struct mapped_device *md)
 {
+	int r;
+	struct dm_table *map;
+
 	BUG_ON(!md->internal_suspend_count);
 
 	if (--md->internal_suspend_count)
@@ -2816,12 +2843,23 @@
 	if (dm_suspended_md(md))
 		goto done; /* resume from nested suspend */
 
-	/*
-	 * NOTE: existing callers don't need to call dm_table_resume_targets
-	 * (which may fail -- so best to avoid it for now by passing NULL map)
-	 */
-	(void) __dm_resume(md, NULL);
-
+	map = rcu_dereference_protected(md->map, lockdep_is_held(&md->suspend_lock));
+	r = __dm_resume(md, map);
+	if (r) {
+		/*
+		 * If a preresume method of some target failed, we are in a
+		 * tricky situation. We can't return an error to the caller. We
+		 * can't fake success because then the "resume" and
+		 * "postsuspend" methods would not be paired correctly, and it
+		 * would break various targets, for example it would cause list
+		 * corruption in the "origin" target.
+		 *
+		 * So, we fake normal suspend here, to make sure that the
+		 * "resume" and "postsuspend" methods will be paired correctly.
+		 */
+		DMERR("Preresume method failed: %d", r);
+		set_bit(DMF_SUSPENDED, &md->flags);
+	}
 done:
 	clear_bit(DMF_SUSPENDED_INTERNALLY, &md->flags);
 	smp_mb__after_atomic();
@@ -2880,17 +2918,25 @@
 int dm_kobject_uevent(struct mapped_device *md, enum kobject_action action,
 		       unsigned cookie)
 {
+	int r;
+	unsigned noio_flag;
 	char udev_cookie[DM_COOKIE_LENGTH];
 	char *envp[] = { udev_cookie, NULL };
 
+	noio_flag = memalloc_noio_save();
+
 	if (!cookie)
-		return kobject_uevent(&disk_to_dev(md->disk)->kobj, action);
+		r = kobject_uevent(&disk_to_dev(md->disk)->kobj, action);
 	else {
 		snprintf(udev_cookie, DM_COOKIE_LENGTH, "%s=%u",
 			 DM_COOKIE_ENV_VAR_NAME, cookie);
-		return kobject_uevent_env(&disk_to_dev(md->disk)->kobj,
-					  action, envp);
+		r = kobject_uevent_env(&disk_to_dev(md->disk)->kobj,
+				       action, envp);
 	}
+
+	memalloc_noio_restore(noio_flag);
+
+	return r;
 }
 
 uint32_t dm_next_uevent_seq(struct mapped_device *md)
@@ -2956,6 +3002,11 @@
 	return test_bit(DMF_SUSPENDED, &md->flags);
 }
 
+static int dm_post_suspending_md(struct mapped_device *md)
+{
+	return test_bit(DMF_POST_SUSPENDING, &md->flags);
+}
+
 int dm_suspended_internally_md(struct mapped_device *md)
 {
 	return test_bit(DMF_SUSPENDED_INTERNALLY, &md->flags);
@@ -2972,6 +3023,12 @@
 }
 EXPORT_SYMBOL_GPL(dm_suspended);
 
+int dm_post_suspending(struct dm_target *ti)
+{
+	return dm_post_suspending_md(dm_table_get_md(ti->table));
+}
+EXPORT_SYMBOL_GPL(dm_post_suspending);
+
 int dm_noflush_suspending(struct dm_target *ti)
 {
 	return __noflush_suspending(dm_table_get_md(ti->table));
@@ -2993,7 +3050,6 @@
 	switch (type) {
 	case DM_TYPE_BIO_BASED:
 	case DM_TYPE_DAX_BIO_BASED:
-	case DM_TYPE_NVME_BIO_BASED:
 		pool_size = max(dm_get_reserved_bio_based_ios(), min_pool_size);
 		front_pad = roundup(per_io_data_size, __alignof__(struct dm_target_io)) + offsetof(struct dm_target_io, clone);
 		io_front_pad = roundup(front_pad,  __alignof__(struct dm_io)) + offsetof(struct dm_io, tio);
@@ -3062,6 +3118,11 @@
 		goto out;
 	ti = dm_table_get_target(table, 0);
 
+	if (dm_suspended_md(md)) {
+		ret = -EAGAIN;
+		goto out;
+	}
+
 	ret = -EINVAL;
 	if (!ti->type->iterate_devices)
 		goto out;
@@ -3232,6 +3293,9 @@
 module_param(dm_numa_node, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(dm_numa_node, "NUMA node for DM device memory allocations");
 
+module_param(swap_bios, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(swap_bios, "Maximum allowed inflight swap IOs");
+
 MODULE_DESCRIPTION(DM_NAME " driver");
 MODULE_AUTHOR("Joe Thornber <dm-devel@redhat.com>");
 MODULE_LICENSE("GPL");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/dm.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/dm.h
@@ -74,7 +74,7 @@
 struct dm_md_mempools *dm_table_get_md_mempools(struct dm_table *t);
 bool dm_table_supports_dax(struct dm_table *t, iterate_devices_callout_fn fn,
 			   int *blocksize);
-int device_supports_dax(struct dm_target *ti, struct dm_dev *dev,
+int device_not_dax_capable(struct dm_target *ti, struct dm_dev *dev,
 			   sector_t start, sector_t len, void *data);
 
 void dm_lock_md_type(struct mapped_device *md);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/md-bitmap.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/md-bitmap.c
@@ -54,14 +54,7 @@
 {
 	unsigned char *mappage;
 
-	if (page >= bitmap->pages) {
-		/* This can happen if bitmap_start_sync goes beyond
-		 * End-of-device while looking for a whole page.
-		 * It is harmless.
-		 */
-		return -EINVAL;
-	}
-
+	WARN_ON_ONCE(page >= bitmap->pages);
 	if (bitmap->bp[page].hijacked) /* it's hijacked, don't try to alloc */
 		return 0;
 
@@ -489,7 +482,7 @@
 	sb = kmap_atomic(bitmap->storage.sb_page);
 	pr_debug("%s: bitmap file superblock:\n", bmname(bitmap));
 	pr_debug("         magic: %08x\n", le32_to_cpu(sb->magic));
-	pr_debug("       version: %d\n", le32_to_cpu(sb->version));
+	pr_debug("       version: %u\n", le32_to_cpu(sb->version));
 	pr_debug("          uuid: %08x.%08x.%08x.%08x\n",
 		 le32_to_cpu(*(__le32 *)(sb->uuid+0)),
 		 le32_to_cpu(*(__le32 *)(sb->uuid+4)),
@@ -500,11 +493,11 @@
 	pr_debug("events cleared: %llu\n",
 		 (unsigned long long) le64_to_cpu(sb->events_cleared));
 	pr_debug("         state: %08x\n", le32_to_cpu(sb->state));
-	pr_debug("     chunksize: %d B\n", le32_to_cpu(sb->chunksize));
-	pr_debug("  daemon sleep: %ds\n", le32_to_cpu(sb->daemon_sleep));
+	pr_debug("     chunksize: %u B\n", le32_to_cpu(sb->chunksize));
+	pr_debug("  daemon sleep: %us\n", le32_to_cpu(sb->daemon_sleep));
 	pr_debug("     sync size: %llu KB\n",
 		 (unsigned long long)le64_to_cpu(sb->sync_size)/2);
-	pr_debug("max write behind: %d\n", le32_to_cpu(sb->write_behind));
+	pr_debug("max write behind: %u\n", le32_to_cpu(sb->write_behind));
 	kunmap_atomic(sb);
 }
 
@@ -642,14 +635,6 @@
 	daemon_sleep = le32_to_cpu(sb->daemon_sleep) * HZ;
 	write_behind = le32_to_cpu(sb->write_behind);
 	sectors_reserved = le32_to_cpu(sb->sectors_reserved);
-	/* Setup nodes/clustername only if bitmap version is
-	 * cluster-compatible
-	 */
-	if (sb->version == cpu_to_le32(BITMAP_MAJOR_CLUSTERED)) {
-		nodes = le32_to_cpu(sb->nodes);
-		strlcpy(bitmap->mddev->bitmap_info.cluster_name,
-				sb->cluster_name, 64);
-	}
 
 	/* verify that the bitmap-specific fields are valid */
 	if (sb->magic != cpu_to_le32(BITMAP_MAGIC))
@@ -671,6 +656,16 @@
 		goto out;
 	}
 
+	/*
+	 * Setup nodes/clustername only if bitmap version is
+	 * cluster-compatible
+	 */
+	if (sb->version == cpu_to_le32(BITMAP_MAJOR_CLUSTERED)) {
+		nodes = le32_to_cpu(sb->nodes);
+		strlcpy(bitmap->mddev->bitmap_info.cluster_name,
+				sb->cluster_name, 64);
+	}
+
 	/* keep the array size field of the bitmap superblock up to date */
 	sb->sync_size = cpu_to_le64(bitmap->mddev->resync_max_sectors);
 
@@ -703,9 +698,9 @@
 
 out:
 	kunmap_atomic(sb);
-	/* Assigning chunksize is required for "re_read" */
-	bitmap->mddev->bitmap_info.chunksize = chunksize;
 	if (err == 0 && nodes && (bitmap->cluster_slot < 0)) {
+		/* Assigning chunksize is required for "re_read" */
+		bitmap->mddev->bitmap_info.chunksize = chunksize;
 		err = md_setup_cluster(bitmap->mddev, nodes);
 		if (err) {
 			pr_warn("%s: Could not setup cluster service (%d)\n",
@@ -716,18 +711,18 @@
 		goto re_read;
 	}
 
-
 out_no_sb:
-	if (test_bit(BITMAP_STALE, &bitmap->flags))
-		bitmap->events_cleared = bitmap->mddev->events;
-	bitmap->mddev->bitmap_info.chunksize = chunksize;
-	bitmap->mddev->bitmap_info.daemon_sleep = daemon_sleep;
-	bitmap->mddev->bitmap_info.max_write_behind = write_behind;
-	bitmap->mddev->bitmap_info.nodes = nodes;
-	if (bitmap->mddev->bitmap_info.space == 0 ||
-	    bitmap->mddev->bitmap_info.space > sectors_reserved)
-		bitmap->mddev->bitmap_info.space = sectors_reserved;
-	if (err) {
+	if (err == 0) {
+		if (test_bit(BITMAP_STALE, &bitmap->flags))
+			bitmap->events_cleared = bitmap->mddev->events;
+		bitmap->mddev->bitmap_info.chunksize = chunksize;
+		bitmap->mddev->bitmap_info.daemon_sleep = daemon_sleep;
+		bitmap->mddev->bitmap_info.max_write_behind = write_behind;
+		bitmap->mddev->bitmap_info.nodes = nodes;
+		if (bitmap->mddev->bitmap_info.space == 0 ||
+			bitmap->mddev->bitmap_info.space > sectors_reserved)
+			bitmap->mddev->bitmap_info.space = sectors_reserved;
+	} else {
 		md_bitmap_print_sb(bitmap);
 		if (bitmap->cluster_slot < 0)
 			md_cluster_stop(bitmap->mddev);
@@ -1364,17 +1359,25 @@
 	sector_t chunk = offset >> bitmap->chunkshift;
 	unsigned long page = chunk >> PAGE_COUNTER_SHIFT;
 	unsigned long pageoff = (chunk & PAGE_COUNTER_MASK) << COUNTER_BYTE_SHIFT;
-	sector_t csize;
+	sector_t csize = ((sector_t)1) << bitmap->chunkshift;
 	int err;
 
+	if (page >= bitmap->pages) {
+		/*
+		 * This can happen if bitmap_start_sync goes beyond
+		 * End-of-device while looking for a whole page or
+		 * user set a huge number to sysfs bitmap_set_bits.
+		 */
+		*blocks = csize - (offset & (csize - 1));
+		return NULL;
+	}
 	err = md_bitmap_checkpage(bitmap, page, create, 0);
 
 	if (bitmap->bp[page].hijacked ||
 	    bitmap->bp[page].map == NULL)
 		csize = ((sector_t)1) << (bitmap->chunkshift +
-					  PAGE_COUNTER_SHIFT - 1);
-	else
-		csize = ((sector_t)1) << bitmap->chunkshift;
+					  PAGE_COUNTER_SHIFT);
+
 	*blocks = csize - (offset & (csize - 1));
 
 	if (err < 0)
@@ -1726,6 +1729,8 @@
 	md_bitmap_daemon_work(mddev);
 	bitmap->daemon_lastrun -= sleep;
 	md_bitmap_daemon_work(mddev);
+	if (mddev->bitmap_info.external)
+		md_super_wait(mddev);
 	md_bitmap_update_sb(bitmap);
 }
 
@@ -1954,6 +1959,7 @@
 }
 EXPORT_SYMBOL_GPL(md_bitmap_load);
 
+/* caller need to free returned bitmap with md_bitmap_free() */
 struct bitmap *get_bitmap_from_slot(struct mddev *mddev, int slot)
 {
 	int rv = 0;
@@ -2017,6 +2023,7 @@
 	md_bitmap_unplug(mddev->bitmap);
 	*low = lo;
 	*high = hi;
+	md_bitmap_free(bitmap);
 
 	return rv;
 }
@@ -2104,7 +2111,8 @@
 			bytes = DIV_ROUND_UP(chunks, 8);
 			if (!bitmap->mddev->bitmap_info.external)
 				bytes += sizeof(bitmap_super_t);
-		} while (bytes > (space << 9));
+		} while (bytes > (space << 9) && (chunkshift + BITMAP_BLOCK_SHIFT) <
+			(BITS_PER_BYTE * sizeof(((bitmap_super_t *)0)->chunksize) - 1));
 	} else
 		chunkshift = ffz(~chunksize) - BITMAP_BLOCK_SHIFT;
 
@@ -2139,6 +2147,7 @@
 		memcpy(page_address(store.sb_page),
 		       page_address(bitmap->storage.sb_page),
 		       sizeof(bitmap_super_t));
+	spin_lock_irq(&bitmap->counts.lock);
 	md_bitmap_file_unmap(&bitmap->storage);
 	bitmap->storage = store;
 
@@ -2148,13 +2157,12 @@
 	bitmap->counts.missing_pages = pages;
 	bitmap->counts.chunkshift = chunkshift;
 	bitmap->counts.chunks = chunks;
-	bitmap->mddev->bitmap_info.chunksize = 1 << (chunkshift +
+	bitmap->mddev->bitmap_info.chunksize = 1UL << (chunkshift +
 						     BITMAP_BLOCK_SHIFT);
 
 	blocks = min(old_counts.chunks << old_counts.chunkshift,
 		     chunks << chunkshift);
 
-	spin_lock_irq(&bitmap->counts.lock);
 	/* For cluster raid, need to pre-allocate bitmap */
 	if (mddev_is_clustered(bitmap->mddev)) {
 		unsigned long page;
@@ -2175,8 +2183,8 @@
 				bitmap->counts.missing_pages = old_counts.pages;
 				bitmap->counts.chunkshift = old_counts.chunkshift;
 				bitmap->counts.chunks = old_counts.chunks;
-				bitmap->mddev->bitmap_info.chunksize = 1 << (old_counts.chunkshift +
-									     BITMAP_BLOCK_SHIFT);
+				bitmap->mddev->bitmap_info.chunksize =
+					1UL << (old_counts.chunkshift + BITMAP_BLOCK_SHIFT);
 				blocks = old_counts.chunks << old_counts.chunkshift;
 				pr_warn("Could not pre-allocate in-memory bitmap for cluster raid\n");
 				break;
@@ -2194,20 +2202,23 @@
 
 		if (set) {
 			bmc_new = md_bitmap_get_counter(&bitmap->counts, block, &new_blocks, 1);
-			if (*bmc_new == 0) {
-				/* need to set on-disk bits too. */
-				sector_t end = block + new_blocks;
-				sector_t start = block >> chunkshift;
-				start <<= chunkshift;
-				while (start < end) {
-					md_bitmap_file_set_bit(bitmap, block);
-					start += 1 << chunkshift;
+			if (bmc_new) {
+				if (*bmc_new == 0) {
+					/* need to set on-disk bits too. */
+					sector_t end = block + new_blocks;
+					sector_t start = block >> chunkshift;
+
+					start <<= chunkshift;
+					while (start < end) {
+						md_bitmap_file_set_bit(bitmap, block);
+						start += 1 << chunkshift;
+					}
+					*bmc_new = 2;
+					md_bitmap_count_page(&bitmap->counts, block, 1);
+					md_bitmap_set_pending(&bitmap->counts, block);
 				}
-				*bmc_new = 2;
-				md_bitmap_count_page(&bitmap->counts, block, 1);
-				md_bitmap_set_pending(&bitmap->counts, block);
+				*bmc_new |= NEEDED_MASK;
 			}
-			*bmc_new |= NEEDED_MASK;
 			if (new_blocks < old_blocks)
 				old_blocks = new_blocks;
 		}
@@ -2469,11 +2480,35 @@
 {
 	unsigned long backlog;
 	unsigned long old_mwb = mddev->bitmap_info.max_write_behind;
+	struct md_rdev *rdev;
+	bool has_write_mostly = false;
 	int rv = kstrtoul(buf, 10, &backlog);
 	if (rv)
 		return rv;
 	if (backlog > COUNTER_MAX)
 		return -EINVAL;
+
+	rv = mddev_lock(mddev);
+	if (rv)
+		return rv;
+
+	/*
+	 * Without write mostly device, it doesn't make sense to set
+	 * backlog for max_write_behind.
+	 */
+	rdev_for_each(rdev, mddev) {
+		if (test_bit(WriteMostly, &rdev->flags)) {
+			has_write_mostly = true;
+			break;
+		}
+	}
+	if (!has_write_mostly) {
+		pr_warn_ratelimited("%s: can't set backlog, no write mostly device available\n",
+				    mdname(mddev));
+		mddev_unlock(mddev);
+		return -EINVAL;
+	}
+
 	mddev->bitmap_info.max_write_behind = backlog;
 	if (!backlog && mddev->wb_info_pool) {
 		/* wb_info_pool is not needed if backlog is zero */
@@ -2488,6 +2523,8 @@
 	}
 	if (old_mwb != backlog)
 		md_bitmap_update_sb(mddev->bitmap);
+
+	mddev_unlock(mddev);
 	return len;
 }
 
@@ -2514,6 +2551,9 @@
 	if (csize < 512 ||
 	    !is_power_of_2(csize))
 		return -EINVAL;
+	if (BITS_PER_LONG > 32 && csize >= (1ULL << (BITS_PER_BYTE *
+		sizeof(((bitmap_super_t *)0)->chunksize))))
+		return -EOVERFLOW;
 	mddev->bitmap_info.chunksize = csize;
 	return len;
 }
@@ -2620,4 +2660,3 @@
 	.name = "bitmap",
 	.attrs = md_bitmap_attrs,
 };
-
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/md-cluster.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/md-cluster.c
@@ -664,9 +664,27 @@
  * Takes the lock on the TOKEN lock resource so no other
  * node can communicate while the operation is underway.
  */
-static int lock_token(struct md_cluster_info *cinfo, bool mddev_locked)
+static int lock_token(struct md_cluster_info *cinfo)
 {
-	int error, set_bit = 0;
+	int error;
+
+	error = dlm_lock_sync(cinfo->token_lockres, DLM_LOCK_EX);
+	if (error) {
+		pr_err("md-cluster(%s:%d): failed to get EX on TOKEN (%d)\n",
+				__func__, __LINE__, error);
+	} else {
+		/* Lock the receive sequence */
+		mutex_lock(&cinfo->recv_mutex);
+	}
+	return error;
+}
+
+/* lock_comm()
+ * Sets the MD_CLUSTER_SEND_LOCK bit to lock the send channel.
+ */
+static int lock_comm(struct md_cluster_info *cinfo, bool mddev_locked)
+{
+	int rv, set_bit = 0;
 	struct mddev *mddev = cinfo->mddev;
 
 	/*
@@ -677,34 +695,19 @@
 	 */
 	if (mddev_locked && !test_bit(MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD,
 				      &cinfo->state)) {
-		error = test_and_set_bit_lock(MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD,
+		rv = test_and_set_bit_lock(MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD,
 					      &cinfo->state);
-		WARN_ON_ONCE(error);
+		WARN_ON_ONCE(rv);
 		md_wakeup_thread(mddev->thread);
 		set_bit = 1;
 	}
-	error = dlm_lock_sync(cinfo->token_lockres, DLM_LOCK_EX);
-	if (set_bit)
-		clear_bit_unlock(MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD, &cinfo->state);
 
-	if (error)
-		pr_err("md-cluster(%s:%d): failed to get EX on TOKEN (%d)\n",
-				__func__, __LINE__, error);
-
-	/* Lock the receive sequence */
-	mutex_lock(&cinfo->recv_mutex);
-	return error;
-}
-
-/* lock_comm()
- * Sets the MD_CLUSTER_SEND_LOCK bit to lock the send channel.
- */
-static int lock_comm(struct md_cluster_info *cinfo, bool mddev_locked)
-{
 	wait_event(cinfo->wait,
 		   !test_and_set_bit(MD_CLUSTER_SEND_LOCK, &cinfo->state));
-
-	return lock_token(cinfo, mddev_locked);
+	rv = lock_token(cinfo);
+	if (set_bit)
+		clear_bit_unlock(MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD, &cinfo->state);
+	return rv;
 }
 
 static void unlock_comm(struct md_cluster_info *cinfo)
@@ -784,9 +787,11 @@
 {
 	int ret;
 
-	lock_comm(cinfo, mddev_locked);
-	ret = __sendmsg(cinfo, cmsg);
-	unlock_comm(cinfo);
+	ret = lock_comm(cinfo, mddev_locked);
+	if (!ret) {
+		ret = __sendmsg(cinfo, cmsg);
+		unlock_comm(cinfo);
+	}
 	return ret;
 }
 
@@ -1061,7 +1066,7 @@
 		return 0;
 	}
 
-	ret = lock_token(cinfo, 1);
+	ret = lock_token(cinfo);
 	clear_bit_unlock(MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD, &cinfo->state);
 	return ret;
 }
@@ -1139,6 +1144,7 @@
 		bitmap = get_bitmap_from_slot(mddev, i);
 		if (IS_ERR(bitmap)) {
 			pr_err("can't get bitmap from slot %d\n", i);
+			bitmap = NULL;
 			goto out;
 		}
 		counts = &bitmap->counts;
@@ -1165,6 +1171,7 @@
 			 * can't resize bitmap
 			 */
 			goto out;
+		md_bitmap_free(bitmap);
 	}
 
 	return 0;
@@ -1253,7 +1260,10 @@
 	int raid_slot = -1;
 
 	md_update_sb(mddev, 1);
-	lock_comm(cinfo, 1);
+	if (lock_comm(cinfo, 1)) {
+		pr_err("%s: lock_comm failed\n", __func__);
+		return;
+	}
 
 	memset(&cmsg, 0, sizeof(cmsg));
 	cmsg.type = cpu_to_le32(METADATA_UPDATED);
@@ -1405,7 +1415,8 @@
 	cmsg.type = cpu_to_le32(NEWDISK);
 	memcpy(cmsg.uuid, uuid, 16);
 	cmsg.raid_slot = cpu_to_le32(rdev->desc_nr);
-	lock_comm(cinfo, 1);
+	if (lock_comm(cinfo, 1))
+		return -EAGAIN;
 	ret = __sendmsg(cinfo, &cmsg);
 	if (ret) {
 		unlock_comm(cinfo);
@@ -1518,6 +1529,7 @@
 			}
 		}
 		kfree(cinfo->other_bitmap_lockres);
+		cinfo->other_bitmap_lockres = NULL;
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/md-linear.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/md-linear.c
@@ -244,10 +244,9 @@
 	sector_t start_sector, end_sector, data_offset;
 	sector_t bio_sector = bio->bi_iter.bi_sector;
 
-	if (unlikely(bio->bi_opf & REQ_PREFLUSH)) {
-		md_flush_request(mddev, bio);
+	if (unlikely(bio->bi_opf & REQ_PREFLUSH)
+	    && md_flush_request(mddev, bio))
 		return true;
-	}
 
 	tmp_dev = which_dev(mddev, bio_sector);
 	start_sector = tmp_dev->end_sector - tmp_dev->rdev->sectors;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/md-multipath.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/md-multipath.c
@@ -104,10 +104,9 @@
 	struct multipath_bh * mp_bh;
 	struct multipath_info *multipath;
 
-	if (unlikely(bio->bi_opf & REQ_PREFLUSH)) {
-		md_flush_request(mddev, bio);
+	if (unlikely(bio->bi_opf & REQ_PREFLUSH)
+	    && md_flush_request(mddev, bio))
 		return true;
-	}
 
 	mp_bh = mempool_alloc(&conf->pool, GFP_NOIO);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/md.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/md.c
@@ -376,17 +376,18 @@
 	struct mddev *mddev = q->queuedata;
 	unsigned int sectors;
 
-	if (unlikely(test_bit(MD_BROKEN, &mddev->flags)) && (rw == WRITE)) {
+	if (mddev == NULL || mddev->pers == NULL) {
 		bio_io_error(bio);
 		return BLK_QC_T_NONE;
 	}
 
-	blk_queue_split(q, &bio);
-
-	if (mddev == NULL || mddev->pers == NULL) {
+	if (unlikely(test_bit(MD_BROKEN, &mddev->flags)) && (rw == WRITE)) {
 		bio_io_error(bio);
 		return BLK_QC_T_NONE;
 	}
+
+	blk_queue_split(q, &bio);
+
 	if (mddev->ro == 1 && unlikely(rw == WRITE)) {
 		if (bio_sectors(bio) != 0)
 			bio->bi_status = BLK_STS_IOERR;
@@ -480,13 +481,14 @@
 	struct md_rdev *rdev = bio->bi_private;
 	struct mddev *mddev = rdev->mddev;
 
+	bio_put(bio);
+
 	rdev_dec_pending(rdev, mddev);
 
 	if (atomic_dec_and_test(&mddev->flush_pending)) {
 		/* The pre-request flush has finished */
 		queue_work(md_wq, &mddev->flush_work);
 	}
-	bio_put(bio);
 }
 
 static void md_submit_flush_data(struct work_struct *ws);
@@ -537,8 +539,10 @@
 	 * could wait for this and below md_handle_request could wait for those
 	 * bios because of suspend check
 	 */
+	spin_lock_irq(&mddev->lock);
 	mddev->last_flush = mddev->start_flush;
 	mddev->flush_bio = NULL;
+	spin_unlock_irq(&mddev->lock);
 	wake_up(&mddev->sb_wait);
 
 	if (bio->bi_iter.bi_size == 0) {
@@ -550,7 +554,13 @@
 	}
 }
 
-void md_flush_request(struct mddev *mddev, struct bio *bio)
+/*
+ * Manages consolidation of flushes and submitting any flushes needed for
+ * a bio with REQ_PREFLUSH.  Returns true if the bio is finished or is
+ * being finished in another context.  Returns false if the flushing is
+ * complete but still needs the I/O portion of the bio to be processed.
+ */
+bool md_flush_request(struct mddev *mddev, struct bio *bio)
 {
 	ktime_t start = ktime_get_boottime();
 	spin_lock_irq(&mddev->lock);
@@ -575,9 +585,10 @@
 			bio_endio(bio);
 		else {
 			bio->bi_opf &= ~REQ_PREFLUSH;
-			mddev->pers->make_request(mddev, bio);
+			return false;
 		}
 	}
+	return true;
 }
 EXPORT_SYMBOL(md_flush_request);
 
@@ -637,8 +648,35 @@
 }
 EXPORT_SYMBOL_GPL(mddev_init);
 
+static struct mddev *mddev_find_locked(dev_t unit)
+{
+	struct mddev *mddev;
+
+	list_for_each_entry(mddev, &all_mddevs, all_mddevs)
+		if (mddev->unit == unit)
+			return mddev;
+
+	return NULL;
+}
+
 static struct mddev *mddev_find(dev_t unit)
 {
+	struct mddev *mddev;
+
+	if (MAJOR(unit) != MD_MAJOR)
+		unit &= ~((1 << MdpMinorShift) - 1);
+
+	spin_lock(&all_mddevs_lock);
+	mddev = mddev_find_locked(unit);
+	if (mddev)
+		mddev_get(mddev);
+	spin_unlock(&all_mddevs_lock);
+
+	return mddev;
+}
+
+static struct mddev *mddev_find_or_alloc(dev_t unit)
+{
 	struct mddev *mddev, *new = NULL;
 
 	if (unit && MAJOR(unit) != MD_MAJOR)
@@ -648,13 +686,13 @@
 	spin_lock(&all_mddevs_lock);
 
 	if (unit) {
-		list_for_each_entry(mddev, &all_mddevs, all_mddevs)
-			if (mddev->unit == unit) {
-				mddev_get(mddev);
-				spin_unlock(&all_mddevs_lock);
-				kfree(new);
-				return mddev;
-			}
+		mddev = mddev_find_locked(unit);
+		if (mddev) {
+			mddev_get(mddev);
+			spin_unlock(&all_mddevs_lock);
+			kfree(new);
+			return mddev;
+		}
 
 		if (new) {
 			list_add(&new->all_mddevs, &all_mddevs);
@@ -680,12 +718,7 @@
 				return NULL;
 			}
 
-			is_free = 1;
-			list_for_each_entry(mddev, &all_mddevs, all_mddevs)
-				if (mddev->unit == dev) {
-					is_free = 0;
-					break;
-				}
+			is_free = !mddev_find_locked(dev);
 		}
 		new->unit = dev;
 		new->md_minor = MINOR(dev);
@@ -853,10 +886,12 @@
 	} else
 		clear_bit(LastDev, &rdev->flags);
 
+	bio_put(bio);
+
+	rdev_dec_pending(rdev, mddev);
+
 	if (atomic_dec_and_test(&mddev->pending_writes))
 		wake_up(&mddev->sb_wait);
-	rdev_dec_pending(rdev, mddev);
-	bio_put(bio);
 }
 
 void md_super_write(struct mddev *mddev, struct md_rdev *rdev,
@@ -1063,6 +1098,7 @@
 					  struct md_rdev *refdev,
 					  int minor_version);
 	int		    (*validate_super)(struct mddev *mddev,
+					      struct md_rdev *freshest,
 					      struct md_rdev *rdev);
 	void		    (*sync_super)(struct mddev *mddev,
 					  struct md_rdev *rdev);
@@ -1098,6 +1134,7 @@
 	char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
 	mdp_super_t *sb;
 	int ret;
+	bool spare_disk = true;
 
 	/*
 	 * Calculate the position of the superblock (512byte sectors),
@@ -1148,8 +1185,19 @@
 	else
 		rdev->desc_nr = sb->this_disk.number;
 
+	/* not spare disk, or LEVEL_MULTIPATH */
+	if (sb->level == LEVEL_MULTIPATH ||
+		(rdev->desc_nr >= 0 &&
+		 rdev->desc_nr < MD_SB_DISKS &&
+		 sb->disks[rdev->desc_nr].state &
+		 ((1<<MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE))))
+		spare_disk = false;
+
 	if (!refdev) {
-		ret = 1;
+		if (!spare_disk)
+			ret = 1;
+		else
+			ret = 0;
 	} else {
 		__u64 ev1, ev2;
 		mdp_super_t *refsb = page_address(refdev->sb_page);
@@ -1165,7 +1213,8 @@
 		}
 		ev1 = md_event(sb);
 		ev2 = md_event(refsb);
-		if (ev1 > ev2)
+
+		if (!spare_disk && ev1 > ev2)
 			ret = 1;
 		else
 			ret = 0;
@@ -1188,8 +1237,9 @@
 
 /*
  * validate_super for 0.90.0
+ * note: we are not using "freshest" for 0.9 superblock
  */
-static int super_90_validate(struct mddev *mddev, struct md_rdev *rdev)
+static int super_90_validate(struct mddev *mddev, struct md_rdev *freshest, struct md_rdev *rdev)
 {
 	mdp_disk_t *desc;
 	mdp_super_t *sb = page_address(rdev->sb_page);
@@ -1525,6 +1575,7 @@
 	sector_t sectors;
 	char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
 	int bmask;
+	bool spare_disk = true;
 
 	/*
 	 * Calculate the position of the superblock in 512byte sectors.
@@ -1658,8 +1709,19 @@
 	    sb->level != 0)
 		return -EINVAL;
 
+	/* not spare disk, or LEVEL_MULTIPATH */
+	if (sb->level == cpu_to_le32(LEVEL_MULTIPATH) ||
+		(rdev->desc_nr >= 0 &&
+		rdev->desc_nr < le32_to_cpu(sb->max_dev) &&
+		(le16_to_cpu(sb->dev_roles[rdev->desc_nr]) < MD_DISK_ROLE_MAX ||
+		 le16_to_cpu(sb->dev_roles[rdev->desc_nr]) == MD_DISK_ROLE_JOURNAL)))
+		spare_disk = false;
+
 	if (!refdev) {
-		ret = 1;
+		if (!spare_disk)
+			ret = 1;
+		else
+			ret = 0;
 	} else {
 		__u64 ev1, ev2;
 		struct mdp_superblock_1 *refsb = page_address(refdev->sb_page);
@@ -1676,7 +1738,7 @@
 		ev1 = le64_to_cpu(sb->events);
 		ev2 = le64_to_cpu(refsb->events);
 
-		if (ev1 > ev2)
+		if (!spare_disk && ev1 > ev2)
 			ret = 1;
 		else
 			ret = 0;
@@ -1692,7 +1754,7 @@
 	return ret;
 }
 
-static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev)
+static int super_1_validate(struct mddev *mddev, struct md_rdev *freshest, struct md_rdev *rdev)
 {
 	struct mdp_superblock_1 *sb = page_address(rdev->sb_page);
 	__u64 ev1 = le64_to_cpu(sb->events);
@@ -1788,13 +1850,15 @@
 		}
 	} else if (mddev->pers == NULL) {
 		/* Insist of good event counter while assembling, except for
-		 * spares (which don't need an event count) */
-		++ev1;
+		 * spares (which don't need an event count).
+		 * Similar to mdadm, we allow event counter difference of 1
+		 * from the freshest device.
+		 */
 		if (rdev->desc_nr >= 0 &&
 		    rdev->desc_nr < le32_to_cpu(sb->max_dev) &&
 		    (le16_to_cpu(sb->dev_roles[rdev->desc_nr]) < MD_DISK_ROLE_MAX ||
 		     le16_to_cpu(sb->dev_roles[rdev->desc_nr]) == MD_DISK_ROLE_JOURNAL))
-			if (ev1 < mddev->events)
+			if (ev1 + 1 < mddev->events)
 				return -EINVAL;
 	} else if (mddev->bitmap) {
 		/* If adding to array with a bitmap, then we can accept an
@@ -1815,8 +1879,38 @@
 		    rdev->desc_nr >= le32_to_cpu(sb->max_dev)) {
 			role = MD_DISK_ROLE_SPARE;
 			rdev->desc_nr = -1;
-		} else
+		} else if (mddev->pers == NULL && freshest && ev1 < mddev->events) {
+			/*
+			 * If we are assembling, and our event counter is smaller than the
+			 * highest event counter, we cannot trust our superblock about the role.
+			 * It could happen that our rdev was marked as Faulty, and all other
+			 * superblocks were updated with +1 event counter.
+			 * Then, before the next superblock update, which typically happens when
+			 * remove_and_add_spares() removes the device from the array, there was
+			 * a crash or reboot.
+			 * If we allow current rdev without consulting the freshest superblock,
+			 * we could cause data corruption.
+			 * Note that in this case our event counter is smaller by 1 than the
+			 * highest, otherwise, this rdev would not be allowed into array;
+			 * both kernel and mdadm allow event counter difference of 1.
+			 */
+			struct mdp_superblock_1 *freshest_sb = page_address(freshest->sb_page);
+			u32 freshest_max_dev = le32_to_cpu(freshest_sb->max_dev);
+
+			if (rdev->desc_nr >= freshest_max_dev) {
+				/* this is unexpected, better not proceed */
+				pr_warn("md: %s: rdev[%pg]: desc_nr(%d) >= freshest(%pg)->sb->max_dev(%u)\n",
+						mdname(mddev), rdev->bdev, rdev->desc_nr,
+						freshest->bdev, freshest_max_dev);
+				return -EUCLEAN;
+			}
+
+			role = le16_to_cpu(freshest_sb->dev_roles[rdev->desc_nr]);
+			pr_debug("md: %s: rdev[%pg]: role=%d(0x%x) according to freshest %pg\n",
+				     mdname(mddev), rdev->bdev, role, role, freshest->bdev);
+		} else {
 			role = le16_to_cpu(sb->dev_roles[rdev->desc_nr]);
+		}
 		switch(role) {
 		case MD_DISK_ROLE_SPARE: /* spare */
 			break;
@@ -2475,14 +2569,16 @@
 
 static bool does_sb_need_changing(struct mddev *mddev)
 {
-	struct md_rdev *rdev;
+	struct md_rdev *rdev = NULL, *iter;
 	struct mdp_superblock_1 *sb;
 	int role;
 
 	/* Find a good rdev */
-	rdev_for_each(rdev, mddev)
-		if ((rdev->raid_disk >= 0) && !test_bit(Faulty, &rdev->flags))
+	rdev_for_each(iter, mddev)
+		if ((iter->raid_disk >= 0) && !test_bit(Faulty, &iter->flags)) {
+			rdev = iter;
 			break;
+		}
 
 	/* No good device found. */
 	if (!rdev)
@@ -2718,7 +2814,7 @@
 		 * and should be added immediately.
 		 */
 		super_types[mddev->major_version].
-			validate_super(mddev, rdev);
+			validate_super(mddev, NULL/*freshest*/, rdev);
 		if (add_journal)
 			mddev_suspend(mddev);
 		err = mddev->pers->hot_add_disk(mddev, rdev);
@@ -3020,6 +3116,9 @@
 		err = kstrtouint(buf, 10, (unsigned int *)&slot);
 		if (err < 0)
 			return err;
+		if (slot < 0)
+			/* overflow */
+			return -ENOSPC;
 	}
 	if (rdev->mddev->pers && slot == -1) {
 		/* Setting 'slot' on an active array requires also
@@ -3597,7 +3696,7 @@
  * Check a full RAID array for plausibility
  */
 
-static void analyze_sbs(struct mddev *mddev)
+static int analyze_sbs(struct mddev *mddev)
 {
 	int i;
 	struct md_rdev *rdev, *freshest, *tmp;
@@ -3618,8 +3717,14 @@
 			md_kick_rdev_from_array(rdev);
 		}
 
+	/* Cannot find a valid fresh disk */
+	if (!freshest) {
+		pr_warn("md: cannot find a valid disk\n");
+		return -EINVAL;
+	}
+
 	super_types[mddev->major_version].
-		validate_super(mddev, freshest);
+		validate_super(mddev, NULL/*freshest*/, freshest);
 
 	i = 0;
 	rdev_for_each_safe(rdev, tmp, mddev) {
@@ -3634,7 +3739,7 @@
 		}
 		if (rdev != freshest) {
 			if (super_types[mddev->major_version].
-			    validate_super(mddev, rdev)) {
+			    validate_super(mddev, freshest, rdev)) {
 				pr_warn("md: kicking non-fresh %s from array!\n",
 					bdevname(rdev->bdev,b));
 				md_kick_rdev_from_array(rdev);
@@ -3652,6 +3757,8 @@
 			clear_bit(In_sync, &rdev->flags);
 		}
 	}
+
+	return 0;
 }
 
 /* Read a fixed-point number.
@@ -3693,8 +3800,9 @@
 static ssize_t
 safe_delay_show(struct mddev *mddev, char *page)
 {
-	int msec = (mddev->safemode_delay*1000)/HZ;
-	return sprintf(page, "%d.%03d\n", msec/1000, msec%1000);
+	unsigned int msec = ((unsigned long)mddev->safemode_delay*1000)/HZ;
+
+	return sprintf(page, "%u.%03u\n", msec/1000, msec%1000);
 }
 static ssize_t
 safe_delay_store(struct mddev *mddev, const char *cbuf, size_t len)
@@ -3706,7 +3814,7 @@
 		return -EINVAL;
 	}
 
-	if (strict_strtoul_scaled(cbuf, &msec, 3) < 0)
+	if (strict_strtoul_scaled(cbuf, &msec, 3) < 0 || msec > UINT_MAX / HZ)
 		return -EINVAL;
 	if (msec == 0)
 		mddev->safemode_delay = 0;
@@ -4367,6 +4475,8 @@
 	rv = kstrtouint(buf, 10, &n);
 	if (rv < 0)
 		return rv;
+	if (n > INT_MAX)
+		return -EINVAL;
 	atomic_set(&mddev->max_corr_read_errors, n);
 	return len;
 }
@@ -4667,11 +4777,21 @@
 			return -EINVAL;
 		err = mddev_lock(mddev);
 		if (!err) {
-			if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
+			if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) {
 				err =  -EBUSY;
-			else {
+			} else if (mddev->reshape_position == MaxSector ||
+				   mddev->pers->check_reshape == NULL ||
+				   mddev->pers->check_reshape(mddev)) {
 				clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
 				err = mddev->pers->start_reshape(mddev);
+			} else {
+				/*
+				 * If reshape is still in progress, and
+				 * md_check_recovery() can continue to reshape,
+				 * don't restart reshape because data can be
+				 * corrupted for raid456.
+				 */
+				clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
 			}
 			mddev_unlock(mddev);
 		}
@@ -5393,7 +5513,7 @@
 	 * writing to /sys/module/md_mod/parameters/new_array.
 	 */
 	static DEFINE_MUTEX(disks_mutex);
-	struct mddev *mddev = mddev_find(dev);
+	struct mddev *mddev = mddev_find_or_alloc(dev);
 	struct gendisk *disk;
 	int partitioned;
 	int shift;
@@ -5470,10 +5590,6 @@
 	 */
 	disk->flags |= GENHD_FL_EXT_DEVT;
 	mddev->gendisk = disk;
-	/* As soon as we call add_disk(), another thread could get
-	 * through to md_open, so make sure it doesn't get too far
-	 */
-	mutex_lock(&mddev->open_mutex);
 	add_disk(disk);
 
 	error = kobject_add(&mddev->kobj, &disk_to_dev(disk)->kobj, "%s", "md");
@@ -5488,7 +5604,6 @@
 	if (mddev->kobj.sd &&
 	    sysfs_create_group(&mddev->kobj, &md_bitmap_group))
 		pr_debug("pointless warning\n");
-	mutex_unlock(&mddev->open_mutex);
  abort:
 	mutex_unlock(&disks_mutex);
 	if (!error && mddev->kobj.sd) {
@@ -5570,7 +5685,9 @@
 	if (!mddev->raid_disks) {
 		if (!mddev->persistent)
 			return -EINVAL;
-		analyze_sbs(mddev);
+		err = analyze_sbs(mddev);
+		if (err)
+			return -EINVAL;
 	}
 
 	if (mddev->level != LEVEL_NONE)
@@ -5998,7 +6115,7 @@
 static void mddev_detach(struct mddev *mddev)
 {
 	md_bitmap_wait_behind_writes(mddev);
-	if (mddev->pers && mddev->pers->quiesce) {
+	if (mddev->pers && mddev->pers->quiesce && !mddev->suspended) {
 		mddev->pers->quiesce(mddev, 1);
 		mddev->pers->quiesce(mddev, 0);
 	}
@@ -6030,6 +6147,7 @@
 	/* stop the array and free an attached data structures.
 	 * This is called from dm-raid
 	 */
+	__md_stop_writes(mddev);
 	__md_stop(mddev);
 	bioset_exit(&mddev->bio_set);
 	bioset_exit(&mddev->sync_set);
@@ -6267,11 +6385,9 @@
 
 		md_probe(dev, NULL, NULL);
 		mddev = mddev_find(dev);
-		if (!mddev || !mddev->gendisk) {
-			if (mddev)
-				mddev_put(mddev);
+		if (!mddev)
 			break;
-		}
+
 		if (mddev_lock(mddev))
 			pr_warn("md: %s locked, cannot run\n", mdname(mddev));
 		else if (mddev->raid_disks || mddev->major_version
@@ -6528,7 +6644,7 @@
 			rdev->saved_raid_disk = rdev->raid_disk;
 		} else
 			super_types[mddev->major_version].
-				validate_super(mddev, rdev);
+				validate_super(mddev, NULL/*freshest*/, rdev);
 		if ((info->state & (1<<MD_DISK_SYNC)) &&
 		     rdev->raid_disk != info->raid_disk) {
 			/* This was a hot-add request, but events doesn't
@@ -6678,8 +6794,10 @@
 		goto busy;
 
 kick_rdev:
-	if (mddev_is_clustered(mddev))
-		md_cluster_ops->remove_disk(mddev, rdev);
+	if (mddev_is_clustered(mddev)) {
+		if (md_cluster_ops->remove_disk(mddev, rdev))
+			goto busy;
+	}
 
 	md_kick_rdev_from_array(rdev);
 	set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags);
@@ -7009,6 +7127,7 @@
 		return -EINVAL;
 	if (mddev->sync_thread ||
 	    test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
+	    test_bit(MD_RESYNCING_REMOTE, &mddev->recovery) ||
 	    mddev->reshape_position != MaxSector)
 		return -EBUSY;
 
@@ -7277,11 +7396,6 @@
 
 	mddev = bdev->bd_disk->private_data;
 
-	if (!mddev) {
-		BUG();
-		goto out;
-	}
-
 	/* Some actions do not requires the mutex */
 	switch (cmd) {
 	case GET_ARRAY_INFO:
@@ -7328,8 +7442,11 @@
 			err = -EBUSY;
 			goto out;
 		}
-		WARN_ON_ONCE(test_bit(MD_CLOSING, &mddev->flags));
-		set_bit(MD_CLOSING, &mddev->flags);
+		if (test_and_set_bit(MD_CLOSING, &mddev->flags)) {
+			mutex_unlock(&mddev->open_mutex);
+			err = -EBUSY;
+			goto out;
+		}
 		did_set_md_closing = true;
 		mutex_unlock(&mddev->open_mutex);
 		sync_blockdev(bdev);
@@ -7565,9 +7682,9 @@
 		 */
 		mddev_put(mddev);
 		/* Wait until bdev->bd_disk is definitely gone */
-		flush_workqueue(md_misc_wq);
-		/* Then retry the open from the top */
-		return -ERESTARTSYS;
+		if (work_pending(&mddev->del_work))
+			flush_workqueue(md_misc_wq);
+		return -EBUSY;
 	}
 	BUG_ON(mddev != bdev->bd_disk->private_data);
 
@@ -7709,17 +7826,22 @@
 
 void md_unregister_thread(struct md_thread **threadp)
 {
-	struct md_thread *thread = *threadp;
-	if (!thread)
-		return;
-	pr_debug("interrupting MD-thread pid %d\n", task_pid_nr(thread->tsk));
-	/* Locking ensures that mddev_unlock does not wake_up a
+	struct md_thread *thread;
+
+	/*
+	 * Locking ensures that mddev_unlock does not wake_up a
 	 * non-existent thread
 	 */
 	spin_lock(&pers_lock);
+	thread = *threadp;
+	if (!thread) {
+		spin_unlock(&pers_lock);
+		return;
+	}
 	*threadp = NULL;
 	spin_unlock(&pers_lock);
 
+	pr_debug("interrupting MD-thread pid %d\n", task_pid_nr(thread->tsk));
 	kthread_stop(thread->tsk);
 	kfree(thread);
 }
@@ -7900,7 +8022,11 @@
 	loff_t l = *pos;
 	struct mddev *mddev;
 
-	if (l >= 0x10000)
+	if (l == 0x10000) {
+		++*pos;
+		return (void *)2;
+	}
+	if (l > 0x10000)
 		return NULL;
 	if (!l--)
 		/* header */
@@ -8319,6 +8445,26 @@
 
 EXPORT_SYMBOL(md_write_end);
 
+/* This is used by raid0 and raid10 */
+void md_submit_discard_bio(struct mddev *mddev, struct md_rdev *rdev,
+			struct bio *bio, sector_t start, sector_t size)
+{
+	struct bio *discard_bio = NULL;
+
+	if (__blkdev_issue_discard(rdev->bdev, start, size, GFP_NOIO, 0,
+			&discard_bio) || !discard_bio)
+		return;
+
+	bio_chain(discard_bio, bio);
+	bio_clone_blkg_association(discard_bio, bio);
+	if (mddev->gendisk)
+		trace_block_bio_remap(bdev_get_queue(rdev->bdev),
+				discard_bio, disk_devt(mddev->gendisk),
+				bio->bi_iter.bi_sector);
+	generic_make_request(discard_bio);
+}
+EXPORT_SYMBOL_GPL(md_submit_discard_bio);
+
 /* md_allow_write(mddev)
  * Calling this ensures that the array is marked 'active' so that writes
  * may proceed without blocking.  It is important to call this before
@@ -8997,11 +9143,11 @@
 		}
 
 		if (mddev_is_clustered(mddev)) {
-			struct md_rdev *rdev;
+			struct md_rdev *rdev, *tmp;
 			/* kick the device if another node issued a
 			 * remove disk.
 			 */
-			rdev_for_each(rdev, mddev) {
+			rdev_for_each_safe(rdev, tmp, mddev) {
 				if (test_and_clear_bit(ClusterRemove, &rdev->flags) &&
 						rdev->raid_disk < 0)
 					md_kick_rdev_from_array(rdev);
@@ -9314,7 +9460,7 @@
 static void check_sb_changes(struct mddev *mddev, struct md_rdev *rdev)
 {
 	struct mdp_superblock_1 *sb = page_address(rdev->sb_page);
-	struct md_rdev *rdev2;
+	struct md_rdev *rdev2, *tmp;
 	int role, ret;
 	char b[BDEVNAME_SIZE];
 
@@ -9331,7 +9477,7 @@
 	}
 
 	/* Check for change of roles in the active devices */
-	rdev_for_each(rdev2, mddev) {
+	rdev_for_each_safe(rdev2, tmp, mddev) {
 		if (test_bit(Faulty, &rdev2->flags))
 			continue;
 
@@ -9376,8 +9522,11 @@
 		}
 	}
 
-	if (mddev->raid_disks != le32_to_cpu(sb->raid_disks))
-		update_raid_disks(mddev, le32_to_cpu(sb->raid_disks));
+	if (mddev->raid_disks != le32_to_cpu(sb->raid_disks)) {
+		ret = update_raid_disks(mddev, le32_to_cpu(sb->raid_disks));
+		if (ret)
+			pr_warn("md: updating array disks failed. %d\n", ret);
+	}
 
 	/*
 	 * Since mddev->delta_disks has already updated in update_raid_disks,
@@ -9456,16 +9605,18 @@
 
 void md_reload_sb(struct mddev *mddev, int nr)
 {
-	struct md_rdev *rdev;
+	struct md_rdev *rdev = NULL, *iter;
 	int err;
 
 	/* Find the rdev */
-	rdev_for_each_rcu(rdev, mddev) {
-		if (rdev->desc_nr == nr)
+	rdev_for_each_rcu(iter, mddev) {
+		if (iter->desc_nr == nr) {
+			rdev = iter;
 			break;
+		}
 	}
 
-	if (!rdev || rdev->desc_nr != nr) {
+	if (!rdev) {
 		pr_warn("%s: %d Could not find rdev with nr %d\n", __func__, __LINE__, nr);
 		return;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/md.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/md.h
@@ -550,7 +550,7 @@
 	int level;
 	struct list_head list;
 	struct module *owner;
-	bool (*make_request)(struct mddev *mddev, struct bio *bio);
+	bool __must_check (*make_request)(struct mddev *mddev, struct bio *bio);
 	/*
 	 * start up works that do NOT require md_thread. tasks that
 	 * requires md_thread should go into start()
@@ -701,9 +701,11 @@
 extern void md_done_sync(struct mddev *mddev, int blocks, int ok);
 extern void md_error(struct mddev *mddev, struct md_rdev *rdev);
 extern void md_finish_reshape(struct mddev *mddev);
+void md_submit_discard_bio(struct mddev *mddev, struct md_rdev *rdev,
+			struct bio *bio, sector_t start, sector_t size);
 
 extern int mddev_congested(struct mddev *mddev, int bits);
-extern void md_flush_request(struct mddev *mddev, struct bio *bio);
+extern bool __must_check md_flush_request(struct mddev *mddev, struct bio *bio);
 extern void md_super_write(struct mddev *mddev, struct md_rdev *rdev,
 			   sector_t sector, int size, struct page *page);
 extern int md_super_wait(struct mddev *mddev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/persistent-data/dm-array.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/persistent-data/dm-array.c
@@ -907,23 +907,27 @@
 	if (c->block)
 		unlock_ablock(c->info, c->block);
 
-	c->block = NULL;
-	c->ab = NULL;
 	c->index = 0;
 
 	r = dm_btree_cursor_get_value(&c->cursor, &key, &value_le);
 	if (r) {
 		DMERR("dm_btree_cursor_get_value failed");
-		dm_btree_cursor_end(&c->cursor);
+		goto out;
 
 	} else {
 		r = get_ablock(c->info, le64_to_cpu(value_le), &c->block, &c->ab);
 		if (r) {
 			DMERR("get_ablock failed");
-			dm_btree_cursor_end(&c->cursor);
+			goto out;
 		}
 	}
 
+	return 0;
+
+out:
+	dm_btree_cursor_end(&c->cursor);
+	c->block = NULL;
+	c->ab = NULL;
 	return r;
 }
 
@@ -946,10 +950,10 @@
 
 void dm_array_cursor_end(struct dm_array_cursor *c)
 {
-	if (c->block) {
+	if (c->block)
 		unlock_ablock(c->info, c->block);
-		dm_btree_cursor_end(&c->cursor);
-	}
+
+	dm_btree_cursor_end(&c->cursor);
 }
 EXPORT_SYMBOL_GPL(dm_array_cursor_end);
 
@@ -989,6 +993,7 @@
 		}
 
 		count -= remaining;
+		c->index += (remaining - 1);
 		r = dm_array_cursor_next(c);
 
 	} while (!r);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/persistent-data/dm-block-manager.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/persistent-data/dm-block-manager.c
@@ -493,7 +493,7 @@
 	void *p;
 	int r;
 
-	if (bm->read_only)
+	if (dm_bm_is_read_only(bm))
 		return -EPERM;
 
 	p = dm_bufio_read(bm->bufio, b, (struct dm_buffer **) result);
@@ -562,7 +562,7 @@
 	struct buffer_aux *aux;
 	void *p;
 
-	if (bm->read_only)
+	if (dm_bm_is_read_only(bm))
 		return -EPERM;
 
 	p = dm_bufio_new(bm->bufio, b, (struct dm_buffer **) result);
@@ -602,7 +602,7 @@
 
 int dm_bm_flush(struct dm_block_manager *bm)
 {
-	if (bm->read_only)
+	if (dm_bm_is_read_only(bm))
 		return -EPERM;
 
 	return dm_bufio_write_dirty_buffers(bm->bufio);
@@ -616,19 +616,21 @@
 
 bool dm_bm_is_read_only(struct dm_block_manager *bm)
 {
-	return bm->read_only;
+	return (bm ? bm->read_only : true);
 }
 EXPORT_SYMBOL_GPL(dm_bm_is_read_only);
 
 void dm_bm_set_read_only(struct dm_block_manager *bm)
 {
-	bm->read_only = true;
+	if (bm)
+		bm->read_only = true;
 }
 EXPORT_SYMBOL_GPL(dm_bm_set_read_only);
 
 void dm_bm_set_read_write(struct dm_block_manager *bm)
 {
-	bm->read_only = false;
+	if (bm)
+		bm->read_only = false;
 }
 EXPORT_SYMBOL_GPL(dm_bm_set_read_write);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/persistent-data/dm-btree-internal.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/persistent-data/dm-btree-internal.h
@@ -34,12 +34,12 @@
 	__le32 max_entries;
 	__le32 value_size;
 	__le32 padding;
-} __packed;
+} __attribute__((packed, aligned(8)));
 
 struct btree_node {
 	struct node_header header;
 	__le64 keys[0];
-} __packed;
+} __attribute__((packed, aligned(8)));
 
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/persistent-data/dm-btree-remove.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/persistent-data/dm-btree-remove.c
@@ -203,7 +203,13 @@
 	struct btree_node *right = r->n;
 	uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
 	uint32_t nr_right = le32_to_cpu(right->header.nr_entries);
-	unsigned threshold = 2 * merge_threshold(left) + 1;
+	/*
+	 * Ensure the number of entries in each child will be greater
+	 * than or equal to (max_entries / 3 + 1), so no matter which
+	 * child is used for removal, the number will still be not
+	 * less than (max_entries / 3).
+	 */
+	unsigned int threshold = 2 * (merge_threshold(left) + 1);
 
 	if (nr_left + nr_right < threshold) {
 		/*
@@ -417,9 +423,9 @@
 
 		memcpy(n, dm_block_data(child),
 		       dm_bm_block_size(dm_tm_get_bm(info->tm)));
-		dm_tm_unlock(info->tm, child);
 
 		dm_tm_dec(info->tm, dm_block_location(child));
+		dm_tm_unlock(info->tm, child);
 		return 0;
 	}
 
@@ -543,7 +549,8 @@
 		delete_at(n, index);
 	}
 
-	*new_root = shadow_root(&spine);
+	if (!r)
+		*new_root = shadow_root(&spine);
 	exit_shadow_spine(&spine);
 
 	return r;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/persistent-data/dm-btree.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/persistent-data/dm-btree.c
@@ -83,14 +83,16 @@
 }
 
 static int insert_at(size_t value_size, struct btree_node *node, unsigned index,
-		      uint64_t key, void *value)
-		      __dm_written_to_disk(value)
+		     uint64_t key, void *value)
+	__dm_written_to_disk(value)
 {
 	uint32_t nr_entries = le32_to_cpu(node->header.nr_entries);
+	uint32_t max_entries = le32_to_cpu(node->header.max_entries);
 	__le64 key_le = cpu_to_le64(key);
 
 	if (index > nr_entries ||
-	    index >= le32_to_cpu(node->header.max_entries)) {
+	    index >= max_entries ||
+	    nr_entries >= max_entries) {
 		DMERR("too many entries in btree node for insert");
 		__dm_unbless_for_disk(value);
 		return -ENOMEM;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/persistent-data/dm-space-map-common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/persistent-data/dm-space-map-common.c
@@ -281,6 +281,11 @@
 	struct disk_index_entry ie_disk;
 	struct dm_block *blk;
 
+	if (b >= ll->nr_blocks) {
+		DMERR_LIMIT("metadata block out of bounds");
+		return -EINVAL;
+	}
+
 	b = do_div(index, ll->entries_per_block);
 	r = ll->load_ie(ll, index, &ie_disk);
 	if (r < 0)
@@ -339,6 +344,8 @@
 	 */
 	begin = do_div(index_begin, ll->entries_per_block);
 	end = do_div(end, ll->entries_per_block);
+	if (end == 0)
+		end = ll->entries_per_block;
 
 	for (i = index_begin; i < index_end; i++, begin = 0) {
 		struct dm_block *blk;
@@ -380,6 +387,33 @@
 	return -ENOSPC;
 }
 
+int sm_ll_find_common_free_block(struct ll_disk *old_ll, struct ll_disk *new_ll,
+	                         dm_block_t begin, dm_block_t end, dm_block_t *b)
+{
+	int r;
+	uint32_t count;
+
+	do {
+		r = sm_ll_find_free_block(new_ll, begin, new_ll->nr_blocks, b);
+		if (r)
+			break;
+
+		/* double check this block wasn't used in the old transaction */
+		if (*b >= old_ll->nr_blocks)
+			count = 0;
+		else {
+			r = sm_ll_lookup(old_ll, *b, &count);
+			if (r)
+				break;
+
+			if (count)
+				begin = *b + 1;
+		}
+	} while (count);
+
+	return r;
+}
+
 static int sm_ll_mutate(struct ll_disk *ll, dm_block_t b,
 			int (*mutator)(void *context, uint32_t old, uint32_t *new),
 			void *context, enum allocation_event *ev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/persistent-data/dm-space-map-common.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/persistent-data/dm-space-map-common.h
@@ -33,7 +33,7 @@
 	__le64 blocknr;
 	__le32 nr_free;
 	__le32 none_free_before;
-} __packed;
+} __attribute__ ((packed, aligned(8)));
 
 
 #define MAX_METADATA_BITMAPS 255
@@ -43,7 +43,7 @@
 	__le64 blocknr;
 
 	struct disk_index_entry index[MAX_METADATA_BITMAPS];
-} __packed;
+} __attribute__ ((packed, aligned(8)));
 
 struct ll_disk;
 
@@ -86,7 +86,7 @@
 	__le64 nr_allocated;
 	__le64 bitmap_root;
 	__le64 ref_count_root;
-} __packed;
+} __attribute__ ((packed, aligned(8)));
 
 #define ENTRIES_PER_BYTE 4
 
@@ -94,7 +94,7 @@
 	__le32 csum;
 	__le32 not_used;
 	__le64 blocknr;
-} __packed;
+} __attribute__ ((packed, aligned(8)));
 
 enum allocation_event {
 	SM_NONE,
@@ -109,6 +109,8 @@
 int sm_ll_lookup(struct ll_disk *ll, dm_block_t b, uint32_t *result);
 int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin,
 			  dm_block_t end, dm_block_t *result);
+int sm_ll_find_common_free_block(struct ll_disk *old_ll, struct ll_disk *new_ll,
+	                         dm_block_t begin, dm_block_t end, dm_block_t *result);
 int sm_ll_insert(struct ll_disk *ll, dm_block_t b, uint32_t ref_count, enum allocation_event *ev);
 int sm_ll_inc(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev);
 int sm_ll_dec(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/persistent-data/dm-space-map-disk.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/persistent-data/dm-space-map-disk.c
@@ -167,8 +167,18 @@
 	enum allocation_event ev;
 	struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
 
-	/* FIXME: we should loop round a couple of times */
-	r = sm_ll_find_free_block(&smd->old_ll, smd->begin, smd->old_ll.nr_blocks, b);
+	/*
+	 * Any block we allocate has to be free in both the old and current ll.
+	 */
+	r = sm_ll_find_common_free_block(&smd->old_ll, &smd->ll, smd->begin, smd->ll.nr_blocks, b);
+	if (r == -ENOSPC) {
+		/*
+		 * There's no free block between smd->begin and the end of the metadata device.
+		 * We search before smd->begin in case something has been freed.
+		 */
+		r = sm_ll_find_common_free_block(&smd->old_ll, &smd->ll, 0, smd->begin, b);
+	}
+
 	if (r)
 		return r;
 
@@ -197,7 +207,6 @@
 		return r;
 
 	memcpy(&smd->old_ll, &smd->ll, sizeof(smd->old_ll));
-	smd->begin = 0;
 	smd->nr_allocated_this_transaction = 0;
 
 	r = sm_disk_get_nr_free(sm, &nr_free);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/persistent-data/dm-space-map-metadata.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/persistent-data/dm-space-map-metadata.c
@@ -275,7 +275,7 @@
 {
 	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
 
-	kfree(smm);
+	kvfree(smm);
 }
 
 static int sm_metadata_get_nr_blocks(struct dm_space_map *sm, dm_block_t *count)
@@ -448,7 +448,18 @@
 	enum allocation_event ev;
 	struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
 
-	r = sm_ll_find_free_block(&smm->old_ll, smm->begin, smm->old_ll.nr_blocks, b);
+	/*
+	 * Any block we allocate has to be free in both the old and current ll.
+	 */
+	r = sm_ll_find_common_free_block(&smm->old_ll, &smm->ll, smm->begin, smm->ll.nr_blocks, b);
+	if (r == -ENOSPC) {
+		/*
+		 * There's no free block between smm->begin and the end of the metadata device.
+		 * We search before smm->begin in case something has been freed.
+		 */
+		r = sm_ll_find_common_free_block(&smm->old_ll, &smm->ll, 0, smm->begin, b);
+	}
+
 	if (r)
 		return r;
 
@@ -500,7 +511,6 @@
 		return r;
 
 	memcpy(&smm->old_ll, &smm->ll, sizeof(smm->old_ll));
-	smm->begin = 0;
 	smm->allocated_this_transaction = 0;
 
 	return 0;
@@ -749,7 +759,7 @@
 {
 	struct sm_metadata *smm;
 
-	smm = kmalloc(sizeof(*smm), GFP_KERNEL);
+	smm = kvmalloc(sizeof(*smm), GFP_KERNEL);
 	if (!smm)
 		return ERR_PTR(-ENOMEM);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/raid0.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/raid0.c
@@ -63,7 +63,7 @@
 		int len = 0;
 
 		for (k = 0; k < conf->strip_zone[j].nb_dev; k++)
-			len += snprintf(line+len, 200-len, "%s%s", k?"/":"",
+			len += scnprintf(line+len, 200-len, "%s%s", k?"/":"",
 					bdevname(conf->devlist[j*raid_disks
 							       + k]->bdev, b));
 		pr_debug("md: zone%d=[%s]\n", j, line);
@@ -87,7 +87,7 @@
 	char b[BDEVNAME_SIZE];
 	char b2[BDEVNAME_SIZE];
 	struct r0conf *conf = kzalloc(sizeof(*conf), GFP_KERNEL);
-	unsigned short blksize = 512;
+	unsigned blksize = 512;
 
 	*private_conf = ERR_PTR(-ENOMEM);
 	if (!conf)
@@ -143,21 +143,6 @@
 	pr_debug("md/raid0:%s: FINAL %d zones\n",
 		 mdname(mddev), conf->nr_strip_zones);
 
-	if (conf->nr_strip_zones == 1) {
-		conf->layout = RAID0_ORIG_LAYOUT;
-	} else if (mddev->layout == RAID0_ORIG_LAYOUT ||
-		   mddev->layout == RAID0_ALT_MULTIZONE_LAYOUT) {
-		conf->layout = mddev->layout;
-	} else if (default_layout == RAID0_ORIG_LAYOUT ||
-		   default_layout == RAID0_ALT_MULTIZONE_LAYOUT) {
-		conf->layout = default_layout;
-	} else {
-		pr_err("md/raid0:%s: cannot assemble multi-zone RAID0 with default_layout setting\n",
-		       mdname(mddev));
-		pr_err("md/raid0: please set raid0.default_layout to 1 or 2\n");
-		err = -ENOTSUPP;
-		goto abort;
-	}
 	/*
 	 * now since we have the hard sector sizes, we can make sure
 	 * chunk size is a multiple of that sector size
@@ -288,6 +273,36 @@
 			 (unsigned long long)smallest->sectors);
 	}
 
+	if (conf->nr_strip_zones == 1 || conf->strip_zone[1].nb_dev == 1) {
+		conf->layout = RAID0_ORIG_LAYOUT;
+	} else if (mddev->layout == RAID0_ORIG_LAYOUT ||
+		   mddev->layout == RAID0_ALT_MULTIZONE_LAYOUT) {
+		conf->layout = mddev->layout;
+	} else if (default_layout == RAID0_ORIG_LAYOUT ||
+		   default_layout == RAID0_ALT_MULTIZONE_LAYOUT) {
+		conf->layout = default_layout;
+	} else {
+		pr_err("md/raid0:%s: cannot assemble multi-zone RAID0 with default_layout setting\n",
+		       mdname(mddev));
+		pr_err("md/raid0: please set raid0.default_layout to 1 or 2\n");
+		pr_err("md/raid0: Read the following page for more information:\n");
+		pr_err("md/raid0: https://wiki.ubuntu.com/Kernel/Raid0LayoutMigration\n");
+		err = -EOPNOTSUPP;
+		goto abort;
+	}
+
+	if (conf->layout == RAID0_ORIG_LAYOUT) {
+		for (i = 1; i < conf->nr_strip_zones; i++) {
+			sector_t first_sector = conf->strip_zone[i-1].zone_end;
+
+			sector_div(first_sector, mddev->chunk_sectors);
+			zone = conf->strip_zone + i;
+			/* disk_shift is first disk index used in the zone */
+			zone->disk_shift = sector_div(first_sector,
+						      zone->nb_dev);
+		}
+	}
+
 	pr_debug("md/raid0:%s: done.\n", mdname(mddev));
 	*private_conf = conf;
 
@@ -474,6 +489,20 @@
 	}
 }
 
+/*
+ * Convert disk_index to the disk order in which it is read/written.
+ *  For example, if we have 4 disks, they are numbered 0,1,2,3. If we
+ *  write the disks starting at disk 3, then the read/write order would
+ *  be disk 3, then 0, then 1, and then disk 2 and we want map_disk_shift()
+ *  to map the disks as follows 0,1,2,3 => 1,2,3,0. So disk 0 would map
+ *  to 1, 1 to 2, 2 to 3, and 3 to 0. That way we can compare disks in
+ *  that 'output' space to understand the read/write disk ordering.
+ */
+static int map_disk_shift(int disk_index, int num_disks, int disk_shift)
+{
+	return ((disk_index + num_disks - disk_shift) % num_disks);
+}
+
 static void raid0_handle_discard(struct mddev *mddev, struct bio *bio)
 {
 	struct r0conf *conf = mddev->private;
@@ -487,7 +516,9 @@
 	sector_t end_disk_offset;
 	unsigned int end_disk_index;
 	unsigned int disk;
+	sector_t orig_start, orig_end;
 
+	orig_start = start;
 	zone = find_zone(conf, &start);
 
 	if (bio_end_sector(bio) > zone->zone_end) {
@@ -501,6 +532,7 @@
 	} else
 		end = bio_end_sector(bio);
 
+	orig_end = end;
 	if (zone != conf->strip_zone)
 		end = end - zone[-1].zone_end;
 
@@ -512,33 +544,49 @@
 	last_stripe_index = end;
 	sector_div(last_stripe_index, stripe_size);
 
-	start_disk_index = (int)(start - first_stripe_index * stripe_size) /
-		mddev->chunk_sectors;
+	/* In the first zone the original and alternate layouts are the same */
+	if ((conf->layout == RAID0_ORIG_LAYOUT) && (zone != conf->strip_zone)) {
+		sector_div(orig_start, mddev->chunk_sectors);
+		start_disk_index = sector_div(orig_start, zone->nb_dev);
+		start_disk_index = map_disk_shift(start_disk_index,
+						  zone->nb_dev,
+						  zone->disk_shift);
+		sector_div(orig_end, mddev->chunk_sectors);
+		end_disk_index = sector_div(orig_end, zone->nb_dev);
+		end_disk_index = map_disk_shift(end_disk_index,
+						zone->nb_dev, zone->disk_shift);
+	} else {
+		start_disk_index = (int)(start - first_stripe_index * stripe_size) /
+			mddev->chunk_sectors;
+		end_disk_index = (int)(end - last_stripe_index * stripe_size) /
+			mddev->chunk_sectors;
+	}
 	start_disk_offset = ((int)(start - first_stripe_index * stripe_size) %
 		mddev->chunk_sectors) +
 		first_stripe_index * mddev->chunk_sectors;
-	end_disk_index = (int)(end - last_stripe_index * stripe_size) /
-		mddev->chunk_sectors;
 	end_disk_offset = ((int)(end - last_stripe_index * stripe_size) %
 		mddev->chunk_sectors) +
 		last_stripe_index * mddev->chunk_sectors;
 
 	for (disk = 0; disk < zone->nb_dev; disk++) {
 		sector_t dev_start, dev_end;
-		struct bio *discard_bio = NULL;
 		struct md_rdev *rdev;
+		int compare_disk;
+
+		compare_disk = map_disk_shift(disk, zone->nb_dev,
+					      zone->disk_shift);
 
-		if (disk < start_disk_index)
+		if (compare_disk < start_disk_index)
 			dev_start = (first_stripe_index + 1) *
 				mddev->chunk_sectors;
-		else if (disk > start_disk_index)
+		else if (compare_disk > start_disk_index)
 			dev_start = first_stripe_index * mddev->chunk_sectors;
 		else
 			dev_start = start_disk_offset;
 
-		if (disk < end_disk_index)
+		if (compare_disk < end_disk_index)
 			dev_end = (last_stripe_index + 1) * mddev->chunk_sectors;
-		else if (disk > end_disk_index)
+		else if (compare_disk > end_disk_index)
 			dev_end = last_stripe_index * mddev->chunk_sectors;
 		else
 			dev_end = end_disk_offset;
@@ -548,18 +596,9 @@
 
 		rdev = conf->devlist[(zone - conf->strip_zone) *
 			conf->strip_zone[0].nb_dev + disk];
-		if (__blkdev_issue_discard(rdev->bdev,
+		md_submit_discard_bio(mddev, rdev, bio,
 			dev_start + zone->dev_start + rdev->data_offset,
-			dev_end - dev_start, GFP_NOIO, 0, &discard_bio) ||
-		    !discard_bio)
-			continue;
-		bio_chain(discard_bio, bio);
-		bio_clone_blkg_association(discard_bio, bio);
-		if (mddev->gendisk)
-			trace_block_bio_remap(bdev_get_queue(rdev->bdev),
-				discard_bio, disk_devt(mddev->gendisk),
-				bio->bi_iter.bi_sector);
-		generic_make_request(discard_bio);
+			dev_end - dev_start);
 	}
 	bio_endio(bio);
 }
@@ -575,10 +614,9 @@
 	unsigned chunk_sects;
 	unsigned sectors;
 
-	if (unlikely(bio->bi_opf & REQ_PREFLUSH)) {
-		md_flush_request(mddev, bio);
+	if (unlikely(bio->bi_opf & REQ_PREFLUSH)
+	    && md_flush_request(mddev, bio))
 		return true;
-	}
 
 	if (unlikely((bio_op(bio) == REQ_OP_DISCARD))) {
 		raid0_handle_discard(mddev, bio);
@@ -615,7 +653,7 @@
 		tmp_dev = map_sector(mddev, zone, sector, &sector);
 		break;
 	default:
-		WARN("md/raid0:%s: Invalid layout\n", mdname(mddev));
+		WARN(1, "md/raid0:%s: Invalid layout\n", mdname(mddev));
 		bio_io_error(bio);
 		return true;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/raid0.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/raid0.h
@@ -6,6 +6,7 @@
 	sector_t zone_end;	/* Start of the next zone (in sectors) */
 	sector_t dev_start;	/* Zone offset in real dev (in sectors) */
 	int	 nb_dev;	/* # of devices attached to the zone */
+	int	 disk_shift;	/* start disk for the original layout */
 };
 
 /* Linux 3.14 (20d0189b101) made an unintended change to
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/raid1.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/raid1.c
@@ -452,12 +452,12 @@
 		/*
 		 * When the device is faulty, it is not necessary to
 		 * handle write error.
-		 * For failfast, this is the only remaining device,
-		 * We need to retry the write without FailFast.
 		 */
 		if (!test_bit(Faulty, &rdev->flags))
 			set_bit(R1BIO_WriteError, &r1_bio->state);
 		else {
+			/* Fail the request */
+			set_bit(R1BIO_Degraded, &r1_bio->state);
 			/* Finished with this branch */
 			r1_bio->bios[mirror] = NULL;
 			to_put = bio;
@@ -1567,10 +1567,9 @@
 {
 	sector_t sectors;
 
-	if (unlikely(bio->bi_opf & REQ_PREFLUSH)) {
-		md_flush_request(mddev, bio);
+	if (unlikely(bio->bi_opf & REQ_PREFLUSH)
+	    && md_flush_request(mddev, bio))
 		return true;
-	}
 
 	/*
 	 * There is a limit to the maximum size, but
@@ -1811,6 +1810,9 @@
 	int number = rdev->raid_disk;
 	struct raid1_info *p = conf->mirrors + number;
 
+	if (unlikely(number >= conf->raid_disks))
+		goto abort;
+
 	if (rdev != p->rdev)
 		p = conf->mirrors + conf->raid_disks + number;
 
@@ -2782,7 +2784,7 @@
 				write_targets++;
 			}
 		}
-		if (bio->bi_end_io) {
+		if (rdev && bio->bi_end_io) {
 			atomic_inc(&rdev->nr_pending);
 			bio->bi_iter.bi_sector = sector_nr + rdev->data_offset;
 			bio_set_dev(bio, rdev->bdev);
@@ -3133,6 +3135,7 @@
 	 * RAID1 needs at least one disk in active
 	 */
 	if (conf->raid_disks - mddev->degraded < 1) {
+		md_unregister_thread(&conf->thread);
 		ret = -EINVAL;
 		goto abort;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/raid10.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/raid10.c
@@ -91,7 +91,7 @@
 static void * r10bio_pool_alloc(gfp_t gfp_flags, void *data)
 {
 	struct r10conf *conf = data;
-	int size = offsetof(struct r10bio, devs[conf->copies]);
+	int size = offsetof(struct r10bio, devs[conf->geo.raid_disks]);
 
 	/* allocate a r10bio with room for raid_disks entries in the
 	 * bios array */
@@ -191,7 +191,7 @@
 
 out_free_pages:
 	while (--j >= 0)
-		resync_free_pages(&rps[j * 2]);
+		resync_free_pages(&rps[j]);
 
 	j = 0;
 out_free_bio:
@@ -238,7 +238,7 @@
 {
 	int i;
 
-	for (i = 0; i < conf->copies; i++) {
+	for (i = 0; i < conf->geo.raid_disks; i++) {
 		struct bio **bio = & r10_bio->devs[i].bio;
 		if (!BIO_SPECIAL(*bio))
 			bio_put(*bio);
@@ -327,7 +327,7 @@
 	int slot;
 	int repl = 0;
 
-	for (slot = 0; slot < conf->copies; slot++) {
+	for (slot = 0; slot < conf->geo.raid_disks; slot++) {
 		if (r10_bio->devs[slot].bio == bio)
 			break;
 		if (r10_bio->devs[slot].repl_bio == bio) {
@@ -336,7 +336,6 @@
 		}
 	}
 
-	BUG_ON(slot == conf->copies);
 	update_head_pos(slot, r10_bio);
 
 	if (slotp)
@@ -470,12 +469,12 @@
 			/*
 			 * When the device is faulty, it is not necessary to
 			 * handle write error.
-			 * For failfast, this is the only remaining device,
-			 * We need to retry the write without FailFast.
 			 */
 			if (!test_bit(Faulty, &rdev->flags))
 				set_bit(R10BIO_WriteError, &r10_bio->state);
 			else {
+				/* Fail the request */
+				set_bit(R10BIO_Degraded, &r10_bio->state);
 				r10_bio->devs[slot].bio = NULL;
 				to_put = bio;
 				dec_rdev = 1;
@@ -751,8 +750,16 @@
 		disk = r10_bio->devs[slot].devnum;
 		rdev = rcu_dereference(conf->mirrors[disk].replacement);
 		if (rdev == NULL || test_bit(Faulty, &rdev->flags) ||
-		    r10_bio->devs[slot].addr + sectors > rdev->recovery_offset)
+		    r10_bio->devs[slot].addr + sectors >
+		    rdev->recovery_offset) {
+			/*
+			 * Read replacement first to prevent reading both rdev
+			 * and replacement as NULL during replacement replace
+			 * rdev.
+			 */
+			smp_mb();
 			rdev = rcu_dereference(conf->mirrors[disk].rdev);
+		}
 		if (rdev == NULL ||
 		    test_bit(Faulty, &rdev->flags))
 			continue;
@@ -919,6 +926,7 @@
 			else
 				generic_make_request(bio);
 			bio = next;
+			cond_resched();
 		}
 		blk_finish_plug(&plug);
 	} else
@@ -1104,6 +1112,7 @@
 		else
 			generic_make_request(bio);
 		bio = next;
+		cond_resched();
 	}
 	kfree(plug);
 }
@@ -1145,7 +1154,7 @@
 	struct md_rdev *err_rdev = NULL;
 	gfp_t gfp = GFP_NOIO;
 
-	if (r10_bio->devs[slot].rdev) {
+	if (slot >= 0 && r10_bio->devs[slot].rdev) {
 		/*
 		 * This is an error retry, but we cannot
 		 * safely dereference the rdev in the r10_bio,
@@ -1293,12 +1302,77 @@
 	}
 }
 
+static void wait_blocked_dev(struct mddev *mddev, struct r10bio *r10_bio)
+{
+	int i;
+	struct r10conf *conf = mddev->private;
+	struct md_rdev *blocked_rdev;
+
+retry_wait:
+	blocked_rdev = NULL;
+	rcu_read_lock();
+	for (i = 0; i < conf->copies; i++) {
+		struct md_rdev *rdev = rcu_dereference(conf->mirrors[i].rdev);
+		struct md_rdev *rrdev = rcu_dereference(
+			conf->mirrors[i].replacement);
+		if (rdev == rrdev)
+			rrdev = NULL;
+		if (rdev && unlikely(test_bit(Blocked, &rdev->flags))) {
+			atomic_inc(&rdev->nr_pending);
+			blocked_rdev = rdev;
+			break;
+		}
+		if (rrdev && unlikely(test_bit(Blocked, &rrdev->flags))) {
+			atomic_inc(&rrdev->nr_pending);
+			blocked_rdev = rrdev;
+			break;
+		}
+
+		if (rdev && test_bit(WriteErrorSeen, &rdev->flags)) {
+			sector_t first_bad;
+			sector_t dev_sector = r10_bio->devs[i].addr;
+			int bad_sectors;
+			int is_bad;
+
+			/*
+			 * Discard request doesn't care the write result
+			 * so it doesn't need to wait blocked disk here.
+			 */
+			if (!r10_bio->sectors)
+				continue;
+
+			is_bad = is_badblock(rdev, dev_sector, r10_bio->sectors,
+					     &first_bad, &bad_sectors);
+			if (is_bad < 0) {
+				/*
+				 * Mustn't write here until the bad block
+				 * is acknowledged
+				 */
+				atomic_inc(&rdev->nr_pending);
+				set_bit(BlockedBadBlocks, &rdev->flags);
+				blocked_rdev = rdev;
+				break;
+			}
+		}
+	}
+	rcu_read_unlock();
+
+	if (unlikely(blocked_rdev)) {
+		/* Have to wait for this device to get unblocked, then retry */
+		allow_barrier(conf);
+		raid10_log(conf->mddev, "%s wait rdev %d blocked",
+				__func__, blocked_rdev->raid_disk);
+		md_wait_for_blocked_rdev(blocked_rdev, mddev);
+		wait_barrier(conf);
+		goto retry_wait;
+	}
+}
+
 static void raid10_write_request(struct mddev *mddev, struct bio *bio,
 				 struct r10bio *r10_bio)
 {
 	struct r10conf *conf = mddev->private;
 	int i;
-	struct md_rdev *blocked_rdev;
 	sector_t sectors;
 	int max_sectors;
 
@@ -1356,28 +1430,25 @@
 
 	r10_bio->read_slot = -1; /* make sure repl_bio gets freed */
 	raid10_find_phys(conf, r10_bio);
-retry_write:
-	blocked_rdev = NULL;
+
+	wait_blocked_dev(mddev, r10_bio);
+
 	rcu_read_lock();
 	max_sectors = r10_bio->sectors;
 
 	for (i = 0;  i < conf->copies; i++) {
 		int d = r10_bio->devs[i].devnum;
-		struct md_rdev *rdev = rcu_dereference(conf->mirrors[d].rdev);
-		struct md_rdev *rrdev = rcu_dereference(
-			conf->mirrors[d].replacement);
+		struct md_rdev *rdev, *rrdev;
+
+		rrdev = rcu_dereference(conf->mirrors[d].replacement);
+		/*
+		 * Read replacement first to prevent reading both rdev and
+		 * replacement as NULL during replacement replace rdev.
+		 */
+		smp_mb();
+		rdev = rcu_dereference(conf->mirrors[d].rdev);
 		if (rdev == rrdev)
 			rrdev = NULL;
-		if (rdev && unlikely(test_bit(Blocked, &rdev->flags))) {
-			atomic_inc(&rdev->nr_pending);
-			blocked_rdev = rdev;
-			break;
-		}
-		if (rrdev && unlikely(test_bit(Blocked, &rrdev->flags))) {
-			atomic_inc(&rrdev->nr_pending);
-			blocked_rdev = rrdev;
-			break;
-		}
 		if (rdev && (test_bit(Faulty, &rdev->flags)))
 			rdev = NULL;
 		if (rrdev && (test_bit(Faulty, &rrdev->flags)))
@@ -1398,15 +1469,6 @@
 
 			is_bad = is_badblock(rdev, dev_sector, max_sectors,
 					     &first_bad, &bad_sectors);
-			if (is_bad < 0) {
-				/* Mustn't write here until the bad block
-				 * is acknowledged
-				 */
-				atomic_inc(&rdev->nr_pending);
-				set_bit(BlockedBadBlocks, &rdev->flags);
-				blocked_rdev = rdev;
-				break;
-			}
 			if (is_bad && first_bad <= dev_sector) {
 				/* Cannot write here at all */
 				bad_sectors -= (dev_sector - first_bad);
@@ -1442,35 +1504,6 @@
 	}
 	rcu_read_unlock();
 
-	if (unlikely(blocked_rdev)) {
-		/* Have to wait for this device to get unblocked, then retry */
-		int j;
-		int d;
-
-		for (j = 0; j < i; j++) {
-			if (r10_bio->devs[j].bio) {
-				d = r10_bio->devs[j].devnum;
-				rdev_dec_pending(conf->mirrors[d].rdev, mddev);
-			}
-			if (r10_bio->devs[j].repl_bio) {
-				struct md_rdev *rdev;
-				d = r10_bio->devs[j].devnum;
-				rdev = conf->mirrors[d].replacement;
-				if (!rdev) {
-					/* Race with remove_disk */
-					smp_mb();
-					rdev = conf->mirrors[d].rdev;
-				}
-				rdev_dec_pending(rdev, mddev);
-			}
-		}
-		allow_barrier(conf);
-		raid10_log(conf->mddev, "wait rdev %d blocked", blocked_rdev->raid_disk);
-		md_wait_for_blocked_rdev(blocked_rdev, mddev);
-		wait_barrier(conf);
-		goto retry_write;
-	}
-
 	if (max_sectors < r10_bio->sectors)
 		r10_bio->sectors = max_sectors;
 
@@ -1510,7 +1543,9 @@
 	r10_bio->mddev = mddev;
 	r10_bio->sector = bio->bi_iter.bi_sector;
 	r10_bio->state = 0;
-	memset(r10_bio->devs, 0, sizeof(r10_bio->devs[0]) * conf->copies);
+	r10_bio->read_slot = -1;
+	memset(r10_bio->devs, 0, sizeof(r10_bio->devs[0]) *
+			conf->geo.raid_disks);
 
 	if (bio_data_dir(bio) == READ)
 		raid10_read_request(mddev, bio, r10_bio);
@@ -1518,6 +1553,304 @@
 		raid10_write_request(mddev, bio, r10_bio);
 }
 
+static void raid_end_discard_bio(struct r10bio *r10bio)
+{
+	struct r10conf *conf = r10bio->mddev->private;
+	struct r10bio *first_r10bio;
+
+	while (atomic_dec_and_test(&r10bio->remaining)) {
+
+		allow_barrier(conf);
+
+		if (!test_bit(R10BIO_Discard, &r10bio->state)) {
+			first_r10bio = (struct r10bio *)r10bio->master_bio;
+			free_r10bio(r10bio);
+			r10bio = first_r10bio;
+		} else {
+			md_write_end(r10bio->mddev);
+			bio_endio(r10bio->master_bio);
+			free_r10bio(r10bio);
+			break;
+		}
+	}
+}
+
+static void raid10_end_discard_request(struct bio *bio)
+{
+	struct r10bio *r10_bio = bio->bi_private;
+	struct r10conf *conf = r10_bio->mddev->private;
+	struct md_rdev *rdev = NULL;
+	int dev;
+	int slot, repl;
+
+	/*
+	 * We don't care the return value of discard bio
+	 */
+	if (!test_bit(R10BIO_Uptodate, &r10_bio->state))
+		set_bit(R10BIO_Uptodate, &r10_bio->state);
+
+	dev = find_bio_disk(conf, r10_bio, bio, &slot, &repl);
+	if (repl)
+		rdev = conf->mirrors[dev].replacement;
+	if (!rdev) {
+		/*
+		 * raid10_remove_disk uses smp_mb to make sure rdev is set to
+		 * replacement before setting replacement to NULL. It can read
+		 * rdev first without barrier protect even replacment is NULL
+		 */
+		smp_rmb();
+		rdev = conf->mirrors[dev].rdev;
+	}
+
+	raid_end_discard_bio(r10_bio);
+	rdev_dec_pending(rdev, conf->mddev);
+}
+
+/*
+ * There are some limitations to handle discard bio
+ * 1st, the discard size is bigger than stripe_size*2.
+ * 2st, if the discard bio spans reshape progress, we use the old way to
+ * handle discard bio
+ */
+static int raid10_handle_discard(struct mddev *mddev, struct bio *bio)
+{
+	struct r10conf *conf = mddev->private;
+	struct geom *geo = &conf->geo;
+	int far_copies = geo->far_copies;
+	bool first_copy = true;
+	struct r10bio *r10_bio, *first_r10bio;
+	struct bio *split;
+	int disk;
+	sector_t chunk;
+	unsigned int stripe_size;
+	unsigned int stripe_data_disks;
+	sector_t split_size;
+	sector_t bio_start, bio_end;
+	sector_t first_stripe_index, last_stripe_index;
+	sector_t start_disk_offset;
+	unsigned int start_disk_index;
+	sector_t end_disk_offset;
+	unsigned int end_disk_index;
+	unsigned int remainder;
+
+	if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery))
+		return -EAGAIN;
+
+	wait_barrier(conf);
+
+	/*
+	 * Check reshape again to avoid reshape happens after checking
+	 * MD_RECOVERY_RESHAPE and before wait_barrier
+	 */
+	if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery))
+		goto out;
+
+	if (geo->near_copies)
+		stripe_data_disks = geo->raid_disks / geo->near_copies +
+					geo->raid_disks % geo->near_copies;
+	else
+		stripe_data_disks = geo->raid_disks;
+
+	stripe_size = stripe_data_disks << geo->chunk_shift;
+
+	bio_start = bio->bi_iter.bi_sector;
+	bio_end = bio_end_sector(bio);
+
+	/*
+	 * Maybe one discard bio is smaller than strip size or across one
+	 * stripe and discard region is larger than one stripe size. For far
+	 * offset layout, if the discard region is not aligned with stripe
+	 * size, there is hole when we submit discard bio to member disk.
+	 * For simplicity, we only handle discard bio which discard region
+	 * is bigger than stripe_size * 2
+	 */
+	if (bio_sectors(bio) < stripe_size*2)
+		goto out;
+
+	/*
+	 * Keep bio aligned with strip size.
+	 */
+	div_u64_rem(bio_start, stripe_size, &remainder);
+	if (remainder) {
+		split_size = stripe_size - remainder;
+		split = bio_split(bio, split_size, GFP_NOIO, &conf->bio_split);
+		bio_chain(split, bio);
+		allow_barrier(conf);
+		/* Resend the fist split part */
+		generic_make_request(split);
+		wait_barrier(conf);
+	}
+	div_u64_rem(bio_end, stripe_size, &remainder);
+	if (remainder) {
+		split_size = bio_sectors(bio) - remainder;
+		split = bio_split(bio, split_size, GFP_NOIO, &conf->bio_split);
+		bio_chain(split, bio);
+		allow_barrier(conf);
+		/* Resend the second split part */
+		generic_make_request(bio);
+		bio = split;
+		wait_barrier(conf);
+	}
+
+	bio_start = bio->bi_iter.bi_sector;
+	bio_end = bio_end_sector(bio);
+
+	/*
+	 * Raid10 uses chunk as the unit to store data. It's similar like raid0.
+	 * One stripe contains the chunks from all member disk (one chunk from
+	 * one disk at the same HBA address). For layout detail, see 'man md 4'
+	 */
+	chunk = bio_start >> geo->chunk_shift;
+	chunk *= geo->near_copies;
+	first_stripe_index = chunk;
+	start_disk_index = sector_div(first_stripe_index, geo->raid_disks);
+	if (geo->far_offset)
+		first_stripe_index *= geo->far_copies;
+	start_disk_offset = (bio_start & geo->chunk_mask) +
+				(first_stripe_index << geo->chunk_shift);
+
+	chunk = bio_end >> geo->chunk_shift;
+	chunk *= geo->near_copies;
+	last_stripe_index = chunk;
+	end_disk_index = sector_div(last_stripe_index, geo->raid_disks);
+	if (geo->far_offset)
+		last_stripe_index *= geo->far_copies;
+	end_disk_offset = (bio_end & geo->chunk_mask) +
+				(last_stripe_index << geo->chunk_shift);
+
+retry_discard:
+	r10_bio = mempool_alloc(&conf->r10bio_pool, GFP_NOIO);
+	r10_bio->mddev = mddev;
+	r10_bio->state = 0;
+	r10_bio->sectors = 0;
+	memset(r10_bio->devs, 0, sizeof(r10_bio->devs[0]) * geo->raid_disks);
+	wait_blocked_dev(mddev, r10_bio);
+
+	/*
+	 * For far layout it needs more than one r10bio to cover all regions.
+	 * Inspired by raid10_sync_request, we can use the first r10bio->master_bio
+	 * to record the discard bio. Other r10bio->master_bio record the first
+	 * r10bio. The first r10bio only release after all other r10bios finish.
+	 * The discard bio returns only first r10bio finishes
+	 */
+	if (first_copy) {
+		r10_bio->master_bio = bio;
+		set_bit(R10BIO_Discard, &r10_bio->state);
+		first_copy = false;
+		first_r10bio = r10_bio;
+	} else
+		r10_bio->master_bio = (struct bio *)first_r10bio;
+
+	rcu_read_lock();
+	for (disk = 0; disk < geo->raid_disks; disk++) {
+		struct md_rdev *rdev = rcu_dereference(conf->mirrors[disk].rdev);
+		struct md_rdev *rrdev = rcu_dereference(
+			conf->mirrors[disk].replacement);
+
+		r10_bio->devs[disk].bio = NULL;
+		r10_bio->devs[disk].repl_bio = NULL;
+
+		if (rdev && (test_bit(Faulty, &rdev->flags)))
+			rdev = NULL;
+		if (rrdev && (test_bit(Faulty, &rrdev->flags)))
+			rrdev = NULL;
+		if (!rdev && !rrdev)
+			continue;
+
+		if (rdev) {
+			r10_bio->devs[disk].bio = bio;
+			atomic_inc(&rdev->nr_pending);
+		}
+		if (rrdev) {
+			r10_bio->devs[disk].repl_bio = bio;
+			atomic_inc(&rrdev->nr_pending);
+		}
+	}
+	rcu_read_unlock();
+
+	atomic_set(&r10_bio->remaining, 1);
+	for (disk = 0; disk < geo->raid_disks; disk++) {
+		sector_t dev_start, dev_end;
+		struct bio *mbio, *rbio = NULL;
+		struct md_rdev *rdev = rcu_dereference(conf->mirrors[disk].rdev);
+		struct md_rdev *rrdev = rcu_dereference(
+			conf->mirrors[disk].replacement);
+
+		/*
+		 * Now start to calculate the start and end address for each disk.
+		 * The space between dev_start and dev_end is the discard region.
+		 *
+		 * For dev_start, it needs to consider three conditions:
+		 * 1st, the disk is before start_disk, you can imagine the disk in
+		 * the next stripe. So the dev_start is the start address of next
+		 * stripe.
+		 * 2st, the disk is after start_disk, it means the disk is at the
+		 * same stripe of first disk
+		 * 3st, the first disk itself, we can use start_disk_offset directly
+		 */
+		if (disk < start_disk_index)
+			dev_start = (first_stripe_index + 1) * mddev->chunk_sectors;
+		else if (disk > start_disk_index)
+			dev_start = first_stripe_index * mddev->chunk_sectors;
+		else
+			dev_start = start_disk_offset;
+
+		if (disk < end_disk_index)
+			dev_end = (last_stripe_index + 1) * mddev->chunk_sectors;
+		else if (disk > end_disk_index)
+			dev_end = last_stripe_index * mddev->chunk_sectors;
+		else
+			dev_end = end_disk_offset;
+
+		/*
+		 * It only handles discard bio which size is >= stripe size, so
+		 * dev_end > dev_start all the time
+		 */
+		if (r10_bio->devs[disk].bio) {
+			mbio = bio_clone_fast(bio, GFP_NOIO, &mddev->bio_set);
+			mbio->bi_end_io = raid10_end_discard_request;
+			mbio->bi_private = r10_bio;
+			r10_bio->devs[disk].bio = mbio;
+			r10_bio->devs[disk].devnum = disk;
+			atomic_inc(&r10_bio->remaining);
+			md_submit_discard_bio(mddev, rdev, mbio,
+					dev_start + choose_data_offset(r10_bio, rdev),
+					dev_end - dev_start);
+			bio_endio(mbio);
+		}
+		if (r10_bio->devs[disk].repl_bio) {
+			rbio = bio_clone_fast(bio, GFP_NOIO, &mddev->bio_set);
+			rbio->bi_end_io = raid10_end_discard_request;
+			rbio->bi_private = r10_bio;
+			r10_bio->devs[disk].repl_bio = rbio;
+			r10_bio->devs[disk].devnum = disk;
+			atomic_inc(&r10_bio->remaining);
+			md_submit_discard_bio(mddev, rrdev, rbio,
+					dev_start + choose_data_offset(r10_bio, rrdev),
+					dev_end - dev_start);
+			bio_endio(rbio);
+		}
+	}
+
+	if (!geo->far_offset && --far_copies) {
+		first_stripe_index += geo->stride >> geo->chunk_shift;
+		start_disk_offset += geo->stride;
+		last_stripe_index += geo->stride >> geo->chunk_shift;
+		end_disk_offset += geo->stride;
+		atomic_inc(&first_r10bio->remaining);
+		raid_end_discard_bio(r10_bio);
+		wait_barrier(conf);
+		goto retry_discard;
+	}
+
+	raid_end_discard_bio(r10_bio);
+
+	return 0;
+out:
+	allow_barrier(conf);
+	return -EAGAIN;
+}
+
 static bool raid10_make_request(struct mddev *mddev, struct bio *bio)
 {
 	struct r10conf *conf = mddev->private;
@@ -1525,14 +1858,17 @@
 	int chunk_sects = chunk_mask + 1;
 	int sectors = bio_sectors(bio);
 
-	if (unlikely(bio->bi_opf & REQ_PREFLUSH)) {
-		md_flush_request(mddev, bio);
+	if (unlikely(bio->bi_opf & REQ_PREFLUSH)
+	    && md_flush_request(mddev, bio))
 		return true;
-	}
 
 	if (!md_write_start(mddev, bio))
 		return false;
 
+	if (unlikely(bio_op(bio) == REQ_OP_DISCARD))
+		if (!raid10_handle_discard(mddev, bio))
+			return true;
+
 	/*
 	 * If this request crosses a chunk boundary, we need to split
 	 * it.
@@ -1826,9 +2162,12 @@
 	int err = 0;
 	int number = rdev->raid_disk;
 	struct md_rdev **rdevp;
-	struct raid10_info *p = conf->mirrors + number;
+	struct raid10_info *p;
 
 	print_conf(conf);
+	if (unlikely(number >= mddev->raid_disks))
+		return 0;
+	p = conf->mirrors + number;
 	if (rdev == p->rdev)
 		rdevp = &p->rdev;
 	else if (rdev == p->replacement)
@@ -2226,11 +2565,22 @@
 {
 	struct r10conf *conf = mddev->private;
 	int d;
-	struct bio *wbio, *wbio2;
+	struct bio *wbio = r10_bio->devs[1].bio;
+	struct bio *wbio2 = r10_bio->devs[1].repl_bio;
+
+	/* Need to test wbio2->bi_end_io before we call
+	 * generic_make_request as if the former is NULL,
+	 * the latter is free to free wbio2.
+	 */
+	if (wbio2 && !wbio2->bi_end_io)
+		wbio2 = NULL;
 
 	if (!test_bit(R10BIO_Uptodate, &r10_bio->state)) {
 		fix_recovery_read_error(r10_bio);
-		end_sync_request(r10_bio);
+		if (wbio->bi_end_io)
+			end_sync_request(r10_bio);
+		if (wbio2)
+			end_sync_request(r10_bio);
 		return;
 	}
 
@@ -2239,14 +2589,6 @@
 	 * and submit the write request
 	 */
 	d = r10_bio->devs[1].devnum;
-	wbio = r10_bio->devs[1].bio;
-	wbio2 = r10_bio->devs[1].repl_bio;
-	/* Need to test wbio2->bi_end_io before we call
-	 * generic_make_request as if the former is NULL,
-	 * the latter is free to free wbio2.
-	 */
-	if (wbio2 && !wbio2->bi_end_io)
-		wbio2 = NULL;
 	if (wbio->bi_end_io) {
 		atomic_inc(&conf->mirrors[d].rdev->nr_pending);
 		md_sync_acct(conf->mirrors[d].rdev->bdev, bio_sectors(wbio));
@@ -2914,10 +3256,6 @@
 	sector_t chunk_mask = conf->geo.chunk_mask;
 	int page_idx = 0;
 
-	if (!mempool_initialized(&conf->r10buf_pool))
-		if (init_resync(conf))
-			return 0;
-
 	/*
 	 * Allow skipping a full rebuild for incremental assembly
 	 * of a clean array, like RAID1 does.
@@ -2933,6 +3271,10 @@
 		return mddev->dev_sectors - sector_nr;
 	}
 
+	if (!mempool_initialized(&conf->r10buf_pool))
+		if (init_resync(conf))
+			return 0;
+
  skipped:
 	max_sector = mddev->dev_sectors;
 	if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) ||
@@ -3047,8 +3389,6 @@
 			sector_t sect;
 			int must_sync;
 			int any_working;
-			int need_recover = 0;
-			int need_replace = 0;
 			struct raid10_info *mirror = &conf->mirrors[i];
 			struct md_rdev *mrdev, *mreplace;
 
@@ -3056,15 +3396,13 @@
 			mrdev = rcu_dereference(mirror->rdev);
 			mreplace = rcu_dereference(mirror->replacement);
 
-			if (mrdev != NULL &&
-			    !test_bit(Faulty, &mrdev->flags) &&
-			    !test_bit(In_sync, &mrdev->flags))
-				need_recover = 1;
-			if (mreplace != NULL &&
-			    !test_bit(Faulty, &mreplace->flags))
-				need_replace = 1;
+			if (mrdev && (test_bit(Faulty, &mrdev->flags) ||
+			    test_bit(In_sync, &mrdev->flags)))
+				mrdev = NULL;
+			if (mreplace && test_bit(Faulty, &mreplace->flags))
+				mreplace = NULL;
 
-			if (!need_recover && !need_replace) {
+			if (!mrdev && !mreplace) {
 				rcu_read_unlock();
 				continue;
 			}
@@ -3080,8 +3418,6 @@
 				rcu_read_unlock();
 				continue;
 			}
-			if (mreplace && test_bit(Faulty, &mreplace->flags))
-				mreplace = NULL;
 			/* Unless we are doing a full sync, or a replacement
 			 * we only need to recover the block if it is set in
 			 * the bitmap
@@ -3100,7 +3436,8 @@
 				rcu_read_unlock();
 				continue;
 			}
-			atomic_inc(&mrdev->nr_pending);
+			if (mrdev)
+				atomic_inc(&mrdev->nr_pending);
 			if (mreplace)
 				atomic_inc(&mreplace->nr_pending);
 			rcu_read_unlock();
@@ -3187,7 +3524,7 @@
 				r10_bio->devs[1].devnum = i;
 				r10_bio->devs[1].addr = to_addr;
 
-				if (need_recover) {
+				if (mrdev) {
 					bio = r10_bio->devs[1].bio;
 					bio->bi_next = biolist;
 					biolist = bio;
@@ -3204,11 +3541,11 @@
 				bio = r10_bio->devs[1].repl_bio;
 				if (bio)
 					bio->bi_end_io = NULL;
-				/* Note: if need_replace, then bio
+				/* Note: if replace is not NULL, then bio
 				 * cannot be NULL as r10buf_pool_alloc will
 				 * have allocated it.
 				 */
-				if (!need_replace)
+				if (!mreplace)
 					break;
 				bio->bi_next = biolist;
 				biolist = bio;
@@ -3232,7 +3569,7 @@
 					for (k = 0; k < conf->copies; k++)
 						if (r10_bio->devs[k].devnum == i)
 							break;
-					if (!test_bit(In_sync,
+					if (mrdev && !test_bit(In_sync,
 						      &mrdev->flags)
 					    && !rdev_set_badblocks(
 						    mrdev,
@@ -3258,12 +3595,14 @@
 				if (rb2)
 					atomic_dec(&rb2->remaining);
 				r10_bio = rb2;
-				rdev_dec_pending(mrdev, mddev);
+				if (mrdev)
+					rdev_dec_pending(mrdev, mddev);
 				if (mreplace)
 					rdev_dec_pending(mreplace, mddev);
 				break;
 			}
-			rdev_dec_pending(mrdev, mddev);
+			if (mrdev)
+				rdev_dec_pending(mrdev, mddev);
 			if (mreplace)
 				rdev_dec_pending(mreplace, mddev);
 			if (r10_bio->devs[0].bio->bi_opf & MD_FAILFAST) {
@@ -3629,6 +3968,20 @@
 	return nc*fc;
 }
 
+static void raid10_free_conf(struct r10conf *conf)
+{
+	if (!conf)
+		return;
+
+	mempool_exit(&conf->r10bio_pool);
+	kfree(conf->mirrors);
+	kfree(conf->mirrors_old);
+	kfree(conf->mirrors_new);
+	safe_put_page(conf->tmppage);
+	bioset_exit(&conf->bio_split);
+	kfree(conf);
+}
+
 static struct r10conf *setup_conf(struct mddev *mddev)
 {
 	struct r10conf *conf = NULL;
@@ -3711,20 +4064,24 @@
 	return conf;
 
  out:
-	if (conf) {
-		mempool_exit(&conf->r10bio_pool);
-		kfree(conf->mirrors);
-		safe_put_page(conf->tmppage);
-		bioset_exit(&conf->bio_split);
-		kfree(conf);
-	}
+	raid10_free_conf(conf);
 	return ERR_PTR(err);
 }
 
+static void raid10_set_io_opt(struct r10conf *conf)
+{
+	int raid_disks = conf->geo.raid_disks;
+
+	if (!(conf->geo.raid_disks % conf->geo.near_copies))
+		raid_disks /= conf->geo.near_copies;
+	blk_queue_io_opt(conf->mddev->queue, (conf->mddev->chunk_sectors << 9) *
+			 raid_disks);
+}
+
 static int raid10_run(struct mddev *mddev)
 {
 	struct r10conf *conf;
-	int i, disk_idx, chunk_size;
+	int i, disk_idx;
 	struct raid10_info *disk;
 	struct md_rdev *rdev;
 	sector_t size;
@@ -3745,6 +4102,9 @@
 	if (!conf)
 		goto out;
 
+	mddev->thread = conf->thread;
+	conf->thread = NULL;
+
 	if (mddev_is_clustered(conf->mddev)) {
 		int fc, fo;
 
@@ -3757,21 +4117,13 @@
 		}
 	}
 
-	mddev->thread = conf->thread;
-	conf->thread = NULL;
-
-	chunk_size = mddev->chunk_sectors << 9;
 	if (mddev->queue) {
 		blk_queue_max_discard_sectors(mddev->queue,
-					      mddev->chunk_sectors);
+					      UINT_MAX);
 		blk_queue_max_write_same_sectors(mddev->queue, 0);
 		blk_queue_max_write_zeroes_sectors(mddev->queue, 0);
-		blk_queue_io_min(mddev->queue, chunk_size);
-		if (conf->geo.raid_disks % conf->geo.near_copies)
-			blk_queue_io_opt(mddev->queue, chunk_size * conf->geo.raid_disks);
-		else
-			blk_queue_io_opt(mddev->queue, chunk_size *
-					 (conf->geo.raid_disks / conf->geo.near_copies));
+		blk_queue_io_min(mddev->queue, mddev->chunk_sectors << 9);
+		raid10_set_io_opt(conf);
 	}
 
 	rdev_for_each(rdev, mddev) {
@@ -3931,10 +4283,7 @@
 
 out_free_conf:
 	md_unregister_thread(&mddev->thread);
-	mempool_exit(&conf->r10bio_pool);
-	safe_put_page(conf->tmppage);
-	kfree(conf->mirrors);
-	kfree(conf);
+	raid10_free_conf(conf);
 	mddev->private = NULL;
 out:
 	return -EIO;
@@ -3942,15 +4291,7 @@
 
 static void raid10_free(struct mddev *mddev, void *priv)
 {
-	struct r10conf *conf = priv;
-
-	mempool_exit(&conf->r10bio_pool);
-	safe_put_page(conf->tmppage);
-	kfree(conf->mirrors);
-	kfree(conf->mirrors_old);
-	kfree(conf->mirrors_new);
-	bioset_exit(&conf->bio_split);
-	kfree(conf);
+	raid10_free_conf(priv);
 }
 
 static void raid10_quiesce(struct mddev *mddev, int quiesce)
@@ -4745,6 +5086,7 @@
 		stripe /= conf->geo.near_copies;
 		if (conf->mddev->queue->backing_dev_info->ra_pages < 2 * stripe)
 			conf->mddev->queue->backing_dev_info->ra_pages = 2 * stripe;
+		raid10_set_io_opt(conf);
 	}
 	conf->fullsync = 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/raid10.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/raid10.h
@@ -179,5 +179,6 @@
 	R10BIO_Previous,
 /* failfast devices did receive failfast requests. */
 	R10BIO_FailFast,
+	R10BIO_Discard,
 };
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/md/raid5.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/md/raid5.c
@@ -609,17 +609,17 @@
 	return degraded;
 }
 
-static int has_failed(struct r5conf *conf)
+static bool has_failed(struct r5conf *conf)
 {
-	int degraded;
+	int degraded = conf->mddev->degraded;
 
-	if (conf->mddev->reshape_position == MaxSector)
-		return conf->mddev->degraded > conf->max_degraded;
+	if (test_bit(MD_BROKEN, &conf->mddev->flags))
+		return true;
 
-	degraded = raid5_calc_degraded(conf);
-	if (degraded > conf->max_degraded)
-		return 1;
-	return 0;
+	if (conf->mddev->reshape_position != MaxSector)
+		degraded = raid5_calc_degraded(conf);
+
+	return degraded > conf->max_degraded;
 }
 
 struct stripe_head *
@@ -2181,7 +2181,7 @@
 	atomic_inc(&conf->active_stripes);
 
 	raid5_release_stripe(sh);
-	conf->max_nr_stripes++;
+	WRITE_ONCE(conf->max_nr_stripes, conf->max_nr_stripes + 1);
 	return 1;
 }
 
@@ -2228,14 +2228,19 @@
  * of the P and Q blocks.
  */
 static int scribble_alloc(struct raid5_percpu *percpu,
-			  int num, int cnt, gfp_t flags)
+			  int num, int cnt)
 {
 	size_t obj_size =
 		sizeof(struct page *) * (num+2) +
 		sizeof(addr_conv_t) * (num+2);
 	void *scribble;
 
-	scribble = kvmalloc_array(cnt, obj_size, flags);
+	/*
+	 * If here is in raid array suspend context, it is in memalloc noio
+	 * context as well, there is no potential recursive memory reclaim
+	 * I/Os with the GFP_KERNEL flag.
+	 */
+	scribble = kvmalloc_array(cnt, obj_size, GFP_KERNEL);
 	if (!scribble)
 		return -ENOMEM;
 
@@ -2267,8 +2272,7 @@
 
 		percpu = per_cpu_ptr(conf->percpu, cpu);
 		err = scribble_alloc(percpu, new_disks,
-				     new_sectors / STRIPE_SECTORS,
-				     GFP_NOIO);
+				     new_sectors / STRIPE_SECTORS);
 		if (err)
 			break;
 	}
@@ -2403,8 +2407,6 @@
 	} else
 		err = -ENOMEM;
 
-	mutex_unlock(&conf->cache_size_mutex);
-
 	conf->slab_cache = sc;
 	conf->active_name = 1-conf->active_name;
 
@@ -2427,6 +2429,8 @@
 
 	if (!err)
 		conf->pool_size = newsize;
+	mutex_unlock(&conf->cache_size_mutex);
+
 	return err;
 }
 
@@ -2444,7 +2448,7 @@
 	shrink_buffers(sh);
 	free_stripe(conf->slab_cache, sh);
 	atomic_dec(&conf->active_stripes);
-	conf->max_nr_stripes--;
+	WRITE_ONCE(conf->max_nr_stripes, conf->max_nr_stripes - 1);
 	return 1;
 }
 
@@ -2594,7 +2598,7 @@
 	struct stripe_head *sh = bi->bi_private;
 	struct r5conf *conf = sh->raid_conf;
 	int disks = sh->disks, i;
-	struct md_rdev *uninitialized_var(rdev);
+	struct md_rdev *rdev;
 	sector_t first_bad;
 	int bad_sectors;
 	int replacement = 0;
@@ -2662,10 +2666,10 @@
 	if (!test_and_clear_bit(R5_DOUBLE_LOCKED, &sh->dev[i].flags))
 		clear_bit(R5_LOCKED, &sh->dev[i].flags);
 	set_bit(STRIPE_HANDLE, &sh->state);
-	raid5_release_stripe(sh);
 
 	if (sh->batch_head && sh != sh->batch_head)
 		raid5_release_stripe(sh->batch_head);
+	raid5_release_stripe(sh);
 }
 
 static void raid5_error(struct mddev *mddev, struct md_rdev *rdev)
@@ -2675,34 +2679,31 @@
 	unsigned long flags;
 	pr_debug("raid456: error called\n");
 
+	pr_crit("md/raid:%s: Disk failure on %s, disabling device.\n",
+		mdname(mddev), bdevname(rdev->bdev, b));
+
 	spin_lock_irqsave(&conf->device_lock, flags);
+	set_bit(Faulty, &rdev->flags);
+	clear_bit(In_sync, &rdev->flags);
+	mddev->degraded = raid5_calc_degraded(conf);
 
-	if (test_bit(In_sync, &rdev->flags) &&
-	    mddev->degraded == conf->max_degraded) {
-		/*
-		 * Don't allow to achieve failed state
-		 * Don't try to recover this device
-		 */
+	if (has_failed(conf)) {
+		set_bit(MD_BROKEN, &conf->mddev->flags);
 		conf->recovery_disabled = mddev->recovery_disabled;
-		spin_unlock_irqrestore(&conf->device_lock, flags);
-		return;
+
+		pr_crit("md/raid:%s: Cannot continue operation (%d/%d failed).\n",
+			mdname(mddev), mddev->degraded, conf->raid_disks);
+	} else {
+		pr_crit("md/raid:%s: Operation continuing on %d devices.\n",
+			mdname(mddev), conf->raid_disks - mddev->degraded);
 	}
 
-	set_bit(Faulty, &rdev->flags);
-	clear_bit(In_sync, &rdev->flags);
-	mddev->degraded = raid5_calc_degraded(conf);
 	spin_unlock_irqrestore(&conf->device_lock, flags);
 	set_bit(MD_RECOVERY_INTR, &mddev->recovery);
 
 	set_bit(Blocked, &rdev->flags);
 	set_mask_bits(&mddev->sb_flags, 0,
 		      BIT(MD_SB_CHANGE_DEVS) | BIT(MD_SB_CHANGE_PENDING));
-	pr_crit("md/raid:%s: Disk failure on %s, disabling device.\n"
-		"md/raid:%s: Operation continuing on %d devices.\n",
-		mdname(mddev),
-		bdevname(rdev->bdev, b),
-		mdname(mddev),
-		conf->raid_disks - mddev->degraded);
 	r5c_update_on_rdev_error(mddev, rdev);
 }
 
@@ -3600,6 +3601,7 @@
 	 * is missing/faulty, then we need to read everything we can.
 	 */
 	if (sh->raid_conf->level != 6 &&
+	    sh->raid_conf->rmw_level != PARITY_DISABLE_RMW &&
 	    sh->sector < sh->raid_conf->mddev->recovery_cp)
 		/* reconstruct-write isn't being forced */
 		return 0;
@@ -3726,7 +3728,7 @@
 		 * back cache (prexor with orig_page, and then xor with
 		 * page) in the read path
 		 */
-		if (s->injournal && s->failed) {
+		if (s->to_read && s->injournal && s->failed) {
 			if (test_bit(STRIPE_R5C_CACHING, &sh->state))
 				r5c_make_stripe_write_out(sh);
 			goto out;
@@ -4835,7 +4837,7 @@
 	 * or to load a block that is being partially written.
 	 */
 	if (s.to_read || s.non_overwrite
-	    || (conf->level == 6 && s.to_write && s.failed)
+	    || (s.to_write && s.failed)
 	    || (s.syncing && (s.uptodate + s.compute < disks))
 	    || s.replacing
 	    || s.expanding)
@@ -5592,8 +5594,8 @@
 		if (ret == 0)
 			return true;
 		if (ret == -ENODEV) {
-			md_flush_request(mddev, bi);
-			return true;
+			if (md_flush_request(mddev, bi))
+				return true;
 		}
 		/* ret == -EAGAIN, fallback */
 		/*
@@ -5726,7 +5728,7 @@
 				do_flush = false;
 			}
 
-			if (!sh->batch_head)
+			if (!sh->batch_head || sh == sh->batch_head)
 				set_bit(STRIPE_HANDLE, &sh->state);
 			clear_bit(STRIPE_DELAYED, &sh->state);
 			if ((!sh->batch_head || sh == sh->batch_head) &&
@@ -5819,7 +5821,9 @@
 	safepos = conf->reshape_safe;
 	sector_div(safepos, data_disks);
 	if (mddev->reshape_backwards) {
-		BUG_ON(writepos < reshape_sectors);
+		if (WARN_ON(writepos < reshape_sectors))
+			return MaxSector;
+
 		writepos -= reshape_sectors;
 		readpos += reshape_sectors;
 		safepos += reshape_sectors;
@@ -5837,14 +5841,18 @@
 	 * to set 'stripe_addr' which is where we will write to.
 	 */
 	if (mddev->reshape_backwards) {
-		BUG_ON(conf->reshape_progress == 0);
+		if (WARN_ON(conf->reshape_progress == 0))
+			return MaxSector;
+
 		stripe_addr = writepos;
-		BUG_ON((mddev->dev_sectors &
-			~((sector_t)reshape_sectors - 1))
-		       - reshape_sectors - stripe_addr
-		       != sector_nr);
+		if (WARN_ON((mddev->dev_sectors &
+		    ~((sector_t)reshape_sectors - 1)) -
+		    reshape_sectors - stripe_addr != sector_nr))
+			return MaxSector;
 	} else {
-		BUG_ON(writepos != sector_nr + reshape_sectors);
+		if (WARN_ON(writepos != sector_nr + reshape_sectors))
+			return MaxSector;
+
 		stripe_addr = sector_nr;
 	}
 
@@ -6296,6 +6304,9 @@
 		int batch_size, released;
 		unsigned int offset;
 
+		if (test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags))
+			break;
+
 		released = release_stripe_list(conf, conf->temp_inactive_list);
 		if (released)
 			clear_bit(R5_DID_ALLOC, &conf->cache_state);
@@ -6379,7 +6390,7 @@
 	if (size <= 16 || size > 32768)
 		return -EINVAL;
 
-	conf->min_nr_stripes = size;
+	WRITE_ONCE(conf->min_nr_stripes, size);
 	mutex_lock(&conf->cache_size_mutex);
 	while (size < conf->max_nr_stripes &&
 	       drop_one_stripe(conf))
@@ -6391,7 +6402,7 @@
 	mutex_lock(&conf->cache_size_mutex);
 	while (size > conf->max_nr_stripes)
 		if (!grow_one_stripe(conf, GFP_KERNEL)) {
-			conf->min_nr_stripes = conf->max_nr_stripes;
+			WRITE_ONCE(conf->min_nr_stripes, conf->max_nr_stripes);
 			result = -ENOMEM;
 			break;
 		}
@@ -6765,8 +6776,7 @@
 			       conf->previous_raid_disks),
 			   max(conf->chunk_sectors,
 			       conf->prev_chunk_sectors)
-			   / STRIPE_SECTORS,
-			   GFP_KERNEL)) {
+			   / STRIPE_SECTORS)) {
 		free_scratch_buffer(conf, percpu);
 		return -ENOMEM;
 	}
@@ -6867,11 +6877,13 @@
 				       struct shrink_control *sc)
 {
 	struct r5conf *conf = container_of(shrink, struct r5conf, shrinker);
+	int max_stripes = READ_ONCE(conf->max_nr_stripes);
+	int min_stripes = READ_ONCE(conf->min_nr_stripes);
 
-	if (conf->max_nr_stripes < conf->min_nr_stripes)
+	if (max_stripes < min_stripes)
 		/* unlikely, but not impossible */
 		return 0;
-	return conf->max_nr_stripes - conf->min_nr_stripes;
+	return max_stripes - min_stripes;
 }
 
 static struct r5conf *setup_conf(struct mddev *mddev)
@@ -7146,6 +7158,12 @@
 	return 0;
 }
 
+static void raid5_set_io_opt(struct r5conf *conf)
+{
+	blk_queue_io_opt(conf->mddev->queue, (conf->chunk_sectors << 9) *
+			 (conf->raid_disks - conf->max_degraded));
+}
+
 static int raid5_run(struct mddev *mddev)
 {
 	struct r5conf *conf;
@@ -7435,8 +7453,7 @@
 
 		chunk_size = mddev->chunk_sectors << 9;
 		blk_queue_io_min(mddev->queue, chunk_size);
-		blk_queue_io_opt(mddev->queue, chunk_size *
-				 (conf->raid_disks - conf->max_degraded));
+		raid5_set_io_opt(conf);
 		mddev->queue->limits.raid_partial_stripes_expensive = 1;
 		/*
 		 * We can only discard a whole stripe. It doesn't make sense to
@@ -7721,6 +7738,7 @@
 	 */
 	if (rdev->saved_raid_disk >= 0 &&
 	    rdev->saved_raid_disk >= first &&
+	    rdev->saved_raid_disk <= last &&
 	    conf->disks[rdev->saved_raid_disk].rdev == NULL)
 		first = rdev->saved_raid_disk;
 
@@ -8029,6 +8047,7 @@
 						   / PAGE_SIZE);
 			if (conf->mddev->queue->backing_dev_info->ra_pages < 2 * stripe)
 				conf->mddev->queue->backing_dev_info->ra_pages = 2 * stripe;
+			raid5_set_io_opt(conf);
 		}
 	}
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/cec/cec-adap.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/cec/cec-adap.c
@@ -378,7 +378,8 @@
 	} else {
 		list_del_init(&data->list);
 		if (!(data->msg.tx_status & CEC_TX_STATUS_OK))
-			data->adap->transmit_queue_sz--;
+			if (!WARN_ON(!data->adap->transmit_queue_sz))
+				data->adap->transmit_queue_sz--;
 	}
 
 	if (data->msg.tx_status & CEC_TX_STATUS_OK) {
@@ -417,7 +418,7 @@
 		cec_data_cancel(data, CEC_TX_STATUS_ABORTED);
 	}
 	if (adap->transmitting)
-		cec_data_cancel(adap->transmitting, CEC_TX_STATUS_ABORTED);
+		adap->transmit_in_progress_aborted = true;
 
 	/* Cancel the pending timeout work. */
 	list_for_each_entry_safe(data, n, &adap->wait_queue, list) {
@@ -430,6 +431,14 @@
 		 * need to do anything special in that case.
 		 */
 	}
+	/*
+	 * If something went wrong and this counter isn't what it should
+	 * be, then this will reset it back to 0. Warn if it is not 0,
+	 * since it indicates a bug, either in this framework or in a
+	 * CEC driver.
+	 */
+	if (WARN_ON(adap->transmit_queue_sz))
+		adap->transmit_queue_sz = 0;
 }
 
 /*
@@ -454,7 +463,7 @@
 		bool timeout = false;
 		u8 attempts;
 
-		if (adap->transmitting) {
+		if (adap->transmit_in_progress) {
 			int err;
 
 			/*
@@ -489,7 +498,16 @@
 			goto unlock;
 		}
 
-		if (adap->transmitting && timeout) {
+		if (adap->transmit_in_progress &&
+		    adap->transmit_in_progress_aborted) {
+			if (adap->transmitting)
+				cec_data_cancel(adap->transmitting,
+						CEC_TX_STATUS_ABORTED);
+			adap->transmit_in_progress = false;
+			adap->transmit_in_progress_aborted = false;
+			goto unlock;
+		}
+		if (adap->transmit_in_progress && timeout) {
 			/*
 			 * If we timeout, then log that. Normally this does
 			 * not happen and it is an indication of a faulty CEC
@@ -498,14 +516,18 @@
 			 * so much traffic on the bus that the adapter was
 			 * unable to transmit for CEC_XFER_TIMEOUT_MS (2.1s).
 			 */
-			pr_warn("cec-%s: message %*ph timed out\n", adap->name,
-				adap->transmitting->msg.len,
-				adap->transmitting->msg.msg);
+			if (adap->transmitting) {
+				pr_warn("cec-%s: message %*ph timed out\n", adap->name,
+					adap->transmitting->msg.len,
+					adap->transmitting->msg.msg);
+				/* Just give up on this. */
+				cec_data_cancel(adap->transmitting,
+						CEC_TX_STATUS_TIMEOUT);
+			} else {
+				pr_warn("cec-%s: transmit timed out\n", adap->name);
+			}
 			adap->transmit_in_progress = false;
 			adap->tx_timeouts++;
-			/* Just give up on this. */
-			cec_data_cancel(adap->transmitting,
-					CEC_TX_STATUS_TIMEOUT);
 			goto unlock;
 		}
 
@@ -520,7 +542,8 @@
 		data = list_first_entry(&adap->transmit_queue,
 					struct cec_data, list);
 		list_del_init(&data->list);
-		adap->transmit_queue_sz--;
+		if (!WARN_ON(!data->adap->transmit_queue_sz))
+			adap->transmit_queue_sz--;
 
 		/* Make this the current transmitting message */
 		adap->transmitting = data;
@@ -555,6 +578,7 @@
 		if (data->attempts == 0)
 			data->attempts = attempts;
 
+		adap->transmit_in_progress_aborted = false;
 		/* Tell the adapter to transmit, cancel on error */
 		if (adap->ops->adap_transmit(adap, data->attempts,
 					     signal_free_time, &data->msg))
@@ -582,6 +606,8 @@
 	struct cec_msg *msg;
 	unsigned int attempts_made = arb_lost_cnt + nack_cnt +
 				     low_drive_cnt + error_cnt;
+	bool done = status & (CEC_TX_STATUS_MAX_RETRIES | CEC_TX_STATUS_OK);
+	bool aborted = adap->transmit_in_progress_aborted;
 
 	dprintk(2, "%s: status 0x%02x\n", __func__, status);
 	if (attempts_made < 1)
@@ -602,6 +628,7 @@
 		goto wake_thread;
 	}
 	adap->transmit_in_progress = false;
+	adap->transmit_in_progress_aborted = false;
 
 	msg = &data->msg;
 
@@ -622,8 +649,7 @@
 	 * the hardware didn't signal that it retried itself (by setting
 	 * CEC_TX_STATUS_MAX_RETRIES), then we will retry ourselves.
 	 */
-	if (data->attempts > attempts_made &&
-	    !(status & (CEC_TX_STATUS_MAX_RETRIES | CEC_TX_STATUS_OK))) {
+	if (!aborted && data->attempts > attempts_made && !done) {
 		/* Retry this message */
 		data->attempts -= attempts_made;
 		if (msg->timeout)
@@ -638,6 +664,8 @@
 		goto wake_thread;
 	}
 
+	if (aborted && !done)
+		status |= CEC_TX_STATUS_ABORTED;
 	data->attempts = 0;
 
 	/* Always set CEC_TX_STATUS_MAX_RETRIES on error */
@@ -734,6 +762,7 @@
 {
 	struct cec_data *data;
 	bool is_raw = msg_is_raw(msg);
+	int err;
 
 	msg->rx_ts = 0;
 	msg->tx_ts = 0;
@@ -893,11 +922,13 @@
 	 * Release the lock and wait, retake the lock afterwards.
 	 */
 	mutex_unlock(&adap->lock);
-	wait_for_completion_killable(&data->c);
-	if (!data->completed)
-		cancel_delayed_work_sync(&data->work);
+	err = wait_for_completion_killable(&data->c);
+	cancel_delayed_work_sync(&data->work);
 	mutex_lock(&adap->lock);
 
+	if (err)
+		adap->transmit_in_progress_aborted = true;
+
 	/* Cancel the transmit if it was interrupted */
 	if (!data->completed)
 		cec_data_cancel(data, CEC_TX_STATUS_ABORTED);
@@ -1063,7 +1094,8 @@
 	mutex_lock(&adap->lock);
 	dprintk(2, "%s: %*ph\n", __func__, msg->len, msg->msg);
 
-	adap->last_initiator = 0xff;
+	if (!adap->transmit_in_progress)
+		adap->last_initiator = 0xff;
 
 	/* Check if this message was for us (directed or broadcast). */
 	if (!cec_msg_is_broadcast(msg))
@@ -1083,11 +1115,11 @@
 			valid_la = false;
 		else if (!cec_msg_is_broadcast(msg) && !(dir_fl & DIRECTED))
 			valid_la = false;
-		else if (cec_msg_is_broadcast(msg) && !(dir_fl & BCAST1_4))
+		else if (cec_msg_is_broadcast(msg) && !(dir_fl & BCAST))
 			valid_la = false;
 		else if (cec_msg_is_broadcast(msg) &&
-			 adap->log_addrs.cec_version >= CEC_OP_CEC_VERSION_2_0 &&
-			 !(dir_fl & BCAST2_0))
+			 adap->log_addrs.cec_version < CEC_OP_CEC_VERSION_2_0 &&
+			 !(dir_fl & BCAST1_4))
 			valid_la = false;
 	}
 	if (valid_la && min_len) {
@@ -1177,6 +1209,7 @@
 			if (abort)
 				dst->rx_status |= CEC_RX_STATUS_FEATURE_ABORT;
 			msg->flags = dst->flags;
+			msg->sequence = dst->sequence;
 			/* Remove it from the wait_queue */
 			list_del_init(&data->list);
 
@@ -1248,7 +1281,7 @@
 		 * While trying to poll the physical address was reset
 		 * and the adapter was unconfigured, so bail out.
 		 */
-		if (!adap->is_configuring)
+		if (adap->phys_addr == CEC_PHYS_ADDR_INVALID)
 			return -EINTR;
 
 		if (err)
@@ -1306,7 +1339,6 @@
 	    adap->phys_addr != CEC_PHYS_ADDR_INVALID)
 		WARN_ON(adap->ops->adap_log_addr(adap, CEC_LOG_ADDR_INVALID));
 	adap->log_addrs.log_addr_mask = 0;
-	adap->is_configuring = false;
 	adap->is_configured = false;
 	memset(adap->phys_addrs, 0xff, sizeof(adap->phys_addrs));
 	cec_flush(adap);
@@ -1499,9 +1531,10 @@
 	for (i = 0; i < las->num_log_addrs; i++)
 		las->log_addr[i] = CEC_LOG_ADDR_INVALID;
 	cec_adap_unconfigure(adap);
+	adap->is_configuring = false;
 	adap->kthread_config = NULL;
-	mutex_unlock(&adap->lock);
 	complete(&adap->config_completion);
+	mutex_unlock(&adap->lock);
 	return 0;
 }
 
@@ -1513,9 +1546,12 @@
  */
 static void cec_claim_log_addrs(struct cec_adapter *adap, bool block)
 {
-	if (WARN_ON(adap->is_configuring || adap->is_configured))
+	if (WARN_ON(adap->is_claiming_log_addrs ||
+		    adap->is_configuring || adap->is_configured))
 		return;
 
+	adap->is_claiming_log_addrs = true;
+
 	init_completion(&adap->config_completion);
 
 	/* Ready to kick off the thread */
@@ -1529,6 +1565,7 @@
 		wait_for_completion(&adap->config_completion);
 		mutex_lock(&adap->lock);
 	}
+	adap->is_claiming_log_addrs = false;
 }
 
 /* Set a new physical address and send an event notifying userspace of this.
@@ -1556,6 +1593,9 @@
 		if (adap->needs_hpd || list_empty(&adap->devnode.fhs)) {
 			WARN_ON(adap->ops->adap_enable(adap, false));
 			adap->transmit_in_progress = false;
+			adap->transmit_in_progress_aborted = false;
+			if (adap->transmitting)
+				cec_data_cancel(adap->transmitting, CEC_TX_STATUS_ABORTED);
 			wake_up_interruptible(&adap->kthread_waitq);
 		}
 		mutex_unlock(&adap->devnode.lock);
@@ -1718,6 +1758,10 @@
 		unsigned j;
 
 		log_addrs->log_addr[i] = CEC_LOG_ADDR_INVALID;
+		if (log_addrs->log_addr_type[i] > CEC_LOG_ADDR_TYPE_UNREGISTERED) {
+			dprintk(1, "unknown logical address type\n");
+			return -EINVAL;
+		}
 		if (type_mask & (1 << log_addrs->log_addr_type[i])) {
 			dprintk(1, "duplicate logical address type\n");
 			return -EINVAL;
@@ -1738,10 +1782,6 @@
 			dprintk(1, "invalid primary device type\n");
 			return -EINVAL;
 		}
-		if (log_addrs->log_addr_type[i] > CEC_LOG_ADDR_TYPE_UNREGISTERED) {
-			dprintk(1, "unknown logical address type\n");
-			return -EINVAL;
-		}
 		for (j = 0; j < feature_sz; j++) {
 			if ((features[j] & 0x80) == 0) {
 				if (op_is_dev_features)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/cec/cec-api.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/cec/cec-api.c
@@ -147,7 +147,13 @@
 	struct cec_log_addrs log_addrs;
 
 	mutex_lock(&adap->lock);
-	log_addrs = adap->log_addrs;
+	/*
+	 * We use memcpy here instead of assignment since there is a
+	 * hole at the end of struct cec_log_addrs that an assignment
+	 * might ignore. So when we do copy_to_user() we could leak
+	 * one byte of memory.
+	 */
+	memcpy(&log_addrs, &adap->log_addrs, sizeof(log_addrs));
 	if (!adap->is_configured)
 		memset(log_addrs.log_addr, CEC_LOG_ADDR_INVALID,
 		       sizeof(log_addrs.log_addr));
@@ -172,7 +178,7 @@
 			   CEC_LOG_ADDRS_FL_ALLOW_RC_PASSTHRU |
 			   CEC_LOG_ADDRS_FL_CDC_ONLY;
 	mutex_lock(&adap->lock);
-	if (!adap->is_configuring &&
+	if (!adap->is_claiming_log_addrs && !adap->is_configuring &&
 	    (!log_addrs.num_log_addrs || !adap->is_configured) &&
 	    !cec_is_busy(adap, fh)) {
 		err = __cec_s_log_addrs(adap, &log_addrs, block);
@@ -646,6 +652,8 @@
 		list_del(&data->xfer_list);
 	}
 	mutex_unlock(&adap->lock);
+
+	mutex_lock(&fh->lock);
 	while (!list_empty(&fh->msgs)) {
 		struct cec_msg_entry *entry =
 			list_first_entry(&fh->msgs, struct cec_msg_entry, list);
@@ -663,6 +671,7 @@
 			kfree(entry);
 		}
 	}
+	mutex_unlock(&fh->lock);
 	kfree(fh);
 
 	cec_put_device(devnode);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/common/saa7146/saa7146_fops.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/common/saa7146/saa7146_fops.c
@@ -525,7 +525,7 @@
 		ERR("out of memory. aborting.\n");
 		kfree(vv);
 		v4l2_ctrl_handler_free(hdl);
-		return -1;
+		return -ENOMEM;
 	}
 
 	saa7146_video_uops.init(dev,vv);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/common/siano/smscoreapi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/common/siano/smscoreapi.c
@@ -908,7 +908,7 @@
 					 void *buffer, size_t size)
 {
 	struct sms_firmware *firmware = (struct sms_firmware *) buffer;
-	struct sms_msg_data4 *msg;
+	struct sms_msg_data5 *msg;
 	u32 mem_address,  calc_checksum = 0;
 	u32 i, *ptr;
 	u8 *payload = firmware->payload;
@@ -989,24 +989,20 @@
 		goto exit_fw_download;
 
 	if (coredev->mode == DEVICE_MODE_NONE) {
-		struct sms_msg_data *trigger_msg =
-			(struct sms_msg_data *) msg;
-
 		pr_debug("sending MSG_SMS_SWDOWNLOAD_TRIGGER_REQ\n");
 		SMS_INIT_MSG(&msg->x_msg_header,
 				MSG_SMS_SWDOWNLOAD_TRIGGER_REQ,
-				sizeof(struct sms_msg_hdr) +
-				sizeof(u32) * 5);
+				sizeof(*msg));
 
-		trigger_msg->msg_data[0] = firmware->start_address;
+		msg->msg_data[0] = firmware->start_address;
 					/* Entry point */
-		trigger_msg->msg_data[1] = 6; /* Priority */
-		trigger_msg->msg_data[2] = 0x200; /* Stack size */
-		trigger_msg->msg_data[3] = 0; /* Parameter */
-		trigger_msg->msg_data[4] = 4; /* Task ID */
+		msg->msg_data[1] = 6; /* Priority */
+		msg->msg_data[2] = 0x200; /* Stack size */
+		msg->msg_data[3] = 0; /* Parameter */
+		msg->msg_data[4] = 4; /* Task ID */
 
-		rc = smscore_sendrequest_and_wait(coredev, trigger_msg,
-					trigger_msg->x_msg_header.msg_length,
+		rc = smscore_sendrequest_and_wait(coredev, msg,
+					msg->x_msg_header.msg_length,
 					&coredev->trigger_done);
 	} else {
 		SMS_INIT_MSG(&msg->x_msg_header, MSG_SW_RELOAD_EXEC_REQ,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/common/siano/smscoreapi.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/common/siano/smscoreapi.h
@@ -629,9 +629,9 @@
 	u32 msg_data[2];
 };
 
-struct sms_msg_data4 {
+struct sms_msg_data5 {
 	struct sms_msg_hdr x_msg_header;
-	u32 msg_data[4];
+	u32 msg_data[5];
 };
 
 struct sms_data_download {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/common/siano/smsdvb-main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/common/siano/smsdvb-main.c
@@ -1169,12 +1169,19 @@
 	rc = dvb_create_media_graph(&client->adapter, true);
 	if (rc < 0) {
 		pr_err("dvb_create_media_graph failed %d\n", rc);
-		goto client_error;
+		goto media_graph_error;
 	}
 
 	pr_info("DVB interface registered.\n");
 	return 0;
 
+media_graph_error:
+	mutex_lock(&g_smsdvb_clientslock);
+	list_del(&client->entry);
+	mutex_unlock(&g_smsdvb_clientslock);
+
+	smsdvb_debugfs_release(client);
+
 client_error:
 	dvb_unregister_frontend(&client->frontend);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c
@@ -113,6 +113,7 @@
 {
 	unsigned pat;
 	unsigned plane;
+	int ret = 0;
 
 	tpg->max_line_width = max_w;
 	for (pat = 0; pat < TPG_MAX_PAT_LINES; pat++) {
@@ -121,14 +122,18 @@
 
 			tpg->lines[pat][plane] =
 				vzalloc(array3_size(max_w, 2, pixelsz));
-			if (!tpg->lines[pat][plane])
-				return -ENOMEM;
+			if (!tpg->lines[pat][plane]) {
+				ret = -ENOMEM;
+				goto free_lines;
+			}
 			if (plane == 0)
 				continue;
 			tpg->downsampled_lines[pat][plane] =
 				vzalloc(array3_size(max_w, 2, pixelsz));
-			if (!tpg->downsampled_lines[pat][plane])
-				return -ENOMEM;
+			if (!tpg->downsampled_lines[pat][plane]) {
+				ret = -ENOMEM;
+				goto free_lines;
+			}
 		}
 	}
 	for (plane = 0; plane < TPG_MAX_PLANES; plane++) {
@@ -136,18 +141,45 @@
 
 		tpg->contrast_line[plane] =
 			vzalloc(array_size(pixelsz, max_w));
-		if (!tpg->contrast_line[plane])
-			return -ENOMEM;
+		if (!tpg->contrast_line[plane]) {
+			ret = -ENOMEM;
+			goto free_contrast_line;
+		}
 		tpg->black_line[plane] =
 			vzalloc(array_size(pixelsz, max_w));
-		if (!tpg->black_line[plane])
-			return -ENOMEM;
+		if (!tpg->black_line[plane]) {
+			ret = -ENOMEM;
+			goto free_contrast_line;
+		}
 		tpg->random_line[plane] =
 			vzalloc(array3_size(max_w, 2, pixelsz));
-		if (!tpg->random_line[plane])
-			return -ENOMEM;
+		if (!tpg->random_line[plane]) {
+			ret = -ENOMEM;
+			goto free_contrast_line;
+		}
 	}
 	return 0;
+
+free_contrast_line:
+	for (plane = 0; plane < TPG_MAX_PLANES; plane++) {
+		vfree(tpg->contrast_line[plane]);
+		vfree(tpg->black_line[plane]);
+		vfree(tpg->random_line[plane]);
+		tpg->contrast_line[plane] = NULL;
+		tpg->black_line[plane] = NULL;
+		tpg->random_line[plane] = NULL;
+	}
+free_lines:
+	for (pat = 0; pat < TPG_MAX_PAT_LINES; pat++)
+		for (plane = 0; plane < TPG_MAX_PLANES; plane++) {
+			vfree(tpg->lines[pat][plane]);
+			tpg->lines[pat][plane] = NULL;
+			if (plane == 0)
+				continue;
+			vfree(tpg->downsampled_lines[pat][plane]);
+			tpg->downsampled_lines[pat][plane] = NULL;
+		}
+	return ret;
 }
 EXPORT_SYMBOL_GPL(tpg_alloc);
 
@@ -1757,6 +1789,9 @@
 	unsigned p;
 	unsigned x;
 
+	if (WARN_ON_ONCE(!tpg->src_width || !tpg->scaled_width))
+		return;
+
 	switch (tpg->pattern) {
 	case TPG_PAT_GREEN:
 		contrast = TPG_COLOR_100_RED;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/common/videobuf2/videobuf2-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/common/videobuf2/videobuf2-core.c
@@ -282,6 +282,10 @@
 	p->mem_priv = NULL;
 	p->dbuf = NULL;
 	p->dbuf_mapped = 0;
+	p->bytesused = 0;
+	p->length = 0;
+	p->m.fd = 0;
+	p->data_offset = 0;
 }
 
 /*
@@ -1177,10 +1181,6 @@
 
 		/* Release previously acquired memory if present */
 		__vb2_plane_dmabuf_put(vb, &vb->planes[plane]);
-		vb->planes[plane].bytesused = 0;
-		vb->planes[plane].length = 0;
-		vb->planes[plane].m.fd = 0;
-		vb->planes[plane].data_offset = 0;
 
 		/* Acquire each plane's memory */
 		mem_priv = call_ptr_memop(vb, attach_dmabuf,
@@ -1512,6 +1512,7 @@
 		  struct media_request *req)
 {
 	struct vb2_buffer *vb;
+	enum vb2_buffer_state orig_state;
 	int ret;
 
 	if (q->error) {
@@ -1611,6 +1612,7 @@
 	 * Add to the queued buffers list, a buffer will stay on it until
 	 * dequeued in dqbuf.
 	 */
+	orig_state = vb->state;
 	list_add_tail(&vb->queued_entry, &q->queued_list);
 	q->queued_count++;
 	q->waiting_for_buffers = false;
@@ -1641,8 +1643,17 @@
 	if (q->streaming && !q->start_streaming_called &&
 	    q->queued_count >= q->min_buffers_needed) {
 		ret = vb2_start_streaming(q);
-		if (ret)
+		if (ret) {
+			/*
+			 * Since vb2_core_qbuf will return with an error,
+			 * we should return it to state DEQUEUED since
+			 * the error indicates that the buffer wasn't queued.
+			 */
+			list_del(&vb->queued_entry);
+			q->queued_count--;
+			vb->state = orig_state;
 			return ret;
+		}
 	}
 
 	dprintk(2, "qbuf of buffer %d succeeded\n", vb->index);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/common/videobuf2/videobuf2-dma-contig.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/common/videobuf2/videobuf2-dma-contig.c
@@ -154,7 +154,7 @@
 	buf->cookie = dma_alloc_attrs(dev, size, &buf->dma_addr,
 					GFP_KERNEL | gfp_flags, buf->attrs);
 	if (!buf->cookie) {
-		dev_err(dev, "dma_alloc_coherent of size %ld failed\n", size);
+		dev_err(dev, "dma_alloc_coherent of size %lu failed\n", size);
 		kfree(buf);
 		return ERR_PTR(-ENOMEM);
 	}
@@ -200,9 +200,9 @@
 
 	vma->vm_ops->open(vma);
 
-	pr_debug("%s: mapped dma addr 0x%08lx at 0x%08lx, size %ld\n",
-		__func__, (unsigned long)buf->dma_addr, vma->vm_start,
-		buf->size);
+	pr_debug("%s: mapped dma addr 0x%08lx at 0x%08lx, size %lu\n",
+		 __func__, (unsigned long)buf->dma_addr, vma->vm_start,
+		 buf->size);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-core/dmxdev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-core/dmxdev.c
@@ -800,6 +800,11 @@
 	if (mutex_lock_interruptible(&dmxdev->mutex))
 		return -ERESTARTSYS;
 
+	if (dmxdev->exit) {
+		mutex_unlock(&dmxdev->mutex);
+		return -ENODEV;
+	}
+
 	for (i = 0; i < dmxdev->filternum; i++)
 		if (dmxdev->filter[i].state == DMXDEV_STATE_FREE)
 			break;
@@ -1413,7 +1418,7 @@
 };
 int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
 {
-	int i;
+	int i, ret;
 
 	if (dmxdev->demux->open(dmxdev->demux) < 0)
 		return -EUSERS;
@@ -1432,21 +1437,36 @@
 					    DMXDEV_STATE_FREE);
 	}
 
-	dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev,
+	ret = dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev,
 			    DVB_DEVICE_DEMUX, dmxdev->filternum);
-	dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr,
+	if (ret < 0)
+		goto err_register_dvbdev;
+
+	ret = dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr,
 			    dmxdev, DVB_DEVICE_DVR, dmxdev->filternum);
+	if (ret < 0)
+		goto err_register_dvr_dvbdev;
 
 	dvb_ringbuffer_init(&dmxdev->dvr_buffer, NULL, 8192);
 
 	return 0;
+
+err_register_dvr_dvbdev:
+	dvb_unregister_device(dmxdev->dvbdev);
+err_register_dvbdev:
+	vfree(dmxdev->filter);
+	dmxdev->filter = NULL;
+	return ret;
 }
 
 EXPORT_SYMBOL(dvb_dmxdev_init);
 
 void dvb_dmxdev_release(struct dmxdev *dmxdev)
 {
+	mutex_lock(&dmxdev->mutex);
 	dmxdev->exit = 1;
+	mutex_unlock(&dmxdev->mutex);
+
 	if (dmxdev->dvbdev->users > 1) {
 		wait_event(dmxdev->dvbdev->wait_queue,
 				dmxdev->dvbdev->users == 1);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-core/dvb_ca_en50221.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-core/dvb_ca_en50221.c
@@ -151,13 +151,19 @@
 
 	/* mutex serializing ioctls */
 	struct mutex ioctl_mutex;
+
+	/* A mutex used when a device is disconnected */
+	struct mutex remove_mutex;
+
+	/* Whether the device is disconnected */
+	int exit;
 };
 
 static void dvb_ca_private_free(struct dvb_ca_private *ca)
 {
 	unsigned int i;
 
-	dvb_free_device(ca->dvbdev);
+	dvb_device_put(ca->dvbdev);
 	for (i = 0; i < ca->slot_count; i++)
 		vfree(ca->slot_info[i].rx_buffer.data);
 
@@ -187,7 +193,7 @@
 static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot,
 				    u8 *ebuf, int ecount);
 static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot,
-				     u8 *ebuf, int ecount);
+				     u8 *ebuf, int ecount, int size_write_flag);
 
 /**
  * Safely find needle in haystack.
@@ -370,7 +376,7 @@
 	ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_FR, HZ / 10);
 	if (ret)
 		return ret;
-	ret = dvb_ca_en50221_write_data(ca, slot, buf, 2);
+	ret = dvb_ca_en50221_write_data(ca, slot, buf, 2, CMDREG_SW);
 	if (ret != 2)
 		return -EIO;
 	ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN);
@@ -778,11 +784,13 @@
  * @buf: The data in this buffer is treated as a complete link-level packet to
  *	 be written.
  * @bytes_write: Size of ebuf.
+ * @size_write_flag: A flag on Command Register which says whether the link size
+ * information will be writen or not.
  *
  * return: Number of bytes written, or < 0 on error.
  */
 static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot,
-				     u8 *buf, int bytes_write)
+				     u8 *buf, int bytes_write, int size_write_flag)
 {
 	struct dvb_ca_slot *sl = &ca->slot_info[slot];
 	int status;
@@ -817,7 +825,7 @@
 
 	/* OK, set HC bit */
 	status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND,
-					    IRQEN | CMDREG_HC);
+					    IRQEN | CMDREG_HC | size_write_flag);
 	if (status)
 		goto exit;
 
@@ -1505,7 +1513,7 @@
 
 			mutex_lock(&sl->slot_lock);
 			status = dvb_ca_en50221_write_data(ca, slot, fragbuf,
-							   fraglen + 2);
+							   fraglen + 2, 0);
 			mutex_unlock(&sl->slot_lock);
 			if (status == (fraglen + 2)) {
 				written = 1;
@@ -1706,12 +1714,22 @@
 
 	dprintk("%s\n", __func__);
 
-	if (!try_module_get(ca->pub->owner))
+	mutex_lock(&ca->remove_mutex);
+
+	if (ca->exit) {
+		mutex_unlock(&ca->remove_mutex);
+		return -ENODEV;
+	}
+
+	if (!try_module_get(ca->pub->owner)) {
+		mutex_unlock(&ca->remove_mutex);
 		return -EIO;
+	}
 
 	err = dvb_generic_open(inode, file);
 	if (err < 0) {
 		module_put(ca->pub->owner);
+		mutex_unlock(&ca->remove_mutex);
 		return err;
 	}
 
@@ -1736,6 +1754,7 @@
 
 	dvb_ca_private_get(ca);
 
+	mutex_unlock(&ca->remove_mutex);
 	return 0;
 }
 
@@ -1755,6 +1774,8 @@
 
 	dprintk("%s\n", __func__);
 
+	mutex_lock(&ca->remove_mutex);
+
 	/* mark the CA device as closed */
 	ca->open = 0;
 	dvb_ca_en50221_thread_update_delay(ca);
@@ -1765,6 +1786,13 @@
 
 	dvb_ca_private_put(ca);
 
+	if (dvbdev->users == 1 && ca->exit == 1) {
+		mutex_unlock(&ca->remove_mutex);
+		wake_up(&dvbdev->wait_queue);
+	} else {
+		mutex_unlock(&ca->remove_mutex);
+	}
+
 	return err;
 }
 
@@ -1888,6 +1916,7 @@
 	}
 
 	mutex_init(&ca->ioctl_mutex);
+	mutex_init(&ca->remove_mutex);
 
 	if (signal_pending(current)) {
 		ret = -EINTR;
@@ -1930,6 +1959,14 @@
 
 	dprintk("%s\n", __func__);
 
+	mutex_lock(&ca->remove_mutex);
+	ca->exit = 1;
+	mutex_unlock(&ca->remove_mutex);
+
+	if (ca->dvbdev->users < 1)
+		wait_event(ca->dvbdev->wait_queue,
+				ca->dvbdev->users == 1);
+
 	/* shutdown the thread if there was one */
 	kthread_stop(ca->thread);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-core/dvb_demux.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-core/dvb_demux.c
@@ -125,12 +125,12 @@
 
 	cc = buf[3] & 0x0f;
 	ccok = ((feed->cc + 1) & 0x0f) == cc;
-	feed->cc = cc;
 	if (!ccok) {
 		set_buf_flags(feed, DMX_BUFFER_FLAG_DISCONTINUITY_DETECTED);
 		dprintk_sect_loss("missed packet: %d instead of %d!\n",
 				  cc, (feed->cc + 1) & 0x0f);
 	}
+	feed->cc = cc;
 
 	if (buf[1] & 0x40)	// PUSI ?
 		feed->peslen = 0xfffa;
@@ -310,7 +310,6 @@
 
 	cc = buf[3] & 0x0f;
 	ccok = ((feed->cc + 1) & 0x0f) == cc;
-	feed->cc = cc;
 
 	if (buf[3] & 0x20) {
 		/* adaption field present, check for discontinuity_indicator */
@@ -346,6 +345,7 @@
 		feed->pusi_seen = false;
 		dvb_dmx_swfilter_section_new(feed);
 	}
+	feed->cc = cc;
 
 	if (buf[1] & 0x40) {
 		/* PUSI=1 (is set), section boundary is here */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-core/dvb_frontend.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-core/dvb_frontend.c
@@ -135,7 +135,7 @@
 	struct dvb_frontend_private *fepriv = fe->frontend_priv;
 
 	if (fepriv)
-		dvb_free_device(fepriv->dvbdev);
+		dvb_device_put(fepriv->dvbdev);
 
 	dvb_frontend_invoke_release(fe, fe->ops.release);
 
@@ -292,14 +292,22 @@
 	}
 
 	if (events->eventw == events->eventr) {
-		int ret;
+		struct wait_queue_entry wait;
+		int ret = 0;
 
 		if (flags & O_NONBLOCK)
 			return -EWOULDBLOCK;
 
-		ret = wait_event_interruptible(events->wait_queue,
-					       dvb_frontend_test_event(fepriv, events));
-
+		init_waitqueue_entry(&wait, current);
+		add_wait_queue(&events->wait_queue, &wait);
+		while (!dvb_frontend_test_event(fepriv, events)) {
+			wait_woken(&wait, TASK_INTERRUPTIBLE, 0);
+			if (signal_pending(current)) {
+				ret = -ERESTARTSYS;
+				break;
+			}
+		}
+		remove_wait_queue(&events->wait_queue, &wait);
 		if (ret < 0)
 			return ret;
 	}
@@ -434,8 +442,8 @@
 
 		default:
 			fepriv->auto_step++;
-			fepriv->auto_sub_step = -1; /* it'll be incremented to 0 in a moment */
-			break;
+			fepriv->auto_sub_step = 0;
+			continue;
 		}
 
 		if (!ready) fepriv->auto_sub_step++;
@@ -2961,6 +2969,7 @@
 		.name = fe->ops.info.name,
 #endif
 	};
+	int ret;
 
 	dev_dbg(dvb->device, "%s:\n", __func__);
 
@@ -2994,8 +3003,13 @@
 		 "DVB: registering adapter %i frontend %i (%s)...\n",
 		 fe->dvb->num, fe->id, fe->ops.info.name);
 
-	dvb_register_device(fe->dvb, &fepriv->dvbdev, &dvbdev_template,
+	ret = dvb_register_device(fe->dvb, &fepriv->dvbdev, &dvbdev_template,
 			    fe, DVB_DEVICE_FRONTEND, 0);
+	if (ret) {
+		dvb_frontend_put(fe);
+		mutex_unlock(&frontend_mutex);
+		return ret;
+	}
 
 	/*
 	 * Initialize the cache to the proper values according with the
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-core/dvb_net.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-core/dvb_net.c
@@ -45,6 +45,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
+#include <linux/nospec.h>
 #include <linux/etherdevice.h>
 #include <linux/dvb/net.h>
 #include <linux/uio.h>
@@ -1462,14 +1463,20 @@
 		struct net_device *netdev;
 		struct dvb_net_priv *priv_data;
 		struct dvb_net_if *dvbnetif = parg;
+		int if_num = dvbnetif->if_num;
 
-		if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX ||
-		    !dvbnet->state[dvbnetif->if_num]) {
+		if (if_num >= DVB_NET_DEVICES_MAX) {
 			ret = -EINVAL;
 			goto ioctl_error;
 		}
+		if_num = array_index_nospec(if_num, DVB_NET_DEVICES_MAX);
 
-		netdev = dvbnet->device[dvbnetif->if_num];
+		if (!dvbnet->state[if_num]) {
+			ret = -EINVAL;
+			goto ioctl_error;
+		}
+
+		netdev = dvbnet->device[if_num];
 
 		priv_data = netdev_priv(netdev);
 		dvbnetif->pid=priv_data->pid;
@@ -1522,14 +1529,20 @@
 		struct net_device *netdev;
 		struct dvb_net_priv *priv_data;
 		struct __dvb_net_if_old *dvbnetif = parg;
+		int if_num = dvbnetif->if_num;
+
+		if (if_num >= DVB_NET_DEVICES_MAX) {
+			ret = -EINVAL;
+			goto ioctl_error;
+		}
+		if_num = array_index_nospec(if_num, DVB_NET_DEVICES_MAX);
 
-		if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX ||
-		    !dvbnet->state[dvbnetif->if_num]) {
+		if (!dvbnet->state[if_num]) {
 			ret = -EINVAL;
 			goto ioctl_error;
 		}
 
-		netdev = dvbnet->device[dvbnetif->if_num];
+		netdev = dvbnet->device[if_num];
 
 		priv_data = netdev_priv(netdev);
 		dvbnetif->pid=priv_data->pid;
@@ -1551,15 +1564,43 @@
 	return dvb_usercopy(file, cmd, arg, dvb_net_do_ioctl);
 }
 
+static int locked_dvb_net_open(struct inode *inode, struct file *file)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct dvb_net *dvbnet = dvbdev->priv;
+	int ret;
+
+	if (mutex_lock_interruptible(&dvbnet->remove_mutex))
+		return -ERESTARTSYS;
+
+	if (dvbnet->exit) {
+		mutex_unlock(&dvbnet->remove_mutex);
+		return -ENODEV;
+	}
+
+	ret = dvb_generic_open(inode, file);
+
+	mutex_unlock(&dvbnet->remove_mutex);
+
+	return ret;
+}
+
 static int dvb_net_close(struct inode *inode, struct file *file)
 {
 	struct dvb_device *dvbdev = file->private_data;
 	struct dvb_net *dvbnet = dvbdev->priv;
 
+	mutex_lock(&dvbnet->remove_mutex);
+
 	dvb_generic_release(inode, file);
 
-	if(dvbdev->users == 1 && dvbnet->exit == 1)
+	if (dvbdev->users == 1 && dvbnet->exit == 1) {
+		mutex_unlock(&dvbnet->remove_mutex);
 		wake_up(&dvbdev->wait_queue);
+	} else {
+		mutex_unlock(&dvbnet->remove_mutex);
+	}
+
 	return 0;
 }
 
@@ -1567,7 +1608,7 @@
 static const struct file_operations dvb_net_fops = {
 	.owner = THIS_MODULE,
 	.unlocked_ioctl = dvb_net_ioctl,
-	.open =	dvb_generic_open,
+	.open =	locked_dvb_net_open,
 	.release = dvb_net_close,
 	.llseek = noop_llseek,
 };
@@ -1586,10 +1627,13 @@
 {
 	int i;
 
+	mutex_lock(&dvbnet->remove_mutex);
 	dvbnet->exit = 1;
+	mutex_unlock(&dvbnet->remove_mutex);
+
 	if (dvbnet->dvbdev->users < 1)
 		wait_event(dvbnet->dvbdev->wait_queue,
-				dvbnet->dvbdev->users==1);
+				dvbnet->dvbdev->users == 1);
 
 	dvb_unregister_device(dvbnet->dvbdev);
 
@@ -1608,6 +1652,7 @@
 	int i;
 
 	mutex_init(&dvbnet->ioctl_mutex);
+	mutex_init(&dvbnet->remove_mutex);
 	dvbnet->demux = dmx;
 
 	for (i=0; i<DVB_NET_DEVICES_MAX; i++)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-core/dvb_vb2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-core/dvb_vb2.c
@@ -358,6 +358,12 @@
 
 int dvb_vb2_querybuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b)
 {
+	struct vb2_queue *q = &ctx->vb_q;
+
+	if (b->index >= q->num_buffers) {
+		dprintk(1, "[%s] buffer index out of range\n", ctx->name);
+		return -EINVAL;
+	}
 	vb2_core_querybuf(&ctx->vb_q, b->index, b);
 	dprintk(3, "[%s] index=%d\n", ctx->name, b->index);
 	return 0;
@@ -382,8 +388,13 @@
 
 int dvb_vb2_qbuf(struct dvb_vb2_ctx *ctx, struct dmx_buffer *b)
 {
+	struct vb2_queue *q = &ctx->vb_q;
 	int ret;
 
+	if (b->index >= q->num_buffers) {
+		dprintk(1, "[%s] buffer index out of range\n", ctx->name);
+		return -EINVAL;
+	}
 	ret = vb2_core_qbuf(&ctx->vb_q, b->index, b, NULL);
 	if (ret) {
 		dprintk(1, "[%s] index=%d errno=%d\n", ctx->name,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-core/dvbdev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-core/dvbdev.c
@@ -37,6 +37,7 @@
 #include <media/tuner.h>
 
 static DEFINE_MUTEX(dvbdev_mutex);
+static LIST_HEAD(dvbdevfops_list);
 static int dvbdev_debug;
 
 module_param(dvbdev_debug, int, 0644);
@@ -95,10 +96,15 @@
 static int dvb_device_open(struct inode *inode, struct file *file)
 {
 	struct dvb_device *dvbdev;
+	unsigned int minor = iminor(inode);
+
+	if (minor >= MAX_DVB_MINORS)
+		return -ENODEV;
 
 	mutex_lock(&dvbdev_mutex);
 	down_read(&minor_rwsem);
-	dvbdev = dvb_minors[iminor(inode)];
+
+	dvbdev = dvb_minors[minor];
 
 	if (dvbdev && dvbdev->fops) {
 		int err = 0;
@@ -107,12 +113,14 @@
 		new_fops = fops_get(dvbdev->fops);
 		if (!new_fops)
 			goto fail;
-		file->private_data = dvbdev;
+		file->private_data = dvb_device_get(dvbdev);
 		replace_fops(file, new_fops);
 		if (file->f_op->open)
 			err = file->f_op->open(inode, file);
 		up_read(&minor_rwsem);
 		mutex_unlock(&dvbdev_mutex);
+		if (err)
+			dvb_device_put(dvbdev);
 		return err;
 	}
 fail:
@@ -171,6 +179,9 @@
 	}
 
 	dvbdev->users++;
+
+	dvb_device_put(dvbdev);
+
 	return 0;
 }
 EXPORT_SYMBOL(dvb_generic_release);
@@ -241,6 +252,7 @@
 
 	if (dvbdev->adapter->conn) {
 		media_device_unregister_entity(dvbdev->adapter->conn);
+		kfree(dvbdev->adapter->conn);
 		dvbdev->adapter->conn = NULL;
 		kfree(dvbdev->adapter->conn_pads);
 		dvbdev->adapter->conn_pads = NULL;
@@ -341,6 +353,7 @@
 				       GFP_KERNEL);
 		if (!dvbdev->pads) {
 			kfree(dvbdev->entity);
+			dvbdev->entity = NULL;
 			return -ENOMEM;
 		}
 	}
@@ -457,14 +470,15 @@
 			enum dvb_device_type type, int demux_sink_pads)
 {
 	struct dvb_device *dvbdev;
-	struct file_operations *dvbdevfops;
+	struct file_operations *dvbdevfops = NULL;
+	struct dvbdevfops_node *node = NULL, *new_node = NULL;
 	struct device *clsdev;
 	int minor;
 	int id, ret;
 
 	mutex_lock(&dvbdev_register_lock);
 
-	if ((id = dvbdev_get_free_id (adap, type)) < 0){
+	if ((id = dvbdev_get_free_id (adap, type)) < 0) {
 		mutex_unlock(&dvbdev_register_lock);
 		*pdvbdev = NULL;
 		pr_err("%s: couldn't find free device id\n", __func__);
@@ -472,78 +486,124 @@
 	}
 
 	*pdvbdev = dvbdev = kzalloc(sizeof(*dvbdev), GFP_KERNEL);
-
 	if (!dvbdev){
 		mutex_unlock(&dvbdev_register_lock);
 		return -ENOMEM;
 	}
 
-	dvbdevfops = kmemdup(template->fops, sizeof(*dvbdevfops), GFP_KERNEL);
+	/*
+	 * When a device of the same type is probe()d more than once,
+	 * the first allocated fops are used. This prevents memory leaks
+	 * that can occur when the same device is probe()d repeatedly.
+	 */
+	list_for_each_entry(node, &dvbdevfops_list, list_head) {
+		if (node->fops->owner == adap->module &&
+				node->type == type &&
+				node->template == template) {
+			dvbdevfops = node->fops;
+			break;
+		}
+	}
 
-	if (!dvbdevfops){
-		kfree (dvbdev);
-		mutex_unlock(&dvbdev_register_lock);
-		return -ENOMEM;
+	if (dvbdevfops == NULL) {
+		dvbdevfops = kmemdup(template->fops, sizeof(*dvbdevfops), GFP_KERNEL);
+		if (!dvbdevfops) {
+			kfree(dvbdev);
+			*pdvbdev = NULL;
+			mutex_unlock(&dvbdev_register_lock);
+			return -ENOMEM;
+		}
+
+		new_node = kzalloc(sizeof(struct dvbdevfops_node), GFP_KERNEL);
+		if (!new_node) {
+			kfree(dvbdevfops);
+			kfree(dvbdev);
+			*pdvbdev = NULL;
+			mutex_unlock(&dvbdev_register_lock);
+			return -ENOMEM;
+		}
+
+		new_node->fops = dvbdevfops;
+		new_node->type = type;
+		new_node->template = template;
+		list_add_tail (&new_node->list_head, &dvbdevfops_list);
 	}
 
 	memcpy(dvbdev, template, sizeof(struct dvb_device));
+	kref_init(&dvbdev->ref);
 	dvbdev->type = type;
 	dvbdev->id = id;
 	dvbdev->adapter = adap;
 	dvbdev->priv = priv;
 	dvbdev->fops = dvbdevfops;
 	init_waitqueue_head (&dvbdev->wait_queue);
-
 	dvbdevfops->owner = adap->module;
-
 	list_add_tail (&dvbdev->list_head, &adap->device_list);
-
 	down_write(&minor_rwsem);
 #ifdef CONFIG_DVB_DYNAMIC_MINORS
 	for (minor = 0; minor < MAX_DVB_MINORS; minor++)
 		if (dvb_minors[minor] == NULL)
 			break;
-
-	if (minor == MAX_DVB_MINORS) {
-		kfree(dvbdevfops);
+#else
+	minor = nums2minor(adap->num, type, id);
+#endif
+	if (minor >= MAX_DVB_MINORS) {
+		if (new_node) {
+			list_del (&new_node->list_head);
+			kfree(dvbdevfops);
+			kfree(new_node);
+		}
+		list_del (&dvbdev->list_head);
 		kfree(dvbdev);
+		*pdvbdev = NULL;
 		up_write(&minor_rwsem);
 		mutex_unlock(&dvbdev_register_lock);
 		return -EINVAL;
 	}
-#else
-	minor = nums2minor(adap->num, type, id);
-#endif
 
 	dvbdev->minor = minor;
-	dvb_minors[minor] = dvbdev;
+	dvb_minors[minor] = dvb_device_get(dvbdev);
 	up_write(&minor_rwsem);
-
 	ret = dvb_register_media_device(dvbdev, type, minor, demux_sink_pads);
 	if (ret) {
 		pr_err("%s: dvb_register_media_device failed to create the mediagraph\n",
 		      __func__);
-
+		if (new_node) {
+			list_del (&new_node->list_head);
+			kfree(dvbdevfops);
+			kfree(new_node);
+		}
 		dvb_media_device_free(dvbdev);
-		kfree(dvbdevfops);
+		list_del (&dvbdev->list_head);
 		kfree(dvbdev);
+		*pdvbdev = NULL;
 		mutex_unlock(&dvbdev_register_lock);
 		return ret;
 	}
 
-	mutex_unlock(&dvbdev_register_lock);
-
 	clsdev = device_create(dvb_class, adap->device,
 			       MKDEV(DVB_MAJOR, minor),
 			       dvbdev, "dvb%d.%s%d", adap->num, dnames[type], id);
 	if (IS_ERR(clsdev)) {
 		pr_err("%s: failed to create device dvb%d.%s%d (%ld)\n",
 		       __func__, adap->num, dnames[type], id, PTR_ERR(clsdev));
+		if (new_node) {
+			list_del (&new_node->list_head);
+			kfree(dvbdevfops);
+			kfree(new_node);
+		}
+		dvb_media_device_free(dvbdev);
+		list_del (&dvbdev->list_head);
+		kfree(dvbdev);
+		*pdvbdev = NULL;
+		mutex_unlock(&dvbdev_register_lock);
 		return PTR_ERR(clsdev);
 	}
+
 	dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
 		adap->num, dnames[type], id, minor, minor);
 
+	mutex_unlock(&dvbdev_register_lock);
 	return 0;
 }
 EXPORT_SYMBOL(dvb_register_device);
@@ -556,6 +616,7 @@
 
 	down_write(&minor_rwsem);
 	dvb_minors[dvbdev->minor] = NULL;
+	dvb_device_put(dvbdev);
 	up_write(&minor_rwsem);
 
 	dvb_media_device_free(dvbdev);
@@ -567,21 +628,33 @@
 EXPORT_SYMBOL(dvb_remove_device);
 
 
-void dvb_free_device(struct dvb_device *dvbdev)
+static void dvb_free_device(struct kref *ref)
 {
-	if (!dvbdev)
-		return;
+	struct dvb_device *dvbdev = container_of(ref, struct dvb_device, ref);
 
-	kfree (dvbdev->fops);
 	kfree (dvbdev);
 }
-EXPORT_SYMBOL(dvb_free_device);
+
+
+struct dvb_device *dvb_device_get(struct dvb_device *dvbdev)
+{
+	kref_get(&dvbdev->ref);
+	return dvbdev;
+}
+EXPORT_SYMBOL(dvb_device_get);
+
+
+void dvb_device_put(struct dvb_device *dvbdev)
+{
+	if (dvbdev)
+		kref_put(&dvbdev->ref, dvb_free_device);
+}
 
 
 void dvb_unregister_device(struct dvb_device *dvbdev)
 {
 	dvb_remove_device(dvbdev);
-	dvb_free_device(dvbdev);
+	dvb_device_put(dvbdev);
 }
 EXPORT_SYMBOL(dvb_unregister_device);
 
@@ -707,9 +780,10 @@
 	}
 
 	if (ntuner && ndemod) {
-		pad_source = media_get_pad_index(tuner, true,
+		/* NOTE: first found tuner source pad presumed correct */
+		pad_source = media_get_pad_index(tuner, false,
 						 PAD_SIGNAL_ANALOG);
-		if (pad_source)
+		if (pad_source < 0)
 			return -EINVAL;
 		ret = media_create_pad_links(mdev,
 					     MEDIA_ENT_F_TUNER,
@@ -906,7 +980,7 @@
 		     int (*func)(struct file *file,
 		     unsigned int cmd, void *arg))
 {
-	char    sbuf[128];
+	char    sbuf[128] = {};
 	void    *mbuf = NULL;
 	void    *parg = NULL;
 	int     err  = -EINVAL;
@@ -1063,9 +1137,17 @@
 
 static void __exit exit_dvbdev(void)
 {
+	struct dvbdevfops_node *node, *next;
+
 	class_destroy(dvb_class);
 	cdev_del(&dvb_device_cdev);
 	unregister_chrdev_region(MKDEV(DVB_MAJOR, 0), MAX_DVB_MINORS);
+
+	list_for_each_entry_safe(node, next, &dvbdevfops_list, list_head) {
+		list_del (&node->list_head);
+		kfree(node->fops);
+		kfree(node);
+	}
 }
 
 subsys_initcall(init_dvbdev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/as102_fe_types.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/as102_fe_types.h
@@ -174,6 +174,6 @@
 	uint32_t addr;
 	/* register mode access */
 	uint8_t mode;
-};
+} __packed;
 
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/ascot2e.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/ascot2e.c
@@ -533,7 +533,7 @@
 		priv->i2c_address, priv->i2c);
 	return fe;
 }
-EXPORT_SYMBOL(ascot2e_attach);
+EXPORT_SYMBOL_GPL(ascot2e_attach);
 
 MODULE_DESCRIPTION("Sony ASCOT2E terr/cab tuner driver");
 MODULE_AUTHOR("info@netup.ru");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/atbm8830.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/atbm8830.c
@@ -489,7 +489,7 @@
 	return NULL;
 
 }
-EXPORT_SYMBOL(atbm8830_attach);
+EXPORT_SYMBOL_GPL(atbm8830_attach);
 
 MODULE_DESCRIPTION("AltoBeam ATBM8830/8831 GB20600 demodulator driver");
 MODULE_AUTHOR("David T. L. Wong <davidtlwong@gmail.com>");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/au8522_dig.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/au8522_dig.c
@@ -879,7 +879,7 @@
 	au8522_release_state(state);
 	return NULL;
 }
-EXPORT_SYMBOL(au8522_attach);
+EXPORT_SYMBOL_GPL(au8522_attach);
 
 static const struct dvb_frontend_ops au8522_ops = {
 	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/bcm3510.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/bcm3510.c
@@ -649,6 +649,7 @@
 		deb_info("firmware chunk, addr: 0x%04x, len: 0x%04x, total length: 0x%04zx\n",addr,len,fw->size);
 		if ((ret = bcm3510_write_ram(st,addr,&b[i+4],len)) < 0) {
 			err("firmware download failed: %d\n",ret);
+			release_firmware(fw);
 			return ret;
 		}
 		i += 4 + len;
@@ -834,7 +835,7 @@
 	kfree(state);
 	return NULL;
 }
-EXPORT_SYMBOL(bcm3510_attach);
+EXPORT_SYMBOL_GPL(bcm3510_attach);
 
 static const struct dvb_frontend_ops bcm3510_ops = {
 	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/cx22700.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/cx22700.c
@@ -432,4 +432,4 @@
 MODULE_AUTHOR("Holger Waechtler");
 MODULE_LICENSE("GPL");
 
-EXPORT_SYMBOL(cx22700_attach);
+EXPORT_SYMBOL_GPL(cx22700_attach);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/cx22702.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/cx22702.c
@@ -604,7 +604,7 @@
 	kfree(state);
 	return NULL;
 }
-EXPORT_SYMBOL(cx22702_attach);
+EXPORT_SYMBOL_GPL(cx22702_attach);
 
 static const struct dvb_frontend_ops cx22702_ops = {
 	.delsys = { SYS_DVBT },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/cx24110.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/cx24110.c
@@ -653,4 +653,4 @@
 MODULE_AUTHOR("Peter Hettkamp");
 MODULE_LICENSE("GPL");
 
-EXPORT_SYMBOL(cx24110_attach);
+EXPORT_SYMBOL_GPL(cx24110_attach);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/cx24113.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/cx24113.c
@@ -590,7 +590,7 @@
 
 	return NULL;
 }
-EXPORT_SYMBOL(cx24113_attach);
+EXPORT_SYMBOL_GPL(cx24113_attach);
 
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/cx24116.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/cx24116.c
@@ -741,6 +741,7 @@
 {
 	struct cx24116_state *state = fe->demodulator_priv;
 	u8 snr_reading;
+	int ret;
 	static const u32 snr_tab[] = { /* 10 x Table (rounded up) */
 		0x00000, 0x0199A, 0x03333, 0x04ccD, 0x06667,
 		0x08000, 0x0999A, 0x0b333, 0x0cccD, 0x0e667,
@@ -749,7 +750,11 @@
 
 	dprintk("%s()\n", __func__);
 
-	snr_reading = cx24116_readreg(state, CX24116_REG_QUALITY0);
+	ret = cx24116_readreg(state, CX24116_REG_QUALITY0);
+	if (ret  < 0)
+		return ret;
+
+	snr_reading = ret;
 
 	if (snr_reading >= 0xa0 /* 100% */)
 		*snr = 0xffff;
@@ -1133,7 +1138,7 @@
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 }
-EXPORT_SYMBOL(cx24116_attach);
+EXPORT_SYMBOL_GPL(cx24116_attach);
 
 /*
  * Initialise or wake up device
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/cx24120.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/cx24120.c
@@ -305,7 +305,7 @@
 	kfree(state);
 	return NULL;
 }
-EXPORT_SYMBOL(cx24120_attach);
+EXPORT_SYMBOL_GPL(cx24120_attach);
 
 static int cx24120_test_rom(struct cx24120_state *state)
 {
@@ -972,7 +972,9 @@
 	cmd.arg[8] = (clock_ratios_table[idx].rate >> 8) & 0xff;
 	cmd.arg[9] = (clock_ratios_table[idx].rate >> 0) & 0xff;
 
-	cx24120_message_send(state, &cmd);
+	ret = cx24120_message_send(state, &cmd);
+	if (ret != 0)
+		return;
 
 	/* Calculate ber window rates for stat work */
 	cx24120_calculate_ber_window(state, clock_ratios_table[idx].rate);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/cx24123.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/cx24123.c
@@ -1096,7 +1096,7 @@
 
 	return NULL;
 }
-EXPORT_SYMBOL(cx24123_attach);
+EXPORT_SYMBOL_GPL(cx24123_attach);
 
 static const struct dvb_frontend_ops cx24123_ops = {
 	.delsys = { SYS_DVBS },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/cxd2820r_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/cxd2820r_core.c
@@ -536,7 +536,7 @@
 
 	return pdata.get_dvb_frontend(client);
 }
-EXPORT_SYMBOL(cxd2820r_attach);
+EXPORT_SYMBOL_GPL(cxd2820r_attach);
 
 static struct dvb_frontend *cxd2820r_get_dvb_frontend(struct i2c_client *client)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/cxd2841er.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/cxd2841er.c
@@ -310,12 +310,8 @@
 
 static u32 cxd2841er_calc_iffreq_xtal(enum cxd2841er_xtal xtal, u32 ifhz)
 {
-	u64 tmp;
-
-	tmp = (u64) ifhz * 16777216;
-	do_div(tmp, ((xtal == SONY_XTAL_24000) ? 48000000 : 41000000));
-
-	return (u32) tmp;
+	return div_u64(ifhz * 16777216ull,
+		       (xtal == SONY_XTAL_24000) ? 48000000 : 41000000);
 }
 
 static u32 cxd2841er_calc_iffreq(u32 ifhz)
@@ -3920,14 +3916,14 @@
 {
 	return cxd2841er_attach(cfg, i2c, SYS_DVBS);
 }
-EXPORT_SYMBOL(cxd2841er_attach_s);
+EXPORT_SYMBOL_GPL(cxd2841er_attach_s);
 
 struct dvb_frontend *cxd2841er_attach_t_c(struct cxd2841er_config *cfg,
 					struct i2c_adapter *i2c)
 {
 	return cxd2841er_attach(cfg, i2c, 0);
 }
-EXPORT_SYMBOL(cxd2841er_attach_t_c);
+EXPORT_SYMBOL_GPL(cxd2841er_attach_t_c);
 
 static const struct dvb_frontend_ops cxd2841er_dvbs_s2_ops = {
 	.delsys = { SYS_DVBS, SYS_DVBS2 },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/cxd2880/cxd2880_top.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/cxd2880/cxd2880_top.c
@@ -1950,7 +1950,7 @@
 
 	return fe;
 }
-EXPORT_SYMBOL(cxd2880_attach);
+EXPORT_SYMBOL_GPL(cxd2880_attach);
 
 MODULE_DESCRIPTION("Sony CXD2880 DVB-T2/T tuner + demod driver");
 MODULE_AUTHOR("Sony Semiconductor Solutions Corporation");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/dib0070.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/dib0070.c
@@ -755,7 +755,7 @@
 	fe->tuner_priv = NULL;
 	return NULL;
 }
-EXPORT_SYMBOL(dib0070_attach);
+EXPORT_SYMBOL_GPL(dib0070_attach);
 
 MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
 MODULE_DESCRIPTION("Driver for the DiBcom 0070 base-band RF Tuner");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/dib0090.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/dib0090.c
@@ -2631,7 +2631,7 @@
 	return NULL;
 }
 
-EXPORT_SYMBOL(dib0090_register);
+EXPORT_SYMBOL_GPL(dib0090_register);
 
 struct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
 {
@@ -2657,7 +2657,7 @@
 	fe->tuner_priv = NULL;
 	return NULL;
 }
-EXPORT_SYMBOL(dib0090_fw_register);
+EXPORT_SYMBOL_GPL(dib0090_fw_register);
 
 MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
 MODULE_AUTHOR("Olivier Grenie <olivier.grenie@parrot.com>");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/dib3000mb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/dib3000mb.c
@@ -51,7 +51,7 @@
 static int dib3000_read_reg(struct dib3000_state *state, u16 reg)
 {
 	u8 wb[] = { ((reg >> 8) | 0x80) & 0xff, reg & 0xff };
-	u8 rb[2];
+	u8 rb[2] = {};
 	struct i2c_msg msg[] = {
 		{ .addr = state->config.demod_address, .flags = 0,        .buf = wb, .len = 2 },
 		{ .addr = state->config.demod_address, .flags = I2C_M_RD, .buf = rb, .len = 2 },
@@ -815,4 +815,4 @@
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
-EXPORT_SYMBOL(dib3000mb_attach);
+EXPORT_SYMBOL_GPL(dib3000mb_attach);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/dib3000mc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/dib3000mc.c
@@ -935,7 +935,7 @@
 	kfree(st);
 	return NULL;
 }
-EXPORT_SYMBOL(dib3000mc_attach);
+EXPORT_SYMBOL_GPL(dib3000mc_attach);
 
 static const struct dvb_frontend_ops dib3000mc_ops = {
 	.delsys = { SYS_DVBT },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/dib7000m.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/dib7000m.c
@@ -1434,7 +1434,7 @@
 	kfree(st);
 	return NULL;
 }
-EXPORT_SYMBOL(dib7000m_attach);
+EXPORT_SYMBOL_GPL(dib7000m_attach);
 
 static const struct dvb_frontend_ops dib7000m_ops = {
 	.delsys = { SYS_DVBT },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/dib7000p.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/dib7000p.c
@@ -497,7 +497,7 @@
 	prediv = reg_1856 & 0x3f;
 	loopdiv = (reg_1856 >> 6) & 0x3f;
 
-	if ((bw != NULL) && (bw->pll_prediv != prediv || bw->pll_ratio != loopdiv)) {
+	if (loopdiv && bw && (bw->pll_prediv != prediv || bw->pll_ratio != loopdiv)) {
 		dprintk("Updating pll (prediv: old =  %d new = %d ; loopdiv : old = %d new = %d)\n", prediv, bw->pll_prediv, loopdiv, bw->pll_ratio);
 		reg_1856 &= 0xf000;
 		reg_1857 = dib7000p_read_word(state, 1857);
@@ -2822,7 +2822,7 @@
 
 	return ops;
 }
-EXPORT_SYMBOL(dib7000p_attach);
+EXPORT_SYMBOL_GPL(dib7000p_attach);
 
 static const struct dvb_frontend_ops dib7000p_ops = {
 	.delsys = { SYS_DVBT },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/dib8000.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/dib8000.c
@@ -2107,32 +2107,55 @@
 			dib8000_write_word(state, 117 + mode, ana_fe[mode]);
 }
 
-static const u16 lut_prbs_2k[14] = {
-	0, 0x423, 0x009, 0x5C7, 0x7A6, 0x3D8, 0x527, 0x7FF, 0x79B, 0x3D6, 0x3A2, 0x53B, 0x2F4, 0x213
+static const u16 lut_prbs_2k[13] = {
+	0x423, 0x009, 0x5C7,
+	0x7A6, 0x3D8, 0x527,
+	0x7FF, 0x79B, 0x3D6,
+	0x3A2, 0x53B, 0x2F4,
+	0x213
 };
-static const u16 lut_prbs_4k[14] = {
-	0, 0x208, 0x0C3, 0x7B9, 0x423, 0x5C7, 0x3D8, 0x7FF, 0x3D6, 0x53B, 0x213, 0x029, 0x0D0, 0x48E
+
+static const u16 lut_prbs_4k[13] = {
+	0x208, 0x0C3, 0x7B9,
+	0x423, 0x5C7, 0x3D8,
+	0x7FF, 0x3D6, 0x53B,
+	0x213, 0x029, 0x0D0,
+	0x48E
 };
-static const u16 lut_prbs_8k[14] = {
-	0, 0x740, 0x069, 0x7DD, 0x208, 0x7B9, 0x5C7, 0x7FF, 0x53B, 0x029, 0x48E, 0x4C4, 0x367, 0x684
+
+static const u16 lut_prbs_8k[13] = {
+	0x740, 0x069, 0x7DD,
+	0x208, 0x7B9, 0x5C7,
+	0x7FF, 0x53B, 0x029,
+	0x48E, 0x4C4, 0x367,
+	0x684
 };
 
 static u16 dib8000_get_init_prbs(struct dib8000_state *state, u16 subchannel)
 {
 	int sub_channel_prbs_group = 0;
+	int prbs_group;
 
-	sub_channel_prbs_group = (subchannel / 3) + 1;
-	dprintk("sub_channel_prbs_group = %d , subchannel =%d prbs = 0x%04x\n", sub_channel_prbs_group, subchannel, lut_prbs_8k[sub_channel_prbs_group]);
+	sub_channel_prbs_group = subchannel / 3;
+	if (sub_channel_prbs_group >= ARRAY_SIZE(lut_prbs_2k))
+		return 0;
 
 	switch (state->fe[0]->dtv_property_cache.transmission_mode) {
 	case TRANSMISSION_MODE_2K:
-			return lut_prbs_2k[sub_channel_prbs_group];
+		prbs_group = lut_prbs_2k[sub_channel_prbs_group];
+		break;
 	case TRANSMISSION_MODE_4K:
-			return lut_prbs_4k[sub_channel_prbs_group];
+		prbs_group =  lut_prbs_4k[sub_channel_prbs_group];
+		break;
 	default:
 	case TRANSMISSION_MODE_8K:
-			return lut_prbs_8k[sub_channel_prbs_group];
+		prbs_group = lut_prbs_8k[sub_channel_prbs_group];
 	}
+
+	dprintk("sub_channel_prbs_group = %d , subchannel =%d prbs = 0x%04x\n",
+		sub_channel_prbs_group, subchannel, prbs_group);
+
+	return prbs_group;
 }
 
 static void dib8000_set_13seg_channel(struct dib8000_state *state)
@@ -2409,10 +2432,8 @@
 	/* TSB or ISDBT ? apply it now */
 	if (c->isdbt_sb_mode) {
 		dib8000_set_sb_channel(state);
-		if (c->isdbt_sb_subchannel < 14)
-			init_prbs = dib8000_get_init_prbs(state, c->isdbt_sb_subchannel);
-		else
-			init_prbs = 0;
+		init_prbs = dib8000_get_init_prbs(state,
+						  c->isdbt_sb_subchannel);
 	} else {
 		dib8000_set_13seg_channel(state);
 		init_prbs = 0xfff;
@@ -2680,8 +2701,11 @@
 	u8 ratio;
 
 	if (state->revision == 0x8090) {
+		u32 internal = dib8000_read32(state, 23) / 1000;
+
 		ratio = 4;
-		unit_khz_dds_val = (1<<26) / (dib8000_read32(state, 23) / 1000);
+
+		unit_khz_dds_val = (1<<26) / (internal ?: 1);
 		if (offset_khz < 0)
 			dds = (1 << 26) - (abs_offset_khz * unit_khz_dds_val);
 		else
@@ -3004,6 +3028,7 @@
 
 	unsigned long *timeout = &state->timeout;
 	unsigned long now = jiffies;
+	u16 init_prbs;
 #ifdef DIB8000_AGC_FREEZE
 	u16 agc1, agc2;
 #endif
@@ -3302,8 +3327,10 @@
 		break;
 
 	case CT_DEMOD_STEP_11:  /* 41 : init prbs autosearch */
-		if (state->subchannel <= 41) {
-			dib8000_set_subchannel_prbs(state, dib8000_get_init_prbs(state, state->subchannel));
+		init_prbs = dib8000_get_init_prbs(state, state->subchannel);
+
+		if (init_prbs) {
+			dib8000_set_subchannel_prbs(state, init_prbs);
 			*tune_state = CT_DEMOD_STEP_9;
 		} else {
 			*tune_state = CT_DEMOD_STOP;
@@ -4449,8 +4476,10 @@
 
 	state->timf_default = cfg->pll->timf;
 
-	if (dib8000_identify(&state->i2c) == 0)
+	if (dib8000_identify(&state->i2c) == 0) {
+		kfree(fe);
 		goto error;
+	}
 
 	dibx000_init_i2c_master(&state->i2c_master, DIB8000, state->i2c.adap, state->i2c.addr);
 
@@ -4501,7 +4530,7 @@
 
 	return ops;
 }
-EXPORT_SYMBOL(dib8000_attach);
+EXPORT_SYMBOL_GPL(dib8000_attach);
 
 MODULE_AUTHOR("Olivier Grenie <Olivier.Grenie@parrot.com, Patrick Boettcher <patrick.boettcher@posteo.de>");
 MODULE_DESCRIPTION("Driver for the DiBcom 8000 ISDB-T demodulator");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/dib9000.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/dib9000.c
@@ -2546,7 +2546,7 @@
 	kfree(st);
 	return NULL;
 }
-EXPORT_SYMBOL(dib9000_attach);
+EXPORT_SYMBOL_GPL(dib9000_attach);
 
 static const struct dvb_frontend_ops dib9000_ops = {
 	.delsys = { SYS_DVBT },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/drx39xyj/drxj.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/drx39xyj/drxj.c
@@ -12366,7 +12366,7 @@
 
 	return NULL;
 }
-EXPORT_SYMBOL(drx39xxj_attach);
+EXPORT_SYMBOL_GPL(drx39xxj_attach);
 
 static const struct dvb_frontend_ops drx39xxj_ops = {
 	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/drxd_hard.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/drxd_hard.c
@@ -2948,7 +2948,7 @@
 	kfree(state);
 	return NULL;
 }
-EXPORT_SYMBOL(drxd_attach);
+EXPORT_SYMBOL_GPL(drxd_attach);
 
 MODULE_DESCRIPTION("DRXD driver");
 MODULE_AUTHOR("Micronas");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/drxk_hard.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/drxk_hard.c
@@ -6684,7 +6684,7 @@
 static int drxk_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
 {
 	struct drxk_state *state = fe->demodulator_priv;
-	u16 err;
+	u16 err = 0;
 
 	dprintk(1, "\n");
 
@@ -6857,7 +6857,7 @@
 	kfree(state);
 	return NULL;
 }
-EXPORT_SYMBOL(drxk_attach);
+EXPORT_SYMBOL_GPL(drxk_attach);
 
 MODULE_DESCRIPTION("DRX-K driver");
 MODULE_AUTHOR("Ralph Metzler");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/ds3000.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/ds3000.c
@@ -859,7 +859,7 @@
 	ds3000_set_voltage(&state->frontend, SEC_VOLTAGE_OFF);
 	return &state->frontend;
 }
-EXPORT_SYMBOL(ds3000_attach);
+EXPORT_SYMBOL_GPL(ds3000_attach);
 
 static int ds3000_set_carrier_offset(struct dvb_frontend *fe,
 					s32 carrier_offset_khz)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/dvb-pll.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/dvb-pll.c
@@ -866,7 +866,7 @@
 
 	return NULL;
 }
-EXPORT_SYMBOL(dvb_pll_attach);
+EXPORT_SYMBOL_GPL(dvb_pll_attach);
 
 
 static int
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/ec100.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/ec100.c
@@ -299,7 +299,7 @@
 	kfree(state);
 	return NULL;
 }
-EXPORT_SYMBOL(ec100_attach);
+EXPORT_SYMBOL_GPL(ec100_attach);
 
 static const struct dvb_frontend_ops ec100_ops = {
 	.delsys = { SYS_DVBT },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/helene.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/helene.c
@@ -1025,7 +1025,7 @@
 			priv->i2c_address, priv->i2c);
 	return fe;
 }
-EXPORT_SYMBOL(helene_attach_s);
+EXPORT_SYMBOL_GPL(helene_attach_s);
 
 struct dvb_frontend *helene_attach(struct dvb_frontend *fe,
 		const struct helene_config *config,
@@ -1061,7 +1061,7 @@
 			priv->i2c_address, priv->i2c);
 	return fe;
 }
-EXPORT_SYMBOL(helene_attach);
+EXPORT_SYMBOL_GPL(helene_attach);
 
 static int helene_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/horus3a.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/horus3a.c
@@ -395,7 +395,7 @@
 		priv->i2c_address, priv->i2c);
 	return fe;
 }
-EXPORT_SYMBOL(horus3a_attach);
+EXPORT_SYMBOL_GPL(horus3a_attach);
 
 MODULE_DESCRIPTION("Sony HORUS3A satellite tuner driver");
 MODULE_AUTHOR("Sergey Kozlov <serjk@netup.ru>");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/isl6405.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/isl6405.c
@@ -141,7 +141,7 @@
 
 	return fe;
 }
-EXPORT_SYMBOL(isl6405_attach);
+EXPORT_SYMBOL_GPL(isl6405_attach);
 
 MODULE_DESCRIPTION("Driver for lnb supply and control ic isl6405");
 MODULE_AUTHOR("Hartmut Hackmann & Oliver Endriss");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/isl6421.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/isl6421.c
@@ -213,7 +213,7 @@
 
 	return fe;
 }
-EXPORT_SYMBOL(isl6421_attach);
+EXPORT_SYMBOL_GPL(isl6421_attach);
 
 MODULE_DESCRIPTION("Driver for lnb supply and control ic isl6421");
 MODULE_AUTHOR("Andrew de Quincey & Oliver Endriss");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/isl6423.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/isl6423.c
@@ -289,7 +289,7 @@
 	fe->sec_priv = NULL;
 	return NULL;
 }
-EXPORT_SYMBOL(isl6423_attach);
+EXPORT_SYMBOL_GPL(isl6423_attach);
 
 MODULE_DESCRIPTION("ISL6423 SEC");
 MODULE_AUTHOR("Manu Abraham");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/itd1000.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/itd1000.c
@@ -389,7 +389,7 @@
 
 	return fe;
 }
-EXPORT_SYMBOL(itd1000_attach);
+EXPORT_SYMBOL_GPL(itd1000_attach);
 
 MODULE_AUTHOR("Patrick Boettcher <pb@linuxtv.org>");
 MODULE_DESCRIPTION("Integrant ITD1000 driver");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/ix2505v.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/ix2505v.c
@@ -302,7 +302,7 @@
 	kfree(state);
 	return NULL;
 }
-EXPORT_SYMBOL(ix2505v_attach);
+EXPORT_SYMBOL_GPL(ix2505v_attach);
 
 module_param_named(debug, ix2505v_debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/l64781.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/l64781.c
@@ -593,4 +593,4 @@
 MODULE_AUTHOR("Holger Waechtler, Marko Kohtala");
 MODULE_LICENSE("GPL");
 
-EXPORT_SYMBOL(l64781_attach);
+EXPORT_SYMBOL_GPL(l64781_attach);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/lg2160.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/lg2160.c
@@ -1426,7 +1426,7 @@
 
 	return &state->frontend;
 }
-EXPORT_SYMBOL(lg2160_attach);
+EXPORT_SYMBOL_GPL(lg2160_attach);
 
 MODULE_DESCRIPTION("LG Electronics LG216x ATSC/MH Demodulator Driver");
 MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/lgdt3305.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/lgdt3305.c
@@ -1148,7 +1148,7 @@
 	kfree(state);
 	return NULL;
 }
-EXPORT_SYMBOL(lgdt3305_attach);
+EXPORT_SYMBOL_GPL(lgdt3305_attach);
 
 static const struct dvb_frontend_ops lgdt3304_ops = {
 	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/lgdt3306a.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/lgdt3306a.c
@@ -1881,7 +1881,7 @@
 	kfree(state);
 	return NULL;
 }
-EXPORT_SYMBOL(lgdt3306a_attach);
+EXPORT_SYMBOL_GPL(lgdt3306a_attach);
 
 #ifdef DBG_DUMP
 
@@ -2199,6 +2199,11 @@
 	struct dvb_frontend *fe;
 	int ret;
 
+	if (!client->dev.platform_data) {
+		dev_err(&client->dev, "platform data is mandatory\n");
+		return -EINVAL;
+	}
+
 	config = kmemdup(client->dev.platform_data,
 			 sizeof(struct lgdt3306a_config), GFP_KERNEL);
 	if (config == NULL) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/lgdt330x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/lgdt330x.c
@@ -928,7 +928,7 @@
 
 	return lgdt330x_get_dvb_frontend(client);
 }
-EXPORT_SYMBOL(lgdt330x_attach);
+EXPORT_SYMBOL_GPL(lgdt330x_attach);
 
 static const struct dvb_frontend_ops lgdt3302_ops = {
 	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/lgs8gxx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/lgs8gxx.c
@@ -1043,7 +1043,7 @@
 	return NULL;
 
 }
-EXPORT_SYMBOL(lgs8gxx_attach);
+EXPORT_SYMBOL_GPL(lgs8gxx_attach);
 
 MODULE_DESCRIPTION("Legend Silicon LGS8913/LGS8GXX DMB-TH demodulator driver");
 MODULE_AUTHOR("David T. L. Wong <davidtlwong@gmail.com>");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/lnbh25.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/lnbh25.c
@@ -173,7 +173,7 @@
 		__func__, priv->i2c_address);
 	return fe;
 }
-EXPORT_SYMBOL(lnbh25_attach);
+EXPORT_SYMBOL_GPL(lnbh25_attach);
 
 MODULE_DESCRIPTION("ST LNBH25 driver");
 MODULE_AUTHOR("info@netup.ru");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/lnbp21.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/lnbp21.c
@@ -155,7 +155,7 @@
 	return lnbx2x_attach(fe, i2c, override_set, override_clear,
 							i2c_addr, LNBH24_TTX);
 }
-EXPORT_SYMBOL(lnbh24_attach);
+EXPORT_SYMBOL_GPL(lnbh24_attach);
 
 struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe,
 				struct i2c_adapter *i2c, u8 override_set,
@@ -164,7 +164,7 @@
 	return lnbx2x_attach(fe, i2c, override_set, override_clear,
 							0x08, LNBP21_ISEL);
 }
-EXPORT_SYMBOL(lnbp21_attach);
+EXPORT_SYMBOL_GPL(lnbp21_attach);
 
 MODULE_DESCRIPTION("Driver for lnb supply and control ic lnbp21, lnbh24");
 MODULE_AUTHOR("Oliver Endriss, Igor M. Liplianin");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/lnbp22.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/lnbp22.c
@@ -125,7 +125,7 @@
 
 	return fe;
 }
-EXPORT_SYMBOL(lnbp22_attach);
+EXPORT_SYMBOL_GPL(lnbp22_attach);
 
 MODULE_DESCRIPTION("Driver for lnb supply and control ic lnbp22");
 MODULE_AUTHOR("Dominik Kuhlen");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/m88ds3103.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/m88ds3103.c
@@ -1284,7 +1284,7 @@
 	*tuner_i2c_adapter = pdata.get_i2c_adapter(client);
 	return pdata.get_dvb_frontend(client);
 }
-EXPORT_SYMBOL(m88ds3103_attach);
+EXPORT_SYMBOL_GPL(m88ds3103_attach);
 
 static const struct dvb_frontend_ops m88ds3103_ops = {
 	.delsys = {SYS_DVBS, SYS_DVBS2},
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/m88rs2000.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/m88rs2000.c
@@ -807,7 +807,7 @@
 
 	return NULL;
 }
-EXPORT_SYMBOL(m88rs2000_attach);
+EXPORT_SYMBOL_GPL(m88rs2000_attach);
 
 MODULE_DESCRIPTION("M88RS2000 DVB-S Demodulator driver");
 MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/mb86a16.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/mb86a16.c
@@ -1851,6 +1851,6 @@
 	kfree(state);
 	return NULL;
 }
-EXPORT_SYMBOL(mb86a16_attach);
+EXPORT_SYMBOL_GPL(mb86a16_attach);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Manu Abraham");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/mb86a20s.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/mb86a20s.c
@@ -2089,7 +2089,7 @@
 	dev_info(&i2c->dev, "Detected a Fujitsu mb86a20s frontend\n");
 	return &state->frontend;
 }
-EXPORT_SYMBOL(mb86a20s_attach);
+EXPORT_SYMBOL_GPL(mb86a20s_attach);
 
 static const struct dvb_frontend_ops mb86a20s_ops = {
 	.delsys = { SYS_ISDBT },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/mn88443x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/mn88443x.c
@@ -204,11 +204,18 @@
 	struct regmap *regmap_t;
 };
 
-static void mn88443x_cmn_power_on(struct mn88443x_priv *chip)
+static int mn88443x_cmn_power_on(struct mn88443x_priv *chip)
 {
+	struct device *dev = &chip->client_s->dev;
 	struct regmap *r_t = chip->regmap_t;
+	int ret;
 
-	clk_prepare_enable(chip->mclk);
+	ret = clk_prepare_enable(chip->mclk);
+	if (ret) {
+		dev_err(dev, "Failed to prepare and enable mclk: %d\n",
+			ret);
+		return ret;
+	}
 
 	gpiod_set_value_cansleep(chip->reset_gpio, 1);
 	usleep_range(100, 1000);
@@ -222,6 +229,8 @@
 	} else {
 		regmap_write(r_t, HIZSET3, 0x8f);
 	}
+
+	return 0;
 }
 
 static void mn88443x_cmn_power_off(struct mn88443x_priv *chip)
@@ -738,7 +747,10 @@
 	chip->fe.demodulator_priv = chip;
 	i2c_set_clientdata(client, chip);
 
-	mn88443x_cmn_power_on(chip);
+	ret = mn88443x_cmn_power_on(chip);
+	if (ret)
+		goto err_i2c_t;
+
 	mn88443x_s_sleep(chip);
 	mn88443x_t_sleep(chip);
 
@@ -788,7 +800,7 @@
 static struct i2c_driver mn88443x_driver = {
 	.driver = {
 		.name = "mn88443x",
-		.of_match_table = of_match_ptr(mn88443x_of_match),
+		.of_match_table = mn88443x_of_match,
 	},
 	.probe    = mn88443x_probe,
 	.remove   = mn88443x_remove,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/mt312.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/mt312.c
@@ -832,7 +832,7 @@
 	kfree(state);
 	return NULL;
 }
-EXPORT_SYMBOL(mt312_attach);
+EXPORT_SYMBOL_GPL(mt312_attach);
 
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/mt352.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/mt352.c
@@ -593,4 +593,4 @@
 MODULE_AUTHOR("Holger Waechtler, Daniel Mack, Antonio Mancuso");
 MODULE_LICENSE("GPL");
 
-EXPORT_SYMBOL(mt352_attach);
+EXPORT_SYMBOL_GPL(mt352_attach);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/mxl5xx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/mxl5xx.c
@@ -1391,57 +1391,57 @@
 	u32 nco_count_min = 0;
 	u32 clk_type = 0;
 
-	struct MXL_REG_FIELD_T xpt_sync_polarity[MXL_HYDRA_DEMOD_MAX] = {
+	static const struct MXL_REG_FIELD_T xpt_sync_polarity[MXL_HYDRA_DEMOD_MAX] = {
 		{0x90700010, 8, 1}, {0x90700010, 9, 1},
 		{0x90700010, 10, 1}, {0x90700010, 11, 1},
 		{0x90700010, 12, 1}, {0x90700010, 13, 1},
 		{0x90700010, 14, 1}, {0x90700010, 15, 1} };
-	struct MXL_REG_FIELD_T xpt_clock_polarity[MXL_HYDRA_DEMOD_MAX] = {
+	static const struct MXL_REG_FIELD_T xpt_clock_polarity[MXL_HYDRA_DEMOD_MAX] = {
 		{0x90700010, 16, 1}, {0x90700010, 17, 1},
 		{0x90700010, 18, 1}, {0x90700010, 19, 1},
 		{0x90700010, 20, 1}, {0x90700010, 21, 1},
 		{0x90700010, 22, 1}, {0x90700010, 23, 1} };
-	struct MXL_REG_FIELD_T xpt_valid_polarity[MXL_HYDRA_DEMOD_MAX] = {
+	static const struct MXL_REG_FIELD_T xpt_valid_polarity[MXL_HYDRA_DEMOD_MAX] = {
 		{0x90700014, 0, 1}, {0x90700014, 1, 1},
 		{0x90700014, 2, 1}, {0x90700014, 3, 1},
 		{0x90700014, 4, 1}, {0x90700014, 5, 1},
 		{0x90700014, 6, 1}, {0x90700014, 7, 1} };
-	struct MXL_REG_FIELD_T xpt_ts_clock_phase[MXL_HYDRA_DEMOD_MAX] = {
+	static const struct MXL_REG_FIELD_T xpt_ts_clock_phase[MXL_HYDRA_DEMOD_MAX] = {
 		{0x90700018, 0, 3}, {0x90700018, 4, 3},
 		{0x90700018, 8, 3}, {0x90700018, 12, 3},
 		{0x90700018, 16, 3}, {0x90700018, 20, 3},
 		{0x90700018, 24, 3}, {0x90700018, 28, 3} };
-	struct MXL_REG_FIELD_T xpt_lsb_first[MXL_HYDRA_DEMOD_MAX] = {
+	static const struct MXL_REG_FIELD_T xpt_lsb_first[MXL_HYDRA_DEMOD_MAX] = {
 		{0x9070000C, 16, 1}, {0x9070000C, 17, 1},
 		{0x9070000C, 18, 1}, {0x9070000C, 19, 1},
 		{0x9070000C, 20, 1}, {0x9070000C, 21, 1},
 		{0x9070000C, 22, 1}, {0x9070000C, 23, 1} };
-	struct MXL_REG_FIELD_T xpt_sync_byte[MXL_HYDRA_DEMOD_MAX] = {
+	static const struct MXL_REG_FIELD_T xpt_sync_byte[MXL_HYDRA_DEMOD_MAX] = {
 		{0x90700010, 0, 1}, {0x90700010, 1, 1},
 		{0x90700010, 2, 1}, {0x90700010, 3, 1},
 		{0x90700010, 4, 1}, {0x90700010, 5, 1},
 		{0x90700010, 6, 1}, {0x90700010, 7, 1} };
-	struct MXL_REG_FIELD_T xpt_enable_output[MXL_HYDRA_DEMOD_MAX] = {
+	static const struct MXL_REG_FIELD_T xpt_enable_output[MXL_HYDRA_DEMOD_MAX] = {
 		{0x9070000C, 0, 1}, {0x9070000C, 1, 1},
 		{0x9070000C, 2, 1}, {0x9070000C, 3, 1},
 		{0x9070000C, 4, 1}, {0x9070000C, 5, 1},
 		{0x9070000C, 6, 1}, {0x9070000C, 7, 1} };
-	struct MXL_REG_FIELD_T xpt_err_replace_sync[MXL_HYDRA_DEMOD_MAX] = {
+	static const struct MXL_REG_FIELD_T xpt_err_replace_sync[MXL_HYDRA_DEMOD_MAX] = {
 		{0x9070000C, 24, 1}, {0x9070000C, 25, 1},
 		{0x9070000C, 26, 1}, {0x9070000C, 27, 1},
 		{0x9070000C, 28, 1}, {0x9070000C, 29, 1},
 		{0x9070000C, 30, 1}, {0x9070000C, 31, 1} };
-	struct MXL_REG_FIELD_T xpt_err_replace_valid[MXL_HYDRA_DEMOD_MAX] = {
+	static const struct MXL_REG_FIELD_T xpt_err_replace_valid[MXL_HYDRA_DEMOD_MAX] = {
 		{0x90700014, 8, 1}, {0x90700014, 9, 1},
 		{0x90700014, 10, 1}, {0x90700014, 11, 1},
 		{0x90700014, 12, 1}, {0x90700014, 13, 1},
 		{0x90700014, 14, 1}, {0x90700014, 15, 1} };
-	struct MXL_REG_FIELD_T xpt_continuous_clock[MXL_HYDRA_DEMOD_MAX] = {
+	static const struct MXL_REG_FIELD_T xpt_continuous_clock[MXL_HYDRA_DEMOD_MAX] = {
 		{0x907001D4, 0, 1}, {0x907001D4, 1, 1},
 		{0x907001D4, 2, 1}, {0x907001D4, 3, 1},
 		{0x907001D4, 4, 1}, {0x907001D4, 5, 1},
 		{0x907001D4, 6, 1}, {0x907001D4, 7, 1} };
-	struct MXL_REG_FIELD_T xpt_nco_clock_rate[MXL_HYDRA_DEMOD_MAX] = {
+	static const struct MXL_REG_FIELD_T xpt_nco_clock_rate[MXL_HYDRA_DEMOD_MAX] = {
 		{0x90700044, 16, 80}, {0x90700044, 16, 81},
 		{0x90700044, 16, 82}, {0x90700044, 16, 83},
 		{0x90700044, 16, 84}, {0x90700044, 16, 85},
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/nxt200x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/nxt200x.c
@@ -1232,5 +1232,5 @@
 MODULE_AUTHOR("Kirk Lapray, Michael Krufky, Jean-Francois Thibert, and Taylor Jacob");
 MODULE_LICENSE("GPL");
 
-EXPORT_SYMBOL(nxt200x_attach);
+EXPORT_SYMBOL_GPL(nxt200x_attach);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/nxt6000.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/nxt6000.c
@@ -621,4 +621,4 @@
 MODULE_AUTHOR("Florian Schirmer");
 MODULE_LICENSE("GPL");
 
-EXPORT_SYMBOL(nxt6000_attach);
+EXPORT_SYMBOL_GPL(nxt6000_attach);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/or51132.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/or51132.c
@@ -605,4 +605,4 @@
 MODULE_AUTHOR("Trent Piepho");
 MODULE_LICENSE("GPL");
 
-EXPORT_SYMBOL(or51132_attach);
+EXPORT_SYMBOL_GPL(or51132_attach);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/or51211.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/or51211.c
@@ -551,5 +551,5 @@
 MODULE_AUTHOR("Kirk Lapray");
 MODULE_LICENSE("GPL");
 
-EXPORT_SYMBOL(or51211_attach);
+EXPORT_SYMBOL_GPL(or51211_attach);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/rtl2830.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/rtl2830.c
@@ -609,7 +609,7 @@
 		index, pid, onoff);
 
 	/* skip invalid PIDs (0x2000) */
-	if (pid > 0x1fff || index > 32)
+	if (pid > 0x1fff || index >= 32)
 		return 0;
 
 	if (onoff)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/rtl2832.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/rtl2832.c
@@ -640,7 +640,7 @@
 	struct i2c_client *client = dev->client;
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 	int ret;
-	u32 uninitialized_var(tmp);
+	u32 tmp;
 	u8 u8tmp, buf[2];
 	u16 u16tmp;
 
@@ -982,7 +982,7 @@
 		index, pid, onoff, dev->slave_ts);
 
 	/* skip invalid PIDs (0x2000) */
-	if (pid > 0x1fff || index > 32)
+	if (pid > 0x1fff || index >= 32)
 		return 0;
 
 	if (onoff)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/s5h1409.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/s5h1409.c
@@ -981,7 +981,7 @@
 	kfree(state);
 	return NULL;
 }
-EXPORT_SYMBOL(s5h1409_attach);
+EXPORT_SYMBOL_GPL(s5h1409_attach);
 
 static const struct dvb_frontend_ops s5h1409_ops = {
 	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/s5h1411.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/s5h1411.c
@@ -900,7 +900,7 @@
 	kfree(state);
 	return NULL;
 }
-EXPORT_SYMBOL(s5h1411_attach);
+EXPORT_SYMBOL_GPL(s5h1411_attach);
 
 static const struct dvb_frontend_ops s5h1411_ops = {
 	.delsys = { SYS_ATSC, SYS_DVBC_ANNEX_B },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/s5h1420.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/s5h1420.c
@@ -918,7 +918,7 @@
 	kfree(state);
 	return NULL;
 }
-EXPORT_SYMBOL(s5h1420_attach);
+EXPORT_SYMBOL_GPL(s5h1420_attach);
 
 static const struct dvb_frontend_ops s5h1420_ops = {
 	.delsys = { SYS_DVBS },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/s5h1432.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/s5h1432.c
@@ -355,7 +355,7 @@
 
 	return &state->frontend;
 }
-EXPORT_SYMBOL(s5h1432_attach);
+EXPORT_SYMBOL_GPL(s5h1432_attach);
 
 static const struct dvb_frontend_ops s5h1432_ops = {
 	.delsys = { SYS_DVBT },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/s921.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/s921.c
@@ -495,7 +495,7 @@
 
 	return &state->frontend;
 }
-EXPORT_SYMBOL(s921_attach);
+EXPORT_SYMBOL_GPL(s921_attach);
 
 static const struct dvb_frontend_ops s921_ops = {
 	.delsys = { SYS_ISDBT },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/si21xx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/si21xx.c
@@ -938,7 +938,7 @@
 	kfree(state);
 	return NULL;
 }
-EXPORT_SYMBOL(si21xx_attach);
+EXPORT_SYMBOL_GPL(si21xx_attach);
 
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/sp8870.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/sp8870.c
@@ -281,7 +281,7 @@
 
 	// read status reg in order to clear pending irqs
 	err = sp8870_readreg(state, 0x200);
-	if (err)
+	if (err < 0)
 		return err;
 
 	// system controller start
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/sp887x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/sp887x.c
@@ -626,4 +626,4 @@
 MODULE_DESCRIPTION("Spase sp887x DVB-T demodulator driver");
 MODULE_LICENSE("GPL");
 
-EXPORT_SYMBOL(sp887x_attach);
+EXPORT_SYMBOL_GPL(sp887x_attach);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/stb0899_algo.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/stb0899_algo.c
@@ -269,7 +269,7 @@
 
 	short int derot_freq = 0, last_derot_freq = 0, derot_limit, next_loop = 3;
 	int index = 0;
-	u8 cfr[2];
+	u8 cfr[2] = {0};
 	u8 reg;
 
 	internal->status = NOCARRIER;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/stb0899_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/stb0899_drv.c
@@ -1638,7 +1638,7 @@
 	kfree(state);
 	return NULL;
 }
-EXPORT_SYMBOL(stb0899_attach);
+EXPORT_SYMBOL_GPL(stb0899_attach);
 MODULE_PARM_DESC(verbose, "Set Verbosity level");
 MODULE_AUTHOR("Manu Abraham");
 MODULE_DESCRIPTION("STB0899 Multi-Std frontend");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/stb6000.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/stb6000.c
@@ -232,7 +232,7 @@
 
 	return fe;
 }
-EXPORT_SYMBOL(stb6000_attach);
+EXPORT_SYMBOL_GPL(stb6000_attach);
 
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/stb6100.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/stb6100.c
@@ -557,7 +557,7 @@
 	kfree(state);
 }
 
-EXPORT_SYMBOL(stb6100_attach);
+EXPORT_SYMBOL_GPL(stb6100_attach);
 MODULE_PARM_DESC(verbose, "Set Verbosity level");
 
 MODULE_AUTHOR("Manu Abraham");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/stv0288.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/stv0288.c
@@ -440,9 +440,8 @@
 	struct stv0288_state *state = fe->demodulator_priv;
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 
-	char tm;
-	unsigned char tda[3];
-	u8 reg, time_out = 0;
+	u8 tda[3], reg, time_out = 0;
+	s8 tm;
 
 	dprintk("%s : FE_SET_FRONTEND\n", __func__);
 
@@ -591,7 +590,7 @@
 
 	return NULL;
 }
-EXPORT_SYMBOL(stv0288_attach);
+EXPORT_SYMBOL_GPL(stv0288_attach);
 
 module_param(debug_legacy_dish_switch, int, 0444);
 MODULE_PARM_DESC(debug_legacy_dish_switch,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/stv0297.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/stv0297.c
@@ -710,4 +710,4 @@
 MODULE_AUTHOR("Dennis Noermann and Andrew de Quincey");
 MODULE_LICENSE("GPL");
 
-EXPORT_SYMBOL(stv0297_attach);
+EXPORT_SYMBOL_GPL(stv0297_attach);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/stv0299.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/stv0299.c
@@ -751,4 +751,4 @@
 MODULE_AUTHOR("Ralph Metzler, Holger Waechtler, Peter Schildmann, Felix Domke, Andreas Oberritter, Andrew de Quincey, Kenneth Aafly");
 MODULE_LICENSE("GPL");
 
-EXPORT_SYMBOL(stv0299_attach);
+EXPORT_SYMBOL_GPL(stv0299_attach);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/stv0367.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/stv0367.c
@@ -118,50 +118,32 @@
 	}
 };
 
-static
-int stv0367_writeregs(struct stv0367_state *state, u16 reg, u8 *data, int len)
+static noinline_for_stack
+int stv0367_writereg(struct stv0367_state *state, u16 reg, u8 data)
 {
-	u8 buf[MAX_XFER_SIZE];
+	u8 buf[3] = { MSB(reg), LSB(reg), data };
 	struct i2c_msg msg = {
 		.addr = state->config->demod_address,
 		.flags = 0,
 		.buf = buf,
-		.len = len + 2
+		.len = 3,
 	};
 	int ret;
 
-	if (2 + len > sizeof(buf)) {
-		printk(KERN_WARNING
-		       "%s: i2c wr reg=%04x: len=%d is too big!\n",
-		       KBUILD_MODNAME, reg, len);
-		return -EINVAL;
-	}
-
-
-	buf[0] = MSB(reg);
-	buf[1] = LSB(reg);
-	memcpy(buf + 2, data, len);
-
 	if (i2cdebug)
 		printk(KERN_DEBUG "%s: [%02x] %02x: %02x\n", __func__,
-			state->config->demod_address, reg, buf[2]);
+			state->config->demod_address, reg, data);
 
 	ret = i2c_transfer(state->i2c, &msg, 1);
 	if (ret != 1)
 		printk(KERN_ERR "%s: i2c write error! ([%02x] %02x: %02x)\n",
-			__func__, state->config->demod_address, reg, buf[2]);
+			__func__, state->config->demod_address, reg, data);
 
 	return (ret != 1) ? -EREMOTEIO : 0;
 }
 
-static int stv0367_writereg(struct stv0367_state *state, u16 reg, u8 data)
-{
-	u8 tmp = data; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
-
-	return stv0367_writeregs(state, reg, &tmp, 1);
-}
-
-static u8 stv0367_readreg(struct stv0367_state *state, u16 reg)
+static noinline_for_stack
+u8 stv0367_readreg(struct stv0367_state *state, u16 reg)
 {
 	u8 b0[] = { 0, 0 };
 	u8 b1[] = { 0 };
@@ -1750,7 +1732,7 @@
 	kfree(state);
 	return NULL;
 }
-EXPORT_SYMBOL(stv0367ter_attach);
+EXPORT_SYMBOL_GPL(stv0367ter_attach);
 
 static int stv0367cab_gate_ctrl(struct dvb_frontend *fe, int enable)
 {
@@ -2923,7 +2905,7 @@
 	kfree(state);
 	return NULL;
 }
-EXPORT_SYMBOL(stv0367cab_attach);
+EXPORT_SYMBOL_GPL(stv0367cab_attach);
 
 /*
  * Functions for operation on Digital Devices hardware
@@ -3344,7 +3326,7 @@
 	kfree(state);
 	return NULL;
 }
-EXPORT_SYMBOL(stv0367ddb_attach);
+EXPORT_SYMBOL_GPL(stv0367ddb_attach);
 
 MODULE_PARM_DESC(debug, "Set debug");
 MODULE_PARM_DESC(i2c_debug, "Set i2c debug");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/stv0900_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/stv0900_core.c
@@ -1957,7 +1957,7 @@
 	kfree(state);
 	return NULL;
 }
-EXPORT_SYMBOL(stv0900_attach);
+EXPORT_SYMBOL_GPL(stv0900_attach);
 
 MODULE_PARM_DESC(debug, "Set debug");
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/stv090x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/stv090x.c
@@ -5073,7 +5073,7 @@
 	kfree(state);
 	return NULL;
 }
-EXPORT_SYMBOL(stv090x_attach);
+EXPORT_SYMBOL_GPL(stv090x_attach);
 
 static const struct i2c_device_id stv090x_id_table[] = {
 	{"stv090x", 0},
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/stv6110.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/stv6110.c
@@ -427,7 +427,7 @@
 
 	return fe;
 }
-EXPORT_SYMBOL(stv6110_attach);
+EXPORT_SYMBOL_GPL(stv6110_attach);
 
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/stv6110x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/stv6110x.c
@@ -469,7 +469,7 @@
 	dev_info(&stv6110x->i2c->dev, "Attaching STV6110x\n");
 	return stv6110x->devctl;
 }
-EXPORT_SYMBOL(stv6110x_attach);
+EXPORT_SYMBOL_GPL(stv6110x_attach);
 
 static const struct i2c_device_id stv6110x_id_table[] = {
 	{"stv6110x", 0},
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/tda10021.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/tda10021.c
@@ -513,4 +513,4 @@
 MODULE_AUTHOR("Ralph Metzler, Holger Waechtler, Markus Schulz");
 MODULE_LICENSE("GPL");
 
-EXPORT_SYMBOL(tda10021_attach);
+EXPORT_SYMBOL_GPL(tda10021_attach);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/tda10023.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/tda10023.c
@@ -594,4 +594,4 @@
 MODULE_AUTHOR("Georg Acher, Hartmut Birr");
 MODULE_LICENSE("GPL");
 
-EXPORT_SYMBOL(tda10023_attach);
+EXPORT_SYMBOL_GPL(tda10023_attach);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/tda10048.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/tda10048.c
@@ -410,6 +410,7 @@
 	struct tda10048_config *config = &state->config;
 	int i;
 	u32 if_freq_khz;
+	u64 sample_freq;
 
 	dprintk(1, "%s(bw = %d)\n", __func__, bw);
 
@@ -451,9 +452,11 @@
 	dprintk(1, "- pll_pfactor = %d\n", state->pll_pfactor);
 
 	/* Calculate the sample frequency */
-	state->sample_freq = state->xtal_hz * (state->pll_mfactor + 45);
-	state->sample_freq /= (state->pll_nfactor + 1);
-	state->sample_freq /= (state->pll_pfactor + 4);
+	sample_freq = state->xtal_hz;
+	sample_freq *= state->pll_mfactor + 45;
+	do_div(sample_freq, state->pll_nfactor + 1);
+	do_div(sample_freq, state->pll_pfactor + 4);
+	state->sample_freq = sample_freq;
 	dprintk(1, "- sample_freq = %d\n", state->sample_freq);
 
 	/* Update the I/F */
@@ -1138,7 +1141,7 @@
 	kfree(state);
 	return NULL;
 }
-EXPORT_SYMBOL(tda10048_attach);
+EXPORT_SYMBOL_GPL(tda10048_attach);
 
 static const struct dvb_frontend_ops tda10048_ops = {
 	.delsys = { SYS_DVBT },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/tda1004x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/tda1004x.c
@@ -1378,5 +1378,5 @@
 MODULE_AUTHOR("Andrew de Quincey & Robert Schlabbach");
 MODULE_LICENSE("GPL");
 
-EXPORT_SYMBOL(tda10045_attach);
-EXPORT_SYMBOL(tda10046_attach);
+EXPORT_SYMBOL_GPL(tda10045_attach);
+EXPORT_SYMBOL_GPL(tda10046_attach);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/tda10071.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/tda10071.c
@@ -470,10 +470,11 @@
 			goto error;
 
 		if (dev->delivery_system == SYS_DVBS) {
-			dev->dvbv3_ber = buf[0] << 24 | buf[1] << 16 |
-					 buf[2] << 8 | buf[3] << 0;
-			dev->post_bit_error += buf[0] << 24 | buf[1] << 16 |
-					       buf[2] << 8 | buf[3] << 0;
+			u32 bit_error = buf[0] << 24 | buf[1] << 16 |
+					buf[2] << 8 | buf[3] << 0;
+
+			dev->dvbv3_ber = bit_error;
+			dev->post_bit_error += bit_error;
 			c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
 			c->post_bit_error.stat[0].uvalue = dev->post_bit_error;
 			dev->block_error += buf[4] << 8 | buf[5] << 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/tda10086.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/tda10086.c
@@ -764,4 +764,4 @@
 MODULE_AUTHOR("Andrew de Quincey");
 MODULE_LICENSE("GPL");
 
-EXPORT_SYMBOL(tda10086_attach);
+EXPORT_SYMBOL_GPL(tda10086_attach);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/tda18271c2dd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/tda18271c2dd.c
@@ -331,7 +331,7 @@
 
 	OscFreq = (u64) freq * (u64) Div;
 	OscFreq *= (u64) 16384;
-	do_div(OscFreq, (u64)16000000);
+	do_div(OscFreq, 16000000);
 	MainDiv = OscFreq;
 
 	state->m_Regs[MPD] = PostDiv & 0x77;
@@ -355,7 +355,7 @@
 	OscFreq = (u64)freq * (u64)Div;
 	/* CalDiv = u32( OscFreq * 16384 / 16000000 ); */
 	OscFreq *= (u64)16384;
-	do_div(OscFreq, (u64)16000000);
+	do_div(OscFreq, 16000000);
 	CalDiv = OscFreq;
 
 	state->m_Regs[CPD] = PostDiv;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/tda665x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/tda665x.c
@@ -227,7 +227,7 @@
 
 	return fe;
 }
-EXPORT_SYMBOL(tda665x_attach);
+EXPORT_SYMBOL_GPL(tda665x_attach);
 
 MODULE_DESCRIPTION("TDA665x driver");
 MODULE_AUTHOR("Manu Abraham");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/tda8083.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/tda8083.c
@@ -481,4 +481,4 @@
 MODULE_AUTHOR("Ralph Metzler, Holger Waechtler");
 MODULE_LICENSE("GPL");
 
-EXPORT_SYMBOL(tda8083_attach);
+EXPORT_SYMBOL_GPL(tda8083_attach);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/tda8261.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/tda8261.c
@@ -188,7 +188,7 @@
 	return NULL;
 }
 
-EXPORT_SYMBOL(tda8261_attach);
+EXPORT_SYMBOL_GPL(tda8261_attach);
 
 MODULE_AUTHOR("Manu Abraham");
 MODULE_DESCRIPTION("TDA8261 8PSK/QPSK Tuner");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/tda826x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/tda826x.c
@@ -164,7 +164,7 @@
 
 	return fe;
 }
-EXPORT_SYMBOL(tda826x_attach);
+EXPORT_SYMBOL_GPL(tda826x_attach);
 
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/ts2020.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/ts2020.c
@@ -525,7 +525,7 @@
 
 	return fe;
 }
-EXPORT_SYMBOL(ts2020_attach);
+EXPORT_SYMBOL_GPL(ts2020_attach);
 
 /*
  * We implement own regmap locking due to legacy DVB attach which uses frontend
@@ -554,13 +554,19 @@
 		const struct i2c_device_id *id)
 {
 	struct ts2020_config *pdata = client->dev.platform_data;
-	struct dvb_frontend *fe = pdata->fe;
+	struct dvb_frontend *fe;
 	struct ts2020_priv *dev;
 	int ret;
 	u8 u8tmp;
 	unsigned int utmp;
 	char *chip_str;
 
+	if (!pdata) {
+		dev_err(&client->dev, "platform data is mandatory\n");
+		return -EINVAL;
+	}
+
+	fe = pdata->fe;
 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 	if (!dev) {
 		ret = -ENOMEM;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/tua6100.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/tua6100.c
@@ -186,7 +186,7 @@
 	fe->tuner_priv = priv;
 	return fe;
 }
-EXPORT_SYMBOL(tua6100_attach);
+EXPORT_SYMBOL_GPL(tua6100_attach);
 
 MODULE_DESCRIPTION("DVB tua6100 driver");
 MODULE_AUTHOR("Andrew de Quincey");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/ves1820.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/ves1820.c
@@ -434,4 +434,4 @@
 MODULE_AUTHOR("Ralph Metzler, Holger Waechtler");
 MODULE_LICENSE("GPL");
 
-EXPORT_SYMBOL(ves1820_attach);
+EXPORT_SYMBOL_GPL(ves1820_attach);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/ves1x93.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/ves1x93.c
@@ -540,4 +540,4 @@
 MODULE_AUTHOR("Ralph Metzler");
 MODULE_LICENSE("GPL");
 
-EXPORT_SYMBOL(ves1x93_attach);
+EXPORT_SYMBOL_GPL(ves1x93_attach);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/zl10036.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/zl10036.c
@@ -496,7 +496,7 @@
 	kfree(state);
 	return NULL;
 }
-EXPORT_SYMBOL(zl10036_attach);
+EXPORT_SYMBOL_GPL(zl10036_attach);
 
 module_param_named(debug, zl10036_debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/zl10039.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/zl10039.c
@@ -295,7 +295,7 @@
 	kfree(state);
 	return NULL;
 }
-EXPORT_SYMBOL(zl10039_attach);
+EXPORT_SYMBOL_GPL(zl10039_attach);
 
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/dvb-frontends/zl10353.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/dvb-frontends/zl10353.c
@@ -665,4 +665,4 @@
 MODULE_AUTHOR("Chris Pascoe");
 MODULE_LICENSE("GPL");
 
-EXPORT_SYMBOL(zl10353_attach);
+EXPORT_SYMBOL_GPL(zl10353_attach);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/firewire/firedtv-avc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/firewire/firedtv-avc.c
@@ -1165,7 +1165,11 @@
 		read_pos += program_info_length;
 		write_pos += program_info_length;
 	}
-	while (read_pos < length) {
+	while (read_pos + 4 < length) {
+		if (write_pos + 4 >= sizeof(c->operand) - 4) {
+			ret = -EINVAL;
+			goto out;
+		}
 		c->operand[write_pos++] = msg[read_pos++];
 		c->operand[write_pos++] = msg[read_pos++];
 		c->operand[write_pos++] = msg[read_pos++];
@@ -1177,13 +1181,17 @@
 		c->operand[write_pos++] = es_info_length >> 8;
 		c->operand[write_pos++] = es_info_length & 0xff;
 		if (es_info_length > 0) {
+			if (read_pos >= length) {
+				ret = -EINVAL;
+				goto out;
+			}
 			pmt_cmd_id = msg[read_pos++];
 			if (pmt_cmd_id != 1 && pmt_cmd_id != 4)
 				dev_err(fdtv->device, "invalid pmt_cmd_id %d at stream level\n",
 					pmt_cmd_id);
 
-			if (es_info_length > sizeof(c->operand) - 4 -
-					     write_pos) {
+			if (es_info_length > sizeof(c->operand) - 4 - write_pos ||
+			    es_info_length > length - read_pos) {
 				ret = -EINVAL;
 				goto out;
 			}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/firewire/firedtv-ci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/firewire/firedtv-ci.c
@@ -134,6 +134,8 @@
 	} else {
 		data_length = msg->msg[3];
 	}
+	if (data_length > sizeof(msg->msg) - data_pos)
+		return -EINVAL;
 
 	return avc_ca_pmt(fdtv, &msg->msg[data_pos], data_length);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/firewire/firedtv-fw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/firewire/firedtv-fw.c
@@ -272,6 +272,10 @@
 
 	name_len = fw_csr_string(unit->directory, CSR_MODEL,
 				 name, sizeof(name));
+	if (name_len < 0) {
+		err = name_len;
+		goto fail_free;
+	}
 	for (i = ARRAY_SIZE(model_names); --i; )
 		if (strlen(model_names[i]) <= name_len &&
 		    strncmp(name, model_names[i], name_len) == 0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/Kconfig
@@ -1095,6 +1095,17 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called upd64083.
 
+config VIDEO_AP1302
+	tristate "ON Semiconductor AP1302 support"
+	depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+	select V4L2_FWNODE
+	help
+	  This is a Video4Linux2 sensor-level driver for the ON Semiconductor
+	  AP1302 ISP.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ap1302.
+
 comment "Audio/Video compression chips"
 
 config VIDEO_SAA6752HS
@@ -1113,6 +1124,7 @@
 config SDR_MAX2175
 	tristate "Maxim 2175 RF to Bits tuner"
 	depends on VIDEO_V4L2 && MEDIA_SDR_SUPPORT && I2C
+	select REGMAP_I2C
 	help
 	  Support for Maxim 2175 tuner. It is an advanced analog/digital
 	  radio receiver with RF-to-Bits front-end designed for SDR solutions.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/Makefile
@@ -63,6 +63,7 @@
 obj-$(CONFIG_VIDEO_SONY_BTF_MPX) += sony-btf-mpx.o
 obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o
 obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o
+obj-$(CONFIG_VIDEO_AP1302) += ap1302.o
 obj-$(CONFIG_VIDEO_OV2640) += ov2640.o
 obj-$(CONFIG_VIDEO_OV2680) += ov2680.o
 obj-$(CONFIG_VIDEO_OV2685) += ov2685.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/ad5820.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/ad5820.c
@@ -309,22 +309,23 @@
 	v4l2_i2c_subdev_init(&coil->subdev, client, &ad5820_ops);
 	coil->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
 	coil->subdev.internal_ops = &ad5820_internal_ops;
+	coil->subdev.entity.function = MEDIA_ENT_F_LENS;
 	strscpy(coil->subdev.name, "ad5820 focus", sizeof(coil->subdev.name));
 
 	ret = media_entity_pads_init(&coil->subdev.entity, 0, NULL);
 	if (ret < 0)
-		goto cleanup2;
+		goto clean_mutex;
 
 	ret = v4l2_async_register_subdev(&coil->subdev);
 	if (ret < 0)
-		goto cleanup;
+		goto clean_entity;
 
 	return ret;
 
-cleanup2:
-	mutex_destroy(&coil->power_lock);
-cleanup:
+clean_entity:
 	media_entity_cleanup(&coil->subdev.entity);
+clean_mutex:
+	mutex_destroy(&coil->power_lock);
 	return ret;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/adv748x/adv748x.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/adv748x/adv748x.h
@@ -394,10 +394,10 @@
 
 #define io_read(s, r) adv748x_read(s, ADV748X_PAGE_IO, r)
 #define io_write(s, r, v) adv748x_write(s, ADV748X_PAGE_IO, r, v)
-#define io_clrset(s, r, m, v) io_write(s, r, (io_read(s, r) & ~m) | v)
+#define io_clrset(s, r, m, v) io_write(s, r, (io_read(s, r) & ~(m)) | (v))
 
 #define hdmi_read(s, r) adv748x_read(s, ADV748X_PAGE_HDMI, r)
-#define hdmi_read16(s, r, m) (((hdmi_read(s, r) << 8) | hdmi_read(s, r+1)) & m)
+#define hdmi_read16(s, r, m) (((hdmi_read(s, r) << 8) | hdmi_read(s, (r)+1)) & (m))
 #define hdmi_write(s, r, v) adv748x_write(s, ADV748X_PAGE_HDMI, r, v)
 
 #define repeater_read(s, r) adv748x_read(s, ADV748X_PAGE_REPEATER, r)
@@ -405,11 +405,11 @@
 
 #define sdp_read(s, r) adv748x_read(s, ADV748X_PAGE_SDP, r)
 #define sdp_write(s, r, v) adv748x_write(s, ADV748X_PAGE_SDP, r, v)
-#define sdp_clrset(s, r, m, v) sdp_write(s, r, (sdp_read(s, r) & ~m) | v)
+#define sdp_clrset(s, r, m, v) sdp_write(s, r, (sdp_read(s, r) & ~(m)) | (v))
 
 #define cp_read(s, r) adv748x_read(s, ADV748X_PAGE_CP, r)
 #define cp_write(s, r, v) adv748x_write(s, ADV748X_PAGE_CP, r, v)
-#define cp_clrset(s, r, m, v) cp_write(s, r, (cp_read(s, r) & ~m) | v)
+#define cp_clrset(s, r, m, v) cp_write(s, r, (cp_read(s, r) & ~(m)) | (v))
 
 #define tx_read(t, r) adv748x_read(t->state, t->page, r)
 #define tx_write(t, r, v) adv748x_write(t->state, t->page, r, v)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/adv7511-v4l2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/adv7511-v4l2.c
@@ -52,6 +52,7 @@
 #define ADV7511_MAX_HEIGHT 1200
 #define ADV7511_MIN_PIXELCLOCK 20000000
 #define ADV7511_MAX_PIXELCLOCK 225000000
+#define XYLON_LOGICVC_INTG
 
 #define ADV7511_MAX_ADDRS (3)
 
@@ -79,7 +80,50 @@
 	bool complete;
 };
 
+struct adv7511_in_params {
+	uint8_t input_id;
+	uint8_t input_style;
+	uint8_t input_color_depth;
+	uint8_t bit_justification;
+	uint8_t hsync_polarity;
+	uint8_t vsync_polarity;
+	uint8_t clock_delay;
+};
+
+struct adv7511_csc_coeff {
+	uint16_t a1;
+	uint16_t a2;
+	uint16_t a3;
+	uint16_t a4;
+	uint16_t b1;
+	uint16_t b2;
+	uint16_t b3;
+	uint16_t b4;
+	uint16_t c1;
+	uint16_t c2;
+	uint16_t c3;
+	uint16_t c4;
+};
+
+struct adv7511_out_params {
+	bool hdmi_mode;
+	uint8_t output_format;
+	uint8_t output_color_space;
+	uint8_t up_conversion;
+	uint8_t csc_enable;
+	uint8_t csc_scaling_factor;
+	struct adv7511_csc_coeff csc_coeff;
+};
+
+struct adv7511_config {
+	struct adv7511_in_params in_params;
+	struct adv7511_out_params out_params;
+	bool embedded_sync;
+	bool loaded;
+};
+
 struct adv7511_state {
+	struct adv7511_config cfg;
 	struct adv7511_platform_data pdata;
 	struct v4l2_subdev sd;
 	struct media_pad pad;
@@ -379,6 +423,10 @@
 {
 	struct adv7511_state *state = get_adv7511_state(sd);
 
+#ifdef XYLON_LOGICVC_INTG
+	return 0;
+#endif
+
 	/* Only makes sense for RGB formats */
 	if (state->fmt_code != MEDIA_BUS_FMT_RGB888_1X24) {
 		/* so just keep quantization */
@@ -555,7 +603,7 @@
 	buffer[3] = 0;
 	buffer[3] = hdmi_infoframe_checksum(buffer, len + 4);
 
-	if (hdmi_infoframe_unpack(&frame, buffer, sizeof(buffer)) < 0) {
+	if (hdmi_infoframe_unpack(&frame, buffer, len + 4) < 0) {
 		v4l2_err(sd, "%s: unpack of %s infoframe failed\n", __func__, cri->desc);
 		return;
 	}
@@ -1527,34 +1575,278 @@
 	adv7511_s_routing(sd, 0, 0, 0);
 }
 
+static void adv7511_set_ofdt_config(struct v4l2_subdev *sd)
+{
+	struct adv7511_state *state = get_adv7511_state(sd);
+	struct adv7511_config *config = &state->cfg;
+	uint8_t val_mask, val;
+	v4l2_dbg(1, debug, sd, "%s\n", __func__);
+
+	/* Input format */
+	val_mask = 0;
+	switch (config->in_params.input_id) {
+	default:
+	case 0:
+		val = 0x00;
+		break;
+	case 1:
+		val = 0x01;
+		break;
+	case 2:
+		val = 0x02;
+		config->embedded_sync = true;
+		break;
+	case 3:
+		val = 0x03;
+		break;
+	case 4:
+		val = 0x04;
+		config->embedded_sync = true;
+		break;
+	case 5:
+		val = 0x05;
+		break;
+	case 6:
+		val = 0x06;
+		break;
+	case 7:
+		val = 0x07;
+		break;
+	case 8:
+		val = 0x08;
+		config->embedded_sync = true;
+		break;
+	}
+	val_mask |= val;
+	adv7511_wr(sd, 0x15, val_mask);
+
+	/* Output format */
+	val_mask = 0;
+	switch (config->out_params.output_color_space) {
+	default:
+	case 0:
+		val = 0x00;
+		break;
+	case 1:
+		val = 0x01;
+		break;
+	}
+	val_mask |= (val << 0);
+	switch (config->in_params.input_style) {
+	case 1:
+		val = 0x02;
+		break;
+	case 2:
+		val = 0x01;
+		break;
+	case 3:
+		val = 0x03;
+		break;
+	default:
+		val = 0x00;
+		break;
+	}
+	val_mask |= (val << 2);
+	switch (config->in_params.input_color_depth) {
+	case 8:
+		val = 0x03;
+		break;
+	case 10:
+		val = 0x01;
+		break;
+	case 12:
+		val = 0x02;
+		break;
+	default:
+		val = 0x00;
+		break;
+	}
+	val_mask |= (val << 4);
+	switch (config->out_params.output_format) {
+	default:
+	case 0:
+		val = 0x00;
+		break;
+	case 1:
+		val = 0x01;
+		break;
+	}
+	val_mask |= (val << 7);
+	adv7511_wr(sd, 0x16, val_mask);
+
+	/* H, V sync polarity, interpolation style */
+	val_mask = 0;
+	switch (config->out_params.up_conversion) {
+	default:
+	case 0:
+		val = 0x00;
+		break;
+	case 1:
+		val = 0x01;
+		break;
+	}
+	val_mask |= (val << 2);
+	switch (config->in_params.hsync_polarity) {
+	default:
+	case 0:
+		val = 0x00;
+		break;
+	case 1:
+		val = 0x01;
+		break;
+	}
+	val_mask |= (val << 5);
+	switch (config->in_params.vsync_polarity) {
+	default:
+	case 0:
+		val = 0x00;
+		break;
+	case 1:
+		val = 0x01;
+		break;
+	}
+	val_mask |= (val << 6);
+	adv7511_wr(sd, 0x17, val_mask);
+
+	/* CSC mode, CSC coefficients */
+	if (config->out_params.csc_enable) {
+		switch (config->out_params.csc_scaling_factor) {
+		case 1:
+			val = 0x00;
+			break;
+		case 2:
+			val = 0x01;
+			break;
+		case 4:
+		default:
+			val = 0x02;
+			break;
+		}
+		adv7511_csc_conversion_mode(sd, val);
+		adv7511_csc_coeff(sd,
+				  config->out_params.csc_coeff.a1,
+				  config->out_params.csc_coeff.a2,
+				  config->out_params.csc_coeff.a3,
+				  config->out_params.csc_coeff.a4,
+				  config->out_params.csc_coeff.b1,
+				  config->out_params.csc_coeff.b2,
+				  config->out_params.csc_coeff.b3,
+				  config->out_params.csc_coeff.b4,
+				  config->out_params.csc_coeff.c1,
+				  config->out_params.csc_coeff.c2,
+				  config->out_params.csc_coeff.c3,
+				  config->out_params.csc_coeff.c4);
+		/* enable CSC */
+		adv7511_wr_and_or(sd, 0x18, 0x7f, 0x80);
+		/* AVI infoframe: Limited range RGB (16-235) */
+		adv7511_wr_and_or(sd, 0x57, 0xf3, 0x04);
+	}
+
+	/* AVI Info, Audio Info */
+	adv7511_wr_and_or(sd, 0x44, 0xe7, 0x10);
+
+	/* Video input justification */
+	val_mask = 0;
+	switch (config->in_params.bit_justification) {
+	default:
+	case 0:
+		val = 0x00;
+		break;
+	case 1:
+		val = 0x01;
+		break;
+	case 2:
+		val = 0x02;
+		break;
+	}
+	val_mask |= (val << 3);
+	adv7511_wr(sd, 0x48, val_mask);
+
+	/* Output format */
+	val_mask = 0x00;
+	if (config->out_params.output_format == 1) {
+		if (config->out_params.output_color_space == 0)
+			val_mask = 0x02;
+		else if (config->out_params.output_format == 1)
+			val_mask = 0x01;
+	}
+	val_mask <<= 5;
+	adv7511_wr(sd, 0x55, val_mask);
+
+	/* Picture format aspect ratio */
+	adv7511_wr(sd, 0x56, 0x28);
+
+	/* HDCP, Frame encryption, HDMI/DVI */
+	val_mask = 0x04;
+	if (config->out_params.hdmi_mode)
+		val_mask |= 0x02;
+	adv7511_wr(sd, 0xaf, val_mask);
+
+	/* Capture for input video clock */
+	val_mask = 0;
+	switch (config->in_params.clock_delay) {
+	default:
+	case 0:
+		val = 0x00;
+		break;
+	case 1:
+		val = 0x01;
+		break;
+	case 2:
+		val = 0x02;
+		break;
+	case 3:
+		val = 0x03;
+		break;
+	case 4:
+		val = 0x04;
+		break;
+	case 5:
+		val = 0x05;
+		break;
+	case 6:
+		val = 0x06;
+		break;
+	case 7:
+		val = 0x07;
+		break;
+	}
+	val_mask |= (val << 5);
+	adv7511_wr_and_or(sd, 0xba, 0x1f, val_mask);
+}
+
 /* Configure hdmi transmitter. */
 static void adv7511_setup(struct v4l2_subdev *sd)
 {
 	struct adv7511_state *state = get_adv7511_state(sd);
 	v4l2_dbg(1, debug, sd, "%s\n", __func__);
 
-	/* Input format: RGB 4:4:4 */
-	adv7511_wr_and_or(sd, 0x15, 0xf0, 0x0);
-	/* Output format: RGB 4:4:4 */
-	adv7511_wr_and_or(sd, 0x16, 0x7f, 0x0);
-	/* 1st order interpolation 4:2:2 -> 4:4:4 up conversion, Aspect ratio: 16:9 */
-	adv7511_wr_and_or(sd, 0x17, 0xf9, 0x06);
-	/* Disable pixel repetition */
-	adv7511_wr_and_or(sd, 0x3b, 0x9f, 0x0);
-	/* Disable CSC */
-	adv7511_wr_and_or(sd, 0x18, 0x7f, 0x0);
-	/* Output format: RGB 4:4:4, Active Format Information is valid,
-	 * underscanned */
-	adv7511_wr_and_or(sd, 0x55, 0x9c, 0x12);
-	/* AVI Info frame packet enable, Audio Info frame disable */
-	adv7511_wr_and_or(sd, 0x44, 0xe7, 0x10);
-	/* Colorimetry, Active format aspect ratio: same as picure. */
-	adv7511_wr(sd, 0x56, 0xa8);
-	/* No encryption */
-	adv7511_wr_and_or(sd, 0xaf, 0xed, 0x0);
+	if (!state->cfg.loaded) {
+		/* Input format: RGB 4:4:4 */
+		adv7511_wr_and_or(sd, 0x15, 0xf0, 0x0);
+		/* Output format: RGB 4:4:4 */
+		adv7511_wr_and_or(sd, 0x16, 0x7f, 0x0);
+		/* 1st order interpolation 4:2:2 -> 4:4:4 up conversion, Aspect ratio: 16:9 */
+		adv7511_wr_and_or(sd, 0x17, 0xf9, 0x06);
+		/* Disable pixel repetition */
+		adv7511_wr_and_or(sd, 0x3b, 0x9f, 0x0);
+		/* Disable CSC */
+		adv7511_wr_and_or(sd, 0x18, 0x7f, 0x0);
+		/* Output format: RGB 4:4:4, Active Format Information is valid,
+		* underscanned */
+		adv7511_wr_and_or(sd, 0x55, 0x9c, 0x12);
+		/* AVI Info frame packet enable, Audio Info frame disable */
+		adv7511_wr_and_or(sd, 0x44, 0xe7, 0x10);
+		/* Colorimetry, Active format aspect ratio: same as picure. */
+		adv7511_wr(sd, 0x56, 0xa8);
+		/* No encryption */
+		adv7511_wr_and_or(sd, 0xaf, 0xed, 0x0);
 
-	/* Positive clk edge capture for input video clock */
-	adv7511_wr_and_or(sd, 0xba, 0x1f, 0x60);
+		/* Positive clk edge capture for input video clock */
+		adv7511_wr_and_or(sd, 0xba, 0x1f, 0x60);
+	} else {
+		adv7511_set_ofdt_config(sd);
+	}
 
 	adv7511_audio_setup(sd);
 
@@ -1792,6 +2084,181 @@
 	adv7511_cec_write(sd, 0x4e, ratio << 2);
 }
 
+
+static void adv7511_get_ofdt_config(struct i2c_client *client,
+	struct adv7511_state *state)
+{
+	struct device_node *dn = client->dev.of_node;
+	struct device_node *np;
+	struct adv7511_config *config = &state->cfg;
+	u32 const *prop;
+	int size;
+	bool vin_loaded, vout_loaded;
+
+	vin_loaded = vout_loaded = false;
+
+	prop = of_get_property(dn, "edid-addr", &size);
+	if (prop)
+		state->pdata.i2c_edid = (uint8_t)be32_to_cpup(prop);
+
+	prop = of_get_property(dn, "pktmem-addr", &size);
+	if (prop)
+		state->pdata.i2c_pktmem = (uint8_t)be32_to_cpup(prop);
+
+	prop = of_get_property(dn, "cec-addr", &size);
+	if (prop)
+		state->pdata.i2c_cec = (uint8_t)be32_to_cpup(prop);
+
+	np = of_find_node_by_name(dn, "video-input");
+	if (np) {
+		prop = of_get_property(np, "input-id", &size);
+		if (prop)
+			config->in_params.input_id =
+				(uint8_t)be32_to_cpup(prop);
+		prop = of_get_property(np, "input-style", &size);
+		if (prop)
+			config->in_params.input_style =
+				(uint8_t)be32_to_cpup(prop);
+		prop = of_get_property(np, "input-color-depth", &size);
+		if (prop)
+			config->in_params.input_color_depth =
+				(uint8_t)be32_to_cpup(prop);
+		prop = of_get_property(np, "bit-justification", &size);
+		if (prop)
+			config->in_params.bit_justification =
+				(uint8_t)be32_to_cpup(prop);
+		prop = of_get_property(np, "hsync-polarity", &size);
+		if (prop)
+			config->in_params.hsync_polarity =
+				(uint8_t)be32_to_cpup(prop);
+		prop = of_get_property(np, "vsync-polarity", &size);
+		if (prop)
+			config->in_params.vsync_polarity =
+				(uint8_t)be32_to_cpup(prop);
+		prop = of_get_property(np, "clock-delay", &size);
+		if (prop)
+			config->in_params.clock_delay =
+				(uint8_t)be32_to_cpup(prop);
+		vin_loaded = true;
+	} else {
+		pr_info("No video input configuration, using device default\n");
+	}
+
+	np = of_find_node_by_name(dn, "video-output");
+	if (np) {
+		prop = of_get_property(np, "hdmi-mode", &size);
+		if (prop) {
+			if (be32_to_cpup(prop) == 1)
+				config->out_params.hdmi_mode = true;
+		}
+		prop = of_get_property(np, "output-format", &size);
+		if (prop)
+			config->out_params.output_format =
+				(uint8_t)be32_to_cpup(prop);
+		prop = of_get_property(np, "output-color-space", &size);
+		if (prop)
+			config->out_params.output_color_space =
+				(uint8_t)be32_to_cpup(prop);
+		prop = of_get_property(np, "up-conversion", &size);
+		if (prop)
+			config->out_params.up_conversion =
+				(uint8_t)be32_to_cpup(prop);
+		prop = of_get_property(np, "csc-enable", &size);
+		if (prop)
+			config->out_params.csc_enable =
+				(uint8_t)be32_to_cpup(prop);
+		if (config->out_params.csc_enable) {
+			prop = of_get_property(np, "csc-scaling-factor", &size);
+			if (prop) {
+				config->out_params.csc_scaling_factor =
+					(uint8_t)be32_to_cpup(prop);
+			}
+			np = of_find_node_by_name(dn, "csc-coefficients");
+			if (np) {
+				prop = of_get_property(np, "a1", &size);
+				if (prop) {
+					config->out_params.csc_coeff.a1 =
+						(uint16_t)be32_to_cpup(prop);
+				}
+				prop = of_get_property(np, "a2", &size);
+				if (prop) {
+					config->out_params.csc_coeff.a2 =
+						(uint16_t)be32_to_cpup(prop);
+				}
+				prop = of_get_property(np, "a3", &size);
+				if (prop) {
+					config->out_params.csc_coeff.a3 =
+						(uint16_t)be32_to_cpup(prop);
+				}
+				prop = of_get_property(np, "a4", &size);
+				if (prop) {
+					config->out_params.csc_coeff.a4 =
+						(uint16_t)be32_to_cpup(prop);
+				}
+				prop = of_get_property(np, "b1", &size);
+				if (prop) {
+					config->out_params.csc_coeff.b1 =
+						(uint16_t)be32_to_cpup(prop);
+				}
+				prop = of_get_property(np, "b2", &size);
+				if (prop) {
+					config->out_params.csc_coeff.b2 =
+						(uint16_t)be32_to_cpup(prop);
+				}
+				prop = of_get_property(np, "b3", &size);
+				if (prop) {
+					config->out_params.csc_coeff.b3 =
+						(uint16_t)be32_to_cpup(prop);
+				}
+				prop = of_get_property(np, "b4", &size);
+				if (prop) {
+					config->out_params.csc_coeff.b4 =
+						(uint16_t)be32_to_cpup(prop);
+				}
+				prop = of_get_property(np, "c1", &size);
+				if (prop) {
+					config->out_params.csc_coeff.c1 =
+						(uint16_t)be32_to_cpup(prop);
+				}
+				prop = of_get_property(np, "c2", &size);
+				if (prop) {
+					config->out_params.csc_coeff.c2 =
+						(uint16_t)be32_to_cpup(prop);
+				}
+				prop = of_get_property(np, "c3", &size);
+				if (prop) {
+					config->out_params.csc_coeff.c3 =
+						(uint16_t)be32_to_cpup(prop);
+				}
+				prop = of_get_property(np, "c4", &size);
+				if (prop) {
+					config->out_params.csc_coeff.c4 =
+						(uint16_t)be32_to_cpup(prop);
+				}
+			} else {
+				pr_info("No CSC coefficients, using default\n");
+			}
+		}
+		vout_loaded = true;
+	} else {
+		pr_info("No video output configuration, using device default\n");
+	}
+
+	if (vin_loaded && vout_loaded)
+		config->loaded = true;
+}
+
+struct v4l2_subdev *adv7511_subdev(struct v4l2_subdev *sd)
+{
+	static struct v4l2_subdev *subdev;
+
+	if (sd)
+		subdev = sd;
+
+	return subdev;
+}
+EXPORT_SYMBOL(adv7511_subdev);
+
 static int adv7511_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
 	struct adv7511_state *state;
@@ -1809,11 +2276,17 @@
 	if (!state)
 		return -ENOMEM;
 
-	/* Platform data */
-	if (!pdata) {
-		v4l_err(client, "No platform data!\n");
-		return -ENODEV;
+	if (client->dev.of_node) {
+		adv7511_get_ofdt_config(client, state);
+	} else {
+		/* Platform data */
+		if (!pdata) {
+			v4l_err(client, "No platform data!\n");
+			return -ENODEV;
+		}
+		memcpy(&state->pdata, pdata, sizeof(state->pdata));
 	}
+
 	memcpy(&state->pdata, pdata, sizeof(state->pdata));
 	state->fmt_code = MEDIA_BUS_FMT_RGB888_1X24;
 	state->colorspace = V4L2_COLORSPACE_SRGB;
@@ -1824,6 +2297,7 @@
 			 client->addr << 1);
 
 	v4l2_i2c_subdev_init(sd, client, &adv7511_ops);
+	adv7511_subdev(sd);
 	sd->internal_ops = &adv7511_int_ops;
 
 	hdl = &state->hdl;
@@ -1917,7 +2391,9 @@
 
 	INIT_DELAYED_WORK(&state->edid_handler, adv7511_edid_handler);
 
+#ifndef XYLON_LOGICVC_INTG
 	adv7511_init_setup(sd);
+#endif
 
 #if IS_ENABLED(CONFIG_VIDEO_ADV7511_CEC)
 	state->cec_adap = cec_allocate_adapter(&adv7511_cec_adap_ops,
@@ -1931,8 +2407,9 @@
 #endif
 
 	adv7511_set_isr(sd, true);
+#ifndef XYLON_LOGICVC_INTG
 	adv7511_check_monitor_present_status(sd);
-
+#endif
 	v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,
 			  client->addr << 1, client->adapter->name);
 	return 0;
@@ -1964,7 +2441,7 @@
 
 	adv7511_set_isr(sd, false);
 	adv7511_init_setup(sd);
-	cancel_delayed_work(&state->edid_handler);
+	cancel_delayed_work_sync(&state->edid_handler);
 	i2c_unregister_device(state->i2c_edid);
 	i2c_unregister_device(state->i2c_cec);
 	i2c_unregister_device(state->i2c_pktmem);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/adv7604.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/adv7604.c
@@ -2444,7 +2444,7 @@
 		buffer[i + 3] = infoframe_read(sd,
 				       adv76xx_cri[index].payload_addr + i);
 
-	if (hdmi_infoframe_unpack(frame, buffer, sizeof(buffer)) < 0) {
+	if (hdmi_infoframe_unpack(frame, buffer, len + 3) < 0) {
 		v4l2_err(sd, "%s: unpack of %s infoframe failed\n", __func__,
 			 adv76xx_cri[index].desc);
 		return -ENOENT;
@@ -2477,10 +2477,10 @@
 	const struct adv76xx_chip_info *info = state->info;
 	struct v4l2_dv_timings timings;
 	struct stdi_readback stdi;
-	u8 reg_io_0x02 = io_read(sd, 0x02);
+	int ret;
+	u8 reg_io_0x02;
 	u8 edid_enabled;
 	u8 cable_det;
-
 	static const char * const csc_coeff_sel_rb[16] = {
 		"bypassed", "YPbPr601 -> RGB", "reserved", "YPbPr709 -> RGB",
 		"reserved", "RGB -> YPbPr601", "reserved", "RGB -> YPbPr709",
@@ -2579,13 +2579,21 @@
 	v4l2_info(sd, "-----Color space-----\n");
 	v4l2_info(sd, "RGB quantization range ctrl: %s\n",
 			rgb_quantization_range_txt[state->rgb_quantization_range]);
-	v4l2_info(sd, "Input color space: %s\n",
-			input_color_space_txt[reg_io_0x02 >> 4]);
-	v4l2_info(sd, "Output color space: %s %s, alt-gamma %s\n",
-			(reg_io_0x02 & 0x02) ? "RGB" : "YCbCr",
-			(((reg_io_0x02 >> 2) & 0x01) ^ (reg_io_0x02 & 0x01)) ?
-				"(16-235)" : "(0-255)",
-			(reg_io_0x02 & 0x08) ? "enabled" : "disabled");
+
+	ret = io_read(sd, 0x02);
+	if (ret < 0) {
+		v4l2_info(sd, "Can't read Input/Output color space\n");
+	} else {
+		reg_io_0x02 = ret;
+
+		v4l2_info(sd, "Input color space: %s\n",
+				input_color_space_txt[reg_io_0x02 >> 4]);
+		v4l2_info(sd, "Output color space: %s %s, alt-gamma %s\n",
+				(reg_io_0x02 & 0x02) ? "RGB" : "YCbCr",
+				(((reg_io_0x02 >> 2) & 0x01) ^ (reg_io_0x02 & 0x01)) ?
+					"(16-235)" : "(0-255)",
+				(reg_io_0x02 & 0x08) ? "enabled" : "disabled");
+	}
 	v4l2_info(sd, "Color space conversion: %s\n",
 			csc_coeff_sel_rb[cp_read(sd, info->cp_csc) >> 4]);
 
@@ -3606,7 +3614,7 @@
 	io_write(sd, 0x6e, 0);
 	io_write(sd, 0x73, 0);
 
-	cancel_delayed_work(&state->delayed_work_enable_hotplug);
+	cancel_delayed_work_sync(&state->delayed_work_enable_hotplug);
 	v4l2_async_unregister_subdev(sd);
 	media_entity_cleanup(&sd->entity);
 	adv76xx_unregister_clients(to_state(sd));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/adv7842.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/adv7842.c
@@ -2574,7 +2574,7 @@
 	for (i = 0; i < len; i++)
 		buffer[i + 3] = infoframe_read(sd, cri->payload_addr + i);
 
-	if (hdmi_infoframe_unpack(&frame, buffer, sizeof(buffer)) < 0) {
+	if (hdmi_infoframe_unpack(&frame, buffer, len + 3) < 0) {
 		v4l2_err(sd, "%s: unpack of %s infoframe failed\n", __func__, cri->desc);
 		return;
 	}
@@ -3586,7 +3586,7 @@
 	struct adv7842_state *state = to_state(sd);
 
 	adv7842_irq_enable(sd, false);
-	cancel_delayed_work(&state->delayed_work_enable_hotplug);
+	cancel_delayed_work_sync(&state->delayed_work_enable_hotplug);
 	v4l2_device_unregister_subdev(sd);
 	media_entity_cleanup(&sd->entity);
 	adv7842_unregister_clients(sd);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/ap1302.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/ap1302.c
@@ -0,0 +1,2761 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Driver for the AP1302 external camera ISP from ON Semiconductor
+ *
+ * Copyright (C) 2021, Witekio, Inc.
+ * Copyright (C) 2021, Xilinx, Inc.
+ * Copyright (C) 2021, Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/media.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+
+#include <media/media-entity.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-fwnode.h>
+
+#define DRIVER_NAME "ap1302"
+
+#define AP1302_FW_WINDOW_SIZE			0x2000
+#define AP1302_FW_WINDOW_OFFSET			0x8000
+
+#define AP1302_MIN_WIDTH			24U
+#define AP1302_MIN_HEIGHT			16U
+#define AP1302_MAX_WIDTH			4224U
+#define AP1302_MAX_HEIGHT			4092U
+
+#define AP1302_REG_16BIT(n)			((2 << 24) | (n))
+#define AP1302_REG_32BIT(n)			((4 << 24) | (n))
+#define AP1302_REG_SIZE(n)			((n) >> 24)
+#define AP1302_REG_ADDR(n)			((n) & 0x0000ffff)
+#define AP1302_REG_PAGE(n)			((n) & 0x00ff0000)
+#define AP1302_REG_PAGE_MASK			0x00ff0000
+
+/* Info Registers */
+#define AP1302_CHIP_VERSION			AP1302_REG_16BIT(0x0000)
+#define AP1302_CHIP_ID				0x0265
+#define AP1302_FRAME_CNT			AP1302_REG_16BIT(0x0002)
+#define AP1302_ERROR				AP1302_REG_16BIT(0x0006)
+#define AP1302_ERR_FILE				AP1302_REG_32BIT(0x0008)
+#define AP1302_ERR_LINE				AP1302_REG_16BIT(0x000c)
+#define AP1302_SIPM_ERR_0			AP1302_REG_16BIT(0x0014)
+#define AP1302_SIPM_ERR_1			AP1302_REG_16BIT(0x0016)
+#define AP1302_CHIP_REV				AP1302_REG_16BIT(0x0050)
+#define AP1302_CON_BUF(n)			AP1302_REG_16BIT(0x0a2c + (n))
+#define AP1302_CON_BUF_SIZE			512
+
+/* Control Registers */
+#define AP1302_DZ_TGT_FCT			AP1302_REG_16BIT(0x1010)
+#define AP1302_SFX_MODE				AP1302_REG_16BIT(0x1016)
+#define AP1302_SFX_MODE_SFX_NORMAL		(0U << 0)
+#define AP1302_SFX_MODE_SFX_ALIEN		(1U << 0)
+#define AP1302_SFX_MODE_SFX_ANTIQUE		(2U << 0)
+#define AP1302_SFX_MODE_SFX_BW			(3U << 0)
+#define AP1302_SFX_MODE_SFX_EMBOSS		(4U << 0)
+#define AP1302_SFX_MODE_SFX_EMBOSS_COLORED	(5U << 0)
+#define AP1302_SFX_MODE_SFX_GRAYSCALE		(6U << 0)
+#define AP1302_SFX_MODE_SFX_NEGATIVE		(7U << 0)
+#define AP1302_SFX_MODE_SFX_BLUISH		(8U << 0)
+#define AP1302_SFX_MODE_SFX_GREENISH		(9U << 0)
+#define AP1302_SFX_MODE_SFX_REDISH		(10U << 0)
+#define AP1302_SFX_MODE_SFX_POSTERIZE1		(11U << 0)
+#define AP1302_SFX_MODE_SFX_POSTERIZE2		(12U << 0)
+#define AP1302_SFX_MODE_SFX_SEPIA1		(13U << 0)
+#define AP1302_SFX_MODE_SFX_SEPIA2		(14U << 0)
+#define AP1302_SFX_MODE_SFX_SKETCH		(15U << 0)
+#define AP1302_SFX_MODE_SFX_SOLARIZE		(16U << 0)
+#define AP1302_SFX_MODE_SFX_FOGGY		(17U << 0)
+#define AP1302_BUBBLE_OUT_FMT			AP1302_REG_16BIT(0x1164)
+#define AP1302_BUBBLE_OUT_FMT_FT_YUV		(3U << 4)
+#define AP1302_BUBBLE_OUT_FMT_FT_RGB		(4U << 4)
+#define AP1302_BUBBLE_OUT_FMT_FT_YUV_JFIF	(5U << 4)
+#define AP1302_BUBBLE_OUT_FMT_FST_RGB_888	(0U << 0)
+#define AP1302_BUBBLE_OUT_FMT_FST_RGB_565	(1U << 0)
+#define AP1302_BUBBLE_OUT_FMT_FST_RGB_555M	(2U << 0)
+#define AP1302_BUBBLE_OUT_FMT_FST_RGB_555L	(3U << 0)
+#define AP1302_BUBBLE_OUT_FMT_FST_YUV_422	(0U << 0)
+#define AP1302_BUBBLE_OUT_FMT_FST_YUV_420	(1U << 0)
+#define AP1302_BUBBLE_OUT_FMT_FST_YUV_400	(2U << 0)
+#define AP1302_ATOMIC				AP1302_REG_16BIT(0x1184)
+#define AP1302_ATOMIC_MODE			BIT(2)
+#define AP1302_ATOMIC_FINISH			BIT(1)
+#define AP1302_ATOMIC_RECORD			BIT(0)
+
+/*
+ * Preview Context Registers (preview_*). AP1302 supports 3 "contexts"
+ * (Preview, Snapshot, Video). These can be programmed for different size,
+ * format, FPS, etc. There is no functional difference between the contexts,
+ * so the only potential benefit of using them is reduced number of register
+ * writes when switching output modes (if your concern is atomicity, see
+ * "atomic" register).
+ * So there's virtually no benefit in using contexts for this driver and it
+ * would significantly increase complexity. Let's use preview context only.
+ */
+#define AP1302_PREVIEW_WIDTH			AP1302_REG_16BIT(0x2000)
+#define AP1302_PREVIEW_HEIGHT			AP1302_REG_16BIT(0x2002)
+#define AP1302_PREVIEW_ROI_X0			AP1302_REG_16BIT(0x2004)
+#define AP1302_PREVIEW_ROI_Y0			AP1302_REG_16BIT(0x2006)
+#define AP1302_PREVIEW_ROI_X1			AP1302_REG_16BIT(0x2008)
+#define AP1302_PREVIEW_ROI_Y1			AP1302_REG_16BIT(0x200a)
+#define AP1302_PREVIEW_OUT_FMT			AP1302_REG_16BIT(0x2012)
+#define AP1302_PREVIEW_OUT_FMT_IPIPE_BYPASS	BIT(13)
+#define AP1302_PREVIEW_OUT_FMT_SS		BIT(12)
+#define AP1302_PREVIEW_OUT_FMT_FAKE_EN		BIT(11)
+#define AP1302_PREVIEW_OUT_FMT_ST_EN		BIT(10)
+#define AP1302_PREVIEW_OUT_FMT_IIS_NONE		(0U << 8)
+#define AP1302_PREVIEW_OUT_FMT_IIS_POST_VIEW	(1U << 8)
+#define AP1302_PREVIEW_OUT_FMT_IIS_VIDEO	(2U << 8)
+#define AP1302_PREVIEW_OUT_FMT_IIS_BUBBLE	(3U << 8)
+#define AP1302_PREVIEW_OUT_FMT_FT_JPEG_422	(0U << 4)
+#define AP1302_PREVIEW_OUT_FMT_FT_JPEG_420	(1U << 4)
+#define AP1302_PREVIEW_OUT_FMT_FT_YUV		(3U << 4)
+#define AP1302_PREVIEW_OUT_FMT_FT_RGB		(4U << 4)
+#define AP1302_PREVIEW_OUT_FMT_FT_YUV_JFIF	(5U << 4)
+#define AP1302_PREVIEW_OUT_FMT_FT_RAW8		(8U << 4)
+#define AP1302_PREVIEW_OUT_FMT_FT_RAW10		(9U << 4)
+#define AP1302_PREVIEW_OUT_FMT_FT_RAW12		(10U << 4)
+#define AP1302_PREVIEW_OUT_FMT_FT_RAW16		(11U << 4)
+#define AP1302_PREVIEW_OUT_FMT_FT_DNG8		(12U << 4)
+#define AP1302_PREVIEW_OUT_FMT_FT_DNG10		(13U << 4)
+#define AP1302_PREVIEW_OUT_FMT_FT_DNG12		(14U << 4)
+#define AP1302_PREVIEW_OUT_FMT_FT_DNG16		(15U << 4)
+#define AP1302_PREVIEW_OUT_FMT_FST_JPEG_ROTATE	BIT(2)
+#define AP1302_PREVIEW_OUT_FMT_FST_JPEG_SCAN	(0U << 0)
+#define AP1302_PREVIEW_OUT_FMT_FST_JPEG_JFIF	(1U << 0)
+#define AP1302_PREVIEW_OUT_FMT_FST_JPEG_EXIF	(2U << 0)
+#define AP1302_PREVIEW_OUT_FMT_FST_RGB_888	(0U << 0)
+#define AP1302_PREVIEW_OUT_FMT_FST_RGB_565	(1U << 0)
+#define AP1302_PREVIEW_OUT_FMT_FST_RGB_555M	(2U << 0)
+#define AP1302_PREVIEW_OUT_FMT_FST_RGB_555L	(3U << 0)
+#define AP1302_PREVIEW_OUT_FMT_FST_YUV_422	(0U << 0)
+#define AP1302_PREVIEW_OUT_FMT_FST_YUV_420	(1U << 0)
+#define AP1302_PREVIEW_OUT_FMT_FST_YUV_400	(2U << 0)
+#define AP1302_PREVIEW_OUT_FMT_FST_RAW_SENSOR	(0U << 0)
+#define AP1302_PREVIEW_OUT_FMT_FST_RAW_CAPTURE	(1U << 0)
+#define AP1302_PREVIEW_OUT_FMT_FST_RAW_CP	(2U << 0)
+#define AP1302_PREVIEW_OUT_FMT_FST_RAW_BPC	(3U << 0)
+#define AP1302_PREVIEW_OUT_FMT_FST_RAW_IHDR	(4U << 0)
+#define AP1302_PREVIEW_OUT_FMT_FST_RAW_PP	(5U << 0)
+#define AP1302_PREVIEW_OUT_FMT_FST_RAW_DENSH	(6U << 0)
+#define AP1302_PREVIEW_OUT_FMT_FST_RAW_PM	(7U << 0)
+#define AP1302_PREVIEW_OUT_FMT_FST_RAW_GC	(8U << 0)
+#define AP1302_PREVIEW_OUT_FMT_FST_RAW_CURVE	(9U << 0)
+#define AP1302_PREVIEW_OUT_FMT_FST_RAW_CCONV	(10U << 0)
+#define AP1302_PREVIEW_S1_SENSOR_MODE		AP1302_REG_16BIT(0x202e)
+#define AP1302_PREVIEW_HINF_CTRL		AP1302_REG_16BIT(0x2030)
+#define AP1302_PREVIEW_HINF_CTRL_BT656_LE	BIT(15)
+#define AP1302_PREVIEW_HINF_CTRL_BT656_16BIT	BIT(14)
+#define AP1302_PREVIEW_HINF_CTRL_MUX_DELAY(n)	((n) << 8)
+#define AP1302_PREVIEW_HINF_CTRL_LV_POL		BIT(7)
+#define AP1302_PREVIEW_HINF_CTRL_FV_POL		BIT(6)
+#define AP1302_PREVIEW_HINF_CTRL_MIPI_CONT_CLK	BIT(5)
+#define AP1302_PREVIEW_HINF_CTRL_SPOOF		BIT(4)
+#define AP1302_PREVIEW_HINF_CTRL_MIPI_MODE	BIT(3)
+#define AP1302_PREVIEW_HINF_CTRL_MIPI_LANES(n)	((n) << 0)
+
+/* IQ Registers */
+#define AP1302_AE_BV_OFF			AP1302_REG_16BIT(0x5014)
+#define AP1302_AWB_CTRL				AP1302_REG_16BIT(0x5100)
+#define AP1302_AWB_CTRL_RECALC			BIT(13)
+#define AP1302_AWB_CTRL_POSTGAIN		BIT(12)
+#define AP1302_AWB_CTRL_UNGAIN			BIT(11)
+#define AP1302_AWB_CTRL_CLIP			BIT(10)
+#define AP1302_AWB_CTRL_SKY			BIT(9)
+#define AP1302_AWB_CTRL_FLASH			BIT(8)
+#define AP1302_AWB_CTRL_FACE_OFF		(0U << 6)
+#define AP1302_AWB_CTRL_FACE_IGNORE		(1U << 6)
+#define AP1302_AWB_CTRL_FACE_CONSTRAINED	(2U << 6)
+#define AP1302_AWB_CTRL_FACE_ONLY		(3U << 6)
+#define AP1302_AWB_CTRL_IMM			BIT(5)
+#define AP1302_AWB_CTRL_IMM1			BIT(4)
+#define AP1302_AWB_CTRL_MODE_OFF		(0U << 0)
+#define AP1302_AWB_CTRL_MODE_HORIZON		(1U << 0)
+#define AP1302_AWB_CTRL_MODE_A			(2U << 0)
+#define AP1302_AWB_CTRL_MODE_CWF		(3U << 0)
+#define AP1302_AWB_CTRL_MODE_D50		(4U << 0)
+#define AP1302_AWB_CTRL_MODE_D65		(5U << 0)
+#define AP1302_AWB_CTRL_MODE_D75		(6U << 0)
+#define AP1302_AWB_CTRL_MODE_MANUAL		(7U << 0)
+#define AP1302_AWB_CTRL_MODE_MEASURE		(8U << 0)
+#define AP1302_AWB_CTRL_MODE_AUTO		(15U << 0)
+#define AP1302_AWB_CTRL_MODE_MASK		0x000f
+#define AP1302_FLICK_CTRL			AP1302_REG_16BIT(0x5440)
+#define AP1302_FLICK_CTRL_FREQ(n)		((n) << 8)
+#define AP1302_FLICK_CTRL_ETC_IHDR_UP		BIT(6)
+#define AP1302_FLICK_CTRL_ETC_DIS		BIT(5)
+#define AP1302_FLICK_CTRL_FRC_OVERRIDE_MAX_ET	BIT(4)
+#define AP1302_FLICK_CTRL_FRC_OVERRIDE_UPPER_ET	BIT(3)
+#define AP1302_FLICK_CTRL_FRC_EN		BIT(2)
+#define AP1302_FLICK_CTRL_MODE_DISABLED		(0U << 0)
+#define AP1302_FLICK_CTRL_MODE_MANUAL		(1U << 0)
+#define AP1302_FLICK_CTRL_MODE_AUTO		(2U << 0)
+#define AP1302_SCENE_CTRL			AP1302_REG_16BIT(0x5454)
+#define AP1302_SCENE_CTRL_MODE_NORMAL		(0U << 0)
+#define AP1302_SCENE_CTRL_MODE_PORTRAIT		(1U << 0)
+#define AP1302_SCENE_CTRL_MODE_LANDSCAPE	(2U << 0)
+#define AP1302_SCENE_CTRL_MODE_SPORT		(3U << 0)
+#define AP1302_SCENE_CTRL_MODE_CLOSE_UP		(4U << 0)
+#define AP1302_SCENE_CTRL_MODE_NIGHT		(5U << 0)
+#define AP1302_SCENE_CTRL_MODE_TWILIGHT		(6U << 0)
+#define AP1302_SCENE_CTRL_MODE_BACKLIGHT	(7U << 0)
+#define AP1302_SCENE_CTRL_MODE_HIGH_SENSITIVE	(8U << 0)
+#define AP1302_SCENE_CTRL_MODE_NIGHT_PORTRAIT	(9U << 0)
+#define AP1302_SCENE_CTRL_MODE_BEACH		(10U << 0)
+#define AP1302_SCENE_CTRL_MODE_DOCUMENT		(11U << 0)
+#define AP1302_SCENE_CTRL_MODE_PARTY		(12U << 0)
+#define AP1302_SCENE_CTRL_MODE_FIREWORKS	(13U << 0)
+#define AP1302_SCENE_CTRL_MODE_SUNSET		(14U << 0)
+#define AP1302_SCENE_CTRL_MODE_AUTO		(0xffU << 0)
+
+/* System Registers */
+#define AP1302_BOOTDATA_STAGE			AP1302_REG_16BIT(0x6002)
+#define AP1302_WARNING(n)			AP1302_REG_16BIT(0x6004 + (n) * 2)
+#define AP1302_SENSOR_SELECT			AP1302_REG_16BIT(0x600c)
+#define AP1302_SENSOR_SELECT_TP_MODE(n)		((n) << 8)
+#define AP1302_SENSOR_SELECT_PATTERN_ON		BIT(7)
+#define AP1302_SENSOR_SELECT_MODE_3D_ON		BIT(6)
+#define AP1302_SENSOR_SELECT_CLOCK		BIT(5)
+#define AP1302_SENSOR_SELECT_SINF_MIPI		BIT(4)
+#define AP1302_SENSOR_SELECT_YUV		BIT(2)
+#define AP1302_SENSOR_SELECT_SENSOR_TP		(0U << 0)
+#define AP1302_SENSOR_SELECT_SENSOR(n)		(((n) + 1) << 0)
+#define AP1302_SYS_START			AP1302_REG_16BIT(0x601a)
+#define AP1302_SYS_START_PLL_LOCK		BIT(15)
+#define AP1302_SYS_START_LOAD_OTP		BIT(12)
+#define AP1302_SYS_START_RESTART_ERROR		BIT(11)
+#define AP1302_SYS_START_STALL_STATUS		BIT(9)
+#define AP1302_SYS_START_STALL_EN		BIT(8)
+#define AP1302_SYS_START_STALL_MODE_FRAME	(0U << 6)
+#define AP1302_SYS_START_STALL_MODE_DISABLED	(1U << 6)
+#define AP1302_SYS_START_STALL_MODE_POWER_DOWN	(2U << 6)
+#define AP1302_SYS_START_GO			BIT(4)
+#define AP1302_SYS_START_PATCH_FUN		BIT(1)
+#define AP1302_SYS_START_PLL_INIT		BIT(0)
+#define AP1302_DMA_SRC				AP1302_REG_32BIT(0x60a0)
+#define AP1302_DMA_DST				AP1302_REG_32BIT(0x60a4)
+#define AP1302_DMA_SIP_SIPM(n)			((n) << 26)
+#define AP1302_DMA_SIP_DATA_16_BIT		BIT(25)
+#define AP1302_DMA_SIP_ADDR_16_BIT		BIT(24)
+#define AP1302_DMA_SIP_ID(n)			((n) << 17)
+#define AP1302_DMA_SIP_REG(n)			((n) << 0)
+#define AP1302_DMA_SIZE				AP1302_REG_32BIT(0x60a8)
+#define AP1302_DMA_CTRL				AP1302_REG_16BIT(0x60ac)
+#define AP1302_DMA_CTRL_SCH_NORMAL		(0 << 12)
+#define AP1302_DMA_CTRL_SCH_NEXT		(1 << 12)
+#define AP1302_DMA_CTRL_SCH_NOW			(2 << 12)
+#define AP1302_DMA_CTRL_DST_REG			(0 << 8)
+#define AP1302_DMA_CTRL_DST_SRAM		(1 << 8)
+#define AP1302_DMA_CTRL_DST_SPI			(2 << 8)
+#define AP1302_DMA_CTRL_DST_SIP			(3 << 8)
+#define AP1302_DMA_CTRL_SRC_REG			(0 << 4)
+#define AP1302_DMA_CTRL_SRC_SRAM		(1 << 4)
+#define AP1302_DMA_CTRL_SRC_SPI			(2 << 4)
+#define AP1302_DMA_CTRL_SRC_SIP			(3 << 4)
+#define AP1302_DMA_CTRL_MODE_32_BIT		BIT(3)
+#define AP1302_DMA_CTRL_MODE_MASK		(7 << 0)
+#define AP1302_DMA_CTRL_MODE_IDLE		(0 << 0)
+#define AP1302_DMA_CTRL_MODE_SET		(1 << 0)
+#define AP1302_DMA_CTRL_MODE_COPY		(2 << 0)
+#define AP1302_DMA_CTRL_MODE_MAP		(3 << 0)
+#define AP1302_DMA_CTRL_MODE_UNPACK		(4 << 0)
+#define AP1302_DMA_CTRL_MODE_OTP_READ		(5 << 0)
+#define AP1302_DMA_CTRL_MODE_SIP_PROBE		(6 << 0)
+
+/* Misc Registers */
+#define AP1302_REG_ADV_START			0xe000
+#define AP1302_ADVANCED_BASE			AP1302_REG_32BIT(0xf038)
+#define AP1302_SIP_CRC				AP1302_REG_16BIT(0xf052)
+
+/* Advanced System Registers */
+#define AP1302_ADV_IRQ_SYS_INTE			AP1302_REG_32BIT(0x00230000)
+#define AP1302_ADV_IRQ_SYS_INTE_TEST_COUNT	BIT(25)
+#define AP1302_ADV_IRQ_SYS_INTE_HINF_1		BIT(24)
+#define AP1302_ADV_IRQ_SYS_INTE_HINF_0		BIT(23)
+#define AP1302_ADV_IRQ_SYS_INTE_SINF_B_MIPI_L	(7U << 20)
+#define AP1302_ADV_IRQ_SYS_INTE_SINF_B_MIPI	BIT(19)
+#define AP1302_ADV_IRQ_SYS_INTE_SINF_A_MIPI_L	(15U << 14)
+#define AP1302_ADV_IRQ_SYS_INTE_SINF_A_MIPI	BIT(13)
+#define AP1302_ADV_IRQ_SYS_INTE_SINF		BIT(12)
+#define AP1302_ADV_IRQ_SYS_INTE_IPIPE_S		BIT(11)
+#define AP1302_ADV_IRQ_SYS_INTE_IPIPE_B		BIT(10)
+#define AP1302_ADV_IRQ_SYS_INTE_IPIPE_A		BIT(9)
+#define AP1302_ADV_IRQ_SYS_INTE_IP		BIT(8)
+#define AP1302_ADV_IRQ_SYS_INTE_TIMER		BIT(7)
+#define AP1302_ADV_IRQ_SYS_INTE_SIPM		(3U << 6)
+#define AP1302_ADV_IRQ_SYS_INTE_SIPS_ADR_RANGE	BIT(5)
+#define AP1302_ADV_IRQ_SYS_INTE_SIPS_DIRECT_WRITE	BIT(4)
+#define AP1302_ADV_IRQ_SYS_INTE_SIPS_FIFO_WRITE	BIT(3)
+#define AP1302_ADV_IRQ_SYS_INTE_SPI		BIT(2)
+#define AP1302_ADV_IRQ_SYS_INTE_GPIO_CNT	BIT(1)
+#define AP1302_ADV_IRQ_SYS_INTE_GPIO_PIN	BIT(0)
+
+/* Advanced Slave MIPI Registers */
+#define AP1302_ADV_SINF_MIPI_INTERNAL_p_LANE_n_STAT(p, n) \
+	AP1302_REG_32BIT(0x00420008 + (p) * 0x50000 + (n) * 0x20)
+#define AP1302_LANE_ERR_LP_VAL(n)		(((n) >> 30) & 3)
+#define AP1302_LANE_ERR_STATE(n)		(((n) >> 24) & 0xf)
+#define AP1302_LANE_ERR				BIT(18)
+#define AP1302_LANE_ABORT			BIT(17)
+#define AP1302_LANE_LP_VAL(n)			(((n) >> 6) & 3)
+#define AP1302_LANE_STATE(n)			((n) & 0xf)
+#define AP1302_LANE_STATE_STOP_S		0x0
+#define AP1302_LANE_STATE_HS_REQ_S		0x1
+#define AP1302_LANE_STATE_LP_REQ_S		0x2
+#define AP1302_LANE_STATE_HS_S			0x3
+#define AP1302_LANE_STATE_LP_S			0x4
+#define AP1302_LANE_STATE_ESC_REQ_S		0x5
+#define AP1302_LANE_STATE_TURN_REQ_S		0x6
+#define AP1302_LANE_STATE_ESC_S			0x7
+#define AP1302_LANE_STATE_ESC_0			0x8
+#define AP1302_LANE_STATE_ESC_1			0x9
+#define AP1302_LANE_STATE_TURN_S		0xa
+#define AP1302_LANE_STATE_TURN_MARK		0xb
+#define AP1302_LANE_STATE_ERROR_S		0xc
+
+#define AP1302_ADV_CAPTURE_A_FV_CNT		AP1302_REG_32BIT(0x00490040)
+#define AP1302_ADV_HINF_MIPI_T3		AP1302_REG_32BIT(0x840014)
+#define AP1302_TCLK_POST_MASK			0xFF
+#define AP1302_TCLK_POST_SHIFT			0x0
+#define AP1302_TCLK_PRE_MASK			0xFF00
+#define AP1302_TCLK_PRE_SHIFT			0x8
+
+struct ap1302_device;
+
+enum {
+	AP1302_PAD_SINK_0,
+	AP1302_PAD_SINK_1,
+	AP1302_PAD_SOURCE,
+	AP1302_PAD_MAX,
+};
+
+struct ap1302_format_info {
+	unsigned int code;
+	u16 out_fmt;
+};
+
+struct ap1302_format {
+	struct v4l2_mbus_framefmt format;
+	const struct ap1302_format_info *info;
+};
+
+struct ap1302_size {
+	unsigned int width;
+	unsigned int height;
+};
+
+struct ap1302_sensor_supply {
+	const char *name;
+	unsigned int post_delay_us;
+};
+
+struct ap1302_sensor_info {
+	const char *model;
+	const char *name;
+	unsigned int i2c_addr;
+	struct ap1302_size resolution;
+	u32 format;
+	const struct ap1302_sensor_supply *supplies;
+};
+
+struct ap1302_sensor {
+	struct ap1302_device *ap1302;
+	unsigned int index;
+
+	struct device_node *of_node;
+	struct device *dev;
+	unsigned int num_supplies;
+	struct regulator_bulk_data *supplies;
+
+	struct v4l2_subdev sd;
+	struct media_pad pad;
+};
+
+static inline struct ap1302_sensor *to_ap1302_sensor(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct ap1302_sensor, sd);
+}
+
+struct ap1302_device {
+	struct device *dev;
+	struct i2c_client *client;
+
+	struct gpio_desc *reset_gpio;
+	struct gpio_desc *standby_gpio;
+	struct clk *clock;
+	struct regmap *regmap16;
+	struct regmap *regmap32;
+	u32 reg_page;
+
+	const struct firmware *fw;
+
+	struct v4l2_fwnode_endpoint bus_cfg;
+
+	struct mutex lock;	/* Protects formats */
+
+	struct v4l2_subdev sd;
+	struct media_pad pads[AP1302_PAD_MAX];
+	struct ap1302_format formats[AP1302_PAD_MAX];
+	unsigned int width_factor;
+
+	struct v4l2_ctrl_handler ctrls;
+
+	const struct ap1302_sensor_info *sensor_info;
+	struct ap1302_sensor sensors[2];
+
+	struct {
+		struct dentry *dir;
+		struct mutex lock;
+		u32 sipm_addr;
+	} debugfs;
+};
+
+static inline struct ap1302_device *to_ap1302(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct ap1302_device, sd);
+}
+
+struct ap1302_firmware_header {
+	u16 pll_init_size;
+	u16 crc;
+} __packed;
+
+#define MAX_FW_LOAD_RETRIES 3
+
+static const struct ap1302_format_info supported_video_formats[] = {
+	{
+		.code = MEDIA_BUS_FMT_UYVY8_1X16,
+		.out_fmt = AP1302_PREVIEW_OUT_FMT_FT_YUV_JFIF
+			 | AP1302_PREVIEW_OUT_FMT_FST_YUV_422,
+	}, {
+		.code = MEDIA_BUS_FMT_UYYVYY8_0_5X24,
+		.out_fmt = AP1302_PREVIEW_OUT_FMT_FT_YUV_JFIF
+			 | AP1302_PREVIEW_OUT_FMT_FST_YUV_420,
+	}, {
+		.code = MEDIA_BUS_FMT_VYYUYY8_1X24,
+		.out_fmt = AP1302_PREVIEW_OUT_FMT_FT_YUV_JFIF
+			 | AP1302_PREVIEW_OUT_FMT_FST_YUV_420,
+	},
+};
+
+/* -----------------------------------------------------------------------------
+ * Sensor Info
+ */
+
+static const struct ap1302_sensor_info ap1302_sensor_info[] = {
+	{
+		.model = "onnn,ar0144",
+		.name = "ar0144",
+		.i2c_addr = 0x10,
+		.resolution = { 1280, 800 },
+		.format = MEDIA_BUS_FMT_SGRBG12_1X12,
+		.supplies = (const struct ap1302_sensor_supply[]) {
+			{ "vaa", 0 },
+			{ "vddio", 0 },
+			{ "vdd", 0 },
+			{ NULL, 0 },
+		},
+	}, {
+		.model = "onnn,ar0330",
+		.name = "ar0330",
+		.i2c_addr = 0x10,
+		.resolution = { 2304, 1536 },
+		.format = MEDIA_BUS_FMT_SGRBG12_1X12,
+		.supplies = (const struct ap1302_sensor_supply[]) {
+			{ "vddpll", 0 },
+			{ "vaa", 0 },
+			{ "vdd", 0 },
+			{ "vddio", 0 },
+			{ NULL, 0 },
+		},
+	}, {
+		.model = "onnn,ar1335",
+		.name = "ar1335",
+		.i2c_addr = 0x36,
+		.resolution = { 4208, 3120 },
+		.format = MEDIA_BUS_FMT_SGRBG10_1X10,
+		.supplies = (const struct ap1302_sensor_supply[]) {
+			{ "vaa", 0 },
+			{ "vddio", 0 },
+			{ "vdd", 0 },
+			{ NULL, 0 },
+		},
+	},
+};
+
+static const struct ap1302_sensor_info ap1302_sensor_info_tpg = {
+	.model = "",
+	.name = "tpg",
+	.resolution = { 1920, 1080 },
+};
+
+/* -----------------------------------------------------------------------------
+ * Register Configuration
+ */
+
+static const struct regmap_config ap1302_reg16_config = {
+	.reg_bits = 16,
+	.val_bits = 16,
+	.reg_stride = 2,
+	.reg_format_endian = REGMAP_ENDIAN_BIG,
+	.val_format_endian = REGMAP_ENDIAN_BIG,
+	.cache_type = REGCACHE_NONE,
+};
+
+static const struct regmap_config ap1302_reg32_config = {
+	.reg_bits = 16,
+	.val_bits = 32,
+	.reg_stride = 4,
+	.reg_format_endian = REGMAP_ENDIAN_BIG,
+	.val_format_endian = REGMAP_ENDIAN_BIG,
+	.cache_type = REGCACHE_NONE,
+};
+
+static int __ap1302_write(struct ap1302_device *ap1302, u32 reg, u32 val)
+{
+	unsigned int size = AP1302_REG_SIZE(reg);
+	u16 addr = AP1302_REG_ADDR(reg);
+	int ret;
+
+	switch (size) {
+	case 2:
+		ret = regmap_write(ap1302->regmap16, addr, val);
+		break;
+	case 4:
+		ret = regmap_write(ap1302->regmap32, addr, val);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (ret) {
+		dev_err(ap1302->dev, "%s: register 0x%04x %s failed: %d\n",
+			__func__, addr, "write", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int ap1302_write(struct ap1302_device *ap1302, u32 reg, u32 val,
+			int *err)
+{
+	u32 page = AP1302_REG_PAGE(reg);
+	int ret;
+
+	if (err && *err)
+		return *err;
+
+	if (page) {
+		if (ap1302->reg_page != page) {
+			ret = __ap1302_write(ap1302, AP1302_ADVANCED_BASE,
+					     page);
+			if (ret < 0)
+				goto done;
+
+			ap1302->reg_page = page;
+		}
+
+		reg &= ~AP1302_REG_PAGE_MASK;
+		reg += AP1302_REG_ADV_START;
+	}
+
+	ret = __ap1302_write(ap1302, reg, val);
+
+done:
+	if (err && ret)
+		*err = ret;
+
+	return ret;
+}
+
+static int __ap1302_read(struct ap1302_device *ap1302, u32 reg, u32 *val)
+{
+	unsigned int size = AP1302_REG_SIZE(reg);
+	u16 addr = AP1302_REG_ADDR(reg);
+	int ret;
+
+	switch (size) {
+	case 2:
+		ret = regmap_read(ap1302->regmap16, addr, val);
+		break;
+	case 4:
+		ret = regmap_read(ap1302->regmap32, addr, val);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (ret) {
+		dev_err(ap1302->dev, "%s: register 0x%04x %s failed: %d\n",
+			__func__, addr, "read", ret);
+		return ret;
+	}
+
+	dev_dbg(ap1302->dev, "%s: R0x%04x = 0x%0*x\n", __func__,
+		addr, size * 2, *val);
+
+	return 0;
+}
+
+static int ap1302_read(struct ap1302_device *ap1302, u32 reg, u32 *val)
+{
+	u32 page = AP1302_REG_PAGE(reg);
+	int ret;
+
+	if (page) {
+		if (ap1302->reg_page != page) {
+			ret = __ap1302_write(ap1302, AP1302_ADVANCED_BASE,
+					     page);
+			if (ret < 0)
+				return ret;
+
+			ap1302->reg_page = page;
+		}
+
+		reg &= ~AP1302_REG_PAGE_MASK;
+		reg += AP1302_REG_ADV_START;
+	}
+
+	return __ap1302_read(ap1302, reg, val);
+}
+
+/* -----------------------------------------------------------------------------
+ * Sensor Registers Access
+ *
+ * Read and write sensor registers through the AP1302 DMA interface.
+ */
+
+static int ap1302_dma_wait_idle(struct ap1302_device *ap1302)
+{
+	unsigned int i;
+	u32 ctrl;
+	int ret;
+
+	for (i = 50; i > 0; i--) {
+		ret = ap1302_read(ap1302, AP1302_DMA_CTRL, &ctrl);
+		if (ret < 0)
+			return ret;
+
+		if ((ctrl & AP1302_DMA_CTRL_MODE_MASK) ==
+		    AP1302_DMA_CTRL_MODE_IDLE)
+			break;
+
+		usleep_range(1000, 1500);
+	}
+
+	if (!i) {
+		dev_err(ap1302->dev, "DMA timeout\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static int ap1302_sipm_read(struct ap1302_device *ap1302, unsigned int port,
+			    u32 reg, u32 *val)
+{
+	unsigned int size = AP1302_REG_SIZE(reg);
+	u32 src;
+	int ret;
+
+	if (size > 2)
+		return -EINVAL;
+
+	ret = ap1302_dma_wait_idle(ap1302);
+	if (ret < 0)
+		return ret;
+
+	ap1302_write(ap1302, AP1302_DMA_SIZE, size, &ret);
+	src = AP1302_DMA_SIP_SIPM(port)
+	    | (size == 2 ? AP1302_DMA_SIP_DATA_16_BIT : 0)
+	    | AP1302_DMA_SIP_ADDR_16_BIT
+	    | AP1302_DMA_SIP_ID(ap1302->sensor_info->i2c_addr)
+	    | AP1302_DMA_SIP_REG(AP1302_REG_ADDR(reg));
+	ap1302_write(ap1302, AP1302_DMA_SRC, src, &ret);
+
+	/*
+	 * Use the AP1302_DMA_DST register as both the destination address, and
+	 * the scratch pad to store the read value.
+	 */
+	ap1302_write(ap1302, AP1302_DMA_DST, AP1302_REG_ADDR(AP1302_DMA_DST),
+		     &ret);
+
+	ap1302_write(ap1302, AP1302_DMA_CTRL,
+		     AP1302_DMA_CTRL_SCH_NORMAL |
+		     AP1302_DMA_CTRL_DST_REG |
+		     AP1302_DMA_CTRL_SRC_SIP |
+		     AP1302_DMA_CTRL_MODE_COPY, &ret);
+	if (ret < 0)
+		return ret;
+
+	ret = ap1302_dma_wait_idle(ap1302);
+	if (ret < 0)
+		return ret;
+
+	ret = ap1302_read(ap1302, AP1302_DMA_DST, val);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * The value is stored in big-endian at the DMA_DST address. The regmap
+	 * uses big-endian, so 8-bit values are stored in bits 31:24 and 16-bit
+	 * values in bits 23:16.
+	 */
+	*val >>= 32 - size * 8;
+
+	return 0;
+}
+
+static int ap1302_sipm_write(struct ap1302_device *ap1302, unsigned int port,
+			     u32 reg, u32 val)
+{
+	unsigned int size = AP1302_REG_SIZE(reg);
+	u32 dst;
+	int ret;
+
+	if (size > 2)
+		return -EINVAL;
+
+	ret = ap1302_dma_wait_idle(ap1302);
+	if (ret < 0)
+		return ret;
+
+	ap1302_write(ap1302, AP1302_DMA_SIZE, size, &ret);
+
+	/*
+	 * Use the AP1302_DMA_SRC register as both the source address, and the
+	 * scratch pad to store the write value.
+	 *
+	 * As the AP1302 uses big endian, to store the value at address DMA_SRC
+	 * it must be written in the high order bits of the registers. However,
+	 * 8-bit values seem to be incorrectly handled by the AP1302, which
+	 * expects them to be stored at DMA_SRC + 1 instead of DMA_SRC. The
+	 * value is thus unconditionally shifted by 16 bits, unlike for DMA
+	 * reads.
+	 */
+	ap1302_write(ap1302, AP1302_DMA_SRC,
+		     (val << 16) | AP1302_REG_ADDR(AP1302_DMA_SRC), &ret);
+	if (ret < 0)
+		return ret;
+
+	dst = AP1302_DMA_SIP_SIPM(port)
+	    | (size == 2 ? AP1302_DMA_SIP_DATA_16_BIT : 0)
+	    | AP1302_DMA_SIP_ADDR_16_BIT
+	    | AP1302_DMA_SIP_ID(ap1302->sensor_info->i2c_addr)
+	    | AP1302_DMA_SIP_REG(AP1302_REG_ADDR(reg));
+	ap1302_write(ap1302, AP1302_DMA_DST, dst, &ret);
+
+	ap1302_write(ap1302, AP1302_DMA_CTRL,
+		     AP1302_DMA_CTRL_SCH_NORMAL |
+		     AP1302_DMA_CTRL_DST_SIP |
+		     AP1302_DMA_CTRL_SRC_REG |
+		     AP1302_DMA_CTRL_MODE_COPY, &ret);
+	if (ret < 0)
+		return ret;
+
+	ret = ap1302_dma_wait_idle(ap1302);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Debugfs
+ */
+
+static int ap1302_sipm_addr_get(void *arg, u64 *val)
+{
+	struct ap1302_device *ap1302 = arg;
+
+	mutex_lock(&ap1302->debugfs.lock);
+	*val = ap1302->debugfs.sipm_addr;
+	mutex_unlock(&ap1302->debugfs.lock);
+
+	return 0;
+}
+
+static int ap1302_sipm_addr_set(void *arg, u64 val)
+{
+	struct ap1302_device *ap1302 = arg;
+
+	if (val & ~0x8700ffff)
+		return -EINVAL;
+
+	switch ((val >> 24) & 7) {
+	case 1:
+	case 2:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	mutex_lock(&ap1302->debugfs.lock);
+	ap1302->debugfs.sipm_addr = val;
+	mutex_unlock(&ap1302->debugfs.lock);
+
+	return 0;
+}
+
+static int ap1302_sipm_data_get(void *arg, u64 *val)
+{
+	struct ap1302_device *ap1302 = arg;
+	u32 value;
+	u32 addr;
+	int ret;
+
+	mutex_lock(&ap1302->debugfs.lock);
+
+	addr = ap1302->debugfs.sipm_addr;
+	if (!addr) {
+		ret = -EINVAL;
+		goto unlock;
+	}
+
+	ret = ap1302_sipm_read(ap1302, addr >> 30, addr & ~BIT(31),
+			       &value);
+	if (!ret)
+		*val = value;
+
+unlock:
+	mutex_unlock(&ap1302->debugfs.lock);
+
+	return ret;
+}
+
+static int ap1302_sipm_data_set(void *arg, u64 val)
+{
+	struct ap1302_device *ap1302 = arg;
+	u32 addr;
+	int ret;
+
+	mutex_lock(&ap1302->debugfs.lock);
+
+	addr = ap1302->debugfs.sipm_addr;
+	if (!addr) {
+		ret = -EINVAL;
+		goto unlock;
+	}
+
+	ret = ap1302_sipm_write(ap1302, addr >> 30, addr & ~BIT(31),
+				val);
+
+unlock:
+	mutex_unlock(&ap1302->debugfs.lock);
+
+	return ret;
+}
+
+static int ap1302_mipi_tclk_post_get(void *arg, u64 *val)
+{
+	struct ap1302_device *ap1302 = arg;
+	u32 value;
+	int ret;
+
+	mutex_lock(&ap1302->debugfs.lock);
+
+	ret = ap1302_read(ap1302, AP1302_ADV_HINF_MIPI_T3, &value);
+	if (!ret)
+		*val = value & AP1302_TCLK_POST_MASK;
+
+	mutex_unlock(&ap1302->debugfs.lock);
+
+	return ret;
+}
+
+static int ap1302_mipi_tclk_post_set(void *arg, u64 val)
+{
+	struct ap1302_device *ap1302 = arg;
+	u32 reg, reg_val;
+	int ret;
+
+	mutex_lock(&ap1302->debugfs.lock);
+	ret = ap1302_read(ap1302, AP1302_ADV_HINF_MIPI_T3, &reg);
+	if (ret < 0)
+		goto unlock;
+
+	reg_val = reg & ~(AP1302_TCLK_POST_MASK);
+	reg_val = reg_val | val;
+	ret = ap1302_write(ap1302, AP1302_ADV_HINF_MIPI_T3, reg_val, NULL);
+
+unlock:
+	mutex_unlock(&ap1302->debugfs.lock);
+
+	return ret;
+}
+
+static int ap1302_mipi_tclk_pre_get(void *arg, u64 *val)
+{
+	struct ap1302_device *ap1302 = arg;
+	u32 value;
+	int ret;
+
+	mutex_lock(&ap1302->debugfs.lock);
+
+	ret = ap1302_read(ap1302, AP1302_ADV_HINF_MIPI_T3, &value);
+	if (!ret)
+		*val = (value & AP1302_TCLK_PRE_MASK) >> AP1302_TCLK_PRE_SHIFT;
+
+	mutex_unlock(&ap1302->debugfs.lock);
+
+	return ret;
+}
+
+static int ap1302_mipi_tclk_pre_set(void *arg, u64 val)
+{
+	struct ap1302_device *ap1302 = arg;
+	u32 reg, reg_val;
+	int ret;
+
+	mutex_lock(&ap1302->debugfs.lock);
+	ret = ap1302_read(ap1302, AP1302_ADV_HINF_MIPI_T3, &reg);
+	if (ret < 0)
+		goto unlock;
+
+	reg_val = reg & ~(AP1302_TCLK_PRE_MASK);
+	reg_val = reg_val | val << AP1302_TCLK_PRE_SHIFT;
+	ret = ap1302_write(ap1302, AP1302_ADV_HINF_MIPI_T3, reg_val, NULL);
+
+unlock:
+	mutex_unlock(&ap1302->debugfs.lock);
+
+	return ret;
+}
+
+/*
+ * The sipm_addr and sipm_data attributes expose access to the sensor I2C bus.
+ *
+ * To read or write a register, sipm_addr has to first be written with the
+ * register address. The address is a 32-bit integer formatted as follows.
+ *
+ * I000 0SSS 0000 0000 RRRR RRRR RRRR RRRR
+ *
+ * I: SIPM index (0 or 1)
+ * S: Size (1: 8-bit, 2: 16-bit)
+ * R: Register address (16-bit)
+ *
+ * The sipm_data attribute can then be read to read the register value, or
+ * written to write it.
+ */
+
+DEFINE_DEBUGFS_ATTRIBUTE(ap1302_sipm_addr_fops, ap1302_sipm_addr_get,
+			 ap1302_sipm_addr_set, "0x%08llx\n");
+DEFINE_DEBUGFS_ATTRIBUTE(ap1302_sipm_data_fops, ap1302_sipm_data_get,
+			 ap1302_sipm_data_set, "0x%08llx\n");
+
+/* The debugfs is to read and write mipi clk parameters tclk_post values */
+DEFINE_DEBUGFS_ATTRIBUTE(ap1302_mipi_tclk_post_fops, ap1302_mipi_tclk_post_get,
+			 ap1302_mipi_tclk_post_set, "0x%08llx\n");
+
+/* The debugfs is to read and write mipi clk parameters and tclk_pre values */
+DEFINE_DEBUGFS_ATTRIBUTE(ap1302_mipi_tclk_pre_fops, ap1302_mipi_tclk_pre_get,
+			 ap1302_mipi_tclk_pre_set, "0x%08llx\n");
+
+static void ap1302_debugfs_init(struct ap1302_device *ap1302)
+{
+	struct dentry *dir;
+	char name[16];
+
+	mutex_init(&ap1302->debugfs.lock);
+
+	snprintf(name, sizeof(name), "ap1302.%s", dev_name(ap1302->dev));
+
+	dir = debugfs_create_dir(name, NULL);
+	if (IS_ERR(dir))
+		return;
+
+	ap1302->debugfs.dir = dir;
+
+	debugfs_create_file_unsafe("sipm_addr", 0600, ap1302->debugfs.dir,
+				   ap1302, &ap1302_sipm_addr_fops);
+	debugfs_create_file_unsafe("sipm_data", 0600, ap1302->debugfs.dir,
+				   ap1302, &ap1302_sipm_data_fops);
+	debugfs_create_file_unsafe("mipi_tclk_post", 0600, ap1302->debugfs.dir,
+				   ap1302, &ap1302_mipi_tclk_post_fops);
+	debugfs_create_file_unsafe("mipi_tclk_pre", 0600, ap1302->debugfs.dir,
+				   ap1302, &ap1302_mipi_tclk_pre_fops);
+}
+
+static void ap1302_debugfs_cleanup(struct ap1302_device *ap1302)
+{
+	debugfs_remove_recursive(ap1302->debugfs.dir);
+	mutex_destroy(&ap1302->debugfs.lock);
+}
+
+/* -----------------------------------------------------------------------------
+ * Power Handling
+ */
+
+static int ap1302_power_on_sensors(struct ap1302_device *ap1302)
+{
+	struct ap1302_sensor *sensor;
+	unsigned int i, j;
+	int ret;
+
+	if (!ap1302->sensor_info->supplies)
+		return 0;
+
+	for (i = 0; i < ARRAY_SIZE(ap1302->sensors); ++i) {
+		sensor = &ap1302->sensors[i];
+		ret = 0;
+
+		for (j = 0; j < sensor->num_supplies; ++j) {
+			unsigned int delay;
+
+			/*
+			 * We can't use regulator_bulk_enable() as it would
+			 * enable all supplies in parallel, breaking the sensor
+			 * power sequencing constraints.
+			 */
+			ret = regulator_enable(sensor->supplies[j].consumer);
+			if (ret < 0) {
+				dev_err(ap1302->dev,
+					"Failed to enable supply %u for sensor %u\n",
+					j, i);
+				goto error;
+			}
+
+			delay = ap1302->sensor_info->supplies[j].post_delay_us;
+			usleep_range(delay, delay + 100);
+		}
+	}
+
+	return 0;
+
+error:
+	for (; j > 0; --j)
+		regulator_disable(sensor->supplies[j - 1].consumer);
+
+	for (; i > 0; --i) {
+		sensor = &ap1302->sensors[i - 1];
+		regulator_bulk_disable(sensor->num_supplies, sensor->supplies);
+	}
+
+	return ret;
+}
+
+static void ap1302_power_off_sensors(struct ap1302_device *ap1302)
+{
+	unsigned int i;
+
+	if (!ap1302->sensor_info->supplies)
+		return;
+
+	for (i = 0; i < ARRAY_SIZE(ap1302->sensors); ++i) {
+		struct ap1302_sensor *sensor = &ap1302->sensors[i];
+
+		regulator_bulk_disable(sensor->num_supplies, sensor->supplies);
+	}
+}
+
+static int ap1302_power_on(struct ap1302_device *ap1302)
+{
+	int ret;
+
+	/* 0. RESET was asserted when getting the GPIO. */
+
+	/* 1. Assert STANDBY. */
+	if (ap1302->standby_gpio) {
+		gpiod_set_value(ap1302->standby_gpio, 1);
+		usleep_range(200, 1000);
+	}
+
+	/* 2. Power up the regulators. To be implemented. */
+
+	/* 3. De-assert STANDBY. */
+	if (ap1302->standby_gpio) {
+		gpiod_set_value(ap1302->standby_gpio, 0);
+		usleep_range(200, 1000);
+	}
+
+	/* 4. Turn the clock on. */
+	ret = clk_prepare_enable(ap1302->clock);
+	if (ret < 0) {
+		dev_err(ap1302->dev, "Failed to enable clock: %d\n", ret);
+		return ret;
+	}
+
+	/* 5. De-assert RESET. */
+	gpiod_set_value(ap1302->reset_gpio, 0);
+
+	/*
+	 * 6. Wait for the AP1302 to initialize. The datasheet doesn't specify
+	 * how long this takes.
+	 */
+	usleep_range(10000, 11000);
+
+	return 0;
+}
+
+static void ap1302_power_off(struct ap1302_device *ap1302)
+{
+	/* 1. Assert RESET. */
+	gpiod_set_value(ap1302->reset_gpio, 1);
+
+	/* 2. Turn the clock off. */
+	clk_disable_unprepare(ap1302->clock);
+
+	/* 3. Assert STANDBY. */
+	if (ap1302->standby_gpio) {
+		gpiod_set_value(ap1302->standby_gpio, 1);
+		usleep_range(200, 1000);
+	}
+
+	/* 4. Power down the regulators. To be implemented. */
+
+	/* 5. De-assert STANDBY. */
+	if (ap1302->standby_gpio) {
+		usleep_range(200, 1000);
+		gpiod_set_value(ap1302->standby_gpio, 0);
+	}
+}
+
+/* -----------------------------------------------------------------------------
+ * Hardware Configuration
+ */
+
+static int ap1302_dump_console(struct ap1302_device *ap1302)
+{
+	u8 *buffer;
+	u8 *endp;
+	u8 *p;
+	int ret;
+
+	buffer = kmalloc(AP1302_CON_BUF_SIZE + 1, GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
+
+	ret = regmap_raw_read(ap1302->regmap16, AP1302_CON_BUF(0), buffer,
+			      AP1302_CON_BUF_SIZE);
+	if (ret < 0) {
+		dev_err(ap1302->dev, "Failed to read console buffer: %d\n",
+			ret);
+		goto done;
+	}
+
+	print_hex_dump(KERN_INFO, "console ", DUMP_PREFIX_OFFSET, 16, 1, buffer,
+		       AP1302_CON_BUF_SIZE, true);
+
+	buffer[AP1302_CON_BUF_SIZE] = '\0';
+
+	for (p = buffer; p < buffer + AP1302_CON_BUF_SIZE && *p; p = endp + 1) {
+		endp = strchrnul(p, '\n');
+		*endp = '\0';
+
+		pr_info("console %s\n", p);
+	}
+
+	ret = 0;
+
+done:
+	kfree(buffer);
+	return ret;
+}
+
+static int ap1302_configure(struct ap1302_device *ap1302)
+{
+	const struct ap1302_format *format = &ap1302->formats[AP1302_PAD_SOURCE];
+	unsigned int data_lanes = ap1302->bus_cfg.bus.mipi_csi2.num_data_lanes;
+	int ret = 0;
+
+	ap1302_write(ap1302, AP1302_PREVIEW_HINF_CTRL,
+		     AP1302_PREVIEW_HINF_CTRL_SPOOF |
+		     AP1302_PREVIEW_HINF_CTRL_MIPI_LANES(data_lanes), &ret);
+
+	ap1302_write(ap1302, AP1302_PREVIEW_WIDTH,
+		     format->format.width / ap1302->width_factor, &ret);
+	ap1302_write(ap1302, AP1302_PREVIEW_HEIGHT,
+		     format->format.height, &ret);
+	ap1302_write(ap1302, AP1302_PREVIEW_OUT_FMT,
+		     format->info->out_fmt, &ret);
+	if (ret < 0)
+		return ret;
+
+	__v4l2_ctrl_handler_setup(&ap1302->ctrls);
+
+	return 0;
+}
+
+static int ap1302_stall(struct ap1302_device *ap1302, bool stall)
+{
+	int ret = 0;
+
+	if (stall) {
+		ap1302_write(ap1302, AP1302_SYS_START,
+			     AP1302_SYS_START_PLL_LOCK |
+			     AP1302_SYS_START_STALL_MODE_DISABLED, &ret);
+		ap1302_write(ap1302, AP1302_SYS_START,
+			     AP1302_SYS_START_PLL_LOCK |
+			     AP1302_SYS_START_STALL_EN |
+			     AP1302_SYS_START_STALL_MODE_DISABLED, &ret);
+		if (ret < 0)
+			return ret;
+
+		msleep(200);
+
+		ap1302_write(ap1302, AP1302_ADV_IRQ_SYS_INTE,
+			     AP1302_ADV_IRQ_SYS_INTE_SIPM |
+			     AP1302_ADV_IRQ_SYS_INTE_SIPS_FIFO_WRITE, &ret);
+		if (ret < 0)
+			return ret;
+
+		return 0;
+	} else {
+		return ap1302_write(ap1302, AP1302_SYS_START,
+				    AP1302_SYS_START_PLL_LOCK |
+				    AP1302_SYS_START_STALL_STATUS |
+				    AP1302_SYS_START_STALL_EN |
+				    AP1302_SYS_START_STALL_MODE_DISABLED, NULL);
+	}
+}
+
+static int ap1302_set_mipi_t3_clk(struct ap1302_device *ap1302)
+{
+	unsigned int mipi_t3, t_clk_post, t_clk_pre;
+	int ret;
+
+	/* Set the Tclk_post and Tclk_pre values */
+	ret = ap1302_read(ap1302, AP1302_ADV_HINF_MIPI_T3, &mipi_t3);
+	if (ret)
+		return ret;
+
+	/* Read Tclk post default setting and increment by 2 */
+	t_clk_post = ((mipi_t3 & AP1302_TCLK_POST_MASK)
+					>> AP1302_TCLK_POST_SHIFT) + 0x5;
+	/* Read Tclk pre default setting and increment by 1 */
+	t_clk_pre = ((mipi_t3 & AP1302_TCLK_PRE_MASK)
+					>> AP1302_TCLK_PRE_SHIFT) + 0x1;
+
+	mipi_t3 = ((mipi_t3 & ~(AP1302_TCLK_POST_MASK))
+					& ~(AP1302_TCLK_PRE_MASK));
+	mipi_t3 = (mipi_t3 | (t_clk_pre << AP1302_TCLK_PRE_SHIFT)
+					| t_clk_post);
+
+	/* Write MIPI_T3 register with updated Tclk_post and Tclk_pre values */
+	return ap1302_write(ap1302, AP1302_ADV_HINF_MIPI_T3, mipi_t3, NULL);
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 Controls
+ */
+
+static u16 ap1302_wb_values[] = {
+	AP1302_AWB_CTRL_MODE_OFF,	/* V4L2_WHITE_BALANCE_MANUAL */
+	AP1302_AWB_CTRL_MODE_AUTO,	/* V4L2_WHITE_BALANCE_AUTO */
+	AP1302_AWB_CTRL_MODE_A,		/* V4L2_WHITE_BALANCE_INCANDESCENT */
+	AP1302_AWB_CTRL_MODE_D50,	/* V4L2_WHITE_BALANCE_FLUORESCENT */
+	AP1302_AWB_CTRL_MODE_D65,	/* V4L2_WHITE_BALANCE_FLUORESCENT_H */
+	AP1302_AWB_CTRL_MODE_HORIZON,	/* V4L2_WHITE_BALANCE_HORIZON */
+	AP1302_AWB_CTRL_MODE_D65,	/* V4L2_WHITE_BALANCE_DAYLIGHT */
+	AP1302_AWB_CTRL_MODE_AUTO,	/* V4L2_WHITE_BALANCE_FLASH */
+	AP1302_AWB_CTRL_MODE_D75,	/* V4L2_WHITE_BALANCE_CLOUDY */
+	AP1302_AWB_CTRL_MODE_D75,	/* V4L2_WHITE_BALANCE_SHADE */
+};
+
+static int ap1302_set_wb_mode(struct ap1302_device *ap1302, s32 mode)
+{
+	u32 val;
+	int ret;
+
+	ret = ap1302_read(ap1302, AP1302_AWB_CTRL, &val);
+	if (ret)
+		return ret;
+
+	val &= ~AP1302_AWB_CTRL_MODE_MASK;
+	val |= ap1302_wb_values[mode];
+
+	if (mode == V4L2_WHITE_BALANCE_FLASH)
+		val |= AP1302_AWB_CTRL_FLASH;
+	else
+		val &= ~AP1302_AWB_CTRL_FLASH;
+
+	return ap1302_write(ap1302, AP1302_AWB_CTRL, val, NULL);
+}
+
+static int ap1302_set_zoom(struct ap1302_device *ap1302, s32 val)
+{
+	return ap1302_write(ap1302, AP1302_DZ_TGT_FCT, val, NULL);
+}
+
+static u16 ap1302_sfx_values[] = {
+	AP1302_SFX_MODE_SFX_NORMAL,	/* V4L2_COLORFX_NONE */
+	AP1302_SFX_MODE_SFX_BW,		/* V4L2_COLORFX_BW */
+	AP1302_SFX_MODE_SFX_SEPIA1,	/* V4L2_COLORFX_SEPIA */
+	AP1302_SFX_MODE_SFX_NEGATIVE,	/* V4L2_COLORFX_NEGATIVE */
+	AP1302_SFX_MODE_SFX_EMBOSS,	/* V4L2_COLORFX_EMBOSS */
+	AP1302_SFX_MODE_SFX_SKETCH,	/* V4L2_COLORFX_SKETCH */
+	AP1302_SFX_MODE_SFX_BLUISH,	/* V4L2_COLORFX_SKY_BLUE */
+	AP1302_SFX_MODE_SFX_GREENISH,	/* V4L2_COLORFX_GRASS_GREEN */
+	AP1302_SFX_MODE_SFX_REDISH,	/* V4L2_COLORFX_SKIN_WHITEN */
+	AP1302_SFX_MODE_SFX_NORMAL,	/* V4L2_COLORFX_VIVID */
+	AP1302_SFX_MODE_SFX_NORMAL,	/* V4L2_COLORFX_AQUA */
+	AP1302_SFX_MODE_SFX_NORMAL,	/* V4L2_COLORFX_ART_FREEZE */
+	AP1302_SFX_MODE_SFX_NORMAL,	/* V4L2_COLORFX_SILHOUETTE */
+	AP1302_SFX_MODE_SFX_SOLARIZE, /* V4L2_COLORFX_SOLARIZATION */
+	AP1302_SFX_MODE_SFX_ANTIQUE, /* V4L2_COLORFX_ANTIQUE */
+	AP1302_SFX_MODE_SFX_NORMAL,	/* V4L2_COLORFX_SET_CBCR */
+};
+
+static int ap1302_set_special_effect(struct ap1302_device *ap1302, s32 val)
+{
+	return ap1302_write(ap1302, AP1302_SFX_MODE, ap1302_sfx_values[val],
+			    NULL);
+}
+
+static u16 ap1302_scene_mode_values[] = {
+	AP1302_SCENE_CTRL_MODE_NORMAL,		/* V4L2_SCENE_MODE_NONE */
+	AP1302_SCENE_CTRL_MODE_BACKLIGHT,	/* V4L2_SCENE_MODE_BACKLIGHT */
+	AP1302_SCENE_CTRL_MODE_BEACH,		/* V4L2_SCENE_MODE_BEACH_SNOW */
+	AP1302_SCENE_CTRL_MODE_TWILIGHT,	/* V4L2_SCENE_MODE_CANDLE_LIGHT */
+	AP1302_SCENE_CTRL_MODE_NORMAL,		/* V4L2_SCENE_MODE_DAWN_DUSK */
+	AP1302_SCENE_CTRL_MODE_NORMAL,		/* V4L2_SCENE_MODE_FALL_COLORS */
+	AP1302_SCENE_CTRL_MODE_FIREWORKS,	/* V4L2_SCENE_MODE_FIREWORKS */
+	AP1302_SCENE_CTRL_MODE_LANDSCAPE,	/* V4L2_SCENE_MODE_LANDSCAPE */
+	AP1302_SCENE_CTRL_MODE_NIGHT,		/* V4L2_SCENE_MODE_NIGHT */
+	AP1302_SCENE_CTRL_MODE_PARTY,		/* V4L2_SCENE_MODE_PARTY_INDOOR */
+	AP1302_SCENE_CTRL_MODE_PORTRAIT,	/* V4L2_SCENE_MODE_PORTRAIT */
+	AP1302_SCENE_CTRL_MODE_SPORT,		/* V4L2_SCENE_MODE_SPORTS */
+	AP1302_SCENE_CTRL_MODE_SUNSET,		/* V4L2_SCENE_MODE_SUNSET */
+	AP1302_SCENE_CTRL_MODE_DOCUMENT,	/* V4L2_SCENE_MODE_TEXT */
+};
+
+static int ap1302_set_scene_mode(struct ap1302_device *ap1302, s32 val)
+{
+	return ap1302_write(ap1302, AP1302_SCENE_CTRL,
+			    ap1302_scene_mode_values[val], NULL);
+}
+
+static const u16 ap1302_flicker_values[] = {
+	AP1302_FLICK_CTRL_MODE_DISABLED,
+	AP1302_FLICK_CTRL_FREQ(50) | AP1302_FLICK_CTRL_MODE_MANUAL,
+	AP1302_FLICK_CTRL_FREQ(60) | AP1302_FLICK_CTRL_MODE_MANUAL,
+	AP1302_FLICK_CTRL_MODE_AUTO,
+};
+
+static int ap1302_set_flicker_freq(struct ap1302_device *ap1302, s32 val)
+{
+	return ap1302_write(ap1302, AP1302_FLICK_CTRL,
+			    ap1302_flicker_values[val], NULL);
+}
+
+static int ap1302_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct ap1302_device *ap1302 =
+		container_of(ctrl->handler, struct ap1302_device, ctrls);
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE:
+		return ap1302_set_wb_mode(ap1302, ctrl->val);
+
+	case V4L2_CID_ZOOM_ABSOLUTE:
+		return ap1302_set_zoom(ap1302, ctrl->val);
+
+	case V4L2_CID_COLORFX:
+		return ap1302_set_special_effect(ap1302, ctrl->val);
+
+	case V4L2_CID_SCENE_MODE:
+		return ap1302_set_scene_mode(ap1302, ctrl->val);
+
+	case V4L2_CID_POWER_LINE_FREQUENCY:
+		return ap1302_set_flicker_freq(ap1302, ctrl->val);
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct v4l2_ctrl_ops ap1302_ctrl_ops = {
+	.s_ctrl = ap1302_s_ctrl,
+};
+
+static const struct v4l2_ctrl_config ap1302_ctrls[] = {
+	{
+		.ops = &ap1302_ctrl_ops,
+		.id = V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE,
+		.min = 0,
+		.max = 9,
+		.def = 1,
+	}, {
+		.ops = &ap1302_ctrl_ops,
+		.id = V4L2_CID_ZOOM_ABSOLUTE,
+		.min = 0x0100,
+		.max = 0x1000,
+		.step = 1,
+		.def = 0x0100,
+	}, {
+		.ops = &ap1302_ctrl_ops,
+		.id = V4L2_CID_COLORFX,
+		.min = 0,
+		.max = 15,
+		.def = 0,
+		.menu_skip_mask = BIT(15) | BIT(12) | BIT(11) | BIT(10) | BIT(9),
+	}, {
+		.ops = &ap1302_ctrl_ops,
+		.id = V4L2_CID_SCENE_MODE,
+		.min = 0,
+		.max = 13,
+		.def = 0,
+		.menu_skip_mask = BIT(5) | BIT(4),
+	}, {
+		.ops = &ap1302_ctrl_ops,
+		.id = V4L2_CID_POWER_LINE_FREQUENCY,
+		.min = 0,
+		.max = 3,
+		.def = 3,
+	},
+};
+
+static int ap1302_ctrls_init(struct ap1302_device *ap1302)
+{
+	unsigned int i;
+	int ret;
+
+	ret = v4l2_ctrl_handler_init(&ap1302->ctrls, ARRAY_SIZE(ap1302_ctrls));
+	if (ret)
+		return ret;
+
+	for (i = 0; i < ARRAY_SIZE(ap1302_ctrls); i++)
+		v4l2_ctrl_new_custom(&ap1302->ctrls, &ap1302_ctrls[i], NULL);
+
+	if (ap1302->ctrls.error) {
+		ret = ap1302->ctrls.error;
+		v4l2_ctrl_handler_free(&ap1302->ctrls);
+		return ret;
+	}
+
+	/* Use same lock for controls as for everything else. */
+	ap1302->ctrls.lock = &ap1302->lock;
+	ap1302->sd.ctrl_handler = &ap1302->ctrls;
+
+	return 0;
+}
+
+static void ap1302_ctrls_cleanup(struct ap1302_device *ap1302)
+{
+	v4l2_ctrl_handler_free(&ap1302->ctrls);
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 Subdev Operations
+ */
+
+static struct v4l2_mbus_framefmt *
+ap1302_get_pad_format(struct ap1302_device *ap1302,
+		      struct v4l2_subdev_pad_config *cfg,
+		      unsigned int pad, u32 which)
+{
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		return v4l2_subdev_get_try_format(&ap1302->sd, cfg, pad);
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		return &ap1302->formats[pad].format;
+	default:
+		return NULL;
+	}
+}
+
+static int ap1302_init_cfg(struct v4l2_subdev *sd,
+			   struct v4l2_subdev_pad_config *cfg)
+{
+	u32 which = cfg ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+	struct ap1302_device *ap1302 = to_ap1302(sd);
+	const struct ap1302_sensor_info *info = ap1302->sensor_info;
+	unsigned int pad;
+
+	for (pad = 0; pad < ARRAY_SIZE(ap1302->formats); ++pad) {
+		struct v4l2_mbus_framefmt *format =
+			ap1302_get_pad_format(ap1302, cfg, pad, which);
+
+		format->width = info->resolution.width;
+		format->height = info->resolution.height;
+
+		/*
+		 * The source pad combines images side by side in multi-sensor
+		 * setup.
+		 */
+		if (pad == AP1302_PAD_SOURCE) {
+			format->width *= ap1302->width_factor;
+			format->code = ap1302->formats[pad].info->code;
+		} else {
+			format->code = info->format;
+		}
+
+		format->field = V4L2_FIELD_NONE;
+		format->colorspace = V4L2_COLORSPACE_SRGB;
+	}
+
+	return 0;
+}
+
+static int ap1302_enum_mbus_code(struct v4l2_subdev *sd,
+				 struct v4l2_subdev_pad_config *cfg,
+				 struct v4l2_subdev_mbus_code_enum *code)
+{
+	struct ap1302_device *ap1302 = to_ap1302(sd);
+
+	if (code->pad != AP1302_PAD_SOURCE) {
+		/*
+		 * On the sink pads, only the format produced by the sensor is
+		 * supported.
+		 */
+		if (code->index)
+			return -EINVAL;
+
+		code->code = ap1302->sensor_info->format;
+	} else {
+		/* On the source pad, multiple formats are supported. */
+		if (code->index >= ARRAY_SIZE(supported_video_formats))
+			return -EINVAL;
+
+		code->code = supported_video_formats[code->index].code;
+	}
+
+	return 0;
+}
+
+static int ap1302_enum_frame_size(struct v4l2_subdev *sd,
+				  struct v4l2_subdev_pad_config *cfg,
+				  struct v4l2_subdev_frame_size_enum *fse)
+{
+	struct ap1302_device *ap1302 = to_ap1302(sd);
+	unsigned int i;
+
+	if (fse->index)
+		return -EINVAL;
+
+	if (fse->pad != AP1302_PAD_SOURCE) {
+		/*
+		 * On the sink pads, only the size produced by the sensor is
+		 * supported.
+		 */
+		if (fse->code != ap1302->sensor_info->format)
+			return -EINVAL;
+
+		fse->min_width = ap1302->sensor_info->resolution.width;
+		fse->min_height = ap1302->sensor_info->resolution.height;
+		fse->max_width = ap1302->sensor_info->resolution.width;
+		fse->max_height = ap1302->sensor_info->resolution.height;
+	} else {
+		/*
+		 * On the source pad, the AP1302 can freely scale within the
+		 * scaler's limits.
+		 */
+		for (i = 0; i < ARRAY_SIZE(supported_video_formats); i++) {
+			if (supported_video_formats[i].code == fse->code)
+				break;
+		}
+
+		if (i >= ARRAY_SIZE(supported_video_formats))
+			return -EINVAL;
+
+		fse->min_width = AP1302_MIN_WIDTH * ap1302->width_factor;
+		fse->min_height = AP1302_MIN_HEIGHT;
+		fse->max_width = AP1302_MAX_WIDTH;
+		fse->max_height = AP1302_MAX_HEIGHT;
+	}
+
+	return 0;
+}
+
+static int ap1302_get_fmt(struct v4l2_subdev *sd,
+			  struct v4l2_subdev_pad_config *cfg,
+			  struct v4l2_subdev_format *fmt)
+{
+	struct ap1302_device *ap1302 = to_ap1302(sd);
+	const struct v4l2_mbus_framefmt *format;
+
+	format = ap1302_get_pad_format(ap1302, cfg, fmt->pad, fmt->which);
+
+	mutex_lock(&ap1302->lock);
+	fmt->format = *format;
+	mutex_unlock(&ap1302->lock);
+
+	return 0;
+}
+
+static int ap1302_set_fmt(struct v4l2_subdev *sd,
+			  struct v4l2_subdev_pad_config *cfg,
+			  struct v4l2_subdev_format *fmt)
+{
+	struct ap1302_device *ap1302 = to_ap1302(sd);
+	const struct ap1302_format_info *info = NULL;
+	struct v4l2_mbus_framefmt *format;
+	unsigned int i;
+
+	/* Formats on the sink pads can't be changed. */
+	if (fmt->pad != AP1302_PAD_SOURCE)
+		return ap1302_get_fmt(sd, cfg, fmt);
+
+	format = ap1302_get_pad_format(ap1302, cfg, fmt->pad, fmt->which);
+
+	/* Validate the media bus code, default to the first supported value. */
+	for (i = 0; i < ARRAY_SIZE(supported_video_formats); i++) {
+		if (supported_video_formats[i].code == fmt->format.code) {
+			info = &supported_video_formats[i];
+			break;
+		}
+	}
+
+	if (!info)
+		info = &supported_video_formats[0];
+
+	/*
+	 * Clamp the size. The width must be a multiple of 4 (or 8 in the
+	 * dual-sensor case) and the height a multiple of 2.
+	 */
+	fmt->format.width = clamp(ALIGN_DOWN(fmt->format.width,
+					     4 * ap1302->width_factor),
+				  AP1302_MIN_WIDTH * ap1302->width_factor,
+				  AP1302_MAX_WIDTH);
+	fmt->format.height = clamp(ALIGN_DOWN(fmt->format.height, 2),
+				   AP1302_MIN_HEIGHT, AP1302_MAX_HEIGHT);
+
+	mutex_lock(&ap1302->lock);
+
+	format->width = fmt->format.width;
+	format->height = fmt->format.height;
+	format->code = info->code;
+
+	if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+		ap1302->formats[fmt->pad].info = info;
+
+	mutex_unlock(&ap1302->lock);
+
+	fmt->format = *format;
+
+	return 0;
+}
+
+static int ap1302_get_selection(struct v4l2_subdev *sd,
+				struct v4l2_subdev_pad_config *cfg,
+				struct v4l2_subdev_selection *sel)
+{
+	struct ap1302_device *ap1302 = to_ap1302(sd);
+	const struct ap1302_size *resolution = &ap1302->sensor_info->resolution;
+
+	switch (sel->target) {
+	case V4L2_SEL_TGT_NATIVE_SIZE:
+	case V4L2_SEL_TGT_CROP_BOUNDS:
+	case V4L2_SEL_TGT_CROP_DEFAULT:
+	case V4L2_SEL_TGT_CROP:
+		sel->r.left = 0;
+		sel->r.top = 0;
+		sel->r.width = resolution->width * ap1302->width_factor;
+		sel->r.height = resolution->height;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int ap1302_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct ap1302_device *ap1302 = to_ap1302(sd);
+	int ret;
+
+	mutex_lock(&ap1302->lock);
+
+	if (enable) {
+		ret = ap1302_configure(ap1302);
+		if (ret < 0)
+			goto done;
+
+		ret = ap1302_stall(ap1302, false);
+	} else {
+		ret = ap1302_stall(ap1302, true);
+	}
+
+done:
+	mutex_unlock(&ap1302->lock);
+
+	if (ret < 0)
+		dev_err(ap1302->dev, "Failed to %s stream: %d\n",
+			enable ? "start" : "stop", ret);
+
+	return ret;
+}
+
+static const char * const ap1302_warnings[] = {
+	"HINF_BANDWIDTH",
+	"FLICKER_DETECTION",
+	"FACED_NE",
+	"SMILED_NE",
+	"HINF_OVERRUN",
+	NULL,
+	"FRAME_TOO_SMALL",
+	"MISSING_PHASES",
+	"SPOOF_UNDERRUN",
+	"JPEG_NOLAST",
+	"NO_IN_FREQ_SPEC",
+	"SINF0",
+	"SINF1",
+	"CAPTURE0",
+	"CAPTURE1",
+	"ISR_UNHANDLED",
+	"INTERLEAVE_SPOOF",
+	"INTERLEAVE_BUF",
+	"COORD_OUT_OF_RANGE",
+	"ICP_CLOCKING",
+	"SENSOR_CLOCKING",
+	"SENSOR_NO_IHDR",
+	"DIVIDE_BY_ZERO",
+	"INT0_UNDERRUN",
+	"INT1_UNDERRUN",
+	"SCRATCHPAD_TOO_BIG",
+	"OTP_RECORD_READ",
+	"NO_LSC_IN_OTP",
+	"GPIO_INT_LOST",
+	"NO_PDAF_DATA",
+	"FAR_PDAF_ACCESS_SKIP",
+	"PDAF_ERROR",
+	"ATM_TVI_BOUNDS",
+	"SIPM_0_RTY",
+	"SIPM_1_TRY",
+	"SIPM_0_NO_ACK",
+	"SIPM_1_NO_ACK",
+	"SMILE_DIS",
+	"DVS_DIS",
+	"TEST_DIS",
+	"SENSOR_LV2LV",
+	"SENSOR_FV2FV",
+	"FRAME_LOST",
+};
+
+static const char * const ap1302_lane_states[] = {
+	"stop_s",
+	"hs_req_s",
+	"lp_req_s",
+	"hs_s",
+	"lp_s",
+	"esc_req_s",
+	"turn_req_s",
+	"esc_s",
+	"esc_0",
+	"esc_1",
+	"turn_s",
+	"turn_mark",
+	"error_s",
+};
+
+static void ap1302_log_lane_state(struct ap1302_sensor *sensor,
+				  unsigned int index)
+{
+	static const char * const lp_states[] = {
+		"00", "10", "01", "11",
+	};
+
+	unsigned int counts[4][ARRAY_SIZE(ap1302_lane_states)];
+	unsigned int samples = 0;
+	unsigned int lane;
+	unsigned int i;
+	u32 first[4] = { 0, };
+	u32 last[4] = { 0, };
+	int ret;
+
+	memset(counts, 0, sizeof(counts));
+
+	for (i = 0; i < 1000; ++i) {
+		u32 values[4];
+
+		/*
+		 * Read the state of all lanes and skip read errors and invalid
+		 * values.
+		 */
+		for (lane = 0; lane < 4; ++lane) {
+			ret = ap1302_read(sensor->ap1302,
+					  AP1302_ADV_SINF_MIPI_INTERNAL_p_LANE_n_STAT(index, lane),
+					  &values[lane]);
+			if (ret < 0)
+				break;
+
+			if (AP1302_LANE_STATE(values[lane]) >=
+			    ARRAY_SIZE(ap1302_lane_states)) {
+				ret = -EINVAL;
+				break;
+			}
+		}
+
+		if (ret < 0)
+			continue;
+
+		/* Accumulate the samples and save the first and last states. */
+		for (lane = 0; lane < 4; ++lane)
+			counts[lane][AP1302_LANE_STATE(values[lane])]++;
+
+		if (!samples)
+			memcpy(first, values, sizeof(first));
+		memcpy(last, values, sizeof(last));
+
+		samples++;
+	}
+
+	if (!samples)
+		return;
+
+	/*
+	 * Print the LP state from the first sample, the error state from the
+	 * last sample, and the states accumulators for each lane.
+	 */
+	for (lane = 0; lane < 4; ++lane) {
+		u32 state = last[lane];
+		char error_msg[25] = "";
+
+		if (state & (AP1302_LANE_ERR | AP1302_LANE_ABORT)) {
+			unsigned int err = AP1302_LANE_ERR_STATE(state);
+			const char *err_state = NULL;
+
+			err_state = err < ARRAY_SIZE(ap1302_lane_states)
+				  ? ap1302_lane_states[err] : "INVALID";
+
+			snprintf(error_msg, sizeof(error_msg), "ERR (%s%s) %s LP%s",
+				 state & AP1302_LANE_ERR ? "E" : "",
+				 state & AP1302_LANE_ABORT ? "A" : "",
+				 err_state,
+				 lp_states[AP1302_LANE_ERR_LP_VAL(state)]);
+		}
+
+		dev_info(sensor->ap1302->dev, "SINF%u L%u state: LP%s %s",
+			 index, lane, lp_states[AP1302_LANE_LP_VAL(first[lane])],
+			 error_msg);
+
+		for (i = 0; i < ARRAY_SIZE(ap1302_lane_states); ++i) {
+			if (counts[lane][i])
+				pr_cont(" %s:%u",
+				       ap1302_lane_states[i],
+				       counts[lane][i]);
+		}
+		pr_cont("\n");
+	}
+
+	/* Reset the error flags. */
+	for (lane = 0; lane < 4; ++lane)
+		ap1302_write(sensor->ap1302,
+			     AP1302_ADV_SINF_MIPI_INTERNAL_p_LANE_n_STAT(index, lane),
+			     AP1302_LANE_ERR | AP1302_LANE_ABORT, NULL);
+}
+
+static int ap1302_log_status(struct v4l2_subdev *sd)
+{
+	struct ap1302_device *ap1302 = to_ap1302(sd);
+	u16 frame_count_icp;
+	u16 frame_count_brac;
+	u16 frame_count_hinf;
+	u32 warning[4];
+	u32 error[3];
+	unsigned int i;
+	u32 value;
+	int ret;
+
+	/* Dump the console buffer. */
+	ret = ap1302_dump_console(ap1302);
+	if (ret < 0)
+		return ret;
+
+	/* Print errors. */
+	ret = ap1302_read(ap1302, AP1302_ERROR, &error[0]);
+	if (ret < 0)
+		return ret;
+
+	ret = ap1302_read(ap1302, AP1302_ERR_FILE, &error[1]);
+	if (ret < 0)
+		return ret;
+
+	ret = ap1302_read(ap1302, AP1302_ERR_LINE, &error[2]);
+	if (ret < 0)
+		return ret;
+
+	dev_info(ap1302->dev, "ERROR: 0x%04x (file 0x%08x:%u)\n",
+		 error[0], error[1], error[2]);
+
+	ret = ap1302_read(ap1302, AP1302_SIPM_ERR_0, &error[0]);
+	if (ret < 0)
+		return ret;
+
+	ret = ap1302_read(ap1302, AP1302_SIPM_ERR_1, &error[1]);
+	if (ret < 0)
+		return ret;
+
+	dev_info(ap1302->dev, "SIPM_ERR [0] 0x%04x [1] 0x%04x\n",
+		 error[0], error[1]);
+
+	/* Print warnings. */
+	for (i = 0; i < ARRAY_SIZE(warning); ++i) {
+		ret = ap1302_read(ap1302, AP1302_WARNING(i), &warning[i]);
+		if (ret < 0)
+			return ret;
+	}
+
+	dev_info(ap1302->dev,
+		 "WARNING [0] 0x%04x [1] 0x%04x [2] 0x%04x [3] 0x%04x\n",
+		 warning[0], warning[1], warning[2], warning[3]);
+
+	for (i = 0; i < ARRAY_SIZE(ap1302_warnings); ++i) {
+		if ((warning[i / 16] & BIT(i % 16)) &&
+		    ap1302_warnings[i])
+			dev_info(ap1302->dev, "- WARN_%s\n",
+				 ap1302_warnings[i]);
+	}
+
+	/* Print the frame counter. */
+	ret = ap1302_read(ap1302, AP1302_FRAME_CNT, &value);
+	if (ret < 0)
+		return ret;
+
+	frame_count_hinf = value >> 8;
+	frame_count_brac = value & 0xff;
+
+	ret = ap1302_read(ap1302, AP1302_ADV_CAPTURE_A_FV_CNT, &value);
+	if (ret < 0)
+		return ret;
+
+	frame_count_icp = value & 0xffff;
+
+	dev_info(ap1302->dev, "Frame counters: ICP %u, HINF %u, BRAC %u\n",
+		 frame_count_icp, frame_count_hinf, frame_count_brac);
+
+	/* Sample the lane state. */
+	for (i = 0; i < ARRAY_SIZE(ap1302->sensors); ++i) {
+		struct ap1302_sensor *sensor = &ap1302->sensors[i];
+
+		if (!sensor->ap1302)
+			continue;
+
+		ap1302_log_lane_state(sensor, i);
+	}
+
+	return 0;
+}
+
+static int ap1302_subdev_registered(struct v4l2_subdev *sd)
+{
+	struct ap1302_device *ap1302 = to_ap1302(sd);
+	unsigned int i;
+	int ret;
+
+	for (i = 0; i < ARRAY_SIZE(ap1302->sensors); ++i) {
+		struct ap1302_sensor *sensor = &ap1302->sensors[i];
+
+		if (!sensor->dev)
+			continue;
+
+		dev_dbg(ap1302->dev, "registering sensor %u\n", i);
+
+		ret = v4l2_device_register_subdev(sd->v4l2_dev, &sensor->sd);
+		if (ret)
+			return ret;
+
+		ret = media_create_pad_link(&sensor->sd.entity, 0,
+					    &sd->entity, i,
+					    MEDIA_LNK_FL_IMMUTABLE |
+					    MEDIA_LNK_FL_ENABLED);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static const struct media_entity_operations ap1302_media_ops = {
+	.link_validate = v4l2_subdev_link_validate
+};
+
+static const struct v4l2_subdev_pad_ops ap1302_pad_ops = {
+	.init_cfg = ap1302_init_cfg,
+	.enum_mbus_code = ap1302_enum_mbus_code,
+	.enum_frame_size = ap1302_enum_frame_size,
+	.get_fmt = ap1302_get_fmt,
+	.set_fmt = ap1302_set_fmt,
+	.get_selection = ap1302_get_selection,
+	.set_selection = ap1302_get_selection,
+};
+
+static const struct v4l2_subdev_video_ops ap1302_video_ops = {
+	.s_stream = ap1302_s_stream,
+};
+
+static const struct v4l2_subdev_core_ops ap1302_core_ops = {
+	.log_status = ap1302_log_status,
+};
+
+static const struct v4l2_subdev_ops ap1302_subdev_ops = {
+	.core = &ap1302_core_ops,
+	.video = &ap1302_video_ops,
+	.pad = &ap1302_pad_ops,
+};
+
+static const struct v4l2_subdev_internal_ops ap1302_subdev_internal_ops = {
+	.registered = ap1302_subdev_registered,
+};
+
+/* -----------------------------------------------------------------------------
+ * Sensor
+ */
+
+static int ap1302_sensor_enum_mbus_code(struct v4l2_subdev *sd,
+					struct v4l2_subdev_pad_config *cfg,
+					struct v4l2_subdev_mbus_code_enum *code)
+{
+	struct ap1302_sensor *sensor = to_ap1302_sensor(sd);
+	const struct ap1302_sensor_info *info = sensor->ap1302->sensor_info;
+
+	if (code->index)
+		return -EINVAL;
+
+	code->code = info->format;
+	return 0;
+}
+
+static int ap1302_sensor_enum_frame_size(struct v4l2_subdev *sd,
+					 struct v4l2_subdev_pad_config *cfg,
+					 struct v4l2_subdev_frame_size_enum *fse)
+{
+	struct ap1302_sensor *sensor = to_ap1302_sensor(sd);
+	const struct ap1302_sensor_info *info = sensor->ap1302->sensor_info;
+
+	if (fse->index)
+		return -EINVAL;
+
+	if (fse->code != info->format)
+		return -EINVAL;
+
+	fse->min_width = info->resolution.width;
+	fse->min_height = info->resolution.height;
+	fse->max_width = info->resolution.width;
+	fse->max_height = info->resolution.height;
+
+	return 0;
+}
+
+static int ap1302_sensor_get_fmt(struct v4l2_subdev *sd,
+				 struct v4l2_subdev_pad_config *cfg,
+				 struct v4l2_subdev_format *fmt)
+{
+	struct ap1302_sensor *sensor = to_ap1302_sensor(sd);
+	const struct ap1302_sensor_info *info = sensor->ap1302->sensor_info;
+
+	memset(&fmt->format, 0, sizeof(fmt->format));
+
+	fmt->format.width = info->resolution.width;
+	fmt->format.height = info->resolution.height;
+	fmt->format.field = V4L2_FIELD_NONE;
+	fmt->format.code = info->format;
+	fmt->format.colorspace = V4L2_COLORSPACE_SRGB;
+
+	return 0;
+}
+
+static const struct v4l2_subdev_pad_ops ap1302_sensor_pad_ops = {
+	.enum_mbus_code = ap1302_sensor_enum_mbus_code,
+	.enum_frame_size = ap1302_sensor_enum_frame_size,
+	.get_fmt = ap1302_sensor_get_fmt,
+	.set_fmt = ap1302_sensor_get_fmt,
+};
+
+static const struct v4l2_subdev_ops ap1302_sensor_subdev_ops = {
+	.pad = &ap1302_sensor_pad_ops,
+};
+
+static int ap1302_sensor_parse_of(struct ap1302_device *ap1302,
+				  struct device_node *node)
+{
+	struct ap1302_sensor *sensor;
+	u32 reg;
+	int ret;
+
+	/* Retrieve the sensor index from the reg property. */
+	ret = of_property_read_u32(node, "reg", &reg);
+	if (ret < 0) {
+		dev_warn(ap1302->dev,
+			 "'reg' property missing in sensor node\n");
+		return -EINVAL;
+	}
+
+	if (reg >= ARRAY_SIZE(ap1302->sensors)) {
+		dev_warn(ap1302->dev, "Out-of-bounds 'reg' value %u\n",
+			 reg);
+		return -EINVAL;
+	}
+
+	sensor = &ap1302->sensors[reg];
+	if (sensor->ap1302) {
+		dev_warn(ap1302->dev, "Duplicate entry for sensor %u\n", reg);
+		return -EINVAL;
+	}
+
+	sensor->ap1302 = ap1302;
+	sensor->of_node = of_node_get(node);
+
+	return 0;
+}
+
+static void ap1302_sensor_dev_release(struct device *dev)
+{
+	of_node_put(dev->of_node);
+	kfree(dev);
+}
+
+static int ap1302_sensor_init(struct ap1302_sensor *sensor, unsigned int index)
+{
+	struct ap1302_device *ap1302 = sensor->ap1302;
+	struct v4l2_subdev *sd = &sensor->sd;
+	unsigned int i;
+	int ret;
+
+	sensor->index = index;
+
+	/*
+	 * Register a device for the sensor, to support usage of the regulator
+	 * API.
+	 */
+	sensor->dev = kzalloc(sizeof(*sensor->dev), GFP_KERNEL);
+	if (!sensor->dev)
+		return -ENOMEM;
+
+	sensor->dev->parent = ap1302->dev;
+	sensor->dev->of_node = of_node_get(sensor->of_node);
+	sensor->dev->release = &ap1302_sensor_dev_release;
+	dev_set_name(sensor->dev, "%s-%s.%u", dev_name(ap1302->dev),
+		     ap1302->sensor_info->name, index);
+
+	ret = device_register(sensor->dev);
+	if (ret < 0) {
+		dev_err(ap1302->dev,
+			"Failed to register device for sensor %u\n", index);
+		goto error;
+	}
+
+	/* Retrieve the power supplies for the sensor, if any. */
+	if (ap1302->sensor_info->supplies) {
+		const struct ap1302_sensor_supply *supplies =
+			ap1302->sensor_info->supplies;
+		unsigned int num_supplies;
+
+		for (num_supplies = 0; supplies[num_supplies].name; ++num_supplies)
+			;
+
+		sensor->supplies = devm_kcalloc(ap1302->dev, num_supplies,
+						sizeof(*sensor->supplies),
+						GFP_KERNEL);
+		if (!sensor->supplies) {
+			ret = -ENOMEM;
+			goto error;
+		}
+
+		for (i = 0; i < num_supplies; ++i)
+			sensor->supplies[i].supply = supplies[i].name;
+
+		ret = regulator_bulk_get(sensor->dev, num_supplies,
+					 sensor->supplies);
+		if (ret < 0) {
+			dev_err(ap1302->dev,
+				"Failed to get supplies for sensor %u\n", index);
+			goto error;
+		}
+
+		sensor->num_supplies = i;
+	}
+
+	sd->dev = sensor->dev;
+	v4l2_subdev_init(sd, &ap1302_sensor_subdev_ops);
+
+	snprintf(sd->name, sizeof(sd->name), "%s %u",
+		 ap1302->sensor_info->name, index);
+
+	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
+	sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
+
+	ret = media_entity_pads_init(&sd->entity, 1, &sensor->pad);
+	if (ret < 0) {
+		dev_err(ap1302->dev,
+			"failed to initialize media entity for sensor %u: %d\n",
+			index, ret);
+		goto error;
+	}
+
+	return 0;
+
+error:
+	put_device(sensor->dev);
+	return ret;
+}
+
+static void ap1302_sensor_cleanup(struct ap1302_sensor *sensor)
+{
+	media_entity_cleanup(&sensor->sd.entity);
+
+	if (sensor->num_supplies)
+		regulator_bulk_free(sensor->num_supplies, sensor->supplies);
+
+	put_device(sensor->dev);
+	of_node_put(sensor->of_node);
+}
+
+/* -----------------------------------------------------------------------------
+ * Boot & Firmware Handling
+ */
+
+static int ap1302_request_firmware(struct ap1302_device *ap1302)
+{
+	static const char * const suffixes[] = {
+		"",
+		"_single",
+		"_dual",
+	};
+
+	const struct ap1302_firmware_header *fw_hdr;
+	unsigned int num_sensors;
+	unsigned int fw_size;
+	unsigned int i;
+	char name[64];
+	int ret;
+
+	for (i = 0, num_sensors = 0; i < ARRAY_SIZE(ap1302->sensors); ++i) {
+		if (ap1302->sensors[i].dev)
+			num_sensors++;
+	}
+
+	ret = snprintf(name, sizeof(name), "ap1302_%s%s_fw.bin",
+		       ap1302->sensor_info->name, suffixes[num_sensors]);
+	if (ret >= sizeof(name)) {
+		dev_err(ap1302->dev, "Firmware name too long\n");
+		return -EINVAL;
+	}
+
+	dev_dbg(ap1302->dev, "Requesting firmware %s\n", name);
+
+	ret = request_firmware(&ap1302->fw, name, ap1302->dev);
+	if (ret) {
+		dev_err(ap1302->dev, "Failed to request firmware: %d\n", ret);
+		return ret;
+	}
+
+	/*
+	 * The firmware binary contains a header defined by the
+	 * ap1302_firmware_header structure. The firmware itself (also referred
+	 * to as bootdata) follows the header. Perform sanity checks to ensure
+	 * the firmware is valid.
+	 */
+	fw_hdr = (const struct ap1302_firmware_header *)ap1302->fw->data;
+	fw_size = ap1302->fw->size - sizeof(*fw_hdr);
+
+	if (fw_hdr->pll_init_size > fw_size) {
+		dev_err(ap1302->dev,
+			"Invalid firmware: PLL init size too large\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * ap1302_write_fw_window() - Write a piece of firmware to the AP1302
+ * @win_pos: Firmware load window current position
+ * @buf: Firmware data buffer
+ * @len: Firmware data length
+ *
+ * The firmware is loaded through a window in the registers space. Writes are
+ * sequential starting at address 0x8000, and must wrap around when reaching
+ * 0x9fff. This function write the firmware data stored in @buf to the AP1302,
+ * keeping track of the window position in the @win_pos argument.
+ */
+static int ap1302_write_fw_window(struct ap1302_device *ap1302, const u8 *buf,
+				  u32 len, unsigned int *win_pos)
+{
+	while (len > 0) {
+		unsigned int write_addr;
+		unsigned int write_size;
+		int ret;
+
+		/*
+		 * Write at most len bytes, from the current position to the
+		 * end of the window.
+		 */
+		write_addr = *win_pos + AP1302_FW_WINDOW_OFFSET;
+		write_size = min(len, AP1302_FW_WINDOW_SIZE - *win_pos);
+
+		ret = regmap_raw_write(ap1302->regmap16, write_addr, buf,
+				       write_size);
+		if (ret)
+			return ret;
+
+		buf += write_size;
+		len -= write_size;
+
+		*win_pos += write_size;
+		if (*win_pos >= AP1302_FW_WINDOW_SIZE)
+			*win_pos = 0;
+	}
+
+	return 0;
+}
+
+static int ap1302_load_firmware(struct ap1302_device *ap1302)
+{
+	const struct ap1302_firmware_header *fw_hdr;
+	unsigned int fw_size;
+	const u8 *fw_data;
+	unsigned int win_pos = 0;
+	unsigned int crc;
+	int ret;
+
+	fw_hdr = (const struct ap1302_firmware_header *)ap1302->fw->data;
+	fw_data = (u8 *)&fw_hdr[1];
+	fw_size = ap1302->fw->size - sizeof(*fw_hdr);
+
+	/* Clear the CRC register. */
+	ret = ap1302_write(ap1302, AP1302_SIP_CRC, 0xffff, NULL);
+	if (ret)
+		return ret;
+
+	/*
+	 * Load the PLL initialization settings, set the bootdata stage to 2 to
+	 * apply the basic_init_hp settings, and wait 1ms for the PLL to lock.
+	 */
+	ret = ap1302_write_fw_window(ap1302, fw_data, fw_hdr->pll_init_size,
+				     &win_pos);
+	if (ret)
+		return ret;
+
+	ret = ap1302_write(ap1302, AP1302_BOOTDATA_STAGE, 0x0002, NULL);
+	if (ret)
+		return ret;
+
+	usleep_range(1000, 2000);
+
+	/* Load the rest of the bootdata content and verify the CRC. */
+	ret = ap1302_write_fw_window(ap1302, fw_data + fw_hdr->pll_init_size,
+				     fw_size - fw_hdr->pll_init_size, &win_pos);
+	if (ret)
+		return ret;
+
+	msleep(40);
+
+	ret = ap1302_read(ap1302, AP1302_SIP_CRC, &crc);
+	if (ret)
+		return ret;
+
+	if (crc != fw_hdr->crc) {
+		dev_warn(ap1302->dev,
+			 "CRC mismatch: expected 0x%04x, got 0x%04x\n",
+			 fw_hdr->crc, crc);
+		return -EAGAIN;
+	}
+
+	/*
+	 * Write 0xffff to the bootdata_stage register to indicate to the
+	 * AP1302 that the whole bootdata content has been loaded.
+	 */
+	ret = ap1302_write(ap1302, AP1302_BOOTDATA_STAGE, 0xffff, NULL);
+	if (ret)
+		return ret;
+
+	/* The AP1302 starts outputting frames right after boot, stop it. */
+	ret = ap1302_stall(ap1302, true);
+	if (ret)
+		return ret;
+
+	/* Adjust MIPI TCLK timings */
+	return ap1302_set_mipi_t3_clk(ap1302);
+}
+
+static int ap1302_detect_chip(struct ap1302_device *ap1302)
+{
+	unsigned int version;
+	unsigned int revision;
+	int ret;
+
+	ret = ap1302_read(ap1302, AP1302_CHIP_VERSION, &version);
+	if (ret)
+		return ret;
+
+	ret = ap1302_read(ap1302, AP1302_CHIP_REV, &revision);
+	if (ret)
+		return ret;
+
+	if (version != AP1302_CHIP_ID) {
+		dev_err(ap1302->dev,
+			"Invalid chip version, expected 0x%04x, got 0x%04x\n",
+			AP1302_CHIP_ID, version);
+		return -EINVAL;
+	}
+
+	dev_info(ap1302->dev, "AP1302 revision %u.%u.%u detected\n",
+		 (revision & 0xf000) >> 12, (revision & 0x0f00) >> 8,
+		 revision & 0x00ff);
+
+	return 0;
+}
+
+static int ap1302_hw_init(struct ap1302_device *ap1302)
+{
+	unsigned int retries;
+	int ret;
+
+	/* Request and validate the firmware. */
+	ret = ap1302_request_firmware(ap1302);
+	if (ret)
+		return ret;
+
+	/*
+	 * Power the sensors first, as the firmware will access them once it
+	 * gets loaded.
+	 */
+	ret = ap1302_power_on_sensors(ap1302);
+	if (ret < 0)
+		goto error_firmware;
+
+	/*
+	 * Load the firmware, retrying in case of CRC errors. The AP1302 is
+	 * reset with a full power cycle between each attempt.
+	 */
+	for (retries = 0; retries < MAX_FW_LOAD_RETRIES; ++retries) {
+		ret = ap1302_power_on(ap1302);
+		if (ret < 0)
+			goto error_power_sensors;
+
+		ret = ap1302_detect_chip(ap1302);
+		if (ret)
+			goto error_power;
+
+		ret = ap1302_load_firmware(ap1302);
+		if (!ret)
+			break;
+
+		if (ret != -EAGAIN)
+			goto error_power;
+
+		ap1302_power_off(ap1302);
+	}
+
+	if (retries == MAX_FW_LOAD_RETRIES) {
+		dev_err(ap1302->dev,
+			"Firmware load retries exceeded, aborting\n");
+		ret = -ETIMEDOUT;
+		goto error_power_sensors;
+	}
+
+	return 0;
+
+error_power:
+	ap1302_power_off(ap1302);
+error_power_sensors:
+	ap1302_power_off_sensors(ap1302);
+error_firmware:
+	release_firmware(ap1302->fw);
+
+	return ret;
+}
+
+static void ap1302_hw_cleanup(struct ap1302_device *ap1302)
+{
+	ap1302_power_off(ap1302);
+	ap1302_power_off_sensors(ap1302);
+}
+
+/* -----------------------------------------------------------------------------
+ * Probe & Remove
+ */
+
+static int ap1302_config_v4l2(struct ap1302_device *ap1302)
+{
+	struct v4l2_subdev *sd;
+	unsigned int i;
+	int ret;
+
+	sd = &ap1302->sd;
+	sd->dev = ap1302->dev;
+	v4l2_i2c_subdev_init(sd, ap1302->client, &ap1302_subdev_ops);
+
+	strscpy(sd->name, DRIVER_NAME, sizeof(sd->name));
+	strlcat(sd->name, ".", sizeof(sd->name));
+	strlcat(sd->name, dev_name(ap1302->dev), sizeof(sd->name));
+	dev_dbg(ap1302->dev, "name %s\n", sd->name);
+
+	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
+	sd->internal_ops = &ap1302_subdev_internal_ops;
+	sd->entity.function = MEDIA_ENT_F_PROC_VIDEO_ISP;
+	sd->entity.ops = &ap1302_media_ops;
+
+	for (i = 0; i < ARRAY_SIZE(ap1302->pads); ++i)
+		ap1302->pads[i].flags = i == AP1302_PAD_SOURCE
+				      ? MEDIA_PAD_FL_SOURCE : MEDIA_PAD_FL_SINK;
+
+	ret = media_entity_pads_init(&sd->entity, ARRAY_SIZE(ap1302->pads),
+				     ap1302->pads);
+	if (ret < 0) {
+		dev_err(ap1302->dev, "media_entity_init failed %d\n", ret);
+		return ret;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(ap1302->formats); ++i)
+		ap1302->formats[i].info = &supported_video_formats[0];
+
+	ret = ap1302_init_cfg(sd, NULL);
+	if (ret < 0)
+		goto error_media;
+
+	ret = ap1302_ctrls_init(ap1302);
+	if (ret < 0)
+		goto error_media;
+
+	ret = v4l2_async_register_subdev(sd);
+	if (ret < 0) {
+		dev_err(ap1302->dev, "v4l2_async_register_subdev failed %d\n", ret);
+		goto error_ctrls;
+	}
+
+	return 0;
+
+error_ctrls:
+	ap1302_ctrls_cleanup(ap1302);
+error_media:
+	media_entity_cleanup(&sd->entity);
+	return ret;
+}
+
+static int ap1302_parse_of(struct ap1302_device *ap1302)
+{
+	struct device_node *sensors;
+	struct device_node *node;
+	struct fwnode_handle *ep;
+	unsigned int num_sensors = 0;
+	const char *model;
+	unsigned int i;
+	int ret;
+
+	/* Clock */
+	ap1302->clock = devm_clk_get(ap1302->dev, NULL);
+	if (IS_ERR(ap1302->clock)) {
+		dev_err(ap1302->dev, "Failed to get clock: %ld\n",
+			PTR_ERR(ap1302->clock));
+		return PTR_ERR(ap1302->clock);
+	}
+
+	/* GPIOs */
+	ap1302->reset_gpio = devm_gpiod_get(ap1302->dev, "reset",
+					    GPIOD_OUT_HIGH);
+	if (IS_ERR(ap1302->reset_gpio)) {
+		dev_err(ap1302->dev, "Can't get reset GPIO: %ld\n",
+			PTR_ERR(ap1302->reset_gpio));
+		return PTR_ERR(ap1302->reset_gpio);
+	}
+
+	ap1302->standby_gpio = devm_gpiod_get_optional(ap1302->dev, "standby",
+						       GPIOD_OUT_LOW);
+	if (IS_ERR(ap1302->standby_gpio)) {
+		dev_err(ap1302->dev, "Can't get standby GPIO: %ld\n",
+			PTR_ERR(ap1302->standby_gpio));
+		return PTR_ERR(ap1302->standby_gpio);
+	}
+
+	/* Bus configuration */
+	ep = fwnode_graph_get_next_endpoint(dev_fwnode(ap1302->dev), NULL);
+	if (!ep)
+		return -EINVAL;
+
+	ap1302->bus_cfg.bus_type = V4L2_MBUS_CSI2_DPHY;
+
+	ret = v4l2_fwnode_endpoint_alloc_parse(ep, &ap1302->bus_cfg);
+	if (ret < 0) {
+		dev_err(ap1302->dev, "Failed to parse bus configuration\n");
+		return ret;
+	}
+
+	/* Sensors */
+	sensors = of_get_child_by_name(ap1302->dev->of_node, "sensors");
+	if (!sensors) {
+		dev_err(ap1302->dev, "'sensors' child node not found\n");
+		return -EINVAL;
+	}
+
+	ret = of_property_read_string(sensors, "onnn,model", &model);
+	if (ret < 0) {
+		/*
+		 * If no sensor is connected, we can still support operation
+		 * with the test pattern generator.
+		 */
+		ap1302->sensor_info = &ap1302_sensor_info_tpg;
+		ap1302->width_factor = 1;
+		ret = 0;
+		goto done;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(ap1302_sensor_info); ++i) {
+		const struct ap1302_sensor_info *info =
+			&ap1302_sensor_info[i];
+
+		if (!strcmp(info->model, model)) {
+			ap1302->sensor_info = info;
+			break;
+		}
+	}
+
+	if (!ap1302->sensor_info) {
+		dev_warn(ap1302->dev, "Unsupported sensor model %s\n", model);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	for_each_child_of_node(sensors, node) {
+		if (of_node_name_eq(node, "sensor")) {
+			if (!ap1302_sensor_parse_of(ap1302, node))
+				num_sensors++;
+		}
+	}
+
+	if (!num_sensors) {
+		dev_err(ap1302->dev, "No sensor found\n");
+		ret = -EINVAL;
+		goto done;
+	}
+
+	ap1302->width_factor = num_sensors;
+
+done:
+	of_node_put(sensors);
+	return ret;
+}
+
+static void ap1302_cleanup(struct ap1302_device *ap1302)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(ap1302->sensors); ++i) {
+		struct ap1302_sensor *sensor = &ap1302->sensors[i];
+
+		if (!sensor->ap1302)
+			continue;
+
+		ap1302_sensor_cleanup(sensor);
+	}
+
+	v4l2_fwnode_endpoint_free(&ap1302->bus_cfg);
+
+	mutex_destroy(&ap1302->lock);
+}
+
+static int ap1302_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+	struct ap1302_device *ap1302;
+	unsigned int i;
+	int ret;
+
+	ap1302 = devm_kzalloc(&client->dev, sizeof(*ap1302), GFP_KERNEL);
+	if (!ap1302)
+		return -ENOMEM;
+
+	ap1302->dev = &client->dev;
+	ap1302->client = client;
+
+	mutex_init(&ap1302->lock);
+
+	ap1302->regmap16 = devm_regmap_init_i2c(client, &ap1302_reg16_config);
+	if (IS_ERR(ap1302->regmap16)) {
+		dev_err(ap1302->dev, "regmap16 init failed: %ld\n",
+			PTR_ERR(ap1302->regmap16));
+		ret = -ENODEV;
+		goto error;
+	}
+
+	ap1302->regmap32 = devm_regmap_init_i2c(client, &ap1302_reg32_config);
+	if (IS_ERR(ap1302->regmap32)) {
+		dev_err(ap1302->dev, "regmap32 init failed: %ld\n",
+			PTR_ERR(ap1302->regmap32));
+		ret = -ENODEV;
+		goto error;
+	}
+
+	ret = ap1302_parse_of(ap1302);
+	if (ret < 0)
+		goto error;
+
+	for (i = 0; i < ARRAY_SIZE(ap1302->sensors); ++i) {
+		struct ap1302_sensor *sensor = &ap1302->sensors[i];
+
+		if (!sensor->ap1302)
+			continue;
+
+		ret = ap1302_sensor_init(sensor, i);
+		if (ret < 0)
+			goto error;
+	}
+
+	ret = ap1302_hw_init(ap1302);
+	if (ret)
+		goto error;
+
+	ap1302_debugfs_init(ap1302);
+
+	ret = ap1302_config_v4l2(ap1302);
+	if (ret)
+		goto error_hw_cleanup;
+
+	return 0;
+
+error_hw_cleanup:
+	ap1302_hw_cleanup(ap1302);
+error:
+	ap1302_cleanup(ap1302);
+	return ret;
+}
+
+static int ap1302_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct ap1302_device *ap1302 = to_ap1302(sd);
+
+	ap1302_debugfs_cleanup(ap1302);
+
+	ap1302_hw_cleanup(ap1302);
+
+	release_firmware(ap1302->fw);
+
+	v4l2_async_unregister_subdev(sd);
+	media_entity_cleanup(&sd->entity);
+
+	ap1302_ctrls_cleanup(ap1302);
+
+	ap1302_cleanup(ap1302);
+
+	return 0;
+}
+
+static const struct of_device_id ap1302_of_id_table[] = {
+	{ .compatible = "onnn,ap1302" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, ap1302_of_id_table);
+
+static struct i2c_driver ap1302_i2c_driver = {
+	.driver = {
+		.name	= DRIVER_NAME,
+		.of_match_table	= ap1302_of_id_table,
+	},
+	.probe		= ap1302_probe,
+	.remove		= ap1302_remove,
+};
+
+module_i2c_driver(ap1302_i2c_driver);
+
+MODULE_AUTHOR("Florian Rebaudo <frebaudo@witekio.com>");
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_AUTHOR("Anil Kumar M <anil.mamidala@xilinx.com>");
+
+MODULE_DESCRIPTION("ON Semiconductor AP1302 ISP driver");
+MODULE_LICENSE("GPL");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/et8ek8/et8ek8_driver.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/et8ek8/et8ek8_driver.c
@@ -1460,7 +1460,7 @@
 	return ret;
 }
 
-static int __exit et8ek8_remove(struct i2c_client *client)
+static int et8ek8_remove(struct i2c_client *client)
 {
 	struct v4l2_subdev *subdev = i2c_get_clientdata(client);
 	struct et8ek8_sensor *sensor = to_et8ek8_sensor(subdev);
@@ -1504,7 +1504,7 @@
 		.of_match_table	= et8ek8_of_table,
 	},
 	.probe_new	= et8ek8_probe,
-	.remove		= __exit_p(et8ek8_remove),
+	.remove		= et8ek8_remove,
 	.id_table	= et8ek8_id_table,
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/imx214.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/imx214.c
@@ -785,7 +785,7 @@
 		if (ret < 0)
 			goto err_rpm_put;
 	} else {
-		ret = imx214_start_streaming(imx214);
+		ret = imx214_stop_streaming(imx214);
 		if (ret < 0)
 			goto err_rpm_put;
 		pm_runtime_put(imx214->dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/imx258.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/imx258.c
@@ -22,7 +22,7 @@
 #define IMX258_CHIP_ID			0x0258
 
 /* V_TIMING internal */
-#define IMX258_VTS_30FPS		0x0c98
+#define IMX258_VTS_30FPS		0x0c50
 #define IMX258_VTS_30FPS_2K		0x0638
 #define IMX258_VTS_30FPS_VGA		0x034c
 #define IMX258_VTS_MAX			0xffff
@@ -46,7 +46,7 @@
 /* Analog gain control */
 #define IMX258_REG_ANALOG_GAIN		0x0204
 #define IMX258_ANA_GAIN_MIN		0
-#define IMX258_ANA_GAIN_MAX		0x1fff
+#define IMX258_ANA_GAIN_MAX		480
 #define IMX258_ANA_GAIN_STEP		1
 #define IMX258_ANA_GAIN_DEFAULT		0x0
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/imx274.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/imx274.c
@@ -1235,6 +1235,8 @@
 	ret = imx274_set_frame_interval(imx274, fi->interval);
 
 	if (!ret) {
+		fi->interval = imx274->frame_interval;
+
 		/*
 		 * exposure time range is decided by frame interval
 		 * need to update it after frame interval changes
@@ -1730,9 +1732,9 @@
 		__func__, frame_interval.numerator,
 		frame_interval.denominator);
 
-	if (frame_interval.numerator == 0) {
-		err = -EINVAL;
-		goto fail;
+	if (frame_interval.numerator == 0 || frame_interval.denominator == 0) {
+		frame_interval.denominator = IMX274_DEF_FRAME_RATE;
+		frame_interval.numerator = 1;
 	}
 
 	req_frame_rate = (u32)(frame_interval.denominator
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/ir-kbd-i2c.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/ir-kbd-i2c.c
@@ -678,8 +678,8 @@
 		goto out_unlock;
 	}
 
-	i = i2c_master_recv(ir->tx_c, buf, 1);
-	if (i != 1) {
+	ret = i2c_master_recv(ir->tx_c, buf, 1);
+	if (ret != 1) {
 		dev_err(&ir->rc->dev, "i2c_master_recv failed with %d\n", ret);
 		ret = -EIO;
 		goto out_unlock;
@@ -791,6 +791,7 @@
 		rc_proto    = RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC6_MCE |
 							RC_PROTO_BIT_RC6_6A_32;
 		ir_codes    = RC_MAP_HAUPPAUGE;
+		ir->polling_interval = 125;
 		probe_tx = true;
 		break;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/m5mols/m5mols_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/m5mols/m5mols_core.c
@@ -488,7 +488,7 @@
 	do {
 		if (code == m5mols_default_ffmt[type].code)
 			return type;
-	} while (type++ != SIZE_DEFAULT_FFMT);
+	} while (++type != SIZE_DEFAULT_FFMT);
 
 	return 0;
 }
@@ -764,7 +764,8 @@
 
 		ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies);
 		if (ret) {
-			info->set_power(&client->dev, 0);
+			if (info->set_power)
+				info->set_power(&client->dev, 0);
 			return ret;
 		}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/max2175.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/max2175.c
@@ -503,7 +503,7 @@
 	}
 }
 
-static bool max2175_set_csm_mode(struct max2175 *ctx,
+static int max2175_set_csm_mode(struct max2175 *ctx,
 			  enum max2175_csm_mode new_mode)
 {
 	int ret = max2175_poll_csm_ready(ctx);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/mt9p031.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/mt9p031.c
@@ -78,7 +78,9 @@
 #define		MT9P031_PIXEL_CLOCK_INVERT		(1 << 15)
 #define		MT9P031_PIXEL_CLOCK_SHIFT(n)		((n) << 8)
 #define		MT9P031_PIXEL_CLOCK_DIVIDE(n)		((n) << 0)
-#define MT9P031_FRAME_RESTART				0x0b
+#define MT9P031_RESTART					0x0b
+#define		MT9P031_FRAME_PAUSE_RESTART		(1 << 1)
+#define		MT9P031_FRAME_RESTART			(1 << 0)
 #define MT9P031_SHUTTER_DELAY				0x0c
 #define MT9P031_RST					0x0d
 #define		MT9P031_RST_ENABLE			1
@@ -445,9 +447,23 @@
 static int mt9p031_s_stream(struct v4l2_subdev *subdev, int enable)
 {
 	struct mt9p031 *mt9p031 = to_mt9p031(subdev);
+	struct i2c_client *client = v4l2_get_subdevdata(subdev);
+	int val;
 	int ret;
 
 	if (!enable) {
+		/* enable pause restart */
+		val = MT9P031_FRAME_PAUSE_RESTART;
+		ret = mt9p031_write(client, MT9P031_RESTART, val);
+		if (ret < 0)
+			return ret;
+
+		/* enable restart + keep pause restart set */
+		val |= MT9P031_FRAME_RESTART;
+		ret = mt9p031_write(client, MT9P031_RESTART, val);
+		if (ret < 0)
+			return ret;
+
 		/* Stop sensor readout */
 		ret = mt9p031_set_output_control(mt9p031,
 						 MT9P031_OUTPUT_CONTROL_CEN, 0);
@@ -467,6 +483,16 @@
 	if (ret < 0)
 		return ret;
 
+	/*
+	 * - clear pause restart
+	 * - don't clear restart as clearing restart manually can cause
+	 *   undefined behavior
+	 */
+	val = MT9P031_FRAME_RESTART;
+	ret = mt9p031_write(client, MT9P031_RESTART, val);
+	if (ret < 0)
+		return ret;
+
 	return mt9p031_pll_enable(mt9p031);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/mt9v032.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/mt9v032.c
@@ -428,10 +428,12 @@
 				  struct v4l2_subdev_pad_config *cfg,
 				  struct v4l2_subdev_mbus_code_enum *code)
 {
+	struct mt9v032 *mt9v032 = to_mt9v032(subdev);
+
 	if (code->index > 0)
 		return -EINVAL;
 
-	code->code = MEDIA_BUS_FMT_SGRBG10_1X10;
+	code->code = mt9v032->format.code;
 	return 0;
 }
 
@@ -439,7 +441,11 @@
 				   struct v4l2_subdev_pad_config *cfg,
 				   struct v4l2_subdev_frame_size_enum *fse)
 {
-	if (fse->index >= 3 || fse->code != MEDIA_BUS_FMT_SGRBG10_1X10)
+	struct mt9v032 *mt9v032 = to_mt9v032(subdev);
+
+	if (fse->index >= 3)
+		return -EINVAL;
+	if (mt9v032->format.code != fse->code)
 		return -EINVAL;
 
 	fse->min_width = MT9V032_WINDOW_WIDTH_DEF / (1 << fse->index);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/ov2659.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/ov2659.c
@@ -419,10 +419,14 @@
 	{ REG_TIMING_YINC, 0x11 },
 	{ REG_TIMING_VERT_FORMAT, 0x80 },
 	{ REG_TIMING_HORIZ_FORMAT, 0x00 },
+	{ 0x370a, 0x12 },
 	{ 0x3a03, 0xe8 },
 	{ 0x3a09, 0x6f },
 	{ 0x3a0b, 0x5d },
 	{ 0x3a15, 0x9a },
+	{ REG_VFIFO_READ_START_H, 0x00 },
+	{ REG_VFIFO_READ_START_L, 0x80 },
+	{ REG_ISP_CTRL02, 0x00 },
 	{ REG_NULL, 0x00 },
 };
 
@@ -1201,11 +1205,15 @@
 		goto unlock;
 	}
 
-	ov2659_set_pixel_clock(ov2659);
-	ov2659_set_frame_size(ov2659);
-	ov2659_set_format(ov2659);
-	ov2659_set_streaming(ov2659, 1);
-	ov2659->streaming = on;
+	ret = ov2659_set_pixel_clock(ov2659);
+	if (!ret)
+		ret = ov2659_set_frame_size(ov2659);
+	if (!ret)
+		ret = ov2659_set_format(ov2659);
+	if (!ret) {
+		ov2659_set_streaming(ov2659, 1);
+		ov2659->streaming = on;
+	}
 
 unlock:
 	mutex_unlock(&ov2659->lock);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/ov2680.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/ov2680.c
@@ -85,15 +85,8 @@
 
 struct ov2680_ctrls {
 	struct v4l2_ctrl_handler handler;
-	struct {
-		struct v4l2_ctrl *auto_exp;
-		struct v4l2_ctrl *exposure;
-	};
-	struct {
-		struct v4l2_ctrl *auto_gain;
-		struct v4l2_ctrl *gain;
-	};
-
+	struct v4l2_ctrl *exposure;
+	struct v4l2_ctrl *gain;
 	struct v4l2_ctrl *hflip;
 	struct v4l2_ctrl *vflip;
 	struct v4l2_ctrl *test_pattern;
@@ -143,6 +136,7 @@
 	{0x380e, 0x02}, {0x380f, 0x84}, {0x3811, 0x04}, {0x3813, 0x04},
 	{0x3814, 0x31}, {0x3815, 0x31}, {0x3820, 0xc0}, {0x4008, 0x00},
 	{0x4009, 0x03}, {0x4837, 0x1e}, {0x3501, 0x4e}, {0x3502, 0xe0},
+	{0x3503, 0x03},
 };
 
 static const struct reg_value ov2680_setting_30fps_720P_1280_720[] = {
@@ -321,70 +315,49 @@
 	usleep_range(5000, 10000);
 }
 
-static int ov2680_bayer_order(struct ov2680_dev *sensor)
+static void ov2680_set_bayer_order(struct ov2680_dev *sensor)
 {
-	u32 format1;
-	u32 format2;
-	u32 hv_flip;
-	int ret;
-
-	ret = ov2680_read_reg(sensor, OV2680_REG_FORMAT1, &format1);
-	if (ret < 0)
-		return ret;
+	int hv_flip = 0;
 
-	ret = ov2680_read_reg(sensor, OV2680_REG_FORMAT2, &format2);
-	if (ret < 0)
-		return ret;
+	if (sensor->ctrls.vflip && sensor->ctrls.vflip->val)
+		hv_flip += 1;
 
-	hv_flip = (format2 & BIT(2)  << 1) | (format1 & BIT(2));
+	if (sensor->ctrls.hflip && sensor->ctrls.hflip->val)
+		hv_flip += 2;
 
 	sensor->fmt.code = ov2680_hv_flip_bayer_order[hv_flip];
-
-	return 0;
 }
 
-static int ov2680_vflip_enable(struct ov2680_dev *sensor)
+static int ov2680_set_vflip(struct ov2680_dev *sensor, s32 val)
 {
 	int ret;
 
-	ret = ov2680_mod_reg(sensor, OV2680_REG_FORMAT1, BIT(2), BIT(2));
-	if (ret < 0)
-		return ret;
+	if (sensor->is_streaming)
+		return -EBUSY;
 
-	return ov2680_bayer_order(sensor);
-}
-
-static int ov2680_vflip_disable(struct ov2680_dev *sensor)
-{
-	int ret;
-
-	ret = ov2680_mod_reg(sensor, OV2680_REG_FORMAT1, BIT(2), BIT(0));
+	ret = ov2680_mod_reg(sensor, OV2680_REG_FORMAT1,
+			     BIT(2), val ? BIT(2) : 0);
 	if (ret < 0)
 		return ret;
 
-	return ov2680_bayer_order(sensor);
+	ov2680_set_bayer_order(sensor);
+	return 0;
 }
 
-static int ov2680_hflip_enable(struct ov2680_dev *sensor)
+static int ov2680_set_hflip(struct ov2680_dev *sensor, s32 val)
 {
 	int ret;
 
-	ret = ov2680_mod_reg(sensor, OV2680_REG_FORMAT2, BIT(2), BIT(2));
-	if (ret < 0)
-		return ret;
+	if (sensor->is_streaming)
+		return -EBUSY;
 
-	return ov2680_bayer_order(sensor);
-}
-
-static int ov2680_hflip_disable(struct ov2680_dev *sensor)
-{
-	int ret;
-
-	ret = ov2680_mod_reg(sensor, OV2680_REG_FORMAT2, BIT(2), BIT(0));
+	ret = ov2680_mod_reg(sensor, OV2680_REG_FORMAT2,
+			     BIT(2), val ? BIT(2) : 0);
 	if (ret < 0)
 		return ret;
 
-	return ov2680_bayer_order(sensor);
+	ov2680_set_bayer_order(sensor);
+	return 0;
 }
 
 static int ov2680_test_pattern_set(struct ov2680_dev *sensor, int value)
@@ -405,69 +378,15 @@
 	return 0;
 }
 
-static int ov2680_gain_set(struct ov2680_dev *sensor, bool auto_gain)
+static int ov2680_gain_set(struct ov2680_dev *sensor, u32 gain)
 {
-	struct ov2680_ctrls *ctrls = &sensor->ctrls;
-	u32 gain;
-	int ret;
-
-	ret = ov2680_mod_reg(sensor, OV2680_REG_R_MANUAL, BIT(1),
-			     auto_gain ? 0 : BIT(1));
-	if (ret < 0)
-		return ret;
-
-	if (auto_gain || !ctrls->gain->is_new)
-		return 0;
-
-	gain = ctrls->gain->val;
-
-	ret = ov2680_write_reg16(sensor, OV2680_REG_GAIN_PK, gain);
-
-	return 0;
+	return ov2680_write_reg16(sensor, OV2680_REG_GAIN_PK, gain);
 }
 
-static int ov2680_gain_get(struct ov2680_dev *sensor)
+static int ov2680_exposure_set(struct ov2680_dev *sensor, u32 exp)
 {
-	u32 gain;
-	int ret;
-
-	ret = ov2680_read_reg16(sensor, OV2680_REG_GAIN_PK, &gain);
-	if (ret)
-		return ret;
-
-	return gain;
-}
-
-static int ov2680_exposure_set(struct ov2680_dev *sensor, bool auto_exp)
-{
-	struct ov2680_ctrls *ctrls = &sensor->ctrls;
-	u32 exp;
-	int ret;
-
-	ret = ov2680_mod_reg(sensor, OV2680_REG_R_MANUAL, BIT(0),
-			     auto_exp ? 0 : BIT(0));
-	if (ret < 0)
-		return ret;
-
-	if (auto_exp || !ctrls->exposure->is_new)
-		return 0;
-
-	exp = (u32)ctrls->exposure->val;
-	exp <<= 4;
-
-	return ov2680_write_reg24(sensor, OV2680_REG_EXPOSURE_PK_HIGH, exp);
-}
-
-static int ov2680_exposure_get(struct ov2680_dev *sensor)
-{
-	int ret;
-	u32 exp;
-
-	ret = ov2680_read_reg24(sensor, OV2680_REG_EXPOSURE_PK_HIGH, &exp);
-	if (ret)
-		return ret;
-
-	return exp >> 4;
+	return ov2680_write_reg24(sensor, OV2680_REG_EXPOSURE_PK_HIGH,
+				  exp << 4);
 }
 
 static int ov2680_stream_enable(struct ov2680_dev *sensor)
@@ -482,33 +401,17 @@
 
 static int ov2680_mode_set(struct ov2680_dev *sensor)
 {
-	struct ov2680_ctrls *ctrls = &sensor->ctrls;
 	int ret;
 
-	ret = ov2680_gain_set(sensor, false);
-	if (ret < 0)
-		return ret;
-
-	ret = ov2680_exposure_set(sensor, false);
+	ret = ov2680_load_regs(sensor, sensor->current_mode);
 	if (ret < 0)
 		return ret;
 
-	ret = ov2680_load_regs(sensor, sensor->current_mode);
+	/* Restore value of all ctrls */
+	ret = __v4l2_ctrl_handler_setup(&sensor->ctrls.handler);
 	if (ret < 0)
 		return ret;
 
-	if (ctrls->auto_gain->val) {
-		ret = ov2680_gain_set(sensor, true);
-		if (ret < 0)
-			return ret;
-	}
-
-	if (ctrls->auto_exp->val == V4L2_EXPOSURE_AUTO) {
-		ret = ov2680_exposure_set(sensor, true);
-		if (ret < 0)
-			return ret;
-	}
-
 	sensor->mode_pending_changes = false;
 
 	return 0;
@@ -556,7 +459,7 @@
 		ret = ov2680_write_reg(sensor, OV2680_REG_SOFT_RESET, 0x01);
 		if (ret != 0) {
 			dev_err(dev, "sensor soft reset failed\n");
-			return ret;
+			goto err_disable_regulators;
 		}
 		usleep_range(1000, 2000);
 	} else {
@@ -566,7 +469,7 @@
 
 	ret = clk_prepare_enable(sensor->xvclk);
 	if (ret < 0)
-		return ret;
+		goto err_disable_regulators;
 
 	sensor->is_enabled = true;
 
@@ -576,6 +479,10 @@
 	ov2680_stream_disable(sensor);
 
 	return 0;
+
+err_disable_regulators:
+	regulator_bulk_disable(OV2680_NUM_SUPPLIES, sensor->supplies);
+	return ret;
 }
 
 static int ov2680_s_power(struct v4l2_subdev *sd, int on)
@@ -590,15 +497,10 @@
 	else
 		ret = ov2680_power_off(sensor);
 
-	mutex_unlock(&sensor->lock);
-
-	if (on && ret == 0) {
-		ret = v4l2_ctrl_handler_setup(&sensor->ctrls.handler);
-		if (ret < 0)
-			return ret;
-
+	if (on && ret == 0)
 		ret = ov2680_mode_restore(sensor);
-	}
+
+	mutex_unlock(&sensor->lock);
 
 	return ret;
 }
@@ -793,66 +695,23 @@
 	return 0;
 }
 
-static int ov2680_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
-{
-	struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
-	struct ov2680_dev *sensor = to_ov2680_dev(sd);
-	struct ov2680_ctrls *ctrls = &sensor->ctrls;
-	int val;
-
-	if (!sensor->is_enabled)
-		return 0;
-
-	switch (ctrl->id) {
-	case V4L2_CID_GAIN:
-		val = ov2680_gain_get(sensor);
-		if (val < 0)
-			return val;
-		ctrls->gain->val = val;
-		break;
-	case V4L2_CID_EXPOSURE:
-		val = ov2680_exposure_get(sensor);
-		if (val < 0)
-			return val;
-		ctrls->exposure->val = val;
-		break;
-	}
-
-	return 0;
-}
-
 static int ov2680_s_ctrl(struct v4l2_ctrl *ctrl)
 {
 	struct v4l2_subdev *sd = ctrl_to_sd(ctrl);
 	struct ov2680_dev *sensor = to_ov2680_dev(sd);
-	struct ov2680_ctrls *ctrls = &sensor->ctrls;
 
 	if (!sensor->is_enabled)
 		return 0;
 
 	switch (ctrl->id) {
-	case V4L2_CID_AUTOGAIN:
-		return ov2680_gain_set(sensor, !!ctrl->val);
 	case V4L2_CID_GAIN:
-		return ov2680_gain_set(sensor, !!ctrls->auto_gain->val);
-	case V4L2_CID_EXPOSURE_AUTO:
-		return ov2680_exposure_set(sensor, !!ctrl->val);
+		return ov2680_gain_set(sensor, ctrl->val);
 	case V4L2_CID_EXPOSURE:
-		return ov2680_exposure_set(sensor, !!ctrls->auto_exp->val);
+		return ov2680_exposure_set(sensor, ctrl->val);
 	case V4L2_CID_VFLIP:
-		if (sensor->is_streaming)
-			return -EBUSY;
-		if (ctrl->val)
-			return ov2680_vflip_enable(sensor);
-		else
-			return ov2680_vflip_disable(sensor);
+		return ov2680_set_vflip(sensor, ctrl->val);
 	case V4L2_CID_HFLIP:
-		if (sensor->is_streaming)
-			return -EBUSY;
-		if (ctrl->val)
-			return ov2680_hflip_enable(sensor);
-		else
-			return ov2680_hflip_disable(sensor);
+		return ov2680_set_hflip(sensor, ctrl->val);
 	case V4L2_CID_TEST_PATTERN:
 		return ov2680_test_pattern_set(sensor, ctrl->val);
 	default:
@@ -863,7 +722,6 @@
 }
 
 static const struct v4l2_ctrl_ops ov2680_ctrl_ops = {
-	.g_volatile_ctrl = ov2680_g_volatile_ctrl,
 	.s_ctrl = ov2680_s_ctrl,
 };
 
@@ -935,7 +793,7 @@
 	if (ret < 0)
 		return ret;
 
-	v4l2_ctrl_handler_init(hdl, 7);
+	v4l2_ctrl_handler_init(hdl, 5);
 
 	hdl->lock = &sensor->lock;
 
@@ -947,16 +805,9 @@
 					ARRAY_SIZE(test_pattern_menu) - 1,
 					0, 0, test_pattern_menu);
 
-	ctrls->auto_exp = v4l2_ctrl_new_std_menu(hdl, ops,
-						 V4L2_CID_EXPOSURE_AUTO,
-						 V4L2_EXPOSURE_MANUAL, 0,
-						 V4L2_EXPOSURE_AUTO);
-
 	ctrls->exposure = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_EXPOSURE,
 					    0, 32767, 1, 0);
 
-	ctrls->auto_gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_AUTOGAIN,
-					     0, 1, 1, 1);
 	ctrls->gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAIN, 0, 2047, 1, 0);
 
 	if (hdl->error) {
@@ -964,11 +815,8 @@
 		goto cleanup_entity;
 	}
 
-	ctrls->gain->flags |= V4L2_CTRL_FLAG_VOLATILE;
-	ctrls->exposure->flags |= V4L2_CTRL_FLAG_VOLATILE;
-
-	v4l2_ctrl_auto_cluster(2, &ctrls->auto_gain, 0, true);
-	v4l2_ctrl_auto_cluster(2, &ctrls->auto_exp, 1, true);
+	ctrls->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
+	ctrls->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
 
 	sensor->sd.ctrl_handler = hdl;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/ov5640.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/ov5640.c
@@ -34,6 +34,8 @@
 #define OV5640_REG_SYS_RESET02		0x3002
 #define OV5640_REG_SYS_CLOCK_ENABLE02	0x3006
 #define OV5640_REG_SYS_CTRL0		0x3008
+#define OV5640_REG_SYS_CTRL0_SW_PWDN	0x42
+#define OV5640_REG_SYS_CTRL0_SW_PWUP	0x02
 #define OV5640_REG_CHIP_ID		0x300a
 #define OV5640_REG_IO_MIPI_CTRL00	0x300e
 #define OV5640_REG_PAD_OUTPUT_ENABLE01	0x3017
@@ -132,6 +134,8 @@
 	{ MEDIA_BUS_FMT_JPEG_1X8, V4L2_COLORSPACE_JPEG, },
 	{ MEDIA_BUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_SRGB, },
 	{ MEDIA_BUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_SRGB, },
+	{ MEDIA_BUS_FMT_UYVY8_1X16, V4L2_COLORSPACE_SRGB, },
+	{ MEDIA_BUS_FMT_YUYV8_1X16, V4L2_COLORSPACE_SRGB, },
 	{ MEDIA_BUS_FMT_RGB565_2X8_LE, V4L2_COLORSPACE_SRGB, },
 	{ MEDIA_BUS_FMT_RGB565_2X8_BE, V4L2_COLORSPACE_SRGB, },
 	{ MEDIA_BUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB, },
@@ -272,8 +276,7 @@
 /* YUV422 UYVY VGA@30fps */
 static const struct reg_value ov5640_init_setting_30fps_VGA[] = {
 	{0x3103, 0x11, 0, 0}, {0x3008, 0x82, 0, 5}, {0x3008, 0x42, 0, 0},
-	{0x3103, 0x03, 0, 0}, {0x3017, 0x00, 0, 0}, {0x3018, 0x00, 0, 0},
-	{0x3630, 0x36, 0, 0},
+	{0x3103, 0x03, 0, 0}, {0x3630, 0x36, 0, 0},
 	{0x3631, 0x0e, 0, 0}, {0x3632, 0xe2, 0, 0}, {0x3633, 0x12, 0, 0},
 	{0x3621, 0xe0, 0, 0}, {0x3704, 0xa0, 0, 0}, {0x3703, 0x5a, 0, 0},
 	{0x3715, 0x78, 0, 0}, {0x3717, 0x01, 0, 0}, {0x370b, 0x60, 0, 0},
@@ -740,7 +743,7 @@
  *               +->| PLL Root Div | - reg 0x3037, bit 4
  *                  +-+------------+
  *                    |  +---------+
- *                    +->| Bit Div | - reg 0x3035, bits 0-3
+ *                    +->| Bit Div | - reg 0x3034, bits 0-3
  *                       +-+-------+
  *                         |  +-------------+
  *                         +->| SCLK Div    | - reg 0x3108, bits 0-1
@@ -874,7 +877,7 @@
 			 * We have reached the maximum allowed PLL1 output,
 			 * increase sysdiv.
 			 */
-			if (!rate)
+			if (!_rate)
 				break;
 
 			/*
@@ -1109,6 +1112,12 @@
 		val = regs->val;
 		mask = regs->mask;
 
+		/* remain in power down mode for DVP */
+		if (regs->reg_addr == OV5640_REG_SYS_CTRL0 &&
+		    val == OV5640_REG_SYS_CTRL0_SW_PWUP &&
+		    sensor->ep.bus_type != V4L2_MBUS_CSI2_DPHY)
+			continue;
+
 		if (mask)
 			ret = ov5640_mod_reg(sensor, reg_addr, mask, val);
 		else
@@ -1199,96 +1208,9 @@
 
 static int ov5640_set_stream_dvp(struct ov5640_dev *sensor, bool on)
 {
-	int ret;
-	unsigned int flags = sensor->ep.bus.parallel.flags;
-	u8 pclk_pol = 0;
-	u8 hsync_pol = 0;
-	u8 vsync_pol = 0;
-
-	/*
-	 * Note about parallel port configuration.
-	 *
-	 * When configured in parallel mode, the OV5640 will
-	 * output 10 bits data on DVP data lines [9:0].
-	 * If only 8 bits data are wanted, the 8 bits data lines
-	 * of the camera interface must be physically connected
-	 * on the DVP data lines [9:2].
-	 *
-	 * Control lines polarity can be configured through
-	 * devicetree endpoint control lines properties.
-	 * If no endpoint control lines properties are set,
-	 * polarity will be as below:
-	 * - VSYNC:	active high
-	 * - HREF:	active low
-	 * - PCLK:	active low
-	 */
-
-	if (on) {
-		/*
-		 * configure parallel port control lines polarity
-		 *
-		 * POLARITY CTRL0
-		 * - [5]:	PCLK polarity (0: active low, 1: active high)
-		 * - [1]:	HREF polarity (0: active low, 1: active high)
-		 * - [0]:	VSYNC polarity (mismatch here between
-		 *		datasheet and hardware, 0 is active high
-		 *		and 1 is active low...)
-		 */
-		if (flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
-			pclk_pol = 1;
-		if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH)
-			hsync_pol = 1;
-		if (flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
-			vsync_pol = 1;
-
-		ret = ov5640_write_reg(sensor,
-				       OV5640_REG_POLARITY_CTRL00,
-				       (pclk_pol << 5) |
-				       (hsync_pol << 1) |
-				       vsync_pol);
-
-		if (ret)
-			return ret;
-	}
-
-	/*
-	 * powerdown MIPI TX/RX PHY & disable MIPI
-	 *
-	 * MIPI CONTROL 00
-	 * 4:	 PWDN PHY TX
-	 * 3:	 PWDN PHY RX
-	 * 2:	 MIPI enable
-	 */
-	ret = ov5640_write_reg(sensor,
-			       OV5640_REG_IO_MIPI_CTRL00, on ? 0x18 : 0);
-	if (ret)
-		return ret;
-
-	/*
-	 * enable VSYNC/HREF/PCLK DVP control lines
-	 * & D[9:6] DVP data lines
-	 *
-	 * PAD OUTPUT ENABLE 01
-	 * - 6:		VSYNC output enable
-	 * - 5:		HREF output enable
-	 * - 4:		PCLK output enable
-	 * - [3:0]:	D[9:6] output enable
-	 */
-	ret = ov5640_write_reg(sensor,
-			       OV5640_REG_PAD_OUTPUT_ENABLE01,
-			       on ? 0x7f : 0);
-	if (ret)
-		return ret;
-
-	/*
-	 * enable D[5:0] DVP data lines
-	 *
-	 * PAD OUTPUT ENABLE 02
-	 * - [7:2]:	D[5:0] output enable
-	 */
-	return ov5640_write_reg(sensor,
-				OV5640_REG_PAD_OUTPUT_ENABLE02,
-				on ? 0xfc : 0);
+	return ov5640_write_reg(sensor, OV5640_REG_SYS_CTRL0, on ?
+				OV5640_REG_SYS_CTRL0_SW_PWUP :
+				OV5640_REG_SYS_CTRL0_SW_PWDN);
 }
 
 static int ov5640_set_stream_mipi(struct ov5640_dev *sensor, bool on)
@@ -1448,6 +1370,7 @@
 			light_freq = 50;
 		} else {
 			/* 60Hz */
+			light_freq = 60;
 		}
 	}
 
@@ -1611,6 +1534,11 @@
 	    !(mode->hact == 640 && mode->vact == 480))
 		return NULL;
 
+	/* 2592x1944 only works at 15fps max */
+	if ((mode->hact == 2592 && mode->vact == 1944) &&
+	    fr > OV5640_15_FPS)
+		return NULL;
+
 	return mode;
 }
 
@@ -1982,6 +1910,153 @@
 	clk_disable_unprepare(sensor->xclk);
 }
 
+static int ov5640_set_power_mipi(struct ov5640_dev *sensor, bool on)
+{
+	int ret;
+
+	if (!on) {
+		/* Reset MIPI bus settings to their default values. */
+		ov5640_write_reg(sensor, OV5640_REG_IO_MIPI_CTRL00, 0x58);
+		ov5640_write_reg(sensor, OV5640_REG_MIPI_CTRL00, 0x04);
+		ov5640_write_reg(sensor, OV5640_REG_PAD_OUTPUT00, 0x00);
+		return 0;
+	}
+
+	/*
+	 * Power up MIPI HS Tx and LS Rx; 2 data lanes mode
+	 *
+	 * 0x300e = 0x40
+	 * [7:5] = 010	: 2 data lanes mode (see FIXME note in
+	 *		  "ov5640_set_stream_mipi()")
+	 * [4] = 0	: Power up MIPI HS Tx
+	 * [3] = 0	: Power up MIPI LS Rx
+	 * [2] = 1	: MIPI interface enabled
+	 */
+	ret = ov5640_write_reg(sensor, OV5640_REG_IO_MIPI_CTRL00, 0x44);
+	if (ret)
+		return ret;
+
+	/*
+	 * Gate clock and set LP11 in 'no packets mode' (idle)
+	 *
+	 * 0x4800 = 0x24
+	 * [5] = 1	: Gate clock when 'no packets'
+	 * [2] = 1	: MIPI bus in LP11 when 'no packets'
+	 */
+	ret = ov5640_write_reg(sensor, OV5640_REG_MIPI_CTRL00, 0x24);
+	if (ret)
+		return ret;
+
+	/*
+	 * Set data lanes and clock in LP11 when 'sleeping'
+	 *
+	 * 0x3019 = 0x70
+	 * [6] = 1	: MIPI data lane 2 in LP11 when 'sleeping'
+	 * [5] = 1	: MIPI data lane 1 in LP11 when 'sleeping'
+	 * [4] = 1	: MIPI clock lane in LP11 when 'sleeping'
+	 */
+	ret = ov5640_write_reg(sensor, OV5640_REG_PAD_OUTPUT00, 0x70);
+	if (ret)
+		return ret;
+
+	/* Give lanes some time to coax into LP11 state. */
+	usleep_range(500, 1000);
+
+	return 0;
+}
+
+static int ov5640_set_power_dvp(struct ov5640_dev *sensor, bool on)
+{
+	unsigned int flags = sensor->ep.bus.parallel.flags;
+	u8 pclk_pol = 0;
+	u8 hsync_pol = 0;
+	u8 vsync_pol = 0;
+	int ret;
+
+	if (!on) {
+		/* Reset settings to their default values. */
+		ov5640_write_reg(sensor, OV5640_REG_IO_MIPI_CTRL00, 0x58);
+		ov5640_write_reg(sensor, OV5640_REG_POLARITY_CTRL00, 0x20);
+		ov5640_write_reg(sensor, OV5640_REG_PAD_OUTPUT_ENABLE01, 0x00);
+		ov5640_write_reg(sensor, OV5640_REG_PAD_OUTPUT_ENABLE02, 0x00);
+		return 0;
+	}
+
+	/*
+	 * Note about parallel port configuration.
+	 *
+	 * When configured in parallel mode, the OV5640 will
+	 * output 10 bits data on DVP data lines [9:0].
+	 * If only 8 bits data are wanted, the 8 bits data lines
+	 * of the camera interface must be physically connected
+	 * on the DVP data lines [9:2].
+	 *
+	 * Control lines polarity can be configured through
+	 * devicetree endpoint control lines properties.
+	 * If no endpoint control lines properties are set,
+	 * polarity will be as below:
+	 * - VSYNC:	active high
+	 * - HREF:	active low
+	 * - PCLK:	active low
+	 */
+	/*
+	 * configure parallel port control lines polarity
+	 *
+	 * POLARITY CTRL0
+	 * - [5]:	PCLK polarity (0: active low, 1: active high)
+	 * - [1]:	HREF polarity (0: active low, 1: active high)
+	 * - [0]:	VSYNC polarity (mismatch here between
+	 *		datasheet and hardware, 0 is active high
+	 *		and 1 is active low...)
+	 */
+	if (flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
+		pclk_pol = 1;
+	if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH)
+		hsync_pol = 1;
+	if (flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)
+		vsync_pol = 1;
+
+	ret = ov5640_write_reg(sensor, OV5640_REG_POLARITY_CTRL00,
+			       (pclk_pol << 5) | (hsync_pol << 1) | vsync_pol);
+
+	if (ret)
+		return ret;
+
+	/*
+	 * powerdown MIPI TX/RX PHY & disable MIPI
+	 *
+	 * MIPI CONTROL 00
+	 * 4:	 PWDN PHY TX
+	 * 3:	 PWDN PHY RX
+	 * 2:	 MIPI enable
+	 */
+	ret = ov5640_write_reg(sensor, OV5640_REG_IO_MIPI_CTRL00, 0x18);
+	if (ret)
+		return ret;
+
+	/*
+	 * enable VSYNC/HREF/PCLK DVP control lines
+	 * & D[9:6] DVP data lines
+	 *
+	 * PAD OUTPUT ENABLE 01
+	 * - 6:		VSYNC output enable
+	 * - 5:		HREF output enable
+	 * - 4:		PCLK output enable
+	 * - [3:0]:	D[9:6] output enable
+	 */
+	ret = ov5640_write_reg(sensor, OV5640_REG_PAD_OUTPUT_ENABLE01, 0x7f);
+	if (ret)
+		return ret;
+
+	/*
+	 * enable D[5:0] DVP data lines
+	 *
+	 * PAD OUTPUT ENABLE 02
+	 * - [7:2]:	D[5:0] output enable
+	 */
+	return ov5640_write_reg(sensor, OV5640_REG_PAD_OUTPUT_ENABLE02, 0xfc);
+}
+
 static int ov5640_set_power(struct ov5640_dev *sensor, bool on)
 {
 	int ret = 0;
@@ -1994,67 +2069,17 @@
 		ret = ov5640_restore_mode(sensor);
 		if (ret)
 			goto power_off;
+	}
 
-		/* We're done here for DVP bus, while CSI-2 needs setup. */
-		if (sensor->ep.bus_type != V4L2_MBUS_CSI2_DPHY)
-			return 0;
-
-		/*
-		 * Power up MIPI HS Tx and LS Rx; 2 data lanes mode
-		 *
-		 * 0x300e = 0x40
-		 * [7:5] = 010	: 2 data lanes mode (see FIXME note in
-		 *		  "ov5640_set_stream_mipi()")
-		 * [4] = 0	: Power up MIPI HS Tx
-		 * [3] = 0	: Power up MIPI LS Rx
-		 * [2] = 0	: MIPI interface disabled
-		 */
-		ret = ov5640_write_reg(sensor,
-				       OV5640_REG_IO_MIPI_CTRL00, 0x40);
-		if (ret)
-			goto power_off;
-
-		/*
-		 * Gate clock and set LP11 in 'no packets mode' (idle)
-		 *
-		 * 0x4800 = 0x24
-		 * [5] = 1	: Gate clock when 'no packets'
-		 * [2] = 1	: MIPI bus in LP11 when 'no packets'
-		 */
-		ret = ov5640_write_reg(sensor,
-				       OV5640_REG_MIPI_CTRL00, 0x24);
-		if (ret)
-			goto power_off;
-
-		/*
-		 * Set data lanes and clock in LP11 when 'sleeping'
-		 *
-		 * 0x3019 = 0x70
-		 * [6] = 1	: MIPI data lane 2 in LP11 when 'sleeping'
-		 * [5] = 1	: MIPI data lane 1 in LP11 when 'sleeping'
-		 * [4] = 1	: MIPI clock lane in LP11 when 'sleeping'
-		 */
-		ret = ov5640_write_reg(sensor,
-				       OV5640_REG_PAD_OUTPUT00, 0x70);
-		if (ret)
-			goto power_off;
-
-		/* Give lanes some time to coax into LP11 state. */
-		usleep_range(500, 1000);
-
-	} else {
-		if (sensor->ep.bus_type == V4L2_MBUS_CSI2_DPHY) {
-			/* Reset MIPI bus settings to their default values. */
-			ov5640_write_reg(sensor,
-					 OV5640_REG_IO_MIPI_CTRL00, 0x58);
-			ov5640_write_reg(sensor,
-					 OV5640_REG_MIPI_CTRL00, 0x04);
-			ov5640_write_reg(sensor,
-					 OV5640_REG_PAD_OUTPUT00, 0x00);
-		}
+	if (sensor->ep.bus_type == V4L2_MBUS_CSI2_DPHY)
+		ret = ov5640_set_power_mipi(sensor, on);
+	else
+		ret = ov5640_set_power_dvp(sensor, on);
+	if (ret)
+		goto power_off;
 
+	if (!on)
 		ov5640_set_power_off(sensor);
-	}
 
 	return 0;
 
@@ -2247,11 +2272,13 @@
 
 	switch (format->code) {
 	case MEDIA_BUS_FMT_UYVY8_2X8:
+	case MEDIA_BUS_FMT_UYVY8_1X16:
 		/* YUV422, UYVY */
 		fmt = 0x3f;
 		mux = OV5640_FMT_MUX_YUV422;
 		break;
 	case MEDIA_BUS_FMT_YUYV8_2X8:
+	case MEDIA_BUS_FMT_YUYV8_1X16:
 		/* YUV422, YUYV */
 		fmt = 0x30;
 		mux = OV5640_FMT_MUX_YUV422;
@@ -2567,6 +2594,13 @@
 
 	/* v4l2_ctrl_lock() locks our own mutex */
 
+	/*
+	 * If the sensor is not powered up by the host driver, do
+	 * not try to access it to update the volatile controls.
+	 */
+	if (sensor->power_count == 0)
+		return 0;
+
 	switch (ctrl->id) {
 	case V4L2_CID_AUTOGAIN:
 		val = ov5640_get_gain(sensor);
@@ -2675,7 +2709,7 @@
 	/* Auto/manual gain */
 	ctrls->auto_gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_AUTOGAIN,
 					     0, 1, 1, 1);
-	ctrls->gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAIN,
+	ctrls->gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_ANALOGUE_GAIN,
 					0, 1023, 1, 0);
 
 	ctrls->saturation = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SATURATION,
@@ -3063,8 +3097,8 @@
 free_ctrls:
 	v4l2_ctrl_handler_free(&sensor->ctrls.handler);
 entity_cleanup:
-	mutex_destroy(&sensor->lock);
 	media_entity_cleanup(&sensor->sd.entity);
+	mutex_destroy(&sensor->lock);
 	return ret;
 }
 
@@ -3074,9 +3108,9 @@
 	struct ov5640_dev *sensor = to_ov5640_dev(sd);
 
 	v4l2_async_unregister_subdev(&sensor->sd);
-	mutex_destroy(&sensor->lock);
 	media_entity_cleanup(&sensor->sd.entity);
 	v4l2_ctrl_handler_free(&sensor->ctrls.handler);
+	mutex_destroy(&sensor->lock);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/ov5670.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/ov5670.c
@@ -2081,7 +2081,8 @@
 
 	/* By default, V4L2_CID_PIXEL_RATE is read only */
 	ov5670->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &ov5670_ctrl_ops,
-					       V4L2_CID_PIXEL_RATE, 0,
+					       V4L2_CID_PIXEL_RATE,
+					       link_freq_configs[0].pixel_rate,
 					       link_freq_configs[0].pixel_rate,
 					       1,
 					       link_freq_configs[0].pixel_rate);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/ov5675.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/ov5675.c
@@ -722,8 +722,10 @@
 				     V4L2_CID_TEST_PATTERN,
 				     ARRAY_SIZE(ov5675_test_pattern_menu) - 1,
 				     0, 0, ov5675_test_pattern_menu);
-	if (ctrl_hdlr->error)
+	if (ctrl_hdlr->error) {
+		v4l2_ctrl_handler_free(ctrl_hdlr);
 		return ctrl_hdlr->error;
+	}
 
 	ov5675->sd.ctrl_handler = ctrl_hdlr;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/ov5695.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/ov5695.c
@@ -971,16 +971,9 @@
 	return ret;
 }
 
-/* Calculate the delay in us by clock rate and clock cycles */
-static inline u32 ov5695_cal_delay(u32 cycles)
-{
-	return DIV_ROUND_UP(cycles, OV5695_XVCLK_FREQ / 1000 / 1000);
-}
-
 static int __ov5695_power_on(struct ov5695 *ov5695)
 {
-	int ret;
-	u32 delay_us;
+	int i, ret;
 	struct device *dev = &ov5695->client->dev;
 
 	ret = clk_prepare_enable(ov5695->xvclk);
@@ -991,21 +984,28 @@
 
 	gpiod_set_value_cansleep(ov5695->reset_gpio, 1);
 
-	ret = regulator_bulk_enable(OV5695_NUM_SUPPLIES, ov5695->supplies);
-	if (ret < 0) {
-		dev_err(dev, "Failed to enable regulators\n");
-		goto disable_clk;
+	/*
+	 * The hardware requires the regulators to be powered on in order,
+	 * so enable them one by one.
+	 */
+	for (i = 0; i < OV5695_NUM_SUPPLIES; i++) {
+		ret = regulator_enable(ov5695->supplies[i].consumer);
+		if (ret) {
+			dev_err(dev, "Failed to enable %s: %d\n",
+				ov5695->supplies[i].supply, ret);
+			goto disable_reg_clk;
+		}
 	}
 
 	gpiod_set_value_cansleep(ov5695->reset_gpio, 0);
 
-	/* 8192 cycles prior to first SCCB transaction */
-	delay_us = ov5695_cal_delay(8192);
-	usleep_range(delay_us, delay_us * 2);
+	usleep_range(1000, 1200);
 
 	return 0;
 
-disable_clk:
+disable_reg_clk:
+	for (--i; i >= 0; i--)
+		regulator_disable(ov5695->supplies[i].consumer);
 	clk_disable_unprepare(ov5695->xvclk);
 
 	return ret;
@@ -1013,9 +1013,22 @@
 
 static void __ov5695_power_off(struct ov5695 *ov5695)
 {
+	struct device *dev = &ov5695->client->dev;
+	int i, ret;
+
 	clk_disable_unprepare(ov5695->xvclk);
 	gpiod_set_value_cansleep(ov5695->reset_gpio, 1);
-	regulator_bulk_disable(OV5695_NUM_SUPPLIES, ov5695->supplies);
+
+	/*
+	 * The hardware requires the regulators to be powered off in order,
+	 * so disable them one by one.
+	 */
+	for (i = OV5695_NUM_SUPPLIES - 1; i >= 0; i--) {
+		ret = regulator_disable(ov5695->supplies[i].consumer);
+		if (ret)
+			dev_err(dev, "Failed to disable %s: %d\n",
+				ov5695->supplies[i].supply, ret);
+	}
 }
 
 static int __maybe_unused ov5695_runtime_resume(struct device *dev)
@@ -1285,7 +1298,7 @@
 	if (clk_get_rate(ov5695->xvclk) != OV5695_XVCLK_FREQ)
 		dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n");
 
-	ov5695->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
+	ov5695->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
 	if (IS_ERR(ov5695->reset_gpio)) {
 		dev_err(dev, "Failed to get reset-gpios\n");
 		return -EINVAL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/ov6650.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/ov6650.c
@@ -130,6 +130,7 @@
 #define CLKRC_24MHz		0xc0
 #define CLKRC_DIV_MASK		0x3f
 #define GET_CLKRC_DIV(x)	(((x) & CLKRC_DIV_MASK) + 1)
+#define DEF_CLKRC		0x00
 
 #define COMA_RESET		BIT(7)
 #define COMA_QCIF		BIT(5)
@@ -200,7 +201,6 @@
 	unsigned long		pclk_max;	/* from resolution and format */
 	struct v4l2_fract	tpf;		/* as requested with s_frame_interval */
 	u32 code;
-	enum v4l2_colorspace	colorspace;
 };
 
 
@@ -213,6 +213,17 @@
 	MEDIA_BUS_FMT_Y8_1X8,
 };
 
+static const struct v4l2_mbus_framefmt ov6650_def_fmt = {
+	.width		= W_CIF,
+	.height		= H_CIF,
+	.code		= MEDIA_BUS_FMT_SBGGR8_1X8,
+	.colorspace	= V4L2_COLORSPACE_SRGB,
+	.field		= V4L2_FIELD_NONE,
+	.ycbcr_enc	= V4L2_YCBCR_ENC_DEFAULT,
+	.quantization	= V4L2_QUANTIZATION_DEFAULT,
+	.xfer_func	= V4L2_XFER_FUNC_DEFAULT,
+};
+
 /* read a register */
 static int ov6650_reg_read(struct i2c_client *client, u8 reg, u8 *val)
 {
@@ -465,38 +476,39 @@
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 	struct ov6650 *priv = to_ov6650(client);
-	struct v4l2_rect rect = sel->r;
 	int ret;
 
 	if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE ||
 	    sel->target != V4L2_SEL_TGT_CROP)
 		return -EINVAL;
 
-	v4l_bound_align_image(&rect.width, 2, W_CIF, 1,
-			      &rect.height, 2, H_CIF, 1, 0);
-	v4l_bound_align_image(&rect.left, DEF_HSTRT << 1,
-			      (DEF_HSTRT << 1) + W_CIF - (__s32)rect.width, 1,
-			      &rect.top, DEF_VSTRT << 1,
-			      (DEF_VSTRT << 1) + H_CIF - (__s32)rect.height, 1,
-			      0);
+	v4l_bound_align_image(&sel->r.width, 2, W_CIF, 1,
+			      &sel->r.height, 2, H_CIF, 1, 0);
+	v4l_bound_align_image(&sel->r.left, DEF_HSTRT << 1,
+			      (DEF_HSTRT << 1) + W_CIF - (__s32)sel->r.width, 1,
+			      &sel->r.top, DEF_VSTRT << 1,
+			      (DEF_VSTRT << 1) + H_CIF - (__s32)sel->r.height,
+			      1, 0);
 
-	ret = ov6650_reg_write(client, REG_HSTRT, rect.left >> 1);
+	ret = ov6650_reg_write(client, REG_HSTRT, sel->r.left >> 1);
 	if (!ret) {
-		priv->rect.left = rect.left;
+		priv->rect.width += priv->rect.left - sel->r.left;
+		priv->rect.left = sel->r.left;
 		ret = ov6650_reg_write(client, REG_HSTOP,
-				(rect.left + rect.width) >> 1);
+				       (sel->r.left + sel->r.width) >> 1);
 	}
 	if (!ret) {
-		priv->rect.width = rect.width;
-		ret = ov6650_reg_write(client, REG_VSTRT, rect.top >> 1);
+		priv->rect.width = sel->r.width;
+		ret = ov6650_reg_write(client, REG_VSTRT, sel->r.top >> 1);
 	}
 	if (!ret) {
-		priv->rect.top = rect.top;
+		priv->rect.height += priv->rect.top - sel->r.top;
+		priv->rect.top = sel->r.top;
 		ret = ov6650_reg_write(client, REG_VSTOP,
-				(rect.top + rect.height) >> 1);
+				       (sel->r.top + sel->r.height) >> 1);
 	}
 	if (!ret)
-		priv->rect.height = rect.height;
+		priv->rect.height = sel->r.height;
 
 	return ret;
 }
@@ -512,12 +524,20 @@
 	if (format->pad)
 		return -EINVAL;
 
-	mf->width	= priv->rect.width >> priv->half_scale;
-	mf->height	= priv->rect.height >> priv->half_scale;
-	mf->code	= priv->code;
-	mf->colorspace	= priv->colorspace;
-	mf->field	= V4L2_FIELD_NONE;
+	/* initialize response with default media bus frame format */
+	*mf = ov6650_def_fmt;
 
+	/* update media bus format code and frame size */
+	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
+		mf->width = cfg->try_fmt.width;
+		mf->height = cfg->try_fmt.height;
+		mf->code = cfg->try_fmt.code;
+
+	} else {
+		mf->width = priv->rect.width >> priv->half_scale;
+		mf->height = priv->rect.height >> priv->half_scale;
+		mf->code = priv->code;
+	}
 	return 0;
 }
 
@@ -610,7 +630,6 @@
 		dev_err(&client->dev, "Pixel format not handled: 0x%x\n", code);
 		return -EINVAL;
 	}
-	priv->code = code;
 
 	if (code == MEDIA_BUS_FMT_Y8_1X8 ||
 			code == MEDIA_BUS_FMT_SBGGR8_1X8) {
@@ -623,11 +642,6 @@
 		priv->pclk_max = 8000000;
 	}
 
-	if (code == MEDIA_BUS_FMT_SBGGR8_1X8)
-		priv->colorspace = V4L2_COLORSPACE_SRGB;
-	else if (code != 0)
-		priv->colorspace = V4L2_COLORSPACE_JPEG;
-
 	if (half_scale) {
 		dev_dbg(&client->dev, "max resolution: QCIF\n");
 		coma_set |= COMA_QCIF;
@@ -636,7 +650,6 @@
 		dev_dbg(&client->dev, "max resolution: CIF\n");
 		coma_mask |= COMA_QCIF;
 	}
-	priv->half_scale = half_scale;
 
 	clkrc = CLKRC_12MHz;
 	mclk = 12000000;
@@ -654,14 +667,14 @@
 		ret = ov6650_reg_rmw(client, REG_COMA, coma_set, coma_mask);
 	if (!ret)
 		ret = ov6650_reg_write(client, REG_CLKRC, clkrc);
-	if (!ret)
-		ret = ov6650_reg_rmw(client, REG_COML, coml_set, coml_mask);
-
 	if (!ret) {
-		mf->colorspace	= priv->colorspace;
-		mf->width = priv->rect.width >> half_scale;
-		mf->height = priv->rect.height >> half_scale;
+		priv->half_scale = half_scale;
+
+		ret = ov6650_reg_rmw(client, REG_COML, coml_set, coml_mask);
 	}
+	if (!ret)
+		priv->code = code;
+
 	return ret;
 }
 
@@ -680,8 +693,6 @@
 		v4l_bound_align_image(&mf->width, 2, W_CIF, 1,
 				&mf->height, 2, H_CIF, 1, 0);
 
-	mf->field = V4L2_FIELD_NONE;
-
 	switch (mf->code) {
 	case MEDIA_BUS_FMT_Y10_1X10:
 		mf->code = MEDIA_BUS_FMT_Y8_1X8;
@@ -691,20 +702,39 @@
 	case MEDIA_BUS_FMT_YUYV8_2X8:
 	case MEDIA_BUS_FMT_VYUY8_2X8:
 	case MEDIA_BUS_FMT_UYVY8_2X8:
-		mf->colorspace = V4L2_COLORSPACE_JPEG;
 		break;
 	default:
 		mf->code = MEDIA_BUS_FMT_SBGGR8_1X8;
 		/* fall through */
 	case MEDIA_BUS_FMT_SBGGR8_1X8:
-		mf->colorspace = V4L2_COLORSPACE_SRGB;
 		break;
 	}
 
-	if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
-		return ov6650_s_fmt(sd, mf);
-	cfg->try_fmt = *mf;
+	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
+		/* store media bus format code and frame size in pad config */
+		cfg->try_fmt.width = mf->width;
+		cfg->try_fmt.height = mf->height;
+		cfg->try_fmt.code = mf->code;
+
+		/* return default mbus frame format updated with pad config */
+		*mf = ov6650_def_fmt;
+		mf->width = cfg->try_fmt.width;
+		mf->height = cfg->try_fmt.height;
+		mf->code = cfg->try_fmt.code;
+
+	} else {
+		/* apply new media bus format code and frame size */
+		int ret = ov6650_s_fmt(sd, mf);
 
+		if (ret)
+			return ret;
+
+		/* return default format updated with active size and code */
+		*mf = ov6650_def_fmt;
+		mf->width = priv->rect.width >> priv->half_scale;
+		mf->height = priv->rect.height >> priv->half_scale;
+		mf->code = priv->code;
+	}
 	return 0;
 }
 
@@ -754,19 +784,17 @@
 	else if (div > GET_CLKRC_DIV(CLKRC_DIV_MASK))
 		div = GET_CLKRC_DIV(CLKRC_DIV_MASK);
 
-	/*
-	 * Keep result to be used as tpf limit
-	 * for subsequent clock divider calculations
-	 */
-	priv->tpf.numerator = div;
-	priv->tpf.denominator = FRAME_RATE_MAX;
+	tpf->numerator = div;
+	tpf->denominator = FRAME_RATE_MAX;
 
-	clkrc = to_clkrc(&priv->tpf, priv->pclk_limit, priv->pclk_max);
+	clkrc = to_clkrc(tpf, priv->pclk_limit, priv->pclk_max);
 
 	ret = ov6650_reg_rmw(client, REG_CLKRC, clkrc, CLKRC_DIV_MASK);
 	if (!ret) {
-		tpf->numerator = GET_CLKRC_DIV(clkrc);
-		tpf->denominator = FRAME_RATE_MAX;
+		priv->tpf.numerator = GET_CLKRC_DIV(clkrc);
+		priv->tpf.denominator = FRAME_RATE_MAX;
+
+		*tpf = priv->tpf;
 	}
 
 	return ret;
@@ -849,6 +877,11 @@
 	ret = ov6650_reset(client);
 	if (!ret)
 		ret = ov6650_prog_dflt(client);
+	if (!ret) {
+		struct v4l2_mbus_framefmt mf = ov6650_def_fmt;
+
+		ret = ov6650_s_fmt(sd, &mf);
+	}
 	if (!ret)
 		ret = v4l2_ctrl_handler_setup(&priv->hdl);
 
@@ -989,8 +1022,10 @@
 			V4L2_CID_GAMMA, 0, 0xff, 1, 0x12);
 
 	priv->subdev.ctrl_handler = &priv->hdl;
-	if (priv->hdl.error)
-		return priv->hdl.error;
+	if (priv->hdl.error) {
+		ret = priv->hdl.error;
+		goto ectlhdlfree;
+	}
 
 	v4l2_ctrl_auto_cluster(2, &priv->autogain, 0, true);
 	v4l2_ctrl_auto_cluster(3, &priv->autowb, 0, true);
@@ -1001,15 +1036,18 @@
 	priv->rect.top	  = DEF_VSTRT << 1;
 	priv->rect.width  = W_CIF;
 	priv->rect.height = H_CIF;
-	priv->half_scale  = false;
-	priv->code	  = MEDIA_BUS_FMT_YUYV8_2X8;
-	priv->colorspace  = V4L2_COLORSPACE_JPEG;
+
+	/* Hardware default frame interval */
+	priv->tpf.numerator   = GET_CLKRC_DIV(DEF_CLKRC);
+	priv->tpf.denominator = FRAME_RATE_MAX;
 
 	priv->subdev.internal_ops = &ov6650_internal_ops;
 
 	ret = v4l2_async_register_subdev(&priv->subdev);
-	if (ret)
-		v4l2_ctrl_handler_free(&priv->hdl);
+	if (!ret)
+		return 0;
+ectlhdlfree:
+	v4l2_ctrl_handler_free(&priv->hdl);
 
 	return ret;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/ov7670.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/ov7670.c
@@ -1824,7 +1824,7 @@
 
 	if (bus_cfg.bus_type != V4L2_MBUS_PARALLEL) {
 		dev_err(dev, "Unsupported media bus type\n");
-		return ret;
+		return -EINVAL;
 	}
 	info->mbus_config = bus_cfg.bus.parallel.flags;
 
@@ -2000,7 +2000,6 @@
 	v4l2_async_unregister_subdev(sd);
 	v4l2_ctrl_handler_free(&info->hdl);
 	media_entity_cleanup(&info->sd.entity);
-	ov7670_power_off(sd);
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/ov772x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/ov772x.c
@@ -1397,7 +1397,7 @@
 	priv->subdev.ctrl_handler = &priv->hdl;
 	if (priv->hdl.error) {
 		ret = priv->hdl.error;
-		goto error_mutex_destroy;
+		goto error_ctrl_free;
 	}
 
 	priv->clk = clk_get(&client->dev, NULL);
@@ -1446,7 +1446,6 @@
 	clk_put(priv->clk);
 error_ctrl_free:
 	v4l2_ctrl_handler_free(&priv->hdl);
-error_mutex_destroy:
 	mutex_destroy(&priv->lock);
 
 	return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/s5c73m3/s5c73m3-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/s5c73m3/s5c73m3-core.c
@@ -1386,7 +1386,7 @@
 	s5c73m3_gpio_deassert(state, STBY);
 	usleep_range(100, 200);
 
-	s5c73m3_gpio_deassert(state, RST);
+	s5c73m3_gpio_deassert(state, RSET);
 	usleep_range(50, 100);
 
 	return 0;
@@ -1401,7 +1401,7 @@
 {
 	int i, ret;
 
-	if (s5c73m3_gpio_assert(state, RST))
+	if (s5c73m3_gpio_assert(state, RSET))
 		usleep_range(10, 50);
 
 	if (s5c73m3_gpio_assert(state, STBY))
@@ -1606,7 +1606,7 @@
 
 		state->mclk_frequency = pdata->mclk_frequency;
 		state->gpio[STBY] = pdata->gpio_stby;
-		state->gpio[RST] = pdata->gpio_reset;
+		state->gpio[RSET] = pdata->gpio_reset;
 		return 0;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/s5c73m3/s5c73m3.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/s5c73m3/s5c73m3.h
@@ -353,7 +353,7 @@
 
 enum s5c73m3_gpio_id {
 	STBY,
-	RST,
+	RSET,
 	GPIO_NUM,
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/s5k4ecgx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/s5k4ecgx.c
@@ -173,7 +173,7 @@
 
 enum s5k4ecgx_gpio_id {
 	STBY,
-	RST,
+	RSET,
 	GPIO_NUM,
 };
 
@@ -476,7 +476,7 @@
 	if (s5k4ecgx_gpio_set_value(priv, STBY, priv->gpio[STBY].level))
 		usleep_range(30, 50);
 
-	if (s5k4ecgx_gpio_set_value(priv, RST, priv->gpio[RST].level))
+	if (s5k4ecgx_gpio_set_value(priv, RSET, priv->gpio[RSET].level))
 		usleep_range(30, 50);
 
 	return 0;
@@ -484,7 +484,7 @@
 
 static int __s5k4ecgx_power_off(struct s5k4ecgx *priv)
 {
-	if (s5k4ecgx_gpio_set_value(priv, RST, !priv->gpio[RST].level))
+	if (s5k4ecgx_gpio_set_value(priv, RSET, !priv->gpio[RSET].level))
 		usleep_range(30, 50);
 
 	if (s5k4ecgx_gpio_set_value(priv, STBY, !priv->gpio[STBY].level))
@@ -872,7 +872,7 @@
 	int ret;
 
 	priv->gpio[STBY].gpio = -EINVAL;
-	priv->gpio[RST].gpio  = -EINVAL;
+	priv->gpio[RSET].gpio  = -EINVAL;
 
 	ret = s5k4ecgx_config_gpio(gpio->gpio, gpio->level, "S5K4ECGX_STBY");
 
@@ -891,7 +891,7 @@
 		s5k4ecgx_free_gpios(priv);
 		return ret;
 	}
-	priv->gpio[RST] = *gpio;
+	priv->gpio[RSET] = *gpio;
 	if (gpio_is_valid(gpio->gpio))
 		gpio_set_value(gpio->gpio, 0);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/s5k5baf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/s5k5baf.c
@@ -235,7 +235,7 @@
 
 enum s5k5baf_gpio_id {
 	STBY,
-	RST,
+	RSET,
 	NUM_GPIOS,
 };
 
@@ -970,7 +970,7 @@
 
 	s5k5baf_gpio_deassert(state, STBY);
 	usleep_range(50, 100);
-	s5k5baf_gpio_deassert(state, RST);
+	s5k5baf_gpio_deassert(state, RSET);
 	return 0;
 
 err_reg_dis:
@@ -988,7 +988,7 @@
 	state->apply_cfg = 0;
 	state->apply_crop = 0;
 
-	s5k5baf_gpio_assert(state, RST);
+	s5k5baf_gpio_assert(state, RSET);
 	s5k5baf_gpio_assert(state, STBY);
 
 	if (!IS_ERR(state->clock))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/s5k6aa.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/s5k6aa.c
@@ -177,7 +177,7 @@
 
 enum s5k6aa_gpio_id {
 	STBY,
-	RST,
+	RSET,
 	GPIO_NUM,
 };
 
@@ -841,7 +841,7 @@
 		ret = s5k6aa->s_power(1);
 	usleep_range(4000, 5000);
 
-	if (s5k6aa_gpio_deassert(s5k6aa, RST))
+	if (s5k6aa_gpio_deassert(s5k6aa, RSET))
 		msleep(20);
 
 	return ret;
@@ -851,7 +851,7 @@
 {
 	int ret;
 
-	if (s5k6aa_gpio_assert(s5k6aa, RST))
+	if (s5k6aa_gpio_assert(s5k6aa, RSET))
 		usleep_range(100, 150);
 
 	if (s5k6aa->s_power) {
@@ -1510,7 +1510,7 @@
 	int ret;
 
 	s5k6aa->gpio[STBY].gpio = -EINVAL;
-	s5k6aa->gpio[RST].gpio  = -EINVAL;
+	s5k6aa->gpio[RSET].gpio  = -EINVAL;
 
 	gpio = &pdata->gpio_stby;
 	if (gpio_is_valid(gpio->gpio)) {
@@ -1533,7 +1533,7 @@
 		if (ret < 0)
 			return ret;
 
-		s5k6aa->gpio[RST] = *gpio;
+		s5k6aa->gpio[RSET] = *gpio;
 	}
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/saa6588.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/saa6588.c
@@ -380,7 +380,7 @@
 
 /* ---------------------------------------------------------------------- */
 
-static long saa6588_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
+static long saa6588_command(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
 {
 	struct saa6588 *s = to_saa6588(sd);
 	struct saa6588_command *a = arg;
@@ -433,7 +433,7 @@
 /* ----------------------------------------------------------------------- */
 
 static const struct v4l2_subdev_core_ops saa6588_core_ops = {
-	.ioctl = saa6588_ioctl,
+	.command = saa6588_command,
 };
 
 static const struct v4l2_subdev_tuner_ops saa6588_tuner_ops = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/smiapp/smiapp-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/smiapp/smiapp-core.c
@@ -2327,11 +2327,12 @@
 		if (rval < 0) {
 			if (rval != -EBUSY && rval != -EAGAIN)
 				pm_runtime_set_active(&client->dev);
-			pm_runtime_put(&client->dev);
+			pm_runtime_put_noidle(&client->dev);
 			return -ENODEV;
 		}
 
 		if (smiapp_read_nvm(sensor, sensor->nvm)) {
+			pm_runtime_put(&client->dev);
 			dev_err(&client->dev, "nvm read failed\n");
 			return -ENODEV;
 		}
@@ -3101,19 +3102,23 @@
 	if (rval < 0)
 		goto out_media_entity_cleanup;
 
-	rval = v4l2_async_register_subdev_sensor_common(&sensor->src->sd);
-	if (rval < 0)
-		goto out_media_entity_cleanup;
-
 	pm_runtime_set_active(&client->dev);
 	pm_runtime_get_noresume(&client->dev);
 	pm_runtime_enable(&client->dev);
+
+	rval = v4l2_async_register_subdev_sensor_common(&sensor->src->sd);
+	if (rval < 0)
+		goto out_disable_runtime_pm;
+
 	pm_runtime_set_autosuspend_delay(&client->dev, 1000);
 	pm_runtime_use_autosuspend(&client->dev);
 	pm_runtime_put_autosuspend(&client->dev);
 
 	return 0;
 
+out_disable_runtime_pm:
+	pm_runtime_disable(&client->dev);
+
 out_media_entity_cleanup:
 	media_entity_cleanup(&sensor->src->sd.entity);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/st-mipid02.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/st-mipid02.c
@@ -971,6 +971,11 @@
 	bridge->reset_gpio = devm_gpiod_get_optional(dev, "reset",
 						     GPIOD_OUT_HIGH);
 
+	if (IS_ERR(bridge->reset_gpio)) {
+		dev_err(dev, "failed to get reset GPIO\n");
+		return PTR_ERR(bridge->reset_gpio);
+	}
+
 	ret = mipid02_get_regulators(bridge);
 	if (ret) {
 		dev_err(dev, "failed to get regulators %d", ret);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/tc358743.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/tc358743.c
@@ -919,8 +919,8 @@
 	.adap_monitor_all_enable = tc358743_cec_adap_monitor_all_enable,
 };
 
-static void tc358743_cec_isr(struct v4l2_subdev *sd, u16 intstatus,
-			     bool *handled)
+static void tc358743_cec_handler(struct v4l2_subdev *sd, u16 intstatus,
+				 bool *handled)
 {
 	struct tc358743_state *state = to_state(sd);
 	unsigned int cec_rxint, cec_txint;
@@ -953,7 +953,8 @@
 			cec_transmit_attempt_done(state->cec_adap,
 						  CEC_TX_STATUS_ERROR);
 		}
-		*handled = true;
+		if (handled)
+			*handled = true;
 	}
 	if ((intstatus & MASK_CEC_RINT) &&
 	    (cec_rxint & MASK_CECRIEND)) {
@@ -968,7 +969,8 @@
 			msg.msg[i] = v & 0xff;
 		}
 		cec_received_msg(state->cec_adap, &msg);
-		*handled = true;
+		if (handled)
+			*handled = true;
 	}
 	i2c_wr16(sd, INTSTATUS,
 		 intstatus & (MASK_CEC_RINT | MASK_CEC_TINT));
@@ -1432,7 +1434,7 @@
 
 #ifdef CONFIG_VIDEO_TC358743_CEC
 	if (intstatus & (MASK_CEC_RINT | MASK_CEC_TINT)) {
-		tc358743_cec_isr(sd, intstatus, handled);
+		tc358743_cec_handler(sd, intstatus, handled);
 		i2c_wr16(sd, INTSTATUS,
 			 intstatus & (MASK_CEC_RINT | MASK_CEC_TINT));
 		intstatus &= ~(MASK_CEC_RINT | MASK_CEC_TINT);
@@ -1461,7 +1463,7 @@
 static irqreturn_t tc358743_irq_handler(int irq, void *dev_id)
 {
 	struct tc358743_state *state = dev_id;
-	bool handled;
+	bool handled = false;
 
 	tc358743_isr(&state->sd, 0, &handled);
 
@@ -1971,6 +1973,7 @@
 	bps_pr_lane = 2 * endpoint.link_frequencies[0];
 	if (bps_pr_lane < 62500000U || bps_pr_lane > 1000000000U) {
 		dev_err(dev, "unsupported bps per lane: %u bps\n", bps_pr_lane);
+		ret = -EINVAL;
 		goto disable_clk;
 	}
 
@@ -2104,9 +2107,6 @@
 	state->mbus_fmt_code = MEDIA_BUS_FMT_RGB888_1X24;
 
 	sd->dev = &client->dev;
-	err = v4l2_async_register_subdev(sd);
-	if (err < 0)
-		goto err_hdl;
 
 	mutex_init(&state->confctl_mutex);
 
@@ -2164,6 +2164,10 @@
 	if (err)
 		goto err_work_queues;
 
+	err = v4l2_async_register_subdev(sd);
+	if (err < 0)
+		goto err_work_queues;
+
 	v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,
 		  client->addr << 1, client->adapter->name);
 
@@ -2171,8 +2175,10 @@
 
 err_work_queues:
 	cec_unregister_adapter(state->cec_adap);
-	if (!state->i2c_client->irq)
+	if (!state->i2c_client->irq) {
+		del_timer(&state->timer);
 		flush_work(&state->work_i2c_poll);
+	}
 	cancel_delayed_work(&state->delayed_work_enable_hotplug);
 	mutex_destroy(&state->confctl_mutex);
 err_hdl:
@@ -2190,7 +2196,7 @@
 		del_timer_sync(&state->timer);
 		flush_work(&state->work_i2c_poll);
 	}
-	cancel_delayed_work(&state->delayed_work_enable_hotplug);
+	cancel_delayed_work_sync(&state->delayed_work_enable_hotplug);
 	cec_unregister_adapter(state->cec_adap);
 	v4l2_async_unregister_subdev(sd);
 	v4l2_device_unregister_subdev(sd);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/tda1997x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/tda1997x.c
@@ -1247,13 +1247,13 @@
 {
 	struct v4l2_subdev *sd = &state->sd;
 	union hdmi_infoframe frame;
-	u8 buffer[40];
+	u8 buffer[40] = { 0 };
 	u8 reg;
 	int len, err;
 
 	/* read data */
 	len = io_readn(sd, addr, sizeof(buffer), buffer);
-	err = hdmi_infoframe_unpack(&frame, buffer, sizeof(buffer));
+	err = hdmi_infoframe_unpack(&frame, buffer, len);
 	if (err) {
 		v4l_err(state->client,
 			"failed parsing %d byte infoframe: 0x%04x/0x%02x\n",
@@ -1695,14 +1695,15 @@
 				     struct v4l2_dv_timings *timings)
 {
 	struct tda1997x_state *state = to_state(sd);
+	int ret;
 
 	v4l_dbg(1, debug, state->client, "%s\n", __func__);
 	memset(timings, 0, sizeof(struct v4l2_dv_timings));
 	mutex_lock(&state->lock);
-	tda1997x_detect_std(state, timings);
+	ret = tda1997x_detect_std(state, timings);
 	mutex_unlock(&state->lock);
 
-	return 0;
+	return ret;
 }
 
 static const struct v4l2_subdev_video_ops tda1997x_video_ops = {
@@ -1926,13 +1927,13 @@
 {
 	struct tda1997x_state *state = to_state(sd);
 	union hdmi_infoframe frame;
-	u8 buffer[40];
+	u8 buffer[40] = { 0 };
 	int len, err;
 
 	/* read data */
 	len = io_readn(sd, addr, sizeof(buffer), buffer);
 	v4l2_dbg(1, debug, sd, "infoframe: addr=%d len=%d\n", addr, len);
-	err = hdmi_infoframe_unpack(&frame, buffer, sizeof(buffer));
+	err = hdmi_infoframe_unpack(&frame, buffer, len);
 	if (err) {
 		v4l_err(state->client,
 			"failed parsing %d byte infoframe: 0x%04x/0x%02x\n",
@@ -2233,6 +2234,7 @@
 	/* get initial HDMI status */
 	state->hdmi_status = io_read(sd, REG_HDMI_FLAGS);
 
+	io_write(sd, REG_EDID_ENABLE, EDID_ENABLE_A_EN | EDID_ENABLE_B_EN);
 	return 0;
 }
 
@@ -2804,7 +2806,7 @@
 	media_entity_cleanup(&sd->entity);
 	v4l2_ctrl_handler_free(&state->hdl);
 	regulator_bulk_disable(TDA1997X_NUM_SUPPLIES, state->supplies);
-	cancel_delayed_work(&state->delayed_work_enable_hpd);
+	cancel_delayed_work_sync(&state->delayed_work_enable_hpd);
 	mutex_destroy(&state->page_lock);
 	mutex_destroy(&state->lock);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/i2c/video-i2c.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/i2c/video-i2c.c
@@ -255,7 +255,7 @@
 	return amg88xx_set_power_off(data);
 }
 
-#if IS_ENABLED(CONFIG_HWMON)
+#if IS_REACHABLE(CONFIG_HWMON)
 
 static const u32 amg88xx_temp_config[] = {
 	HWMON_T_INPUT,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/mc/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/mc/Makefile
@@ -3,7 +3,7 @@
 mc-objs	:= mc-device.o mc-devnode.o mc-entity.o \
 	   mc-request.o
 
-ifeq ($(CONFIG_USB),y)
+ifneq ($(CONFIG_USB),)
 	mc-objs += mc-dev-allocator.o
 endif
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/mc/mc-device.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/mc/mc-device.c
@@ -575,6 +575,38 @@
 	dev_dbg(devnode->parent, "Media device released\n");
 }
 
+static void __media_device_unregister_entity(struct media_entity *entity)
+{
+	struct media_device *mdev = entity->graph_obj.mdev;
+	struct media_link *link, *tmp;
+	struct media_interface *intf;
+	unsigned int i;
+
+	ida_free(&mdev->entity_internal_idx, entity->internal_idx);
+
+	/* Remove all interface links pointing to this entity */
+	list_for_each_entry(intf, &mdev->interfaces, graph_obj.list) {
+		list_for_each_entry_safe(link, tmp, &intf->links, list) {
+			if (link->entity == entity)
+				__media_remove_intf_link(link);
+		}
+	}
+
+	/* Remove all data links that belong to this entity */
+	__media_entity_remove_links(entity);
+
+	/* Remove all pads that belong to this entity */
+	for (i = 0; i < entity->num_pads; i++)
+		media_gobj_destroy(&entity->pads[i].graph_obj);
+
+	/* Remove the entity */
+	media_gobj_destroy(&entity->graph_obj);
+
+	/* invoke entity_notify callbacks to handle entity removal?? */
+
+	entity->graph_obj.mdev = NULL;
+}
+
 /**
  * media_device_register_entity - Register an entity with a media device
  * @mdev:	The media device
@@ -632,6 +664,7 @@
 		 */
 		ret = media_graph_walk_init(&new, mdev);
 		if (ret) {
+			__media_device_unregister_entity(entity);
 			mutex_unlock(&mdev->graph_mutex);
 			return ret;
 		}
@@ -644,38 +677,6 @@
 }
 EXPORT_SYMBOL_GPL(media_device_register_entity);
 
-static void __media_device_unregister_entity(struct media_entity *entity)
-{
-	struct media_device *mdev = entity->graph_obj.mdev;
-	struct media_link *link, *tmp;
-	struct media_interface *intf;
-	unsigned int i;
-
-	ida_free(&mdev->entity_internal_idx, entity->internal_idx);
-
-	/* Remove all interface links pointing to this entity */
-	list_for_each_entry(intf, &mdev->interfaces, graph_obj.list) {
-		list_for_each_entry_safe(link, tmp, &intf->links, list) {
-			if (link->entity == entity)
-				__media_remove_intf_link(link);
-		}
-	}
-
-	/* Remove all data links that belong to this entity */
-	__media_entity_remove_links(entity);
-
-	/* Remove all pads that belong to this entity */
-	for (i = 0; i < entity->num_pads; i++)
-		media_gobj_destroy(&entity->pads[i].graph_obj);
-
-	/* Remove the entity */
-	media_gobj_destroy(&entity->graph_obj);
-
-	/* invoke entity_notify callbacks to handle entity removal?? */
-
-	entity->graph_obj.mdev = NULL;
-}
-
 void media_device_unregister_entity(struct media_entity *entity)
 {
 	struct media_device *mdev = entity->graph_obj.mdev;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/mc/mc-devnode.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/mc/mc-devnode.c
@@ -246,15 +246,14 @@
 	kobject_set_name(&devnode->cdev.kobj, "media%d", devnode->minor);
 
 	/* Part 3: Add the media and char device */
+	set_bit(MEDIA_FLAG_REGISTERED, &devnode->flags);
 	ret = cdev_device_add(&devnode->cdev, &devnode->dev);
 	if (ret < 0) {
+		clear_bit(MEDIA_FLAG_REGISTERED, &devnode->flags);
 		pr_err("%s: cdev_device_add failed\n", __func__);
 		goto cdev_add_error;
 	}
 
-	/* Part 4: Activate this minor. The char device can now be used. */
-	set_bit(MEDIA_FLAG_REGISTERED, &devnode->flags);
-
 	return 0;
 
 cdev_add_error:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/mc/mc-entity.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/mc/mc-entity.c
@@ -264,7 +264,36 @@
 #define stack_top(en)	((en)->stack[(en)->top].entity)
 
 /**
- * media_graph_walk_init - Allocate resources for graph walk
+ * media_entity_has_route - Check if two entity pads are connected internally
+ * @entity: The entity
+ * @pad0: The first pad index
+ * @pad1: The second pad index
+ *
+ * This function can be used to check whether two pads of an entity are
+ * connected internally in the entity.
+ *
+ * The caller must hold entity->source->parent->mutex.
+ *
+ * Return: true if the pads are connected internally and false otherwise.
+ */
+bool media_entity_has_route(struct media_entity *entity, unsigned int pad0,
+			    unsigned int pad1)
+{
+	if (pad0 >= entity->num_pads || pad1 >= entity->num_pads)
+		return false;
+
+	if (pad0 == pad1)
+		return true;
+
+	if (!entity->ops || !entity->ops->has_route)
+		return true;
+
+	return entity->ops->has_route(entity, pad0, pad1);
+}
+EXPORT_SYMBOL_GPL(media_entity_has_route);
+
+/**
+ * media_entity_graph_walk_init - Allocate resources for graph walk
  * @graph: Media graph structure that will be used to walk the graph
  * @mdev: Media device
  *
@@ -639,9 +668,9 @@
 		return -EINVAL;
 
 	for (i = 0; i < entity->num_pads; i++) {
-		if (entity->pads[i].flags == MEDIA_PAD_FL_SINK)
+		if (entity->pads[i].flags & MEDIA_PAD_FL_SINK)
 			pad_is_sink = true;
-		else if (entity->pads[i].flags == MEDIA_PAD_FL_SOURCE)
+		else if (entity->pads[i].flags & MEDIA_PAD_FL_SOURCE)
 			pad_is_sink = false;
 		else
 			continue;	/* This is an error! */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/mc/mc-request.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/mc/mc-request.c
@@ -296,9 +296,18 @@
 	if (WARN_ON(!mdev->ops->req_alloc ^ !mdev->ops->req_free))
 		return -ENOMEM;
 
+	if (mdev->ops->req_alloc)
+		req = mdev->ops->req_alloc(mdev);
+	else
+		req = kzalloc(sizeof(*req), GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+
 	fd = get_unused_fd_flags(O_CLOEXEC);
-	if (fd < 0)
-		return fd;
+	if (fd < 0) {
+		ret = fd;
+		goto err_free_req;
+	}
 
 	filp = anon_inode_getfile("request", &request_fops, NULL, O_CLOEXEC);
 	if (IS_ERR(filp)) {
@@ -306,15 +315,6 @@
 		goto err_put_fd;
 	}
 
-	if (mdev->ops->req_alloc)
-		req = mdev->ops->req_alloc(mdev);
-	else
-		req = kzalloc(sizeof(*req), GFP_KERNEL);
-	if (!req) {
-		ret = -ENOMEM;
-		goto err_fput;
-	}
-
 	filp->private_data = req;
 	req->mdev = mdev;
 	req->state = MEDIA_REQUEST_STATE_IDLE;
@@ -336,12 +336,15 @@
 
 	return 0;
 
-err_fput:
-	fput(filp);
-
 err_put_fd:
 	put_unused_fd(fd);
 
+err_free_req:
+	if (mdev->ops->req_free)
+		mdev->ops->req_free(req);
+	else
+		kfree(req);
+
 	return ret;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/b2c2/flexcop-pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/b2c2/flexcop-pci.c
@@ -185,6 +185,8 @@
 		dma_addr_t cur_addr =
 			fc->read_ibi_reg(fc,dma1_008).dma_0x8.dma_cur_addr << 2;
 		u32 cur_pos = cur_addr - fc_pci->dma[0].dma_addr0;
+		if (cur_pos > fc_pci->dma[0].size * 2)
+			goto error;
 
 		deb_irq("%u irq: %08x cur_addr: %llx: cur_pos: %08x, last_cur_pos: %08x ",
 				jiffies_to_usecs(jiffies - fc_pci->last_irq),
@@ -225,6 +227,7 @@
 		ret = IRQ_NONE;
 	}
 
+error:
 	spin_unlock_irqrestore(&fc_pci->irq_lock, flags);
 	return ret;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/bt8xx/bt878.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/bt8xx/bt878.c
@@ -477,6 +477,9 @@
 	btwrite(0, BT878_AINT_MASK);
 	bt878_num++;
 
+	if (!bt->tasklet.func)
+		tasklet_disable(&bt->tasklet);
+
 	return 0;
 
       fail2:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/bt8xx/bttv-driver.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/bt8xx/bttv-driver.c
@@ -2964,7 +2964,7 @@
 
 	dprintk("open dev=%s\n", video_device_node_name(vdev));
 
-	if (vdev->vfl_type == VFL_TYPE_GRABBER) {
+	if (vdev->vfl_type == VFL_TYPE_VIDEO) {
 		type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	} else if (vdev->vfl_type == VFL_TYPE_VBI) {
 		type = V4L2_BUF_TYPE_VBI_CAPTURE;
@@ -3187,7 +3187,7 @@
 
 	btv->radio_user--;
 
-	bttv_call_all(btv, core, ioctl, SAA6588_CMD_CLOSE, &cmd);
+	bttv_call_all(btv, core, command, SAA6588_CMD_CLOSE, &cmd);
 
 	if (btv->radio_user == 0)
 		btv->has_radio_tuner = 0;
@@ -3268,7 +3268,7 @@
 	cmd.result = -ENODEV;
 	radio_enable(btv);
 
-	bttv_call_all(btv, core, ioctl, SAA6588_CMD_READ, &cmd);
+	bttv_call_all(btv, core, command, SAA6588_CMD_READ, &cmd);
 
 	return cmd.result;
 }
@@ -3289,7 +3289,7 @@
 	cmd.instance = file;
 	cmd.event_list = wait;
 	cmd.poll_mask = res;
-	bttv_call_all(btv, core, ioctl, SAA6588_CMD_POLL, &cmd);
+	bttv_call_all(btv, core, command, SAA6588_CMD_POLL, &cmd);
 
 	return cmd.poll_mask;
 }
@@ -3898,14 +3898,14 @@
 
 	/* video */
 	vdev_init(btv, &btv->video_dev, &bttv_video_template, "video");
-	btv->video_dev.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER |
+	btv->video_dev.device_caps = V4L2_CAP_VIDEO_CAPTURE |
 				     V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
 	if (btv->tuner_type != TUNER_ABSENT)
 		btv->video_dev.device_caps |= V4L2_CAP_TUNER;
 	if (no_overlay <= 0)
 		btv->video_dev.device_caps |= V4L2_CAP_VIDEO_OVERLAY;
 
-	if (video_register_device(&btv->video_dev, VFL_TYPE_GRABBER,
+	if (video_register_device(&btv->video_dev, VFL_TYPE_VIDEO,
 				  video_nr[btv->c.nr]) < 0)
 		goto err;
 	pr_info("%d: registered device %s\n",
@@ -3919,7 +3919,7 @@
 	/* vbi */
 	vdev_init(btv, &btv->vbi_dev, &bttv_video_template, "vbi");
 	btv->vbi_dev.device_caps = V4L2_CAP_VBI_CAPTURE | V4L2_CAP_READWRITE |
-				   V4L2_CAP_STREAMING | V4L2_CAP_TUNER;
+				   V4L2_CAP_STREAMING;
 	if (btv->tuner_type != TUNER_ABSENT)
 		btv->vbi_dev.device_caps |= V4L2_CAP_TUNER;
 
@@ -4013,11 +4013,13 @@
 	btv->id  = dev->device;
 	if (pci_enable_device(dev)) {
 		pr_warn("%d: Can't enable device\n", btv->c.nr);
-		return -EIO;
+		result = -EIO;
+		goto free_mem;
 	}
 	if (pci_set_dma_mask(dev, DMA_BIT_MASK(32))) {
 		pr_warn("%d: No suitable DMA available\n", btv->c.nr);
-		return -EIO;
+		result = -EIO;
+		goto free_mem;
 	}
 	if (!request_mem_region(pci_resource_start(dev,0),
 				pci_resource_len(dev,0),
@@ -4025,7 +4027,8 @@
 		pr_warn("%d: can't request iomem (0x%llx)\n",
 			btv->c.nr,
 			(unsigned long long)pci_resource_start(dev, 0));
-		return -EBUSY;
+		result = -EBUSY;
+		goto free_mem;
 	}
 	pci_set_master(dev);
 	pci_set_command(dev);
@@ -4211,6 +4214,10 @@
 	release_mem_region(pci_resource_start(btv->c.pci,0),
 			   pci_resource_len(btv->c.pci,0));
 	pci_disable_device(btv->c.pci);
+
+free_mem:
+	bttvs[btv->c.nr] = NULL;
+	kfree(btv);
 	return result;
 }
 
@@ -4251,6 +4258,7 @@
 
 	/* free resources */
 	free_irq(btv->c.pci->irq,btv);
+	del_timer_sync(&btv->timeout);
 	iounmap(btv->bt848_mmio);
 	release_mem_region(pci_resource_start(btv->c.pci,0),
 			   pci_resource_len(btv->c.pci,0));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/bt8xx/dst.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/bt8xx/dst.c
@@ -1722,7 +1722,7 @@
 	return state;				/*	Manu (DST is a card not a frontend)	*/
 }
 
-EXPORT_SYMBOL(dst_attach);
+EXPORT_SYMBOL_GPL(dst_attach);
 
 static const struct dvb_frontend_ops dst_dvbt_ops = {
 	.delsys = { SYS_DVBT },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/bt8xx/dst_ca.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/bt8xx/dst_ca.c
@@ -668,7 +668,7 @@
 	return NULL;
 }
 
-EXPORT_SYMBOL(dst_ca_attach);
+EXPORT_SYMBOL_GPL(dst_ca_attach);
 
 MODULE_DESCRIPTION("DST DVB-S/T/C Combo CA driver");
 MODULE_AUTHOR("Manu Abraham");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/cobalt/cobalt-driver.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/cobalt/cobalt-driver.c
@@ -8,6 +8,7 @@
  *  All rights reserved.
  */
 
+#include <linux/bitfield.h>
 #include <linux/delay.h>
 #include <media/i2c/adv7604.h>
 #include <media/i2c/adv7842.h>
@@ -210,17 +211,17 @@
 	pcie_capability_read_word(pci_dev, PCI_EXP_LNKSTA, &stat);
 	cobalt_info("PCIe link capability 0x%08x: %s per lane and %u lanes\n",
 			capa, get_link_speed(capa),
-			(capa & PCI_EXP_LNKCAP_MLW) >> 4);
+			FIELD_GET(PCI_EXP_LNKCAP_MLW, capa));
 	cobalt_info("PCIe link control 0x%04x\n", ctrl);
 	cobalt_info("PCIe link status 0x%04x: %s per lane and %u lanes\n",
 		    stat, get_link_speed(stat),
-		    (stat & PCI_EXP_LNKSTA_NLW) >> 4);
+		    FIELD_GET(PCI_EXP_LNKSTA_NLW, stat));
 
 	/* Bus */
 	pcie_capability_read_dword(pci_bus_dev, PCI_EXP_LNKCAP, &capa);
 	cobalt_info("PCIe bus link capability 0x%08x: %s per lane and %u lanes\n",
 			capa, get_link_speed(capa),
-			(capa & PCI_EXP_LNKCAP_MLW) >> 4);
+			FIELD_GET(PCI_EXP_LNKCAP_MLW, capa));
 
 	/* Slot */
 	pcie_capability_read_dword(pci_dev, PCI_EXP_SLTCAP, &capa);
@@ -239,7 +240,7 @@
 	if (!pci_is_pcie(pci_dev))
 		return 0;
 	pcie_capability_read_word(pci_dev, PCI_EXP_LNKSTA, &link);
-	return (link & PCI_EXP_LNKSTA_NLW) >> 4;
+	return FIELD_GET(PCI_EXP_LNKSTA_NLW, link);
 }
 
 static unsigned pcie_bus_link_get_lanes(struct cobalt *cobalt)
@@ -250,7 +251,7 @@
 	if (!pci_is_pcie(pci_dev))
 		return 0;
 	pcie_capability_read_dword(pci_dev, PCI_EXP_LNKCAP, &link);
-	return (link & PCI_EXP_LNKCAP_MLW) >> 4;
+	return FIELD_GET(PCI_EXP_LNKCAP_MLW, link);
 }
 
 static void msi_config_show(struct cobalt *cobalt, struct pci_dev *pci_dev)
@@ -667,6 +668,7 @@
 		return -ENOMEM;
 	cobalt->pci_dev = pci_dev;
 	cobalt->instance = i;
+	mutex_init(&cobalt->pci_lock);
 
 	retval = v4l2_device_register(&pci_dev->dev, &cobalt->v4l2_dev);
 	if (retval) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/cobalt/cobalt-driver.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/cobalt/cobalt-driver.h
@@ -251,6 +251,8 @@
 	int instance;
 	struct pci_dev *pci_dev;
 	struct v4l2_device v4l2_dev;
+	/* serialize PCI access in cobalt_s_bit_sysctrl() */
+	struct mutex pci_lock;
 
 	void __iomem *bar0, *bar1;
 
@@ -320,10 +322,13 @@
 static inline void cobalt_s_bit_sysctrl(struct cobalt *cobalt,
 					int bit, int val)
 {
-	u32 ctrl = cobalt_read_bar1(cobalt, COBALT_SYS_CTRL_BASE);
+	u32 ctrl;
 
+	mutex_lock(&cobalt->pci_lock);
+	ctrl = cobalt_read_bar1(cobalt, COBALT_SYS_CTRL_BASE);
 	cobalt_write_bar1(cobalt, COBALT_SYS_CTRL_BASE,
 			(ctrl & ~(1UL << bit)) | (val << bit));
+	mutex_unlock(&cobalt->pci_lock);
 }
 
 static inline u32 cobalt_g_sysstat(struct cobalt *cobalt)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/cobalt/cobalt-v4l2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/cobalt/cobalt-v4l2.c
@@ -1272,7 +1272,7 @@
 	video_set_drvdata(vdev, s);
 	ret = vb2_queue_init(q);
 	if (!s->is_audio && ret == 0)
-		ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
+		ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
 	else if (!s->is_dummy)
 		ret = cobalt_alsa_init(s);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/cx18/cx18-streams.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/cx18/cx18-streams.c
@@ -48,19 +48,19 @@
 } cx18_stream_info[] = {
 	{	/* CX18_ENC_STREAM_TYPE_MPG */
 		"encoder MPEG",
-		VFL_TYPE_GRABBER, 0,
+		VFL_TYPE_VIDEO, 0,
 		PCI_DMA_FROMDEVICE,
 		V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
 		V4L2_CAP_AUDIO | V4L2_CAP_TUNER
 	},
 	{	/* CX18_ENC_STREAM_TYPE_TS */
 		"TS",
-		VFL_TYPE_GRABBER, -1,
+		VFL_TYPE_VIDEO, -1,
 		PCI_DMA_FROMDEVICE,
 	},
 	{	/* CX18_ENC_STREAM_TYPE_YUV */
 		"encoder YUV",
-		VFL_TYPE_GRABBER, CX18_V4L2_ENC_YUV_OFFSET,
+		VFL_TYPE_VIDEO, CX18_V4L2_ENC_YUV_OFFSET,
 		PCI_DMA_FROMDEVICE,
 		V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
 		V4L2_CAP_STREAMING | V4L2_CAP_AUDIO | V4L2_CAP_TUNER
@@ -74,13 +74,13 @@
 	},
 	{	/* CX18_ENC_STREAM_TYPE_PCM */
 		"encoder PCM audio",
-		VFL_TYPE_GRABBER, CX18_V4L2_ENC_PCM_OFFSET,
+		VFL_TYPE_VIDEO, CX18_V4L2_ENC_PCM_OFFSET,
 		PCI_DMA_FROMDEVICE,
 		V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
 	},
 	{	/* CX18_ENC_STREAM_TYPE_IDX */
 		"encoder IDX",
-		VFL_TYPE_GRABBER, -1,
+		VFL_TYPE_VIDEO, -1,
 		PCI_DMA_FROMDEVICE,
 	},
 	{	/* CX18_ENC_STREAM_TYPE_RAD */
@@ -434,7 +434,7 @@
 	name = video_device_node_name(&s->video_dev);
 
 	switch (vfl_type) {
-	case VFL_TYPE_GRABBER:
+	case VFL_TYPE_VIDEO:
 		CX18_INFO("Registered device %s for %s (%d x %d.%02d kB)\n",
 			  name, s->name, cx->stream_buffers[type],
 			  cx->stream_buf_size[type] / 1024,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/cx23885/cx23885-417.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/cx23885/cx23885-417.c
@@ -1545,7 +1545,7 @@
 	if (dev->tuner_type != TUNER_ABSENT)
 		dev->v4l_device->device_caps |= V4L2_CAP_TUNER;
 	err = video_register_device(dev->v4l_device,
-		VFL_TYPE_GRABBER, -1);
+		VFL_TYPE_VIDEO, -1);
 	if (err < 0) {
 		pr_info("%s: can't register mpeg device\n", dev->name);
 		return err;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/cx23885/cx23885-alsa.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/cx23885/cx23885-alsa.c
@@ -550,7 +550,7 @@
 			   SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
 			THIS_MODULE, sizeof(struct cx23885_audio_dev), &card);
 	if (err < 0)
-		goto error;
+		goto error_msg;
 
 	chip = (struct cx23885_audio_dev *) card->private_data;
 	chip->dev = dev;
@@ -576,6 +576,7 @@
 
 error:
 	snd_card_free(card);
+error_msg:
 	pr_err("%s(): Failed to register analog audio adapter\n",
 	       __func__);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/cx23885/cx23885-cards.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/cx23885/cx23885-cards.c
@@ -801,6 +801,25 @@
 		.name		= "Hauppauge WinTV-Starburst2",
 		.portb		= CX23885_MPEG_DVB,
 	},
+	[CX23885_BOARD_AVERMEDIA_CE310B] = {
+		.name		= "AVerMedia CE310B",
+		.porta		= CX23885_ANALOG_VIDEO,
+		.force_bff	= 1,
+		.input          = {{
+			.type   = CX23885_VMUX_COMPOSITE1,
+			.vmux   = CX25840_VIN1_CH1 |
+				  CX25840_NONE_CH2 |
+				  CX25840_NONE0_CH3,
+			.amux   = CX25840_AUDIO7,
+		}, {
+			.type   = CX23885_VMUX_SVIDEO,
+			.vmux   = CX25840_VIN8_CH1 |
+				  CX25840_NONE_CH2 |
+				  CX25840_VIN7_CH3 |
+				  CX25840_SVIDEO_ON,
+			.amux   = CX25840_AUDIO7,
+		} },
+	},
 };
 const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
 
@@ -1124,6 +1143,10 @@
 		.subvendor = 0x0070,
 		.subdevice = 0xf02a,
 		.card      = CX23885_BOARD_HAUPPAUGE_STARBURST2,
+	}, {
+		.subvendor = 0x1461,
+		.subdevice = 0x3100,
+		.card      = CX23885_BOARD_AVERMEDIA_CE310B,
 	},
 };
 const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids);
@@ -2348,6 +2371,7 @@
 	case CX23885_BOARD_DVBSKY_T982:
 	case CX23885_BOARD_VIEWCAST_260E:
 	case CX23885_BOARD_VIEWCAST_460E:
+	case CX23885_BOARD_AVERMEDIA_CE310B:
 		dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev,
 				&dev->i2c_bus[2].i2c_adap,
 				"cx25840", 0x88 >> 1, NULL);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/cx23885/cx23885-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/cx23885/cx23885-core.c
@@ -2074,6 +2074,10 @@
 	 * 0x1451 is PCI ID for the IOMMU found on Ryzen
 	 */
 	{ PCI_VENDOR_ID_AMD, 0x1451 },
+	/* According to sudo lspci -nn,
+	 * 0x1423 is the PCI ID for the IOMMU found on Kaveri
+	 */
+	{ PCI_VENDOR_ID_AMD, 0x1423 },
 };
 
 static bool cx23885_does_need_dma_reset(void)
@@ -2150,7 +2154,7 @@
 	err = pci_set_dma_mask(pci_dev, 0xffffffff);
 	if (err) {
 		pr_err("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);
-		goto fail_ctrl;
+		goto fail_dma_set_mask;
 	}
 
 	err = request_irq(pci_dev->irq, cx23885_irq,
@@ -2158,7 +2162,7 @@
 	if (err < 0) {
 		pr_err("%s: can't get IRQ %d\n",
 		       dev->name, pci_dev->irq);
-		goto fail_irq;
+		goto fail_dma_set_mask;
 	}
 
 	switch (dev->board) {
@@ -2180,7 +2184,7 @@
 
 	return 0;
 
-fail_irq:
+fail_dma_set_mask:
 	cx23885_dev_unregister(dev);
 fail_ctrl:
 	v4l2_ctrl_handler_free(hdl);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/cx23885/cx23885-video.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/cx23885/cx23885-video.c
@@ -257,7 +257,8 @@
 		(dev->board == CX23885_BOARD_MYGICA_X8507) ||
 		(dev->board == CX23885_BOARD_AVERMEDIA_HC81R) ||
 		(dev->board == CX23885_BOARD_VIEWCAST_260E) ||
-		(dev->board == CX23885_BOARD_VIEWCAST_460E)) {
+		(dev->board == CX23885_BOARD_VIEWCAST_460E) ||
+		(dev->board == CX23885_BOARD_AVERMEDIA_CE310B)) {
 		/* Configure audio routing */
 		v4l2_subdev_call(dev->sd_cx25840, audio, s_routing,
 			INPUT(input)->amux, 0, 0);
@@ -408,7 +409,7 @@
 				dev->height >> 1);
 		break;
 	default:
-		BUG();
+		return -EINVAL; /* should not happen */
 	}
 	dprintk(2, "[%p/%d] buffer_init - %dx%d %dbpp 0x%08x - dma=0x%08lx\n",
 		buf, buf->vb.vb2_buf.index,
@@ -1298,12 +1299,16 @@
 	/* register Video device */
 	dev->video_dev = cx23885_vdev_init(dev, dev->pci,
 		&cx23885_video_template, "video");
+	if (!dev->video_dev) {
+		err = -ENOMEM;
+		goto fail_unreg;
+	}
 	dev->video_dev->queue = &dev->vb2_vidq;
 	dev->video_dev->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |
 				      V4L2_CAP_AUDIO | V4L2_CAP_VIDEO_CAPTURE;
 	if (dev->tuner_type != TUNER_ABSENT)
 		dev->video_dev->device_caps |= V4L2_CAP_TUNER;
-	err = video_register_device(dev->video_dev, VFL_TYPE_GRABBER,
+	err = video_register_device(dev->video_dev, VFL_TYPE_VIDEO,
 				    video_nr[dev->nr]);
 	if (err < 0) {
 		pr_info("%s: can't register video device\n",
@@ -1316,6 +1321,10 @@
 	/* register VBI device */
 	dev->vbi_dev = cx23885_vdev_init(dev, dev->pci,
 		&cx23885_vbi_template, "vbi");
+	if (!dev->vbi_dev) {
+		err = -ENOMEM;
+		goto fail_unreg;
+	}
 	dev->vbi_dev->queue = &dev->vb2_vbiq;
 	dev->vbi_dev->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |
 				    V4L2_CAP_AUDIO | V4L2_CAP_VBI_CAPTURE;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/cx23885/cx23885.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/cx23885/cx23885.h
@@ -101,6 +101,7 @@
 #define CX23885_BOARD_HAUPPAUGE_STARBURST2     59
 #define CX23885_BOARD_HAUPPAUGE_QUADHD_DVB_885 60
 #define CX23885_BOARD_HAUPPAUGE_QUADHD_ATSC_885 61
+#define CX23885_BOARD_AVERMEDIA_CE310B         62
 
 #define GPIO_0 0x00000001
 #define GPIO_1 0x00000002
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/cx23885/cx23888-ir.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/cx23885/cx23888-ir.c
@@ -1167,8 +1167,11 @@
 		return -ENOMEM;
 
 	spin_lock_init(&state->rx_kfifo_lock);
-	if (kfifo_alloc(&state->rx_kfifo, CX23888_IR_RX_KFIFO_SIZE, GFP_KERNEL))
+	if (kfifo_alloc(&state->rx_kfifo, CX23888_IR_RX_KFIFO_SIZE,
+			GFP_KERNEL)) {
+		kfree(state);
 		return -ENOMEM;
+	}
 
 	state->dev = dev;
 	sd = &state->sd;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/cx25821/cx25821-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/cx25821/cx25821-core.c
@@ -976,8 +976,10 @@
 	__le32 *cpu;
 	dma_addr_t dma = 0;
 
-	if (NULL != risc->cpu && risc->size < size)
+	if (risc->cpu && risc->size < size) {
 		pci_free_consistent(pci, risc->size, risc->cpu, risc->dma);
+		risc->cpu = NULL;
+	}
 	if (NULL == risc->cpu) {
 		cpu = pci_zalloc_consistent(pci, size, &dma);
 		if (NULL == cpu)
@@ -1338,11 +1340,11 @@
 	struct cx25821_dev *dev = get_cx25821(v4l2_dev);
 
 	cx25821_shutdown(dev);
-	pci_disable_device(pci_dev);
 
 	/* unregister stuff */
 	if (pci_dev->irq)
 		free_irq(pci_dev->irq, dev);
+	pci_disable_device(pci_dev);
 
 	cx25821_dev_unregister(dev);
 	v4l2_device_unregister(v4l2_dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/cx25821/cx25821-video.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/cx25821/cx25821-video.c
@@ -757,7 +757,7 @@
 		snprintf(vdev->name, sizeof(vdev->name), "%s #%d", dev->name, i);
 		video_set_drvdata(vdev, chan);
 
-		err = video_register_device(vdev, VFL_TYPE_GRABBER,
+		err = video_register_device(vdev, VFL_TYPE_VIDEO,
 					    video_nr[dev->nr]);
 
 		if (err < 0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/cx88/cx88-blackbird.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/cx88/cx88-blackbird.c
@@ -1138,7 +1138,7 @@
 				    V4L2_CAP_VIDEO_CAPTURE;
 	if (dev->core->board.tuner_type != UNSET)
 		dev->mpeg_dev.device_caps |= V4L2_CAP_TUNER;
-	err = video_register_device(&dev->mpeg_dev, VFL_TYPE_GRABBER, -1);
+	err = video_register_device(&dev->mpeg_dev, VFL_TYPE_VIDEO, -1);
 	if (err < 0) {
 		pr_info("can't register mpeg device\n");
 		return err;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/cx88/cx88-mpeg.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/cx88/cx88-mpeg.c
@@ -162,6 +162,9 @@
 	cx_write(MO_TS_GPCNTRL, GP_COUNT_CONTROL_RESET);
 	q->count = 0;
 
+	/* clear interrupt status register */
+	cx_write(MO_TS_INTSTAT,  0x1f1111);
+
 	/* enable irqs */
 	dprintk(1, "setting the interrupt mask\n");
 	cx_set(MO_PCI_INTMSK, core->pci_irqmask | PCI_INT_TSINT);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/cx88/cx88-vbi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/cx88/cx88-vbi.c
@@ -144,11 +144,10 @@
 		return -EINVAL;
 	vb2_set_plane_payload(vb, 0, size);
 
-	cx88_risc_buffer(dev->pci, &buf->risc, sgt->sgl,
-			 0, VBI_LINE_LENGTH * lines,
-			 VBI_LINE_LENGTH, 0,
-			 lines);
-	return 0;
+	return cx88_risc_buffer(dev->pci, &buf->risc, sgt->sgl,
+				0, VBI_LINE_LENGTH * lines,
+				VBI_LINE_LENGTH, 0,
+				lines);
 }
 
 static void buffer_finish(struct vb2_buffer *vb)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/cx88/cx88-video.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/cx88/cx88-video.c
@@ -433,6 +433,7 @@
 
 static int buffer_prepare(struct vb2_buffer *vb)
 {
+	int ret;
 	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
 	struct cx88_core *core = dev->core;
@@ -447,35 +448,35 @@
 
 	switch (core->field) {
 	case V4L2_FIELD_TOP:
-		cx88_risc_buffer(dev->pci, &buf->risc,
-				 sgt->sgl, 0, UNSET,
-				 buf->bpl, 0, core->height);
+		ret = cx88_risc_buffer(dev->pci, &buf->risc,
+				       sgt->sgl, 0, UNSET,
+				       buf->bpl, 0, core->height);
 		break;
 	case V4L2_FIELD_BOTTOM:
-		cx88_risc_buffer(dev->pci, &buf->risc,
-				 sgt->sgl, UNSET, 0,
-				 buf->bpl, 0, core->height);
+		ret = cx88_risc_buffer(dev->pci, &buf->risc,
+				       sgt->sgl, UNSET, 0,
+				       buf->bpl, 0, core->height);
 		break;
 	case V4L2_FIELD_SEQ_TB:
-		cx88_risc_buffer(dev->pci, &buf->risc,
-				 sgt->sgl,
-				 0, buf->bpl * (core->height >> 1),
-				 buf->bpl, 0,
-				 core->height >> 1);
+		ret = cx88_risc_buffer(dev->pci, &buf->risc,
+				       sgt->sgl,
+				       0, buf->bpl * (core->height >> 1),
+				       buf->bpl, 0,
+				       core->height >> 1);
 		break;
 	case V4L2_FIELD_SEQ_BT:
-		cx88_risc_buffer(dev->pci, &buf->risc,
-				 sgt->sgl,
-				 buf->bpl * (core->height >> 1), 0,
-				 buf->bpl, 0,
-				 core->height >> 1);
+		ret = cx88_risc_buffer(dev->pci, &buf->risc,
+				       sgt->sgl,
+				       buf->bpl * (core->height >> 1), 0,
+				       buf->bpl, 0,
+				       core->height >> 1);
 		break;
 	case V4L2_FIELD_INTERLACED:
 	default:
-		cx88_risc_buffer(dev->pci, &buf->risc,
-				 sgt->sgl, 0, buf->bpl,
-				 buf->bpl, buf->bpl,
-				 core->height >> 1);
+		ret = cx88_risc_buffer(dev->pci, &buf->risc,
+				       sgt->sgl, 0, buf->bpl,
+				       buf->bpl, buf->bpl,
+				       core->height >> 1);
 		break;
 	}
 	dprintk(2,
@@ -483,7 +484,7 @@
 		buf, buf->vb.vb2_buf.index, __func__,
 		core->width, core->height, dev->fmt->depth, dev->fmt->fourcc,
 		(unsigned long)buf->risc.dma);
-	return 0;
+	return ret;
 }
 
 static void buffer_finish(struct vb2_buffer *vb)
@@ -1277,7 +1278,7 @@
 	core = cx88_core_get(dev->pci);
 	if (!core) {
 		err = -EINVAL;
-		goto fail_free;
+		goto fail_disable;
 	}
 	dev->core = core;
 
@@ -1323,7 +1324,7 @@
 				       cc->step, cc->default_value);
 		if (!vc) {
 			err = core->audio_hdl.error;
-			goto fail_core;
+			goto fail_irq;
 		}
 		vc->priv = (void *)cc;
 	}
@@ -1337,7 +1338,7 @@
 				       cc->step, cc->default_value);
 		if (!vc) {
 			err = core->video_hdl.error;
-			goto fail_core;
+			goto fail_irq;
 		}
 		vc->priv = (void *)cc;
 		if (vc->id == V4L2_CID_CHROMA_AGC)
@@ -1451,7 +1452,7 @@
 				     V4L2_CAP_VIDEO_CAPTURE;
 	if (core->board.tuner_type != UNSET)
 		dev->video_dev.device_caps |= V4L2_CAP_TUNER;
-	err = video_register_device(&dev->video_dev, VFL_TYPE_GRABBER,
+	err = video_register_device(&dev->video_dev, VFL_TYPE_VIDEO,
 				    video_nr[core->nr]);
 	if (err < 0) {
 		pr_err("can't register video device\n");
@@ -1509,11 +1510,14 @@
 
 fail_unreg:
 	cx8800_unregister_video(dev);
-	free_irq(pci_dev->irq, dev);
 	mutex_unlock(&core->lock);
+fail_irq:
+	free_irq(pci_dev->irq, dev);
 fail_core:
 	core->v4ldev = NULL;
 	cx88_core_put(core, dev->pci);
+fail_disable:
+	pci_disable_device(pci_dev);
 fail_free:
 	kfree(dev);
 	return err;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/ddbridge/ddbridge-main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/ddbridge/ddbridge-main.c
@@ -247,7 +247,7 @@
 	ddb_unmap(dev);
 	pci_set_drvdata(pdev, NULL);
 	pci_disable_device(pdev);
-	return -1;
+	return stat;
 }
 
 /****************************************************************************/
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/dm1105/dm1105.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/dm1105/dm1105.c
@@ -1179,6 +1179,7 @@
 	struct dvb_demux *dvbdemux = &dev->demux;
 	struct dmx_demux *dmx = &dvbdemux->dmx;
 
+	cancel_work_sync(&dev->ir.work);
 	dm1105_ir_exit(dev);
 	dmx->close(dmx);
 	dvb_net_release(&dev->dvbnet);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/dt3155/dt3155.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/dt3155/dt3155.c
@@ -550,7 +550,7 @@
 					IRQF_SHARED, DT3155_NAME, pd);
 	if (err)
 		goto err_iounmap;
-	err = video_register_device(&pd->vdev, VFL_TYPE_GRABBER, -1);
+	err = video_register_device(&pd->vdev, VFL_TYPE_VIDEO, -1);
 	if (err)
 		goto err_free_irq;
 	dev_info(&pdev->dev, "/dev/video%i is ready\n", pd->vdev.minor);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/intel/ipu3/ipu3-cio2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/intel/ipu3/ipu3-cio2.c
@@ -359,7 +359,7 @@
 	void __iomem *const base = cio2->base;
 	u8 lanes, csi2bus = q->csi2.port;
 	u8 sensor_vc = SENSOR_VIR_CH_DFLT;
-	struct cio2_csi2_timing timing;
+	struct cio2_csi2_timing timing = { 0 };
 	int i, r;
 
 	fmt = cio2_find_format(NULL, &q->subdev_fmt.code);
@@ -799,6 +799,7 @@
 			atomic_dec(&q->bufs_queued);
 			vb2_buffer_done(&q->bufs[i]->vbb.vb2_buf,
 					state);
+			q->bufs[i] = NULL;
 		}
 	}
 }
@@ -1243,29 +1244,15 @@
 			       struct v4l2_subdev_format *fmt)
 {
 	struct cio2_queue *q = container_of(sd, struct cio2_queue, subdev);
-	struct v4l2_subdev_format format;
-	int ret;
-
-	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-		fmt->format = *v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
-		return 0;
-	}
 
-	if (fmt->pad == CIO2_PAD_SINK) {
-		format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
-		ret = v4l2_subdev_call(sd, pad, get_fmt, NULL,
-				       &format);
+	mutex_lock(&q->subdev_lock);
 
-		if (ret)
-			return ret;
-		/* update colorspace etc */
-		q->subdev_fmt.colorspace = format.format.colorspace;
-		q->subdev_fmt.ycbcr_enc = format.format.ycbcr_enc;
-		q->subdev_fmt.quantization = format.format.quantization;
-		q->subdev_fmt.xfer_func = format.format.xfer_func;
-	}
+	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
+		fmt->format = *v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
+	else
+		fmt->format = q->subdev_fmt;
 
-	fmt->format = q->subdev_fmt;
+	mutex_unlock(&q->subdev_lock);
 
 	return 0;
 }
@@ -1282,6 +1269,9 @@
 			       struct v4l2_subdev_format *fmt)
 {
 	struct cio2_queue *q = container_of(sd, struct cio2_queue, subdev);
+	struct v4l2_mbus_framefmt *mbus;
+	u32 mbus_code = fmt->format.code;
+	unsigned int i;
 
 	/*
 	 * Only allow setting sink pad format;
@@ -1290,16 +1280,29 @@
 	if (fmt->pad == CIO2_PAD_SOURCE)
 		return cio2_subdev_get_fmt(sd, cfg, fmt);
 
-	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
-		*v4l2_subdev_get_try_format(sd, cfg, fmt->pad) = fmt->format;
-	} else {
-		/* It's the sink, allow changing frame size */
-		q->subdev_fmt.width = fmt->format.width;
-		q->subdev_fmt.height = fmt->format.height;
-		q->subdev_fmt.code = fmt->format.code;
-		fmt->format = q->subdev_fmt;
+	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
+		mbus = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
+	else
+		mbus = &q->subdev_fmt;
+
+	fmt->format.code = formats[0].mbus_code;
+
+	for (i = 0; i < ARRAY_SIZE(formats); i++) {
+		if (formats[i].mbus_code == mbus_code) {
+			fmt->format.code = mbus_code;
+			break;
+		}
 	}
 
+	fmt->format.width = min_t(u32, fmt->format.width, CIO2_IMAGE_MAX_WIDTH);
+	fmt->format.height = min_t(u32, fmt->format.height,
+				   CIO2_IMAGE_MAX_LENGTH);
+	fmt->format.field = V4L2_FIELD_NONE;
+
+	mutex_lock(&q->subdev_lock);
+	*mbus = fmt->format;
+	mutex_unlock(&q->subdev_lock);
+
 	return 0;
 }
 
@@ -1558,6 +1561,7 @@
 
 	/* Initialize miscellaneous variables */
 	mutex_init(&q->lock);
+	mutex_init(&q->subdev_lock);
 
 	/* Initialize formats to default values */
 	fmt = &q->subdev_fmt;
@@ -1647,7 +1651,7 @@
 	vdev->queue = &q->vbq;
 	vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING;
 	video_set_drvdata(vdev, cio2);
-	r = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
+	r = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
 	if (r) {
 		dev_err(&cio2->pci_dev->dev,
 			"failed to register video device (%d)\n", r);
@@ -1676,6 +1680,7 @@
 fail_subdev_media_entity:
 	cio2_fbpt_exit(q, &cio2->pci_dev->dev);
 fail_fbpt:
+	mutex_destroy(&q->subdev_lock);
 	mutex_destroy(&q->lock);
 
 	return r;
@@ -1689,6 +1694,7 @@
 	v4l2_device_unregister_subdev(&q->subdev);
 	media_entity_cleanup(&q->subdev.entity);
 	cio2_fbpt_exit(q, &cio2->pci_dev->dev);
+	mutex_destroy(&q->subdev_lock);
 	mutex_destroy(&q->lock);
 }
 
@@ -1865,6 +1871,9 @@
 	v4l2_device_unregister(&cio2->v4l2_dev);
 	media_device_cleanup(&cio2->media_dev);
 	mutex_destroy(&cio2->lock);
+
+	pm_runtime_forbid(&pci_dev->dev);
+	pm_runtime_get_noresume(&pci_dev->dev);
 }
 
 static int __maybe_unused cio2_runtime_suspend(struct device *dev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/intel/ipu3/ipu3-cio2.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/intel/ipu3/ipu3-cio2.h
@@ -332,6 +332,7 @@
 
 	/* Subdev, /dev/v4l-subdevX */
 	struct v4l2_subdev subdev;
+	struct mutex subdev_lock; /* Serialise acces to subdev_fmt field */
 	struct media_pad subdev_pads[CIO2_PADS];
 	struct v4l2_mbus_framefmt subdev_fmt;
 	atomic_t frame_sequence;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/ivtv/ivtv-driver.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/ivtv/ivtv-driver.h
@@ -333,7 +333,6 @@
 	struct ivtv *itv;		/* for ease of use */
 	const char *name;		/* name of the stream */
 	int type;			/* stream type */
-	u32 caps;			/* V4L2 capabilities */
 
 	struct v4l2_fh *fh;		/* pointer to the streaming filehandle */
 	spinlock_t qlock;		/* locks access to the queues */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/ivtv/ivtv-ioctl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/ivtv/ivtv-ioctl.c
@@ -443,7 +443,7 @@
 	struct ivtv_stream *s = &itv->streams[fh2id(fh)->type];
 	struct v4l2_window *winfmt = &fmt->fmt.win;
 
-	if (!(s->caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
+	if (!(s->vdev.device_caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
 		return -EINVAL;
 	if (!itv->osd_video_pbase)
 		return -EINVAL;
@@ -554,7 +554,7 @@
 	u32 chromakey = fmt->fmt.win.chromakey;
 	u8 global_alpha = fmt->fmt.win.global_alpha;
 
-	if (!(s->caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
+	if (!(s->vdev.device_caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
 		return -EINVAL;
 	if (!itv->osd_video_pbase)
 		return -EINVAL;
@@ -1386,7 +1386,7 @@
 		0,
 	};
 
-	if (!(s->caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
+	if (!(s->vdev.device_caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
 		return -ENOTTY;
 	if (!itv->osd_video_pbase)
 		return -ENOTTY;
@@ -1453,7 +1453,7 @@
 	struct ivtv_stream *s = &itv->streams[fh2id(fh)->type];
 	struct yuv_playback_info *yi = &itv->yuv_info;
 
-	if (!(s->caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
+	if (!(s->vdev.device_caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
 		return -ENOTTY;
 	if (!itv->osd_video_pbase)
 		return -ENOTTY;
@@ -1473,7 +1473,7 @@
 	struct ivtv *itv = id->itv;
 	struct ivtv_stream *s = &itv->streams[fh2id(fh)->type];
 
-	if (!(s->caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
+	if (!(s->vdev.device_caps & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
 		return -ENOTTY;
 	if (!itv->osd_video_pbase)
 		return -ENOTTY;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/ivtv/ivtv-streams.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/ivtv/ivtv-streams.c
@@ -99,7 +99,7 @@
 } ivtv_stream_info[] = {
 	{	/* IVTV_ENC_STREAM_TYPE_MPG */
 		"encoder MPG",
-		VFL_TYPE_GRABBER, 0,
+		VFL_TYPE_VIDEO, 0,
 		PCI_DMA_FROMDEVICE, 0,
 		V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER |
 			V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
@@ -107,7 +107,7 @@
 	},
 	{	/* IVTV_ENC_STREAM_TYPE_YUV */
 		"encoder YUV",
-		VFL_TYPE_GRABBER, IVTV_V4L2_ENC_YUV_OFFSET,
+		VFL_TYPE_VIDEO, IVTV_V4L2_ENC_YUV_OFFSET,
 		PCI_DMA_FROMDEVICE, 0,
 		V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER |
 			V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
@@ -123,7 +123,7 @@
 	},
 	{	/* IVTV_ENC_STREAM_TYPE_PCM */
 		"encoder PCM",
-		VFL_TYPE_GRABBER, IVTV_V4L2_ENC_PCM_OFFSET,
+		VFL_TYPE_VIDEO, IVTV_V4L2_ENC_PCM_OFFSET,
 		PCI_DMA_FROMDEVICE, 0,
 		V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
 		&ivtv_v4l2_enc_fops
@@ -137,7 +137,7 @@
 	},
 	{	/* IVTV_DEC_STREAM_TYPE_MPG */
 		"decoder MPG",
-		VFL_TYPE_GRABBER, IVTV_V4L2_DEC_MPG_OFFSET,
+		VFL_TYPE_VIDEO, IVTV_V4L2_DEC_MPG_OFFSET,
 		PCI_DMA_TODEVICE, 0,
 		V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
 		&ivtv_v4l2_dec_fops
@@ -158,7 +158,7 @@
 	},
 	{	/* IVTV_DEC_STREAM_TYPE_YUV */
 		"decoder YUV",
-		VFL_TYPE_GRABBER, IVTV_V4L2_DEC_YUV_OFFSET,
+		VFL_TYPE_VIDEO, IVTV_V4L2_DEC_YUV_OFFSET,
 		PCI_DMA_TODEVICE, 0,
 		V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
 		&ivtv_v4l2_dec_fops
@@ -176,7 +176,7 @@
 	s->itv = itv;
 	s->type = type;
 	s->name = ivtv_stream_info[type].name;
-	s->caps = ivtv_stream_info[type].v4l2_caps;
+	s->vdev.device_caps = ivtv_stream_info[type].v4l2_caps;
 
 	if (ivtv_stream_info[type].pio)
 		s->dma = PCI_DMA_NONE;
@@ -299,12 +299,9 @@
 		if (s_mpg->vdev.v4l2_dev)
 			num = s_mpg->vdev.num + ivtv_stream_info[type].num_offset;
 	}
-	s->vdev.device_caps = s->caps;
-	if (itv->osd_video_pbase) {
-		itv->streams[IVTV_DEC_STREAM_TYPE_YUV].vdev.device_caps |=
-			V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
-		itv->streams[IVTV_DEC_STREAM_TYPE_MPG].vdev.device_caps |=
-			V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
+	if (itv->osd_video_pbase && (type == IVTV_DEC_STREAM_TYPE_YUV ||
+				     type == IVTV_DEC_STREAM_TYPE_MPG)) {
+		s->vdev.device_caps |= V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
 		itv->v4l2_cap |= V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
 	}
 	video_set_drvdata(&s->vdev, s);
@@ -318,7 +315,7 @@
 	name = video_device_node_name(&s->vdev);
 
 	switch (vfl_type) {
-	case VFL_TYPE_GRABBER:
+	case VFL_TYPE_VIDEO:
 		IVTV_INFO("Registered device %s for %s (%d kB)\n",
 			name, s->name, itv->options.kilobytes[type]);
 		break;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/meye/meye.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/meye/meye.c
@@ -1711,7 +1711,7 @@
 	v4l2_ctrl_handler_setup(&meye.hdl);
 	meye.vdev.ctrl_handler = &meye.hdl;
 
-	if (video_register_device(&meye.vdev, VFL_TYPE_GRABBER,
+	if (video_register_device(&meye.vdev, VFL_TYPE_VIDEO,
 				  video_nr) < 0) {
 		v4l2_err(v4l2_dev, "video_register_device failed\n");
 		goto outvideoreg;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/netup_unidvb/netup_unidvb_core.c
@@ -258,19 +258,24 @@
 	if ((reg40 & AVL_IRQ_ASSERTED) != 0) {
 		/* IRQ is being signaled */
 		reg_isr = readw(ndev->bmmio0 + REG_ISR);
-		if (reg_isr & NETUP_UNIDVB_IRQ_I2C0) {
-			iret = netup_i2c_interrupt(&ndev->i2c[0]);
-		} else if (reg_isr & NETUP_UNIDVB_IRQ_I2C1) {
-			iret = netup_i2c_interrupt(&ndev->i2c[1]);
-		} else if (reg_isr & NETUP_UNIDVB_IRQ_SPI) {
+		if (reg_isr & NETUP_UNIDVB_IRQ_SPI)
 			iret = netup_spi_interrupt(ndev->spi);
-		} else if (reg_isr & NETUP_UNIDVB_IRQ_DMA1) {
-			iret = netup_dma_interrupt(&ndev->dma[0]);
-		} else if (reg_isr & NETUP_UNIDVB_IRQ_DMA2) {
-			iret = netup_dma_interrupt(&ndev->dma[1]);
-		} else if (reg_isr & NETUP_UNIDVB_IRQ_CI) {
-			iret = netup_ci_interrupt(ndev);
+		else if (!ndev->old_fw) {
+			if (reg_isr & NETUP_UNIDVB_IRQ_I2C0) {
+				iret = netup_i2c_interrupt(&ndev->i2c[0]);
+			} else if (reg_isr & NETUP_UNIDVB_IRQ_I2C1) {
+				iret = netup_i2c_interrupt(&ndev->i2c[1]);
+			} else if (reg_isr & NETUP_UNIDVB_IRQ_DMA1) {
+				iret = netup_dma_interrupt(&ndev->dma[0]);
+			} else if (reg_isr & NETUP_UNIDVB_IRQ_DMA2) {
+				iret = netup_dma_interrupt(&ndev->dma[1]);
+			} else if (reg_isr & NETUP_UNIDVB_IRQ_CI) {
+				iret = netup_ci_interrupt(ndev);
+			} else {
+				goto err;
+			}
 		} else {
+err:
 			dev_err(&pci_dev->dev,
 				"%s(): unknown interrupt 0x%x\n",
 				__func__, reg_isr);
@@ -692,7 +697,7 @@
 	netup_unidvb_dma_enable(dma, 0);
 	msleep(50);
 	cancel_work_sync(&dma->work);
-	del_timer(&dma->timeout);
+	del_timer_sync(&dma->timeout);
 }
 
 static int netup_unidvb_dma_setup(struct netup_unidvb_dev *ndev)
@@ -882,12 +887,7 @@
 		ndev->lmmio0, (u32)pci_resource_len(pci_dev, 0),
 		ndev->lmmio1, (u32)pci_resource_len(pci_dev, 1),
 		pci_dev->irq);
-	if (request_irq(pci_dev->irq, netup_unidvb_isr, IRQF_SHARED,
-			"netup_unidvb", pci_dev) < 0) {
-		dev_err(&pci_dev->dev,
-			"%s(): can't get IRQ %d\n", __func__, pci_dev->irq);
-		goto irq_request_err;
-	}
+
 	ndev->dma_size = 2 * 188 *
 		NETUP_DMA_BLOCKS_COUNT * NETUP_DMA_PACKETS_COUNT;
 	ndev->dma_virt = dma_alloc_coherent(&pci_dev->dev,
@@ -928,6 +928,14 @@
 		dev_err(&pci_dev->dev, "netup_unidvb: DMA setup failed\n");
 		goto dma_setup_err;
 	}
+
+	if (request_irq(pci_dev->irq, netup_unidvb_isr, IRQF_SHARED,
+			"netup_unidvb", pci_dev) < 0) {
+		dev_err(&pci_dev->dev,
+			"%s(): can't get IRQ %d\n", __func__, pci_dev->irq);
+		goto dma_setup_err;
+	}
+
 	dev_info(&pci_dev->dev,
 		"netup_unidvb: device has been initialized\n");
 	return 0;
@@ -946,8 +954,6 @@
 	dma_free_coherent(&pci_dev->dev, ndev->dma_size,
 			ndev->dma_virt, ndev->dma_phys);
 dma_alloc_err:
-	free_irq(pci_dev->irq, pci_dev);
-irq_request_err:
 	iounmap(ndev->lmmio1);
 pci_bar1_error:
 	iounmap(ndev->lmmio0);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/netup_unidvb/netup_unidvb_spi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/netup_unidvb/netup_unidvb_spi.c
@@ -175,7 +175,7 @@
 	struct spi_master *master;
 	struct netup_spi *nspi;
 
-	master = spi_alloc_master(&ndev->pci_dev->dev,
+	master = devm_spi_alloc_master(&ndev->pci_dev->dev,
 		sizeof(struct netup_spi));
 	if (!master) {
 		dev_err(&ndev->pci_dev->dev,
@@ -208,6 +208,7 @@
 		ndev->pci_slot,
 		ndev->pci_func);
 	if (!spi_new_device(master, &netup_spi_board)) {
+		spi_unregister_master(master);
 		ndev->spi = NULL;
 		dev_err(&ndev->pci_dev->dev,
 			"%s(): unable to create SPI device\n", __func__);
@@ -226,13 +227,13 @@
 	if (!spi)
 		return;
 
+	spi_unregister_master(spi->master);
 	spin_lock_irqsave(&spi->lock, flags);
 	reg = readw(&spi->regs->control_stat);
 	writew(reg | NETUP_SPI_CTRL_IRQ, &spi->regs->control_stat);
 	reg = readw(&spi->regs->control_stat);
 	writew(reg & ~NETUP_SPI_CTRL_IMASK, &spi->regs->control_stat);
 	spin_unlock_irqrestore(&spi->lock, flags);
-	spi_unregister_master(spi->master);
 	ndev->spi = NULL;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/ngene/ngene-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/ngene/ngene-core.c
@@ -385,7 +385,7 @@
 
 	com.cmd.hdr.Opcode = CMD_CONFIGURE_FREE_BUFFER;
 	com.cmd.hdr.Length = 6;
-	memcpy(&com.cmd.ConfigureBuffers.config, config, 6);
+	memcpy(&com.cmd.ConfigureFreeBuffers.config, config, 6);
 	com.in_len = 6;
 	com.out_len = 0;
 
@@ -1488,7 +1488,9 @@
 	}
 
 	if (dev->ci.en && (io & NGENE_IO_TSOUT)) {
-		dvb_ca_en50221_init(adapter, dev->ci.en, 0, 1);
+		ret = dvb_ca_en50221_init(adapter, dev->ci.en, 0, 1);
+		if (ret != 0)
+			goto err;
 		set_transfer(chan, 1);
 		chan->dev->channel[2].DataFormatFlags = DF_SWAP32;
 		set_transfer(&chan->dev->channel[2], 1);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/ngene/ngene.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/ngene/ngene.h
@@ -407,12 +407,14 @@
 
 struct FW_CONFIGURE_FREE_BUFFERS {
 	struct FW_HEADER hdr;
-	u8   UVI1_BufferLength;
-	u8   UVI2_BufferLength;
-	u8   TVO_BufferLength;
-	u8   AUD1_BufferLength;
-	u8   AUD2_BufferLength;
-	u8   TVA_BufferLength;
+	struct {
+		u8   UVI1_BufferLength;
+		u8   UVI2_BufferLength;
+		u8   TVO_BufferLength;
+		u8   AUD1_BufferLength;
+		u8   AUD2_BufferLength;
+		u8   TVA_BufferLength;
+	} __packed config;
 } __attribute__ ((__packed__));
 
 struct FW_CONFIGURE_UART {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/saa7134/saa7134-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/saa7134/saa7134-core.c
@@ -1214,7 +1214,7 @@
 	if (saa7134_no_overlay <= 0)
 		dev->video_dev->device_caps |= V4L2_CAP_VIDEO_OVERLAY;
 
-	err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER,
+	err = video_register_device(dev->video_dev,VFL_TYPE_VIDEO,
 				    video_nr[dev->nr]);
 	if (err < 0) {
 		pr_info("%s: can't register video device\n",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/saa7134/saa7134-dvb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/saa7134/saa7134-dvb.c
@@ -466,7 +466,9 @@
 	/* switch the board to analog mode */
 	if (fe->ops.i2c_gate_ctrl)
 		fe->ops.i2c_gate_ctrl(fe, 1);
-	i2c_transfer(&dev->i2c_adap, &analog_msg, 1);
+	if (i2c_transfer(&dev->i2c_adap, &analog_msg, 1) != 1)
+		return -EIO;
+
 	return 0;
 }
 
@@ -1018,7 +1020,9 @@
 	else
 		wbuf[1] = rbuf & 0xef;
 	msg[0].len = 2;
-	i2c_transfer(&dev->i2c_adap, msg, 1);
+	if (i2c_transfer(&dev->i2c_adap, msg, 1) != 1)
+		return -EIO;
+
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/saa7134/saa7134-empress.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/saa7134/saa7134-empress.c
@@ -282,8 +282,11 @@
 	q->lock = &dev->lock;
 	q->dev = &dev->pci->dev;
 	err = vb2_queue_init(q);
-	if (err)
+	if (err) {
+		video_device_release(dev->empress_dev);
+		dev->empress_dev = NULL;
 		return err;
+	}
 	dev->empress_dev->queue = q;
 	dev->empress_dev->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |
 					V4L2_CAP_VIDEO_CAPTURE;
@@ -291,7 +294,7 @@
 		dev->empress_dev->device_caps |= V4L2_CAP_TUNER;
 
 	video_set_drvdata(dev->empress_dev, dev);
-	err = video_register_device(dev->empress_dev,VFL_TYPE_GRABBER,
+	err = video_register_device(dev->empress_dev,VFL_TYPE_VIDEO,
 				    empress_nr[dev->nr]);
 	if (err < 0) {
 		pr_info("%s: can't register video device\n",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/saa7134/saa7134-ts.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/saa7134/saa7134-ts.c
@@ -300,6 +300,7 @@
 
 int saa7134_ts_fini(struct saa7134_dev *dev)
 {
+	del_timer_sync(&dev->ts_q.timeout);
 	saa7134_pgtable_free(dev->pci, &dev->ts_q.pt);
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/saa7134/saa7134-tvaudio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/saa7134/saa7134-tvaudio.c
@@ -683,7 +683,8 @@
 {
 	int err;
 
-	audio_dbg(2, "dsp write reg 0x%x = 0x%06x\n", reg << 2, value);
+	audio_dbg(2, "dsp write reg 0x%x = 0x%06x\n",
+		  (reg << 2) & 0xffffffff, value);
 	err = saa_dsp_wait_bit(dev,SAA7135_DSP_RWSTATE_WRR);
 	if (err < 0)
 		return err;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/saa7134/saa7134-vbi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/saa7134/saa7134-vbi.c
@@ -185,6 +185,7 @@
 int saa7134_vbi_fini(struct saa7134_dev *dev)
 {
 	/* nothing */
+	del_timer_sync(&dev->vbi_q.timeout);
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/saa7134/saa7134-video.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/saa7134/saa7134-video.c
@@ -1179,7 +1179,7 @@
 
 	saa_call_all(dev, tuner, standby);
 	if (vdev->vfl_type == VFL_TYPE_RADIO)
-		saa_call_all(dev, core, ioctl, SAA6588_CMD_CLOSE, &cmd);
+		saa_call_all(dev, core, command, SAA6588_CMD_CLOSE, &cmd);
 	mutex_unlock(&dev->lock);
 
 	return 0;
@@ -1198,7 +1198,7 @@
 	cmd.result = -ENODEV;
 
 	mutex_lock(&dev->lock);
-	saa_call_all(dev, core, ioctl, SAA6588_CMD_READ, &cmd);
+	saa_call_all(dev, core, command, SAA6588_CMD_READ, &cmd);
 	mutex_unlock(&dev->lock);
 
 	return cmd.result;
@@ -1214,7 +1214,7 @@
 	cmd.event_list = wait;
 	cmd.poll_mask = 0;
 	mutex_lock(&dev->lock);
-	saa_call_all(dev, core, ioctl, SAA6588_CMD_POLL, &cmd);
+	saa_call_all(dev, core, command, SAA6588_CMD_POLL, &cmd);
 	mutex_unlock(&dev->lock);
 
 	return rc | cmd.poll_mask;
@@ -2154,6 +2154,7 @@
 
 void saa7134_video_fini(struct saa7134_dev *dev)
 {
+	del_timer_sync(&dev->video_q.timeout);
 	/* free stuff */
 	vb2_queue_release(&dev->video_vbq);
 	saa7134_pgtable_free(dev->pci, &dev->video_q.pt);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/saa7146/hexium_gemini.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/saa7146/hexium_gemini.c
@@ -284,12 +284,17 @@
 	hexium_set_input(hexium, 0);
 	hexium->cur_input = 0;
 
-	saa7146_vv_init(dev, &vv_data);
+	ret = saa7146_vv_init(dev, &vv_data);
+	if (ret) {
+		i2c_del_adapter(&hexium->i2c_adapter);
+		kfree(hexium);
+		return ret;
+	}
 
 	vv_data.vid_ops.vidioc_enum_input = vidioc_enum_input;
 	vv_data.vid_ops.vidioc_g_input = vidioc_g_input;
 	vv_data.vid_ops.vidioc_s_input = vidioc_s_input;
-	ret = saa7146_register_device(&hexium->video_dev, dev, "hexium gemini", VFL_TYPE_GRABBER);
+	ret = saa7146_register_device(&hexium->video_dev, dev, "hexium gemini", VFL_TYPE_VIDEO);
 	if (ret < 0) {
 		pr_err("cannot register capture v4l2 device. skipping.\n");
 		saa7146_vv_release(dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/saa7146/hexium_orion.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/saa7146/hexium_orion.c
@@ -355,14 +355,20 @@
 static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
 {
 	struct hexium *hexium = (struct hexium *) dev->ext_priv;
+	int ret;
 
 	DEB_EE("\n");
 
-	saa7146_vv_init(dev, &vv_data);
+	ret = saa7146_vv_init(dev, &vv_data);
+	if (ret) {
+		pr_err("Error in saa7146_vv_init()\n");
+		return ret;
+	}
+
 	vv_data.vid_ops.vidioc_enum_input = vidioc_enum_input;
 	vv_data.vid_ops.vidioc_g_input = vidioc_g_input;
 	vv_data.vid_ops.vidioc_s_input = vidioc_s_input;
-	if (0 != saa7146_register_device(&hexium->video_dev, dev, "hexium orion", VFL_TYPE_GRABBER)) {
+	if (0 != saa7146_register_device(&hexium->video_dev, dev, "hexium orion", VFL_TYPE_VIDEO)) {
 		pr_err("cannot register capture v4l2 device. skipping.\n");
 		return -1;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/saa7146/mxb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/saa7146/mxb.c
@@ -641,16 +641,17 @@
 	struct mxb *mxb = (struct mxb *)dev->ext_priv;
 
 	DEB_D("VIDIOC_S_AUDIO %d\n", a->index);
-	if (mxb_inputs[mxb->cur_input].audioset & (1 << a->index)) {
-		if (mxb->cur_audinput != a->index) {
-			mxb->cur_audinput = a->index;
-			tea6420_route(mxb, a->index);
-			if (mxb->cur_audinput == 0)
-				mxb_update_audmode(mxb);
-		}
-		return 0;
+	if (a->index >= 32 ||
+	    !(mxb_inputs[mxb->cur_input].audioset & (1 << a->index)))
+		return -EINVAL;
+
+	if (mxb->cur_audinput != a->index) {
+		mxb->cur_audinput = a->index;
+		tea6420_route(mxb, a->index);
+		if (mxb->cur_audinput == 0)
+			mxb_update_audmode(mxb);
 	}
-	return -EINVAL;
+	return 0;
 }
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -682,10 +683,16 @@
 static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
 {
 	struct mxb *mxb;
+	int ret;
 
 	DEB_EE("dev:%p\n", dev);
 
-	saa7146_vv_init(dev, &vv_data);
+	ret = saa7146_vv_init(dev, &vv_data);
+	if (ret) {
+		ERR("Error in saa7146_vv_init()");
+		return ret;
+	}
+
 	if (mxb_probe(dev)) {
 		saa7146_vv_release(dev);
 		return -1;
@@ -707,7 +714,7 @@
 	vv_data.vid_ops.vidioc_g_register = vidioc_g_register;
 	vv_data.vid_ops.vidioc_s_register = vidioc_s_register;
 #endif
-	if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) {
+	if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_VIDEO)) {
 		ERR("cannot register capture v4l2 device. skipping.\n");
 		saa7146_vv_release(dev);
 		return -1;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/saa7164/saa7164-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/saa7164/saa7164-core.c
@@ -1227,7 +1227,7 @@
 
 	if (saa7164_dev_setup(dev) < 0) {
 		err = -EINVAL;
-		goto fail_free;
+		goto fail_dev;
 	}
 
 	/* print pci info */
@@ -1395,6 +1395,8 @@
 
 fail_irq:
 	saa7164_dev_unregister(dev);
+fail_dev:
+	pci_disable_device(pci_dev);
 fail_free:
 	v4l2_device_unregister(&dev->v4l2_dev);
 	kfree(dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/saa7164/saa7164-encoder.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/saa7164/saa7164-encoder.c
@@ -1008,7 +1008,7 @@
 		printk(KERN_ERR "%s() failed (errno = %d), NO PCI configuration\n",
 			__func__, result);
 		result = -ENOMEM;
-		goto failed;
+		goto fail_pci;
 	}
 
 	/* Establish encoder defaults here */
@@ -1062,7 +1062,7 @@
 			  100000, ENCODER_DEF_BITRATE);
 	if (hdl->error) {
 		result = hdl->error;
-		goto failed;
+		goto fail_hdl;
 	}
 
 	port->std = V4L2_STD_NTSC_M;
@@ -1080,21 +1080,18 @@
 		printk(KERN_INFO "%s: can't allocate mpeg device\n",
 			dev->name);
 		result = -ENOMEM;
-		goto failed;
+		goto fail_hdl;
 	}
 
 	port->v4l_device->ctrl_handler = hdl;
 	v4l2_ctrl_handler_setup(hdl);
 	video_set_drvdata(port->v4l_device, port);
 	result = video_register_device(port->v4l_device,
-		VFL_TYPE_GRABBER, -1);
+		VFL_TYPE_VIDEO, -1);
 	if (result < 0) {
 		printk(KERN_INFO "%s: can't register mpeg device\n",
 			dev->name);
-		/* TODO: We're going to leak here if we don't dealloc
-		 The buffers above. The unreg function can't deal wit it.
-		*/
-		goto failed;
+		goto fail_reg;
 	}
 
 	printk(KERN_INFO "%s: registered device video%d [mpeg]\n",
@@ -1116,9 +1113,14 @@
 
 	saa7164_api_set_encoder(port);
 	saa7164_api_get_encoder(port);
+	return 0;
 
-	result = 0;
-failed:
+fail_reg:
+	video_device_release(port->v4l_device);
+	port->v4l_device = NULL;
+fail_hdl:
+	v4l2_ctrl_handler_free(hdl);
+fail_pci:
 	return result;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/smipcie/smipcie-ir.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/smipcie/smipcie-ir.c
@@ -60,39 +60,45 @@
 {
 	struct smi_dev *dev = ir->dev;
 	struct rc_dev *rc_dev = ir->rc_dev;
-	u32 dwIRControl, dwIRData;
-	u8 index, ucIRCount, readLoop;
+	u32 control, data;
+	u8 index, ir_count, read_loop;
 
-	dwIRControl = smi_read(IR_Init_Reg);
+	control = smi_read(IR_Init_Reg);
 
-	if (dwIRControl & rbIRVld) {
-		ucIRCount = (u8) smi_read(IR_Data_Cnt);
+	dev_dbg(&rc_dev->dev, "ircontrol: 0x%08x\n", control);
 
-		readLoop = ucIRCount/4;
-		if (ucIRCount % 4)
-			readLoop += 1;
-		for (index = 0; index < readLoop; index++) {
-			dwIRData = smi_read(IR_DATA_BUFFER_BASE + (index * 4));
-
-			ir->irData[index*4 + 0] = (u8)(dwIRData);
-			ir->irData[index*4 + 1] = (u8)(dwIRData >> 8);
-			ir->irData[index*4 + 2] = (u8)(dwIRData >> 16);
-			ir->irData[index*4 + 3] = (u8)(dwIRData >> 24);
+	if (control & rbIRVld) {
+		ir_count = (u8)smi_read(IR_Data_Cnt);
+
+		dev_dbg(&rc_dev->dev, "ircount %d\n", ir_count);
+
+		read_loop = ir_count / 4;
+		if (ir_count % 4)
+			read_loop += 1;
+		for (index = 0; index < read_loop; index++) {
+			data = smi_read(IR_DATA_BUFFER_BASE + (index * 4));
+			dev_dbg(&rc_dev->dev, "IRData 0x%08x\n", data);
+
+			ir->irData[index * 4 + 0] = (u8)(data);
+			ir->irData[index * 4 + 1] = (u8)(data >> 8);
+			ir->irData[index * 4 + 2] = (u8)(data >> 16);
+			ir->irData[index * 4 + 3] = (u8)(data >> 24);
 		}
-		smi_raw_process(rc_dev, ir->irData, ucIRCount);
-		smi_set(IR_Init_Reg, rbIRVld);
+		smi_raw_process(rc_dev, ir->irData, ir_count);
 	}
 
-	if (dwIRControl & rbIRhighidle) {
+	if (control & rbIRhighidle) {
 		struct ir_raw_event rawir = {};
 
+		dev_dbg(&rc_dev->dev, "high idle\n");
+
 		rawir.pulse = 0;
 		rawir.duration = US_TO_NS(SMI_SAMPLE_PERIOD *
 					  SMI_SAMPLE_IDLEMIN);
 		ir_raw_event_store_with_filter(rc_dev, &rawir);
-		smi_set(IR_Init_Reg, rbIRhighidle);
 	}
 
+	smi_set(IR_Init_Reg, rbIRVld);
 	ir_raw_event_handle(rc_dev);
 }
 
@@ -151,7 +157,7 @@
 	rc_dev->dev.parent = &dev->pci_dev->dev;
 
 	rc_dev->map_name = dev->info->rc_map;
-	rc_dev->timeout = MS_TO_NS(100);
+	rc_dev->timeout = US_TO_NS(SMI_SAMPLE_PERIOD * SMI_SAMPLE_IDLEMIN);
 	rc_dev->rx_resolution = US_TO_NS(SMI_SAMPLE_PERIOD);
 
 	ir->rc_dev = rc_dev;
@@ -174,7 +180,7 @@
 	struct smi_rc *ir = &dev->ir;
 	struct rc_dev *rc_dev = ir->rc_dev;
 
-	smi_ir_stop(ir);
 	rc_unregister_device(rc_dev);
+	smi_ir_stop(ir);
 	ir->rc_dev = NULL;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/solo6x10/solo6x10-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/solo6x10/solo6x10-core.c
@@ -420,6 +420,7 @@
 		     solo_dev->nr_chans);
 
 	if (device_register(dev)) {
+		put_device(dev);
 		dev->parent = NULL;
 		return -ENOMEM;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/solo6x10/solo6x10-g723.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/solo6x10/solo6x10-g723.c
@@ -399,7 +399,7 @@
 
 	ret = snd_ctl_add(card, snd_ctl_new1(&kctl, solo_dev));
 	if (ret < 0)
-		return ret;
+		goto snd_error;
 
 	ret = solo_snd_pcm_init(solo_dev);
 	if (ret < 0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/solo6x10/solo6x10-offsets.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/solo6x10/solo6x10-offsets.h
@@ -57,16 +57,16 @@
 #define SOLO_MP4E_EXT_ADDR(__solo) \
 	(SOLO_EREF_EXT_ADDR(__solo) + SOLO_EREF_EXT_AREA(__solo))
 #define SOLO_MP4E_EXT_SIZE(__solo) \
-	max((__solo->nr_chans * 0x00080000),				\
-	    min(((__solo->sdram_size - SOLO_MP4E_EXT_ADDR(__solo)) -	\
-		 __SOLO_JPEG_MIN_SIZE(__solo)), 0x00ff0000))
+	clamp(__solo->sdram_size - SOLO_MP4E_EXT_ADDR(__solo) -	\
+	      __SOLO_JPEG_MIN_SIZE(__solo),			\
+	      __solo->nr_chans * 0x00080000, 0x00ff0000)
 
 #define __SOLO_JPEG_MIN_SIZE(__solo)		(__solo->nr_chans * 0x00080000)
 #define SOLO_JPEG_EXT_ADDR(__solo) \
 		(SOLO_MP4E_EXT_ADDR(__solo) + SOLO_MP4E_EXT_SIZE(__solo))
 #define SOLO_JPEG_EXT_SIZE(__solo) \
-	max(__SOLO_JPEG_MIN_SIZE(__solo),				\
-	    min((__solo->sdram_size - SOLO_JPEG_EXT_ADDR(__solo)), 0x00ff0000))
+	clamp(__solo->sdram_size - SOLO_JPEG_EXT_ADDR(__solo),	\
+	      __SOLO_JPEG_MIN_SIZE(__solo), 0x00ff0000)
 
 #define SOLO_SDRAM_END(__solo) \
 	(SOLO_JPEG_EXT_ADDR(__solo) + SOLO_JPEG_EXT_SIZE(__solo))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
@@ -1304,7 +1304,7 @@
 	solo_enc->vfd->queue = &solo_enc->vidq;
 	solo_enc->vfd->lock = &solo_enc->lock;
 	video_set_drvdata(solo_enc->vfd, solo_enc);
-	ret = video_register_device(solo_enc->vfd, VFL_TYPE_GRABBER, nr);
+	ret = video_register_device(solo_enc->vfd, VFL_TYPE_VIDEO, nr);
 	if (ret < 0)
 		goto vdev_release;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/solo6x10/solo6x10-v4l2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/solo6x10/solo6x10-v4l2.c
@@ -692,7 +692,7 @@
 	while (erase_off(solo_dev))
 		/* Do nothing */;
 
-	ret = video_register_device(solo_dev->vfd, VFL_TYPE_GRABBER, nr);
+	ret = video_register_device(solo_dev->vfd, VFL_TYPE_VIDEO, nr);
 	if (ret < 0)
 		goto fail;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/sta2x11/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/sta2x11/Kconfig
@@ -2,6 +2,7 @@
 config STA2X11_VIP
 	tristate "STA2X11 VIP Video For Linux"
 	depends on STA2X11 || COMPILE_TEST
+	select GPIOLIB if MEDIA_SUBDRV_AUTOSELECT
 	select VIDEO_ADV7180 if MEDIA_SUBDRV_AUTOSELECT
 	select VIDEOBUF2_DMA_CONTIG
 	depends on PCI && VIDEO_V4L2 && VIRT_TO_BUS
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/sta2x11/sta2x11_vip.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/sta2x11/sta2x11_vip.c
@@ -760,7 +760,7 @@
 /**
  * vip_irq - interrupt routine
  * @irq: Number of interrupt ( not used, correct number is assumed )
- * @vip: local data structure containing all information
+ * @data: local data structure containing all information
  *
  * check for both frame interrupts set ( top and bottom ).
  * check FIFO overflow, but limit number of log messages after open.
@@ -770,8 +770,9 @@
  *
  * IRQ_HANDLED, interrupt done.
  */
-static irqreturn_t vip_irq(int irq, struct sta2x11_vip *vip)
+static irqreturn_t vip_irq(int irq, void *data)
 {
+	struct sta2x11_vip *vip = data;
 	unsigned int status;
 
 	status = reg_read(vip, DVP_ITS);
@@ -1053,9 +1054,7 @@
 
 	spin_lock_init(&vip->slock);
 
-	ret = request_irq(pdev->irq,
-			  (irq_handler_t) vip_irq,
-			  IRQF_SHARED, KBUILD_MODNAME, vip);
+	ret = request_irq(pdev->irq, vip_irq, IRQF_SHARED, KBUILD_MODNAME, vip);
 	if (ret) {
 		dev_err(&pdev->dev, "request_irq failed\n");
 		ret = -ENODEV;
@@ -1069,7 +1068,7 @@
 	vip->video_dev.lock = &vip->v4l_lock;
 	video_set_drvdata(&vip->video_dev, vip);
 
-	ret = video_register_device(&vip->video_dev, VFL_TYPE_GRABBER, -1);
+	ret = video_register_device(&vip->video_dev, VFL_TYPE_VIDEO, -1);
 	if (ret)
 		goto vrelease;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/ttpci/av7110.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/ttpci/av7110.c
@@ -406,14 +406,15 @@
 	case DATA_CI_GET:
 	{
 		u8 *data = av7110->debi_virt;
+		u8 data_0 = data[0];
 
-		if ((data[0] < 2) && data[2] == 0xff) {
+		if (data_0 < 2 && data[2] == 0xff) {
 			int flags = 0;
 			if (data[5] > 0)
 				flags |= CA_CI_MODULE_PRESENT;
 			if (data[5] > 5)
 				flags |= CA_CI_MODULE_READY;
-			av7110->ci_slot[data[0]].flags = flags;
+			av7110->ci_slot[data_0].flags = flags;
 		} else
 			ci_get_data(&av7110->ci_rbuffer,
 				    av7110->debi_virt,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/ttpci/av7110_av.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/ttpci/av7110_av.c
@@ -822,10 +822,10 @@
 		av7110_ipack_flush(ipack);
 
 	if (buf[3] & ADAPT_FIELD) {
+		if (buf[4] > len - 1 - 4)
+			return 0;
 		len -= buf[4] + 1;
 		buf += buf[4] + 1;
-		if (!len)
-			return 0;
 	}
 
 	av7110_ipack_instant_repack(buf + 4, len - 4, ipack);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/ttpci/av7110_v4l.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/ttpci/av7110_v4l.c
@@ -831,7 +831,7 @@
 	if (FW_VERSION(av7110->arm_app) < 0x2623)
 		vv_data->capabilities &= ~V4L2_CAP_SLICED_VBI_OUTPUT;
 
-	if (saa7146_register_device(&av7110->v4l_dev, dev, "av7110", VFL_TYPE_GRABBER)) {
+	if (saa7146_register_device(&av7110->v4l_dev, dev, "av7110", VFL_TYPE_VIDEO)) {
 		ERR("cannot register capture device. skipping\n");
 		saa7146_vv_release(dev);
 		return -ENODEV;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/ttpci/budget-av.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/ttpci/budget-av.c
@@ -1462,7 +1462,8 @@
 		budget_av->has_saa7113 = 1;
 		err = saa7146_vv_init(dev, &vv_data);
 		if (err != 0) {
-			/* fixme: proper cleanup here */
+			ttpci_budget_deinit(&budget_av->budget);
+			kfree(budget_av);
 			ERR("cannot init vv subsystem\n");
 			return err;
 		}
@@ -1470,10 +1471,11 @@
 		vv_data.vid_ops.vidioc_g_input = vidioc_g_input;
 		vv_data.vid_ops.vidioc_s_input = vidioc_s_input;
 
-		if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", VFL_TYPE_GRABBER))) {
-			/* fixme: proper cleanup here */
-			ERR("cannot register capture v4l2 device\n");
+		if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", VFL_TYPE_VIDEO))) {
 			saa7146_vv_release(dev);
+			ttpci_budget_deinit(&budget_av->budget);
+			kfree(budget_av);
+			ERR("cannot register capture v4l2 device\n");
 			return err;
 		}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/ttpci/budget-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/ttpci/budget-core.c
@@ -369,20 +369,25 @@
 	ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &budget->hw_frontend);
 
 	if (ret < 0)
-		return ret;
+		goto err_release_dmx;
 
 	budget->mem_frontend.source = DMX_MEMORY_FE;
 	ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &budget->mem_frontend);
 	if (ret < 0)
-		return ret;
+		goto err_release_dmx;
 
 	ret = dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, &budget->hw_frontend);
 	if (ret < 0)
-		return ret;
+		goto err_release_dmx;
 
 	dvb_net_init(&budget->dvb_adapter, &budget->dvb_net, &dvbdemux->dmx);
 
 	return 0;
+
+err_release_dmx:
+	dvb_dmxdev_release(&budget->dmxdev);
+	dvb_dmx_release(&budget->demux);
+	return ret;
 }
 
 static void budget_unregister(struct budget *budget)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/tw5864/tw5864-video.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/tw5864/tw5864-video.c
@@ -767,6 +767,9 @@
 	fintv->type = V4L2_FRMIVAL_TYPE_STEPWISE;
 
 	ret = tw5864_frameinterval_get(input, &frameinterval);
+	if (ret)
+		return ret;
+
 	fintv->stepwise.step = frameinterval;
 	fintv->stepwise.min = frameinterval;
 	fintv->stepwise.max = frameinterval;
@@ -785,6 +788,9 @@
 	cp->capability = V4L2_CAP_TIMEPERFRAME;
 
 	ret = tw5864_frameinterval_get(input, &cp->timeperframe);
+	if (ret)
+		return ret;
+
 	cp->timeperframe.numerator *= input->frame_interval;
 	cp->capturemode = 0;
 	cp->readbuffers = 2;
@@ -1156,7 +1162,7 @@
 	input->gop = GOP_SIZE;
 	input->frame_interval = 1;
 
-	ret = video_register_device(&input->vdev, VFL_TYPE_GRABBER, video_nr);
+	ret = video_register_device(&input->vdev, VFL_TYPE_VIDEO, video_nr);
 	if (ret)
 		goto free_v4l2_hdl;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/tw68/tw68-video.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/tw68/tw68-video.c
@@ -962,7 +962,7 @@
 	dev->vdev.lock = &dev->lock;
 	dev->vdev.queue = &dev->vidq;
 	video_set_drvdata(&dev->vdev, dev);
-	return video_register_device(&dev->vdev, VFL_TYPE_GRABBER, video_nr);
+	return video_register_device(&dev->vdev, VFL_TYPE_VIDEO, video_nr);
 }
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/tw686x/tw686x-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/tw686x/tw686x-core.c
@@ -315,13 +315,6 @@
 
 	spin_lock_init(&dev->lock);
 
-	err = request_irq(pci_dev->irq, tw686x_irq, IRQF_SHARED,
-			  dev->name, dev);
-	if (err < 0) {
-		dev_err(&pci_dev->dev, "unable to request interrupt\n");
-		goto iounmap;
-	}
-
 	timer_setup(&dev->dma_delay_timer, tw686x_dma_delay, 0);
 
 	/*
@@ -333,18 +326,23 @@
 	err = tw686x_video_init(dev);
 	if (err) {
 		dev_err(&pci_dev->dev, "can't register video\n");
-		goto free_irq;
+		goto iounmap;
 	}
 
 	err = tw686x_audio_init(dev);
 	if (err)
 		dev_warn(&pci_dev->dev, "can't register audio\n");
 
+	err = request_irq(pci_dev->irq, tw686x_irq, IRQF_SHARED,
+			  dev->name, dev);
+	if (err < 0) {
+		dev_err(&pci_dev->dev, "unable to request interrupt\n");
+		goto iounmap;
+	}
+
 	pci_set_drvdata(pci_dev, dev);
 	return 0;
 
-free_irq:
-	free_irq(pci_dev->irq, dev);
 iounmap:
 	pci_iounmap(pci_dev, dev->mmio);
 free_region:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/pci/tw686x/tw686x-video.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/pci/tw686x/tw686x-video.c
@@ -1282,7 +1282,7 @@
 		vc->device = vdev;
 		video_set_drvdata(vdev, vc);
 
-		err = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
+		err = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
 		if (err < 0)
 			goto error;
 		vc->num = vdev->num;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/am437x/am437x-vpfe.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/am437x/am437x-vpfe.c
@@ -1830,6 +1830,10 @@
 	if (!(sdinfo->inputs[0].capabilities & V4L2_IN_CAP_STD))
 		return -ENODATA;
 
+	/* if trying to set the same std then nothing to do */
+	if (vpfe_standards[vpfe->std_index].std_id == std_id)
+		return 0;
+
 	/* If streaming is started, return error */
 	if (vb2_is_busy(&vpfe->buffer_queue)) {
 		vpfe_err(vpfe, "%s device busy\n", __func__);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/aspeed-video.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/aspeed-video.c
@@ -151,7 +151,7 @@
 #define  VE_SRC_TB_EDGE_DET_BOT		GENMASK(28, VE_SRC_TB_EDGE_DET_BOT_SHF)
 
 #define VE_MODE_DETECT_STATUS		0x098
-#define  VE_MODE_DETECT_H_PIXELS	GENMASK(11, 0)
+#define  VE_MODE_DETECT_H_PERIOD	GENMASK(11, 0)
 #define  VE_MODE_DETECT_V_LINES_SHF	16
 #define  VE_MODE_DETECT_V_LINES		GENMASK(27, VE_MODE_DETECT_V_LINES_SHF)
 #define  VE_MODE_DETECT_STATUS_VSYNC	BIT(28)
@@ -162,6 +162,8 @@
 #define  VE_SYNC_STATUS_VSYNC_SHF	16
 #define  VE_SYNC_STATUS_VSYNC		GENMASK(27, VE_SYNC_STATUS_VSYNC_SHF)
 
+#define VE_H_TOTAL_PIXELS		0x0A0
+
 #define VE_INTERRUPT_CTRL		0x304
 #define VE_INTERRUPT_STATUS		0x308
 #define  VE_INTERRUPT_MODE_DETECT_WD	BIT(0)
@@ -477,6 +479,10 @@
 	aspeed_video_update(video, VE_INTERRUPT_CTRL, 0,
 			    VE_INTERRUPT_MODE_DETECT);
 
+	/* Disable mode detect in order to re-trigger */
+	aspeed_video_update(video, VE_SEQ_CTRL,
+			    VE_SEQ_CTRL_TRIG_MODE_DET, 0);
+
 	/* Trigger mode detect */
 	aspeed_video_update(video, VE_SEQ_CTRL, 0, VE_SEQ_CTRL_TRIG_MODE_DET);
 }
@@ -491,8 +497,8 @@
 	aspeed_video_write(video, VE_INTERRUPT_STATUS, 0xffffffff);
 
 	/* Turn off the relevant clocks */
-	clk_disable(video->vclk);
 	clk_disable(video->eclk);
+	clk_disable(video->vclk);
 
 	clear_bit(VIDEO_CLOCKS_ON, &video->flags);
 }
@@ -503,8 +509,8 @@
 		return;
 
 	/* Turn on the relevant clocks */
-	clk_enable(video->eclk);
 	clk_enable(video->vclk);
+	clk_enable(video->eclk);
 
 	set_bit(VIDEO_CLOCKS_ON, &video->flags);
 }
@@ -529,6 +535,8 @@
 	set_bit(VIDEO_RES_CHANGE, &video->flags);
 	clear_bit(VIDEO_FRAME_INPRG, &video->flags);
 
+	video->v4l2_input_status = V4L2_IN_ST_NO_SIGNAL;
+
 	aspeed_video_off(video);
 	aspeed_video_bufs_done(video, VB2_BUF_STATE_ERROR);
 
@@ -606,6 +614,16 @@
 			aspeed_video_start_frame(video);
 	}
 
+	/*
+	 * CAPTURE_COMPLETE and FRAME_COMPLETE interrupts come even when these
+	 * are disabled in the VE_INTERRUPT_CTRL register so clear them to
+	 * prevent unnecessary interrupt calls.
+	 */
+	if (sts & VE_INTERRUPT_CAPTURE_COMPLETE)
+		sts &= ~VE_INTERRUPT_CAPTURE_COMPLETE;
+	if (sts & VE_INTERRUPT_FRAME_COMPLETE)
+		sts &= ~VE_INTERRUPT_FRAME_COMPLETE;
+
 	return sts ? IRQ_NONE : IRQ_HANDLED;
 }
 
@@ -727,6 +745,7 @@
 	u32 src_lr_edge;
 	u32 src_tb_edge;
 	u32 sync;
+	u32 htotal;
 	struct v4l2_bt_timings *det = &video->detected_timings;
 
 	det->width = MIN_WIDTH;
@@ -741,6 +760,8 @@
 		}
 
 		set_bit(VIDEO_RES_DETECT, &video->flags);
+		aspeed_video_update(video, VE_CTRL,
+				    VE_CTRL_VSYNC_POL | VE_CTRL_HSYNC_POL, 0);
 		aspeed_video_enable_mode_detect(video);
 
 		rc = wait_event_interruptible_timeout(video->wait,
@@ -752,10 +773,6 @@
 			return;
 		}
 
-		/* Disable mode detect in order to re-trigger */
-		aspeed_video_update(video, VE_SEQ_CTRL,
-				    VE_SEQ_CTRL_TRIG_MODE_DET, 0);
-
 		aspeed_video_check_and_set_polarity(video);
 
 		aspeed_video_enable_mode_detect(video);
@@ -773,6 +790,7 @@
 		src_tb_edge = aspeed_video_read(video, VE_SRC_TB_EDGE_DET);
 		mds = aspeed_video_read(video, VE_MODE_DETECT_STATUS);
 		sync = aspeed_video_read(video, VE_SYNC_STATUS);
+		htotal = aspeed_video_read(video, VE_H_TOTAL_PIXELS);
 
 		video->frame_bottom = (src_tb_edge & VE_SRC_TB_EDGE_DET_BOT) >>
 			VE_SRC_TB_EDGE_DET_BOT_SHF;
@@ -789,8 +807,7 @@
 			VE_SRC_LR_EDGE_DET_RT_SHF;
 		video->frame_left = src_lr_edge & VE_SRC_LR_EDGE_DET_LEFT;
 		det->hfrontporch = video->frame_left;
-		det->hbackporch = (mds & VE_MODE_DETECT_H_PIXELS) -
-			video->frame_right;
+		det->hbackporch = htotal - video->frame_right;
 		det->hsync = sync & VE_SYNC_STATUS_HSYNC;
 		if (video->frame_left > video->frame_right)
 			continue;
@@ -1303,7 +1320,6 @@
 	struct delayed_work *dwork = to_delayed_work(work);
 	struct aspeed_video *video = container_of(dwork, struct aspeed_video,
 						  res_work);
-	u32 input_status = video->v4l2_input_status;
 
 	aspeed_video_on(video);
 
@@ -1316,8 +1332,7 @@
 	aspeed_video_get_resolution(video);
 
 	if (video->detected_timings.width != video->active_timings.width ||
-	    video->detected_timings.height != video->active_timings.height ||
-	    input_status != video->v4l2_input_status) {
+	    video->detected_timings.height != video->active_timings.height) {
 		static const struct v4l2_event ev = {
 			.type = V4L2_EVENT_SOURCE_CHANGE,
 			.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
@@ -1517,12 +1532,12 @@
 			       V4L2_JPEG_CHROMA_SUBSAMPLING_420, mask,
 			       V4L2_JPEG_CHROMA_SUBSAMPLING_444);
 
-	if (video->ctrl_handler.error) {
+	rc = video->ctrl_handler.error;
+	if (rc) {
 		v4l2_ctrl_handler_free(&video->ctrl_handler);
 		v4l2_device_unregister(v4l2_dev);
 
-		dev_err(video->dev, "Failed to init controls: %d\n",
-			video->ctrl_handler.error);
+		dev_err(video->dev, "Failed to init controls: %d\n", rc);
 		return rc;
 	}
 
@@ -1646,7 +1661,8 @@
 {
 	int rc;
 	struct resource *res;
-	struct aspeed_video *video = kzalloc(sizeof(*video), GFP_KERNEL);
+	struct aspeed_video *video =
+		devm_kzalloc(&pdev->dev, sizeof(*video), GFP_KERNEL);
 
 	if (!video)
 		return -ENOMEM;
@@ -1671,8 +1687,12 @@
 		return rc;
 
 	rc = aspeed_video_setup_video(video);
-	if (rc)
+	if (rc) {
+		aspeed_video_free_buf(video, &video->jpeg);
+		clk_unprepare(video->vclk);
+		clk_unprepare(video->eclk);
 		return rc;
+	}
 
 	return 0;
 }
@@ -1696,8 +1716,7 @@
 
 	v4l2_device_unregister(v4l2_dev);
 
-	dma_free_coherent(video->dev, VE_JPEG_HEADER_SIZE, video->jpeg.virt,
-			  video->jpeg.dma);
+	aspeed_video_free_buf(video, &video->jpeg);
 
 	of_reserved_mem_device_release(dev);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/cadence/cdns-csi2rx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/cadence/cdns-csi2rx.c
@@ -129,7 +129,7 @@
 	 */
 	for (i = csi2rx->num_lanes; i < csi2rx->max_lanes; i++) {
 		unsigned int idx = find_first_zero_bit(&lanes_used,
-						       sizeof(lanes_used));
+						       csi2rx->max_lanes);
 		set_bit(idx, &lanes_used);
 		reg |= CSI2RX_STATIC_CFG_DLANE_MAP(i, i + 1);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/coda/coda-bit.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/coda/coda-bit.c
@@ -852,7 +852,7 @@
 		/* Only H.264BP and H.263P3 are considered */
 		iram_info->buf_dbk_y_use = coda_iram_alloc(iram_info, w64);
 		iram_info->buf_dbk_c_use = coda_iram_alloc(iram_info, w64);
-		if (!iram_info->buf_dbk_c_use)
+		if (!iram_info->buf_dbk_y_use || !iram_info->buf_dbk_c_use)
 			goto out;
 		iram_info->axi_sram_use |= dbk_bits;
 
@@ -876,7 +876,7 @@
 
 		iram_info->buf_dbk_y_use = coda_iram_alloc(iram_info, w128);
 		iram_info->buf_dbk_c_use = coda_iram_alloc(iram_info, w128);
-		if (!iram_info->buf_dbk_c_use)
+		if (!iram_info->buf_dbk_y_use || !iram_info->buf_dbk_c_use)
 			goto out;
 		iram_info->axi_sram_use |= dbk_bits;
 
@@ -1082,10 +1082,16 @@
 	}
 
 	if (dst_fourcc == V4L2_PIX_FMT_JPEG) {
-		if (!ctx->params.jpeg_qmat_tab[0])
+		if (!ctx->params.jpeg_qmat_tab[0]) {
 			ctx->params.jpeg_qmat_tab[0] = kmalloc(64, GFP_KERNEL);
-		if (!ctx->params.jpeg_qmat_tab[1])
+			if (!ctx->params.jpeg_qmat_tab[0])
+				return -ENOMEM;
+		}
+		if (!ctx->params.jpeg_qmat_tab[1]) {
 			ctx->params.jpeg_qmat_tab[1] = kmalloc(64, GFP_KERNEL);
+			if (!ctx->params.jpeg_qmat_tab[1])
+				return -ENOMEM;
+		}
 		coda_set_jpeg_compression_quality(ctx, ctx->params.jpeg_quality);
 	}
 
@@ -2023,17 +2029,25 @@
 	u32 src_fourcc, dst_fourcc;
 	int ret;
 
+	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+	src_fourcc = q_data_src->fourcc;
+	dst_fourcc = q_data_dst->fourcc;
+
 	if (!ctx->initialized) {
 		ret = __coda_decoder_seq_init(ctx);
 		if (ret < 0)
 			return ret;
+	} else {
+		ctx->frame_mem_ctrl &= ~(CODA_FRAME_CHROMA_INTERLEAVE | (0x3 << 9) |
+					 CODA9_FRAME_TILED2LINEAR);
+		if (dst_fourcc == V4L2_PIX_FMT_NV12 || dst_fourcc == V4L2_PIX_FMT_YUYV)
+			ctx->frame_mem_ctrl |= CODA_FRAME_CHROMA_INTERLEAVE;
+		if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP)
+			ctx->frame_mem_ctrl |= (0x3 << 9) |
+				((ctx->use_vdoa) ? 0 : CODA9_FRAME_TILED2LINEAR);
 	}
 
-	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
-	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-	src_fourcc = q_data_src->fourcc;
-	dst_fourcc = q_data_dst->fourcc;
-
 	coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR);
 
 	ret = coda_alloc_framebuffers(ctx, q_data_dst, src_fourcc);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/coda/coda-common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/coda/coda-common.c
@@ -372,6 +372,7 @@
 	if (!vdoa_data)
 		vdoa_data = ERR_PTR(-EPROBE_DEFER);
 
+	put_device(&vdoa_pdev->dev);
 out:
 	of_node_put(vdoa_node);
 
@@ -1084,16 +1085,16 @@
 
 	switch (dc->cmd) {
 	case V4L2_DEC_CMD_START:
-		mutex_lock(&ctx->bitstream_mutex);
 		mutex_lock(&dev->coda_mutex);
+		mutex_lock(&ctx->bitstream_mutex);
 		coda_bitstream_flush(ctx);
-		mutex_unlock(&dev->coda_mutex);
 		dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
 					 V4L2_BUF_TYPE_VIDEO_CAPTURE);
 		vb2_clear_last_buffer_dequeued(dst_vq);
 		ctx->bit_stream_param &= ~CODA_BIT_STREAM_END_FLAG;
 		coda_fill_bitstream(ctx, NULL);
 		mutex_unlock(&ctx->bitstream_mutex);
+		mutex_unlock(&dev->coda_mutex);
 		break;
 	case V4L2_DEC_CMD_STOP:
 		stream_end = false;
@@ -1191,7 +1192,8 @@
 				    struct v4l2_frmivalenum *f)
 {
 	struct coda_ctx *ctx = fh_to_ctx(fh);
-	int i;
+	struct coda_q_data *q_data;
+	const struct coda_codec *codec;
 
 	if (f->index)
 		return -EINVAL;
@@ -1200,12 +1202,19 @@
 	if (!ctx->vdoa && f->pixel_format == V4L2_PIX_FMT_YUYV)
 		return -EINVAL;
 
-	for (i = 0; i < CODA_MAX_FORMATS; i++) {
-		if (f->pixel_format == ctx->cvd->src_formats[i] ||
-		    f->pixel_format == ctx->cvd->dst_formats[i])
-			break;
+	if (coda_format_normalize_yuv(f->pixel_format) == V4L2_PIX_FMT_YUV420) {
+		q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+		codec = coda_find_codec(ctx->dev, f->pixel_format,
+					q_data->fourcc);
+	} else {
+		codec = coda_find_codec(ctx->dev, V4L2_PIX_FMT_YUV420,
+					f->pixel_format);
 	}
-	if (i == CODA_MAX_FORMATS)
+	if (!codec)
+		return -EINVAL;
+
+	if (f->width < MIN_W || f->width > codec->max_w ||
+	    f->height < MIN_H || f->height > codec->max_h)
 		return -EINVAL;
 
 	f->type = V4L2_FRMIVAL_TYPE_CONTINUOUS;
@@ -2163,8 +2172,8 @@
 		V4L2_CID_MPEG_VIDEO_H264_CHROMA_QP_INDEX_OFFSET, -12, 12, 1, 0);
 	v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
 		V4L2_CID_MPEG_VIDEO_H264_PROFILE,
-		V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE, 0x0,
-		V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE);
+		V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE, 0x0,
+		V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE);
 	if (ctx->dev->devtype->product == CODA_HX4 ||
 	    ctx->dev->devtype->product == CODA_7541) {
 		v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
@@ -2178,12 +2187,15 @@
 	if (ctx->dev->devtype->product == CODA_960) {
 		v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
 			V4L2_CID_MPEG_VIDEO_H264_LEVEL,
-			V4L2_MPEG_VIDEO_H264_LEVEL_4_0,
-			~((1 << V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
+			V4L2_MPEG_VIDEO_H264_LEVEL_4_2,
+			~((1 << V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
+			  (1 << V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
 			  (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
 			  (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
 			  (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
-			  (1 << V4L2_MPEG_VIDEO_H264_LEVEL_4_0)),
+			  (1 << V4L2_MPEG_VIDEO_H264_LEVEL_4_0) |
+			  (1 << V4L2_MPEG_VIDEO_H264_LEVEL_4_1) |
+			  (1 << V4L2_MPEG_VIDEO_H264_LEVEL_4_2)),
 			V4L2_MPEG_VIDEO_H264_LEVEL_4_0);
 	}
 	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
@@ -2245,7 +2257,7 @@
 	ctx->h264_profile_ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrls,
 		&coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_H264_PROFILE,
 		V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
-		~((1 << V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) |
+		~((1 << V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
 		  (1 << V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
 		  (1 << V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)),
 		V4L2_MPEG_VIDEO_H264_PROFILE_HIGH);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/coda/imx-vdoa.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/coda/imx-vdoa.c
@@ -287,7 +287,11 @@
 	struct resource *res;
 	int ret;
 
-	dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+	ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+	if (ret) {
+		dev_err(&pdev->dev, "DMA enable failed\n");
+		return ret;
+	}
 
 	vdoa = devm_kzalloc(&pdev->dev, sizeof(*vdoa), GFP_KERNEL);
 	if (!vdoa)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/cros-ec-cec/cros-ec-cec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/cros-ec-cec/cros-ec-cec.c
@@ -45,6 +45,8 @@
 	uint8_t *cec_message = cros_ec->event_data.data.cec_message;
 	unsigned int len = cros_ec->event_size;
 
+	if (len > CEC_MAX_MSG_SIZE)
+		len = CEC_MAX_MSG_SIZE;
 	cros_ec_cec->rx_msg.len = len;
 	memcpy(cros_ec_cec->rx_msg.msg, cec_message, len);
 
@@ -278,11 +280,7 @@
 	platform_set_drvdata(pdev, cros_ec_cec);
 	cros_ec_cec->cros_ec = cros_ec;
 
-	ret = device_init_wakeup(&pdev->dev, 1);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to initialize wakeup\n");
-		return ret;
-	}
+	device_init_wakeup(&pdev->dev, 1);
 
 	cros_ec_cec->adap = cec_allocate_adapter(&cros_ec_cec_ops, cros_ec_cec,
 						 DRV_NAME,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/davinci/vpbe_display.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/davinci/vpbe_display.c
@@ -48,7 +48,7 @@
 
 	ret = v4l2_subdev_call(vpbe_dev->venc,
 			       core,
-			       ioctl,
+			       command,
 			       VENC_GET_FLD,
 			       &val);
 	if (ret < 0) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/davinci/vpbe_venc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/davinci/vpbe_venc.c
@@ -521,9 +521,7 @@
 	return ret;
 }
 
-static long venc_ioctl(struct v4l2_subdev *sd,
-			unsigned int cmd,
-			void *arg)
+static long venc_command(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
 {
 	u32 val;
 
@@ -542,7 +540,7 @@
 }
 
 static const struct v4l2_subdev_core_ops venc_core_ops = {
-	.ioctl      = venc_ioctl,
+	.command      = venc_command,
 };
 
 static const struct v4l2_subdev_video_ops venc_video_ops = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/davinci/vpif.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/davinci/vpif.c
@@ -496,6 +496,7 @@
 
 static int vpif_remove(struct platform_device *pdev)
 {
+	pm_runtime_put(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/davinci/vpif_capture.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/davinci/vpif_capture.c
@@ -1482,8 +1482,6 @@
 		/* Unregister video device */
 		video_unregister_device(&ch->video_dev);
 	}
-	kfree(vpif_obj.sd);
-	v4l2_device_unregister(&vpif_obj.v4l2_dev);
 
 	return err;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/davinci/vpss.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/davinci/vpss.c
@@ -505,19 +505,31 @@
 
 static int __init vpss_init(void)
 {
+	int ret;
+
 	if (!request_mem_region(VPSS_CLK_CTRL, 4, "vpss_clock_control"))
 		return -EBUSY;
 
 	oper_cfg.vpss_regs_base2 = ioremap(VPSS_CLK_CTRL, 4);
 	if (unlikely(!oper_cfg.vpss_regs_base2)) {
-		release_mem_region(VPSS_CLK_CTRL, 4);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto err_ioremap;
 	}
 
 	writel(VPSS_CLK_CTRL_VENCCLKEN |
-		     VPSS_CLK_CTRL_DACCLKEN, oper_cfg.vpss_regs_base2);
+	       VPSS_CLK_CTRL_DACCLKEN, oper_cfg.vpss_regs_base2);
+
+	ret = platform_driver_register(&vpss_driver);
+	if (ret)
+		goto err_pd_register;
+
+	return 0;
 
-	return platform_driver_register(&vpss_driver);
+err_pd_register:
+	iounmap(oper_cfg.vpss_regs_base2);
+err_ioremap:
+	release_mem_region(VPSS_CLK_CTRL, 4);
+	return ret;
 }
 subsys_initcall(vpss_init);
 module_exit(vpss_exit);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/exynos-gsc/gsc-m2m.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/exynos-gsc/gsc-m2m.c
@@ -56,10 +56,8 @@
 static int gsc_m2m_start_streaming(struct vb2_queue *q, unsigned int count)
 {
 	struct gsc_ctx *ctx = q->drv_priv;
-	int ret;
 
-	ret = pm_runtime_get_sync(&ctx->gsc_dev->pdev->dev);
-	return ret > 0 ? 0 : ret;
+	return pm_runtime_resume_and_get(&ctx->gsc_dev->pdev->dev);
 }
 
 static void __gsc_m2m_cleanup_queue(struct gsc_ctx *ctx)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/exynos4-is/fimc-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/exynos4-is/fimc-core.c
@@ -1231,7 +1231,7 @@
 	return platform_driver_register(&fimc_driver);
 }
 
-void __exit fimc_unregister_driver(void)
+void fimc_unregister_driver(void)
 {
 	platform_driver_unregister(&fimc_driver);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/exynos4-is/fimc-is.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/exynos4-is/fimc-is.c
@@ -141,7 +141,7 @@
 			dev_err(&is->pdev->dev, "clock %s enable failed\n",
 				fimc_is_clocks[i]);
 			for (--i; i >= 0; i--)
-				clk_disable(is->clocks[i]);
+				clk_disable_unprepare(is->clocks[i]);
 			return ret;
 		}
 		pr_debug("enabled clock: %s\n", fimc_is_clocks[i]);
@@ -214,6 +214,7 @@
 
 			if (ret < 0 || index >= FIMC_IS_SENSORS_NUM) {
 				of_node_put(child);
+				of_node_put(i2c_bus);
 				return ret;
 			}
 			index++;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/exynos4-is/fimc-isp-video.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/exynos4-is/fimc-isp-video.c
@@ -305,17 +305,20 @@
 	struct fimc_is_video *ivc = &isp->video_capture;
 	struct media_entity *entity = &ivc->ve.vdev.entity;
 	struct media_device *mdev = entity->graph_obj.mdev;
+	bool is_singular_file;
 
 	mutex_lock(&isp->video_lock);
 
-	if (v4l2_fh_is_singular_file(file) && ivc->streaming) {
+	is_singular_file = v4l2_fh_is_singular_file(file);
+
+	if (is_singular_file && ivc->streaming) {
 		media_pipeline_stop(entity);
 		ivc->streaming = 0;
 	}
 
-	vb2_fop_release(file);
+	_vb2_fop_release(file, NULL);
 
-	if (v4l2_fh_is_singular_file(file)) {
+	if (is_singular_file) {
 		fimc_pipeline_call(&ivc->ve, close);
 
 		mutex_lock(&mdev->graph_mutex);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/exynos4-is/fimc-isp-video.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/exynos4-is/fimc-isp-video.h
@@ -32,7 +32,7 @@
 	return 0;
 }
 
-void fimc_isp_video_device_unregister(struct fimc_isp *isp,
+static inline void fimc_isp_video_device_unregister(struct fimc_isp *isp,
 				enum v4l2_buf_type type)
 {
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/exynos4-is/fimc-isp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/exynos4-is/fimc-isp.c
@@ -305,8 +305,10 @@
 
 	if (on) {
 		ret = pm_runtime_get_sync(&is->pdev->dev);
-		if (ret < 0)
+		if (ret < 0) {
+			pm_runtime_put(&is->pdev->dev);
 			return ret;
+		}
 		set_bit(IS_ST_PWR_ON, &is->state);
 
 		ret = fimc_is_start_firmware(is);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/exynos4-is/fimc-lite.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/exynos4-is/fimc-lite.c
@@ -470,7 +470,7 @@
 	set_bit(ST_FLITE_IN_USE, &fimc->state);
 	ret = pm_runtime_get_sync(&fimc->pdev->dev);
 	if (ret < 0)
-		goto unlock;
+		goto err_pm;
 
 	ret = v4l2_fh_open(file);
 	if (ret < 0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/exynos4-is/media-dev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/exynos4-is/media-dev.c
@@ -484,8 +484,10 @@
 		return -ENXIO;
 
 	ret = pm_runtime_get_sync(fmd->pmf);
-	if (ret < 0)
+	if (ret < 0) {
+		pm_runtime_put(fmd->pmf);
 		return ret;
+	}
 
 	fmd->num_sensors = 0;
 
@@ -1268,6 +1270,7 @@
 	if (IS_ERR(pctl->state_default))
 		return PTR_ERR(pctl->state_default);
 
+	/* PINCTRL_STATE_IDLE is optional */
 	pctl->state_idle = pinctrl_lookup_state(pctl->pinctrl,
 					PINCTRL_STATE_IDLE);
 	return 0;
@@ -1457,12 +1460,12 @@
 	ret = v4l2_device_register(dev, &fmd->v4l2_dev);
 	if (ret < 0) {
 		v4l2_err(v4l2_dev, "Failed to register v4l2_device: %d\n", ret);
-		return ret;
+		goto err_md;
 	}
 
 	ret = fimc_md_get_clocks(fmd);
 	if (ret)
-		goto err_md;
+		goto err_v4l2dev;
 
 	ret = fimc_md_get_pinctrl(fmd);
 	if (ret < 0) {
@@ -1519,9 +1522,10 @@
 	fimc_md_unregister_entities(fmd);
 err_clk:
 	fimc_md_put_clocks(fmd);
+err_v4l2dev:
+	v4l2_device_unregister(&fmd->v4l2_dev);
 err_md:
 	media_device_cleanup(&fmd->media_dev);
-	v4l2_device_unregister(&fmd->v4l2_dev);
 	return ret;
 }
 
@@ -1577,7 +1581,11 @@
 	if (ret)
 		return ret;
 
-	return platform_driver_register(&fimc_md_driver);
+	ret = platform_driver_register(&fimc_md_driver);
+	if (ret)
+		fimc_unregister_driver();
+
+	return ret;
 }
 
 static void __exit fimc_md_exit(void)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/exynos4-is/mipi-csis.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/exynos4-is/mipi-csis.c
@@ -510,8 +510,10 @@
 	if (enable) {
 		s5pcsis_clear_counters(state);
 		ret = pm_runtime_get_sync(&state->pdev->dev);
-		if (ret && ret != 1)
+		if (ret && ret != 1) {
+			pm_runtime_put_noidle(&state->pdev->dev);
 			return ret;
+		}
 	}
 
 	mutex_lock(&state->lock);
@@ -939,13 +941,19 @@
 					       state->supplies);
 			goto unlock;
 		}
-		clk_enable(state->clock[CSIS_CLK_GATE]);
+		ret = clk_enable(state->clock[CSIS_CLK_GATE]);
+		if (ret) {
+			phy_power_off(state->phy);
+			regulator_bulk_disable(CSIS_NUM_SUPPLIES,
+					       state->supplies);
+			goto unlock;
+		}
 	}
 	if (state->flags & ST_STREAMING)
 		s5pcsis_start_stream(state);
 
 	state->flags &= ~ST_SUSPENDED;
- unlock:
+unlock:
 	mutex_unlock(&state->lock);
 	return ret ? -EAGAIN : 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/imx-pxp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/imx-pxp.c
@@ -1664,6 +1664,8 @@
 	if (irq < 0)
 		return irq;
 
+	spin_lock_init(&dev->irqlock);
+
 	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, pxp_irq_handler,
 			IRQF_ONESHOT, dev_name(&pdev->dev), dev);
 	if (ret < 0) {
@@ -1681,8 +1683,6 @@
 		goto err_clk;
 	}
 
-	spin_lock_init(&dev->irqlock);
-
 	ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
 	if (ret)
 		goto err_clk;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/marvell-ccic/mcam-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/marvell-ccic/mcam-core.c
@@ -1940,6 +1940,7 @@
 out:
 	v4l2_async_notifier_unregister(&cam->notifier);
 	v4l2_device_unregister(&cam->v4l2_dev);
+	v4l2_async_notifier_cleanup(&cam->notifier);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(mccic_register);
@@ -1961,6 +1962,7 @@
 	v4l2_ctrl_handler_free(&cam->ctrl_handler);
 	v4l2_async_notifier_unregister(&cam->notifier);
 	v4l2_device_unregister(&cam->v4l2_dev);
+	v4l2_async_notifier_cleanup(&cam->notifier);
 }
 EXPORT_SYMBOL_GPL(mccic_shutdown);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/meson/ao-cec-g12a.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/meson/ao-cec-g12a.c
@@ -662,34 +662,27 @@
 	if (IS_ERR(ao_cec->adap))
 		return PTR_ERR(ao_cec->adap);
 
-	ao_cec->notify = cec_notifier_cec_adap_register(hdmi_dev, NULL,
-							ao_cec->adap);
-	if (!ao_cec->notify) {
-		ret = -ENOMEM;
-		goto out_probe_adapter;
-	}
-
 	ao_cec->adap->owner = THIS_MODULE;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	base = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(base)) {
 		ret = PTR_ERR(base);
-		goto out_probe_notify;
+		goto out_probe_adapter;
 	}
 
 	ao_cec->regmap = devm_regmap_init_mmio(&pdev->dev, base,
 					       &meson_ao_cec_g12a_regmap_conf);
 	if (IS_ERR(ao_cec->regmap)) {
 		ret = PTR_ERR(ao_cec->regmap);
-		goto out_probe_notify;
+		goto out_probe_adapter;
 	}
 
 	ao_cec->regmap_cec = devm_regmap_init(&pdev->dev, NULL, ao_cec,
 					   &meson_ao_cec_g12a_cec_regmap_conf);
 	if (IS_ERR(ao_cec->regmap_cec)) {
 		ret = PTR_ERR(ao_cec->regmap_cec);
-		goto out_probe_notify;
+		goto out_probe_adapter;
 	}
 
 	irq = platform_get_irq(pdev, 0);
@@ -699,45 +692,52 @@
 					0, NULL, ao_cec);
 	if (ret) {
 		dev_err(&pdev->dev, "irq request failed\n");
-		goto out_probe_notify;
+		goto out_probe_adapter;
 	}
 
 	ao_cec->oscin = devm_clk_get(&pdev->dev, "oscin");
 	if (IS_ERR(ao_cec->oscin)) {
 		dev_err(&pdev->dev, "oscin clock request failed\n");
 		ret = PTR_ERR(ao_cec->oscin);
-		goto out_probe_notify;
+		goto out_probe_adapter;
 	}
 
 	ret = meson_ao_cec_g12a_setup_clk(ao_cec);
 	if (ret)
-		goto out_probe_notify;
+		goto out_probe_adapter;
 
 	ret = clk_prepare_enable(ao_cec->core);
 	if (ret) {
 		dev_err(&pdev->dev, "core clock enable failed\n");
-		goto out_probe_notify;
+		goto out_probe_adapter;
 	}
 
 	device_reset_optional(&pdev->dev);
 
 	platform_set_drvdata(pdev, ao_cec);
 
+	ao_cec->notify = cec_notifier_cec_adap_register(hdmi_dev, NULL,
+							ao_cec->adap);
+	if (!ao_cec->notify) {
+		ret = -ENOMEM;
+		goto out_probe_core_clk;
+	}
+
 	ret = cec_register_adapter(ao_cec->adap, &pdev->dev);
 	if (ret < 0)
-		goto out_probe_core_clk;
+		goto out_probe_notify;
 
 	/* Setup Hardware */
 	regmap_write(ao_cec->regmap, CECB_GEN_CNTL_REG, CECB_GEN_CNTL_RESET);
 
 	return 0;
 
-out_probe_core_clk:
-	clk_disable_unprepare(ao_cec->core);
-
 out_probe_notify:
 	cec_notifier_cec_adap_unregister(ao_cec->notify);
 
+out_probe_core_clk:
+	clk_disable_unprepare(ao_cec->core);
+
 out_probe_adapter:
 	cec_delete_adapter(ao_cec->adap);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/meson/ao-cec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/meson/ao-cec.c
@@ -624,20 +624,13 @@
 	if (IS_ERR(ao_cec->adap))
 		return PTR_ERR(ao_cec->adap);
 
-	ao_cec->notify = cec_notifier_cec_adap_register(hdmi_dev, NULL,
-							ao_cec->adap);
-	if (!ao_cec->notify) {
-		ret = -ENOMEM;
-		goto out_probe_adapter;
-	}
-
 	ao_cec->adap->owner = THIS_MODULE;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	ao_cec->base = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(ao_cec->base)) {
 		ret = PTR_ERR(ao_cec->base);
-		goto out_probe_notify;
+		goto out_probe_adapter;
 	}
 
 	irq = platform_get_irq(pdev, 0);
@@ -647,20 +640,20 @@
 					0, NULL, ao_cec);
 	if (ret) {
 		dev_err(&pdev->dev, "irq request failed\n");
-		goto out_probe_notify;
+		goto out_probe_adapter;
 	}
 
 	ao_cec->core = devm_clk_get(&pdev->dev, "core");
 	if (IS_ERR(ao_cec->core)) {
 		dev_err(&pdev->dev, "core clock request failed\n");
 		ret = PTR_ERR(ao_cec->core);
-		goto out_probe_notify;
+		goto out_probe_adapter;
 	}
 
 	ret = clk_prepare_enable(ao_cec->core);
 	if (ret) {
 		dev_err(&pdev->dev, "core clock enable failed\n");
-		goto out_probe_notify;
+		goto out_probe_adapter;
 	}
 
 	ret = clk_set_rate(ao_cec->core, CEC_CLK_RATE);
@@ -674,9 +667,16 @@
 	ao_cec->pdev = pdev;
 	platform_set_drvdata(pdev, ao_cec);
 
+	ao_cec->notify = cec_notifier_cec_adap_register(hdmi_dev, NULL,
+							ao_cec->adap);
+	if (!ao_cec->notify) {
+		ret = -ENOMEM;
+		goto out_probe_clk;
+	}
+
 	ret = cec_register_adapter(ao_cec->adap, &pdev->dev);
 	if (ret < 0)
-		goto out_probe_clk;
+		goto out_probe_notify;
 
 	/* Setup Hardware */
 	writel_relaxed(CEC_GEN_CNTL_RESET,
@@ -684,12 +684,12 @@
 
 	return 0;
 
-out_probe_clk:
-	clk_disable_unprepare(ao_cec->core);
-
 out_probe_notify:
 	cec_notifier_cec_adap_unregister(ao_cec->notify);
 
+out_probe_clk:
+	clk_disable_unprepare(ao_cec->core);
+
 out_probe_adapter:
 	cec_delete_adapter(ao_cec->adap);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
@@ -571,6 +571,13 @@
 	if (!q_data)
 		return -EINVAL;
 
+	if (*num_planes) {
+		for (i = 0; i < *num_planes; i++)
+			if (sizes[i] < q_data->sizeimage[i])
+				return -EINVAL;
+		return 0;
+	}
+
 	*num_planes = q_data->fmt->colplanes;
 	for (i = 0; i < q_data->fmt->colplanes; i++) {
 		sizes[i] = q_data->sizeimage[i];
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/mtk-mdp/mtk_mdp_ipi.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/mtk-mdp/mtk_mdp_ipi.h
@@ -40,12 +40,14 @@
  * @ipi_id        : IPI_MDP
  * @ap_inst       : AP mtk_mdp_vpu address
  * @vpu_inst_addr : VPU MDP instance address
+ * @padding       : Alignment padding
  */
 struct mdp_ipi_comm {
 	uint32_t msg_id;
 	uint32_t ipi_id;
 	uint64_t ap_inst;
 	uint32_t vpu_inst_addr;
+	uint32_t padding;
 };
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c
@@ -402,12 +402,12 @@
 	struct mtk_mdp_ctx *ctx = q->drv_priv;
 	int ret;
 
-	ret = pm_runtime_get_sync(&ctx->mdp_dev->pdev->dev);
+	ret = pm_runtime_resume_and_get(&ctx->mdp_dev->pdev->dev);
 	if (ret < 0)
-		mtk_mdp_dbg(1, "[%d] pm_runtime_get_sync failed:%d",
+		mtk_mdp_dbg(1, "[%d] pm_runtime_resume_and_get failed:%d",
 			    ctx->id, ret);
 
-	return 0;
+	return ret;
 }
 
 static void *mtk_mdp_m2m_buf_remove(struct mtk_mdp_ctx *ctx,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
@@ -142,7 +142,9 @@
 	mtk_vcodec_dec_set_default_params(ctx);
 
 	if (v4l2_fh_is_singular(&ctx->fh)) {
-		mtk_vcodec_dec_pw_on(&dev->pm);
+		ret = mtk_vcodec_dec_pw_on(&dev->pm);
+		if (ret < 0)
+			goto err_load_fw;
 		/*
 		 * vpu_load_firmware checks if it was loaded already and
 		 * does nothing in that case
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c
@@ -48,11 +48,14 @@
 		dec_clk->clk_info = devm_kcalloc(&pdev->dev,
 			dec_clk->clk_num, sizeof(*clk_info),
 			GFP_KERNEL);
-		if (!dec_clk->clk_info)
-			return -ENOMEM;
+		if (!dec_clk->clk_info) {
+			ret = -ENOMEM;
+			goto put_device;
+		}
 	} else {
 		mtk_v4l2_err("Failed to get vdec clock count");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto put_device;
 	}
 
 	for (i = 0; i < dec_clk->clk_num; i++) {
@@ -61,34 +64,40 @@
 			"clock-names", i, &clk_info->clk_name);
 		if (ret) {
 			mtk_v4l2_err("Failed to get clock name id = %d", i);
-			return ret;
+			goto put_device;
 		}
 		clk_info->vcodec_clk = devm_clk_get(&pdev->dev,
 			clk_info->clk_name);
 		if (IS_ERR(clk_info->vcodec_clk)) {
 			mtk_v4l2_err("devm_clk_get (%d)%s fail", i,
 				clk_info->clk_name);
-			return PTR_ERR(clk_info->vcodec_clk);
+			ret = PTR_ERR(clk_info->vcodec_clk);
+			goto put_device;
 		}
 	}
 
 	pm_runtime_enable(&pdev->dev);
-
+	return 0;
+put_device:
+	put_device(pm->larbvdec);
 	return ret;
 }
 
 void mtk_vcodec_release_dec_pm(struct mtk_vcodec_dev *dev)
 {
 	pm_runtime_disable(dev->pm.dev);
+	put_device(dev->pm.larbvdec);
 }
 
-void mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm)
+int mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm)
 {
 	int ret;
 
-	ret = pm_runtime_get_sync(pm->dev);
+	ret = pm_runtime_resume_and_get(pm->dev);
 	if (ret)
-		mtk_v4l2_err("pm_runtime_get_sync fail %d", ret);
+		mtk_v4l2_err("pm_runtime_resume_and_get fail %d", ret);
+
+	return ret;
 }
 
 void mtk_vcodec_dec_pw_off(struct mtk_vcodec_pm *pm)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h
@@ -12,7 +12,7 @@
 int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *dev);
 void mtk_vcodec_release_dec_pm(struct mtk_vcodec_dev *dev);
 
-void mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm);
+int mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm);
 void mtk_vcodec_dec_pw_off(struct mtk_vcodec_pm *pm);
 void mtk_vcodec_dec_clock_on(struct mtk_vcodec_pm *pm);
 void mtk_vcodec_dec_clock_off(struct mtk_vcodec_pm *pm);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
@@ -759,6 +759,8 @@
 		return -EINVAL;
 
 	if (*nplanes) {
+		if (*nplanes != q_data->fmt->num_planes)
+			return -EINVAL;
 		for (i = 0; i < *nplanes; i++)
 			if (sizes[i] < q_data->sizeimage[i])
 				return -EINVAL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
@@ -209,11 +209,11 @@
 	mtk_v4l2_debug(1, "[%d] encoder", ctx->id);
 	mutex_lock(&dev->dev_mutex);
 
+	v4l2_m2m_ctx_release(ctx->m2m_ctx);
 	mtk_vcodec_enc_release(ctx);
 	v4l2_fh_del(&ctx->fh);
 	v4l2_fh_exit(&ctx->fh);
 	v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
-	v4l2_m2m_ctx_release(ctx->m2m_ctx);
 
 	list_del_init(&ctx->list);
 	kfree(ctx);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_pm.c
@@ -49,14 +49,16 @@
 	node = of_parse_phandle(dev->of_node, "mediatek,larb", 1);
 	if (!node) {
 		mtk_v4l2_err("no mediatek,larb found");
-		return -ENODEV;
+		ret = -ENODEV;
+		goto put_larbvenc;
 	}
 
 	pdev = of_find_device_by_node(node);
 	of_node_put(node);
 	if (!pdev) {
 		mtk_v4l2_err("no mediatek,larb device found");
-		return -ENODEV;
+		ret = -ENODEV;
+		goto put_larbvenc;
 	}
 
 	pm->larbvenclt = &pdev->dev;
@@ -69,11 +71,14 @@
 		enc_clk->clk_info = devm_kcalloc(&pdev->dev,
 			enc_clk->clk_num, sizeof(*clk_info),
 			GFP_KERNEL);
-		if (!enc_clk->clk_info)
-			return -ENOMEM;
+		if (!enc_clk->clk_info) {
+			ret = -ENOMEM;
+			goto put_larbvenclt;
+		}
 	} else {
 		mtk_v4l2_err("Failed to get venc clock count");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto put_larbvenclt;
 	}
 
 	for (i = 0; i < enc_clk->clk_num; i++) {
@@ -82,17 +87,24 @@
 			"clock-names", i, &clk_info->clk_name);
 		if (ret) {
 			mtk_v4l2_err("venc failed to get clk name %d", i);
-			return ret;
+			goto put_larbvenclt;
 		}
 		clk_info->vcodec_clk = devm_clk_get(&pdev->dev,
 			clk_info->clk_name);
 		if (IS_ERR(clk_info->vcodec_clk)) {
 			mtk_v4l2_err("venc devm_clk_get (%d)%s fail", i,
 				clk_info->clk_name);
-			return PTR_ERR(clk_info->vcodec_clk);
+			ret = PTR_ERR(clk_info->vcodec_clk);
+			goto put_larbvenclt;
 		}
 	}
 
+	return 0;
+
+put_larbvenclt:
+	put_device(pm->larbvenclt);
+put_larbvenc:
+	put_device(pm->larbvenc);
 	return ret;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/mtk-vcodec/vdec/vdec_vp9_if.c
@@ -222,10 +222,11 @@
 		if (fb->base_y.va == addr) {
 			list_move_tail(&node->list,
 				       &inst->available_fb_node_list);
-			break;
+			return fb;
 		}
 	}
-	return fb;
+
+	return NULL;
 }
 
 static void vp9_add_to_fb_free_list(struct vdec_vp9_inst *inst,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/mtk-vpu/mtk_vpu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/mtk-vpu/mtk_vpu.c
@@ -529,15 +529,17 @@
 int vpu_load_firmware(struct platform_device *pdev)
 {
 	struct mtk_vpu *vpu;
-	struct device *dev = &pdev->dev;
+	struct device *dev;
 	struct vpu_run *run;
 	int ret;
 
 	if (!pdev) {
-		dev_err(dev, "VPU platform device is invalid\n");
+		pr_err("VPU platform device is invalid\n");
 		return -EINVAL;
 	}
 
+	dev = &pdev->dev;
+
 	vpu = platform_get_drvdata(pdev);
 	run = &vpu->run;
 
@@ -809,7 +811,8 @@
 	vpu->wdt.wq = create_singlethread_workqueue("vpu_wdt");
 	if (!vpu->wdt.wq) {
 		dev_err(dev, "initialize wdt workqueue failed\n");
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto clk_unprepare;
 	}
 	INIT_WORK(&vpu->wdt.ws, vpu_wdt_reset_func);
 	mutex_init(&vpu->vpu_mutex);
@@ -908,6 +911,8 @@
 	vpu_clock_disable(vpu);
 workqueue_destroy:
 	destroy_workqueue(vpu->wdt.wq);
+clk_unprepare:
+	clk_unprepare(vpu->clk);
 
 	return ret;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/mx2_emmaprp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/mx2_emmaprp.c
@@ -852,8 +852,11 @@
 	platform_set_drvdata(pdev, pcdev);
 
 	irq = platform_get_irq(pdev, 0);
-	if (irq < 0)
-		return irq;
+	if (irq < 0) {
+		ret = irq;
+		goto rel_vdev;
+	}
+
 	ret = devm_request_irq(&pdev->dev, irq, emmaprp_irq, 0,
 			       dev_name(&pdev->dev), pcdev);
 	if (ret)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/omap3isp/isp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/omap3isp/isp.c
@@ -2312,7 +2312,16 @@
 
 	/* Regulators */
 	isp->isp_csiphy1.vdd = devm_regulator_get(&pdev->dev, "vdd-csiphy1");
+	if (IS_ERR(isp->isp_csiphy1.vdd)) {
+		ret = PTR_ERR(isp->isp_csiphy1.vdd);
+		goto error;
+	}
+
 	isp->isp_csiphy2.vdd = devm_regulator_get(&pdev->dev, "vdd-csiphy2");
+	if (IS_ERR(isp->isp_csiphy2.vdd)) {
+		ret = PTR_ERR(isp->isp_csiphy2.vdd);
+		goto error;
+	}
 
 	/* Clocks
 	 *
@@ -2330,8 +2339,10 @@
 		mem = platform_get_resource(pdev, IORESOURCE_MEM, i);
 		isp->mmio_base[map_idx] =
 			devm_ioremap_resource(isp->dev, mem);
-		if (IS_ERR(isp->mmio_base[map_idx]))
-			return PTR_ERR(isp->mmio_base[map_idx]);
+		if (IS_ERR(isp->mmio_base[map_idx])) {
+			ret = PTR_ERR(isp->mmio_base[map_idx]);
+			goto error;
+		}
 	}
 
 	ret = isp_get_clocks(isp);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/omap3isp/isppreview.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/omap3isp/isppreview.c
@@ -2287,7 +2287,7 @@
 	me->ops = &preview_media_ops;
 	ret = media_entity_pads_init(me, PREV_PADS_NUM, pads);
 	if (ret < 0)
-		return ret;
+		goto error_handler_free;
 
 	preview_init_formats(sd, NULL);
 
@@ -2320,6 +2320,8 @@
 	omap3isp_video_cleanup(&prev->video_in);
 error_video_in:
 	media_entity_cleanup(&prev->subdev.entity);
+error_handler_free:
+	v4l2_ctrl_handler_free(&prev->ctrls);
 	return ret;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/pxa_camera.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/pxa_camera.c
@@ -1447,6 +1447,9 @@
 	struct pxa_camera_dev *pcdev = vb2_get_drv_priv(vb->vb2_queue);
 	struct pxa_buffer *buf = vb2_to_pxa_buffer(vb);
 	int ret = 0;
+#ifdef DEBUG
+	int i;
+#endif
 
 	switch (pcdev->channels) {
 	case 1:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/qcom/camss/camss-csiphy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/qcom/camss/camss-csiphy.c
@@ -176,8 +176,10 @@
 		int ret;
 
 		ret = pm_runtime_get_sync(dev);
-		if (ret < 0)
+		if (ret < 0) {
+			pm_runtime_put_sync(dev);
 			return ret;
+		}
 
 		ret = csiphy_set_clock_rates(csiphy);
 		if (ret < 0) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/qcom/camss/camss-video.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/qcom/camss/camss-video.c
@@ -438,7 +438,7 @@
 
 	ret = media_pipeline_start(&vdev->entity, &video->pipe);
 	if (ret < 0)
-		return ret;
+		goto flush_buffers;
 
 	ret = video_check_format(video);
 	if (ret < 0)
@@ -467,6 +467,7 @@
 error:
 	media_pipeline_stop(&vdev->entity);
 
+flush_buffers:
 	video->ops->flush_buffers(video, VB2_BUF_STATE_QUEUED);
 
 	return ret;
@@ -901,6 +902,7 @@
 			video->nformats = ARRAY_SIZE(formats_rdi_8x96);
 		}
 	} else {
+		ret = -EINVAL;
 		goto error_video_register;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/qcom/camss/camss.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/qcom/camss/camss.c
@@ -431,8 +431,11 @@
 	struct v4l2_fwnode_bus_mipi_csi2 *mipi_csi2;
 	struct v4l2_fwnode_endpoint vep = { { 0 } };
 	unsigned int i;
+	int ret;
 
-	v4l2_fwnode_endpoint_parse(of_fwnode_handle(node), &vep);
+	ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(node), &vep);
+	if (ret)
+		return ret;
 
 	csd->interface.csiphy_id = vep.base.port;
 
@@ -504,7 +507,6 @@
 	return num_subdevs;
 
 err_cleanup:
-	v4l2_async_notifier_cleanup(&camss->notifier);
 	of_node_put(node);
 	return ret;
 }
@@ -835,29 +837,38 @@
 		camss->csid_num = 4;
 		camss->vfe_num = 2;
 	} else {
-		return -EINVAL;
+		ret = -EINVAL;
+		goto err_free;
 	}
 
 	camss->csiphy = devm_kcalloc(dev, camss->csiphy_num,
 				     sizeof(*camss->csiphy), GFP_KERNEL);
-	if (!camss->csiphy)
-		return -ENOMEM;
+	if (!camss->csiphy) {
+		ret = -ENOMEM;
+		goto err_free;
+	}
 
 	camss->csid = devm_kcalloc(dev, camss->csid_num, sizeof(*camss->csid),
 				   GFP_KERNEL);
-	if (!camss->csid)
-		return -ENOMEM;
+	if (!camss->csid) {
+		ret = -ENOMEM;
+		goto err_free;
+	}
 
 	camss->vfe = devm_kcalloc(dev, camss->vfe_num, sizeof(*camss->vfe),
 				  GFP_KERNEL);
-	if (!camss->vfe)
-		return -ENOMEM;
+	if (!camss->vfe) {
+		ret = -ENOMEM;
+		goto err_free;
+	}
 
 	v4l2_async_notifier_init(&camss->notifier);
 
 	num_subdevs = camss_of_parse_ports(camss);
-	if (num_subdevs < 0)
-		return num_subdevs;
+	if (num_subdevs < 0) {
+		ret = num_subdevs;
+		goto err_cleanup;
+	}
 
 	ret = camss_init_subdevices(camss);
 	if (ret < 0)
@@ -936,6 +947,8 @@
 	v4l2_device_unregister(&camss->v4l2_dev);
 err_cleanup:
 	v4l2_async_notifier_cleanup(&camss->notifier);
+err_free:
+	kfree(camss);
 
 	return ret;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/qcom/venus/core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/qcom/venus/core.c
@@ -289,11 +289,11 @@
 
 	ret = venus_firmware_init(core);
 	if (ret)
-		goto err_runtime_disable;
+		goto err_of_depopulate;
 
 	ret = venus_boot(core);
 	if (ret)
-		goto err_runtime_disable;
+		goto err_firmware_deinit;
 
 	ret = hfi_core_resume(core, true);
 	if (ret)
@@ -316,8 +316,10 @@
 		goto err_core_deinit;
 
 	ret = pm_runtime_put_sync(dev);
-	if (ret)
+	if (ret) {
+		pm_runtime_get_noresume(dev);
 		goto err_dev_unregister;
+	}
 
 	return 0;
 
@@ -327,9 +329,14 @@
 	hfi_core_deinit(core, false);
 err_venus_shutdown:
 	venus_shutdown(core);
+err_firmware_deinit:
+	venus_firmware_deinit(core);
+err_of_depopulate:
+	of_platform_depopulate(dev);
 err_runtime_disable:
-	pm_runtime_set_suspended(dev);
+	pm_runtime_put_noidle(dev);
 	pm_runtime_disable(dev);
+	pm_runtime_set_suspended(dev);
 	hfi_destroy(core);
 	return ret;
 }
@@ -340,6 +347,7 @@
 	struct device *dev = core->dev;
 	int ret;
 
+	cancel_delayed_work_sync(&core->work);
 	ret = pm_runtime_get_sync(dev);
 	WARN_ON(ret < 0);
 
@@ -427,10 +435,11 @@
 };
 
 static const struct freq_tbl msm8996_freq_table[] = {
-	{ 1944000, 490000000 },	/* 4k UHD @ 60 */
-	{  972000, 320000000 },	/* 4k UHD @ 30 */
-	{  489600, 150000000 },	/* 1080p @ 60 */
-	{  244800,  75000000 },	/* 1080p @ 30 */
+	{ 1944000, 520000000 },	/* 4k UHD @ 60 (decode only) */
+	{  972000, 520000000 },	/* 4k UHD @ 30 */
+	{  489600, 346666667 },	/* 1080p @ 60 */
+	{  244800, 150000000 },	/* 1080p @ 30 */
+	{  108000,  75000000 },	/* 720p @ 30 */
 };
 
 static const struct reg_val msm8996_reg_preset[] = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/qcom/venus/firmware.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/qcom/venus/firmware.c
@@ -44,8 +44,14 @@
 
 int venus_set_hw_state(struct venus_core *core, bool resume)
 {
-	if (core->use_tz)
-		return qcom_scm_set_remote_state(resume, 0);
+	int ret;
+
+	if (core->use_tz) {
+		ret = qcom_scm_set_remote_state(resume, 0);
+		if (resume && ret == -EINVAL)
+			ret = 0;
+		return ret;
+	}
 
 	if (resume)
 		venus_reset_cpu(core);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/qcom/venus/hfi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/qcom/venus/hfi.c
@@ -104,6 +104,9 @@
 		mutex_lock(&core->lock);
 	}
 
+	if (!core->ops)
+		goto unlock;
+
 	ret = core->ops->core_deinit(core);
 
 	if (!ret)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/qcom/venus/hfi_msgs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/qcom/venus/hfi_msgs.c
@@ -350,7 +350,7 @@
 		memcpy(&bufreq[idx], buf_req, sizeof(*bufreq));
 		idx++;
 
-		if (idx > HFI_BUFFER_TYPE_MAX)
+		if (idx >= HFI_BUFFER_TYPE_MAX)
 			return HFI_ERR_SESSION_INVALID_PARAMETER;
 
 		req_bytes -= sizeof(struct hfi_buffer_requirements);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/qcom/venus/hfi_parser.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/qcom/venus/hfi_parser.c
@@ -19,6 +19,9 @@
 	struct venus_caps *caps = core->caps, *cap;
 	unsigned long bit;
 
+	if (hweight_long(core->dec_codecs) + hweight_long(core->enc_codecs) > MAX_CODEC_NUM)
+		return;
+
 	for_each_set_bit(bit, &core->dec_codecs, MAX_CODEC_NUM) {
 		cap = &caps[core->codecs_count++];
 		cap->codec = BIT(bit);
@@ -86,6 +89,9 @@
 {
 	const struct hfi_profile_level *pl = data;
 
+	if (cap->num_pl + num >= HFI_MAX_PROFILE_COUNT)
+		return;
+
 	memcpy(&cap->pl[cap->num_pl], pl, num * sizeof(*pl));
 	cap->num_pl += num;
 }
@@ -111,6 +117,9 @@
 {
 	const struct hfi_capability *caps = data;
 
+	if (cap->num_caps + num >= MAX_CAP_ENTRIES)
+		return;
+
 	memcpy(&cap->caps[cap->num_caps], caps, num * sizeof(*caps));
 	cap->num_caps += num;
 }
@@ -137,6 +146,9 @@
 {
 	const struct raw_formats *formats = fmts;
 
+	if (cap->num_fmts + num_fmts >= MAX_FMT_ENTRIES)
+		return;
+
 	memcpy(&cap->fmts[cap->num_fmts], formats, num_fmts * sizeof(*formats));
 	cap->num_fmts += num_fmts;
 }
@@ -159,6 +171,9 @@
 		rawfmts[i].buftype = fmt->buffer_type;
 		i++;
 
+		if (i >= MAX_FMT_ENTRIES)
+			return;
+
 		if (pinfo->num_planes > MAX_PLANES)
 			break;
 
@@ -181,6 +196,7 @@
 	if (IS_V1(core)) {
 		core->dec_codecs &= ~HFI_VIDEO_CODEC_HEVC;
 		core->dec_codecs &= ~HFI_VIDEO_CODEC_SPARK;
+		core->enc_codecs &= ~HFI_VIDEO_CODEC_HEVC;
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/qcom/venus/hfi_venus.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/qcom/venus/hfi_venus.c
@@ -206,6 +206,11 @@
 
 	new_wr_idx = wr_idx + dwords;
 	wr_ptr = (u32 *)(queue->qmem.kva + (wr_idx << 2));
+
+	if (wr_ptr < (u32 *)queue->qmem.kva ||
+	    wr_ptr > (u32 *)(queue->qmem.kva + queue->qmem.size - sizeof(*wr_ptr)))
+		return -EINVAL;
+
 	if (new_wr_idx < qsize) {
 		memcpy(wr_ptr, packet, dwords << 2);
 	} else {
@@ -273,6 +278,11 @@
 	}
 
 	rd_ptr = (u32 *)(queue->qmem.kva + (rd_idx << 2));
+
+	if (rd_ptr < (u32 *)queue->qmem.kva ||
+	    rd_ptr > (u32 *)(queue->qmem.kva + queue->qmem.size - sizeof(*rd_ptr)))
+		return -EINVAL;
+
 	dwords = *rd_ptr >> 2;
 	if (!dwords)
 		return -EINVAL;
@@ -1472,6 +1482,7 @@
 {
 	struct venus_hfi_device *hdev = to_hfi_priv(core);
 	struct device *dev = core->dev;
+	u32 ctrl_status;
 	bool val;
 	int ret;
 
@@ -1487,6 +1498,10 @@
 		return -EINVAL;
 	}
 
+	ctrl_status = venus_readl(hdev, CPU_CS_SCIACMDARG0);
+	if (ctrl_status & CPU_CS_SCIACMDARG0_PC_READY)
+		goto power_off;
+
 	/*
 	 * Power collapse sequence for Venus 3xx and 4xx versions:
 	 * 1. Check for ARM9 and video core to be idle by checking WFI bit
@@ -1511,6 +1526,7 @@
 	if (ret)
 		return ret;
 
+power_off:
 	mutex_lock(&hdev->lock);
 
 	ret = venus_power_off(hdev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/qcom/venus/vdec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/qcom/venus/vdec.c
@@ -157,6 +157,8 @@
 		else
 			return NULL;
 		fmt = find_format(inst, pixmp->pixelformat, f->type);
+		if (!fmt)
+			return NULL;
 	}
 
 	pixmp->width = clamp(pixmp->width, frame_width_min(inst),
@@ -987,11 +989,10 @@
 		ret = hfi_session_flush(inst, HFI_FLUSH_OUTPUT);
 		vdec_cancel_dst_buffers(inst);
 		inst->codec_state = VENUS_DEC_STATE_CAPTURE_SETUP;
-		INIT_LIST_HEAD(&inst->registeredbufs);
 		venus_helper_free_dpb_bufs(inst);
 		break;
 	default:
-		return 0;
+		break;
 	}
 
 	return ret;
@@ -1090,6 +1091,14 @@
 static void vdec_buf_cleanup(struct vb2_buffer *vb)
 {
 	struct venus_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct venus_buffer *buf = to_venus_buffer(vbuf);
+
+	mutex_lock(&inst->lock);
+	if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+		if (!list_empty(&inst->registeredbufs))
+			list_del_init(&buf->reg_list);
+	mutex_unlock(&inst->lock);
 
 	inst->buf_count--;
 	if (!inst->buf_count)
@@ -1391,6 +1400,7 @@
 {
 	struct venus_inst *inst = to_inst(file);
 
+	cancel_work_sync(&inst->delayed_process_work);
 	v4l2_m2m_ctx_release(inst->m2m_ctx);
 	v4l2_m2m_release(inst->m2m_dev);
 	vdec_ctrl_deinit(inst);
@@ -1412,9 +1422,6 @@
 	.unlocked_ioctl = video_ioctl2,
 	.poll = v4l2_m2m_fop_poll,
 	.mmap = v4l2_m2m_fop_mmap,
-#ifdef CONFIG_COMPAT
-	.compat_ioctl32 = v4l2_compat_ioctl32,
-#endif
 };
 
 static int vdec_probe(struct platform_device *pdev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/qcom/venus/venc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/qcom/venus/venc.c
@@ -308,6 +308,8 @@
 		else
 			return NULL;
 		fmt = find_format(inst, pixmp->pixelformat, f->type);
+		if (!fmt)
+			return NULL;
 	}
 
 	pixmp->width = clamp(pixmp->width, frame_width_min(inst),
@@ -1235,9 +1237,6 @@
 	.unlocked_ioctl = video_ioctl2,
 	.poll = v4l2_m2m_fop_poll,
 	.mmap = v4l2_m2m_fop_mmap,
-#ifdef CONFIG_COMPAT
-	.compat_ioctl32 = v4l2_compat_ioctl32,
-#endif
 };
 
 static int venc_probe(struct platform_device *pdev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/rcar-fcp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/rcar-fcp.c
@@ -8,6 +8,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/dma-mapping.h>
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/mod_devicetable.h>
@@ -21,6 +22,7 @@
 struct rcar_fcp_device {
 	struct list_head list;
 	struct device *dev;
+	struct device_dma_parameters dma_parms;
 };
 
 static LIST_HEAD(fcp_devices);
@@ -101,8 +103,10 @@
 		return 0;
 
 	ret = pm_runtime_get_sync(fcp->dev);
-	if (ret < 0)
+	if (ret < 0) {
+		pm_runtime_put_noidle(fcp->dev);
 		return ret;
+	}
 
 	return 0;
 }
@@ -136,6 +140,9 @@
 
 	fcp->dev = &pdev->dev;
 
+	fcp->dev->dma_parms = &fcp->dma_parms;
+	dma_set_max_seg_size(fcp->dev, DMA_BIT_MASK(32));
+
 	pm_runtime_enable(&pdev->dev);
 
 	mutex_lock(&fcp_lock);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/rcar-vin/rcar-csi2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/rcar-vin/rcar-csi2.c
@@ -361,7 +361,6 @@
 	struct media_pad pads[NR_OF_RCAR_CSI2_PAD];
 
 	struct v4l2_async_notifier notifier;
-	struct v4l2_async_subdev asd;
 	struct v4l2_subdev *remote;
 
 	struct v4l2_mbus_framefmt mf;
@@ -431,16 +430,23 @@
 static int rcsi2_set_phypll(struct rcar_csi2 *priv, unsigned int mbps)
 {
 	const struct rcsi2_mbps_reg *hsfreq;
+	const struct rcsi2_mbps_reg *hsfreq_prev = NULL;
 
-	for (hsfreq = priv->info->hsfreqrange; hsfreq->mbps != 0; hsfreq++)
+	for (hsfreq = priv->info->hsfreqrange; hsfreq->mbps != 0; hsfreq++) {
 		if (hsfreq->mbps >= mbps)
 			break;
+		hsfreq_prev = hsfreq;
+	}
 
 	if (!hsfreq->mbps) {
 		dev_err(priv->dev, "Unsupported PHY speed (%u Mbps)", mbps);
 		return -ERANGE;
 	}
 
+	if (hsfreq_prev &&
+	    ((mbps - hsfreq_prev->mbps) <= (hsfreq->mbps - mbps)))
+		hsfreq = hsfreq_prev;
+
 	rcsi2_write(priv, PHYPLL_REG, PHYPLL_HSFREQRANGE(hsfreq->reg));
 
 	return 0;
@@ -489,6 +495,8 @@
 
 	/* Code is validated in set_fmt. */
 	format = rcsi2_code_to_fmt(priv->mf.code);
+	if (!format)
+		return -EINVAL;
 
 	/*
 	 * Enable all supported CSI-2 channels with virtual channel and
@@ -810,6 +818,8 @@
 
 static int rcsi2_parse_dt(struct rcar_csi2 *priv)
 {
+	struct v4l2_async_subdev *asd;
+	struct fwnode_handle *fwnode;
 	struct device_node *ep;
 	struct v4l2_fwnode_endpoint v4l2_ep = { .bus_type = 0 };
 	int ret;
@@ -833,24 +843,19 @@
 		return ret;
 	}
 
-	priv->asd.match.fwnode =
-		fwnode_graph_get_remote_endpoint(of_fwnode_handle(ep));
-	priv->asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
-
+	fwnode = fwnode_graph_get_remote_endpoint(of_fwnode_handle(ep));
 	of_node_put(ep);
 
-	v4l2_async_notifier_init(&priv->notifier);
-
-	ret = v4l2_async_notifier_add_subdev(&priv->notifier, &priv->asd);
-	if (ret) {
-		fwnode_handle_put(priv->asd.match.fwnode);
-		return ret;
-	}
+	dev_dbg(priv->dev, "Found '%pOF'\n", to_of_node(fwnode));
 
+	v4l2_async_notifier_init(&priv->notifier);
 	priv->notifier.ops = &rcar_csi2_notify_ops;
 
-	dev_dbg(priv->dev, "Found '%pOF'\n",
-		to_of_node(priv->asd.match.fwnode));
+	asd = v4l2_async_notifier_add_fwnode_subdev(&priv->notifier, fwnode,
+						    sizeof(*asd));
+	fwnode_handle_put(fwnode);
+	if (IS_ERR(asd))
+		return PTR_ERR(asd);
 
 	ret = v4l2_async_subdev_notifier_register(&priv->subdev,
 						  &priv->notifier);
@@ -906,10 +911,17 @@
 				 const struct rcsi2_mbps_reg *values, u16 code)
 {
 	const struct rcsi2_mbps_reg *value;
+	const struct rcsi2_mbps_reg *prev_value = NULL;
 
-	for (value = values; value->mbps; value++)
+	for (value = values; value->mbps; value++) {
 		if (value->mbps >= mbps)
 			break;
+		prev_value = value;
+	}
+
+	if (prev_value &&
+	    ((mbps - prev_value->mbps) <= (value->mbps - mbps)))
+		value = prev_value;
 
 	if (!value->mbps) {
 		dev_err(priv->dev, "Unsupported PHY speed (%u Mbps)", mbps);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/rcar-vin/rcar-dma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/rcar-vin/rcar-dma.c
@@ -638,6 +638,7 @@
 		vnmc = VNMC_IM_FULL | VNMC_FOC;
 		break;
 	case V4L2_FIELD_NONE:
+	case V4L2_FIELD_ALTERNATE:
 		vnmc = VNMC_IM_ODD_EVEN;
 		progressive = true;
 		break;
@@ -1334,8 +1335,10 @@
 	int ret;
 
 	ret = pm_runtime_get_sync(vin->dev);
-	if (ret < 0)
+	if (ret < 0) {
+		pm_runtime_put_noidle(vin->dev);
 		return ret;
+	}
 
 	/* Make register writes take effect immediately. */
 	vnmc = rvin_read(vin, VNMC_REG);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/rcar-vin/rcar-v4l2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/rcar-vin/rcar-v4l2.c
@@ -208,6 +208,7 @@
 	ret = v4l2_subdev_call(sd, pad, set_fmt, pad_cfg, &format);
 	if (ret < 0 && ret != -ENOIOCTLCMD)
 		goto done;
+	ret = 0;
 
 	v4l2_fill_pix_format(pix, &format.format);
 
@@ -242,7 +243,7 @@
 done:
 	v4l2_subdev_free_pad_config(pad_cfg);
 
-	return 0;
+	return ret;
 }
 
 static int rvin_querycap(struct file *file, void *priv,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/rcar_drif.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/rcar_drif.c
@@ -185,7 +185,6 @@
 /* OF graph endpoint's V4L2 async data */
 struct rcar_drif_graph_ep {
 	struct v4l2_subdev *subdev;	/* Async matched subdev */
-	struct v4l2_async_subdev asd;	/* Async sub-device descriptor */
 };
 
 /* DMA buffer */
@@ -1104,12 +1103,6 @@
 	struct rcar_drif_sdr *sdr =
 		container_of(notifier, struct rcar_drif_sdr, notifier);
 
-	if (sdr->ep.asd.match.fwnode !=
-	    of_fwnode_handle(subdev->dev->of_node)) {
-		rdrif_err(sdr, "subdev %s cannot bind\n", subdev->name);
-		return -EINVAL;
-	}
-
 	v4l2_set_subdev_hostdata(subdev, sdr);
 	sdr->ep.subdev = subdev;
 	rdrif_dbg(sdr, "bound asd %s\n", subdev->name);
@@ -1213,7 +1206,7 @@
 {
 	struct v4l2_async_notifier *notifier = &sdr->notifier;
 	struct fwnode_handle *fwnode, *ep;
-	int ret;
+	struct v4l2_async_subdev *asd;
 
 	v4l2_async_notifier_init(notifier);
 
@@ -1222,26 +1215,21 @@
 	if (!ep)
 		return 0;
 
+	/* Get the endpoint properties */
+	rcar_drif_get_ep_properties(sdr, ep);
+
 	fwnode = fwnode_graph_get_remote_port_parent(ep);
+	fwnode_handle_put(ep);
 	if (!fwnode) {
 		dev_warn(sdr->dev, "bad remote port parent\n");
-		fwnode_handle_put(ep);
 		return -EINVAL;
 	}
 
-	sdr->ep.asd.match.fwnode = fwnode;
-	sdr->ep.asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
-	ret = v4l2_async_notifier_add_subdev(notifier, &sdr->ep.asd);
-	if (ret) {
-		fwnode_handle_put(fwnode);
-		return ret;
-	}
-
-	/* Get the endpoint properties */
-	rcar_drif_get_ep_properties(sdr, ep);
-
+	asd = v4l2_async_notifier_add_fwnode_subdev(notifier, fwnode,
+						    sizeof(*asd));
 	fwnode_handle_put(fwnode);
-	fwnode_handle_put(ep);
+	if (IS_ERR(asd))
+		return PTR_ERR(asd);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/rcar_fdp1.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/rcar_fdp1.c
@@ -2121,9 +2121,7 @@
 
 	if (ctx->hdl.error) {
 		ret = ctx->hdl.error;
-		v4l2_ctrl_handler_free(&ctx->hdl);
-		kfree(ctx);
-		goto done;
+		goto error_ctx;
 	}
 
 	ctx->fh.ctrl_handler = &ctx->hdl;
@@ -2137,20 +2135,27 @@
 
 	if (IS_ERR(ctx->fh.m2m_ctx)) {
 		ret = PTR_ERR(ctx->fh.m2m_ctx);
-
-		v4l2_ctrl_handler_free(&ctx->hdl);
-		kfree(ctx);
-		goto done;
+		goto error_ctx;
 	}
 
 	/* Perform any power management required */
-	pm_runtime_get_sync(fdp1->dev);
+	ret = pm_runtime_resume_and_get(fdp1->dev);
+	if (ret < 0)
+		goto error_pm;
 
 	v4l2_fh_add(&ctx->fh);
 
 	dprintk(fdp1, "Created instance: %p, m2m_ctx: %p\n",
 		ctx, ctx->fh.m2m_ctx);
 
+	mutex_unlock(&fdp1->dev_mutex);
+	return 0;
+
+error_pm:
+       v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
+error_ctx:
+	v4l2_ctrl_handler_free(&ctx->hdl);
+	kfree(ctx);
 done:
 	mutex_unlock(&fdp1->dev_mutex);
 	return ret;
@@ -2255,7 +2260,6 @@
 	struct fdp1_dev *fdp1;
 	struct video_device *vfd;
 	struct device_node *fcp_node;
-	struct resource *res;
 	struct clk *clk;
 	unsigned int i;
 
@@ -2282,17 +2286,15 @@
 	platform_set_drvdata(pdev, fdp1);
 
 	/* Memory-mapped registers */
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	fdp1->regs = devm_ioremap_resource(&pdev->dev, res);
+	fdp1->regs = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(fdp1->regs))
 		return PTR_ERR(fdp1->regs);
 
 	/* Interrupt service routine registration */
-	fdp1->irq = ret = platform_get_irq(pdev, 0);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "cannot find IRQ\n");
+	ret = platform_get_irq(pdev, 0);
+	if (ret < 0)
 		return ret;
-	}
+	fdp1->irq = ret;
 
 	ret = devm_request_irq(&pdev->dev, fdp1->irq, fdp1_irq_handler, 0,
 			       dev_name(&pdev->dev), fdp1);
@@ -2315,8 +2317,10 @@
 
 	/* Determine our clock rate */
 	clk = clk_get(&pdev->dev, NULL);
-	if (IS_ERR(clk))
-		return PTR_ERR(clk);
+	if (IS_ERR(clk)) {
+		ret = PTR_ERR(clk);
+		goto put_dev;
+	}
 
 	fdp1->clk_rate = clk_get_rate(clk);
 	clk_put(clk);
@@ -2325,7 +2329,7 @@
 	ret = v4l2_device_register(&pdev->dev, &fdp1->v4l2_dev);
 	if (ret) {
 		v4l2_err(&fdp1->v4l2_dev, "Failed to register video device\n");
-		return ret;
+		goto put_dev;
 	}
 
 	/* M2M registration */
@@ -2355,7 +2359,9 @@
 
 	/* Power up the cells to read HW */
 	pm_runtime_enable(&pdev->dev);
-	pm_runtime_get_sync(fdp1->dev);
+	ret = pm_runtime_resume_and_get(fdp1->dev);
+	if (ret < 0)
+		goto disable_pm;
 
 	hw_version = fdp1_read(fdp1, FD1_IP_INTDATA);
 	switch (hw_version) {
@@ -2369,7 +2375,7 @@
 		dprintk(fdp1, "FDP1 Version R-Car H3\n");
 		break;
 	case FD1_IP_M3N:
-		dprintk(fdp1, "FDP1 Version R-Car M3N\n");
+		dprintk(fdp1, "FDP1 Version R-Car M3-N\n");
 		break;
 	case FD1_IP_E3:
 		dprintk(fdp1, "FDP1 Version R-Car E3\n");
@@ -2384,12 +2390,17 @@
 
 	return 0;
 
+disable_pm:
+	pm_runtime_disable(fdp1->dev);
+
 release_m2m:
 	v4l2_m2m_release(fdp1->m2m_dev);
 
 unreg_dev:
 	v4l2_device_unregister(&fdp1->v4l2_dev);
 
+put_dev:
+	rcar_fcp_put(fdp1->fcp);
 	return ret;
 }
 
@@ -2401,6 +2412,7 @@
 	video_unregister_device(&fdp1->vfd);
 	v4l2_device_unregister(&fdp1->v4l2_dev);
 	pm_runtime_disable(&pdev->dev);
+	rcar_fcp_put(fdp1->fcp);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/rockchip/rga/rga-buf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/rockchip/rga/rga-buf.c
@@ -81,6 +81,7 @@
 
 	ret = pm_runtime_get_sync(rga->dev);
 	if (ret < 0) {
+		pm_runtime_put_noidle(rga->dev);
 		rga_buf_return_buffers(q, VB2_BUF_STATE_QUEUED);
 		return ret;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/rockchip/rga/rga-hw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/rockchip/rga/rga-hw.c
@@ -200,22 +200,25 @@
 	dst_info.data.format = ctx->out.fmt->hw_format;
 	dst_info.data.swap = ctx->out.fmt->color_swap;
 
-	if (ctx->in.fmt->hw_format >= RGA_COLOR_FMT_YUV422SP) {
-		if (ctx->out.fmt->hw_format < RGA_COLOR_FMT_YUV422SP) {
-			switch (ctx->in.colorspace) {
-			case V4L2_COLORSPACE_REC709:
-				src_info.data.csc_mode =
-					RGA_SRC_CSC_MODE_BT709_R0;
-				break;
-			default:
-				src_info.data.csc_mode =
-					RGA_SRC_CSC_MODE_BT601_R0;
-				break;
-			}
+	/*
+	 * CSC mode must only be set when the colorspace families differ between
+	 * input and output. It must remain unset (zeroed) if both are the same.
+	 */
+
+	if (RGA_COLOR_FMT_IS_YUV(ctx->in.fmt->hw_format) &&
+	    RGA_COLOR_FMT_IS_RGB(ctx->out.fmt->hw_format)) {
+		switch (ctx->in.colorspace) {
+		case V4L2_COLORSPACE_REC709:
+			src_info.data.csc_mode = RGA_SRC_CSC_MODE_BT709_R0;
+			break;
+		default:
+			src_info.data.csc_mode = RGA_SRC_CSC_MODE_BT601_R0;
+			break;
 		}
 	}
 
-	if (ctx->out.fmt->hw_format >= RGA_COLOR_FMT_YUV422SP) {
+	if (RGA_COLOR_FMT_IS_RGB(ctx->in.fmt->hw_format) &&
+	    RGA_COLOR_FMT_IS_YUV(ctx->out.fmt->hw_format)) {
 		switch (ctx->out.colorspace) {
 		case V4L2_COLORSPACE_REC709:
 			dst_info.data.csc_mode = RGA_SRC_CSC_MODE_BT709_R0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/rockchip/rga/rga-hw.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/rockchip/rga/rga-hw.h
@@ -95,6 +95,11 @@
 #define RGA_COLOR_FMT_CP_8BPP 15
 #define RGA_COLOR_FMT_MASK 15
 
+#define RGA_COLOR_FMT_IS_YUV(fmt) \
+	(((fmt) >= RGA_COLOR_FMT_YUV422SP) && ((fmt) < RGA_COLOR_FMT_CP_1BPP))
+#define RGA_COLOR_FMT_IS_RGB(fmt) \
+	((fmt) < RGA_COLOR_FMT_YUV422SP)
+
 #define RGA_COLOR_NONE_SWAP 0
 #define RGA_COLOR_RB_SWAP 1
 #define RGA_COLOR_ALPHA_SWAP 2
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/rockchip/rga/rga.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/rockchip/rga/rga.c
@@ -187,7 +187,7 @@
 static struct rga_fmt formats[] = {
 	{
 		.fourcc = V4L2_PIX_FMT_ARGB32,
-		.color_swap = RGA_COLOR_RB_SWAP,
+		.color_swap = RGA_COLOR_ALPHA_SWAP,
 		.hw_format = RGA_COLOR_FMT_ABGR8888,
 		.depth = 32,
 		.uv_factor = 1,
@@ -195,17 +195,8 @@
 		.x_div = 1,
 	},
 	{
-		.fourcc = V4L2_PIX_FMT_XRGB32,
-		.color_swap = RGA_COLOR_RB_SWAP,
-		.hw_format = RGA_COLOR_FMT_XBGR8888,
-		.depth = 32,
-		.uv_factor = 1,
-		.y_div = 1,
-		.x_div = 1,
-	},
-	{
 		.fourcc = V4L2_PIX_FMT_ABGR32,
-		.color_swap = RGA_COLOR_ALPHA_SWAP,
+		.color_swap = RGA_COLOR_RB_SWAP,
 		.hw_format = RGA_COLOR_FMT_ABGR8888,
 		.depth = 32,
 		.uv_factor = 1,
@@ -214,7 +205,7 @@
 	},
 	{
 		.fourcc = V4L2_PIX_FMT_XBGR32,
-		.color_swap = RGA_COLOR_ALPHA_SWAP,
+		.color_swap = RGA_COLOR_RB_SWAP,
 		.hw_format = RGA_COLOR_FMT_XBGR8888,
 		.depth = 32,
 		.uv_factor = 1,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/s3c-camif/camif-capture.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/s3c-camif/camif-capture.c
@@ -1132,12 +1132,12 @@
 
 	ret = vb2_queue_init(q);
 	if (ret)
-		goto err_vd_rel;
+		return ret;
 
 	vp->pad.flags = MEDIA_PAD_FL_SINK;
 	ret = media_entity_pads_init(&vfd->entity, 1, &vp->pad);
 	if (ret)
-		goto err_vd_rel;
+		return ret;
 
 	video_set_drvdata(vfd, vp);
 
@@ -1170,8 +1170,6 @@
 	v4l2_ctrl_handler_free(&vp->ctrl_handler);
 err_me_cleanup:
 	media_entity_cleanup(&vfd->entity);
-err_vd_rel:
-	video_device_release(vfd);
 	return ret;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/s3c-camif/camif-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/s3c-camif/camif-core.c
@@ -464,7 +464,7 @@
 
 	ret = camif_media_dev_init(camif);
 	if (ret < 0)
-		goto err_alloc;
+		goto err_pm;
 
 	ret = camif_register_sensor(camif);
 	if (ret < 0)
@@ -498,10 +498,9 @@
 	media_device_unregister(&camif->media_dev);
 	media_device_cleanup(&camif->media_dev);
 	camif_unregister_media_entities(camif);
-err_alloc:
+err_pm:
 	pm_runtime_put(dev);
 	pm_runtime_disable(dev);
-err_pm:
 	camif_clk_put(camif);
 err_clk:
 	s3c_camif_unregister_subdev(camif);
@@ -530,10 +529,19 @@
 static int s3c_camif_runtime_resume(struct device *dev)
 {
 	struct camif_dev *camif = dev_get_drvdata(dev);
+	int ret;
+
+	ret = clk_enable(camif->clock[CLK_GATE]);
+	if (ret)
+		return ret;
 
-	clk_enable(camif->clock[CLK_GATE]);
 	/* null op on s3c244x */
-	clk_enable(camif->clock[CLK_CAM]);
+	ret = clk_enable(camif->clock[CLK_CAM]);
+	if (ret) {
+		clk_disable(camif->clock[CLK_GATE]);
+		return ret;
+	}
+
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/s5p-cec/s5p_cec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/s5p-cec/s5p_cec.c
@@ -35,10 +35,13 @@
 
 static int s5p_cec_adap_enable(struct cec_adapter *adap, bool enable)
 {
+	int ret;
 	struct s5p_cec_dev *cec = cec_get_drvdata(adap);
 
 	if (enable) {
-		pm_runtime_get_sync(cec->dev);
+		ret = pm_runtime_resume_and_get(cec->dev);
+		if (ret < 0)
+			return ret;
 
 		s5p_cec_reset(cec);
 
@@ -51,7 +54,7 @@
 	} else {
 		s5p_cec_mask_tx_interrupts(cec);
 		s5p_cec_mask_rx_interrupts(cec);
-		pm_runtime_disable(cec->dev);
+		pm_runtime_put(cec->dev);
 	}
 
 	return 0;
@@ -112,6 +115,8 @@
 				dev_dbg(cec->dev, "Buffer overrun (worker did not process previous message)\n");
 			cec->rx = STATE_BUSY;
 			cec->msg.len = status >> 24;
+			if (cec->msg.len > CEC_MAX_MSG_SIZE)
+				cec->msg.len = CEC_MAX_MSG_SIZE;
 			cec->msg.rx_status = CEC_RX_STATUS_OK;
 			s5p_cec_get_rx_buf(cec, cec->msg.len,
 					cec->msg.msg);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/s5p-g2d/g2d.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/s5p-g2d/g2d.c
@@ -276,6 +276,9 @@
 	struct g2d_dev *dev = video_drvdata(file);
 	struct g2d_ctx *ctx = fh2ctx(file->private_data);
 
+	mutex_lock(&dev->mutex);
+	v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
+	mutex_unlock(&dev->mutex);
 	v4l2_ctrl_handler_free(&ctx->ctrl_handler);
 	v4l2_fh_del(&ctx->fh);
 	v4l2_fh_exit(&ctx->fh);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/s5p-jpeg/jpeg-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/s5p-jpeg/jpeg-core.c
@@ -774,11 +774,14 @@
 		(unsigned long)vb2_plane_vaddr(&vb->vb2_buf, 0) + ctx->out_q.sos + 2;
 	jpeg_buffer.curr = 0;
 
-	word = 0;
-
 	if (get_word_be(&jpeg_buffer, &word))
 		return;
-	jpeg_buffer.size = (long)word - 2;
+
+	if (word < 2)
+		jpeg_buffer.size = 0;
+	else
+		jpeg_buffer.size = (long)word - 2;
+
 	jpeg_buffer.data += 2;
 	jpeg_buffer.curr = 0;
 
@@ -1057,6 +1060,7 @@
 	if (byte == -1)
 		return -1;
 	*word = (unsigned int)byte | temp;
+
 	return 0;
 }
 
@@ -1144,7 +1148,7 @@
 			if (get_word_be(&jpeg_buffer, &word))
 				break;
 			length = (long)word - 2;
-			if (!length)
+			if (length <= 0)
 				return false;
 			sof = jpeg_buffer.curr; /* after 0xffc0 */
 			sof_len = length;
@@ -1175,7 +1179,7 @@
 			if (get_word_be(&jpeg_buffer, &word))
 				break;
 			length = (long)word - 2;
-			if (!length)
+			if (length <= 0)
 				return false;
 			if (n_dqt >= S5P_JPEG_MAX_MARKER)
 				return false;
@@ -1188,7 +1192,7 @@
 			if (get_word_be(&jpeg_buffer, &word))
 				break;
 			length = (long)word - 2;
-			if (!length)
+			if (length <= 0)
 				return false;
 			if (n_dht >= S5P_JPEG_MAX_MARKER)
 				return false;
@@ -1213,6 +1217,7 @@
 			if (get_word_be(&jpeg_buffer, &word))
 				break;
 			length = (long)word - 2;
+			/* No need to check underflows as skip() does it  */
 			skip(&jpeg_buffer, length);
 			break;
 		}
@@ -2579,11 +2584,8 @@
 static int s5p_jpeg_start_streaming(struct vb2_queue *q, unsigned int count)
 {
 	struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(q);
-	int ret;
-
-	ret = pm_runtime_get_sync(ctx->jpeg->dev);
 
-	return ret > 0 ? 0 : ret;
+	return pm_runtime_resume_and_get(ctx->jpeg->dev);
 }
 
 static void s5p_jpeg_stop_streaming(struct vb2_queue *q)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -1279,11 +1279,15 @@
 	spin_lock_init(&dev->condlock);
 	dev->plat_dev = pdev;
 	if (!dev->plat_dev) {
-		dev_err(&pdev->dev, "No platform data specified\n");
+		mfc_err("No platform data specified\n");
 		return -ENODEV;
 	}
 
 	dev->variant = of_device_get_match_data(&pdev->dev);
+	if (!dev->variant) {
+		dev_err(&pdev->dev, "Failed to get device MFC hardware variant information\n");
+		return -ENOENT;
+	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	dev->regs_base = devm_ioremap_resource(&pdev->dev, res);
@@ -1576,8 +1580,18 @@
 	.port_num	= MFC_NUM_PORTS_V7,
 	.buf_size	= &buf_size_v7,
 	.fw_name[0]     = "s5p-mfc-v7.fw",
-	.clk_names	= {"mfc", "sclk_mfc"},
-	.num_clocks	= 2,
+	.clk_names	= {"mfc"},
+	.num_clocks	= 1,
+};
+
+static struct s5p_mfc_variant mfc_drvdata_v7_3250 = {
+	.version        = MFC_VERSION_V7,
+	.version_bit    = MFC_V7_BIT,
+	.port_num       = MFC_NUM_PORTS_V7,
+	.buf_size       = &buf_size_v7,
+	.fw_name[0]     = "s5p-mfc-v7.fw",
+	.clk_names      = {"mfc", "sclk_mfc"},
+	.num_clocks     = 2,
 };
 
 static struct s5p_mfc_buf_size_v6 mfc_buf_size_v8 = {
@@ -1648,6 +1662,9 @@
 		.compatible = "samsung,mfc-v7",
 		.data = &mfc_drvdata_v7,
 	}, {
+		.compatible = "samsung,exynos3250-mfc",
+		.data = &mfc_drvdata_v7_3250,
+	}, {
 		.compatible = "samsung,mfc-v8",
 		.data = &mfc_drvdata_v8,
 	}, {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
@@ -468,8 +468,10 @@
 	s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
 	/* Wait until instance is returned or timeout occurred */
 	if (s5p_mfc_wait_for_done_ctx(ctx,
-				S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET, 0))
+				S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET, 0)){
+		clear_work_bit_irqsave(ctx);
 		mfc_err("Err returning instance\n");
+	}
 
 	/* Free resources */
 	s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers, ctx);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
@@ -1212,6 +1212,7 @@
 	unsigned long mb_y_addr, mb_c_addr;
 	int slice_type;
 	unsigned int strm_size;
+	bool src_ready;
 
 	slice_type = s5p_mfc_hw_call(dev->mfc_ops, get_enc_slice_type, dev);
 	strm_size = s5p_mfc_hw_call(dev->mfc_ops, get_enc_strm_size, dev);
@@ -1251,7 +1252,8 @@
 			}
 		}
 	}
-	if ((ctx->src_queue_cnt > 0) && (ctx->state == MFCINST_RUNNING)) {
+	if (ctx->src_queue_cnt > 0 && (ctx->state == MFCINST_RUNNING ||
+				       ctx->state == MFCINST_FINISHING)) {
 		mb_entry = list_entry(ctx->src_queue.next, struct s5p_mfc_buf,
 									list);
 		if (mb_entry->flags & MFC_BUF_FLAG_USED) {
@@ -1282,7 +1284,13 @@
 		vb2_set_plane_payload(&mb_entry->b->vb2_buf, 0, strm_size);
 		vb2_buffer_done(&mb_entry->b->vb2_buf, VB2_BUF_STATE_DONE);
 	}
-	if ((ctx->src_queue_cnt == 0) || (ctx->dst_queue_cnt == 0))
+
+	src_ready = true;
+	if (ctx->state == MFCINST_RUNNING && ctx->src_queue_cnt == 0)
+		src_ready = false;
+	if (ctx->state == MFCINST_FINISHING && ctx->ref_queue_cnt == 0)
+		src_ready = false;
+	if (!src_ready || ctx->dst_queue_cnt == 0)
 		clear_work_bit(ctx);
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
@@ -1060,7 +1060,7 @@
 	}
 
 	/* aspect ratio VUI */
-	readl(mfc_regs->e_h264_options);
+	reg = readl(mfc_regs->e_h264_options);
 	reg &= ~(0x1 << 5);
 	reg |= ((p_h264->vui_sar & 0x1) << 5);
 	writel(reg, mfc_regs->e_h264_options);
@@ -1083,7 +1083,7 @@
 
 	/* intra picture period for H.264 open GOP */
 	/* control */
-	readl(mfc_regs->e_h264_options);
+	reg = readl(mfc_regs->e_h264_options);
 	reg &= ~(0x1 << 4);
 	reg |= ((p_h264->open_gop & 0x1) << 4);
 	writel(reg, mfc_regs->e_h264_options);
@@ -1097,23 +1097,23 @@
 	}
 
 	/* 'WEIGHTED_BI_PREDICTION' for B is disable */
-	readl(mfc_regs->e_h264_options);
+	reg = readl(mfc_regs->e_h264_options);
 	reg &= ~(0x3 << 9);
 	writel(reg, mfc_regs->e_h264_options);
 
 	/* 'CONSTRAINED_INTRA_PRED_ENABLE' is disable */
-	readl(mfc_regs->e_h264_options);
+	reg = readl(mfc_regs->e_h264_options);
 	reg &= ~(0x1 << 14);
 	writel(reg, mfc_regs->e_h264_options);
 
 	/* ASO */
-	readl(mfc_regs->e_h264_options);
+	reg = readl(mfc_regs->e_h264_options);
 	reg &= ~(0x1 << 6);
 	reg |= ((p_h264->aso & 0x1) << 6);
 	writel(reg, mfc_regs->e_h264_options);
 
 	/* hier qp enable */
-	readl(mfc_regs->e_h264_options);
+	reg = readl(mfc_regs->e_h264_options);
 	reg &= ~(0x1 << 8);
 	reg |= ((p_h264->open_gop & 0x1) << 8);
 	writel(reg, mfc_regs->e_h264_options);
@@ -1134,7 +1134,7 @@
 	writel(reg, mfc_regs->e_h264_num_t_layer);
 
 	/* frame packing SEI generation */
-	readl(mfc_regs->e_h264_options);
+	reg = readl(mfc_regs->e_h264_options);
 	reg &= ~(0x1 << 25);
 	reg |= ((p_h264->sei_frame_packing & 0x1) << 25);
 	writel(reg, mfc_regs->e_h264_options);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
@@ -79,8 +79,10 @@
 	int i, ret = 0;
 
 	ret = pm_runtime_get_sync(pm->device);
-	if (ret < 0)
+	if (ret < 0) {
+		pm_runtime_put_noidle(pm->device);
 		return ret;
+	}
 
 	/* clock control */
 	for (i = 0; i < pm->num_clocks; i++) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/seco-cec/seco-cec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/seco-cec/seco-cec.c
@@ -675,6 +675,7 @@
 err_delete_adapter:
 	cec_delete_adapter(secocec->cec_adap);
 err:
+	release_region(BRA_SMB_BASE_ADDR, 7);
 	dev_err(dev, "%s device probe failed\n", dev_name(dev));
 
 	return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/sh_vou.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/sh_vou.c
@@ -1133,7 +1133,11 @@
 	if (v4l2_fh_is_singular_file(file) &&
 	    vou_dev->status == SH_VOU_INITIALISING) {
 		/* First open */
-		pm_runtime_get_sync(vou_dev->v4l2_dev.dev);
+		err = pm_runtime_resume_and_get(vou_dev->v4l2_dev.dev);
+		if (err < 0) {
+			v4l2_fh_release(file);
+			goto done_open;
+		}
 		err = sh_vou_hw_init(vou_dev);
 		if (err < 0) {
 			pm_runtime_put(vou_dev->v4l2_dev.dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/sti/bdisp/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/sti/bdisp/Makefile
@@ -1,4 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_VIDEO_STI_BDISP) := bdisp.o
+obj-$(CONFIG_VIDEO_STI_BDISP) += bdisp.o
 
 bdisp-objs := bdisp-v4l2.o bdisp-hw.o bdisp-debug.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/sti/bdisp/bdisp-debug.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/sti/bdisp/bdisp-debug.c
@@ -480,7 +480,7 @@
 	int ret;
 	unsigned int i;
 
-	ret = pm_runtime_get_sync(bdisp->dev);
+	ret = pm_runtime_resume_and_get(bdisp->dev);
 	if (ret < 0) {
 		seq_puts(s, "Cannot wake up IP\n");
 		return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/sti/bdisp/bdisp-hw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/sti/bdisp/bdisp-hw.c
@@ -14,8 +14,8 @@
 #define MAX_SRC_WIDTH           2048
 
 /* Reset & boot poll config */
-#define POLL_RST_MAX            50
-#define POLL_RST_DELAY_MS       20
+#define POLL_RST_MAX            500
+#define POLL_RST_DELAY_MS       2
 
 enum bdisp_target_plan {
 	BDISP_RGB,
@@ -382,7 +382,7 @@
 	for (i = 0; i < POLL_RST_MAX; i++) {
 		if (readl(bdisp->regs + BLT_STA1) & BLT_STA1_IDLE)
 			break;
-		msleep(POLL_RST_DELAY_MS);
+		udelay(POLL_RST_DELAY_MS * 1000);
 	}
 	if (i == POLL_RST_MAX)
 		dev_err(bdisp->dev, "Reset timeout\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/sti/bdisp/bdisp-v4l2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/sti/bdisp/bdisp-v4l2.c
@@ -499,7 +499,7 @@
 {
 	struct bdisp_ctx *ctx = q->drv_priv;
 	struct vb2_v4l2_buffer *buf;
-	int ret = pm_runtime_get_sync(ctx->bdisp_dev->dev);
+	int ret = pm_runtime_resume_and_get(ctx->bdisp_dev->dev);
 
 	if (ret < 0) {
 		dev_err(ctx->bdisp_dev->dev, "failed to set runtime PM\n");
@@ -651,8 +651,7 @@
 
 	dev_dbg(bdisp->dev, "%s\n", __func__);
 
-	if (mutex_lock_interruptible(&bdisp->lock))
-		return -ERESTARTSYS;
+	mutex_lock(&bdisp->lock);
 
 	v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
 
@@ -1309,6 +1308,8 @@
 	init_waitqueue_head(&bdisp->irq_queue);
 	INIT_DELAYED_WORK(&bdisp->timeout_work, bdisp_irq_timeout);
 	bdisp->work_queue = create_workqueue(BDISP_NAME);
+	if (!bdisp->work_queue)
+		return -ENOMEM;
 
 	spin_lock_init(&bdisp->slock);
 	mutex_init(&bdisp->lock);
@@ -1365,10 +1366,10 @@
 
 	/* Power management */
 	pm_runtime_enable(dev);
-	ret = pm_runtime_get_sync(dev);
+	ret = pm_runtime_resume_and_get(dev);
 	if (ret < 0) {
 		dev_err(dev, "failed to set PM\n");
-		goto err_dbg;
+		goto err_remove;
 	}
 
 	/* Filters */
@@ -1396,7 +1397,7 @@
 	bdisp_hw_free_filters(bdisp->dev);
 err_pm:
 	pm_runtime_put(dev);
-err_dbg:
+err_remove:
 	bdisp_debugfs_remove(bdisp);
 err_v4l2:
 	v4l2_device_unregister(&bdisp->v4l2_dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c
@@ -939,6 +939,7 @@
 		if (ret) {
 			dev_err(fei->dev,
 				"configure_memdma_and_inputblock failed\n");
+			of_node_put(child);
 			goto err_unmap;
 		}
 		index++;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/sti/delta/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/sti/delta/Makefile
@@ -1,5 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_VIDEO_STI_DELTA_DRIVER) := st-delta.o
+obj-$(CONFIG_VIDEO_STI_DELTA_DRIVER) += st-delta.o
 st-delta-y := delta-v4l2.o delta-mem.o delta-ipc.o delta-debug.o
 
 # MJPEG support
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/sti/delta/delta-v4l2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/sti/delta/delta-v4l2.c
@@ -954,8 +954,10 @@
 	/* enable the hardware */
 	if (!dec->pm) {
 		ret = delta_get_sync(ctx);
-		if (ret)
+		if (ret) {
+			delta_put_autosuspend(ctx);
 			goto err;
+		}
 	}
 
 	/* decode this access unit */
@@ -1860,7 +1862,7 @@
 	if (ret) {
 		dev_err(delta->dev, "%s failed to initialize firmware ipc channel\n",
 			DELTA_PREFIX);
-		goto err;
+		goto err_pm_disable;
 	}
 
 	/* register all available decoders */
@@ -1874,7 +1876,7 @@
 	if (ret) {
 		dev_err(delta->dev, "%s failed to register V4L2 device\n",
 			DELTA_PREFIX);
-		goto err;
+		goto err_pm_disable;
 	}
 
 	delta->work_queue = create_workqueue(DELTA_NAME);
@@ -1899,6 +1901,8 @@
 	destroy_workqueue(delta->work_queue);
 err_v4l2:
 	v4l2_device_unregister(&delta->v4l2_dev);
+err_pm_disable:
+	pm_runtime_disable(dev);
 err:
 	return ret;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/sti/hva/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/sti/hva/Makefile
@@ -1,4 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_VIDEO_STI_HVA) := st-hva.o
+obj-$(CONFIG_VIDEO_STI_HVA) += st-hva.o
 st-hva-y := hva-v4l2.o hva-hw.o hva-mem.o hva-h264.o
 st-hva-$(CONFIG_VIDEO_STI_HVA_DEBUGFS) += hva-debugfs.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/sti/hva/hva-hw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/sti/hva/hva-hw.c
@@ -130,8 +130,7 @@
 	ctx_id = (hva->sts_reg & 0xFF00) >> 8;
 	if (ctx_id >= HVA_MAX_INSTANCES) {
 		dev_err(dev, "%s     %s: bad context identifier: %d\n",
-			ctx->name, __func__, ctx_id);
-		ctx->hw_err = true;
+			HVA_PREFIX, __func__, ctx_id);
 		goto out;
 	}
 
@@ -272,6 +271,7 @@
 
 	if (pm_runtime_get_sync(dev) < 0) {
 		dev_err(dev, "%s     failed to get pm_runtime\n", HVA_PREFIX);
+		pm_runtime_put_noidle(dev);
 		mutex_unlock(&hva->protect_mutex);
 		return -EFAULT;
 	}
@@ -388,7 +388,7 @@
 	ret = pm_runtime_get_sync(dev);
 	if (ret < 0) {
 		dev_err(dev, "%s     failed to set PM\n", HVA_PREFIX);
-		goto err_clk;
+		goto err_pm;
 	}
 
 	/* check IP hardware version */
@@ -553,6 +553,7 @@
 
 	if (pm_runtime_get_sync(dev) < 0) {
 		seq_puts(s, "Cannot wake up IP\n");
+		pm_runtime_put_noidle(dev);
 		mutex_unlock(&hva->protect_mutex);
 		return;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/stm32/stm32-dcmi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/stm32/stm32-dcmi.c
@@ -135,6 +135,7 @@
 	int				sequence;
 	struct list_head		buffers;
 	struct dcmi_buf			*active;
+	int			irq;
 
 	struct v4l2_device		v4l2_dev;
 	struct video_device		*vdev;
@@ -733,7 +734,7 @@
 	if (ret < 0) {
 		dev_err(dcmi->dev, "%s: Failed to start streaming, cannot get sync (%d)\n",
 			__func__, ret);
-		goto err_release_buffers;
+		goto err_pm_put;
 	}
 
 	ret = media_pipeline_start(&dcmi->vdev->entity, &dcmi->pipeline);
@@ -837,8 +838,6 @@
 
 err_pm_put:
 	pm_runtime_put(dcmi->dev);
-
-err_release_buffers:
 	spin_lock_irq(&dcmi->irqlock);
 	/*
 	 * Return all buffers to vb2 in QUEUED state.
@@ -1722,6 +1721,14 @@
 		return ret;
 	}
 
+	ret = devm_request_threaded_irq(dcmi->dev, dcmi->irq, dcmi_irq_callback,
+					dcmi_irq_thread, IRQF_ONESHOT,
+					dev_name(dcmi->dev), dcmi);
+	if (ret) {
+		dev_err(dcmi->dev, "Unable to request irq %d\n", dcmi->irq);
+		return ret;
+	}
+
 	return 0;
 }
 
@@ -1883,6 +1890,8 @@
 	if (irq <= 0)
 		return irq ? irq : -ENXIO;
 
+	dcmi->irq = irq;
+
 	dcmi->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!dcmi->res) {
 		dev_err(&pdev->dev, "Could not get resource\n");
@@ -1895,14 +1904,6 @@
 		return PTR_ERR(dcmi->regs);
 	}
 
-	ret = devm_request_threaded_irq(&pdev->dev, irq, dcmi_irq_callback,
-					dcmi_irq_thread, IRQF_ONESHOT,
-					dev_name(&pdev->dev), dcmi);
-	if (ret) {
-		dev_err(&pdev->dev, "Unable to request irq %d\n", irq);
-		return ret;
-	}
-
 	mclk = devm_clk_get(&pdev->dev, "mclk");
 	if (IS_ERR(mclk)) {
 		if (PTR_ERR(mclk) != -EPROBE_DEFER)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/of_graph.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
@@ -32,6 +33,10 @@
 	.link_validate = v4l2_subdev_link_validate,
 };
 
+static const struct media_entity_operations sun4i_csi_subdev_entity_ops = {
+	.link_validate = v4l2_subdev_link_validate,
+};
+
 static int sun4i_csi_notify_bound(struct v4l2_async_notifier *notifier,
 				  struct v4l2_subdev *subdev,
 				  struct v4l2_async_subdev *asd)
@@ -155,6 +160,27 @@
 	subdev = &csi->subdev;
 	vdev = &csi->vdev;
 
+	/*
+	 * On Allwinner SoCs, some high memory bandwidth devices do DMA
+	 * directly over the memory bus (called MBUS), instead of the
+	 * system bus. The memory bus has a different addressing scheme
+	 * without the DRAM starting offset.
+	 *
+	 * In some cases this can be described by an interconnect in
+	 * the device tree. In other cases where the hardware is not
+	 * fully understood and the interconnect is left out of the
+	 * device tree, fall back to a default offset.
+	 */
+	if (of_find_property(csi->dev->of_node, "interconnects", NULL)) {
+		ret = of_dma_configure(csi->dev, csi->dev->of_node, true);
+		if (ret)
+			return ret;
+	} else {
+#ifdef PHYS_PFN_OFFSET
+		csi->dev->dma_pfn_offset = PHYS_PFN_OFFSET;
+#endif
+	}
+
 	csi->mdev.dev = csi->dev;
 	strscpy(csi->mdev.model, "Allwinner Video Capture Device",
 		sizeof(csi->mdev.model));
@@ -199,6 +225,7 @@
 	v4l2_subdev_init(subdev, &sun4i_csi_subdev_ops);
 	subdev->flags = V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
 	subdev->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
+	subdev->entity.ops = &sun4i_csi_subdev_entity_ops;
 	subdev->owner = THIS_MODULE;
 	snprintf(subdev->name, sizeof(subdev->name), "sun4i-csi-0");
 	v4l2_set_subdevdata(subdev, csi);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.h
@@ -22,8 +22,8 @@
 #define CSI_CFG_INPUT_FMT(fmt)			((fmt) << 20)
 #define CSI_CFG_OUTPUT_FMT(fmt)			((fmt) << 16)
 #define CSI_CFG_YUV_DATA_SEQ(seq)		((seq) << 8)
-#define CSI_CFG_VSYNC_POL(pol)			((pol) << 2)
-#define CSI_CFG_HSYNC_POL(pol)			((pol) << 1)
+#define CSI_CFG_VREF_POL(pol)			((pol) << 2)
+#define CSI_CFG_HREF_POL(pol)			((pol) << 1)
 #define CSI_CFG_PCLK_POL(pol)			((pol) << 0)
 
 #define CSI_CPT_CTRL_REG		0x08
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/sunxi/sun4i-csi/sun4i_dma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/sunxi/sun4i-csi/sun4i_dma.c
@@ -228,7 +228,7 @@
 	struct sun4i_csi *csi = vb2_get_drv_priv(vq);
 	struct v4l2_fwnode_bus_parallel *bus = &csi->bus;
 	const struct sun4i_csi_format *csi_fmt;
-	unsigned long hsync_pol, pclk_pol, vsync_pol;
+	unsigned long href_pol, pclk_pol, vref_pol;
 	unsigned long flags;
 	unsigned int i;
 	int ret;
@@ -278,13 +278,21 @@
 	writel(CSI_WIN_CTRL_H_ACTIVE(csi->fmt.height),
 	       csi->regs + CSI_WIN_CTRL_H_REG);
 
-	hsync_pol = !!(bus->flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH);
-	pclk_pol = !!(bus->flags & V4L2_MBUS_DATA_ACTIVE_HIGH);
-	vsync_pol = !!(bus->flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH);
+	/*
+	 * This hardware uses [HV]REF instead of [HV]SYNC. Based on the
+	 * provided timing diagrams in the manual, positive polarity
+	 * equals active high [HV]REF.
+	 *
+	 * When the back porch is 0, [HV]REF is more or less equivalent
+	 * to [HV]SYNC inverted.
+	 */
+	href_pol = !!(bus->flags & V4L2_MBUS_HSYNC_ACTIVE_LOW);
+	vref_pol = !!(bus->flags & V4L2_MBUS_VSYNC_ACTIVE_LOW);
+	pclk_pol = !!(bus->flags & V4L2_MBUS_PCLK_SAMPLE_RISING);
 	writel(CSI_CFG_INPUT_FMT(csi_fmt->input) |
 	       CSI_CFG_OUTPUT_FMT(csi_fmt->output) |
-	       CSI_CFG_VSYNC_POL(vsync_pol) |
-	       CSI_CFG_HSYNC_POL(hsync_pol) |
+	       CSI_CFG_VREF_POL(vref_pol) |
+	       CSI_CFG_HREF_POL(href_pol) |
 	       CSI_CFG_PCLK_POL(pclk_pol),
 	       csi->regs + CSI_CFG_REG);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c
@@ -151,8 +151,10 @@
 	}
 
 	subdev = sun6i_video_remote_subdev(video, NULL);
-	if (!subdev)
+	if (!subdev) {
+		ret = -EINVAL;
 		goto stop_media_pipeline;
+	}
 
 	config.pixelformat = video->fmt.fmt.pix.pixelformat;
 	config.code = video->mbus_code;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/tegra-cec/tegra_cec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/tegra-cec/tegra_cec.c
@@ -366,7 +366,11 @@
 		return -ENOENT;
 	}
 
-	clk_prepare_enable(cec->clk);
+	ret = clk_prepare_enable(cec->clk);
+	if (ret) {
+		dev_err(&pdev->dev, "Unable to prepare clock for CEC\n");
+		return ret;
+	}
 
 	/* set context info. */
 	cec->dev = &pdev->dev;
@@ -446,9 +450,7 @@
 
 	dev_notice(&pdev->dev, "Resuming\n");
 
-	clk_prepare_enable(cec->clk);
-
-	return 0;
+	return clk_prepare_enable(cec->clk);
 }
 #endif
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/ti-vpe/cal.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/ti-vpe/cal.c
@@ -266,8 +266,6 @@
 	struct v4l2_subdev	*sensor;
 	struct v4l2_fwnode_endpoint	endpoint;
 
-	struct v4l2_async_subdev asd;
-
 	struct v4l2_fh		fh;
 	struct cal_dev		*dev;
 	struct cc_data		*cc;
@@ -537,16 +535,16 @@
 
 static void disable_irqs(struct cal_ctx *ctx)
 {
+	u32 val;
+
 	/* Disable IRQ_WDMA_END 0/1 */
-	reg_write_field(ctx->dev,
-			CAL_HL_IRQENABLE_CLR(2),
-			CAL_HL_IRQ_CLEAR,
-			CAL_HL_IRQ_MASK(ctx->csi2_port));
+	val = 0;
+	set_field(&val, CAL_HL_IRQ_CLEAR, CAL_HL_IRQ_MASK(ctx->csi2_port));
+	reg_write(ctx->dev, CAL_HL_IRQENABLE_CLR(2), val);
 	/* Disable IRQ_WDMA_START 0/1 */
-	reg_write_field(ctx->dev,
-			CAL_HL_IRQENABLE_CLR(3),
-			CAL_HL_IRQ_CLEAR,
-			CAL_HL_IRQ_MASK(ctx->csi2_port));
+	val = 0;
+	set_field(&val, CAL_HL_IRQ_CLEAR, CAL_HL_IRQ_MASK(ctx->csi2_port));
+	reg_write(ctx->dev, CAL_HL_IRQENABLE_CLR(3), val);
 	/* Todo: Add VC_IRQ and CSI2_COMPLEXIO_IRQ handling */
 	reg_write(ctx->dev, CAL_CSI2_VC_IRQENABLE(1), 0);
 }
@@ -680,12 +678,13 @@
 }
 
 static void cal_wr_dma_config(struct cal_ctx *ctx,
-			      unsigned int width)
+			      unsigned int width, unsigned int height)
 {
 	u32 val;
 
 	val = reg_read(ctx->dev, CAL_WR_DMA_CTRL(ctx->csi2_port));
 	set_field(&val, ctx->csi2_port, CAL_WR_DMA_CTRL_CPORT_MASK);
+	set_field(&val, height, CAL_WR_DMA_CTRL_YSIZE_MASK);
 	set_field(&val, CAL_WR_DMA_CTRL_DTAG_PIX_DAT,
 		  CAL_WR_DMA_CTRL_DTAG_MASK);
 	set_field(&val, CAL_WR_DMA_CTRL_MODE_CONST,
@@ -1308,7 +1307,8 @@
 	csi2_lane_config(ctx);
 	csi2_ctx_config(ctx);
 	pix_proc_config(ctx);
-	cal_wr_dma_config(ctx, ctx->v_fmt.fmt.pix.bytesperline);
+	cal_wr_dma_config(ctx, ctx->v_fmt.fmt.pix.bytesperline,
+			  ctx->v_fmt.fmt.pix.height);
 	cal_wr_dma_addr(ctx, addr);
 	csi2_ppi_enable(ctx);
 
@@ -1648,7 +1648,6 @@
 
 	parent = pdev->dev.of_node;
 
-	asd = &ctx->asd;
 	endpoint = &ctx->endpoint;
 
 	ep_node = NULL;
@@ -1695,8 +1694,6 @@
 		ctx_dbg(3, ctx, "can't get remote parent\n");
 		goto cleanup_exit;
 	}
-	asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
-	asd->match.fwnode = of_fwnode_handle(sensor_node);
 
 	v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep_node), endpoint);
 
@@ -1726,9 +1723,17 @@
 
 	v4l2_async_notifier_init(&ctx->notifier);
 
+	asd = kzalloc(sizeof(*asd), GFP_KERNEL);
+	if (!asd)
+		goto cleanup_exit;
+
+	asd->match_type = V4L2_ASYNC_MATCH_FWNODE;
+	asd->match.fwnode = of_fwnode_handle(sensor_node);
+
 	ret = v4l2_async_notifier_add_subdev(&ctx->notifier, asd);
 	if (ret) {
 		ctx_err(ctx, "Error adding asd\n");
+		kfree(asd);
 		goto cleanup_exit;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/ti-vpe/vpdma.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/ti-vpe/vpdma.h
@@ -57,6 +57,7 @@
 						 * line stride of source and dest
 						 * buffers should be 16 byte aligned
 						 */
+#define VPDMA_MAX_STRIDE		65520	/* Max line stride 16 byte aligned */
 #define VPDMA_DTD_DESC_SIZE		32	/* 8 words */
 #define VPDMA_CFD_CTD_DESC_SIZE		16	/* 4 words */
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/ti-vpe/vpe.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/ti-vpe/vpe.c
@@ -338,20 +338,25 @@
 };
 
 /* find our format description corresponding to the passed v4l2_format */
-static struct vpe_fmt *find_format(struct v4l2_format *f)
+static struct vpe_fmt *__find_format(u32 fourcc)
 {
 	struct vpe_fmt *fmt;
 	unsigned int k;
 
 	for (k = 0; k < ARRAY_SIZE(vpe_formats); k++) {
 		fmt = &vpe_formats[k];
-		if (fmt->fourcc == f->fmt.pix.pixelformat)
+		if (fmt->fourcc == fourcc)
 			return fmt;
 	}
 
 	return NULL;
 }
 
+static struct vpe_fmt *find_format(struct v4l2_format *f)
+{
+	return __find_format(f->fmt.pix.pixelformat);
+}
+
 /*
  * there is one vpe_dev structure in the driver, it is shared by
  * all instances.
@@ -1013,11 +1018,14 @@
 	dma_addr_t dma_addr;
 	u32 flags = 0;
 	u32 offset = 0;
+	u32 stride;
 
 	if (port == VPE_PORT_MV_OUT) {
 		vpdma_fmt = &vpdma_misc_fmts[VPDMA_DATA_FMT_MV];
 		dma_addr = ctx->mv_buf_dma[mv_buf_selector];
 		q_data = &ctx->q_data[Q_DATA_SRC];
+		stride = ALIGN((q_data->width * vpdma_fmt->depth) >> 3,
+			       VPDMA_STRIDE_ALIGN);
 	} else {
 		/* to incorporate interleaved formats */
 		int plane = fmt->coplanar ? p_data->vb_part : 0;
@@ -1044,6 +1052,7 @@
 		}
 		/* Apply the offset */
 		dma_addr += offset;
+		stride = q_data->bytesperline[VPE_LUMA];
 	}
 
 	if (q_data->flags & Q_DATA_FRAME_1D)
@@ -1055,7 +1064,7 @@
 			   MAX_W, MAX_H);
 
 	vpdma_add_out_dtd(&ctx->desc_list, q_data->width,
-			  q_data->bytesperline[VPE_LUMA], &q_data->c_rect,
+			  stride, &q_data->c_rect,
 			  vpdma_fmt, dma_addr, MAX_OUT_WIDTH_REG1,
 			  MAX_OUT_HEIGHT_REG1, p_data->channel, flags);
 }
@@ -1074,10 +1083,13 @@
 	dma_addr_t dma_addr;
 	u32 flags = 0;
 	u32 offset = 0;
+	u32 stride;
 
 	if (port == VPE_PORT_MV_IN) {
 		vpdma_fmt = &vpdma_misc_fmts[VPDMA_DATA_FMT_MV];
 		dma_addr = ctx->mv_buf_dma[mv_buf_selector];
+		stride = ALIGN((q_data->width * vpdma_fmt->depth) >> 3,
+			       VPDMA_STRIDE_ALIGN);
 	} else {
 		/* to incorporate interleaved formats */
 		int plane = fmt->coplanar ? p_data->vb_part : 0;
@@ -1104,6 +1116,7 @@
 		}
 		/* Apply the offset */
 		dma_addr += offset;
+		stride = q_data->bytesperline[VPE_LUMA];
 
 		if (q_data->flags & Q_DATA_INTERLACED_SEQ_TB) {
 			/*
@@ -1139,10 +1152,10 @@
 	if (p_data->vb_part && fmt->fourcc == V4L2_PIX_FMT_NV12)
 		frame_height /= 2;
 
-	vpdma_add_in_dtd(&ctx->desc_list, q_data->width,
-			 q_data->bytesperline[VPE_LUMA], &q_data->c_rect,
-		vpdma_fmt, dma_addr, p_data->channel, field, flags, frame_width,
-		frame_height, 0, 0);
+	vpdma_add_in_dtd(&ctx->desc_list, q_data->width, stride,
+			 &q_data->c_rect, vpdma_fmt, dma_addr,
+			 p_data->channel, field, flags, frame_width,
+			 frame_height, 0, 0);
 }
 
 /*
@@ -1391,9 +1404,6 @@
 	 /* the previous dst mv buffer becomes the next src mv buffer */
 	ctx->src_mv_buf_selector = !ctx->src_mv_buf_selector;
 
-	if (ctx->aborting)
-		goto finished;
-
 	s_vb = ctx->src_vbs[0];
 	d_vb = ctx->dst_vb;
 
@@ -1404,6 +1414,7 @@
 		d_vb->timecode = s_vb->timecode;
 
 	d_vb->sequence = ctx->sequence;
+	s_vb->sequence = ctx->sequence;
 
 	d_q_data = &ctx->q_data[Q_DATA_DST];
 	if (d_q_data->flags & Q_IS_INTERLACED) {
@@ -1457,6 +1468,9 @@
 	ctx->src_vbs[0] = NULL;
 	ctx->dst_vb = NULL;
 
+	if (ctx->aborting)
+		goto finished;
+
 	ctx->bufs_completed++;
 	if (ctx->bufs_completed < ctx->bufs_per_job && job_ready(ctx)) {
 		device_run(ctx);
@@ -1566,9 +1580,9 @@
 	unsigned int stride = 0;
 
 	if (!fmt || !(fmt->types & type)) {
-		vpe_err(ctx->dev, "Fourcc format (0x%08x) invalid.\n",
+		vpe_dbg(ctx->dev, "Fourcc format (0x%08x) invalid.\n",
 			pix->pixelformat);
-		return -EINVAL;
+		fmt = __find_format(V4L2_PIX_FMT_YUYV);
 	}
 
 	if (pix->field != V4L2_FIELD_NONE && pix->field != V4L2_FIELD_ALTERNATE
@@ -1615,7 +1629,7 @@
 			      &pix->height, MIN_H, MAX_H, H_ALIGN,
 			      S_ALIGN);
 
-	if (!pix->num_planes)
+	if (!pix->num_planes || pix->num_planes > 2)
 		pix->num_planes = fmt->coplanar ? 2 : 1;
 	else if (pix->num_planes > 1 && !fmt->coplanar)
 		pix->num_planes = 1;
@@ -1654,6 +1668,10 @@
 		if (stride > plane_fmt->bytesperline)
 			plane_fmt->bytesperline = stride;
 
+		plane_fmt->bytesperline = clamp_t(u32, plane_fmt->bytesperline,
+						  stride,
+						  VPDMA_MAX_STRIDE);
+
 		plane_fmt->bytesperline = ALIGN(plane_fmt->bytesperline,
 						VPDMA_STRIDE_ALIGN);
 
@@ -2274,7 +2292,7 @@
 	v4l2_ctrl_handler_setup(hdl);
 
 	s_q_data = &ctx->q_data[Q_DATA_SRC];
-	s_q_data->fmt = &vpe_formats[2];
+	s_q_data->fmt = __find_format(V4L2_PIX_FMT_YUYV);
 	s_q_data->width = 1920;
 	s_q_data->height = 1080;
 	s_q_data->nplanes = 1;
@@ -2352,6 +2370,12 @@
 
 	mutex_lock(&dev->dev_mutex);
 	free_mv_buffers(ctx);
+
+	vpdma_unmap_desc_buf(dev->vpdma, &ctx->desc_list.buf);
+	vpdma_unmap_desc_buf(dev->vpdma, &ctx->mmr_adb);
+	vpdma_unmap_desc_buf(dev->vpdma, &ctx->sc_coeff_h);
+	vpdma_unmap_desc_buf(dev->vpdma, &ctx->sc_coeff_v);
+
 	vpdma_free_desc_list(&ctx->desc_list);
 	vpdma_free_desc_buf(&ctx->mmr_adb);
 
@@ -2411,6 +2435,8 @@
 
 	r = pm_runtime_get_sync(&pdev->dev);
 	WARN_ON(r < 0);
+	if (r)
+		pm_runtime_put_noidle(&pdev->dev);
 	return r < 0 ? r : 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/vicodec/codec-v4l2-fwht.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/vicodec/codec-v4l2-fwht.c
@@ -27,17 +27,17 @@
 	{ V4L2_PIX_FMT_BGR24,   3, 3, 1, 3, 3, 1, 1, 3, 1, FWHT_FL_PIXENC_RGB},
 	{ V4L2_PIX_FMT_RGB24,   3, 3, 1, 3, 3, 1, 1, 3, 1, FWHT_FL_PIXENC_RGB},
 	{ V4L2_PIX_FMT_HSV24,   3, 3, 1, 3, 3, 1, 1, 3, 1, FWHT_FL_PIXENC_HSV},
-	{ V4L2_PIX_FMT_BGR32,   4, 4, 1, 4, 4, 1, 1, 3, 1, FWHT_FL_PIXENC_RGB},
-	{ V4L2_PIX_FMT_XBGR32,  4, 4, 1, 4, 4, 1, 1, 3, 1, FWHT_FL_PIXENC_RGB},
+	{ V4L2_PIX_FMT_BGR32,   4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
+	{ V4L2_PIX_FMT_XBGR32,  4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
 	{ V4L2_PIX_FMT_ABGR32,  4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
-	{ V4L2_PIX_FMT_RGB32,   4, 4, 1, 4, 4, 1, 1, 3, 1, FWHT_FL_PIXENC_RGB},
-	{ V4L2_PIX_FMT_XRGB32,  4, 4, 1, 4, 4, 1, 1, 3, 1, FWHT_FL_PIXENC_RGB},
+	{ V4L2_PIX_FMT_RGB32,   4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
+	{ V4L2_PIX_FMT_XRGB32,  4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
 	{ V4L2_PIX_FMT_ARGB32,  4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
-	{ V4L2_PIX_FMT_BGRX32,  4, 4, 1, 4, 4, 1, 1, 3, 1, FWHT_FL_PIXENC_RGB},
+	{ V4L2_PIX_FMT_BGRX32,  4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
 	{ V4L2_PIX_FMT_BGRA32,  4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
-	{ V4L2_PIX_FMT_RGBX32,  4, 4, 1, 4, 4, 1, 1, 3, 1, FWHT_FL_PIXENC_RGB},
+	{ V4L2_PIX_FMT_RGBX32,  4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
 	{ V4L2_PIX_FMT_RGBA32,  4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_RGB},
-	{ V4L2_PIX_FMT_HSV32,   4, 4, 1, 4, 4, 1, 1, 3, 1, FWHT_FL_PIXENC_HSV},
+	{ V4L2_PIX_FMT_HSV32,   4, 4, 1, 4, 4, 1, 1, 4, 1, FWHT_FL_PIXENC_HSV},
 	{ V4L2_PIX_FMT_GREY,    1, 1, 1, 1, 0, 1, 1, 1, 1, FWHT_FL_PIXENC_RGB},
 };
 
@@ -175,22 +175,14 @@
 	case V4L2_PIX_FMT_RGB32:
 	case V4L2_PIX_FMT_XRGB32:
 	case V4L2_PIX_FMT_HSV32:
-		rf->cr = rf->luma + 1;
-		rf->cb = rf->cr + 2;
-		rf->luma += 2;
-		break;
-	case V4L2_PIX_FMT_BGR32:
-	case V4L2_PIX_FMT_XBGR32:
-		rf->cb = rf->luma;
-		rf->cr = rf->cb + 2;
-		rf->luma++;
-		break;
 	case V4L2_PIX_FMT_ARGB32:
 		rf->alpha = rf->luma;
 		rf->cr = rf->luma + 1;
 		rf->cb = rf->cr + 2;
 		rf->luma += 2;
 		break;
+	case V4L2_PIX_FMT_BGR32:
+	case V4L2_PIX_FMT_XBGR32:
 	case V4L2_PIX_FMT_ABGR32:
 		rf->cb = rf->luma;
 		rf->cr = rf->cb + 2;
@@ -198,10 +190,6 @@
 		rf->alpha = rf->cr + 1;
 		break;
 	case V4L2_PIX_FMT_BGRX32:
-		rf->cb = rf->luma + 1;
-		rf->cr = rf->cb + 2;
-		rf->luma += 2;
-		break;
 	case V4L2_PIX_FMT_BGRA32:
 		rf->alpha = rf->luma;
 		rf->cb = rf->luma + 1;
@@ -209,10 +197,6 @@
 		rf->luma += 2;
 		break;
 	case V4L2_PIX_FMT_RGBX32:
-		rf->cr = rf->luma;
-		rf->cb = rf->cr + 2;
-		rf->luma++;
-		break;
 	case V4L2_PIX_FMT_RGBA32:
 		rf->alpha = rf->luma + 3;
 		rf->cr = rf->luma;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/vicodec/vicodec-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/vicodec/vicodec-core.c
@@ -2052,6 +2052,7 @@
 	}
 	ctrl = v4l2_ctrl_request_hdl_ctrl_find(hdl,
 					       vicodec_ctrl_stateless_state.id);
+	v4l2_ctrl_request_hdl_put(hdl);
 	if (!ctrl) {
 		v4l2_info(&ctx->dev->v4l2_dev,
 			  "Missing required codec control\n");
@@ -2139,6 +2140,9 @@
 	v4l2_m2m_release(dev->stateful_enc.m2m_dev);
 	v4l2_m2m_release(dev->stateful_dec.m2m_dev);
 	v4l2_m2m_release(dev->stateless_dec.m2m_dev);
+#ifdef CONFIG_MEDIA_CONTROLLER
+	media_device_cleanup(&dev->mdev);
+#endif
 	kfree(dev);
 }
 
@@ -2169,16 +2173,19 @@
 
 	platform_set_drvdata(pdev, dev);
 
-	if (register_instance(dev, &dev->stateful_enc,
-			      "stateful-encoder", true))
+	ret = register_instance(dev, &dev->stateful_enc, "stateful-encoder",
+				true);
+	if (ret)
 		goto unreg_dev;
 
-	if (register_instance(dev, &dev->stateful_dec,
-			      "stateful-decoder", false))
+	ret = register_instance(dev, &dev->stateful_dec, "stateful-decoder",
+				false);
+	if (ret)
 		goto unreg_sf_enc;
 
-	if (register_instance(dev, &dev->stateless_dec,
-			      "stateless-decoder", false))
+	ret = register_instance(dev, &dev->stateless_dec, "stateless-decoder",
+				false);
+	if (ret)
 		goto unreg_sf_dec;
 
 #ifdef CONFIG_MEDIA_CONTROLLER
@@ -2250,7 +2257,6 @@
 	v4l2_m2m_unregister_media_controller(dev->stateful_enc.m2m_dev);
 	v4l2_m2m_unregister_media_controller(dev->stateful_dec.m2m_dev);
 	v4l2_m2m_unregister_media_controller(dev->stateless_dec.m2m_dev);
-	media_device_cleanup(&dev->mdev);
 #endif
 
 	video_unregister_device(&dev->stateful_enc.vfd);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/vim2m.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/vim2m.c
@@ -1073,6 +1073,9 @@
 	if (!q_data)
 		return -EINVAL;
 
+	if (V4L2_TYPE_IS_OUTPUT(q->type))
+		ctx->aborting = 0;
+
 	q_data->sequence = 0;
 	return 0;
 }
@@ -1272,6 +1275,9 @@
 
 	v4l2_device_unregister(&dev->v4l2_dev);
 	v4l2_m2m_release(dev->m2m_dev);
+#ifdef CONFIG_MEDIA_CONTROLLER
+	media_device_cleanup(&dev->mdev);
+#endif
 	kfree(dev);
 }
 
@@ -1327,12 +1333,6 @@
 	vfd->lock = &dev->dev_mutex;
 	vfd->v4l2_dev = &dev->v4l2_dev;
 
-	ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
-	if (ret) {
-		v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
-		goto error_v4l2;
-	}
-
 	video_set_drvdata(vfd, dev);
 	v4l2_info(&dev->v4l2_dev,
 		  "Device registered as /dev/video%d\n", vfd->num);
@@ -1343,6 +1343,7 @@
 	if (IS_ERR(dev->m2m_dev)) {
 		v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n");
 		ret = PTR_ERR(dev->m2m_dev);
+		dev->m2m_dev = NULL;
 		goto error_dev;
 	}
 
@@ -1354,12 +1355,20 @@
 	media_device_init(&dev->mdev);
 	dev->mdev.ops = &m2m_media_ops;
 	dev->v4l2_dev.mdev = &dev->mdev;
+#endif
 
+	ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
+	if (ret) {
+		v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
+		goto error_m2m;
+	}
+
+#ifdef CONFIG_MEDIA_CONTROLLER
 	ret = v4l2_m2m_register_media_controller(dev->m2m_dev, vfd,
 						 MEDIA_ENT_F_PROC_VIDEO_SCALER);
 	if (ret) {
 		v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem media controller\n");
-		goto error_dev;
+		goto error_v4l2;
 	}
 
 	ret = media_device_register(&dev->mdev);
@@ -1374,11 +1383,13 @@
 error_m2m_mc:
 	v4l2_m2m_unregister_media_controller(dev->m2m_dev);
 #endif
-error_dev:
+error_v4l2:
 	video_unregister_device(&dev->vfd);
 	/* vim2m_device_release called by video_unregister_device to release various objects */
 	return ret;
-error_v4l2:
+error_m2m:
+	v4l2_m2m_release(dev->m2m_dev);
+error_dev:
 	v4l2_device_unregister(&dev->v4l2_dev);
 error_free:
 	kfree(dev);
@@ -1395,7 +1406,6 @@
 #ifdef CONFIG_MEDIA_CONTROLLER
 	media_device_unregister(&dev->mdev);
 	v4l2_m2m_unregister_media_controller(dev->m2m_dev);
-	media_device_cleanup(&dev->mdev);
 #endif
 	video_unregister_device(&dev->vfd);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/vimc/vimc-common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/vimc/vimc-common.c
@@ -375,7 +375,7 @@
 {
 	int ret;
 
-	/* Allocate the pads */
+	/* Allocate the pads. Should be released from the sd_int_op release */
 	ved->pads = vimc_pads_init(num_pads, pads_flag);
 	if (IS_ERR(ved->pads))
 		return PTR_ERR(ved->pads);
@@ -424,7 +424,6 @@
 void vimc_ent_sd_unregister(struct vimc_ent_device *ved, struct v4l2_subdev *sd)
 {
 	media_entity_cleanup(ved->ent);
-	vimc_pads_cleanup(ved->pads);
 	v4l2_device_unregister_subdev(sd);
 }
 EXPORT_SYMBOL_GPL(vimc_ent_sd_unregister);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/vimc/vimc-debayer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/vimc/vimc-debayer.c
@@ -484,6 +484,7 @@
 	struct vimc_deb_device *vdeb =
 				container_of(sd, struct vimc_deb_device, sd);
 
+	vimc_pads_cleanup(vdeb->ved.pads);
 	kfree(vdeb);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/vimc/vimc-scaler.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/vimc/vimc-scaler.c
@@ -343,6 +343,7 @@
 	struct vimc_sca_device *vsca =
 				container_of(sd, struct vimc_sca_device, sd);
 
+	vimc_pads_cleanup(vsca->ved.pads);
 	kfree(vsca);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/vimc/vimc-sensor.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/vimc/vimc-sensor.c
@@ -25,7 +25,6 @@
 	struct v4l2_subdev sd;
 	struct device *dev;
 	struct tpg_data tpg;
-	struct task_struct *kthread_sen;
 	u8 *frame;
 	/* The active format */
 	struct v4l2_mbus_framefmt mbus_format;
@@ -208,10 +207,6 @@
 		const struct vimc_pix_map *vpix;
 		unsigned int frame_size;
 
-		if (vsen->kthread_sen)
-			/* tpg is already executing */
-			return 0;
-
 		/* Calculate the frame size */
 		vpix = vimc_pix_map_by_code(vsen->mbus_format.code);
 		frame_size = vsen->mbus_format.width * vpix->bpp *
@@ -297,6 +292,7 @@
 
 	v4l2_ctrl_handler_free(&vsen->hdl);
 	tpg_free(&vsen->tpg);
+	vimc_pads_cleanup(vsen->ved.pads);
 	kfree(vsen);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/vivid/vivid-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/vivid/vivid-core.c
@@ -174,13 +174,13 @@
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x7b,
 
-	0x02, 0x03, 0x3f, 0xf0, 0x51, 0x61, 0x60, 0x5f,
+	0x02, 0x03, 0x3f, 0xf1, 0x51, 0x61, 0x60, 0x5f,
 	0x5e, 0x5d, 0x10, 0x1f, 0x04, 0x13, 0x22, 0x21,
 	0x20, 0x05, 0x14, 0x02, 0x11, 0x01, 0x23, 0x09,
 	0x07, 0x07, 0x83, 0x01, 0x00, 0x00, 0x6d, 0x03,
 	0x0c, 0x00, 0x10, 0x00, 0x00, 0x3c, 0x21, 0x00,
 	0x60, 0x01, 0x02, 0x03, 0x67, 0xd8, 0x5d, 0xc4,
-	0x01, 0x78, 0x00, 0x00, 0xe2, 0x00, 0xea, 0xe3,
+	0x01, 0x78, 0x00, 0x00, 0xe2, 0x00, 0xca, 0xe3,
 	0x05, 0x00, 0x00, 0xe3, 0x06, 0x01, 0x00, 0x4d,
 	0xd0, 0x00, 0xa0, 0xf0, 0x70, 0x3e, 0x80, 0x30,
 	0x20, 0x35, 0x00, 0xc0, 0x1c, 0x32, 0x00, 0x00,
@@ -189,7 +189,7 @@
 	0x00, 0x00, 0x1a, 0x1a, 0x1d, 0x00, 0x80, 0x51,
 	0xd0, 0x1c, 0x20, 0x40, 0x80, 0x35, 0x00, 0xc0,
 	0x1c, 0x32, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82,
 };
 
 static int vidioc_querycap(struct file *file, void  *priv,
@@ -297,6 +297,28 @@
 	return vivid_vid_out_g_fbuf(file, fh, a);
 }
 
+/*
+ * Only support the framebuffer of one of the vivid instances.
+ * Anything else is rejected.
+ */
+bool vivid_validate_fb(const struct v4l2_framebuffer *a)
+{
+	struct vivid_dev *dev;
+	int i;
+
+	for (i = 0; i < n_devs; i++) {
+		dev = vivid_devs[i];
+		if (!dev || !dev->video_pbase)
+			continue;
+		if ((unsigned long)a->base == dev->video_pbase &&
+		    a->fmt.width <= dev->display_width &&
+		    a->fmt.height <= dev->display_height &&
+		    a->fmt.bytesperline <= dev->display_byte_stride)
+			return true;
+	}
+	return false;
+}
+
 static int vidioc_s_fbuf(struct file *file, void *fh, const struct v4l2_framebuffer *a)
 {
 	struct video_device *vdev = video_devdata(file);
@@ -616,6 +638,9 @@
 
 	vivid_free_controls(dev);
 	v4l2_device_unregister(&dev->v4l2_dev);
+#ifdef CONFIG_MEDIA_CONTROLLER
+	media_device_cleanup(&dev->mdev);
+#endif
 	vfree(dev->scaled_line);
 	vfree(dev->blended_line);
 	vfree(dev->edid);
@@ -1580,7 +1605,6 @@
 
 #ifdef CONFIG_MEDIA_CONTROLLER
 		media_device_unregister(&dev->mdev);
-		media_device_cleanup(&dev->mdev);
 #endif
 
 		if (dev->has_vid_cap) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/vivid/vivid-core.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/vivid/vivid-core.h
@@ -564,4 +564,6 @@
 	return dev->output_type[dev->output] == HDMI;
 }
 
+bool vivid_validate_fb(const struct v4l2_framebuffer *a);
+
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/vivid/vivid-kthread-cap.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/vivid/vivid-kthread-cap.c
@@ -796,7 +796,11 @@
 		if (kthread_should_stop())
 			break;
 
-		mutex_lock(&dev->mutex);
+		if (!mutex_trylock(&dev->mutex)) {
+			schedule_timeout_uninterruptible(1);
+			continue;
+		}
+
 		cur_jiffies = jiffies;
 		if (dev->cap_seq_resync) {
 			dev->jiffies_vid_cap = cur_jiffies;
@@ -956,8 +960,6 @@
 
 	/* shutdown control thread */
 	vivid_grab_controls(dev, false);
-	mutex_unlock(&dev->mutex);
 	kthread_stop(dev->kthread_vid_cap);
 	dev->kthread_vid_cap = NULL;
-	mutex_lock(&dev->mutex);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/vivid/vivid-kthread-out.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/vivid/vivid-kthread-out.c
@@ -143,7 +143,11 @@
 		if (kthread_should_stop())
 			break;
 
-		mutex_lock(&dev->mutex);
+		if (!mutex_trylock(&dev->mutex)) {
+			schedule_timeout_uninterruptible(1);
+			continue;
+		}
+
 		cur_jiffies = jiffies;
 		if (dev->out_seq_resync) {
 			dev->jiffies_vid_out = cur_jiffies;
@@ -301,8 +305,6 @@
 
 	/* shutdown control thread */
 	vivid_grab_controls(dev, false);
-	mutex_unlock(&dev->mutex);
 	kthread_stop(dev->kthread_vid_out);
 	dev->kthread_vid_out = NULL;
-	mutex_lock(&dev->mutex);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/vivid/vivid-rds-gen.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/vivid/vivid-rds-gen.c
@@ -145,7 +145,7 @@
 	rds->ta = alt;
 	rds->ms = true;
 	snprintf(rds->psname, sizeof(rds->psname), "%6d.%1d",
-		 freq / 16, ((freq & 0xf) * 10) / 16);
+		 (freq / 16) % 1000000, (((freq & 0xf) * 10) / 16) % 10);
 	if (alt)
 		strscpy(rds->radiotext,
 			" The Radio Data System can switch between different Radio Texts ",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/vivid/vivid-sdr-cap.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/vivid/vivid-sdr-cap.c
@@ -141,7 +141,11 @@
 		if (kthread_should_stop())
 			break;
 
-		mutex_lock(&dev->mutex);
+		if (!mutex_trylock(&dev->mutex)) {
+			schedule_timeout_uninterruptible(1);
+			continue;
+		}
+
 		cur_jiffies = jiffies;
 		if (dev->sdr_cap_seq_resync) {
 			dev->jiffies_sdr_cap = cur_jiffies;
@@ -303,10 +307,8 @@
 	}
 
 	/* shutdown control thread */
-	mutex_unlock(&dev->mutex);
 	kthread_stop(dev->kthread_sdr_cap);
 	dev->kthread_sdr_cap = NULL;
-	mutex_lock(&dev->mutex);
 }
 
 static void sdr_cap_buf_request_complete(struct vb2_buffer *vb)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/vivid/vivid-vid-cap.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/vivid/vivid-vid-cap.c
@@ -223,9 +223,6 @@
 	if (vb2_is_streaming(&dev->vb_vid_out_q))
 		dev->can_loop_video = vivid_vid_can_loop(dev);
 
-	if (dev->kthread_vid_cap)
-		return 0;
-
 	dev->vid_cap_seq_count = 0;
 	dprintk(dev, 1, "%s\n", __func__);
 	for (i = 0; i < VIDEO_MAX_FRAME; i++)
@@ -455,6 +452,12 @@
 	tpg_reset_source(&dev->tpg, dev->src_rect.width, dev->src_rect.height, dev->field_cap);
 	dev->crop_cap = dev->src_rect;
 	dev->crop_bounds_cap = dev->src_rect;
+	if (dev->bitmap_cap &&
+	    (dev->compose_cap.width != dev->crop_cap.width ||
+	     dev->compose_cap.height != dev->crop_cap.height)) {
+		vfree(dev->bitmap_cap);
+		dev->bitmap_cap = NULL;
+	}
 	dev->compose_cap = dev->crop_cap;
 	if (V4L2_FIELD_HAS_T_OR_B(dev->field_cap))
 		dev->compose_cap.height /= 2;
@@ -886,6 +889,8 @@
 	struct vivid_dev *dev = video_drvdata(file);
 	struct v4l2_rect *crop = &dev->crop_cap;
 	struct v4l2_rect *compose = &dev->compose_cap;
+	unsigned orig_compose_w = compose->width;
+	unsigned orig_compose_h = compose->height;
 	unsigned factor = V4L2_FIELD_HAS_T_OR_B(dev->field_cap) ? 2 : 1;
 	int ret;
 
@@ -930,6 +935,7 @@
 			if (dev->has_compose_cap) {
 				v4l2_rect_set_min_size(compose, &min_rect);
 				v4l2_rect_set_max_size(compose, &max_rect);
+				v4l2_rect_map_inside(compose, &fmt);
 			}
 			dev->fmt_cap_rect = fmt;
 			tpg_s_buf_height(&dev->tpg, fmt.height);
@@ -1002,17 +1008,17 @@
 			s->r.height /= factor;
 		}
 		v4l2_rect_map_inside(&s->r, &dev->fmt_cap_rect);
-		if (dev->bitmap_cap && (compose->width != s->r.width ||
-					compose->height != s->r.height)) {
-			vfree(dev->bitmap_cap);
-			dev->bitmap_cap = NULL;
-		}
 		*compose = s->r;
 		break;
 	default:
 		return -EINVAL;
 	}
 
+	if (dev->bitmap_cap && (compose->width != orig_compose_w ||
+				compose->height != orig_compose_h)) {
+		vfree(dev->bitmap_cap);
+		dev->bitmap_cap = NULL;
+	}
 	tpg_s_crop_compose(&dev->tpg, crop, compose);
 	return 0;
 }
@@ -1253,7 +1259,14 @@
 		return -EINVAL;
 	if (a->fmt.bytesperline < (a->fmt.width * fmt->bit_depth[0]) / 8)
 		return -EINVAL;
-	if (a->fmt.height * a->fmt.bytesperline < a->fmt.sizeimage)
+	if (a->fmt.bytesperline > a->fmt.sizeimage / a->fmt.height)
+		return -EINVAL;
+
+	/*
+	 * Only support the framebuffer of one of the vivid instances.
+	 * Anything else is rejected.
+	 */
+	if (!vivid_validate_fb(a))
 		return -EINVAL;
 
 	dev->fb_vbase_cap = phys_to_virt((unsigned long)a->base);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/vivid/vivid-vid-out.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/vivid/vivid-vid-out.c
@@ -161,9 +161,6 @@
 	if (vb2_is_streaming(&dev->vb_vid_cap_q))
 		dev->can_loop_video = vivid_vid_can_loop(dev);
 
-	if (dev->kthread_vid_out)
-		return 0;
-
 	dev->vid_out_seq_count = 0;
 	dprintk(dev, 1, "%s\n", __func__);
 	if (dev->start_streaming_error) {
@@ -1028,7 +1025,7 @@
 		return -EINVAL;
 	}
 	dev->fbuf_out_flags &= ~(chroma_flags | alpha_flags);
-	dev->fbuf_out_flags = a->flags & (chroma_flags | alpha_flags);
+	dev->fbuf_out_flags |= a->flags & (chroma_flags | alpha_flags);
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/vsp1/vsp1_dl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/vsp1/vsp1_dl.c
@@ -431,6 +431,8 @@
 	if (!pool)
 		return NULL;
 
+	pool->vsp1 = vsp1;
+
 	spin_lock_init(&pool->lock);
 	INIT_LIST_HEAD(&pool->free);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/vsp1/vsp1_drm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/vsp1/vsp1_drm.c
@@ -245,7 +245,7 @@
 		brx = &vsp1->bru->entity;
 	else if (pipe->brx && !drm_pipe->force_brx_release)
 		brx = pipe->brx;
-	else if (!vsp1->bru->entity.pipe)
+	else if (vsp1_feature(vsp1, VSP1_HAS_BRU) && !vsp1->bru->entity.pipe)
 		brx = &vsp1->bru->entity;
 	else
 		brx = &vsp1->brs->entity;
@@ -462,9 +462,9 @@
 	 * make sure it is present in the pipeline's list of entities if it
 	 * wasn't already.
 	 */
-	if (!use_uif) {
+	if (drm_pipe->uif && !use_uif) {
 		drm_pipe->uif->pipe = NULL;
-	} else if (!drm_pipe->uif->pipe) {
+	} else if (drm_pipe->uif && !drm_pipe->uif->pipe) {
 		drm_pipe->uif->pipe = pipe;
 		list_add_tail(&drm_pipe->uif->list_pipe, &pipe->entities);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/vsp1/vsp1_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/vsp1/vsp1_drv.c
@@ -562,7 +562,12 @@
 	int ret;
 
 	ret = pm_runtime_get_sync(vsp1->dev);
-	return ret < 0 ? ret : 0;
+	if (ret < 0) {
+		pm_runtime_put_noidle(vsp1->dev);
+		return ret;
+	}
+
+	return 0;
 }
 
 /*
@@ -845,12 +850,12 @@
 	/* Configure device parameters based on the version register. */
 	pm_runtime_enable(&pdev->dev);
 
-	ret = pm_runtime_get_sync(&pdev->dev);
+	ret = vsp1_device_get(vsp1);
 	if (ret < 0)
 		goto done;
 
 	vsp1->version = vsp1_read(vsp1, VI6_IP_VERSION);
-	pm_runtime_put_sync(&pdev->dev);
+	vsp1_device_put(vsp1);
 
 	for (i = 0; i < ARRAY_SIZE(vsp1_device_infos); ++i) {
 		if ((vsp1->version & VI6_IP_VERSION_MODEL_MASK) ==
@@ -877,8 +882,10 @@
 	}
 
 done:
-	if (ret)
+	if (ret) {
 		pm_runtime_disable(&pdev->dev);
+		rcar_fcp_put(vsp1->fcp);
+	}
 
 	return ret;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/vsp1/vsp1_histo.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/vsp1/vsp1_histo.c
@@ -36,9 +36,8 @@
 vsp1_histogram_buffer_get(struct vsp1_histogram *histo)
 {
 	struct vsp1_histogram_buffer *buf = NULL;
-	unsigned long flags;
 
-	spin_lock_irqsave(&histo->irqlock, flags);
+	spin_lock(&histo->irqlock);
 
 	if (list_empty(&histo->irqqueue))
 		goto done;
@@ -49,7 +48,7 @@
 	histo->readout = true;
 
 done:
-	spin_unlock_irqrestore(&histo->irqlock, flags);
+	spin_unlock(&histo->irqlock);
 	return buf;
 }
 
@@ -58,7 +57,6 @@
 				    size_t size)
 {
 	struct vsp1_pipeline *pipe = histo->entity.pipe;
-	unsigned long flags;
 
 	/*
 	 * The pipeline pointer is guaranteed to be valid as this function is
@@ -70,10 +68,10 @@
 	vb2_set_plane_payload(&buf->buf.vb2_buf, 0, size);
 	vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_DONE);
 
-	spin_lock_irqsave(&histo->irqlock, flags);
+	spin_lock(&histo->irqlock);
 	histo->readout = false;
 	wake_up(&histo->wait_queue);
-	spin_unlock_irqrestore(&histo->irqlock, flags);
+	spin_unlock(&histo->irqlock);
 }
 
 /* -----------------------------------------------------------------------------
@@ -124,11 +122,10 @@
 	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
 	struct vsp1_histogram *histo = vb2_get_drv_priv(vb->vb2_queue);
 	struct vsp1_histogram_buffer *buf = to_vsp1_histogram_buffer(vbuf);
-	unsigned long flags;
 
-	spin_lock_irqsave(&histo->irqlock, flags);
+	spin_lock_irq(&histo->irqlock);
 	list_add_tail(&buf->queue, &histo->irqqueue);
-	spin_unlock_irqrestore(&histo->irqlock, flags);
+	spin_unlock_irq(&histo->irqlock);
 }
 
 static int histo_start_streaming(struct vb2_queue *vq, unsigned int count)
@@ -140,9 +137,8 @@
 {
 	struct vsp1_histogram *histo = vb2_get_drv_priv(vq);
 	struct vsp1_histogram_buffer *buffer;
-	unsigned long flags;
 
-	spin_lock_irqsave(&histo->irqlock, flags);
+	spin_lock_irq(&histo->irqlock);
 
 	/* Remove all buffers from the IRQ queue. */
 	list_for_each_entry(buffer, &histo->irqqueue, queue)
@@ -152,7 +148,7 @@
 	/* Wait for the buffer being read out (if any) to complete. */
 	wait_event_lock_irq(histo->wait_queue, !histo->readout, histo->irqlock);
 
-	spin_unlock_irqrestore(&histo->irqlock, flags);
+	spin_unlock_irq(&histo->irqlock);
 }
 
 static const struct vb2_ops histo_video_queue_qops = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/vsp1/vsp1_pipe.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/vsp1/vsp1_pipe.h
@@ -73,7 +73,7 @@
  * @wpf: The WPF partition window configuration
  */
 struct vsp1_partition {
-	struct vsp1_partition_window rpf;
+	struct vsp1_partition_window rpf[VSP1_MAX_RPF];
 	struct vsp1_partition_window uds_sink;
 	struct vsp1_partition_window uds_source;
 	struct vsp1_partition_window sru;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/vsp1/vsp1_rpf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/vsp1/vsp1_rpf.c
@@ -271,8 +271,8 @@
 	 * 'width' need to be adjusted.
 	 */
 	if (pipe->partitions > 1) {
-		crop.width = pipe->partition->rpf.width;
-		crop.left += pipe->partition->rpf.left;
+		crop.width = pipe->partition->rpf[rpf->entity.index].width;
+		crop.left += pipe->partition->rpf[rpf->entity.index].left;
 	}
 
 	if (pipe->interlaced) {
@@ -291,11 +291,11 @@
 		     + crop.left * fmtinfo->bpp[0] / 8;
 
 	if (format->num_planes > 1) {
+		unsigned int bpl = format->plane_fmt[1].bytesperline;
 		unsigned int offset;
 
-		offset = crop.top * format->plane_fmt[1].bytesperline
-		       + crop.left / fmtinfo->hsub
-		       * fmtinfo->bpp[1] / 8;
+		offset = crop.top / fmtinfo->vsub * bpl
+		       + crop.left / fmtinfo->hsub * fmtinfo->bpp[1] / 8;
 		mem.addr[1] += offset;
 		mem.addr[2] += offset;
 	}
@@ -327,7 +327,9 @@
 			  unsigned int partition_idx,
 			  struct vsp1_partition_window *window)
 {
-	partition->rpf = *window;
+	struct vsp1_rwpf *rpf = to_rwpf(&entity->subdev);
+
+	partition->rpf[rpf->entity.index] = *window;
 }
 
 static const struct vsp1_entity_operations rpf_entity_ops = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/Kconfig
@@ -4,23 +4,172 @@
 	tristate "Xilinx Video IP (EXPERIMENTAL)"
 	depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && OF && HAS_DMA
 	select VIDEOBUF2_DMA_CONTIG
+	select DMADEVICES
+	select XILINX_FRMBUF
 	select V4L2_FWNODE
 	help
 	  Driver for Xilinx Video IP Pipelines
 
 if VIDEO_XILINX
 
+config VIDEO_XILINX_AXI4S_SWITCH
+	tristate "Xilinx AXI4-Stream Video Switch"
+	depends on VIDEO_XILINX
+	---help---
+	  Driver for the Xilinx AXI4-Stream Video Switch. This is a
+	  V4L sub device based driver. It supports fixed (TDEST based)
+	  as well as dynamic (control register based) routing.
+	  Say M to modularize. Say N if unsure.
+
+config VIDEO_XILINX_CFA
+	tristate "Xilinx Video Color Filter Array"
+	depends on VIDEO_XILINX
+	---help---
+	  Driver for the Xilinx Color Filter Array
+
+config VIDEO_XILINX_CRESAMPLE
+	tristate "Xilinx Video Chroma Resampler"
+	depends on VIDEO_XILINX
+	---help---
+	  Driver for the Xilinx Chroma Resampler
+
+config VIDEO_XILINX_DEMOSAIC
+	tristate "Xilinx Video Demosaic IP"
+	depends on VIDEO_XILINX
+	---help---
+	  Driver for Xilinx Video Demosaic IP. This is a V4L sub-device
+	  based driver for the Demosaic IP that takes input a Bayer video
+	  stream format as input and generates an RGB video output.
+	  Say M to modularize. Say N if unsure.
+
+config VIDEO_XILINX_GAMMA
+	tristate "Xilinx Gamma Correction LUT"
+	depends on VIDEO_XILINX
+	---help---
+	  Driver for Xilinx Gamma Correction LUT IP. This is a V4L sub-device
+	  based driver that exposes V4L controls to adjust Red, Blue and Green
+	  Gamma Correction.
+
+	  Say M to modularize. Say N if unsure.
+
+config VIDEO_XILINX_HLS
+	tristate "Xilinx Video HLS Core"
+	depends on VIDEO_XILINX
+	---help---
+	  Driver for the Xilinx Video HLS Cores
+
+config VIDEO_XILINX_REMAPPER
+	tristate "Xilinx Video Remapper"
+	depends on VIDEO_XILINX
+	---help---
+	  Driver for the Xilinx Video Remapper
+
+config VIDEO_XILINX_RGB2YUV
+	tristate "Xilinx Video RGB to YUV Convertor"
+	depends on VIDEO_XILINX
+	---help---
+	  Driver for the Xilinx Video RGB to YUV Convertor
+
+config VIDEO_XILINX_SCALER
+	tristate "Xilinx Video Scaler"
+	depends on VIDEO_XILINX
+	---help---
+	  Driver for the Xilinx Video Scaler
+
+config VIDEO_XILINX_MULTISCALER
+	tristate "Xilinx Video Multiscaler"
+	depends on VIDEO_XILINX
+	depends on VIDEO_DEV && VIDEO_V4L2
+	select V4L2_MEM2MEM_DEV
+	select VIDEOBUF2_DMA_CONTIG
+	---help---
+	  Driver for the Xilinx Video Multi Scaler. This is a V4L2 memory to
+	  memory based driver. Multi-Scaler has max 8 channels which can be
+	  programed for different scaling ratio.
+
+config VIDEO_XILINX_SDIRXSS
+	tristate "Xilinx SDI Rx Subsystem"
+	depends on VIDEO_XILINX
+	---help---
+	  Driver for Xilinx SDI Rx Subsystem
+
+config VIDEO_XILINX_SWITCH
+	tristate "Xilinx Video Switch"
+	depends on VIDEO_XILINX
+	---help---
+	  Driver for the Xilinx Video Switch
+
 config VIDEO_XILINX_TPG
 	tristate "Xilinx Video Test Pattern Generator"
 	depends on VIDEO_XILINX
 	select VIDEO_XILINX_VTC
 	help
-	   Driver for the Xilinx Video Test Pattern Generator
+	  Driver for the Xilinx Video Test Pattern Generator
+
+config VIDEO_XILINX_VPSS_CSC
+	tristate "Xilinx VPSS CSC"
+	depends on VIDEO_XILINX
+	---help---
+	  Driver for the Xilinx Video Processing Sub-System (VPSS)
+	  Color Space Conversion. The driver provides RGB to YUV444
+	  conversion and provides video controls like Brightness,
+	  Contrast, Color Gains that can be applied to video.
+	  Say N if unsure. Say M to modularize.
+
+config VIDEO_XILINX_VPSS_SCALER
+	tristate "Xilinx Video VPSS Scaler"
+	depends on VIDEO_XILINX
+	---help---
+	  Driver for Xilinx Video Processing Sub-System(VPSS) Scaler.
+	  It allows upscaling and downscaling of video. It also supports
+	  limited Color Space Conversion.
+	  Say N if unsure.
 
 config VIDEO_XILINX_VTC
 	tristate "Xilinx Video Timing Controller"
 	depends on VIDEO_XILINX
 	help
-	   Driver for the Xilinx Video Timing Controller
+	  Driver for the Xilinx Video Timing Controller
+
+config VIDEO_XILINX_CSI2RXSS
+	tristate "Xilinx CSI2 Rx Subsystem"
+	depends on VIDEO_XILINX
+	---help---
+	  Driver for Xilinx MIPI CSI2 Rx Subsystem
+
+config VIDEO_XILINX_DPRXSS
+	tristate "Xilinx DP Rx Subsystem"
+	depends on VIDEO_XILINX
+	help
+	  Driver for Xilinx DisplayPort Rx Subsystem. This is a V4L sub-device
+	  based driver for the DisplayPort receiver subsystem IP. It captures
+	  AXI-Stream video data and output to video IPs. Choose this driver
+	  in a platform where the DisplayPort rx subsystem can be instantiated.
+
+config VIDEO_XILINX_SCD
+	tristate "Xilinx Scene Change Detect"
+	depends on VIDEO_XILINX
+	---help---
+	  Driver for Xilinx Scene Change Detection Controller.
+	  The driver allows applications to pass video buffers and
+	  provides if scene change detection is present between
+	  adjacent frames.
+
+config VIDEO_XILINX_M2M
+	tristate "Xilinx Video mem2mem"
+	depends on VIDEO_XILINX
+	select V4L2_MEM2MEM_DEV
+	---help---
+	  Driver for Xilinx V4L2 mem2mem pipeline operation to achieve memory
+	  copy between two different physical memories using DMA transfers.
+
+config VIDEO_XILINX_AXI4S_BROADCASTER
+	tristate "Xilinx AXI4-Stream Video Broadcaster"
+	depends on VIDEO_XILINX
+	help
+	  Driver for the Xilinx AXI4-Stream Video Broadcaster. This is a
+	  V4L sub device based driver. It replicates a single input AXI4-Stream
+	  into multiple output AXI4-Stream.
+	  Say M to modularize. Say N if unsure.
 
 endif #VIDEO_XILINX
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/Makefile
@@ -1,7 +1,28 @@
 # SPDX-License-Identifier: GPL-2.0
 
+xilinx-scd-objs += xilinx-scenechange.o xilinx-scenechange-channel.o \
+		   xilinx-scenechange-dma.o
 xilinx-video-objs += xilinx-dma.o xilinx-vip.o xilinx-vipp.o
 
 obj-$(CONFIG_VIDEO_XILINX) += xilinx-video.o
+obj-$(CONFIG_VIDEO_XILINX_AXI4S_BROADCASTER) += xilinx-axis-broadcaster.o
+obj-$(CONFIG_VIDEO_XILINX_AXI4S_SWITCH) += xilinx-axis-switch.o
+obj-$(CONFIG_VIDEO_XILINX_CFA) += xilinx-cfa.o
+obj-$(CONFIG_VIDEO_XILINX_CRESAMPLE) += xilinx-cresample.o
+obj-$(CONFIG_VIDEO_XILINX_CSI2RXSS) += xilinx-csi2rxss.o
+obj-$(CONFIG_VIDEO_XILINX_DEMOSAIC) += xilinx-demosaic.o
+obj-$(CONFIG_VIDEO_XILINX_DPRXSS) += xilinx-dprxss.o
+obj-$(CONFIG_VIDEO_XILINX_GAMMA) += xilinx-gamma.o
+obj-$(CONFIG_VIDEO_XILINX_HLS) += xilinx-hls.o
+obj-$(CONFIG_VIDEO_XILINX_M2M) += xilinx-m2m.o
+obj-$(CONFIG_VIDEO_XILINX_MULTISCALER) += xilinx-multi-scaler.o
+obj-$(CONFIG_VIDEO_XILINX_REMAPPER) += xilinx-remapper.o
+obj-$(CONFIG_VIDEO_XILINX_RGB2YUV) += xilinx-rgb2yuv.o
+obj-$(CONFIG_VIDEO_XILINX_SCALER) += xilinx-scaler.o
+obj-$(CONFIG_VIDEO_XILINX_SCD) += xilinx-scd.o
+obj-$(CONFIG_VIDEO_XILINX_SDIRXSS) += xilinx-sdirxss.o
+obj-$(CONFIG_VIDEO_XILINX_SWITCH) += xilinx-switch.o
 obj-$(CONFIG_VIDEO_XILINX_TPG) += xilinx-tpg.o
+obj-$(CONFIG_VIDEO_XILINX_VPSS_CSC) += xilinx-vpss-csc.o
+obj-$(CONFIG_VIDEO_XILINX_VPSS_SCALER) += xilinx-vpss-scaler.o
 obj-$(CONFIG_VIDEO_XILINX_VTC) += xilinx-vtc.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/xilinx-axis-broadcaster.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/xilinx-axis-broadcaster.c
@@ -0,0 +1,288 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx AXI4-Stream Video Broadcaster
+ *
+ * Copyright (C) 2021 Xilinx, Inc.
+ *
+ * Author: Ronak Shah <ronak.shah@xilinx.com>
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include <media/media-device.h>
+#include <media/v4l2-async.h>
+#include <media/v4l2-subdev.h>
+
+#include "xilinx-vip.h"
+
+#define MAX_VBR_SINKS			1
+#define MIN_VBR_SRCS			2
+#define MAX_VBR_SRCS			16
+
+/**
+ * struct xvbroadcaster_device - AXI4-Stream Broadcaster device structure
+ * @dev: Platform structure
+ * @subdev: The v4l2 subdev structure
+ * @pads: media pads
+ * @formats: active V4L2 media bus formats on each pad
+ * @npads: number of pads
+ */
+struct xvbroadcaster_device {
+	struct device *dev;
+	struct v4l2_subdev subdev;
+	struct media_pad *pads;
+	struct v4l2_mbus_framefmt formats;
+	u32 npads;
+};
+
+static inline struct xvbroadcaster_device *to_xvbr(struct v4l2_subdev *subdev)
+{
+	return container_of(subdev, struct xvbroadcaster_device, subdev);
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 Subdevice Video Operations
+ */
+
+static int xvbr_s_stream(struct v4l2_subdev *subdev, int enable)
+{
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 Subdevice Pad Operations
+ */
+
+static struct v4l2_mbus_framefmt *
+xvbr_get_pad_format(struct xvbroadcaster_device *xvbr,
+		    struct v4l2_subdev_pad_config *cfg,
+		    unsigned int pad, u32 which)
+{
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		return v4l2_subdev_get_try_format(&xvbr->subdev, cfg, pad);
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		return &xvbr->formats;
+	default:
+		return NULL;
+	}
+}
+
+static int xvbr_get_format(struct v4l2_subdev *subdev,
+			   struct v4l2_subdev_pad_config *cfg,
+			   struct v4l2_subdev_format *fmt)
+{
+	struct xvbroadcaster_device *xvbr = to_xvbr(subdev);
+
+	fmt->format = *xvbr_get_pad_format(xvbr, cfg, fmt->pad, fmt->which);
+
+	return 0;
+}
+
+static int xvbr_set_format(struct v4l2_subdev *subdev,
+			   struct v4l2_subdev_pad_config *cfg,
+			   struct v4l2_subdev_format *fmt)
+{
+	struct xvbroadcaster_device *xvbr = to_xvbr(subdev);
+	struct v4l2_mbus_framefmt *format;
+
+	format = xvbr_get_pad_format(xvbr, cfg, fmt->pad, fmt->which);
+
+	*format = fmt->format;
+
+	xvip_set_format_size(format, fmt);
+
+	fmt->format = *format;
+
+	return 0;
+}
+
+static int xvbr_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+	struct xvbroadcaster_device *xvbr = to_xvbr(subdev);
+	struct v4l2_mbus_framefmt *format;
+	unsigned int i;
+
+	for (i = 0; i < xvbr->npads; ++i) {
+		format = v4l2_subdev_get_try_format(subdev, fh->pad, i);
+		*format = xvbr->formats;
+	}
+
+	return 0;
+}
+
+static int xvbr_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+	return 0;
+}
+
+static struct v4l2_subdev_video_ops xvbr_video_ops = {
+	.s_stream = xvbr_s_stream,
+};
+
+static struct v4l2_subdev_pad_ops xvbr_pad_ops = {
+	.enum_mbus_code = xvip_enum_mbus_code,
+	.enum_frame_size = xvip_enum_frame_size,
+	.get_fmt = xvbr_get_format,
+	.set_fmt = xvbr_set_format,
+};
+
+static struct v4l2_subdev_ops xvbr_ops = {
+	.video = &xvbr_video_ops,
+	.pad = &xvbr_pad_ops,
+};
+
+static const struct v4l2_subdev_internal_ops xvbr_internal_ops = {
+	.open = xvbr_open,
+	.close = xvbr_close,
+};
+
+/* -----------------------------------------------------------------------------
+ * Media Operations
+ */
+
+static const struct media_entity_operations xvbr_media_ops = {
+	.link_validate = v4l2_subdev_link_validate,
+};
+
+/* -----------------------------------------------------------------------------
+ * Platform Device Driver
+ */
+
+static int xvbr_parse_of(struct xvbroadcaster_device *xvbr)
+{
+	struct device_node *node = xvbr->dev->of_node;
+	struct device_node *ports;
+	struct device_node *port;
+
+	ports = of_get_child_by_name(node, "ports");
+	if (!ports)
+		ports = node;
+
+	for_each_child_of_node(ports, port) {
+		struct device_node *endpoint;
+
+		if (!port->name || of_node_cmp(port->name, "port"))
+			continue;
+
+		endpoint = of_get_next_child(port, NULL);
+		if (!endpoint) {
+			dev_err(xvbr->dev, "No port at\n");
+			return -EINVAL;
+		}
+
+		/* Count the number of ports. */
+		xvbr->npads++;
+	}
+
+	/* validate number of ports */
+	if ((xvbr->npads > (MAX_VBR_SINKS + MAX_VBR_SRCS)) ||
+	    (xvbr->npads < (MAX_VBR_SINKS + MIN_VBR_SRCS))) {
+		dev_err(xvbr->dev, "invalid number of ports %u\n", xvbr->npads);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int xvbr_probe(struct platform_device *pdev)
+{
+	struct v4l2_subdev *subdev;
+	struct xvbroadcaster_device *xvbr;
+	unsigned int i;
+	int ret;
+
+	xvbr = devm_kzalloc(&pdev->dev, sizeof(*xvbr), GFP_KERNEL);
+	if (!xvbr)
+		return -ENOMEM;
+
+	xvbr->dev = &pdev->dev;
+
+	ret = xvbr_parse_of(xvbr);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * Initialize V4L2 subdevice and media entity
+	 */
+	xvbr->pads = devm_kzalloc(&pdev->dev, xvbr->npads * sizeof(*xvbr->pads),
+				  GFP_KERNEL);
+	if (!xvbr->pads)
+		return -ENOMEM;
+
+	xvbr->pads[0].flags = MEDIA_PAD_FL_SINK;
+
+	for (i = 1; i < xvbr->npads; ++i)
+		xvbr->pads[i].flags = MEDIA_PAD_FL_SOURCE;
+
+	xvbr->formats.code = MEDIA_BUS_FMT_RGB888_1X24;
+	xvbr->formats.field = V4L2_FIELD_NONE;
+	xvbr->formats.colorspace = V4L2_COLORSPACE_SRGB;
+	xvbr->formats.width = XVIP_MAX_WIDTH;
+	xvbr->formats.height = XVIP_MAX_HEIGHT;
+
+	subdev = &xvbr->subdev;
+	v4l2_subdev_init(subdev, &xvbr_ops);
+	subdev->dev = &pdev->dev;
+	subdev->internal_ops = &xvbr_internal_ops;
+	strlcpy(subdev->name, dev_name(&pdev->dev), sizeof(subdev->name));
+	v4l2_set_subdevdata(subdev, xvbr);
+	subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	subdev->entity.ops = &xvbr_media_ops;
+
+	ret = media_entity_pads_init(&subdev->entity, xvbr->npads, xvbr->pads);
+	if (ret < 0)
+		goto error;
+
+	platform_set_drvdata(pdev, xvbr);
+
+	ret = v4l2_async_register_subdev(subdev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to register subdev\n");
+		goto error;
+	}
+
+	dev_info(xvbr->dev, "Xilinx AXI4-Stream Broadcaster found!\n");
+
+	return 0;
+
+error:
+	media_entity_cleanup(&subdev->entity);
+
+	return ret;
+}
+
+static int xvbr_remove(struct platform_device *pdev)
+{
+	struct xvbroadcaster_device *xvbr = platform_get_drvdata(pdev);
+	struct v4l2_subdev *subdev = &xvbr->subdev;
+
+	v4l2_async_unregister_subdev(subdev);
+	media_entity_cleanup(&subdev->entity);
+
+	return 0;
+}
+
+static const struct of_device_id xvbr_of_id_table[] = {
+	{ .compatible = "xlnx,axis-broadcaster-1.1" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, xvbr_of_id_table);
+
+static struct platform_driver xvbr_driver = {
+	.driver = {
+		.name		= "xilinx-axis-broadcaster",
+		.of_match_table	= xvbr_of_id_table,
+	},
+	.probe			= xvbr_probe,
+	.remove			= xvbr_remove,
+};
+
+module_platform_driver(xvbr_driver);
+
+MODULE_AUTHOR("Ronak Shah <ronak.shah@xilinx.com>");
+MODULE_DESCRIPTION("Xilinx AXI4-Stream Broadcaster Driver");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/xilinx-axis-switch.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/xilinx-axis-switch.c
@@ -0,0 +1,629 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx AXI4-Stream Video Switch
+ *
+ * Copyright (C) 2018 Xilinx, Inc.
+ *
+ * Author: Vishal Sagar <vishal.sagar@xilinx.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include <media/media-device.h>
+#include <media/v4l2-async.h>
+#include <media/v4l2-subdev.h>
+
+#include "xilinx-vip.h"
+
+#define XVSW_CTRL_REG			0x00
+#define XVSW_CTRL_REG_UPDATE_MASK	BIT(1)
+
+#define XVSW_MI_MUX_REG_BASE		0x40
+#define XVSW_MI_MUX_VAL_MASK		0xF
+#define XVSW_MI_MUX_DISABLE_MASK	BIT(31)
+
+#define MIN_VSW_SINKS			1
+#define MAX_VSW_SINKS			16
+#define MIN_VSW_SRCS			1
+#define MAX_VSW_SRCS			16
+
+/**
+ * struct xvswitch_device - Xilinx AXI4-Stream Switch device structure
+ * @dev: Platform structure
+ * @iomem: Base address of IP
+ * @subdev: The v4l2 subdev structure
+ * @pads: media pads
+ * @routing: sink pad connected to each source pad (-1 if none)
+ * @formats: active V4L2 media bus formats on sink pads
+ * @nsinks: number of sink pads (1 to 8)
+ * @nsources: number of source pads (2 to 8)
+ * @tdest_routing: Whether TDEST routing is enabled
+ * @aclk: Video clock
+ * @saxi_ctlclk: AXI-Lite control clock
+ */
+struct xvswitch_device {
+	struct device *dev;
+	void __iomem *iomem;
+	struct v4l2_subdev subdev;
+	struct media_pad *pads;
+	int routing[MAX_VSW_SRCS];
+	struct v4l2_mbus_framefmt *formats;
+	u32 nsinks;
+	u32 nsources;
+	bool tdest_routing;
+	struct clk *aclk;
+	struct clk *saxi_ctlclk;
+};
+
+static inline struct xvswitch_device *to_xvsw(struct v4l2_subdev *subdev)
+{
+	return container_of(subdev, struct xvswitch_device, subdev);
+}
+
+static inline u32 xvswitch_read(struct xvswitch_device *xvsw, u32 addr)
+{
+	return ioread32(xvsw->iomem + addr);
+}
+
+static inline void xvswitch_write(struct xvswitch_device *xvsw, u32 addr,
+				  u32 value)
+{
+	iowrite32(value, xvsw->iomem + addr);
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 Subdevice Video Operations
+ */
+
+static int xvsw_s_stream(struct v4l2_subdev *subdev, int enable)
+{
+	struct xvswitch_device *xvsw = to_xvsw(subdev);
+	unsigned int i;
+
+	/* Nothing to be done in case of TDEST routing */
+	if (xvsw->tdest_routing)
+		return 0;
+
+	if (!enable) {
+		/* In control reg routing, disable all master ports */
+		for (i = 0; i < xvsw->nsources; i++) {
+			xvswitch_write(xvsw, XVSW_MI_MUX_REG_BASE + (i * 4),
+				       XVSW_MI_MUX_DISABLE_MASK);
+		}
+		xvswitch_write(xvsw, XVSW_CTRL_REG, XVSW_CTRL_REG_UPDATE_MASK);
+		return 0;
+	}
+
+	/*
+	 * In case of control reg routing,
+	 * from routing table write the values into respective reg
+	 * and enable
+	 */
+	for (i = 0; i < MAX_VSW_SRCS; i++) {
+		u32 val;
+
+		if (xvsw->routing[i] != -1)
+			val = xvsw->routing[i];
+		else
+			val = XVSW_MI_MUX_DISABLE_MASK;
+
+		xvswitch_write(xvsw, XVSW_MI_MUX_REG_BASE + (i * 4),
+			       val);
+	}
+
+	xvswitch_write(xvsw, XVSW_CTRL_REG, XVSW_CTRL_REG_UPDATE_MASK);
+
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 Subdevice Pad Operations
+ */
+
+static struct v4l2_mbus_framefmt *
+xvsw_get_pad_format(struct xvswitch_device *xvsw,
+		    struct v4l2_subdev_pad_config *cfg,
+		    unsigned int pad, u32 which)
+{
+	struct v4l2_mbus_framefmt *get_fmt;
+
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		get_fmt = v4l2_subdev_get_try_format(&xvsw->subdev, cfg, pad);
+		break;
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		get_fmt = &xvsw->formats[pad];
+		break;
+	default:
+		get_fmt = NULL;
+		break;
+	}
+
+	return get_fmt;
+}
+
+static int xvsw_get_format(struct v4l2_subdev *subdev,
+			   struct v4l2_subdev_pad_config *cfg,
+			   struct v4l2_subdev_format *fmt)
+{
+	struct xvswitch_device *xvsw = to_xvsw(subdev);
+	int pad = fmt->pad;
+	struct v4l2_mbus_framefmt *get_fmt;
+
+	/*
+	 * If control reg routing and pad is source pad then
+	 * get corresponding sink pad. if no sink pad then
+	 * clear the format and return
+	 */
+
+	if (!xvsw->tdest_routing && pad >= xvsw->nsinks) {
+		pad = xvsw->routing[pad - xvsw->nsinks];
+		if (pad < 0) {
+			memset(&fmt->format, 0, sizeof(fmt->format));
+			return 0;
+		}
+	}
+
+	get_fmt = xvsw_get_pad_format(xvsw, cfg, pad, fmt->which);
+	if (!get_fmt)
+		return -EINVAL;
+
+	fmt->format = *get_fmt;
+
+	return 0;
+}
+
+static int xvsw_set_format(struct v4l2_subdev *subdev,
+			   struct v4l2_subdev_pad_config *cfg,
+			   struct v4l2_subdev_format *fmt)
+{
+	struct xvswitch_device *xvsw = to_xvsw(subdev);
+	struct v4l2_mbus_framefmt *format;
+
+	if (!xvsw->tdest_routing && fmt->pad >= xvsw->nsinks) {
+		/*
+		 * In case of control reg routing,
+		 * get the corresponding sink pad to source pad passed.
+		 *
+		 * The source pad format is always identical to the
+		 * sink pad format and can't be modified.
+		 *
+		 * If sink pad found then get_format for that pad
+		 * else clear the fmt->format as the source pad
+		 * isn't connected and return.
+		 */
+		return xvsw_get_format(subdev, cfg, fmt);
+	}
+
+	if (xvsw->nsinks == 1 && fmt->pad != 0) {
+		struct v4l2_mbus_framefmt *sinkformat;
+
+		/*
+		 * in tdest routing if there is only one sink then all the
+		 * source pads will have same property as sink pad, assuming
+		 * streams going to each source pad will have same
+		 * properties.
+		 */
+
+		/* get sink pad format */
+		sinkformat = xvsw_get_pad_format(xvsw, cfg, 0, fmt->which);
+		if (!sinkformat)
+			return -EINVAL;
+
+		fmt->format = *sinkformat;
+
+		/* set sink pad format on source pad */
+		format = xvsw_get_pad_format(xvsw, cfg, fmt->pad, fmt->which);
+		if (!format)
+			return -EINVAL;
+
+		*format = *sinkformat;
+
+		return 0;
+	}
+
+	/*
+	 * In TDEST routing mode, one can set any format on the pad as
+	 * it can't be checked which pad's data will travel to
+	 * which pad. E.g. In a system with 2 slaves and 4 masters,
+	 * S0 or S1 data can reach M0 thru M3 based on TDEST
+	 * S0 may have RBG and S1 may have YUV. M0, M1 stream RBG
+	 * and M2, M3 stream YUV based on TDEST.
+	 *
+	 * In Control reg routing mode, set format only for sink pads.
+	 */
+	format = xvsw_get_pad_format(xvsw, cfg, fmt->pad, fmt->which);
+	if (!format)
+		return -EINVAL;
+
+	format->code = fmt->format.code;
+	format->width = clamp_t(unsigned int, fmt->format.width,
+				XVIP_MIN_WIDTH, XVIP_MAX_WIDTH);
+	format->height = clamp_t(unsigned int, fmt->format.height,
+				 XVIP_MIN_HEIGHT, XVIP_MAX_HEIGHT);
+	format->field = V4L2_FIELD_NONE;
+	format->colorspace = V4L2_COLORSPACE_SRGB;
+
+	fmt->format = *format;
+
+	return 0;
+}
+
+static int xvsw_get_routing(struct v4l2_subdev *subdev,
+			    struct v4l2_subdev_routing *route)
+{
+	struct xvswitch_device *xvsw = to_xvsw(subdev);
+	unsigned int i;
+	u32 min;
+
+	/* In case of tdest routing, we can't get routing */
+	if (xvsw->tdest_routing)
+		return -EINVAL;
+
+	mutex_lock(&subdev->entity.graph_obj.mdev->graph_mutex);
+
+	if (xvsw->nsources < route->num_routes)
+		min = xvsw->nsources;
+	else
+		min = route->num_routes;
+
+	for (i = 0; i < min; ++i) {
+		route->routes[i].sink = xvsw->routing[i];
+		route->routes[i].source = i;
+	}
+
+	route->num_routes = xvsw->nsources;
+
+	mutex_unlock(&subdev->entity.graph_obj.mdev->graph_mutex);
+
+	return 0;
+}
+
+static int xvsw_set_routing(struct v4l2_subdev *subdev,
+			    struct v4l2_subdev_routing *route)
+{
+	struct xvswitch_device *xvsw = to_xvsw(subdev);
+	unsigned int i;
+	int ret = 0;
+
+	/* In case of tdest routing, we can't set routing */
+	if (xvsw->tdest_routing)
+		return -EINVAL;
+
+	mutex_lock(&subdev->entity.graph_obj.mdev->graph_mutex);
+
+	if (subdev->entity.stream_count) {
+		ret = -EBUSY;
+		goto done;
+	}
+
+	for (i = 0; i < xvsw->nsources; ++i)
+		xvsw->routing[i] = -1;
+
+	for (i = 0; i < route->num_routes; ++i)
+		xvsw->routing[route->routes[i].source - xvsw->nsinks] =
+			route->routes[i].sink;
+
+done:
+	mutex_unlock(&subdev->entity.graph_obj.mdev->graph_mutex);
+	return ret;
+}
+
+static int xvsw_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+	return 0;
+}
+
+static int xvsw_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+	return 0;
+}
+
+static struct v4l2_subdev_video_ops xvsw_video_ops = {
+	.s_stream = xvsw_s_stream,
+};
+
+static struct v4l2_subdev_pad_ops xvsw_pad_ops = {
+	.enum_mbus_code = xvip_enum_mbus_code,
+	.enum_frame_size = xvip_enum_frame_size,
+	.get_fmt = xvsw_get_format,
+	.set_fmt = xvsw_set_format,
+	.get_routing = xvsw_get_routing,
+	.set_routing = xvsw_set_routing,
+};
+
+static struct v4l2_subdev_ops xvsw_ops = {
+	.video = &xvsw_video_ops,
+	.pad = &xvsw_pad_ops,
+};
+
+static const struct v4l2_subdev_internal_ops xvsw_internal_ops = {
+	.open = xvsw_open,
+	.close = xvsw_close,
+};
+
+/* -----------------------------------------------------------------------------
+ * Media Operations
+ */
+
+static bool xvsw_has_route(struct media_entity *entity, unsigned int pad0,
+			   unsigned int pad1)
+{
+	struct xvswitch_device *xvsw =
+		container_of(entity, struct xvswitch_device, subdev.entity);
+	unsigned int sink0, sink1;
+
+	/* Two sinks are never connected together. */
+	if (pad0 < xvsw->nsinks && pad1 < xvsw->nsinks)
+		return false;
+
+	/* In TDEST routing, assume all sinks and sources are connected */
+	if (xvsw->tdest_routing)
+		return true;
+
+	sink0 = pad0 < xvsw->nsinks ? pad0 : xvsw->routing[pad0 - xvsw->nsinks];
+	sink1 = pad1 < xvsw->nsinks ? pad1 : xvsw->routing[pad1 - xvsw->nsinks];
+
+	return sink0 == sink1;
+}
+
+static const struct media_entity_operations xvsw_media_ops = {
+	.link_validate = v4l2_subdev_link_validate,
+	.has_route = xvsw_has_route,
+};
+
+/* -----------------------------------------------------------------------------
+ * Platform Device Driver
+ */
+
+static int xvsw_parse_of(struct xvswitch_device *xvsw)
+{
+	struct device_node *node = xvsw->dev->of_node;
+	struct device_node *ports;
+	struct device_node *port;
+	unsigned int nports = 0;
+	u32 routing_mode = 0;
+	int ret;
+
+	ret = of_property_read_u32(node, "xlnx,num-si-slots", &xvsw->nsinks);
+	if (ret < 0 || xvsw->nsinks < MIN_VSW_SINKS ||
+	    xvsw->nsinks > MAX_VSW_SINKS) {
+		dev_err(xvsw->dev, "missing or invalid xlnx,num-si-slots property\n");
+		return ret;
+	}
+
+	ret = of_property_read_u32(node, "xlnx,num-mi-slots", &xvsw->nsources);
+	if (ret < 0 || xvsw->nsources < MIN_VSW_SRCS ||
+	    xvsw->nsources > MAX_VSW_SRCS) {
+		dev_err(xvsw->dev, "missing or invalid xlnx,num-mi-slots property\n");
+		return ret;
+	}
+
+	ret = of_property_read_u32(node, "xlnx,routing-mode", &routing_mode);
+	if (ret < 0 || routing_mode > 1) {
+		dev_err(xvsw->dev, "missing or invalid xlnx,routing property\n");
+		return ret;
+	}
+
+	if (!routing_mode)
+		xvsw->tdest_routing = true;
+
+	xvsw->aclk = devm_clk_get(xvsw->dev, "aclk");
+	if (IS_ERR(xvsw->aclk)) {
+		ret = PTR_ERR(xvsw->aclk);
+		dev_err(xvsw->dev, "failed to get ap_clk (%d)\n", ret);
+		return ret;
+	}
+
+	if (!xvsw->tdest_routing) {
+		xvsw->saxi_ctlclk = devm_clk_get(xvsw->dev,
+						 "s_axi_ctl_clk");
+		if (IS_ERR(xvsw->saxi_ctlclk)) {
+			ret = PTR_ERR(xvsw->saxi_ctlclk);
+			dev_err(xvsw->dev,
+				"failed to get s_axi_ctl_clk (%d)\n",
+				ret);
+			return ret;
+		}
+	}
+
+	if (xvsw->tdest_routing && xvsw->nsinks > 1) {
+		dev_err(xvsw->dev, "sinks = %d. Driver Limitation max 1 sink in TDEST routing mode\n",
+			xvsw->nsinks);
+		return -EINVAL;
+	}
+
+	ports = of_get_child_by_name(node, "ports");
+	if (!ports)
+		ports = node;
+
+	for_each_child_of_node(ports, port) {
+		struct device_node *endpoint;
+
+		if (!port->name || of_node_cmp(port->name, "port"))
+			continue;
+
+		endpoint = of_get_next_child(port, NULL);
+		if (!endpoint) {
+			dev_err(xvsw->dev, "No port at\n");
+			return -EINVAL;
+		}
+
+		/* Count the number of ports. */
+		nports++;
+	}
+
+	/* validate number of ports */
+	if (nports != (xvsw->nsinks + xvsw->nsources)) {
+		dev_err(xvsw->dev, "invalid number of ports %u\n", nports);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int xvsw_probe(struct platform_device *pdev)
+{
+	struct v4l2_subdev *subdev;
+	struct xvswitch_device *xvsw;
+	struct resource *res;
+	unsigned int npads;
+	unsigned int i, padcount;
+	int ret;
+
+	xvsw = devm_kzalloc(&pdev->dev, sizeof(*xvsw), GFP_KERNEL);
+	if (!xvsw)
+		return -ENOMEM;
+
+	xvsw->dev = &pdev->dev;
+
+	ret = xvsw_parse_of(xvsw);
+	if (ret < 0)
+		return ret;
+
+	/* ioremap only if control reg based routing */
+	if (!xvsw->tdest_routing) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+		xvsw->iomem = devm_ioremap_resource(xvsw->dev, res);
+		if (IS_ERR(xvsw->iomem))
+			return PTR_ERR(xvsw->iomem);
+	}
+
+	/*
+	 * Initialize V4L2 subdevice and media entity. Pad numbers depend on the
+	 * number of pads.
+	 */
+	npads = xvsw->nsinks + xvsw->nsources;
+	xvsw->pads = devm_kzalloc(&pdev->dev, npads * sizeof(*xvsw->pads),
+				  GFP_KERNEL);
+	if (!xvsw->pads)
+		return -ENOMEM;
+
+	for (i = 0; i < xvsw->nsinks; ++i)
+		xvsw->pads[i].flags = MEDIA_PAD_FL_SINK;
+
+	for (; i < npads; ++i)
+		xvsw->pads[i].flags = MEDIA_PAD_FL_SOURCE;
+
+	padcount = xvsw->tdest_routing ? npads : xvsw->nsinks;
+
+	/*
+	 * In case of tdest routing, allocate format per pad.
+	 * source pad format has to match one of the sink pads in tdest routing.
+	 *
+	 * Otherwise only allocate for sinks as sources will
+	 * get the same pad format and corresponding sink.
+	 * set format on src pad will return corresponding sinks data.
+	 */
+	xvsw->formats = devm_kzalloc(&pdev->dev,
+				     padcount * sizeof(*xvsw->formats),
+				     GFP_KERNEL);
+	if (!xvsw->formats) {
+		dev_err(xvsw->dev, "No memory to allocate formats!\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < padcount; i++) {
+		xvsw->formats[i].code = MEDIA_BUS_FMT_RGB888_1X24;
+		xvsw->formats[i].field = V4L2_FIELD_NONE;
+		xvsw->formats[i].colorspace = V4L2_COLORSPACE_SRGB;
+		xvsw->formats[i].width = XVIP_MAX_WIDTH;
+		xvsw->formats[i].height = XVIP_MAX_HEIGHT;
+	}
+
+	/*
+	 * Initialize the routing table if none are connected.
+	 * Routing table is valid only incase routing is not TDEST based.
+	 */
+	for (i = 0; i < MAX_VSW_SRCS; ++i)
+		xvsw->routing[i] = -1;
+
+	ret = clk_prepare_enable(xvsw->aclk);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to enable aclk (%d)\n",
+			ret);
+		return ret;
+	}
+
+	if (!xvsw->tdest_routing) {
+		ret = clk_prepare_enable(xvsw->saxi_ctlclk);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"failed to enable s_axi_ctl_clk (%d)\n",
+				ret);
+			clk_disable_unprepare(xvsw->aclk);
+			return ret;
+		}
+	}
+
+	subdev = &xvsw->subdev;
+	v4l2_subdev_init(subdev, &xvsw_ops);
+	subdev->dev = &pdev->dev;
+	subdev->internal_ops = &xvsw_internal_ops;
+	strlcpy(subdev->name, dev_name(&pdev->dev), sizeof(subdev->name));
+	v4l2_set_subdevdata(subdev, xvsw);
+	subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	subdev->entity.ops = &xvsw_media_ops;
+
+	ret = media_entity_pads_init(&subdev->entity, npads, xvsw->pads);
+	if (ret < 0)
+		goto clk_error;
+
+	platform_set_drvdata(pdev, xvsw);
+
+	ret = v4l2_async_register_subdev(subdev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to register subdev\n");
+		goto error;
+	}
+
+	dev_info(xvsw->dev, "Xilinx AXI4-Stream Switch found!\n");
+
+	return 0;
+
+error:
+	media_entity_cleanup(&subdev->entity);
+clk_error:
+	if (!xvsw->tdest_routing)
+		clk_disable_unprepare(xvsw->saxi_ctlclk);
+	clk_disable_unprepare(xvsw->aclk);
+	return ret;
+}
+
+static int xvsw_remove(struct platform_device *pdev)
+{
+	struct xvswitch_device *xvsw = platform_get_drvdata(pdev);
+	struct v4l2_subdev *subdev = &xvsw->subdev;
+
+	v4l2_async_unregister_subdev(subdev);
+	media_entity_cleanup(&subdev->entity);
+	if (!xvsw->tdest_routing)
+		clk_disable_unprepare(xvsw->saxi_ctlclk);
+	clk_disable_unprepare(xvsw->aclk);
+	return 0;
+}
+
+static const struct of_device_id xvsw_of_id_table[] = {
+	{ .compatible = "xlnx,axis-switch-1.1" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, xvsw_of_id_table);
+
+static struct platform_driver xvsw_driver = {
+	.driver = {
+		.name		= "xilinx-axis-switch",
+		.of_match_table	= xvsw_of_id_table,
+	},
+	.probe			= xvsw_probe,
+	.remove			= xvsw_remove,
+};
+
+module_platform_driver(xvsw_driver);
+
+MODULE_AUTHOR("Vishal Sagar <vishal.sagar@xilinx.com>");
+MODULE_DESCRIPTION("Xilinx AXI4-Stream Switch Driver");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/xilinx-cfa.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/xilinx-cfa.c
@@ -0,0 +1,409 @@
+/*
+ * Xilinx Color Filter Array
+ *
+ * Copyright (C) 2013-2015 Ideas on Board
+ * Copyright (C) 2013-2015 Xilinx, Inc.
+ *
+ * Contacts: Hyun Kwon <hyun.kwon@xilinx.com>
+ *           Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include <media/v4l2-async.h>
+#include <media/v4l2-subdev.h>
+
+#include "xilinx-vip.h"
+
+#define XCFA_BAYER_PHASE	0x100
+#define XCFA_BAYER_PHASE_RGGB	0
+#define XCFA_BAYER_PHASE_GRBG	1
+#define XCFA_BAYER_PHASE_GBRG	2
+#define XCFA_BAYER_PHASE_BGGR	3
+
+/**
+ * struct xcfa_device - Xilinx CFA device structure
+ * @xvip: Xilinx Video IP device
+ * @pads: media pads
+ * @formats: V4L2 media bus formats
+ * @default_formats: default V4L2 media bus formats
+ * @vip_formats: Xilinx Video IP formats
+ */
+struct xcfa_device {
+	struct xvip_device xvip;
+
+	struct media_pad pads[2];
+
+	struct v4l2_mbus_framefmt formats[2];
+	struct v4l2_mbus_framefmt default_formats[2];
+	const struct xvip_video_format *vip_formats[2];
+};
+
+static inline struct xcfa_device *to_cfa(struct v4l2_subdev *subdev)
+{
+	return container_of(subdev, struct xcfa_device, xvip.subdev);
+}
+
+/*
+ * V4L2 Subdevice Video Operations
+ */
+
+static int xcfa_get_bayer_phase(const unsigned int code)
+{
+	switch (code) {
+	case MEDIA_BUS_FMT_SRGGB8_1X8:
+		return XCFA_BAYER_PHASE_RGGB;
+	case MEDIA_BUS_FMT_SGRBG8_1X8:
+		return XCFA_BAYER_PHASE_GRBG;
+	case MEDIA_BUS_FMT_SGBRG8_1X8:
+		return XCFA_BAYER_PHASE_GBRG;
+	case MEDIA_BUS_FMT_SBGGR8_1X8:
+		return XCFA_BAYER_PHASE_BGGR;
+	}
+
+	return -EINVAL;
+}
+
+static int xcfa_s_stream(struct v4l2_subdev *subdev, int enable)
+{
+	struct xcfa_device *xcfa = to_cfa(subdev);
+	const unsigned int code = xcfa->formats[XVIP_PAD_SINK].code;
+	u32 bayer_phase;
+
+	if (!enable) {
+		xvip_stop(&xcfa->xvip);
+		return 0;
+	}
+
+	/* This always returns the valid bayer phase value */
+	bayer_phase = xcfa_get_bayer_phase(code);
+
+	xvip_write(&xcfa->xvip, XCFA_BAYER_PHASE, bayer_phase);
+
+	xvip_set_frame_size(&xcfa->xvip, &xcfa->formats[XVIP_PAD_SINK]);
+
+	xvip_start(&xcfa->xvip);
+
+	return 0;
+}
+
+/*
+ * V4L2 Subdevice Pad Operations
+ */
+
+static struct v4l2_mbus_framefmt *
+__xcfa_get_pad_format(struct xcfa_device *xcfa,
+		      struct v4l2_subdev_pad_config *cfg,
+		      unsigned int pad, u32 which)
+{
+	struct v4l2_mbus_framefmt *format;
+
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		format = v4l2_subdev_get_try_format(&xcfa->xvip.subdev, cfg,
+						    pad);
+		break;
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		format = &xcfa->formats[pad];
+		break;
+	default:
+		format = NULL;
+		break;
+	}
+
+	return format;
+}
+
+static int xcfa_get_format(struct v4l2_subdev *subdev,
+			   struct v4l2_subdev_pad_config *cfg,
+			   struct v4l2_subdev_format *fmt)
+{
+	struct xcfa_device *xcfa = to_cfa(subdev);
+	struct v4l2_mbus_framefmt *format;
+
+	format = __xcfa_get_pad_format(xcfa, cfg, fmt->pad, fmt->which);
+	if (!format)
+		return -EINVAL;
+
+	fmt->format = *format;
+
+	return 0;
+}
+
+static int xcfa_set_format(struct v4l2_subdev *subdev,
+			   struct v4l2_subdev_pad_config *cfg,
+			   struct v4l2_subdev_format *fmt)
+{
+	struct xcfa_device *xcfa = to_cfa(subdev);
+	struct v4l2_mbus_framefmt *format;
+	int bayer_phase;
+
+	format = __xcfa_get_pad_format(xcfa, cfg, fmt->pad, fmt->which);
+	if (!format)
+		return -EINVAL;
+
+	if (fmt->pad == XVIP_PAD_SOURCE) {
+		fmt->format = *format;
+		return 0;
+	}
+
+	bayer_phase = xcfa_get_bayer_phase(fmt->format.code);
+	if (bayer_phase >= 0) {
+		xcfa->vip_formats[XVIP_PAD_SINK] =
+			xvip_get_format_by_code(fmt->format.code);
+		format->code = fmt->format.code;
+	}
+
+	xvip_set_format_size(format, fmt);
+
+	fmt->format = *format;
+
+	/* Propagate the format to the source pad */
+	format = __xcfa_get_pad_format(xcfa, cfg, XVIP_PAD_SOURCE, fmt->which);
+
+	xvip_set_format_size(format, fmt);
+
+	return 0;
+}
+
+/*
+ * V4L2 Subdevice Operations
+ */
+
+static int xcfa_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+	struct xcfa_device *xcfa = to_cfa(subdev);
+	struct v4l2_mbus_framefmt *format;
+
+	/* Initialize with default formats */
+	format = v4l2_subdev_get_try_format(subdev, fh->pad, XVIP_PAD_SINK);
+	*format = xcfa->default_formats[XVIP_PAD_SINK];
+
+	format = v4l2_subdev_get_try_format(subdev, fh->pad, XVIP_PAD_SOURCE);
+	*format = xcfa->default_formats[XVIP_PAD_SOURCE];
+
+	return 0;
+}
+
+static int xcfa_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+	return 0;
+}
+
+static struct v4l2_subdev_video_ops xcfa_video_ops = {
+	.s_stream = xcfa_s_stream,
+};
+
+static struct v4l2_subdev_pad_ops xcfa_pad_ops = {
+	.enum_mbus_code		= xvip_enum_mbus_code,
+	.enum_frame_size	= xvip_enum_frame_size,
+	.get_fmt		= xcfa_get_format,
+	.set_fmt		= xcfa_set_format,
+};
+
+static struct v4l2_subdev_ops xcfa_ops = {
+	.video  = &xcfa_video_ops,
+	.pad    = &xcfa_pad_ops,
+};
+
+static const struct v4l2_subdev_internal_ops xcfa_internal_ops = {
+	.open	= xcfa_open,
+	.close	= xcfa_close,
+};
+
+/*
+ * Media Operations
+ */
+
+static const struct media_entity_operations xcfa_media_ops = {
+	.link_validate = v4l2_subdev_link_validate,
+};
+
+/*
+ * Power Management
+ */
+
+static int __maybe_unused xcfa_pm_suspend(struct device *dev)
+{
+	struct xcfa_device *xcfa = dev_get_drvdata(dev);
+
+	xvip_suspend(&xcfa->xvip);
+
+	return 0;
+}
+
+static int __maybe_unused xcfa_pm_resume(struct device *dev)
+{
+	struct xcfa_device *xcfa = dev_get_drvdata(dev);
+
+	xvip_resume(&xcfa->xvip);
+
+	return 0;
+}
+
+/*
+ * Platform Device Driver
+ */
+
+static int xcfa_parse_of(struct xcfa_device *xcfa)
+{
+	struct device *dev = xcfa->xvip.dev;
+	struct device_node *node = xcfa->xvip.dev->of_node;
+	struct device_node *ports;
+	struct device_node *port;
+	u32 port_id;
+	int ret;
+
+	ports = of_get_child_by_name(node, "ports");
+	if (ports == NULL)
+		ports = node;
+
+	/* Get the format description for each pad */
+	for_each_child_of_node(ports, port) {
+		if (port->name && (of_node_cmp(port->name, "port") == 0)) {
+			const struct xvip_video_format *vip_format;
+
+			vip_format = xvip_of_get_format(port);
+			if (IS_ERR(vip_format)) {
+				dev_err(dev, "invalid format in DT");
+				return PTR_ERR(vip_format);
+			}
+
+			ret = of_property_read_u32(port, "reg", &port_id);
+			if (ret < 0) {
+				dev_err(dev, "no reg in DT");
+				return ret;
+			}
+
+			if (port_id != 0 && port_id != 1) {
+				dev_err(dev, "invalid reg in DT");
+				return -EINVAL;
+			}
+
+			xcfa->vip_formats[port_id] = vip_format;
+		}
+	}
+
+	return 0;
+}
+
+static int xcfa_probe(struct platform_device *pdev)
+{
+	struct xcfa_device *xcfa;
+	struct v4l2_subdev *subdev;
+	struct v4l2_mbus_framefmt *default_format;
+	int ret;
+
+	xcfa = devm_kzalloc(&pdev->dev, sizeof(*xcfa), GFP_KERNEL);
+	if (!xcfa)
+		return -ENOMEM;
+
+	xcfa->xvip.dev = &pdev->dev;
+
+	ret = xcfa_parse_of(xcfa);
+	if (ret < 0)
+		return ret;
+
+	ret = xvip_init_resources(&xcfa->xvip);
+	if (ret < 0)
+		return ret;
+
+	/* Reset and initialize the core */
+	xvip_reset(&xcfa->xvip);
+
+	/* Initialize V4L2 subdevice and media entity */
+	subdev = &xcfa->xvip.subdev;
+	v4l2_subdev_init(subdev, &xcfa_ops);
+	subdev->dev = &pdev->dev;
+	subdev->internal_ops = &xcfa_internal_ops;
+	strlcpy(subdev->name, dev_name(&pdev->dev), sizeof(subdev->name));
+	v4l2_set_subdevdata(subdev, xcfa);
+	subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	/* Initialize default and active formats */
+	default_format = &xcfa->default_formats[XVIP_PAD_SINK];
+	default_format->code = xcfa->vip_formats[XVIP_PAD_SINK]->code;
+	default_format->field = V4L2_FIELD_NONE;
+	default_format->colorspace = V4L2_COLORSPACE_SRGB;
+	xvip_get_frame_size(&xcfa->xvip, default_format);
+
+	xcfa->formats[XVIP_PAD_SINK] = *default_format;
+
+	default_format = &xcfa->default_formats[XVIP_PAD_SOURCE];
+	*default_format = xcfa->default_formats[XVIP_PAD_SINK];
+	default_format->code = xcfa->vip_formats[XVIP_PAD_SOURCE]->code;
+
+	xcfa->formats[XVIP_PAD_SOURCE] = *default_format;
+
+	xcfa->pads[XVIP_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+	xcfa->pads[XVIP_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+	subdev->entity.ops = &xcfa_media_ops;
+	ret = media_entity_pads_init(&subdev->entity, 2, xcfa->pads);
+	if (ret < 0)
+		goto error;
+
+	platform_set_drvdata(pdev, xcfa);
+
+	xvip_print_version(&xcfa->xvip);
+
+	ret = v4l2_async_register_subdev(subdev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to register subdev\n");
+		goto error;
+	}
+
+	return 0;
+
+error:
+	media_entity_cleanup(&subdev->entity);
+	xvip_cleanup_resources(&xcfa->xvip);
+	return ret;
+}
+
+static int xcfa_remove(struct platform_device *pdev)
+{
+	struct xcfa_device *xcfa = platform_get_drvdata(pdev);
+	struct v4l2_subdev *subdev = &xcfa->xvip.subdev;
+
+	v4l2_async_unregister_subdev(subdev);
+	media_entity_cleanup(&subdev->entity);
+
+	xvip_cleanup_resources(&xcfa->xvip);
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(xcfa_pm_ops, xcfa_pm_suspend, xcfa_pm_resume);
+
+static const struct of_device_id xcfa_of_id_table[] = {
+	{ .compatible = "xlnx,v-cfa-7.0" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, xcfa_of_id_table);
+
+static struct platform_driver xcfa_driver = {
+	.driver			= {
+		.name		= "xilinx-cfa",
+		.pm		= &xcfa_pm_ops,
+		.of_match_table	= xcfa_of_id_table,
+	},
+	.probe			= xcfa_probe,
+	.remove			= xcfa_remove,
+};
+
+module_platform_driver(xcfa_driver);
+
+MODULE_DESCRIPTION("Xilinx Color Filter Array Driver");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/xilinx-cresample.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/xilinx-cresample.c
@@ -0,0 +1,461 @@
+/*
+ * Xilinx Chroma Resampler
+ *
+ * Copyright (C) 2013-2015 Ideas on Board
+ * Copyright (C) 2013-2015 Xilinx, Inc.
+ *
+ * Contacts: Hyun Kwon <hyun.kwon@xilinx.com>
+ *           Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/xilinx-v4l2-controls.h>
+
+#include <media/v4l2-async.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-subdev.h>
+
+#include "xilinx-vip.h"
+
+#define XCRESAMPLE_ENCODING			0x100
+#define XCRESAMPLE_ENCODING_FIELD		(1 << 7)
+#define XCRESAMPLE_ENCODING_CHROMA		(1 << 8)
+
+/**
+ * struct xcresample_device - Xilinx CRESAMPLE device structure
+ * @xvip: Xilinx Video IP device
+ * @pads: media pads
+ * @formats: V4L2 media bus formats at the sink and source pads
+ * @default_formats: default V4L2 media bus formats
+ * @vip_formats: Xilinx Video IP formats
+ * @ctrl_handler: control handler
+ */
+struct xcresample_device {
+	struct xvip_device xvip;
+
+	struct media_pad pads[2];
+
+	struct v4l2_mbus_framefmt formats[2];
+	struct v4l2_mbus_framefmt default_formats[2];
+	const struct xvip_video_format *vip_formats[2];
+
+	struct v4l2_ctrl_handler ctrl_handler;
+};
+
+static inline struct xcresample_device *to_cresample(struct v4l2_subdev *subdev)
+{
+	return container_of(subdev, struct xcresample_device, xvip.subdev);
+}
+
+/*
+ * V4L2 Subdevice Video Operations
+ */
+
+static int xcresample_s_stream(struct v4l2_subdev *subdev, int enable)
+{
+	struct xcresample_device *xcresample = to_cresample(subdev);
+
+	if (!enable) {
+		xvip_stop(&xcresample->xvip);
+		return 0;
+	}
+
+	xvip_set_frame_size(&xcresample->xvip,
+			    &xcresample->formats[XVIP_PAD_SINK]);
+
+	xvip_start(&xcresample->xvip);
+
+	return 0;
+}
+
+/*
+ * V4L2 Subdevice Pad Operations
+ */
+
+static struct v4l2_mbus_framefmt *
+__xcresample_get_pad_format(struct xcresample_device *xcresample,
+			    struct v4l2_subdev_pad_config *cfg,
+			    unsigned int pad, u32 which)
+{
+	struct v4l2_mbus_framefmt *format;
+
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		format = v4l2_subdev_get_try_format(&xcresample->xvip.subdev,
+						    cfg, pad);
+		break;
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		format = &xcresample->formats[pad];
+		break;
+	default:
+		format = NULL;
+		break;
+	}
+
+	return format;
+}
+
+static int xcresample_get_format(struct v4l2_subdev *subdev,
+				 struct v4l2_subdev_pad_config *cfg,
+				 struct v4l2_subdev_format *fmt)
+{
+	struct xcresample_device *xcresample = to_cresample(subdev);
+	struct v4l2_mbus_framefmt *format;
+
+	format = __xcresample_get_pad_format(xcresample, cfg, fmt->pad,
+					     fmt->which);
+	if (!format)
+		return -EINVAL;
+
+	fmt->format = *format;
+
+	return 0;
+}
+
+static int xcresample_set_format(struct v4l2_subdev *subdev,
+				 struct v4l2_subdev_pad_config *cfg,
+				 struct v4l2_subdev_format *fmt)
+{
+	struct xcresample_device *xcresample = to_cresample(subdev);
+	struct v4l2_mbus_framefmt *format;
+
+	format = __xcresample_get_pad_format(xcresample, cfg, fmt->pad,
+					     fmt->which);
+	if (!format)
+		return -EINVAL;
+
+	if (fmt->pad == XVIP_PAD_SOURCE) {
+		fmt->format = *format;
+		return 0;
+	}
+
+	xvip_set_format_size(format, fmt);
+
+	fmt->format = *format;
+
+	/* Propagate the format to the source pad. */
+	format = __xcresample_get_pad_format(xcresample, cfg, XVIP_PAD_SOURCE,
+					     fmt->which);
+
+	xvip_set_format_size(format, fmt);
+
+	return 0;
+}
+
+/*
+ * V4L2 Subdevice Operations
+ */
+
+static int xcresample_open(struct v4l2_subdev *subdev,
+			   struct v4l2_subdev_fh *fh)
+{
+	struct xcresample_device *xcresample = to_cresample(subdev);
+	struct v4l2_mbus_framefmt *format;
+
+	/* Initialize with default formats */
+	format = v4l2_subdev_get_try_format(subdev, fh->pad, XVIP_PAD_SINK);
+	*format = xcresample->default_formats[XVIP_PAD_SINK];
+
+	format = v4l2_subdev_get_try_format(subdev, fh->pad, XVIP_PAD_SOURCE);
+	*format = xcresample->default_formats[XVIP_PAD_SOURCE];
+
+	return 0;
+}
+
+static int xcresample_close(struct v4l2_subdev *subdev,
+			    struct v4l2_subdev_fh *fh)
+{
+	return 0;
+}
+
+static int xcresample_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct xcresample_device *xcresample =
+		container_of(ctrl->handler, struct xcresample_device,
+			     ctrl_handler);
+	switch (ctrl->id) {
+	case V4L2_CID_XILINX_CRESAMPLE_FIELD_PARITY:
+		xvip_clr_or_set(&xcresample->xvip, XCRESAMPLE_ENCODING,
+				XCRESAMPLE_ENCODING_FIELD, ctrl->val);
+		return 0;
+	case V4L2_CID_XILINX_CRESAMPLE_CHROMA_PARITY:
+		xvip_clr_or_set(&xcresample->xvip, XCRESAMPLE_ENCODING,
+				XCRESAMPLE_ENCODING_CHROMA, ctrl->val);
+		return 0;
+	}
+
+	return -EINVAL;
+
+}
+
+static const struct v4l2_ctrl_ops xcresample_ctrl_ops = {
+	.s_ctrl	= xcresample_s_ctrl,
+};
+
+static struct v4l2_subdev_video_ops xcresample_video_ops = {
+	.s_stream = xcresample_s_stream,
+};
+
+static struct v4l2_subdev_pad_ops xcresample_pad_ops = {
+	.enum_mbus_code		= xvip_enum_mbus_code,
+	.enum_frame_size	= xvip_enum_frame_size,
+	.get_fmt		= xcresample_get_format,
+	.set_fmt		= xcresample_set_format,
+};
+
+static struct v4l2_subdev_ops xcresample_ops = {
+	.video  = &xcresample_video_ops,
+	.pad    = &xcresample_pad_ops,
+};
+
+static const struct v4l2_subdev_internal_ops xcresample_internal_ops = {
+	.open	= xcresample_open,
+	.close	= xcresample_close,
+};
+
+/*
+ * Control Configs
+ */
+
+static const char *const xcresample_parity_string[] = {
+	"Even",
+	"Odd",
+};
+
+static struct v4l2_ctrl_config xcresample_field = {
+	.ops	= &xcresample_ctrl_ops,
+	.id	= V4L2_CID_XILINX_CRESAMPLE_FIELD_PARITY,
+	.name	= "Chroma Resampler: Encoding Field Parity",
+	.type	= V4L2_CTRL_TYPE_MENU,
+	.min	= 0,
+	.max	= 1,
+	.qmenu	= xcresample_parity_string,
+};
+
+static struct v4l2_ctrl_config xcresample_chroma = {
+	.ops	= &xcresample_ctrl_ops,
+	.id	= V4L2_CID_XILINX_CRESAMPLE_CHROMA_PARITY,
+	.name	= "Chroma Resampler: Encoding Chroma Parity",
+	.type	= V4L2_CTRL_TYPE_MENU,
+	.min	= 0,
+	.max	= 1,
+	.qmenu	= xcresample_parity_string,
+};
+
+/*
+ * Media Operations
+ */
+
+static const struct media_entity_operations xcresample_media_ops = {
+	.link_validate = v4l2_subdev_link_validate,
+};
+
+/*
+ * Power Management
+ */
+
+static int __maybe_unused xcresample_pm_suspend(struct device *dev)
+{
+	struct xcresample_device *xcresample = dev_get_drvdata(dev);
+
+	xvip_suspend(&xcresample->xvip);
+
+	return 0;
+}
+
+static int __maybe_unused xcresample_pm_resume(struct device *dev)
+{
+	struct xcresample_device *xcresample = dev_get_drvdata(dev);
+
+	xvip_resume(&xcresample->xvip);
+
+	return 0;
+}
+
+/*
+ * Platform Device Driver
+ */
+
+static int xcresample_parse_of(struct xcresample_device *xcresample)
+{
+	struct device *dev = xcresample->xvip.dev;
+	struct device_node *node = xcresample->xvip.dev->of_node;
+	struct device_node *ports;
+	struct device_node *port;
+	u32 port_id;
+	int ret;
+
+	ports = of_get_child_by_name(node, "ports");
+	if (ports == NULL)
+		ports = node;
+
+	/* Get the format description for each pad */
+	for_each_child_of_node(ports, port) {
+		if (port->name && (of_node_cmp(port->name, "port") == 0)) {
+			const struct xvip_video_format *vip_format;
+
+			vip_format = xvip_of_get_format(port);
+			if (IS_ERR(vip_format)) {
+				dev_err(dev, "invalid format in DT");
+				return PTR_ERR(vip_format);
+			}
+
+			ret = of_property_read_u32(port, "reg", &port_id);
+			if (ret < 0) {
+				dev_err(dev, "no reg in DT");
+				return ret;
+			}
+
+			if (port_id != 0 && port_id != 1) {
+				dev_err(dev, "invalid reg in DT");
+				return -EINVAL;
+			}
+
+			xcresample->vip_formats[port_id] = vip_format;
+		}
+	}
+
+	return 0;
+}
+
+static int xcresample_probe(struct platform_device *pdev)
+{
+	struct xcresample_device *xcresample;
+	struct v4l2_subdev *subdev;
+	struct v4l2_mbus_framefmt *default_format;
+	int ret;
+
+	xcresample = devm_kzalloc(&pdev->dev, sizeof(*xcresample), GFP_KERNEL);
+	if (!xcresample)
+		return -ENOMEM;
+
+	xcresample->xvip.dev = &pdev->dev;
+
+	ret = xcresample_parse_of(xcresample);
+	if (ret < 0)
+		return ret;
+
+	ret = xvip_init_resources(&xcresample->xvip);
+	if (ret < 0)
+		return ret;
+
+	/* Reset and initialize the core */
+	xvip_reset(&xcresample->xvip);
+
+	/* Initialize V4L2 subdevice and media entity */
+	subdev = &xcresample->xvip.subdev;
+	v4l2_subdev_init(subdev, &xcresample_ops);
+	subdev->dev = &pdev->dev;
+	subdev->internal_ops = &xcresample_internal_ops;
+	strlcpy(subdev->name, dev_name(&pdev->dev), sizeof(subdev->name));
+	v4l2_set_subdevdata(subdev, xcresample);
+	subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	/* Initialize default and active formats */
+	default_format = &xcresample->default_formats[XVIP_PAD_SINK];
+	default_format->code = xcresample->vip_formats[XVIP_PAD_SINK]->code;
+	default_format->field = V4L2_FIELD_NONE;
+	default_format->colorspace = V4L2_COLORSPACE_SRGB;
+	xvip_get_frame_size(&xcresample->xvip, default_format);
+
+	xcresample->formats[XVIP_PAD_SINK] = *default_format;
+
+	default_format = &xcresample->default_formats[XVIP_PAD_SOURCE];
+	*default_format = xcresample->default_formats[XVIP_PAD_SINK];
+	default_format->code = xcresample->vip_formats[XVIP_PAD_SOURCE]->code;
+
+	xcresample->formats[XVIP_PAD_SOURCE] = *default_format;
+
+	xcresample->pads[XVIP_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+	xcresample->pads[XVIP_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+	subdev->entity.ops = &xcresample_media_ops;
+	ret = media_entity_pads_init(&subdev->entity, 2, xcresample->pads);
+	if (ret < 0)
+		goto error;
+
+	v4l2_ctrl_handler_init(&xcresample->ctrl_handler, 2);
+	xcresample_field.def =
+		(xvip_read(&xcresample->xvip, XCRESAMPLE_ENCODING) &
+		 XCRESAMPLE_ENCODING_FIELD) ? 1 : 0;
+	v4l2_ctrl_new_custom(&xcresample->ctrl_handler, &xcresample_field,
+			     NULL);
+	xcresample_chroma.def =
+		(xvip_read(&xcresample->xvip, XCRESAMPLE_ENCODING) &
+		 XCRESAMPLE_ENCODING_CHROMA) ? 1 : 0;
+	v4l2_ctrl_new_custom(&xcresample->ctrl_handler, &xcresample_chroma,
+			     NULL);
+	if (xcresample->ctrl_handler.error) {
+		dev_err(&pdev->dev, "failed to add controls\n");
+		ret = xcresample->ctrl_handler.error;
+		goto error;
+	}
+	subdev->ctrl_handler = &xcresample->ctrl_handler;
+
+	platform_set_drvdata(pdev, xcresample);
+
+	xvip_print_version(&xcresample->xvip);
+
+	ret = v4l2_async_register_subdev(subdev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to register subdev\n");
+		goto error;
+	}
+
+	return 0;
+
+error:
+	v4l2_ctrl_handler_free(&xcresample->ctrl_handler);
+	media_entity_cleanup(&subdev->entity);
+	xvip_cleanup_resources(&xcresample->xvip);
+	return ret;
+}
+
+static int xcresample_remove(struct platform_device *pdev)
+{
+	struct xcresample_device *xcresample = platform_get_drvdata(pdev);
+	struct v4l2_subdev *subdev = &xcresample->xvip.subdev;
+
+	v4l2_async_unregister_subdev(subdev);
+	v4l2_ctrl_handler_free(&xcresample->ctrl_handler);
+	media_entity_cleanup(&subdev->entity);
+
+	xvip_cleanup_resources(&xcresample->xvip);
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(xcresample_pm_ops, xcresample_pm_suspend,
+			 xcresample_pm_resume);
+
+static const struct of_device_id xcresample_of_id_table[] = {
+	{ .compatible = "xlnx,v-cresample-4.0" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, xcresample_of_id_table);
+
+static struct platform_driver xcresample_driver = {
+	.driver			= {
+		.name		= "xilinx-cresample",
+		.pm		= &xcresample_pm_ops,
+		.of_match_table	= xcresample_of_id_table,
+	},
+	.probe			= xcresample_probe,
+	.remove			= xcresample_remove,
+};
+
+module_platform_driver(xcresample_driver);
+
+MODULE_DESCRIPTION("Xilinx Chroma Resampler Driver");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/xilinx-csi2rxss.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/xilinx-csi2rxss.c
@@ -0,0 +1,2133 @@
+/*
+ * Xilinx MIPI CSI2 Subsystem
+ *
+ * Copyright (C) 2016 Xilinx, Inc.
+ *
+ * Contacts: Vishal Sagar <vsagar@xilinx.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <dt-bindings/media/xilinx-vip.h>
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/compiler.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/spinlock_types.h>
+#include <linux/types.h>
+#include <linux/v4l2-subdev.h>
+#include <linux/xilinx-csi2rxss.h>
+#include <linux/xilinx-v4l2-controls.h>
+#include <media/media-entity.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-subdev.h>
+#include "xilinx-vip.h"
+
+/*
+ * MIPI CSI2 Rx register map, bitmask and offsets
+ */
+#define XCSI_CCR_OFFSET			0x00000000
+#define XCSI_CCR_SOFTRESET_SHIFT	1
+#define XCSI_CCR_COREENB_SHIFT		0
+#define XCSI_CCR_SOFTRESET_MASK		BIT(XCSI_CCR_SOFTRESET_SHIFT)
+#define XCSI_CCR_COREENB_MASK		BIT(XCSI_CCR_COREENB_SHIFT)
+
+#define XCSI_PCR_OFFSET			0x00000004
+#define XCSI_PCR_MAXLANES_MASK		0x00000018
+#define XCSI_PCR_ACTLANES_MASK		0x00000003
+#define XCSI_PCR_MAXLANES_SHIFT		3
+#define XCSI_PCR_ACTLANES_SHIFT		0
+
+#define XCSI_CSR_OFFSET			0x00000010
+#define XCSI_CSR_PKTCOUNT_SHIFT		16
+#define XCSI_CSR_SPFIFOFULL_SHIFT	3
+#define XCSI_CSR_SPFIFONE_SHIFT		2
+#define XCSI_CSR_SLBF_SHIFT		1
+#define XCSI_CSR_RIPCD_SHIFT		0
+#define XCSI_CSR_PKTCOUNT_MASK		0xFFFF0000
+#define XCSI_CSR_SPFIFOFULL_MASK	BIT(XCSI_CSR_SPFIFOFULL_SHIFT)
+#define XCSI_CSR_SPFIFONE_MASK		BIT(XCSI_CSR_SPFIFONE_SHIFT)
+#define XCSI_CSR_SLBF_MASK		BIT(XCSI_CSR_SLBF_SHIFT)
+#define XCSI_CSR_RIPCD_MASK		BIT(XCSI_CSR_RIPCD_SHIFT)
+
+#define XCSI_GIER_OFFSET		0x00000020
+#define XCSI_GIER_GIE_SHIFT		0
+#define XCSI_GIER_GIE_MASK		BIT(XCSI_GIER_GIE_SHIFT)
+#define XCSI_GIER_SET			1
+#define XCSI_GIER_RESET			0
+
+#define XCSI_ISR_OFFSET			0x00000024
+#define XCSI_ISR_FR_SHIFT		31
+#define XCSI_ISR_VCX_SHIFT		30
+#define XCSI_ISR_YUV420_SHIFT		28
+#define XCSI_ISR_ILC_SHIFT		21
+#define XCSI_ISR_SPFIFOF_SHIFT		20
+#define XCSI_ISR_SPFIFONE_SHIFT		19
+#define XCSI_ISR_SLBF_SHIFT		18
+#define XCSI_ISR_STOP_SHIFT		17
+#define XCSI_ISR_SOTERR_SHIFT		13
+#define XCSI_ISR_SOTSYNCERR_SHIFT	12
+#define XCSI_ISR_ECC2BERR_SHIFT		11
+#define XCSI_ISR_ECC1BERR_SHIFT		10
+#define XCSI_ISR_CRCERR_SHIFT		9
+#define XCSI_ISR_DATAIDERR_SHIFT	8
+#define XCSI_ISR_VC3FSYNCERR_SHIFT	7
+#define XCSI_ISR_VC3FLVLERR_SHIFT	6
+#define XCSI_ISR_VC2FSYNCERR_SHIFT	5
+#define XCSI_ISR_VC2FLVLERR_SHIFT	4
+#define XCSI_ISR_VC1FSYNCERR_SHIFT	3
+#define XCSI_ISR_VC1FLVLERR_SHIFT	2
+#define XCSI_ISR_VC0FSYNCERR_SHIFT	1
+#define XCSI_ISR_VC0FLVLERR_SHIFT	0
+#define XCSI_ISR_FR_MASK		BIT(XCSI_ISR_FR_SHIFT)
+#define XCSI_ISR_VCX_MASK		BIT(XCSI_ISR_VCX_SHIFT)
+#define XCSI_ISR_YUV420_MASK		BIT(XCSI_ISR_YUV420_SHIFT)
+#define XCSI_ISR_ILC_MASK		BIT(XCSI_ISR_ILC_SHIFT)
+#define XCSI_ISR_SPFIFOF_MASK		BIT(XCSI_ISR_SPFIFOF_SHIFT)
+#define XCSI_ISR_SPFIFONE_MASK		BIT(XCSI_ISR_SPFIFONE_SHIFT)
+#define XCSI_ISR_SLBF_MASK		BIT(XCSI_ISR_SLBF_SHIFT)
+#define XCSI_ISR_STOP_MASK		BIT(XCSI_ISR_STOP_SHIFT)
+#define XCSI_ISR_SOTERR_MASK		BIT(XCSI_ISR_SOTERR_SHIFT)
+#define XCSI_ISR_SOTSYNCERR_MASK	BIT(XCSI_ISR_SOTSYNCERR_SHIFT)
+#define XCSI_ISR_ECC2BERR_MASK		BIT(XCSI_ISR_ECC2BERR_SHIFT)
+#define XCSI_ISR_ECC1BERR_MASK		BIT(XCSI_ISR_ECC1BERR_SHIFT)
+#define XCSI_ISR_CRCERR_MASK		BIT(XCSI_ISR_CRCERR_SHIFT)
+#define XCSI_ISR_DATAIDERR_MASK		BIT(XCSI_ISR_DATAIDERR_SHIFT)
+#define XCSI_ISR_VC3FSYNCERR_MASK	BIT(XCSI_ISR_VC3FSYNCERR_SHIFT)
+#define XCSI_ISR_VC3FLVLERR_MASK	BIT(XCSI_ISR_VC3FLVLERR_SHIFT)
+#define XCSI_ISR_VC2FSYNCERR_MASK	BIT(XCSI_ISR_VC2FSYNCERR_SHIFT)
+#define XCSI_ISR_VC2FLVLERR_MASK	BIT(XCSI_ISR_VC2FLVLERR_SHIFT)
+#define XCSI_ISR_VC1FSYNCERR_MASK	BIT(XCSI_ISR_VC1FSYNCERR_SHIFT)
+#define XCSI_ISR_VC1FLVLERR_MASK	BIT(XCSI_ISR_VC1FLVLERR_SHIFT)
+#define XCSI_ISR_VC0FSYNCERR_MASK	BIT(XCSI_ISR_VC0FSYNCERR_SHIFT)
+#define XCSI_ISR_VC0FLVLERR_MASK	BIT(XCSI_ISR_VC0FLVLERR_SHIFT)
+#define XCSI_ISR_ALLINTR_MASK		0xD03FFFFF
+
+#define XCSI_INTR_PROT_MASK	(XCSI_ISR_VC3FSYNCERR_MASK |	\
+				 XCSI_ISR_VC3FLVLERR_MASK |	\
+				 XCSI_ISR_VC2FSYNCERR_MASK |	\
+				 XCSI_ISR_VC2FLVLERR_MASK |	\
+				 XCSI_ISR_VC1FSYNCERR_MASK |	\
+				 XCSI_ISR_VC1FLVLERR_MASK |	\
+				 XCSI_ISR_VC0FSYNCERR_MASK |	\
+				 XCSI_ISR_VC0FLVLERR_MASK |	\
+				 XCSI_ISR_VCX_MASK)
+
+#define XCSI_INTR_PKTLVL_MASK	(XCSI_ISR_ECC2BERR_MASK |	\
+				 XCSI_ISR_ECC1BERR_MASK |	\
+				 XCSI_ISR_CRCERR_MASK   |	\
+				 XCSI_ISR_DATAIDERR_MASK)
+
+#define XCSI_INTR_DPHY_MASK	(XCSI_ISR_SOTERR_MASK	|	\
+				 XCSI_ISR_SOTSYNCERR_MASK)
+
+#define XCSI_INTR_SPKT_MASK	(XCSI_ISR_SPFIFOF_MASK |	\
+				 XCSI_ISR_SPFIFONE_MASK)
+
+#define XCSI_INTR_FRAMERCVD_MASK	(XCSI_ISR_FR_MASK)
+
+#define XCSI_INTR_ERR_MASK	(XCSI_ISR_ILC_MASK |	\
+				 XCSI_ISR_YUV420_MASK | \
+				 XCSI_ISR_SLBF_MASK |	\
+				 XCSI_ISR_STOP_MASK)
+
+#define XCSI_IER_OFFSET			0x00000028
+#define XCSI_IER_FR_SHIFT		31
+#define XCSI_IER_VCX_SHIFT		30
+#define XCSI_IER_YUV420_SHIFT		28
+#define XCSI_IER_ILC_SHIFT		21
+#define XCSI_IER_SPFIFOF_SHIFT		20
+#define XCSI_IER_SPFIFONE_SHIFT		19
+#define XCSI_IER_SLBF_SHIFT		18
+#define XCSI_IER_STOP_SHIFT		17
+#define XCSI_IER_SOTERR_SHIFT		13
+#define XCSI_IER_SOTSYNCERR_SHIFT	12
+#define XCSI_IER_ECC2BERR_SHIFT		11
+#define XCSI_IER_ECC1BERR_SHIFT		10
+#define XCSI_IER_CRCERR_SHIFT		9
+#define XCSI_IER_DATAIDERR_SHIFT	8
+#define XCSI_IER_VC3FSYNCERR_SHIFT	7
+#define XCSI_IER_VC3FLVLERR_SHIFT	6
+#define XCSI_IER_VC2FSYNCERR_SHIFT	5
+#define XCSI_IER_VC2FLVLERR_SHIFT	4
+#define XCSI_IER_VC1FSYNCERR_SHIFT	3
+#define XCSI_IER_VC1FLVLERR_SHIFT	2
+#define XCSI_IER_VC0FSYNCERR_SHIFT	1
+#define XCSI_IER_VC0FLVLERR_SHIFT	0
+#define XCSI_IER_FR_MASK		BIT(XCSI_IER_FR_SHIFT)
+#define XCSI_IER_VCX_MASK		BIT(XCSI_IER_VCX_SHIFT)
+#define XCSI_IER_YUV420_MASK		BIT(XCSI_IER_YUV420_SHIFT)
+#define XCSI_IER_ILC_MASK		BIT(XCSI_IER_ILC_SHIFT)
+#define XCSI_IER_SPFIFOF_MASK		BIT(XCSI_IER_SPFIFOF_SHIFT)
+#define XCSI_IER_SPFIFONE_MASK		BIT(XCSI_IER_SPFIFONE_SHIFT)
+#define XCSI_IER_SLBF_MASK		BIT(XCSI_IER_SLBF_SHIFT)
+#define XCSI_IER_STOP_MASK		BIT(XCSI_IER_STOP_SHIFT)
+#define XCSI_IER_SOTERR_MASK		BIT(XCSI_IER_SOTERR_SHIFT)
+#define XCSI_IER_SOTSYNCERR_MASK	BIT(XCSI_IER_SOTSYNCERR_SHIFT)
+#define XCSI_IER_ECC2BERR_MASK		BIT(XCSI_IER_ECC2BERR_SHIFT)
+#define XCSI_IER_ECC1BERR_MASK		BIT(XCSI_IER_ECC1BERR_SHIFT)
+#define XCSI_IER_CRCERR_MASK		BIT(XCSI_IER_CRCERR_SHIFT)
+#define XCSI_IER_DATAIDERR_MASK		BIT(XCSI_IER_DATAIDERR_SHIFT)
+#define XCSI_IER_VC3FSYNCERR_MASK	BIT(XCSI_IER_VC3FSYNCERR_SHIFT)
+#define XCSI_IER_VC3FLVLERR_MASK	BIT(XCSI_IER_VC3FLVLERR_SHIFT)
+#define XCSI_IER_VC2FSYNCERR_MASK	BIT(XCSI_IER_VC2FSYNCERR_SHIFT)
+#define XCSI_IER_VC2FLVLERR_MASK	BIT(XCSI_IER_VC2FLVLERR_SHIFT)
+#define XCSI_IER_VC1FSYNCERR_MASK	BIT(XCSI_IER_VC1FSYNCERR_SHIFT)
+#define XCSI_IER_VC1FLVLERR_MASK	BIT(XCSI_IER_VC1FLVLERR_SHIFT)
+#define XCSI_IER_VC0FSYNCERR_MASK	BIT(XCSI_IER_VC0FSYNCERR_SHIFT)
+#define XCSI_IER_VC0FLVLERR_MASK	BIT(XCSI_IER_VC0FLVLERR_SHIFT)
+#define XCSI_IER_ALLINTR_MASK		0xD03FFFFF
+
+#define XCSI_SPKTR_OFFSET		0x00000030
+#define XCSI_SPKTR_DATA_SHIFT		8
+#define XCSI_SPKTR_VC_SHIFT		6
+#define XCSI_SPKTR_DT_SHIFT		0
+#define XCSI_SPKTR_DATA_MASK		0x00FFFF00
+#define XCSI_SPKTR_VC_MASK		0x000000C0
+#define XCSI_SPKTR_DT_MASK		0x0000003F
+
+#define XCSI_VCXR_OFFSET		0x00000034
+#define XCSI_VCXR_VC15FSYNCERR_MASK	BIT(23)
+#define XCSI_VCXR_VC15FLVLERR_MASK	BIT(22)
+#define XCSI_VCXR_VC14FSYNCERR_MASK	BIT(21)
+#define XCSI_VCXR_VC14FLVLERR_MASK	BIT(20)
+#define XCSI_VCXR_VC13FSYNCERR_MASK	BIT(19)
+#define XCSI_VCXR_VC13FLVLERR_MASK	BIT(18)
+#define XCSI_VCXR_VC12FSYNCERR_MASK	BIT(17)
+#define XCSI_VCXR_VC12FLVLERR_MASK	BIT(16)
+#define XCSI_VCXR_VC11FSYNCERR_MASK	BIT(15)
+#define XCSI_VCXR_VC11FLVLERR_MASK	BIT(14)
+#define XCSI_VCXR_VC10FSYNCERR_MASK	BIT(13)
+#define XCSI_VCXR_VC10FLVLERR_MASK	BIT(12)
+#define XCSI_VCXR_VC9FSYNCERR_MASK	BIT(11)
+#define XCSI_VCXR_VC9FLVLERR_MASK	BIT(10)
+#define XCSI_VCXR_VC8FSYNCERR_MASK	BIT(9)
+#define XCSI_VCXR_VC8FLVLERR_MASK	BIT(8)
+#define XCSI_VCXR_VC7FSYNCERR_MASK	BIT(7)
+#define XCSI_VCXR_VC7FLVLERR_MASK	BIT(6)
+#define XCSI_VCXR_VC6FSYNCERR_MASK	BIT(5)
+#define XCSI_VCXR_VC6FLVLERR_MASK	BIT(4)
+#define XCSI_VCXR_VC5FSYNCERR_MASK	BIT(3)
+#define XCSI_VCXR_VC5FLVLERR_MASK	BIT(2)
+#define XCSI_VCXR_VC4FSYNCERR_MASK	BIT(1)
+#define XCSI_VCXR_VC4FLVLERR_MASK	BIT(0)
+#define XCSI_VCXR_MASK			0x00FFFFFF
+
+#define XCSI_CLKINFR_OFFSET		0x0000003C
+#define XCSI_CLKINFR_STOP_SHIFT		1
+#define XCSI_CLKINFR_STOP_MASK		BIT(XCSI_CLKINFR_STOP_SHIFT)
+
+#define XCSI_L0INFR_OFFSET		0x00000040
+#define XCSI_L1INFR_OFFSET		0x00000044
+#define XCSI_L2INFR_OFFSET		0x00000048
+#define XCSI_L3INFR_OFFSET		0x0000004C
+#define XCSI_LXINFR_STOP_SHIFT		5
+#define XCSI_LXINFR_SOTERR_SHIFT	1
+#define XCSI_LXINFR_SOTSYNCERR_SHIFT	0
+#define XCSI_LXINFR_STOP_MASK		BIT(XCSI_LXINFR_STOP_SHIFT)
+#define XCSI_LXINFR_SOTERR_MASK		BIT(XCSI_LXINFR_SOTERR_SHIFT)
+#define XCSI_LXINFR_SOTSYNCERR_MASK	BIT(XCSI_LXINFR_SOTSYNCERR_SHIFT)
+
+#define XCSI_VC0INF1R_OFFSET		0x00000060
+#define XCSI_VC1INF1R_OFFSET		0x00000068
+#define XCSI_VC2INF1R_OFFSET		0x00000070
+#define XCSI_VC3INF1R_OFFSET		0x00000078
+#define XCSI_VC4INF1R_OFFSET		0x00000080
+#define XCSI_VC5INF1R_OFFSET		0x00000088
+#define XCSI_VC6INF1R_OFFSET		0x00000090
+#define XCSI_VC7INF1R_OFFSET		0x00000098
+#define XCSI_VC8INF1R_OFFSET		0x000000A0
+#define XCSI_VC9INF1R_OFFSET		0x000000A8
+#define XCSI_VC10INF1R_OFFSET		0x000000B0
+#define XCSI_VC11INF1R_OFFSET		0x000000B8
+#define XCSI_VC12INF1R_OFFSET		0x000000C0
+#define XCSI_VC13INF1R_OFFSET		0x000000C8
+#define XCSI_VC14INF1R_OFFSET		0x000000D0
+#define XCSI_VC15INF1R_OFFSET		0x000000D8
+#define XCSI_VCXINF1R_LINECOUNT_SHIFT	16
+#define XCSI_VCXINF1R_BYTECOUNT_SHIFT	0
+#define XCSI_VCXINF1R_LINECOUNT_MASK	0xFFFF0000
+#define XCSI_VCXINF1R_BYTECOUNT_MASK	0x0000FFFF
+
+#define XCSI_VC0INF2R_OFFSET		0x00000064
+#define XCSI_VC1INF2R_OFFSET		0x0000006C
+#define XCSI_VC2INF2R_OFFSET		0x00000074
+#define XCSI_VC3INF2R_OFFSET		0x0000007C
+#define XCSI_VC4INF2R_OFFSET		0x00000084
+#define XCSI_VC5INF2R_OFFSET		0x0000008C
+#define XCSI_VC6INF2R_OFFSET		0x00000094
+#define XCSI_VC7INF2R_OFFSET		0x0000009C
+#define XCSI_VC8INF2R_OFFSET		0x000000A4
+#define XCSI_VC9INF2R_OFFSET		0x000000AC
+#define XCSI_VC10INF2R_OFFSET		0x000000B4
+#define XCSI_VC11INF2R_OFFSET		0x000000BC
+#define XCSI_VC12INF2R_OFFSET		0x000000C4
+#define XCSI_VC13INF2R_OFFSET		0x000000CC
+#define XCSI_VC14INF2R_OFFSET		0x000000D4
+#define XCSI_VC15INF2R_OFFSET		0x000000DC
+#define XCSI_VCXINF2R_DATATYPE_SHIFT	0
+#define XCSI_VCXINF2R_DATATYPE_MASK	0x0000003F
+
+#define XDPHY_CTRLREG_OFFSET		0x0
+#define XDPHY_CTRLREG_DPHYEN_SHIFT	1
+#define XDPHY_CTRLREG_DPHYEN_MASK	BIT(XDPHY_CTRLREG_DPHYEN_SHIFT)
+
+#define XDPHY_CLKSTATREG_OFFSET		0x18
+#define XDPHY_CLKSTATREG_MODE_SHIFT	0
+#define XDPHY_CLKSTATREG_MODE_MASK	0x3
+#define XDPHY_LOW_POWER_MODE		0x0
+#define XDPHY_HI_SPEED_MODE		0x1
+#define XDPHY_ESC_MODE			0x2
+
+/*
+ * Interrupt mask
+ */
+#define XCSI_INTR_MASK		(XCSI_ISR_ALLINTR_MASK & ~XCSI_ISR_STOP_MASK)
+/*
+ * Timeout for reset
+ */
+#define XCSI_TIMEOUT_VAL	(1000) /* us */
+
+/*
+ * Max string length for CSI Data type string
+ */
+#define MAX_XIL_CSIDT_STR_LENGTH 64
+
+/*
+ * Maximum number of short packet events per file handle.
+ */
+#define XCSI_MAX_SPKT		(512)
+
+/* Number of media pads */
+#define XILINX_CSI_MEDIA_PADS	(2)
+
+#define XCSI_DEFAULT_WIDTH	(1920)
+#define XCSI_DEFAULT_HEIGHT	(1080)
+
+#define XCSI_DPHY_CLK_MIN	197000000000UL
+#define XCSI_DPHY_CLK_MAX	203000000000UL
+#define XCSI_DPHY_CLK_REQ	200000000000UL
+
+/*
+ * Macro to return "true" or "false" string if bit is set
+ */
+#define XCSI_GET_BITSET_STR(val, mask)	(val) & (mask) ? "true" : "false"
+
+#define XCSI_CLK_PROP		BIT(0)
+#define XCSI_DPHY_PROP		BIT(1)
+#define XCSI_DPHY_ADDR_PROP	BIT(2)
+
+/**
+ * struct xcsi2rxss_feature - dt or IP property structure
+ * @flags: Bitmask of properties enabled in IP or dt
+ */
+struct xcsi2rxss_feature {
+	u32 flags;
+};
+
+enum CSI_DataTypes {
+	MIPI_CSI_DT_FRAME_START_CODE = 0x00,
+	MIPI_CSI_DT_FRAME_END_CODE,
+	MIPI_CSI_DT_LINE_START_CODE,
+	MIPI_CSI_DT_LINE_END_CODE,
+	MIPI_CSI_DT_SYNC_RSVD_04,
+	MIPI_CSI_DT_SYNC_RSVD_05,
+	MIPI_CSI_DT_SYNC_RSVD_06,
+	MIPI_CSI_DT_SYNC_RSVD_07,
+	MIPI_CSI_DT_GSPKT_08,
+	MIPI_CSI_DT_GSPKT_09,
+	MIPI_CSI_DT_GSPKT_0A,
+	MIPI_CSI_DT_GSPKT_0B,
+	MIPI_CSI_DT_GSPKT_0C,
+	MIPI_CSI_DT_GSPKT_0D,
+	MIPI_CSI_DT_GSPKT_0E,
+	MIPI_CSI_DT_GSPKT_0F,
+	MIPI_CSI_DT_GLPKT_10,
+	MIPI_CSI_DT_GLPKT_11,
+	MIPI_CSI_DT_GLPKT_12,
+	MIPI_CSI_DT_GLPKT_13,
+	MIPI_CSI_DT_GLPKT_14,
+	MIPI_CSI_DT_GLPKT_15,
+	MIPI_CSI_DT_GLPKT_16,
+	MIPI_CSI_DT_GLPKT_17,
+	MIPI_CSI_DT_YUV_420_8B,
+	MIPI_CSI_DT_YUV_420_10B,
+	MIPI_CSI_DT_YUV_420_8B_LEGACY,
+	MIPI_CSI_DT_YUV_RSVD,
+	MIPI_CSI_DT_YUV_420_8B_CSPS,
+	MIPI_CSI_DT_YUV_420_10B_CSPS,
+	MIPI_CSI_DT_YUV_422_8B,
+	MIPI_CSI_DT_YUV_422_10B,
+	MIPI_CSI_DT_RGB_444,
+	MIPI_CSI_DT_RGB_555,
+	MIPI_CSI_DT_RGB_565,
+	MIPI_CSI_DT_RGB_666,
+	MIPI_CSI_DT_RGB_888,
+	MIPI_CSI_DT_RGB_RSVD_25,
+	MIPI_CSI_DT_RGB_RSVD_26,
+	MIPI_CSI_DT_RGB_RSVD_27,
+	MIPI_CSI_DT_RAW_6,
+	MIPI_CSI_DT_RAW_7,
+	MIPI_CSI_DT_RAW_8,
+	MIPI_CSI_DT_RAW_10,
+	MIPI_CSI_DT_RAW_12,
+	MIPI_CSI_DT_RAW_14,
+	MIPI_CSI_DT_RAW_16,
+	MIPI_CSI_DT_RAW_20,
+	MIPI_CSI_DT_USER_30,
+	MIPI_CSI_DT_USER_31,
+	MIPI_CSI_DT_USER_32,
+	MIPI_CSI_DT_USER_33,
+	MIPI_CSI_DT_USER_34,
+	MIPI_CSI_DT_USER_35,
+	MIPI_CSI_DT_USER_36,
+	MIPI_CSI_DT_USER_37,
+	MIPI_CSI_DT_RSVD_38,
+	MIPI_CSI_DT_RSVD_39,
+	MIPI_CSI_DT_RSVD_3A,
+	MIPI_CSI_DT_RSVD_3B,
+	MIPI_CSI_DT_RSVD_3C,
+	MIPI_CSI_DT_RSVD_3D,
+	MIPI_CSI_DT_RSVD_3E,
+	MIPI_CSI_DT_RSVD_3F
+};
+
+/**
+ * struct pixel_format - Data Type to string name structure
+ * @PixelFormat: MIPI CSI2 Data type
+ * @PixelFormatStr: String name of Data Type
+ */
+struct pixel_format {
+	enum CSI_DataTypes PixelFormat;
+	char PixelFormatStr[MAX_XIL_CSIDT_STR_LENGTH];
+};
+
+/**
+ * struct xcsi2rxss_event - Event log structure
+ * @mask: Event mask
+ * @name: Name of the event
+ * @counter: Count number of events
+ */
+struct xcsi2rxss_event {
+	u32 mask;
+	const char * const name;
+	unsigned int counter;
+};
+
+/*
+ * struct xcsi2rxss_core - Core configuration CSI2 Rx Subsystem device structure
+ * @dev: Platform structure
+ * @iomem: Base address of subsystem
+ * @irq: requested irq number
+ * @dphy_present: Flag for DPHY register interface presence
+ * @dphy_offset: DPHY registers offset
+ * @enable_active_lanes: If number of active lanes can be modified
+ * @max_num_lanes: Maximum number of lanes present
+ * @vfb: Video Format Bridge enabled or not
+ * @ppc: pixels per clock
+ * @vc: Virtual Channel
+ * @axis_tdata_width: AXI Stream data width
+ * @datatype: Data type filter
+ * @pxlformat: String with CSI pixel format from IP
+ * @num_lanes: Number of lanes requested from application
+ * @events: Structure to maintain event logs
+ * @vcx_events: Structure to maintain VCX event logs
+ * @en_vcx: If more than 4 VC are enabled.
+ * @cfg: Pointer to csi2rxss config structure
+ * @lite_aclk: AXI4-Lite interface clock
+ * @video_aclk: Video clock
+ * @dphy_clk_200M: 200MHz DPHY clock
+ * @rst_gpio: video_aresetn
+ */
+struct xcsi2rxss_core {
+	struct device *dev;
+	void __iomem *iomem;
+	int irq;
+	u32 dphy_offset;
+	bool dphy_present;
+	bool enable_active_lanes;
+	u32 max_num_lanes;
+	bool vfb;
+	u32 ppc;
+	u32 vc;
+	u32 axis_tdata_width;
+	u32 datatype;
+	const char *pxlformat;
+	u32 num_lanes;
+	struct xcsi2rxss_event *events;
+	struct xcsi2rxss_event *vcx_events;
+	bool en_vcx;
+	const struct xcsi2rxss_feature *cfg;
+	struct clk *lite_aclk;
+	struct clk *video_aclk;
+	struct clk *dphy_clk_200M;
+	struct gpio_desc *rst_gpio;
+};
+
+/**
+ * struct xcsi2rxss_state - CSI2 Rx Subsystem device structure
+ * @core: Core structure for MIPI CSI2 Rx Subsystem
+ * @subdev: The v4l2 subdev structure
+ * @ctrl_handler: control handler
+ * @formats: Active V4L2 formats on each pad
+ * @default_format: default V4L2 media bus format
+ * @vip_format: format information corresponding to the active format
+ * @event: Holds the short packet event
+ * @lock: mutex for serializing operations
+ * @pads: media pads
+ * @npads: number of pads
+ * @streaming: Flag for storing streaming state
+ * @suspended: Flag for storing suspended state
+ *
+ * This structure contains the device driver related parameters
+ */
+struct xcsi2rxss_state {
+	struct xcsi2rxss_core core;
+	struct v4l2_subdev subdev;
+	struct v4l2_ctrl_handler ctrl_handler;
+	struct v4l2_mbus_framefmt formats;
+	struct v4l2_mbus_framefmt default_format;
+	const struct xvip_video_format *vip_format;
+	struct v4l2_event event;
+	struct mutex lock;
+	struct media_pad pads[XILINX_CSI_MEDIA_PADS];
+	unsigned int npads;
+	bool streaming;
+	bool suspended;
+};
+
+static const struct xcsi2rxss_feature xlnx_csi2rxss_v5_0 = {
+	.flags = XCSI_CLK_PROP | XCSI_DPHY_PROP | XCSI_DPHY_ADDR_PROP,
+};
+
+static const struct xcsi2rxss_feature xlnx_csi2rxss_v4_1 = {
+	.flags = XCSI_CLK_PROP | XCSI_DPHY_PROP,
+};
+
+static const struct xcsi2rxss_feature xlnx_csi2rxss_v4_0 = {
+	.flags = XCSI_CLK_PROP,
+};
+
+static const struct xcsi2rxss_feature xlnx_csi2rxss_v2_0 = {
+	.flags = 0,
+};
+
+static const struct of_device_id xcsi2rxss_of_id_table[] = {
+	{ .compatible = "xlnx,mipi-csi2-rx-subsystem-2.0",
+		.data = &xlnx_csi2rxss_v2_0 },
+	{ .compatible = "xlnx,mipi-csi2-rx-subsystem-3.0",
+		.data = &xlnx_csi2rxss_v2_0 },
+	{ .compatible = "xlnx,mipi-csi2-rx-subsystem-4.0",
+		.data = &xlnx_csi2rxss_v4_0 },
+	{ .compatible = "xlnx,mipi-csi2-rx-subsystem-4.1",
+		.data = &xlnx_csi2rxss_v4_1 },
+	{ .compatible = "xlnx,mipi-csi2-rx-subsystem-5.0",
+		.data = &xlnx_csi2rxss_v5_0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, xcsi2rxss_of_id_table);
+
+static inline struct xcsi2rxss_state *
+to_xcsi2rxssstate(struct v4l2_subdev *subdev)
+{
+	return container_of(subdev, struct xcsi2rxss_state, subdev);
+}
+
+/*
+ * Regsiter related operations
+ */
+static inline u32 xcsi2rxss_read(struct xcsi2rxss_core *xcsi2rxss,
+					u32 addr)
+{
+	return ioread32(xcsi2rxss->iomem + addr);
+}
+
+static inline void xcsi2rxss_write(struct xcsi2rxss_core *xcsi2rxss,
+					u32 addr,
+					u32 value)
+{
+	iowrite32(value, xcsi2rxss->iomem + addr);
+}
+
+static inline void xcsi2rxss_clr(struct xcsi2rxss_core *xcsi2rxss,
+					u32 addr,
+					u32 clr)
+{
+	xcsi2rxss_write(xcsi2rxss,
+			addr,
+			xcsi2rxss_read(xcsi2rxss, addr) & ~clr);
+}
+
+static inline void xcsi2rxss_set(struct xcsi2rxss_core *xcsi2rxss,
+					u32 addr,
+					u32 set)
+{
+	xcsi2rxss_write(xcsi2rxss,
+			addr,
+			xcsi2rxss_read(xcsi2rxss, addr) | set);
+}
+
+static const struct pixel_format pixel_formats[] = {
+	{ MIPI_CSI_DT_YUV_420_8B, "YUV420_8bit" },
+	{ MIPI_CSI_DT_YUV_420_10B, "YUV420_10bit" },
+	{ MIPI_CSI_DT_YUV_420_8B_LEGACY, "Legacy_YUV420_8bit" },
+	{ MIPI_CSI_DT_YUV_420_8B_CSPS, "YUV420_8bit_CSPS" },
+	{ MIPI_CSI_DT_YUV_420_10B_CSPS, "YUV420_10bit_CSPS" },
+	{ MIPI_CSI_DT_YUV_422_8B, "YUV422_8bit" },
+	{ MIPI_CSI_DT_YUV_422_10B, "YUV422_10bit" },
+	{ MIPI_CSI_DT_RGB_444, "RGB444" },
+	{ MIPI_CSI_DT_RGB_555, "RGB555" },
+	{ MIPI_CSI_DT_RGB_565, "RGB565" },
+	{ MIPI_CSI_DT_RGB_666, "RGB666" },
+	{ MIPI_CSI_DT_RGB_888, "RGB888" },
+	{ MIPI_CSI_DT_RAW_6, "RAW6" },
+	{ MIPI_CSI_DT_RAW_7, "RAW7" },
+	{ MIPI_CSI_DT_RAW_8, "RAW8" },
+	{ MIPI_CSI_DT_RAW_10, "RAW10" },
+	{ MIPI_CSI_DT_RAW_12, "RAW12" },
+	{ MIPI_CSI_DT_RAW_14, "RAW14"},
+	{ MIPI_CSI_DT_RAW_16, "RAW16"},
+	{ MIPI_CSI_DT_RAW_20, "RAW20"}
+};
+
+static struct xcsi2rxss_event xcsi2rxss_events[] = {
+	{ XCSI_ISR_FR_MASK, "Frame Received", 0 },
+	{ XCSI_ISR_VCX_MASK, "VCX Frame Errors", 0 },
+	{ XCSI_ISR_YUV420_MASK, "YUV 420 Word Count Error", 0 },
+	{ XCSI_ISR_ILC_MASK, "Invalid Lane Count Error", 0 },
+	{ XCSI_ISR_SPFIFOF_MASK, "Short Packet FIFO OverFlow Error", 0 },
+	{ XCSI_ISR_SPFIFONE_MASK, "Short Packet FIFO Not Empty", 0 },
+	{ XCSI_ISR_SLBF_MASK, "Streamline Buffer Full Error", 0 },
+	{ XCSI_ISR_STOP_MASK, "Lane Stop State", 0 },
+	{ XCSI_ISR_SOTERR_MASK, "SOT Error", 0 },
+	{ XCSI_ISR_SOTSYNCERR_MASK, "SOT Sync Error", 0 },
+	{ XCSI_ISR_ECC2BERR_MASK, "2 Bit ECC Unrecoverable Error", 0 },
+	{ XCSI_ISR_ECC1BERR_MASK, "1 Bit ECC Recoverable Error", 0 },
+	{ XCSI_ISR_CRCERR_MASK,	"CRC Error", 0 },
+	{ XCSI_ISR_DATAIDERR_MASK, "Data Id Error", 0 },
+	{ XCSI_ISR_VC3FSYNCERR_MASK, "Virtual Channel 3 Frame Sync Error", 0 },
+	{ XCSI_ISR_VC3FLVLERR_MASK, "Virtual Channel 3 Frame Level Error", 0 },
+	{ XCSI_ISR_VC2FSYNCERR_MASK, "Virtual Channel 2 Frame Sync Error", 0 },
+	{ XCSI_ISR_VC2FLVLERR_MASK, "Virtual Channel 2 Frame Level Error", 0 },
+	{ XCSI_ISR_VC1FSYNCERR_MASK, "Virtual Channel 1 Frame Sync Error", 0 },
+	{ XCSI_ISR_VC1FLVLERR_MASK, "Virtual Channel 1 Frame Level Error", 0 },
+	{ XCSI_ISR_VC0FSYNCERR_MASK, "Virtual Channel 0 Frame Sync Error", 0 },
+	{ XCSI_ISR_VC0FLVLERR_MASK, "Virtual Channel 0 Frame Level Error", 0 }
+};
+
+#define XMIPICSISS_NUM_EVENTS ARRAY_SIZE(xcsi2rxss_events)
+
+#define XMIPICSISS_VCX_START		(4)
+#define XMIPICSISS_MAX_VC		(4)
+#define XMIPICSISS_MAX_VCX		(16)
+
+/* There are 2 events frame sync and frame level error per VC */
+#define XMIPICSISS_VCX_NUM_EVENTS	((XMIPICSISS_MAX_VCX -\
+					 XMIPICSISS_MAX_VC) * 2)
+
+/**
+ * xcsi2rxss_clr_and_set - Clear and set the register with a bitmask
+ * @xcsi2rxss: Xilinx MIPI CSI2 Rx Subsystem subdev core struct
+ * @addr: address of register
+ * @clr: bitmask to be cleared
+ * @set: bitmask to be set
+ *
+ * Clear a bit(s) of mask @clr in the register at address @addr, then set
+ * a bit(s) of mask @set in the register after.
+ */
+static void xcsi2rxss_clr_and_set(struct xcsi2rxss_core *xcsi2rxss,
+				u32 addr, u32 clr, u32 set)
+{
+	u32 reg;
+
+	reg = xcsi2rxss_read(xcsi2rxss, addr);
+	reg &= ~clr;
+	reg |= set;
+	xcsi2rxss_write(xcsi2rxss, addr, reg);
+}
+
+/**
+ * xcsi2rxss_pxlfmtstrtodt - Convert pixel format string got from dts
+ * to data type.
+ * @pxlfmtstr: String obtained while parsing device node
+ *
+ * This function takes a CSI pixel format string obtained while parsing
+ * device tree node and converts it to data type.
+ *
+ * Eg. "RAW8" string is converted to 0x2A.
+ * Refer to MIPI CSI2 specification for details.
+ *
+ * Return: Equivalent pixel format value from table
+ */
+static u32 xcsi2rxss_pxlfmtstrtodt(const char *pxlfmtstr)
+{
+	u32 Index;
+	u32 MaxEntries = ARRAY_SIZE(pixel_formats);
+
+	for (Index = 0; Index < MaxEntries; Index++) {
+		if (!strncmp(pixel_formats[Index].PixelFormatStr,
+				pxlfmtstr, MAX_XIL_CSIDT_STR_LENGTH))
+			return pixel_formats[Index].PixelFormat;
+	}
+
+	return -EINVAL;
+}
+
+/**
+ * xcsi2rxss_pxlfmtdttostr - Convert pixel format data type to string.
+ * @datatype: MIPI CSI-2 Data Type
+ *
+ * This function takes a CSI pixel format data type and returns a
+ * pointer to the string name.
+ *
+ * Eg. 0x2A returns "RAW8" string.
+ * Refer to MIPI CSI2 specification for details.
+ *
+ * Return: Equivalent pixel format string from table
+ */
+static const char *xcsi2rxss_pxlfmtdttostr(u32 datatype)
+{
+	u32 Index;
+	u32 MaxEntries = ARRAY_SIZE(pixel_formats);
+
+	for (Index = 0; Index < MaxEntries; Index++) {
+		if (pixel_formats[Index].PixelFormat == datatype)
+			return pixel_formats[Index].PixelFormatStr;
+	}
+
+	return NULL;
+}
+
+/**
+ * xcsi2rxss_enable - Enable or disable the CSI Core
+ * @core: Core Xilinx CSI2 Rx Subsystem structure pointer
+ * @flag: true for enabling, false for disabling
+ *
+ * This function enables/disables the MIPI CSI2 Rx Subsystem core.
+ * After enabling the CSI2 Rx core, the DPHY is enabled in case the
+ * register interface for it is present.
+ */
+static void xcsi2rxss_enable(struct xcsi2rxss_core *core, bool flag)
+{
+	u32 DphyCtrlRegOffset = core->dphy_offset + XDPHY_CTRLREG_OFFSET;
+
+	if (flag) {
+		xcsi2rxss_write(core, XCSI_CCR_OFFSET, XCSI_CCR_COREENB_MASK);
+		if (core->dphy_present)
+			xcsi2rxss_write(core, DphyCtrlRegOffset,
+					XDPHY_CTRLREG_DPHYEN_MASK);
+	} else {
+		xcsi2rxss_write(core, XCSI_CCR_OFFSET, 0);
+		if (core->dphy_present)
+			xcsi2rxss_write(core, DphyCtrlRegOffset, 0);
+	}
+
+}
+
+/**
+ * xcsi2rxss_interrupts_enable - Enable or disable CSI interrupts
+ * @core: Core Xilinx CSI2 Rx Subsystem structure pointer
+ * @flag: true for enabling, false for disabling
+ *
+ * This function enables/disables the interrupts for the MIPI CSI2
+ * Rx Subsystem.
+ */
+static void xcsi2rxss_interrupts_enable(struct xcsi2rxss_core *core, bool flag)
+{
+	if (flag) {
+		xcsi2rxss_clr(core, XCSI_GIER_OFFSET, XCSI_GIER_GIE_MASK);
+		xcsi2rxss_write(core, XCSI_IER_OFFSET, XCSI_INTR_MASK);
+		xcsi2rxss_set(core, XCSI_GIER_OFFSET, XCSI_GIER_GIE_MASK);
+	} else {
+		xcsi2rxss_clr(core, XCSI_IER_OFFSET, XCSI_INTR_MASK);
+		xcsi2rxss_clr(core, XCSI_GIER_OFFSET, XCSI_GIER_GIE_MASK);
+	}
+}
+
+/**
+ * xcsi2rxss_reset - Does a soft reset of the MIPI CSI2 Rx Subsystem
+ * @core: Core Xilinx CSI2 Rx Subsystem structure pointer
+ *
+ * Return: 0 - on success OR -ETIME if reset times out
+ */
+static int xcsi2rxss_reset(struct xcsi2rxss_core *core)
+{
+	u32 Timeout = XCSI_TIMEOUT_VAL;
+
+	xcsi2rxss_set(core, XCSI_CCR_OFFSET, XCSI_CCR_SOFTRESET_MASK);
+
+	while (xcsi2rxss_read(core, XCSI_CSR_OFFSET) & XCSI_CSR_RIPCD_MASK) {
+		if (Timeout == 0) {
+			dev_err(core->dev, "Xilinx CSI2 Rx Subsystem Soft Reset Timeout!\n");
+			return -ETIME;
+		}
+
+		Timeout--;
+		udelay(1);
+	}
+
+	xcsi2rxss_clr(core, XCSI_CCR_OFFSET, XCSI_CCR_SOFTRESET_MASK);
+	return 0;
+}
+
+static void xcsi2rxss_stop_stream(struct xcsi2rxss_state *xcsi2rxss)
+{
+	xcsi2rxss_interrupts_enable(&xcsi2rxss->core, false);
+	xcsi2rxss_enable(&xcsi2rxss->core, false);
+}
+
+/**
+ * xcsi2rxss_irq_handler - Interrupt handler for CSI-2
+ * @irq: IRQ number
+ * @dev_id: Pointer to device state
+ *
+ * In the interrupt handler, a list of event counters are updated for
+ * corresponding interrupts. This is useful to get status / debug.
+ * If the short packet FIFO not empty or overflow interrupt is received
+ * capture the short packet and notify of event occurrence
+ *
+ * Return: IRQ_HANDLED after handling interrupts
+ */
+static irqreturn_t xcsi2rxss_irq_handler(int irq, void *dev_id)
+{
+	struct xcsi2rxss_state *state = (struct xcsi2rxss_state *)dev_id;
+	struct xcsi2rxss_core *core = &state->core;
+	u32 status;
+
+	status = xcsi2rxss_read(core, XCSI_ISR_OFFSET) & XCSI_INTR_MASK;
+	dev_dbg(core->dev, "interrupt status = 0x%08x\n", status);
+
+	if (!status)
+		return IRQ_NONE;
+
+	if (status & XCSI_ISR_SPFIFONE_MASK) {
+
+		memset(&state->event, 0, sizeof(state->event));
+
+		state->event.type = V4L2_EVENT_XLNXCSIRX_SPKT;
+
+		*((u32 *)(&state->event.u.data)) =
+			xcsi2rxss_read(core, XCSI_SPKTR_OFFSET);
+
+		v4l2_subdev_notify_event(&state->subdev, &state->event);
+	}
+
+	if (status & XCSI_ISR_SPFIFOF_MASK) {
+		dev_alert(core->dev, "Short packet FIFO overflowed\n");
+
+		memset(&state->event, 0, sizeof(state->event));
+
+		state->event.type = V4L2_EVENT_XLNXCSIRX_SPKT_OVF;
+
+		v4l2_subdev_notify_event(&state->subdev, &state->event);
+	}
+
+	if (status & (XCSI_ISR_SLBF_MASK | XCSI_ISR_YUV420_MASK)) {
+		if (status & XCSI_ISR_SLBF_MASK)
+			dev_alert(core->dev, "Stream Line Buffer Full!\n");
+		if (status & XCSI_ISR_YUV420_MASK)
+			dev_alert(core->dev, "YUV 420 Word count error!\n");
+
+		if (core->rst_gpio) {
+			gpiod_set_value(core->rst_gpio, 1);
+			/* minimum 40 dphy_clk_200M cycles */
+			ndelay(250);
+			gpiod_set_value(core->rst_gpio, 0);
+		}
+
+		xcsi2rxss_stop_stream(state);
+
+		memset(&state->event, 0, sizeof(state->event));
+
+		state->event.type = V4L2_EVENT_XLNXCSIRX_SLBF;
+
+		v4l2_subdev_notify_event(&state->subdev, &state->event);
+	}
+
+	if (status & XCSI_ISR_ALLINTR_MASK) {
+		unsigned int i;
+
+		for (i = 0; i < XMIPICSISS_NUM_EVENTS; i++) {
+			if (!(status & core->events[i].mask))
+				continue;
+			core->events[i].counter++;
+			dev_dbg(core->dev, "%s: %d\n", core->events[i].name,
+					core->events[i].counter);
+		}
+
+		if (status & XCSI_ISR_VCX_MASK && core->en_vcx) {
+			u32 vcxstatus;
+
+			vcxstatus = xcsi2rxss_read(core, XCSI_VCXR_OFFSET);
+			vcxstatus &= XCSI_VCXR_MASK;
+			for (i = 0; i < XMIPICSISS_VCX_NUM_EVENTS; i++) {
+				if (!(vcxstatus & core->vcx_events[i].mask))
+					continue;
+				core->vcx_events[i].counter++;
+			}
+			xcsi2rxss_write(core, XCSI_VCXR_OFFSET, vcxstatus);
+		}
+	}
+
+	xcsi2rxss_write(core, XCSI_ISR_OFFSET, status);
+
+	return IRQ_HANDLED;
+}
+
+static void xcsi2rxss_reset_event_counters(struct xcsi2rxss_state *state)
+{
+	int i;
+
+	for (i = 0; i < XMIPICSISS_NUM_EVENTS; i++)
+		state->core.events[i].counter = 0;
+
+	if (!state->core.en_vcx)
+		return;
+
+	for (i = 0; i < XMIPICSISS_VCX_NUM_EVENTS; i++)
+		state->core.vcx_events[i].counter = 0;
+}
+
+/**
+ * xcsi2rxss_log_counters - Print out the event counters.
+ * @state: Pointer to device state
+ *
+ */
+static void xcsi2rxss_log_counters(struct xcsi2rxss_state *state)
+{
+	int i;
+
+	for (i = 0; i < XMIPICSISS_NUM_EVENTS; i++) {
+		if (state->core.events[i].counter > 0)
+			v4l2_info(&state->subdev, "%s events: %d\n",
+				  state->core.events[i].name,
+				  state->core.events[i].counter);
+	}
+
+	if (!state->core.en_vcx)
+		return;
+
+	for (i = 0; i < XMIPICSISS_VCX_NUM_EVENTS; i++) {
+		if (state->core.vcx_events[i].counter > 0)
+			v4l2_info(&state->subdev,
+				  "VC %d Frame %s error vcx events: %d\n",
+				  (i / 2) + XMIPICSISS_VCX_START,
+				  i & 1 ? "Sync" : "Level",
+				  state->core.vcx_events[i].counter);
+	}
+}
+
+/**
+ * xcsi2rxss_log_status - Logs the status of the CSI-2 Receiver
+ * @sd: Pointer to V4L2 subdevice structure
+ *
+ * This function prints the current status of Xilinx MIPI CSI-2
+ *
+ * Return: 0 on success
+ */
+static int xcsi2rxss_log_status(struct v4l2_subdev *sd)
+{
+	struct xcsi2rxss_state *xcsi2rxss = to_xcsi2rxssstate(sd);
+	struct xcsi2rxss_core *core = &xcsi2rxss->core;
+	u32 reg, data, i, max_vc;
+
+	mutex_lock(&xcsi2rxss->lock);
+
+	xcsi2rxss_log_counters(xcsi2rxss);
+
+	v4l2_info(sd, "***** Core Status *****\n");
+	data = xcsi2rxss_read(core, XCSI_CSR_OFFSET);
+	v4l2_info(sd, "Short Packet FIFO Full = %s\n",
+		XCSI_GET_BITSET_STR(data, XCSI_CSR_SPFIFOFULL_MASK));
+	v4l2_info(sd, "Short Packet FIFO Not Empty = %s\n",
+		XCSI_GET_BITSET_STR(data, XCSI_CSR_SPFIFONE_MASK));
+	v4l2_info(sd, "Stream line buffer full = %s\n",
+		XCSI_GET_BITSET_STR(data, XCSI_CSR_SLBF_MASK));
+	v4l2_info(sd, "Soft reset/Core disable in progress = %s\n",
+		XCSI_GET_BITSET_STR(data, XCSI_CSR_RIPCD_MASK));
+
+	/* Clk & Lane Info  */
+	v4l2_info(sd, "******** Clock Lane Info *********\n");
+	data = xcsi2rxss_read(core, XCSI_CLKINFR_OFFSET);
+	v4l2_info(sd, "Clock Lane in Stop State = %s\n",
+		XCSI_GET_BITSET_STR(data, XCSI_CLKINFR_STOP_MASK));
+
+	v4l2_info(sd, "******** Data Lane Info *********\n");
+	v4l2_info(sd, "Lane\tSoT Error\tSoT Sync Error\tStop State\n");
+	reg = XCSI_L0INFR_OFFSET;
+	for (i = 0; i < 4; i++) {
+		data = xcsi2rxss_read(core, reg);
+
+		v4l2_info(sd, "%d\t%s\t\t%s\t\t%s\n",
+			i,
+			XCSI_GET_BITSET_STR(data, XCSI_LXINFR_SOTERR_MASK),
+			XCSI_GET_BITSET_STR(data, XCSI_LXINFR_SOTSYNCERR_MASK),
+			XCSI_GET_BITSET_STR(data, XCSI_LXINFR_STOP_MASK));
+
+		reg += 4;
+	}
+
+	/* Virtual Channel Image Information */
+	v4l2_info(sd, "********** Virtual Channel Info ************\n");
+	v4l2_info(sd, "VC\tLine Count\tByte Count\tData Type\n");
+	if (core->en_vcx)
+		max_vc = XMIPICSISS_MAX_VCX;
+	else
+		max_vc = XMIPICSISS_MAX_VC;
+
+	reg = XCSI_VC0INF1R_OFFSET;
+	for (i = 0; i < max_vc; i++) {
+		u32 line_count, byte_count, data_type;
+		char *datatypestr;
+
+		/* Get line and byte count from VCXINFR1 Register */
+		data = xcsi2rxss_read(core, reg);
+		byte_count = (data & XCSI_VCXINF1R_BYTECOUNT_MASK) >>
+				XCSI_VCXINF1R_BYTECOUNT_SHIFT;
+		line_count = (data & XCSI_VCXINF1R_LINECOUNT_MASK) >>
+				XCSI_VCXINF1R_LINECOUNT_SHIFT;
+
+		/* Get data type from VCXINFR2 Register */
+		reg += 4;
+		data = xcsi2rxss_read(core, reg);
+		data_type = (data & XCSI_VCXINF2R_DATATYPE_MASK) >>
+				XCSI_VCXINF2R_DATATYPE_SHIFT;
+		datatypestr = (char *)xcsi2rxss_pxlfmtdttostr(data_type);
+
+		v4l2_info(sd, "%d\t%d\t\t%d\t\t%s\n",
+			i, line_count, byte_count, datatypestr);
+
+		/* Move to next pair of VC Info registers */
+		reg += 4;
+	}
+
+	mutex_unlock(&xcsi2rxss->lock);
+
+	return 0;
+}
+
+/*
+ * xcsi2rxss_subscribe_event - Subscribe to the custom short packet
+ * receive event.
+ * @sd: V4L2 Sub device
+ * @fh: V4L2 File Handle
+ * @sub: Subcribe event structure
+ *
+ * There are two types of events to be subscribed.
+ *
+ * First is to register for receiving a short packet.
+ * The short packets received are queued up in a FIFO.
+ * On reception of a short packet, an event will be generated
+ * with the short packet contents copied to its data area.
+ * Application subscribed to this event will poll for POLLPRI.
+ * On getting the event, the app dequeues the event to get the short packet
+ * data.
+ *
+ * Second is to register for Short packet FIFO overflow
+ * In case the rate of receiving short packets is high and
+ * the short packet FIFO overflows, this event will be triggered.
+ *
+ * Return: 0 on success, errors otherwise
+ */
+static int xcsi2rxss_subscribe_event(struct v4l2_subdev *sd,
+				struct v4l2_fh *fh,
+				struct v4l2_event_subscription *sub)
+{
+	int ret;
+	struct xcsi2rxss_state *xcsi2rxss = to_xcsi2rxssstate(sd);
+
+	mutex_lock(&xcsi2rxss->lock);
+
+	switch (sub->type) {
+	case V4L2_EVENT_XLNXCSIRX_SPKT:
+	case V4L2_EVENT_XLNXCSIRX_SPKT_OVF:
+	case V4L2_EVENT_XLNXCSIRX_SLBF:
+		ret = v4l2_event_subscribe(fh, sub, XCSI_MAX_SPKT, NULL);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	mutex_unlock(&xcsi2rxss->lock);
+
+	return ret;
+}
+
+/**
+ * xcsi2rxss_unsubscribe_event - Unsubscribe from all events registered
+ * @sd: V4L2 Sub device
+ * @fh: V4L2 file handle
+ * @sub: pointer to Event unsubscription structure
+ *
+ * Return: zero on success, else a negative error code.
+ */
+static int xcsi2rxss_unsubscribe_event(struct v4l2_subdev *sd,
+				struct v4l2_fh *fh,
+				struct v4l2_event_subscription *sub)
+{
+	int ret = 0;
+	struct xcsi2rxss_state *xcsi2rxss = to_xcsi2rxssstate(sd);
+
+	mutex_lock(&xcsi2rxss->lock);
+	ret = v4l2_event_unsubscribe(fh, sub);
+	mutex_unlock(&xcsi2rxss->lock);
+
+	return ret;
+}
+
+/**
+ * xcsi2rxss_s_ctrl - This is used to set the Xilinx MIPI CSI-2 V4L2 controls
+ * @ctrl: V4L2 control to be set
+ *
+ * This function is used to set the V4L2 controls for the Xilinx MIPI
+ * CSI-2 Rx Subsystem. It is used to set the active lanes in the system.
+ * The event counters can be reset.
+ *
+ * Return: 0 on success, errors otherwise
+ */
+static int xcsi2rxss_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	int ret = 0;
+	u32 Timeout = XCSI_TIMEOUT_VAL;
+	u32 active_lanes = 1;
+
+	struct xcsi2rxss_state *xcsi2rxss =
+		container_of(ctrl->handler,
+				struct xcsi2rxss_state, ctrl_handler);
+	struct xcsi2rxss_core *core = &xcsi2rxss->core;
+
+	mutex_lock(&xcsi2rxss->lock);
+
+	switch (ctrl->id) {
+	case V4L2_CID_XILINX_MIPICSISS_ACT_LANES:
+		/*
+		 * This will be called only when "Enable Active Lanes" parameter
+		 * is set in design
+		 */
+		xcsi2rxss_clr_and_set(core, XCSI_PCR_OFFSET,
+			XCSI_PCR_ACTLANES_MASK, ctrl->val - 1);
+
+		/*
+		 * If the core is enabled, wait for active lanes to be
+		 * set.
+		 *
+		 * If core is disabled or there is no clock from DPHY Tx
+		 * then the read back won't reflect the updated value
+		 * as the PPI clock will not be present.
+		 */
+
+		if (core->dphy_present) {
+			u32 dphyclkstatregoffset = core->dphy_offset +
+							XDPHY_CLKSTATREG_OFFSET;
+
+			u32 dphyclkstat =
+				xcsi2rxss_read(core, dphyclkstatregoffset) &
+					XDPHY_CLKSTATREG_MODE_MASK;
+
+			u32 coreenable =
+				xcsi2rxss_read(core, XCSI_CCR_OFFSET) &
+					XCSI_CCR_COREENB_MASK;
+
+			char lpmstr[] = "Low Power";
+			char hsmstr[] = "High Speed";
+			char esmstr[] = "Escape";
+			char *modestr;
+
+			switch (dphyclkstat) {
+			case 0:
+				modestr = lpmstr;
+				break;
+			case 1:
+				modestr = hsmstr;
+				break;
+			case 2:
+				modestr = esmstr;
+				break;
+			default:
+				modestr = NULL;
+				break;
+			}
+
+			dev_dbg(core->dev, "DPHY Clock Lane in %s mode\n",
+					modestr);
+
+			if ((dphyclkstat == XDPHY_HI_SPEED_MODE) &&
+					coreenable) {
+
+				/* Wait for core to apply new active lanes */
+				while (Timeout--)
+					udelay(1);
+
+				active_lanes =
+					xcsi2rxss_read(core, XCSI_PCR_OFFSET);
+				active_lanes &=	XCSI_PCR_ACTLANES_MASK;
+				active_lanes++;
+
+				if (active_lanes != ctrl->val) {
+					dev_err(core->dev, "Failed to set active lanes!\n");
+					ret = -EAGAIN;
+				}
+			}
+		} else {
+			dev_dbg(core->dev, "No read back as no DPHY present.\n");
+		}
+
+		dev_dbg(core->dev, "Set active lanes: requested = %d, active = %d\n",
+				ctrl->val, active_lanes);
+		break;
+	case V4L2_CID_XILINX_MIPICSISS_RESET_COUNTERS:
+		xcsi2rxss_reset_event_counters(xcsi2rxss);
+		break;
+	default:
+		break;
+	}
+
+	mutex_unlock(&xcsi2rxss->lock);
+
+	return ret;
+}
+
+/**
+ * xcsi2rxss_g_volatile_ctrl - get the Xilinx MIPI CSI-2 Rx controls
+ * @ctrl: Pointer to V4L2 control
+ *
+ * This is used to get the number of frames received by the Xilinx
+ * MIPI CSI-2 Rx.
+ *
+ * Return: 0 on success, errors otherwise
+ */
+static int xcsi2rxss_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
+{
+	int ret = 0;
+	struct xcsi2rxss_state *xcsi2rxss =
+		container_of(ctrl->handler,
+				struct xcsi2rxss_state, ctrl_handler);
+
+	mutex_lock(&xcsi2rxss->lock);
+
+	switch (ctrl->id) {
+	case V4L2_CID_XILINX_MIPICSISS_FRAME_COUNTER:
+		ctrl->val = xcsi2rxss->core.events[0].counter;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	mutex_unlock(&xcsi2rxss->lock);
+
+	return ret;
+}
+
+static int xcsi2rxss_start_stream(struct xcsi2rxss_state *xcsi2rxss)
+{
+	int ret;
+
+	xcsi2rxss_enable(&xcsi2rxss->core, true);
+
+	ret = xcsi2rxss_reset(&xcsi2rxss->core);
+	if (ret < 0)
+		return ret;
+
+	xcsi2rxss_interrupts_enable(&xcsi2rxss->core, true);
+
+	return 0;
+}
+
+
+/**
+ * xcsi2rxss_s_stream - It is used to start/stop the streaming.
+ * @sd: V4L2 Sub device
+ * @enable: Flag (True / False)
+ *
+ * This function controls the start or stop of streaming for the
+ * Xilinx MIPI CSI-2 Rx Subsystem provided the device isn't in
+ * suspended state.
+ *
+ * Return: 0 on success, errors otherwise
+ */
+static int xcsi2rxss_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	int ret = 0;
+	struct xcsi2rxss_state *xcsi2rxss = to_xcsi2rxssstate(sd);
+
+	mutex_lock(&xcsi2rxss->lock);
+
+	if (xcsi2rxss->suspended) {
+		ret = -EBUSY;
+		goto unlock;
+	}
+
+	if (enable) {
+		if (!xcsi2rxss->streaming) {
+			/* reset the event counters */
+			xcsi2rxss_reset_event_counters(xcsi2rxss);
+
+			ret = xcsi2rxss_start_stream(xcsi2rxss);
+			if (ret == 0)
+				xcsi2rxss->streaming = true;
+		}
+	} else {
+		if (xcsi2rxss->streaming) {
+			struct gpio_desc *rst = xcsi2rxss->core.rst_gpio;
+
+			if (rst) {
+				gpiod_set_value_cansleep(rst, 1);
+				usleep_range(1, 2);
+				gpiod_set_value_cansleep(rst, 0);
+			}
+
+			xcsi2rxss_stop_stream(xcsi2rxss);
+			xcsi2rxss->streaming = false;
+		}
+	}
+unlock:
+	mutex_unlock(&xcsi2rxss->lock);
+	return ret;
+}
+
+static struct v4l2_mbus_framefmt *
+__xcsi2rxss_get_pad_format(struct xcsi2rxss_state *xcsi2rxss,
+				struct v4l2_subdev_pad_config *cfg,
+				unsigned int pad, u32 which)
+{
+	struct v4l2_mbus_framefmt *get_fmt;
+
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		get_fmt = v4l2_subdev_get_try_format(&xcsi2rxss->subdev, cfg,
+						     pad);
+		break;
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		get_fmt = &xcsi2rxss->formats;
+		break;
+	default:
+		get_fmt = NULL;
+		break;
+	}
+
+	return get_fmt;
+}
+
+/**
+ * xcsi2rxss_get_format - Get the pad format
+ * @sd: Pointer to V4L2 Sub device structure
+ * @cfg: Pointer to sub device pad information structure
+ * @fmt: Pointer to pad level media bus format
+ *
+ * This function is used to get the pad format information.
+ *
+ * Return: 0 on success
+ */
+static int xcsi2rxss_get_format(struct v4l2_subdev *sd,
+					struct v4l2_subdev_pad_config *cfg,
+					struct v4l2_subdev_format *fmt)
+{
+
+	struct xcsi2rxss_state *xcsi2rxss = to_xcsi2rxssstate(sd);
+	struct v4l2_mbus_framefmt *get_fmt;
+	int ret = 0;
+
+	mutex_lock(&xcsi2rxss->lock);
+
+	get_fmt = __xcsi2rxss_get_pad_format(xcsi2rxss, cfg,
+					     fmt->pad, fmt->which);
+	if (!get_fmt) {
+		ret = -EINVAL;
+		goto unlock_get_format;
+	}
+
+	fmt->format = *get_fmt;
+
+unlock_get_format:
+	mutex_unlock(&xcsi2rxss->lock);
+
+	return ret;
+}
+
+/**
+ * xcsi2rxss_set_format - This is used to set the pad format
+ * @sd: Pointer to V4L2 Sub device structure
+ * @cfg: Pointer to sub device pad information structure
+ * @fmt: Pointer to pad level media bus format
+ *
+ * This function is used to set the pad format.
+ * Since the pad format is fixed in hardware, it can't be
+ * modified on run time. So when a format set is requested by
+ * application, all parameters except the format type is
+ * saved for the pad and the original pad format is sent
+ * back to the application.
+ *
+ * Return: 0 on success
+ */
+static int xcsi2rxss_set_format(struct v4l2_subdev *sd,
+				struct v4l2_subdev_pad_config *cfg,
+				struct v4l2_subdev_format *fmt)
+{
+	struct v4l2_mbus_framefmt *__format;
+	struct xcsi2rxss_state *xcsi2rxss = to_xcsi2rxssstate(sd);
+	struct xcsi2rxss_core *core = &xcsi2rxss->core;
+	u32 code;
+	int ret = 0;
+
+	mutex_lock(&xcsi2rxss->lock);
+
+	/*
+	 * Only the format->code parameter matters for CSI as the
+	 * CSI format cannot be changed at runtime.
+	 * Ensure that format to set is copied to over to CSI pad format
+	 */
+	__format = __xcsi2rxss_get_pad_format(xcsi2rxss, cfg,
+					      fmt->pad, fmt->which);
+	if (!__format) {
+		ret = -EINVAL;
+		goto unlock_set_fmt;
+	}
+
+	/*
+	 * If trying to set format on source pad, then
+	 * return the format set on sink pad
+	 */
+	if (fmt->pad == 0) {
+		fmt->format = *__format;
+		goto unlock_set_fmt;
+	}
+
+	/* Save the pad format code */
+	code = __format->code;
+
+	/* If the bayer pattern to be set is SXXXX8 then only 1x8 type
+	 * is supported and core's data type doesn't matter.
+	 * In case the bayer pattern being set is SXXX10 then only
+	 * 1x10 type are supported and core should be configured for RAW10.
+	 * In case the bayer pattern being set is SXXX12 then only
+	 * 1x12 type are supported and core should be configured for RAW12.
+	 *
+	 * Otherwise don't allow change.
+	 */
+	if (((fmt->format.code == MEDIA_BUS_FMT_SBGGR8_1X8) ||
+		(fmt->format.code == MEDIA_BUS_FMT_SGBRG8_1X8) ||
+		(fmt->format.code == MEDIA_BUS_FMT_SGRBG8_1X8) ||
+		(fmt->format.code == MEDIA_BUS_FMT_SRGGB8_1X8))
+	|| ((core->datatype == MIPI_CSI_DT_RAW_10) &&
+		((fmt->format.code == MEDIA_BUS_FMT_SBGGR10_1X10) ||
+		 (fmt->format.code == MEDIA_BUS_FMT_SGBRG10_1X10) ||
+		 (fmt->format.code == MEDIA_BUS_FMT_SGRBG10_1X10) ||
+		 (fmt->format.code == MEDIA_BUS_FMT_SRGGB10_1X10)))
+	|| ((core->datatype == MIPI_CSI_DT_RAW_12) &&
+		((fmt->format.code == MEDIA_BUS_FMT_SBGGR12_1X12) ||
+		 (fmt->format.code == MEDIA_BUS_FMT_SGBRG12_1X12) ||
+		 (fmt->format.code == MEDIA_BUS_FMT_SGRBG12_1X12) ||
+		 (fmt->format.code == MEDIA_BUS_FMT_SRGGB12_1X12))) ||
+	((core->datatype == MIPI_CSI_DT_RAW_16) &&
+		((fmt->format.code == MEDIA_BUS_FMT_SBGGR16_1X16) ||
+		 (fmt->format.code == MEDIA_BUS_FMT_SGBRG16_1X16) ||
+		 (fmt->format.code == MEDIA_BUS_FMT_SGRBG16_1X16) ||
+		 (fmt->format.code == MEDIA_BUS_FMT_SRGGB16_1X16))))
+
+		/* Copy over the format to be set */
+		*__format = fmt->format;
+	else {
+		/* Restore the original pad format code */
+		fmt->format.code = code;
+		__format->code = code;
+		__format->width = fmt->format.width;
+		__format->height = fmt->format.height;
+	}
+
+unlock_set_fmt:
+	mutex_unlock(&xcsi2rxss->lock);
+
+	return ret;
+}
+
+/**
+ * xcsi2rxss_open - Called on v4l2_open()
+ * @sd: Pointer to V4L2 sub device structure
+ * @fh: Pointer to V4L2 File handle
+ *
+ * This function is called on v4l2_open(). It sets the default format
+ * for both pads.
+ *
+ * Return: 0 on success
+ */
+static int xcsi2rxss_open(struct v4l2_subdev *sd,
+				struct v4l2_subdev_fh *fh)
+{
+	struct v4l2_mbus_framefmt *format;
+	struct xcsi2rxss_state *xcsi2rxss = to_xcsi2rxssstate(sd);
+
+	format = v4l2_subdev_get_try_format(sd, fh->pad, 0);
+	*format = xcsi2rxss->default_format;
+
+	format = v4l2_subdev_get_try_format(sd, fh->pad, 1);
+	*format = xcsi2rxss->default_format;
+
+	return 0;
+}
+
+static int xcsi2rxss_close(struct v4l2_subdev *sd,
+				struct v4l2_subdev_fh *fh)
+{
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Media Operations
+ */
+
+static const struct media_entity_operations xcsi2rxss_media_ops = {
+	.link_validate = v4l2_subdev_link_validate
+};
+
+static const struct v4l2_ctrl_ops xcsi2rxss_ctrl_ops = {
+	.g_volatile_ctrl = xcsi2rxss_g_volatile_ctrl,
+	.s_ctrl	= xcsi2rxss_s_ctrl
+};
+
+static struct v4l2_ctrl_config xcsi2rxss_ctrls[] = {
+	{
+		.ops	= &xcsi2rxss_ctrl_ops,
+		.id	= V4L2_CID_XILINX_MIPICSISS_ACT_LANES,
+		.name	= "MIPI CSI2 Rx Subsystem: Active Lanes",
+		.type	= V4L2_CTRL_TYPE_INTEGER,
+		.min	= 1,
+		.max	= 4,
+		.step	= 1,
+		.def	= 1,
+	}, {
+		.ops	= &xcsi2rxss_ctrl_ops,
+		.id	= V4L2_CID_XILINX_MIPICSISS_FRAME_COUNTER,
+		.name	= "MIPI CSI2 Rx Subsystem: Frames Received Counter",
+		.type	= V4L2_CTRL_TYPE_INTEGER,
+		.min	= 0,
+		.max	= 0xFFFFFFFF,
+		.step	= 1,
+		.def	= 0,
+		.flags	= V4L2_CTRL_FLAG_VOLATILE | V4L2_CTRL_FLAG_READ_ONLY,
+	}, {
+		.ops	= &xcsi2rxss_ctrl_ops,
+		.id	= V4L2_CID_XILINX_MIPICSISS_RESET_COUNTERS,
+		.name	= "MIPI CSI2 Rx Subsystem: Reset Counters",
+		.type	= V4L2_CTRL_TYPE_BUTTON,
+		.min	= 0,
+		.max	= 1,
+		.step	= 1,
+		.def	= 0,
+		.flags	= V4L2_CTRL_FLAG_WRITE_ONLY,
+	}
+};
+
+static const struct v4l2_subdev_core_ops xcsi2rxss_core_ops = {
+	.log_status = xcsi2rxss_log_status,
+	.subscribe_event = xcsi2rxss_subscribe_event,
+	.unsubscribe_event = xcsi2rxss_unsubscribe_event
+};
+
+static struct v4l2_subdev_video_ops xcsi2rxss_video_ops = {
+	.s_stream = xcsi2rxss_s_stream
+};
+
+static struct v4l2_subdev_pad_ops xcsi2rxss_pad_ops = {
+	.get_fmt = xcsi2rxss_get_format,
+	.set_fmt = xcsi2rxss_set_format,
+};
+
+static struct v4l2_subdev_ops xcsi2rxss_ops = {
+	.core = &xcsi2rxss_core_ops,
+	.video = &xcsi2rxss_video_ops,
+	.pad = &xcsi2rxss_pad_ops
+};
+
+static const struct v4l2_subdev_internal_ops xcsi2rxss_internal_ops = {
+	.open = xcsi2rxss_open,
+	.close = xcsi2rxss_close
+};
+
+/* -----------------------------------------------------------------------------
+ * Power Management
+ */
+
+/*
+ * xcsi2rxss_pm_suspend - Function called on Power Suspend
+ * @dev: Pointer to device structure
+ *
+ * On power suspend the CSI-2 Core is disabled if the device isn't
+ * in suspended state and is streaming.
+ *
+ * Return: 0 on success
+ */
+static int __maybe_unused xcsi2rxss_pm_suspend(struct device *dev)
+{
+	struct xcsi2rxss_state *xcsi2rxss = dev_get_drvdata(dev);
+
+	mutex_lock(&xcsi2rxss->lock);
+
+	if (!xcsi2rxss->suspended && xcsi2rxss->streaming)
+		xcsi2rxss_clr(&xcsi2rxss->core,
+				XCSI_CCR_OFFSET, XCSI_CCR_COREENB_MASK);
+
+	xcsi2rxss->suspended = true;
+
+	mutex_unlock(&xcsi2rxss->lock);
+
+	return 0;
+}
+
+/*
+ * xcsi2rxss_pm_resume - Function called on Power Resume
+ * @dev: Pointer to device structure
+ *
+ * On power resume the CSI-2 Core is enabled when it is in suspended state
+ * and prior to entering suspended state it was streaming.
+ *
+ * Return: 0 on success
+ */
+static int __maybe_unused xcsi2rxss_pm_resume(struct device *dev)
+{
+	struct xcsi2rxss_state *xcsi2rxss = dev_get_drvdata(dev);
+
+	mutex_lock(&xcsi2rxss->lock);
+
+	if ((xcsi2rxss->suspended) && (xcsi2rxss->streaming))
+		xcsi2rxss_set(&xcsi2rxss->core,
+				XCSI_CCR_OFFSET, XCSI_CCR_COREENB_MASK);
+
+	xcsi2rxss->suspended = false;
+
+	mutex_unlock(&xcsi2rxss->lock);
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Platform Device Driver
+ */
+
+static int xcsi2rxss_parse_of(struct xcsi2rxss_state *xcsi2rxss)
+{
+	struct device_node *node = xcsi2rxss->core.dev->of_node;
+	struct device_node *ports = NULL;
+	struct device_node *port = NULL;
+	unsigned int nports = 0;
+	struct xcsi2rxss_core *core = &xcsi2rxss->core;
+	int ret;
+	bool iic_present;
+
+	if (core->cfg->flags & XCSI_CLK_PROP) {
+		core->lite_aclk = devm_clk_get(core->dev, "lite_aclk");
+		if (IS_ERR(core->lite_aclk)) {
+			ret = PTR_ERR(core->lite_aclk);
+			dev_err(core->dev, "failed to get lite_aclk (%d)\n",
+				ret);
+			return ret;
+		}
+
+		core->video_aclk = devm_clk_get(core->dev, "video_aclk");
+		if (IS_ERR(core->video_aclk)) {
+			ret = PTR_ERR(core->video_aclk);
+			dev_err(core->dev, "failed to get video_aclk (%d)\n",
+				ret);
+			return ret;
+		}
+
+		core->dphy_clk_200M = devm_clk_get(core->dev, "dphy_clk_200M");
+		if (IS_ERR(core->dphy_clk_200M)) {
+			ret = PTR_ERR(core->dphy_clk_200M);
+			dev_err(core->dev, "failed to get dphy_clk_200M (%d)\n",
+				ret);
+			return ret;
+		}
+	} else {
+		dev_info(core->dev, "assuming all required clocks are enabled!\n");
+	}
+
+	core->dphy_present = of_property_read_bool(node, "xlnx,dphy-present");
+	dev_dbg(core->dev, "DPHY present property = %s\n",
+			core->dphy_present ? "Present" : "Absent");
+
+	iic_present = of_property_read_bool(node, "xlnx,iic-present");
+	dev_dbg(core->dev, "IIC present property = %s\n",
+			iic_present ? "Present" : "Absent");
+
+	if (iic_present && (core->cfg->flags & XCSI_DPHY_PROP)) {
+		/*
+		 * In IP v4.1 the DPHY offset is 0x10000, if present,
+		 * and the iic is removed from subsystem.
+		 */
+		dev_err(core->dev, "Invalid case - IIC present!");
+		return -EINVAL;
+	}
+
+	if (core->dphy_present) {
+		if (iic_present) {
+			core->dphy_offset = 0x20000;
+		} else {
+			if (core->cfg->flags & XCSI_DPHY_ADDR_PROP)
+				core->dphy_offset = 0x1000;
+			else
+				core->dphy_offset = 0x10000;
+		}
+	}
+
+	ret = of_property_read_u32(node, "xlnx,max-lanes",
+					&core->max_num_lanes);
+	if (ret < 0) {
+		dev_err(core->dev, "missing xlnx,max-lanes property\n");
+		return ret;
+	}
+
+	if ((core->max_num_lanes > 4) || (core->max_num_lanes < 1)) {
+		dev_err(core->dev, "%d max lanes : invalid xlnx,max-lanes property\n",
+			core->max_num_lanes);
+		return -EINVAL;
+	}
+
+	core->en_vcx = of_property_read_bool(node, "xlnx,en-vcx");
+
+	ret = of_property_read_u32(node, "xlnx,vc", &core->vc);
+	if (ret < 0) {
+		dev_err(core->dev, "missing xlnx,vc property\n");
+		return ret;
+	}
+	if ((core->vc > XMIPICSISS_MAX_VC && !core->en_vcx) ||
+	    (core->vc > XMIPICSISS_MAX_VCX && core->en_vcx)) {
+		dev_err(core->dev, "invalid virtual channel property value.\n");
+		return -EINVAL;
+	}
+
+	core->enable_active_lanes =
+		of_property_read_bool(node, "xlnx,en-active-lanes");
+	dev_dbg(core->dev, "Enable active lanes property = %s\n",
+			core->enable_active_lanes ? "Present" : "Absent");
+
+	ret = of_property_read_string(node, "xlnx,csi-pxl-format",
+					&core->pxlformat);
+	if (ret < 0) {
+		dev_err(core->dev, "missing xlnx,csi-pxl-format property\n");
+		return ret;
+	}
+
+	core->datatype = xcsi2rxss_pxlfmtstrtodt(core->pxlformat);
+	if ((core->datatype < MIPI_CSI_DT_YUV_420_8B) ||
+		(core->datatype > MIPI_CSI_DT_RAW_20)) {
+		dev_err(core->dev, "Invalid xlnx,csi-pxl-format string\n");
+		return -EINVAL;
+	}
+
+	core->vfb = of_property_read_bool(node, "xlnx,vfb");
+	dev_dbg(core->dev, "Video Format Bridge property = %s\n",
+			core->vfb ? "Present" : "Absent");
+
+	if (core->vfb) {
+		ret = of_property_read_u32(node, "xlnx,ppc", &core->ppc);
+		if ((ret < 0) || !((core->ppc == 1) ||
+			(core->ppc == 2) || (core->ppc == 4))) {
+			dev_err(core->dev, "Invalid xlnx,ppc property ret = %d ppc = %d\n",
+					ret, core->ppc);
+			return -EINVAL;
+		}
+	}
+
+	ports = of_get_child_by_name(node, "ports");
+	if (ports == NULL)
+		ports = node;
+
+	for_each_child_of_node(ports, port) {
+		int ret;
+		const struct xvip_video_format *format;
+		struct device_node *endpoint;
+		struct v4l2_fwnode_endpoint v4lendpoint = { 0 };
+
+		if (!port->name || of_node_cmp(port->name, "port"))
+			continue;
+
+		/*
+		 * Currently only a subset of VFB enabled formats present in
+		 * xvip are supported in the  driver.
+		 *
+		 * If the VFB is disabled, the pixels per clock don't matter.
+		 * The data width is either 32 or 64 bit as selected in design.
+		 *
+		 * For e.g. If Data Type is RGB888, VFB is disabled and
+		 * data width is 32 bits.
+		 *
+		 * Clk Cycle  |  Byte 0  |  Byte 1  |  Byte 2  |  Byte 3
+		 * -----------+----------+----------+----------+----------
+		 *     1      |     B0   |     G0   |     R0   |     B1
+		 *     2      |     G1   |     R1   |     B2   |     G2
+		 *     3      |     R2   |     B3   |     G3   |     R3
+		 */
+		format = xvip_of_get_format(port);
+		if (IS_ERR(format)) {
+			dev_err(core->dev, "invalid format in DT");
+			return PTR_ERR(format);
+		}
+
+		if (core->vfb &&
+			(format->vf_code != XVIP_VF_YUV_422) &&
+			(format->vf_code != XVIP_VF_YUV_420) &&
+			(format->vf_code != XVIP_VF_RBG) &&
+			(format->vf_code != XVIP_VF_MONO_SENSOR)) {
+			dev_err(core->dev, "Invalid UG934 video format set.\n");
+			return -EINVAL;
+		}
+
+		/* Get and check the format description */
+		if (!xcsi2rxss->vip_format) {
+			xcsi2rxss->vip_format = format;
+		} else if (xcsi2rxss->vip_format != format) {
+			dev_err(core->dev, "in/out format mismatch in DT");
+			return -EINVAL;
+		}
+
+		endpoint = of_get_next_child(port, NULL);
+		if (!endpoint) {
+			dev_err(core->dev, "No port at\n");
+			return -EINVAL;
+		}
+
+		ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint),
+						 &v4lendpoint);
+		if (ret) {
+			of_node_put(endpoint);
+			return ret;
+		}
+
+		of_node_put(endpoint);
+		dev_dbg(core->dev, "%s : port %d bus type = %d\n",
+				__func__, nports, v4lendpoint.bus_type);
+
+		if (v4lendpoint.bus_type == V4L2_MBUS_CSI2_DPHY) {
+			dev_dbg(core->dev, "%s : base.port = %d base.id = %d\n",
+					__func__,
+					v4lendpoint.base.port,
+					v4lendpoint.base.id);
+
+			dev_dbg(core->dev, "%s : mipi number lanes = %d\n",
+				__func__,
+				v4lendpoint.bus.mipi_csi2.num_data_lanes);
+		} else {
+			dev_dbg(core->dev, "%s : Not a CSI2 bus\n", __func__);
+		}
+
+		/* Count the number of ports. */
+		nports++;
+	}
+
+	if (nports != 2) {
+		dev_err(core->dev, "invalid number of ports %u\n", nports);
+		return -EINVAL;
+	}
+	xcsi2rxss->npads = nports;
+
+	/*Register interrupt handler */
+	core->irq = irq_of_parse_and_map(node, 0);
+
+	ret = devm_request_irq(core->dev, core->irq, xcsi2rxss_irq_handler,
+				IRQF_SHARED, "xilinx-csi2rxss", xcsi2rxss);
+	if (ret) {
+		dev_err(core->dev, "Err = %d Interrupt handler reg failed!\n",
+				ret);
+		return ret;
+	}
+
+	/* Reset GPIO */
+	core->rst_gpio = devm_gpiod_get_optional(core->dev, "reset",
+						 GPIOD_OUT_HIGH);
+	if (IS_ERR(core->rst_gpio)) {
+		if (PTR_ERR(core->rst_gpio) != -EPROBE_DEFER)
+			dev_err(core->dev, "Reset GPIO not setup in DT");
+		return PTR_ERR(core->rst_gpio);
+	}
+
+	return 0;
+}
+
+static int xcsi2rxss_probe(struct platform_device *pdev)
+{
+	struct v4l2_subdev *subdev;
+	struct xcsi2rxss_state *xcsi2rxss;
+	struct resource *res;
+	const struct of_device_id *match;
+	struct device_node *node = pdev->dev.of_node;
+	u32 i;
+	int ret;
+	int num_ctrls;
+
+	xcsi2rxss = devm_kzalloc(&pdev->dev, sizeof(*xcsi2rxss), GFP_KERNEL);
+	if (!xcsi2rxss)
+		return -ENOMEM;
+
+	mutex_init(&xcsi2rxss->lock);
+
+	xcsi2rxss->core.dev = &pdev->dev;
+
+	match = of_match_node(xcsi2rxss_of_id_table, node);
+	if (!match)
+		return -ENODEV;
+
+	xcsi2rxss->core.cfg = match->data;
+
+	ret = xcsi2rxss_parse_of(xcsi2rxss);
+	if (ret < 0)
+		return ret;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	xcsi2rxss->core.iomem = devm_ioremap_resource(xcsi2rxss->core.dev, res);
+	if (IS_ERR(xcsi2rxss->core.iomem))
+		return PTR_ERR(xcsi2rxss->core.iomem);
+
+	if (xcsi2rxss->core.cfg->flags & XCSI_CLK_PROP) {
+		unsigned long rate;
+
+		ret = clk_prepare_enable(xcsi2rxss->core.lite_aclk);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to enable lite_aclk (%d)\n",
+				ret);
+			goto clk_err;
+		}
+
+		ret = clk_prepare_enable(xcsi2rxss->core.video_aclk);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to enable video_aclk (%d)\n",
+				ret);
+			goto video_aclk_err;
+		}
+
+		ret = clk_prepare_enable(xcsi2rxss->core.dphy_clk_200M);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to enable dphy clk (%d)\n",
+				ret);
+			goto dphy_clk_err;
+		}
+
+		ret = clk_set_rate(xcsi2rxss->core.dphy_clk_200M,
+				   XCSI_DPHY_CLK_REQ);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to set dphy clk rate (%d)\n",
+				ret);
+
+			goto all_clk_err;
+		}
+
+		rate = clk_get_rate(xcsi2rxss->core.dphy_clk_200M);
+		if (rate < XCSI_DPHY_CLK_MIN && rate > XCSI_DPHY_CLK_MAX) {
+			dev_err(&pdev->dev, "Err DPHY Clock = %lu\n",
+				rate);
+			ret = -EINVAL;
+			goto all_clk_err;
+		}
+	}
+
+	/*
+	 * Reset and initialize the core.
+	 */
+
+	if (xcsi2rxss->core.rst_gpio) {
+		gpiod_set_value_cansleep(xcsi2rxss->core.rst_gpio, 1);
+		/* minimum of 40 dphy_clk_200M cycles */
+		usleep_range(1, 2);
+		gpiod_set_value_cansleep(xcsi2rxss->core.rst_gpio, 0);
+	}
+
+	xcsi2rxss_reset(&xcsi2rxss->core);
+
+	xcsi2rxss->core.events =  (struct xcsi2rxss_event *)&xcsi2rxss_events;
+
+	if (xcsi2rxss->core.en_vcx) {
+		u32 alloc_size;
+
+		alloc_size = sizeof(struct xcsi2rxss_event) *
+			     XMIPICSISS_VCX_NUM_EVENTS;
+		xcsi2rxss->core.vcx_events = devm_kzalloc(&pdev->dev,
+							  alloc_size,
+							  GFP_KERNEL);
+		if (!xcsi2rxss->core.vcx_events) {
+			mutex_destroy(&xcsi2rxss->lock);
+			return -ENOMEM;
+		}
+
+		for (i = 0; i < XMIPICSISS_VCX_NUM_EVENTS; i++)
+			xcsi2rxss->core.vcx_events[i].mask = 1 << i;
+	}
+
+	/* Initialize V4L2 subdevice and media entity */
+	xcsi2rxss->pads[0].flags = MEDIA_PAD_FL_SOURCE;
+	xcsi2rxss->pads[1].flags = MEDIA_PAD_FL_SINK;
+
+	/* Initialize the default format */
+	memset(&xcsi2rxss->default_format, 0,
+		sizeof(xcsi2rxss->default_format));
+	xcsi2rxss->default_format.code = xcsi2rxss->vip_format->code;
+	xcsi2rxss->default_format.field = V4L2_FIELD_NONE;
+	xcsi2rxss->default_format.colorspace = V4L2_COLORSPACE_SRGB;
+	xcsi2rxss->default_format.width = XCSI_DEFAULT_WIDTH;
+	xcsi2rxss->default_format.height = XCSI_DEFAULT_HEIGHT;
+
+	xcsi2rxss->formats = xcsi2rxss->default_format;
+
+	/* Initialize V4L2 subdevice and media entity */
+	subdev = &xcsi2rxss->subdev;
+	v4l2_subdev_init(subdev, &xcsi2rxss_ops);
+
+	subdev->dev = &pdev->dev;
+	subdev->internal_ops = &xcsi2rxss_internal_ops;
+	strlcpy(subdev->name, dev_name(&pdev->dev), sizeof(subdev->name));
+
+	subdev->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	subdev->entity.ops = &xcsi2rxss_media_ops;
+
+	v4l2_set_subdevdata(subdev, xcsi2rxss);
+
+	ret = media_entity_pads_init(&subdev->entity, 2, xcsi2rxss->pads);
+	if (ret < 0)
+		goto error;
+
+	/*
+	 * In case the Enable Active Lanes config parameter is not set,
+	 * dynamic lane reconfiguration is not allowed.
+	 * So V4L2_CID_XILINX_MIPICSISS_ACT_LANES ctrl will not be registered.
+	 * Accordingly allocate the number of controls
+	 */
+	num_ctrls = ARRAY_SIZE(xcsi2rxss_ctrls);
+
+	if (!xcsi2rxss->core.enable_active_lanes)
+		num_ctrls--;
+
+	dev_dbg(xcsi2rxss->core.dev, "# of ctrls = %d\n", num_ctrls);
+
+	v4l2_ctrl_handler_init(&xcsi2rxss->ctrl_handler, num_ctrls);
+
+	for (i = 0; i < ARRAY_SIZE(xcsi2rxss_ctrls); i++) {
+		struct v4l2_ctrl *ctrl;
+
+		if (xcsi2rxss_ctrls[i].id ==
+			V4L2_CID_XILINX_MIPICSISS_ACT_LANES) {
+
+			if (xcsi2rxss->core.enable_active_lanes) {
+				xcsi2rxss_ctrls[i].max =
+					xcsi2rxss->core.max_num_lanes;
+				xcsi2rxss_ctrls[i].def =
+					xcsi2rxss->core.max_num_lanes;
+			} else {
+				/* Don't register control */
+				dev_dbg(xcsi2rxss->core.dev,
+						"Skip active lane control\n");
+				continue;
+			}
+		}
+
+		dev_dbg(xcsi2rxss->core.dev, "%d ctrl = 0x%x\n",
+				i, xcsi2rxss_ctrls[i].id);
+		ctrl = v4l2_ctrl_new_custom(&xcsi2rxss->ctrl_handler,
+						&xcsi2rxss_ctrls[i], NULL);
+		if (!ctrl) {
+			dev_err(xcsi2rxss->core.dev, "Failed for %s ctrl\n",
+				xcsi2rxss_ctrls[i].name);
+			goto error;
+		}
+	}
+
+	dev_dbg(xcsi2rxss->core.dev, "# v4l2 ctrls registered = %d\n", i - 1);
+
+	if (xcsi2rxss->ctrl_handler.error) {
+		dev_err(&pdev->dev, "failed to add controls\n");
+		ret = xcsi2rxss->ctrl_handler.error;
+		goto error;
+	}
+
+	subdev->ctrl_handler = &xcsi2rxss->ctrl_handler;
+
+	ret = v4l2_ctrl_handler_setup(&xcsi2rxss->ctrl_handler);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to set controls\n");
+		goto error;
+	}
+
+	platform_set_drvdata(pdev, xcsi2rxss);
+
+	dev_info(xcsi2rxss->core.dev, "Xilinx CSI2 Rx Subsystem device found!\n");
+
+	ret = v4l2_async_register_subdev(subdev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to register subdev\n");
+		goto error;
+	}
+
+	/* default states for streaming and suspend */
+	xcsi2rxss->streaming = false;
+	xcsi2rxss->suspended = false;
+	return 0;
+
+error:
+	v4l2_ctrl_handler_free(&xcsi2rxss->ctrl_handler);
+	media_entity_cleanup(&subdev->entity);
+	mutex_destroy(&xcsi2rxss->lock);
+
+all_clk_err:
+	clk_disable_unprepare(xcsi2rxss->core.dphy_clk_200M);
+dphy_clk_err:
+	clk_disable_unprepare(xcsi2rxss->core.video_aclk);
+video_aclk_err:
+	clk_disable_unprepare(xcsi2rxss->core.lite_aclk);
+clk_err:
+	return ret;
+}
+
+static int xcsi2rxss_remove(struct platform_device *pdev)
+{
+	struct xcsi2rxss_state *xcsi2rxss = platform_get_drvdata(pdev);
+	struct v4l2_subdev *subdev = &xcsi2rxss->subdev;
+
+	v4l2_async_unregister_subdev(subdev);
+	v4l2_ctrl_handler_free(&xcsi2rxss->ctrl_handler);
+	media_entity_cleanup(&subdev->entity);
+	mutex_destroy(&xcsi2rxss->lock);
+	clk_disable_unprepare(xcsi2rxss->core.dphy_clk_200M);
+	clk_disable_unprepare(xcsi2rxss->core.video_aclk);
+	clk_disable_unprepare(xcsi2rxss->core.lite_aclk);
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(xcsi2rxss_pm_ops,
+			 xcsi2rxss_pm_suspend, xcsi2rxss_pm_resume);
+
+static struct platform_driver xcsi2rxss_driver = {
+	.driver = {
+		.name		= "xilinx-csi2rxss",
+		.pm		= &xcsi2rxss_pm_ops,
+		.of_match_table	= xcsi2rxss_of_id_table,
+	},
+	.probe			= xcsi2rxss_probe,
+	.remove			= xcsi2rxss_remove,
+};
+
+module_platform_driver(xcsi2rxss_driver);
+
+MODULE_AUTHOR("Vishal Sagar <vsagar@xilinx.com>");
+MODULE_DESCRIPTION("Xilinx MIPI CSI2 Rx Subsystem Driver");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/xilinx-demosaic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/xilinx-demosaic.c
@@ -0,0 +1,436 @@
+/*
+ * Xilinx Video Demosaic IP
+ *
+ * Copyright (C) 2017 Xilinx, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include <media/v4l2-async.h>
+#include <media/v4l2-subdev.h>
+
+#include "xilinx-vip.h"
+
+#define XDEMOSAIC_AP_CTRL			(0x00)
+#define XDEMOSAIC_WIDTH				(0x10)
+#define XDEMOSAIC_HEIGHT			(0x18)
+#define XDEMOSAIC_INPUT_BAYER_FORMAT		(0x28)
+
+#define XDEMOSAIC_MIN_HEIGHT	(64)
+#define XDEMOSAIC_MAX_HEIGHT	(4320)
+#define XDEMOSAIC_DEF_HEIGHT	(720)
+#define XDEMOSAIC_MIN_WIDTH	(64)
+#define XDEMOSAIC_MAX_WIDTH	(8192)
+#define XDEMOSAIC_DEF_WIDTH	(1280)
+
+#define XDEMOSAIC_RESET_DEASSERT	(0)
+#define XDEMOSAIC_RESET_ASSERT		(1)
+#define XDEMOSAIC_START			BIT(0)
+#define XDEMOSAIC_AUTO_RESTART		BIT(7)
+#define XDEMOSAIC_STREAM_ON	(XDEMOSAIC_AUTO_RESTART | XDEMOSAIC_START)
+
+enum xdmsc_bayer_format {
+	XDEMOSAIC_RGGB = 0,
+	XDEMOSAIC_GRBG,
+	XDEMOSAIC_GBRG,
+	XDEMOSAIC_BGGR,
+};
+
+struct xdmsc_dev {
+	struct xvip_device xvip;
+	struct media_pad pads[2];
+	struct v4l2_mbus_framefmt formats[2];
+	struct v4l2_mbus_framefmt default_formats[2];
+
+	enum xdmsc_bayer_format bayer_fmt;
+	struct gpio_desc *rst_gpio;
+	u32 max_width;
+	u32 max_height;
+};
+
+static inline u32 xdmsc_read(struct xdmsc_dev *xdmsc, u32 reg)
+{
+	u32 data;
+
+	data = xvip_read(&xdmsc->xvip, reg);
+	dev_dbg(xdmsc->xvip.dev,
+		"Reading 0x%x from reg offset 0x%x", data, reg);
+	return data;
+}
+
+static inline void xdmsc_write(struct xdmsc_dev *xdmsc, u32 reg, u32 data)
+{
+	xvip_write(&xdmsc->xvip, reg, data);
+	dev_dbg(xdmsc->xvip.dev,
+		"Writing 0x%x to reg offset 0x%x", data, reg);
+#ifdef DEBUG
+	if (xdmsc_read(xdmsc, reg) != data)
+		dev_err(xdmsc->xvip.dev,
+			"Wrote 0x%x does not match read back", data);
+#endif
+}
+
+static inline struct xdmsc_dev *to_xdmsc(struct v4l2_subdev *subdev)
+{
+	return container_of(subdev, struct xdmsc_dev, xvip.subdev);
+}
+
+static struct v4l2_mbus_framefmt
+*__xdmsc_get_pad_format(struct xdmsc_dev *xdmsc,
+			struct v4l2_subdev_pad_config *cfg,
+			unsigned int pad, u32 which)
+{
+	struct v4l2_mbus_framefmt *get_fmt;
+
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		get_fmt = v4l2_subdev_get_try_format(&xdmsc->xvip.subdev,
+						     cfg, pad);
+		break;
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		get_fmt = &xdmsc->formats[pad];
+		break;
+	default:
+		get_fmt = NULL;
+		break;
+	}
+
+	return get_fmt;
+}
+
+static int xdmsc_s_stream(struct v4l2_subdev *subdev, int enable)
+{
+	struct xdmsc_dev *xdmsc = to_xdmsc(subdev);
+
+	if (!enable) {
+		dev_dbg(xdmsc->xvip.dev, "%s : Off", __func__);
+		gpiod_set_value_cansleep(xdmsc->rst_gpio,
+					 XDEMOSAIC_RESET_ASSERT);
+		gpiod_set_value_cansleep(xdmsc->rst_gpio,
+					 XDEMOSAIC_RESET_DEASSERT);
+		return 0;
+	}
+
+	xdmsc_write(xdmsc, XDEMOSAIC_WIDTH,
+		    xdmsc->formats[XVIP_PAD_SINK].width);
+	xdmsc_write(xdmsc, XDEMOSAIC_HEIGHT,
+		    xdmsc->formats[XVIP_PAD_SINK].height);
+	xdmsc_write(xdmsc, XDEMOSAIC_INPUT_BAYER_FORMAT, xdmsc->bayer_fmt);
+
+	/* Start Demosaic Video IP */
+	xdmsc_write(xdmsc, XDEMOSAIC_AP_CTRL, XDEMOSAIC_STREAM_ON);
+	return 0;
+}
+
+static const struct v4l2_subdev_video_ops xdmsc_video_ops = {
+	.s_stream = xdmsc_s_stream,
+};
+
+static int xdmsc_get_format(struct v4l2_subdev *subdev,
+			    struct v4l2_subdev_pad_config *cfg,
+			    struct v4l2_subdev_format *fmt)
+{
+	struct xdmsc_dev *xdmsc = to_xdmsc(subdev);
+	struct v4l2_mbus_framefmt *get_fmt;
+
+	get_fmt = __xdmsc_get_pad_format(xdmsc, cfg, fmt->pad, fmt->which);
+	if (!get_fmt)
+		return -EINVAL;
+
+	fmt->format = *get_fmt;
+
+	return 0;
+}
+
+static bool
+xdmsc_is_format_bayer(struct xdmsc_dev *xdmsc, u32 code)
+{
+	switch (code) {
+	case MEDIA_BUS_FMT_SRGGB8_1X8:
+	case MEDIA_BUS_FMT_SRGGB10_1X10:
+	case MEDIA_BUS_FMT_SRGGB12_1X12:
+	case MEDIA_BUS_FMT_SRGGB16_1X16:
+		xdmsc->bayer_fmt = XDEMOSAIC_RGGB;
+		break;
+	case MEDIA_BUS_FMT_SGRBG8_1X8:
+	case MEDIA_BUS_FMT_SGRBG10_1X10:
+	case MEDIA_BUS_FMT_SGRBG12_1X12:
+	case MEDIA_BUS_FMT_SGRBG16_1X16:
+		xdmsc->bayer_fmt = XDEMOSAIC_GRBG;
+		break;
+	case MEDIA_BUS_FMT_SGBRG8_1X8:
+	case MEDIA_BUS_FMT_SGBRG10_1X10:
+	case MEDIA_BUS_FMT_SGBRG12_1X12:
+	case MEDIA_BUS_FMT_SGBRG16_1X16:
+		xdmsc->bayer_fmt = XDEMOSAIC_GBRG;
+		break;
+	case MEDIA_BUS_FMT_SBGGR8_1X8:
+	case MEDIA_BUS_FMT_SBGGR10_1X10:
+	case MEDIA_BUS_FMT_SBGGR12_1X12:
+	case MEDIA_BUS_FMT_SBGGR16_1X16:
+		xdmsc->bayer_fmt = XDEMOSAIC_BGGR;
+		break;
+	default:
+		dev_dbg(xdmsc->xvip.dev, "Unsupported format for Sink Pad");
+		return false;
+	}
+	return true;
+}
+
+static int xdmsc_set_format(struct v4l2_subdev *subdev,
+			    struct v4l2_subdev_pad_config *cfg,
+			    struct v4l2_subdev_format *fmt)
+{
+	struct xdmsc_dev *xdmsc = to_xdmsc(subdev);
+	struct v4l2_mbus_framefmt *__format;
+
+	__format = __xdmsc_get_pad_format(xdmsc, cfg, fmt->pad, fmt->which);
+	if (!__format)
+		return -EINVAL;
+
+	*__format = fmt->format;
+
+	__format->width = clamp_t(unsigned int, fmt->format.width,
+				  XDEMOSAIC_MIN_WIDTH, xdmsc->max_width);
+	__format->height = clamp_t(unsigned int, fmt->format.height,
+				   XDEMOSAIC_MIN_HEIGHT, xdmsc->max_height);
+
+	if (fmt->pad == XVIP_PAD_SOURCE) {
+		if (__format->code != MEDIA_BUS_FMT_RBG888_1X24 &&
+		    __format->code != MEDIA_BUS_FMT_RBG101010_1X30 &&
+		    __format->code != MEDIA_BUS_FMT_RBG121212_1X36 &&
+		    __format->code != MEDIA_BUS_FMT_RBG161616_1X48) {
+			dev_dbg(xdmsc->xvip.dev,
+				"%s : Unsupported source media bus code format",
+				__func__);
+			__format->code = MEDIA_BUS_FMT_RBG888_1X24;
+		}
+	}
+
+	if (fmt->pad == XVIP_PAD_SINK) {
+		if (!xdmsc_is_format_bayer(xdmsc, __format->code)) {
+			dev_dbg(xdmsc->xvip.dev,
+				"Unsupported Sink Pad Media format, defaulting to RGGB");
+			__format->code = MEDIA_BUS_FMT_SRGGB8_1X8;
+		}
+	}
+
+	fmt->format = *__format;
+	return 0;
+}
+
+static int xdmsc_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+	struct xdmsc_dev *xdmsc = to_xdmsc(subdev);
+	struct v4l2_mbus_framefmt *format;
+
+	format = v4l2_subdev_get_try_format(subdev, fh->pad, XVIP_PAD_SINK);
+	*format = xdmsc->default_formats[XVIP_PAD_SINK];
+
+	format = v4l2_subdev_get_try_format(subdev, fh->pad, XVIP_PAD_SOURCE);
+	*format = xdmsc->default_formats[XVIP_PAD_SOURCE];
+	return 0;
+}
+
+static int xdmsc_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+	return 0;
+}
+
+static const struct v4l2_subdev_internal_ops xdmsc_internal_ops = {
+	.open = xdmsc_open,
+	.close = xdmsc_close,
+};
+
+static const struct v4l2_subdev_pad_ops xdmsc_pad_ops = {
+	.enum_mbus_code = xvip_enum_mbus_code,
+	.enum_frame_size = xvip_enum_frame_size,
+	.get_fmt = xdmsc_get_format,
+	.set_fmt = xdmsc_set_format,
+};
+
+static const struct v4l2_subdev_ops xdmsc_ops = {
+	.video = &xdmsc_video_ops,
+	.pad = &xdmsc_pad_ops,
+};
+
+static const struct media_entity_operations xdmsc_media_ops = {
+	.link_validate = v4l2_subdev_link_validate,
+};
+
+static int xdmsc_parse_of(struct xdmsc_dev *xdmsc)
+{
+	struct device *dev = xdmsc->xvip.dev;
+	struct device_node *node = dev->of_node;
+	struct device_node *ports;
+	struct device_node *port;
+	u32 port_id = 0;
+	int rval;
+
+	rval = of_property_read_u32(node, "xlnx,max-height",
+				    &xdmsc->max_height);
+	if (rval < 0) {
+		dev_err(dev, "missing xlnx,max-height property!");
+		return -EINVAL;
+	} else if (xdmsc->max_height > XDEMOSAIC_MAX_HEIGHT ||
+		 xdmsc->max_height < XDEMOSAIC_MIN_HEIGHT) {
+		dev_err(dev, "Invalid height in dt");
+		return -EINVAL;
+	}
+
+	rval = of_property_read_u32(node, "xlnx,max-width",
+				    &xdmsc->max_width);
+	if (rval < 0) {
+		dev_err(dev, "missing xlnx,max-width property!");
+		return -EINVAL;
+	} else if (xdmsc->max_width > XDEMOSAIC_MAX_WIDTH ||
+		 xdmsc->max_width < XDEMOSAIC_MIN_WIDTH) {
+		dev_err(dev, "Invalid width in dt");
+		return -EINVAL;
+	}
+
+	ports = of_get_child_by_name(node, "ports");
+	if (!ports)
+		ports = node;
+	/* Get the format description for each pad */
+	for_each_child_of_node(ports, port) {
+		if (port->name && (of_node_cmp(port->name, "port") == 0)) {
+			rval = of_property_read_u32(port, "reg", &port_id);
+			if (rval < 0) {
+				dev_err(dev, "No reg in DT");
+				return rval;
+			}
+
+			if (port_id != 0 && port_id != 1) {
+				dev_err(dev, "Invalid reg in DT");
+				return -EINVAL;
+			}
+		}
+	}
+
+	xdmsc->rst_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(xdmsc->rst_gpio)) {
+		if (PTR_ERR(xdmsc->rst_gpio) != -EPROBE_DEFER)
+			dev_err(dev, "Reset GPIO not setup in DT");
+		return PTR_ERR(xdmsc->rst_gpio);
+	}
+	return 0;
+}
+
+static int xdmsc_probe(struct platform_device *pdev)
+{
+	struct xdmsc_dev *xdmsc;
+	struct v4l2_subdev *subdev;
+	struct v4l2_mbus_framefmt *def_fmt;
+	int rval;
+
+	xdmsc = devm_kzalloc(&pdev->dev, sizeof(*xdmsc), GFP_KERNEL);
+	if (!xdmsc)
+		return -ENOMEM;
+	xdmsc->xvip.dev = &pdev->dev;
+	rval = xdmsc_parse_of(xdmsc);
+	if (rval < 0)
+		return rval;
+	rval = xvip_init_resources(&xdmsc->xvip);
+	if (rval)
+		return -EIO;
+
+	/* Reset Demosaic IP */
+	gpiod_set_value_cansleep(xdmsc->rst_gpio,
+				 XDEMOSAIC_RESET_DEASSERT);
+
+	/* Init V4L2 subdev */
+	subdev = &xdmsc->xvip.subdev;
+	v4l2_subdev_init(subdev, &xdmsc_ops);
+	subdev->dev = &pdev->dev;
+	subdev->internal_ops = &xdmsc_internal_ops;
+	strlcpy(subdev->name, dev_name(&pdev->dev), sizeof(subdev->name));
+	subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	/* Default Formats Initialization */
+	def_fmt = &xdmsc->default_formats[XVIP_PAD_SINK];
+	def_fmt->field = V4L2_FIELD_NONE;
+	def_fmt->colorspace = V4L2_COLORSPACE_SRGB;
+	def_fmt->width = XDEMOSAIC_DEF_WIDTH;
+	def_fmt->height = XDEMOSAIC_DEF_HEIGHT;
+
+	/*
+	 * Sink Pad can be any Bayer format.
+	 * Default Sink Pad format is RGGB.
+	 */
+	def_fmt->code = MEDIA_BUS_FMT_SRGGB8_1X8;
+	xdmsc->formats[XVIP_PAD_SINK] = *def_fmt;
+
+	def_fmt = &xdmsc->default_formats[XVIP_PAD_SOURCE];
+	*def_fmt = xdmsc->default_formats[XVIP_PAD_SINK];
+
+	/* Source Pad has a fixed media bus format of RGB */
+	def_fmt->code = MEDIA_BUS_FMT_RBG888_1X24;
+	xdmsc->formats[XVIP_PAD_SOURCE] = *def_fmt;
+
+	xdmsc->pads[XVIP_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+	xdmsc->pads[XVIP_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+
+	/* Init Media Entity */
+	subdev->entity.ops = &xdmsc_media_ops;
+	rval = media_entity_pads_init(&subdev->entity, 2, xdmsc->pads);
+	if (rval < 0)
+		goto media_error;
+
+	platform_set_drvdata(pdev, xdmsc);
+	rval = v4l2_async_register_subdev(subdev);
+	if (rval < 0) {
+		dev_err(&pdev->dev, "failed to register subdev");
+		goto v4l2_subdev_error;
+	}
+	dev_info(&pdev->dev,
+		 "Xilinx Video Demosaic Probe Successful");
+	return 0;
+
+v4l2_subdev_error:
+	media_entity_cleanup(&subdev->entity);
+media_error:
+	xvip_cleanup_resources(&xdmsc->xvip);
+	return rval;
+}
+
+static int xdmsc_remove(struct platform_device *pdev)
+{
+	struct xdmsc_dev *xdmsc = platform_get_drvdata(pdev);
+	struct v4l2_subdev *subdev = &xdmsc->xvip.subdev;
+
+	v4l2_async_unregister_subdev(subdev);
+	media_entity_cleanup(&subdev->entity);
+	xvip_cleanup_resources(&xdmsc->xvip);
+	return 0;
+}
+
+static const struct of_device_id xdmsc_of_id_table[] = {
+	{.compatible = "xlnx,v-demosaic"},
+	{ }
+};
+MODULE_DEVICE_TABLE(of, xdmsc_of_id_table);
+
+static struct platform_driver xdmsc_driver = {
+	.driver = {
+		.name = "xilinx-demosaic",
+		.of_match_table = xdmsc_of_id_table,
+	},
+	.probe = xdmsc_probe,
+	.remove = xdmsc_remove,
+
+};
+
+module_platform_driver(xdmsc_driver);
+MODULE_DESCRIPTION("Xilinx Demosaic IP Driver");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/xilinx-dma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/xilinx-dma.c
@@ -10,11 +10,13 @@
  */
 
 #include <linux/dma/xilinx_dma.h>
+#include <linux/dma/xilinx_frmbuf.h>
 #include <linux/lcm.h>
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/slab.h>
+#include <linux/xilinx-v4l2-controls.h>
 
 #include <media/v4l2-dev.h>
 #include <media/v4l2-fh.h>
@@ -62,7 +64,7 @@
 	int ret;
 
 	subdev = xvip_dma_remote_subdev(&dma->pad, &fmt.pad);
-	if (subdev == NULL)
+	if (!subdev)
 		return -EPIPE;
 
 	fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
@@ -70,10 +72,15 @@
 	if (ret < 0)
 		return ret == -ENOIOCTLCMD ? -EINVAL : ret;
 
-	if (dma->fmtinfo->code != fmt.format.code ||
-	    dma->format.height != fmt.format.height ||
-	    dma->format.width != fmt.format.width ||
-	    dma->format.colorspace != fmt.format.colorspace)
+	if (dma->fmtinfo->code != fmt.format.code)
+		return -EINVAL;
+
+	/*
+	 * Crop rectangle contains format resolution by default, and crop
+	 * rectangle if s_selection is executed.
+	 */
+	if (dma->r.width != fmt.format.width ||
+	    dma->r.height != fmt.format.height)
 		return -EINVAL;
 
 	return 0;
@@ -83,45 +90,6 @@
  * Pipeline Stream Management
  */
 
-/**
- * xvip_pipeline_start_stop - Start ot stop streaming on a pipeline
- * @pipe: The pipeline
- * @start: Start (when true) or stop (when false) the pipeline
- *
- * Walk the entities chain starting at the pipeline output video node and start
- * or stop all of them.
- *
- * Return: 0 if successful, or the return value of the failed video::s_stream
- * operation otherwise.
- */
-static int xvip_pipeline_start_stop(struct xvip_pipeline *pipe, bool start)
-{
-	struct xvip_dma *dma = pipe->output;
-	struct media_entity *entity;
-	struct media_pad *pad;
-	struct v4l2_subdev *subdev;
-	int ret;
-
-	entity = &dma->video.entity;
-	while (1) {
-		pad = &entity->pads[0];
-		if (!(pad->flags & MEDIA_PAD_FL_SINK))
-			break;
-
-		pad = media_entity_remote_pad(pad);
-		if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
-			break;
-
-		entity = pad->entity;
-		subdev = media_entity_to_v4l2_subdev(entity);
-
-		ret = v4l2_subdev_call(subdev, video, s_stream, start);
-		if (start && ret < 0 && ret != -ENOIOCTLCMD)
-			return ret;
-	}
-
-	return 0;
-}
 
 /**
  * xvip_pipeline_set_stream - Enable/disable streaming on a pipeline
@@ -133,7 +101,8 @@
  * independently, pipelines have a shared stream state that enable or disable
  * all entities in the pipeline. For this reason the pipeline uses a streaming
  * counter that tracks the number of DMA engines that have requested the stream
- * to be enabled.
+ * to be enabled. This will walk the graph starting from each DMA and enable or
+ * disable the entities in the path.
  *
  * When called with the @on argument set to true, this function will increment
  * the pipeline streaming count. If the streaming count reaches the number of
@@ -150,20 +119,22 @@
  */
 static int xvip_pipeline_set_stream(struct xvip_pipeline *pipe, bool on)
 {
+	struct xvip_composite_device *xdev;
 	int ret = 0;
 
 	mutex_lock(&pipe->lock);
+	xdev = pipe->xdev;
 
 	if (on) {
 		if (pipe->stream_count == pipe->num_dmas - 1) {
-			ret = xvip_pipeline_start_stop(pipe, true);
+			ret = xvip_graph_pipeline_start_stop(xdev, pipe, true);
 			if (ret < 0)
 				goto done;
 		}
 		pipe->stream_count++;
 	} else {
 		if (--pipe->stream_count == 0)
-			xvip_pipeline_start_stop(pipe, false);
+			xvip_graph_pipeline_start_stop(xdev, pipe, false);
 	}
 
 done:
@@ -200,23 +171,22 @@
 
 		dma = to_xvip_dma(media_entity_to_video_device(entity));
 
-		if (dma->pad.flags & MEDIA_PAD_FL_SINK) {
-			pipe->output = dma;
+		if (dma->pad.flags & MEDIA_PAD_FL_SINK)
 			num_outputs++;
-		} else {
+		else
 			num_inputs++;
-		}
 	}
 
 	mutex_unlock(&mdev->graph_mutex);
 
 	media_graph_walk_cleanup(&graph);
 
-	/* We need exactly one output and zero or one input. */
-	if (num_outputs != 1 || num_inputs > 1)
+	/* We need at least one DMA to proceed */
+	if (num_outputs == 0 && num_inputs == 0)
 		return -EPIPE;
 
 	pipe->num_dmas = num_inputs + num_outputs;
+	pipe->xdev = start->xdev;
 
 	return 0;
 }
@@ -224,7 +194,6 @@
 static void __xvip_pipeline_cleanup(struct xvip_pipeline *pipe)
 {
 	pipe->num_dmas = 0;
-	pipe->output = NULL;
 }
 
 /**
@@ -287,11 +256,13 @@
  * @buf: vb2 buffer base object
  * @queue: buffer list entry in the DMA engine queued buffers list
  * @dma: DMA channel that uses the buffer
+ * @desc: Descriptor associated with this structure
  */
 struct xvip_dma_buffer {
 	struct vb2_v4l2_buffer buf;
 	struct list_head queue;
 	struct xvip_dma *dma;
+	struct dma_async_tx_descriptor *desc;
 };
 
 #define to_xvip_dma_buffer(vb)	container_of(vb, struct xvip_dma_buffer, buf)
@@ -300,6 +271,9 @@
 {
 	struct xvip_dma_buffer *buf = param;
 	struct xvip_dma *dma = buf->dma;
+	int i, sizeimage;
+	u32 fid;
+	int status;
 
 	spin_lock(&dma->queued_lock);
 	list_del(&buf->queue);
@@ -308,7 +282,38 @@
 	buf->buf.field = V4L2_FIELD_NONE;
 	buf->buf.sequence = dma->sequence++;
 	buf->buf.vb2_buf.timestamp = ktime_get_ns();
-	vb2_set_plane_payload(&buf->buf.vb2_buf, 0, dma->format.sizeimage);
+
+	status = xilinx_xdma_get_fid(dma->dma, buf->desc, &fid);
+	if (!status) {
+		if (((V4L2_TYPE_IS_MULTIPLANAR(dma->format.type)) &&
+		     dma->format.fmt.pix_mp.field == V4L2_FIELD_ALTERNATE) ||
+		     dma->format.fmt.pix.field == V4L2_FIELD_ALTERNATE) {
+			/*
+			 * fid = 1 is odd field i.e. V4L2_FIELD_TOP.
+			 * fid = 0 is even field i.e. V4L2_FIELD_BOTTOM.
+			 */
+			buf->buf.field = fid ?
+					 V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM;
+
+			if (fid == dma->prev_fid)
+				buf->buf.sequence = dma->sequence++;
+
+			buf->buf.sequence >>= 1;
+			dma->prev_fid = fid;
+		}
+	}
+
+	if (V4L2_TYPE_IS_MULTIPLANAR(dma->format.type)) {
+		for (i = 0; i < dma->fmtinfo->buffers; i++) {
+			sizeimage =
+				dma->format.fmt.pix_mp.plane_fmt[i].sizeimage;
+			vb2_set_plane_payload(&buf->buf.vb2_buf, i, sizeimage);
+		}
+	} else {
+		sizeimage = dma->format.fmt.pix.sizeimage;
+		vb2_set_plane_payload(&buf->buf.vb2_buf, 0, sizeimage);
+	}
+
 	vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_DONE);
 }
 
@@ -318,13 +323,39 @@
 		     unsigned int sizes[], struct device *alloc_devs[])
 {
 	struct xvip_dma *dma = vb2_get_drv_priv(vq);
+	unsigned int i;
+	int sizeimage;
+
+	/* Multi planar case: Make sure the image size is large enough */
+	if (V4L2_TYPE_IS_MULTIPLANAR(dma->format.type)) {
+		if (*nplanes) {
+			if (*nplanes != dma->format.fmt.pix_mp.num_planes)
+				return -EINVAL;
+
+			for (i = 0; i < *nplanes; i++) {
+				sizeimage =
+				  dma->format.fmt.pix_mp.plane_fmt[i].sizeimage;
+				if (sizes[i] < sizeimage)
+					return -EINVAL;
+			}
+		} else {
+			*nplanes = dma->fmtinfo->buffers;
+			for (i = 0; i < dma->fmtinfo->buffers; i++) {
+				sizeimage =
+				  dma->format.fmt.pix_mp.plane_fmt[i].sizeimage;
+				sizes[i] = sizeimage;
+			}
+		}
+		return 0;
+	}
 
-	/* Make sure the image size is large enough. */
-	if (*nplanes)
-		return sizes[0] < dma->format.sizeimage ? -EINVAL : 0;
+	/* Single planar case: Make sure the image size is large enough */
+	sizeimage = dma->format.fmt.pix.sizeimage;
+	if (*nplanes == 1)
+		return sizes[0] < sizeimage ? -EINVAL : 0;
 
 	*nplanes = 1;
-	sizes[0] = dma->format.sizeimage;
+	sizes[0] = sizeimage;
 
 	return 0;
 }
@@ -347,15 +378,21 @@
 	struct xvip_dma_buffer *buf = to_xvip_dma_buffer(vbuf);
 	struct dma_async_tx_descriptor *desc;
 	dma_addr_t addr = vb2_dma_contig_plane_dma_addr(vb, 0);
-	u32 flags;
+	u32 flags = 0;
+	u32 luma_size;
+	u32 padding_factor_nume, padding_factor_deno, bpl_nume, bpl_deno;
+	u32 fid = ~0;
+	u32 bpl;
 
-	if (dma->queue.type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+	if (dma->queue.type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+	    dma->queue.type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
 		flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK;
 		dma->xt.dir = DMA_DEV_TO_MEM;
 		dma->xt.src_sgl = false;
 		dma->xt.dst_sgl = true;
 		dma->xt.dst_start = addr;
-	} else {
+	} else if (dma->queue.type == V4L2_BUF_TYPE_VIDEO_OUTPUT ||
+		   dma->queue.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
 		flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK;
 		dma->xt.dir = DMA_MEM_TO_DEV;
 		dma->xt.src_sgl = true;
@@ -363,10 +400,77 @@
 		dma->xt.src_start = addr;
 	}
 
-	dma->xt.frame_size = 1;
-	dma->sgl[0].size = dma->format.width * dma->fmtinfo->bpp;
-	dma->sgl[0].icg = dma->format.bytesperline - dma->sgl[0].size;
-	dma->xt.numf = dma->format.height;
+	/*
+	 * DMA IP supports only 2 planes, so one datachunk is sufficient
+	 * to get start address of 2nd plane
+	 */
+	if (V4L2_TYPE_IS_MULTIPLANAR(dma->format.type)) {
+		struct v4l2_pix_format_mplane *pix_mp;
+		size_t size;
+
+		pix_mp = &dma->format.fmt.pix_mp;
+		bpl = pix_mp->plane_fmt[0].bytesperline;
+
+		xilinx_xdma_v4l2_config(dma->dma, pix_mp->pixelformat);
+		xvip_width_padding_factor(pix_mp->pixelformat,
+					  &padding_factor_nume,
+					  &padding_factor_deno);
+		xvip_bpl_scaling_factor(pix_mp->pixelformat, &bpl_nume,
+					&bpl_deno);
+		dma->xt.frame_size = dma->fmtinfo->num_planes;
+
+		size = ((size_t)dma->r.width * dma->fmtinfo->bpl_factor *
+			padding_factor_nume * bpl_nume) /
+			((size_t)padding_factor_deno * bpl_deno);
+		dma->sgl[0].size = size;
+
+		dma->sgl[0].icg = bpl - dma->sgl[0].size;
+		dma->xt.numf = dma->r.height;
+
+		/*
+		 * dst_icg is the number of bytes to jump after last luma addr
+		 * and before first chroma addr
+		 */
+
+		/* Handling contiguous data with mplanes */
+		if (dma->fmtinfo->buffers == 1) {
+			dma->sgl[0].dst_icg = (size_t)bpl *
+					      (pix_mp->height - dma->r.height);
+		} else {
+			/* Handling non-contiguous data with mplanes */
+			if (dma->fmtinfo->buffers == 2) {
+				dma_addr_t chroma_addr =
+					vb2_dma_contig_plane_dma_addr(vb, 1);
+				luma_size = bpl * dma->xt.numf;
+				if (chroma_addr > addr)
+					dma->sgl[0].dst_icg = chroma_addr -
+							      addr - luma_size;
+				}
+		}
+	} else {
+		struct v4l2_pix_format *pix;
+		size_t size;
+		size_t dst_icg;
+
+		pix = &dma->format.fmt.pix;
+		bpl = pix->bytesperline;
+		xilinx_xdma_v4l2_config(dma->dma, pix->pixelformat);
+		xvip_width_padding_factor(pix->pixelformat,
+					  &padding_factor_nume,
+					  &padding_factor_deno);
+		xvip_bpl_scaling_factor(pix->pixelformat, &bpl_nume,
+					&bpl_deno);
+		dma->xt.frame_size = dma->fmtinfo->num_planes;
+		size = ((size_t)dma->r.width * dma->fmtinfo->bpl_factor *
+			padding_factor_nume * bpl_nume) /
+			((size_t)padding_factor_deno * bpl_deno);
+		dma->sgl[0].size = size;
+		dma->sgl[0].icg = bpl - dma->sgl[0].size;
+		dma->xt.numf = dma->r.height;
+		dma->sgl[0].dst_icg = 0;
+		dst_icg = (size_t)bpl * (pix->height - dma->r.height);
+		dma->sgl[0].dst_icg = dst_icg;
+	}
 
 	desc = dmaengine_prep_interleaved_dma(dma->dma, &dma->xt, flags);
 	if (!desc) {
@@ -376,11 +480,28 @@
 	}
 	desc->callback = xvip_dma_complete;
 	desc->callback_param = buf;
+	buf->desc = desc;
+
+	if (buf->buf.field == V4L2_FIELD_TOP)
+		fid = 1;
+	else if (buf->buf.field == V4L2_FIELD_BOTTOM)
+		fid = 0;
+	else if (buf->buf.field == V4L2_FIELD_NONE)
+		fid = 0;
+
+	xilinx_xdma_set_fid(dma->dma, desc, fid);
 
 	spin_lock_irq(&dma->queued_lock);
 	list_add_tail(&buf->queue, &dma->queued_bufs);
 	spin_unlock_irq(&dma->queued_lock);
 
+	/*
+	 * Low latency capture: Give descriptor callback at start of
+	 * processing the descriptor
+	 */
+	if (dma->low_latency_cap)
+		xilinx_xdma_set_earlycb(dma->dma, desc,
+					EARLY_CALLBACK_START_DESC);
 	dmaengine_submit(desc);
 
 	if (vb2_is_streaming(&dma->queue))
@@ -395,6 +516,7 @@
 	int ret;
 
 	dma->sequence = 0;
+	dma->prev_fid = ~0;
 
 	/*
 	 * Start streaming on the pipeline. No link touching an entity in the
@@ -403,10 +525,12 @@
 	 * Use the pipeline object embedded in the first DMA object that starts
 	 * streaming.
 	 */
+	mutex_lock(&dma->xdev->lock);
 	pipe = dma->video.entity.pipe
 	     ? to_xvip_pipeline(&dma->video.entity) : &dma->pipe;
 
 	ret = media_pipeline_start(&dma->video.entity, &pipe->pipe);
+	mutex_unlock(&dma->xdev->lock);
 	if (ret < 0)
 		goto error;
 
@@ -423,11 +547,25 @@
 
 	/* Start the DMA engine. This must be done before starting the blocks
 	 * in the pipeline to avoid DMA synchronization issues.
+	 * We dont't want to start DMA in case of low latency capture mode,
+	 * applications will start DMA using S_CTRL at later point of time.
 	 */
-	dma_async_issue_pending(dma->dma);
+	if (!dma->low_latency_cap) {
+		dma_async_issue_pending(dma->dma);
+	} else {
+		/* For low latency capture, return the first buffer early
+		 * so that consumer can initialize until we start DMA.
+		 */
+		buf = list_first_entry(&dma->queued_bufs,
+				       struct xvip_dma_buffer, queue);
+		xvip_dma_complete(buf);
+		buf->desc->callback = NULL;
+	}
 
 	/* Start the pipeline. */
-	xvip_pipeline_set_stream(pipe, true);
+	ret = xvip_pipeline_set_stream(pipe, true);
+	if (ret < 0)
+		goto error_stop;
 
 	return 0;
 
@@ -435,6 +573,7 @@
 	media_pipeline_stop(&dma->video.entity);
 
 error:
+	dmaengine_terminate_all(dma->dma);
 	/* Give back all queued buffers to videobuf2. */
 	spin_lock_irq(&dma->queued_lock);
 	list_for_each_entry_safe(buf, nbuf, &dma->queued_bufs, queue) {
@@ -494,10 +633,104 @@
 	cap->capabilities = dma->xdev->v4l2_caps | V4L2_CAP_STREAMING |
 			    V4L2_CAP_DEVICE_CAPS;
 
-	strscpy(cap->driver, "xilinx-vipp", sizeof(cap->driver));
-	strscpy(cap->card, dma->video.name, sizeof(cap->card));
-	snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%pOFn:%u",
-		 dma->xdev->dev->of_node, dma->port);
+	strscpy((char *)cap->driver, "xilinx-vipp", sizeof(cap->driver));
+	strscpy((char *)cap->card, (char *)dma->video.name, sizeof(cap->card));
+	snprintf((char *)cap->bus_info, sizeof(cap->bus_info),
+		 "platform:%pOFn:%u", dma->xdev->dev->of_node, dma->port);
+
+	return 0;
+}
+
+static int xvip_xdma_enum_fmt(struct xvip_dma *dma, struct v4l2_fmtdesc *f,
+			      struct v4l2_subdev_format *v4l_fmt)
+{
+	const struct xvip_video_format *fmt;
+	int ret;
+	u32 i, fmt_cnt, *fmts;
+
+	ret = xilinx_xdma_get_v4l2_vid_fmts(dma->dma, &fmt_cnt, &fmts);
+	if (ret)
+		return ret;
+
+	/* Has media pad value changed? */
+	if (v4l_fmt->format.code != dma->remote_subdev_med_bus ||
+	    !dma->remote_subdev_med_bus) {
+		/* Re-generate legal list of fourcc codes */
+		dma->poss_v4l2_fmt_cnt = 0;
+		dma->remote_subdev_med_bus = v4l_fmt->format.code;
+
+		if (!dma->poss_v4l2_fmts) {
+			dma->poss_v4l2_fmts =
+				devm_kzalloc(&dma->video.dev,
+					     sizeof(u32) * fmt_cnt,
+					     GFP_KERNEL);
+			if (!dma->poss_v4l2_fmts)
+				return -ENOMEM;
+		}
+
+		for (i = 0; i < fmt_cnt; i++) {
+			fmt = xvip_get_format_by_fourcc(fmts[i]);
+			if (IS_ERR(fmt))
+				return PTR_ERR(fmt);
+
+			if (fmt->code != dma->remote_subdev_med_bus)
+				continue;
+
+			dma->poss_v4l2_fmts[dma->poss_v4l2_fmt_cnt++] =	fmts[i];
+		}
+	}
+
+	/* Return err if index is greater than count of legal values */
+	if (f->index >= dma->poss_v4l2_fmt_cnt)
+		return -EINVAL;
+
+	/* Else return pix format in table */
+	fmt = xvip_get_format_by_fourcc(dma->poss_v4l2_fmts[f->index]);
+	if (IS_ERR(fmt))
+		return PTR_ERR(fmt);
+
+	f->pixelformat = fmt->fourcc;
+
+	return 0;
+}
+
+static int
+xvip_dma_enum_input(struct file *file, void *priv, struct v4l2_input *i)
+{
+	struct v4l2_fh *vfh = file->private_data;
+	struct xvip_dma *dma = to_xvip_dma(vfh->vdev);
+	struct v4l2_subdev *subdev;
+
+	if (i->index > 0)
+		return -EINVAL;
+
+	subdev = xvip_dma_remote_subdev(&dma->pad, NULL);
+	if (!subdev)
+		return -EPIPE;
+
+	/*
+	 * FIXME: right now only camera input type is handled.
+	 * There should be mechanism to distinguish other types of
+	 * input like V4L2_INPUT_TYPE_TUNER and V4L2_INPUT_TYPE_TOUCH.
+	 */
+	i->type = V4L2_INPUT_TYPE_CAMERA;
+	strlcpy((char *)i->name, (char *)subdev->name, sizeof(i->name));
+
+	return 0;
+}
+
+static int
+xvip_dma_get_input(struct file *file, void *fh, unsigned int *i)
+{
+	*i = 0;
+	return 0;
+}
+
+static int
+xvip_dma_set_input(struct file *file, void *fh, unsigned int i)
+{
+	if (i > 0)
+		return -EINVAL;
 
 	return 0;
 }
@@ -512,11 +745,43 @@
 {
 	struct v4l2_fh *vfh = file->private_data;
 	struct xvip_dma *dma = to_xvip_dma(vfh->vdev);
+	struct v4l2_subdev *subdev;
+	struct v4l2_subdev_format v4l_fmt;
+	const struct xvip_video_format *fmt;
+	int err, ret;
+
+	/* Establish media pad format */
+	subdev = xvip_dma_remote_subdev(&dma->pad, &v4l_fmt.pad);
+	if (!subdev)
+		return -EPIPE;
 
+	v4l_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+	ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &v4l_fmt);
+	if (ret < 0)
+		return ret == -ENOIOCTLCMD ? -EINVAL : ret;
+
+	/*
+	 * In case of frmbuf DMA, this will invoke frambuf driver specific APIs
+	 * to enumerate formats otherwise return the pix format corresponding
+	 * to subdev's media bus format. This kind of separation would be
+	 * helpful for clean up and upstreaming.
+	 */
+	err = xvip_xdma_enum_fmt(dma, f, &v4l_fmt);
+	if (!err)
+		return err;
+
+	/*
+	 * This logic will just return one pix format based on subdev's
+	 * media bus format
+	 */
 	if (f->index > 0)
 		return -EINVAL;
 
-	f->pixelformat = dma->format.pixelformat;
+	fmt = xvip_get_format_by_code(v4l_fmt.format.code);
+	if (IS_ERR(fmt))
+		return PTR_ERR(fmt);
+
+	f->pixelformat = fmt->fourcc;
 
 	return 0;
 }
@@ -527,13 +792,17 @@
 	struct v4l2_fh *vfh = file->private_data;
 	struct xvip_dma *dma = to_xvip_dma(vfh->vdev);
 
-	format->fmt.pix = dma->format;
+	if (V4L2_TYPE_IS_MULTIPLANAR(dma->format.type))
+		format->fmt.pix_mp = dma->format.fmt.pix_mp;
+	else
+		format->fmt.pix = dma->format.fmt.pix;
 
 	return 0;
 }
 
 static void
-__xvip_dma_try_format(struct xvip_dma *dma, struct v4l2_pix_format *pix,
+__xvip_dma_try_format(struct xvip_dma *dma,
+		      struct v4l2_format *format,
 		      const struct xvip_video_format **fmtinfo)
 {
 	const struct xvip_video_format *info;
@@ -544,40 +813,151 @@
 	unsigned int width;
 	unsigned int align;
 	unsigned int bpl;
+	unsigned int i, hsub, vsub, plane_width, plane_height;
+	unsigned int fourcc;
+	unsigned int padding_factor_nume, padding_factor_deno;
+	unsigned int bpl_nume, bpl_deno;
+	struct v4l2_subdev_format fmt;
+	struct v4l2_subdev *subdev;
+	int ret;
+
+	subdev = xvip_dma_remote_subdev(&dma->pad, &fmt.pad);
+	if (!subdev)
+		return;
+
+	fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+	ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
+	if (ret < 0)
+		return;
+
+	if (fmt.format.field == V4L2_FIELD_ALTERNATE) {
+		if (V4L2_TYPE_IS_MULTIPLANAR(dma->format.type))
+			dma->format.fmt.pix_mp.field = V4L2_FIELD_ALTERNATE;
+		else
+			dma->format.fmt.pix.field = V4L2_FIELD_ALTERNATE;
+	} else {
+		if (V4L2_TYPE_IS_MULTIPLANAR(dma->format.type))
+			dma->format.fmt.pix_mp.field = V4L2_FIELD_NONE;
+		else
+			dma->format.fmt.pix.field = V4L2_FIELD_NONE;
+	}
 
 	/* Retrieve format information and select the default format if the
 	 * requested format isn't supported.
 	 */
-	info = xvip_get_format_by_fourcc(pix->pixelformat);
+	if (V4L2_TYPE_IS_MULTIPLANAR(dma->format.type))
+		fourcc = format->fmt.pix_mp.pixelformat;
+	else
+		fourcc = format->fmt.pix.pixelformat;
+
+	info = xvip_get_format_by_fourcc(fourcc);
+
 	if (IS_ERR(info))
 		info = xvip_get_format_by_fourcc(XVIP_DMA_DEF_FORMAT);
 
-	pix->pixelformat = info->fourcc;
-	pix->field = V4L2_FIELD_NONE;
+	xvip_width_padding_factor(info->fourcc, &padding_factor_nume,
+				  &padding_factor_deno);
+	xvip_bpl_scaling_factor(info->fourcc, &bpl_nume, &bpl_deno);
 
 	/* The transfer alignment requirements are expressed in bytes. Compute
 	 * the minimum and maximum values, clamp the requested width and convert
 	 * it back to pixels.
 	 */
-	align = lcm(dma->align, info->bpp);
+	align = lcm(dma->align, info->bpp >> 3);
+	if (!align) {
+		dev_err(dma->xdev->dev,
+			"transfer alignment is 0: dma->align = %x, bpp = %u\n",
+			dma->align, info->bpp);
+		return;
+	}
+
 	min_width = roundup(XVIP_DMA_MIN_WIDTH, align);
 	max_width = rounddown(XVIP_DMA_MAX_WIDTH, align);
-	width = rounddown(pix->width * info->bpp, align);
 
-	pix->width = clamp(width, min_width, max_width) / info->bpp;
-	pix->height = clamp(pix->height, XVIP_DMA_MIN_HEIGHT,
-			    XVIP_DMA_MAX_HEIGHT);
-
-	/* Clamp the requested bytes per line value. If the maximum bytes per
-	 * line value is zero, the module doesn't support user configurable line
-	 * sizes. Override the requested value with the minimum in that case.
-	 */
-	min_bpl = pix->width * info->bpp;
-	max_bpl = rounddown(XVIP_DMA_MAX_WIDTH, dma->align);
-	bpl = rounddown(pix->bytesperline, dma->align);
+	if (V4L2_TYPE_IS_MULTIPLANAR(dma->format.type)) {
+		struct v4l2_pix_format_mplane *pix_mp;
+		struct v4l2_plane_pix_format *plane_fmt;
+
+		pix_mp = &format->fmt.pix_mp;
+		plane_fmt = pix_mp->plane_fmt;
+		pix_mp->field = dma->format.fmt.pix_mp.field;
+		width = rounddown(pix_mp->width * info->bpl_factor, align);
+		pix_mp->width = clamp(width, min_width, max_width) /
+				info->bpl_factor;
+		pix_mp->height = clamp(pix_mp->height, XVIP_DMA_MIN_HEIGHT,
+				       XVIP_DMA_MAX_HEIGHT);
+
+		/*
+		 * Clamp the requested bytes per line value. If the maximum
+		 * bytes per line value is zero, the module doesn't support
+		 * user configurable line sizes. Override the requested value
+		 * with the minimum in that case.
+		 */
+
+		max_bpl = rounddown(XVIP_DMA_MAX_WIDTH, dma->align);
+
+		/* Handling contiguous data with mplanes */
+		if (info->buffers == 1) {
+			min_bpl = (pix_mp->width * info->bpl_factor *
+				   padding_factor_nume * bpl_nume) /
+				   (padding_factor_deno * bpl_deno);
+			min_bpl = roundup(min_bpl, dma->align);
+			bpl = roundup(plane_fmt[0].bytesperline, dma->align);
+			plane_fmt[0].bytesperline = clamp(bpl, min_bpl,
+							  max_bpl);
+
+			if (info->num_planes == 1) {
+				/* Single plane formats */
+				plane_fmt[0].sizeimage =
+						plane_fmt[0].bytesperline *
+						pix_mp->height;
+			} else {
+				/* Multi plane formats */
+				plane_fmt[0].sizeimage =
+					DIV_ROUND_UP(plane_fmt[0].bytesperline *
+						     pix_mp->height *
+						     info->bpp, 8);
+			}
+		} else {
+			/* Handling non-contiguous data with mplanes */
+			hsub = info->hsub;
+			vsub = info->vsub;
+			for (i = 0; i < info->num_planes; i++) {
+				plane_width = pix_mp->width / (i ? hsub : 1);
+				plane_height = pix_mp->height / (i ? vsub : 1);
+				min_bpl = (plane_width * info->bpl_factor *
+					   padding_factor_nume * bpl_nume) /
+					   (padding_factor_deno * bpl_deno);
+				min_bpl = roundup(min_bpl, dma->align);
+				bpl = rounddown(plane_fmt[i].bytesperline,
+						dma->align);
+				plane_fmt[i].bytesperline =
+						clamp(bpl, min_bpl, max_bpl);
+				plane_fmt[i].sizeimage =
+						plane_fmt[i].bytesperline *
+						plane_height;
+			}
+		}
+	} else {
+		struct v4l2_pix_format *pix;
 
-	pix->bytesperline = clamp(bpl, min_bpl, max_bpl);
-	pix->sizeimage = pix->bytesperline * pix->height;
+		pix = &format->fmt.pix;
+		pix->field = dma->format.fmt.pix.field;
+		width = rounddown(pix->width * info->bpl_factor, align);
+		pix->width = clamp(width, min_width, max_width) /
+			     info->bpl_factor;
+		pix->height = clamp(pix->height, XVIP_DMA_MIN_HEIGHT,
+				    XVIP_DMA_MAX_HEIGHT);
+
+		min_bpl = (pix->width * info->bpl_factor *
+			  padding_factor_nume * bpl_nume) /
+			  (padding_factor_deno * bpl_deno);
+		min_bpl = roundup(min_bpl, dma->align);
+		max_bpl = rounddown(XVIP_DMA_MAX_WIDTH, dma->align);
+		bpl = rounddown(pix->bytesperline, dma->align);
+		pix->bytesperline = clamp(bpl, min_bpl, max_bpl);
+		pix->sizeimage = pix->width * pix->height * info->bpp / 8;
+	}
 
 	if (fmtinfo)
 		*fmtinfo = info;
@@ -589,7 +969,7 @@
 	struct v4l2_fh *vfh = file->private_data;
 	struct xvip_dma *dma = to_xvip_dma(vfh->vdev);
 
-	__xvip_dma_try_format(dma, &format->fmt.pix, NULL);
+	__xvip_dma_try_format(dma, format, NULL);
 	return 0;
 }
 
@@ -600,26 +980,149 @@
 	struct xvip_dma *dma = to_xvip_dma(vfh->vdev);
 	const struct xvip_video_format *info;
 
-	__xvip_dma_try_format(dma, &format->fmt.pix, &info);
+	__xvip_dma_try_format(dma, format, &info);
 
 	if (vb2_is_busy(&dma->queue))
 		return -EBUSY;
 
-	dma->format = format->fmt.pix;
+	if (V4L2_TYPE_IS_MULTIPLANAR(dma->format.type)) {
+		dma->format.fmt.pix_mp = format->fmt.pix_mp;
+
+		/*
+		 * Save format resolution in crop rectangle. This will be
+		 * updated when s_slection is called.
+		 */
+		dma->r.width = format->fmt.pix_mp.width;
+		dma->r.height = format->fmt.pix_mp.height;
+	} else {
+		dma->format.fmt.pix = format->fmt.pix;
+		dma->r.width = format->fmt.pix.width;
+		dma->r.height = format->fmt.pix.height;
+	}
+
 	dma->fmtinfo = info;
 
 	return 0;
 }
 
+static int
+xvip_dma_g_selection(struct file *file, void *fh, struct v4l2_selection *sel)
+{
+	struct v4l2_fh *vfh = file->private_data;
+	struct xvip_dma *dma = to_xvip_dma(vfh->vdev);
+	u32 width, height;
+	bool crop_frame = false;
+
+	switch (sel->target) {
+	case V4L2_SEL_TGT_COMPOSE:
+		if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+			return -EINVAL;
+
+		crop_frame = true;
+		break;
+	case V4L2_SEL_TGT_COMPOSE_BOUNDS:
+	case V4L2_SEL_TGT_COMPOSE_DEFAULT:
+		if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+			return -EINVAL;
+		break;
+	case V4L2_SEL_TGT_CROP:
+		if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+			return -EINVAL;
+
+		crop_frame = true;
+		break;
+	case V4L2_SEL_TGT_CROP_BOUNDS:
+	case V4L2_SEL_TGT_CROP_DEFAULT:
+		if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+			return -EINVAL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	sel->r.left = 0;
+	sel->r.top = 0;
+
+	if (crop_frame) {
+		sel->r.width = dma->r.width;
+		sel->r.height = dma->r.height;
+	} else {
+		if (V4L2_TYPE_IS_MULTIPLANAR(dma->format.type)) {
+			width = dma->format.fmt.pix_mp.width;
+			height = dma->format.fmt.pix_mp.height;
+		} else {
+			width = dma->format.fmt.pix.width;
+			height = dma->format.fmt.pix.height;
+		}
+
+		sel->r.width = width;
+		sel->r.height = height;
+	}
+
+	return 0;
+}
+
+static int
+xvip_dma_s_selection(struct file *file, void *fh, struct v4l2_selection *sel)
+{
+	struct v4l2_fh *vfh = file->private_data;
+	struct xvip_dma *dma = to_xvip_dma(vfh->vdev);
+	u32 width, height;
+
+	switch (sel->target) {
+	case V4L2_SEL_TGT_COMPOSE:
+		/* COMPOSE target is only valid for capture buftype */
+		if (sel->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+			return -EINVAL;
+		break;
+	case V4L2_SEL_TGT_CROP:
+		/* CROP target is only valid for output buftype */
+		if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+			return -EINVAL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (V4L2_TYPE_IS_MULTIPLANAR(dma->format.type)) {
+		width = dma->format.fmt.pix_mp.width;
+		height = dma->format.fmt.pix_mp.height;
+	} else {
+		width = dma->format.fmt.pix.width;
+		height = dma->format.fmt.pix.height;
+	}
+
+	if (sel->r.width > width || sel->r.height > height ||
+	    sel->r.top != 0 || sel->r.left != 0)
+		return -EINVAL;
+
+	sel->r.width = roundup(max(XVIP_DMA_MIN_WIDTH, sel->r.width),
+			       dma->align);
+	sel->r.height = max(XVIP_DMA_MIN_HEIGHT, sel->r.height);
+	dma->r.width = sel->r.width;
+	dma->r.height = sel->r.height;
+
+	return 0;
+}
+
 static const struct v4l2_ioctl_ops xvip_dma_ioctl_ops = {
 	.vidioc_querycap		= xvip_dma_querycap,
 	.vidioc_enum_fmt_vid_cap	= xvip_dma_enum_format,
+	.vidioc_enum_fmt_vid_out	= xvip_dma_enum_format,
 	.vidioc_g_fmt_vid_cap		= xvip_dma_get_format,
+	.vidioc_g_fmt_vid_cap_mplane	= xvip_dma_get_format,
 	.vidioc_g_fmt_vid_out		= xvip_dma_get_format,
+	.vidioc_g_fmt_vid_out_mplane	= xvip_dma_get_format,
 	.vidioc_s_fmt_vid_cap		= xvip_dma_set_format,
+	.vidioc_s_fmt_vid_cap_mplane	= xvip_dma_set_format,
 	.vidioc_s_fmt_vid_out		= xvip_dma_set_format,
+	.vidioc_s_fmt_vid_out_mplane	= xvip_dma_set_format,
 	.vidioc_try_fmt_vid_cap		= xvip_dma_try_format,
+	.vidioc_try_fmt_vid_cap_mplane	= xvip_dma_try_format,
 	.vidioc_try_fmt_vid_out		= xvip_dma_try_format,
+	.vidioc_try_fmt_vid_out_mplane	= xvip_dma_try_format,
+	.vidioc_s_selection		= xvip_dma_s_selection,
+	.vidioc_g_selection		= xvip_dma_g_selection,
 	.vidioc_reqbufs			= vb2_ioctl_reqbufs,
 	.vidioc_querybuf		= vb2_ioctl_querybuf,
 	.vidioc_qbuf			= vb2_ioctl_qbuf,
@@ -628,6 +1131,99 @@
 	.vidioc_expbuf			= vb2_ioctl_expbuf,
 	.vidioc_streamon		= vb2_ioctl_streamon,
 	.vidioc_streamoff		= vb2_ioctl_streamoff,
+	.vidioc_enum_input	= &xvip_dma_enum_input,
+	.vidioc_g_input		= &xvip_dma_get_input,
+	.vidioc_s_input		= &xvip_dma_set_input,
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 controls
+ */
+
+static int xvip_dma_s_ctrl(struct v4l2_ctrl *ctl)
+{
+	struct xvip_dma *dma = container_of(ctl->handler, struct xvip_dma,
+					    ctrl_handler);
+	int ret = 0;
+
+	switch (ctl->id)  {
+	case V4L2_CID_XILINX_LOW_LATENCY:
+		if (ctl->val == XVIP_LOW_LATENCY_ENABLE) {
+			if (vb2_is_busy(&dma->queue))
+				return -EBUSY;
+
+			dma->low_latency_cap = true;
+			/*
+			 * Don't use auto-restart for low latency
+			 * to avoid extra one frame delay between
+			 * programming and actual writing of data
+			 */
+			xilinx_xdma_set_mode(dma->dma, DEFAULT);
+		} else if (ctl->val == XVIP_LOW_LATENCY_DISABLE) {
+			if (vb2_is_busy(&dma->queue))
+				return -EBUSY;
+
+			dma->low_latency_cap = false;
+			xilinx_xdma_set_mode(dma->dma, AUTO_RESTART);
+		} else if (ctl->val == XVIP_START_DMA) {
+			/*
+			 * In low latency capture, the driver allows application
+			 * to start dma when queue has buffers. That's why we
+			 * don't check for vb2_is_busy().
+			 */
+			if (dma->low_latency_cap &&
+			    vb2_is_streaming(&dma->queue))
+				dma_async_issue_pending(dma->dma);
+			else
+				ret = -EINVAL;
+		} else {
+			ret = -EINVAL;
+		}
+
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int xvip_dma_open(struct file *file)
+{
+	int ret;
+
+	ret = v4l2_fh_open(file);
+	if (ret)
+		return ret;
+
+	/* Disable the low latency mode as default */
+	if (v4l2_fh_is_singular_file(file)) {
+		struct xvip_dma *dma = video_drvdata(file);
+
+		mutex_lock(&dma->lock);
+		dma->low_latency_cap = false;
+		xilinx_xdma_set_mode(dma->dma, AUTO_RESTART);
+		mutex_unlock(&dma->lock);
+	}
+
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops xvip_dma_ctrl_ops = {
+	.s_ctrl = xvip_dma_s_ctrl,
+};
+
+static const struct v4l2_ctrl_config xvip_dma_ctrls[] = {
+	{
+		.ops = &xvip_dma_ctrl_ops,
+		.id = V4L2_CID_XILINX_LOW_LATENCY,
+		.name = "Low Latency Controls",
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.min = XVIP_LOW_LATENCY_ENABLE,
+		.max = XVIP_START_DMA,
+		.step = 1,
+		.def = XVIP_LOW_LATENCY_DISABLE,
+	}
 };
 
 /* -----------------------------------------------------------------------------
@@ -637,7 +1233,7 @@
 static const struct v4l2_file_operations xvip_dma_fops = {
 	.owner		= THIS_MODULE,
 	.unlocked_ioctl	= video_ioctl2,
-	.open		= v4l2_fh_open,
+	.open		= xvip_dma_open,
 	.release	= vb2_fop_release,
 	.poll		= vb2_fop_poll,
 	.mmap		= vb2_fop_mmap,
@@ -652,6 +1248,7 @@
 {
 	char name[16];
 	int ret;
+	u32 i, hsub, vsub, width, height;
 
 	dma->xdev = xdev;
 	dma->port = port;
@@ -661,41 +1258,131 @@
 	spin_lock_init(&dma->queued_lock);
 
 	dma->fmtinfo = xvip_get_format_by_fourcc(XVIP_DMA_DEF_FORMAT);
-	dma->format.pixelformat = dma->fmtinfo->fourcc;
-	dma->format.colorspace = V4L2_COLORSPACE_SRGB;
-	dma->format.field = V4L2_FIELD_NONE;
-	dma->format.width = XVIP_DMA_DEF_WIDTH;
-	dma->format.height = XVIP_DMA_DEF_HEIGHT;
-	dma->format.bytesperline = dma->format.width * dma->fmtinfo->bpp;
-	dma->format.sizeimage = dma->format.bytesperline * dma->format.height;
+	dma->format.type = type;
+
+	if (V4L2_TYPE_IS_MULTIPLANAR(type)) {
+		struct v4l2_pix_format_mplane *pix_mp;
+
+		pix_mp = &dma->format.fmt.pix_mp;
+		pix_mp->pixelformat = dma->fmtinfo->fourcc;
+		pix_mp->colorspace = V4L2_COLORSPACE_SRGB;
+		pix_mp->field = V4L2_FIELD_NONE;
+		pix_mp->width = XVIP_DMA_DEF_WIDTH;
+
+		/* Handling contiguous data with mplanes */
+		if (dma->fmtinfo->buffers == 1) {
+			pix_mp->plane_fmt[0].bytesperline =
+				pix_mp->width * dma->fmtinfo->bpl_factor;
+			pix_mp->plane_fmt[0].sizeimage =
+					pix_mp->width * pix_mp->height *
+					dma->fmtinfo->bpp / 8;
+		} else {
+		    /* Handling non-contiguous data with mplanes */
+			hsub = dma->fmtinfo->hsub;
+			vsub = dma->fmtinfo->vsub;
+			for (i = 0; i < dma->fmtinfo->buffers; i++) {
+				width = pix_mp->width / (i ? hsub : 1);
+				height = pix_mp->height / (i ? vsub : 1);
+				pix_mp->plane_fmt[i].bytesperline =
+					width *	dma->fmtinfo->bpl_factor;
+				pix_mp->plane_fmt[i].sizeimage = width * height;
+			}
+		}
+	} else {
+		struct v4l2_pix_format *pix;
+
+		pix = &dma->format.fmt.pix;
+		pix->pixelformat = dma->fmtinfo->fourcc;
+		pix->colorspace = V4L2_COLORSPACE_SRGB;
+		pix->field = V4L2_FIELD_NONE;
+		pix->width = XVIP_DMA_DEF_WIDTH;
+		pix->height = XVIP_DMA_DEF_HEIGHT;
+		pix->bytesperline = pix->width * dma->fmtinfo->bpl_factor;
+		pix->sizeimage =
+			pix->width * pix->height * dma->fmtinfo->bpp / 8;
+	}
 
 	/* Initialize the media entity... */
-	dma->pad.flags = type == V4L2_BUF_TYPE_VIDEO_CAPTURE
-		       ? MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE;
+	if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+	    type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+		dma->pad.flags = MEDIA_PAD_FL_SINK;
+	else
+		dma->pad.flags = MEDIA_PAD_FL_SOURCE;
 
 	ret = media_entity_pads_init(&dma->video.entity, 1, &dma->pad);
 	if (ret < 0)
 		goto error;
 
+	ret = v4l2_ctrl_handler_init(&dma->ctrl_handler,
+				     ARRAY_SIZE(xvip_dma_ctrls));
+	if (ret < 0) {
+		dev_err(dma->xdev->dev, "failed to initialize V4L2 ctrl\n");
+		goto error;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(xvip_dma_ctrls); i++) {
+		struct v4l2_ctrl *ctrl;
+
+		dev_dbg(dma->xdev->dev, "%d ctrl = 0x%x\n", i,
+			xvip_dma_ctrls[i].id);
+		ctrl = v4l2_ctrl_new_custom(&dma->ctrl_handler,
+					    &xvip_dma_ctrls[i], NULL);
+		if (!ctrl) {
+			dev_err(dma->xdev->dev, "Failed for %s ctrl\n",
+				xvip_dma_ctrls[i].name);
+			goto error;
+		}
+	}
+
+	if (dma->ctrl_handler.error) {
+		dev_err(dma->xdev->dev, "failed to add controls\n");
+		ret = dma->ctrl_handler.error;
+		goto error;
+	}
+
+	ret = v4l2_ctrl_handler_setup(&dma->ctrl_handler);
+	if (ret < 0) {
+		dev_err(dma->xdev->dev, "failed to set controls\n");
+		goto error;
+	}
+
 	/* ... and the video node... */
 	dma->video.fops = &xvip_dma_fops;
 	dma->video.v4l2_dev = &xdev->v4l2_dev;
+	dma->video.v4l2_dev->ctrl_handler = &dma->ctrl_handler;
 	dma->video.queue = &dma->queue;
 	snprintf(dma->video.name, sizeof(dma->video.name), "%pOFn %s %u",
 		 xdev->dev->of_node,
-		 type == V4L2_BUF_TYPE_VIDEO_CAPTURE ? "output" : "input",
+		 (type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+		  type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+					? "output" : "input",
 		 port);
+
 	dma->video.vfl_type = VFL_TYPE_GRABBER;
-	dma->video.vfl_dir = type == V4L2_BUF_TYPE_VIDEO_CAPTURE
-			   ? VFL_DIR_RX : VFL_DIR_TX;
+	if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+	    type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+		dma->video.vfl_dir = VFL_DIR_RX;
+	else
+		dma->video.vfl_dir = VFL_DIR_TX;
+
 	dma->video.release = video_device_release_empty;
 	dma->video.ioctl_ops = &xvip_dma_ioctl_ops;
 	dma->video.lock = &dma->lock;
 	dma->video.device_caps = V4L2_CAP_STREAMING;
-	if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+	switch (dma->format.type) {
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+		dma->video.device_caps |= V4L2_CAP_VIDEO_CAPTURE_MPLANE;
+		break;
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 		dma->video.device_caps |= V4L2_CAP_VIDEO_CAPTURE;
-	else
+		break;
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+		dma->video.device_caps |= V4L2_CAP_VIDEO_OUTPUT_MPLANE;
+		break;
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
 		dma->video.device_caps |= V4L2_CAP_VIDEO_OUTPUT;
+		break;
+	}
 
 	video_set_drvdata(&dma->video, dma);
 
@@ -725,10 +1412,12 @@
 
 	/* ... and the DMA channel. */
 	snprintf(name, sizeof(name), "port%u", port);
-	dma->dma = dma_request_slave_channel(dma->xdev->dev, name);
-	if (dma->dma == NULL) {
-		dev_err(dma->xdev->dev, "no VDMA channel found\n");
-		ret = -ENODEV;
+	dma->dma = dma_request_chan(dma->xdev->dev, name);
+	if (IS_ERR(dma->dma)) {
+		ret = PTR_ERR(dma->dma);
+		if (ret != -EPROBE_DEFER)
+			dev_err(dma->xdev->dev,
+				"No Video DMA channel found");
 		goto error;
 	}
 
@@ -752,9 +1441,10 @@
 	if (video_is_registered(&dma->video))
 		video_unregister_device(&dma->video);
 
-	if (dma->dma)
+	if (!IS_ERR(dma->dma))
 		dma_release_channel(dma->dma);
 
+	v4l2_ctrl_handler_free(&dma->ctrl_handler);
 	media_entity_cleanup(&dma->video.entity);
 
 	mutex_destroy(&dma->lock);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/xilinx-dma.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/xilinx-dma.h
@@ -18,6 +18,7 @@
 #include <linux/videodev2.h>
 
 #include <media/media-entity.h>
+#include <media/v4l2-ctrls.h>
 #include <media/v4l2-dev.h>
 #include <media/videobuf2-v4l2.h>
 
@@ -32,7 +33,7 @@
  * @use_count: number of DMA engines using the pipeline
  * @stream_count: number of DMA engines currently streaming
  * @num_dmas: number of DMA engines in the pipeline
- * @output: DMA engine at the output of the pipeline
+ * @xdev: Composite device the pipe belongs to
  */
 struct xvip_pipeline {
 	struct media_pipeline pipe;
@@ -42,7 +43,7 @@
 	unsigned int stream_count;
 
 	unsigned int num_dmas;
-	struct xvip_dma *output;
+	struct xvip_composite_device *xdev;
 };
 
 static inline struct xvip_pipeline *to_xvip_pipeline(struct media_entity *e)
@@ -55,12 +56,17 @@
  * @list: list entry in a composite device dmas list
  * @video: V4L2 video device associated with the DMA channel
  * @pad: media pad for the video device entity
+ * @remote_subdev_med_bus: media bus format of sub-device
+ * @ctrl_handler: V4L2 ctrl_handler for inheritance ctrls from subdev
  * @xdev: composite device the DMA channel belongs to
  * @pipe: pipeline belonging to the DMA channel
  * @port: composite device DT node port number for the DMA channel
  * @lock: protects the @format, @fmtinfo and @queue fields
  * @format: active V4L2 pixel format
+ * @r: crop rectangle parameters
  * @fmtinfo: format information corresponding to the active @format
+ * @poss_v4l2_fmts: All possible v4l formats supported
+ * @poss_v4l2_fmt_cnt: number of supported v4l formats
  * @queue: vb2 buffers queue
  * @sequence: V4L2 buffers sequence number
  * @queued_bufs: list of queued buffers
@@ -69,19 +75,27 @@
  * @align: transfer alignment required by the DMA channel (in bytes)
  * @xt: dma interleaved template for dma configuration
  * @sgl: data chunk structure for dma_interleaved_template
+ * @prev_fid: Previous Field ID
+ * @low_latency_cap: Low latency capture mode
  */
 struct xvip_dma {
 	struct list_head list;
 	struct video_device video;
 	struct media_pad pad;
+	u32 remote_subdev_med_bus;
+
+	struct v4l2_ctrl_handler ctrl_handler;
 
 	struct xvip_composite_device *xdev;
 	struct xvip_pipeline pipe;
 	unsigned int port;
 
 	struct mutex lock;
-	struct v4l2_pix_format format;
+	struct v4l2_format format;
+	struct v4l2_rect r;
 	const struct xvip_video_format *fmtinfo;
+	u32 *poss_v4l2_fmts;
+	u32 poss_v4l2_fmt_cnt;
 
 	struct vb2_queue queue;
 	unsigned int sequence;
@@ -93,6 +107,9 @@
 	unsigned int align;
 	struct dma_interleaved_template xt;
 	struct data_chunk sgl[1];
+
+	u32 prev_fid;
+	u32 low_latency_cap;
 };
 
 #define to_xvip_dma(vdev)	container_of(vdev, struct xvip_dma, video)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/xilinx-dprxss.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/xilinx-dprxss.c
@@ -0,0 +1,1318 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx DP Rx Subsystem
+ *
+ * Copyright (C) 2020 Xilinx, Inc.
+ *
+ * Author: Rajesh Gugulothu <gugulothu.rajesh@xilinx.com>
+ *
+ */
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/phy/phy.h>
+#include <linux/phy/phy-dp.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+#include <linux/v4l2-dv-timings.h>
+#include <linux/v4l2-subdev.h>
+
+#include <drm/drm_dp_helper.h>
+#include <dt-bindings/media/xilinx-vip.h>
+
+#include <media/v4l2-dv-timings.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-subdev.h>
+
+#include "xilinx-vip.h"
+
+/* DP Rx subsysetm register map, bitmask, and offsets. */
+#define XDPRX_LINK_ENABLE_REG		0x000
+#define XDPRX_AUX_CLKDIV_REG		0x004
+#define XDPRX_AUX_DEFER_COUNT		6
+#define XDPRX_AUX_DEFER_SHIFT		24
+#define XDPRX_AUX_DEFER_MASK		GENMASK(27, 24)
+
+#define XDPRX_LINERST_DIS_REG		0x008
+#define XDPRX_DTG_REG			0x00c
+#define XDPRX_DTG_DIS_MASK		GENMASK(31, 1)
+
+#define XDPRX_PIXEL_WIDTH_REG		0x010
+#define XDPRX_INTR_MASK_REG		0x014
+#define XDPRX_INTR_POWER_MASK		BIT(1)
+#define XDPRX_INTR_NOVID_MASK		BIT(2)
+#define XDPRX_INTR_VBLANK_MASK		BIT(3)
+#define XDPRX_INTR_TRLOST_MASK		BIT(4)
+#define XDPRX_INTR_VID_MASK		BIT(6)
+#define XDPRX_INTR_TRDONE_MASK		BIT(14)
+#define XDPRX_INTR_BWCHANGE_MASK	BIT(15)
+#define XDPRX_INTR_TP1_MASK		BIT(16)
+#define XDPRX_INTR_T2_MASK		BIT(17)
+#define XDPRX_INTR_TP3_MASK		BIT(18)
+#define XDPRX_INTR_LINKQUAL_MASK	BIT(29)
+#define XDPRX_INTR_UNPLUG_MASK		BIT(31)
+#define XDPRX_INTR_CRCTST_MASK		BIT(30)
+#define XDPRX_INTR_TRNG_MASK		(XDPRX_INTR_TP1_MASK | \
+					 XDPRX_INTR_T2_MASK |\
+					 XDPRX_INTR_TP3_MASK | \
+					 XDPRX_INTR_POWER_MASK |\
+					 XDPRX_INTR_CRCTST_MASK |\
+					 XDPRX_INTR_BWCHANGE_MASK)
+#define XDPRX_INTR_ALL_MASK		0xffffffff
+
+#define XDPRX_SOFT_RST_REG		0x01c
+#define XDPRX_SOFT_VIDRST_MASK		BIT(0)
+#define XDPRX_SOFT_AUXRST_MASK		BIT(7)
+
+#define XDPRX_HPD_INTR_REG		0x02c
+#define XDPRX_HPD_INTR_MASK		BIT(1)
+#define XDPRX_HPD_PULSE_MASK		GENMASK(31, 16)
+
+#define XDPRX_INTR_CAUSE_REG		0x040
+#define XDPRX_INTR_CAUSE1_REG		0x048
+#define XDPRX_CRC_CONFIG_REG		0x074
+#define XDPRX_CRC_EN_MASK		BIT(5)
+
+#define XDPRX_LOCAL_EDID_REG		0x084
+#define XDPRX_VIDEO_UNSUPPORTED_REG	0x094
+#define XDPRX_VRD_BWSET_REG		0x09c
+#define XDPRX_LANE_CNT_REG		0x0a0
+#define XDPRX_EFRAME_CAP_MASK		BIT(7)
+#define XDPRX_LNCNT_TPS3_MASK		BIT(6)
+
+#define XDPRX_TP_SET_REG		0x0a4
+#define XDPRX_AUX_RDINT_SHIFT		8
+#define XDPRX_AUX_RDINT_16MS		4
+#define XDPRX_AUX_READINTRVL_REG	BIT(15)
+
+#define XDPRX_CTRL_DPCD_REG		0x0b8
+#define XDPRX_MST_CAP_REG		0x0d0
+#define XDPRX_SINK_COUNT_REG		0x0d4
+
+#define XDPRX_PHY_REG			0x200
+#define XDPRX_PHY_GTPLLRST_MASK		BIT(0)
+#define XDPRX_PHY_GTRXRST_MASK		BIT(1)
+#define XDPRX_PHYRST_TRITER_MASK	BIT(23)
+#define XDPRX_PHYRST_RATECHANGE_MASK	BIT(24)
+#define XDPRX_PHYRST_TP1START_MASK	BIT(25)
+#define XDPRX_PHYRST_ENBL_MASK		0x0
+#define XDPRX_PHY_INIT_MASK		GENMASK(29, 27)
+
+#define XDPRX_MINVOLT_SWING_REG		0x214
+#define XDPRX_VS_PE_SHIFT		12
+#define XDPRX_VS_SWEEP_CNTSHIFT		4
+#define XDPRX_VS_CROPT_SHIFT		2
+#define XDPRX_VS_CROPT_INC4CNT		1
+#define XDPRX_MIN_VS_MASK		(1 | (XDPRX_VS_CROPT_INC4CNT << \
+					 XDPRX_VS_CROPT_SHIFT) | \
+					 (4 << XDPRX_VS_SWEEP_CNTSHIFT) | \
+					 (1 << XDPRX_VS_PE_SHIFT))
+
+#define XDPRX_CDRCTRL_CFG_REG		0x21c
+/* CDR tDLOCK calibration value */
+#define XDPRX_CDRCTRL_TDLOCK_VAL	0x1388
+#define XDPRX_CDRCTRL_DIS_TIMEOUT	BIT(30)
+
+#define XDPRX_BSIDLE_TIME_REG		0x220
+#define XDPRX_BSIDLE_TMOUT_VAL		0x047868C0
+
+#define XDPRX_LINK_BW_REG		0x400
+#define XDPRX_LANE_COUNT_REG		0x404
+#define XDPRX_MSA_HRES_REG		0x500
+#define XDPRX_MSA_VHEIGHT_REG		0x514
+#define XDPRX_MSA_HTOTAL_REG		0x510
+#define XDPRX_MSA_VTOTAL_REG		0x524
+#define XDPRX_MSA_MISC0_REG		0x528
+#define XDPRX_MSA_FMT_MASK		GENMASK(2, 1)
+#define XDPRX_MSA_BPC_MASK		GENMASK(7, 5)
+#define XDPRX_COLOR_DEPTH_SHIFT		5
+#define XDPRX_COLOR_FMT_SHIFT		1
+
+#define XDPRX_MSA_MISC1_REG		0x52c
+#define XDPRX_INTERLACE_MASK		BIT(0)
+
+#define XDPRX_MSA_MVID_REG		0x530
+#define XDPRX_MSA_NVID_REG		0x534
+#define XDPRX_INTR_ERRORCNT_MASK	BIT(28)
+#define XDPRX_INTR_LANESET_MASK		BIT(30)
+
+#define XDPRX_COLOR_FORMAT_RGB		0x0
+#define XDPRX_COLOR_FORMAT_422		0x1
+#define XDPRX_COLOR_FORMAT_444		0x2
+#define MHZ				1000000
+#define XDPRX_MAX_LANE_COUNT		4
+
+#define XDPRX_EDID_NUM_BLOCKS		3
+#define XDPRX_EDID_BLOCK_SIZE		128
+#define XDPRX_EDID_LENGTH		(XDPRX_EDID_BLOCK_SIZE * \
+					 XDPRX_EDID_NUM_BLOCKS * 4)
+/*
+ * IRQ_HPD pulse for upstream device is 5ms as per
+ * the VESA standard
+ */
+#define XDPRX_HPD_PLUSE_5000		5000
+/*
+ * low going IRQ_HPD generated for upstream device
+ * as per the VESA standard
+ */
+#define XDPRX_HPD_PLUSE_750		750
+
+/**
+ * struct xdprxss_state - DP Rx Subsystem device structure
+ * @dev: Platform structure
+ * @subdev: The v4l2 subdev structure
+ * @event: Holds the video unlock event
+ * @detected_timings: Detected Video timings
+ * @phy: pointer to phy instance
+ * @pad: media pad
+ * @axi_clk: Axi lite interface clock
+ * @rx_lnk_clk: DP Rx GT clock
+ * @rx_vid_clk: DP RX Video clock
+ * @dp_base: Base address of DP Rx Subsystem
+ * @edid_base: Bare Address of EDID block
+ * @lock: Lock is used for width, height, framerate variables
+ * @format: Active V4L2 format on each pad
+ * @frame_interval: Captures the frame rate
+ * @max_linkrate: Maximum supported link rate
+ * @max_lanecount: Maximux supported lane count
+ * @bpc: Bits per component
+ * @hdcp_enable: To indicate hdcp enabled or not
+ * @audio_enable: To indicate audio enabled or not
+ * @valid_stream: To indicate valid video
+ * @streaming: Flag for storing streaming state
+ * This structure contains the device driver related parameters
+ */
+struct xdprxss_state {
+	struct device *dev;
+	struct v4l2_subdev subdev;
+	struct v4l2_event event;
+	struct v4l2_dv_timings detected_timings;
+	struct phy *phy[XDPRX_MAX_LANE_COUNT];
+	struct media_pad pad;
+	struct clk *axi_clk;
+	struct clk *rx_lnk_clk;
+	struct clk *rx_vid_clk;
+	void __iomem *dp_base;
+	void __iomem *edid_base;
+	/* protects width, height, framerate variables */
+	spinlock_t lock;
+	struct v4l2_mbus_framefmt format;
+	unsigned int frame_interval;
+	u32 max_linkrate;
+	u32 max_lanecount;
+	u32 bpc;
+	bool hdcp_enable;
+	bool audio_enable;
+	unsigned int valid_stream : 1;
+	unsigned int streaming : 1;
+};
+
+/*
+ * This is a default EDID data loaded to EDID memory. It allows the source
+ * to get edid before application start on DP Rx.User can load their
+ * custom EDID data using set_edid functions call
+ */
+static u8 xilinx_edid[384] = {
+	0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x10, 0xac, 0x47, 0x41,
+	0x4c, 0x35, 0x37, 0x30, 0x20, 0x1b, 0x01, 0x04, 0xb5, 0x46, 0x27, 0x78,
+	0x3a, 0x76, 0x45, 0xae, 0x51, 0x33, 0xba, 0x26, 0x0d, 0x50, 0x54, 0xa5,
+	0x4b, 0x00, 0x81, 0x00, 0xb3, 0x00, 0xd1, 0x00, 0xa9, 0x40, 0x81, 0x80,
+	0xd1, 0xc0, 0x01, 0x01, 0x01, 0x01, 0x4d, 0xd0, 0x00, 0xa0, 0xf0, 0x70,
+	0x3e, 0x80, 0x30, 0x20, 0x35, 0x00, 0xba, 0x89, 0x21, 0x00, 0x00, 0x1a,
+	0x00, 0x00, 0x00, 0xff, 0x00, 0x46, 0x46, 0x4e, 0x58, 0x4d, 0x37, 0x38,
+	0x37, 0x30, 0x37, 0x35, 0x4c, 0x0a, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x44,
+	0x45, 0x4c, 0x4c, 0x20, 0x55, 0x50, 0x33, 0x32, 0x31, 0x38, 0x4b, 0x0a,
+	0x00, 0x00, 0x00, 0xfd, 0x00, 0x18, 0x4b, 0x1e, 0xb4, 0x6c, 0x01, 0x0a,
+	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x02, 0x70, 0x02, 0x03, 0x1d, 0xf1,
+	0x50, 0x10, 0x1f, 0x20, 0x05, 0x14, 0x04, 0x13, 0x12, 0x11, 0x03, 0x02,
+	0x16, 0x15, 0x07, 0x06, 0x01, 0x23, 0x09, 0x1f, 0x07, 0x83, 0x01, 0x00,
+	0x00, 0xa3, 0x66, 0x00, 0xa0, 0xf0, 0x70, 0x1f, 0x80, 0x30, 0x20, 0x35,
+	0x00, 0xba, 0x89, 0x21, 0x00, 0x00, 0x1a, 0x56, 0x5e, 0x00, 0xa0, 0xa0,
+	0xa0, 0x29, 0x50, 0x30, 0x20, 0x35, 0x00, 0xba, 0x89, 0x21, 0x00, 0x00,
+	0x1a, 0x7c, 0x39, 0x00, 0xA0, 0x80, 0x38, 0x1f, 0x40, 0x30, 0x20, 0x3a,
+	0x00, 0xba, 0x89, 0x21, 0x00, 0x00, 0x1a, 0xa8, 0x16, 0x00, 0xa0, 0x80,
+	0x38, 0x13, 0x40, 0x30, 0x20, 0x3a, 0x00, 0xba, 0x89, 0x21, 0x00, 0x00,
+	0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x47, 0x70, 0x12, 0x79, 0x00, 0x00, 0x12, 0x00, 0x16,
+	0x82, 0x10, 0x10, 0x00, 0xff, 0x0e, 0xdf, 0x10, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x44, 0x45, 0x4c, 0x47, 0x41, 0x4c, 0x35, 0x37, 0x30, 0x03, 0x01,
+	0x50, 0x70, 0x92, 0x01, 0x84, 0xff, 0x1d, 0xc7, 0x00, 0x1d, 0x80, 0x09,
+	0x00, 0xdf, 0x10, 0x2f, 0x00, 0x02, 0x00, 0x04, 0x00, 0xc1, 0x42, 0x01,
+	0x84, 0xff, 0x1d, 0xc7, 0x00, 0x2f, 0x80, 0x1f, 0x00, 0xdf, 0x10, 0x30,
+	0x00, 0x02, 0x00, 0x04, 0x00, 0xa8, 0x4e, 0x01, 0x04, 0xff, 0x0e, 0xc7,
+	0x00, 0x2f, 0x80, 0x1f, 0x00, 0xdf, 0x10, 0x61, 0x00, 0x02, 0x00, 0x09,
+	0x00, 0x97, 0x9d, 0x01, 0x04, 0xff, 0x0e, 0xc7, 0x00, 0x2f, 0x80, 0x1f,
+	0x00, 0xdf, 0x10, 0x2f, 0x00, 0x02, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x90,
+};
+
+static const u32 xdprxss_supported_mbus_fmts[] = {
+	MEDIA_BUS_FMT_UYVY8_1X16,
+	MEDIA_BUS_FMT_VUY8_1X24,
+	MEDIA_BUS_FMT_RBG888_1X24,
+	MEDIA_BUS_FMT_UYVY10_1X20,
+	MEDIA_BUS_FMT_VUY10_1X30,
+	MEDIA_BUS_FMT_RBG101010_1X30,
+};
+
+#define XLNX_V4L2_DV_BT_2048X1080P60 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2048, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 88, 44, 20, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861) \
+}
+
+#define XLNX_V4L2_DV_BT_2048X1080I50 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2048, 1080, 1, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 274, 44, 274, 2, 5, 15, 3, 5, 15, \
+		V4L2_DV_BT_STD_CEA861) \
+}
+
+#define XLNX_V4L2_DV_BT_2048X1080I60 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2048, 1080, 1, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 66, 20, 66, 2, 5, 15, 3, 5, 15, \
+		V4L2_DV_BT_STD_CEA861) \
+}
+
+#define XLNX_V4L2_DV_BT_2048X1080P50 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2048, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 400, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861) \
+}
+
+#define XLNX_V4L2_DV_BT_7680X4320P30 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(7680, 4320, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 552, 176, 592, 16, 20, 44, 0, 0, 0, \
+		V4L2_DV_BT_STD_CEA861) \
+}
+
+static const struct v4l2_dv_timings fmt_cap[] = {
+	V4L2_DV_BT_CEA_1280X720P25,
+	V4L2_DV_BT_CEA_1280X720P30,
+	V4L2_DV_BT_CEA_1280X720P50,
+	V4L2_DV_BT_CEA_1280X720P60,
+	V4L2_DV_BT_CEA_1920X1080P25,
+	V4L2_DV_BT_CEA_1920X1080P30,
+	V4L2_DV_BT_CEA_1920X1080P50,
+	V4L2_DV_BT_CEA_1920X1080P60,
+	V4L2_DV_BT_CEA_1920X1080I50,
+	V4L2_DV_BT_CEA_1920X1080I60,
+	V4L2_DV_BT_CEA_3840X2160P30,
+	V4L2_DV_BT_CEA_3840X2160P50,
+	V4L2_DV_BT_CEA_3840X2160P60,
+	V4L2_DV_BT_CEA_4096X2160P25,
+	V4L2_DV_BT_CEA_4096X2160P30,
+	V4L2_DV_BT_CEA_4096X2160P50,
+	V4L2_DV_BT_CEA_4096X2160P60,
+
+	XLNX_V4L2_DV_BT_2048X1080I50,
+	XLNX_V4L2_DV_BT_2048X1080I60,
+	XLNX_V4L2_DV_BT_2048X1080P50,
+	XLNX_V4L2_DV_BT_2048X1080P60,
+	XLNX_V4L2_DV_BT_7680X4320P30,
+};
+
+struct xdprxss_dv_map {
+	u32 width;
+	u32 height;
+	u32 fps;
+	struct v4l2_dv_timings timing;
+};
+
+static const struct xdprxss_dv_map xdprxss_dv_timings[] = {
+	/* HD - 1280x720p25 */
+	{ 1280, 720, 25, V4L2_DV_BT_CEA_1280X720P25 },
+	/* HD - 1280x720p30 */
+	{ 1280, 720, 30, V4L2_DV_BT_CEA_1280X720P30 },
+	/* HD - 1280x720p50 */
+	{ 1280, 720, 50, V4L2_DV_BT_CEA_1280X720P50 },
+	/* HD - 1280x720p60 */
+	{ 1280, 720, 60, V4L2_DV_BT_CEA_1280X720P60 },
+	/* HD - 1920x1080p25 */
+	{ 1920, 1080, 25, V4L2_DV_BT_CEA_1920X1080P25 },
+	/* HD - 1920x1080p30 */
+	{ 1920, 1080, 30, V4L2_DV_BT_CEA_1920X1080P30 },
+	/* HD - 1920x1080p50 */
+	{ 1920, 1080, 50, V4L2_DV_BT_CEA_1920X1080P50 },
+	/* HD - 1920x1080p60 */
+	{ 1920, 1080, 60, V4L2_DV_BT_CEA_1920X1080P60 },
+	/* HD - 1920x1080i50 */
+	{ 1920, 540, 25, V4L2_DV_BT_CEA_1920X1080I50 },
+	/* HD - 1920x1080i59.94 */
+	/* HD - 1920x1080i60 */
+	{ 1920, 540, 30, V4L2_DV_BT_CEA_1920X1080I60 },
+	{ 3840, 2160, 30, V4L2_DV_BT_CEA_3840X2160P30 },
+	{ 3840, 2160, 50, V4L2_DV_BT_CEA_3840X2160P50 },
+	{ 3840, 2160, 60, V4L2_DV_BT_CEA_3840X2160P60 },
+	{ 4096, 2160, 25, V4L2_DV_BT_CEA_4096X2160P25 },
+	{ 4096, 2160, 30, V4L2_DV_BT_CEA_4096X2160P30 },
+	{ 4096, 2160, 50, V4L2_DV_BT_CEA_4096X2160P50 },
+	{ 4096, 2160, 60, V4L2_DV_BT_CEA_4096X2160P60 },
+	/* HD - 2048x1080i50 */
+	{ 2048, 540, 25, XLNX_V4L2_DV_BT_2048X1080I50 },
+	/* HD - 2048x1080i59.94 */
+	/* HD - 2048x1080i60 */
+	{ 2048, 540, 30, XLNX_V4L2_DV_BT_2048X1080I60 },
+	/* 3G - 2048x1080p50 */
+	{ 2048, 1080, 50, XLNX_V4L2_DV_BT_2048X1080P50 },
+	/* 3G - 2048x1080p59.94 */
+	/* 3G - 2048x1080p60 */
+	{ 2048, 1080, 60, XLNX_V4L2_DV_BT_2048X1080P60 },
+	{ 7680, 4320, 30, XLNX_V4L2_DV_BT_7680X4320P30 }
+};
+
+static inline struct xdprxss_state *
+to_xdprxssstate(struct v4l2_subdev *subdev)
+{
+	return container_of(subdev, struct xdprxss_state, subdev);
+}
+
+/* Register related operations */
+static inline u32 xdprxss_read(struct xdprxss_state *xdprxss, u32 addr)
+{
+	return ioread32(xdprxss->dp_base + addr);
+}
+
+static inline void xdprxss_write(struct xdprxss_state *xdprxss, u32 addr,
+				 u32 value)
+{
+	iowrite32(value, xdprxss->dp_base + addr);
+}
+
+static inline void xdprxss_clr(struct xdprxss_state *xdprxss, u32 addr,
+			       u32 clr)
+{
+	xdprxss_write(xdprxss, addr, xdprxss_read(xdprxss, addr) & ~clr);
+}
+
+static inline void xdprxss_set(struct xdprxss_state *xdprxss, u32 addr,
+			       u32 set)
+{
+	xdprxss_write(xdprxss, addr, xdprxss_read(xdprxss, addr) | set);
+}
+
+static inline void xdprxss_dpcd_update_start(struct xdprxss_state *xdprxss)
+{
+	iowrite32(0x1, xdprxss->dp_base + XDPRX_CTRL_DPCD_REG);
+}
+
+static inline void xdprxss_dpcd_update_end(struct xdprxss_state *xdprxss)
+{
+	iowrite32(0x0, xdprxss->dp_base + XDPRX_CTRL_DPCD_REG);
+}
+
+/**
+ * xdprxss_dpcd_update - Update the DPCD registers
+ * @xdprxss: pointer to driver state
+ * @addr: DPCD register address
+ * @val: Value to be override
+ * This function is used to override the DPCD registers set.
+ * DPCD register set is ranges from 0x084-0x0f0.
+ * Register 0x0B8(direct_dpcd_access) must be set to 1 to
+ * override DPCD values
+ */
+static inline void xdprxss_dpcd_update(struct xdprxss_state *xdprxss,
+				       u32 addr, u32 val)
+{
+	xdprxss_write(xdprxss, addr, val);
+}
+
+/**
+ * xdprxss_get_stream_properties - Get DP Rx stream properties
+ * @state: pointer to driver state
+ * This function decodes the stream to get stream properties
+ * like width, height, format, picture type (interlaced/progressive),etc.
+ *
+ * Return: 0 for success else errors
+ */
+static int xdprxss_get_stream_properties(struct xdprxss_state *state)
+{
+	struct v4l2_mbus_framefmt *format = &state->format;
+	struct v4l2_bt_timings *bt = &state->detected_timings.bt;
+
+	u32 rxmsa_mvid, rxmsa_nvid, rxmsa_misc, recv_clk_freq, linkrate;
+	u16 vres_total, hres_total, framerate, lanecount;
+	u8 pixel_width, fmt;
+	u16 read_val;
+
+	rxmsa_mvid = xdprxss_read(state, XDPRX_MSA_MVID_REG);
+	rxmsa_nvid = xdprxss_read(state, XDPRX_MSA_NVID_REG);
+
+	bt->width = xdprxss_read(state, XDPRX_MSA_HRES_REG);
+
+	bt->height = xdprxss_read(state, XDPRX_MSA_VHEIGHT_REG);
+	rxmsa_misc = xdprxss_read(state, XDPRX_MSA_MISC0_REG);
+
+	vres_total = xdprxss_read(state, XDPRX_MSA_VTOTAL_REG);
+	hres_total = xdprxss_read(state, XDPRX_MSA_HTOTAL_REG);
+	linkrate = xdprxss_read(state, XDPRX_LINK_BW_REG);
+	lanecount = xdprxss_read(state, XDPRX_LANE_COUNT_REG);
+
+	recv_clk_freq = (linkrate * 27 * rxmsa_mvid) / rxmsa_nvid;
+
+	if (recv_clk_freq > 540 && lanecount == 4)
+		pixel_width = 0x4;
+	else if (recv_clk_freq > 270 && (lanecount != 1))
+		pixel_width = 0x2;
+	else
+		pixel_width = 0x1;
+
+	framerate = (recv_clk_freq * MHZ) / (hres_total * vres_total);
+	framerate = roundup(framerate, 5);
+	xdprxss_write(state, XDPRX_LINERST_DIS_REG, 0x1);
+	/* set pixel mode as per lane count and reset the DTG */
+	read_val = xdprxss_read(state, XDPRX_DTG_REG);
+	xdprxss_write(state, XDPRX_DTG_REG, (read_val & XDPRX_DTG_DIS_MASK));
+	xdprxss_write(state, XDPRX_PIXEL_WIDTH_REG, pixel_width);
+	read_val = xdprxss_read(state, XDPRX_DTG_REG);
+	xdprxss_write(state, XDPRX_DTG_REG, (read_val | 0x1));
+	fmt = FIELD_GET(XDPRX_MSA_FMT_MASK, rxmsa_misc);
+	state->bpc = FIELD_GET(XDPRX_MSA_BPC_MASK, rxmsa_misc);
+
+	switch (fmt) {
+	case XDPRX_COLOR_FORMAT_422:
+		if (state->bpc == 10)
+			format->code = MEDIA_BUS_FMT_UYVY10_1X20;
+		else
+			format->code = MEDIA_BUS_FMT_UYVY8_1X16;
+		break;
+	case XDPRX_COLOR_FORMAT_444:
+		if (state->bpc == 10)
+			format->code = MEDIA_BUS_FMT_VUY10_1X30;
+		else
+			format->code = MEDIA_BUS_FMT_VUY8_1X24;
+		break;
+	case XDPRX_COLOR_FORMAT_RGB:
+		if (state->bpc == 10)
+			format->code = MEDIA_BUS_FMT_RBG101010_1X30;
+		else
+			format->code = MEDIA_BUS_FMT_RBG888_1X24;
+		break;
+	default:
+		dev_err(state->dev, "Unsupported color format\n");
+
+		return -EINVAL;
+	}
+
+	spin_lock(&state->lock);
+	format->width = bt->width;
+	format->height = bt->height;
+	format->colorspace = V4L2_COLORSPACE_REC709;
+	format->xfer_func = V4L2_XFER_FUNC_DEFAULT;
+	format->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+	format->quantization = V4L2_QUANTIZATION_DEFAULT;
+	format->field = V4L2_FIELD_NONE;
+	state->frame_interval = framerate;
+	spin_unlock(&state->lock);
+
+	dev_dbg(state->dev, "detected properties : width %d height %d\n",
+		bt->width, bt->height);
+
+	return 0;
+}
+
+static void xdprxss_set_training_params(struct xdprxss_state *xdprxss)
+{
+	unsigned int offset;
+
+	/*
+	 * This register is used to set a minimum value which which must be met
+	 * As per the Display Port protocol.The internal logic forces training
+	 * to fail until this value is met.Please refer to PG 300
+	 * https://www.xilinx.com/support/documentation/ip_documentation/dp_rx_subsystem/v2_1/pg233-displayport-rx-subsystem.pdf
+	 */
+	xdprxss_write(xdprxss, XDPRX_MINVOLT_SWING_REG, XDPRX_MIN_VS_MASK);
+	xdprxss_write(xdprxss, XDPRX_AUX_CLKDIV_REG,
+		      xdprxss_read(xdprxss, XDPRX_AUX_CLKDIV_REG) |
+		      FIELD_PREP(XDPRX_AUX_DEFER_MASK, XDPRX_AUX_DEFER_COUNT));
+
+	xdprxss_dpcd_update_start(xdprxss);
+	xdprxss_dpcd_update(xdprxss, XDPRX_TP_SET_REG,
+			    (XDPRX_AUX_RDINT_16MS << XDPRX_AUX_RDINT_SHIFT) |
+			    XDPRX_AUX_READINTRVL_REG);
+	xdprxss_dpcd_update_end(xdprxss);
+
+	xdprxss_clr(xdprxss, XDPRX_INTR_MASK_REG, XDPRX_INTR_ALL_MASK);
+
+	/* Load edid data to EDID memory block */
+	for (offset = 0; offset < XDPRX_EDID_LENGTH; offset = offset + 4) {
+		iowrite32((uint32_t)xilinx_edid[offset / 4],
+			  xdprxss->edid_base + offset);
+	}
+	xdprxss_write(xdprxss, XDPRX_LOCAL_EDID_REG, 0x1);
+
+	/* Disable all the interrupts */
+	xdprxss_set(xdprxss, XDPRX_INTR_MASK_REG, XDPRX_INTR_ALL_MASK);
+
+	/* Enable trainng related interrupts */
+	xdprxss_clr(xdprxss, XDPRX_INTR_MASK_REG, XDPRX_INTR_TRNG_MASK);
+	xdprxss_write(xdprxss, XDPRX_AUX_CLKDIV_REG,
+		      xdprxss_read(xdprxss, XDPRX_AUX_CLKDIV_REG) |
+		      FIELD_PREP(XDPRX_AUX_DEFER_MASK, XDPRX_AUX_DEFER_COUNT));
+	xdprxss_write(xdprxss, XDPRX_BSIDLE_TIME_REG, XDPRX_BSIDLE_TMOUT_VAL);
+	xdprxss_clr(xdprxss, XDPRX_CRC_CONFIG_REG, XDPRX_CRC_EN_MASK);
+	xdprxss_write(xdprxss, XDPRX_LINK_ENABLE_REG, 0x1);
+}
+
+static void xdprxss_core_init(struct xdprxss_state *xdprxss)
+{
+	unsigned long axi_clk;
+
+	u32 max_lanecount = xdprxss->max_lanecount;
+
+	xdprxss_dpcd_update_start(xdprxss);
+	xdprxss_dpcd_update(xdprxss,
+			    XDPRX_VRD_BWSET_REG, xdprxss->max_linkrate);
+	max_lanecount |= (XDPRX_EFRAME_CAP_MASK | XDPRX_LNCNT_TPS3_MASK);
+	xdprxss_dpcd_update(xdprxss, XDPRX_LANE_CNT_REG, max_lanecount);
+	xdprxss_dpcd_update_end(xdprxss);
+	xdprxss_write(xdprxss, XDPRX_LINK_ENABLE_REG, 0x0);
+	axi_clk = clk_get_rate(xdprxss->axi_clk);
+	xdprxss_write(xdprxss, XDPRX_AUX_CLKDIV_REG, axi_clk / MHZ);
+	/* Put both GT RX/TX and CPLL into reset */
+	xdprxss_write(xdprxss, XDPRX_PHY_REG, XDPRX_PHY_GTPLLRST_MASK |
+		      XDPRX_PHY_GTRXRST_MASK);
+	/* Release CPLL reset */
+	xdprxss_write(xdprxss, XDPRX_PHY_REG, XDPRX_PHY_GTRXRST_MASK);
+	/*
+	 * Remove the reset from the PHY and configure to issue reset after
+	 * every training iteration, link rate change, and start of training
+	 * pattern
+	 */
+	xdprxss_write(xdprxss, XDPRX_PHY_REG,
+		      XDPRX_PHYRST_ENBL_MASK |
+		      XDPRX_PHYRST_TRITER_MASK |
+		      XDPRX_PHYRST_RATECHANGE_MASK |
+		      XDPRX_PHYRST_TP1START_MASK);
+	xdprxss_write(xdprxss, XDPRX_MST_CAP_REG, 0x0);
+	xdprxss_write(xdprxss, XDPRX_SINK_COUNT_REG, 1);
+	xdprxss_set_training_params(xdprxss);
+}
+
+static void xdprxss_irq_unplug(struct xdprxss_state *state)
+{
+	dev_dbg(state->dev, "Asserted cable unplug interrupt\n");
+
+	xdprxss_set(state, XDPRX_SOFT_RST_REG, XDPRX_SOFT_VIDRST_MASK);
+	xdprxss_clr(state, XDPRX_SOFT_RST_REG, XDPRX_SOFT_VIDRST_MASK);
+
+	xdprxss_set(state, XDPRX_INTR_MASK_REG, XDPRX_INTR_ALL_MASK);
+	xdprxss_clr(state, XDPRX_INTR_MASK_REG, XDPRX_INTR_TRNG_MASK);
+	/*
+	 * In a scenario, where the cable is plugged-in but the training
+	 * is lost, the software is expected to assert a HPD upon the
+	 * occurrence of a TRAINING_LOST interrupt, so that the Source
+	 * can retrain the link.
+	 */
+	xdprxss_write(state, XDPRX_HPD_INTR_REG,
+		      FIELD_PREP(XDPRX_HPD_PULSE_MASK, XDPRX_HPD_PLUSE_5000) |
+		      XDPRX_HPD_INTR_MASK);
+}
+
+static void xdprxss_irq_tp1(struct xdprxss_state *state)
+{
+	union phy_configure_opts phy_opts = { 0 };
+	struct phy_configure_opts_dp *phy_cfg = &phy_opts.dp;
+	u32 linkrate;
+	unsigned int i;
+
+	dev_dbg(state->dev, "Asserted traning pattern 1\n");
+
+	linkrate = xdprxss_read(state, XDPRX_LINK_BW_REG);
+
+	switch (linkrate) {
+	case DP_LINK_BW_1_62:
+	case DP_LINK_BW_2_7:
+	case DP_LINK_BW_5_4:
+	case DP_LINK_BW_8_1:
+		phy_cfg->link_rate = linkrate * 270;
+		break;
+	default:
+		dev_err(state->dev, "invalid link rate\n");
+		break;
+	}
+	phy_cfg->set_rate = 1;
+	for (i = 0; i < state->max_lanecount; i++)
+		phy_configure(state->phy[i], &phy_opts);
+
+	/* Initialize phy logic of DP-RX core */
+	xdprxss_write(state, XDPRX_PHY_REG, XDPRX_PHY_INIT_MASK);
+	phy_reset(state->phy[0]);
+	xdprxss_clr(state, XDPRX_INTR_MASK_REG, XDPRX_INTR_ALL_MASK);
+}
+
+static void xdprxss_training_failure(struct xdprxss_state *state)
+{
+	dev_dbg(state->dev, "Traning Lost !!\n");
+	state->valid_stream = false;
+
+	xdprxss_write(state, XDPRX_HPD_INTR_REG,
+		      FIELD_PREP(XDPRX_HPD_PULSE_MASK, XDPRX_HPD_PLUSE_750) |
+		      XDPRX_HPD_INTR_MASK);
+
+	/* reset the aux logic */
+	xdprxss_set(state, XDPRX_SOFT_RST_REG, XDPRX_SOFT_AUXRST_MASK);
+	xdprxss_clr(state, XDPRX_SOFT_RST_REG, XDPRX_SOFT_AUXRST_MASK);
+}
+
+static void xdprxss_irq_no_video(struct xdprxss_state *state)
+{
+	dev_dbg(state->dev, "No Valid video received !!\n");
+
+	xdprxss_write(state, XDPRX_VIDEO_UNSUPPORTED_REG, 0x1);
+	xdprxss_clr(state, XDPRX_INTR_MASK_REG, XDPRX_INTR_VBLANK_MASK);
+	xdprxss_set(state, XDPRX_INTR_MASK_REG, XDPRX_INTR_NOVID_MASK);
+	/* reset the dtg core */
+	xdprxss_set(state, XDPRX_DTG_REG, 0x0);
+	xdprxss_set(state, XDPRX_DTG_REG, 0x1);
+
+	/* reset the video logic */
+	xdprxss_set(state, XDPRX_SOFT_RST_REG, XDPRX_SOFT_VIDRST_MASK);
+	xdprxss_clr(state, XDPRX_SOFT_RST_REG, XDPRX_SOFT_VIDRST_MASK);
+
+	/* notify source change event */
+	memset(&state->event, 0, sizeof(state->event));
+	state->event.type = V4L2_EVENT_SOURCE_CHANGE;
+	state->event.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION;
+	v4l2_subdev_notify_event(&state->subdev, &state->event);
+	state->valid_stream = false;
+}
+
+static void xdprxss_irq_valid_video(struct xdprxss_state *state)
+{
+	dev_dbg(state->dev, "Valid Video received !!\n");
+	xdprxss_write(state, XDPRX_VIDEO_UNSUPPORTED_REG, 0x0);
+
+	if (!xdprxss_get_stream_properties(state)) {
+		memset(&state->event, 0, sizeof(state->event));
+		state->event.type = V4L2_EVENT_SOURCE_CHANGE;
+		state->event.u.src_change.changes =
+				V4L2_EVENT_SRC_CH_RESOLUTION;
+		v4l2_subdev_notify_event(&state->subdev, &state->event);
+		state->valid_stream = true;
+	} else {
+		dev_err(state->dev, "Unable to get stream properties!\n");
+		state->valid_stream = false;
+	}
+}
+
+static irqreturn_t xdprxss_irq_handler(int irq, void *dev_id)
+{
+	struct xdprxss_state *state = (struct xdprxss_state *)dev_id;
+	u32 status;
+
+	status = xdprxss_read(state, XDPRX_INTR_CAUSE_REG);
+	status &= ~xdprxss_read(state, XDPRX_INTR_MASK_REG);
+
+	if (!status)
+		return IRQ_NONE;
+
+	if (status & XDPRX_INTR_UNPLUG_MASK)
+		xdprxss_irq_unplug(state);
+	if (status & XDPRX_INTR_TP1_MASK)
+		xdprxss_irq_tp1(state);
+	if (status & XDPRX_INTR_TRLOST_MASK)
+		xdprxss_training_failure(state);
+	if (status & XDPRX_INTR_NOVID_MASK)
+		xdprxss_irq_no_video(state);
+	if (status & XDPRX_INTR_VID_MASK)
+		xdprxss_irq_valid_video(state);
+#ifdef DEBUG
+	if (status & XDPRX_INTR_TRDONE_MASK)
+		dev_dbg(state->dev, "DP Link training is done !!\n");
+#endif
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * xdprxss_subscribe_event - Subscribe to video source change event
+ * @sd: V4L2 Sub device
+ * @fh: V4L2 File Handle
+ * @sub: Subcribe event structure
+ *
+ * Return: 0 on success, errors otherwise
+ */
+static int xdprxss_subscribe_event(struct v4l2_subdev *sd,
+				   struct v4l2_fh *fh,
+				   struct v4l2_event_subscription *sub)
+{
+	int ret;
+	struct xdprxss_state *xdprxss = to_xdprxssstate(sd);
+
+	dev_dbg(xdprxss->dev, "Event subscribed : 0x%08x\n", sub->type);
+
+	switch (sub->type) {
+	case V4L2_EVENT_SOURCE_CHANGE:
+		ret = v4l2_src_change_event_subscribe(fh, sub);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int xdprxss_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct xdprxss_state *xdprxss = to_xdprxssstate(sd);
+
+	/* DP does not need to be enabled when we start streaming */
+	if (enable == xdprxss->streaming)
+		return 0;
+
+	if (enable && !xdprxss->valid_stream)
+		return -EINVAL;
+
+	xdprxss->streaming = enable;
+
+	return 0;
+}
+
+/**
+ * xdprxss_g_input_status - It is used to determine if the video signal
+ * is present / locked onto or not.
+ *
+ * @sd: V4L2 Sub device
+ * @status: status of signal locked
+ *
+ * This is used to determine if the valid video signal is present and
+ * locked onto by the DP Rx xdprxss or not .
+ *
+ * Return: zero on success
+ */
+static int xdprxss_g_input_status(struct v4l2_subdev *sd, u32 *status)
+{
+	struct xdprxss_state *xdprxss = to_xdprxssstate(sd);
+
+	if (!xdprxss->valid_stream)
+		*status = V4L2_IN_ST_NO_SYNC | V4L2_IN_ST_NO_SIGNAL;
+	else
+		*status = 0;
+
+	return 0;
+}
+
+static struct v4l2_mbus_framefmt *
+__xdprxss_get_pad_format(struct xdprxss_state *xdprxss,
+			 struct v4l2_subdev_pad_config *cfg,
+			 unsigned int pad, u32 which)
+{
+	struct v4l2_mbus_framefmt *format;
+
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		format = v4l2_subdev_get_try_format(&xdprxss->subdev, cfg, pad);
+		break;
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		format = &xdprxss->format;
+		break;
+	default:
+		format = NULL;
+		break;
+	}
+
+	return format;
+}
+
+/**
+ * xdprxss_init_cfg - Initialise the pad format config to default
+ * @sd: Pointer to V4L2 Sub device structure
+ * @cfg: Pointer to sub device pad information structure
+ *
+ * This function is used to initialize the pad format with the default
+ * values.
+ *
+ * Return: 0 on success
+ */
+static int xdprxss_init_cfg(struct v4l2_subdev *sd,
+			    struct v4l2_subdev_pad_config *cfg)
+{
+	struct xdprxss_state *xdprxss = to_xdprxssstate(sd);
+	struct v4l2_mbus_framefmt *format;
+
+	format = v4l2_subdev_get_try_format(sd, cfg, 0);
+
+	if (!xdprxss->valid_stream)
+		*format = xdprxss->format;
+
+	return 0;
+}
+
+/**
+ * xdprxss_getset_format - This is used to set and get the pad format
+ * @sd: Pointer to V4L2 Sub device structure
+ * @cfg: Pointer to sub device pad information structure
+ * @fmt: Pointer to pad level media bus format
+ *
+ * This function is used to set the pad format.
+ * Since the pad format is fixed in hardware, it can't be
+ * modified on run time.
+ *
+ * Return: 0 on success
+ */
+static int xdprxss_getset_format(struct v4l2_subdev *sd,
+				 struct v4l2_subdev_pad_config *cfg,
+				 struct v4l2_subdev_format *fmt)
+{
+	struct xdprxss_state *xdprxss = to_xdprxssstate(sd);
+	struct v4l2_mbus_framefmt *format;
+
+	if (!xdprxss->valid_stream) {
+		dev_err(xdprxss->dev, "Video not locked!\n");
+		return -EINVAL;
+	}
+
+	dev_dbg(xdprxss->dev,
+		"set width %d height %d code %d field %d colorspace %d\n",
+		fmt->format.width, fmt->format.height,
+		fmt->format.code, fmt->format.field,
+		fmt->format.colorspace);
+	format = __xdprxss_get_pad_format(xdprxss, cfg,
+					  fmt->pad, fmt->which);
+	if (!format)
+		return -EINVAL;
+
+	fmt->format = *format;
+
+	return 0;
+}
+
+/**
+ * xdprxss_enum_mbus_code - Handle pixel format enumeration
+ * @sd: pointer to v4l2 subdev structure
+ * @cfg: V4L2 subdev pad configuration
+ * @code: pointer to v4l2_subdev_mbus_code_enum structure
+ *
+ * Return: -EINVAL or zero on success
+ */
+static int xdprxss_enum_mbus_code(struct v4l2_subdev *sd,
+				  struct v4l2_subdev_pad_config *cfg,
+				  struct v4l2_subdev_mbus_code_enum *code)
+{
+	struct xdprxss_state *xdprxss = to_xdprxssstate(sd);
+	u32 index = code->index;
+	u32 base = 0;
+
+	if (xdprxss->bpc == 8)
+		base = 0;
+
+	if (xdprxss->bpc == 10)
+		base = 3;
+
+	if (code->pad || index >= 3)
+		return -EINVAL;
+
+	code->code = xdprxss_supported_mbus_fmts[base + index];
+
+	return 0;
+}
+
+/**
+ * xdprxss_enum_dv_timings - Enumerate all the supported DV timings
+ * @sd: pointer to v4l2 subdev structure
+ * @timings: DV timings structure to be returned.
+ *
+ * Return: -EINVAL incase of invalid index and pad or zero on success
+ */
+static int xdprxss_enum_dv_timings(struct v4l2_subdev *sd,
+				   struct v4l2_enum_dv_timings *timings)
+{
+	if (timings->index >= ARRAY_SIZE(fmt_cap))
+		return -EINVAL;
+
+	if (timings->pad != 0)
+		return -EINVAL;
+
+	timings->timings = fmt_cap[timings->index];
+
+	return 0;
+}
+
+/**
+ * xdprxss_get_dv_timings_cap - This is used to set the dv timing
+ * capabilities
+ * @subdev: Pointer to V4L2 Sub device structure
+ * @cap: Pointer to dv timing capability structure
+ *
+ * Return: -EINVAL incase of invalid pad or zero on success
+ */
+static int xdprxss_get_dv_timings_cap(struct v4l2_subdev *subdev,
+				      struct v4l2_dv_timings_cap *cap)
+{
+	struct v4l2_dv_timings_cap xdprxss_dv_timings_cap = {
+		.type = V4L2_DV_BT_656_1120,
+		.reserved = { 0 },
+		V4L2_INIT_BT_TIMINGS
+		(800, 7680,
+		600, 4320,
+		25000000, 297000000,
+		V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
+		V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT,
+		V4L2_DV_BT_CAP_INTERLACED | V4L2_DV_BT_CAP_PROGRESSIVE |
+		V4L2_DV_BT_CAP_REDUCED_BLANKING |
+		V4L2_DV_BT_CAP_CUSTOM
+		)
+	};
+
+	if (cap->pad != 0)
+		return -EINVAL;
+
+	*cap = xdprxss_dv_timings_cap;
+
+	return 0;
+}
+
+static int xdprxss_query_dv_timings(struct v4l2_subdev *sd,
+				    struct v4l2_dv_timings *timings)
+{
+	struct xdprxss_state *state = to_xdprxssstate(sd);
+	unsigned int i;
+
+	if (!timings)
+		return -EINVAL;
+
+	if (!state->valid_stream)
+		return -ENOLCK;
+	for (i = 0; i < ARRAY_SIZE(xdprxss_dv_timings); i++) {
+		if (state->format.width == xdprxss_dv_timings[i].width &&
+		    state->format.height == xdprxss_dv_timings[i].height &&
+		    state->frame_interval == xdprxss_dv_timings[i].fps) {
+			*timings = xdprxss_dv_timings[i].timing;
+			return 0;
+		}
+	}
+
+	return -ERANGE;
+}
+
+/* ------------------------------------------------------------
+ * Media Operations
+ */
+
+static const struct media_entity_operations xdprxss_media_ops = {
+	.link_validate = v4l2_subdev_link_validate
+};
+
+static const struct v4l2_subdev_core_ops xdprxss_core_ops = {
+	.subscribe_event	= xdprxss_subscribe_event,
+	.unsubscribe_event	= v4l2_event_subdev_unsubscribe,
+};
+
+static const struct v4l2_subdev_video_ops xdprxss_video_ops = {
+	.query_dv_timings	= xdprxss_query_dv_timings,
+	.s_stream		= xdprxss_s_stream,
+	.g_input_status		= xdprxss_g_input_status,
+};
+
+static const struct v4l2_subdev_pad_ops xdprxss_pad_ops = {
+	.init_cfg		= xdprxss_init_cfg,
+	.enum_mbus_code		= xdprxss_enum_mbus_code,
+	.get_fmt		= xdprxss_getset_format,
+	.set_fmt		= xdprxss_getset_format,
+	.enum_dv_timings	= xdprxss_enum_dv_timings,
+	.dv_timings_cap         = xdprxss_get_dv_timings_cap,
+};
+
+static const struct v4l2_subdev_ops xdprxss_ops = {
+	.core	= &xdprxss_core_ops,
+	.video	= &xdprxss_video_ops,
+	.pad	= &xdprxss_pad_ops
+};
+
+/* ----------------------------------------------------------------
+ * Platform Device Driver
+ */
+static int xdprxss_parse_of(struct xdprxss_state *xdprxss)
+{
+	struct device_node *node = xdprxss->dev->of_node;
+	u32 val = 0;
+	int ret;
+
+	ret = of_property_read_u32(node, "xlnx,bpc", &xdprxss->bpc);
+	if (ret < 0) {
+		if (ret != -EINVAL) {
+			dev_err(xdprxss->dev, "failed to get xlnx,bpp\n");
+			return ret;
+		}
+	}
+	/*
+	 * TODO : For now driver supports only 8, 10 bpc.
+	 * In future, driver may add with other bpc support
+	 */
+	if (xdprxss->bpc != 8 && xdprxss->bpc != 10) {
+		dev_err(xdprxss->dev, "unsupported bpc = %u\n", xdprxss->bpc);
+		return -EINVAL;
+	}
+
+	xdprxss->hdcp_enable = of_property_read_bool(node, "xlnx,hdcp-enable");
+	/* TODO : This driver does not support HDCP feature */
+	if (xdprxss->hdcp_enable) {
+		dev_err(xdprxss->dev, "hdcp unsupported\n");
+		return -EINVAL;
+	}
+
+	xdprxss->audio_enable = of_property_read_bool(node,
+						      "xlnx,audio-enable");
+	/* TODO : This driver does not support audio */
+	if (xdprxss->audio_enable) {
+		dev_err(xdprxss->dev, "audio unsupported\n");
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32(node, "xlnx,link-rate", &val);
+	if (ret < 0) {
+		dev_err(xdprxss->dev, "xlnx,link-rate property not found\n");
+		return ret;
+	}
+	if (!(val == DP_LINK_BW_1_62 ||
+	      val == DP_LINK_BW_2_7 ||
+	      val == DP_LINK_BW_5_4 ||
+	      val == DP_LINK_BW_8_1)) {
+		dev_err(xdprxss->dev, "invalid link rate\n");
+		return -EINVAL;
+	}
+	xdprxss->max_linkrate = val;
+
+	ret = of_property_read_u32(node, "xlnx,lane-count", &val);
+	if (ret < 0) {
+		dev_err(xdprxss->dev, "xlnx,lane-count property not found\n");
+		return ret;
+	}
+	if (val < 1 && val > 4) {
+		dev_err(xdprxss->dev, "invalid lane count\n");
+		return -EINVAL;
+	}
+	xdprxss->max_lanecount = val;
+
+	ret = of_property_read_u32(node, "xlnx,mode", &val);
+	if (ret < 0) {
+		dev_err(xdprxss->dev, "xlnx,mode property not found\n");
+		return ret;
+	}
+	if (val > 0) {
+		dev_err(xdprxss->dev, "driver does't support MST mode\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int xdprxss_probe(struct platform_device *pdev)
+{
+	struct v4l2_subdev *subdev;
+	struct xdprxss_state *xdprxss;
+	struct device_node *node;
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	int ret, irq;
+	unsigned int i = 0, j;
+
+	xdprxss = devm_kzalloc(dev, sizeof(*xdprxss), GFP_KERNEL);
+	if (!xdprxss)
+		return -ENOMEM;
+
+	xdprxss->dev = &pdev->dev;
+	node = xdprxss->dev->of_node;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dp_base");
+	xdprxss->dp_base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(xdprxss->dp_base)) {
+		dev_err(dev, "couldn't map DisplayPort registers\n");
+		return -ENODEV;
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "edid_base");
+	xdprxss->edid_base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(xdprxss->edid_base)) {
+		dev_err(dev, "Couldn't map EDID IP memory\n");
+		return -ENOENT;
+	}
+
+	xdprxss->axi_clk = devm_clk_get(dev, "s_axi_aclk");
+	if (IS_ERR(xdprxss->axi_clk)) {
+		ret = PTR_ERR(xdprxss->axi_clk);
+		dev_err(&pdev->dev, "failed to get s_axi_clk (%d)\n", ret);
+		return ret;
+	}
+
+	xdprxss->rx_lnk_clk = devm_clk_get(dev, "rx_lnk_clk");
+	if (IS_ERR(xdprxss->rx_lnk_clk)) {
+		ret = PTR_ERR(xdprxss->rx_lnk_clk);
+		dev_err(&pdev->dev, "failed to get rx_lnk_clk (%d)\n", ret);
+		return ret;
+	}
+
+	xdprxss->rx_vid_clk = devm_clk_get(dev, "rx_vid_clk");
+	if (IS_ERR(xdprxss->rx_vid_clk)) {
+		ret = PTR_ERR(xdprxss->rx_vid_clk);
+		dev_err(&pdev->dev, "failed to get rx_vid_clk (%d)\n", ret);
+		return ret;
+	}
+
+	ret = xdprxss_parse_of(xdprxss);
+	if (ret < 0)
+		goto clk_err;
+
+	/* acquire vphy lanes */
+	for (i = 0; i < xdprxss->max_lanecount; i++) {
+		char phy_name[16];
+
+		snprintf(phy_name, sizeof(phy_name), "dp-phy%d", i);
+		xdprxss->phy[i] = devm_phy_get(xdprxss->dev, phy_name);
+		if (IS_ERR(xdprxss->phy[i])) {
+			ret = PTR_ERR(xdprxss->phy[i]);
+			xdprxss->phy[i] = NULL;
+			if (ret == -EPROBE_DEFER)
+				dev_info(dev, "phy not ready -EPROBE_DEFER\n");
+			if (ret != -EPROBE_DEFER)
+				dev_err(dev,
+					"failed to get phy lane %s i %d\n",
+					phy_name, i);
+			goto error_phy;
+		}
+		ret = phy_init(xdprxss->phy[i]);
+		if (ret) {
+			dev_err(dev,
+				"failed to init phy lane %d\n", i);
+			goto error_phy;
+		}
+	}
+
+	ret = clk_prepare_enable(xdprxss->axi_clk);
+	if (ret) {
+		dev_err(dev, "failed to enable axi_clk (%d)\n", ret);
+		goto error_phy;
+	}
+
+	ret = clk_prepare_enable(xdprxss->rx_lnk_clk);
+	if (ret) {
+		dev_err(dev, "failed to enable rx_lnk_clk (%d)\n", ret);
+		goto rx_lnk_clk_err;
+	}
+
+	ret = clk_prepare_enable(xdprxss->rx_vid_clk);
+	if (ret) {
+		dev_err(dev, "failed to enable rx_vid_clk (%d)\n", ret);
+		goto rx_vid_clk_err;
+	}
+
+	spin_lock_init(&xdprxss->lock);
+
+	/* Initialize the DP core */
+	xdprxss_core_init(xdprxss);
+
+	/* Initialize V4L2 subdevice and media entity */
+	xdprxss->pad.flags = MEDIA_PAD_FL_SOURCE;
+
+	/* Initialize V4L2 subdevice and media entity */
+	subdev = &xdprxss->subdev;
+	v4l2_subdev_init(subdev, &xdprxss_ops);
+	subdev->dev = &pdev->dev;
+	strscpy(subdev->name, dev_name(&pdev->dev), sizeof(subdev->name));
+
+	subdev->flags = V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	subdev->entity.ops = &xdprxss_media_ops;
+
+	v4l2_set_subdevdata(subdev, xdprxss);
+	ret = media_entity_pads_init(&subdev->entity, 1, &xdprxss->pad);
+	if (ret < 0)
+		goto error;
+
+	/* Register interrupt handler */
+	irq = irq_of_parse_and_map(node, 0);
+	ret = devm_request_irq(xdprxss->dev, irq, xdprxss_irq_handler,
+			       IRQF_SHARED, subdev->name, xdprxss);
+	if (ret) {
+		dev_err(dev, "Err = %d Interrupt handler reg failed!\n",
+			ret);
+		goto error;
+	}
+
+	platform_set_drvdata(pdev, xdprxss);
+
+	ret = v4l2_async_register_subdev(subdev);
+	if (ret < 0) {
+		dev_err(dev, "failed to register subdev\n");
+		goto error;
+	}
+
+	return 0;
+
+error:
+	media_entity_cleanup(&subdev->entity);
+clk_err:
+	clk_disable_unprepare(xdprxss->rx_vid_clk);
+rx_vid_clk_err:
+	clk_disable_unprepare(xdprxss->rx_lnk_clk);
+rx_lnk_clk_err:
+	clk_disable_unprepare(xdprxss->axi_clk);
+error_phy:
+	dev_dbg(dev, " %s error_phy:\n", __func__);
+	/* release the lanes that we did get, if we did not get all lanes */
+	for (j = 0; j < i; j++) {
+		if (xdprxss->phy[j]) {
+			dev_dbg(dev,
+				"phy_exit() xdprxss->phy[%d] = %p\n",
+				j, xdprxss->phy[j]);
+			phy_exit(xdprxss->phy[j]);
+			xdprxss->phy[j] = NULL;
+		}
+	}
+
+	return ret;
+}
+
+static int xdprxss_remove(struct platform_device *pdev)
+{
+	struct xdprxss_state *xdprxss = platform_get_drvdata(pdev);
+	struct v4l2_subdev *subdev = &xdprxss->subdev;
+	unsigned int i;
+
+	v4l2_async_unregister_subdev(subdev);
+	media_entity_cleanup(&subdev->entity);
+	clk_disable_unprepare(xdprxss->rx_vid_clk);
+	clk_disable_unprepare(xdprxss->rx_lnk_clk);
+	clk_disable_unprepare(xdprxss->axi_clk);
+	for (i = 0; i < XDPRX_MAX_LANE_COUNT; i++) {
+		phy_exit(xdprxss->phy[i]);
+		xdprxss->phy[i] = NULL;
+	}
+	return 0;
+}
+
+static const struct of_device_id xdprxss_of_id_table[] = {
+	{ .compatible = "xlnx,v-dp-rxss-3.0", },
+	{ /* end of table */ }
+};
+MODULE_DEVICE_TABLE(of, xdprxss_of_id_table);
+
+static struct platform_driver xdprxss_driver = {
+	.driver = {
+		.name		= "xilinx-dprxss",
+		.of_match_table	= xdprxss_of_id_table,
+	},
+	.probe			= xdprxss_probe,
+	.remove			= xdprxss_remove,
+};
+
+module_platform_driver(xdprxss_driver);
+
+MODULE_AUTHOR("Rajesh Gugulothu <gugulothu.rajesh@xilinx.com");
+MODULE_DESCRIPTION("Xilinx DP Rx Subsystem Driver");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/xilinx-gamma-coeff.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/xilinx-gamma-coeff.h
@@ -0,0 +1,5385 @@
+/*
+ * Xilinx Gamma Correction IP
+ *
+ * Copyright (C) 2017 Xilinx, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __XILINX_GAMMA_COEFF_H__
+#define __XILINX_GAMMA_COEFF_H__
+
+#define GAMMA_CURVE_LENGTH	(40)
+
+#define GAMMA_BPC_8			(8)
+#define GAMMA8_TABLE_LENGTH		BIT(GAMMA_BPC_8)
+static const u16 xgamma8_01[GAMMA8_TABLE_LENGTH] = {
+	0, 147, 157, 164, 168, 172, 175, 178,
+	180, 183, 184, 186, 188, 189, 191, 192,
+	193, 195, 196, 197, 198, 199, 200, 200,
+	201, 202, 203, 204, 204, 205, 206, 207,
+	207, 208, 208, 209, 210, 210, 211, 211,
+	212, 212, 213, 213, 214, 214, 215, 215,
+	216, 216, 217, 217, 218, 218, 218, 219,
+	219, 220, 220, 220, 221, 221, 221, 222,
+	222, 222, 223, 223, 223, 224, 224, 224,
+	225, 225, 225, 226, 226, 226, 227, 227,
+	227, 227, 228, 228, 228, 228, 229, 229,
+	229, 230, 230, 230, 230, 231, 231, 231,
+	231, 232, 232, 232, 232, 232, 233, 233,
+	233, 233, 234, 234, 234, 234, 234, 235,
+	235, 235, 235, 235, 236, 236, 236, 236,
+	236, 237, 237, 237, 237, 237, 238, 238,
+	238, 238, 238, 239, 239, 239, 239, 239,
+	239, 240, 240, 240, 240, 240, 240, 241,
+	241, 241, 241, 241, 241, 242, 242, 242,
+	242, 242, 242, 243, 243, 243, 243, 243,
+	243, 244, 244, 244, 244, 244, 244, 244,
+	245, 245, 245, 245, 245, 245, 245, 246,
+	246, 246, 246, 246, 246, 246, 247, 247,
+	247, 247, 247, 247, 247, 247, 248, 248,
+	248, 248, 248, 248, 248, 249, 249, 249,
+	249, 249, 249, 249, 249, 249, 250, 250,
+	250, 250, 250, 250, 250, 250, 251, 251,
+	251, 251, 251, 251, 251, 251, 251, 252,
+	252, 252, 252, 252, 252, 252, 252, 252,
+	253, 253, 253, 253, 253, 253, 253, 253,
+	253, 254, 254, 254, 254, 254, 254, 254,
+	254, 254, 254, 255, 255, 255, 255, 255,
+};
+
+static const u16 xgamma8_02[GAMMA8_TABLE_LENGTH] = {
+	0, 84, 97, 105, 111, 116, 120, 124,
+	128, 131, 133, 136, 138, 141, 143, 145,
+	147, 148, 150, 152, 153, 155, 156, 158,
+	159, 160, 162, 163, 164, 165, 166, 167,
+	168, 169, 170, 171, 172, 173, 174, 175,
+	176, 177, 178, 179, 179, 180, 181, 182,
+	183, 183, 184, 185, 186, 186, 187, 188,
+	188, 189, 190, 190, 191, 192, 192, 193,
+	193, 194, 195, 195, 196, 196, 197, 197,
+	198, 199, 199, 200, 200, 201, 201, 202,
+	202, 203, 203, 204, 204, 205, 205, 206,
+	206, 207, 207, 208, 208, 208, 209, 209,
+	210, 210, 211, 211, 211, 212, 212, 213,
+	213, 214, 214, 214, 215, 215, 216, 216,
+	216, 217, 217, 217, 218, 218, 219, 219,
+	219, 220, 220, 220, 221, 221, 221, 222,
+	222, 223, 223, 223, 224, 224, 224, 225,
+	225, 225, 226, 226, 226, 227, 227, 227,
+	227, 228, 228, 228, 229, 229, 229, 230,
+	230, 230, 231, 231, 231, 231, 232, 232,
+	232, 233, 233, 233, 233, 234, 234, 234,
+	235, 235, 235, 235, 236, 236, 236, 237,
+	237, 237, 237, 238, 238, 238, 238, 239,
+	239, 239, 239, 240, 240, 240, 240, 241,
+	241, 241, 241, 242, 242, 242, 242, 243,
+	243, 243, 243, 244, 244, 244, 244, 245,
+	245, 245, 245, 246, 246, 246, 246, 246,
+	247, 247, 247, 247, 248, 248, 248, 248,
+	248, 249, 249, 249, 249, 250, 250, 250,
+	250, 250, 251, 251, 251, 251, 252, 252,
+	252, 252, 252, 253, 253, 253, 253, 253,
+	254, 254, 254, 254, 254, 255, 255, 255,
+};
+
+static const u16 xgamma8_03[GAMMA8_TABLE_LENGTH] = {
+	0, 48, 60, 67, 73, 78, 83, 87,
+	90, 94, 97, 99, 102, 104, 107, 109,
+	111, 113, 115, 117, 119, 121, 122, 124,
+	125, 127, 129, 130, 131, 133, 134, 136,
+	137, 138, 139, 141, 142, 143, 144, 145,
+	146, 147, 148, 149, 151, 152, 153, 154,
+	155, 155, 156, 157, 158, 159, 160, 161,
+	162, 163, 164, 164, 165, 166, 167, 168,
+	168, 169, 170, 171, 172, 172, 173, 174,
+	174, 175, 176, 177, 177, 178, 179, 179,
+	180, 181, 181, 182, 183, 183, 184, 185,
+	185, 186, 187, 187, 188, 188, 189, 190,
+	190, 191, 191, 192, 193, 193, 194, 194,
+	195, 195, 196, 197, 197, 198, 198, 199,
+	199, 200, 200, 201, 201, 202, 202, 203,
+	203, 204, 204, 205, 205, 206, 206, 207,
+	207, 208, 208, 209, 209, 210, 210, 211,
+	211, 212, 212, 213, 213, 213, 214, 214,
+	215, 215, 216, 216, 217, 217, 217, 218,
+	218, 219, 219, 220, 220, 220, 221, 221,
+	222, 222, 223, 223, 223, 224, 224, 225,
+	225, 225, 226, 226, 227, 227, 227, 228,
+	228, 229, 229, 229, 230, 230, 230, 231,
+	231, 232, 232, 232, 233, 233, 233, 234,
+	234, 235, 235, 235, 236, 236, 236, 237,
+	237, 237, 238, 238, 238, 239, 239, 240,
+	240, 240, 241, 241, 241, 242, 242, 242,
+	243, 243, 243, 244, 244, 244, 245, 245,
+	245, 246, 246, 246, 247, 247, 247, 248,
+	248, 248, 249, 249, 249, 249, 250, 250,
+	250, 251, 251, 251, 252, 252, 252, 253,
+	253, 253, 253, 254, 254, 254, 255, 255,
+};
+
+static const u16 xgamma8_04[GAMMA8_TABLE_LENGTH] = {
+	0, 28, 37, 43, 48, 53, 57, 61,
+	64, 67, 70, 73, 75, 78, 80, 82,
+	84, 86, 88, 90, 92, 94, 96, 97,
+	99, 101, 102, 104, 105, 107, 108, 110,
+	111, 113, 114, 115, 117, 118, 119, 120,
+	122, 123, 124, 125, 126, 127, 129, 130,
+	131, 132, 133, 134, 135, 136, 137, 138,
+	139, 140, 141, 142, 143, 144, 145, 146,
+	147, 148, 149, 149, 150, 151, 152, 153,
+	154, 155, 155, 156, 157, 158, 159, 160,
+	160, 161, 162, 163, 164, 164, 165, 166,
+	167, 167, 168, 169, 170, 170, 171, 172,
+	173, 173, 174, 175, 175, 176, 177, 177,
+	178, 179, 179, 180, 181, 182, 182, 183,
+	183, 184, 185, 185, 186, 187, 187, 188,
+	189, 189, 190, 190, 191, 192, 192, 193,
+	194, 194, 195, 195, 196, 197, 197, 198,
+	198, 199, 199, 200, 201, 201, 202, 202,
+	203, 203, 204, 205, 205, 206, 206, 207,
+	207, 208, 208, 209, 209, 210, 211, 211,
+	212, 212, 213, 213, 214, 214, 215, 215,
+	216, 216, 217, 217, 218, 218, 219, 219,
+	220, 220, 221, 221, 222, 222, 223, 223,
+	224, 224, 225, 225, 226, 226, 227, 227,
+	228, 228, 229, 229, 230, 230, 230, 231,
+	231, 232, 232, 233, 233, 234, 234, 235,
+	235, 235, 236, 236, 237, 237, 238, 238,
+	239, 239, 240, 240, 240, 241, 241, 242,
+	242, 243, 243, 243, 244, 244, 245, 245,
+	246, 246, 246, 247, 247, 248, 248, 248,
+	249, 249, 250, 250, 251, 251, 251, 252,
+	252, 253, 253, 253, 254, 254, 255, 255,
+};
+
+static const u16 xgamma8_05[GAMMA8_TABLE_LENGTH] = {
+	0, 16, 23, 28, 32, 36, 39, 42,
+	45, 48, 50, 53, 55, 58, 60, 62,
+	64, 66, 68, 70, 71, 73, 75, 77,
+	78, 80, 81, 83, 84, 86, 87, 89,
+	90, 92, 93, 94, 96, 97, 98, 100,
+	101, 102, 103, 105, 106, 107, 108, 109,
+	111, 112, 113, 114, 115, 116, 117, 118,
+	119, 121, 122, 123, 124, 125, 126, 127,
+	128, 129, 130, 131, 132, 133, 134, 135,
+	135, 136, 137, 138, 139, 140, 141, 142,
+	143, 144, 145, 145, 146, 147, 148, 149,
+	150, 151, 151, 152, 153, 154, 155, 156,
+	156, 157, 158, 159, 160, 160, 161, 162,
+	163, 164, 164, 165, 166, 167, 167, 168,
+	169, 170, 170, 171, 172, 173, 173, 174,
+	175, 176, 176, 177, 178, 179, 179, 180,
+	181, 181, 182, 183, 183, 184, 185, 186,
+	186, 187, 188, 188, 189, 190, 190, 191,
+	192, 192, 193, 194, 194, 195, 196, 196,
+	197, 198, 198, 199, 199, 200, 201, 201,
+	202, 203, 203, 204, 204, 205, 206, 206,
+	207, 208, 208, 209, 209, 210, 211, 211,
+	212, 212, 213, 214, 214, 215, 215, 216,
+	217, 217, 218, 218, 219, 220, 220, 221,
+	221, 222, 222, 223, 224, 224, 225, 225,
+	226, 226, 227, 228, 228, 229, 229, 230,
+	230, 231, 231, 232, 233, 233, 234, 234,
+	235, 235, 236, 236, 237, 237, 238, 238,
+	239, 240, 240, 241, 241, 242, 242, 243,
+	243, 244, 244, 245, 245, 246, 246, 247,
+	247, 248, 248, 249, 249, 250, 250, 251,
+	251, 252, 252, 253, 253, 254, 254, 255,
+};
+
+static const u16 xgamma8_06[GAMMA8_TABLE_LENGTH] = {
+	0, 9, 14, 18, 21, 24, 27, 29,
+	32, 34, 37, 39, 41, 43, 45, 47,
+	48, 50, 52, 54, 55, 57, 59, 60,
+	62, 63, 65, 66, 68, 69, 71, 72,
+	73, 75, 76, 77, 79, 80, 81, 83,
+	84, 85, 86, 88, 89, 90, 91, 92,
+	94, 95, 96, 97, 98, 99, 100, 102,
+	103, 104, 105, 106, 107, 108, 109, 110,
+	111, 112, 113, 114, 115, 116, 117, 118,
+	119, 120, 121, 122, 123, 124, 125, 126,
+	127, 128, 129, 130, 131, 132, 133, 134,
+	135, 136, 137, 137, 138, 139, 140, 141,
+	142, 143, 144, 145, 145, 146, 147, 148,
+	149, 150, 151, 151, 152, 153, 154, 155,
+	156, 156, 157, 158, 159, 160, 161, 161,
+	162, 163, 164, 165, 165, 166, 167, 168,
+	169, 169, 170, 171, 172, 173, 173, 174,
+	175, 176, 176, 177, 178, 179, 179, 180,
+	181, 182, 182, 183, 184, 185, 185, 186,
+	187, 188, 188, 189, 190, 191, 191, 192,
+	193, 194, 194, 195, 196, 196, 197, 198,
+	199, 199, 200, 201, 201, 202, 203, 203,
+	204, 205, 206, 206, 207, 208, 208, 209,
+	210, 210, 211, 212, 212, 213, 214, 214,
+	215, 216, 216, 217, 218, 218, 219, 220,
+	220, 221, 222, 222, 223, 224, 224, 225,
+	226, 226, 227, 228, 228, 229, 230, 230,
+	231, 231, 232, 233, 233, 234, 235, 235,
+	236, 237, 237, 238, 238, 239, 240, 240,
+	241, 242, 242, 243, 243, 244, 245, 245,
+	246, 247, 247, 248, 248, 249, 250, 250,
+	251, 251, 252, 253, 253, 254, 254, 255,
+};
+
+static const u16 xgamma8_07[GAMMA8_TABLE_LENGTH] = {
+	0, 5, 9, 11, 14, 16, 18, 21,
+	23, 25, 26, 28, 30, 32, 33, 35,
+	37, 38, 40, 41, 43, 44, 46, 47,
+	49, 50, 52, 53, 54, 56, 57, 58,
+	60, 61, 62, 64, 65, 66, 67, 69,
+	70, 71, 72, 73, 75, 76, 77, 78,
+	79, 80, 82, 83, 84, 85, 86, 87,
+	88, 89, 90, 92, 93, 94, 95, 96,
+	97, 98, 99, 100, 101, 102, 103, 104,
+	105, 106, 107, 108, 109, 110, 111, 112,
+	113, 114, 115, 116, 117, 118, 119, 120,
+	121, 122, 123, 124, 125, 126, 127, 128,
+	129, 130, 131, 131, 132, 133, 134, 135,
+	136, 137, 138, 139, 140, 141, 142, 142,
+	143, 144, 145, 146, 147, 148, 149, 150,
+	150, 151, 152, 153, 154, 155, 156, 157,
+	157, 158, 159, 160, 161, 162, 163, 163,
+	164, 165, 166, 167, 168, 168, 169, 170,
+	171, 172, 173, 173, 174, 175, 176, 177,
+	178, 178, 179, 180, 181, 182, 182, 183,
+	184, 185, 186, 186, 187, 188, 189, 190,
+	190, 191, 192, 193, 194, 194, 195, 196,
+	197, 197, 198, 199, 200, 201, 201, 202,
+	203, 204, 204, 205, 206, 207, 208, 208,
+	209, 210, 211, 211, 212, 213, 214, 214,
+	215, 216, 217, 217, 218, 219, 220, 220,
+	221, 222, 223, 223, 224, 225, 226, 226,
+	227, 228, 228, 229, 230, 231, 231, 232,
+	233, 234, 234, 235, 236, 237, 237, 238,
+	239, 239, 240, 241, 242, 242, 243, 244,
+	244, 245, 246, 247, 247, 248, 249, 249,
+	250, 251, 251, 252, 253, 254, 254, 255,
+};
+
+static const u16 xgamma8_08[GAMMA8_TABLE_LENGTH] = {
+	0, 3, 5, 7, 9, 11, 13, 14,
+	16, 18, 19, 21, 22, 24, 25, 26,
+	28, 29, 31, 32, 33, 35, 36, 37,
+	39, 40, 41, 42, 44, 45, 46, 47,
+	48, 50, 51, 52, 53, 54, 56, 57,
+	58, 59, 60, 61, 63, 64, 65, 66,
+	67, 68, 69, 70, 71, 73, 74, 75,
+	76, 77, 78, 79, 80, 81, 82, 83,
+	84, 85, 86, 88, 89, 90, 91, 92,
+	93, 94, 95, 96, 97, 98, 99, 100,
+	101, 102, 103, 104, 105, 106, 107, 108,
+	109, 110, 111, 112, 113, 114, 115, 116,
+	117, 118, 119, 120, 121, 122, 123, 123,
+	124, 125, 126, 127, 128, 129, 130, 131,
+	132, 133, 134, 135, 136, 137, 138, 139,
+	140, 140, 141, 142, 143, 144, 145, 146,
+	147, 148, 149, 150, 151, 151, 152, 153,
+	154, 155, 156, 157, 158, 159, 160, 161,
+	161, 162, 163, 164, 165, 166, 167, 168,
+	169, 169, 170, 171, 172, 173, 174, 175,
+	176, 177, 177, 178, 179, 180, 181, 182,
+	183, 183, 184, 185, 186, 187, 188, 189,
+	190, 190, 191, 192, 193, 194, 195, 196,
+	196, 197, 198, 199, 200, 201, 202, 202,
+	203, 204, 205, 206, 207, 207, 208, 209,
+	210, 211, 212, 212, 213, 214, 215, 216,
+	217, 217, 218, 219, 220, 221, 222, 222,
+	223, 224, 225, 226, 227, 227, 228, 229,
+	230, 231, 232, 232, 233, 234, 235, 236,
+	236, 237, 238, 239, 240, 240, 241, 242,
+	243, 244, 245, 245, 246, 247, 248, 249,
+	249, 250, 251, 252, 253, 253, 254, 255,
+};
+
+static const u16 xgamma8_09[GAMMA8_TABLE_LENGTH] = {
+	0, 2, 3, 5, 6, 7, 9, 10,
+	11, 13, 14, 15, 16, 18, 19, 20,
+	21, 22, 23, 25, 26, 27, 28, 29,
+	30, 32, 33, 34, 35, 36, 37, 38,
+	39, 40, 42, 43, 44, 45, 46, 47,
+	48, 49, 50, 51, 52, 54, 55, 56,
+	57, 58, 59, 60, 61, 62, 63, 64,
+	65, 66, 67, 68, 69, 70, 71, 72,
+	73, 75, 76, 77, 78, 79, 80, 81,
+	82, 83, 84, 85, 86, 87, 88, 89,
+	90, 91, 92, 93, 94, 95, 96, 97,
+	98, 99, 100, 101, 102, 103, 104, 105,
+	106, 107, 108, 109, 110, 111, 112, 113,
+	114, 115, 116, 117, 118, 119, 120, 121,
+	122, 123, 124, 125, 126, 126, 127, 128,
+	129, 130, 131, 132, 133, 134, 135, 136,
+	137, 138, 139, 140, 141, 142, 143, 144,
+	145, 146, 147, 148, 149, 150, 151, 152,
+	152, 153, 154, 155, 156, 157, 158, 159,
+	160, 161, 162, 163, 164, 165, 166, 167,
+	168, 169, 170, 170, 171, 172, 173, 174,
+	175, 176, 177, 178, 179, 180, 181, 182,
+	183, 184, 185, 185, 186, 187, 188, 189,
+	190, 191, 192, 193, 194, 195, 196, 197,
+	198, 198, 199, 200, 201, 202, 203, 204,
+	205, 206, 207, 208, 209, 210, 210, 211,
+	212, 213, 214, 215, 216, 217, 218, 219,
+	220, 221, 221, 222, 223, 224, 225, 226,
+	227, 228, 229, 230, 231, 231, 232, 233,
+	234, 235, 236, 237, 238, 239, 240, 241,
+	241, 242, 243, 244, 245, 246, 247, 248,
+	249, 250, 250, 251, 252, 253, 254, 255,
+};
+
+static const u16 xgamma8_10[GAMMA8_TABLE_LENGTH] = {
+	0, 1, 2, 3, 4, 5, 6, 7,
+	8, 9, 10, 11, 12, 13, 14, 15,
+	16, 17, 18, 19, 20, 21, 22, 23,
+	24, 25, 26, 27, 28, 29, 30, 31,
+	32, 33, 34, 35, 36, 37, 38, 39,
+	40, 41, 42, 43, 44, 45, 46, 47,
+	48, 49, 50, 51, 52, 53, 54, 55,
+	56, 57, 58, 59, 60, 61, 62, 63,
+	64, 65, 66, 67, 68, 69, 70, 71,
+	72, 73, 74, 75, 76, 77, 78, 79,
+	80, 81, 82, 83, 84, 85, 86, 87,
+	88, 89, 90, 91, 92, 93, 94, 95,
+	96, 97, 98, 99, 100, 101, 102, 103,
+	104, 105, 106, 107, 108, 109, 110, 111,
+	112, 113, 114, 115, 116, 117, 118, 119,
+	120, 121, 122, 123, 124, 125, 126, 127,
+	128, 129, 130, 131, 132, 133, 134, 135,
+	136, 137, 138, 139, 140, 141, 142, 143,
+	144, 145, 146, 147, 148, 149, 150, 151,
+	152, 153, 154, 155, 156, 157, 158, 159,
+	160, 161, 162, 163, 164, 165, 166, 167,
+	168, 169, 170, 171, 172, 173, 174, 175,
+	176, 177, 178, 179, 180, 181, 182, 183,
+	184, 185, 186, 187, 188, 189, 190, 191,
+	192, 193, 194, 195, 196, 197, 198, 199,
+	200, 201, 202, 203, 204, 205, 206, 207,
+	208, 209, 210, 211, 212, 213, 214, 215,
+	216, 217, 218, 219, 220, 221, 222, 223,
+	224, 225, 226, 227, 228, 229, 230, 231,
+	232, 233, 234, 235, 236, 237, 238, 239,
+	240, 241, 242, 243, 244, 245, 246, 247,
+	248, 249, 250, 251, 252, 253, 254, 255,
+};
+
+static const u16 xgamma8_11[GAMMA8_TABLE_LENGTH] = {
+	0, 1, 1, 2, 3, 3, 4, 5,
+	6, 6, 7, 8, 9, 10, 10, 11,
+	12, 13, 14, 15, 16, 16, 17, 18,
+	19, 20, 21, 22, 22, 23, 24, 25,
+	26, 27, 28, 29, 30, 31, 31, 32,
+	33, 34, 35, 36, 37, 38, 39, 40,
+	41, 42, 42, 43, 44, 45, 46, 47,
+	48, 49, 50, 51, 52, 53, 54, 55,
+	56, 57, 58, 59, 60, 61, 62, 62,
+	63, 64, 65, 66, 67, 68, 69, 70,
+	71, 72, 73, 74, 75, 76, 77, 78,
+	79, 80, 81, 82, 83, 84, 85, 86,
+	87, 88, 89, 90, 91, 92, 93, 94,
+	95, 96, 97, 98, 99, 100, 101, 102,
+	103, 104, 105, 106, 107, 108, 109, 110,
+	111, 112, 113, 114, 115, 116, 117, 118,
+	119, 121, 122, 123, 124, 125, 126, 127,
+	128, 129, 130, 131, 132, 133, 134, 135,
+	136, 137, 138, 139, 140, 141, 142, 143,
+	144, 145, 146, 147, 149, 150, 151, 152,
+	153, 154, 155, 156, 157, 158, 159, 160,
+	161, 162, 163, 164, 165, 166, 167, 169,
+	170, 171, 172, 173, 174, 175, 176, 177,
+	178, 179, 180, 181, 182, 183, 184, 186,
+	187, 188, 189, 190, 191, 192, 193, 194,
+	195, 196, 197, 198, 199, 201, 202, 203,
+	204, 205, 206, 207, 208, 209, 210, 211,
+	212, 214, 215, 216, 217, 218, 219, 220,
+	221, 222, 223, 224, 225, 227, 228, 229,
+	230, 231, 232, 233, 234, 235, 236, 237,
+	239, 240, 241, 242, 243, 244, 245, 246,
+	247, 248, 250, 251, 252, 253, 254, 255,
+};
+
+static const u16 xgamma8_12[GAMMA8_TABLE_LENGTH] = {
+	0, 0, 1, 1, 2, 2, 3, 3,
+	4, 5, 5, 6, 7, 7, 8, 9,
+	9, 10, 11, 11, 12, 13, 13, 14,
+	15, 16, 16, 17, 18, 19, 20, 20,
+	21, 22, 23, 24, 24, 25, 26, 27,
+	28, 28, 29, 30, 31, 32, 33, 34,
+	34, 35, 36, 37, 38, 39, 40, 40,
+	41, 42, 43, 44, 45, 46, 47, 48,
+	49, 49, 50, 51, 52, 53, 54, 55,
+	56, 57, 58, 59, 60, 61, 62, 62,
+	63, 64, 65, 66, 67, 68, 69, 70,
+	71, 72, 73, 74, 75, 76, 77, 78,
+	79, 80, 81, 82, 83, 84, 85, 86,
+	87, 88, 89, 90, 91, 92, 93, 94,
+	95, 96, 97, 98, 99, 100, 101, 102,
+	103, 104, 105, 106, 107, 108, 109, 110,
+	112, 113, 114, 115, 116, 117, 118, 119,
+	120, 121, 122, 123, 124, 125, 126, 127,
+	128, 130, 131, 132, 133, 134, 135, 136,
+	137, 138, 139, 140, 141, 142, 144, 145,
+	146, 147, 148, 149, 150, 151, 152, 153,
+	155, 156, 157, 158, 159, 160, 161, 162,
+	163, 165, 166, 167, 168, 169, 170, 171,
+	172, 173, 175, 176, 177, 178, 179, 180,
+	181, 183, 184, 185, 186, 187, 188, 189,
+	191, 192, 193, 194, 195, 196, 197, 199,
+	200, 201, 202, 203, 204, 205, 207, 208,
+	209, 210, 211, 212, 214, 215, 216, 217,
+	218, 219, 221, 222, 223, 224, 225, 226,
+	228, 229, 230, 231, 232, 234, 235, 236,
+	237, 238, 239, 241, 242, 243, 244, 245,
+	247, 248, 249, 250, 251, 253, 254, 255,
+};
+
+static const u16 xgamma8_13[GAMMA8_TABLE_LENGTH] = {
+	0, 0, 0, 1, 1, 2, 2, 2,
+	3, 3, 4, 4, 5, 5, 6, 6,
+	7, 8, 8, 9, 9, 10, 11, 11,
+	12, 12, 13, 14, 14, 15, 16, 16,
+	17, 18, 19, 19, 20, 21, 21, 22,
+	23, 24, 24, 25, 26, 27, 28, 28,
+	29, 30, 31, 31, 32, 33, 34, 35,
+	36, 36, 37, 38, 39, 40, 41, 41,
+	42, 43, 44, 45, 46, 47, 47, 48,
+	49, 50, 51, 52, 53, 54, 55, 56,
+	57, 57, 58, 59, 60, 61, 62, 63,
+	64, 65, 66, 67, 68, 69, 70, 71,
+	72, 73, 74, 75, 76, 76, 77, 78,
+	79, 80, 81, 82, 83, 84, 85, 86,
+	88, 89, 90, 91, 92, 93, 94, 95,
+	96, 97, 98, 99, 100, 101, 102, 103,
+	104, 105, 106, 107, 108, 109, 110, 112,
+	113, 114, 115, 116, 117, 118, 119, 120,
+	121, 122, 124, 125, 126, 127, 128, 129,
+	130, 131, 132, 133, 135, 136, 137, 138,
+	139, 140, 141, 143, 144, 145, 146, 147,
+	148, 149, 151, 152, 153, 154, 155, 156,
+	157, 159, 160, 161, 162, 163, 164, 166,
+	167, 168, 169, 170, 172, 173, 174, 175,
+	176, 178, 179, 180, 181, 182, 184, 185,
+	186, 187, 188, 190, 191, 192, 193, 194,
+	196, 197, 198, 199, 201, 202, 203, 204,
+	206, 207, 208, 209, 210, 212, 213, 214,
+	215, 217, 218, 219, 220, 222, 223, 224,
+	226, 227, 228, 229, 231, 232, 233, 234,
+	236, 237, 238, 240, 241, 242, 243, 245,
+	246, 247, 249, 250, 251, 252, 254, 255,
+};
+
+static const u16 xgamma8_14[GAMMA8_TABLE_LENGTH] = {
+	0, 0, 0, 1, 1, 1, 1, 2,
+	2, 2, 3, 3, 4, 4, 4, 5,
+	5, 6, 6, 7, 7, 8, 8, 9,
+	9, 10, 10, 11, 12, 12, 13, 13,
+	14, 15, 15, 16, 16, 17, 18, 18,
+	19, 20, 20, 21, 22, 22, 23, 24,
+	25, 25, 26, 27, 28, 28, 29, 30,
+	31, 31, 32, 33, 34, 34, 35, 36,
+	37, 38, 38, 39, 40, 41, 42, 43,
+	43, 44, 45, 46, 47, 48, 49, 49,
+	50, 51, 52, 53, 54, 55, 56, 57,
+	57, 58, 59, 60, 61, 62, 63, 64,
+	65, 66, 67, 68, 69, 70, 71, 72,
+	73, 74, 75, 76, 77, 78, 79, 80,
+	81, 82, 83, 84, 85, 86, 87, 88,
+	89, 90, 91, 92, 93, 94, 95, 96,
+	97, 98, 99, 100, 101, 103, 104, 105,
+	106, 107, 108, 109, 110, 111, 112, 113,
+	115, 116, 117, 118, 119, 120, 121, 122,
+	124, 125, 126, 127, 128, 129, 130, 132,
+	133, 134, 135, 136, 137, 139, 140, 141,
+	142, 143, 145, 146, 147, 148, 149, 151,
+	152, 153, 154, 155, 157, 158, 159, 160,
+	161, 163, 164, 165, 166, 168, 169, 170,
+	171, 173, 174, 175, 176, 178, 179, 180,
+	181, 183, 184, 185, 187, 188, 189, 190,
+	192, 193, 194, 196, 197, 198, 200, 201,
+	202, 203, 205, 206, 207, 209, 210, 211,
+	213, 214, 215, 217, 218, 219, 221, 222,
+	223, 225, 226, 227, 229, 230, 232, 233,
+	234, 236, 237, 238, 240, 241, 242, 244,
+	245, 247, 248, 249, 251, 252, 254, 255,
+};
+
+static const u16 xgamma8_15[GAMMA8_TABLE_LENGTH] = {
+	0, 0, 0, 0, 1, 1, 1, 1,
+	1, 2, 2, 2, 3, 3, 3, 4,
+	4, 4, 5, 5, 6, 6, 6, 7,
+	7, 8, 8, 9, 9, 10, 10, 11,
+	11, 12, 12, 13, 14, 14, 15, 15,
+	16, 16, 17, 18, 18, 19, 20, 20,
+	21, 21, 22, 23, 23, 24, 25, 26,
+	26, 27, 28, 28, 29, 30, 31, 31,
+	32, 33, 34, 34, 35, 36, 37, 37,
+	38, 39, 40, 41, 41, 42, 43, 44,
+	45, 46, 46, 47, 48, 49, 50, 51,
+	52, 53, 53, 54, 55, 56, 57, 58,
+	59, 60, 61, 62, 63, 64, 65, 65,
+	66, 67, 68, 69, 70, 71, 72, 73,
+	74, 75, 76, 77, 78, 79, 80, 81,
+	82, 83, 84, 85, 86, 88, 89, 90,
+	91, 92, 93, 94, 95, 96, 97, 98,
+	99, 100, 102, 103, 104, 105, 106, 107,
+	108, 109, 110, 112, 113, 114, 115, 116,
+	117, 119, 120, 121, 122, 123, 124, 126,
+	127, 128, 129, 130, 132, 133, 134, 135,
+	136, 138, 139, 140, 141, 142, 144, 145,
+	146, 147, 149, 150, 151, 152, 154, 155,
+	156, 158, 159, 160, 161, 163, 164, 165,
+	167, 168, 169, 171, 172, 173, 174, 176,
+	177, 178, 180, 181, 182, 184, 185, 187,
+	188, 189, 191, 192, 193, 195, 196, 197,
+	199, 200, 202, 203, 204, 206, 207, 209,
+	210, 211, 213, 214, 216, 217, 218, 220,
+	221, 223, 224, 226, 227, 228, 230, 231,
+	233, 234, 236, 237, 239, 240, 242, 243,
+	245, 246, 248, 249, 251, 252, 254, 255,
+};
+
+static const u16 xgamma8_16[GAMMA8_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 1, 1,
+	1, 1, 1, 2, 2, 2, 2, 3,
+	3, 3, 4, 4, 4, 5, 5, 5,
+	6, 6, 7, 7, 7, 8, 8, 9,
+	9, 10, 10, 11, 11, 12, 12, 13,
+	13, 14, 14, 15, 15, 16, 16, 17,
+	18, 18, 19, 19, 20, 21, 21, 22,
+	23, 23, 24, 25, 25, 26, 27, 27,
+	28, 29, 29, 30, 31, 31, 32, 33,
+	34, 34, 35, 36, 37, 38, 38, 39,
+	40, 41, 42, 42, 43, 44, 45, 46,
+	46, 47, 48, 49, 50, 51, 52, 53,
+	53, 54, 55, 56, 57, 58, 59, 60,
+	61, 62, 63, 64, 64, 65, 66, 67,
+	68, 69, 70, 71, 72, 73, 74, 75,
+	76, 77, 78, 79, 80, 81, 83, 84,
+	85, 86, 87, 88, 89, 90, 91, 92,
+	93, 94, 95, 97, 98, 99, 100, 101,
+	102, 103, 104, 106, 107, 108, 109, 110,
+	111, 113, 114, 115, 116, 117, 119, 120,
+	121, 122, 123, 125, 126, 127, 128, 130,
+	131, 132, 133, 135, 136, 137, 138, 140,
+	141, 142, 143, 145, 146, 147, 149, 150,
+	151, 153, 154, 155, 157, 158, 159, 161,
+	162, 163, 165, 166, 167, 169, 170, 171,
+	173, 174, 176, 177, 178, 180, 181, 183,
+	184, 185, 187, 188, 190, 191, 193, 194,
+	196, 197, 198, 200, 201, 203, 204, 206,
+	207, 209, 210, 212, 213, 215, 216, 218,
+	219, 221, 222, 224, 225, 227, 228, 230,
+	231, 233, 235, 236, 238, 239, 241, 242,
+	244, 245, 247, 249, 250, 252, 253, 255,
+};
+
+static const u16 xgamma8_17[GAMMA8_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 1,
+	1, 1, 1, 1, 1, 2, 2, 2,
+	2, 3, 3, 3, 3, 4, 4, 4,
+	5, 5, 5, 6, 6, 6, 7, 7,
+	7, 8, 8, 9, 9, 10, 10, 10,
+	11, 11, 12, 12, 13, 13, 14, 14,
+	15, 15, 16, 17, 17, 18, 18, 19,
+	19, 20, 21, 21, 22, 22, 23, 24,
+	24, 25, 26, 26, 27, 28, 28, 29,
+	30, 30, 31, 32, 33, 33, 34, 35,
+	36, 36, 37, 38, 39, 39, 40, 41,
+	42, 43, 43, 44, 45, 46, 47, 48,
+	48, 49, 50, 51, 52, 53, 54, 55,
+	56, 56, 57, 58, 59, 60, 61, 62,
+	63, 64, 65, 66, 67, 68, 69, 70,
+	71, 72, 73, 74, 75, 76, 77, 78,
+	79, 80, 81, 82, 83, 84, 85, 86,
+	88, 89, 90, 91, 92, 93, 94, 95,
+	97, 98, 99, 100, 101, 102, 103, 105,
+	106, 107, 108, 109, 111, 112, 113, 114,
+	115, 117, 118, 119, 120, 122, 123, 124,
+	125, 127, 128, 129, 131, 132, 133, 134,
+	136, 137, 138, 140, 141, 142, 144, 145,
+	146, 148, 149, 151, 152, 153, 155, 156,
+	157, 159, 160, 162, 163, 164, 166, 167,
+	169, 170, 172, 173, 174, 176, 177, 179,
+	180, 182, 183, 185, 186, 188, 189, 191,
+	192, 194, 195, 197, 198, 200, 201, 203,
+	205, 206, 208, 209, 211, 212, 214, 216,
+	217, 219, 220, 222, 224, 225, 227, 228,
+	230, 232, 233, 235, 237, 238, 240, 242,
+	243, 245, 247, 248, 250, 252, 253, 255,
+};
+
+static const u16 xgamma8_18[GAMMA8_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	1, 1, 1, 1, 1, 1, 1, 2,
+	2, 2, 2, 2, 3, 3, 3, 3,
+	4, 4, 4, 4, 5, 5, 5, 6,
+	6, 6, 7, 7, 8, 8, 8, 9,
+	9, 10, 10, 10, 11, 11, 12, 12,
+	13, 13, 14, 14, 15, 15, 16, 16,
+	17, 17, 18, 18, 19, 19, 20, 21,
+	21, 22, 22, 23, 24, 24, 25, 26,
+	26, 27, 28, 28, 29, 30, 30, 31,
+	32, 32, 33, 34, 35, 35, 36, 37,
+	38, 38, 39, 40, 41, 41, 42, 43,
+	44, 45, 46, 46, 47, 48, 49, 50,
+	51, 52, 53, 53, 54, 55, 56, 57,
+	58, 59, 60, 61, 62, 63, 64, 65,
+	66, 67, 68, 69, 70, 71, 72, 73,
+	74, 75, 76, 77, 78, 79, 80, 81,
+	82, 83, 84, 86, 87, 88, 89, 90,
+	91, 92, 93, 95, 96, 97, 98, 99,
+	100, 102, 103, 104, 105, 107, 108, 109,
+	110, 111, 113, 114, 115, 116, 118, 119,
+	120, 122, 123, 124, 126, 127, 128, 129,
+	131, 132, 134, 135, 136, 138, 139, 140,
+	142, 143, 145, 146, 147, 149, 150, 152,
+	153, 154, 156, 157, 159, 160, 162, 163,
+	165, 166, 168, 169, 171, 172, 174, 175,
+	177, 178, 180, 181, 183, 184, 186, 188,
+	189, 191, 192, 194, 195, 197, 199, 200,
+	202, 204, 205, 207, 208, 210, 212, 213,
+	215, 217, 218, 220, 222, 224, 225, 227,
+	229, 230, 232, 234, 236, 237, 239, 241,
+	243, 244, 246, 248, 250, 251, 253, 255,
+};
+
+static const u16 xgamma8_19[GAMMA8_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 1, 1, 1, 1, 1, 1,
+	1, 1, 2, 2, 2, 2, 2, 3,
+	3, 3, 3, 4, 4, 4, 4, 5,
+	5, 5, 6, 6, 6, 7, 7, 7,
+	8, 8, 8, 9, 9, 9, 10, 10,
+	11, 11, 12, 12, 12, 13, 13, 14,
+	14, 15, 15, 16, 16, 17, 17, 18,
+	18, 19, 20, 20, 21, 21, 22, 22,
+	23, 24, 24, 25, 26, 26, 27, 28,
+	28, 29, 30, 30, 31, 32, 32, 33,
+	34, 35, 35, 36, 37, 38, 38, 39,
+	40, 41, 41, 42, 43, 44, 45, 46,
+	46, 47, 48, 49, 50, 51, 52, 53,
+	53, 54, 55, 56, 57, 58, 59, 60,
+	61, 62, 63, 64, 65, 66, 67, 68,
+	69, 70, 71, 72, 73, 74, 75, 76,
+	77, 78, 79, 81, 82, 83, 84, 85,
+	86, 87, 88, 90, 91, 92, 93, 94,
+	95, 97, 98, 99, 100, 101, 103, 104,
+	105, 106, 108, 109, 110, 112, 113, 114,
+	115, 117, 118, 119, 121, 122, 123, 125,
+	126, 127, 129, 130, 132, 133, 134, 136,
+	137, 139, 140, 141, 143, 144, 146, 147,
+	149, 150, 152, 153, 155, 156, 158, 159,
+	161, 162, 164, 165, 167, 168, 170, 172,
+	173, 175, 176, 178, 180, 181, 183, 184,
+	186, 188, 189, 191, 193, 194, 196, 198,
+	199, 201, 203, 204, 206, 208, 210, 211,
+	213, 215, 217, 218, 220, 222, 224, 225,
+	227, 229, 231, 233, 235, 236, 238, 240,
+	242, 244, 246, 247, 249, 251, 253, 255,
+};
+
+static const u16 xgamma8_20[GAMMA8_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 1, 1, 1, 1,
+	1, 1, 1, 1, 2, 2, 2, 2,
+	2, 2, 3, 3, 3, 3, 4, 4,
+	4, 4, 5, 5, 5, 5, 6, 6,
+	6, 7, 7, 7, 8, 8, 8, 9,
+	9, 9, 10, 10, 11, 11, 11, 12,
+	12, 13, 13, 14, 14, 15, 15, 16,
+	16, 17, 17, 18, 18, 19, 19, 20,
+	20, 21, 21, 22, 23, 23, 24, 24,
+	25, 26, 26, 27, 28, 28, 29, 30,
+	30, 31, 32, 32, 33, 34, 35, 35,
+	36, 37, 38, 38, 39, 40, 41, 42,
+	42, 43, 44, 45, 46, 47, 47, 48,
+	49, 50, 51, 52, 53, 54, 55, 56,
+	56, 57, 58, 59, 60, 61, 62, 63,
+	64, 65, 66, 67, 68, 69, 70, 71,
+	73, 74, 75, 76, 77, 78, 79, 80,
+	81, 82, 84, 85, 86, 87, 88, 89,
+	91, 92, 93, 94, 95, 97, 98, 99,
+	100, 102, 103, 104, 105, 107, 108, 109,
+	111, 112, 113, 115, 116, 117, 119, 120,
+	121, 123, 124, 126, 127, 128, 130, 131,
+	133, 134, 136, 137, 139, 140, 142, 143,
+	145, 146, 148, 149, 151, 152, 154, 155,
+	157, 158, 160, 162, 163, 165, 166, 168,
+	170, 171, 173, 175, 176, 178, 180, 181,
+	183, 185, 186, 188, 190, 192, 193, 195,
+	197, 199, 200, 202, 204, 206, 207, 209,
+	211, 213, 215, 217, 218, 220, 222, 224,
+	226, 228, 230, 232, 233, 235, 237, 239,
+	241, 243, 245, 247, 249, 251, 253, 255,
+};
+
+static const u16 xgamma8_21[GAMMA8_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 2,
+	2, 2, 2, 2, 2, 3, 3, 3,
+	3, 3, 4, 4, 4, 4, 5, 5,
+	5, 5, 6, 6, 6, 7, 7, 7,
+	8, 8, 8, 9, 9, 9, 10, 10,
+	11, 11, 11, 12, 12, 13, 13, 14,
+	14, 14, 15, 15, 16, 16, 17, 17,
+	18, 18, 19, 20, 20, 21, 21, 22,
+	22, 23, 24, 24, 25, 25, 26, 27,
+	27, 28, 29, 29, 30, 31, 31, 32,
+	33, 33, 34, 35, 36, 36, 37, 38,
+	39, 40, 40, 41, 42, 43, 44, 44,
+	45, 46, 47, 48, 49, 50, 51, 51,
+	52, 53, 54, 55, 56, 57, 58, 59,
+	60, 61, 62, 63, 64, 65, 66, 67,
+	68, 69, 70, 71, 72, 73, 75, 76,
+	77, 78, 79, 80, 81, 83, 84, 85,
+	86, 87, 88, 90, 91, 92, 93, 95,
+	96, 97, 98, 100, 101, 102, 104, 105,
+	106, 107, 109, 110, 112, 113, 114, 116,
+	117, 118, 120, 121, 123, 124, 126, 127,
+	129, 130, 131, 133, 134, 136, 137, 139,
+	141, 142, 144, 145, 147, 148, 150, 151,
+	153, 155, 156, 158, 160, 161, 163, 165,
+	166, 168, 170, 171, 173, 175, 176, 178,
+	180, 182, 183, 185, 187, 189, 191, 192,
+	194, 196, 198, 200, 202, 203, 205, 207,
+	209, 211, 213, 215, 217, 219, 221, 223,
+	225, 226, 228, 230, 232, 234, 236, 238,
+	241, 243, 245, 247, 249, 251, 253, 255,
+};
+
+static const u16 xgamma8_22[GAMMA8_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 1,
+	1, 1, 1, 1, 1, 1, 1, 1,
+	1, 2, 2, 2, 2, 2, 2, 2,
+	3, 3, 3, 3, 3, 4, 4, 4,
+	4, 5, 5, 5, 5, 6, 6, 6,
+	6, 7, 7, 7, 8, 8, 8, 9,
+	9, 9, 10, 10, 11, 11, 11, 12,
+	12, 13, 13, 13, 14, 14, 15, 15,
+	16, 16, 17, 17, 18, 18, 19, 19,
+	20, 20, 21, 22, 22, 23, 23, 24,
+	25, 25, 26, 26, 27, 28, 28, 29,
+	30, 30, 31, 32, 33, 33, 34, 35,
+	35, 36, 37, 38, 39, 39, 40, 41,
+	42, 43, 43, 44, 45, 46, 47, 48,
+	49, 49, 50, 51, 52, 53, 54, 55,
+	56, 57, 58, 59, 60, 61, 62, 63,
+	64, 65, 66, 67, 68, 69, 70, 71,
+	73, 74, 75, 76, 77, 78, 79, 81,
+	82, 83, 84, 85, 87, 88, 89, 90,
+	91, 93, 94, 95, 97, 98, 99, 100,
+	102, 103, 105, 106, 107, 109, 110, 111,
+	113, 114, 116, 117, 119, 120, 121, 123,
+	124, 126, 127, 129, 130, 132, 133, 135,
+	137, 138, 140, 141, 143, 145, 146, 148,
+	149, 151, 153, 154, 156, 158, 159, 161,
+	163, 165, 166, 168, 170, 172, 173, 175,
+	177, 179, 181, 182, 184, 186, 188, 190,
+	192, 194, 196, 197, 199, 201, 203, 205,
+	207, 209, 211, 213, 215, 217, 219, 221,
+	223, 225, 227, 229, 231, 234, 236, 238,
+	240, 242, 244, 246, 248, 251, 253, 255,
+};
+
+static const u16 xgamma8_23[GAMMA8_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 2, 2, 2, 2,
+	2, 2, 2, 3, 3, 3, 3, 3,
+	4, 4, 4, 4, 4, 5, 5, 5,
+	5, 6, 6, 6, 7, 7, 7, 7,
+	8, 8, 8, 9, 9, 10, 10, 10,
+	11, 11, 11, 12, 12, 13, 13, 13,
+	14, 14, 15, 15, 16, 16, 17, 17,
+	18, 18, 19, 19, 20, 20, 21, 21,
+	22, 23, 23, 24, 24, 25, 26, 26,
+	27, 28, 28, 29, 30, 30, 31, 32,
+	32, 33, 34, 35, 35, 36, 37, 38,
+	38, 39, 40, 41, 42, 42, 43, 44,
+	45, 46, 47, 48, 49, 49, 50, 51,
+	52, 53, 54, 55, 56, 57, 58, 59,
+	60, 61, 62, 63, 64, 65, 66, 67,
+	69, 70, 71, 72, 73, 74, 75, 76,
+	78, 79, 80, 81, 82, 84, 85, 86,
+	87, 89, 90, 91, 92, 94, 95, 96,
+	98, 99, 100, 102, 103, 104, 106, 107,
+	109, 110, 112, 113, 114, 116, 117, 119,
+	120, 122, 123, 125, 126, 128, 130, 131,
+	133, 134, 136, 138, 139, 141, 143, 144,
+	146, 148, 149, 151, 153, 154, 156, 158,
+	160, 161, 163, 165, 167, 169, 170, 172,
+	174, 176, 178, 180, 182, 183, 185, 187,
+	189, 191, 193, 195, 197, 199, 201, 203,
+	205, 207, 209, 211, 213, 215, 218, 220,
+	222, 224, 226, 228, 230, 233, 235, 237,
+	239, 241, 244, 246, 248, 250, 253, 255,
+};
+
+static const u16 xgamma8_24[GAMMA8_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 2,
+	2, 2, 2, 2, 2, 2, 3, 3,
+	3, 3, 3, 4, 4, 4, 4, 4,
+	5, 5, 5, 5, 6, 6, 6, 6,
+	7, 7, 7, 8, 8, 8, 9, 9,
+	9, 10, 10, 10, 11, 11, 11, 12,
+	12, 13, 13, 14, 14, 14, 15, 15,
+	16, 16, 17, 17, 18, 18, 19, 19,
+	20, 20, 21, 22, 22, 23, 23, 24,
+	24, 25, 26, 26, 27, 28, 28, 29,
+	30, 30, 31, 32, 32, 33, 34, 35,
+	35, 36, 37, 38, 39, 39, 40, 41,
+	42, 43, 43, 44, 45, 46, 47, 48,
+	49, 50, 51, 52, 53, 53, 54, 55,
+	56, 57, 58, 59, 60, 62, 63, 64,
+	65, 66, 67, 68, 69, 70, 71, 73,
+	74, 75, 76, 77, 78, 80, 81, 82,
+	83, 85, 86, 87, 88, 90, 91, 92,
+	94, 95, 96, 98, 99, 100, 102, 103,
+	105, 106, 108, 109, 111, 112, 114, 115,
+	117, 118, 120, 121, 123, 124, 126, 127,
+	129, 131, 132, 134, 136, 137, 139, 141,
+	142, 144, 146, 148, 149, 151, 153, 155,
+	156, 158, 160, 162, 164, 166, 167, 169,
+	171, 173, 175, 177, 179, 181, 183, 185,
+	187, 189, 191, 193, 195, 197, 199, 201,
+	203, 205, 207, 210, 212, 214, 216, 218,
+	220, 223, 225, 227, 229, 232, 234, 236,
+	239, 241, 243, 246, 248, 250, 253, 255,
+};
+
+static const u16 xgamma8_25[GAMMA8_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1,
+	1, 2, 2, 2, 2, 2, 2, 2,
+	2, 3, 3, 3, 3, 3, 4, 4,
+	4, 4, 4, 5, 5, 5, 5, 6,
+	6, 6, 6, 7, 7, 7, 7, 8,
+	8, 8, 9, 9, 9, 10, 10, 10,
+	11, 11, 12, 12, 12, 13, 13, 14,
+	14, 15, 15, 15, 16, 16, 17, 17,
+	18, 18, 19, 19, 20, 20, 21, 22,
+	22, 23, 23, 24, 25, 25, 26, 26,
+	27, 28, 28, 29, 30, 30, 31, 32,
+	33, 33, 34, 35, 36, 36, 37, 38,
+	39, 40, 40, 41, 42, 43, 44, 45,
+	46, 46, 47, 48, 49, 50, 51, 52,
+	53, 54, 55, 56, 57, 58, 59, 60,
+	61, 62, 63, 64, 65, 67, 68, 69,
+	70, 71, 72, 73, 75, 76, 77, 78,
+	80, 81, 82, 83, 85, 86, 87, 89,
+	90, 91, 93, 94, 95, 97, 98, 99,
+	101, 102, 104, 105, 107, 108, 110, 111,
+	113, 114, 116, 117, 119, 121, 122, 124,
+	125, 127, 129, 130, 132, 134, 135, 137,
+	139, 141, 142, 144, 146, 148, 150, 151,
+	153, 155, 157, 159, 161, 163, 165, 166,
+	168, 170, 172, 174, 176, 178, 180, 182,
+	184, 186, 189, 191, 193, 195, 197, 199,
+	201, 204, 206, 208, 210, 212, 215, 217,
+	219, 221, 224, 226, 228, 231, 233, 235,
+	238, 240, 243, 245, 248, 250, 253, 255,
+};
+
+static const u16 xgamma8_26[GAMMA8_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 2, 2, 2, 2,
+	2, 2, 2, 2, 3, 3, 3, 3,
+	3, 3, 4, 4, 4, 4, 5, 5,
+	5, 5, 5, 6, 6, 6, 6, 7,
+	7, 7, 8, 8, 8, 9, 9, 9,
+	10, 10, 10, 11, 11, 11, 12, 12,
+	13, 13, 13, 14, 14, 15, 15, 16,
+	16, 17, 17, 18, 18, 19, 19, 20,
+	20, 21, 21, 22, 22, 23, 24, 24,
+	25, 25, 26, 27, 27, 28, 29, 29,
+	30, 31, 31, 32, 33, 34, 34, 35,
+	36, 37, 38, 38, 39, 40, 41, 42,
+	42, 43, 44, 45, 46, 47, 48, 49,
+	50, 51, 52, 53, 54, 55, 56, 57,
+	58, 59, 60, 61, 62, 63, 64, 65,
+	66, 68, 69, 70, 71, 72, 73, 75,
+	76, 77, 78, 80, 81, 82, 84, 85,
+	86, 88, 89, 90, 92, 93, 94, 96,
+	97, 99, 100, 102, 103, 105, 106, 108,
+	109, 111, 112, 114, 115, 117, 119, 120,
+	122, 124, 125, 127, 129, 130, 132, 134,
+	136, 137, 139, 141, 143, 145, 146, 148,
+	150, 152, 154, 156, 158, 160, 162, 164,
+	166, 168, 170, 172, 174, 176, 178, 180,
+	182, 184, 186, 188, 191, 193, 195, 197,
+	199, 202, 204, 206, 209, 211, 213, 215,
+	218, 220, 223, 225, 227, 230, 232, 235,
+	237, 240, 242, 245, 247, 250, 252, 255,
+};
+
+static const u16 xgamma8_27[GAMMA8_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 2,
+	2, 2, 2, 2, 2, 2, 3, 3,
+	3, 3, 3, 3, 3, 4, 4, 4,
+	4, 4, 5, 5, 5, 5, 6, 6,
+	6, 6, 7, 7, 7, 7, 8, 8,
+	8, 9, 9, 9, 10, 10, 10, 11,
+	11, 12, 12, 12, 13, 13, 14, 14,
+	14, 15, 15, 16, 16, 17, 17, 18,
+	18, 19, 19, 20, 20, 21, 21, 22,
+	23, 23, 24, 24, 25, 26, 26, 27,
+	28, 28, 29, 30, 30, 31, 32, 33,
+	33, 34, 35, 36, 36, 37, 38, 39,
+	40, 41, 41, 42, 43, 44, 45, 46,
+	47, 48, 49, 50, 51, 51, 52, 53,
+	55, 56, 57, 58, 59, 60, 61, 62,
+	63, 64, 65, 66, 68, 69, 70, 71,
+	72, 74, 75, 76, 77, 79, 80, 81,
+	83, 84, 85, 87, 88, 89, 91, 92,
+	94, 95, 97, 98, 100, 101, 103, 104,
+	106, 107, 109, 110, 112, 114, 115, 117,
+	119, 120, 122, 124, 125, 127, 129, 131,
+	132, 134, 136, 138, 140, 141, 143, 145,
+	147, 149, 151, 153, 155, 157, 159, 161,
+	163, 165, 167, 169, 171, 173, 175, 178,
+	180, 182, 184, 186, 188, 191, 193, 195,
+	198, 200, 202, 205, 207, 209, 212, 214,
+	216, 219, 221, 224, 226, 229, 231, 234,
+	237, 239, 242, 244, 247, 250, 252, 255,
+};
+
+static const u16 xgamma8_28[GAMMA8_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1,
+	1, 2, 2, 2, 2, 2, 2, 2,
+	2, 3, 3, 3, 3, 3, 3, 3,
+	4, 4, 4, 4, 4, 5, 5, 5,
+	5, 6, 6, 6, 6, 7, 7, 7,
+	7, 8, 8, 8, 9, 9, 9, 10,
+	10, 10, 11, 11, 11, 12, 12, 13,
+	13, 13, 14, 14, 15, 15, 16, 16,
+	17, 17, 18, 18, 19, 19, 20, 20,
+	21, 21, 22, 22, 23, 24, 24, 25,
+	25, 26, 27, 27, 28, 29, 29, 30,
+	31, 32, 32, 33, 34, 35, 35, 36,
+	37, 38, 39, 39, 40, 41, 42, 43,
+	44, 45, 46, 47, 48, 49, 50, 50,
+	51, 52, 54, 55, 56, 57, 58, 59,
+	60, 61, 62, 63, 64, 66, 67, 68,
+	69, 70, 72, 73, 74, 75, 77, 78,
+	79, 81, 82, 83, 85, 86, 87, 89,
+	90, 92, 93, 95, 96, 98, 99, 101,
+	102, 104, 105, 107, 109, 110, 112, 114,
+	115, 117, 119, 120, 122, 124, 126, 127,
+	129, 131, 133, 135, 137, 138, 140, 142,
+	144, 146, 148, 150, 152, 154, 156, 158,
+	160, 162, 164, 167, 169, 171, 173, 175,
+	177, 180, 182, 184, 186, 189, 191, 193,
+	196, 198, 200, 203, 205, 208, 210, 213,
+	215, 218, 220, 223, 225, 228, 231, 233,
+	236, 239, 241, 244, 247, 249, 252, 255,
+};
+
+static const u16 xgamma8_29[GAMMA8_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 2, 2, 2, 2,
+	2, 2, 2, 2, 3, 3, 3, 3,
+	3, 3, 3, 4, 4, 4, 4, 4,
+	5, 5, 5, 5, 6, 6, 6, 6,
+	7, 7, 7, 7, 8, 8, 8, 9,
+	9, 9, 9, 10, 10, 11, 11, 11,
+	12, 12, 12, 13, 13, 14, 14, 15,
+	15, 15, 16, 16, 17, 17, 18, 18,
+	19, 19, 20, 21, 21, 22, 22, 23,
+	23, 24, 25, 25, 26, 27, 27, 28,
+	29, 29, 30, 31, 32, 32, 33, 34,
+	35, 35, 36, 37, 38, 39, 39, 40,
+	41, 42, 43, 44, 45, 46, 47, 48,
+	49, 50, 51, 52, 53, 54, 55, 56,
+	57, 58, 59, 60, 61, 62, 64, 65,
+	66, 67, 68, 70, 71, 72, 73, 75,
+	76, 77, 79, 80, 81, 83, 84, 86,
+	87, 88, 90, 91, 93, 94, 96, 97,
+	99, 101, 102, 104, 105, 107, 109, 110,
+	112, 114, 115, 117, 119, 121, 122, 124,
+	126, 128, 130, 132, 134, 135, 137, 139,
+	141, 143, 145, 147, 149, 151, 153, 155,
+	158, 160, 162, 164, 166, 168, 171, 173,
+	175, 177, 180, 182, 184, 187, 189, 191,
+	194, 196, 199, 201, 204, 206, 209, 211,
+	214, 216, 219, 222, 224, 227, 230, 232,
+	235, 238, 241, 244, 246, 249, 252, 255,
+};
+
+static const u16 xgamma8_30[GAMMA8_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 2,
+	2, 2, 2, 2, 2, 2, 2, 3,
+	3, 3, 3, 3, 3, 3, 4, 4,
+	4, 4, 4, 5, 5, 5, 5, 6,
+	6, 6, 6, 6, 7, 7, 7, 8,
+	8, 8, 8, 9, 9, 9, 10, 10,
+	10, 11, 11, 12, 12, 12, 13, 13,
+	14, 14, 14, 15, 15, 16, 16, 17,
+	17, 18, 18, 19, 19, 20, 20, 21,
+	22, 22, 23, 23, 24, 25, 25, 26,
+	27, 27, 28, 29, 29, 30, 31, 32,
+	32, 33, 34, 35, 35, 36, 37, 38,
+	39, 40, 40, 41, 42, 43, 44, 45,
+	46, 47, 48, 49, 50, 51, 52, 53,
+	54, 55, 56, 57, 58, 60, 61, 62,
+	63, 64, 65, 67, 68, 69, 70, 72,
+	73, 74, 76, 77, 78, 80, 81, 82,
+	84, 85, 87, 88, 90, 91, 93, 94,
+	96, 97, 99, 101, 102, 104, 105, 107,
+	109, 111, 112, 114, 116, 118, 119, 121,
+	123, 125, 127, 129, 131, 132, 134, 136,
+	138, 140, 142, 144, 147, 149, 151, 153,
+	155, 157, 159, 162, 164, 166, 168, 171,
+	173, 175, 178, 180, 182, 185, 187, 190,
+	192, 195, 197, 200, 202, 205, 207, 210,
+	213, 215, 218, 221, 223, 226, 229, 232,
+	235, 237, 240, 243, 246, 249, 252, 255,
+};
+
+static const u16 xgamma8_31[GAMMA8_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1,
+	1, 2, 2, 2, 2, 2, 2, 2,
+	2, 2, 3, 3, 3, 3, 3, 3,
+	4, 4, 4, 4, 4, 4, 5, 5,
+	5, 5, 6, 6, 6, 6, 6, 7,
+	7, 7, 8, 8, 8, 8, 9, 9,
+	9, 10, 10, 10, 11, 11, 12, 12,
+	12, 13, 13, 14, 14, 14, 15, 15,
+	16, 16, 17, 17, 18, 18, 19, 19,
+	20, 20, 21, 22, 22, 23, 23, 24,
+	25, 25, 26, 27, 27, 28, 29, 29,
+	30, 31, 32, 32, 33, 34, 35, 36,
+	36, 37, 38, 39, 40, 41, 42, 42,
+	43, 44, 45, 46, 47, 48, 49, 50,
+	51, 52, 53, 54, 56, 57, 58, 59,
+	60, 61, 62, 64, 65, 66, 67, 69,
+	70, 71, 73, 74, 75, 77, 78, 79,
+	81, 82, 84, 85, 87, 88, 90, 91,
+	93, 94, 96, 97, 99, 101, 102, 104,
+	106, 108, 109, 111, 113, 115, 116, 118,
+	120, 122, 124, 126, 128, 130, 132, 134,
+	136, 138, 140, 142, 144, 146, 148, 150,
+	152, 155, 157, 159, 161, 164, 166, 168,
+	171, 173, 175, 178, 180, 183, 185, 188,
+	190, 193, 195, 198, 201, 203, 206, 209,
+	211, 214, 217, 220, 222, 225, 228, 231,
+	234, 237, 240, 243, 246, 249, 252, 255,
+};
+
+static const u16 xgamma8_32[GAMMA8_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 2, 2, 2, 2,
+	2, 2, 2, 2, 2, 3, 3, 3,
+	3, 3, 3, 4, 4, 4, 4, 4,
+	4, 5, 5, 5, 5, 6, 6, 6,
+	6, 6, 7, 7, 7, 8, 8, 8,
+	8, 9, 9, 9, 10, 10, 10, 11,
+	11, 12, 12, 12, 13, 13, 14, 14,
+	14, 15, 15, 16, 16, 17, 17, 18,
+	18, 19, 19, 20, 21, 21, 22, 22,
+	23, 23, 24, 25, 25, 26, 27, 27,
+	28, 29, 30, 30, 31, 32, 33, 33,
+	34, 35, 36, 37, 37, 38, 39, 40,
+	41, 42, 43, 44, 45, 46, 47, 48,
+	49, 50, 51, 52, 53, 54, 55, 56,
+	57, 59, 60, 61, 62, 63, 65, 66,
+	67, 68, 70, 71, 72, 74, 75, 76,
+	78, 79, 81, 82, 84, 85, 87, 88,
+	90, 91, 93, 95, 96, 98, 99, 101,
+	103, 105, 106, 108, 110, 112, 113, 115,
+	117, 119, 121, 123, 125, 127, 129, 131,
+	133, 135, 137, 139, 141, 143, 146, 148,
+	150, 152, 154, 157, 159, 161, 164, 166,
+	168, 171, 173, 176, 178, 181, 183, 186,
+	188, 191, 194, 196, 199, 202, 204, 207,
+	210, 213, 216, 219, 221, 224, 227, 230,
+	233, 236, 239, 242, 246, 249, 252, 255,
+};
+
+static const u16 xgamma8_33[GAMMA8_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 1,
+	1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 2, 2,
+	2, 2, 2, 2, 2, 2, 2, 3,
+	3, 3, 3, 3, 3, 3, 4, 4,
+	4, 4, 4, 4, 5, 5, 5, 5,
+	6, 6, 6, 6, 7, 7, 7, 7,
+	8, 8, 8, 9, 9, 9, 9, 10,
+	10, 11, 11, 11, 12, 12, 12, 13,
+	13, 14, 14, 15, 15, 15, 16, 16,
+	17, 17, 18, 18, 19, 19, 20, 21,
+	21, 22, 22, 23, 24, 24, 25, 26,
+	26, 27, 28, 28, 29, 30, 31, 31,
+	32, 33, 34, 34, 35, 36, 37, 38,
+	39, 40, 40, 41, 42, 43, 44, 45,
+	46, 47, 48, 49, 50, 51, 53, 54,
+	55, 56, 57, 58, 59, 61, 62, 63,
+	64, 66, 67, 68, 70, 71, 72, 74,
+	75, 76, 78, 79, 81, 82, 84, 85,
+	87, 88, 90, 92, 93, 95, 97, 98,
+	100, 102, 103, 105, 107, 109, 111, 113,
+	114, 116, 118, 120, 122, 124, 126, 128,
+	130, 132, 134, 136, 139, 141, 143, 145,
+	147, 150, 152, 154, 157, 159, 161, 164,
+	166, 169, 171, 174, 176, 179, 181, 184,
+	187, 189, 192, 195, 198, 200, 203, 206,
+	209, 212, 215, 217, 220, 223, 226, 230,
+	233, 236, 239, 242, 245, 248, 252, 255,
+};
+
+static const u16 xgamma8_34[GAMMA8_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1,
+	1, 2, 2, 2, 2, 2, 2, 2,
+	2, 2, 3, 3, 3, 3, 3, 3,
+	3, 4, 4, 4, 4, 4, 5, 5,
+	5, 5, 5, 6, 6, 6, 6, 7,
+	7, 7, 7, 8, 8, 8, 9, 9,
+	9, 10, 10, 10, 11, 11, 11, 12,
+	12, 12, 13, 13, 14, 14, 15, 15,
+	16, 16, 17, 17, 18, 18, 19, 19,
+	20, 20, 21, 21, 22, 23, 23, 24,
+	24, 25, 26, 26, 27, 28, 29, 29,
+	30, 31, 32, 32, 33, 34, 35, 36,
+	37, 37, 38, 39, 40, 41, 42, 43,
+	44, 45, 46, 47, 48, 49, 50, 51,
+	52, 53, 55, 56, 57, 58, 59, 60,
+	62, 63, 64, 66, 67, 68, 70, 71,
+	72, 74, 75, 77, 78, 80, 81, 83,
+	84, 86, 87, 89, 90, 92, 94, 95,
+	97, 99, 101, 102, 104, 106, 108, 110,
+	112, 114, 115, 117, 119, 121, 123, 125,
+	128, 130, 132, 134, 136, 138, 141, 143,
+	145, 147, 150, 152, 154, 157, 159, 162,
+	164, 167, 169, 172, 174, 177, 180, 182,
+	185, 188, 190, 193, 196, 199, 202, 205,
+	208, 210, 213, 216, 219, 223, 226, 229,
+	232, 235, 238, 242, 245, 248, 252, 255,
+};
+
+static const u16 xgamma8_35[GAMMA8_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 2, 2, 2, 2, 2,
+	2, 2, 2, 2, 2, 3, 3, 3,
+	3, 3, 3, 4, 4, 4, 4, 4,
+	4, 5, 5, 5, 5, 5, 6, 6,
+	6, 6, 7, 7, 7, 7, 8, 8,
+	8, 9, 9, 9, 10, 10, 10, 11,
+	11, 11, 12, 12, 13, 13, 13, 14,
+	14, 15, 15, 16, 16, 17, 17, 18,
+	18, 19, 19, 20, 20, 21, 22, 22,
+	23, 23, 24, 25, 25, 26, 27, 28,
+	28, 29, 30, 30, 31, 32, 33, 34,
+	35, 35, 36, 37, 38, 39, 40, 41,
+	42, 43, 44, 45, 46, 47, 48, 49,
+	50, 51, 52, 53, 54, 56, 57, 58,
+	59, 60, 62, 63, 64, 66, 67, 68,
+	70, 71, 72, 74, 75, 77, 78, 80,
+	81, 83, 85, 86, 88, 89, 91, 93,
+	94, 96, 98, 100, 102, 103, 105, 107,
+	109, 111, 113, 115, 117, 119, 121, 123,
+	125, 127, 129, 131, 134, 136, 138, 140,
+	143, 145, 147, 150, 152, 155, 157, 159,
+	162, 165, 167, 170, 172, 175, 178, 180,
+	183, 186, 189, 192, 194, 197, 200, 203,
+	206, 209, 212, 215, 219, 222, 225, 228,
+	231, 235, 238, 241, 245, 248, 252, 255,
+};
+
+static const u16 xgamma8_36[GAMMA8_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 2, 2,
+	2, 2, 2, 2, 2, 2, 2, 3,
+	3, 3, 3, 3, 3, 3, 4, 4,
+	4, 4, 4, 4, 5, 5, 5, 5,
+	6, 6, 6, 6, 6, 7, 7, 7,
+	8, 8, 8, 8, 9, 9, 9, 10,
+	10, 10, 11, 11, 12, 12, 12, 13,
+	13, 14, 14, 15, 15, 15, 16, 16,
+	17, 17, 18, 18, 19, 20, 20, 21,
+	21, 22, 23, 23, 24, 24, 25, 26,
+	27, 27, 28, 29, 29, 30, 31, 32,
+	33, 33, 34, 35, 36, 37, 38, 39,
+	40, 41, 42, 42, 43, 44, 46, 47,
+	48, 49, 50, 51, 52, 53, 54, 56,
+	57, 58, 59, 61, 62, 63, 64, 66,
+	67, 69, 70, 71, 73, 74, 76, 77,
+	79, 80, 82, 83, 85, 87, 88, 90,
+	92, 94, 95, 97, 99, 101, 103, 104,
+	106, 108, 110, 112, 114, 116, 118, 120,
+	122, 125, 127, 129, 131, 133, 136, 138,
+	140, 143, 145, 147, 150, 152, 155, 157,
+	160, 162, 165, 168, 170, 173, 176, 179,
+	181, 184, 187, 190, 193, 196, 199, 202,
+	205, 208, 211, 214, 218, 221, 224, 227,
+	231, 234, 237, 241, 244, 248, 251, 255,
+};
+
+static const u16 xgamma8_37[GAMMA8_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1,
+	2, 2, 2, 2, 2, 2, 2, 2,
+	2, 2, 3, 3, 3, 3, 3, 3,
+	3, 4, 4, 4, 4, 4, 5, 5,
+	5, 5, 5, 6, 6, 6, 6, 7,
+	7, 7, 7, 8, 8, 8, 9, 9,
+	9, 10, 10, 10, 11, 11, 11, 12,
+	12, 13, 13, 13, 14, 14, 15, 15,
+	16, 16, 17, 17, 18, 18, 19, 19,
+	20, 20, 21, 22, 22, 23, 24, 24,
+	25, 26, 26, 27, 28, 28, 29, 30,
+	31, 32, 32, 33, 34, 35, 36, 37,
+	38, 39, 39, 40, 41, 42, 43, 44,
+	45, 47, 48, 49, 50, 51, 52, 53,
+	54, 56, 57, 58, 59, 61, 62, 63,
+	65, 66, 67, 69, 70, 72, 73, 75,
+	76, 78, 79, 81, 83, 84, 86, 88,
+	89, 91, 93, 95, 96, 98, 100, 102,
+	104, 106, 108, 110, 112, 114, 116, 118,
+	120, 122, 124, 127, 129, 131, 133, 136,
+	138, 140, 143, 145, 148, 150, 153, 155,
+	158, 160, 163, 166, 169, 171, 174, 177,
+	180, 183, 186, 188, 191, 194, 198, 201,
+	204, 207, 210, 213, 217, 220, 223, 227,
+	230, 233, 237, 241, 244, 248, 251, 255,
+};
+
+static const u16 xgamma8_38[GAMMA8_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 2, 2, 2, 2, 2,
+	2, 2, 2, 2, 3, 3, 3, 3,
+	3, 3, 3, 4, 4, 4, 4, 4,
+	4, 5, 5, 5, 5, 6, 6, 6,
+	6, 6, 7, 7, 7, 8, 8, 8,
+	8, 9, 9, 9, 10, 10, 10, 11,
+	11, 12, 12, 12, 13, 13, 14, 14,
+	15, 15, 15, 16, 16, 17, 18, 18,
+	19, 19, 20, 20, 21, 21, 22, 23,
+	23, 24, 25, 25, 26, 27, 28, 28,
+	29, 30, 31, 31, 32, 33, 34, 35,
+	36, 37, 38, 38, 39, 40, 41, 42,
+	43, 44, 45, 47, 48, 49, 50, 51,
+	52, 53, 55, 56, 57, 58, 60, 61,
+	62, 64, 65, 66, 68, 69, 71, 72,
+	74, 75, 77, 78, 80, 82, 83, 85,
+	87, 88, 90, 92, 94, 96, 98, 99,
+	101, 103, 105, 107, 109, 111, 113, 115,
+	118, 120, 122, 124, 126, 129, 131, 133,
+	136, 138, 141, 143, 146, 148, 151, 153,
+	156, 158, 161, 164, 167, 169, 172, 175,
+	178, 181, 184, 187, 190, 193, 196, 199,
+	203, 206, 209, 212, 216, 219, 222, 226,
+	229, 233, 237, 240, 244, 247, 251, 255,
+};
+
+static const u16 xgamma8_39[GAMMA8_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 2, 2, 2,
+	2, 2, 2, 2, 2, 2, 3, 3,
+	3, 3, 3, 3, 3, 4, 4, 4,
+	4, 4, 4, 5, 5, 5, 5, 5,
+	6, 6, 6, 6, 7, 7, 7, 7,
+	8, 8, 8, 9, 9, 9, 10, 10,
+	10, 11, 11, 11, 12, 12, 13, 13,
+	13, 14, 14, 15, 15, 16, 16, 17,
+	17, 18, 18, 19, 20, 20, 21, 21,
+	22, 23, 23, 24, 25, 25, 26, 27,
+	27, 28, 29, 30, 31, 31, 32, 33,
+	34, 35, 36, 37, 38, 38, 39, 40,
+	41, 42, 43, 45, 46, 47, 48, 49,
+	50, 51, 52, 54, 55, 56, 57, 59,
+	60, 61, 63, 64, 66, 67, 68, 70,
+	71, 73, 74, 76, 78, 79, 81, 83,
+	84, 86, 88, 90, 91, 93, 95, 97,
+	99, 101, 103, 105, 107, 109, 111, 113,
+	115, 117, 120, 122, 124, 126, 129, 131,
+	133, 136, 138, 141, 143, 146, 149, 151,
+	154, 157, 159, 162, 165, 168, 171, 173,
+	176, 179, 182, 185, 189, 192, 195, 198,
+	201, 205, 208, 211, 215, 218, 222, 225,
+	229, 232, 236, 240, 243, 247, 251, 255,
+};
+
+static const u16 xgamma8_40[GAMMA8_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 2,
+	2, 2, 2, 2, 2, 2, 2, 2,
+	2, 3, 3, 3, 3, 3, 3, 3,
+	4, 4, 4, 4, 4, 5, 5, 5,
+	5, 5, 6, 6, 6, 6, 7, 7,
+	7, 7, 8, 8, 8, 9, 9, 9,
+	9, 10, 10, 11, 11, 11, 12, 12,
+	13, 13, 13, 14, 14, 15, 15, 16,
+	16, 17, 17, 18, 18, 19, 19, 20,
+	21, 21, 22, 23, 23, 24, 25, 25,
+	26, 27, 27, 28, 29, 30, 31, 31,
+	32, 33, 34, 35, 36, 37, 38, 39,
+	40, 41, 42, 43, 44, 45, 46, 47,
+	48, 49, 50, 52, 53, 54, 55, 57,
+	58, 59, 61, 62, 63, 65, 66, 68,
+	69, 71, 72, 74, 75, 77, 79, 80,
+	82, 84, 85, 87, 89, 91, 93, 95,
+	96, 98, 100, 102, 104, 107, 109, 111,
+	113, 115, 117, 120, 122, 124, 126, 129,
+	131, 134, 136, 139, 141, 144, 146, 149,
+	152, 155, 157, 160, 163, 166, 169, 172,
+	175, 178, 181, 184, 187, 190, 194, 197,
+	200, 203, 207, 210, 214, 217, 221, 224,
+	228, 232, 236, 239, 243, 247, 251, 255,
+};
+
+static const u16 *xgamma8_curves[GAMMA_CURVE_LENGTH] =  {
+	&xgamma8_01[0],
+	&xgamma8_02[0],
+	&xgamma8_03[0],
+	&xgamma8_04[0],
+	&xgamma8_05[0],
+	&xgamma8_06[0],
+	&xgamma8_07[0],
+	&xgamma8_08[0],
+	&xgamma8_09[0],
+	&xgamma8_10[0],
+	&xgamma8_11[0],
+	&xgamma8_12[0],
+	&xgamma8_13[0],
+	&xgamma8_14[0],
+	&xgamma8_15[0],
+	&xgamma8_16[0],
+	&xgamma8_17[0],
+	&xgamma8_18[0],
+	&xgamma8_19[0],
+	&xgamma8_20[0],
+	&xgamma8_21[0],
+	&xgamma8_22[0],
+	&xgamma8_23[0],
+	&xgamma8_24[0],
+	&xgamma8_25[0],
+	&xgamma8_26[0],
+	&xgamma8_27[0],
+	&xgamma8_28[0],
+	&xgamma8_29[0],
+	&xgamma8_30[0],
+	&xgamma8_31[0],
+	&xgamma8_32[0],
+	&xgamma8_33[0],
+	&xgamma8_34[0],
+	&xgamma8_35[0],
+	&xgamma8_36[0],
+	&xgamma8_37[0],
+	&xgamma8_38[0],
+	&xgamma8_39[0],
+	&xgamma8_40[0],
+};
+
+#define GAMMA_BPC_10		(10)
+#define GAMMA10_TABLE_LENGTH	BIT(GAMMA_BPC_10)
+static const u16 xgamma10_01[GAMMA10_TABLE_LENGTH] = {
+	0, 512, 548, 571, 588, 601, 612, 621, 630, 637, 644,
+	650, 656, 661, 666, 671, 675, 679, 683, 687, 690, 694,
+	697, 700, 703, 706, 709, 711, 714, 716, 719, 721, 723,
+	726, 728, 730, 732, 734, 736, 738, 740, 742, 743, 745,
+	747, 749, 750, 752, 753, 755, 756, 758, 759, 761, 762,
+	764, 765, 766, 768, 769, 770, 772, 773, 774, 775, 777,
+	778, 779, 780, 781, 782, 783, 785, 786, 787, 788, 789,
+	790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800,
+	800, 801, 802, 803, 804, 805, 806, 807, 807, 808, 809,
+	810, 811, 812, 812, 813, 814, 815, 815, 816, 817, 818,
+	819, 819, 820, 821, 821, 822, 823, 824, 824, 825, 826,
+	826, 827, 828, 828, 829, 830, 830, 831, 832, 832, 833,
+	834, 834, 835, 835, 836, 837, 837, 838, 838, 839, 840,
+	840, 841, 841, 842, 843, 843, 844, 844, 845, 845, 846,
+	847, 847, 848, 848, 849, 849, 850, 850, 851, 851, 852,
+	852, 853, 853, 854, 854, 855, 855, 856, 856, 857, 857,
+	858, 858, 859, 859, 860, 860, 861, 861, 862, 862, 863,
+	863, 864, 864, 864, 865, 865, 866, 866, 867, 867, 868,
+	868, 869, 869, 869, 870, 870, 871, 871, 872, 872, 872,
+	873, 873, 874, 874, 874, 875, 875, 876, 876, 876, 877,
+	877, 878, 878, 878, 879, 879, 880, 880, 880, 881, 881,
+	882, 882, 882, 883, 883, 883, 884, 884, 885, 885, 885,
+	886, 886, 886, 887, 887, 887, 888, 888, 889, 889, 889,
+	890, 890, 890, 891, 891, 891, 892, 892, 892, 893, 893,
+	893, 894, 894, 894, 895, 895, 895, 896, 896, 896, 897,
+	897, 897, 898, 898, 898, 899, 899, 899, 900, 900, 900,
+	901, 901, 901, 902, 902, 902, 902, 903, 903, 903, 904,
+	904, 904, 905, 905, 905, 906, 906, 906, 906, 907, 907,
+	907, 908, 908, 908, 908, 909, 909, 909, 910, 910, 910,
+	910, 911, 911, 911, 912, 912, 912, 912, 913, 913, 913,
+	914, 914, 914, 914, 915, 915, 915, 915, 916, 916, 916,
+	917, 917, 917, 917, 918, 918, 918, 918, 919, 919, 919,
+	919, 920, 920, 920, 921, 921, 921, 921, 922, 922, 922,
+	922, 923, 923, 923, 923, 924, 924, 924, 924, 925, 925,
+	925, 925, 926, 926, 926, 926, 927, 927, 927, 927, 928,
+	928, 928, 928, 928, 929, 929, 929, 929, 930, 930, 930,
+	930, 931, 931, 931, 931, 932, 932, 932, 932, 932, 933,
+	933, 933, 933, 934, 934, 934, 934, 935, 935, 935, 935,
+	935, 936, 936, 936, 936, 937, 937, 937, 937, 937, 938,
+	938, 938, 938, 939, 939, 939, 939, 939, 940, 940, 940,
+	940, 940, 941, 941, 941, 941, 942, 942, 942, 942, 942,
+	943, 943, 943, 943, 943, 944, 944, 944, 944, 944, 945,
+	945, 945, 945, 945, 946, 946, 946, 946, 946, 947, 947,
+	947, 947, 947, 948, 948, 948, 948, 948, 949, 949, 949,
+	949, 949, 950, 950, 950, 950, 950, 951, 951, 951, 951,
+	951, 952, 952, 952, 952, 952, 953, 953, 953, 953, 953,
+	953, 954, 954, 954, 954, 954, 955, 955, 955, 955, 955,
+	956, 956, 956, 956, 956, 956, 957, 957, 957, 957, 957,
+	958, 958, 958, 958, 958, 958, 959, 959, 959, 959, 959,
+	960, 960, 960, 960, 960, 960, 961, 961, 961, 961, 961,
+	961, 962, 962, 962, 962, 962, 962, 963, 963, 963, 963,
+	963, 964, 964, 964, 964, 964, 964, 965, 965, 965, 965,
+	965, 965, 966, 966, 966, 966, 966, 966, 967, 967, 967,
+	967, 967, 967, 968, 968, 968, 968, 968, 968, 969, 969,
+	969, 969, 969, 969, 970, 970, 970, 970, 970, 970, 970,
+	971, 971, 971, 971, 971, 971, 972, 972, 972, 972, 972,
+	972, 973, 973, 973, 973, 973, 973, 974, 974, 974, 974,
+	974, 974, 974, 975, 975, 975, 975, 975, 975, 976, 976,
+	976, 976, 976, 976, 976, 977, 977, 977, 977, 977, 977,
+	977, 978, 978, 978, 978, 978, 978, 979, 979, 979, 979,
+	979, 979, 979, 980, 980, 980, 980, 980, 980, 980, 981,
+	981, 981, 981, 981, 981, 981, 982, 982, 982, 982, 982,
+	982, 982, 983, 983, 983, 983, 983, 983, 983, 984, 984,
+	984, 984, 984, 984, 984, 985, 985, 985, 985, 985, 985,
+	985, 986, 986, 986, 986, 986, 986, 986, 987, 987, 987,
+	987, 987, 987, 987, 988, 988, 988, 988, 988, 988, 988,
+	989, 989, 989, 989, 989, 989, 989, 989, 990, 990, 990,
+	990, 990, 990, 990, 991, 991, 991, 991, 991, 991, 991,
+	991, 992, 992, 992, 992, 992, 992, 992, 993, 993, 993,
+	993, 993, 993, 993, 993, 994, 994, 994, 994, 994, 994,
+	994, 994, 995, 995, 995, 995, 995, 995, 995, 996, 996,
+	996, 996, 996, 996, 996, 996, 997, 997, 997, 997, 997,
+	997, 997, 997, 998, 998, 998, 998, 998, 998, 998, 998,
+	999, 999, 999, 999, 999, 999, 999, 999, 1000, 1000, 1000,
+	1000, 1000, 1000, 1000, 1000, 1000, 1001, 1001, 1001, 1001, 1001,
+	1001, 1001, 1001, 1002, 1002, 1002, 1002, 1002, 1002, 1002, 1002,
+	1003, 1003, 1003, 1003, 1003, 1003, 1003, 1003, 1004, 1004, 1004,
+	1004, 1004, 1004, 1004, 1004, 1004, 1005, 1005, 1005, 1005, 1005,
+	1005, 1005, 1005, 1006, 1006, 1006, 1006, 1006, 1006, 1006, 1006,
+	1006, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1007, 1008,
+	1008, 1008, 1008, 1008, 1008, 1008, 1008, 1009, 1009, 1009, 1009,
+	1009, 1009, 1009, 1009, 1009, 1010, 1010, 1010, 1010, 1010, 1010,
+	1010, 1010, 1010, 1011, 1011, 1011, 1011, 1011, 1011, 1011, 1011,
+	1011, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1013,
+	1013, 1013, 1013, 1013, 1013, 1013, 1013, 1013, 1014, 1014, 1014,
+	1014, 1014, 1014, 1014, 1014, 1014, 1014, 1015, 1015, 1015, 1015,
+	1015, 1015, 1015, 1015, 1015, 1016, 1016, 1016, 1016, 1016, 1016,
+	1016, 1016, 1016, 1017, 1017, 1017, 1017, 1017, 1017, 1017, 1017,
+	1017, 1017, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018, 1018,
+	1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1019, 1020,
+	1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1020, 1021, 1021,
+	1021, 1021, 1021, 1021, 1021, 1021, 1021, 1021, 1022, 1022, 1022,
+	1022, 1022, 1022, 1022, 1022, 1022, 1022, 1023, 1023, 1023, 1023,
+	1023,
+};
+
+static const u16 xgamma10_02[GAMMA10_TABLE_LENGTH] = {
+	0, 256, 294, 319, 338, 353, 366, 378, 388, 397, 405,
+	413, 420, 427, 434, 440, 445, 451, 456, 461, 466, 470,
+	475, 479, 483, 487, 491, 495, 498, 502, 505, 508, 512,
+	515, 518, 521, 524, 527, 529, 532, 535, 538, 540, 543,
+	545, 548, 550, 552, 555, 557, 559, 562, 564, 566, 568,
+	570, 572, 574, 576, 578, 580, 582, 584, 586, 588, 589,
+	591, 593, 595, 597, 598, 600, 602, 603, 605, 607, 608,
+	610, 611, 613, 614, 616, 618, 619, 621, 622, 623, 625,
+	626, 628, 629, 631, 632, 633, 635, 636, 637, 639, 640,
+	641, 643, 644, 645, 646, 648, 649, 650, 651, 653, 654,
+	655, 656, 657, 658, 660, 661, 662, 663, 664, 665, 666,
+	668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678,
+	679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689,
+	690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700,
+	700, 701, 702, 703, 704, 705, 706, 707, 708, 708, 709,
+	710, 711, 712, 713, 714, 714, 715, 716, 717, 718, 719,
+	719, 720, 721, 722, 723, 723, 724, 725, 726, 727, 727,
+	728, 729, 730, 731, 731, 732, 733, 734, 734, 735, 736,
+	737, 737, 738, 739, 740, 740, 741, 742, 742, 743, 744,
+	745, 745, 746, 747, 747, 748, 749, 750, 750, 751, 752,
+	752, 753, 754, 754, 755, 756, 756, 757, 758, 758, 759,
+	760, 760, 761, 762, 762, 763, 764, 764, 765, 765, 766,
+	767, 767, 768, 769, 769, 770, 771, 771, 772, 772, 773,
+	774, 774, 775, 775, 776, 777, 777, 778, 778, 779, 780,
+	780, 781, 781, 782, 783, 783, 784, 784, 785, 785, 786,
+	787, 787, 788, 788, 789, 789, 790, 791, 791, 792, 792,
+	793, 793, 794, 794, 795, 796, 796, 797, 797, 798, 798,
+	799, 799, 800, 800, 801, 801, 802, 803, 803, 804, 804,
+	805, 805, 806, 806, 807, 807, 808, 808, 809, 809, 810,
+	810, 811, 811, 812, 812, 813, 813, 814, 814, 815, 815,
+	816, 816, 817, 817, 818, 818, 819, 819, 820, 820, 821,
+	821, 822, 822, 823, 823, 824, 824, 825, 825, 825, 826,
+	826, 827, 827, 828, 828, 829, 829, 830, 830, 831, 831,
+	832, 832, 832, 833, 833, 834, 834, 835, 835, 836, 836,
+	837, 837, 837, 838, 838, 839, 839, 840, 840, 841, 841,
+	841, 842, 842, 843, 843, 844, 844, 844, 845, 845, 846,
+	846, 847, 847, 847, 848, 848, 849, 849, 850, 850, 850,
+	851, 851, 852, 852, 852, 853, 853, 854, 854, 855, 855,
+	855, 856, 856, 857, 857, 857, 858, 858, 859, 859, 859,
+	860, 860, 861, 861, 861, 862, 862, 863, 863, 863, 864,
+	864, 865, 865, 865, 866, 866, 866, 867, 867, 868, 868,
+	868, 869, 869, 870, 870, 870, 871, 871, 871, 872, 872,
+	873, 873, 873, 874, 874, 875, 875, 875, 876, 876, 876,
+	877, 877, 877, 878, 878, 879, 879, 879, 880, 880, 880,
+	881, 881, 882, 882, 882, 883, 883, 883, 884, 884, 884,
+	885, 885, 885, 886, 886, 887, 887, 887, 888, 888, 888,
+	889, 889, 889, 890, 890, 890, 891, 891, 891, 892, 892,
+	892, 893, 893, 894, 894, 894, 895, 895, 895, 896, 896,
+	896, 897, 897, 897, 898, 898, 898, 899, 899, 899, 900,
+	900, 900, 901, 901, 901, 902, 902, 902, 903, 903, 903,
+	904, 904, 904, 905, 905, 905, 906, 906, 906, 907, 907,
+	907, 908, 908, 908, 908, 909, 909, 909, 910, 910, 910,
+	911, 911, 911, 912, 912, 912, 913, 913, 913, 914, 914,
+	914, 914, 915, 915, 915, 916, 916, 916, 917, 917, 917,
+	918, 918, 918, 919, 919, 919, 919, 920, 920, 920, 921,
+	921, 921, 922, 922, 922, 923, 923, 923, 923, 924, 924,
+	924, 925, 925, 925, 926, 926, 926, 926, 927, 927, 927,
+	928, 928, 928, 928, 929, 929, 929, 930, 930, 930, 931,
+	931, 931, 931, 932, 932, 932, 933, 933, 933, 933, 934,
+	934, 934, 935, 935, 935, 935, 936, 936, 936, 937, 937,
+	937, 937, 938, 938, 938, 939, 939, 939, 939, 940, 940,
+	940, 941, 941, 941, 941, 942, 942, 942, 942, 943, 943,
+	943, 944, 944, 944, 944, 945, 945, 945, 946, 946, 946,
+	946, 947, 947, 947, 947, 948, 948, 948, 949, 949, 949,
+	949, 950, 950, 950, 950, 951, 951, 951, 951, 952, 952,
+	952, 953, 953, 953, 953, 954, 954, 954, 954, 955, 955,
+	955, 955, 956, 956, 956, 956, 957, 957, 957, 958, 958,
+	958, 958, 959, 959, 959, 959, 960, 960, 960, 960, 961,
+	961, 961, 961, 962, 962, 962, 962, 963, 963, 963, 963,
+	964, 964, 964, 964, 965, 965, 965, 965, 966, 966, 966,
+	966, 967, 967, 967, 967, 968, 968, 968, 968, 969, 969,
+	969, 969, 970, 970, 970, 970, 971, 971, 971, 971, 972,
+	972, 972, 972, 973, 973, 973, 973, 974, 974, 974, 974,
+	975, 975, 975, 975, 976, 976, 976, 976, 977, 977, 977,
+	977, 978, 978, 978, 978, 978, 979, 979, 979, 979, 980,
+	980, 980, 980, 981, 981, 981, 981, 982, 982, 982, 982,
+	983, 983, 983, 983, 983, 984, 984, 984, 984, 985, 985,
+	985, 985, 986, 986, 986, 986, 986, 987, 987, 987, 987,
+	988, 988, 988, 988, 989, 989, 989, 989, 989, 990, 990,
+	990, 990, 991, 991, 991, 991, 992, 992, 992, 992, 992,
+	993, 993, 993, 993, 994, 994, 994, 994, 994, 995, 995,
+	995, 995, 996, 996, 996, 996, 996, 997, 997, 997, 997,
+	998, 998, 998, 998, 998, 999, 999, 999, 999, 1000, 1000,
+	1000, 1000, 1000, 1001, 1001, 1001, 1001, 1002, 1002, 1002, 1002,
+	1002, 1003, 1003, 1003, 1003, 1003, 1004, 1004, 1004, 1004, 1005,
+	1005, 1005, 1005, 1005, 1006, 1006, 1006, 1006, 1006, 1007, 1007,
+	1007, 1007, 1008, 1008, 1008, 1008, 1008, 1009, 1009, 1009, 1009,
+	1009, 1010, 1010, 1010, 1010, 1010, 1011, 1011, 1011, 1011, 1012,
+	1012, 1012, 1012, 1012, 1013, 1013, 1013, 1013, 1013, 1014, 1014,
+	1014, 1014, 1014, 1015, 1015, 1015, 1015, 1015, 1016, 1016, 1016,
+	1016, 1017, 1017, 1017, 1017, 1017, 1018, 1018, 1018, 1018, 1018,
+	1019, 1019, 1019, 1019, 1019, 1020, 1020, 1020, 1020, 1020, 1021,
+	1021, 1021, 1021, 1021, 1022, 1022, 1022, 1022, 1022, 1023, 1023,
+	1023,
+};
+
+static const u16 xgamma10_03[GAMMA10_TABLE_LENGTH] = {
+	0, 128, 157, 178, 194, 207, 219, 229, 239, 247, 255,
+	263, 270, 276, 282, 288, 294, 299, 304, 309, 314, 319,
+	323, 328, 332, 336, 340, 344, 348, 351, 355, 358, 362,
+	365, 368, 372, 375, 378, 381, 384, 387, 390, 393, 395,
+	398, 401, 403, 406, 409, 411, 414, 416, 419, 421, 423,
+	426, 428, 430, 432, 435, 437, 439, 441, 443, 445, 447,
+	450, 452, 454, 456, 458, 460, 461, 463, 465, 467, 469,
+	471, 473, 474, 476, 478, 480, 482, 483, 485, 487, 488,
+	490, 492, 493, 495, 497, 498, 500, 501, 503, 505, 506,
+	508, 509, 511, 512, 514, 515, 517, 518, 520, 521, 523,
+	524, 525, 527, 528, 530, 531, 532, 534, 535, 537, 538,
+	539, 541, 542, 543, 544, 546, 547, 548, 550, 551, 552,
+	553, 555, 556, 557, 558, 560, 561, 562, 563, 565, 566,
+	567, 568, 569, 570, 572, 573, 574, 575, 576, 577, 579,
+	580, 581, 582, 583, 584, 585, 586, 587, 589, 590, 591,
+	592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602,
+	603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613,
+	614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624,
+	625, 626, 627, 628, 629, 630, 631, 632, 633, 633, 634,
+	635, 636, 637, 638, 639, 640, 641, 642, 642, 643, 644,
+	645, 646, 647, 648, 649, 649, 650, 651, 652, 653, 654,
+	655, 655, 656, 657, 658, 659, 660, 661, 661, 662, 663,
+	664, 665, 665, 666, 667, 668, 669, 670, 670, 671, 672,
+	673, 674, 674, 675, 676, 677, 677, 678, 679, 680, 681,
+	681, 682, 683, 684, 684, 685, 686, 687, 688, 688, 689,
+	690, 691, 691, 692, 693, 694, 694, 695, 696, 696, 697,
+	698, 699, 699, 700, 701, 702, 702, 703, 704, 704, 705,
+	706, 707, 707, 708, 709, 709, 710, 711, 712, 712, 713,
+	714, 714, 715, 716, 716, 717, 718, 718, 719, 720, 721,
+	721, 722, 723, 723, 724, 725, 725, 726, 727, 727, 728,
+	729, 729, 730, 731, 731, 732, 733, 733, 734, 734, 735,
+	736, 736, 737, 738, 738, 739, 740, 740, 741, 742, 742,
+	743, 743, 744, 745, 745, 746, 747, 747, 748, 748, 749,
+	750, 750, 751, 752, 752, 753, 753, 754, 755, 755, 756,
+	756, 757, 758, 758, 759, 759, 760, 761, 761, 762, 762,
+	763, 764, 764, 765, 765, 766, 767, 767, 768, 768, 769,
+	770, 770, 771, 771, 772, 772, 773, 774, 774, 775, 775,
+	776, 776, 777, 778, 778, 779, 779, 780, 780, 781, 782,
+	782, 783, 783, 784, 784, 785, 785, 786, 787, 787, 788,
+	788, 789, 789, 790, 790, 791, 792, 792, 793, 793, 794,
+	794, 795, 795, 796, 796, 797, 797, 798, 799, 799, 800,
+	800, 801, 801, 802, 802, 803, 803, 804, 804, 805, 805,
+	806, 806, 807, 808, 808, 809, 809, 810, 810, 811, 811,
+	812, 812, 813, 813, 814, 814, 815, 815, 816, 816, 817,
+	817, 818, 818, 819, 819, 820, 820, 821, 821, 822, 822,
+	823, 823, 824, 824, 825, 825, 826, 826, 827, 827, 828,
+	828, 829, 829, 830, 830, 831, 831, 832, 832, 833, 833,
+	834, 834, 835, 835, 836, 836, 836, 837, 837, 838, 838,
+	839, 839, 840, 840, 841, 841, 842, 842, 843, 843, 844,
+	844, 845, 845, 845, 846, 846, 847, 847, 848, 848, 849,
+	849, 850, 850, 851, 851, 852, 852, 852, 853, 853, 854,
+	854, 855, 855, 856, 856, 857, 857, 857, 858, 858, 859,
+	859, 860, 860, 861, 861, 862, 862, 862, 863, 863, 864,
+	864, 865, 865, 866, 866, 866, 867, 867, 868, 868, 869,
+	869, 869, 870, 870, 871, 871, 872, 872, 873, 873, 873,
+	874, 874, 875, 875, 876, 876, 876, 877, 877, 878, 878,
+	879, 879, 879, 880, 880, 881, 881, 882, 882, 882, 883,
+	883, 884, 884, 885, 885, 885, 886, 886, 887, 887, 887,
+	888, 888, 889, 889, 890, 890, 890, 891, 891, 892, 892,
+	892, 893, 893, 894, 894, 895, 895, 895, 896, 896, 897,
+	897, 897, 898, 898, 899, 899, 899, 900, 900, 901, 901,
+	901, 902, 902, 903, 903, 903, 904, 904, 905, 905, 905,
+	906, 906, 907, 907, 907, 908, 908, 909, 909, 909, 910,
+	910, 911, 911, 911, 912, 912, 913, 913, 913, 914, 914,
+	915, 915, 915, 916, 916, 916, 917, 917, 918, 918, 918,
+	919, 919, 920, 920, 920, 921, 921, 921, 922, 922, 923,
+	923, 923, 924, 924, 925, 925, 925, 926, 926, 926, 927,
+	927, 928, 928, 928, 929, 929, 929, 930, 930, 931, 931,
+	931, 932, 932, 932, 933, 933, 934, 934, 934, 935, 935,
+	935, 936, 936, 936, 937, 937, 938, 938, 938, 939, 939,
+	939, 940, 940, 941, 941, 941, 942, 942, 942, 943, 943,
+	943, 944, 944, 945, 945, 945, 946, 946, 946, 947, 947,
+	947, 948, 948, 948, 949, 949, 950, 950, 950, 951, 951,
+	951, 952, 952, 952, 953, 953, 953, 954, 954, 955, 955,
+	955, 956, 956, 956, 957, 957, 957, 958, 958, 958, 959,
+	959, 959, 960, 960, 960, 961, 961, 962, 962, 962, 963,
+	963, 963, 964, 964, 964, 965, 965, 965, 966, 966, 966,
+	967, 967, 967, 968, 968, 968, 969, 969, 969, 970, 970,
+	970, 971, 971, 971, 972, 972, 972, 973, 973, 973, 974,
+	974, 974, 975, 975, 975, 976, 976, 976, 977, 977, 977,
+	978, 978, 978, 979, 979, 979, 980, 980, 980, 981, 981,
+	981, 982, 982, 982, 983, 983, 983, 984, 984, 984, 985,
+	985, 985, 986, 986, 986, 987, 987, 987, 988, 988, 988,
+	989, 989, 989, 990, 990, 990, 991, 991, 991, 992, 992,
+	992, 993, 993, 993, 994, 994, 994, 994, 995, 995, 995,
+	996, 996, 996, 997, 997, 997, 998, 998, 998, 999, 999,
+	999, 1000, 1000, 1000, 1001, 1001, 1001, 1001, 1002, 1002, 1002,
+	1003, 1003, 1003, 1004, 1004, 1004, 1005, 1005, 1005, 1006, 1006,
+	1006, 1006, 1007, 1007, 1007, 1008, 1008, 1008, 1009, 1009, 1009,
+	1010, 1010, 1010, 1011, 1011, 1011, 1011, 1012, 1012, 1012, 1013,
+	1013, 1013, 1014, 1014, 1014, 1015, 1015, 1015, 1015, 1016, 1016,
+	1016, 1017, 1017, 1017, 1018, 1018, 1018, 1018, 1019, 1019, 1019,
+	1020, 1020, 1020, 1021, 1021, 1021, 1021, 1022, 1022, 1022, 1023,
+	1023,
+};
+
+static const u16 xgamma10_04[GAMMA10_TABLE_LENGTH] = {
+	0, 64, 84, 99, 111, 122, 131, 139, 147, 154, 161,
+	167, 173, 178, 184, 189, 194, 199, 203, 208, 212, 216,
+	220, 224, 228, 232, 235, 239, 243, 246, 249, 253, 256,
+	259, 262, 265, 268, 271, 274, 277, 280, 283, 285, 288,
+	291, 293, 296, 298, 301, 303, 306, 308, 311, 313, 315,
+	318, 320, 322, 325, 327, 329, 331, 333, 335, 338, 340,
+	342, 344, 346, 348, 350, 352, 354, 356, 358, 360, 362,
+	364, 365, 367, 369, 371, 373, 375, 376, 378, 380, 382,
+	383, 385, 387, 389, 390, 392, 394, 395, 397, 399, 400,
+	402, 404, 405, 407, 408, 410, 412, 413, 415, 416, 418,
+	419, 421, 422, 424, 425, 427, 428, 430, 431, 433, 434,
+	436, 437, 438, 440, 441, 443, 444, 445, 447, 448, 450,
+	451, 452, 454, 455, 456, 458, 459, 460, 462, 463, 464,
+	466, 467, 468, 470, 471, 472, 473, 475, 476, 477, 478,
+	480, 481, 482, 483, 485, 486, 487, 488, 489, 491, 492,
+	493, 494, 495, 497, 498, 499, 500, 501, 503, 504, 505,
+	506, 507, 508, 509, 511, 512, 513, 514, 515, 516, 517,
+	518, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529,
+	530, 531, 533, 534, 535, 536, 537, 538, 539, 540, 541,
+	542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552,
+	553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563,
+	564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574,
+	575, 576, 577, 578, 578, 579, 580, 581, 582, 583, 584,
+	585, 586, 587, 588, 589, 590, 591, 591, 592, 593, 594,
+	595, 596, 597, 598, 599, 600, 600, 601, 602, 603, 604,
+	605, 606, 607, 607, 608, 609, 610, 611, 612, 613, 614,
+	614, 615, 616, 617, 618, 619, 620, 620, 621, 622, 623,
+	624, 625, 625, 626, 627, 628, 629, 630, 630, 631, 632,
+	633, 634, 635, 635, 636, 637, 638, 639, 639, 640, 641,
+	642, 643, 643, 644, 645, 646, 647, 647, 648, 649, 650,
+	651, 651, 652, 653, 654, 655, 655, 656, 657, 658, 658,
+	659, 660, 661, 662, 662, 663, 664, 665, 665, 666, 667,
+	668, 668, 669, 670, 671, 671, 672, 673, 674, 674, 675,
+	676, 677, 677, 678, 679, 680, 680, 681, 682, 683, 683,
+	684, 685, 685, 686, 687, 688, 688, 689, 690, 691, 691,
+	692, 693, 693, 694, 695, 696, 696, 697, 698, 698, 699,
+	700, 701, 701, 702, 703, 703, 704, 705, 705, 706, 707,
+	708, 708, 709, 710, 710, 711, 712, 712, 713, 714, 714,
+	715, 716, 717, 717, 718, 719, 719, 720, 721, 721, 722,
+	723, 723, 724, 725, 725, 726, 727, 727, 728, 729, 729,
+	730, 731, 731, 732, 733, 733, 734, 735, 735, 736, 737,
+	737, 738, 739, 739, 740, 740, 741, 742, 742, 743, 744,
+	744, 745, 746, 746, 747, 748, 748, 749, 749, 750, 751,
+	751, 752, 753, 753, 754, 755, 755, 756, 756, 757, 758,
+	758, 759, 760, 760, 761, 761, 762, 763, 763, 764, 765,
+	765, 766, 766, 767, 768, 768, 769, 769, 770, 771, 771,
+	772, 773, 773, 774, 774, 775, 776, 776, 777, 777, 778,
+	779, 779, 780, 780, 781, 782, 782, 783, 783, 784, 785,
+	785, 786, 786, 787, 788, 788, 789, 789, 790, 791, 791,
+	792, 792, 793, 793, 794, 795, 795, 796, 796, 797, 798,
+	798, 799, 799, 800, 800, 801, 802, 802, 803, 803, 804,
+	804, 805, 806, 806, 807, 807, 808, 808, 809, 810, 810,
+	811, 811, 812, 812, 813, 814, 814, 815, 815, 816, 816,
+	817, 818, 818, 819, 819, 820, 820, 821, 821, 822, 823,
+	823, 824, 824, 825, 825, 826, 826, 827, 827, 828, 829,
+	829, 830, 830, 831, 831, 832, 832, 833, 834, 834, 835,
+	835, 836, 836, 837, 837, 838, 838, 839, 839, 840, 841,
+	841, 842, 842, 843, 843, 844, 844, 845, 845, 846, 846,
+	847, 847, 848, 849, 849, 850, 850, 851, 851, 852, 852,
+	853, 853, 854, 854, 855, 855, 856, 856, 857, 857, 858,
+	859, 859, 860, 860, 861, 861, 862, 862, 863, 863, 864,
+	864, 865, 865, 866, 866, 867, 867, 868, 868, 869, 869,
+	870, 870, 871, 871, 872, 872, 873, 873, 874, 874, 875,
+	875, 876, 876, 877, 877, 878, 878, 879, 879, 880, 880,
+	881, 881, 882, 882, 883, 883, 884, 884, 885, 885, 886,
+	886, 887, 887, 888, 888, 889, 889, 890, 890, 891, 891,
+	892, 892, 893, 893, 894, 894, 895, 895, 896, 896, 897,
+	897, 898, 898, 899, 899, 900, 900, 901, 901, 902, 902,
+	903, 903, 904, 904, 905, 905, 905, 906, 906, 907, 907,
+	908, 908, 909, 909, 910, 910, 911, 911, 912, 912, 913,
+	913, 914, 914, 915, 915, 915, 916, 916, 917, 917, 918,
+	918, 919, 919, 920, 920, 921, 921, 922, 922, 923, 923,
+	923, 924, 924, 925, 925, 926, 926, 927, 927, 928, 928,
+	929, 929, 929, 930, 930, 931, 931, 932, 932, 933, 933,
+	934, 934, 935, 935, 935, 936, 936, 937, 937, 938, 938,
+	939, 939, 940, 940, 940, 941, 941, 942, 942, 943, 943,
+	944, 944, 945, 945, 945, 946, 946, 947, 947, 948, 948,
+	949, 949, 949, 950, 950, 951, 951, 952, 952, 953, 953,
+	953, 954, 954, 955, 955, 956, 956, 957, 957, 957, 958,
+	958, 959, 959, 960, 960, 961, 961, 961, 962, 962, 963,
+	963, 964, 964, 965, 965, 965, 966, 966, 967, 967, 968,
+	968, 968, 969, 969, 970, 970, 971, 971, 971, 972, 972,
+	973, 973, 974, 974, 974, 975, 975, 976, 976, 977, 977,
+	977, 978, 978, 979, 979, 980, 980, 980, 981, 981, 982,
+	982, 983, 983, 983, 984, 984, 985, 985, 986, 986, 986,
+	987, 987, 988, 988, 989, 989, 989, 990, 990, 991, 991,
+	991, 992, 992, 993, 993, 994, 994, 994, 995, 995, 996,
+	996, 996, 997, 997, 998, 998, 999, 999, 999, 1000, 1000,
+	1001, 1001, 1001, 1002, 1002, 1003, 1003, 1004, 1004, 1004, 1005,
+	1005, 1006, 1006, 1006, 1007, 1007, 1008, 1008, 1008, 1009, 1009,
+	1010, 1010, 1010, 1011, 1011, 1012, 1012, 1013, 1013, 1013, 1014,
+	1014, 1015, 1015, 1015, 1016, 1016, 1017, 1017, 1017, 1018, 1018,
+	1019, 1019, 1019, 1020, 1020, 1021, 1021, 1021, 1022, 1022, 1023,
+	1023,
+};
+
+static const u16 xgamma10_05[GAMMA10_TABLE_LENGTH] = {
+	0, 32, 45, 55, 64, 72, 78, 85, 90, 96, 101,
+	106, 111, 115, 120, 124, 128, 132, 136, 139, 143, 147,
+	150, 153, 157, 160, 163, 166, 169, 172, 175, 178, 181,
+	184, 186, 189, 192, 195, 197, 200, 202, 205, 207, 210,
+	212, 215, 217, 219, 222, 224, 226, 228, 231, 233, 235,
+	237, 239, 241, 244, 246, 248, 250, 252, 254, 256, 258,
+	260, 262, 264, 266, 268, 270, 271, 273, 275, 277, 279,
+	281, 282, 284, 286, 288, 290, 291, 293, 295, 297, 298,
+	300, 302, 303, 305, 307, 308, 310, 312, 313, 315, 317,
+	318, 320, 321, 323, 325, 326, 328, 329, 331, 332, 334,
+	335, 337, 338, 340, 341, 343, 344, 346, 347, 349, 350,
+	352, 353, 355, 356, 358, 359, 360, 362, 363, 365, 366,
+	367, 369, 370, 372, 373, 374, 376, 377, 378, 380, 381,
+	382, 384, 385, 386, 388, 389, 390, 392, 393, 394, 396,
+	397, 398, 399, 401, 402, 403, 405, 406, 407, 408, 410,
+	411, 412, 413, 415, 416, 417, 418, 419, 421, 422, 423,
+	424, 426, 427, 428, 429, 430, 431, 433, 434, 435, 436,
+	437, 439, 440, 441, 442, 443, 444, 445, 447, 448, 449,
+	450, 451, 452, 453, 455, 456, 457, 458, 459, 460, 461,
+	462, 463, 465, 466, 467, 468, 469, 470, 471, 472, 473,
+	474, 475, 477, 478, 479, 480, 481, 482, 483, 484, 485,
+	486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 497,
+	498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508,
+	509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519,
+	520, 521, 522, 523, 524, 525, 526, 527, 527, 528, 529,
+	530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540,
+	541, 542, 543, 544, 545, 546, 547, 547, 548, 549, 550,
+	551, 552, 553, 554, 555, 556, 557, 558, 559, 559, 560,
+	561, 562, 563, 564, 565, 566, 567, 568, 569, 569, 570,
+	571, 572, 573, 574, 575, 576, 577, 577, 578, 579, 580,
+	581, 582, 583, 584, 585, 585, 586, 587, 588, 589, 590,
+	591, 591, 592, 593, 594, 595, 596, 597, 598, 598, 599,
+	600, 601, 602, 603, 603, 604, 605, 606, 607, 608, 609,
+	609, 610, 611, 612, 613, 614, 614, 615, 616, 617, 618,
+	619, 619, 620, 621, 622, 623, 623, 624, 625, 626, 627,
+	628, 628, 629, 630, 631, 632, 632, 633, 634, 635, 636,
+	636, 637, 638, 639, 640, 640, 641, 642, 643, 644, 644,
+	645, 646, 647, 648, 648, 649, 650, 651, 652, 652, 653,
+	654, 655, 655, 656, 657, 658, 659, 659, 660, 661, 662,
+	662, 663, 664, 665, 666, 666, 667, 668, 669, 669, 670,
+	671, 672, 672, 673, 674, 675, 675, 676, 677, 678, 678,
+	679, 680, 681, 681, 682, 683, 684, 684, 685, 686, 687,
+	687, 688, 689, 690, 690, 691, 692, 693, 693, 694, 695,
+	696, 696, 697, 698, 699, 699, 700, 701, 701, 702, 703,
+	704, 704, 705, 706, 707, 707, 708, 709, 709, 710, 711,
+	712, 712, 713, 714, 714, 715, 716, 717, 717, 718, 719,
+	719, 720, 721, 722, 722, 723, 724, 724, 725, 726, 727,
+	727, 728, 729, 729, 730, 731, 731, 732, 733, 734, 734,
+	735, 736, 736, 737, 738, 738, 739, 740, 740, 741, 742,
+	743, 743, 744, 745, 745, 746, 747, 747, 748, 749, 749,
+	750, 751, 751, 752, 753, 754, 754, 755, 756, 756, 757,
+	758, 758, 759, 760, 760, 761, 762, 762, 763, 764, 764,
+	765, 766, 766, 767, 768, 768, 769, 770, 770, 771, 772,
+	772, 773, 774, 774, 775, 776, 776, 777, 778, 778, 779,
+	780, 780, 781, 781, 782, 783, 783, 784, 785, 785, 786,
+	787, 787, 788, 789, 789, 790, 791, 791, 792, 793, 793,
+	794, 794, 795, 796, 796, 797, 798, 798, 799, 800, 800,
+	801, 802, 802, 803, 803, 804, 805, 805, 806, 807, 807,
+	808, 809, 809, 810, 810, 811, 812, 812, 813, 814, 814,
+	815, 815, 816, 817, 817, 818, 819, 819, 820, 820, 821,
+	822, 822, 823, 824, 824, 825, 825, 826, 827, 827, 828,
+	829, 829, 830, 830, 831, 832, 832, 833, 833, 834, 835,
+	835, 836, 836, 837, 838, 838, 839, 840, 840, 841, 841,
+	842, 843, 843, 844, 844, 845, 846, 846, 847, 847, 848,
+	849, 849, 850, 850, 851, 852, 852, 853, 853, 854, 855,
+	855, 856, 856, 857, 858, 858, 859, 859, 860, 861, 861,
+	862, 862, 863, 864, 864, 865, 865, 866, 867, 867, 868,
+	868, 869, 869, 870, 871, 871, 872, 872, 873, 874, 874,
+	875, 875, 876, 877, 877, 878, 878, 879, 879, 880, 881,
+	881, 882, 882, 883, 883, 884, 885, 885, 886, 886, 887,
+	888, 888, 889, 889, 890, 890, 891, 892, 892, 893, 893,
+	894, 894, 895, 896, 896, 897, 897, 898, 898, 899, 900,
+	900, 901, 901, 902, 902, 903, 904, 904, 905, 905, 906,
+	906, 907, 907, 908, 909, 909, 910, 910, 911, 911, 912,
+	913, 913, 914, 914, 915, 915, 916, 916, 917, 918, 918,
+	919, 919, 920, 920, 921, 921, 922, 923, 923, 924, 924,
+	925, 925, 926, 926, 927, 928, 928, 929, 929, 930, 930,
+	931, 931, 932, 932, 933, 934, 934, 935, 935, 936, 936,
+	937, 937, 938, 939, 939, 940, 940, 941, 941, 942, 942,
+	943, 943, 944, 944, 945, 946, 946, 947, 947, 948, 948,
+	949, 949, 950, 950, 951, 952, 952, 953, 953, 954, 954,
+	955, 955, 956, 956, 957, 957, 958, 958, 959, 960, 960,
+	961, 961, 962, 962, 963, 963, 964, 964, 965, 965, 966,
+	966, 967, 967, 968, 969, 969, 970, 970, 971, 971, 972,
+	972, 973, 973, 974, 974, 975, 975, 976, 976, 977, 977,
+	978, 979, 979, 980, 980, 981, 981, 982, 982, 983, 983,
+	984, 984, 985, 985, 986, 986, 987, 987, 988, 988, 989,
+	989, 990, 990, 991, 992, 992, 993, 993, 994, 994, 995,
+	995, 996, 996, 997, 997, 998, 998, 999, 999, 1000, 1000,
+	1001, 1001, 1002, 1002, 1003, 1003, 1004, 1004, 1005, 1005, 1006,
+	1006, 1007, 1007, 1008, 1008, 1009, 1009, 1010, 1010, 1011, 1011,
+	1012, 1012, 1013, 1013, 1014, 1014, 1015, 1015, 1016, 1016, 1017,
+	1017, 1018, 1018, 1019, 1019, 1020, 1020, 1021, 1021, 1022, 1022,
+	1023,
+};
+
+static const u16 xgamma10_06[GAMMA10_TABLE_LENGTH] = {
+	0, 16, 24, 31, 37, 42, 47, 51, 56, 60, 64,
+	67, 71, 75, 78, 81, 84, 88, 91, 94, 97, 99,
+	102, 105, 108, 110, 113, 116, 118, 121, 123, 126, 128,
+	130, 133, 135, 137, 140, 142, 144, 146, 148, 151, 153,
+	155, 157, 159, 161, 163, 165, 167, 169, 171, 173, 175,
+	177, 179, 181, 183, 185, 187, 188, 190, 192, 194, 196,
+	198, 199, 201, 203, 205, 206, 208, 210, 212, 213, 215,
+	217, 218, 220, 222, 223, 225, 227, 228, 230, 232, 233,
+	235, 236, 238, 240, 241, 243, 244, 246, 247, 249, 250,
+	252, 253, 255, 257, 258, 260, 261, 263, 264, 265, 267,
+	268, 270, 271, 273, 274, 276, 277, 279, 280, 281, 283,
+	284, 286, 287, 288, 290, 291, 293, 294, 295, 297, 298,
+	299, 301, 302, 303, 305, 306, 308, 309, 310, 312, 313,
+	314, 315, 317, 318, 319, 321, 322, 323, 325, 326, 327,
+	328, 330, 331, 332, 334, 335, 336, 337, 339, 340, 341,
+	342, 344, 345, 346, 347, 349, 350, 351, 352, 353, 355,
+	356, 357, 358, 359, 361, 362, 363, 364, 365, 367, 368,
+	369, 370, 371, 373, 374, 375, 376, 377, 378, 380, 381,
+	382, 383, 384, 385, 387, 388, 389, 390, 391, 392, 393,
+	394, 396, 397, 398, 399, 400, 401, 402, 403, 405, 406,
+	407, 408, 409, 410, 411, 412, 413, 415, 416, 417, 418,
+	419, 420, 421, 422, 423, 424, 425, 426, 428, 429, 430,
+	431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441,
+	442, 443, 445, 446, 447, 448, 449, 450, 451, 452, 453,
+	454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464,
+	465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475,
+	476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486,
+	487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497,
+	498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 507,
+	508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518,
+	519, 520, 521, 522, 523, 524, 525, 525, 526, 527, 528,
+	529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 538,
+	539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 548,
+	549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 558,
+	559, 560, 561, 562, 563, 564, 565, 566, 566, 567, 568,
+	569, 570, 571, 572, 573, 574, 574, 575, 576, 577, 578,
+	579, 580, 581, 581, 582, 583, 584, 585, 586, 587, 588,
+	588, 589, 590, 591, 592, 593, 594, 594, 595, 596, 597,
+	598, 599, 600, 601, 601, 602, 603, 604, 605, 606, 606,
+	607, 608, 609, 610, 611, 612, 612, 613, 614, 615, 616,
+	617, 617, 618, 619, 620, 621, 622, 622, 623, 624, 625,
+	626, 627, 627, 628, 629, 630, 631, 632, 632, 633, 634,
+	635, 636, 637, 637, 638, 639, 640, 641, 642, 642, 643,
+	644, 645, 646, 646, 647, 648, 649, 650, 650, 651, 652,
+	653, 654, 655, 655, 656, 657, 658, 659, 659, 660, 661,
+	662, 663, 663, 664, 665, 666, 667, 667, 668, 669, 670,
+	671, 671, 672, 673, 674, 675, 675, 676, 677, 678, 678,
+	679, 680, 681, 682, 682, 683, 684, 685, 686, 686, 687,
+	688, 689, 689, 690, 691, 692, 693, 693, 694, 695, 696,
+	696, 697, 698, 699, 700, 700, 701, 702, 703, 703, 704,
+	705, 706, 707, 707, 708, 709, 710, 710, 711, 712, 713,
+	713, 714, 715, 716, 716, 717, 718, 719, 719, 720, 721,
+	722, 723, 723, 724, 725, 726, 726, 727, 728, 729, 729,
+	730, 731, 732, 732, 733, 734, 735, 735, 736, 737, 738,
+	738, 739, 740, 741, 741, 742, 743, 743, 744, 745, 746,
+	746, 747, 748, 749, 749, 750, 751, 752, 752, 753, 754,
+	755, 755, 756, 757, 758, 758, 759, 760, 760, 761, 762,
+	763, 763, 764, 765, 766, 766, 767, 768, 768, 769, 770,
+	771, 771, 772, 773, 774, 774, 775, 776, 776, 777, 778,
+	779, 779, 780, 781, 781, 782, 783, 784, 784, 785, 786,
+	786, 787, 788, 789, 789, 790, 791, 791, 792, 793, 794,
+	794, 795, 796, 796, 797, 798, 799, 799, 800, 801, 801,
+	802, 803, 803, 804, 805, 806, 806, 807, 808, 808, 809,
+	810, 811, 811, 812, 813, 813, 814, 815, 815, 816, 817,
+	818, 818, 819, 820, 820, 821, 822, 822, 823, 824, 824,
+	825, 826, 827, 827, 828, 829, 829, 830, 831, 831, 832,
+	833, 833, 834, 835, 835, 836, 837, 838, 838, 839, 840,
+	840, 841, 842, 842, 843, 844, 844, 845, 846, 846, 847,
+	848, 848, 849, 850, 851, 851, 852, 853, 853, 854, 855,
+	855, 856, 857, 857, 858, 859, 859, 860, 861, 861, 862,
+	863, 863, 864, 865, 865, 866, 867, 867, 868, 869, 869,
+	870, 871, 871, 872, 873, 873, 874, 875, 875, 876, 877,
+	877, 878, 879, 879, 880, 881, 881, 882, 883, 883, 884,
+	885, 885, 886, 887, 887, 888, 889, 889, 890, 891, 891,
+	892, 893, 893, 894, 895, 895, 896, 897, 897, 898, 898,
+	899, 900, 900, 901, 902, 902, 903, 904, 904, 905, 906,
+	906, 907, 908, 908, 909, 910, 910, 911, 911, 912, 913,
+	913, 914, 915, 915, 916, 917, 917, 918, 919, 919, 920,
+	921, 921, 922, 922, 923, 924, 924, 925, 926, 926, 927,
+	928, 928, 929, 930, 930, 931, 931, 932, 933, 933, 934,
+	935, 935, 936, 937, 937, 938, 938, 939, 940, 940, 941,
+	942, 942, 943, 944, 944, 945, 945, 946, 947, 947, 948,
+	949, 949, 950, 950, 951, 952, 952, 953, 954, 954, 955,
+	956, 956, 957, 957, 958, 959, 959, 960, 961, 961, 962,
+	962, 963, 964, 964, 965, 966, 966, 967, 967, 968, 969,
+	969, 970, 970, 971, 972, 972, 973, 974, 974, 975, 975,
+	976, 977, 977, 978, 979, 979, 980, 980, 981, 982, 982,
+	983, 983, 984, 985, 985, 986, 987, 987, 988, 988, 989,
+	990, 990, 991, 991, 992, 993, 993, 994, 995, 995, 996,
+	996, 997, 998, 998, 999, 999, 1000, 1001, 1001, 1002, 1002,
+	1003, 1004, 1004, 1005, 1006, 1006, 1007, 1007, 1008, 1009, 1009,
+	1010, 1010, 1011, 1012, 1012, 1013, 1013, 1014, 1015, 1015, 1016,
+	1016, 1017, 1018, 1018, 1019, 1019, 1020, 1021, 1021, 1022, 1022,
+	1023,
+};
+
+static const u16 xgamma10_07[GAMMA10_TABLE_LENGTH] = {
+	0, 8, 13, 17, 21, 25, 28, 31, 34, 37, 40,
+	43, 46, 48, 51, 53, 56, 58, 60, 63, 65, 67,
+	70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90,
+	92, 94, 96, 98, 100, 102, 104, 106, 108, 109, 111,
+	113, 115, 117, 118, 120, 122, 124, 125, 127, 129, 131,
+	132, 134, 136, 137, 139, 140, 142, 144, 145, 147, 149,
+	150, 152, 153, 155, 157, 158, 160, 161, 163, 164, 166,
+	167, 169, 170, 172, 173, 175, 176, 178, 179, 181, 182,
+	184, 185, 187, 188, 190, 191, 192, 194, 195, 197, 198,
+	199, 201, 202, 204, 205, 206, 208, 209, 211, 212, 213,
+	215, 216, 217, 219, 220, 222, 223, 224, 226, 227, 228,
+	230, 231, 232, 234, 235, 236, 237, 239, 240, 241, 243,
+	244, 245, 247, 248, 249, 250, 252, 253, 254, 256, 257,
+	258, 259, 261, 262, 263, 264, 266, 267, 268, 269, 271,
+	272, 273, 274, 275, 277, 278, 279, 280, 282, 283, 284,
+	285, 286, 288, 289, 290, 291, 292, 294, 295, 296, 297,
+	298, 300, 301, 302, 303, 304, 306, 307, 308, 309, 310,
+	311, 313, 314, 315, 316, 317, 318, 319, 321, 322, 323,
+	324, 325, 326, 327, 329, 330, 331, 332, 333, 334, 335,
+	337, 338, 339, 340, 341, 342, 343, 344, 346, 347, 348,
+	349, 350, 351, 352, 353, 354, 355, 357, 358, 359, 360,
+	361, 362, 363, 364, 365, 366, 368, 369, 370, 371, 372,
+	373, 374, 375, 376, 377, 378, 379, 380, 382, 383, 384,
+	385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395,
+	396, 397, 398, 400, 401, 402, 403, 404, 405, 406, 407,
+	408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418,
+	419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429,
+	430, 431, 432, 433, 434, 435, 436, 437, 439, 440, 441,
+	442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452,
+	452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462,
+	463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473,
+	474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484,
+	485, 486, 487, 488, 489, 490, 491, 492, 492, 493, 494,
+	495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505,
+	506, 507, 508, 509, 510, 511, 511, 512, 513, 514, 515,
+	516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526,
+	526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536,
+	537, 538, 538, 539, 540, 541, 542, 543, 544, 545, 546,
+	547, 548, 549, 549, 550, 551, 552, 553, 554, 555, 556,
+	557, 558, 559, 560, 560, 561, 562, 563, 564, 565, 566,
+	567, 568, 569, 569, 570, 571, 572, 573, 574, 575, 576,
+	577, 578, 578, 579, 580, 581, 582, 583, 584, 585, 586,
+	586, 587, 588, 589, 590, 591, 592, 593, 594, 594, 595,
+	596, 597, 598, 599, 600, 601, 601, 602, 603, 604, 605,
+	606, 607, 608, 608, 609, 610, 611, 612, 613, 614, 615,
+	615, 616, 617, 618, 619, 620, 621, 622, 622, 623, 624,
+	625, 626, 627, 628, 628, 629, 630, 631, 632, 633, 634,
+	634, 635, 636, 637, 638, 639, 640, 640, 641, 642, 643,
+	644, 645, 646, 646, 647, 648, 649, 650, 651, 652, 652,
+	653, 654, 655, 656, 657, 657, 658, 659, 660, 661, 662,
+	663, 663, 664, 665, 666, 667, 668, 668, 669, 670, 671,
+	672, 673, 673, 674, 675, 676, 677, 678, 678, 679, 680,
+	681, 682, 683, 683, 684, 685, 686, 687, 688, 688, 689,
+	690, 691, 692, 693, 693, 694, 695, 696, 697, 698, 698,
+	699, 700, 701, 702, 703, 703, 704, 705, 706, 707, 707,
+	708, 709, 710, 711, 712, 712, 713, 714, 715, 716, 716,
+	717, 718, 719, 720, 721, 721, 722, 723, 724, 725, 725,
+	726, 727, 728, 729, 729, 730, 731, 732, 733, 733, 734,
+	735, 736, 737, 738, 738, 739, 740, 741, 742, 742, 743,
+	744, 745, 746, 746, 747, 748, 749, 750, 750, 751, 752,
+	753, 754, 754, 755, 756, 757, 758, 758, 759, 760, 761,
+	761, 762, 763, 764, 765, 765, 766, 767, 768, 769, 769,
+	770, 771, 772, 773, 773, 774, 775, 776, 777, 777, 778,
+	779, 780, 780, 781, 782, 783, 784, 784, 785, 786, 787,
+	788, 788, 789, 790, 791, 791, 792, 793, 794, 795, 795,
+	796, 797, 798, 798, 799, 800, 801, 802, 802, 803, 804,
+	805, 805, 806, 807, 808, 809, 809, 810, 811, 812, 812,
+	813, 814, 815, 816, 816, 817, 818, 819, 819, 820, 821,
+	822, 822, 823, 824, 825, 826, 826, 827, 828, 829, 829,
+	830, 831, 832, 832, 833, 834, 835, 835, 836, 837, 838,
+	839, 839, 840, 841, 842, 842, 843, 844, 845, 845, 846,
+	847, 848, 848, 849, 850, 851, 851, 852, 853, 854, 854,
+	855, 856, 857, 857, 858, 859, 860, 860, 861, 862, 863,
+	864, 864, 865, 866, 867, 867, 868, 869, 870, 870, 871,
+	872, 873, 873, 874, 875, 876, 876, 877, 878, 879, 879,
+	880, 881, 881, 882, 883, 884, 884, 885, 886, 887, 887,
+	888, 889, 890, 890, 891, 892, 893, 893, 894, 895, 896,
+	896, 897, 898, 899, 899, 900, 901, 902, 902, 903, 904,
+	904, 905, 906, 907, 907, 908, 909, 910, 910, 911, 912,
+	913, 913, 914, 915, 916, 916, 917, 918, 918, 919, 920,
+	921, 921, 922, 923, 924, 924, 925, 926, 927, 927, 928,
+	929, 929, 930, 931, 932, 932, 933, 934, 935, 935, 936,
+	937, 937, 938, 939, 940, 940, 941, 942, 943, 943, 944,
+	945, 945, 946, 947, 948, 948, 949, 950, 950, 951, 952,
+	953, 953, 954, 955, 956, 956, 957, 958, 958, 959, 960,
+	961, 961, 962, 963, 963, 964, 965, 966, 966, 967, 968,
+	968, 969, 970, 971, 971, 972, 973, 973, 974, 975, 976,
+	976, 977, 978, 978, 979, 980, 981, 981, 982, 983, 983,
+	984, 985, 986, 986, 987, 988, 988, 989, 990, 991, 991,
+	992, 993, 993, 994, 995, 996, 996, 997, 998, 998, 999,
+	1000, 1000, 1001, 1002, 1003, 1003, 1004, 1005, 1005, 1006, 1007,
+	1008, 1008, 1009, 1010, 1010, 1011, 1012, 1012, 1013, 1014, 1015,
+	1015, 1016, 1017, 1017, 1018, 1019, 1019, 1020, 1021, 1022, 1022,
+	1023,
+};
+
+static const u16 xgamma10_08[GAMMA10_TABLE_LENGTH] = {
+	0, 4, 7, 10, 12, 14, 17, 19, 21, 23, 25,
+	27, 29, 31, 33, 35, 37, 39, 40, 42, 44, 46,
+	47, 49, 51, 53, 54, 56, 58, 59, 61, 62, 64,
+	66, 67, 69, 70, 72, 73, 75, 76, 78, 80, 81,
+	83, 84, 86, 87, 89, 90, 91, 93, 94, 96, 97,
+	99, 100, 102, 103, 104, 106, 107, 109, 110, 111, 113,
+	114, 116, 117, 118, 120, 121, 122, 124, 125, 126, 128,
+	129, 131, 132, 133, 135, 136, 137, 138, 140, 141, 142,
+	144, 145, 146, 148, 149, 150, 152, 153, 154, 155, 157,
+	158, 159, 160, 162, 163, 164, 166, 167, 168, 169, 171,
+	172, 173, 174, 176, 177, 178, 179, 181, 182, 183, 184,
+	185, 187, 188, 189, 190, 192, 193, 194, 195, 196, 198,
+	199, 200, 201, 202, 204, 205, 206, 207, 208, 210, 211,
+	212, 213, 214, 216, 217, 218, 219, 220, 221, 223, 224,
+	225, 226, 227, 228, 230, 231, 232, 233, 234, 235, 237,
+	238, 239, 240, 241, 242, 243, 245, 246, 247, 248, 249,
+	250, 251, 253, 254, 255, 256, 257, 258, 259, 260, 262,
+	263, 264, 265, 266, 267, 268, 269, 271, 272, 273, 274,
+	275, 276, 277, 278, 279, 281, 282, 283, 284, 285, 286,
+	287, 288, 289, 290, 292, 293, 294, 295, 296, 297, 298,
+	299, 300, 301, 302, 304, 305, 306, 307, 308, 309, 310,
+	311, 312, 313, 314, 315, 316, 318, 319, 320, 321, 322,
+	323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333,
+	335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345,
+	346, 347, 348, 349, 350, 351, 352, 353, 355, 356, 357,
+	358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368,
+	369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379,
+	380, 381, 382, 383, 384, 385, 386, 388, 389, 390, 391,
+	392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402,
+	403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413,
+	414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424,
+	425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435,
+	436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446,
+	447, 448, 449, 450, 451, 451, 452, 453, 454, 455, 456,
+	457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467,
+	468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478,
+	479, 480, 481, 482, 483, 484, 485, 486, 486, 487, 488,
+	489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499,
+	500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 509,
+	510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520,
+	521, 522, 523, 524, 525, 526, 527, 527, 528, 529, 530,
+	531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541,
+	542, 543, 543, 544, 545, 546, 547, 548, 549, 550, 551,
+	552, 553, 554, 555, 556, 557, 557, 558, 559, 560, 561,
+	562, 563, 564, 565, 566, 567, 568, 569, 570, 570, 571,
+	572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582,
+	582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592,
+	593, 594, 594, 595, 596, 597, 598, 599, 600, 601, 602,
+	603, 604, 604, 605, 606, 607, 608, 609, 610, 611, 612,
+	613, 614, 615, 615, 616, 617, 618, 619, 620, 621, 622,
+	623, 624, 624, 625, 626, 627, 628, 629, 630, 631, 632,
+	633, 634, 634, 635, 636, 637, 638, 639, 640, 641, 642,
+	643, 643, 644, 645, 646, 647, 648, 649, 650, 651, 651,
+	652, 653, 654, 655, 656, 657, 658, 659, 660, 660, 661,
+	662, 663, 664, 665, 666, 667, 668, 668, 669, 670, 671,
+	672, 673, 674, 675, 676, 676, 677, 678, 679, 680, 681,
+	682, 683, 684, 684, 685, 686, 687, 688, 689, 690, 691,
+	691, 692, 693, 694, 695, 696, 697, 698, 699, 699, 700,
+	701, 702, 703, 704, 705, 706, 706, 707, 708, 709, 710,
+	711, 712, 713, 713, 714, 715, 716, 717, 718, 719, 720,
+	720, 721, 722, 723, 724, 725, 726, 727, 727, 728, 729,
+	730, 731, 732, 733, 734, 734, 735, 736, 737, 738, 739,
+	740, 740, 741, 742, 743, 744, 745, 746, 747, 747, 748,
+	749, 750, 751, 752, 753, 753, 754, 755, 756, 757, 758,
+	759, 759, 760, 761, 762, 763, 764, 765, 766, 766, 767,
+	768, 769, 770, 771, 772, 772, 773, 774, 775, 776, 777,
+	778, 778, 779, 780, 781, 782, 783, 784, 784, 785, 786,
+	787, 788, 789, 790, 790, 791, 792, 793, 794, 795, 795,
+	796, 797, 798, 799, 800, 801, 801, 802, 803, 804, 805,
+	806, 807, 807, 808, 809, 810, 811, 812, 812, 813, 814,
+	815, 816, 817, 818, 818, 819, 820, 821, 822, 823, 823,
+	824, 825, 826, 827, 828, 829, 829, 830, 831, 832, 833,
+	834, 834, 835, 836, 837, 838, 839, 839, 840, 841, 842,
+	843, 844, 845, 845, 846, 847, 848, 849, 850, 850, 851,
+	852, 853, 854, 855, 855, 856, 857, 858, 859, 860, 860,
+	861, 862, 863, 864, 865, 865, 866, 867, 868, 869, 870,
+	870, 871, 872, 873, 874, 875, 875, 876, 877, 878, 879,
+	880, 880, 881, 882, 883, 884, 885, 885, 886, 887, 888,
+	889, 890, 890, 891, 892, 893, 894, 895, 895, 896, 897,
+	898, 899, 899, 900, 901, 902, 903, 904, 904, 905, 906,
+	907, 908, 909, 909, 910, 911, 912, 913, 913, 914, 915,
+	916, 917, 918, 918, 919, 920, 921, 922, 923, 923, 924,
+	925, 926, 927, 927, 928, 929, 930, 931, 932, 932, 933,
+	934, 935, 936, 936, 937, 938, 939, 940, 941, 941, 942,
+	943, 944, 945, 945, 946, 947, 948, 949, 950, 950, 951,
+	952, 953, 954, 954, 955, 956, 957, 958, 958, 959, 960,
+	961, 962, 963, 963, 964, 965, 966, 967, 967, 968, 969,
+	970, 971, 971, 972, 973, 974, 975, 976, 976, 977, 978,
+	979, 980, 980, 981, 982, 983, 984, 984, 985, 986, 987,
+	988, 988, 989, 990, 991, 992, 992, 993, 994, 995, 996,
+	997, 997, 998, 999, 1000, 1001, 1001, 1002, 1003, 1004, 1005,
+	1005, 1006, 1007, 1008, 1009, 1009, 1010, 1011, 1012, 1013, 1013,
+	1014, 1015, 1016, 1017, 1017, 1018, 1019, 1020, 1021, 1021, 1022,
+	1023,
+};
+
+static const u16 xgamma10_09[GAMMA10_TABLE_LENGTH] = {
+	0, 2, 4, 5, 7, 9, 10, 12, 13, 14, 16,
+	17, 19, 20, 22, 23, 24, 26, 27, 28, 30, 31,
+	32, 34, 35, 36, 38, 39, 40, 41, 43, 44, 45,
+	47, 48, 49, 50, 52, 53, 54, 55, 57, 58, 59,
+	60, 62, 63, 64, 65, 66, 68, 69, 70, 71, 72,
+	74, 75, 76, 77, 78, 80, 81, 82, 83, 84, 86,
+	87, 88, 89, 90, 92, 93, 94, 95, 96, 97, 99,
+	100, 101, 102, 103, 104, 106, 107, 108, 109, 110, 111,
+	112, 114, 115, 116, 117, 118, 119, 120, 122, 123, 124,
+	125, 126, 127, 128, 130, 131, 132, 133, 134, 135, 136,
+	137, 139, 140, 141, 142, 143, 144, 145, 146, 148, 149,
+	150, 151, 152, 153, 154, 155, 156, 158, 159, 160, 161,
+	162, 163, 164, 165, 166, 168, 169, 170, 171, 172, 173,
+	174, 175, 176, 177, 178, 180, 181, 182, 183, 184, 185,
+	186, 187, 188, 189, 190, 192, 193, 194, 195, 196, 197,
+	198, 199, 200, 201, 202, 203, 204, 206, 207, 208, 209,
+	210, 211, 212, 213, 214, 215, 216, 217, 218, 220, 221,
+	222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232,
+	233, 234, 235, 237, 238, 239, 240, 241, 242, 243, 244,
+	245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255,
+	257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267,
+	268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278,
+	280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290,
+	291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301,
+	302, 303, 304, 305, 306, 307, 308, 309, 311, 312, 313,
+	314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324,
+	325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335,
+	336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346,
+	347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357,
+	358, 359, 360, 361, 362, 363, 364, 365, 367, 368, 369,
+	370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380,
+	381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391,
+	392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402,
+	403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413,
+	414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424,
+	425, 426, 427, 427, 428, 429, 430, 431, 432, 433, 434,
+	435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445,
+	446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456,
+	457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467,
+	468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478,
+	479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489,
+	489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499,
+	500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510,
+	511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521,
+	522, 523, 524, 525, 525, 526, 527, 528, 529, 530, 531,
+	532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542,
+	543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553,
+	554, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563,
+	564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574,
+	575, 576, 577, 578, 579, 579, 580, 581, 582, 583, 584,
+	585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595,
+	596, 597, 598, 599, 600, 601, 601, 602, 603, 604, 605,
+	606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616,
+	617, 618, 619, 620, 621, 621, 622, 623, 624, 625, 626,
+	627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637,
+	638, 639, 640, 640, 641, 642, 643, 644, 645, 646, 647,
+	648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658,
+	658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668,
+	669, 670, 671, 672, 673, 674, 675, 675, 676, 677, 678,
+	679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689,
+	690, 691, 691, 692, 693, 694, 695, 696, 697, 698, 699,
+	700, 701, 702, 703, 704, 705, 706, 706, 707, 708, 709,
+	710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720,
+	721, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730,
+	731, 732, 733, 734, 735, 735, 736, 737, 738, 739, 740,
+	741, 742, 743, 744, 745, 746, 747, 748, 749, 749, 750,
+	751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761,
+	762, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771,
+	772, 773, 774, 775, 776, 776, 777, 778, 779, 780, 781,
+	782, 783, 784, 785, 786, 787, 788, 788, 789, 790, 791,
+	792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 801,
+	802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812,
+	813, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822,
+	823, 824, 825, 825, 826, 827, 828, 829, 830, 831, 832,
+	833, 834, 835, 836, 836, 837, 838, 839, 840, 841, 842,
+	843, 844, 845, 846, 847, 848, 848, 849, 850, 851, 852,
+	853, 854, 855, 856, 857, 858, 859, 859, 860, 861, 862,
+	863, 864, 865, 866, 867, 868, 869, 870, 870, 871, 872,
+	873, 874, 875, 876, 877, 878, 879, 880, 881, 881, 882,
+	883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 892,
+	893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 902,
+	903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913,
+	913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923,
+	923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933,
+	933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943,
+	943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953,
+	953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 962,
+	963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 972,
+	973, 974, 975, 976, 977, 978, 979, 980, 981, 982, 982,
+	983, 984, 985, 986, 987, 988, 989, 990, 991, 991, 992,
+	993, 994, 995, 996, 997, 998, 999, 1000, 1000, 1001, 1002,
+	1003, 1004, 1005, 1006, 1007, 1008, 1009, 1009, 1010, 1011, 1012,
+	1013, 1014, 1015, 1016, 1017, 1018, 1018, 1019, 1020, 1021, 1022,
+	1023,
+};
+
+static const u16 xgamma10_10[GAMMA10_TABLE_LENGTH] = {
+	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+	11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+	22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+	33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+	44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+	55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+	66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
+	77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
+	88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
+	99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
+	110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
+	121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131,
+	132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,
+	143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153,
+	154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
+	165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
+	176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186,
+	187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197,
+	198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208,
+	209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
+	220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230,
+	231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241,
+	242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252,
+	253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263,
+	264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
+	275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285,
+	286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296,
+	297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307,
+	308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318,
+	319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329,
+	330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340,
+	341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351,
+	352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362,
+	363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373,
+	374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384,
+	385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395,
+	396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406,
+	407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417,
+	418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428,
+	429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439,
+	440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450,
+	451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461,
+	462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472,
+	473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483,
+	484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494,
+	495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505,
+	506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516,
+	517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527,
+	528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538,
+	539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549,
+	550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560,
+	561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571,
+	572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582,
+	583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593,
+	594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604,
+	605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615,
+	616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626,
+	627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637,
+	638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648,
+	649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659,
+	660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670,
+	671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681,
+	682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692,
+	693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703,
+	704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714,
+	715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725,
+	726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736,
+	737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747,
+	748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758,
+	759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769,
+	770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780,
+	781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791,
+	792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802,
+	803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813,
+	814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824,
+	825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835,
+	836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846,
+	847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857,
+	858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868,
+	869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879,
+	880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890,
+	891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901,
+	902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912,
+	913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923,
+	924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934,
+	935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945,
+	946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956,
+	957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967,
+	968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978,
+	979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 989,
+	990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000,
+	1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011,
+	1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022,
+	1023,
+};
+
+static const u16 xgamma10_11[GAMMA10_TABLE_LENGTH] = {
+	0, 1, 1, 2, 2, 3, 4, 4, 5, 6, 6,
+	7, 8, 8, 9, 10, 11, 11, 12, 13, 13, 14,
+	15, 16, 16, 17, 18, 19, 20, 20, 21, 22, 23,
+	23, 24, 25, 26, 27, 27, 28, 29, 30, 31, 31,
+	32, 33, 34, 35, 35, 36, 37, 38, 39, 39, 40,
+	41, 42, 43, 44, 44, 45, 46, 47, 48, 49, 49,
+	50, 51, 52, 53, 54, 54, 55, 56, 57, 58, 59,
+	59, 60, 61, 62, 63, 64, 65, 65, 66, 67, 68,
+	69, 70, 71, 71, 72, 73, 74, 75, 76, 77, 78,
+	78, 79, 80, 81, 82, 83, 84, 84, 85, 86, 87,
+	88, 89, 90, 91, 92, 92, 93, 94, 95, 96, 97,
+	98, 99, 100, 100, 101, 102, 103, 104, 105, 106, 107,
+	108, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
+	117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
+	127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137,
+	137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147,
+	148, 149, 149, 150, 151, 152, 153, 154, 155, 156, 157,
+	158, 159, 160, 161, 161, 162, 163, 164, 165, 166, 167,
+	168, 169, 170, 171, 172, 173, 174, 175, 175, 176, 177,
+	178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188,
+	189, 190, 191, 191, 192, 193, 194, 195, 196, 197, 198,
+	199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
+	210, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
+	220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230,
+	231, 232, 232, 233, 234, 235, 236, 237, 238, 239, 240,
+	241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251,
+	252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 261,
+	262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272,
+	273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283,
+	284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
+	295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305,
+	306, 307, 307, 308, 309, 310, 311, 312, 313, 314, 315,
+	316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326,
+	327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337,
+	338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348,
+	349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359,
+	360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370,
+	371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381,
+	382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392,
+	393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403,
+	404, 405, 406, 407, 408, 409, 410, 411, 412, 414, 415,
+	416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426,
+	427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437,
+	438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448,
+	449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459,
+	460, 461, 462, 463, 464, 465, 466, 468, 469, 470, 471,
+	472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482,
+	483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493,
+	494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 505,
+	506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516,
+	517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527,
+	528, 529, 530, 531, 532, 533, 535, 536, 537, 538, 539,
+	540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550,
+	551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 562,
+	563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573,
+	574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584,
+	586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596,
+	597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 608,
+	609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619,
+	620, 621, 622, 623, 624, 625, 626, 627, 629, 630, 631,
+	632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642,
+	643, 644, 645, 646, 648, 649, 650, 651, 652, 653, 654,
+	655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665,
+	667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677,
+	678, 679, 680, 681, 682, 683, 685, 686, 687, 688, 689,
+	690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700,
+	702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712,
+	713, 714, 715, 716, 717, 719, 720, 721, 722, 723, 724,
+	725, 726, 727, 728, 729, 730, 731, 732, 733, 735, 736,
+	737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747,
+	748, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759,
+	760, 761, 762, 763, 764, 766, 767, 768, 769, 770, 771,
+	772, 773, 774, 775, 776, 777, 778, 779, 781, 782, 783,
+	784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 795,
+	796, 797, 798, 799, 800, 801, 802, 803, 804, 805, 806,
+	807, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818,
+	819, 820, 821, 823, 824, 825, 826, 827, 828, 829, 830,
+	831, 832, 833, 834, 835, 837, 838, 839, 840, 841, 842,
+	843, 844, 845, 846, 847, 848, 850, 851, 852, 853, 854,
+	855, 856, 857, 858, 859, 860, 861, 863, 864, 865, 866,
+	867, 868, 869, 870, 871, 872, 873, 874, 876, 877, 878,
+	879, 880, 881, 882, 883, 884, 885, 886, 887, 889, 890,
+	891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 902,
+	903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 914,
+	915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 926,
+	927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 938,
+	939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 950,
+	951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 962,
+	963, 964, 965, 966, 967, 968, 969, 970, 971, 973, 974,
+	975, 976, 977, 978, 979, 980, 981, 982, 983, 985, 986,
+	987, 988, 989, 990, 991, 992, 993, 994, 996, 997, 998,
+	999, 1000, 1001, 1002, 1003, 1004, 1005, 1007, 1008, 1009, 1010,
+	1011, 1012, 1013, 1014, 1015, 1016, 1018, 1019, 1020, 1021, 1022,
+	1023,
+};
+
+static const u16 xgamma10_12[GAMMA10_TABLE_LENGTH] = {
+	0, 0, 1, 1, 1, 2, 2, 3, 3, 3, 4,
+	4, 5, 5, 6, 6, 7, 7, 8, 9, 9, 10,
+	10, 11, 11, 12, 12, 13, 14, 14, 15, 15, 16,
+	17, 17, 18, 18, 19, 20, 20, 21, 22, 22, 23,
+	23, 24, 25, 25, 26, 27, 27, 28, 29, 29, 30,
+	31, 31, 32, 33, 33, 34, 35, 35, 36, 37, 37,
+	38, 39, 40, 40, 41, 42, 42, 43, 44, 44, 45,
+	46, 47, 47, 48, 49, 49, 50, 51, 52, 52, 53,
+	54, 55, 55, 56, 57, 58, 58, 59, 60, 61, 61,
+	62, 63, 64, 64, 65, 66, 67, 67, 68, 69, 70,
+	70, 71, 72, 73, 74, 74, 75, 76, 77, 77, 78,
+	79, 80, 81, 81, 82, 83, 84, 84, 85, 86, 87,
+	88, 88, 89, 90, 91, 92, 92, 93, 94, 95, 96,
+	96, 97, 98, 99, 100, 101, 101, 102, 103, 104, 105,
+	105, 106, 107, 108, 109, 110, 110, 111, 112, 113, 114,
+	115, 115, 116, 117, 118, 119, 120, 120, 121, 122, 123,
+	124, 125, 125, 126, 127, 128, 129, 130, 131, 131, 132,
+	133, 134, 135, 136, 137, 137, 138, 139, 140, 141, 142,
+	143, 143, 144, 145, 146, 147, 148, 149, 150, 150, 151,
+	152, 153, 154, 155, 156, 157, 157, 158, 159, 160, 161,
+	162, 163, 164, 164, 165, 166, 167, 168, 169, 170, 171,
+	172, 172, 173, 174, 175, 176, 177, 178, 179, 180, 180,
+	181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 190,
+	191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 200,
+	201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211,
+	211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221,
+	222, 223, 224, 224, 225, 226, 227, 228, 229, 230, 231,
+	232, 233, 234, 235, 236, 237, 238, 238, 239, 240, 241,
+	242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252,
+	253, 254, 255, 256, 256, 257, 258, 259, 260, 261, 262,
+	263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273,
+	274, 275, 276, 277, 278, 279, 280, 280, 281, 282, 283,
+	284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
+	295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305,
+	306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316,
+	317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327,
+	328, 329, 330, 331, 332, 333, 334, 334, 335, 336, 337,
+	338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348,
+	349, 350, 351, 353, 354, 355, 356, 357, 358, 359, 360,
+	361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371,
+	372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382,
+	383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393,
+	394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404,
+	405, 406, 407, 408, 409, 411, 412, 413, 414, 415, 416,
+	417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427,
+	428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 439,
+	440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450,
+	451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 462,
+	463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473,
+	474, 475, 476, 477, 478, 479, 481, 482, 483, 484, 485,
+	486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496,
+	497, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508,
+	509, 510, 511, 512, 513, 515, 516, 517, 518, 519, 520,
+	521, 522, 523, 524, 525, 526, 527, 529, 530, 531, 532,
+	533, 534, 535, 536, 537, 538, 539, 540, 541, 543, 544,
+	545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555,
+	557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567,
+	569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579,
+	581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591,
+	593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 604,
+	605, 606, 607, 608, 609, 610, 611, 612, 613, 615, 616,
+	617, 618, 619, 620, 621, 622, 623, 624, 626, 627, 628,
+	629, 630, 631, 632, 633, 634, 636, 637, 638, 639, 640,
+	641, 642, 643, 644, 646, 647, 648, 649, 650, 651, 652,
+	653, 654, 656, 657, 658, 659, 660, 661, 662, 663, 664,
+	666, 667, 668, 669, 670, 671, 672, 673, 675, 676, 677,
+	678, 679, 680, 681, 682, 683, 685, 686, 687, 688, 689,
+	690, 691, 692, 694, 695, 696, 697, 698, 699, 700, 701,
+	703, 704, 705, 706, 707, 708, 709, 710, 712, 713, 714,
+	715, 716, 717, 718, 720, 721, 722, 723, 724, 725, 726,
+	727, 729, 730, 731, 732, 733, 734, 735, 737, 738, 739,
+	740, 741, 742, 743, 745, 746, 747, 748, 749, 750, 751,
+	752, 754, 755, 756, 757, 758, 759, 760, 762, 763, 764,
+	765, 766, 767, 768, 770, 771, 772, 773, 774, 775, 776,
+	778, 779, 780, 781, 782, 783, 785, 786, 787, 788, 789,
+	790, 791, 793, 794, 795, 796, 797, 798, 799, 801, 802,
+	803, 804, 805, 806, 808, 809, 810, 811, 812, 813, 814,
+	816, 817, 818, 819, 820, 821, 823, 824, 825, 826, 827,
+	828, 830, 831, 832, 833, 834, 835, 836, 838, 839, 840,
+	841, 842, 843, 845, 846, 847, 848, 849, 850, 852, 853,
+	854, 855, 856, 857, 859, 860, 861, 862, 863, 864, 866,
+	867, 868, 869, 870, 871, 873, 874, 875, 876, 877, 878,
+	880, 881, 882, 883, 884, 885, 887, 888, 889, 890, 891,
+	892, 894, 895, 896, 897, 898, 900, 901, 902, 903, 904,
+	905, 907, 908, 909, 910, 911, 912, 914, 915, 916, 917,
+	918, 920, 921, 922, 923, 924, 925, 927, 928, 929, 930,
+	931, 932, 934, 935, 936, 937, 938, 940, 941, 942, 943,
+	944, 946, 947, 948, 949, 950, 951, 953, 954, 955, 956,
+	957, 959, 960, 961, 962, 963, 964, 966, 967, 968, 969,
+	970, 972, 973, 974, 975, 976, 978, 979, 980, 981, 982,
+	984, 985, 986, 987, 988, 989, 991, 992, 993, 994, 995,
+	997, 998, 999, 1000, 1001, 1003, 1004, 1005, 1006, 1007, 1009,
+	1010, 1011, 1012, 1013, 1015, 1016, 1017, 1018, 1019, 1021, 1022,
+	1023,
+};
+
+static const u16 xgamma10_13[GAMMA10_TABLE_LENGTH] = {
+	0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+	3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 7,
+	7, 7, 8, 8, 9, 9, 10, 10, 10, 11, 11,
+	12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17,
+	17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
+	23, 23, 24, 25, 25, 26, 26, 27, 27, 28, 28,
+	29, 30, 30, 31, 31, 32, 32, 33, 34, 34, 35,
+	35, 36, 37, 37, 38, 38, 39, 40, 40, 41, 42,
+	42, 43, 43, 44, 45, 45, 46, 47, 47, 48, 48,
+	49, 50, 50, 51, 52, 52, 53, 54, 54, 55, 56,
+	56, 57, 58, 58, 59, 60, 60, 61, 62, 62, 63,
+	64, 64, 65, 66, 67, 67, 68, 69, 69, 70, 71,
+	71, 72, 73, 74, 74, 75, 76, 76, 77, 78, 79,
+	79, 80, 81, 81, 82, 83, 84, 84, 85, 86, 87,
+	87, 88, 89, 89, 90, 91, 92, 92, 93, 94, 95,
+	95, 96, 97, 98, 98, 99, 100, 101, 102, 102, 103,
+	104, 105, 105, 106, 107, 108, 108, 109, 110, 111, 112,
+	112, 113, 114, 115, 115, 116, 117, 118, 119, 119, 120,
+	121, 122, 123, 123, 124, 125, 126, 127, 127, 128, 129,
+	130, 131, 131, 132, 133, 134, 135, 135, 136, 137, 138,
+	139, 140, 140, 141, 142, 143, 144, 145, 145, 146, 147,
+	148, 149, 149, 150, 151, 152, 153, 154, 155, 155, 156,
+	157, 158, 159, 160, 160, 161, 162, 163, 164, 165, 166,
+	166, 167, 168, 169, 170, 171, 172, 172, 173, 174, 175,
+	176, 177, 178, 178, 179, 180, 181, 182, 183, 184, 185,
+	185, 186, 187, 188, 189, 190, 191, 192, 192, 193, 194,
+	195, 196, 197, 198, 199, 200, 200, 201, 202, 203, 204,
+	205, 206, 207, 208, 209, 209, 210, 211, 212, 213, 214,
+	215, 216, 217, 218, 218, 219, 220, 221, 222, 223, 224,
+	225, 226, 227, 228, 229, 229, 230, 231, 232, 233, 234,
+	235, 236, 237, 238, 239, 240, 241, 242, 242, 243, 244,
+	245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255,
+	256, 257, 257, 258, 259, 260, 261, 262, 263, 264, 265,
+	266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276,
+	277, 278, 278, 279, 280, 281, 282, 283, 284, 285, 286,
+	287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297,
+	298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308,
+	309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319,
+	320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330,
+	331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341,
+	342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352,
+	353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363,
+	364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374,
+	375, 376, 377, 378, 379, 380, 381, 383, 384, 385, 386,
+	387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397,
+	398, 399, 400, 401, 402, 403, 404, 405, 407, 408, 409,
+	410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420,
+	421, 422, 423, 424, 426, 427, 428, 429, 430, 431, 432,
+	433, 434, 435, 436, 437, 438, 439, 440, 442, 443, 444,
+	445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455,
+	457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467,
+	468, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479,
+	480, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491,
+	493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 504,
+	505, 506, 507, 508, 509, 510, 511, 512, 513, 515, 516,
+	517, 518, 519, 520, 521, 522, 523, 525, 526, 527, 528,
+	529, 530, 531, 532, 534, 535, 536, 537, 538, 539, 540,
+	541, 542, 544, 545, 546, 547, 548, 549, 550, 551, 553,
+	554, 555, 556, 557, 558, 559, 561, 562, 563, 564, 565,
+	566, 567, 568, 570, 571, 572, 573, 574, 575, 576, 578,
+	579, 580, 581, 582, 583, 584, 586, 587, 588, 589, 590,
+	591, 592, 594, 595, 596, 597, 598, 599, 600, 602, 603,
+	604, 605, 606, 607, 608, 610, 611, 612, 613, 614, 615,
+	617, 618, 619, 620, 621, 622, 624, 625, 626, 627, 628,
+	629, 630, 632, 633, 634, 635, 636, 637, 639, 640, 641,
+	642, 643, 644, 646, 647, 648, 649, 650, 652, 653, 654,
+	655, 656, 657, 659, 660, 661, 662, 663, 664, 666, 667,
+	668, 669, 670, 671, 673, 674, 675, 676, 677, 679, 680,
+	681, 682, 683, 684, 686, 687, 688, 689, 690, 692, 693,
+	694, 695, 696, 698, 699, 700, 701, 702, 704, 705, 706,
+	707, 708, 709, 711, 712, 713, 714, 715, 717, 718, 719,
+	720, 721, 723, 724, 725, 726, 727, 729, 730, 731, 732,
+	733, 735, 736, 737, 738, 739, 741, 742, 743, 744, 746,
+	747, 748, 749, 750, 752, 753, 754, 755, 756, 758, 759,
+	760, 761, 762, 764, 765, 766, 767, 769, 770, 771, 772,
+	773, 775, 776, 777, 778, 780, 781, 782, 783, 784, 786,
+	787, 788, 789, 791, 792, 793, 794, 795, 797, 798, 799,
+	800, 802, 803, 804, 805, 807, 808, 809, 810, 811, 813,
+	814, 815, 816, 818, 819, 820, 821, 823, 824, 825, 826,
+	827, 829, 830, 831, 832, 834, 835, 836, 837, 839, 840,
+	841, 842, 844, 845, 846, 847, 849, 850, 851, 852, 854,
+	855, 856, 857, 859, 860, 861, 862, 864, 865, 866, 867,
+	869, 870, 871, 872, 874, 875, 876, 877, 879, 880, 881,
+	882, 884, 885, 886, 887, 889, 890, 891, 892, 894, 895,
+	896, 897, 899, 900, 901, 903, 904, 905, 906, 908, 909,
+	910, 911, 913, 914, 915, 916, 918, 919, 920, 922, 923,
+	924, 925, 927, 928, 929, 930, 932, 933, 934, 935, 937,
+	938, 939, 941, 942, 943, 944, 946, 947, 948, 950, 951,
+	952, 953, 955, 956, 957, 958, 960, 961, 962, 964, 965,
+	966, 967, 969, 970, 971, 973, 974, 975, 976, 978, 979,
+	980, 982, 983, 984, 985, 987, 988, 989, 991, 992, 993,
+	994, 996, 997, 998, 1000, 1001, 1002, 1004, 1005, 1006, 1007,
+	1009, 1010, 1011, 1013, 1014, 1015, 1017, 1018, 1019, 1020, 1022,
+	1023,
+};
+
+static const u16 xgamma10_14[GAMMA10_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2,
+	2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4,
+	5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8,
+	8, 9, 9, 9, 10, 10, 11, 11, 11, 12, 12,
+	12, 13, 13, 14, 14, 15, 15, 15, 16, 16, 17,
+	17, 18, 18, 18, 19, 19, 20, 20, 21, 21, 22,
+	22, 23, 23, 23, 24, 24, 25, 25, 26, 26, 27,
+	27, 28, 28, 29, 29, 30, 30, 31, 31, 32, 32,
+	33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38,
+	39, 39, 40, 41, 41, 42, 42, 43, 43, 44, 45,
+	45, 46, 46, 47, 47, 48, 49, 49, 50, 50, 51,
+	52, 52, 53, 53, 54, 55, 55, 56, 56, 57, 58,
+	58, 59, 59, 60, 61, 61, 62, 63, 63, 64, 64,
+	65, 66, 66, 67, 68, 68, 69, 70, 70, 71, 72,
+	72, 73, 74, 74, 75, 76, 76, 77, 78, 78, 79,
+	80, 80, 81, 82, 82, 83, 84, 84, 85, 86, 86,
+	87, 88, 88, 89, 90, 91, 91, 92, 93, 93, 94,
+	95, 95, 96, 97, 98, 98, 99, 100, 100, 101, 102,
+	103, 103, 104, 105, 106, 106, 107, 108, 109, 109, 110,
+	111, 111, 112, 113, 114, 114, 115, 116, 117, 117, 118,
+	119, 120, 120, 121, 122, 123, 124, 124, 125, 126, 127,
+	127, 128, 129, 130, 130, 131, 132, 133, 134, 134, 135,
+	136, 137, 138, 138, 139, 140, 141, 141, 142, 143, 144,
+	145, 145, 146, 147, 148, 149, 150, 150, 151, 152, 153,
+	154, 154, 155, 156, 157, 158, 158, 159, 160, 161, 162,
+	163, 163, 164, 165, 166, 167, 168, 168, 169, 170, 171,
+	172, 173, 173, 174, 175, 176, 177, 178, 179, 179, 180,
+	181, 182, 183, 184, 185, 185, 186, 187, 188, 189, 190,
+	191, 191, 192, 193, 194, 195, 196, 197, 198, 198, 199,
+	200, 201, 202, 203, 204, 205, 205, 206, 207, 208, 209,
+	210, 211, 212, 213, 213, 214, 215, 216, 217, 218, 219,
+	220, 221, 222, 222, 223, 224, 225, 226, 227, 228, 229,
+	230, 231, 232, 232, 233, 234, 235, 236, 237, 238, 239,
+	240, 241, 242, 243, 244, 244, 245, 246, 247, 248, 249,
+	250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 259,
+	260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270,
+	271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281,
+	282, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291,
+	292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302,
+	303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313,
+	314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324,
+	325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335,
+	336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346,
+	347, 348, 349, 351, 352, 353, 354, 355, 356, 357, 358,
+	359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369,
+	370, 371, 372, 373, 374, 375, 377, 378, 379, 380, 381,
+	382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392,
+	393, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404,
+	405, 406, 407, 408, 410, 411, 412, 413, 414, 415, 416,
+	417, 418, 419, 420, 421, 423, 424, 425, 426, 427, 428,
+	429, 430, 431, 432, 433, 435, 436, 437, 438, 439, 440,
+	441, 442, 443, 444, 446, 447, 448, 449, 450, 451, 452,
+	453, 454, 456, 457, 458, 459, 460, 461, 462, 463, 464,
+	466, 467, 468, 469, 470, 471, 472, 473, 475, 476, 477,
+	478, 479, 480, 481, 482, 484, 485, 486, 487, 488, 489,
+	490, 491, 493, 494, 495, 496, 497, 498, 499, 501, 502,
+	503, 504, 505, 506, 507, 509, 510, 511, 512, 513, 514,
+	515, 517, 518, 519, 520, 521, 522, 524, 525, 526, 527,
+	528, 529, 531, 532, 533, 534, 535, 536, 537, 539, 540,
+	541, 542, 543, 544, 546, 547, 548, 549, 550, 552, 553,
+	554, 555, 556, 557, 559, 560, 561, 562, 563, 564, 566,
+	567, 568, 569, 570, 572, 573, 574, 575, 576, 578, 579,
+	580, 581, 582, 583, 585, 586, 587, 588, 589, 591, 592,
+	593, 594, 595, 597, 598, 599, 600, 601, 603, 604, 605,
+	606, 607, 609, 610, 611, 612, 613, 615, 616, 617, 618,
+	620, 621, 622, 623, 624, 626, 627, 628, 629, 630, 632,
+	633, 634, 635, 637, 638, 639, 640, 641, 643, 644, 645,
+	646, 648, 649, 650, 651, 653, 654, 655, 656, 657, 659,
+	660, 661, 662, 664, 665, 666, 667, 669, 670, 671, 672,
+	674, 675, 676, 677, 679, 680, 681, 682, 684, 685, 686,
+	687, 689, 690, 691, 692, 694, 695, 696, 697, 699, 700,
+	701, 702, 704, 705, 706, 707, 709, 710, 711, 712, 714,
+	715, 716, 717, 719, 720, 721, 723, 724, 725, 726, 728,
+	729, 730, 731, 733, 734, 735, 737, 738, 739, 740, 742,
+	743, 744, 745, 747, 748, 749, 751, 752, 753, 754, 756,
+	757, 758, 760, 761, 762, 763, 765, 766, 767, 769, 770,
+	771, 772, 774, 775, 776, 778, 779, 780, 782, 783, 784,
+	785, 787, 788, 789, 791, 792, 793, 794, 796, 797, 798,
+	800, 801, 802, 804, 805, 806, 808, 809, 810, 811, 813,
+	814, 815, 817, 818, 819, 821, 822, 823, 825, 826, 827,
+	829, 830, 831, 833, 834, 835, 836, 838, 839, 840, 842,
+	843, 844, 846, 847, 848, 850, 851, 852, 854, 855, 856,
+	858, 859, 860, 862, 863, 864, 866, 867, 868, 870, 871,
+	872, 874, 875, 876, 878, 879, 880, 882, 883, 884, 886,
+	887, 888, 890, 891, 893, 894, 895, 897, 898, 899, 901,
+	902, 903, 905, 906, 907, 909, 910, 911, 913, 914, 915,
+	917, 918, 920, 921, 922, 924, 925, 926, 928, 929, 930,
+	932, 933, 935, 936, 937, 939, 940, 941, 943, 944, 945,
+	947, 948, 950, 951, 952, 954, 955, 956, 958, 959, 961,
+	962, 963, 965, 966, 967, 969, 970, 972, 973, 974, 976,
+	977, 978, 980, 981, 983, 984, 985, 987, 988, 990, 991,
+	992, 994, 995, 996, 998, 999, 1001, 1002, 1003, 1005, 1006,
+	1008, 1009, 1010, 1012, 1013, 1015, 1016, 1017, 1019, 1020, 1022,
+	1023,
+};
+
+static const u16 xgamma10_15[GAMMA10_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
+	1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3,
+	3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6,
+	6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9,
+	9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12,
+	13, 13, 13, 14, 14, 15, 15, 15, 16, 16, 16,
+	17, 17, 18, 18, 18, 19, 19, 20, 20, 20, 21,
+	21, 22, 22, 22, 23, 23, 24, 24, 25, 25, 25,
+	26, 26, 27, 27, 28, 28, 28, 29, 29, 30, 30,
+	31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36,
+	36, 37, 37, 38, 38, 39, 39, 40, 40, 41, 41,
+	42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47,
+	47, 48, 48, 49, 50, 50, 51, 51, 52, 52, 53,
+	53, 54, 55, 55, 56, 56, 57, 57, 58, 59, 59,
+	60, 60, 61, 62, 62, 63, 63, 64, 64, 65, 66,
+	66, 67, 67, 68, 69, 69, 70, 71, 71, 72, 72,
+	73, 74, 74, 75, 76, 76, 77, 77, 78, 79, 79,
+	80, 81, 81, 82, 83, 83, 84, 84, 85, 86, 86,
+	87, 88, 88, 89, 90, 90, 91, 92, 92, 93, 94,
+	94, 95, 96, 97, 97, 98, 99, 99, 100, 101, 101,
+	102, 103, 103, 104, 105, 106, 106, 107, 108, 108, 109,
+	110, 110, 111, 112, 113, 113, 114, 115, 116, 116, 117,
+	118, 118, 119, 120, 121, 121, 122, 123, 124, 124, 125,
+	126, 127, 127, 128, 129, 130, 130, 131, 132, 133, 133,
+	134, 135, 136, 136, 137, 138, 139, 139, 140, 141, 142,
+	143, 143, 144, 145, 146, 146, 147, 148, 149, 150, 150,
+	151, 152, 153, 154, 154, 155, 156, 157, 158, 158, 159,
+	160, 161, 162, 162, 163, 164, 165, 166, 167, 167, 168,
+	169, 170, 171, 171, 172, 173, 174, 175, 176, 176, 177,
+	178, 179, 180, 181, 181, 182, 183, 184, 185, 186, 187,
+	187, 188, 189, 190, 191, 192, 193, 193, 194, 195, 196,
+	197, 198, 199, 199, 200, 201, 202, 203, 204, 205, 206,
+	206, 207, 208, 209, 210, 211, 212, 213, 214, 214, 215,
+	216, 217, 218, 219, 220, 221, 222, 223, 223, 224, 225,
+	226, 227, 228, 229, 230, 231, 232, 233, 233, 234, 235,
+	236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 245,
+	246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256,
+	257, 258, 259, 260, 261, 261, 262, 263, 264, 265, 266,
+	267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277,
+	278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288,
+	289, 290, 291, 292, 293, 293, 294, 295, 296, 297, 298,
+	299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309,
+	310, 311, 312, 314, 315, 316, 317, 318, 319, 320, 321,
+	322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332,
+	333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343,
+	344, 345, 346, 347, 349, 350, 351, 352, 353, 354, 355,
+	356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366,
+	368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378,
+	379, 380, 381, 383, 384, 385, 386, 387, 388, 389, 390,
+	391, 392, 393, 395, 396, 397, 398, 399, 400, 401, 402,
+	403, 404, 405, 407, 408, 409, 410, 411, 412, 413, 414,
+	415, 417, 418, 419, 420, 421, 422, 423, 424, 425, 427,
+	428, 429, 430, 431, 432, 433, 434, 436, 437, 438, 439,
+	440, 441, 442, 444, 445, 446, 447, 448, 449, 450, 451,
+	453, 454, 455, 456, 457, 458, 460, 461, 462, 463, 464,
+	465, 466, 468, 469, 470, 471, 472, 473, 475, 476, 477,
+	478, 479, 480, 482, 483, 484, 485, 486, 487, 489, 490,
+	491, 492, 493, 494, 496, 497, 498, 499, 500, 501, 503,
+	504, 505, 506, 507, 509, 510, 511, 512, 513, 515, 516,
+	517, 518, 519, 521, 522, 523, 524, 525, 527, 528, 529,
+	530, 531, 533, 534, 535, 536, 537, 539, 540, 541, 542,
+	543, 545, 546, 547, 548, 550, 551, 552, 553, 554, 556,
+	557, 558, 559, 561, 562, 563, 564, 565, 567, 568, 569,
+	570, 572, 573, 574, 575, 577, 578, 579, 580, 582, 583,
+	584, 585, 587, 588, 589, 590, 591, 593, 594, 595, 596,
+	598, 599, 600, 602, 603, 604, 605, 607, 608, 609, 610,
+	612, 613, 614, 615, 617, 618, 619, 620, 622, 623, 624,
+	626, 627, 628, 629, 631, 632, 633, 634, 636, 637, 638,
+	640, 641, 642, 643, 645, 646, 647, 649, 650, 651, 652,
+	654, 655, 656, 658, 659, 660, 662, 663, 664, 665, 667,
+	668, 669, 671, 672, 673, 675, 676, 677, 678, 680, 681,
+	682, 684, 685, 686, 688, 689, 690, 692, 693, 694, 696,
+	697, 698, 700, 701, 702, 703, 705, 706, 707, 709, 710,
+	711, 713, 714, 715, 717, 718, 719, 721, 722, 723, 725,
+	726, 727, 729, 730, 731, 733, 734, 735, 737, 738, 740,
+	741, 742, 744, 745, 746, 748, 749, 750, 752, 753, 754,
+	756, 757, 758, 760, 761, 763, 764, 765, 767, 768, 769,
+	771, 772, 773, 775, 776, 778, 779, 780, 782, 783, 784,
+	786, 787, 789, 790, 791, 793, 794, 795, 797, 798, 800,
+	801, 802, 804, 805, 806, 808, 809, 811, 812, 813, 815,
+	816, 818, 819, 820, 822, 823, 825, 826, 827, 829, 830,
+	832, 833, 834, 836, 837, 839, 840, 841, 843, 844, 846,
+	847, 848, 850, 851, 853, 854, 855, 857, 858, 860, 861,
+	863, 864, 865, 867, 868, 870, 871, 872, 874, 875, 877,
+	878, 880, 881, 882, 884, 885, 887, 888, 890, 891, 892,
+	894, 895, 897, 898, 900, 901, 902, 904, 905, 907, 908,
+	910, 911, 913, 914, 915, 917, 918, 920, 921, 923, 924,
+	926, 927, 929, 930, 931, 933, 934, 936, 937, 939, 940,
+	942, 943, 945, 946, 947, 949, 950, 952, 953, 955, 956,
+	958, 959, 961, 962, 964, 965, 967, 968, 969, 971, 972,
+	974, 975, 977, 978, 980, 981, 983, 984, 986, 987, 989,
+	990, 992, 993, 995, 996, 998, 999, 1001, 1002, 1004, 1005,
+	1007, 1008, 1010, 1011, 1013, 1014, 1016, 1017, 1019, 1020, 1022,
+	1023,
+};
+
+static const u16 xgamma10_16[GAMMA10_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
+	2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4,
+	4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6,
+	7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9,
+	10, 10, 10, 10, 11, 11, 11, 12, 12, 12, 12,
+	13, 13, 13, 14, 14, 14, 15, 15, 15, 16, 16,
+	16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 20,
+	20, 21, 21, 21, 22, 22, 22, 23, 23, 24, 24,
+	24, 25, 25, 26, 26, 26, 27, 27, 28, 28, 28,
+	29, 29, 30, 30, 31, 31, 31, 32, 32, 33, 33,
+	34, 34, 35, 35, 35, 36, 36, 37, 37, 38, 38,
+	39, 39, 40, 40, 41, 41, 41, 42, 42, 43, 43,
+	44, 44, 45, 45, 46, 46, 47, 47, 48, 48, 49,
+	49, 50, 50, 51, 52, 52, 53, 53, 54, 54, 55,
+	55, 56, 56, 57, 57, 58, 58, 59, 60, 60, 61,
+	61, 62, 62, 63, 63, 64, 65, 65, 66, 66, 67,
+	67, 68, 69, 69, 70, 70, 71, 72, 72, 73, 73,
+	74, 75, 75, 76, 76, 77, 78, 78, 79, 79, 80,
+	81, 81, 82, 82, 83, 84, 84, 85, 86, 86, 87,
+	87, 88, 89, 89, 90, 91, 91, 92, 93, 93, 94,
+	95, 95, 96, 97, 97, 98, 99, 99, 100, 101, 101,
+	102, 103, 103, 104, 105, 105, 106, 107, 107, 108, 109,
+	109, 110, 111, 111, 112, 113, 114, 114, 115, 116, 116,
+	117, 118, 119, 119, 120, 121, 121, 122, 123, 124, 124,
+	125, 126, 126, 127, 128, 129, 129, 130, 131, 132, 132,
+	133, 134, 135, 135, 136, 137, 138, 138, 139, 140, 141,
+	141, 142, 143, 144, 144, 145, 146, 147, 148, 148, 149,
+	150, 151, 151, 152, 153, 154, 155, 155, 156, 157, 158,
+	159, 159, 160, 161, 162, 163, 163, 164, 165, 166, 167,
+	167, 168, 169, 170, 171, 171, 172, 173, 174, 175, 176,
+	176, 177, 178, 179, 180, 181, 181, 182, 183, 184, 185,
+	186, 186, 187, 188, 189, 190, 191, 192, 192, 193, 194,
+	195, 196, 197, 198, 198, 199, 200, 201, 202, 203, 204,
+	204, 205, 206, 207, 208, 209, 210, 211, 212, 212, 213,
+	214, 215, 216, 217, 218, 219, 220, 220, 221, 222, 223,
+	224, 225, 226, 227, 228, 229, 230, 230, 231, 232, 233,
+	234, 235, 236, 237, 238, 239, 240, 241, 242, 242, 243,
+	244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254,
+	255, 256, 257, 258, 258, 259, 260, 261, 262, 263, 264,
+	265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275,
+	276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286,
+	287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297,
+	298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308,
+	309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319,
+	320, 321, 322, 323, 324, 325, 326, 327, 329, 330, 331,
+	332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342,
+	343, 344, 345, 346, 348, 349, 350, 351, 352, 353, 354,
+	355, 356, 357, 358, 359, 360, 362, 363, 364, 365, 366,
+	367, 368, 369, 370, 371, 372, 374, 375, 376, 377, 378,
+	379, 380, 381, 382, 383, 385, 386, 387, 388, 389, 390,
+	391, 392, 393, 395, 396, 397, 398, 399, 400, 401, 402,
+	404, 405, 406, 407, 408, 409, 410, 411, 413, 414, 415,
+	416, 417, 418, 419, 421, 422, 423, 424, 425, 426, 428,
+	429, 430, 431, 432, 433, 434, 436, 437, 438, 439, 440,
+	441, 443, 444, 445, 446, 447, 448, 450, 451, 452, 453,
+	454, 456, 457, 458, 459, 460, 461, 463, 464, 465, 466,
+	467, 469, 470, 471, 472, 473, 475, 476, 477, 478, 479,
+	481, 482, 483, 484, 485, 487, 488, 489, 490, 491, 493,
+	494, 495, 496, 498, 499, 500, 501, 502, 504, 505, 506,
+	507, 509, 510, 511, 512, 514, 515, 516, 517, 519, 520,
+	521, 522, 523, 525, 526, 527, 528, 530, 531, 532, 533,
+	535, 536, 537, 538, 540, 541, 542, 544, 545, 546, 547,
+	549, 550, 551, 552, 554, 555, 556, 557, 559, 560, 561,
+	563, 564, 565, 566, 568, 569, 570, 572, 573, 574, 575,
+	577, 578, 579, 581, 582, 583, 584, 586, 587, 588, 590,
+	591, 592, 594, 595, 596, 598, 599, 600, 601, 603, 604,
+	605, 607, 608, 609, 611, 612, 613, 615, 616, 617, 619,
+	620, 621, 623, 624, 625, 627, 628, 629, 631, 632, 633,
+	635, 636, 637, 639, 640, 641, 643, 644, 645, 647, 648,
+	649, 651, 652, 653, 655, 656, 657, 659, 660, 662, 663,
+	664, 666, 667, 668, 670, 671, 672, 674, 675, 677, 678,
+	679, 681, 682, 683, 685, 686, 688, 689, 690, 692, 693,
+	694, 696, 697, 699, 700, 701, 703, 704, 706, 707, 708,
+	710, 711, 712, 714, 715, 717, 718, 719, 721, 722, 724,
+	725, 727, 728, 729, 731, 732, 734, 735, 736, 738, 739,
+	741, 742, 743, 745, 746, 748, 749, 751, 752, 753, 755,
+	756, 758, 759, 761, 762, 763, 765, 766, 768, 769, 771,
+	772, 774, 775, 776, 778, 779, 781, 782, 784, 785, 787,
+	788, 789, 791, 792, 794, 795, 797, 798, 800, 801, 803,
+	804, 805, 807, 808, 810, 811, 813, 814, 816, 817, 819,
+	820, 822, 823, 825, 826, 827, 829, 830, 832, 833, 835,
+	836, 838, 839, 841, 842, 844, 845, 847, 848, 850, 851,
+	853, 854, 856, 857, 859, 860, 862, 863, 865, 866, 868,
+	869, 871, 872, 874, 875, 877, 878, 880, 881, 883, 884,
+	886, 887, 889, 890, 892, 893, 895, 897, 898, 900, 901,
+	903, 904, 906, 907, 909, 910, 912, 913, 915, 916, 918,
+	919, 921, 923, 924, 926, 927, 929, 930, 932, 933, 935,
+	936, 938, 940, 941, 943, 944, 946, 947, 949, 950, 952,
+	954, 955, 957, 958, 960, 961, 963, 964, 966, 968, 969,
+	971, 972, 974, 975, 977, 979, 980, 982, 983, 985, 986,
+	988, 990, 991, 993, 994, 996, 998, 999, 1001, 1002, 1004,
+	1005, 1007, 1009, 1010, 1012, 1013, 1015, 1017, 1018, 1020, 1021,
+	1023,
+};
+
+static const u16 xgamma10_17[GAMMA10_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3,
+	3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5,
+	5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7,
+	7, 7, 8, 8, 8, 8, 8, 9, 9, 9, 9,
+	10, 10, 10, 10, 11, 11, 11, 12, 12, 12, 12,
+	13, 13, 13, 13, 14, 14, 14, 15, 15, 15, 15,
+	16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19,
+	19, 20, 20, 20, 21, 21, 21, 22, 22, 22, 23,
+	23, 23, 24, 24, 25, 25, 25, 26, 26, 26, 27,
+	27, 28, 28, 28, 29, 29, 29, 30, 30, 31, 31,
+	31, 32, 32, 33, 33, 34, 34, 34, 35, 35, 36,
+	36, 37, 37, 37, 38, 38, 39, 39, 40, 40, 40,
+	41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46,
+	46, 46, 47, 47, 48, 48, 49, 49, 50, 50, 51,
+	51, 52, 52, 53, 53, 54, 54, 55, 55, 56, 56,
+	57, 57, 58, 58, 59, 60, 60, 61, 61, 62, 62,
+	63, 63, 64, 64, 65, 65, 66, 67, 67, 68, 68,
+	69, 69, 70, 70, 71, 72, 72, 73, 73, 74, 74,
+	75, 76, 76, 77, 77, 78, 79, 79, 80, 80, 81,
+	82, 82, 83, 83, 84, 85, 85, 86, 86, 87, 88,
+	88, 89, 89, 90, 91, 91, 92, 93, 93, 94, 95,
+	95, 96, 96, 97, 98, 98, 99, 100, 100, 101, 102,
+	102, 103, 104, 104, 105, 106, 106, 107, 108, 108, 109,
+	110, 110, 111, 112, 112, 113, 114, 114, 115, 116, 116,
+	117, 118, 119, 119, 120, 121, 121, 122, 123, 124, 124,
+	125, 126, 126, 127, 128, 129, 129, 130, 131, 131, 132,
+	133, 134, 134, 135, 136, 137, 137, 138, 139, 140, 140,
+	141, 142, 143, 143, 144, 145, 146, 146, 147, 148, 149,
+	149, 150, 151, 152, 153, 153, 154, 155, 156, 156, 157,
+	158, 159, 160, 160, 161, 162, 163, 164, 164, 165, 166,
+	167, 168, 168, 169, 170, 171, 172, 172, 173, 174, 175,
+	176, 177, 177, 178, 179, 180, 181, 182, 182, 183, 184,
+	185, 186, 187, 187, 188, 189, 190, 191, 192, 193, 193,
+	194, 195, 196, 197, 198, 199, 199, 200, 201, 202, 203,
+	204, 205, 206, 206, 207, 208, 209, 210, 211, 212, 213,
+	213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 222,
+	223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233,
+	233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243,
+	244, 245, 246, 247, 248, 248, 249, 250, 251, 252, 253,
+	254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+	265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275,
+	276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286,
+	287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297,
+	298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308,
+	309, 310, 311, 312, 313, 314, 315, 316, 317, 319, 320,
+	321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331,
+	332, 333, 334, 336, 337, 338, 339, 340, 341, 342, 343,
+	344, 345, 346, 347, 349, 350, 351, 352, 353, 354, 355,
+	356, 357, 358, 360, 361, 362, 363, 364, 365, 366, 367,
+	368, 370, 371, 372, 373, 374, 375, 376, 377, 379, 380,
+	381, 382, 383, 384, 385, 386, 388, 389, 390, 391, 392,
+	393, 394, 396, 397, 398, 399, 400, 401, 403, 404, 405,
+	406, 407, 408, 409, 411, 412, 413, 414, 415, 417, 418,
+	419, 420, 421, 422, 424, 425, 426, 427, 428, 430, 431,
+	432, 433, 434, 435, 437, 438, 439, 440, 441, 443, 444,
+	445, 446, 448, 449, 450, 451, 452, 454, 455, 456, 457,
+	458, 460, 461, 462, 463, 465, 466, 467, 468, 469, 471,
+	472, 473, 474, 476, 477, 478, 479, 481, 482, 483, 484,
+	486, 487, 488, 489, 491, 492, 493, 494, 496, 497, 498,
+	499, 501, 502, 503, 505, 506, 507, 508, 510, 511, 512,
+	513, 515, 516, 517, 519, 520, 521, 522, 524, 525, 526,
+	528, 529, 530, 532, 533, 534, 535, 537, 538, 539, 541,
+	542, 543, 545, 546, 547, 549, 550, 551, 552, 554, 555,
+	556, 558, 559, 560, 562, 563, 564, 566, 567, 568, 570,
+	571, 572, 574, 575, 576, 578, 579, 580, 582, 583, 584,
+	586, 587, 589, 590, 591, 593, 594, 595, 597, 598, 599,
+	601, 602, 604, 605, 606, 608, 609, 610, 612, 613, 615,
+	616, 617, 619, 620, 621, 623, 624, 626, 627, 628, 630,
+	631, 633, 634, 635, 637, 638, 640, 641, 642, 644, 645,
+	647, 648, 649, 651, 652, 654, 655, 656, 658, 659, 661,
+	662, 664, 665, 666, 668, 669, 671, 672, 674, 675, 676,
+	678, 679, 681, 682, 684, 685, 686, 688, 689, 691, 692,
+	694, 695, 697, 698, 699, 701, 702, 704, 705, 707, 708,
+	710, 711, 713, 714, 716, 717, 718, 720, 721, 723, 724,
+	726, 727, 729, 730, 732, 733, 735, 736, 738, 739, 741,
+	742, 744, 745, 747, 748, 750, 751, 753, 754, 756, 757,
+	759, 760, 762, 763, 765, 766, 768, 769, 771, 772, 774,
+	775, 777, 778, 780, 781, 783, 784, 786, 787, 789, 790,
+	792, 793, 795, 797, 798, 800, 801, 803, 804, 806, 807,
+	809, 810, 812, 814, 815, 817, 818, 820, 821, 823, 824,
+	826, 827, 829, 831, 832, 834, 835, 837, 838, 840, 842,
+	843, 845, 846, 848, 849, 851, 853, 854, 856, 857, 859,
+	860, 862, 864, 865, 867, 868, 870, 872, 873, 875, 876,
+	878, 880, 881, 883, 884, 886, 888, 889, 891, 892, 894,
+	896, 897, 899, 900, 902, 904, 905, 907, 908, 910, 912,
+	913, 915, 917, 918, 920, 921, 923, 925, 926, 928, 930,
+	931, 933, 935, 936, 938, 939, 941, 943, 944, 946, 948,
+	949, 951, 953, 954, 956, 958, 959, 961, 963, 964, 966,
+	968, 969, 971, 973, 974, 976, 978, 979, 981, 983, 984,
+	986, 988, 989, 991, 993, 994, 996, 998, 999, 1001, 1003,
+	1004, 1006, 1008, 1009, 1011, 1013, 1015, 1016, 1018, 1020, 1021,
+	1023,
+};
+
+static const u16 xgamma10_18[GAMMA10_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,
+	2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3,
+	4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5,
+	5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7,
+	7, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9,
+	10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12,
+	12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15,
+	15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18,
+	18, 19, 19, 19, 20, 20, 20, 21, 21, 21, 22,
+	22, 22, 23, 23, 23, 24, 24, 24, 25, 25, 25,
+	26, 26, 26, 27, 27, 27, 28, 28, 29, 29, 29,
+	30, 30, 30, 31, 31, 32, 32, 32, 33, 33, 33,
+	34, 34, 35, 35, 35, 36, 36, 37, 37, 38, 38,
+	38, 39, 39, 40, 40, 40, 41, 41, 42, 42, 43,
+	43, 43, 44, 44, 45, 45, 46, 46, 47, 47, 48,
+	48, 48, 49, 49, 50, 50, 51, 51, 52, 52, 53,
+	53, 54, 54, 55, 55, 56, 56, 57, 57, 58, 58,
+	59, 59, 60, 60, 61, 61, 62, 62, 63, 63, 64,
+	64, 65, 65, 66, 66, 67, 68, 68, 69, 69, 70,
+	70, 71, 71, 72, 72, 73, 74, 74, 75, 75, 76,
+	76, 77, 78, 78, 79, 79, 80, 80, 81, 82, 82,
+	83, 83, 84, 85, 85, 86, 86, 87, 88, 88, 89,
+	89, 90, 91, 91, 92, 92, 93, 94, 94, 95, 96,
+	96, 97, 97, 98, 99, 99, 100, 101, 101, 102, 103,
+	103, 104, 104, 105, 106, 106, 107, 108, 108, 109, 110,
+	110, 111, 112, 112, 113, 114, 114, 115, 116, 117, 117,
+	118, 119, 119, 120, 121, 121, 122, 123, 123, 124, 125,
+	126, 126, 127, 128, 128, 129, 130, 131, 131, 132, 133,
+	133, 134, 135, 136, 136, 137, 138, 139, 139, 140, 141,
+	142, 142, 143, 144, 145, 145, 146, 147, 148, 148, 149,
+	150, 151, 151, 152, 153, 154, 155, 155, 156, 157, 158,
+	158, 159, 160, 161, 162, 162, 163, 164, 165, 166, 166,
+	167, 168, 169, 170, 170, 171, 172, 173, 174, 175, 175,
+	176, 177, 178, 179, 179, 180, 181, 182, 183, 184, 184,
+	185, 186, 187, 188, 189, 190, 190, 191, 192, 193, 194,
+	195, 196, 196, 197, 198, 199, 200, 201, 202, 203, 203,
+	204, 205, 206, 207, 208, 209, 210, 210, 211, 212, 213,
+	214, 215, 216, 217, 218, 219, 219, 220, 221, 222, 223,
+	224, 225, 226, 227, 228, 229, 230, 230, 231, 232, 233,
+	234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244,
+	245, 246, 247, 247, 248, 249, 250, 251, 252, 253, 254,
+	255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265,
+	266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276,
+	277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287,
+	288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298,
+	299, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310,
+	311, 312, 313, 314, 315, 316, 317, 319, 320, 321, 322,
+	323, 324, 325, 326, 327, 328, 329, 330, 331, 333, 334,
+	335, 336, 337, 338, 339, 340, 341, 342, 344, 345, 346,
+	347, 348, 349, 350, 351, 353, 354, 355, 356, 357, 358,
+	359, 360, 362, 363, 364, 365, 366, 367, 368, 370, 371,
+	372, 373, 374, 375, 376, 378, 379, 380, 381, 382, 383,
+	385, 386, 387, 388, 389, 390, 392, 393, 394, 395, 396,
+	397, 399, 400, 401, 402, 403, 405, 406, 407, 408, 409,
+	411, 412, 413, 414, 415, 417, 418, 419, 420, 421, 423,
+	424, 425, 426, 427, 429, 430, 431, 432, 434, 435, 436,
+	437, 439, 440, 441, 442, 443, 445, 446, 447, 448, 450,
+	451, 452, 453, 455, 456, 457, 458, 460, 461, 462, 464,
+	465, 466, 467, 469, 470, 471, 472, 474, 475, 476, 478,
+	479, 480, 481, 483, 484, 485, 487, 488, 489, 490, 492,
+	493, 494, 496, 497, 498, 500, 501, 502, 504, 505, 506,
+	507, 509, 510, 511, 513, 514, 515, 517, 518, 519, 521,
+	522, 523, 525, 526, 527, 529, 530, 531, 533, 534, 535,
+	537, 538, 540, 541, 542, 544, 545, 546, 548, 549, 550,
+	552, 553, 555, 556, 557, 559, 560, 561, 563, 564, 566,
+	567, 568, 570, 571, 572, 574, 575, 577, 578, 579, 581,
+	582, 584, 585, 586, 588, 589, 591, 592, 594, 595, 596,
+	598, 599, 601, 602, 603, 605, 606, 608, 609, 611, 612,
+	613, 615, 616, 618, 619, 621, 622, 624, 625, 626, 628,
+	629, 631, 632, 634, 635, 637, 638, 640, 641, 642, 644,
+	645, 647, 648, 650, 651, 653, 654, 656, 657, 659, 660,
+	662, 663, 665, 666, 668, 669, 671, 672, 673, 675, 676,
+	678, 679, 681, 682, 684, 686, 687, 689, 690, 692, 693,
+	695, 696, 698, 699, 701, 702, 704, 705, 707, 708, 710,
+	711, 713, 714, 716, 717, 719, 721, 722, 724, 725, 727,
+	728, 730, 731, 733, 734, 736, 738, 739, 741, 742, 744,
+	745, 747, 749, 750, 752, 753, 755, 756, 758, 760, 761,
+	763, 764, 766, 767, 769, 771, 772, 774, 775, 777, 779,
+	780, 782, 783, 785, 787, 788, 790, 791, 793, 795, 796,
+	798, 799, 801, 803, 804, 806, 807, 809, 811, 812, 814,
+	816, 817, 819, 820, 822, 824, 825, 827, 829, 830, 832,
+	834, 835, 837, 839, 840, 842, 843, 845, 847, 848, 850,
+	852, 853, 855, 857, 858, 860, 862, 863, 865, 867, 868,
+	870, 872, 873, 875, 877, 878, 880, 882, 884, 885, 887,
+	889, 890, 892, 894, 895, 897, 899, 900, 902, 904, 906,
+	907, 909, 911, 912, 914, 916, 918, 919, 921, 923, 924,
+	926, 928, 930, 931, 933, 935, 936, 938, 940, 942, 943,
+	945, 947, 949, 950, 952, 954, 956, 957, 959, 961, 963,
+	964, 966, 968, 970, 971, 973, 975, 977, 978, 980, 982,
+	984, 986, 987, 989, 991, 993, 994, 996, 998, 1000, 1002,
+	1003, 1005, 1007, 1009, 1010, 1012, 1014, 1016, 1018, 1019, 1021,
+	1023,
+};
+
+static const u16 xgamma10_19[GAMMA10_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+	3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4,
+	4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5,
+	6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7,
+	8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9,
+	10, 10, 10, 10, 11, 11, 11, 11, 11, 12, 12,
+	12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15,
+	15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 17,
+	18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 21,
+	21, 21, 22, 22, 22, 22, 23, 23, 23, 24, 24,
+	24, 25, 25, 25, 26, 26, 26, 27, 27, 27, 28,
+	28, 28, 29, 29, 29, 30, 30, 30, 31, 31, 32,
+	32, 32, 33, 33, 33, 34, 34, 35, 35, 35, 36,
+	36, 36, 37, 37, 38, 38, 38, 39, 39, 40, 40,
+	41, 41, 41, 42, 42, 43, 43, 43, 44, 44, 45,
+	45, 46, 46, 46, 47, 47, 48, 48, 49, 49, 50,
+	50, 51, 51, 51, 52, 52, 53, 53, 54, 54, 55,
+	55, 56, 56, 57, 57, 58, 58, 59, 59, 60, 60,
+	61, 61, 62, 62, 63, 63, 64, 64, 65, 65, 66,
+	66, 67, 67, 68, 68, 69, 69, 70, 70, 71, 71,
+	72, 72, 73, 74, 74, 75, 75, 76, 76, 77, 77,
+	78, 79, 79, 80, 80, 81, 81, 82, 83, 83, 84,
+	84, 85, 85, 86, 87, 87, 88, 88, 89, 90, 90,
+	91, 91, 92, 93, 93, 94, 94, 95, 96, 96, 97,
+	98, 98, 99, 99, 100, 101, 101, 102, 103, 103, 104,
+	105, 105, 106, 107, 107, 108, 108, 109, 110, 110, 111,
+	112, 112, 113, 114, 114, 115, 116, 116, 117, 118, 119,
+	119, 120, 121, 121, 122, 123, 123, 124, 125, 125, 126,
+	127, 128, 128, 129, 130, 130, 131, 132, 133, 133, 134,
+	135, 135, 136, 137, 138, 138, 139, 140, 141, 141, 142,
+	143, 144, 144, 145, 146, 147, 147, 148, 149, 150, 150,
+	151, 152, 153, 154, 154, 155, 156, 157, 157, 158, 159,
+	160, 161, 161, 162, 163, 164, 165, 165, 166, 167, 168,
+	169, 169, 170, 171, 172, 173, 173, 174, 175, 176, 177,
+	178, 178, 179, 180, 181, 182, 183, 183, 184, 185, 186,
+	187, 188, 188, 189, 190, 191, 192, 193, 194, 195, 195,
+	196, 197, 198, 199, 200, 201, 201, 202, 203, 204, 205,
+	206, 207, 208, 209, 209, 210, 211, 212, 213, 214, 215,
+	216, 217, 218, 219, 219, 220, 221, 222, 223, 224, 225,
+	226, 227, 228, 229, 230, 231, 232, 232, 233, 234, 235,
+	236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246,
+	247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257,
+	258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268,
+	269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279,
+	280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290,
+	291, 292, 293, 294, 295, 296, 297, 299, 300, 301, 302,
+	303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 314,
+	315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 326,
+	327, 328, 329, 330, 331, 332, 333, 334, 336, 337, 338,
+	339, 340, 341, 342, 343, 345, 346, 347, 348, 349, 350,
+	351, 353, 354, 355, 356, 357, 358, 360, 361, 362, 363,
+	364, 365, 367, 368, 369, 370, 371, 372, 374, 375, 376,
+	377, 378, 379, 381, 382, 383, 384, 385, 387, 388, 389,
+	390, 391, 393, 394, 395, 396, 397, 399, 400, 401, 402,
+	404, 405, 406, 407, 408, 410, 411, 412, 413, 415, 416,
+	417, 418, 420, 421, 422, 423, 425, 426, 427, 428, 430,
+	431, 432, 433, 435, 436, 437, 439, 440, 441, 442, 444,
+	445, 446, 447, 449, 450, 451, 453, 454, 455, 456, 458,
+	459, 460, 462, 463, 464, 466, 467, 468, 470, 471, 472,
+	473, 475, 476, 477, 479, 480, 481, 483, 484, 485, 487,
+	488, 489, 491, 492, 493, 495, 496, 498, 499, 500, 502,
+	503, 504, 506, 507, 508, 510, 511, 512, 514, 515, 517,
+	518, 519, 521, 522, 523, 525, 526, 528, 529, 530, 532,
+	533, 535, 536, 537, 539, 540, 542, 543, 544, 546, 547,
+	549, 550, 551, 553, 554, 556, 557, 559, 560, 561, 563,
+	564, 566, 567, 569, 570, 572, 573, 574, 576, 577, 579,
+	580, 582, 583, 585, 586, 587, 589, 590, 592, 593, 595,
+	596, 598, 599, 601, 602, 604, 605, 607, 608, 610, 611,
+	613, 614, 616, 617, 619, 620, 622, 623, 625, 626, 628,
+	629, 631, 632, 634, 635, 637, 638, 640, 641, 643, 644,
+	646, 647, 649, 650, 652, 653, 655, 656, 658, 660, 661,
+	663, 664, 666, 667, 669, 670, 672, 674, 675, 677, 678,
+	680, 681, 683, 684, 686, 688, 689, 691, 692, 694, 696,
+	697, 699, 700, 702, 703, 705, 707, 708, 710, 711, 713,
+	715, 716, 718, 719, 721, 723, 724, 726, 728, 729, 731,
+	732, 734, 736, 737, 739, 741, 742, 744, 745, 747, 749,
+	750, 752, 754, 755, 757, 759, 760, 762, 764, 765, 767,
+	768, 770, 772, 773, 775, 777, 778, 780, 782, 783, 785,
+	787, 789, 790, 792, 794, 795, 797, 799, 800, 802, 804,
+	805, 807, 809, 810, 812, 814, 816, 817, 819, 821, 822,
+	824, 826, 828, 829, 831, 833, 834, 836, 838, 840, 841,
+	843, 845, 847, 848, 850, 852, 854, 855, 857, 859, 861,
+	862, 864, 866, 868, 869, 871, 873, 875, 876, 878, 880,
+	882, 883, 885, 887, 889, 891, 892, 894, 896, 898, 899,
+	901, 903, 905, 907, 908, 910, 912, 914, 916, 917, 919,
+	921, 923, 925, 926, 928, 930, 932, 934, 936, 937, 939,
+	941, 943, 945, 947, 948, 950, 952, 954, 956, 958, 959,
+	961, 963, 965, 967, 969, 970, 972, 974, 976, 978, 980,
+	982, 983, 985, 987, 989, 991, 993, 995, 997, 998, 1000,
+	1002, 1004, 1006, 1008, 1010, 1012, 1014, 1015, 1017, 1019, 1021,
+	1023,
+};
+
+static const u16 xgamma10_20[GAMMA10_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
+	2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3,
+	3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4,
+	4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 6,
+	6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7,
+	8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9,
+	10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 12,
+	12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14,
+	14, 15, 15, 15, 15, 16, 16, 16, 16, 17, 17,
+	17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 20,
+	20, 20, 21, 21, 21, 21, 22, 22, 22, 23, 23,
+	23, 23, 24, 24, 24, 25, 25, 25, 26, 26, 26,
+	27, 27, 27, 28, 28, 28, 29, 29, 29, 30, 30,
+	30, 31, 31, 31, 32, 32, 32, 33, 33, 33, 34,
+	34, 35, 35, 35, 36, 36, 36, 37, 37, 38, 38,
+	38, 39, 39, 39, 40, 40, 41, 41, 41, 42, 42,
+	43, 43, 44, 44, 44, 45, 45, 46, 46, 46, 47,
+	47, 48, 48, 49, 49, 49, 50, 50, 51, 51, 52,
+	52, 53, 53, 54, 54, 54, 55, 55, 56, 56, 57,
+	57, 58, 58, 59, 59, 60, 60, 61, 61, 62, 62,
+	63, 63, 64, 64, 65, 65, 66, 66, 67, 67, 68,
+	68, 69, 69, 70, 70, 71, 71, 72, 72, 73, 73,
+	74, 74, 75, 76, 76, 77, 77, 78, 78, 79, 79,
+	80, 81, 81, 82, 82, 83, 83, 84, 84, 85, 86,
+	86, 87, 87, 88, 89, 89, 90, 90, 91, 92, 92,
+	93, 93, 94, 95, 95, 96, 96, 97, 98, 98, 99,
+	99, 100, 101, 101, 102, 103, 103, 104, 105, 105, 106,
+	106, 107, 108, 108, 109, 110, 110, 111, 112, 112, 113,
+	114, 114, 115, 116, 116, 117, 118, 118, 119, 120, 120,
+	121, 122, 122, 123, 124, 125, 125, 126, 127, 127, 128,
+	129, 130, 130, 131, 132, 132, 133, 134, 135, 135, 136,
+	137, 137, 138, 139, 140, 140, 141, 142, 143, 143, 144,
+	145, 146, 146, 147, 148, 149, 149, 150, 151, 152, 153,
+	153, 154, 155, 156, 156, 157, 158, 159, 160, 160, 161,
+	162, 163, 164, 164, 165, 166, 167, 168, 168, 169, 170,
+	171, 172, 172, 173, 174, 175, 176, 177, 177, 178, 179,
+	180, 181, 182, 182, 183, 184, 185, 186, 187, 188, 188,
+	189, 190, 191, 192, 193, 194, 194, 195, 196, 197, 198,
+	199, 200, 201, 201, 202, 203, 204, 205, 206, 207, 208,
+	209, 210, 210, 211, 212, 213, 214, 215, 216, 217, 218,
+	219, 220, 221, 221, 222, 223, 224, 225, 226, 227, 228,
+	229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
+	240, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249,
+	250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260,
+	261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271,
+	273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283,
+	284, 285, 286, 287, 288, 289, 290, 291, 292, 294, 295,
+	296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 307,
+	308, 309, 310, 311, 312, 313, 314, 315, 316, 318, 319,
+	320, 321, 322, 323, 324, 325, 327, 328, 329, 330, 331,
+	332, 333, 335, 336, 337, 338, 339, 340, 341, 343, 344,
+	345, 346, 347, 348, 350, 351, 352, 353, 354, 355, 357,
+	358, 359, 360, 361, 363, 364, 365, 366, 367, 369, 370,
+	371, 372, 373, 375, 376, 377, 378, 379, 381, 382, 383,
+	384, 386, 387, 388, 389, 390, 392, 393, 394, 395, 397,
+	398, 399, 400, 402, 403, 404, 405, 407, 408, 409, 410,
+	412, 413, 414, 416, 417, 418, 419, 421, 422, 423, 425,
+	426, 427, 428, 430, 431, 432, 434, 435, 436, 437, 439,
+	440, 441, 443, 444, 445, 447, 448, 449, 451, 452, 453,
+	455, 456, 457, 459, 460, 461, 463, 464, 465, 467, 468,
+	469, 471, 472, 474, 475, 476, 478, 479, 480, 482, 483,
+	484, 486, 487, 489, 490, 491, 493, 494, 496, 497, 498,
+	500, 501, 503, 504, 505, 507, 508, 510, 511, 512, 514,
+	515, 517, 518, 519, 521, 522, 524, 525, 527, 528, 530,
+	531, 532, 534, 535, 537, 538, 540, 541, 543, 544, 545,
+	547, 548, 550, 551, 553, 554, 556, 557, 559, 560, 562,
+	563, 565, 566, 568, 569, 571, 572, 574, 575, 577, 578,
+	580, 581, 583, 584, 586, 587, 589, 590, 592, 593, 595,
+	596, 598, 599, 601, 602, 604, 605, 607, 609, 610, 612,
+	613, 615, 616, 618, 619, 621, 622, 624, 626, 627, 629,
+	630, 632, 633, 635, 637, 638, 640, 641, 643, 645, 646,
+	648, 649, 651, 652, 654, 656, 657, 659, 660, 662, 664,
+	665, 667, 669, 670, 672, 673, 675, 677, 678, 680, 682,
+	683, 685, 686, 688, 690, 691, 693, 695, 696, 698, 700,
+	701, 703, 705, 706, 708, 710, 711, 713, 715, 716, 718,
+	720, 721, 723, 725, 726, 728, 730, 731, 733, 735, 736,
+	738, 740, 742, 743, 745, 747, 748, 750, 752, 754, 755,
+	757, 759, 760, 762, 764, 766, 767, 769, 771, 773, 774,
+	776, 778, 780, 781, 783, 785, 787, 788, 790, 792, 794,
+	795, 797, 799, 801, 802, 804, 806, 808, 809, 811, 813,
+	815, 817, 818, 820, 822, 824, 826, 827, 829, 831, 833,
+	835, 836, 838, 840, 842, 844, 845, 847, 849, 851, 853,
+	855, 856, 858, 860, 862, 864, 866, 867, 869, 871, 873,
+	875, 877, 878, 880, 882, 884, 886, 888, 890, 892, 893,
+	895, 897, 899, 901, 903, 905, 907, 908, 910, 912, 914,
+	916, 918, 920, 922, 924, 925, 927, 929, 931, 933, 935,
+	937, 939, 941, 943, 945, 946, 948, 950, 952, 954, 956,
+	958, 960, 962, 964, 966, 968, 970, 972, 974, 976, 978,
+	979, 981, 983, 985, 987, 989, 991, 993, 995, 997, 999,
+	1001, 1003, 1005, 1007, 1009, 1011, 1013, 1015, 1017, 1019, 1021,
+	1023,
+};
+
+static const u16 xgamma10_21[GAMMA10_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+	2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3,
+	3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
+	4, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6,
+	6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
+	8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9,
+	9, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11,
+	12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 14,
+	14, 14, 14, 15, 15, 15, 15, 15, 16, 16, 16,
+	16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19,
+	19, 19, 20, 20, 20, 21, 21, 21, 21, 22, 22,
+	22, 22, 23, 23, 23, 24, 24, 24, 24, 25, 25,
+	25, 26, 26, 26, 27, 27, 27, 28, 28, 28, 29,
+	29, 29, 29, 30, 30, 30, 31, 31, 31, 32, 32,
+	33, 33, 33, 34, 34, 34, 35, 35, 35, 36, 36,
+	36, 37, 37, 38, 38, 38, 39, 39, 39, 40, 40,
+	41, 41, 41, 42, 42, 43, 43, 43, 44, 44, 45,
+	45, 45, 46, 46, 47, 47, 47, 48, 48, 49, 49,
+	50, 50, 50, 51, 51, 52, 52, 53, 53, 54, 54,
+	54, 55, 55, 56, 56, 57, 57, 58, 58, 59, 59,
+	59, 60, 60, 61, 61, 62, 62, 63, 63, 64, 64,
+	65, 65, 66, 66, 67, 67, 68, 68, 69, 69, 70,
+	70, 71, 71, 72, 72, 73, 74, 74, 75, 75, 76,
+	76, 77, 77, 78, 78, 79, 79, 80, 81, 81, 82,
+	82, 83, 83, 84, 85, 85, 86, 86, 87, 87, 88,
+	89, 89, 90, 90, 91, 91, 92, 93, 93, 94, 94,
+	95, 96, 96, 97, 97, 98, 99, 99, 100, 101, 101,
+	102, 102, 103, 104, 104, 105, 106, 106, 107, 108, 108,
+	109, 110, 110, 111, 111, 112, 113, 113, 114, 115, 115,
+	116, 117, 117, 118, 119, 120, 120, 121, 122, 122, 123,
+	124, 124, 125, 126, 126, 127, 128, 129, 129, 130, 131,
+	131, 132, 133, 134, 134, 135, 136, 136, 137, 138, 139,
+	139, 140, 141, 142, 142, 143, 144, 145, 145, 146, 147,
+	148, 148, 149, 150, 151, 152, 152, 153, 154, 155, 155,
+	156, 157, 158, 159, 159, 160, 161, 162, 163, 163, 164,
+	165, 166, 167, 167, 168, 169, 170, 171, 171, 172, 173,
+	174, 175, 176, 176, 177, 178, 179, 180, 181, 181, 182,
+	183, 184, 185, 186, 187, 187, 188, 189, 190, 191, 192,
+	193, 194, 194, 195, 196, 197, 198, 199, 200, 201, 202,
+	202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212,
+	212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222,
+	223, 224, 225, 226, 227, 227, 228, 229, 230, 231, 232,
+	233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243,
+	244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254,
+	255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265,
+	266, 267, 268, 269, 271, 272, 273, 274, 275, 276, 277,
+	278, 279, 280, 281, 282, 283, 284, 285, 286, 288, 289,
+	290, 291, 292, 293, 294, 295, 296, 297, 298, 300, 301,
+	302, 303, 304, 305, 306, 307, 308, 310, 311, 312, 313,
+	314, 315, 316, 317, 319, 320, 321, 322, 323, 324, 326,
+	327, 328, 329, 330, 331, 332, 334, 335, 336, 337, 338,
+	339, 341, 342, 343, 344, 345, 347, 348, 349, 350, 351,
+	353, 354, 355, 356, 357, 359, 360, 361, 362, 363, 365,
+	366, 367, 368, 370, 371, 372, 373, 375, 376, 377, 378,
+	380, 381, 382, 383, 385, 386, 387, 388, 390, 391, 392,
+	393, 395, 396, 397, 399, 400, 401, 402, 404, 405, 406,
+	408, 409, 410, 411, 413, 414, 415, 417, 418, 419, 421,
+	422, 423, 425, 426, 427, 429, 430, 431, 433, 434, 435,
+	437, 438, 439, 441, 442, 443, 445, 446, 447, 449, 450,
+	452, 453, 454, 456, 457, 458, 460, 461, 463, 464, 465,
+	467, 468, 469, 471, 472, 474, 475, 477, 478, 479, 481,
+	482, 484, 485, 486, 488, 489, 491, 492, 494, 495, 496,
+	498, 499, 501, 502, 504, 505, 507, 508, 509, 511, 512,
+	514, 515, 517, 518, 520, 521, 523, 524, 526, 527, 529,
+	530, 532, 533, 535, 536, 538, 539, 541, 542, 544, 545,
+	547, 548, 550, 551, 553, 554, 556, 557, 559, 560, 562,
+	563, 565, 566, 568, 569, 571, 573, 574, 576, 577, 579,
+	580, 582, 583, 585, 587, 588, 590, 591, 593, 595, 596,
+	598, 599, 601, 602, 604, 606, 607, 609, 610, 612, 614,
+	615, 617, 618, 620, 622, 623, 625, 627, 628, 630, 631,
+	633, 635, 636, 638, 640, 641, 643, 645, 646, 648, 650,
+	651, 653, 654, 656, 658, 659, 661, 663, 664, 666, 668,
+	670, 671, 673, 675, 676, 678, 680, 681, 683, 685, 686,
+	688, 690, 692, 693, 695, 697, 698, 700, 702, 704, 705,
+	707, 709, 711, 712, 714, 716, 717, 719, 721, 723, 724,
+	726, 728, 730, 732, 733, 735, 737, 739, 740, 742, 744,
+	746, 747, 749, 751, 753, 755, 756, 758, 760, 762, 764,
+	765, 767, 769, 771, 773, 774, 776, 778, 780, 782, 784,
+	785, 787, 789, 791, 793, 795, 796, 798, 800, 802, 804,
+	806, 807, 809, 811, 813, 815, 817, 819, 821, 822, 824,
+	826, 828, 830, 832, 834, 836, 837, 839, 841, 843, 845,
+	847, 849, 851, 853, 855, 856, 858, 860, 862, 864, 866,
+	868, 870, 872, 874, 876, 878, 880, 882, 883, 885, 887,
+	889, 891, 893, 895, 897, 899, 901, 903, 905, 907, 909,
+	911, 913, 915, 917, 919, 921, 923, 925, 927, 929, 931,
+	933, 935, 937, 939, 941, 943, 945, 947, 949, 951, 953,
+	955, 957, 959, 961, 963, 965, 967, 969, 971, 973, 975,
+	977, 979, 981, 984, 986, 988, 990, 992, 994, 996, 998,
+	1000, 1002, 1004, 1006, 1008, 1010, 1013, 1015, 1017, 1019, 1021,
+	1023,
+};
+
+static const u16 xgamma10_22[GAMMA10_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2,
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+	2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+	3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5,
+	5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6,
+	6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
+	8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9,
+	9, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11,
+	11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13,
+	13, 14, 14, 14, 14, 15, 15, 15, 15, 15, 16,
+	16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
+	18, 19, 19, 19, 19, 20, 20, 20, 21, 21, 21,
+	21, 22, 22, 22, 22, 23, 23, 23, 23, 24, 24,
+	24, 25, 25, 25, 25, 26, 26, 26, 27, 27, 27,
+	28, 28, 28, 29, 29, 29, 29, 30, 30, 30, 31,
+	31, 31, 32, 32, 32, 33, 33, 33, 34, 34, 34,
+	35, 35, 35, 36, 36, 37, 37, 37, 38, 38, 38,
+	39, 39, 39, 40, 40, 41, 41, 41, 42, 42, 43,
+	43, 43, 44, 44, 44, 45, 45, 46, 46, 46, 47,
+	47, 48, 48, 49, 49, 49, 50, 50, 51, 51, 52,
+	52, 52, 53, 53, 54, 54, 55, 55, 55, 56, 56,
+	57, 57, 58, 58, 59, 59, 60, 60, 61, 61, 61,
+	62, 62, 63, 63, 64, 64, 65, 65, 66, 66, 67,
+	67, 68, 68, 69, 69, 70, 70, 71, 71, 72, 72,
+	73, 73, 74, 75, 75, 76, 76, 77, 77, 78, 78,
+	79, 79, 80, 80, 81, 82, 82, 83, 83, 84, 84,
+	85, 85, 86, 87, 87, 88, 88, 89, 89, 90, 91,
+	91, 92, 92, 93, 94, 94, 95, 95, 96, 97, 97,
+	98, 98, 99, 100, 100, 101, 102, 102, 103, 103, 104,
+	105, 105, 106, 107, 107, 108, 109, 109, 110, 110, 111,
+	112, 112, 113, 114, 114, 115, 116, 116, 117, 118, 118,
+	119, 120, 121, 121, 122, 123, 123, 124, 125, 125, 126,
+	127, 127, 128, 129, 130, 130, 131, 132, 132, 133, 134,
+	135, 135, 136, 137, 138, 138, 139, 140, 141, 141, 142,
+	143, 144, 144, 145, 146, 147, 147, 148, 149, 150, 150,
+	151, 152, 153, 154, 154, 155, 156, 157, 157, 158, 159,
+	160, 161, 161, 162, 163, 164, 165, 166, 166, 167, 168,
+	169, 170, 170, 171, 172, 173, 174, 175, 175, 176, 177,
+	178, 179, 180, 181, 181, 182, 183, 184, 185, 186, 187,
+	187, 188, 189, 190, 191, 192, 193, 194, 194, 195, 196,
+	197, 198, 199, 200, 201, 202, 203, 203, 204, 205, 206,
+	207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 216,
+	217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227,
+	228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238,
+	239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249,
+	250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260,
+	261, 262, 263, 264, 265, 266, 267, 269, 270, 271, 272,
+	273, 274, 275, 276, 277, 278, 279, 280, 281, 283, 284,
+	285, 286, 287, 288, 289, 290, 291, 292, 294, 295, 296,
+	297, 298, 299, 300, 301, 303, 304, 305, 306, 307, 308,
+	309, 311, 312, 313, 314, 315, 316, 317, 319, 320, 321,
+	322, 323, 324, 326, 327, 328, 329, 330, 332, 333, 334,
+	335, 336, 338, 339, 340, 341, 342, 344, 345, 346, 347,
+	348, 350, 351, 352, 353, 355, 356, 357, 358, 360, 361,
+	362, 363, 365, 366, 367, 368, 370, 371, 372, 373, 375,
+	376, 377, 378, 380, 381, 382, 384, 385, 386, 387, 389,
+	390, 391, 393, 394, 395, 397, 398, 399, 401, 402, 403,
+	405, 406, 407, 409, 410, 411, 413, 414, 415, 417, 418,
+	419, 421, 422, 423, 425, 426, 427, 429, 430, 432, 433,
+	434, 436, 437, 438, 440, 441, 443, 444, 445, 447, 448,
+	450, 451, 452, 454, 455, 457, 458, 459, 461, 462, 464,
+	465, 467, 468, 469, 471, 472, 474, 475, 477, 478, 480,
+	481, 483, 484, 485, 487, 488, 490, 491, 493, 494, 496,
+	497, 499, 500, 502, 503, 505, 506, 508, 509, 511, 512,
+	514, 515, 517, 518, 520, 521, 523, 524, 526, 527, 529,
+	530, 532, 534, 535, 537, 538, 540, 541, 543, 544, 546,
+	548, 549, 551, 552, 554, 555, 557, 559, 560, 562, 563,
+	565, 567, 568, 570, 571, 573, 575, 576, 578, 579, 581,
+	583, 584, 586, 587, 589, 591, 592, 594, 596, 597, 599,
+	601, 602, 604, 605, 607, 609, 610, 612, 614, 615, 617,
+	619, 620, 622, 624, 625, 627, 629, 631, 632, 634, 636,
+	637, 639, 641, 642, 644, 646, 648, 649, 651, 653, 654,
+	656, 658, 660, 661, 663, 665, 667, 668, 670, 672, 674,
+	675, 677, 679, 681, 682, 684, 686, 688, 689, 691, 693,
+	695, 697, 698, 700, 702, 704, 705, 707, 709, 711, 713,
+	714, 716, 718, 720, 722, 724, 725, 727, 729, 731, 733,
+	735, 736, 738, 740, 742, 744, 746, 747, 749, 751, 753,
+	755, 757, 759, 760, 762, 764, 766, 768, 770, 772, 774,
+	776, 777, 779, 781, 783, 785, 787, 789, 791, 793, 795,
+	796, 798, 800, 802, 804, 806, 808, 810, 812, 814, 816,
+	818, 820, 822, 824, 826, 828, 829, 831, 833, 835, 837,
+	839, 841, 843, 845, 847, 849, 851, 853, 855, 857, 859,
+	861, 863, 865, 867, 869, 871, 873, 875, 877, 879, 881,
+	883, 885, 887, 889, 892, 894, 896, 898, 900, 902, 904,
+	906, 908, 910, 912, 914, 916, 918, 920, 922, 925, 927,
+	929, 931, 933, 935, 937, 939, 941, 943, 945, 948, 950,
+	952, 954, 956, 958, 960, 962, 965, 967, 969, 971, 973,
+	975, 977, 980, 982, 984, 986, 988, 990, 992, 995, 997,
+	999, 1001, 1003, 1005, 1008, 1010, 1012, 1014, 1016, 1019, 1021,
+	1023,
+};
+
+static const u16 xgamma10_23[GAMMA10_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2,
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3,
+	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4,
+	4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5,
+	5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6,
+	6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
+	8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9,
+	9, 9, 10, 10, 10, 10, 10, 10, 11, 11, 11,
+	11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13,
+	13, 13, 14, 14, 14, 14, 14, 15, 15, 15, 15,
+	15, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18,
+	18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 20,
+	21, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23,
+	23, 24, 24, 24, 25, 25, 25, 25, 26, 26, 26,
+	27, 27, 27, 27, 28, 28, 28, 29, 29, 29, 30,
+	30, 30, 30, 31, 31, 31, 32, 32, 32, 33, 33,
+	33, 34, 34, 34, 35, 35, 35, 36, 36, 36, 37,
+	37, 38, 38, 38, 39, 39, 39, 40, 40, 40, 41,
+	41, 42, 42, 42, 43, 43, 43, 44, 44, 45, 45,
+	45, 46, 46, 47, 47, 47, 48, 48, 49, 49, 49,
+	50, 50, 51, 51, 52, 52, 52, 53, 53, 54, 54,
+	55, 55, 55, 56, 56, 57, 57, 58, 58, 59, 59,
+	59, 60, 60, 61, 61, 62, 62, 63, 63, 64, 64,
+	65, 65, 66, 66, 67, 67, 68, 68, 69, 69, 70,
+	70, 71, 71, 72, 72, 73, 73, 74, 74, 75, 75,
+	76, 76, 77, 77, 78, 78, 79, 80, 80, 81, 81,
+	82, 82, 83, 83, 84, 85, 85, 86, 86, 87, 87,
+	88, 89, 89, 90, 90, 91, 91, 92, 93, 93, 94,
+	94, 95, 96, 96, 97, 97, 98, 99, 99, 100, 100,
+	101, 102, 102, 103, 104, 104, 105, 106, 106, 107, 107,
+	108, 109, 109, 110, 111, 111, 112, 113, 113, 114, 115,
+	115, 116, 117, 117, 118, 119, 119, 120, 121, 121, 122,
+	123, 124, 124, 125, 126, 126, 127, 128, 128, 129, 130,
+	131, 131, 132, 133, 133, 134, 135, 136, 136, 137, 138,
+	139, 139, 140, 141, 142, 142, 143, 144, 145, 145, 146,
+	147, 148, 148, 149, 150, 151, 152, 152, 153, 154, 155,
+	156, 156, 157, 158, 159, 160, 160, 161, 162, 163, 164,
+	164, 165, 166, 167, 168, 168, 169, 170, 171, 172, 173,
+	174, 174, 175, 176, 177, 178, 179, 179, 180, 181, 182,
+	183, 184, 185, 186, 186, 187, 188, 189, 190, 191, 192,
+	193, 194, 194, 195, 196, 197, 198, 199, 200, 201, 202,
+	203, 204, 204, 205, 206, 207, 208, 209, 210, 211, 212,
+	213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 222,
+	223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233,
+	234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244,
+	245, 246, 248, 249, 250, 251, 252, 253, 254, 255, 256,
+	257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 268,
+	269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 280,
+	281, 282, 283, 284, 285, 286, 287, 288, 290, 291, 292,
+	293, 294, 295, 296, 298, 299, 300, 301, 302, 303, 304,
+	306, 307, 308, 309, 310, 311, 313, 314, 315, 316, 317,
+	319, 320, 321, 322, 323, 325, 326, 327, 328, 329, 331,
+	332, 333, 334, 335, 337, 338, 339, 340, 342, 343, 344,
+	345, 347, 348, 349, 350, 352, 353, 354, 355, 357, 358,
+	359, 360, 362, 363, 364, 366, 367, 368, 369, 371, 372,
+	373, 375, 376, 377, 379, 380, 381, 383, 384, 385, 386,
+	388, 389, 390, 392, 393, 394, 396, 397, 399, 400, 401,
+	403, 404, 405, 407, 408, 409, 411, 412, 414, 415, 416,
+	418, 419, 420, 422, 423, 425, 426, 427, 429, 430, 432,
+	433, 435, 436, 437, 439, 440, 442, 443, 444, 446, 447,
+	449, 450, 452, 453, 455, 456, 458, 459, 460, 462, 463,
+	465, 466, 468, 469, 471, 472, 474, 475, 477, 478, 480,
+	481, 483, 484, 486, 487, 489, 490, 492, 493, 495, 496,
+	498, 499, 501, 502, 504, 506, 507, 509, 510, 512, 513,
+	515, 516, 518, 520, 521, 523, 524, 526, 527, 529, 531,
+	532, 534, 535, 537, 539, 540, 542, 543, 545, 547, 548,
+	550, 551, 553, 555, 556, 558, 560, 561, 563, 565, 566,
+	568, 569, 571, 573, 574, 576, 578, 579, 581, 583, 584,
+	586, 588, 590, 591, 593, 595, 596, 598, 600, 601, 603,
+	605, 606, 608, 610, 612, 613, 615, 617, 619, 620, 622,
+	624, 625, 627, 629, 631, 632, 634, 636, 638, 640, 641,
+	643, 645, 647, 648, 650, 652, 654, 655, 657, 659, 661,
+	663, 664, 666, 668, 670, 672, 674, 675, 677, 679, 681,
+	683, 684, 686, 688, 690, 692, 694, 696, 697, 699, 701,
+	703, 705, 707, 709, 710, 712, 714, 716, 718, 720, 722,
+	724, 725, 727, 729, 731, 733, 735, 737, 739, 741, 743,
+	745, 746, 748, 750, 752, 754, 756, 758, 760, 762, 764,
+	766, 768, 770, 772, 774, 776, 778, 780, 782, 784, 786,
+	787, 789, 791, 793, 795, 797, 799, 801, 803, 805, 807,
+	809, 811, 814, 816, 818, 820, 822, 824, 826, 828, 830,
+	832, 834, 836, 838, 840, 842, 844, 846, 848, 850, 852,
+	854, 857, 859, 861, 863, 865, 867, 869, 871, 873, 875,
+	878, 880, 882, 884, 886, 888, 890, 892, 894, 897, 899,
+	901, 903, 905, 907, 909, 912, 914, 916, 918, 920, 922,
+	925, 927, 929, 931, 933, 936, 938, 940, 942, 944, 946,
+	949, 951, 953, 955, 958, 960, 962, 964, 966, 969, 971,
+	973, 975, 978, 980, 982, 984, 987, 989, 991, 993, 996,
+	998, 1000, 1002, 1005, 1007, 1009, 1012, 1014, 1016, 1018, 1021,
+	1023,
+};
+
+static const u16 xgamma10_24[GAMMA10_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+	2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3,
+	3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4,
+	4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5,
+	5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6,
+	6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
+	8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9,
+	9, 9, 9, 10, 10, 10, 10, 10, 10, 11, 11,
+	11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 13,
+	13, 13, 13, 13, 14, 14, 14, 14, 14, 15, 15,
+	15, 15, 15, 16, 16, 16, 16, 16, 17, 17, 17,
+	17, 18, 18, 18, 18, 18, 19, 19, 19, 19, 20,
+	20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22,
+	23, 23, 23, 23, 24, 24, 24, 24, 25, 25, 25,
+	26, 26, 26, 26, 27, 27, 27, 28, 28, 28, 28,
+	29, 29, 29, 30, 30, 30, 31, 31, 31, 32, 32,
+	32, 32, 33, 33, 33, 34, 34, 34, 35, 35, 35,
+	36, 36, 36, 37, 37, 38, 38, 38, 39, 39, 39,
+	40, 40, 40, 41, 41, 41, 42, 42, 43, 43, 43,
+	44, 44, 44, 45, 45, 46, 46, 46, 47, 47, 48,
+	48, 48, 49, 49, 50, 50, 50, 51, 51, 52, 52,
+	53, 53, 53, 54, 54, 55, 55, 56, 56, 56, 57,
+	57, 58, 58, 59, 59, 60, 60, 61, 61, 61, 62,
+	62, 63, 63, 64, 64, 65, 65, 66, 66, 67, 67,
+	68, 68, 69, 69, 70, 70, 71, 71, 72, 72, 73,
+	73, 74, 74, 75, 75, 76, 76, 77, 77, 78, 79,
+	79, 80, 80, 81, 81, 82, 82, 83, 83, 84, 85,
+	85, 86, 86, 87, 87, 88, 89, 89, 90, 90, 91,
+	91, 92, 93, 93, 94, 94, 95, 96, 96, 97, 97,
+	98, 99, 99, 100, 100, 101, 102, 102, 103, 104, 104,
+	105, 106, 106, 107, 107, 108, 109, 109, 110, 111, 111,
+	112, 113, 113, 114, 115, 115, 116, 117, 117, 118, 119,
+	119, 120, 121, 121, 122, 123, 124, 124, 125, 126, 126,
+	127, 128, 129, 129, 130, 131, 131, 132, 133, 134, 134,
+	135, 136, 137, 137, 138, 139, 140, 140, 141, 142, 143,
+	143, 144, 145, 146, 146, 147, 148, 149, 149, 150, 151,
+	152, 153, 153, 154, 155, 156, 157, 157, 158, 159, 160,
+	161, 161, 162, 163, 164, 165, 166, 166, 167, 168, 169,
+	170, 171, 171, 172, 173, 174, 175, 176, 177, 177, 178,
+	179, 180, 181, 182, 183, 184, 184, 185, 186, 187, 188,
+	189, 190, 191, 192, 192, 193, 194, 195, 196, 197, 198,
+	199, 200, 201, 202, 203, 204, 204, 205, 206, 207, 208,
+	209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
+	220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230,
+	231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241,
+	242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252,
+	253, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+	265, 266, 268, 269, 270, 271, 272, 273, 274, 275, 276,
+	277, 279, 280, 281, 282, 283, 284, 285, 287, 288, 289,
+	290, 291, 292, 293, 295, 296, 297, 298, 299, 300, 302,
+	303, 304, 305, 306, 308, 309, 310, 311, 312, 314, 315,
+	316, 317, 318, 320, 321, 322, 323, 324, 326, 327, 328,
+	329, 331, 332, 333, 334, 336, 337, 338, 339, 341, 342,
+	343, 344, 346, 347, 348, 350, 351, 352, 353, 355, 356,
+	357, 359, 360, 361, 363, 364, 365, 367, 368, 369, 370,
+	372, 373, 374, 376, 377, 378, 380, 381, 383, 384, 385,
+	387, 388, 389, 391, 392, 393, 395, 396, 398, 399, 400,
+	402, 403, 405, 406, 407, 409, 410, 412, 413, 414, 416,
+	417, 419, 420, 421, 423, 424, 426, 427, 429, 430, 432,
+	433, 434, 436, 437, 439, 440, 442, 443, 445, 446, 448,
+	449, 451, 452, 454, 455, 457, 458, 460, 461, 463, 464,
+	466, 467, 469, 470, 472, 473, 475, 476, 478, 479, 481,
+	483, 484, 486, 487, 489, 490, 492, 493, 495, 497, 498,
+	500, 501, 503, 505, 506, 508, 509, 511, 512, 514, 516,
+	517, 519, 521, 522, 524, 525, 527, 529, 530, 532, 534,
+	535, 537, 539, 540, 542, 543, 545, 547, 548, 550, 552,
+	553, 555, 557, 559, 560, 562, 564, 565, 567, 569, 570,
+	572, 574, 576, 577, 579, 581, 582, 584, 586, 588, 589,
+	591, 593, 595, 596, 598, 600, 602, 603, 605, 607, 609,
+	610, 612, 614, 616, 618, 619, 621, 623, 625, 627, 628,
+	630, 632, 634, 636, 637, 639, 641, 643, 645, 647, 648,
+	650, 652, 654, 656, 658, 660, 661, 663, 665, 667, 669,
+	671, 673, 674, 676, 678, 680, 682, 684, 686, 688, 690,
+	692, 693, 695, 697, 699, 701, 703, 705, 707, 709, 711,
+	713, 715, 717, 719, 721, 723, 724, 726, 728, 730, 732,
+	734, 736, 738, 740, 742, 744, 746, 748, 750, 752, 754,
+	756, 758, 760, 762, 764, 766, 768, 770, 772, 774, 777,
+	779, 781, 783, 785, 787, 789, 791, 793, 795, 797, 799,
+	801, 803, 805, 808, 810, 812, 814, 816, 818, 820, 822,
+	824, 826, 829, 831, 833, 835, 837, 839, 841, 844, 846,
+	848, 850, 852, 854, 856, 859, 861, 863, 865, 867, 870,
+	872, 874, 876, 878, 880, 883, 885, 887, 889, 891, 894,
+	896, 898, 900, 903, 905, 907, 909, 912, 914, 916, 918,
+	921, 923, 925, 927, 930, 932, 934, 936, 939, 941, 943,
+	946, 948, 950, 952, 955, 957, 959, 962, 964, 966, 969,
+	971, 973, 976, 978, 980, 983, 985, 987, 990, 992, 994,
+	997, 999, 1002, 1004, 1006, 1009, 1011, 1013, 1016, 1018, 1021,
+	1023,
+};
+
+static const u16 xgamma10_25[GAMMA10_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+	2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3,
+	3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4,
+	4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5,
+	5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6,
+	6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
+	7, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9,
+	9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 11,
+	11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12,
+	13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14,
+	15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 17,
+	17, 17, 17, 18, 18, 18, 18, 18, 19, 19, 19,
+	19, 20, 20, 20, 20, 20, 21, 21, 21, 21, 22,
+	22, 22, 22, 23, 23, 23, 23, 24, 24, 24, 25,
+	25, 25, 25, 26, 26, 26, 26, 27, 27, 27, 28,
+	28, 28, 28, 29, 29, 29, 30, 30, 30, 31, 31,
+	31, 31, 32, 32, 32, 33, 33, 33, 34, 34, 34,
+	35, 35, 35, 36, 36, 36, 37, 37, 37, 38, 38,
+	38, 39, 39, 39, 40, 40, 40, 41, 41, 42, 42,
+	42, 43, 43, 43, 44, 44, 45, 45, 45, 46, 46,
+	46, 47, 47, 48, 48, 48, 49, 49, 50, 50, 50,
+	51, 51, 52, 52, 53, 53, 53, 54, 54, 55, 55,
+	56, 56, 56, 57, 57, 58, 58, 59, 59, 60, 60,
+	60, 61, 61, 62, 62, 63, 63, 64, 64, 65, 65,
+	66, 66, 67, 67, 68, 68, 69, 69, 70, 70, 71,
+	71, 72, 72, 73, 73, 74, 74, 75, 75, 76, 76,
+	77, 77, 78, 78, 79, 79, 80, 80, 81, 82, 82,
+	83, 83, 84, 84, 85, 85, 86, 87, 87, 88, 88,
+	89, 89, 90, 91, 91, 92, 92, 93, 94, 94, 95,
+	95, 96, 97, 97, 98, 98, 99, 100, 100, 101, 102,
+	102, 103, 103, 104, 105, 105, 106, 107, 107, 108, 109,
+	109, 110, 110, 111, 112, 112, 113, 114, 114, 115, 116,
+	117, 117, 118, 119, 119, 120, 121, 121, 122, 123, 123,
+	124, 125, 126, 126, 127, 128, 128, 129, 130, 131, 131,
+	132, 133, 133, 134, 135, 136, 136, 137, 138, 139, 139,
+	140, 141, 142, 143, 143, 144, 145, 146, 146, 147, 148,
+	149, 149, 150, 151, 152, 153, 153, 154, 155, 156, 157,
+	158, 158, 159, 160, 161, 162, 162, 163, 164, 165, 166,
+	167, 167, 168, 169, 170, 171, 172, 173, 173, 174, 175,
+	176, 177, 178, 179, 180, 180, 181, 182, 183, 184, 185,
+	186, 187, 188, 188, 189, 190, 191, 192, 193, 194, 195,
+	196, 197, 198, 199, 200, 200, 201, 202, 203, 204, 205,
+	206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216,
+	217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227,
+	228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238,
+	239, 240, 241, 242, 243, 244, 245, 247, 248, 249, 250,
+	251, 252, 253, 254, 255, 256, 257, 258, 260, 261, 262,
+	263, 264, 265, 266, 267, 268, 270, 271, 272, 273, 274,
+	275, 276, 277, 279, 280, 281, 282, 283, 284, 286, 287,
+	288, 289, 290, 291, 293, 294, 295, 296, 297, 298, 300,
+	301, 302, 303, 304, 306, 307, 308, 309, 311, 312, 313,
+	314, 315, 317, 318, 319, 320, 322, 323, 324, 325, 327,
+	328, 329, 330, 332, 333, 334, 336, 337, 338, 339, 341,
+	342, 343, 345, 346, 347, 349, 350, 351, 352, 354, 355,
+	356, 358, 359, 360, 362, 363, 364, 366, 367, 369, 370,
+	371, 373, 374, 375, 377, 378, 379, 381, 382, 384, 385,
+	386, 388, 389, 391, 392, 393, 395, 396, 398, 399, 400,
+	402, 403, 405, 406, 408, 409, 411, 412, 413, 415, 416,
+	418, 419, 421, 422, 424, 425, 427, 428, 430, 431, 433,
+	434, 436, 437, 439, 440, 442, 443, 445, 446, 448, 449,
+	451, 452, 454, 455, 457, 458, 460, 461, 463, 465, 466,
+	468, 469, 471, 472, 474, 476, 477, 479, 480, 482, 483,
+	485, 487, 488, 490, 491, 493, 495, 496, 498, 500, 501,
+	503, 504, 506, 508, 509, 511, 513, 514, 516, 518, 519,
+	521, 523, 524, 526, 528, 529, 531, 533, 534, 536, 538,
+	540, 541, 543, 545, 546, 548, 550, 552, 553, 555, 557,
+	558, 560, 562, 564, 565, 567, 569, 571, 572, 574, 576,
+	578, 580, 581, 583, 585, 587, 588, 590, 592, 594, 596,
+	597, 599, 601, 603, 605, 607, 608, 610, 612, 614, 616,
+	618, 619, 621, 623, 625, 627, 629, 631, 632, 634, 636,
+	638, 640, 642, 644, 646, 648, 649, 651, 653, 655, 657,
+	659, 661, 663, 665, 667, 669, 671, 673, 674, 676, 678,
+	680, 682, 684, 686, 688, 690, 692, 694, 696, 698, 700,
+	702, 704, 706, 708, 710, 712, 714, 716, 718, 720, 722,
+	724, 726, 728, 730, 732, 734, 736, 739, 741, 743, 745,
+	747, 749, 751, 753, 755, 757, 759, 761, 763, 766, 768,
+	770, 772, 774, 776, 778, 780, 782, 785, 787, 789, 791,
+	793, 795, 797, 800, 802, 804, 806, 808, 810, 813, 815,
+	817, 819, 821, 824, 826, 828, 830, 832, 835, 837, 839,
+	841, 843, 846, 848, 850, 852, 855, 857, 859, 861, 864,
+	866, 868, 870, 873, 875, 877, 880, 882, 884, 886, 889,
+	891, 893, 896, 898, 900, 903, 905, 907, 910, 912, 914,
+	917, 919, 921, 924, 926, 928, 931, 933, 935, 938, 940,
+	942, 945, 947, 950, 952, 954, 957, 959, 962, 964, 966,
+	969, 971, 974, 976, 979, 981, 983, 986, 988, 991, 993,
+	996, 998, 1001, 1003, 1006, 1008, 1011, 1013, 1016, 1018, 1021,
+	1023,
+};
+
+static const u16 xgamma10_26[GAMMA10_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+	2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
+	3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4,
+	4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5,
+	5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6,
+	6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
+	7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9,
+	9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10,
+	11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12,
+	12, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14,
+	14, 14, 15, 15, 15, 15, 15, 16, 16, 16, 16,
+	16, 17, 17, 17, 17, 18, 18, 18, 18, 18, 19,
+	19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21,
+	21, 22, 22, 22, 22, 23, 23, 23, 23, 24, 24,
+	24, 24, 25, 25, 25, 25, 26, 26, 26, 27, 27,
+	27, 27, 28, 28, 28, 28, 29, 29, 29, 30, 30,
+	30, 31, 31, 31, 31, 32, 32, 32, 33, 33, 33,
+	34, 34, 34, 35, 35, 35, 36, 36, 36, 37, 37,
+	37, 38, 38, 38, 39, 39, 39, 40, 40, 40, 41,
+	41, 41, 42, 42, 43, 43, 43, 44, 44, 44, 45,
+	45, 46, 46, 46, 47, 47, 47, 48, 48, 49, 49,
+	49, 50, 50, 51, 51, 51, 52, 52, 53, 53, 54,
+	54, 54, 55, 55, 56, 56, 57, 57, 57, 58, 58,
+	59, 59, 60, 60, 61, 61, 62, 62, 62, 63, 63,
+	64, 64, 65, 65, 66, 66, 67, 67, 68, 68, 69,
+	69, 70, 70, 71, 71, 72, 72, 73, 73, 74, 74,
+	75, 75, 76, 76, 77, 77, 78, 78, 79, 80, 80,
+	81, 81, 82, 82, 83, 83, 84, 84, 85, 86, 86,
+	87, 87, 88, 88, 89, 90, 90, 91, 91, 92, 93,
+	93, 94, 94, 95, 96, 96, 97, 97, 98, 99, 99,
+	100, 100, 101, 102, 102, 103, 104, 104, 105, 106, 106,
+	107, 107, 108, 109, 109, 110, 111, 111, 112, 113, 113,
+	114, 115, 115, 116, 117, 117, 118, 119, 120, 120, 121,
+	122, 122, 123, 124, 124, 125, 126, 127, 127, 128, 129,
+	129, 130, 131, 132, 132, 133, 134, 135, 135, 136, 137,
+	138, 138, 139, 140, 141, 141, 142, 143, 144, 145, 145,
+	146, 147, 148, 149, 149, 150, 151, 152, 153, 153, 154,
+	155, 156, 157, 157, 158, 159, 160, 161, 162, 162, 163,
+	164, 165, 166, 167, 167, 168, 169, 170, 171, 172, 173,
+	173, 174, 175, 176, 177, 178, 179, 180, 181, 181, 182,
+	183, 184, 185, 186, 187, 188, 189, 190, 191, 191, 192,
+	193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203,
+	204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214,
+	215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225,
+	226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236,
+	237, 238, 239, 240, 241, 242, 243, 245, 246, 247, 248,
+	249, 250, 251, 252, 253, 254, 256, 257, 258, 259, 260,
+	261, 262, 263, 264, 266, 267, 268, 269, 270, 271, 272,
+	274, 275, 276, 277, 278, 279, 281, 282, 283, 284, 285,
+	286, 288, 289, 290, 291, 292, 294, 295, 296, 297, 299,
+	300, 301, 302, 303, 305, 306, 307, 308, 310, 311, 312,
+	313, 315, 316, 317, 318, 320, 321, 322, 323, 325, 326,
+	327, 329, 330, 331, 333, 334, 335, 336, 338, 339, 340,
+	342, 343, 344, 346, 347, 348, 350, 351, 352, 354, 355,
+	356, 358, 359, 361, 362, 363, 365, 366, 367, 369, 370,
+	372, 373, 374, 376, 377, 379, 380, 381, 383, 384, 386,
+	387, 389, 390, 391, 393, 394, 396, 397, 399, 400, 402,
+	403, 405, 406, 407, 409, 410, 412, 413, 415, 416, 418,
+	419, 421, 422, 424, 425, 427, 428, 430, 432, 433, 435,
+	436, 438, 439, 441, 442, 444, 445, 447, 449, 450, 452,
+	453, 455, 456, 458, 460, 461, 463, 464, 466, 468, 469,
+	471, 472, 474, 476, 477, 479, 481, 482, 484, 485, 487,
+	489, 490, 492, 494, 495, 497, 499, 500, 502, 504, 505,
+	507, 509, 510, 512, 514, 516, 517, 519, 521, 522, 524,
+	526, 528, 529, 531, 533, 535, 536, 538, 540, 542, 543,
+	545, 547, 549, 550, 552, 554, 556, 558, 559, 561, 563,
+	565, 567, 568, 570, 572, 574, 576, 577, 579, 581, 583,
+	585, 587, 588, 590, 592, 594, 596, 598, 600, 601, 603,
+	605, 607, 609, 611, 613, 615, 617, 619, 620, 622, 624,
+	626, 628, 630, 632, 634, 636, 638, 640, 642, 644, 646,
+	648, 650, 651, 653, 655, 657, 659, 661, 663, 665, 667,
+	669, 671, 673, 675, 677, 679, 681, 683, 685, 688, 690,
+	692, 694, 696, 698, 700, 702, 704, 706, 708, 710, 712,
+	714, 716, 718, 721, 723, 725, 727, 729, 731, 733, 735,
+	737, 740, 742, 744, 746, 748, 750, 752, 755, 757, 759,
+	761, 763, 765, 768, 770, 772, 774, 776, 779, 781, 783,
+	785, 787, 790, 792, 794, 796, 798, 801, 803, 805, 807,
+	810, 812, 814, 816, 819, 821, 823, 826, 828, 830, 832,
+	835, 837, 839, 842, 844, 846, 849, 851, 853, 855, 858,
+	860, 862, 865, 867, 870, 872, 874, 877, 879, 881, 884,
+	886, 888, 891, 893, 896, 898, 900, 903, 905, 908, 910,
+	913, 915, 917, 920, 922, 925, 927, 930, 932, 934, 937,
+	939, 942, 944, 947, 949, 952, 954, 957, 959, 962, 964,
+	967, 969, 972, 974, 977, 979, 982, 984, 987, 990, 992,
+	995, 997, 1000, 1002, 1005, 1007, 1010, 1013, 1015, 1018, 1020,
+	1023,
+};
+
+static const u16 xgamma10_27[GAMMA10_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+	2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+	3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4,
+	4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5,
+	5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6,
+	6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
+	7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9,
+	9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10,
+	10, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12,
+	12, 12, 12, 13, 13, 13, 13, 13, 14, 14, 14,
+	14, 14, 14, 15, 15, 15, 15, 15, 16, 16, 16,
+	16, 16, 17, 17, 17, 17, 17, 18, 18, 18, 18,
+	18, 19, 19, 19, 19, 20, 20, 20, 20, 20, 21,
+	21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23,
+	24, 24, 24, 24, 25, 25, 25, 25, 26, 26, 26,
+	26, 27, 27, 27, 27, 28, 28, 28, 29, 29, 29,
+	29, 30, 30, 30, 31, 31, 31, 32, 32, 32, 32,
+	33, 33, 33, 34, 34, 34, 35, 35, 35, 36, 36,
+	36, 37, 37, 37, 38, 38, 38, 39, 39, 39, 40,
+	40, 40, 41, 41, 41, 42, 42, 43, 43, 43, 44,
+	44, 44, 45, 45, 46, 46, 46, 47, 47, 47, 48,
+	48, 49, 49, 49, 50, 50, 51, 51, 51, 52, 52,
+	53, 53, 54, 54, 54, 55, 55, 56, 56, 57, 57,
+	57, 58, 58, 59, 59, 60, 60, 61, 61, 61, 62,
+	62, 63, 63, 64, 64, 65, 65, 66, 66, 67, 67,
+	68, 68, 69, 69, 70, 70, 71, 71, 72, 72, 73,
+	73, 74, 74, 75, 75, 76, 76, 77, 77, 78, 78,
+	79, 79, 80, 81, 81, 82, 82, 83, 83, 84, 84,
+	85, 86, 86, 87, 87, 88, 88, 89, 90, 90, 91,
+	91, 92, 92, 93, 94, 94, 95, 95, 96, 97, 97,
+	98, 99, 99, 100, 100, 101, 102, 102, 103, 104, 104,
+	105, 105, 106, 107, 107, 108, 109, 109, 110, 111, 111,
+	112, 113, 113, 114, 115, 115, 116, 117, 118, 118, 119,
+	120, 120, 121, 122, 122, 123, 124, 125, 125, 126, 127,
+	127, 128, 129, 130, 130, 131, 132, 133, 133, 134, 135,
+	136, 136, 137, 138, 139, 139, 140, 141, 142, 143, 143,
+	144, 145, 146, 146, 147, 148, 149, 150, 150, 151, 152,
+	153, 154, 155, 155, 156, 157, 158, 159, 160, 160, 161,
+	162, 163, 164, 165, 165, 166, 167, 168, 169, 170, 171,
+	172, 172, 173, 174, 175, 176, 177, 178, 179, 180, 180,
+	181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
+	192, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201,
+	202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212,
+	213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
+	224, 225, 226, 227, 228, 229, 230, 231, 233, 234, 235,
+	236, 237, 238, 239, 240, 241, 242, 243, 244, 246, 247,
+	248, 249, 250, 251, 252, 253, 254, 256, 257, 258, 259,
+	260, 261, 262, 263, 265, 266, 267, 268, 269, 270, 272,
+	273, 274, 275, 276, 278, 279, 280, 281, 282, 283, 285,
+	286, 287, 288, 290, 291, 292, 293, 294, 296, 297, 298,
+	299, 301, 302, 303, 304, 306, 307, 308, 309, 311, 312,
+	313, 315, 316, 317, 318, 320, 321, 322, 324, 325, 326,
+	328, 329, 330, 332, 333, 334, 336, 337, 338, 340, 341,
+	342, 344, 345, 346, 348, 349, 351, 352, 353, 355, 356,
+	357, 359, 360, 362, 363, 364, 366, 367, 369, 370, 372,
+	373, 374, 376, 377, 379, 380, 382, 383, 385, 386, 387,
+	389, 390, 392, 393, 395, 396, 398, 399, 401, 402, 404,
+	405, 407, 408, 410, 411, 413, 414, 416, 417, 419, 421,
+	422, 424, 425, 427, 428, 430, 431, 433, 435, 436, 438,
+	439, 441, 442, 444, 446, 447, 449, 450, 452, 454, 455,
+	457, 459, 460, 462, 463, 465, 467, 468, 470, 472, 473,
+	475, 477, 478, 480, 482, 483, 485, 487, 488, 490, 492,
+	494, 495, 497, 499, 500, 502, 504, 506, 507, 509, 511,
+	513, 514, 516, 518, 520, 521, 523, 525, 527, 528, 530,
+	532, 534, 536, 537, 539, 541, 543, 545, 546, 548, 550,
+	552, 554, 556, 557, 559, 561, 563, 565, 567, 569, 570,
+	572, 574, 576, 578, 580, 582, 584, 586, 587, 589, 591,
+	593, 595, 597, 599, 601, 603, 605, 607, 609, 611, 613,
+	614, 616, 618, 620, 622, 624, 626, 628, 630, 632, 634,
+	636, 638, 640, 642, 644, 646, 648, 650, 652, 654, 656,
+	659, 661, 663, 665, 667, 669, 671, 673, 675, 677, 679,
+	681, 683, 685, 688, 690, 692, 694, 696, 698, 700, 702,
+	705, 707, 709, 711, 713, 715, 717, 720, 722, 724, 726,
+	728, 730, 733, 735, 737, 739, 741, 744, 746, 748, 750,
+	752, 755, 757, 759, 761, 764, 766, 768, 770, 773, 775,
+	777, 779, 782, 784, 786, 789, 791, 793, 795, 798, 800,
+	802, 805, 807, 809, 812, 814, 816, 819, 821, 823, 826,
+	828, 831, 833, 835, 838, 840, 842, 845, 847, 850, 852,
+	854, 857, 859, 862, 864, 867, 869, 871, 874, 876, 879,
+	881, 884, 886, 889, 891, 894, 896, 899, 901, 903, 906,
+	908, 911, 914, 916, 919, 921, 924, 926, 929, 931, 934,
+	936, 939, 941, 944, 947, 949, 952, 954, 957, 959, 962,
+	965, 967, 970, 973, 975, 978, 980, 983, 986, 988, 991,
+	994, 996, 999, 1002, 1004, 1007, 1010, 1012, 1015, 1018, 1020,
+	1023,
+};
+
+static const u16 xgamma10_28[GAMMA10_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3,
+	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+	3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
+	4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5,
+	5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6,
+	6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
+	7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9,
+	9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10,
+	10, 10, 11, 11, 11, 11, 11, 11, 12, 12, 12,
+	12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 14,
+	14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 16,
+	16, 16, 16, 16, 17, 17, 17, 17, 17, 18, 18,
+	18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 20,
+	20, 21, 21, 21, 21, 22, 22, 22, 22, 23, 23,
+	23, 23, 24, 24, 24, 24, 25, 25, 25, 25, 26,
+	26, 26, 26, 27, 27, 27, 27, 28, 28, 28, 29,
+	29, 29, 29, 30, 30, 30, 31, 31, 31, 31, 32,
+	32, 32, 33, 33, 33, 34, 34, 34, 35, 35, 35,
+	35, 36, 36, 36, 37, 37, 37, 38, 38, 38, 39,
+	39, 40, 40, 40, 41, 41, 41, 42, 42, 42, 43,
+	43, 43, 44, 44, 45, 45, 45, 46, 46, 46, 47,
+	47, 48, 48, 48, 49, 49, 50, 50, 50, 51, 51,
+	52, 52, 52, 53, 53, 54, 54, 55, 55, 55, 56,
+	56, 57, 57, 58, 58, 58, 59, 59, 60, 60, 61,
+	61, 62, 62, 63, 63, 63, 64, 64, 65, 65, 66,
+	66, 67, 67, 68, 68, 69, 69, 70, 70, 71, 71,
+	72, 72, 73, 73, 74, 74, 75, 75, 76, 76, 77,
+	77, 78, 79, 79, 80, 80, 81, 81, 82, 82, 83,
+	83, 84, 85, 85, 86, 86, 87, 87, 88, 89, 89,
+	90, 90, 91, 92, 92, 93, 93, 94, 95, 95, 96,
+	96, 97, 98, 98, 99, 99, 100, 101, 101, 102, 103,
+	103, 104, 105, 105, 106, 106, 107, 108, 108, 109, 110,
+	110, 111, 112, 112, 113, 114, 115, 115, 116, 117, 117,
+	118, 119, 119, 120, 121, 122, 122, 123, 124, 124, 125,
+	126, 127, 127, 128, 129, 130, 130, 131, 132, 132, 133,
+	134, 135, 136, 136, 137, 138, 139, 139, 140, 141, 142,
+	143, 143, 144, 145, 146, 146, 147, 148, 149, 150, 151,
+	151, 152, 153, 154, 155, 155, 156, 157, 158, 159, 160,
+	161, 161, 162, 163, 164, 165, 166, 167, 167, 168, 169,
+	170, 171, 172, 173, 174, 175, 175, 176, 177, 178, 179,
+	180, 181, 182, 183, 184, 185, 186, 186, 187, 188, 189,
+	190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200,
+	201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211,
+	212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222,
+	223, 224, 225, 226, 228, 229, 230, 231, 232, 233, 234,
+	235, 236, 237, 238, 239, 241, 242, 243, 244, 245, 246,
+	247, 248, 249, 251, 252, 253, 254, 255, 256, 257, 259,
+	260, 261, 262, 263, 264, 266, 267, 268, 269, 270, 272,
+	273, 274, 275, 276, 278, 279, 280, 281, 282, 284, 285,
+	286, 287, 289, 290, 291, 292, 294, 295, 296, 297, 299,
+	300, 301, 302, 304, 305, 306, 308, 309, 310, 311, 313,
+	314, 315, 317, 318, 319, 321, 322, 323, 325, 326, 327,
+	329, 330, 331, 333, 334, 336, 337, 338, 340, 341, 342,
+	344, 345, 347, 348, 349, 351, 352, 354, 355, 356, 358,
+	359, 361, 362, 364, 365, 366, 368, 369, 371, 372, 374,
+	375, 377, 378, 380, 381, 383, 384, 386, 387, 389, 390,
+	392, 393, 395, 396, 398, 399, 401, 402, 404, 405, 407,
+	408, 410, 412, 413, 415, 416, 418, 419, 421, 423, 424,
+	426, 427, 429, 431, 432, 434, 435, 437, 439, 440, 442,
+	444, 445, 447, 448, 450, 452, 453, 455, 457, 458, 460,
+	462, 463, 465, 467, 468, 470, 472, 474, 475, 477, 479,
+	480, 482, 484, 486, 487, 489, 491, 493, 494, 496, 498,
+	500, 501, 503, 505, 507, 509, 510, 512, 514, 516, 518,
+	519, 521, 523, 525, 527, 528, 530, 532, 534, 536, 538,
+	539, 541, 543, 545, 547, 549, 551, 553, 554, 556, 558,
+	560, 562, 564, 566, 568, 570, 572, 574, 575, 577, 579,
+	581, 583, 585, 587, 589, 591, 593, 595, 597, 599, 601,
+	603, 605, 607, 609, 611, 613, 615, 617, 619, 621, 623,
+	625, 627, 629, 631, 633, 635, 637, 640, 642, 644, 646,
+	648, 650, 652, 654, 656, 658, 660, 663, 665, 667, 669,
+	671, 673, 675, 678, 680, 682, 684, 686, 688, 690, 693,
+	695, 697, 699, 701, 704, 706, 708, 710, 712, 715, 717,
+	719, 721, 724, 726, 728, 730, 733, 735, 737, 739, 742,
+	744, 746, 749, 751, 753, 755, 758, 760, 762, 765, 767,
+	769, 772, 774, 776, 779, 781, 783, 786, 788, 790, 793,
+	795, 798, 800, 802, 805, 807, 810, 812, 814, 817, 819,
+	822, 824, 827, 829, 831, 834, 836, 839, 841, 844, 846,
+	849, 851, 854, 856, 859, 861, 864, 866, 869, 871, 874,
+	876, 879, 881, 884, 887, 889, 892, 894, 897, 899, 902,
+	905, 907, 910, 912, 915, 918, 920, 923, 925, 928, 931,
+	933, 936, 939, 941, 944, 947, 949, 952, 955, 957, 960,
+	963, 965, 968, 971, 973, 976, 979, 982, 984, 987, 990,
+	992, 995, 998, 1001, 1004, 1006, 1009, 1012, 1015, 1017, 1020,
+	1023,
+};
+
+static const u16 xgamma10_29[GAMMA10_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2,
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+	2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3,
+	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+	3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+	4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5,
+	5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6,
+	6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
+	7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9,
+	9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10,
+	10, 10, 11, 11, 11, 11, 11, 11, 11, 12, 12,
+	12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13,
+	14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15,
+	16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 18,
+	18, 18, 18, 18, 19, 19, 19, 19, 19, 20, 20,
+	20, 20, 21, 21, 21, 21, 21, 22, 22, 22, 22,
+	23, 23, 23, 23, 24, 24, 24, 24, 25, 25, 25,
+	25, 26, 26, 26, 26, 27, 27, 27, 28, 28, 28,
+	28, 29, 29, 29, 29, 30, 30, 30, 31, 31, 31,
+	31, 32, 32, 32, 33, 33, 33, 34, 34, 34, 35,
+	35, 35, 35, 36, 36, 36, 37, 37, 37, 38, 38,
+	38, 39, 39, 39, 40, 40, 41, 41, 41, 42, 42,
+	42, 43, 43, 43, 44, 44, 44, 45, 45, 46, 46,
+	46, 47, 47, 48, 48, 48, 49, 49, 49, 50, 50,
+	51, 51, 52, 52, 52, 53, 53, 54, 54, 54, 55,
+	55, 56, 56, 57, 57, 57, 58, 58, 59, 59, 60,
+	60, 61, 61, 61, 62, 62, 63, 63, 64, 64, 65,
+	65, 66, 66, 67, 67, 68, 68, 69, 69, 70, 70,
+	71, 71, 72, 72, 73, 73, 74, 74, 75, 75, 76,
+	76, 77, 77, 78, 78, 79, 80, 80, 81, 81, 82,
+	82, 83, 83, 84, 85, 85, 86, 86, 87, 87, 88,
+	89, 89, 90, 90, 91, 92, 92, 93, 93, 94, 95,
+	95, 96, 96, 97, 98, 98, 99, 99, 100, 101, 101,
+	102, 103, 103, 104, 105, 105, 106, 107, 107, 108, 109,
+	109, 110, 111, 111, 112, 113, 113, 114, 115, 115, 116,
+	117, 117, 118, 119, 120, 120, 121, 122, 122, 123, 124,
+	125, 125, 126, 127, 128, 128, 129, 130, 131, 131, 132,
+	133, 134, 134, 135, 136, 137, 137, 138, 139, 140, 141,
+	141, 142, 143, 144, 145, 145, 146, 147, 148, 149, 149,
+	150, 151, 152, 153, 154, 154, 155, 156, 157, 158, 159,
+	160, 160, 161, 162, 163, 164, 165, 166, 166, 167, 168,
+	169, 170, 171, 172, 173, 174, 175, 175, 176, 177, 178,
+	179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
+	190, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
+	200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210,
+	211, 212, 214, 215, 216, 217, 218, 219, 220, 221, 222,
+	223, 224, 225, 226, 227, 228, 229, 231, 232, 233, 234,
+	235, 236, 237, 238, 239, 241, 242, 243, 244, 245, 246,
+	247, 248, 250, 251, 252, 253, 254, 255, 257, 258, 259,
+	260, 261, 263, 264, 265, 266, 267, 269, 270, 271, 272,
+	273, 275, 276, 277, 278, 280, 281, 282, 283, 285, 286,
+	287, 288, 290, 291, 292, 293, 295, 296, 297, 299, 300,
+	301, 302, 304, 305, 306, 308, 309, 310, 312, 313, 314,
+	316, 317, 318, 320, 321, 322, 324, 325, 327, 328, 329,
+	331, 332, 333, 335, 336, 338, 339, 340, 342, 343, 345,
+	346, 348, 349, 350, 352, 353, 355, 356, 358, 359, 361,
+	362, 363, 365, 366, 368, 369, 371, 372, 374, 375, 377,
+	378, 380, 381, 383, 384, 386, 388, 389, 391, 392, 394,
+	395, 397, 398, 400, 402, 403, 405, 406, 408, 409, 411,
+	413, 414, 416, 417, 419, 421, 422, 424, 426, 427, 429,
+	430, 432, 434, 435, 437, 439, 440, 442, 444, 445, 447,
+	449, 450, 452, 454, 456, 457, 459, 461, 462, 464, 466,
+	468, 469, 471, 473, 475, 476, 478, 480, 482, 483, 485,
+	487, 489, 491, 492, 494, 496, 498, 500, 501, 503, 505,
+	507, 509, 511, 512, 514, 516, 518, 520, 522, 524, 525,
+	527, 529, 531, 533, 535, 537, 539, 541, 542, 544, 546,
+	548, 550, 552, 554, 556, 558, 560, 562, 564, 566, 568,
+	570, 572, 574, 576, 578, 580, 582, 584, 586, 588, 590,
+	592, 594, 596, 598, 600, 602, 604, 606, 608, 610, 612,
+	614, 616, 618, 621, 623, 625, 627, 629, 631, 633, 635,
+	637, 640, 642, 644, 646, 648, 650, 652, 655, 657, 659,
+	661, 663, 665, 668, 670, 672, 674, 676, 679, 681, 683,
+	685, 688, 690, 692, 694, 697, 699, 701, 703, 706, 708,
+	710, 712, 715, 717, 719, 722, 724, 726, 729, 731, 733,
+	736, 738, 740, 743, 745, 747, 750, 752, 754, 757, 759,
+	762, 764, 766, 769, 771, 774, 776, 778, 781, 783, 786,
+	788, 791, 793, 795, 798, 800, 803, 805, 808, 810, 813,
+	815, 818, 820, 823, 825, 828, 830, 833, 835, 838, 841,
+	843, 846, 848, 851, 853, 856, 859, 861, 864, 866, 869,
+	872, 874, 877, 879, 882, 885, 887, 890, 893, 895, 898,
+	901, 903, 906, 909, 911, 914, 917, 919, 922, 925, 927,
+	930, 933, 936, 938, 941, 944, 947, 949, 952, 955, 958,
+	960, 963, 966, 969, 972, 974, 977, 980, 983, 986, 989,
+	991, 994, 997, 1000, 1003, 1006, 1009, 1011, 1014, 1017, 1020,
+	1023,
+};
+
+static const u16 xgamma10_30[GAMMA10_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+	2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
+	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+	3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+	4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
+	5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6,
+	6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
+	7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9,
+	9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10,
+	10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 12,
+	12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13,
+	14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15,
+	15, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17,
+	18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 20,
+	20, 20, 20, 21, 21, 21, 21, 21, 22, 22, 22,
+	22, 23, 23, 23, 23, 24, 24, 24, 24, 25, 25,
+	25, 25, 26, 26, 26, 26, 27, 27, 27, 27, 28,
+	28, 28, 28, 29, 29, 29, 30, 30, 30, 30, 31,
+	31, 31, 32, 32, 32, 33, 33, 33, 33, 34, 34,
+	34, 35, 35, 35, 36, 36, 36, 37, 37, 37, 38,
+	38, 38, 39, 39, 39, 40, 40, 40, 41, 41, 41,
+	42, 42, 42, 43, 43, 43, 44, 44, 45, 45, 45,
+	46, 46, 46, 47, 47, 48, 48, 48, 49, 49, 50,
+	50, 50, 51, 51, 52, 52, 52, 53, 53, 54, 54,
+	55, 55, 55, 56, 56, 57, 57, 58, 58, 58, 59,
+	59, 60, 60, 61, 61, 62, 62, 63, 63, 63, 64,
+	64, 65, 65, 66, 66, 67, 67, 68, 68, 69, 69,
+	70, 70, 71, 71, 72, 72, 73, 73, 74, 74, 75,
+	75, 76, 77, 77, 78, 78, 79, 79, 80, 80, 81,
+	81, 82, 83, 83, 84, 84, 85, 85, 86, 86, 87,
+	88, 88, 89, 89, 90, 91, 91, 92, 92, 93, 94,
+	94, 95, 95, 96, 97, 97, 98, 99, 99, 100, 100,
+	101, 102, 102, 103, 104, 104, 105, 106, 106, 107, 108,
+	108, 109, 110, 110, 111, 112, 112, 113, 114, 114, 115,
+	116, 117, 117, 118, 119, 119, 120, 121, 122, 122, 123,
+	124, 125, 125, 126, 127, 128, 128, 129, 130, 131, 131,
+	132, 133, 134, 134, 135, 136, 137, 137, 138, 139, 140,
+	141, 141, 142, 143, 144, 145, 146, 146, 147, 148, 149,
+	150, 150, 151, 152, 153, 154, 155, 156, 156, 157, 158,
+	159, 160, 161, 162, 162, 163, 164, 165, 166, 167, 168,
+	169, 170, 171, 171, 172, 173, 174, 175, 176, 177, 178,
+	179, 180, 181, 182, 183, 184, 185, 185, 186, 187, 188,
+	189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
+	200, 201, 202, 203, 204, 205, 206, 207, 208, 210, 211,
+	212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222,
+	223, 224, 226, 227, 228, 229, 230, 231, 232, 233, 234,
+	236, 237, 238, 239, 240, 241, 242, 244, 245, 246, 247,
+	248, 249, 250, 252, 253, 254, 255, 256, 258, 259, 260,
+	261, 262, 264, 265, 266, 267, 269, 270, 271, 272, 273,
+	275, 276, 277, 278, 280, 281, 282, 284, 285, 286, 287,
+	289, 290, 291, 293, 294, 295, 296, 298, 299, 300, 302,
+	303, 304, 306, 307, 308, 310, 311, 313, 314, 315, 317,
+	318, 319, 321, 322, 324, 325, 326, 328, 329, 331, 332,
+	333, 335, 336, 338, 339, 341, 342, 343, 345, 346, 348,
+	349, 351, 352, 354, 355, 357, 358, 360, 361, 363, 364,
+	366, 367, 369, 370, 372, 373, 375, 376, 378, 379, 381,
+	383, 384, 386, 387, 389, 390, 392, 394, 395, 397, 398,
+	400, 402, 403, 405, 406, 408, 410, 411, 413, 415, 416,
+	418, 419, 421, 423, 424, 426, 428, 429, 431, 433, 435,
+	436, 438, 440, 441, 443, 445, 447, 448, 450, 452, 453,
+	455, 457, 459, 460, 462, 464, 466, 468, 469, 471, 473,
+	475, 477, 478, 480, 482, 484, 486, 487, 489, 491, 493,
+	495, 497, 498, 500, 502, 504, 506, 508, 510, 512, 513,
+	515, 517, 519, 521, 523, 525, 527, 529, 531, 533, 535,
+	537, 539, 540, 542, 544, 546, 548, 550, 552, 554, 556,
+	558, 560, 562, 564, 566, 568, 570, 572, 574, 577, 579,
+	581, 583, 585, 587, 589, 591, 593, 595, 597, 599, 601,
+	604, 606, 608, 610, 612, 614, 616, 618, 621, 623, 625,
+	627, 629, 631, 634, 636, 638, 640, 642, 645, 647, 649,
+	651, 653, 656, 658, 660, 662, 665, 667, 669, 671, 674,
+	676, 678, 680, 683, 685, 687, 690, 692, 694, 697, 699,
+	701, 704, 706, 708, 711, 713, 715, 718, 720, 722, 725,
+	727, 730, 732, 734, 737, 739, 742, 744, 746, 749, 751,
+	754, 756, 759, 761, 764, 766, 769, 771, 774, 776, 779,
+	781, 784, 786, 789, 791, 794, 796, 799, 801, 804, 806,
+	809, 812, 814, 817, 819, 822, 824, 827, 830, 832, 835,
+	837, 840, 843, 845, 848, 851, 853, 856, 859, 861, 864,
+	867, 869, 872, 875, 878, 880, 883, 886, 888, 891, 894,
+	897, 899, 902, 905, 908, 910, 913, 916, 919, 922, 924,
+	927, 930, 933, 936, 938, 941, 944, 947, 950, 953, 956,
+	958, 961, 964, 967, 970, 973, 976, 979, 982, 984, 987,
+	990, 993, 996, 999, 1002, 1005, 1008, 1011, 1014, 1017, 1020,
+	1023,
+};
+
+static const u16 xgamma10_31[GAMMA10_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+	2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3,
+	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4,
+	4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+	4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+	5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6,
+	6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
+	7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9,
+	9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10,
+	10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 12,
+	12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13,
+	13, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15,
+	15, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17,
+	17, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19,
+	20, 20, 20, 20, 21, 21, 21, 21, 21, 22, 22,
+	22, 22, 23, 23, 23, 23, 24, 24, 24, 24, 25,
+	25, 25, 25, 26, 26, 26, 26, 27, 27, 27, 27,
+	28, 28, 28, 28, 29, 29, 29, 30, 30, 30, 30,
+	31, 31, 31, 32, 32, 32, 32, 33, 33, 33, 34,
+	34, 34, 35, 35, 35, 36, 36, 36, 36, 37, 37,
+	37, 38, 38, 38, 39, 39, 39, 40, 40, 41, 41,
+	41, 42, 42, 42, 43, 43, 43, 44, 44, 44, 45,
+	45, 46, 46, 46, 47, 47, 47, 48, 48, 49, 49,
+	49, 50, 50, 51, 51, 51, 52, 52, 53, 53, 54,
+	54, 54, 55, 55, 56, 56, 57, 57, 57, 58, 58,
+	59, 59, 60, 60, 61, 61, 61, 62, 62, 63, 63,
+	64, 64, 65, 65, 66, 66, 67, 67, 68, 68, 69,
+	69, 70, 70, 71, 71, 72, 72, 73, 73, 74, 74,
+	75, 75, 76, 76, 77, 77, 78, 79, 79, 80, 80,
+	81, 81, 82, 82, 83, 84, 84, 85, 85, 86, 86,
+	87, 88, 88, 89, 89, 90, 91, 91, 92, 92, 93,
+	94, 94, 95, 95, 96, 97, 97, 98, 99, 99, 100,
+	101, 101, 102, 102, 103, 104, 104, 105, 106, 106, 107,
+	108, 108, 109, 110, 111, 111, 112, 113, 113, 114, 115,
+	115, 116, 117, 118, 118, 119, 120, 120, 121, 122, 123,
+	123, 124, 125, 126, 126, 127, 128, 129, 129, 130, 131,
+	132, 132, 133, 134, 135, 136, 136, 137, 138, 139, 140,
+	140, 141, 142, 143, 144, 144, 145, 146, 147, 148, 149,
+	149, 150, 151, 152, 153, 154, 155, 155, 156, 157, 158,
+	159, 160, 161, 162, 162, 163, 164, 165, 166, 167, 168,
+	169, 170, 171, 171, 172, 173, 174, 175, 176, 177, 178,
+	179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
+	190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200,
+	201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211,
+	212, 213, 214, 216, 217, 218, 219, 220, 221, 222, 223,
+	224, 225, 227, 228, 229, 230, 231, 232, 233, 234, 236,
+	237, 238, 239, 240, 241, 243, 244, 245, 246, 247, 248,
+	250, 251, 252, 253, 254, 256, 257, 258, 259, 260, 262,
+	263, 264, 265, 267, 268, 269, 270, 272, 273, 274, 275,
+	277, 278, 279, 281, 282, 283, 285, 286, 287, 288, 290,
+	291, 292, 294, 295, 296, 298, 299, 300, 302, 303, 305,
+	306, 307, 309, 310, 311, 313, 314, 316, 317, 318, 320,
+	321, 323, 324, 325, 327, 328, 330, 331, 333, 334, 336,
+	337, 338, 340, 341, 343, 344, 346, 347, 349, 350, 352,
+	353, 355, 356, 358, 359, 361, 362, 364, 366, 367, 369,
+	370, 372, 373, 375, 376, 378, 380, 381, 383, 384, 386,
+	388, 389, 391, 392, 394, 396, 397, 399, 401, 402, 404,
+	406, 407, 409, 411, 412, 414, 416, 417, 419, 421, 422,
+	424, 426, 427, 429, 431, 433, 434, 436, 438, 440, 441,
+	443, 445, 447, 448, 450, 452, 454, 456, 457, 459, 461,
+	463, 465, 466, 468, 470, 472, 474, 476, 477, 479, 481,
+	483, 485, 487, 489, 490, 492, 494, 496, 498, 500, 502,
+	504, 506, 508, 510, 511, 513, 515, 517, 519, 521, 523,
+	525, 527, 529, 531, 533, 535, 537, 539, 541, 543, 545,
+	547, 549, 551, 553, 555, 557, 559, 561, 564, 566, 568,
+	570, 572, 574, 576, 578, 580, 582, 584, 587, 589, 591,
+	593, 595, 597, 599, 602, 604, 606, 608, 610, 613, 615,
+	617, 619, 621, 624, 626, 628, 630, 632, 635, 637, 639,
+	641, 644, 646, 648, 651, 653, 655, 657, 660, 662, 664,
+	667, 669, 671, 674, 676, 678, 681, 683, 685, 688, 690,
+	692, 695, 697, 700, 702, 704, 707, 709, 712, 714, 717,
+	719, 721, 724, 726, 729, 731, 734, 736, 739, 741, 744,
+	746, 749, 751, 754, 756, 759, 761, 764, 766, 769, 772,
+	774, 777, 779, 782, 784, 787, 790, 792, 795, 797, 800,
+	803, 805, 808, 811, 813, 816, 819, 821, 824, 827, 829,
+	832, 835, 837, 840, 843, 845, 848, 851, 854, 856, 859,
+	862, 865, 867, 870, 873, 876, 879, 881, 884, 887, 890,
+	893, 895, 898, 901, 904, 907, 910, 913, 915, 918, 921,
+	924, 927, 930, 933, 936, 939, 942, 945, 947, 950, 953,
+	956, 959, 962, 965, 968, 971, 974, 977, 980, 983, 986,
+	989, 992, 995, 998, 1001, 1005, 1008, 1011, 1014, 1017, 1020,
+	1023,
+};
+
+static const u16 xgamma10_32[GAMMA10_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+	2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
+	3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4,
+	4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+	4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+	5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+	6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+	7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9,
+	9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10,
+	10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 12,
+	12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13,
+	13, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15,
+	15, 15, 16, 16, 16, 16, 16, 17, 17, 17, 17,
+	17, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19,
+	20, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22,
+	22, 22, 22, 23, 23, 23, 23, 24, 24, 24, 24,
+	25, 25, 25, 25, 26, 26, 26, 26, 27, 27, 27,
+	27, 28, 28, 28, 28, 29, 29, 29, 30, 30, 30,
+	30, 31, 31, 31, 32, 32, 32, 32, 33, 33, 33,
+	34, 34, 34, 35, 35, 35, 36, 36, 36, 37, 37,
+	37, 37, 38, 38, 38, 39, 39, 39, 40, 40, 41,
+	41, 41, 42, 42, 42, 43, 43, 43, 44, 44, 44,
+	45, 45, 46, 46, 46, 47, 47, 48, 48, 48, 49,
+	49, 49, 50, 50, 51, 51, 51, 52, 52, 53, 53,
+	54, 54, 54, 55, 55, 56, 56, 57, 57, 57, 58,
+	58, 59, 59, 60, 60, 61, 61, 62, 62, 62, 63,
+	63, 64, 64, 65, 65, 66, 66, 67, 67, 68, 68,
+	69, 69, 70, 70, 71, 71, 72, 72, 73, 73, 74,
+	74, 75, 75, 76, 77, 77, 78, 78, 79, 79, 80,
+	80, 81, 81, 82, 83, 83, 84, 84, 85, 85, 86,
+	87, 87, 88, 88, 89, 90, 90, 91, 91, 92, 93,
+	93, 94, 95, 95, 96, 96, 97, 98, 98, 99, 100,
+	100, 101, 102, 102, 103, 104, 104, 105, 106, 106, 107,
+	108, 108, 109, 110, 110, 111, 112, 112, 113, 114, 114,
+	115, 116, 117, 117, 118, 119, 120, 120, 121, 122, 122,
+	123, 124, 125, 125, 126, 127, 128, 129, 129, 130, 131,
+	132, 132, 133, 134, 135, 136, 136, 137, 138, 139, 140,
+	140, 141, 142, 143, 144, 145, 145, 146, 147, 148, 149,
+	150, 150, 151, 152, 153, 154, 155, 156, 157, 157, 158,
+	159, 160, 161, 162, 163, 164, 165, 166, 166, 167, 168,
+	169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
+	180, 181, 182, 183, 184, 185, 186, 186, 187, 188, 189,
+	190, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201,
+	202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212,
+	214, 215, 216, 217, 218, 219, 220, 221, 222, 224, 225,
+	226, 227, 228, 229, 230, 231, 233, 234, 235, 236, 237,
+	238, 240, 241, 242, 243, 244, 246, 247, 248, 249, 250,
+	252, 253, 254, 255, 257, 258, 259, 260, 262, 263, 264,
+	265, 267, 268, 269, 270, 272, 273, 274, 276, 277, 278,
+	280, 281, 282, 283, 285, 286, 287, 289, 290, 291, 293,
+	294, 296, 297, 298, 300, 301, 302, 304, 305, 307, 308,
+	309, 311, 312, 314, 315, 316, 318, 319, 321, 322, 324,
+	325, 327, 328, 330, 331, 332, 334, 335, 337, 338, 340,
+	341, 343, 344, 346, 347, 349, 351, 352, 354, 355, 357,
+	358, 360, 361, 363, 364, 366, 368, 369, 371, 372, 374,
+	376, 377, 379, 380, 382, 384, 385, 387, 389, 390, 392,
+	394, 395, 397, 399, 400, 402, 404, 405, 407, 409, 410,
+	412, 414, 416, 417, 419, 421, 423, 424, 426, 428, 430,
+	431, 433, 435, 437, 438, 440, 442, 444, 446, 447, 449,
+	451, 453, 455, 457, 458, 460, 462, 464, 466, 468, 469,
+	471, 473, 475, 477, 479, 481, 483, 485, 487, 488, 490,
+	492, 494, 496, 498, 500, 502, 504, 506, 508, 510, 512,
+	514, 516, 518, 520, 522, 524, 526, 528, 530, 532, 534,
+	536, 538, 540, 542, 544, 547, 549, 551, 553, 555, 557,
+	559, 561, 563, 565, 568, 570, 572, 574, 576, 578, 581,
+	583, 585, 587, 589, 591, 594, 596, 598, 600, 602, 605,
+	607, 609, 611, 614, 616, 618, 620, 623, 625, 627, 630,
+	632, 634, 636, 639, 641, 643, 646, 648, 650, 653, 655,
+	657, 660, 662, 665, 667, 669, 672, 674, 677, 679, 681,
+	684, 686, 689, 691, 694, 696, 698, 701, 703, 706, 708,
+	711, 713, 716, 718, 721, 723, 726, 728, 731, 734, 736,
+	739, 741, 744, 746, 749, 751, 754, 757, 759, 762, 765,
+	767, 770, 772, 775, 778, 780, 783, 786, 788, 791, 794,
+	796, 799, 802, 804, 807, 810, 813, 815, 818, 821, 824,
+	826, 829, 832, 835, 838, 840, 843, 846, 849, 852, 854,
+	857, 860, 863, 866, 869, 871, 874, 877, 880, 883, 886,
+	889, 892, 895, 897, 900, 903, 906, 909, 912, 915, 918,
+	921, 924, 927, 930, 933, 936, 939, 942, 945, 948, 951,
+	954, 957, 960, 963, 967, 970, 973, 976, 979, 982, 985,
+	988, 991, 994, 998, 1001, 1004, 1007, 1010, 1013, 1017, 1020,
+	1023,
+};
+
+static const u16 xgamma10_33[GAMMA10_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+	2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+	3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4,
+	4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+	5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+	5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+	6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+	8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9,
+	9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10,
+	10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 12,
+	12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13,
+	13, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15,
+	15, 15, 16, 16, 16, 16, 16, 17, 17, 17, 17,
+	17, 17, 18, 18, 18, 18, 18, 19, 19, 19, 19,
+	19, 20, 20, 20, 20, 21, 21, 21, 21, 21, 22,
+	22, 22, 22, 23, 23, 23, 23, 23, 24, 24, 24,
+	24, 25, 25, 25, 25, 26, 26, 26, 26, 27, 27,
+	27, 28, 28, 28, 28, 29, 29, 29, 29, 30, 30,
+	30, 31, 31, 31, 31, 32, 32, 32, 33, 33, 33,
+	33, 34, 34, 34, 35, 35, 35, 36, 36, 36, 37,
+	37, 37, 38, 38, 38, 39, 39, 39, 40, 40, 40,
+	41, 41, 41, 42, 42, 42, 43, 43, 44, 44, 44,
+	45, 45, 45, 46, 46, 47, 47, 47, 48, 48, 48,
+	49, 49, 50, 50, 50, 51, 51, 52, 52, 53, 53,
+	53, 54, 54, 55, 55, 55, 56, 56, 57, 57, 58,
+	58, 59, 59, 59, 60, 60, 61, 61, 62, 62, 63,
+	63, 64, 64, 65, 65, 66, 66, 67, 67, 68, 68,
+	69, 69, 70, 70, 71, 71, 72, 72, 73, 73, 74,
+	74, 75, 75, 76, 76, 77, 77, 78, 79, 79, 80,
+	80, 81, 81, 82, 82, 83, 84, 84, 85, 85, 86,
+	87, 87, 88, 88, 89, 90, 90, 91, 91, 92, 93,
+	93, 94, 94, 95, 96, 96, 97, 98, 98, 99, 100,
+	100, 101, 102, 102, 103, 104, 104, 105, 106, 106, 107,
+	108, 108, 109, 110, 110, 111, 112, 112, 113, 114, 115,
+	115, 116, 117, 118, 118, 119, 120, 120, 121, 122, 123,
+	123, 124, 125, 126, 127, 127, 128, 129, 130, 130, 131,
+	132, 133, 134, 134, 135, 136, 137, 138, 138, 139, 140,
+	141, 142, 143, 143, 144, 145, 146, 147, 148, 148, 149,
+	150, 151, 152, 153, 154, 155, 155, 156, 157, 158, 159,
+	160, 161, 162, 163, 164, 165, 165, 166, 167, 168, 169,
+	170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180,
+	181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
+	192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202,
+	203, 204, 206, 207, 208, 209, 210, 211, 212, 213, 214,
+	215, 216, 218, 219, 220, 221, 222, 223, 224, 226, 227,
+	228, 229, 230, 231, 233, 234, 235, 236, 237, 238, 240,
+	241, 242, 243, 245, 246, 247, 248, 249, 251, 252, 253,
+	254, 256, 257, 258, 259, 261, 262, 263, 265, 266, 267,
+	268, 270, 271, 272, 274, 275, 276, 278, 279, 280, 282,
+	283, 284, 286, 287, 288, 290, 291, 292, 294, 295, 297,
+	298, 299, 301, 302, 304, 305, 307, 308, 309, 311, 312,
+	314, 315, 317, 318, 320, 321, 322, 324, 325, 327, 328,
+	330, 331, 333, 334, 336, 337, 339, 341, 342, 344, 345,
+	347, 348, 350, 351, 353, 355, 356, 358, 359, 361, 362,
+	364, 366, 367, 369, 371, 372, 374, 375, 377, 379, 380,
+	382, 384, 385, 387, 389, 390, 392, 394, 395, 397, 399,
+	401, 402, 404, 406, 408, 409, 411, 413, 414, 416, 418,
+	420, 422, 423, 425, 427, 429, 431, 432, 434, 436, 438,
+	440, 441, 443, 445, 447, 449, 451, 453, 454, 456, 458,
+	460, 462, 464, 466, 468, 470, 472, 473, 475, 477, 479,
+	481, 483, 485, 487, 489, 491, 493, 495, 497, 499, 501,
+	503, 505, 507, 509, 511, 513, 515, 517, 519, 521, 523,
+	525, 528, 530, 532, 534, 536, 538, 540, 542, 544, 547,
+	549, 551, 553, 555, 557, 559, 562, 564, 566, 568, 570,
+	573, 575, 577, 579, 581, 584, 586, 588, 590, 593, 595,
+	597, 599, 602, 604, 606, 609, 611, 613, 615, 618, 620,
+	622, 625, 627, 629, 632, 634, 637, 639, 641, 644, 646,
+	648, 651, 653, 656, 658, 661, 663, 665, 668, 670, 673,
+	675, 678, 680, 683, 685, 688, 690, 693, 695, 698, 700,
+	703, 705, 708, 710, 713, 716, 718, 721, 723, 726, 729,
+	731, 734, 736, 739, 742, 744, 747, 750, 752, 755, 758,
+	760, 763, 766, 768, 771, 774, 776, 779, 782, 785, 787,
+	790, 793, 796, 798, 801, 804, 807, 810, 812, 815, 818,
+	821, 824, 827, 829, 832, 835, 838, 841, 844, 847, 850,
+	852, 855, 858, 861, 864, 867, 870, 873, 876, 879, 882,
+	885, 888, 891, 894, 897, 900, 903, 906, 909, 912, 915,
+	918, 921, 924, 927, 930, 933, 937, 940, 943, 946, 949,
+	952, 955, 958, 962, 965, 968, 971, 974, 978, 981, 984,
+	987, 990, 994, 997, 1000, 1003, 1007, 1010, 1013, 1016, 1020,
+	1023,
+};
+
+static const u16 xgamma10_34[GAMMA10_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3,
+	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+	3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4,
+	4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5,
+	5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+	6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+	6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8,
+	8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9,
+	9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10,
+	10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 12,
+	12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13,
+	13, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15,
+	15, 15, 16, 16, 16, 16, 16, 17, 17, 17, 17,
+	17, 17, 18, 18, 18, 18, 18, 19, 19, 19, 19,
+	19, 20, 20, 20, 20, 21, 21, 21, 21, 21, 22,
+	22, 22, 22, 23, 23, 23, 23, 23, 24, 24, 24,
+	24, 25, 25, 25, 25, 26, 26, 26, 26, 27, 27,
+	27, 27, 28, 28, 28, 29, 29, 29, 29, 30, 30,
+	30, 30, 31, 31, 31, 32, 32, 32, 33, 33, 33,
+	33, 34, 34, 34, 35, 35, 35, 36, 36, 36, 37,
+	37, 37, 38, 38, 38, 39, 39, 39, 40, 40, 40,
+	41, 41, 41, 42, 42, 42, 43, 43, 43, 44, 44,
+	45, 45, 45, 46, 46, 46, 47, 47, 48, 48, 48,
+	49, 49, 50, 50, 50, 51, 51, 52, 52, 52, 53,
+	53, 54, 54, 55, 55, 55, 56, 56, 57, 57, 58,
+	58, 59, 59, 59, 60, 60, 61, 61, 62, 62, 63,
+	63, 64, 64, 65, 65, 66, 66, 67, 67, 68, 68,
+	69, 69, 70, 70, 71, 71, 72, 72, 73, 73, 74,
+	74, 75, 75, 76, 76, 77, 78, 78, 79, 79, 80,
+	80, 81, 81, 82, 83, 83, 84, 84, 85, 86, 86,
+	87, 87, 88, 88, 89, 90, 90, 91, 92, 92, 93,
+	93, 94, 95, 95, 96, 97, 97, 98, 99, 99, 100,
+	101, 101, 102, 102, 103, 104, 105, 105, 106, 107, 107,
+	108, 109, 109, 110, 111, 111, 112, 113, 114, 114, 115,
+	116, 117, 117, 118, 119, 119, 120, 121, 122, 123, 123,
+	124, 125, 126, 126, 127, 128, 129, 129, 130, 131, 132,
+	133, 133, 134, 135, 136, 137, 138, 138, 139, 140, 141,
+	142, 143, 143, 144, 145, 146, 147, 148, 149, 149, 150,
+	151, 152, 153, 154, 155, 156, 157, 157, 158, 159, 160,
+	161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171,
+	172, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181,
+	182, 183, 184, 185, 186, 187, 188, 189, 191, 192, 193,
+	194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204,
+	205, 207, 208, 209, 210, 211, 212, 213, 214, 215, 217,
+	218, 219, 220, 221, 222, 223, 225, 226, 227, 228, 229,
+	231, 232, 233, 234, 235, 237, 238, 239, 240, 241, 243,
+	244, 245, 246, 248, 249, 250, 251, 253, 254, 255, 256,
+	258, 259, 260, 262, 263, 264, 266, 267, 268, 269, 271,
+	272, 273, 275, 276, 278, 279, 280, 282, 283, 284, 286,
+	287, 288, 290, 291, 293, 294, 296, 297, 298, 300, 301,
+	303, 304, 306, 307, 308, 310, 311, 313, 314, 316, 317,
+	319, 320, 322, 323, 325, 326, 328, 329, 331, 332, 334,
+	335, 337, 339, 340, 342, 343, 345, 346, 348, 350, 351,
+	353, 354, 356, 358, 359, 361, 363, 364, 366, 367, 369,
+	371, 372, 374, 376, 377, 379, 381, 383, 384, 386, 388,
+	389, 391, 393, 395, 396, 398, 400, 402, 403, 405, 407,
+	409, 410, 412, 414, 416, 418, 419, 421, 423, 425, 427,
+	429, 430, 432, 434, 436, 438, 440, 442, 443, 445, 447,
+	449, 451, 453, 455, 457, 459, 461, 463, 464, 466, 468,
+	470, 472, 474, 476, 478, 480, 482, 484, 486, 488, 490,
+	492, 494, 496, 498, 500, 503, 505, 507, 509, 511, 513,
+	515, 517, 519, 521, 523, 526, 528, 530, 532, 534, 536,
+	538, 541, 543, 545, 547, 549, 551, 554, 556, 558, 560,
+	563, 565, 567, 569, 572, 574, 576, 578, 581, 583, 585,
+	587, 590, 592, 594, 597, 599, 601, 604, 606, 608, 611,
+	613, 615, 618, 620, 623, 625, 627, 630, 632, 635, 637,
+	640, 642, 644, 647, 649, 652, 654, 657, 659, 662, 664,
+	667, 669, 672, 674, 677, 679, 682, 685, 687, 690, 692,
+	695, 697, 700, 703, 705, 708, 711, 713, 716, 718, 721,
+	724, 726, 729, 732, 734, 737, 740, 743, 745, 748, 751,
+	753, 756, 759, 762, 764, 767, 770, 773, 776, 778, 781,
+	784, 787, 790, 793, 795, 798, 801, 804, 807, 810, 813,
+	815, 818, 821, 824, 827, 830, 833, 836, 839, 842, 845,
+	848, 851, 854, 857, 860, 863, 866, 869, 872, 875, 878,
+	881, 884, 887, 890, 893, 896, 899, 903, 906, 909, 912,
+	915, 918, 921, 925, 928, 931, 934, 937, 940, 944, 947,
+	950, 953, 957, 960, 963, 966, 970, 973, 976, 979, 983,
+	986, 989, 993, 996, 999, 1003, 1006, 1009, 1013, 1016, 1020,
+	1023,
+};
+
+static const u16 xgamma10_35[GAMMA10_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2,
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+	2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3,
+	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+	3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4,
+	4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5,
+	5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6,
+	6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8,
+	8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9,
+	9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10,
+	10, 10, 11, 11, 11, 11, 11, 11, 11, 12, 12,
+	12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13,
+	13, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15,
+	15, 15, 16, 16, 16, 16, 16, 17, 17, 17, 17,
+	17, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
+	20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 22,
+	22, 22, 22, 23, 23, 23, 23, 23, 24, 24, 24,
+	24, 25, 25, 25, 25, 26, 26, 26, 26, 27, 27,
+	27, 27, 28, 28, 28, 29, 29, 29, 29, 30, 30,
+	30, 31, 31, 31, 31, 32, 32, 32, 33, 33, 33,
+	33, 34, 34, 34, 35, 35, 35, 36, 36, 36, 37,
+	37, 37, 38, 38, 38, 39, 39, 39, 40, 40, 40,
+	41, 41, 41, 42, 42, 42, 43, 43, 43, 44, 44,
+	45, 45, 45, 46, 46, 47, 47, 47, 48, 48, 48,
+	49, 49, 50, 50, 50, 51, 51, 52, 52, 53, 53,
+	53, 54, 54, 55, 55, 56, 56, 56, 57, 57, 58,
+	58, 59, 59, 60, 60, 60, 61, 61, 62, 62, 63,
+	63, 64, 64, 65, 65, 66, 66, 67, 67, 68, 68,
+	69, 69, 70, 70, 71, 71, 72, 72, 73, 73, 74,
+	75, 75, 76, 76, 77, 77, 78, 78, 79, 79, 80,
+	81, 81, 82, 82, 83, 84, 84, 85, 85, 86, 86,
+	87, 88, 88, 89, 89, 90, 91, 91, 92, 93, 93,
+	94, 95, 95, 96, 96, 97, 98, 98, 99, 100, 100,
+	101, 102, 102, 103, 104, 104, 105, 106, 107, 107, 108,
+	109, 109, 110, 111, 111, 112, 113, 114, 114, 115, 116,
+	117, 117, 118, 119, 120, 120, 121, 122, 123, 123, 124,
+	125, 126, 126, 127, 128, 129, 130, 130, 131, 132, 133,
+	134, 135, 135, 136, 137, 138, 139, 140, 140, 141, 142,
+	143, 144, 145, 146, 146, 147, 148, 149, 150, 151, 152,
+	153, 154, 154, 155, 156, 157, 158, 159, 160, 161, 162,
+	163, 164, 165, 166, 167, 167, 168, 169, 170, 171, 172,
+	173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183,
+	184, 185, 186, 188, 189, 190, 191, 192, 193, 194, 195,
+	196, 197, 198, 199, 200, 201, 202, 204, 205, 206, 207,
+	208, 209, 210, 211, 213, 214, 215, 216, 217, 218, 219,
+	221, 222, 223, 224, 225, 227, 228, 229, 230, 231, 233,
+	234, 235, 236, 237, 239, 240, 241, 242, 244, 245, 246,
+	247, 249, 250, 251, 253, 254, 255, 256, 258, 259, 260,
+	262, 263, 264, 266, 267, 268, 270, 271, 272, 274, 275,
+	277, 278, 279, 281, 282, 284, 285, 286, 288, 289, 291,
+	292, 293, 295, 296, 298, 299, 301, 302, 304, 305, 307,
+	308, 310, 311, 313, 314, 316, 317, 319, 320, 322, 323,
+	325, 326, 328, 329, 331, 332, 334, 336, 337, 339, 340,
+	342, 344, 345, 347, 348, 350, 352, 353, 355, 357, 358,
+	360, 362, 363, 365, 367, 368, 370, 372, 373, 375, 377,
+	378, 380, 382, 384, 385, 387, 389, 391, 392, 394, 396,
+	398, 400, 401, 403, 405, 407, 409, 410, 412, 414, 416,
+	418, 420, 421, 423, 425, 427, 429, 431, 433, 435, 436,
+	438, 440, 442, 444, 446, 448, 450, 452, 454, 456, 458,
+	460, 462, 464, 466, 468, 470, 472, 474, 476, 478, 480,
+	482, 484, 486, 488, 490, 492, 494, 496, 498, 500, 503,
+	505, 507, 509, 511, 513, 515, 517, 520, 522, 524, 526,
+	528, 531, 533, 535, 537, 539, 542, 544, 546, 548, 550,
+	553, 555, 557, 560, 562, 564, 566, 569, 571, 573, 576,
+	578, 580, 583, 585, 587, 590, 592, 594, 597, 599, 602,
+	604, 606, 609, 611, 614, 616, 618, 621, 623, 626, 628,
+	631, 633, 636, 638, 641, 643, 646, 648, 651, 653, 656,
+	658, 661, 664, 666, 669, 671, 674, 677, 679, 682, 684,
+	687, 690, 692, 695, 698, 700, 703, 706, 708, 711, 714,
+	716, 719, 722, 725, 727, 730, 733, 736, 738, 741, 744,
+	747, 750, 752, 755, 758, 761, 764, 766, 769, 772, 775,
+	778, 781, 784, 787, 789, 792, 795, 798, 801, 804, 807,
+	810, 813, 816, 819, 822, 825, 828, 831, 834, 837, 840,
+	843, 846, 849, 852, 855, 858, 862, 865, 868, 871, 874,
+	877, 880, 883, 887, 890, 893, 896, 899, 902, 906, 909,
+	912, 915, 919, 922, 925, 928, 932, 935, 938, 941, 945,
+	948, 951, 955, 958, 961, 965, 968, 971, 975, 978, 982,
+	985, 988, 992, 995, 999, 1002, 1006, 1009, 1013, 1016, 1020,
+	1023,
+};
+
+static const u16 xgamma10_36[GAMMA10_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+	2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
+	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+	3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
+	4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5,
+	5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6,
+	6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7,
+	7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9,
+	9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10,
+	10, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12,
+	12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13,
+	14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15,
+	15, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17,
+	17, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19,
+	20, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22,
+	22, 22, 22, 23, 23, 23, 23, 24, 24, 24, 24,
+	25, 25, 25, 25, 26, 26, 26, 26, 27, 27, 27,
+	27, 28, 28, 28, 28, 29, 29, 29, 29, 30, 30,
+	30, 31, 31, 31, 31, 32, 32, 32, 33, 33, 33,
+	34, 34, 34, 35, 35, 35, 35, 36, 36, 36, 37,
+	37, 37, 38, 38, 38, 39, 39, 39, 40, 40, 40,
+	41, 41, 41, 42, 42, 43, 43, 43, 44, 44, 44,
+	45, 45, 46, 46, 46, 47, 47, 47, 48, 48, 49,
+	49, 49, 50, 50, 51, 51, 52, 52, 52, 53, 53,
+	54, 54, 54, 55, 55, 56, 56, 57, 57, 58, 58,
+	58, 59, 59, 60, 60, 61, 61, 62, 62, 63, 63,
+	64, 64, 65, 65, 66, 66, 67, 67, 68, 68, 69,
+	69, 70, 70, 71, 71, 72, 72, 73, 73, 74, 74,
+	75, 76, 76, 77, 77, 78, 78, 79, 79, 80, 81,
+	81, 82, 82, 83, 83, 84, 85, 85, 86, 86, 87,
+	88, 88, 89, 90, 90, 91, 91, 92, 93, 93, 94,
+	95, 95, 96, 97, 97, 98, 99, 99, 100, 101, 101,
+	102, 103, 103, 104, 105, 105, 106, 107, 107, 108, 109,
+	110, 110, 111, 112, 112, 113, 114, 115, 115, 116, 117,
+	118, 118, 119, 120, 121, 121, 122, 123, 124, 125, 125,
+	126, 127, 128, 129, 129, 130, 131, 132, 133, 133, 134,
+	135, 136, 137, 138, 138, 139, 140, 141, 142, 143, 144,
+	145, 145, 146, 147, 148, 149, 150, 151, 152, 153, 153,
+	154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164,
+	165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
+	176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186,
+	187, 188, 189, 190, 191, 192, 193, 194, 196, 197, 198,
+	199, 200, 201, 202, 203, 204, 205, 207, 208, 209, 210,
+	211, 212, 214, 215, 216, 217, 218, 219, 221, 222, 223,
+	224, 225, 227, 228, 229, 230, 231, 233, 234, 235, 236,
+	238, 239, 240, 241, 243, 244, 245, 247, 248, 249, 250,
+	252, 253, 254, 256, 257, 258, 260, 261, 262, 264, 265,
+	266, 268, 269, 271, 272, 273, 275, 276, 277, 279, 280,
+	282, 283, 285, 286, 287, 289, 290, 292, 293, 295, 296,
+	298, 299, 301, 302, 304, 305, 307, 308, 310, 311, 313,
+	314, 316, 317, 319, 320, 322, 324, 325, 327, 328, 330,
+	331, 333, 335, 336, 338, 339, 341, 343, 344, 346, 348,
+	349, 351, 353, 354, 356, 358, 359, 361, 363, 364, 366,
+	368, 370, 371, 373, 375, 377, 378, 380, 382, 384, 385,
+	387, 389, 391, 393, 394, 396, 398, 400, 402, 403, 405,
+	407, 409, 411, 413, 415, 416, 418, 420, 422, 424, 426,
+	428, 430, 432, 434, 436, 438, 439, 441, 443, 445, 447,
+	449, 451, 453, 455, 457, 459, 461, 463, 465, 467, 470,
+	472, 474, 476, 478, 480, 482, 484, 486, 488, 490, 492,
+	495, 497, 499, 501, 503, 505, 508, 510, 512, 514, 516,
+	518, 521, 523, 525, 527, 530, 532, 534, 536, 539, 541,
+	543, 545, 548, 550, 552, 555, 557, 559, 562, 564, 566,
+	569, 571, 573, 576, 578, 580, 583, 585, 588, 590, 592,
+	595, 597, 600, 602, 605, 607, 610, 612, 615, 617, 620,
+	622, 625, 627, 630, 632, 635, 637, 640, 642, 645, 648,
+	650, 653, 655, 658, 661, 663, 666, 669, 671, 674, 677,
+	679, 682, 685, 687, 690, 693, 695, 698, 701, 704, 706,
+	709, 712, 715, 717, 720, 723, 726, 729, 732, 734, 737,
+	740, 743, 746, 749, 751, 754, 757, 760, 763, 766, 769,
+	772, 775, 778, 781, 784, 787, 790, 793, 796, 799, 802,
+	805, 808, 811, 814, 817, 820, 823, 826, 829, 832, 835,
+	838, 842, 845, 848, 851, 854, 857, 860, 864, 867, 870,
+	873, 876, 880, 883, 886, 889, 893, 896, 899, 903, 906,
+	909, 912, 916, 919, 922, 926, 929, 932, 936, 939, 943,
+	946, 949, 953, 956, 960, 963, 967, 970, 973, 977, 980,
+	984, 987, 991, 994, 998, 1002, 1005, 1009, 1012, 1016, 1019,
+	1023,
+};
+
+static const u16 xgamma10_37[GAMMA10_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+	2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3,
+	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+	3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+	4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5,
+	5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6,
+	6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7,
+	7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9,
+	9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
+	11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12,
+	12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 14,
+	14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15,
+	16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17,
+	18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 20,
+	20, 20, 20, 20, 21, 21, 21, 21, 21, 22, 22,
+	22, 22, 23, 23, 23, 23, 24, 24, 24, 24, 24,
+	25, 25, 25, 25, 26, 26, 26, 26, 27, 27, 27,
+	28, 28, 28, 28, 29, 29, 29, 29, 30, 30, 30,
+	31, 31, 31, 31, 32, 32, 32, 33, 33, 33, 33,
+	34, 34, 34, 35, 35, 35, 36, 36, 36, 37, 37,
+	37, 38, 38, 38, 39, 39, 39, 40, 40, 40, 41,
+	41, 41, 42, 42, 42, 43, 43, 44, 44, 44, 45,
+	45, 45, 46, 46, 47, 47, 47, 48, 48, 49, 49,
+	49, 50, 50, 51, 51, 51, 52, 52, 53, 53, 54,
+	54, 54, 55, 55, 56, 56, 57, 57, 58, 58, 58,
+	59, 59, 60, 60, 61, 61, 62, 62, 63, 63, 64,
+	64, 65, 65, 66, 66, 67, 67, 68, 68, 69, 69,
+	70, 70, 71, 71, 72, 72, 73, 73, 74, 75, 75,
+	76, 76, 77, 77, 78, 78, 79, 80, 80, 81, 81,
+	82, 82, 83, 84, 84, 85, 85, 86, 87, 87, 88,
+	89, 89, 90, 90, 91, 92, 92, 93, 94, 94, 95,
+	96, 96, 97, 98, 98, 99, 100, 100, 101, 102, 102,
+	103, 104, 104, 105, 106, 106, 107, 108, 109, 109, 110,
+	111, 112, 112, 113, 114, 114, 115, 116, 117, 118, 118,
+	119, 120, 121, 121, 122, 123, 124, 125, 125, 126, 127,
+	128, 129, 129, 130, 131, 132, 133, 134, 134, 135, 136,
+	137, 138, 139, 139, 140, 141, 142, 143, 144, 145, 146,
+	146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156,
+	157, 158, 158, 159, 160, 161, 162, 163, 164, 165, 166,
+	167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177,
+	178, 179, 180, 181, 182, 184, 185, 186, 187, 188, 189,
+	190, 191, 192, 193, 194, 195, 197, 198, 199, 200, 201,
+	202, 203, 204, 206, 207, 208, 209, 210, 211, 213, 214,
+	215, 216, 217, 218, 220, 221, 222, 223, 225, 226, 227,
+	228, 229, 231, 232, 233, 234, 236, 237, 238, 240, 241,
+	242, 243, 245, 246, 247, 249, 250, 251, 253, 254, 255,
+	257, 258, 259, 261, 262, 263, 265, 266, 268, 269, 270,
+	272, 273, 275, 276, 277, 279, 280, 282, 283, 285, 286,
+	288, 289, 291, 292, 294, 295, 297, 298, 300, 301, 303,
+	304, 306, 307, 309, 310, 312, 313, 315, 316, 318, 320,
+	321, 323, 324, 326, 328, 329, 331, 332, 334, 336, 337,
+	339, 341, 342, 344, 346, 347, 349, 351, 352, 354, 356,
+	358, 359, 361, 363, 364, 366, 368, 370, 372, 373, 375,
+	377, 379, 380, 382, 384, 386, 388, 389, 391, 393, 395,
+	397, 399, 401, 402, 404, 406, 408, 410, 412, 414, 416,
+	418, 420, 421, 423, 425, 427, 429, 431, 433, 435, 437,
+	439, 441, 443, 445, 447, 449, 451, 453, 455, 457, 459,
+	462, 464, 466, 468, 470, 472, 474, 476, 478, 480, 483,
+	485, 487, 489, 491, 493, 496, 498, 500, 502, 504, 507,
+	509, 511, 513, 515, 518, 520, 522, 524, 527, 529, 531,
+	534, 536, 538, 541, 543, 545, 548, 550, 552, 555, 557,
+	559, 562, 564, 567, 569, 571, 574, 576, 579, 581, 584,
+	586, 589, 591, 593, 596, 598, 601, 603, 606, 609, 611,
+	614, 616, 619, 621, 624, 626, 629, 632, 634, 637, 639,
+	642, 645, 647, 650, 653, 655, 658, 661, 663, 666, 669,
+	672, 674, 677, 680, 682, 685, 688, 691, 694, 696, 699,
+	702, 705, 708, 710, 713, 716, 719, 722, 725, 728, 730,
+	733, 736, 739, 742, 745, 748, 751, 754, 757, 760, 763,
+	766, 769, 772, 775, 778, 781, 784, 787, 790, 793, 796,
+	799, 802, 805, 809, 812, 815, 818, 821, 824, 827, 831,
+	834, 837, 840, 843, 847, 850, 853, 856, 860, 863, 866,
+	869, 873, 876, 879, 883, 886, 889, 893, 896, 899, 903,
+	906, 910, 913, 916, 920, 923, 927, 930, 934, 937, 940,
+	944, 947, 951, 954, 958, 961, 965, 969, 972, 976, 979,
+	983, 986, 990, 994, 997, 1001, 1005, 1008, 1012, 1016, 1019,
+	1023,
+};
+
+static const u16 xgamma10_38[GAMMA10_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+	2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4,
+	4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+	4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5,
+	5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6,
+	6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7,
+	7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9,
+	9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 11,
+	11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12,
+	12, 12, 13, 13, 13, 13, 13, 13, 13, 14, 14,
+	14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 16,
+	16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 18,
+	18, 18, 18, 18, 19, 19, 19, 19, 19, 20, 20,
+	20, 20, 20, 21, 21, 21, 21, 21, 22, 22, 22,
+	22, 23, 23, 23, 23, 24, 24, 24, 24, 24, 25,
+	25, 25, 25, 26, 26, 26, 26, 27, 27, 27, 28,
+	28, 28, 28, 29, 29, 29, 29, 30, 30, 30, 31,
+	31, 31, 31, 32, 32, 32, 33, 33, 33, 33, 34,
+	34, 34, 35, 35, 35, 36, 36, 36, 37, 37, 37,
+	38, 38, 38, 39, 39, 39, 40, 40, 40, 41, 41,
+	41, 42, 42, 43, 43, 43, 44, 44, 44, 45, 45,
+	46, 46, 46, 47, 47, 47, 48, 48, 49, 49, 49,
+	50, 50, 51, 51, 52, 52, 52, 53, 53, 54, 54,
+	55, 55, 55, 56, 56, 57, 57, 58, 58, 59, 59,
+	60, 60, 60, 61, 61, 62, 62, 63, 63, 64, 64,
+	65, 65, 66, 66, 67, 67, 68, 68, 69, 69, 70,
+	70, 71, 72, 72, 73, 73, 74, 74, 75, 75, 76,
+	76, 77, 78, 78, 79, 79, 80, 81, 81, 82, 82,
+	83, 83, 84, 85, 85, 86, 86, 87, 88, 88, 89,
+	90, 90, 91, 92, 92, 93, 93, 94, 95, 95, 96,
+	97, 97, 98, 99, 99, 100, 101, 102, 102, 103, 104,
+	104, 105, 106, 106, 107, 108, 109, 109, 110, 111, 112,
+	112, 113, 114, 115, 115, 116, 117, 118, 118, 119, 120,
+	121, 122, 122, 123, 124, 125, 126, 126, 127, 128, 129,
+	130, 130, 131, 132, 133, 134, 135, 136, 136, 137, 138,
+	139, 140, 141, 142, 143, 143, 144, 145, 146, 147, 148,
+	149, 150, 151, 152, 153, 153, 154, 155, 156, 157, 158,
+	159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169,
+	170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180,
+	182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192,
+	193, 195, 196, 197, 198, 199, 200, 201, 203, 204, 205,
+	206, 207, 208, 210, 211, 212, 213, 214, 216, 217, 218,
+	219, 220, 222, 223, 224, 225, 227, 228, 229, 230, 232,
+	233, 234, 235, 237, 238, 239, 241, 242, 243, 245, 246,
+	247, 249, 250, 251, 253, 254, 255, 257, 258, 259, 261,
+	262, 264, 265, 266, 268, 269, 271, 272, 274, 275, 276,
+	278, 279, 281, 282, 284, 285, 287, 288, 290, 291, 293,
+	294, 296, 297, 299, 300, 302, 303, 305, 307, 308, 310,
+	311, 313, 314, 316, 318, 319, 321, 323, 324, 326, 327,
+	329, 331, 332, 334, 336, 337, 339, 341, 342, 344, 346,
+	348, 349, 351, 353, 354, 356, 358, 360, 361, 363, 365,
+	367, 369, 370, 372, 374, 376, 378, 379, 381, 383, 385,
+	387, 389, 391, 392, 394, 396, 398, 400, 402, 404, 406,
+	408, 410, 412, 413, 415, 417, 419, 421, 423, 425, 427,
+	429, 431, 433, 435, 437, 439, 441, 443, 446, 448, 450,
+	452, 454, 456, 458, 460, 462, 464, 466, 469, 471, 473,
+	475, 477, 479, 482, 484, 486, 488, 490, 493, 495, 497,
+	499, 501, 504, 506, 508, 511, 513, 515, 517, 520, 522,
+	524, 527, 529, 531, 534, 536, 538, 541, 543, 546, 548,
+	550, 553, 555, 558, 560, 562, 565, 567, 570, 572, 575,
+	577, 580, 582, 585, 587, 590, 592, 595, 597, 600, 603,
+	605, 608, 610, 613, 616, 618, 621, 623, 626, 629, 631,
+	634, 637, 639, 642, 645, 648, 650, 653, 656, 658, 661,
+	664, 667, 669, 672, 675, 678, 681, 684, 686, 689, 692,
+	695, 698, 701, 703, 706, 709, 712, 715, 718, 721, 724,
+	727, 730, 733, 736, 739, 742, 745, 748, 751, 754, 757,
+	760, 763, 766, 769, 772, 775, 778, 781, 785, 788, 791,
+	794, 797, 800, 803, 807, 810, 813, 816, 820, 823, 826,
+	829, 832, 836, 839, 842, 846, 849, 852, 856, 859, 862,
+	866, 869, 872, 876, 879, 883, 886, 889, 893, 896, 900,
+	903, 907, 910, 914, 917, 921, 924, 928, 931, 935, 938,
+	942, 945, 949, 953, 956, 960, 964, 967, 971, 974, 978,
+	982, 986, 989, 993, 997, 1000, 1004, 1008, 1012, 1015, 1019,
+	1023,
+};
+
+static const u16 xgamma10_39[GAMMA10_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2,
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3,
+	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+	3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4,
+	4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+	4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+	5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6,
+	6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7,
+	7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9,
+	9, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11,
+	11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12,
+	12, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14,
+	14, 14, 14, 15, 15, 15, 15, 15, 15, 16, 16,
+	16, 16, 16, 16, 17, 17, 17, 17, 17, 18, 18,
+	18, 18, 18, 19, 19, 19, 19, 19, 20, 20, 20,
+	20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22,
+	23, 23, 23, 23, 24, 24, 24, 24, 25, 25, 25,
+	25, 26, 26, 26, 26, 27, 27, 27, 27, 28, 28,
+	28, 28, 29, 29, 29, 29, 30, 30, 30, 31, 31,
+	31, 31, 32, 32, 32, 33, 33, 33, 34, 34, 34,
+	35, 35, 35, 35, 36, 36, 36, 37, 37, 37, 38,
+	38, 38, 39, 39, 39, 40, 40, 41, 41, 41, 42,
+	42, 42, 43, 43, 43, 44, 44, 45, 45, 45, 46,
+	46, 46, 47, 47, 48, 48, 48, 49, 49, 50, 50,
+	51, 51, 51, 52, 52, 53, 53, 53, 54, 54, 55,
+	55, 56, 56, 57, 57, 57, 58, 58, 59, 59, 60,
+	60, 61, 61, 62, 62, 63, 63, 64, 64, 65, 65,
+	66, 66, 67, 67, 68, 68, 69, 69, 70, 70, 71,
+	71, 72, 73, 73, 74, 74, 75, 75, 76, 76, 77,
+	78, 78, 79, 79, 80, 80, 81, 82, 82, 83, 83,
+	84, 85, 85, 86, 87, 87, 88, 88, 89, 90, 90,
+	91, 92, 92, 93, 94, 94, 95, 96, 96, 97, 98,
+	98, 99, 100, 100, 101, 102, 102, 103, 104, 105, 105,
+	106, 107, 107, 108, 109, 110, 110, 111, 112, 113, 113,
+	114, 115, 116, 116, 117, 118, 119, 120, 120, 121, 122,
+	123, 124, 124, 125, 126, 127, 128, 129, 129, 130, 131,
+	132, 133, 134, 134, 135, 136, 137, 138, 139, 140, 141,
+	141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151,
+	152, 153, 153, 154, 155, 156, 157, 158, 159, 160, 161,
+	162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172,
+	173, 174, 176, 177, 178, 179, 180, 181, 182, 183, 184,
+	185, 186, 187, 188, 190, 191, 192, 193, 194, 195, 196,
+	198, 199, 200, 201, 202, 203, 204, 206, 207, 208, 209,
+	210, 212, 213, 214, 215, 217, 218, 219, 220, 221, 223,
+	224, 225, 227, 228, 229, 230, 232, 233, 234, 236, 237,
+	238, 239, 241, 242, 243, 245, 246, 248, 249, 250, 252,
+	253, 254, 256, 257, 259, 260, 261, 263, 264, 266, 267,
+	269, 270, 271, 273, 274, 276, 277, 279, 280, 282, 283,
+	285, 286, 288, 289, 291, 292, 294, 295, 297, 299, 300,
+	302, 303, 305, 306, 308, 310, 311, 313, 314, 316, 318,
+	319, 321, 323, 324, 326, 328, 329, 331, 333, 334, 336,
+	338, 340, 341, 343, 345, 346, 348, 350, 352, 353, 355,
+	357, 359, 361, 362, 364, 366, 368, 370, 372, 373, 375,
+	377, 379, 381, 383, 385, 386, 388, 390, 392, 394, 396,
+	398, 400, 402, 404, 406, 408, 410, 412, 414, 416, 418,
+	420, 422, 424, 426, 428, 430, 432, 434, 436, 438, 440,
+	442, 444, 446, 448, 451, 453, 455, 457, 459, 461, 463,
+	466, 468, 470, 472, 474, 477, 479, 481, 483, 485, 488,
+	490, 492, 494, 497, 499, 501, 504, 506, 508, 511, 513,
+	515, 518, 520, 522, 525, 527, 529, 532, 534, 537, 539,
+	541, 544, 546, 549, 551, 554, 556, 559, 561, 564, 566,
+	569, 571, 574, 576, 579, 581, 584, 586, 589, 592, 594,
+	597, 599, 602, 605, 607, 610, 613, 615, 618, 621, 623,
+	626, 629, 632, 634, 637, 640, 643, 645, 648, 651, 654,
+	656, 659, 662, 665, 668, 671, 673, 676, 679, 682, 685,
+	688, 691, 694, 697, 700, 702, 705, 708, 711, 714, 717,
+	720, 723, 726, 729, 732, 735, 739, 742, 745, 748, 751,
+	754, 757, 760, 763, 766, 770, 773, 776, 779, 782, 786,
+	789, 792, 795, 798, 802, 805, 808, 811, 815, 818, 821,
+	825, 828, 831, 835, 838, 841, 845, 848, 852, 855, 858,
+	862, 865, 869, 872, 876, 879, 883, 886, 890, 893, 897,
+	900, 904, 907, 911, 914, 918, 922, 925, 929, 933, 936,
+	940, 944, 947, 951, 955, 958, 962, 966, 969, 973, 977,
+	981, 985, 988, 992, 996, 1000, 1004, 1007, 1011, 1015, 1019,
+	1023,
+};
+
+static const u16 xgamma10_40[GAMMA10_TABLE_LENGTH] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+	1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+	2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3,
+	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+	3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4,
+	4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+	5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+	5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6,
+	6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
+	7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8,
+	8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10,
+	10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11,
+	11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12,
+	13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14,
+	14, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16,
+	16, 16, 17, 17, 17, 17, 17, 18, 18, 18, 18,
+	18, 18, 19, 19, 19, 19, 19, 20, 20, 20, 20,
+	21, 21, 21, 21, 21, 22, 22, 22, 22, 23, 23,
+	23, 23, 23, 24, 24, 24, 24, 25, 25, 25, 25,
+	26, 26, 26, 26, 27, 27, 27, 27, 28, 28, 28,
+	29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 31,
+	32, 32, 32, 33, 33, 33, 33, 34, 34, 34, 35,
+	35, 35, 36, 36, 36, 37, 37, 37, 38, 38, 38,
+	39, 39, 39, 40, 40, 40, 41, 41, 41, 42, 42,
+	43, 43, 43, 44, 44, 44, 45, 45, 46, 46, 46,
+	47, 47, 48, 48, 48, 49, 49, 50, 50, 50, 51,
+	51, 52, 52, 53, 53, 53, 54, 54, 55, 55, 56,
+	56, 57, 57, 57, 58, 58, 59, 59, 60, 60, 61,
+	61, 62, 62, 63, 63, 64, 64, 65, 65, 66, 66,
+	67, 67, 68, 68, 69, 69, 70, 70, 71, 72, 72,
+	73, 73, 74, 74, 75, 75, 76, 77, 77, 78, 78,
+	79, 79, 80, 81, 81, 82, 82, 83, 84, 84, 85,
+	85, 86, 87, 87, 88, 89, 89, 90, 91, 91, 92,
+	93, 93, 94, 95, 95, 96, 97, 97, 98, 99, 99,
+	100, 101, 101, 102, 103, 104, 104, 105, 106, 106, 107,
+	108, 109, 109, 110, 111, 112, 112, 113, 114, 115, 116,
+	116, 117, 118, 119, 119, 120, 121, 122, 123, 123, 124,
+	125, 126, 127, 128, 128, 129, 130, 131, 132, 133, 134,
+	134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 143,
+	144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
+	155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165,
+	166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
+	177, 178, 179, 180, 182, 183, 184, 185, 186, 187, 188,
+	189, 190, 192, 193, 194, 195, 196, 197, 199, 200, 201,
+	202, 203, 204, 206, 207, 208, 209, 210, 212, 213, 214,
+	215, 217, 218, 219, 220, 222, 223, 224, 226, 227, 228,
+	229, 231, 232, 233, 235, 236, 237, 239, 240, 241, 243,
+	244, 245, 247, 248, 250, 251, 252, 254, 255, 257, 258,
+	259, 261, 262, 264, 265, 267, 268, 270, 271, 273, 274,
+	276, 277, 279, 280, 282, 283, 285, 286, 288, 289, 291,
+	292, 294, 296, 297, 299, 300, 302, 304, 305, 307, 308,
+	310, 312, 313, 315, 317, 318, 320, 322, 323, 325, 327,
+	328, 330, 332, 333, 335, 337, 339, 340, 342, 344, 346,
+	348, 349, 351, 353, 355, 357, 358, 360, 362, 364, 366,
+	368, 369, 371, 373, 375, 377, 379, 381, 383, 385, 386,
+	388, 390, 392, 394, 396, 398, 400, 402, 404, 406, 408,
+	410, 412, 414, 416, 418, 420, 422, 424, 426, 429, 431,
+	433, 435, 437, 439, 441, 443, 445, 448, 450, 452, 454,
+	456, 458, 461, 463, 465, 467, 469, 472, 474, 476, 478,
+	481, 483, 485, 488, 490, 492, 495, 497, 499, 501, 504,
+	506, 509, 511, 513, 516, 518, 521, 523, 525, 528, 530,
+	533, 535, 538, 540, 543, 545, 548, 550, 553, 555, 558,
+	560, 563, 565, 568, 570, 573, 576, 578, 581, 583, 586,
+	589, 591, 594, 597, 599, 602, 605, 607, 610, 613, 616,
+	618, 621, 624, 627, 629, 632, 635, 638, 641, 643, 646,
+	649, 652, 655, 658, 660, 663, 666, 669, 672, 675, 678,
+	681, 684, 687, 690, 693, 696, 699, 702, 705, 708, 711,
+	714, 717, 720, 723, 726, 729, 732, 735, 739, 742, 745,
+	748, 751, 754, 758, 761, 764, 767, 770, 774, 777, 780,
+	783, 787, 790, 793, 797, 800, 803, 807, 810, 813, 817,
+	820, 824, 827, 830, 834, 837, 841, 844, 848, 851, 855,
+	858, 862, 865, 869, 872, 876, 879, 883, 886, 890, 894,
+	897, 901, 905, 908, 912, 916, 919, 923, 927, 930, 934,
+	938, 942, 945, 949, 953, 957, 960, 964, 968, 972, 976,
+	980, 984, 987, 991, 995, 999, 1003, 1007, 1011, 1015, 1019,
+	1023,
+};
+
+static const u16 *xgamma10_curves[GAMMA_CURVE_LENGTH] =  {
+	&xgamma10_01[0],
+	&xgamma10_02[0],
+	&xgamma10_03[0],
+	&xgamma10_04[0],
+	&xgamma10_05[0],
+	&xgamma10_06[0],
+	&xgamma10_07[0],
+	&xgamma10_08[0],
+	&xgamma10_09[0],
+	&xgamma10_10[0],
+	&xgamma10_11[0],
+	&xgamma10_12[0],
+	&xgamma10_13[0],
+	&xgamma10_14[0],
+	&xgamma10_15[0],
+	&xgamma10_16[0],
+	&xgamma10_17[0],
+	&xgamma10_18[0],
+	&xgamma10_19[0],
+	&xgamma10_20[0],
+	&xgamma10_21[0],
+	&xgamma10_22[0],
+	&xgamma10_23[0],
+	&xgamma10_24[0],
+	&xgamma10_25[0],
+	&xgamma10_26[0],
+	&xgamma10_27[0],
+	&xgamma10_28[0],
+	&xgamma10_29[0],
+	&xgamma10_30[0],
+	&xgamma10_31[0],
+	&xgamma10_32[0],
+	&xgamma10_33[0],
+	&xgamma10_34[0],
+	&xgamma10_35[0],
+	&xgamma10_36[0],
+	&xgamma10_37[0],
+	&xgamma10_38[0],
+	&xgamma10_39[0],
+	&xgamma10_40[0],
+};
+#endif /* __XILINX_GAMMA_COEFF_H__ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/xilinx-gamma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/xilinx-gamma.c
@@ -0,0 +1,564 @@
+/*
+ * Xilinx Gamma Correction IP
+ *
+ * Copyright (C) 2017 Xilinx, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/xilinx-v4l2-controls.h>
+
+#include <media/v4l2-async.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-subdev.h>
+
+#include "xilinx-gamma-coeff.h"
+#include "xilinx-vip.h"
+
+#define XGAMMA_MIN_HEIGHT	(64)
+#define XGAMMA_MAX_HEIGHT	(4320)
+#define XGAMMA_DEF_HEIGHT	(720)
+#define XGAMMA_MIN_WIDTH	(64)
+#define XGAMMA_MAX_WIDTH	(8192)
+#define XGAMMA_DEF_WIDTH	(1280)
+
+#define XGAMMA_AP_CTRL			(0x0000)
+#define XGAMMA_GIE			(0x0004)
+#define XGAMMA_IER			(0x0008)
+#define XGAMMA_ISR			(0x000c)
+#define XGAMMA_WIDTH			(0x0010)
+#define XGAMMA_HEIGHT			(0x0018)
+#define XGAMMA_VIDEO_FORMAT		(0x0020)
+#define XGAMMA_GAMMA_LUT_0_BASE		(0x0800)
+#define XGAMMA_GAMMA_LUT_1_BASE		(0x1000)
+#define XGAMMA_GAMMA_LUT_2_BASE		(0x1800)
+
+#define XGAMMA_RESET_DEASSERT	(0)
+#define XGAMMA_RESET_ASSERT	(1)
+#define XGAMMA_START		BIT(0)
+#define XGAMMA_AUTO_RESTART	BIT(7)
+#define XGAMMA_STREAM_ON	(XGAMMA_START | XGAMMA_AUTO_RESTART)
+
+enum xgamma_video_format {
+	XGAMMA_RGB = 0,
+};
+
+/**
+ * struct xgamma_dev - Xilinx Video Gamma LUT device structure
+ * @xvip: Xilinx Video IP device
+ * @pads: Scaler sub-device media pads
+ * @formats: V4L2 media bus formats at the sink and source pads
+ * @default_formats: default V4L2 media bus formats
+ * @ctrl_handler: V4L2 Control Handler for R,G,B Gamma Controls
+ * @red_lut: Pointer to the gamma coefficient as per the Red Gamma control
+ * @green_lut: Pointer to the gamma coefficient as per the Green Gamma control
+ * @blue_lut: Pointer to the gamma coefficient as per the Blue Gamma control
+ * @color_depth: Color depth of the Video Gamma IP
+ * @gamma_table: Pointer to the table containing various gamma values
+ * @rst_gpio: GPIO reset line to bring VPSS Scaler out of reset
+ * @max_width: Maximum width supported by this instance.
+ * @max_height: Maximum height supported by this instance.
+ */
+struct xgamma_dev {
+	struct xvip_device xvip;
+	struct media_pad pads[2];
+	struct v4l2_mbus_framefmt formats[2];
+	struct v4l2_mbus_framefmt default_formats[2];
+	struct v4l2_ctrl_handler ctrl_handler;
+
+	const u16 *red_lut;
+	const u16 *green_lut;
+	const u16 *blue_lut;
+	u32 color_depth;
+	const u16 **gamma_table;
+	struct gpio_desc *rst_gpio;
+	u32 max_width;
+	u32 max_height;
+};
+
+static inline u32 xg_read(struct xgamma_dev *xg, u32 reg)
+{
+	u32 data;
+
+	data = xvip_read(&xg->xvip, reg);
+	dev_dbg(xg->xvip.dev,
+		"Reading 0x%x from reg offset 0x%x", data, reg);
+	return data;
+}
+
+static inline void xg_write(struct xgamma_dev *xg, u32 reg, u32 data)
+{
+	dev_dbg(xg->xvip.dev,
+		"Writing 0x%x to reg offset 0x%x", data, reg);
+	xvip_write(&xg->xvip, reg, data);
+#ifdef DEBUG
+	if (xg_read(xg, reg) != data)
+		dev_err(xg->xvip.dev,
+			"Write 0x%x does not match read back", data);
+#endif
+}
+
+static inline struct xgamma_dev *to_xg(struct v4l2_subdev *subdev)
+{
+	return container_of(subdev, struct xgamma_dev, xvip.subdev);
+}
+
+static struct v4l2_mbus_framefmt *
+__xg_get_pad_format(struct xgamma_dev *xg,
+		    struct v4l2_subdev_pad_config *cfg,
+		    unsigned int pad, u32 which)
+{
+	struct v4l2_mbus_framefmt *format;
+
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		format = v4l2_subdev_get_try_format(&xg->xvip.subdev, cfg,
+						    pad);
+		break;
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		format = &xg->formats[pad];
+		break;
+	default:
+		format = NULL;
+		break;
+	}
+
+	return format;
+}
+
+static void xg_set_lut_entries(struct xgamma_dev *xg,
+			       const u16 *lut, const u32 lut_base)
+{
+	int itr;
+	u32 lut_offset, lut_data;
+
+	lut_offset = lut_base;
+	/* Write LUT Entries */
+	for (itr = 0; itr < BIT(xg->color_depth - 1); itr++) {
+		lut_data = (lut[2 * itr + 1] << 16) | lut[2 * itr];
+		xg_write(xg, lut_offset, lut_data);
+		lut_offset += 4;
+	}
+}
+
+static int xg_s_stream(struct v4l2_subdev *subdev, int enable)
+{
+	struct xgamma_dev *xg = to_xg(subdev);
+
+	if (!enable) {
+		dev_dbg(xg->xvip.dev, "%s : Off", __func__);
+		gpiod_set_value_cansleep(xg->rst_gpio, XGAMMA_RESET_ASSERT);
+		gpiod_set_value_cansleep(xg->rst_gpio, XGAMMA_RESET_DEASSERT);
+		return 0;
+	}
+	dev_dbg(xg->xvip.dev, "%s : Started", __func__);
+
+	dev_dbg(xg->xvip.dev, "%s : Setting width %d and height %d",
+		__func__, xg->formats[XVIP_PAD_SINK].width,
+		xg->formats[XVIP_PAD_SINK].height);
+	xg_write(xg, XGAMMA_WIDTH, xg->formats[XVIP_PAD_SINK].width);
+	xg_write(xg, XGAMMA_HEIGHT, xg->formats[XVIP_PAD_SINK].height);
+	xg_write(xg, XGAMMA_VIDEO_FORMAT, XGAMMA_RGB);
+	xg_set_lut_entries(xg, xg->red_lut, XGAMMA_GAMMA_LUT_0_BASE);
+	xg_set_lut_entries(xg, xg->green_lut, XGAMMA_GAMMA_LUT_1_BASE);
+	xg_set_lut_entries(xg, xg->blue_lut, XGAMMA_GAMMA_LUT_2_BASE);
+
+	/* Start GAMMA Correction LUT Video IP */
+	xg_write(xg, XGAMMA_AP_CTRL, XGAMMA_STREAM_ON);
+	return 0;
+}
+
+static const struct v4l2_subdev_video_ops xg_video_ops = {
+	.s_stream = xg_s_stream,
+};
+
+static int xg_get_format(struct v4l2_subdev *subdev,
+			 struct v4l2_subdev_pad_config *cfg,
+			 struct v4l2_subdev_format *fmt)
+{
+	struct xgamma_dev *xg = to_xg(subdev);
+	struct v4l2_mbus_framefmt *format;
+
+	format = __xg_get_pad_format(xg, cfg, fmt->pad, fmt->which);
+	if (!format)
+		return -EINVAL;
+
+	fmt->format = *format;
+
+	return 0;
+}
+
+static int xg_set_format(struct v4l2_subdev *subdev,
+			 struct v4l2_subdev_pad_config *cfg,
+			 struct v4l2_subdev_format *fmt)
+{
+	struct xgamma_dev *xg = to_xg(subdev);
+	struct v4l2_mbus_framefmt *__format;
+
+	__format = __xg_get_pad_format(xg, cfg, fmt->pad, fmt->which);
+	if (!__format)
+		return -EINVAL;
+
+	*__format = fmt->format;
+
+	if (fmt->pad == XVIP_PAD_SINK) {
+		if (__format->code != MEDIA_BUS_FMT_RBG888_1X24) {
+			dev_dbg(xg->xvip.dev,
+				"Unsupported sink media bus code format");
+			__format->code = MEDIA_BUS_FMT_RBG888_1X24;
+		}
+	}
+	__format->width = clamp_t(unsigned int, fmt->format.width,
+				  XGAMMA_MIN_WIDTH, xg->max_width);
+	__format->height = clamp_t(unsigned int, fmt->format.height,
+				   XGAMMA_MIN_HEIGHT, xg->max_height);
+
+	fmt->format = *__format;
+	/* Propagate to Source Pad */
+	__format = __xg_get_pad_format(xg, cfg, XVIP_PAD_SOURCE, fmt->which);
+	if (!__format)
+		return -EINVAL;
+
+	*__format = fmt->format;
+	return 0;
+}
+
+static int xg_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+	struct xgamma_dev *xg = to_xg(subdev);
+	struct v4l2_mbus_framefmt *format;
+
+	format = v4l2_subdev_get_try_format(subdev, fh->pad, XVIP_PAD_SINK);
+	*format = xg->default_formats[XVIP_PAD_SINK];
+
+	format = v4l2_subdev_get_try_format(subdev, fh->pad, XVIP_PAD_SOURCE);
+	*format = xg->default_formats[XVIP_PAD_SOURCE];
+	return 0;
+}
+
+static int xg_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+	return 0;
+}
+
+static const struct v4l2_subdev_internal_ops xg_internal_ops = {
+	.open = xg_open,
+	.close = xg_close,
+};
+
+static const struct v4l2_subdev_pad_ops xg_pad_ops = {
+	.enum_mbus_code = xvip_enum_mbus_code,
+	.enum_frame_size = xvip_enum_frame_size,
+	.get_fmt = xg_get_format,
+	.set_fmt = xg_set_format,
+};
+
+static const struct v4l2_subdev_ops xg_ops = {
+	.video = &xg_video_ops,
+	.pad = &xg_pad_ops,
+};
+
+static int
+select_gamma(s32 value, const u16 **coeff, const u16 **xgamma_curves)
+{
+	if (!coeff)
+		return -EINVAL;
+	if (value <= 0 || value > GAMMA_CURVE_LENGTH)
+		return -EINVAL;
+
+	*coeff = *(xgamma_curves + value - 1);
+	return 0;
+}
+
+static int xg_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	int rval;
+	struct xgamma_dev *xg =
+		container_of(ctrl->handler,
+			     struct xgamma_dev, ctrl_handler);
+	dev_dbg(xg->xvip.dev, "%s called", __func__);
+	switch (ctrl->id) {
+	case V4L2_CID_XILINX_GAMMA_CORR_RED_GAMMA:
+		rval = select_gamma(ctrl->val, &xg->red_lut, xg->gamma_table);
+		if (rval < 0) {
+			dev_err(xg->xvip.dev, "Invalid Red Gamma");
+			return rval;
+		}
+		dev_dbg(xg->xvip.dev, "%s: Setting Red Gamma to %d.%d",
+			__func__, ctrl->val / 10, ctrl->val % 10);
+		xg_set_lut_entries(xg, xg->red_lut, XGAMMA_GAMMA_LUT_0_BASE);
+		break;
+	case V4L2_CID_XILINX_GAMMA_CORR_BLUE_GAMMA:
+		rval = select_gamma(ctrl->val, &xg->blue_lut, xg->gamma_table);
+		if (rval < 0) {
+			dev_err(xg->xvip.dev, "Invalid Blue Gamma");
+			return rval;
+		}
+		dev_dbg(xg->xvip.dev, "%s: Setting Blue Gamma to %d.%d",
+			__func__, ctrl->val / 10, ctrl->val % 10);
+		xg_set_lut_entries(xg, xg->blue_lut, XGAMMA_GAMMA_LUT_1_BASE);
+		break;
+	case V4L2_CID_XILINX_GAMMA_CORR_GREEN_GAMMA:
+		rval = select_gamma(ctrl->val, &xg->green_lut, xg->gamma_table);
+		if (rval < 0) {
+			dev_err(xg->xvip.dev, "Invalid Green Gamma");
+			return -EINVAL;
+		}
+		dev_dbg(xg->xvip.dev, "%s: Setting Green Gamma to %d.%d",
+			__func__, ctrl->val / 10, ctrl->val % 10);
+		xg_set_lut_entries(xg, xg->green_lut, XGAMMA_GAMMA_LUT_2_BASE);
+		break;
+	}
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops xg_ctrl_ops = {
+	.s_ctrl = xg_s_ctrl,
+};
+
+static struct v4l2_ctrl_config xg_ctrls[] = {
+	/* Red Gamma */
+	{
+		.ops = &xg_ctrl_ops,
+		.id = V4L2_CID_XILINX_GAMMA_CORR_RED_GAMMA,
+		.name = "Red Gamma Correction|1->0.1|10->1.0",
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.min = 1,
+		.max = 40,
+		.step = 1,
+		.def = 10,
+		.flags = V4L2_CTRL_FLAG_SLIDER,
+	},
+	/* Blue Gamma */
+	{
+		.ops = &xg_ctrl_ops,
+		.id = V4L2_CID_XILINX_GAMMA_CORR_BLUE_GAMMA,
+		.name = "Blue Gamma Correction|1->0.1|10->1.0",
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.min = 1,
+		.max = 40,
+		.step = 1,
+		.def = 10,
+		.flags = V4L2_CTRL_FLAG_SLIDER,
+	},
+	/* Green Gamma */
+	{
+		.ops = &xg_ctrl_ops,
+		.id = V4L2_CID_XILINX_GAMMA_CORR_GREEN_GAMMA,
+		.name = "Green Gamma Correction|1->0.1|10->1.0)",
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.min = 1,
+		.max = 40,
+		.step = 1,
+		.def = 10,
+		.flags = V4L2_CTRL_FLAG_SLIDER,
+	},
+};
+
+static const struct media_entity_operations xg_media_ops = {
+	.link_validate = v4l2_subdev_link_validate,
+};
+
+static int xg_parse_of(struct xgamma_dev *xg)
+{
+	struct device *dev = xg->xvip.dev;
+	struct device_node *node = dev->of_node;
+	struct device_node *ports;
+	struct device_node *port;
+	u32 port_id = 0;
+	int rval;
+
+	rval = of_property_read_u32(node, "xlnx,max-height", &xg->max_height);
+	if (rval < 0) {
+		dev_err(dev, "xlnx,max-height is missing!");
+		return -EINVAL;
+	} else if (xg->max_height > XGAMMA_MAX_HEIGHT ||
+		   xg->max_height < XGAMMA_MIN_HEIGHT) {
+		dev_err(dev, "Invalid height in dt");
+		return -EINVAL;
+	}
+
+	rval = of_property_read_u32(node, "xlnx,max-width", &xg->max_width);
+	if (rval < 0) {
+		dev_err(dev, "xlnx,max-width is missing!");
+		return -EINVAL;
+	} else if (xg->max_width > XGAMMA_MAX_WIDTH ||
+		   xg->max_width < XGAMMA_MIN_WIDTH) {
+		dev_err(dev, "Invalid width in dt");
+		return -EINVAL;
+	}
+
+	ports = of_get_child_by_name(node, "ports");
+	if (!ports)
+		ports = node;
+
+	/* Get the format description for each pad */
+	for_each_child_of_node(ports, port) {
+		if (port->name && (of_node_cmp(port->name, "port") == 0)) {
+			rval = of_property_read_u32(port, "reg", &port_id);
+			if (rval < 0) {
+				dev_err(dev, "No reg in DT");
+				return rval;
+			}
+			if (port_id != 0 && port_id != 1) {
+				dev_err(dev, "Invalid reg in DT");
+				return -EINVAL;
+			}
+
+			rval = of_property_read_u32(port, "xlnx,video-width",
+						    &xg->color_depth);
+			if (rval < 0) {
+				dev_err(dev, "Missing xlnx-video-width in DT");
+				return rval;
+			}
+			switch (xg->color_depth) {
+			case GAMMA_BPC_8:
+				xg->gamma_table = xgamma8_curves;
+				break;
+			case GAMMA_BPC_10:
+				xg->gamma_table = xgamma10_curves;
+				break;
+			default:
+				dev_err(dev, "Unsupported color depth %d",
+					xg->color_depth);
+				return -EINVAL;
+			}
+		}
+	}
+
+	xg->rst_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(xg->rst_gpio)) {
+		if (PTR_ERR(xg->rst_gpio) != -EPROBE_DEFER)
+			dev_err(dev, "Reset GPIO not setup in DT");
+		return PTR_ERR(xg->rst_gpio);
+	}
+	return 0;
+}
+
+static int xg_probe(struct platform_device *pdev)
+{
+	struct xgamma_dev *xg;
+	struct v4l2_subdev *subdev;
+	struct v4l2_mbus_framefmt *def_fmt;
+	int rval, itr;
+
+	dev_dbg(&pdev->dev, "Gamma LUT Probe Started");
+	xg = devm_kzalloc(&pdev->dev, sizeof(*xg), GFP_KERNEL);
+	if (!xg)
+		return -ENOMEM;
+	xg->xvip.dev = &pdev->dev;
+	rval = xg_parse_of(xg);
+	if (rval < 0)
+		return rval;
+	rval = xvip_init_resources(&xg->xvip);
+	if (rval)
+		return -EIO;
+
+	dev_dbg(xg->xvip.dev, "Reset Xilinx Video Gamma Corrrection");
+	gpiod_set_value_cansleep(xg->rst_gpio, XGAMMA_RESET_DEASSERT);
+
+	/* Init V4L2 subdev */
+	subdev = &xg->xvip.subdev;
+	v4l2_subdev_init(subdev, &xg_ops);
+	subdev->dev = &pdev->dev;
+	subdev->internal_ops = &xg_internal_ops;
+	strlcpy(subdev->name, dev_name(&pdev->dev), sizeof(subdev->name));
+	subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	/* Default Formats Initialization */
+	def_fmt = &xg->default_formats[XVIP_PAD_SINK];
+	/* GAMMA LUT IP only to be supported for RGB */
+	def_fmt->code = MEDIA_BUS_FMT_RBG888_1X24;
+	def_fmt->field = V4L2_FIELD_NONE;
+	def_fmt->colorspace = V4L2_COLORSPACE_SRGB;
+	def_fmt->width = XGAMMA_DEF_WIDTH;
+	def_fmt->height = XGAMMA_DEF_HEIGHT;
+	xg->formats[XVIP_PAD_SINK] = *def_fmt;
+
+	def_fmt = &xg->default_formats[XVIP_PAD_SOURCE];
+	*def_fmt = xg->default_formats[XVIP_PAD_SINK];
+	xg->formats[XVIP_PAD_SOURCE] = *def_fmt;
+
+	xg->pads[XVIP_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+	xg->pads[XVIP_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+
+	/* Init Media Entity */
+	subdev->entity.ops = &xg_media_ops;
+	rval = media_entity_pads_init(&subdev->entity, 2, xg->pads);
+	if (rval < 0)
+		goto media_error;
+
+	/* V4L2 Controls */
+	v4l2_ctrl_handler_init(&xg->ctrl_handler, ARRAY_SIZE(xg_ctrls));
+	for (itr = 0; itr < ARRAY_SIZE(xg_ctrls); itr++) {
+		v4l2_ctrl_new_custom(&xg->ctrl_handler,
+				     &xg_ctrls[itr], NULL);
+	}
+	if (xg->ctrl_handler.error) {
+		dev_err(&pdev->dev, "Failed to add V4L2 controls");
+		rval = xg->ctrl_handler.error;
+		goto ctrl_error;
+	}
+	subdev->ctrl_handler = &xg->ctrl_handler;
+	rval = v4l2_ctrl_handler_setup(&xg->ctrl_handler);
+	if (rval < 0) {
+		dev_err(&pdev->dev, "Failed to setup control handler");
+		goto  ctrl_error;
+	}
+
+	platform_set_drvdata(pdev, xg);
+	rval = v4l2_async_register_subdev(subdev);
+	if (rval < 0) {
+		dev_err(&pdev->dev, "failed to register subdev");
+		goto v4l2_subdev_error;
+	}
+	dev_info(&pdev->dev,
+		 "Xilinx %d-bit Video Gamma Correction LUT registered",
+		 xg->color_depth);
+	return 0;
+ctrl_error:
+	v4l2_ctrl_handler_free(&xg->ctrl_handler);
+v4l2_subdev_error:
+	media_entity_cleanup(&subdev->entity);
+media_error:
+	xvip_cleanup_resources(&xg->xvip);
+	return rval;
+}
+
+static int xg_remove(struct platform_device *pdev)
+{
+	struct xgamma_dev *xg = platform_get_drvdata(pdev);
+	struct v4l2_subdev *subdev = &xg->xvip.subdev;
+
+	v4l2_async_unregister_subdev(subdev);
+	/* Add entry to cleanup v4l2 control handle */
+	media_entity_cleanup(&subdev->entity);
+	xvip_cleanup_resources(&xg->xvip);
+	return 0;
+}
+
+static const struct of_device_id xg_of_id_table[] = {
+	{.compatible = "xlnx,v-gamma-lut"},
+	{ }
+};
+MODULE_DEVICE_TABLE(of, xg_of_id_table);
+
+static struct platform_driver xg_driver = {
+	.driver = {
+		.name = "xilinx-gamma-lut",
+		.of_match_table = xg_of_id_table,
+	},
+	.probe = xg_probe,
+	.remove = xg_remove,
+};
+
+module_platform_driver(xg_driver);
+MODULE_DESCRIPTION("Xilinx Video Gamma Correction LUT Driver");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/xilinx-hls-common.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/xilinx-hls-common.h
@@ -0,0 +1,36 @@
+/*
+ * Xilinx HLS common header
+ *
+ * Copyright (C) 2013-2015 Xilinx, Inc.
+ *
+ * Contacts: Radhey Shyam Pandey <radheys@xilinx.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __XILINX_HLS_COMMON_H__
+#define __XILINX_HLS_COMMON_H__
+
+#include <linux/bitops.h>
+
+#define XHLS_DEF_WIDTH                          1920
+#define XHLS_DEF_HEIGHT                         1080
+
+#define XHLS_REG_CTRL_DONE                      BIT(1)
+#define XHLS_REG_CTRL_IDLE                      BIT(2)
+#define XHLS_REG_CTRL_READY                     BIT(3)
+#define XHLS_REG_CTRL_AUTO_RESTART              BIT(7)
+#define XHLS_REG_GIE                            0x04
+#define XHLS_REG_GIE_GIE                        BIT(0)
+#define XHLS_REG_IER                            0x08
+#define XHLS_REG_IER_DONE                       BIT(0)
+#define XHLS_REG_IER_READY                      BIT(1)
+#define XHLS_REG_ISR                            0x0c
+#define XHLS_REG_ISR_DONE                       BIT(0)
+#define XHLS_REG_ISR_READY                      BIT(1)
+#define XHLS_REG_ROWS                           0x10
+#define XHLS_REG_COLS                           0x18
+
+#endif /* __XILINX_HLS_COMMON_H__ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/xilinx-hls.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/xilinx-hls.c
@@ -0,0 +1,505 @@
+/*
+ * Xilinx HLS Core
+ *
+ * Copyright (C) 2013-2015 Ideas on Board
+ * Copyright (C) 2013-2015 Xilinx, Inc.
+ *
+ * Contacts: Hyun Kwon <hyun.kwon@xilinx.com>
+ *           Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/xilinx-hls.h>
+#include <linux/xilinx-v4l2-controls.h>
+
+#include <media/v4l2-async.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-subdev.h>
+
+#include "xilinx-hls-common.h"
+#include "xilinx-vip.h"
+
+/**
+ * struct xhls_device - Xilinx HLS Core device structure
+ * @xvip: Xilinx Video IP device
+ * @pads: media pads
+ * @compatible: first DT compatible string for the device
+ * @formats: active V4L2 media bus formats at the sink and source pads
+ * @default_formats: default V4L2 media bus formats
+ * @vip_formats: format information corresponding to the pads active formats
+ * @model: additional description of IP implementation if available
+ * @ctrl_handler: control handler
+ * @user_mem: user portion of the register space
+ * @user_mem_size: size of the user portion of the register space
+ */
+struct xhls_device {
+	struct xvip_device xvip;
+	struct media_pad pads[2];
+
+	const char *compatible;
+
+	struct v4l2_mbus_framefmt formats[2];
+	struct v4l2_mbus_framefmt default_formats[2];
+	const struct xvip_video_format *vip_formats[2];
+
+	struct v4l2_ctrl_handler ctrl_handler;
+	struct v4l2_ctrl *model;
+
+	void __iomem *user_mem;
+	size_t user_mem_size;
+};
+
+static inline struct xhls_device *to_hls(struct v4l2_subdev *subdev)
+{
+	return container_of(subdev, struct xhls_device, xvip.subdev);
+}
+
+/* -----------------------------------------------------------------------------
+ * Controls
+ */
+
+static const struct v4l2_ctrl_config xhls_model_ctrl = {
+	.id	= V4L2_CID_XILINX_HLS_MODEL,
+	.name	= "HLS Model",
+	.type	= V4L2_CTRL_TYPE_STRING,
+	.step	= 1,
+	.flags	= V4L2_CTRL_FLAG_READ_ONLY,
+};
+
+static int xhls_create_controls(struct xhls_device *xhls)
+{
+	struct v4l2_ctrl_config model = xhls_model_ctrl;
+	struct v4l2_ctrl *ctrl;
+	int ret;
+
+	model.max = strlen(xhls->compatible);
+	model.min = model.max;
+
+	ret = v4l2_ctrl_handler_init(&xhls->ctrl_handler, 1);
+	if (ret) {
+		dev_err(xhls->xvip.dev,
+			"failed to initializing controls (%d)\n", ret);
+		return ret;
+	}
+
+	ctrl = v4l2_ctrl_new_custom(&xhls->ctrl_handler, &model, NULL);
+
+	if (xhls->ctrl_handler.error || !ctrl) {
+		dev_err(xhls->xvip.dev, "failed to add controls\n");
+		v4l2_ctrl_handler_free(&xhls->ctrl_handler);
+		return xhls->ctrl_handler.error;
+	}
+
+	v4l2_ctrl_s_ctrl_string(ctrl, xhls->compatible);
+
+	xhls->xvip.subdev.ctrl_handler = &xhls->ctrl_handler;
+
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 Subdevice Core Operations
+ */
+
+static int xhls_user_read(struct xhls_device *xhls,
+			  struct xilinx_axi_hls_registers *regs)
+{
+	unsigned int i;
+	u32 offset;
+	u32 value;
+
+	if (regs->num_regs >= xhls->user_mem_size / 4)
+		return -EINVAL;
+
+	for (i = 0; i < regs->num_regs; ++i) {
+		if (copy_from_user(&offset, &regs->regs[i].offset,
+				   sizeof(offset)))
+			return -EFAULT;
+
+		if (offset >= xhls->user_mem_size || offset & 3)
+			return -EINVAL;
+
+		value = ioread32(xhls->user_mem + offset);
+
+		if (copy_to_user(&regs->regs[i].value, &value, sizeof(value)))
+			return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int xhls_user_write(struct xhls_device *xhls,
+			   struct xilinx_axi_hls_registers *regs)
+{
+	struct xilinx_axi_hls_register reg;
+	unsigned int i;
+
+	if (regs->num_regs >= xhls->user_mem_size / 4)
+		return -EINVAL;
+
+	for (i = 0; i < regs->num_regs; ++i) {
+		if (copy_from_user(&reg, &regs->regs[i], sizeof(reg)))
+			return -EFAULT;
+
+		if (reg.offset >= xhls->user_mem_size || reg.offset & 3)
+			return -EINVAL;
+
+		iowrite32(reg.value, xhls->user_mem + reg.offset);
+	}
+
+	return 0;
+}
+
+static long xhls_ioctl(struct v4l2_subdev *subdev, unsigned int cmd, void *arg)
+{
+	struct xhls_device *xhls = to_hls(subdev);
+
+	switch (cmd) {
+	case XILINX_AXI_HLS_READ:
+		return xhls_user_read(xhls, arg);
+	case XILINX_AXI_HLS_WRITE:
+		return xhls_user_write(xhls, arg);
+	}
+
+	return -ENOTTY;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 Subdevice Video Operations
+ */
+
+static int xhls_s_stream(struct v4l2_subdev *subdev, int enable)
+{
+	struct xhls_device *xhls = to_hls(subdev);
+	struct v4l2_mbus_framefmt *format = &xhls->formats[XVIP_PAD_SINK];
+
+	if (!enable) {
+		xvip_write(&xhls->xvip, XVIP_CTRL_CONTROL, 0);
+		return 0;
+	}
+
+	xvip_write(&xhls->xvip, XHLS_REG_COLS, format->width);
+	xvip_write(&xhls->xvip, XHLS_REG_ROWS, format->height);
+
+	xvip_write(&xhls->xvip, XVIP_CTRL_CONTROL,
+		   XHLS_REG_CTRL_AUTO_RESTART | XVIP_CTRL_CONTROL_SW_ENABLE);
+
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 Subdevice Pad Operations
+ */
+
+static struct v4l2_mbus_framefmt *
+__xhls_get_pad_format(struct xhls_device *xhls,
+		      struct v4l2_subdev_pad_config *cfg,
+		      unsigned int pad, u32 which)
+{
+	struct v4l2_mbus_framefmt *format;
+
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		format = v4l2_subdev_get_try_format(&xhls->xvip.subdev,
+						    cfg, pad);
+		break;
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		format = &xhls->formats[pad];
+		break;
+	default:
+		format = NULL;
+		break;
+	}
+
+	return format;
+}
+
+static int xhls_get_format(struct v4l2_subdev *subdev,
+			   struct v4l2_subdev_pad_config *cfg,
+			   struct v4l2_subdev_format *fmt)
+{
+	struct xhls_device *xhls = to_hls(subdev);
+	struct v4l2_mbus_framefmt *format;
+
+	format = __xhls_get_pad_format(xhls, cfg, fmt->pad, fmt->which);
+	if (!format)
+		return -EINVAL;
+
+	fmt->format = *format;
+
+	return 0;
+}
+
+static int xhls_set_format(struct v4l2_subdev *subdev,
+			   struct v4l2_subdev_pad_config *cfg,
+			   struct v4l2_subdev_format *fmt)
+{
+	struct xhls_device *xhls = to_hls(subdev);
+	struct v4l2_mbus_framefmt *format;
+
+	format = __xhls_get_pad_format(xhls, cfg, fmt->pad, fmt->which);
+	if (!format)
+		return -EINVAL;
+
+	if (fmt->pad == XVIP_PAD_SOURCE) {
+		fmt->format = *format;
+		return 0;
+	}
+
+	xvip_set_format_size(format, fmt);
+
+	fmt->format = *format;
+
+	/* Propagate the format to the source pad. */
+	format = __xhls_get_pad_format(xhls, cfg, XVIP_PAD_SOURCE,
+					 fmt->which);
+	if (!format)
+		return -EINVAL;
+
+	xvip_set_format_size(format, fmt);
+
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 Subdevice Operations
+ */
+
+static int xhls_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+	struct xhls_device *xhls = to_hls(subdev);
+	struct v4l2_mbus_framefmt *format;
+
+	/* Initialize with default formats */
+	format = v4l2_subdev_get_try_format(subdev, fh->pad, XVIP_PAD_SINK);
+	*format = xhls->default_formats[XVIP_PAD_SINK];
+
+	format = v4l2_subdev_get_try_format(subdev, fh->pad, XVIP_PAD_SOURCE);
+	*format = xhls->default_formats[XVIP_PAD_SOURCE];
+
+	return 0;
+}
+
+static int xhls_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+	return 0;
+}
+
+static struct v4l2_subdev_core_ops xhls_core_ops = {
+	.ioctl = xhls_ioctl,
+};
+
+static struct v4l2_subdev_video_ops xhls_video_ops = {
+	.s_stream = xhls_s_stream,
+};
+
+static struct v4l2_subdev_pad_ops xhls_pad_ops = {
+	.enum_mbus_code = xvip_enum_mbus_code,
+	.enum_frame_size = xvip_enum_frame_size,
+	.get_fmt = xhls_get_format,
+	.set_fmt = xhls_set_format,
+};
+
+static struct v4l2_subdev_ops xhls_ops = {
+	.core   = &xhls_core_ops,
+	.video  = &xhls_video_ops,
+	.pad    = &xhls_pad_ops,
+};
+
+static const struct v4l2_subdev_internal_ops xhls_internal_ops = {
+	.open = xhls_open,
+	.close = xhls_close,
+};
+
+/* -----------------------------------------------------------------------------
+ * Media Operations
+ */
+
+static const struct media_entity_operations xhls_media_ops = {
+	.link_validate = v4l2_subdev_link_validate,
+};
+
+/* -----------------------------------------------------------------------------
+ * Platform Device Driver
+ */
+
+static void xhls_init_formats(struct xhls_device *xhls)
+{
+	struct v4l2_mbus_framefmt *format;
+
+	/* Initialize default and active formats */
+	format = &xhls->default_formats[XVIP_PAD_SINK];
+	format->code = xhls->vip_formats[XVIP_PAD_SINK]->code;
+	format->field = V4L2_FIELD_NONE;
+	format->colorspace = V4L2_COLORSPACE_SRGB;
+
+	format->width = xvip_read(&xhls->xvip, XHLS_REG_COLS);
+	format->height = xvip_read(&xhls->xvip, XHLS_REG_ROWS);
+
+	xhls->formats[XVIP_PAD_SINK] = *format;
+
+	format = &xhls->default_formats[XVIP_PAD_SOURCE];
+	*format = xhls->default_formats[XVIP_PAD_SINK];
+	format->code = xhls->vip_formats[XVIP_PAD_SOURCE]->code;
+
+	xhls->formats[XVIP_PAD_SOURCE] = *format;
+}
+
+static int xhls_parse_of(struct xhls_device *xhls)
+{
+	struct device *dev = xhls->xvip.dev;
+	struct device_node *node = xhls->xvip.dev->of_node;
+	struct device_node *ports;
+	struct device_node *port;
+	u32 port_id;
+	int ret;
+
+	ret = of_property_read_string(node, "compatible", &xhls->compatible);
+	if (ret < 0)
+		return -EINVAL;
+
+	ports = of_get_child_by_name(node, "ports");
+	if (ports == NULL)
+		ports = node;
+
+	/* Get the format description for each pad */
+	for_each_child_of_node(ports, port) {
+		if (port->name && (of_node_cmp(port->name, "port") == 0)) {
+			const struct xvip_video_format *vip_format;
+
+			vip_format = xvip_of_get_format(port);
+			if (IS_ERR(vip_format)) {
+				dev_err(dev, "invalid format in DT");
+				return PTR_ERR(vip_format);
+			}
+
+			ret = of_property_read_u32(port, "reg", &port_id);
+			if (ret < 0) {
+				dev_err(dev, "no reg in DT");
+				return ret;
+			}
+
+			if (port_id != 0 && port_id != 1) {
+				dev_err(dev, "invalid reg in DT");
+				return -EINVAL;
+			}
+
+			xhls->vip_formats[port_id] = vip_format;
+		}
+	}
+
+	return 0;
+}
+
+static int xhls_probe(struct platform_device *pdev)
+{
+	struct v4l2_subdev *subdev;
+	struct xhls_device *xhls;
+	struct resource *mem;
+	int ret;
+
+	xhls = devm_kzalloc(&pdev->dev, sizeof(*xhls), GFP_KERNEL);
+	if (!xhls)
+		return -ENOMEM;
+
+	xhls->xvip.dev = &pdev->dev;
+
+	ret = xhls_parse_of(xhls);
+	if (ret < 0)
+		return ret;
+
+	ret = xvip_init_resources(&xhls->xvip);
+	if (ret < 0)
+		return ret;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	xhls->user_mem = devm_ioremap_resource(&pdev->dev, mem);
+	if (IS_ERR(xhls->user_mem))
+		return PTR_ERR(xhls->user_mem);
+	xhls->user_mem_size = resource_size(mem);
+
+	/* Reset and initialize the core */
+	xvip_reset(&xhls->xvip);
+
+	/* Initialize V4L2 subdevice and media entity */
+	subdev = &xhls->xvip.subdev;
+	v4l2_subdev_init(subdev, &xhls_ops);
+	subdev->dev = &pdev->dev;
+	subdev->internal_ops = &xhls_internal_ops;
+	strlcpy(subdev->name, dev_name(&pdev->dev), sizeof(subdev->name));
+	v4l2_set_subdevdata(subdev, xhls);
+	subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	xhls_init_formats(xhls);
+
+	xhls->pads[XVIP_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+	xhls->pads[XVIP_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+	subdev->entity.ops = &xhls_media_ops;
+	ret = media_entity_pads_init(&subdev->entity, 2, xhls->pads);
+	if (ret < 0)
+		goto error;
+
+	ret = xhls_create_controls(xhls);
+	if (ret < 0)
+		goto error;
+
+	platform_set_drvdata(pdev, xhls);
+
+	ret = v4l2_async_register_subdev(subdev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to register subdev\n");
+		goto error;
+	}
+
+	dev_info(xhls->xvip.dev, "device %s found\n", xhls->compatible);
+
+	return 0;
+
+error:
+	v4l2_ctrl_handler_free(&xhls->ctrl_handler);
+	media_entity_cleanup(&subdev->entity);
+	xvip_cleanup_resources(&xhls->xvip);
+	return ret;
+}
+
+static int xhls_remove(struct platform_device *pdev)
+{
+	struct xhls_device *xhls = platform_get_drvdata(pdev);
+	struct v4l2_subdev *subdev = &xhls->xvip.subdev;
+
+	v4l2_async_unregister_subdev(subdev);
+	v4l2_ctrl_handler_free(&xhls->ctrl_handler);
+	media_entity_cleanup(&subdev->entity);
+
+	xvip_cleanup_resources(&xhls->xvip);
+
+	return 0;
+}
+
+static const struct of_device_id xhls_of_id_table[] = {
+	{ .compatible = "xlnx,v-hls" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, xhls_of_id_table);
+
+static struct platform_driver xhls_driver = {
+	.driver = {
+		.name = "xilinx-hls",
+		.of_match_table = xhls_of_id_table,
+	},
+	.probe = xhls_probe,
+	.remove = xhls_remove,
+};
+
+module_platform_driver(xhls_driver);
+
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_DESCRIPTION("Xilinx HLS Core Driver");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/xilinx-m2m.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/xilinx-m2m.c
@@ -0,0 +1,2216 @@
+//SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx V4L2 mem2mem driver
+ *
+ * Copyright (C) 2017-2018 Xilinx, Inc.
+ *
+ * Author: Satish Kumar Nagireddy <satish.nagireddy.nagireddy@xilinx.com>
+ */
+
+#include <drm/drm_fourcc.h>
+#include <linux/delay.h>
+#include <linux/dma/xilinx_frmbuf.h>
+#include <linux/lcm.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_graph.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <media/v4l2-async.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "xilinx-vip.h"
+
+#define XVIP_M2M_NAME		"xilinx-mem2mem"
+#define XVIP_M2M_DEFAULT_FMT	V4L2_PIX_FMT_RGB24
+
+/* Minimum and maximum widths are expressed in bytes */
+#define XVIP_M2M_MIN_WIDTH	1U
+#define XVIP_M2M_MAX_WIDTH	65535U
+#define XVIP_M2M_MIN_HEIGHT	1U
+#define XVIP_M2M_MAX_HEIGHT	8191U
+
+#define XVIP_M2M_DEF_WIDTH	1920
+#define XVIP_M2M_DEF_HEIGHT	1080
+
+#define XVIP_M2M_PAD_SINK	1
+#define XVIP_M2M_PAD_SOURCE	0
+
+/**
+ * struct xvip_graph_entity - Entity in the video graph
+ * @list: list entry in a graph entities list
+ * @node: the entity's DT node
+ * @entity: media entity, from the corresponding V4L2 subdev
+ * @asd: subdev asynchronous registration information
+ * @subdev: V4L2 subdev
+ * @streaming: status of the V4L2 subdev if streaming or not
+ */
+struct xvip_graph_entity {
+	struct list_head list;
+	struct device_node *node;
+	struct media_entity *entity;
+
+	struct v4l2_async_subdev asd;
+	struct v4l2_subdev *subdev;
+	bool streaming;
+};
+
+/**
+ * struct xvip_pipeline - Xilinx Video IP pipeline structure
+ * @pipe: media pipeline
+ * @lock: protects the pipeline @stream_count
+ * @use_count: number of DMA engines using the pipeline
+ * @stream_count: number of DMA engines currently streaming
+ * @num_dmas: number of DMA engines in the pipeline
+ * @xdev: Composite device the pipe belongs to
+ */
+struct xvip_pipeline {
+	struct media_pipeline pipe;
+
+	/* protects the pipeline @stream_count */
+	struct mutex lock;
+	unsigned int use_count;
+	unsigned int stream_count;
+
+	unsigned int num_dmas;
+	struct xvip_m2m_dev *xdev;
+};
+
+struct xventity_list {
+	struct list_head list;
+	struct media_entity *entity;
+};
+
+/**
+ * struct xvip_m2m_dev - Xilinx Video mem2mem device structure
+ * @v4l2_dev: V4L2 device
+ * @dev: (OF) device
+ * @media_dev: media device
+ * @notifier: V4L2 asynchronous subdevs notifier
+ * @entities: entities in the graph as a list of xvip_graph_entity
+ * @num_subdevs: number of subdevs in the pipeline
+ * @lock: This is to protect mem2mem context structure data
+ * @queued_lock: This is to protect video buffer information
+ * @dma: Video DMA channels
+ * @m2m_dev: V4L2 mem2mem device structure
+ * @v4l2_caps: V4L2 capabilities of the whole device
+ */
+struct xvip_m2m_dev {
+	struct v4l2_device v4l2_dev;
+	struct device *dev;
+
+	struct media_device media_dev;
+	struct v4l2_async_notifier notifier;
+	struct list_head entities;
+	unsigned int num_subdevs;
+
+	/* Protects to m2m context data */
+	struct mutex lock;
+
+	/* Protects vb2_v4l2_buffer data */
+	spinlock_t queued_lock;
+	struct xvip_m2m_dma *dma;
+	struct v4l2_m2m_dev *m2m_dev;
+	u32 v4l2_caps;
+};
+
+static inline struct xvip_pipeline *to_xvip_pipeline(struct media_entity *e)
+{
+	return container_of(e->pipe, struct xvip_pipeline, pipe);
+}
+
+/**
+ * struct xvip_m2m_dma - Video DMA channel
+ * @video: V4L2 video device associated with the DMA channel
+ * @xdev: composite mem2mem device the DMA channels belongs to
+ * @chan_tx: DMA engine channel for MEM2DEV transfer
+ * @chan_rx: DMA engine channel for DEV2MEM transfer
+ * @outfmt: active V4L2 OUTPUT port pixel format
+ * @capfmt: active V4L2 CAPTURE port pixel format
+ * @r: crop rectangle parameters
+ * @outinfo: format information corresponding to the active @outfmt
+ * @capinfo: format information corresponding to the active @capfmt
+ * @align: transfer alignment required by the DMA channel (in bytes)
+ * @crop: boolean flag to indicate if crop is requested
+ * @pads: media pads for the video M2M device entity
+ * @pipe: pipeline belonging to the DMA channel
+ */
+struct xvip_m2m_dma {
+	struct video_device video;
+	struct xvip_m2m_dev *xdev;
+	struct dma_chan *chan_tx;
+	struct dma_chan *chan_rx;
+	struct v4l2_format outfmt;
+	struct v4l2_format capfmt;
+	struct v4l2_rect r;
+	const struct xvip_video_format *outinfo;
+	const struct xvip_video_format *capinfo;
+	u32 align;
+	bool crop;
+
+	struct media_pad pads[2];
+	struct xvip_pipeline pipe;
+};
+
+/**
+ * struct xvip_m2m_ctx - VIPP mem2mem context
+ * @fh: V4L2 file handler
+ * @xdev: composite mem2mem device the DMA channels belongs to
+ * @xt: dma interleaved template for dma configuration
+ * @sgl: data chunk structure for dma_interleaved_template
+ */
+struct xvip_m2m_ctx {
+	struct v4l2_fh fh;
+	struct xvip_m2m_dev *xdev;
+	struct dma_interleaved_template xt;
+	struct data_chunk sgl[1];
+};
+
+static inline struct xvip_m2m_ctx *file2ctx(struct file *file)
+{
+	return container_of(file->private_data, struct xvip_m2m_ctx, fh);
+}
+
+static struct v4l2_subdev *
+xvip_dma_remote_subdev(struct media_pad *local, u32 *pad)
+{
+	struct media_pad *remote;
+
+	remote = media_entity_remote_pad(local);
+	if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
+		return NULL;
+
+	if (pad)
+		*pad = remote->index;
+
+	return media_entity_to_v4l2_subdev(remote->entity);
+}
+
+static int xvip_dma_verify_format(struct xvip_m2m_dma *dma)
+{
+	struct v4l2_subdev_format fmt;
+	struct v4l2_subdev *subdev;
+	int ret;
+	int width, height;
+
+	subdev = xvip_dma_remote_subdev(&dma->pads[XVIP_PAD_SOURCE], &fmt.pad);
+	if (!subdev)
+		return -EPIPE;
+
+	fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+	ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
+	if (ret < 0)
+		return ret == -ENOIOCTLCMD ? -EINVAL : ret;
+
+	if (dma->outinfo->code != fmt.format.code)
+		return -EINVAL;
+
+	if (V4L2_TYPE_IS_MULTIPLANAR(dma->outfmt.type)) {
+		width = dma->outfmt.fmt.pix_mp.width;
+		height = dma->outfmt.fmt.pix_mp.height;
+	} else {
+		width = dma->outfmt.fmt.pix.width;
+		height = dma->outfmt.fmt.pix.height;
+	}
+
+	if (width != fmt.format.width || height != fmt.format.height)
+		return -EINVAL;
+
+	return 0;
+}
+
+#define to_xvip_dma(vdev)	container_of(vdev, struct xvip_m2m_dma, video)
+/* -----------------------------------------------------------------------------
+ * Pipeline Stream Management
+ */
+
+/**
+ * xvip_subdev_set_streaming - Find and update streaming status of subdev
+ * @xdev: Composite video device
+ * @subdev: V4L2 sub-device
+ * @enable: enable/disable streaming status
+ *
+ * Walk the xvip graph entities list and find if subdev is present. Returns
+ * streaming status of subdev and update the status as requested
+ *
+ * Return: streaming status (true or false) if successful or warn_on if subdev
+ * is not present and return false
+ */
+static bool xvip_subdev_set_streaming(struct xvip_m2m_dev *xdev,
+				      struct v4l2_subdev *subdev, bool enable)
+{
+	struct xvip_graph_entity *entity;
+
+	list_for_each_entry(entity, &xdev->entities, list)
+		if (entity->node == subdev->dev->of_node) {
+			bool status = entity->streaming;
+
+			entity->streaming = enable;
+			return status;
+		}
+
+	WARN(1, "Should never get here\n");
+	return false;
+}
+
+static int xvip_entity_start_stop(struct xvip_m2m_dev *xdev,
+				  struct media_entity *entity, bool start)
+{
+	struct v4l2_subdev *subdev;
+	bool is_streaming;
+	int ret = 0;
+
+	dev_dbg(xdev->dev, "%s entity %s\n",
+		start ? "Starting" : "Stopping", entity->name);
+	subdev = media_entity_to_v4l2_subdev(entity);
+
+	/* This is to maintain list of stream on/off devices */
+	is_streaming = xvip_subdev_set_streaming(xdev, subdev, start);
+
+	/*
+	 * start or stop the subdev only once in case if they are
+	 * shared between sub-graphs
+	 */
+	if (start && !is_streaming) {
+		/* power-on subdevice */
+		ret = v4l2_subdev_call(subdev, core, s_power, 1);
+		if (ret < 0 && ret != -ENOIOCTLCMD) {
+			dev_err(xdev->dev,
+				"s_power on failed on subdev\n");
+			xvip_subdev_set_streaming(xdev, subdev, 0);
+			return ret;
+		}
+
+		/* stream-on subdevice */
+		ret = v4l2_subdev_call(subdev, video, s_stream, 1);
+		if (ret < 0 && ret != -ENOIOCTLCMD) {
+			dev_err(xdev->dev,
+				"s_stream on failed on subdev\n");
+			v4l2_subdev_call(subdev, core, s_power, 0);
+			xvip_subdev_set_streaming(xdev, subdev, 0);
+		}
+	} else if (!start && is_streaming) {
+		/* stream-off subdevice */
+		ret = v4l2_subdev_call(subdev, video, s_stream, 0);
+		if (ret < 0 && ret != -ENOIOCTLCMD) {
+			dev_err(xdev->dev,
+				"s_stream off failed on subdev\n");
+			xvip_subdev_set_streaming(xdev, subdev, 1);
+		}
+
+		/* power-off subdevice */
+		ret = v4l2_subdev_call(subdev, core, s_power, 0);
+		if (ret < 0 && ret != -ENOIOCTLCMD)
+			dev_err(xdev->dev,
+				"s_power off failed on subdev\n");
+	}
+
+	return ret;
+}
+
+/**
+ * xvip_pipeline_start_stop - Start ot stop streaming on a pipeline
+ * @xdev: Composite video device
+ * @dma: xvip dma
+ * @start: Start (when true) or stop (when false) the pipeline
+ *
+ * Walk the entities chain starting @dma and start or stop all of them
+ *
+ * Return: 0 if successful, or the return value of the failed video::s_stream
+ * operation otherwise.
+ */
+static int xvip_pipeline_start_stop(struct xvip_m2m_dev *xdev,
+				    struct xvip_m2m_dma *dma, bool start)
+{
+	struct media_graph graph;
+	struct media_entity *entity = &dma->video.entity;
+	struct media_device *mdev = entity->graph_obj.mdev;
+	struct xventity_list *temp, *_temp;
+	LIST_HEAD(ent_list);
+	int ret = 0;
+
+	mutex_lock(&mdev->graph_mutex);
+
+	/* Walk the graph to locate the subdev nodes */
+	ret = media_graph_walk_init(&graph, mdev);
+	if (ret)
+		goto error;
+
+	media_graph_walk_start(&graph, entity);
+
+	/* get the list of entities */
+	while ((entity = media_graph_walk_next(&graph))) {
+		struct xventity_list *ele;
+
+		/* We want to stream on/off only subdevs */
+		if (!is_media_entity_v4l2_subdev(entity))
+			continue;
+
+		/* Maintain the pipeline sequence in a list */
+		ele = kzalloc(sizeof(*ele), GFP_KERNEL);
+		if (!ele) {
+			ret = -ENOMEM;
+			goto error;
+		}
+
+		ele->entity = entity;
+		list_add(&ele->list, &ent_list);
+	}
+
+	if (start) {
+		list_for_each_entry_safe(temp, _temp, &ent_list, list) {
+			/* Enable all subdevs from sink to source */
+			ret = xvip_entity_start_stop(xdev, temp->entity, start);
+			if (ret < 0) {
+				dev_err(xdev->dev, "ret = %d for entity %s\n",
+					ret, temp->entity->name);
+				break;
+			}
+		}
+	} else {
+		list_for_each_entry_safe_reverse(temp, _temp, &ent_list, list)
+			/* Enable all subdevs from source to sink */
+			xvip_entity_start_stop(xdev, temp->entity, start);
+	}
+
+	list_for_each_entry_safe(temp, _temp, &ent_list, list) {
+		list_del(&temp->list);
+		kfree(temp);
+	}
+
+error:
+	mutex_unlock(&mdev->graph_mutex);
+	media_graph_walk_cleanup(&graph);
+	return ret;
+}
+
+/**
+ * xvip_pipeline_set_stream - Enable/disable streaming on a pipeline
+ * @pipe: The pipeline
+ * @on: Turn the stream on when true or off when false
+ *
+ * The pipeline is shared between all DMA engines connect at its input and
+ * output. While the stream state of DMA engines can be controlled
+ * independently, pipelines have a shared stream state that enable or disable
+ * all entities in the pipeline. For this reason the pipeline uses a streaming
+ * counter that tracks the number of DMA engines that have requested the stream
+ * to be enabled. This will walk the graph starting from each DMA and enable or
+ * disable the entities in the path.
+ *
+ * When called with the @on argument set to true, this function will increment
+ * the pipeline streaming count. If the streaming count reaches the number of
+ * DMA engines in the pipeline it will enable all entities that belong to the
+ * pipeline.
+ *
+ * Similarly, when called with the @on argument set to false, this function will
+ * decrement the pipeline streaming count and disable all entities in the
+ * pipeline when the streaming count reaches zero.
+ *
+ * Return: 0 if successful, or the return value of the failed video::s_stream
+ * operation otherwise. Stopping the pipeline never fails. The pipeline state is
+ * not updated when the operation fails.
+ */
+static int xvip_pipeline_set_stream(struct xvip_pipeline *pipe, bool on)
+{
+	struct xvip_m2m_dev *xdev;
+	struct xvip_m2m_dma *dma;
+	int ret = 0;
+
+	mutex_lock(&pipe->lock);
+	xdev = pipe->xdev;
+	dma = xdev->dma;
+
+	if (on) {
+		ret = xvip_pipeline_start_stop(xdev, dma, true);
+		if (ret < 0)
+			goto done;
+		pipe->stream_count++;
+	} else {
+		if (--pipe->stream_count == 0)
+			xvip_pipeline_start_stop(xdev, dma, false);
+	}
+
+done:
+	mutex_unlock(&pipe->lock);
+	return ret;
+}
+
+static int xvip_pipeline_validate(struct xvip_pipeline *pipe,
+				  struct xvip_m2m_dma *start)
+{
+	struct media_graph graph;
+	struct media_entity *entity = &start->video.entity;
+	struct media_device *mdev = entity->graph_obj.mdev;
+	unsigned int num_inputs = 0;
+	unsigned int num_outputs = 0;
+	int ret;
+
+	mutex_lock(&mdev->graph_mutex);
+
+	/* Walk the graph to locate the video nodes. */
+	ret = media_graph_walk_init(&graph, mdev);
+	if (ret) {
+		mutex_unlock(&mdev->graph_mutex);
+		return ret;
+	}
+
+	media_graph_walk_start(&graph, entity);
+
+	while ((entity = media_graph_walk_next(&graph))) {
+		if (entity->function != MEDIA_ENT_F_IO_V4L)
+			continue;
+
+		num_outputs++;
+		num_inputs++;
+	}
+
+	mutex_unlock(&mdev->graph_mutex);
+
+	media_graph_walk_cleanup(&graph);
+
+	/* We need at least one DMA to proceed */
+	if (num_outputs == 0 && num_inputs == 0)
+		return -EPIPE;
+
+	pipe->num_dmas = num_inputs + num_outputs;
+	pipe->xdev = start->xdev;
+
+	return 0;
+}
+
+static void __xvip_pipeline_cleanup(struct xvip_pipeline *pipe)
+{
+	pipe->num_dmas = 0;
+}
+
+/**
+ * xvip_pipeline_cleanup - Cleanup the pipeline after streaming
+ * @pipe: the pipeline
+ *
+ * Decrease the pipeline use count and clean it up if we were the last user.
+ */
+static void xvip_pipeline_cleanup(struct xvip_pipeline *pipe)
+{
+	mutex_lock(&pipe->lock);
+
+	/* If we're the last user clean up the pipeline. */
+	if (--pipe->use_count == 0)
+		__xvip_pipeline_cleanup(pipe);
+
+	mutex_unlock(&pipe->lock);
+}
+
+/**
+ * xvip_pipeline_prepare - Prepare the pipeline for streaming
+ * @pipe: the pipeline
+ * @dma: DMA engine at one end of the pipeline
+ *
+ * Validate the pipeline if no user exists yet, otherwise just increase the use
+ * count.
+ *
+ * Return: 0 if successful or -EPIPE if the pipeline is not valid.
+ */
+static int xvip_pipeline_prepare(struct xvip_pipeline *pipe,
+				 struct xvip_m2m_dma *dma)
+{
+	int ret;
+
+	mutex_lock(&pipe->lock);
+
+	/* If we're the first user validate and initialize the pipeline. */
+	if (pipe->use_count == 0) {
+		ret = xvip_pipeline_validate(pipe, dma);
+		if (ret < 0) {
+			__xvip_pipeline_cleanup(pipe);
+			goto done;
+		}
+	}
+
+	pipe->use_count++;
+	ret = 0;
+
+done:
+	mutex_unlock(&pipe->lock);
+	return ret;
+}
+
+static void xvip_m2m_dma_callback_mem2dev(void *data)
+{
+}
+
+static void xvip_m2m_dma_callback(void *data)
+{
+	struct xvip_m2m_ctx *ctx = data;
+	struct xvip_m2m_dev *xdev = ctx->xdev;
+	struct vb2_v4l2_buffer *src_vb, *dst_vb;
+
+	spin_lock(&xdev->queued_lock);
+	src_vb = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+	dst_vb = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+
+	dst_vb->vb2_buf.timestamp = src_vb->vb2_buf.timestamp;
+	dst_vb->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+	dst_vb->flags |=
+		src_vb->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+	dst_vb->timecode = src_vb->timecode;
+
+	v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
+	v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);
+	v4l2_m2m_job_finish(xdev->m2m_dev, ctx->fh.m2m_ctx);
+	spin_unlock(&xdev->queued_lock);
+}
+
+/*
+ * Queue operations
+ */
+
+static int xvip_m2m_queue_setup(struct vb2_queue *vq,
+				u32 *nbuffers, u32 *nplanes,
+				u32 sizes[], struct device *alloc_devs[])
+{
+	struct xvip_m2m_ctx *ctx = vb2_get_drv_priv(vq);
+	struct xvip_m2m_dma *dma = ctx->xdev->dma;
+	struct v4l2_format *f;
+	const struct xvip_video_format *info;
+	u32 i;
+
+	if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		f = &dma->outfmt;
+		info = dma->outinfo;
+	} else {
+		f = &dma->capfmt;
+		info = dma->capinfo;
+	}
+
+	if (*nplanes) {
+		if (*nplanes != f->fmt.pix_mp.num_planes)
+			return -EINVAL;
+
+		for (i = 0; i < *nplanes; i++) {
+			if (sizes[i] < f->fmt.pix_mp.plane_fmt[i].sizeimage)
+				return -EINVAL;
+		}
+	} else {
+		*nplanes = info->buffers;
+		for (i = 0; i < info->buffers; i++)
+			sizes[i] = f->fmt.pix_mp.plane_fmt[i].sizeimage;
+	}
+
+	return 0;
+}
+
+static int xvip_m2m_buf_prepare(struct vb2_buffer *vb)
+{
+	struct xvip_m2m_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct xvip_m2m_dma *dma = ctx->xdev->dma;
+	struct v4l2_format *f;
+	const struct xvip_video_format *info;
+	u32 i;
+
+	if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		f = &dma->outfmt;
+		info = dma->outinfo;
+	} else {
+		f = &dma->capfmt;
+		info = dma->capinfo;
+	}
+
+	for (i = 0; i < info->buffers; i++) {
+		if (vb2_plane_size(vb, i) <
+			f->fmt.pix_mp.plane_fmt[i].sizeimage) {
+			dev_err(ctx->xdev->dev,
+				"insufficient plane size (%u < %u)\n",
+				(u32)vb2_plane_size(vb, i),
+				f->fmt.pix_mp.plane_fmt[i].sizeimage);
+			return -EINVAL;
+		}
+
+		vb2_set_plane_payload(vb, i,
+				      f->fmt.pix_mp.plane_fmt[i].sizeimage);
+	}
+
+	return 0;
+}
+
+static void xvip_m2m_buf_queue(struct vb2_buffer *vb)
+{
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct xvip_m2m_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+
+	v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
+}
+
+static void xvip_m2m_stop_streaming(struct vb2_queue *q)
+{
+	struct xvip_m2m_ctx *ctx = vb2_get_drv_priv(q);
+	struct xvip_m2m_dma *dma = ctx->xdev->dma;
+	struct xvip_pipeline *pipe = to_xvip_pipeline(&dma->video.entity);
+	struct vb2_v4l2_buffer *vbuf;
+
+	dma->crop = false;
+	if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+		dmaengine_terminate_sync(dma->chan_tx);
+	else
+		dmaengine_terminate_sync(dma->chan_rx);
+
+	if (ctx->xdev->num_subdevs) {
+		/* Stop the pipeline. */
+		xvip_pipeline_set_stream(pipe, false);
+
+		/* Cleanup the pipeline and mark it as being stopped. */
+		xvip_pipeline_cleanup(pipe);
+		media_pipeline_stop(&dma->video.entity);
+	}
+
+	for (;;) {
+		if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+			vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+		else
+			vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+
+		if (!vbuf)
+			return;
+
+		spin_lock(&ctx->xdev->queued_lock);
+		v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
+		spin_unlock(&ctx->xdev->queued_lock);
+	}
+}
+
+static int xvip_m2m_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+	struct xvip_m2m_ctx *ctx = vb2_get_drv_priv(q);
+	struct xvip_m2m_dma *dma = ctx->xdev->dma;
+	struct xvip_m2m_dev *xdev = ctx->xdev;
+	struct xvip_pipeline *pipe;
+	int ret;
+
+	if (!xdev->num_subdevs)
+		return 0;
+
+	pipe = dma->video.entity.pipe
+	     ? to_xvip_pipeline(&dma->video.entity) : &dma->pipe;
+
+	ret = media_pipeline_start(&dma->video.entity, &pipe->pipe);
+	if (ret < 0)
+		goto error;
+
+	/* Verify that the configured format matches the output of the
+	 * connected subdev.
+	 */
+	ret = xvip_dma_verify_format(dma);
+	if (ret < 0)
+		goto error_stop;
+
+	ret = xvip_pipeline_prepare(pipe, dma);
+	if (ret < 0)
+		goto error_stop;
+
+	/* Start the pipeline. */
+	ret = xvip_pipeline_set_stream(pipe, true);
+	if (ret < 0)
+		goto error_stop;
+
+	return 0;
+error_stop:
+	media_pipeline_stop(&dma->video.entity);
+
+error:
+	xvip_m2m_stop_streaming(q);
+
+	return ret;
+}
+
+static const struct vb2_ops m2m_vb2_ops = {
+	.queue_setup = xvip_m2m_queue_setup,
+	.buf_prepare = xvip_m2m_buf_prepare,
+	.buf_queue = xvip_m2m_buf_queue,
+	.start_streaming = xvip_m2m_start_streaming,
+	.stop_streaming = xvip_m2m_stop_streaming,
+	.wait_prepare = vb2_ops_wait_prepare,
+	.wait_finish = vb2_ops_wait_finish,
+};
+
+static int xvip_m2m_queue_init(void *priv, struct vb2_queue *src_vq,
+			       struct vb2_queue *dst_vq)
+{
+	struct xvip_m2m_ctx *ctx = priv;
+	int ret;
+
+	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+	src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
+	src_vq->drv_priv = ctx;
+	src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+	src_vq->ops = &m2m_vb2_ops;
+	src_vq->mem_ops = &vb2_dma_contig_memops;
+	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	src_vq->dev = ctx->xdev->v4l2_dev.dev;
+
+	ret = vb2_queue_init(src_vq);
+	if (ret)
+		return ret;
+
+	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+	dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
+	dst_vq->drv_priv = ctx;
+	dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+	dst_vq->ops = &m2m_vb2_ops;
+	dst_vq->mem_ops = &vb2_dma_contig_memops;
+	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	dst_vq->dev = ctx->xdev->v4l2_dev.dev;
+
+	return vb2_queue_init(dst_vq);
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 ioctls
+ */
+
+static int
+xvip_dma_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
+{
+	cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE;
+	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+
+	strlcpy(cap->driver, XVIP_M2M_NAME, sizeof(cap->driver));
+	strlcpy(cap->card, XVIP_M2M_NAME, sizeof(cap->card));
+	strlcpy(cap->bus_info, XVIP_M2M_NAME, sizeof(cap->card));
+
+	return 0;
+}
+
+static int
+xvip_m2m_enum_fmt(struct file *file, void *fh, struct v4l2_fmtdesc *f)
+{
+	struct xvip_m2m_ctx *ctx = file2ctx(file);
+	struct xvip_m2m_dma *dma = ctx->xdev->dma;
+	const struct xvip_video_format *fmtinfo;
+	const struct xvip_video_format *fmt;
+	struct v4l2_subdev *subdev;
+	struct v4l2_subdev_format v4l_fmt;
+	struct xvip_m2m_dev *xdev = ctx->xdev;
+	u32 i, fmt_cnt, *fmts;
+	int ret;
+
+	if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+		ret = xilinx_xdma_get_v4l2_vid_fmts(dma->chan_rx,
+						    &fmt_cnt, &fmts);
+	else
+		ret = xilinx_xdma_get_v4l2_vid_fmts(dma->chan_tx,
+						    &fmt_cnt, &fmts);
+	if (ret)
+		return ret;
+
+	if (f->index >= fmt_cnt)
+		return -EINVAL;
+
+	if (!xdev->num_subdevs) {
+		fmt = xvip_get_format_by_fourcc(fmts[f->index]);
+		if (IS_ERR(fmt))
+			return PTR_ERR(fmt);
+
+		f->pixelformat = fmt->fourcc;
+		return 0;
+	}
+
+	if (f->index > 0)
+		return -EINVAL;
+
+	/* Establish media pad format */
+	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+		subdev = xvip_dma_remote_subdev(&dma->pads[XVIP_PAD_SOURCE],
+						&v4l_fmt.pad);
+	else
+		subdev = xvip_dma_remote_subdev(&dma->pads[XVIP_PAD_SINK],
+						&v4l_fmt.pad);
+	if (!subdev)
+		return -EPIPE;
+
+	v4l_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+	ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &v4l_fmt);
+	if (ret < 0)
+		return ret == -ENOIOCTLCMD ? -EINVAL : ret;
+
+	for (i = 0; i < fmt_cnt; i++) {
+		fmt = xvip_get_format_by_fourcc(fmts[i]);
+		if (IS_ERR(fmt))
+			return PTR_ERR(fmt);
+
+		if (fmt->code == v4l_fmt.format.code)
+			break;
+	}
+
+	if (i >= fmt_cnt)
+		return -EINVAL;
+
+	fmtinfo = xvip_get_format_by_fourcc(fmts[i]);
+	f->pixelformat = fmtinfo->fourcc;
+
+	return 0;
+}
+
+static int xvip_m2m_get_fmt(struct file *file, void *fh, struct v4l2_format *f)
+{
+	struct xvip_m2m_ctx *ctx = file2ctx(file);
+	struct xvip_m2m_dma *dma = ctx->xdev->dma;
+	struct vb2_queue *vq;
+
+	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
+	if (!vq)
+		return -EINVAL;
+
+	if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+		f->fmt.pix_mp = dma->outfmt.fmt.pix_mp;
+	else
+		f->fmt.pix_mp = dma->capfmt.fmt.pix_mp;
+
+	return 0;
+}
+
+static int __xvip_m2m_try_fmt(struct xvip_m2m_ctx *ctx, struct v4l2_format *f)
+{
+	struct xvip_m2m_dma *dma = ctx->xdev->dma;
+	const struct xvip_video_format *info;
+	struct v4l2_pix_format_mplane *pix_mp;
+	struct v4l2_plane_pix_format *plane_fmt;
+	u32 align, min_width, max_width;
+	u32 bpl, min_bpl, max_bpl;
+	u32 padding_factor_nume, padding_factor_deno;
+	u32 bpl_nume, bpl_deno;
+	u32 i, plane_width, plane_height;
+	struct v4l2_subdev_format fmt;
+	struct v4l2_subdev *subdev;
+	struct xvip_m2m_dev *xdev = ctx->xdev;
+	int ret;
+
+	if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
+	    f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+		return -EINVAL;
+
+	if (xdev->num_subdevs) {
+		if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+			subdev = xvip_dma_remote_subdev
+				(&dma->pads[XVIP_PAD_SOURCE], &fmt.pad);
+		else
+			subdev = xvip_dma_remote_subdev
+				(&dma->pads[XVIP_PAD_SINK], &fmt.pad);
+
+		if (!subdev)
+			return -EPIPE;
+
+		fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+		ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
+		if (ret < 0)
+			return -EINVAL;
+	}
+
+	pix_mp = &f->fmt.pix_mp;
+	plane_fmt = pix_mp->plane_fmt;
+	info = xvip_get_format_by_fourcc(f->fmt.pix_mp.pixelformat);
+	if (info) {
+		if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+			dma->outinfo = info;
+		else
+			dma->capinfo = info;
+	} else {
+		info = xvip_get_format_by_fourcc(XVIP_M2M_DEFAULT_FMT);
+	}
+
+	if (xdev->num_subdevs) {
+		if (info->code != fmt.format.code ||
+		    fmt.format.width != pix_mp->width ||
+		    fmt.format.height != pix_mp->height) {
+			dev_err(xdev->dev, "Failed to set format\n");
+			dev_info(xdev->dev,
+				 "Reqed Code = %d, Width = %d, Height = %d\n",
+				 info->code, pix_mp->width, pix_mp->height);
+			dev_info(xdev->dev,
+				 "Subdev Code = %d, Width = %d, Height = %d",
+				 fmt.format.code, fmt.format.width,
+				 fmt.format.height);
+			return -EINVAL;
+		}
+	}
+
+	xvip_width_padding_factor(info->fourcc, &padding_factor_nume,
+				  &padding_factor_deno);
+	xvip_bpl_scaling_factor(info->fourcc, &bpl_nume, &bpl_deno);
+
+	/*
+	 * V4L2 specification suggests the driver corrects the format struct
+	 * if any of the dimensions is unsupported
+	 */
+	align = lcm(dma->align, info->bpp >> 3);
+	min_width = roundup(XVIP_M2M_MIN_WIDTH, align);
+	max_width = rounddown(XVIP_M2M_MAX_WIDTH, align);
+	pix_mp->width = clamp(pix_mp->width, min_width, max_width);
+	pix_mp->height = clamp(pix_mp->height, XVIP_M2M_MIN_HEIGHT,
+			       XVIP_M2M_MAX_HEIGHT);
+
+	/*
+	 * Clamp the requested bytes per line value. If the maximum
+	 * bytes per line value is zero, the module doesn't support
+	 * user configurable line sizes. Override the requested value
+	 * with the minimum in that case.
+	 */
+	max_bpl = rounddown(XVIP_M2M_MAX_WIDTH, align);
+
+	if (info->buffers == 1) {
+		/* Handling contiguous data with mplanes */
+		min_bpl = (pix_mp->width * info->bpl_factor *
+			   padding_factor_nume * bpl_nume) /
+			   (padding_factor_deno * bpl_deno);
+		min_bpl = roundup(min_bpl, align);
+		bpl = roundup(plane_fmt[0].bytesperline, align);
+		plane_fmt[0].bytesperline = clamp(bpl, min_bpl, max_bpl);
+
+		if (info->num_planes == 1) {
+			/* Single plane formats */
+			plane_fmt[0].sizeimage = plane_fmt[0].bytesperline *
+						 pix_mp->height;
+		} else {
+			/* Multi plane formats in contiguous buffer*/
+			plane_fmt[0].sizeimage =
+				DIV_ROUND_UP(plane_fmt[0].bytesperline *
+					     pix_mp->height *
+					     info->bpp, 8);
+		}
+	} else {
+		/* Handling non-contiguous data with mplanes */
+		for (i = 0; i < info->num_planes; i++) {
+			plane_width = pix_mp->width / (i ? info->hsub : 1);
+			plane_height = pix_mp->height / (i ? info->vsub : 1);
+			min_bpl = (plane_width * info->bpl_factor *
+				   padding_factor_nume * bpl_nume) /
+				   (padding_factor_deno * bpl_deno);
+			min_bpl = roundup(min_bpl, align);
+			bpl = rounddown(plane_fmt[i].bytesperline, align);
+			plane_fmt[i].bytesperline = clamp(bpl, min_bpl,
+							  max_bpl);
+			plane_fmt[i].sizeimage = plane_fmt[i].bytesperline *
+						 plane_height;
+		}
+	}
+
+	return 0;
+}
+
+static int xvip_m2m_try_fmt(struct file *file, void *fh, struct v4l2_format *f)
+{
+	struct xvip_m2m_ctx *ctx = file2ctx(file);
+	int ret;
+
+	ret = __xvip_m2m_try_fmt(ctx, f);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int xvip_m2m_set_fmt(struct file *file, void *fh, struct v4l2_format *f)
+{
+	struct xvip_m2m_ctx *ctx = file2ctx(file);
+	struct xvip_m2m_dma *dma = ctx->xdev->dma;
+	struct vb2_queue *vq;
+	int ret;
+
+	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
+	if (!vq)
+		return -EINVAL;
+
+	if (vb2_is_busy(vq)) {
+		v4l2_err(&ctx->xdev->v4l2_dev, "%s queue busy\n", __func__);
+		return -EBUSY;
+	}
+
+	ret = __xvip_m2m_try_fmt(ctx, f);
+	if (ret < 0)
+		return ret;
+
+	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+		dma->outfmt.fmt.pix_mp = f->fmt.pix_mp;
+	else
+		dma->capfmt.fmt.pix_mp = f->fmt.pix_mp;
+
+	return 0;
+}
+
+static int
+xvip_m2m_g_selection(struct file *file, void *fh, struct v4l2_selection *s)
+{
+	struct xvip_m2m_ctx *ctx = file2ctx(file);
+	struct xvip_m2m_dma *dma = ctx->xdev->dma;
+	int ret = 0;
+
+	if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+	    s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	switch (s->target) {
+	case V4L2_SEL_TGT_COMPOSE:
+		ret = -ENOTTY;
+		break;
+	case V4L2_SEL_TGT_CROP:
+		s->r.left = 0;
+		s->r.top = 0;
+		s->r.width = dma->r.width;
+		s->r.height = dma->r.height;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int
+xvip_m2m_s_selection(struct file *file, void *fh, struct v4l2_selection *s)
+{
+	struct xvip_m2m_ctx *ctx = file2ctx(file);
+	struct xvip_m2m_dma *dma = ctx->xdev->dma;
+	u32 min_width, max_width;
+	int ret = 0;
+
+	if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+	    s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	switch (s->target) {
+	case V4L2_SEL_TGT_COMPOSE:
+		ret = -ENOTTY;
+		break;
+	case V4L2_SEL_TGT_CROP:
+		if (s->r.width > dma->outfmt.fmt.pix_mp.width ||
+		    s->r.height > dma->outfmt.fmt.pix_mp.height ||
+		    s->r.top != 0 || s->r.left != 0)
+			return -EINVAL;
+
+		dma->crop = true;
+		min_width = roundup(XVIP_M2M_MIN_WIDTH, dma->align);
+		max_width = rounddown(XVIP_M2M_MAX_WIDTH, dma->align);
+		dma->r.width = clamp(s->r.width, min_width, max_width);
+		dma->r.height = s->r.height;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static const struct v4l2_ioctl_ops xvip_m2m_ioctl_ops = {
+	.vidioc_querycap		= xvip_dma_querycap,
+
+	.vidioc_enum_fmt_vid_cap	= xvip_m2m_enum_fmt,
+	.vidioc_g_fmt_vid_cap_mplane	= xvip_m2m_get_fmt,
+	.vidioc_try_fmt_vid_cap_mplane	= xvip_m2m_try_fmt,
+	.vidioc_s_fmt_vid_cap_mplane	= xvip_m2m_set_fmt,
+
+	.vidioc_enum_fmt_vid_out	= xvip_m2m_enum_fmt,
+	.vidioc_g_fmt_vid_out_mplane	= xvip_m2m_get_fmt,
+	.vidioc_try_fmt_vid_out_mplane	= xvip_m2m_try_fmt,
+	.vidioc_s_fmt_vid_out_mplane	= xvip_m2m_set_fmt,
+	.vidioc_s_selection		= xvip_m2m_s_selection,
+	.vidioc_g_selection		= xvip_m2m_g_selection,
+
+	.vidioc_reqbufs			= v4l2_m2m_ioctl_reqbufs,
+	.vidioc_querybuf		= v4l2_m2m_ioctl_querybuf,
+	.vidioc_qbuf			= v4l2_m2m_ioctl_qbuf,
+	.vidioc_dqbuf			= v4l2_m2m_ioctl_dqbuf,
+	.vidioc_prepare_buf		= v4l2_m2m_ioctl_prepare_buf,
+	.vidioc_create_bufs		= v4l2_m2m_ioctl_create_bufs,
+	.vidioc_expbuf			= v4l2_m2m_ioctl_expbuf,
+
+	.vidioc_streamon		= v4l2_m2m_ioctl_streamon,
+	.vidioc_streamoff		= v4l2_m2m_ioctl_streamoff,
+};
+
+/*
+ * File operations
+ */
+static int xvip_m2m_open(struct file *file)
+{
+	struct xvip_m2m_dev *xdev = video_drvdata(file);
+	struct xvip_m2m_ctx *ctx = NULL;
+	int ret;
+
+	ctx = devm_kzalloc(xdev->dev, sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	v4l2_fh_init(&ctx->fh, video_devdata(file));
+	file->private_data = &ctx->fh;
+	ctx->xdev = xdev;
+
+	ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(xdev->m2m_dev, ctx,
+					    &xvip_m2m_queue_init);
+	if (IS_ERR(ctx->fh.m2m_ctx)) {
+		ret = PTR_ERR(ctx->fh.m2m_ctx);
+		v4l2_fh_exit(&ctx->fh);
+		return ret;
+	}
+
+	v4l2_fh_add(&ctx->fh);
+	dev_info(xdev->dev, "Created instance %p, m2m_ctx: %p\n", ctx,
+		 ctx->fh.m2m_ctx);
+	return 0;
+}
+
+static int xvip_m2m_release(struct file *file)
+{
+	struct xvip_m2m_ctx *ctx = file->private_data;
+
+	v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
+	return 0;
+}
+
+static u32 xvip_m2m_poll(struct file *file,
+			 struct poll_table_struct *wait)
+{
+	struct xvip_m2m_ctx *ctx = file->private_data;
+	int ret;
+
+	mutex_lock(&ctx->xdev->lock);
+	ret = v4l2_m2m_poll(file, ctx->fh.m2m_ctx, wait);
+	mutex_unlock(&ctx->xdev->lock);
+
+	return ret;
+}
+
+static int xvip_m2m_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct xvip_m2m_ctx *ctx = file->private_data;
+
+	return v4l2_m2m_mmap(file, ctx->fh.m2m_ctx, vma);
+}
+
+/*
+ * mem2mem callbacks
+ */
+
+static int xvip_m2m_job_ready(void *priv)
+{
+	struct xvip_m2m_ctx *ctx = priv;
+
+	if ((v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) > 0) &&
+	    (v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx) > 0))
+		return 1;
+
+	return 0;
+}
+
+static void xvip_m2m_job_abort(void *priv)
+{
+	struct xvip_m2m_ctx *ctx = priv;
+
+	/* Will cancel the transaction in the next interrupt handler */
+	v4l2_m2m_job_finish(ctx->xdev->m2m_dev, ctx->fh.m2m_ctx);
+}
+
+static void xvip_m2m_prep_submit_dev2mem_desc(struct xvip_m2m_ctx *ctx,
+					      struct vb2_v4l2_buffer *dst_buf)
+{
+	struct xvip_m2m_dma *dma = ctx->xdev->dma;
+	struct xvip_m2m_dev *xdev = ctx->xdev;
+	struct dma_async_tx_descriptor *desc;
+	dma_addr_t p_out;
+	const struct xvip_video_format *info;
+	struct v4l2_pix_format_mplane *pix_mp;
+	u32 padding_factor_nume, padding_factor_deno;
+	u32 bpl_nume, bpl_deno;
+	u32 luma_size;
+	u32 flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK;
+	enum operation_mode mode = DEFAULT;
+	u32 bpl, dst_width, dst_height;
+
+	p_out = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0);
+
+	if (!p_out) {
+		dev_err(xdev->dev,
+			"Acquiring kernel pointer to buffer failed\n");
+		return;
+	}
+
+	ctx->xt.dir = DMA_DEV_TO_MEM;
+	ctx->xt.src_sgl = false;
+	ctx->xt.dst_sgl = true;
+	ctx->xt.dst_start = p_out;
+
+	pix_mp = &dma->capfmt.fmt.pix_mp;
+	bpl = pix_mp->plane_fmt[0].bytesperline;
+	if (dma->crop) {
+		dst_width = dma->r.width;
+		dst_height = dma->r.height;
+	} else {
+		dst_width = pix_mp->width;
+		dst_height = pix_mp->height;
+	}
+
+	info = dma->capinfo;
+	xilinx_xdma_set_mode(dma->chan_rx, mode);
+	xilinx_xdma_v4l2_config(dma->chan_rx, pix_mp->pixelformat);
+	xvip_width_padding_factor(pix_mp->pixelformat, &padding_factor_nume,
+				  &padding_factor_deno);
+	xvip_bpl_scaling_factor(pix_mp->pixelformat, &bpl_nume, &bpl_deno);
+
+	ctx->xt.frame_size = info->num_planes;
+	ctx->sgl[0].size = (dst_width * info->bpl_factor *
+			    padding_factor_nume * bpl_nume) /
+			    (padding_factor_deno * bpl_deno);
+	ctx->sgl[0].icg = bpl - ctx->sgl[0].size;
+	ctx->xt.numf = dst_height;
+
+	/*
+	 * dst_icg is the number of bytes to jump after last luma addr
+	 * and before first chroma addr
+	 */
+	ctx->sgl[0].src_icg = 0;
+
+	if (info->buffers == 1) {
+		/* Handling contiguous data with mplanes */
+		ctx->sgl[0].dst_icg = 0;
+		if (dma->crop)
+			ctx->sgl[0].dst_icg = bpl *
+					      (pix_mp->height - dst_height);
+	} else {
+		/* Handling non-contiguous data with mplanes */
+		if (info->buffers == 2) {
+			dma_addr_t chroma_cap =
+			vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 1);
+			luma_size = pix_mp->plane_fmt[0].bytesperline *
+				    ctx->xt.numf;
+			if (chroma_cap > p_out)
+				ctx->sgl[0].dst_icg = chroma_cap - p_out -
+						      luma_size;
+			}
+	}
+
+	desc = dmaengine_prep_interleaved_dma(dma->chan_rx, &ctx->xt, flags);
+	if (!desc) {
+		dev_err(xdev->dev, "Failed to prepare DMA rx transfer\n");
+		return;
+	}
+
+	desc->callback = xvip_m2m_dma_callback;
+	desc->callback_param = ctx;
+	dmaengine_submit(desc);
+	dma_async_issue_pending(dma->chan_rx);
+}
+
+static void xvip_m2m_prep_submit_mem2dev_desc(struct xvip_m2m_ctx *ctx,
+					      struct vb2_v4l2_buffer *src_buf)
+{
+	struct xvip_m2m_dma *dma = ctx->xdev->dma;
+	struct xvip_m2m_dev *xdev = ctx->xdev;
+	struct dma_async_tx_descriptor *desc;
+	dma_addr_t p_in;
+	const struct xvip_video_format *info;
+	struct v4l2_pix_format_mplane *pix_mp;
+	u32 padding_factor_nume, padding_factor_deno;
+	u32 bpl_nume, bpl_deno;
+	u32 luma_size;
+	u32 flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK;
+	enum operation_mode mode = DEFAULT;
+	u32 bpl, src_width, src_height;
+
+	p_in = vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0);
+
+	if (!p_in) {
+		dev_err(xdev->dev,
+			"Acquiring kernel pointer to buffer failed\n");
+		return;
+	}
+
+	ctx->xt.dir = DMA_MEM_TO_DEV;
+	ctx->xt.src_sgl = true;
+	ctx->xt.dst_sgl = false;
+	ctx->xt.src_start = p_in;
+
+	pix_mp = &dma->outfmt.fmt.pix_mp;
+	bpl = pix_mp->plane_fmt[0].bytesperline;
+	if (dma->crop) {
+		src_width = dma->r.width;
+		src_height = dma->r.height;
+	} else {
+		src_width = pix_mp->width;
+		src_height = pix_mp->height;
+	}
+
+	info = dma->outinfo;
+	xilinx_xdma_set_mode(dma->chan_tx, mode);
+	xilinx_xdma_v4l2_config(dma->chan_tx, pix_mp->pixelformat);
+	xvip_width_padding_factor(pix_mp->pixelformat, &padding_factor_nume,
+				  &padding_factor_deno);
+	xvip_bpl_scaling_factor(pix_mp->pixelformat, &bpl_nume, &bpl_deno);
+
+	ctx->xt.frame_size = info->num_planes;
+	ctx->sgl[0].size = (src_width * info->bpl_factor *
+			    padding_factor_nume * bpl_nume) /
+			    (padding_factor_deno * bpl_deno);
+	ctx->sgl[0].icg = bpl - ctx->sgl[0].size;
+	ctx->xt.numf = src_height;
+
+	/*
+	 * src_icg is the number of bytes to jump after last luma addr
+	 * and before first chroma addr
+	 */
+	ctx->sgl[0].dst_icg = 0;
+
+	if (info->buffers == 1) {
+		/* Handling contiguous data with mplanes */
+		ctx->sgl[0].src_icg = 0;
+		if (dma->crop)
+			ctx->sgl[0].src_icg = bpl *
+					      (pix_mp->height - src_height);
+	} else {
+		/* Handling non-contiguous data with mplanes */
+		if (info->buffers == 2) {
+			dma_addr_t chroma_out =
+			vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 1);
+			luma_size = bpl * ctx->xt.numf;
+			if (chroma_out > p_in)
+				ctx->sgl[0].src_icg = chroma_out - p_in -
+						      luma_size;
+			}
+	}
+
+	desc = dmaengine_prep_interleaved_dma(dma->chan_tx, &ctx->xt, flags);
+	if (!desc) {
+		dev_err(xdev->dev, "Failed to prepare DMA tx transfer\n");
+		return;
+	}
+
+	desc->callback = xvip_m2m_dma_callback_mem2dev;
+	desc->callback_param = ctx;
+	dmaengine_submit(desc);
+	dma_async_issue_pending(dma->chan_tx);
+}
+
+/**
+ * xvip_m2m_device_run - prepares and starts the device
+ *
+ * @priv: Instance private data
+ *
+ * This simulates all the immediate preparations required before starting
+ * a device. This will be called by the framework when it decides to schedule
+ * a particular instance.
+ */
+static void xvip_m2m_device_run(void *priv)
+{
+	struct xvip_m2m_ctx *ctx = priv;
+	struct vb2_v4l2_buffer *src_buf, *dst_buf;
+
+	src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+
+	/* Prepare and submit mem2dev transaction */
+	xvip_m2m_prep_submit_mem2dev_desc(ctx, src_buf);
+
+	/* Prepare and submit dev2mem transaction */
+	xvip_m2m_prep_submit_dev2mem_desc(ctx, dst_buf);
+}
+
+static const struct v4l2_file_operations xvip_m2m_fops = {
+	.owner		= THIS_MODULE,
+	.open		= xvip_m2m_open,
+	.release	= xvip_m2m_release,
+	.poll		= xvip_m2m_poll,
+	.unlocked_ioctl	= video_ioctl2,
+	.mmap		= xvip_m2m_mmap,
+};
+
+static struct video_device xvip_m2m_videodev = {
+	.name		= XVIP_M2M_NAME,
+	.fops		= &xvip_m2m_fops,
+	.ioctl_ops	= &xvip_m2m_ioctl_ops,
+	.release	= video_device_release_empty,
+	.vfl_dir	= VFL_DIR_M2M,
+	.device_caps	= V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING,
+	.vfl_type	= VFL_TYPE_GRABBER,
+};
+
+static const struct v4l2_m2m_ops xvip_m2m_ops = {
+	.device_run	= xvip_m2m_device_run,
+	.job_ready	= xvip_m2m_job_ready,
+	.job_abort	= xvip_m2m_job_abort,
+};
+
+/*
+ * This function is taken from the framework
+ * video_register_media_controller() function
+ */
+static int xvideo_register_media_controller(struct video_device *vdev)
+{
+#if defined(CONFIG_MEDIA_CONTROLLER)
+	u32 intf_type;
+	int ret;
+
+	/*
+	 * Modified this by removing the condition for VFL_DIR_M2M
+	 * to ensure that the video entity is created.
+	 */
+	if (!vdev->v4l2_dev->mdev)
+		return 0;
+
+	vdev->entity.obj_type = MEDIA_ENTITY_TYPE_VIDEO_DEVICE;
+	vdev->entity.function = MEDIA_ENT_F_UNKNOWN;
+
+	switch (vdev->vfl_type) {
+	case VFL_TYPE_GRABBER:
+		intf_type = MEDIA_INTF_T_V4L_VIDEO;
+		vdev->entity.function = MEDIA_ENT_F_IO_V4L;
+		break;
+	case VFL_TYPE_VBI:
+		intf_type = MEDIA_INTF_T_V4L_VBI;
+		vdev->entity.function = MEDIA_ENT_F_IO_VBI;
+		break;
+	case VFL_TYPE_SDR:
+		intf_type = MEDIA_INTF_T_V4L_SWRADIO;
+		vdev->entity.function = MEDIA_ENT_F_IO_SWRADIO;
+		break;
+	case VFL_TYPE_TOUCH:
+		intf_type = MEDIA_INTF_T_V4L_TOUCH;
+		vdev->entity.function = MEDIA_ENT_F_IO_V4L;
+		break;
+	case VFL_TYPE_RADIO:
+		intf_type = MEDIA_INTF_T_V4L_RADIO;
+		/*
+		 * Radio doesn't have an entity at the V4L2 side to represent
+		 * radio input or output. Instead, the audio input/output goes
+		 * via either physical wires or ALSA.
+		 */
+		break;
+	case VFL_TYPE_SUBDEV:
+		intf_type = MEDIA_INTF_T_V4L_SUBDEV;
+		/* Entity will be created via v4l2_device_register_subdev() */
+		break;
+	default:
+		return 0;
+	}
+
+	if (vdev->entity.function != MEDIA_ENT_F_UNKNOWN) {
+		vdev->entity.name = vdev->name;
+
+		/* Needed just for backward compatibility with legacy MC API */
+		vdev->entity.info.dev.major = VIDEO_MAJOR;
+		vdev->entity.info.dev.minor = vdev->minor;
+
+		ret = media_device_register_entity(vdev->v4l2_dev->mdev,
+						   &vdev->entity);
+		if (ret < 0) {
+			pr_warn("%s: media_device_register_entity failed\n",
+				__func__);
+			return ret;
+		}
+	}
+
+	vdev->intf_devnode = media_devnode_create(vdev->v4l2_dev->mdev,
+						  intf_type,
+						  0, VIDEO_MAJOR,
+						  vdev->minor);
+	if (!vdev->intf_devnode) {
+		media_device_unregister_entity(&vdev->entity);
+		return -ENOMEM;
+	}
+
+	if (vdev->entity.function != MEDIA_ENT_F_UNKNOWN) {
+		struct media_link *link;
+
+		link = media_create_intf_link(&vdev->entity,
+					      &vdev->intf_devnode->intf,
+					      MEDIA_LNK_FL_ENABLED |
+					      MEDIA_LNK_FL_IMMUTABLE);
+		if (!link) {
+			media_devnode_remove(vdev->intf_devnode);
+			media_device_unregister_entity(&vdev->entity);
+			return -ENOMEM;
+		}
+	}
+
+	/* FIXME: how to create the other interface links? */
+
+#endif
+	/* This is added from __video_register_device() */
+
+	/* Part 6: Activate this minor. The char device can now be used. */
+	set_bit(V4L2_FL_REGISTERED, &vdev->flags);
+
+	return 0;
+}
+
+static int xvip_m2m_dma_init(struct xvip_m2m_dma *dma)
+{
+	struct xvip_m2m_dev *xdev;
+	struct v4l2_pix_format_mplane *pix_mp;
+	int ret;
+
+	xdev = dma->xdev;
+	mutex_init(&xdev->lock);
+	mutex_init(&dma->pipe.lock);
+	spin_lock_init(&xdev->queued_lock);
+
+	/* Format info on capture port - NV12 is the default format */
+	dma->capinfo = xvip_get_format_by_fourcc(XVIP_M2M_DEFAULT_FMT);
+	pix_mp = &dma->capfmt.fmt.pix_mp;
+	pix_mp->pixelformat = dma->capinfo->fourcc;
+
+	pix_mp->field = V4L2_FIELD_NONE;
+	pix_mp->width = XVIP_M2M_DEF_WIDTH;
+	pix_mp->height = XVIP_M2M_DEF_HEIGHT;
+	pix_mp->plane_fmt[0].bytesperline = pix_mp->width *
+					    dma->capinfo->bpl_factor;
+	pix_mp->plane_fmt[0].sizeimage =
+			DIV_ROUND_UP(pix_mp->plane_fmt[0].bytesperline *
+				     pix_mp->height * dma->capinfo->bpp, 8);
+
+	/* Format info on output port - NV12 is the default format */
+	dma->outinfo = xvip_get_format_by_fourcc(XVIP_M2M_DEFAULT_FMT);
+	pix_mp = &dma->capfmt.fmt.pix_mp;
+	pix_mp->pixelformat = dma->outinfo->fourcc;
+	pix_mp->field = V4L2_FIELD_NONE;
+	pix_mp->width = XVIP_M2M_DEF_WIDTH;
+	pix_mp->height = XVIP_M2M_DEF_HEIGHT;
+	pix_mp->plane_fmt[0].bytesperline = pix_mp->width *
+					    dma->outinfo->bpl_factor;
+	pix_mp->plane_fmt[0].sizeimage =
+			DIV_ROUND_UP(pix_mp->plane_fmt[0].bytesperline *
+				     pix_mp->height * dma->outinfo->bpp, 8);
+
+	/* DMA channels for mem2mem */
+	dma->chan_tx = dma_request_chan(xdev->dev, "tx");
+	if (IS_ERR(dma->chan_tx)) {
+		ret = PTR_ERR(dma->chan_tx);
+		if (ret != -EPROBE_DEFER)
+			dev_err(xdev->dev, "mem2mem DMA tx channel not found");
+
+		return ret;
+	}
+
+	dma->chan_rx = dma_request_chan(xdev->dev, "rx");
+	if (IS_ERR(dma->chan_rx)) {
+		ret = PTR_ERR(dma->chan_rx);
+		if (ret != -EPROBE_DEFER)
+			dev_err(xdev->dev, "mem2mem DMA rx channel not found");
+
+		goto tx;
+	}
+
+	dma->align = BIT(dma->chan_tx->device->copy_align);
+
+	/* Video node */
+	dma->video = xvip_m2m_videodev;
+	dma->video.v4l2_dev = &xdev->v4l2_dev;
+	dma->video.lock = &xdev->lock;
+
+	dma->pads[XVIP_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+	dma->pads[XVIP_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+
+	ret = media_entity_pads_init(&dma->video.entity, 2, dma->pads);
+	if (ret < 0)
+		goto error;
+
+	ret = video_register_device(&dma->video, VFL_TYPE_GRABBER, -1);
+	if (ret < 0) {
+		dev_err(xdev->dev, "Failed to register mem2mem video device\n");
+		goto tx_rx;
+	}
+
+	ret = xvideo_register_media_controller(&dma->video);
+	if (ret < 0) {
+		dev_err(xdev->dev, "Failed to register media controller\n");
+		goto unreg_video;
+	}
+
+	video_set_drvdata(&dma->video, dma->xdev);
+	return 0;
+
+unreg_video:
+	video_unregister_device(&dma->video);
+tx_rx:
+	dma_release_channel(dma->chan_rx);
+tx:
+	dma_release_channel(dma->chan_tx);
+error:
+	return ret;
+}
+
+static void xvip_m2m_dma_deinit(struct xvip_m2m_dma *dma)
+{
+	if (video_is_registered(&dma->video))
+		video_unregister_device(&dma->video);
+
+	mutex_destroy(&dma->pipe.lock);
+	mutex_destroy(&dma->xdev->lock);
+	dma_release_channel(dma->chan_tx);
+	dma_release_channel(dma->chan_rx);
+}
+
+static int xvip_m2m_dma_alloc_init(struct xvip_m2m_dev *xdev)
+{
+	struct xvip_m2m_dma *dma = NULL;
+	int ret;
+
+	dma = devm_kzalloc(xdev->dev, sizeof(*dma), GFP_KERNEL);
+	if (!dma)
+		return -ENOMEM;
+
+	dma->xdev = xdev;
+	xdev->dma = dma;
+
+	ret = xvip_m2m_dma_init(xdev->dma);
+	if (ret) {
+		dev_err(xdev->dev, "DMA initialization failed\n");
+		return ret;
+	}
+
+	xdev->v4l2_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE;
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Platform Device Driver
+ */
+static void xvip_composite_v4l2_cleanup(struct xvip_m2m_dev *xdev)
+{
+	v4l2_device_unregister(&xdev->v4l2_dev);
+	media_device_unregister(&xdev->media_dev);
+	media_device_cleanup(&xdev->media_dev);
+}
+
+static int xvip_composite_v4l2_init(struct xvip_m2m_dev *xdev)
+{
+	int ret;
+
+	xdev->media_dev.dev = xdev->dev;
+	strlcpy(xdev->media_dev.model, "Xilinx Video M2M Composite Device",
+		sizeof(xdev->media_dev.model));
+	xdev->media_dev.hw_revision = 0;
+
+	media_device_init(&xdev->media_dev);
+
+	xdev->v4l2_dev.mdev = &xdev->media_dev;
+	ret = v4l2_device_register(xdev->dev, &xdev->v4l2_dev);
+	if (ret < 0) {
+		dev_err(xdev->dev, "V4L2 device registration failed (%d)\n",
+			ret);
+		media_device_cleanup(&xdev->media_dev);
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct xvip_graph_entity *
+xvip_graph_find_entity(struct xvip_m2m_dev *xdev,
+		       const struct device_node *node)
+{
+	struct xvip_graph_entity *entity;
+
+	list_for_each_entry(entity, &xdev->entities, list) {
+		if (entity->node == node)
+			return entity;
+	}
+
+	return NULL;
+}
+
+static int xvip_graph_build_one(struct xvip_m2m_dev *xdev,
+				struct xvip_graph_entity *entity)
+{
+	u32 link_flags = MEDIA_LNK_FL_ENABLED;
+	struct media_entity *local = entity->entity;
+	struct media_entity *remote;
+	struct media_pad *local_pad;
+	struct media_pad *remote_pad;
+	struct xvip_graph_entity *ent;
+	struct v4l2_fwnode_link link;
+	struct device_node *ep = NULL;
+	struct device_node *next;
+	int ret = 0;
+
+	dev_dbg(xdev->dev, "creating links for entity %s\n", local->name);
+
+	while (1) {
+		/* Get the next endpoint and parse its link. */
+		next = of_graph_get_next_endpoint(entity->node, ep);
+		if (!next)
+			break;
+
+		ep = next;
+
+		dev_dbg(xdev->dev, "processing endpoint %pOF\n", ep);
+
+		ret = v4l2_fwnode_parse_link(of_fwnode_handle(ep), &link);
+		if (ret < 0) {
+			dev_err(xdev->dev, "failed to parse link for %pOF\n",
+				ep);
+			continue;
+		}
+
+		/* Skip sink ports, they will be processed from the other end of
+		 * the link.
+		 */
+		if (link.local_port >= local->num_pads) {
+			dev_err(xdev->dev, "invalid port number %u for %pOF\n",
+				link.local_port,
+				to_of_node(link.local_node));
+			v4l2_fwnode_put_link(&link);
+			ret = -EINVAL;
+			break;
+		}
+
+		local_pad = &local->pads[link.local_port];
+
+		if (local_pad->flags & MEDIA_PAD_FL_SINK) {
+			dev_dbg(xdev->dev, "skipping sink port %pOF:%u\n",
+				to_of_node(link.local_node),
+				link.local_port);
+			v4l2_fwnode_put_link(&link);
+			continue;
+		}
+
+		/* Skip DMA engines, they will be processed separately. */
+		if (link.remote_node == of_fwnode_handle(xdev->dev->of_node)) {
+			dev_dbg(xdev->dev, "skipping DMA port %pOF:%u\n",
+				to_of_node(link.local_node),
+				link.local_port);
+			v4l2_fwnode_put_link(&link);
+			continue;
+		}
+
+		/* Find the remote entity. */
+		ent = xvip_graph_find_entity(xdev,
+					     to_of_node(link.remote_node));
+		if (!ent) {
+			dev_err(xdev->dev, "no entity found for %pOF\n",
+				to_of_node(link.remote_node));
+			v4l2_fwnode_put_link(&link);
+			ret = -ENODEV;
+			break;
+		}
+
+		remote = ent->entity;
+
+		if (link.remote_port >= remote->num_pads) {
+			dev_err(xdev->dev, "invalid port number %u on %pOF\n",
+				link.remote_port, to_of_node(link.remote_node));
+			v4l2_fwnode_put_link(&link);
+			ret = -EINVAL;
+			break;
+		}
+
+		remote_pad = &remote->pads[link.remote_port];
+
+		v4l2_fwnode_put_link(&link);
+
+		/* Create the media link. */
+		dev_dbg(xdev->dev, "creating %s:%u -> %s:%u link\n",
+			local->name, local_pad->index,
+			remote->name, remote_pad->index);
+
+		ret = media_create_pad_link(local, local_pad->index,
+					    remote, remote_pad->index,
+					    link_flags);
+		if (ret < 0) {
+			dev_err(xdev->dev,
+				"failed to create %s:%u -> %s:%u link\n",
+				local->name, local_pad->index,
+				remote->name, remote_pad->index);
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static int xvip_graph_parse_one(struct xvip_m2m_dev *xdev,
+				struct device_node *node)
+{
+	struct xvip_graph_entity *entity;
+	struct device_node *remote;
+	struct device_node *ep = NULL;
+	int ret = 0;
+
+	dev_dbg(xdev->dev, "parsing node %pOF\n", node);
+
+	while (1) {
+		ep = of_graph_get_next_endpoint(node, ep);
+		if (!ep)
+			break;
+
+		dev_dbg(xdev->dev, "handling endpoint %pOF %s\n",
+			ep, ep->name);
+
+		remote = of_graph_get_remote_port_parent(ep);
+		if (!remote) {
+			ret = -EINVAL;
+			break;
+		}
+		dev_dbg(xdev->dev, "Remote endpoint %pOF %s\n",
+			remote, remote->name);
+
+		/* Skip entities that we have already processed. */
+		if (remote == xdev->dev->of_node ||
+		    xvip_graph_find_entity(xdev, remote)) {
+			of_node_put(remote);
+			continue;
+		}
+
+		entity = devm_kzalloc(xdev->dev, sizeof(*entity), GFP_KERNEL);
+		if (!entity) {
+			of_node_put(remote);
+			ret = -ENOMEM;
+			break;
+		}
+
+		entity->node = remote;
+		entity->asd.match_type = V4L2_ASYNC_MATCH_FWNODE;
+		entity->asd.match.fwnode = of_fwnode_handle(remote);
+		list_add_tail(&entity->list, &xdev->entities);
+		xdev->num_subdevs++;
+	}
+
+	of_node_put(ep);
+	return ret;
+}
+
+static int xvip_graph_parse(struct xvip_m2m_dev *xdev)
+{
+	struct xvip_graph_entity *entity;
+	int ret;
+
+	/*
+	 * Walk the links to parse the full graph. Start by parsing the
+	 * composite node and then parse entities in turn. The list_for_each
+	 * loop will handle entities added at the end of the list while walking
+	 * the links.
+	 */
+	ret = xvip_graph_parse_one(xdev, xdev->dev->of_node);
+	if (ret < 0)
+		return 0;
+
+	list_for_each_entry(entity, &xdev->entities, list) {
+		ret = xvip_graph_parse_one(xdev, entity->node);
+		if (ret < 0)
+			break;
+	}
+
+	return ret;
+}
+
+static int xvip_graph_build_dma(struct xvip_m2m_dev *xdev)
+{
+	u32 link_flags = MEDIA_LNK_FL_ENABLED;
+	struct device_node *node = xdev->dev->of_node;
+	struct media_entity *source;
+	struct media_entity *sink;
+	struct media_pad *source_pad;
+	struct media_pad *sink_pad;
+	struct xvip_graph_entity *ent;
+	struct v4l2_fwnode_link link;
+	struct device_node *ep = NULL;
+	struct device_node *next;
+	struct xvip_m2m_dma *dma = xdev->dma;
+	int ret = 0;
+
+	dev_dbg(xdev->dev, "creating links for DMA engines\n");
+
+	while (1) {
+		/* Get the next endpoint and parse its link. */
+		next = of_graph_get_next_endpoint(node, ep);
+		if (!next)
+			break;
+
+		ep = next;
+
+		dev_dbg(xdev->dev, "processing endpoint %pOF\n", ep);
+
+		ret = v4l2_fwnode_parse_link(of_fwnode_handle(ep), &link);
+		if (ret < 0) {
+			dev_err(xdev->dev, "failed to parse link for %pOF\n",
+				ep);
+			continue;
+		}
+
+		dev_dbg(xdev->dev, "creating link for DMA engine %s\n",
+			dma->video.name);
+
+		/* Find the remote entity. */
+		ent = xvip_graph_find_entity(xdev,
+					     to_of_node(link.remote_node));
+		if (!ent) {
+			dev_err(xdev->dev, "no entity found for %pOF\n",
+				to_of_node(link.remote_node));
+			v4l2_fwnode_put_link(&link);
+			ret = -ENODEV;
+			break;
+		}
+		if (link.remote_port >= ent->entity->num_pads) {
+			dev_err(xdev->dev, "invalid port number %u on %pOF\n",
+				link.remote_port,
+				to_of_node(link.remote_node));
+			v4l2_fwnode_put_link(&link);
+			ret = -EINVAL;
+			break;
+		}
+
+		dev_dbg(xdev->dev, "Entity %s %s\n", ent->node->name,
+			ent->node->full_name);
+		dev_dbg(xdev->dev, "port number %u on %pOF\n",
+			link.remote_port, to_of_node(link.remote_node));
+		dev_dbg(xdev->dev, "local port number %u on %pOF\n",
+			link.local_port, to_of_node(link.local_node));
+
+		if (link.local_port == XVIP_PAD_SOURCE) {
+			source = &dma->video.entity;
+			source_pad = &dma->pads[XVIP_PAD_SOURCE];
+			sink = ent->entity;
+			sink_pad = &sink->pads[XVIP_PAD_SINK];
+
+		} else {
+			source = ent->entity;
+			source_pad = &source->pads[XVIP_PAD_SOURCE];
+			sink = &dma->video.entity;
+			sink_pad = &dma->pads[XVIP_PAD_SINK];
+		}
+
+		v4l2_fwnode_put_link(&link);
+
+		/* Create the media link. */
+		dev_dbg(xdev->dev, "creating %s:%u -> %s:%u link\n",
+			source->name, source_pad->index,
+			sink->name, sink_pad->index);
+
+		ret = media_create_pad_link(source, source_pad->index,
+					    sink, sink_pad->index,
+					    link_flags);
+		if (ret < 0) {
+			dev_err(xdev->dev,
+				"failed to create %s:%u -> %s:%u link\n",
+				source->name, source_pad->index,
+				sink->name, sink_pad->index);
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static int xvip_graph_notify_complete(struct v4l2_async_notifier *notifier)
+{
+	struct xvip_m2m_dev *xdev =
+		container_of(notifier, struct xvip_m2m_dev, notifier);
+	struct xvip_graph_entity *entity;
+	int ret;
+
+	dev_dbg(xdev->dev, "notify complete, all subdevs registered\n");
+
+	/* Create links for every entity. */
+	list_for_each_entry(entity, &xdev->entities, list) {
+		ret = xvip_graph_build_one(xdev, entity);
+		if (ret < 0)
+			return ret;
+	}
+
+	/* Create links for DMA channels. */
+	ret = xvip_graph_build_dma(xdev);
+	if (ret < 0)
+		return ret;
+
+	ret = v4l2_device_register_subdev_nodes(&xdev->v4l2_dev);
+	if (ret < 0)
+		dev_err(xdev->dev, "failed to register subdev nodes\n");
+
+	return media_device_register(&xdev->media_dev);
+}
+
+static int xvip_graph_notify_bound(struct v4l2_async_notifier *notifier,
+				   struct v4l2_subdev *subdev,
+				   struct v4l2_async_subdev *asd)
+{
+	struct xvip_m2m_dev *xdev =
+		container_of(notifier, struct xvip_m2m_dev, notifier);
+	struct xvip_graph_entity *entity;
+
+	/* Locate the entity corresponding to the bound subdev and store the
+	 * subdev pointer.
+	 */
+	list_for_each_entry(entity, &xdev->entities, list) {
+		if (entity->node != subdev->dev->of_node)
+			continue;
+
+		if (entity->subdev) {
+			dev_err(xdev->dev, "duplicate subdev for node %pOF\n",
+				entity->node);
+			return -EINVAL;
+		}
+
+		dev_dbg(xdev->dev, "subdev %s bound\n", subdev->name);
+		entity->entity = &subdev->entity;
+		entity->subdev = subdev;
+		return 0;
+	}
+
+	dev_err(xdev->dev, "no entity for subdev %s\n", subdev->name);
+	return -EINVAL;
+}
+
+static const struct v4l2_async_notifier_operations xvip_graph_notify_ops = {
+	.bound = xvip_graph_notify_bound,
+	.complete = xvip_graph_notify_complete,
+};
+
+static void xvip_graph_cleanup(struct xvip_m2m_dev *xdev)
+{
+	struct xvip_graph_entity *entityp;
+	struct xvip_graph_entity *entity;
+
+	v4l2_async_notifier_cleanup(&xdev->notifier);
+	v4l2_async_notifier_unregister(&xdev->notifier);
+
+	list_for_each_entry_safe(entity, entityp, &xdev->entities, list) {
+		of_node_put(entity->node);
+		list_del(&entity->list);
+	}
+}
+
+static int xvip_graph_init(struct xvip_m2m_dev *xdev)
+{
+	struct xvip_graph_entity *entity;
+	int ret;
+
+	/* Init the DMA channels. */
+	ret = xvip_m2m_dma_alloc_init(xdev);
+	if (ret < 0) {
+		dev_err(xdev->dev, "DMA initialization failed\n");
+		goto done;
+	}
+
+	/* Parse the graph to extract a list of subdevice DT nodes. */
+	ret = xvip_graph_parse(xdev);
+	if (ret < 0) {
+		dev_err(xdev->dev, "graph parsing failed\n");
+		goto done;
+	}
+	dev_dbg(xdev->dev, "Number of subdev = %d\n", xdev->num_subdevs);
+
+	if (!xdev->num_subdevs) {
+		dev_err(xdev->dev, "no subdev found in graph\n");
+		goto done;
+	}
+
+	/* Register the subdevices notifier. */
+	list_for_each_entry(entity, &xdev->entities, list) {
+		ret = v4l2_async_notifier_add_subdev(&xdev->notifier,
+						     &entity->asd);
+		if (ret)
+			goto done;
+	}
+
+	xdev->notifier.ops = &xvip_graph_notify_ops;
+
+	ret = v4l2_async_notifier_register(&xdev->v4l2_dev, &xdev->notifier);
+	if (ret < 0) {
+		dev_err(xdev->dev, "notifier registration failed\n");
+		goto done;
+	}
+
+	ret = 0;
+
+done:
+	if (ret < 0)
+		xvip_graph_cleanup(xdev);
+
+	return ret;
+}
+
+static int xvip_composite_remove(struct platform_device *pdev)
+{
+	struct xvip_m2m_dev *xdev = platform_get_drvdata(pdev);
+
+	xvip_graph_cleanup(xdev);
+	xvip_composite_v4l2_cleanup(xdev);
+
+	return 0;
+}
+
+static int xvip_m2m_probe(struct platform_device *pdev)
+{
+	struct xvip_m2m_dev *xdev = NULL;
+	int ret;
+
+	xdev = devm_kzalloc(&pdev->dev, sizeof(*xdev), GFP_KERNEL);
+	if (!xdev)
+		return -ENOMEM;
+
+	xdev->dev = &pdev->dev;
+	INIT_LIST_HEAD(&xdev->entities);
+	v4l2_async_notifier_init(&xdev->notifier);
+
+	ret = xvip_composite_v4l2_init(xdev);
+	if (ret)
+		return -EINVAL;
+
+	ret = xvip_graph_init(xdev);
+	if (ret < 0)
+		goto error;
+
+	ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
+	if (ret) {
+		dev_err(&pdev->dev, "dma_set_coherent_mask: %d\n", ret);
+		goto dma_cleanup;
+	}
+
+	platform_set_drvdata(pdev, xdev);
+
+	xdev->m2m_dev = v4l2_m2m_init(&xvip_m2m_ops);
+	if (IS_ERR(xdev->m2m_dev)) {
+		dev_err(xdev->dev, "Failed to init mem2mem device\n");
+		ret = PTR_ERR(xdev->m2m_dev);
+		goto dma_cleanup;
+	}
+
+	dev_info(xdev->dev, "mem2mem device registered\n");
+	return 0;
+
+dma_cleanup:
+	xvip_m2m_dma_deinit(xdev->dma);
+
+error:
+	v4l2_device_unregister(&xdev->v4l2_dev);
+	return ret;
+}
+
+static int xvip_m2m_remove(struct platform_device *pdev)
+{
+	xvip_composite_remove(pdev);
+	return 0;
+}
+
+static const struct of_device_id xvip_m2m_of_id_table[] = {
+	{ .compatible = "xlnx,mem2mem" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, xvip_m2m_of_id_table);
+
+static struct platform_driver xvip_m2m_driver = {
+	.driver = {
+		.name = XVIP_M2M_NAME,
+		.of_match_table = xvip_m2m_of_id_table,
+	},
+	.probe = xvip_m2m_probe,
+	.remove = xvip_m2m_remove,
+};
+
+module_platform_driver(xvip_m2m_driver);
+
+MODULE_AUTHOR("Xilinx Inc.");
+MODULE_DESCRIPTION("Xilinx V4L2 mem2mem driver");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/xilinx-multi-scaler-coeff.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/xilinx-multi-scaler-coeff.h
@@ -0,0 +1,574 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Xilinx Memory-to-Memory Video Multi-Scaler IP
+ *
+ * Copyright (C) 2018 Xilinx, Inc.
+ *
+ * Author: Suresh Gupta <sureshg@xilinx.com>
+ *
+ * The file contains the coefficients used by the Xilinx
+ * Video Multi Scaler Controller driver (xm2msc)
+ *
+ */
+
+#define XSCALER_MAX_PHASES	(64)
+#define XSCALER_MAX_TAPS	(12)
+
+#define XSCALER_TAPS_6		(6)
+#define XSCALER_TAPS_8		(8)
+#define XSCALER_TAPS_10		(10)
+#define XSCALER_TAPS_12		(12)
+
+/* Filter bank ID for various filter tap configurations */
+enum xm2mvsc_filter_bank_id {
+	FILTER_BANK_TAPS_6 = 0,
+	FILTER_BANK_TAPS_8,
+	FILTER_BANK_TAPS_10,
+	FILTER_BANK_TAPS_12,
+};
+
+/* H-scaler coefficients for 6, 8, 10 and 12 tap filters */
+static const short
+xhsc_coeff_taps6[XSCALER_MAX_PHASES][XSCALER_TAPS_6] = {
+	{  -132,   236,  3824,   236,  -132,    64, },
+	{  -116,   184,  3816,   292,  -144,    64, },
+	{  -100,   132,  3812,   348,  -160,    64, },
+	{   -88,    84,  3808,   404,  -176,    64, },
+	{   -72,    36,  3796,   464,  -192,    64, },
+	{   -60,    -8,  3780,   524,  -208,    68, },
+	{   -48,   -52,  3768,   588,  -228,    68, },
+	{   -32,   -96,  3748,   652,  -244,    68, },
+	{   -20,  -136,  3724,   716,  -260,    72, },
+	{    -8,  -172,  3696,   784,  -276,    72, },
+	{     0,  -208,  3676,   848,  -292,    72, },
+	{    12,  -244,  3640,   920,  -308,    76, },
+	{    20,  -276,  3612,   988,  -324,    76, },
+	{    32,  -304,  3568,  1060,  -340,    80, },
+	{    40,  -332,  3532,  1132,  -356,    80, },
+	{    48,  -360,  3492,  1204,  -372,    84, },
+	{    56,  -384,  3448,  1276,  -388,    88, },
+	{    64,  -408,  3404,  1352,  -404,    88, },
+	{    72,  -428,  3348,  1428,  -416,    92, },
+	{    76,  -448,  3308,  1500,  -432,    92, },
+	{    84,  -464,  3248,  1576,  -444,    96, },
+	{    88,  -480,  3200,  1652,  -460,    96, },
+	{    92,  -492,  3140,  1728,  -472,   100, },
+	{    96,  -504,  3080,  1804,  -484,   104, },
+	{   100,  -516,  3020,  1880,  -492,   104, },
+	{   104,  -524,  2956,  1960,  -504,   104, },
+	{   104,  -532,  2892,  2036,  -512,   108, },
+	{   108,  -540,  2832,  2108,  -520,   108, },
+	{   108,  -544,  2764,  2184,  -528,   112, },
+	{   112,  -544,  2688,  2260,  -532,   112, },
+	{   112,  -548,  2624,  2336,  -540,   112, },
+	{   112,  -548,  2556,  2408,  -544,   112, },
+	{   112,  -544,  2480,  2480,  -544,   112, },
+	{   112,  -544,  2408,  2556,  -548,   112, },
+	{   112,  -540,  2336,  2624,  -548,   112, },
+	{   112,  -532,  2260,  2688,  -544,   112, },
+	{   112,  -528,  2184,  2764,  -544,   108, },
+	{   108,  -520,  2108,  2832,  -540,   108, },
+	{   108,  -512,  2036,  2892,  -532,   104, },
+	{   104,  -504,  1960,  2956,  -524,   104, },
+	{   104,  -492,  1880,  3020,  -516,   100, },
+	{   104,  -484,  1804,  3080,  -504,    96, },
+	{   100,  -472,  1728,  3140,  -492,    92, },
+	{    96,  -460,  1652,  3200,  -480,    88, },
+	{    96,  -444,  1576,  3248,  -464,    84, },
+	{    92,  -432,  1500,  3308,  -448,    76, },
+	{    92,  -416,  1428,  3348,  -428,    72, },
+	{    88,  -404,  1352,  3404,  -408,    64, },
+	{    88,  -388,  1276,  3448,  -384,    56, },
+	{    84,  -372,  1204,  3492,  -360,    48, },
+	{    80,  -356,  1132,  3532,  -332,    40, },
+	{    80,  -340,  1060,  3568,  -304,    32, },
+	{    76,  -324,   988,  3612,  -276,    20, },
+	{    76,  -308,   920,  3640,  -244,    12, },
+	{    72,  -292,   848,  3676,  -208,     0, },
+	{    72,  -276,   784,  3696,  -172,    -8, },
+	{    72,  -260,   716,  3724,  -136,   -20, },
+	{    68,  -244,   652,  3748,   -96,   -32, },
+	{    68,  -228,   588,  3768,   -52,   -48, },
+	{    68,  -208,   524,  3780,    -8,   -60, },
+	{    64,  -192,   464,  3796,    36,   -72, },
+	{    64,  -176,   404,  3808,    84,   -88, },
+	{    64,  -160,   348,  3812,   132,  -100, },
+	{    64,  -144,   292,  3816,   184,  -116, }
+};
+
+static const short
+xhsc_coeff_taps8[XSCALER_MAX_PHASES][XSCALER_TAPS_8] = {
+	{-5, 309, 1023, 1445, 1034, 317, -3, -24, },
+	{-6, 300, 1011, 1445, 1045, 326, -1, -24, },
+	{-7, 291, 1000, 1444, 1056, 336, 0, -24, },
+	{-9, 282, 988, 1444, 1067, 345, 2, -24, },
+	{-10, 274, 977, 1443, 1078, 354, 4, -24, },
+	{-11, 266, 965, 1441, 1089, 364, 6, -24, },
+	{-12, 258, 953, 1440, 1100, 373, 8, -24, },
+	{-13, 250, 942, 1438, 1110, 383, 10, -24, },
+	{-14, 242, 930, 1437, 1121, 393, 12, -24, },
+	{-15, 234, 918, 1434, 1131, 403, 14, -24, },
+	{-16, 226, 906, 1432, 1142, 413, 17, -24, },
+	{-17, 219, 894, 1430, 1152, 423, 19, -24, },
+	{-17, 211, 882, 1427, 1162, 433, 22, -24, },
+	{-18, 204, 870, 1424, 1172, 443, 24, -24, },
+	{-19, 197, 858, 1420, 1182, 454, 27, -24, },
+	{-19, 190, 846, 1417, 1191, 464, 30, -24, },
+	{-20, 183, 834, 1413, 1201, 475, 33, -24, },
+	{-20, 176, 822, 1409, 1210, 486, 36, -24, },
+	{-21, 170, 810, 1405, 1220, 497, 39, -24, },
+	{-21, 163, 798, 1401, 1229, 507, 42, -24, },
+	{-22, 157, 786, 1396, 1238, 518, 46, -24, },
+	{-22, 151, 774, 1392, 1247, 529, 49, -24, },
+	{-22, 144, 762, 1387, 1255, 540, 53, -24, },
+	{-23, 139, 750, 1382, 1264, 552, 57, -24, },
+	{-23, 133, 738, 1376, 1272, 563, 60, -24, },
+	{-23, 127, 726, 1371, 1280, 574, 64, -24, },
+	{-23, 121, 714, 1365, 1288, 586, 69, -24, },
+	{-23, 116, 703, 1359, 1296, 597, 73, -24, },
+	{-24, 111, 691, 1353, 1304, 609, 77, -24, },
+	{-24, 105, 679, 1346, 1312, 620, 81, -24, },
+	{-24, 100, 667, 1340, 1319, 632, 86, -24, },
+	{-24, 96, 655, 1333, 1326, 644, 91, -24, },
+	{-24, 91, 644, 1326, 1333, 655, 96, -24, },
+	{-24, 86, 632, 1319, 1340, 667, 100, -24, },
+	{-24, 81, 620, 1312, 1346, 679, 105, -24, },
+	{-24, 77, 609, 1304, 1353, 691, 111, -24, },
+	{-24, 73, 597, 1296, 1359, 703, 116, -23, },
+	{-24, 69, 586, 1288, 1365, 714, 121, -23, },
+	{-24, 64, 574, 1280, 1371, 726, 127, -23, },
+	{-24, 60, 563, 1272, 1376, 738, 133, -23, },
+	{-24, 57, 552, 1264, 1382, 750, 139, -23, },
+	{-24, 53, 540, 1255, 1387, 762, 144, -22, },
+	{-24, 49, 529, 1247, 1392, 774, 151, -22, },
+	{-24, 46, 518, 1238, 1396, 786, 157, -22, },
+	{-24, 42, 507, 1229, 1401, 798, 163, -21, },
+	{-24, 39, 497, 1220, 1405, 810, 170, -21, },
+	{-24, 36, 486, 1210, 1409, 822, 176, -20, },
+	{-24, 33, 475, 1201, 1413, 834, 183, -20, },
+	{-24, 30, 464, 1191, 1417, 846, 190, -19, },
+	{-24, 27, 454, 1182, 1420, 858, 197, -19, },
+	{-24, 24, 443, 1172, 1424, 870, 204, -18, },
+	{-24, 22, 433, 1162, 1427, 882, 211, -17, },
+	{-24, 19, 423, 1152, 1430, 894, 219, -17, },
+	{-24, 17, 413, 1142, 1432, 906, 226, -16, },
+	{-24, 14, 403, 1131, 1434, 918, 234, -15, },
+	{-24, 12, 393, 1121, 1437, 930, 242, -14, },
+	{-24, 10, 383, 1110, 1438, 942, 250, -13, },
+	{-24, 8, 373, 1100, 1440, 953, 258, -12, },
+	{-24, 6, 364, 1089, 1441, 965, 266, -11, },
+	{-24, 4, 354, 1078, 1443, 977, 274, -10, },
+	{-24, 2, 345, 1067, 1444, 988, 282, -9, },
+	{-24, 0, 336, 1056, 1444, 1000, 291, -7, },
+	{-24, -1, 326, 1045, 1445, 1011, 300, -6, },
+	{-24, -3, 317, 1034, 1445, 1023, 309, -5, },
+};
+
+static const short
+xhsc_coeff_taps10[XSCALER_MAX_PHASES][XSCALER_TAPS_10] = {
+	{59, 224, 507, 790, 911, 793, 512, 227, 61, 13, },
+	{58, 220, 502, 786, 911, 797, 516, 231, 62, 13, },
+	{56, 216, 497, 783, 911, 800, 521, 235, 64, 13, },
+	{55, 213, 492, 779, 910, 804, 526, 238, 65, 13, },
+	{54, 209, 487, 775, 910, 807, 531, 242, 67, 14, },
+	{52, 206, 482, 772, 910, 810, 536, 246, 69, 14, },
+	{51, 202, 477, 768, 909, 813, 541, 250, 70, 14, },
+	{50, 199, 473, 764, 909, 817, 545, 254, 72, 14, },
+	{48, 195, 468, 760, 908, 820, 550, 258, 74, 15, },
+	{47, 192, 463, 756, 908, 823, 555, 262, 76, 15, },
+	{46, 188, 458, 752, 907, 826, 560, 266, 78, 15, },
+	{45, 185, 453, 748, 906, 829, 565, 270, 79, 16, },
+	{44, 182, 448, 744, 906, 832, 569, 274, 81, 16, },
+	{42, 179, 444, 740, 905, 835, 574, 278, 83, 16, },
+	{41, 175, 439, 736, 904, 837, 579, 282, 85, 17, },
+	{40, 172, 434, 732, 903, 840, 584, 286, 87, 17, },
+	{39, 169, 429, 728, 902, 843, 589, 290, 89, 18, },
+	{38, 166, 425, 724, 901, 846, 593, 294, 91, 18, },
+	{37, 163, 420, 720, 900, 848, 598, 298, 93, 18, },
+	{36, 160, 415, 716, 899, 851, 603, 302, 95, 19, },
+	{35, 157, 410, 711, 897, 854, 608, 307, 98, 19, },
+	{34, 154, 406, 707, 896, 856, 612, 311, 100, 20, },
+	{33, 151, 401, 703, 895, 859, 617, 315, 102, 20, },
+	{33, 148, 396, 698, 893, 861, 622, 320, 104, 21, },
+	{32, 145, 392, 694, 892, 863, 626, 324, 107, 21, },
+	{31, 142, 387, 690, 890, 866, 631, 328, 109, 22, },
+	{30, 140, 382, 685, 889, 868, 636, 333, 111, 23, },
+	{29, 137, 378, 681, 887, 870, 640, 337, 114, 23, },
+	{28, 134, 373, 677, 886, 872, 645, 342, 116, 24, },
+	{28, 131, 369, 672, 884, 874, 649, 346, 119, 24, },
+	{27, 129, 364, 668, 882, 876, 654, 350, 121, 25, },
+	{26, 126, 359, 663, 880, 878, 659, 355, 124, 26, },
+	{26, 124, 355, 659, 878, 880, 663, 359, 126, 26, },
+	{25, 121, 350, 654, 876, 882, 668, 364, 129, 27, },
+	{24, 119, 346, 649, 874, 884, 672, 369, 131, 28, },
+	{24, 116, 342, 645, 872, 886, 677, 373, 134, 28, },
+	{23, 114, 337, 640, 870, 887, 681, 378, 137, 29, },
+	{23, 111, 333, 636, 868, 889, 685, 382, 140, 30, },
+	{22, 109, 328, 631, 866, 890, 690, 387, 142, 31, },
+	{21, 107, 324, 626, 863, 892, 694, 392, 145, 32, },
+	{21, 104, 320, 622, 861, 893, 698, 396, 148, 33, },
+	{20, 102, 315, 617, 859, 895, 703, 401, 151, 33, },
+	{20, 100, 311, 612, 856, 896, 707, 406, 154, 34, },
+	{19, 98, 307, 608, 854, 897, 711, 410, 157, 35, },
+	{19, 95, 302, 603, 851, 899, 716, 415, 160, 36, },
+	{18, 93, 298, 598, 848, 900, 720, 420, 163, 37, },
+	{18, 91, 294, 593, 846, 901, 724, 425, 166, 38, },
+	{18, 89, 290, 589, 843, 902, 728, 429, 169, 39, },
+	{17, 87, 286, 584, 840, 903, 732, 434, 172, 40, },
+	{17, 85, 282, 579, 837, 904, 736, 439, 175, 41, },
+	{16, 83, 278, 574, 835, 905, 740, 444, 179, 42, },
+	{16, 81, 274, 569, 832, 906, 744, 448, 182, 44, },
+	{16, 79, 270, 565, 829, 906, 748, 453, 185, 45, },
+	{15, 78, 266, 560, 826, 907, 752, 458, 188, 46, },
+	{15, 76, 262, 555, 823, 908, 756, 463, 192, 47, },
+	{15, 74, 258, 550, 820, 908, 760, 468, 195, 48, },
+	{14, 72, 254, 545, 817, 909, 764, 473, 199, 50, },
+	{14, 70, 250, 541, 813, 909, 768, 477, 202, 51, },
+	{14, 69, 246, 536, 810, 910, 772, 482, 206, 52, },
+	{14, 67, 242, 531, 807, 910, 775, 487, 209, 54, },
+	{13, 65, 238, 526, 804, 910, 779, 492, 213, 55, },
+	{13, 64, 235, 521, 800, 911, 783, 497, 216, 56, },
+	{13, 62, 231, 516, 797, 911, 786, 502, 220, 58, },
+	{13, 61, 227, 512, 793, 911, 790, 507, 224, 59, },
+};
+
+static const short
+xhsc_coeff_taps12[XSCALER_MAX_PHASES][XSCALER_TAPS_12] = {
+	{48, 143, 307, 504, 667, 730, 669, 507, 310, 145, 49, 18, },
+	{47, 141, 304, 501, 665, 730, 670, 510, 313, 147, 50, 18, },
+	{46, 138, 301, 498, 663, 730, 672, 513, 316, 149, 51, 18, },
+	{45, 136, 298, 495, 661, 730, 674, 516, 319, 151, 52, 18, },
+	{44, 134, 295, 492, 659, 730, 676, 519, 322, 153, 53, 18, },
+	{44, 132, 292, 489, 657, 730, 677, 522, 325, 155, 54, 18, },
+	{43, 130, 289, 486, 655, 729, 679, 525, 328, 157, 55, 19, },
+	{42, 129, 287, 483, 653, 729, 681, 528, 331, 160, 56, 19, },
+	{41, 127, 284, 480, 651, 729, 683, 531, 334, 162, 57, 19, },
+	{40, 125, 281, 477, 648, 729, 684, 534, 337, 164, 58, 19, },
+	{40, 123, 278, 474, 646, 728, 686, 537, 340, 166, 59, 20, },
+	{39, 121, 275, 471, 644, 728, 687, 539, 343, 169, 60, 20, },
+	{38, 119, 272, 468, 642, 727, 689, 542, 346, 171, 61, 20, },
+	{37, 117, 269, 465, 640, 727, 690, 545, 349, 173, 62, 20, },
+	{37, 115, 266, 461, 638, 727, 692, 548, 353, 175, 63, 21, },
+	{36, 114, 264, 458, 635, 726, 693, 551, 356, 178, 65, 21, },
+	{35, 112, 261, 455, 633, 726, 695, 554, 359, 180, 66, 21, },
+	{35, 110, 258, 452, 631, 725, 696, 556, 362, 183, 67, 21, },
+	{34, 108, 255, 449, 628, 724, 698, 559, 365, 185, 68, 22, },
+	{33, 107, 252, 446, 626, 724, 699, 562, 368, 187, 69, 22, },
+	{33, 105, 250, 443, 624, 723, 700, 565, 371, 190, 71, 22, },
+	{32, 103, 247, 440, 621, 723, 702, 567, 374, 192, 72, 23, },
+	{32, 101, 244, 437, 619, 722, 703, 570, 377, 195, 73, 23, },
+	{31, 100, 241, 433, 617, 721, 704, 573, 380, 197, 75, 23, },
+	{31, 98, 239, 430, 614, 720, 705, 576, 383, 200, 76, 24, },
+	{30, 97, 236, 427, 612, 720, 707, 578, 387, 202, 77, 24, },
+	{29, 95, 233, 424, 609, 719, 708, 581, 390, 205, 79, 24, },
+	{29, 93, 231, 421, 607, 718, 709, 584, 393, 207, 80, 25, },
+	{28, 92, 228, 418, 604, 717, 710, 586, 396, 210, 81, 25, },
+	{28, 90, 225, 415, 602, 716, 711, 589, 399, 212, 83, 26, },
+	{27, 89, 223, 412, 599, 715, 712, 591, 402, 215, 84, 26, },
+	{27, 87, 220, 408, 597, 714, 713, 594, 405, 217, 86, 27, },
+	{27, 86, 217, 405, 594, 713, 714, 597, 408, 220, 87, 27, },
+	{26, 84, 215, 402, 591, 712, 715, 599, 412, 223, 89, 27, },
+	{26, 83, 212, 399, 589, 711, 716, 602, 415, 225, 90, 28, },
+	{25, 81, 210, 396, 586, 710, 717, 604, 418, 228, 92, 28, },
+	{25, 80, 207, 393, 584, 709, 718, 607, 421, 231, 93, 29, },
+	{24, 79, 205, 390, 581, 708, 719, 609, 424, 233, 95, 29, },
+	{24, 77, 202, 387, 578, 707, 720, 612, 427, 236, 97, 30, },
+	{24, 76, 200, 383, 576, 705, 720, 614, 430, 239, 98, 31, },
+	{23, 75, 197, 380, 573, 704, 721, 617, 433, 241, 100, 31, },
+	{23, 73, 195, 377, 570, 703, 722, 619, 437, 244, 101, 32, },
+	{23, 72, 192, 374, 567, 702, 723, 621, 440, 247, 103, 32, },
+	{22, 71, 190, 371, 565, 700, 723, 624, 443, 250, 105, 33, },
+	{22, 69, 187, 368, 562, 699, 724, 626, 446, 252, 107, 33, },
+	{22, 68, 185, 365, 559, 698, 724, 628, 449, 255, 108, 34, },
+	{21, 67, 183, 362, 556, 696, 725, 631, 452, 258, 110, 35, },
+	{21, 66, 180, 359, 554, 695, 726, 633, 455, 261, 112, 35, },
+	{21, 65, 178, 356, 551, 693, 726, 635, 458, 264, 114, 36, },
+	{21, 63, 175, 353, 548, 692, 727, 638, 461, 266, 115, 37, },
+	{20, 62, 173, 349, 545, 690, 727, 640, 465, 269, 117, 37, },
+	{20, 61, 171, 346, 542, 689, 727, 642, 468, 272, 119, 38, },
+	{20, 60, 169, 343, 539, 687, 728, 644, 471, 275, 121, 39, },
+	{20, 59, 166, 340, 537, 686, 728, 646, 474, 278, 123, 40, },
+	{19, 58, 164, 337, 534, 684, 729, 648, 477, 281, 125, 40, },
+	{19, 57, 162, 334, 531, 683, 729, 651, 480, 284, 127, 41, },
+	{19, 56, 160, 331, 528, 681, 729, 653, 483, 287, 129, 42, },
+	{19, 55, 157, 328, 525, 679, 729, 655, 486, 289, 130, 43, },
+	{18, 54, 155, 325, 522, 677, 730, 657, 489, 292, 132, 44, },
+	{18, 53, 153, 322, 519, 676, 730, 659, 492, 295, 134, 44, },
+	{18, 52, 151, 319, 516, 674, 730, 661, 495, 298, 136, 45, },
+	{18, 51, 149, 316, 513, 672, 730, 663, 498, 301, 138, 46, },
+	{18, 50, 147, 313, 510, 670, 730, 665, 501, 304, 141, 47, },
+	{18, 49, 145, 310, 507, 669, 730, 667, 504, 307, 143, 48, },
+};
+
+/* V-scaler coefficients for 6, 8, 10 and 12 tap filters */
+static const short
+xvsc_coeff_taps6[XSCALER_MAX_PHASES][XSCALER_TAPS_6] = {
+	{-132, 236, 3824, 236, -132, 64, },
+	{-116, 184, 3816, 292, -144, 64, },
+	{-100, 132, 3812, 348, -160, 64, },
+	{-88, 84, 3808, 404, -176, 64, },
+	{-72, 36, 3796, 464, -192, 64, },
+	{-60, -8, 3780, 524, -208, 68, },
+	{-48, -52, 3768, 588, -228, 68, },
+	{-32, -96, 3748, 652, -244, 68, },
+	{-20, -136, 3724, 716, -260, 72, },
+	{-8, -172, 3696, 784, -276, 72, },
+	{0, -208, 3676, 848, -292, 72, },
+	{12, -244, 3640, 920, -308, 76, },
+	{20, -276, 3612, 988, -324, 76, },
+	{32, -304, 3568, 1060, -340, 80, },
+	{40, -332, 3532, 1132, -356, 80, },
+	{48, -360, 3492, 1204, -372, 84, },
+	{56, -384, 3448, 1276, -388, 88, },
+	{64, -408, 3404, 1352, -404, 88, },
+	{72, -428, 3348, 1428, -416, 92, },
+	{76, -448, 3308, 1500, -432, 92, },
+	{84, -464, 3248, 1576, -444, 96, },
+	{88, -480, 3200, 1652, -460, 96, },
+	{92, -492, 3140, 1728, -472, 100, },
+	{96, -504, 3080, 1804, -484, 104, },
+	{100, -516, 3020, 1880, -492, 104, },
+	{104, -524, 2956, 1960, -504, 104, },
+	{104, -532, 2892, 2036, -512, 108, },
+	{108, -540, 2832, 2108, -520, 108, },
+	{108, -544, 2764, 2184, -528, 112, },
+	{112, -544, 2688, 2260, -532, 112, },
+	{112, -548, 2624, 2336, -540, 112, },
+	{112, -548, 2556, 2408, -544, 112, },
+	{112, -544, 2480, 2480, -544, 112, },
+	{112, -544, 2408, 2556, -548, 112, },
+	{112, -540, 2336, 2624, -548, 112, },
+	{112, -532, 2260, 2688, -544, 112, },
+	{112, -528, 2184, 2764, -544, 108, },
+	{108, -520, 2108, 2832, -540, 108, },
+	{108, -512, 2036, 2892, -532, 104, },
+	{104, -504, 1960, 2956, -524, 104, },
+	{104, -492, 1880, 3020, -516, 100, },
+	{104, -484, 1804, 3080, -504, 96, },
+	{100, -472, 1728, 3140, -492, 92, },
+	{ 96, -460, 1652, 3200, -480, 88, },
+	{ 96, -444, 1576, 3248, -464, 84, },
+	{ 92, -432, 1500, 3308, -448, 76, },
+	{ 92, -416, 1428, 3348, -428, 72, },
+	{ 88, -404, 1352, 3404, -408, 64, },
+	{ 88, -388, 1276, 3448, -384, 56, },
+	{ 84, -372, 1204, 3492, -360, 48, },
+	{ 80, -356, 1132, 3532, -332, 40, },
+	{ 80, -340, 1060, 3568, -304, 32, },
+	{ 76, -324, 988, 3612, -276, 20, },
+	{ 76, -308, 920, 3640, -244, 12, },
+	{ 72, -292, 848, 3676, -208, 0, },
+	{ 72, -276, 784, 3696, -172, -8, },
+	{ 72, -260, 716, 3724, -136, -20, },
+	{ 68, -244, 652, 3748, -96, -32, },
+	{ 68, -228, 588, 3768, -52, -48, },
+	{ 68, -208, 524, 3780, -8, -60, },
+	{ 64, -192, 464, 3796, 36, -72, },
+	{ 64, -176, 404, 3808, 84, -88, },
+	{ 64, -160, 348, 3812, 132, -100, },
+	{ 64, -144, 292, 3816, 184, -116, }
+};
+
+static const short
+xvsc_coeff_taps8[XSCALER_MAX_PHASES][XSCALER_TAPS_8] = {
+	{-5, 309, 1023, 1445, 1034, 317, -3, -24, },
+	{-6, 300, 1011, 1445, 1045, 326, -1, -24, },
+	{-7, 291, 1000, 1444, 1056, 336, 0, -24, },
+	{-9, 282, 988, 1444, 1067, 345, 2, -24, },
+	{-10, 274, 977, 1443, 1078, 354, 4, -24, },
+	{-11, 266, 965, 1441, 1089, 364, 6, -24, },
+	{-12, 258, 953, 1440, 1100, 373, 8, -24, },
+	{-13, 250, 942, 1438, 1110, 383, 10, -24, },
+	{-14, 242, 930, 1437, 1121, 393, 12, -24, },
+	{-15, 234, 918, 1434, 1131, 403, 14, -24, },
+	{-16, 226, 906, 1432, 1142, 413, 17, -24, },
+	{-17, 219, 894, 1430, 1152, 423, 19, -24, },
+	{-17, 211, 882, 1427, 1162, 433, 22, -24, },
+	{-18, 204, 870, 1424, 1172, 443, 24, -24, },
+	{-19, 197, 858, 1420, 1182, 454, 27, -24, },
+	{-19, 190, 846, 1417, 1191, 464, 30, -24, },
+	{-20, 183, 834, 1413, 1201, 475, 33, -24, },
+	{-20, 176, 822, 1409, 1210, 486, 36, -24, },
+	{-21, 170, 810, 1405, 1220, 497, 39, -24, },
+	{-21, 163, 798, 1401, 1229, 507, 42, -24, },
+	{-22, 157, 786, 1396, 1238, 518, 46, -24, },
+	{-22, 151, 774, 1392, 1247, 529, 49, -24, },
+	{-22, 144, 762, 1387, 1255, 540, 53, -24, },
+	{-23, 139, 750, 1382, 1264, 552, 57, -24, },
+	{-23, 133, 738, 1376, 1272, 563, 60, -24, },
+	{-23, 127, 726, 1371, 1280, 574, 64, -24, },
+	{-23, 121, 714, 1365, 1288, 586, 69, -24, },
+	{-23, 116, 703, 1359, 1296, 597, 73, -24, },
+	{-24, 111, 691, 1353, 1304, 609, 77, -24, },
+	{-24, 105, 679, 1346, 1312, 620, 81, -24, },
+	{-24, 100, 667, 1340, 1319, 632, 86, -24, },
+	{-24, 96, 655, 1333, 1326, 644, 91, -24, },
+	{-24, 91, 644, 1326, 1333, 655, 96, -24, },
+	{-24, 86, 632, 1319, 1340, 667, 100, -24, },
+	{-24, 81, 620, 1312, 1346, 679, 105, -24, },
+	{-24, 77, 609, 1304, 1353, 691, 111, -24, },
+	{-24, 73, 597, 1296, 1359, 703, 116, -23, },
+	{-24, 69, 586, 1288, 1365, 714, 121, -23, },
+	{-24, 64, 574, 1280, 1371, 726, 127, -23, },
+	{-24, 60, 563, 1272, 1376, 738, 133, -23, },
+	{-24, 57, 552, 1264, 1382, 750, 139, -23, },
+	{-24, 53, 540, 1255, 1387, 762, 144, -22, },
+	{-24, 49, 529, 1247, 1392, 774, 151, -22, },
+	{-24, 46, 518, 1238, 1396, 786, 157, -22, },
+	{-24, 42, 507, 1229, 1401, 798, 163, -21, },
+	{-24, 39, 497, 1220, 1405, 810, 170, -21, },
+	{-24, 36, 486, 1210, 1409, 822, 176, -20, },
+	{-24, 33, 475, 1201, 1413, 834, 183, -20, },
+	{-24, 30, 464, 1191, 1417, 846, 190, -19, },
+	{-24, 27, 454, 1182, 1420, 858, 197, -19, },
+	{-24, 24, 443, 1172, 1424, 870, 204, -18, },
+	{-24, 22, 433, 1162, 1427, 882, 211, -17, },
+	{-24, 19, 423, 1152, 1430, 894, 219, -17, },
+	{-24, 17, 413, 1142, 1432, 906, 226, -16, },
+	{-24, 14, 403, 1131, 1434, 918, 234, -15, },
+	{-24, 12, 393, 1121, 1437, 930, 242, -14, },
+	{-24, 10, 383, 1110, 1438, 942, 250, -13, },
+	{-24, 8, 373, 1100, 1440, 953, 258, -12, },
+	{-24, 6, 364, 1089, 1441, 965, 266, -11, },
+	{-24, 4, 354, 1078, 1443, 977, 274, -10, },
+	{-24, 2, 345, 1067, 1444, 988, 282, -9, },
+	{-24, 0, 336, 1056, 1444, 1000, 291, -7, },
+	{-24, -1, 326, 1045, 1445, 1011, 300, -6, },
+	{-24, -3, 317, 1034, 1445, 1023, 309, -5, },
+};
+
+static const short
+xvsc_coeff_taps10[XSCALER_MAX_PHASES][XSCALER_TAPS_10] = {
+	{59, 224, 507, 790, 911, 793, 512, 227, 61, 13, },
+	{58, 220, 502, 786, 911, 797, 516, 231, 62, 13, },
+	{56, 216, 497, 783, 911, 800, 521, 235, 64, 13, },
+	{55, 213, 492, 779, 910, 804, 526, 238, 65, 13, },
+	{54, 209, 487, 775, 910, 807, 531, 242, 67, 14, },
+	{52, 206, 482, 772, 910, 810, 536, 246, 69, 14, },
+	{51, 202, 477, 768, 909, 813, 541, 250, 70, 14, },
+	{50, 199, 473, 764, 909, 817, 545, 254, 72, 14, },
+	{48, 195, 468, 760, 908, 820, 550, 258, 74, 15, },
+	{47, 192, 463, 756, 908, 823, 555, 262, 76, 15, },
+	{46, 188, 458, 752, 907, 826, 560, 266, 78, 15, },
+	{45, 185, 453, 748, 906, 829, 565, 270, 79, 16, },
+	{44, 182, 448, 744, 906, 832, 569, 274, 81, 16, },
+	{42, 179, 444, 740, 905, 835, 574, 278, 83, 16, },
+	{41, 175, 439, 736, 904, 837, 579, 282, 85, 17, },
+	{40, 172, 434, 732, 903, 840, 584, 286, 87, 17, },
+	{39, 169, 429, 728, 902, 843, 589, 290, 89, 18, },
+	{38, 166, 425, 724, 901, 846, 593, 294, 91, 18, },
+	{37, 163, 420, 720, 900, 848, 598, 298, 93, 18, },
+	{36, 160, 415, 716, 899, 851, 603, 302, 95, 19, },
+	{35, 157, 410, 711, 897, 854, 608, 307, 98, 19, },
+	{34, 154, 406, 707, 896, 856, 612, 311, 100, 20, },
+	{33, 151, 401, 703, 895, 859, 617, 315, 102, 20, },
+	{33, 148, 396, 698, 893, 861, 622, 320, 104, 21, },
+	{32, 145, 392, 694, 892, 863, 626, 324, 107, 21, },
+	{31, 142, 387, 690, 890, 866, 631, 328, 109, 22, },
+	{30, 140, 382, 685, 889, 868, 636, 333, 111, 23, },
+	{29, 137, 378, 681, 887, 870, 640, 337, 114, 23, },
+	{28, 134, 373, 677, 886, 872, 645, 342, 116, 24, },
+	{28, 131, 369, 672, 884, 874, 649, 346, 119, 24, },
+	{27, 129, 364, 668, 882, 876, 654, 350, 121, 25, },
+	{26, 126, 359, 663, 880, 878, 659, 355, 124, 26, },
+	{26, 124, 355, 659, 878, 880, 663, 359, 126, 26, },
+	{25, 121, 350, 654, 876, 882, 668, 364, 129, 27, },
+	{24, 119, 346, 649, 874, 884, 672, 369, 131, 28, },
+	{24, 116, 342, 645, 872, 886, 677, 373, 134, 28, },
+	{23, 114, 337, 640, 870, 887, 681, 378, 137, 29, },
+	{23, 111, 333, 636, 868, 889, 685, 382, 140, 30, },
+	{22, 109, 328, 631, 866, 890, 690, 387, 142, 31, },
+	{21, 107, 324, 626, 863, 892, 694, 392, 145, 32, },
+	{21, 104, 320, 622, 861, 893, 698, 396, 148, 33, },
+	{20, 102, 315, 617, 859, 895, 703, 401, 151, 33, },
+	{20, 100, 311, 612, 856, 896, 707, 406, 154, 34, },
+	{19, 98, 307, 608, 854, 897, 711, 410, 157, 35, },
+	{19, 95, 302, 603, 851, 899, 716, 415, 160, 36, },
+	{18, 93, 298, 598, 848, 900, 720, 420, 163, 37, },
+	{18, 91, 294, 593, 846, 901, 724, 425, 166, 38, },
+	{18, 89, 290, 589, 843, 902, 728, 429, 169, 39, },
+	{17, 87, 286, 584, 840, 903, 732, 434, 172, 40, },
+	{17, 85, 282, 579, 837, 904, 736, 439, 175, 41, },
+	{16, 83, 278, 574, 835, 905, 740, 444, 179, 42, },
+	{16, 81, 274, 569, 832, 906, 744, 448, 182, 44, },
+	{16, 79, 270, 565, 829, 906, 748, 453, 185, 45, },
+	{15, 78, 266, 560, 826, 907, 752, 458, 188, 46, },
+	{15, 76, 262, 555, 823, 908, 756, 463, 192, 47, },
+	{15, 74, 258, 550, 820, 908, 760, 468, 195, 48, },
+	{14, 72, 254, 545, 817, 909, 764, 473, 199, 50, },
+	{14, 70, 250, 541, 813, 909, 768, 477, 202, 51, },
+	{14, 69, 246, 536, 810, 910, 772, 482, 206, 52, },
+	{14, 67, 242, 531, 807, 910, 775, 487, 209, 54, },
+	{13, 65, 238, 526, 804, 910, 779, 492, 213, 55, },
+	{13, 64, 235, 521, 800, 911, 783, 497, 216, 56, },
+	{13, 62, 231, 516, 797, 911, 786, 502, 220, 58, },
+	{13, 61, 227, 512, 793, 911, 790, 507, 224, 59, },
+};
+
+static const short
+xvsc_coeff_taps12[XSCALER_MAX_PHASES][XSCALER_TAPS_12] = {
+	{48, 143, 307, 504, 667, 730, 669, 507, 310, 145, 49, 18, },
+	{47, 141, 304, 501, 665, 730, 670, 510, 313, 147, 50, 18, },
+	{46, 138, 301, 498, 663, 730, 672, 513, 316, 149, 51, 18, },
+	{45, 136, 298, 495, 661, 730, 674, 516, 319, 151, 52, 18, },
+	{44, 134, 295, 492, 659, 730, 676, 519, 322, 153, 53, 18, },
+	{44, 132, 292, 489, 657, 730, 677, 522, 325, 155, 54, 18, },
+	{43, 130, 289, 486, 655, 729, 679, 525, 328, 157, 55, 19, },
+	{42, 129, 287, 483, 653, 729, 681, 528, 331, 160, 56, 19, },
+	{41, 127, 284, 480, 651, 729, 683, 531, 334, 162, 57, 19, },
+	{40, 125, 281, 477, 648, 729, 684, 534, 337, 164, 58, 19, },
+	{40, 123, 278, 474, 646, 728, 686, 537, 340, 166, 59, 20, },
+	{39, 121, 275, 471, 644, 728, 687, 539, 343, 169, 60, 20, },
+	{38, 119, 272, 468, 642, 727, 689, 542, 346, 171, 61, 20, },
+	{37, 117, 269, 465, 640, 727, 690, 545, 349, 173, 62, 20, },
+	{37, 115, 266, 461, 638, 727, 692, 548, 353, 175, 63, 21, },
+	{36, 114, 264, 458, 635, 726, 693, 551, 356, 178, 65, 21, },
+	{35, 112, 261, 455, 633, 726, 695, 554, 359, 180, 66, 21, },
+	{35, 110, 258, 452, 631, 725, 696, 556, 362, 183, 67, 21, },
+	{34, 108, 255, 449, 628, 724, 698, 559, 365, 185, 68, 22, },
+	{33, 107, 252, 446, 626, 724, 699, 562, 368, 187, 69, 22, },
+	{33, 105, 250, 443, 624, 723, 700, 565, 371, 190, 71, 22, },
+	{32, 103, 247, 440, 621, 723, 702, 567, 374, 192, 72, 23, },
+	{32, 101, 244, 437, 619, 722, 703, 570, 377, 195, 73, 23, },
+	{31, 100, 241, 433, 617, 721, 704, 573, 380, 197, 75, 23, },
+	{31, 98, 239, 430, 614, 720, 705, 576, 383, 200, 76, 24, },
+	{30, 97, 236, 427, 612, 720, 707, 578, 387, 202, 77, 24, },
+	{29, 95, 233, 424, 609, 719, 708, 581, 390, 205, 79, 24, },
+	{29, 93, 231, 421, 607, 718, 709, 584, 393, 207, 80, 25, },
+	{28, 92, 228, 418, 604, 717, 710, 586, 396, 210, 81, 25, },
+	{28, 90, 225, 415, 602, 716, 711, 589, 399, 212, 83, 26, },
+	{27, 89, 223, 412, 599, 715, 712, 591, 402, 215, 84, 26, },
+	{27, 87, 220, 408, 597, 714, 713, 594, 405, 217, 86, 27, },
+	{27, 86, 217, 405, 594, 713, 714, 597, 408, 220, 87, 27, },
+	{26, 84, 215, 402, 591, 712, 715, 599, 412, 223, 89, 27, },
+	{26, 83, 212, 399, 589, 711, 716, 602, 415, 225, 90, 28, },
+	{25, 81, 210, 396, 586, 710, 717, 604, 418, 228, 92, 28, },
+	{25, 80, 207, 393, 584, 709, 718, 607, 421, 231, 93, 29, },
+	{24, 79, 205, 390, 581, 708, 719, 609, 424, 233, 95, 29, },
+	{24, 77, 202, 387, 578, 707, 720, 612, 427, 236, 97, 30, },
+	{24, 76, 200, 383, 576, 705, 720, 614, 430, 239, 98, 31, },
+	{23, 75, 197, 380, 573, 704, 721, 617, 433, 241, 100, 31, },
+	{23, 73, 195, 377, 570, 703, 722, 619, 437, 244, 101, 32, },
+	{23, 72, 192, 374, 567, 702, 723, 621, 440, 247, 103, 32, },
+	{22, 71, 190, 371, 565, 700, 723, 624, 443, 250, 105, 33, },
+	{22, 69, 187, 368, 562, 699, 724, 626, 446, 252, 107, 33, },
+	{22, 68, 185, 365, 559, 698, 724, 628, 449, 255, 108, 34, },
+	{21, 67, 183, 362, 556, 696, 725, 631, 452, 258, 110, 35, },
+	{21, 66, 180, 359, 554, 695, 726, 633, 455, 261, 112, 35, },
+	{21, 65, 178, 356, 551, 693, 726, 635, 458, 264, 114, 36, },
+	{21, 63, 175, 353, 548, 692, 727, 638, 461, 266, 115, 37, },
+	{20, 62, 173, 349, 545, 690, 727, 640, 465, 269, 117, 37, },
+	{20, 61, 171, 346, 542, 689, 727, 642, 468, 272, 119, 38, },
+	{20, 60, 169, 343, 539, 687, 728, 644, 471, 275, 121, 39, },
+	{20, 59, 166, 340, 537, 686, 728, 646, 474, 278, 123, 40, },
+	{19, 58, 164, 337, 534, 684, 729, 648, 477, 281, 125, 40, },
+	{19, 57, 162, 334, 531, 683, 729, 651, 480, 284, 127, 41, },
+	{19, 56, 160, 331, 528, 681, 729, 653, 483, 287, 129, 42, },
+	{19, 55, 157, 328, 525, 679, 729, 655, 486, 289, 130, 43, },
+	{18, 54, 155, 325, 522, 677, 730, 657, 489, 292, 132, 44, },
+	{18, 53, 153, 322, 519, 676, 730, 659, 492, 295, 134, 44, },
+	{18, 52, 151, 319, 516, 674, 730, 661, 495, 298, 136, 45, },
+	{18, 51, 149, 316, 513, 672, 730, 663, 498, 301, 138, 46, },
+	{18, 50, 147, 313, 510, 670, 730, 665, 501, 304, 141, 47, },
+	{18, 49, 145, 310, 507, 669, 730, 667, 504, 307, 143, 48, },
+};
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/xilinx-multi-scaler.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/xilinx-multi-scaler.c
@@ -0,0 +1,2483 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx Memory-to-Memory Video Multi-Scaler IP
+ *
+ * Copyright (C) 2018 Xilinx, Inc.
+ *
+ * Author: Suresh Gupta <suresh.gupta@xilinx.com>
+ *
+ * Based on the virtual v4l2-mem2mem example device
+ *
+ * This driver adds support to control the Xilinx Video Multi
+ * Scaler Controller
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/gpio/consumer.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "xilinx-multi-scaler-coeff.h"
+
+/* 0x0000 : Control signals */
+#define XM2MSC_AP_CTRL			0x0000
+#define XM2MSC_AP_CTRL_START		BIT(0)
+#define XM2MSC_AP_CTRL_DONE		BIT(1)
+#define XM2MSC_AP_CTRL_IDEL		BIT(2)
+#define XM2MSC_AP_CTRL_READY		BIT(3)
+#define XM2MSC_AP_CTRL_AUTO_RESTART	BIT(7)
+
+/* 0x0004 : Global Interrupt Enable Register */
+#define XM2MSC_GIE			0x0004
+#define XM2MSC_GIE_EN			BIT(0)
+
+/* 0x0008 : IP Interrupt Enable Register (Read/Write) */
+#define XM2MSC_IER			0x0008
+#define XM2MSC_ISR			0x000c
+#define XM2MSC_ISR_DONE			BIT(0)
+#define XM2MSC_ISR_READY		BIT(1)
+
+#define XM2MSC_NUM_OUTS			0x0010
+
+#define XM2MSC_WIDTHIN			0x000
+#define XM2MSC_WIDTHOUT			0x008
+#define XM2MSC_HEIGHTIN			0x010
+#define XM2MSC_HEIGHTOUT		0x018
+#define XM2MSC_LINERATE			0x020
+#define XM2MSC_PIXELRATE		0x028
+#define XM2MSC_INPIXELFMT		0x030
+#define XM2MSC_OUTPIXELFMT		0x038
+#define XM2MSC_INSTRIDE			0x050
+#define XM2MSC_OUTSTRIDE		0x058
+#define XM2MSC_SRCIMGBUF0		0x060
+#define XM2MSC_SRCIMGBUF1		0x070
+#define XM2MSC_DSTIMGBUF0		0x090
+#define XM2MSC_DSTIMGBUF1		0x0100
+
+#define XM2MVSC_VFLTCOEFF_L	0x2000
+#define XM2MVSC_VFLTCOEFF(x)	(XM2MVSC_VFLTCOEFF_L + 0x2000 * (x))
+#define XM2MVSC_HFLTCOEFF_L	0x2800
+#define XM2MVSC_HFLTCOEFF(x)	(XM2MVSC_HFLTCOEFF_L + 0x2000 * (x))
+
+#define XM2MSC_CHAN_REGS_START(x)	(0x100 + 0x200 * (x))
+
+/*
+ * IP has reserved area between XM2MSC_DSTIMGBUF0 and
+ * XM2MSC_DSTIMGBUF1 registers of channel 4
+ */
+#define XM2MSC_RESERVED_AREA		0x600
+
+/* GPIO RESET MACROS */
+#define XM2MSC_RESET_ASSERT	(0x1)
+#define XM2MSC_RESET_DEASSERT	(0x0)
+
+#define XM2MSC_MIN_CHAN		1
+#define XM2MSC_MAX_CHAN		8
+
+#define XM2MSC_MAX_WIDTH	(8192)
+#define XM2MSC_MAX_HEIGHT	(4320)
+#define XM2MSC_MIN_WIDTH	(64)
+#define XM2MSC_MIN_HEIGHT	(64)
+#define XM2MSC_STEP_PRECISION	(65536)
+/* Mask definitions for Low 16 bits in a 32 bit number */
+#define XM2MSC_MASK_LOW_16BITS	GENMASK(15, 0)
+#define XM2MSC_BITSHIFT_16	(16)
+
+#define XM2MSC_DRIVER_NAME	"xm2msc"
+
+#define CHAN_ATTACHED		BIT(0)
+#define CHAN_OPENED		BIT(1)
+
+#define XM2MSC_CHAN_OUT		0
+#define XM2MSC_CHAN_CAP		1
+
+#define NUM_STREAM(_x)			\
+	({ typeof(_x) (x) = (_x);	\
+	min(ffz(x->out_streamed_chan),	\
+	    ffz(x->cap_streamed_chan)); })
+
+#define XM2MSC_ALIGN_MUL	8
+
+/*
+ * These are temporary variables. Once the stride and height
+ * alignment support added to plugin, these variables will
+ * be remove.
+ */
+static unsigned int output_stride_align[XM2MSC_MAX_CHAN] = {
+					1, 1, 1, 1, 1, 1, 1, 1 };
+module_param_array(output_stride_align, uint, NULL, 0644);
+MODULE_PARM_DESC(output_stride_align,
+		 "Per Cahnnel stride alignment requied at output.");
+
+static unsigned int capture_stride_align[XM2MSC_MAX_CHAN] = {
+					1, 1, 1, 1, 1, 1, 1, 1 };
+module_param_array(capture_stride_align, uint, NULL, 0644);
+MODULE_PARM_DESC(capture_stride_align,
+		 "Per channel stride alignment requied at capture.");
+
+static unsigned int output_height_align[XM2MSC_MAX_CHAN] = {
+					1, 1, 1, 1, 1, 1, 1, 1 };
+module_param_array(output_height_align, uint, NULL, 0644);
+MODULE_PARM_DESC(output_height_align,
+		 "Per Channel height alignment requied at output.");
+
+static unsigned int capture_height_align[XM2MSC_MAX_CHAN] = {
+					1, 1, 1, 1, 1, 1, 1, 1 };
+module_param_array(capture_height_align, uint, NULL, 0644);
+MODULE_PARM_DESC(capture_height_align,
+		 "Per channel height alignment requied at capture.");
+
+/* Xilinx Video Specific Color/Pixel Formats */
+enum xm2msc_pix_fmt {
+	XILINX_M2MSC_FMT_RGBX8		= 10,
+	XILINX_M2MSC_FMT_YUVX8		= 11,
+	XILINX_M2MSC_FMT_YUYV8		= 12,
+	XILINX_M2MSC_FMT_RGBX10		= 15,
+	XILINX_M2MSC_FMT_YUVX10		= 16,
+	XILINX_M2MSC_FMT_Y_UV8		= 18,
+	XILINX_M2MSC_FMT_Y_UV8_420	= 19,
+	XILINX_M2MSC_FMT_RGB8		= 20,
+	XILINX_M2MSC_FMT_YUV8		= 21,
+	XILINX_M2MSC_FMT_Y_UV10		= 22,
+	XILINX_M2MSC_FMT_Y_UV10_420	= 23,
+	XILINX_M2MSC_FMT_Y8		= 24,
+	XILINX_M2MSC_FMT_Y10		= 25,
+	XILINX_M2MSC_FMT_BGRX8		= 27,
+	XILINX_M2MSC_FMT_UYVY8		= 28,
+	XILINX_M2MSC_FMT_BGR8		= 29,
+};
+
+/**
+ * struct xm2msc_fmt - driver info for each of the supported video formats
+ * @name: human-readable device tree name for this entry
+ * @fourcc: standard format identifier
+ * @xm2msc_fmt: Xilinx Video Specific Color/Pixel Formats
+ * @num_buffs: number of physically non-contiguous data planes/buffs
+ */
+struct xm2msc_fmt {
+	char *name;
+	u32 fourcc;
+	enum xm2msc_pix_fmt xm2msc_fmt;
+	u32 num_buffs;
+};
+
+static const struct xm2msc_fmt formats[] = {
+	{
+		.name = "xbgr8888",
+		.fourcc = V4L2_PIX_FMT_BGRX32,
+		.xm2msc_fmt = XILINX_M2MSC_FMT_RGBX8,
+		.num_buffs = 1,
+	},
+	{
+		.name = "xvuy8888",
+		.fourcc = V4L2_PIX_FMT_XVUY32,
+		.xm2msc_fmt = XILINX_M2MSC_FMT_YUVX8,
+		.num_buffs = 1,
+	},
+	{
+		.name = "yuyv",
+		.fourcc = V4L2_PIX_FMT_YUYV,
+		.xm2msc_fmt = XILINX_M2MSC_FMT_YUYV8,
+		.num_buffs = 1,
+	},
+	{
+		.name = "xbgr2101010",
+		.fourcc = V4L2_PIX_FMT_XBGR30,
+		.xm2msc_fmt = XILINX_M2MSC_FMT_RGBX10,
+		.num_buffs = 1,
+	},
+	{
+		.name = "yuvx2101010",
+		.fourcc = V4L2_PIX_FMT_XVUY10,
+		.xm2msc_fmt = XILINX_M2MSC_FMT_YUVX10,
+		.num_buffs = 1,
+	},
+	{
+		.name = "nv16",
+		.fourcc = V4L2_PIX_FMT_NV16M,
+		.xm2msc_fmt = XILINX_M2MSC_FMT_Y_UV8,
+		.num_buffs = 2,
+	},
+	{
+		.name = "nv16",
+		.fourcc = V4L2_PIX_FMT_NV16,
+		.xm2msc_fmt = XILINX_M2MSC_FMT_Y_UV8,
+		.num_buffs = 1,
+	},
+	{
+		.name = "nv12",
+		.fourcc = V4L2_PIX_FMT_NV12M,
+		.xm2msc_fmt = XILINX_M2MSC_FMT_Y_UV8_420,
+		.num_buffs = 2,
+	},
+	{
+		.name = "nv12",
+		.fourcc = V4L2_PIX_FMT_NV12,
+		.xm2msc_fmt = XILINX_M2MSC_FMT_Y_UV8_420,
+		.num_buffs = 1,
+	},
+	{
+		.name = "bgr888",
+		.fourcc = V4L2_PIX_FMT_RGB24,
+		.xm2msc_fmt = XILINX_M2MSC_FMT_RGB8,
+		.num_buffs = 1,
+	},
+	{
+		.name = "vuy888",
+		.fourcc = V4L2_PIX_FMT_VUY24,
+		.xm2msc_fmt = XILINX_M2MSC_FMT_YUV8,
+		.num_buffs = 1,
+	},
+	{
+		.name = "xv20",
+		.fourcc = V4L2_PIX_FMT_XV20M,
+		.xm2msc_fmt = XILINX_M2MSC_FMT_Y_UV10,
+		.num_buffs = 2,
+	},
+	{
+		.name = "xv20",
+		.fourcc = V4L2_PIX_FMT_XV20,
+		.xm2msc_fmt = XILINX_M2MSC_FMT_Y_UV10,
+		.num_buffs = 1,
+	},
+	{
+		.name = "xv15",
+		.fourcc = V4L2_PIX_FMT_XV15M,
+		.xm2msc_fmt = XILINX_M2MSC_FMT_Y_UV10_420,
+		.num_buffs = 2,
+	},
+	{
+		.name = "xv15",
+		.fourcc = V4L2_PIX_FMT_XV15,
+		.xm2msc_fmt = XILINX_M2MSC_FMT_Y_UV10_420,
+		.num_buffs = 1,
+	},
+	{
+		.name = "y8",
+		.fourcc = V4L2_PIX_FMT_GREY,
+		.xm2msc_fmt = XILINX_M2MSC_FMT_Y8,
+		.num_buffs = 1,
+	},
+	{
+		.name = "y10",
+		.fourcc = V4L2_PIX_FMT_Y10,
+		.xm2msc_fmt = XILINX_M2MSC_FMT_Y10,
+		.num_buffs = 1,
+	},
+	{
+		.name = "xrgb8888",
+		.fourcc = V4L2_PIX_FMT_XBGR32,
+		.xm2msc_fmt = XILINX_M2MSC_FMT_BGRX8,
+		.num_buffs = 1,
+	},
+	{
+		.name = "uyvy",
+		.fourcc = V4L2_PIX_FMT_UYVY,
+		.xm2msc_fmt = XILINX_M2MSC_FMT_UYVY8,
+		.num_buffs = 1,
+	},
+	{
+		.name = "rgb888",
+		.fourcc = V4L2_PIX_FMT_BGR24,
+		.xm2msc_fmt = XILINX_M2MSC_FMT_BGR8,
+		.num_buffs = 1,
+	},
+};
+
+/**
+ * struct xm2msc_q_data - Per-queue, driver-specific private data
+ * There is one source queue and one destination queue for each m2m context.
+ * @width: frame width
+ * @height: frame height
+ * @stride: bytes per lines
+ * @nbuffs: Current number of buffs
+ * @bytesperline: bytes per line per plane
+ * @sizeimage: image size per plane
+ * @colorspace: supported colorspace
+ * @field: supported field value
+ * @fmt: format info
+ */
+struct xm2msc_q_data {
+	unsigned int width;
+	unsigned int height;
+	unsigned int stride;
+	unsigned int nbuffs;
+	unsigned int bytesperline[2];
+	unsigned int sizeimage[2];
+	enum v4l2_colorspace colorspace;
+	enum v4l2_field field;
+	const struct xm2msc_fmt *fmt;
+};
+
+/**
+ * struct xm2msc_chan_ctx - Scaler Channel Info, Per-Channel context
+ * @regs: IO mapped base address of the Channel
+ * @xm2msc_dev: Pointer to struct xm2m_msc_dev
+ * @num: HW Scaling Channel number
+ * @minor: Minor number of the video device
+ * @output_stride_align: required align stride value at output pad
+ * @capture_stride_align: required align stride valure at capture pad
+ * @output_height_align: required align height value at output pad
+ * @capture_height_align: required align heigh value at capture pad
+ * @status: channel status, CHAN_ATTACHED or CHAN_OPENED
+ * @frames: number of frames processed
+ * @vfd: V4L2 device
+ * @fh: v4l2 file handle
+ * @m2m_dev: m2m device
+ * @m2m_ctx: memory to memory context structure
+ * @q_data: src & dst queue data
+ */
+struct xm2msc_chan_ctx {
+	void __iomem *regs;
+	struct xm2m_msc_dev *xm2msc_dev;
+	u32 num;
+	u32 minor;
+	u32 output_stride_align;
+	u32 capture_stride_align;
+	u32 output_height_align;
+	u32 capture_height_align;
+	u8 status;
+	unsigned long frames;
+
+	struct video_device vfd;
+	struct v4l2_fh fh;
+	struct v4l2_m2m_dev *m2m_dev;
+	struct v4l2_m2m_ctx *m2m_ctx;
+
+	struct xm2msc_q_data q_data[2];
+};
+
+/**
+ * struct xm2m_msc_dev - Xilinx M2M Multi-scaler Device
+ * @dev: pointer to struct device instance used by the driver
+ * @regs: IO mapped base address of the HW/IP
+ * @irq: interrupt number
+ * @clk: video core clock
+ * @max_chan: maximum number of Scaling Channels
+ * @max_ht: maximum number of rows in a plane
+ * @max_wd: maximum number of column in a plane
+ * @taps: number of taps set in HW
+ * @supported_fmt: bitmap for all supported fmts by HW
+ * @dma_addr_size: Size of dma address pointer in IP (either 32 or 64)
+ * @ppc: Pixels per clock set in IP (1, 2 or 4)
+ * @rst_gpio: reset gpio handler
+ * @opened_chan: bitmap for all open channel
+ * @out_streamed_chan: bitmap for all out streamed channel
+ * @cap_streamed_chan: bitmap for all capture streamed channel
+ * @running_chan: currently running channels
+ * @device_busy: HW device is busy or not
+ * @isr_wait: flag to follow the ISR complete or not
+ * @isr_finished: Wait queue used to wait for IP to complete processing
+ * @v4l2_dev: main struct to for V4L2 device drivers
+ * @dev_mutex: lock for V4L2 device
+ * @mutex: lock for channel ctx
+ * @lock: lock used in IRQ
+ * @xm2msc_chan: arrey of channel context
+ * @hscaler_coeff: Array of filter coefficients for the Horizontal Scaler
+ * @vscaler_coeff: Array of filter coefficients for the Vertical Scaler
+ */
+struct xm2m_msc_dev {
+	struct device *dev;
+	void __iomem *regs;
+	int irq;
+	struct clk *clk;
+	u32 max_chan;
+	u32 max_ht;
+	u32 max_wd;
+	u32 taps;
+	u32 supported_fmt;
+	u32 dma_addr_size;
+	u8 ppc;
+	struct gpio_desc *rst_gpio;
+
+	u32 opened_chan;
+	u32 out_streamed_chan;
+	u32 cap_streamed_chan;
+	u32 running_chan;
+	bool device_busy;
+	bool isr_wait;
+	wait_queue_head_t isr_finished;
+
+	struct v4l2_device v4l2_dev;
+
+	struct mutex dev_mutex; /*the mutex for v4l2*/
+	struct mutex mutex; /*lock for bitmap reg*/
+	spinlock_t lock; /*IRQ lock*/
+
+	struct xm2msc_chan_ctx xm2msc_chan[XM2MSC_MAX_CHAN];
+	short hscaler_coeff[XSCALER_MAX_PHASES][XSCALER_MAX_TAPS];
+	short vscaler_coeff[XSCALER_MAX_PHASES][XSCALER_MAX_TAPS];
+};
+
+#define fh_to_chanctx(__fh) container_of(__fh, struct xm2msc_chan_ctx, fh)
+
+static inline u32 xm2msc_readreg(const void __iomem *addr)
+{
+	return ioread32(addr);
+}
+
+static inline void xm2msc_write64reg(void __iomem *addr, u64 value)
+{
+	iowrite32(lower_32_bits(value), addr);
+	iowrite32(upper_32_bits(value), (void __iomem *)(addr + 4));
+}
+
+static inline void xm2msc_writereg(void __iomem *addr, u32 value)
+{
+	iowrite32(value, addr);
+}
+
+static bool xm2msc_is_yuv_singlebuff(u32 fourcc)
+{
+	if (fourcc == V4L2_PIX_FMT_NV12 || fourcc == V4L2_PIX_FMT_XV15 ||
+	    fourcc ==  V4L2_PIX_FMT_NV16 || fourcc == V4L2_PIX_FMT_XV20)
+		return true;
+
+	return false;
+}
+
+static inline u32 xm2msc_yuv_1stplane_size(struct xm2msc_q_data *q_data,
+					   u32 row_align)
+{
+	return	q_data->bytesperline[0] * ALIGN(q_data->height, row_align);
+}
+
+static struct xm2msc_q_data *get_q_data(struct xm2msc_chan_ctx *chan_ctx,
+					enum v4l2_buf_type type)
+{
+	switch (type) {
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+		return &chan_ctx->q_data[XM2MSC_CHAN_OUT];
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+		return &chan_ctx->q_data[XM2MSC_CHAN_CAP];
+	default:
+		v4l2_err(&chan_ctx->xm2msc_dev->v4l2_dev,
+			 "Not supported Q type %d\n", type);
+	}
+	return NULL;
+}
+
+static u32 find_format_index(struct v4l2_format *f)
+{
+	const struct xm2msc_fmt *fmt;
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(formats); i++) {
+		fmt = &formats[i];
+		if (fmt->fourcc == f->fmt.pix_mp.pixelformat)
+			break;
+	}
+
+	return i;
+}
+
+static const struct xm2msc_fmt *find_format(struct v4l2_format *f)
+{
+	const struct xm2msc_fmt *fmt;
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(formats); i++) {
+		fmt = &formats[i];
+		if (fmt->fourcc == f->fmt.pix_mp.pixelformat)
+			break;
+	}
+
+	if (i == ARRAY_SIZE(formats))
+		return NULL;
+
+	return &formats[i];
+}
+
+static void
+xm2msc_hscaler_load_ext_coeff(struct xm2m_msc_dev *xm2msc,
+			      const short *coeff, u32 ntaps)
+{
+	unsigned int i, j, pad, offset;
+	const u32 nphases = XSCALER_MAX_PHASES;
+
+	/* Determine if coefficient needs padding (effective vs. max taps) */
+	pad = XSCALER_MAX_TAPS - ntaps;
+	offset = pad >> 1;
+
+	memset(xm2msc->hscaler_coeff, 0, sizeof(xm2msc->hscaler_coeff));
+
+	/* Load coefficients into scaler coefficient table */
+	for (i = 0; i < nphases; i++) {
+		for (j = 0; j < ntaps; ++j)
+			xm2msc->hscaler_coeff[i][j + offset] =
+						coeff[i * ntaps + j];
+	}
+}
+
+static void xm2msc_hscaler_set_coeff(struct xm2msc_chan_ctx *chan_ctx,
+				     const u32 base_addr)
+{
+	struct xm2m_msc_dev *xm2msc = chan_ctx->xm2msc_dev;
+	int val, offset, rd_indx;
+	unsigned int i, j;
+	u32 ntaps = chan_ctx->xm2msc_dev->taps;
+	const u32 nphases = XSCALER_MAX_PHASES;
+
+	offset = (XSCALER_MAX_TAPS - ntaps) / 2;
+	for (i = 0; i < nphases; i++) {
+		for (j = 0; j < ntaps / 2; j++) {
+			rd_indx = j * 2 + offset;
+			val = (xm2msc->hscaler_coeff[i][rd_indx + 1] <<
+			       XM2MSC_BITSHIFT_16) |
+			       (xm2msc->hscaler_coeff[i][rd_indx] &
+			       XM2MSC_MASK_LOW_16BITS);
+			 xm2msc_writereg((xm2msc->regs + base_addr) +
+				    ((i * ntaps / 2 + j) * 4), val);
+		}
+	}
+}
+
+static void
+xm2msc_vscaler_load_ext_coeff(struct xm2m_msc_dev *xm2msc,
+			      const short *coeff, const u32 ntaps)
+{
+	unsigned int i, j;
+	int pad, offset;
+	const u32 nphases = XSCALER_MAX_PHASES;
+
+	/* Determine if coefficient needs padding (effective vs. max taps) */
+	pad = XSCALER_MAX_TAPS - ntaps;
+	offset = pad ? (pad >> 1) : 0;
+
+	/* Zero Entire Array */
+	memset(xm2msc->vscaler_coeff, 0, sizeof(xm2msc->vscaler_coeff));
+
+	/* Load User defined coefficients into scaler coefficient table */
+	for (i = 0; i < nphases; i++) {
+		for (j = 0; j < ntaps; ++j)
+			xm2msc->vscaler_coeff[i][j + offset] =
+						coeff[i * ntaps + j];
+	}
+}
+
+static void
+xm2msc_vscaler_set_coeff(struct xm2msc_chan_ctx *chan_ctx,
+			 const u32 base_addr)
+{
+	struct xm2m_msc_dev *xm2msc = chan_ctx->xm2msc_dev;
+	u32 val, i, j, offset, rd_indx;
+	u32 ntaps = chan_ctx->xm2msc_dev->taps;
+	const u32 nphases = XSCALER_MAX_PHASES;
+
+	offset = (XSCALER_MAX_TAPS - ntaps) / 2;
+
+	for (i = 0; i < nphases; i++) {
+		for (j = 0; j < ntaps / 2; j++) {
+			rd_indx = j * 2 + offset;
+			val = (xm2msc->vscaler_coeff[i][rd_indx + 1] <<
+			       XM2MSC_BITSHIFT_16) |
+			       (xm2msc->vscaler_coeff[i][rd_indx] &
+			       XM2MSC_MASK_LOW_16BITS);
+			xm2msc_writereg((xm2msc->regs +
+				   base_addr) + ((i * ntaps / 2 + j) * 4), val);
+		}
+	}
+}
+
+static u32
+xm2msc_select_hcoeff(struct xm2msc_chan_ctx *chan_ctx, const short **coeff)
+{
+	u16 hscale_ratio;
+	u32 width_in = chan_ctx->q_data[XM2MSC_CHAN_OUT].width;
+	u32 width_out = chan_ctx->q_data[XM2MSC_CHAN_CAP].width;
+	u32 ntaps;
+
+	if (width_out < width_in) {
+		hscale_ratio = (width_in * 10) / width_out;
+
+		switch (chan_ctx->xm2msc_dev->taps) {
+		case XSCALER_TAPS_12:
+			if (hscale_ratio > 35) {
+				*coeff = &xhsc_coeff_taps12[0][0];
+				ntaps = XSCALER_TAPS_12;
+			} else if (hscale_ratio > 25) {
+				*coeff = &xhsc_coeff_taps10[0][0];
+				ntaps = XSCALER_TAPS_10;
+			} else if (hscale_ratio > 15) {
+				*coeff = &xhsc_coeff_taps8[0][0];
+				ntaps = XSCALER_TAPS_8;
+			} else {
+				*coeff = &xhsc_coeff_taps6[0][0];
+				ntaps = XSCALER_TAPS_6;
+			}
+		break;
+		case XSCALER_TAPS_10:
+			if (hscale_ratio > 25) {
+				*coeff = &xhsc_coeff_taps10[0][0];
+				ntaps = XSCALER_TAPS_10;
+			} else if (hscale_ratio > 15) {
+				*coeff = &xhsc_coeff_taps8[0][0];
+				ntaps = XSCALER_TAPS_8;
+			} else {
+				*coeff = &xhsc_coeff_taps6[0][0];
+				ntaps = XSCALER_TAPS_6;
+			}
+		break;
+		case XSCALER_TAPS_8:
+			if (hscale_ratio > 15) {
+				*coeff = &xhsc_coeff_taps8[0][0];
+				ntaps = XSCALER_TAPS_8;
+			} else {
+				*coeff = &xhsc_coeff_taps6[0][0];
+				ntaps = XSCALER_TAPS_6;
+			}
+		break;
+		default: /* or XSCALER_TAPS_6 */
+			*coeff = &xhsc_coeff_taps6[0][0];
+			ntaps = XSCALER_TAPS_6;
+		}
+	} else {
+		/*
+		 * Scale Up Mode will always use 6 tap filter
+		 * This also includes 1:1
+		 */
+		*coeff = &xhsc_coeff_taps6[0][0];
+		ntaps = XSCALER_TAPS_6;
+	}
+
+	return ntaps;
+}
+
+static u32
+xm2msc_select_vcoeff(struct xm2msc_chan_ctx *chan_ctx, const short **coeff)
+{
+	u16 vscale_ratio;
+	u32 height_in = chan_ctx->q_data[XM2MSC_CHAN_OUT].height;
+	u32 height_out = chan_ctx->q_data[XM2MSC_CHAN_CAP].height;
+	u32 ntaps;
+
+	if (height_out < height_in) {
+		vscale_ratio = (height_in * 10) / height_out;
+
+		switch (chan_ctx->xm2msc_dev->taps) {
+		case XSCALER_TAPS_12:
+			if (vscale_ratio > 35) {
+				*coeff = &xvsc_coeff_taps12[0][0];
+				ntaps = XSCALER_TAPS_12;
+			} else if (vscale_ratio > 25) {
+				*coeff = &xvsc_coeff_taps10[0][0];
+				ntaps = XSCALER_TAPS_10;
+			} else if (vscale_ratio > 15) {
+				*coeff = &xvsc_coeff_taps8[0][0];
+				ntaps = XSCALER_TAPS_8;
+			} else {
+				*coeff = &xvsc_coeff_taps6[0][0];
+				ntaps = XSCALER_TAPS_6;
+			}
+		break;
+		case XSCALER_TAPS_10:
+			if (vscale_ratio > 25) {
+				*coeff = &xvsc_coeff_taps10[0][0];
+				ntaps = XSCALER_TAPS_10;
+			} else if (vscale_ratio > 15) {
+				*coeff = &xvsc_coeff_taps8[0][0];
+				ntaps = XSCALER_TAPS_8;
+			} else {
+				*coeff = &xvsc_coeff_taps6[0][0];
+				ntaps = XSCALER_TAPS_6;
+			}
+		break;
+		case XSCALER_TAPS_8:
+			if (vscale_ratio > 15) {
+				*coeff = &xvsc_coeff_taps8[0][0];
+				ntaps = XSCALER_TAPS_8;
+			} else {
+				*coeff = &xvsc_coeff_taps6[0][0];
+				ntaps = XSCALER_TAPS_6;
+			}
+		break;
+		default: /* or XSCALER_TAPS_6 */
+			*coeff = &xvsc_coeff_taps6[0][0];
+			ntaps = XSCALER_TAPS_6;
+		}
+	} else {
+		/*
+		 * Scale Up Mode will always use 6 tap filter
+		 * This also includes 1:1
+		 */
+		*coeff = &xvsc_coeff_taps6[0][0];
+		ntaps = XSCALER_TAPS_6;
+	}
+
+	return ntaps;
+}
+
+static void xm2mvsc_initialize_coeff_banks(struct xm2msc_chan_ctx *chan_ctx)
+{
+	const short *coeff = NULL;
+	u32 ntaps;
+	struct xm2m_msc_dev *xm2msc = chan_ctx->xm2msc_dev;
+
+	ntaps = xm2msc_select_hcoeff(chan_ctx, &coeff);
+	xm2msc_hscaler_load_ext_coeff(xm2msc, coeff, ntaps);
+	xm2msc_hscaler_set_coeff(chan_ctx, XM2MVSC_HFLTCOEFF(chan_ctx->num));
+
+	dev_dbg(xm2msc->dev, "htaps %d selected for chan %d\n",
+		ntaps, chan_ctx->num);
+
+	ntaps = xm2msc_select_vcoeff(chan_ctx, &coeff);
+	xm2msc_vscaler_load_ext_coeff(xm2msc, coeff, ntaps);
+	xm2msc_vscaler_set_coeff(chan_ctx, XM2MVSC_VFLTCOEFF(chan_ctx->num));
+
+	dev_dbg(xm2msc->dev, "vtaps %d selected for chan %d\n",
+		ntaps, chan_ctx->num);
+}
+
+static int xm2msc_set_chan_params(struct xm2msc_chan_ctx *chan_ctx,
+				  enum v4l2_buf_type type)
+{
+	struct xm2msc_q_data *q_data = get_q_data(chan_ctx, type);
+	const struct xm2msc_fmt *fmt;
+	void __iomem *base = chan_ctx->regs;
+
+	if (!q_data)
+		return -EINVAL;
+
+	fmt = q_data->fmt;
+
+	if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		xm2msc_writereg(base + XM2MSC_WIDTHIN, q_data->width);
+		xm2msc_writereg(base + XM2MSC_HEIGHTIN, q_data->height);
+		xm2msc_writereg(base + XM2MSC_INPIXELFMT, fmt->xm2msc_fmt);
+		xm2msc_writereg(base + XM2MSC_INSTRIDE, q_data->stride);
+	} else {
+		xm2msc_writereg(base + XM2MSC_WIDTHOUT, q_data->width);
+		xm2msc_writereg(base + XM2MSC_HEIGHTOUT, q_data->height);
+		xm2msc_writereg(base + XM2MSC_OUTPIXELFMT, fmt->xm2msc_fmt);
+		xm2msc_writereg(base + XM2MSC_OUTSTRIDE, q_data->stride);
+	}
+
+	return 0;
+}
+
+static void xm2msc_set_chan_com_params(struct xm2msc_chan_ctx *chan_ctx)
+{
+	void __iomem *base = chan_ctx->regs;
+	struct xm2msc_q_data *out_q_data = &chan_ctx->q_data[XM2MSC_CHAN_OUT];
+	struct xm2msc_q_data *cap_q_data = &chan_ctx->q_data[XM2MSC_CHAN_CAP];
+	u32 pixel_rate;
+	u32 line_rate;
+
+	xm2mvsc_initialize_coeff_banks(chan_ctx);
+
+	pixel_rate = (out_q_data->width * XM2MSC_STEP_PRECISION) /
+		cap_q_data->width;
+	line_rate = (out_q_data->height * XM2MSC_STEP_PRECISION) /
+		cap_q_data->height;
+
+	xm2msc_writereg(base + XM2MSC_PIXELRATE, pixel_rate);
+	xm2msc_writereg(base + XM2MSC_LINERATE, line_rate);
+}
+
+static int xm2msc_program_allchan(struct xm2m_msc_dev *xm2msc)
+{
+	u32 chan;
+
+	for (chan = 0; chan < xm2msc->running_chan; chan++) {
+		struct xm2msc_chan_ctx *chan_ctx;
+		enum v4l2_buf_type type;
+		int ret;
+
+		chan_ctx = &xm2msc->xm2msc_chan[chan];
+		type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+		ret = xm2msc_set_chan_params(chan_ctx, type);
+		if (ret)
+			return ret;
+
+		type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+		ret = xm2msc_set_chan_params(chan_ctx, type);
+		if (ret)
+			return ret;
+		xm2msc_set_chan_com_params(chan_ctx);
+	}
+	return 0;
+}
+
+static void
+xm2msc_pr_q(struct device *dev, struct xm2msc_q_data *q, int chan,
+	    int type, const char *fun_name)
+{
+	unsigned int i;
+	const struct xm2msc_fmt *fmt = q->fmt;
+
+	if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+		dev_dbg(dev, "\n\nOUTPUT Q (%d) Context from [[ %s ]]",
+			chan, fun_name);
+	else
+		dev_dbg(dev, "\n\nCAPTURE Q (%d) Context from [[ %s ]]",
+			chan, fun_name);
+
+	dev_dbg(dev, "width height stride clrspace field planes\n");
+	dev_dbg(dev, "  %d  %d    %d     %d       %d    %d\n",
+		q->width, q->height, q->stride,
+		q->colorspace, q->field, q->nbuffs);
+
+	for (i = 0; i < q->nbuffs; i++) {
+		dev_dbg(dev, "[plane %d ] bytesperline sizeimage\n", i);
+		dev_dbg(dev, "                %d        %d\n",
+			q->bytesperline[i], q->sizeimage[i]);
+	}
+
+	dev_dbg(dev, "fmt_name 4cc xlnx-fmt\n");
+	dev_dbg(dev, "%s %d %d\n",
+		fmt->name, fmt->fourcc, fmt->xm2msc_fmt);
+	dev_dbg(dev, "\n\n");
+}
+
+static void
+xm2msc_pr_status(struct xm2m_msc_dev *xm2msc,
+		 const char *fun_name)
+{
+	struct device *dev = xm2msc->dev;
+
+	dev_dbg(dev, "Status in %s\n", fun_name);
+	dev_dbg(dev, "opened_chan out_streamed_chan cap_streamed_chan\n");
+	dev_dbg(dev, "0x%x           0x%x               0x%x\n",
+		xm2msc->opened_chan, xm2msc->out_streamed_chan,
+		xm2msc->cap_streamed_chan);
+	dev_dbg(dev, "\n\n");
+}
+
+static void
+xm2msc_pr_chanctx(struct xm2msc_chan_ctx *ctx, const char *fun_name)
+{
+	struct device *dev = ctx->xm2msc_dev->dev;
+
+	dev_dbg(dev, "\n\n----- [[ %s ]]: Channel %d (0x%p) context -----\n",
+		fun_name, ctx->num, ctx);
+	dev_dbg(dev, "minor = %d\n", ctx->minor);
+	dev_dbg(dev, "reg mapped at %p\n", ctx->regs);
+	dev_dbg(dev, "xm2msc \tm2m_dev \tm2m_ctx\n");
+	dev_dbg(dev, "%p \t%p \t%p\n", ctx->xm2msc_dev,
+		ctx->m2m_dev, ctx->m2m_ctx);
+
+	if (ctx->status & CHAN_OPENED)
+		dev_dbg(dev, "Opened ");
+	if (ctx->status & CHAN_ATTACHED)
+		dev_dbg(dev, "and attached");
+	dev_dbg(dev, "\n");
+	dev_dbg(dev, "-----------------------------------\n");
+	dev_dbg(dev, "\n\n");
+}
+
+static void
+xm2msc_pr_screg(struct device *dev, const void __iomem *base)
+{
+	dev_dbg(dev, "Ctr, GIE,  IE,  IS   OUT\n");
+	dev_dbg(dev, "0x%x  0x%x   0x%x  0x%x  0x%x\n",
+		xm2msc_readreg(base + XM2MSC_AP_CTRL),
+		xm2msc_readreg(base + XM2MSC_GIE),
+		xm2msc_readreg(base + XM2MSC_IER),
+		xm2msc_readreg(base + XM2MSC_ISR),
+		xm2msc_readreg(base + XM2MSC_NUM_OUTS));
+}
+
+static void
+xm2msc_pr_chanreg(struct device *dev, struct xm2msc_chan_ctx *chan)
+{
+	const void __iomem *base = chan->regs;
+
+	dev_dbg(dev, "WIN HIN INPIXELFMT INSTRIDE SRCB0L/H SRCB1L/H\n");
+	dev_dbg(dev, "%d   %d     %d       %d      0x%x/0x%x      0x%x/0x%x\n",
+		xm2msc_readreg(base + XM2MSC_WIDTHIN),
+		xm2msc_readreg(base + XM2MSC_HEIGHTIN),
+		xm2msc_readreg(base + XM2MSC_INPIXELFMT),
+		xm2msc_readreg(base + XM2MSC_INSTRIDE),
+		xm2msc_readreg(base + XM2MSC_SRCIMGBUF0),
+		xm2msc_readreg(base + XM2MSC_SRCIMGBUF0 + 4),
+		xm2msc_readreg(base + XM2MSC_SRCIMGBUF1),
+		xm2msc_readreg(base + XM2MSC_SRCIMGBUF1 + 4));
+	dev_dbg(dev, "WOUT HOUT OUTPIXELFMT OUTSTRIDE DBUF0L/H DBUF1L/H\n");
+	dev_dbg(dev, "%d   %d     %d       %d      0x%x/0x%x      0x%x/0x%x\n",
+		xm2msc_readreg(base + XM2MSC_WIDTHOUT),
+		xm2msc_readreg(base + XM2MSC_HEIGHTOUT),
+		xm2msc_readreg(base + XM2MSC_OUTPIXELFMT),
+		xm2msc_readreg(base + XM2MSC_OUTSTRIDE),
+		xm2msc_readreg(base + XM2MSC_DSTIMGBUF0),
+		xm2msc_readreg(base + XM2MSC_DSTIMGBUF0 + 4),
+		chan->num == 4 ?
+		xm2msc_readreg(base +
+			       XM2MSC_DSTIMGBUF1 + XM2MSC_RESERVED_AREA) :
+			xm2msc_readreg(base + XM2MSC_DSTIMGBUF1),
+		chan->num == 4 ?
+		xm2msc_readreg(base +
+			       XM2MSC_DSTIMGBUF1 + XM2MSC_RESERVED_AREA + 4) :
+			xm2msc_readreg(base + XM2MSC_DSTIMGBUF1 + 4));
+
+	dev_dbg(dev, "LINERATE PIXELRATE\n");
+	dev_dbg(dev, "0x%x     0x%x\n",
+		xm2msc_readreg(base + XM2MSC_LINERATE),
+		xm2msc_readreg(base + XM2MSC_PIXELRATE));
+}
+
+static void
+xm2msc_pr_allchanreg(struct xm2m_msc_dev *xm2msc)
+{
+	unsigned int i;
+	struct xm2msc_chan_ctx *chan_ctx;
+	struct device *dev = xm2msc->dev;
+
+	xm2msc_pr_screg(xm2msc->dev, xm2msc->regs);
+
+	for (i = 0; i < xm2msc->running_chan; i++) {
+		chan_ctx = &xm2msc->xm2msc_chan[i];
+		dev_dbg(dev, "Regs val for channel %d\n", i);
+		dev_dbg(dev, "______________________________________________\n");
+		xm2msc_pr_chanreg(dev, chan_ctx);
+		dev_dbg(dev, "processed frames = %lu\n", chan_ctx->frames);
+		dev_dbg(dev, "______________________________________________\n");
+	}
+}
+
+static inline bool xm2msc_testbit(int num, u32 *addr)
+{
+	return (*addr & BIT(num));
+}
+
+static inline void xm2msc_setbit(int num, u32 *addr)
+{
+	*addr |= BIT(num);
+}
+
+static inline void xm2msc_clrbit(int num, u32 *addr)
+{
+	*addr &= ~BIT(num);
+}
+
+static void xm2msc_stop(struct xm2m_msc_dev *xm2msc)
+{
+	void __iomem *base = xm2msc->regs;
+	u32 data = xm2msc_readreg(base + XM2MSC_AP_CTRL);
+
+	data &= ~XM2MSC_AP_CTRL_START;
+	xm2msc_writereg(base + XM2MSC_AP_CTRL, data);
+}
+
+static void xm2msc_start(struct xm2m_msc_dev *xm2msc)
+{
+	void __iomem *base = xm2msc->regs;
+	u32 data = xm2msc_readreg(base + XM2MSC_AP_CTRL);
+
+	data |= XM2MSC_AP_CTRL_START;
+	xm2msc_writereg(base + XM2MSC_AP_CTRL, data);
+}
+
+static void xm2msc_set_chan(struct xm2msc_chan_ctx *ctx, bool state)
+{
+	mutex_lock(&ctx->xm2msc_dev->mutex);
+	if (state)
+		xm2msc_setbit(ctx->num, &ctx->xm2msc_dev->opened_chan);
+	else
+		xm2msc_clrbit(ctx->num, &ctx->xm2msc_dev->opened_chan);
+	mutex_unlock(&ctx->xm2msc_dev->mutex);
+}
+
+static void
+xm2msc_set_chan_stream(struct xm2msc_chan_ctx *ctx, bool state, int type)
+{
+	u32 *ptr;
+
+	if (type == XM2MSC_CHAN_OUT)
+		ptr = &ctx->xm2msc_dev->out_streamed_chan;
+	else
+		ptr = &ctx->xm2msc_dev->cap_streamed_chan;
+
+	spin_lock(&ctx->xm2msc_dev->lock);
+	if (state)
+		xm2msc_setbit(ctx->num, ptr);
+	else
+		xm2msc_clrbit(ctx->num, ptr);
+
+	spin_unlock(&ctx->xm2msc_dev->lock);
+}
+
+static int
+xm2msc_chk_chan_stream(struct xm2msc_chan_ctx *ctx, int type)
+{
+	u32 *ptr;
+	int ret;
+
+	if (type == XM2MSC_CHAN_OUT)
+		ptr = &ctx->xm2msc_dev->out_streamed_chan;
+	else
+		ptr = &ctx->xm2msc_dev->cap_streamed_chan;
+
+	mutex_lock(&ctx->xm2msc_dev->mutex);
+	ret = xm2msc_testbit(ctx->num, ptr);
+	mutex_unlock(&ctx->xm2msc_dev->mutex);
+
+	return ret;
+}
+
+static void xm2msc_set_fmt(struct xm2m_msc_dev *xm2msc, u32 index)
+{
+	xm2msc_setbit(index, &xm2msc->supported_fmt);
+}
+
+static int xm2msc_chk_fmt(struct xm2m_msc_dev *xm2msc, u32 index)
+{
+	return xm2msc_testbit(index, &xm2msc->supported_fmt);
+}
+
+static void xm2msc_reset(struct xm2m_msc_dev *xm2msc)
+{
+	gpiod_set_value_cansleep(xm2msc->rst_gpio, XM2MSC_RESET_ASSERT);
+	gpiod_set_value_cansleep(xm2msc->rst_gpio, XM2MSC_RESET_DEASSERT);
+}
+
+/*
+ * mem2mem callbacks
+ */
+static int xm2msc_job_ready(void *priv)
+{
+	struct xm2msc_chan_ctx *chan_ctx = priv;
+
+	if ((v4l2_m2m_num_src_bufs_ready(chan_ctx->m2m_ctx) > 0) &&
+	    (v4l2_m2m_num_dst_bufs_ready(chan_ctx->m2m_ctx) > 0))
+		return 1;
+	return 0;
+}
+
+static bool xm2msc_alljob_ready(struct xm2m_msc_dev *xm2msc)
+{
+	struct xm2msc_chan_ctx *chan_ctx;
+	unsigned int chan;
+
+	for (chan = 0; chan < xm2msc->running_chan; chan++) {
+		chan_ctx = &xm2msc->xm2msc_chan[chan];
+
+		if (!xm2msc_job_ready((void *)chan_ctx)) {
+			dev_dbg(xm2msc->dev, "chan %d not ready\n",
+				chan_ctx->num);
+			return false;
+		}
+	}
+
+	return true;
+}
+
+static void xm2msc_chan_abort_bufs(struct xm2msc_chan_ctx *chan_ctx)
+{
+	struct xm2m_msc_dev *xm2msc = chan_ctx->xm2msc_dev;
+	struct vb2_v4l2_buffer *dst_vb, *src_vb;
+
+	spin_lock(&xm2msc->lock);
+	dev_dbg(xm2msc->dev, "aborting all buffers\n");
+
+	while (v4l2_m2m_num_src_bufs_ready(chan_ctx->m2m_ctx) > 0) {
+		src_vb = v4l2_m2m_src_buf_remove(chan_ctx->m2m_ctx);
+		if (src_vb)
+			v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_ERROR);
+	}
+
+	while (v4l2_m2m_num_dst_bufs_ready(chan_ctx->m2m_ctx) > 0) {
+		dst_vb = v4l2_m2m_dst_buf_remove(chan_ctx->m2m_ctx);
+		if (dst_vb)
+			v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_ERROR);
+	}
+
+	v4l2_m2m_job_finish(chan_ctx->m2m_dev, chan_ctx->m2m_ctx);
+	spin_unlock(&xm2msc->lock);
+}
+
+static void xm2msc_job_abort(void *priv)
+{
+	struct xm2msc_chan_ctx *chan_ctx = priv;
+
+	xm2msc_chan_abort_bufs(chan_ctx);
+
+	/*
+	 * Stream off the channel as job_abort may not always
+	 * be called after streamoff
+	 */
+	xm2msc_set_chan_stream(chan_ctx, false, XM2MSC_CHAN_OUT);
+	xm2msc_set_chan_stream(chan_ctx, false, XM2MSC_CHAN_CAP);
+}
+
+static int xm2msc_set_bufaddr(struct xm2m_msc_dev *xm2msc)
+{
+	unsigned int chan;
+	u32 row_align;
+	struct xm2msc_chan_ctx *chan_ctx;
+	struct vb2_v4l2_buffer *src_vb, *dst_vb;
+	void __iomem *base;
+	struct xm2msc_q_data *q_data;
+	dma_addr_t src_luma, dst_luma;
+	dma_addr_t src_croma, dst_croma;
+
+	if (!xm2msc_alljob_ready(xm2msc))
+		return -EINVAL;
+
+	for (chan = 0; chan < xm2msc->running_chan; chan++) {
+		chan_ctx = &xm2msc->xm2msc_chan[chan];
+		base = chan_ctx->regs;
+
+		src_vb = v4l2_m2m_next_src_buf(chan_ctx->m2m_ctx);
+		dst_vb = v4l2_m2m_next_dst_buf(chan_ctx->m2m_ctx);
+
+		if (!src_vb || !dst_vb) {
+			v4l2_err(&xm2msc->v4l2_dev, "buffer not found chan = %d\n",
+				 chan_ctx->num);
+			return -EINVAL;
+		}
+
+		src_luma = vb2_dma_contig_plane_dma_addr(&src_vb->vb2_buf, 0);
+		dst_luma = vb2_dma_contig_plane_dma_addr(&dst_vb->vb2_buf, 0);
+
+		q_data = &chan_ctx->q_data[XM2MSC_CHAN_OUT];
+		row_align = chan_ctx->output_height_align;
+		if (chan_ctx->q_data[XM2MSC_CHAN_OUT].nbuffs == 2)
+			/* fmts having 2 planes 2 buffers */
+			src_croma =
+				vb2_dma_contig_plane_dma_addr(&src_vb->vb2_buf,
+							      1);
+		else if (xm2msc_is_yuv_singlebuff(q_data->fmt->fourcc))
+			/* fmts having 2 planes 1 contiguous buffer */
+			src_croma = src_luma +
+				xm2msc_yuv_1stplane_size(q_data, row_align);
+		else /* fmts having 1 planes 1 contiguous buffer */
+			src_croma = 0;
+
+		q_data = &chan_ctx->q_data[XM2MSC_CHAN_CAP];
+		row_align = chan_ctx->capture_height_align;
+		if (chan_ctx->q_data[XM2MSC_CHAN_CAP].nbuffs == 2)
+			dst_croma =
+				vb2_dma_contig_plane_dma_addr(&dst_vb->vb2_buf,
+							      1);
+		else if (xm2msc_is_yuv_singlebuff(q_data->fmt->fourcc))
+			dst_croma = dst_luma +
+				xm2msc_yuv_1stplane_size(q_data, row_align);
+		else
+			dst_croma = 0;
+
+		if (xm2msc->dma_addr_size == 64 &&
+		    sizeof(dma_addr_t) == sizeof(u64)) {
+			xm2msc_write64reg(base + XM2MSC_SRCIMGBUF0, src_luma);
+			xm2msc_write64reg(base + XM2MSC_SRCIMGBUF1, src_croma);
+			xm2msc_write64reg(base + XM2MSC_DSTIMGBUF0, dst_luma);
+			if (chan_ctx->num == 4) /* TODO: To be fixed in HW */
+				xm2msc_write64reg(base + XM2MSC_DSTIMGBUF1 +
+						  XM2MSC_RESERVED_AREA,
+						  dst_croma);
+			else
+				xm2msc_write64reg(base + XM2MSC_DSTIMGBUF1,
+						  dst_croma);
+		} else {
+			xm2msc_writereg(base + XM2MSC_SRCIMGBUF0, src_luma);
+			xm2msc_writereg(base + XM2MSC_SRCIMGBUF1, src_croma);
+			xm2msc_writereg(base + XM2MSC_DSTIMGBUF0, dst_luma);
+			if (chan_ctx->num == 4) /* TODO: To be fixed in HW */
+				xm2msc_writereg(base + XM2MSC_DSTIMGBUF1 +
+						XM2MSC_RESERVED_AREA,
+						dst_croma);
+			else
+				xm2msc_writereg(base + XM2MSC_DSTIMGBUF1,
+						dst_croma);
+		}
+	}
+	return 0;
+}
+
+static void xm2msc_job_finish(struct xm2m_msc_dev *xm2msc)
+{
+	unsigned int chan;
+
+	for (chan = 0; chan < xm2msc->running_chan; chan++) {
+		struct xm2msc_chan_ctx *chan_ctx;
+
+		chan_ctx = &xm2msc->xm2msc_chan[chan];
+		v4l2_m2m_job_finish(chan_ctx->m2m_dev, chan_ctx->m2m_ctx);
+	}
+}
+
+static void xm2msc_job_done(struct xm2m_msc_dev *xm2msc)
+{
+	u32 chan;
+
+	for (chan = 0; chan < xm2msc->running_chan; chan++) {
+		struct xm2msc_chan_ctx *chan_ctx;
+		struct vb2_v4l2_buffer *src_vb, *dst_vb;
+		unsigned long flags;
+
+		chan_ctx = &xm2msc->xm2msc_chan[chan];
+
+		src_vb = v4l2_m2m_src_buf_remove(chan_ctx->m2m_ctx);
+		dst_vb = v4l2_m2m_dst_buf_remove(chan_ctx->m2m_ctx);
+
+		if (src_vb && dst_vb) {
+			dst_vb->vb2_buf.timestamp = src_vb->vb2_buf.timestamp;
+			dst_vb->timecode = src_vb->timecode;
+			dst_vb->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+			dst_vb->flags |=
+			    src_vb->flags & V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
+
+			spin_lock_irqsave(&xm2msc->lock, flags);
+			v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
+			v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);
+			spin_unlock_irqrestore(&xm2msc->lock, flags);
+		}
+		chan_ctx->frames++;
+	}
+}
+
+static void xm2msc_device_run(void *priv)
+{
+	struct xm2msc_chan_ctx *chan_ctx = priv;
+	struct xm2m_msc_dev *xm2msc = chan_ctx->xm2msc_dev;
+	void __iomem *base = xm2msc->regs;
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&xm2msc->lock, flags);
+	if (xm2msc->device_busy) {
+		spin_unlock_irqrestore(&xm2msc->lock, flags);
+		return;
+	}
+	xm2msc->device_busy = true;
+
+	if (xm2msc->running_chan != NUM_STREAM(xm2msc)) {
+		dev_dbg(xm2msc->dev, "Running chan was %d\n",
+			xm2msc->running_chan);
+		xm2msc->running_chan = NUM_STREAM(xm2msc);
+
+		/* IP need reset for updating of XM2MSC_NUM_OUT */
+		xm2msc_reset(xm2msc);
+		xm2msc_writereg(base + XM2MSC_NUM_OUTS, xm2msc->running_chan);
+		ret = xm2msc_program_allchan(xm2msc);
+		if (ret) {
+			spin_unlock_irqrestore(&xm2msc->lock, flags);
+			xm2msc->device_busy = false;
+			return;
+		}
+	}
+	spin_unlock_irqrestore(&xm2msc->lock, flags);
+
+	dev_dbg(xm2msc->dev, "Running chan = %d\n", xm2msc->running_chan);
+	if (!xm2msc->running_chan) {
+		xm2msc->device_busy = false;
+		return;
+	}
+
+	ret = xm2msc_set_bufaddr(xm2msc);
+	if (ret) {
+		/*
+		 * All channel does not have buffer
+		 * Currently we do not handle the removal of any Intermediate
+		 * channel while streaming is going on
+		 */
+		if (xm2msc->out_streamed_chan || xm2msc->cap_streamed_chan)
+			dev_err(xm2msc->dev,
+				"Buffer not available, streaming chan 0x%x\n",
+				xm2msc->cap_streamed_chan);
+
+		xm2msc->device_busy = false;
+		return;
+	}
+
+	xm2msc_writereg(base + XM2MSC_GIE, XM2MSC_GIE_EN);
+	xm2msc_writereg(base + XM2MSC_IER, XM2MSC_ISR_DONE);
+
+	xm2msc_pr_status(xm2msc, __func__);
+	xm2msc_pr_screg(xm2msc->dev, base);
+	xm2msc_pr_allchanreg(xm2msc);
+
+	xm2msc_start(xm2msc);
+
+	xm2msc->isr_wait = true;
+	wait_event(xm2msc->isr_finished, !xm2msc->isr_wait);
+
+	xm2msc_job_done(xm2msc);
+
+	xm2msc->device_busy = false;
+
+	if (xm2msc_alljob_ready(xm2msc))
+		xm2msc_device_run(xm2msc->xm2msc_chan);
+
+	xm2msc_job_finish(xm2msc);
+}
+
+static irqreturn_t xm2msc_isr(int irq, void *data)
+{
+	struct xm2m_msc_dev *xm2msc = (struct xm2m_msc_dev *)data;
+	void __iomem *base = xm2msc->regs;
+	u32 status;
+
+	status = xm2msc_readreg(base + XM2MSC_ISR);
+	if (!(status & XM2MSC_ISR_DONE))
+		return IRQ_NONE;
+
+	xm2msc_writereg(base + XM2MSC_ISR, status & XM2MSC_ISR_DONE);
+
+	xm2msc_stop(xm2msc);
+
+	xm2msc->isr_wait = false;
+	wake_up(&xm2msc->isr_finished);
+
+	return IRQ_HANDLED;
+}
+
+static int xm2msc_streamon(struct file *file, void *fh,
+			   enum v4l2_buf_type type)
+{
+	struct xm2msc_chan_ctx *chan_ctx = fh_to_chanctx(fh);
+
+	return v4l2_m2m_streamon(file, chan_ctx->m2m_ctx, type);
+}
+
+static int xm2msc_streamoff(struct file *file, void *fh,
+			    enum v4l2_buf_type type)
+{
+	struct xm2msc_chan_ctx *chan_ctx = fh_to_chanctx(fh);
+	int ret;
+
+	ret = v4l2_m2m_streamoff(file, chan_ctx->m2m_ctx, type);
+
+	/* Check if any channel is still running */
+	xm2msc_device_run(chan_ctx);
+	return ret;
+}
+
+static int xm2msc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
+{
+	struct xm2msc_chan_ctx *chan_ctx = fh_to_chanctx(fh);
+
+	return v4l2_m2m_qbuf(file, chan_ctx->m2m_ctx, buf);
+}
+
+static int xm2msc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
+{
+	struct xm2msc_chan_ctx *chan_ctx = fh_to_chanctx(fh);
+
+	return v4l2_m2m_dqbuf(file, chan_ctx->m2m_ctx, buf);
+}
+
+static int xm2msc_expbuf(struct file *file, void *fh,
+			 struct v4l2_exportbuffer *eb)
+{
+	struct xm2msc_chan_ctx *chan_ctx = fh_to_chanctx(fh);
+
+	return v4l2_m2m_expbuf(file, chan_ctx->m2m_ctx, eb);
+}
+
+static int xm2msc_createbufs(struct file *file, void *fh,
+			     struct v4l2_create_buffers *cb)
+{
+	struct xm2msc_chan_ctx *chan_ctx = fh_to_chanctx(fh);
+
+	return v4l2_m2m_create_bufs(file, chan_ctx->m2m_ctx, cb);
+}
+
+static int xm2msc_reqbufs(struct file *file, void *fh,
+			  struct v4l2_requestbuffers *reqbufs)
+{
+	struct xm2msc_chan_ctx *chan_ctx = fh_to_chanctx(fh);
+
+	return v4l2_m2m_reqbufs(file, chan_ctx->m2m_ctx, reqbufs);
+}
+
+static int xm2msc_querybuf(struct file *file, void *fh,
+			   struct v4l2_buffer *buf)
+{
+	struct xm2msc_chan_ctx *chan_ctx = fh_to_chanctx(fh);
+
+	return v4l2_m2m_querybuf(file, chan_ctx->m2m_ctx, buf);
+}
+
+static void
+xm2msc_cal_imagesize(struct xm2msc_chan_ctx *chan_ctx,
+		     struct xm2msc_q_data *q_data, u32 type)
+{
+	unsigned int i;
+	u32 fourcc = q_data->fmt->fourcc;
+	u32 height = q_data->height;
+
+	if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+		height = ALIGN(height, chan_ctx->output_height_align);
+	else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+		height = ALIGN(height, chan_ctx->capture_height_align);
+
+	for (i = 0; i < q_data->nbuffs; i++) {
+		q_data->bytesperline[i] = q_data->stride;
+		q_data->sizeimage[i] = q_data->stride * height;
+	}
+
+	switch (fourcc) {
+	case V4L2_PIX_FMT_NV12:
+	case V4L2_PIX_FMT_XV15:
+		/*
+		 * Adding chroma plane size as NV12/XV15
+		 * have a contiguous buffer for luma and chroma
+		 */
+		q_data->sizeimage[0] +=
+				q_data->stride * (height / 2);
+		break;
+	case V4L2_PIX_FMT_NV12M:
+	case V4L2_PIX_FMT_XV15M:
+		q_data->sizeimage[1] =
+				q_data->stride * (height / 2);
+		break;
+	default:
+		break;
+	}
+}
+
+static unsigned int
+xm2msc_cal_stride(unsigned int width, enum xm2msc_pix_fmt xfmt, u8 ppc)
+{
+	unsigned int stride;
+	u32 align;
+
+	/* Stride in Bytes = (Width × Bytes per Pixel); */
+	switch (xfmt) {
+	case XILINX_M2MSC_FMT_RGBX8:
+	case XILINX_M2MSC_FMT_YUVX8:
+	case XILINX_M2MSC_FMT_RGBX10:
+	case XILINX_M2MSC_FMT_YUVX10:
+	case XILINX_M2MSC_FMT_BGRX8:
+		stride = width * 4;
+		break;
+	case XILINX_M2MSC_FMT_YUYV8:
+	case XILINX_M2MSC_FMT_UYVY8:
+		stride = width * 2;
+		break;
+	case XILINX_M2MSC_FMT_Y_UV8:
+	case XILINX_M2MSC_FMT_Y_UV8_420:
+	case XILINX_M2MSC_FMT_Y8:
+		stride = width * 1;
+		break;
+	case XILINX_M2MSC_FMT_RGB8:
+	case XILINX_M2MSC_FMT_YUV8:
+	case XILINX_M2MSC_FMT_BGR8:
+		stride = width * 3;
+		break;
+	case XILINX_M2MSC_FMT_Y_UV10:
+	case XILINX_M2MSC_FMT_Y_UV10_420:
+	case XILINX_M2MSC_FMT_Y10:
+		/* 4 bytes per 3 pixels */
+		stride = DIV_ROUND_UP(width * 4, 3);
+		break;
+	default:
+		stride = 0;
+	}
+
+	/* The data size is 64*pixels per clock bits */
+	align = ppc * XM2MSC_ALIGN_MUL;
+	stride = ALIGN(stride, align);
+
+	return stride;
+}
+
+static int
+vidioc_try_fmt(struct xm2msc_chan_ctx *chan_ctx, struct v4l2_format *f)
+{
+	struct xm2m_msc_dev *xm2msc = chan_ctx->xm2msc_dev;
+	struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
+	struct xm2msc_q_data *q_data;
+	struct vb2_queue *vq;
+	int index;
+
+	if (pix->width < XM2MSC_MIN_WIDTH || pix->width > xm2msc->max_wd ||
+	    pix->height < XM2MSC_MIN_HEIGHT || pix->height > xm2msc->max_ht)
+		dev_dbg(xm2msc->dev,
+			"Wrong input parameters %d, wxh: %dx%d.\n",
+			f->type, f->fmt.pix.width, f->fmt.pix.height);
+
+	/* The width value must be a multiple of pixels per clock */
+	if (pix->width % chan_ctx->xm2msc_dev->ppc) {
+		dev_dbg(xm2msc->dev,
+			"Wrong align parameters %d, wxh: %dx%d.\n",
+			f->type, f->fmt.pix.width, f->fmt.pix.height);
+		pix->width = ALIGN(pix->width, chan_ctx->xm2msc_dev->ppc);
+	}
+
+	/*
+	 * V4L2 specification suggests the driver corrects the
+	 * format struct if any of the dimensions is unsupported
+	 */
+	if (pix->height < XM2MSC_MIN_HEIGHT)
+		pix->height = XM2MSC_MIN_HEIGHT;
+	else if (pix->height > xm2msc->max_ht)
+		pix->height = xm2msc->max_ht;
+
+	if (pix->width < XM2MSC_MIN_WIDTH)
+		pix->width = XM2MSC_MIN_WIDTH;
+	else if (pix->width > xm2msc->max_wd)
+		pix->width = xm2msc->max_wd;
+
+	vq = v4l2_m2m_get_vq(chan_ctx->m2m_ctx, (enum v4l2_buf_type)f->type);
+	if (!vq)
+		return -EINVAL;
+
+	q_data = get_q_data(chan_ctx, (enum v4l2_buf_type)f->type);
+	if (!q_data)
+		return -EINVAL;
+
+	if (vb2_is_busy(vq)) {
+		v4l2_err(&xm2msc->v4l2_dev,
+			 "%s queue busy\n", __func__);
+		return -EBUSY;
+	}
+
+	q_data->fmt = find_format(f);
+	index = find_format_index(f);
+	if (!q_data->fmt || index == ARRAY_SIZE(formats) ||
+	    !xm2msc_chk_fmt(xm2msc, index)) {
+		v4l2_err(&xm2msc->v4l2_dev,
+			 "Couldn't set format type %d, wxh: %dx%d. ",
+			 f->type, f->fmt.pix.width, f->fmt.pix.height);
+		v4l2_err(&xm2msc->v4l2_dev,
+			 "fmt: %d, field: %d\n",
+			 f->fmt.pix.pixelformat, f->fmt.pix.field);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void xm2msc_get_align(struct xm2msc_chan_ctx *chan_ctx)
+{
+	/*
+	 * TODO: This is a temporary solution, will be reverted once stride and
+	 * height align value come from application.
+	 */
+	chan_ctx->output_stride_align = output_stride_align[chan_ctx->num];
+	chan_ctx->capture_stride_align = capture_stride_align[chan_ctx->num];
+	chan_ctx->output_height_align = output_height_align[chan_ctx->num];
+	chan_ctx->capture_height_align = capture_height_align[chan_ctx->num];
+	if (output_stride_align[chan_ctx->num] != 1 ||
+	    capture_stride_align[chan_ctx->num] != 1 ||
+	    output_height_align[chan_ctx->num] != 1 ||
+	    capture_height_align[chan_ctx->num] != 1) {
+		dev_info(chan_ctx->xm2msc_dev->dev,
+			 "You entered values other than default values.\n");
+		dev_info(chan_ctx->xm2msc_dev->dev,
+			 "Please note this may not be available for longer");
+		dev_info(chan_ctx->xm2msc_dev->dev,
+			 "and align values will come from application\n");
+		dev_info(chan_ctx->xm2msc_dev->dev,
+			 "value entered are -\n"
+			 "output_stride_align = %d\n"
+			 "output_height_align = %d\n"
+			 "capture_stride_align = %d\n"
+			 "capture_height_align = %d\n",
+			chan_ctx->output_stride_align,
+			chan_ctx->output_height_align,
+			chan_ctx->capture_stride_align,
+			chan_ctx->capture_height_align);
+	}
+}
+
+static int
+vidioc_s_fmt(struct xm2msc_chan_ctx *chan_ctx, struct v4l2_format *f)
+{
+	struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
+	struct xm2msc_q_data *q_data;
+	unsigned int i;
+	unsigned int align = 1;
+
+	q_data = get_q_data(chan_ctx, (enum v4l2_buf_type)f->type);
+	if (!q_data)
+		return -EINVAL;
+
+	q_data->width = pix->width;
+	q_data->height = pix->height;
+	q_data->stride = xm2msc_cal_stride(pix->width,
+					   q_data->fmt->xm2msc_fmt,
+					   chan_ctx->xm2msc_dev->ppc);
+
+	xm2msc_get_align(chan_ctx);
+
+	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+		align = chan_ctx->output_stride_align;
+	else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+		align = chan_ctx->capture_stride_align;
+
+	q_data->stride = ALIGN(q_data->stride, align);
+
+	q_data->colorspace = (enum v4l2_colorspace)pix->colorspace;
+	q_data->field = (enum v4l2_field)pix->field;
+	q_data->nbuffs = q_data->fmt->num_buffs;
+
+	xm2msc_cal_imagesize(chan_ctx, q_data, f->type);
+
+	for (i = 0; i < q_data->nbuffs; i++) {
+		pix->plane_fmt[i].bytesperline = q_data->bytesperline[i];
+		pix->plane_fmt[i].sizeimage = q_data->sizeimage[i];
+	}
+
+	xm2msc_pr_q(chan_ctx->xm2msc_dev->dev, q_data,
+		    chan_ctx->num, f->type, __func__);
+
+	return 0;
+}
+
+static int xm2msc_try_fmt_vid_out(struct file *file, void *fh,
+				  struct v4l2_format *f)
+{
+	struct xm2msc_chan_ctx *chan_ctx = fh_to_chanctx(fh);
+
+	return vidioc_try_fmt(chan_ctx, f);
+}
+
+static int xm2msc_try_fmt_vid_cap(struct file *file, void *fh,
+				  struct v4l2_format *f)
+{
+	struct xm2msc_chan_ctx *chan_ctx = fh_to_chanctx(fh);
+
+	return vidioc_try_fmt(chan_ctx, f);
+}
+
+static int xm2msc_s_fmt_vid_cap(struct file *file, void *fh,
+				struct v4l2_format *f)
+{
+	int ret;
+	struct xm2msc_chan_ctx *chan_ctx = fh_to_chanctx(fh);
+
+	ret = xm2msc_try_fmt_vid_cap(file, fh, f);
+	if (ret)
+		return ret;
+	return vidioc_s_fmt(chan_ctx, f);
+}
+
+static int xm2msc_s_fmt_vid_out(struct file *file, void *fh,
+				struct v4l2_format *f)
+{
+	int ret;
+	struct xm2msc_chan_ctx *chan_ctx = fh_to_chanctx(fh);
+
+	ret = xm2msc_try_fmt_vid_out(file, fh, f);
+	if (ret)
+		return ret;
+
+	return vidioc_s_fmt(chan_ctx, f);
+}
+
+static int vidioc_g_fmt(struct xm2msc_chan_ctx *chan_ctx, struct v4l2_format *f)
+{
+	struct vb2_queue *vq;
+	struct xm2msc_q_data *q_data;
+	struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
+	unsigned int i;
+
+	vq = v4l2_m2m_get_vq(chan_ctx->m2m_ctx, (enum v4l2_buf_type)f->type);
+	if (!vq)
+		return -EINVAL;
+
+	q_data = get_q_data(chan_ctx, (enum v4l2_buf_type)f->type);
+	if (!q_data)
+		return -EINVAL;
+
+	pix->width = q_data->width;
+	pix->height = q_data->height;
+	pix->field = V4L2_FIELD_NONE;
+	pix->pixelformat = q_data->fmt->fourcc;
+	pix->colorspace = q_data->colorspace;
+	pix->num_planes = q_data->nbuffs;
+
+	for (i = 0; i < pix->num_planes; i++) {
+		pix->plane_fmt[i].bytesperline = q_data->bytesperline[i];
+		pix->plane_fmt[i].sizeimage = q_data->sizeimage[i];
+	}
+
+	return 0;
+}
+
+static int xm2msc_g_fmt_vid_out(struct file *file, void *fh,
+				struct v4l2_format *f)
+{
+	struct xm2msc_chan_ctx *chan_ctx = fh_to_chanctx(fh);
+
+	return vidioc_g_fmt(chan_ctx, f);
+}
+
+static int xm2msc_g_fmt_vid_cap(struct file *file, void *fh,
+				struct v4l2_format *f)
+{
+	struct xm2msc_chan_ctx *chan_ctx = fh_to_chanctx(fh);
+
+	return vidioc_g_fmt(chan_ctx, f);
+}
+
+static int enum_fmt(struct xm2m_msc_dev *xm2msc, struct v4l2_fmtdesc *f)
+{
+	const struct xm2msc_fmt *fmt;
+	unsigned int i, enabled = 0;
+
+	for (i = 0; i < ARRAY_SIZE(formats); i++) {
+		if (xm2msc_chk_fmt(xm2msc, i) && enabled++ == f->index)
+			break;
+	}
+
+	if (i == ARRAY_SIZE(formats))
+		/* Format not found */
+		return -EINVAL;
+
+	/* Format found */
+	fmt = &formats[i];
+	strlcpy((char *)f->description, (char *)fmt->name,
+		sizeof(f->description));
+	f->pixelformat = fmt->fourcc;
+
+	return 0;
+}
+
+static int xm2msc_enum_fmt_vid_cap(struct file *file, void *fh,
+				   struct v4l2_fmtdesc *f)
+{
+	struct xm2msc_chan_ctx *chan_ctx = fh_to_chanctx(fh);
+
+	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+		return -EINVAL;
+
+	return enum_fmt(chan_ctx->xm2msc_dev, f);
+}
+
+static int xm2msc_enum_fmt_vid_out(struct file *file, void *fh,
+				   struct v4l2_fmtdesc *f)
+{
+	struct xm2msc_chan_ctx *chan_ctx = fh_to_chanctx(fh);
+
+	if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+		return -EINVAL;
+
+	return enum_fmt(chan_ctx->xm2msc_dev, f);
+}
+
+static int xm2msc_querycap(struct file *file, void *fh,
+			   struct v4l2_capability *cap)
+{
+	struct xm2msc_chan_ctx *chan_ctx = fh_to_chanctx(fh);
+	struct video_device *vfd = &chan_ctx->vfd;
+
+	strncpy((char *)cap->driver, XM2MSC_DRIVER_NAME,
+		sizeof(cap->driver) - 1);
+	strncpy((char *)cap->card, XM2MSC_DRIVER_NAME, sizeof(cap->card) - 1);
+	snprintf((char *)cap->bus_info, sizeof(cap->bus_info),
+		 "platform:%s", XM2MSC_DRIVER_NAME);
+	cap->device_caps = vfd->device_caps;
+	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+
+	return 0;
+}
+
+static int xm2msc_queue_setup(struct vb2_queue *vq,
+			      unsigned int *nbuffers, unsigned int *nplanes,
+			      unsigned int sizes[], struct device *alloc_devs[])
+{
+	unsigned int i;
+	struct xm2msc_chan_ctx *chan_ctx = vb2_get_drv_priv(vq);
+	struct xm2msc_q_data *q_data;
+
+	q_data = get_q_data(chan_ctx, (enum v4l2_buf_type)vq->type);
+	if (!q_data)
+		return -EINVAL;
+
+	*nplanes = q_data->nbuffs;
+
+	for (i = 0; i < *nplanes; i++)
+		sizes[i] = q_data->sizeimage[i];
+
+	dev_dbg(chan_ctx->xm2msc_dev->dev, "get %d buffer(s) of size %d",
+		*nbuffers, sizes[0]);
+	if (q_data->nbuffs == 2)
+		dev_dbg(chan_ctx->xm2msc_dev->dev, " and %d\n", sizes[1]);
+
+	return 0;
+}
+
+static int xm2msc_buf_prepare(struct vb2_buffer *vb)
+{
+	struct xm2msc_chan_ctx *chan_ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct xm2m_msc_dev *xm2msc = chan_ctx->xm2msc_dev;
+	struct xm2msc_q_data *q_data;
+	unsigned int i, num_buffs;
+
+	q_data = get_q_data(chan_ctx, (enum v4l2_buf_type)vb->vb2_queue->type);
+	if (!q_data)
+		return -EINVAL;
+	num_buffs = q_data->nbuffs;
+
+	for (i = 0; i < num_buffs; i++) {
+		if (vb2_plane_size(vb, i) < q_data->sizeimage[i]) {
+			v4l2_err(&xm2msc->v4l2_dev, "data will not fit into plane ");
+				   v4l2_err(&xm2msc->v4l2_dev, "(%lu < %lu)\n",
+					    vb2_plane_size(vb, i),
+					    (long)q_data->sizeimage[i]);
+			return -EINVAL;
+		}
+	}
+
+	for (i = 0; i < num_buffs; i++)
+		vb2_set_plane_payload(vb, i, q_data->sizeimage[i]);
+
+	return 0;
+}
+
+static void xm2msc_buf_queue(struct vb2_buffer *vb)
+{
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct xm2msc_chan_ctx *chan_ctx = vb2_get_drv_priv(vb->vb2_queue);
+
+	v4l2_m2m_buf_queue(chan_ctx->m2m_ctx, vbuf);
+}
+
+static void xm2msc_return_all_buffers(struct xm2msc_chan_ctx *chan_ctx,
+				      struct vb2_queue *q,
+				      enum vb2_buffer_state state)
+{
+	struct vb2_v4l2_buffer *vb;
+	unsigned long flags;
+
+	for (;;) {
+		if (V4L2_TYPE_IS_OUTPUT(q->type))
+			vb = v4l2_m2m_src_buf_remove(chan_ctx->m2m_ctx);
+		else
+			vb = v4l2_m2m_dst_buf_remove(chan_ctx->m2m_ctx);
+		if (!vb)
+			break;
+		spin_lock_irqsave(&chan_ctx->xm2msc_dev->lock, flags);
+		v4l2_m2m_buf_done(vb, state);
+		spin_unlock_irqrestore(&chan_ctx->xm2msc_dev->lock, flags);
+	}
+}
+
+static int xm2msc_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+	struct xm2msc_chan_ctx *chan_ctx = vb2_get_drv_priv(q);
+	static struct xm2msc_q_data *q_data;
+	int type;
+	int ret;
+
+	if (V4L2_TYPE_IS_OUTPUT(q->type))
+		xm2msc_set_chan_stream(chan_ctx, true, XM2MSC_CHAN_OUT);
+	else
+		xm2msc_set_chan_stream(chan_ctx, true, XM2MSC_CHAN_CAP);
+
+	ret = xm2msc_set_chan_params(chan_ctx, (enum v4l2_buf_type)q->type);
+	if (ret)
+		return ret;
+
+	if (xm2msc_chk_chan_stream(chan_ctx, XM2MSC_CHAN_CAP) &&
+	    xm2msc_chk_chan_stream(chan_ctx, XM2MSC_CHAN_OUT))
+		xm2msc_set_chan_com_params(chan_ctx);
+
+	type = V4L2_TYPE_IS_OUTPUT(q->type) ?
+		V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE :
+		V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+	q_data = get_q_data(chan_ctx, (enum v4l2_buf_type)type);
+	xm2msc_pr_q(chan_ctx->xm2msc_dev->dev, q_data, chan_ctx->num,
+		    type, __func__);
+	xm2msc_pr_status(chan_ctx->xm2msc_dev, __func__);
+
+	return 0;
+}
+
+static void xm2msc_stop_streaming(struct vb2_queue *q)
+{
+	struct xm2msc_chan_ctx *chan_ctx = vb2_get_drv_priv(q);
+
+	xm2msc_return_all_buffers(chan_ctx, q, VB2_BUF_STATE_ERROR);
+
+	if (V4L2_TYPE_IS_OUTPUT(q->type))
+		xm2msc_set_chan_stream(chan_ctx, false, XM2MSC_CHAN_OUT);
+	else
+		xm2msc_set_chan_stream(chan_ctx, false, XM2MSC_CHAN_CAP);
+}
+
+static const struct vb2_ops xm2msc_qops = {
+	.queue_setup = xm2msc_queue_setup,
+	.buf_prepare = xm2msc_buf_prepare,
+	.buf_queue = xm2msc_buf_queue,
+	.start_streaming = xm2msc_start_streaming,
+	.stop_streaming = xm2msc_stop_streaming,
+};
+
+static int queue_init(void *priv, struct vb2_queue *src_vq,
+		      struct vb2_queue *dst_vq)
+{
+	struct xm2msc_chan_ctx *chan_ctx = priv;
+	struct xm2m_msc_dev *xm2msc = chan_ctx->xm2msc_dev;
+	int ret;
+
+	memset(src_vq, 0, sizeof(*src_vq));
+	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+	src_vq->io_modes = VB2_DMABUF | VB2_MMAP | VB2_USERPTR;
+	src_vq->drv_priv = chan_ctx;
+	src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+	src_vq->ops = &xm2msc_qops;
+	src_vq->mem_ops = &vb2_dma_contig_memops;
+	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	src_vq->lock = &xm2msc->dev_mutex;
+	src_vq->dev = xm2msc->v4l2_dev.dev;
+
+	ret = vb2_queue_init(src_vq);
+	if (ret)
+		return ret;
+
+	memset(dst_vq, 0, sizeof(*dst_vq));
+	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+	dst_vq->io_modes = VB2_MMAP | VB2_DMABUF | VB2_USERPTR;
+	dst_vq->drv_priv = chan_ctx;
+	dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+	dst_vq->ops = &xm2msc_qops;
+	dst_vq->mem_ops = &vb2_dma_contig_memops;
+	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	dst_vq->lock = &xm2msc->dev_mutex;
+	dst_vq->dev = xm2msc->v4l2_dev.dev;
+
+	return vb2_queue_init(dst_vq);
+}
+
+static const struct v4l2_ioctl_ops xm2msc_ioctl_ops = {
+	.vidioc_querycap = xm2msc_querycap,
+
+	.vidioc_enum_fmt_vid_cap = xm2msc_enum_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap_mplane = xm2msc_g_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap_mplane = xm2msc_try_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap_mplane = xm2msc_s_fmt_vid_cap,
+
+	.vidioc_enum_fmt_vid_out = xm2msc_enum_fmt_vid_out,
+	.vidioc_g_fmt_vid_out_mplane = xm2msc_g_fmt_vid_out,
+	.vidioc_try_fmt_vid_out_mplane = xm2msc_try_fmt_vid_out,
+	.vidioc_s_fmt_vid_out_mplane = xm2msc_s_fmt_vid_out,
+
+	.vidioc_reqbufs = xm2msc_reqbufs,
+	.vidioc_querybuf = xm2msc_querybuf,
+	.vidioc_expbuf = xm2msc_expbuf,
+	.vidioc_create_bufs = xm2msc_createbufs,
+
+	.vidioc_qbuf = xm2msc_qbuf,
+	.vidioc_dqbuf = xm2msc_dqbuf,
+
+	.vidioc_streamon = xm2msc_streamon,
+	.vidioc_streamoff = xm2msc_streamoff,
+};
+
+static int xm2msc_set_q_data(struct xm2msc_chan_ctx *chan_ctx,
+			     const struct xm2msc_fmt *fmt,
+			     enum v4l2_buf_type type)
+{
+	struct xm2msc_q_data *q_data;
+	struct xm2m_msc_dev *xm2msc = chan_ctx->xm2msc_dev;
+
+	q_data = get_q_data(chan_ctx, type);
+
+	if (!q_data)
+		return -EINVAL;
+
+	q_data->fmt = fmt;
+	q_data->width = xm2msc->max_wd;
+	q_data->height = xm2msc->max_ht;
+	q_data->field = V4L2_FIELD_NONE;
+	q_data->nbuffs = q_data->fmt->num_buffs;
+
+	q_data->stride = xm2msc_cal_stride(q_data->width,
+				q_data->fmt->xm2msc_fmt,
+				xm2msc->ppc);
+
+	xm2msc_cal_imagesize(chan_ctx, q_data, type);
+
+	return 0;
+}
+
+static int xm2msc_set_chan_parm(struct xm2msc_chan_ctx *chan_ctx)
+{
+	int ret = 0;
+	unsigned int i;
+	struct xm2m_msc_dev *xm2msc = chan_ctx->xm2msc_dev;
+
+	chan_ctx->output_stride_align = 1;
+	chan_ctx->output_height_align = 1;
+	chan_ctx->capture_stride_align = 1;
+	chan_ctx->capture_height_align = 1;
+
+	for (i = 0; i < ARRAY_SIZE(formats); i++) {
+		if (xm2msc_chk_fmt(xm2msc, i))
+			break;
+	}
+
+	/* No supported format */
+	if (i == ARRAY_SIZE(formats)) {
+		dev_err(xm2msc->dev, "no supported format found\n");
+		return -EINVAL;
+	}
+
+	ret = xm2msc_set_q_data(chan_ctx, &formats[i],
+				V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+	if (ret)
+		return ret;
+
+	return xm2msc_set_q_data(chan_ctx, &formats[i],
+				 V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+}
+
+static int xm2msc_open(struct file *file)
+{
+	struct xm2m_msc_dev *xm2msc = video_drvdata(file);
+	struct xm2msc_chan_ctx *chan_ctx = NULL;
+	u32 minor, chan;
+	int ret;
+
+	if (mutex_lock_interruptible(&xm2msc->dev_mutex))
+		return -ERESTARTSYS;
+
+	minor = iminor(file_inode(file));
+
+	for (chan = 0; chan < xm2msc->max_chan; chan++) {
+		chan_ctx = &xm2msc->xm2msc_chan[chan];
+
+		if ((chan_ctx->status & CHAN_ATTACHED) &&
+		    chan_ctx->minor == minor)
+			break;
+	}
+
+	if (chan == xm2msc->max_chan) {
+		v4l2_err(&xm2msc->v4l2_dev,
+			 "%s Chan not found with minor = %d\n",
+			 __func__, minor);
+		ret = -EBADF;
+		goto unlock;
+	}
+
+	/* Already opened, do not allow same channel
+	 * to be open more then once
+	 */
+	if (chan_ctx->status & CHAN_OPENED) {
+		v4l2_warn(&xm2msc->v4l2_dev,
+			  "%s Chan already opened for minor = %d\n",
+			  __func__, minor);
+		ret = -EBUSY;
+		goto unlock;
+	}
+
+	v4l2_fh_init(&chan_ctx->fh, &chan_ctx->vfd);
+	file->private_data = &chan_ctx->fh;
+	v4l2_fh_add(&chan_ctx->fh);
+
+	chan_ctx->m2m_ctx = v4l2_m2m_ctx_init(chan_ctx->m2m_dev,
+					      chan_ctx, &queue_init);
+	if (IS_ERR(chan_ctx->m2m_ctx)) {
+		ret = PTR_ERR(chan_ctx->m2m_ctx);
+		v4l2_err(&xm2msc->v4l2_dev,
+			 "%s Chan M2M CTX not creted for minor %d\n",
+			 __func__, minor);
+		goto error_m2m;
+	}
+
+	chan_ctx->fh.m2m_ctx = chan_ctx->m2m_ctx;
+	chan_ctx->status |= CHAN_OPENED;
+	chan_ctx->xm2msc_dev = xm2msc;
+	chan_ctx->frames = 0;
+
+	xm2msc_set_chan(chan_ctx, true);
+
+	v4l2_info(&xm2msc->v4l2_dev, "Channel %d instance created\n", chan);
+
+	mutex_unlock(&xm2msc->dev_mutex);
+	xm2msc_pr_chanctx(chan_ctx, __func__);
+	xm2msc_pr_status(xm2msc, __func__);
+	return 0;
+
+error_m2m:
+	v4l2_fh_del(&chan_ctx->fh);
+	v4l2_fh_exit(&chan_ctx->fh);
+unlock:
+	mutex_unlock(&xm2msc->dev_mutex);
+	xm2msc_pr_chanctx(chan_ctx, __func__);
+	xm2msc_pr_status(xm2msc, __func__);
+	return ret;
+}
+
+static int xm2msc_release(struct file *file)
+{
+	struct xm2m_msc_dev *xm2msc = video_drvdata(file);
+	struct xm2msc_chan_ctx *chan_ctx = fh_to_chanctx(file->private_data);
+
+	if (mutex_lock_interruptible(&xm2msc->dev_mutex))
+		return -ERESTARTSYS;
+
+	v4l2_m2m_ctx_release(chan_ctx->m2m_ctx);
+	v4l2_fh_del(&chan_ctx->fh);
+	v4l2_fh_exit(&chan_ctx->fh);
+	chan_ctx->status &= ~CHAN_OPENED;
+	xm2msc_set_chan(chan_ctx, false);
+
+	v4l2_info(&xm2msc->v4l2_dev, "Channel %d instance released\n",
+		  chan_ctx->num);
+
+	mutex_unlock(&xm2msc->dev_mutex);
+	return 0;
+}
+
+static unsigned int xm2msc_poll(struct file *file,
+				struct poll_table_struct *wait)
+{
+	struct xm2msc_chan_ctx *chan_ctx = fh_to_chanctx(file->private_data);
+	struct xm2m_msc_dev *xm2msc = chan_ctx->xm2msc_dev;
+	int ret;
+
+	mutex_lock(&xm2msc->dev_mutex);
+	ret = v4l2_m2m_poll(file, chan_ctx->m2m_ctx, wait);
+	mutex_unlock(&xm2msc->dev_mutex);
+
+	return ret;
+}
+
+static int xm2msc_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct xm2msc_chan_ctx *chan_ctx = file->private_data;
+	struct xm2m_msc_dev *xm2msc = chan_ctx->xm2msc_dev;
+	int ret;
+
+	mutex_lock(&xm2msc->dev_mutex);
+	ret = v4l2_m2m_mmap(file, chan_ctx->m2m_ctx, vma);
+
+	mutex_unlock(&xm2msc->dev_mutex);
+	return ret;
+}
+
+static const struct v4l2_file_operations xm2msc_fops = {
+	.owner = THIS_MODULE,
+	.open = xm2msc_open,
+	.release = xm2msc_release,
+	.poll = xm2msc_poll,
+	.unlocked_ioctl = video_ioctl2,
+	.mmap = xm2msc_mmap,
+};
+
+static const struct video_device xm2msc_videodev = {
+	.name = XM2MSC_DRIVER_NAME,
+	.fops = &xm2msc_fops,
+	.ioctl_ops = &xm2msc_ioctl_ops,
+	.minor = -1,
+	.release = video_device_release_empty,
+	.vfl_dir = VFL_DIR_M2M,
+};
+
+static const struct v4l2_m2m_ops xm2msc_m2m_ops = {
+	.device_run = xm2msc_device_run,
+	.job_ready = xm2msc_job_ready,
+	.job_abort = xm2msc_job_abort,
+};
+
+static int xm2msc_parse_of(struct platform_device *pdev,
+			   struct xm2m_msc_dev *xm2msc)
+{
+	struct resource *res;
+	struct device *dev = &pdev->dev;
+	struct device_node *node = dev->of_node;
+	int hw_vid_fmt_cnt;
+	const char *vid_fmts[ARRAY_SIZE(formats)];
+	int ret;
+	u32 i, j;
+
+	xm2msc->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(xm2msc->clk)) {
+		ret = PTR_ERR(xm2msc->clk);
+		dev_err(dev, "failed to get clk (%d)\n", ret);
+		return ret;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	xm2msc->regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR((__force void *)xm2msc->regs))
+		return PTR_ERR((__force const void *)xm2msc->regs);
+
+	dev_dbg(dev, "IO Mem %pa mapped at %p\n", &res->start, xm2msc->regs);
+
+	ret = of_property_read_u32(node, "xlnx,max-chan",
+				   &xm2msc->max_chan);
+	if (ret < 0)
+		return ret;
+
+	if (xm2msc->max_chan < XM2MSC_MIN_CHAN ||
+	    xm2msc->max_chan > XM2MSC_MAX_CHAN) {
+		dev_err(dev,
+			"Invalid maximum scaler channels : %d",
+			xm2msc->max_chan);
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32(node, "xlnx,max-width",
+				   &xm2msc->max_wd);
+	if (ret < 0) {
+		dev_err(dev,
+			"missing xlnx,max-width prop\n");
+		return ret;
+	}
+
+	if (xm2msc->max_wd < XM2MSC_MIN_WIDTH ||
+	    xm2msc->max_wd > XM2MSC_MAX_WIDTH) {
+		dev_err(dev, "Invalid width : %d",
+			xm2msc->max_wd);
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32(node, "xlnx,max-height",
+				   &xm2msc->max_ht);
+	if (ret < 0) {
+		dev_err(dev, "missing xlnx,max-height prop\n");
+		return ret;
+	}
+
+	if (xm2msc->max_ht < XM2MSC_MIN_HEIGHT ||
+	    xm2msc->max_ht > XM2MSC_MAX_HEIGHT) {
+		dev_err(dev, "Invalid height : %d",
+			xm2msc->max_ht);
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32(node, "xlnx,dma-addr-width",
+				   &xm2msc->dma_addr_size);
+	if (ret || (xm2msc->dma_addr_size != 32 &&
+		    xm2msc->dma_addr_size != 64)) {
+		dev_err(dev, "missing/invalid addr width dts prop\n");
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u8(node, "xlnx,pixels-per-clock",
+				  &xm2msc->ppc);
+	if (ret || (xm2msc->ppc != 1 && xm2msc->ppc != 2 && xm2msc->ppc != 4)) {
+		dev_err(dev, "missing or invalid pixels per clock dts prop\n");
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32(node, "xlnx,num-taps",
+				   &xm2msc->taps);
+	if (ret || (xm2msc->taps != XSCALER_TAPS_6 &&
+		    xm2msc->taps != XSCALER_TAPS_8 &&
+		    xm2msc->taps != XSCALER_TAPS_10 &&
+		    xm2msc->taps != XSCALER_TAPS_12)) {
+		dev_err(dev, "missing/invalid taps in dts prop\n");
+		return -EINVAL;
+	}
+
+	xm2msc->irq = irq_of_parse_and_map(node, 0);
+	if (xm2msc->irq < 0) {
+		dev_err(dev, "Unable to get IRQ");
+		return xm2msc->irq;
+	}
+
+	dev_dbg(dev, "Max Channel Supported = %d\n", xm2msc->max_chan);
+	dev_dbg(dev, "DMA Addr width Supported = %d\n", xm2msc->dma_addr_size);
+	dev_dbg(dev, "Max col/row Supported = (%d) / (%d)\n",
+		xm2msc->max_wd, xm2msc->max_ht);
+	dev_dbg(dev, "taps Supported = %d\n", xm2msc->taps);
+	/* read supported video formats and update internal table */
+	hw_vid_fmt_cnt = of_property_count_strings(node, "xlnx,vid-formats");
+
+	ret = of_property_read_string_array(node, "xlnx,vid-formats",
+					    vid_fmts, hw_vid_fmt_cnt);
+	if (ret < 0) {
+		dev_err(dev,
+			"Missing or invalid xlnx,vid-formats dts prop\n");
+		return ret;
+	}
+
+	dev_dbg(dev, "Supported format = ");
+	for (i = 0; i < hw_vid_fmt_cnt; i++) {
+		const char *vid_fmt_name = vid_fmts[i];
+
+		for (j = 0; j < ARRAY_SIZE(formats); j++) {
+			const char *dts_name = formats[j].name;
+
+			if (strcmp(vid_fmt_name, dts_name))
+				continue;
+			dev_dbg(dev, "%s ", dts_name);
+
+			xm2msc_set_fmt(xm2msc, j);
+		}
+	}
+	dev_dbg(dev, "\n");
+	xm2msc->rst_gpio = devm_gpiod_get(dev, "reset",
+					  GPIOD_OUT_HIGH);
+	if (IS_ERR(xm2msc->rst_gpio)) {
+		ret = PTR_ERR(xm2msc->rst_gpio);
+		if (ret == -EPROBE_DEFER)
+			dev_info(dev,
+				 "Probe deferred due to GPIO reset defer\n");
+		else
+			dev_err(dev,
+				"Unable to locate reset property in dt\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static void xm2msc_unreg_video_n_m2m(struct xm2m_msc_dev *xm2msc)
+{
+	struct xm2msc_chan_ctx *chan_ctx;
+	unsigned int chan;
+
+	for (chan = 0; chan < xm2msc->max_chan; chan++) {
+		chan_ctx = &xm2msc->xm2msc_chan[chan];
+		if (!(chan_ctx->status & CHAN_ATTACHED))
+			break;	/*We register video sequentially */
+		video_unregister_device(&chan_ctx->vfd);
+		chan_ctx->status &= ~CHAN_ATTACHED;
+
+		if (!IS_ERR(chan_ctx->m2m_dev))
+			v4l2_m2m_release(chan_ctx->m2m_dev);
+	}
+}
+
+static int xm2m_msc_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct xm2m_msc_dev *xm2msc;
+	struct xm2msc_chan_ctx *chan_ctx;
+	struct video_device *vfd;
+	unsigned int chan;
+
+	xm2msc = devm_kzalloc(&pdev->dev, sizeof(*xm2msc), GFP_KERNEL);
+	if (!xm2msc)
+		return -ENOMEM;
+
+	ret = xm2msc_parse_of(pdev, xm2msc);
+	if (ret < 0)
+		return ret;
+
+	xm2msc->dev = &pdev->dev;
+
+	ret = clk_prepare_enable(xm2msc->clk);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to enable clk (%d)\n", ret);
+		return ret;
+	}
+
+	xm2msc_reset(xm2msc);
+
+	spin_lock_init(&xm2msc->lock);
+
+	ret = v4l2_device_register(&pdev->dev, &xm2msc->v4l2_dev);
+	if (ret)
+		goto reg_dev_err;
+
+	for (chan = 0; chan < xm2msc->max_chan; chan++) {
+		chan_ctx = &xm2msc->xm2msc_chan[chan];
+
+		vfd = &chan_ctx->vfd;
+		*vfd = xm2msc_videodev;
+		vfd->lock = &xm2msc->dev_mutex;
+		vfd->v4l2_dev = &xm2msc->v4l2_dev;
+		vfd->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE |
+				   V4L2_CAP_STREAMING;
+
+		ret = video_register_device(vfd, VFL_TYPE_GRABBER, chan);
+		if (ret) {
+			v4l2_err(&xm2msc->v4l2_dev,
+				 "Failed to register video dev for chan %d\n",
+				 chan);
+			goto unreg_dev;
+		}
+
+		chan_ctx->status = CHAN_ATTACHED;
+
+		video_set_drvdata(vfd, xm2msc);
+		snprintf(vfd->name, sizeof(vfd->name),
+			 "%s", xm2msc_videodev.name);
+		v4l2_info(&xm2msc->v4l2_dev,
+			  " Device registered as /dev/video%d\n", vfd->num);
+
+		dev_dbg(xm2msc->dev, "%s Device registered as /dev/video%d\n",
+			__func__, vfd->num);
+
+		chan_ctx->m2m_dev = v4l2_m2m_init(&xm2msc_m2m_ops);
+		if (IS_ERR(chan_ctx->m2m_dev)) {
+			v4l2_err(&xm2msc->v4l2_dev,
+				 "Failed to init mem2mem device for chan %d\n",
+				 chan);
+			ret = PTR_ERR(chan_ctx->m2m_dev);
+			goto unreg_dev;
+		}
+		chan_ctx->xm2msc_dev = xm2msc;
+		chan_ctx->regs = xm2msc->regs + XM2MSC_CHAN_REGS_START(chan);
+		if (chan > 4) /* TODO: To be fixed in HW */
+			chan_ctx->regs += XM2MSC_RESERVED_AREA;
+		chan_ctx->num = chan;
+		chan_ctx->minor = vfd->minor;
+
+		/* Set channel parameters to default values */
+		ret = xm2msc_set_chan_parm(chan_ctx);
+		if (ret)
+			goto unreg_dev;
+
+		xm2msc_pr_chanctx(chan_ctx, __func__);
+	}
+
+	mutex_init(&xm2msc->dev_mutex);
+	mutex_init(&xm2msc->mutex);
+	init_waitqueue_head(&xm2msc->isr_finished);
+
+	ret = devm_request_irq(&pdev->dev, xm2msc->irq,
+			       xm2msc_isr, IRQF_SHARED,
+			       XM2MSC_DRIVER_NAME, xm2msc);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Unable to register IRQ\n");
+		goto unreg_dev;
+	}
+
+	platform_set_drvdata(pdev, xm2msc);
+
+	return 0;
+
+unreg_dev:
+	xm2msc_unreg_video_n_m2m(xm2msc);
+	v4l2_device_unregister(&xm2msc->v4l2_dev);
+reg_dev_err:
+	clk_disable_unprepare(xm2msc->clk);
+	return ret;
+}
+
+static int xm2m_msc_remove(struct platform_device *pdev)
+{
+	struct xm2m_msc_dev *xm2msc = platform_get_drvdata(pdev);
+
+	xm2msc_unreg_video_n_m2m(xm2msc);
+	v4l2_device_unregister(&xm2msc->v4l2_dev);
+	clk_disable_unprepare(xm2msc->clk);
+	return 0;
+}
+
+static const struct of_device_id xm2m_msc_of_id_table[] = {
+	{.compatible = "xlnx,v-multi-scaler-v1.0"},
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, xm2m_msc_of_id_table);
+
+static struct platform_driver xm2m_msc_driver = {
+	.driver = {
+		.name = "xilinx-multiscaler",
+		.of_match_table = xm2m_msc_of_id_table,
+	},
+	.probe = xm2m_msc_probe,
+	.remove = xm2m_msc_remove,
+};
+
+module_platform_driver(xm2m_msc_driver);
+
+MODULE_DESCRIPTION("Xilinx M2M Multi-Scaler Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("xlnx_m2m_multiscaler_dev");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/xilinx-remapper.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/xilinx-remapper.c
@@ -0,0 +1,566 @@
+/*
+ * Xilinx Video Remapper
+ *
+ * Copyright (C) 2013-2015 Ideas on Board
+ * Copyright (C) 2013-2015 Xilinx, Inc.
+ *
+ * Contacts: Hyun Kwon <hyun.kwon@xilinx.com>
+ *           Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <media/v4l2-async.h>
+#include <media/v4l2-subdev.h>
+
+#include "xilinx-vip.h"
+
+#define XREMAP_MIN_WIDTH			1
+#define XREMAP_DEF_WIDTH			1920
+#define XREMAP_MAX_WIDTH			65535
+#define XREMAP_MIN_HEIGHT			1
+#define XREMAP_DEF_HEIGHT			1080
+#define XREMAP_MAX_HEIGHT			65535
+
+#define XREMAP_PAD_SINK				0
+#define XREMAP_PAD_SOURCE			1
+
+/**
+ * struct xremap_mapping_output - Output format description
+ * @code: media bus pixel core after remapping
+ * @num_components: number of pixel components after remapping
+ * @component_maps: configuration array corresponding to this output
+ */
+struct xremap_mapping_output {
+	u32 code;
+	unsigned int num_components;
+	unsigned int component_maps[4];
+};
+
+/**
+ * struct xremap_mapping - Input-output remapping description
+ * @code: media bus pixel code before remapping
+ * @width: video bus width in bits
+ * @num_components: number of pixel components before remapping
+ * @outputs: array of possible output formats
+ */
+struct xremap_mapping {
+	u32 code;
+	unsigned int width;
+	unsigned int num_components;
+	const struct xremap_mapping_output *outputs;
+};
+
+/**
+ * struct xremap_device - Xilinx Test Pattern Generator device structure
+ * @xvip: Xilinx Video IP device
+ * @pads: media pads
+ * @formats: V4L2 media bus formats at the sink and source pads
+ * @config: device configuration parsed from its DT node
+ * @config.width: video bus width in bits
+ * @config.num_s_components: number of pixel components at the input
+ * @config.num_m_components: number of pixel components at the output
+ * @config.component_maps: component remapping configuration
+ * @default_mapping: Default mapping compatible with the configuration
+ * @default_output: Default output format for the default mapping
+ */
+struct xremap_device {
+	struct xvip_device xvip;
+	struct media_pad pads[2];
+	struct v4l2_mbus_framefmt formats[2];
+
+	struct {
+		unsigned int width;
+		unsigned int num_s_components;
+		unsigned int num_m_components;
+		unsigned int component_maps[4];
+	} config;
+
+	const struct xremap_mapping *default_mapping;
+	const struct xremap_mapping_output *default_output;
+};
+
+static inline struct xremap_device *to_remap(struct v4l2_subdev *subdev)
+{
+	return container_of(subdev, struct xremap_device, xvip.subdev);
+}
+
+/* -----------------------------------------------------------------------------
+ * Mappings
+ */
+
+static const struct xremap_mapping xremap_mappings[] = {
+	{
+		.code = MEDIA_BUS_FMT_RBG888_1X24,
+		.width = 8,
+		.num_components = 3,
+		.outputs = (const struct xremap_mapping_output[]) {
+			{ MEDIA_BUS_FMT_RGB888_1X32_PADHI, 4, { 1, 0, 2, 4 } },
+			{ },
+		},
+	},
+};
+
+static const struct xremap_mapping_output *
+xremap_match_mapping(struct xremap_device *xremap,
+		     const struct xremap_mapping *mapping)
+{
+	const struct xremap_mapping_output *output;
+
+	if (mapping->width != xremap->config.width ||
+	    mapping->num_components != xremap->config.num_s_components)
+		return NULL;
+
+	for (output = mapping->outputs; output->code; ++output) {
+		unsigned int i;
+
+		if (output->num_components != xremap->config.num_m_components)
+			continue;
+
+		for (i = 0; i < output->num_components; ++i) {
+			if (output->component_maps[i] !=
+			    xremap->config.component_maps[i])
+				break;
+		}
+
+		if (i == output->num_components)
+			return output;
+	}
+
+	return NULL;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 Subdevice Pad Operations
+ */
+
+static int xremap_enum_mbus_code(struct v4l2_subdev *subdev,
+				 struct v4l2_subdev_pad_config *cfg,
+				 struct v4l2_subdev_mbus_code_enum *code)
+{
+	struct xremap_device *xremap = to_remap(subdev);
+	struct v4l2_mbus_framefmt *format;
+
+	if (code->pad == XREMAP_PAD_SINK) {
+		const struct xremap_mapping *mapping = NULL;
+		unsigned int index = code->index + 1;
+		unsigned int i;
+
+		/* Iterate through the mappings and skip the ones that don't
+		 * match the remapper configuration until we reach the requested
+		 * index.
+		 */
+		for (i = 0; i < ARRAY_SIZE(xremap_mappings) && index; ++i) {
+			mapping = &xremap_mappings[i];
+
+			if (xremap_match_mapping(xremap, mapping))
+				index--;
+		}
+
+		/* If the index was larger than the number of supported mappings
+		 * return -EINVAL.
+		 */
+		if (index > 0)
+			return -EINVAL;
+
+		code->code = mapping->code;
+	} else {
+		if (code->index)
+			return -EINVAL;
+
+		format = v4l2_subdev_get_try_format(subdev, cfg, code->pad);
+		code->code = format->code;
+	}
+
+	return 0;
+}
+
+static int xremap_enum_frame_size(struct v4l2_subdev *subdev,
+				  struct v4l2_subdev_pad_config *cfg,
+				  struct v4l2_subdev_frame_size_enum *fse)
+{
+	struct v4l2_mbus_framefmt *format;
+
+	format = v4l2_subdev_get_try_format(subdev, cfg, fse->pad);
+
+	if (fse->index || fse->code != format->code)
+		return -EINVAL;
+
+	if (fse->pad == XREMAP_PAD_SINK) {
+		/* The remapper doesn't restrict the size on the sink pad. */
+		fse->min_width = XREMAP_MIN_WIDTH;
+		fse->max_width = XREMAP_MAX_WIDTH;
+		fse->min_height = XREMAP_MIN_HEIGHT;
+		fse->max_height = XREMAP_MAX_HEIGHT;
+	} else {
+		/* The size on the source pad are fixed and always identical to
+		 * the size on the sink pad.
+		 */
+		fse->min_width = format->width;
+		fse->max_width = format->width;
+		fse->min_height = format->height;
+		fse->max_height = format->height;
+	}
+
+	return 0;
+}
+
+static struct v4l2_mbus_framefmt *
+xremap_get_pad_format(struct xremap_device *xremap,
+		      struct v4l2_subdev_pad_config *cfg,
+		      unsigned int pad, u32 which)
+{
+	struct v4l2_mbus_framefmt *format;
+
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		format = v4l2_subdev_get_try_format(&xremap->xvip.subdev, cfg,
+						    pad);
+		break;
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		format = &xremap->formats[pad];
+		break;
+	default:
+		format = NULL;
+		break;
+	}
+
+	return format;
+}
+
+static int xremap_get_format(struct v4l2_subdev *subdev,
+			     struct v4l2_subdev_pad_config *cfg,
+			     struct v4l2_subdev_format *fmt)
+{
+	struct xremap_device *xremap = to_remap(subdev);
+	struct v4l2_mbus_framefmt *format;
+
+	format = xremap_get_pad_format(xremap, cfg, fmt->pad, fmt->which);
+	if (!format)
+		return -EINVAL;
+
+	fmt->format = *format;
+
+	return 0;
+}
+
+static int xremap_set_format(struct v4l2_subdev *subdev,
+			     struct v4l2_subdev_pad_config *cfg,
+			     struct v4l2_subdev_format *fmt)
+{
+	struct xremap_device *xremap = to_remap(subdev);
+	const struct xremap_mapping_output *output = NULL;
+	const struct xremap_mapping *mapping;
+	struct v4l2_mbus_framefmt *format;
+	unsigned int i;
+
+	format = xremap_get_pad_format(xremap, cfg, fmt->pad, fmt->which);
+	if (!format)
+		return -EINVAL;
+
+	if (fmt->pad == XREMAP_PAD_SOURCE) {
+		fmt->format = *format;
+		return 0;
+	}
+
+	/* Find the mapping. If the requested format has no mapping, use the
+	 * default.
+	 */
+	for (i = 0; i < ARRAY_SIZE(xremap_mappings); ++i) {
+		mapping = &xremap_mappings[i];
+		if (mapping->code != fmt->format.code)
+			continue;
+
+		output = xremap_match_mapping(xremap, mapping);
+		if (output)
+			break;
+	}
+
+	if (!output) {
+		mapping = xremap->default_mapping;
+		output = xremap->default_output;
+	}
+
+	format->code = mapping->code;
+	format->width = clamp_t(unsigned int, fmt->format.width,
+				XREMAP_MIN_WIDTH, XREMAP_MAX_WIDTH);
+	format->height = clamp_t(unsigned int, fmt->format.height,
+				 XREMAP_MIN_HEIGHT, XREMAP_MAX_HEIGHT);
+	format->field = V4L2_FIELD_NONE;
+	format->colorspace = V4L2_COLORSPACE_SRGB;
+
+	fmt->format = *format;
+
+	/* Propagate the format to the source pad. */
+	format = xremap_get_pad_format(xremap, cfg, XREMAP_PAD_SOURCE,
+				       fmt->which);
+	if (!format)
+		return -EINVAL;
+	*format = fmt->format;
+	format->code = output->code;
+
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 Subdevice Operations
+ */
+
+/*
+ * xremap_init_formats - Initialize formats on all pads
+ * @subdev: remapper V4L2 subdevice
+ * @fh: V4L2 subdev file handle
+ *
+ * Initialize all pad formats with default values. If fh is not NULL, try
+ * formats are initialized on the file handle. Otherwise active formats are
+ * initialized on the device.
+ */
+static void xremap_init_formats(struct v4l2_subdev *subdev,
+				struct v4l2_subdev_fh *fh)
+{
+	struct xremap_device *xremap = to_remap(subdev);
+	struct v4l2_subdev_format format;
+
+	memset(&format, 0, sizeof(format));
+
+	format.pad = XREMAP_PAD_SINK;
+	format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+	format.format.code = xremap->default_mapping->code;
+	format.format.width = XREMAP_DEF_WIDTH;
+	format.format.height = XREMAP_DEF_HEIGHT;
+
+	xremap_set_format(subdev, fh ? fh->pad : NULL, &format);
+}
+
+static int xremap_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+	xremap_init_formats(subdev, fh);
+
+	return 0;
+}
+
+static int xremap_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+	return 0;
+}
+
+static struct v4l2_subdev_core_ops xremap_core_ops = {
+};
+
+static struct v4l2_subdev_video_ops xremap_video_ops = {
+};
+
+static struct v4l2_subdev_pad_ops xremap_pad_ops = {
+	.enum_mbus_code = xremap_enum_mbus_code,
+	.enum_frame_size = xremap_enum_frame_size,
+	.get_fmt = xremap_get_format,
+	.set_fmt = xremap_set_format,
+};
+
+static struct v4l2_subdev_ops xremap_ops = {
+	.core   = &xremap_core_ops,
+	.video  = &xremap_video_ops,
+	.pad    = &xremap_pad_ops,
+};
+
+static const struct v4l2_subdev_internal_ops xremap_internal_ops = {
+	.open = xremap_open,
+	.close = xremap_close,
+};
+
+/* -----------------------------------------------------------------------------
+ * Media Operations
+ */
+
+static const struct media_entity_operations xremap_media_ops = {
+	.link_validate = v4l2_subdev_link_validate,
+};
+
+/* -----------------------------------------------------------------------------
+ * Platform Device Driver
+ */
+
+static int xremap_parse_of(struct xremap_device *xremap)
+{
+	struct device_node *node = xremap->xvip.dev->of_node;
+	unsigned int i;
+	int ret;
+
+	/* Parse the DT properties. */
+	ret = of_property_read_u32(node, "xlnx,video-width",
+				   &xremap->config.width);
+	if (ret < 0) {
+		dev_dbg(xremap->xvip.dev, "unable to parse %s property\n",
+			"xlnx,video-width");
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32(node, "#xlnx,s-components",
+				   &xremap->config.num_s_components);
+	if (ret < 0) {
+		dev_dbg(xremap->xvip.dev, "unable to parse %s property\n",
+			"#xlnx,s-components");
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32(node, "#xlnx,m-components",
+				   &xremap->config.num_m_components);
+	if (ret < 0) {
+		dev_dbg(xremap->xvip.dev, "unable to parse %s property\n",
+			"#xlnx,m-components");
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32_array(node, "xlnx,component-maps",
+					 xremap->config.component_maps,
+					 xremap->config.num_m_components);
+	if (ret < 0) {
+		dev_dbg(xremap->xvip.dev, "unable to parse %s property\n",
+			"xlnx,component-maps");
+		return -EINVAL;
+	}
+
+	/* Validate the parsed values. */
+	if (xremap->config.num_s_components > 4 ||
+	    xremap->config.num_m_components > 4) {
+		dev_dbg(xremap->xvip.dev,
+			"invalid number of components (s %u m %u)\n",
+			xremap->config.num_s_components,
+			xremap->config.num_m_components);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < xremap->config.num_m_components; ++i) {
+		if (xremap->config.component_maps[i] > 4) {
+			dev_dbg(xremap->xvip.dev, "invalid map %u @%u\n",
+				xremap->config.component_maps[i], i);
+			return -EINVAL;
+		}
+	}
+
+	/* Find the first mapping that matches the remapper configuration and
+	 * store it as the default mapping.
+	 */
+	for (i = 0; i < ARRAY_SIZE(xremap_mappings); ++i) {
+		const struct xremap_mapping_output *output;
+		const struct xremap_mapping *mapping;
+
+		mapping = &xremap_mappings[i];
+		output = xremap_match_mapping(xremap, mapping);
+
+		if (output) {
+			xremap->default_mapping = mapping;
+			xremap->default_output = output;
+			return 0;
+		}
+	}
+
+	dev_err(xremap->xvip.dev,
+		"No format compatible with device configuration\n");
+
+	return -EINVAL;
+}
+
+static int xremap_probe(struct platform_device *pdev)
+{
+	struct xremap_device *xremap;
+	struct v4l2_subdev *subdev;
+	int ret;
+
+	xremap = devm_kzalloc(&pdev->dev, sizeof(*xremap), GFP_KERNEL);
+	if (!xremap)
+		return -ENOMEM;
+
+	xremap->xvip.dev = &pdev->dev;
+
+	ret = xremap_parse_of(xremap);
+	if (ret < 0)
+		return ret;
+
+	xremap->xvip.clk = devm_clk_get(xremap->xvip.dev, NULL);
+	if (IS_ERR(xremap->xvip.clk))
+		return PTR_ERR(xremap->xvip.clk);
+
+	ret = clk_prepare_enable(xremap->xvip.clk);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to enable clk (%d)\n", ret);
+		return ret;
+	}
+
+	/* Initialize V4L2 subdevice and media entity */
+	subdev = &xremap->xvip.subdev;
+	v4l2_subdev_init(subdev, &xremap_ops);
+	subdev->dev = &pdev->dev;
+	subdev->internal_ops = &xremap_internal_ops;
+	strlcpy(subdev->name, dev_name(&pdev->dev), sizeof(subdev->name));
+	v4l2_set_subdevdata(subdev, xremap);
+	subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	xremap_init_formats(subdev, NULL);
+
+	xremap->pads[XREMAP_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+	xremap->pads[XREMAP_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+	subdev->entity.ops = &xremap_media_ops;
+	ret = media_entity_pads_init(&subdev->entity, 2, xremap->pads);
+	if (ret < 0)
+		goto error;
+
+	platform_set_drvdata(pdev, xremap);
+
+	ret = v4l2_async_register_subdev(subdev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to register subdev\n");
+		goto error;
+	}
+
+	dev_info(&pdev->dev, "device registered\n");
+
+	return 0;
+
+error:
+	media_entity_cleanup(&subdev->entity);
+	clk_disable_unprepare(xremap->xvip.clk);
+	return ret;
+}
+
+static int xremap_remove(struct platform_device *pdev)
+{
+	struct xremap_device *xremap = platform_get_drvdata(pdev);
+	struct v4l2_subdev *subdev = &xremap->xvip.subdev;
+
+	v4l2_async_unregister_subdev(subdev);
+	media_entity_cleanup(&subdev->entity);
+
+	clk_disable_unprepare(xremap->xvip.clk);
+
+	return 0;
+}
+
+static const struct of_device_id xremap_of_id_table[] = {
+	{ .compatible = "xlnx,v-remapper" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, xremap_of_id_table);
+
+static struct platform_driver xremap_driver = {
+	.driver = {
+		.name = "xilinx-remapper",
+		.of_match_table = xremap_of_id_table,
+	},
+	.probe = xremap_probe,
+	.remove = xremap_remove,
+};
+
+module_platform_driver(xremap_driver);
+
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_DESCRIPTION("Xilinx Video Remapper Driver");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/xilinx-rgb2yuv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/xilinx-rgb2yuv.c
@@ -0,0 +1,580 @@
+/*
+ * Xilinx RGB to YUV Convertor
+ *
+ * Copyright (C) 2013-2015 Ideas on Board
+ * Copyright (C) 2013-2015 Xilinx, Inc.
+ *
+ * Contacts: Hyun Kwon <hyun.kwon@xilinx.com>
+ *           Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/xilinx-v4l2-controls.h>
+
+#include <media/v4l2-async.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-subdev.h>
+
+#include "xilinx-vip.h"
+
+#define XRGB2YUV_YMAX					0x100
+#define XRGB2YUV_YMIN					0x104
+#define XRGB2YUV_CBMAX					0x108
+#define XRGB2YUV_CBMIN					0x10c
+#define XRGB2YUV_CRMAX					0x110
+#define XRGB2YUV_CRMIN					0x114
+#define XRGB2YUV_YOFFSET				0x118
+#define XRGB2YUV_CBOFFSET				0x11c
+#define XRGB2YUV_CROFFSET				0x120
+#define XRGB2YUV_ACOEF					0x124
+#define XRGB2YUV_BCOEF					0x128
+#define XRGB2YUV_CCOEF					0x12c
+#define XRGB2YUV_DCOEF					0x130
+
+/**
+ * struct xrgb2yuv_device - Xilinx RGB2YUV device structure
+ * @xvip: Xilinx Video IP device
+ * @pads: media pads
+ * @formats: V4L2 media bus formats at the sink and source pads
+ * @default_formats: default V4L2 media bus formats
+ * @vip_formats: Xilinx Video IP formats
+ * @ctrl_handler: control handler
+ */
+struct xrgb2yuv_device {
+	struct xvip_device xvip;
+
+	struct media_pad pads[2];
+
+	struct v4l2_mbus_framefmt formats[2];
+	struct v4l2_mbus_framefmt default_formats[2];
+	const struct xvip_video_format *vip_formats[2];
+
+	struct v4l2_ctrl_handler ctrl_handler;
+};
+
+static inline struct xrgb2yuv_device *to_rgb2yuv(struct v4l2_subdev *subdev)
+{
+	return container_of(subdev, struct xrgb2yuv_device, xvip.subdev);
+}
+
+/*
+ * V4L2 Subdevice Video Operations
+ */
+
+static int xrgb2yuv_s_stream(struct v4l2_subdev *subdev, int enable)
+{
+	struct xrgb2yuv_device *xrgb2yuv = to_rgb2yuv(subdev);
+
+	if (!enable) {
+		xvip_stop(&xrgb2yuv->xvip);
+		return 0;
+	}
+
+	xvip_set_frame_size(&xrgb2yuv->xvip, &xrgb2yuv->formats[XVIP_PAD_SINK]);
+
+	xvip_start(&xrgb2yuv->xvip);
+
+	return 0;
+}
+
+/*
+ * V4L2 Subdevice Pad Operations
+ */
+
+static struct v4l2_mbus_framefmt *
+__xrgb2yuv_get_pad_format(struct xrgb2yuv_device *xrgb2yuv,
+			  struct v4l2_subdev_pad_config *cfg,
+			  unsigned int pad, u32 which)
+{
+	struct v4l2_mbus_framefmt *format;
+
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		format = v4l2_subdev_get_try_format(&xrgb2yuv->xvip.subdev,
+						    cfg, pad);
+		break;
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		format = &xrgb2yuv->formats[pad];
+		break;
+	default:
+		format = NULL;
+		break;
+	}
+
+	return format;
+}
+
+static int xrgb2yuv_get_format(struct v4l2_subdev *subdev,
+			       struct v4l2_subdev_pad_config *cfg,
+			       struct v4l2_subdev_format *fmt)
+{
+	struct xrgb2yuv_device *xrgb2yuv = to_rgb2yuv(subdev);
+	struct v4l2_mbus_framefmt *format;
+
+	format = __xrgb2yuv_get_pad_format(xrgb2yuv, cfg, fmt->pad,
+					   fmt->which);
+	if (!format)
+		return -EINVAL;
+
+	fmt->format = *format;
+
+	return 0;
+}
+
+static int xrgb2yuv_set_format(struct v4l2_subdev *subdev,
+			       struct v4l2_subdev_pad_config *cfg,
+			       struct v4l2_subdev_format *fmt)
+{
+	struct xrgb2yuv_device *xrgb2yuv = to_rgb2yuv(subdev);
+	struct v4l2_mbus_framefmt *format;
+
+	format = __xrgb2yuv_get_pad_format(xrgb2yuv, cfg, fmt->pad, fmt->which);
+	if (!format)
+		return -EINVAL;
+
+	if (fmt->pad == XVIP_PAD_SOURCE) {
+		fmt->format = *format;
+		return 0;
+	}
+
+	xvip_set_format_size(format, fmt);
+
+	fmt->format = *format;
+
+	/* Propagate the format to the source pad. */
+	format = __xrgb2yuv_get_pad_format(xrgb2yuv, cfg, XVIP_PAD_SOURCE,
+					     fmt->which);
+
+	xvip_set_format_size(format, fmt);
+
+	return 0;
+}
+
+/*
+ * V4L2 Subdevice Operations
+ */
+
+static int xrgb2yuv_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+	struct xrgb2yuv_device *xrgb2yuv = to_rgb2yuv(subdev);
+	struct v4l2_mbus_framefmt *format;
+
+	/* Initialize with default formats */
+	format = v4l2_subdev_get_try_format(subdev, fh->pad, XVIP_PAD_SINK);
+	*format = xrgb2yuv->default_formats[XVIP_PAD_SINK];
+
+	format = v4l2_subdev_get_try_format(subdev, fh->pad, XVIP_PAD_SOURCE);
+	*format = xrgb2yuv->default_formats[XVIP_PAD_SOURCE];
+
+	return 0;
+}
+
+static int xrgb2yuv_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+	return 0;
+}
+
+static int xrgb2yuv_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct xrgb2yuv_device *xrgb2yuv =
+		container_of(ctrl->handler, struct xrgb2yuv_device,
+			     ctrl_handler);
+
+	switch (ctrl->id) {
+	case V4L2_CID_XILINX_RGB2YUV_YMAX:
+		xvip_write(&xrgb2yuv->xvip, XRGB2YUV_YMAX, ctrl->val);
+		return 0;
+	case V4L2_CID_XILINX_RGB2YUV_YMIN:
+		xvip_write(&xrgb2yuv->xvip, XRGB2YUV_YMIN, ctrl->val);
+		return 0;
+	case V4L2_CID_XILINX_RGB2YUV_CBMAX:
+		xvip_write(&xrgb2yuv->xvip, XRGB2YUV_CBMAX, ctrl->val);
+		return 0;
+	case V4L2_CID_XILINX_RGB2YUV_CBMIN:
+		xvip_write(&xrgb2yuv->xvip, XRGB2YUV_CBMIN, ctrl->val);
+		return 0;
+	case V4L2_CID_XILINX_RGB2YUV_CRMAX:
+		xvip_write(&xrgb2yuv->xvip, XRGB2YUV_CRMAX, ctrl->val);
+		return 0;
+	case V4L2_CID_XILINX_RGB2YUV_CRMIN:
+		xvip_write(&xrgb2yuv->xvip, XRGB2YUV_CRMIN, ctrl->val);
+		return 0;
+	case V4L2_CID_XILINX_RGB2YUV_YOFFSET:
+		xvip_write(&xrgb2yuv->xvip, XRGB2YUV_YOFFSET, ctrl->val);
+		return 0;
+	case V4L2_CID_XILINX_RGB2YUV_CBOFFSET:
+		xvip_write(&xrgb2yuv->xvip, XRGB2YUV_CBOFFSET, ctrl->val);
+		return 0;
+	case V4L2_CID_XILINX_RGB2YUV_CROFFSET:
+		xvip_write(&xrgb2yuv->xvip, XRGB2YUV_CROFFSET, ctrl->val);
+		return 0;
+	case V4L2_CID_XILINX_RGB2YUV_ACOEF:
+		xvip_write(&xrgb2yuv->xvip, XRGB2YUV_ACOEF, ctrl->val);
+		return 0;
+	case V4L2_CID_XILINX_RGB2YUV_BCOEF:
+		xvip_write(&xrgb2yuv->xvip, XRGB2YUV_BCOEF, ctrl->val);
+		return 0;
+	case V4L2_CID_XILINX_RGB2YUV_CCOEF:
+		xvip_write(&xrgb2yuv->xvip, XRGB2YUV_CCOEF, ctrl->val);
+		return 0;
+	case V4L2_CID_XILINX_RGB2YUV_DCOEF:
+		xvip_write(&xrgb2yuv->xvip, XRGB2YUV_DCOEF, ctrl->val);
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static const struct v4l2_ctrl_ops xrgb2yuv_ctrl_ops = {
+	.s_ctrl	= xrgb2yuv_s_ctrl,
+};
+
+static struct v4l2_subdev_video_ops xrgb2yuv_video_ops = {
+	.s_stream = xrgb2yuv_s_stream,
+};
+
+static struct v4l2_subdev_pad_ops xrgb2yuv_pad_ops = {
+	.enum_mbus_code		= xvip_enum_mbus_code,
+	.enum_frame_size	= xvip_enum_frame_size,
+	.get_fmt		= xrgb2yuv_get_format,
+	.set_fmt		= xrgb2yuv_set_format,
+};
+
+static struct v4l2_subdev_ops xrgb2yuv_ops = {
+	.video  = &xrgb2yuv_video_ops,
+	.pad    = &xrgb2yuv_pad_ops,
+};
+
+static const struct v4l2_subdev_internal_ops xrgb2yuv_internal_ops = {
+	.open	= xrgb2yuv_open,
+	.close	= xrgb2yuv_close,
+};
+
+/*
+ * Control Configs
+ */
+
+static struct v4l2_ctrl_config xrgb2yuv_ctrls[] = {
+	{
+		.ops	= &xrgb2yuv_ctrl_ops,
+		.id	= V4L2_CID_XILINX_RGB2YUV_YMAX,
+		.name	= "RGB to YUV: Maximum Y value",
+		.type	= V4L2_CTRL_TYPE_INTEGER,
+		.min	= 0,
+		.max	= (1 << 16) - 1,
+		.step	= 1,
+	}, {
+		.ops	= &xrgb2yuv_ctrl_ops,
+		.id	= V4L2_CID_XILINX_RGB2YUV_YMIN,
+		.name	= "RGB to YUV: Minimum Y value",
+		.type	= V4L2_CTRL_TYPE_INTEGER,
+		.min	= 0,
+		.max	= (1 << 16) - 1,
+		.step	= 1,
+	}, {
+		.ops	= &xrgb2yuv_ctrl_ops,
+		.id	= V4L2_CID_XILINX_RGB2YUV_CBMAX,
+		.name	= "RGB to YUV: Maximum Cb value",
+		.type	= V4L2_CTRL_TYPE_INTEGER,
+		.min	= 0,
+		.max	= (1 << 16) - 1,
+		.step	= 1,
+	}, {
+		.ops	= &xrgb2yuv_ctrl_ops,
+		.id	= V4L2_CID_XILINX_RGB2YUV_CBMIN,
+		.name	= "RGB to YUV: Minimum Cb value",
+		.type	= V4L2_CTRL_TYPE_INTEGER,
+		.min	= 0,
+		.max	= (1 << 16) - 1,
+		.step	= 1,
+	}, {
+		.ops	= &xrgb2yuv_ctrl_ops,
+		.id	= V4L2_CID_XILINX_RGB2YUV_CRMAX,
+		.name	= "RGB to YUV: Maximum Cr value",
+		.type	= V4L2_CTRL_TYPE_INTEGER,
+		.min	= 0,
+		.max	= (1 << 16) - 1,
+		.step	= 1,
+	}, {
+		.ops	= &xrgb2yuv_ctrl_ops,
+		.id	= V4L2_CID_XILINX_RGB2YUV_CRMIN,
+		.name	= "RGB to YUV: Minimum Cr value",
+		.type	= V4L2_CTRL_TYPE_INTEGER,
+		.min	= 0,
+		.max	= (1 << 16) - 1,
+		.step	= 1,
+	}, {
+		.ops	= &xrgb2yuv_ctrl_ops,
+		.id	= V4L2_CID_XILINX_RGB2YUV_YOFFSET,
+		.name	= "RGB to YUV: Luma offset",
+		.type	= V4L2_CTRL_TYPE_INTEGER,
+		.min	= 0,
+		.max	= (1 << 17) - 1,
+		.step	= 1,
+	}, {
+		.ops	= &xrgb2yuv_ctrl_ops,
+		.id	= V4L2_CID_XILINX_RGB2YUV_CBOFFSET,
+		.name	= "RGB to YUV: Chroma Cb offset",
+		.type	= V4L2_CTRL_TYPE_INTEGER,
+		.min	= 0,
+		.max	= (1 << 17) - 1,
+		.step	= 1,
+	}, {
+		.ops	= &xrgb2yuv_ctrl_ops,
+		.id	= V4L2_CID_XILINX_RGB2YUV_CROFFSET,
+		.name	= "RGB to YUV: Chroma Cr offset",
+		.type	= V4L2_CTRL_TYPE_INTEGER,
+		.min	= 0,
+		.max	= (1 << 17) - 1,
+		.step	= 1,
+	}, {
+		.ops	= &xrgb2yuv_ctrl_ops,
+		.id	= V4L2_CID_XILINX_RGB2YUV_ACOEF,
+		.name	= "RGB to YUV: CA coefficient",
+		.type	= V4L2_CTRL_TYPE_INTEGER,
+		.min	= -((1 << 17) - 1),
+		.max	= (1 << 17) - 1,
+		.step	= 1,
+	}, {
+		.ops	= &xrgb2yuv_ctrl_ops,
+		.id	= V4L2_CID_XILINX_RGB2YUV_BCOEF,
+		.name	= "RGB to YUV: CB coefficient",
+		.type	= V4L2_CTRL_TYPE_INTEGER,
+		.min	= -((1 << 17) - 1),
+		.max	= (1 << 17) - 1,
+		.step	= 1,
+	}, {
+		.ops	= &xrgb2yuv_ctrl_ops,
+		.id	= V4L2_CID_XILINX_RGB2YUV_CCOEF,
+		.name	= "RGB to YUV: CC coefficient",
+		.type	= V4L2_CTRL_TYPE_INTEGER,
+		.min	= -((1 << 17) - 1),
+		.max	= (1 << 17) - 1,
+		.step	= 1,
+	}, {
+		.ops	= &xrgb2yuv_ctrl_ops,
+		.id	= V4L2_CID_XILINX_RGB2YUV_DCOEF,
+		.name	= "RGB to YUV: CD coefficient",
+		.type	= V4L2_CTRL_TYPE_INTEGER,
+		.min	= -((1 << 17) - 1),
+		.max	= (1 << 17) - 1,
+		.step	= 1,
+	},
+};
+
+/*
+ * Media Operations
+ */
+
+static const struct media_entity_operations xrgb2yuv_media_ops = {
+	.link_validate = v4l2_subdev_link_validate,
+};
+
+/*
+ * Power Management
+ */
+
+static int __maybe_unused xrgb2yuv_pm_suspend(struct device *dev)
+{
+	struct xrgb2yuv_device *xrgb2yuv = dev_get_drvdata(dev);
+
+	xvip_suspend(&xrgb2yuv->xvip);
+
+	return 0;
+}
+
+static int __maybe_unused xrgb2yuv_pm_resume(struct device *dev)
+{
+	struct xrgb2yuv_device *xrgb2yuv = dev_get_drvdata(dev);
+
+	xvip_resume(&xrgb2yuv->xvip);
+
+	return 0;
+}
+
+/*
+ * Platform Device Driver
+ */
+
+static int xrgb2yuv_parse_of(struct xrgb2yuv_device *xrgb2yuv)
+{
+	struct device *dev = xrgb2yuv->xvip.dev;
+	struct device_node *node = xrgb2yuv->xvip.dev->of_node;
+	struct device_node *ports;
+	struct device_node *port;
+	u32 port_id;
+	int ret;
+
+	ports = of_get_child_by_name(node, "ports");
+	if (ports == NULL)
+		ports = node;
+
+	/* Get the format description for each pad */
+	for_each_child_of_node(ports, port) {
+		if (port->name && (of_node_cmp(port->name, "port") == 0)) {
+			const struct xvip_video_format *vip_format;
+
+			vip_format = xvip_of_get_format(port);
+			if (IS_ERR(vip_format)) {
+				dev_err(dev, "invalid format in DT");
+				return PTR_ERR(vip_format);
+			}
+
+			ret = of_property_read_u32(port, "reg", &port_id);
+			if (ret < 0) {
+				dev_err(dev, "no reg in DT");
+				return ret;
+			}
+
+			if (port_id != 0 && port_id != 1) {
+				dev_err(dev, "invalid reg in DT");
+				return -EINVAL;
+			}
+
+			xrgb2yuv->vip_formats[port_id] = vip_format;
+		}
+	}
+
+	return 0;
+}
+
+static int xrgb2yuv_probe(struct platform_device *pdev)
+{
+	struct xrgb2yuv_device *xrgb2yuv;
+	struct v4l2_subdev *subdev;
+	struct v4l2_mbus_framefmt *default_format;
+	unsigned int i;
+	int ret;
+
+	xrgb2yuv = devm_kzalloc(&pdev->dev, sizeof(*xrgb2yuv), GFP_KERNEL);
+	if (!xrgb2yuv)
+		return -ENOMEM;
+
+	xrgb2yuv->xvip.dev = &pdev->dev;
+
+	ret = xrgb2yuv_parse_of(xrgb2yuv);
+	if (ret < 0)
+		return ret;
+
+	ret = xvip_init_resources(&xrgb2yuv->xvip);
+	if (ret < 0)
+		return ret;
+
+	/* Reset and initialize the core */
+	xvip_reset(&xrgb2yuv->xvip);
+
+	/* Initialize V4L2 subdevice and media entity */
+	subdev = &xrgb2yuv->xvip.subdev;
+	v4l2_subdev_init(subdev, &xrgb2yuv_ops);
+	subdev->dev = &pdev->dev;
+	subdev->internal_ops = &xrgb2yuv_internal_ops;
+	strlcpy(subdev->name, dev_name(&pdev->dev), sizeof(subdev->name));
+	v4l2_set_subdevdata(subdev, xrgb2yuv);
+	subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	/* Initialize default and active formats */
+	default_format = &xrgb2yuv->default_formats[XVIP_PAD_SINK];
+	default_format->code = xrgb2yuv->vip_formats[XVIP_PAD_SINK]->code;
+	default_format->field = V4L2_FIELD_NONE;
+	default_format->colorspace = V4L2_COLORSPACE_SRGB;
+	xvip_get_frame_size(&xrgb2yuv->xvip, default_format);
+
+	xrgb2yuv->formats[XVIP_PAD_SINK] = *default_format;
+
+	default_format = &xrgb2yuv->default_formats[XVIP_PAD_SOURCE];
+	*default_format = xrgb2yuv->default_formats[XVIP_PAD_SINK];
+	default_format->code = xrgb2yuv->vip_formats[XVIP_PAD_SOURCE]->code;
+
+	xrgb2yuv->formats[XVIP_PAD_SOURCE] = *default_format;
+
+	xrgb2yuv->pads[XVIP_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+	xrgb2yuv->pads[XVIP_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+	subdev->entity.ops = &xrgb2yuv_media_ops;
+	ret = media_entity_pads_init(&subdev->entity, 2, xrgb2yuv->pads);
+	if (ret < 0)
+		goto error;
+
+	v4l2_ctrl_handler_init(&xrgb2yuv->ctrl_handler, 13);
+
+	for (i = 0; i < ARRAY_SIZE(xrgb2yuv_ctrls); i++) {
+		xrgb2yuv_ctrls[i].def = xvip_read(&xrgb2yuv->xvip,
+						  XRGB2YUV_YMAX + i * 4);
+		v4l2_ctrl_new_custom(&xrgb2yuv->ctrl_handler,
+				     &xrgb2yuv_ctrls[i], NULL);
+	}
+
+	if (xrgb2yuv->ctrl_handler.error) {
+		dev_err(&pdev->dev, "failed to add controls\n");
+		ret = xrgb2yuv->ctrl_handler.error;
+		goto error;
+	}
+	subdev->ctrl_handler = &xrgb2yuv->ctrl_handler;
+
+	platform_set_drvdata(pdev, xrgb2yuv);
+
+	xvip_print_version(&xrgb2yuv->xvip);
+
+	ret = v4l2_async_register_subdev(subdev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to register subdev\n");
+		goto error;
+	}
+
+	return 0;
+
+error:
+	v4l2_ctrl_handler_free(&xrgb2yuv->ctrl_handler);
+	media_entity_cleanup(&subdev->entity);
+	xvip_cleanup_resources(&xrgb2yuv->xvip);
+	return ret;
+}
+
+static int xrgb2yuv_remove(struct platform_device *pdev)
+{
+	struct xrgb2yuv_device *xrgb2yuv = platform_get_drvdata(pdev);
+	struct v4l2_subdev *subdev = &xrgb2yuv->xvip.subdev;
+
+	v4l2_async_unregister_subdev(subdev);
+	v4l2_ctrl_handler_free(&xrgb2yuv->ctrl_handler);
+	media_entity_cleanup(&subdev->entity);
+
+	xvip_cleanup_resources(&xrgb2yuv->xvip);
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(xrgb2yuv_pm_ops, xrgb2yuv_pm_suspend,
+			 xrgb2yuv_pm_resume);
+
+static const struct of_device_id xrgb2yuv_of_id_table[] = {
+	{ .compatible = "xlnx,v-rgb2yuv-7.1" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, xrgb2yuv_of_id_table);
+
+static struct platform_driver xrgb2yuv_driver = {
+	.driver			= {
+		.name		= "xilinx-rgb2yuv",
+		.pm		= &xrgb2yuv_pm_ops,
+		.of_match_table	= xrgb2yuv_of_id_table,
+	},
+	.probe			= xrgb2yuv_probe,
+	.remove			= xrgb2yuv_remove,
+};
+
+module_platform_driver(xrgb2yuv_driver);
+
+MODULE_DESCRIPTION("Xilinx RGB to YUV Converter Driver");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/xilinx-scaler.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/xilinx-scaler.c
@@ -0,0 +1,747 @@
+/*
+ * Xilinx Scaler
+ *
+ * Copyright (C) 2013-2015 Ideas on Board
+ * Copyright (C) 2013-2015 Xilinx, Inc.
+ *
+ * Contacts: Hyun Kwon <hyun.kwon@xilinx.com>
+ *           Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/fixp-arith.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <media/v4l2-async.h>
+#include <media/v4l2-subdev.h>
+
+#include "xilinx-vip.h"
+
+#define XSCALER_MIN_WIDTH			32
+#define XSCALER_MAX_WIDTH			4096
+#define XSCALER_MIN_HEIGHT			32
+#define XSCALER_MAX_HEIGHT			4096
+
+#define XSCALER_HSF				0x0100
+#define XSCALER_VSF				0x0104
+#define XSCALER_SF_SHIFT			20
+#define XSCALER_SF_MASK				0xffffff
+#define XSCALER_SOURCE_SIZE			0x0108
+#define XSCALER_SIZE_HORZ_SHIFT			0
+#define XSCALER_SIZE_VERT_SHIFT			16
+#define XSCALER_SIZE_MASK			0xfff
+#define XSCALER_HAPERTURE			0x010c
+#define XSCALER_VAPERTURE			0x0110
+#define XSCALER_APERTURE_START_SHIFT		0
+#define XSCALER_APERTURE_END_SHIFT		16
+#define XSCALER_OUTPUT_SIZE			0x0114
+#define XSCALER_COEF_DATA_IN			0x0134
+#define XSCALER_COEF_DATA_IN_SHIFT		16
+
+/* Fixed point operations */
+#define FRAC_N	8
+
+static inline s16 fixp_new(s16 a)
+{
+	return a << FRAC_N;
+}
+
+static inline s16 fixp_mult(s16 a, s16 b)
+{
+	return ((s32)(a * b)) >> FRAC_N;
+}
+
+/**
+ * struct xscaler_device - Xilinx Scaler device structure
+ * @xvip: Xilinx Video IP device
+ * @pads: media pads
+ * @formats: V4L2 media bus formats at the sink and source pads
+ * @default_formats: default V4L2 media bus formats
+ * @vip_format: Xilinx Video IP format
+ * @crop: Active crop rectangle for the sink pad
+ * @num_hori_taps: number of vertical taps
+ * @num_vert_taps: number of vertical taps
+ * @max_num_phases: maximum number of phases
+ * @separate_yc_coef: separate coefficients for Luma(y) and Chroma(c)
+ * @separate_hv_coef: separate coefficients for Horizontal(h) and Vertical(v)
+ */
+struct xscaler_device {
+	struct xvip_device xvip;
+
+	struct media_pad pads[2];
+
+	struct v4l2_mbus_framefmt formats[2];
+	struct v4l2_mbus_framefmt default_formats[2];
+	const struct xvip_video_format *vip_format;
+	struct v4l2_rect crop;
+
+	u32 num_hori_taps;
+	u32 num_vert_taps;
+	u32 max_num_phases;
+	bool separate_yc_coef;
+	bool separate_hv_coef;
+};
+
+static inline struct xscaler_device *to_scaler(struct v4l2_subdev *subdev)
+{
+	return container_of(subdev, struct xscaler_device, xvip.subdev);
+}
+
+/*
+ * V4L2 Subdevice Video Operations
+ */
+
+/**
+ * lanczos - Lanczos 2D FIR kernel convolution
+ * @x: phase
+ * @a: Lanczos kernel size
+ *
+ * Return: the coefficient value in fixed point format.
+ */
+static s16 lanczos(s16 x, s16 a)
+{
+	s16 pi;
+	s16 numerator;
+	s16 denominator;
+	s16 temp;
+
+	if (x < -a || x > a)
+		return 0;
+	else if (x == 0)
+		return fixp_new(1);
+
+	/* a * sin(pi * x) * sin(pi * x / a) / (pi * pi * x * x) */
+
+	pi = (fixp_new(157) << FRAC_N) / fixp_new(50);
+
+	if (x < 0)
+		x = -x;
+
+	/* sin(pi * x) */
+	temp = fixp_mult(fixp_new(180), x);
+	temp = fixp_sin16(temp >> FRAC_N);
+
+	/* a * sin(pi * x) */
+	numerator = fixp_mult(temp, a);
+
+	/* sin(pi * x / a) */
+	temp = (fixp_mult(fixp_new(180), x) << FRAC_N) / a;
+	temp = fixp_sin16(temp >> FRAC_N);
+
+	/* a * sin(pi * x) * sin(pi * x / a) */
+	numerator = fixp_mult(temp, numerator);
+
+	/* pi * pi * x * x */
+	denominator = fixp_mult(pi, pi);
+	temp = fixp_mult(x, x);
+	denominator = fixp_mult(temp, denominator);
+
+	return (numerator << FRAC_N) / denominator;
+}
+
+/**
+ * xscaler_set_coefs - generate and program the coefficient table
+ * @xscaler: scaler device
+ * @taps: maximum coefficient tap index
+ *
+ * Generate the coefficient table using Lanczos resampling, and program
+ * generated coefficients to the scaler. The generated coefficients are
+ * supposed to work regardless of resolutions.
+ *
+ * Return: 0 if the coefficient table is programmed, and -ENOMEM if memory
+ * allocation for the table fails.
+ */
+static int xscaler_set_coefs(struct xscaler_device *xscaler, s16 taps)
+{
+	s16 *coef;
+	s16 dy;
+	u32 coef_val;
+	u16 phases = xscaler->max_num_phases;
+	u16 i;
+	u16 j;
+
+	coef = kcalloc(phases, sizeof(*coef), GFP_KERNEL);
+	if (!coef)
+		return -ENOMEM;
+
+	for (i = 0; i < phases; i++) {
+		s16 sum = 0;
+
+		dy = ((fixp_new(i) << FRAC_N) / fixp_new(phases));
+
+		/* Generate Lanczos coefficients */
+		for (j = 0; j < taps; j++) {
+			coef[j] = lanczos(fixp_new(j - (taps >> 1)) + dy,
+					  fixp_new(taps >> 1));
+			sum += coef[j];
+		}
+
+		/* Program coefficients */
+		for (j = 0; j < taps; j += 2) {
+			/* Normalize and multiply coefficients */
+			coef_val = (((coef[j] << FRAC_N) << (FRAC_N - 2)) /
+				    sum) & 0xffff;
+			if (j + 1 < taps)
+				coef_val |= ((((coef[j + 1] << FRAC_N) <<
+					      (FRAC_N - 2)) / sum) & 0xffff) <<
+					    16;
+
+			xvip_write(&xscaler->xvip, XSCALER_COEF_DATA_IN,
+				   coef_val);
+		}
+	}
+
+	kfree(coef);
+
+	return 0;
+}
+
+static void xscaler_set_aperture(struct xscaler_device *xscaler)
+{
+	u16 start;
+	u16 end;
+	u32 scale_factor;
+
+	xvip_disable_reg_update(&xscaler->xvip);
+
+	/* set horizontal aperture */
+	start = xscaler->crop.left;
+	end = start + xscaler->crop.width - 1;
+	xvip_write(&xscaler->xvip, XSCALER_HAPERTURE,
+		   (end << XSCALER_APERTURE_END_SHIFT) |
+		   (start << XSCALER_APERTURE_START_SHIFT));
+
+	/* set vertical aperture */
+	start = xscaler->crop.top;
+	end = start + xscaler->crop.height - 1;
+	xvip_write(&xscaler->xvip, XSCALER_VAPERTURE,
+		   (end << XSCALER_APERTURE_END_SHIFT) |
+		   (start << XSCALER_APERTURE_START_SHIFT));
+
+	/* set scaling factors */
+	scale_factor = ((xscaler->crop.width << XSCALER_SF_SHIFT) /
+			xscaler->formats[XVIP_PAD_SOURCE].width) &
+		       XSCALER_SF_MASK;
+	xvip_write(&xscaler->xvip, XSCALER_HSF, scale_factor);
+
+	scale_factor = ((xscaler->crop.height << XSCALER_SF_SHIFT) /
+			xscaler->formats[XVIP_PAD_SOURCE].height) &
+		       XSCALER_SF_MASK;
+	xvip_write(&xscaler->xvip, XSCALER_VSF, scale_factor);
+
+	xvip_enable_reg_update(&xscaler->xvip);
+}
+
+static int xscaler_s_stream(struct v4l2_subdev *subdev, int enable)
+{
+	struct xscaler_device *xscaler = to_scaler(subdev);
+	u32 width;
+	u32 height;
+
+	if (!enable) {
+		xvip_stop(&xscaler->xvip);
+		return 0;
+	}
+
+	/* set input width / height */
+	width = xscaler->formats[XVIP_PAD_SINK].width;
+	height = xscaler->formats[XVIP_PAD_SINK].height;
+	xvip_write(&xscaler->xvip, XSCALER_SOURCE_SIZE,
+		   (height << XSCALER_SIZE_VERT_SHIFT) |
+		   (width << XSCALER_SIZE_HORZ_SHIFT));
+
+	/* set output width / height */
+	width = xscaler->formats[XVIP_PAD_SOURCE].width;
+	height = xscaler->formats[XVIP_PAD_SOURCE].height;
+	xvip_write(&xscaler->xvip, XSCALER_OUTPUT_SIZE,
+		   (height << XSCALER_SIZE_VERT_SHIFT) |
+		   (width << XSCALER_SIZE_HORZ_SHIFT));
+
+	/* set aperture */
+	xscaler_set_aperture(xscaler);
+
+	xvip_start(&xscaler->xvip);
+
+	return 0;
+}
+
+/*
+ * V4L2 Subdevice Pad Operations
+ */
+
+static int xscaler_enum_frame_size(struct v4l2_subdev *subdev,
+				   struct v4l2_subdev_pad_config *cfg,
+				   struct v4l2_subdev_frame_size_enum *fse)
+{
+	struct v4l2_mbus_framefmt *format;
+
+	format = v4l2_subdev_get_try_format(subdev, cfg, fse->pad);
+
+	if (fse->index || fse->code != format->code)
+		return -EINVAL;
+
+	fse->min_width = XSCALER_MIN_WIDTH;
+	fse->max_width = XSCALER_MAX_WIDTH;
+	fse->min_height = XSCALER_MIN_HEIGHT;
+	fse->max_height = XSCALER_MAX_HEIGHT;
+
+	return 0;
+}
+
+static struct v4l2_mbus_framefmt *
+__xscaler_get_pad_format(struct xscaler_device *xscaler,
+			 struct v4l2_subdev_pad_config *cfg,
+			 unsigned int pad, u32 which)
+{
+	struct v4l2_mbus_framefmt *format;
+
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		format = v4l2_subdev_get_try_format(&xscaler->xvip.subdev, cfg,
+						    pad);
+		break;
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		format = &xscaler->formats[pad];
+		break;
+	default:
+		format = NULL;
+		break;
+	}
+
+	return format;
+}
+
+static struct v4l2_rect *__xscaler_get_crop(struct xscaler_device *xscaler,
+					    struct v4l2_subdev_pad_config *cfg,
+					    u32 which)
+{
+	struct v4l2_rect *crop;
+
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		crop = v4l2_subdev_get_try_crop(&xscaler->xvip.subdev, cfg,
+						XVIP_PAD_SINK);
+		break;
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		crop = &xscaler->crop;
+		break;
+	default:
+		crop = NULL;
+		break;
+	}
+
+	return crop;
+}
+
+static int xscaler_get_format(struct v4l2_subdev *subdev,
+			      struct v4l2_subdev_pad_config *cfg,
+			      struct v4l2_subdev_format *fmt)
+{
+	struct xscaler_device *xscaler = to_scaler(subdev);
+	struct v4l2_mbus_framefmt *format;
+
+	format = __xscaler_get_pad_format(xscaler, cfg, fmt->pad,
+					  fmt->which);
+	if (!format)
+		return -EINVAL;
+
+	fmt->format = *format;
+
+	return 0;
+}
+
+static void xscaler_try_crop(const struct v4l2_mbus_framefmt *sink,
+			     struct v4l2_rect *crop)
+{
+
+	crop->left = min_t(u32, crop->left, sink->width - XSCALER_MIN_WIDTH);
+	crop->top = min_t(u32, crop->top, sink->height - XSCALER_MIN_HEIGHT);
+	crop->width = clamp_t(u32, crop->width, XSCALER_MIN_WIDTH,
+			      sink->width - crop->left);
+	crop->height = clamp_t(u32, crop->height, XSCALER_MIN_HEIGHT,
+			       sink->height - crop->top);
+}
+
+static int xscaler_set_format(struct v4l2_subdev *subdev,
+			      struct v4l2_subdev_pad_config *cfg,
+			      struct v4l2_subdev_format *fmt)
+{
+	struct xscaler_device *xscaler = to_scaler(subdev);
+	struct v4l2_mbus_framefmt *format;
+	struct v4l2_rect *crop;
+
+	format = __xscaler_get_pad_format(xscaler, cfg, fmt->pad, fmt->which);
+	if (!format)
+		return -EINVAL;
+
+	format->width = clamp_t(unsigned int, fmt->format.width,
+				  XSCALER_MIN_WIDTH, XSCALER_MAX_WIDTH);
+	format->height = clamp_t(unsigned int, fmt->format.height,
+				   XSCALER_MIN_HEIGHT, XSCALER_MAX_HEIGHT);
+
+	fmt->format = *format;
+
+	if (fmt->pad == XVIP_PAD_SINK) {
+		/* Set the crop rectangle to the full frame */
+		crop = __xscaler_get_crop(xscaler, cfg, fmt->which);
+		if (!crop)
+			return -EINVAL;
+		crop->left = 0;
+		crop->top = 0;
+		crop->width = fmt->format.width;
+		crop->height = fmt->format.height;
+	}
+
+	return 0;
+}
+
+static int xscaler_get_selection(struct v4l2_subdev *subdev,
+				 struct v4l2_subdev_pad_config *cfg,
+				 struct v4l2_subdev_selection *sel)
+{
+	struct xscaler_device *xscaler = to_scaler(subdev);
+	struct v4l2_mbus_framefmt *format;
+	struct v4l2_rect *crop;
+
+	if (sel->pad != XVIP_PAD_SINK)
+		return -EINVAL;
+
+	switch (sel->target) {
+	case V4L2_SEL_TGT_CROP_BOUNDS:
+		format = __xscaler_get_pad_format(xscaler, cfg, XVIP_PAD_SINK,
+						  sel->which);
+		if (!format)
+			return -EINVAL;
+
+		sel->r.left = 0;
+		sel->r.top = 0;
+		sel->r.width = format->width;
+		sel->r.height = format->height;
+		return 0;
+	case V4L2_SEL_TGT_CROP:
+		crop = __xscaler_get_crop(xscaler, cfg, sel->which);
+		if (!crop)
+			return -EINVAL;
+		sel->r = *crop;
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int xscaler_set_selection(struct v4l2_subdev *subdev,
+				 struct v4l2_subdev_pad_config *cfg,
+				 struct v4l2_subdev_selection *sel)
+{
+	struct xscaler_device *xscaler = to_scaler(subdev);
+	struct v4l2_mbus_framefmt *format;
+	struct v4l2_rect *crop;
+
+	if ((sel->target != V4L2_SEL_TGT_CROP) || (sel->pad != XVIP_PAD_SINK))
+		return -EINVAL;
+
+	format = __xscaler_get_pad_format(xscaler, cfg, XVIP_PAD_SINK,
+					  sel->which);
+	if (!format)
+		return -EINVAL;
+
+	xscaler_try_crop(format, &sel->r);
+	crop = __xscaler_get_crop(xscaler, cfg, sel->which);
+	if (!crop)
+		return -EINVAL;
+
+	*crop = sel->r;
+
+	return 0;
+}
+
+/*
+ * V4L2 Subdevice Operations
+ */
+
+static int xscaler_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+	struct xscaler_device *xscaler = to_scaler(subdev);
+	struct v4l2_mbus_framefmt *format;
+
+	/* Initialize with default formats */
+	format = v4l2_subdev_get_try_format(subdev, fh->pad, XVIP_PAD_SINK);
+	*format = xscaler->default_formats[XVIP_PAD_SINK];
+
+	format = v4l2_subdev_get_try_format(subdev, fh->pad, XVIP_PAD_SOURCE);
+	*format = xscaler->default_formats[XVIP_PAD_SOURCE];
+
+	return 0;
+}
+
+static int xscaler_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+	return 0;
+}
+
+static struct v4l2_subdev_video_ops xscaler_video_ops = {
+	.s_stream = xscaler_s_stream,
+};
+
+static struct v4l2_subdev_pad_ops xscaler_pad_ops = {
+	.enum_mbus_code		= xvip_enum_mbus_code,
+	.enum_frame_size	= xscaler_enum_frame_size,
+	.get_fmt		= xscaler_get_format,
+	.set_fmt		= xscaler_set_format,
+	.get_selection		= xscaler_get_selection,
+	.set_selection		= xscaler_set_selection,
+};
+
+static struct v4l2_subdev_ops xscaler_ops = {
+	.video  = &xscaler_video_ops,
+	.pad    = &xscaler_pad_ops,
+};
+
+static const struct v4l2_subdev_internal_ops xscaler_internal_ops = {
+	.open	= xscaler_open,
+	.close	= xscaler_close,
+};
+
+/*
+ * Media Operations
+ */
+
+static const struct media_entity_operations xscaler_media_ops = {
+	.link_validate = v4l2_subdev_link_validate,
+};
+
+/*
+ * Power Management
+ */
+
+static int __maybe_unused xscaler_pm_suspend(struct device *dev)
+{
+	struct xscaler_device *xscaler = dev_get_drvdata(dev);
+
+	xvip_suspend(&xscaler->xvip);
+
+	return 0;
+}
+
+static int __maybe_unused xscaler_pm_resume(struct device *dev)
+{
+	struct xscaler_device *xscaler = dev_get_drvdata(dev);
+
+	xvip_resume(&xscaler->xvip);
+
+	return 0;
+}
+
+/*
+ * Platform Device Driver
+ */
+
+static int xscaler_parse_of(struct xscaler_device *xscaler)
+{
+	struct device *dev = xscaler->xvip.dev;
+	struct device_node *node = xscaler->xvip.dev->of_node;
+	struct device_node *ports;
+	struct device_node *port;
+	int ret;
+
+	ports = of_get_child_by_name(node, "ports");
+	if (ports == NULL)
+		ports = node;
+
+	/* Get the format description for each pad */
+	for_each_child_of_node(ports, port) {
+		if (port->name && (of_node_cmp(port->name, "port") == 0)) {
+			const struct xvip_video_format *vip_format;
+
+			vip_format = xvip_of_get_format(port);
+			if (IS_ERR(vip_format)) {
+				dev_err(dev, "invalid format in DT");
+				return PTR_ERR(vip_format);
+			}
+
+			if (!xscaler->vip_format) {
+				xscaler->vip_format = vip_format;
+			} else if (xscaler->vip_format != vip_format) {
+				dev_err(dev, "in/out format mismatch in DT");
+				return -EINVAL;
+			}
+		}
+	}
+
+	ret = of_property_read_u32(node, "xlnx,num-hori-taps",
+				   &xscaler->num_hori_taps);
+	if (ret < 0)
+		return ret;
+
+	ret = of_property_read_u32(node, "xlnx,num-vert-taps",
+				   &xscaler->num_vert_taps);
+	if (ret < 0)
+		return ret;
+
+	ret = of_property_read_u32(node, "xlnx,max-num-phases",
+				   &xscaler->max_num_phases);
+	if (ret < 0)
+		return ret;
+
+	xscaler->separate_yc_coef =
+		of_property_read_bool(node, "xlnx,separate-yc-coef");
+
+	xscaler->separate_hv_coef =
+		of_property_read_bool(node, "xlnx,separate-hv-coef");
+
+	return 0;
+}
+
+static int xscaler_probe(struct platform_device *pdev)
+{
+	struct xscaler_device *xscaler;
+	struct v4l2_subdev *subdev;
+	struct v4l2_mbus_framefmt *default_format;
+	u32 size;
+	int ret;
+
+	xscaler = devm_kzalloc(&pdev->dev, sizeof(*xscaler), GFP_KERNEL);
+	if (!xscaler)
+		return -ENOMEM;
+
+	xscaler->xvip.dev = &pdev->dev;
+
+	ret = xscaler_parse_of(xscaler);
+	if (ret < 0)
+		return ret;
+
+	ret = xvip_init_resources(&xscaler->xvip);
+	if (ret < 0)
+		return ret;
+
+	/* Reset and initialize the core */
+	xvip_reset(&xscaler->xvip);
+
+	/* Initialize V4L2 subdevice and media entity */
+	subdev = &xscaler->xvip.subdev;
+	v4l2_subdev_init(subdev, &xscaler_ops);
+	subdev->dev = &pdev->dev;
+	subdev->internal_ops = &xscaler_internal_ops;
+	strlcpy(subdev->name, dev_name(&pdev->dev), sizeof(subdev->name));
+	v4l2_set_subdevdata(subdev, xscaler);
+	subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	/* Initialize default and active formats */
+	default_format = &xscaler->default_formats[XVIP_PAD_SINK];
+	default_format->code = xscaler->vip_format->code;
+	default_format->field = V4L2_FIELD_NONE;
+	default_format->colorspace = V4L2_COLORSPACE_SRGB;
+	size = xvip_read(&xscaler->xvip, XSCALER_SOURCE_SIZE);
+	default_format->width = (size >> XSCALER_SIZE_HORZ_SHIFT) &
+				 XSCALER_SIZE_MASK;
+	default_format->height = (size >> XSCALER_SIZE_VERT_SHIFT) &
+				 XSCALER_SIZE_MASK;
+
+	xscaler->formats[XVIP_PAD_SINK] = *default_format;
+
+	default_format = &xscaler->default_formats[XVIP_PAD_SOURCE];
+	*default_format = xscaler->default_formats[XVIP_PAD_SINK];
+	size = xvip_read(&xscaler->xvip, XSCALER_OUTPUT_SIZE);
+	default_format->width = (size >> XSCALER_SIZE_HORZ_SHIFT) &
+				 XSCALER_SIZE_MASK;
+	default_format->height = (size >> XSCALER_SIZE_VERT_SHIFT) &
+				 XSCALER_SIZE_MASK;
+
+	xscaler->formats[XVIP_PAD_SOURCE] = *default_format;
+
+	xscaler->pads[XVIP_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+	xscaler->pads[XVIP_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+	subdev->entity.ops = &xscaler_media_ops;
+
+	ret = media_entity_pads_init(&subdev->entity, 2, xscaler->pads);
+	if (ret < 0)
+		goto error;
+
+	platform_set_drvdata(pdev, xscaler);
+
+	xvip_print_version(&xscaler->xvip);
+
+	ret = xscaler_set_coefs(xscaler, (s16)xscaler->num_hori_taps);
+	if (ret < 0)
+		goto error;
+
+	if (xscaler->separate_hv_coef) {
+		ret = xscaler_set_coefs(xscaler, (s16)xscaler->num_vert_taps);
+		if (ret < 0)
+			goto error;
+	}
+
+	if (xscaler->separate_yc_coef) {
+		ret = xscaler_set_coefs(xscaler, (s16)xscaler->num_hori_taps);
+		if (ret < 0)
+			goto error;
+
+		if (xscaler->separate_hv_coef) {
+			ret = xscaler_set_coefs(xscaler,
+						(s16)xscaler->num_vert_taps);
+			if (ret < 0)
+				goto error;
+		}
+	}
+
+	ret = v4l2_async_register_subdev(subdev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to register subdev\n");
+		goto error;
+	}
+
+	return 0;
+
+error:
+	media_entity_cleanup(&subdev->entity);
+	xvip_cleanup_resources(&xscaler->xvip);
+	return ret;
+}
+
+static int xscaler_remove(struct platform_device *pdev)
+{
+	struct xscaler_device *xscaler = platform_get_drvdata(pdev);
+	struct v4l2_subdev *subdev = &xscaler->xvip.subdev;
+
+	v4l2_async_unregister_subdev(subdev);
+	media_entity_cleanup(&subdev->entity);
+
+	xvip_cleanup_resources(&xscaler->xvip);
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(xscaler_pm_ops, xscaler_pm_suspend, xscaler_pm_resume);
+
+static const struct of_device_id xscaler_of_id_table[] = {
+	{ .compatible = "xlnx,v-scaler-8.1" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, xscaler_of_id_table);
+
+static struct platform_driver xscaler_driver = {
+	.driver			= {
+		.name		= "xilinx-scaler",
+		.pm		= &xscaler_pm_ops,
+		.of_match_table	= xscaler_of_id_table,
+	},
+	.probe			= xscaler_probe,
+	.remove			= xscaler_remove,
+};
+
+module_platform_driver(xscaler_driver);
+
+MODULE_DESCRIPTION("Xilinx Scaler Driver");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/xilinx-scenechange-channel.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/xilinx-scenechange-channel.c
@@ -0,0 +1,462 @@
+//SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx Scene Change Detection driver
+ *
+ * Copyright (C) 2018 Xilinx, Inc.
+ *
+ * Authors: Anand Ashok Dumbre <anand.ashok.dumbre@xilinx.com>
+ *          Satish Kumar Nagireddy <satish.nagireddy.nagireddy@xilinx.com>
+ */
+
+#include <linux/gpio/consumer.h>
+#include <linux/of.h>
+#include <linux/xilinx-v4l2-events.h>
+
+#include <media/v4l2-async.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-subdev.h>
+
+#include "xilinx-scenechange.h"
+#include "xilinx-vip.h"
+
+#define XSCD_DEFAULT_WIDTH	3840
+#define XSCD_DEFAULT_HEIGHT	2160
+#define XSCD_MAX_WIDTH		8192
+#define XSCD_MAX_HEIGHT		4320
+#define XSCD_MIN_WIDTH		64
+#define XSCD_MIN_HEIGHT		64
+
+#define XSCD_V_SUBSAMPLING		16
+#define XSCD_BYTE_ALIGN			16
+#define MULTIPLICATION_FACTOR		100
+
+#define XSCD_SCENE_CHANGE		1
+#define XSCD_NO_SCENE_CHANGE		0
+
+/* -----------------------------------------------------------------------------
+ * V4L2 Subdevice Pad Operations
+ */
+
+static int xscd_enum_mbus_code(struct v4l2_subdev *subdev,
+			       struct v4l2_subdev_pad_config *cfg,
+			       struct v4l2_subdev_mbus_code_enum *code)
+{
+	return 0;
+}
+
+static int xscd_enum_frame_size(struct v4l2_subdev *subdev,
+				struct v4l2_subdev_pad_config *cfg,
+				struct v4l2_subdev_frame_size_enum *fse)
+{
+	return 0;
+}
+
+static struct v4l2_mbus_framefmt *
+__xscd_get_pad_format(struct xscd_chan *chan,
+		      struct v4l2_subdev_pad_config *cfg,
+		      unsigned int pad, u32 which)
+{
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		return v4l2_subdev_get_try_format(&chan->subdev, cfg, pad);
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		return &chan->format;
+	default:
+		return NULL;
+	}
+	return NULL;
+}
+
+static int xscd_get_format(struct v4l2_subdev *subdev,
+			   struct v4l2_subdev_pad_config *cfg,
+			   struct v4l2_subdev_format *fmt)
+{
+	struct xscd_chan *chan = to_xscd_chan(subdev);
+
+	fmt->format = *__xscd_get_pad_format(chan, cfg, fmt->pad, fmt->which);
+	return 0;
+}
+
+static int xscd_set_format(struct v4l2_subdev *subdev,
+			   struct v4l2_subdev_pad_config *cfg,
+			   struct v4l2_subdev_format *fmt)
+{
+	struct xscd_chan *chan = to_xscd_chan(subdev);
+	struct v4l2_mbus_framefmt *format;
+
+	format = __xscd_get_pad_format(chan, cfg, fmt->pad, fmt->which);
+	format->width = clamp_t(unsigned int, fmt->format.width,
+				XSCD_MIN_WIDTH, XSCD_MAX_WIDTH);
+	format->height = clamp_t(unsigned int, fmt->format.height,
+				 XSCD_MIN_HEIGHT, XSCD_MAX_HEIGHT);
+	format->code = fmt->format.code;
+	/*
+	 * If memory based, SCD can support interlaced alternate mode because
+	 * SCD is agnostic to field. If stream based, SCD does not have a fid
+	 * pin so interlaced alternate mode is not supported there.
+	 */
+	if (chan->xscd->memory_based)
+		format->field = fmt->format.field;
+
+	fmt->format = *format;
+
+	return 0;
+}
+
+static int xscd_chan_get_vid_fmt(u32 media_bus_fmt, bool memory_based)
+{
+	u32 vid_fmt;
+
+	if (memory_based) {
+		switch (media_bus_fmt) {
+		case MEDIA_BUS_FMT_VYYUYY8_1X24:
+		case MEDIA_BUS_FMT_UYVY8_1X16:
+		case MEDIA_BUS_FMT_VUY8_1X24:
+			vid_fmt = XSCD_VID_FMT_Y8;
+			break;
+		case MEDIA_BUS_FMT_VYYUYY10_4X20:
+		case MEDIA_BUS_FMT_UYVY10_1X20:
+		case MEDIA_BUS_FMT_VUY10_1X30:
+			vid_fmt = XSCD_VID_FMT_Y10;
+			break;
+		default:
+			vid_fmt = XSCD_VID_FMT_Y8;
+		}
+
+		return vid_fmt;
+	}
+
+	/* Streaming based */
+	switch (media_bus_fmt) {
+	case MEDIA_BUS_FMT_VYYUYY8_1X24:
+	case MEDIA_BUS_FMT_VYYUYY10_4X20:
+		vid_fmt = XSCD_VID_FMT_YUV_420;
+		break;
+	case MEDIA_BUS_FMT_UYVY8_1X16:
+	case MEDIA_BUS_FMT_UYVY10_1X20:
+		vid_fmt = XSCD_VID_FMT_YUV_422;
+		break;
+	case MEDIA_BUS_FMT_VUY8_1X24:
+	case MEDIA_BUS_FMT_VUY10_1X30:
+		vid_fmt = XSCD_VID_FMT_YUV_444;
+		break;
+	case MEDIA_BUS_FMT_RBG888_1X24:
+	case MEDIA_BUS_FMT_RBG101010_1X30:
+		vid_fmt = XSCD_VID_FMT_RGB;
+		break;
+	default:
+		vid_fmt = XSCD_VID_FMT_YUV_420;
+	}
+
+	return vid_fmt;
+}
+
+/**
+ * xscd_chan_configure_params - Program parameters to HW registers
+ * @chan: Driver specific channel struct pointer
+ */
+static void xscd_chan_configure_params(struct xscd_chan *chan)
+{
+	u32 vid_fmt, stride;
+
+	xscd_write(chan->iomem, XSCD_WIDTH_OFFSET, chan->format.width);
+
+	/* Stride is required only for memory based IP, not for streaming IP */
+	if (chan->xscd->memory_based) {
+		stride = roundup(chan->format.width, XSCD_BYTE_ALIGN);
+		xscd_write(chan->iomem, XSCD_STRIDE_OFFSET, stride);
+	}
+
+	xscd_write(chan->iomem, XSCD_HEIGHT_OFFSET, chan->format.height);
+
+	/* Hardware video format */
+	vid_fmt = xscd_chan_get_vid_fmt(chan->format.code,
+					chan->xscd->memory_based);
+	xscd_write(chan->iomem, XSCD_VID_FMT_OFFSET, vid_fmt);
+
+	/*
+	 * This is the vertical subsampling factor of the input image. Instead
+	 * of sampling every line to calculate the histogram, IP uses this
+	 * register value to sample only specific lines of the frame.
+	 */
+	xscd_write(chan->iomem, XSCD_SUBSAMPLE_OFFSET, XSCD_V_SUBSAMPLING);
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 Subdevice Operations
+ */
+
+static int xscd_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	int ret = 0;
+	struct xscd_chan *chan = container_of(ctrl->handler, struct xscd_chan,
+					      ctrl_handler);
+
+	switch (ctrl->id) {
+	case V4L2_CID_XILINX_SCD_THRESHOLD:
+		chan->threshold = ctrl->val;
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static int xscd_s_stream(struct v4l2_subdev *subdev, int enable)
+{
+	struct xscd_chan *chan = to_xscd_chan(subdev);
+	struct xscd_device *xscd = chan->xscd;
+
+	if (enable)
+		xscd_chan_configure_params(chan);
+
+	xscd_dma_enable_channel(&chan->dmachan, enable);
+
+	/*
+	 * Resolution change doesn't work in stream based mode unless
+	 * the device is reset.
+	 */
+	if (!enable && !xscd->memory_based) {
+		gpiod_set_value_cansleep(xscd->rst_gpio, XSCD_RESET_ASSERT);
+		gpiod_set_value_cansleep(xscd->rst_gpio, XSCD_RESET_DEASSERT);
+	}
+
+	return 0;
+}
+
+static int xscd_subscribe_event(struct v4l2_subdev *sd,
+				struct v4l2_fh *fh,
+				struct v4l2_event_subscription *sub)
+{
+	int ret;
+	struct xscd_chan *chan = to_xscd_chan(sd);
+
+	mutex_lock(&chan->lock);
+
+	switch (sub->type) {
+	case V4L2_EVENT_XLNXSCD:
+		ret = v4l2_event_subscribe(fh, sub, 1, NULL);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	mutex_unlock(&chan->lock);
+
+	return ret;
+}
+
+static int xscd_unsubscribe_event(struct v4l2_subdev *sd,
+				  struct v4l2_fh *fh,
+				  struct v4l2_event_subscription *sub)
+{
+	int ret;
+	struct xscd_chan *chan = to_xscd_chan(sd);
+
+	mutex_lock(&chan->lock);
+	ret = v4l2_event_unsubscribe(fh, sub);
+	mutex_unlock(&chan->lock);
+
+	return ret;
+}
+
+static int xscd_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+	return 0;
+}
+
+static int xscd_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops xscd_ctrl_ops = {
+	.s_ctrl	= xscd_s_ctrl
+};
+
+static const struct v4l2_ctrl_config xscd_ctrls[] = {
+	{
+		.ops = &xscd_ctrl_ops,
+		.id = V4L2_CID_XILINX_SCD_THRESHOLD,
+		.name = "Threshold Value",
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.min = 0,
+		.max = 100,
+		.step = 1,
+		.def = 50,
+	}
+};
+
+static const struct v4l2_subdev_core_ops xscd_core_ops = {
+	.subscribe_event = xscd_subscribe_event,
+	.unsubscribe_event = xscd_unsubscribe_event
+};
+
+static struct v4l2_subdev_video_ops xscd_video_ops = {
+	.s_stream = xscd_s_stream,
+};
+
+static struct v4l2_subdev_pad_ops xscd_pad_ops = {
+	.enum_mbus_code = xscd_enum_mbus_code,
+	.enum_frame_size = xscd_enum_frame_size,
+	.get_fmt = xscd_get_format,
+	.set_fmt = xscd_set_format,
+};
+
+static struct v4l2_subdev_ops xscd_ops = {
+	.core = &xscd_core_ops,
+	.video = &xscd_video_ops,
+	.pad = &xscd_pad_ops,
+};
+
+static const struct v4l2_subdev_internal_ops xscd_internal_ops = {
+	.open = xscd_open,
+	.close = xscd_close,
+};
+
+/* -----------------------------------------------------------------------------
+ * Media Operations
+ */
+
+static const struct media_entity_operations xscd_media_ops = {
+	.link_validate = v4l2_subdev_link_validate,
+};
+
+void xscd_chan_event_notify(struct xscd_chan *chan)
+{
+	u32 *eventdata;
+	u32 sad;
+
+	sad = xscd_read(chan->iomem, XSCD_SAD_OFFSET);
+	sad = (sad * XSCD_V_SUBSAMPLING * MULTIPLICATION_FACTOR) /
+	       (chan->format.width * chan->format.height);
+	eventdata = (u32 *)&chan->event.u.data;
+
+	if (sad > chan->threshold)
+		eventdata[0] = XSCD_SCENE_CHANGE;
+	else
+		eventdata[0] = XSCD_NO_SCENE_CHANGE;
+
+	chan->event.type = V4L2_EVENT_XLNXSCD;
+	v4l2_subdev_notify_event(&chan->subdev, &chan->event);
+}
+
+/**
+ * xscd_chan_init - Initialize the V4L2 subdev for a channel
+ * @xscd: Pointer to the SCD device structure
+ * @chan_id: Channel id
+ * @node: device node
+ *
+ * Return: '0' on success and failure value on error
+ */
+int xscd_chan_init(struct xscd_device *xscd, unsigned int chan_id,
+		   struct device_node *node)
+{
+	struct xscd_chan *chan = &xscd->chans[chan_id];
+	struct v4l2_subdev *subdev;
+	unsigned int num_pads;
+	int ret;
+	unsigned int i;
+
+	mutex_init(&chan->lock);
+	chan->xscd = xscd;
+	chan->id = chan_id;
+	chan->iomem = chan->xscd->iomem + chan->id * XSCD_CHAN_OFFSET;
+
+	/* Initialize V4L2 subdevice and media entity */
+	subdev = &chan->subdev;
+	v4l2_subdev_init(subdev, &xscd_ops);
+	subdev->dev = chan->xscd->dev;
+	subdev->fwnode = of_fwnode_handle(node);
+	subdev->internal_ops = &xscd_internal_ops;
+	snprintf(subdev->name, sizeof(subdev->name), "xlnx-scdchan.%u",
+		 chan_id);
+	v4l2_set_subdevdata(subdev, chan);
+	subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
+
+	/* Initialize default format */
+	chan->format.code = MEDIA_BUS_FMT_VYYUYY8_1X24;
+	chan->format.field = V4L2_FIELD_NONE;
+	chan->format.width = XSCD_DEFAULT_WIDTH;
+	chan->format.height = XSCD_DEFAULT_HEIGHT;
+
+	/* Initialize media pads */
+	num_pads = xscd->memory_based ? 1 : 2;
+
+	chan->pads[XVIP_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+	if (!xscd->memory_based)
+		chan->pads[XVIP_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+
+	ret = media_entity_pads_init(&subdev->entity, num_pads, chan->pads);
+	if (ret < 0)
+		goto media_init_error;
+
+	subdev->entity.ops = &xscd_media_ops;
+
+	/* Initialize V4L2 Control Handler */
+	v4l2_ctrl_handler_init(&chan->ctrl_handler, ARRAY_SIZE(xscd_ctrls));
+
+	for (i = 0; i < ARRAY_SIZE(xscd_ctrls); i++) {
+		struct v4l2_ctrl *ctrl;
+
+		dev_dbg(chan->xscd->dev, "%d ctrl = 0x%x\n", i,
+			xscd_ctrls[i].id);
+		ctrl = v4l2_ctrl_new_custom(&chan->ctrl_handler, &xscd_ctrls[i],
+					    NULL);
+		if (!ctrl) {
+			dev_err(chan->xscd->dev, "Failed for %s ctrl\n",
+				xscd_ctrls[i].name);
+			goto ctrl_handler_error;
+		}
+	}
+
+	if (chan->ctrl_handler.error) {
+		dev_err(chan->xscd->dev, "failed to add controls\n");
+		ret = chan->ctrl_handler.error;
+		goto ctrl_handler_error;
+	}
+
+	subdev->ctrl_handler = &chan->ctrl_handler;
+
+	ret = v4l2_ctrl_handler_setup(&chan->ctrl_handler);
+	if (ret < 0) {
+		dev_err(chan->xscd->dev, "failed to set controls\n");
+		goto ctrl_handler_error;
+	}
+
+	ret = v4l2_async_register_subdev(subdev);
+	if (ret < 0) {
+		dev_err(chan->xscd->dev, "failed to register subdev\n");
+		goto ctrl_handler_error;
+	}
+
+	dev_info(chan->xscd->dev, "Scene change detection channel found!\n");
+	return 0;
+
+ctrl_handler_error:
+	v4l2_ctrl_handler_free(&chan->ctrl_handler);
+media_init_error:
+	media_entity_cleanup(&subdev->entity);
+	mutex_destroy(&chan->lock);
+	return ret;
+}
+
+/**
+ * xscd_chan_cleanup - Clean up the V4L2 subdev for a channel
+ * @xscd: Pointer to the SCD device structure
+ * @chan_id: Channel id
+ * @node: device node
+ */
+void xscd_chan_cleanup(struct xscd_device *xscd, unsigned int chan_id,
+		       struct device_node *node)
+{
+	struct xscd_chan *chan = &xscd->chans[chan_id];
+	struct v4l2_subdev *subdev = &chan->subdev;
+
+	v4l2_async_unregister_subdev(subdev);
+	v4l2_ctrl_handler_free(&chan->ctrl_handler);
+	media_entity_cleanup(&subdev->entity);
+	mutex_destroy(&chan->lock);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/xilinx-scenechange-dma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/xilinx-scenechange-dma.c
@@ -0,0 +1,554 @@
+//SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx Scene Change Detection DMA driver
+ *
+ * Copyright (C) 2018 Xilinx, Inc.
+ *
+ * Authors: Anand Ashok Dumbre <anand.ashok.dumbre@xilinx.com>
+ *          Satish Kumar Nagireddy <satish.nagireddy.nagireddy@xilinx.com>
+ */
+
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/of_dma.h>
+#include <linux/slab.h>
+
+#include "../../../dma/dmaengine.h"
+
+#include "xilinx-scenechange.h"
+
+/**
+ * xscd_dma_start - Start the SCD core
+ * @xscd: The SCD device
+ * @channels: Bitmask of enabled channels
+ */
+static void xscd_dma_start(struct xscd_device *xscd, unsigned int channels)
+{
+	xscd_write(xscd->iomem, XSCD_IE_OFFSET, XSCD_IE_AP_DONE);
+	xscd_write(xscd->iomem, XSCD_GIE_OFFSET, XSCD_GIE_EN);
+	xscd_write(xscd->iomem, XSCD_CHAN_EN_OFFSET, channels);
+
+	xscd_set(xscd->iomem, XSCD_CTRL_OFFSET,
+		 xscd->memory_based ? XSCD_CTRL_AP_START
+				    : XSCD_CTRL_AP_START |
+				      XSCD_CTRL_AUTO_RESTART);
+
+	xscd->running = true;
+}
+
+/**
+ * xscd_dma_stop - Stop the SCD core
+ * @xscd: The SCD device
+ */
+static void xscd_dma_stop(struct xscd_device *xscd)
+{
+	xscd_clr(xscd->iomem, XSCD_CTRL_OFFSET,
+		 xscd->memory_based ? XSCD_CTRL_AP_START
+				    : XSCD_CTRL_AP_START |
+				      XSCD_CTRL_AUTO_RESTART);
+
+	xscd->running = false;
+}
+
+/**
+ * xscd_dma_setup_channel - Setup a channel for transfer
+ * @chan: Driver specific channel struct pointer
+ *
+ * Return: 1 if the channel starts to run for a new transfer. Otherwise, 0.
+ */
+static int xscd_dma_setup_channel(struct xscd_dma_chan *chan)
+{
+	struct xscd_dma_tx_descriptor *desc;
+
+	if (!chan->enabled)
+		return 0;
+
+	if (list_empty(&chan->pending_list))
+		return 0;
+
+	desc = list_first_entry(&chan->pending_list,
+				struct xscd_dma_tx_descriptor, node);
+	list_del(&desc->node);
+
+	xscd_write(chan->iomem, XSCD_ADDR_OFFSET, desc->sw.luma_plane_addr);
+	chan->active_desc = desc;
+
+	return 1;
+}
+
+/**
+ * xscd_dma_kick - Start a run of the SCD core if channels are ready
+ * @xscd: The SCD device
+ *
+ * This function starts a single run of the SCD core when all the following
+ * conditions are met:
+ *
+ * - The SCD is not currently running
+ * - At least one channel is enabled and has buffers available
+ *
+ * It can be used to start the SCD when a buffer is queued, when a channel
+ * starts streaming, or to start the next run. Calling this function is only
+ * valid for memory-based mode and is not permitted for stream-based mode.
+ *
+ * The running state for all channels is updated. Channels that are being
+ * stopped are signalled through the channel wait queue.
+ *
+ * The function must be called with the xscd_device lock held.
+ */
+static void xscd_dma_kick(struct xscd_device *xscd)
+{
+	unsigned int channels = 0;
+	unsigned int i;
+
+	lockdep_assert_held(&xscd->lock);
+
+	if (xscd->running)
+		return;
+
+	for (i = 0; i < xscd->num_streams; i++) {
+		struct xscd_dma_chan *chan = xscd->channels[i];
+		unsigned long flags;
+		unsigned int running;
+		bool stopped;
+
+		spin_lock_irqsave(&chan->lock, flags);
+		running = xscd_dma_setup_channel(chan);
+		stopped = chan->running && !running;
+		chan->running = running;
+		spin_unlock_irqrestore(&chan->lock, flags);
+
+		channels |= running << chan->id;
+		if (stopped)
+			wake_up(&chan->wait);
+	}
+
+	if (channels)
+		xscd_dma_start(xscd, channels);
+	else
+		xscd_dma_stop(xscd);
+}
+
+/**
+ * xscd_dma_enable_channel - Enable/disable a channel
+ * @chan: Driver specific channel struct pointer
+ * @enable: True to enable the channel, false to disable it
+ *
+ * This function enables or disable a channel. When operating in memory-based
+ * mode, enabling a channel kicks processing if buffers are available for any
+ * enabled channel and the SCD core is idle. When operating in stream-based
+ * mode, the SCD core is started or stopped synchronously when then channel is
+ * enabled or disabled.
+ *
+ * This function must be called in non-atomic, non-interrupt context.
+ */
+void xscd_dma_enable_channel(struct xscd_dma_chan *chan, bool enable)
+{
+	struct xscd_device *xscd = chan->xscd;
+
+	if (enable) {
+		/*
+		 * FIXME: Don't set chan->enabled to false here, it will be
+		 * done in xscd_dma_terminate_all(). This works around a bug
+		 * introduced in commit 2e77607047c6 ("xilinx: v4l2: dma: Add
+		 * multiple output support") that stops all channels when the
+		 * first one is stopped, even though they are part of
+		 * independent pipelines. This workaround should be safe as
+		 * long as dmaengine_terminate_all() is called after
+		 * xvip_pipeline_set_stream().
+		 */
+		spin_lock_irq(&chan->lock);
+		chan->enabled = true;
+		spin_unlock_irq(&chan->lock);
+	}
+
+	if (xscd->memory_based) {
+		if (enable) {
+			spin_lock_irq(&xscd->lock);
+			xscd_dma_kick(xscd);
+			spin_unlock_irq(&xscd->lock);
+		}
+	} else {
+		if (enable)
+			xscd_dma_start(xscd, BIT(chan->id));
+		else
+			xscd_dma_stop(xscd);
+	}
+}
+
+/**
+ * xscd_dma_irq_handler - scdma Interrupt handler
+ * @xscd: Pointer to the SCD device structure
+ */
+void xscd_dma_irq_handler(struct xscd_device *xscd)
+{
+	unsigned int i;
+
+	/*
+	 * Mark the active descriptors as complete, move them to the done list
+	 * and schedule the tasklet to clean them up.
+	 */
+	for (i = 0; i < xscd->num_streams; ++i) {
+		struct xscd_dma_chan *chan = xscd->channels[i];
+		struct xscd_dma_tx_descriptor *desc = chan->active_desc;
+
+		if (!desc)
+			continue;
+
+		dma_cookie_complete(&desc->async_tx);
+		xscd_chan_event_notify(&xscd->chans[i]);
+
+		spin_lock(&chan->lock);
+		list_add_tail(&desc->node, &chan->done_list);
+		chan->active_desc = NULL;
+		spin_unlock(&chan->lock);
+
+		tasklet_schedule(&chan->tasklet);
+	}
+
+	/* Start the next run, if any. */
+	spin_lock(&xscd->lock);
+	xscd->running = false;
+	xscd_dma_kick(xscd);
+	spin_unlock(&xscd->lock);
+}
+
+/* -----------------------------------------------------------------------------
+ * DMA Engine
+ */
+
+/**
+ * xscd_dma_tx_submit - Submit DMA transaction
+ * @tx: Async transaction descriptor
+ *
+ * Return: cookie value on success and failure value on error
+ */
+static dma_cookie_t xscd_dma_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+	struct xscd_dma_tx_descriptor *desc = to_xscd_dma_tx_descriptor(tx);
+	struct xscd_dma_chan *chan = to_xscd_dma_chan(tx->chan);
+	dma_cookie_t cookie;
+	unsigned long flags;
+
+	spin_lock_irqsave(&chan->lock, flags);
+	cookie = dma_cookie_assign(tx);
+	list_add_tail(&desc->node, &chan->pending_list);
+	spin_unlock_irqrestore(&chan->lock, flags);
+
+	return cookie;
+}
+
+/**
+ * xscd_dma_free_desc_list - Free descriptors list
+ * @chan: Driver specific dma channel
+ * @list: List to parse and delete the descriptor
+ */
+static void xscd_dma_free_desc_list(struct xscd_dma_chan *chan,
+				    struct list_head *list)
+{
+	struct xscd_dma_tx_descriptor *desc, *next;
+
+	list_for_each_entry_safe(desc, next, list, node) {
+		list_del(&desc->node);
+		kfree(desc);
+	}
+}
+
+/**
+ * xscd_dma_free_descriptors - Free channel descriptors
+ * @chan: Driver specific dma channel
+ */
+static void xscd_dma_free_descriptors(struct xscd_dma_chan *chan)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&chan->lock, flags);
+
+	xscd_dma_free_desc_list(chan, &chan->pending_list);
+	xscd_dma_free_desc_list(chan, &chan->done_list);
+	kfree(chan->active_desc);
+
+	chan->active_desc = NULL;
+	INIT_LIST_HEAD(&chan->pending_list);
+	INIT_LIST_HEAD(&chan->done_list);
+
+	spin_unlock_irqrestore(&chan->lock, flags);
+}
+
+/**
+ * scd_dma_chan_desc_cleanup - Clean channel descriptors
+ * @chan: Driver specific dma channel
+ */
+static void xscd_dma_chan_desc_cleanup(struct xscd_dma_chan *chan)
+{
+	struct xscd_dma_tx_descriptor *desc, *next;
+	unsigned long flags;
+
+	spin_lock_irqsave(&chan->lock, flags);
+
+	list_for_each_entry_safe(desc, next, &chan->done_list, node) {
+		dma_async_tx_callback callback;
+		void *callback_param;
+
+		list_del(&desc->node);
+
+		/* Run the link descriptor callback function */
+		callback = desc->async_tx.callback;
+		callback_param = desc->async_tx.callback_param;
+		if (callback) {
+			spin_unlock_irqrestore(&chan->lock, flags);
+			callback(callback_param);
+			spin_lock_irqsave(&chan->lock, flags);
+		}
+
+		kfree(desc);
+	}
+
+	spin_unlock_irqrestore(&chan->lock, flags);
+}
+
+/**
+ * xscd_dma_dma_prep_interleaved - prepare a descriptor for a
+ * DMA_SLAVE transaction
+ * @dchan: DMA channel
+ * @xt: Interleaved template pointer
+ * @flags: transfer ack flags
+ *
+ * Return: Async transaction descriptor on success and NULL on failure
+ */
+static struct dma_async_tx_descriptor *
+xscd_dma_prep_interleaved(struct dma_chan *dchan,
+			  struct dma_interleaved_template *xt,
+			  unsigned long flags)
+{
+	struct xscd_dma_chan *chan = to_xscd_dma_chan(dchan);
+	struct xscd_dma_tx_descriptor *desc;
+	struct xscd_dma_desc *sw;
+
+	desc = kzalloc(sizeof(*desc), GFP_KERNEL);
+	if (!desc)
+		return NULL;
+
+	dma_async_tx_descriptor_init(&desc->async_tx, &chan->common);
+	desc->async_tx.tx_submit = xscd_dma_tx_submit;
+	async_tx_ack(&desc->async_tx);
+
+	sw = &desc->sw;
+	sw->vsize = xt->numf;
+	sw->hsize = xt->sgl[0].size;
+	sw->stride = xt->sgl[0].size + xt->sgl[0].icg;
+	sw->luma_plane_addr = xt->src_start;
+
+	return &desc->async_tx;
+}
+
+static bool xscd_dma_is_running(struct xscd_dma_chan *chan)
+{
+	bool running;
+
+	spin_lock_irq(&chan->lock);
+	running = chan->running;
+	spin_unlock_irq(&chan->lock);
+
+	return running;
+}
+
+/**
+ * xscd_dma_terminate_all - Halt the channel and free descriptors
+ * @dchan: Driver specific dma channel pointer
+ *
+ * Return: 0
+ */
+static int xscd_dma_terminate_all(struct dma_chan *dchan)
+{
+	struct xscd_dma_chan *chan = to_xscd_dma_chan(dchan);
+	int ret;
+
+	spin_lock_irq(&chan->lock);
+	chan->enabled = false;
+	spin_unlock_irq(&chan->lock);
+
+	/* Wait for any on-going transfer to complete. */
+	ret = wait_event_timeout(chan->wait, !xscd_dma_is_running(chan),
+				 msecs_to_jiffies(100));
+	WARN_ON(ret == 0);
+
+	xscd_dma_free_descriptors(chan);
+	return 0;
+}
+
+/**
+ * xscd_dma_issue_pending - Issue pending transactions
+ * @dchan: DMA channel
+ */
+static void xscd_dma_issue_pending(struct dma_chan *dchan)
+{
+	struct xscd_dma_chan *chan = to_xscd_dma_chan(dchan);
+	struct xscd_device *xscd = chan->xscd;
+	unsigned long flags;
+
+	spin_lock_irqsave(&xscd->lock, flags);
+	xscd_dma_kick(xscd);
+	spin_unlock_irqrestore(&xscd->lock, flags);
+}
+
+static enum dma_status xscd_dma_tx_status(struct dma_chan *dchan,
+					  dma_cookie_t cookie,
+					  struct dma_tx_state *txstate)
+{
+	return dma_cookie_status(dchan, cookie, txstate);
+}
+
+/**
+ * xscd_dma_free_chan_resources - Free channel resources
+ * @dchan: DMA channel
+ */
+static void xscd_dma_free_chan_resources(struct dma_chan *dchan)
+{
+	struct xscd_dma_chan *chan = to_xscd_dma_chan(dchan);
+
+	xscd_dma_free_descriptors(chan);
+}
+
+/**
+ * xscd_dma_do_tasklet - Schedule completion tasklet
+ * @data: Pointer to the Xilinx scdma channel structure
+ */
+static void xscd_dma_do_tasklet(unsigned long data)
+{
+	struct xscd_dma_chan *chan = (struct xscd_dma_chan *)data;
+
+	xscd_dma_chan_desc_cleanup(chan);
+}
+
+/**
+ * xscd_dma_alloc_chan_resources - Allocate channel resources
+ * @dchan: DMA channel
+ *
+ * Return: '0' on success and failure value on error
+ */
+static int xscd_dma_alloc_chan_resources(struct dma_chan *dchan)
+{
+	dma_cookie_init(dchan);
+	return 0;
+}
+
+/**
+ * of_scdma_xilinx_xlate - Translation function
+ * @dma_spec: Pointer to DMA specifier as found in the device tree
+ * @ofdma: Pointer to DMA controller data
+ *
+ * Return: DMA channel pointer on success and NULL on error
+ */
+static struct dma_chan *of_scdma_xilinx_xlate(struct of_phandle_args *dma_spec,
+					      struct of_dma *ofdma)
+{
+	struct xscd_device *xscd = ofdma->of_dma_data;
+	u32 chan_id = dma_spec->args[0];
+
+	if (chan_id >= xscd->num_streams)
+		return NULL;
+
+	if (!xscd->channels[chan_id])
+		return NULL;
+
+	return dma_get_slave_channel(&xscd->channels[chan_id]->common);
+}
+
+static void xscd_dma_chan_init(struct xscd_device *xscd, int chan_id)
+{
+	struct xscd_dma_chan *chan = &xscd->chans[chan_id].dmachan;
+
+	chan->id = chan_id;
+	chan->iomem = xscd->iomem + chan->id * XSCD_CHAN_OFFSET;
+	chan->xscd = xscd;
+
+	xscd->channels[chan->id] = chan;
+
+	spin_lock_init(&chan->lock);
+	INIT_LIST_HEAD(&chan->pending_list);
+	INIT_LIST_HEAD(&chan->done_list);
+	tasklet_init(&chan->tasklet, xscd_dma_do_tasklet,
+		     (unsigned long)chan);
+	init_waitqueue_head(&chan->wait);
+
+	chan->common.device = &xscd->dma_device;
+	list_add_tail(&chan->common.device_node, &xscd->dma_device.channels);
+}
+
+/**
+ * xscd_dma_chan_remove - Per Channel remove function
+ * @chan: Driver specific DMA channel
+ */
+static void xscd_dma_chan_remove(struct xscd_dma_chan *chan)
+{
+	list_del(&chan->common.device_node);
+}
+
+/**
+ * xscd_dma_init - Initialize the SCD DMA engine
+ * @xscd: Pointer to the SCD device structure
+ *
+ * Return: '0' on success and failure value on error
+ */
+int xscd_dma_init(struct xscd_device *xscd)
+{
+	struct dma_device *ddev = &xscd->dma_device;
+	unsigned int chan_id;
+	int ret;
+
+	/* Initialize the DMA engine */
+	ddev->dev = xscd->dev;
+	dma_set_mask(xscd->dev, DMA_BIT_MASK(32));
+
+	INIT_LIST_HEAD(&ddev->channels);
+	dma_cap_set(DMA_SLAVE, ddev->cap_mask);
+	dma_cap_set(DMA_PRIVATE, ddev->cap_mask);
+	ddev->device_alloc_chan_resources = xscd_dma_alloc_chan_resources;
+	ddev->device_free_chan_resources = xscd_dma_free_chan_resources;
+	ddev->device_tx_status = xscd_dma_tx_status;
+	ddev->device_issue_pending = xscd_dma_issue_pending;
+	ddev->device_terminate_all = xscd_dma_terminate_all;
+	ddev->device_prep_interleaved_dma = xscd_dma_prep_interleaved;
+
+	for (chan_id = 0; chan_id < xscd->num_streams; chan_id++)
+		xscd_dma_chan_init(xscd, chan_id);
+
+	ret = dma_async_device_register(ddev);
+	if (ret) {
+		dev_err(xscd->dev, "failed to register the dma device\n");
+		goto error;
+	}
+
+	ret = of_dma_controller_register(xscd->dev->of_node,
+					 of_scdma_xilinx_xlate, xscd);
+	if (ret) {
+		dev_err(xscd->dev, "failed to register DMA to DT DMA helper\n");
+		goto error_of_dma;
+	}
+
+	dev_info(xscd->dev, "Xilinx Scene Change DMA is initialized!\n");
+	return 0;
+
+error_of_dma:
+	dma_async_device_unregister(ddev);
+
+error:
+	for (chan_id = 0; chan_id < xscd->num_streams; chan_id++)
+		xscd_dma_chan_remove(xscd->channels[chan_id]);
+
+	return ret;
+}
+
+/**
+ * xscd_dma_cleanup - Clean up the SCD DMA engine
+ * @xscd: Pointer to the SCD device structure
+ *
+ * This function is the counterpart of xscd_dma_init() and cleans up the
+ * resources related to the DMA engine.
+ */
+void xscd_dma_cleanup(struct xscd_device *xscd)
+{
+	dma_async_device_unregister(&xscd->dma_device);
+	of_dma_controller_free(xscd->dev->of_node);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/xilinx-scenechange.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/xilinx-scenechange.c
@@ -0,0 +1,195 @@
+//SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx Scene Change Detection driver
+ *
+ * Copyright (C) 2018 Xilinx, Inc.
+ *
+ * Authors: Anand Ashok Dumbre <anand.ashok.dumbre@xilinx.com>
+ *          Satish Kumar Nagireddy <satish.nagireddy.nagireddy@xilinx.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/gpio/consumer.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include "xilinx-scenechange.h"
+
+static irqreturn_t xscd_irq_handler(int irq, void *data)
+{
+	struct xscd_device *xscd = (struct xscd_device *)data;
+	u32 status;
+
+	status = xscd_read(xscd->iomem, XSCD_ISR_OFFSET);
+	if (!(status & XSCD_IE_AP_DONE))
+		return IRQ_NONE;
+
+	xscd_write(xscd->iomem, XSCD_ISR_OFFSET, XSCD_IE_AP_DONE);
+
+	if (xscd->memory_based)
+		xscd_dma_irq_handler(xscd);
+	else
+		xscd_chan_event_notify(&xscd->chans[0]);
+
+	return IRQ_HANDLED;
+}
+
+static int xscd_init_resources(struct xscd_device *xscd)
+{
+	struct platform_device *pdev = to_platform_device(xscd->dev);
+	struct resource *res;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	xscd->iomem = devm_ioremap_resource(xscd->dev, res);
+	if (IS_ERR(xscd->iomem))
+		return PTR_ERR(xscd->iomem);
+
+	xscd->irq = platform_get_irq(pdev, 0);
+	if (xscd->irq < 0) {
+		dev_err(xscd->dev, "No valid irq found\n");
+		return -EINVAL;
+	}
+
+	xscd->clk = devm_clk_get(xscd->dev, NULL);
+	if (IS_ERR(xscd->clk))
+		return PTR_ERR(xscd->clk);
+
+	clk_prepare_enable(xscd->clk);
+	return 0;
+}
+
+static int xscd_parse_of(struct xscd_device *xscd)
+{
+	struct device *dev = xscd->dev;
+	struct device_node *node = xscd->dev->of_node;
+	int ret;
+
+	xscd->memory_based = of_property_read_bool(node, "xlnx,memorybased");
+	xscd->rst_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(xscd->rst_gpio)) {
+		if (PTR_ERR(xscd->rst_gpio) != -EPROBE_DEFER)
+			dev_err(dev, "Reset GPIO not setup in DT\n");
+
+		return PTR_ERR(xscd->rst_gpio);
+	}
+
+	ret = of_property_read_u32(node, "xlnx,numstreams",
+				   &xscd->num_streams);
+	if (ret < 0)
+		return ret;
+
+	if (!xscd->memory_based && xscd->num_streams != 1) {
+		dev_err(dev, "Stream-based mode only supports one stream\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int xscd_probe(struct platform_device *pdev)
+{
+	struct xscd_device *xscd;
+	struct device_node *subdev_node;
+	unsigned int id;
+	int ret;
+
+	xscd = devm_kzalloc(&pdev->dev, sizeof(*xscd), GFP_KERNEL);
+	if (!xscd)
+		return -ENOMEM;
+
+	spin_lock_init(&xscd->lock);
+
+	xscd->dev = &pdev->dev;
+	platform_set_drvdata(pdev, xscd);
+
+	ret = xscd_parse_of(xscd);
+	if (ret < 0)
+		return ret;
+
+	ret = xscd_init_resources(xscd);
+	if (ret < 0)
+		return ret;
+
+	/* Reset Scene Change Detection IP */
+	gpiod_set_value_cansleep(xscd->rst_gpio, XSCD_RESET_ASSERT);
+	gpiod_set_value_cansleep(xscd->rst_gpio, XSCD_RESET_DEASSERT);
+
+	/* Initialize the channels. */
+	xscd->chans = devm_kcalloc(xscd->dev, xscd->num_streams,
+				   sizeof(*xscd->chans), GFP_KERNEL);
+	if (!xscd->chans)
+		return -ENOMEM;
+
+	id = 0;
+	for_each_child_of_node(xscd->dev->of_node, subdev_node) {
+		if (id >= xscd->num_streams) {
+			dev_warn(&pdev->dev,
+				 "Too many channels, limiting to %u\n",
+				 xscd->num_streams);
+			of_node_put(subdev_node);
+			break;
+		}
+
+		ret = xscd_chan_init(xscd, id, subdev_node);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "Failed to initialize channel %u\n",
+				id);
+			return ret;
+		}
+
+		id++;
+	}
+
+	/* Initialize the DMA engine. */
+	ret = xscd_dma_init(xscd);
+	if (ret < 0)
+		dev_err(&pdev->dev, "Failed to initialize the DMA\n");
+
+	ret = devm_request_irq(xscd->dev, xscd->irq, xscd_irq_handler,
+			       IRQF_SHARED, dev_name(xscd->dev), xscd);
+	if (ret < 0)
+		dev_err(&pdev->dev, "Failed to request IRQ\n");
+
+	dev_info(xscd->dev, "scene change detect device found!\n");
+	return 0;
+}
+
+static int xscd_remove(struct platform_device *pdev)
+{
+	struct xscd_device *xscd = platform_get_drvdata(pdev);
+	struct device_node *subdev_node;
+	unsigned int id = 0;
+
+	for_each_child_of_node(xscd->dev->of_node, subdev_node) {
+		xscd_chan_cleanup(xscd, id, subdev_node);
+		id++;
+	}
+
+	xscd_dma_cleanup(xscd);
+	clk_disable_unprepare(xscd->clk);
+
+	return 0;
+}
+
+static const struct of_device_id xscd_of_id_table[] = {
+	{ .compatible = "xlnx,v-scd" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, xscd_of_id_table);
+
+static struct platform_driver xscd_driver = {
+	.driver = {
+		.name		= "xilinx-scd",
+		.of_match_table	= xscd_of_id_table,
+	},
+	.probe			= xscd_probe,
+	.remove			= xscd_remove,
+};
+
+module_platform_driver(xscd_driver);
+
+MODULE_AUTHOR("Xilinx Inc.");
+MODULE_DESCRIPTION("Xilinx Scene Change Detection");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/xilinx-scenechange.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/xilinx-scenechange.h
@@ -0,0 +1,245 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Xilinx Scene Change Detection driver
+ *
+ * Copyright (C) 2018 Xilinx, Inc.
+ *
+ * Authors: Anand Ashok Dumbre <anand.ashok.dumbre@xilinx.com>
+ *          Satish Kumar Nagireddy <satish.nagireddy.nagireddy@xilinx.com>
+ */
+
+#ifndef _XILINX_SCENECHANGE_H_
+#define _XILINX_SCENECHANGE_H_
+
+#include <linux/bitops.h>
+#include <linux/dmaengine.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+#include <linux/xilinx-v4l2-controls.h>
+
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-subdev.h>
+
+struct clk;
+struct device;
+struct device_node;
+struct gpio_desc;
+
+/* Register/Descriptor Offsets */
+#define XSCD_CTRL_OFFSET		0x000
+#define XSCD_CTRL_AP_START		BIT(0)
+#define XSCD_CTRL_AP_DONE		BIT(1)
+#define XSCD_CTRL_AP_IDLE		BIT(2)
+#define XSCD_CTRL_AP_READY		BIT(3)
+#define XSCD_CTRL_AUTO_RESTART		BIT(7)
+
+#define XSCD_GIE_OFFSET			0x004
+#define XSCD_GIE_EN			BIT(0)
+
+#define XSCD_IE_OFFSET			0x008
+#define XSCD_IE_AP_DONE			BIT(0)
+#define XSCD_IE_AP_READY		BIT(1)
+
+#define XSCD_ISR_OFFSET			0x00c
+#define XSCD_WIDTH_OFFSET		0x010
+#define XSCD_HEIGHT_OFFSET		0x018
+#define XSCD_STRIDE_OFFSET		0x020
+#define XSCD_VID_FMT_OFFSET		0x028
+#define XSCD_VID_FMT_RGB		0
+#define XSCD_VID_FMT_YUV_444		1
+#define XSCD_VID_FMT_YUV_422		2
+#define XSCD_VID_FMT_YUV_420		3
+#define XSCD_VID_FMT_Y8			24
+#define XSCD_VID_FMT_Y10		25
+
+#define XSCD_SUBSAMPLE_OFFSET		0x030
+#define XSCD_SAD_OFFSET			0x038
+#define XSCD_ADDR_OFFSET		0x040
+#define XSCD_CHAN_OFFSET		0x100
+#define XSCD_CHAN_EN_OFFSET		0x780
+
+#define XSCD_MAX_CHANNELS		8
+
+#define XSCD_RESET_DEASSERT		(0)
+#define XSCD_RESET_ASSERT		(1)
+
+/****************************** PROTOTYPES ************************************/
+
+struct xscd_device;
+
+/**
+ * struct xscd_dma_desc - DMA channel
+ * @luma_plane_addr: Luma plane buffer address
+ * @vsize: width of the luma frame
+ * @hsize: height of the luma frame
+ * @stride: stride of the luma frame
+ */
+struct xscd_dma_desc {
+	dma_addr_t luma_plane_addr;
+	u32 vsize;
+	u32 hsize;
+	u32 stride;
+};
+
+/**
+ * struct xscd_dma_tx_descriptor - Per Transaction structure
+ * @async_tx: Async transaction descriptor
+ * @sw: Software Descriptor
+ * @node: Node in the channel descriptor list
+ */
+struct xscd_dma_tx_descriptor {
+	struct dma_async_tx_descriptor async_tx;
+	struct xscd_dma_desc sw;
+	struct list_head node;
+};
+
+static inline struct xscd_dma_tx_descriptor *
+to_xscd_dma_tx_descriptor(struct dma_async_tx_descriptor *tx)
+{
+	return container_of(tx, struct xscd_dma_tx_descriptor, async_tx);
+}
+
+/**
+ * struct xscd_dma_chan - DMA Channel structure
+ * @xscd: SCD device
+ * @iomem: I/O memory address of the channel registers
+ * @id: scene change channel ID
+ * @common: DMA common channel
+ * @tasklet: Cleanup work after irq
+ * @lock: Protects pending_list, done_list, active_desc, enabled and running
+ * @pending_list: Descriptors waiting
+ * @done_list: Complete descriptors
+ * @active_desc: Currently active buffer being read/written to
+ * @enabled: Channel is enabled
+ * @running: Channel is running
+ * @wait: Wait queue to wait for the channel to stop
+ */
+struct xscd_dma_chan {
+	struct xscd_device *xscd;
+	void __iomem *iomem;
+	unsigned int id;
+
+	struct dma_chan common;
+	struct tasklet_struct tasklet;
+
+	spinlock_t lock;
+	struct list_head pending_list;
+	struct list_head done_list;
+	struct xscd_dma_tx_descriptor *active_desc;
+	unsigned int enabled;
+	unsigned int running;
+	wait_queue_head_t wait;
+};
+
+static inline struct xscd_dma_chan *to_xscd_dma_chan(struct dma_chan *chan)
+{
+	return container_of(chan, struct xscd_dma_chan, common);
+}
+
+/**
+ * struct xscd_chan - Video Stream structure
+ * @id: scene change channel ID
+ * @threshold: scene change detection threshold
+ * @iomem: I/O memory address of the channel registers
+ * @xscd: SCD device
+ * @subdev: V4L2 subdevice
+ * @ctrl_handler: V4L2 control handler
+ * @pads: media pads
+ * @format: active V4L2 media bus format for the pad
+ * @event: scene change event
+ * @dmachan: dma channel part of the scenechange stream
+ * @lock: lock to protect active stream count variable
+ */
+struct xscd_chan {
+	int id;
+	int threshold;
+	void __iomem *iomem;
+	struct xscd_device *xscd;
+	struct v4l2_subdev subdev;
+	struct v4l2_ctrl_handler ctrl_handler;
+	struct media_pad pads[2];
+	struct v4l2_mbus_framefmt format;
+	struct v4l2_event event;
+	struct xscd_dma_chan dmachan;
+
+	/* Lock to protect active stream count */
+	struct mutex lock;
+};
+
+static inline struct xscd_chan *to_xscd_chan(struct v4l2_subdev *subdev)
+{
+	return container_of(subdev, struct xscd_chan, subdev);
+}
+
+/**
+ * struct xscd_device - Xilinx Scene Change Detection device structure
+ * @dev: (OF) device
+ * @iomem: device I/O register space remapped to kernel virtual memory
+ * @rst_gpio: reset GPIO
+ * @clk: video core clock
+ * @irq: Device IRQ
+ * @memory_based: Flag to identify memory based mode
+ * @num_streams: Number of streams in the design
+ * @chans: video stream instances
+ * @dma_device: DMA device structure
+ * @channels: DMA channels
+ * @lock: Protects the running field
+ * @running: True when the SCD core is running
+ */
+struct xscd_device {
+	struct device *dev;
+	void __iomem *iomem;
+	struct gpio_desc *rst_gpio;
+	struct clk *clk;
+	int irq;
+
+	u8 memory_based;
+	int num_streams;
+
+	struct xscd_chan *chans;
+
+	struct dma_device dma_device;
+	struct xscd_dma_chan *channels[XSCD_MAX_CHANNELS];
+
+	/* This lock is to protect the running field */
+	spinlock_t lock;
+	u8 running;
+};
+
+/*
+ * Register related operations
+ */
+static inline u32 xscd_read(void __iomem *iomem, u32 addr)
+{
+	return ioread32(iomem + addr);
+}
+
+static inline void xscd_write(void __iomem *iomem, u32 addr, u32 value)
+{
+	iowrite32(value, iomem + addr);
+}
+
+static inline void xscd_clr(void __iomem *iomem, u32 addr, u32 clr)
+{
+	xscd_write(iomem, addr, xscd_read(iomem, addr) & ~clr);
+}
+
+static inline void xscd_set(void __iomem *iomem, u32 addr, u32 set)
+{
+	xscd_write(iomem, addr, xscd_read(iomem, addr) | set);
+}
+
+void xscd_dma_enable_channel(struct xscd_dma_chan *chan, bool enable);
+void xscd_dma_irq_handler(struct xscd_device *xscd);
+int xscd_dma_init(struct xscd_device *xscd);
+void xscd_dma_cleanup(struct xscd_device *xscd);
+
+void xscd_chan_event_notify(struct xscd_chan *chan);
+int xscd_chan_init(struct xscd_device *xscd, unsigned int chan_id,
+		   struct device_node *node);
+void xscd_chan_cleanup(struct xscd_device *xscd, unsigned int chan_id,
+		       struct device_node *node);
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/xilinx-sdirxss.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/xilinx-sdirxss.c
@@ -0,0 +1,2678 @@
+/*
+ * Xilinx SDI Rx Subsystem
+ *
+ * Copyright (C) 2017 Xilinx, Inc.
+ *
+ * Contacts: Vishal Sagar <vsagar@xilinx.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <dt-bindings/media/xilinx-vip.h>
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/compiler.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/spinlock_types.h>
+#include <linux/types.h>
+#include <linux/v4l2-dv-timings.h>
+#include <linux/v4l2-subdev.h>
+#include <linux/xilinx-sdirxss.h>
+#include <linux/xilinx-v4l2-controls.h>
+#include <media/hdr-ctrls.h>
+#include <media/media-entity.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-subdev.h>
+#include "xilinx-vip.h"
+
+/*
+ * SDI Rx register map, bitmask and offsets
+ */
+#define XSDIRX_RST_CTRL_REG		0x00
+#define XSDIRX_MDL_CTRL_REG		0x04
+#define XSDIRX_GLBL_IER_REG		0x0C
+#define XSDIRX_ISR_REG			0x10
+#define XSDIRX_IER_REG			0x14
+#define XSDIRX_ST352_VALID_REG		0x18
+#define XSDIRX_ST352_DS1_REG		0x1C
+#define XSDIRX_ST352_DS3_REG		0x20
+#define XSDIRX_ST352_DS5_REG		0x24
+#define XSDIRX_ST352_DS7_REG		0x28
+#define XSDIRX_ST352_DS9_REG		0x2C
+#define XSDIRX_ST352_DS11_REG		0x30
+#define XSDIRX_ST352_DS13_REG		0x34
+#define XSDIRX_ST352_DS15_REG		0x38
+#define XSDIRX_VERSION_REG		0x3C
+#define XSDIRX_SS_CONFIG_REG		0x40
+#define XSDIRX_MODE_DET_STAT_REG	0x44
+#define XSDIRX_TS_DET_STAT_REG		0x48
+#define XSDIRX_EDH_STAT_REG		0x4C
+#define XSDIRX_EDH_ERRCNT_EN_REG	0x50
+#define XSDIRX_EDH_ERRCNT_REG		0x54
+#define XSDIRX_CRC_ERRCNT_REG		0x58
+#define XSDIRX_VID_LOCK_WINDOW_REG	0x5C
+#define XSDIRX_SB_RX_STS_REG		0x60
+
+#define XSDIRX_RST_CTRL_SS_EN_MASK			BIT(0)
+#define XSDIRX_RST_CTRL_SRST_MASK			BIT(1)
+#define XSDIRX_RST_CTRL_RST_CRC_ERRCNT_MASK		BIT(2)
+#define XSDIRX_RST_CTRL_RST_EDH_ERRCNT_MASK		BIT(3)
+#define XSDIRX_RST_CTRL_SDIRX_BRIDGE_ENB_MASK		BIT(8)
+#define XSDIRX_RST_CTRL_VIDIN_AXI4S_MOD_ENB_MASK	BIT(9)
+#define XSDIRX_RST_CTRL_BRIDGE_CH_FMT_OFFSET		10
+#define XSDIRX_RST_CTRL_BRIDGE_CH_FMT_MASK		GENMASK(12, 10)
+#define XSDIRX_RST_CTRL_BRIDGE_CH_FMT_YUV444		1
+
+#define XSDIRX_MDL_CTRL_FRM_EN_MASK		BIT(4)
+#define XSDIRX_MDL_CTRL_MODE_DET_EN_MASK	BIT(5)
+#define XSDIRX_MDL_CTRL_MODE_HD_EN_MASK		BIT(8)
+#define XSDIRX_MDL_CTRL_MODE_SD_EN_MASK		BIT(9)
+#define XSDIRX_MDL_CTRL_MODE_3G_EN_MASK		BIT(10)
+#define XSDIRX_MDL_CTRL_MODE_6G_EN_MASK		BIT(11)
+#define XSDIRX_MDL_CTRL_MODE_12GI_EN_MASK	BIT(12)
+#define XSDIRX_MDL_CTRL_MODE_12GF_EN_MASK	BIT(13)
+#define XSDIRX_MDL_CTRL_MODE_AUTO_DET_MASK	GENMASK(13, 8)
+
+#define XSDIRX_MDL_CTRL_FORCED_MODE_OFFSET	16
+#define XSDIRX_MDL_CTRL_FORCED_MODE_MASK	GENMASK(18, 16)
+
+#define XSDIRX_GLBL_INTR_EN_MASK	BIT(0)
+
+#define XSDIRX_INTR_VIDLOCK_MASK	BIT(0)
+#define XSDIRX_INTR_VIDUNLOCK_MASK	BIT(1)
+#define XSDIRX_INTR_VSYNC_MASK		BIT(2)
+#define XSDIRX_INTR_OVERFLOW_MASK	BIT(9)
+#define XSDIRX_INTR_UNDERFLOW_MASK	BIT(10)
+
+#define XSDIRX_INTR_ALL_MASK	(XSDIRX_INTR_VIDLOCK_MASK |\
+				XSDIRX_INTR_VIDUNLOCK_MASK |\
+				XSDIRX_INTR_VSYNC_MASK |\
+				XSDIRX_INTR_OVERFLOW_MASK |\
+				XSDIRX_INTR_UNDERFLOW_MASK)
+
+#define XSDIRX_ST352_VALID_DS1_MASK	BIT(0)
+#define XSDIRX_ST352_VALID_DS3_MASK	BIT(1)
+#define XSDIRX_ST352_VALID_DS5_MASK	BIT(2)
+#define XSDIRX_ST352_VALID_DS7_MASK	BIT(3)
+#define XSDIRX_ST352_VALID_DS9_MASK	BIT(4)
+#define XSDIRX_ST352_VALID_DS11_MASK	BIT(5)
+#define XSDIRX_ST352_VALID_DS13_MASK	BIT(6)
+#define XSDIRX_ST352_VALID_DS15_MASK	BIT(7)
+
+#define XSDIRX_MODE_DET_STAT_RX_MODE_MASK	GENMASK(2, 0)
+#define XSDIRX_MODE_DET_STAT_MODE_LOCK_MASK	BIT(3)
+#define XSDIRX_MODE_DET_STAT_ACT_STREAM_MASK	GENMASK(6, 4)
+#define XSDIRX_MODE_DET_STAT_ACT_STREAM_OFFSET	4
+#define XSDIRX_MODE_DET_STAT_LVLB_3G_MASK	BIT(7)
+
+#define XSDIRX_ACTIVE_STREAMS_1		0x0
+#define XSDIRX_ACTIVE_STREAMS_2		0x1
+#define XSDIRX_ACTIVE_STREAMS_4		0x2
+#define XSDIRX_ACTIVE_STREAMS_8		0x3
+#define XSDIRX_ACTIVE_STREAMS_16	0x4
+
+#define XSDIRX_TS_DET_STAT_LOCKED_MASK		BIT(0)
+#define XSDIRX_TS_DET_STAT_SCAN_MASK		BIT(1)
+#define XSDIRX_TS_DET_STAT_SCAN_OFFSET		(1)
+#define XSDIRX_TS_DET_STAT_FAMILY_MASK		GENMASK(7, 4)
+#define XSDIRX_TS_DET_STAT_FAMILY_OFFSET	(4)
+#define XSDIRX_TS_DET_STAT_RATE_MASK		GENMASK(11, 8)
+#define XSDIRX_TS_DET_STAT_RATE_OFFSET		(8)
+
+#define XSDIRX_TS_DET_STAT_RATE_NONE		0x0
+#define XSDIRX_TS_DET_STAT_RATE_96HZ		0x1
+#define XSDIRX_TS_DET_STAT_RATE_23_98HZ		0x2
+#define XSDIRX_TS_DET_STAT_RATE_24HZ		0x3
+#define XSDIRX_TS_DET_STAT_RATE_47_95HZ		0x4
+#define XSDIRX_TS_DET_STAT_RATE_25HZ		0x5
+#define XSDIRX_TS_DET_STAT_RATE_29_97HZ		0x6
+#define XSDIRX_TS_DET_STAT_RATE_30HZ		0x7
+#define XSDIRX_TS_DET_STAT_RATE_48HZ		0x8
+#define XSDIRX_TS_DET_STAT_RATE_50HZ		0x9
+#define XSDIRX_TS_DET_STAT_RATE_59_94HZ		0xA
+#define XSDIRX_TS_DET_STAT_RATE_60HZ		0xB
+#define XSDIRX_TS_DET_STAT_RATE_95_90HZ		0xC
+#define XSDIRX_TS_DET_STAT_RATE_100HZ		0xD
+#define XSDIRX_TS_DET_STAT_RATE_120HZ		0xE
+#define XSDIRX_TS_DET_STAT_RATE_119_88HZ	0xF
+
+#define XSDIRX_EDH_STAT_EDH_AP_MASK	BIT(0)
+#define XSDIRX_EDH_STAT_EDH_FF_MASK	BIT(1)
+#define XSDIRX_EDH_STAT_EDH_ANC_MASK	BIT(2)
+#define XSDIRX_EDH_STAT_AP_FLAG_MASK	GENMASK(8, 4)
+#define XSDIRX_EDH_STAT_FF_FLAG_MASK	GENMASK(13, 9)
+#define XSDIRX_EDH_STAT_ANC_FLAG_MASK	GENMASK(18, 14)
+#define XSDIRX_EDH_STAT_PKT_FLAG_MASK	GENMASK(22, 19)
+
+#define XSDIRX_EDH_ERRCNT_COUNT_MASK	GENMASK(15, 0)
+
+#define XSDIRX_CRC_ERRCNT_COUNT_MASK	GENMASK(31, 16)
+#define XSDIRX_CRC_ERRCNT_DS_CRC_MASK	GENMASK(15, 0)
+
+#define XSDIRX_VERSION_REV_MASK		GENMASK(7, 0)
+#define XSDIRX_VERSION_PATCHID_MASK	GENMASK(11, 8)
+#define XSDIRX_VERSION_VER_REV_MASK	GENMASK(15, 12)
+#define XSDIRX_VERSION_VER_MIN_MASK	GENMASK(23, 16)
+#define XSDIRX_VERSION_VER_MAJ_MASK	GENMASK(31, 24)
+
+#define XSDIRX_SS_CONFIG_EDH_INCLUDED_MASK		BIT(1)
+
+#define XSDIRX_STAT_SB_RX_TDATA_CHANGE_DONE_MASK	BIT(0)
+#define XSDIRX_STAT_SB_RX_TDATA_CHANGE_FAIL_MASK	BIT(1)
+#define XSDIRX_STAT_SB_RX_TDATA_GT_RESETDONE_MASK	BIT(2)
+#define XSDIRX_STAT_SB_RX_TDATA_GT_BITRATE_MASK		BIT(3)
+
+#define XSDIRX_DEFAULT_WIDTH	(1920)
+#define XSDIRX_DEFAULT_HEIGHT	(1080)
+
+#define XSDIRX_MAX_STR_LENGTH	16
+
+#define XSDIRXSS_SDI_STD_3G		0
+#define XSDIRXSS_SDI_STD_6G		1
+#define XSDIRXSS_SDI_STD_12G_8DS	2
+
+#define XSDIRX_DEFAULT_VIDEO_LOCK_WINDOW	0x3000
+
+#define XSDIRX_MODE_HD_MASK	0x0
+#define XSDIRX_MODE_SD_MASK	0x1
+#define XSDIRX_MODE_3G_MASK	0x2
+#define XSDIRX_MODE_6G_MASK	0x4
+#define XSDIRX_MODE_12GI_MASK	0x5
+#define XSDIRX_MODE_12GF_MASK	0x6
+
+/* Maximum number of events per file handle. */
+#define XSDIRX_MAX_EVENTS	(128)
+
+/* ST352 related macros */
+#define XST352_PAYLOAD_BYTE_MASK	0xFF
+#define XST352_PAYLOAD_BYTE1_SHIFT	0
+#define XST352_PAYLOAD_BYTE2_SHIFT	8
+#define XST352_PAYLOAD_BYTE3_SHIFT	16
+#define XST352_PAYLOAD_BYTE4_SHIFT	24
+
+#define XST352_BYTE1_ST292_1x720L_1_5G		0x84
+#define XST352_BYTE1_ST292_1x1080L_1_5G		0x85
+#define XST352_BYTE1_ST425_2008_750L_3GB	0x88
+#define XST352_BYTE1_ST425_2008_1125L_3GA	0x89
+#define XST352_BYTE1_ST372_DL_3GB		0x8A
+#define XST352_BYTE1_ST372_2x720L_3GB		0x8B
+#define XST352_BYTE1_ST372_2x1080L_3GB		0x8C
+#define XST352_BYTE1_ST2081_10_2160L_6G		0xC0
+#define XST352_BYTE1_ST2081_10_2_1080L_6G	0xC1
+#define XST352_BYTE1_ST2081_10_DL_2160L_6G	0xC2
+#define XST352_BYTE1_ST2082_10_2160L_12G	0xCE
+
+#define XST352_BYTE2_TS_TYPE_MASK		BIT(15)
+#define XST352_BYTE2_TS_TYPE_OFFSET		15
+#define XST352_BYTE2_PIC_TYPE_MASK		BIT(14)
+#define XST352_BYTE2_PIC_TYPE_OFFSET		14
+#define XST352_BYTE2_TS_PIC_TYPE_INTERLACED	0
+#define XST352_BYTE2_TS_PIC_TYPE_PROGRESSIVE	1
+
+#define XST352_BYTE2_FPS_MASK			0xF
+#define XST352_BYTE2_FPS_SHIFT			8
+#define XST352_BYTE2_FPS_96F			0x1
+#define XST352_BYTE2_FPS_24F			0x2
+#define XST352_BYTE2_FPS_24			0x3
+#define XST352_BYTE2_FPS_48F			0x4
+#define XST352_BYTE2_FPS_25			0x5
+#define XST352_BYTE2_FPS_30F			0x6
+#define XST352_BYTE2_FPS_30			0x7
+#define XST352_BYTE2_FPS_48			0x8
+#define XST352_BYTE2_FPS_50			0x9
+#define XST352_BYTE2_FPS_60F			0xA
+#define XST352_BYTE2_FPS_60			0xB
+/* Table 4 ST 2081-10:2015 */
+#define XST352_BYTE2_FPS_96			0xC
+#define XST352_BYTE2_FPS_100			0xD
+#define XST352_BYTE2_FPS_120			0xE
+#define XST352_BYTE2_FPS_120F			0xF
+
+/* Electro Optical Transfer Function Byte 2 bit[5:4] */
+#define XST352_BYTE2_EOTF_MASK			GENMASK(13, 12)
+#define XST352_BYTE2_EOTF_OFFSET		12
+#define XST352_BYTE2_EOTF_SDRTV			0x0
+#define XST352_BYTE2_EOTF_HLG			0x1
+#define XST352_BYTE2_EOTF_SMPTE2084		0x2
+
+#define XST352_BYTE2_COLORIMETRY_MASK		GENMASK(21, 20)
+#define XST352_BYTE2_COLORIMETRY_OFFSET		20
+#define XST352_BYTE2_COLORIMETRY_BT709		0
+#define XST352_BYTE2_COLORIMETRY_VANC		1
+#define XST352_BYTE2_COLORIMETRY_UHDTV		2
+#define XST352_BYTE2_COLORIMETRY_UNKNOWN	3
+
+#define XST352_BYTE3_ACT_LUMA_COUNT_MASK	BIT(22)
+#define XST352_BYTE3_ACT_LUMA_COUNT_OFFSET	22
+
+#define XST352_BYTE3_COLOR_FORMAT_MASK		GENMASK(19, 16)
+#define XST352_BYTE3_COLOR_FORMAT_OFFSET	16
+#define XST352_BYTE3_COLOR_FORMAT_422		0x0
+#define XST352_BYTE3_COLOR_FORMAT_YUV444	0x1
+#define XST352_BYTE3_COLOR_FORMAT_420		0x3
+#define XST352_BYTE3_COLOR_FORMAT_GBR		0x2
+
+#define XST352_BYTE4_BIT_DEPTH_MASK		GENMASK(25, 24)
+#define XST352_BYTE4_BIT_DEPTH_OFFSET		24
+#define XST352_BYTE4_BIT_DEPTH_10		0x1
+#define XST352_BYTE4_BIT_DEPTH_12		0x2
+
+/* Refer Table 3 ST2082-10:2018 */
+#define XST352_BYTE4_LUM_COL_DIFF_MASK		BIT(28)
+
+#define CLK_INT		148500000UL
+
+/**
+ * enum sdi_family_enc - SDI Transport Video Format Detected with Active Pixels
+ * @XSDIRX_SMPTE_ST_274: SMPTE ST 274 detected with AP 1920x1080
+ * @XSDIRX_SMPTE_ST_296: SMPTE ST 296 detected with AP 1280x720
+ * @XSDIRX_SMPTE_ST_2048_2: SMPTE ST 2048-2 detected with AP 2048x1080
+ * @XSDIRX_SMPTE_ST_295: SMPTE ST 295 detected with AP 1920x1080
+ * @XSDIRX_NTSC: NTSC encoding detected with AP 720x486
+ * @XSDIRX_PAL: PAL encoding detected with AP 720x576
+ * @XSDIRX_TS_UNKNOWN: Unknown SMPTE Transport family type
+ */
+enum sdi_family_enc {
+	XSDIRX_SMPTE_ST_274	= 0,
+	XSDIRX_SMPTE_ST_296	= 1,
+	XSDIRX_SMPTE_ST_2048_2	= 2,
+	XSDIRX_SMPTE_ST_295	= 3,
+	XSDIRX_NTSC		= 8,
+	XSDIRX_PAL		= 9,
+	XSDIRX_TS_UNKNOWN	= 15
+};
+
+/**
+ * struct xsdirxss_core - Core configuration SDI Rx Subsystem device structure
+ * @dev: Platform structure
+ * @iomem: Base address of subsystem
+ * @irq: requested irq number
+ * @include_edh: EDH processor presence
+ * @mode: 3G/6G/12G mode
+ * @clks: array of clocks
+ * @num_clks: number of clocks
+ * @rst_gt_gpio: reset gt gpio (fmc init done)
+ * @rst_picxo_gpio: reset picxo core
+ * @bpc: Bits per component, can be 10 or 12
+ */
+struct xsdirxss_core {
+	struct device *dev;
+	void __iomem *iomem;
+	int irq;
+	bool include_edh;
+	int mode;
+	struct clk_bulk_data *clks;
+	int num_clks;
+	struct gpio_desc *rst_gt_gpio;
+	struct gpio_desc *rst_picxo_gpio;
+	u32 bpc;
+};
+
+/**
+ * struct xsdirxss_state - SDI Rx Subsystem device structure
+ * @core: Core structure for MIPI SDI Rx Subsystem
+ * @subdev: The v4l2 subdev structure
+ * @ctrl_handler: control handler
+ * @event: Holds the video unlock event
+ * @format: Active V4L2 format on source pad
+ * @default_format: default V4L2 media bus format
+ * @frame_interval: Captures the frame rate
+ * @vip_format: format information corresponding to the active format
+ * @pad: source media pad
+ * @static_hdr: static hdr payload
+ * @prev_payload: Previous ST352 payload
+ * @vidlockwin: Video lock window value set by control
+ * @edhmask: EDH mask set by control
+ * @searchmask: Search mask set by control
+ * @streaming: Flag for storing streaming state
+ * @vidlocked: Flag indicating SDI Rx has locked onto video stream
+ * @ts_is_interlaced: Flag indicating Transport Stream is interlaced.
+ * @framer_enable: Flag for framer enabled or not set by control
+ *
+ * This structure contains the device driver related parameters
+ */
+struct xsdirxss_state {
+	struct xsdirxss_core core;
+	struct v4l2_subdev subdev;
+	struct v4l2_ctrl_handler ctrl_handler;
+	struct v4l2_event event;
+	struct v4l2_mbus_framefmt format;
+	struct v4l2_mbus_framefmt default_format;
+	struct v4l2_fract frame_interval;
+	const struct xvip_video_format *vip_format;
+	struct media_pad pad;
+	struct v4l2_hdr10_payload static_hdr;
+	u32 prev_payload;
+	u32 vidlockwin;
+	u32 edhmask;
+	u16 searchmask;
+	bool streaming;
+	bool vidlocked;
+	bool ts_is_interlaced;
+	bool framer_enable;
+};
+
+/* List of clocks required by UHD-SDI Rx subsystem */
+static const char * const xsdirxss_clks[] = {
+	"s_axi_aclk", "sdi_rx_clk", "video_out_clk",
+};
+
+static const u32 xsdirxss_10bpc_mbus_fmts[] = {
+	MEDIA_BUS_FMT_UYVY10_1X20,
+	MEDIA_BUS_FMT_VYYUYY10_4X20,
+	MEDIA_BUS_FMT_VUY10_1X30,
+	MEDIA_BUS_FMT_RBG101010_1X30,
+};
+
+static const u32 xsdirxss_12bpc_mbus_fmts[] = {
+	MEDIA_BUS_FMT_UYVY12_1X24,
+	MEDIA_BUS_FMT_UYYVYY12_4X24,
+	MEDIA_BUS_FMT_VUY12_1X36,
+	MEDIA_BUS_FMT_RBG121212_1X36,
+};
+
+#define XLNX_V4L2_DV_BT_2048X1080P24 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2048, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 510, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_SDI) \
+}
+
+#define XLNX_V4L2_DV_BT_2048X1080P25 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2048, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 400, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_SDI) \
+}
+
+#define XLNX_V4L2_DV_BT_2048X1080P30 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2048, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 66, 20, 66, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_SDI) \
+}
+
+#define XLNX_V4L2_DV_BT_2048X1080I48 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2048, 1080, 1, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 329, 44, 329, 2, 5, 15, 3, 5, 15, \
+		V4L2_DV_BT_STD_SDI) \
+}
+
+#define XLNX_V4L2_DV_BT_2048X1080I50 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2048, 1080, 1, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 274, 44, 274, 2, 5, 15, 3, 5, 15, \
+		V4L2_DV_BT_STD_SDI) \
+}
+
+#define XLNX_V4L2_DV_BT_2048X1080I60 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2048, 1080, 1, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		74250000, 66, 20, 66, 2, 5, 15, 3, 5, 15, \
+		V4L2_DV_BT_STD_SDI) \
+}
+
+#define XLNX_V4L2_DV_BT_1920X1080P48 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 638, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_SDI) \
+}
+
+#define XLNX_V4L2_DV_BT_2048X1080P48 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2048, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 510, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_SDI) \
+}
+
+#define XLNX_V4L2_DV_BT_2048X1080P50 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2048, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 400, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_SDI) \
+}
+
+#define XLNX_V4L2_DV_BT_2048X1080P60 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2048, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 88, 44, 20, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_SDI) \
+}
+
+#define XLNX_V4L2_DV_BT_3840X2160P48 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(3840, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		594000000, 1276, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_SDI) \
+}
+
+#define XLNX_V4L2_DV_BT_4096X2160P48 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(4096, 2160, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		594000000, 1020, 88, 296, 8, 10, 72, 0, 0, 0, \
+		V4L2_DV_BT_STD_SDI) \
+}
+
+#define XLNX_V4L2_DV_BT_1920X1080I48 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 1, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		148500000, 371, 88, 371, 2, 5, 15, 3, 5, 15, \
+		V4L2_DV_BT_STD_SDI) \
+}
+
+#define XLNX_V4L2_DV_BT_1920X1080P96 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		297000000, 638, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_SDI) \
+}
+
+#define XLNX_V4L2_DV_BT_1920X1080P100 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		297000000, 528, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_SDI) \
+}
+
+#define XLNX_V4L2_DV_BT_1920X1080P120 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(1920, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		297000000, 88, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_SDI) \
+}
+
+#define XLNX_V4L2_DV_BT_2048X1080P96 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2048, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		297000000, 510, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_SDI) \
+}
+
+#define XLNX_V4L2_DV_BT_2048X1080P100 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2048, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		297000000, 400, 44, 148, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_SDI) \
+}
+
+#define XLNX_V4L2_DV_BT_2048X1080P120 { \
+	.type = V4L2_DV_BT_656_1120, \
+	V4L2_INIT_BT_TIMINGS(2048, 1080, 0, \
+		V4L2_DV_HSYNC_POS_POL | V4L2_DV_VSYNC_POS_POL, \
+		297000000, 88, 44, 20, 4, 5, 36, 0, 0, 0, \
+		V4L2_DV_BT_STD_SDI) \
+}
+
+static const struct v4l2_dv_timings fmt_cap[] = {
+	V4L2_DV_BT_SDI_720X487I60,
+	V4L2_DV_BT_CEA_720X576I50,
+	V4L2_DV_BT_CEA_1280X720P24,
+	V4L2_DV_BT_CEA_1280X720P25,
+	V4L2_DV_BT_CEA_1280X720P30,
+	V4L2_DV_BT_CEA_1280X720P50,
+	V4L2_DV_BT_CEA_1280X720P60,
+	V4L2_DV_BT_CEA_1920X1080P24,
+	V4L2_DV_BT_CEA_1920X1080P30,
+	V4L2_DV_BT_CEA_1920X1080I50,
+	V4L2_DV_BT_CEA_1920X1080I60,
+	V4L2_DV_BT_CEA_1920X1080P50,
+	V4L2_DV_BT_CEA_1920X1080P60,
+	V4L2_DV_BT_CEA_3840X2160P24,
+	V4L2_DV_BT_CEA_3840X2160P30,
+	V4L2_DV_BT_CEA_3840X2160P50,
+	V4L2_DV_BT_CEA_3840X2160P60,
+	V4L2_DV_BT_CEA_4096X2160P24,
+	V4L2_DV_BT_CEA_4096X2160P25,
+	V4L2_DV_BT_CEA_4096X2160P30,
+	V4L2_DV_BT_CEA_4096X2160P50,
+	V4L2_DV_BT_CEA_4096X2160P60,
+
+	XLNX_V4L2_DV_BT_2048X1080P24,
+	XLNX_V4L2_DV_BT_2048X1080P25,
+	XLNX_V4L2_DV_BT_2048X1080P30,
+	XLNX_V4L2_DV_BT_2048X1080I48,
+	XLNX_V4L2_DV_BT_2048X1080I50,
+	XLNX_V4L2_DV_BT_2048X1080I60,
+	XLNX_V4L2_DV_BT_2048X1080P48,
+	XLNX_V4L2_DV_BT_2048X1080P50,
+	XLNX_V4L2_DV_BT_2048X1080P60,
+	XLNX_V4L2_DV_BT_1920X1080P48,
+	XLNX_V4L2_DV_BT_1920X1080I48,
+	XLNX_V4L2_DV_BT_3840X2160P48,
+	XLNX_V4L2_DV_BT_4096X2160P48,
+
+	/* HFR */
+	XLNX_V4L2_DV_BT_1920X1080P96,
+	XLNX_V4L2_DV_BT_1920X1080P100,
+	XLNX_V4L2_DV_BT_1920X1080P120,
+	XLNX_V4L2_DV_BT_2048X1080P96,
+	XLNX_V4L2_DV_BT_2048X1080P100,
+	XLNX_V4L2_DV_BT_2048X1080P120,
+};
+
+struct xsdirxss_dv_map {
+	u32 width;
+	u32 height;
+	u32 fps;
+	struct v4l2_dv_timings format;
+};
+
+static const struct xsdirxss_dv_map xsdirxss_dv_timings[] = {
+	/* SD - 720x487i60 */
+	{ 720, 243, 30, V4L2_DV_BT_SDI_720X487I60 },
+	/* SD - 720x576i50 */
+	{ 720, 288, 25, V4L2_DV_BT_CEA_720X576I50 },
+	/* HD - 1280x720p23.98 */
+	/* HD - 1280x720p24 */
+	{ 1280, 720, 24, V4L2_DV_BT_CEA_1280X720P24 },
+	/* HD - 1280x720p25 */
+	{ 1280, 720, 25, V4L2_DV_BT_CEA_1280X720P25 },
+	/* HD - 1280x720p29.97 */
+	/* HD - 1280x720p30 */
+	{ 1280, 720, 30, V4L2_DV_BT_CEA_1280X720P30 },
+	/* HD - 1280x720p50 */
+	{ 1280, 720, 50, V4L2_DV_BT_CEA_1280X720P50 },
+	/* HD - 1280x720p59.94 */
+	/* HD - 1280x720p60 */
+	{ 1280, 720, 60, V4L2_DV_BT_CEA_1280X720P60 },
+	/* HD - 1920x1080p23.98 */
+	/* HD - 1920x1080p24 */
+	{ 1920, 1080, 24, V4L2_DV_BT_CEA_1920X1080P24 },
+	/* HD - 1920x1080p25 */
+	{ 1920, 1080, 25, V4L2_DV_BT_CEA_1920X1080P25 },
+	/* HD - 1920x1080p29.97 */
+	/* HD - 1920x1080p30 */
+	{ 1920, 1080, 30, V4L2_DV_BT_CEA_1920X1080P30 },
+
+	/* HD - 2048x1080p23.98 */
+	/* HD - 2048x1080p24 */
+	{ 2048, 1080, 24, XLNX_V4L2_DV_BT_2048X1080P24 },
+	/* HD - 2048x1080p25 */
+	{ 2048, 1080, 24, XLNX_V4L2_DV_BT_2048X1080P25 },
+	/* HD - 2048x1080p29.97 */
+	/* HD - 2048x1080p30 */
+	{ 2048, 1080, 24, XLNX_V4L2_DV_BT_2048X1080P30 },
+	/* HD - 1920x1080i47.95 */
+	/* HD - 1920x1080i48 */
+	{ 1920, 540, 24, XLNX_V4L2_DV_BT_1920X1080I48 },
+
+	/* HD - 1920x1080i50 */
+	{ 1920, 540, 25, V4L2_DV_BT_CEA_1920X1080I50 },
+	/* HD - 1920x1080i59.94 */
+	/* HD - 1920x1080i60 */
+	{ 1920, 540, 30, V4L2_DV_BT_CEA_1920X1080I60 },
+
+	/* HD - 2048x1080i47.95 */
+	/* HD - 2048x1080i48 */
+	{ 2048, 540, 24, XLNX_V4L2_DV_BT_2048X1080I48 },
+	/* HD - 2048x1080i50 */
+	{ 2048, 540, 25, XLNX_V4L2_DV_BT_2048X1080I50 },
+	/* HD - 2048x1080i59.94 */
+	/* HD - 2048x1080i60 */
+	{ 2048, 540, 30, XLNX_V4L2_DV_BT_2048X1080I60 },
+	/* 3G - 1920x1080p47.95 */
+	/* 3G - 1920x1080p48 */
+	{ 1920, 1080, 48, XLNX_V4L2_DV_BT_1920X1080P48 },
+
+	/* 3G - 1920x1080p50 148.5 */
+	{ 1920, 1080, 50, V4L2_DV_BT_CEA_1920X1080P50 },
+	/* 3G - 1920x1080p59.94 148.5/1.001 */
+	/* 3G - 1920x1080p60 148.5 */
+	{ 1920, 1080, 60, V4L2_DV_BT_CEA_1920X1080P60 },
+
+	/* 3G - 2048x1080p47.95 */
+	/* 3G - 2048x1080p48 */
+	{ 2048, 1080, 48, XLNX_V4L2_DV_BT_2048X1080P48 },
+	/* 3G - 2048x1080p50 */
+	{ 2048, 1080, 50, XLNX_V4L2_DV_BT_2048X1080P50 },
+	/* 3G - 2048x1080p59.94 */
+	/* 3G - 2048x1080p60 */
+	{ 2048, 1080, 60, XLNX_V4L2_DV_BT_2048X1080P60 },
+
+	/* 6G - 3840X2160p23.98 */
+	/* 6G - 3840X2160p24 */
+	{ 3840, 2160, 24, V4L2_DV_BT_CEA_3840X2160P24 },
+	/* 6G - 3840X2160p25 */
+	{ 3840, 2160, 25, V4L2_DV_BT_CEA_3840X2160P25 },
+	/* 6G - 3840X2160p29.97 */
+	/* 6G - 3840X2160p30 */
+	{ 3840, 2160, 30, V4L2_DV_BT_CEA_3840X2160P30 },
+	/* 6G - 4096X2160p23.98 */
+	/* 6G - 4096X2160p24 */
+	{ 4096, 2160, 24, V4L2_DV_BT_CEA_4096X2160P24 },
+	/* 6G - 4096X2160p25 */
+	{ 4096, 2160, 25, V4L2_DV_BT_CEA_4096X2160P25 },
+	/* 6G - 4096X2160p29.97 */
+	/* 6G - 4096X2160p30 */
+	{ 4096, 2160, 30, V4L2_DV_BT_CEA_4096X2160P30 },
+	/* 12G - 3840X2160p47.95 */
+	/* 12G - 3840X2160p48 */
+	{ 3840, 2160, 48, XLNX_V4L2_DV_BT_3840X2160P48 },
+
+	/* 12G - 3840X2160p50 */
+	{ 3840, 2160, 50, V4L2_DV_BT_CEA_3840X2160P50 },
+	/* 12G - 3840X2160p59.94 */
+	/* 12G - 3840X2160p60 */
+	{ 3840, 2160, 60, V4L2_DV_BT_CEA_3840X2160P60 },
+
+	/* 12G - 4096X2160p47.95 */
+	/* 12G - 4096X2160p48 */
+	{ 3840, 2160, 48, XLNX_V4L2_DV_BT_4096X2160P48 },
+
+	/* 12G - 4096X2160p50 */
+	{ 4096, 2160, 50, V4L2_DV_BT_CEA_4096X2160P50 },
+	/* 12G - 4096X2160p59.94 */
+	/* 12G - 4096X2160p60 */
+	{ 4096, 2160, 60, V4L2_DV_BT_CEA_4096X2160P60 },
+
+	/* 6G/12G HFR */
+	{ 1920, 1080, 96, XLNX_V4L2_DV_BT_1920X1080P96 },
+	{ 1920, 1080, 100, XLNX_V4L2_DV_BT_1920X1080P100 },
+	{ 1920, 1080, 120, XLNX_V4L2_DV_BT_1920X1080P120 },
+	{ 2048, 1080, 96, XLNX_V4L2_DV_BT_2048X1080P96 },
+	{ 2048, 1080, 100, XLNX_V4L2_DV_BT_2048X1080P100 },
+	{ 2048, 1080, 120, XLNX_V4L2_DV_BT_2048X1080P120 },
+};
+
+static inline struct xsdirxss_state *
+to_xsdirxssstate(struct v4l2_subdev *subdev)
+{
+	return container_of(subdev, struct xsdirxss_state, subdev);
+}
+
+/*
+ * Register related operations
+ */
+static inline u32 xsdirxss_read(struct xsdirxss_core *xsdirxss, u32 addr)
+{
+	return ioread32(xsdirxss->iomem + addr);
+}
+
+static inline void xsdirxss_write(struct xsdirxss_core *xsdirxss, u32 addr,
+				  u32 value)
+{
+	iowrite32(value, xsdirxss->iomem + addr);
+}
+
+static inline void xsdirxss_clr(struct xsdirxss_core *xsdirxss, u32 addr,
+				u32 clr)
+{
+	xsdirxss_write(xsdirxss, addr, xsdirxss_read(xsdirxss, addr) & ~clr);
+}
+
+static inline void xsdirxss_set(struct xsdirxss_core *xsdirxss, u32 addr,
+				u32 set)
+{
+	xsdirxss_write(xsdirxss, addr, xsdirxss_read(xsdirxss, addr) | set);
+}
+
+static inline void xsdirx_core_disable(struct xsdirxss_core *core)
+{
+	xsdirxss_clr(core, XSDIRX_RST_CTRL_REG, XSDIRX_RST_CTRL_SS_EN_MASK);
+}
+
+static inline void xsdirx_core_enable(struct xsdirxss_core *core)
+{
+	xsdirxss_set(core, XSDIRX_RST_CTRL_REG, XSDIRX_RST_CTRL_SS_EN_MASK);
+}
+
+static void xsdirxss_gt_reset(struct xsdirxss_core *core)
+{
+	/* reset qpll0 */
+	gpiod_set_value(core->rst_gt_gpio, 0x1);
+	gpiod_set_value(core->rst_gt_gpio, 0x0);
+	/* reset picxo core */
+	gpiod_set_value(core->rst_picxo_gpio, 0x1);
+	gpiod_set_value(core->rst_picxo_gpio, 0x0);
+}
+
+static int xsdirx_set_modedetect(struct xsdirxss_core *core, u16 mask)
+{
+	u32 i, val;
+
+	mask &= XSDIRX_DETECT_ALL_MODES;
+	if (!mask) {
+		dev_err(core->dev, "Invalid bit mask = 0x%08x\n", mask);
+		return -EINVAL;
+	}
+
+	dev_dbg(core->dev, "mask = 0x%x\n", mask);
+
+	val = xsdirxss_read(core, XSDIRX_MDL_CTRL_REG);
+	val &= ~XSDIRX_MDL_CTRL_MODE_DET_EN_MASK;
+	val &= ~XSDIRX_MDL_CTRL_MODE_AUTO_DET_MASK;
+	val &= ~XSDIRX_MDL_CTRL_FORCED_MODE_MASK;
+
+	if (hweight16(mask) > 1) {
+		/* Multi mode detection as more than 1 bit set in mask */
+		dev_dbg(core->dev, "Detect multiple modes\n");
+		for (i = 0; i < XSDIRX_MODE_NUM_SUPPORTED; i++) {
+			switch (mask & (1 << i)) {
+			case BIT(XSDIRX_MODE_SD_OFFSET):
+				val |= XSDIRX_MDL_CTRL_MODE_SD_EN_MASK;
+				break;
+			case BIT(XSDIRX_MODE_HD_OFFSET):
+				val |= XSDIRX_MDL_CTRL_MODE_HD_EN_MASK;
+				break;
+			case BIT(XSDIRX_MODE_3G_OFFSET):
+				val |= XSDIRX_MDL_CTRL_MODE_3G_EN_MASK;
+				break;
+			case BIT(XSDIRX_MODE_6G_OFFSET):
+				val |= XSDIRX_MDL_CTRL_MODE_6G_EN_MASK;
+				break;
+			case BIT(XSDIRX_MODE_12GI_OFFSET):
+				val |= XSDIRX_MDL_CTRL_MODE_12GI_EN_MASK;
+				break;
+			case BIT(XSDIRX_MODE_12GF_OFFSET):
+				val |= XSDIRX_MDL_CTRL_MODE_12GF_EN_MASK;
+				break;
+			}
+		}
+		val |= XSDIRX_MDL_CTRL_MODE_DET_EN_MASK;
+	} else {
+		/* Fixed Mode */
+		u32 forced_mode_mask;
+
+		dev_dbg(core->dev, "Detect fixed mode\n");
+
+		/* Find offset of first bit set */
+		switch (__ffs(mask)) {
+		case XSDIRX_MODE_SD_OFFSET:
+			forced_mode_mask = XSDIRX_MODE_SD_MASK;
+			break;
+		case XSDIRX_MODE_HD_OFFSET:
+			forced_mode_mask = XSDIRX_MODE_HD_MASK;
+			break;
+		case XSDIRX_MODE_3G_OFFSET:
+			forced_mode_mask = XSDIRX_MODE_3G_MASK;
+			break;
+		case XSDIRX_MODE_6G_OFFSET:
+			forced_mode_mask = XSDIRX_MODE_6G_MASK;
+			break;
+		case XSDIRX_MODE_12GI_OFFSET:
+			forced_mode_mask = XSDIRX_MODE_12GI_MASK;
+			break;
+		case XSDIRX_MODE_12GF_OFFSET:
+			forced_mode_mask = XSDIRX_MODE_12GF_MASK;
+			break;
+		default:
+			forced_mode_mask = 0;
+		}
+		dev_dbg(core->dev, "Forced Mode Mask : 0x%x\n",
+			forced_mode_mask);
+		val |= forced_mode_mask << XSDIRX_MDL_CTRL_FORCED_MODE_OFFSET;
+	}
+
+	dev_dbg(core->dev, "Modes to be detected : sdi ctrl reg = 0x%08x\n",
+		val);
+	xsdirxss_write(core, XSDIRX_MDL_CTRL_REG, val);
+
+	return 0;
+}
+
+static void xsdirx_framer(struct xsdirxss_core *core, bool flag)
+{
+	if (flag)
+		xsdirxss_set(core, XSDIRX_MDL_CTRL_REG,
+			     XSDIRX_MDL_CTRL_FRM_EN_MASK);
+	else
+		xsdirxss_clr(core, XSDIRX_MDL_CTRL_REG,
+			     XSDIRX_MDL_CTRL_FRM_EN_MASK);
+}
+
+static void xsdirx_setedherrcnttrigger(struct xsdirxss_core *core, u32 enable)
+{
+	u32 val;
+
+	val = enable & XSDIRX_EDH_ALLERR_MASK;
+
+	xsdirxss_write(core, XSDIRX_EDH_ERRCNT_EN_REG, val);
+}
+
+static inline void xsdirx_setvidlockwindow(struct xsdirxss_core *core, u32 val)
+{
+	/*
+	 * The video lock window is the amount of time for which the
+	 * the mode and transport stream should be locked to get the
+	 * video lock interrupt.
+	 */
+	xsdirxss_write(core, XSDIRX_VID_LOCK_WINDOW_REG, val);
+}
+
+static inline void xsdirx_disableintr(struct xsdirxss_core *core, u32 mask)
+{
+	xsdirxss_clr(core, XSDIRX_IER_REG, mask);
+}
+
+static inline void xsdirx_enableintr(struct xsdirxss_core *core, u32 mask)
+{
+	xsdirxss_set(core, XSDIRX_IER_REG, mask);
+}
+
+static void xsdirx_globalintr(struct xsdirxss_core *core, bool flag)
+{
+	if (flag)
+		xsdirxss_set(core, XSDIRX_GLBL_IER_REG,
+			     XSDIRX_GLBL_INTR_EN_MASK);
+	else
+		xsdirxss_clr(core, XSDIRX_GLBL_IER_REG,
+			     XSDIRX_GLBL_INTR_EN_MASK);
+}
+
+static inline void xsdirx_clearintr(struct xsdirxss_core *core, u32 mask)
+{
+	xsdirxss_set(core, XSDIRX_ISR_REG, mask);
+}
+
+static void xsdirx_vid_bridge_control(struct xsdirxss_core *core,
+				      bool enable)
+{
+	struct xsdirxss_state *state =
+		container_of(core, struct xsdirxss_state, core);
+	u32 mask = XSDIRX_RST_CTRL_SDIRX_BRIDGE_ENB_MASK;
+
+	if (state->format.code == MEDIA_BUS_FMT_VUY10_1X30 ||
+	    state->format.code == MEDIA_BUS_FMT_RBG101010_1X30 ||
+	    state->format.code == MEDIA_BUS_FMT_RBG121212_1X36 ||
+	    state->format.code == MEDIA_BUS_FMT_VUY12_1X36)
+		mask |= (XSDIRX_RST_CTRL_BRIDGE_CH_FMT_YUV444 <<
+			 XSDIRX_RST_CTRL_BRIDGE_CH_FMT_OFFSET);
+
+	if (enable)
+		xsdirxss_set(core, XSDIRX_RST_CTRL_REG, mask);
+	else
+		xsdirxss_clr(core, XSDIRX_RST_CTRL_REG, mask);
+}
+
+static void xsdirx_axis4_bridge_control(struct xsdirxss_core *core,
+					bool enable)
+{
+	if (enable)
+		xsdirxss_set(core, XSDIRX_RST_CTRL_REG,
+			     XSDIRX_RST_CTRL_VIDIN_AXI4S_MOD_ENB_MASK);
+	else
+		xsdirxss_clr(core, XSDIRX_RST_CTRL_REG,
+			     XSDIRX_RST_CTRL_VIDIN_AXI4S_MOD_ENB_MASK);
+}
+
+static void xsdirx_streamflow_control(struct xsdirxss_core *core, bool enable)
+{
+	/* The sdi to native bridge is followed by native to axis4 bridge */
+	if (enable) {
+		xsdirx_axis4_bridge_control(core, enable);
+		xsdirx_vid_bridge_control(core, enable);
+	} else {
+		xsdirx_vid_bridge_control(core, enable);
+		xsdirx_axis4_bridge_control(core, enable);
+	}
+}
+
+static void xsdirxss_get_framerate(struct v4l2_fract *frame_interval,
+				   u32 framerate)
+{
+	switch (framerate) {
+	case XSDIRX_TS_DET_STAT_RATE_23_98HZ:
+		frame_interval->numerator = 1001;
+		frame_interval->denominator = 24000;
+		break;
+	case XSDIRX_TS_DET_STAT_RATE_24HZ:
+		frame_interval->numerator = 1000;
+		frame_interval->denominator = 24000;
+		break;
+	case XSDIRX_TS_DET_STAT_RATE_25HZ:
+		frame_interval->numerator = 1000;
+		frame_interval->denominator = 25000;
+		break;
+	case XSDIRX_TS_DET_STAT_RATE_29_97HZ:
+		frame_interval->numerator = 1001;
+		frame_interval->denominator = 30000;
+		break;
+	case XSDIRX_TS_DET_STAT_RATE_30HZ:
+		frame_interval->numerator = 1000;
+		frame_interval->denominator = 30000;
+		break;
+	case XSDIRX_TS_DET_STAT_RATE_47_95HZ:
+		frame_interval->numerator = 1001;
+		frame_interval->denominator = 48000;
+		break;
+	case XSDIRX_TS_DET_STAT_RATE_48HZ:
+		frame_interval->numerator = 1000;
+		frame_interval->denominator = 48000;
+		break;
+	case XSDIRX_TS_DET_STAT_RATE_50HZ:
+		frame_interval->numerator = 1000;
+		frame_interval->denominator = 50000;
+		break;
+	case XSDIRX_TS_DET_STAT_RATE_59_94HZ:
+		frame_interval->numerator = 1001;
+		frame_interval->denominator = 60000;
+		break;
+	case XSDIRX_TS_DET_STAT_RATE_60HZ:
+		frame_interval->numerator = 1000;
+		frame_interval->denominator = 60000;
+		break;
+	case XSDIRX_TS_DET_STAT_RATE_95_90HZ:
+		frame_interval->numerator = 1001;
+		frame_interval->denominator = 96000;
+		break;
+	case XSDIRX_TS_DET_STAT_RATE_96HZ:
+		frame_interval->numerator = 1000;
+		frame_interval->denominator = 96000;
+		break;
+	case XSDIRX_TS_DET_STAT_RATE_100HZ:
+		frame_interval->numerator = 1000;
+		frame_interval->denominator = 100000;
+		break;
+	case XSDIRX_TS_DET_STAT_RATE_119_88HZ:
+		frame_interval->numerator = 1001;
+		frame_interval->denominator = 120000;
+		break;
+	case XSDIRX_TS_DET_STAT_RATE_120HZ:
+		frame_interval->numerator = 1000;
+		frame_interval->denominator = 120000;
+		break;
+	default:
+		frame_interval->numerator = 1;
+		frame_interval->denominator = 1;
+	}
+}
+
+static void xsdirxss_set_gtclk(struct xsdirxss_state *state)
+{
+	struct clk *gtclk;
+	unsigned long clkrate;
+	int ret, is_frac;
+	struct xsdirxss_core *core = &state->core;
+	u32 mode;
+
+	mode = xsdirxss_read(core, XSDIRX_MODE_DET_STAT_REG);
+	mode &= XSDIRX_MODE_DET_STAT_RX_MODE_MASK;
+
+	xsdirx_core_disable(core);
+	xsdirx_globalintr(core, false);
+	xsdirx_disableintr(core, XSDIRX_INTR_ALL_MASK);
+
+	/* get sdi_rx_clk */
+	gtclk = core->clks[1].clk;
+	is_frac = state->frame_interval.numerator == 1001 ? 1 : 0;
+
+	/*
+	 * PLL ref clock is 148.5MHz for integer frame rates
+	 * and 148.35MHz for fractional frame rates.
+	 * For SD mode its always 148.5MHz for integer & fractional.
+	 * Please refer to Table 5-2 in PG290
+	 * https://www.xilinx.com/support/documentation/ip_documentation/v_smpte_uhdsdi_rx_ss/v2_0/pg290-v-smpte-uhdsdi-rx-ss.pdf
+	 */
+	if (!is_frac || mode == XSDIRX_MODE_SD_MASK)
+		clkrate = CLK_INT;
+	else
+		clkrate = (CLK_INT * 1000) / 1001;
+
+	ret = clk_set_rate(gtclk, clkrate);
+	if (ret)
+		dev_err(core->dev, "failed to set clk rate = %d\n", ret);
+
+	/* reset qpll0 and picxo core */
+	xsdirxss_gt_reset(core);
+
+	clkrate = clk_get_rate(gtclk);
+
+	dev_dbg(core->dev, "clkrate = %lu is_frac = %d\n",
+		clkrate, is_frac);
+
+	xsdirx_framer(core, state->framer_enable);
+	xsdirx_setedherrcnttrigger(core, state->edhmask);
+	xsdirx_setvidlockwindow(core, state->vidlockwin);
+	xsdirx_set_modedetect(core, state->searchmask);
+	xsdirx_enableintr(core, XSDIRX_INTR_ALL_MASK);
+	xsdirx_globalintr(core, true);
+	xsdirx_core_enable(core);
+}
+
+/**
+ * xsdirx_get_stream_properties - Get SDI Rx stream properties
+ * @state: pointer to driver state
+ *
+ * This function decodes the stream's ST352 payload (if available) to get
+ * stream properties like width, height, picture type (interlaced/progressive),
+ * etc.
+ *
+ * Return: 0 for success else errors
+ */
+static int xsdirx_get_stream_properties(struct xsdirxss_state *state)
+{
+	struct xsdirxss_core *core = &state->core;
+	u32 mode, payload = 0, val, family, valid, tscan;
+	u8 byte1 = 0, active_luma = 0, pic_type = 0, framerate = 0;
+	u8 sampling = XST352_BYTE3_COLOR_FORMAT_422;
+	struct v4l2_mbus_framefmt *format = &state->format;
+	u32 bpc = XST352_BYTE4_BIT_DEPTH_10;
+
+	mode = xsdirxss_read(core, XSDIRX_MODE_DET_STAT_REG);
+	mode &= XSDIRX_MODE_DET_STAT_RX_MODE_MASK;
+
+	valid = xsdirxss_read(core, XSDIRX_ST352_VALID_REG);
+
+	if (mode >= XSDIRX_MODE_3G_MASK && !valid) {
+		dev_err_ratelimited(core->dev, "No valid ST352 payload present even for 3G mode and above\n");
+		return -EINVAL;
+	}
+
+	val = xsdirxss_read(core, XSDIRX_TS_DET_STAT_REG);
+	if (valid & XSDIRX_ST352_VALID_DS1_MASK) {
+		payload = xsdirxss_read(core, XSDIRX_ST352_DS1_REG);
+		byte1 = (payload >> XST352_PAYLOAD_BYTE1_SHIFT) &
+				XST352_PAYLOAD_BYTE_MASK;
+		active_luma = (payload & XST352_BYTE3_ACT_LUMA_COUNT_MASK) >>
+				XST352_BYTE3_ACT_LUMA_COUNT_OFFSET;
+		pic_type = (payload & XST352_BYTE2_PIC_TYPE_MASK) >>
+				XST352_BYTE2_PIC_TYPE_OFFSET;
+		framerate = (payload >> XST352_BYTE2_FPS_SHIFT) &
+				XST352_BYTE2_FPS_MASK;
+		tscan = (payload & XST352_BYTE2_TS_TYPE_MASK) >>
+				XST352_BYTE2_TS_TYPE_OFFSET;
+		sampling = (payload & XST352_BYTE3_COLOR_FORMAT_MASK) >>
+			   XST352_BYTE3_COLOR_FORMAT_OFFSET;
+		bpc = (payload & XST352_BYTE4_BIT_DEPTH_MASK) >>
+			XST352_BYTE4_BIT_DEPTH_OFFSET;
+	} else {
+		dev_dbg(core->dev, "No ST352 payload available : Mode = %d\n",
+			mode);
+		framerate = (val & XSDIRX_TS_DET_STAT_RATE_MASK) >>
+				XSDIRX_TS_DET_STAT_RATE_OFFSET;
+		tscan = (val & XSDIRX_TS_DET_STAT_SCAN_MASK) >>
+				XSDIRX_TS_DET_STAT_SCAN_OFFSET;
+	}
+
+	if ((bpc == XST352_BYTE4_BIT_DEPTH_10 && core->bpc != 10) ||
+	    (bpc == XST352_BYTE4_BIT_DEPTH_12 && core->bpc != 12)) {
+		dev_dbg(core->dev, "Bit depth not supported. bpc = %d core->bpc = %d\n",
+			bpc, core->bpc);
+		return -EINVAL;
+	}
+
+	family = (val & XSDIRX_TS_DET_STAT_FAMILY_MASK) >>
+			XSDIRX_TS_DET_STAT_FAMILY_OFFSET;
+	state->ts_is_interlaced = tscan ? false : true;
+
+	dev_dbg(core->dev, "ts_is_interlaced = %d, family = %d\n",
+		state->ts_is_interlaced, family);
+
+	switch (mode) {
+	case XSDIRX_MODE_HD_MASK:
+		if (!valid) {
+			/* No payload obtained */
+			dev_dbg(core->dev, "frame rate : %d, tscan = %d\n",
+				framerate, tscan);
+			/*
+			 * NOTE : A progressive segmented frame pSF will be
+			 * reported incorrectly as Interlaced as we rely on IP's
+			 * transport scan locked bit.
+			 */
+			dev_warn(core->dev, "pSF will be incorrectly reported as Interlaced\n");
+
+			switch (framerate) {
+			case XSDIRX_TS_DET_STAT_RATE_23_98HZ:
+			case XSDIRX_TS_DET_STAT_RATE_24HZ:
+			case XSDIRX_TS_DET_STAT_RATE_25HZ:
+			case XSDIRX_TS_DET_STAT_RATE_29_97HZ:
+			case XSDIRX_TS_DET_STAT_RATE_30HZ:
+				if (family == XSDIRX_SMPTE_ST_296) {
+					format->width = 1280;
+					format->height = 720;
+					format->field = V4L2_FIELD_NONE;
+				} else if (family == XSDIRX_SMPTE_ST_2048_2) {
+					format->width = 2048;
+					format->height = 1080;
+					if (tscan)
+						format->field = V4L2_FIELD_NONE;
+					else
+						format->field =
+							V4L2_FIELD_ALTERNATE;
+				} else {
+					format->width = 1920;
+					format->height = 1080;
+					if (tscan)
+						format->field = V4L2_FIELD_NONE;
+					else
+						format->field =
+							V4L2_FIELD_ALTERNATE;
+				}
+				break;
+			case XSDIRX_TS_DET_STAT_RATE_50HZ:
+			case XSDIRX_TS_DET_STAT_RATE_59_94HZ:
+			case XSDIRX_TS_DET_STAT_RATE_60HZ:
+				if (family == XSDIRX_SMPTE_ST_274) {
+					format->width = 1920;
+					format->height = 1080;
+				} else {
+					format->width = 1280;
+					format->height = 720;
+				}
+				format->field = V4L2_FIELD_NONE;
+				break;
+			default:
+				format->width = 1920;
+				format->height = 1080;
+				format->field = V4L2_FIELD_NONE;
+			}
+		} else {
+			dev_dbg(core->dev, "Got the payload\n");
+			switch (byte1) {
+			case XST352_BYTE1_ST292_1x720L_1_5G:
+				/* SMPTE ST 292-1 for 720 line payloads */
+				format->width = 1280;
+				format->height = 720;
+				break;
+			case XST352_BYTE1_ST292_1x1080L_1_5G:
+				/* SMPTE ST 292-1 for 1080 line payloads */
+				format->height = 1080;
+				if (active_luma)
+					format->width = 2048;
+				else
+					format->width = 1920;
+				break;
+			default:
+				dev_dbg(core->dev, "Unknown HD Mode SMPTE standard\n");
+				return -EINVAL;
+			}
+		}
+		break;
+	case XSDIRX_MODE_SD_MASK:
+		format->field = V4L2_FIELD_ALTERNATE;
+
+		switch (family) {
+		case XSDIRX_NTSC:
+			format->width = 720;
+			format->height = 486;
+			break;
+		case XSDIRX_PAL:
+			format->width = 720;
+			format->height = 576;
+			break;
+		default:
+			dev_dbg(core->dev, "Unknown SD Mode SMPTE standard\n");
+			return -EINVAL;
+		}
+		break;
+	case XSDIRX_MODE_3G_MASK:
+		switch (byte1) {
+		case XST352_BYTE1_ST425_2008_750L_3GB:
+			/* Sec 4.1.6.1 SMPTE 425-2008 */
+		case XST352_BYTE1_ST372_2x720L_3GB:
+			/* Table 13 SMPTE 425-2008 */
+			format->width = 1280;
+			format->height = 720;
+			break;
+		case XST352_BYTE1_ST425_2008_1125L_3GA:
+			/* ST352 Table SMPTE 425-1 */
+		case XST352_BYTE1_ST372_DL_3GB:
+			/* Table 13 SMPTE 425-2008 */
+		case XST352_BYTE1_ST372_2x1080L_3GB:
+			/* Table 13 SMPTE 425-2008 */
+			format->height = 1080;
+			if (active_luma)
+				format->width = 2048;
+			else
+				format->width = 1920;
+			break;
+		default:
+			dev_dbg(core->dev, "Unknown 3G Mode SMPTE standard\n");
+			return -EINVAL;
+		}
+		break;
+	case XSDIRX_MODE_6G_MASK:
+		switch (byte1) {
+		case XST352_BYTE1_ST2081_10_DL_2160L_6G:
+			/* Dual link 6G */
+		case XST352_BYTE1_ST2081_10_2160L_6G:
+			/* Table 3 SMPTE ST 2081-10 */
+			format->height = 2160;
+			if (active_luma)
+				format->width = 4096;
+			else
+				format->width = 3840;
+			break;
+		case XST352_BYTE1_ST2081_10_2_1080L_6G:
+			format->height = 1080;
+			if (active_luma)
+				format->width = 2048;
+			else
+				format->width = 1920;
+			break;
+		default:
+			dev_dbg(core->dev, "Unknown 6G Mode SMPTE standard\n");
+			return -EINVAL;
+		}
+		break;
+	case XSDIRX_MODE_12GI_MASK:
+	case XSDIRX_MODE_12GF_MASK:
+		switch (byte1) {
+		case XST352_BYTE1_ST2082_10_2160L_12G:
+			/* Section 4.3.1 SMPTE ST 2082-10 */
+			format->height = 2160;
+			if (active_luma)
+				format->width = 4096;
+			else
+				format->width = 3840;
+			break;
+		default:
+			dev_dbg(core->dev, "Unknown 12G Mode SMPTE standard\n");
+			return -EINVAL;
+		}
+		break;
+	default:
+		dev_err(core->dev, "Invalid Mode\n");
+		return -EINVAL;
+	}
+
+	if (valid) {
+		if (pic_type)
+			format->field = V4L2_FIELD_NONE;
+		else
+			format->field = V4L2_FIELD_ALTERNATE;
+
+		if (format->height == 1080 && pic_type && !tscan)
+			format->field = V4L2_FIELD_ALTERNATE;
+
+		/*
+		 * In 3GB DL pSF mode the video is similar to interlaced.
+		 * So though it is a progressive video, its transport is
+		 * interlaced and is sent as two width x (height/2) buffers.
+		 */
+		if (byte1 == XST352_BYTE1_ST372_DL_3GB) {
+			if (state->ts_is_interlaced)
+				format->field = V4L2_FIELD_ALTERNATE;
+			else
+				format->field = V4L2_FIELD_NONE;
+		}
+	}
+
+	if (format->field == V4L2_FIELD_ALTERNATE)
+		format->height = format->height / 2;
+
+	switch (sampling) {
+	case XST352_BYTE3_COLOR_FORMAT_420:
+		if (core->bpc == 10)
+			format->code = MEDIA_BUS_FMT_VYYUYY10_4X20;
+		else
+			format->code = MEDIA_BUS_FMT_UYYVYY12_4X24;
+		break;
+	case XST352_BYTE3_COLOR_FORMAT_422:
+		if (core->bpc == 10)
+			format->code = MEDIA_BUS_FMT_UYVY10_1X20;
+		else
+			format->code = MEDIA_BUS_FMT_UYVY12_1X24;
+		break;
+	case XST352_BYTE3_COLOR_FORMAT_YUV444:
+		if (core->bpc == 10)
+			format->code = MEDIA_BUS_FMT_VUY10_1X30;
+		else
+			format->code = MEDIA_BUS_FMT_VUY12_1X36;
+		break;
+	case XST352_BYTE3_COLOR_FORMAT_GBR:
+		if (core->bpc == 10)
+			format->code = MEDIA_BUS_FMT_RBG101010_1X30;
+		else
+			format->code = MEDIA_BUS_FMT_RBG121212_1X36;
+		break;
+	default:
+		dev_err(core->dev, "Unsupported color format : %d\n", sampling);
+		return -EINVAL;
+	}
+
+	xsdirxss_get_framerate(&state->frame_interval, framerate);
+
+	memset(&state->static_hdr, 0, sizeof(state->static_hdr));
+
+	state->static_hdr.eotf = V4L2_EOTF_TRADITIONAL_GAMMA_SDR;
+	format->colorspace = V4L2_COLORSPACE_SMPTE170M;
+	format->xfer_func = V4L2_XFER_FUNC_709;
+	format->ycbcr_enc = V4L2_YCBCR_ENC_601;
+	format->quantization = V4L2_QUANTIZATION_LIM_RANGE;
+
+	if (mode != XSDIRX_MODE_SD_MASK) {
+		u8 eotf = (payload & XST352_BYTE2_EOTF_MASK) >>
+			XST352_BYTE2_EOTF_OFFSET;
+
+		u8 colorimetry = (payload & XST352_BYTE2_COLORIMETRY_MASK) >>
+			XST352_BYTE2_COLORIMETRY_OFFSET;
+
+		/*
+		 * Bit 7 and 4 of byte 3 form the colorimetry field for HD.
+		 * Checkout SMPTE 292-1:2018 Sec 9.5 for details
+		 */
+		if (mode == XSDIRX_MODE_HD_MASK ||
+		    byte1 == XST352_BYTE1_ST372_DL_3GB) {
+			/* For case when there might be no payload */
+			colorimetry = XST352_BYTE2_COLORIMETRY_BT709;
+
+			if (valid & XSDIRX_ST352_VALID_DS1_MASK) {
+				colorimetry = (FIELD_GET(BIT(23), payload) << 1) |
+					FIELD_GET(BIT(20), payload);
+			}
+		}
+
+		/* Get the EOTF function */
+		switch (eotf) {
+		case XST352_BYTE2_EOTF_SDRTV:
+			state->static_hdr.eotf =
+				V4L2_EOTF_TRADITIONAL_GAMMA_SDR;
+			break;
+		case XST352_BYTE2_EOTF_SMPTE2084:
+			state->static_hdr.eotf = V4L2_EOTF_SMPTE_ST2084;
+			format->xfer_func = V4L2_XFER_FUNC_SMPTE2084;
+			break;
+		case XST352_BYTE2_EOTF_HLG:
+			state->static_hdr.eotf = V4L2_EOTF_BT_2100_HLG;
+			format->xfer_func = V4L2_XFER_FUNC_HLG;
+			break;
+		}
+
+		/* Get the colorimetry data */
+		switch (colorimetry) {
+		case XST352_BYTE2_COLORIMETRY_BT709:
+			format->colorspace = V4L2_COLORSPACE_REC709;
+			format->ycbcr_enc = V4L2_YCBCR_ENC_709;
+			break;
+		case XST352_BYTE2_COLORIMETRY_UHDTV:
+			format->colorspace = V4L2_COLORSPACE_BT2020;
+			format->ycbcr_enc = V4L2_YCBCR_ENC_BT2020;
+			break;
+		default:
+			/*
+			 * Modes which will have VANC and Unknown colorimetery
+			 * are currently not supported
+			 */
+			format->colorspace = V4L2_COLORSPACE_DEFAULT;
+			format->xfer_func = V4L2_XFER_FUNC_DEFAULT;
+			break;
+		}
+	}
+
+	/* Refer to Table 3 ST 2082-10:2018 */
+	if (mode == XSDIRX_MODE_12GI_OFFSET ||
+	    mode == XSDIRX_MODE_12GF_OFFSET) {
+		switch (sampling) {
+		case XST352_BYTE3_COLOR_FORMAT_420:
+		case XST352_BYTE3_COLOR_FORMAT_422:
+		case XST352_BYTE3_COLOR_FORMAT_YUV444:
+			if (payload & XST352_BYTE4_LUM_COL_DIFF_MASK)
+				format->ycbcr_enc =
+					V4L2_YCBCR_ENC_BT2020_CONST_LUM;
+			else
+				format->ycbcr_enc =
+					V4L2_YCBCR_ENC_BT2020;
+		}
+	}
+
+	/* Set quantization range */
+	if (sampling == XST352_BYTE3_COLOR_FORMAT_GBR &&
+	    format->colorspace != V4L2_COLORSPACE_BT2020)
+		format->quantization = V4L2_QUANTIZATION_FULL_RANGE;
+
+	/*
+	 * Save the payload to be used in vsync interrupt to check for
+	 * change in payload without video lock/unlock sequence
+	 */
+	if (valid & XSDIRX_ST352_VALID_DS1_MASK)
+		state->prev_payload = payload;
+
+	dev_dbg(core->dev, "Stream width = %d height = %d Field = %d payload = 0x%08x ts = 0x%08x\n",
+		format->width, format->height, format->field, payload, val);
+	dev_dbg(core->dev, "frame rate numerator = %d denominator = %d\n",
+		state->frame_interval.numerator,
+		state->frame_interval.denominator);
+	dev_dbg(core->dev, "Stream code = 0x%x\n", format->code);
+	return 0;
+}
+
+/**
+ * xsdirxss_irq_handler - Interrupt handler for SDI Rx
+ * @irq: IRQ number
+ * @dev_id: Pointer to device state
+ *
+ * The SDI Rx interrupts are cleared by writing 1 to corresponding bit.
+ *
+ * Return: IRQ_HANDLED after handling interrupts
+ */
+static irqreturn_t xsdirxss_irq_handler(int irq, void *dev_id)
+{
+	struct xsdirxss_state *state = (struct xsdirxss_state *)dev_id;
+	struct xsdirxss_core *core = &state->core;
+	u32 status;
+
+	status = xsdirxss_read(core, XSDIRX_ISR_REG);
+	dev_dbg(core->dev, "interrupt status = 0x%08x\n", status);
+
+	if (!status)
+		return IRQ_NONE;
+
+	xsdirxss_write(core, XSDIRX_ISR_REG, status);
+
+	if (status & XSDIRX_INTR_VIDLOCK_MASK ||
+	    status & XSDIRX_INTR_VIDUNLOCK_MASK) {
+		u32 val1, val2;
+		bool gen_event = true;
+
+		dev_dbg(core->dev, "video lock/unlock interrupt\n");
+
+		xsdirx_streamflow_control(core, false);
+		state->streaming = false;
+
+		val1 = xsdirxss_read(core, XSDIRX_MODE_DET_STAT_REG);
+		val2 = xsdirxss_read(core, XSDIRX_TS_DET_STAT_REG);
+
+		if ((val1 & XSDIRX_MODE_DET_STAT_MODE_LOCK_MASK) &&
+		    (val2 & XSDIRX_TS_DET_STAT_LOCKED_MASK)) {
+			u32 mask = XSDIRX_RST_CTRL_RST_CRC_ERRCNT_MASK |
+				   XSDIRX_RST_CTRL_RST_EDH_ERRCNT_MASK;
+
+			dev_dbg(core->dev, "video lock interrupt\n");
+
+			xsdirxss_set(core, XSDIRX_RST_CTRL_REG, mask);
+			xsdirxss_clr(core, XSDIRX_RST_CTRL_REG, mask);
+
+			val1 = xsdirxss_read(core, XSDIRX_ST352_VALID_REG);
+			val2 = xsdirxss_read(core, XSDIRX_ST352_DS1_REG);
+
+			dev_dbg(core->dev, "valid st352 mask = 0x%08x\n", val1);
+			dev_dbg(core->dev, "st352 payload = 0x%08x\n", val2);
+
+			if (state->vidlocked) {
+				gen_event = false;
+			} else if (!xsdirx_get_stream_properties(state)) {
+				state->vidlocked = true;
+				xsdirxss_set_gtclk(state);
+			} else {
+				dev_err_ratelimited(core->dev, "Unable to get stream properties!\n");
+				state->vidlocked = false;
+			}
+
+		} else {
+			dev_dbg(core->dev, "video unlock interrupt\n");
+			state->vidlocked = false;
+		}
+		if (gen_event) {
+			memset(&state->event, 0, sizeof(state->event));
+			state->event.type = V4L2_EVENT_SOURCE_CHANGE;
+			state->event.u.src_change.changes =
+				V4L2_EVENT_SRC_CH_RESOLUTION;
+			v4l2_subdev_notify_event(&state->subdev, &state->event);
+		}
+	}
+
+	if (status & XSDIRX_INTR_UNDERFLOW_MASK) {
+		dev_dbg(core->dev, "Video in to AXI4 Stream core underflow interrupt\n");
+
+		memset(&state->event, 0, sizeof(state->event));
+		state->event.type = V4L2_EVENT_XLNXSDIRX_UNDERFLOW;
+		v4l2_subdev_notify_event(&state->subdev, &state->event);
+	}
+
+	if (status & XSDIRX_INTR_OVERFLOW_MASK) {
+		dev_dbg(core->dev, "Video in to AXI4 Stream core overflow interrupt\n");
+
+		memset(&state->event, 0, sizeof(state->event));
+		state->event.type = V4L2_EVENT_XLNXSDIRX_OVERFLOW;
+		v4l2_subdev_notify_event(&state->subdev, &state->event);
+	}
+
+	if (status & XSDIRX_INTR_VSYNC_MASK) {
+		u32 valid, payload;
+		/*
+		 * If ST352 payload changed without generating video unlock/
+		 * lock sequence, then use vsync interrupt to update the
+		 * frame rate, video format and static hdr structures and
+		 * notify the userspace.
+		 */
+
+		/*
+		 * Do this while driver has state as video locked though
+		 * it is implicit from the interrupt type i.e. vsync interrupt
+		 * can occur only when video is locked.
+		 * Avoid generating source change event twice.
+		 */
+		if (status & XSDIRX_INTR_VIDLOCK_MASK)
+			return IRQ_HANDLED;
+
+		valid = xsdirxss_read(core, XSDIRX_ST352_VALID_REG);
+		if (!(valid & XSDIRX_ST352_VALID_DS1_MASK))
+			return IRQ_HANDLED;
+
+		payload = xsdirxss_read(core, XSDIRX_ST352_DS1_REG);
+		/* Return if previous and current payload are same */
+		if (payload == state->prev_payload)
+			return IRQ_HANDLED;
+
+		if (xsdirx_get_stream_properties(state))
+			return IRQ_HANDLED;
+
+		memset(&state->event, 0, sizeof(state->event));
+		state->event.type = V4L2_EVENT_SOURCE_CHANGE;
+		state->event.u.src_change.changes =
+			V4L2_EVENT_SRC_CH_RESOLUTION;
+		v4l2_subdev_notify_event(&state->subdev, &state->event);
+	}
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * xsdirxss_subscribe_event - Subscribe to video lock and unlock event
+ * @sd: V4L2 Sub device
+ * @fh: V4L2 File Handle
+ * @sub: Subcribe event structure
+ *
+ * Return: 0 on success, errors otherwise
+ */
+static int xsdirxss_subscribe_event(struct v4l2_subdev *sd,
+				    struct v4l2_fh *fh,
+				    struct v4l2_event_subscription *sub)
+{
+	int ret;
+	struct xsdirxss_state *xsdirxss = to_xsdirxssstate(sd);
+	struct xsdirxss_core *core = &xsdirxss->core;
+
+	switch (sub->type) {
+	case V4L2_EVENT_XLNXSDIRX_UNDERFLOW:
+	case V4L2_EVENT_XLNXSDIRX_OVERFLOW:
+		ret = v4l2_event_subscribe(fh, sub, XSDIRX_MAX_EVENTS, NULL);
+		break;
+	case V4L2_EVENT_SOURCE_CHANGE:
+		ret = v4l2_src_change_event_subscribe(fh, sub);
+		break;
+	default:
+		return -EINVAL;
+	}
+	dev_dbg(core->dev, "Event subscribed : 0x%08x\n", sub->type);
+	return ret;
+}
+
+/**
+ * xsdirxss_unsubscribe_event - Unsubscribe from all events registered
+ * @sd: V4L2 Sub device
+ * @fh: V4L2 file handle
+ * @sub: pointer to Event unsubscription structure
+ *
+ * Return: zero on success, else a negative error code.
+ */
+static int xsdirxss_unsubscribe_event(struct v4l2_subdev *sd,
+				      struct v4l2_fh *fh,
+				      struct v4l2_event_subscription *sub)
+{
+	struct xsdirxss_state *xsdirxss = to_xsdirxssstate(sd);
+	struct xsdirxss_core *core = &xsdirxss->core;
+
+	dev_dbg(core->dev, "Event unsubscribe : 0x%08x\n", sub->type);
+	return v4l2_event_unsubscribe(fh, sub);
+}
+
+/**
+ * xsdirxss_s_ctrl - This is used to set the Xilinx SDI Rx V4L2 controls
+ * @ctrl: V4L2 control to be set
+ *
+ * This function is used to set the V4L2 controls for the Xilinx SDI Rx
+ * Subsystem.
+ *
+ * Return: 0 on success, errors otherwise
+ */
+static int xsdirxss_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	int ret = 0;
+	struct xsdirxss_state *xsdirxss =
+		container_of(ctrl->handler,
+			     struct xsdirxss_state, ctrl_handler);
+	struct xsdirxss_core *core = &xsdirxss->core;
+
+	dev_dbg(core->dev, "set ctrl id = 0x%08x val = 0x%08x\n",
+		ctrl->id, ctrl->val);
+
+	if (xsdirxss->streaming) {
+		dev_err(core->dev, "Cannot set controls while streaming\n");
+		return -EINVAL;
+	}
+
+	xsdirx_core_disable(core);
+	switch (ctrl->id) {
+	case V4L2_CID_XILINX_SDIRX_FRAMER:
+		xsdirx_framer(core, ctrl->val);
+		xsdirxss->framer_enable = ctrl->val;
+		break;
+	case V4L2_CID_XILINX_SDIRX_VIDLOCK_WINDOW:
+		xsdirx_setvidlockwindow(core, ctrl->val);
+		xsdirxss->vidlockwin = ctrl->val;
+		break;
+	case V4L2_CID_XILINX_SDIRX_EDH_ERRCNT_ENABLE:
+		xsdirx_setedherrcnttrigger(core, ctrl->val);
+		xsdirxss->edhmask = ctrl->val;
+		break;
+	case V4L2_CID_XILINX_SDIRX_SEARCH_MODES:
+		if (ctrl->val) {
+			if (core->mode == XSDIRXSS_SDI_STD_3G) {
+				dev_dbg(core->dev, "Upto 3G supported\n");
+				ctrl->val &= ~(BIT(XSDIRX_MODE_6G_OFFSET) |
+					       BIT(XSDIRX_MODE_12GI_OFFSET) |
+					       BIT(XSDIRX_MODE_12GF_OFFSET));
+			}
+
+			if (core->mode == XSDIRXSS_SDI_STD_6G) {
+				dev_dbg(core->dev, "Upto 6G supported\n");
+				ctrl->val &= ~(BIT(XSDIRX_MODE_12GI_OFFSET) |
+					       BIT(XSDIRX_MODE_12GF_OFFSET));
+			}
+
+			ret = xsdirx_set_modedetect(core, ctrl->val);
+			if (!ret)
+				xsdirxss->searchmask = ctrl->val;
+		} else {
+			dev_err(core->dev, "Select at least one mode!\n");
+			return -EINVAL;
+		}
+		break;
+	default:
+		xsdirxss_set(core, XSDIRX_RST_CTRL_REG,
+			     XSDIRX_RST_CTRL_SS_EN_MASK);
+		return -EINVAL;
+	}
+	xsdirx_core_enable(core);
+	return ret;
+}
+
+/**
+ * xsdirxss_g_volatile_ctrl - get the Xilinx SDI Rx controls
+ * @ctrl: Pointer to V4L2 control
+ *
+ * Return: 0 on success, errors otherwise
+ */
+static int xsdirxss_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
+{
+	u32 val;
+	struct xsdirxss_state *xsdirxss =
+		container_of(ctrl->handler,
+			     struct xsdirxss_state, ctrl_handler);
+	struct xsdirxss_core *core = &xsdirxss->core;
+	struct v4l2_metadata_hdr *hdr_ptr;
+
+	switch (ctrl->id) {
+	case V4L2_CID_XILINX_SDIRX_MODE_DETECT:
+		if (!xsdirxss->vidlocked) {
+			dev_err(core->dev, "Can't get values when video not locked!\n");
+			return -EINVAL;
+		}
+		val = xsdirxss_read(core, XSDIRX_MODE_DET_STAT_REG);
+		val &= XSDIRX_MODE_DET_STAT_RX_MODE_MASK;
+
+		switch (val) {
+		case XSDIRX_MODE_SD_MASK:
+			ctrl->val = XSDIRX_MODE_SD_OFFSET;
+			break;
+		case XSDIRX_MODE_HD_MASK:
+			ctrl->val = XSDIRX_MODE_HD_OFFSET;
+			break;
+		case XSDIRX_MODE_3G_MASK:
+			ctrl->val = XSDIRX_MODE_3G_OFFSET;
+			break;
+		case XSDIRX_MODE_6G_MASK:
+			ctrl->val = XSDIRX_MODE_6G_OFFSET;
+			break;
+		case XSDIRX_MODE_12GI_MASK:
+			ctrl->val = XSDIRX_MODE_12GI_OFFSET;
+			break;
+		case XSDIRX_MODE_12GF_MASK:
+			ctrl->val = XSDIRX_MODE_12GF_OFFSET;
+			break;
+		}
+		break;
+	case V4L2_CID_XILINX_SDIRX_CRC:
+		ctrl->val = xsdirxss_read(core, XSDIRX_CRC_ERRCNT_REG);
+		xsdirxss_write(core, XSDIRX_CRC_ERRCNT_REG, 0xFFFF);
+		break;
+	case V4L2_CID_XILINX_SDIRX_EDH_ERRCNT:
+		val = xsdirxss_read(core, XSDIRX_MODE_DET_STAT_REG);
+		val &= XSDIRX_MODE_DET_STAT_RX_MODE_MASK;
+		if (val == XSDIRX_MODE_SD_MASK) {
+			ctrl->val = xsdirxss_read(core, XSDIRX_EDH_ERRCNT_REG);
+		} else {
+			dev_dbg(core->dev, "%d - not in SD mode\n", ctrl->id);
+			return -EINVAL;
+		}
+		break;
+	case V4L2_CID_XILINX_SDIRX_EDH_STATUS:
+		val = xsdirxss_read(core, XSDIRX_MODE_DET_STAT_REG);
+		val &= XSDIRX_MODE_DET_STAT_RX_MODE_MASK;
+		if (val == XSDIRX_MODE_SD_MASK) {
+			ctrl->val = xsdirxss_read(core, XSDIRX_EDH_STAT_REG);
+		} else {
+			dev_dbg(core->dev, "%d - not in SD mode\n", ctrl->id);
+			return -EINVAL;
+		}
+		break;
+	case V4L2_CID_XILINX_SDIRX_TS_IS_INTERLACED:
+		if (!xsdirxss->vidlocked) {
+			dev_err(core->dev, "Can't get values when video not locked!\n");
+			return -EINVAL;
+		}
+		ctrl->val = xsdirxss->ts_is_interlaced;
+		break;
+	case V4L2_CID_XILINX_SDIRX_ACTIVE_STREAMS:
+		if (!xsdirxss->vidlocked) {
+			dev_err(core->dev, "Can't get values when video not locked!\n");
+			return -EINVAL;
+		}
+		val = xsdirxss_read(core, XSDIRX_MODE_DET_STAT_REG);
+		val &= XSDIRX_MODE_DET_STAT_ACT_STREAM_MASK;
+		val >>= XSDIRX_MODE_DET_STAT_ACT_STREAM_OFFSET;
+		ctrl->val = 1 << val;
+		break;
+	case V4L2_CID_XILINX_SDIRX_IS_3GB:
+		if (!xsdirxss->vidlocked) {
+			dev_err(core->dev, "Can't get values when video not locked!\n");
+			return -EINVAL;
+		}
+		val = xsdirxss_read(core, XSDIRX_MODE_DET_STAT_REG);
+		val &= XSDIRX_MODE_DET_STAT_LVLB_3G_MASK;
+		ctrl->val = val ? true : false;
+		break;
+	case V4L2_CID_METADATA_HDR:
+		if (!xsdirxss->vidlocked) {
+			dev_err(core->dev, "Can't get values when video not locked!\n");
+			return -EINVAL;
+		}
+		hdr_ptr = (struct v4l2_metadata_hdr *)ctrl->p_new.p;
+		hdr_ptr->metadata_type = V4L2_HDR_TYPE_HDR10;
+		hdr_ptr->size = sizeof(struct v4l2_hdr10_payload);
+		memcpy(hdr_ptr->payload, &xsdirxss->static_hdr,
+		       hdr_ptr->size);
+		break;
+	default:
+		dev_err(core->dev, "Get Invalid control id 0x%0x\n", ctrl->id);
+		return -EINVAL;
+	}
+	dev_dbg(core->dev, "Get ctrl id = 0x%08x val = 0x%08x\n",
+		ctrl->id, ctrl->val);
+	return 0;
+}
+
+/**
+ * xsdirxss_log_status - Logs the status of the SDI Rx Subsystem
+ * @sd: Pointer to V4L2 subdevice structure
+ *
+ * This function prints the current status of Xilinx SDI Rx Subsystem
+ *
+ * Return: 0 on success
+ */
+static int xsdirxss_log_status(struct v4l2_subdev *sd)
+{
+	struct xsdirxss_state *xsdirxss = to_xsdirxssstate(sd);
+	struct xsdirxss_core *core = &xsdirxss->core;
+	u32 i;
+
+	v4l2_info(sd, "***** SDI Rx subsystem reg dump start *****\n");
+	for (i = 0; i < 0x28; i++) {
+		u32 data;
+
+		data = xsdirxss_read(core, i * 4);
+		v4l2_info(sd, "offset 0x%08x data 0x%08x\n",
+			  i * 4, data);
+	}
+	v4l2_info(sd, "***** SDI Rx subsystem reg dump end *****\n");
+	return 0;
+}
+
+/**
+ * xsdirxss_g_frame_interval - Get the frame interval
+ * @sd: V4L2 Sub device
+ * @fi: Pointer to V4l2 Sub device frame interval structure
+ *
+ * This function is used to get the frame interval.
+ * The frame rate can be integral or fractional.
+ * Integral frame rate e.g. numerator = 1000, denominator = 24000 => 24 fps
+ * Fractional frame rate e.g. numerator = 1001, denominator = 24000 => 23.97 fps
+ *
+ * Return: 0 on success
+ */
+static int xsdirxss_g_frame_interval(struct v4l2_subdev *sd,
+				     struct v4l2_subdev_frame_interval *fi)
+{
+	struct xsdirxss_state *xsdirxss = to_xsdirxssstate(sd);
+	struct xsdirxss_core *core = &xsdirxss->core;
+
+	if (!xsdirxss->vidlocked) {
+		dev_err(core->dev, "Video not locked!\n");
+		return -EINVAL;
+	}
+
+	fi->interval = xsdirxss->frame_interval;
+
+	dev_dbg(core->dev, "frame rate numerator = %d denominator = %d\n",
+		xsdirxss->frame_interval.numerator,
+		xsdirxss->frame_interval.denominator);
+	return 0;
+}
+
+/**
+ * xsdirxss_s_stream - It is used to start/stop the streaming.
+ * @sd: V4L2 Sub device
+ * @enable: Flag (True / False)
+ *
+ * This function controls the start or stop of streaming for the
+ * Xilinx SDI Rx Subsystem.
+ *
+ * Return: 0 on success, errors otherwise
+ */
+static int xsdirxss_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct xsdirxss_state *xsdirxss = to_xsdirxssstate(sd);
+	struct xsdirxss_core *core = &xsdirxss->core;
+
+	if (enable) {
+		if (!xsdirxss->vidlocked) {
+			dev_dbg(core->dev, "Video is not locked\n");
+			return -EINVAL;
+		}
+		if (xsdirxss->streaming) {
+			dev_dbg(core->dev, "Already streaming\n");
+			return -EINVAL;
+		}
+
+		xsdirx_streamflow_control(core, true);
+		xsdirxss->streaming = true;
+		dev_dbg(core->dev, "Streaming started\n");
+	} else {
+		if (!xsdirxss->streaming) {
+			dev_dbg(core->dev, "Stopped streaming already\n");
+			return 0;
+		}
+
+		xsdirx_streamflow_control(core, false);
+		xsdirxss->streaming = false;
+		dev_dbg(core->dev, "Streaming stopped\n");
+	}
+
+	return 0;
+}
+
+/**
+ * xsdirxss_g_input_status - It is used to determine if the video signal
+ * is present / locked onto or not.
+ *
+ * @sd: V4L2 Sub device
+ * @status: status of signal locked
+ *
+ * This is used to determine if the video signal is present and locked onto
+ * by the SDI Rx core or not based on vidlocked flag.
+ *
+ * Return: zero on success
+ */
+static int xsdirxss_g_input_status(struct v4l2_subdev *sd, u32 *status)
+{
+	struct xsdirxss_state *xsdirxss = to_xsdirxssstate(sd);
+
+	if (!xsdirxss->vidlocked)
+		*status = V4L2_IN_ST_NO_SYNC | V4L2_IN_ST_NO_SIGNAL;
+	else
+		*status = 0;
+
+	return 0;
+}
+
+static struct v4l2_mbus_framefmt *
+__xsdirxss_get_pad_format(struct xsdirxss_state *xsdirxss,
+			  struct v4l2_subdev_pad_config *cfg,
+			  unsigned int pad, u32 which)
+{
+	struct v4l2_mbus_framefmt *format;
+
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		format = v4l2_subdev_get_try_format(&xsdirxss->subdev, cfg,
+						    pad);
+		break;
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		format = &xsdirxss->format;
+		break;
+	default:
+		format = NULL;
+		break;
+	}
+
+	return format;
+}
+
+/**
+ * xsdirxss_get_format - Get the pad format
+ * @sd: Pointer to V4L2 Sub device structure
+ * @cfg: Pointer to sub device pad information structure
+ * @fmt: Pointer to pad level media bus format
+ *
+ * This function is used to get the pad format information.
+ *
+ * Return: 0 on success
+ */
+static int xsdirxss_get_format(struct v4l2_subdev *sd,
+			       struct v4l2_subdev_pad_config *cfg,
+			       struct v4l2_subdev_format *fmt)
+{
+	struct xsdirxss_state *xsdirxss = to_xsdirxssstate(sd);
+	struct xsdirxss_core *core = &xsdirxss->core;
+	struct v4l2_mbus_framefmt *format;
+
+	if (!xsdirxss->vidlocked) {
+		dev_err(core->dev, "Video not locked!\n");
+		return -EINVAL;
+	}
+
+	format = __xsdirxss_get_pad_format(xsdirxss, cfg,
+					   fmt->pad, fmt->which);
+	if (!format)
+		return -EINVAL;
+
+	fmt->format = *format;
+
+	dev_dbg(core->dev, "Stream width = %d height = %d Field = %d\n",
+		fmt->format.width, fmt->format.height, fmt->format.field);
+
+	return 0;
+}
+
+/**
+ * xsdirxss_set_format - This is used to set the pad format
+ * @sd: Pointer to V4L2 Sub device structure
+ * @cfg: Pointer to sub device pad information structure
+ * @fmt: Pointer to pad level media bus format
+ *
+ * This function is used to set the pad format.
+ * Since the pad format is fixed in hardware, it can't be
+ * modified on run time.
+ *
+ * Return: 0 on success
+ */
+static int xsdirxss_set_format(struct v4l2_subdev *sd,
+			       struct v4l2_subdev_pad_config *cfg,
+			       struct v4l2_subdev_format *fmt)
+{
+	struct v4l2_mbus_framefmt *__format;
+	struct xsdirxss_state *xsdirxss = to_xsdirxssstate(sd);
+
+	dev_dbg(xsdirxss->core.dev,
+		"set width %d height %d code %d field %d colorspace %d\n",
+		fmt->format.width, fmt->format.height,
+		fmt->format.code, fmt->format.field,
+		fmt->format.colorspace);
+
+	__format = __xsdirxss_get_pad_format(xsdirxss, cfg,
+					     fmt->pad, fmt->which);
+	if (!__format)
+		return -EINVAL;
+
+	/* Currently reset the code to one fixed in hardware */
+	/* TODO : Add checks for width height */
+	fmt->format.code = __format->code;
+
+	return 0;
+}
+
+/**
+ * xsdirxss_enum_mbus_code - Handle pixel format enumeration
+ * @sd: pointer to v4l2 subdev structure
+ * @cfg: V4L2 subdev pad configuration
+ * @code: pointer to v4l2_subdev_mbus_code_enum structure
+ *
+ * Return: -EINVAL or zero on success
+ */
+static int xsdirxss_enum_mbus_code(struct v4l2_subdev *sd,
+				   struct v4l2_subdev_pad_config *cfg,
+				   struct v4l2_subdev_mbus_code_enum *code)
+{
+	struct xsdirxss_state *xsdirxss = to_xsdirxssstate(sd);
+	u32 index = code->index;
+
+	if (code->pad || index >= 4)
+		return -EINVAL;
+
+	if (xsdirxss->core.bpc == 12)
+		code->code = xsdirxss_12bpc_mbus_fmts[index];
+	else
+		code->code = xsdirxss_10bpc_mbus_fmts[index];
+
+	return 0;
+}
+
+/**
+ * xsdirxss_enum_dv_timings: Enumerate all the supported DV timings
+ * @sd: pointer to v4l2 subdev structure
+ * @timings: DV timings structure to be returned.
+ *
+ * Return: -EINVAL incase of invalid index and pad or zero on success
+ */
+static int xsdirxss_enum_dv_timings(struct v4l2_subdev *sd,
+				    struct v4l2_enum_dv_timings *timings)
+{
+	if (timings->index >= ARRAY_SIZE(fmt_cap))
+		return -EINVAL;
+
+	if (timings->pad != 0)
+		return -EINVAL;
+
+	timings->timings = fmt_cap[timings->index];
+	return 0;
+}
+
+/**
+ * xsdirxss_query_dv_timings: Query for the current DV timings
+ * @sd: pointer to v4l2 subdev structure
+ * @timings: DV timings structure to be returned.
+ *
+ * Return: -ENOLCK when video is not locked, -ERANGE when corresponding timing
+ * entry is not found or zero on success.
+ */
+static int xsdirxss_query_dv_timings(struct v4l2_subdev *sd,
+				     struct v4l2_dv_timings *timings)
+{
+	struct xsdirxss_state *state = to_xsdirxssstate(sd);
+	unsigned int i;
+
+	if (!state->vidlocked)
+		return -ENOLCK;
+
+	for (i = 0; i < ARRAY_SIZE(xsdirxss_dv_timings); i++) {
+		if (state->format.width == xsdirxss_dv_timings[i].width &&
+		    state->format.height == xsdirxss_dv_timings[i].height &&
+		    state->frame_interval.denominator ==
+		    (xsdirxss_dv_timings[i].fps * 1000)) {
+			*timings = xsdirxss_dv_timings[i].format;
+			return 0;
+		}
+	}
+
+	return -ERANGE;
+}
+
+/**
+ * xsdirxss_open - Called on v4l2_open()
+ * @sd: Pointer to V4L2 sub device structure
+ * @fh: Pointer to V4L2 File handle
+ *
+ * This function is called on v4l2_open(). It sets the default format for pad.
+ *
+ * Return: 0 on success
+ */
+static int xsdirxss_open(struct v4l2_subdev *sd,
+			 struct v4l2_subdev_fh *fh)
+{
+	struct v4l2_mbus_framefmt *format;
+	struct xsdirxss_state *xsdirxss = to_xsdirxssstate(sd);
+
+	format = v4l2_subdev_get_try_format(sd, fh->pad, 0);
+	*format = xsdirxss->default_format;
+
+	return 0;
+}
+
+/**
+ * xsdirxss_close - Called on v4l2_close()
+ * @sd: Pointer to V4L2 sub device structure
+ * @fh: Pointer to V4L2 File handle
+ *
+ * This function is called on v4l2_close().
+ *
+ * Return: 0 on success
+ */
+static int xsdirxss_close(struct v4l2_subdev *sd,
+			  struct v4l2_subdev_fh *fh)
+{
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Media Operations
+ */
+
+static const struct media_entity_operations xsdirxss_media_ops = {
+	.link_validate = v4l2_subdev_link_validate
+};
+
+static const struct v4l2_ctrl_ops xsdirxss_ctrl_ops = {
+	.g_volatile_ctrl = xsdirxss_g_volatile_ctrl,
+	.s_ctrl	= xsdirxss_s_ctrl
+};
+
+static const struct v4l2_ctrl_config xsdirxss_edh_ctrls[] = {
+	{
+		.ops	= &xsdirxss_ctrl_ops,
+		.id	= V4L2_CID_XILINX_SDIRX_EDH_ERRCNT_ENABLE,
+		.name	= "SDI Rx : EDH Error Count Enable",
+		.type	= V4L2_CTRL_TYPE_BITMASK,
+		.min	= 0,
+		.max	= XSDIRX_EDH_ALLERR_MASK,
+		.def	= 0,
+	}, {
+		.ops	= &xsdirxss_ctrl_ops,
+		.id	= V4L2_CID_XILINX_SDIRX_EDH_ERRCNT,
+		.name	= "SDI Rx : EDH Error Count",
+		.type	= V4L2_CTRL_TYPE_INTEGER,
+		.min	= 0,
+		.max	= 0xFFFF,
+		.step	= 1,
+		.def	= 0,
+		.flags  = V4L2_CTRL_FLAG_VOLATILE | V4L2_CTRL_FLAG_READ_ONLY,
+	}, {
+		.ops	= &xsdirxss_ctrl_ops,
+		.id	= V4L2_CID_XILINX_SDIRX_EDH_STATUS,
+		.name	= "SDI Rx : EDH Status",
+		.type	= V4L2_CTRL_TYPE_INTEGER,
+		.min	= 0,
+		.max	= 0xFFFFFFFF,
+		.step	= 1,
+		.def	= 0,
+		.flags  = V4L2_CTRL_FLAG_VOLATILE | V4L2_CTRL_FLAG_READ_ONLY,
+	}
+};
+
+static const struct v4l2_ctrl_config xsdirxss_ctrls[] = {
+	{
+		.ops	= &xsdirxss_ctrl_ops,
+		.id	= V4L2_CID_XILINX_SDIRX_FRAMER,
+		.name	= "SDI Rx : Enable Framer",
+		.type	= V4L2_CTRL_TYPE_BOOLEAN,
+		.min	= false,
+		.max	= true,
+		.step	= 1,
+		.def	= true,
+	}, {
+		.ops	= &xsdirxss_ctrl_ops,
+		.id	= V4L2_CID_XILINX_SDIRX_VIDLOCK_WINDOW,
+		.name	= "SDI Rx : Video Lock Window",
+		.type	= V4L2_CTRL_TYPE_INTEGER,
+		.min	= 0,
+		.max	= 0xFFFFFFFF,
+		.step	= 1,
+		.def	= XSDIRX_DEFAULT_VIDEO_LOCK_WINDOW,
+	}, {
+		.ops	= &xsdirxss_ctrl_ops,
+		.id	= V4L2_CID_XILINX_SDIRX_SEARCH_MODES,
+		.name	= "SDI Rx : Modes search Mask",
+		.type	= V4L2_CTRL_TYPE_BITMASK,
+		.min	= 0,
+		.max	= XSDIRX_DETECT_ALL_MODES,
+		.def	= XSDIRX_DETECT_ALL_MODES,
+	}, {
+		.ops	= &xsdirxss_ctrl_ops,
+		.id	= V4L2_CID_XILINX_SDIRX_MODE_DETECT,
+		.name	= "SDI Rx : Mode Detect Status",
+		.type	= V4L2_CTRL_TYPE_INTEGER,
+		.min	= XSDIRX_MODE_SD_OFFSET,
+		.max	= XSDIRX_MODE_12GF_OFFSET,
+		.step	= 1,
+		.flags  = V4L2_CTRL_FLAG_VOLATILE | V4L2_CTRL_FLAG_READ_ONLY,
+	}, {
+		.ops	= &xsdirxss_ctrl_ops,
+		.id	= V4L2_CID_XILINX_SDIRX_CRC,
+		.name	= "SDI Rx : CRC Error status",
+		.type	= V4L2_CTRL_TYPE_INTEGER,
+		.min	= 0,
+		.max	= 0xFFFFFFFF,
+		.step	= 1,
+		.def	= 0,
+		.flags  = V4L2_CTRL_FLAG_VOLATILE | V4L2_CTRL_FLAG_READ_ONLY,
+	}, {
+		.ops	= &xsdirxss_ctrl_ops,
+		.id	= V4L2_CID_XILINX_SDIRX_TS_IS_INTERLACED,
+		.name	= "SDI Rx : TS is Interlaced",
+		.type	= V4L2_CTRL_TYPE_BOOLEAN,
+		.min	= false,
+		.max	= true,
+		.def	= false,
+		.step	= 1,
+		.flags  = V4L2_CTRL_FLAG_VOLATILE | V4L2_CTRL_FLAG_READ_ONLY,
+	}, {
+		.ops	= &xsdirxss_ctrl_ops,
+		.id	= V4L2_CID_XILINX_SDIRX_ACTIVE_STREAMS,
+		.name	= "SDI Rx : Active Streams",
+		.type	= V4L2_CTRL_TYPE_INTEGER,
+		.min	= 1,
+		.max	= 16,
+		.def	= 1,
+		.step	= 1,
+		.flags  = V4L2_CTRL_FLAG_VOLATILE | V4L2_CTRL_FLAG_READ_ONLY,
+	}, {
+		.ops	= &xsdirxss_ctrl_ops,
+		.id	= V4L2_CID_XILINX_SDIRX_IS_3GB,
+		.name	= "SDI Rx : Is 3GB",
+		.type	= V4L2_CTRL_TYPE_BOOLEAN,
+		.min	= false,
+		.max	= true,
+		.def	= false,
+		.step	= 1,
+		.flags  = V4L2_CTRL_FLAG_VOLATILE | V4L2_CTRL_FLAG_READ_ONLY,
+	}, {
+		.ops	= &xsdirxss_ctrl_ops,
+		.id	= V4L2_CID_METADATA_HDR,
+		.name	= "HDR Controls",
+		.type	= V4L2_CTRL_TYPE_HDR,
+		.min	= 0x8000000000000000,
+		.max	= 0x7FFFFFFFFFFFFFFF,
+		.step	= 1,
+		.def	= 0,
+		.elem_size = sizeof(struct v4l2_metadata_hdr),
+		.flags	= V4L2_CTRL_FLAG_VOLATILE | V4L2_CTRL_FLAG_HAS_PAYLOAD |
+			V4L2_CTRL_FLAG_READ_ONLY,
+	},
+};
+
+static const struct v4l2_subdev_core_ops xsdirxss_core_ops = {
+	.log_status = xsdirxss_log_status,
+	.subscribe_event = xsdirxss_subscribe_event,
+	.unsubscribe_event = xsdirxss_unsubscribe_event
+};
+
+static const struct v4l2_subdev_video_ops xsdirxss_video_ops = {
+	.g_frame_interval = xsdirxss_g_frame_interval,
+	.s_stream = xsdirxss_s_stream,
+	.g_input_status = xsdirxss_g_input_status,
+	.query_dv_timings = xsdirxss_query_dv_timings,
+};
+
+static const struct v4l2_subdev_pad_ops xsdirxss_pad_ops = {
+	.get_fmt = xsdirxss_get_format,
+	.set_fmt = xsdirxss_set_format,
+	.enum_mbus_code = xsdirxss_enum_mbus_code,
+	.enum_dv_timings = xsdirxss_enum_dv_timings,
+};
+
+static const struct v4l2_subdev_ops xsdirxss_ops = {
+	.core = &xsdirxss_core_ops,
+	.video = &xsdirxss_video_ops,
+	.pad = &xsdirxss_pad_ops
+};
+
+static const struct v4l2_subdev_internal_ops xsdirxss_internal_ops = {
+	.open = xsdirxss_open,
+	.close = xsdirxss_close
+};
+
+/* -----------------------------------------------------------------------------
+ * Platform Device Driver
+ */
+
+static int xsdirxss_parse_of(struct xsdirxss_state *xsdirxss)
+{
+	struct device_node *node = xsdirxss->core.dev->of_node;
+	struct device_node *ports = NULL;
+	struct device_node *port = NULL;
+	unsigned int nports = 0;
+	struct xsdirxss_core *core = &xsdirxss->core;
+	int ret;
+	const char *sdi_std;
+
+	core->include_edh = of_property_read_bool(node, "xlnx,include-edh");
+	dev_dbg(core->dev, "EDH property = %s\n",
+		core->include_edh ? "Present" : "Absent");
+
+	ret = of_property_read_string(node, "xlnx,line-rate", &sdi_std);
+	if (ret < 0) {
+		dev_err(core->dev, "xlnx,line-rate property not found\n");
+		return ret;
+	}
+
+	if (!strncmp(sdi_std, "12G_SDI_8DS", XSDIRX_MAX_STR_LENGTH)) {
+		core->mode = XSDIRXSS_SDI_STD_12G_8DS;
+	} else if (!strncmp(sdi_std, "6G_SDI", XSDIRX_MAX_STR_LENGTH)) {
+		core->mode = XSDIRXSS_SDI_STD_6G;
+	} else if (!strncmp(sdi_std, "3G_SDI", XSDIRX_MAX_STR_LENGTH)) {
+		core->mode = XSDIRXSS_SDI_STD_3G;
+	} else {
+		dev_err(core->dev, "Invalid Line Rate\n");
+		return -EINVAL;
+	}
+	dev_dbg(core->dev, "SDI Rx Line Rate = %s, mode = %d\n", sdi_std,
+		core->mode);
+
+	ret = of_property_read_u32(node, "xlnx,bpp", &core->bpc);
+	if (ret < 0) {
+		if (ret != -EINVAL) {
+			dev_err(core->dev, "failed to get xlnx,bpp\n");
+			return ret;
+		}
+
+		/*
+		 * For backward compatibility, set default bpc as 10
+		 * in case xlnx,bpp is not present.
+		 */
+		core->bpc = 10;
+	}
+
+	if (core->bpc != 10 && core->bpc != 12) {
+		dev_err(core->dev, "bits per component=%u. Can be 10 or 12 only\n",
+			core->bpc);
+		return -EINVAL;
+	}
+
+	ports = of_get_child_by_name(node, "ports");
+	if (!ports)
+		ports = node;
+
+	for_each_child_of_node(ports, port) {
+		const struct xvip_video_format *format;
+		struct device_node *endpoint;
+
+		if (!port->name || of_node_cmp(port->name, "port"))
+			continue;
+
+		format = xvip_of_get_format(port);
+		if (IS_ERR(format)) {
+			dev_err(core->dev, "invalid format in DT");
+			return PTR_ERR(format);
+		}
+
+		dev_dbg(core->dev, "vf_code = %d bpc = %d bpp = %d\n",
+			format->vf_code, format->width, format->bpp);
+
+		if (format->vf_code != XVIP_VF_YUV_422 &&
+		    format->vf_code != XVIP_VF_YUV_420 &&
+		    format->vf_code != XVIP_VF_YUV_444 &&
+		    format->vf_code != XVIP_VF_RBG &&
+		    ((core->bpc == 10 && format->width != 10) ||
+		     (core->bpc == 12 && format->width != 12))) {
+			dev_err(core->dev,
+				"Incorrect UG934 video format set.\n");
+			return -EINVAL;
+		}
+		xsdirxss->vip_format = format;
+
+		endpoint = of_get_next_child(port, NULL);
+		if (!endpoint) {
+			dev_err(core->dev, "No port at\n");
+			return -EINVAL;
+		}
+
+		/* Count the number of ports. */
+		nports++;
+	}
+
+	if (nports != 1) {
+		dev_err(core->dev, "invalid number of ports %u\n", nports);
+		return -EINVAL;
+	}
+
+	/* Register interrupt handler */
+	core->irq = irq_of_parse_and_map(node, 0);
+	ret = devm_request_threaded_irq(core->dev, core->irq, NULL,
+					xsdirxss_irq_handler, IRQF_ONESHOT,
+					"xilinx-sdirxss", xsdirxss);
+	if (ret) {
+		dev_err(core->dev, "Err = %d Interrupt handler reg failed!\n",
+			ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int xsdirxss_probe(struct platform_device *pdev)
+{
+	struct v4l2_subdev *subdev;
+	struct xsdirxss_state *xsdirxss;
+	struct xsdirxss_core *core;
+	struct resource *res;
+	int ret;
+	unsigned int num_ctrls, num_edh_ctrls = 0, i;
+
+	xsdirxss = devm_kzalloc(&pdev->dev, sizeof(*xsdirxss), GFP_KERNEL);
+	if (!xsdirxss)
+		return -ENOMEM;
+
+	xsdirxss->core.dev = &pdev->dev;
+	core = &xsdirxss->core;
+
+	core->rst_gt_gpio = devm_gpiod_get_optional(&pdev->dev, "reset_gt",
+						    GPIOD_OUT_HIGH);
+	if (IS_ERR(core->rst_gt_gpio)) {
+		ret = PTR_ERR(core->rst_gt_gpio);
+		if (ret != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "Reset GT GPIO not setup in DT\n");
+		return ret;
+	}
+
+	core->rst_picxo_gpio = devm_gpiod_get_optional(&pdev->dev,
+						       "picxo_reset",
+						       GPIOD_OUT_LOW);
+	if (IS_ERR(core->rst_picxo_gpio)) {
+		ret = PTR_ERR(core->rst_picxo_gpio);
+		if (ret != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "PICXO Reset GPIO not setup in DT\n");
+		return ret;
+	}
+
+	core->num_clks = ARRAY_SIZE(xsdirxss_clks);
+	core->clks = devm_kcalloc(&pdev->dev, core->num_clks,
+				  sizeof(*core->clks), GFP_KERNEL);
+	if (!core->clks)
+		return -ENOMEM;
+
+	for (i = 0; i < core->num_clks; i++)
+		core->clks[i].id = xsdirxss_clks[i];
+
+	ret = devm_clk_bulk_get(&pdev->dev, core->num_clks, core->clks);
+	if (ret)
+		return ret;
+
+	ret = clk_bulk_prepare_enable(core->num_clks, core->clks);
+	if (ret)
+		return ret;
+
+	ret = xsdirxss_parse_of(xsdirxss);
+	if (ret < 0)
+		goto clk_err;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	xsdirxss->core.iomem = devm_ioremap_resource(xsdirxss->core.dev, res);
+	if (IS_ERR(xsdirxss->core.iomem)) {
+		ret = PTR_ERR(xsdirxss->core.iomem);
+		goto clk_err;
+	}
+
+	/* Reset the core */
+	xsdirx_streamflow_control(core, false);
+	xsdirx_core_disable(core);
+	xsdirx_clearintr(core, XSDIRX_INTR_ALL_MASK);
+	xsdirx_disableintr(core, XSDIRX_INTR_ALL_MASK);
+	xsdirx_enableintr(core, XSDIRX_INTR_ALL_MASK);
+	xsdirx_globalintr(core, true);
+	xsdirxss_write(core, XSDIRX_CRC_ERRCNT_REG, 0xFFFF);
+
+	/* Initialize V4L2 subdevice and media entity */
+	xsdirxss->pad.flags = MEDIA_PAD_FL_SOURCE;
+
+	/* Initialize the default format */
+	xsdirxss->default_format.code = xsdirxss->vip_format->code;
+	xsdirxss->default_format.field = V4L2_FIELD_NONE;
+	xsdirxss->default_format.colorspace = V4L2_COLORSPACE_DEFAULT;
+	xsdirxss->default_format.width = XSDIRX_DEFAULT_WIDTH;
+	xsdirxss->default_format.height = XSDIRX_DEFAULT_HEIGHT;
+
+	xsdirxss->format = xsdirxss->default_format;
+
+	/* Initialize V4L2 subdevice and media entity */
+	subdev = &xsdirxss->subdev;
+	v4l2_subdev_init(subdev, &xsdirxss_ops);
+
+	subdev->dev = &pdev->dev;
+	subdev->internal_ops = &xsdirxss_internal_ops;
+	strscpy(subdev->name, dev_name(&pdev->dev), sizeof(subdev->name));
+
+	subdev->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	subdev->entity.ops = &xsdirxss_media_ops;
+
+	v4l2_set_subdevdata(subdev, xsdirxss);
+
+	ret = media_entity_pads_init(&subdev->entity, 1, &xsdirxss->pad);
+	if (ret < 0)
+		goto error;
+
+	/* Initialise and register the controls */
+	num_ctrls = ARRAY_SIZE(xsdirxss_ctrls);
+
+	if (xsdirxss->core.include_edh)
+		num_edh_ctrls = ARRAY_SIZE(xsdirxss_edh_ctrls);
+
+	v4l2_ctrl_handler_init(&xsdirxss->ctrl_handler,
+			       (num_ctrls + num_edh_ctrls));
+
+	for (i = 0; i < num_ctrls; i++) {
+		struct v4l2_ctrl *ctrl;
+
+		dev_dbg(xsdirxss->core.dev, "%d %s ctrl = 0x%x\n",
+			i, xsdirxss_ctrls[i].name, xsdirxss_ctrls[i].id);
+
+		ctrl = v4l2_ctrl_new_custom(&xsdirxss->ctrl_handler,
+					    &xsdirxss_ctrls[i], NULL);
+		if (!ctrl) {
+			dev_dbg(xsdirxss->core.dev, "Failed to add %s ctrl\n",
+				xsdirxss_ctrls[i].name);
+			goto error;
+		}
+	}
+
+	if (xsdirxss->core.include_edh) {
+		for (i = 0; i < num_edh_ctrls; i++) {
+			struct v4l2_ctrl *ctrl;
+
+			dev_dbg(xsdirxss->core.dev, "%d %s ctrl = 0x%x\n",
+				i, xsdirxss_edh_ctrls[i].name,
+				xsdirxss_edh_ctrls[i].id);
+
+			ctrl = v4l2_ctrl_new_custom(&xsdirxss->ctrl_handler,
+						    &xsdirxss_edh_ctrls[i],
+						    NULL);
+			if (!ctrl) {
+				dev_dbg(xsdirxss->core.dev, "Failed to add %s ctrl\n",
+					xsdirxss_edh_ctrls[i].name);
+				goto error;
+			}
+		}
+	}
+
+	if (xsdirxss->ctrl_handler.error) {
+		dev_err(&pdev->dev, "failed to add controls\n");
+		ret = xsdirxss->ctrl_handler.error;
+		goto error;
+	}
+
+	subdev->ctrl_handler = &xsdirxss->ctrl_handler;
+
+	ret = v4l2_ctrl_handler_setup(&xsdirxss->ctrl_handler);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to set controls\n");
+		goto error;
+	}
+
+	platform_set_drvdata(pdev, xsdirxss);
+
+	ret = v4l2_async_register_subdev(subdev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to register subdev\n");
+		goto error;
+	}
+
+	xsdirxss->streaming = false;
+
+	xsdirx_core_enable(core);
+
+	dev_info(xsdirxss->core.dev, "Xilinx SDI Rx Subsystem device found!\n");
+
+	return 0;
+error:
+	v4l2_ctrl_handler_free(&xsdirxss->ctrl_handler);
+	media_entity_cleanup(&subdev->entity);
+	xsdirx_globalintr(core, false);
+	xsdirx_disableintr(core, XSDIRX_INTR_ALL_MASK);
+clk_err:
+	clk_bulk_disable_unprepare(core->num_clks, core->clks);
+	return ret;
+}
+
+static int xsdirxss_remove(struct platform_device *pdev)
+{
+	struct xsdirxss_state *xsdirxss = platform_get_drvdata(pdev);
+	struct xsdirxss_core *core = &xsdirxss->core;
+	struct v4l2_subdev *subdev = &xsdirxss->subdev;
+
+	v4l2_async_unregister_subdev(subdev);
+	v4l2_ctrl_handler_free(&xsdirxss->ctrl_handler);
+	media_entity_cleanup(&subdev->entity);
+
+	xsdirx_globalintr(core, false);
+	xsdirx_disableintr(core, XSDIRX_INTR_ALL_MASK);
+	xsdirx_core_disable(core);
+	xsdirx_streamflow_control(core, false);
+
+	clk_bulk_disable_unprepare(core->num_clks, core->clks);
+
+	return 0;
+}
+
+static const struct of_device_id xsdirxss_of_id_table[] = {
+	{ .compatible = "xlnx,v-smpte-uhdsdi-rx-ss" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, xsdirxss_of_id_table);
+
+static struct platform_driver xsdirxss_driver = {
+	.driver = {
+		.name		= "xilinx-sdirxss",
+		.of_match_table	= xsdirxss_of_id_table,
+	},
+	.probe			= xsdirxss_probe,
+	.remove			= xsdirxss_remove,
+};
+
+module_platform_driver(xsdirxss_driver);
+
+MODULE_AUTHOR("Vishal Sagar <vsagar@xilinx.com>");
+MODULE_DESCRIPTION("Xilinx SDI Rx Subsystem Driver");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/xilinx-switch.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/xilinx-switch.c
@@ -0,0 +1,476 @@
+/*
+ * Xilinx Video Switch
+ *
+ * Copyright (C) 2013-2015 Ideas on Board
+ * Copyright (C) 2013-2015 Xilinx, Inc.
+ *
+ * Contacts: Hyun Kwon <hyun.kwon@xilinx.com>
+ *           Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include <media/media-device.h>
+#include <media/v4l2-async.h>
+#include <media/v4l2-subdev.h>
+
+#include "xilinx-vip.h"
+
+#define XSW_CORE_CH_CTRL			0x0100
+#define XSW_CORE_CH_CTRL_FORCE			(1 << 3)
+
+#define XSW_SWITCH_STATUS			0x0104
+
+/**
+ * struct xswitch_device - Xilinx Video Switch device structure
+ * @xvip: Xilinx Video IP device
+ * @pads: media pads
+ * @nsinks: number of sink pads (2 to 8)
+ * @nsources: number of source pads (1 to 8)
+ * @routing: sink pad connected to each source pad (-1 if none)
+ * @formats: active V4L2 media bus formats on sink pads
+ */
+struct xswitch_device {
+	struct xvip_device xvip;
+
+	struct media_pad *pads;
+	unsigned int nsinks;
+	unsigned int nsources;
+
+	int routing[8];
+
+	struct v4l2_mbus_framefmt *formats;
+};
+
+static inline struct xswitch_device *to_xsw(struct v4l2_subdev *subdev)
+{
+	return container_of(subdev, struct xswitch_device, xvip.subdev);
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 Subdevice Video Operations
+ */
+
+static int xsw_s_stream(struct v4l2_subdev *subdev, int enable)
+{
+	struct xswitch_device *xsw = to_xsw(subdev);
+	unsigned int unused_input;
+	unsigned int i;
+	u32 routing;
+
+	if (!enable) {
+		xvip_stop(&xsw->xvip);
+		return 0;
+	}
+
+	/*
+	 * All outputs must be routed to an input. When less than 8 inputs are
+	 * synthesized we can use input 7 for that purpose. Otherwise find an
+	 * unused input to connect to unused outputs.
+	 */
+	if (xsw->nsinks == 8) {
+		u32 mask;
+
+		for (i = 0, mask = 0xff; i < xsw->nsources; ++i) {
+			if (xsw->routing[i] != -1)
+				mask &= ~BIT(xsw->routing[i]);
+		}
+
+		/*
+		 * If all inputs are used all outputs are also used. We don't
+		 * need an unused input in that case, use a zero value.
+		 */
+		unused_input = mask ? ffs(mask) - 1 : 0;
+	} else {
+		unused_input = 7;
+	}
+
+	/* Configure routing. */
+	for (i = 0, routing = 0; i < xsw->nsources; ++i) {
+		unsigned int route;
+
+		route = xsw->routing[i] == -1 ?  unused_input : xsw->routing[i];
+		routing |= (XSW_CORE_CH_CTRL_FORCE | route)
+			<< (i * 4);
+	}
+
+	xvip_write(&xsw->xvip, XSW_CORE_CH_CTRL, routing);
+
+	xvip_write(&xsw->xvip, XVIP_CTRL_CONTROL,
+		   ((((unsigned long)1 << xsw->nsources) - 1) << 4) |
+		   XVIP_CTRL_CONTROL_SW_ENABLE);
+
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 Subdevice Pad Operations
+ */
+
+static struct v4l2_mbus_framefmt *
+xsw_get_pad_format(struct xswitch_device *xsw,
+		   struct v4l2_subdev_pad_config *cfg,
+		   unsigned int pad, u32 which)
+{
+	struct v4l2_mbus_framefmt *format;
+
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		format = v4l2_subdev_get_try_format(&xsw->xvip.subdev,
+						    cfg, pad);
+		break;
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		format = &xsw->formats[pad];
+		break;
+	default:
+		format = NULL;
+		break;
+	}
+
+	return format;
+}
+
+static int xsw_get_format(struct v4l2_subdev *subdev,
+			  struct v4l2_subdev_pad_config *cfg,
+			  struct v4l2_subdev_format *fmt)
+{
+	struct xswitch_device *xsw = to_xsw(subdev);
+	int pad = fmt->pad;
+	struct v4l2_mbus_framefmt *format;
+
+	if (pad >= xsw->nsinks) {
+		pad = xsw->routing[pad - xsw->nsinks];
+		if (pad < 0) {
+			memset(&fmt->format, 0, sizeof(fmt->format));
+			return 0;
+		}
+	}
+
+	format = xsw_get_pad_format(xsw, cfg, pad, fmt->which);
+	if (!format)
+		return -EINVAL;
+
+	fmt->format = *format;
+
+	return 0;
+}
+
+static int xsw_set_format(struct v4l2_subdev *subdev,
+			  struct v4l2_subdev_pad_config *cfg,
+			  struct v4l2_subdev_format *fmt)
+{
+	struct xswitch_device *xsw = to_xsw(subdev);
+	struct v4l2_mbus_framefmt *format;
+
+	/* The source pad format is always identical to the sink pad format and
+	 * can't be modified.
+	 */
+	if (fmt->pad >= xsw->nsinks)
+		return xsw_get_format(subdev, cfg, fmt);
+
+	format = xsw_get_pad_format(xsw, cfg, fmt->pad, fmt->which);
+	if (!format)
+		return -EINVAL;
+
+	format->code = fmt->format.code;
+	format->width = clamp_t(unsigned int, fmt->format.width,
+				XVIP_MIN_WIDTH, XVIP_MAX_WIDTH);
+	format->height = clamp_t(unsigned int, fmt->format.height,
+				 XVIP_MIN_HEIGHT, XVIP_MAX_HEIGHT);
+	format->field = V4L2_FIELD_NONE;
+	format->colorspace = V4L2_COLORSPACE_SRGB;
+
+	fmt->format = *format;
+
+	return 0;
+}
+
+static int xsw_get_routing(struct v4l2_subdev *subdev,
+			   struct v4l2_subdev_routing *route)
+{
+	struct xswitch_device *xsw = to_xsw(subdev);
+	unsigned int i;
+
+	mutex_lock(&subdev->entity.graph_obj.mdev->graph_mutex);
+
+	for (i = 0; i < min(xsw->nsources, route->num_routes); ++i) {
+		route->routes[i].sink = xsw->routing[i];
+		route->routes[i].source = i;
+	}
+
+	route->num_routes = xsw->nsources;
+
+	mutex_unlock(&subdev->entity.graph_obj.mdev->graph_mutex);
+
+	return 0;
+}
+
+static int xsw_set_routing(struct v4l2_subdev *subdev,
+			   struct v4l2_subdev_routing *route)
+{
+	struct xswitch_device *xsw = to_xsw(subdev);
+	unsigned int i;
+	int ret = 0;
+
+	mutex_lock(&subdev->entity.graph_obj.mdev->graph_mutex);
+
+	if (subdev->entity.stream_count) {
+		ret = -EBUSY;
+		goto done;
+	}
+
+	for (i = 0; i < xsw->nsources; ++i)
+		xsw->routing[i] = -1;
+
+	for (i = 0; i < route->num_routes; ++i)
+		xsw->routing[route->routes[i].source - xsw->nsinks] =
+			route->routes[i].sink;
+
+done:
+	mutex_unlock(&subdev->entity.graph_obj.mdev->graph_mutex);
+	return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 Subdevice Operations
+ */
+
+/**
+ * xsw_init_formats - Initialize formats on all pads
+ * @subdev: tpgper V4L2 subdevice
+ * @fh: V4L2 subdev file handle
+ *
+ * Initialize all pad formats with default values. If fh is not NULL, try
+ * formats are initialized on the file handle. Otherwise active formats are
+ * initialized on the device.
+ *
+ * The function sets the format on pad 0 only. In two pads mode, this is the
+ * sink pad and the set format handler will propagate the format to the source
+ * pad. In one pad mode this is the source pad.
+ */
+static void xsw_init_formats(struct v4l2_subdev *subdev,
+			      struct v4l2_subdev_fh *fh)
+{
+	struct xswitch_device *xsw = to_xsw(subdev);
+	struct v4l2_subdev_format format;
+	unsigned int i;
+
+	for (i = 0; i < xsw->nsinks; ++i) {
+		memset(&format, 0, sizeof(format));
+
+		format.pad = 0;
+		format.which = fh ? V4L2_SUBDEV_FORMAT_TRY
+			     : V4L2_SUBDEV_FORMAT_ACTIVE;
+		format.format.width = 1920;
+		format.format.height = 1080;
+
+		xsw_set_format(subdev, fh ? fh->pad : NULL, &format);
+	}
+}
+
+static int xsw_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+	xsw_init_formats(subdev, fh);
+
+	return 0;
+}
+
+static int xsw_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+	return 0;
+}
+
+static struct v4l2_subdev_video_ops xsw_video_ops = {
+	.s_stream = xsw_s_stream,
+};
+
+static struct v4l2_subdev_pad_ops xsw_pad_ops = {
+	.enum_mbus_code = xvip_enum_mbus_code,
+	.enum_frame_size = xvip_enum_frame_size,
+	.get_fmt = xsw_get_format,
+	.set_fmt = xsw_set_format,
+	.get_routing = xsw_get_routing,
+	.set_routing = xsw_set_routing,
+};
+
+static struct v4l2_subdev_ops xsw_ops = {
+	.video = &xsw_video_ops,
+	.pad = &xsw_pad_ops,
+};
+
+static const struct v4l2_subdev_internal_ops xsw_internal_ops = {
+	.open = xsw_open,
+	.close = xsw_close,
+};
+
+/* -----------------------------------------------------------------------------
+ * Media Operations
+ */
+
+static bool xsw_has_route(struct media_entity *entity, unsigned int pad0,
+			  unsigned int pad1)
+{
+	struct xswitch_device *xsw = container_of(entity, struct xswitch_device,
+						  xvip.subdev.entity);
+	unsigned int sink0, sink1;
+
+	/* Two sinks are never connected together. */
+	if (pad0 < xsw->nsinks && pad1 < xsw->nsinks)
+		return false;
+
+	sink0 = pad0 < xsw->nsinks ? pad0 : xsw->routing[pad0 - xsw->nsinks];
+	sink1 = pad1 < xsw->nsinks ? pad1 : xsw->routing[pad1 - xsw->nsinks];
+
+	return sink0 == sink1;
+}
+
+static const struct media_entity_operations xsw_media_ops = {
+	.link_validate = v4l2_subdev_link_validate,
+	.has_route = xsw_has_route,
+};
+
+/* -----------------------------------------------------------------------------
+ * Platform Device Driver
+ */
+
+static int xsw_parse_of(struct xswitch_device *xsw)
+{
+	struct device_node *node = xsw->xvip.dev->of_node;
+	int ret;
+
+	ret = of_property_read_u32(node, "#xlnx,inputs", &xsw->nsinks);
+	if (ret < 0) {
+		dev_err(xsw->xvip.dev, "missing or invalid #xlnx,%s property\n",
+			"inputs");
+		return ret;
+	}
+
+	ret = of_property_read_u32(node, "#xlnx,outputs", &xsw->nsources);
+	if (ret < 0) {
+		dev_err(xsw->xvip.dev, "missing or invalid #xlnx,%s property\n",
+			"outputs");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int xsw_probe(struct platform_device *pdev)
+{
+	struct v4l2_subdev *subdev;
+	struct xswitch_device *xsw;
+	unsigned int npads;
+	unsigned int i;
+	int ret;
+
+	xsw = devm_kzalloc(&pdev->dev, sizeof(*xsw), GFP_KERNEL);
+	if (!xsw)
+		return -ENOMEM;
+
+	xsw->xvip.dev = &pdev->dev;
+
+	ret = xsw_parse_of(xsw);
+	if (ret < 0)
+		return ret;
+
+	ret = xvip_init_resources(&xsw->xvip);
+	if (ret < 0)
+		return ret;
+
+	/* Initialize V4L2 subdevice and media entity. Pad numbers depend on the
+	 * number of pads.
+	 */
+	npads = xsw->nsinks + xsw->nsources;
+	xsw->pads = devm_kzalloc(&pdev->dev, npads * sizeof(*xsw->pads),
+				 GFP_KERNEL);
+	if (!xsw->pads)
+		goto error_resources;
+
+	for (i = 0; i < xsw->nsinks; ++i)
+		xsw->pads[i].flags = MEDIA_PAD_FL_SINK;
+	for (; i < npads; ++i)
+		xsw->pads[i].flags = MEDIA_PAD_FL_SOURCE;
+
+	xsw->formats = devm_kzalloc(&pdev->dev,
+				    xsw->nsinks * sizeof(*xsw->formats),
+				    GFP_KERNEL);
+	if (!xsw->formats)
+		goto error_resources;
+
+	for (i = 0; i < xsw->nsources; ++i)
+		xsw->routing[i] = i < xsw->nsinks ? i : -1;
+
+	subdev = &xsw->xvip.subdev;
+	v4l2_subdev_init(subdev, &xsw_ops);
+	subdev->dev = &pdev->dev;
+	subdev->internal_ops = &xsw_internal_ops;
+	strlcpy(subdev->name, dev_name(&pdev->dev), sizeof(subdev->name));
+	v4l2_set_subdevdata(subdev, xsw);
+	subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	subdev->entity.ops = &xsw_media_ops;
+
+	xsw_init_formats(subdev, NULL);
+
+	ret = media_entity_pads_init(&subdev->entity, npads, xsw->pads);
+	if (ret < 0)
+		goto error;
+
+	platform_set_drvdata(pdev, xsw);
+
+	xvip_print_version(&xsw->xvip);
+
+	ret = v4l2_async_register_subdev(subdev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to register subdev\n");
+		goto error;
+	}
+
+	return 0;
+
+error:
+	media_entity_cleanup(&subdev->entity);
+error_resources:
+	xvip_cleanup_resources(&xsw->xvip);
+	return ret;
+}
+
+static int xsw_remove(struct platform_device *pdev)
+{
+	struct xswitch_device *xsw = platform_get_drvdata(pdev);
+	struct v4l2_subdev *subdev = &xsw->xvip.subdev;
+
+	v4l2_async_unregister_subdev(subdev);
+	media_entity_cleanup(&subdev->entity);
+
+	xvip_cleanup_resources(&xsw->xvip);
+
+	return 0;
+}
+
+static const struct of_device_id xsw_of_id_table[] = {
+	{ .compatible = "xlnx,v-switch-1.0" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, xsw_of_id_table);
+
+static struct platform_driver xsw_driver = {
+	.driver = {
+		.name		= "xilinx-switch",
+		.of_match_table	= xsw_of_id_table,
+	},
+	.probe			= xsw_probe,
+	.remove			= xsw_remove,
+};
+
+module_platform_driver(xsw_driver);
+
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_DESCRIPTION("Xilinx Video Switch Driver");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/xilinx-tpg.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/xilinx-tpg.c
@@ -20,6 +20,7 @@
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-subdev.h>
 
+#include "xilinx-hls-common.h"
 #include "xilinx-vip.h"
 #include "xilinx-vtc.h"
 
@@ -58,6 +59,36 @@
 #define XTPG_BAYER_PHASE_BGGR			3
 #define XTPG_BAYER_PHASE_OFF			4
 
+/* TPG v7 is a completely redesigned IP using Vivado HLS
+ * having a different AXI4-Lite interface
+ */
+#define XTPG_HLS_BG_PATTERN			0x0020
+#define XTPG_HLS_FG_PATTERN			0x0028
+#define XTPG_HLS_FG_PATTERN_CROSS_HAIR		(1 << 1)
+#define XTPG_HLS_MASK_ID			0x0030
+#define XTPG_HLS_MOTION_SPEED			0x0038
+#define XTPG_HLS_COLOR_FORMAT			0x0040
+#define XTPG_HLS_COLOR_FORMAT_RGB		0
+#define XTPG_HLS_COLOR_FORMAT_YUV_444		1
+#define XTPG_HLS_COLOR_FORMAT_YUV_422		2
+#define XTPG_HLS_COLOR_FORMAT_YUV_420		3
+#define XTPG_HLS_CROSS_HAIR_HOR			0x0048
+#define XTPG_HLS_CROSS_HAIR_VER			0x0050
+#define XTPG_HLS_ZPLATE_HOR_CNTL_START		0x0058
+#define XTPG_HLS_ZPLATE_HOR_CNTL_DELTA		0x0060
+#define XTPG_HLS_ZPLATE_VER_CNTL_START		0x0068
+#define XTPG_HLS_ZPLATE_VER_CNTL_DELTA		0x0070
+#define XTPG_HLS_BOX_SIZE			0x0078
+#define XTPG_HLS_BOX_COLOR_RED_CB		0x0080
+#define XTPG_HLS_BOX_COLOR_GREEN_CR		0x0088
+#define XTPG_HLS_BOX_COLOR_BLUE_Y		0x0090
+#define XTPG_HLS_ENABLE_INPUT			0x0098
+#define XTPG_HLS_USE_INPUT_VID_STREAM		(1 << 0)
+#define XTPG_HLS_PASS_THRU_START_X		0x00a0
+#define XTPG_HLS_PASS_THRU_START_Y		0x00a8
+#define XTPG_HLS_PASS_THRU_END_X		0x00b0
+#define XTPG_HLS_PASS_THRU_END_Y		0x00b8
+
 /*
  * The minimum blanking value is one clock cycle for the front porch, one clock
  * cycle for the sync pulse and one clock cycle for the back porch.
@@ -67,6 +98,15 @@
 #define XTPG_MIN_VBLANK			3
 #define XTPG_MAX_VBLANK			(XVTC_MAX_VSIZE - XVIP_MIN_HEIGHT)
 
+#define XTPG_MIN_WIDTH			(64)
+#define XTPG_MIN_HEIGHT			(64)
+#define XTPG_MAX_WIDTH			(10328)
+#define XTPG_MAX_HEIGHT			(7760)
+
+#define XTPG_MIN_PPC			1
+
+#define XTPG_MIN_FRM_INT		1
+
 /**
  * struct xtpg_device - Xilinx Test Pattern Generator device structure
  * @xvip: Xilinx Video IP device
@@ -82,8 +122,15 @@
  * @vblank: vertical blanking control
  * @pattern: test pattern control
  * @streaming: is the video stream active
+ * @is_hls: whether the IP core is HLS based
  * @vtc: video timing controller
  * @vtmux_gpio: video timing mux GPIO
+ * @rst_gpio: reset IP core GPIO
+ * @max_width: Maximum width supported by this instance
+ * @max_height: Maximum height supported by this instance
+ * @fi_d: frame interval denominator
+ * @fi_n: frame interval numerator
+ * @ppc: Pixels per clock control
  */
 struct xtpg_device {
 	struct xvip_device xvip;
@@ -102,9 +149,17 @@
 	struct v4l2_ctrl *vblank;
 	struct v4l2_ctrl *pattern;
 	bool streaming;
+	bool is_hls;
 
 	struct xvtc_device *vtc;
 	struct gpio_desc *vtmux_gpio;
+	struct gpio_desc *rst_gpio;
+
+	u32 max_width;
+	u32 max_height;
+	u32 fi_d;
+	u32 fi_n;
+	u32 ppc;
 };
 
 static inline struct xtpg_device *to_tpg(struct v4l2_subdev *subdev)
@@ -128,6 +183,32 @@
 	}
 }
 
+static void xtpg_config_vtc(struct xtpg_device *xtpg, int width, int height)
+{
+
+	struct xvtc_config config = {
+		.hblank_start = width / xtpg->ppc,
+		.hsync_start = width / xtpg->ppc + 1,
+		.vblank_start = height,
+		.vsync_start = height + 1,
+		.fps = xtpg->fi_d / xtpg->fi_n,
+	};
+	unsigned int htotal;
+	unsigned int vtotal;
+
+	htotal = min_t(unsigned int, XVTC_MAX_HSIZE,
+		       (v4l2_ctrl_g_ctrl(xtpg->hblank) + width) / xtpg->ppc);
+	vtotal = min_t(unsigned int, XVTC_MAX_VSIZE,
+		       v4l2_ctrl_g_ctrl(xtpg->vblank) + height);
+
+	config.hsync_end = htotal - 1;
+	config.hsize = htotal;
+	config.vsync_end = vtotal - 1;
+	config.vsize = vtotal;
+
+	xvtc_generator_start(xtpg->vtc, &config);
+}
+
 static void __xtpg_update_pattern_control(struct xtpg_device *xtpg,
 					  bool passthrough, bool pattern)
 {
@@ -164,6 +245,33 @@
  * V4L2 Subdevice Video Operations
  */
 
+static int xtpg_g_frame_interval(struct v4l2_subdev *subdev,
+				 struct v4l2_subdev_frame_interval *fi)
+{
+	struct xtpg_device *xtpg = to_tpg(subdev);
+
+	fi->interval.numerator = xtpg->fi_n;
+	fi->interval.denominator = xtpg->fi_d;
+
+	return 0;
+}
+
+static int xtpg_s_frame_interval(struct v4l2_subdev *subdev,
+				 struct v4l2_subdev_frame_interval *fi)
+{
+	struct xtpg_device *xtpg = to_tpg(subdev);
+
+	if (!fi->interval.numerator || !fi->interval.denominator) {
+		xtpg->fi_n = XTPG_MIN_FRM_INT;
+		xtpg->fi_d = XTPG_MIN_FRM_INT;
+	} else {
+		xtpg->fi_n = fi->interval.numerator;
+		xtpg->fi_d = fi->interval.denominator;
+	}
+
+	return 0;
+}
+
 static int xtpg_s_stream(struct v4l2_subdev *subdev, int enable)
 {
 	struct xtpg_device *xtpg = to_tpg(subdev);
@@ -173,7 +281,27 @@
 	u32 bayer_phase;
 
 	if (!enable) {
-		xvip_stop(&xtpg->xvip);
+		if (!xtpg->is_hls) {
+			xvip_stop(&xtpg->xvip);
+		} else {
+			int ret;
+			/*
+			 * There is an known issue in TPG v7.0 that on
+			 * resolution change it doesn't generates pattern
+			 * correctly i.e some hor/ver offset is added.
+			 * As a workaround issue reset on stop.
+			 */
+			gpiod_set_value_cansleep(xtpg->rst_gpio, 0x1);
+			gpiod_set_value_cansleep(xtpg->rst_gpio, 0x0);
+			ret = v4l2_ctrl_handler_setup(&xtpg->ctrl_handler);
+			if (ret) {
+				struct device *dev = xtpg->xvip.dev;
+
+				dev_err(dev, "failed to set controls\n");
+				return ret;
+			}
+		}
+
 		if (xtpg->vtc)
 			xvtc_generator_stop(xtpg->vtc);
 
@@ -182,31 +310,36 @@
 		return 0;
 	}
 
-	xvip_set_frame_size(&xtpg->xvip, &xtpg->formats[0]);
+	if (xtpg->is_hls) {
+		u32 fmt = 0;
 
-	if (xtpg->vtc) {
-		struct xvtc_config config = {
-			.hblank_start = width,
-			.hsync_start = width + 1,
-			.vblank_start = height,
-			.vsync_start = height + 1,
-		};
-		unsigned int htotal;
-		unsigned int vtotal;
-
-		htotal = min_t(unsigned int, XVTC_MAX_HSIZE,
-			       v4l2_ctrl_g_ctrl(xtpg->hblank) + width);
-		vtotal = min_t(unsigned int, XVTC_MAX_VSIZE,
-			       v4l2_ctrl_g_ctrl(xtpg->vblank) + height);
-
-		config.hsync_end = htotal - 1;
-		config.hsize = htotal;
-		config.vsync_end = vtotal - 1;
-		config.vsize = vtotal;
-
-		xvtc_generator_start(xtpg->vtc, &config);
+		switch (xtpg->formats[0].code) {
+		case MEDIA_BUS_FMT_VYYUYY8_1X24:
+		case MEDIA_BUS_FMT_VYYUYY10_4X20:
+			fmt = XTPG_HLS_COLOR_FORMAT_YUV_420;
+			break;
+		case MEDIA_BUS_FMT_UYVY8_1X16:
+		case MEDIA_BUS_FMT_UYVY10_1X20:
+			fmt = XTPG_HLS_COLOR_FORMAT_YUV_422;
+			break;
+		case MEDIA_BUS_FMT_VUY8_1X24:
+		case MEDIA_BUS_FMT_VUY10_1X30:
+			fmt = XTPG_HLS_COLOR_FORMAT_YUV_444;
+			break;
+		case MEDIA_BUS_FMT_RBG888_1X24:
+		case MEDIA_BUS_FMT_RBG101010_1X30:
+			fmt = XTPG_HLS_COLOR_FORMAT_RGB;
+			break;
+		}
+		xvip_write(&xtpg->xvip, XTPG_HLS_COLOR_FORMAT, fmt);
+		xvip_write(&xtpg->xvip, XHLS_REG_COLS, width);
+		xvip_write(&xtpg->xvip, XHLS_REG_ROWS, height);
+	} else {
+		xvip_set_frame_size(&xtpg->xvip, &xtpg->formats[0]);
 	}
 
+	if (xtpg->vtc)
+		xtpg_config_vtc(xtpg, width, height);
 	/*
 	 * Configure the bayer phase and video timing mux based on the
 	 * operation mode (passthrough or test pattern generation). The test
@@ -215,7 +348,11 @@
 	 */
 	mutex_lock(xtpg->ctrl_handler.lock);
 
-	xvip_clr_and_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
+	if (xtpg->is_hls)
+		xvip_write(&xtpg->xvip, XTPG_HLS_BG_PATTERN,
+			   xtpg->pattern->cur.val);
+	else
+		xvip_clr_and_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
 			 XTPG_PATTERN_MASK, xtpg->pattern->cur.val);
 
 	/*
@@ -229,18 +366,26 @@
 
 	mutex_unlock(xtpg->ctrl_handler.lock);
 
-	/*
-	 * For TPG v5.0, the bayer phase needs to be off for the pass through
-	 * mode, otherwise the external input would be subsampled.
-	 */
-	bayer_phase = passthrough ? XTPG_BAYER_PHASE_OFF
-		    : xtpg_get_bayer_phase(xtpg->formats[0].code);
-	xvip_write(&xtpg->xvip, XTPG_BAYER_PHASE, bayer_phase);
-
 	if (xtpg->vtmux_gpio)
 		gpiod_set_value_cansleep(xtpg->vtmux_gpio, !passthrough);
 
-	xvip_start(&xtpg->xvip);
+	if (xtpg->is_hls) {
+		xvip_set(&xtpg->xvip, XTPG_HLS_ENABLE_INPUT,
+			 XTPG_HLS_USE_INPUT_VID_STREAM);
+		xvip_set(&xtpg->xvip, XVIP_CTRL_CONTROL,
+			 XHLS_REG_CTRL_AUTO_RESTART |
+			 XVIP_CTRL_CONTROL_SW_ENABLE);
+	} else {
+		/*
+		 * For TPG v5.0, the bayer phase needs to be off for the pass
+		 * through mode, otherwise the external input would
+		 * be subsampled.
+		 */
+		bayer_phase = passthrough ? XTPG_BAYER_PHASE_OFF
+			    : xtpg_get_bayer_phase(xtpg->formats[0].code);
+		xvip_write(&xtpg->xvip, XTPG_BAYER_PHASE, bayer_phase);
+		xvip_start(&xtpg->xvip);
+	}
 
 	return 0;
 }
@@ -254,14 +399,22 @@
 		      struct v4l2_subdev_pad_config *cfg,
 		      unsigned int pad, u32 which)
 {
+	struct v4l2_mbus_framefmt *format;
+
 	switch (which) {
 	case V4L2_SUBDEV_FORMAT_TRY:
-		return v4l2_subdev_get_try_format(&xtpg->xvip.subdev, cfg, pad);
+		format = v4l2_subdev_get_try_format(&xtpg->xvip.subdev, cfg,
+						    pad);
+		break;
 	case V4L2_SUBDEV_FORMAT_ACTIVE:
-		return &xtpg->formats[pad];
+		format = &xtpg->formats[pad];
+		break;
 	default:
-		return NULL;
+		format = NULL;
+		break;
 	}
+
+	return format;
 }
 
 static int xtpg_get_format(struct v4l2_subdev *subdev,
@@ -269,8 +422,13 @@
 			   struct v4l2_subdev_format *fmt)
 {
 	struct xtpg_device *xtpg = to_tpg(subdev);
+	struct v4l2_mbus_framefmt *format;
+
+	format = __xtpg_get_pad_format(xtpg, cfg, fmt->pad, fmt->which);
+	if (!format)
+		return -EINVAL;
 
-	fmt->format = *__xtpg_get_pad_format(xtpg, cfg, fmt->pad, fmt->which);
+	fmt->format = *format;
 
 	return 0;
 }
@@ -284,6 +442,8 @@
 	u32 bayer_phase;
 
 	__format = __xtpg_get_pad_format(xtpg, cfg, fmt->pad, fmt->which);
+	if (!__format)
+		return -EINVAL;
 
 	/* In two pads mode the source pad format is always identical to the
 	 * sink pad format.
@@ -300,13 +460,35 @@
 			__format->code = fmt->format.code;
 	}
 
-	xvip_set_format_size(__format, fmt);
+	if (xtpg->is_hls) {
+		switch (fmt->format.code) {
+		case MEDIA_BUS_FMT_VYYUYY8_1X24:
+		case MEDIA_BUS_FMT_VYYUYY10_4X20:
+		case MEDIA_BUS_FMT_UYVY8_1X16:
+		case MEDIA_BUS_FMT_UYVY10_1X20:
+		case MEDIA_BUS_FMT_VUY8_1X24:
+		case MEDIA_BUS_FMT_VUY10_1X30:
+		case MEDIA_BUS_FMT_RBG888_1X24:
+		case MEDIA_BUS_FMT_RBG101010_1X30:
+			__format->code = fmt->format.code;
+			break;
+		default:
+			__format->code = xtpg->default_format.code;
+		}
+	}
+
+	__format->width = clamp_t(unsigned int, fmt->format.width,
+				  XTPG_MIN_WIDTH, xtpg->max_width);
+	__format->height = clamp_t(unsigned int, fmt->format.height,
+				   XTPG_MIN_HEIGHT, xtpg->max_height);
 
 	fmt->format = *__format;
 
 	/* Propagate the format to the source pad. */
 	if (xtpg->npads == 2) {
 		__format = __xtpg_get_pad_format(xtpg, cfg, 1, fmt->which);
+		if (!__format)
+			return -EINVAL;
 		*__format = fmt->format;
 	}
 
@@ -322,6 +504,7 @@
 				struct v4l2_subdev_frame_size_enum *fse)
 {
 	struct v4l2_mbus_framefmt *format;
+	struct xtpg_device *xtpg = to_tpg(subdev);
 
 	format = v4l2_subdev_get_try_format(subdev, cfg, fse->pad);
 
@@ -330,12 +513,13 @@
 
 	/* Min / max values for pad 0 is always fixed in both one and two pads
 	 * modes. In two pads mode, the source pad(= 1) size is identical to
-	 * the sink pad size */
+	 * the sink pad size.
+	 */
 	if (fse->pad == 0) {
-		fse->min_width = XVIP_MIN_WIDTH;
-		fse->max_width = XVIP_MAX_WIDTH;
-		fse->min_height = XVIP_MIN_HEIGHT;
-		fse->max_height = XVIP_MAX_HEIGHT;
+		fse->min_width = XTPG_MIN_WIDTH;
+		fse->max_width = xtpg->max_width;
+		fse->min_height = XTPG_MIN_HEIGHT;
+		fse->max_height = xtpg->max_height;
 	} else {
 		fse->min_width = format->width;
 		fse->max_width = format->width;
@@ -374,8 +558,12 @@
 						ctrl_handler);
 	switch (ctrl->id) {
 	case V4L2_CID_TEST_PATTERN:
-		xvip_clr_and_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
-				 XTPG_PATTERN_MASK, ctrl->val);
+		if (xtpg->is_hls)
+			xvip_write(&xtpg->xvip, XTPG_HLS_BG_PATTERN,
+				   ctrl->val);
+		else
+			xvip_clr_and_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
+					 XTPG_PATTERN_MASK, ctrl->val);
 		return 0;
 	case V4L2_CID_XILINX_TPG_CROSS_HAIRS:
 		xvip_clr_or_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
@@ -386,10 +574,13 @@
 				XTPG_PATTERN_CONTROL_MOVING_BOX, ctrl->val);
 		return 0;
 	case V4L2_CID_XILINX_TPG_COLOR_MASK:
-		xvip_clr_and_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
-				 XTPG_PATTERN_CONTROL_COLOR_MASK_MASK,
-				 ctrl->val <<
-				 XTPG_PATTERN_CONTROL_COLOR_MASK_SHIFT);
+		if (xtpg->is_hls)
+			xvip_write(&xtpg->xvip, XTPG_HLS_MASK_ID, ctrl->val);
+		else
+			xvip_clr_and_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
+				      XTPG_PATTERN_CONTROL_COLOR_MASK_MASK,
+				      ctrl->val <<
+				      XTPG_PATTERN_CONTROL_COLOR_MASK_SHIFT);
 		return 0;
 	case V4L2_CID_XILINX_TPG_STUCK_PIXEL:
 		xvip_clr_or_set(&xtpg->xvip, XTPG_PATTERN_CONTROL,
@@ -404,43 +595,85 @@
 				XTPG_PATTERN_CONTROL_MOTION, ctrl->val);
 		return 0;
 	case V4L2_CID_XILINX_TPG_MOTION_SPEED:
-		xvip_write(&xtpg->xvip, XTPG_MOTION_SPEED, ctrl->val);
+		if (xtpg->is_hls)
+			xvip_write(&xtpg->xvip, XTPG_HLS_MOTION_SPEED,
+				   ctrl->val);
+		else
+			xvip_write(&xtpg->xvip, XTPG_MOTION_SPEED, ctrl->val);
 		return 0;
 	case V4L2_CID_XILINX_TPG_CROSS_HAIR_ROW:
-		xvip_clr_and_set(&xtpg->xvip, XTPG_CROSS_HAIRS,
-				 XTPG_CROSS_HAIRS_ROW_MASK,
-				 ctrl->val << XTPG_CROSS_HAIRS_ROW_SHIFT);
+		if (xtpg->is_hls)
+			xvip_write(&xtpg->xvip, XTPG_HLS_CROSS_HAIR_HOR,
+				    ctrl->val);
+		else
+			xvip_clr_and_set(&xtpg->xvip, XTPG_CROSS_HAIRS,
+					 XTPG_CROSS_HAIRS_ROW_MASK,
+					 ctrl->val <<
+					 XTPG_CROSS_HAIRS_ROW_SHIFT);
 		return 0;
 	case V4L2_CID_XILINX_TPG_CROSS_HAIR_COLUMN:
-		xvip_clr_and_set(&xtpg->xvip, XTPG_CROSS_HAIRS,
-				 XTPG_CROSS_HAIRS_COLUMN_MASK,
-				 ctrl->val << XTPG_CROSS_HAIRS_COLUMN_SHIFT);
+		if (xtpg->is_hls)
+			xvip_write(&xtpg->xvip, XTPG_HLS_CROSS_HAIR_VER,
+				   ctrl->val);
+		else
+			xvip_clr_and_set(&xtpg->xvip, XTPG_CROSS_HAIRS,
+					 XTPG_CROSS_HAIRS_COLUMN_MASK,
+					 ctrl->val <<
+					 XTPG_CROSS_HAIRS_COLUMN_SHIFT);
 		return 0;
 	case V4L2_CID_XILINX_TPG_ZPLATE_HOR_START:
-		xvip_clr_and_set(&xtpg->xvip, XTPG_ZPLATE_HOR_CONTROL,
-				 XTPG_ZPLATE_START_MASK,
-				 ctrl->val << XTPG_ZPLATE_START_SHIFT);
+		if (xtpg->is_hls)
+			xvip_write(&xtpg->xvip, XTPG_HLS_ZPLATE_HOR_CNTL_START,
+				   ctrl->val);
+		else
+			xvip_clr_and_set(&xtpg->xvip, XTPG_ZPLATE_HOR_CONTROL,
+					 XTPG_ZPLATE_START_MASK,
+					 ctrl->val << XTPG_ZPLATE_START_SHIFT);
 		return 0;
 	case V4L2_CID_XILINX_TPG_ZPLATE_HOR_SPEED:
-		xvip_clr_and_set(&xtpg->xvip, XTPG_ZPLATE_HOR_CONTROL,
-				 XTPG_ZPLATE_SPEED_MASK,
-				 ctrl->val << XTPG_ZPLATE_SPEED_SHIFT);
+		if (xtpg->is_hls)
+			xvip_write(&xtpg->xvip, XTPG_HLS_ZPLATE_HOR_CNTL_DELTA,
+				   ctrl->val);
+		else
+			xvip_clr_and_set(&xtpg->xvip, XTPG_ZPLATE_HOR_CONTROL,
+					 XTPG_ZPLATE_SPEED_MASK,
+					 ctrl->val << XTPG_ZPLATE_SPEED_SHIFT);
 		return 0;
 	case V4L2_CID_XILINX_TPG_ZPLATE_VER_START:
-		xvip_clr_and_set(&xtpg->xvip, XTPG_ZPLATE_VER_CONTROL,
-				 XTPG_ZPLATE_START_MASK,
-				 ctrl->val << XTPG_ZPLATE_START_SHIFT);
+		if (xtpg->is_hls)
+			xvip_write(&xtpg->xvip, XTPG_HLS_ZPLATE_VER_CNTL_START,
+				   ctrl->val);
+		else
+			xvip_clr_and_set(&xtpg->xvip, XTPG_ZPLATE_VER_CONTROL,
+					 XTPG_ZPLATE_START_MASK,
+					 ctrl->val << XTPG_ZPLATE_START_SHIFT);
 		return 0;
 	case V4L2_CID_XILINX_TPG_ZPLATE_VER_SPEED:
-		xvip_clr_and_set(&xtpg->xvip, XTPG_ZPLATE_VER_CONTROL,
-				 XTPG_ZPLATE_SPEED_MASK,
-				 ctrl->val << XTPG_ZPLATE_SPEED_SHIFT);
+		if (xtpg->is_hls)
+			xvip_write(&xtpg->xvip, XTPG_HLS_ZPLATE_VER_CNTL_DELTA,
+				   ctrl->val);
+		else
+			xvip_clr_and_set(&xtpg->xvip, XTPG_ZPLATE_VER_CONTROL,
+					 XTPG_ZPLATE_SPEED_MASK,
+					 ctrl->val << XTPG_ZPLATE_SPEED_SHIFT);
 		return 0;
 	case V4L2_CID_XILINX_TPG_BOX_SIZE:
-		xvip_write(&xtpg->xvip, XTPG_BOX_SIZE, ctrl->val);
+		if (xtpg->is_hls)
+			xvip_write(&xtpg->xvip, XTPG_HLS_BOX_SIZE, ctrl->val);
+		else
+			xvip_write(&xtpg->xvip, XTPG_BOX_SIZE, ctrl->val);
 		return 0;
 	case V4L2_CID_XILINX_TPG_BOX_COLOR:
-		xvip_write(&xtpg->xvip, XTPG_BOX_COLOR, ctrl->val);
+		if (xtpg->is_hls) {
+			xvip_write(&xtpg->xvip, XTPG_HLS_BOX_COLOR_RED_CB,
+				   ctrl->val >> 16);
+			xvip_write(&xtpg->xvip, XTPG_HLS_BOX_COLOR_GREEN_CR,
+				   ctrl->val >> 8);
+			xvip_write(&xtpg->xvip, XTPG_HLS_BOX_COLOR_BLUE_Y,
+				   ctrl->val);
+		} else {
+			xvip_write(&xtpg->xvip, XTPG_BOX_COLOR, ctrl->val);
+		}
 		return 0;
 	case V4L2_CID_XILINX_TPG_STUCK_PIXEL_THRESH:
 		xvip_write(&xtpg->xvip, XTPG_STUCK_PIXEL_THRESH, ctrl->val);
@@ -448,6 +681,9 @@
 	case V4L2_CID_XILINX_TPG_NOISE_GAIN:
 		xvip_write(&xtpg->xvip, XTPG_NOISE_GAIN, ctrl->val);
 		return 0;
+	case V4L2_CID_XILINX_TPG_HLS_FG_PATTERN:
+		xvip_write(&xtpg->xvip, XTPG_HLS_FG_PATTERN, ctrl->val);
+		return 0;
 	}
 
 	return 0;
@@ -461,6 +697,8 @@
 };
 
 static const struct v4l2_subdev_video_ops xtpg_video_ops = {
+	.g_frame_interval = xtpg_g_frame_interval,
+	.s_frame_interval = xtpg_s_frame_interval,
 	.s_stream = xtpg_s_stream,
 };
 
@@ -505,60 +743,51 @@
 	"Black/White Checker Board",
 };
 
-static struct v4l2_ctrl_config xtpg_ctrls[] = {
+static const char *const xtpg_hls_pattern_strings[] = {
+	"Passthrough",
+	"Horizontal Ramp",
+	"Vertical Ramp",
+	"Temporal Ramp",
+	"Solid Red",
+	"Solid Green",
+	"Solid Blue",
+	"Solid Black",
+	"Solid White",
+	"Color Bars",
+	"Zone Plate",
+	"Tartan Color Bars",
+	"Cross Hatch",
+	"Color Sweep",
+	"Vertical/Horizontal Ramps",
+	"Black/White Checker Board",
+	"PseudoRandom",
+};
+
+static const char *const xtpg_hls_fg_strings[] = {
+	"No Overlay",
+	"Moving Box",
+	"Cross Hairs",
+};
+
+static const struct v4l2_ctrl_config xtpg_hls_fg_ctrl = {
+	.ops	= &xtpg_ctrl_ops,
+	.id     = V4L2_CID_XILINX_TPG_HLS_FG_PATTERN,
+	.name   = "Test Pattern: Foreground Pattern",
+	.type   = V4L2_CTRL_TYPE_MENU,
+	.min	= 0,
+	.max	= ARRAY_SIZE(xtpg_hls_fg_strings) - 1,
+	.qmenu	= xtpg_hls_fg_strings,
+};
+
+static struct v4l2_ctrl_config xtpg_common_ctrls[] = {
 	{
-		.ops	= &xtpg_ctrl_ops,
-		.id	= V4L2_CID_XILINX_TPG_CROSS_HAIRS,
-		.name	= "Test Pattern: Cross Hairs",
-		.type	= V4L2_CTRL_TYPE_BOOLEAN,
-		.min	= false,
-		.max	= true,
-		.step	= 1,
-		.def	= 0,
-	}, {
-		.ops	= &xtpg_ctrl_ops,
-		.id	= V4L2_CID_XILINX_TPG_MOVING_BOX,
-		.name	= "Test Pattern: Moving Box",
-		.type	= V4L2_CTRL_TYPE_BOOLEAN,
-		.min	= false,
-		.max	= true,
-		.step	= 1,
-		.def	= 0,
-	}, {
-		.ops	= &xtpg_ctrl_ops,
-		.id	= V4L2_CID_XILINX_TPG_COLOR_MASK,
-		.name	= "Test Pattern: Color Mask",
-		.type	= V4L2_CTRL_TYPE_BITMASK,
-		.min	= 0,
-		.max	= 0xf,
-		.def	= 0,
-	}, {
-		.ops	= &xtpg_ctrl_ops,
-		.id	= V4L2_CID_XILINX_TPG_STUCK_PIXEL,
-		.name	= "Test Pattern: Stuck Pixel",
-		.type	= V4L2_CTRL_TYPE_BOOLEAN,
-		.min	= false,
-		.max	= true,
-		.step	= 1,
-		.def	= 0,
-	}, {
-		.ops	= &xtpg_ctrl_ops,
-		.id	= V4L2_CID_XILINX_TPG_NOISE,
-		.name	= "Test Pattern: Noise",
-		.type	= V4L2_CTRL_TYPE_BOOLEAN,
-		.min	= false,
-		.max	= true,
-		.step	= 1,
-		.def	= 0,
-	}, {
-		.ops	= &xtpg_ctrl_ops,
-		.id	= V4L2_CID_XILINX_TPG_MOTION,
-		.name	= "Test Pattern: Motion",
-		.type	= V4L2_CTRL_TYPE_BOOLEAN,
-		.min	= false,
-		.max	= true,
-		.step	= 1,
-		.def	= 0,
+		.ops    = &xtpg_ctrl_ops,
+		.id     = V4L2_CID_XILINX_TPG_COLOR_MASK,
+		.name   = "Test Pattern: Color Mask",
+		.type   = V4L2_CTRL_TYPE_BITMASK,
+		.min    = 0,
+		.max    = 0x7,
+		.def    = 0,
 	}, {
 		.ops	= &xtpg_ctrl_ops,
 		.id	= V4L2_CID_XILINX_TPG_MOTION_SPEED,
@@ -642,12 +871,61 @@
 	}, {
 		.ops	= &xtpg_ctrl_ops,
 		.id	= V4L2_CID_XILINX_TPG_BOX_COLOR,
-		.name	= "Test Pattern: Box Color(RGB)",
+		.name	= "Test Pattern: Box Color(RGB/YCbCr)",
 		.type	= V4L2_CTRL_TYPE_INTEGER,
 		.min	= 0,
 		.max	= (1 << 24) - 1,
 		.step	= 1,
 		.def	= 0,
+	},
+};
+
+static struct v4l2_ctrl_config xtpg_ctrls[] = {
+	{
+		.ops	= &xtpg_ctrl_ops,
+		.id	= V4L2_CID_XILINX_TPG_CROSS_HAIRS,
+		.name	= "Test Pattern: Cross Hairs",
+		.type	= V4L2_CTRL_TYPE_BOOLEAN,
+		.min	= false,
+		.max	= true,
+		.step	= 1,
+		.def	= 0,
+	}, {
+		.ops	= &xtpg_ctrl_ops,
+		.id	= V4L2_CID_XILINX_TPG_MOVING_BOX,
+		.name	= "Test Pattern: Moving Box",
+		.type	= V4L2_CTRL_TYPE_BOOLEAN,
+		.min	= false,
+		.max	= true,
+		.step	= 1,
+		.def	= 0,
+	}, {
+		.ops	= &xtpg_ctrl_ops,
+		.id	= V4L2_CID_XILINX_TPG_STUCK_PIXEL,
+		.name	= "Test Pattern: Stuck Pixel",
+		.type	= V4L2_CTRL_TYPE_BOOLEAN,
+		.min	= false,
+		.max	= true,
+		.step	= 1,
+		.def	= 0,
+	}, {
+		.ops	= &xtpg_ctrl_ops,
+		.id	= V4L2_CID_XILINX_TPG_NOISE,
+		.name	= "Test Pattern: Noise",
+		.type	= V4L2_CTRL_TYPE_BOOLEAN,
+		.min	= false,
+		.max	= true,
+		.step	= 1,
+		.def	= 0,
+	}, {
+		.ops	= &xtpg_ctrl_ops,
+		.id	= V4L2_CID_XILINX_TPG_MOTION,
+		.name	= "Test Pattern: Motion",
+		.type	= V4L2_CTRL_TYPE_BOOLEAN,
+		.min	= false,
+		.max	= true,
+		.step	= 1,
+		.def	= 0,
 	}, {
 		.ops	= &xtpg_ctrl_ops,
 		.id	= V4L2_CID_XILINX_TPG_STUCK_PIXEL_THRESH,
@@ -713,6 +991,49 @@
 	struct device_node *port;
 	unsigned int nports = 0;
 	bool has_endpoint = false;
+	int ret;
+
+	if (!of_device_is_compatible(dev->of_node, "xlnx,v-tpg-5.0"))
+		xtpg->is_hls = true;
+
+	ret = of_property_read_u32(node, "xlnx,max-height",
+				   &xtpg->max_height);
+	if (ret < 0) {
+		if (of_device_is_compatible(dev->of_node, "xlnx,v-tpg-8.0")) {
+			dev_err(dev, "xlnx,max-height dt property is missing!");
+			return -EINVAL;
+		}
+		xtpg->max_height = XTPG_MAX_HEIGHT;
+	} else if (xtpg->max_height > XTPG_MAX_HEIGHT ||
+		   xtpg->max_height < XTPG_MIN_HEIGHT) {
+		dev_err(dev, "Invalid height in dt");
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32(node, "xlnx,max-width",
+				   &xtpg->max_width);
+	if (ret < 0) {
+		if (of_device_is_compatible(dev->of_node, "xlnx,v-tpg-8.0")) {
+			dev_err(dev, "xlnx,max-width dt property is missing!");
+			return -EINVAL;
+		}
+		xtpg->max_width = XTPG_MAX_WIDTH;
+	} else if (xtpg->max_width > XTPG_MAX_WIDTH ||
+		   xtpg->max_width < XTPG_MIN_WIDTH) {
+		dev_err(dev, "Invalid width in dt");
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32(node, "xlnx,ppc",
+				   &xtpg->ppc);
+	if (ret < 0) {
+		xtpg->ppc = XTPG_MIN_PPC;
+		dev_dbg(dev, "failed to read ppc in dt\n");
+	} else if ((xtpg->ppc != 1) && (xtpg->ppc != 2) &&
+			(xtpg->ppc != 4) && (xtpg->ppc != 8)) {
+		dev_err(dev, "Invalid ppc config in dt\n");
+		return -EINVAL;
+	}
 
 	ports = of_get_child_by_name(node, "ports");
 	if (ports == NULL)
@@ -769,6 +1090,7 @@
 	struct v4l2_subdev *subdev;
 	struct xtpg_device *xtpg;
 	u32 i, bayer_phase;
+	u32 npatterns;
 	int ret;
 
 	xtpg = devm_kzalloc(&pdev->dev, sizeof(*xtpg), GFP_KERNEL);
@@ -792,14 +1114,29 @@
 		goto error_resource;
 	}
 
+	if (xtpg->is_hls) {
+		xtpg->rst_gpio = devm_gpiod_get(&pdev->dev, "reset",
+						   GPIOD_OUT_HIGH);
+		if (IS_ERR(xtpg->rst_gpio)) {
+			ret = PTR_ERR(xtpg->rst_gpio);
+			goto error_resource;
+		}
+	}
+
 	xtpg->vtc = xvtc_of_get(pdev->dev.of_node);
 	if (IS_ERR(xtpg->vtc)) {
 		ret = PTR_ERR(xtpg->vtc);
 		goto error_resource;
 	}
 
-	/* Reset and initialize the core */
-	xvip_reset(&xtpg->xvip);
+	/*
+	 * Reset and initialize the core. For TPG HLS version there
+	 * is no SW_RESET bit hence using GPIO based reset.
+	 */
+	if (xtpg->is_hls)
+		gpiod_set_value_cansleep(xtpg->rst_gpio, 0x0);
+	else
+		xvip_reset(&xtpg->xvip);
 
 	/* Initialize V4L2 subdevice and media entity. Pad numbers depend on the
 	 * number of pads.
@@ -815,11 +1152,23 @@
 	xtpg->default_format.code = xtpg->vip_format->code;
 	xtpg->default_format.field = V4L2_FIELD_NONE;
 	xtpg->default_format.colorspace = V4L2_COLORSPACE_SRGB;
-	xvip_get_frame_size(&xtpg->xvip, &xtpg->default_format);
 
-	bayer_phase = xtpg_get_bayer_phase(xtpg->vip_format->code);
-	if (bayer_phase != XTPG_BAYER_PHASE_OFF)
-		xtpg->bayer = true;
+	if (xtpg->is_hls) {
+		npatterns = ARRAY_SIZE(xtpg_hls_pattern_strings);
+		xtpg->default_format.width = xvip_read(&xtpg->xvip,
+						       XHLS_REG_COLS);
+		xtpg->default_format.height = xvip_read(&xtpg->xvip,
+							XHLS_REG_ROWS);
+	} else {
+		npatterns = ARRAY_SIZE(xtpg_pattern_strings);
+		xvip_get_frame_size(&xtpg->xvip, &xtpg->default_format);
+	}
+
+	if (!xtpg->is_hls) {
+		bayer_phase = xtpg_get_bayer_phase(xtpg->vip_format->code);
+		if (bayer_phase != XTPG_BAYER_PHASE_OFF)
+			xtpg->bayer = true;
+	}
 
 	xtpg->formats[0] = xtpg->default_format;
 	if (xtpg->npads == 2)
@@ -839,7 +1188,13 @@
 	if (ret < 0)
 		goto error;
 
-	v4l2_ctrl_handler_init(&xtpg->ctrl_handler, 3 + ARRAY_SIZE(xtpg_ctrls));
+	if (xtpg->is_hls)
+		v4l2_ctrl_handler_init(&xtpg->ctrl_handler, 4 +
+				       ARRAY_SIZE(xtpg_common_ctrls));
+	else
+		v4l2_ctrl_handler_init(&xtpg->ctrl_handler, 3 +
+				       ARRAY_SIZE(xtpg_common_ctrls) +
+				       ARRAY_SIZE(xtpg_ctrls));
 
 	xtpg->vblank = v4l2_ctrl_new_std(&xtpg->ctrl_handler, &xtpg_ctrl_ops,
 					 V4L2_CID_VBLANK, XTPG_MIN_VBLANK,
@@ -847,19 +1202,41 @@
 	xtpg->hblank = v4l2_ctrl_new_std(&xtpg->ctrl_handler, &xtpg_ctrl_ops,
 					 V4L2_CID_HBLANK, XTPG_MIN_HBLANK,
 					 XTPG_MAX_HBLANK, 1, 100);
-	xtpg->pattern = v4l2_ctrl_new_std_menu_items(&xtpg->ctrl_handler,
-					&xtpg_ctrl_ops, V4L2_CID_TEST_PATTERN,
-					ARRAY_SIZE(xtpg_pattern_strings) - 1,
-					1, 9, xtpg_pattern_strings);
 
-	for (i = 0; i < ARRAY_SIZE(xtpg_ctrls); i++)
-		v4l2_ctrl_new_custom(&xtpg->ctrl_handler, &xtpg_ctrls[i], NULL);
+	if (xtpg->is_hls) {
+		xtpg->pattern =
+			v4l2_ctrl_new_std_menu_items(&xtpg->ctrl_handler,
+						     &xtpg_ctrl_ops,
+						     V4L2_CID_TEST_PATTERN,
+						     npatterns - 1,
+						     1, 9,
+						     xtpg_hls_pattern_strings);
+		v4l2_ctrl_new_custom(&xtpg->ctrl_handler,
+				     &xtpg_hls_fg_ctrl, NULL);
+	} else {
+		xtpg->pattern =
+			v4l2_ctrl_new_std_menu_items(&xtpg->ctrl_handler,
+						     &xtpg_ctrl_ops,
+						     V4L2_CID_TEST_PATTERN,
+						     npatterns - 1,
+						     1, 9,
+						     xtpg_pattern_strings);
+
+		for (i = 0; i < ARRAY_SIZE(xtpg_ctrls); i++)
+			v4l2_ctrl_new_custom(&xtpg->ctrl_handler,
+					     &xtpg_ctrls[i], NULL);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(xtpg_common_ctrls); i++)
+		v4l2_ctrl_new_custom(&xtpg->ctrl_handler,
+				     &xtpg_common_ctrls[i], NULL);
 
 	if (xtpg->ctrl_handler.error) {
 		dev_err(&pdev->dev, "failed to add controls\n");
 		ret = xtpg->ctrl_handler.error;
 		goto error;
 	}
+
 	subdev->ctrl_handler = &xtpg->ctrl_handler;
 
 	xtpg_update_pattern_control(xtpg, true, true);
@@ -872,7 +1249,12 @@
 
 	platform_set_drvdata(pdev, xtpg);
 
-	xvip_print_version(&xtpg->xvip);
+	if (!xtpg->is_hls)
+		xvip_print_version(&xtpg->xvip);
+
+	/* Initialize default frame interval */
+	xtpg->fi_n = 1;
+	xtpg->fi_d = 30;
 
 	ret = v4l2_async_register_subdev(subdev);
 	if (ret < 0) {
@@ -909,6 +1291,8 @@
 
 static const struct of_device_id xtpg_of_id_table[] = {
 	{ .compatible = "xlnx,v-tpg-5.0" },
+	{ .compatible = "xlnx,v-tpg-7.0" },
+	{ .compatible = "xlnx,v-tpg-8.0" },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, xtpg_of_id_table);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/xilinx-vip.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/xilinx-vip.c
@@ -24,22 +24,102 @@
  */
 
 static const struct xvip_video_format xvip_video_formats[] = {
+	{ XVIP_VF_YUV_420, 8, NULL, MEDIA_BUS_FMT_VYYUYY8_1X24,
+	  1, 12, V4L2_PIX_FMT_NV12, 2, 1, 1, 2 },
+	{ XVIP_VF_YUV_420, 8, NULL, MEDIA_BUS_FMT_VYYUYY8_1X24,
+	  1, 12, V4L2_PIX_FMT_NV12M, 2, 2, 1, 2 },
+	{ XVIP_VF_YUV_420, 10, NULL, MEDIA_BUS_FMT_VYYUYY10_4X20,
+	  1, 12, V4L2_PIX_FMT_XV15, 2, 1, 2, 2 },
+	{ XVIP_VF_YUV_420, 10, NULL, MEDIA_BUS_FMT_VYYUYY10_4X20,
+	  1, 12, V4L2_PIX_FMT_XV15M, 2, 2, 1, 2 },
+	{ XVIP_VF_YUV_420, 12, NULL, MEDIA_BUS_FMT_UYYVYY12_4X24,
+	  1, 12, V4L2_PIX_FMT_X012, 2, 1, 2, 2 },
+	{ XVIP_VF_YUV_420, 12, NULL, MEDIA_BUS_FMT_UYYVYY12_4X24,
+	  1, 12, V4L2_PIX_FMT_X012M, 2, 2, 1, 2 },
+	{ XVIP_VF_YUV_420, 16, NULL, MEDIA_BUS_FMT_UYYVYY16_4X32,
+	  2, 12, V4L2_PIX_FMT_X016, 2, 1, 2, 2 },
+	{ XVIP_VF_YUV_420, 16, NULL, MEDIA_BUS_FMT_UYYVYY16_4X32,
+	  2, 12, V4L2_PIX_FMT_X016M, 2, 2, 1, 2 },
 	{ XVIP_VF_YUV_422, 8, NULL, MEDIA_BUS_FMT_UYVY8_1X16,
-	  2, V4L2_PIX_FMT_YUYV },
+	  1, 16, V4L2_PIX_FMT_NV16, 2, 1, 1, 1 },
+	{ XVIP_VF_YUV_422, 8, NULL, MEDIA_BUS_FMT_UYVY8_1X16,
+	  1, 16, V4L2_PIX_FMT_NV16M, 2, 2, 1, 1 },
+	{ XVIP_VF_YUV_422, 8, NULL, MEDIA_BUS_FMT_UYVY8_1X16,
+	  2, 16, V4L2_PIX_FMT_YUYV, 1, 1, 2, 1 },
+	{ XVIP_VF_VUY_422, 8, NULL, MEDIA_BUS_FMT_UYVY8_1X16,
+	  2, 16, V4L2_PIX_FMT_UYVY, 1, 1, 2, 1 },
+	{ XVIP_VF_YUV_422, 10, NULL, MEDIA_BUS_FMT_UYVY10_1X20,
+	  1, 16, V4L2_PIX_FMT_XV20, 2, 1, 2, 1 },
+	{ XVIP_VF_YUV_422, 10, NULL, MEDIA_BUS_FMT_UYVY10_1X20,
+	  1, 16, V4L2_PIX_FMT_XV20M, 2, 2, 1, 1 },
+	{ XVIP_VF_YUV_422, 12, NULL, MEDIA_BUS_FMT_UYVY12_1X24,
+	  1, 16, V4L2_PIX_FMT_X212, 2, 1, 2, 1 },
+	{ XVIP_VF_YUV_422, 12, NULL, MEDIA_BUS_FMT_UYVY12_1X24,
+	  1, 16, V4L2_PIX_FMT_X212M, 2, 2, 1, 1 },
+	{ XVIP_VF_YUV_422, 16, NULL, MEDIA_BUS_FMT_UYVY16_2X32,
+	  2, 16, V4L2_PIX_FMT_X216, 2, 1, 2, 1 },
+	{ XVIP_VF_YUV_422, 16, NULL, MEDIA_BUS_FMT_UYVY16_2X32,
+	  2, 16, V4L2_PIX_FMT_X216M, 2, 2, 1, 1 },
 	{ XVIP_VF_YUV_444, 8, NULL, MEDIA_BUS_FMT_VUY8_1X24,
-	  3, V4L2_PIX_FMT_YUV444 },
+	  3, 24, V4L2_PIX_FMT_VUY24, 1, 1, 1, 1 },
+	{ XVIP_VF_YUVX, 8, NULL, MEDIA_BUS_FMT_VUY8_1X24,
+	  4, 32, V4L2_PIX_FMT_XVUY32, 1, 1, 1, 1 },
+	{ XVIP_VF_YUVX, 10, NULL, MEDIA_BUS_FMT_VUY10_1X30,
+	  3, 32, V4L2_PIX_FMT_XVUY10, 1, 1, 1, 1 },
+	{ XVIP_VF_YUV_444, 12, NULL, MEDIA_BUS_FMT_VUY12_1X36,
+	  1, 24, V4L2_PIX_FMT_X412, 1, 1, 1, 1 },
+	{ XVIP_VF_YUV_444, 12, NULL, MEDIA_BUS_FMT_VUY12_1X36,
+	  1, 24, V4L2_PIX_FMT_X412M, 1, 1, 1, 1 },
+	{ XVIP_VF_YUV_444, 16, NULL, MEDIA_BUS_FMT_VUY16_1X48,
+	  2, 24, V4L2_PIX_FMT_X416, 1, 1, 1, 1 },
+	{ XVIP_VF_YUV_444, 16, NULL, MEDIA_BUS_FMT_VUY16_1X48,
+	  2, 24, V4L2_PIX_FMT_X416M, 1, 1, 1, 1 },
+	{ XVIP_VF_RBG, 8, NULL, MEDIA_BUS_FMT_RBG888_1X24,
+	  3, 24, V4L2_PIX_FMT_BGR24, 1, 1, 1, 1 },
 	{ XVIP_VF_RBG, 8, NULL, MEDIA_BUS_FMT_RBG888_1X24,
-	  3, 0 },
+	  3, 24, V4L2_PIX_FMT_RGB24, 1, 1, 1, 1 },
+	{ XVIP_VF_BGRX, 8, NULL, MEDIA_BUS_FMT_RBG888_1X24,
+	  4, 32, V4L2_PIX_FMT_BGRX32, 1, 1, 1, 1 },
+	{ XVIP_VF_XRGB, 8, NULL, MEDIA_BUS_FMT_RBG888_1X24,
+	  4, 32, V4L2_PIX_FMT_XBGR32, 1, 1, 1, 1 },
+	{ XVIP_VF_XBGR, 10, NULL, MEDIA_BUS_FMT_RBG101010_1X30,
+	  3, 32, V4L2_PIX_FMT_XBGR30, 1, 1, 1, 1 },
+	{ XVIP_VF_XBGR, 12, NULL, MEDIA_BUS_FMT_RBG121212_1X36,
+	  3, 40, V4L2_PIX_FMT_XBGR40, 1, 1, 1, 1 },
+	{ XVIP_VF_RBG, 16, NULL, MEDIA_BUS_FMT_RBG161616_1X48,
+	  6, 48, V4L2_PIX_FMT_BGR48, 1, 1, 1, 1 },
 	{ XVIP_VF_MONO_SENSOR, 8, "mono", MEDIA_BUS_FMT_Y8_1X8,
-	  1, V4L2_PIX_FMT_GREY },
+	  1, 8, V4L2_PIX_FMT_GREY, 1, 1, 1, 1 },
+	{ XVIP_VF_Y_GREY, 10, NULL, MEDIA_BUS_FMT_Y10_1X10,
+	  1, 32, V4L2_PIX_FMT_XY10, 1, 1, 1, 1 },
+	{ XVIP_VF_Y_GREY, 12, NULL, MEDIA_BUS_FMT_Y12_1X12,
+	  1, 12, V4L2_PIX_FMT_XY12, 1, 1, 1, 1 },
+	{ XVIP_VF_Y_GREY, 16, NULL, MEDIA_BUS_FMT_Y16_1X16,
+	  2, 16, V4L2_PIX_FMT_Y16, 1, 1, 1, 1 },
 	{ XVIP_VF_MONO_SENSOR, 8, "rggb", MEDIA_BUS_FMT_SRGGB8_1X8,
-	  1, V4L2_PIX_FMT_SRGGB8 },
+	  1, 8, V4L2_PIX_FMT_SGRBG8, 1, 1, 1, 1 },
 	{ XVIP_VF_MONO_SENSOR, 8, "grbg", MEDIA_BUS_FMT_SGRBG8_1X8,
-	  1, V4L2_PIX_FMT_SGRBG8 },
+	  1, 8, V4L2_PIX_FMT_SGRBG8, 1, 1, 1, 1 },
 	{ XVIP_VF_MONO_SENSOR, 8, "gbrg", MEDIA_BUS_FMT_SGBRG8_1X8,
-	  1, V4L2_PIX_FMT_SGBRG8 },
+	  1, 8, V4L2_PIX_FMT_SGBRG8, 1, 1, 1, 1 },
 	{ XVIP_VF_MONO_SENSOR, 8, "bggr", MEDIA_BUS_FMT_SBGGR8_1X8,
-	  1, V4L2_PIX_FMT_SBGGR8 },
+	  1, 8, V4L2_PIX_FMT_SBGGR8, 1, 1, 1, 1 },
+	{ XVIP_VF_MONO_SENSOR, 12, "rggb", MEDIA_BUS_FMT_SRGGB12_1X12,
+	  1, 12, V4L2_PIX_FMT_SRGGB12, 1, 1, 1, 1 },
+	{ XVIP_VF_MONO_SENSOR, 12, "grbg", MEDIA_BUS_FMT_SGRBG12_1X12,
+	  1, 12, V4L2_PIX_FMT_SGRBG12, 1, 1, 1, 1 },
+	{ XVIP_VF_MONO_SENSOR, 12, "gbrg", MEDIA_BUS_FMT_SGBRG12_1X12,
+	  1, 12, V4L2_PIX_FMT_SGBRG12, 1, 1, 1, 1 },
+	{ XVIP_VF_MONO_SENSOR, 12, "bggr", MEDIA_BUS_FMT_SBGGR12_1X12,
+	  1, 12, V4L2_PIX_FMT_SBGGR12, 1, 1, 1, 1 },
+	{ XVIP_VF_MONO_SENSOR, 16, "rggb", MEDIA_BUS_FMT_SRGGB16_1X16,
+	  1, 16, V4L2_PIX_FMT_SRGGB16, 1, 1, 1, 1 },
+	{ XVIP_VF_MONO_SENSOR, 16, "grbg", MEDIA_BUS_FMT_SGRBG16_1X16,
+	  1, 12, V4L2_PIX_FMT_SGRBG16, 1, 1, 1, 1 },
+	{ XVIP_VF_MONO_SENSOR, 16, "gbrg", MEDIA_BUS_FMT_SGBRG16_1X16,
+	  1, 12, V4L2_PIX_FMT_SGBRG16, 1, 1, 1, 1 },
+	{ XVIP_VF_MONO_SENSOR, 16, "bggr", MEDIA_BUS_FMT_SBGGR12_1X12,
+	  1, 12, V4L2_PIX_FMT_SBGGR16, 1, 1, 1, 1 },
 };
 
 /**
@@ -89,6 +169,87 @@
 EXPORT_SYMBOL_GPL(xvip_get_format_by_fourcc);
 
 /**
+ * xvip_bpl_scaling_factor - Retrieve bpl scaling factor for a 4CC
+ * @fourcc: the format 4CC
+ * @numerator: returning numerator of scaling factor
+ * @denominator: returning denominator of scaling factor
+ *
+ * Return: Return numerator and denominator values by address
+ */
+void xvip_bpl_scaling_factor(u32 fourcc, u32 *numerator, u32 *denominator)
+{
+	switch (fourcc) {
+	case V4L2_PIX_FMT_XY10:
+	case V4L2_PIX_FMT_XV15:
+	case V4L2_PIX_FMT_XV20:
+	case V4L2_PIX_FMT_XV15M:
+	case V4L2_PIX_FMT_XV20M:
+	case V4L2_PIX_FMT_XBGR30:
+	case V4L2_PIX_FMT_XVUY10:
+		*numerator = 10;
+		*denominator = 8;
+		break;
+	case V4L2_PIX_FMT_XBGR40:
+	case V4L2_PIX_FMT_XY12:
+	case V4L2_PIX_FMT_X012:
+	case V4L2_PIX_FMT_X012M:
+	case V4L2_PIX_FMT_X212:
+	case V4L2_PIX_FMT_X212M:
+	case V4L2_PIX_FMT_X412:
+	case V4L2_PIX_FMT_X412M:
+		*numerator = 12;
+		*denominator = 8;
+		break;
+	default:
+		*numerator = 1;
+		*denominator = 1;
+		break;
+	}
+}
+EXPORT_SYMBOL_GPL(xvip_bpl_scaling_factor);
+
+/**
+ * xvip_width_padding_factor - Retrieve width's padding factor for a 4CC
+ * @fourcc: the format 4CC
+ * @numerator: returning numerator of padding factor
+ * @denominator: returning denominator of padding factor
+ *
+ * Return: Return numerator and denominator values by address
+ */
+void xvip_width_padding_factor(u32 fourcc, u32 *numerator, u32 *denominator)
+{
+	switch (fourcc) {
+	case V4L2_PIX_FMT_XY10:
+	case V4L2_PIX_FMT_XV15:
+	case V4L2_PIX_FMT_XV20:
+	case V4L2_PIX_FMT_XV15M:
+	case V4L2_PIX_FMT_XV20M:
+	case V4L2_PIX_FMT_XBGR30:
+	case V4L2_PIX_FMT_XVUY10:
+		/* 32 bits are required per 30 bits of data */
+		*numerator = 32;
+		*denominator = 30;
+		break;
+	case V4L2_PIX_FMT_XBGR40:
+	case V4L2_PIX_FMT_XY12:
+	case V4L2_PIX_FMT_X012:
+	case V4L2_PIX_FMT_X012M:
+	case V4L2_PIX_FMT_X212:
+	case V4L2_PIX_FMT_X212M:
+	case V4L2_PIX_FMT_X412:
+	case V4L2_PIX_FMT_X412M:
+		*numerator = 40;
+		*denominator = 36;
+		break;
+	default:
+		*numerator = 1;
+		*denominator = 1;
+		break;
+	}
+}
+EXPORT_SYMBOL_GPL(xvip_width_padding_factor);
+
+/**
  * xvip_of_get_format - Parse a device tree node and return format information
  * @node: the device tree node
  *
@@ -102,9 +263,9 @@
 const struct xvip_video_format *xvip_of_get_format(struct device_node *node)
 {
 	const char *pattern = "mono";
-	unsigned int vf_code;
+	unsigned int vf_code = 0;
 	unsigned int i;
-	u32 width;
+	u32 width = 0;
 	int ret;
 
 	ret = of_property_read_u32(node, "xlnx,video-format", &vf_code);
@@ -115,8 +276,13 @@
 	if (ret < 0)
 		return ERR_PTR(ret);
 
-	if (vf_code == XVIP_VF_MONO_SENSOR)
-		of_property_read_string(node, "xlnx,cfa-pattern", &pattern);
+	if (vf_code == XVIP_VF_MONO_SENSOR) {
+		ret = of_property_read_string(node,
+					      "xlnx,cfa-pattern",
+					      &pattern);
+		if (ret < 0)
+			return ERR_PTR(ret);
+	}
 
 	for (i = 0; i < ARRAY_SIZE(xvip_video_formats); ++i) {
 		const struct xvip_video_format *format = &xvip_video_formats[i];
@@ -216,8 +382,7 @@
 	if (IS_ERR(xvip->clk))
 		return PTR_ERR(xvip->clk);
 
-	clk_prepare_enable(xvip->clk);
-	return 0;
+	return clk_prepare_enable(xvip->clk);
 }
 EXPORT_SYMBOL_GPL(xvip_init_resources);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/xilinx-vip.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/xilinx-vip.h
@@ -107,21 +107,33 @@
  * @width: AXI4 format width in bits per component
  * @pattern: CFA pattern for Mono/Sensor formats
  * @code: media bus format code
- * @bpp: bytes per pixel (when stored in memory)
+ * @bpl_factor: Bytes per line factor
+ * @bpp: bits per pixel
  * @fourcc: V4L2 pixel format FCC identifier
+ * @num_planes: number of planes w.r.t. color format
+ * @buffers: number of buffers per format
+ * @hsub: Horizontal sampling factor of Chroma
+ * @vsub: Vertical sampling factor of Chroma
  */
 struct xvip_video_format {
 	unsigned int vf_code;
 	unsigned int width;
 	const char *pattern;
 	unsigned int code;
+	unsigned int bpl_factor;
 	unsigned int bpp;
 	u32 fourcc;
+	u8 num_planes;
+	u8 buffers;
+	u8 hsub;
+	u8 vsub;
 };
 
 const struct xvip_video_format *xvip_get_format_by_code(unsigned int code);
 const struct xvip_video_format *xvip_get_format_by_fourcc(u32 fourcc);
 const struct xvip_video_format *xvip_of_get_format(struct device_node *node);
+void xvip_bpl_scaling_factor(u32 fourcc, u32 *numerator, u32 *denominator);
+void xvip_width_padding_factor(u32 fourcc, u32 *numerator, u32 *denominator);
 void xvip_set_format_size(struct v4l2_mbus_framefmt *format,
 			  const struct v4l2_subdev_format *fmt);
 int xvip_enum_mbus_code(struct v4l2_subdev *subdev,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/xilinx-vipp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/xilinx-vipp.c
@@ -27,16 +27,27 @@
 #define XVIPP_DMA_S2MM				0
 #define XVIPP_DMA_MM2S				1
 
+/*
+ * This is for backward compatibility for existing applications,
+ * and planned to be deprecated
+ */
+static bool xvip_is_mplane = true;
+MODULE_PARM_DESC(is_mplane,
+		 "v4l2 device capability to handle multi planar formats");
+module_param_named(is_mplane, xvip_is_mplane, bool, 0444);
+
 /**
  * struct xvip_graph_entity - Entity in the video graph
  * @asd: subdev asynchronous registration information
  * @entity: media entity, from the corresponding V4L2 subdev
  * @subdev: V4L2 subdev
+ * @streaming: status of the V4L2 subdev if streaming or not
  */
 struct xvip_graph_entity {
 	struct v4l2_async_subdev asd; /* must be first */
 	struct media_entity *entity;
 	struct v4l2_subdev *subdev;
+	bool streaming;
 };
 
 static inline struct xvip_graph_entity *
@@ -65,6 +76,22 @@
 	return NULL;
 }
 
+static struct xvip_graph_entity *
+xvip_graph_find_entity_from_media(struct xvip_composite_device *xdev,
+				  struct media_entity *entity)
+{
+	struct xvip_graph_entity *xvip_entity;
+	struct v4l2_async_subdev *asd;
+
+	list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) {
+		xvip_entity = to_xvip_entity(asd);
+		if (xvip_entity->entity == entity)
+			return xvip_entity;
+	}
+
+	return NULL;
+}
+
 static int xvip_graph_build_one(struct xvip_composite_device *xdev,
 				struct xvip_graph_entity *entity)
 {
@@ -165,7 +192,6 @@
 		}
 	}
 
-	fwnode_handle_put(ep);
 	return ret;
 }
 
@@ -182,6 +208,190 @@
 	return NULL;
 }
 
+/**
+ * xvip_graph_entity_set_streaming - Update the streaming status
+ * @xdev: Composite video device
+ * @entity: graph entity to update
+ * @enable: enable/disable streaming status
+ *
+ * Update the streaming status of given entity.
+ *
+ * Return: previous streaming status (true or false)
+ */
+static bool xvip_graph_entity_set_streaming(struct xvip_composite_device *xdev,
+					    struct xvip_graph_entity *entity,
+					    bool enable)
+{
+	bool status = entity->streaming;
+
+	entity->streaming = enable;
+	return status;
+}
+
+static int
+xvip_graph_entity_start_stop_subdev(struct xvip_composite_device *xdev,
+				    struct xvip_graph_entity *entity, bool on)
+{
+	struct v4l2_subdev *subdev;
+	int ret = 0;
+
+	dev_dbg(xdev->dev, "%s entity %s\n",
+		on ? "Starting" : "Stopping", entity->entity->name);
+	subdev = media_entity_to_v4l2_subdev(entity->entity);
+
+	/*
+	 * start or stop the subdev only once in case if they are
+	 * shared between sub-graphs
+	 */
+	if (on) {
+		/* power-on subdevice */
+		ret = v4l2_subdev_call(subdev, core, s_power, 1);
+		if (ret < 0 && ret != -ENOIOCTLCMD) {
+			dev_err(xdev->dev,
+				"s_power on failed on subdev\n");
+			xvip_graph_entity_set_streaming(xdev, entity, 0);
+			return ret;
+		}
+
+		/* stream-on subdevice */
+		ret = v4l2_subdev_call(subdev, video, s_stream, 1);
+		if (ret < 0 && ret != -ENOIOCTLCMD) {
+			dev_err(xdev->dev,
+				"s_stream on failed on subdev\n");
+			v4l2_subdev_call(subdev, core, s_power, 0);
+			xvip_graph_entity_set_streaming(xdev, entity, 0);
+		}
+	} else {
+		/* stream-off subdevice */
+		ret = v4l2_subdev_call(subdev, video, s_stream, 0);
+		if (ret < 0 && ret != -ENOIOCTLCMD) {
+			dev_err(xdev->dev,
+				"s_stream off failed on subdev\n");
+			xvip_graph_entity_set_streaming(xdev, entity, 1);
+		}
+
+		/* power-off subdevice */
+		ret = v4l2_subdev_call(subdev, core, s_power, 0);
+		if (ret < 0 && ret != -ENOIOCTLCMD)
+			dev_err(xdev->dev,
+				"s_power off failed on subdev\n");
+	}
+
+	if (ret == -ENOIOCTLCMD)
+		ret = 0;
+
+	return ret;
+}
+
+/**
+ * xvip_graph_entity_start_stop - start / stop the graph entity
+ * @xdev: composite device
+ * @entity: entity to check
+ * @on: boolean flag. true for enable and false for disable
+ *
+ * Check if all immediate dependencies are ready dependeing on 'on' flag.
+ * If enabling, check all source pads. Sink pads for disabling. Once all
+ * dependencies are ready, set the streaming state on the entity. If the state
+ * is already set, optimize it by skipping checks.
+ *
+ * Return: true if the state is successfully or already set. false otherwise.
+ */
+static bool xvip_graph_entity_start_stop(struct xvip_composite_device *xdev,
+					 struct xvip_graph_entity *entity,
+					 bool on)
+{
+	unsigned long pad_flag = on ? MEDIA_PAD_FL_SOURCE : MEDIA_PAD_FL_SINK;
+	unsigned int i;
+	bool state;
+	int ret;
+
+	if (entity->streaming == on)
+		return true;
+
+	for (i = 0; i < entity->entity->num_pads; i++) {
+		struct xvip_graph_entity *remote;
+		struct media_pad *pad;
+
+		if (!(entity->entity->pads[i].flags & pad_flag))
+			continue;
+
+		/* skipping not connected pads */
+		pad = media_entity_remote_pad(&entity->entity->pads[i]);
+		if (!pad || !pad->entity)
+			continue;
+
+		/*
+		 * Skip if there is no remote. This entity is at the end,
+		 * such as DMA, sensor, or other type.
+		 */
+		remote = xvip_graph_find_entity_from_media(xdev, pad->entity);
+		if (!remote)
+			continue;
+
+		/* the dependency state doesn't meet */
+		if (remote->streaming != on) {
+			state = xvip_graph_entity_start_stop(xdev, remote, on);
+			if (!state)
+				return state;
+		}
+	}
+
+	/* set state and report if state is changed or not */
+	state = xvip_graph_entity_set_streaming(xdev, entity, on);
+	/* This shouldn't happen as check is already above */
+	if (state == on) {
+		WARN(1, "Should never get here\n");
+		return true;
+	}
+
+	ret = xvip_graph_entity_start_stop_subdev(xdev, entity, on);
+	if (ret < 0) {
+		dev_err(xdev->dev, "ret = %d for entity %s\n",
+			ret, entity->entity->name);
+		return false;
+	}
+
+	return true;
+}
+
+/**
+ * xvip_graph_pipeline_start_stop - start or stop the pipe in the graph
+ * @xdev: composite device
+ * @pipe: pipeline to start / stop
+ * @on: boolean flag. true for enable and false for disable
+ *
+ * Enable or disable the pipe in the graph by iterating the asd list.
+ * The pipe is a sub-graph, and the check ensures the given entity
+ * is part of the pipe before doing start or stop. This function
+ * or any subsequent functions don't and shouldn't change the asd list,
+ * so that there's no race if the caller holds the pipeline lock.
+ * xvip_graph_entity_start_stop() takes care of dependencies,
+ * or state-checking.
+ *
+ * Return: 0 for success, otherwise error code
+ */
+int xvip_graph_pipeline_start_stop(struct xvip_composite_device *xdev,
+				   struct xvip_pipeline *pipe, bool on)
+{
+	struct v4l2_async_subdev *asd;
+
+	list_for_each_entry(asd, &xdev->notifier.asd_list, asd_list) {
+		struct xvip_graph_entity *entity;
+		bool state;
+
+		entity = to_xvip_entity(asd);
+		/* skip an entity not belongng to the given pipe */
+		if (&pipe->pipe != entity->entity->pipe)
+			continue;
+
+		state = xvip_graph_entity_start_stop(xdev, entity, on);
+		if (!state)
+			return -EPIPE;
+	}
+
+	return 0;
+}
+
 static int xvip_graph_build_dma(struct xvip_composite_device *xdev)
 {
 	u32 link_flags = MEDIA_LNK_FL_ENABLED;
@@ -276,7 +486,6 @@
 		}
 	}
 
-	of_node_put(ep);
 	return ret;
 }
 
@@ -442,9 +651,11 @@
 		return ret;
 
 	if (strcmp(direction, "input") == 0)
-		type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+		type = xvip_is_mplane ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
+						V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	else if (strcmp(direction, "output") == 0)
-		type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+		type = xvip_is_mplane ? V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE :
+					V4L2_BUF_TYPE_VIDEO_OUTPUT;
 	else
 		return -EINVAL;
 
@@ -462,8 +673,14 @@
 
 	list_add_tail(&dma->list, &xdev->dmas);
 
-	xdev->v4l2_caps |= type == V4L2_BUF_TYPE_VIDEO_CAPTURE
-			 ? V4L2_CAP_VIDEO_CAPTURE : V4L2_CAP_VIDEO_OUTPUT;
+	if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+		xdev->v4l2_caps |= V4L2_CAP_VIDEO_CAPTURE_MPLANE;
+	else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		xdev->v4l2_caps |= V4L2_CAP_VIDEO_CAPTURE;
+	else if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+		xdev->v4l2_caps |= V4L2_CAP_VIDEO_OUTPUT;
+	else if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+		xdev->v4l2_caps |= V4L2_CAP_VIDEO_OUTPUT_MPLANE;
 
 	return 0;
 }
@@ -472,7 +689,7 @@
 {
 	struct device_node *ports;
 	struct device_node *port;
-	int ret;
+	int ret = 0;
 
 	ports = of_get_child_by_name(xdev->dev->of_node, "ports");
 	if (ports == NULL) {
@@ -482,13 +699,14 @@
 
 	for_each_child_of_node(ports, port) {
 		ret = xvip_graph_dma_init_one(xdev, port);
-		if (ret < 0) {
+		if (ret) {
 			of_node_put(port);
-			return ret;
+			break;
 		}
 	}
 
-	return 0;
+	of_node_put(ports);
+	return ret;
 }
 
 static void xvip_graph_cleanup(struct xvip_composite_device *xdev)
@@ -594,6 +812,7 @@
 		return -ENOMEM;
 
 	xdev->dev = &pdev->dev;
+	mutex_init(&xdev->lock);
 	INIT_LIST_HEAD(&xdev->dmas);
 	v4l2_async_notifier_init(&xdev->notifier);
 
@@ -620,6 +839,7 @@
 {
 	struct xvip_composite_device *xdev = platform_get_drvdata(pdev);
 
+	mutex_destroy(&xdev->lock);
 	xvip_graph_cleanup(xdev);
 	xvip_composite_v4l2_cleanup(xdev);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/xilinx-vipp.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/xilinx-vipp.h
@@ -27,6 +27,7 @@
  * @notifier: V4L2 asynchronous subdevs notifier
  * @dmas: list of DMA channels at the pipeline output and input
  * @v4l2_caps: V4L2 capabilities of the whole device (see VIDIOC_QUERYCAP)
+ * @lock: This is to ensure all dma path entities acquire same pipeline object
  */
 struct xvip_composite_device {
 	struct v4l2_device v4l2_dev;
@@ -37,6 +38,10 @@
 
 	struct list_head dmas;
 	u32 v4l2_caps;
+	struct mutex lock; /* lock to protect xvip pipeline instance */
 };
 
+int xvip_graph_pipeline_start_stop(struct xvip_composite_device *xdev,
+				   struct xvip_pipeline *pipe, bool on);
+
 #endif /* __XILINX_VIPP_H__ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/xilinx-vpss-csc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/xilinx-vpss-csc.c
@@ -0,0 +1,1191 @@
+/*
+ * Xilinx VPSS Color Space Converter
+ *
+ * Copyright (C) 2017 Xilinx, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/xilinx-v4l2-controls.h>
+
+#include <media/v4l2-async.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-subdev.h>
+
+#include "xilinx-vip.h"
+
+#define XV_CSC_AP_CTRL					(0x000)
+#define XV_CSC_INVIDEOFORMAT				(0x010)
+#define XV_CSC_OUTVIDEOFORMAT				(0x018)
+#define XV_CSC_WIDTH					(0x020)
+#define XV_CSC_HEIGHT					(0x028)
+#define XV_CSC_K11					(0x050)
+#define XV_CSC_K12					(0x058)
+#define XV_CSC_K13					(0x060)
+#define XV_CSC_K21					(0x068)
+#define XV_CSC_K22					(0x070)
+#define XV_CSC_K23					(0x078)
+#define XV_CSC_K31					(0x080)
+#define XV_CSC_K32					(0x088)
+#define XV_CSC_K33					(0x090)
+#define XV_CSC_ROFFSET					(0x098)
+#define XV_CSC_GOFFSET					(0x0a0)
+#define XV_CSC_BOFFSET					(0x0a8)
+#define XV_CSC_CLAMPMIN					(0x0b0)
+#define XV_CSC_CLIPMAX					(0x0b8)
+
+#define XV_CSC_FRACTIONAL_BITS	(12)
+#define XV_CSC_SCALE_FACTOR	(4096)
+/* This a VPSS CSC specific macro used to calculate Contrast */
+#define XV_CSC_DIVISOR		(10000)
+#define XV_CSC_DEFAULT_HEIGHT	(720)
+#define XV_CSC_DEFAULT_WIDTH	(1280)
+#define XV_CSC_K_MAX_ROWS	(3)
+#define XV_CSC_K_MAX_COLUMNS	(3)
+#define XV_CSC_MIN_WIDTH	(64)
+#define XV_CSC_MAX_WIDTH	(8192)
+#define XV_CSC_MIN_HEIGHT	(64)
+#define XV_CSC_MAX_HEIGHT	(4320)
+
+/* GPIO Reset Assert/De-assert */
+#define XCSC_RESET_ASSERT	(1)
+#define XCSC_RESET_DEASSERT	(0)
+/* Streaming Macros */
+#define XCSC_CLAMP_MIN_ZERO	(0)
+#define XCSC_AP_START		BIT(0)
+#define XCSC_AP_AUTO_RESTART	BIT(7)
+#define XCSC_STREAM_ON	(XCSC_AP_START | XCSC_AP_AUTO_RESTART)
+/* Color Control Macros */
+#define XCSC_COLOR_CTRL_COUNT		(5)
+#define XCSC_COLOR_CTRL_DEFAULT		(50)
+
+enum xcsc_color_fmt {
+	XVIDC_CSF_RGB = 0,
+	XVIDC_CSF_YCRCB_444,
+	XVIDC_CSF_YCRCB_422,
+	XVIDC_CSF_YCRCB_420,
+};
+
+enum xcsc_output_range {
+	XVIDC_CR_0_255 = 1,
+	XVIDC_CR_16_240,
+	XVIDC_CR_16_235
+};
+
+enum xcsc_color_depth {
+	XVIDC_BPC_8 = 8,
+	XVIDC_BPC_10 = 10,
+};
+
+static const s32
+rgb_unity_matrix[XV_CSC_K_MAX_ROWS][XV_CSC_K_MAX_COLUMNS + 1] = {
+	{XV_CSC_SCALE_FACTOR, 0, 0, 0},
+	{0, XV_CSC_SCALE_FACTOR, 0, 0},
+	{0, 0, XV_CSC_SCALE_FACTOR, 0},
+};
+
+static const s32
+ycrcb_to_rgb_unity[XV_CSC_K_MAX_ROWS][XV_CSC_K_MAX_COLUMNS + 1] = {
+	{
+	 11644 * XV_CSC_SCALE_FACTOR / XV_CSC_DIVISOR,
+	 0,
+	 17927 * XV_CSC_SCALE_FACTOR / XV_CSC_DIVISOR,
+	 0
+	},
+	{
+	 11644 * XV_CSC_SCALE_FACTOR / XV_CSC_DIVISOR,
+	 -2132 * XV_CSC_SCALE_FACTOR / XV_CSC_DIVISOR,
+	 -5329 * XV_CSC_SCALE_FACTOR / XV_CSC_DIVISOR,
+	 0
+	},
+	{
+	 11644 * XV_CSC_SCALE_FACTOR / XV_CSC_DIVISOR,
+	 21124 * XV_CSC_SCALE_FACTOR / XV_CSC_DIVISOR,
+	 0,
+	 0
+	},
+};
+
+static const s32
+rgb_to_ycrcb_unity[XV_CSC_K_MAX_ROWS][XV_CSC_K_MAX_COLUMNS + 1] = {
+	{
+	 1826 * XV_CSC_SCALE_FACTOR / XV_CSC_DIVISOR,
+	 6142 * XV_CSC_SCALE_FACTOR / XV_CSC_DIVISOR,
+	 620 * XV_CSC_SCALE_FACTOR / XV_CSC_DIVISOR,
+	 0
+	},
+	{
+	 -1006 * XV_CSC_SCALE_FACTOR / XV_CSC_DIVISOR,
+	 -3386 * XV_CSC_SCALE_FACTOR / XV_CSC_DIVISOR,
+	 4392 * XV_CSC_SCALE_FACTOR / XV_CSC_DIVISOR,
+	 0
+	},
+	{
+	 4392 * XV_CSC_SCALE_FACTOR / XV_CSC_DIVISOR,
+	 -3989 * XV_CSC_SCALE_FACTOR / XV_CSC_DIVISOR,
+	 -403 * XV_CSC_SCALE_FACTOR / XV_CSC_DIVISOR,
+	 0,
+	},
+};
+
+/**
+ * struct xcsc_dev - xilinx vpss csc device structure
+ * @xvip: Xilinx Video IP core struct
+ * @pads: Media bus pads for VPSS CSC
+ * @formats: Current media bus formats
+ * @default_formats: Default media bus formats for VPSS CSC
+ * @vip_formats: Pointer to DT specified media bus code info
+ * @ctrl_handler: V4L2 Control Handler struct
+ * @custom_ctrls: Array of pointers to various custom controls
+ * @cft_in: IP or Hardware specific input video format
+ * @cft_out: IP or Hardware specific output video format
+ * @output_range: Color range for Outgoing video
+ * @color_depth: Data width used to represent color
+ * @brightness: Expected brightness value
+ * @contrast: Expected contrast value
+ * @red_gain: Expected red gain
+ * @green_gain: Expect green gain
+ * @blue_gain: Expected blue gain
+ * @brightness_active: Current brightness value
+ * @contrast_active: Current contrast value
+ * @red_gain_active: Current red gain
+ * @green_gain_active: Current green gain
+ * @blue_gain_active: Current blue gain
+ * @k_hw : Coefficients to be written to IP/Hardware
+ * @shadow_coeff: Coefficients to track RGB equivalents for color controls
+ * @clip_max: Maximum value to clip output color range
+ * @rst_gpio: Handle to PS GPIO specifier to assert/de-assert the reset line
+ * @max_width: Maximum width supported by IP.
+ * @max_height: Maximum height supported by IP.
+ */
+struct xcsc_dev {
+	struct xvip_device xvip;
+	struct media_pad pads[2];
+	struct v4l2_mbus_framefmt formats[2];
+	struct v4l2_mbus_framefmt default_formats[2];
+	const struct xvip_video_format *vip_formats[2];
+	struct v4l2_ctrl_handler ctrl_handler;
+	struct v4l2_ctrl *custom_ctrls[XCSC_COLOR_CTRL_COUNT];
+
+	enum xcsc_color_fmt cft_in;
+	enum xcsc_color_fmt cft_out;
+	enum xcsc_output_range output_range;
+	enum xcsc_color_depth color_depth;
+	s32 brightness;
+	s32 contrast;
+	s32 red_gain;
+	s32 green_gain;
+	s32 blue_gain;
+	s32 brightness_active;
+	s32 contrast_active;
+	s32 red_gain_active;
+	s32 green_gain_active;
+	s32 blue_gain_active;
+	s32 k_hw[XV_CSC_K_MAX_ROWS][XV_CSC_K_MAX_COLUMNS + 1];
+	s32 shadow_coeff[XV_CSC_K_MAX_ROWS][XV_CSC_K_MAX_COLUMNS + 1];
+	s32 clip_max;
+	struct gpio_desc *rst_gpio;
+	u32 max_width;
+	u32 max_height;
+};
+
+#ifdef DEBUG
+static u32 xcsc_read(struct xcsc_dev *xcsc, u32 reg)
+{
+	u32 data;
+
+	data = xvip_read(&xcsc->xvip, reg);
+	return data;
+}
+
+static void xcsc_get_coeff(struct xcsc_dev *xcsc, s32 C[3][4])
+{
+	C[0][0] = xcsc_read(xcsc, XV_CSC_K11);
+	C[0][1] = xcsc_read(xcsc, XV_CSC_K12);
+	C[0][2] = xcsc_read(xcsc, XV_CSC_K13);
+	C[1][0] = xcsc_read(xcsc, XV_CSC_K21);
+	C[1][1] = xcsc_read(xcsc, XV_CSC_K22);
+	C[1][2] = xcsc_read(xcsc, XV_CSC_K23);
+	C[2][0] = xcsc_read(xcsc, XV_CSC_K31);
+	C[2][1] = xcsc_read(xcsc, XV_CSC_K32);
+	C[2][2] = xcsc_read(xcsc, XV_CSC_K33);
+	C[0][3] = xcsc_read(xcsc, XV_CSC_ROFFSET);
+	C[1][3] = xcsc_read(xcsc, XV_CSC_GOFFSET);
+	C[2][3] = xcsc_read(xcsc, XV_CSC_BOFFSET);
+}
+
+static void xcsc_print_coeff(struct xcsc_dev *xcsc)
+{
+	s32 C[3][4];
+
+	xcsc_get_coeff(xcsc, C);
+
+	dev_info(xcsc->xvip.dev,
+		 "-------------CSC Coeff Dump Start------\n");
+	dev_info(xcsc->xvip.dev,
+		 " R row : %5d  %5d  %5d\n",
+		 (s16)C[0][0], (s16)C[0][1], (s16)C[0][2]);
+	dev_info(xcsc->xvip.dev,
+		 " G row : %5d  %5d  %5d\n",
+		 (s16)C[1][0], (s16)C[1][1], (s16)C[1][2]);
+	dev_info(xcsc->xvip.dev,
+		 " B row : %5d  %5d  %5d\n",
+		 (s16)C[2][0], (s16)C[2][1], (s16)C[2][2]);
+	dev_info(xcsc->xvip.dev,
+		 "Offset : %5d  %5d  %5d\n",
+		 (s16)C[0][3], (s16)C[1][3], (s16)C[2][3]);
+	dev_info(xcsc->xvip.dev,
+		 "ClampMin: %3d  ClipMax %3d",
+		 xcsc_read(xcsc, XV_CSC_CLAMPMIN),
+		 xcsc_read(xcsc, XV_CSC_CLIPMAX));
+	dev_info(xcsc->xvip.dev,
+		 "-------------CSC Coeff Dump Stop-------\n");
+}
+
+static void
+xcsc_log_coeff(struct device *dev,
+	       s32 coeff[XV_CSC_K_MAX_ROWS][XV_CSC_K_MAX_COLUMNS + 1])
+{
+	if (!dev)
+		return;
+	dev_dbg(dev, "--- %s : Start Coeff Log ---", __func__);
+	dev_dbg(dev, "R row : %5d  %5d  %5d\n",
+		coeff[0][0], coeff[0][1], coeff[0][2]);
+	dev_dbg(dev, "G row : %5d  %5d  %5d\n",
+		coeff[1][0], coeff[1][1], coeff[1][2]);
+	dev_dbg(dev, "B row : %5d  %5d  %5d\n",
+		coeff[2][0], coeff[2][1], coeff[2][2]);
+	dev_dbg(dev, "Offset: %5d  %5d  %5d\n",
+		coeff[0][3], coeff[1][3], coeff[2][3]);
+	dev_dbg(dev, "---  %s : Stop Coeff Log ---", __func__);
+}
+
+static void xcsc_print_k_hw(struct xcsc_dev *xcsc)
+{
+	dev_dbg(xcsc->xvip.dev,
+		"-------------CSC Driver k_hw[][] Dump------------\n");
+	xcsc_log_coeff(xcsc->xvip.dev, xcsc->k_hw);
+	dev_dbg(xcsc->xvip.dev,
+		"-------------------------------------------------\n");
+}
+#endif /* DEBUG */
+
+static void xcsc_write(struct xcsc_dev *xcsc, u32 reg, u32 data)
+{
+	xvip_write(&xcsc->xvip, reg, data);
+}
+
+static void xcsc_write_rgb_3x3(struct xcsc_dev *xcsc)
+{
+	/* Write Matrix Coefficients */
+	xcsc_write(xcsc, XV_CSC_K11, xcsc->k_hw[0][0]);
+	xcsc_write(xcsc, XV_CSC_K12, xcsc->k_hw[0][1]);
+	xcsc_write(xcsc, XV_CSC_K13, xcsc->k_hw[0][2]);
+	xcsc_write(xcsc, XV_CSC_K21, xcsc->k_hw[1][0]);
+	xcsc_write(xcsc, XV_CSC_K22, xcsc->k_hw[1][1]);
+	xcsc_write(xcsc, XV_CSC_K23, xcsc->k_hw[1][2]);
+	xcsc_write(xcsc, XV_CSC_K31, xcsc->k_hw[2][0]);
+	xcsc_write(xcsc, XV_CSC_K32, xcsc->k_hw[2][1]);
+	xcsc_write(xcsc, XV_CSC_K33, xcsc->k_hw[2][2]);
+}
+
+static void xcsc_write_rgb_offset(struct xcsc_dev *xcsc)
+{
+	/* Write RGB Offsets */
+	xcsc_write(xcsc, XV_CSC_ROFFSET, xcsc->k_hw[0][3]);
+	xcsc_write(xcsc, XV_CSC_GOFFSET, xcsc->k_hw[1][3]);
+	xcsc_write(xcsc, XV_CSC_BOFFSET, xcsc->k_hw[2][3]);
+}
+
+static void xcsc_write_coeff(struct xcsc_dev *xcsc)
+{
+	xcsc_write_rgb_3x3(xcsc);
+	xcsc_write_rgb_offset(xcsc);
+}
+
+static void xcsc_set_v4l2_ctrl_defaults(struct xcsc_dev *xcsc)
+{
+	unsigned int i;
+
+	mutex_lock(xcsc->ctrl_handler.lock);
+	for (i = 0; i < XCSC_COLOR_CTRL_COUNT; i++)
+		xcsc->custom_ctrls[i]->cur.val = XCSC_COLOR_CTRL_DEFAULT;
+	mutex_unlock(xcsc->ctrl_handler.lock);
+}
+
+static void xcsc_set_control_defaults(struct xcsc_dev *xcsc)
+{
+	/* These are VPSS CSC IP specific defaults */
+	xcsc->brightness = 120;
+	xcsc->contrast = 0;
+	xcsc->red_gain = 120;
+	xcsc->blue_gain = 120;
+	xcsc->green_gain = 120;
+	xcsc->brightness_active	= 120;
+	xcsc->contrast_active = 0;
+	xcsc->red_gain_active = 120;
+	xcsc->blue_gain_active = 120;
+	xcsc->green_gain_active = 120;
+}
+
+static void xcsc_copy_coeff(
+	s32 dest[XV_CSC_K_MAX_ROWS][XV_CSC_K_MAX_COLUMNS + 1],
+	s32 const src[XV_CSC_K_MAX_ROWS][XV_CSC_K_MAX_COLUMNS + 1])
+{
+	unsigned int i, j;
+
+	for (i = 0; i < XV_CSC_K_MAX_ROWS; i++)
+		for (j = 0; j < XV_CSC_K_MAX_COLUMNS + 1; j++)
+			memcpy(&dest[i][j], &src[i][j], sizeof(dest[0][0]));
+}
+
+static void xcsc_set_unity_matrix(struct xcsc_dev *xcsc)
+{
+	xcsc_copy_coeff(xcsc->k_hw, rgb_unity_matrix);
+	xcsc_copy_coeff(xcsc->shadow_coeff, rgb_unity_matrix);
+}
+
+static void xcsc_set_default_state(struct xcsc_dev *xcsc)
+{
+	xcsc->cft_in = XVIDC_CSF_RGB;
+	xcsc->cft_out = XVIDC_CSF_RGB;
+	xcsc->output_range = XVIDC_CR_0_255;
+	/* Needed to add 10, 12 and 16 bit color depth support */
+	xcsc->clip_max = BIT(xcsc->color_depth) - 1;
+	xcsc_set_control_defaults(xcsc);
+	xcsc_set_unity_matrix(xcsc);
+	xcsc_write(xcsc, XV_CSC_INVIDEOFORMAT, xcsc->cft_in);
+	xcsc_write(xcsc, XV_CSC_OUTVIDEOFORMAT, xcsc->cft_out);
+	xcsc_write_coeff(xcsc);
+	xcsc_write(xcsc, XV_CSC_CLIPMAX, xcsc->clip_max);
+	xcsc_write(xcsc, XV_CSC_CLAMPMIN, XCSC_CLAMP_MIN_ZERO);
+}
+
+static void
+xcsc_ycrcb_to_rgb(struct xcsc_dev *xcsc, s32 *clip_max,
+		  s32 temp[XV_CSC_K_MAX_ROWS][XV_CSC_K_MAX_COLUMNS + 1])
+{
+	u16 bpc_scale = BIT(xcsc->color_depth - 8);
+
+	/*
+	 * See http://graficaobscura.com/matrix/index.html for
+	 * how these numbers are derived. The VPSS CSC IP is
+	 * derived from this Matrix style algorithm. And the
+	 * 'magic' numbers here are derived from the algorithm.
+	 *
+	 * XV_CSC_DIVISOR is used to help with floating constants
+	 * while performing multiplicative operations
+	 *
+	 * Coefficients valid only for BT 709
+	 */
+	dev_dbg(xcsc->xvip.dev, "Performing YCrCb to RGB BT 709");
+	xcsc_copy_coeff(temp, ycrcb_to_rgb_unity);
+	temp[0][3] = -248 * bpc_scale;
+	temp[1][3] = 77 * bpc_scale;
+	temp[2][3] = -289 * bpc_scale;
+	*clip_max = BIT(xcsc->color_depth) - 1;
+}
+
+static void
+xcsc_matrix_multiply(s32 K1[XV_CSC_K_MAX_ROWS][XV_CSC_K_MAX_COLUMNS + 1],
+		     s32 K2[XV_CSC_K_MAX_ROWS][XV_CSC_K_MAX_COLUMNS + 1],
+		     s32 kout[XV_CSC_K_MAX_ROWS][XV_CSC_K_MAX_COLUMNS + 1])
+{
+	s32 A, B, C, D, E, F, G, H, I, J, K, L, M, N;
+	s32 O, P, Q, R, S, T, U, V, W, X;
+
+	A = K1[0][0]; B = K1[0][1]; C = K1[0][2]; J = K1[0][3];
+	D = K1[1][0]; E = K1[1][1]; F = K1[1][2]; K = K1[1][3];
+	G = K1[2][0]; H = K1[2][1]; I = K1[2][2]; L = K1[2][3];
+
+	M = K2[0][0]; N = K2[0][1]; O = K2[0][2]; V = K2[0][3];
+	P = K2[1][0]; Q = K2[1][1]; R = K2[1][2]; W = K2[1][3];
+	S = K2[2][0]; T = K2[2][1]; U = K2[2][2]; X = K2[2][3];
+
+	kout[0][0] = (M * A + N * D + O * G) / XV_CSC_SCALE_FACTOR;
+	kout[0][1] = (M * B + N * E + O * H) / XV_CSC_SCALE_FACTOR;
+	kout[0][2] = (M * C + N * F + O * I) / XV_CSC_SCALE_FACTOR;
+	kout[1][0] = (P * A + Q * D + R * G) / XV_CSC_SCALE_FACTOR;
+	kout[1][1] = (P * B + Q * E + R * H) / XV_CSC_SCALE_FACTOR;
+	kout[1][2] = (P * C + Q * F + R * I) / XV_CSC_SCALE_FACTOR;
+	kout[2][0] = (S * A + T * D + U * G) / XV_CSC_SCALE_FACTOR;
+	kout[2][1] = (S * B + T * E + U * H) / XV_CSC_SCALE_FACTOR;
+	kout[2][2] = (S * C + T * F + U * I) / XV_CSC_SCALE_FACTOR;
+	kout[0][3] = ((M * J + N * K + O * L) / XV_CSC_SCALE_FACTOR) + V;
+	kout[1][3] = ((P * J + Q * K + R * L) / XV_CSC_SCALE_FACTOR) + W;
+	kout[2][3] = ((S * J + T * K + U * L) / XV_CSC_SCALE_FACTOR) + X;
+}
+
+static void
+xcsc_rgb_to_ycrcb(struct xcsc_dev *xcsc, s32 *clip_max,
+		  s32 temp[XV_CSC_K_MAX_ROWS][XV_CSC_K_MAX_COLUMNS + 1])
+{
+	u16 bpc_scale = BIT(xcsc->color_depth - 8);
+
+	/*
+	 * See http://graficaobscura.com/matrix/index.html for
+	 * how these numbers are derived. The VPSS CSC IP is
+	 * derived from this Matrix style algorithm. And the
+	 * 'magic' numbers here are derived from the algorithm.
+	 *
+	 * XV_CSC_DIVISOR is used to help with floating constants
+	 * while performing multiplicative operations
+	 *
+	 * Coefficients valid only for BT 709
+	 */
+	dev_dbg(xcsc->xvip.dev, "Performing RGB to YCrCb BT 709");
+	xcsc_copy_coeff(temp, rgb_to_ycrcb_unity);
+	temp[0][3] = 16 * bpc_scale;
+	temp[1][3] = 128 * bpc_scale;
+	temp[2][3] = 128 * bpc_scale;
+	*clip_max = BIT(xcsc->color_depth) - 1;
+}
+
+static int xcsc_update_formats(struct xcsc_dev *xcsc)
+{
+	u32 color_in, color_out;
+
+	/* Write In and Out Video Formats */
+	color_in = xcsc->formats[XVIP_PAD_SINK].code;
+	color_out = xcsc->formats[XVIP_PAD_SOURCE].code;
+
+	switch (color_in) {
+	case MEDIA_BUS_FMT_RBG888_1X24:
+	case MEDIA_BUS_FMT_RBG101010_1X30:
+		dev_dbg(xcsc->xvip.dev, "Media Format In : RGB");
+		xcsc->cft_in = XVIDC_CSF_RGB;
+		break;
+	case MEDIA_BUS_FMT_VUY8_1X24:
+	case MEDIA_BUS_FMT_VUY10_1X30:
+		dev_dbg(xcsc->xvip.dev, "Media Format In : YUV 444");
+		xcsc->cft_in = XVIDC_CSF_YCRCB_444;
+		break;
+	case MEDIA_BUS_FMT_UYVY8_1X16:
+	case MEDIA_BUS_FMT_UYVY10_1X20:
+		dev_dbg(xcsc->xvip.dev, "Media Format In : YUV 422");
+		xcsc->cft_in = XVIDC_CSF_YCRCB_422;
+		break;
+	case MEDIA_BUS_FMT_VYYUYY8_1X24:
+	case MEDIA_BUS_FMT_VYYUYY10_4X20:
+		dev_dbg(xcsc->xvip.dev, "Media Format In : YUV 420");
+		xcsc->cft_in = XVIDC_CSF_YCRCB_420;
+		break;
+	}
+
+	switch (color_out) {
+	case MEDIA_BUS_FMT_RBG888_1X24:
+	case MEDIA_BUS_FMT_RBG101010_1X30:
+		xcsc->cft_out = XVIDC_CSF_RGB;
+		dev_dbg(xcsc->xvip.dev, "Media Format Out : RGB");
+		if (color_in != MEDIA_BUS_FMT_RBG888_1X24)
+			xcsc_ycrcb_to_rgb(xcsc, &xcsc->clip_max, xcsc->k_hw);
+		else
+			xcsc_set_unity_matrix(xcsc);
+		break;
+	case MEDIA_BUS_FMT_VUY8_1X24:
+	case MEDIA_BUS_FMT_VUY10_1X30:
+		xcsc->cft_out = XVIDC_CSF_YCRCB_444;
+		dev_dbg(xcsc->xvip.dev, "Media Format Out : YUV 444");
+		if (color_in == MEDIA_BUS_FMT_RBG888_1X24)
+			xcsc_rgb_to_ycrcb(xcsc, &xcsc->clip_max, xcsc->k_hw);
+		else
+			xcsc_set_unity_matrix(xcsc);
+		break;
+	case MEDIA_BUS_FMT_UYVY8_1X16:
+	case MEDIA_BUS_FMT_UYVY10_1X20:
+		xcsc->cft_out = XVIDC_CSF_YCRCB_422;
+		dev_dbg(xcsc->xvip.dev, "Media Format Out : YUV 422");
+		if (color_in == MEDIA_BUS_FMT_RBG888_1X24)
+			xcsc_rgb_to_ycrcb(xcsc, &xcsc->clip_max, xcsc->k_hw);
+		else
+			xcsc_set_unity_matrix(xcsc);
+		break;
+	case MEDIA_BUS_FMT_VYYUYY8_1X24:
+	case MEDIA_BUS_FMT_VYYUYY10_4X20:
+		xcsc->cft_out = XVIDC_CSF_YCRCB_420;
+		dev_dbg(xcsc->xvip.dev, "Media Format Out : YUV 420");
+		if (color_in ==  MEDIA_BUS_FMT_RBG888_1X24)
+			xcsc_rgb_to_ycrcb(xcsc, &xcsc->clip_max, xcsc->k_hw);
+		else
+			xcsc_set_unity_matrix(xcsc);
+		break;
+	}
+
+	xcsc_write(xcsc, XV_CSC_INVIDEOFORMAT, xcsc->cft_in);
+	xcsc_write(xcsc, XV_CSC_OUTVIDEOFORMAT, xcsc->cft_out);
+
+	xcsc_write_coeff(xcsc);
+
+	xcsc_write(xcsc, XV_CSC_CLIPMAX, xcsc->clip_max);
+	xcsc_write(xcsc, XV_CSC_CLAMPMIN, XCSC_CLAMP_MIN_ZERO);
+#ifdef DEBUG
+	xcsc_print_k_hw(xcsc);
+	xcsc_print_coeff(xcsc);
+#endif
+	return 0;
+}
+
+static inline struct xcsc_dev *to_csc(struct v4l2_subdev *subdev)
+{
+	return container_of(subdev, struct xcsc_dev, xvip.subdev);
+}
+
+static struct v4l2_mbus_framefmt *
+__xcsc_get_pad_format(struct xcsc_dev *xcsc,
+		      struct v4l2_subdev_pad_config *cfg,
+		      unsigned int pad, u32 which)
+{
+	struct v4l2_mbus_framefmt *format;
+
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		format = v4l2_subdev_get_try_format(&xcsc->xvip.subdev,
+						    cfg, pad);
+		break;
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		format = &xcsc->formats[pad];
+		break;
+	default:
+		format = NULL;
+		break;
+	}
+
+	return format;
+}
+
+static void
+xcsc_correct_coeff(struct xcsc_dev *xcsc,
+		   s32 temp[XV_CSC_K_MAX_ROWS][XV_CSC_K_MAX_COLUMNS + 1])
+{
+	s32 csc_change[XV_CSC_K_MAX_ROWS][XV_CSC_K_MAX_COLUMNS + 1] = { {0} };
+	s32 csc_extra[XV_CSC_K_MAX_ROWS][XV_CSC_K_MAX_COLUMNS + 1] = { {0} };
+	u32 mbus_in = xcsc->formats[XVIP_PAD_SINK].code;
+	u32 mbus_out = xcsc->formats[XVIP_PAD_SOURCE].code;
+
+#ifdef DEBUG
+	xcsc_log_coeff(xcsc->xvip.dev, temp);
+#endif
+	if (mbus_in == MEDIA_BUS_FMT_RBG888_1X24 && mbus_out == mbus_in) {
+		dev_dbg(xcsc->xvip.dev, "%s : RGB to RGB", __func__);
+		xcsc_copy_coeff(xcsc->k_hw,
+				(const s32 (*)[XV_CSC_K_MAX_COLUMNS + 1])temp);
+	} else if (mbus_in == MEDIA_BUS_FMT_RBG888_1X24 &&
+		   mbus_out != MEDIA_BUS_FMT_RBG888_1X24) {
+		dev_dbg(xcsc->xvip.dev, "%s : RGB to YUV", __func__);
+		xcsc_rgb_to_ycrcb(xcsc, &xcsc->clip_max, csc_change);
+		xcsc_matrix_multiply(temp, csc_change, xcsc->k_hw);
+	} else if (mbus_in != MEDIA_BUS_FMT_RBG888_1X24 &&
+		   mbus_out == MEDIA_BUS_FMT_RBG888_1X24) {
+		dev_dbg(xcsc->xvip.dev, "%s : YUV to RGB", __func__);
+		xcsc_ycrcb_to_rgb(xcsc, &xcsc->clip_max, csc_change);
+		xcsc_matrix_multiply(csc_change, temp, xcsc->k_hw);
+	} else if (mbus_in != MEDIA_BUS_FMT_RBG888_1X24 &&
+		   mbus_out != MEDIA_BUS_FMT_RBG888_1X24) {
+		dev_dbg(xcsc->xvip.dev, "%s : YUV to YUV", __func__);
+		xcsc_ycrcb_to_rgb(xcsc, &xcsc->clip_max, csc_change);
+		xcsc_matrix_multiply(csc_change, temp, csc_extra);
+		xcsc_rgb_to_ycrcb(xcsc, &xcsc->clip_max, csc_change);
+		xcsc_matrix_multiply(csc_extra, csc_change, xcsc->k_hw);
+	} else {
+		/* Should never get here */
+		WARN_ON(1);
+	}
+}
+
+static void xcsc_set_brightness(struct xcsc_dev *xcsc)
+{
+	unsigned int i, j;
+
+	dev_dbg(xcsc->xvip.dev,
+		"%s : Brightness %d Brightness Active %d",
+		__func__,
+		((xcsc->brightness - 20) / 2),
+		((xcsc->brightness_active - 20) / 2));
+	if (xcsc->brightness == xcsc->brightness_active)
+		return;
+	for (i = 0; i < XV_CSC_K_MAX_ROWS; i++) {
+		for (j = 0; j < XV_CSC_K_MAX_COLUMNS; j++) {
+			xcsc->shadow_coeff[i][j] = (xcsc->shadow_coeff[i][j] *
+						    xcsc->brightness) /
+						    xcsc->brightness_active;
+		}
+	}
+	xcsc->brightness_active = xcsc->brightness;
+	xcsc_correct_coeff(xcsc, xcsc->shadow_coeff);
+	xcsc_write_coeff(xcsc);
+}
+
+static void xcsc_set_contrast(struct xcsc_dev *xcsc)
+{
+	s32 contrast;
+	u8 scale = BIT(xcsc->color_depth - 8);
+
+	contrast = xcsc->contrast - xcsc->contrast_active;
+	dev_dbg(xcsc->xvip.dev,
+		"%s : Contrast Difference %d scale = %d",
+		__func__, contrast, scale);
+	/* Avoid updates if same */
+	if (!contrast)
+		return;
+	/* Update RGB Offsets */
+	xcsc->shadow_coeff[0][3] += contrast * scale;
+	xcsc->shadow_coeff[1][3] += contrast * scale;
+	xcsc->shadow_coeff[2][3] += contrast * scale;
+	xcsc->contrast_active = xcsc->contrast;
+	xcsc_correct_coeff(xcsc, xcsc->shadow_coeff);
+	xcsc_write_coeff(xcsc);
+}
+
+static void xcsc_set_red_gain(struct xcsc_dev *xcsc)
+{
+	dev_dbg(xcsc->xvip.dev,
+		"%s: Red Gain %d Red Gain Active %d", __func__,
+		(xcsc->red_gain - 20) / 2,
+		(xcsc->red_gain_active - 20) / 2);
+
+	if (xcsc->red_gain != xcsc->red_gain_active) {
+		xcsc->shadow_coeff[0][0] = (xcsc->shadow_coeff[0][0] *
+					    xcsc->red_gain) /
+					    xcsc->red_gain_active;
+		xcsc->shadow_coeff[0][1] = (xcsc->shadow_coeff[0][1] *
+					    xcsc->red_gain) /
+					    xcsc->red_gain_active;
+		xcsc->shadow_coeff[0][2] = (xcsc->shadow_coeff[0][2] *
+					    xcsc->red_gain) /
+					    xcsc->red_gain_active;
+		xcsc->red_gain_active = xcsc->red_gain;
+		xcsc_correct_coeff(xcsc, xcsc->shadow_coeff);
+		xcsc_write_coeff(xcsc);
+	}
+}
+
+static void xcsc_set_green_gain(struct xcsc_dev *xcsc)
+{
+	dev_dbg(xcsc->xvip.dev,
+		"%s: Green Gain %d Green Gain Active %d", __func__,
+		 (xcsc->green_gain - 20) / 2,
+		 (xcsc->green_gain_active - 20) / 2);
+
+	if (xcsc->green_gain != xcsc->green_gain_active) {
+		xcsc->shadow_coeff[1][0] = (xcsc->shadow_coeff[1][0] *
+					    xcsc->green_gain) /
+					    xcsc->green_gain_active;
+		xcsc->shadow_coeff[1][1] = (xcsc->shadow_coeff[1][1] *
+					    xcsc->green_gain) /
+					    xcsc->green_gain_active;
+		xcsc->shadow_coeff[1][2] = (xcsc->shadow_coeff[1][2] *
+					    xcsc->green_gain) /
+					    xcsc->green_gain_active;
+		xcsc->green_gain_active = xcsc->green_gain;
+		xcsc_correct_coeff(xcsc, xcsc->shadow_coeff);
+		xcsc_write_coeff(xcsc);
+	}
+}
+
+static void xcsc_set_blue_gain(struct xcsc_dev *xcsc)
+{
+	dev_dbg(xcsc->xvip.dev,
+		"%s: Blue Gain %d Blue Gain Active %d", __func__,
+		 (xcsc->blue_gain - 20) / 2,
+		 (xcsc->blue_gain_active - 20) / 2);
+
+	if (xcsc->blue_gain != xcsc->blue_gain_active) {
+		xcsc->shadow_coeff[2][0] = (xcsc->shadow_coeff[2][0] *
+					    xcsc->blue_gain) /
+					     xcsc->blue_gain_active;
+		xcsc->shadow_coeff[2][1] = (xcsc->shadow_coeff[2][1] *
+					    xcsc->blue_gain) /
+					     xcsc->blue_gain_active;
+		xcsc->shadow_coeff[2][2] = (xcsc->shadow_coeff[2][2] *
+					    xcsc->blue_gain) /
+					     xcsc->blue_gain_active;
+		xcsc->blue_gain_active = xcsc->blue_gain;
+		xcsc_correct_coeff(xcsc, xcsc->shadow_coeff);
+		xcsc_write_coeff(xcsc);
+	}
+}
+
+static void xcsc_set_size(struct xcsc_dev *xcsc)
+{
+	u32 width, height;
+
+	width = xcsc->formats[XVIP_PAD_SINK].width;
+	height = xcsc->formats[XVIP_PAD_SINK].height;
+	dev_dbg(xcsc->xvip.dev, "%s : Setting width %d and height %d",
+		__func__, width, height);
+	xcsc_write(xcsc, XV_CSC_WIDTH, width);
+	xcsc_write(xcsc, XV_CSC_HEIGHT, height);
+}
+
+static int xcsc_s_stream(struct v4l2_subdev *subdev, int enable)
+{
+	struct xcsc_dev *xcsc = to_csc(subdev);
+
+	dev_dbg(xcsc->xvip.dev, "%s : Stream %s", __func__,
+		enable ? "On" : "Off");
+	if (!enable) {
+		/* Reset the Global IP Reset through PS GPIO */
+		gpiod_set_value_cansleep(xcsc->rst_gpio, XCSC_RESET_ASSERT);
+		gpiod_set_value_cansleep(xcsc->rst_gpio, XCSC_RESET_DEASSERT);
+		return 0;
+	}
+	xcsc_write(xcsc, XV_CSC_INVIDEOFORMAT, xcsc->cft_in);
+	xcsc_write(xcsc, XV_CSC_OUTVIDEOFORMAT, xcsc->cft_out);
+	xcsc_write(xcsc, XV_CSC_CLIPMAX, xcsc->clip_max);
+	xcsc_write(xcsc, XV_CSC_CLAMPMIN, XCSC_CLAMP_MIN_ZERO);
+	xcsc_set_size(xcsc);
+	xcsc_write_coeff(xcsc);
+#ifdef DEBUG
+	xcsc_print_coeff(xcsc);
+	dev_dbg(xcsc->xvip.dev, "cft_in = %d cft_out = %d",
+		xcsc_read(xcsc, XV_CSC_INVIDEOFORMAT),
+		xcsc_read(xcsc, XV_CSC_OUTVIDEOFORMAT));
+	dev_dbg(xcsc->xvip.dev, "clipmax = %d clampmin = %d",
+		xcsc_read(xcsc, XV_CSC_CLIPMAX),
+		xcsc_read(xcsc, XV_CSC_CLAMPMIN));
+	dev_dbg(xcsc->xvip.dev, "height = %d width = %d",
+		xcsc_read(xcsc, XV_CSC_HEIGHT),
+		xcsc_read(xcsc, XV_CSC_WIDTH));
+#endif
+	/* Start VPSS CSC IP */
+	xcsc_write(xcsc, XV_CSC_AP_CTRL, XCSC_STREAM_ON);
+	return 0;
+}
+
+static const struct v4l2_subdev_video_ops xcsc_video_ops = {
+	.s_stream = xcsc_s_stream,
+};
+
+static int xcsc_get_format(struct v4l2_subdev *subdev,
+			   struct v4l2_subdev_pad_config *cfg,
+			   struct v4l2_subdev_format *fmt)
+{
+	struct xcsc_dev *xcsc = to_csc(subdev);
+	struct v4l2_mbus_framefmt *format;
+
+	format = __xcsc_get_pad_format(xcsc, cfg, fmt->pad, fmt->which);
+	if (!format)
+		return -EINVAL;
+
+	fmt->format = *format;
+	return 0;
+}
+
+static int xcsc_set_format(struct v4l2_subdev *subdev,
+			   struct v4l2_subdev_pad_config *cfg,
+			   struct v4l2_subdev_format *fmt)
+{
+	struct xcsc_dev *xcsc = to_csc(subdev);
+	struct v4l2_mbus_framefmt *__format;
+	struct v4l2_mbus_framefmt *__propagate;
+
+	__format = __xcsc_get_pad_format(xcsc, cfg, fmt->pad, fmt->which);
+	if (!__format)
+		return -EINVAL;
+
+	/* Propagate to Source Pad */
+	__propagate = __xcsc_get_pad_format(xcsc, cfg,
+					    XVIP_PAD_SOURCE, fmt->which);
+	if (!__propagate)
+		return -EINVAL;
+
+	*__format = fmt->format;
+
+	__format->width = clamp_t(unsigned int, fmt->format.width,
+				  XV_CSC_MIN_WIDTH, xcsc->max_width);
+	__format->height = clamp_t(unsigned int, fmt->format.height,
+				   XV_CSC_MIN_HEIGHT, xcsc->max_height);
+
+	switch (__format->code) {
+	case MEDIA_BUS_FMT_VUY8_1X24:
+	case MEDIA_BUS_FMT_RBG888_1X24:
+	case MEDIA_BUS_FMT_RBG101010_1X30:
+	case MEDIA_BUS_FMT_UYVY8_1X16:
+	case MEDIA_BUS_FMT_VYYUYY8_1X24:
+	case MEDIA_BUS_FMT_VYYUYY10_4X20:
+	case MEDIA_BUS_FMT_UYVY10_1X20:
+	case MEDIA_BUS_FMT_VUY10_1X30:
+		break;
+	default:
+		/* Unsupported Format. Default to RGB */
+		__format->code = MEDIA_BUS_FMT_RBG888_1X24;
+		return -EINVAL;
+	}
+
+	/* Always propagate Sink image size to Source */
+	__propagate->width  = __format->width;
+	__propagate->height = __format->height;
+
+	fmt->format = *__format;
+	xcsc_update_formats(xcsc);
+	xcsc_set_control_defaults(xcsc);
+	xcsc_set_v4l2_ctrl_defaults(xcsc);
+	dev_info(xcsc->xvip.dev, "VPSS CSC color controls reset to defaults");
+	return 0;
+}
+
+static const struct v4l2_subdev_pad_ops xcsc_pad_ops = {
+	.enum_mbus_code = xvip_enum_mbus_code,
+	.enum_frame_size = xvip_enum_frame_size,
+	.get_fmt = xcsc_get_format,
+	.set_fmt = xcsc_set_format,
+};
+
+static const struct v4l2_subdev_ops xcsc_ops = {
+	.video = &xcsc_video_ops,
+	.pad = &xcsc_pad_ops
+};
+
+static int xcsc_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct xcsc_dev *xcsc = container_of(ctrl->handler,
+					struct xcsc_dev,
+					ctrl_handler);
+
+	switch (ctrl->id) {
+	case V4L2_CID_XILINX_CSC_BRIGHTNESS:
+		xcsc->brightness = (2 * ctrl->val) + 20;
+		xcsc_set_brightness(xcsc);
+		break;
+	case V4L2_CID_XILINX_CSC_CONTRAST:
+		xcsc->contrast = (4 * ctrl->val) - 200;
+		xcsc_set_contrast(xcsc);
+		break;
+	case V4L2_CID_XILINX_CSC_RED_GAIN:
+		xcsc->red_gain =  (2 * ctrl->val) + 20;
+		xcsc_set_red_gain(xcsc);
+		break;
+	case V4L2_CID_XILINX_CSC_BLUE_GAIN:
+		xcsc->blue_gain =  (2 * ctrl->val) + 20;
+		xcsc_set_blue_gain(xcsc);
+		break;
+	case V4L2_CID_XILINX_CSC_GREEN_GAIN:
+		xcsc->green_gain =  (2 * ctrl->val) + 20;
+		xcsc_set_green_gain(xcsc);
+		break;
+	}
+#ifdef DEBUG
+	xcsc_print_k_hw(xcsc);
+	xcsc_print_coeff(xcsc);
+#endif
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops xcsc_ctrl_ops = {
+	.s_ctrl = xcsc_s_ctrl,
+};
+
+static struct v4l2_ctrl_config xcsc_color_ctrls[XCSC_COLOR_CTRL_COUNT] = {
+	/* Brightness */
+	{
+		.ops = &xcsc_ctrl_ops,
+		.id = V4L2_CID_XILINX_CSC_BRIGHTNESS,
+		.name = "CSC Brightness",
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.min = 0,
+		.max = 100,
+		.step = 1,
+		.def = XCSC_COLOR_CTRL_DEFAULT,
+		.flags = V4L2_CTRL_FLAG_SLIDER,
+	},
+	/* Contrast */
+	{
+		.ops = &xcsc_ctrl_ops,
+		.id = V4L2_CID_XILINX_CSC_CONTRAST,
+		.name = "CSC Contrast",
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.min = 0,
+		.max = 100,
+		.step = 1,
+		.def = XCSC_COLOR_CTRL_DEFAULT,
+		.flags = V4L2_CTRL_FLAG_SLIDER,
+	},
+	/* Red Gain */
+	{
+		.ops = &xcsc_ctrl_ops,
+		.id = V4L2_CID_XILINX_CSC_RED_GAIN,
+		.name = "CSC Red Gain",
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.min = 0,
+		.max = 100,
+		.step = 1,
+		.def = XCSC_COLOR_CTRL_DEFAULT,
+		.flags = V4L2_CTRL_FLAG_SLIDER,
+	},
+	/* Blue Gain */
+	{
+		.ops = &xcsc_ctrl_ops,
+		.id = V4L2_CID_XILINX_CSC_BLUE_GAIN,
+		.name = "CSC Blue Gain",
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.min = 0,
+		.max = 100,
+		.step = 1,
+		.def = XCSC_COLOR_CTRL_DEFAULT,
+		.flags = V4L2_CTRL_FLAG_SLIDER,
+	},
+	/* Green Gain */
+	{
+		.ops = &xcsc_ctrl_ops,
+		.id = V4L2_CID_XILINX_CSC_GREEN_GAIN,
+		.name = "CSC Green Gain",
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.min = 0,
+		.max = 100,
+		.step = 1,
+		.def = XCSC_COLOR_CTRL_DEFAULT,
+		.flags = V4L2_CTRL_FLAG_SLIDER,
+	},
+};
+
+static int xcsc_open(struct v4l2_subdev *subdev,
+		     struct v4l2_subdev_fh *fh)
+{
+	struct xcsc_dev *xcsc = to_csc(subdev);
+	struct v4l2_mbus_framefmt *format;
+
+	/* Initialize with default formats */
+	format = v4l2_subdev_get_try_format(subdev, fh->pad, XVIP_PAD_SINK);
+	*format = xcsc->default_formats[XVIP_PAD_SINK];
+
+	format = v4l2_subdev_get_try_format(subdev, fh->pad, XVIP_PAD_SOURCE);
+	*format = xcsc->default_formats[XVIP_PAD_SOURCE];
+
+	return 0;
+}
+
+static int xcsc_close(struct v4l2_subdev *subdev,
+		      struct v4l2_subdev_fh *fh)
+{
+	return 0;
+}
+
+static const struct v4l2_subdev_internal_ops xcsc_internal_ops = {
+	.open  = xcsc_open,
+	.close = xcsc_close,
+};
+
+static const struct media_entity_operations xcsc_media_ops = {
+	.link_validate = v4l2_subdev_link_validate,
+};
+
+static int xcsc_parse_of(struct xcsc_dev *xcsc)
+{
+	struct device *dev = xcsc->xvip.dev;
+	struct device_node *node = xcsc->xvip.dev->of_node;
+	const struct xvip_video_format *vip_format;
+	struct device_node *ports, *port;
+	int rval;
+	u32 port_id = 0;
+	u32 video_width[2] = {0};
+
+	rval = of_property_read_u32(node, "xlnx,max-height", &xcsc->max_height);
+	if (rval < 0) {
+		dev_err(dev, "xlnx,max-height is missing!");
+		return -EINVAL;
+	} else if (xcsc->max_height > XV_CSC_MAX_HEIGHT ||
+		   xcsc->max_height < XV_CSC_MIN_HEIGHT) {
+		dev_err(dev, "Invalid height in dt");
+		return -EINVAL;
+	}
+
+	rval = of_property_read_u32(node, "xlnx,max-width", &xcsc->max_width);
+	if (rval < 0) {
+		dev_err(dev, "xlnx,max-width is missing!");
+		return -EINVAL;
+	} else if (xcsc->max_width > XV_CSC_MAX_WIDTH ||
+		   xcsc->max_width < XV_CSC_MIN_WIDTH) {
+		dev_err(dev, "Invalid width in dt");
+		return -EINVAL;
+	}
+
+	ports = of_get_child_by_name(node, "ports");
+	if (!ports)
+		ports = node;
+
+	/* Get the format description for each pad */
+	for_each_child_of_node(ports, port) {
+		if (port->name && (of_node_cmp(port->name, "port") == 0)) {
+			vip_format = xvip_of_get_format(port);
+			if (IS_ERR(vip_format)) {
+				dev_err(dev, "Invalid media pad format in DT");
+				return PTR_ERR(vip_format);
+			}
+
+			rval = of_property_read_u32(port, "reg", &port_id);
+			if (rval < 0) {
+				dev_err(dev, "No reg in DT to specify pad");
+				return rval;
+			}
+
+			if (port_id != 0 && port_id != 1) {
+				dev_err(dev, "Invalid reg in DT");
+				return -EINVAL;
+			}
+			xcsc->vip_formats[port_id] = vip_format;
+
+			rval = of_property_read_u32(port, "xlnx,video-width",
+						    &video_width[port_id]);
+			if (rval < 0) {
+				dev_err(dev,
+					"DT Port%d xlnx,video-width not found",
+					port_id);
+				return rval;
+			}
+		}
+	}
+	if (video_width[0] != video_width[1]) {
+		dev_err(dev, "Changing video width in DT not supported");
+		return -EINVAL;
+	}
+	switch (video_width[0]) {
+	case XVIDC_BPC_8:
+		xcsc->color_depth = XVIDC_BPC_8;
+		break;
+	case XVIDC_BPC_10:
+		xcsc->color_depth = XVIDC_BPC_10;
+		break;
+	default:
+		dev_err(dev, "Unsupported color depth %d", video_width[0]);
+		return -EINVAL;
+	}
+	/* Reset GPIO */
+	xcsc->rst_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(xcsc->rst_gpio)) {
+		if (PTR_ERR(xcsc->rst_gpio) != -EPROBE_DEFER)
+			dev_err(dev, "Reset GPIO not setup in DT");
+		return PTR_ERR(xcsc->rst_gpio);
+	}
+	return 0;
+}
+
+static int xcsc_probe(struct platform_device *pdev)
+{
+	struct xcsc_dev *xcsc;
+	struct v4l2_subdev *subdev;
+	struct v4l2_mbus_framefmt *def_fmt;
+	int rval, itr;
+
+	xcsc = devm_kzalloc(&pdev->dev, sizeof(*xcsc), GFP_KERNEL);
+	if (!xcsc)
+		return -ENOMEM;
+
+	xcsc->xvip.dev = &pdev->dev;
+
+	rval = xcsc_parse_of(xcsc);
+	if (rval < 0)
+		return rval;
+
+	/* Reset and initialize the core */
+	gpiod_set_value_cansleep(xcsc->rst_gpio, XCSC_RESET_DEASSERT);
+	rval = xvip_init_resources(&xcsc->xvip);
+	if (rval < 0)
+		return rval;
+
+	/* Init v4l2 subdev */
+	subdev = &xcsc->xvip.subdev;
+	v4l2_subdev_init(subdev, &xcsc_ops);
+	subdev->dev = &pdev->dev;
+	subdev->internal_ops = &xcsc_internal_ops;
+	strlcpy(subdev->name, dev_name(&pdev->dev), sizeof(subdev->name));
+	v4l2_set_subdevdata(subdev, xcsc);
+	subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	/* Default Formats Initialization */
+	xcsc_set_default_state(xcsc);
+	def_fmt = &xcsc->default_formats[XVIP_PAD_SINK];
+	def_fmt->code = xcsc->vip_formats[XVIP_PAD_SINK]->code;
+	def_fmt->field = V4L2_FIELD_NONE;
+	def_fmt->colorspace = V4L2_COLORSPACE_REC709;
+	def_fmt->width = XV_CSC_DEFAULT_WIDTH;
+	def_fmt->height = XV_CSC_DEFAULT_HEIGHT;
+	xcsc->formats[XVIP_PAD_SINK] = *def_fmt;
+	/* Source supports only YUV 444, YUV 422, and RGB */
+	def_fmt = &xcsc->default_formats[XVIP_PAD_SOURCE];
+	*def_fmt = xcsc->default_formats[XVIP_PAD_SINK];
+	def_fmt->code = xcsc->vip_formats[XVIP_PAD_SOURCE]->code;
+	def_fmt->width = XV_CSC_DEFAULT_WIDTH;
+	def_fmt->height = XV_CSC_DEFAULT_HEIGHT;
+	xcsc->formats[XVIP_PAD_SOURCE] = *def_fmt;
+	xcsc->pads[XVIP_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+	xcsc->pads[XVIP_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+
+	/* Init Media Entity */
+	subdev->entity.ops = &xcsc_media_ops;
+	rval = media_entity_pads_init(&subdev->entity, 2, xcsc->pads);
+	if (rval < 0)
+		goto media_error;
+	/* V4L2 Control Setup */
+	v4l2_ctrl_handler_init(&xcsc->ctrl_handler,
+			       ARRAY_SIZE(xcsc_color_ctrls));
+	for (itr = 0; itr < ARRAY_SIZE(xcsc_color_ctrls); itr++) {
+		xcsc->custom_ctrls[itr] =
+			v4l2_ctrl_new_custom(&xcsc->ctrl_handler,
+					     &xcsc_color_ctrls[itr], NULL);
+	}
+	if (xcsc->ctrl_handler.error) {
+		dev_err(&pdev->dev, "Failed to add  v4l2 controls");
+		rval = xcsc->ctrl_handler.error;
+		goto ctrl_error;
+	}
+	subdev->ctrl_handler = &xcsc->ctrl_handler;
+	rval = v4l2_ctrl_handler_setup(&xcsc->ctrl_handler);
+	if (rval < 0) {
+		dev_err(xcsc->xvip.dev, "Failed to setup control handler");
+		goto ctrl_error;
+	}
+	platform_set_drvdata(pdev, xcsc);
+	rval = v4l2_async_register_subdev(subdev);
+	if (rval < 0) {
+		dev_err(&pdev->dev, "failed to register subdev\n");
+		goto ctrl_error;
+	}
+	dev_info(&pdev->dev, "VPSS CSC %d-bit Color Depth Probe Successful",
+		 xcsc->color_depth);
+	return 0;
+ctrl_error:
+	v4l2_ctrl_handler_free(&xcsc->ctrl_handler);
+	media_entity_cleanup(&subdev->entity);
+media_error:
+	xvip_cleanup_resources(&xcsc->xvip);
+	return rval;
+}
+
+static int xcsc_remove(struct platform_device *pdev)
+{
+	struct xcsc_dev *xcsc = platform_get_drvdata(pdev);
+	struct v4l2_subdev *subdev = &xcsc->xvip.subdev;
+
+	v4l2_async_unregister_subdev(subdev);
+	v4l2_ctrl_handler_free(&xcsc->ctrl_handler);
+	media_entity_cleanup(&subdev->entity);
+	xvip_cleanup_resources(&xcsc->xvip);
+	return 0;
+}
+
+static const struct of_device_id xcsc_of_id_table[] = {
+	{.compatible = "xlnx,v-vpss-csc"},
+	{ }
+};
+
+MODULE_DEVICE_TABLE(of, xcsc_of_id_table);
+
+static struct platform_driver xcsc_driver = {
+	.driver = {
+		.name = "xilinx-vpss-csc",
+		.of_match_table = xcsc_of_id_table,
+	},
+	.probe = xcsc_probe,
+	.remove = xcsc_remove,
+};
+
+module_platform_driver(xcsc_driver);
+MODULE_DESCRIPTION("Xilinx VPSS CSC Driver");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/xilinx-vpss-scaler.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/xilinx-vpss-scaler.c
@@ -0,0 +1,2122 @@
+/*
+ * Xilinx VPSS Scaler
+ *
+ * Copyright (C) 2017 Xilinx, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#include <media/v4l2-async.h>
+#include <media/v4l2-subdev.h>
+#include "xilinx-vip.h"
+
+#define XSCALER_MIN_WIDTH		(64)
+#define XSCALER_MAX_WIDTH		(8192)
+#define XSCALER_MIN_HEIGHT		(64)
+#define XSCALER_MAX_HEIGHT		(4320)
+#define XSCALER_MAX_PHASES		(64)
+
+/* Modify to defaults incase it is not configured from application */
+#define XSCALER_DEF_IN_HEIGHT		(720)
+#define XSCALER_DEF_IN_WIDTH		(1280)
+#define XSCALER_DEF_OUT_HEIGHT		(1080)
+#define XSCALER_DEF_OUT_WIDTH		(1920)
+
+#define XSCALER_HSF			(0x0100)
+#define XSCALER_VSF			(0x0104)
+#define XSCALER_SF_SHIFT		(20)
+#define XSCALER_SF_MASK			(0xffffff)
+#define XSCALER_SOURCE_SIZE		(0x0108)
+#define XSCALER_SIZE_HORZ_SHIFT		(0)
+#define XSCALER_SIZE_VERT_SHIFT		(16)
+#define XSCALER_SIZE_MASK		(0xfff)
+#define XSCALER_HAPERTURE		(0x010c)
+#define XSCALER_VAPERTURE		(0x0110)
+#define XSCALER_APERTURE_START_SHIFT	(0)
+#define XSCALER_APERTURE_END_SHIFT	(16)
+#define XSCALER_OUTPUT_SIZE		(0x0114)
+#define XSCALER_COEF_DATA_IN		(0x0134)
+#define XSCALER_BITSHIFT_16		(16)
+
+/* Video subsytems block offset */
+#define S_AXIS_RESET_OFF	(0x00010000)
+#define V_HSCALER_OFF		(0x00000000)
+#define V_VSCALER_OFF		(0x00020000)
+
+/* HW Reset Network GPIO Channel */
+#define XGPIO_CH_RESET_SEL		(1)
+#define XGPIO_RESET_MASK_VIDEO_IN	BIT(0)
+#define XGPIO_RESET_MASK_IP_AXIS	BIT(1)
+#define XGPIO_RESET_MASK_IP_AXIMM	BIT(0)
+#define XGPIO_RESET_MASK_ALL_BLOCKS	(XGPIO_RESET_MASK_VIDEO_IN  | \
+						XGPIO_RESET_MASK_IP_AXIS)
+#define XGPIO_DATA_OFFSET		(0x0)
+#define XGPIO_TRI_OFFSET		(0x4)
+#define XGPIO_DATA2_OFFSET		(0x8)
+#define XGPIO_TRI2_OFFSET		(0xc)
+
+#define XGPIO_GIE_OFFSET		(0x11c)
+#define XGPIO_ISR_OFFSET		(0x120)
+#define XGPIO_IER_OFFSET		(0x128)
+#define XGPIO_CHAN_OFFSET		(8)
+#define STEP_PRECISION			(65536)
+
+/* Video IP Formats */
+enum xscaler_vid_reg_fmts {
+	XVIDC_CSF_RGB = 0,
+	XVIDC_CSF_YCRCB_444,
+	XVIDC_CSF_YCRCB_422,
+	XVIDC_CSF_YCRCB_420,
+};
+
+/* Video IP PPC */
+#define XSCALER_PPC_1			(1)
+#define XSCALER_PPC_2			(2)
+#define XSCALER_PPC_4			(4)
+
+#define XV_HSCALER_MAX_H_TAPS           (12)
+#define XV_HSCALER_MAX_H_PHASES         (64)
+#define XV_HSCALER_MAX_LINE_WIDTH       (3840)
+#define XV_VSCALER_MAX_V_TAPS           (12)
+#define XV_VSCALER_MAX_V_PHASES         (64)
+
+#define XV_HSCALER_TAPS_2		(2)
+#define XV_HSCALER_TAPS_4		(4)
+#define XV_HSCALER_TAPS_6		(6)
+#define XV_HSCALER_TAPS_8		(8)
+#define XV_HSCALER_TAPS_10		(10)
+#define XV_HSCALER_TAPS_12		(12)
+#define XV_VSCALER_TAPS_2		(2)
+#define XV_VSCALER_TAPS_4		(4)
+#define XV_VSCALER_TAPS_6		(6)
+#define XV_VSCALER_TAPS_8		(8)
+#define XV_VSCALER_TAPS_10		(10)
+#define XV_VSCALER_TAPS_12		(12)
+
+/* Mask definitions for Low and high 16 bits in a 32 bit number */
+#define XHSC_MASK_LOW_16BITS		GENMASK(15, 0)
+#define XHSC_MASK_HIGH_16BITS		GENMASK(31, 16)
+#define XHSC_MASK_LOW_32BITS		GENMASK(31, 0)
+#define XHSC_STEP_PRECISION_SHIFT	(16)
+#define XHSC_HPHASE_SHIFT_BY_6		(6)
+#define XHSC_HPHASE_MULTIPLIER		(9)
+#define XHSC_HPHASE_MUL_4PPC		(10)
+
+/* Mask definitions for Low and high 16 bits in a 32 bit number */
+#define XVSC_MASK_LOW_16BITS            GENMASK(15, 0)
+#define XVSC_MASK_HIGH_16BITS           GENMASK(31, 16)
+
+/* XSCALER POWER MACROS */
+#define XSCALER_RESET_ASSERT	(0x1)
+#define XSCALER_RESET_DEASSERT	(0x0)
+
+/* Scaler AP Control Registers */
+#define XSCALER_START		BIT(0)
+#define XSCALER_AUTO_RESTART	BIT(7)
+#define XSCALER_STREAM_ON	(XSCALER_START | XSCALER_AUTO_RESTART)
+
+/* H-scaler registers */
+#define XV_HSCALER_CTRL_ADDR_AP_CTRL				(0x0000)
+#define XV_HSCALER_CTRL_ADDR_GIE				(0x0004)
+#define XV_HSCALER_CTRL_ADDR_IER				(0x0008)
+#define XV_HSCALER_CTRL_ADDR_ISR				(0x000c)
+#define XV_HSCALER_CTRL_ADDR_HWREG_HEIGHT_DATA			(0x0010)
+#define XV_HSCALER_CTRL_ADDR_HWREG_WIDTHIN_DATA			(0x0018)
+#define XV_HSCALER_CTRL_ADDR_HWREG_WIDTHOUT_DATA		(0x0020)
+#define XV_HSCALER_CTRL_ADDR_HWREG_COLORMODE_DATA		(0x0028)
+#define XV_HSCALER_CTRL_ADDR_HWREG_PIXELRATE_DATA		(0x0030)
+#define XV_HSCALER_CTRL_ADDR_HWREG_COLORMODEOUT_DATA		(0X0038)
+#define XV_HSCALER_CTRL_ADDR_HWREG_HFLTCOEFF_BASE		(0x0800)
+#define XV_HSCALER_CTRL_ADDR_HWREG_HFLTCOEFF_HIGH		(0x0bff)
+
+/* Coefficients for 6, 8, 10 and 12 tap filters */
+
+static const s16 XV_lanczos2_taps6[XV_HSCALER_MAX_H_PHASES][XV_HSCALER_TAPS_6] = {
+	{   0,    0, 4096,    0,    0,   0, },
+	{   0,  -40, 4099,   42,    0,  -5, },
+	{  -1,  -77, 4097,   87,   -1,  -9, },
+	{  -2, -111, 4092,  134,   -2, -15, },
+	{  -4, -143, 4082,  184,   -4, -19, },
+	{  -6, -173, 4068,  237,   -7, -23, },
+	{  -8, -201, 4051,  292,  -10, -28, },
+	{ -11, -226, 4029,  350,  -13, -33, },
+	{ -14, -248, 4003,  411,  -18, -38, },
+	{ -17, -269, 3974,  474,  -23, -43, },
+	{ -21, -287, 3940,  539,  -28, -47, },
+	{ -24, -303, 3903,  608,  -34, -54, },
+	{ -28, -317, 3862,  678,  -41, -58, },
+	{ -32, -329, 3817,  751,  -49, -62, },
+	{ -37, -339, 3768,  826,  -57, -65, },
+	{ -41, -347, 3716,  903,  -65, -70, },
+	{ -45, -353, 3661,  982,  -75, -74, },
+	{ -50, -358, 3602, 1063,  -84, -77, },
+	{ -54, -361, 3539, 1146,  -95, -79, },
+	{ -58, -362, 3474, 1230, -106, -82, },
+	{ -62, -361, 3406, 1317, -117, -87, },
+	{ -66, -359, 3335, 1404, -128, -90, },
+	{ -70, -356, 3261, 1493, -140, -92, },
+	{ -74, -351, 3185, 1583, -153, -94, },
+	{ -77, -346, 3106, 1673, -165, -95, },
+	{ -81, -339, 3025, 1765, -178, -96, },
+	{ -84, -331, 2942, 1857, -191, -97, },
+	{ -87, -322, 2858, 1950, -204, -99, },
+	{ -89, -313, 2771, 2043, -217, -99, },
+	{ -92, -302, 2683, 2136, -230, -99, },
+	{ -94, -292, 2594, 2228, -243, -97, },
+	{ -95, -280, 2504, 2321, -256, -98, },
+	{ -97, -268, 2413, 2413, -268, -97, },
+	{ -97, -256, 2321, 2504, -280, -96, },
+	{ -98, -243, 2228, 2594, -292, -93, },
+	{ -98, -230, 2136, 2683, -302, -93, },
+	{ -98, -217, 2043, 2771, -313, -90, },
+	{ -98, -204, 1950, 2858, -322, -88, },
+	{ -97, -191, 1857, 2942, -331, -84, },
+	{ -96, -178, 1765, 3025, -339, -81, },
+	{ -95, -165, 1673, 3106, -346, -77, },
+	{ -93, -153, 1583, 3185, -351, -75, },
+	{ -91, -140, 1493, 3261, -356, -71, },
+	{ -89, -128, 1404, 3335, -359, -67, },
+	{ -86, -117, 1317, 3406, -361, -63, },
+	{ -83, -106, 1230, 3474, -362, -57, },
+	{ -80,  -95, 1146, 3539, -361, -53, },
+	{ -77,  -84, 1063, 3602, -358, -50, },
+	{ -73,  -75,  982, 3661, -353, -46, },
+	{ -69,  -65,  903, 3716, -347, -42, },
+	{ -65,  -57,  826, 3768, -339, -37, },
+	{ -61,  -49,  751, 3817, -329, -33, },
+	{ -57,  -41,  678, 3862, -317, -29, },
+	{ -52,  -34,  608, 3903, -303, -26, },
+	{ -47,  -28,  539, 3940, -287, -21, },
+	{ -43,  -23,  474, 3974, -269, -17, },
+	{ -38,  -18,  411, 4003, -248, -14, },
+	{ -33,  -13,  350, 4029, -226, -11, },
+	{ -28,  -10,  292, 4051, -201,  -8, },
+	{ -24,   -7,  237, 4068, -173,  -5, },
+	{ -19,   -4,  184, 4082, -143,  -4, },
+	{ -14,   -2,  134, 4092, -111,  -3, },
+	{  -9,   -1,   87, 4097,  -77,  -1, },
+	{  -5,    0,   42, 4099,  -40,   0, }
+};
+
+/* ScalingRatio = 1.25 */
+static const s16 XV_fixedcoeff_taps6_SR1p2[XV_HSCALER_MAX_H_PHASES][XV_HSCALER_TAPS_6] = {
+	{ -102,  512, 3208,  512, -102,  68, },
+	{  -97,  471, 3209,  555, -107,  65, },
+	{  -92,  431, 3208,  599, -113,  63, },
+	{  -87,  392, 3205,  645, -118,  59, },
+	{  -82,  354, 3199,  691, -124,  58, },
+	{  -77,  318, 3191,  739, -130,  55, },
+	{  -72,  282, 3181,  788, -136,  53, },
+	{  -68,  248, 3169,  838, -141,  50, },
+	{  -64,  216, 3155,  889, -147,  47, },
+	{  -59,  184, 3139,  941, -153,  44, },
+	{  -55,  154, 3120,  993, -158,  42, },
+	{  -52,  125, 3100, 1047, -164,  40, },
+	{  -48,   98, 3077, 1101, -169,  37, },
+	{  -44,   71, 3052, 1157, -174,  34, },
+	{  -41,   46, 3025, 1212, -180,  34, },
+	{  -38,   23, 2996, 1269, -184,  30, },
+	{  -35,    0, 2965, 1326, -189,  29, },
+	{  -32,  -21, 2933, 1383, -193,  26, },
+	{  -29,  -41, 2898, 1441, -198,  25, },
+	{  -26,  -60, 2862, 1500, -201,  21, },
+	{  -24,  -78, 2823, 1558, -205,  22, },
+	{  -21,  -94, 2784, 1617, -208,  18, },
+	{  -19, -109, 2742, 1676, -210,  16, },
+	{  -17, -123, 2699, 1734, -212,  15, },
+	{  -14, -136, 2654, 1793, -214,  13, },
+	{  -12, -148, 2608, 1852, -214,  10, },
+	{  -10, -159, 2560, 1910, -215,  10, },
+	{   -9, -168, 2512, 1968, -215,   8, },
+	{   -7, -177, 2461, 2026, -214,   7, },
+	{   -5, -185, 2410, 2083, -212,   5, },
+	{   -3, -192, 2358, 2139, -209,   3, },
+	{   -2, -197, 2304, 2195, -206,   2, },
+	{    0, -202, 2250, 2250, -202,   0, },
+	{    2, -206, 2195, 2304, -197,  -2, },
+	{    3, -209, 2139, 2358, -192,  -3, },
+	{    5, -212, 2083, 2410, -185,  -5, },
+	{    6, -214, 2026, 2461, -177,  -6, },
+	{    8, -215, 1968, 2512, -168,  -9, },
+	{   10, -215, 1910, 2560, -159, -10, },
+	{   11, -214, 1852, 2608, -148, -13, },
+	{   13, -214, 1793, 2654, -136, -14, },
+	{   15, -212, 1734, 2699, -123, -17, },
+	{   17, -210, 1676, 2742, -109, -20, },
+	{   18, -208, 1617, 2784,  -94, -21, },
+	{   20, -205, 1558, 2823,  -78, -22, },
+	{   22, -201, 1500, 2862,  -60, -27, },
+	{   24, -198, 1441, 2898,  -41, -28, },
+	{   26, -193, 1383, 2933,  -21, -32, },
+	{   28, -189, 1326, 2965,    0, -34, },
+	{   30, -184, 1269, 2996,   23, -38, },
+	{   33, -180, 1212, 3025,   46, -40, },
+	{   35, -174, 1157, 3052,   71, -45, },
+	{   37, -169, 1101, 3077,   98, -48, },
+	{   40, -164, 1047, 3100,  125, -52, },
+	{   42, -158,  993, 3120,  154, -55, },
+	{   44, -153,  941, 3139,  184, -59, },
+	{   47, -147,  889, 3155,  216, -64, },
+	{   50, -141,  838, 3169,  248, -68, },
+	{   52, -136,  788, 3181,  282, -71, },
+	{   55, -130,  739, 3191,  318, -77, },
+	{   57, -124,  691, 3199,  354, -81, },
+	{   60, -118,  645, 3205,  392, -88, },
+	{   63, -113,  599, 3208,  431, -92, },
+	{   65, -107,  555, 3209,  471, -97, }
+};
+
+/* ScalingRatio = 2.0 */
+static const s16 XV_fixedcoeff_taps6_SR2[XV_HSCALER_MAX_H_PHASES][XV_HSCALER_TAPS_6] = {
+	{   0, 970, 2235,  970,   0, -79, },
+	{  -3, 943, 2233,  997,   3, -77, },
+	{  -5, 915, 2231, 1025,   6, -76, },
+	{  -8, 888, 2227, 1052,  10, -73, },
+	{ -10, 861, 2223, 1079,  14, -71, },
+	{ -12, 834, 2218, 1107,  18, -69, },
+	{ -14, 808, 2213, 1134,  22, -67, },
+	{ -15, 782, 2206, 1162,  27, -66, },
+	{ -17, 756, 2199, 1189,  32, -63, },
+	{ -18, 731, 2191, 1217,  37, -62, },
+	{ -20, 706, 2182, 1245,  42, -59, },
+	{ -21, 681, 2172, 1272,  48, -56, },
+	{ -22, 657, 2162, 1300,  55, -56, },
+	{ -22, 633, 2151, 1327,  61, -54, },
+	{ -23, 609, 2139, 1355,  68, -52, },
+	{ -24, 586, 2126, 1382,  76, -50, },
+	{ -25, 564, 2113, 1410,  83, -49, },
+	{ -25, 541, 2099, 1437,  91, -47, },
+	{ -26, 520, 2084, 1464, 100, -46, },
+	{ -26, 498, 2069, 1491, 109, -45, },
+	{ -27, 477, 2053, 1517, 118, -42, },
+	{ -27, 457, 2036, 1544, 128, -42, },
+	{ -27, 437, 2019, 1570, 138, -41, },
+	{ -28, 418, 2001, 1596, 148, -39, },
+	{ -28, 399, 1983, 1622, 160, -40, },
+	{ -29, 380, 1964, 1647, 171, -37, },
+	{ -29, 362, 1944, 1672, 183, -36, },
+	{ -29, 345, 1924, 1697, 195, -36, },
+	{ -30, 328, 1903, 1722, 208, -35, },
+	{ -30, 311, 1882, 1746, 221, -34, },
+	{ -31, 295, 1860, 1770, 235, -33, },
+	{ -31, 279, 1838, 1793, 249, -32, },
+	{ -32, 264, 1816, 1816, 264, -32, },
+	{ -32, 249, 1793, 1838, 279, -31, },
+	{ -33, 235, 1770, 1860, 295, -31, },
+	{ -34, 221, 1746, 1882, 311, -30, },
+	{ -35, 208, 1722, 1903, 328, -30, },
+	{ -35, 195, 1697, 1924, 345, -30, },
+	{ -36, 183, 1672, 1944, 362, -29, },
+	{ -37, 171, 1647, 1964, 380, -29, },
+	{ -38, 160, 1622, 1983, 399, -30, },
+	{ -39, 148, 1596, 2001, 418, -28, },
+	{ -40, 138, 1570, 2019, 437, -28, },
+	{ -42, 128, 1544, 2036, 457, -27, },
+	{ -43, 118, 1517, 2053, 477, -26, },
+	{ -44, 109, 1491, 2069, 498, -27, },
+	{ -46, 100, 1464, 2084, 520, -26, },
+	{ -47,  91, 1437, 2099, 541, -25, },
+	{ -49,  83, 1410, 2113, 564, -25, },
+	{ -50,  76, 1382, 2126, 586, -24, },
+	{ -52,  68, 1355, 2139, 609, -23, },
+	{ -54,  61, 1327, 2151, 633, -22, },
+	{ -55,  55, 1300, 2162, 657, -23, },
+	{ -57,  48, 1272, 2172, 681, -20, },
+	{ -59,  42, 1245, 2182, 706, -20, },
+	{ -61,  37, 1217, 2191, 731, -19, },
+	{ -63,  32, 1189, 2199, 756, -17, },
+	{ -65,  27, 1162, 2206, 782, -16, },
+	{ -67,  22, 1134, 2213, 808, -14, },
+	{ -69,  18, 1107, 2218, 834, -12, },
+	{ -71,  14, 1079, 2223, 861, -10, },
+	{ -73,  10, 1052, 2227, 888,  -8, },
+	{ -75,   6, 1025, 2231, 915,  -6, },
+	{ -77,   3,  997, 2233, 943,  -3, }
+};
+
+/* ScalingRatio = 3.0 */
+static const s16 XV_fixedcoeff_taps6_SR3[XV_HSCALER_MAX_H_PHASES][XV_HSCALER_TAPS_6] = {
+	{ 126, 1019, 1806, 1019,  126,   0, },
+	{ 120, 1000, 1805, 1038,  132,   1, },
+	{ 114,  980, 1804, 1057,  138,   3, },
+	{ 108,  961, 1802, 1075,  145,   5, },
+	{ 103,  942, 1800, 1094,  152,   5, },
+	{  98,  922, 1797, 1113,  159,   7, },
+	{  93,  903, 1794, 1131,  167,   8, },
+	{  88,  884, 1790, 1150,  174,  10, },
+	{  84,  865, 1786, 1168,  182,  11, },
+	{  80,  846, 1782, 1187,  191,  10, },
+	{  76,  827, 1777, 1205,  199,  12, },
+	{  72,  809, 1771, 1223,  208,  13, },
+	{  68,  790, 1766, 1241,  217,  14, },
+	{  65,  772, 1759, 1259,  226,  15, },
+	{  61,  753, 1753, 1277,  236,  16, },
+	{  58,  735, 1746, 1295,  246,  16, },
+	{  56,  717, 1738, 1313,  256,  16, },
+	{  53,  699, 1730, 1330,  266,  18, },
+	{  50,  682, 1722, 1347,  277,  18, },
+	{  48,  664, 1713, 1364,  288,  19, },
+	{  46,  647, 1704, 1381,  299,  19, },
+	{  43,  630, 1694, 1398,  311,  20, },
+	{  41,  613, 1684, 1414,  323,  21, },
+	{  40,  596, 1674, 1430,  335,  21, },
+	{  38,  580, 1663, 1446,  347,  22, },
+	{  36,  563, 1652, 1462,  360,  23, },
+	{  35,  547, 1641, 1478,  373,  22, },
+	{  33,  531, 1629, 1493,  386,  24, },
+	{  32,  516, 1617, 1508,  399,  24, },
+	{  31,  500, 1604, 1523,  413,  25, },
+	{  30,  485, 1592, 1537,  427,  25, },
+	{  29,  470, 1578, 1551,  441,  27, },
+	{  28,  455, 1565, 1565,  455,  28, },
+	{  27,  441, 1551, 1578,  470,  29, },
+	{  26,  427, 1537, 1592,  485,  29, },
+	{  25,  413, 1523, 1604,  500,  31, },
+	{  24,  399, 1508, 1617,  516,  32, },
+	{  24,  386, 1493, 1629,  531,  33, },
+	{  23,  373, 1478, 1641,  547,  34, },
+	{  22,  360, 1462, 1652,  563,  37, },
+	{  22,  347, 1446, 1663,  580,  38, },
+	{  21,  335, 1430, 1674,  596,  40, },
+	{  20,  323, 1414, 1684,  613,  42, },
+	{  20,  311, 1398, 1694,  630,  43, },
+	{  19,  299, 1381, 1704,  647,  46, },
+	{  19,  288, 1364, 1713,  664,  48, },
+	{  18,  277, 1347, 1722,  682,  50, },
+	{  17,  266, 1330, 1730,  699,  54, },
+	{  17,  256, 1313, 1738,  717,  55, },
+	{  16,  246, 1295, 1746,  735,  58, },
+	{  15,  236, 1277, 1753,  753,  62, },
+	{  15,  226, 1259, 1759,  772,  65, },
+	{  14,  217, 1241, 1766,  790,  68, },
+	{  13,  208, 1223, 1771,  809,  72, },
+	{  12,  199, 1205, 1777,  827,  76, },
+	{  11,  191, 1187, 1782,  846,  79, },
+	{  10,  182, 1168, 1786,  865,  85, },
+	{   9,  174, 1150, 1790,  884,  89, },
+	{   8,  167, 1131, 1794,  903,  93, },
+	{   7,  159, 1113, 1797,  922,  98, },
+	{   6,  152, 1094, 1800,  942, 102, },
+	{   5,  145, 1075, 1802,  961, 108, },
+	{   3,  138, 1057, 1804,  980, 114, },
+	{   2,  132, 1038, 1805, 1000, 119, }
+};
+
+/* ScalingRatio = 4 */
+static const s16 XV_fixedcoeff_taps6_SR4[XV_HSCALER_MAX_H_PHASES][XV_HSCALER_TAPS_6] = {
+	{ 176, 1009, 1643, 1009, 176,  83, },
+	{ 169,  993, 1644, 1026, 183,  81, },
+	{ 162,  978, 1644, 1042, 190,  80, },
+	{ 156,  962, 1643, 1058, 198,  79, },
+	{ 150,  946, 1642, 1074, 205,  79, },
+	{ 144,  930, 1641, 1091, 213,  77, },
+	{ 138,  914, 1640, 1107, 222,  75, },
+	{ 133,  898, 1638, 1123, 230,  74, },
+	{ 128,  882, 1635, 1139, 239,  73, },
+	{ 123,  866, 1633, 1154, 248,  72, },
+	{ 118,  850, 1629, 1170, 257,  72, },
+	{ 114,  834, 1626, 1186, 267,  69, },
+	{ 109,  818, 1622, 1201, 276,  70, },
+	{ 105,  802, 1618, 1217, 286,  68, },
+	{ 101,  786, 1613, 1232, 297,  67, },
+	{  97,  771, 1608, 1247, 307,  66, },
+	{  94,  755, 1603, 1262, 318,  64, },
+	{  91,  739, 1597, 1276, 328,  65, },
+	{  87,  724, 1591, 1291, 339,  64, },
+	{  85,  708, 1585, 1305, 351,  62, },
+	{  82,  693, 1578, 1319, 362,  62, },
+	{  79,  677, 1571, 1333, 374,  62, },
+	{  77,  662, 1563, 1347, 386,  61, },
+	{  75,  647, 1556, 1360, 398,  60, },
+	{  73,  632, 1547, 1373, 410,  61, },
+	{  71,  617, 1539, 1386, 423,  60, },
+	{  69,  602, 1530, 1399, 436,  60, },
+	{  68,  587, 1521, 1412, 449,  59, },
+	{  66,  573, 1511, 1424, 462,  60, },
+	{  65,  558, 1501, 1436, 475,  61, },
+	{  64,  544, 1491, 1447, 488,  62, },
+	{  63,  530, 1481, 1459, 502,  61, },
+	{  62,  516, 1470, 1470, 516,  62, },
+	{  62,  502, 1459, 1481, 530,  62, },
+	{  61,  488, 1447, 1491, 544,  65, },
+	{  61,  475, 1436, 1501, 558,  65, },
+	{  60,  462, 1424, 1511, 573,  66, },
+	{  60,  449, 1412, 1521, 587,  67, },
+	{  60,  436, 1399, 1530, 602,  69, },
+	{  60,  423, 1386, 1539, 617,  71, },
+	{  61,  410, 1373, 1547, 632,  73, },
+	{  61,  398, 1360, 1556, 647,  74, },
+	{  61,  386, 1347, 1563, 662,  77, },
+	{  62,  374, 1333, 1571, 677,  79, },
+	{  62,  362, 1319, 1578, 693,  82, },
+	{  63,  351, 1305, 1585, 708,  84, },
+	{  64,  339, 1291, 1591, 724,  87, },
+	{  64,  328, 1276, 1597, 739,  92, },
+	{  65,  318, 1262, 1603, 755,  93, },
+	{  66,  307, 1247, 1608, 771,  97, },
+	{  67,  297, 1232, 1613, 786, 101, },
+	{  68,  286, 1217, 1618, 802, 105, },
+	{  69,  276, 1201, 1622, 818, 110, },
+	{  70,  267, 1186, 1626, 834, 113, },
+	{  71,  257, 1170, 1629, 850, 119, },
+	{  72,  248, 1154, 1633, 866, 123, },
+	{  73,  239, 1139, 1635, 882, 128, },
+	{  75,  230, 1123, 1638, 898, 132, },
+	{  76,  222, 1107, 1640, 914, 137, },
+	{  77,  213, 1091, 1641, 930, 144, },
+	{  78,  205, 1074, 1642, 946, 151, },
+	{  79,  198, 1058, 1643, 962, 156, },
+	{  80,  190, 1042, 1644, 978, 162, },
+	{  82,  183, 1026, 1644, 993, 168, }
+};
+
+/* ScalingRatio = 2.0 */
+static const s16 XV_fixedcoeff_taps8_SR2[XV_HSCALER_MAX_H_PHASES][XV_HSCALER_TAPS_8] = {
+	{ -55,   0, 1078, 2049, 1078,    0, -55,   1, },
+	{ -53,  -7, 1055, 2049, 1102,    7, -56,  -1, },
+	{ -52, -13, 1032, 2048, 1126,   15, -58,  -2, },
+	{ -50, -20, 1009, 2047, 1149,   22, -59,  -2, },
+	{ -49, -26,  986, 2046, 1173,   31, -61,  -4, },
+	{ -47, -31,  963, 2043, 1197,   39, -62,  -6, },
+	{ -46, -37,  940, 2040, 1220,   48, -64,  -5, },
+	{ -45, -42,  917, 2037, 1244,   57, -65,  -7, },
+	{ -43, -47,  894, 2033, 1267,   66, -67,  -7, },
+	{ -42, -51,  871, 2028, 1290,   76, -69,  -7, },
+	{ -41, -55,  848, 2023, 1313,   86, -70,  -8, },
+	{ -40, -59,  826, 2017, 1336,   97, -72,  -9, },
+	{ -38, -63,  803, 2010, 1359,  108, -73, -10, },
+	{ -37, -67,  781, 2003, 1382,  119, -75, -10, },
+	{ -36, -70,  759, 1996, 1405,  130, -76, -12, },
+	{ -35, -73,  737, 1987, 1427,  142, -78, -11, },
+	{ -34, -76,  715, 1979, 1449,  154, -79, -12, },
+	{ -33, -78,  693, 1969, 1471,  167, -81, -12, },
+	{ -32, -81,  672, 1959, 1493,  180, -82, -13, },
+	{ -31, -83,  650, 1949, 1514,  193, -83, -13, },
+	{ -30, -85,  629, 1938, 1536,  207, -85, -14, },
+	{ -29, -86,  609, 1926, 1557,  221, -86, -16, },
+	{ -28, -88,  588, 1914, 1577,  235, -87, -15, },
+	{ -28, -89,  568, 1902, 1598,  250, -88, -17, },
+	{ -27, -90,  548, 1889, 1618,  265, -89, -18, },
+	{ -26, -91,  528, 1875, 1638,  280, -90, -18, },
+	{ -25, -92,  508, 1861, 1657,  296, -91, -18, },
+	{ -24, -93,  489, 1846, 1676,  312, -92, -18, },
+	{ -24, -93,  470, 1831, 1695,  328, -92, -19, },
+	{ -23, -94,  451, 1816, 1714,  345, -93, -20, },
+	{ -22, -94,  432, 1800, 1732,  361, -93, -20, },
+	{ -22, -94,  414, 1783, 1749,  379, -94, -19, },
+	{ -21, -94,  396, 1767, 1767,  396, -94, -21, },
+	{ -21, -94,  379, 1749, 1783,  414, -94, -20, },
+	{ -20, -93,  361, 1732, 1800,  432, -94, -22, },
+	{ -19, -93,  345, 1714, 1816,  451, -94, -24, },
+	{ -19, -92,  328, 1695, 1831,  470, -93, -24, },
+	{ -18, -92,  312, 1676, 1846,  489, -93, -24, },
+	{ -18, -91,  296, 1657, 1861,  508, -92, -25, },
+	{ -17, -90,  280, 1638, 1875,  528, -91, -27, },
+	{ -17, -89,  265, 1618, 1889,  548, -90, -28, },
+	{ -16, -88,  250, 1598, 1902,  568, -89, -29, },
+	{ -16, -87,  235, 1577, 1914,  588, -88, -27, },
+	{ -15, -86,  221, 1557, 1926,  609, -86, -30, },
+	{ -14, -85,  207, 1536, 1938,  629, -85, -30, },
+	{ -14, -83,  193, 1514, 1949,  650, -83, -30, },
+	{ -13, -82,  180, 1493, 1959,  672, -81, -32, },
+	{ -13, -81,  167, 1471, 1969,  693, -78, -32, },
+	{ -12, -79,  154, 1449, 1979,  715, -76, -34, },
+	{ -12, -78,  142, 1427, 1987,  737, -73, -34, },
+	{ -11, -76,  130, 1405, 1996,  759, -70, -37, },
+	{ -10, -75,  119, 1382, 2003,  781, -67, -37, },
+	{ -10, -73,  108, 1359, 2010,  803, -63, -38, },
+	{  -9, -72,   97, 1336, 2017,  826, -59, -40, },
+	{  -8, -70,   86, 1313, 2023,  848, -55, -41, },
+	{  -8, -69,   76, 1290, 2028,  871, -51, -41, },
+	{  -7, -67,   66, 1267, 2033,  894, -47, -43, },
+	{  -6, -65,   57, 1244, 2037,  917, -42, -46, },
+	{  -5, -64,   48, 1220, 2040,  940, -37, -46, },
+	{  -5, -62,   39, 1197, 2043,  963, -31, -48, },
+	{  -4, -61,   31, 1173, 2046,  986, -26, -49, },
+	{  -3, -59,   22, 1149, 2047, 1009, -20, -49, },
+	{  -2, -58,   15, 1126, 2048, 1032, -13, -52, },
+	{  -1, -56,    7, 1102, 2049, 1055,  -7, -53, }
+};
+
+/* ScalingRatio = 3.0 */
+static const s16 XV_fixedcoeff_taps8_SR3[XV_HSCALER_MAX_H_PHASES][XV_HSCALER_TAPS_8] = {
+	{   0, 275, 1036, 1514, 1036,  275,   0, -40, },
+	{  -1, 266, 1023, 1514, 1048,  283,   1, -38, },
+	{  -2, 257, 1010, 1513, 1060,  292,   2, -36, },
+	{  -3, 249,  997, 1512, 1073,  301,   3, -36, },
+	{  -3, 241,  983, 1510, 1085,  310,   5, -35, },
+	{  -4, 233,  970, 1509, 1097,  319,   6, -34, },
+	{  -5, 225,  957, 1507, 1109,  329,   7, -33, },
+	{  -6, 217,  944, 1505, 1121,  338,   9, -32, },
+	{  -6, 210,  931, 1503, 1133,  348,  10, -33, },
+	{  -7, 202,  917, 1500, 1144,  358,  12, -30, },
+	{  -7, 195,  904, 1497, 1156,  368,  13, -30, },
+	{  -8, 188,  891, 1494, 1167,  378,  15, -29, },
+	{  -9, 181,  877, 1491, 1179,  388,  17, -28, },
+	{  -9, 174,  864, 1487, 1190,  398,  19, -27, },
+	{  -9, 168,  851, 1483, 1201,  409,  21, -28, },
+	{ -10, 161,  837, 1479, 1212,  419,  23, -25, },
+	{ -10, 155,  824, 1475, 1223,  430,  25, -26, },
+	{ -11, 149,  811, 1470, 1233,  441,  27, -24, },
+	{ -11, 142,  798, 1465, 1244,  452,  29, -23, },
+	{ -12, 137,  784, 1460, 1254,  463,  32, -22, },
+	{ -12, 131,  771, 1455, 1264,  474,  34, -21, },
+	{ -12, 125,  758, 1449, 1275,  486,  37, -22, },
+	{ -13, 120,  745, 1444, 1284,  497,  40, -21, },
+	{ -13, 115,  732, 1438, 1294,  509,  42, -21, },
+	{ -13, 109,  719, 1432, 1304,  520,  45, -20, },
+	{ -14, 104,  706, 1425, 1313,  532,  48, -18, },
+	{ -14, 100,  693, 1418, 1322,  544,  52, -19, },
+	{ -14,  95,  680, 1412, 1332,  556,  55, -20, },
+	{ -15,  90,  667, 1404, 1340,  568,  58, -16, },
+	{ -15,  86,  655, 1397, 1349,  580,  62, -18, },
+	{ -16,  82,  642, 1390, 1358,  592,  66, -18, },
+	{ -16,  77,  630, 1382, 1366,  605,  69, -17, },
+	{ -16,  73,  617, 1374, 1374,  617,  73, -16, },
+	{ -17,  69,  605, 1366, 1382,  630,  77, -16, },
+	{ -17,  66,  592, 1358, 1390,  642,  82, -17, },
+	{ -18,  62,  580, 1349, 1397,  655,  86, -15, },
+	{ -18,  58,  568, 1340, 1404,  667,  90, -13, },
+	{ -18,  55,  556, 1332, 1412,  680,  95, -16, },
+	{ -19,  52,  544, 1322, 1418,  693, 100, -14, },
+	{ -19,  48,  532, 1313, 1425,  706, 104, -13, },
+	{ -20,  45,  520, 1304, 1432,  719, 109, -13, },
+	{ -20,  42,  509, 1294, 1438,  732, 115, -14, },
+	{ -21,  40,  497, 1284, 1444,  745, 120, -13, },
+	{ -22,  37,  486, 1275, 1449,  758, 125, -12, },
+	{ -22,  34,  474, 1264, 1455,  771, 131, -11, },
+	{ -23,  32,  463, 1254, 1460,  784, 137, -11, },
+	{ -23,  29,  452, 1244, 1465,  798, 142, -11, },
+	{ -24,  27,  441, 1233, 1470,  811, 149, -11, },
+	{ -25,  25,  430, 1223, 1475,  824, 155, -11, },
+	{ -26,  23,  419, 1212, 1479,  837, 161,  -9, },
+	{ -26,  21,  409, 1201, 1483,  851, 168, -11, },
+	{ -27,  19,  398, 1190, 1487,  864, 174,  -9, },
+	{ -28,  17,  388, 1179, 1491,  877, 181,  -9, },
+	{ -29,  15,  378, 1167, 1494,  891, 188,  -8, },
+	{ -29,  13,  368, 1156, 1497,  904, 195,  -8, },
+	{ -30,  12,  358, 1144, 1500,  917, 202,  -7, },
+	{ -31,  10,  348, 1133, 1503,  931, 210,  -8, },
+	{ -32,   9,  338, 1121, 1505,  944, 217,  -6, },
+	{ -33,   7,  329, 1109, 1507,  957, 225,  -5, },
+	{ -34,   6,  319, 1097, 1509,  970, 233,  -4, },
+	{ -35,   5,  310, 1085, 1510,  983, 241,  -3, },
+	{ -36,   3,  301, 1073, 1512,  997, 249,  -3, },
+	{ -37,   2,  292, 1060, 1513, 1010, 257,  -1, },
+	{ -38,   1,  283, 1048, 1514, 1023, 266,  -1, }
+};
+
+/* ScalingRatio = 4 */
+static const s16 XV_fixedcoeff_taps8_SR4[XV_HSCALER_MAX_H_PHASES][XV_HSCALER_TAPS_8] = {
+	{ 49, 366, 977, 1312,  977, 366,  49,  0, },
+	{ 48, 357, 967, 1312,  986, 374,  51,  1, },
+	{ 46, 349, 958, 1311,  995, 382,  54,  1, },
+	{ 44, 342, 948, 1311, 1004, 390,  56,  1, },
+	{ 42, 334, 939, 1310, 1013, 399,  58,  1, },
+	{ 40, 326, 929, 1309, 1021, 407,  60,  4, },
+	{ 39, 318, 919, 1308, 1030, 415,  63,  4, },
+	{ 37, 311, 910, 1307, 1039, 424,  65,  3, },
+	{ 36, 303, 900, 1305, 1047, 433,  68,  4, },
+	{ 34, 296, 890, 1303, 1055, 442,  70,  6, },
+	{ 33, 289, 880, 1301, 1064, 450,  73,  6, },
+	{ 32, 282, 870, 1299, 1072, 459,  76,  6, },
+	{ 31, 275, 861, 1297, 1080, 468,  79,  5, },
+	{ 29, 268, 851, 1295, 1088, 477,  82,  6, },
+	{ 28, 261, 841, 1292, 1096, 486,  85,  7, },
+	{ 27, 254, 831, 1289, 1104, 496,  88,  7, },
+	{ 26, 248, 821, 1287, 1112, 505,  91,  6, },
+	{ 25, 241, 811, 1284, 1119, 514,  94,  8, },
+	{ 24, 235, 800, 1280, 1127, 523,  98,  9, },
+	{ 23, 228, 790, 1277, 1134, 533, 101, 10, },
+	{ 22, 222, 780, 1273, 1141, 542, 105, 11, },
+	{ 22, 216, 770, 1270, 1148, 552, 109,  9, },
+	{ 21, 210, 760, 1266, 1155, 561, 112, 11, },
+	{ 20, 204, 750, 1262, 1162, 571, 116, 11, },
+	{ 19, 198, 740, 1257, 1169, 581, 120, 12, },
+	{ 19, 193, 730, 1253, 1175, 590, 124, 12, },
+	{ 18, 187, 720, 1248, 1182, 600, 129, 12, },
+	{ 17, 182, 710, 1244, 1188, 610, 133, 12, },
+	{ 17, 176, 700, 1239, 1194, 620, 137, 13, },
+	{ 16, 171, 690, 1234, 1201, 630, 142, 12, },
+	{ 16, 166, 680, 1229, 1206, 640, 146, 13, },
+	{ 15, 161, 670, 1223, 1212, 650, 151, 14, },
+	{ 15, 156, 660, 1218, 1218, 660, 156, 13, },
+	{ 14, 151, 650, 1212, 1223, 670, 161, 15, },
+	{ 14, 146, 640, 1206, 1229, 680, 166, 15, },
+	{ 13, 142, 630, 1201, 1234, 690, 171, 15, },
+	{ 13, 137, 620, 1194, 1239, 700, 176, 17, },
+	{ 12, 133, 610, 1188, 1244, 710, 182, 17, },
+	{ 12, 129, 600, 1182, 1248, 720, 187, 18, },
+	{ 11, 124, 590, 1175, 1253, 730, 193, 20, },
+	{ 11, 120, 581, 1169, 1257, 740, 198, 20, },
+	{ 11, 116, 571, 1162, 1262, 750, 204, 20, },
+	{ 10, 112, 561, 1155, 1266, 760, 210, 22, },
+	{ 10, 109, 552, 1148, 1270, 770, 216, 21, },
+	{ 10, 105, 542, 1141, 1273, 780, 222, 23, },
+	{  9, 101, 533, 1134, 1277, 790, 228, 24, },
+	{  9,  98, 523, 1127, 1280, 800, 235, 24, },
+	{  8,  94, 514, 1119, 1284, 811, 241, 25, },
+	{  8,  91, 505, 1112, 1287, 821, 248, 24, },
+	{  8,  88, 496, 1104, 1289, 831, 254, 26, },
+	{  7,  85, 486, 1096, 1292, 841, 261, 28, },
+	{  7,  82, 477, 1088, 1295, 851, 268, 28, },
+	{  6,  79, 468, 1080, 1297, 861, 275, 30, },
+	{  6,  76, 459, 1072, 1299, 870, 282, 32, },
+	{  5,  73, 450, 1064, 1301, 880, 289, 34, },
+	{  5,  70, 442, 1055, 1303, 890, 296, 35, },
+	{  4,  68, 433, 1047, 1305, 900, 303, 36, },
+	{  4,  65, 424, 1039, 1307, 910, 311, 36, },
+	{  3,  63, 415, 1030, 1308, 919, 318, 40, },
+	{  3,  60, 407, 1021, 1309, 929, 326, 41, },
+	{  2,  58, 399, 1013, 1310, 939, 334, 41, },
+	{  2,  56, 390, 1004, 1311, 948, 342, 43, },
+	{  1,  54, 382,  995, 1311, 958, 349, 46, },
+	{  1,  51, 374,  986, 1312, 967, 357, 48, }
+};
+
+/* ScalingRatio = 3.0 */
+static const s16 XV_fixedcoeff_taps10_SR3[XV_HSCALER_MAX_H_PHASES][XV_HSCALER_TAPS_10] = {
+	{ -31,   0, 359, 1033, 1399, 1033,  359,   0, -31, -25, },
+	{ -31,  -2, 350, 1022, 1398, 1043,  368,   3, -31, -24, },
+	{ -30,  -4, 341, 1012, 1398, 1053,  378,   5, -32, -25, },
+	{ -30,  -6, 333, 1002, 1398, 1062,  387,   8, -32, -26, },
+	{ -30,  -8, 324,  992, 1397, 1072,  396,  10, -32, -25, },
+	{ -30, -10, 315,  981, 1396, 1082,  406,  13, -33, -24, },
+	{ -29, -12, 307,  971, 1395, 1091,  415,  16, -33, -25, },
+	{ -29, -13, 298,  960, 1393, 1101,  425,  18, -33, -24, },
+	{ -29, -15, 290,  949, 1392, 1110,  434,  21, -34, -22, },
+	{ -28, -17, 282,  939, 1390, 1120,  444,  25, -34, -25, },
+	{ -28, -18, 274,  928, 1388, 1129,  454,  28, -34, -25, },
+	{ -28, -20, 266,  917, 1386, 1138,  464,  31, -34, -24, },
+	{ -27, -21, 258,  906, 1384, 1147,  474,  34, -35, -24, },
+	{ -27, -22, 250,  895, 1381, 1156,  484,  38, -35, -24, },
+	{ -27, -23, 242,  885, 1379, 1164,  494,  41, -35, -24, },
+	{ -27, -25, 235,  874, 1376, 1173,  504,  45, -35, -24, },
+	{ -26, -26, 227,  863, 1373, 1181,  515,  49, -36, -24, },
+	{ -26, -27, 220,  852, 1369, 1190,  525,  53, -36, -24, },
+	{ -26, -28, 213,  841, 1366, 1198,  535,  56, -36, -23, },
+	{ -26, -29, 206,  830, 1362, 1206,  546,  61, -36, -24, },
+	{ -25, -29, 199,  819, 1358, 1214,  556,  65, -36, -25, },
+	{ -25, -30, 192,  808, 1354, 1222,  567,  69, -36, -25, },
+	{ -25, -31, 185,  797, 1350, 1229,  577,  73, -36, -23, },
+	{ -25, -32, 178,  785, 1346, 1237,  588,  78, -36, -23, },
+	{ -25, -32, 172,  774, 1341, 1244,  599,  83, -36, -24, },
+	{ -25, -33, 165,  763, 1336, 1252,  610,  87, -36, -23, },
+	{ -24, -33, 159,  752, 1331, 1259,  620,  92, -36, -24, },
+	{ -24, -34, 153,  741, 1326, 1266,  631,  97, -36, -24, },
+	{ -24, -34, 147,  730, 1321, 1272,  642, 102, -36, -24, },
+	{ -24, -35, 141,  719, 1315, 1279,  653, 107, -36, -23, },
+	{ -24, -35, 135,  708, 1310, 1285,  664, 113, -36, -24, },
+	{ -24, -35, 129,  697, 1304, 1292,  675, 118, -36, -24, },
+	{ -24, -36, 124,  686, 1298, 1298,  686, 124, -36, -24, },
+	{ -24, -36, 118,  675, 1292, 1304,  697, 129, -35, -24, },
+	{ -24, -36, 113,  664, 1285, 1310,  708, 135, -35, -24, },
+	{ -24, -36, 107,  653, 1279, 1315,  719, 141, -35, -23, },
+	{ -24, -36, 102,  642, 1272, 1321,  730, 147, -34, -24, },
+	{ -23, -36,  97,  631, 1266, 1326,  741, 153, -34, -25, },
+	{ -23, -36,  92,  620, 1259, 1331,  752, 159, -33, -25, },
+	{ -23, -36,  87,  610, 1252, 1336,  763, 165, -33, -25, },
+	{ -23, -36,  83,  599, 1244, 1341,  774, 172, -32, -26, },
+	{ -23, -36,  78,  588, 1237, 1346,  785, 178, -32, -25, },
+	{ -23, -36,  73,  577, 1229, 1350,  797, 185, -31, -25, },
+	{ -23, -36,  69,  567, 1222, 1354,  808, 192, -30, -27, },
+	{ -23, -36,  65,  556, 1214, 1358,  819, 199, -29, -27, },
+	{ -24, -36,  61,  546, 1206, 1362,  830, 206, -29, -26, },
+	{ -24, -36,  56,  535, 1198, 1366,  841, 213, -28, -25, },
+	{ -24, -36,  53,  525, 1190, 1369,  852, 220, -27, -26, },
+	{ -24, -36,  49,  515, 1181, 1373,  863, 227, -26, -26, },
+	{ -24, -35,  45,  504, 1173, 1376,  874, 235, -25, -27, },
+	{ -24, -35,  41,  494, 1164, 1379,  885, 242, -23, -27, },
+	{ -24, -35,  38,  484, 1156, 1381,  895, 250, -22, -27, },
+	{ -24, -35,  34,  474, 1147, 1384,  906, 258, -21, -27, },
+	{ -24, -34,  31,  464, 1138, 1386,  917, 266, -20, -28, },
+	{ -24, -34,  28,  454, 1129, 1388,  928, 274, -18, -29, },
+	{ -24, -34,  25,  444, 1120, 1390,  939, 282, -17, -29, },
+	{ -24, -34,  21,  434, 1110, 1392,  949, 290, -15, -27, },
+	{ -24, -33,  18,  425, 1101, 1393,  960, 298, -13, -29, },
+	{ -24, -33,  16,  415, 1091, 1395,  971, 307, -12, -30, },
+	{ -25, -33,  13,  406, 1082, 1396,  981, 315, -10, -29, },
+	{ -25, -32,  10,  396, 1072, 1397,  992, 324,  -8, -30, },
+	{ -25, -32,   8,  387, 1062, 1398, 1002, 333,  -6, -31, },
+	{ -25, -32,   5,  378, 1053, 1398, 1012, 341,  -4, -30, },
+	{ -25, -31,   3,  368, 1043, 1398, 1022, 350,  -2, -30, }
+};
+
+/* ScalingRatio = 4 */
+static const s16 XV_fixedcoeff_taps10_SR4[XV_HSCALER_MAX_H_PHASES][XV_HSCALER_TAPS_10] = {
+	{   0, 107, 454, 924, 1150,  924, 454, 107,   0, -24, },
+	{   0, 104, 446, 917, 1149,  930, 461, 110,   0, -21, },
+	{  -1, 100, 439, 910, 1149,  936, 468, 114,   1, -20, },
+	{  -1,  97, 432, 904, 1149,  942, 475, 117,   2, -21, },
+	{  -2,  94, 425, 897, 1148,  948, 482, 121,   2, -19, },
+	{  -2,  91, 418, 890, 1147,  954, 490, 125,   3, -20, },
+	{  -3,  88, 411, 883, 1147,  960, 497, 128,   3, -18, },
+	{  -3,  85, 404, 876, 1146,  966, 504, 132,   4, -18, },
+	{  -3,  82, 397, 869, 1145,  972, 512, 136,   5, -19, },
+	{  -4,  79, 390, 862, 1144,  978, 519, 140,   5, -17, },
+	{  -4,  76, 384, 855, 1142,  983, 526, 144,   6, -16, },
+	{  -4,  74, 377, 848, 1141,  989, 534, 148,   7, -18, },
+	{  -5,  71, 370, 841, 1139,  995, 541, 152,   7, -15, },
+	{  -5,  68, 364, 834, 1138, 1000, 549, 156,   8, -16, },
+	{  -5,  66, 357, 827, 1136, 1005, 556, 160,   9, -15, },
+	{  -6,  63, 350, 820, 1134, 1011, 564, 165,  10, -15, },
+	{  -6,  61, 344, 812, 1132, 1016, 571, 169,  11, -14, },
+	{  -6,  59, 338, 805, 1130, 1021, 579, 174,  12, -16, },
+	{  -6,  56, 331, 798, 1128, 1026, 586, 178,  13, -14, },
+	{  -7,  54, 325, 790, 1126, 1031, 594, 183,  14, -14, },
+	{  -7,  52, 319, 783, 1124, 1036, 601, 187,  15, -14, },
+	{  -7,  50, 312, 776, 1121, 1041, 609, 192,  16, -14, },
+	{  -7,  48, 306, 768, 1119, 1045, 617, 197,  17, -14, },
+	{  -8,  46, 300, 761, 1116, 1050, 624, 202,  18, -13, },
+	{  -8,  44, 294, 753, 1113, 1054, 632, 207,  19, -12, },
+	{  -8,  42, 288, 746, 1110, 1059, 639, 212,  20, -12, },
+	{  -8,  40, 282, 738, 1107, 1063, 647, 217,  22, -12, },
+	{  -9,  38, 277, 731, 1104, 1067, 655, 222,  23, -12, },
+	{  -9,  36, 271, 723, 1101, 1071, 662, 227,  24, -10, },
+	{  -9,  35, 265, 715, 1097, 1075, 670, 232,  26, -10, },
+	{  -9,  33, 259, 708, 1094, 1079, 677, 238,  27, -10, },
+	{ -10,  32, 254, 700, 1091, 1083, 685, 243,  28, -10, },
+	{ -10,  30, 248, 693, 1087, 1087, 693, 248,  30, -10, },
+	{ -10,  28, 243, 685, 1083, 1091, 700, 254,  32, -10, },
+	{ -10,  27, 238, 677, 1079, 1094, 708, 259,  33,  -9, },
+	{ -11,  26, 232, 670, 1075, 1097, 715, 265,  35,  -8, },
+	{ -11,  24, 227, 662, 1071, 1101, 723, 271,  36,  -8, },
+	{ -11,  23, 222, 655, 1067, 1104, 731, 277,  38, -10, },
+	{ -12,  22, 217, 647, 1063, 1107, 738, 282,  40,  -8, },
+	{ -12,  20, 212, 639, 1059, 1110, 746, 288,  42,  -8, },
+	{ -12,  19, 207, 632, 1054, 1113, 753, 294,  44,  -8, },
+	{ -12,  18, 202, 624, 1050, 1116, 761, 300,  46,  -9, },
+	{ -13,  17, 197, 617, 1045, 1119, 768, 306,  48,  -8, },
+	{ -13,  16, 192, 609, 1041, 1121, 776, 312,  50,  -8, },
+	{ -13,  15, 187, 601, 1036, 1124, 783, 319,  52,  -8, },
+	{ -14,  14, 183, 594, 1031, 1126, 790, 325,  54,  -7, },
+	{ -14,  13, 178, 586, 1026, 1128, 798, 331,  56,  -6, },
+	{ -14,  12, 174, 579, 1021, 1130, 805, 338,  59,  -8, },
+	{ -15,  11, 169, 571, 1016, 1132, 812, 344,  61,  -5, },
+	{ -15,  10, 165, 564, 1011, 1134, 820, 350,  63,  -6, },
+	{ -16,   9, 160, 556, 1005, 1136, 827, 357,  66,  -4, },
+	{ -16,   8, 156, 549, 1000, 1138, 834, 364,  68,  -5, },
+	{ -16,   7, 152, 541,  995, 1139, 841, 370,  71,  -4, },
+	{ -17,   7, 148, 534,  989, 1141, 848, 377,  74,  -5, },
+	{ -17,   6, 144, 526,  983, 1142, 855, 384,  76,  -3, },
+	{ -18,   5, 140, 519,  978, 1144, 862, 390,  79,  -3, },
+	{ -18,   5, 136, 512,  972, 1145, 869, 397,  82,  -4, },
+	{ -19,   4, 132, 504,  966, 1146, 876, 404,  85,  -2, },
+	{ -19,   3, 128, 497,  960, 1147, 883, 411,  88,  -2, },
+	{ -20,   3, 125, 490,  954, 1147, 890, 418,  91,  -2, },
+	{ -20,   2, 121, 482,  948, 1148, 897, 425,  94,  -1, },
+	{ -21,   2, 117, 475,  942, 1149, 904, 432,  97,  -1, },
+	{ -21,   1, 114, 468,  936, 1149, 910, 439, 100,   0, },
+	{ -22,   0, 110, 461,  930, 1149, 917, 446, 104,   1, }
+};
+
+/* ScalingRatio = 4 */
+static const s16 XV_fixedcoeff_taps12_SR4[XV_HSCALER_MAX_H_PHASES][XV_HSCALER_TAPS_12] = {
+	{ -19,   0, 152, 498, 893, 1070,  893, 498, 152,   0, -19, -22, },
+	{ -19,  -1, 147, 487, 879, 1059,  889, 499, 155,   1, -19,  19, },
+	{ -19,  -2, 143, 480, 874, 1059,  894, 506, 159,   2, -19,  19, },
+	{ -19,  -3, 139, 474, 869, 1059,  899, 512, 163,   3, -19,  19, },
+	{ -19,  -4, 136, 468, 863, 1059,  904, 519, 167,   4, -19,  18, },
+	{ -19,  -5, 132, 461, 858, 1058,  909, 525, 171,   5, -19,  20, },
+	{ -19,  -5, 128, 455, 853, 1058,  913, 531, 175,   7, -19,  19, },
+	{ -18,  -6, 125, 449, 847, 1057,  918, 538, 180,   8, -19,  17, },
+	{ -18,  -7, 121, 443, 842, 1056,  923, 544, 184,   9, -19,  18, },
+	{ -18,  -8, 118, 436, 836, 1056,  927, 551, 188,  10, -19,  19, },
+	{ -18,  -8, 114, 430, 831, 1055,  932, 557, 193,  12, -19,  17, },
+	{ -18,  -9, 111, 424, 825, 1054,  936, 564, 197,  13, -19,  18, },
+	{ -18, -10, 107, 418, 819, 1053,  941, 570, 202,  14, -19,  19, },
+	{ -18, -10, 104, 412, 814, 1052,  945, 577, 206,  16, -19,  17, },
+	{ -18, -11, 101, 406, 808, 1050,  949, 583, 211,  17, -19,  19, },
+	{ -18, -11,  98, 400, 802, 1049,  954, 590, 216,  19, -19,  16, },
+	{ -18, -12,  95, 394, 796, 1048,  958, 596, 220,  20, -19,  18, },
+	{ -18, -12,  92, 388, 791, 1046,  962, 603, 225,  22, -19,  16, },
+	{ -18, -13,  89, 382, 785, 1045,  966, 609, 230,  24, -19,  16, },
+	{ -18, -13,  86, 376, 779, 1043,  970, 616, 235,  25, -19,  16, },
+	{ -18, -14,  83, 370, 773, 1041,  973, 622, 240,  27, -19,  18, },
+	{ -18, -14,  80, 364, 767, 1039,  977, 629, 244,  29, -19,  18, },
+	{ -18, -15,  77, 358, 761, 1037,  981, 635, 249,  31, -19,  19, },
+	{ -18, -15,  74, 352, 755, 1035,  984, 642, 255,  33, -19,  18, },
+	{ -18, -15,  71, 347, 749, 1033,  988, 648, 260,  35, -19,  17, },
+	{ -18, -16,  69, 341, 743, 1031,  991, 654, 265,  36, -19,  19, },
+	{ -18, -16,  66, 335, 736, 1029,  995, 661, 270,  38, -19,  19, },
+	{ -18, -16,  64, 330, 730, 1026,  998, 667, 275,  41, -18,  17, },
+	{ -18, -17,  61, 324, 724, 1024, 1001, 674, 280,  43, -18,  18, },
+	{ -18, -17,  59, 318, 718, 1021, 1004, 680, 286,  45, -18,  18, },
+	{ -18, -17,  56, 313, 712, 1019, 1007, 686, 291,  47, -18,  18, },
+	{ -18, -17,  54, 307, 705, 1016, 1010, 693, 296,  49, -18,  19, },
+	{ -18, -18,  51, 302, 699, 1013, 1013, 699, 302,  51, -18,  20, },
+	{ -18, -18,  49, 296, 693, 1010, 1016, 705, 307,  54, -17,  19, },
+	{ -18, -18,  47, 291, 686, 1007, 1019, 712, 313,  56, -17,  18, },
+	{ -18, -18,  45, 286, 680, 1004, 1021, 718, 318,  59, -17,  18, },
+	{ -18, -18,  43, 280, 674, 1001, 1024, 724, 324,  61, -17,  18, },
+	{ -18, -18,  41, 275, 667,  998, 1026, 730, 330,  64, -16,  17, },
+	{ -18, -19,  38, 270, 661,  995, 1029, 736, 335,  66, -16,  19, },
+	{ -19, -19,  36, 265, 654,  991, 1031, 743, 341,  69, -16,  20, },
+	{ -19, -19,  35, 260, 648,  988, 1033, 749, 347,  71, -15,  18, },
+	{ -19, -19,  33, 255, 642,  984, 1035, 755, 352,  74, -15,  19, },
+	{ -19, -19,  31, 249, 635,  981, 1037, 761, 358,  77, -15,  20, },
+	{ -19, -19,  29, 244, 629,  977, 1039, 767, 364,  80, -14,  19, },
+	{ -19, -19,  27, 240, 622,  973, 1041, 773, 370,  83, -14,  19, },
+	{ -19, -19,  25, 235, 616,  970, 1043, 779, 376,  86, -13,  17, },
+	{ -19, -19,  24, 230, 609,  966, 1045, 785, 382,  89, -13,  17, },
+	{ -19, -19,  22, 225, 603,  962, 1046, 791, 388,  92, -12,  17, },
+	{ -19, -19,  20, 220, 596,  958, 1048, 796, 394,  95, -12,  19, },
+	{ -20, -19,  19, 216, 590,  954, 1049, 802, 400,  98, -11,  18, },
+	{ -20, -19,  17, 211, 583,  949, 1050, 808, 406, 101, -11,  21, },
+	{ -20, -19,  16, 206, 577,  945, 1052, 814, 412, 104, -10,  19, },
+	{ -20, -19,  14, 202, 570,  941, 1053, 819, 418, 107, -10,  21, },
+	{ -20, -19,  13, 197, 564,  936, 1054, 825, 424, 111,  -9,  20, },
+	{ -20, -19,  12, 193, 557,  932, 1055, 831, 430, 114,  -8,  19, },
+	{ -21, -19,  10, 188, 551,  927, 1056, 836, 436, 118,  -8,  22, },
+	{ -21, -19,   9, 184, 544,  923, 1056, 842, 443, 121,  -7,  21, },
+	{ -21, -19,   8, 180, 538,  918, 1057, 847, 449, 125,  -6,  20, },
+	{ -21, -19,   7, 175, 531,  913, 1058, 853, 455, 128,  -5,  21, },
+	{ -21, -19,   5, 171, 525,  909, 1058, 858, 461, 132,  -5,  22, },
+	{ -21, -19,   4, 167, 519,  904, 1059, 863, 468, 136,  -4,  20, },
+	{ -22, -19,   3, 163, 512,  899, 1059, 869, 474, 139,  -3,  22, },
+	{ -22, -19,   2, 159, 506,  894, 1059, 874, 480, 143,  -2,  22, },
+	{ -22, -19,   1, 155, 499,  889, 1059, 879, 487, 147,  -1,  22, }
+};
+
+#define XV_HSCALER_CTRL_WIDTH_HWREG_HFLTCOEFF			(16)
+#define XV_HSCALER_CTRL_DEPTH_HWREG_HFLTCOEFF			(384)
+#define XV_HSCALER_CTRL_ADDR_HWREG_PHASESH_V_BASE		(0x2000)
+#define XV_HSCALER_CTRL_ADDR_HWREG_PHASESH_V_HIGH		(0x3fff)
+#define XV_HSCALER_CTRL_WIDTH_HWREG_PHASESH_V			(18)
+#define XV_HSCALER_CTRL_DEPTH_HWREG_PHASESH_V			(1920)
+#define XV_HSCALER_CTRL_ADDR_HWREG_PHASEH_FIX			(0x4000)
+
+/* H-scaler masks */
+#define XV_HSCALER_PHASESH_V_OUTPUT_WR_EN			BIT(8)
+
+/* V-scaler registers */
+#define XV_VSCALER_CTRL_ADDR_AP_CTRL			(0x000)
+#define XV_VSCALER_CTRL_ADDR_GIE			(0x004)
+#define XV_VSCALER_CTRL_ADDR_IER			(0x008)
+#define XV_VSCALER_CTRL_ADDR_ISR			(0x00c)
+#define XV_VSCALER_CTRL_ADDR_HWREG_HEIGHTIN_DATA	(0x010)
+#define XV_VSCALER_CTRL_ADDR_HWREG_WIDTH_DATA		(0x018)
+#define XV_VSCALER_CTRL_ADDR_HWREG_HEIGHTOUT_DATA	(0x020)
+#define XV_VSCALER_CTRL_ADDR_HWREG_LINERATE_DATA	(0x028)
+#define XV_VSCALER_CTRL_ADDR_HWREG_COLORMODE_DATA	(0x030)
+#define XV_VSCALER_CTRL_ADDR_HWREG_VFLTCOEFF_BASE	(0x800)
+#define XV_VSCALER_CTRL_ADDR_HWREG_VFLTCOEFF_HIGH	(0xbff)
+
+#define XV_VSCALER_CTRL_WIDTH_HWREG_VFLTCOEFF		(16)
+#define XV_VSCALER_CTRL_DEPTH_HWREG_VFLTCOEFF		(384)
+
+/* These bits are for xscaler feature flags */
+#define XSCALER_CLK_PROP	BIT(0)
+#define XSCALER_HPHASE_FIX	BIT(1)
+
+/**
+ * struct xscaler_feature - dt or IP property structure
+ * @flags: Bitmask of properties enabled in IP or dt
+ */
+struct xscaler_feature {
+	u32 flags;
+};
+
+/**
+ * struct xscaler_device - Xilinx Scaler device structure
+ * @xvip: Xilinx Video IP device
+ * @pads: Scaler sub-device media pads
+ * @formats: V4L2 media bus formats at the sink and source pads
+ * @default_formats: default V4L2 media bus formats
+ * @vip_formats: Xilinx Video IP format retrieved from the DT
+ * @num_hori_taps: number of horizontal taps
+ * @num_vert_taps: number of vertical taps
+ * @max_num_phases: maximum number of phases
+ * @pix_per_clk: Pixels per Clock cycle the IP operates upon
+ * @max_pixels: The maximum number of pixels that the H-scaler examines
+ * @max_lines: The maximum number of lines that the V-scaler examines
+ * @H_phases: The phases needed to program the H-scaler for different taps
+ * @hscaler_coeff: The complete array of H-scaler coefficients
+ * @vscaler_coeff: The complete array of V-scaler coefficients
+ * @is_polyphase: Track if scaling algorithm is polyphase or not
+ * @rst_gpio: GPIO reset line to bring VPSS Scaler out of reset
+ * @cfg: Pointer to scaler config structure
+ * @aclk_axis: AXI4-Stream video interface clock
+ * @aclk_ctrl: AXI4-Lite control interface clock
+ */
+struct xscaler_device {
+	struct xvip_device xvip;
+
+	struct media_pad pads[2];
+	struct v4l2_mbus_framefmt formats[2];
+	struct v4l2_mbus_framefmt default_formats[2];
+	const struct xvip_video_format *vip_formats[2];
+
+	u32 num_hori_taps;
+	u32 num_vert_taps;
+	u32 max_num_phases;
+	u32 pix_per_clk;
+	u32 max_pixels;
+	u32 max_lines;
+	u64 H_phases[XV_HSCALER_MAX_LINE_WIDTH];
+	short hscaler_coeff[XV_HSCALER_MAX_H_PHASES][XV_HSCALER_MAX_H_TAPS];
+	short vscaler_coeff[XV_VSCALER_MAX_V_PHASES][XV_VSCALER_MAX_V_TAPS];
+	bool is_polyphase;
+
+	struct gpio_desc *rst_gpio;
+	const struct xscaler_feature *cfg;
+	struct clk *aclk_axis;
+	struct clk *aclk_ctrl;
+};
+
+static const struct xscaler_feature xlnx_scaler_v2_2 = {
+	.flags = XSCALER_CLK_PROP | XSCALER_HPHASE_FIX,
+};
+
+static const struct xscaler_feature xlnx_scaler_v1_0 = {
+	.flags = XSCALER_CLK_PROP,
+};
+
+static const struct xscaler_feature xlnx_scaler = {
+	.flags = 0,
+};
+
+static const struct of_device_id xscaler_of_id_table[] = {
+	{ .compatible = "xlnx,v-vpss-scaler",
+		.data = &xlnx_scaler},
+	{ .compatible = "xlnx,v-vpss-scaler-1.0",
+		.data = &xlnx_scaler_v1_0},
+	{ .compatible = "xlnx,v-vpss-scaler-2.2",
+		.data = &xlnx_scaler_v2_2},
+	{ /* end of table */ }
+};
+MODULE_DEVICE_TABLE(of, xscaler_of_id_table);
+
+static inline struct xscaler_device *to_scaler(struct v4l2_subdev *subdev)
+{
+	return container_of(subdev, struct xscaler_device, xvip.subdev);
+}
+
+static void
+xv_hscaler_calculate_phases(struct xscaler_device *xscaler,
+			    u32 width_in, u32 width_out, u32 pixel_rate)
+{
+	unsigned int loop_width;
+	unsigned int x, s;
+	int offset = 0;
+	int xwrite_pos = 0;
+	bool output_write_en;
+	bool get_new_pix;
+	u64 phaseH;
+	u64 array_idx = 0;
+	int nr_rds = 0;
+	int nr_rds_clck;
+	unsigned int nphases = xscaler->max_num_phases;
+	unsigned int nppc = xscaler->pix_per_clk;
+	unsigned int shift = XHSC_STEP_PRECISION_SHIFT - ilog2(nphases);
+
+	loop_width = max_t(u32, width_in, width_out);
+	loop_width = ALIGN(loop_width + nppc - 1, nppc);
+
+	for (x = 0; x < loop_width; x++) {
+		nr_rds_clck = 0;
+		for (s = 0; s < nppc; s++) {
+			phaseH = (offset >> shift) & (nphases - 1);
+			get_new_pix = false;
+			output_write_en = false;
+			if ((offset >> XHSC_STEP_PRECISION_SHIFT) != 0) {
+				/* read a new input sample */
+				get_new_pix = true;
+				offset -= (1 << XHSC_STEP_PRECISION_SHIFT);
+				array_idx++;
+			}
+
+			if (((offset >> XHSC_STEP_PRECISION_SHIFT) == 0) &&
+			    (xwrite_pos < width_out)) {
+				/* produce a new output sample */
+				offset += pixel_rate;
+				output_write_en = true;
+				xwrite_pos++;
+			}
+
+			if (nppc == XSCALER_PPC_4) {
+				xscaler->H_phases[x] |=
+					((u64)phaseH <<
+					 (s * XHSC_HPHASE_MUL_4PPC));
+				xscaler->H_phases[x] |=
+					((u64)array_idx <<
+					 (XHSC_HPHASE_SHIFT_BY_6 +
+					  (s * XHSC_HPHASE_MUL_4PPC)));
+				if (output_write_en)
+					xscaler->H_phases[x] |=
+						((u64)1 <<
+						 (XHSC_HPHASE_MULTIPLIER + s *
+						  XHSC_HPHASE_MUL_4PPC));
+			} else {
+				xscaler->H_phases[x] |=
+					(phaseH <<
+					 (s * XHSC_HPHASE_MULTIPLIER));
+				xscaler->H_phases[x] |=
+					(array_idx <<
+					 (XHSC_HPHASE_SHIFT_BY_6 +
+					  (s * XHSC_HPHASE_MULTIPLIER)));
+
+				if (output_write_en)
+					xscaler->H_phases[x] |=
+						(XV_HSCALER_PHASESH_V_OUTPUT_WR_EN <<
+						 (s * XHSC_HPHASE_MULTIPLIER));
+			}
+
+			if (get_new_pix)
+				nr_rds_clck++;
+		}
+		if (array_idx >= nppc)
+			array_idx &= (nppc - 1);
+
+		nr_rds += nr_rds_clck;
+		if (nr_rds >= nppc)
+			nr_rds -= nppc;
+	}
+}
+
+static void
+xv_hscaler_load_ext_coeff(struct xscaler_device *xscaler,
+			  const short *coeff, u32 ntaps)
+{
+	unsigned int i, j, pad, offset;
+	u32 nphases = xscaler->max_num_phases;
+
+	/* Determine if coefficient needs padding (effective vs. max taps) */
+	pad = XV_HSCALER_MAX_H_TAPS - ntaps;
+	offset = pad >> 1;
+	dev_dbg(xscaler->xvip.dev,
+		"%s : Pad = %d Offset = %d Nphases = %d ntaps = %d",
+			__func__, pad, offset, nphases, ntaps);
+
+	/* Load coefficients into scaler coefficient table */
+	for (i = 0; i < nphases; i++) {
+		for (j = 0; j < ntaps; ++j)
+			xscaler->hscaler_coeff[i][j + offset] =
+						coeff[i * ntaps + j];
+	}
+
+	if (pad) { /* effective taps < max_taps */
+		for (i = 0; i < nphases; i++) {
+			/* pad left */
+			for (j = 0; j < offset; j++)
+				xscaler->hscaler_coeff[i][j] = 0;
+			/* pad right */
+			j = ntaps + offset;
+			for (; j < XV_HSCALER_MAX_H_TAPS; j++)
+				xscaler->hscaler_coeff[i][j] = 0;
+		}
+	}
+}
+
+static const short *xv_select_coeff(struct xscaler_device *xscaler,
+				    u32 in, u32 out, u32 *ntaps)
+{
+	const short *coeff = NULL;
+
+	/*
+	 * Scale Down Mode will use dynamic filter selection logic
+	 * Scale Up Mode (including 1:1) will always use 6 tap filter
+	 */
+	if (out < in) {
+		u16 scale_ratio = (in * 10) / out;
+
+		/* Since XV_HSCALER_TAPS_* is same as XV_VSCALER_TAPS_* */
+		switch (*ntaps) {
+		case XV_HSCALER_TAPS_6:
+			*ntaps = XV_HSCALER_TAPS_6;
+			if (scale_ratio > 35)
+				coeff = &XV_fixedcoeff_taps6_SR4[0][0];
+			else if (scale_ratio > 25)
+				coeff = &XV_fixedcoeff_taps6_SR3[0][0];
+			else if (scale_ratio > 15)
+				coeff = &XV_fixedcoeff_taps6_SR2[0][0];
+			else
+				coeff = &XV_fixedcoeff_taps6_SR1p2[0][0];
+			break;
+		case XV_HSCALER_TAPS_8:
+			if (scale_ratio > 35) {
+				coeff = &XV_fixedcoeff_taps8_SR4[0][0];
+				*ntaps = XV_HSCALER_TAPS_8;
+			} else if (scale_ratio > 25) {
+				coeff = &XV_fixedcoeff_taps8_SR3[0][0];
+				*ntaps = XV_HSCALER_TAPS_8;
+			} else if (scale_ratio > 15) {
+				coeff = &XV_fixedcoeff_taps8_SR2[0][0];
+				*ntaps = XV_HSCALER_TAPS_8;
+			} else {
+				coeff = &XV_fixedcoeff_taps6_SR1p2[0][0];
+				*ntaps = XV_HSCALER_TAPS_6;
+			}
+			break;
+		case XV_HSCALER_TAPS_10:
+			if (scale_ratio > 35) {
+				coeff = &XV_fixedcoeff_taps10_SR4[0][0];
+				*ntaps = XV_HSCALER_TAPS_10;
+			} else if (scale_ratio > 25) {
+				coeff = &XV_fixedcoeff_taps10_SR3[0][0];
+				*ntaps = XV_HSCALER_TAPS_10;
+			} else if (scale_ratio > 15) {
+				coeff = &XV_fixedcoeff_taps8_SR2[0][0];
+				*ntaps = XV_HSCALER_TAPS_8;
+			} else {
+				coeff = &XV_fixedcoeff_taps6_SR1p2[0][0];
+				*ntaps = XV_HSCALER_TAPS_6;
+			}
+			break;
+		case XV_HSCALER_TAPS_12:
+			if (scale_ratio > 35) {
+				coeff = &XV_fixedcoeff_taps12_SR4[0][0];
+				*ntaps = XV_HSCALER_TAPS_12;
+			} else if (scale_ratio > 25) {
+				coeff = &XV_fixedcoeff_taps10_SR3[0][0];
+				*ntaps = XV_HSCALER_TAPS_10;
+			} else if (scale_ratio > 15) {
+				coeff = &XV_fixedcoeff_taps8_SR2[0][0];
+				*ntaps = XV_HSCALER_TAPS_8;
+			} else {
+				coeff = &XV_fixedcoeff_taps6_SR1p2[0][0];
+				*ntaps = XV_HSCALER_TAPS_6;
+			}
+			break;
+		default:
+			dev_err(xscaler->xvip.dev,
+				"Unsupported number of taps = %d",
+				*ntaps);
+		}
+	} else {
+		dev_dbg(xscaler->xvip.dev, "scaler : scale up 6 tap");
+		coeff = &XV_lanczos2_taps6[0][0];
+		*ntaps = XV_HSCALER_TAPS_6;
+	}
+
+	return coeff;
+}
+
+/**
+ * xv_hscaler_coeff_select - Selection of H-Scaler coefficients of operation
+ * @xscaler: VPSS Scaler device information
+ * @width_in: Width of input video
+ * @width_out: Width of desired output video
+ *
+ * There are instances when a N-tap filter might operate in an M-tap
+ * configuration where N > M.
+ *
+ * For example :
+ * Depending on the ratio of scaling (while downscaling), a 12-tap
+ * filter may operate with 10 tap coefficients and zero-pads the remaining
+ * coefficients.
+ *
+ * While upscaling the driver will program 6-tap filter coefficients
+ * in any N-tap configurations (for N >= 6).
+ *
+ * This selection is adopted by the as it gives optimal
+ * video output determined by repeated testing of the IP
+ *
+ * Return: Will return 0 if successful. Returns -EINVAL on an unsupported
+ * H-scaler number of taps.
+ */
+static int
+xv_hscaler_select_coeff(struct xscaler_device *xscaler,
+			u32 width_in, u32 width_out)
+{
+	const short *coeff;
+	u32 ntaps = xscaler->num_hori_taps;
+
+	coeff = xv_select_coeff(xscaler, width_in, width_out, &ntaps);
+	if (!coeff)
+		return -EINVAL;
+
+	xv_hscaler_load_ext_coeff(xscaler, coeff, ntaps);
+	return 0;
+}
+
+static void xv_hscaler_set_coeff(struct xscaler_device *xscaler)
+{
+	int val, i, j, offset, rd_indx;
+	u32 ntaps = xscaler->num_hori_taps;
+	u32 nphases = xscaler->max_num_phases;
+	u32 base_addr;
+
+	offset = (XV_HSCALER_MAX_H_TAPS - ntaps) / 2;
+	base_addr = V_HSCALER_OFF + XV_HSCALER_CTRL_ADDR_HWREG_HFLTCOEFF_BASE;
+	for (i = 0; i < nphases; i++) {
+		for (j = 0; j < ntaps / 2; j++) {
+			rd_indx = j * 2 + offset;
+			val = (xscaler->hscaler_coeff[i][rd_indx + 1] <<
+			       XSCALER_BITSHIFT_16) |
+			       (xscaler->hscaler_coeff[i][rd_indx] &
+			       XHSC_MASK_LOW_16BITS);
+			 xvip_write(&xscaler->xvip, base_addr +
+				    ((i * ntaps / 2 + j) * 4), val);
+		}
+	}
+}
+
+static void
+xv_vscaler_load_ext_coeff(struct xscaler_device *xscaler,
+			  const short *coeff, u32 ntaps)
+{
+	int i, j, pad, offset;
+	u32 nphases = xscaler->max_num_phases;
+
+	/* Determine if coefficient needs padding (effective vs. max taps) */
+	pad = XV_VSCALER_MAX_V_TAPS - ntaps;
+	offset = pad ? (pad >> 1) : 0;
+
+	dev_dbg(xscaler->xvip.dev,
+		"%s : Pad = %d Offset = %d Nphases = %d ntaps = %d",
+			__func__, pad, offset, nphases, ntaps);
+
+	/* Load User defined coefficients into scaler coefficient table */
+	for (i = 0; i < nphases; i++) {
+		for (j = 0; j < ntaps; ++j)
+			xscaler->vscaler_coeff[i][j + offset] =
+						coeff[i * ntaps + j];
+	}
+
+	if (pad) { /* effective taps < max_taps */
+		for (i = 0; i < nphases; i++) {
+			/* pad left */
+			for (j = 0; j < offset; j++)
+				xscaler->vscaler_coeff[i][j] = 0;
+			/* pad right */
+			j = ntaps + offset;
+			for (; j < XV_VSCALER_MAX_V_TAPS; j++)
+				xscaler->vscaler_coeff[i][j] = 0;
+		}
+	}
+}
+
+static void xv_vscaler_set_coeff(struct xscaler_device *xscaler)
+{
+	u32 nphases = xscaler->max_num_phases;
+	u32 ntaps   = xscaler->num_vert_taps;
+	int val, i, j, offset, rd_indx;
+	u32 base_addr;
+
+	offset = (XV_VSCALER_MAX_V_TAPS - ntaps) / 2;
+	base_addr = V_VSCALER_OFF + XV_VSCALER_CTRL_ADDR_HWREG_VFLTCOEFF_BASE;
+
+	for (i = 0; i < nphases; i++) {
+		for (j = 0; j < ntaps / 2; j++) {
+			rd_indx = j * 2 + offset;
+			val = (xscaler->vscaler_coeff[i][rd_indx + 1] <<
+			       XSCALER_BITSHIFT_16) |
+			       (xscaler->vscaler_coeff[i][rd_indx] &
+			       XVSC_MASK_LOW_16BITS);
+			xvip_write(&xscaler->xvip,
+				   base_addr + ((i * ntaps / 2 + j) * 4), val);
+		}
+	}
+}
+
+/**
+ * xv_vscaler_coeff_select - Selection of V-Scaler coefficients of operation
+ * @xscaler: VPSS Scaler device information
+ * @height_in: Height of input video
+ * @height_out: Height of desired output video
+ *
+ * There are instances when a N-tap filter might operate in an M-tap
+ * configuration where N > M.
+ *
+ * For example :
+ * Depending on the ratio of scaling (while downscaling), a 10-tap
+ * filter may operate with 6 tap coefficients and zero-pads the remaining
+ * coefficients.
+ *
+ * While upscaling the driver will program 6-tap filter coefficients
+ * in any N-tap configurations (for N >= 6).
+ *
+ * This selection is adopted by the as it gives optimal
+ * video output determined by repeated testing of the IP
+ *
+ * Return: Will return 0 if successful. Returns -EINVAL on an unsupported
+ * V-scaler number of taps.
+ */
+static int
+xv_vscaler_select_coeff(struct xscaler_device *xscaler,
+			u32 height_in, u32 height_out)
+{
+	const short *coeff;
+	u32 ntaps = xscaler->num_vert_taps;
+
+	coeff = xv_select_coeff(xscaler, height_in, height_out, &ntaps);
+	if (!coeff)
+		return -EINVAL;
+
+	xv_vscaler_load_ext_coeff(xscaler, coeff, ntaps);
+	return 0;
+}
+
+/*
+ * V4L2 Subdevice Video Operations
+ */
+
+static inline void
+xv_procss_disable_block(struct xvip_device *xvip, u32 channel, u32 ip_block)
+{
+	xvip_clr(xvip, ((channel - 1) * XGPIO_CHAN_OFFSET) +
+		 XGPIO_DATA_OFFSET + S_AXIS_RESET_OFF,
+		 ip_block);
+}
+
+static inline void
+xv_procss_enable_block(struct xvip_device *xvip, u32 channel, u32 ip_block)
+{
+	xvip_set(xvip, ((channel - 1) * XGPIO_CHAN_OFFSET) +
+		 XGPIO_DATA_OFFSET + S_AXIS_RESET_OFF,
+		 ip_block);
+}
+
+static void xscaler_reset(struct xscaler_device *xscaler)
+{
+	xv_procss_disable_block(&xscaler->xvip, XGPIO_CH_RESET_SEL,
+				XGPIO_RESET_MASK_ALL_BLOCKS);
+	xv_procss_enable_block(&xscaler->xvip, XGPIO_CH_RESET_SEL,
+			       XGPIO_RESET_MASK_IP_AXIS);
+}
+
+static int
+xv_vscaler_setup_video_fmt(struct xscaler_device *xscaler, u32 code_in)
+{
+	u32 video_in;
+
+	switch (code_in) {
+	case MEDIA_BUS_FMT_VYYUYY8_1X24:
+	case MEDIA_BUS_FMT_VYYUYY10_4X20:
+		dev_dbg(xscaler->xvip.dev,
+			"Vscaler Input Media Format YUV 420");
+		video_in = XVIDC_CSF_YCRCB_420;
+		break;
+	case MEDIA_BUS_FMT_UYVY8_1X16:
+	case MEDIA_BUS_FMT_UYVY10_1X20:
+		dev_dbg(xscaler->xvip.dev,
+			"Vscaler Input Media Format YUV 422");
+		video_in = XVIDC_CSF_YCRCB_422;
+		break;
+	case MEDIA_BUS_FMT_VUY8_1X24:
+	case MEDIA_BUS_FMT_VUY10_1X30:
+		dev_dbg(xscaler->xvip.dev,
+			"Vscaler Input Media Format YUV 444");
+		video_in = XVIDC_CSF_YCRCB_444;
+		break;
+	case MEDIA_BUS_FMT_RBG888_1X24:
+	case MEDIA_BUS_FMT_RBG101010_1X30:
+		dev_dbg(xscaler->xvip.dev,
+			"Vscaler Input Media Format RGB");
+		video_in = XVIDC_CSF_RGB;
+		break;
+	default:
+		dev_err(xscaler->xvip.dev,
+			"Vscaler Unsupported Input Media Format 0x%x",
+			code_in);
+		return -EINVAL;
+	}
+	xvip_write(&xscaler->xvip, V_VSCALER_OFF +
+		   XV_VSCALER_CTRL_ADDR_HWREG_COLORMODE_DATA,
+		   video_in);
+	/*
+	 * Vscaler will upscale to YUV 422 before
+	 * Hscaler starts operation
+	 */
+	if (video_in == XVIDC_CSF_YCRCB_420)
+		return XVIDC_CSF_YCRCB_422;
+	return video_in;
+}
+
+static int xv_hscaler_setup_video_fmt(struct xscaler_device *xscaler,
+				      u32 code_out, u32 vsc_out)
+{
+	u32 video_out;
+
+	switch (vsc_out) {
+	case XVIDC_CSF_YCRCB_422:
+		dev_dbg(xscaler->xvip.dev,
+			"Hscaler Input Media Format is YUV 422");
+		break;
+	case XVIDC_CSF_YCRCB_444:
+		dev_dbg(xscaler->xvip.dev,
+			"Hscaler Input Media Format is YUV 444");
+		break;
+	case XVIDC_CSF_RGB:
+		dev_dbg(xscaler->xvip.dev,
+			"Hscaler Input Media Format is RGB");
+		break;
+	default:
+		dev_err(xscaler->xvip.dev,
+			"Hscaler got unsupported format from Vscaler");
+		return -EINVAL;
+	}
+
+	xvip_write(&xscaler->xvip, V_HSCALER_OFF +
+		XV_HSCALER_CTRL_ADDR_HWREG_COLORMODE_DATA,
+		vsc_out);
+
+	switch (code_out) {
+	case MEDIA_BUS_FMT_VYYUYY8_1X24:
+	case MEDIA_BUS_FMT_VYYUYY10_4X20:
+		dev_dbg(xscaler->xvip.dev,
+			"Hscaler Output Media Format YUV 420\n");
+		video_out = XVIDC_CSF_YCRCB_420;
+		break;
+	case MEDIA_BUS_FMT_UYVY8_1X16:
+	case MEDIA_BUS_FMT_UYVY10_1X20:
+		dev_dbg(xscaler->xvip.dev,
+			"Hscaler Output Media Format YUV 422\n");
+		video_out = XVIDC_CSF_YCRCB_422;
+		break;
+	case MEDIA_BUS_FMT_VUY8_1X24:
+	case MEDIA_BUS_FMT_VUY10_1X30:
+		dev_dbg(xscaler->xvip.dev,
+			"Hscaler Output Media Format YUV 444\n");
+		video_out = XVIDC_CSF_YCRCB_444;
+		break;
+	case MEDIA_BUS_FMT_RBG888_1X24:
+	case MEDIA_BUS_FMT_RBG101010_1X30:
+		dev_dbg(xscaler->xvip.dev,
+			"Hscaler Output Media Format RGB\n");
+		video_out = XVIDC_CSF_RGB;
+		break;
+	default:
+		dev_err(xscaler->xvip.dev,
+			"Hscaler Unsupported Output Media Format 0x%x",
+			code_out);
+		return -EINVAL;
+	}
+	xvip_write(&xscaler->xvip, V_HSCALER_OFF +
+		   XV_HSCALER_CTRL_ADDR_HWREG_COLORMODEOUT_DATA,
+		   video_out);
+	return 0;
+}
+
+static void
+xv_hscaler_set_phases(struct xscaler_device *xscaler)
+{
+	u32 loop_width;
+	u32 index = 0, val;
+	u32 offset, i, j = 0, lsb, msb;
+	u64 phasehdata;
+
+	loop_width = xscaler->max_pixels / xscaler->pix_per_clk;
+
+	if (xscaler->cfg->flags & XSCALER_HPHASE_FIX) {
+		offset = V_HSCALER_OFF +
+			XV_HSCALER_CTRL_ADDR_HWREG_PHASEH_FIX;
+	} else {
+		offset = V_HSCALER_OFF +
+			XV_HSCALER_CTRL_ADDR_HWREG_PHASESH_V_BASE;
+	}
+
+	switch (xscaler->pix_per_clk) {
+	case XSCALER_PPC_1:
+		/*
+		 * phaseH is 64 bits but only lower 16 bits of each entry
+		 * is valid .Form a 32 bit word with 16bit LSB from 2
+		 * consecutive entries. Need 1 32b write to get 2 entries
+		 * into IP registers (i is array loc and index is
+		 * address offset)
+		 */
+		for (i = 0; i < loop_width; i += 2) {
+			lsb = lower_32_bits(xscaler->H_phases[i] &
+					    XHSC_MASK_LOW_16BITS);
+			msb = lower_32_bits(xscaler->H_phases[i + 1] &
+					    XHSC_MASK_LOW_16BITS);
+			val = (msb << 16 | lsb);
+			xvip_write(&xscaler->xvip, offset + (index * 4), val);
+			++index;
+		}
+		dev_dbg(xscaler->xvip.dev,
+			"%s : Operating in 1 PPC design", __func__);
+		return;
+	case XSCALER_PPC_2:
+		/*
+		 * PhaseH is 64bits but only lower 32b of each entry is valid
+		 * Need 1 32b write to get each entry into IP registers
+		 */
+		for (i = 0; i < loop_width; i++) {
+			val = lower_32_bits(xscaler->H_phases[i] &
+					    XHSC_MASK_LOW_32BITS);
+			xvip_write(&xscaler->xvip, offset + (i * 4), val);
+		}
+		dev_dbg(xscaler->xvip.dev,
+			"%s : Operating in 2 PPC design", __func__);
+		return;
+	case XSCALER_PPC_4:
+		/*
+		 * PhaseH is 64bits and each entry has valid 32b MSB & LSB
+		 * Need 2 32b writes to get each entry into IP registers
+		 * (index is array loc and offset is address offset)
+		 */
+		for (i = 0; i < loop_width; i++) {
+			phasehdata = xscaler->H_phases[index++];
+			lsb = (u32)(phasehdata & XHSC_MASK_LOW_32BITS);
+			msb = (u32)((phasehdata >> 32) & XHSC_MASK_LOW_32BITS);
+			xvip_write(&xscaler->xvip, offset + (j * 4), lsb);
+			xvip_write(&xscaler->xvip, offset + ((j + 1) * 4), msb);
+			j += 2;
+		}
+		dev_dbg(xscaler->xvip.dev,
+			"%s : Operating in 4 PPC design", __func__);
+		return;
+	default:
+		dev_warn(xscaler->xvip.dev, "%s : %d unsupported ppc design!!!\n",
+			 __func__, xscaler->pix_per_clk);
+	}
+}
+
+static int xscaler_s_stream(struct v4l2_subdev *subdev, int enable)
+{
+	struct xscaler_device *xscaler = to_scaler(subdev);
+	u32 width_in, width_out;
+	u32 height_in, height_out;
+	u32 code_in, code_out;
+	u32 pixel_rate;
+	u32 line_rate;
+	int ret;
+
+	if (!enable) {
+		dev_dbg(xscaler->xvip.dev, "%s: Stream Off", __func__);
+		/* Reset the Global IP Reset through PS GPIO */
+		gpiod_set_value_cansleep(xscaler->rst_gpio,
+					 XSCALER_RESET_ASSERT);
+		gpiod_set_value_cansleep(xscaler->rst_gpio,
+					 XSCALER_RESET_DEASSERT);
+		xscaler_reset(xscaler);
+		memset(xscaler->H_phases, 0, sizeof(xscaler->H_phases));
+		return 0;
+	}
+
+	dev_dbg(xscaler->xvip.dev, "%s: Stream On", __func__);
+
+	/* Extract Sink Pad Information */
+	width_in = xscaler->formats[XVIP_PAD_SINK].width;
+	height_in = xscaler->formats[XVIP_PAD_SINK].height;
+	code_in = xscaler->formats[XVIP_PAD_SINK].code;
+
+	/* Extract Source Pad Information */
+	width_out = xscaler->formats[XVIP_PAD_SOURCE].width;
+	height_out = xscaler->formats[XVIP_PAD_SOURCE].height;
+	code_out = xscaler->formats[XVIP_PAD_SOURCE].code;
+
+	/*
+	 * V Scaler is before H Scaler
+	 * V-Scaler_setup
+	 */
+	line_rate = (height_in * STEP_PRECISION) / height_out;
+
+	if (xscaler->is_polyphase) {
+		ret = xv_vscaler_select_coeff(xscaler, height_in, height_out);
+		if (ret < 0)
+			return ret;
+		xv_vscaler_set_coeff(xscaler);
+	}
+
+	xvip_write(&xscaler->xvip, V_VSCALER_OFF +
+		   XV_VSCALER_CTRL_ADDR_HWREG_HEIGHTIN_DATA, height_in);
+	xvip_write(&xscaler->xvip, V_VSCALER_OFF +
+		   XV_VSCALER_CTRL_ADDR_HWREG_WIDTH_DATA, width_in);
+	xvip_write(&xscaler->xvip, V_VSCALER_OFF +
+		   XV_VSCALER_CTRL_ADDR_HWREG_HEIGHTOUT_DATA, height_out);
+	xvip_write(&xscaler->xvip, V_VSCALER_OFF +
+		   XV_VSCALER_CTRL_ADDR_HWREG_LINERATE_DATA, line_rate);
+	ret = xv_vscaler_setup_video_fmt(xscaler, code_in);
+	if (ret < 0)
+		return ret;
+
+	/* H-Scaler_setup */
+	pixel_rate = (width_in * STEP_PRECISION) / width_out;
+
+	xvip_write(&xscaler->xvip, V_HSCALER_OFF +
+		   XV_HSCALER_CTRL_ADDR_HWREG_HEIGHT_DATA, height_out);
+	xvip_write(&xscaler->xvip, V_HSCALER_OFF +
+		   XV_HSCALER_CTRL_ADDR_HWREG_WIDTHIN_DATA, width_in);
+	xvip_write(&xscaler->xvip, V_HSCALER_OFF +
+		   XV_HSCALER_CTRL_ADDR_HWREG_WIDTHOUT_DATA, width_out);
+	xvip_write(&xscaler->xvip, V_HSCALER_OFF +
+		   XV_HSCALER_CTRL_ADDR_HWREG_PIXELRATE_DATA, pixel_rate);
+	ret = xv_hscaler_setup_video_fmt(xscaler, code_out, ret);
+	if (ret < 0)
+		return ret;
+
+	if (xscaler->is_polyphase) {
+		ret = xv_hscaler_select_coeff(xscaler, width_in, width_out);
+		if (ret < 0)
+			return ret;
+		xv_hscaler_set_coeff(xscaler);
+	}
+
+	xv_hscaler_calculate_phases(xscaler, width_in, width_out, pixel_rate);
+	xv_hscaler_set_phases(xscaler);
+
+	/* Start Scaler sub-cores */
+	xvip_write(&xscaler->xvip, V_HSCALER_OFF +
+		   XV_HSCALER_CTRL_ADDR_AP_CTRL, XSCALER_STREAM_ON);
+	xvip_write(&xscaler->xvip, V_VSCALER_OFF +
+		   XV_VSCALER_CTRL_ADDR_AP_CTRL, XSCALER_STREAM_ON);
+	xv_procss_enable_block(&xscaler->xvip, XGPIO_CH_RESET_SEL,
+			       XGPIO_RESET_MASK_VIDEO_IN);
+	return 0;
+}
+
+/*
+ * V4L2 Subdevice Pad Operations
+ */
+
+static int xscaler_enum_frame_size(struct v4l2_subdev *subdev,
+				   struct v4l2_subdev_pad_config *cfg,
+				   struct v4l2_subdev_frame_size_enum *fse)
+{
+	struct v4l2_mbus_framefmt *format;
+	struct xscaler_device *xscaler = to_scaler(subdev);
+
+	format = v4l2_subdev_get_try_format(subdev, cfg, fse->pad);
+	if (fse->index || fse->code != format->code)
+		return -EINVAL;
+
+	fse->min_width = XSCALER_MIN_WIDTH;
+	fse->max_width = xscaler->max_pixels;
+	fse->min_height = XSCALER_MIN_HEIGHT;
+	fse->max_height = xscaler->max_lines;
+
+	return 0;
+}
+
+static struct v4l2_mbus_framefmt *
+__xscaler_get_pad_format(struct xscaler_device *xscaler,
+			 struct v4l2_subdev_pad_config *cfg,
+			 unsigned int pad, u32 which)
+{
+	struct v4l2_mbus_framefmt *format;
+
+	switch (which) {
+	case V4L2_SUBDEV_FORMAT_TRY:
+		format = v4l2_subdev_get_try_format(&xscaler->xvip.subdev, cfg,
+						    pad);
+		break;
+	case V4L2_SUBDEV_FORMAT_ACTIVE:
+		format = &xscaler->formats[pad];
+		break;
+	default:
+		format = NULL;
+		break;
+	}
+
+	return format;
+}
+
+static int xscaler_get_format(struct v4l2_subdev *subdev,
+			      struct v4l2_subdev_pad_config *cfg,
+			      struct v4l2_subdev_format *fmt)
+{
+	struct xscaler_device *xscaler = to_scaler(subdev);
+	struct v4l2_mbus_framefmt *format;
+
+	format = __xscaler_get_pad_format(xscaler, cfg, fmt->pad,
+					  fmt->which);
+	if (!format)
+		return -EINVAL;
+
+	fmt->format = *format;
+
+	return 0;
+}
+
+static int xscaler_set_format(struct v4l2_subdev *subdev,
+			      struct v4l2_subdev_pad_config *cfg,
+			      struct v4l2_subdev_format *fmt)
+{
+	struct xscaler_device *xscaler = to_scaler(subdev);
+	struct v4l2_mbus_framefmt *format;
+
+	format = __xscaler_get_pad_format(xscaler, cfg, fmt->pad, fmt->which);
+	if (!format)
+		return -EINVAL;
+
+	*format = fmt->format;
+
+	format->width = clamp_t(unsigned int, fmt->format.width,
+				XSCALER_MIN_WIDTH, xscaler->max_pixels);
+	format->height = clamp_t(unsigned int, fmt->format.height,
+				 XSCALER_MIN_HEIGHT, xscaler->max_lines);
+	format->code = fmt->format.code;
+	fmt->format = *format;
+	return 0;
+}
+
+/*
+ * V4L2 Subdevice Operations
+ */
+
+static int
+xscaler_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+	struct xscaler_device *xscaler = to_scaler(subdev);
+	struct v4l2_mbus_framefmt *format;
+
+	/* Initialize with default formats */
+	format = v4l2_subdev_get_try_format(subdev, fh->pad, XVIP_PAD_SINK);
+	*format = xscaler->default_formats[XVIP_PAD_SINK];
+
+	format = v4l2_subdev_get_try_format(subdev, fh->pad, XVIP_PAD_SOURCE);
+	*format = xscaler->default_formats[XVIP_PAD_SOURCE];
+
+	return 0;
+}
+
+static int
+xscaler_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
+{
+	return 0;
+}
+
+static struct v4l2_subdev_video_ops xscaler_video_ops = {
+	.s_stream = xscaler_s_stream,
+};
+
+static struct v4l2_subdev_pad_ops xscaler_pad_ops = {
+	.enum_mbus_code		= xvip_enum_mbus_code,
+	.enum_frame_size	= xscaler_enum_frame_size,
+	.get_fmt		= xscaler_get_format,
+	.set_fmt		= xscaler_set_format,
+};
+
+static struct v4l2_subdev_ops xscaler_ops = {
+	.video  = &xscaler_video_ops,
+	.pad    = &xscaler_pad_ops,
+};
+
+static const struct v4l2_subdev_internal_ops xscaler_internal_ops = {
+	.open	= xscaler_open,
+	.close	= xscaler_close,
+};
+
+/*
+ * Media Operations
+ */
+
+static const struct media_entity_operations xscaler_media_ops = {
+	.link_validate = v4l2_subdev_link_validate,
+};
+
+/*
+ * Platform Device Driver
+ */
+
+static int xscaler_parse_of(struct xscaler_device *xscaler)
+{
+	struct device *dev = xscaler->xvip.dev;
+	struct device_node *node = xscaler->xvip.dev->of_node;
+	const struct xvip_video_format *vip_format;
+	struct device_node *ports;
+	struct device_node *port;
+	int ret;
+	u32 port_id, dt_ppc = 0;
+
+	if (xscaler->cfg->flags & XSCALER_CLK_PROP) {
+		xscaler->aclk_axis = devm_clk_get(dev, "aclk_axis");
+		if (IS_ERR(xscaler->aclk_axis)) {
+			ret = PTR_ERR(xscaler->aclk_axis);
+			dev_err(dev, "failed to get aclk_axis (%d)\n", ret);
+			return ret;
+		}
+		xscaler->aclk_ctrl = devm_clk_get(dev, "aclk_ctrl");
+		if (IS_ERR(xscaler->aclk_ctrl)) {
+			ret = PTR_ERR(xscaler->aclk_ctrl);
+			dev_err(dev, "failed to get aclk_ctrl (%d)\n", ret);
+			return ret;
+		}
+	} else {
+		dev_info(dev, "assuming all required clocks are enabled!\n");
+	}
+
+	ret = of_property_read_u32(node, "xlnx,max-height",
+				   &xscaler->max_lines);
+	if (ret < 0) {
+		dev_err(dev, "xlnx,max-height is missing!");
+		return -EINVAL;
+	} else if (xscaler->max_lines > XSCALER_MAX_HEIGHT ||
+		   xscaler->max_lines < XSCALER_MIN_HEIGHT) {
+		dev_err(dev, "Invalid height in dt");
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32(node, "xlnx,max-width",
+				   &xscaler->max_pixels);
+	if (ret < 0) {
+		dev_err(dev, "xlnx,max-width is missing!");
+		return -EINVAL;
+	} else if (xscaler->max_pixels > XSCALER_MAX_WIDTH ||
+		   xscaler->max_pixels < XSCALER_MIN_WIDTH) {
+		dev_err(dev, "Invalid width in dt");
+		return -EINVAL;
+	}
+
+	ports = of_get_child_by_name(node, "ports");
+	if (!ports)
+		ports = node;
+
+	/* Get the format description for each pad */
+	for_each_child_of_node(ports, port) {
+		if (port->name && (of_node_cmp(port->name, "port") == 0)) {
+			vip_format = xvip_of_get_format(port);
+			if (IS_ERR(vip_format)) {
+				dev_err(dev, "invalid format in DT");
+				return PTR_ERR(vip_format);
+			}
+
+			ret = of_property_read_u32(port, "reg", &port_id);
+			if (ret < 0) {
+				dev_err(dev, "No reg in DT");
+				return ret;
+			}
+
+			if (port_id != 0 && port_id != 1) {
+				dev_err(dev, "Invalid reg in DT");
+				return -EINVAL;
+			}
+			xscaler->vip_formats[port_id] = vip_format;
+		}
+	}
+
+	ret = of_property_read_u32(node, "xlnx,num-hori-taps",
+				   &xscaler->num_hori_taps);
+	if (ret < 0)
+		return ret;
+
+	switch (xscaler->num_hori_taps) {
+	case XV_HSCALER_TAPS_2:
+	case XV_HSCALER_TAPS_4:
+		xscaler->is_polyphase = false;
+		break;
+	case XV_HSCALER_TAPS_6:
+	case XV_HSCALER_TAPS_8:
+	case XV_HSCALER_TAPS_10:
+	case XV_HSCALER_TAPS_12:
+		xscaler->is_polyphase = true;
+		break;
+	default:
+		dev_err(dev, "Unsupported num-hori-taps %d",
+			xscaler->num_hori_taps);
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32(node, "xlnx,num-vert-taps",
+				   &xscaler->num_vert_taps);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * For Bilinear and Bicubic case
+	 * number of vertical and horizontal taps must match
+	 */
+	switch (xscaler->num_vert_taps) {
+	case XV_HSCALER_TAPS_2:
+	case XV_VSCALER_TAPS_4:
+		if (xscaler->num_vert_taps != xscaler->num_hori_taps) {
+			dev_err(dev,
+				"H-scaler taps %d mismatches V-scaler taps %d",
+				 xscaler->num_hori_taps,
+				 xscaler->num_vert_taps);
+			return -EINVAL;
+		}
+		break;
+	case XV_VSCALER_TAPS_6:
+	case XV_VSCALER_TAPS_8:
+	case XV_VSCALER_TAPS_10:
+	case XV_VSCALER_TAPS_12:
+		xscaler->is_polyphase = true;
+		break;
+	default:
+		dev_err(dev, "Unsupported num-vert-taps %d",
+			xscaler->num_vert_taps);
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32(node, "xlnx,pix-per-clk", &dt_ppc);
+	if (ret < 0)
+		return ret;
+
+	/* Driver only supports 1 PPC and 2 PPC */
+	if (dt_ppc != XSCALER_PPC_1 && dt_ppc != XSCALER_PPC_2 &&
+	    dt_ppc != XSCALER_PPC_4) {
+		dev_err(xscaler->xvip.dev,
+			"Unsupported xlnx,pix-per-clk(%d) value in DT", dt_ppc);
+		return -EINVAL;
+	}
+	xscaler->pix_per_clk = dt_ppc;
+
+	/* Reset GPIO */
+	xscaler->rst_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(xscaler->rst_gpio)) {
+		if (PTR_ERR(xscaler->rst_gpio) != -EPROBE_DEFER)
+			dev_err(dev, "Reset GPIO not setup in DT");
+		return PTR_ERR(xscaler->rst_gpio);
+	}
+
+	return 0;
+}
+
+static int xscaler_probe(struct platform_device *pdev)
+{
+	struct xscaler_device *xscaler;
+	struct v4l2_subdev *subdev;
+	struct v4l2_mbus_framefmt *default_format;
+	int ret;
+	const struct of_device_id *match;
+	struct device_node *node = pdev->dev.of_node;
+	struct resource *res;
+
+	xscaler = devm_kzalloc(&pdev->dev, sizeof(*xscaler), GFP_KERNEL);
+	if (!xscaler)
+		return -ENOMEM;
+
+	xscaler->xvip.dev = &pdev->dev;
+
+	match = of_match_node(xscaler_of_id_table, node);
+	if (!match)
+		return -ENODEV;
+
+	if (!strcmp(xscaler_of_id_table[0].compatible, match->compatible)) {
+		dev_warn(&pdev->dev,
+			 "%s - compatible string is getting deprecated!\n",
+			 match->compatible);
+	}
+
+	xscaler->cfg = match->data;
+
+	ret = xscaler_parse_of(xscaler);
+	if (ret < 0)
+		return ret;
+
+	/* Initialize coefficient parameters */
+	xscaler->max_num_phases = XSCALER_MAX_PHASES;
+
+	if (xscaler->cfg->flags & XSCALER_CLK_PROP) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+		xscaler->xvip.iomem = devm_ioremap_resource(xscaler->xvip.dev,
+							    res);
+		if (IS_ERR(xscaler->xvip.iomem))
+			return PTR_ERR(xscaler->xvip.iomem);
+
+		ret = clk_prepare_enable(xscaler->aclk_axis);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to enable aclk_axis (%d)\n",
+				ret);
+			goto res_cleanup;
+		}
+
+		ret = clk_prepare_enable(xscaler->aclk_ctrl);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to enable aclk_ctrl (%d)\n",
+				ret);
+			goto axis_clk_cleanup;
+		}
+	} else {
+		ret = xvip_init_resources(&xscaler->xvip);
+		if (ret < 0)
+			return ret;
+	}
+
+	/* Reset the Global IP Reset through a PS GPIO */
+	gpiod_set_value_cansleep(xscaler->rst_gpio, XSCALER_RESET_DEASSERT);
+	/* Reset internal GPIO within the IP */
+	xscaler_reset(xscaler);
+
+	/* Initialize V4L2 subdevice and media entity */
+	subdev = &xscaler->xvip.subdev;
+	v4l2_subdev_init(subdev, &xscaler_ops);
+	subdev->dev = &pdev->dev;
+	subdev->internal_ops = &xscaler_internal_ops;
+	strlcpy(subdev->name, dev_name(&pdev->dev), sizeof(subdev->name));
+	v4l2_set_subdevdata(subdev, xscaler);
+	subdev->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	/* Initialize default and active formats */
+	default_format = &xscaler->default_formats[XVIP_PAD_SINK];
+	default_format->code = xscaler->vip_formats[XVIP_PAD_SINK]->code;
+	default_format->field = V4L2_FIELD_NONE;
+	default_format->colorspace = V4L2_COLORSPACE_SRGB;
+	default_format->width = XSCALER_DEF_IN_WIDTH;
+	default_format->height = XSCALER_DEF_IN_HEIGHT;
+	xscaler->formats[XVIP_PAD_SINK] = *default_format;
+
+	default_format = &xscaler->default_formats[XVIP_PAD_SOURCE];
+	*default_format = xscaler->default_formats[XVIP_PAD_SINK];
+	default_format->code = xscaler->vip_formats[XVIP_PAD_SOURCE]->code;
+	default_format->width = XSCALER_DEF_OUT_WIDTH;
+	default_format->height = XSCALER_DEF_OUT_HEIGHT;
+	xscaler->formats[XVIP_PAD_SOURCE] = *default_format;
+
+	xscaler->pads[XVIP_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+	xscaler->pads[XVIP_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+	subdev->entity.ops = &xscaler_media_ops;
+
+	ret = media_entity_pads_init(&subdev->entity, 2, xscaler->pads);
+	if (ret < 0)
+		goto error;
+
+	platform_set_drvdata(pdev, xscaler);
+
+	ret = v4l2_async_register_subdev(subdev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to register subdev");
+		goto error;
+	}
+	dev_info(xscaler->xvip.dev, "Num Hori Taps %d",
+		 xscaler->num_hori_taps);
+	dev_info(xscaler->xvip.dev, "Num Vert Taps %d",
+		 xscaler->num_vert_taps);
+	dev_info(&pdev->dev, "VPSS Scaler Probe Successful");
+	return 0;
+
+error:
+	media_entity_cleanup(&subdev->entity);
+	clk_disable_unprepare(xscaler->aclk_ctrl);
+axis_clk_cleanup:
+	clk_disable_unprepare(xscaler->aclk_axis);
+res_cleanup:
+	xvip_cleanup_resources(&xscaler->xvip);
+	return ret;
+}
+
+static int xscaler_remove(struct platform_device *pdev)
+{
+	struct xscaler_device *xscaler = platform_get_drvdata(pdev);
+	struct v4l2_subdev *subdev = &xscaler->xvip.subdev;
+
+	v4l2_async_unregister_subdev(subdev);
+	media_entity_cleanup(&subdev->entity);
+	clk_disable_unprepare(xscaler->aclk_ctrl);
+	clk_disable_unprepare(xscaler->aclk_axis);
+	xvip_cleanup_resources(&xscaler->xvip);
+
+	return 0;
+}
+
+static struct platform_driver xscaler_driver = {
+	.driver			= {
+		.name		= "xilinx-vpss-scaler",
+		.of_match_table	= xscaler_of_id_table,
+	},
+	.probe			= xscaler_probe,
+	.remove			= xscaler_remove,
+};
+
+module_platform_driver(xscaler_driver);
+MODULE_DESCRIPTION("Xilinx Scaler VPSS Driver");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/xilinx-vtc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/xilinx-vtc.c
@@ -141,6 +141,9 @@
 
 #define XVTC_GENERATOR_GLOBAL_DELAY		0x0104
 
+/* Value of 1 = .01% */
+#define XVTC_CLK_MAX_PCT_ERR			1
+
 /**
  * struct xvtc_device - Xilinx Video Timing Controller device structure
  * @xvip: Xilinx Video IP device
@@ -175,10 +178,25 @@
 			 const struct xvtc_config *config)
 {
 	int ret;
+	unsigned long s_rate;
+	unsigned long g_rate;
+	unsigned long clk_err;
 
 	if (!xvtc->has_generator)
 		return -ENXIO;
 
+	s_rate = (unsigned long)config->fps * config->hsize * config->vsize;
+	ret = clk_set_rate(xvtc->xvip.clk, s_rate);
+	if (ret < 0)
+		return ret;
+
+	/* Verify that the clock is within a reasonable tolerance. */
+	g_rate = clk_get_rate(xvtc->xvip.clk);
+	clk_err = (abs(g_rate - s_rate) * 10000) / (s_rate);
+	if (clk_err > XVTC_CLK_MAX_PCT_ERR)
+		dev_warn(xvtc->xvip.dev, "Failed to set clk rate: %lu, actual rate: %lu\n",
+				s_rate, g_rate);
+
 	ret = clk_prepare_enable(xvtc->xvip.clk);
 	if (ret < 0)
 		return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/platform/xilinx/xilinx-vtc.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/platform/xilinx/xilinx-vtc.h
@@ -27,6 +27,7 @@
 	unsigned int vsync_start;
 	unsigned int vsync_end;
 	unsigned int vsize;
+	unsigned int fps;
 };
 
 struct xvtc_device *xvtc_of_get(struct device_node *np);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/radio/radio-isa.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/radio/radio-isa.c
@@ -36,7 +36,7 @@
 
 	strscpy(v->driver, isa->drv->driver.driver.name, sizeof(v->driver));
 	strscpy(v->card, isa->drv->card, sizeof(v->card));
-	snprintf(v->bus_info, sizeof(v->bus_info), "ISA:%s", isa->v4l2_dev.name);
+	snprintf(v->bus_info, sizeof(v->bus_info), "ISA:%s", dev_name(isa->v4l2_dev.dev));
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/radio/radio-shark.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/radio/radio-shark.c
@@ -316,6 +316,16 @@
 {
 	struct shark_device *shark;
 	int retval = -ENOMEM;
+	static const u8 ep_addresses[] = {
+		SHARK_IN_EP | USB_DIR_IN,
+		SHARK_OUT_EP | USB_DIR_OUT,
+		0};
+
+	/* Are the expected endpoints present? */
+	if (!usb_check_int_endpoints(intf, ep_addresses)) {
+		dev_err(&intf->dev, "Invalid radioSHARK device\n");
+		return -EINVAL;
+	}
 
 	shark = kzalloc(sizeof(struct shark_device), GFP_KERNEL);
 	if (!shark)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/radio/radio-shark2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/radio/radio-shark2.c
@@ -62,7 +62,7 @@
 #ifdef SHARK_USE_LEDS
 	struct work_struct led_work;
 	struct led_classdev leds[NO_LEDS];
-	char led_names[NO_LEDS][32];
+	char led_names[NO_LEDS][64];
 	atomic_t brightness[NO_LEDS];
 	unsigned long brightness_new;
 #endif
@@ -282,6 +282,16 @@
 {
 	struct shark_device *shark;
 	int retval = -ENOMEM;
+	static const u8 ep_addresses[] = {
+		SHARK_IN_EP | USB_DIR_IN,
+		SHARK_OUT_EP | USB_DIR_OUT,
+		0};
+
+	/* Are the expected endpoints present? */
+	if (!usb_check_int_endpoints(intf, ep_addresses)) {
+		dev_err(&intf->dev, "Invalid radioSHARK2 device\n");
+		return -EINVAL;
+	}
 
 	shark = kzalloc(sizeof(struct shark_device), GFP_KERNEL);
 	if (!shark)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/radio/radio-wl1273.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/radio/radio-wl1273.c
@@ -1148,8 +1148,7 @@
 	if (radio->rds_users > 0) {
 		radio->rds_users--;
 		if (radio->rds_users == 0) {
-			if (mutex_lock_interruptible(&core->lock))
-				return -EINTR;
+			mutex_lock(&core->lock);
 
 			radio->irq_flags &= ~WL1273_RDS_EVENT;
 
@@ -1280,7 +1279,7 @@
 
 	strscpy(capability->driver, WL1273_FM_DRIVER_NAME,
 		sizeof(capability->driver));
-	strscpy(capability->card, "Texas Instruments Wl1273 FM Radio",
+	strscpy(capability->card, "TI Wl1273 FM Radio",
 		sizeof(capability->card));
 	strscpy(capability->bus_info, radio->bus_type,
 		sizeof(capability->bus_info));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/radio/si470x/radio-si470x-i2c.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/radio/si470x/radio-si470x-i2c.c
@@ -11,7 +11,7 @@
 
 /* driver definitions */
 #define DRIVER_AUTHOR "Joonyoung Shim <jy0922.shim@samsung.com>";
-#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver"
+#define DRIVER_CARD "Silicon Labs Si470x FM Radio"
 #define DRIVER_DESC "I2C radio driver for Si470x FM Radio Receivers"
 #define DRIVER_VERSION "1.0.2"
 
@@ -368,7 +368,7 @@
 	if (radio->hdl.error) {
 		retval = radio->hdl.error;
 		dev_err(&client->dev, "couldn't register control\n");
-		goto err_dev;
+		goto err_all;
 	}
 
 	/* video device initialization */
@@ -463,7 +463,6 @@
 	return 0;
 err_all:
 	v4l2_ctrl_handler_free(&radio->hdl);
-err_dev:
 	v4l2_device_unregister(&radio->v4l2_dev);
 err_initial:
 	return retval;
@@ -482,6 +481,8 @@
 	if (radio->gpio_reset)
 		gpiod_set_value(radio->gpio_reset, 0);
 
+	v4l2_ctrl_handler_free(&radio->hdl);
+	v4l2_device_unregister(&radio->v4l2_dev);
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/radio/si470x/radio-si470x-usb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/radio/si470x/radio-si470x-usb.c
@@ -16,7 +16,7 @@
 
 /* driver definitions */
 #define DRIVER_AUTHOR "Tobias Lorenz <tobias.lorenz@gmx.net>"
-#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver"
+#define DRIVER_CARD "Silicon Labs Si470x FM Radio"
 #define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers"
 #define DRIVER_VERSION "1.0.10"
 
@@ -733,8 +733,10 @@
 
 	/* start radio */
 	retval = si470x_start_usb(radio);
-	if (retval < 0)
+	if (retval < 0 && !radio->int_in_running)
 		goto err_buf;
+	else if (retval < 0)	/* in case of radio->int_in_running == 1 */
+		goto err_all;
 
 	/* set initial frequency */
 	si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/radio/wl128x/fmdrv_common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/radio/wl128x/fmdrv_common.c
@@ -463,11 +463,12 @@
 			   jiffies_to_msecs(FM_DRV_TX_TIMEOUT) / 1000);
 		return -ETIMEDOUT;
 	}
+	spin_lock_irqsave(&fmdev->resp_skb_lock, flags);
 	if (!fmdev->resp_skb) {
+		spin_unlock_irqrestore(&fmdev->resp_skb_lock, flags);
 		fmerr("Response SKB is missing\n");
 		return -EFAULT;
 	}
-	spin_lock_irqsave(&fmdev->resp_skb_lock, flags);
 	skb = fmdev->resp_skb;
 	fmdev->resp_skb = NULL;
 	spin_unlock_irqrestore(&fmdev->resp_skb_lock, flags);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/rc/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/rc/Makefile
@@ -5,6 +5,7 @@
 obj-$(CONFIG_RC_CORE) += rc-core.o
 rc-core-y := rc-main.o rc-ir-raw.o
 rc-core-$(CONFIG_LIRC) += lirc_dev.o
+rc-core-$(CONFIG_MEDIA_CEC_RC) += keymaps/rc-cec.o
 rc-core-$(CONFIG_BPF_LIRC_MODE2) += bpf-lirc.o
 obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o
 obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/rc/ati_remote.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/rc/ati_remote.c
@@ -835,6 +835,10 @@
 		err("%s: endpoint_in message size==0? \n", __func__);
 		return -ENODEV;
 	}
+	if (!usb_endpoint_is_int_out(endpoint_out)) {
+		err("%s: Unexpected endpoint_out\n", __func__);
+		return -ENODEV;
+	}
 
 	ati_remote = kzalloc(sizeof (struct ati_remote), GFP_KERNEL);
 	rc_dev = rc_allocate_device(RC_DRIVER_SCANCODE);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/rc/bpf-lirc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/rc/bpf-lirc.c
@@ -329,7 +329,8 @@
 	}
 
 	if (attr->query.prog_cnt != 0 && prog_ids && cnt)
-		ret = bpf_prog_array_copy_to_user(progs, prog_ids, cnt);
+		ret = bpf_prog_array_copy_to_user(progs, prog_ids,
+						  attr->query.prog_cnt);
 
 unlock:
 	mutex_unlock(&ir_raw_handler_lock);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/rc/ene_ir.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/rc/ene_ir.c
@@ -1106,6 +1106,8 @@
 	struct ene_device *dev = pnp_get_drvdata(pnp_dev);
 	unsigned long flags;
 
+	rc_unregister_device(dev->rdev);
+	del_timer_sync(&dev->tx_sim_timer);
 	spin_lock_irqsave(&dev->hw_lock, flags);
 	ene_rx_disable(dev);
 	ene_rx_restore_hw_buffer(dev);
@@ -1113,7 +1115,6 @@
 
 	free_irq(dev->irq, dev);
 	release_region(dev->hw_io, ENE_IO_SIZE);
-	rc_unregister_device(dev->rdev);
 	kfree(dev);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/rc/gpio-ir-recv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/rc/gpio-ir-recv.c
@@ -83,6 +83,8 @@
 		rcdev->map_name = RC_MAP_EMPTY;
 
 	gpio_dev->rcdev = rcdev;
+	if (of_property_read_bool(np, "wakeup-source"))
+		device_init_wakeup(dev, true);
 
 	rc = devm_rc_register_device(dev, rcdev);
 	if (rc < 0) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/rc/gpio-ir-tx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/rc/gpio-ir-tx.c
@@ -79,13 +79,8 @@
 			// space
 			edge = ktime_add_us(edge, txbuf[i]);
 			delta = ktime_us_delta(edge, ktime_get());
-			if (delta > 10) {
-				spin_unlock_irqrestore(&gpio_ir->lock, flags);
-				usleep_range(delta, delta + 10);
-				spin_lock_irqsave(&gpio_ir->lock, flags);
-			} else if (delta > 0) {
+			if (delta > 0)
 				udelay(delta);
-			}
 		} else {
 			// pulse
 			ktime_t last = ktime_add_us(edge, txbuf[i]);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/rc/igorplugusb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/rc/igorplugusb.c
@@ -64,9 +64,11 @@
 	if (start >= len) {
 		dev_err(ir->dev, "receive overflow invalid: %u", overflow);
 	} else {
-		if (overflow > 0)
+		if (overflow > 0) {
 			dev_warn(ir->dev, "receive overflow, at least %u lost",
 								overflow);
+			ir_raw_event_reset(ir->rc);
+		}
 
 		do {
 			rawir.duration = ir->buf_in[i] * 85333;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/rc/iguanair.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/rc/iguanair.c
@@ -200,8 +200,10 @@
 	if (rc)
 		return rc;
 
-	if (wait_for_completion_timeout(&ir->completion, TIMEOUT) == 0)
+	if (wait_for_completion_timeout(&ir->completion, TIMEOUT) == 0) {
+		usb_kill_urb(ir->urb_out);
 		return -ETIMEDOUT;
+	}
 
 	return rc;
 }
@@ -413,7 +415,7 @@
 	int ret, pipein, pipeout;
 	struct usb_host_interface *idesc;
 
-	idesc = intf->altsetting;
+	idesc = intf->cur_altsetting;
 	if (idesc->desc.bNumEndpoints < 2)
 		return -ENODEV;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/rc/imon.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/rc/imon.c
@@ -151,6 +151,24 @@
 	int touch_y;			/* y coordinate on touchscreen */
 	struct imon_usb_dev_descr *dev_descr; /* device description with key
 						 table for front panels */
+	/*
+	 * Fields for deferring free_imon_context().
+	 *
+	 * Since reference to "struct imon_context" is stored into
+	 * "struct file"->private_data, we need to remember
+	 * how many file descriptors might access this "struct imon_context".
+	 */
+	refcount_t users;
+	/*
+	 * Use a flag for telling display_open()/vfd_write()/lcd_write() that
+	 * imon_disconnect() was already called.
+	 */
+	bool disconnected;
+	/*
+	 * We need to wait for RCU grace period in order to allow
+	 * display_open() to safely check ->disconnected and increment ->users.
+	 */
+	struct rcu_head rcu;
 };
 
 #define TOUCH_TIMEOUT	(HZ/30)
@@ -158,18 +176,18 @@
 /* vfd character device file operations */
 static const struct file_operations vfd_fops = {
 	.owner		= THIS_MODULE,
-	.open		= &display_open,
-	.write		= &vfd_write,
-	.release	= &display_close,
+	.open		= display_open,
+	.write		= vfd_write,
+	.release	= display_close,
 	.llseek		= noop_llseek,
 };
 
 /* lcd character device file operations */
 static const struct file_operations lcd_fops = {
 	.owner		= THIS_MODULE,
-	.open		= &display_open,
-	.write		= &lcd_write,
-	.release	= &display_close,
+	.open		= display_open,
+	.write		= lcd_write,
+	.release	= display_close,
 	.llseek		= noop_llseek,
 };
 
@@ -411,9 +429,6 @@
 	.id_table	= imon_usb_id_table,
 };
 
-/* to prevent races between open() and disconnect(), probing, etc */
-static DEFINE_MUTEX(driver_lock);
-
 /* Module bookkeeping bits */
 MODULE_AUTHOR(MOD_AUTHOR);
 MODULE_DESCRIPTION(MOD_DESC);
@@ -453,9 +468,11 @@
 	struct device *dev = ictx->dev;
 
 	usb_free_urb(ictx->tx_urb);
+	WARN_ON(ictx->dev_present_intf0);
 	usb_free_urb(ictx->rx_urb_intf0);
+	WARN_ON(ictx->dev_present_intf1);
 	usb_free_urb(ictx->rx_urb_intf1);
-	kfree(ictx);
+	kfree_rcu(ictx, rcu);
 
 	dev_dbg(dev, "%s: iMON context freed\n", __func__);
 }
@@ -471,9 +488,6 @@
 	int subminor;
 	int retval = 0;
 
-	/* prevent races with disconnect */
-	mutex_lock(&driver_lock);
-
 	subminor = iminor(inode);
 	interface = usb_find_interface(&imon_driver, subminor);
 	if (!interface) {
@@ -481,17 +495,22 @@
 		retval = -ENODEV;
 		goto exit;
 	}
-	ictx = usb_get_intfdata(interface);
 
-	if (!ictx) {
+	rcu_read_lock();
+	ictx = usb_get_intfdata(interface);
+	if (!ictx || ictx->disconnected || !refcount_inc_not_zero(&ictx->users)) {
+		rcu_read_unlock();
 		pr_err("no context found for minor %d\n", subminor);
 		retval = -ENODEV;
 		goto exit;
 	}
+	rcu_read_unlock();
 
 	mutex_lock(&ictx->lock);
 
-	if (!ictx->display_supported) {
+	if (ictx->disconnected) {
+		retval = -ENODEV;
+	} else if (!ictx->display_supported) {
 		pr_err("display not supported by device\n");
 		retval = -ENODEV;
 	} else if (ictx->display_isopen) {
@@ -505,8 +524,10 @@
 
 	mutex_unlock(&ictx->lock);
 
+	if (retval && refcount_dec_and_test(&ictx->users))
+		free_imon_context(ictx);
+
 exit:
-	mutex_unlock(&driver_lock);
 	return retval;
 }
 
@@ -516,16 +537,9 @@
  */
 static int display_close(struct inode *inode, struct file *file)
 {
-	struct imon_context *ictx = NULL;
+	struct imon_context *ictx = file->private_data;
 	int retval = 0;
 
-	ictx = file->private_data;
-
-	if (!ictx) {
-		pr_err("no context for device\n");
-		return -ENODEV;
-	}
-
 	mutex_lock(&ictx->lock);
 
 	if (!ictx->display_supported) {
@@ -540,6 +554,8 @@
 	}
 
 	mutex_unlock(&ictx->lock);
+	if (refcount_dec_and_test(&ictx->users))
+		free_imon_context(ictx);
 	return retval;
 }
 
@@ -556,6 +572,9 @@
 	int retval = 0;
 	struct usb_ctrlrequest *control_req = NULL;
 
+	if (ictx->disconnected)
+		return -ENODEV;
+
 	/* Check if we need to use control or interrupt urb */
 	if (!ictx->tx_control) {
 		pipe = usb_sndintpipe(ictx->usbdev_intf0,
@@ -604,15 +623,14 @@
 		pr_err_ratelimited("error submitting urb(%d)\n", retval);
 	} else {
 		/* Wait for transmission to complete (or abort) */
-		mutex_unlock(&ictx->lock);
 		retval = wait_for_completion_interruptible(
 				&ictx->tx.finished);
 		if (retval) {
 			usb_kill_urb(ictx->tx_urb);
 			pr_err_ratelimited("task interrupted\n");
 		}
-		mutex_lock(&ictx->lock);
 
+		ictx->tx.busy = false;
 		retval = ictx->tx.status;
 		if (retval)
 			pr_err_ratelimited("packet tx failed (%d)\n", retval);
@@ -909,17 +927,17 @@
 	int offset;
 	int seq;
 	int retval = 0;
-	struct imon_context *ictx;
+	struct imon_context *ictx = file->private_data;
 	static const unsigned char vfd_packet6[] = {
 		0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF };
 
-	ictx = file->private_data;
-	if (!ictx) {
-		pr_err_ratelimited("no context for device\n");
-		return -ENODEV;
-	}
+	if (mutex_lock_interruptible(&ictx->lock))
+		return -ERESTARTSYS;
 
-	mutex_lock(&ictx->lock);
+	if (ictx->disconnected) {
+		retval = -ENODEV;
+		goto exit;
+	}
 
 	if (!ictx->dev_present_intf0) {
 		pr_err_ratelimited("no iMON device present\n");
@@ -993,16 +1011,15 @@
 			 size_t n_bytes, loff_t *pos)
 {
 	int retval = 0;
-	struct imon_context *ictx;
-
-	ictx = file->private_data;
-	if (!ictx) {
-		pr_err_ratelimited("no context for device\n");
-		return -ENODEV;
-	}
+	struct imon_context *ictx = file->private_data;
 
 	mutex_lock(&ictx->lock);
 
+	if (ictx->disconnected) {
+		retval = -ENODEV;
+		goto exit;
+	}
+
 	if (!ictx->display_supported) {
 		pr_err_ratelimited("no iMON display present\n");
 		retval = -ENODEV;
@@ -1117,10 +1134,7 @@
 
 	memcpy(ictx->usb_tx_buf, &ir_proto_packet, sizeof(ir_proto_packet));
 
-	if (!mutex_is_locked(&ictx->lock)) {
-		unlock = true;
-		mutex_lock(&ictx->lock);
-	}
+	unlock = mutex_trylock(&ictx->lock);
 
 	retval = send_packet(ictx);
 	if (retval)
@@ -1598,8 +1612,7 @@
 	spin_unlock_irqrestore(&ictx->kc_lock, flags);
 
 	/* send touchscreen events through input subsystem if touchpad data */
-	if (ictx->display_type == IMON_DISPLAY_TYPE_VGA && len == 8 &&
-	    buf[7] == 0x86) {
+	if (ictx->touch && len == 8 && buf[7] == 0x86) {
 		imon_touch_event(ictx, buf);
 		return;
 
@@ -2365,7 +2378,6 @@
 	int ifnum, sysfs_err;
 	int ret = 0;
 	struct imon_context *ictx = NULL;
-	struct imon_context *first_if_ctx = NULL;
 	u16 vendor, product;
 
 	usbdev     = usb_get_dev(interface_to_usbdev(interface));
@@ -2377,17 +2389,12 @@
 	dev_dbg(dev, "%s: found iMON device (%04x:%04x, intf%d)\n",
 		__func__, vendor, product, ifnum);
 
-	/* prevent races probing devices w/multiple interfaces */
-	mutex_lock(&driver_lock);
-
 	first_if = usb_ifnum_to_if(usbdev, 0);
 	if (!first_if) {
 		ret = -ENODEV;
 		goto fail;
 	}
 
-	first_if_ctx = usb_get_intfdata(first_if);
-
 	if (ifnum == 0) {
 		ictx = imon_init_intf0(interface, id);
 		if (!ictx) {
@@ -2395,9 +2402,11 @@
 			ret = -ENODEV;
 			goto fail;
 		}
+		refcount_set(&ictx->users, 1);
 
 	} else {
 		/* this is the secondary interface on the device */
+		struct imon_context *first_if_ctx = usb_get_intfdata(first_if);
 
 		/* fail early if first intf failed to register */
 		if (!first_if_ctx) {
@@ -2411,14 +2420,13 @@
 			ret = -ENODEV;
 			goto fail;
 		}
+		refcount_inc(&ictx->users);
 
 	}
 
 	usb_set_intfdata(interface, ictx);
 
 	if (ifnum == 0) {
-		mutex_lock(&ictx->lock);
-
 		if (product == 0xffdc && ictx->rf_device) {
 			sysfs_err = sysfs_create_group(&interface->dev.kobj,
 						       &imon_rf_attr_group);
@@ -2429,21 +2437,17 @@
 
 		if (ictx->display_supported)
 			imon_init_display(ictx, interface);
-
-		mutex_unlock(&ictx->lock);
 	}
 
 	dev_info(dev, "iMON device (%04x:%04x, intf%d) on usb<%d:%d> initialized\n",
 		 vendor, product, ifnum,
 		 usbdev->bus->busnum, usbdev->devnum);
 
-	mutex_unlock(&driver_lock);
 	usb_put_dev(usbdev);
 
 	return 0;
 
 fail:
-	mutex_unlock(&driver_lock);
 	usb_put_dev(usbdev);
 	dev_err(dev, "unable to register, err %d\n", ret);
 
@@ -2459,10 +2463,12 @@
 	struct device *dev;
 	int ifnum;
 
-	/* prevent races with multi-interface device probing and display_open */
-	mutex_lock(&driver_lock);
-
 	ictx = usb_get_intfdata(interface);
+
+	mutex_lock(&ictx->lock);
+	ictx->disconnected = true;
+	mutex_unlock(&ictx->lock);
+
 	dev = ictx->dev;
 	ifnum = interface->cur_altsetting->desc.bInterfaceNumber;
 
@@ -2503,11 +2509,9 @@
 		}
 	}
 
-	if (!ictx->dev_present_intf0 && !ictx->dev_present_intf1)
+	if (refcount_dec_and_test(&ictx->users))
 		free_imon_context(ictx);
 
-	mutex_unlock(&driver_lock);
-
 	dev_dbg(dev, "%s: iMON device (intf%d) disconnected\n",
 		__func__, ifnum);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/rc/ir-sharp-decoder.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/rc/ir-sharp-decoder.c
@@ -15,7 +15,9 @@
 #define SHARP_UNIT		40000  /* ns */
 #define SHARP_BIT_PULSE		(8    * SHARP_UNIT) /* 320us */
 #define SHARP_BIT_0_PERIOD	(25   * SHARP_UNIT) /* 1ms (680us space) */
-#define SHARP_BIT_1_PERIOD	(50   * SHARP_UNIT) /* 2ms (1680ms space) */
+#define SHARP_BIT_1_PERIOD	(50   * SHARP_UNIT) /* 2ms (1680us space) */
+#define SHARP_BIT_0_SPACE	(17   * SHARP_UNIT) /* 680us space */
+#define SHARP_BIT_1_SPACE	(42   * SHARP_UNIT) /* 1680us space */
 #define SHARP_ECHO_SPACE	(1000 * SHARP_UNIT) /* 40 ms */
 #define SHARP_TRAILER_SPACE	(125  * SHARP_UNIT) /* 5 ms (even longer) */
 
@@ -168,8 +170,8 @@
 	.header_pulse  = 0,
 	.header_space  = 0,
 	.bit_pulse     = SHARP_BIT_PULSE,
-	.bit_space[0]  = SHARP_BIT_0_PERIOD,
-	.bit_space[1]  = SHARP_BIT_1_PERIOD,
+	.bit_space[0]  = SHARP_BIT_0_SPACE,
+	.bit_space[1]  = SHARP_BIT_1_SPACE,
 	.trailer_pulse = SHARP_BIT_PULSE,
 	.trailer_space = SHARP_ECHO_SPACE,
 	.msb_first     = 1,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/rc/ite-cir.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/rc/ite-cir.c
@@ -276,6 +276,12 @@
 	/* read the interrupt flags */
 	iflags = dev->params.get_irq_causes(dev);
 
+	/* Check for RX overflow */
+	if (iflags & ITE_IRQ_RX_FIFO_OVERRUN) {
+		dev_warn(&dev->rdev->dev, "receive overflow\n");
+		ir_raw_event_reset(dev->rdev);
+	}
+
 	/* check for the receive interrupt */
 	if (iflags & (ITE_IRQ_RX_FIFO | ITE_IRQ_RX_FIFO_OVERRUN)) {
 		/* read the FIFO bytes */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/rc/keymaps/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/rc/keymaps/Makefile
@@ -20,7 +20,6 @@
 			rc-behold.o \
 			rc-behold-columbus.o \
 			rc-budget-ci-old.o \
-			rc-cec.o \
 			rc-cinergy-1400.o \
 			rc-cinergy.o \
 			rc-d680-dmb.o \
@@ -117,6 +116,7 @@
 			rc-videomate-m1f.o \
 			rc-videomate-s350.o \
 			rc-videomate-tv-pvr.o \
+			rc-videostrong-kii-pro.o \
 			rc-wetek-hub.o \
 			rc-wetek-play2.o \
 			rc-winfast.o \
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/rc/keymaps/rc-cec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/rc/keymaps/rc-cec.c
@@ -1,6 +1,16 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 /* Keytable for the CEC remote control
  *
+ * This keymap is unusual in that it can't be built as a module,
+ * instead it is registered directly in rc-main.c if CONFIG_MEDIA_CEC_RC
+ * is set. This is because it can be called from drm_dp_cec_set_edid() via
+ * cec_register_adapter() in an asynchronous context, and it is not
+ * allowed to use request_module() to load rc-cec.ko in that case.
+ *
+ * Since this keymap is only used if CONFIG_MEDIA_CEC_RC is set, we
+ * just compile this keymap into the rc-core module and never as a
+ * separate module.
+ *
  * Copyright (c) 2015 by Kamil Debski
  */
 
@@ -152,7 +162,7 @@
 	/* 0x77-0xff: Reserved */
 };
 
-static struct rc_map_list cec_map = {
+struct rc_map_list cec_map = {
 	.map = {
 		.scan		= cec,
 		.size		= ARRAY_SIZE(cec),
@@ -160,19 +170,3 @@
 		.name		= RC_MAP_CEC,
 	}
 };
-
-static int __init init_rc_map_cec(void)
-{
-	return rc_map_register(&cec_map);
-}
-
-static void __exit exit_rc_map_cec(void)
-{
-	rc_map_unregister(&cec_map);
-}
-
-module_init(init_rc_map_cec);
-module_exit(exit_rc_map_cec);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Kamil Debski");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/rc/keymaps/rc-videostrong-kii-pro.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/rc/keymaps/rc-videostrong-kii-pro.c
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright (C) 2019 Mohammad Rasim <mohammad.rasim96@gmail.com>
+
+#include <media/rc-map.h>
+#include <linux/module.h>
+
+//
+// Keytable for the Videostrong KII Pro STB remote control
+//
+
+static struct rc_map_table kii_pro[] = {
+	{ 0x59, KEY_POWER },
+	{ 0x19, KEY_MUTE },
+	{ 0x42, KEY_RED },
+	{ 0x40, KEY_GREEN },
+	{ 0x00, KEY_YELLOW },
+	{ 0x03, KEY_BLUE },
+	{ 0x4a, KEY_BACK },
+	{ 0x48, KEY_FORWARD },
+	{ 0x08, KEY_PREVIOUSSONG},
+	{ 0x0b, KEY_NEXTSONG},
+	{ 0x46, KEY_PLAYPAUSE },
+	{ 0x44, KEY_STOP },
+	{ 0x1f, KEY_FAVORITES},	//KEY_F5?
+	{ 0x04, KEY_PVR },
+	{ 0x4d, KEY_EPG },
+	{ 0x02, KEY_INFO },
+	{ 0x09, KEY_SUBTITLE },
+	{ 0x01, KEY_AUDIO },
+	{ 0x0d, KEY_HOMEPAGE },
+	{ 0x11, KEY_TV },	// DTV ?
+	{ 0x06, KEY_UP },
+	{ 0x5a, KEY_LEFT },
+	{ 0x1a, KEY_ENTER },	// KEY_OK ?
+	{ 0x1b, KEY_RIGHT },
+	{ 0x16, KEY_DOWN },
+	{ 0x45, KEY_MENU },
+	{ 0x05, KEY_ESC },
+	{ 0x13, KEY_VOLUMEUP },
+	{ 0x17, KEY_VOLUMEDOWN },
+	{ 0x58, KEY_APPSELECT },
+	{ 0x12, KEY_VENDOR },	// mouse
+	{ 0x55, KEY_PAGEUP },	// KEY_CHANNELUP ?
+	{ 0x15, KEY_PAGEDOWN },	// KEY_CHANNELDOWN ?
+	{ 0x52, KEY_1 },
+	{ 0x50, KEY_2 },
+	{ 0x10, KEY_3 },
+	{ 0x56, KEY_4 },
+	{ 0x54, KEY_5 },
+	{ 0x14, KEY_6 },
+	{ 0x4e, KEY_7 },
+	{ 0x4c, KEY_8 },
+	{ 0x0c, KEY_9 },
+	{ 0x18, KEY_WWW },	// KEY_F7
+	{ 0x0f, KEY_0 },
+	{ 0x51, KEY_BACKSPACE },
+};
+
+static struct rc_map_list kii_pro_map = {
+	.map = {
+		.scan     = kii_pro,
+		.size     = ARRAY_SIZE(kii_pro),
+		.rc_proto = RC_PROTO_NEC,
+		.name     = RC_MAP_KII_PRO,
+	}
+};
+
+static int __init init_rc_map_kii_pro(void)
+{
+	return rc_map_register(&kii_pro_map);
+}
+
+static void __exit exit_rc_map_kii_pro(void)
+{
+	rc_map_unregister(&kii_pro_map);
+}
+
+module_init(init_rc_map_kii_pro)
+module_exit(exit_rc_map_kii_pro)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mohammad Rasim <mohammad.rasim96@gmail.com>");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/rc/lirc_dev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/rc/lirc_dev.c
@@ -292,7 +292,11 @@
 		if (ret < 0)
 			goto out_kfree_raw;
 
-		count = ret;
+		/* drop trailing space */
+		if (!(ret % 2))
+			count = ret - 1;
+		else
+			count = ret;
 
 		txbuf = kmalloc_array(count, sizeof(unsigned int), GFP_KERNEL);
 		if (!txbuf) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/rc/mceusb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/rc/mceusb.c
@@ -564,7 +564,7 @@
 			datasize = 4;
 			break;
 		case MCE_CMD_G_REVISION:
-			datasize = 2;
+			datasize = 4;
 			break;
 		case MCE_RSP_EQWAKESUPPORT:
 		case MCE_RSP_GETWAKESOURCE:
@@ -600,14 +600,9 @@
 	char *inout;
 	u8 cmd, subcmd, *data;
 	struct device *dev = ir->dev;
-	int start, skip = 0;
 	u32 carrier, period;
 
-	/* skip meaningless 0xb1 0x60 header bytes on orig receiver */
-	if (ir->flags.microsoft_gen1 && !out && !offset)
-		skip = 2;
-
-	if (len <= skip)
+	if (offset < 0 || offset >= buf_len)
 		return;
 
 	dev_dbg(dev, "%cx data[%d]: %*ph (len=%d sz=%d)",
@@ -616,11 +611,32 @@
 
 	inout = out ? "Request" : "Got";
 
-	start  = offset + skip;
-	cmd    = buf[start] & 0xff;
-	subcmd = buf[start + 1] & 0xff;
-	data = buf + start + 2;
+	cmd    = buf[offset];
+	subcmd = (offset + 1 < buf_len) ? buf[offset + 1] : 0;
+	data   = &buf[offset] + 2;
+
+	/* Trace meaningless 0xb1 0x60 header bytes on original receiver */
+	if (ir->flags.microsoft_gen1 && !out && !offset) {
+		dev_dbg(dev, "MCE gen 1 header");
+		return;
+	}
 
+	/* Trace IR data header or trailer */
+	if (cmd != MCE_CMD_PORT_IR &&
+	    (cmd & MCE_PORT_MASK) == MCE_COMMAND_IRDATA) {
+		if (cmd == MCE_IRDATA_TRAILER)
+			dev_dbg(dev, "End of raw IR data");
+		else
+			dev_dbg(dev, "Raw IR data, %d pulse/space samples",
+				cmd & MCE_PACKET_LENGTH_MASK);
+		return;
+	}
+
+	/* Unexpected end of buffer? */
+	if (offset + len > buf_len)
+		return;
+
+	/* Decode MCE command/response */
 	switch (cmd) {
 	case MCE_CMD_NULL:
 		if (subcmd == MCE_CMD_NULL)
@@ -644,7 +660,7 @@
 				dev_dbg(dev, "Get hw/sw rev?");
 			else
 				dev_dbg(dev, "hw/sw rev %*ph",
-					4, &buf[start + 2]);
+					4, &buf[offset + 2]);
 			break;
 		case MCE_CMD_RESUME:
 			dev_dbg(dev, "Device resume requested");
@@ -685,11 +701,18 @@
 				data[0], data[1]);
 			break;
 		case MCE_RSP_EQIRCFS:
+			if (!data[0] && !data[1]) {
+				dev_dbg(dev, "%s: no carrier", inout);
+				break;
+			}
+			// prescaler should make sense
+			if (data[0] > 8)
+				break;
 			period = DIV_ROUND_CLOSEST((1U << data[0] * 2) *
 						   (data[1] + 1), 10);
 			if (!period)
 				break;
-			carrier = (1000 * 1000) / period;
+			carrier = USEC_PER_SEC / period;
 			dev_dbg(dev, "%s carrier of %u Hz (period %uus)",
 				 inout, carrier, period);
 			break;
@@ -746,13 +769,6 @@
 	default:
 		break;
 	}
-
-	if (cmd == MCE_IRDATA_TRAILER)
-		dev_dbg(dev, "End of raw IR data");
-	else if ((cmd != MCE_CMD_PORT_IR) &&
-		 ((cmd & MCE_PORT_MASK) == MCE_COMMAND_IRDATA))
-		dev_dbg(dev, "Raw IR data, %d pulse/space samples",
-			cmd & MCE_PACKET_LENGTH_MASK);
 #endif
 }
 
@@ -1136,32 +1152,62 @@
 }
 
 /*
+ * Handle PORT_SYS/IR command response received from the MCE device.
+ *
+ * Assumes single response with all its data (not truncated)
+ * in buf_in[]. The response itself determines its total length
+ * (mceusb_cmd_datasize() + 2) and hence the minimum size of buf_in[].
+ *
  * We don't do anything but print debug spew for many of the command bits
  * we receive from the hardware, but some of them are useful information
  * we want to store so that we can use them.
  */
-static void mceusb_handle_command(struct mceusb_dev *ir, int index)
+static void mceusb_handle_command(struct mceusb_dev *ir, u8 *buf_in)
 {
+	u8 cmd = buf_in[0];
+	u8 subcmd = buf_in[1];
+	u8 *hi = &buf_in[2];		/* read only when required */
+	u8 *lo = &buf_in[3];		/* read only when required */
 	struct ir_raw_event rawir = {};
-	u8 hi = ir->buf_in[index + 1] & 0xff;
-	u8 lo = ir->buf_in[index + 2] & 0xff;
 	u32 carrier_cycles;
 	u32 cycles_fix;
 
-	switch (ir->buf_in[index]) {
-	/* the one and only 5-byte return value command */
-	case MCE_RSP_GETPORTSTATUS:
-		if ((ir->buf_in[index + 4] & 0xff) == 0x00)
-			ir->txports_cabled |= 1 << hi;
-		break;
+	if (cmd == MCE_CMD_PORT_SYS) {
+		switch (subcmd) {
+		/* the one and only 5-byte return value command */
+		case MCE_RSP_GETPORTSTATUS:
+			if (buf_in[5] == 0 && *hi < 8)
+				ir->txports_cabled |= 1 << *hi;
+			break;
+
+		/* 1-byte return value commands */
+		case MCE_RSP_EQEMVER:
+			ir->emver = *hi;
+			break;
 
+		/* No return value commands */
+		case MCE_RSP_CMD_ILLEGAL:
+			ir->need_reset = true;
+			break;
+
+		default:
+			break;
+		}
+
+		return;
+	}
+
+	if (cmd != MCE_CMD_PORT_IR)
+		return;
+
+	switch (subcmd) {
 	/* 2-byte return value commands */
 	case MCE_RSP_EQIRTIMEOUT:
-		ir->rc->timeout = US_TO_NS((hi << 8 | lo) * MCE_TIME_UNIT);
+		ir->rc->timeout = US_TO_NS((*hi << 8 | *lo) * MCE_TIME_UNIT);
 		break;
 	case MCE_RSP_EQIRNUMPORTS:
-		ir->num_txports = hi;
-		ir->num_rxports = lo;
+		ir->num_txports = *hi;
+		ir->num_rxports = *lo;
 		break;
 	case MCE_RSP_EQIRRXCFCNT:
 		/*
@@ -1174,7 +1220,7 @@
 		 */
 		if (ir->carrier_report_enabled && ir->learning_active &&
 		    ir->pulse_tunit > 0) {
-			carrier_cycles = (hi << 8 | lo);
+			carrier_cycles = (*hi << 8 | *lo);
 			/*
 			 * Adjust carrier cycle count by adding
 			 * 1 missed count per pulse "on"
@@ -1192,24 +1238,24 @@
 		break;
 
 	/* 1-byte return value commands */
-	case MCE_RSP_EQEMVER:
-		ir->emver = hi;
-		break;
 	case MCE_RSP_EQIRTXPORTS:
-		ir->tx_mask = hi;
+		ir->tx_mask = *hi;
 		break;
 	case MCE_RSP_EQIRRXPORTEN:
-		ir->learning_active = ((hi & 0x02) == 0x02);
-		if (ir->rxports_active != hi) {
+		ir->learning_active = ((*hi & 0x02) == 0x02);
+		if (ir->rxports_active != *hi) {
 			dev_info(ir->dev, "%s-range (0x%x) receiver active",
-				 ir->learning_active ? "short" : "long", hi);
-			ir->rxports_active = hi;
+				 ir->learning_active ? "short" : "long", *hi);
+			ir->rxports_active = *hi;
 		}
 		break;
+
+	/* No return value commands */
 	case MCE_RSP_CMD_ILLEGAL:
 	case MCE_RSP_TX_TIMEOUT:
 		ir->need_reset = true;
 		break;
+
 	default:
 		break;
 	}
@@ -1235,7 +1281,8 @@
 			ir->rem = mceusb_cmd_datasize(ir->cmd, ir->buf_in[i]);
 			mceusb_dev_printdata(ir, ir->buf_in, buf_len, i - 1,
 					     ir->rem + 2, false);
-			mceusb_handle_command(ir, i);
+			if (i + ir->rem < buf_len)
+				mceusb_handle_command(ir, &ir->buf_in[i - 1]);
 			ir->parser_state = CMD_DATA;
 			break;
 		case PARSE_IRDATA:
@@ -1264,15 +1311,22 @@
 			ir->rem--;
 			break;
 		case CMD_HEADER:
-			/* decode mce packets of the form (84),AA,BB,CC,DD */
-			/* IR data packets can span USB messages - rem */
 			ir->cmd = ir->buf_in[i];
 			if ((ir->cmd == MCE_CMD_PORT_IR) ||
 			    ((ir->cmd & MCE_PORT_MASK) !=
 			     MCE_COMMAND_IRDATA)) {
+				/*
+				 * got PORT_SYS, PORT_IR, or unknown
+				 * command response prefix
+				 */
 				ir->parser_state = SUBCMD;
 				continue;
 			}
+			/*
+			 * got IR data prefix (0x80 + num_bytes)
+			 * decode MCE packets of the form {0x83, AA, BB, CC}
+			 * IR data packets can span USB messages
+			 */
 			ir->rem = (ir->cmd & MCE_PACKET_LENGTH_MASK);
 			mceusb_dev_printdata(ir, ir->buf_in, buf_len,
 					     i, ir->rem + 1, false);
@@ -1296,6 +1350,14 @@
 		if (ir->parser_state != CMD_HEADER && !ir->rem)
 			ir->parser_state = CMD_HEADER;
 	}
+
+	/*
+	 * Accept IR data spanning multiple rx buffers.
+	 * Reject MCE command response spanning multiple rx buffers.
+	 */
+	if (ir->parser_state != PARSE_IRDATA || !ir->rem)
+		ir->parser_state = CMD_HEADER;
+
 	if (event) {
 		dev_dbg(ir->dev, "processed IR data");
 		ir_raw_event_handle(ir->rc);
@@ -1324,6 +1386,7 @@
 	case -ECONNRESET:
 	case -ENOENT:
 	case -EILSEQ:
+	case -EPROTO:
 	case -ESHUTDOWN:
 		usb_unlink_urb(urb);
 		return;
@@ -1353,42 +1416,37 @@
 {
 	int ret;
 	struct device *dev = ir->dev;
-	char *data;
-
-	data = kzalloc(USB_CTRL_MSG_SZ, GFP_KERNEL);
-	if (!data) {
-		dev_err(dev, "%s: memory allocation failed!", __func__);
-		return;
-	}
+	char data[USB_CTRL_MSG_SZ];
 
 	/*
 	 * This is a strange one. Windows issues a set address to the device
 	 * on the receive control pipe and expect a certain value pair back
 	 */
-	ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0),
-			      USB_REQ_SET_ADDRESS, USB_TYPE_VENDOR, 0, 0,
-			      data, USB_CTRL_MSG_SZ, HZ * 3);
+	ret = usb_control_msg_recv(ir->usbdev, 0, USB_REQ_SET_ADDRESS,
+				   USB_DIR_IN | USB_TYPE_VENDOR,
+				   0, 0, data, USB_CTRL_MSG_SZ, 3000,
+				   GFP_KERNEL);
 	dev_dbg(dev, "set address - ret = %d", ret);
 	dev_dbg(dev, "set address - data[0] = %d, data[1] = %d",
 						data[0], data[1]);
 
 	/* set feature: bit rate 38400 bps */
-	ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
-			      USB_REQ_SET_FEATURE, USB_TYPE_VENDOR,
-			      0xc04e, 0x0000, NULL, 0, HZ * 3);
+	ret = usb_control_msg_send(ir->usbdev, 0,
+				   USB_REQ_SET_FEATURE, USB_TYPE_VENDOR,
+				   0xc04e, 0x0000, NULL, 0, 3000, GFP_KERNEL);
 
 	dev_dbg(dev, "set feature - ret = %d", ret);
 
 	/* bRequest 4: set char length to 8 bits */
-	ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
-			      4, USB_TYPE_VENDOR,
-			      0x0808, 0x0000, NULL, 0, HZ * 3);
+	ret = usb_control_msg_send(ir->usbdev, 0,
+				   4, USB_TYPE_VENDOR,
+				   0x0808, 0x0000, NULL, 0, 3000, GFP_KERNEL);
 	dev_dbg(dev, "set char length - retB = %d", ret);
 
 	/* bRequest 2: set handshaking to use DTR/DSR */
-	ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
-			      2, USB_TYPE_VENDOR,
-			      0x0000, 0x0100, NULL, 0, HZ * 3);
+	ret = usb_control_msg_send(ir->usbdev, 0,
+				   2, USB_TYPE_VENDOR,
+				   0x0000, 0x0100, NULL, 0, 3000, GFP_KERNEL);
 	dev_dbg(dev, "set handshake  - retC = %d", ret);
 
 	/* device resume */
@@ -1396,8 +1454,6 @@
 
 	/* get hw/sw revision? */
 	mce_command_out(ir, GET_REVISION, sizeof(GET_REVISION));
-
-	kfree(data);
 }
 
 static void mceusb_gen2_init(struct mceusb_dev *ir)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/rc/rc-loopback.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/rc/rc-loopback.c
@@ -42,7 +42,7 @@
 
 	if ((mask & (RXMASK_REGULAR | RXMASK_LEARNING)) != mask) {
 		dprintk("invalid tx mask: %u\n", mask);
-		return -EINVAL;
+		return 2;
 	}
 
 	dprintk("setting tx mask: %u\n", mask);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/rc/rc-main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/rc/rc-main.c
@@ -1256,6 +1256,10 @@
 	}
 
 	mutex_lock(&dev->lock);
+	if (!dev->registered) {
+		mutex_unlock(&dev->lock);
+		return -ENODEV;
+	}
 
 	old_protocols = *current_protocols;
 	new_protocols = old_protocols;
@@ -1394,6 +1398,10 @@
 		return -EINVAL;
 
 	mutex_lock(&dev->lock);
+	if (!dev->registered) {
+		mutex_unlock(&dev->lock);
+		return -ENODEV;
+	}
 
 	new_filter = *filter;
 	if (fattr->mask)
@@ -1508,6 +1516,10 @@
 	int i;
 
 	mutex_lock(&dev->lock);
+	if (!dev->registered) {
+		mutex_unlock(&dev->lock);
+		return -ENODEV;
+	}
 
 	allowed = dev->allowed_wakeup_protocols;
 
@@ -1565,25 +1577,25 @@
 	kfree(dev);
 }
 
-#define ADD_HOTPLUG_VAR(fmt, val...)					\
-	do {								\
-		int err = add_uevent_var(env, fmt, val);		\
-		if (err)						\
-			return err;					\
-	} while (0)
-
 static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env)
 {
 	struct rc_dev *dev = to_rc_dev(device);
+	int ret = 0;
+
+	mutex_lock(&dev->lock);
 
-	if (dev->rc_map.name)
-		ADD_HOTPLUG_VAR("NAME=%s", dev->rc_map.name);
-	if (dev->driver_name)
-		ADD_HOTPLUG_VAR("DRV_NAME=%s", dev->driver_name);
-	if (dev->device_name)
-		ADD_HOTPLUG_VAR("DEV_NAME=%s", dev->device_name);
+	if (!dev->registered)
+		ret = -ENODEV;
+	if (ret == 0 && dev->rc_map.name)
+		ret = add_uevent_var(env, "NAME=%s", dev->rc_map.name);
+	if (ret == 0 && dev->driver_name)
+		ret = add_uevent_var(env, "DRV_NAME=%s", dev->driver_name);
+	if (ret == 0 && dev->device_name)
+		ret = add_uevent_var(env, "DEV_NAME=%s", dev->device_name);
 
-	return 0;
+	mutex_unlock(&dev->lock);
+
+	return ret;
 }
 
 /*
@@ -1773,6 +1785,7 @@
 	set_bit(MSC_SCAN, dev->input_dev->mscbit);
 
 	/* Pointer/mouse events */
+	set_bit(INPUT_PROP_POINTING_STICK, dev->input_dev->propbit);
 	set_bit(EV_REL, dev->input_dev->evbit);
 	set_bit(REL_X, dev->input_dev->relbit);
 	set_bit(REL_Y, dev->input_dev->relbit);
@@ -1879,6 +1892,8 @@
 			goto out_raw;
 	}
 
+	dev->registered = true;
+
 	rc = device_add(&dev->dev);
 	if (rc)
 		goto out_rx_free;
@@ -1888,25 +1903,28 @@
 		 dev->device_name ?: "Unspecified device", path ?: "N/A");
 	kfree(path);
 
-	dev->registered = true;
+	/*
+	 * once the the input device is registered in rc_setup_rx_device,
+	 * userspace can open the input device and rc_open() will be called
+	 * as a result. This results in driver code being allowed to submit
+	 * keycodes with rc_keydown, so lirc must be registered first.
+	 */
+	if (dev->allowed_protocols != RC_PROTO_BIT_CEC) {
+		rc = ir_lirc_register(dev);
+		if (rc < 0)
+			goto out_dev;
+	}
 
 	if (dev->driver_type != RC_DRIVER_IR_RAW_TX) {
 		rc = rc_setup_rx_device(dev);
 		if (rc)
-			goto out_dev;
-	}
-
-	/* Ensure that the lirc kfifo is setup before we start the thread */
-	if (dev->allowed_protocols != RC_PROTO_BIT_CEC) {
-		rc = ir_lirc_register(dev);
-		if (rc < 0)
-			goto out_rx;
+			goto out_lirc;
 	}
 
 	if (dev->driver_type == RC_DRIVER_IR_RAW) {
 		rc = ir_raw_event_register(dev);
 		if (rc < 0)
-			goto out_lirc;
+			goto out_rx;
 	}
 
 	dev_dbg(&dev->dev, "Registered rc%u (driver: %s)\n", dev->minor,
@@ -1914,11 +1932,11 @@
 
 	return 0;
 
+out_rx:
+	rc_free_rx_device(dev);
 out_lirc:
 	if (dev->allowed_protocols != RC_PROTO_BIT_CEC)
 		ir_lirc_unregister(dev);
-out_rx:
-	rc_free_rx_device(dev);
 out_dev:
 	device_del(&dev->dev);
 out_rx_free:
@@ -1969,14 +1987,14 @@
 	del_timer_sync(&dev->timer_keyup);
 	del_timer_sync(&dev->timer_repeat);
 
-	rc_free_rx_device(dev);
-
 	mutex_lock(&dev->lock);
 	if (dev->users && dev->close)
 		dev->close(dev);
 	dev->registered = false;
 	mutex_unlock(&dev->lock);
 
+	rc_free_rx_device(dev);
+
 	/*
 	 * lirc device should be freed with dev->registered = false, so
 	 * that userspace polling will get notified.
@@ -2015,6 +2033,9 @@
 
 	led_trigger_register_simple("rc-feedback", &led_feedback);
 	rc_map_register(&empty_map);
+#ifdef CONFIG_MEDIA_CEC_RC
+	rc_map_register(&cec_map);
+#endif
 
 	return 0;
 }
@@ -2024,6 +2045,9 @@
 	lirc_dev_exit();
 	class_unregister(&rc_class);
 	led_trigger_unregister_simple(led_feedback);
+#ifdef CONFIG_MEDIA_CEC_RC
+	rc_map_unregister(&cec_map);
+#endif
 	rc_map_unregister(&empty_map);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/rc/redrat3.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/rc/redrat3.c
@@ -405,7 +405,7 @@
 	udev = rr3->udev;
 	res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), cmd,
 			      USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
-			      0x0000, 0x0000, data, sizeof(u8), HZ * 10);
+			      0x0000, 0x0000, data, sizeof(u8), 10000);
 
 	if (res < 0) {
 		dev_err(rr3->dev, "%s: Error sending rr3 cmd res %d, data %d",
@@ -481,7 +481,7 @@
 	pipe = usb_rcvctrlpipe(rr3->udev, 0);
 	ret = usb_control_msg(rr3->udev, pipe, RR3_GET_IR_PARAM,
 			      USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
-			      RR3_IR_IO_SIG_TIMEOUT, 0, tmp, len, HZ * 5);
+			      RR3_IR_IO_SIG_TIMEOUT, 0, tmp, len, 5000);
 	if (ret != len)
 		dev_warn(rr3->dev, "Failed to read timeout from hardware\n");
 	else {
@@ -511,7 +511,7 @@
 	ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), RR3_SET_IR_PARAM,
 		     USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
 		     RR3_IR_IO_SIG_TIMEOUT, 0, timeout, sizeof(*timeout),
-		     HZ * 25);
+		     25000);
 	dev_dbg(dev, "set ir parm timeout %d ret 0x%02x\n",
 						be32_to_cpu(*timeout), ret);
 
@@ -543,32 +543,32 @@
 	*val = 0x01;
 	rc = usb_control_msg(udev, rxpipe, RR3_RESET,
 			     USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
-			     RR3_CPUCS_REG_ADDR, 0, val, len, HZ * 25);
+			     RR3_CPUCS_REG_ADDR, 0, val, len, 25000);
 	dev_dbg(dev, "reset returned 0x%02x\n", rc);
 
 	*val = length_fuzz;
 	rc = usb_control_msg(udev, txpipe, RR3_SET_IR_PARAM,
 			     USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
-			     RR3_IR_IO_LENGTH_FUZZ, 0, val, len, HZ * 25);
+			     RR3_IR_IO_LENGTH_FUZZ, 0, val, len, 25000);
 	dev_dbg(dev, "set ir parm len fuzz %d rc 0x%02x\n", *val, rc);
 
 	*val = (65536 - (minimum_pause * 2000)) / 256;
 	rc = usb_control_msg(udev, txpipe, RR3_SET_IR_PARAM,
 			     USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
-			     RR3_IR_IO_MIN_PAUSE, 0, val, len, HZ * 25);
+			     RR3_IR_IO_MIN_PAUSE, 0, val, len, 25000);
 	dev_dbg(dev, "set ir parm min pause %d rc 0x%02x\n", *val, rc);
 
 	*val = periods_measure_carrier;
 	rc = usb_control_msg(udev, txpipe, RR3_SET_IR_PARAM,
 			     USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
-			     RR3_IR_IO_PERIODS_MF, 0, val, len, HZ * 25);
+			     RR3_IR_IO_PERIODS_MF, 0, val, len, 25000);
 	dev_dbg(dev, "set ir parm periods measure carrier %d rc 0x%02x", *val,
 									rc);
 
 	*val = RR3_DRIVER_MAXLENS;
 	rc = usb_control_msg(udev, txpipe, RR3_SET_IR_PARAM,
 			     USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
-			     RR3_IR_IO_MAX_LENGTHS, 0, val, len, HZ * 25);
+			     RR3_IR_IO_MAX_LENGTHS, 0, val, len, 25000);
 	dev_dbg(dev, "set ir parm max lens %d rc 0x%02x\n", *val, rc);
 
 	kfree(val);
@@ -586,7 +586,7 @@
 	rc = usb_control_msg(rr3->udev, usb_rcvctrlpipe(rr3->udev, 0),
 			     RR3_FW_VERSION,
 			     USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
-			     0, 0, buffer, RR3_FW_VERSION_LEN, HZ * 5);
+			     0, 0, buffer, RR3_FW_VERSION_LEN, 5000);
 
 	if (rc >= 0)
 		dev_info(rr3->dev, "Firmware rev: %s", buffer);
@@ -826,14 +826,14 @@
 
 	pipe = usb_sndbulkpipe(rr3->udev, rr3->ep_out->bEndpointAddress);
 	ret = usb_bulk_msg(rr3->udev, pipe, irdata,
-			    sendbuf_len, &ret_len, 10 * HZ);
+			    sendbuf_len, &ret_len, 10000);
 	dev_dbg(dev, "sent %d bytes, (ret %d)\n", ret_len, ret);
 
 	/* now tell the hardware to transmit what we sent it */
 	pipe = usb_rcvctrlpipe(rr3->udev, 0);
 	ret = usb_control_msg(rr3->udev, pipe, RR3_TX_SEND_SIGNAL,
 			      USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
-			      0, 0, irdata, 2, HZ * 10);
+			      0, 0, irdata, 2, 10000);
 
 	if (ret < 0)
 		dev_err(dev, "Error: control msg send failed, rc %d\n", ret);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/rc/sunxi-cir.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/rc/sunxi-cir.c
@@ -137,6 +137,8 @@
 	} else if (status & REG_RXSTA_RPE) {
 		ir_raw_event_set_idle(ir->rc, true);
 		ir_raw_event_handle(ir->rc);
+	} else {
+		ir_raw_event_handle(ir->rc);
 	}
 
 	spin_unlock(&ir->ir_lock);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/spi/cxd2880-spi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/spi/cxd2880-spi.c
@@ -524,13 +524,13 @@
 	if (IS_ERR(dvb_spi->vcc_supply)) {
 		if (PTR_ERR(dvb_spi->vcc_supply) == -EPROBE_DEFER) {
 			ret = -EPROBE_DEFER;
-			goto fail_adapter;
+			goto fail_regulator;
 		}
 		dvb_spi->vcc_supply = NULL;
 	} else {
 		ret = regulator_enable(dvb_spi->vcc_supply);
 		if (ret)
-			goto fail_adapter;
+			goto fail_regulator;
 	}
 
 	dvb_spi->spi = spi;
@@ -618,6 +618,9 @@
 fail_attach:
 	dvb_unregister_adapter(&dvb_spi->adapter);
 fail_adapter:
+	if (dvb_spi->vcc_supply)
+		regulator_disable(dvb_spi->vcc_supply);
+fail_regulator:
 	kfree(dvb_spi);
 	return ret;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/tuners/fc0011.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/tuners/fc0011.c
@@ -499,7 +499,7 @@
 
 	return fe;
 }
-EXPORT_SYMBOL(fc0011_attach);
+EXPORT_SYMBOL_GPL(fc0011_attach);
 
 MODULE_DESCRIPTION("Fitipower FC0011 silicon tuner driver");
 MODULE_AUTHOR("Michael Buesch <m@bues.ch>");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/tuners/fc0012.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/tuners/fc0012.c
@@ -495,7 +495,7 @@
 
 	return fe;
 }
-EXPORT_SYMBOL(fc0012_attach);
+EXPORT_SYMBOL_GPL(fc0012_attach);
 
 MODULE_DESCRIPTION("Fitipower FC0012 silicon tuner driver");
 MODULE_AUTHOR("Hans-Frieder Vogt <hfvogt@gmx.net>");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/tuners/fc0013.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/tuners/fc0013.c
@@ -608,7 +608,7 @@
 
 	return fe;
 }
-EXPORT_SYMBOL(fc0013_attach);
+EXPORT_SYMBOL_GPL(fc0013_attach);
 
 MODULE_DESCRIPTION("Fitipower FC0013 silicon tuner driver");
 MODULE_AUTHOR("Hans-Frieder Vogt <hfvogt@gmx.net>");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/tuners/m88rs6000t.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/tuners/m88rs6000t.c
@@ -525,7 +525,7 @@
 	PGA2_cri = PGA2_GC >> 2;
 	PGA2_crf = PGA2_GC & 0x03;
 
-	for (i = 0; i <= RF_GC; i++)
+	for (i = 0; i <= RF_GC && i < ARRAY_SIZE(RFGS); i++)
 		RFG += RFGS[i];
 
 	if (RF_GC == 0)
@@ -537,12 +537,12 @@
 	if (RF_GC == 3)
 		RFG += 100;
 
-	for (i = 0; i <= IF_GC; i++)
+	for (i = 0; i <= IF_GC && i < ARRAY_SIZE(IFGS); i++)
 		IFG += IFGS[i];
 
 	TIAG = TIA_GC * TIA_GS;
 
-	for (i = 0; i <= BB_GC; i++)
+	for (i = 0; i <= BB_GC && i < ARRAY_SIZE(BBGS); i++)
 		BBG += BBGS[i];
 
 	PGA2G = PGA2_cri * PGA2_cri_GS + PGA2_crf * PGA2_crf_GS;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/tuners/max2165.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/tuners/max2165.c
@@ -410,7 +410,7 @@
 
 	return fe;
 }
-EXPORT_SYMBOL(max2165_attach);
+EXPORT_SYMBOL_GPL(max2165_attach);
 
 MODULE_AUTHOR("David T. L. Wong <davidtlwong@gmail.com>");
 MODULE_DESCRIPTION("Maxim MAX2165 silicon tuner driver");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/tuners/mc44s803.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/tuners/mc44s803.c
@@ -356,7 +356,7 @@
 	kfree(priv);
 	return NULL;
 }
-EXPORT_SYMBOL(mc44s803_attach);
+EXPORT_SYMBOL_GPL(mc44s803_attach);
 
 MODULE_AUTHOR("Jochen Friedrich");
 MODULE_DESCRIPTION("Freescale MC44S803 silicon tuner driver");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/tuners/msi001.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/tuners/msi001.c
@@ -442,6 +442,13 @@
 			V4L2_CID_RF_TUNER_BANDWIDTH_AUTO, 0, 1, 1, 1);
 	dev->bandwidth = v4l2_ctrl_new_std(&dev->hdl, &msi001_ctrl_ops,
 			V4L2_CID_RF_TUNER_BANDWIDTH, 200000, 8000000, 1, 200000);
+	if (dev->hdl.error) {
+		ret = dev->hdl.error;
+		dev_err(&spi->dev, "Could not initialize controls\n");
+		/* control init failed, free handler */
+		goto err_ctrl_handler_free;
+	}
+
 	v4l2_ctrl_auto_cluster(2, &dev->bandwidth_auto, 0, false);
 	dev->lna_gain = v4l2_ctrl_new_std(&dev->hdl, &msi001_ctrl_ops,
 			V4L2_CID_RF_TUNER_LNA_GAIN, 0, 1, 1, 1);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/tuners/mt2060.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/tuners/mt2060.c
@@ -440,7 +440,7 @@
 
 	return fe;
 }
-EXPORT_SYMBOL(mt2060_attach);
+EXPORT_SYMBOL_GPL(mt2060_attach);
 
 static int mt2060_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/tuners/mt2131.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/tuners/mt2131.c
@@ -274,7 +274,7 @@
 	fe->tuner_priv = priv;
 	return fe;
 }
-EXPORT_SYMBOL(mt2131_attach);
+EXPORT_SYMBOL_GPL(mt2131_attach);
 
 MODULE_AUTHOR("Steven Toth");
 MODULE_DESCRIPTION("Microtune MT2131 silicon tuner driver");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/tuners/mt2266.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/tuners/mt2266.c
@@ -336,7 +336,7 @@
 	mt2266_calibrate(priv);
 	return fe;
 }
-EXPORT_SYMBOL(mt2266_attach);
+EXPORT_SYMBOL_GPL(mt2266_attach);
 
 MODULE_AUTHOR("Olivier DANET");
 MODULE_DESCRIPTION("Microtune MT2266 silicon tuner driver");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/tuners/mxl5005s.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/tuners/mxl5005s.c
@@ -4114,7 +4114,7 @@
 	fe->tuner_priv = state;
 	return fe;
 }
-EXPORT_SYMBOL(mxl5005s_attach);
+EXPORT_SYMBOL_GPL(mxl5005s_attach);
 
 MODULE_DESCRIPTION("MaxLinear MXL5005S silicon tuner driver");
 MODULE_AUTHOR("Steven Toth");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/tuners/qm1d1c0042.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/tuners/qm1d1c0042.c
@@ -343,8 +343,10 @@
 		if (val == reg_initval[reg_index][0x00])
 			break;
 	}
-	if (reg_index >= QM1D1C0042_NUM_REG_ROWS)
+	if (reg_index >= QM1D1C0042_NUM_REG_ROWS) {
+		ret = -EINVAL;
 		goto failed;
+	}
 	memcpy(state->regs, reg_initval[reg_index], QM1D1C0042_NUM_REGS);
 	usleep_range(2000, 3000);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/tuners/qt1010.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/tuners/qt1010.c
@@ -215,7 +215,7 @@
 static int qt1010_init_meas1(struct qt1010_priv *priv,
 			     u8 oper, u8 reg, u8 reg_init_val, u8 *retval)
 {
-	u8 i, val1, uninitialized_var(val2);
+	u8 i, val1, val2;
 	int err;
 
 	qt1010_i2c_oper_t i2c_data[] = {
@@ -250,7 +250,7 @@
 static int qt1010_init_meas2(struct qt1010_priv *priv,
 			    u8 reg_init_val, u8 *retval)
 {
-	u8 i, uninitialized_var(val);
+	u8 i, val;
 	int err;
 	qt1010_i2c_oper_t i2c_data[] = {
 		{ QT1010_WR, 0x07, reg_init_val },
@@ -342,11 +342,12 @@
 			else
 				valptr = &tmpval;
 
-			BUG_ON(i >= ARRAY_SIZE(i2c_data) - 1);
-
-			err = qt1010_init_meas1(priv, i2c_data[i+1].reg,
-						i2c_data[i].reg,
-						i2c_data[i].val, valptr);
+			if (i >= ARRAY_SIZE(i2c_data) - 1)
+				err = -EIO;
+			else
+				err = qt1010_init_meas1(priv, i2c_data[i + 1].reg,
+							i2c_data[i].reg,
+							i2c_data[i].val, valptr);
 			i++;
 			break;
 		}
@@ -437,7 +438,7 @@
 	fe->tuner_priv = priv;
 	return fe;
 }
-EXPORT_SYMBOL(qt1010_attach);
+EXPORT_SYMBOL_GPL(qt1010_attach);
 
 MODULE_DESCRIPTION("Quantek QT1010 silicon tuner driver");
 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/tuners/si2157.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/tuners/si2157.c
@@ -75,24 +75,23 @@
 	struct si2157_cmd cmd;
 	const struct firmware *fw;
 	const char *fw_name;
-	unsigned int uitmp, chip_id;
+	unsigned int chip_id, xtal_trim;
 
 	dev_dbg(&client->dev, "\n");
 
-	/* Returned IF frequency is garbage when firmware is not running */
-	memcpy(cmd.args, "\x15\x00\x06\x07", 4);
+	/* Try to get Xtal trim property, to verify tuner still running */
+	memcpy(cmd.args, "\x15\x00\x02\x04", 4);
 	cmd.wlen = 4;
 	cmd.rlen = 4;
 	ret = si2157_cmd_execute(client, &cmd);
-	if (ret)
-		goto err;
 
-	uitmp = cmd.args[2] << 0 | cmd.args[3] << 8;
-	dev_dbg(&client->dev, "if_frequency kHz=%u\n", uitmp);
+	xtal_trim = cmd.args[2] | (cmd.args[3] << 8);
 
-	if (uitmp == dev->if_frequency / 1000)
+	if (ret == 0 && xtal_trim < 16)
 		goto warm;
 
+	dev->if_frequency = 0; /* we no longer know current tuner state */
+
 	/* power up */
 	if (dev->chiptype == SI2157_CHIPTYPE_SI2146) {
 		memcpy(cmd.args, "\xc0\x05\x01\x00\x00\x0b\x00\x00\x01", 9);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/tuners/tda18218.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/tuners/tda18218.c
@@ -336,7 +336,7 @@
 
 	return fe;
 }
-EXPORT_SYMBOL(tda18218_attach);
+EXPORT_SYMBOL_GPL(tda18218_attach);
 
 MODULE_DESCRIPTION("NXP TDA18218HN silicon tuner driver");
 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/tuners/tuner-simple.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/tuners/tuner-simple.c
@@ -500,7 +500,7 @@
 	case TUNER_TENA_9533_DI:
 	case TUNER_YMEC_TVF_5533MF:
 		tuner_dbg("This tuner doesn't have FM. Most cards have a TEA5767 for FM\n");
-		return 0;
+		return -EINVAL;
 	case TUNER_PHILIPS_FM1216ME_MK3:
 	case TUNER_PHILIPS_FM1236_MK3:
 	case TUNER_PHILIPS_FMD1216ME_MK3:
@@ -702,7 +702,8 @@
 		    TUNER_RATIO_SELECT_50; /* 50 kHz step */
 
 	/* Bandswitch byte */
-	simple_radio_bandswitch(fe, &buffer[0]);
+	if (simple_radio_bandswitch(fe, &buffer[0]))
+		return 0;
 
 	/* Convert from 1/16 kHz V4L steps to 1/20 MHz (=50 kHz) PLL steps
 	   freq * (1 Mhz / 16000 V4L steps) * (20 PLL steps / 1 MHz) =
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/tuners/tuner-xc2028.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/tuners/tuner-xc2028.c
@@ -1361,9 +1361,16 @@
 			     void *context)
 {
 	struct dvb_frontend *fe = context;
-	struct xc2028_data *priv = fe->tuner_priv;
+	struct xc2028_data *priv;
 	int rc;
 
+	if (!fe) {
+		pr_warn("xc2028: No frontend in %s\n", __func__);
+		return;
+	}
+
+	priv = fe->tuner_priv;
+
 	tuner_dbg("request_firmware_nowait(): %s\n", fw ? "OK" : "error");
 	if (!fw) {
 		tuner_err("Could not load firmware %s.\n", priv->fname);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/tuners/xc4000.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/tuners/xc4000.c
@@ -1517,10 +1517,10 @@
 {
 	struct xc4000_priv *priv = fe->tuner_priv;
 
+	mutex_lock(&priv->lock);
 	*freq = priv->freq_hz + priv->freq_offset;
 
 	if (debug) {
-		mutex_lock(&priv->lock);
 		if ((priv->cur_fw.type
 		     & (BASE | FM | DTV6 | DTV7 | DTV78 | DTV8)) == BASE) {
 			u16	snr = 0;
@@ -1531,8 +1531,8 @@
 				return 0;
 			}
 		}
-		mutex_unlock(&priv->lock);
 	}
+	mutex_unlock(&priv->lock);
 
 	dprintk(1, "%s()\n", __func__);
 
@@ -1744,7 +1744,7 @@
 	xc4000_release(fe);
 	return NULL;
 }
-EXPORT_SYMBOL(xc4000_attach);
+EXPORT_SYMBOL_GPL(xc4000_attach);
 
 MODULE_AUTHOR("Steven Toth, Davide Ferri");
 MODULE_DESCRIPTION("Xceive xc4000 silicon tuner driver");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/tuners/xc5000.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/tuners/xc5000.c
@@ -1460,7 +1460,7 @@
 	xc5000_release(fe);
 	return NULL;
 }
-EXPORT_SYMBOL(xc5000_attach);
+EXPORT_SYMBOL_GPL(xc5000_attach);
 
 MODULE_AUTHOR("Steven Toth");
 MODULE_DESCRIPTION("Xceive xc5000 silicon tuner driver");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/au0828/au0828-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/au0828/au0828-core.c
@@ -199,8 +199,8 @@
 	struct media_device *mdev;
 
 	mdev = media_device_usb_allocate(udev, KBUILD_MODNAME, THIS_MODULE);
-	if (!mdev)
-		return -ENOMEM;
+	if (IS_ERR(mdev))
+		return PTR_ERR(mdev);
 
 	dev->media_dev = mdev;
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/b2c2/flexcop-usb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/b2c2/flexcop-usb.c
@@ -87,7 +87,7 @@
 			0,
 			fc_usb->data,
 			sizeof(u32),
-			B2C2_WAIT_FOR_OPERATION_RDW * HZ);
+			B2C2_WAIT_FOR_OPERATION_RDW);
 
 	if (ret != sizeof(u32)) {
 		err("error while %s dword from %d (%d).", read ? "reading" :
@@ -155,7 +155,7 @@
 			wIndex,
 			fc_usb->data,
 			buflen,
-			nWaitTime * HZ);
+			nWaitTime);
 	if (ret != buflen)
 		ret = -EIO;
 
@@ -249,13 +249,13 @@
 		/* DKT 020208 - add this to support special case of DiSEqC */
 	case USB_FUNC_I2C_CHECKWRITE:
 		pipe = B2C2_USB_CTRL_PIPE_OUT;
-		nWaitTime = 2;
+		nWaitTime = 2000;
 		request_type |= USB_DIR_OUT;
 		break;
 	case USB_FUNC_I2C_READ:
 	case USB_FUNC_I2C_REPEATREAD:
 		pipe = B2C2_USB_CTRL_PIPE_IN;
-		nWaitTime = 2;
+		nWaitTime = 2000;
 		request_type |= USB_DIR_IN;
 		break;
 	default:
@@ -282,7 +282,7 @@
 			wIndex,
 			fc_usb->data,
 			buflen,
-			nWaitTime * HZ);
+			nWaitTime);
 
 	if (ret != buflen)
 		ret = -EIO;
@@ -295,7 +295,7 @@
 
 	mutex_unlock(&fc_usb->data_mutex);
 
-	return 0;
+	return ret;
 }
 
 /* actual bus specific access functions,
@@ -504,7 +504,16 @@
 static int flexcop_usb_init(struct flexcop_usb *fc_usb)
 {
 	/* use the alternate setting with the larges buffer */
-	usb_set_interface(fc_usb->udev,0,1);
+	int ret = usb_set_interface(fc_usb->udev, 0, 1);
+
+	if (ret) {
+		err("set interface failed.");
+		return ret;
+	}
+
+	if (fc_usb->uintf->cur_altsetting->desc.bNumEndpoints < 1)
+		return -ENODEV;
+
 	switch (fc_usb->udev->speed) {
 	case USB_SPEED_LOW:
 		err("cannot handle USB speed because it is too slow.");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/b2c2/flexcop-usb.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/b2c2/flexcop-usb.h
@@ -91,13 +91,13 @@
 	UTILITY_SRAM_TESTVERIFY     = 0x16,
 } flexcop_usb_utility_function_t;
 
-#define B2C2_WAIT_FOR_OPERATION_RW (1*HZ)
-#define B2C2_WAIT_FOR_OPERATION_RDW (3*HZ)
-#define B2C2_WAIT_FOR_OPERATION_WDW (1*HZ)
+#define B2C2_WAIT_FOR_OPERATION_RW 1000
+#define B2C2_WAIT_FOR_OPERATION_RDW 3000
+#define B2C2_WAIT_FOR_OPERATION_WDW 1000
 
-#define B2C2_WAIT_FOR_OPERATION_V8READ (3*HZ)
-#define B2C2_WAIT_FOR_OPERATION_V8WRITE (3*HZ)
-#define B2C2_WAIT_FOR_OPERATION_V8FLASH (3*HZ)
+#define B2C2_WAIT_FOR_OPERATION_V8READ 3000
+#define B2C2_WAIT_FOR_OPERATION_V8WRITE 3000
+#define B2C2_WAIT_FOR_OPERATION_V8FLASH 3000
 
 typedef enum {
 	V8_MEMORY_PAGE_DVB_CI = 0x20,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/cpia2/cpia2.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/cpia2/cpia2.h
@@ -429,6 +429,7 @@
 int cpia2_do_command(struct camera_data *cam,
 		     unsigned int command,
 		     unsigned char direction, unsigned char param);
+void cpia2_deinit_camera_struct(struct camera_data *cam, struct usb_interface *intf);
 struct camera_data *cpia2_init_camera_struct(struct usb_interface *intf);
 int cpia2_init_camera(struct camera_data *cam);
 int cpia2_allocate_buffers(struct camera_data *cam);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/cpia2/cpia2_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/cpia2/cpia2_core.c
@@ -2167,6 +2167,18 @@
  *
  *  cpia2_init_camera_struct
  *
+ *  Deinitialize camera struct
+ *****************************************************************************/
+void cpia2_deinit_camera_struct(struct camera_data *cam, struct usb_interface *intf)
+{
+	v4l2_device_unregister(&cam->v4l2_dev);
+	kfree(cam);
+}
+
+/******************************************************************************
+ *
+ *  cpia2_init_camera_struct
+ *
  *  Initializes camera struct, does not call reset to fill in defaults.
  *****************************************************************************/
 struct camera_data *cpia2_init_camera_struct(struct usb_interface *intf)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/cpia2/cpia2_usb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/cpia2/cpia2_usb.c
@@ -550,7 +550,7 @@
 			       0,	/* index */
 			       buf,	/* buffer */
 			       size,
-			       HZ);
+			       1000);
 
 	kfree(buf);
 	return ret;
@@ -582,7 +582,7 @@
 			       0,	/* index */
 			       buf,	/* buffer */
 			       size,
-			       HZ);
+			       1000);
 
 	if (ret >= 0)
 		memcpy(registers, buf, size);
@@ -844,15 +844,13 @@
 	ret = set_alternate(cam, USBIF_CMDONLY);
 	if (ret < 0) {
 		ERR("%s: usb_set_interface error (ret = %d)\n", __func__, ret);
-		kfree(cam);
-		return ret;
+		goto alt_err;
 	}
 
 
 	if((ret = cpia2_init_camera(cam)) < 0) {
 		ERR("%s: failed to initialize cpia2 camera (ret = %d)\n", __func__, ret);
-		kfree(cam);
-		return ret;
+		goto alt_err;
 	}
 	LOG("  CPiA Version: %d.%02d (%d.%d)\n",
 	       cam->params.version.firmware_revision_hi,
@@ -872,11 +870,14 @@
 	ret = cpia2_register_camera(cam);
 	if (ret < 0) {
 		ERR("%s: Failed to register cpia2 camera (ret = %d)\n", __func__, ret);
-		kfree(cam);
-		return ret;
+		goto alt_err;
 	}
 
 	return 0;
+
+alt_err:
+	cpia2_deinit_camera_struct(cam, intf);
+	return ret;
 }
 
 /******************************************************************************
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/cx231xx/cx231xx-cards.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/cx231xx/cx231xx-cards.c
@@ -994,6 +994,8 @@
 
 /* table of devices that work with this driver */
 struct usb_device_id cx231xx_id_table[] = {
+	{USB_DEVICE(0x1D19, 0x6108),
+	.driver_info = CX231XX_BOARD_PV_XCAPTURE_USB},
 	{USB_DEVICE(0x1D19, 0x6109),
 	.driver_info = CX231XX_BOARD_PV_XCAPTURE_USB},
 	{USB_DEVICE(0x0572, 0x5A3C),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/cx231xx/cx231xx-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/cx231xx/cx231xx-core.c
@@ -1028,6 +1028,7 @@
 	if (!dev->video_mode.isoc_ctl.urb) {
 		dev_err(dev->dev,
 			"cannot alloc memory for usb buffers\n");
+		kfree(dma_q->p_left_data);
 		return -ENOMEM;
 	}
 
@@ -1037,6 +1038,7 @@
 		dev_err(dev->dev,
 			"cannot allocate memory for usbtransfer\n");
 		kfree(dev->video_mode.isoc_ctl.urb);
+		kfree(dma_q->p_left_data);
 		return -ENOMEM;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/dvb-usb-v2/af9035.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/dvb-usb-v2/af9035.c
@@ -269,6 +269,7 @@
 	struct dvb_usb_device *d = i2c_get_adapdata(adap);
 	struct state *state = d_to_priv(d);
 	int ret;
+	u32 reg;
 
 	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
 		return -EAGAIN;
@@ -321,8 +322,12 @@
 			ret = -EOPNOTSUPP;
 		} else if ((msg[0].addr == state->af9033_i2c_addr[0]) ||
 			   (msg[0].addr == state->af9033_i2c_addr[1])) {
+			if (msg[0].len < 3 || msg[1].len < 1) {
+				ret = -EOPNOTSUPP;
+				goto unlock;
+			}
 			/* demod access via firmware interface */
-			u32 reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 |
+			reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 |
 					msg[0].buf[2];
 
 			if (msg[0].addr == state->af9033_i2c_addr[1])
@@ -380,17 +385,18 @@
 			ret = -EOPNOTSUPP;
 		} else if ((msg[0].addr == state->af9033_i2c_addr[0]) ||
 			   (msg[0].addr == state->af9033_i2c_addr[1])) {
+			if (msg[0].len < 3) {
+				ret = -EOPNOTSUPP;
+				goto unlock;
+			}
 			/* demod access via firmware interface */
-			u32 reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 |
+			reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 |
 					msg[0].buf[2];
 
 			if (msg[0].addr == state->af9033_i2c_addr[1])
 				reg |= 0x100000;
 
-			ret = (msg[0].len >= 3) ? af9035_wr_regs(d, reg,
-							         &msg[0].buf[3],
-							         msg[0].len - 3)
-					        : -EOPNOTSUPP;
+			ret = af9035_wr_regs(d, reg, &msg[0].buf[3], msg[0].len - 3);
 		} else {
 			/* I2C write */
 			u8 buf[MAX_XFER_SIZE];
@@ -457,6 +463,7 @@
 		ret = -EOPNOTSUPP;
 	}
 
+unlock:
 	mutex_unlock(&d->i2c_mutex);
 
 	if (ret < 0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/dvb-usb-v2/anysee.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/dvb-usb-v2/anysee.c
@@ -202,7 +202,7 @@
 
 	while (i < num) {
 		if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {
-			if (msg[i].len > 2 || msg[i+1].len > 60) {
+			if (msg[i].len != 2 || msg[i + 1].len > 60) {
 				ret = -EOPNOTSUPP;
 				break;
 			}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/dvb-usb-v2/az6007.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/dvb-usb-v2/az6007.c
@@ -202,7 +202,8 @@
 	unsigned code;
 	enum rc_proto proto;
 
-	az6007_read(d, AZ6007_READ_IR, 0, 0, st->data, 10);
+	if (az6007_read(d, AZ6007_READ_IR, 0, 0, st->data, 10) < 0)
+		return -EIO;
 
 	if (st->data[1] == 0x44)
 		return 0;
@@ -787,6 +788,10 @@
 			if (az6007_xfer_debug)
 				printk(KERN_DEBUG "az6007: I2C W addr=0x%x len=%d\n",
 				       addr, msgs[i].len);
+			if (msgs[i].len < 1) {
+				ret = -EIO;
+				goto err;
+			}
 			req = AZ6007_I2C_WR;
 			index = msgs[i].buf[0];
 			value = addr | (1 << 8);
@@ -801,6 +806,10 @@
 			if (az6007_xfer_debug)
 				printk(KERN_DEBUG "az6007: I2C R addr=0x%x len=%d\n",
 				       addr, msgs[i].len);
+			if (msgs[i].len < 1) {
+				ret = -EIO;
+				goto err;
+			}
 			req = AZ6007_I2C_RD;
 			index = msgs[i].buf[0];
 			value = addr;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/dvb-usb-v2/ce6230.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/dvb-usb-v2/ce6230.c
@@ -101,6 +101,10 @@
 		if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {
 			if (msg[i].addr ==
 				ce6230_zl10353_config.demod_address) {
+				if (msg[i].len < 1) {
+					i = -EOPNOTSUPP;
+					break;
+				}
 				req.cmd = DEMOD_READ;
 				req.value = msg[i].addr >> 1;
 				req.index = msg[i].buf[0];
@@ -117,6 +121,10 @@
 		} else {
 			if (msg[i].addr ==
 				ce6230_zl10353_config.demod_address) {
+				if (msg[i].len < 1) {
+					i = -EOPNOTSUPP;
+					break;
+				}
 				req.cmd = DEMOD_WRITE;
 				req.value = msg[i].addr >> 1;
 				req.index = msg[i].buf[0];
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/dvb-usb-v2/dvbsky.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/dvb-usb-v2/dvbsky.c
@@ -792,6 +792,9 @@
 	{ DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230C,
 		&mygica_t230c_props, "MyGica Mini DVB-T2 USB Stick T230C",
 		RC_MAP_TOTAL_MEDIA_IN_HAND_02) },
+	{ DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230C_LITE,
+		&mygica_t230c_props, "MyGica Mini DVB-T2 USB Stick T230C Lite",
+		NULL) },
 	{ DVB_USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230C2,
 		&mygica_t230c_props, "MyGica Mini DVB-T2 USB Stick T230C v2",
 		RC_MAP_TOTAL_MEDIA_IN_HAND_02) },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/dvb-usb-v2/ec168.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/dvb-usb-v2/ec168.c
@@ -115,6 +115,10 @@
 	while (i < num) {
 		if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {
 			if (msg[i].addr == ec168_ec100_config.demod_address) {
+				if (msg[i].len < 1) {
+					i = -EOPNOTSUPP;
+					break;
+				}
 				req.cmd = READ_DEMOD;
 				req.value = 0;
 				req.index = 0xff00 + msg[i].buf[0]; /* reg */
@@ -131,6 +135,10 @@
 			}
 		} else {
 			if (msg[i].addr == ec168_ec100_config.demod_address) {
+				if (msg[i].len < 1) {
+					i = -EOPNOTSUPP;
+					break;
+				}
 				req.cmd = WRITE_DEMOD;
 				req.value = msg[i].buf[1]; /* val */
 				req.index = 0xff00 + msg[i].buf[0]; /* reg */
@@ -139,6 +147,10 @@
 				ret = ec168_ctrl_msg(d, &req);
 				i += 1;
 			} else {
+				if (msg[i].len < 1) {
+					i = -EOPNOTSUPP;
+					break;
+				}
 				req.cmd = WRITE_I2C;
 				req.value = msg[i].buf[0]; /* val */
 				req.index = 0x0100 + msg[i].addr; /* I2C addr */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/dvb-usb-v2/lmedm04.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/dvb-usb-v2/lmedm04.c
@@ -372,8 +372,9 @@
 	struct dvb_usb_device *d = adap_to_d(adap);
 	struct lme2510_state *lme_int = adap_to_priv(adap);
 	struct usb_host_endpoint *ep;
+	int ret;
 
-	lme_int->lme_urb = usb_alloc_urb(0, GFP_ATOMIC);
+	lme_int->lme_urb = usb_alloc_urb(0, GFP_KERNEL);
 
 	if (lme_int->lme_urb == NULL)
 			return -ENOMEM;
@@ -389,11 +390,20 @@
 
 	/* Quirk of pipe reporting PIPE_BULK but behaves as interrupt */
 	ep = usb_pipe_endpoint(d->udev, lme_int->lme_urb->pipe);
+	if (!ep) {
+		usb_free_urb(lme_int->lme_urb);
+		return -ENODEV;
+	}
 
 	if (usb_endpoint_type(&ep->desc) == USB_ENDPOINT_XFER_BULK)
-		lme_int->lme_urb->pipe = usb_rcvbulkpipe(d->udev, 0xa),
+		lme_int->lme_urb->pipe = usb_rcvbulkpipe(d->udev, 0xa);
+
+	ret = usb_submit_urb(lme_int->lme_urb, GFP_KERNEL);
+	if (ret) {
+		usb_free_urb(lme_int->lme_urb);
+		return ret;
+	}
 
-	usb_submit_urb(lme_int->lme_urb, GFP_ATOMIC);
 	info("INT Interrupt Service Started");
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/dvb-usb-v2/mxl111sf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/dvb-usb-v2/mxl111sf.c
@@ -931,8 +931,6 @@
 		  .len = sizeof(eeprom), .buf = eeprom },
 	};
 
-	mutex_init(&state->msg_lock);
-
 	ret = get_chip_info(state);
 	if (mxl_fail(ret))
 		pr_err("failed to get chip info during probe");
@@ -1074,6 +1072,14 @@
 	return 0;
 }
 
+static int mxl111sf_probe(struct dvb_usb_device *dev)
+{
+	struct mxl111sf_state *state = d_to_priv(dev);
+
+	mutex_init(&state->msg_lock);
+	return 0;
+}
+
 static struct dvb_usb_device_properties mxl111sf_props_dvbt = {
 	.driver_name = KBUILD_MODNAME,
 	.owner = THIS_MODULE,
@@ -1083,6 +1089,7 @@
 	.generic_bulk_ctrl_endpoint = 0x02,
 	.generic_bulk_ctrl_endpoint_response = 0x81,
 
+	.probe             = mxl111sf_probe,
 	.i2c_algo          = &mxl111sf_i2c_algo,
 	.frontend_attach   = mxl111sf_frontend_attach_dvbt,
 	.tuner_attach      = mxl111sf_attach_tuner,
@@ -1124,6 +1131,7 @@
 	.generic_bulk_ctrl_endpoint = 0x02,
 	.generic_bulk_ctrl_endpoint_response = 0x81,
 
+	.probe             = mxl111sf_probe,
 	.i2c_algo          = &mxl111sf_i2c_algo,
 	.frontend_attach   = mxl111sf_frontend_attach_atsc,
 	.tuner_attach      = mxl111sf_attach_tuner,
@@ -1165,6 +1173,7 @@
 	.generic_bulk_ctrl_endpoint = 0x02,
 	.generic_bulk_ctrl_endpoint_response = 0x81,
 
+	.probe             = mxl111sf_probe,
 	.i2c_algo          = &mxl111sf_i2c_algo,
 	.frontend_attach   = mxl111sf_frontend_attach_mh,
 	.tuner_attach      = mxl111sf_attach_tuner,
@@ -1233,6 +1242,7 @@
 	.generic_bulk_ctrl_endpoint = 0x02,
 	.generic_bulk_ctrl_endpoint_response = 0x81,
 
+	.probe             = mxl111sf_probe,
 	.i2c_algo          = &mxl111sf_i2c_algo,
 	.frontend_attach   = mxl111sf_frontend_attach_atsc_mh,
 	.tuner_attach      = mxl111sf_attach_tuner,
@@ -1311,6 +1321,7 @@
 	.generic_bulk_ctrl_endpoint = 0x02,
 	.generic_bulk_ctrl_endpoint_response = 0x81,
 
+	.probe             = mxl111sf_probe,
 	.i2c_algo          = &mxl111sf_i2c_algo,
 	.frontend_attach   = mxl111sf_frontend_attach_mercury,
 	.tuner_attach      = mxl111sf_attach_tuner,
@@ -1381,6 +1392,7 @@
 	.generic_bulk_ctrl_endpoint = 0x02,
 	.generic_bulk_ctrl_endpoint_response = 0x81,
 
+	.probe             = mxl111sf_probe,
 	.i2c_algo          = &mxl111sf_i2c_algo,
 	.frontend_attach   = mxl111sf_frontend_attach_mercury_mh,
 	.tuner_attach      = mxl111sf_attach_tuner,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -37,7 +37,16 @@
 	} else {
 		/* read */
 		requesttype = (USB_TYPE_VENDOR | USB_DIR_IN);
-		pipe = usb_rcvctrlpipe(d->udev, 0);
+
+		/*
+		 * Zero-length transfers must use usb_sndctrlpipe() and
+		 * rtl28xxu_identify_state() uses a zero-length i2c read
+		 * command to determine the chip type.
+		 */
+		if (req->size)
+			pipe = usb_rcvctrlpipe(d->udev, 0);
+		else
+			pipe = usb_sndctrlpipe(d->udev, 0);
 	}
 
 	ret = usb_control_msg(d->udev, pipe, 0, requesttype, req->value,
@@ -167,6 +176,10 @@
 			ret = -EOPNOTSUPP;
 			goto err_mutex_unlock;
 		} else if (msg[0].addr == 0x10) {
+			if (msg[0].len < 1 || msg[1].len < 1) {
+				ret = -EOPNOTSUPP;
+				goto err_mutex_unlock;
+			}
 			/* method 1 - integrated demod */
 			if (msg[0].buf[0] == 0x00) {
 				/* return demod page from driver cache */
@@ -180,6 +193,10 @@
 				ret = rtl28xxu_ctrl_msg(d, &req);
 			}
 		} else if (msg[0].len < 2) {
+			if (msg[0].len < 1) {
+				ret = -EOPNOTSUPP;
+				goto err_mutex_unlock;
+			}
 			/* method 2 - old I2C */
 			req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1);
 			req.index = CMD_I2C_RD;
@@ -208,8 +225,16 @@
 			ret = -EOPNOTSUPP;
 			goto err_mutex_unlock;
 		} else if (msg[0].addr == 0x10) {
+			if (msg[0].len < 1) {
+				ret = -EOPNOTSUPP;
+				goto err_mutex_unlock;
+			}
 			/* method 1 - integrated demod */
 			if (msg[0].buf[0] == 0x00) {
+				if (msg[0].len < 2) {
+					ret = -EOPNOTSUPP;
+					goto err_mutex_unlock;
+				}
 				/* save demod page for later demod access */
 				dev->page = msg[0].buf[1];
 				ret = 0;
@@ -222,6 +247,10 @@
 				ret = rtl28xxu_ctrl_msg(d, &req);
 			}
 		} else if ((msg[0].len < 23) && (!dev->new_i2c_write)) {
+			if (msg[0].len < 1) {
+				ret = -EOPNOTSUPP;
+				goto err_mutex_unlock;
+			}
 			/* method 2 - old I2C */
 			req.value = (msg[0].buf[0] << 8) | (msg[0].addr << 1);
 			req.index = CMD_I2C_WR;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/dvb-usb/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/dvb-usb/Kconfig
@@ -150,6 +150,7 @@
 config DVB_USB_CXUSB_ANALOG
 	bool "Analog support for the Conexant USB2.0 hybrid reference design"
 	depends on DVB_USB_CXUSB && VIDEO_V4L2
+	depends on VIDEO_V4L2=y || VIDEO_V4L2=DVB_USB_CXUSB
 	select VIDEO_CX25840
 	select VIDEOBUF2_VMALLOC
 	help
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/dvb-usb/af9005.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/dvb-usb/af9005.c
@@ -422,6 +422,10 @@
 		if (ret == 0)
 			ret = 2;
 	} else {
+		if (msg[0].len < 2) {
+			ret = -EOPNOTSUPP;
+			goto unlock;
+		}
 		/* write one or more registers */
 		reg = msg[0].buf[0];
 		addr = msg[0].addr;
@@ -431,6 +435,7 @@
 			ret = 1;
 	}
 
+unlock:
 	mutex_unlock(&d->i2c_mutex);
 	return ret;
 }
@@ -554,7 +559,7 @@
 			      u8 *buf, int size)
 {
 	u16 checksum;
-	int act_len, i, ret;
+	int act_len = 0, i, ret;
 
 	memset(buf, 0, size);
 	buf[0] = (u8) (FW_BULKOUT_SIZE & 0xff);
@@ -976,8 +981,9 @@
 	else if (reply == 0x02)
 		*cold = 0;
 	else
-		return -EIO;
-	deb_info("Identify state cold = %d\n", *cold);
+		ret = -EIO;
+	if (!ret)
+		deb_info("Identify state cold = %d\n", *cold);
 
 err:
 	kfree(buf);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/dvb-usb/az6027.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/dvb-usb/az6027.c
@@ -391,6 +391,7 @@
 /* remote control stuff (does not work with my box) */
 static int az6027_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 {
+	*state = REMOTE_NO_KEY_PRESSED;
 	return 0;
 }
 
@@ -974,6 +975,10 @@
 		if (msg[i].addr == 0x99) {
 			req = 0xBE;
 			index = 0;
+			if (msg[i].len < 1) {
+				i = -EOPNOTSUPP;
+				break;
+			}
 			value = msg[i].buf[0] & 0x00ff;
 			length = 1;
 			az6027_usb_out_op(d, req, value, index, data, length);
@@ -983,6 +988,10 @@
 			/* write/read request */
 			if (i + 1 < num && (msg[i + 1].flags & I2C_M_RD)) {
 				req = 0xB9;
+				if (msg[i].len < 1) {
+					i = -EOPNOTSUPP;
+					break;
+				}
 				index = (((msg[i].buf[0] << 8) & 0xff00) | (msg[i].buf[1] & 0x00ff));
 				value = msg[i].addr + (msg[i].len << 8);
 				length = msg[i + 1].len + 6;
@@ -996,6 +1005,10 @@
 
 				/* demod 16bit addr */
 				req = 0xBD;
+				if (msg[i].len < 1) {
+					i = -EOPNOTSUPP;
+					break;
+				}
 				index = (((msg[i].buf[0] << 8) & 0xff00) | (msg[i].buf[1] & 0x00ff));
 				value = msg[i].addr + (2 << 8);
 				length = msg[i].len - 2;
@@ -1021,6 +1034,10 @@
 			} else {
 
 				req = 0xBD;
+				if (msg[i].len < 1) {
+					i = -EOPNOTSUPP;
+					break;
+				}
 				index = msg[i].buf[0] & 0x00FF;
 				value = msg[i].addr + (1 << 8);
 				length = msg[i].len - 1;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/dvb-usb/cinergyT2-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/dvb-usb/cinergyT2-core.c
@@ -78,6 +78,8 @@
 
 	ret = dvb_usb_generic_rw(d, st->data, 1, st->data, 3, 0);
 	if (ret < 0) {
+		if (adap->fe_adap[0].fe)
+			adap->fe_adap[0].fe->ops.release(adap->fe_adap[0].fe);
 		deb_rc("cinergyt2_power_ctrl() Failed to retrieve sleep state info\n");
 	}
 	mutex_unlock(&d->data_mutex);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/dvb-usb/cxusb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/dvb-usb/cxusb.c
@@ -521,7 +521,8 @@
 {
 	u8 ircode[4];
 
-	cxusb_ctrl_msg(d, CMD_GET_IR_CODE, NULL, 0, ircode, 4);
+	if (cxusb_ctrl_msg(d, CMD_GET_IR_CODE, NULL, 0, ircode, 4) < 0)
+		return 0;
 
 	if (ircode[2] || ircode[3])
 		rc_keydown(d->rc_dev, RC_PROTO_NEC,
@@ -1949,7 +1950,7 @@
 
 	.size_of_priv     = sizeof(struct cxusb_state),
 
-	.num_adapters = 2,
+	.num_adapters = 1,
 	.adapter = {
 		{
 		.num_frontends = 1,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/dvb-usb/dib0700_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/dvb-usb/dib0700_core.c
@@ -616,8 +616,6 @@
 		deb_info("the endpoint number (%i) is not correct, use the adapter id instead", adap->fe_adap[0].stream.props.endpoint);
 		if (onoff)
 			st->channel_state |=	1 << (adap->id);
-		else
-			st->channel_state |=	1 << ~(adap->id);
 	} else {
 		if (onoff)
 			st->channel_state |=	1 << (adap->fe_adap[0].stream.props.endpoint-2);
@@ -818,7 +816,7 @@
 
 	/* Starting in firmware 1.20, the RC info is provided on a bulk pipe */
 
-	if (intf->altsetting[0].desc.bNumEndpoints < rc_ep + 1)
+	if (intf->cur_altsetting->desc.bNumEndpoints < rc_ep + 1)
 		return -ENODEV;
 
 	purb = usb_alloc_urb(0, GFP_KERNEL);
@@ -838,7 +836,7 @@
 	 * Some devices like the Hauppauge NovaTD model 52009 use an interrupt
 	 * endpoint, while others use a bulk one.
 	 */
-	e = &intf->altsetting[0].endpoint[rc_ep].desc;
+	e = &intf->cur_altsetting->endpoint[rc_ep].desc;
 	if (usb_endpoint_dir_in(e)) {
 		if (usb_endpoint_xfer_bulk(e)) {
 			pipe = usb_rcvbulkpipe(d->udev, rc_ep);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/dvb-usb/dib0700_devices.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/dvb-usb/dib0700_devices.c
@@ -2424,7 +2424,12 @@
 
 	adap->fe_adap[0].fe = dvb_attach(dib9000_attach, &adap->dev->i2c_adap, 0x80, &stk9090m_config);
 
-	return adap->fe_adap[0].fe == NULL ?  -ENODEV : 0;
+	if (!adap->fe_adap[0].fe) {
+		release_firmware(state->frontend_firmware);
+		return -ENODEV;
+	}
+
+	return 0;
 }
 
 static int dib9090_tuner_attach(struct dvb_usb_adapter *adap)
@@ -2497,8 +2502,10 @@
 	dib9000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x20, 0x80);
 	adap->fe_adap[0].fe = dvb_attach(dib9000_attach, &adap->dev->i2c_adap, 0x80, &nim9090md_config[0]);
 
-	if (adap->fe_adap[0].fe == NULL)
+	if (!adap->fe_adap[0].fe) {
+		release_firmware(state->frontend_firmware);
 		return -ENODEV;
+	}
 
 	i2c = dib9000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_3_4, 0);
 	dib9000_i2c_enumeration(i2c, 1, 0x12, 0x82);
@@ -2506,7 +2513,12 @@
 	fe_slave = dvb_attach(dib9000_attach, i2c, 0x82, &nim9090md_config[1]);
 	dib9000_set_slave_frontend(adap->fe_adap[0].fe, fe_slave);
 
-	return fe_slave == NULL ?  -ENODEV : 0;
+	if (!fe_slave) {
+		release_firmware(state->frontend_firmware);
+		return -ENODEV;
+	}
+
+	return 0;
 }
 
 static int nim9090md_tuner_attach(struct dvb_usb_adapter *adap)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/dvb-usb/dibusb-common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/dvb-usb/dibusb-common.c
@@ -223,7 +223,7 @@
 	u8 *buf;
 	int rc;
 
-	buf = kmalloc(2, GFP_KERNEL);
+	buf = kzalloc(2, GFP_KERNEL);
 	if (!buf)
 		return -ENOMEM;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/dvb-usb/dibusb-mb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/dvb-usb/dibusb-mb.c
@@ -81,7 +81,7 @@
 
 	if (i2c_transfer(&adap->dev->i2c_adap, msg, 2) != 2) {
 		err("tuner i2c write failed.");
-		ret = -EREMOTEIO;
+		return -EREMOTEIO;
 	}
 
 	if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/dvb-usb/digitv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/dvb-usb/digitv.c
@@ -63,6 +63,10 @@
 		warn("more than 2 i2c messages at a time is not handled yet. TODO.");
 
 	for (i = 0; i < num; i++) {
+		if (msg[i].len < 1) {
+			i = -EOPNOTSUPP;
+			break;
+		}
 		/* write/read request */
 		if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
 			if (digitv_ctrl_msg(d, USB_READ_COFDM, msg[i].buf[0], NULL, 0,
@@ -230,18 +234,22 @@
 
 static int digitv_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
 {
-	int i;
+	int ret, i;
 	u8 key[5];
 	u8 b[4] = { 0 };
 
 	*event = 0;
 	*state = REMOTE_NO_KEY_PRESSED;
 
-	digitv_ctrl_msg(d,USB_READ_REMOTE,0,NULL,0,&key[1],4);
+	ret = digitv_ctrl_msg(d, USB_READ_REMOTE, 0, NULL, 0, &key[1], 4);
+	if (ret)
+		return ret;
 
 	/* Tell the device we've read the remote. Not sure how necessary
 	   this is, but the Nebula SDK does it. */
-	digitv_ctrl_msg(d,USB_WRITE_REMOTE,0,b,4,NULL,0);
+	ret = digitv_ctrl_msg(d, USB_WRITE_REMOTE, 0, b, 4, NULL, 0);
+	if (ret)
+		return ret;
 
 	/* if something is inside the buffer, simulate key press */
 	if (key[1] != 0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/dvb-usb/dtv5100.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/dvb-usb/dtv5100.c
@@ -26,6 +26,7 @@
 			   u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
 {
 	struct dtv5100_state *st = d->priv;
+	unsigned int pipe;
 	u8 request;
 	u8 type;
 	u16 value;
@@ -34,6 +35,7 @@
 	switch (wlen) {
 	case 1:
 		/* write { reg }, read { value } */
+		pipe = usb_rcvctrlpipe(d->udev, 0);
 		request = (addr == DTV5100_DEMOD_ADDR ? DTV5100_DEMOD_READ :
 							DTV5100_TUNER_READ);
 		type = USB_TYPE_VENDOR | USB_DIR_IN;
@@ -41,6 +43,7 @@
 		break;
 	case 2:
 		/* write { reg, value } */
+		pipe = usb_sndctrlpipe(d->udev, 0);
 		request = (addr == DTV5100_DEMOD_ADDR ? DTV5100_DEMOD_WRITE :
 							DTV5100_TUNER_WRITE);
 		type = USB_TYPE_VENDOR | USB_DIR_OUT;
@@ -54,7 +57,7 @@
 
 	memcpy(st->data, rbuf, rlen);
 	msleep(1); /* avoid I2C errors */
-	return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), request,
+	return usb_control_msg(d->udev, pipe, request,
 			       type, value, index, st->data, rlen,
 			       DTV5100_USB_TIMEOUT);
 }
@@ -141,7 +144,7 @@
 
 	/* initialize non qt1010/zl10353 part? */
 	for (i = 0; dtv5100_init[i].request; i++) {
-		ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+		ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
 				      dtv5100_init[i].request,
 				      USB_TYPE_VENDOR | USB_DIR_OUT,
 				      dtv5100_init[i].value,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/dvb-usb/dvb-usb-i2c.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/dvb-usb/dvb-usb-i2c.c
@@ -17,7 +17,8 @@
 
 	if (d->props.i2c_algo == NULL) {
 		err("no i2c algorithm specified");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto err;
 	}
 
 	strscpy(d->i2c_adap.name, d->desc->name, sizeof(d->i2c_adap.name));
@@ -27,11 +28,15 @@
 
 	i2c_set_adapdata(&d->i2c_adap, d);
 
-	if ((ret = i2c_add_adapter(&d->i2c_adap)) < 0)
+	ret = i2c_add_adapter(&d->i2c_adap);
+	if (ret < 0) {
 		err("could not add i2c adapter");
+		goto err;
+	}
 
 	d->state |= DVB_USB_STATE_I2C;
 
+err:
 	return ret;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/dvb-usb/dvb-usb-init.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/dvb-usb/dvb-usb-init.c
@@ -79,11 +79,17 @@
 			}
 		}
 
-		if ((ret = dvb_usb_adapter_stream_init(adap)) ||
-			(ret = dvb_usb_adapter_dvb_init(adap, adapter_nrs)) ||
-			(ret = dvb_usb_adapter_frontend_init(adap))) {
-			return ret;
-		}
+		ret = dvb_usb_adapter_stream_init(adap);
+		if (ret)
+			goto stream_init_err;
+
+		ret = dvb_usb_adapter_dvb_init(adap, adapter_nrs);
+		if (ret)
+			goto dvb_init_err;
+
+		ret = dvb_usb_adapter_frontend_init(adap);
+		if (ret)
+			goto frontend_init_err;
 
 		/* use exclusive FE lock if there is multiple shared FEs */
 		if (adap->fe_adap[1].fe)
@@ -103,6 +109,14 @@
 	}
 
 	return 0;
+
+frontend_init_err:
+	dvb_usb_adapter_dvb_exit(adap);
+dvb_init_err:
+	dvb_usb_adapter_stream_exit(adap);
+stream_init_err:
+	kfree(adap->priv);
+	return ret;
 }
 
 static int dvb_usb_adapter_exit(struct dvb_usb_device *d)
@@ -158,22 +172,20 @@
 
 		if (d->props.priv_init != NULL) {
 			ret = d->props.priv_init(d);
-			if (ret != 0) {
-				kfree(d->priv);
-				d->priv = NULL;
-				return ret;
-			}
+			if (ret != 0)
+				goto err_priv_init;
 		}
 	}
 
 	/* check the capabilities and set appropriate variables */
 	dvb_usb_device_power_ctrl(d, 1);
 
-	if ((ret = dvb_usb_i2c_init(d)) ||
-		(ret = dvb_usb_adapter_init(d, adapter_nums))) {
-		dvb_usb_exit(d);
-		return ret;
-	}
+	ret = dvb_usb_i2c_init(d);
+	if (ret)
+		goto err_i2c_init;
+	ret = dvb_usb_adapter_init(d, adapter_nums);
+	if (ret)
+		goto err_adapter_init;
 
 	if ((ret = dvb_usb_remote_init(d)))
 		err("could not initialize remote control.");
@@ -181,6 +193,17 @@
 	dvb_usb_device_power_ctrl(d, 0);
 
 	return 0;
+
+err_adapter_init:
+	dvb_usb_adapter_exit(d);
+	dvb_usb_i2c_exit(d);
+err_i2c_init:
+	if (d->priv && d->props.priv_destroy)
+		d->props.priv_destroy(d);
+err_priv_init:
+	kfree(d->priv);
+	d->priv = NULL;
+	return ret;
 }
 
 /* determine the name and the state of the just found USB device */
@@ -255,41 +278,50 @@
 	if (du != NULL)
 		*du = NULL;
 
-	if ((desc = dvb_usb_find_device(udev, props, &cold)) == NULL) {
+	d = kzalloc(sizeof(*d), GFP_KERNEL);
+	if (!d) {
+		err("no memory for 'struct dvb_usb_device'");
+		return -ENOMEM;
+	}
+
+	memcpy(&d->props, props, sizeof(struct dvb_usb_device_properties));
+
+	desc = dvb_usb_find_device(udev, &d->props, &cold);
+	if (!desc) {
 		deb_err("something went very wrong, device was not found in current device list - let's see what comes next.\n");
-		return -ENODEV;
+		ret = -ENODEV;
+		goto error;
 	}
 
 	if (cold) {
 		info("found a '%s' in cold state, will try to load a firmware", desc->name);
 		ret = dvb_usb_download_firmware(udev, props);
 		if (!props->no_reconnect || ret != 0)
-			return ret;
+			goto error;
 	}
 
 	info("found a '%s' in warm state.", desc->name);
-	d = kzalloc(sizeof(struct dvb_usb_device), GFP_KERNEL);
-	if (d == NULL) {
-		err("no memory for 'struct dvb_usb_device'");
-		return -ENOMEM;
-	}
-
 	d->udev = udev;
-	memcpy(&d->props, props, sizeof(struct dvb_usb_device_properties));
 	d->desc = desc;
 	d->owner = owner;
 
 	usb_set_intfdata(intf, d);
 
-	if (du != NULL)
+	ret = dvb_usb_init(d, adapter_nums);
+	if (ret) {
+		info("%s error while loading driver (%d)", desc->name, ret);
+		goto error;
+	}
+
+	if (du)
 		*du = d;
 
-	ret = dvb_usb_init(d, adapter_nums);
+	info("%s successfully initialized and connected.", desc->name);
+	return 0;
 
-	if (ret == 0)
-		info("%s successfully initialized and connected.", desc->name);
-	else
-		info("%s error while loading driver (%d)", desc->name, ret);
+ error:
+	usb_set_intfdata(intf, NULL);
+	kfree(d);
 	return ret;
 }
 EXPORT_SYMBOL(dvb_usb_device_init);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/dvb-usb/dvb-usb-urb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/dvb-usb/dvb-usb-urb.c
@@ -12,7 +12,7 @@
 int dvb_usb_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf,
 	u16 rlen, int delay_ms)
 {
-	int actlen,ret = -ENOMEM;
+	int actlen = 0, ret = -ENOMEM;
 
 	if (!d || wbuf == NULL || wlen == 0)
 		return -EINVAL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/dvb-usb/dvb-usb.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/dvb-usb/dvb-usb.h
@@ -485,7 +485,7 @@
 dvb_usb_generic_write(struct dvb_usb_device *, u8 *, u16);
 
 /* commonly used remote control parsing */
-extern int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *, u8[], u32 *, int *);
+extern int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *, u8[5], u32 *, int *);
 
 /* commonly used firmware download types and function */
 struct hexline {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/dvb-usb/dw2102.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/dvb-usb/dw2102.c
@@ -128,6 +128,10 @@
 
 	switch (num) {
 	case 2:
+		if (msg[0].len < 1) {
+			num = -EOPNOTSUPP;
+			break;
+		}
 		/* read stv0299 register */
 		value = msg[0].buf[0];/* register */
 		for (i = 0; i < msg[1].len; i++) {
@@ -139,6 +143,10 @@
 	case 1:
 		switch (msg[0].addr) {
 		case 0x68:
+			if (msg[0].len < 2) {
+				num = -EOPNOTSUPP;
+				break;
+			}
 			/* write to stv0299 register */
 			buf6[0] = 0x2a;
 			buf6[1] = msg[0].buf[0];
@@ -148,6 +156,10 @@
 			break;
 		case 0x60:
 			if (msg[0].flags == 0) {
+				if (msg[0].len < 4) {
+					num = -EOPNOTSUPP;
+					break;
+				}
 			/* write to tuner pll */
 				buf6[0] = 0x2c;
 				buf6[1] = 5;
@@ -159,6 +171,10 @@
 				dw210x_op_rw(d->udev, 0xb2, 0, 0,
 						buf6, 7, DW210X_WRITE_MSG);
 			} else {
+				if (msg[0].len < 1) {
+					num = -EOPNOTSUPP;
+					break;
+				}
 			/* read from tuner */
 				dw210x_op_rw(d->udev, 0xb5, 0, 0,
 						buf6, 1, DW210X_READ_MSG);
@@ -166,12 +182,20 @@
 			}
 			break;
 		case (DW2102_RC_QUERY):
+			if (msg[0].len < 2) {
+				num = -EOPNOTSUPP;
+				break;
+			}
 			dw210x_op_rw(d->udev, 0xb8, 0, 0,
 					buf6, 2, DW210X_READ_MSG);
 			msg[0].buf[0] = buf6[0];
 			msg[0].buf[1] = buf6[1];
 			break;
 		case (DW2102_VOLTAGE_CTRL):
+			if (msg[0].len < 1) {
+				num = -EOPNOTSUPP;
+				break;
+			}
 			buf6[0] = 0x30;
 			buf6[1] = msg[0].buf[0];
 			dw210x_op_rw(d->udev, 0xb2, 0, 0,
@@ -692,6 +716,7 @@
 {
 	struct dvb_usb_device *d = i2c_get_adapdata(adap);
 	struct dw2102_state *state;
+	int j;
 
 	if (!d)
 		return -ENODEV;
@@ -705,11 +730,11 @@
 		return -EAGAIN;
 	}
 
-	switch (num) {
-	case 1:
-		switch (msg[0].addr) {
+	j = 0;
+	while (j < num) {
+		switch (msg[j].addr) {
 		case SU3000_STREAM_CTRL:
-			state->data[0] = msg[0].buf[0] + 0x36;
+			state->data[0] = msg[j].buf[0] + 0x36;
 			state->data[1] = 3;
 			state->data[2] = 0;
 			if (dvb_usb_generic_rw(d, state->data, 3,
@@ -721,61 +746,86 @@
 			if (dvb_usb_generic_rw(d, state->data, 1,
 					state->data, 2, 0) < 0)
 				err("i2c transfer failed.");
-			msg[0].buf[1] = state->data[0];
-			msg[0].buf[0] = state->data[1];
+			msg[j].buf[1] = state->data[0];
+			msg[j].buf[0] = state->data[1];
 			break;
 		default:
-			if (3 + msg[0].len > sizeof(state->data)) {
-				warn("i2c wr: len=%d is too big!\n",
-				     msg[0].len);
+			/* if the current write msg is followed by a another
+			 * read msg to/from the same address
+			 */
+			if ((j+1 < num) && (msg[j+1].flags & I2C_M_RD) &&
+			    (msg[j].addr == msg[j+1].addr)) {
+				/* join both i2c msgs to one usb read command */
+				if (4 + msg[j].len > sizeof(state->data)) {
+					warn("i2c combined wr/rd: write len=%d is too big!\n",
+					    msg[j].len);
+					num = -EOPNOTSUPP;
+					break;
+				}
+				if (1 + msg[j+1].len > sizeof(state->data)) {
+					warn("i2c combined wr/rd: read len=%d is too big!\n",
+					    msg[j+1].len);
+					num = -EOPNOTSUPP;
+					break;
+				}
+
+				state->data[0] = 0x09;
+				state->data[1] = msg[j].len;
+				state->data[2] = msg[j+1].len;
+				state->data[3] = msg[j].addr;
+				memcpy(&state->data[4], msg[j].buf, msg[j].len);
+
+				if (dvb_usb_generic_rw(d, state->data, msg[j].len + 4,
+					state->data, msg[j+1].len + 1, 0) < 0)
+					err("i2c transfer failed.");
+
+				memcpy(msg[j+1].buf, &state->data[1], msg[j+1].len);
+				j++;
+				break;
+			}
+
+			if (msg[j].flags & I2C_M_RD) {
+				/* single read */
+				if (4 + msg[j].len > sizeof(state->data)) {
+					warn("i2c rd: len=%d is too big!\n", msg[j].len);
+					num = -EOPNOTSUPP;
+					break;
+				}
+
+				state->data[0] = 0x09;
+				state->data[1] = 0;
+				state->data[2] = msg[j].len;
+				state->data[3] = msg[j].addr;
+				memcpy(&state->data[4], msg[j].buf, msg[j].len);
+
+				if (dvb_usb_generic_rw(d, state->data, 4,
+					state->data, msg[j].len + 1, 0) < 0)
+					err("i2c transfer failed.");
+
+				memcpy(msg[j].buf, &state->data[1], msg[j].len);
+				break;
+			}
+
+			/* single write */
+			if (3 + msg[j].len > sizeof(state->data)) {
+				warn("i2c wr: len=%d is too big!\n", msg[j].len);
 				num = -EOPNOTSUPP;
 				break;
 			}
 
-			/* always i2c write*/
 			state->data[0] = 0x08;
-			state->data[1] = msg[0].addr;
-			state->data[2] = msg[0].len;
+			state->data[1] = msg[j].addr;
+			state->data[2] = msg[j].len;
 
-			memcpy(&state->data[3], msg[0].buf, msg[0].len);
+			memcpy(&state->data[3], msg[j].buf, msg[j].len);
 
-			if (dvb_usb_generic_rw(d, state->data, msg[0].len + 3,
+			if (dvb_usb_generic_rw(d, state->data, msg[j].len + 3,
 						state->data, 1, 0) < 0)
 				err("i2c transfer failed.");
+		} // switch
+		j++;
 
-		}
-		break;
-	case 2:
-		/* always i2c read */
-		if (4 + msg[0].len > sizeof(state->data)) {
-			warn("i2c rd: len=%d is too big!\n",
-			     msg[0].len);
-			num = -EOPNOTSUPP;
-			break;
-		}
-		if (1 + msg[1].len > sizeof(state->data)) {
-			warn("i2c rd: len=%d is too big!\n",
-			     msg[1].len);
-			num = -EOPNOTSUPP;
-			break;
-		}
-
-		state->data[0] = 0x09;
-		state->data[1] = msg[0].len;
-		state->data[2] = msg[1].len;
-		state->data[3] = msg[0].addr;
-		memcpy(&state->data[4], msg[0].buf, msg[0].len);
-
-		if (dvb_usb_generic_rw(d, state->data, msg[0].len + 4,
-					state->data, msg[1].len + 1, 0) < 0)
-			err("i2c transfer failed.");
-
-		memcpy(msg[1].buf, &state->data[1], msg[1].len);
-		break;
-	default:
-		warn("more than 2 i2c messages at a time is not handled yet.");
-		break;
-	}
+	} // while
 	mutex_unlock(&d->data_mutex);
 	mutex_unlock(&d->i2c_mutex);
 	return num;
@@ -946,7 +996,7 @@
 	for (i = 0; i < 6; i++) {
 		obuf[1] = 0xf0 + i;
 		if (i2c_transfer(&d->i2c_adap, msg, 2) != 2)
-			break;
+			return -1;
 		else
 			mac[i] = ibuf[0];
 	}
@@ -2098,46 +2148,153 @@
 	}
 };
 
-static const struct dvb_usb_device_description d1100 = {
-	"Prof 1100 USB ",
-	{&dw2102_table[PROF_1100], NULL},
-	{NULL},
-};
+static struct dvb_usb_device_properties p1100_properties = {
+	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
+	.usb_ctrl = DEVICE_SPECIFIC,
+	.size_of_priv = sizeof(struct dw2102_state),
+	.firmware = P1100_FIRMWARE,
+	.no_reconnect = 1,
 
-static const struct dvb_usb_device_description d660 = {
-	"TeVii S660 USB",
-	{&dw2102_table[TEVII_S660], NULL},
-	{NULL},
-};
+	.i2c_algo = &s6x0_i2c_algo,
+	.rc.core = {
+		.rc_interval = 150,
+		.rc_codes = RC_MAP_TBS_NEC,
+		.module_name = "dw2102",
+		.allowed_protos   = RC_PROTO_BIT_NEC,
+		.rc_query = prof_rc_query,
+	},
 
-static const struct dvb_usb_device_description d480_1 = {
-	"TeVii S480.1 USB",
-	{&dw2102_table[TEVII_S480_1], NULL},
-	{NULL},
+	.generic_bulk_ctrl_endpoint = 0x81,
+	.num_adapters = 1,
+	.download_firmware = dw2102_load_firmware,
+	.read_mac_address = s6x0_read_mac_address,
+	.adapter = {
+		{
+			.num_frontends = 1,
+			.fe = {{
+				.frontend_attach = stv0288_frontend_attach,
+				.stream = {
+					.type = USB_BULK,
+					.count = 8,
+					.endpoint = 0x82,
+					.u = {
+						.bulk = {
+							.buffersize = 4096,
+						}
+					}
+				},
+			} },
+		}
+	},
+	.num_device_descs = 1,
+	.devices = {
+		{"Prof 1100 USB ",
+			{&dw2102_table[PROF_1100], NULL},
+			{NULL},
+		},
+	}
 };
 
-static const struct dvb_usb_device_description d480_2 = {
-	"TeVii S480.2 USB",
-	{&dw2102_table[TEVII_S480_2], NULL},
-	{NULL},
-};
+static struct dvb_usb_device_properties s660_properties = {
+	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
+	.usb_ctrl = DEVICE_SPECIFIC,
+	.size_of_priv = sizeof(struct dw2102_state),
+	.firmware = S660_FIRMWARE,
+	.no_reconnect = 1,
 
-static const struct dvb_usb_device_description d7500 = {
-	"Prof 7500 USB DVB-S2",
-	{&dw2102_table[PROF_7500], NULL},
-	{NULL},
-};
+	.i2c_algo = &s6x0_i2c_algo,
+	.rc.core = {
+		.rc_interval = 150,
+		.rc_codes = RC_MAP_TEVII_NEC,
+		.module_name = "dw2102",
+		.allowed_protos   = RC_PROTO_BIT_NEC,
+		.rc_query = dw2102_rc_query,
+	},
 
-static const struct dvb_usb_device_description d421 = {
-	"TeVii S421 PCI",
-	{&dw2102_table[TEVII_S421], NULL},
-	{NULL},
+	.generic_bulk_ctrl_endpoint = 0x81,
+	.num_adapters = 1,
+	.download_firmware = dw2102_load_firmware,
+	.read_mac_address = s6x0_read_mac_address,
+	.adapter = {
+		{
+			.num_frontends = 1,
+			.fe = {{
+				.frontend_attach = ds3000_frontend_attach,
+				.stream = {
+					.type = USB_BULK,
+					.count = 8,
+					.endpoint = 0x82,
+					.u = {
+						.bulk = {
+							.buffersize = 4096,
+						}
+					}
+				},
+			} },
+		}
+	},
+	.num_device_descs = 3,
+	.devices = {
+		{"TeVii S660 USB",
+			{&dw2102_table[TEVII_S660], NULL},
+			{NULL},
+		},
+		{"TeVii S480.1 USB",
+			{&dw2102_table[TEVII_S480_1], NULL},
+			{NULL},
+		},
+		{"TeVii S480.2 USB",
+			{&dw2102_table[TEVII_S480_2], NULL},
+			{NULL},
+		},
+	}
 };
 
-static const struct dvb_usb_device_description d632 = {
-	"TeVii S632 USB",
-	{&dw2102_table[TEVII_S632], NULL},
-	{NULL},
+static struct dvb_usb_device_properties p7500_properties = {
+	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
+	.usb_ctrl = DEVICE_SPECIFIC,
+	.size_of_priv = sizeof(struct dw2102_state),
+	.firmware = P7500_FIRMWARE,
+	.no_reconnect = 1,
+
+	.i2c_algo = &s6x0_i2c_algo,
+	.rc.core = {
+		.rc_interval = 150,
+		.rc_codes = RC_MAP_TBS_NEC,
+		.module_name = "dw2102",
+		.allowed_protos   = RC_PROTO_BIT_NEC,
+		.rc_query = prof_rc_query,
+	},
+
+	.generic_bulk_ctrl_endpoint = 0x81,
+	.num_adapters = 1,
+	.download_firmware = dw2102_load_firmware,
+	.read_mac_address = s6x0_read_mac_address,
+	.adapter = {
+		{
+			.num_frontends = 1,
+			.fe = {{
+				.frontend_attach = prof_7500_frontend_attach,
+				.stream = {
+					.type = USB_BULK,
+					.count = 8,
+					.endpoint = 0x82,
+					.u = {
+						.bulk = {
+							.buffersize = 4096,
+						}
+					}
+				},
+			} },
+		}
+	},
+	.num_device_descs = 1,
+	.devices = {
+		{"Prof 7500 USB DVB-S2",
+			{&dw2102_table[PROF_7500], NULL},
+			{NULL},
+		},
+	}
 };
 
 static struct dvb_usb_device_properties su3000_properties = {
@@ -2209,6 +2366,59 @@
 	}
 };
 
+static struct dvb_usb_device_properties s421_properties = {
+	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
+	.usb_ctrl = DEVICE_SPECIFIC,
+	.size_of_priv = sizeof(struct dw2102_state),
+	.power_ctrl = su3000_power_ctrl,
+	.num_adapters = 1,
+	.identify_state	= su3000_identify_state,
+	.i2c_algo = &su3000_i2c_algo,
+
+	.rc.core = {
+		.rc_interval = 150,
+		.rc_codes = RC_MAP_SU3000,
+		.module_name = "dw2102",
+		.allowed_protos   = RC_PROTO_BIT_RC5,
+		.rc_query = su3000_rc_query,
+	},
+
+	.read_mac_address = su3000_read_mac_address,
+
+	.generic_bulk_ctrl_endpoint = 0x01,
+
+	.adapter = {
+		{
+		.num_frontends = 1,
+		.fe = {{
+			.streaming_ctrl   = su3000_streaming_ctrl,
+			.frontend_attach  = m88rs2000_frontend_attach,
+			.stream = {
+				.type = USB_BULK,
+				.count = 8,
+				.endpoint = 0x82,
+				.u = {
+					.bulk = {
+						.buffersize = 4096,
+					}
+				}
+			}
+		} },
+		}
+	},
+	.num_device_descs = 2,
+	.devices = {
+		{ "TeVii S421 PCI",
+			{ &dw2102_table[TEVII_S421], NULL },
+			{ NULL },
+		},
+		{ "TeVii S632 USB",
+			{ &dw2102_table[TEVII_S632], NULL },
+			{ NULL },
+		},
+	}
+};
+
 static struct dvb_usb_device_properties t220_properties = {
 	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
 	.usb_ctrl = DEVICE_SPECIFIC,
@@ -2326,101 +2536,33 @@
 static int dw2102_probe(struct usb_interface *intf,
 		const struct usb_device_id *id)
 {
-	int retval = -ENOMEM;
-	struct dvb_usb_device_properties *p1100;
-	struct dvb_usb_device_properties *s660;
-	struct dvb_usb_device_properties *p7500;
-	struct dvb_usb_device_properties *s421;
-
-	p1100 = kmemdup(&s6x0_properties,
-			sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
-	if (!p1100)
-		goto err0;
-
-	/* copy default structure */
-	/* fill only different fields */
-	p1100->firmware = P1100_FIRMWARE;
-	p1100->devices[0] = d1100;
-	p1100->rc.core.rc_query = prof_rc_query;
-	p1100->rc.core.rc_codes = RC_MAP_TBS_NEC;
-	p1100->adapter->fe[0].frontend_attach = stv0288_frontend_attach;
-
-	s660 = kmemdup(&s6x0_properties,
-		       sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
-	if (!s660)
-		goto err1;
-
-	s660->firmware = S660_FIRMWARE;
-	s660->num_device_descs = 3;
-	s660->devices[0] = d660;
-	s660->devices[1] = d480_1;
-	s660->devices[2] = d480_2;
-	s660->adapter->fe[0].frontend_attach = ds3000_frontend_attach;
-
-	p7500 = kmemdup(&s6x0_properties,
-			sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
-	if (!p7500)
-		goto err2;
-
-	p7500->firmware = P7500_FIRMWARE;
-	p7500->devices[0] = d7500;
-	p7500->rc.core.rc_query = prof_rc_query;
-	p7500->rc.core.rc_codes = RC_MAP_TBS_NEC;
-	p7500->adapter->fe[0].frontend_attach = prof_7500_frontend_attach;
-
-
-	s421 = kmemdup(&su3000_properties,
-		       sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
-	if (!s421)
-		goto err3;
-
-	s421->num_device_descs = 2;
-	s421->devices[0] = d421;
-	s421->devices[1] = d632;
-	s421->adapter->fe[0].frontend_attach = m88rs2000_frontend_attach;
-
-	if (0 == dvb_usb_device_init(intf, &dw2102_properties,
-			THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, &dw2104_properties,
-			THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, &dw3101_properties,
-			THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, &s6x0_properties,
-			THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, p1100,
-			THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, s660,
-			THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, p7500,
-			THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, s421,
-			THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, &su3000_properties,
-			 THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, &t220_properties,
-			 THIS_MODULE, NULL, adapter_nr) ||
-	    0 == dvb_usb_device_init(intf, &tt_s2_4600_properties,
-			 THIS_MODULE, NULL, adapter_nr)) {
-
-		/* clean up copied properties */
-		kfree(s421);
-		kfree(p7500);
-		kfree(s660);
-		kfree(p1100);
+	if (!(dvb_usb_device_init(intf, &dw2102_properties,
+			          THIS_MODULE, NULL, adapter_nr) &&
+	      dvb_usb_device_init(intf, &dw2104_properties,
+				  THIS_MODULE, NULL, adapter_nr) &&
+	      dvb_usb_device_init(intf, &dw3101_properties,
+			          THIS_MODULE, NULL, adapter_nr) &&
+	      dvb_usb_device_init(intf, &s6x0_properties,
+			          THIS_MODULE, NULL, adapter_nr) &&
+	      dvb_usb_device_init(intf, &p1100_properties,
+			          THIS_MODULE, NULL, adapter_nr) &&
+	      dvb_usb_device_init(intf, &s660_properties,
+				  THIS_MODULE, NULL, adapter_nr) &&
+	      dvb_usb_device_init(intf, &p7500_properties,
+				  THIS_MODULE, NULL, adapter_nr) &&
+	      dvb_usb_device_init(intf, &s421_properties,
+				  THIS_MODULE, NULL, adapter_nr) &&
+	      dvb_usb_device_init(intf, &su3000_properties,
+				  THIS_MODULE, NULL, adapter_nr) &&
+	      dvb_usb_device_init(intf, &t220_properties,
+				  THIS_MODULE, NULL, adapter_nr) &&
+	      dvb_usb_device_init(intf, &tt_s2_4600_properties,
+				  THIS_MODULE, NULL, adapter_nr))) {
 
 		return 0;
 	}
 
-	retval = -ENODEV;
-	kfree(s421);
-err3:
-	kfree(p7500);
-err2:
-	kfree(s660);
-err1:
-	kfree(p1100);
-err0:
-	return retval;
+	return -ENODEV;
 }
 
 static void dw2102_disconnect(struct usb_interface *intf)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/dvb-usb/gp8psk.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/dvb-usb/gp8psk.c
@@ -182,7 +182,7 @@
 
 static int gp8psk_power_ctrl(struct dvb_usb_device *d, int onoff)
 {
-	u8 status, buf;
+	u8 status = 0, buf;
 	int gp_product_id = le16_to_cpu(d->udev->descriptor.idProduct);
 
 	if (onoff) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/dvb-usb/m920x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/dvb-usb/m920x.c
@@ -274,6 +274,12 @@
 			/* Should check for ack here, if we knew how. */
 		}
 		if (msg[i].flags & I2C_M_RD) {
+			char *read = kmalloc(1, GFP_KERNEL);
+			if (!read) {
+				ret = -ENOMEM;
+				goto unlock;
+			}
+
 			for (j = 0; j < msg[i].len; j++) {
 				/* Last byte of transaction?
 				 * Send STOP, otherwise send ACK. */
@@ -281,9 +287,14 @@
 
 				if ((ret = m920x_read(d->udev, M9206_I2C, 0x0,
 						      0x20 | stop,
-						      &msg[i].buf[j], 1)) != 0)
+						      read, 1)) != 0) {
+					kfree(read);
 					goto unlock;
+				}
+				msg[i].buf[j] = read[0];
 			}
+
+			kfree(read);
 		} else {
 			for (j = 0; j < msg[i].len; j++) {
 				/* Last byte of transaction? Then send STOP. */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/dvb-usb/nova-t-usb2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/dvb-usb/nova-t-usb2.c
@@ -130,7 +130,7 @@
 
 static int nova_t_read_mac_address (struct dvb_usb_device *d, u8 mac[6])
 {
-	int i;
+	int i, ret;
 	u8 b;
 
 	mac[0] = 0x00;
@@ -139,7 +139,9 @@
 
 	/* this is a complete guess, but works for my box */
 	for (i = 136; i < 139; i++) {
-		dibusb_read_eeprom_byte(d,i, &b);
+		ret = dibusb_read_eeprom_byte(d, i, &b);
+		if (ret)
+			return ret;
 
 		mac[5 - (i - 136)] = b;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/dvb-usb/vp702x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/dvb-usb/vp702x.c
@@ -291,16 +291,22 @@
 static int vp702x_read_mac_addr(struct dvb_usb_device *d,u8 mac[6])
 {
 	u8 i, *buf;
+	int ret;
 	struct vp702x_device_state *st = d->priv;
 
 	mutex_lock(&st->buf_mutex);
 	buf = st->buf;
-	for (i = 6; i < 12; i++)
-		vp702x_usb_in_op(d, READ_EEPROM_REQ, i, 1, &buf[i - 6], 1);
+	for (i = 6; i < 12; i++) {
+		ret = vp702x_usb_in_op(d, READ_EEPROM_REQ, i, 1,
+				       &buf[i - 6], 1);
+		if (ret < 0)
+			goto err;
+	}
 
 	memcpy(mac, buf, 6);
+err:
 	mutex_unlock(&st->buf_mutex);
-	return 0;
+	return ret;
 }
 
 static int vp702x_frontend_attach(struct dvb_usb_adapter *adap)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/dvb-usb/vp7045.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/dvb-usb/vp7045.c
@@ -96,10 +96,14 @@
 
 static int vp7045_rc_query(struct dvb_usb_device *d)
 {
+	int ret;
 	u8 key;
-	vp7045_usb_op(d,RC_VAL_READ,NULL,0,&key,1,20);
 
-	deb_rc("remote query key: %x %d\n",key,key);
+	ret = vp7045_usb_op(d, RC_VAL_READ, NULL, 0, &key, 1, 20);
+	if (ret)
+		return ret;
+
+	deb_rc("remote query key: %x\n", key);
 
 	if (key != 0x44) {
 		/*
@@ -115,15 +119,18 @@
 
 static int vp7045_read_eeprom(struct dvb_usb_device *d,u8 *buf, int len, int offset)
 {
-	int i = 0;
-	u8 v,br[2];
+	int i, ret;
+	u8 v, br[2];
 	for (i=0; i < len; i++) {
 		v = offset + i;
-		vp7045_usb_op(d,GET_EE_VALUE,&v,1,br,2,5);
+		ret = vp7045_usb_op(d, GET_EE_VALUE, &v, 1, br, 2, 5);
+		if (ret)
+			return ret;
+
 		buf[i] = br[1];
 	}
-	deb_info("VP7045 EEPROM read (offs: %d, len: %d) : ",offset, i);
-	debug_dump(buf,i,deb_info);
+	deb_info("VP7045 EEPROM read (offs: %d, len: %d) : ", offset, i);
+	debug_dump(buf, i, deb_info);
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/em28xx/em28xx-cards.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/em28xx/em28xx-cards.c
@@ -3515,8 +3515,10 @@
 
 	if (dev->is_audio_only) {
 		retval = em28xx_audio_setup(dev);
-		if (retval)
-			return -ENODEV;
+		if (retval) {
+			retval = -ENODEV;
+			goto err_deinit_media;
+		}
 		em28xx_init_extension(dev);
 
 		return 0;
@@ -3535,7 +3537,7 @@
 		dev_err(&dev->intf->dev,
 			"%s: em28xx_i2c_register bus 0 - error [%d]!\n",
 		       __func__, retval);
-		return retval;
+		goto err_deinit_media;
 	}
 
 	/* register i2c bus 1 */
@@ -3551,9 +3553,7 @@
 				"%s: em28xx_i2c_register bus 1 - error [%d]!\n",
 				__func__, retval);
 
-			em28xx_i2c_unregister(dev, 0);
-
-			return retval;
+			goto err_unreg_i2c;
 		}
 	}
 
@@ -3561,6 +3561,12 @@
 	em28xx_card_setup(dev);
 
 	return 0;
+
+err_unreg_i2c:
+	em28xx_i2c_unregister(dev, 0);
+err_deinit_media:
+	em28xx_unregister_media_device(dev);
+	return retval;
 }
 
 static int em28xx_duplicate_dev(struct em28xx *dev)
@@ -3815,6 +3821,8 @@
 		goto err_free;
 	}
 
+	kref_init(&dev->ref);
+
 	dev->devno = nr;
 	dev->model = id->driver_info;
 	dev->alt   = -1;
@@ -3915,6 +3923,8 @@
 	}
 
 	if (dev->board.has_dual_ts && em28xx_duplicate_dev(dev) == 0) {
+		kref_init(&dev->dev_next->ref);
+
 		dev->dev_next->ts = SECONDARY_TS;
 		dev->dev_next->alt   = -1;
 		dev->dev_next->is_audio_only = has_vendor_audio &&
@@ -3969,12 +3979,8 @@
 			em28xx_write_reg(dev, 0x0b, 0x82);
 			mdelay(100);
 		}
-
-		kref_init(&dev->dev_next->ref);
 	}
 
-	kref_init(&dev->ref);
-
 	request_modules(dev);
 
 	/*
@@ -3983,6 +3989,10 @@
 	 * topology will likely change after the load of the em28xx subdrivers.
 	 */
 #ifdef CONFIG_MEDIA_CONTROLLER
+	/*
+	 * No need to check the return value, the device will still be
+	 * usable without media controller API.
+	 */
 	retval = media_device_register(dev->media_dev);
 #endif
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/em28xx/em28xx-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/em28xx/em28xx-core.c
@@ -89,7 +89,7 @@
 	mutex_lock(&dev->ctrl_urb_lock);
 	ret = usb_control_msg(udev, pipe, req,
 			      USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			      0x0000, reg, dev->urb_buf, len, HZ);
+			      0x0000, reg, dev->urb_buf, len, 1000);
 	if (ret < 0) {
 		em28xx_regdbg("(pipe 0x%08x): IN:  %02x %02x %02x %02x %02x %02x %02x %02x  failed with error %i\n",
 			      pipe,
@@ -158,7 +158,7 @@
 	memcpy(dev->urb_buf, buf, len);
 	ret = usb_control_msg(udev, pipe, req,
 			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			      0x0000, reg, dev->urb_buf, len, HZ);
+			      0x0000, reg, dev->urb_buf, len, 1000);
 	mutex_unlock(&dev->ctrl_urb_lock);
 
 	if (ret < 0) {
@@ -956,14 +956,10 @@
 
 		usb_bufs->buf[i] = kzalloc(sb_size, GFP_KERNEL);
 		if (!usb_bufs->buf[i]) {
-			em28xx_uninit_usb_xfer(dev, mode);
-
 			for (i--; i >= 0; i--)
 				kfree(usb_bufs->buf[i]);
 
-			kfree(usb_bufs->buf);
-			usb_bufs->buf = NULL;
-
+			em28xx_uninit_usb_xfer(dev, mode);
 			return -ENOMEM;
 		}
 
@@ -1156,8 +1152,9 @@
 	dev_info(&dev->intf->dev, "Suspending extensions\n");
 	mutex_lock(&em28xx_devlist_mutex);
 	list_for_each_entry(ops, &em28xx_extension_devlist, next) {
-		if (ops->suspend)
-			ops->suspend(dev);
+		if (!ops->suspend)
+			continue;
+		ops->suspend(dev);
 		if (dev->dev_next)
 			ops->suspend(dev->dev_next);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/em28xx/em28xx-dvb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/em28xx/em28xx-dvb.c
@@ -1924,6 +1924,7 @@
 	return result;
 
 out_free:
+	em28xx_uninit_usb_xfer(dev, EM28XX_DIGITAL_MODE);
 	kfree(dvb);
 	dev->dvb = NULL;
 	goto ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/em28xx/em28xx-input.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/em28xx/em28xx-input.c
@@ -720,7 +720,8 @@
 			dev->board.has_ir_i2c = 0;
 			dev_warn(&dev->intf->dev,
 				 "No i2c IR remote control device found.\n");
-			return -ENODEV;
+			err = -ENODEV;
+			goto ref_put;
 		}
 	}
 
@@ -735,7 +736,7 @@
 
 	ir = kzalloc(sizeof(*ir), GFP_KERNEL);
 	if (!ir)
-		return -ENOMEM;
+		goto ref_put;
 	rc = rc_allocate_device(RC_DRIVER_SCANCODE);
 	if (!rc)
 		goto error;
@@ -839,6 +840,8 @@
 	dev->ir = NULL;
 	rc_free_device(rc);
 	kfree(ir);
+ref_put:
+	em28xx_shutdown_buttons(dev);
 	return err;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/go7007/go7007-driver.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/go7007/go7007-driver.c
@@ -80,7 +80,7 @@
 	const struct firmware *fw_entry;
 	char fw_name[] = "go7007/go7007fw.bin";
 	void *bounce;
-	int fw_len, rv = 0;
+	int fw_len;
 	u16 intr_val, intr_data;
 
 	if (go->boot_fw == NULL) {
@@ -109,9 +109,11 @@
 	    go7007_read_interrupt(go, &intr_val, &intr_data) < 0 ||
 			(intr_val & ~0x1) != 0x5a5a) {
 		v4l2_err(go, "error transferring firmware\n");
-		rv = -1;
+		kfree(go->boot_fw);
+		go->boot_fw = NULL;
+		return -1;
 	}
-	return rv;
+	return 0;
 }
 
 MODULE_FIRMWARE("go7007/go7007fw.bin");
@@ -691,49 +693,23 @@
 						struct device *dev)
 {
 	struct go7007 *go;
-	int i;
 
 	go = kzalloc(sizeof(struct go7007), GFP_KERNEL);
 	if (go == NULL)
 		return NULL;
 	go->dev = dev;
 	go->board_info = board;
-	go->board_id = 0;
 	go->tuner_type = -1;
-	go->channel_number = 0;
-	go->name[0] = 0;
 	mutex_init(&go->hw_lock);
 	init_waitqueue_head(&go->frame_waitq);
 	spin_lock_init(&go->spinlock);
 	go->status = STATUS_INIT;
-	memset(&go->i2c_adapter, 0, sizeof(go->i2c_adapter));
-	go->i2c_adapter_online = 0;
-	go->interrupt_available = 0;
 	init_waitqueue_head(&go->interrupt_waitq);
-	go->input = 0;
 	go7007_update_board(go);
-	go->encoder_h_halve = 0;
-	go->encoder_v_halve = 0;
-	go->encoder_subsample = 0;
 	go->format = V4L2_PIX_FMT_MJPEG;
 	go->bitrate = 1500000;
 	go->fps_scale = 1;
-	go->pali = 0;
 	go->aspect_ratio = GO7007_RATIO_1_1;
-	go->gop_size = 0;
-	go->ipb = 0;
-	go->closed_gop = 0;
-	go->repeat_seqhead = 0;
-	go->seq_header_enable = 0;
-	go->gop_header_enable = 0;
-	go->dvd_mode = 0;
-	go->interlace_coding = 0;
-	for (i = 0; i < 4; ++i)
-		go->modet[i].enable = 0;
-	for (i = 0; i < 1624; ++i)
-		go->modet_map[i] = 0;
-	go->audio_deliver = NULL;
-	go->audio_enabled = 0;
 
 	return go;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/go7007/go7007-i2c.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/go7007/go7007-i2c.c
@@ -165,8 +165,6 @@
 		} else if (msgs[i].len == 3) {
 			if (msgs[i].flags & I2C_M_RD)
 				return -EIO;
-			if (msgs[i].len != 3)
-				return -EIO;
 			if (go7007_i2c_xfer(go, msgs[i].addr, 0,
 					(msgs[i].buf[0] << 8) | msgs[i].buf[1],
 					0x01, &msgs[i].buf[2]) < 0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/go7007/go7007-usb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/go7007/go7007-usb.c
@@ -1044,6 +1044,7 @@
 	struct go7007_usb *usb;
 	const struct go7007_usb_board *board;
 	struct usb_device *usbdev = interface_to_usbdev(intf);
+	struct usb_host_endpoint *ep;
 	unsigned num_i2c_devs;
 	char *name;
 	int video_pipe, i, v_urb_len;
@@ -1140,7 +1141,8 @@
 	if (usb->intr_urb->transfer_buffer == NULL)
 		goto allocfail;
 
-	if (go->board_id == GO7007_BOARDID_SENSORAY_2250)
+	ep = usb->usbdev->ep_in[4];
+	if (usb_endpoint_type(&ep->desc) == USB_ENDPOINT_XFER_BULK)
 		usb_fill_bulk_urb(usb->intr_urb, usb->usbdev,
 			usb_rcvbulkpipe(usb->usbdev, 4),
 			usb->intr_urb->transfer_buffer, 2*sizeof(u16),
@@ -1196,7 +1198,9 @@
 				u16 channel;
 
 				/* read channel number from GPIO[1:0] */
-				go7007_read_addr(go, 0x3c81, &channel);
+				if (go7007_read_addr(go, 0x3c81, &channel))
+					goto allocfail;
+
 				channel &= 0x3;
 				go->board_id = GO7007_BOARDID_ADLINK_MPG24;
 				usb->board = board = &board_adlink_mpg24;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/go7007/s2250-board.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/go7007/s2250-board.c
@@ -504,6 +504,7 @@
 	u8 *data;
 	struct go7007 *go = i2c_get_adapdata(adapter);
 	struct go7007_usb *usb = go->hpi_context;
+	int err = -EIO;
 
 	audio = i2c_new_dummy_device(adapter, TLV320_ADDRESS >> 1);
 	if (IS_ERR(audio))
@@ -532,11 +533,8 @@
 		V4L2_CID_HUE, -512, 511, 1, 0);
 	sd->ctrl_handler = &state->hdl;
 	if (state->hdl.error) {
-		int err = state->hdl.error;
-
-		v4l2_ctrl_handler_free(&state->hdl);
-		kfree(state);
-		return err;
+		err = state->hdl.error;
+		goto fail;
 	}
 
 	state->std = V4L2_STD_NTSC;
@@ -600,7 +598,7 @@
 	i2c_unregister_device(audio);
 	v4l2_ctrl_handler_free(&state->hdl);
 	kfree(state);
-	return -EIO;
+	return err;
 }
 
 static int s2250_remove(struct i2c_client *client)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/go7007/snd-go7007.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/go7007/snd-go7007.c
@@ -236,22 +236,18 @@
 	gosnd->capturing = 0;
 	ret = snd_card_new(go->dev, index[dev], id[dev], THIS_MODULE, 0,
 			   &gosnd->card);
-	if (ret < 0) {
-		kfree(gosnd);
-		return ret;
-	}
+	if (ret < 0)
+		goto free_snd;
+
 	ret = snd_device_new(gosnd->card, SNDRV_DEV_LOWLEVEL, go,
 			&go7007_snd_device_ops);
-	if (ret < 0) {
-		kfree(gosnd);
-		return ret;
-	}
+	if (ret < 0)
+		goto free_card;
+
 	ret = snd_pcm_new(gosnd->card, "go7007", 0, 0, 1, &gosnd->pcm);
-	if (ret < 0) {
-		snd_card_free(gosnd->card);
-		kfree(gosnd);
-		return ret;
-	}
+	if (ret < 0)
+		goto free_card;
+
 	strscpy(gosnd->card->driver, "go7007", sizeof(gosnd->card->driver));
 	strscpy(gosnd->card->shortname, go->name, sizeof(gosnd->card->shortname));
 	strscpy(gosnd->card->longname, gosnd->card->shortname,
@@ -262,11 +258,8 @@
 			&go7007_snd_capture_ops);
 
 	ret = snd_card_register(gosnd->card);
-	if (ret < 0) {
-		snd_card_free(gosnd->card);
-		kfree(gosnd);
-		return ret;
-	}
+	if (ret < 0)
+		goto free_card;
 
 	gosnd->substream = NULL;
 	go->snd_context = gosnd;
@@ -274,6 +267,12 @@
 	++dev;
 
 	return 0;
+
+free_card:
+	snd_card_free(gosnd->card);
+free_snd:
+	kfree(gosnd);
+	return ret;
 }
 EXPORT_SYMBOL(go7007_snd_init);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/gspca/cpia1.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/gspca/cpia1.c
@@ -18,6 +18,7 @@
 
 #include <linux/input.h>
 #include <linux/sched/signal.h>
+#include <linux/bitops.h>
 
 #include "gspca.h"
 
@@ -1027,6 +1028,8 @@
 			sd->params.exposure.expMode = 2;
 			sd->exposure_status = EXPOSURE_NORMAL;
 		}
+		if (sd->params.exposure.gain >= BITS_PER_TYPE(currentexp))
+			return -EINVAL;
 		currentexp = currentexp << sd->params.exposure.gain;
 		sd->params.exposure.gain = 0;
 		/* round down current exposure to nearest value */
@@ -1424,7 +1427,6 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	struct cam *cam;
-	int ret;
 
 	sd->mainsFreq = FREQ_DEF == V4L2_CID_POWER_LINE_FREQUENCY_60HZ;
 	reset_camera_params(gspca_dev);
@@ -1436,10 +1438,7 @@
 	cam->cam_mode = mode;
 	cam->nmodes = ARRAY_SIZE(mode);
 
-	ret = goto_low_power(gspca_dev);
-	if (ret)
-		gspca_err(gspca_dev, "Cannot go to low power mode: %d\n",
-			  ret);
+	goto_low_power(gspca_dev);
 	/* Check the firmware version. */
 	sd->params.version.firmwareVersion = 0;
 	get_version_information(gspca_dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/gspca/gl860/gl860.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/gspca/gl860/gl860.c
@@ -561,8 +561,8 @@
 					len, 400 + 200 * (len > 1));
 			memcpy(pdata, gspca_dev->usb_buf, len);
 		} else {
-			r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
-					req, pref, val, index, NULL, len, 400);
+			gspca_err(gspca_dev, "zero-length read request\n");
+			r = -EINVAL;
 		}
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/gspca/gspca.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/gspca/gspca.c
@@ -1461,7 +1461,7 @@
 		pr_err("couldn't kzalloc gspca struct\n");
 		return -ENOMEM;
 	}
-	gspca_dev->usb_buf = kmalloc(USB_BUF_SZ, GFP_KERNEL);
+	gspca_dev->usb_buf = kzalloc(USB_BUF_SZ, GFP_KERNEL);
 	if (!gspca_dev->usb_buf) {
 		pr_err("out of memory\n");
 		ret = -ENOMEM;
@@ -1575,6 +1575,9 @@
 		input_unregister_device(gspca_dev->input_dev);
 #endif
 	v4l2_ctrl_handler_free(gspca_dev->vdev.ctrl_handler);
+	v4l2_device_unregister(&gspca_dev->v4l2_dev);
+	if (sd_desc->probe_error)
+		sd_desc->probe_error(gspca_dev);
 	kfree(gspca_dev->usb_buf);
 	kfree(gspca_dev);
 	return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/gspca/gspca.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/gspca/gspca.h
@@ -105,6 +105,7 @@
 	cam_cf_op config;	/* called on probe */
 	cam_op init;		/* called on probe and resume */
 	cam_op init_controls;	/* called on probe */
+	cam_v_op probe_error;	/* called if probe failed, do cleanup here */
 	cam_op start;		/* called on stream on after URBs creation */
 	cam_pkt_op pkt_scan;
 /* optional operations */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/gspca/m5602/m5602_mt9m111.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/gspca/m5602/m5602_mt9m111.c
@@ -195,7 +195,7 @@
 int mt9m111_probe(struct sd *sd)
 {
 	u8 data[2] = {0x00, 0x00};
-	int i, rc = 0;
+	int i, err;
 	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 
 	if (force_sensor) {
@@ -213,18 +213,18 @@
 	/* Do the preinit */
 	for (i = 0; i < ARRAY_SIZE(preinit_mt9m111); i++) {
 		if (preinit_mt9m111[i][0] == BRIDGE) {
-			rc |= m5602_write_bridge(sd,
-				preinit_mt9m111[i][1],
-				preinit_mt9m111[i][2]);
+			err = m5602_write_bridge(sd,
+					preinit_mt9m111[i][1],
+					preinit_mt9m111[i][2]);
 		} else {
 			data[0] = preinit_mt9m111[i][2];
 			data[1] = preinit_mt9m111[i][3];
-			rc |= m5602_write_sensor(sd,
-				preinit_mt9m111[i][1], data, 2);
+			err = m5602_write_sensor(sd,
+					preinit_mt9m111[i][1], data, 2);
 		}
+		if (err < 0)
+			return err;
 	}
-	if (rc < 0)
-		return rc;
 
 	if (m5602_read_sensor(sd, MT9M111_SC_CHIPVER, data, 2))
 		return -ENODEV;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/gspca/m5602/m5602_po1030.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/gspca/m5602/m5602_po1030.c
@@ -154,8 +154,8 @@
 
 int po1030_probe(struct sd *sd)
 {
-	int rc = 0;
 	u8 dev_id_h = 0, i;
+	int err;
 	struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 
 	if (force_sensor) {
@@ -174,14 +174,14 @@
 	for (i = 0; i < ARRAY_SIZE(preinit_po1030); i++) {
 		u8 data = preinit_po1030[i][2];
 		if (preinit_po1030[i][0] == SENSOR)
-			rc |= m5602_write_sensor(sd,
-				preinit_po1030[i][1], &data, 1);
+			err = m5602_write_sensor(sd, preinit_po1030[i][1],
+						 &data, 1);
 		else
-			rc |= m5602_write_bridge(sd, preinit_po1030[i][1],
-						data);
+			err = m5602_write_bridge(sd, preinit_po1030[i][1],
+						 data);
+		if (err < 0)
+			return err;
 	}
-	if (rc < 0)
-		return rc;
 
 	if (m5602_read_sensor(sd, PO1030_DEVID_H, &dev_id_h, 1))
 		return -ENODEV;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/gspca/ov519.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/gspca/ov519.c
@@ -3477,6 +3477,11 @@
 		return;
 	}
 
+	if (alt->desc.bNumEndpoints < 1) {
+		sd->gspca_dev.usb_err = -ENODEV;
+		return;
+	}
+
 	packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
 	reg_w(sd, R51x_FIFO_PSIZE, packet_size >> 5);
 
@@ -3603,6 +3608,11 @@
 		return;
 	}
 
+	if (alt->desc.bNumEndpoints < 1) {
+		sd->gspca_dev.usb_err = -ENODEV;
+		return;
+	}
+
 	packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
 	ov518_reg_w32(sd, R51x_FIFO_PSIZE, packet_size & ~7, 2);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/gspca/ov534.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/gspca/ov534.c
@@ -847,7 +847,7 @@
 		r = rate_1;
 		i = ARRAY_SIZE(rate_1);
 	}
-	while (--i > 0) {
+	while (--i >= 0) {
 		if (sd->frame_rate >= r->fps)
 			break;
 		r++;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/gspca/sq905.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/gspca/sq905.c
@@ -116,7 +116,7 @@
 	}
 
 	ret = usb_control_msg(gspca_dev->dev,
-			      usb_sndctrlpipe(gspca_dev->dev, 0),
+			      usb_rcvctrlpipe(gspca_dev->dev, 0),
 			      USB_REQ_SYNCH_FRAME,                /* request */
 			      USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			      SQ905_PING, 0, gspca_dev->usb_buf, 1,
@@ -158,7 +158,7 @@
 sq905_read_data(struct gspca_dev *gspca_dev, u8 *data, int size, int need_lock)
 {
 	int ret;
-	int act_len;
+	int act_len = 0;
 
 	gspca_dev->usb_buf[0] = '\0';
 	if (need_lock)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/gspca/stv06xx/stv06xx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/gspca/stv06xx/stv06xx.c
@@ -282,6 +282,9 @@
 		return -EIO;
 	}
 
+	if (alt->desc.bNumEndpoints < 1)
+		return -ENODEV;
+
 	packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
 	err = stv06xx_write_bridge(sd, STV_ISO_SIZE_L, packet_size);
 	if (err < 0)
@@ -306,11 +309,21 @@
 
 static int stv06xx_isoc_init(struct gspca_dev *gspca_dev)
 {
+	struct usb_interface_cache *intfc;
 	struct usb_host_interface *alt;
 	struct sd *sd = (struct sd *) gspca_dev;
 
+	intfc = gspca_dev->dev->actconfig->intf_cache[0];
+
+	if (intfc->num_altsetting < 2)
+		return -ENODEV;
+
+	alt = &intfc->altsetting[1];
+
+	if (alt->desc.bNumEndpoints < 1)
+		return -ENODEV;
+
 	/* Start isoc bandwidth "negotiation" at max isoc bandwidth */
-	alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
 	alt->endpoint[0].desc.wMaxPacketSize =
 		cpu_to_le16(sd->sensor->max_packet_size[gspca_dev->curr_mode]);
 
@@ -323,6 +336,10 @@
 	struct usb_host_interface *alt;
 	struct sd *sd = (struct sd *) gspca_dev;
 
+	/*
+	 * Existence of altsetting and endpoint was verified in
+	 * stv06xx_isoc_init()
+	 */
 	alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
 	packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
 	min_packet_size = sd->sensor->min_packet_size[gspca_dev->curr_mode];
@@ -512,12 +529,21 @@
 static int stv06xx_config(struct gspca_dev *gspca_dev,
 			  const struct usb_device_id *id);
 
+static void stv06xx_probe_error(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *)gspca_dev;
+
+	kfree(sd->sensor_priv);
+	sd->sensor_priv = NULL;
+}
+
 /* sub-driver description */
 static const struct sd_desc sd_desc = {
 	.name = MODULE_NAME,
 	.config = stv06xx_config,
 	.init = stv06xx_init,
 	.init_controls = stv06xx_init_controls,
+	.probe_error = stv06xx_probe_error,
 	.start = stv06xx_start,
 	.stopN = stv06xx_stopN,
 	.pkt_scan = stv06xx_pkt_scan,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c
@@ -185,6 +185,10 @@
 	alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
 	if (!alt)
 		return -ENODEV;
+
+	if (alt->desc.bNumEndpoints < 1)
+		return -ENODEV;
+
 	packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
 
 	/* If we don't have enough bandwidth use a lower framerate */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/gspca/sunplus.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/gspca/sunplus.c
@@ -242,6 +242,10 @@
 		gspca_err(gspca_dev, "reg_r: buffer overflow\n");
 		return;
 	}
+	if (len == 0) {
+		gspca_err(gspca_dev, "reg_r: zero-length read\n");
+		return;
+	}
 	if (gspca_dev->usb_err < 0)
 		return;
 	ret = usb_control_msg(gspca_dev->dev,
@@ -250,7 +254,7 @@
 			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			0,		/* value */
 			index,
-			len ? gspca_dev->usb_buf : NULL, len,
+			gspca_dev->usb_buf, len,
 			500);
 	if (ret < 0) {
 		pr_err("reg_r err %d\n", ret);
@@ -727,7 +731,7 @@
 		case MegaImageVI:
 			reg_w_riv(gspca_dev, 0xf0, 0, 0);
 			spca504B_WaitCmdStatus(gspca_dev);
-			reg_r(gspca_dev, 0xf0, 4, 0);
+			reg_w_riv(gspca_dev, 0xf0, 4, 0);
 			spca504B_WaitCmdStatus(gspca_dev);
 			break;
 		default:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/gspca/vicam.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/gspca/vicam.c
@@ -225,7 +225,7 @@
 {
 	int ret;
 	const struct ihex_binrec *rec;
-	const struct firmware *uninitialized_var(fw);
+	const struct firmware *fw;
 	u8 *firmware_buf;
 
 	ret = request_ihex_firmware(&fw, VICAM_FIRMWARE,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/gspca/xirlink_cit.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/gspca/xirlink_cit.c
@@ -1442,6 +1442,9 @@
 		return -EIO;
 	}
 
+	if (alt->desc.bNumEndpoints < 1)
+		return -ENODEV;
+
 	return le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
 }
 
@@ -2626,6 +2629,7 @@
 
 static int sd_isoc_init(struct gspca_dev *gspca_dev)
 {
+	struct usb_interface_cache *intfc;
 	struct usb_host_interface *alt;
 	int max_packet_size;
 
@@ -2641,8 +2645,17 @@
 		break;
 	}
 
+	intfc = gspca_dev->dev->actconfig->intf_cache[0];
+
+	if (intfc->num_altsetting < 2)
+		return -ENODEV;
+
+	alt = &intfc->altsetting[1];
+
+	if (alt->desc.bNumEndpoints < 1)
+		return -ENODEV;
+
 	/* Start isoc bandwidth "negotiation" at max isoc bandwidth */
-	alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
 	alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(max_packet_size);
 
 	return 0;
@@ -2665,6 +2678,9 @@
 		break;
 	}
 
+	/*
+	 * Existence of altsetting and endpoint was verified in sd_isoc_init()
+	 */
 	alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1];
 	packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
 	if (packet_size <= min_packet_size)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/hdpvr/hdpvr-video.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/hdpvr/hdpvr-video.c
@@ -308,7 +308,6 @@
 
 	dev->status = STATUS_STREAMING;
 
-	INIT_WORK(&dev->worker, hdpvr_transmit_buffers);
 	schedule_work(&dev->worker);
 
 	v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev,
@@ -410,7 +409,7 @@
 	struct hdpvr_device *dev = video_drvdata(file);
 	struct hdpvr_buffer *buf = NULL;
 	struct urb *urb;
-	unsigned int ret = 0;
+	int ret = 0;
 	int rem, cnt;
 
 	if (*pos)
@@ -1165,6 +1164,9 @@
 	bool ac3 = dev->flags & HDPVR_FLAG_AC3_CAP;
 	int res;
 
+	// initialize dev->worker
+	INIT_WORK(&dev->worker, hdpvr_transmit_buffers);
+
 	dev->cur_std = V4L2_STD_525_60;
 	dev->width = 720;
 	dev->height = 480;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/msi2500/msi2500.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/msi2500/msi2500.c
@@ -1230,7 +1230,7 @@
 	}
 
 	dev->master = master;
-	master->bus_num = 0;
+	master->bus_num = -1;
 	master->num_chipselect = 1;
 	master->transfer_one_message = msi2500_transfer_one_message;
 	spi_master_set_devdata(master, dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/pulse8-cec/pulse8-cec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/pulse8-cec/pulse8-cec.c
@@ -116,6 +116,7 @@
 	unsigned int vers;
 	struct completion cmd_done;
 	struct work_struct work;
+	u8 work_result;
 	struct delayed_work ping_eeprom_work;
 	struct cec_msg rx_msg;
 	u8 data[DATA_SIZE];
@@ -137,8 +138,10 @@
 {
 	struct pulse8 *pulse8 =
 		container_of(work, struct pulse8, work);
+	u8 result = pulse8->work_result;
 
-	switch (pulse8->data[0] & 0x3f) {
+	pulse8->work_result = 0;
+	switch (result & 0x3f) {
 	case MSGCODE_FRAME_DATA:
 		cec_received_msg(pulse8->adap, &pulse8->rx_msg);
 		break;
@@ -172,12 +175,12 @@
 		pulse8->escape = false;
 	} else if (data == MSGEND) {
 		struct cec_msg *msg = &pulse8->rx_msg;
+		u8 msgcode = pulse8->buf[0];
 
 		if (debug)
 			dev_info(pulse8->dev, "received: %*ph\n",
 				 pulse8->idx, pulse8->buf);
-		pulse8->data[0] = pulse8->buf[0];
-		switch (pulse8->buf[0] & 0x3f) {
+		switch (msgcode & 0x3f) {
 		case MSGCODE_FRAME_START:
 			msg->len = 1;
 			msg->msg[0] = pulse8->buf[1];
@@ -186,14 +189,20 @@
 			if (msg->len == CEC_MAX_MSG_SIZE)
 				break;
 			msg->msg[msg->len++] = pulse8->buf[1];
-			if (pulse8->buf[0] & MSGCODE_FRAME_EOM)
+			if (msgcode & MSGCODE_FRAME_EOM) {
+				WARN_ON(pulse8->work_result);
+				pulse8->work_result = msgcode;
 				schedule_work(&pulse8->work);
+				break;
+			}
 			break;
 		case MSGCODE_TRANSMIT_SUCCEEDED:
 		case MSGCODE_TRANSMIT_FAILED_LINE:
 		case MSGCODE_TRANSMIT_FAILED_ACK:
 		case MSGCODE_TRANSMIT_FAILED_TIMEOUT_DATA:
 		case MSGCODE_TRANSMIT_FAILED_TIMEOUT_LINE:
+			WARN_ON(pulse8->work_result);
+			pulse8->work_result = msgcode;
 			schedule_work(&pulse8->work);
 			break;
 		case MSGCODE_HIGH_ERROR:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/pvrusb2/pvrusb2-context.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/pvrusb2/pvrusb2-context.c
@@ -90,8 +90,10 @@
 }
 
 
-static void pvr2_context_notify(struct pvr2_context *mp)
+static void pvr2_context_notify(void *ptr)
 {
+	struct pvr2_context *mp = ptr;
+
 	pvr2_context_set_notify(mp,!0);
 }
 
@@ -106,9 +108,7 @@
 		pvr2_trace(PVR2_TRACE_CTXT,
 			   "pvr2_context %p (initialize)", mp);
 		/* Finish hardware initialization */
-		if (pvr2_hdw_initialize(mp->hdw,
-					(void (*)(void *))pvr2_context_notify,
-					mp)) {
+		if (pvr2_hdw_initialize(mp->hdw, pvr2_context_notify, mp)) {
 			mp->video_stream.stream =
 				pvr2_hdw_get_video_stream(mp->hdw);
 			/* Trigger interface initialization.  By doing this
@@ -267,8 +267,9 @@
 void pvr2_context_disconnect(struct pvr2_context *mp)
 {
 	pvr2_hdw_disconnect(mp->hdw);
+	if (!pvr2_context_shutok())
+		pvr2_context_notify(mp);
 	mp->disconnect_flag = !0;
-	pvr2_context_notify(mp);
 }
 
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/pvrusb2/pvrusb2-dvb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/pvrusb2/pvrusb2-dvb.c
@@ -88,8 +88,10 @@
 	return stat;
 }
 
-static void pvr2_dvb_notify(struct pvr2_dvb_adapter *adap)
+static void pvr2_dvb_notify(void *ptr)
 {
+	struct pvr2_dvb_adapter *adap = ptr;
+
 	wake_up(&adap->buffer_wait_data);
 }
 
@@ -149,7 +151,7 @@
 	}
 
 	pvr2_stream_set_callback(pvr->video_stream.stream,
-				 (pvr2_stream_callback) pvr2_dvb_notify, adap);
+				 pvr2_dvb_notify, adap);
 
 	ret = pvr2_stream_set_buffer_count(stream, PVR2_DVB_BUFFER_COUNT);
 	if (ret < 0) return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
@@ -1468,7 +1468,7 @@
 	for (address = 0; address < fwsize; address += 0x800) {
 		memcpy(fw_ptr, fw_entry->data + address, 0x800);
 		ret += usb_control_msg(hdw->usb_dev, pipe, 0xa0, 0x40, address,
-				       0, fw_ptr, 0x800, HZ);
+				       0, fw_ptr, 0x800, 1000);
 	}
 
 	trace_firmware("Upload done, releasing device's CPU");
@@ -1606,7 +1606,7 @@
 			((u32 *)fw_ptr)[icnt] = swab32(((u32 *)fw_ptr)[icnt]);
 
 		ret |= usb_bulk_msg(hdw->usb_dev, pipe, fw_ptr,bcnt,
-				    &actual_length, HZ);
+				    &actual_length, 1000);
 		ret |= (actual_length != bcnt);
 		if (ret) break;
 		fw_done += bcnt;
@@ -2570,6 +2570,11 @@
 	} while (0);
 	mutex_unlock(&pvr2_unit_mtx);
 
+	INIT_WORK(&hdw->workpoll, pvr2_hdw_worker_poll);
+
+	if (hdw->unit_number == -1)
+		goto fail;
+
 	cnt1 = 0;
 	cnt2 = scnprintf(hdw->name+cnt1,sizeof(hdw->name)-cnt1,"pvrusb2");
 	cnt1 += cnt2;
@@ -2581,8 +2586,6 @@
 	if (cnt1 >= sizeof(hdw->name)) cnt1 = sizeof(hdw->name)-1;
 	hdw->name[cnt1] = 0;
 
-	INIT_WORK(&hdw->workpoll,pvr2_hdw_worker_poll);
-
 	pvr2_trace(PVR2_TRACE_INIT,"Driver unit number is %d, name is %s",
 		   hdw->unit_number,hdw->name);
 
@@ -2608,6 +2611,7 @@
 		del_timer_sync(&hdw->encoder_run_timer);
 		del_timer_sync(&hdw->encoder_wait_timer);
 		flush_work(&hdw->workpoll);
+		v4l2_device_unregister(&hdw->v4l2_dev);
 		usb_free_urb(hdw->ctl_read_urb);
 		usb_free_urb(hdw->ctl_write_urb);
 		kfree(hdw->ctl_read_buffer);
@@ -2677,9 +2681,8 @@
 		pvr2_stream_destroy(hdw->vid_stream);
 		hdw->vid_stream = NULL;
 	}
-	pvr2_i2c_core_done(hdw);
 	v4l2_device_unregister(&hdw->v4l2_dev);
-	pvr2_hdw_remove_usb_stuff(hdw);
+	pvr2_hdw_disconnect(hdw);
 	mutex_lock(&pvr2_unit_mtx);
 	do {
 		if ((hdw->unit_number >= 0) &&
@@ -2706,6 +2709,7 @@
 {
 	pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_disconnect(hdw=%p)",hdw);
 	LOCK_TAKE(hdw->big_lock);
+	pvr2_i2c_core_done(hdw);
 	LOCK_TAKE(hdw->ctl_lock);
 	pvr2_hdw_remove_usb_stuff(hdw);
 	LOCK_GIVE(hdw->ctl_lock);
@@ -3439,7 +3443,7 @@
 						      0xa0,0xc0,
 						      address,0,
 						      hdw->fw_buffer+address,
-						      0x800,HZ);
+						      0x800,1000);
 				if (ret < 0) break;
 			}
 
@@ -3978,7 +3982,7 @@
 	/* Write the CPUCS register on the 8051.  The lsb of the register
 	   is the reset bit; a 1 asserts reset while a 0 clears it. */
 	pipe = usb_sndctrlpipe(hdw->usb_dev, 0);
-	ret = usb_control_msg(hdw->usb_dev,pipe,0xa0,0x40,0xe600,0,da,1,HZ);
+	ret = usb_control_msg(hdw->usb_dev,pipe,0xa0,0x40,0xe600,0,da,1,1000);
 	if (ret < 0) {
 		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
 			   "cpureset_assert(%d) error=%d",val,ret);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c
@@ -898,8 +898,12 @@
 	pvr2_v4l2_dev_disassociate_parent(vp->dev_video);
 	pvr2_v4l2_dev_disassociate_parent(vp->dev_radio);
 	if (!list_empty(&vp->dev_video->devbase.fh_list) ||
-	    !list_empty(&vp->dev_radio->devbase.fh_list))
+	    (vp->dev_radio &&
+	     !list_empty(&vp->dev_radio->devbase.fh_list))) {
+		pvr2_trace(PVR2_TRACE_STRUCT,
+			   "pvr2_v4l2 internal_check exit-empty id=%p", vp);
 		return;
+	}
 	pvr2_v4l2_destroy_no_lock(vp);
 }
 
@@ -935,7 +939,8 @@
 	kfree(fhp);
 	if (vp->channel.mc_head->disconnect_flag &&
 	    list_empty(&vp->dev_video->devbase.fh_list) &&
-	    list_empty(&vp->dev_radio->devbase.fh_list)) {
+	    (!vp->dev_radio ||
+	     list_empty(&vp->dev_radio->devbase.fh_list))) {
 		pvr2_v4l2_destroy_no_lock(vp);
 	}
 	return 0;
@@ -1032,8 +1037,10 @@
 }
 
 
-static void pvr2_v4l2_notify(struct pvr2_v4l2_fh *fhp)
+static void pvr2_v4l2_notify(void *ptr)
 {
+	struct pvr2_v4l2_fh *fhp = ptr;
+
 	wake_up(&fhp->wait_data);
 }
 
@@ -1066,7 +1073,7 @@
 
 	hdw = fh->channel.mc_head->hdw;
 	sp = fh->pdi->stream->stream;
-	pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh);
+	pvr2_stream_set_callback(sp, pvr2_v4l2_notify, fh);
 	pvr2_hdw_set_stream_type(hdw,fh->pdi->config);
 	if ((ret = pvr2_hdw_set_streaming(hdw,!0)) < 0) return ret;
 	return pvr2_ioread_set_enabled(fh->rhp,!0);
@@ -1197,11 +1204,6 @@
 		dip->minor_type = pvr2_v4l_type_video;
 		nr_ptr = video_nr;
 		caps |= V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_AUDIO;
-		if (!dip->stream) {
-			pr_err(KBUILD_MODNAME
-				": Failed to set up pvrusb2 v4l video dev due to missing stream instance\n");
-			return;
-		}
 		break;
 	case VFL_TYPE_VBI:
 		dip->config = pvr2_config_vbi;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/pwc/pwc-if.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/pwc/pwc-if.c
@@ -147,16 +147,17 @@
 /***************************************************************************/
 /* Private functions */
 
-static void *pwc_alloc_urb_buffer(struct device *dev,
+static void *pwc_alloc_urb_buffer(struct usb_device *dev,
 				  size_t size, dma_addr_t *dma_handle)
 {
+	struct device *dmadev = dev->bus->sysdev;
 	void *buffer = kmalloc(size, GFP_KERNEL);
 
 	if (!buffer)
 		return NULL;
 
-	*dma_handle = dma_map_single(dev, buffer, size, DMA_FROM_DEVICE);
-	if (dma_mapping_error(dev, *dma_handle)) {
+	*dma_handle = dma_map_single(dmadev, buffer, size, DMA_FROM_DEVICE);
+	if (dma_mapping_error(dmadev, *dma_handle)) {
 		kfree(buffer);
 		return NULL;
 	}
@@ -164,12 +165,14 @@
 	return buffer;
 }
 
-static void pwc_free_urb_buffer(struct device *dev,
+static void pwc_free_urb_buffer(struct usb_device *dev,
 				size_t size,
 				void *buffer,
 				dma_addr_t dma_handle)
 {
-	dma_unmap_single(dev, dma_handle, size, DMA_FROM_DEVICE);
+	struct device *dmadev = dev->bus->sysdev;
+
+	dma_unmap_single(dmadev, dma_handle, size, DMA_FROM_DEVICE);
 	kfree(buffer);
 }
 
@@ -274,6 +277,7 @@
 static void pwc_isoc_handler(struct urb *urb)
 {
 	struct pwc_device *pdev = (struct pwc_device *)urb->context;
+	struct device *dmadev = urb->dev->bus->sysdev;
 	int i, fst, flen;
 	unsigned char *iso_buf = NULL;
 
@@ -320,7 +324,7 @@
 	/* Reset ISOC error counter. We did get here, after all. */
 	pdev->visoc_errors = 0;
 
-	dma_sync_single_for_cpu(&urb->dev->dev,
+	dma_sync_single_for_cpu(dmadev,
 				urb->transfer_dma,
 				urb->transfer_buffer_length,
 				DMA_FROM_DEVICE);
@@ -371,7 +375,7 @@
 		pdev->vlast_packet_size = flen;
 	}
 
-	dma_sync_single_for_device(&urb->dev->dev,
+	dma_sync_single_for_device(dmadev,
 				   urb->transfer_dma,
 				   urb->transfer_buffer_length,
 				   DMA_FROM_DEVICE);
@@ -453,7 +457,7 @@
 		urb->pipe = usb_rcvisocpipe(udev, pdev->vendpoint);
 		urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
 		urb->transfer_buffer_length = ISO_BUFFER_SIZE;
-		urb->transfer_buffer = pwc_alloc_urb_buffer(&udev->dev,
+		urb->transfer_buffer = pwc_alloc_urb_buffer(udev,
 							    urb->transfer_buffer_length,
 							    &urb->transfer_dma);
 		if (urb->transfer_buffer == NULL) {
@@ -516,7 +520,7 @@
 		if (urb) {
 			PWC_DEBUG_MEMORY("Freeing URB\n");
 			if (urb->transfer_buffer)
-				pwc_free_urb_buffer(&urb->dev->dev,
+				pwc_free_urb_buffer(urb->dev,
 						    urb->transfer_buffer_length,
 						    urb->transfer_buffer,
 						    urb->transfer_dma);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/s2255/s2255drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/s2255/s2255drv.c
@@ -247,7 +247,7 @@
 struct s2255_dev {
 	struct s2255_vc         vc[MAX_CHANNELS];
 	struct v4l2_device      v4l2_dev;
-	atomic_t                num_channels;
+	refcount_t		num_channels;
 	int			frames;
 	struct mutex		lock;	/* channels[].vdev.lock */
 	struct mutex		cmdlock; /* protects cmdbuf */
@@ -1552,11 +1552,11 @@
 		container_of(vdev, struct s2255_vc, vdev);
 
 	dprintk(dev, 4, "%s, chnls: %d\n", __func__,
-		atomic_read(&dev->num_channels));
+		refcount_read(&dev->num_channels));
 
 	v4l2_ctrl_handler_free(&vc->hdl);
 
-	if (atomic_dec_and_test(&dev->num_channels))
+	if (refcount_dec_and_test(&dev->num_channels))
 		s2255_destroy(dev);
 	return;
 }
@@ -1661,7 +1661,7 @@
 				"failed to register video device!\n");
 			break;
 		}
-		atomic_inc(&dev->num_channels);
+		refcount_inc(&dev->num_channels);
 		v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n",
 			  video_device_node_name(&vc->vdev));
 
@@ -1669,11 +1669,11 @@
 	pr_info("Sensoray 2255 V4L driver Revision: %s\n",
 		S2255_VERSION);
 	/* if no channels registered, return error and probe will fail*/
-	if (atomic_read(&dev->num_channels) == 0) {
+	if (refcount_read(&dev->num_channels) == 0) {
 		v4l2_device_unregister(&dev->v4l2_dev);
 		return ret;
 	}
-	if (atomic_read(&dev->num_channels) != MAX_CHANNELS)
+	if (refcount_read(&dev->num_channels) != MAX_CHANNELS)
 		pr_warn("s2255: Not all channels available.\n");
 	return 0;
 }
@@ -1884,7 +1884,7 @@
 				    USB_TYPE_VENDOR | USB_RECIP_DEVICE |
 				    USB_DIR_IN,
 				    Value, Index, buf,
-				    TransferBufferLength, HZ * 5);
+				    TransferBufferLength, USB_CTRL_SET_TIMEOUT);
 
 		if (r >= 0)
 			memcpy(TransferBuffer, buf, TransferBufferLength);
@@ -1893,7 +1893,7 @@
 		r = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
 				    Request, USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 				    Value, Index, buf,
-				    TransferBufferLength, HZ * 5);
+				    TransferBufferLength, USB_CTRL_SET_TIMEOUT);
 	}
 	kfree(buf);
 	return r;
@@ -2222,7 +2222,7 @@
 		goto errorFWDATA1;
 	}
 
-	atomic_set(&dev->num_channels, 0);
+	refcount_set(&dev->num_channels, 0);
 	dev->pid = id->idProduct;
 	dev->fw_data = kzalloc(sizeof(struct s2255_fw), GFP_KERNEL);
 	if (!dev->fw_data)
@@ -2342,12 +2342,12 @@
 {
 	struct s2255_dev *dev = to_s2255_dev(usb_get_intfdata(interface));
 	int i;
-	int channels = atomic_read(&dev->num_channels);
+	int channels = refcount_read(&dev->num_channels);
 	mutex_lock(&dev->lock);
 	v4l2_device_disconnect(&dev->v4l2_dev);
 	mutex_unlock(&dev->lock);
 	/*see comments in the uvc_driver.c usb disconnect function */
-	atomic_inc(&dev->num_channels);
+	refcount_inc(&dev->num_channels);
 	/* unregister each video device. */
 	for (i = 0; i < channels; i++)
 		video_unregister_device(&dev->vc[i].vdev);
@@ -2360,7 +2360,7 @@
 		dev->vc[i].vidstatus_ready = 1;
 		wake_up(&dev->vc[i].wait_vidstatus);
 	}
-	if (atomic_dec_and_test(&dev->num_channels))
+	if (refcount_dec_and_test(&dev->num_channels))
 		s2255_destroy(dev);
 	dev_info(&interface->dev, "%s\n", __func__);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/siano/smsusb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/siano/smsusb.c
@@ -179,6 +179,8 @@
 
 	for (i = 0; i < MAX_URBS; i++) {
 		usb_kill_urb(&dev->surbs[i].urb);
+		if (dev->surbs[i].wq.func)
+			cancel_work_sync(&dev->surbs[i].wq);
 
 		if (dev->surbs[i].cb) {
 			smscore_putbuffer(dev->coredev, dev->surbs[i].cb);
@@ -453,12 +455,7 @@
 	rc = smscore_register_device(&params, &dev->coredev, 0, mdev);
 	if (rc < 0) {
 		pr_err("smscore_register_device(...) failed, rc %d\n", rc);
-		smsusb_term_device(intf);
-#ifdef CONFIG_MEDIA_CONTROLLER_DVB
-		media_device_unregister(mdev);
-#endif
-		kfree(mdev);
-		return rc;
+		goto err_unregister_device;
 	}
 
 	smscore_set_board_id(dev->coredev, board_id);
@@ -475,8 +472,7 @@
 	rc = smsusb_start_streaming(dev);
 	if (rc < 0) {
 		pr_err("smsusb_start_streaming(...) failed\n");
-		smsusb_term_device(intf);
-		return rc;
+		goto err_unregister_device;
 	}
 
 	dev->state = SMSUSB_ACTIVE;
@@ -484,13 +480,20 @@
 	rc = smscore_start_device(dev->coredev);
 	if (rc < 0) {
 		pr_err("smscore_start_device(...) failed\n");
-		smsusb_term_device(intf);
-		return rc;
+		goto err_unregister_device;
 	}
 
 	pr_debug("device 0x%p created\n", dev);
 
 	return rc;
+
+err_unregister_device:
+	smsusb_term_device(intf);
+#ifdef CONFIG_MEDIA_CONTROLLER_DVB
+	media_device_unregister(mdev);
+#endif
+	kfree(mdev);
+	return rc;
 }
 
 static int smsusb_probe(struct usb_interface *intf,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/stk1160/stk1160-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/stk1160/stk1160-core.c
@@ -65,7 +65,7 @@
 		return -ENOMEM;
 	ret = usb_control_msg(dev->udev, pipe, 0x00,
 			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			0x00, reg, buf, sizeof(u8), HZ);
+			0x00, reg, buf, sizeof(u8), 1000);
 	if (ret < 0) {
 		stk1160_err("read failed on reg 0x%x (%d)\n",
 			reg, ret);
@@ -85,7 +85,7 @@
 
 	ret =  usb_control_msg(dev->udev, pipe, 0x01,
 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			value, reg, NULL, 0, HZ);
+			value, reg, NULL, 0, 1000);
 	if (ret < 0) {
 		stk1160_err("write failed on reg 0x%x (%d)\n",
 			reg, ret);
@@ -403,7 +403,7 @@
 	/* Here is the only place where isoc get released */
 	stk1160_uninit_isoc(dev);
 
-	stk1160_clear_queue(dev);
+	stk1160_clear_queue(dev, VB2_BUF_STATE_ERROR);
 
 	video_unregister_device(&dev->vdev);
 	v4l2_device_disconnect(&dev->v4l2_dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/stk1160/stk1160-v4l.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/stk1160/stk1160-v4l.c
@@ -258,7 +258,7 @@
 	stk1160_uninit_isoc(dev);
 out_stop_hw:
 	usb_set_interface(dev->udev, 0, 0);
-	stk1160_clear_queue(dev);
+	stk1160_clear_queue(dev, VB2_BUF_STATE_QUEUED);
 
 	mutex_unlock(&dev->v4l_lock);
 
@@ -306,7 +306,7 @@
 
 	stk1160_stop_hw(dev);
 
-	stk1160_clear_queue(dev);
+	stk1160_clear_queue(dev, VB2_BUF_STATE_ERROR);
 
 	stk1160_dbg("streaming stopped\n");
 
@@ -745,7 +745,7 @@
 /********************************************************************/
 
 /* Must be called with both v4l_lock and vb_queue_lock hold */
-void stk1160_clear_queue(struct stk1160 *dev)
+void stk1160_clear_queue(struct stk1160 *dev, enum vb2_buffer_state vb2_state)
 {
 	struct stk1160_buffer *buf;
 	unsigned long flags;
@@ -756,7 +756,7 @@
 		buf = list_first_entry(&dev->avail_bufs,
 			struct stk1160_buffer, list);
 		list_del(&buf->list);
-		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, vb2_state);
 		stk1160_dbg("buffer [%p/%d] aborted\n",
 			    buf, buf->vb.vb2_buf.index);
 	}
@@ -766,7 +766,7 @@
 		buf = dev->isoc_ctl.buf;
 		dev->isoc_ctl.buf = NULL;
 
-		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+		vb2_buffer_done(&buf->vb.vb2_buf, vb2_state);
 		stk1160_dbg("buffer [%p/%d] aborted\n",
 			    buf, buf->vb.vb2_buf.index);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/stk1160/stk1160-video.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/stk1160/stk1160-video.c
@@ -99,7 +99,7 @@
 static inline
 void stk1160_copy_video(struct stk1160 *dev, u8 *src, int len)
 {
-	int linesdone, lineoff, lencopy;
+	int linesdone, lineoff, lencopy, offset;
 	int bytesperline = dev->width * 2;
 	struct stk1160_buffer *buf = dev->isoc_ctl.buf;
 	u8 *dst = buf->mem;
@@ -107,8 +107,7 @@
 
 	/*
 	 * TODO: These stk1160_dbg are very spammy!
-	 * We should 1) check why we are getting them
-	 * and 2) add ratelimit.
+	 * We should check why we are getting them.
 	 *
 	 * UPDATE: One of the reasons (the only one?) for getting these
 	 * is incorrect standard (mismatch between expected and configured).
@@ -140,8 +139,13 @@
 	 * Check if we have enough space left in the buffer.
 	 * In that case, we force loop exit after copy.
 	 */
-	if (lencopy > buf->bytesused - buf->length) {
-		lencopy = buf->bytesused - buf->length;
+	offset = dst - (u8 *)buf->mem;
+	if (offset > buf->length) {
+		dev_warn_ratelimited(dev->dev, "out of bounds offset\n");
+		return;
+	}
+	if (lencopy > buf->length - offset) {
+		lencopy = buf->length - offset;
 		remain = lencopy;
 	}
 
@@ -151,7 +155,7 @@
 
 	/* Let the bug hunt begin! sanity checks! */
 	if (lencopy < 0) {
-		stk1160_dbg("copy skipped: negative lencopy\n");
+		printk_ratelimited(KERN_DEBUG "copy skipped: negative lencopy\n");
 		return;
 	}
 
@@ -183,8 +187,13 @@
 		 * Check if we have enough space left in the buffer.
 		 * In that case, we force loop exit after copy.
 		 */
-		if (lencopy > buf->bytesused - buf->length) {
-			lencopy = buf->bytesused - buf->length;
+		offset = dst - (u8 *)buf->mem;
+		if (offset > buf->length) {
+			dev_warn_ratelimited(dev->dev, "offset out of bounds\n");
+			return;
+		}
+		if (lencopy > buf->length - offset) {
+			lencopy = buf->length - offset;
 			remain = lencopy;
 		}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/stk1160/stk1160.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/stk1160/stk1160.h
@@ -166,7 +166,7 @@
 int stk1160_vb2_setup(struct stk1160 *dev);
 int stk1160_video_register(struct stk1160 *dev);
 void stk1160_video_unregister(struct stk1160 *dev);
-void stk1160_clear_queue(struct stk1160 *dev);
+void stk1160_clear_queue(struct stk1160 *dev, enum vb2_buffer_state vb2_state);
 
 /* Provided by stk1160-video.c */
 int stk1160_alloc_isoc(struct stk1160 *dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/stkwebcam/stk-webcam.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/stkwebcam/stk-webcam.c
@@ -1346,7 +1346,7 @@
 	if (!dev->isoc_ep) {
 		pr_err("Could not find isoc-in endpoint\n");
 		err = -ENODEV;
-		goto error;
+		goto error_put;
 	}
 	dev->vsettings.palette = V4L2_PIX_FMT_RGB565;
 	dev->vsettings.mode = MODE_VGA;
@@ -1359,10 +1359,12 @@
 
 	err = stk_register_video_device(dev);
 	if (err)
-		goto error;
+		goto error_put;
 
 	return 0;
 
+error_put:
+	usb_put_intf(interface);
 error:
 	v4l2_ctrl_handler_free(hdl);
 	v4l2_device_unregister(&dev->v4l2_dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/tm6000/tm6000-dvb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/tm6000/tm6000-dvb.c
@@ -141,6 +141,10 @@
 	if (ret < 0) {
 		printk(KERN_ERR "tm6000: error %i in %s during pipe reset\n",
 							ret, __func__);
+
+		kfree(dvb->bulk_urb->transfer_buffer);
+		usb_free_urb(dvb->bulk_urb);
+		dvb->bulk_urb = NULL;
 		return ret;
 	} else
 		printk(KERN_ERR "tm6000: pipe reset\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/tm6000/tm6000-video.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/tm6000/tm6000-video.c
@@ -461,11 +461,12 @@
 	if (dev->urb_buffer)
 		return 0;
 
-	dev->urb_buffer = kmalloc_array(num_bufs, sizeof(void *), GFP_KERNEL);
+	dev->urb_buffer = kmalloc_array(num_bufs, sizeof(*dev->urb_buffer),
+					GFP_KERNEL);
 	if (!dev->urb_buffer)
 		return -ENOMEM;
 
-	dev->urb_dma = kmalloc_array(num_bufs, sizeof(dma_addr_t *),
+	dev->urb_dma = kmalloc_array(num_bufs, sizeof(*dev->urb_dma),
 				     GFP_KERNEL);
 	if (!dev->urb_dma)
 		return -ENOMEM;
@@ -853,8 +854,7 @@
 	struct tm6000_core *dev = ((struct tm6000_fh *)priv)->dev;
 
 	strscpy(cap->driver, "tm6000", sizeof(cap->driver));
-	strscpy(cap->card, "Trident TVMaster TM5600/6000/6010",
-		sizeof(cap->card));
+	strscpy(cap->card, "Trident TM5600/6000/6010", sizeof(cap->card));
 	usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
 	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
 			    V4L2_CAP_DEVICE_CAPS;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/ttusb-dec/ttusb_dec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/ttusb-dec/ttusb_dec.c
@@ -1551,8 +1551,7 @@
 	dvb_dmx_release(&dec->demux);
 	if (dec->fe) {
 		dvb_unregister_frontend(dec->fe);
-		if (dec->fe->ops.release)
-			dec->fe->ops.release(dec->fe);
+		dvb_frontend_detach(dec->fe);
 	}
 	dvb_unregister_adapter(&dec->adapter);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/usbtv/usbtv-audio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/usbtv/usbtv-audio.c
@@ -399,7 +399,7 @@
 	cancel_work_sync(&usbtv->snd_trigger);
 
 	if (usbtv->snd && usbtv->udev) {
-		snd_card_free(usbtv->snd);
+		snd_card_free_when_closed(usbtv->snd);
 		usbtv->snd = NULL;
 	}
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/usbtv/usbtv-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/usbtv/usbtv-core.c
@@ -56,7 +56,7 @@
 
 		ret = usb_control_msg(usbtv->udev, pipe, USBTV_REQUEST_REG,
 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			value, index, NULL, 0, 0);
+			value, index, NULL, 0, USB_CTRL_GET_TIMEOUT);
 		if (ret < 0)
 			return ret;
 	}
@@ -113,7 +113,8 @@
 
 usbtv_audio_fail:
 	/* we must not free at this point */
-	usb_get_dev(usbtv->udev);
+	v4l2_device_get(&usbtv->v4l2_dev);
+	/* this will undo the v4l2_device_get() */
 	usbtv_video_free(usbtv);
 
 usbtv_video_fail:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/usbtv/usbtv-video.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/usbtv/usbtv-video.c
@@ -800,7 +800,8 @@
 		ret = usb_control_msg(usbtv->udev,
 			usb_rcvctrlpipe(usbtv->udev, 0), USBTV_CONTROL_REG,
 			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			0, USBTV_BASE + 0x0244, (void *)data, 3, 0);
+			0, USBTV_BASE + 0x0244, (void *)data, 3,
+			USB_CTRL_GET_TIMEOUT);
 		if (ret < 0)
 			goto error;
 	}
@@ -851,7 +852,7 @@
 	ret = usb_control_msg(usbtv->udev, usb_sndctrlpipe(usbtv->udev, 0),
 			USBTV_CONTROL_REG,
 			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			0, index, (void *)data, size, 0);
+			0, index, (void *)data, size, USB_CTRL_SET_TIMEOUT);
 
 error:
 	if (ret < 0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/usbvision/usbvision-video.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/usbvision/usbvision-video.c
@@ -314,6 +314,10 @@
 	if (mutex_lock_interruptible(&usbvision->v4l2_lock))
 		return -ERESTARTSYS;
 
+	if (usbvision->remove_pending) {
+		err_code = -ENODEV;
+		goto unlock;
+	}
 	if (usbvision->user) {
 		err_code = -EBUSY;
 	} else {
@@ -377,6 +381,7 @@
 static int usbvision_v4l2_close(struct file *file)
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
+	int r;
 
 	PDEBUG(DBG_IO, "close");
 
@@ -391,9 +396,10 @@
 	usbvision_scratch_free(usbvision);
 
 	usbvision->user--;
+	r = usbvision->remove_pending;
 	mutex_unlock(&usbvision->v4l2_lock);
 
-	if (usbvision->remove_pending) {
+	if (r) {
 		printk(KERN_INFO "%s: Final disconnect\n", __func__);
 		usbvision_release(usbvision);
 		return 0;
@@ -453,6 +459,9 @@
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
 
+	if (!usbvision->dev)
+		return -ENODEV;
+
 	strscpy(vc->driver, "USBVision", sizeof(vc->driver));
 	strscpy(vc->card,
 		usbvision_device_data[usbvision->dev_model].model_string,
@@ -1061,6 +1070,11 @@
 
 	if (mutex_lock_interruptible(&usbvision->v4l2_lock))
 		return -ERESTARTSYS;
+
+	if (usbvision->remove_pending) {
+		err_code = -ENODEV;
+		goto out;
+	}
 	err_code = v4l2_fh_open(file);
 	if (err_code)
 		goto out;
@@ -1093,21 +1107,24 @@
 static int usbvision_radio_close(struct file *file)
 {
 	struct usb_usbvision *usbvision = video_drvdata(file);
+	int r;
 
 	PDEBUG(DBG_IO, "");
 
 	mutex_lock(&usbvision->v4l2_lock);
 	/* Set packet size to 0 */
 	usbvision->iface_alt = 0;
-	usb_set_interface(usbvision->dev, usbvision->iface,
-				    usbvision->iface_alt);
+	if (usbvision->dev)
+		usb_set_interface(usbvision->dev, usbvision->iface,
+				  usbvision->iface_alt);
 
 	usbvision_audio_off(usbvision);
 	usbvision->radio = 0;
 	usbvision->user--;
+	r = usbvision->remove_pending;
 	mutex_unlock(&usbvision->v4l2_lock);
 
-	if (usbvision->remove_pending) {
+	if (r) {
 		printk(KERN_INFO "%s: Final disconnect\n", __func__);
 		v4l2_fh_release(file);
 		usbvision_release(usbvision);
@@ -1539,6 +1556,7 @@
 static void usbvision_disconnect(struct usb_interface *intf)
 {
 	struct usb_usbvision *usbvision = to_usbvision(usb_get_intfdata(intf));
+	int u;
 
 	PDEBUG(DBG_PROBE, "");
 
@@ -1555,13 +1573,14 @@
 	v4l2_device_disconnect(&usbvision->v4l2_dev);
 	usbvision_i2c_unregister(usbvision);
 	usbvision->remove_pending = 1;	/* Now all ISO data will be ignored */
+	u = usbvision->user;
 
 	usb_put_dev(usbvision->dev);
 	usbvision->dev = NULL;	/* USB device is no more */
 
 	mutex_unlock(&usbvision->v4l2_lock);
 
-	if (usbvision->user) {
+	if (u) {
 		printk(KERN_INFO "%s: In use, disconnect pending\n",
 		       __func__);
 		wake_up_interruptible(&usbvision->wait_frame);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/uvc/uvc_ctrl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/uvc/uvc_ctrl.c
@@ -6,6 +6,7 @@
  *          Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  */
 
+#include <asm/barrier.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/module.h>
@@ -773,12 +774,16 @@
 	offset &= 7;
 	mask = ((1LL << bits) - 1) << offset;
 
-	for (; bits > 0; data++) {
+	while (1) {
 		u8 byte = *data & mask;
 		value |= offset > 0 ? (byte >> offset) : (byte << (-offset));
 		bits -= 8 - (offset > 0 ? offset : 0);
+		if (bits <= 0)
+			break;
+
 		offset -= 8;
 		mask = (1 << bits) - 1;
+		data++;
 	}
 
 	/* Sign-extend the value if needed. */
@@ -987,26 +992,56 @@
 	return value;
 }
 
-static int __uvc_ctrl_get(struct uvc_video_chain *chain,
-	struct uvc_control *ctrl, struct uvc_control_mapping *mapping,
-	s32 *value)
+static int __uvc_ctrl_load_cur(struct uvc_video_chain *chain,
+			       struct uvc_control *ctrl)
 {
+	u8 *data;
 	int ret;
 
-	if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0)
-		return -EACCES;
+	if (ctrl->loaded)
+		return 0;
 
-	if (!ctrl->loaded) {
-		ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, ctrl->entity->id,
-				chain->dev->intfnum, ctrl->info.selector,
-				uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
-				ctrl->info.size);
-		if (ret < 0)
-			return ret;
+	data = uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT);
 
+	if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0) {
+		memset(data, 0, ctrl->info.size);
 		ctrl->loaded = 1;
+
+		return 0;
 	}
 
+	if (ctrl->entity->get_cur)
+		ret = ctrl->entity->get_cur(chain->dev, ctrl->entity,
+					    ctrl->info.selector, data,
+					    ctrl->info.size);
+	else
+		ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR,
+				     ctrl->entity->id, chain->dev->intfnum,
+				     ctrl->info.selector, data,
+				     ctrl->info.size);
+
+	if (ret < 0)
+		return ret;
+
+	ctrl->loaded = 1;
+
+	return ret;
+}
+
+static int __uvc_ctrl_get(struct uvc_video_chain *chain,
+			  struct uvc_control *ctrl,
+			  struct uvc_control_mapping *mapping,
+			  s32 *value)
+{
+	int ret;
+
+	if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0)
+		return -EACCES;
+
+	ret = __uvc_ctrl_load_cur(chain, ctrl);
+	if (ret < 0)
+		return ret;
+
 	*value = __uvc_ctrl_get_value(mapping,
 				uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
 
@@ -1271,25 +1306,55 @@
 	uvc_ctrl_send_event(chain, handle, ctrl, mapping, val, changes);
 }
 
-static void uvc_ctrl_status_event_work(struct work_struct *work)
+static void uvc_ctrl_set_handle(struct uvc_fh *handle, struct uvc_control *ctrl,
+				struct uvc_fh *new_handle)
+{
+	lockdep_assert_held(&handle->chain->ctrl_mutex);
+
+	if (new_handle) {
+		if (ctrl->handle)
+			dev_warn_ratelimited(&handle->stream->dev->udev->dev,
+					     "UVC non compliance: Setting an async control with a pending operation.");
+
+		if (new_handle == ctrl->handle)
+			return;
+
+		if (ctrl->handle) {
+			WARN_ON(!ctrl->handle->pending_async_ctrls);
+			if (ctrl->handle->pending_async_ctrls)
+				ctrl->handle->pending_async_ctrls--;
+		}
+
+		ctrl->handle = new_handle;
+		handle->pending_async_ctrls++;
+		return;
+	}
+
+	/* Cannot clear the handle for a control not owned by us.*/
+	if (WARN_ON(ctrl->handle != handle))
+		return;
+
+	ctrl->handle = NULL;
+	if (WARN_ON(!handle->pending_async_ctrls))
+		return;
+	handle->pending_async_ctrls--;
+}
+
+void uvc_ctrl_status_event(struct uvc_video_chain *chain,
+			   struct uvc_control *ctrl, const u8 *data)
 {
-	struct uvc_device *dev = container_of(work, struct uvc_device,
-					      async_ctrl.work);
-	struct uvc_ctrl_work *w = &dev->async_ctrl;
-	struct uvc_video_chain *chain = w->chain;
 	struct uvc_control_mapping *mapping;
-	struct uvc_control *ctrl = w->ctrl;
 	struct uvc_fh *handle;
 	unsigned int i;
-	int ret;
 
 	mutex_lock(&chain->ctrl_mutex);
 
 	handle = ctrl->handle;
-	ctrl->handle = NULL;
+	if (handle)
+		uvc_ctrl_set_handle(handle, ctrl, NULL);
 
 	list_for_each_entry(mapping, &ctrl->info.mappings, list) {
-		s32 value = __uvc_ctrl_get_value(mapping, w->data);
+		s32 value = __uvc_ctrl_get_value(mapping, data);
 
 		/*
 		 * handle may be NULL here if the device sends auto-update
@@ -1308,6 +1373,20 @@
 	}
 
 	mutex_unlock(&chain->ctrl_mutex);
+}
+
+static void uvc_ctrl_status_event_work(struct work_struct *work)
+{
+	struct uvc_device *dev = container_of(work, struct uvc_device,
+					      async_ctrl.work);
+	struct uvc_ctrl_work *w = &dev->async_ctrl;
+	int ret;
+
+	uvc_ctrl_status_event(w->chain, w->ctrl, w->data);
+
+	/* The barrier is needed to synchronize with uvc_status_stop(). */
+	if (smp_load_acquire(&dev->flush_status))
+		return;
 
 	/* Resubmit the URB. */
 	w->urb->interval = dev->int_ep->desc.bInterval;
@@ -1317,16 +1396,14 @@
 			   ret);
 }
 
-bool uvc_ctrl_status_event(struct urb *urb, struct uvc_video_chain *chain,
-			   struct uvc_control *ctrl, const u8 *data)
+bool uvc_ctrl_status_event_async(struct urb *urb, struct uvc_video_chain *chain,
+				 struct uvc_control *ctrl, const u8 *data)
 {
 	struct uvc_device *dev = chain->dev;
 	struct uvc_ctrl_work *w = &dev->async_ctrl;
 
-	if (list_empty(&ctrl->info.mappings)) {
-		ctrl->handle = NULL;
+	if (list_empty(&ctrl->info.mappings))
 		return false;
-	}
 
 	w->data = data;
 	w->urb = urb;
@@ -1356,13 +1433,13 @@
 {
 	struct uvc_control_mapping *mapping;
 	struct uvc_control *ctrl;
-	u32 changes = V4L2_EVENT_CTRL_CH_VALUE;
 	unsigned int i;
 	unsigned int j;
 
 	for (i = 0; i < xctrls_count; ++i) {
-		ctrl = uvc_find_control(handle->chain, xctrls[i].id, &mapping);
+		u32 changes = V4L2_EVENT_CTRL_CH_VALUE;
 
+		ctrl = uvc_find_control(handle->chain, xctrls[i].id, &mapping);
 		if (ctrl->info.flags & UVC_CTRL_FLAG_ASYNCHRONOUS)
 			/* Notification will be sent from an Interrupt event. */
 			continue;
@@ -1484,7 +1561,9 @@
 }
 
 static int uvc_ctrl_commit_entity(struct uvc_device *dev,
-	struct uvc_entity *entity, int rollback)
+				  struct uvc_fh *handle,
+				  struct uvc_entity *entity,
+				  int rollback)
 {
 	struct uvc_control *ctrl;
 	unsigned int i;
@@ -1528,6 +1607,10 @@
 
 		if (ret < 0)
 			return ret;
+
+		if (!rollback && handle &&
+		    ctrl->info.flags & UVC_CTRL_FLAG_ASYNCHRONOUS)
+			uvc_ctrl_set_handle(handle, ctrl, handle);
 	}
 
 	return 0;
@@ -1543,7 +1626,8 @@
 
 	/* Find the control. */
 	list_for_each_entry(entity, &chain->entities, chain) {
-		ret = uvc_ctrl_commit_entity(chain->dev, entity, rollback);
+		ret = uvc_ctrl_commit_entity(chain->dev, handle, entity,
+					     rollback);
 		if (ret < 0)
 			goto done;
 	}
@@ -1651,21 +1735,10 @@
 	 * needs to be loaded from the device to perform the read-modify-write
 	 * operation.
 	 */
-	if (!ctrl->loaded && (ctrl->info.size * 8) != mapping->size) {
-		if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0) {
-			memset(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
-				0, ctrl->info.size);
-		} else {
-			ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR,
-				ctrl->entity->id, chain->dev->intfnum,
-				ctrl->info.selector,
-				uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
-				ctrl->info.size);
-			if (ret < 0)
-				return ret;
-		}
-
-		ctrl->loaded = 1;
+	if ((ctrl->info.size * 8) != mapping->size) {
+		ret = __uvc_ctrl_load_cur(chain, ctrl);
+		if (ret < 0)
+			return ret;
 	}
 
 	/* Backup the current value in case we need to rollback later. */
@@ -1678,9 +1751,6 @@
 	mapping->set(mapping, value,
 		uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
 
-	if (ctrl->info.flags & UVC_CTRL_FLAG_ASYNCHRONOUS)
-		ctrl->handle = handle;
-
 	ctrl->dirty = 1;
 	ctrl->modified = 1;
 	return 0;
@@ -1704,9 +1774,19 @@
 	if (data == NULL)
 		return -ENOMEM;
 
-	ret = uvc_query_ctrl(dev, UVC_GET_INFO, ctrl->entity->id, dev->intfnum,
-			     info->selector, data, 1);
-	if (!ret)
+	if (ctrl->entity->get_info)
+		ret = ctrl->entity->get_info(dev, ctrl->entity,
+					     ctrl->info.selector, data);
+	else
+		ret = uvc_query_ctrl(dev, UVC_GET_INFO, ctrl->entity->id,
+				     dev->intfnum, info->selector, data, 1);
+
+	if (!ret) {
+		info->flags &= ~(UVC_CTRL_FLAG_GET_CUR |
+				 UVC_CTRL_FLAG_SET_CUR |
+				 UVC_CTRL_FLAG_AUTO_UPDATE |
+				 UVC_CTRL_FLAG_ASYNCHRONOUS);
+
 		info->flags |= (data[0] & UVC_CONTROL_CAP_GET ?
 				UVC_CTRL_FLAG_GET_CUR : 0)
 			    |  (data[0] & UVC_CONTROL_CAP_SET ?
@@ -1715,6 +1795,7 @@
 				UVC_CTRL_FLAG_AUTO_UPDATE : 0)
 			    |  (data[0] & UVC_CONTROL_CAP_ASYNCHRONOUS ?
 				UVC_CTRL_FLAG_ASYNCHRONOUS : 0);
+	}
 
 	kfree(data);
 	return ret;
@@ -1844,30 +1925,35 @@
 {
 	struct uvc_entity *entity;
 	struct uvc_control *ctrl;
-	unsigned int i, found = 0;
+	unsigned int i;
+	bool found;
 	u32 reqflags;
 	u16 size;
 	u8 *data = NULL;
 	int ret;
 
 	/* Find the extension unit. */
+	found = false;
 	list_for_each_entry(entity, &chain->entities, chain) {
 		if (UVC_ENTITY_TYPE(entity) == UVC_VC_EXTENSION_UNIT &&
-		    entity->id == xqry->unit)
+		    entity->id == xqry->unit) {
+			found = true;
 			break;
+		}
 	}
 
-	if (entity->id != xqry->unit) {
+	if (!found) {
 		uvc_trace(UVC_TRACE_CONTROL, "Extension unit %u not found.\n",
 			xqry->unit);
 		return -ENOENT;
 	}
 
 	/* Find the control and perform delayed initialization if needed. */
+	found = false;
 	for (i = 0; i < entity->ncontrols; ++i) {
 		ctrl = &entity->controls[i];
 		if (ctrl->index == xqry->selector - 1) {
-			found = 1;
+			found = true;
 			break;
 		}
 	}
@@ -1993,7 +2079,7 @@
 			ctrl->dirty = 1;
 		}
 
-		ret = uvc_ctrl_commit_entity(dev, entity, 0);
+		ret = uvc_ctrl_commit_entity(dev, NULL, entity, 0);
 		if (ret < 0)
 			return ret;
 	}
@@ -2024,13 +2110,6 @@
 		goto done;
 	}
 
-	/*
-	 * Retrieve control flags from the device. Ignore errors and work with
-	 * default flag values from the uvc_ctrl array when the device doesn't
-	 * properly implement GET_INFO on standard controls.
-	 */
-	uvc_ctrl_get_flags(dev, ctrl, &ctrl->info);
-
 	ctrl->initialized = 1;
 
 	uvc_trace(UVC_TRACE_CONTROL, "Added control %pUl/%u to device %s "
@@ -2253,6 +2332,13 @@
 		if (uvc_entity_match_guid(ctrl->entity, info->entity) &&
 		    ctrl->index == info->index) {
 			uvc_ctrl_add_info(dev, ctrl, info);
+			/*
+			 * Retrieve control flags from the device. Ignore errors
+			 * and work with default flag values from the uvc_ctrl
+			 * array when the device doesn't properly implement
+			 * GET_INFO on standard controls.
+			 */
+			uvc_ctrl_get_flags(dev, ctrl, &ctrl->info);
 			break;
 		 }
 	}
@@ -2325,6 +2411,30 @@
 	return 0;
 }
 
+void uvc_ctrl_cleanup_fh(struct uvc_fh *handle)
+{
+	struct uvc_entity *entity;
+
+	mutex_lock(&handle->chain->ctrl_mutex);
+
+	if (!handle->pending_async_ctrls) {
+		mutex_unlock(&handle->chain->ctrl_mutex);
+		return;
+	}
+
+	list_for_each_entry(entity, &handle->chain->dev->entities, list) {
+		unsigned int i;
+		for (i = 0; i < entity->ncontrols; ++i) {
+			if (entity->controls[i].handle != handle)
+				continue;
+			uvc_ctrl_set_handle(handle, &entity->controls[i], NULL);
+		}
+	}
+
+	WARN_ON(handle->pending_async_ctrls);
+	mutex_unlock(&handle->chain->ctrl_mutex);
+}
+
 /*
  * Cleanup device controls.
  */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/uvc/uvc_driver.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/uvc/uvc_driver.c
@@ -214,6 +214,11 @@
 		.guid		= UVC_GUID_FORMAT_CNF4,
 		.fcc		= V4L2_PIX_FMT_CNF4,
 	},
+	{
+		.name		= "HEVC",
+		.guid		= UVC_GUID_FORMAT_HEVC,
+		.fcc		= V4L2_PIX_FMT_HEVC,
+	},
 };
 
 /* ------------------------------------------------------------------------
@@ -497,6 +502,22 @@
 			}
 		}
 
+		/* Some devices report bpp that doesn't match the format. */
+		if (dev->quirks & UVC_QUIRK_FORCE_BPP) {
+			const struct v4l2_format_info *info =
+				v4l2_format_info(format->fcc);
+
+			if (info) {
+				unsigned int div = info->hdiv * info->vdiv;
+
+				n = info->bpp[0] * div;
+				for (i = 1; i < info->comp_planes; i++)
+					n += info->bpp[i];
+
+				format->bpp = DIV_ROUND_UP(8 * n, div);
+			}
+		}
+
 		if (buffer[2] == UVC_VS_FORMAT_UNCOMPRESSED) {
 			ftype = UVC_VS_FRAME_UNCOMPRESSED;
 		} else {
@@ -586,7 +607,7 @@
 	/* Parse the frame descriptors. Only uncompressed, MJPEG and frame
 	 * based formats have frame descriptors.
 	 */
-	while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE &&
+	while (ftype && buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE &&
 	       buffer[2] == ftype) {
 		frame = &format->frame[format->nframes];
 		if (ftype != UVC_VS_FRAME_FRAME_BASED)
@@ -871,16 +892,26 @@
 		goto error;
 	}
 
-	size = nformats * sizeof(*format) + nframes * sizeof(*frame)
+	/*
+	 * Allocate memory for the formats, the frames and the intervals,
+	 * plus any required padding to guarantee that everything has the
+	 * correct alignment.
+	 */
+	size = nformats * sizeof(*format);
+	size = ALIGN(size, __alignof__(*frame)) + nframes * sizeof(*frame);
+	size = ALIGN(size, __alignof__(*interval))
 	     + nintervals * sizeof(*interval);
+
 	format = kzalloc(size, GFP_KERNEL);
-	if (format == NULL) {
+	if (!format) {
 		ret = -ENOMEM;
 		goto error;
 	}
 
-	frame = (struct uvc_frame *)&format[nformats];
-	interval = (u32 *)&frame[nframes];
+	frame = (void *)format + nformats * sizeof(*format);
+	frame = PTR_ALIGN(frame, __alignof__(*frame));
+	interval = (void *)frame + nframes * sizeof(*frame);
+	interval = PTR_ALIGN(interval, __alignof__(*interval));
 
 	streaming->format = format;
 	streaming->nformats = nformats;
@@ -951,7 +982,10 @@
 	unsigned int i;
 
 	extra_size = roundup(extra_size, sizeof(*entity->pads));
-	num_inputs = (type & UVC_TERM_OUTPUT) ? num_pads : num_pads - 1;
+	if (num_pads)
+		num_inputs = type & UVC_TERM_OUTPUT ? num_pads : num_pads - 1;
+	else
+		num_inputs = 0;
 	size = sizeof(*entity) + extra_size + sizeof(*entity->pads) * num_pads
 	     + num_inputs;
 	entity = kzalloc(size, GFP_KERNEL);
@@ -967,7 +1001,7 @@
 
 	for (i = 0; i < num_inputs; ++i)
 		entity->pads[i].flags = MEDIA_PAD_FL_SINK;
-	if (!UVC_ENTITY_IS_OTERM(entity))
+	if (!UVC_ENTITY_IS_OTERM(entity) && num_pads)
 		entity->pads[num_pads-1].flags = MEDIA_PAD_FL_SOURCE;
 
 	entity->bNrInPins = num_inputs;
@@ -1041,10 +1075,8 @@
 					       + n;
 		memcpy(unit->extension.bmControls, &buffer[23+p], 2*n);
 
-		if (buffer[24+p+2*n] != 0)
-			usb_string(udev, buffer[24+p+2*n], unit->name,
-				   sizeof(unit->name));
-		else
+		if (buffer[24+p+2*n] == 0 ||
+		    usb_string(udev, buffer[24+p+2*n], unit->name, sizeof(unit->name)) < 0)
 			sprintf(unit->name, "Extension %u", buffer[3]);
 
 		list_add_tail(&unit->list, &dev->entities);
@@ -1169,15 +1201,15 @@
 			memcpy(term->media.bmTransportModes, &buffer[10+n], p);
 		}
 
-		if (buffer[7] != 0)
-			usb_string(udev, buffer[7], term->name,
-				   sizeof(term->name));
-		else if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA)
-			sprintf(term->name, "Camera %u", buffer[3]);
-		else if (UVC_ENTITY_TYPE(term) == UVC_ITT_MEDIA_TRANSPORT_INPUT)
-			sprintf(term->name, "Media %u", buffer[3]);
-		else
-			sprintf(term->name, "Input %u", buffer[3]);
+		if (buffer[7] == 0 ||
+		    usb_string(udev, buffer[7], term->name, sizeof(term->name)) < 0) {
+			if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA)
+				sprintf(term->name, "Camera %u", buffer[3]);
+			if (UVC_ENTITY_TYPE(term) == UVC_ITT_MEDIA_TRANSPORT_INPUT)
+				sprintf(term->name, "Media %u", buffer[3]);
+			else
+				sprintf(term->name, "Input %u", buffer[3]);
+		}
 
 		list_add_tail(&term->list, &dev->entities);
 		break;
@@ -1209,10 +1241,8 @@
 
 		memcpy(term->baSourceID, &buffer[7], 1);
 
-		if (buffer[8] != 0)
-			usb_string(udev, buffer[8], term->name,
-				   sizeof(term->name));
-		else
+		if (buffer[8] == 0 ||
+		    usb_string(udev, buffer[8], term->name, sizeof(term->name)) < 0)
 			sprintf(term->name, "Output %u", buffer[3]);
 
 		list_add_tail(&term->list, &dev->entities);
@@ -1234,10 +1264,8 @@
 
 		memcpy(unit->baSourceID, &buffer[5], p);
 
-		if (buffer[5+p] != 0)
-			usb_string(udev, buffer[5+p], unit->name,
-				   sizeof(unit->name));
-		else
+		if (buffer[5+p] == 0 ||
+		    usb_string(udev, buffer[5+p], unit->name, sizeof(unit->name)) < 0)
 			sprintf(unit->name, "Selector %u", buffer[3]);
 
 		list_add_tail(&unit->list, &dev->entities);
@@ -1267,10 +1295,8 @@
 		if (dev->uvc_version >= 0x0110)
 			unit->processing.bmVideoStandards = buffer[9+n];
 
-		if (buffer[8+n] != 0)
-			usb_string(udev, buffer[8+n], unit->name,
-				   sizeof(unit->name));
-		else
+		if (buffer[8+n] == 0 ||
+		    usb_string(udev, buffer[8+n], unit->name, sizeof(unit->name)) < 0)
 			sprintf(unit->name, "Processing %u", buffer[3]);
 
 		list_add_tail(&unit->list, &dev->entities);
@@ -1298,10 +1324,8 @@
 		unit->extension.bmControls = (u8 *)unit + sizeof(*unit);
 		memcpy(unit->extension.bmControls, &buffer[23+p], n);
 
-		if (buffer[23+p+n] != 0)
-			usb_string(udev, buffer[23+p+n], unit->name,
-				   sizeof(unit->name));
-		else
+		if (buffer[23+p+n] == 0 ||
+		    usb_string(udev, buffer[23+p+n], unit->name, sizeof(unit->name)) < 0)
 			sprintf(unit->name, "Extension %u", buffer[3]);
 
 		list_add_tail(&unit->list, &dev->entities);
@@ -1493,6 +1517,11 @@
 			break;
 		if (forward == prev)
 			continue;
+		if (forward->chain.next || forward->chain.prev) {
+			uvc_trace(UVC_TRACE_DESCR, "Found reference to "
+				"entity %d already in chain.\n", forward->id);
+			return -EINVAL;
+		}
 
 		switch (UVC_ENTITY_TYPE(forward)) {
 		case UVC_VC_EXTENSION_UNIT:
@@ -1574,6 +1603,13 @@
 				return -1;
 			}
 
+			if (term->chain.next || term->chain.prev) {
+				uvc_trace(UVC_TRACE_DESCR, "Found reference to "
+					"entity %d already in chain.\n",
+					term->id);
+				return -EINVAL;
+			}
+
 			if (uvc_trace_param & UVC_TRACE_PROBE)
 				printk(KERN_CONT " %d", term->id);
 
@@ -2151,6 +2187,20 @@
 			   sizeof(dev->name) - len);
 	}
 
+	/* Initialize the media device. */
+#ifdef CONFIG_MEDIA_CONTROLLER
+	dev->mdev.dev = &intf->dev;
+	strscpy(dev->mdev.model, dev->name, sizeof(dev->mdev.model));
+	if (udev->serial)
+		strscpy(dev->mdev.serial, udev->serial,
+			sizeof(dev->mdev.serial));
+	usb_make_path(udev, dev->mdev.bus_info, sizeof(dev->mdev.bus_info));
+	dev->mdev.hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
+	media_device_init(&dev->mdev);
+
+	dev->vdev.mdev = &dev->mdev;
+#endif
+
 	/* Parse the Video Class control descriptor. */
 	if (uvc_parse_control(dev) < 0) {
 		uvc_trace(UVC_TRACE_PROBE, "Unable to parse UVC "
@@ -2171,19 +2221,7 @@
 			"linux-uvc-devel mailing list.\n");
 	}
 
-	/* Initialize the media device and register the V4L2 device. */
-#ifdef CONFIG_MEDIA_CONTROLLER
-	dev->mdev.dev = &intf->dev;
-	strscpy(dev->mdev.model, dev->name, sizeof(dev->mdev.model));
-	if (udev->serial)
-		strscpy(dev->mdev.serial, udev->serial,
-			sizeof(dev->mdev.serial));
-	usb_make_path(udev, dev->mdev.bus_info, sizeof(dev->mdev.bus_info));
-	dev->mdev.hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
-	media_device_init(&dev->mdev);
-
-	dev->vdev.mdev = &dev->mdev;
-#endif
+	/* Register the V4L2 device. */
 	if (v4l2_device_register(&intf->dev, &dev->vdev) < 0)
 		goto error;
 
@@ -2392,6 +2430,8 @@
  * The Logitech cameras listed below have their interface class set to
  * VENDOR_SPEC because they don't announce themselves as UVC devices, even
  * though they are compliant.
+ *
+ * Sort these by vendor/product ID.
  */
 static const struct usb_device_id uvc_ids[] = {
 	/* LogiLink Wireless Webcam */
@@ -2439,6 +2479,24 @@
 	  .bInterfaceSubClass	= 1,
 	  .bInterfaceProtocol	= 0,
 	  .driver_info		= (kernel_ulong_t)&uvc_quirk_probe_minmax },
+	/* Logitech, Webcam C910 */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor		= 0x046d,
+	  .idProduct		= 0x0821,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_INFO_QUIRK(UVC_QUIRK_WAKE_AUTOSUSPEND)},
+	/* Logitech, Webcam B910 */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor		= 0x046d,
+	  .idProduct		= 0x0823,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_INFO_QUIRK(UVC_QUIRK_WAKE_AUTOSUSPEND)},
 	/* Logitech Quickcam Fusion */
 	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
 				| USB_DEVICE_ID_MATCH_INT_INFO,
@@ -2842,6 +2900,15 @@
 	  .bInterfaceProtocol	= 0,
 	  .driver_info		= UVC_INFO_QUIRK(UVC_QUIRK_PROBE_MINMAX
 					| UVC_QUIRK_IGNORE_SELECTOR_UNIT) },
+	/* NXP Semiconductors IR VIDEO */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor		= 0x1fc9,
+	  .idProduct		= 0x009b,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= (kernel_ulong_t)&uvc_quirk_probe_minmax },
 	/* Oculus VR Positional Tracker DK2 */
 	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
 				| USB_DEVICE_ID_MATCH_INT_INFO,
@@ -2860,6 +2927,15 @@
 	  .bInterfaceSubClass	= 1,
 	  .bInterfaceProtocol	= 0,
 	  .driver_info		= (kernel_ulong_t)&uvc_quirk_force_y8 },
+	/* GEO Semiconductor GC6500 */
+	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
+				| USB_DEVICE_ID_MATCH_INT_INFO,
+	  .idVendor		= 0x29fe,
+	  .idProduct		= 0x4d53,
+	  .bInterfaceClass	= USB_CLASS_VIDEO,
+	  .bInterfaceSubClass	= 1,
+	  .bInterfaceProtocol	= 0,
+	  .driver_info		= UVC_INFO_QUIRK(UVC_QUIRK_FORCE_BPP) },
 	/* Intel RealSense D4M */
 	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
 				| USB_DEVICE_ID_MATCH_INT_INFO,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/uvc/uvc_entity.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/uvc/uvc_entity.c
@@ -37,7 +37,7 @@
 			continue;
 
 		remote = uvc_entity_by_id(chain->dev, entity->baSourceID[i]);
-		if (remote == NULL)
+		if (remote == NULL || remote->num_pads == 0)
 			return -EINVAL;
 
 		source = (UVC_ENTITY_TYPE(remote) == UVC_TT_STREAMING)
@@ -73,10 +73,45 @@
 	int ret;
 
 	if (UVC_ENTITY_TYPE(entity) != UVC_TT_STREAMING) {
+		u32 function;
+
 		v4l2_subdev_init(&entity->subdev, &uvc_subdev_ops);
 		strscpy(entity->subdev.name, entity->name,
 			sizeof(entity->subdev.name));
 
+		switch (UVC_ENTITY_TYPE(entity)) {
+		case UVC_VC_SELECTOR_UNIT:
+			function = MEDIA_ENT_F_VID_MUX;
+			break;
+		case UVC_VC_PROCESSING_UNIT:
+		case UVC_VC_EXTENSION_UNIT:
+			/* For lack of a better option. */
+			function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;
+			break;
+		case UVC_COMPOSITE_CONNECTOR:
+		case UVC_COMPONENT_CONNECTOR:
+			function = MEDIA_ENT_F_CONN_COMPOSITE;
+			break;
+		case UVC_SVIDEO_CONNECTOR:
+			function = MEDIA_ENT_F_CONN_SVIDEO;
+			break;
+		case UVC_ITT_CAMERA:
+			function = MEDIA_ENT_F_CAM_SENSOR;
+			break;
+		case UVC_TT_VENDOR_SPECIFIC:
+		case UVC_ITT_VENDOR_SPECIFIC:
+		case UVC_ITT_MEDIA_TRANSPORT_INPUT:
+		case UVC_OTT_VENDOR_SPECIFIC:
+		case UVC_OTT_DISPLAY:
+		case UVC_OTT_MEDIA_TRANSPORT_OUTPUT:
+		case UVC_EXTERNAL_VENDOR_SPECIFIC:
+		default:
+			function = MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN;
+			break;
+		}
+
+		entity->subdev.entity.function = function;
+
 		ret = media_entity_pads_init(&entity->subdev.entity,
 					entity->num_pads, entity->pads);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/uvc/uvc_queue.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/uvc/uvc_queue.c
@@ -185,14 +185,27 @@
 static void uvc_stop_streaming(struct vb2_queue *vq)
 {
 	struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
+	struct uvc_streaming *stream = uvc_queue_to_stream(queue);
 
 	lockdep_assert_irqs_enabled();
 
+	/* Prevent new buffers coming in. */
+	spin_lock_irq(&queue->irqlock);
+	queue->flags |= UVC_QUEUE_STOPPING;
+	spin_unlock_irq(&queue->irqlock);
+
+	/*
+	 * All pending work should be completed before disabling the stream, as
+	 * all URBs will be free'd during uvc_video_enable(s, 0).
+	 */
+	flush_workqueue(stream->async_wq);
+
 	if (vq->type != V4L2_BUF_TYPE_META_CAPTURE)
 		uvc_video_stop_streaming(uvc_queue_to_stream(queue));
 
 	spin_lock_irq(&queue->irqlock);
 	uvc_queue_return_buffers(queue, UVC_BUF_STATE_ERROR);
+	queue->flags &= ~UVC_QUEUE_STOPPING;
 	spin_unlock_irq(&queue->irqlock);
 }
 
@@ -486,7 +499,8 @@
 
 	buf->state = buf->error ? UVC_BUF_STATE_ERROR : UVC_BUF_STATE_DONE;
 	vb2_set_plane_payload(&buf->buf.vb2_buf, 0, buf->bytesused);
-	vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_DONE);
+	vb2_buffer_done(&buf->buf.vb2_buf, buf->error ? VB2_BUF_STATE_ERROR :
+							VB2_BUF_STATE_DONE);
 }
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/uvc/uvc_status.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/uvc/uvc_status.c
@@ -6,6 +6,7 @@
  *          Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  */
 
+#include <asm/barrier.h>
 #include <linux/kernel.h>
 #include <linux/input.h>
 #include <linux/slab.h>
@@ -179,7 +180,8 @@
 
 	switch (status->bAttribute) {
 	case UVC_CTRL_VALUE_CHANGE:
-		return uvc_ctrl_status_event(urb, chain, ctrl, status->bValue);
+		return uvc_ctrl_status_event_async(urb, chain, ctrl,
+						   status->bValue);
 
 	case UVC_CTRL_INFO_CHANGE:
 	case UVC_CTRL_FAILURE_CHANGE:
@@ -267,6 +269,7 @@
 	dev->int_urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (dev->int_urb == NULL) {
 		kfree(dev->status);
+		dev->status = NULL;
 		return -ENOMEM;
 	}
 
@@ -309,5 +312,41 @@
 
 void uvc_status_stop(struct uvc_device *dev)
 {
+	struct uvc_ctrl_work *w = &dev->async_ctrl;
+
+	/*
+	 * Prevent the asynchronous control handler from requeing the URB. The
+	 * barrier is needed so the flush_status change is visible to other
+	 * CPUs running the asynchronous handler before usb_kill_urb() is
+	 * called below.
+	 */
+	smp_store_release(&dev->flush_status, true);
+
+	/*
+	 * Cancel any pending asynchronous work. If any status event was queued,
+	 * process it synchronously.
+	 */
+	if (cancel_work_sync(&w->work))
+		uvc_ctrl_status_event(w->chain, w->ctrl, w->data);
+
+	/* Kill the urb. */
 	usb_kill_urb(dev->int_urb);
+
+	/*
+	 * The URB completion handler may have queued asynchronous work. This
+	 * won't resubmit the URB as flush_status is set, but it needs to be
+	 * cancelled before returning or it could then race with a future
+	 * uvc_status_start() call.
+	 */
+	if (cancel_work_sync(&w->work))
+		uvc_ctrl_status_event(w->chain, w->ctrl, w->data);
+
+	/*
+	 * From this point, there are no events on the queue and the status URB
+	 * is dead. No events will be queued until uvc_status_start() is called.
+	 * The barrier is needed to make sure that flush_status is visible to
+	 * uvc_ctrl_status_event_work() when uvc_status_start() will be called
+	 * again.
+	 */
+	smp_store_release(&dev->flush_status, false);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/uvc/uvc_v4l2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/uvc/uvc_v4l2.c
@@ -247,11 +247,41 @@
 	if (ret < 0)
 		goto done;
 
+	/* After the probe, update fmt with the values returned from
+	 * negotiation with the device. Some devices return invalid bFormatIndex
+	 * and bFrameIndex values, in which case we can only assume they have
+	 * accepted the requested format as-is.
+	 */
+	for (i = 0; i < stream->nformats; ++i) {
+		if (probe->bFormatIndex == stream->format[i].index) {
+			format = &stream->format[i];
+			break;
+		}
+	}
+
+	if (i == stream->nformats)
+		uvc_trace(UVC_TRACE_FORMAT,
+			  "Unknown bFormatIndex %u, using default\n",
+			  probe->bFormatIndex);
+
+	for (i = 0; i < format->nframes; ++i) {
+		if (probe->bFrameIndex == format->frame[i].bFrameIndex) {
+			frame = &format->frame[i];
+			break;
+		}
+	}
+
+	if (i == format->nframes)
+		uvc_trace(UVC_TRACE_FORMAT,
+			  "Unknown bFrameIndex %u, using default\n",
+			  probe->bFrameIndex);
+
 	fmt->fmt.pix.width = frame->wWidth;
 	fmt->fmt.pix.height = frame->wHeight;
 	fmt->fmt.pix.field = V4L2_FIELD_NONE;
 	fmt->fmt.pix.bytesperline = uvc_v4l2_get_bytesperline(format, frame);
 	fmt->fmt.pix.sizeimage = probe->dwMaxVideoFrameSize;
+	fmt->fmt.pix.pixelformat = format->fcc;
 	fmt->fmt.pix.colorspace = format->colorspace;
 
 	if (uvc_format != NULL)
@@ -437,10 +467,13 @@
 	uvc_simplify_fraction(&timeperframe.numerator,
 		&timeperframe.denominator, 8, 333);
 
-	if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+	if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
 		parm->parm.capture.timeperframe = timeperframe;
-	else
+		parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
+	} else {
 		parm->parm.output.timeperframe = timeperframe;
+		parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
+	}
 
 	return 0;
 }
@@ -556,6 +589,8 @@
 
 	uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_release\n");
 
+	uvc_ctrl_cleanup_fh(handle);
+
 	/* Only free resources if this is a privileged handle. */
 	if (uvc_has_privileges(handle))
 		uvc_queue_release(&stream->queue);
@@ -826,29 +861,31 @@
 	struct uvc_video_chain *chain = handle->chain;
 	const struct uvc_entity *selector = chain->selector;
 	struct uvc_entity *iterm = NULL;
+	struct uvc_entity *it;
 	u32 index = input->index;
-	int pin = 0;
 
 	if (selector == NULL ||
 	    (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
 		if (index != 0)
 			return -EINVAL;
-		list_for_each_entry(iterm, &chain->entities, chain) {
-			if (UVC_ENTITY_IS_ITERM(iterm))
+		list_for_each_entry(it, &chain->entities, chain) {
+			if (UVC_ENTITY_IS_ITERM(it)) {
+				iterm = it;
 				break;
+			}
 		}
-		pin = iterm->id;
 	} else if (index < selector->bNrInPins) {
-		pin = selector->baSourceID[index];
-		list_for_each_entry(iterm, &chain->entities, chain) {
-			if (!UVC_ENTITY_IS_ITERM(iterm))
+		list_for_each_entry(it, &chain->entities, chain) {
+			if (!UVC_ENTITY_IS_ITERM(it))
 				continue;
-			if (iterm->id == pin)
+			if (it->id == selector->baSourceID[index]) {
+				iterm = it;
 				break;
+			}
 		}
 	}
 
-	if (iterm == NULL || iterm->id != pin)
+	if (iterm == NULL)
 		return -EINVAL;
 
 	memset(input, 0, sizeof(*input));
@@ -864,8 +901,8 @@
 {
 	struct uvc_fh *handle = fh;
 	struct uvc_video_chain *chain = handle->chain;
+	u8 *buf;
 	int ret;
-	u8 i;
 
 	if (chain->selector == NULL ||
 	    (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
@@ -873,22 +910,27 @@
 		return 0;
 	}
 
+	buf = kmalloc(1, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
 	ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, chain->selector->id,
 			     chain->dev->intfnum,  UVC_SU_INPUT_SELECT_CONTROL,
-			     &i, 1);
-	if (ret < 0)
-		return ret;
+			     buf, 1);
+	if (!ret)
+		*input = *buf - 1;
 
-	*input = i - 1;
-	return 0;
+	kfree(buf);
+
+	return ret;
 }
 
 static int uvc_ioctl_s_input(struct file *file, void *fh, unsigned int input)
 {
 	struct uvc_fh *handle = fh;
 	struct uvc_video_chain *chain = handle->chain;
+	u8 *buf;
 	int ret;
-	u32 i;
 
 	ret = uvc_acquire_privileges(handle);
 	if (ret < 0)
@@ -904,10 +946,17 @@
 	if (input >= chain->selector->bNrInPins)
 		return -EINVAL;
 
-	i = input + 1;
-	return uvc_query_ctrl(chain->dev, UVC_SET_CUR, chain->selector->id,
-			      chain->dev->intfnum, UVC_SU_INPUT_SELECT_CONTROL,
-			      &i, 1);
+	buf = kmalloc(1, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	*buf = input + 1;
+	ret = uvc_query_ctrl(chain->dev, UVC_SET_CUR, chain->selector->id,
+			     chain->dev->intfnum, UVC_SU_INPUT_SELECT_CONTROL,
+			     buf, 1);
+	kfree(buf);
+
+	return ret;
 }
 
 static int uvc_ioctl_queryctrl(struct file *file, void *fh,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/uvc/uvc_video.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/uvc/uvc_video.c
@@ -112,6 +112,11 @@
 	case 5: /* Invalid unit */
 	case 6: /* Invalid control */
 	case 7: /* Invalid Request */
+		/*
+		 * The firmware has not properly implemented
+		 * the control or there has been a HW error.
+		 */
+		return -EIO;
 	case 8: /* Invalid value within range */
 		return -EINVAL;
 	default: /* reserved or unknown */
@@ -124,10 +129,37 @@
 static void uvc_fixup_video_ctrl(struct uvc_streaming *stream,
 	struct uvc_streaming_control *ctrl)
 {
+	static const struct usb_device_id elgato_cam_link_4k = {
+		USB_DEVICE(0x0fd9, 0x0066)
+	};
 	struct uvc_format *format = NULL;
 	struct uvc_frame *frame = NULL;
 	unsigned int i;
 
+	/*
+	 * The response of the Elgato Cam Link 4K is incorrect: The second byte
+	 * contains bFormatIndex (instead of being the second byte of bmHint).
+	 * The first byte is always zero. The third byte is always 1.
+	 *
+	 * The UVC 1.5 class specification defines the first five bits in the
+	 * bmHint bitfield. The remaining bits are reserved and should be zero.
+	 * Therefore a valid bmHint will be less than 32.
+	 *
+	 * Latest Elgato Cam Link 4K firmware as of 2021-03-23 needs this fix.
+	 * MCU: 20.02.19, FPGA: 67
+	 */
+	if (usb_match_one_id(stream->dev->intf, &elgato_cam_link_4k) &&
+	    ctrl->bmHint > 255) {
+		u8 corrected_format_index = ctrl->bmHint >> 8;
+
+		uvc_trace(UVC_TRACE_VIDEO,
+			"Correct USB video probe response from {bmHint: 0x%04x, bFormatIndex: %u} to {bmHint: 0x%04x, bFormatIndex: %u}\n",
+			ctrl->bmHint, ctrl->bFormatIndex,
+			1, corrected_format_index);
+		ctrl->bmHint = 1;
+		ctrl->bFormatIndex = corrected_format_index;
+	}
+
 	for (i = 0; i < stream->nformats; ++i) {
 		if (stream->format[i].index == ctrl->bFormatIndex) {
 			format = &stream->format[i];
@@ -175,13 +207,13 @@
 		/* Compute a bandwidth estimation by multiplying the frame
 		 * size by the number of video frames per second, divide the
 		 * result by the number of USB frames (or micro-frames for
-		 * high-speed devices) per second and add the UVC header size
-		 * (assumed to be 12 bytes long).
+		 * high- and super-speed devices) per second and add the UVC
+		 * header size (assumed to be 12 bytes long).
 		 */
 		bandwidth = frame->wWidth * frame->wHeight / 8 * format->bpp;
 		bandwidth *= 10000000 / interval + 1;
 		bandwidth /= 1000;
-		if (stream->dev->udev->speed == USB_SPEED_HIGH)
+		if (stream->dev->udev->speed >= USB_SPEED_HIGH)
 			bandwidth /= 8;
 		bandwidth += 12;
 
@@ -436,6 +468,7 @@
 	ktime_t time;
 	u16 host_sof;
 	u16 dev_sof;
+	u32 dev_stc;
 
 	switch (data[1] & (UVC_STREAM_PTS | UVC_STREAM_SCR)) {
 	case UVC_STREAM_PTS | UVC_STREAM_SCR:
@@ -480,6 +513,34 @@
 	if (dev_sof == stream->clock.last_sof)
 		return;
 
+	dev_stc = get_unaligned_le32(&data[header_size - 6]);
+
+	/*
+	 * STC (Source Time Clock) is the clock used by the camera. The UVC 1.5
+	 * standard states that it "must be captured when the first video data
+	 * of a video frame is put on the USB bus". This is generally understood
+	 * as requiring devices to clear the payload header's SCR bit before
+	 * the first packet containing video data.
+	 *
+	 * Most vendors follow that interpretation, but some (namely SunplusIT
+	 * on some devices) always set the `UVC_STREAM_SCR` bit, fill the SCR
+	 * field with 0's,and expect that the driver only processes the SCR if
+	 * there is data in the packet.
+	 *
+	 * Ignore all the hardware timestamp information if we haven't received
+	 * any data for this frame yet, the packet contains no data, and both
+	 * STC and SOF are zero. This heuristics should be safe on compliant
+	 * devices. This should be safe with compliant devices, as in the very
+	 * unlikely case where a UVC 1.1 device would send timing information
+	 * only before the first packet containing data, and both STC and SOF
+	 * happen to be zero for a particular frame, we would only miss one
+	 * clock sample from many and the clock recovery algorithm wouldn't
+	 * suffer from this condition.
+	 */
+	if (buf && buf->bytesused == 0 && len == header_size &&
+	    dev_stc == 0 && dev_sof == 0)
+		return;
+
 	stream->clock.last_sof = dev_sof;
 
 	host_sof = usb_get_current_frame_number(stream->dev->udev);
@@ -517,7 +578,7 @@
 	spin_lock_irqsave(&stream->clock.lock, flags);
 
 	sample = &stream->clock.samples[stream->clock.head];
-	sample->dev_stc = get_unaligned_le32(&data[header_size - 6]);
+	sample->dev_stc = dev_stc;
 	sample->dev_sof = dev_sof;
 	sample->host_sof = host_sof;
 	sample->host_time = time;
@@ -662,11 +723,11 @@
 	unsigned long flags;
 	u64 timestamp;
 	u32 delta_stc;
-	u32 y1, y2;
+	u32 y1;
 	u32 x1, x2;
 	u32 mean;
 	u32 sof;
-	u64 y;
+	u64 y, y2;
 
 	if (!uvc_hw_timestamps_param)
 		return;
@@ -706,7 +767,7 @@
 	sof = y;
 
 	uvc_trace(UVC_TRACE_CLOCK, "%s: PTS %u y %llu.%06llu SOF %u.%06llu "
-		  "(x1 %u x2 %u y1 %u y2 %u SOF offset %u)\n",
+		  "(x1 %u x2 %u y1 %u y2 %llu SOF offset %u)\n",
 		  stream->dev->name, buf->pts,
 		  y >> 16, div_u64((y & 0xffff) * 1000000, 65536),
 		  sof >> 16, div_u64(((u64)sof & 0xffff) * 1000000LLU, 65536),
@@ -721,7 +782,7 @@
 		goto done;
 
 	y1 = NSEC_PER_SEC;
-	y2 = (u32)ktime_to_ns(ktime_sub(last->host_time, first->host_time)) + y1;
+	y2 = ktime_to_ns(ktime_sub(last->host_time, first->host_time)) + y1;
 
 	/* Interpolated and host SOF timestamps can wrap around at slightly
 	 * different times. Handle this by adding or removing 2048 to or from
@@ -741,7 +802,7 @@
 	timestamp = ktime_to_ns(first->host_time) + y - y1;
 
 	uvc_trace(UVC_TRACE_CLOCK, "%s: SOF %u.%06llu y %llu ts %llu "
-		  "buf ts %llu (x1 %u/%u/%u x2 %u/%u/%u y1 %u y2 %u)\n",
+		  "buf ts %llu (x1 %u/%u/%u x2 %u/%u/%u y1 %u y2 %llu)\n",
 		  stream->dev->name,
 		  sof >> 16, div_u64(((u64)sof & 0xffff) * 1000000LLU, 65536),
 		  y, timestamp, vbuf->vb2_buf.timestamp,
@@ -765,9 +826,9 @@
 	unsigned int header_size;
 	bool has_pts = false;
 	bool has_scr = false;
-	u16 uninitialized_var(scr_sof);
-	u32 uninitialized_var(scr_stc);
-	u32 uninitialized_var(pts);
+	u16 scr_sof;
+	u32 scr_stc;
+	u32 pts;
 
 	if (stream->stats.stream.nb_frames == 0 &&
 	    stream->stats.frame.nb_packets == 0)
@@ -1097,6 +1158,20 @@
 	return data[0];
 }
 
+static void uvc_video_copy_packets(struct uvc_urb *uvc_urb)
+{
+	unsigned int i;
+
+	for (i = 0; i < uvc_urb->async_operations; i++) {
+		struct uvc_copy_op *op = &uvc_urb->copy_operations[i];
+
+		memcpy(op->dst, op->src, op->len);
+
+		/* Release reference taken on this buffer. */
+		uvc_queue_buffer_release(op->buf);
+	}
+}
+
 /*
  * uvc_video_decode_data_work: Asynchronous memcpy processing
  *
@@ -1106,22 +1181,26 @@
 static void uvc_video_copy_data_work(struct work_struct *work)
 {
 	struct uvc_urb *uvc_urb = container_of(work, struct uvc_urb, work);
-	unsigned int i;
+	struct uvc_streaming *stream = uvc_urb->stream;
+	struct uvc_video_queue *queue = &stream->queue;
 	int ret;
 
-	for (i = 0; i < uvc_urb->async_operations; i++) {
-		struct uvc_copy_op *op = &uvc_urb->copy_operations[i];
-
-		memcpy(op->dst, op->src, op->len);
+	uvc_video_copy_packets(uvc_urb);
 
-		/* Release reference taken on this buffer. */
-		uvc_queue_buffer_release(op->buf);
+	/*
+	 * Prevent resubmitting URBs when shutting down to ensure that no new
+	 * work item will be scheduled after uvc_stop_streaming() flushes the
+	 * work queue.
+	 */
+	spin_lock_irq(&queue->irqlock);
+	if (!(queue->flags & UVC_QUEUE_STOPPING)) {
+		ret = usb_submit_urb(uvc_urb->urb, GFP_ATOMIC);
+		if (ret < 0)
+			uvc_printk(KERN_ERR,
+				   "Failed to resubmit video URB (%d).\n",
+				   ret);
 	}
-
-	ret = usb_submit_urb(uvc_urb->urb, GFP_KERNEL);
-	if (ret < 0)
-		uvc_printk(KERN_ERR, "Failed to resubmit video URB (%d).\n",
-			   ret);
+	spin_unlock_irq(&queue->irqlock);
 }
 
 static void uvc_video_decode_data(struct uvc_urb *uvc_urb,
@@ -1276,7 +1355,9 @@
 	if (has_scr)
 		memcpy(stream->clock.last_scr, scr, 6);
 
-	memcpy(&meta->length, mem, length);
+	meta->length = mem[0];
+	meta->flags  = mem[1];
+	memcpy(meta->buf, &mem[2], length - 2);
 	meta_buf->bytesused += length + sizeof(meta->ns) + sizeof(meta->sof);
 
 	uvc_trace(UVC_TRACE_FRAME,
@@ -1524,6 +1605,10 @@
 
 	buf = uvc_queue_get_current_buffer(queue);
 
+	/*
+	 * Process the URB headers, and optionally queue expensive memcpy tasks
+	 * to be deferred to a work queue.
+	 */
 	if (vb2_qmeta) {
 		spin_lock_irqsave(&qmeta->irqlock, flags);
 		if (!list_empty(&qmeta->irqqueue))
@@ -1551,7 +1636,21 @@
 		return;
 	}
 
-	queue_work(stream->async_wq, &uvc_urb->work);
+	/*
+	 * When the stream is stopped, all URBs are freed as part of the call to
+	 * uvc_stop_streaming() and must not be handled asynchronously. In that
+	 * event we can safely complete the packet work directly in this
+	 * context, without resubmitting the URB.
+	 */
+	spin_lock_irqsave(&queue->irqlock, flags);
+	if (!(queue->flags & UVC_QUEUE_STOPPING)) {
+		/* Handle any heavy lifting required */
+		INIT_WORK(&uvc_urb->work, uvc_video_copy_data_work);
+		queue_work(stream->async_wq, &uvc_urb->work);
+	} else {
+		uvc_video_copy_packets(uvc_urb);
+	}
+	spin_unlock_irqrestore(&queue->irqlock, flags);
 }
 
 /*
@@ -1828,7 +1927,7 @@
 		struct usb_host_endpoint *best_ep = NULL;
 		unsigned int best_psize = UINT_MAX;
 		unsigned int bandwidth;
-		unsigned int uninitialized_var(altsetting);
+		unsigned int altsetting;
 		int intfnum = stream->intfnum;
 
 		/* Isochronous endpoint, select the alternate setting. */
@@ -1871,6 +1970,17 @@
 		uvc_trace(UVC_TRACE_VIDEO, "Selecting alternate setting %u "
 			"(%u B/frame bandwidth).\n", altsetting, best_psize);
 
+		/*
+		 * Some devices, namely the Logitech C910 and B910, are unable
+		 * to recover from a USB autosuspend, unless the alternate
+		 * setting of the streaming interface is toggled.
+		 */
+		if (stream->dev->quirks & UVC_QUIRK_WAKE_AUTOSUSPEND) {
+			usb_set_interface(stream->dev->udev, intfnum,
+					  altsetting);
+			usb_set_interface(stream->dev->udev, intfnum, 0);
+		}
+
 		ret = usb_set_interface(stream->dev->udev, intfnum, altsetting);
 		if (ret < 0)
 			return ret;
@@ -1883,6 +1993,10 @@
 		if (ep == NULL)
 			return -EIO;
 
+		/* Reject broken descriptors. */
+		if (usb_endpoint_maxp(&ep->desc) == 0)
+			return -EIO;
+
 		ret = uvc_init_video_bulk(stream, ep, gfp_flags);
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/uvc/uvcvideo.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/uvc/uvcvideo.h
@@ -165,6 +165,10 @@
 	{0x32, 0x00, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00, \
 	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
 
+#define UVC_GUID_FORMAT_HEVC \
+	{ 'H',  'E',  'V',  'C', 0x00, 0x00, 0x10, 0x00, \
+	 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+
 
 /* ------------------------------------------------------------------------
  * Driver specific constants.
@@ -173,13 +177,13 @@
 #define DRIVER_VERSION		"1.1.1"
 
 /* Number of isochronous URBs. */
-#define UVC_URBS		5
+#define UVC_URBS		50
 /* Maximum number of packets per URB. */
-#define UVC_MAX_PACKETS		32
+#define UVC_MAX_PACKETS		48
 /* Maximum status buffer size in bytes of interrupt URB. */
 #define UVC_MAX_STATUS_SIZE	16
 
-#define UVC_CTRL_CONTROL_TIMEOUT	500
+#define UVC_CTRL_CONTROL_TIMEOUT	5000
 #define UVC_CTRL_STREAMING_TIMEOUT	5000
 
 /* Maximum allowed number of control mappings per device */
@@ -198,6 +202,8 @@
 #define UVC_QUIRK_RESTRICT_FRAME_RATE	0x00000200
 #define UVC_QUIRK_RESTORE_CTRLS_ON_INIT	0x00000400
 #define UVC_QUIRK_FORCE_Y8		0x00000800
+#define UVC_QUIRK_FORCE_BPP		0x00001000
+#define UVC_QUIRK_WAKE_AUTOSUSPEND	0x00002000
 
 /* Format flags */
 #define UVC_FMT_FLAG_COMPRESSED		0x00000001
@@ -348,6 +354,11 @@
 	u8 bNrInPins;
 	u8 *baSourceID;
 
+	int (*get_info)(struct uvc_device *dev, struct uvc_entity *entity,
+			u8 cs, u8 *caps);
+	int (*get_cur)(struct uvc_device *dev, struct uvc_entity *entity,
+		       u8 cs, void *data, u16 size);
+
 	unsigned int ncontrols;
 	struct uvc_control *controls;
 };
@@ -420,6 +431,7 @@
 
 #define UVC_QUEUE_DISCONNECTED		(1 << 0)
 #define UVC_QUEUE_DROP_CORRUPTED	(1 << 1)
+#define UVC_QUEUE_STOPPING		(1 << 2)
 
 struct uvc_video_queue {
 	struct vb2_queue queue;
@@ -440,7 +452,11 @@
 	struct uvc_entity *processing;		/* Processing unit */
 	struct uvc_entity *selector;		/* Selector unit */
 
-	struct mutex ctrl_mutex;		/* Protects ctrl.info */
+	struct mutex ctrl_mutex;		/*
+						 * Protects ctrl.info,
+						 * ctrl.handle and
+						 * uvc_fh.pending_async_ctrls
+						 */
 
 	struct v4l2_prio_state prio;		/* V4L2 priority state */
 	u32 caps;				/* V4L2 chain-wide caps */
@@ -662,6 +678,7 @@
 	/* Status Interrupt Endpoint */
 	struct usb_host_endpoint *int_ep;
 	struct urb *int_urb;
+	bool flush_status;
 	u8 *status;
 	struct input_dev *input;
 	char input_phys[64];
@@ -685,6 +702,7 @@
 	struct uvc_video_chain *chain;
 	struct uvc_streaming *stream;
 	enum uvc_handle_state state;
+	unsigned int pending_async_ctrls;
 };
 
 struct uvc_driver {
@@ -831,7 +849,9 @@
 int uvc_ctrl_init_device(struct uvc_device *dev);
 void uvc_ctrl_cleanup_device(struct uvc_device *dev);
 int uvc_ctrl_restore_values(struct uvc_device *dev);
-bool uvc_ctrl_status_event(struct urb *urb, struct uvc_video_chain *chain,
+bool uvc_ctrl_status_event_async(struct urb *urb, struct uvc_video_chain *chain,
+				 struct uvc_control *ctrl, const u8 *data);
+void uvc_ctrl_status_event(struct uvc_video_chain *chain,
 			   struct uvc_control *ctrl, const u8 *data);
 
 int uvc_ctrl_begin(struct uvc_video_chain *chain);
@@ -855,6 +875,8 @@
 int uvc_xu_ctrl_query(struct uvc_video_chain *chain,
 		      struct uvc_xu_control_query *xqry);
 
+void uvc_ctrl_cleanup_fh(struct uvc_fh *handle);
+
 /* Utility functions */
 void uvc_simplify_fraction(u32 *numerator, u32 *denominator,
 			   unsigned int n_terms, unsigned int threshold);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/usb/zr364xx/zr364xx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/usb/zr364xx/zr364xx.c
@@ -1037,6 +1037,7 @@
 	DBG("submitting URB %p\n", pipe_info->stream_urb);
 	retval = usb_submit_urb(pipe_info->stream_urb, GFP_KERNEL);
 	if (retval) {
+		usb_free_urb(pipe_info->stream_urb);
 		printk(KERN_ERR KBUILD_MODNAME ": start read pipe failed\n");
 		return retval;
 	}
@@ -1186,15 +1187,11 @@
 	return err;
 }
 
-static void zr364xx_release(struct v4l2_device *v4l2_dev)
+static void zr364xx_board_uninit(struct zr364xx_camera *cam)
 {
-	struct zr364xx_camera *cam =
-		container_of(v4l2_dev, struct zr364xx_camera, v4l2_dev);
 	unsigned long i;
 
-	v4l2_device_unregister(&cam->v4l2_dev);
-
-	videobuf_mmap_free(&cam->vb_vidq);
+	zr364xx_stop_readpipe(cam);
 
 	/* release sys buffers */
 	for (i = 0; i < FRAMES; i++) {
@@ -1205,9 +1202,19 @@
 		cam->buffer.frame[i].lpvbits = NULL;
 	}
 
-	v4l2_ctrl_handler_free(&cam->ctrl_handler);
 	/* release transfer buffer */
 	kfree(cam->pipe->transfer_buffer);
+}
+
+static void zr364xx_release(struct v4l2_device *v4l2_dev)
+{
+	struct zr364xx_camera *cam =
+		container_of(v4l2_dev, struct zr364xx_camera, v4l2_dev);
+
+	videobuf_mmap_free(&cam->vb_vidq);
+	v4l2_ctrl_handler_free(&cam->ctrl_handler);
+	zr364xx_board_uninit(cam);
+	v4l2_device_unregister(&cam->v4l2_dev);
 	kfree(cam);
 }
 
@@ -1330,6 +1337,7 @@
 {
 	struct zr364xx_pipeinfo *pipe = cam->pipe;
 	unsigned long i;
+	int err;
 
 	DBG("board init: %p\n", cam);
 	memset(pipe, 0, sizeof(*pipe));
@@ -1362,9 +1370,8 @@
 
 	if (i == 0) {
 		printk(KERN_INFO KBUILD_MODNAME ": out of memory. Aborting\n");
-		kfree(cam->pipe->transfer_buffer);
-		cam->pipe->transfer_buffer = NULL;
-		return -ENOMEM;
+		err = -ENOMEM;
+		goto err_free;
 	} else
 		cam->buffer.dwFrames = i;
 
@@ -1379,9 +1386,20 @@
 	/*** end create system buffers ***/
 
 	/* start read pipe */
-	zr364xx_start_readpipe(cam);
+	err = zr364xx_start_readpipe(cam);
+	if (err)
+		goto err_free_frames;
+
 	DBG(": board initialized\n");
 	return 0;
+
+err_free_frames:
+	for (i = 0; i < FRAMES; i++)
+		vfree(cam->buffer.frame[i].lpvbits);
+err_free:
+	kfree(cam->pipe->transfer_buffer);
+	cam->pipe->transfer_buffer = NULL;
+	return err;
 }
 
 static int zr364xx_probe(struct usb_interface *intf,
@@ -1406,12 +1424,10 @@
 	if (!cam)
 		return -ENOMEM;
 
-	cam->v4l2_dev.release = zr364xx_release;
 	err = v4l2_device_register(&intf->dev, &cam->v4l2_dev);
 	if (err < 0) {
 		dev_err(&udev->dev, "couldn't register v4l2_device\n");
-		kfree(cam);
-		return err;
+		goto free_cam;
 	}
 	hdl = &cam->ctrl_handler;
 	v4l2_ctrl_handler_init(hdl, 1);
@@ -1420,7 +1436,7 @@
 	if (hdl->error) {
 		err = hdl->error;
 		dev_err(&udev->dev, "couldn't register control\n");
-		goto fail;
+		goto free_hdlr_and_unreg_dev;
 	}
 	/* save the init method used by this camera */
 	cam->method = id->driver_info;
@@ -1493,7 +1509,7 @@
 	if (!cam->read_endpoint) {
 		err = -ENOMEM;
 		dev_err(&intf->dev, "Could not find bulk-in endpoint\n");
-		goto fail;
+		goto free_hdlr_and_unreg_dev;
 	}
 
 	/* v4l */
@@ -1504,10 +1520,11 @@
 
 	/* load zr364xx board specific */
 	err = zr364xx_board_init(cam);
-	if (!err)
-		err = v4l2_ctrl_handler_setup(hdl);
 	if (err)
-		goto fail;
+		goto free_hdlr_and_unreg_dev;
+	err = v4l2_ctrl_handler_setup(hdl);
+	if (err)
+		goto board_uninit;
 
 	spin_lock_init(&cam->slock);
 
@@ -1522,16 +1539,20 @@
 	err = video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1);
 	if (err) {
 		dev_err(&udev->dev, "video_register_device failed\n");
-		goto fail;
+		goto board_uninit;
 	}
+	cam->v4l2_dev.release = zr364xx_release;
 
 	dev_info(&udev->dev, DRIVER_DESC " controlling device %s\n",
 		 video_device_node_name(&cam->vdev));
 	return 0;
 
-fail:
+board_uninit:
+	zr364xx_board_uninit(cam);
+free_hdlr_and_unreg_dev:
 	v4l2_ctrl_handler_free(hdl);
 	v4l2_device_unregister(&cam->v4l2_dev);
+free_cam:
 	kfree(cam);
 	return err;
 }
@@ -1578,10 +1599,19 @@
 	if (!cam->was_streaming)
 		return 0;
 
-	zr364xx_start_readpipe(cam);
+	res = zr364xx_start_readpipe(cam);
+	if (res)
+		return res;
+
 	res = zr364xx_prepare(cam);
-	if (!res)
-		zr364xx_start_acquire(cam);
+	if (res)
+		goto err_prepare;
+
+	zr364xx_start_acquire(cam);
+	return 0;
+
+err_prepare:
+	zr364xx_stop_readpipe(cam);
 	return res;
 }
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -1183,36 +1183,38 @@
 	u32 aux_space;
 	int compatible_arg = 1;
 	long err = 0;
+	unsigned int ncmd;
 
 	/*
 	 * 1. When struct size is different, converts the command.
 	 */
 	switch (cmd) {
-	case VIDIOC_G_FMT32: cmd = VIDIOC_G_FMT; break;
-	case VIDIOC_S_FMT32: cmd = VIDIOC_S_FMT; break;
-	case VIDIOC_QUERYBUF32: cmd = VIDIOC_QUERYBUF; break;
-	case VIDIOC_G_FBUF32: cmd = VIDIOC_G_FBUF; break;
-	case VIDIOC_S_FBUF32: cmd = VIDIOC_S_FBUF; break;
-	case VIDIOC_QBUF32: cmd = VIDIOC_QBUF; break;
-	case VIDIOC_DQBUF32: cmd = VIDIOC_DQBUF; break;
-	case VIDIOC_ENUMSTD32: cmd = VIDIOC_ENUMSTD; break;
-	case VIDIOC_ENUMINPUT32: cmd = VIDIOC_ENUMINPUT; break;
-	case VIDIOC_TRY_FMT32: cmd = VIDIOC_TRY_FMT; break;
-	case VIDIOC_G_EXT_CTRLS32: cmd = VIDIOC_G_EXT_CTRLS; break;
-	case VIDIOC_S_EXT_CTRLS32: cmd = VIDIOC_S_EXT_CTRLS; break;
-	case VIDIOC_TRY_EXT_CTRLS32: cmd = VIDIOC_TRY_EXT_CTRLS; break;
-	case VIDIOC_DQEVENT32: cmd = VIDIOC_DQEVENT; break;
-	case VIDIOC_OVERLAY32: cmd = VIDIOC_OVERLAY; break;
-	case VIDIOC_STREAMON32: cmd = VIDIOC_STREAMON; break;
-	case VIDIOC_STREAMOFF32: cmd = VIDIOC_STREAMOFF; break;
-	case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break;
-	case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break;
-	case VIDIOC_G_OUTPUT32: cmd = VIDIOC_G_OUTPUT; break;
-	case VIDIOC_S_OUTPUT32: cmd = VIDIOC_S_OUTPUT; break;
-	case VIDIOC_CREATE_BUFS32: cmd = VIDIOC_CREATE_BUFS; break;
-	case VIDIOC_PREPARE_BUF32: cmd = VIDIOC_PREPARE_BUF; break;
-	case VIDIOC_G_EDID32: cmd = VIDIOC_G_EDID; break;
-	case VIDIOC_S_EDID32: cmd = VIDIOC_S_EDID; break;
+	case VIDIOC_G_FMT32: ncmd = VIDIOC_G_FMT; break;
+	case VIDIOC_S_FMT32: ncmd = VIDIOC_S_FMT; break;
+	case VIDIOC_QUERYBUF32: ncmd = VIDIOC_QUERYBUF; break;
+	case VIDIOC_G_FBUF32: ncmd = VIDIOC_G_FBUF; break;
+	case VIDIOC_S_FBUF32: ncmd = VIDIOC_S_FBUF; break;
+	case VIDIOC_QBUF32: ncmd = VIDIOC_QBUF; break;
+	case VIDIOC_DQBUF32: ncmd = VIDIOC_DQBUF; break;
+	case VIDIOC_ENUMSTD32: ncmd = VIDIOC_ENUMSTD; break;
+	case VIDIOC_ENUMINPUT32: ncmd = VIDIOC_ENUMINPUT; break;
+	case VIDIOC_TRY_FMT32: ncmd = VIDIOC_TRY_FMT; break;
+	case VIDIOC_G_EXT_CTRLS32: ncmd = VIDIOC_G_EXT_CTRLS; break;
+	case VIDIOC_S_EXT_CTRLS32: ncmd = VIDIOC_S_EXT_CTRLS; break;
+	case VIDIOC_TRY_EXT_CTRLS32: ncmd = VIDIOC_TRY_EXT_CTRLS; break;
+	case VIDIOC_DQEVENT32: ncmd = VIDIOC_DQEVENT; break;
+	case VIDIOC_OVERLAY32: ncmd = VIDIOC_OVERLAY; break;
+	case VIDIOC_STREAMON32: ncmd = VIDIOC_STREAMON; break;
+	case VIDIOC_STREAMOFF32: ncmd = VIDIOC_STREAMOFF; break;
+	case VIDIOC_G_INPUT32: ncmd = VIDIOC_G_INPUT; break;
+	case VIDIOC_S_INPUT32: ncmd = VIDIOC_S_INPUT; break;
+	case VIDIOC_G_OUTPUT32: ncmd = VIDIOC_G_OUTPUT; break;
+	case VIDIOC_S_OUTPUT32: ncmd = VIDIOC_S_OUTPUT; break;
+	case VIDIOC_CREATE_BUFS32: ncmd = VIDIOC_CREATE_BUFS; break;
+	case VIDIOC_PREPARE_BUF32: ncmd = VIDIOC_PREPARE_BUF; break;
+	case VIDIOC_G_EDID32: ncmd = VIDIOC_G_EDID; break;
+	case VIDIOC_S_EDID32: ncmd = VIDIOC_S_EDID; break;
+	default: ncmd = cmd; break;
 	}
 
 	/*
@@ -1221,11 +1223,11 @@
 	 * argument into it.
 	 */
 	switch (cmd) {
-	case VIDIOC_OVERLAY:
-	case VIDIOC_STREAMON:
-	case VIDIOC_STREAMOFF:
-	case VIDIOC_S_INPUT:
-	case VIDIOC_S_OUTPUT:
+	case VIDIOC_OVERLAY32:
+	case VIDIOC_STREAMON32:
+	case VIDIOC_STREAMOFF32:
+	case VIDIOC_S_INPUT32:
+	case VIDIOC_S_OUTPUT32:
 		err = alloc_userspace(sizeof(unsigned int), 0, &new_p64);
 		if (!err && assign_in_user((unsigned int __user *)new_p64,
 					   (compat_uint_t __user *)p32))
@@ -1233,23 +1235,23 @@
 		compatible_arg = 0;
 		break;
 
-	case VIDIOC_G_INPUT:
-	case VIDIOC_G_OUTPUT:
+	case VIDIOC_G_INPUT32:
+	case VIDIOC_G_OUTPUT32:
 		err = alloc_userspace(sizeof(unsigned int), 0, &new_p64);
 		compatible_arg = 0;
 		break;
 
-	case VIDIOC_G_EDID:
-	case VIDIOC_S_EDID:
+	case VIDIOC_G_EDID32:
+	case VIDIOC_S_EDID32:
 		err = alloc_userspace(sizeof(struct v4l2_edid), 0, &new_p64);
 		if (!err)
 			err = get_v4l2_edid32(new_p64, p32);
 		compatible_arg = 0;
 		break;
 
-	case VIDIOC_G_FMT:
-	case VIDIOC_S_FMT:
-	case VIDIOC_TRY_FMT:
+	case VIDIOC_G_FMT32:
+	case VIDIOC_S_FMT32:
+	case VIDIOC_TRY_FMT32:
 		err = bufsize_v4l2_format(p32, &aux_space);
 		if (!err)
 			err = alloc_userspace(sizeof(struct v4l2_format),
@@ -1262,7 +1264,7 @@
 		compatible_arg = 0;
 		break;
 
-	case VIDIOC_CREATE_BUFS:
+	case VIDIOC_CREATE_BUFS32:
 		err = bufsize_v4l2_create(p32, &aux_space);
 		if (!err)
 			err = alloc_userspace(sizeof(struct v4l2_create_buffers),
@@ -1275,10 +1277,10 @@
 		compatible_arg = 0;
 		break;
 
-	case VIDIOC_PREPARE_BUF:
-	case VIDIOC_QUERYBUF:
-	case VIDIOC_QBUF:
-	case VIDIOC_DQBUF:
+	case VIDIOC_PREPARE_BUF32:
+	case VIDIOC_QUERYBUF32:
+	case VIDIOC_QBUF32:
+	case VIDIOC_DQBUF32:
 		err = bufsize_v4l2_buffer(p32, &aux_space);
 		if (!err)
 			err = alloc_userspace(sizeof(struct v4l2_buffer),
@@ -1291,7 +1293,7 @@
 		compatible_arg = 0;
 		break;
 
-	case VIDIOC_S_FBUF:
+	case VIDIOC_S_FBUF32:
 		err = alloc_userspace(sizeof(struct v4l2_framebuffer), 0,
 				      &new_p64);
 		if (!err)
@@ -1299,13 +1301,13 @@
 		compatible_arg = 0;
 		break;
 
-	case VIDIOC_G_FBUF:
+	case VIDIOC_G_FBUF32:
 		err = alloc_userspace(sizeof(struct v4l2_framebuffer), 0,
 				      &new_p64);
 		compatible_arg = 0;
 		break;
 
-	case VIDIOC_ENUMSTD:
+	case VIDIOC_ENUMSTD32:
 		err = alloc_userspace(sizeof(struct v4l2_standard), 0,
 				      &new_p64);
 		if (!err)
@@ -1313,16 +1315,16 @@
 		compatible_arg = 0;
 		break;
 
-	case VIDIOC_ENUMINPUT:
+	case VIDIOC_ENUMINPUT32:
 		err = alloc_userspace(sizeof(struct v4l2_input), 0, &new_p64);
 		if (!err)
 			err = get_v4l2_input32(new_p64, p32);
 		compatible_arg = 0;
 		break;
 
-	case VIDIOC_G_EXT_CTRLS:
-	case VIDIOC_S_EXT_CTRLS:
-	case VIDIOC_TRY_EXT_CTRLS:
+	case VIDIOC_G_EXT_CTRLS32:
+	case VIDIOC_S_EXT_CTRLS32:
+	case VIDIOC_TRY_EXT_CTRLS32:
 		err = bufsize_v4l2_ext_controls(p32, &aux_space);
 		if (!err)
 			err = alloc_userspace(sizeof(struct v4l2_ext_controls),
@@ -1334,7 +1336,7 @@
 		}
 		compatible_arg = 0;
 		break;
-	case VIDIOC_DQEVENT:
+	case VIDIOC_DQEVENT32:
 		err = alloc_userspace(sizeof(struct v4l2_event), 0, &new_p64);
 		compatible_arg = 0;
 		break;
@@ -1352,9 +1354,9 @@
 	 * Otherwise, it will pass the newly allocated @new_p64 argument.
 	 */
 	if (compatible_arg)
-		err = native_ioctl(file, cmd, (unsigned long)p32);
+		err = native_ioctl(file, ncmd, (unsigned long)p32);
 	else
-		err = native_ioctl(file, cmd, (unsigned long)new_p64);
+		err = native_ioctl(file, ncmd, (unsigned long)new_p64);
 
 	if (err == -ENOTTY)
 		return err;
@@ -1370,13 +1372,13 @@
 	 * the blocks to maximum allowed value.
 	 */
 	switch (cmd) {
-	case VIDIOC_G_EXT_CTRLS:
-	case VIDIOC_S_EXT_CTRLS:
-	case VIDIOC_TRY_EXT_CTRLS:
+	case VIDIOC_G_EXT_CTRLS32:
+	case VIDIOC_S_EXT_CTRLS32:
+	case VIDIOC_TRY_EXT_CTRLS32:
 		if (put_v4l2_ext_controls32(file, new_p64, p32))
 			err = -EFAULT;
 		break;
-	case VIDIOC_S_EDID:
+	case VIDIOC_S_EDID32:
 		if (put_v4l2_edid32(new_p64, p32))
 			err = -EFAULT;
 		break;
@@ -1389,49 +1391,49 @@
 	 * the original 32 bits structure.
 	 */
 	switch (cmd) {
-	case VIDIOC_S_INPUT:
-	case VIDIOC_S_OUTPUT:
-	case VIDIOC_G_INPUT:
-	case VIDIOC_G_OUTPUT:
+	case VIDIOC_S_INPUT32:
+	case VIDIOC_S_OUTPUT32:
+	case VIDIOC_G_INPUT32:
+	case VIDIOC_G_OUTPUT32:
 		if (assign_in_user((compat_uint_t __user *)p32,
 				   ((unsigned int __user *)new_p64)))
 			err = -EFAULT;
 		break;
 
-	case VIDIOC_G_FBUF:
+	case VIDIOC_G_FBUF32:
 		err = put_v4l2_framebuffer32(new_p64, p32);
 		break;
 
-	case VIDIOC_DQEVENT:
+	case VIDIOC_DQEVENT32:
 		err = put_v4l2_event32(new_p64, p32);
 		break;
 
-	case VIDIOC_G_EDID:
+	case VIDIOC_G_EDID32:
 		err = put_v4l2_edid32(new_p64, p32);
 		break;
 
-	case VIDIOC_G_FMT:
-	case VIDIOC_S_FMT:
-	case VIDIOC_TRY_FMT:
+	case VIDIOC_G_FMT32:
+	case VIDIOC_S_FMT32:
+	case VIDIOC_TRY_FMT32:
 		err = put_v4l2_format32(new_p64, p32);
 		break;
 
-	case VIDIOC_CREATE_BUFS:
+	case VIDIOC_CREATE_BUFS32:
 		err = put_v4l2_create32(new_p64, p32);
 		break;
 
-	case VIDIOC_PREPARE_BUF:
-	case VIDIOC_QUERYBUF:
-	case VIDIOC_QBUF:
-	case VIDIOC_DQBUF:
+	case VIDIOC_PREPARE_BUF32:
+	case VIDIOC_QUERYBUF32:
+	case VIDIOC_QBUF32:
+	case VIDIOC_DQBUF32:
 		err = put_v4l2_buffer32(new_p64, p32);
 		break;
 
-	case VIDIOC_ENUMSTD:
+	case VIDIOC_ENUMSTD32:
 		err = put_v4l2_standard32(new_p64, p32);
 		break;
 
-	case VIDIOC_ENUMINPUT:
+	case VIDIOC_ENUMINPUT32:
 		err = put_v4l2_input32(new_p64, p32);
 		break;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/v4l2-core/v4l2-ctrls.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -1795,7 +1795,8 @@
 	case V4L2_CTRL_TYPE_INTEGER_MENU:
 		if (ptr.p_s32[idx] < ctrl->minimum || ptr.p_s32[idx] > ctrl->maximum)
 			return -ERANGE;
-		if (ctrl->menu_skip_mask & (1ULL << ptr.p_s32[idx]))
+		if (ptr.p_s32[idx] < BITS_PER_LONG_LONG &&
+		    (ctrl->menu_skip_mask & BIT_ULL(ptr.p_s32[idx])))
 			return -EINVAL;
 		if (ctrl->type == V4L2_CTRL_TYPE_MENU &&
 		    ctrl->qmenu[ptr.p_s32[idx]][0] == '\0')
@@ -2154,7 +2155,15 @@
 	if (hdl == NULL || hdl->buckets == NULL)
 		return;
 
-	if (!hdl->req_obj.req && !list_empty(&hdl->requests)) {
+	/*
+	 * If the main handler is freed and it is used by handler objects in
+	 * outstanding requests, then unbind and put those objects before
+	 * freeing the main handler.
+	 *
+	 * The main handler can be identified by having a NULL ops pointer in
+	 * the request object.
+	 */
+	if (!hdl->req_obj.ops && !list_empty(&hdl->requests)) {
 		struct v4l2_ctrl_handler *req, *next_req;
 
 		list_for_each_entry_safe(req, next_req, &hdl->requests, requests) {
@@ -3144,6 +3153,7 @@
 	struct v4l2_ctrl_handler *prev_hdl = NULL;
 	struct v4l2_ctrl_ref *ref_ctrl, *ref_ctrl_prev = NULL;
 
+	mutex_lock(main_hdl->lock);
 	if (list_empty(&main_hdl->requests_queued))
 		goto queue;
 
@@ -3175,18 +3185,22 @@
 queue:
 	list_add_tail(&hdl->requests_queued, &main_hdl->requests_queued);
 	hdl->request_is_queued = true;
+	mutex_unlock(main_hdl->lock);
 }
 
 static void v4l2_ctrl_request_unbind(struct media_request_object *obj)
 {
 	struct v4l2_ctrl_handler *hdl =
 		container_of(obj, struct v4l2_ctrl_handler, req_obj);
+	struct v4l2_ctrl_handler *main_hdl = obj->priv;
 
+	mutex_lock(main_hdl->lock);
 	list_del_init(&hdl->requests);
 	if (hdl->request_is_queued) {
 		list_del_init(&hdl->requests_queued);
 		hdl->request_is_queued = false;
 	}
+	mutex_unlock(main_hdl->lock);
 }
 
 static void v4l2_ctrl_request_release(struct media_request_object *obj)
@@ -3240,8 +3254,11 @@
 	if (!ret) {
 		ret = media_request_object_bind(req, &req_ops,
 						from, false, &hdl->req_obj);
-		if (!ret)
+		if (!ret) {
+			mutex_lock(from->lock);
 			list_add_tail(&hdl->requests, &from->requests);
+			mutex_unlock(from->lock);
+		}
 	}
 	return ret;
 }
@@ -4128,9 +4145,11 @@
 		v4l2_ctrl_unlock(ctrl);
 	}
 
+	mutex_lock(main_hdl->lock);
 	WARN_ON(!hdl->request_is_queued);
 	list_del_init(&hdl->requests_queued);
 	hdl->request_is_queued = false;
+	mutex_unlock(main_hdl->lock);
 	media_request_object_complete(obj);
 	media_request_object_put(obj);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/v4l2-core/v4l2-dev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/v4l2-core/v4l2-dev.c
@@ -533,13 +533,23 @@
  */
 static void determine_valid_ioctls(struct video_device *vdev)
 {
+	const u32 vid_caps = V4L2_CAP_VIDEO_CAPTURE |
+			     V4L2_CAP_VIDEO_CAPTURE_MPLANE |
+			     V4L2_CAP_VIDEO_OUTPUT |
+			     V4L2_CAP_VIDEO_OUTPUT_MPLANE |
+			     V4L2_CAP_VIDEO_M2M | V4L2_CAP_VIDEO_M2M_MPLANE;
+	const u32 meta_caps = V4L2_CAP_META_CAPTURE |
+			      V4L2_CAP_META_OUTPUT;
 	DECLARE_BITMAP(valid_ioctls, BASE_VIDIOC_PRIVATE);
 	const struct v4l2_ioctl_ops *ops = vdev->ioctl_ops;
-	bool is_vid = vdev->vfl_type == VFL_TYPE_GRABBER;
+	bool is_vid = vdev->vfl_type == VFL_TYPE_VIDEO &&
+		      (vdev->device_caps & vid_caps);
 	bool is_vbi = vdev->vfl_type == VFL_TYPE_VBI;
 	bool is_radio = vdev->vfl_type == VFL_TYPE_RADIO;
 	bool is_sdr = vdev->vfl_type == VFL_TYPE_SDR;
 	bool is_tch = vdev->vfl_type == VFL_TYPE_TOUCH;
+	bool is_meta = vdev->vfl_type == VFL_TYPE_VIDEO &&
+		       (vdev->device_caps & meta_caps);
 	bool is_rx = vdev->vfl_dir != VFL_DIR_TX;
 	bool is_tx = vdev->vfl_dir != VFL_DIR_RX;
 
@@ -587,39 +597,31 @@
 		set_bit(_IOC_NR(VIDIOC_ENUM_FREQ_BANDS), valid_ioctls);
 
 	if (is_vid || is_tch) {
-		/* video and metadata specific ioctls */
+		/* video and touch specific ioctls */
 		if ((is_rx && (ops->vidioc_enum_fmt_vid_cap ||
-			       ops->vidioc_enum_fmt_vid_overlay ||
-			       ops->vidioc_enum_fmt_meta_cap)) ||
-		    (is_tx && (ops->vidioc_enum_fmt_vid_out ||
-			       ops->vidioc_enum_fmt_meta_out)))
+			       ops->vidioc_enum_fmt_vid_overlay)) ||
+		    (is_tx && ops->vidioc_enum_fmt_vid_out))
 			set_bit(_IOC_NR(VIDIOC_ENUM_FMT), valid_ioctls);
 		if ((is_rx && (ops->vidioc_g_fmt_vid_cap ||
 			       ops->vidioc_g_fmt_vid_cap_mplane ||
-			       ops->vidioc_g_fmt_vid_overlay ||
-			       ops->vidioc_g_fmt_meta_cap)) ||
+			       ops->vidioc_g_fmt_vid_overlay)) ||
 		    (is_tx && (ops->vidioc_g_fmt_vid_out ||
 			       ops->vidioc_g_fmt_vid_out_mplane ||
-			       ops->vidioc_g_fmt_vid_out_overlay ||
-			       ops->vidioc_g_fmt_meta_out)))
+			       ops->vidioc_g_fmt_vid_out_overlay)))
 			 set_bit(_IOC_NR(VIDIOC_G_FMT), valid_ioctls);
 		if ((is_rx && (ops->vidioc_s_fmt_vid_cap ||
 			       ops->vidioc_s_fmt_vid_cap_mplane ||
-			       ops->vidioc_s_fmt_vid_overlay ||
-			       ops->vidioc_s_fmt_meta_cap)) ||
+			       ops->vidioc_s_fmt_vid_overlay)) ||
 		    (is_tx && (ops->vidioc_s_fmt_vid_out ||
 			       ops->vidioc_s_fmt_vid_out_mplane ||
-			       ops->vidioc_s_fmt_vid_out_overlay ||
-			       ops->vidioc_s_fmt_meta_out)))
+			       ops->vidioc_s_fmt_vid_out_overlay)))
 			 set_bit(_IOC_NR(VIDIOC_S_FMT), valid_ioctls);
 		if ((is_rx && (ops->vidioc_try_fmt_vid_cap ||
 			       ops->vidioc_try_fmt_vid_cap_mplane ||
-			       ops->vidioc_try_fmt_vid_overlay ||
-			       ops->vidioc_try_fmt_meta_cap)) ||
+			       ops->vidioc_try_fmt_vid_overlay)) ||
 		    (is_tx && (ops->vidioc_try_fmt_vid_out ||
 			       ops->vidioc_try_fmt_vid_out_mplane ||
-			       ops->vidioc_try_fmt_vid_out_overlay ||
-			       ops->vidioc_try_fmt_meta_out)))
+			       ops->vidioc_try_fmt_vid_out_overlay)))
 			 set_bit(_IOC_NR(VIDIOC_TRY_FMT), valid_ioctls);
 		SET_VALID_IOCTL(ops, VIDIOC_OVERLAY, vidioc_overlay);
 		SET_VALID_IOCTL(ops, VIDIOC_G_FBUF, vidioc_g_fbuf);
@@ -641,7 +643,21 @@
 			set_bit(_IOC_NR(VIDIOC_S_CROP), valid_ioctls);
 		SET_VALID_IOCTL(ops, VIDIOC_G_SELECTION, vidioc_g_selection);
 		SET_VALID_IOCTL(ops, VIDIOC_S_SELECTION, vidioc_s_selection);
-	} else if (is_vbi) {
+	}
+	if (is_meta && is_rx) {
+		/* metadata capture specific ioctls */
+		SET_VALID_IOCTL(ops, VIDIOC_ENUM_FMT, vidioc_enum_fmt_meta_cap);
+		SET_VALID_IOCTL(ops, VIDIOC_G_FMT, vidioc_g_fmt_meta_cap);
+		SET_VALID_IOCTL(ops, VIDIOC_S_FMT, vidioc_s_fmt_meta_cap);
+		SET_VALID_IOCTL(ops, VIDIOC_TRY_FMT, vidioc_try_fmt_meta_cap);
+	} else if (is_meta && is_tx) {
+		/* metadata output specific ioctls */
+		SET_VALID_IOCTL(ops, VIDIOC_ENUM_FMT, vidioc_enum_fmt_meta_out);
+		SET_VALID_IOCTL(ops, VIDIOC_G_FMT, vidioc_g_fmt_meta_out);
+		SET_VALID_IOCTL(ops, VIDIOC_S_FMT, vidioc_s_fmt_meta_out);
+		SET_VALID_IOCTL(ops, VIDIOC_TRY_FMT, vidioc_try_fmt_meta_out);
+	}
+	if (is_vbi) {
 		/* vbi specific ioctls */
 		if ((is_rx && (ops->vidioc_g_fmt_vbi_cap ||
 			       ops->vidioc_g_fmt_sliced_vbi_cap)) ||
@@ -681,8 +697,8 @@
 			set_bit(_IOC_NR(VIDIOC_TRY_FMT), valid_ioctls);
 	}
 
-	if (is_vid || is_vbi || is_sdr || is_tch) {
-		/* ioctls valid for video, metadata, vbi or sdr */
+	if (is_vid || is_vbi || is_sdr || is_tch || is_meta) {
+		/* ioctls valid for video, vbi, sdr, touch and metadata */
 		SET_VALID_IOCTL(ops, VIDIOC_REQBUFS, vidioc_reqbufs);
 		SET_VALID_IOCTL(ops, VIDIOC_QUERYBUF, vidioc_querybuf);
 		SET_VALID_IOCTL(ops, VIDIOC_QBUF, vidioc_qbuf);
@@ -694,8 +710,8 @@
 		SET_VALID_IOCTL(ops, VIDIOC_STREAMOFF, vidioc_streamoff);
 	}
 
-	if (is_vid || is_vbi || is_tch) {
-		/* ioctls valid for video or vbi */
+	if (is_vid || is_vbi || is_tch || is_meta) {
+		/* ioctls valid for video, vbi, touch and metadata */
 		if (ops->vidioc_s_std)
 			set_bit(_IOC_NR(VIDIOC_ENUMSTD), valid_ioctls);
 		SET_VALID_IOCTL(ops, VIDIOC_S_STD, vidioc_s_std);
@@ -761,7 +777,7 @@
 	vdev->entity.function = MEDIA_ENT_F_UNKNOWN;
 
 	switch (vdev->vfl_type) {
-	case VFL_TYPE_GRABBER:
+	case VFL_TYPE_VIDEO:
 		intf_type = MEDIA_INTF_T_V4L_VIDEO;
 		vdev->entity.function = MEDIA_ENT_F_IO_V4L;
 		break;
@@ -869,7 +885,7 @@
 
 	/* Part 1: check device type */
 	switch (type) {
-	case VFL_TYPE_GRABBER:
+	case VFL_TYPE_VIDEO:
 		name_base = "video";
 		break;
 	case VFL_TYPE_VBI:
@@ -913,7 +929,7 @@
 	 * of 128-191 and just pick the first free minor there
 	 * (new style). */
 	switch (type) {
-	case VFL_TYPE_GRABBER:
+	case VFL_TYPE_VIDEO:
 		minor_offset = 0;
 		minor_cnt = 64;
 		break;
@@ -995,8 +1011,10 @@
 	vdev->dev.devt = MKDEV(VIDEO_MAJOR, vdev->minor);
 	vdev->dev.parent = vdev->dev_parent;
 	dev_set_name(&vdev->dev, "%s%d", name_base, vdev->num);
+	mutex_lock(&videodev_lock);
 	ret = device_register(&vdev->dev);
 	if (ret < 0) {
+		mutex_unlock(&videodev_lock);
 		pr_err("%s: device_register failed\n", __func__);
 		goto cleanup;
 	}
@@ -1016,6 +1034,7 @@
 
 	/* Part 6: Activate this minor. The char device can now be used. */
 	set_bit(V4L2_FL_REGISTERED, &vdev->flags);
+	mutex_unlock(&videodev_lock);
 
 	return 0;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/v4l2-core/v4l2-device.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/v4l2-core/v4l2-device.c
@@ -179,6 +179,7 @@
 
 	if (sd->internal_ops && sd->internal_ops->release)
 		sd->internal_ops->release(sd);
+	sd->devnode = NULL;
 	module_put(owner);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/v4l2-core/v4l2-dv-timings.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/v4l2-core/v4l2-dv-timings.c
@@ -145,6 +145,8 @@
 	const struct v4l2_bt_timings *bt = &t->bt;
 	const struct v4l2_bt_timings_cap *cap = &dvcap->bt;
 	u32 caps = cap->capabilities;
+	const u32 max_vert = 10240;
+	u32 max_hor = 3 * bt->width;
 
 	if (t->type != V4L2_DV_BT_656_1120)
 		return false;
@@ -161,6 +163,26 @@
 	    (bt->interlaced && !(caps & V4L2_DV_BT_CAP_INTERLACED)) ||
 	    (!bt->interlaced && !(caps & V4L2_DV_BT_CAP_PROGRESSIVE)))
 		return false;
+
+	/* sanity checks for the blanking timings */
+	if (!bt->interlaced &&
+	    (bt->il_vbackporch || bt->il_vsync || bt->il_vfrontporch))
+		return false;
+	/*
+	 * Some video receivers cannot properly separate the frontporch,
+	 * backporch and sync values, and instead they only have the total
+	 * blanking. That can be assigned to any of these three fields.
+	 * So just check that none of these are way out of range.
+	 */
+	if (bt->hfrontporch > max_hor ||
+	    bt->hsync > max_hor || bt->hbackporch > max_hor)
+		return false;
+	if (bt->vfrontporch > max_vert ||
+	    bt->vsync > max_vert || bt->vbackporch > max_vert)
+		return false;
+	if (bt->interlaced && (bt->il_vfrontporch > max_vert ||
+	    bt->il_vsync > max_vert || bt->il_vbackporch > max_vert))
+		return false;
 	return fnc == NULL || fnc(t, fnc_handle);
 }
 EXPORT_SYMBOL_GPL(v4l2_valid_dv_timings);
@@ -196,7 +218,7 @@
 	if (!v4l2_valid_dv_timings(t, cap, fnc, fnc_handle))
 		return false;
 
-	for (i = 0; i < v4l2_dv_timings_presets[i].bt.width; i++) {
+	for (i = 0; v4l2_dv_timings_presets[i].bt.width; i++) {
 		if (v4l2_valid_dv_timings(v4l2_dv_timings_presets + i, cap,
 					  fnc, fnc_handle) &&
 		    v4l2_match_dv_timings(t, v4l2_dv_timings_presets + i,
@@ -218,7 +240,7 @@
 {
 	unsigned int i;
 
-	for (i = 0; i < v4l2_dv_timings_presets[i].bt.width; i++) {
+	for (i = 0; v4l2_dv_timings_presets[i].bt.width; i++) {
 		const struct v4l2_bt_timings *bt =
 			&v4l2_dv_timings_presets[i].bt;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/v4l2-core/v4l2-fh.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/v4l2-core/v4l2-fh.c
@@ -96,6 +96,7 @@
 		v4l2_fh_del(fh);
 		v4l2_fh_exit(fh);
 		kfree(fh);
+		filp->private_data = NULL;
 	}
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/v4l2-core/v4l2-fwnode.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/v4l2-core/v4l2-fwnode.c
@@ -93,7 +93,7 @@
 	const struct v4l2_fwnode_bus_conv *conv =
 		get_v4l2_fwnode_bus_conv_by_fwnode_bus(type);
 
-	return conv ? conv->mbus_type : V4L2_MBUS_UNKNOWN;
+	return conv ? conv->mbus_type : V4L2_MBUS_INVALID;
 }
 
 static const char *
@@ -436,6 +436,10 @@
 		 v4l2_fwnode_mbus_type_to_string(vep->bus_type),
 		 vep->bus_type);
 	mbus_type = v4l2_fwnode_bus_type_to_mbus(bus_type);
+	if (mbus_type == V4L2_MBUS_INVALID) {
+		pr_debug("unsupported bus type %u\n", bus_type);
+		return -EINVAL;
+	}
 
 	if (vep->bus_type != V4L2_MBUS_UNKNOWN) {
 		if (mbus_type != V4L2_MBUS_UNKNOWN &&
@@ -556,35 +560,38 @@
 }
 EXPORT_SYMBOL_GPL(v4l2_fwnode_endpoint_alloc_parse);
 
-int v4l2_fwnode_parse_link(struct fwnode_handle *__fwnode,
+int v4l2_fwnode_parse_link(struct fwnode_handle *fwnode,
 			   struct v4l2_fwnode_link *link)
 {
-	const char *port_prop = is_of_node(__fwnode) ? "reg" : "port";
-	struct fwnode_handle *fwnode;
+	struct fwnode_endpoint fwep;
 
 	memset(link, 0, sizeof(*link));
 
-	fwnode = fwnode_get_parent(__fwnode);
-	fwnode_property_read_u32(fwnode, port_prop, &link->local_port);
-	fwnode = fwnode_get_next_parent(fwnode);
-	if (is_of_node(fwnode) && of_node_name_eq(to_of_node(fwnode), "ports"))
-		fwnode = fwnode_get_next_parent(fwnode);
-	link->local_node = fwnode;
-
-	fwnode = fwnode_graph_get_remote_endpoint(__fwnode);
-	if (!fwnode) {
-		fwnode_handle_put(fwnode);
+	fwnode_graph_parse_endpoint(fwnode, &fwep);
+	link->local_port = fwep.port;
+	link->local_node = fwnode_graph_get_port_parent(fwnode);
+	if (!link->local_node)
 		return -ENOLINK;
-	}
 
-	fwnode = fwnode_get_parent(fwnode);
-	fwnode_property_read_u32(fwnode, port_prop, &link->remote_port);
-	fwnode = fwnode_get_next_parent(fwnode);
-	if (is_of_node(fwnode) && of_node_name_eq(to_of_node(fwnode), "ports"))
-		fwnode = fwnode_get_next_parent(fwnode);
-	link->remote_node = fwnode;
+	fwnode = fwnode_graph_get_remote_endpoint(fwnode);
+	if (!fwnode)
+		goto err_put_local_node;
+
+	fwnode_graph_parse_endpoint(fwnode, &fwep);
+	link->remote_port = fwep.port;
+	link->remote_node = fwnode_graph_get_port_parent(fwnode);
+	if (!link->remote_node)
+		goto err_put_remote_endpoint;
 
 	return 0;
+
+err_put_remote_endpoint:
+	fwnode_handle_put(fwnode);
+
+err_put_local_node:
+	fwnode_handle_put(link->local_node);
+
+	return -ENOLINK;
 }
 EXPORT_SYMBOL_GPL(v4l2_fwnode_parse_link);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/v4l2-core/v4l2-ioctl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/version.h>
 
+#include <linux/v4l2-subdev.h>
 #include <linux/videodev2.h>
 
 #include <media/v4l2-common.h>
@@ -902,7 +903,7 @@
 	pr_cont("driver-specific ioctl\n");
 }
 
-static int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv)
+static bool check_ext_ctrls(struct v4l2_ext_controls *c, unsigned long ioctl)
 {
 	__u32 i;
 
@@ -911,33 +912,61 @@
 	for (i = 0; i < c->count; i++)
 		c->controls[i].reserved2[0] = 0;
 
-	/* V4L2_CID_PRIVATE_BASE cannot be used as control class
-	   when using extended controls.
-	   Only when passed in through VIDIOC_G_CTRL and VIDIOC_S_CTRL
-	   is it allowed for backwards compatibility.
-	 */
-	if (!allow_priv && c->which == V4L2_CID_PRIVATE_BASE)
-		return 0;
-	if (!c->which)
-		return 1;
+	switch (c->which) {
+	case V4L2_CID_PRIVATE_BASE:
+		/*
+		 * V4L2_CID_PRIVATE_BASE cannot be used as control class
+		 * when using extended controls.
+		 * Only when passed in through VIDIOC_G_CTRL and VIDIOC_S_CTRL
+		 * is it allowed for backwards compatibility.
+		 */
+		if (ioctl == VIDIOC_G_CTRL || ioctl == VIDIOC_S_CTRL)
+			return false;
+		break;
+	case V4L2_CTRL_WHICH_DEF_VAL:
+		/* Default value cannot be changed */
+		if (ioctl == VIDIOC_S_EXT_CTRLS ||
+		    ioctl == VIDIOC_TRY_EXT_CTRLS) {
+			c->error_idx = c->count;
+			return false;
+		}
+		return true;
+	case V4L2_CTRL_WHICH_CUR_VAL:
+		return true;
+	case V4L2_CTRL_WHICH_REQUEST_VAL:
+		c->error_idx = c->count;
+		return false;
+	}
+
 	/* Check that all controls are from the same control class. */
 	for (i = 0; i < c->count; i++) {
 		if (V4L2_CTRL_ID2WHICH(c->controls[i].id) != c->which) {
-			c->error_idx = i;
-			return 0;
+			c->error_idx = ioctl == VIDIOC_TRY_EXT_CTRLS ? i :
+								      c->count;
+			return false;
 		}
 	}
-	return 1;
+	return true;
 }
 
 static int check_fmt(struct file *file, enum v4l2_buf_type type)
 {
+	const u32 vid_caps = V4L2_CAP_VIDEO_CAPTURE |
+			     V4L2_CAP_VIDEO_CAPTURE_MPLANE |
+			     V4L2_CAP_VIDEO_OUTPUT |
+			     V4L2_CAP_VIDEO_OUTPUT_MPLANE |
+			     V4L2_CAP_VIDEO_M2M | V4L2_CAP_VIDEO_M2M_MPLANE;
+	const u32 meta_caps = V4L2_CAP_META_CAPTURE |
+			      V4L2_CAP_META_OUTPUT;
 	struct video_device *vfd = video_devdata(file);
 	const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
-	bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
+	bool is_vid = vfd->vfl_type == VFL_TYPE_VIDEO &&
+		      (vfd->device_caps & vid_caps);
 	bool is_vbi = vfd->vfl_type == VFL_TYPE_VBI;
 	bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
 	bool is_tch = vfd->vfl_type == VFL_TYPE_TOUCH;
+	bool is_meta = vfd->vfl_type == VFL_TYPE_VIDEO &&
+		       (vfd->device_caps & meta_caps);
 	bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
 	bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
 
@@ -996,11 +1025,11 @@
 			return 0;
 		break;
 	case V4L2_BUF_TYPE_META_CAPTURE:
-		if (is_vid && is_rx && ops->vidioc_g_fmt_meta_cap)
+		if (is_meta && is_rx && ops->vidioc_g_fmt_meta_cap)
 			return 0;
 		break;
 	case V4L2_BUF_TYPE_META_OUTPUT:
-		if (is_vid && is_tx && ops->vidioc_g_fmt_meta_out)
+		if (is_meta && is_tx && ops->vidioc_g_fmt_meta_out)
 			return 0;
 		break;
 	default:
@@ -1207,6 +1236,9 @@
 	case V4L2_PIX_FMT_BGRX32:	descr = "32-bit XBGR 8-8-8-8"; break;
 	case V4L2_PIX_FMT_RGBA32:	descr = "32-bit RGBA 8-8-8-8"; break;
 	case V4L2_PIX_FMT_RGBX32:	descr = "32-bit RGBX 8-8-8-8"; break;
+	case V4L2_PIX_FMT_XBGR30:	descr = "32-bit XBGR 2-10-10-10"; break;
+	case V4L2_PIX_FMT_XBGR40:	descr = "40-bit XBGR 4-12-12-12"; break;
+	case V4L2_PIX_FMT_BGR48:	descr = "48-bit BGR 16-16-16"; break;
 	case V4L2_PIX_FMT_GREY:		descr = "8-bit Greyscale"; break;
 	case V4L2_PIX_FMT_Y4:		descr = "4-bit Greyscale"; break;
 	case V4L2_PIX_FMT_Y6:		descr = "6-bit Greyscale"; break;
@@ -1234,6 +1266,9 @@
 	case V4L2_PIX_FMT_YUV411P:	descr = "Planar YUV 4:1:1"; break;
 	case V4L2_PIX_FMT_Y41P:		descr = "YUV 4:1:1 (Packed)"; break;
 	case V4L2_PIX_FMT_YUV444:	descr = "16-bit A/XYUV 4-4-4-4"; break;
+	case V4L2_PIX_FMT_XVUY32:	descr = "32-bit packed XVUY 8-8-8-8"; break;
+	case V4L2_PIX_FMT_AVUY32:	descr = "32-bit packed AVUY 8-8-8-8"; break;
+	case V4L2_PIX_FMT_VUY24:	descr = "24-bit packed VUY 8-8-8"; break;
 	case V4L2_PIX_FMT_YUV555:	descr = "16-bit A/XYUV 1-5-5-5"; break;
 	case V4L2_PIX_FMT_YUV565:	descr = "16-bit YUV 5-6-5"; break;
 	case V4L2_PIX_FMT_YUV32:	descr = "32-bit A/XYUV 8-8-8-8"; break;
@@ -1246,24 +1281,41 @@
 	case V4L2_PIX_FMT_HI240:	descr = "8-bit Dithered RGB (BTTV)"; break;
 	case V4L2_PIX_FMT_HM12:		descr = "YUV 4:2:0 (16x16 Macroblocks)"; break;
 	case V4L2_PIX_FMT_M420:		descr = "YUV 4:2:0 (M420)"; break;
+	case V4L2_PIX_FMT_XVUY10:	descr = "XVUY 2-10-10-10"; break;
 	case V4L2_PIX_FMT_NV12:		descr = "Y/CbCr 4:2:0"; break;
 	case V4L2_PIX_FMT_NV21:		descr = "Y/CrCb 4:2:0"; break;
 	case V4L2_PIX_FMT_NV16:		descr = "Y/CbCr 4:2:2"; break;
 	case V4L2_PIX_FMT_NV61:		descr = "Y/CrCb 4:2:2"; break;
 	case V4L2_PIX_FMT_NV24:		descr = "Y/CbCr 4:4:4"; break;
 	case V4L2_PIX_FMT_NV42:		descr = "Y/CrCb 4:4:4"; break;
+	case V4L2_PIX_FMT_XV15:         descr = "Y/CrCb 4:2:0 10-bit"; break;
+	case V4L2_PIX_FMT_XV20:		descr = "Y/CrCb 4:2:2 10-bit"; break;
 	case V4L2_PIX_FMT_NV12M:	descr = "Y/CbCr 4:2:0 (N-C)"; break;
 	case V4L2_PIX_FMT_NV21M:	descr = "Y/CrCb 4:2:0 (N-C)"; break;
 	case V4L2_PIX_FMT_NV16M:	descr = "Y/CbCr 4:2:2 (N-C)"; break;
 	case V4L2_PIX_FMT_NV61M:	descr = "Y/CrCb 4:2:2 (N-C)"; break;
 	case V4L2_PIX_FMT_NV12MT:	descr = "Y/CbCr 4:2:0 (64x32 MB, N-C)"; break;
 	case V4L2_PIX_FMT_NV12MT_16X16:	descr = "Y/CbCr 4:2:0 (16x16 MB, N-C)"; break;
+	case V4L2_PIX_FMT_XV20M:        descr = "Y/CrCb 4:2:2 10-bit (N-C)"; break;
+	case V4L2_PIX_FMT_XV15M:        descr = "Y/CrCb 4:2:0 10-bit (N-C)"; break;
 	case V4L2_PIX_FMT_YUV420M:	descr = "Planar YUV 4:2:0 (N-C)"; break;
 	case V4L2_PIX_FMT_YVU420M:	descr = "Planar YVU 4:2:0 (N-C)"; break;
 	case V4L2_PIX_FMT_YUV422M:	descr = "Planar YUV 4:2:2 (N-C)"; break;
 	case V4L2_PIX_FMT_YVU422M:	descr = "Planar YVU 4:2:2 (N-C)"; break;
 	case V4L2_PIX_FMT_YUV444M:	descr = "Planar YUV 4:4:4 (N-C)"; break;
 	case V4L2_PIX_FMT_YVU444M:	descr = "Planar YVU 4:4:4 (N-C)"; break;
+	case V4L2_PIX_FMT_X012:		descr = "Y/CbCr 4:2:0, 4-12-12-12"; break;
+	case V4L2_PIX_FMT_X012M:	descr = "Y/CbCr 4:2:0, 4-12-12-12 (N-C)"; break;
+	case V4L2_PIX_FMT_X212:		descr = "Y/CbCr 4:2:2, 4-12-12-12"; break;
+	case V4L2_PIX_FMT_X212M:	descr = "Y/CbCr 4:2:2, 4-12-12-12 (N-C)"; break;
+	case V4L2_PIX_FMT_X412:		descr = "Y/CbCr 4:4:4, 4-12-12-12"; break;
+	case V4L2_PIX_FMT_X412M:	descr = "Y/CbCr 4:4:4, 4-12-12-12 (N-C)"; break;
+	case V4L2_PIX_FMT_X016:		descr = "Y/CbCr 4:2:0, 16-16-16"; break;
+	case V4L2_PIX_FMT_X016M:	descr = "Y/CbCr 4:2:0, 16-16-16 (N-C)"; break;
+	case V4L2_PIX_FMT_X216:		descr = "Y/CbCr 4:2:2, 16-16-16"; break;
+	case V4L2_PIX_FMT_X216M:	descr = "Y/CbCr 4:2:2, 16-16-16 (N-C)"; break;
+	case V4L2_PIX_FMT_X416:		descr = "Y/CbCr 4:4:4, 16-16-16"; break;
+	case V4L2_PIX_FMT_X416M:	descr = "Y/CbCr 4:4:4, 16-16-16 (N-C)"; break;
 	case V4L2_PIX_FMT_SBGGR8:	descr = "8-bit Bayer BGBG/GRGR"; break;
 	case V4L2_PIX_FMT_SGBRG8:	descr = "8-bit Bayer GBGB/RGRG"; break;
 	case V4L2_PIX_FMT_SGRBG8:	descr = "8-bit Bayer GRGR/BGBG"; break;
@@ -1466,10 +1518,26 @@
 	return ret;
 }
 
+static void v4l_pix_format_touch(struct v4l2_pix_format *p)
+{
+	/*
+	 * The v4l2_pix_format structure contains fields that make no sense for
+	 * touch. Set them to default values in this case.
+	 */
+
+	p->field = V4L2_FIELD_NONE;
+	p->colorspace = V4L2_COLORSPACE_RAW;
+	p->flags = 0;
+	p->ycbcr_enc = 0;
+	p->quantization = 0;
+	p->xfer_func = 0;
+}
+
 static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops,
 				struct file *file, void *fh, void *arg)
 {
 	struct v4l2_format *p = arg;
+	struct video_device *vfd = video_devdata(file);
 	int ret = check_fmt(file, p->type);
 
 	if (ret)
@@ -1507,6 +1575,8 @@
 		ret = ops->vidioc_g_fmt_vid_cap(file, fh, arg);
 		/* just in case the driver zeroed it again */
 		p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+		if (vfd->vfl_type == VFL_TYPE_TOUCH)
+			v4l_pix_format_touch(&p->fmt.pix);
 		return ret;
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
 		return ops->vidioc_g_fmt_vid_cap_mplane(file, fh, arg);
@@ -1544,21 +1614,6 @@
 	return -EINVAL;
 }
 
-static void v4l_pix_format_touch(struct v4l2_pix_format *p)
-{
-	/*
-	 * The v4l2_pix_format structure contains fields that make no sense for
-	 * touch. Set them to default values in this case.
-	 */
-
-	p->field = V4L2_FIELD_NONE;
-	p->colorspace = V4L2_COLORSPACE_RAW;
-	p->flags = 0;
-	p->ycbcr_enc = 0;
-	p->quantization = 0;
-	p->xfer_func = 0;
-}
-
 static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
 				struct file *file, void *fh, void *arg)
 {
@@ -1602,12 +1657,12 @@
 	case V4L2_BUF_TYPE_VBI_CAPTURE:
 		if (unlikely(!ops->vidioc_s_fmt_vbi_cap))
 			break;
-		CLEAR_AFTER_FIELD(p, fmt.vbi);
+		CLEAR_AFTER_FIELD(p, fmt.vbi.flags);
 		return ops->vidioc_s_fmt_vbi_cap(file, fh, arg);
 	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
 		if (unlikely(!ops->vidioc_s_fmt_sliced_vbi_cap))
 			break;
-		CLEAR_AFTER_FIELD(p, fmt.sliced);
+		CLEAR_AFTER_FIELD(p, fmt.sliced.io_size);
 		return ops->vidioc_s_fmt_sliced_vbi_cap(file, fh, arg);
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
 		if (unlikely(!ops->vidioc_s_fmt_vid_out))
@@ -1633,22 +1688,22 @@
 	case V4L2_BUF_TYPE_VBI_OUTPUT:
 		if (unlikely(!ops->vidioc_s_fmt_vbi_out))
 			break;
-		CLEAR_AFTER_FIELD(p, fmt.vbi);
+		CLEAR_AFTER_FIELD(p, fmt.vbi.flags);
 		return ops->vidioc_s_fmt_vbi_out(file, fh, arg);
 	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
 		if (unlikely(!ops->vidioc_s_fmt_sliced_vbi_out))
 			break;
-		CLEAR_AFTER_FIELD(p, fmt.sliced);
+		CLEAR_AFTER_FIELD(p, fmt.sliced.io_size);
 		return ops->vidioc_s_fmt_sliced_vbi_out(file, fh, arg);
 	case V4L2_BUF_TYPE_SDR_CAPTURE:
 		if (unlikely(!ops->vidioc_s_fmt_sdr_cap))
 			break;
-		CLEAR_AFTER_FIELD(p, fmt.sdr);
+		CLEAR_AFTER_FIELD(p, fmt.sdr.buffersize);
 		return ops->vidioc_s_fmt_sdr_cap(file, fh, arg);
 	case V4L2_BUF_TYPE_SDR_OUTPUT:
 		if (unlikely(!ops->vidioc_s_fmt_sdr_out))
 			break;
-		CLEAR_AFTER_FIELD(p, fmt.sdr);
+		CLEAR_AFTER_FIELD(p, fmt.sdr.buffersize);
 		return ops->vidioc_s_fmt_sdr_out(file, fh, arg);
 	case V4L2_BUF_TYPE_META_CAPTURE:
 		if (unlikely(!ops->vidioc_s_fmt_meta_cap))
@@ -1704,12 +1759,12 @@
 	case V4L2_BUF_TYPE_VBI_CAPTURE:
 		if (unlikely(!ops->vidioc_try_fmt_vbi_cap))
 			break;
-		CLEAR_AFTER_FIELD(p, fmt.vbi);
+		CLEAR_AFTER_FIELD(p, fmt.vbi.flags);
 		return ops->vidioc_try_fmt_vbi_cap(file, fh, arg);
 	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
 		if (unlikely(!ops->vidioc_try_fmt_sliced_vbi_cap))
 			break;
-		CLEAR_AFTER_FIELD(p, fmt.sliced);
+		CLEAR_AFTER_FIELD(p, fmt.sliced.io_size);
 		return ops->vidioc_try_fmt_sliced_vbi_cap(file, fh, arg);
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
 		if (unlikely(!ops->vidioc_try_fmt_vid_out))
@@ -1735,22 +1790,22 @@
 	case V4L2_BUF_TYPE_VBI_OUTPUT:
 		if (unlikely(!ops->vidioc_try_fmt_vbi_out))
 			break;
-		CLEAR_AFTER_FIELD(p, fmt.vbi);
+		CLEAR_AFTER_FIELD(p, fmt.vbi.flags);
 		return ops->vidioc_try_fmt_vbi_out(file, fh, arg);
 	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
 		if (unlikely(!ops->vidioc_try_fmt_sliced_vbi_out))
 			break;
-		CLEAR_AFTER_FIELD(p, fmt.sliced);
+		CLEAR_AFTER_FIELD(p, fmt.sliced.io_size);
 		return ops->vidioc_try_fmt_sliced_vbi_out(file, fh, arg);
 	case V4L2_BUF_TYPE_SDR_CAPTURE:
 		if (unlikely(!ops->vidioc_try_fmt_sdr_cap))
 			break;
-		CLEAR_AFTER_FIELD(p, fmt.sdr);
+		CLEAR_AFTER_FIELD(p, fmt.sdr.buffersize);
 		return ops->vidioc_try_fmt_sdr_cap(file, fh, arg);
 	case V4L2_BUF_TYPE_SDR_OUTPUT:
 		if (unlikely(!ops->vidioc_try_fmt_sdr_out))
 			break;
-		CLEAR_AFTER_FIELD(p, fmt.sdr);
+		CLEAR_AFTER_FIELD(p, fmt.sdr.buffersize);
 		return ops->vidioc_try_fmt_sdr_out(file, fh, arg);
 	case V4L2_BUF_TYPE_META_CAPTURE:
 		if (unlikely(!ops->vidioc_try_fmt_meta_cap))
@@ -2025,6 +2080,7 @@
 static int v4l_g_parm(const struct v4l2_ioctl_ops *ops,
 				struct file *file, void *fh, void *arg)
 {
+	struct video_device *vfd = video_devdata(file);
 	struct v4l2_streamparm *p = arg;
 	v4l2_std_id std;
 	int ret = check_fmt(file, p->type);
@@ -2036,7 +2092,8 @@
 	if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
 	    p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
 		return -EINVAL;
-	p->parm.capture.readbuffers = 2;
+	if (vfd->device_caps & V4L2_CAP_READWRITE)
+		p->parm.capture.readbuffers = 2;
 	ret = ops->vidioc_g_std(file, fh, &std);
 	if (ret == 0)
 		v4l2_video_std_frame_period(std, &p->parm.capture.timeperframe);
@@ -2142,7 +2199,7 @@
 	ctrls.controls = &ctrl;
 	ctrl.id = p->id;
 	ctrl.value = p->value;
-	if (check_ext_ctrls(&ctrls, 1)) {
+	if (check_ext_ctrls(&ctrls, VIDIOC_G_CTRL)) {
 		int ret = ops->vidioc_g_ext_ctrls(file, fh, &ctrls);
 
 		if (ret == 0)
@@ -2176,7 +2233,7 @@
 	ctrls.controls = &ctrl;
 	ctrl.id = p->id;
 	ctrl.value = p->value;
-	if (check_ext_ctrls(&ctrls, 1))
+	if (check_ext_ctrls(&ctrls, VIDIOC_S_CTRL))
 		return ops->vidioc_s_ext_ctrls(file, fh, &ctrls);
 	return -EINVAL;
 }
@@ -2198,8 +2255,8 @@
 					vfd, vfd->v4l2_dev->mdev, p);
 	if (ops->vidioc_g_ext_ctrls == NULL)
 		return -ENOTTY;
-	return check_ext_ctrls(p, 0) ? ops->vidioc_g_ext_ctrls(file, fh, p) :
-					-EINVAL;
+	return check_ext_ctrls(p, VIDIOC_G_EXT_CTRLS) ?
+				ops->vidioc_g_ext_ctrls(file, fh, p) : -EINVAL;
 }
 
 static int v4l_s_ext_ctrls(const struct v4l2_ioctl_ops *ops,
@@ -2219,8 +2276,8 @@
 					vfd, vfd->v4l2_dev->mdev, p);
 	if (ops->vidioc_s_ext_ctrls == NULL)
 		return -ENOTTY;
-	return check_ext_ctrls(p, 0) ? ops->vidioc_s_ext_ctrls(file, fh, p) :
-					-EINVAL;
+	return check_ext_ctrls(p, VIDIOC_S_EXT_CTRLS) ?
+				ops->vidioc_s_ext_ctrls(file, fh, p) : -EINVAL;
 }
 
 static int v4l_try_ext_ctrls(const struct v4l2_ioctl_ops *ops,
@@ -2240,8 +2297,8 @@
 					  vfd, vfd->v4l2_dev->mdev, p);
 	if (ops->vidioc_try_ext_ctrls == NULL)
 		return -ENOTTY;
-	return check_ext_ctrls(p, 0) ? ops->vidioc_try_ext_ctrls(file, fh, p) :
-					-EINVAL;
+	return check_ext_ctrls(p, VIDIOC_TRY_EXT_CTRLS) ?
+			ops->vidioc_try_ext_ctrls(file, fh, p) : -EINVAL;
 }
 
 /*
@@ -3003,6 +3060,23 @@
 		}
 		break;
 	}
+
+	case VIDIOC_SUBDEV_G_ROUTING:
+	case VIDIOC_SUBDEV_S_ROUTING: {
+		struct v4l2_subdev_routing *route = parg;
+
+		if (route->num_routes > 0) {
+			if (route->num_routes > 256)
+				return -EINVAL;
+
+			*user_ptr = (void __user *)route->routes;
+			*kernel_ptr = (void *)&route->routes;
+			*array_size = sizeof(struct v4l2_plane)
+				    * route->num_routes;
+			ret = 1;
+		}
+		break;
+	}
 	}
 
 	return ret;
@@ -3013,7 +3087,7 @@
 	       v4l2_kioctl func)
 {
 	char	sbuf[128];
-	void    *mbuf = NULL;
+	void    *mbuf = NULL, *array_buf = NULL;
 	void	*parg = (void *)arg;
 	long	err  = -EINVAL;
 	bool	has_array_args;
@@ -3072,20 +3146,14 @@
 	has_array_args = err;
 
 	if (has_array_args) {
-		/*
-		 * When adding new types of array args, make sure that the
-		 * parent argument to ioctl (which contains the pointer to the
-		 * array) fits into sbuf (so that mbuf will still remain
-		 * unused up to here).
-		 */
-		mbuf = kvmalloc(array_size, GFP_KERNEL);
+		array_buf = kvmalloc(array_size, GFP_KERNEL);
 		err = -ENOMEM;
-		if (NULL == mbuf)
+		if (array_buf == NULL)
 			goto out_array_args;
 		err = -EFAULT;
-		if (copy_from_user(mbuf, user_ptr, array_size))
+		if (copy_from_user(array_buf, user_ptr, array_size))
 			goto out_array_args;
-		*kernel_ptr = mbuf;
+		*kernel_ptr = array_buf;
 	}
 
 	/* Handles IOCTL */
@@ -3104,7 +3172,7 @@
 
 	if (has_array_args) {
 		*kernel_ptr = (void __force *)user_ptr;
-		if (copy_to_user(user_ptr, mbuf, array_size))
+		if (copy_to_user(user_ptr, array_buf, array_size))
 			err = -EFAULT;
 		goto out_array_args;
 	}
@@ -3126,6 +3194,7 @@
 	}
 
 out:
+	kvfree(array_buf);
 	kvfree(mbuf);
 	return err;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/v4l2-core/v4l2-mem2mem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/v4l2-core/v4l2-mem2mem.c
@@ -460,19 +460,14 @@
 }
 EXPORT_SYMBOL_GPL(v4l2_m2m_reqbufs);
 
-int v4l2_m2m_querybuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
-		      struct v4l2_buffer *buf)
+static void v4l2_m2m_adjust_mem_offset(struct vb2_queue *vq,
+				       struct v4l2_buffer *buf)
 {
-	struct vb2_queue *vq;
-	int ret = 0;
-	unsigned int i;
-
-	vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
-	ret = vb2_querybuf(vq, buf);
-
 	/* Adjust MMAP memory offsets for the CAPTURE queue */
 	if (buf->memory == V4L2_MEMORY_MMAP && !V4L2_TYPE_IS_OUTPUT(vq->type)) {
 		if (V4L2_TYPE_IS_MULTIPLANAR(vq->type)) {
+			unsigned int i;
+
 			for (i = 0; i < buf->length; ++i)
 				buf->m.planes[i].m.mem_offset
 					+= DST_QUEUE_OFF_BASE;
@@ -480,8 +475,23 @@
 			buf->m.offset += DST_QUEUE_OFF_BASE;
 		}
 	}
+}
 
-	return ret;
+int v4l2_m2m_querybuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
+		      struct v4l2_buffer *buf)
+{
+	struct vb2_queue *vq;
+	int ret;
+
+	vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
+	ret = vb2_querybuf(vq, buf);
+	if (ret)
+		return ret;
+
+	/* Adjust MMAP memory offsets for the CAPTURE queue */
+	v4l2_m2m_adjust_mem_offset(vq, buf);
+
+	return 0;
 }
 EXPORT_SYMBOL_GPL(v4l2_m2m_querybuf);
 
@@ -500,10 +510,16 @@
 		return -EPERM;
 	}
 	ret = vb2_qbuf(vq, vdev->v4l2_dev->mdev, buf);
-	if (!ret && !(buf->flags & V4L2_BUF_FLAG_IN_REQUEST))
+	if (ret)
+		return ret;
+
+	/* Adjust MMAP memory offsets for the CAPTURE queue */
+	v4l2_m2m_adjust_mem_offset(vq, buf);
+
+	if (!(buf->flags & V4L2_BUF_FLAG_IN_REQUEST))
 		v4l2_m2m_try_schedule(m2m_ctx);
 
-	return ret;
+	return 0;
 }
 EXPORT_SYMBOL_GPL(v4l2_m2m_qbuf);
 
@@ -511,9 +527,17 @@
 		   struct v4l2_buffer *buf)
 {
 	struct vb2_queue *vq;
+	int ret;
 
 	vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
-	return vb2_dqbuf(vq, buf, file->f_flags & O_NONBLOCK);
+	ret = vb2_dqbuf(vq, buf, file->f_flags & O_NONBLOCK);
+	if (ret)
+		return ret;
+
+	/* Adjust MMAP memory offsets for the CAPTURE queue */
+	v4l2_m2m_adjust_mem_offset(vq, buf);
+
+	return 0;
 }
 EXPORT_SYMBOL_GPL(v4l2_m2m_dqbuf);
 
@@ -522,9 +546,17 @@
 {
 	struct video_device *vdev = video_devdata(file);
 	struct vb2_queue *vq;
+	int ret;
 
 	vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
-	return vb2_prepare_buf(vq, vdev->v4l2_dev->mdev, buf);
+	ret = vb2_prepare_buf(vq, vdev->v4l2_dev->mdev, buf);
+	if (ret)
+		return ret;
+
+	/* Adjust MMAP memory offsets for the CAPTURE queue */
+	v4l2_m2m_adjust_mem_offset(vq, buf);
+
+	return 0;
 }
 EXPORT_SYMBOL_GPL(v4l2_m2m_prepare_buf);
 
@@ -635,10 +667,8 @@
 		 * If the last buffer was dequeued from the capture queue,
 		 * return immediately. DQBUF will return -EPIPE.
 		 */
-		if (dst_q->last_buffer_dequeued) {
-			spin_unlock_irqrestore(&dst_q->done_lock, flags);
-			return EPOLLIN | EPOLLRDNORM;
-		}
+		if (dst_q->last_buffer_dequeued)
+			rc |= EPOLLIN | EPOLLRDNORM;
 	}
 	spin_unlock_irqrestore(&dst_q->done_lock, flags);
 
@@ -769,11 +799,17 @@
 	entity->function = function;
 
 	ret = media_entity_pads_init(entity, num_pads, pads);
-	if (ret)
+	if (ret) {
+		kfree(entity->name);
+		entity->name = NULL;
 		return ret;
+	}
 	ret = media_device_register_entity(mdev, entity);
-	if (ret)
+	if (ret) {
+		kfree(entity->name);
+		entity->name = NULL;
 		return ret;
+	}
 
 	return 0;
 }
@@ -809,12 +845,12 @@
 		goto err_rel_entity1;
 
 	/* Connect the three entities */
-	ret = media_create_pad_link(m2m_dev->source, 0, &m2m_dev->proc, 1,
+	ret = media_create_pad_link(m2m_dev->source, 0, &m2m_dev->proc, 0,
 			MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
 	if (ret)
 		goto err_rel_entity2;
 
-	ret = media_create_pad_link(&m2m_dev->proc, 0, &m2m_dev->sink, 0,
+	ret = media_create_pad_link(&m2m_dev->proc, 1, &m2m_dev->sink, 0,
 			MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
 	if (ret)
 		goto err_rm_links0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/v4l2-core/v4l2-subdev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/v4l2-core/v4l2-subdev.c
@@ -582,6 +582,33 @@
 	case VIDIOC_SUBDEV_S_DV_TIMINGS:
 		return v4l2_subdev_call(sd, video, s_dv_timings, arg);
 
+	case VIDIOC_SUBDEV_G_ROUTING:
+		return v4l2_subdev_call(sd, pad, get_routing, arg);
+
+	case VIDIOC_SUBDEV_S_ROUTING: {
+		struct v4l2_subdev_routing *route = arg;
+		unsigned int i;
+
+		if (route->num_routes > sd->entity.num_pads)
+			return -EINVAL;
+
+		for (i = 0; i < route->num_routes; ++i) {
+			unsigned int sink = route->routes[i].sink;
+			unsigned int source = route->routes[i].source;
+			struct media_pad *pads = sd->entity.pads;
+
+			if (sink >= sd->entity.num_pads ||
+			    source >= sd->entity.num_pads)
+				return -EINVAL;
+
+			if (!(pads[sink].flags & MEDIA_PAD_FL_SINK) ||
+			    !(pads[source].flags & MEDIA_PAD_FL_SOURCE))
+				return -EINVAL;
+		}
+
+		return v4l2_subdev_call(sd, pad, set_routing, route);
+	}
+
 	case VIDIOC_SUBDEV_G_STD:
 		return v4l2_subdev_call(sd, video, g_std, arg);
 
@@ -604,6 +631,7 @@
 	case VIDIOC_SUBDEV_QUERYSTD:
 		return v4l2_subdev_call(sd, video, querystd, arg);
 #endif
+
 	default:
 		return v4l2_subdev_call(sd, core, ioctl, cmd, arg);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/v4l2-core/videobuf-dma-contig.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/v4l2-core/videobuf-dma-contig.c
@@ -36,12 +36,11 @@
 
 static int __videobuf_dc_alloc(struct device *dev,
 			       struct videobuf_dma_contig_memory *mem,
-			       unsigned long size, gfp_t flags)
+			       unsigned long size)
 {
 	mem->size = size;
-	mem->vaddr = dma_alloc_coherent(dev, mem->size,
-					&mem->dma_handle, flags);
-
+	mem->vaddr = dma_alloc_coherent(dev, mem->size, &mem->dma_handle,
+					GFP_KERNEL);
 	if (!mem->vaddr) {
 		dev_err(dev, "memory alloc size %ld failed\n", mem->size);
 		return -ENOMEM;
@@ -258,8 +257,7 @@
 			return videobuf_dma_contig_user_get(mem, vb);
 
 		/* allocate memory for the read() method */
-		if (__videobuf_dc_alloc(q->dev, mem, PAGE_ALIGN(vb->size),
-					GFP_KERNEL))
+		if (__videobuf_dc_alloc(q->dev, mem, PAGE_ALIGN(vb->size)))
 			return -ENOMEM;
 		break;
 	case V4L2_MEMORY_OVERLAY:
@@ -295,22 +293,18 @@
 	BUG_ON(!mem);
 	MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
 
-	if (__videobuf_dc_alloc(q->dev, mem, PAGE_ALIGN(buf->bsize),
-				GFP_KERNEL | __GFP_COMP))
+	if (__videobuf_dc_alloc(q->dev, mem, PAGE_ALIGN(buf->bsize)))
 		goto error;
 
-	/* Try to remap memory */
-	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
 	/* the "vm_pgoff" is just used in v4l2 to find the
 	 * corresponding buffer data structure which is allocated
 	 * earlier and it does not mean the offset from the physical
 	 * buffer start address as usual. So set it to 0 to pass
-	 * the sanity check in vm_iomap_memory().
+	 * the sanity check in dma_mmap_coherent().
 	 */
 	vma->vm_pgoff = 0;
-
-	retval = vm_iomap_memory(vma, mem->dma_handle, mem->size);
+	retval = dma_mmap_coherent(q->dev, vma, mem->vaddr, mem->dma_handle,
+				   mem->size);
 	if (retval) {
 		dev_err(q->dev, "mmap: remap failed with error %d. ",
 			retval);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/media/v4l2-core/videobuf-dma-sg.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/media/v4l2-core/videobuf-dma-sg.c
@@ -349,8 +349,11 @@
 	BUG_ON(dma->sglen);
 
 	if (dma->pages) {
-		for (i = 0; i < dma->nr_pages; i++)
+		for (i = 0; i < dma->nr_pages; i++) {
+			if (dma->direction == DMA_FROM_DEVICE)
+				set_page_dirty_lock(dma->pages[i]);
 			put_page(dma->pages[i]);
+		}
 		kfree(dma->pages);
 		dma->pages = NULL;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/memory/atmel-ebi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/memory/atmel-ebi.c
@@ -545,20 +545,27 @@
 	smc_np = of_parse_phandle(dev->of_node, "atmel,smc", 0);
 
 	ebi->smc.regmap = syscon_node_to_regmap(smc_np);
-	if (IS_ERR(ebi->smc.regmap))
-		return PTR_ERR(ebi->smc.regmap);
+	if (IS_ERR(ebi->smc.regmap)) {
+		ret = PTR_ERR(ebi->smc.regmap);
+		goto put_node;
+	}
 
 	ebi->smc.layout = atmel_hsmc_get_reg_layout(smc_np);
-	if (IS_ERR(ebi->smc.layout))
-		return PTR_ERR(ebi->smc.layout);
+	if (IS_ERR(ebi->smc.layout)) {
+		ret = PTR_ERR(ebi->smc.layout);
+		goto put_node;
+	}
 
 	ebi->smc.clk = of_clk_get(smc_np, 0);
 	if (IS_ERR(ebi->smc.clk)) {
-		if (PTR_ERR(ebi->smc.clk) != -ENOENT)
-			return PTR_ERR(ebi->smc.clk);
+		if (PTR_ERR(ebi->smc.clk) != -ENOENT) {
+			ret = PTR_ERR(ebi->smc.clk);
+			goto put_node;
+		}
 
 		ebi->smc.clk = NULL;
 	}
+	of_node_put(smc_np);
 	ret = clk_prepare_enable(ebi->smc.clk);
 	if (ret)
 		return ret;
@@ -601,12 +608,18 @@
 				child);
 
 			ret = atmel_ebi_dev_disable(ebi, child);
-			if (ret)
+			if (ret) {
+				of_node_put(child);
 				return ret;
+			}
 		}
 	}
 
 	return of_platform_populate(np, NULL, NULL, dev);
+
+put_node:
+	of_node_put(smc_np);
+	return ret;
 }
 
 static __maybe_unused int atmel_ebi_resume(struct device *dev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/memory/atmel-sdramc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/memory/atmel-sdramc.c
@@ -47,19 +47,17 @@
 	caps = of_device_get_match_data(&pdev->dev);
 
 	if (caps->has_ddrck) {
-		clk = devm_clk_get(&pdev->dev, "ddrck");
+		clk = devm_clk_get_enabled(&pdev->dev, "ddrck");
 		if (IS_ERR(clk))
 			return PTR_ERR(clk);
-		clk_prepare_enable(clk);
 	}
 
 	if (caps->has_mpddr_clk) {
-		clk = devm_clk_get(&pdev->dev, "mpddr");
+		clk = devm_clk_get_enabled(&pdev->dev, "mpddr");
 		if (IS_ERR(clk)) {
 			pr_err("AT91 RAMC: couldn't get mpddr clock\n");
 			return PTR_ERR(clk);
 		}
-		clk_prepare_enable(clk);
 	}
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/memory/brcmstb_dpfe.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/memory/brcmstb_dpfe.c
@@ -398,15 +398,17 @@
 static int __send_command(struct private_data *priv, unsigned int cmd,
 			  u32 result[])
 {
-	const u32 *msg = priv->dpfe_api->command[cmd];
 	void __iomem *regs = priv->regs;
 	unsigned int i, chksum, chksum_idx;
+	const u32 *msg;
 	int ret = 0;
 	u32 resp;
 
 	if (cmd >= DPFE_CMD_MAX)
 		return -1;
 
+	msg = priv->dpfe_api->command[cmd];
+
 	mutex_lock(&priv->lock);
 
 	/* Wait for DCPU to become ready */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/memory/emif.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/memory/emif.c
@@ -163,35 +163,12 @@
 
 static int __init_or_module emif_debugfs_init(struct emif_data *emif)
 {
-	struct dentry	*dentry;
-	int		ret;
-
-	dentry = debugfs_create_dir(dev_name(emif->dev), NULL);
-	if (!dentry) {
-		ret = -ENOMEM;
-		goto err0;
-	}
-	emif->debugfs_root = dentry;
-
-	dentry = debugfs_create_file("regcache_dump", S_IRUGO,
-			emif->debugfs_root, emif, &emif_regdump_fops);
-	if (!dentry) {
-		ret = -ENOMEM;
-		goto err1;
-	}
-
-	dentry = debugfs_create_file("mr4", S_IRUGO,
-			emif->debugfs_root, emif, &emif_mr4_fops);
-	if (!dentry) {
-		ret = -ENOMEM;
-		goto err1;
-	}
-
+	emif->debugfs_root = debugfs_create_dir(dev_name(emif->dev), NULL);
+	debugfs_create_file("regcache_dump", S_IRUGO, emif->debugfs_root, emif,
+			    &emif_regdump_fops);
+	debugfs_create_file("mr4", S_IRUGO, emif->debugfs_root, emif,
+			    &emif_mr4_fops);
 	return 0;
-err1:
-	debugfs_remove_recursive(emif->debugfs_root);
-err0:
-	return ret;
 }
 
 static void __exit emif_debugfs_exit(struct emif_data *emif)
@@ -1446,7 +1423,7 @@
 	temp	= devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
 	dev_info = devm_kzalloc(dev, sizeof(*dev_info), GFP_KERNEL);
 
-	if (!emif || !pd || !dev_info) {
+	if (!emif || !temp || !dev_info) {
 		dev_err(dev, "%s:%d: allocation error\n", __func__, __LINE__);
 		goto error;
 	}
@@ -1538,7 +1515,7 @@
 {
 	struct emif_data	*emif;
 	struct resource		*res;
-	int			irq;
+	int			irq, ret;
 
 	if (pdev->dev.of_node)
 		emif = of_get_memory_device_details(pdev->dev.of_node, &pdev->dev);
@@ -1572,7 +1549,9 @@
 	emif_onetime_settings(emif);
 	emif_debugfs_init(emif);
 	disable_and_clear_all_interrupts(emif);
-	setup_interrupts(emif, irq);
+	ret = setup_interrupts(emif, irq);
+	if (ret)
+		goto error;
 
 	/* One-time actions taken on probing the first device */
 	if (!emif1) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/memory/fsl-corenet-cf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/memory/fsl-corenet-cf.c
@@ -211,10 +211,8 @@
 	dev_set_drvdata(&pdev->dev, ccf);
 
 	irq = platform_get_irq(pdev, 0);
-	if (!irq) {
-		dev_err(&pdev->dev, "%s: no irq\n", __func__);
-		return -ENXIO;
-	}
+	if (irq < 0)
+		return irq;
 
 	ret = devm_request_irq(&pdev->dev, irq, ccf_irq, 0, pdev->name, ccf);
 	if (ret) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/memory/fsl_ifc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/memory/fsl_ifc.c
@@ -96,7 +96,6 @@
 	iounmap(ctrl->gregs);
 
 	dev_set_drvdata(&dev->dev, NULL);
-	kfree(ctrl);
 
 	return 0;
 }
@@ -208,7 +207,8 @@
 
 	dev_info(&dev->dev, "Freescale Integrated Flash Controller\n");
 
-	fsl_ifc_ctrl_dev = kzalloc(sizeof(*fsl_ifc_ctrl_dev), GFP_KERNEL);
+	fsl_ifc_ctrl_dev = devm_kzalloc(&dev->dev, sizeof(*fsl_ifc_ctrl_dev),
+					GFP_KERNEL);
 	if (!fsl_ifc_ctrl_dev)
 		return -ENOMEM;
 
@@ -218,8 +218,7 @@
 	fsl_ifc_ctrl_dev->gregs = of_iomap(dev->dev.of_node, 0);
 	if (!fsl_ifc_ctrl_dev->gregs) {
 		dev_err(&dev->dev, "failed to get memory region\n");
-		ret = -ENODEV;
-		goto err;
+		return -ENODEV;
 	}
 
 	if (of_property_read_bool(dev->dev.of_node, "little-endian")) {
@@ -264,7 +263,7 @@
 
 	ret = fsl_ifc_ctrl_init(fsl_ifc_ctrl_dev);
 	if (ret < 0)
-		goto err;
+		goto err_unmap_nandirq;
 
 	init_waitqueue_head(&fsl_ifc_ctrl_dev->nand_wait);
 
@@ -273,7 +272,7 @@
 	if (ret != 0) {
 		dev_err(&dev->dev, "failed to install irq (%d)\n",
 			fsl_ifc_ctrl_dev->irq);
-		goto err_irq;
+		goto err_unmap_nandirq;
 	}
 
 	if (fsl_ifc_ctrl_dev->nand_irq) {
@@ -282,19 +281,19 @@
 		if (ret != 0) {
 			dev_err(&dev->dev, "failed to install irq (%d)\n",
 				fsl_ifc_ctrl_dev->nand_irq);
-			goto err_nandirq;
+			goto err_free_irq;
 		}
 	}
 
 	return 0;
 
-err_nandirq:
-	free_irq(fsl_ifc_ctrl_dev->nand_irq, fsl_ifc_ctrl_dev);
-	irq_dispose_mapping(fsl_ifc_ctrl_dev->nand_irq);
-err_irq:
+err_free_irq:
 	free_irq(fsl_ifc_ctrl_dev->irq, fsl_ifc_ctrl_dev);
+err_unmap_nandirq:
+	irq_dispose_mapping(fsl_ifc_ctrl_dev->nand_irq);
 	irq_dispose_mapping(fsl_ifc_ctrl_dev->irq);
 err:
+	iounmap(fsl_ifc_ctrl_dev->gregs);
 	return ret;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/memory/mtk-smi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/memory/mtk-smi.c
@@ -127,7 +127,7 @@
 
 int mtk_smi_larb_get(struct device *larbdev)
 {
-	int ret = pm_runtime_get_sync(larbdev);
+	int ret = pm_runtime_resume_and_get(larbdev);
 
 	return (ret < 0) ? ret : 0;
 }
@@ -336,7 +336,7 @@
 	int ret;
 
 	/* Power on smi-common. */
-	ret = pm_runtime_get_sync(larb->smi_common_dev);
+	ret = pm_runtime_resume_and_get(larb->smi_common_dev);
 	if (ret < 0) {
 		dev_err(dev, "Failed to pm get for smi-common(%d).\n", ret);
 		return ret;
@@ -366,6 +366,8 @@
 
 static const struct dev_pm_ops smi_larb_pm_ops = {
 	SET_RUNTIME_PM_OPS(mtk_smi_larb_suspend, mtk_smi_larb_resume, NULL)
+	SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+				     pm_runtime_force_resume)
 };
 
 static struct platform_driver mtk_smi_larb_driver = {
@@ -507,6 +509,8 @@
 
 static const struct dev_pm_ops smi_common_pm_ops = {
 	SET_RUNTIME_PM_OPS(mtk_smi_common_suspend, mtk_smi_common_resume, NULL)
+	SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+				     pm_runtime_force_resume)
 };
 
 static struct platform_driver mtk_smi_common_driver = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/memory/mvebu-devbus.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/memory/mvebu-devbus.c
@@ -282,10 +282,9 @@
 	if (IS_ERR(devbus->base))
 		return PTR_ERR(devbus->base);
 
-	clk = devm_clk_get(&pdev->dev, NULL);
+	clk = devm_clk_get_enabled(&pdev->dev, NULL);
 	if (IS_ERR(clk))
 		return PTR_ERR(clk);
-	clk_prepare_enable(clk);
 
 	/*
 	 * Obtain clock period in picoseconds,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/memory/of_memory.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/memory/of_memory.c
@@ -132,6 +132,7 @@
 	for_each_child_of_node(np_ddr, np_tim) {
 		if (of_device_is_compatible(np_tim, tim_compat)) {
 			if (of_do_get_timings(np_tim, &timings[i])) {
+				of_node_put(np_tim);
 				devm_kfree(dev, timings);
 				goto default_timings;
 			}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/memory/omap-gpmc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/memory/omap-gpmc.c
@@ -949,7 +949,7 @@
 	int ret;
 	u32 old_base, size;
 
-	if (cs > gpmc_cs_num) {
+	if (cs >= gpmc_cs_num) {
 		pr_err("%s: requested chip-select is disabled\n", __func__);
 		return -ENODEV;
 	}
@@ -984,7 +984,7 @@
 	struct resource *res = &gpmc->mem;
 	int r = -1;
 
-	if (cs > gpmc_cs_num) {
+	if (cs >= gpmc_cs_num) {
 		pr_err("%s: requested chip-select is disabled\n", __func__);
 		return -ENODEV;
 	}
@@ -1026,8 +1026,8 @@
 
 void gpmc_cs_free(int cs)
 {
-	struct gpmc_cs_data *gpmc = &gpmc_cs[cs];
-	struct resource *res = &gpmc->mem;
+	struct gpmc_cs_data *gpmc;
+	struct resource *res;
 
 	spin_lock(&gpmc_mem_lock);
 	if (cs >= gpmc_cs_num || cs < 0 || !gpmc_cs_reserved(cs)) {
@@ -1036,6 +1036,9 @@
 		spin_unlock(&gpmc_mem_lock);
 		return;
 	}
+	gpmc = &gpmc_cs[cs];
+	res = &gpmc->mem;
+
 	gpmc_cs_disable_mem(cs);
 	if (res->flags)
 		release_resource(res);
@@ -2274,6 +2277,10 @@
 	}
 }
 #else
+void gpmc_read_settings_dt(struct device_node *np, struct gpmc_settings *p)
+{
+	memset(p, 0, sizeof(*p));
+}
 static int gpmc_probe_dt(struct platform_device *pdev)
 {
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/memory/pl353-smc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/memory/pl353-smc.c
@@ -63,7 +63,7 @@
 /* ECC memory config register specific constants */
 #define PL353_SMC_ECC_MEMCFG_MODE_MASK	0xC
 #define PL353_SMC_ECC_MEMCFG_MODE_SHIFT	2
-#define PL353_SMC_ECC_MEMCFG_PGSIZE_MASK	0xC
+#define PL353_SMC_ECC_MEMCFG_PGSIZE_MASK	0x3
 
 #define PL353_SMC_DC_UPT_NAND_REGS	((4 << 23) |	/* CS: NAND chip */ \
 				 (2 << 21))	/* UpdateRegs operation */
@@ -407,14 +407,17 @@
 		break;
 	}
 	if (!match) {
+		err = -ENODEV;
 		dev_err(&adev->dev, "no matching children\n");
 		goto out_clk_disable;
 	}
 
-	init = match->data;
+	init = (void (*)(struct amba_device *,
+			 struct device_node *))match->data;
 	if (init)
 		init(adev, child);
 	of_platform_device_create(child, NULL, &adev->dev);
+	of_node_put(child);
 
 	return 0;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/memory/ti-aemif.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/memory/ti-aemif.c
@@ -378,8 +378,10 @@
 		 */
 		for_each_available_child_of_node(np, child_np) {
 			ret = of_aemif_parse_abus_config(pdev, child_np);
-			if (ret < 0)
+			if (ret < 0) {
+				of_node_put(child_np);
 				goto error;
+			}
 		}
 	} else if (pdata && pdata->num_abus_data > 0) {
 		for (i = 0; i < pdata->num_abus_data; i++, aemif->num_cs++) {
@@ -405,8 +407,10 @@
 		for_each_available_child_of_node(np, child_np) {
 			ret = of_platform_populate(child_np, NULL,
 						   dev_lookup, dev);
-			if (ret < 0)
+			if (ret < 0) {
+				of_node_put(child_np);
 				goto error;
+			}
 		}
 	} else if (pdata) {
 		for (i = 0; i < pdata->num_sub_devices; i++) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/memstick/core/memstick.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/memstick/core/memstick.c
@@ -412,6 +412,7 @@
 	return card;
 err_out:
 	host->card = old_card;
+	kfree_const(card->dev.kobj.name);
 	kfree(card);
 	return NULL;
 }
@@ -441,6 +442,9 @@
 	} else if (host->card->stop)
 		host->card->stop(host->card);
 
+	if (host->removing)
+		goto out_power_off;
+
 	card = memstick_alloc_card(host);
 
 	if (!card) {
@@ -465,11 +469,12 @@
 			host->card = card;
 			if (device_register(&card->dev)) {
 				put_device(&card->dev);
-				kfree(host->card);
 				host->card = NULL;
 			}
-		} else
+		} else {
+			kfree_const(card->dev.kobj.name);
 			kfree(card);
+		}
 	}
 
 out_power_off:
@@ -545,6 +550,7 @@
  */
 void memstick_remove_host(struct memstick_host *host)
 {
+	host->removing = 1;
 	flush_workqueue(workqueue);
 	mutex_lock(&host->lock);
 	if (host->card)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/memstick/core/ms_block.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/memstick/core/ms_block.c
@@ -1335,17 +1335,17 @@
 	msb->zone_count = msb->block_count / MS_BLOCKS_IN_ZONE;
 	msb->logical_block_count = msb->zone_count * 496 - 2;
 
-	msb->used_blocks_bitmap = kzalloc(msb->block_count / 8, GFP_KERNEL);
-	msb->erased_blocks_bitmap = kzalloc(msb->block_count / 8, GFP_KERNEL);
+	msb->used_blocks_bitmap = bitmap_zalloc(msb->block_count, GFP_KERNEL);
+	msb->erased_blocks_bitmap = bitmap_zalloc(msb->block_count, GFP_KERNEL);
 	msb->lba_to_pba_table =
 		kmalloc_array(msb->logical_block_count, sizeof(u16),
 			      GFP_KERNEL);
 
 	if (!msb->used_blocks_bitmap || !msb->lba_to_pba_table ||
 						!msb->erased_blocks_bitmap) {
-		kfree(msb->used_blocks_bitmap);
+		bitmap_free(msb->used_blocks_bitmap);
+		bitmap_free(msb->erased_blocks_bitmap);
 		kfree(msb->lba_to_pba_table);
-		kfree(msb->erased_blocks_bitmap);
 		return -ENOMEM;
 	}
 
@@ -1727,7 +1727,7 @@
 	msb->pages_in_block = boot_block->attr.block_size * 2;
 	msb->block_size = msb->page_size * msb->pages_in_block;
 
-	if (msb->page_size > PAGE_SIZE) {
+	if ((size_t)msb->page_size > PAGE_SIZE) {
 		/* this isn't supported by linux at all, anyway*/
 		dbg("device page %d size isn't supported", msb->page_size);
 		return -EINVAL;
@@ -1953,7 +1953,8 @@
 static void msb_data_clear(struct msb_data *msb)
 {
 	kfree(msb->boot_page);
-	kfree(msb->used_blocks_bitmap);
+	bitmap_free(msb->used_blocks_bitmap);
+	bitmap_free(msb->erased_blocks_bitmap);
 	kfree(msb->lba_to_pba_table);
 	kfree(msb->cache);
 	msb->card = NULL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/memstick/host/jmb38x_ms.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/memstick/host/jmb38x_ms.c
@@ -314,7 +314,7 @@
 	}
 
 	while (length) {
-		unsigned int uninitialized_var(p_off);
+		unsigned int p_off;
 
 		if (host->req->long_data) {
 			pg = nth_page(sg_page(&host->req->sg),
@@ -899,7 +899,7 @@
 
 	iounmap(host->addr);
 err_out_free:
-	kfree(msh);
+	memstick_free_host(msh);
 	return NULL;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/memstick/host/r592.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/memstick/host/r592.c
@@ -44,12 +44,10 @@
  * memstick_debug_get_tpc_name - debug helper that returns string for
  * a TPC number
  */
-const char *memstick_debug_get_tpc_name(int tpc)
+static __maybe_unused const char *memstick_debug_get_tpc_name(int tpc)
 {
 	return tpc_names[tpc-1];
 }
-EXPORT_SYMBOL(memstick_debug_get_tpc_name);
-
 
 /* Read a register*/
 static inline u32 r592_read_reg(struct r592_device *dev, int address)
@@ -759,8 +757,10 @@
 		goto error3;
 
 	dev->mmio = pci_ioremap_bar(pdev, 0);
-	if (!dev->mmio)
+	if (!dev->mmio) {
+		error = -ENOMEM;
 		goto error4;
+	}
 
 	dev->irq = pdev->irq;
 	spin_lock_init(&dev->irq_lock);
@@ -786,12 +786,14 @@
 		&dev->dummy_dma_page_physical_address, GFP_KERNEL);
 	r592_stop_dma(dev , 0);
 
-	if (request_irq(dev->irq, &r592_irq, IRQF_SHARED,
-			  DRV_NAME, dev))
+	error = request_irq(dev->irq, &r592_irq, IRQF_SHARED,
+			  DRV_NAME, dev);
+	if (error)
 		goto error6;
 
 	r592_update_card_detect(dev);
-	if (memstick_add_host(host))
+	error = memstick_add_host(host);
+	if (error)
 		goto error7;
 
 	message("driver successfully loaded");
@@ -824,7 +826,7 @@
 	/* Stop the processing thread.
 	That ensures that we won't take any more requests */
 	kthread_stop(dev->io_thread);
-
+	del_timer_sync(&dev->detect_timer);
 	r592_enable_device(dev, false);
 
 	while (!error && dev->req) {
@@ -833,15 +835,15 @@
 	}
 	memstick_remove_host(dev->host);
 
+	if (dev->dummy_dma_page)
+		dma_free_coherent(&pdev->dev, PAGE_SIZE, dev->dummy_dma_page,
+			dev->dummy_dma_page_physical_address);
+
 	free_irq(dev->irq, dev);
 	iounmap(dev->mmio);
 	pci_release_regions(pdev);
 	pci_disable_device(pdev);
 	memstick_free_host(dev->host);
-
-	if (dev->dummy_dma_page)
-		dma_free_coherent(&pdev->dev, PAGE_SIZE, dev->dummy_dma_page,
-			dev->dummy_dma_page_physical_address);
 }
 
 #ifdef CONFIG_PM_SLEEP
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/memstick/host/rtsx_usb_ms.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/memstick/host/rtsx_usb_ms.c
@@ -799,9 +799,9 @@
 
 	return 0;
 err_out:
-	memstick_free_host(msh);
 	pm_runtime_disable(ms_dev(host));
 	pm_runtime_put_noidle(ms_dev(host));
+	memstick_free_host(msh);
 	return err;
 }
 
@@ -813,6 +813,7 @@
 
 	host->eject = true;
 	cancel_work_sync(&host->handle_req);
+	cancel_delayed_work_sync(&host->poll_card);
 
 	mutex_lock(&host->host_mutex);
 	if (host->req) {
@@ -828,9 +829,6 @@
 	}
 	mutex_unlock(&host->host_mutex);
 
-	memstick_remove_host(msh);
-	memstick_free_host(msh);
-
 	/* Balance possible unbalanced usage count
 	 * e.g. unconditional module removal
 	 */
@@ -838,10 +836,11 @@
 		pm_runtime_put(ms_dev(host));
 
 	pm_runtime_disable(ms_dev(host));
-	platform_set_drvdata(pdev, NULL);
-
+	memstick_remove_host(msh);
 	dev_dbg(ms_dev(host),
 		": Realtek USB Memstick controller has been removed\n");
+	memstick_free_host(msh);
+	platform_set_drvdata(pdev, NULL);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/memstick/host/tifm_ms.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/memstick/host/tifm_ms.c
@@ -198,7 +198,7 @@
 		host->block_pos);
 
 	while (length) {
-		unsigned int uninitialized_var(p_off);
+		unsigned int p_off;
 
 		if (host->req->long_data) {
 			pg = nth_page(sg_page(&host->req->sg),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/message/fusion/mptctl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/message/fusion/mptctl.c
@@ -100,19 +100,19 @@
  * Function prototypes. Called from OS entry point mptctl_ioctl.
  * arg contents specific to function.
  */
-static int mptctl_fw_download(unsigned long arg);
-static int mptctl_getiocinfo(unsigned long arg, unsigned int cmd);
-static int mptctl_gettargetinfo(unsigned long arg);
-static int mptctl_readtest(unsigned long arg);
-static int mptctl_mpt_command(unsigned long arg);
-static int mptctl_eventquery(unsigned long arg);
-static int mptctl_eventenable(unsigned long arg);
-static int mptctl_eventreport(unsigned long arg);
-static int mptctl_replace_fw(unsigned long arg);
-
-static int mptctl_do_reset(unsigned long arg);
-static int mptctl_hp_hostinfo(unsigned long arg, unsigned int cmd);
-static int mptctl_hp_targetinfo(unsigned long arg);
+static int mptctl_fw_download(MPT_ADAPTER *iocp, unsigned long arg);
+static int mptctl_getiocinfo(MPT_ADAPTER *iocp, unsigned long arg, unsigned int cmd);
+static int mptctl_gettargetinfo(MPT_ADAPTER *iocp, unsigned long arg);
+static int mptctl_readtest(MPT_ADAPTER *iocp, unsigned long arg);
+static int mptctl_mpt_command(MPT_ADAPTER *iocp, unsigned long arg);
+static int mptctl_eventquery(MPT_ADAPTER *iocp, unsigned long arg);
+static int mptctl_eventenable(MPT_ADAPTER *iocp, unsigned long arg);
+static int mptctl_eventreport(MPT_ADAPTER *iocp, unsigned long arg);
+static int mptctl_replace_fw(MPT_ADAPTER *iocp, unsigned long arg);
+
+static int mptctl_do_reset(MPT_ADAPTER *iocp, unsigned long arg);
+static int mptctl_hp_hostinfo(MPT_ADAPTER *iocp, unsigned long arg, unsigned int cmd);
+static int mptctl_hp_targetinfo(MPT_ADAPTER *iocp, unsigned long arg);
 
 static int  mptctl_probe(struct pci_dev *, const struct pci_device_id *);
 static void mptctl_remove(struct pci_dev *);
@@ -123,8 +123,8 @@
 /*
  * Private function calls.
  */
-static int mptctl_do_mpt_command(struct mpt_ioctl_command karg, void __user *mfPtr);
-static int mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen);
+static int mptctl_do_mpt_command(MPT_ADAPTER *iocp, struct mpt_ioctl_command karg, void __user *mfPtr);
+static int mptctl_do_fw_download(MPT_ADAPTER *iocp, char __user *ufwbuf, size_t fwlen);
 static MptSge_t *kbuf_alloc_2_sgl(int bytes, u32 dir, int sge_offset, int *frags,
 		struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc);
 static void kfree_sgl(MptSge_t *sgl, dma_addr_t sgl_dma,
@@ -656,19 +656,19 @@
 	 * by TM and FW reloads.
 	 */
 	if ((cmd & ~IOCSIZE_MASK) == (MPTIOCINFO & ~IOCSIZE_MASK)) {
-		return mptctl_getiocinfo(arg, _IOC_SIZE(cmd));
+		return mptctl_getiocinfo(iocp, arg, _IOC_SIZE(cmd));
 	} else if (cmd == MPTTARGETINFO) {
-		return mptctl_gettargetinfo(arg);
+		return mptctl_gettargetinfo(iocp, arg);
 	} else if (cmd == MPTTEST) {
-		return mptctl_readtest(arg);
+		return mptctl_readtest(iocp, arg);
 	} else if (cmd == MPTEVENTQUERY) {
-		return mptctl_eventquery(arg);
+		return mptctl_eventquery(iocp, arg);
 	} else if (cmd == MPTEVENTENABLE) {
-		return mptctl_eventenable(arg);
+		return mptctl_eventenable(iocp, arg);
 	} else if (cmd == MPTEVENTREPORT) {
-		return mptctl_eventreport(arg);
+		return mptctl_eventreport(iocp, arg);
 	} else if (cmd == MPTFWREPLACE) {
-		return mptctl_replace_fw(arg);
+		return mptctl_replace_fw(iocp, arg);
 	}
 
 	/* All of these commands require an interrupt or
@@ -678,15 +678,15 @@
 		return ret;
 
 	if (cmd == MPTFWDOWNLOAD)
-		ret = mptctl_fw_download(arg);
+		ret = mptctl_fw_download(iocp, arg);
 	else if (cmd == MPTCOMMAND)
-		ret = mptctl_mpt_command(arg);
+		ret = mptctl_mpt_command(iocp, arg);
 	else if (cmd == MPTHARDRESET)
-		ret = mptctl_do_reset(arg);
+		ret = mptctl_do_reset(iocp, arg);
 	else if ((cmd & ~IOCSIZE_MASK) == (HP_GETHOSTINFO & ~IOCSIZE_MASK))
-		ret = mptctl_hp_hostinfo(arg, _IOC_SIZE(cmd));
+		ret = mptctl_hp_hostinfo(iocp, arg, _IOC_SIZE(cmd));
 	else if (cmd == HP_GETTARGETINFO)
-		ret = mptctl_hp_targetinfo(arg);
+		ret = mptctl_hp_targetinfo(iocp, arg);
 	else
 		ret = -EINVAL;
 
@@ -705,11 +705,10 @@
 	return ret;
 }
 
-static int mptctl_do_reset(unsigned long arg)
+static int mptctl_do_reset(MPT_ADAPTER *iocp, unsigned long arg)
 {
 	struct mpt_ioctl_diag_reset __user *urinfo = (void __user *) arg;
 	struct mpt_ioctl_diag_reset krinfo;
-	MPT_ADAPTER		*iocp;
 
 	if (copy_from_user(&krinfo, urinfo, sizeof(struct mpt_ioctl_diag_reset))) {
 		printk(KERN_ERR MYNAM "%s@%d::mptctl_do_reset - "
@@ -718,12 +717,6 @@
 		return -EFAULT;
 	}
 
-	if (mpt_verify_adapter(krinfo.hdr.iocnum, &iocp) < 0) {
-		printk(KERN_DEBUG MYNAM "%s@%d::mptctl_do_reset - ioc%d not found!\n",
-				__FILE__, __LINE__, krinfo.hdr.iocnum);
-		return -ENODEV; /* (-6) No such device or address */
-	}
-
 	dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "mptctl_do_reset called.\n",
 	    iocp->name));
 
@@ -754,7 +747,7 @@
  *		-ENOMSG if FW upload returned bad status
  */
 static int
-mptctl_fw_download(unsigned long arg)
+mptctl_fw_download(MPT_ADAPTER *iocp, unsigned long arg)
 {
 	struct mpt_fw_xfer __user *ufwdl = (void __user *) arg;
 	struct mpt_fw_xfer	 kfwdl;
@@ -766,7 +759,7 @@
 		return -EFAULT;
 	}
 
-	return mptctl_do_fw_download(kfwdl.iocnum, kfwdl.bufp, kfwdl.fwlen);
+	return mptctl_do_fw_download(iocp, kfwdl.bufp, kfwdl.fwlen);
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -784,11 +777,10 @@
  *		-ENOMSG if FW upload returned bad status
  */
 static int
-mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
+mptctl_do_fw_download(MPT_ADAPTER *iocp, char __user *ufwbuf, size_t fwlen)
 {
 	FWDownload_t		*dlmsg;
 	MPT_FRAME_HDR		*mf;
-	MPT_ADAPTER		*iocp;
 	FWDownloadTCSGE_t	*ptsge;
 	MptSge_t		*sgl, *sgIn;
 	char			*sgOut;
@@ -808,17 +800,10 @@
 	pFWDownloadReply_t	 ReplyMsg = NULL;
 	unsigned long		 timeleft;
 
-	if (mpt_verify_adapter(ioc, &iocp) < 0) {
-		printk(KERN_DEBUG MYNAM "ioctl_fwdl - ioc%d not found!\n",
-				 ioc);
-		return -ENODEV; /* (-6) No such device or address */
-	} else {
-
-		/*  Valid device. Get a message frame and construct the FW download message.
-	 	*/
-		if ((mf = mpt_get_msg_frame(mptctl_id, iocp)) == NULL)
-			return -EAGAIN;
-	}
+	/*  Valid device. Get a message frame and construct the FW download message.
+	*/
+	if ((mf = mpt_get_msg_frame(mptctl_id, iocp)) == NULL)
+		return -EAGAIN;
 
 	dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT
 	    "mptctl_do_fwdl called. mptctl_id = %xh.\n", iocp->name, mptctl_id));
@@ -826,8 +811,6 @@
 	    iocp->name, ufwbuf));
 	dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "DbG: kfwdl.fwlen = %d\n",
 	    iocp->name, (int)fwlen));
-	dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "DbG: kfwdl.ioc   = %04xh\n",
-	    iocp->name, ioc));
 
 	dlmsg = (FWDownload_t*) mf;
 	ptsge = (FWDownloadTCSGE_t *) &dlmsg->SGL;
@@ -1238,13 +1221,11 @@
  *		-ENODEV  if no such device/adapter
  */
 static int
-mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
+mptctl_getiocinfo (MPT_ADAPTER *ioc, unsigned long arg, unsigned int data_size)
 {
 	struct mpt_ioctl_iocinfo __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_iocinfo *karg;
-	MPT_ADAPTER		*ioc;
 	struct pci_dev		*pdev;
-	int			iocnum;
 	unsigned int		port;
 	int			cim_rev;
 	struct scsi_device 	*sdev;
@@ -1272,14 +1253,6 @@
 		return PTR_ERR(karg);
 	}
 
-	if (((iocnum = mpt_verify_adapter(karg->hdr.iocnum, &ioc)) < 0) ||
-	    (ioc == NULL)) {
-		printk(KERN_DEBUG MYNAM "%s::mptctl_getiocinfo() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum);
-		kfree(karg);
-		return -ENODEV;
-	}
-
 	/* Verify the data transfer size is correct. */
 	if (karg->hdr.maxDataSize != data_size) {
 		printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_getiocinfo - "
@@ -1385,15 +1358,13 @@
  *		-ENODEV  if no such device/adapter
  */
 static int
-mptctl_gettargetinfo (unsigned long arg)
+mptctl_gettargetinfo (MPT_ADAPTER *ioc, unsigned long arg)
 {
 	struct mpt_ioctl_targetinfo __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_targetinfo karg;
-	MPT_ADAPTER		*ioc;
 	VirtDevice		*vdevice;
 	char			*pmem;
 	int			*pdata;
-	int			iocnum;
 	int			numDevices = 0;
 	int			lun;
 	int			maxWordsLeft;
@@ -1408,13 +1379,6 @@
 		return -EFAULT;
 	}
 
-	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-	    (ioc == NULL)) {
-		printk(KERN_DEBUG MYNAM "%s::mptctl_gettargetinfo() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum);
-		return -ENODEV;
-	}
-
 	dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_gettargetinfo called.\n",
 	    ioc->name));
 	/* Get the port number and set the maximum number of bytes
@@ -1510,12 +1474,10 @@
  *		-ENODEV  if no such device/adapter
  */
 static int
-mptctl_readtest (unsigned long arg)
+mptctl_readtest (MPT_ADAPTER *ioc, unsigned long arg)
 {
 	struct mpt_ioctl_test __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_test	 karg;
-	MPT_ADAPTER *ioc;
-	int iocnum;
 
 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_test))) {
 		printk(KERN_ERR MYNAM "%s@%d::mptctl_readtest - "
@@ -1524,13 +1486,6 @@
 		return -EFAULT;
 	}
 
-	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-	    (ioc == NULL)) {
-		printk(KERN_DEBUG MYNAM "%s::mptctl_readtest() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum);
-		return -ENODEV;
-	}
-
 	dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_readtest called.\n",
 	    ioc->name));
 	/* Fill in the data and return the structure to the calling
@@ -1571,12 +1526,10 @@
  *		-ENODEV  if no such device/adapter
  */
 static int
-mptctl_eventquery (unsigned long arg)
+mptctl_eventquery (MPT_ADAPTER *ioc, unsigned long arg)
 {
 	struct mpt_ioctl_eventquery __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_eventquery	 karg;
-	MPT_ADAPTER *ioc;
-	int iocnum;
 
 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventquery))) {
 		printk(KERN_ERR MYNAM "%s@%d::mptctl_eventquery - "
@@ -1585,13 +1538,6 @@
 		return -EFAULT;
 	}
 
-	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-	    (ioc == NULL)) {
-		printk(KERN_DEBUG MYNAM "%s::mptctl_eventquery() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum);
-		return -ENODEV;
-	}
-
 	dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_eventquery called.\n",
 	    ioc->name));
 	karg.eventEntries = MPTCTL_EVENT_LOG_SIZE;
@@ -1610,12 +1556,10 @@
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 static int
-mptctl_eventenable (unsigned long arg)
+mptctl_eventenable (MPT_ADAPTER *ioc, unsigned long arg)
 {
 	struct mpt_ioctl_eventenable __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_eventenable	 karg;
-	MPT_ADAPTER *ioc;
-	int iocnum;
 
 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventenable))) {
 		printk(KERN_ERR MYNAM "%s@%d::mptctl_eventenable - "
@@ -1624,13 +1568,6 @@
 		return -EFAULT;
 	}
 
-	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-	    (ioc == NULL)) {
-		printk(KERN_DEBUG MYNAM "%s::mptctl_eventenable() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum);
-		return -ENODEV;
-	}
-
 	dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_eventenable called.\n",
 	    ioc->name));
 	if (ioc->events == NULL) {
@@ -1658,12 +1595,10 @@
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 static int
-mptctl_eventreport (unsigned long arg)
+mptctl_eventreport (MPT_ADAPTER *ioc, unsigned long arg)
 {
 	struct mpt_ioctl_eventreport __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_eventreport	 karg;
-	MPT_ADAPTER		 *ioc;
-	int			 iocnum;
 	int			 numBytes, maxEvents, max;
 
 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventreport))) {
@@ -1673,12 +1608,6 @@
 		return -EFAULT;
 	}
 
-	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-	    (ioc == NULL)) {
-		printk(KERN_DEBUG MYNAM "%s::mptctl_eventreport() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum);
-		return -ENODEV;
-	}
 	dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_eventreport called.\n",
 	    ioc->name));
 
@@ -1712,12 +1641,10 @@
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 static int
-mptctl_replace_fw (unsigned long arg)
+mptctl_replace_fw (MPT_ADAPTER *ioc, unsigned long arg)
 {
 	struct mpt_ioctl_replace_fw __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_replace_fw	 karg;
-	MPT_ADAPTER		 *ioc;
-	int			 iocnum;
 	int			 newFwSize;
 
 	if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_replace_fw))) {
@@ -1727,13 +1654,6 @@
 		return -EFAULT;
 	}
 
-	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-	    (ioc == NULL)) {
-		printk(KERN_DEBUG MYNAM "%s::mptctl_replace_fw() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum);
-		return -ENODEV;
-	}
-
 	dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_replace_fw called.\n",
 	    ioc->name));
 	/* If caching FW, Free the old FW image
@@ -1780,12 +1700,10 @@
  *		-ENOMEM if memory allocation error
  */
 static int
-mptctl_mpt_command (unsigned long arg)
+mptctl_mpt_command (MPT_ADAPTER *ioc, unsigned long arg)
 {
 	struct mpt_ioctl_command __user *uarg = (void __user *) arg;
 	struct mpt_ioctl_command  karg;
-	MPT_ADAPTER	*ioc;
-	int		iocnum;
 	int		rc;
 
 
@@ -1796,14 +1714,7 @@
 		return -EFAULT;
 	}
 
-	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-	    (ioc == NULL)) {
-		printk(KERN_DEBUG MYNAM "%s::mptctl_mpt_command() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum);
-		return -ENODEV;
-	}
-
-	rc = mptctl_do_mpt_command (karg, &uarg->MF);
+	rc = mptctl_do_mpt_command (ioc, karg, &uarg->MF);
 
 	return rc;
 }
@@ -1821,9 +1732,8 @@
  *		-EPERM if SCSI I/O and target is untagged
  */
 static int
-mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
+mptctl_do_mpt_command (MPT_ADAPTER *ioc, struct mpt_ioctl_command karg, void __user *mfPtr)
 {
-	MPT_ADAPTER	*ioc;
 	MPT_FRAME_HDR	*mf = NULL;
 	MPIHeader_t	*hdr;
 	char		*psge;
@@ -1832,7 +1742,7 @@
 	dma_addr_t	dma_addr_in;
 	dma_addr_t	dma_addr_out;
 	int		sgSize = 0;	/* Num SG elements */
-	int		iocnum, flagsLength;
+	int		flagsLength;
 	int		sz, rc = 0;
 	int		msgContext;
 	u16		req_idx;
@@ -1847,13 +1757,6 @@
 	bufIn.kptr = bufOut.kptr = NULL;
 	bufIn.len = bufOut.len = 0;
 
-	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-	    (ioc == NULL)) {
-		printk(KERN_DEBUG MYNAM "%s::mptctl_do_mpt_command() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum);
-		return -ENODEV;
-	}
-
 	spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
 	if (ioc->ioc_reset_in_progress) {
 		spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
@@ -2418,17 +2321,15 @@
  *		-ENOMEM if memory allocation error
  */
 static int
-mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
+mptctl_hp_hostinfo(MPT_ADAPTER *ioc, unsigned long arg, unsigned int data_size)
 {
 	hp_host_info_t	__user *uarg = (void __user *) arg;
-	MPT_ADAPTER		*ioc;
 	struct pci_dev		*pdev;
 	char                    *pbuf=NULL;
 	dma_addr_t		buf_dma;
 	hp_host_info_t		karg;
 	CONFIGPARMS		cfg;
 	ConfigPageHeader_t	hdr;
-	int			iocnum;
 	int			rc, cim_rev;
 	ToolboxIstwiReadWriteRequest_t	*IstwiRWRequest;
 	MPT_FRAME_HDR		*mf = NULL;
@@ -2452,12 +2353,6 @@
 		return -EFAULT;
 	}
 
-	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-	    (ioc == NULL)) {
-		printk(KERN_DEBUG MYNAM "%s::mptctl_hp_hostinfo() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum);
-		return -ENODEV;
-	}
 	dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": mptctl_hp_hostinfo called.\n",
 	    ioc->name));
 
@@ -2659,15 +2554,13 @@
  *		-ENOMEM if memory allocation error
  */
 static int
-mptctl_hp_targetinfo(unsigned long arg)
+mptctl_hp_targetinfo(MPT_ADAPTER *ioc, unsigned long arg)
 {
 	hp_target_info_t __user *uarg = (void __user *) arg;
 	SCSIDevicePage0_t	*pg0_alloc;
 	SCSIDevicePage3_t	*pg3_alloc;
-	MPT_ADAPTER		*ioc;
 	MPT_SCSI_HOST 		*hd = NULL;
 	hp_target_info_t	karg;
-	int			iocnum;
 	int			data_sz;
 	dma_addr_t		page_dma;
 	CONFIGPARMS	 	cfg;
@@ -2681,12 +2574,6 @@
 		return -EFAULT;
 	}
 
-	if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-		(ioc == NULL)) {
-		printk(KERN_DEBUG MYNAM "%s::mptctl_hp_targetinfo() @%d - ioc%d not found!\n",
-				__FILE__, __LINE__, iocnum);
-		return -ENODEV;
-	}
 	if (karg.hdr.id >= MPT_MAX_FC_DEVICES)
 		return -EINVAL;
 	dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_hp_targetinfo called.\n",
@@ -2854,7 +2741,7 @@
 	kfw.fwlen = kfw32.fwlen;
 	kfw.bufp = compat_ptr(kfw32.bufp);
 
-	ret = mptctl_do_fw_download(kfw.iocnum, kfw.bufp, kfw.fwlen);
+	ret = mptctl_do_fw_download(iocp, kfw.bufp, kfw.fwlen);
 
 	mutex_unlock(&iocp->ioctl_cmds.mutex);
 
@@ -2908,7 +2795,7 @@
 
 	/* Pass new structure to do_mpt_command
 	 */
-	ret = mptctl_do_mpt_command (karg, &uarg->MF);
+	ret = mptctl_do_mpt_command (iocp, karg, &uarg->MF);
 
 	mutex_unlock(&iocp->ioctl_cmds.mutex);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/message/fusion/mptlan.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/message/fusion/mptlan.c
@@ -1430,7 +1430,9 @@
 {
 	MPT_ADAPTER 		*ioc = pci_get_drvdata(pdev);
 	struct net_device	*dev = ioc->netdev;
+	struct mpt_lan_priv *priv = netdev_priv(dev);
 
+	cancel_delayed_work_sync(&priv->post_buckets_task);
 	if(dev != NULL) {
 		unregister_netdev(dev);
 		free_netdev(dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/message/fusion/mptsas.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/message/fusion/mptsas.c
@@ -4205,10 +4205,8 @@
 static void
 mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
 {
-	int rc;
-
 	sdev->no_uld_attach = data ? 1 : 0;
-	rc = scsi_device_reprobe(sdev);
+	WARN_ON(scsi_device_reprobe(sdev));
 }
 
 static void
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/message/fusion/mptscsih.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/message/fusion/mptscsih.c
@@ -118,8 +118,6 @@
 int 		mptscsih_resume(struct pci_dev *pdev);
 #endif
 
-#define SNS_LEN(scp)	SCSI_SENSE_BUFFERSIZE
-
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -1178,8 +1176,10 @@
 	MPT_SCSI_HOST		*hd;
 	int sz1;
 
-	if((hd = shost_priv(host)) == NULL)
-		return;
+	if (host == NULL)
+		hd = NULL;
+	else
+		hd = shost_priv(host);
 
 	mptscsih_shutdown(pdev);
 
@@ -1195,14 +1195,15 @@
 	    "Free'd ScsiLookup (%d) memory\n",
 	    ioc->name, sz1));
 
-	kfree(hd->info_kbuf);
+	if (hd)
+		kfree(hd->info_kbuf);
 
 	/* NULL the Scsi_Host pointer
 	 */
 	ioc->sh = NULL;
 
-	scsi_host_put(host);
-
+	if (host)
+		scsi_host_put(host);
 	mpt_detach(pdev);
 
 }
@@ -2422,7 +2423,7 @@
 		/* Copy the sense received into the scsi command block. */
 		req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
 		sense_data = ((u8 *)ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC));
-		memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc));
+		memcpy(sc->sense_buffer, sense_data, MPT_SENSE_BUFFER_ALLOC);
 
 		/* Log SMART data (asc = 0x5D, non-IM case only) if required.
 		 */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/Kconfig
@@ -758,6 +758,7 @@
 	depends on OF || COMPILE_TEST
 	select MFD_CORE
 	select REGMAP_I2C
+	select REGMAP_IRQ
 	help
 	  Say Y here to add support for Maxim Semiconductor MAX77650 and
 	  MAX77651 Power Management ICs. This is the core multifunction
@@ -1298,6 +1299,7 @@
 
 config MFD_TI_AM335X_TSCADC
 	tristate "TI ADC / Touch Screen chip support"
+	depends on ARCH_OMAP2PLUS || ARCH_K3 || COMPILE_TEST
 	select MFD_CORE
 	select REGMAP
 	select REGMAP_MMIO
@@ -2011,5 +2013,16 @@
 	  Select this to get support for the Supervisory Processor
 	  device found on several devices in RAVE line of hardware.
 
+config MFD_AHC1EC0
+	tristate "Advantech AHC1EC0 Embedded Controller Module"
+	depends on X86
+	depends on UBUNTU_ODM_DRIVERS
+	select MFD_CORE
+	help
+	  This is the core function that for Advantech EC drivers. It
+	  includes the sub-devices such as hwmon, watchdog, etc. And also
+	  provides expose functions for sub-devices to read/write the value
+	  to embedded controller.
+
 endmenu
 endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/Makefile
@@ -256,3 +256,5 @@
 obj-$(CONFIG_MFD_ROHM_BD718XX)	+= rohm-bd718x7.o
 obj-$(CONFIG_MFD_STMFX) 	+= stmfx.o
 
+obj-$(CONFIG_MFD_AHC1EC0)	+= ahc1ec0.o
+
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/ab8500-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/ab8500-core.c
@@ -493,7 +493,7 @@
 		if (line == AB8540_INT_GPIO43F || line == AB8540_INT_GPIO44F)
 			line += 1;
 
-		handle_nested_irq(irq_create_mapping(ab8500->domain, line));
+		handle_nested_irq(irq_find_mapping(ab8500->domain, line));
 	}
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/ahc1ec0.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/ahc1ec0.c
@@ -0,0 +1,808 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Advantech embedded controller core driver AHC1EC0
+ *
+ * Copyright 2020 Advantech IIoT Group
+ *
+ */
+
+#include <linux/acpi.h>
+#include <linux/delay.h>
+#include <linux/dmi.h>
+#include <linux/errno.h>
+#include <linux/mfd/ahc1ec0.h>
+#include <linux/mfd/core.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+
+#define DRV_NAME      "ahc1ec0"
+
+enum {
+	ADVEC_SUBDEV_BRIGHTNESS = 0,
+	ADVEC_SUBDEV_EEPROM,
+	ADVEC_SUBDEV_GPIO,
+	ADVEC_SUBDEV_HWMON,
+	ADVEC_SUBDEV_LED,
+	ADVEC_SUBDEV_WDT,
+	ADVEC_SUBDEV_MAX,
+};
+
+/* Wait IBF (Input Buffer Full) clear */
+static int ec_wait_write(void)
+{
+	int i;
+
+	for (i = 0; i < EC_MAX_TIMEOUT_COUNT; i++) {
+		if ((inb(EC_COMMAND_PORT) & EC_COMMAND_BIT_IBF) == 0)
+			return 0;
+
+		udelay(EC_RETRY_UDELAY);
+	}
+
+	return -ETIMEDOUT;
+}
+
+/* Wait OBF (Output Buffer Full) data ready */
+static int ec_wait_read(void)
+{
+	int i;
+
+	for (i = 0; i < EC_MAX_TIMEOUT_COUNT; i++) {
+		if ((inb(EC_COMMAND_PORT) & EC_COMMAND_BIT_OBF) != 0)
+			return 0;
+
+		udelay(EC_RETRY_UDELAY);
+	}
+
+	return -ETIMEDOUT;
+}
+
+/* Read data from EC HW RAM, the process is the following:
+ * Step 0. Wait IBF clear to send command
+ * Step 1. Send read command to EC command port
+ * Step 2. Wait IBF clear that means command is got by EC
+ * Step 3. Send read address to EC data port
+ * Step 4. Wait OBF data ready
+ * Step 5. Get data from EC data port
+ */
+int read_hw_ram(struct adv_ec_platform_data *adv_ec_data, unsigned char addr, unsigned char *data)
+{
+	int ret;
+
+	mutex_lock(&adv_ec_data->lock);
+
+	ret = ec_wait_write();
+	if (ret)
+		goto error;
+	outb(EC_HW_RAM_READ, EC_COMMAND_PORT);
+
+	ret = ec_wait_write();
+	if (ret)
+		goto error;
+	outb(addr, EC_STATUS_PORT);
+
+	ret = ec_wait_read();
+	if (ret)
+		goto error;
+	*data = inb(EC_STATUS_PORT);
+
+	mutex_unlock(&adv_ec_data->lock);
+
+	return ret;
+
+error:
+	mutex_unlock(&adv_ec_data->lock);
+	dev_err(adv_ec_data->dev, "%s: Wait for IBF or OBF too long. line: %d\n", __func__,
+	       __LINE__);
+
+	return ret;
+}
+
+/* Write data to EC HW RAM
+ * Step 0. Wait IBF clear to send command
+ * Step 1. Send write command to EC command port
+ * Step 2. Wait IBF clear that means command is got by EC
+ * Step 3. Send write address to EC data port
+ * Step 4. Wait IBF clear that means command is got by EC
+ * Step 5. Send data to EC data port
+ */
+int write_hw_ram(struct adv_ec_platform_data *adv_ec_data, unsigned char addr, unsigned char data)
+{
+	int ret;
+
+	mutex_lock(&adv_ec_data->lock);
+
+	ret = ec_wait_write();
+	if (ret)
+		goto error;
+	outb(EC_HW_RAM_WRITE, EC_COMMAND_PORT);
+
+	ret = ec_wait_write();
+	if (ret)
+		goto error;
+	outb(addr, EC_STATUS_PORT);
+
+	ret = ec_wait_write();
+	if (ret)
+		goto error;
+	outb(data, EC_STATUS_PORT);
+
+	mutex_unlock(&adv_ec_data->lock);
+
+	return 0;
+
+error:
+	mutex_unlock(&adv_ec_data->lock);
+
+	dev_err(adv_ec_data->dev, "%s: Wait for IBF or OBF too long. line: %d\n", __func__,
+	       __LINE__);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(write_hw_ram);
+
+/* Get dynamic control table */
+static int adv_get_dynamic_tab(struct adv_ec_platform_data *adv_ec_data)
+{
+	int i, ret;
+	unsigned char pin_tmp, device_id;
+
+	mutex_lock(&adv_ec_data->lock);
+
+	for (i = 0; i < EC_MAX_TBL_NUM; i++) {
+		adv_ec_data->dym_tbl[i].device_id = 0xff;
+		adv_ec_data->dym_tbl[i].hw_pin_num = 0xff;
+	}
+
+	for (i = 0; i < EC_MAX_TBL_NUM; i++) {
+		ret = ec_wait_write();
+		if (ret) {
+			dev_dbg(adv_ec_data->dev, "%s: ec_wait_write. line: %d\n", __func__,
+				__LINE__);
+			goto error;
+		}
+		outb(EC_TBL_WRITE_ITEM, EC_COMMAND_PORT);
+
+		ret = ec_wait_write();
+		if (ret) {
+			dev_dbg(adv_ec_data->dev, "%s: ec_wait_write. line: %d\n", __func__,
+				__LINE__);
+			goto error;
+		}
+		outb(i, EC_STATUS_PORT);
+
+		ret = ec_wait_read();
+		if (ret) {
+			dev_dbg(adv_ec_data->dev, "%s: ec_wait_read. line: %d\n", __func__,
+				__LINE__);
+			goto error;
+		}
+
+		/*
+		 *  If item is defined, EC will return item number.
+		 *  If table item is not defined, EC will return 0xFF.
+		 */
+		pin_tmp = inb(EC_STATUS_PORT);
+		if (pin_tmp == 0xff) {
+			dev_dbg(adv_ec_data->dev, "%s: inb(EC_STATUS_PORT)=0x%02x != 0xff.\n",
+				__func__, pin_tmp);
+			goto pass;
+		}
+
+		ret = ec_wait_write();
+		if (ret) {
+			dev_dbg(adv_ec_data->dev, "%s: ec_wait_write. line: %d\n", __func__,
+				__LINE__);
+			goto error;
+		}
+		outb(EC_TBL_GET_PIN, EC_COMMAND_PORT);
+
+		ret = ec_wait_read();
+		if (ret) {
+			dev_dbg(adv_ec_data->dev, "%s: ec_wait_read. line: %d\n", __func__,
+				__LINE__);
+			goto error;
+		}
+		pin_tmp = inb(EC_STATUS_PORT) & 0xff;
+		if (pin_tmp == 0xff) {
+			dev_dbg(adv_ec_data->dev, "%s: pin_tmp(0x%02X). line: %d\n", __func__,
+				pin_tmp, __LINE__);
+			goto pass;
+		}
+
+		ret = ec_wait_write();
+		if (ret)
+			goto error;
+		outb(EC_TBL_GET_DEVID, EC_COMMAND_PORT);
+
+		ret = ec_wait_read();
+		if (ret) {
+			dev_dbg(adv_ec_data->dev, "%s: ec_wait_read. line: %d\n", __func__,
+				__LINE__);
+			goto error;
+		}
+		device_id = inb(EC_STATUS_PORT) & 0xff;
+
+		dev_dbg(adv_ec_data->dev, "%s: device_id=0x%02X. line: %d\n", __func__,
+			device_id, __LINE__);
+
+		adv_ec_data->dym_tbl[i].device_id = device_id;
+		adv_ec_data->dym_tbl[i].hw_pin_num = pin_tmp;
+	}
+
+pass:
+	mutex_unlock(&adv_ec_data->lock);
+	return 0;
+
+error:
+	mutex_unlock(&adv_ec_data->lock);
+	dev_err(adv_ec_data->dev, "%s: Wait for IBF or OBF too long. line: %d\n",
+		__func__, __LINE__);
+	return ret;
+}
+
+int read_ad_value(struct adv_ec_platform_data *adv_ec_data, unsigned char hwpin,
+		unsigned char multi)
+{
+	int ret;
+	u32 ret_val;
+	unsigned int LSB, MSB;
+
+	mutex_lock(&adv_ec_data->lock);
+	ret = ec_wait_write();
+	if (ret)
+		goto error;
+	outb(EC_AD_INDEX_WRITE, EC_COMMAND_PORT);
+
+	ret = ec_wait_write();
+	if (ret)
+		goto error;
+	outb(hwpin, EC_STATUS_PORT);
+
+	ret = ec_wait_read();
+	if (ret)
+		goto error;
+
+	if (inb(EC_STATUS_PORT) == 0xff) {
+		mutex_unlock(&adv_ec_data->lock);
+		return -1;
+	}
+
+	ret = ec_wait_write();
+	if (ret)
+		goto error;
+	outb(EC_AD_LSB_READ, EC_COMMAND_PORT);
+
+	ret = ec_wait_read();
+	if (ret)
+		goto error;
+	LSB = inb(EC_STATUS_PORT);
+
+	ret = ec_wait_write();
+	if (ret)
+		goto error;
+	outb(EC_AD_MSB_READ, EC_COMMAND_PORT);
+
+	ret = ec_wait_read();
+	if (ret)
+		goto error;
+	MSB = inb(EC_STATUS_PORT);
+	ret_val = ((MSB << 8) | LSB) & 0x03FF;
+	ret_val = ret_val * multi * 100;
+
+	mutex_unlock(&adv_ec_data->lock);
+	return ret_val;
+
+error:
+	mutex_unlock(&adv_ec_data->lock);
+
+	dev_warn(adv_ec_data->dev, "%s: Wait for IBF or OBF too long. line: %d\n", __func__,
+		__LINE__);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(read_ad_value);
+
+int read_acpi_value(struct adv_ec_platform_data *adv_ec_data, unsigned char addr,
+		unsigned char *pvalue)
+{
+	int ret;
+	unsigned char value;
+
+	mutex_lock(&adv_ec_data->lock);
+
+	ret = ec_wait_write();
+	if (ret)
+		goto error;
+	outb(EC_ACPI_RAM_READ, EC_COMMAND_PORT);
+
+	ret = ec_wait_write();
+	if (ret)
+		goto error;
+	outb(addr, EC_STATUS_PORT);
+
+	ret = ec_wait_read();
+	if (ret)
+		goto error;
+	value = inb(EC_STATUS_PORT);
+	*pvalue = value;
+
+	mutex_unlock(&adv_ec_data->lock);
+
+	return 0;
+
+error:
+	mutex_unlock(&adv_ec_data->lock);
+
+	dev_warn(adv_ec_data->dev, "%s: Wait for IBF or OBF too long. line: %d\n", __func__,
+		__LINE__);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(read_acpi_value);
+
+int write_acpi_value(struct adv_ec_platform_data *adv_ec_data, unsigned char addr,
+		unsigned char value)
+{
+	int ret;
+
+	mutex_lock(&adv_ec_data->lock);
+
+	ret = ec_wait_write();
+	if (ret)
+		goto error;
+	outb(EC_ACPI_DATA_WRITE, EC_COMMAND_PORT);
+
+	ret = ec_wait_write();
+	if (ret)
+		goto error;
+	outb(addr, EC_STATUS_PORT);
+
+	ret = ec_wait_write();
+	if (ret)
+		goto error;
+	outb(value, EC_STATUS_PORT);
+
+	mutex_unlock(&adv_ec_data->lock);
+	return 0;
+
+error:
+	mutex_unlock(&adv_ec_data->lock);
+
+	dev_warn(adv_ec_data->dev, "%s: Wait for IBF or OBF too long. line: %d\n", __func__,
+		__LINE__);
+
+	return ret;
+}
+
+int read_gpio_status(struct adv_ec_platform_data *adv_ec_data, unsigned char PinNumber,
+		unsigned char *pvalue)
+{
+	int ret;
+
+	unsigned char gpio_status_value;
+
+	mutex_lock(&adv_ec_data->lock);
+
+	ret = ec_wait_write();
+	if (ret)
+		goto error;
+	outb(EC_GPIO_INDEX_WRITE, EC_COMMAND_PORT);
+
+	ret = ec_wait_write();
+	if (ret)
+		goto error;
+	outb(PinNumber, EC_STATUS_PORT);
+
+	ret = ec_wait_read();
+	if (ret)
+		goto error;
+
+	if (inb(EC_STATUS_PORT) == 0xff) {
+		dev_err(adv_ec_data->dev, "%s: Read Pin Number error!!\n", __func__);
+		mutex_unlock(&adv_ec_data->lock);
+		return -1;
+	}
+
+	ret = ec_wait_write();
+	if (ret)
+		goto error;
+	outb(EC_GPIO_STATUS_READ, EC_COMMAND_PORT);
+
+	ret = ec_wait_read();
+	if (ret)
+		goto error;
+	gpio_status_value = inb(EC_STATUS_PORT);
+
+	*pvalue = gpio_status_value;
+	mutex_unlock(&adv_ec_data->lock);
+	return 0;
+
+error:
+	mutex_unlock(&adv_ec_data->lock);
+
+	dev_warn(adv_ec_data->dev, "%s: Wait for IBF or OBF too long. line: %d\n", __func__,
+		__LINE__);
+	return ret;
+}
+
+int write_gpio_status(struct adv_ec_platform_data *adv_ec_data, unsigned char PinNumber,
+		unsigned char value)
+{
+	int ret;
+
+	mutex_lock(&adv_ec_data->lock);
+
+	ret = ec_wait_write();
+	if (ret)
+		goto error;
+	outb(EC_GPIO_INDEX_WRITE, EC_COMMAND_PORT);
+
+	ret = ec_wait_write();
+	if (ret)
+		goto error;
+	outb(PinNumber, EC_STATUS_PORT);
+
+	ret = ec_wait_read();
+	if (ret)
+		goto error;
+
+	if (inb(EC_STATUS_PORT) == 0xff) {
+		mutex_unlock(&adv_ec_data->lock);
+		dev_err(adv_ec_data->dev, "%s: Read Pin Number error!!\n", __func__);
+		return -1;
+	}
+
+	ret = ec_wait_write();
+	if (ret)
+		goto error;
+	outb(EC_GPIO_STATUS_WRITE, EC_COMMAND_PORT);
+
+	ret = ec_wait_write();
+	if (ret)
+		goto error;
+	outb(value, EC_STATUS_PORT);
+
+	mutex_unlock(&adv_ec_data->lock);
+	return 0;
+
+error:
+	mutex_unlock(&adv_ec_data->lock);
+	dev_err(adv_ec_data->dev, "%s: Wait for IBF or OBF too long. line: %d", __func__,
+		__LINE__);
+
+	return ret;
+}
+
+int read_gpio_dir(struct adv_ec_platform_data *adv_ec_data, unsigned char PinNumber,
+		unsigned char *pvalue)
+{
+	int ret;
+	unsigned char gpio_dir_value;
+
+	mutex_lock(&adv_ec_data->lock);
+
+	ret = ec_wait_write();
+	if (ret)
+		goto error;
+	outb(EC_GPIO_INDEX_WRITE, EC_COMMAND_PORT);
+
+	ret = ec_wait_write();
+	if (ret)
+		goto error;
+	outb(PinNumber, EC_STATUS_PORT);
+
+	ret = ec_wait_read();
+	if (ret)
+		goto error;
+
+	if (inb(EC_STATUS_PORT) == 0xff) {
+		mutex_unlock(&adv_ec_data->lock);
+		dev_err(adv_ec_data->dev, "%s: Read Pin Number error!! line: %d\n", __func__,
+			__LINE__);
+		return -1;
+	}
+
+	ret = ec_wait_write();
+	if (ret)
+		goto error;
+	outb(EC_GPIO_DIR_READ, EC_COMMAND_PORT);
+
+	ret = ec_wait_read();
+	if (ret)
+		goto error;
+	gpio_dir_value = inb(EC_STATUS_PORT);
+	*pvalue = gpio_dir_value;
+
+	mutex_unlock(&adv_ec_data->lock);
+	return 0;
+
+error:
+	mutex_unlock(&adv_ec_data->lock);
+
+	dev_warn(adv_ec_data->dev, "%s: Wait for IBF or OBF too long. line: %d\n", __func__,
+			__LINE__);
+
+	return ret;
+}
+
+int write_gpio_dir(struct adv_ec_platform_data *adv_ec_data, unsigned char PinNumber,
+		unsigned char value)
+{
+	int ret;
+
+	mutex_lock(&adv_ec_data->lock);
+
+	ret = ec_wait_write();
+	if (ret)
+		goto error;
+	outb(EC_GPIO_INDEX_WRITE, EC_COMMAND_PORT);
+
+	ret = ec_wait_write();
+	if (ret)
+		goto error;
+	outb(PinNumber, EC_STATUS_PORT);
+
+	ret = ec_wait_read();
+	if (ret)
+		goto error;
+
+	if (inb(EC_STATUS_PORT) == 0xff) {
+		mutex_unlock(&adv_ec_data->lock);
+		dev_warn(adv_ec_data->dev, "%s: Read Pin Number error!! line: %d\n", __func__,
+			__LINE__);
+
+		return -1;
+	}
+
+	ret = ec_wait_write();
+	if (ret)
+		goto error;
+	outb(EC_GPIO_DIR_WRITE, EC_COMMAND_PORT);
+
+	ret = ec_wait_write();
+	if (ret)
+		goto error;
+	outb(value, EC_STATUS_PORT);
+
+	mutex_unlock(&adv_ec_data->lock);
+	return 0;
+
+error:
+	mutex_unlock(&adv_ec_data->lock);
+
+	dev_warn(adv_ec_data->dev, "%s: Wait for IBF or OBF too long. line: %d\n", __func__,
+			__LINE__);
+
+	return ret;
+}
+
+int write_hwram_command(struct adv_ec_platform_data *adv_ec_data, unsigned char data)
+{
+	int ret;
+
+	mutex_lock(&adv_ec_data->lock);
+
+	ret = ec_wait_write();
+	if (ret)
+		goto error;
+	outb(data, EC_COMMAND_PORT);
+
+	mutex_unlock(&adv_ec_data->lock);
+	return 0;
+
+error:
+	mutex_unlock(&adv_ec_data->lock);
+
+	dev_warn(adv_ec_data->dev, "%s: Wait for IBF or OBF too long. line: %d\n", __func__,
+			__LINE__);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(write_hwram_command);
+
+static int adv_ec_get_productname(struct adv_ec_platform_data *adv_ec_data, char *product)
+{
+	const char *vendor, *device;
+	int length = 0;
+
+	/* Check it is Advantech board */
+	vendor = dmi_get_system_info(DMI_SYS_VENDOR);
+	if (memcmp(vendor, "Advantech", sizeof("Advantech")) != 0)
+		return -ENODEV;
+
+	/* Get product model name */
+	device = dmi_get_system_info(DMI_PRODUCT_NAME);
+	if (device) {
+		while ((device[length] != ' ')
+			&& (length < AMI_ADVANTECH_BOARD_ID_LENGTH))
+			length++;
+		memset(product, 0, AMI_ADVANTECH_BOARD_ID_LENGTH);
+		memmove(product, device, length);
+
+		dev_info(adv_ec_data->dev, "BIOS Product Name = %s\n", product);
+
+		return 0;
+	}
+
+	dev_warn(adv_ec_data->dev, "This device is not Advantech Board (%s)!\n", product);
+
+	return -ENODEV;
+}
+
+static const struct mfd_cell adv_ec_sub_cells[] = {
+	{ .name = "adv-ec-brightness", },
+	{ .name = "adv-ec-eeprom", },
+	{ .name = "adv-ec-gpio", },
+	{ .name = "ahc1ec0-hwmon", },
+	{ .name = "adv-ec-led", },
+	{ .name = "ahc1ec0-wdt", },
+};
+
+static int adv_ec_init_ec_data(struct adv_ec_platform_data *adv_ec_data)
+{
+	int ret;
+
+	adv_ec_data->sub_dev_mask = 0;
+	adv_ec_data->sub_dev_nb = 0;
+	adv_ec_data->dym_tbl = NULL;
+	adv_ec_data->bios_product_name = NULL;
+
+	mutex_init(&adv_ec_data->lock);
+
+	/* Get product name */
+	adv_ec_data->bios_product_name =
+		devm_kzalloc(adv_ec_data->dev, AMI_ADVANTECH_BOARD_ID_LENGTH, GFP_KERNEL);
+	if (!adv_ec_data->bios_product_name)
+		return -ENOMEM;
+
+	memset(adv_ec_data->bios_product_name, 0, AMI_ADVANTECH_BOARD_ID_LENGTH);
+	ret = adv_ec_get_productname(adv_ec_data, adv_ec_data->bios_product_name);
+	if (ret)
+		return ret;
+
+	/* Get pin table */
+	adv_ec_data->dym_tbl = devm_kzalloc(adv_ec_data->dev,
+					EC_MAX_TBL_NUM * sizeof(struct ec_dynamic_table),
+					GFP_KERNEL);
+	if (!adv_ec_data->dym_tbl)
+		return -ENOMEM;
+
+	ret = adv_get_dynamic_tab(adv_ec_data);
+
+	return ret;
+}
+
+static int adv_ec_parse_prop(struct adv_ec_platform_data *adv_ec_data)
+{
+	int i, ret;
+	u32 nb, sub_dev[ADVEC_SUBDEV_MAX];
+
+	ret = device_property_read_u32(adv_ec_data->dev, "advantech,sub-dev-nb", &nb);
+	if (ret < 0) {
+		dev_err(adv_ec_data->dev, "get sub-dev-nb failed! (%d)\n", ret);
+		return ret;
+	}
+	adv_ec_data->sub_dev_nb = nb;
+
+	ret = device_property_read_u32_array(adv_ec_data->dev, "advantech,sub-dev",
+					     sub_dev, nb);
+	if (ret < 0) {
+		dev_err(adv_ec_data->dev, "get sub-dev failed! (%d)\n", ret);
+		return ret;
+	}
+
+	for (i = 0; i < nb; i++) {
+		switch (sub_dev[i]) {
+		case ADVEC_SUBDEV_BRIGHTNESS:
+		case ADVEC_SUBDEV_EEPROM:
+		case ADVEC_SUBDEV_GPIO:
+		case ADVEC_SUBDEV_HWMON:
+		case ADVEC_SUBDEV_LED:
+		case ADVEC_SUBDEV_WDT:
+			adv_ec_data->sub_dev_mask |= BIT(sub_dev[i]);
+			break;
+		default:
+			dev_err(adv_ec_data->dev, "invalid prop value(%d)!\n",
+				sub_dev[i]);
+		}
+	}
+	dev_info(adv_ec_data->dev, "sub-dev mask = 0x%x\n", adv_ec_data->sub_dev_mask);
+
+	return 0;
+}
+
+static int adv_ec_probe(struct platform_device *pdev)
+{
+	int ret, i;
+	struct device *dev = &pdev->dev;
+	struct adv_ec_platform_data *adv_ec_data;
+
+	adv_ec_data = devm_kzalloc(dev, sizeof(struct adv_ec_platform_data), GFP_KERNEL);
+	if (!adv_ec_data)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, adv_ec_data);
+	adv_ec_data->dev = dev;
+
+	ret = adv_ec_init_ec_data(adv_ec_data);
+	if (ret)
+		goto err_init_data;
+
+	ret = adv_ec_parse_prop(adv_ec_data);
+	if (ret)
+		goto err_prop;
+
+	/* check whether this EC has the following subdevices. */
+	for (i = 0; i < ARRAY_SIZE(adv_ec_sub_cells); i++) {
+		if (adv_ec_data->sub_dev_mask & BIT(i)) {
+			ret = mfd_add_hotplug_devices(dev, &adv_ec_sub_cells[i], 1);
+			dev_info(adv_ec_data->dev, "mfd_add_hotplug_devices[%d] %s\n", i,
+				adv_ec_sub_cells[i].name);
+			if (ret)
+				dev_err(dev, "failed to add %s subdevice: %d\n",
+					adv_ec_sub_cells[i].name, ret);
+		}
+	}
+
+	dev_info(adv_ec_data->dev, "Advantech EC probe done");
+
+	return 0;
+
+err_prop:
+	dev_err(dev, "failed to probe\n");
+
+err_init_data:
+	mutex_destroy(&adv_ec_data->lock);
+
+	dev_err(dev, "failed to init data\n");
+
+	return ret;
+}
+
+static int adv_ec_remove(struct platform_device *pdev)
+{
+	struct adv_ec_platform_data *adv_ec_data;
+
+	adv_ec_data = dev_get_drvdata(&pdev->dev);
+
+	mutex_destroy(&adv_ec_data->lock);
+
+	mfd_remove_devices(&pdev->dev);
+
+	return 0;
+}
+
+static const struct of_device_id adv_ec_of_match[] __maybe_unused = {
+	{
+		.compatible = "advantech,ahc1ec0",
+	},
+	{}
+};
+MODULE_DEVICE_TABLE(of, adv_ec_of_match);
+
+static const struct acpi_device_id adv_ec_acpi_match[] __maybe_unused = {
+	{"AHC1EC0", 0},
+	{},
+};
+MODULE_DEVICE_TABLE(acpi, adv_ec_acpi_match);
+
+static struct platform_driver adv_ec_driver = {
+	.driver = {
+		.name = DRV_NAME,
+		.of_match_table = of_match_ptr(adv_ec_of_match),
+		.acpi_match_table = ACPI_PTR(adv_ec_acpi_match),
+	},
+	.probe = adv_ec_probe,
+	.remove = adv_ec_remove,
+};
+module_platform_driver(adv_ec_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DESCRIPTION("Advantech Embedded Controller core driver.");
+MODULE_AUTHOR("Campion Kang <campion.kang@advantech.com.tw>");
+MODULE_AUTHOR("Jianfeng Dai <jianfeng.dai@advantech.com.cn>");
+MODULE_VERSION("1.0");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/altera-sysmgr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/altera-sysmgr.c
@@ -109,7 +109,9 @@
 
 	dev = driver_find_device_by_of_node(&altr_sysmgr_driver.driver,
 					    (void *)sysmgr_np);
-	of_node_put(sysmgr_np);
+	if (property)
+		of_node_put(sysmgr_np);
+
 	if (!dev)
 		return ERR_PTR(-EPROBE_DEFER);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/arizona-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/arizona-core.c
@@ -45,7 +45,7 @@
 	if (arizona->clk32k_ref == 1) {
 		switch (arizona->pdata.clk32k_src) {
 		case ARIZONA_32KZ_MCLK1:
-			ret = pm_runtime_get_sync(arizona->dev);
+			ret = pm_runtime_resume_and_get(arizona->dev);
 			if (ret != 0)
 				goto err_ref;
 			ret = clk_prepare_enable(arizona->mclk[ARIZONA_MCLK1]);
@@ -1430,6 +1430,15 @@
 	arizona_irq_exit(arizona);
 err_pm:
 	pm_runtime_disable(arizona->dev);
+
+	switch (arizona->pdata.clk32k_src) {
+	case ARIZONA_32KZ_MCLK1:
+	case ARIZONA_32KZ_MCLK2:
+		arizona_clk32k_disable(arizona);
+		break;
+	default:
+		break;
+	}
 err_reset:
 	arizona_enable_reset(arizona);
 	regulator_disable(arizona->dcvdd);
@@ -1452,6 +1461,15 @@
 	regulator_disable(arizona->dcvdd);
 	regulator_put(arizona->dcvdd);
 
+	switch (arizona->pdata.clk32k_src) {
+	case ARIZONA_32KZ_MCLK1:
+	case ARIZONA_32KZ_MCLK2:
+		arizona_clk32k_disable(arizona);
+		break;
+	default:
+		break;
+	}
+
 	mfd_remove_devices(arizona->dev);
 	arizona_free_irq(arizona, ARIZONA_IRQ_UNDERCLOCKED, arizona);
 	arizona_free_irq(arizona, ARIZONA_IRQ_OVERCLOCKED, arizona);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/arizona-irq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/arizona-irq.c
@@ -100,7 +100,7 @@
 	unsigned int val;
 	int ret;
 
-	ret = pm_runtime_get_sync(arizona->dev);
+	ret = pm_runtime_resume_and_get(arizona->dev);
 	if (ret < 0) {
 		dev_err(arizona->dev, "Failed to resume device: %d\n", ret);
 		return IRQ_NONE;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/asic3.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/asic3.c
@@ -914,14 +914,14 @@
 		ret = mfd_add_devices(&pdev->dev, pdev->id,
 			&asic3_cell_ds1wm, 1, mem, asic->irq_base, NULL);
 		if (ret < 0)
-			goto out;
+			goto out_unmap;
 	}
 
 	if (mem_sdio && (irq >= 0)) {
 		ret = mfd_add_devices(&pdev->dev, pdev->id,
 			&asic3_cell_mmc, 1, mem_sdio, irq, NULL);
 		if (ret < 0)
-			goto out;
+			goto out_unmap;
 	}
 
 	ret = 0;
@@ -935,8 +935,12 @@
 		ret = mfd_add_devices(&pdev->dev, 0,
 			asic3_cell_leds, ASIC3_NUM_LEDS, NULL, 0, NULL);
 	}
+	return ret;
 
- out:
+out_unmap:
+	if (asic->tmio_cnf)
+		iounmap(asic->tmio_cnf);
+out:
 	return ret;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/axp20x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/axp20x.c
@@ -125,12 +125,13 @@
 
 static const struct regmap_range axp288_volatile_ranges[] = {
 	regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP288_POWER_REASON),
+	regmap_reg_range(AXP22X_PWR_OUT_CTRL1, AXP22X_ALDO3_V_OUT),
 	regmap_reg_range(AXP288_BC_GLOBAL, AXP288_BC_GLOBAL),
-	regmap_reg_range(AXP288_BC_DET_STAT, AXP288_BC_DET_STAT),
+	regmap_reg_range(AXP288_BC_DET_STAT, AXP20X_VBUS_IPSOUT_MGMT),
 	regmap_reg_range(AXP20X_CHRG_BAK_CTRL, AXP20X_CHRG_BAK_CTRL),
 	regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IPSOUT_V_HIGH_L),
 	regmap_reg_range(AXP20X_TIMER_CTRL, AXP20X_TIMER_CTRL),
-	regmap_reg_range(AXP22X_GPIO_STATE, AXP22X_GPIO_STATE),
+	regmap_reg_range(AXP20X_GPIO1_CTRL, AXP22X_GPIO_STATE),
 	regmap_reg_range(AXP288_RT_BATT_V_H, AXP288_RT_BATT_V_L),
 	regmap_reg_range(AXP20X_FG_RES, AXP288_FG_CC_CAP_REG),
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/bd9571mwv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/bd9571mwv.c
@@ -185,9 +185,9 @@
 		return ret;
 	}
 
-	ret = mfd_add_devices(bd->dev, PLATFORM_DEVID_AUTO, bd9571mwv_cells,
-			      ARRAY_SIZE(bd9571mwv_cells), NULL, 0,
-			      regmap_irq_get_domain(bd->irq_data));
+	ret = devm_mfd_add_devices(bd->dev, PLATFORM_DEVID_AUTO,
+				   bd9571mwv_cells, ARRAY_SIZE(bd9571mwv_cells),
+				   NULL, 0, regmap_irq_get_domain(bd->irq_data));
 	if (ret) {
 		regmap_del_irq_chip(bd->irq, bd->irq_data);
 		return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/da9052-i2c.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/da9052-i2c.c
@@ -113,6 +113,7 @@
 	{"da9053-bc", DA9053_BC},
 	{}
 };
+MODULE_DEVICE_TABLE(i2c, da9052_i2c_id);
 
 #ifdef CONFIG_OF
 static const struct of_device_id dialog_dt_ids[] = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/da9052-spi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/da9052-spi.c
@@ -37,7 +37,7 @@
 	spi_set_drvdata(spi, da9052);
 
 	config = da9052_regmap_config;
-	config.read_flag_mask = 1;
+	config.write_flag_mask = 1;
 	config.reg_bits = 7;
 	config.pad_bits = 1;
 	config.val_bits = 8;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/da9062-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/da9062-core.c
@@ -248,7 +248,7 @@
 		.name		= "da9062-watchdog",
 		.num_resources	= ARRAY_SIZE(da9062_wdt_resources),
 		.resources	= da9062_wdt_resources,
-		.of_compatible  = "dlg,da9062-wdt",
+		.of_compatible  = "dlg,da9062-watchdog",
 	},
 	{
 		.name		= "da9062-thermal",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/davinci_voicecodec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/davinci_voicecodec.c
@@ -46,14 +46,12 @@
 	}
 	clk_enable(davinci_vc->clk);
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
-	fifo_base = (dma_addr_t)res->start;
-	davinci_vc->base = devm_ioremap_resource(&pdev->dev, res);
+	davinci_vc->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
 	if (IS_ERR(davinci_vc->base)) {
 		ret = PTR_ERR(davinci_vc->base);
 		goto fail;
 	}
+	fifo_base = (dma_addr_t)res->start;
 
 	davinci_vc->regmap = devm_regmap_init_mmio(&pdev->dev,
 						   davinci_vc->base,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/db8500-prcmu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/db8500-prcmu.c
@@ -1695,22 +1695,20 @@
 }
 
 static const unsigned long db8500_armss_freqs[] = {
-	200000000,
-	400000000,
-	800000000,
+	199680000,
+	399360000,
+	798720000,
 	998400000
 };
 
 /* The DB8520 has slightly higher ARMSS max frequency */
 static const unsigned long db8520_armss_freqs[] = {
-	200000000,
-	400000000,
-	800000000,
+	199680000,
+	399360000,
+	798720000,
 	1152000000
 };
 
-
-
 static long round_armss_rate(unsigned long rate)
 {
 	unsigned long freq = 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/dln2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/dln2.c
@@ -90,6 +90,11 @@
 	spinlock_t lock;
 };
 
+enum dln2_endpoint {
+	DLN2_EP_OUT	= 0,
+	DLN2_EP_IN	= 1,
+};
+
 struct dln2_dev {
 	struct usb_device *usb_dev;
 	struct usb_interface *interface;
@@ -282,7 +287,11 @@
 	len = urb->actual_length - sizeof(struct dln2_header);
 
 	if (handle == DLN2_HANDLE_EVENT) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&dln2->event_cb_lock, flags);
 		dln2_run_event_callbacks(dln2, id, echo, data, len);
+		spin_unlock_irqrestore(&dln2->event_cb_lock, flags);
 	} else {
 		/* URB will be re-submitted in _dln2_transfer (free_rx_slot) */
 		if (dln2_transfer_complete(dln2, urb, handle, echo))
@@ -722,6 +731,8 @@
 		      const struct usb_device_id *usb_id)
 {
 	struct usb_host_interface *hostif = interface->cur_altsetting;
+	struct usb_endpoint_descriptor *epin;
+	struct usb_endpoint_descriptor *epout;
 	struct device *dev = &interface->dev;
 	struct dln2_dev *dln2;
 	int ret;
@@ -731,12 +742,19 @@
 	    hostif->desc.bNumEndpoints < 2)
 		return -ENODEV;
 
+	epout = &hostif->endpoint[DLN2_EP_OUT].desc;
+	if (!usb_endpoint_is_bulk_out(epout))
+		return -ENODEV;
+	epin = &hostif->endpoint[DLN2_EP_IN].desc;
+	if (!usb_endpoint_is_bulk_in(epin))
+		return -ENODEV;
+
 	dln2 = kzalloc(sizeof(*dln2), GFP_KERNEL);
 	if (!dln2)
 		return -ENOMEM;
 
-	dln2->ep_out = hostif->endpoint[0].desc.bEndpointAddress;
-	dln2->ep_in = hostif->endpoint[1].desc.bEndpointAddress;
+	dln2->ep_out = epout->bEndpointAddress;
+	dln2->ep_in = epin->bEndpointAddress;
 	dln2->usb_dev = usb_get_dev(interface_to_usbdev(interface));
 	dln2->interface = interface;
 	usb_set_intfdata(interface, dln2);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/fsl-imx25-tsadc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/fsl-imx25-tsadc.c
@@ -69,7 +69,7 @@
 	int irq;
 
 	irq = platform_get_irq(pdev, 0);
-	if (irq <= 0)
+	if (irq < 0)
 		return irq;
 
 	tsadc->domain = irq_domain_add_simple(np, 2, 0, &mx25_tsadc_domain_ops,
@@ -84,6 +84,19 @@
 	return 0;
 }
 
+static int mx25_tsadc_unset_irq(struct platform_device *pdev)
+{
+	struct mx25_tsadc *tsadc = platform_get_drvdata(pdev);
+	int irq = platform_get_irq(pdev, 0);
+
+	if (irq >= 0) {
+		irq_set_chained_handler_and_data(irq, NULL, NULL);
+		irq_domain_remove(tsadc->domain);
+	}
+
+	return 0;
+}
+
 static void mx25_tsadc_setup_clk(struct platform_device *pdev,
 				 struct mx25_tsadc *tsadc)
 {
@@ -171,18 +184,21 @@
 
 	platform_set_drvdata(pdev, tsadc);
 
-	return devm_of_platform_populate(dev);
+	ret = devm_of_platform_populate(dev);
+	if (ret)
+		goto err_irq;
+
+	return 0;
+
+err_irq:
+	mx25_tsadc_unset_irq(pdev);
+
+	return ret;
 }
 
 static int mx25_tsadc_remove(struct platform_device *pdev)
 {
-	struct mx25_tsadc *tsadc = platform_get_drvdata(pdev);
-	int irq = platform_get_irq(pdev, 0);
-
-	if (irq) {
-		irq_set_chained_handler_and_data(irq, NULL, NULL);
-		irq_domain_remove(tsadc->domain);
-	}
+	mx25_tsadc_unset_irq(pdev);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/intel-lpss-acpi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/intel-lpss-acpi.c
@@ -102,6 +102,7 @@
 {
 	struct intel_lpss_platform_info *info;
 	const struct acpi_device_id *id;
+	int ret;
 
 	id = acpi_match_device(intel_lpss_acpi_ids, &pdev->dev);
 	if (!id)
@@ -113,12 +114,19 @@
 		return -ENOMEM;
 
 	info->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!info->mem)
+		return -ENODEV;
+
 	info->irq = platform_get_irq(pdev, 0);
 
+	ret = intel_lpss_probe(&pdev->dev, info);
+	if (ret)
+		return ret;
+
 	pm_runtime_set_active(&pdev->dev);
 	pm_runtime_enable(&pdev->dev);
 
-	return intel_lpss_probe(&pdev->dev, info);
+	return 0;
 }
 
 static int intel_lpss_acpi_remove(struct platform_device *pdev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/intel-lpss-pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/intel-lpss-pci.c
@@ -122,13 +122,25 @@
 	.properties = apl_i2c_properties,
 };
 
+static struct property_entry glk_i2c_properties[] = {
+	PROPERTY_ENTRY_U32("i2c-sda-hold-time-ns", 313),
+	PROPERTY_ENTRY_U32("i2c-sda-falling-time-ns", 171),
+	PROPERTY_ENTRY_U32("i2c-scl-falling-time-ns", 290),
+	{ },
+};
+
+static const struct intel_lpss_platform_info glk_i2c_info = {
+	.clk_rate = 133000000,
+	.properties = glk_i2c_properties,
+};
+
 static const struct intel_lpss_platform_info cnl_i2c_info = {
 	.clk_rate = 216000000,
 	.properties = spt_i2c_properties,
 };
 
 static const struct pci_device_id intel_lpss_pci_ids[] = {
-	/* CML */
+	/* CML-LP */
 	{ PCI_VDEVICE(INTEL, 0x02a8), (kernel_ulong_t)&spt_uart_info },
 	{ PCI_VDEVICE(INTEL, 0x02a9), (kernel_ulong_t)&spt_uart_info },
 	{ PCI_VDEVICE(INTEL, 0x02aa), (kernel_ulong_t)&spt_info },
@@ -141,6 +153,17 @@
 	{ PCI_VDEVICE(INTEL, 0x02ea), (kernel_ulong_t)&cnl_i2c_info },
 	{ PCI_VDEVICE(INTEL, 0x02eb), (kernel_ulong_t)&cnl_i2c_info },
 	{ PCI_VDEVICE(INTEL, 0x02fb), (kernel_ulong_t)&spt_info },
+	/* CML-H */
+	{ PCI_VDEVICE(INTEL, 0x06a8), (kernel_ulong_t)&spt_uart_info },
+	{ PCI_VDEVICE(INTEL, 0x06a9), (kernel_ulong_t)&spt_uart_info },
+	{ PCI_VDEVICE(INTEL, 0x06aa), (kernel_ulong_t)&spt_info },
+	{ PCI_VDEVICE(INTEL, 0x06ab), (kernel_ulong_t)&spt_info },
+	{ PCI_VDEVICE(INTEL, 0x06c7), (kernel_ulong_t)&spt_uart_info },
+	{ PCI_VDEVICE(INTEL, 0x06e8), (kernel_ulong_t)&cnl_i2c_info },
+	{ PCI_VDEVICE(INTEL, 0x06e9), (kernel_ulong_t)&cnl_i2c_info },
+	{ PCI_VDEVICE(INTEL, 0x06ea), (kernel_ulong_t)&cnl_i2c_info },
+	{ PCI_VDEVICE(INTEL, 0x06eb), (kernel_ulong_t)&cnl_i2c_info },
+	{ PCI_VDEVICE(INTEL, 0x06fb), (kernel_ulong_t)&spt_info },
 	/* BXT A-Step */
 	{ PCI_VDEVICE(INTEL, 0x0aac), (kernel_ulong_t)&bxt_i2c_info },
 	{ PCI_VDEVICE(INTEL, 0x0aae), (kernel_ulong_t)&bxt_i2c_info },
@@ -173,15 +196,18 @@
 	{ PCI_VDEVICE(INTEL, 0x1ac4), (kernel_ulong_t)&bxt_info },
 	{ PCI_VDEVICE(INTEL, 0x1ac6), (kernel_ulong_t)&bxt_info },
 	{ PCI_VDEVICE(INTEL, 0x1aee), (kernel_ulong_t)&bxt_uart_info },
+	/* EBG */
+	{ PCI_VDEVICE(INTEL, 0x1bad), (kernel_ulong_t)&bxt_uart_info },
+	{ PCI_VDEVICE(INTEL, 0x1bae), (kernel_ulong_t)&bxt_uart_info },
 	/* GLK */
-	{ PCI_VDEVICE(INTEL, 0x31ac), (kernel_ulong_t)&bxt_i2c_info },
-	{ PCI_VDEVICE(INTEL, 0x31ae), (kernel_ulong_t)&bxt_i2c_info },
-	{ PCI_VDEVICE(INTEL, 0x31b0), (kernel_ulong_t)&bxt_i2c_info },
-	{ PCI_VDEVICE(INTEL, 0x31b2), (kernel_ulong_t)&bxt_i2c_info },
-	{ PCI_VDEVICE(INTEL, 0x31b4), (kernel_ulong_t)&bxt_i2c_info },
-	{ PCI_VDEVICE(INTEL, 0x31b6), (kernel_ulong_t)&bxt_i2c_info },
-	{ PCI_VDEVICE(INTEL, 0x31b8), (kernel_ulong_t)&bxt_i2c_info },
-	{ PCI_VDEVICE(INTEL, 0x31ba), (kernel_ulong_t)&bxt_i2c_info },
+	{ PCI_VDEVICE(INTEL, 0x31ac), (kernel_ulong_t)&glk_i2c_info },
+	{ PCI_VDEVICE(INTEL, 0x31ae), (kernel_ulong_t)&glk_i2c_info },
+	{ PCI_VDEVICE(INTEL, 0x31b0), (kernel_ulong_t)&glk_i2c_info },
+	{ PCI_VDEVICE(INTEL, 0x31b2), (kernel_ulong_t)&glk_i2c_info },
+	{ PCI_VDEVICE(INTEL, 0x31b4), (kernel_ulong_t)&glk_i2c_info },
+	{ PCI_VDEVICE(INTEL, 0x31b6), (kernel_ulong_t)&glk_i2c_info },
+	{ PCI_VDEVICE(INTEL, 0x31b8), (kernel_ulong_t)&glk_i2c_info },
+	{ PCI_VDEVICE(INTEL, 0x31ba), (kernel_ulong_t)&glk_i2c_info },
 	{ PCI_VDEVICE(INTEL, 0x31bc), (kernel_ulong_t)&bxt_uart_info },
 	{ PCI_VDEVICE(INTEL, 0x31be), (kernel_ulong_t)&bxt_uart_info },
 	{ PCI_VDEVICE(INTEL, 0x31c0), (kernel_ulong_t)&bxt_uart_info },
@@ -202,6 +228,22 @@
 	{ PCI_VDEVICE(INTEL, 0x34ea), (kernel_ulong_t)&bxt_i2c_info },
 	{ PCI_VDEVICE(INTEL, 0x34eb), (kernel_ulong_t)&bxt_i2c_info },
 	{ PCI_VDEVICE(INTEL, 0x34fb), (kernel_ulong_t)&spt_info },
+	/* TGL-H */
+	{ PCI_VDEVICE(INTEL, 0x43a7), (kernel_ulong_t)&bxt_uart_info },
+	{ PCI_VDEVICE(INTEL, 0x43a8), (kernel_ulong_t)&bxt_uart_info },
+	{ PCI_VDEVICE(INTEL, 0x43a9), (kernel_ulong_t)&bxt_uart_info },
+	{ PCI_VDEVICE(INTEL, 0x43aa), (kernel_ulong_t)&bxt_info },
+	{ PCI_VDEVICE(INTEL, 0x43ab), (kernel_ulong_t)&bxt_info },
+	{ PCI_VDEVICE(INTEL, 0x43ad), (kernel_ulong_t)&bxt_i2c_info },
+	{ PCI_VDEVICE(INTEL, 0x43ae), (kernel_ulong_t)&bxt_i2c_info },
+	{ PCI_VDEVICE(INTEL, 0x43d8), (kernel_ulong_t)&bxt_i2c_info },
+	{ PCI_VDEVICE(INTEL, 0x43da), (kernel_ulong_t)&bxt_uart_info },
+	{ PCI_VDEVICE(INTEL, 0x43e8), (kernel_ulong_t)&bxt_i2c_info },
+	{ PCI_VDEVICE(INTEL, 0x43e9), (kernel_ulong_t)&bxt_i2c_info },
+	{ PCI_VDEVICE(INTEL, 0x43ea), (kernel_ulong_t)&bxt_i2c_info },
+	{ PCI_VDEVICE(INTEL, 0x43eb), (kernel_ulong_t)&bxt_i2c_info },
+	{ PCI_VDEVICE(INTEL, 0x43fb), (kernel_ulong_t)&bxt_info },
+	{ PCI_VDEVICE(INTEL, 0x43fd), (kernel_ulong_t)&bxt_info },
 	/* EHL */
 	{ PCI_VDEVICE(INTEL, 0x4b28), (kernel_ulong_t)&bxt_uart_info },
 	{ PCI_VDEVICE(INTEL, 0x4b29), (kernel_ulong_t)&bxt_uart_info },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/intel-lpss.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/intel-lpss.c
@@ -384,7 +384,7 @@
 	if (!lpss)
 		return -ENOMEM;
 
-	lpss->priv = devm_ioremap(dev, info->mem->start + LPSS_PRIV_OFFSET,
+	lpss->priv = devm_ioremap_uc(dev, info->mem->start + LPSS_PRIV_OFFSET,
 				  LPSS_PRIV_SIZE);
 	if (!lpss->priv)
 		return -ENOMEM;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/intel_soc_pmic_bxtwc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/intel_soc_pmic_bxtwc.c
@@ -227,43 +227,54 @@
 
 static struct mfd_cell bxt_wc_dev[] = {
 	{
-		.name = "bxt_wcove_gpadc",
-		.num_resources = ARRAY_SIZE(adc_resources),
-		.resources = adc_resources,
-	},
-	{
 		.name = "bxt_wcove_thermal",
 		.num_resources = ARRAY_SIZE(thermal_resources),
 		.resources = thermal_resources,
 	},
 	{
-		.name = "bxt_wcove_usbc",
-		.num_resources = ARRAY_SIZE(usbc_resources),
-		.resources = usbc_resources,
+		.name = "bxt_wcove_gpio",
+		.num_resources = ARRAY_SIZE(gpio_resources),
+		.resources = gpio_resources,
 	},
 	{
-		.name = "bxt_wcove_ext_charger",
-		.num_resources = ARRAY_SIZE(charger_resources),
-		.resources = charger_resources,
+		.name = "bxt_wcove_region",
 	},
+};
+
+static const struct mfd_cell bxt_wc_tmu_dev[] = {
+	{
+		.name = "bxt_wcove_tmu",
+		.num_resources = ARRAY_SIZE(tmu_resources),
+		.resources = tmu_resources,
+	},
+};
+
+static const struct mfd_cell bxt_wc_bcu_dev[] = {
 	{
 		.name = "bxt_wcove_bcu",
 		.num_resources = ARRAY_SIZE(bcu_resources),
 		.resources = bcu_resources,
 	},
+};
+
+static const struct mfd_cell bxt_wc_adc_dev[] = {
 	{
-		.name = "bxt_wcove_tmu",
-		.num_resources = ARRAY_SIZE(tmu_resources),
-		.resources = tmu_resources,
+		.name = "bxt_wcove_gpadc",
+		.num_resources = ARRAY_SIZE(adc_resources),
+		.resources = adc_resources,
 	},
+};
 
+static struct mfd_cell bxt_wc_chgr_dev[] = {
 	{
-		.name = "bxt_wcove_gpio",
-		.num_resources = ARRAY_SIZE(gpio_resources),
-		.resources = gpio_resources,
+		.name = "bxt_wcove_usbc",
+		.num_resources = ARRAY_SIZE(usbc_resources),
+		.resources = usbc_resources,
 	},
 	{
-		.name = "bxt_wcove_region",
+		.name = "bxt_wcove_ext_charger",
+		.num_resources = ARRAY_SIZE(charger_resources),
+		.resources = charger_resources,
 	},
 };
 
@@ -414,19 +425,37 @@
 	int irq;
 
 	irq = regmap_irq_get_virq(pdata, pirq);
-	if (irq < 0) {
-		dev_err(pmic->dev,
-			"Failed to get parent vIRQ(%d) for chip %s, ret:%d\n",
-			pirq, chip->name, irq);
-		return irq;
-	}
+	if (irq < 0)
+		return dev_err_probe(pmic->dev, irq, "Failed to get parent vIRQ(%d) for chip %s\n",
+				     pirq, chip->name);
 
 	return devm_regmap_add_irq_chip(pmic->dev, pmic->regmap, irq, irq_flags,
 					0, chip, data);
 }
 
+static int bxtwc_add_chained_devices(struct intel_soc_pmic *pmic,
+				     const struct mfd_cell *cells, int n_devs,
+				     struct regmap_irq_chip_data *pdata,
+				     int pirq, int irq_flags,
+				     const struct regmap_irq_chip *chip,
+				     struct regmap_irq_chip_data **data)
+{
+	struct device *dev = pmic->dev;
+	struct irq_domain *domain;
+	int ret;
+
+	ret = bxtwc_add_chained_irq_chip(pmic, pdata, pirq, irq_flags, chip, data);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to add %s IRQ chip\n", chip->name);
+
+	domain = regmap_irq_get_domain(*data);
+
+	return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, cells, n_devs, NULL, 0, domain);
+}
+
 static int bxtwc_probe(struct platform_device *pdev)
 {
+	struct device *dev = &pdev->dev;
 	int ret;
 	acpi_handle handle;
 	acpi_status status;
@@ -435,15 +464,10 @@
 
 	handle = ACPI_HANDLE(&pdev->dev);
 	status = acpi_evaluate_integer(handle, "_HRV", NULL, &hrv);
-	if (ACPI_FAILURE(status)) {
-		dev_err(&pdev->dev, "Failed to get PMIC hardware revision\n");
-		return -ENODEV;
-	}
-	if (hrv != BROXTON_PMIC_WC_HRV) {
-		dev_err(&pdev->dev, "Invalid PMIC hardware revision: %llu\n",
-			hrv);
-		return -ENODEV;
-	}
+	if (ACPI_FAILURE(status))
+		return dev_err_probe(dev, -ENODEV, "Failed to get PMIC hardware revision\n");
+	if (hrv != BROXTON_PMIC_WC_HRV)
+		return dev_err_probe(dev, -ENODEV, "Invalid PMIC hardware revision: %llu\n", hrv);
 
 	pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
 	if (!pmic)
@@ -459,79 +483,59 @@
 
 	pmic->regmap = devm_regmap_init(&pdev->dev, NULL, pmic,
 					&bxtwc_regmap_config);
-	if (IS_ERR(pmic->regmap)) {
-		ret = PTR_ERR(pmic->regmap);
-		dev_err(&pdev->dev, "Failed to initialise regmap: %d\n", ret);
-		return ret;
-	}
+	if (IS_ERR(pmic->regmap))
+		return dev_err_probe(dev, PTR_ERR(pmic->regmap), "Failed to initialise regmap\n");
 
 	ret = devm_regmap_add_irq_chip(&pdev->dev, pmic->regmap, pmic->irq,
 				       IRQF_ONESHOT | IRQF_SHARED,
 				       0, &bxtwc_regmap_irq_chip,
 				       &pmic->irq_chip_data);
-	if (ret) {
-		dev_err(&pdev->dev, "Failed to add IRQ chip\n");
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to add IRQ chip\n");
+
+	ret = bxtwc_add_chained_devices(pmic, bxt_wc_tmu_dev, ARRAY_SIZE(bxt_wc_tmu_dev),
+					pmic->irq_chip_data,
+					BXTWC_TMU_LVL1_IRQ,
+					IRQF_ONESHOT,
+					&bxtwc_regmap_irq_chip_tmu,
+					&pmic->irq_chip_data_tmu);
+	if (ret)
 		return ret;
-	}
 
 	ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data,
 					 BXTWC_PWRBTN_LVL1_IRQ,
 					 IRQF_ONESHOT,
 					 &bxtwc_regmap_irq_chip_pwrbtn,
 					 &pmic->irq_chip_data_pwrbtn);
-	if (ret) {
-		dev_err(&pdev->dev, "Failed to add PWRBTN IRQ chip\n");
-		return ret;
-	}
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to add PWRBTN IRQ chip\n");
 
-	ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data,
-					 BXTWC_TMU_LVL1_IRQ,
-					 IRQF_ONESHOT,
-					 &bxtwc_regmap_irq_chip_tmu,
-					 &pmic->irq_chip_data_tmu);
-	if (ret) {
-		dev_err(&pdev->dev, "Failed to add TMU IRQ chip\n");
+	ret = bxtwc_add_chained_devices(pmic, bxt_wc_bcu_dev, ARRAY_SIZE(bxt_wc_bcu_dev),
+					pmic->irq_chip_data,
+					BXTWC_BCU_LVL1_IRQ,
+					IRQF_ONESHOT,
+					&bxtwc_regmap_irq_chip_bcu,
+					&pmic->irq_chip_data_bcu);
+	if (ret)
 		return ret;
-	}
 
-	/* Add chained IRQ handler for BCU IRQs */
-	ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data,
-					 BXTWC_BCU_LVL1_IRQ,
-					 IRQF_ONESHOT,
-					 &bxtwc_regmap_irq_chip_bcu,
-					 &pmic->irq_chip_data_bcu);
-
-
-	if (ret) {
-		dev_err(&pdev->dev, "Failed to add BUC IRQ chip\n");
-		return ret;
-	}
-
-	/* Add chained IRQ handler for ADC IRQs */
-	ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data,
-					 BXTWC_ADC_LVL1_IRQ,
-					 IRQF_ONESHOT,
-					 &bxtwc_regmap_irq_chip_adc,
-					 &pmic->irq_chip_data_adc);
-
-
-	if (ret) {
-		dev_err(&pdev->dev, "Failed to add ADC IRQ chip\n");
+	ret = bxtwc_add_chained_devices(pmic, bxt_wc_adc_dev, ARRAY_SIZE(bxt_wc_adc_dev),
+					pmic->irq_chip_data,
+					BXTWC_ADC_LVL1_IRQ,
+					IRQF_ONESHOT,
+					&bxtwc_regmap_irq_chip_adc,
+					&pmic->irq_chip_data_adc);
+	if (ret)
 		return ret;
-	}
-
-	/* Add chained IRQ handler for CHGR IRQs */
-	ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data,
-					 BXTWC_CHGR_LVL1_IRQ,
-					 IRQF_ONESHOT,
-					 &bxtwc_regmap_irq_chip_chgr,
-					 &pmic->irq_chip_data_chgr);
-
 
-	if (ret) {
-		dev_err(&pdev->dev, "Failed to add CHGR IRQ chip\n");
+	ret = bxtwc_add_chained_devices(pmic, bxt_wc_chgr_dev, ARRAY_SIZE(bxt_wc_chgr_dev),
+					pmic->irq_chip_data,
+					BXTWC_CHGR_LVL1_IRQ,
+					IRQF_ONESHOT,
+					&bxtwc_regmap_irq_chip_chgr,
+					&pmic->irq_chip_data_chgr);
+	if (ret)
 		return ret;
-	}
 
 	/* Add chained IRQ handler for CRIT IRQs */
 	ret = bxtwc_add_chained_irq_chip(pmic, pmic->irq_chip_data,
@@ -539,19 +543,13 @@
 					 IRQF_ONESHOT,
 					 &bxtwc_regmap_irq_chip_crit,
 					 &pmic->irq_chip_data_crit);
-
-
-	if (ret) {
-		dev_err(&pdev->dev, "Failed to add CRIT IRQ chip\n");
-		return ret;
-	}
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to add CRIT IRQ chip\n");
 
 	ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, bxt_wc_dev,
 				   ARRAY_SIZE(bxt_wc_dev), NULL, 0, NULL);
-	if (ret) {
-		dev_err(&pdev->dev, "Failed to add devices\n");
-		return ret;
-	}
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to add devices\n");
 
 	ret = sysfs_create_group(&pdev->dev.kobj, &bxtwc_group);
 	if (ret) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/intel_soc_pmic_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/intel_soc_pmic_core.c
@@ -111,6 +111,7 @@
 	return 0;
 
 err_del_irq_chip:
+	pwm_remove_table(crc_pwm_lookup, ARRAY_SIZE(crc_pwm_lookup));
 	regmap_del_irq_chip(pmic->irq, pmic->irq_chip_data);
 	return ret;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/ipaq-micro.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/ipaq-micro.c
@@ -407,7 +407,7 @@
 	micro_reset_comm(micro);
 
 	irq = platform_get_irq(pdev, 0);
-	if (!irq)
+	if (irq < 0)
 		return -EINVAL;
 	ret = devm_request_irq(&pdev->dev, irq, micro_serial_isr,
 			       IRQF_SHARED, "ipaq-micro",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/lp8788-irq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/lp8788-irq.c
@@ -175,6 +175,7 @@
 				IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
 				"lp8788-irq", irqd);
 	if (ret) {
+		irq_domain_remove(lp->irqdm);
 		dev_err(lp->dev, "failed to create a thread for IRQ_N\n");
 		return ret;
 	}
@@ -188,4 +189,6 @@
 {
 	if (lp->irq)
 		free_irq(lp->irq, lp->irqdm);
+	if (lp->irqdm)
+		irq_domain_remove(lp->irqdm);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/lp8788.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/lp8788.c
@@ -195,8 +195,16 @@
 	if (ret)
 		return ret;
 
-	return mfd_add_devices(lp->dev, -1, lp8788_devs,
-			       ARRAY_SIZE(lp8788_devs), NULL, 0, NULL);
+	ret = mfd_add_devices(lp->dev, -1, lp8788_devs,
+			      ARRAY_SIZE(lp8788_devs), NULL, 0, NULL);
+	if (ret)
+		goto err_exit_irq;
+
+	return 0;
+
+err_exit_irq:
+	lp8788_irq_exit(lp);
+	return ret;
 }
 
 static int lp8788_remove(struct i2c_client *cl)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/lpc_ich.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/lpc_ich.c
@@ -685,8 +685,9 @@
 	{ PCI_VDEVICE(INTEL, 0x2917), LPC_ICH9ME},
 	{ PCI_VDEVICE(INTEL, 0x2918), LPC_ICH9},
 	{ PCI_VDEVICE(INTEL, 0x2919), LPC_ICH9M},
-	{ PCI_VDEVICE(INTEL, 0x3197), LPC_GLK},
 	{ PCI_VDEVICE(INTEL, 0x2b9c), LPC_COUGARMOUNTAIN},
+	{ PCI_VDEVICE(INTEL, 0x3197), LPC_GLK},
+	{ PCI_VDEVICE(INTEL, 0x31e8), LPC_GLK},
 	{ PCI_VDEVICE(INTEL, 0x3a14), LPC_ICH10DO},
 	{ PCI_VDEVICE(INTEL, 0x3a16), LPC_ICH10R},
 	{ PCI_VDEVICE(INTEL, 0x3a18), LPC_ICH10},
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/max77620.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/max77620.c
@@ -418,9 +418,11 @@
 		ret = max77620_config_fps(chip, fps_child);
 		if (ret < 0) {
 			of_node_put(fps_child);
+			of_node_put(fps_np);
 			return ret;
 		}
 	}
+	of_node_put(fps_np);
 
 	config = chip->enable_global_lpm ? MAX77620_ONOFFCNFG2_SLP_LPM_MSK : 0;
 	ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG2,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/mc13xxx-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/mc13xxx-core.c
@@ -323,8 +323,10 @@
 		adc1 |= MC13783_ADC1_ATOX;
 
 	dev_dbg(mc13xxx->dev, "%s: request irq\n", __func__);
-	mc13xxx_irq_request(mc13xxx, MC13XXX_IRQ_ADCDONE,
+	ret = mc13xxx_irq_request(mc13xxx, MC13XXX_IRQ_ADCDONE,
 			mc13xxx_handler_adcdone, __func__, &adcdone_data);
+	if (ret)
+		goto out;
 
 	mc13xxx_reg_write(mc13xxx, MC13XXX_ADC0, adc0);
 	mc13xxx_reg_write(mc13xxx, MC13XXX_ADC1, adc1);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/mfd-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/mfd-core.c
@@ -28,6 +28,11 @@
 	const struct mfd_cell *cell = mfd_get_cell(pdev);
 	int err = 0;
 
+	if (!cell->enable) {
+		dev_dbg(&pdev->dev, "No .enable() call-back registered\n");
+		return 0;
+	}
+
 	/* only call enable hook if the cell wasn't previously enabled */
 	if (atomic_inc_return(cell->usage_count) == 1)
 		err = cell->enable(pdev);
@@ -45,6 +50,11 @@
 	const struct mfd_cell *cell = mfd_get_cell(pdev);
 	int err = 0;
 
+	if (!cell->disable) {
+		dev_dbg(&pdev->dev, "No .disable() call-back registered\n");
+		return 0;
+	}
+
 	/* only disable if no other clients are using it */
 	if (atomic_dec_return(cell->usage_count) == 0)
 		err = cell->disable(pdev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/motorola-cpcap.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/motorola-cpcap.c
@@ -305,6 +305,10 @@
 	if (ret)
 		return ret;
 
+	/* Parent SPI controller uses DMA, CPCAP and child devices do not */
+	spi->dev.coherent_dma_mask = 0;
+	spi->dev.dma_mask = &spi->dev.coherent_dma_mask;
+
 	return devm_mfd_add_devices(&spi->dev, 0, cpcap_mfd_devices,
 				    ARRAY_SIZE(cpcap_mfd_devices), NULL, 0, NULL);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/omap-usb-tll.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/omap-usb-tll.c
@@ -235,8 +235,7 @@
 		break;
 	}
 
-	tll = devm_kzalloc(dev, sizeof(*tll) + sizeof(tll->ch_clk[nch]),
-			   GFP_KERNEL);
+	tll = devm_kzalloc(dev, struct_size(tll, ch_clk, nch), GFP_KERNEL);
 	if (!tll) {
 		pm_runtime_put_sync(dev);
 		pm_runtime_disable(dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/pcf50633-adc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/pcf50633-adc.c
@@ -136,6 +136,7 @@
 			     void *callback_param)
 {
 	struct pcf50633_adc_request *req;
+	int ret;
 
 	/* req is freed when the result is ready, in interrupt handler */
 	req = kmalloc(sizeof(*req), GFP_KERNEL);
@@ -147,7 +148,11 @@
 	req->callback = callback;
 	req->callback_param = callback_param;
 
-	return adc_enqueue_request(pcf, req);
+	ret = adc_enqueue_request(pcf, req);
+	if (ret)
+		kfree(req);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(pcf50633_adc_async_read);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/rn5t618.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/rn5t618.c
@@ -26,6 +26,7 @@
 	case RN5T618_WATCHDOGCNT:
 	case RN5T618_DCIRQ:
 	case RN5T618_ILIMDATAH ... RN5T618_AIN0DATAL:
+	case RN5T618_ADCCNT3:
 	case RN5T618_IR_ADC1 ... RN5T618_IR_ADC3:
 	case RN5T618_IR_GPR:
 	case RN5T618_IR_GPF:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/rt5033.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/rt5033.c
@@ -42,9 +42,6 @@
 		.name = "rt5033-charger",
 		.of_compatible = "richtek,rt5033-charger",
 	}, {
-		.name = "rt5033-battery",
-		.of_compatible = "richtek,rt5033-battery",
-	}, {
 		.name = "rt5033-led",
 		.of_compatible = "richtek,rt5033-led",
 	},
@@ -85,8 +82,8 @@
 	}
 	dev_info(&i2c->dev, "Device found Device ID: %04x\n", dev_id);
 
-	ret = regmap_add_irq_chip(rt5033->regmap, rt5033->irq,
-			IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+	ret = devm_regmap_add_irq_chip(rt5033->dev, rt5033->regmap,
+			rt5033->irq, IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
 			0, &rt5033_irq_chip, &rt5033->irq_data);
 	if (ret) {
 		dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/sm501.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/sm501.c
@@ -920,7 +920,7 @@
 {
 	struct sm501_gpio_chip *smchip = gpiochip_get_data(chip);
 	struct sm501_gpio *smgpio = smchip->ourgpio;
-	unsigned long bit = 1 << offset;
+	unsigned long bit = BIT(offset);
 	void __iomem *regs = smchip->regbase;
 	unsigned long save;
 	unsigned long val;
@@ -946,7 +946,7 @@
 	struct sm501_gpio_chip *smchip = gpiochip_get_data(chip);
 	struct sm501_gpio *smgpio = smchip->ourgpio;
 	void __iomem *regs = smchip->regbase;
-	unsigned long bit = 1 << offset;
+	unsigned long bit = BIT(offset);
 	unsigned long save;
 	unsigned long ddr;
 
@@ -971,7 +971,7 @@
 {
 	struct sm501_gpio_chip *smchip = gpiochip_get_data(chip);
 	struct sm501_gpio *smgpio = smchip->ourgpio;
-	unsigned long bit = 1 << offset;
+	unsigned long bit = BIT(offset);
 	void __iomem *regs = smchip->regbase;
 	unsigned long save;
 	unsigned long val;
@@ -1424,8 +1424,14 @@
 		goto err_claim;
 	}
 
-	return sm501_init_dev(sm);
+	ret = sm501_init_dev(sm);
+	if (ret)
+		goto err_unmap;
+
+	return 0;
 
+ err_unmap:
+	iounmap(sm->regs);
  err_claim:
 	release_resource(sm->regs_claim);
 	kfree(sm->regs_claim);
@@ -1727,7 +1733,12 @@
 
 static int __init sm501_base_init(void)
 {
-	platform_driver_register(&sm501_plat_driver);
+	int ret;
+
+	ret = platform_driver_register(&sm501_plat_driver);
+	if (ret < 0)
+		return ret;
+
 	return pci_register_driver(&sm501_pci_driver);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/sprd-sc27xx-spi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/sprd-sc27xx-spi.c
@@ -204,7 +204,7 @@
 	}
 
 	ret = devm_regmap_add_irq_chip(&spi->dev, ddata->regmap, ddata->irq,
-				       IRQF_ONESHOT | IRQF_NO_SUSPEND, 0,
+				       IRQF_ONESHOT, 0,
 				       &ddata->irq_chip, &ddata->irq_data);
 	if (ret) {
 		dev_err(&spi->dev, "Failed to add PMIC irq chip %d\n", ret);
@@ -220,9 +220,34 @@
 		return ret;
 	}
 
+	device_init_wakeup(&spi->dev, true);
 	return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int sprd_pmic_suspend(struct device *dev)
+{
+	struct sprd_pmic *ddata = dev_get_drvdata(dev);
+
+	if (device_may_wakeup(dev))
+		enable_irq_wake(ddata->irq);
+
+	return 0;
+}
+
+static int sprd_pmic_resume(struct device *dev)
+{
+	struct sprd_pmic *ddata = dev_get_drvdata(dev);
+
+	if (device_may_wakeup(dev))
+		disable_irq_wake(ddata->irq);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(sprd_pmic_pm_ops, sprd_pmic_suspend, sprd_pmic_resume);
+
 static const struct of_device_id sprd_pmic_match[] = {
 	{ .compatible = "sprd,sc2731", .data = &sc2731_data },
 	{},
@@ -234,6 +259,7 @@
 		.name = "sc27xx-pmic",
 		.bus = &spi_bus_type,
 		.of_match_table = sprd_pmic_match,
+		.pm = &sprd_pmic_pm_ops,
 	},
 	.probe = sprd_pmic_probe,
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/stm32-timers.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/stm32-timers.c
@@ -158,13 +158,18 @@
 
 static void stm32_timers_get_arr_size(struct stm32_timers *ddata)
 {
+	u32 arr;
+
+	/* Backup ARR to restore it after getting the maximum value */
+	regmap_read(ddata->regmap, TIM_ARR, &arr);
+
 	/*
 	 * Only the available bits will be written so when readback
 	 * we get the maximum value of auto reload register
 	 */
 	regmap_write(ddata->regmap, TIM_ARR, ~0L);
 	regmap_read(ddata->regmap, TIM_ARR, &ddata->max_arr);
-	regmap_write(ddata->regmap, TIM_ARR, 0x0);
+	regmap_write(ddata->regmap, TIM_ARR, arr);
 }
 
 static void stm32_timers_dma_probe(struct device *dev,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/stmfx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/stmfx.c
@@ -287,14 +287,21 @@
 
 	ret = regmap_write(stmfx->map, STMFX_REG_IRQ_OUT_PIN, irqoutpin);
 	if (ret)
-		return ret;
+		goto irq_exit;
 
 	ret = devm_request_threaded_irq(stmfx->dev, client->irq,
 					NULL, stmfx_irq_handler,
 					irqtrigger | IRQF_ONESHOT,
 					"stmfx", stmfx);
 	if (ret)
-		stmfx_irq_exit(client);
+		goto irq_exit;
+
+	stmfx->irq = client->irq;
+
+	return 0;
+
+irq_exit:
+	stmfx_irq_exit(client);
 
 	return ret;
 }
@@ -382,7 +389,7 @@
 
 err:
 	if (stmfx->vdd)
-		return regulator_disable(stmfx->vdd);
+		regulator_disable(stmfx->vdd);
 
 	return ret;
 }
@@ -481,6 +488,8 @@
 	if (ret)
 		return ret;
 
+	disable_irq(stmfx->irq);
+
 	if (stmfx->vdd)
 		return regulator_disable(stmfx->vdd);
 
@@ -501,6 +510,13 @@
 		}
 	}
 
+	/* Reset STMFX - supply has been stopped during suspend */
+	ret = stmfx_chip_reset(stmfx);
+	if (ret) {
+		dev_err(stmfx->dev, "Failed to reset chip: %d\n", ret);
+		return ret;
+	}
+
 	ret = regmap_raw_write(stmfx->map, STMFX_REG_SYS_CTRL,
 			       &stmfx->bkp_sysctrl, sizeof(stmfx->bkp_sysctrl));
 	if (ret)
@@ -517,6 +533,8 @@
 	if (ret)
 		return ret;
 
+	enable_irq(stmfx->irq);
+
 	return 0;
 }
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/stmpe-i2c.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/stmpe-i2c.c
@@ -109,7 +109,7 @@
 	{ "stmpe2403", STMPE2403 },
 	{ }
 };
-MODULE_DEVICE_TABLE(i2c, stmpe_id);
+MODULE_DEVICE_TABLE(i2c, stmpe_i2c_id);
 
 static struct i2c_driver stmpe_i2c_driver = {
 	.driver = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/stmpe.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/stmpe.c
@@ -1091,7 +1091,7 @@
 
 	if (variant->id_val == STMPE801_ID ||
 	    variant->id_val == STMPE1600_ID) {
-		int base = irq_create_mapping(stmpe->domain, 0);
+		int base = irq_find_mapping(stmpe->domain, 0);
 
 		handle_nested_irq(base);
 		return IRQ_HANDLED;
@@ -1119,7 +1119,7 @@
 		while (status) {
 			int bit = __ffs(status);
 			int line = bank * 8 + bit;
-			int nestedirq = irq_create_mapping(stmpe->domain, line);
+			int nestedirq = irq_find_mapping(stmpe->domain, line);
 
 			handle_nested_irq(nestedirq);
 			status &= ~(1 << bit);
@@ -1494,9 +1494,9 @@
 
 int stmpe_remove(struct stmpe *stmpe)
 {
-	if (!IS_ERR(stmpe->vio))
+	if (!IS_ERR(stmpe->vio) && regulator_is_enabled(stmpe->vio))
 		regulator_disable(stmpe->vio);
-	if (!IS_ERR(stmpe->vcc))
+	if (!IS_ERR(stmpe->vcc) && regulator_is_enabled(stmpe->vcc))
 		regulator_disable(stmpe->vcc);
 
 	__stmpe_disable(stmpe, STMPE_BLOCK_ADC);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/syscon.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/syscon.c
@@ -219,7 +219,9 @@
 		return ERR_PTR(-ENODEV);
 
 	regmap = syscon_node_to_regmap(syscon_np);
-	of_node_put(syscon_np);
+
+	if (property)
+		of_node_put(syscon_np);
 
 	return regmap;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/t7l66xb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/t7l66xb.c
@@ -405,11 +405,8 @@
 
 static int t7l66xb_remove(struct platform_device *dev)
 {
-	struct t7l66xb_platform_data *pdata = dev_get_platdata(&dev->dev);
 	struct t7l66xb *t7l66xb = platform_get_drvdata(dev);
-	int ret;
 
-	ret = pdata->disable(dev);
 	clk_disable_unprepare(t7l66xb->clk48m);
 	clk_put(t7l66xb->clk48m);
 	clk_disable_unprepare(t7l66xb->clk32k);
@@ -420,8 +417,7 @@
 	mfd_remove_devices(&dev->dev);
 	kfree(t7l66xb);
 
-	return ret;
-
+	return 0;
 }
 
 static struct platform_driver t7l66xb_platform_driver = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/tc3589x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/tc3589x.c
@@ -187,7 +187,7 @@
 
 	while (status) {
 		int bit = __ffs(status);
-		int virq = irq_create_mapping(tc3589x->domain, bit);
+		int virq = irq_find_mapping(tc3589x->domain, bit);
 
 		handle_nested_irq(virq);
 		status &= ~(1 << bit);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/tps65010.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/tps65010.c
@@ -550,17 +550,13 @@
 	 */
 	if (client->irq > 0) {
 		status = request_irq(client->irq, tps65010_irq,
-				     IRQF_TRIGGER_FALLING, DRIVER_NAME, tps);
+				     IRQF_TRIGGER_FALLING | IRQF_NO_AUTOEN,
+				     DRIVER_NAME, tps);
 		if (status < 0) {
 			dev_dbg(&client->dev, "can't get IRQ %d, err %d\n",
 					client->irq, status);
 			return status;
 		}
-		/* annoying race here, ideally we'd have an option
-		 * to claim the irq now and enable it later.
-		 * FIXME genirq IRQF_NOAUTOEN now solves that ...
-		 */
-		disable_irq(client->irq);
 		set_bit(FLAG_IRQ_ENABLE, &tps->flags);
 	} else
 		dev_warn(&client->dev, "IRQ not configured!\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/tqmx86.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/tqmx86.c
@@ -210,6 +210,8 @@
 
 		/* Assumes the IRQ resource is first. */
 		tqmx_gpio_resources[0].start = gpio_irq;
+	} else {
+		tqmx_gpio_resources[0].flags = 0;
 	}
 
 	ocores_platfom_data.clock_khz = tqmx86_board_id_to_clk_rate(board_id);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/wm831x-auxadc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/wm831x-auxadc.c
@@ -93,11 +93,10 @@
 	wait_for_completion_timeout(&req->done, msecs_to_jiffies(500));
 
 	mutex_lock(&wm831x->auxadc_lock);
-
-	list_del(&req->list);
 	ret = req->val;
 
 out:
+	list_del(&req->list);
 	mutex_unlock(&wm831x->auxadc_lock);
 
 	kfree(req);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/wm8994-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/wm8994-core.c
@@ -690,3 +690,4 @@
 MODULE_DESCRIPTION("Core support for the WM8994 audio CODEC");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_SOFTDEP("pre: wm8994_regulator");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mfd/wm8994-irq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mfd/wm8994-irq.c
@@ -154,7 +154,7 @@
 	struct wm8994 *wm8994 = data;
 
 	while (gpio_get_value_cansleep(wm8994->pdata.irq_gpio))
-		handle_nested_irq(irq_create_mapping(wm8994->edge_irq, 0));
+		handle_nested_irq(irq_find_mapping(wm8994->edge_irq, 0));
 
 	return IRQ_HANDLED;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/Kconfig
@@ -454,6 +454,40 @@
 
 	  If unsure, say N.
 
+config XILINX_FLEX_PM
+	tristate "Xilinx Flexnoc Performance Monitor"
+	help
+	  This option enables support for the Xilinx Flex Noc Performance Monitor driver.
+	  It monitors the read and write transactions. It has counters for the LPD and
+	  FPD domains.
+
+	  If unsure, say N
+
+config XILINX_TRAFGEN
+	tristate "Xilinx Traffic Generator"
+	help
+	  This option enables support for the Xilinx Traffic Generator driver.
+	  It is designed to generate AXI4 traffic which can be used to stress
+	  different modules/interconnect connected in the system. Different
+	  configurable options which are provided through sysfs entries allow
+	  allow the user to generate a wide variety of traffic based on their
+	  their requirements.
+
+	  If unsure, say N
+
+config XILINX_AIE
+	tristate "Xilinx AI engine"
+	depends on ARM64 || COMPILE_TEST
+	select FPGA_BRIDGE
+	help
+	  This option enables support for the Xilinx AI engine driver.
+	  One Xilinx AI engine device can have multiple partitions (groups of
+	  AI engine tiles). Xilinx AI engine device driver instance manages
+	  AI engine partitions. User application access its partitions through
+	  AI engine partition instance file operations.
+
+	  If unsure, say N
+
 config MISC_RTSX
 	tristate
 	default MISC_RTSX_PCI || MISC_RTSX_USB
@@ -466,6 +500,7 @@
 	  a paravirtualized device provided by QEMU; it lets a virtual machine
 	  (guest) communicate panic events to the host.
 
+source "drivers/misc/jesd204b/Kconfig"
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/Makefile
@@ -57,3 +57,7 @@
 obj-$(CONFIG_PVPANIC)   	+= pvpanic.o
 obj-$(CONFIG_HABANA_AI)		+= habanalabs/
 obj-$(CONFIG_XILINX_SDFEC)	+= xilinx_sdfec.o
+obj-$(CONFIG_XILINX_FLEX_PM)	+= xilinx_flex_pm.o
+obj-$(CONFIG_XILINX_TRAFGEN)	+= xilinx_trafgen.o
+obj-$(CONFIG_XILINX_JESD204B)	+= jesd204b/
+obj-$(CONFIG_XILINX_AIE)	+= xilinx-ai-engine/
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/altera-stapl/altera.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/altera-stapl/altera.c
@@ -2112,8 +2112,8 @@
 	return status;
 }
 
-static int altera_get_note(u8 *p, s32 program_size,
-			s32 *offset, char *key, char *value, int length)
+static int altera_get_note(u8 *p, s32 program_size, s32 *offset,
+			   char *key, char *value, int keylen, int vallen)
 /*
  * Gets key and value of NOTE fields in the JBC file.
  * Can be called in two modes:  if offset pointer is NULL,
@@ -2170,7 +2170,7 @@
 						&p[note_table + (8 * i) + 4])];
 
 				if (value != NULL)
-					strlcpy(value, value_ptr, length);
+					strlcpy(value, value_ptr, vallen);
 
 			}
 		}
@@ -2189,13 +2189,13 @@
 				strlcpy(key, &p[note_strings +
 						get_unaligned_be32(
 						&p[note_table + (8 * i)])],
-					length);
+					keylen);
 
 			if (value != NULL)
 				strlcpy(value, &p[note_strings +
 						get_unaligned_be32(
 						&p[note_table + (8 * i) + 4])],
-					length);
+					vallen);
 
 			*offset = i + 1;
 		}
@@ -2449,7 +2449,7 @@
 			__func__, (format_version == 2) ? "Jam STAPL" :
 						"pre-standardized Jam 1.1");
 		while (altera_get_note((u8 *)fw->data, fw->size,
-					&offset, key, value, 256) == 0)
+					&offset, key, value, 32, 256) == 0)
 			printk(KERN_INFO "%s: NOTE \"%s\" = \"%s\"\n",
 					__func__, key, value);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/apds990x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/apds990x.c
@@ -1148,7 +1148,7 @@
 		err = chip->pdata->setup_resources();
 		if (err) {
 			err = -EINVAL;
-			goto fail3;
+			goto fail4;
 		}
 	}
 
@@ -1156,7 +1156,7 @@
 				apds990x_attribute_group);
 	if (err < 0) {
 		dev_err(&chip->client->dev, "Sysfs registration failed\n");
-		goto fail4;
+		goto fail5;
 	}
 
 	err = request_threaded_irq(client->irq, NULL,
@@ -1167,15 +1167,17 @@
 	if (err) {
 		dev_err(&client->dev, "could not get IRQ %d\n",
 			client->irq);
-		goto fail5;
+		goto fail6;
 	}
 	return err;
-fail5:
+fail6:
 	sysfs_remove_group(&chip->client->dev.kobj,
 			&apds990x_attribute_group[0]);
-fail4:
+fail5:
 	if (chip->pdata && chip->pdata->release_resources)
 		chip->pdata->release_resources();
+fail4:
+	pm_runtime_disable(&client->dev);
 fail3:
 	regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs);
 fail2:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/atmel-ssc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/atmel-ssc.c
@@ -10,7 +10,7 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/io.h>
-#include <linux/spinlock.h>
+#include <linux/mutex.h>
 #include <linux/atmel-ssc.h>
 #include <linux/slab.h>
 #include <linux/module.h>
@@ -20,7 +20,7 @@
 #include "../../sound/soc/atmel/atmel_ssc_dai.h"
 
 /* Serialize access to ssc_list and user count */
-static DEFINE_SPINLOCK(user_lock);
+static DEFINE_MUTEX(user_lock);
 static LIST_HEAD(ssc_list);
 
 struct ssc_device *ssc_request(unsigned int ssc_num)
@@ -28,7 +28,7 @@
 	int ssc_valid = 0;
 	struct ssc_device *ssc;
 
-	spin_lock(&user_lock);
+	mutex_lock(&user_lock);
 	list_for_each_entry(ssc, &ssc_list, list) {
 		if (ssc->pdev->dev.of_node) {
 			if (of_alias_get_id(ssc->pdev->dev.of_node, "ssc")
@@ -44,18 +44,18 @@
 	}
 
 	if (!ssc_valid) {
-		spin_unlock(&user_lock);
+		mutex_unlock(&user_lock);
 		pr_err("ssc: ssc%d platform device is missing\n", ssc_num);
 		return ERR_PTR(-ENODEV);
 	}
 
 	if (ssc->user) {
-		spin_unlock(&user_lock);
+		mutex_unlock(&user_lock);
 		dev_dbg(&ssc->pdev->dev, "module busy\n");
 		return ERR_PTR(-EBUSY);
 	}
 	ssc->user++;
-	spin_unlock(&user_lock);
+	mutex_unlock(&user_lock);
 
 	clk_prepare(ssc->clk);
 
@@ -67,14 +67,14 @@
 {
 	bool disable_clk = true;
 
-	spin_lock(&user_lock);
+	mutex_lock(&user_lock);
 	if (ssc->user)
 		ssc->user--;
 	else {
 		disable_clk = false;
 		dev_dbg(&ssc->pdev->dev, "device already free\n");
 	}
-	spin_unlock(&user_lock);
+	mutex_unlock(&user_lock);
 
 	if (disable_clk)
 		clk_unprepare(ssc->clk);
@@ -232,14 +232,14 @@
 	clk_disable_unprepare(ssc->clk);
 
 	ssc->irq = platform_get_irq(pdev, 0);
-	if (!ssc->irq) {
+	if (ssc->irq < 0) {
 		dev_dbg(&pdev->dev, "could not get irq\n");
-		return -ENXIO;
+		return ssc->irq;
 	}
 
-	spin_lock(&user_lock);
+	mutex_lock(&user_lock);
 	list_add_tail(&ssc->list, &ssc_list);
-	spin_unlock(&user_lock);
+	mutex_unlock(&user_lock);
 
 	platform_set_drvdata(pdev, ssc);
 
@@ -258,9 +258,9 @@
 
 	ssc_sound_dai_remove(ssc);
 
-	spin_lock(&user_lock);
+	mutex_lock(&user_lock);
 	list_del(&ssc->list);
-	spin_unlock(&user_lock);
+	mutex_unlock(&user_lock);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/cardreader/alcor_pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/cardreader/alcor_pci.c
@@ -133,7 +133,13 @@
 	u32 val32;
 
 	priv->pdev_cap_off    = alcor_pci_find_cap_offset(priv, priv->pdev);
-	priv->parent_cap_off = alcor_pci_find_cap_offset(priv,
+	/*
+	 * A device might be attached to root complex directly and
+	 * priv->parent_pdev will be NULL. In this case we don't check its
+	 * capability and disable ASPM completely.
+	 */
+	if (priv->parent_pdev)
+		priv->parent_cap_off = alcor_pci_find_cap_offset(priv,
 							 priv->parent_pdev);
 
 	if ((priv->pdev_cap_off == 0) || (priv->parent_cap_off == 0)) {
@@ -254,7 +260,7 @@
 	if (!priv)
 		return -ENOMEM;
 
-	ret = ida_simple_get(&alcor_pci_idr, 0, 0, GFP_KERNEL);
+	ret = ida_alloc(&alcor_pci_idr, GFP_KERNEL);
 	if (ret < 0)
 		return ret;
 	priv->id = ret;
@@ -268,7 +274,8 @@
 	ret = pci_request_regions(pdev, DRV_NAME_ALCOR_PCI);
 	if (ret) {
 		dev_err(&pdev->dev, "Cannot request region\n");
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto error_free_ida;
 	}
 
 	if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) {
@@ -312,6 +319,8 @@
 
 error_release_regions:
 	pci_release_regions(pdev);
+error_free_ida:
+	ida_free(&alcor_pci_idr, priv->id);
 	return ret;
 }
 
@@ -325,7 +334,7 @@
 
 	mfd_remove_devices(&pdev->dev);
 
-	ida_simple_remove(&alcor_pci_idr, priv->id);
+	ida_free(&alcor_pci_idr, priv->id);
 
 	pci_release_regions(pdev);
 	pci_set_drvdata(pdev, NULL);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/cardreader/rts5227.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/cardreader/rts5227.c
@@ -338,6 +338,11 @@
 {
 	rts5227_extra_init_hw(pcr);
 
+	/* Power down OCP for power consumption */
+	if (!pcr->card_exist)
+		rtsx_pci_write_register(pcr, FPDCTL, OC_POWER_DOWN,
+				OC_POWER_DOWN);
+
 	rtsx_pci_write_register(pcr, FUNC_FORCE_CTL, FUNC_FORCE_UPME_XMT_DBG,
 		FUNC_FORCE_UPME_XMT_DBG);
 	rtsx_pci_write_register(pcr, PCLK_CTL, 0x04, 0x04);
@@ -394,7 +399,8 @@
 void rts522a_init_params(struct rtsx_pcr *pcr)
 {
 	rts5227_init_params(pcr);
-
+	pcr->ops = &rts522a_pcr_ops;
+	pcr->tx_initial_phase = SET_CLOCK_PHASE(20, 20, 11);
 	pcr->reg_pm_ctrl3 = RTS522A_PM_CTRL3;
 
 	pcr->option.ocp_en = 1;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/cardreader/rts5249.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/cardreader/rts5249.c
@@ -618,6 +618,7 @@
 void rts524a_init_params(struct rtsx_pcr *pcr)
 {
 	rts5249_init_params(pcr);
+	pcr->tx_initial_phase = SET_CLOCK_PHASE(27, 29, 11);
 	pcr->option.ltr_l1off_sspwrgate = LTR_L1OFF_SSPWRGATE_5250_DEF;
 	pcr->option.ltr_l1off_snooze_sspwrgate =
 		LTR_L1OFF_SNOOZE_SSPWRGATE_5250_DEF;
@@ -733,6 +734,7 @@
 void rts525a_init_params(struct rtsx_pcr *pcr)
 {
 	rts5249_init_params(pcr);
+	pcr->tx_initial_phase = SET_CLOCK_PHASE(25, 29, 11);
 	pcr->option.ltr_l1off_sspwrgate = LTR_L1OFF_SSPWRGATE_5250_DEF;
 	pcr->option.ltr_l1off_snooze_sspwrgate =
 		LTR_L1OFF_SNOOZE_SSPWRGATE_5250_DEF;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/cardreader/rts5260.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/cardreader/rts5260.c
@@ -663,7 +663,7 @@
 	pcr->sd30_drive_sel_1v8 = CFG_DRIVER_TYPE_B;
 	pcr->sd30_drive_sel_3v3 = CFG_DRIVER_TYPE_B;
 	pcr->aspm_en = ASPM_L1_EN;
-	pcr->tx_initial_phase = SET_CLOCK_PHASE(1, 29, 16);
+	pcr->tx_initial_phase = SET_CLOCK_PHASE(27, 29, 11);
 	pcr->rx_initial_phase = SET_CLOCK_PHASE(24, 6, 5);
 
 	pcr->ic_version = rts5260_get_ic_version(pcr);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/cardreader/rtsx_pcr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/cardreader/rtsx_pcr.c
@@ -143,6 +143,9 @@
 
 	rtsx_disable_aspm(pcr);
 
+	/* Fixes DMA transfer timout issue after disabling ASPM on RTS5260 */
+	msleep(1);
+
 	if (option->ltr_enabled)
 		rtsx_set_ltr_latency(pcr, option->ltr_active_latency);
 
@@ -1186,10 +1189,6 @@
 			rtsx_pci_write_register(pcr, REG_OCPGLITCH,
 				SD_OCP_GLITCH_MASK, pcr->hw_param.ocp_glitch);
 			rtsx_pci_enable_ocp(pcr);
-		} else {
-			/* OC power down */
-			rtsx_pci_write_register(pcr, FPDCTL, OC_POWER_DOWN,
-				OC_POWER_DOWN);
 		}
 	}
 }
@@ -1486,7 +1485,7 @@
 	pcr->remap_addr = ioremap_nocache(base, len);
 	if (!pcr->remap_addr) {
 		ret = -ENOMEM;
-		goto free_handle;
+		goto free_idr;
 	}
 
 	pcr->rtsx_resv_buf = dma_alloc_coherent(&(pcidev->dev),
@@ -1531,12 +1530,14 @@
 	ret = mfd_add_devices(&pcidev->dev, pcr->id, rtsx_pcr_cells,
 			ARRAY_SIZE(rtsx_pcr_cells), NULL, 0, NULL);
 	if (ret < 0)
-		goto disable_irq;
+		goto free_slots;
 
 	schedule_delayed_work(&pcr->idle_work, msecs_to_jiffies(200));
 
 	return 0;
 
+free_slots:
+	kfree(pcr->slots);
 disable_irq:
 	free_irq(pcr->irq, (void *)pcr);
 disable_msi:
@@ -1546,6 +1547,10 @@
 			pcr->rtsx_resv_buf, pcr->rtsx_resv_buf_addr);
 unmap:
 	iounmap(pcr->remap_addr);
+free_idr:
+	spin_lock(&rtsx_pci_lock);
+	idr_remove(&rtsx_pci_idr, pcr->id);
+	spin_unlock(&rtsx_pci_lock);
 free_handle:
 	kfree(handle);
 free_pcr:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/cardreader/rtsx_usb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/cardreader/rtsx_usb.c
@@ -631,16 +631,20 @@
 
 	ucr->pusb_dev = usb_dev;
 
-	ucr->iobuf = usb_alloc_coherent(ucr->pusb_dev, IOBUF_SIZE,
-			GFP_KERNEL, &ucr->iobuf_dma);
-	if (!ucr->iobuf)
+	ucr->cmd_buf = kmalloc(IOBUF_SIZE, GFP_KERNEL);
+	if (!ucr->cmd_buf)
 		return -ENOMEM;
 
+	ucr->rsp_buf = kmalloc(IOBUF_SIZE, GFP_KERNEL);
+	if (!ucr->rsp_buf) {
+		ret = -ENOMEM;
+		goto out_free_cmd_buf;
+	}
+
 	usb_set_intfdata(intf, ucr);
 
 	ucr->vendor_id = id->idVendor;
 	ucr->product_id = id->idProduct;
-	ucr->cmd_buf = ucr->rsp_buf = ucr->iobuf;
 
 	mutex_init(&ucr->dev_mutex);
 
@@ -667,8 +671,12 @@
 	return 0;
 
 out_init_fail:
-	usb_free_coherent(ucr->pusb_dev, IOBUF_SIZE, ucr->iobuf,
-			ucr->iobuf_dma);
+	usb_set_intfdata(ucr->pusb_intf, NULL);
+	kfree(ucr->rsp_buf);
+	ucr->rsp_buf = NULL;
+out_free_cmd_buf:
+	kfree(ucr->cmd_buf);
+	ucr->cmd_buf = NULL;
 	return ret;
 }
 
@@ -681,8 +689,12 @@
 	mfd_remove_devices(&intf->dev);
 
 	usb_set_intfdata(ucr->pusb_intf, NULL);
-	usb_free_coherent(ucr->pusb_dev, IOBUF_SIZE, ucr->iobuf,
-			ucr->iobuf_dma);
+
+	kfree(ucr->cmd_buf);
+	ucr->cmd_buf = NULL;
+
+	kfree(ucr->rsp_buf);
+	ucr->rsp_buf = NULL;
 }
 
 #ifdef CONFIG_PM
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/cb710/sgbuf2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/cb710/sgbuf2.c
@@ -47,7 +47,7 @@
 #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
 	return false;
 #else
-	return ((ptr - NULL) & 3) != 0;
+	return ((uintptr_t)ptr & 3) != 0;
 #endif
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/cxl/flash.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/cxl/flash.c
@@ -473,12 +473,6 @@
 		return -EINVAL;
 }
 
-static long device_compat_ioctl(struct file *file, unsigned int cmd,
-				unsigned long arg)
-{
-	return device_ioctl(file, cmd, arg);
-}
-
 static int device_close(struct inode *inode, struct file *file)
 {
 	struct cxl *adapter = file->private_data;
@@ -514,7 +508,7 @@
 	.owner		= THIS_MODULE,
 	.open		= device_open,
 	.unlocked_ioctl	= device_ioctl,
-	.compat_ioctl	= device_compat_ioctl,
+	.compat_ioctl	= compat_ptr_ioctl,
 	.release	= device_close,
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/cxl/guest.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/cxl/guest.c
@@ -959,10 +959,10 @@
 	 * if it returns an error!
 	 */
 	if ((rc = cxl_register_afu(afu)))
-		goto err_put1;
+		goto err_put_dev;
 
 	if ((rc = cxl_sysfs_afu_add(afu)))
-		goto err_put1;
+		goto err_del_dev;
 
 	/*
 	 * pHyp doesn't expose the programming models supported by the
@@ -978,7 +978,7 @@
 		afu->modes_supported = CXL_MODE_DIRECTED;
 
 	if ((rc = cxl_afu_select_best_mode(afu)))
-		goto err_put2;
+		goto err_remove_sysfs;
 
 	adapter->afu[afu->slice] = afu;
 
@@ -998,10 +998,12 @@
 
 	return 0;
 
-err_put2:
+err_remove_sysfs:
 	cxl_sysfs_afu_remove(afu);
-err_put1:
-	device_unregister(&afu->dev);
+err_del_dev:
+	device_del(&afu->dev);
+err_put_dev:
+	put_device(&afu->dev);
 	free = false;
 	guest_release_serr_irq(afu);
 err2:
@@ -1135,18 +1137,20 @@
 	 * even if it returns an error!
 	 */
 	if ((rc = cxl_register_adapter(adapter)))
-		goto err_put1;
+		goto err_put_dev;
 
 	if ((rc = cxl_sysfs_adapter_add(adapter)))
-		goto err_put1;
+		goto err_del_dev;
 
 	/* release the context lock as the adapter is configured */
 	cxl_adapter_context_unlock(adapter);
 
 	return adapter;
 
-err_put1:
-	device_unregister(&adapter->dev);
+err_del_dev:
+	device_del(&adapter->dev);
+err_put_dev:
+	put_device(&adapter->dev);
 	free = false;
 	cxl_guest_remove_chardev(adapter);
 err1:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/cxl/irq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/cxl/irq.c
@@ -349,6 +349,7 @@
 
 out:
 	cxl_ops->release_irq_ranges(&ctx->irqs, ctx->afu->adapter);
+	bitmap_free(ctx->irq_bitmap);
 	afu_irq_name_free(ctx);
 	return -ENOMEM;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/cxl/pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/cxl/pci.c
@@ -387,14 +387,15 @@
 	rc = get_phb_index(np, phb_index);
 	if (rc) {
 		pr_err("cxl: invalid phb index\n");
+		of_node_put(np);
 		return rc;
 	}
 
 	*capp_unit_id = get_capp_unit_id(np, *phb_index);
 	of_node_put(np);
 	if (!*capp_unit_id) {
-		pr_err("cxl: invalid capp unit id (phb_index: %d)\n",
-		       *phb_index);
+		pr_err("cxl: No capp unit found for PHB[%lld,%d]. Make sure the adapter is on a capi-compatible slot\n",
+		       *chipid, *phb_index);
 		return -ENODEV;
 	}
 
@@ -1164,10 +1165,10 @@
 	 * if it returns an error!
 	 */
 	if ((rc = cxl_register_afu(afu)))
-		goto err_put1;
+		goto err_put_dev;
 
 	if ((rc = cxl_sysfs_afu_add(afu)))
-		goto err_put1;
+		goto err_del_dev;
 
 	adapter->afu[afu->slice] = afu;
 
@@ -1176,10 +1177,12 @@
 
 	return 0;
 
-err_put1:
+err_del_dev:
+	device_del(&afu->dev);
+err_put_dev:
 	pci_deconfigure_afu(afu);
 	cxl_debugfs_afu_remove(afu);
-	device_unregister(&afu->dev);
+	put_device(&afu->dev);
 	return rc;
 
 err_free_native:
@@ -1667,23 +1670,25 @@
 	 * even if it returns an error!
 	 */
 	if ((rc = cxl_register_adapter(adapter)))
-		goto err_put1;
+		goto err_put_dev;
 
 	if ((rc = cxl_sysfs_adapter_add(adapter)))
-		goto err_put1;
+		goto err_del_dev;
 
 	/* Release the context lock as adapter is configured */
 	cxl_adapter_context_unlock(adapter);
 
 	return adapter;
 
-err_put1:
+err_del_dev:
+	device_del(&adapter->dev);
+err_put_dev:
 	/* This should mirror cxl_remove_adapter, except without the
 	 * sysfs parts
 	 */
 	cxl_debugfs_adapter_remove(adapter);
 	cxl_deconfigure_adapter(adapter);
-	device_unregister(&adapter->dev);
+	put_device(&adapter->dev);
 	return ERR_PTR(rc);
 
 err_release:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/cxl/sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/cxl/sysfs.c
@@ -624,7 +624,7 @@
 	rc = kobject_init_and_add(&cr->kobj, &afu_config_record_type,
 				  &afu->dev.kobj, "cr%i", cr->cr);
 	if (rc)
-		goto err;
+		goto err1;
 
 	rc = sysfs_create_bin_file(&cr->kobj, &cr->config_attr);
 	if (rc)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/eeprom/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/eeprom/Kconfig
@@ -6,6 +6,7 @@
 	depends on I2C && SYSFS
 	select NVMEM
 	select NVMEM_SYSFS
+	select REGMAP
 	select REGMAP_I2C
 	help
 	  Enable this driver to get read/write support to most I2C EEPROMs
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/eeprom/at24.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/eeprom/at24.c
@@ -695,10 +695,6 @@
 	nvmem_config.word_size = 1;
 	nvmem_config.size = byte_len;
 
-	at24->nvmem = devm_nvmem_register(dev, &nvmem_config);
-	if (IS_ERR(at24->nvmem))
-		return PTR_ERR(at24->nvmem);
-
 	i2c_set_clientdata(client, at24);
 
 	/* enable runtime pm */
@@ -710,12 +706,19 @@
 	 * chip is functional.
 	 */
 	err = at24_read(at24, 0, &test_byte, 1);
-	pm_runtime_idle(dev);
 	if (err) {
 		pm_runtime_disable(dev);
 		return -ENODEV;
 	}
 
+	at24->nvmem = devm_nvmem_register(dev, &nvmem_config);
+	if (IS_ERR(at24->nvmem)) {
+		pm_runtime_disable(dev);
+		return PTR_ERR(at24->nvmem);
+	}
+
+	pm_runtime_idle(dev);
+
 	dev_info(dev, "%u byte %s EEPROM, %s, %u bytes/write\n",
 		 byte_len, client->name,
 		 writable ? "writable" : "read-only", at24->write_max);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/eeprom/at25.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/eeprom/at25.c
@@ -358,7 +358,7 @@
 	at25->nvmem_config.reg_read = at25_ee_read;
 	at25->nvmem_config.reg_write = at25_ee_write;
 	at25->nvmem_config.priv = at25;
-	at25->nvmem_config.stride = 4;
+	at25->nvmem_config.stride = 1;
 	at25->nvmem_config.word_size = 1;
 	at25->nvmem_config.size = chip.byte_len;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/eeprom/digsy_mtc_eeprom.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/eeprom/digsy_mtc_eeprom.c
@@ -60,7 +60,7 @@
 };
 
 static struct gpiod_lookup_table eeprom_spi_gpiod_table = {
-	.dev_id         = "spi_gpio",
+	.dev_id         = "spi_gpio.1",
 	.table          = {
 		GPIO_LOOKUP("gpio@b00", GPIO_EEPROM_CLK,
 			    "sck", GPIO_ACTIVE_HIGH),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/eeprom/ee1004.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/eeprom/ee1004.c
@@ -82,6 +82,9 @@
 	if (unlikely(offset + count > EE1004_PAGE_SIZE))
 		count = EE1004_PAGE_SIZE - offset;
 
+	if (count > I2C_SMBUS_BLOCK_MAX)
+		count = I2C_SMBUS_BLOCK_MAX;
+
 	status = i2c_smbus_read_i2c_block_data_or_emulated(client, offset,
 							   count, buf);
 	dev_dbg(&client->dev, "read %zu@%d --> %d\n", count, offset, status);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/eeprom/eeprom_93cx6.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/eeprom/eeprom_93cx6.c
@@ -186,6 +186,11 @@
 	eeprom_93cx6_write_bits(eeprom, command,
 		PCI_EEPROM_WIDTH_OPCODE + eeprom->width);
 
+	if (has_quirk_extra_read_cycle(eeprom)) {
+		eeprom_93cx6_pulse_high(eeprom);
+		eeprom_93cx6_pulse_low(eeprom);
+	}
+
 	/*
 	 * Read the requested 16 bits.
 	 */
@@ -252,6 +257,11 @@
 	eeprom_93cx6_write_bits(eeprom, command,
 		PCI_EEPROM_WIDTH_OPCODE + eeprom->width + 1);
 
+	if (has_quirk_extra_read_cycle(eeprom)) {
+		eeprom_93cx6_pulse_high(eeprom);
+		eeprom_93cx6_pulse_low(eeprom);
+	}
+
 	/*
 	 * Read the requested 8 bits.
 	 */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/eeprom/eeprom_93xx46.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/eeprom/eeprom_93xx46.c
@@ -35,6 +35,10 @@
 		  EEPROM_93XX46_QUIRK_INSTRUCTION_LENGTH,
 };
 
+static const struct eeprom_93xx46_devtype_data microchip_93lc46b_data = {
+	.quirks = EEPROM_93XX46_QUIRK_EXTRA_READ_CYCLE,
+};
+
 struct eeprom_93xx46_dev {
 	struct spi_device *spi;
 	struct eeprom_93xx46_platform_data *pdata;
@@ -55,6 +59,11 @@
 	return edev->pdata->quirks & EEPROM_93XX46_QUIRK_INSTRUCTION_LENGTH;
 }
 
+static inline bool has_quirk_extra_read_cycle(struct eeprom_93xx46_dev *edev)
+{
+	return edev->pdata->quirks & EEPROM_93XX46_QUIRK_EXTRA_READ_CYCLE;
+}
+
 static int eeprom_93xx46_read(void *priv, unsigned int off,
 			      void *val, size_t count)
 {
@@ -96,6 +105,11 @@
 		dev_dbg(&edev->spi->dev, "read cmd 0x%x, %d Hz\n",
 			cmd_addr, edev->spi->max_speed_hz);
 
+		if (has_quirk_extra_read_cycle(edev)) {
+			cmd_addr <<= 1;
+			bits += 1;
+		}
+
 		spi_message_init(&m);
 
 		t[0].tx_buf = (char *)&cmd_addr;
@@ -363,6 +377,7 @@
 static const struct of_device_id eeprom_93xx46_of_table[] = {
 	{ .compatible = "eeprom-93xx46", },
 	{ .compatible = "atmel,at93c46d", .data = &atmel_at93c46d_data, },
+	{ .compatible = "microchip,93lc46b", .data = &microchip_93lc46b_data, },
 	{}
 };
 MODULE_DEVICE_TABLE(of, eeprom_93xx46_of_table);
@@ -511,3 +526,4 @@
 MODULE_DESCRIPTION("Driver for 93xx46 EEPROMs");
 MODULE_AUTHOR("Anatolij Gustschin <agust@denx.de>");
 MODULE_ALIAS("spi:93xx46");
+MODULE_ALIAS("spi:eeprom-93xx46");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/eeprom/idt_89hpesx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/eeprom/idt_89hpesx.c
@@ -1126,11 +1126,10 @@
 
 	device_for_each_child_node(dev, fwnode) {
 		ee_id = idt_ee_match_id(fwnode);
-		if (!ee_id) {
-			dev_warn(dev, "Skip unsupported EEPROM device");
-			continue;
-		} else
+		if (ee_id)
 			break;
+
+		dev_warn(dev, "Skip unsupported EEPROM device %pfw\n", fwnode);
 	}
 
 	/* If there is no fwnode EEPROM device, then set zero size */
@@ -1161,6 +1160,7 @@
 	else /* if (!fwnode_property_read_bool(node, "read-only")) */
 		pdev->eero = false;
 
+	fwnode_handle_put(fwnode);
 	dev_info(dev, "EEPROM of %d bytes found by 0x%x",
 		pdev->eesize, pdev->eeaddr);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/enclosure.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/enclosure.c
@@ -406,10 +406,9 @@
 		cdev = &edev->component[i];
 		if (cdev->dev == dev) {
 			enclosure_remove_links(cdev);
-			device_del(&cdev->cdev);
 			put_device(dev);
 			cdev->dev = NULL;
-			return device_add(&cdev->cdev);
+			return 0;
 		}
 	}
 	return -ENODEV;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/fastrpc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/fastrpc.c
@@ -218,6 +218,13 @@
 		dma_buf_put(map->buf);
 	}
 
+	if (map->fl) {
+		spin_lock(&map->fl->lock);
+		list_del(&map->node);
+		spin_unlock(&map->fl->lock);
+		map->fl = NULL;
+	}
+
 	kfree(map);
 }
 
@@ -227,10 +234,12 @@
 		kref_put(&map->refcount, fastrpc_free_map);
 }
 
-static void fastrpc_map_get(struct fastrpc_map *map)
+static int fastrpc_map_get(struct fastrpc_map *map)
 {
-	if (map)
-		kref_get(&map->refcount);
+	if (!map)
+		return -ENOENT;
+
+	return kref_get_unless_zero(&map->refcount) ? 0 : -ENOENT;
 }
 
 static int fastrpc_map_find(struct fastrpc_user *fl, int fd,
@@ -693,16 +702,18 @@
 static u64 fastrpc_get_payload_size(struct fastrpc_invoke_ctx *ctx, int metalen)
 {
 	u64 size = 0;
-	int i;
+	int oix;
 
 	size = ALIGN(metalen, FASTRPC_ALIGN);
-	for (i = 0; i < ctx->nscalars; i++) {
+	for (oix = 0; oix < ctx->nbufs; oix++) {
+		int i = ctx->olaps[oix].raix;
+
 		if (ctx->args[i].fd == 0 || ctx->args[i].fd == -1) {
 
-			if (ctx->olaps[i].offset == 0)
+			if (ctx->olaps[oix].offset == 0)
 				size = ALIGN(size, FASTRPC_ALIGN);
 
-			size += (ctx->olaps[i].mend - ctx->olaps[i].mstart);
+			size += (ctx->olaps[oix].mend - ctx->olaps[oix].mstart);
 		}
 	}
 
@@ -790,7 +801,7 @@
 
 			vma = find_vma(current->mm, ctx->args[i].ptr);
 			if (vma)
-				pages[i].addr += ctx->args[i].ptr -
+				pages[i].addr += (ctx->args[i].ptr & PAGE_MASK) -
 						 vma->vm_start;
 
 			pg_start = (ctx->args[i].ptr & PAGE_MASK) >> PAGE_SHIFT;
@@ -886,6 +897,7 @@
 	struct fastrpc_channel_ctx *cctx;
 	struct fastrpc_user *fl = ctx->fl;
 	struct fastrpc_msg *msg = &ctx->msg;
+	int ret;
 
 	cctx = fl->cctx;
 	msg->pid = fl->tgid;
@@ -901,7 +913,13 @@
 	msg->size = roundup(ctx->msg_sz, PAGE_SIZE);
 	fastrpc_context_get(ctx);
 
-	return rpmsg_send(cctx->rpdev->ept, (void *)msg, sizeof(*msg));
+	ret = rpmsg_send(cctx->rpdev->ept, (void *)msg, sizeof(*msg));
+
+	if (ret)
+		fastrpc_context_put(ctx);
+
+	return ret;
+
 }
 
 static int fastrpc_internal_invoke(struct fastrpc_user *fl,  u32 kernel,
@@ -917,6 +935,11 @@
 	if (!fl->cctx->rpdev)
 		return -EPIPE;
 
+	if (handle == FASTRPC_INIT_HANDLE && !kernel) {
+		dev_warn_ratelimited(fl->sctx->dev, "user app trying to send a kernel RPC message (%d)\n",  handle);
+		return -EPERM;
+	}
+
 	ctx = fastrpc_context_alloc(fl, kernel, sc, args);
 	if (IS_ERR(ctx))
 		return PTR_ERR(ctx);
@@ -1051,7 +1074,7 @@
 
 	sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_CREATE, 4, 0);
 	if (init.attrs)
-		sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_CREATE_ATTR, 6, 0);
+		sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_CREATE_ATTR, 4, 0);
 
 	err = fastrpc_internal_invoke(fl, true, FASTRPC_INIT_HANDLE,
 				      sc, args);
@@ -1066,12 +1089,7 @@
 	fl->init_mem = NULL;
 	fastrpc_buf_free(imem);
 err_alloc:
-	if (map) {
-		spin_lock(&fl->lock);
-		list_del(&map->node);
-		spin_unlock(&fl->lock);
-		fastrpc_map_put(map);
-	}
+	fastrpc_map_put(map);
 err:
 	kfree(args);
 
@@ -1147,10 +1165,8 @@
 		fastrpc_context_put(ctx);
 	}
 
-	list_for_each_entry_safe(map, m, &fl->maps, node) {
-		list_del(&map->node);
+	list_for_each_entry_safe(map, m, &fl->maps, node)
 		fastrpc_map_put(map);
-	}
 
 	fastrpc_session_free(cctx, fl->sctx);
 	fastrpc_channel_ctx_put(cctx);
@@ -1231,7 +1247,14 @@
 	}
 
 	if (copy_to_user(argp, &bp, sizeof(bp))) {
-		dma_buf_put(buf->dmabuf);
+		/*
+		 * The usercopy failed, but we can't do much about it, as
+		 * dma_buf_fd() already called fd_install() and made the
+		 * file descriptor accessible for the current process. It
+		 * might already be closed and dmabuf no longer valid when
+		 * we reach this point. Therefore "leak" the fd and rely on
+		 * the process exit path to do any required cleanup.
+		 */
 		return -EFAULT;
 	}
 
@@ -1336,7 +1359,12 @@
 	of_property_read_u32(dev->of_node, "qcom,nsessions", &sessions);
 
 	spin_lock_irqsave(&cctx->lock, flags);
-	sess = &cctx->session[cctx->sesscount];
+	if (cctx->sesscount >= FASTRPC_MAX_SESSIONS) {
+		dev_err(&pdev->dev, "too many sessions\n");
+		spin_unlock_irqrestore(&cctx->lock, flags);
+		return -ENOSPC;
+	}
+	sess = &cctx->session[cctx->sesscount++];
 	sess->used = false;
 	sess->valid = true;
 	sess->dev = dev;
@@ -1349,13 +1377,12 @@
 		struct fastrpc_session_ctx *dup_sess;
 
 		for (i = 1; i < sessions; i++) {
-			if (cctx->sesscount++ >= FASTRPC_MAX_SESSIONS)
+			if (cctx->sesscount >= FASTRPC_MAX_SESSIONS)
 				break;
-			dup_sess = &cctx->session[cctx->sesscount];
+			dup_sess = &cctx->session[cctx->sesscount++];
 			memcpy(dup_sess, sess, sizeof(*dup_sess));
 		}
 	}
-	cctx->sesscount++;
 	spin_unlock_irqrestore(&cctx->lock, flags);
 	rc = dma_set_mask(dev, DMA_BIT_MASK(32));
 	if (rc) {
@@ -1374,7 +1401,7 @@
 	int i;
 
 	spin_lock_irqsave(&cctx->lock, flags);
-	for (i = 1; i < FASTRPC_MAX_SESSIONS; i++) {
+	for (i = 0; i < FASTRPC_MAX_SESSIONS; i++) {
 		if (cctx->session[i].sid == sess->sid) {
 			cctx->session[i].valid = false;
 			cctx->sesscount--;
@@ -1430,12 +1457,14 @@
 		return -ENOMEM;
 
 	data->miscdev.minor = MISC_DYNAMIC_MINOR;
-	data->miscdev.name = kasprintf(GFP_KERNEL, "fastrpc-%s",
-				domains[domain_id]);
+	data->miscdev.name = devm_kasprintf(rdev, GFP_KERNEL, "fastrpc-%s",
+					    domains[domain_id]);
 	data->miscdev.fops = &fastrpc_fops;
 	err = misc_register(&data->miscdev);
-	if (err)
+	if (err) {
+		kfree(data);
 		return err;
+	}
 
 	kref_init(&data->refcount);
 
@@ -1455,8 +1484,10 @@
 	struct fastrpc_invoke_ctx *ctx;
 
 	spin_lock(&user->lock);
-	list_for_each_entry(ctx, &user->pending, node)
+	list_for_each_entry(ctx, &user->pending, node) {
+		ctx->retval = -EPIPE;
 		complete(&ctx->work);
+	}
 	spin_unlock(&user->lock);
 }
 
@@ -1466,7 +1497,9 @@
 	struct fastrpc_user *user;
 	unsigned long flags;
 
+	/* No invocations past this point */
 	spin_lock_irqsave(&cctx->lock, flags);
+	cctx->rpdev = NULL;
 	list_for_each_entry(user, &cctx->users, user)
 		fastrpc_notify_users(user);
 	spin_unlock_irqrestore(&cctx->lock, flags);
@@ -1474,7 +1507,6 @@
 	misc_deregister(&cctx->miscdev);
 	of_platform_depopulate(&rpdev->dev);
 
-	cctx->rpdev = NULL;
 	fastrpc_channel_ctx_put(cctx);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/genwqe/card_dev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/genwqe/card_dev.c
@@ -1215,34 +1215,13 @@
 	return rc;
 }
 
-#if defined(CONFIG_COMPAT)
-/**
- * genwqe_compat_ioctl() - Compatibility ioctl
- *
- * Called whenever a 32-bit process running under a 64-bit kernel
- * performs an ioctl on /dev/genwqe<n>_card.
- *
- * @filp:        file pointer.
- * @cmd:         command.
- * @arg:         user argument.
- * Return:       zero on success or negative number on failure.
- */
-static long genwqe_compat_ioctl(struct file *filp, unsigned int cmd,
-				unsigned long arg)
-{
-	return genwqe_ioctl(filp, cmd, arg);
-}
-#endif /* defined(CONFIG_COMPAT) */
-
 static const struct file_operations genwqe_fops = {
 	.owner		= THIS_MODULE,
 	.open		= genwqe_open,
 	.fasync		= genwqe_fasync,
 	.mmap		= genwqe_mmap,
 	.unlocked_ioctl	= genwqe_ioctl,
-#if defined(CONFIG_COMPAT)
-	.compat_ioctl   = genwqe_compat_ioctl,
-#endif
+	.compat_ioctl   = compat_ptr_ioctl,
 	.release	= genwqe_release,
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/habanalabs/command_submission.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/habanalabs/command_submission.c
@@ -777,8 +777,9 @@
 	memset(args, 0, sizeof(*args));
 
 	if (rc < 0) {
-		dev_err(hdev->dev, "Error %ld on waiting for CS handle %llu\n",
-			rc, seq);
+		dev_err_ratelimited(hdev->dev,
+				"Error %ld on waiting for CS handle %llu\n",
+				rc, seq);
 		if (rc == -ERESTARTSYS) {
 			args->out.status = HL_WAIT_CS_STATUS_INTERRUPTED;
 			rc = -EINTR;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/habanalabs/context.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/habanalabs/context.c
@@ -176,7 +176,7 @@
 	spin_lock(&ctx->cs_lock);
 
 	if (seq >= ctx->cs_sequence) {
-		dev_notice(hdev->dev,
+		dev_notice_ratelimited(hdev->dev,
 			"Can't wait on seq %llu because current CS is at seq %llu\n",
 			seq, ctx->cs_sequence);
 		spin_unlock(&ctx->cs_lock);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/habanalabs/device.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/habanalabs/device.c
@@ -108,6 +108,8 @@
 	list_del(&hpriv->dev_node);
 	mutex_unlock(&hdev->fpriv_list_lock);
 
+	put_pid(hpriv->taskpid);
+
 	kfree(hpriv);
 
 	return 0;
@@ -229,16 +231,16 @@
 
 static void device_cdev_sysfs_del(struct hl_device *hdev)
 {
-	/* device_release() won't be called so must free devices explicitly */
-	if (!hdev->cdev_sysfs_created) {
-		kfree(hdev->dev_ctrl);
-		kfree(hdev->dev);
-		return;
-	}
+	if (!hdev->cdev_sysfs_created)
+		goto put_devices;
 
 	hl_sysfs_fini(hdev);
 	cdev_device_del(&hdev->cdev_ctrl, hdev->dev_ctrl);
 	cdev_device_del(&hdev->cdev, hdev->dev);
+
+put_devices:
+	put_device(hdev->dev);
+	put_device(hdev->dev_ctrl);
 }
 
 /*
@@ -600,7 +602,9 @@
 			goto out;
 		}
 
-		hdev->asic_funcs->halt_coresight(hdev);
+		if (!hdev->hard_reset_pending)
+			hdev->asic_funcs->halt_coresight(hdev);
+
 		hdev->in_debug = 0;
 
 		goto out;
@@ -957,6 +961,7 @@
 						GFP_KERNEL);
 		if (!hdev->kernel_ctx) {
 			rc = -ENOMEM;
+			hl_mmu_fini(hdev);
 			goto out_err;
 		}
 
@@ -968,6 +973,7 @@
 				"failed to init kernel ctx in hard reset\n");
 			kfree(hdev->kernel_ctx);
 			hdev->kernel_ctx = NULL;
+			hl_mmu_fini(hdev);
 			goto out_err;
 		}
 	}
@@ -1185,6 +1191,7 @@
 	if (hdev->asic_funcs->get_hw_state(hdev) == HL_DEVICE_HW_STATE_DIRTY) {
 		dev_info(hdev->dev,
 			"H/W state is dirty, must reset before initializing\n");
+		hdev->asic_funcs->halt_engines(hdev, true);
 		hdev->asic_funcs->hw_fini(hdev, true);
 	}
 
@@ -1282,9 +1289,9 @@
 early_fini:
 	device_early_fini(hdev);
 free_dev_ctrl:
-	kfree(hdev->dev_ctrl);
+	put_device(hdev->dev_ctrl);
 free_dev:
-	kfree(hdev->dev);
+	put_device(hdev->dev);
 out_disabled:
 	hdev->disabled = true;
 	if (add_cdev_sysfs_on_err)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/habanalabs/firmware_if.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/habanalabs/firmware_if.c
@@ -11,6 +11,7 @@
 #include <linux/genalloc.h>
 #include <linux/io-64-nonatomic-lo-hi.h>
 
+#define FW_FILE_MAX_SIZE	0x1400000 /* maximum size of 20MB */
 /**
  * hl_fw_push_fw_to_device() - Push FW code to device.
  * @hdev: pointer to hl_device structure.
@@ -43,6 +44,14 @@
 
 	dev_dbg(hdev->dev, "%s firmware size == %zu\n", fw_name, fw_size);
 
+	if (fw_size > FW_FILE_MAX_SIZE) {
+		dev_err(hdev->dev,
+			"FW file size %zu exceeds maximum of %u bytes\n",
+			fw_size, FW_FILE_MAX_SIZE);
+		rc = -EINVAL;
+		goto out;
+	}
+
 	fw_data = (const u64 *) fw->data;
 
 	memcpy_toio(dst, fw_data, fw_size);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/habanalabs/goya/goya.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/habanalabs/goya/goya.c
@@ -869,6 +869,11 @@
  */
 static void goya_disable_external_queues(struct hl_device *hdev)
 {
+	struct goya_device *goya = hdev->asic_specific;
+
+	if (!(goya->hw_cap_initialized & HW_CAP_DMA))
+		return;
+
 	WREG32(mmDMA_QM_0_GLBL_CFG0, 0);
 	WREG32(mmDMA_QM_1_GLBL_CFG0, 0);
 	WREG32(mmDMA_QM_2_GLBL_CFG0, 0);
@@ -930,6 +935,11 @@
 {
 	int rc, retval = 0;
 
+	struct goya_device *goya = hdev->asic_specific;
+
+	if (!(goya->hw_cap_initialized & HW_CAP_DMA))
+		return retval;
+
 	rc = goya_stop_queue(hdev,
 			mmDMA_QM_0_GLBL_CFG1,
 			mmDMA_QM_0_CP_STS,
@@ -1719,9 +1729,18 @@
  */
 static void goya_disable_internal_queues(struct hl_device *hdev)
 {
+	struct goya_device *goya = hdev->asic_specific;
+
+	if (!(goya->hw_cap_initialized & HW_CAP_MME))
+		goto disable_tpc;
+
 	WREG32(mmMME_QM_GLBL_CFG0, 0);
 	WREG32(mmMME_CMDQ_GLBL_CFG0, 0);
 
+disable_tpc:
+	if (!(goya->hw_cap_initialized & HW_CAP_TPC))
+		return;
+
 	WREG32(mmTPC0_QM_GLBL_CFG0, 0);
 	WREG32(mmTPC0_CMDQ_GLBL_CFG0, 0);
 
@@ -1757,8 +1776,12 @@
  */
 static int goya_stop_internal_queues(struct hl_device *hdev)
 {
+	struct goya_device *goya = hdev->asic_specific;
 	int rc, retval = 0;
 
+	if (!(goya->hw_cap_initialized & HW_CAP_MME))
+		goto stop_tpc;
+
 	/*
 	 * Each queue (QMAN) is a separate H/W logic. That means that each
 	 * QMAN can be stopped independently and failure to stop one does NOT
@@ -1785,6 +1808,10 @@
 		retval = -EIO;
 	}
 
+stop_tpc:
+	if (!(goya->hw_cap_initialized & HW_CAP_TPC))
+		return retval;
+
 	rc = goya_stop_queue(hdev,
 			mmTPC0_QM_GLBL_CFG1,
 			mmTPC0_QM_CP_STS,
@@ -1950,6 +1977,11 @@
 
 static void goya_dma_stall(struct hl_device *hdev)
 {
+	struct goya_device *goya = hdev->asic_specific;
+
+	if (!(goya->hw_cap_initialized & HW_CAP_DMA))
+		return;
+
 	WREG32(mmDMA_QM_0_GLBL_CFG1, 1 << DMA_QM_0_GLBL_CFG1_DMA_STOP_SHIFT);
 	WREG32(mmDMA_QM_1_GLBL_CFG1, 1 << DMA_QM_1_GLBL_CFG1_DMA_STOP_SHIFT);
 	WREG32(mmDMA_QM_2_GLBL_CFG1, 1 << DMA_QM_2_GLBL_CFG1_DMA_STOP_SHIFT);
@@ -1959,6 +1991,11 @@
 
 static void goya_tpc_stall(struct hl_device *hdev)
 {
+	struct goya_device *goya = hdev->asic_specific;
+
+	if (!(goya->hw_cap_initialized & HW_CAP_TPC))
+		return;
+
 	WREG32(mmTPC0_CFG_TPC_STALL, 1 << TPC0_CFG_TPC_STALL_V_SHIFT);
 	WREG32(mmTPC1_CFG_TPC_STALL, 1 << TPC1_CFG_TPC_STALL_V_SHIFT);
 	WREG32(mmTPC2_CFG_TPC_STALL, 1 << TPC2_CFG_TPC_STALL_V_SHIFT);
@@ -1971,6 +2008,11 @@
 
 static void goya_mme_stall(struct hl_device *hdev)
 {
+	struct goya_device *goya = hdev->asic_specific;
+
+	if (!(goya->hw_cap_initialized & HW_CAP_MME))
+		return;
+
 	WREG32(mmMME_STALL, 0xFFFFFFFF);
 }
 
@@ -2171,7 +2213,7 @@
 
 static int goya_pldm_init_cpu(struct hl_device *hdev)
 {
-	u32 val, unit_rst_val;
+	u32 unit_rst_val;
 	int rc;
 
 	/* Must initialize SRAM scrambler before pushing u-boot to SRAM */
@@ -2179,14 +2221,14 @@
 
 	/* Put ARM cores into reset */
 	WREG32(mmCPU_CA53_CFG_ARM_RST_CONTROL, CPU_RESET_ASSERT);
-	val = RREG32(mmCPU_CA53_CFG_ARM_RST_CONTROL);
+	RREG32(mmCPU_CA53_CFG_ARM_RST_CONTROL);
 
 	/* Reset the CA53 MACRO */
 	unit_rst_val = RREG32(mmPSOC_GLOBAL_CONF_UNIT_RST_N);
 	WREG32(mmPSOC_GLOBAL_CONF_UNIT_RST_N, CA53_RESET);
-	val = RREG32(mmPSOC_GLOBAL_CONF_UNIT_RST_N);
+	RREG32(mmPSOC_GLOBAL_CONF_UNIT_RST_N);
 	WREG32(mmPSOC_GLOBAL_CONF_UNIT_RST_N, unit_rst_val);
-	val = RREG32(mmPSOC_GLOBAL_CONF_UNIT_RST_N);
+	RREG32(mmPSOC_GLOBAL_CONF_UNIT_RST_N);
 
 	rc = goya_push_uboot_to_device(hdev);
 	if (rc)
@@ -2207,7 +2249,7 @@
 	/* Release ARM core 0 from reset */
 	WREG32(mmCPU_CA53_CFG_ARM_RST_CONTROL,
 					CPU_RESET_CORE0_DEASSERT);
-	val = RREG32(mmCPU_CA53_CFG_ARM_RST_CONTROL);
+	RREG32(mmCPU_CA53_CFG_ARM_RST_CONTROL);
 
 	return 0;
 }
@@ -2475,13 +2517,12 @@
 static int goya_hw_init(struct hl_device *hdev)
 {
 	struct asic_fixed_properties *prop = &hdev->asic_prop;
-	u32 val;
 	int rc;
 
 	dev_info(hdev->dev, "Starting initialization of H/W\n");
 
 	/* Perform read from the device to make sure device is up */
-	val = RREG32(mmPCIE_DBI_DEVICE_ID_VENDOR_ID_REG);
+	RREG32(mmPCIE_DBI_DEVICE_ID_VENDOR_ID_REG);
 
 	/*
 	 * Let's mark in the H/W that we have reached this point. We check
@@ -2533,7 +2574,7 @@
 		goto disable_queues;
 
 	/* Perform read from the device to flush all MSI-X configuration */
-	val = RREG32(mmPCIE_DBI_DEVICE_ID_VENDOR_ID_REG);
+	RREG32(mmPCIE_DBI_DEVICE_ID_VENDOR_ID_REG);
 
 	return 0;
 
@@ -4625,8 +4666,6 @@
 
 	rc = goya_send_job_on_qman0(hdev, job);
 
-	hl_cb_put(job->patched_cb);
-
 	hl_debugfs_remove_job(hdev, job);
 	kfree(job);
 	cb->cs_cnt--;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/habanalabs/goya/goya_security.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/habanalabs/goya/goya_security.c
@@ -695,7 +695,6 @@
 	mask |= 1 << ((mmTPC0_CFG_CFG_SUBTRACT_VALUE & 0x7F) >> 2);
 	mask |= 1 << ((mmTPC0_CFG_SM_BASE_ADDRESS_LOW & 0x7F) >> 2);
 	mask |= 1 << ((mmTPC0_CFG_SM_BASE_ADDRESS_HIGH & 0x7F) >> 2);
-	mask |= 1 << ((mmTPC0_CFG_CFG_SUBTRACT_VALUE & 0x7F) >> 2);
 	mask |= 1 << ((mmTPC0_CFG_TPC_STALL & 0x7F) >> 2);
 	mask |= 1 << ((mmTPC0_CFG_MSS_CONFIG & 0x7F) >> 2);
 	mask |= 1 << ((mmTPC0_CFG_TPC_INTR_CAUSE & 0x7F) >> 2);
@@ -875,6 +874,16 @@
 	goya_pb_set_block(hdev, mmTPC1_RD_REGULATOR_BASE);
 	goya_pb_set_block(hdev, mmTPC1_WR_REGULATOR_BASE);
 
+	pb_addr = (mmTPC1_CFG_SEMAPHORE & ~0xFFF) + PROT_BITS_OFFS;
+	word_offset = ((mmTPC1_CFG_SEMAPHORE & PROT_BITS_OFFS) >> 7) << 2;
+
+	mask = 1 << ((mmTPC1_CFG_SEMAPHORE & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC1_CFG_VFLAGS & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC1_CFG_SFLAGS & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC1_CFG_STATUS & 0x7F) >> 2);
+
+	WREG32(pb_addr + word_offset, ~mask);
+
 	pb_addr = (mmTPC1_CFG_CFG_BASE_ADDRESS_HIGH & ~0xFFF) + PROT_BITS_OFFS;
 	word_offset = ((mmTPC1_CFG_CFG_BASE_ADDRESS_HIGH &
 			PROT_BITS_OFFS) >> 7) << 2;
@@ -882,6 +891,10 @@
 	mask |= 1 << ((mmTPC1_CFG_CFG_SUBTRACT_VALUE & 0x7F) >> 2);
 	mask |= 1 << ((mmTPC1_CFG_SM_BASE_ADDRESS_LOW & 0x7F) >> 2);
 	mask |= 1 << ((mmTPC1_CFG_SM_BASE_ADDRESS_HIGH & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC1_CFG_TPC_STALL & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC1_CFG_MSS_CONFIG & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC1_CFG_TPC_INTR_CAUSE & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC1_CFG_TPC_INTR_MASK & 0x7F) >> 2);
 
 	WREG32(pb_addr + word_offset, ~mask);
 
@@ -1057,6 +1070,16 @@
 	goya_pb_set_block(hdev, mmTPC2_RD_REGULATOR_BASE);
 	goya_pb_set_block(hdev, mmTPC2_WR_REGULATOR_BASE);
 
+	pb_addr = (mmTPC2_CFG_SEMAPHORE & ~0xFFF) + PROT_BITS_OFFS;
+	word_offset = ((mmTPC2_CFG_SEMAPHORE & PROT_BITS_OFFS) >> 7) << 2;
+
+	mask = 1 << ((mmTPC2_CFG_SEMAPHORE & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC2_CFG_VFLAGS & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC2_CFG_SFLAGS & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC2_CFG_STATUS & 0x7F) >> 2);
+
+	WREG32(pb_addr + word_offset, ~mask);
+
 	pb_addr = (mmTPC2_CFG_CFG_BASE_ADDRESS_HIGH & ~0xFFF) + PROT_BITS_OFFS;
 	word_offset = ((mmTPC2_CFG_CFG_BASE_ADDRESS_HIGH &
 			PROT_BITS_OFFS) >> 7) << 2;
@@ -1064,6 +1087,10 @@
 	mask |= 1 << ((mmTPC2_CFG_CFG_SUBTRACT_VALUE & 0x7F) >> 2);
 	mask |= 1 << ((mmTPC2_CFG_SM_BASE_ADDRESS_LOW & 0x7F) >> 2);
 	mask |= 1 << ((mmTPC2_CFG_SM_BASE_ADDRESS_HIGH & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC2_CFG_TPC_STALL & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC2_CFG_MSS_CONFIG & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC2_CFG_TPC_INTR_CAUSE & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC2_CFG_TPC_INTR_MASK & 0x7F) >> 2);
 
 	WREG32(pb_addr + word_offset, ~mask);
 
@@ -1239,6 +1266,16 @@
 	goya_pb_set_block(hdev, mmTPC3_RD_REGULATOR_BASE);
 	goya_pb_set_block(hdev, mmTPC3_WR_REGULATOR_BASE);
 
+	pb_addr = (mmTPC3_CFG_SEMAPHORE & ~0xFFF) + PROT_BITS_OFFS;
+	word_offset = ((mmTPC3_CFG_SEMAPHORE & PROT_BITS_OFFS) >> 7) << 2;
+
+	mask = 1 << ((mmTPC3_CFG_SEMAPHORE & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC3_CFG_VFLAGS & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC3_CFG_SFLAGS & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC3_CFG_STATUS & 0x7F) >> 2);
+
+	WREG32(pb_addr + word_offset, ~mask);
+
 	pb_addr = (mmTPC3_CFG_CFG_BASE_ADDRESS_HIGH & ~0xFFF) + PROT_BITS_OFFS;
 	word_offset = ((mmTPC3_CFG_CFG_BASE_ADDRESS_HIGH
 			& PROT_BITS_OFFS) >> 7) << 2;
@@ -1246,6 +1283,10 @@
 	mask |= 1 << ((mmTPC3_CFG_CFG_SUBTRACT_VALUE & 0x7F) >> 2);
 	mask |= 1 << ((mmTPC3_CFG_SM_BASE_ADDRESS_LOW & 0x7F) >> 2);
 	mask |= 1 << ((mmTPC3_CFG_SM_BASE_ADDRESS_HIGH & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC3_CFG_TPC_STALL & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC3_CFG_MSS_CONFIG & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC3_CFG_TPC_INTR_CAUSE & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC3_CFG_TPC_INTR_MASK & 0x7F) >> 2);
 
 	WREG32(pb_addr + word_offset, ~mask);
 
@@ -1421,6 +1462,16 @@
 	goya_pb_set_block(hdev, mmTPC4_RD_REGULATOR_BASE);
 	goya_pb_set_block(hdev, mmTPC4_WR_REGULATOR_BASE);
 
+	pb_addr = (mmTPC4_CFG_SEMAPHORE & ~0xFFF) + PROT_BITS_OFFS;
+	word_offset = ((mmTPC4_CFG_SEMAPHORE & PROT_BITS_OFFS) >> 7) << 2;
+
+	mask = 1 << ((mmTPC4_CFG_SEMAPHORE & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC4_CFG_VFLAGS & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC4_CFG_SFLAGS & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC4_CFG_STATUS & 0x7F) >> 2);
+
+	WREG32(pb_addr + word_offset, ~mask);
+
 	pb_addr = (mmTPC4_CFG_CFG_BASE_ADDRESS_HIGH & ~0xFFF) + PROT_BITS_OFFS;
 	word_offset = ((mmTPC4_CFG_CFG_BASE_ADDRESS_HIGH &
 			PROT_BITS_OFFS) >> 7) << 2;
@@ -1428,6 +1479,10 @@
 	mask |= 1 << ((mmTPC4_CFG_CFG_SUBTRACT_VALUE & 0x7F) >> 2);
 	mask |= 1 << ((mmTPC4_CFG_SM_BASE_ADDRESS_LOW & 0x7F) >> 2);
 	mask |= 1 << ((mmTPC4_CFG_SM_BASE_ADDRESS_HIGH & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC4_CFG_TPC_STALL & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC4_CFG_MSS_CONFIG & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC4_CFG_TPC_INTR_CAUSE & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC4_CFG_TPC_INTR_MASK & 0x7F) >> 2);
 
 	WREG32(pb_addr + word_offset, ~mask);
 
@@ -1603,6 +1658,16 @@
 	goya_pb_set_block(hdev, mmTPC5_RD_REGULATOR_BASE);
 	goya_pb_set_block(hdev, mmTPC5_WR_REGULATOR_BASE);
 
+	pb_addr = (mmTPC5_CFG_SEMAPHORE & ~0xFFF) + PROT_BITS_OFFS;
+	word_offset = ((mmTPC5_CFG_SEMAPHORE & PROT_BITS_OFFS) >> 7) << 2;
+
+	mask = 1 << ((mmTPC5_CFG_SEMAPHORE & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC5_CFG_VFLAGS & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC5_CFG_SFLAGS & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC5_CFG_STATUS & 0x7F) >> 2);
+
+	WREG32(pb_addr + word_offset, ~mask);
+
 	pb_addr = (mmTPC5_CFG_CFG_BASE_ADDRESS_HIGH & ~0xFFF) + PROT_BITS_OFFS;
 	word_offset = ((mmTPC5_CFG_CFG_BASE_ADDRESS_HIGH &
 			PROT_BITS_OFFS) >> 7) << 2;
@@ -1610,6 +1675,10 @@
 	mask |= 1 << ((mmTPC5_CFG_CFG_SUBTRACT_VALUE & 0x7F) >> 2);
 	mask |= 1 << ((mmTPC5_CFG_SM_BASE_ADDRESS_LOW & 0x7F) >> 2);
 	mask |= 1 << ((mmTPC5_CFG_SM_BASE_ADDRESS_HIGH & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC5_CFG_TPC_STALL & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC5_CFG_MSS_CONFIG & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC5_CFG_TPC_INTR_CAUSE & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC5_CFG_TPC_INTR_MASK & 0x7F) >> 2);
 
 	WREG32(pb_addr + word_offset, ~mask);
 
@@ -1785,6 +1854,16 @@
 	goya_pb_set_block(hdev, mmTPC6_RD_REGULATOR_BASE);
 	goya_pb_set_block(hdev, mmTPC6_WR_REGULATOR_BASE);
 
+	pb_addr = (mmTPC6_CFG_SEMAPHORE & ~0xFFF) + PROT_BITS_OFFS;
+	word_offset = ((mmTPC6_CFG_SEMAPHORE & PROT_BITS_OFFS) >> 7) << 2;
+
+	mask = 1 << ((mmTPC6_CFG_SEMAPHORE & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC6_CFG_VFLAGS & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC6_CFG_SFLAGS & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC6_CFG_STATUS & 0x7F) >> 2);
+
+	WREG32(pb_addr + word_offset, ~mask);
+
 	pb_addr = (mmTPC6_CFG_CFG_BASE_ADDRESS_HIGH & ~0xFFF) + PROT_BITS_OFFS;
 	word_offset = ((mmTPC6_CFG_CFG_BASE_ADDRESS_HIGH &
 			PROT_BITS_OFFS) >> 7) << 2;
@@ -1792,6 +1871,10 @@
 	mask |= 1 << ((mmTPC6_CFG_CFG_SUBTRACT_VALUE & 0x7F) >> 2);
 	mask |= 1 << ((mmTPC6_CFG_SM_BASE_ADDRESS_LOW & 0x7F) >> 2);
 	mask |= 1 << ((mmTPC6_CFG_SM_BASE_ADDRESS_HIGH & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC6_CFG_TPC_STALL & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC6_CFG_MSS_CONFIG & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC6_CFG_TPC_INTR_CAUSE & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC6_CFG_TPC_INTR_MASK & 0x7F) >> 2);
 
 	WREG32(pb_addr + word_offset, ~mask);
 
@@ -1967,6 +2050,16 @@
 	goya_pb_set_block(hdev, mmTPC7_RD_REGULATOR_BASE);
 	goya_pb_set_block(hdev, mmTPC7_WR_REGULATOR_BASE);
 
+	pb_addr = (mmTPC7_CFG_SEMAPHORE & ~0xFFF) + PROT_BITS_OFFS;
+	word_offset = ((mmTPC7_CFG_SEMAPHORE & PROT_BITS_OFFS) >> 7) << 2;
+
+	mask = 1 << ((mmTPC7_CFG_SEMAPHORE & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC7_CFG_VFLAGS & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC7_CFG_SFLAGS & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC7_CFG_STATUS & 0x7F) >> 2);
+
+	WREG32(pb_addr + word_offset, ~mask);
+
 	pb_addr = (mmTPC7_CFG_CFG_BASE_ADDRESS_HIGH & ~0xFFF) +	PROT_BITS_OFFS;
 	word_offset = ((mmTPC7_CFG_CFG_BASE_ADDRESS_HIGH &
 			PROT_BITS_OFFS) >> 7) << 2;
@@ -1974,6 +2067,10 @@
 	mask |= 1 << ((mmTPC7_CFG_CFG_SUBTRACT_VALUE & 0x7F) >> 2);
 	mask |= 1 << ((mmTPC7_CFG_SM_BASE_ADDRESS_LOW & 0x7F) >> 2);
 	mask |= 1 << ((mmTPC7_CFG_SM_BASE_ADDRESS_HIGH & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC7_CFG_TPC_STALL & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC7_CFG_MSS_CONFIG & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC7_CFG_TPC_INTR_CAUSE & 0x7F) >> 2);
+	mask |= 1 << ((mmTPC7_CFG_TPC_INTR_MASK & 0x7F) >> 2);
 
 	WREG32(pb_addr + word_offset, ~mask);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/habanalabs/habanalabs.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/habanalabs/habanalabs.h
@@ -23,7 +23,7 @@
 
 #define HL_MMAP_CB_MASK			(0x8000000000000000ull >> PAGE_SHIFT)
 
-#define HL_PENDING_RESET_PER_SEC	5
+#define HL_PENDING_RESET_PER_SEC	30
 
 #define HL_DEVICE_TIMEOUT_USEC		1000000 /* 1 s */
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/habanalabs/habanalabs_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/habanalabs/habanalabs_drv.c
@@ -443,6 +443,7 @@
 	.id_table = ids,
 	.probe = hl_pci_probe,
 	.remove = hl_pci_remove,
+	.shutdown = hl_pci_remove,
 	.driver.pm = &hl_pm_ops,
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/habanalabs/memory.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/habanalabs/memory.c
@@ -67,6 +67,11 @@
 	num_pgs = (args->alloc.mem_size + (page_size - 1)) >> page_shift;
 	total_size = num_pgs << page_shift;
 
+	if (!total_size) {
+		dev_err(hdev->dev, "Cannot allocate 0 bytes\n");
+		return -EINVAL;
+	}
+
 	contiguous = args->flags & HL_MEM_CONTIGUOUS;
 
 	if (contiguous) {
@@ -94,7 +99,7 @@
 	phys_pg_pack->contiguous = contiguous;
 
 	phys_pg_pack->pages = kvmalloc_array(num_pgs, sizeof(u64), GFP_KERNEL);
-	if (!phys_pg_pack->pages) {
+	if (ZERO_OR_NULL_PTR(phys_pg_pack->pages)) {
 		rc = -ENOMEM;
 		goto pages_arr_err;
 	}
@@ -689,7 +694,7 @@
 
 	phys_pg_pack->pages = kvmalloc_array(total_npages, sizeof(u64),
 						GFP_KERNEL);
-	if (!phys_pg_pack->pages) {
+	if (ZERO_OR_NULL_PTR(phys_pg_pack->pages)) {
 		rc = -ENOMEM;
 		goto page_pack_arr_mem_err;
 	}
@@ -965,17 +970,19 @@
  *
  * @ctx                 : current context
  * @vaddr               : device virtual address to unmap
+ * @ctx_free            : true if in context free flow, false otherwise.
  *
  * This function does the following:
  * - Unmap the physical pages related to the given virtual address
  * - return the device virtual block to the virtual block list
  */
-static int unmap_device_va(struct hl_ctx *ctx, u64 vaddr)
+static int unmap_device_va(struct hl_ctx *ctx, u64 vaddr, bool ctx_free)
 {
 	struct hl_device *hdev = ctx->hdev;
 	struct hl_vm_phys_pg_pack *phys_pg_pack = NULL;
 	struct hl_vm_hash_node *hnode = NULL;
 	struct hl_userptr *userptr = NULL;
+	struct hl_va_range *va_range;
 	enum vm_type_t *vm_type;
 	u64 next_vaddr, i;
 	u32 page_size;
@@ -1003,6 +1010,7 @@
 
 	if (*vm_type == VM_TYPE_USERPTR) {
 		is_userptr = true;
+		va_range = &ctx->host_va_range;
 		userptr = hnode->ptr;
 		rc = init_phys_pg_pack_from_userptr(ctx, userptr,
 				&phys_pg_pack);
@@ -1014,6 +1022,7 @@
 		}
 	} else if (*vm_type == VM_TYPE_PHYS_PACK) {
 		is_userptr = false;
+		va_range = &ctx->dram_va_range;
 		phys_pg_pack = hnode->ptr;
 	} else {
 		dev_warn(hdev->dev,
@@ -1052,12 +1061,18 @@
 
 	mutex_unlock(&ctx->mmu_lock);
 
-	if (add_va_block(hdev,
-			is_userptr ? &ctx->host_va_range : &ctx->dram_va_range,
-			vaddr,
-			vaddr + phys_pg_pack->total_size - 1))
-		dev_warn(hdev->dev, "add va block failed for vaddr: 0x%llx\n",
-				vaddr);
+	/*
+	 * No point in maintaining the free VA block list if the context is
+	 * closing as the list will be freed anyway
+	 */
+	if (!ctx_free) {
+		rc = add_va_block(hdev, va_range, vaddr,
+					vaddr + phys_pg_pack->total_size - 1);
+		if (rc)
+			dev_warn(hdev->dev,
+					"add va block failed for vaddr: 0x%llx\n",
+					vaddr);
+	}
 
 	atomic_dec(&phys_pg_pack->mapping_cnt);
 	kfree(hnode);
@@ -1189,8 +1204,8 @@
 		break;
 
 	case HL_MEM_OP_UNMAP:
-		rc = unmap_device_va(ctx,
-				args->in.unmap.device_virt_addr);
+		rc = unmap_device_va(ctx, args->in.unmap.device_virt_addr,
+					false);
 		break;
 
 	default:
@@ -1620,7 +1635,7 @@
 		dev_dbg(hdev->dev,
 			"hl_mem_hash_node of vaddr 0x%llx of asid %d is still alive\n",
 			hnode->vaddr, ctx->asid);
-		unmap_device_va(ctx, hnode->vaddr);
+		unmap_device_va(ctx, hnode->vaddr, true);
 	}
 
 	spin_lock(&vm->idr_lock);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/habanalabs/mmu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/habanalabs/mmu.c
@@ -422,7 +422,7 @@
 	hdev->mmu_shadow_hop0 = kvmalloc_array(prop->max_asid,
 					prop->mmu_hop_table_size,
 					GFP_KERNEL | __GFP_ZERO);
-	if (!hdev->mmu_shadow_hop0) {
+	if (ZERO_OR_NULL_PTR(hdev->mmu_shadow_hop0)) {
 		rc = -ENOMEM;
 		goto err_pool_add;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/ibmasm/module.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/ibmasm/module.c
@@ -111,7 +111,7 @@
 	result = ibmasm_init_remote_input_dev(sp);
 	if (result) {
 		dev_err(sp->dev, "Failed to initialize remote queue\n");
-		goto error_send_message;
+		goto error_init_remote;
 	}
 
 	result = ibmasm_send_driver_vpd(sp);
@@ -131,8 +131,9 @@
 	return 0;
 
 error_send_message:
-	disable_sp_interrupts(sp->base_address);
 	ibmasm_free_remote_input_dev(sp);
+error_init_remote:
+	disable_sp_interrupts(sp->base_address);
 	free_irq(sp->irq, (void *)sp);
 error_request_irq:
 	iounmap(sp->base_address);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/ics932s401.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/ics932s401.c
@@ -134,7 +134,7 @@
 	for (i = 0; i < NUM_MIRRORED_REGS; i++) {
 		temp = i2c_smbus_read_word_data(client, regs_to_copy[i]);
 		if (temp < 0)
-			data->regs[regs_to_copy[i]] = 0;
+			temp = 0;
 		data->regs[regs_to_copy[i]] = temp >> 8;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/jesd204b/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/jesd204b/Kconfig
@@ -0,0 +1,28 @@
+#
+# Jesd204b support
+#
+
+config XILINX_JESD204B
+	tristate "Xilinx JESD204B"
+	help
+	  This option enables support for the Xilinx JESD204B driver.
+	  It is designed to allow user to access JESD204B IP registers
+	  with sysfs entries. JESD204B is the protocol used by High-Speed
+	  data converters to transfer data to FPGA/ASIC.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called jesd204b.
+
+config XILINX_JESD204B_PHY
+	tristate "JESD Phy Driver"
+	depends on XILINX_JESD204B
+	help
+	  This is JESD204b Phy Interface. It enables support for xilinx jesd204b phy
+	  controller.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called jesd204b_phy.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/jesd204b/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/jesd204b/Makefile
@@ -0,0 +1,5 @@
+obj-$(CONFIG_XILINX_JESD204B_PHY) += jesd204b_phy.o
+jesd204b_phy-y += jesd_phy.o gtx7s_cpll_bands.o \
+		gtx7s_qpll_bands.o
+obj-$(CONFIG_XILINX_JESD204B) += jesd204b.o
+jesd204b-y += xilinx_jesd204b.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/jesd204b/gtx7s_cpll_bands.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/jesd204b/gtx7s_cpll_bands.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2014 - 2015 Xilinx, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/types.h>
+#include "s7_gtxe2_drp.h"
+#include "gtx7s_cpll_bands.h"
+
+static const u32 gtx7s_cpll_channel_address_lut
+			[GTX7S_CPLL_NUM_CHANNEL_DRP_REGS] = {
+	RXCDR_CFG0_ADDR,
+	RXCDR_CFG1_ADDR,
+	RXCDR_CFG2_ADDR,
+	RXCDR_CFG3_ADDR,
+	RXCDR_CFG4_ADDR,
+	RXOUT_DIV_ADDR,
+	TXOUT_DIV_ADDR,
+	RX_DFE_LPM_CFG_ADDR
+};
+
+static const u32 gtx7s_cpll_channel_offset_lut
+			[GTX7S_CPLL_NUM_CHANNEL_DRP_REGS] = {
+	RXCDR_CFG0_OFFSET,
+	RXCDR_CFG1_OFFSET,
+	RXCDR_CFG2_OFFSET,
+	RXCDR_CFG3_OFFSET,
+	RXCDR_CFG4_OFFSET,
+	RXOUT_DIV_OFFSET,
+	TXOUT_DIV_OFFSET,
+	RX_DFE_LPM_CFG_OFFSET
+};
+
+static const u32 gtx7s_cpll_channel_mask_lut
+			[GTX7S_CPLL_NUM_CHANNEL_DRP_REGS] = {
+	RXCDR_CFG0_MASK,
+	RXCDR_CFG1_MASK,
+	RXCDR_CFG2_MASK,
+	RXCDR_CFG3_MASK,
+	RXCDR_CFG4_MASK,
+	RXOUT_DIV_MASK,
+	TXOUT_DIV_MASK,
+	RX_DFE_LPM_CFG_MASK
+};
+
+/* Note bands run vertically from 1 to 4 */
+static const u16 gtx7s_cpll_channel_param_lut[GTX7S_CPLL_NUM_CHANNEL_DRP_REGS]
+			[GTX7S_CPLL_NUM_LINE_RATE_BANDS] = {
+	{0x20,	 0x20,		0x20,	0x20	},/*	 RXCDR_CFG0 */
+	{0x1010, 0x1020,	0x1040,	0x1040	},/*	 RXCDR_CFG1 */
+	{0x23ff, 0x23ff,	0x23ff,	0x23ff	},/*	 RXCDR_CFG2 */
+	{0x0,	 0x0,		0x0,	0x0	},/*	 RXCDR_CFG3 */
+	{0x3,	0x3,		0x3,	0x3	},/*	 RXCDR_CFG4 */
+	{0x3,	0x2,		0x1,	0x1	},/*	 RXOUT_DIV  */
+	{0x3,	0x2,		0x1,	0x1	},/*	TXOUT_DIV   */
+	{0x904,	0x904,		0x904,	0x104	} /*	RX_DFE_LPM_CFG */
+};
+
+u32 get_gtx7s_cpll_address_lut(u32 lut_address)
+{
+	return gtx7s_cpll_channel_address_lut[lut_address];
+}
+
+u32 get_gtx7s_cpll_offset_lut(u32 lut_address)
+{
+	return gtx7s_cpll_channel_offset_lut[lut_address];
+}
+
+u32 get_gtx7s_cpll_mask_lut(u32 lut_address)
+{
+	return gtx7s_cpll_channel_mask_lut[lut_address];
+}
+
+u16 get_gtx7s_cpll_param_lut(u32 param_address, u32 band_address)
+{
+	return gtx7s_cpll_channel_param_lut[param_address][band_address];
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/jesd204b/gtx7s_cpll_bands.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/jesd204b/gtx7s_cpll_bands.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2014 - 2015 Xilinx, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/types.h>
+
+#ifndef GTX7S_CPLL_BANDS_H_
+#define GTX7S_CPLL_BANDS_H_
+
+#define GTX7S_CPLL_NUM_CHANNEL_DRP_REGS 8
+#define GTX7S_CPLL_NUM_LINE_RATE_BANDS 4
+
+u32 get_gtx7s_cpll_address_lut(u32);
+u32 get_gtx7s_cpll_offset_lut(u32);
+u32 get_gtx7s_cpll_mask_lut(u32);
+u16 get_gtx7s_cpll_param_lut(u32, u32);
+
+#endif /* GTX7S_CPLL_BANDS_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/jesd204b/gtx7s_qpll_bands.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/jesd204b/gtx7s_qpll_bands.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2014 - 2015 Xilinx, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/types.h>
+#include "s7_gtxe2_drp.h"
+#include "gtx7s_qpll_bands.h"
+
+static const u32 gtx7s_qpll_channel_address_lut
+			[GTX7S_QPLL_NUM_CHANNEL_DRP_REGS] = {
+	RXCDR_CFG0_ADDR,
+	RXCDR_CFG1_ADDR,
+	RXCDR_CFG2_ADDR,
+	RXCDR_CFG3_ADDR,
+	RXCDR_CFG4_ADDR,
+	RXOUT_DIV_ADDR,
+	TXOUT_DIV_ADDR,
+	RX_DFE_LPM_CFG_ADDR,
+	QPLL_CFG0_ADDR,
+	QPLL_CFG1_ADDR
+};
+
+static const u32 gtx7s_qpll_channel_offset_lut
+			[GTX7S_QPLL_NUM_CHANNEL_DRP_REGS] = {
+	RXCDR_CFG0_OFFSET,
+	RXCDR_CFG1_OFFSET,
+	RXCDR_CFG2_OFFSET,
+	RXCDR_CFG3_OFFSET,
+	RXCDR_CFG4_OFFSET,
+	RXOUT_DIV_OFFSET,
+	TXOUT_DIV_OFFSET,
+	RX_DFE_LPM_CFG_OFFSET,
+	QPLL_CFG0_OFFSET,
+	QPLL_CFG1_OFFSET
+};
+
+static const u32 gtx7s_qpll_channel_mask_lut
+			[GTX7S_QPLL_NUM_CHANNEL_DRP_REGS] = {
+	RXCDR_CFG0_MASK,
+	RXCDR_CFG1_MASK,
+	RXCDR_CFG2_MASK,
+	RXCDR_CFG3_MASK,
+	RXCDR_CFG4_MASK,
+	RXOUT_DIV_MASK,
+	TXOUT_DIV_MASK,
+	RX_DFE_LPM_CFG_MASK,
+	QPLL_CFG0_MASK,
+	QPLL_CFG1_MASK
+};
+
+/* Note bands run vertically from 1 to 10 */
+static const u16 gtx7s_qpll_channel_param_lut[GTX7S_QPLL_NUM_CHANNEL_DRP_REGS]
+			[GTX7S_QPLL_NUM_LINE_RATE_BANDS] = {
+{0x20,     0x20,   0x20,   0x20,     0x20,    0x20,    0x20,    0x20,    0x20,    0x20},/* RXCDR_CFG0 */
+{0x1008,   0x1010, 0x1020, 0x1010,   0x1020,  0x1040,  0x1020,  0x1040,  0x1040,  0x1040},/* RXCDR_CFG1 */
+{0x23ff,   0x23ff, 0x23ff, 0x23ff,   0x23ff,  0x23ff,  0x23ff,  0x23ff,  0x23ff,  0x23ff},/* RXCDR_CFG2 */
+{0x0,      0x0,    0x0,    0x0,      0x0,     0x0,     0x0,     0x0,     0x0,     0x0}, /* RXCDR_CFG3 */
+{0x3,      0x3,    0x3,    0x3,      0x3,     0x3,     0x3,     0x3,     0x3,     0x3},/* RXCDR_CFG4 */
+{0x3e8,    0x4,    0x2,    0x3,      0x2,     0x1,     0x2,     0x1,     0x1,     0x1},/* RXOUT_DIV  */
+{0x3e8,    0x4,    0x2,    0x3,      0x2,     0x1,     0x2,     0x1,     0x1,     0x1},/* TXOUT_DIV  */
+{0x904,    0x904,  0x904,  0x904,    0x904,   0x904,   0x904,   0x904,   0x104,   0x104},/* RX_DFE_LPM_CFG */
+{0x1c1,    0x1c1,  0x1c1,  0x181,    0x1c1,   0x1c1,   0x181,   0x1c1,   0x1c1,   0x181},/* QPLL_CFG0 */
+{0x68,     0x68,   0x68,   0x68,     0x68,    0x68,    0x68,    0x68,    0x68,    0x68} /* QPLL_CFG1 */
+};
+
+u32 get_gtx7s_qpll_address_lut(u32 lut_address)
+{
+	return gtx7s_qpll_channel_address_lut[lut_address];
+}
+
+u32 get_gtx7s_qpll_offset_lut(u32 lut_address)
+{
+	return gtx7s_qpll_channel_offset_lut[lut_address];
+}
+
+u32 get_gtx7s_qpll_mask_lut(u32 lut_address)
+{
+	return gtx7s_qpll_channel_mask_lut[lut_address];
+}
+
+u16 get_gtx7s_qpll_param_lut(u32 param_address, u32 band_address)
+{
+	return gtx7s_qpll_channel_param_lut[param_address][band_address];
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/jesd204b/gtx7s_qpll_bands.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/jesd204b/gtx7s_qpll_bands.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2014 - 2015 Xilinx, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/types.h>
+
+#ifndef GTX7S_QPLL_BANDS_H_
+#define GTX7S_QPLL_BANDS_H_
+
+#define GTX7S_QPLL_NUM_CHANNEL_DRP_REGS 10
+#define GTX7S_QPLL_NUM_LINE_RATE_BANDS 10
+
+u32 get_gtx7s_qpll_address_lut(u32);
+u32 get_gtx7s_qpll_offset_lut(u32);
+u32 get_gtx7s_qpll_mask_lut(u32);
+u16 get_gtx7s_qpll_param_lut(u32, u32);
+
+#endif /* GTX7S_QPLL_BANDS_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/jesd204b/jesd_phy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/jesd204b/jesd_phy.c
@@ -0,0 +1,384 @@
+/*
+ * Jesd204b phy support
+ *
+ * Copyright (C) 2014 - 2015 Xilinx, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include "jesd_phy.h"
+#include "gtx7s_cpll_bands.h"
+#include "gtx7s_qpll_bands.h"
+
+#define PLATFORM_JESD204_PHY_ADDR 0x41E10000
+#define JESD_PHY_LOOP_OFF	0
+#define JESD_PHY_LOOP_PCS	1
+#define JESD_PHY_LOOP_PMA	2
+#define JESD_PHY_LOOP_MAX	2
+
+static inline void jesd204b_phy_write(struct jesd204b_phy_state *st,
+				      unsigned reg, unsigned val)
+{
+	iowrite32(val, st->phy + reg);
+}
+
+static inline unsigned int jesd204b_phy_read(struct jesd204b_phy_state *st,
+					     unsigned reg)
+{
+	return ioread32(st->phy + reg);
+}
+
+#define NUM_GT_CHANNELS	8
+
+#define QPLL	0x3 /* QPLL (7 series) QPLL1 (UltraScale) */
+#define QPLL0	0x2 /* (UltraScale Only) */
+#define CPLL	0x0
+
+#define DRPREAD  BIT(30)
+#define DRPWRITE BIT(31)
+
+#define NR_COMMON_DRP_INTERFACES 0x008
+#define NR_TRANS_DRP_INTERFACES 0x00C
+
+#define CHANNEL_DRP_BASE	0x200
+#define CHANNEL_DRP_ADDR	0x204
+#define CHANNEL_DRP_DREAD	0x20C
+#define CHANNEL_DRP_DWRITE	0x208
+#define CHANNEL_DRP_STAT	0x214
+
+#define CHANNEL_XCVR_SEL	0x400
+#define CHANNEL_XCVR_TXPLL	0x40C
+#define CHANNEL_XCVR_RXPLL	0x410
+#define CHANNEL_XCVR_LOOPB	0x41C
+
+static u32 read_channel_drp_reg(struct jesd204b_phy_state *st, u32 addr)
+{
+	u32 temp;
+
+	jesd204b_phy_write(st, CHANNEL_DRP_ADDR, (DRPREAD | addr));
+	temp = jesd204b_phy_read(st, CHANNEL_DRP_DREAD);
+	return temp;
+}
+
+static void write_channel_drp_reg(struct jesd204b_phy_state *st, u32 addr,
+				  u32 data)
+{
+	u32 loop = 10;
+
+	jesd204b_phy_write(st, CHANNEL_DRP_DWRITE, data);
+	jesd204b_phy_write(st, CHANNEL_DRP_ADDR, (DRPWRITE | addr));
+
+	do {
+		if (!jesd204b_phy_read(st, CHANNEL_DRP_STAT))
+			break;
+		msleep(1);
+	} while (loop--);
+
+	if (!loop)
+		dev_err(st->dev, "DRP wait timeout\n");
+}
+
+static void read_plls(struct jesd204b_phy_state *st)
+{
+	int i;
+	int pll = st->pll;
+	u32 no_of_common_drp_interfaces = 1;
+
+	if (st->pll == CPLL)
+		no_of_common_drp_interfaces = jesd204b_phy_read(
+						st, NR_TRANS_DRP_INTERFACES);
+	else
+		no_of_common_drp_interfaces = jesd204b_phy_read(
+						st, NR_COMMON_DRP_INTERFACES);
+
+	for (i = 0; i < no_of_common_drp_interfaces; i++) {
+		jesd204b_phy_write(st, CHANNEL_XCVR_SEL, i);
+		pll = jesd204b_phy_read(st, CHANNEL_XCVR_TXPLL);
+		pll = jesd204b_phy_read(st, CHANNEL_XCVR_RXPLL);
+	}
+}
+
+static void configure_plls(struct jesd204b_phy_state *st, u32 pll)
+{
+	int i;
+	u32 no_of_common_drp_interfaces;
+
+	if (pll == CPLL)
+		no_of_common_drp_interfaces = jesd204b_phy_read(
+						st, NR_TRANS_DRP_INTERFACES);
+	else
+		no_of_common_drp_interfaces = jesd204b_phy_read(
+						st, NR_COMMON_DRP_INTERFACES);
+
+	for (i = 0; i < no_of_common_drp_interfaces; i++) {
+		jesd204b_phy_write(st, CHANNEL_XCVR_SEL, i);
+		jesd204b_phy_write(st, CHANNEL_XCVR_TXPLL, pll);
+		jesd204b_phy_write(st, CHANNEL_XCVR_RXPLL, pll);
+	}
+}
+
+static void configure_channel_drp(struct jesd204b_phy_state *st, u32 setting)
+{
+	u32 i, j, addr, temp, no_of_common_drp_interfaces;
+	u32 no_channel_drp_reg = GTX7S_QPLL_NUM_CHANNEL_DRP_REGS;
+
+	no_of_common_drp_interfaces = jesd204b_phy_read(
+					st, NR_TRANS_DRP_INTERFACES);
+
+	if (st->pll == CPLL)
+		no_channel_drp_reg = GTX7S_CPLL_NUM_CHANNEL_DRP_REGS;
+	for (i = 0; i < no_of_common_drp_interfaces; i++) {
+		jesd204b_phy_write(st, CHANNEL_DRP_BASE, i);
+		for (j = 0; j < no_channel_drp_reg; j++) {
+			/* Get the register address */
+			if (st->pll == QPLL) {
+				addr = get_gtx7s_qpll_address_lut(j);
+
+				/* Read the register */
+				temp = read_channel_drp_reg(st, addr);
+
+				temp &= (0xFFFF ^ (get_gtx7s_qpll_mask_lut(j)));
+				temp |= ((get_gtx7s_qpll_param_lut(j, setting)
+						<< get_gtx7s_qpll_offset_lut(j))
+						& get_gtx7s_qpll_mask_lut(j));
+			} else {
+				addr = get_gtx7s_cpll_address_lut(j);
+
+				temp = read_channel_drp_reg(st, addr);
+
+				temp &= (0xFFFF ^ (get_gtx7s_cpll_mask_lut(j)));
+				temp |= ((get_gtx7s_cpll_param_lut(j, setting)
+						<< get_gtx7s_cpll_offset_lut(j))
+						& get_gtx7s_cpll_mask_lut(j));
+			}
+			write_channel_drp_reg(st, addr, temp);
+		}
+	}
+}
+
+void jesd204_phy_set_speed(struct jesd204b_phy_state *st, u32 band)
+{
+	/* make sure we have the correct PLL's selected. */
+	configure_channel_drp(st, band);
+}
+
+static void jesd204_phy_init(struct jesd204b_phy_state *st, int line_rate)
+{
+	jesd204_phy_set_speed(st, line_rate);
+}
+
+int jesd204_phy_set_loop(struct jesd204b_phy_state *st, u32 loopval)
+{
+	int i;
+	u32 no_of_channels;
+
+	no_of_channels = jesd204b_phy_read(st, NR_COMMON_DRP_INTERFACES);
+
+	if (loopval > JESD_PHY_LOOP_MAX)
+		return -EINVAL;
+
+	for (i = 0; i < no_of_channels ; i++) {
+		jesd204b_phy_write(st, CHANNEL_XCVR_SEL, i);
+		jesd204b_phy_write(st, CHANNEL_XCVR_LOOPB, loopval);
+	}
+	return 0;
+}
+
+static ssize_t jesd204b_pll_read(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	struct jesd204b_phy_state *st = dev_get_drvdata(dev);
+
+	read_plls(st);
+	if (st->pll == CPLL)
+		return sprintf(buf, "cpll\n");
+	return sprintf(buf, "qpll\n");
+}
+
+static ssize_t jesd204b_configure_pll(struct device *dev,
+				      struct device_attribute *attr,
+				      const char *buf, size_t count)
+{
+	struct jesd204b_phy_state *st = dev_get_drvdata(dev);
+	unsigned val;
+	int ret;
+
+	ret = kstrtouint(buf, 0, &val);
+	if (!ret)
+		return 0;
+
+	if (val > QPLL) {
+		dev_err(dev, "Setting the pll to %d valid values\n"
+			      "00 = CPLL\n"
+			      "10 = QPLL0 (UltraScale Only)\n"
+			      "11 = QPLL (7 series) QPLL1 (UltraScale)\n", val);
+		return 0;
+	}
+	st->pll = val;
+	configure_plls(st, val);
+
+	return count;
+}
+
+static DEVICE_ATTR(configure_pll, S_IWUSR | S_IRUSR, jesd204b_pll_read,
+			jesd204b_configure_pll);
+
+static ssize_t jesd204b_linerate_read(struct device *dev,
+				      struct device_attribute *attr,
+				      char *buf)
+{
+	struct jesd204b_phy_state *st = dev_get_drvdata(dev);
+
+	return sprintf(buf, "0x%X\n", st->band);
+}
+
+static ssize_t jesd204b_linerate_write(struct device *dev,
+				       struct device_attribute *attr,
+				       const char *buf, size_t count)
+{
+	struct jesd204b_phy_state *st = dev_get_drvdata(dev);
+	int ret;
+	/* Low frequencies are not supported by qpll */
+
+	ret = kstrtouint(buf, 0, &st->band);
+	if (ret)
+		return ret;
+
+	dev_info(dev, "Setting the line rate to band to %d\n", st->band);
+	/* QPLL - freq options in phy
+	 * 62.5
+	 * 78.125
+	 * 94.697
+	 * 97.656
+	 * 125.000
+	 * 156.25
+	 * 187.5
+	 * 189.394
+	 * 195.313
+	 * 234.375
+	 * 250.000
+	 * 284.091
+	 * 292.969
+	 */
+	if (st->band == 2)
+		clk_set_rate(st->clk,  62500000); /* 2.5G */
+	else if (st->band == 4)
+		clk_set_rate(st->clk,  97656000); /* 3.9G */
+	else if (st->band == 6)
+		clk_set_rate(st->clk, 125000000); /* 5G */
+	else if (st->band == 7)
+		clk_set_rate(st->clk, 156250000); /* 6.25G */
+	else if (st->band == 8)
+		clk_set_rate(st->clk, 195313000); /* 7.812G */
+	else if (st->band == 9)
+		clk_set_rate(st->clk, 250000000);/* 10G */
+
+	jesd204_phy_init(st, st->band);
+
+	return count;
+}
+
+static DEVICE_ATTR(line_rate_band, S_IWUSR | S_IRUSR, jesd204b_linerate_read,
+		   jesd204b_linerate_write);
+
+/* Match table for of_platform binding */
+static const struct of_device_id jesd204b_phy_of_match[] = {
+	{ .compatible = "xlnx,jesd204-phy-2.0", },
+	{ /* end of list */ },
+};
+
+static int jesd204b_phy_probe(struct platform_device *pdev)
+{
+	struct jesd204b_phy_state *st;
+	struct resource *mem; /* IO mem resources */
+	int ret;
+	u32 ref_clk;
+
+	st = devm_kzalloc(&pdev->dev, sizeof(*st), GFP_KERNEL);
+	if (!st)
+		return -ENOMEM;
+
+	st->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(st->clk))
+		return -EPROBE_DEFER;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	st->phy = devm_ioremap_resource(&pdev->dev, mem);
+	if (IS_ERR(st->phy)) {
+		dev_err(&pdev->dev, "Failed ioremap\n");
+		return PTR_ERR(st->phy);
+	}
+	st->dev = &pdev->dev;
+	platform_set_drvdata(pdev, st);
+
+	ret = of_property_read_u32(pdev->dev.of_node, "xlnx,lanes",
+				   &st->lanes);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to read required dt property\n");
+		return ret;
+	}
+	ret = of_property_read_u32(pdev->dev.of_node, "xlnx,pll-selection",
+				   &st->pll);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to read required dt property\n");
+		return ret;
+	}
+	ret = of_property_read_u32(pdev->dev.of_node, "xlnx,gt-refclk-freq",
+				   &ref_clk);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to read required dt property\n");
+		return ret;
+	}
+
+	clk_set_rate(st->clk, (unsigned long)ref_clk);
+	device_create_file(&pdev->dev, &dev_attr_configure_pll);
+	device_create_file(&pdev->dev, &dev_attr_line_rate_band);
+
+	ret = clk_prepare_enable(st->clk);
+	if (ret) {
+		dev_err(&pdev->dev, "Unable to enable clock.\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int jesd204b_phy_remove(struct platform_device *pdev)
+{
+	struct jesd204b_phy_state *st = platform_get_drvdata(pdev);
+
+	clk_disable_unprepare(st->clk);
+	clk_put(st->clk);
+	device_remove_file(&pdev->dev, &dev_attr_configure_pll);
+	device_remove_file(&pdev->dev, &dev_attr_line_rate_band);
+	return 0;
+}
+
+static struct platform_driver jesd204b_driver = {
+	.driver = {
+		.name = "jesd204b_phy",
+		.of_match_table = jesd204b_phy_of_match,
+	},
+	.probe		= jesd204b_phy_probe,
+	.remove		= jesd204b_phy_remove,
+};
+
+module_platform_driver(jesd204b_driver);
+
+MODULE_AUTHOR("Shubhrajyoti Datta <shubhraj@xilinx.com>");
+MODULE_DESCRIPTION("AXI-JESD204B Phy Interface Module");
+MODULE_LICENSE("GPL");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/jesd204b/jesd_phy.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/jesd204b/jesd_phy.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2014 - 2015 Xilinx, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef JESD_PHY_H_
+#define JESD_PHY_H_
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+struct jesd204b_phy_state {
+	struct device	*dev;
+	void __iomem	*phy;
+	struct clk	*clk;
+	u32		vers_id;
+	u32		addr;
+	u32		lanes;
+	u32		band;
+	u32		pll;
+	unsigned long	rate;
+};
+
+int jesd204_phy_set_loop(struct jesd204b_phy_state *st, u32 loopval);
+
+#endif /* JESD_PHY_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/jesd204b/s7_gtxe2_drp.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/jesd204b/s7_gtxe2_drp.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2014 - 2015 Xilinx, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#define TXOUT_DIV_ADDR					0x88
+#define TXOUT_DIV_MASK					0x70
+#define TXOUT_DIV_OFFSET				0x4
+#define TXOUT_DIV_WIDTH					0x3
+#define TXOUT_DIV_DEFAULT				0x0
+
+#define RXOUT_DIV_ADDR					0x88
+#define RXOUT_DIV_MASK					0x7
+#define RXOUT_DIV_OFFSET				0x0
+#define RXOUT_DIV_WIDTH					0x3
+#define RXOUT_DIV_DEFAULT				0x0
+
+#define RXCDR_CFG0_ADDR					0xa8
+#define RXCDR_CFG0_MASK					0xffff
+#define RXCDR_CFG0_OFFSET				0x0
+#define RXCDR_CFG0_WIDTH				0x10
+#define RXCDR_CFG0_DEFAULT				0x0
+
+#define RXCDR_CFG1_ADDR					0xa9
+#define RXCDR_CFG1_MASK					0xffff
+#define RXCDR_CFG1_OFFSET				0x0
+#define RXCDR_CFG1_WIDTH				0x10
+#define RXCDR_CFG1_DEFAULT				0x0
+
+#define RXCDR_CFG2_ADDR					0xaa
+#define RXCDR_CFG2_MASK					0xffff
+#define RXCDR_CFG2_OFFSET				0x0
+#define RXCDR_CFG2_WIDTH				0x10
+#define RXCDR_CFG2_DEFAULT				0x0
+
+#define RXCDR_CFG3_ADDR					0xab
+#define RXCDR_CFG3_MASK					0xffff
+#define RXCDR_CFG3_OFFSET				0x0
+#define RXCDR_CFG3_WIDTH				0x10
+#define RXCDR_CFG3_DEFAULT				0x0
+
+#define RXCDR_CFG4_ADDR					0xac
+#define RXCDR_CFG4_MASK					0xff
+#define RXCDR_CFG4_OFFSET				0x0
+#define RXCDR_CFG4_WIDTH				0x8
+#define RXCDR_CFG4_DEFAULT				0x0
+
+#define RX_DFE_LPM_CFG_ADDR				0x29
+#define RX_DFE_LPM_CFG_MASK				0xffff
+#define RX_DFE_LPM_CFG_OFFSET				0x0
+#define RX_DFE_LPM_CFG_WIDTH				0x10
+#define RX_DFE_LPM_CFG_DEFAULT				0x0
+
+#define QPLL_CFG0_ADDR					0x32
+#define QPLL_CFG0_MASK					0xffff
+#define QPLL_CFG0_OFFSET				0x0
+#define QPLL_CFG0_WIDTH					0x10
+#define QPLL_CFG0_DEFAULT				0x0
+
+#define QPLL_CFG1_ADDR					0x33
+#define QPLL_CFG1_MASK					0x7ff
+#define QPLL_CFG1_OFFSET				0x0
+#define QPLL_CFG1_WIDTH					0xb
+#define QPLL_CFG1_DEFAULT				0x0
+
+#define QPLL_REFCLK_DIV_M_ADDR				0x33
+#define QPLL_REFCLK_DIV_M_MASK				0xf800
+#define QPLL_REFCLK_DIV_M_OFFSET			0xb
+#define QPLL_REFCLK_DIV_M_WIDTH				0x5
+#define QPLL_REFCLK_DIV_M_DEFAULT			0x0
+
+#define QPLL_FBDIV_N_ADDR				0x36
+#define QPLL_FBDIV_N_MASK				0x3ff
+#define QPLL_FBDIV_N_OFFSET				0x0
+#define QPLL_FBDIV_N_WIDTH				0xa
+#define QPLL_FBDIV_N_DEFAULT				0x0
+
+#define QPLL_FBDIV_RATIO_ADDR				0x37
+#define QPLL_FBDIV_RATIO_MASK				0x40
+#define QPLL_FBDIV_RATIO_OFFSET				0x6
+#define QPLL_FBDIV_RATIO_WIDTH				0x1
+#define QPLL_FBDIV_RATIO_DEFAULT			0x0
+
+#define CPLL_CFG0_ADDR					0x5c
+#define CPLL_CFG0_MASK					0xff00
+#define CPLL_CFG0_OFFSET				0x8
+#define CPLL_CFG0_WIDTH					0x8
+#define CPLL_CFG0_DEFAULT				0x0
+
+#define CPLL_CFG1_ADDR					0x5d
+#define CPLL_CFG1_MASK					0xffff
+#define CPLL_CFG1_OFFSET				0x0
+#define CPLL_CFG1_WIDTH					0x10
+#define CPLL_CFG1_DEFAULT				0x0
+
+#define CPLL_REFCLK_DIV_M_ADDR				0x5e
+#define CPLL_REFCLK_DIV_M_MASK				0x1f00
+#define CPLL_REFCLK_DIV_M_OFFSET			0x8
+#define CPLL_REFCLK_DIV_M_WIDTH				0x5
+#define CPLL_REFCLK_DIV_M_DEFAULT			0x0
+
+#define CPLL_FB_DIV_45_N1_ADDR				0x5e
+#define CPLL_FB_DIV_45_N1_MASK				0x80
+#define CPLL_FB_DIV_45_N1_OFFSET			0x7
+#define CPLL_FB_DIV_45_N1_WIDTH				0x1
+#define CPLL_FB_DIV_45_N1_DEFAULT			0x0
+
+#define CPLL_FBDIV_N2_ADDR				0x5e
+#define CPLL_FBDIV_N2_MASK				0x7f
+#define CPLL_FBDIV_N2_OFFSET				0x0
+#define CPLL_FBDIV_N2_WIDTH				0x7
+#define CPLL_FBDIV_N2_DEFAULT				0x0
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/jesd204b/xilinx_jesd204b.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/jesd204b/xilinx_jesd204b.c
@@ -0,0 +1,369 @@
+/*
+ * Xilinx AXI-JESD204B Interface Module
+ *
+ * Copyright 2014 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ *
+ * http://wiki.analog.com/resources/fpga/xilinx/
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/wait.h>
+
+#include "xilinx_jesd204b.h"
+
+struct child_clk {
+	struct clk_hw		hw;
+	struct jesd204b_state	*st;
+	unsigned long		rate;
+	bool			enabled;
+};
+
+#define to_clk_priv(_hw) container_of(_hw, struct child_clk, hw)
+
+static inline void jesd204b_write(struct jesd204b_state *st,
+				  unsigned int reg, unsigned int val)
+{
+	iowrite32(val, st->regs + reg);
+}
+
+static inline unsigned int jesd204b_read(struct jesd204b_state *st,
+					 unsigned int reg)
+{
+	return ioread32(st->regs + reg);
+}
+
+static ssize_t jesd204b_laneinfo_read(struct device *dev,
+				      struct device_attribute *attr,
+				      char *buf, unsigned int lane)
+{
+	struct jesd204b_state *st = dev_get_drvdata(dev);
+	int ret;
+	unsigned int val1, val2, val3;
+
+	val1 = jesd204b_read(st, XLNX_JESD204_REG_ID_L(lane));
+	val2 = jesd204b_read(st, XLNX_JESD204_REG_LANE_F(lane));
+	val3 = jesd204b_read(st, XLNX_JESD204_REG_SCR_S_HD_CF(lane));
+	ret = sprintf(buf,
+		      "DID: %d, BID: %d, LID: %d, L: %d, SCR: %d, F: %d\n",
+		      XLNX_JESD204_LANE_DID(val1),
+		      XLNX_JESD204_LANE_BID(val1),
+		      XLNX_JESD204_LANE_LID(val1),
+		      XLNX_JESD204_LANE_L(val1),
+		      XLNX_JESD204_LANE_SCR(val3),
+		      XLNX_JESD204_LANE_F(val2));
+
+	val1 = jesd204b_read(st, XLNX_JESD204_REG_LANE_K(lane));
+	val2 = jesd204b_read(st, XLNX_JESD204_REG_M_N_ND_CS(lane));
+
+	ret += sprintf(buf + ret,
+		       "K: %d, M: %d, N: %d, CS: %d, S: %d, N': %d, HD: %d\n",
+		       XLNX_JESD204_LANE_K(val1),
+		       XLNX_JESD204_LANE_M(val2),
+		       XLNX_JESD204_LANE_N(val2),
+		       XLNX_JESD204_LANE_CS(val2),
+		       XLNX_JESD204_LANE_S(val3),
+		       XLNX_JESD204_LANE_ND(val2),
+		       XLNX_JESD204_LANE_HD(val3));
+
+	val1 = jesd204b_read(st, XLNX_JESD204_REG_FCHK(lane));
+	ret += sprintf(buf + ret, "FCHK: 0x%X, CF: %d\n",
+		       XLNX_JESD204_LANE_FCHK(val1),
+		       XLNX_JESD204_LANE_CF(val3));
+
+	val1 = jesd204b_read(st, XLNX_JESD204_REG_SC2_ADJ_CTRL(lane));
+	val2 = jesd204b_read(st, XLNX_JESD204_REG_LANE_VERSION(lane));
+	ret += sprintf(buf + ret,
+		"ADJCNT: %d, PHYADJ: %d, ADJDIR: %d, JESDV: %d, SUBCLASS: %d\n",
+		       XLNX_JESD204_LANE_ADJ_CNT(val1),
+		       XLNX_JESD204_LANE_PHASE_ADJ_REQ(val1),
+		       XLNX_JESD204_LANE_ADJ_CNT_DIR(val1),
+		       XLNX_JESD204_LANE_JESDV(val2),
+		       XLNX_JESD204_LANE_SUBCLASS(val2));
+
+	ret += sprintf(buf + ret, "MFCNT : 0x%X\n",
+		       jesd204b_read(st, XLNX_JESD204_REG_TM_MFC_CNT(lane)));
+	ret += sprintf(buf + ret, "ILACNT: 0x%X\n",
+		       jesd204b_read(st, XLNX_JESD204_REG_TM_ILA_CNT(lane)));
+	ret += sprintf(buf + ret, "ERRCNT: 0x%X\n",
+		       jesd204b_read(st, XLNX_JESD204_REG_TM_ERR_CNT(lane)));
+	ret += sprintf(buf + ret, "BUFCNT: 0x%X\n",
+		       jesd204b_read(st, XLNX_JESD204_REG_TM_BUF_ADJ(lane)));
+	ret += sprintf(buf + ret, "LECNT: 0x%X\n",
+		       jesd204b_read(st,
+		       XLNX_JESD204_REG_TM_LINK_ERR_CNT(lane)));
+
+	ret += sprintf(buf + ret, "FC: %lu\n", st->rate);
+
+	return ret;
+}
+
+#define JESD_LANE(_x)							    \
+static ssize_t jesd204b_lane##_x##_info_read(struct device *dev,	    \
+					     struct device_attribute *attr, \
+					     char *buf)			    \
+{									    \
+	return jesd204b_laneinfo_read(dev, attr, buf, _x);		    \
+}									    \
+static DEVICE_ATTR(lane##_x##_info, 0400, jesd204b_lane##_x##_info_read, \
+		   NULL)
+
+JESD_LANE(0);
+JESD_LANE(1);
+JESD_LANE(2);
+JESD_LANE(3);
+JESD_LANE(4);
+JESD_LANE(5);
+JESD_LANE(6);
+JESD_LANE(7);
+
+static ssize_t jesd204b_lane_syscstat_read(struct device *dev,
+			struct device_attribute *attr,
+			char *buf, unsigned int lane)
+{
+	unsigned int stat;
+	struct jesd204b_state *st = dev_get_drvdata(dev);
+
+	stat = jesd204b_read(st, XLNX_JESD204_REG_SYNC_ERR_STAT);
+
+	return sprintf(buf,
+			"NOT_IN_TAB: %d, DISPARITY: %d, UNEXPECTED_K: %d\n",
+			stat & XLNX_JESD204_SYNC_ERR_NOT_IN_TAB(lane),
+			stat & XLNX_JESD204_SYNC_ERR_DISPARITY(lane),
+			stat & XLNX_JESD204_SYNC_ERR_UNEXPECTED_K(lane));
+}
+
+#define JESD_SYNCSTAT_LANE(_x)						       \
+static ssize_t jesd204b_lane##_x##_syncstat_read(struct device *dev,	       \
+						 struct device_attribute *attr,\
+						 char *buf)		       \
+{									       \
+	return jesd204b_lane_syscstat_read(dev, attr, buf, _x);		       \
+}									       \
+static DEVICE_ATTR(lane##_x##_syncstat, 0400,			       \
+		   jesd204b_lane##_x##_syncstat_read, NULL)
+
+JESD_SYNCSTAT_LANE(0);
+JESD_SYNCSTAT_LANE(1);
+JESD_SYNCSTAT_LANE(2);
+JESD_SYNCSTAT_LANE(3);
+JESD_SYNCSTAT_LANE(4);
+JESD_SYNCSTAT_LANE(5);
+JESD_SYNCSTAT_LANE(6);
+JESD_SYNCSTAT_LANE(7);
+
+static ssize_t jesd204b_reg_write(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t count)
+{
+	struct jesd204b_state *st = dev_get_drvdata(dev);
+	unsigned int val;
+	int ret;
+
+	ret = sscanf(buf, "%i %i", &st->addr, &val);
+	if (ret == 2)
+		jesd204b_write(st, st->addr, val);
+
+	return count;
+}
+
+static ssize_t jesd204b_reg_read(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	struct jesd204b_state *st = dev_get_drvdata(dev);
+
+	return sprintf(buf, "0x%X\n", jesd204b_read(st, st->addr));
+}
+
+static DEVICE_ATTR(reg_access, 0600, jesd204b_reg_read,
+		   jesd204b_reg_write);
+
+static ssize_t jesd204b_syncreg_read(struct device *dev,
+				     struct device_attribute *attr,
+				     char *buf)
+{
+	struct jesd204b_state *st = dev_get_drvdata(dev);
+
+	return sprintf(buf, "0x%X\n", jesd204b_read(st,
+					XLNX_JESD204_REG_SYNC_STATUS));
+}
+
+static DEVICE_ATTR(sync_status, 0400, jesd204b_syncreg_read, NULL);
+
+/* Match table for of_platform binding */
+static const struct of_device_id jesd204b_of_match[] = {
+	{ .compatible = "xlnx,jesd204-5.1",},
+	{ .compatible = "xlnx,jesd204-5.2",},
+	{ .compatible = "xlnx,jesd204-6.1",},
+	{ /* end of list */ },
+};
+MODULE_DEVICE_TABLE(of, jesd204b_of_match);
+
+static int jesd204b_probe(struct platform_device *pdev)
+{
+	struct jesd204b_state *st;
+	struct resource *mem; /* IO mem resources */
+	struct clk *clk;
+	struct child_clk *clk_priv;
+	struct clk_init_data init;
+	unsigned int val;
+	int ret;
+
+	clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(clk))
+		return -EPROBE_DEFER;
+
+	st = devm_kzalloc(&pdev->dev, sizeof(*st), GFP_KERNEL);
+	if (!st)
+		return -ENOMEM;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	st->regs = devm_ioremap_resource(&pdev->dev, mem);
+	if (IS_ERR(st->regs)) {
+		dev_err(&pdev->dev, "Failed ioremap\n");
+		return PTR_ERR(st->regs);
+	}
+
+	st->dev = &pdev->dev;
+
+	platform_set_drvdata(pdev, st);
+
+	st->clk = clk;
+	clk_set_rate(st->clk, 156250000);
+	st->rate = clk_get_rate(clk);
+
+	of_property_read_u32(pdev->dev.of_node, "xlnx,node-is-transmit",
+			     &st->transmit);
+
+	ret = of_property_read_u32(pdev->dev.of_node, "xlnx,lanes",
+				   &st->lanes);
+	if (ret)
+		st->lanes = jesd204b_read(st, XLNX_JESD204_REG_LANES) + 1;
+
+	jesd204b_write(st, XLNX_JESD204_REG_RESET, XLNX_JESD204_RESET);
+	while (!jesd204b_read(st, XLNX_JESD204_REG_RESET))
+		msleep(20);
+
+	jesd204b_write(st, XLNX_JESD204_REG_ILA_CTRL,
+		       (of_property_read_bool(pdev->dev.of_node,
+			"xlnx,lanesync-enable") ? XLNX_JESD204_ILA_EN : 0));
+
+	jesd204b_write(st, XLNX_JESD204_REG_SCR_CTRL,
+		       (of_property_read_bool(pdev->dev.of_node,
+			"xlnx,scramble-enable") ? XLNX_JESD204_SCR_EN : 0));
+
+	jesd204b_write(st, XLNX_JESD204_REG_SYSREF_CTRL,
+		       (of_property_read_bool(pdev->dev.of_node,
+			"xlnx,sysref-always-enable") ?
+			XLNX_JESD204_ALWAYS_SYSREF_EN : 0));
+
+	device_create_file(&pdev->dev, &dev_attr_reg_access);
+
+	device_create_file(&pdev->dev, &dev_attr_sync_status);
+	switch (st->lanes) {
+	case 8:
+		device_create_file(&pdev->dev, &dev_attr_lane4_info);
+		device_create_file(&pdev->dev, &dev_attr_lane5_info);
+		device_create_file(&pdev->dev, &dev_attr_lane6_info);
+		device_create_file(&pdev->dev, &dev_attr_lane7_info);
+		if (!st->transmit) {
+			device_create_file(&pdev->dev,
+					   &dev_attr_lane4_syncstat);
+			device_create_file(&pdev->dev,
+					   &dev_attr_lane5_syncstat);
+			device_create_file(&pdev->dev,
+					   &dev_attr_lane6_syncstat);
+			device_create_file(&pdev->dev,
+					   &dev_attr_lane7_syncstat);
+		}
+		/* fall through */
+	case 4:
+		device_create_file(&pdev->dev, &dev_attr_lane2_info);
+		device_create_file(&pdev->dev, &dev_attr_lane3_info);
+		if (!st->transmit) {
+			device_create_file(&pdev->dev,
+					   &dev_attr_lane2_syncstat);
+			device_create_file(&pdev->dev,
+					   &dev_attr_lane3_syncstat);
+		}
+		/* fall through */
+	case 2:
+		device_create_file(&pdev->dev, &dev_attr_lane1_info);
+		if (!st->transmit)
+			device_create_file(&pdev->dev,
+					   &dev_attr_lane1_syncstat);
+		/* fall through */
+	case 1:
+		device_create_file(&pdev->dev, &dev_attr_lane0_info);
+		if (!st->transmit)
+			device_create_file(&pdev->dev,
+					   &dev_attr_lane0_syncstat);
+		break;
+	default:
+
+		break;
+	}
+
+	clk_priv = devm_kzalloc(&pdev->dev, sizeof(*clk_priv), GFP_KERNEL);
+	if (!clk_priv)
+		return -ENOMEM;
+
+	/* struct child_clk assignments */
+	clk_priv->hw.init = &init;
+	clk_priv->rate = st->rate;
+	clk_priv->st = st;
+
+	ret = clk_prepare_enable(clk);
+	if (ret) {
+		dev_err(&pdev->dev, "Unable to enable clock.\n");
+		return ret;
+	}
+	val = jesd204b_read(st, XLNX_JESD204_REG_VERSION);
+
+	dev_info(&pdev->dev,
+		 "AXI-JESD204B %d.%d Rev %d, at 0x%08llX mapped to 0x%p",
+		 XLNX_JESD204_VERSION_MAJOR(val),
+		 XLNX_JESD204_VERSION_MINOR(val),
+		 XLNX_JESD204_VERSION_REV(val),
+		 (unsigned long long)mem->start, st->regs);
+
+	return 0;
+}
+
+static int jesd204b_remove(struct platform_device *pdev)
+{
+	struct jesd204b_state *st = platform_get_drvdata(pdev);
+
+	clk_disable_unprepare(st->clk);
+	clk_put(st->clk);
+
+	return 0;
+}
+
+static struct platform_driver jesd204b_driver = {
+	.driver = {
+		.name = KBUILD_MODNAME,
+		.of_match_table = jesd204b_of_match,
+	},
+	.probe		= jesd204b_probe,
+	.remove		= jesd204b_remove,
+};
+
+module_platform_driver(jesd204b_driver);
+
+MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
+MODULE_DESCRIPTION("Analog Devices AXI-JESD204B Interface Module");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/jesd204b/xilinx_jesd204b.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/jesd204b/xilinx_jesd204b.h
@@ -0,0 +1,135 @@
+/*
+ * Xilinx AXI-JESD204B v5.1 Interface Module
+ *
+ * Copyright 2014 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ *
+ * http://wiki.analog.com/resources/fpga/xilinx/
+ */
+
+#ifndef XILINX_JESD204B_H_
+#define XILINX_JESD204B_H_
+
+struct jesd204b_state {
+	struct device	*dev;
+	void __iomem	*regs;
+	void __iomem	*phy;
+	struct clk	*clk;
+	u32		lanes;
+	u32		vers_id;
+	u32		addr;
+	u32		band;
+	u32		transmit;
+	u32		pll;
+	unsigned long	rate;
+};
+
+#define XLNX_JESD204_REG_VERSION		0x000
+#define XLNX_JESD204_VERSION_MAJOR(x)		(((x) >> 24) & 0xFF)
+#define XLNX_JESD204_VERSION_MINOR(x)		(((x) >> 16) & 0xFF)
+#define XLNX_JESD204_VERSION_REV(x)		(((x) >> 8) & 0xFF)
+
+#define XLNX_JESD204_REG_RESET			0x004
+#define XLNX_JESD204_RESET			(1 << 0)
+
+#define XLNX_JESD204_REG_ILA_CTRL		0x008
+#define XLNX_JESD204_ILA_EN			(1 << 0)
+
+#define XLNX_JESD204_REG_SCR_CTRL		0x00C
+#define XLNX_JESD204_SCR_EN			(1 << 0)
+
+#define XLNX_JESD204_REG_SYSREF_CTRL		0x010
+#define XLNX_JESD204_ALWAYS_SYSREF_EN		(1 << 0)
+
+#define XLNX_JESD204_REG_ILA_MFC		0x014
+#define XLNX_JESD204_ILA_MFC(x)			(((x) - 1) & 0xFF)
+						/* TX only 4..256 */
+
+#define XLNX_JESD204_REG_TEST_MODE_SEL		0x018
+#define XLNX_JESD204_TEST_MODE_OFF		0 /* Normal operation */
+#define XLNX_JESD204_TEST_MODE_K28_5		1 /* Send/Receive /K28.5/
+						   * indefinitely
+						   */
+#define XLNX_JESD204_TEST_MODE_ILA		2 /* Synchronize as normal then
+						   * send/receive repeated ILA
+						   * sequences
+						   */
+#define XLNX_JESD204_TEST_MODE_D21_5		3 /* Send/Receive /D21.5/
+						   * indefinitely
+						   */
+#define XLNX_JESD204_TEST_MODE_RPAT		5 /* Send/Receive modified
+						   * random pattern (RPAT)
+						   */
+#define XLNX_JESD204_TEST_MODE_JSPAT		7 /* Send/Receive a scrambled
+						   * jitter pattern (JSPAT)
+						   */
+
+#define XLNX_JESD204_REG_SYNC_STATUS		0x038 /* Link SYNC status */
+#define XLNX_JESD204_REG_SYNC_ERR_STAT		0x01C /* RX only */
+#define XLNX_JESD204_SYNC_ERR_NOT_IN_TAB(lane)		(1 << (0 + (lane) * 3))
+#define XLNX_JESD204_SYNC_ERR_DISPARITY(lane)		(1 << (1 + (lane) * 3))
+#define XLNX_JESD204_SYNC_ERR_UNEXPECTED_K(lane)	(1 << (2 + (lane) * 3))
+
+#define XLNX_JESD204_REG_OCTETS_PER_FRAME	0x020
+#define XLNX_JESD204_OCTETS_PER_FRAME(x)	(((x) - 1) & 0xFF) /* 1..256 */
+
+#define XLNX_JESD204_REG_FRAMES_PER_MFRAME	0x024
+#define XLNX_JESD204_FRAMES_PER_MFRAME(x)	(((x) - 1) & 0x1F) /* 1..32 */
+
+#define XLNX_JESD204_REG_LANES			0x028
+#define XLNX_JESD204_LANES(x)			(((x) - 1) & 0x1F) /* 1..32 */
+
+#define XLNX_JESD204_REG_SUBCLASS		0x02C
+
+#define XLNX_JESD204_REG_RX_BUF_DELAY		0x030 /* RX only */
+#define XLNX_JESD204_RX_BUF_DELAY(x)		((x) & 0x1FFF)
+
+#define XLNX_JESD204_REG_RX_LINK_CTRL		0x034 /* RX only */
+#define XLNX_JESD204_LINK_TEST_EN		(1 << 0)
+#define XLNX_JESD204_SYNC_ERR_REP_DIS		(1 << 8)
+
+/* Per LANE Registers */
+#define XLNX_JESD204_REG_LANE_VERSION(l)	(0x800 + ((l) * 0x40))
+#define XLNX_JESD204_LANE_SUBCLASS(x)		(((x) >> 0) & 0x7)
+#define XLNX_JESD204_LANE_JESDV(x)		(((x) >> 8) & 0x7)
+
+#define XLNX_JESD204_REG_LANE_F(l)		(0x804 + ((l) * 0x40))
+#define XLNX_JESD204_LANE_F(x)			((((x) >> 0) & 0xFF) + 1)
+
+#define XLNX_JESD204_REG_LANE_K(l)		(0x808 + ((l) * 0x40))
+#define XLNX_JESD204_LANE_K(x)			((((x) >> 0) & 0x1F) + 1)
+
+#define XLNX_JESD204_REG_ID_L(l)		(0x80C + ((l) * 0x40))
+#define XLNX_JESD204_LANE_DID(x)		(((x) >> 0) & 0xFF)
+#define XLNX_JESD204_LANE_BID(x)		(((x) >> 8) & 0x1F)
+#define XLNX_JESD204_LANE_LID(x)		(((x) >> 16) & 0x1F)
+#define XLNX_JESD204_LANE_L(x)			((((x) >> 24) & 0x1F) + 1)
+
+#define XLNX_JESD204_REG_M_N_ND_CS(l)		(0x810 + ((l) * 0x40))
+#define XLNX_JESD204_LANE_M(x)			((((x) >> 0) & 0xFF) + 1)
+#define XLNX_JESD204_LANE_N(x)			((((x) >> 8) & 0x1F) + 1)
+#define XLNX_JESD204_LANE_ND(x)			((((x) >> 16) & 0x1F) + 1)
+#define XLNX_JESD204_LANE_CS(x)			(((x) >> 24) & 0x3)
+
+#define XLNX_JESD204_REG_SCR_S_HD_CF(l)		(0x814 + ((l) * 0x40))
+#define XLNX_JESD204_LANE_SCR(x)		(((x) >> 0) & 0x1)
+#define XLNX_JESD204_LANE_S(x)			((((x) >> 8) & 0x1F) + 1)
+#define XLNX_JESD204_LANE_HD(x)			(((x) >> 16) & 0x1)
+#define XLNX_JESD204_LANE_CF(x)			(((x) >> 24) & 0x1F)
+
+#define XLNX_JESD204_REG_FCHK(l)		(0x818 + ((l) * 0x40))
+#define XLNX_JESD204_LANE_FCHK(x)		(((x) >> 16) & 0xFF)
+
+#define XLNX_JESD204_REG_SC2_ADJ_CTRL(l)	(0x81C + ((l) * 0x40))
+#define XLNX_JESD204_LANE_ADJ_CNT(x)		(((x) >> 0) & 0xF)
+#define XLNX_JESD204_LANE_PHASE_ADJ_REQ(x)	(((x) >> 8) & 0x1)
+#define XLNX_JESD204_LANE_ADJ_CNT_DIR(x)		(((x) >> 16) & 0x1)
+
+#define XLNX_JESD204_REG_TM_ERR_CNT(l)		(0x820 + ((l) * 0x40))
+#define XLNX_JESD204_REG_TM_LINK_ERR_CNT(l)	(0x824 + ((l) * 0x40))
+#define XLNX_JESD204_REG_TM_ILA_CNT(l)		(0x828 + ((l) * 0x40))
+#define XLNX_JESD204_REG_TM_MFC_CNT(l)		(0x82C + ((l) * 0x40))
+#define XLNX_JESD204_REG_TM_BUF_ADJ(l)		(0x830 + ((l) * 0x40))
+
+#endif /* ADI_JESD204B_V51_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/kgdbts.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/kgdbts.c
@@ -95,19 +95,20 @@
 
 #include <asm/sections.h>
 
-#define v1printk(a...) do { \
-	if (verbose) \
-		printk(KERN_INFO a); \
-	} while (0)
-#define v2printk(a...) do { \
-	if (verbose > 1) \
-		printk(KERN_INFO a); \
-		touch_nmi_watchdog();	\
-	} while (0)
-#define eprintk(a...) do { \
-		printk(KERN_ERR a); \
-		WARN_ON(1); \
-	} while (0)
+#define v1printk(a...) do {		\
+	if (verbose)			\
+		printk(KERN_INFO a);	\
+} while (0)
+#define v2printk(a...) do {		\
+	if (verbose > 1) {		\
+		printk(KERN_INFO a);	\
+	}				\
+	touch_nmi_watchdog();		\
+} while (0)
+#define eprintk(a...) do {		\
+	printk(KERN_ERR a);		\
+	WARN_ON(1);			\
+} while (0)
 #define MAX_CONFIG_LEN		40
 
 static struct kgdb_io kgdbts_io_ops;
@@ -1059,10 +1060,10 @@
 {
 	if (strlen(opt) >= MAX_CONFIG_LEN) {
 		printk(KERN_ERR "kgdbts: config string too long\n");
-		return -ENOSPC;
+		return 1;
 	}
 	strcpy(config, opt);
-	return 0;
+	return 1;
 }
 
 __setup("kgdbts=", kgdbts_option_setup);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/lattice-ecp3-config.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/lattice-ecp3-config.c
@@ -77,12 +77,12 @@
 
 	if (fw == NULL) {
 		dev_err(&spi->dev, "Cannot load firmware, aborting\n");
-		return;
+		goto out;
 	}
 
 	if (fw->size == 0) {
 		dev_err(&spi->dev, "Error: Firmware size is 0!\n");
-		return;
+		goto out;
 	}
 
 	/* Fill dummy data (24 stuffing bits for commands) */
@@ -104,7 +104,7 @@
 		dev_err(&spi->dev,
 			"Error: No supported FPGA detected (JEDEC_ID=%08x)!\n",
 			jedec_id);
-		return;
+		goto out;
 	}
 
 	dev_info(&spi->dev, "FPGA %s detected\n", ecp3_dev[i].name);
@@ -117,7 +117,7 @@
 	buffer = kzalloc(fw->size + 8, GFP_KERNEL);
 	if (!buffer) {
 		dev_err(&spi->dev, "Error: Can't allocate memory!\n");
-		return;
+		goto out;
 	}
 
 	/*
@@ -156,7 +156,7 @@
 			"Error: Timeout waiting for FPGA to clear (status=%08x)!\n",
 			status);
 		kfree(buffer);
-		return;
+		goto out;
 	}
 
 	dev_info(&spi->dev, "Configuring the FPGA...\n");
@@ -182,7 +182,7 @@
 	release_firmware(fw);
 
 	kfree(buffer);
-
+out:
 	complete(&data->fw_loaded);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/lis3lv02d/lis3lv02d.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/lis3lv02d/lis3lv02d.c
@@ -208,7 +208,7 @@
 static int lis3_3dlh_rates[4] = {50, 100, 400, 1000};
 
 /* ODR is Output Data Rate */
-static int lis3lv02d_get_odr(struct lis3lv02d *lis3)
+static int lis3lv02d_get_odr_index(struct lis3lv02d *lis3)
 {
 	u8 ctrl;
 	int shift;
@@ -216,15 +216,23 @@
 	lis3->read(lis3, CTRL_REG1, &ctrl);
 	ctrl &= lis3->odr_mask;
 	shift = ffs(lis3->odr_mask) - 1;
-	return lis3->odrs[(ctrl >> shift)];
+	return (ctrl >> shift);
 }
 
 static int lis3lv02d_get_pwron_wait(struct lis3lv02d *lis3)
 {
-	int div = lis3lv02d_get_odr(lis3);
+	int odr_idx = lis3lv02d_get_odr_index(lis3);
+	int div = lis3->odrs[odr_idx];
 
-	if (WARN_ONCE(div == 0, "device returned spurious data"))
+	if (div == 0) {
+		if (odr_idx == 0) {
+			/* Power-down mode, not sampling no need to sleep */
+			return 0;
+		}
+
+		dev_err(&lis3->pdev->dev, "Error unknown odrs-index: %d\n", odr_idx);
 		return -ENXIO;
+	}
 
 	/* LIS3 power on delay is quite long */
 	msleep(lis3->pwron_delay / div);
@@ -807,9 +815,12 @@
 			struct device_attribute *attr, char *buf)
 {
 	struct lis3lv02d *lis3 = dev_get_drvdata(dev);
+	int odr_idx;
 
 	lis3lv02d_sysfs_poweron(lis3);
-	return sprintf(buf, "%d\n", lis3lv02d_get_odr(lis3));
+
+	odr_idx = lis3lv02d_get_odr_index(lis3);
+	return sprintf(buf, "%d\n", lis3->odrs[odr_idx]);
 }
 
 static ssize_t lis3lv02d_rate_set(struct device *dev,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/lis3lv02d/lis3lv02d.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/lis3lv02d/lis3lv02d.h
@@ -271,6 +271,7 @@
 	int			regs_size;
 	u8                      *reg_cache;
 	bool			regs_stored;
+	bool			init_required;
 	u8                      odr_mask;  /* ODR bit mask */
 	u8			whoami;    /* indicates measurement precision */
 	s16 (*read_data) (struct lis3lv02d *lis3, int reg);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/lkdtm/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/lkdtm/Makefile
@@ -16,7 +16,7 @@
 
 OBJCOPYFLAGS :=
 OBJCOPYFLAGS_rodata_objcopy.o	:= \
-			--rename-section .text=.rodata,alloc,readonly,load
+			--rename-section .noinstr.text=.rodata,alloc,readonly,load,contents
 targets += rodata.o rodata_objcopy.o
 $(obj)/rodata_objcopy.o: $(obj)/rodata.o FORCE
 	$(call if_changed,objcopy)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/lkdtm/bugs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/lkdtm/bugs.c
@@ -274,7 +274,7 @@
 
 void lkdtm_UNSET_SMEP(void)
 {
-#ifdef CONFIG_X86_64
+#if IS_ENABLED(CONFIG_X86_64) && !IS_ENABLED(CONFIG_UML)
 #define MOV_CR4_DEPTH	64
 	void (*direct_write_cr4)(unsigned long val);
 	unsigned char *insn;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/lkdtm/refcount.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/lkdtm/refcount.c
@@ -6,14 +6,6 @@
 #include "lkdtm.h"
 #include <linux/refcount.h>
 
-#ifdef CONFIG_REFCOUNT_FULL
-#define REFCOUNT_MAX		(UINT_MAX - 1)
-#define REFCOUNT_SATURATED	UINT_MAX
-#else
-#define REFCOUNT_MAX		INT_MAX
-#define REFCOUNT_SATURATED	(INT_MIN / 2)
-#endif
-
 static void overflow_check(refcount_t *ref)
 {
 	switch (refcount_read(ref)) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/lkdtm/rodata.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/lkdtm/rodata.c
@@ -5,7 +5,7 @@
  */
 #include "lkdtm.h"
 
-void notrace lkdtm_rodata_do_nothing(void)
+void noinstr lkdtm_rodata_do_nothing(void)
 {
 	/* Does nothing. We just want an architecture agnostic "return". */
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/lkdtm/usercopy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/lkdtm/usercopy.c
@@ -30,12 +30,12 @@
  */
 static noinline unsigned char *trick_compiler(unsigned char *stack)
 {
-	return stack + 0;
+	return stack + unconst;
 }
 
 static noinline unsigned char *do_usercopy_stack_callee(int value)
 {
-	unsigned char buf[32];
+	unsigned char buf[128];
 	int i;
 
 	/* Exercise stack to avoid everything living in registers. */
@@ -43,7 +43,12 @@
 		buf[i] = value & 0xff;
 	}
 
-	return trick_compiler(buf);
+	/*
+	 * Put the target buffer in the middle of stack allocation
+	 * so that we don't step on future stack users regardless
+	 * of stack growth direction.
+	 */
+	return trick_compiler(&buf[(128/2)-32]);
 }
 
 static noinline void do_usercopy_stack(bool to_user, bool bad_frame)
@@ -66,6 +71,12 @@
 		bad_stack -= sizeof(unsigned long);
 	}
 
+#ifdef ARCH_HAS_CURRENT_STACK_POINTER
+	pr_info("stack     : %px\n", (void *)current_stack_pointer);
+#endif
+	pr_info("good_stack: %px-%px\n", good_stack, good_stack + sizeof(good_stack));
+	pr_info("bad_stack : %px-%px\n", bad_stack, bad_stack + sizeof(good_stack));
+
 	user_addr = vm_mmap(NULL, 0, PAGE_SIZE,
 			    PROT_READ | PROT_WRITE | PROT_EXEC,
 			    MAP_ANONYMOUS | MAP_PRIVATE, 0);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/mei/bus-fixup.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/mei/bus-fixup.c
@@ -178,7 +178,7 @@
 	ret = __mei_cl_send(cldev->cl, buf, sizeof(struct mkhi_msg_hdr),
 			    MEI_CL_IO_TX_BLOCKING);
 	if (ret < 0) {
-		dev_err(&cldev->dev, "Could not send ReqFWVersion cmd\n");
+		dev_err(&cldev->dev, "Could not send ReqFWVersion cmd ret = %d\n", ret);
 		return ret;
 	}
 
@@ -190,7 +190,7 @@
 		 * Should be at least one version block,
 		 * error out if nothing found
 		 */
-		dev_err(&cldev->dev, "Could not read FW version\n");
+		dev_err(&cldev->dev, "Could not read FW version ret = %d\n", bytes_recv);
 		return -EIO;
 	}
 
@@ -339,7 +339,7 @@
 	ret = __mei_cl_send(cl, (u8 *)&cmd, sizeof(struct mei_nfc_cmd),
 			    MEI_CL_IO_TX_BLOCKING);
 	if (ret < 0) {
-		dev_err(bus->dev, "Could not send IF version cmd\n");
+		dev_err(bus->dev, "Could not send IF version cmd ret = %d\n", ret);
 		return ret;
 	}
 
@@ -354,7 +354,7 @@
 	ret = 0;
 	bytes_recv = __mei_cl_recv(cl, (u8 *)reply, if_version_length, 0, 0);
 	if (bytes_recv < 0 || (size_t)bytes_recv < if_version_length) {
-		dev_err(bus->dev, "Could not read IF version\n");
+		dev_err(bus->dev, "Could not read IF version ret = %d\n", bytes_recv);
 		ret = -EIO;
 		goto err;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/mei/bus.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/mei/bus.c
@@ -745,9 +745,8 @@
 
 	mei_cl_bus_module_put(cldev);
 	module_put(THIS_MODULE);
-	dev->driver = NULL;
-	return ret;
 
+	return ret;
 }
 
 static ssize_t name_show(struct device *dev, struct device_attribute *a,
@@ -873,15 +872,16 @@
 
 /**
  * mei_cl_bus_set_name - set device name for me client device
+ *  <controller>-<client device>
+ *  Example: 0000:00:16.0-55213584-9a29-4916-badf-0fb7ed682aeb
  *
  * @cldev: me client device
  */
 static inline void mei_cl_bus_set_name(struct mei_cl_device *cldev)
 {
-	dev_set_name(&cldev->dev, "mei:%s:%pUl:%02X",
-		     cldev->name,
-		     mei_me_cl_uuid(cldev->me_cl),
-		     mei_me_cl_ver(cldev->me_cl));
+	dev_set_name(&cldev->dev, "%s-%pUl",
+		     dev_name(cldev->bus->dev),
+		     mei_me_cl_uuid(cldev->me_cl));
 }
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/mei/client.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/mei/client.c
@@ -266,6 +266,7 @@
 	down_write(&dev->me_clients_rwsem);
 	me_cl = __mei_me_cl_by_uuid(dev, uuid);
 	__mei_me_cl_del(dev, me_cl);
+	mei_me_cl_put(me_cl);
 	up_write(&dev->me_clients_rwsem);
 }
 
@@ -287,6 +288,7 @@
 	down_write(&dev->me_clients_rwsem);
 	me_cl = __mei_me_cl_by_uuid_id(dev, uuid, id);
 	__mei_me_cl_del(dev, me_cl);
+	mei_me_cl_put(me_cl);
 	up_write(&dev->me_clients_rwsem);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/mei/client.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/mei/client.h
@@ -128,11 +128,11 @@
  *
  * @cl: host client
  *
- * Return: mtu
+ * Return: mtu or 0 if client is not connected
  */
 static inline size_t mei_cl_mtu(const struct mei_cl *cl)
 {
-	return cl->me_cl->props.max_msg_length;
+	return cl->me_cl ? cl->me_cl->props.max_msg_length : 0;
 }
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/mei/hbm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/mei/hbm.c
@@ -1300,7 +1300,7 @@
 			return -EPROTO;
 		}
 
-		dev->dev_state = MEI_DEV_POWER_DOWN;
+		mei_set_devstate(dev, MEI_DEV_POWER_DOWN);
 		dev_info(dev->dev, "hbm: stop response: resetting.\n");
 		/* force the reset */
 		return -EPROTO;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/mei/hdcp/mei_hdcp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/mei/hdcp/mei_hdcp.c
@@ -758,11 +758,38 @@
 	.unbind = mei_component_master_unbind,
 };
 
+/**
+ * mei_hdcp_component_match - compare function for matching mei hdcp.
+ *
+ *    The function checks if the driver is i915, the subcomponent is HDCP
+ *    and the grand parent of hdcp and the parent of i915 are the same
+ *    PCH device.
+ *
+ * @dev: master device
+ * @subcomponent: subcomponent to match (I915_COMPONENT_HDCP)
+ * @data: compare data (mei hdcp device)
+ *
+ * Return:
+ * * 1 - if components match
+ * * 0 - otherwise
+ */
 static int mei_hdcp_component_match(struct device *dev, int subcomponent,
 				    void *data)
 {
-	return !strcmp(dev->driver->name, "i915") &&
-	       subcomponent == I915_COMPONENT_HDCP;
+	struct device *base = data;
+
+	if (strcmp(dev->driver->name, "i915") ||
+	    subcomponent != I915_COMPONENT_HDCP)
+		return 0;
+
+	base = base->parent;
+	if (!base)
+		return 0;
+
+	base = base->parent;
+	dev = dev->parent;
+
+	return (base && dev && dev == base);
 }
 
 static int mei_hdcp_probe(struct mei_cl_device *cldev,
@@ -786,7 +813,7 @@
 
 	master_match = NULL;
 	component_match_add_typed(&cldev->dev, &master_match,
-				  mei_hdcp_component_match, comp_master);
+				  mei_hdcp_component_match, &cldev->dev);
 	if (IS_ERR_OR_NULL(master_match)) {
 		ret = -ENOMEM;
 		goto err_exit;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/mei/hw-me-regs.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/mei/hw-me-regs.h
@@ -82,7 +82,15 @@
 #define MEI_DEV_ID_CMP_LP     0x02e0  /* Comet Point LP */
 #define MEI_DEV_ID_CMP_LP_3   0x02e4  /* Comet Point LP 3 (iTouch) */
 
+#define MEI_DEV_ID_CMP_V      0xA3BA  /* Comet Point Lake V */
+
+#define MEI_DEV_ID_CMP_H      0x06e0  /* Comet Lake H */
+#define MEI_DEV_ID_CMP_H_3    0x06e4  /* Comet Lake H 3 (iTouch) */
+
+#define MEI_DEV_ID_CDF        0x18D3  /* Cedar Fork */
+
 #define MEI_DEV_ID_ICP_LP     0x34E0  /* Ice Lake Point LP */
+#define MEI_DEV_ID_ICP_N      0x38E0  /* Ice Lake Point N */
 
 #define MEI_DEV_ID_TGP_LP     0xA0E0  /* Tiger Lake Point LP */
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/mei/interrupt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/mei/interrupt.c
@@ -222,6 +222,9 @@
 		return ret;
 	}
 
+	pm_runtime_mark_last_busy(dev->dev);
+	pm_request_autosuspend(dev->dev);
+
 	list_move_tail(&cb->list, &cl->rd_pending);
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/mei/main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/mei/main.c
@@ -268,7 +268,7 @@
 	}
 
 	if (!mei_cl_is_connected(cl)) {
-		cl_err(dev, cl, "is not connected");
+		cl_dbg(dev, cl, "is not connected");
 		rets = -ENODEV;
 		goto out;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/mei/pci-me.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/mei/pci-me.c
@@ -32,6 +32,9 @@
 #include "hw-me-regs.h"
 #include "hw-me.h"
 
+static bool disable_msi;
+module_param(disable_msi, bool, 0);
+
 /* mei_pci_tbl - PCI Device ID Table */
 static const struct pci_device_id mei_me_pci_tbl[] = {
 	{MEI_PCI_DEVICE(MEI_DEV_ID_82946GZ, MEI_ME_ICH_CFG)},
@@ -98,14 +101,20 @@
 
 	{MEI_PCI_DEVICE(MEI_DEV_ID_CMP_LP, MEI_ME_PCH12_CFG)},
 	{MEI_PCI_DEVICE(MEI_DEV_ID_CMP_LP_3, MEI_ME_PCH8_CFG)},
+	{MEI_PCI_DEVICE(MEI_DEV_ID_CMP_V, MEI_ME_PCH12_CFG)},
+	{MEI_PCI_DEVICE(MEI_DEV_ID_CMP_H, MEI_ME_PCH12_CFG)},
+	{MEI_PCI_DEVICE(MEI_DEV_ID_CMP_H_3, MEI_ME_PCH8_CFG)},
 
 	{MEI_PCI_DEVICE(MEI_DEV_ID_ICP_LP, MEI_ME_PCH12_CFG)},
+	{MEI_PCI_DEVICE(MEI_DEV_ID_ICP_N, MEI_ME_PCH12_CFG)},
 
 	{MEI_PCI_DEVICE(MEI_DEV_ID_TGP_LP, MEI_ME_PCH12_CFG)},
 
 	{MEI_PCI_DEVICE(MEI_DEV_ID_MCC, MEI_ME_PCH12_CFG)},
 	{MEI_PCI_DEVICE(MEI_DEV_ID_MCC_4, MEI_ME_PCH8_CFG)},
 
+	{MEI_PCI_DEVICE(MEI_DEV_ID_CDF, MEI_ME_PCH8_CFG)},
+
 	/* required last entry */
 	{0, }
 };
@@ -199,7 +208,8 @@
 	hw = to_me_hw(dev);
 	hw->mem_addr = pcim_iomap_table(pdev)[0];
 
-	pci_enable_msi(pdev);
+	if (!disable_msi)
+		pci_enable_msi(pdev);
 
 	 /* request and enable interrupt */
 	irqflags = pci_dev_msi_enabled(pdev) ? IRQF_ONESHOT : IRQF_SHARED;
@@ -373,8 +383,10 @@
 	}
 
 	err = mei_restart(dev);
-	if (err)
+	if (err) {
+		free_irq(pdev->irq, dev);
 		return err;
+	}
 
 	/* Start timer if stopped in suspend */
 	schedule_delayed_work(&dev->timer_work, HZ);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/mic/scif/scif_rma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/mic/scif/scif_rma.c
@@ -1381,6 +1381,8 @@
 				(prot & SCIF_PROT_WRITE) ? FOLL_WRITE : 0,
 				pinned_pages->pages);
 		if (nr_pages != pinned_pages->nr_pages) {
+			if (pinned_pages->nr_pages < 0)
+				pinned_pages->nr_pages = 0;
 			if (try_upgrade) {
 				if (ulimit)
 					__scif_dec_pinned_vm_lock(mm, nr_pages);
@@ -1400,7 +1402,6 @@
 
 	if (pinned_pages->nr_pages < nr_pages) {
 		err = -EFAULT;
-		pinned_pages->nr_pages = nr_pages;
 		goto dec_pinned;
 	}
 
@@ -1413,7 +1414,6 @@
 		__scif_dec_pinned_vm_lock(mm, nr_pages);
 	/* Something went wrong! Rollback */
 error_unmap:
-	pinned_pages->nr_pages = nr_pages;
 	scif_destroy_pinned_pages(pinned_pages);
 	*pages = NULL;
 	dev_dbg(scif_info.mdev.this_device,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/mic/vop/vop_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/mic/vop/vop_main.c
@@ -320,7 +320,7 @@
 	/* First assign the vring's allocated in host memory */
 	vqconfig = _vop_vq_config(vdev->desc) + index;
 	memcpy_fromio(&config, vqconfig, sizeof(config));
-	_vr_size = vring_size(le16_to_cpu(config.num), MIC_VIRTIO_RING_ALIGN);
+	_vr_size = round_up(vring_size(le16_to_cpu(config.num), MIC_VIRTIO_RING_ALIGN), 4);
 	vr_size = PAGE_ALIGN(_vr_size + sizeof(struct _mic_vring_info));
 	va = vpdev->hw_ops->remap(vpdev, le64_to_cpu(config.address), vr_size);
 	if (!va)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/mic/vop/vop_vringh.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/mic/vop/vop_vringh.c
@@ -296,7 +296,7 @@
 
 		num = le16_to_cpu(vqconfig[i].num);
 		mutex_init(&vvr->vr_mutex);
-		vr_size = PAGE_ALIGN(vring_size(num, MIC_VIRTIO_RING_ALIGN) +
+		vr_size = PAGE_ALIGN(round_up(vring_size(num, MIC_VIRTIO_RING_ALIGN), 4) +
 			sizeof(struct _mic_vring_info));
 		vr->va = (void *)
 			__get_free_pages(GFP_KERNEL | __GFP_ZERO,
@@ -308,7 +308,7 @@
 			goto err;
 		}
 		vr->len = vr_size;
-		vr->info = vr->va + vring_size(num, MIC_VIRTIO_RING_ALIGN);
+		vr->info = vr->va + round_up(vring_size(num, MIC_VIRTIO_RING_ALIGN), 4);
 		vr->info->magic = cpu_to_le32(MIC_MAGIC + vdev->virtio_id + i);
 		vr_addr = dma_map_single(&vpdev->dev, vr->va, vr_size,
 					 DMA_BIDIRECTIONAL);
@@ -602,6 +602,7 @@
 	size_t partlen;
 	bool dma = VOP_USE_DMA && vi->dma_ch;
 	int err = 0;
+	size_t offset = 0;
 
 	if (dma) {
 		dma_alignment = 1 << vi->dma_ch->device->copy_align;
@@ -655,13 +656,20 @@
 	 * We are copying to IO below and should ideally use something
 	 * like copy_from_user_toio(..) if it existed.
 	 */
-	if (copy_from_user((void __force *)dbuf, ubuf, len)) {
-		err = -EFAULT;
-		dev_err(vop_dev(vdev), "%s %d err %d\n",
-			__func__, __LINE__, err);
-		goto err;
+	while (len) {
+		partlen = min_t(size_t, len, VOP_INT_DMA_BUF_SIZE);
+
+		if (copy_from_user(vvr->buf, ubuf + offset, partlen)) {
+			err = -EFAULT;
+			dev_err(vop_dev(vdev), "%s %d err %d\n",
+				__func__, __LINE__, err);
+			goto err;
+		}
+		memcpy_toio(dbuf + offset, vvr->buf, partlen);
+		offset += partlen;
+		vdev->out_bytes += partlen;
+		len -= partlen;
 	}
-	vdev->out_bytes += len;
 	err = 0;
 err:
 	vpdev->hw_ops->unmap(vpdev, dbuf);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/ocxl/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/ocxl/Kconfig
@@ -11,6 +11,7 @@
 	tristate "OpenCAPI coherent accelerator support"
 	depends on PPC_POWERNV && PCI && EEH
 	select OCXL_BASE
+	select HOTPLUG_PCI_POWERNV
 	default m
 	help
 	  Select this option to enable the ocxl driver for Open
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/ocxl/context.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/ocxl/context.c
@@ -10,18 +10,17 @@
 	int pasid;
 	struct ocxl_context *ctx;
 
-	*context = kzalloc(sizeof(struct ocxl_context), GFP_KERNEL);
-	if (!*context)
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
 		return -ENOMEM;
 
-	ctx = *context;
-
 	ctx->afu = afu;
 	mutex_lock(&afu->contexts_lock);
 	pasid = idr_alloc(&afu->contexts_idr, ctx, afu->pasid_base,
 			afu->pasid_base + afu->pasid_max, GFP_KERNEL);
 	if (pasid < 0) {
 		mutex_unlock(&afu->contexts_lock);
+		kfree(ctx);
 		return pasid;
 	}
 	afu->pasid_count++;
@@ -43,6 +42,7 @@
 	 * duration of the life of the context
 	 */
 	ocxl_afu_get(afu);
+	*context = ctx;
 	return 0;
 }
 EXPORT_SYMBOL_GPL(ocxl_context_alloc);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/ocxl/file.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/ocxl/file.c
@@ -18,18 +18,15 @@
 static struct mutex minors_idr_lock;
 static struct idr minors_idr;
 
-static struct ocxl_file_info *find_file_info(dev_t devno)
+static struct ocxl_file_info *find_and_get_file_info(dev_t devno)
 {
 	struct ocxl_file_info *info;
 
-	/*
-	 * We don't declare an RCU critical section here, as our AFU
-	 * is protected by a reference counter on the device. By the time the
-	 * info reference is removed from the idr, the ref count of
-	 * the device is already at 0, so no user API will access that AFU and
-	 * this function can't return it.
-	 */
+	mutex_lock(&minors_idr_lock);
 	info = idr_find(&minors_idr, MINOR(devno));
+	if (info)
+		get_device(&info->dev);
+	mutex_unlock(&minors_idr_lock);
 	return info;
 }
 
@@ -58,14 +55,16 @@
 
 	pr_debug("%s for device %x\n", __func__, inode->i_rdev);
 
-	info = find_file_info(inode->i_rdev);
+	info = find_and_get_file_info(inode->i_rdev);
 	if (!info)
 		return -ENODEV;
 
 	rc = ocxl_context_alloc(&ctx, info->afu, inode->i_mapping);
-	if (rc)
+	if (rc) {
+		put_device(&info->dev);
 		return rc;
-
+	}
+	put_device(&info->dev);
 	file->private_data = ctx;
 	return 0;
 }
@@ -260,6 +259,8 @@
 		if (IS_ERR(ev_ctx))
 			return PTR_ERR(ev_ctx);
 		rc = ocxl_irq_set_handler(ctx, irq_id, irq_handler, irq_free, ev_ctx);
+		if (rc)
+			eventfd_ctx_put(ev_ctx);
 		break;
 
 	case OCXL_IOCTL_GET_METADATA:
@@ -487,7 +488,6 @@
 {
 	struct ocxl_file_info *info = container_of(dev, struct ocxl_file_info, dev);
 
-	free_minor(info);
 	ocxl_afu_put(info->afu);
 	kfree(info);
 }
@@ -543,8 +543,11 @@
 		goto err_put;
 
 	rc = device_register(&info->dev);
-	if (rc)
-		goto err_put;
+	if (rc) {
+		free_minor(info);
+		put_device(&info->dev);
+		return rc;
+	}
 
 	rc = ocxl_sysfs_register_afu(info);
 	if (rc)
@@ -560,7 +563,9 @@
 
 err_unregister:
 	ocxl_sysfs_unregister_afu(info); // safe to call even if register failed
+	free_minor(info);
 	device_unregister(&info->dev);
+	return rc;
 err_put:
 	ocxl_afu_put(afu);
 	free_minor(info);
@@ -577,6 +582,7 @@
 
 	ocxl_file_make_invisible(info);
 	ocxl_sysfs_unregister_afu(info);
+	free_minor(info);
 	device_unregister(&info->dev);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/pci_endpoint_test.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/pci_endpoint_test.c
@@ -98,6 +98,7 @@
 	struct completion irq_raised;
 	int		last_irq;
 	int		num_irqs;
+	int		irq_type;
 	/* mutex to protect the ioctls */
 	struct mutex	mutex;
 	struct miscdevice miscdev;
@@ -157,6 +158,7 @@
 	struct pci_dev *pdev = test->pdev;
 
 	pci_free_irq_vectors(pdev);
+	test->irq_type = IRQ_TYPE_UNDEFINED;
 }
 
 static bool pci_endpoint_test_alloc_irq_vectors(struct pci_endpoint_test *test,
@@ -191,6 +193,8 @@
 		irq = 0;
 		res = false;
 	}
+
+	test->irq_type = type;
 	test->num_irqs = irq;
 
 	return res;
@@ -330,6 +334,7 @@
 	dma_addr_t orig_dst_phys_addr;
 	size_t offset;
 	size_t alignment = test->alignment;
+	int irq_type = test->irq_type;
 	u32 src_crc32;
 	u32 dst_crc32;
 
@@ -426,6 +431,7 @@
 	dma_addr_t orig_phys_addr;
 	size_t offset;
 	size_t alignment = test->alignment;
+	int irq_type = test->irq_type;
 	u32 crc32;
 
 	if (size > SIZE_MAX - alignment)
@@ -494,6 +500,7 @@
 	dma_addr_t orig_phys_addr;
 	size_t offset;
 	size_t alignment = test->alignment;
+	int irq_type = test->irq_type;
 	u32 crc32;
 
 	if (size > SIZE_MAX - alignment)
@@ -555,7 +562,7 @@
 		return false;
 	}
 
-	if (irq_type == req_irq_type)
+	if (test->irq_type == req_irq_type)
 		return true;
 
 	pci_endpoint_test_release_irq(test);
@@ -567,12 +574,10 @@
 	if (!pci_endpoint_test_request_irq(test))
 		goto err;
 
-	irq_type = req_irq_type;
 	return true;
 
 err:
 	pci_endpoint_test_free_irq_vectors(test);
-	irq_type = IRQ_TYPE_UNDEFINED;
 	return false;
 }
 
@@ -585,6 +590,10 @@
 	struct pci_dev *pdev = test->pdev;
 
 	mutex_lock(&test->mutex);
+
+	reinit_completion(&test->irq_raised);
+	test->last_irq = -ENODATA;
+
 	switch (cmd) {
 	case PCITEST_BAR:
 		bar = arg;
@@ -633,7 +642,7 @@
 {
 	int err;
 	int id;
-	char name[20];
+	char name[24];
 	enum pci_barno bar;
 	void __iomem *base;
 	struct device *dev = &pdev->dev;
@@ -652,6 +661,7 @@
 	test->test_reg_bar = 0;
 	test->alignment = 0;
 	test->pdev = pdev;
+	test->irq_type = IRQ_TYPE_UNDEFINED;
 
 	if (no_msi)
 		irq_type = IRQ_TYPE_LEGACY;
@@ -768,6 +778,9 @@
 	if (id < 0)
 		return;
 
+	pci_endpoint_test_release_irq(test);
+	pci_endpoint_test_free_irq_vectors(test);
+
 	misc_deregister(&test->miscdev);
 	kfree(misc_device->name);
 	ida_simple_remove(&pci_endpoint_test_ida, id);
@@ -776,9 +789,6 @@
 			pci_iounmap(pdev, test->bar[bar]);
 	}
 
-	pci_endpoint_test_release_irq(test);
-	pci_endpoint_test_free_irq_vectors(test);
-
 	pci_release_regions(pdev);
 	pci_disable_device(pdev);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/pvpanic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/pvpanic.c
@@ -166,6 +166,7 @@
 	{ .compatible = "qemu,pvpanic-mmio", },
 	{}
 };
+MODULE_DEVICE_TABLE(of, pvpanic_mmio_match);
 
 static struct platform_driver pvpanic_mmio_driver = {
 	.driver = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/sgi-gru/grufault.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/sgi-gru/grufault.c
@@ -648,6 +648,7 @@
 	if ((cb & (GRU_HANDLE_STRIDE - 1)) || ucbnum >= GRU_NUM_CB)
 		return -EINVAL;
 
+again:
 	gts = gru_find_lock_gts(cb);
 	if (!gts)
 		return -EINVAL;
@@ -656,7 +657,11 @@
 	if (ucbnum >= gts->ts_cbr_au_count * GRU_CBR_AU_SIZE)
 		goto exit;
 
-	gru_check_context_placement(gts);
+	if (gru_check_context_placement(gts)) {
+		gru_unlock_gts(gts);
+		gru_unload_context(gts, 1);
+		goto again;
+	}
 
 	/*
 	 * CCH may contain stale data if ts_force_cch_reload is set.
@@ -874,7 +879,11 @@
 		} else {
 			gts->ts_user_blade_id = req.val1;
 			gts->ts_user_chiplet_id = req.val0;
-			gru_check_context_placement(gts);
+			if (gru_check_context_placement(gts)) {
+				gru_unlock_gts(gts);
+				gru_unload_context(gts, 1);
+				return ret;
+			}
 		}
 		break;
 	case sco_gseg_owner:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/sgi-gru/grukservices.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/sgi-gru/grukservices.c
@@ -257,7 +257,6 @@
 	int lcpu;
 
 	BUG_ON(dsr_bytes > GRU_NUM_KERNEL_DSR_BYTES);
-	preempt_disable();
 	bs = gru_lock_kernel_context(-1);
 	lcpu = uv_blade_processor_id();
 	*cb = bs->kernel_cb + lcpu * GRU_HANDLE_STRIDE;
@@ -271,7 +270,6 @@
 static void gru_free_cpu_resources(void *cb, void *dsr)
 {
 	gru_unlock_kernel_context(uv_numa_blade_id());
-	preempt_enable();
 }
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/sgi-gru/grumain.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/sgi-gru/grumain.c
@@ -716,9 +716,10 @@
  * chiplet. Misassignment can occur if the process migrates to a different
  * blade or if the user changes the selected blade/chiplet.
  */
-void gru_check_context_placement(struct gru_thread_state *gts)
+int gru_check_context_placement(struct gru_thread_state *gts)
 {
 	struct gru_state *gru;
+	int ret = 0;
 
 	/*
 	 * If the current task is the context owner, verify that the
@@ -726,15 +727,23 @@
 	 * references. Pthread apps use non-owner references to the CBRs.
 	 */
 	gru = gts->ts_gru;
+	/*
+	 * If gru or gts->ts_tgid_owner isn't initialized properly, return
+	 * success to indicate that the caller does not need to unload the
+	 * gru context.The caller is responsible for their inspection and
+	 * reinitialization if needed.
+	 */
 	if (!gru || gts->ts_tgid_owner != current->tgid)
-		return;
+		return ret;
 
 	if (!gru_check_chiplet_assignment(gru, gts)) {
 		STAT(check_context_unload);
-		gru_unload_context(gts, 1);
+		ret = -EINVAL;
 	} else if (gru_retarget_intr(gts)) {
 		STAT(check_context_retarget_intr);
 	}
+
+	return ret;
 }
 
 
@@ -932,14 +941,16 @@
 
 again:
 	mutex_lock(&gts->ts_ctxlock);
-	preempt_disable();
 
-	gru_check_context_placement(gts);
+	if (gru_check_context_placement(gts)) {
+		mutex_unlock(&gts->ts_ctxlock);
+		gru_unload_context(gts, 1);
+		return VM_FAULT_NOPAGE;
+	}
 
 	if (!gts->ts_gru) {
 		STAT(load_user_context);
 		if (!gru_assign_gru_context(gts)) {
-			preempt_enable();
 			mutex_unlock(&gts->ts_ctxlock);
 			set_current_state(TASK_INTERRUPTIBLE);
 			schedule_timeout(GRU_ASSIGN_DELAY);  /* true hack ZZZ */
@@ -955,7 +966,6 @@
 				vma->vm_page_prot);
 	}
 
-	preempt_enable();
 	mutex_unlock(&gts->ts_ctxlock);
 
 	return VM_FAULT_NOPAGE;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/sgi-gru/grutables.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/sgi-gru/grutables.h
@@ -637,7 +637,7 @@
 extern int gru_user_unload_context(unsigned long arg);
 extern int gru_get_exception_detail(unsigned long arg);
 extern int gru_set_context_option(unsigned long address);
-extern void gru_check_context_placement(struct gru_thread_state *gts);
+extern int gru_check_context_placement(struct gru_thread_state *gts);
 extern int gru_cpu_fault_map_id(void);
 extern struct vm_area_struct *gru_find_vma(unsigned long vaddr);
 extern void gru_flush_all_tlb(struct gru_state *gru);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/sgi-gru/grutlbpurge.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/sgi-gru/grutlbpurge.c
@@ -65,7 +65,6 @@
 	struct gru_tlb_global_handle *tgh;
 	int n;
 
-	preempt_disable();
 	if (uv_numa_blade_id() == gru->gs_blade_id)
 		n = get_on_blade_tgh(gru);
 	else
@@ -79,7 +78,6 @@
 static void get_unlock_tgh_handle(struct gru_tlb_global_handle *tgh)
 {
 	unlock_tgh_handle(tgh);
-	preempt_enable();
 }
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/sgi-xp/xpc_partition.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/sgi-xp/xpc_partition.c
@@ -290,7 +290,7 @@
 
 		/* cancel the timer function, provided it's not us */
 		if (!in_interrupt())
-			del_singleshot_timer_sync(&part->disengage_timer);
+			del_timer_sync(&part->disengage_timer);
 
 		DBUG_ON(part->act_state != XPC_P_AS_DEACTIVATING &&
 			part->act_state != XPC_P_AS_INACTIVE);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/ti-st/st_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/ti-st/st_core.c
@@ -15,6 +15,7 @@
 #include <linux/skbuff.h>
 
 #include <linux/ti_wilink_st.h>
+#include <linux/netdevice.h>
 
 extern void st_kim_recv(void *, const unsigned char *, long);
 void st_int_recv(void *, const unsigned char *, long);
@@ -423,7 +424,7 @@
 	case ST_LL_AWAKE_TO_ASLEEP:
 		pr_err("ST LL is illegal state(%ld),"
 			   "purging received skb.", st_ll_getstate(st_gdata));
-		kfree_skb(skb);
+		dev_kfree_skb_irq(skb);
 		break;
 	case ST_LL_ASLEEP:
 		skb_queue_tail(&st_gdata->tx_waitq, skb);
@@ -432,7 +433,7 @@
 	default:
 		pr_err("ST LL is illegal state(%ld),"
 			   "purging received skb.", st_ll_getstate(st_gdata));
-		kfree_skb(skb);
+		dev_kfree_skb_irq(skb);
 		break;
 	}
 
@@ -486,7 +487,7 @@
 				spin_unlock_irqrestore(&st_data->lock, flags);
 				break;
 			}
-			kfree_skb(skb);
+			dev_kfree_skb_irq(skb);
 			spin_unlock_irqrestore(&st_data->lock, flags);
 		}
 		/* if wake-up is set in another context- restart sending */
@@ -708,7 +709,6 @@
  */
 static int st_tty_open(struct tty_struct *tty)
 {
-	int err = 0;
 	struct st_data_s *st_gdata;
 	pr_info("%s ", __func__);
 
@@ -731,7 +731,8 @@
 	 */
 	st_kim_complete(st_gdata->kim_data);
 	pr_debug("done %s", __func__);
-	return err;
+
+	return 0;
 }
 
 static void st_tty_close(struct tty_struct *tty)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/tifm_7xx1.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/tifm_7xx1.c
@@ -190,7 +190,7 @@
 				spin_unlock_irqrestore(&fm->lock, flags);
 			}
 			if (sock)
-				tifm_free_device(&sock->dev);
+				put_device(&sock->dev);
 		}
 		spin_lock_irqsave(&fm->lock, flags);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/vmw_vmci/vmci_context.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/vmw_vmci/vmci_context.c
@@ -743,7 +743,7 @@
 			return VMCI_ERROR_MORE_DATA;
 		}
 
-		dbells = kmalloc(data_size, GFP_ATOMIC);
+		dbells = kzalloc(data_size, GFP_ATOMIC);
 		if (!dbells)
 			return VMCI_ERROR_NO_MEM;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/vmw_vmci/vmci_datagram.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/vmw_vmci/vmci_datagram.c
@@ -234,7 +234,8 @@
 
 			dg_info->in_dg_host_queue = true;
 			dg_info->entry = dst_entry;
-			memcpy(&dg_info->msg, dg, dg_size);
+			dg_info->msg = *dg;
+			memcpy(&dg_info->msg_payload, dg + 1, dg->payload_size);
 
 			INIT_WORK(&dg_info->work, dg_delayed_dispatch);
 			schedule_work(&dg_info->work);
@@ -377,7 +378,8 @@
 
 		dg_info->in_dg_host_queue = false;
 		dg_info->entry = dst_entry;
-		memcpy(&dg_info->msg, dg, VMCI_DG_SIZE(dg));
+		dg_info->msg = *dg;
+		memcpy(&dg_info->msg_payload, dg + 1, dg->payload_size);
 
 		INIT_WORK(&dg_info->work, dg_delayed_dispatch);
 		schedule_work(&dg_info->work);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/vmw_vmci/vmci_doorbell.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/vmw_vmci/vmci_doorbell.c
@@ -326,7 +326,7 @@
 bool vmci_dbell_register_notification_bitmap(u64 bitmap_ppn)
 {
 	int result;
-	struct vmci_notify_bm_set_msg bitmap_set_msg;
+	struct vmci_notify_bm_set_msg bitmap_set_msg = { };
 
 	bitmap_set_msg.hdr.dst = vmci_make_handle(VMCI_HYPERVISOR_CONTEXT_ID,
 						  VMCI_SET_NOTIFY_BITMAP);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/vmw_vmci/vmci_event.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/vmw_vmci/vmci_event.c
@@ -9,6 +9,7 @@
 #include <linux/vmw_vmci_api.h>
 #include <linux/list.h>
 #include <linux/module.h>
+#include <linux/nospec.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/rculist.h>
@@ -86,9 +87,12 @@
 {
 	struct vmci_subscription *cur;
 	struct list_head *subscriber_list;
+	u32 sanitized_event, max_vmci_event;
 
 	rcu_read_lock();
-	subscriber_list = &subscriber_array[event_msg->event_data.event];
+	max_vmci_event = ARRAY_SIZE(subscriber_array);
+	sanitized_event = array_index_nospec(event_msg->event_data.event, max_vmci_event);
+	subscriber_list = &subscriber_array[sanitized_event];
 	list_for_each_entry_rcu(cur, subscriber_list, node) {
 		cur->callback(cur->id, &event_msg->event_data,
 			      cur->callback_data);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/vmw_vmci/vmci_guest.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/vmw_vmci/vmci_guest.c
@@ -168,7 +168,7 @@
 				VMCI_UTIL_NUM_RESOURCES * sizeof(u32);
 	struct vmci_datagram *check_msg;
 
-	check_msg = kmalloc(msg_size, GFP_KERNEL);
+	check_msg = kzalloc(msg_size, GFP_KERNEL);
 	if (!check_msg) {
 		dev_err(&pdev->dev, "%s: Insufficient memory\n", __func__);
 		return -ENOMEM;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/vmw_vmci/vmci_host.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/vmw_vmci/vmci_host.c
@@ -160,10 +160,16 @@
 static __poll_t vmci_host_poll(struct file *filp, poll_table *wait)
 {
 	struct vmci_host_dev *vmci_host_dev = filp->private_data;
-	struct vmci_ctx *context = vmci_host_dev->context;
+	struct vmci_ctx *context;
 	__poll_t mask = 0;
 
 	if (vmci_host_dev->ct_type == VMCIOBJ_CONTEXT) {
+		/*
+		 * Read context only if ct_type == VMCIOBJ_CONTEXT to make
+		 * sure that context is initialized
+		 */
+		context = vmci_host_dev->context;
+
 		/* Check for VMCI calls to this VM context. */
 		if (wait)
 			poll_wait(filp, &context->host_context.wait_queue,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/vmw_vmci/vmci_queue_pair.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/vmw_vmci/vmci_queue_pair.c
@@ -537,6 +537,9 @@
 
 	queue_page_size = num_pages * sizeof(*queue->kernel_if->u.h.page);
 
+	if (queue_size + queue_page_size > KMALLOC_MAX_SIZE)
+		return NULL;
+
 	queue = kzalloc(queue_size + queue_page_size, GFP_KERNEL);
 	if (queue) {
 		queue->q_header = NULL;
@@ -630,7 +633,7 @@
 
 	for (i = 0; i < num_pages; i++) {
 		if (dirty)
-			set_page_dirty(pages[i]);
+			set_page_dirty_lock(pages[i]);
 
 		put_page(pages[i]);
 		pages[i] = NULL;
@@ -657,8 +660,9 @@
 	if (retval < (int)produce_q->kernel_if->num_pages) {
 		pr_debug("get_user_pages_fast(produce) failed (retval=%d)",
 			retval);
-		qp_release_pages(produce_q->kernel_if->u.h.header_page,
-				 retval, false);
+		if (retval > 0)
+			qp_release_pages(produce_q->kernel_if->u.h.header_page,
+					retval, false);
 		err = VMCI_ERROR_NO_MEM;
 		goto out;
 	}
@@ -670,8 +674,9 @@
 	if (retval < (int)consume_q->kernel_if->num_pages) {
 		pr_debug("get_user_pages_fast(consume) failed (retval=%d)",
 			retval);
-		qp_release_pages(consume_q->kernel_if->u.h.header_page,
-				 retval, false);
+		if (retval > 0)
+			qp_release_pages(consume_q->kernel_if->u.h.header_page,
+					retval, false);
 		qp_release_pages(produce_q->kernel_if->u.h.header_page,
 				 produce_q->kernel_if->num_pages, false);
 		err = VMCI_ERROR_NO_MEM;
@@ -847,6 +852,7 @@
 	u32 context_id = vmci_get_context_id();
 	struct vmci_event_qp ev;
 
+	memset(&ev, 0, sizeof(ev));
 	ev.msg.hdr.dst = vmci_make_handle(context_id, VMCI_EVENT_HANDLER);
 	ev.msg.hdr.src = vmci_make_handle(VMCI_HYPERVISOR_CONTEXT_ID,
 					  VMCI_CONTEXT_RESOURCE_ID);
@@ -1460,6 +1466,7 @@
 	 * kernel.
 	 */
 
+	memset(&ev, 0, sizeof(ev));
 	ev.msg.hdr.dst = vmci_make_handle(peer_id, VMCI_EVENT_HANDLER);
 	ev.msg.hdr.src = vmci_make_handle(VMCI_HYPERVISOR_CONTEXT_ID,
 					  VMCI_CONTEXT_RESOURCE_ID);
@@ -2233,7 +2240,8 @@
 
 	result = VMCI_SUCCESS;
 
-	if (context_id != VMCI_HOST_CONTEXT_ID) {
+	if (context_id != VMCI_HOST_CONTEXT_ID &&
+	    !QPBROKERSTATE_HAS_MEM(entry)) {
 		struct vmci_qp_page_store page_store;
 
 		page_store.pages = guest_mem;
@@ -2340,7 +2348,8 @@
 		goto out;
 	}
 
-	if (context_id != VMCI_HOST_CONTEXT_ID) {
+	if (context_id != VMCI_HOST_CONTEXT_ID &&
+	    QPBROKERSTATE_HAS_MEM(entry)) {
 		qp_acquire_queue_mutex(entry->produce_q);
 		result = qp_save_headers(entry);
 		if (result < VMCI_SUCCESS)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/vmw_vmci/vmci_resource.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/vmw_vmci/vmci_resource.c
@@ -144,7 +144,8 @@
 	spin_lock(&vmci_resource_table.lock);
 
 	hlist_for_each_entry(r, &vmci_resource_table.entries[idx], node) {
-		if (vmci_handle_is_equal(r->handle, resource->handle)) {
+		if (vmci_handle_is_equal(r->handle, resource->handle) &&
+		    resource->type == r->type) {
 			hlist_del_init_rcu(&r->node);
 			break;
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/xilinx-ai-engine/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/xilinx-ai-engine/Makefile
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Makefile for Xilinx AI engine device driver
+#
+
+obj-$(CONFIG_XILINX_AIE)	+= xilinx-aie.o
+
+xilinx-aie-$(CONFIG_XILINX_AIE) := ai-engine-aie.o \
+				   ai-engine-clock.o \
+				   ai-engine-dev.o \
+				   ai-engine-dma.o \
+				   ai-engine-fpga.o \
+				   ai-engine-interrupt.o \
+				   ai-engine-mem.o \
+				   ai-engine-part.o \
+				   ai-engine-res.o \
+				   ai-engine-reset.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/xilinx-ai-engine/ai-engine-aie.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/xilinx-ai-engine/ai-engine-aie.c
@@ -0,0 +1,883 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx AI Engine driver AIE device specific implementation
+ *
+ * Copyright (C) 2020 Xilinx, Inc.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/firmware/xlnx-zynqmp.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/xlnx-ai-engine.h>
+
+#include "ai-engine-internal.h"
+
+#define KBYTES(n)	((n) * 1024)
+
+#define AIE_ARRAY_SHIFT		30U
+#define AIE_COL_SHIFT		23U
+#define AIE_ROW_SHIFT		18U
+
+#define NUM_MEMS_PER_TILE	2U
+
+/*
+ * Registers offsets
+ */
+#define AIE_SHIMNOC_L2INTR_MASK_REGOFF		0x00015000U
+#define AIE_SHIMNOC_L2INTR_INTR_REGOFF		0x00015010U
+#define AIE_SHIMNOC_DMA_BD0_ADDRLOW_REGOFF	0x0001d000U
+#define AIE_SHIMNOC_DMA_BD15_PACKET_REGOFF	0x0001d13cU
+#define AIE_SHIMNOC_AXIMM_REGOFF		0x0001e020U
+#define AIE_SHIMPL_L1INTR_MASK_A_REGOFF		0x00035000U
+#define AIE_SHIMPL_L1INTR_BLOCK_NORTH_B_REGOFF	0x00035050U
+#define AIE_SHIMPL_CLKCNTR_REGOFF		0x00036040U
+#define AIE_SHIMPL_COLRESET_REGOFF		0x00036048U
+#define AIE_SHIMPL_RESET_REGOFF			0x0003604cU
+#define AIE_SHIMPL_GROUP_ERROR_REGOFF		0x0003450cU
+#define AIE_TILE_CORE_CLKCNTR_REGOFF		0x00036040U
+#define AIE_TILE_CORE_GROUP_ERROR_REGOFF	0x00034510U
+#define AIE_TILE_MEM_GROUP_ERROR_REGOFF		0x00014514U
+
+/*
+ * Register masks
+ */
+#define AIE_SHIMPL_SHIMRST_MASK			0x1U
+#define AIE_SHIMPL_COLRST_MASK			0x1U
+#define AIE_SHIMPL_CLKCNTR_COLBUF_MASK		0x1U
+#define AIE_SHIMPL_CLKCNTR_NEXTCLK_MASK		BIT(1)
+#define AIE_TILE_CLKCNTR_COLBUF_MASK		BIT(0)
+#define AIE_TILE_CLKCNTR_NEXTCLK_MASK		BIT(1)
+
+/*
+ * AI engine SHIM reset ID.
+ * TODO: it should follow the Linux reset framework. The ID should be in the
+ * device tree. However, as versal resets is not ready, we hardcode it in the
+ * driver.
+ */
+#define VERSAL_PM_RST_AIE_SHIM_ID			0xc10405fU
+
+static const struct aie_tile_regs aie_kernel_regs[] = {
+	/* SHIM AXI MM Config */
+	{.attribute = AIE_TILE_TYPE_SHIMNOC << AIE_REGS_ATTR_TILE_TYPE_SHIFT,
+	 .soff = AIE_SHIMNOC_AXIMM_REGOFF,
+	 .eoff = AIE_SHIMNOC_AXIMM_REGOFF,
+	},
+	/* SHIM DMA ADDRESS range */
+	{.attribute = AIE_TILE_TYPE_SHIMNOC << AIE_REGS_ATTR_TILE_TYPE_SHIFT,
+	 .soff = AIE_SHIMNOC_DMA_BD0_ADDRLOW_REGOFF,
+	 .eoff = AIE_SHIMNOC_DMA_BD15_PACKET_REGOFF,
+	},
+	/* SHIM 2nd level interrupt controller */
+	{.attribute = AIE_TILE_TYPE_SHIMNOC << AIE_REGS_ATTR_TILE_TYPE_SHIFT,
+	 .soff = AIE_SHIMNOC_L2INTR_MASK_REGOFF,
+	 .eoff = AIE_SHIMNOC_L2INTR_INTR_REGOFF,
+	},
+	/* SHIM 1st level interrupt controller */
+	{.attribute = (AIE_TILE_TYPE_SHIMPL | AIE_TILE_TYPE_SHIMNOC) <<
+		      AIE_REGS_ATTR_TILE_TYPE_SHIFT,
+	 .soff = AIE_SHIMPL_L1INTR_MASK_A_REGOFF,
+	 .eoff = AIE_SHIMPL_L1INTR_BLOCK_NORTH_B_REGOFF,
+	},
+	/* SHIM column reset */
+	{.attribute = (AIE_TILE_TYPE_SHIMPL | AIE_TILE_TYPE_SHIMNOC) <<
+		      AIE_REGS_ATTR_TILE_TYPE_SHIFT,
+	 .soff = AIE_SHIMPL_COLRESET_REGOFF,
+	 .eoff = AIE_SHIMPL_COLRESET_REGOFF,
+	},
+	/* SHIM reset Enable */
+	{.attribute = (AIE_TILE_TYPE_SHIMPL | AIE_TILE_TYPE_SHIMNOC) <<
+		      AIE_REGS_ATTR_TILE_TYPE_SHIFT,
+	 .soff = AIE_SHIMPL_RESET_REGOFF,
+	 .eoff = AIE_SHIMPL_RESET_REGOFF,
+	},
+	/* SHIM clock control */
+	{.attribute = (AIE_TILE_TYPE_SHIMPL | AIE_TILE_TYPE_SHIMNOC) <<
+		      AIE_REGS_ATTR_TILE_TYPE_SHIFT,
+	 .soff = AIE_SHIMPL_CLKCNTR_REGOFF,
+	 .eoff = AIE_SHIMPL_CLKCNTR_REGOFF,
+	},
+	/* SHIM group error enable */
+	{.attribute = (AIE_TILE_TYPE_SHIMPL | AIE_TILE_TYPE_SHIMNOC) <<
+		      AIE_REGS_ATTR_TILE_TYPE_SHIFT,
+	 .soff = AIE_SHIMPL_GROUP_ERROR_REGOFF,
+	 .eoff = AIE_SHIMPL_GROUP_ERROR_REGOFF,
+	},
+	/* Tile clock control */
+	{.attribute = AIE_TILE_TYPE_TILE << AIE_REGS_ATTR_TILE_TYPE_SHIFT,
+	 .soff = AIE_TILE_CORE_CLKCNTR_REGOFF,
+	 .eoff = AIE_TILE_CORE_CLKCNTR_REGOFF,
+	},
+	/* Tile group error for core module */
+	{.attribute = AIE_TILE_TYPE_TILE << AIE_REGS_ATTR_TILE_TYPE_SHIFT,
+	 .soff = AIE_TILE_CORE_GROUP_ERROR_REGOFF,
+	 .eoff = AIE_TILE_CORE_GROUP_ERROR_REGOFF,
+	},
+	/* Tile group error for memory module */
+	{.attribute = AIE_TILE_TYPE_TILE << AIE_REGS_ATTR_TILE_TYPE_SHIFT,
+	 .soff = AIE_TILE_MEM_GROUP_ERROR_REGOFF,
+	 .eoff = AIE_TILE_MEM_GROUP_ERROR_REGOFF,
+	},
+};
+
+static const struct aie_single_reg_field aie_col_rst = {
+	.mask = AIE_SHIMPL_COLRST_MASK,
+	.regoff = AIE_SHIMPL_COLRESET_REGOFF,
+};
+
+static const struct aie_single_reg_field aie_col_clkbuf = {
+	.mask = AIE_SHIMPL_CLKCNTR_COLBUF_MASK,
+	.regoff = AIE_SHIMPL_CLKCNTR_REGOFF,
+};
+
+static const struct aie_dma_attr aie_shimdma = {
+	.laddr = {
+		.mask = 0xffffffffU,
+		.regoff = 0U,
+	},
+	.haddr = {
+		.mask = 0xffff0000U,
+		.regoff = 0x8U,
+	},
+	.buflen = {
+		.mask = 0xffffffffU,
+		.regoff = 0x4U,
+	},
+	.bd_regoff = 0x0001d000U,
+	.num_bds = 16,
+	.bd_len = 0x14U,
+};
+
+static const struct aie_event_attr aie_pl_event = {
+	.bc_event = {
+		.mask = GENMASK(6, 0),
+		.regoff = 0x0U,
+	},
+	.group_error = {
+		.mask = GENMASK(10, 0),
+		.regoff = 0xcU,
+	},
+	.bc_regoff = 0x34010U,
+	.status_regoff = 0x34200U,
+	.group_regoff = 0x34500U,
+	.base_error_event = 62U,
+	.num_broadcasts = 16U,
+	.base_bc_event = 107U,
+	.num_events = 128U,
+};
+
+static const struct aie_event_attr aie_mem_event = {
+	.bc_event = {
+		.mask = GENMASK(6, 0),
+		.regoff = 0x0U,
+	},
+	.group_error = {
+		.mask = GENMASK(13, 0),
+		.regoff = 0x14U,
+	},
+	.bc_regoff = 0x14010U,
+	.status_regoff = 0x14200U,
+	.group_regoff = 0x14500U,
+	.base_error_event = 87U,
+	.num_broadcasts = 16U,
+	.base_bc_event = 107U,
+	.num_events = 128U,
+};
+
+static const struct aie_event_attr aie_core_event = {
+	.bc_event = {
+		.mask = GENMASK(6, 0),
+		.regoff = 0x0U,
+	},
+	.group_error = {
+		.mask = GENMASK(21, 0),
+		.regoff = 0x10U,
+	},
+	.bc_regoff = 0x34010U,
+	.status_regoff = 0x34200U,
+	.group_regoff = 0x34500U,
+	.base_error_event = 48U,
+	.num_broadcasts = 16U,
+	.base_bc_event = 107U,
+	.num_events = 128U,
+};
+
+static const struct aie_l1_intr_ctrl_attr aie_l1_intr_ctrl = {
+	.swa_status = {
+		.mask = GENMASK(19, 0),
+		.regoff = 0xcU,
+	},
+	.swb_status = {
+		.mask = GENMASK(19, 0),
+		.regoff = 0x3cU,
+	},
+	.swa_event = {
+		.mask = GENMASK(6, 0),
+		.regoff = 0x14U,
+	},
+	.swb_event = {
+		.mask = GENMASK(6, 0),
+		.regoff = 0x44U,
+	},
+	.regoff = 0x35000U,
+	.event_lsb = 8,
+	.num_broadcasts = 0x14U,
+};
+
+static const struct aie_l2_intr_ctrl_attr aie_l2_intr_ctrl = {
+	.mask = {
+		.mask = GENMASK(15, 0),
+		.regoff = 0x0U,
+	},
+	.enable = {
+		.mask = GENMASK(15, 0),
+		.regoff = 0x4U,
+	},
+	.disable = {
+		.mask = GENMASK(15, 0),
+		.regoff = 0x8U,
+	},
+	.status = {
+		.mask = GENMASK(15, 0),
+		.regoff = 0xcU,
+	},
+	.regoff = 0x15000U,
+	.num_broadcasts = 0x10U,
+};
+
+static const struct aie_event_prop aie_core_stream_error_prop[] = {
+	{
+		.event = 54U,
+		.event_str = "CORE: TLAST in WSS words 0-2",
+	},
+	{
+		.event = 57U,
+		.event_str = "CORE: Control packet error",
+	},
+	{
+		.event = 56U,
+		.event_str = "CORE: Stream packet parity error",
+	},
+};
+
+static const struct aie_event_prop aie_core_inst_error_prop[] = {
+	{
+		.event = 59U,
+		.event_str = "CORE: Instruction decompression error",
+	},
+};
+
+static const struct aie_event_prop aie_core_ecc_error_prop[] = {
+	{
+		.event = 64U,
+		.event_str = "CORE: PM ECC error 2-bit",
+	},
+	{
+		.event = 62U,
+		.event_str = "CORE: PM ECC error scrub 2-bit",
+	},
+};
+
+static const struct aie_event_prop aie_core_access_error_prop[] = {
+	{
+		.event = 55U,
+		.event_str = "CORE: PM reg access failure",
+	},
+	{
+		.event = 66U,
+		.event_str = "CORE: DM access to unavailable",
+	},
+	{
+		.event = 65U,
+		.event_str = "CORE: PM address out of range",
+	},
+	{
+		.event = 60U,
+		.event_str = "CORE: DM address out of range",
+	},
+};
+
+static const struct aie_event_prop aie_core_lock_error_prop[] = {
+	{
+		.event = 67U,
+		.event_str = "CORE: Lock access to unavailable",
+	},
+};
+
+static const struct aie_event_prop aie_core_bus_error_prop[] = {
+	{
+		.event = 58U,
+		.event_str = "CORE: AXI-MM slave error",
+	},
+};
+
+static const struct aie_event_prop aie_mem_ecc_error_prop[] = {
+	{
+		.event = 88U,
+		.event_str = "MEM: DM ECC error scrub 2-bit",
+	},
+	{
+		.event = 90U,
+		.event_str = "MEM: DM ECC error 2-bit",
+	},
+};
+
+static const struct aie_event_prop aie_mem_parity_error_prop[] = {
+	{
+		.event = 91U,
+		.event_str = " MEM: DM parity error bank 2",
+	},
+	{
+		.event = 92U,
+		.event_str = " MEM: DM parity error bank 3",
+	},
+	{
+		.event = 93U,
+		.event_str = " MEM: DM parity error bank 4",
+	},
+	{
+		.event = 94U,
+		.event_str = " MEM: DM parity error bank 5",
+	},
+	{
+		.event = 95U,
+		.event_str = " MEM: DM parity error bank 6",
+	},
+	{
+		.event = 96U,
+		.event_str = " MEM: DM parity error bank 7",
+	},
+};
+
+static const struct aie_event_prop aie_mem_dma_error_prop[] = {
+	{
+		.event = 97U,
+		.event_str = " MEM: DMA S2MM 0 error",
+	},
+	{
+		.event = 98U,
+		.event_str = " MEM: DMA S2MM 1 error",
+	},
+	{
+		.event = 99U,
+		.event_str = " MEM: DMA MM2S 0 error",
+	},
+	{
+		.event = 100U,
+		.event_str = " MEM: DMA MM2S 1 error",
+	},
+};
+
+static const struct aie_event_prop aie_shim_bus_error_prop[] = {
+	{
+		.event = 62U,
+		.event_str = "SHIM: AXI-MM slave tile error",
+	},
+};
+
+static const struct aie_event_prop aie_shim_stream_error_prop[] = {
+	{
+		.event = 63U,
+		.event_str = "SHIM: Control packet error",
+	},
+	{
+		.event = 64U,
+		.event_str = "SHIM: AXI-MM decode NSU error",
+	},
+	{
+		.event = 65U,
+		.event_str = "SHIM: AXI-MM slave NSU error",
+	},
+	{
+		.event = 66U,
+		.event_str = "SHIM: AXI-MM unsupported traffic",
+	},
+	{
+		.event = 67U,
+		.event_str = "SHIM: AXI-MM unsecure access in secure mode",
+	},
+	{
+		.event = 68U,
+		.event_str = "SHIM: AXI-MM byte strobe error",
+	},
+};
+
+static const struct aie_event_prop aie_shim_dma_error_prop[] = {
+	{
+		.event = 69U,
+		.event_str = "SHIM: DMA S2MM 0 error",
+	},
+	{
+		.event = 70U,
+		.event_str = "SHIM: DMA S2MM 1 error",
+	},
+	{
+		.event = 71U,
+		.event_str = "SHIM: DMA MM2S 0 error",
+	},
+	{
+		.event = 72U,
+		.event_str = "SHIM: DMA MM2S 1 error",
+	},
+};
+
+static const struct aie_err_category aie_core_err_category[] = {
+	{
+		/* AIE_ERROR_CATEGORY_STREAM */
+		.err_category = AIE_ERROR_CATEGORY_STREAM,
+		.num_events = ARRAY_SIZE(aie_core_stream_error_prop),
+		.prop = aie_core_stream_error_prop,
+	},
+	{
+		/* AIE_ERROR_CATEGORY_ACCESS */
+		.err_category = AIE_ERROR_CATEGORY_ACCESS,
+		.num_events = ARRAY_SIZE(aie_core_access_error_prop),
+		.prop = aie_core_access_error_prop,
+	},
+	{
+		/* AIE_ERROR_CATEGORY_BUS */
+		.err_category = AIE_ERROR_CATEGORY_BUS,
+		.num_events = ARRAY_SIZE(aie_core_bus_error_prop),
+		.prop = aie_core_bus_error_prop,
+	},
+	{
+		/* AIE_ERROR_CATEGORY_INSTRUCTION */
+		.err_category = AIE_ERROR_CATEGORY_INSTRUCTION,
+		.num_events = ARRAY_SIZE(aie_core_inst_error_prop),
+		.prop = aie_core_inst_error_prop,
+	},
+	{
+		/* AIE_ERROR_CATEGORY_ECC */
+		.err_category = AIE_ERROR_CATEGORY_ECC,
+		.num_events = ARRAY_SIZE(aie_core_ecc_error_prop),
+		.prop = aie_core_ecc_error_prop,
+	},
+	{
+		/* AIE_ERROR_CATEGORY_LOCK */
+		.err_category = AIE_ERROR_CATEGORY_LOCK,
+		.num_events = ARRAY_SIZE(aie_core_lock_error_prop),
+		.prop = aie_core_lock_error_prop,
+	},
+};
+
+static const struct aie_err_category aie_mem_err_category[] = {
+	{
+		/* AIE_ERROR_CATEGORY_ECC */
+		.err_category = AIE_ERROR_CATEGORY_ECC,
+		.num_events = ARRAY_SIZE(aie_mem_ecc_error_prop),
+		.prop = aie_mem_ecc_error_prop,
+	},
+	{
+		/* AIE_ERROR_CATEGORY_MEM_PARITY */
+		.err_category = AIE_ERROR_CATEGORY_MEM_PARITY,
+		.num_events = ARRAY_SIZE(aie_mem_parity_error_prop),
+		.prop = aie_mem_parity_error_prop,
+	},
+	{
+		/* AIE_ERROR_CATEGORY_DMA */
+		.err_category = AIE_ERROR_CATEGORY_DMA,
+		.num_events = ARRAY_SIZE(aie_mem_dma_error_prop),
+		.prop = aie_mem_dma_error_prop,
+	},
+};
+
+static const struct aie_err_category aie_shim_err_category[] = {
+	{
+		/* AIE_ERROR_CATEGORY_BUS */
+		.err_category = AIE_ERROR_CATEGORY_BUS,
+		.num_events = ARRAY_SIZE(aie_shim_bus_error_prop),
+		.prop = aie_shim_bus_error_prop,
+	},
+	{
+		/* AIE_ERROR_CATEGORY_STREAM */
+		.err_category = AIE_ERROR_CATEGORY_STREAM,
+		.num_events = ARRAY_SIZE(aie_shim_stream_error_prop),
+		.prop = aie_shim_stream_error_prop,
+	},
+	{
+		/* AIE_ERROR_CATEGORY_DMA */
+		.err_category = AIE_ERROR_CATEGORY_DMA,
+		.num_events = ARRAY_SIZE(aie_shim_dma_error_prop),
+		.prop = aie_shim_dma_error_prop,
+	},
+};
+
+static const struct aie_error_attr aie_core_error = {
+	.num_err_categories = ARRAY_SIZE(aie_core_err_category),
+	.err_category = aie_core_err_category,
+};
+
+static const struct aie_error_attr aie_mem_error = {
+	.num_err_categories = ARRAY_SIZE(aie_mem_err_category),
+	.err_category = aie_mem_err_category,
+};
+
+static const struct aie_error_attr aie_shim_error = {
+	.num_err_categories = ARRAY_SIZE(aie_shim_err_category),
+	.err_category = aie_shim_err_category,
+};
+
+static u32 aie_get_tile_type(struct aie_location *loc)
+{
+	if (loc->row)
+		return AIE_TILE_TYPE_TILE;
+	/* SHIM row */
+	if ((loc->col % 4) < 2)
+		return AIE_TILE_TYPE_SHIMPL;
+
+	return AIE_TILE_TYPE_SHIMNOC;
+}
+
+static unsigned int aie_get_mem_info(struct aie_range *range,
+				     struct aie_part_mem *pmem)
+{
+	unsigned int i;
+
+	if (range->start.row + range->size.row <= 1) {
+		/* SHIM row only, no memories in this range */
+		return 0;
+	}
+	if (!pmem)
+		return NUM_MEMS_PER_TILE;
+
+	for (i = 0; i < NUM_MEMS_PER_TILE; i++) {
+		struct aie_mem *mem = &pmem[i].mem;
+
+		memcpy(&mem->range, range, sizeof(*range));
+		if (!mem->range.start.row) {
+			mem->range.start.row = 1;
+			mem->range.size.row--;
+		}
+	}
+	/* Setup tile data memory information */
+	pmem[0].mem.offset = 0;
+	pmem[0].mem.size = KBYTES(32);
+	/* Setup program memory information */
+	pmem[1].mem.offset = 0x20000;
+	pmem[1].mem.size = KBYTES(16);
+
+	return NUM_MEMS_PER_TILE;
+}
+
+/**
+ * aie_set_shim_reset() - Set AI engine SHIM reset
+ * @adev: AI engine device
+ * @range: range of AI engine tiles
+ * @assert: true to set reset, false to unset reset
+ */
+static void aie_set_shim_reset(struct aie_device *adev,
+			       struct aie_range *range, bool assert)
+{
+	u32 c;
+	u32 val;
+	struct aie_location loc;
+
+	val = FIELD_PREP(AIE_SHIMPL_SHIMRST_MASK, (assert ? 1 : 0));
+	loc.row = 0;
+	for (c = range->start.col; c < range->start.col + range->size.col;
+	     c++) {
+		u32 regoff;
+
+		loc.col = c;
+		regoff = aie_cal_regoff(adev, loc, AIE_SHIMPL_RESET_REGOFF);
+		iowrite32(val, adev->base + regoff);
+	}
+}
+
+static int aie_reset_shim(struct aie_device *adev, struct aie_range *range)
+{
+	int ret;
+
+	/* Enable shim reset of each column */
+	aie_set_shim_reset(adev, range, true);
+
+	/* Assert shim reset of AI engine array */
+	ret = adev->eemi_ops->reset_assert(VERSAL_PM_RST_AIE_SHIM_ID,
+					   PM_RESET_ACTION_ASSERT);
+	if (ret < 0) {
+		dev_err(&adev->dev, "failed to assert SHIM reset.\n");
+		return ret;
+	}
+
+	/* Release shim reset of AI engine array */
+	ret = adev->eemi_ops->reset_assert(VERSAL_PM_RST_AIE_SHIM_ID,
+					   PM_RESET_ACTION_RELEASE);
+	if (ret < 0) {
+		dev_err(&adev->dev, "failed to release SHIM reset.\n");
+		return ret;
+	}
+
+	/* Disable shim reset of each column */
+	aie_set_shim_reset(adev, range, false);
+
+	return 0;
+}
+
+static int aie_init_part_clk_state(struct aie_partition *apart)
+{
+	int ret, num_tiles;
+
+	num_tiles = apart->range.size.col * (apart->range.size.row - 1);
+
+	ret = aie_resource_initialize(&apart->cores_clk_state, num_tiles);
+	if (ret) {
+		dev_err(&apart->dev,
+			"failed to initialize cores clock state resource.\n");
+		return ret;
+	}
+
+	ret = aie_resource_initialize(&apart->tiles_inuse, num_tiles);
+	if (ret) {
+		dev_err(&apart->dev,
+			"failed to initialize tiles in use resource.\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int aie_scan_part_clocks(struct aie_partition *apart)
+{
+	struct aie_device *adev = apart->adev;
+	struct aie_range *range = &apart->range;
+	struct aie_location loc;
+
+	/* Clear the bitmap of cores and memories clock state */
+	aie_resource_put_region(&apart->cores_clk_state, 0,
+				apart->cores_clk_state.total);
+
+	for (loc.col = range->start.col;
+	     loc.col < range->start.col + range->size.col;
+	     loc.col++) {
+		for (loc.row = range->start.row;
+		     loc.row < range->start.row + range->size.row - 1;
+		     loc.row++) {
+			void __iomem *va;
+			u32 val, nbitpos;
+
+			/*
+			 * Reading registers of the current tile to see the next
+			 * tile is clock gated.
+			 */
+			nbitpos = loc.col * (range->size.row - 1) + loc.row;
+
+			if (aie_get_tile_type(&loc) != AIE_TILE_TYPE_TILE) {
+				/* Checks shim tile for next core tile */
+				va = adev->base +
+				     aie_cal_regoff(adev, loc,
+						    AIE_SHIMPL_CLKCNTR_REGOFF);
+				val = ioread32(va);
+
+				/*
+				 * check if the clock buffer and the next clock
+				 * tile is set, if one of them is not set, the
+				 * tiles of the column are clock gated.
+				 */
+				if (!(val & AIE_SHIMPL_CLKCNTR_COLBUF_MASK) ||
+				    !(val & AIE_SHIMPL_CLKCNTR_NEXTCLK_MASK))
+					break;
+
+				/* Set next tile in the row clock state on */
+				aie_resource_set(&apart->cores_clk_state,
+						 nbitpos, 1);
+				continue;
+			}
+
+			/* Checks core tile for next tile */
+			va = adev->base +
+			     aie_cal_regoff(adev, loc,
+					    AIE_TILE_CORE_CLKCNTR_REGOFF);
+			val = ioread32(va);
+
+			/*
+			 * If the next tile is gated, skip the rest of the
+			 * column.
+			 */
+			if (!(val & AIE_TILE_CLKCNTR_NEXTCLK_MASK))
+				break;
+
+			aie_resource_set(&apart->cores_clk_state, nbitpos, 1);
+		}
+	}
+
+	/*
+	 * Set the tiles in use bitmap.
+	 * In case of scanning, tiles which are powered on are considered as
+	 * tiles in use.
+	 */
+	bitmap_copy(apart->tiles_inuse.bitmap, apart->cores_clk_state.bitmap,
+		    apart->tiles_inuse.total);
+
+	return 0;
+}
+
+/* aie_set_col_clocks() - set clocks of a range of tiles of a column
+ * @apart: AI engine partition
+ * @range: range of tiles of a column
+ * @enable: true to enable the clock, false to disable
+ * @return: 0 for success, negative value of errors.
+ */
+static int aie_set_col_clocks(struct aie_partition *apart,
+			      struct aie_range *range, bool enable)
+{
+	struct aie_location ploc;
+	u32 startbit;
+
+	/*
+	 * check if the range is of single colum. only single column is allowed.
+	 * check if the start row is tile row, only tile rows are allowed.
+	 */
+	if (range->size.col != 1 || range->start.row < 1)
+		return -EINVAL;
+
+	ploc.col = range->start.col;
+	for (ploc.row = range->start.row - 1;
+	     ploc.row < range->start.row + range->size.row - 1;
+	     ploc.row++) {
+		struct aie_device *adev = apart->adev;
+
+		if (!ploc.row) {
+			void __iomem *va;
+			u32 val = 0;
+
+			/*
+			 * Configure SHIM clock registers to gate or
+			 * ungate next tile.
+			 */
+			if (enable)
+				val = AIE_SHIMPL_CLKCNTR_COLBUF_MASK |
+				      AIE_SHIMPL_CLKCNTR_NEXTCLK_MASK;
+			va = adev->base +
+			     aie_cal_regoff(adev, ploc,
+					    AIE_SHIMPL_CLKCNTR_REGOFF);
+			iowrite32(val, va);
+		} else {
+			void __iomem *va;
+			u32 val = 0;
+
+			/*
+			 * Configure core tile clock registers to gate
+			 * or ungate next tile.
+			 */
+			if (enable)
+				val = AIE_TILE_CLKCNTR_COLBUF_MASK |
+				      AIE_TILE_CLKCNTR_NEXTCLK_MASK;
+			va = adev->base +
+			     aie_cal_regoff(adev, ploc,
+					    AIE_TILE_CORE_CLKCNTR_REGOFF);
+			iowrite32(val, va);
+		}
+
+		/* If the tile clock is not on, jump to next column */
+		if (!enable)
+			break;
+	}
+
+	/* Update clock state bitmap */
+	startbit = range->start.col * (apart->range.size.row - 1) +
+		   range->start.row - 1;
+	if (enable)
+		aie_resource_set(&apart->cores_clk_state, startbit,
+				 range->size.row);
+	else
+		aie_resource_clear(&apart->cores_clk_state, startbit,
+				   range->size.row);
+
+	return 0;
+}
+
+static int aie_set_part_clocks(struct aie_partition *apart)
+{
+	struct aie_range *range = &apart->range, lrange;
+	struct aie_location loc;
+
+	/*
+	 * The tiles below the highest tile whose clock is on, need to have the
+	 * clock on. The first for loop is to scan the clock states bitmap to
+	 * see which tiles are required to be clocked on, and update the bitmap
+	 * to make sure the tiles below are also required to be clocked on.
+	 */
+	for (loc.col = range->start.col;
+	     loc.col < range->start.col + range->size.col;
+	     loc.col++) {
+		u32 startbit, inuse_toprow = 0, clk_toprow = 0;
+
+		startbit = loc.col * (range->size.row - 1);
+
+		for (loc.row = range->start.row + 1;
+		     loc.row < range->start.row + range->size.row;
+		     loc.row++) {
+			u32 bit = startbit + loc.row - 1;
+
+			if (aie_resource_testbit(&apart->tiles_inuse, bit))
+				inuse_toprow = loc.row;
+			if (aie_resource_testbit(&apart->cores_clk_state, bit))
+				clk_toprow = loc.row;
+		}
+
+		/* Update clock states of a column */
+		lrange.start.col = loc.col;
+		lrange.size.col = 1;
+		if (inuse_toprow < clk_toprow) {
+			lrange.start.row = inuse_toprow + 1;
+			lrange.size.row = clk_toprow - inuse_toprow;
+			aie_set_col_clocks(apart, &lrange, false);
+		} else  if (inuse_toprow > clk_toprow) {
+			lrange.start.row = clk_toprow + 1;
+			lrange.size.row = inuse_toprow - clk_toprow;
+			aie_set_col_clocks(apart, &lrange, true);
+		}
+	}
+
+	return 0;
+}
+
+static const struct aie_tile_operations aie_ops = {
+	.get_tile_type = aie_get_tile_type,
+	.get_mem_info = aie_get_mem_info,
+	.reset_shim = aie_reset_shim,
+	.init_part_clk_state = aie_init_part_clk_state,
+	.scan_part_clocks = aie_scan_part_clocks,
+	.set_part_clocks = aie_set_part_clocks,
+};
+
+/**
+ * aie_device_init() - Initialize AI engine device struct AIE specific
+ * @adev: AI engine device
+ * @return: 0 for success, negative value for failure.
+ *
+ * This function initialize the AI engine device structure device version
+ * specific elements such as register addressing related array shift,
+ * column shift, and row shift; AIE device specific device operations, device
+ * columns resource.
+ */
+int aie_device_init(struct aie_device *adev)
+{
+	int ret;
+
+	adev->array_shift = AIE_ARRAY_SHIFT;
+	adev->col_shift = AIE_COL_SHIFT;
+	adev->row_shift = AIE_ROW_SHIFT;
+	adev->ops = &aie_ops;
+	adev->num_kernel_regs = ARRAY_SIZE(aie_kernel_regs);
+	adev->kernel_regs = aie_kernel_regs;
+	adev->col_rst = &aie_col_rst;
+	adev->col_clkbuf = &aie_col_clkbuf;
+	adev->shim_dma = &aie_shimdma;
+	adev->pl_events = &aie_pl_event;
+	adev->mem_events = &aie_mem_event;
+	adev->core_events = &aie_core_event;
+	adev->l1_ctrl = &aie_l1_intr_ctrl;
+	adev->l2_ctrl = &aie_l2_intr_ctrl;
+	adev->core_errors = &aie_core_error;
+	adev->mem_errors = &aie_mem_error;
+	adev->shim_errors = &aie_shim_error;
+
+	/* Get the columns resource */
+	/* Get number of columns from AI engine memory resource */
+	ret = aie_resource_initialize(&adev->cols_res, 50);
+	if (ret)
+		dev_err(&adev->dev, "failed to initialize columns resource.\n");
+
+	return ret;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/xilinx-ai-engine/ai-engine-clock.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/xilinx-ai-engine/ai-engine-clock.c
@@ -0,0 +1,244 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx AI Engine device driver
+ *
+ * Copyright (C) 2020 Xilinx, Inc.
+ */
+
+#include "ai-engine-internal.h"
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+/**
+ * aie_part_get_clk_state_bit() - return bit position of the clock state of a
+ *				  tile
+ * @apart: AI engine partition
+ * @loc: AI engine tile location
+ * @return: bit position for success, negative value for failure
+ */
+static int aie_part_get_clk_state_bit(struct aie_partition *apart,
+				      struct aie_location *loc)
+{
+	if (apart->adev->ops->get_tile_type(loc) != AIE_TILE_TYPE_TILE)
+		return -EINVAL;
+
+	return loc->col * (apart->range.size.row - 1) + loc->row - 1;
+}
+
+/**
+ * aie_part_scan_clk_state() - scan the clock states of tiles of the AI engine
+ *			       partition
+ * @apart: AI engine partition
+ * @return: 0 for success, negative value for failure.
+ *
+ * This function will scan the clock status of both the memory and core
+ * modules.
+ */
+int aie_part_scan_clk_state(struct aie_partition *apart)
+{
+	return apart->adev->ops->scan_part_clocks(apart);
+}
+
+/**
+ * aie_part_check_clk_enable_loc() - return if clock of a tile is enabled
+ * @apart: AI engine partition
+ * @loc: AI engine tile location
+ * @return: true for enabled, false for disabled
+ */
+bool aie_part_check_clk_enable_loc(struct aie_partition *apart,
+				   struct aie_location *loc)
+{
+	int bit;
+
+	if (apart->adev->ops->get_tile_type(loc) != AIE_TILE_TYPE_TILE)
+		return true;
+
+	bit = aie_part_get_clk_state_bit(apart, loc);
+	return aie_resource_testbit(&apart->cores_clk_state, bit);
+}
+
+/**
+ * aie_part_request_tiles() - request tiles from an AI engine partition.
+ * @apart: AI engine partition
+ * @num_tiles: number of tiles to request. If it is 0, it means all tiles
+ * @locs: the AI engine tiles locations array which will be requested
+ * @return: 0 for success, negative value for failure.
+ *
+ * This function will enable clocks of the specified tiles.
+ */
+static int aie_part_request_tiles(struct aie_partition *apart, int num_tiles,
+				  struct aie_location *locs)
+{
+	if (num_tiles == 0) {
+		aie_resource_set(&apart->tiles_inuse, 0,
+				 apart->tiles_inuse.total);
+	} else {
+		u32 n;
+
+		if (!locs)
+			return -EINVAL;
+
+		for (n = 0; n < num_tiles; n++) {
+			int bit = aie_part_get_clk_state_bit(apart, &locs[n]);
+
+			if (bit >= 0)
+				aie_resource_set(&apart->tiles_inuse, bit, 1);
+		}
+	}
+
+	return apart->adev->ops->set_part_clocks(apart);
+}
+
+/**
+ * aie_part_release_tiles() - release tiles from an AI engine partition.
+ * @apart: AI engine partition
+ * @num_tiles: number of tiles to release. If it is 0, it means all tiles
+ * @locs: the AI engine tiles locations array which will be released
+ * @return: 0 for success, negative value for failure.
+ *
+ * This function will disable clocks of the specified tiles.
+ */
+static int aie_part_release_tiles(struct aie_partition *apart, int num_tiles,
+				  struct aie_location *locs)
+{
+	if (num_tiles == 0) {
+		aie_resource_clear(&apart->tiles_inuse, 0,
+				   apart->tiles_inuse.total);
+	} else {
+		u32 n;
+
+		if (!locs)
+			return -EINVAL;
+
+		for (n = 0; n < num_tiles; n++) {
+			int bit = aie_part_get_clk_state_bit(apart, &locs[n]);
+
+			if (bit >= 0)
+				aie_resource_clear(&apart->tiles_inuse, bit, 1);
+		}
+	}
+
+	return apart->adev->ops->set_part_clocks(apart);
+}
+
+/**
+ * aie_part_request_tiles_from_user() - request tiles from an AI engine
+ *					partition from user
+ * @apart: AI engine partition
+ * @user_args: user AI engine request tiles argument
+ * @return: 0 for success, negative value for failure.
+ *
+ * This function will request tiles from user request.
+ */
+int aie_part_request_tiles_from_user(struct aie_partition *apart,
+				     void __user *user_args)
+{
+	struct aie_tiles_array args;
+	struct aie_location *locs = NULL;
+	int ret;
+
+	if (copy_from_user(&args, user_args, sizeof(args)))
+		return -EFAULT;
+
+	if (args.num_tiles) {
+		u32 i;
+
+		locs = kmalloc_array(args.num_tiles, sizeof(*locs),
+				     GFP_KERNEL);
+		if (!locs)
+			return -ENOMEM;
+
+		if (copy_from_user(locs, (void __user *)args.locs,
+				   args.num_tiles * sizeof(*locs))) {
+			kfree(locs);
+			return -EFAULT;
+		}
+
+		/* update the location to absolute location */
+		for (i = 0; i < args.num_tiles; i++) {
+			if (locs[i].col > apart->range.size.col ||
+			    locs[i].row > apart->range.size.row) {
+				dev_err(&apart->dev,
+					"failed to request tiles, invalid tile(%u,%u).\n",
+					locs[i].col, locs[i].row);
+				kfree(locs);
+				return -EINVAL;
+			}
+			locs[i].col += apart->range.start.col;
+			locs[i].row += apart->range.start.row;
+		}
+	}
+
+	ret = mutex_lock_interruptible(&apart->mlock);
+	if (ret) {
+		kfree(locs);
+		return ret;
+	}
+
+	ret = aie_part_request_tiles(apart, args.num_tiles, locs);
+	mutex_unlock(&apart->mlock);
+
+	kfree(locs);
+	return ret;
+}
+
+/**
+ * aie_part_release_tiles_from_user() - release tiles from an AI engine
+ *					partition from user
+ * @apart: AI engine partition
+ * @user_args: user AI engine request tiles argument
+ * @return: 0 for success, negative value for failure.
+ *
+ * This function will release tiles from user request.
+ */
+int aie_part_release_tiles_from_user(struct aie_partition *apart,
+				     void __user *user_args)
+{
+	struct aie_tiles_array args;
+	struct aie_location *locs = NULL;
+	int ret;
+
+	if (copy_from_user(&args, user_args, sizeof(args)))
+		return -EFAULT;
+
+	if (args.num_tiles) {
+		int i;
+
+		locs = kmalloc_array(args.num_tiles, sizeof(*locs),
+				     GFP_KERNEL);
+		if (!locs)
+			return -ENOMEM;
+
+		if (copy_from_user(locs, (void __user *)args.locs,
+				   args.num_tiles * sizeof(*locs))) {
+			kfree(locs);
+			return -EFAULT;
+		}
+
+		/* update the location to absolute location */
+		for (i = 0; i < args.num_tiles; i++) {
+			if (locs[i].col > apart->range.size.col ||
+			    locs[i].row > apart->range.size.row) {
+				dev_err(&apart->dev,
+					"failed to release tiles, invalid tile(%u,%u).\n",
+					locs[i].col, locs[i].row);
+				kfree(locs);
+				return -EINVAL;
+			}
+			locs[i].col += apart->range.start.col;
+			locs[i].row += apart->range.start.row;
+		}
+	}
+
+	ret = mutex_lock_interruptible(&apart->mlock);
+	if (ret) {
+		kfree(locs);
+		return ret;
+	}
+
+	ret = aie_part_release_tiles(apart, args.num_tiles, locs);
+	mutex_unlock(&apart->mlock);
+
+	kfree(locs);
+	return ret;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/xilinx-ai-engine/ai-engine-dev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/xilinx-ai-engine/ai-engine-dev.c
@@ -0,0 +1,747 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx AI Engine device driver
+ *
+ * Copyright (C) 2020 Xilinx, Inc.
+ */
+
+#include <linux/anon_inodes.h>
+#include <linux/cdev.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/file.h>
+#include <linux/firmware/xlnx-zynqmp.h>
+#include <linux/fs.h>
+#include <linux/idr.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/xlnx-ai-engine.h>
+#include <uapi/linux/xlnx-ai-engine.h>
+
+#include "ai-engine-internal.h"
+
+#define AIE_DEV_MAX			(MINORMASK + 1)
+#define VERSAL_SILICON_REV_MASK		GENMASK(31, 28)
+
+static dev_t aie_major;
+struct class *aie_class;
+
+static DEFINE_IDA(aie_device_ida);
+static DEFINE_IDA(aie_minor_ida);
+
+/**
+ * aie_partition_fd() - returns a file descriptor for the given AI engine
+ *			partition device
+ * @apart: AI engine partition
+ * @return: file descriptor of the AI engine partition for success,
+ *	    negative value for failure.
+ *
+ * This function allocate a file descriptor for the AI engine partition
+ * export file.
+ */
+static int aie_partition_fd(struct aie_partition *apart)
+{
+	int ret;
+
+	ret = get_unused_fd_flags(O_CLOEXEC);
+	if (ret < 0) {
+		dev_err(&apart->dev,
+			"Failed to get fd for partition %u.\n",
+			apart->partition_id);
+		return ret;
+	}
+	fd_install(ret, apart->filep);
+
+	return ret;
+}
+
+/**
+ * aie_enquire_partitions() - get AI engine partitions information
+ * @adev: AI engine device
+ * @query: data struct to store the partition information
+ * @return: 0 for success, and negative value for failure.
+ */
+static int aie_enquire_partitions(struct aie_device *adev,
+				  struct aie_partition_query *query)
+{
+	struct aie_partition *apart;
+	u32 partition_cnt, i = 0;
+	int ret;
+
+	if (!query->partitions) {
+		/*
+		 * If partitions information buffer is NULL.
+		 * It is to get the number of partitions.
+		 */
+		query->partition_cnt = 0;
+		list_for_each_entry(apart, &adev->partitions, node)
+			query->partition_cnt++;
+		return 0;
+	}
+
+	partition_cnt = query->partition_cnt;
+	if (!partition_cnt)
+		return 0;
+
+	ret = mutex_lock_interruptible(&adev->mlock);
+	if (ret)
+		return ret;
+
+	list_for_each_entry(apart, &adev->partitions, node) {
+		struct aie_range_args part;
+
+		if (i >= partition_cnt)
+			break;
+		part.partition_id = apart->partition_id;
+		/*
+		 * TBD: check with PLM that if the partition is programmed
+		 * and get the UID of the image which is loaded on the AI
+		 * engine partition.
+		 */
+		part.uid = 0;
+		part.range.start.col = apart->range.start.col;
+		part.range.start.row = apart->range.start.row;
+		part.range.size.col = apart->range.size.col;
+		part.range.size.row = apart->range.size.row;
+		/* Check if partition is in use */
+		part.status = apart->status;
+		if (copy_to_user((void __user *)&query->partitions[i], &part,
+				 sizeof(part))) {
+			mutex_unlock(&adev->mlock);
+			return -EFAULT;
+		}
+		i++;
+	}
+	mutex_unlock(&adev->mlock);
+	query->partition_cnt = i;
+
+	return 0;
+}
+
+/**
+ * aie_get_partition_from_id() - get AI engine partition from id
+ * @adev: AI engine device
+ * @partition_id: partition id to check
+ * @return: partition pointer if partition exists, otherwise, NULL.
+ *
+ * This function checks defined partitions with partition id.
+ * This function expect the caller to lock mlock of @adev.
+ */
+struct aie_partition *aie_get_partition_from_id(struct aie_device *adev,
+						u32 partition_id)
+{
+	struct aie_partition *apart;
+
+	list_for_each_entry(apart, &adev->partitions, node) {
+		if (apart->partition_id == partition_id)
+			return apart;
+	}
+
+	return NULL;
+}
+
+/**
+ * aie_partition_get() - Request the specified AI engine partition
+ *
+ * @apart: AI engine partition
+ * @req: AI engine partition request information which includes image UID.
+ *	 flag to indicate if the partition will cleanup or not when releasing
+ *	 the partition.
+ * @return: 0 for success, and negative value for failure.
+ *
+ * This function will check if the specified partition can be requested, it
+ * will check if the partition has been loaded with an image, if no, as long
+ * as it is not in use, the partition request will be granted. If there is
+ * image loaded, it will check if the given UID from @req matches the image UID
+ * loaded on the partition, if they match, the partition request will be
+ * granted. A file will be created for the requested partition.
+ */
+static int aie_partition_get(struct aie_partition *apart,
+			     struct aie_partition_req *req)
+{
+	struct file *filep;
+	int ret;
+
+	(void)req;
+
+	if (apart->status & XAIE_PART_STATUS_INUSE) {
+		dev_err(&apart->dev,
+			"request partition %u failed, partition in use.\n",
+			apart->partition_id);
+		return -EBUSY;
+	}
+	/*
+	 * TODO:
+	 * 1. It will check image UID too to see if the user matches what's
+	 *    loaded in the AI engine partition. And check the meta data to see
+	 *    which resources used by application.
+	 */
+
+	/* scan to setup the initial clock state for tiles */
+	ret = aie_part_scan_clk_state(apart);
+	if (ret)
+		return ret;
+
+	/* Get a file for the partition */
+	filep = anon_inode_getfile(dev_name(&apart->dev), &aie_part_fops,
+				   apart, O_RDWR);
+	if (IS_ERR(filep)) {
+		dev_err(&apart->dev,
+			"Failed to request partition %u, failed to get file.\n",
+			apart->partition_id);
+		return PTR_ERR(filep);
+	}
+
+	filep->f_mode |= (FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
+	apart->filep = filep;
+
+	apart->status = XAIE_PART_STATUS_INUSE;
+	apart->cntrflag = req->flag;
+	return 0;
+}
+
+/**
+ * aie_partition_request_from_adev() - request AI engine partition from AI
+ *				       engine device
+ * @adev: AI engine device
+ * @req: partition request, includes the requested AI engine information
+ *	 such as partition node ID and the UID of the image which is used
+ *	 to describe the partition to request.
+ * @return: pointer to the AI engine partition for success, and negative
+ *	    value for failure.
+ *
+ * This function finds a defined partition which matches the specified
+ * partition id, and request it.
+ */
+static struct aie_partition *
+aie_partition_request_from_adev(struct aie_device *adev,
+				struct aie_partition_req *req)
+{
+	struct aie_partition *apart;
+	int ret;
+
+	ret = mutex_lock_interruptible(&adev->mlock);
+	if (ret)
+		return ERR_PTR(ret);
+
+	apart = aie_get_partition_from_id(adev, req->partition_id);
+	if (!apart) {
+		dev_err(&adev->dev,
+			"request partition %u failed, not exist.\n",
+			req->partition_id);
+		mutex_unlock(&adev->mlock);
+		return ERR_PTR(-EINVAL);
+	}
+	mutex_unlock(&adev->mlock);
+
+	ret = mutex_lock_interruptible(&apart->mlock);
+	if (ret)
+		return ERR_PTR(ret);
+
+	ret = aie_partition_get(apart, req);
+
+	mutex_unlock(&apart->mlock);
+
+	if (ret)
+		apart = ERR_PTR(ret);
+	return apart;
+}
+
+static long xilinx_ai_engine_ioctl(struct file *filp, unsigned int cmd,
+				   unsigned long arg)
+{
+	struct inode *inode = file_inode(filp);
+	struct aie_device *adev = cdev_to_aiedev(inode->i_cdev);
+	void __user *argp = (void __user *)arg;
+	int ret;
+
+	switch (cmd) {
+	case AIE_ENQUIRE_PART_IOCTL:
+	{
+		struct aie_partition_query query;
+		struct aie_partition_query  __user *uquery_ptr = argp;
+
+		if (copy_from_user(&query, uquery_ptr, sizeof(query)))
+			return -EFAULT;
+		ret = aie_enquire_partitions(adev, &query);
+		if (ret < 0)
+			return ret;
+		if (copy_to_user((void __user *)&uquery_ptr->partition_cnt,
+				 &query.partition_cnt,
+				 sizeof(query.partition_cnt)))
+			return -EFAULT;
+		break;
+	}
+	case AIE_REQUEST_PART_IOCTL:
+	{
+		struct aie_partition_req req;
+		struct aie_partition *apart;
+
+		if (copy_from_user(&req, argp, sizeof(req)))
+			return -EFAULT;
+
+		apart = aie_partition_request_from_adev(adev, &req);
+		if (IS_ERR(apart))
+			return PTR_ERR(apart);
+
+		/* Allocate fd */
+		ret = aie_partition_fd(apart);
+		if (ret < 0) {
+			fput(apart->filep);
+			break;
+		}
+		break;
+	}
+	default:
+		dev_err(&adev->dev, "Invalid ioctl command %u.\n", cmd);
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static const struct file_operations aie_device_fops = {
+	.owner		= THIS_MODULE,
+	.unlocked_ioctl	= xilinx_ai_engine_ioctl,
+};
+
+static void xilinx_ai_engine_release_device(struct device *dev)
+{
+	struct aie_device *adev = dev_to_aiedev(dev);
+
+	ida_simple_remove(&aie_device_ida, dev->id);
+	ida_simple_remove(&aie_minor_ida, MINOR(dev->devt));
+	cdev_del(&adev->cdev);
+	aie_resource_uninitialize(&adev->cols_res);
+}
+
+/**
+ * of_xilinx_ai_engine_part_probe() - probes for AI engine partition nodes
+ * @adev: AI engine device
+ *
+ * This function will probe for children AI engine partition nodes and create
+ * an AI engine partition instance for each node.
+ */
+static void of_xilinx_ai_engine_part_probe(struct aie_device *adev)
+{
+	struct device_node *nc;
+
+	for_each_available_child_of_node(adev->dev.of_node, nc) {
+		struct aie_partition *apart;
+
+		if (of_node_test_and_set_flag(nc, OF_POPULATED))
+			continue;
+		apart = of_aie_part_probe(adev, nc);
+		if (IS_ERR(apart)) {
+			dev_err(&adev->dev,
+				"Failed to probe AI engine part for %pOF\n",
+				nc);
+			of_node_clear_flag(nc, OF_POPULATED);
+		}
+	}
+}
+
+static int xilinx_ai_engine_probe(struct platform_device *pdev)
+{
+	struct aie_device *adev;
+	struct device *dev;
+	u32 idcode, version, pm_reg[2];
+	int ret;
+
+	adev = devm_kzalloc(&pdev->dev, sizeof(*adev), GFP_KERNEL);
+	if (!adev)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, adev);
+	INIT_LIST_HEAD(&adev->partitions);
+	mutex_init(&adev->mlock);
+
+	adev->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!adev->res) {
+		dev_err(&pdev->dev, "No memory resource.\n");
+		return -EINVAL;
+	}
+	adev->base = devm_ioremap_resource(&pdev->dev, adev->res);
+	if (IS_ERR(adev->base)) {
+		dev_err(&pdev->dev, "no io memory resource.\n");
+		return PTR_ERR(adev->base);
+	}
+
+	/* Initialize AIE device specific instance. */
+	ret = aie_device_init(adev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to initialize device instance.\n");
+		return ret;
+	}
+
+	/*
+	 * AI Engine platform management node ID is required for requesting
+	 * services from firmware driver.
+	 */
+	ret = of_property_read_u32_array(pdev->dev.of_node, "power-domains",
+					 pm_reg, ARRAY_SIZE(pm_reg));
+	if (ret < 0) {
+		dev_err(&pdev->dev,
+			"Failed to read power manangement information\n");
+		return ret;
+	}
+	adev->pm_node_id = pm_reg[1];
+
+	adev->eemi_ops = zynqmp_pm_get_eemi_ops();
+	if (IS_ERR(adev->eemi_ops)) {
+		dev_err(&adev->dev, "failed to get eemi ops.\n");
+		return PTR_ERR(adev->eemi_ops);
+	}
+	if (!adev->eemi_ops->reset_assert || !adev->eemi_ops->get_chipid ||
+	    !adev->eemi_ops->ioctl) {
+		dev_err(&adev->dev, "required eemi ops not found.\n");
+		return -EINVAL;
+	}
+
+	ret = adev->eemi_ops->get_chipid(&idcode, &version);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Failed to get chip ID\n");
+		return ret;
+	}
+	adev->version = FIELD_GET(VERSAL_SILICON_REV_MASK, idcode);
+
+	dev = &adev->dev;
+	device_initialize(dev);
+	dev->class = aie_class;
+	dev->parent = &pdev->dev;
+	dev->of_node = pdev->dev.of_node;
+
+	ret = ida_simple_get(&aie_minor_ida, 0, AIE_DEV_MAX, GFP_KERNEL);
+	if (ret < 0)
+		goto free_dev;
+	dev->devt = MKDEV(MAJOR(aie_major), ret);
+	ret = ida_simple_get(&aie_device_ida, 0, 0, GFP_KERNEL);
+	if (ret < 0)
+		goto free_minor_ida;
+	dev->id = ret;
+	dev_set_name(&adev->dev, "aie%d", dev->id);
+
+	cdev_init(&adev->cdev, &aie_device_fops);
+	adev->cdev.owner = THIS_MODULE;
+	ret = cdev_add(&adev->cdev, dev->devt, 1);
+	if (ret)
+		goto free_ida;
+	/* We can now rely on the release function for cleanup */
+	dev->release = xilinx_ai_engine_release_device;
+
+	ret = device_add(dev);
+	if (ret) {
+		dev_err(&pdev->dev, "device_add failed: %d\n", ret);
+		put_device(dev);
+		return ret;
+	}
+
+	of_xilinx_ai_engine_part_probe(adev);
+	dev_info(&pdev->dev, "Xilinx AI Engine device(cols=%u) probed\n",
+		 adev->cols_res.total);
+
+	INIT_WORK(&adev->backtrack, aie_array_backtrack);
+
+	adev->irq = platform_get_irq_byname(pdev, "interrupt1");
+	if (adev->irq < 0)
+		goto free_ida;
+
+	ret = devm_request_threaded_irq(dev, adev->irq, NULL, aie_interrupt,
+					IRQF_ONESHOT, dev_name(dev), adev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to request AIE IRQ.\n");
+		goto free_ida;
+	}
+	return 0;
+
+free_ida:
+	ida_simple_remove(&aie_device_ida, dev->id);
+free_minor_ida:
+	ida_simple_remove(&aie_minor_ida, MINOR(dev->devt));
+free_dev:
+	put_device(dev);
+
+	return ret;
+}
+
+static int xilinx_ai_engine_remove(struct platform_device *pdev)
+{
+	struct aie_device *adev = platform_get_drvdata(pdev);
+	struct aie_partition *apart;
+
+	list_for_each_entry(apart, &adev->partitions, node)
+		aie_part_remove(apart);
+
+	device_del(&adev->dev);
+	put_device(&adev->dev);
+
+	return 0;
+}
+
+static const struct of_device_id xilinx_ai_engine_of_match[] = {
+	{ .compatible = "xlnx,ai-engine-v1.0", },
+	{ /* end of table */ },
+};
+MODULE_DEVICE_TABLE(of, xilinx_ai_engine_of_match);
+
+static struct platform_driver xilinx_ai_engine_driver = {
+	.probe			= xilinx_ai_engine_probe,
+	.remove			= xilinx_ai_engine_remove,
+	.driver			= {
+		.name		= "xilinx-ai-engine",
+		.of_match_table	= xilinx_ai_engine_of_match,
+	},
+};
+
+/**
+ * aie_partition_dev_match() - check if AI engine partition matches partition ID
+ *
+ * @dev: pointer to the AI engine partition device
+ * @data: partition_id
+ * @return: 1 if partition matches, otherwise 0.
+ */
+static int aie_partition_dev_match(struct device *dev, const void *data)
+{
+	struct aie_partition *apart;
+	u32 partition_id = (u32)(uintptr_t)data;
+
+	if (strncmp(dev_name(dev), "aiepart", strlen("aiepart")))
+		return 0;
+
+	apart = dev_to_aiepart(dev);
+	if (apart->partition_id == partition_id)
+		return 1;
+	return 0;
+}
+
+/**
+ * aie_class_find_partition_from_id() - Find the AI engine partition whose ID
+ *					matches.
+ * @partition_id: AI engine partition ID
+ * @return: pointer to the AI engine partition if partition is found, otherwise
+ *	    NULL.
+ *
+ * This function looks up all the devices of the AI engine class to check if
+ * the device is AI engine partition device if if the partition ID matches.
+ */
+static struct aie_partition *aie_class_find_partition_from_id(u32 partition_id)
+{
+	struct device *dev;
+
+	dev = class_find_device(aie_class, NULL,
+				(void *)(uintptr_t)partition_id,
+				aie_partition_dev_match);
+	if (!dev)
+		return NULL;
+	return dev_to_aiepart(dev);
+}
+
+/**
+ * aie_partition_is_available() - Check if an AI engine partition is available
+ * @req: AI engine partition requesting arguments
+ * @return: true if the AI engine partition is not in use, otherwise, false
+ *
+ * This function looks up the AI engine class devices to find the AI engine
+ * partition whose partition ID matches the given partition ID in @req. If
+ * the partition can be found, if will check if the partition is in use.
+ *
+ * In case the AI engine release function is called from kernel context, the
+ * release() will be scheduled when the AI engine partition reference count is
+ * reduced to 0 instead of get called synchronously, and thus, this is a helper
+ * function for another kernel module to check if the partitions is released
+ * after calling release function from kernel context
+ *
+ * However, if closing the partition is from user context, it will not return
+ * until the release is complete when there is no reference to the AI engine
+ * partition file. In this case, user doesn't need to call this function to
+ * check if the partition is released.
+ */
+bool aie_partition_is_available(struct aie_partition_req *req)
+{
+	struct aie_partition *apart;
+	int ret;
+
+	if (!req)
+		return false;
+
+	apart = aie_class_find_partition_from_id(req->partition_id);
+	if (!apart)
+		return false;
+
+	ret = mutex_lock_interruptible(&apart->mlock);
+	if (ret)
+		return false;
+
+	if (apart->status & XAIE_PART_STATUS_INUSE) {
+		mutex_unlock(&apart->mlock);
+		return false;
+	}
+
+	mutex_unlock(&apart->mlock);
+	return true;
+}
+EXPORT_SYMBOL_GPL(aie_partition_is_available);
+
+/**
+ * aie_partition_request() - Request an AI engine partition
+ * @req: AI engine partition requesting arguments
+ * @return: pointer to the AI engine partition device, error value for failure.
+ *
+ * This function looks up the AI engine class devices to find the AI engine
+ * partition whose partition ID matches the given partition ID in @req. If
+ * the partition can be found, it will try to request it. It will get a file
+ * for the requested AI engine partition. User can only use the AI engine
+ * partition after it is successfully requested.
+ */
+struct device *aie_partition_request(struct aie_partition_req *req)
+{
+	struct aie_partition *apart;
+	int ret;
+
+	if (!req)
+		return ERR_PTR(-EINVAL);
+
+	apart = aie_class_find_partition_from_id(req->partition_id);
+	if (!apart)
+		return ERR_PTR(-ENODEV);
+
+	ret = mutex_lock_interruptible(&apart->mlock);
+	if (ret)
+		return ERR_PTR(ret);
+
+	ret = aie_partition_get(apart, req);
+	mutex_unlock(&apart->mlock);
+	if (ret)
+		return ERR_PTR(ret);
+
+	if (apart->error_to_report)
+		schedule_work(&apart->adev->backtrack);
+
+	return &apart->dev;
+}
+EXPORT_SYMBOL_GPL(aie_partition_request);
+
+/**
+ * aie_partition_get_fd() - get AI engine partition file descriptor
+ * @dev: AI engine partition device pointer
+ * @return: file descriptor for the AI engine partition for success, and
+ *	    negative value for failure.
+ *
+ * This function allocate a file descriptor for the AI engine requested
+ * partition, and increase the reference count to the AI engine partition file.
+ */
+int aie_partition_get_fd(struct device *dev)
+{
+	struct aie_partition *apart;
+	int ret;
+
+	if (!dev)
+		return -EINVAL;
+
+	apart = dev_to_aiepart(dev);
+
+	ret = aie_partition_fd(apart);
+	if (ret < 0)
+		return ret;
+
+	get_file(apart->filep);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(aie_partition_get_fd);
+
+/**
+ * aie_partition_release() - Recrease refcount of the AI engine partition
+ * @dev: AI engine partition device
+ */
+void aie_partition_release(struct device *dev)
+{
+	struct aie_partition *apart;
+
+	if (WARN_ON(!dev))
+		return;
+
+	apart = dev_to_aiepart(dev);
+	fput(apart->filep);
+}
+EXPORT_SYMBOL_GPL(aie_partition_release);
+
+/**
+ * aie_partition_reset() - Reset AI engine partition
+ * @dev: AI engine partition device
+ * @return: 0 for success, negative value for failure
+ */
+int aie_partition_reset(struct device *dev)
+{
+	struct aie_partition *apart;
+
+	if (WARN_ON(!dev))
+		return -EINVAL;
+
+	apart = dev_to_aiepart(dev);
+	return aie_part_reset(apart);
+}
+EXPORT_SYMBOL_GPL(aie_partition_reset);
+
+/**
+ * aie_partition_post_reinit() - Indicate AI engine partition driver the
+ *				 partition has been re-initialized.
+ * @dev: AI engine partition device
+ * @return: 0 for success, negative value for failure
+ *
+ * This function is called after the AI engine partition is reconfigured with
+ * PDI outside the AI engine driver.
+ */
+int aie_partition_post_reinit(struct device *dev)
+{
+	struct aie_partition *apart;
+
+	if (WARN_ON(!dev))
+		return -EINVAL;
+
+	apart = dev_to_aiepart(dev);
+	return aie_part_post_reinit(apart);
+}
+EXPORT_SYMBOL_GPL(aie_partition_post_reinit);
+
+static int __init xilinx_ai_engine_init(void)
+{
+	int ret;
+
+	ret = alloc_chrdev_region(&aie_major, 0, AIE_DEV_MAX, "aie");
+	if (ret < 0) {
+		pr_err("aie: failed to allocate aie region\n");
+		return ret;
+	}
+
+	aie_class = class_create(THIS_MODULE, "aie");
+	if (IS_ERR(aie_class)) {
+		pr_err("failed to create aie class\n");
+		unregister_chrdev_region(aie_major, AIE_DEV_MAX);
+		return PTR_ERR(aie_class);
+	}
+
+	platform_driver_register(&xilinx_ai_engine_driver);
+
+	return 0;
+}
+postcore_initcall(xilinx_ai_engine_init);
+
+static void __exit xilinx_ai_engine_exit(void)
+{
+	platform_driver_unregister(&xilinx_ai_engine_driver);
+	class_destroy(aie_class);
+	unregister_chrdev_region(aie_major, AIE_DEV_MAX);
+}
+module_exit(xilinx_ai_engine_exit);
+
+MODULE_AUTHOR("Xilinx, Inc.");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/xilinx-ai-engine/ai-engine-dma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/xilinx-ai-engine/ai-engine-dma.c
@@ -0,0 +1,637 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx AI Engine driver DMA implementation
+ *
+ * Copyright (C) 2020 Xilinx, Inc.
+ */
+
+#include "ai-engine-internal.h"
+#include <linux/dma-buf.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/refcount.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+
+/**
+ * struct aie_dmabuf - AI engine dmabuf information
+ * @attach: dmabuf attachment pointer
+ * @sgt: scatter/gather table
+ * @refs: refcount of the attached aie_dmabuf
+ * @node: list node
+ */
+struct aie_dmabuf {
+	struct dma_buf_attachment *attach;
+	struct sg_table *sgt;
+	refcount_t refs;
+	struct list_head node;
+};
+
+/**
+ * aie_part_find_dmabuf() - find a attached dmabuf
+ * @apart: AI engine partition
+ * @dmabuf: pointer to dmabuf
+ * @return: pointer to AI engine dmabuf struct of the found dmabuf, if dmabuf
+ *	    is not found, returns NULL.
+ *
+ * This function scans all the attached dmabufs to see the input dmabuf is
+ * in the list. if it is attached, return the corresponding struct aie_dmabuf
+ * pointer.
+ */
+static struct aie_dmabuf *
+aie_part_find_dmabuf(struct aie_partition *apart, struct dma_buf *dmabuf)
+{
+	struct aie_dmabuf *adbuf;
+
+	list_for_each_entry(adbuf, &apart->dbufs, node) {
+		if (dmabuf == adbuf->attach->dmabuf)
+			return adbuf;
+	}
+
+	return NULL;
+}
+
+/**
+ * aie_part_find_dmabuf_from_file() - find a attached dmabuf from file
+ * @apart: AI engine partition
+ * @file: file which belongs to a dmabuf
+ * @return: pointer to AI engine dmabuf struct of the found dmabuf, if dmabuf
+ *	    is not found, returns NULL.
+ *
+ * This function scans all the attached dmabufs of the AI engine partition,
+ * it checks the file with the attached dmabufs, if it founds a match, it
+ * returns the aie_dmabuf pointer.
+ */
+static struct aie_dmabuf *
+aie_part_find_dmabuf_from_file(struct aie_partition *apart,
+			       const struct file *file)
+{
+	struct aie_dmabuf *adbuf;
+
+	list_for_each_entry(adbuf, &apart->dbufs, node) {
+		if (file == adbuf->attach->dmabuf->file)
+			return adbuf;
+	}
+
+	return NULL;
+}
+
+/**
+ * aie_part_get_dmabuf_da() -  get DMA address from the va
+ * @apart: AI engine partition
+ * @va: virtual address
+ * @len: memory length
+ * @return: dma address of of the specified va, or 0 if va is not valid
+ *
+ * This function returns DMA address if the has been mapped to a dmabuf which
+ * has been attached to the AI engine partition.
+ */
+static dma_addr_t aie_part_get_dmabuf_da(struct aie_partition *apart,
+					 void *va, size_t len)
+{
+	struct vm_area_struct *vma;
+	struct aie_dmabuf *adbuf;
+	unsigned long va_start, va_off;
+
+	va_start = (unsigned long)((uintptr_t)va);
+	if (!current->mm) {
+		dev_err(&apart->dev,
+			"failed to get dma address from va, no process mm.\n");
+		return 0;
+	}
+
+	vma = find_vma(current->mm, va_start);
+	if (!vma) {
+		dev_err(&apart->dev, "failed to find vma for %p, 0x%zx.\n",
+			va, len);
+		return 0;
+	}
+
+	adbuf = aie_part_find_dmabuf_from_file(apart, vma->vm_file);
+	if (!adbuf) {
+		dev_err(&apart->dev,
+			"failed to get dma address for %p, no dma buf is found.\n",
+			va);
+		return 0;
+	}
+
+	va_off = va_start - vma->vm_start;
+	/*
+	 * As we only support continuous DMA memory which is guaranteed from
+	 * dmabuf attachment, we will compared with the size of the dmabuf only
+	 */
+	if (va_off + len >= adbuf->attach->dmabuf->size) {
+		dev_err(&apart->dev,
+			"failed to get dma address for %p, 0x%zx.\n", va, len);
+		return 0;
+	}
+
+	return sg_dma_address(adbuf->sgt->sgl) + va_off;
+}
+
+/**
+ * aie_part_get_dmabuf_da_from_off() - get DMA address from offset to a dmabuf
+ * @apart: AI engine partition
+ * @dmabuf_fd: dmabuf file descriptor
+ * @off: offset to the start of a dmabuf
+ * @len: memory length
+ * @return: dma address, or 0 if @off or @len is invalid, or if @dmabuf_fd is
+ *	    not attached.
+ *
+ * This function returns DMA address if has been mapped to a dmabuf which has
+ * been attached to the AI engine partition.
+ */
+static dma_addr_t
+aie_part_get_dmabuf_da_from_off(struct aie_partition *apart, int dmabuf_fd,
+				u64 off, size_t len)
+{
+	struct dma_buf *dbuf = dma_buf_get(dmabuf_fd);
+	struct aie_dmabuf *adbuf;
+
+	if (IS_ERR(dbuf)) {
+		dev_err(&apart->dev,
+			"failed to get dma address, not able to get dmabuf from %d.\n",
+			dmabuf_fd);
+		return 0;
+	}
+
+	adbuf = aie_part_find_dmabuf(apart, dbuf);
+	dma_buf_put(dbuf);
+	if (!adbuf) {
+		dev_err(&apart->dev,
+			"failed to get dma address, dmabuf %d not attached.\n",
+			dmabuf_fd);
+		return 0;
+	}
+
+	if (off >= dbuf->size || off + len >= dbuf->size) {
+		dev_err(&apart->dev,
+			"failed to get dma address from buf %d, off=0x%llx, len=0x%zx.\n",
+			dmabuf_fd, off, len);
+		return 0;
+	}
+
+	return sg_dma_address(adbuf->sgt->sgl) + off;
+}
+
+/**
+ * aie_part_set_shimdma_bd() - Set the buffer descriptor to AI engine partition
+ *			       hardware
+ * @apart: AI engine partition
+ * @loc: AI engine tile location
+ * @bd_id: buffer descriptor ID
+ * @bd: pointer buffer descriptor content
+ * @return: 0 for success, negative value for failure
+ *
+ * This function sets the specified buffer descriptor content to the
+ * specified buffer descriptor in the specified AI engine SHIM NOC tile.
+ */
+static int aie_part_set_shimdma_bd(struct aie_partition *apart,
+				   struct aie_location loc, u32 bd_id, u32 *bd)
+{
+	const struct aie_dma_attr *shim_dma = apart->adev->shim_dma;
+	struct aie_location loc_adjust;
+	u32 i, regoff, intile_regoff;
+
+	intile_regoff = shim_dma->bd_regoff + shim_dma->bd_len * bd_id;
+	loc_adjust.col = loc.col + apart->range.start.col;
+	loc_adjust.row = loc.row + apart->range.start.row;
+	regoff = aie_cal_regoff(apart->adev, loc_adjust, intile_regoff);
+
+	for (i = 0; i < shim_dma->bd_len / (sizeof(*bd));
+	     i++, regoff += sizeof(*bd))
+		iowrite32(bd[i], apart->adev->base + regoff);
+	return 0;
+}
+
+/**
+ * aie_part_validate_bdloc() - Validate SHIM DMA buffer descriptor location
+ * @apart: AI engine partition
+ * @loc: tile location
+ * @bd_id: buffer descriptor id
+ *
+ * @return: 0 for success, negative value for failure
+ *
+ * This function validate the SHIM DMA buffer descriptor base address.
+ */
+static int aie_part_validate_bdloc(struct aie_partition *apart,
+				   struct aie_location loc, u32 bd_id)
+{
+	const struct aie_dma_attr *shim_dma = apart->adev->shim_dma;
+	struct aie_location loc_adjust;
+	u32 ttype;
+
+	loc_adjust.col = loc.col + apart->range.start.col;
+	loc_adjust.row = loc.row + apart->range.start.row;
+
+	if (aie_validate_location(apart, loc_adjust) < 0) {
+		dev_err(&apart->dev,
+			"invalid loc (%u,%u) in (%u,%u).\n",
+			loc.col, loc.row,
+			apart->range.size.col, apart->range.size.row);
+		return -EINVAL;
+	}
+
+	ttype = apart->adev->ops->get_tile_type(&loc_adjust);
+	if (ttype != AIE_TILE_TYPE_SHIMNOC) {
+		dev_err(&apart->dev,
+			"failed to set bd, (%u,%u) is not SHIM NOC\n",
+			loc.col, loc.row);
+		return -EINVAL;
+	}
+
+	if (bd_id >= shim_dma->num_bds) {
+		dev_err(&apart->dev,
+			"invalid SHIM DMA bd id: %u.\n", bd_id);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * aie_part_attach_dmabuf() - Attach dmabuf to an AI engine
+ * @apart: AI engine partition
+ * @dbuf: pointer to the DMA buffer to attach
+ * @return: pointer to AI engine dmabuf structure for success, or error value
+ *	    for failure
+ *
+ * This function attaches a dmabuf to the specified AI engine partition.
+ */
+static struct aie_dmabuf *aie_part_attach_dmabuf(struct aie_partition *apart,
+						 struct dma_buf *dbuf)
+{
+	struct aie_dmabuf *adbuf;
+	struct dma_buf_attachment *attach;
+	struct sg_table *sgt;
+
+	attach = dma_buf_attach(dbuf, &apart->dev);
+	if (IS_ERR(attach)) {
+		dev_err(&apart->dev, "failed to attach dmabuf\n");
+		return ERR_CAST(attach);
+	}
+
+	sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
+	if (IS_ERR(sgt)) {
+		dev_err(&apart->dev, "failed to map dmabuf attachment\n");
+		dma_buf_detach(dbuf, attach);
+		return ERR_CAST(sgt);
+	}
+
+	if (sgt->nents != 1) {
+		dma_addr_t next_sg_addr = sg_dma_address(sgt->sgl);
+		struct scatterlist *s;
+		unsigned int i;
+
+		for_each_sg(sgt->sgl, s, sgt->nents, i) {
+			if (sg_dma_address(s) != next_sg_addr) {
+				dev_err(&apart->dev,
+					"dmabuf not contiguous\n");
+				dma_buf_unmap_attachment(attach, sgt,
+							 attach->dir);
+				dma_buf_detach(dbuf, attach);
+				return ERR_PTR(-EINVAL);
+			}
+
+			next_sg_addr = sg_dma_address(s) + sg_dma_len(s);
+		}
+	}
+
+	adbuf = devm_kzalloc(&apart->dev, sizeof(*adbuf), GFP_KERNEL);
+	if (!adbuf) {
+		dma_buf_unmap_attachment(attach, sgt, attach->dir);
+		dma_buf_detach(dbuf, attach);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	adbuf->attach = attach;
+	/*
+	 * dmabuf attachment doesn't always include the sgt, store it in
+	 * AI engine dma buf structure.
+	 */
+	adbuf->sgt = sgt;
+
+	refcount_set(&adbuf->refs, 1);
+
+	list_add(&adbuf->node, &apart->dbufs);
+	return adbuf;
+}
+
+/**
+ * aie_part_dmabuf_attach_get() - Get reference to an dmabuf attachment
+ * @adbuf: AI engine partition attached dmabuf
+ *
+ * This call will increase the reference count by 1
+ */
+static void aie_part_dmabuf_attach_get(struct aie_dmabuf *adbuf)
+{
+	refcount_inc(&adbuf->refs);
+}
+
+/**
+ * aie_part_dmabuf_attach_put() - Put reference to an dmabuf attachment
+ * @adbuf: AI engine partition attached dmabuf
+ *
+ * This call will decrease the reference count by 1. If the refcount reaches
+ * 0, it will detach the dmabuf.
+ */
+static void aie_part_dmabuf_attach_put(struct aie_dmabuf *adbuf)
+{
+	struct dma_buf *dbuf;
+
+	if (!refcount_dec_and_test(&adbuf->refs))
+		return;
+
+	dbuf = adbuf->attach->dmabuf;
+	dma_buf_unmap_attachment(adbuf->attach, adbuf->sgt, adbuf->attach->dir);
+	dma_buf_detach(dbuf, adbuf->attach);
+	dma_buf_put(dbuf);
+	list_del(&adbuf->node);
+}
+
+/**
+ * aie_part_release_dmabufs() - detach all the attached dmabufs from partition
+ * @apart: AI engine partition
+ */
+void aie_part_release_dmabufs(struct aie_partition *apart)
+{
+	struct aie_dmabuf *adbuf, *tmpadbuf;
+
+	list_for_each_entry_safe(adbuf, tmpadbuf, &apart->dbufs, node) {
+		struct dma_buf *dbuf = adbuf->attach->dmabuf;
+
+		dma_buf_unmap_attachment(adbuf->attach, adbuf->sgt,
+					 adbuf->attach->dir);
+		dma_buf_detach(dbuf, adbuf->attach);
+		dma_buf_put(dbuf);
+		list_del(&adbuf->node);
+		devm_kfree(&apart->dev, adbuf);
+	}
+}
+
+/**
+ * aie_part_attach_dmabuf_req() - Handle attaching dmabuf to an AI engine
+ *				  partition request
+ * @apart: AI engine partition
+ * @user_args: user AI engine dmabuf argument
+ *
+ * @return: 0 for success, negative value for failure
+ *
+ * This function attaches a dmabuf to the specified AI engine partition and map
+ * the attachment. It checks if the dmabuf is already attached, if it is not
+ * attached, attach it. It returns the number of entries of the attachment to
+ * the AI engine dmabuf user argument. If user wants to know the sg list, it
+ * can use AI engine get sg ioctl.
+ */
+long aie_part_attach_dmabuf_req(struct aie_partition *apart,
+				void __user *user_args)
+{
+	struct aie_dmabuf *adbuf;
+	struct dma_buf *dbuf;
+	long ret;
+	int dmabuf_fd = (int)(uintptr_t)user_args;
+
+	dbuf = dma_buf_get(dmabuf_fd);
+	if (IS_ERR(dbuf)) {
+		dev_err(&apart->dev, "failed to get dmabuf from %d.\n",
+			dmabuf_fd);
+		return PTR_ERR(dbuf);
+	}
+
+	ret = mutex_lock_interruptible(&apart->mlock);
+	if (ret) {
+		dma_buf_put(dbuf);
+		return ret;
+	}
+
+	adbuf = aie_part_find_dmabuf(apart, dbuf);
+	if (!adbuf)
+		adbuf = aie_part_attach_dmabuf(apart, dbuf);
+	else
+		aie_part_dmabuf_attach_get(adbuf);
+
+	mutex_unlock(&apart->mlock);
+
+	if (IS_ERR(adbuf)) {
+		dev_err(&apart->dev, "failed to attach dmabuf\n");
+		dma_buf_put(dbuf);
+		return PTR_ERR(adbuf);
+	}
+
+	return 0;
+}
+
+/**
+ * aie_part_detach_dmabuf_req() - Handle detaching dmabuf from an AI engine
+ *				  partition request
+ * @apart: AI engine partition
+ * @user_args: user AI engine dmabuf argument
+ *
+ * @return: 0 for success, negative value for failure
+ *
+ * This function unmaps and detaches a dmabuf from the specified AI engine
+ * partition.
+ */
+long aie_part_detach_dmabuf_req(struct aie_partition *apart,
+				void __user *user_args)
+{
+	int dmabuf_fd;
+	struct dma_buf *dbuf;
+	struct aie_dmabuf *adbuf;
+	int ret;
+
+	dmabuf_fd = (int)(uintptr_t)user_args;
+
+	dbuf = dma_buf_get(dmabuf_fd);
+	if (IS_ERR(dbuf)) {
+		dev_err(&apart->dev, "failed to get dmabuf %d.\n", dmabuf_fd);
+		return PTR_ERR(dbuf);
+	}
+
+	ret = mutex_lock_interruptible(&apart->mlock);
+	if (ret) {
+		dma_buf_put(dbuf);
+		return ret;
+	}
+
+	adbuf = aie_part_find_dmabuf(apart, dbuf);
+	dma_buf_put(dbuf);
+	if (!adbuf) {
+		dev_err(&apart->dev, "failed to find dmabuf %d.\n", dmabuf_fd);
+		mutex_unlock(&apart->mlock);
+		return -EINVAL;
+	}
+
+	aie_part_dmabuf_attach_put(adbuf);
+
+	mutex_unlock(&apart->mlock);
+
+	return 0;
+}
+
+/**
+ * aie_part_set_bd() - Set AI engine SHIM DMA buffer descriptor
+ * @apart: AI engine partition
+ * @user_args: user AI engine dmabuf argument
+ *
+ * @return: 0 for success, negative value for failure
+ *
+ * This function set the user specified buffer descriptor into the SHIM DMA
+ * buffer descriptor.
+ */
+long aie_part_set_bd(struct aie_partition *apart, void __user *user_args)
+{
+	struct aie_device *adev = apart->adev;
+	const struct aie_dma_attr *shim_dma = adev->shim_dma;
+	struct aie_dma_bd_args args;
+	u32 *bd, *tmpbd, buf_len, laddr, haddr, regval;
+	dma_addr_t addr;
+	int ret;
+
+	if (copy_from_user(&args, user_args, sizeof(args)))
+		return -EFAULT;
+
+	ret = aie_part_validate_bdloc(apart, args.loc, args.bd_id);
+	if (ret) {
+		dev_err(&apart->dev, "invalid SHIM DMA BD reg address.\n");
+		return -EINVAL;
+	}
+
+	bd = memdup_user((void __user *)args.bd, shim_dma->bd_len);
+	if (IS_ERR(bd))
+		return PTR_ERR(bd);
+
+	regval = bd[shim_dma->buflen.regoff / sizeof(u32)];
+	buf_len = aie_get_reg_field(&shim_dma->buflen, regval);
+	if (!buf_len) {
+		dev_err(&apart->dev, "no buf length from shim dma bd.\n");
+		kfree(bd);
+		return -EINVAL;
+	}
+
+	ret = mutex_lock_interruptible(&apart->mlock);
+	if (ret) {
+		kfree(bd);
+		return ret;
+	}
+
+	/* Get device address from virtual address */
+	addr = aie_part_get_dmabuf_da(apart, (void *)(uintptr_t)args.data_va,
+				      buf_len);
+	if (!addr) {
+		dev_err(&apart->dev, "invalid buffer 0x%llx, 0x%x.\n",
+			args.data_va, buf_len);
+		mutex_unlock(&apart->mlock);
+		kfree(bd);
+		return -EINVAL;
+	}
+
+	/* Set low 32bit address */
+	laddr = lower_32_bits(addr);
+	tmpbd = (u32 *)((char *)bd + shim_dma->laddr.regoff);
+	*tmpbd &= ~shim_dma->laddr.mask;
+	*tmpbd |= aie_get_field_val(&shim_dma->laddr, laddr);
+
+	/* Set high 32bit address */
+	haddr = upper_32_bits(addr);
+	tmpbd = (u32 *)((char *)bd + shim_dma->haddr.regoff);
+	*tmpbd &= ~shim_dma->haddr.mask;
+	*tmpbd |= aie_get_field_val(&shim_dma->haddr, haddr);
+
+	ret = aie_part_set_shimdma_bd(apart, args.loc, args.bd_id, bd);
+	mutex_unlock(&apart->mlock);
+	if (ret)
+		dev_err(&apart->dev, "failed to set to shim dma bd.\n");
+
+	kfree(bd);
+	return ret;
+}
+
+/**
+ * aie_part_set_dmabuf_bd() - Set AI engine SHIM DMA dmabuf buffer descriptor
+ * @apart: AI engine partition
+ * @user_args: user AI engine dmabuf argument
+ *
+ * @return: 0 for success, negative value for failure
+ *
+ * This function set the user specified buffer descriptor into the SHIM DMA
+ * buffer descriptor. The buffer descriptor contained in the @user_args has the
+ * offset to the start of the buffer descriptor.
+ */
+long aie_part_set_dmabuf_bd(struct aie_partition *apart,
+			    void __user *user_args)
+{
+	struct aie_device *adev = apart->adev;
+	const struct aie_dma_attr *shim_dma = adev->shim_dma;
+	struct aie_dmabuf_bd_args args;
+	u32 *bd, *tmpbd, len, laddr, haddr, regval;
+	u64 off;
+	dma_addr_t addr;
+	int ret;
+
+	if (copy_from_user(&args, user_args, sizeof(args)))
+		return -EFAULT;
+
+	ret = aie_part_validate_bdloc(apart, args.loc, args.bd_id);
+	if (ret) {
+		dev_err(&apart->dev, "invalid SHIM DMA BD reg address.\n");
+		return -EINVAL;
+	}
+
+	bd = memdup_user((void __user *)args.bd, shim_dma->bd_len);
+	if (IS_ERR(bd))
+		return PTR_ERR(bd);
+
+	regval = bd[shim_dma->buflen.regoff / sizeof(u32)];
+	len = aie_get_reg_field(&shim_dma->buflen, regval);
+	if (!len) {
+		dev_err(&apart->dev, "no buf length from shim dma bd.\n");
+		kfree(bd);
+		return -EINVAL;
+	}
+
+	/* Get low 32bit address offset */
+	tmpbd = (u32 *)((char *)bd + shim_dma->laddr.regoff);
+	laddr = *tmpbd & shim_dma->laddr.mask;
+	/* Get high 32bit address offset */
+	tmpbd = (u32 *)((char *)bd + shim_dma->haddr.regoff);
+	haddr = *tmpbd & shim_dma->haddr.mask;
+	off = laddr | ((u64)haddr << 32);
+
+	ret = mutex_lock_interruptible(&apart->mlock);
+	if (ret) {
+		kfree(bd);
+		return ret;
+	}
+
+	/* Get device address from offset */
+	addr = aie_part_get_dmabuf_da_from_off(apart, args.buf_fd, off, len);
+	if (!addr) {
+		dev_err(&apart->dev, "invalid buffer 0x%llx, 0x%x.\n",
+			off, len);
+		mutex_unlock(&apart->mlock);
+		kfree(bd);
+		return -EINVAL;
+	}
+
+	/* Set low 32bit address */
+	laddr = lower_32_bits(addr);
+	tmpbd = (u32 *)((char *)bd + shim_dma->laddr.regoff);
+	*tmpbd &= ~shim_dma->laddr.mask;
+	*tmpbd |= aie_get_field_val(&shim_dma->laddr, laddr);
+
+	/* Set high 32bit address */
+	haddr = upper_32_bits(addr);
+	tmpbd = (u32 *)((char *)bd + shim_dma->haddr.regoff);
+	*tmpbd &= ~shim_dma->haddr.mask;
+	*tmpbd |= aie_get_field_val(&shim_dma->haddr, haddr);
+
+	ret = aie_part_set_shimdma_bd(apart, args.loc, args.bd_id, bd);
+	mutex_unlock(&apart->mlock);
+	if (ret)
+		dev_err(&apart->dev, "failed to set to shim dma bd.\n");
+
+	kfree(bd);
+	return ret;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/xilinx-ai-engine/ai-engine-fpga.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/xilinx-ai-engine/ai-engine-fpga.c
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx AI Engine driver FPGA region implementation
+ *
+ * Copyright (C) 2020 Xilinx, Inc.
+ */
+
+#include "ai-engine-internal.h"
+
+static int aie_fpga_bridge_enable_set(struct fpga_bridge *bridge, bool enable)
+{
+	struct aie_partition *apart = bridge->priv;
+	int ret;
+
+	/*
+	 * TBD:
+	 * "Enable" should enable the SHIM tile configuration.
+	 * "Disable" should should disable SHIM DMAs, and wait
+	 * until SHIM DMA stops, and disable SHIM
+	 * to PL streams within partition.
+	 */
+	ret = mutex_lock_interruptible(&apart->mlock);
+	if (ret)
+		return ret;
+
+	if (enable)
+		apart->status |= XAIE_PART_STATUS_BRIDGE_ENABLED;
+	else
+		apart->status &= ~XAIE_PART_STATUS_BRIDGE_ENABLED;
+	mutex_unlock(&apart->mlock);
+	return 0;
+}
+
+static int aie_fpga_bridge_enable_show(struct fpga_bridge *bridge)
+{
+	struct aie_partition *apart = bridge->priv;
+	int ret;
+
+	ret = mutex_lock_interruptible(&apart->mlock);
+	if (ret)
+		return ret;
+
+	if (apart->status & XAIE_PART_STATUS_BRIDGE_ENABLED)
+		ret = 1;
+	else
+		ret = 0;
+	mutex_unlock(&apart->mlock);
+	return ret;
+}
+
+static const struct fpga_bridge_ops aie_fpga_bridge_ops = {
+	.enable_set = aie_fpga_bridge_enable_set,
+	.enable_show = aie_fpga_bridge_enable_show,
+};
+
+/**
+ * aie_fpga_create_bridge() - Create FPGA bridge for AI engine partition
+ * @apart: AI engine partition
+ * @return: 0 for success, negative value for failure
+ *
+ * This function will create FPGA bridge for AI engine partition.
+ * FPGA bridge is the presentation of SHIM row of the AI engine partition.
+ * FPGA bridge connects AI engine partition with other FPGA regions.
+ */
+int aie_fpga_create_bridge(struct aie_partition *apart)
+{
+	struct fpga_bridge *br;
+	int ret;
+
+	snprintf(apart->br.name, sizeof(apart->br.name) - 1,
+		 "xlnx-aie-bridge-%u-%u", apart->range.start.col, 0);
+	br = devm_fpga_bridge_create(&apart->dev, apart->br.name,
+				     &aie_fpga_bridge_ops, apart);
+	if (!br)
+		return -ENOMEM;
+	ret = fpga_bridge_register(br);
+	if (ret) {
+		dev_err(&apart->dev, "Failed to register bridge.\n");
+		return ret;
+	}
+	apart->br.br = br;
+	return 0;
+}
+
+/**
+ * aie_fpga_free_bridge() - Free AI engine partition FPGA bridge
+ * @apart: AI engine partition
+ *
+ * This function will free the FPGA bridge for AI engine partition.
+ */
+void aie_fpga_free_bridge(struct aie_partition *apart)
+{
+	if (!WARN_ON(!apart->br.br))
+		fpga_bridge_unregister(apart->br.br);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/xilinx-ai-engine/ai-engine-internal.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/xilinx-ai-engine/ai-engine-internal.h
@@ -0,0 +1,570 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Xilinx AI Engine driver internal header
+ *
+ * Copyright (C) 2020 Xilinx, Inc.
+ */
+
+#ifndef AIE_INTERNAL_H
+#define AIE_INTERNAL_H
+
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/dma-buf.h>
+#include <linux/file.h>
+#include <linux/fpga/fpga-bridge.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <uapi/linux/xlnx-ai-engine.h>
+
+/*
+ * Macros for AI engine tile type bitmasks
+ */
+#define AIE_TILE_TYPE_TILE	BIT(0)
+#define AIE_TILE_TYPE_SHIMPL	BIT(1)
+/* SHIM NOC tile includes SHIM PL and SHIM NOC modules */
+#define AIE_TILE_TYPE_SHIMNOC	BIT(2)
+
+/*
+ * Macros for attribute property of AI engine registers accessed by kernel
+ * 0 - 7 bits: tile type bits
+ * 8 - 15 bits: permission bits. If it is 1, it allows write from userspace
+ */
+#define AIE_REGS_ATTR_TILE_TYPE_SHIFT	0U
+#define AIE_REGS_ATTR_PERM_SHIFT	8U
+#define AIE_REGS_ATTR_TILE_TYPE_MASK	GENMASK(AIE_REGS_ATTR_PERM_SHIFT - 1, \
+						AIE_REGS_ATTR_TILE_TYPE_SHIFT)
+#define AIE_REGS_ATTR_PERM_MASK		GENMASK(15, \
+						AIE_REGS_ATTR_PERM_SHIFT)
+
+#define AIE_PART_STATUS_BRIDGE_DISABLED	0x1U
+
+/* Silicon Engineering Sample(ES) revision ID */
+#define VERSAL_ES1_REV_ID		0x0
+#define VERSAL_ES2_REV_ID		0x1
+
+#define AIE_NPI_ERROR_ID		BIT(1)
+
+/* Macros relevant to interrupts */
+#define AIE_INTR_L2_CTRL_MASK_WIDTH	32
+
+/*
+ * enum aie_shim_switch_type - identifies different switches in shim tile.
+ */
+enum aie_shim_switch_type {
+	AIE_SHIM_SWITCH_A,
+	AIE_SHIM_SWITCH_B
+};
+
+/**
+ * struct aie_tile_regs - contiguous range of AI engine register
+ *			  within an AI engine tile
+ * @soff: start offset of the range
+ * @eoff: end offset of the range
+ * @attribute: registers attribute. It uses AIE_REGS_ATTR_* macros defined
+ *	       above.
+ */
+struct aie_tile_regs {
+	size_t soff;
+	size_t eoff;
+	u32 attribute;
+};
+
+/**
+ * struct aie_single_reg_field - AI engine single field register attribute
+ * @mask: field mask
+ * @regoff: register offset of the field
+ */
+struct aie_single_reg_field {
+	u32 mask;
+	u32 regoff;
+};
+
+struct aie_device;
+struct aie_partition;
+
+/**
+ * struct aie_part_mem - AI engine partition memory information structure
+ * @apart: AI engine partition
+ * @dbuf: dmabuf pointer associated with the memory
+ * @mem: memory information of a type of memory
+ * @size: size of the total memories in the partition
+ *
+ * This structure is to keep the information of a type of memory in a
+ * partition. The memory information will be stored in @mem property.
+ * The following information will be keep:
+ *  * memory start address offset within a tile
+ *  * memory size
+ *  * what tiles contain this type of memory
+ */
+struct aie_part_mem {
+	struct aie_partition *apart;
+	struct dma_buf *dbuf;
+	struct aie_mem mem;
+	size_t size;
+};
+
+/**
+ * struct aie_dma_attr - AI engine DMA attributes structure
+ * @laddr: low address field attributes
+ * @haddr: high address field attributes
+ * @buflen: buffer length field attributes
+ * @bd_regoff: SHIM DMA buffer descriptors register offset
+ * @num_bds: number of buffer descriptors
+ * @bd_len: length of a buffer descriptor in bytes
+ */
+struct aie_dma_attr {
+	struct aie_single_reg_field laddr;
+	struct aie_single_reg_field haddr;
+	struct aie_single_reg_field buflen;
+	u32 bd_regoff;
+	u32 num_bds;
+	u32 bd_len;
+};
+
+/**
+ * struct aie_tile_operations - AI engine device operations
+ * @get_tile_type: get type of tile based on tile operation
+ * @get_mem_info: get different types of memories information
+ * @reset_shim: reset shim, it will assert and then release SHIM reset
+ * @init_part_clk_state: initialize clock states software structure which is a
+ *			 bitmap for the AI engine partition. The clock states
+ *			 structure is the structure used to keep track of if
+ *			 the modules in the AI engine partition are gated.
+ * @scan_part_clocks: scan partition modules to check whether the modules are
+ *		      clock gated or not, and update the soft clock states
+ *		      structure. It is required to be called when the partition
+ *		      is requested so that the driver knows which modules are
+ *		      clock gated when the partition is requested. This function
+ *		      expects the caller to apply partition lock before calling
+ *		      this function.
+ * @set_part_clocks: set partition modules clocks gate registers based on the
+ *		     partition clock states bitmap. This function expects the
+ *		     caller to apply partition lock before calling this
+ *		     function. The caller function will need to set the bitmap
+ *		     on which tiles are required to be clocked on.
+ *
+ * Different AI engine device version has its own device
+ * operation.
+ */
+struct aie_tile_operations {
+	u32 (*get_tile_type)(struct aie_location *loc);
+	unsigned int (*get_mem_info)(struct aie_range *range,
+				     struct aie_part_mem *pmem);
+	int (*reset_shim)(struct aie_device *adev, struct aie_range *range);
+	int (*init_part_clk_state)(struct aie_partition *apart);
+	int (*scan_part_clocks)(struct aie_partition *apart);
+	int (*set_part_clocks)(struct aie_partition *apart);
+};
+
+/**
+ * struct aie_resource - AI engine resource structure
+ * @bitmap: resource bitmap
+ * @total: total number of resource
+ */
+struct aie_resource {
+	unsigned long *bitmap;
+	u32 total;
+};
+
+/**
+ * struct aie_event_attr - AI Engine event attributes structure.
+ * @bc_event: broadcast event attribute to capture event mask value and
+ *	      register offset from @bc_regoff.
+ * @group_error: group error attribute to capture error group mask value and
+ *		 register offset value from @group_regoff.
+ * @bc_regoff: base broadcast register offset.
+ * @status_regoff: base status register offset.
+ * @group_regoff: base group error register offset.
+ * @base_error_event: event ID of first error event in a group error.
+ * @num_broadcasts: total number of broadcast events.
+ * @base_bc_event: broadcast 0 vent ID
+ * @num_events: total number of events.
+ */
+struct aie_event_attr {
+	struct aie_single_reg_field bc_event;
+	struct aie_single_reg_field group_error;
+	u32 bc_regoff;
+	u32 status_regoff;
+	u32 group_regoff;
+	u32 base_error_event;
+	u32 num_broadcasts;
+	u32 base_bc_event;
+	u32 num_events;
+};
+
+/**
+ * struct aie_l1_intr_ctrl_attr - AI engine level 1 interrupt controller
+ *				  attributes structure.
+ * @mask: level 1 interrupt controller mask attribute.
+ * @swa_status: switch A level 1 interrupt controller status attribute.
+ * @swb_status: switch A level 1 interrupt controller status attribute.
+ * @swa_event: switch A level 1 interrupt controller event attribute.
+ * @swb_event: switch A level 1 interrupt controller event attribute.
+ * @regoff: base level 1 interrupt controller register offset.
+ * @event_lsb: lsb of IRQ event within IRQ event switch register.
+ * @num_broadcasts: total number of broadcast signals to level 1 interrupt
+ *		    controller.
+ */
+struct aie_l1_intr_ctrl_attr {
+	struct aie_single_reg_field swa_status;
+	struct aie_single_reg_field swb_status;
+	struct aie_single_reg_field swa_event;
+	struct aie_single_reg_field swb_event;
+	u32 regoff;
+	u32 event_lsb;
+	u32 num_broadcasts;
+};
+
+/**
+ * struct aie_l2_intr_ctrl_attr - AI engine level 2 interrupt controller
+ *				  attributes structure.
+ * @mask: level 2 interrupt controller mask attribute.
+ * @enable: level 2 interrupt controller enable attribute.
+ * @disable: level 2 interrupt controller disable attribute.
+ * @status: level 2 interrupt controller status attribute.
+ * @regoff: level 2 interrupt controller register offset.
+ * @num_broadcasts: total number of broadcast signals to level 2 interrupt
+ *		    controller.
+ */
+struct aie_l2_intr_ctrl_attr {
+	struct aie_single_reg_field mask;
+	struct aie_single_reg_field enable;
+	struct aie_single_reg_field disable;
+	struct aie_single_reg_field status;
+	u32 regoff;
+	u32 num_broadcasts;
+};
+
+/**
+ * struct aie_error_cb - AI engine error callback struct.
+ * @cb: pointer to callback function.
+ * @priv: data to be passed to the callback function.
+ */
+struct aie_error_cb {
+	void (*cb)(void *priv);
+	void *priv;
+};
+
+/**
+ * struct aie_event_prop - AI engine event property.
+ * @event: error event ID.
+ * @event_str: error string.
+ */
+struct aie_event_prop {
+	u32 event;
+	char *event_str;
+};
+
+/**
+ * struct aie_err_category - AI engine errors category.
+ * @err_category: category of error.
+ * @num_events: number of event IDs in a category.
+ * @prop: pointer to an array event properties.
+ */
+struct aie_err_category {
+	u32 err_category;
+	u32 num_events;
+	const struct aie_event_prop *prop;
+};
+
+/**
+ * struct aie_error_attr - AI engine error attribute.
+ * @num_err_categories: number of possible error categories valid for a given
+ *			module.
+ * @err_category: pointer to an array of error categories.
+ */
+struct aie_error_attr {
+	u32 num_err_categories;
+	const struct aie_err_category *err_category;
+};
+
+/**
+ * struct aie_device - AI engine device structure
+ * @partitions: list of partitions requested
+ * @cdev: cdev for the AI engine
+ * @dev: device for the AI engine device
+ * @mlock: protection for AI engine device operations
+ * @base: AI engine device base virtual address
+ * @res: memory resource of AI engine device
+ * @eemi_ops: pointer to eemi ops structure
+ * @kernel_regs: array of kernel only registers
+ * @ops: tile operations
+ * @col_rst: column reset attribute
+ * @col_clkbuf: column clock buffer attribute
+ * @shim_dma: SHIM DMA attribute
+ * @pl_events: pl module event attribute
+ * @mem_events: memory module event attribute
+ * @core_events: core module event attribute
+ * @l1_ctrl: level 1 interrupt controller attribute
+ * @l2_ctrl: level 2 interrupt controller attribute
+ * @core_errors: core module error attribute
+ * @mem_errors: memory module error attribute
+ * @shim_errors: shim tile error attribute
+ * @size: size of the AI engine address space
+ * @array_shift: array address shift
+ * @col_shift: column address shift
+ * @row_shift: row address shift
+ * @cols_res: AI engine columns resources to indicate
+ *	      while columns are occupied by partitions.
+ * @num_kernel_regs: number of kernel only registers range
+ * @irq: Linux IRQ number
+ * @backtrack: workqueue to backtrack interrupt
+ * @version: AI engine device version
+ * @pm_node_id: AI Engine platform management node ID
+ */
+struct aie_device {
+	struct list_head partitions;
+	struct cdev cdev;
+	struct device dev;
+	struct mutex mlock; /* protection for AI engine partitions */
+	void __iomem *base;
+	struct resource *res;
+	const struct zynqmp_eemi_ops *eemi_ops;
+	const struct aie_tile_regs *kernel_regs;
+	const struct aie_tile_operations *ops;
+	const struct aie_single_reg_field *col_rst;
+	const struct aie_single_reg_field *col_clkbuf;
+	const struct aie_dma_attr *shim_dma;
+	const struct aie_event_attr *pl_events;
+	const struct aie_event_attr *mem_events;
+	const struct aie_event_attr *core_events;
+	const struct aie_l1_intr_ctrl_attr *l1_ctrl;
+	const struct aie_l2_intr_ctrl_attr *l2_ctrl;
+	const struct aie_error_attr *core_errors;
+	const struct aie_error_attr *mem_errors;
+	const struct aie_error_attr *shim_errors;
+	size_t size;
+	struct aie_resource cols_res;
+	u32 array_shift;
+	u32 col_shift;
+	u32 row_shift;
+	u32 num_kernel_regs;
+	int irq;
+	struct work_struct backtrack;
+	int version;
+	u32 pm_node_id;
+};
+
+/**
+ * struct aie_part_bridge - AI engine FPGA bridge
+ * @name: name of the FPGA bridge
+ * @br: pointer to FPGA bridge
+ */
+struct aie_part_bridge {
+	char name[32];
+	struct fpga_bridge *br;
+};
+
+/**
+ * struct aie_partition - AI engine partition structure
+ * @node: list node
+ * @dbufs: dmabufs list
+ * @adev: pointer to AI device instance
+ * @filep: pointer to file for refcount on the users of the partition
+ * @pmems: pointer to partition memories types
+ * @br: AI engine FPGA bridge
+ * @range: range of partition
+ * @mlock: protection for AI engine partition operations
+ * @dev: device for the AI engine partition
+ * @cores_clk_state: bitmap to indicate the power state of core modules
+ * @tiles_inuse: bitmap to indicate if a tile is in use
+ * @error_cb: error callback
+ * @core_event_status: core module event bitmap
+ * @mem_event_status: memory module event bitmap
+ * @pl_event_status: pl module event bitmap
+ * @l2_mask: level 2 interrupt controller mask bitmap
+ * @partition_id: partition id. Partition ID is the identifier
+ *		  of the AI engine partition in the system.
+ * @status: indicate if the partition is in use
+ * @cntrflag: partition control flag. e.g. whether to reset columns when
+ *	      the partition is released
+ * @error_to_report: indicates if there are errors pending to be reported to
+ *		     the application. This value is set to true if errors are
+ *		     found during backtracking, and error interrupt was
+ *		     received when partition was not requested yet.
+ */
+struct aie_partition {
+	struct list_head node;
+	struct list_head dbufs;
+	struct aie_part_bridge br;
+	struct aie_device *adev;
+	struct file *filep;
+	struct aie_part_mem *pmems;
+	struct aie_range range;
+	struct mutex mlock; /* protection for AI engine partition operations */
+	struct device dev;
+	struct aie_resource cores_clk_state;
+	struct aie_resource tiles_inuse;
+	struct aie_error_cb error_cb;
+	struct aie_resource core_event_status;
+	struct aie_resource mem_event_status;
+	struct aie_resource pl_event_status;
+	struct aie_resource l2_mask;
+	u32 partition_id;
+	u32 status;
+	u32 cntrflag;
+	u8 error_to_report;
+};
+
+extern struct class *aie_class;
+extern const struct file_operations aie_part_fops;
+
+#define cdev_to_aiedev(i_cdev) container_of((i_cdev), struct aie_device, cdev)
+#define dev_to_aiedev(_dev) container_of((_dev), struct aie_device, dev)
+#define dev_to_aiepart(_dev) container_of((_dev), struct aie_partition, dev)
+
+#define aie_col_mask(adev) ({ \
+	struct aie_device *_adev = (adev); \
+	GENMASK_ULL(_adev->array_shift - 1, _adev->col_shift);  \
+	})
+
+#define aie_row_mask(adev) ({ \
+	struct aie_device *_adev = (adev); \
+	GENMASK_ULL(_adev->col_shift - 1, _adev->row_shift);  \
+	})
+
+#define aie_tile_reg_mask(adev) ({ \
+	struct aie_device *_adev = (adev); \
+	GENMASK_ULL(_adev->row_shift - 1, 0);  \
+	})
+
+/*
+ * Need to define field get, as AI engine shift mask is not constant.
+ * Cannot use FIELD_GET()
+ */
+#define aie_tile_reg_field_get(mask, shift, regoff) ( \
+	((regoff) & (mask)) >> (shift))
+
+#define aie_cal_tile_reg(adev, regoff) ( \
+	aie_tile_reg_field_get(aie_tile_reg_mask(adev), 0, regoff))
+
+/**
+ * aie_get_field_val() - calculate value of an AI engine register field
+ * @field: a field in a register
+ * @val: value of the field
+ * @return: value of a register field
+ */
+static inline u32 aie_get_field_val(const struct aie_single_reg_field *field,
+				    u32 val)
+{
+	long long mask = (long long)field->mask & 0x00000000ffffffff;
+
+	return (val << __bf_shf(mask)) & field->mask;
+}
+
+/**
+ * aie_get_reg_field() - get value from a field from a register valuer
+ * @field: a field in a register
+ * @regval: register value
+ * @return: value of a register field
+ */
+static inline u32 aie_get_reg_field(const struct aie_single_reg_field *field,
+				    u32 regval)
+{
+	long long mask64 = (long long)field->mask & 0x00000000ffffffff;
+
+	return (regval & field->mask) >> __bf_shf(mask64);
+}
+
+/**
+ * aie_cal_regoff() - calculate register offset to the whole AI engine
+ *		      device start address
+ * @adev: AI engine device
+ * @loc: AI engine tile location
+ * @regoff_intile: register offset within a tile
+ * @return: register offset to the whole AI engine device start address
+ */
+static inline u32 aie_cal_regoff(struct aie_device *adev,
+				 struct aie_location loc, u32 regoff_intile)
+{
+	return regoff_intile + (loc.col << adev->col_shift) +
+	       (loc.row << adev->row_shift);
+}
+
+/**
+ * aie_validate_location() - validate tile location within an AI engine
+ *			     partition
+ * @apart: AI engine partition
+ * @loc: AI engine tile location
+ * @return: return 0 if it it is valid, negative value for errors.
+ *
+ * This function checks if the AI engine location is within the AI engine
+ * partition.
+ */
+static inline int aie_validate_location(struct aie_partition *apart,
+					struct aie_location loc)
+{
+	if (loc.col < apart->range.start.col ||
+	    loc.col >= apart->range.start.col + apart->range.size.col ||
+	    loc.row < apart->range.start.row ||
+	    loc.row >= apart->range.start.row + apart->range.size.row)
+		return -EINVAL;
+
+	return 0;
+}
+
+int aie_resource_initialize(struct aie_resource *res, int count);
+void aie_resource_uninitialize(struct aie_resource *res);
+int aie_resource_check_region(struct aie_resource *res, u32 start,
+			      u32 count);
+int aie_resource_get_region(struct aie_resource *res, u32 start,
+			    u32 count);
+void aie_resource_put_region(struct aie_resource *res, int start, u32 count);
+int aie_resource_set(struct aie_resource *res, u32 start, u32 count);
+int aie_resource_cpy_from_arr32(struct aie_resource *res, u32 start,
+				const u32 *src, u32 nbits);
+int aie_resource_cpy_to_arr32(struct aie_resource *res, u32 start, u32 *dst,
+			      u32 nbits);
+int aie_resource_clear(struct aie_resource *res, u32 start, u32 count);
+int aie_resource_clear_all(struct aie_resource *res);
+bool aie_resource_testbit(struct aie_resource *res, u32 bit);
+
+const struct file_operations *aie_part_get_fops(void);
+u8 aie_part_in_use(struct aie_partition *apart);
+struct aie_partition *aie_get_partition_from_id(struct aie_device *adev,
+						u32 partition_id);
+struct aie_partition *of_aie_part_probe(struct aie_device *adev,
+					struct device_node *nc);
+void aie_part_remove(struct aie_partition *apart);
+int aie_part_clean(struct aie_partition *apart);
+
+int aie_fpga_create_bridge(struct aie_partition *apart);
+void aie_fpga_free_bridge(struct aie_partition *apart);
+
+int aie_mem_get_info(struct aie_partition *apart, unsigned long arg);
+
+long aie_part_attach_dmabuf_req(struct aie_partition *apart,
+				void __user *user_args);
+long aie_part_detach_dmabuf_req(struct aie_partition *apart,
+				void __user *user_args);
+long aie_part_set_bd(struct aie_partition *apart, void __user *user_args);
+long aie_part_set_dmabuf_bd(struct aie_partition *apart,
+			    void __user *user_args);
+void aie_part_release_dmabufs(struct aie_partition *apart);
+
+int aie_part_scan_clk_state(struct aie_partition *apart);
+bool aie_part_check_clk_enable_loc(struct aie_partition *apart,
+				   struct aie_location *loc);
+int aie_part_request_tiles_from_user(struct aie_partition *apart,
+				     void __user *user_args);
+int aie_part_release_tiles_from_user(struct aie_partition *apart,
+				     void __user *user_args);
+int aie_device_init(struct aie_device *adev);
+
+void aie_array_backtrack(struct work_struct *work);
+irqreturn_t aie_interrupt(int irq, void *data);
+void aie_part_clear_cached_events(struct aie_partition *apart);
+
+bool aie_part_has_mem_mmapped(struct aie_partition *apart);
+bool aie_part_has_regs_mmapped(struct aie_partition *apart);
+
+int aie_part_reset(struct aie_partition *apart);
+int aie_part_post_reinit(struct aie_partition *apart);
+#endif /* AIE_INTERNAL_H */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/xilinx-ai-engine/ai-engine-interrupt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/xilinx-ai-engine/ai-engine-interrupt.c
@@ -0,0 +1,1215 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx AI Engine device driver
+ *
+ * Copyright (C) 2020 Xilinx, Inc.
+ */
+#include <linux/bitmap.h>
+#include <linux/firmware/xlnx-zynqmp.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+
+#include "ai-engine-internal.h"
+#include "linux/xlnx-ai-engine.h"
+
+#define AIE_ARRAY_TILE_ERROR_BC_ID		0U
+#define AIE_SHIM_TILE_ERROR_IRQ_ID		16U
+
+/**
+ * aie_get_broadcast_event() - get event ID being broadcast on given
+ *			       broadcast line.
+ * @apart: AIE partition pointer.
+ * @loc: pointer to tile location.
+ * @module: module type.
+ * @bc_id: broadcast ID.
+ * @return: event ID.
+ */
+static u8 aie_get_broadcast_event(struct aie_partition *apart,
+				  struct aie_location *loc,
+				  enum aie_module_type module, u8 bc_id)
+{
+	const struct aie_event_attr *event_mod;
+	u32 bcoff, regoff;
+
+	if (module == AIE_CORE_MOD)
+		event_mod = apart->adev->core_events;
+	else if (module == AIE_MEM_MOD)
+		event_mod = apart->adev->mem_events;
+	else
+		event_mod = apart->adev->pl_events;
+
+	bcoff = event_mod->bc_regoff + event_mod->bc_event.regoff + bc_id * 4U;
+	regoff = aie_cal_regoff(apart->adev, *loc, bcoff);
+	return ioread32(apart->adev->base + regoff);
+}
+
+/**
+ * aie_read_event_status() - get the status of event status registers.
+ * @apart: AIE partition pointer.
+ * @loc: pointer to tile location.
+ * @module: module type.
+ * @reg: array to store event status register values.
+ */
+static void aie_read_event_status(struct aie_partition *apart,
+				  struct aie_location *loc,
+				  enum aie_module_type module, u32 *reg)
+{
+	const struct aie_event_attr *event_mod;
+	u8 offset;
+
+	if (module == AIE_CORE_MOD)
+		event_mod = apart->adev->core_events;
+	else if (module == AIE_MEM_MOD)
+		event_mod = apart->adev->mem_events;
+	else
+		event_mod = apart->adev->pl_events;
+
+	for (offset = 0; offset < (event_mod->num_events / 32); offset++) {
+		u32 status_off = event_mod->status_regoff + offset * 4U;
+		u32 regoff = aie_cal_regoff(apart->adev, *loc, status_off);
+
+		reg[offset] = ioread32(apart->adev->base + regoff);
+	}
+}
+
+/**
+ * aie_clear_event_status() - clears the status of event.
+ * @apart: AIE partition pointer.
+ * @loc: pointer to tile location.
+ * @module: module type.
+ * @event: event ID.
+ */
+static void aie_clear_event_status(struct aie_partition *apart,
+				   struct aie_location *loc,
+				   enum aie_module_type module, u8 event)
+{
+	const struct aie_event_attr *event_mod;
+	u32 status_off, regoff;
+
+	if (module == AIE_CORE_MOD)
+		event_mod = apart->adev->core_events;
+	else if (module == AIE_MEM_MOD)
+		event_mod = apart->adev->mem_events;
+	else
+		event_mod = apart->adev->pl_events;
+
+	if (event >= event_mod->num_events)
+		return;
+
+	status_off = event_mod->status_regoff + (event / 32) * 4U;
+	regoff = aie_cal_regoff(apart->adev, *loc, status_off);
+	iowrite32(BIT(event % 32), apart->adev->base + regoff);
+}
+
+/**
+ * aie_check_group_errors_enabled() - get error events enabled in group error.
+ * @apart: AIE partition pointer.
+ * @loc: pointer to tile location.
+ * @module: module type.
+ * @return: bitmap of enabled error events.
+ */
+static u32 aie_check_group_errors_enabled(struct aie_partition *apart,
+					  struct aie_location *loc,
+					  enum aie_module_type module)
+{
+	const struct aie_event_attr *event_mod;
+	u32 groff, regoff;
+
+	if (module == AIE_CORE_MOD)
+		event_mod = apart->adev->core_events;
+	else if (module == AIE_MEM_MOD)
+		event_mod = apart->adev->mem_events;
+	else
+		event_mod = apart->adev->pl_events;
+
+	groff = event_mod->group_regoff + event_mod->group_error.regoff;
+	regoff = aie_cal_regoff(apart->adev, *loc, groff);
+	return ioread32(apart->adev->base + regoff);
+}
+
+/**
+ * aie_set_error_event() - enable/disable error events in group error.
+ * @apart: AIE partition pointer.
+ * @loc: pointer to tile location.
+ * @module: module type.
+ * @bitmap: error event to enable/disable in group errors.
+ */
+static void aie_set_error_event(struct aie_partition *apart,
+				struct aie_location *loc,
+				enum aie_module_type module, u32 bitmap)
+{
+	const struct aie_event_attr *event_mod;
+	u32 groff, regoff;
+
+	if (module == AIE_CORE_MOD)
+		event_mod = apart->adev->core_events;
+	else if (module == AIE_MEM_MOD)
+		event_mod = apart->adev->mem_events;
+	else
+		event_mod = apart->adev->pl_events;
+
+	groff = event_mod->group_regoff + event_mod->group_error.regoff;
+	regoff = aie_cal_regoff(apart->adev, *loc, groff);
+	iowrite32(bitmap, apart->adev->base + regoff);
+}
+
+/**
+ * aie_get_error_event() - map group error status bit to actual error
+ *			   event number.
+ * @apart: AIE partition pointer.
+ * @loc: pointer to tile location.
+ * @module: module type.
+ * @index: event index within group errors.
+ * @return: true event ID.
+ */
+static u32 aie_get_error_event(struct aie_partition *apart,
+			       struct aie_location *loc,
+			       enum aie_module_type module, u8 index)
+{
+	const struct aie_event_attr *event_mod;
+
+	if (module == AIE_CORE_MOD)
+		event_mod = apart->adev->core_events;
+	else if (module == AIE_MEM_MOD)
+		event_mod = apart->adev->mem_events;
+	else
+		event_mod = apart->adev->pl_events;
+
+	return event_mod->base_error_event + index;
+}
+
+/**
+ * aie_get_bc_event() - get the broadcast event ID.
+ * @apart: AIE partition pointer.
+ * @loc: pointer to tile location.
+ * @module: module type.
+ * @bc_id: broadcast line ID.
+ * @return: broadcast event ID.
+ */
+static u32 aie_get_bc_event(struct aie_partition *apart,
+			    struct aie_location *loc,
+			    enum aie_module_type module, u8 bc_id)
+{
+	const struct aie_event_attr *event_mod;
+
+	if (module == AIE_CORE_MOD)
+		event_mod = apart->adev->core_events;
+	else if (module == AIE_MEM_MOD)
+		event_mod = apart->adev->mem_events;
+	else
+		event_mod = apart->adev->pl_events;
+
+	return event_mod->base_bc_event + bc_id;
+}
+
+/**
+ * aie_get_l1_event() - get event ID being broadcast on level 1 IRQ.
+ * @apart: AIE partition pointer.
+ * @loc: pointer to tile location.
+ * @sw: switch type.
+ * @irq_id: IRQ event ID to be read.
+ * @return: true event ID.
+ */
+static u8 aie_get_l1_event(struct aie_partition *apart,
+			   struct aie_location *loc,
+			   enum aie_shim_switch_type sw, u8 irq_id)
+{
+	const struct aie_l1_intr_ctrl_attr *intr_ctrl = apart->adev->l1_ctrl;
+	u32 l1off, l1mask, regoff, reg_value;
+
+	if (sw == AIE_SHIM_SWITCH_A) {
+		l1off = intr_ctrl->regoff + intr_ctrl->swa_event.regoff;
+		l1mask = intr_ctrl->swa_event.mask;
+	} else {
+		l1off = intr_ctrl->regoff + intr_ctrl->swb_event.regoff;
+		l1mask = intr_ctrl->swb_event.mask;
+	}
+
+	regoff = aie_cal_regoff(apart->adev, *loc, l1off);
+	reg_value = ioread32(apart->adev->base + regoff);
+	reg_value &= l1mask << (irq_id * intr_ctrl->event_lsb);
+	reg_value >>= (irq_id * intr_ctrl->event_lsb);
+	return reg_value;
+}
+
+/**
+ * aie_clear_l1_intr() - clear level 1 interrupt controller status.
+ * @apart: AIE partition pointer.
+ * @loc: pointer to tile location.
+ * @sw: switch type.
+ * @irq_id: IRQ ID to be cleared.
+ */
+static void aie_clear_l1_intr(struct aie_partition *apart,
+			      struct aie_location *loc,
+			      enum aie_shim_switch_type sw, u8 irq_id)
+{
+	const struct aie_l1_intr_ctrl_attr *intr_ctrl = apart->adev->l1_ctrl;
+	u32 l1off, regoff;
+
+	if (sw == AIE_SHIM_SWITCH_A)
+		l1off = intr_ctrl->regoff + intr_ctrl->swa_status.regoff;
+	else
+		l1off = intr_ctrl->regoff + intr_ctrl->swb_status.regoff;
+
+	regoff = aie_cal_regoff(apart->adev, *loc, l1off);
+	iowrite32(BIT(irq_id), apart->adev->base + regoff);
+}
+
+/**
+ * aie_get_l1_status() - get level 1 interrupt controller status value.
+ * @apart: AIE partition pointer.
+ * @loc: pointer to tile location.
+ * @sw: switch type.
+ * @return: status value.
+ */
+static u32 aie_get_l1_status(struct aie_partition *apart,
+			     struct aie_location *loc,
+			     enum aie_shim_switch_type sw)
+{
+	const struct aie_l1_intr_ctrl_attr *intr_ctrl = apart->adev->l1_ctrl;
+	u32 l1off, regoff;
+
+	if (sw == AIE_SHIM_SWITCH_A)
+		l1off = intr_ctrl->regoff + intr_ctrl->swa_status.regoff;
+	else
+		l1off = intr_ctrl->regoff + intr_ctrl->swb_status.regoff;
+
+	regoff = aie_cal_regoff(apart->adev, *loc, l1off);
+	return ioread32(apart->adev->base + regoff);
+}
+
+/**
+ * aie_clear_l2_intr() - clear level 2 interrupt controller status.
+ * @apart: AIE partition pointer.
+ * @loc: pointer to tile location.
+ * @bitmap_irq: IRQ bitmap. IRQ lines corresponding to set bits will be
+ *		cleared.
+ */
+static void aie_clear_l2_intr(struct aie_partition *apart,
+			      struct aie_location *loc, u32 bitmap_irq)
+{
+	const struct aie_l2_intr_ctrl_attr *intr_ctrl = apart->adev->l2_ctrl;
+	u32 l2off = intr_ctrl->regoff + intr_ctrl->status.regoff;
+	u32 regoff = aie_cal_regoff(apart->adev, *loc, l2off);
+
+	iowrite32(bitmap_irq, apart->adev->base + regoff);
+}
+
+/**
+ * aie_get_l2_status() - get level 2 interrupt controller status value.
+ * @apart: AIE partition pointer.
+ * @loc: pointer to tile location.
+ * @return: status value.
+ */
+static u32 aie_get_l2_status(struct aie_partition *apart,
+			     struct aie_location *loc)
+{
+	const struct aie_l2_intr_ctrl_attr *intr_ctrl = apart->adev->l2_ctrl;
+	u32 l2off = intr_ctrl->regoff + intr_ctrl->status.regoff;
+	u32 regoff = aie_cal_regoff(apart->adev, *loc, l2off);
+
+	return ioread32(apart->adev->base + regoff);
+}
+
+/**
+ * aie_get_l2_mask() - get level 2 interrupt controller mask value.
+ * @apart: AIE partition pointer.
+ * @loc: pointer to tile location.
+ * @return: mask value.
+ */
+static u32 aie_get_l2_mask(struct aie_partition *apart,
+			   struct aie_location *loc)
+{
+	const struct aie_l2_intr_ctrl_attr *intr_ctrl = apart->adev->l2_ctrl;
+	u32 l2off = intr_ctrl->regoff + intr_ctrl->mask.regoff;
+	u32 regoff = aie_cal_regoff(apart->adev, *loc, l2off);
+
+	return ioread32(apart->adev->base + regoff);
+}
+
+/**
+ * aie_enable_l2_ctrl() - enable interrupts to level 2 interrupt controller.
+ * @apart: AIE partition pointer.
+ * @loc: pointer to tile location.
+ * @bit_map: bitmap of broadcast lines to enable.
+ */
+static void aie_enable_l2_ctrl(struct aie_partition *apart,
+			       struct aie_location *loc, u32 bit_map)
+{
+	const struct aie_l2_intr_ctrl_attr *intr_ctrl = apart->adev->l2_ctrl;
+	u32 l2off = intr_ctrl->regoff + intr_ctrl->enable.regoff;
+	u32 regoff = aie_cal_regoff(apart->adev, *loc, l2off);
+
+	bit_map &= intr_ctrl->enable.mask;
+	iowrite32(bit_map, apart->adev->base + regoff);
+}
+
+/**
+ * aie_disable_l2_ctrl() - disable interrupts to level 2 interrupt controller.
+ * @apart: AIE partition pointer.
+ * @loc: pointer to tile location.
+ * @bit_map: bitmap of broadcast lines to disable.
+ */
+static void aie_disable_l2_ctrl(struct aie_partition *apart,
+				struct aie_location *loc, u32 bit_map)
+{
+	const struct aie_l2_intr_ctrl_attr *intr_ctrl = apart->adev->l2_ctrl;
+	u32 l2off = intr_ctrl->regoff + intr_ctrl->disable.regoff;
+	u32 regoff = aie_cal_regoff(apart->adev, *loc, l2off);
+
+	bit_map &= intr_ctrl->disable.mask;
+	iowrite32(bit_map, apart->adev->base + regoff);
+}
+
+/**
+ * aie_part_set_event_bitmap() - set the status of event in local event
+ *				 bitmap.
+ * @apart: AIE partition pointer.
+ * @loc: tile location.
+ * @module: module type.
+ * @event: event ID to be logged.
+ */
+static void aie_part_set_event_bitmap(struct aie_partition *apart,
+				      struct aie_location loc,
+				      enum aie_module_type module, u8 event)
+{
+	u8 row, col, mod_num_events;
+	struct aie_resource *event_sts;
+	u32 offset;
+
+	if (module == AIE_CORE_MOD) {
+		event_sts = &apart->core_event_status;
+		mod_num_events = apart->adev->core_events->num_events;
+		row = loc.row - apart->range.start.row - 1;
+	} else if (module == AIE_MEM_MOD) {
+		event_sts = &apart->mem_event_status;
+		mod_num_events = apart->adev->mem_events->num_events;
+		row = loc.row - apart->range.start.row - 1;
+	} else {
+		event_sts = &apart->pl_event_status;
+		mod_num_events = apart->adev->pl_events->num_events;
+		row = loc.row;
+	}
+
+	col = loc.col - apart->range.start.col;
+
+	offset = (col + row * apart->range.size.col) * mod_num_events + event;
+	aie_resource_set(event_sts, offset, 1);
+}
+
+/**
+ * aie_check_error_bitmap() - check the status of event in local event bitmap.
+ * @apart: AIE partition pointer.
+ * @loc: tile location.
+ * @module: module type.
+ * @event: event ID to check.
+ * @return: true if event has happened, else false.
+ */
+static bool aie_check_error_bitmap(struct aie_partition *apart,
+				   struct aie_location loc,
+				   enum aie_module_type module, u8 event)
+{
+	struct aie_resource *event_sts;
+	u32 offset;
+	u8 row, col, mod_num_events;
+
+	if (module == AIE_CORE_MOD) {
+		event_sts = &apart->core_event_status;
+		mod_num_events = apart->adev->core_events->num_events;
+		row = loc.row - apart->range.start.row - 1;
+	} else if (module == AIE_MEM_MOD) {
+		event_sts = &apart->mem_event_status;
+		mod_num_events = apart->adev->mem_events->num_events;
+		row = loc.row - apart->range.start.row - 1;
+	} else {
+		event_sts = &apart->pl_event_status;
+		mod_num_events = apart->adev->pl_events->num_events;
+		row = loc.row;
+	}
+
+	col = loc.col - apart->range.start.col;
+
+	offset = (col + row * apart->range.size.col) * mod_num_events + event;
+	return aie_resource_testbit(event_sts, offset);
+}
+
+/**
+ * aie_tile_backtrack() - if error was asserted on a broadcast line in
+ *			  the given array tile,
+ *				* disable the error from the group errors
+ *				* record the error event in local bitmap
+ * @apart: AIE partition pointer.
+ * @loc: tile location.
+ * @module: module type.
+ * @sw: switch type.
+ * @bc_id: broadcast ID.
+ * @return: true if error was asserted, else return false.
+ */
+static bool aie_tile_backtrack(struct aie_partition *apart,
+			       struct aie_location loc,
+			       enum aie_module_type module,
+			       enum aie_shim_switch_type sw, u8 bc_id)
+{
+	unsigned long grenabled;
+	u32 status[4];
+	u8 n, grevent, eevent;
+	bool ret = false;
+
+	if (module == AIE_PL_MOD)
+		grevent = aie_get_l1_event(apart, &loc, sw, bc_id);
+	else
+		grevent = aie_get_broadcast_event(apart, &loc, module, bc_id);
+
+	aie_read_event_status(apart, &loc, module, status);
+
+	if (!(status[grevent / 32] & BIT(grevent % 32)))
+		return ret;
+
+	grenabled = aie_check_group_errors_enabled(apart, &loc, module);
+	for_each_set_bit(n, &grenabled, 32) {
+		eevent = aie_get_error_event(apart, &loc, module, n);
+		if (!(status[eevent / 32] & BIT(eevent % 32)))
+			continue;
+		grenabled &= ~BIT(n);
+		aie_part_set_event_bitmap(apart, loc, module, eevent);
+		ret = true;
+		dev_err_ratelimited(&apart->adev->dev,
+				    "Asserted tile error event %d at col %d row %d\n",
+				    eevent, loc.col, loc.row);
+	}
+	aie_set_error_event(apart, &loc, module, grenabled);
+
+	return ret;
+}
+
+/**
+ * aie_map_l2_to_l1() - map the status bit set in level 2 interrupt controller
+ *		        to a level 1 interrupt controller.
+ * @apart: AIE partition pointer.
+ * @set_pos: position of level 2 set bit.
+ * @l2_col: level 2 interrupt controller column ID.
+ * @l1_col: pointer to return corresponding level 1 column ID.
+ * @sw: pointer to return the level 1 interrupt controller switch ID.
+ *
+ * This API implementation is tightly coupled with the level 2 to level 1
+ * static mapping created when AIE application CDOs are generated.
+ */
+static void aie_map_l2_to_l1(struct aie_partition *apart, u32 set_pos,
+			     u32 l2_col, u32 *l1_col,
+			     enum aie_shim_switch_type *sw)
+{
+	if (l2_col + 3 >= apart->range.start.col + apart->range.size.col) {
+		*l1_col = l2_col + (set_pos % 6) / 2;
+		*sw = (set_pos % 6) % 2;
+	} else if (l2_col % 2 == 0) {
+		/* set bit position could be 0 - 5 */
+		*l1_col = l2_col - (2 - (set_pos % 6) / 2);
+		*sw = (set_pos % 6) % 2;
+	} else {
+		/* set bit position could be 0 - 1 */
+		*l1_col = l2_col;
+		*sw = set_pos;
+	}
+}
+
+/**
+ * aie_l1_backtrack() - backtrack AIE array tiles or shim tile based on
+ *			the level 2 status bit set.
+ * @apart: AIE partition pointer.
+ * @loc: tile location of level 2 interrupt controller.
+ * @set_pos: set bit position in level 2 controller status.
+ * @return: true if error was asserted, else return false.
+ */
+static bool aie_l1_backtrack(struct aie_partition *apart,
+			     struct aie_location loc, u32 set_pos)
+{
+	struct aie_location l1_ctrl;
+	enum aie_shim_switch_type sw;
+	unsigned long status;
+	u32 srow = apart->range.start.row + 1;
+	u32 erow = apart->range.start.row + apart->range.size.row;
+	bool ret = false;
+
+	/*
+	 * Based on the set status bit find which level 1 interrupt
+	 * controller has generated an interrupt
+	 */
+	l1_ctrl.row = 0;
+	aie_map_l2_to_l1(apart, set_pos, loc.col, &l1_ctrl.col, &sw);
+
+	status = aie_get_l1_status(apart, &l1_ctrl, sw);
+
+	/* For now, support error broadcasts only */
+	if (status & BIT(AIE_ARRAY_TILE_ERROR_BC_ID)) {
+		struct aie_location temp;
+		enum aie_module_type module;
+		u32 bc_event;
+
+		if (sw == AIE_SHIM_SWITCH_A)
+			module = AIE_CORE_MOD;
+		else
+			module = AIE_MEM_MOD;
+
+		aie_clear_l1_intr(apart, &l1_ctrl, sw,
+				  AIE_ARRAY_TILE_ERROR_BC_ID);
+
+		temp.row = srow;
+		temp.col = l1_ctrl.col;
+		bc_event = aie_get_bc_event(apart, &temp, module,
+					    AIE_ARRAY_TILE_ERROR_BC_ID);
+		for (; temp.row < erow; temp.row++) {
+			u32 reg[4];
+
+			if (!aie_part_check_clk_enable_loc(apart, &temp))
+				break;
+
+			if (aie_tile_backtrack(apart, temp, module, sw,
+					       AIE_ARRAY_TILE_ERROR_BC_ID))
+				ret = true;
+
+			aie_read_event_status(apart, &temp, module, reg);
+			if (!(reg[bc_event / 32] & BIT(bc_event % 32)))
+				break;
+
+			aie_clear_event_status(apart, &temp, module, bc_event);
+		}
+	}
+
+	if (status & BIT(AIE_SHIM_TILE_ERROR_IRQ_ID)) {
+		aie_clear_l1_intr(apart, &l1_ctrl, sw,
+				  AIE_SHIM_TILE_ERROR_IRQ_ID);
+		if (aie_tile_backtrack(apart, l1_ctrl, AIE_PL_MOD, sw,
+				       AIE_SHIM_TILE_ERROR_IRQ_ID))
+			ret = true;
+	}
+	return ret;
+}
+
+/**
+ * aie_l2_backtrack() - iterate through each level 2 interrupt controller
+ *			in a given partition and backtrack its
+ *			corresponding level 1 interrupt controller.
+ * @apart: AIE partition pointer
+ */
+static void aie_l2_backtrack(struct aie_partition *apart)
+{
+	struct aie_location loc;
+	unsigned long l2_mask = 0;
+	u32 n, ttype, l2_bitmap_offset = 0;
+	int ret;
+	bool sched_work = false;
+
+	ret = mutex_lock_interruptible(&apart->mlock);
+	if (ret) {
+		dev_err_ratelimited(&apart->dev,
+				    "Failed to acquire lock. Process was interrupted by fatal signals\n");
+		return;
+	}
+
+	for (loc.col = apart->range.start.col, loc.row = 0;
+	     loc.col < apart->range.start.col + apart->range.size.col;
+	     loc.col++) {
+		ttype = apart->adev->ops->get_tile_type(&loc);
+		if (ttype != AIE_TILE_TYPE_SHIMNOC)
+			continue;
+
+		aie_resource_cpy_to_arr32(&apart->l2_mask, l2_bitmap_offset *
+					  32, (u32 *)&l2_mask, 32);
+		l2_bitmap_offset++;
+
+		for_each_set_bit(n, &l2_mask,
+				 apart->adev->l2_ctrl->num_broadcasts) {
+			if (aie_l1_backtrack(apart, loc, n))
+				apart->error_to_report = 1;
+		}
+
+		aie_enable_l2_ctrl(apart, &loc, l2_mask);
+	}
+
+	/*
+	 * Level 2 interrupt registers are edge-triggered. As a result,
+	 * re-enabling level 2 won't trigger an interrupt for the already
+	 * latched interrupts at level 1 controller.
+	 */
+	for (loc.col = apart->range.start.col, loc.row = 0;
+	     loc.col < apart->range.start.col + apart->range.size.col;
+	     loc.col++) {
+		if (aie_get_l1_status(apart, &loc, AIE_SHIM_SWITCH_A) ||
+		    aie_get_l1_status(apart, &loc, AIE_SHIM_SWITCH_B)) {
+			mutex_unlock(&apart->mlock);
+			sched_work = true;
+			schedule_work(&apart->adev->backtrack);
+			break;
+		}
+	}
+
+	if (!sched_work)
+		mutex_unlock(&apart->mlock);
+
+	/*
+	 * If error was asserted or there are errors pending to be reported to
+	 * the application, then invoke callback.
+	 */
+	if (apart->error_cb.cb && apart->error_to_report) {
+		apart->error_to_report = 0;
+		apart->error_cb.cb(apart->error_cb.priv);
+	}
+}
+
+/**
+ * aie_part_backtrack() - backtrack a individual.
+ * @apart: AIE partition pointer.
+ */
+static void aie_part_backtrack(struct aie_partition *apart)
+{
+	aie_l2_backtrack(apart);
+}
+
+/**
+ * aie_array_backtrack() - backtrack each partition to find the source of error
+ *			   interrupt.
+ * @work: pointer to the work structure.
+ *
+ * This task will re-enable IRQ after errors in all partitions has been
+ * serviced.
+ */
+void aie_array_backtrack(struct work_struct *work)
+{
+	struct aie_device *adev;
+	struct aie_partition *apart;
+	int ret;
+
+	adev = container_of(work, struct aie_device, backtrack);
+
+	ret = mutex_lock_interruptible(&adev->mlock);
+	if (ret) {
+		dev_err_ratelimited(&adev->dev,
+				    "Failed to acquire lock. Process was interrupted by fatal signals\n");
+		return;
+	}
+
+	list_for_each_entry(apart, &adev->partitions, node) {
+		/*
+		 * If partition isn't requested yet, then only record the
+		 * occurrence of error interrupt. Such errors can only be
+		 * backtracked when the tiles in-use are known. Based on the
+		 * error_to_report value a task is scheduled in the workqueue
+		 * to backtrack this error interrupt when partition is
+		 * requested.
+		 */
+		if (!apart->status) {
+			apart->error_to_report = 1;
+			continue;
+		}
+		aie_part_backtrack(apart);
+	}
+
+	mutex_unlock(&adev->mlock);
+}
+
+/**
+ * aie_interrupt() - interrupt handler for AIE.
+ * @irq: Interrupt number.
+ * @data: AI engine device structure.
+ * @return: IRQ_HANDLED.
+ *
+ * This thread function disables level 2 interrupt controllers and schedules a
+ * task in workqueue to backtrack the source of error interrupt. Disabled
+ * interrupts are re-enabled after successful completion of bottom half.
+ */
+irqreturn_t aie_interrupt(int irq, void *data)
+{
+	struct aie_device *adev = data;
+	struct aie_partition *apart;
+	int ret;
+	bool sched_work = false;
+
+	ret = mutex_lock_interruptible(&adev->mlock);
+	if (ret) {
+		dev_err(&adev->dev,
+			"Failed to acquire lock. Process was interrupted by fatal signals\n");
+		return IRQ_NONE;
+	}
+
+	list_for_each_entry(apart, &adev->partitions, node) {
+		struct aie_location loc;
+		u32 ttype, l2_mask, l2_status, l2_bitmap_offset  = 0;
+
+		ret = mutex_lock_interruptible(&apart->mlock);
+		if (ret) {
+			dev_err(&apart->dev,
+				"Failed to acquire lock. Process was interrupted by fatal signals\n");
+			return IRQ_NONE;
+		}
+
+		for (loc.col = apart->range.start.col, loc.row = 0;
+		     loc.col < apart->range.start.col + apart->range.size.col;
+		     loc.col++) {
+			ttype = apart->adev->ops->get_tile_type(&loc);
+			if (ttype != AIE_TILE_TYPE_SHIMNOC)
+				continue;
+
+			l2_mask = aie_get_l2_mask(apart, &loc);
+			if (l2_mask) {
+				aie_resource_cpy_from_arr32(&apart->l2_mask,
+							    l2_bitmap_offset  *
+							    32, &l2_mask, 32);
+				aie_disable_l2_ctrl(apart, &loc, l2_mask);
+			}
+			l2_bitmap_offset++;
+
+			l2_status = aie_get_l2_status(apart, &loc);
+			if (l2_status) {
+				aie_clear_l2_intr(apart, &loc, l2_status);
+				sched_work = true;
+			} else {
+				aie_enable_l2_ctrl(apart, &loc, l2_mask);
+			}
+		}
+		mutex_unlock(&apart->mlock);
+	}
+
+	/* For ES1 silicon, interrupts are latched in NPI */
+	if (adev->version == VERSAL_ES1_REV_ID) {
+		ret = adev->eemi_ops->ioctl(adev->pm_node_id,
+					    IOCTL_AIE_ISR_CLEAR,
+					    AIE_NPI_ERROR_ID, 0, NULL);
+		if (ret < 0)
+			dev_err(&adev->dev, "Failed to clear NPI ISR\n");
+	}
+
+	mutex_unlock(&adev->mlock);
+
+	if (sched_work)
+		schedule_work(&adev->backtrack);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * aie_get_module_error_count() - get the total count of errors in a module
+ *				  from local bitmap.
+ * @apart: AIE partition pointer.
+ * @loc: tile location.
+ * @module: module type.
+ * @err_attr: error attribute for given module type.
+ * @return: total number of errors found.
+ */
+static u32 aie_get_module_error_count(struct aie_partition *apart,
+				      struct aie_location loc,
+				      enum aie_module_type module,
+				      const struct aie_error_attr *err_attr)
+{
+	u32 count = 0;
+	u8 i, j;
+
+	for (i = 0; i < err_attr->num_err_categories; i++) {
+		for (j = 0; j < err_attr->err_category[i].num_events; j++) {
+			u8 event = err_attr->err_category[i].prop[j].event;
+
+			if (aie_check_error_bitmap(apart, loc, module, event))
+				count++;
+		}
+	}
+	return count;
+}
+
+/**
+ * aie_get_error_count() - get the total count of errors in a partition from
+ *			   local bitmap.
+ * @apart: AIE partition pointer.
+ * @return: total number of errors found.
+ */
+static u32 aie_get_error_count(struct aie_partition *apart)
+{
+	const struct aie_error_attr *core_errs = apart->adev->core_errors;
+	const struct aie_error_attr *mem_errs = apart->adev->mem_errors;
+	const struct aie_error_attr *shim_errs = apart->adev->shim_errors;
+	struct aie_location loc;
+	u32 ttype, num = 0;
+
+	for (loc.col = apart->range.start.col;
+	     loc.col < apart->range.size.col; loc.col++) {
+		for (loc.row = apart->range.start.row;
+		     loc.row < apart->range.size.row; loc.row++) {
+			ttype = apart->adev->ops->get_tile_type(&loc);
+			if (ttype == AIE_TILE_TYPE_TILE) {
+				num += aie_get_module_error_count(apart, loc,
+								  AIE_CORE_MOD,
+								  core_errs);
+				num += aie_get_module_error_count(apart, loc,
+								  AIE_MEM_MOD,
+								  mem_errs);
+			} else {
+				num += aie_get_module_error_count(apart, loc,
+								  AIE_PL_MOD,
+								  shim_errs);
+			}
+		}
+	}
+
+	return num;
+}
+
+/**
+ * aie_get_errors_from_bitmap() - get status of errors from local bitmap.
+ * @apart: AIE partition pointer.
+ * @loc: tile location.
+ * @module: module type.
+ * @err_attr: error attribute for given module type.
+ * @aie_err: pointer to array of error structure.
+ * @return: total number of errors found.
+ *
+ * This function parses local bitmaps and initializes @aie_err structures with
+ * the tile location of error event, module type and, its event ID.
+ */
+static u32 aie_get_errors_from_bitmap(struct aie_partition *apart,
+				      struct aie_location loc,
+				      enum aie_module_type module,
+				      const struct aie_error_attr *err_attr,
+				      struct aie_error *aie_err)
+{
+	u8 i, j;
+	u32 num_err = 0;
+
+	for (i = 0; i < err_attr->num_err_categories; i++) {
+		const struct aie_err_category *category;
+
+		category = &err_attr->err_category[i];
+		for (j = 0; j < category->num_events; j++) {
+			u8 event = category->prop[j].event;
+
+			if (!aie_check_error_bitmap(apart, loc, module, event))
+				continue;
+
+			aie_err[num_err].loc.col = loc.col;
+			aie_err[num_err].loc.row = loc.row;
+			aie_err[num_err].module = module;
+			aie_err[num_err].error_id = event;
+			aie_err[num_err].category = category->err_category;
+			num_err++;
+		}
+	}
+	return num_err;
+}
+
+/**
+ * aie_get_module_errors() - get errors for a given module type
+ *			     in a partition.
+ * @apart: AIE partition pointer.
+ * @module: module type.
+ * @aie_err: pointer to array of error structure.
+ * @return: total number of errors found.
+ *
+ * This function parses local bitmaps and initializes @aie_err structures.
+ */
+static u32 aie_get_module_errors(struct aie_partition *apart,
+				 enum aie_module_type module,
+				 struct aie_error *aie_err)
+{
+	const struct aie_error_attr *err_attr;
+	struct aie_location loc;
+	u32 srow, erow, scol, ecol, num_err = 0;
+
+	if (module == AIE_CORE_MOD) {
+		err_attr = apart->adev->core_errors;
+		srow = apart->range.start.row + 1;
+		erow = srow + apart->range.size.row - 1;
+	} else if (module == AIE_MEM_MOD) {
+		err_attr = apart->adev->mem_errors;
+		srow = apart->range.start.row + 1;
+		erow = srow + apart->range.size.row - 1;
+	} else {
+		err_attr = apart->adev->shim_errors;
+		srow = 0;
+		erow = 0;
+	}
+
+	scol = apart->range.start.col;
+	ecol = apart->range.start.col + apart->range.size.col - 1;
+
+	for (loc.col = scol; loc.col <= ecol; loc.col++) {
+		for (loc.row = srow; loc.row <= erow; loc.row++) {
+			num_err +=
+				aie_get_errors_from_bitmap(apart, loc,
+							   module, err_attr,
+							   &aie_err[num_err]);
+		}
+	}
+	return num_err;
+}
+
+/**
+ * aie_part_clear_cached_events() - clear cached events in a partition.
+ * @apart: AIE partition pointer
+ *
+ * This function will clear the cached events in a partition.
+ */
+void aie_part_clear_cached_events(struct aie_partition *apart)
+{
+	aie_resource_clear_all(&apart->core_event_status);
+	aie_resource_clear_all(&apart->mem_event_status);
+	aie_resource_clear_all(&apart->pl_event_status);
+}
+
+/**
+ * aie_register_error_notification() - register a callback for error
+ *				       notification.
+ * @dev: AIE partition device.
+ * @cb: pointer to a function that accepts pointer to private data as an
+ *	argument. callbacks are called in the bottom half without locks.
+ * @priv: private data to be passed to the callback.
+ * @return: 0 for success, and negative value for failure.
+ */
+int aie_register_error_notification(struct device *dev,
+				    void (*cb)(void *priv), void *priv)
+{
+	struct aie_partition *apart;
+	int ret;
+
+	if (!cb || !dev)
+		return -EINVAL;
+
+	apart = container_of(dev, struct aie_partition, dev);
+
+	ret = mutex_lock_interruptible(&apart->mlock);
+	if (ret) {
+		dev_err(&apart->dev,
+			"Failed to acquire lock. Process was interrupted by fatal signals\n");
+		return ret;
+	}
+
+	if (apart->error_cb.cb) {
+		dev_err(&apart->dev,
+			"Error callback already registered. Unregister the existing callback to register a new one.\n");
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	apart->error_cb.cb = cb;
+	apart->error_cb.priv = priv;
+
+	/*
+	 * Errors during configuration are logged even for the partitions
+	 * which are not requested. Such errors must be reported back to the
+	 * application when a valid callback is registered.
+	 */
+	if (apart->error_to_report) {
+		mutex_unlock(&apart->mlock);
+		schedule_work(&apart->adev->backtrack);
+		return ret;
+	}
+
+exit:
+	mutex_unlock(&apart->mlock);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(aie_register_error_notification);
+
+/**
+ * aie_unregister_error_notification() - Unregister the callback for error
+ *					 notification.
+ * @dev: AIE partition device.
+ * @return: 0 for success, and negative value for failure.
+ */
+int aie_unregister_error_notification(struct device *dev)
+{
+	struct aie_partition *apart;
+	int ret;
+
+	if (!dev)
+		return -EINVAL;
+
+	apart = container_of(dev, struct aie_partition, dev);
+
+	ret = mutex_lock_interruptible(&apart->mlock);
+	if (ret) {
+		dev_err(&apart->dev,
+			"Failed to acquire lock. Process was interrupted by fatal signals\n");
+		return ret;
+	}
+
+	apart->error_cb.cb = NULL;
+	apart->error_cb.priv = NULL;
+
+	mutex_unlock(&apart->mlock);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(aie_unregister_error_notification);
+
+/**
+ * aie_get_errors() - get errors that has happened.
+ * @dev: AIE partition device.
+ * @return: struct pointer of type aie_errors.
+ *
+ * This API allocates and initializes data structures by parsing local
+ * bitmaps. Allocated data structure must be deallocated using
+ * aie_free_errors() function.
+ */
+struct aie_errors *aie_get_errors(struct device *dev)
+{
+	struct aie_partition *apart;
+	struct aie_errors *aie_errs;
+	struct aie_error *error;
+	u32 num_errs, count = 0;
+	int ret;
+
+	if (!dev)
+		return ERR_PTR(-EINVAL);
+
+	apart = container_of(dev, struct aie_partition, dev);
+
+	ret = mutex_lock_interruptible(&apart->mlock);
+	if (ret) {
+		dev_err(&apart->dev,
+			"Failed to acquire lock. Process was interrupted by fatal signals\n");
+		return ERR_PTR(ret);
+	}
+
+	num_errs = aie_get_error_count(apart);
+	if (!num_errs) {
+		mutex_unlock(&apart->mlock);
+		return NULL;
+	}
+
+	aie_errs = kzalloc(sizeof(*aie_errs), GFP_KERNEL);
+	if (!aie_errs) {
+		mutex_unlock(&apart->mlock);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	error = kcalloc(num_errs, sizeof(*error), GFP_KERNEL);
+	if (!error) {
+		kfree(aie_errs);
+		mutex_unlock(&apart->mlock);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	count += aie_get_module_errors(apart, AIE_MEM_MOD, &error[count]);
+	count += aie_get_module_errors(apart, AIE_CORE_MOD, &error[count]);
+	count += aie_get_module_errors(apart, AIE_PL_MOD, &error[count]);
+
+	aie_errs->dev = dev;
+	aie_errs->errors = error;
+	aie_errs->num_err = count;
+
+	mutex_unlock(&apart->mlock);
+	return aie_errs;
+}
+EXPORT_SYMBOL_GPL(aie_get_errors);
+
+/**
+ * aie_get_error_categories() - Get the error categories. Error information
+ *				returned by aie_get_errors() could be
+ *				abstracted by classifying errors into various
+ *				categories. All DMA channel error are
+ *				classified as AIE_ERROR_CATEGORY_DMA, program
+ *				and data memory ECC errors are classified as
+ *				AIE_ERROR_CATEGORY_ECC, and so on.
+ * @aie_errs: AIE errors structure.
+ * @return: Bitmap of category of error events.
+ */
+u32 aie_get_error_categories(struct aie_errors *aie_errs)
+{
+	u32 e, ret = 0;
+
+	if (!aie_errs || !aie_errs->errors)
+		return 0;
+
+	for (e = 0; e < aie_errs->num_err; e++) {
+		struct aie_error *error = &aie_errs->errors[e];
+
+		ret |= BIT(error->category);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(aie_get_error_categories);
+
+/**
+ * aie_get_error_string() - get error string corresponding an error.
+ * @aie_errs: pointer to an array of error structure.
+ * @aie_err: AIE error.
+ * @return: string corresponding to @aie_err.
+ */
+const char *aie_get_error_string(struct aie_errors *aie_errs,
+				 struct aie_error *aie_err)
+{
+	struct aie_partition *apart;
+	const struct aie_error_attr *err_attr;
+	u8 i, j;
+	int ret;
+
+	if (!aie_errs || !aie_errs->dev || !aie_err)
+		return ERR_PTR(-EINVAL);
+
+	apart = container_of(aie_errs->dev, struct aie_partition, dev);
+
+	ret = mutex_lock_interruptible(&apart->mlock);
+	if (ret) {
+		dev_err(&apart->dev,
+			"Failed to acquire lock. Process was interrupted by fatal signals\n");
+		return ERR_PTR(ret);
+	}
+
+	if (aie_err->module == AIE_CORE_MOD)
+		err_attr = apart->adev->core_errors;
+	else if (aie_err->module == AIE_MEM_MOD)
+		err_attr = apart->adev->mem_errors;
+	else
+		err_attr = apart->adev->shim_errors;
+
+	for (i = 0; i < err_attr->num_err_categories; i++) {
+		for (j = 0; j < err_attr->err_category[i].num_events; j++) {
+			u8 event = err_attr->err_category[i].prop[j].event;
+
+			if (event != aie_err->error_id)
+				continue;
+
+			mutex_unlock(&apart->mlock);
+			return err_attr->err_category[i].prop[j].event_str;
+		}
+	}
+
+	mutex_unlock(&apart->mlock);
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(aie_get_error_string);
+
+/**
+ * aie_flush_errors() - Flush all pending errors.
+ * @dev: AIE partition device.
+ * @return: 0 for success, and negative value for failure.
+ *
+ * This function backtracks a given partition, updates local event status
+ * bitmaps and, invokes the registered callback function for any error event.
+ */
+int aie_flush_errors(struct device *dev)
+{
+	struct aie_partition *apart;
+
+	if (!dev)
+		return -EINVAL;
+
+	apart = container_of(dev, struct aie_partition, dev);
+	aie_part_backtrack(apart);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(aie_flush_errors);
+
+/**
+ * aie_free_errors() - Free allocated AIE error structure.
+ * @aie_errs: AIE error structure.
+ */
+void aie_free_errors(struct aie_errors *aie_errs)
+{
+	if (!aie_errs || !aie_errs->errors)
+		return;
+
+	kfree(aie_errs->errors);
+	kfree(aie_errs);
+}
+EXPORT_SYMBOL_GPL(aie_free_errors);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/xilinx-ai-engine/ai-engine-mem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/xilinx-ai-engine/ai-engine-mem.c
@@ -0,0 +1,297 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx AI Engine device memory implementation
+ *
+ * Copyright (C) 2020 Xilinx, Inc.
+ */
+
+#include <linux/dma-buf.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <uapi/linux/xlnx-ai-engine.h>
+
+#include "ai-engine-internal.h"
+
+#define aie_cal_reg_goffset(adev, loc, regoff) ({ \
+	struct aie_device *_adev = (adev); \
+	struct aie_location *_loc = &(loc); \
+	(_loc->col << _adev->col_shift) + \
+	(_loc->row << _adev->row_shift) + (regoff); \
+	})
+
+#define aie_cal_reg_pa(adev, loc, regoff) ({ \
+	struct aie_device *__adev = (adev); \
+	__adev->res->start + aie_cal_reg_goffset(__adev, loc, regoff); \
+	})
+
+static struct sg_table *
+aie_mem_map_dma_buf(struct dma_buf_attachment *attachment,
+		    enum dma_data_direction direction)
+{
+	/*
+	 * TODO: It is mandatory by DMA buf operation. It is used return
+	 * scatterlist table of an attachment. We don't have the implementation
+	 * for now. And thus it has empty implementation.
+	 */
+	(void)attachment;
+	(void)direction;
+	dev_warn(attachment->dev,
+		 "AI engine memory map dma buf is not implemented.\n");
+	return NULL;
+}
+
+static void aie_mem_unmap_dma_buf(struct dma_buf_attachment *attachment,
+				  struct sg_table *table,
+				  enum dma_data_direction direction)
+{
+	/*
+	 * TODO: It is mandatory by DMA buf operation. It is used deallocate
+	 * scatterlist table of an attachment. We don't have the implementation
+	 * for now. And thus it has empty implementation.
+	 */
+	(void)attachment;
+	(void)table;
+	(void)direction;
+	dev_warn(attachment->dev,
+		 "AI engine memory unmap dma buf is not implemented.\n");
+}
+
+static int aie_mem_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
+{
+	struct aie_part_mem *pmem = dmabuf->priv;
+	struct aie_mem *mem = &pmem->mem;
+	struct aie_partition *apart = pmem->apart;
+	struct aie_location loc;
+	unsigned long addr = vma->vm_start;
+	unsigned long offset = vma->vm_pgoff * PAGE_SIZE, moffset = 0;
+	unsigned long remainder = vma->vm_end - addr;
+	size_t msize = mem->size;
+
+	if (remainder + offset > pmem->size)
+		return -EINVAL;
+
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+	for (loc.col = mem->range.start.col;
+	     loc.col < mem->range.start.col + mem->range.size.col; loc.col++) {
+		for (loc.row = mem->range.start.row;
+		     loc.row < mem->range.start.row + mem->range.size.row;
+		     loc.row++) {
+			unsigned long toffset, len;
+			phys_addr_t mempa;
+			int ret;
+
+			remainder = vma->vm_end - addr;
+			if (!remainder)
+				return 0;
+
+			if (moffset + msize < offset) {
+				moffset += msize;
+				continue;
+			}
+			/*
+			 * calculate offset within the tile memory.
+			 * offset is the offset to vma->start.
+			 * moffset is the tile memory start offset to
+			 * vma->start.
+			 */
+			toffset = offset - moffset;
+			len = msize - toffset;
+			if (len > remainder)
+				len = remainder;
+			mempa = aie_cal_reg_pa(apart->adev, loc,
+					       toffset + mem->offset);
+
+			ret = remap_pfn_range(vma, addr, mempa >> PAGE_SHIFT,
+					      len, vma->vm_page_prot);
+			if (ret) {
+				dev_err(&apart->dev,
+					"failed to mmap (%u,%u)memory, remap failed, 0x%pa, 0x%lx.\n",
+					loc.col, loc.row, &mempa, len);
+				return ret;
+			}
+			addr += len;
+			offset += len;
+			moffset += msize;
+		}
+	}
+	return 0;
+}
+
+static void aie_mem_dmabuf_release(struct dma_buf *dmabuf)
+{
+	struct aie_part_mem *pmem = dmabuf->priv;
+
+	pmem->dbuf = NULL;
+}
+
+static const struct dma_buf_ops aie_mem_dma_buf_ops = {
+	.map_dma_buf = aie_mem_map_dma_buf,
+	.unmap_dma_buf = aie_mem_unmap_dma_buf,
+	.mmap = aie_mem_mmap,
+	.release = aie_mem_dmabuf_release,
+};
+
+/**
+ * aie_mem_create_dmabuf() - creates DMA buffer for AI engine partition
+ *			     memories
+ * @apart: AI engine partition
+ * @pmem: pointer to the partition memory information
+ * @mem: pointer to where it store the memory information and DMA buf file
+ *	 descriptor for user.
+ * @return: 0 for success, negative value for failure
+ *
+ * This function will create DMA buffer for the AI engine partition memory
+ * and will store the DMA buffer file descriptor and memory information in
+ * @mem.
+ */
+static int aie_mem_create_dmabuf(struct aie_partition *apart,
+				 struct aie_part_mem *pmem,
+				 struct aie_mem *mem)
+{
+	struct dma_buf *dmabuf;
+	int ret;
+
+	if (!PAGE_ALIGNED(pmem->mem.size)) {
+		dev_warn(&apart->dev,
+			 "no dmabuf for mem(0x%zx, 0x%zx), not aligned with page size.\n",
+			 pmem->mem.offset, pmem->mem.size);
+		return -EINVAL;
+	}
+
+	dmabuf = pmem->dbuf;
+	if (!dmabuf) {
+		DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+
+		exp_info.ops = &aie_mem_dma_buf_ops;
+		exp_info.size = pmem->size;
+		exp_info.flags = O_RDWR;
+		exp_info.priv = pmem;
+
+		dmabuf = dma_buf_export(&exp_info);
+		if (IS_ERR(dmabuf))
+			return PTR_ERR(dmabuf);
+
+		pmem->dbuf = dmabuf;
+	}
+
+	ret = dma_buf_fd(dmabuf, O_CLOEXEC);
+	if (ret < 0) {
+		dev_err(&apart->dev,
+			"dmabuf creation failed, failed to get fd.\n");
+		return ret;
+	}
+	memcpy(mem, &pmem->mem, sizeof(*mem));
+	mem->fd = ret;
+
+	return 0;
+}
+
+/**
+ * aie_mem_get_info() - get AI engine memories information
+ * @apart: AI engine partition
+ * @arg: argument from user to enquire AI engine partition memory information
+ * @return: 0 for success, and negative value for failure
+ *
+ * This function will get the memories information for the specified AI engine
+ * partition. It will create DMA buf file descriptors for the memories and
+ * return the DMA buf file descriptors to users.
+ * It will create a DMA buffer per type of memories.
+ * e.g. There will be a DMA buffer for all the tile program memories in the
+ * partition, and another DMA buffer for all the tile data memories in the
+ * partition.
+ * User can first pass num_mems as 0 in the @arg to enquire for how many types
+ * of memories in this AI engine partition. And then, user can allocate memory
+ * to keep the information for different types of memories, and then use the
+ * same enqury with non-zero num_mems and none NULL pointer to ask for the
+ * details of the information of all the types of memories in the AI engine
+ * partition.
+ */
+int aie_mem_get_info(struct aie_partition *apart, unsigned long arg)
+{
+	struct aie_mem_args margs;
+	struct aie_mem *mems;
+	unsigned int num_mems, i;
+	int ret;
+
+	if (copy_from_user(&margs, (void __user *)arg, sizeof(margs)))
+		return -EFAULT;
+
+	num_mems = apart->adev->ops->get_mem_info(&apart->range, NULL);
+	if (num_mems <= 0)
+		return -EINVAL;
+
+	if (!margs.num_mems) {
+		struct aie_mem_args __user *umargs_ptr = (void __user *)arg;
+
+		/* This enquiry is to get the number of types of memories. */
+		if (copy_to_user((void __user *)&umargs_ptr->num_mems,
+				 &num_mems, sizeof(num_mems)))
+			return -EFAULT;
+		return 0;
+	}
+
+	if (num_mems != margs.num_mems) {
+		dev_err(&apart->dev,
+			"failed to get mem info, invalid num of mems %d,%d.\n",
+			num_mems, margs.num_mems);
+		return -EINVAL;
+	}
+	if (!margs.mems) {
+		dev_err(&apart->dev,
+			"failed to get mem info, mems pointer is NULL.\n");
+		return -EINVAL;
+	}
+
+	mems = kcalloc(num_mems, sizeof(*mems), GFP_KERNEL);
+	if (!mems)
+		return -ENOMEM;
+
+	/*
+	 * Create DMA buffer for the memories.
+	 * Each type of memory in the partition has its own DMA buf.
+	 */
+	for (i = 0; i < num_mems; i++) {
+		ret = aie_mem_create_dmabuf(apart, &apart->pmems[i], &mems[i]);
+		if (ret)
+			break;
+	}
+	if (!ret) {
+		if (copy_to_user((void __user *)margs.mems, mems,
+				 num_mems * sizeof(mems[0])))
+			ret = -EFAULT;
+	}
+
+	if (ret) {
+		for (i = 0; i < num_mems; i++) {
+			if (mems[i].fd)
+				put_unused_fd(mems[i].fd);
+		}
+	}
+
+	kfree(mems);
+	return ret;
+}
+
+/**
+ * aie_part_has_mem_mmapped() - check if memories in the partition are mapped
+ * @apart: AI engine partition
+ * @return: return true if there are memories mmaped, false otherwise.
+ *
+ * This function checks if there are memories in the partition mmapped in the
+ * partition.
+ */
+bool aie_part_has_mem_mmapped(struct aie_partition *apart)
+{
+	unsigned int num_mems, i;
+
+	num_mems = apart->adev->ops->get_mem_info(&apart->range, NULL);
+	if (!num_mems)
+		return false;
+
+	for (i = 0; i < num_mems; i++) {
+		if (apart->pmems[i].dbuf)
+			return true;
+	}
+	return false;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/xilinx-ai-engine/ai-engine-part.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/xilinx-ai-engine/ai-engine-part.c
@@ -0,0 +1,828 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx AI Engine partition driver
+ *
+ * Copyright (C) 2020 Xilinx, Inc.
+ */
+
+#include <linux/cdev.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/mmu_context.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/uio.h>
+#include <uapi/linux/xlnx-ai-engine.h>
+
+#include "ai-engine-internal.h"
+
+/**
+ * aie_cal_loc() - calculate tile location from register offset to the AI
+ *		   engine device
+ * @adev: AI engine device
+ * @loc: memory pointer to restore returning location information
+ * @regoff: tile internal register offset
+ *
+ * This function returns the tile location.
+ */
+static void aie_cal_loc(struct aie_device *adev,
+			struct aie_location *loc, u64 regoff)
+{
+	loc->col = (u32)aie_tile_reg_field_get(aie_col_mask(adev),
+					       adev->col_shift, regoff);
+	loc->row = (u32)aie_tile_reg_field_get(aie_row_mask(adev),
+					       adev->row_shift, regoff);
+}
+
+/**
+ * aie_part_reg_validation() - validate AI engine partition register access
+ * @apart: AI engine partition
+ * @offset: AI engine register offset
+ * @len: len of data to write/read
+ * @is_write: is the access to write to register
+ * @return: 0 for success, or negative value for failure.
+ *
+ * This function validate if the register to access is within the AI engine
+ * partition. If it is write access, if the register is writable by user.
+ */
+static int aie_part_reg_validation(struct aie_partition *apart, size_t offset,
+				   size_t len, u8 is_write)
+{
+	struct aie_device *adev;
+	u32 regend32, ttype;
+	u64 regoff, regend64;
+	struct aie_location loc;
+	unsigned int i;
+
+	adev = apart->adev;
+	if (offset % sizeof(u32)) {
+		dev_err(&apart->dev,
+			"Invalid reg off(0x%zx), not 32bit aligned.\n",
+			offset);
+		return -EINVAL;
+	}
+
+	if (len % sizeof(u32)) {
+		dev_err(&apart->dev, "Invalid reg operation len %zu.\n", len);
+		return -EINVAL;
+	}
+
+	regoff = aie_cal_tile_reg(adev, offset);
+	regend64 = regoff + len;
+	if (regend64 >= BIT_ULL(adev->row_shift)) {
+		dev_err(&apart->dev,
+			"Invalid reg operation len %zu.\n", len);
+		return -EINVAL;
+	}
+
+	aie_cal_loc(adev, &loc, offset);
+	if (aie_validate_location(apart, loc)) {
+		dev_err(&apart->dev,
+			"Invalid (%d,%d) out of part(%d,%d),(%d,%d)\n",
+			loc.col, loc.row,
+			apart->range.start.col, apart->range.start.row,
+			apart->range.size.col, apart->range.size.row);
+		return -EINVAL;
+	}
+
+	/*
+	 * We check if a tile is gated before trying to access the tile.
+	 * As we mmap() the registers as read only to enable faster status
+	 * enquiry, and mmap() memories as write/read to faster memory access,
+	 * user can still access the clock gated tiles from userspace by
+	 * accessing the mmapped space.
+	 * Accessing the gated tiles can cause decode error. With PDI flow,
+	 * the PDI sets up the SHIM NOC AXI MM to only generate AI engine error
+	 * even instead of generating the NSU error. but for non PDI flow, as
+	 * the AXI MM register are protected register, until we have EEMI API
+	 * to update the AXI MM register, access the gated tiles can cause NSU
+	 * errors.
+	 * TODO: To solve this, we need to either request EEMI to configure
+	 * AXI MM or split the mmapped space into tiles based lists.
+	 */
+	if (!aie_part_check_clk_enable_loc(apart, &loc)) {
+		dev_err(&apart->dev,
+			"Tile(%u,%d) is gated.\n", loc.col, loc.row);
+		return -EINVAL;
+	}
+
+	if (!is_write)
+		return 0;
+
+	regend32 = lower_32_bits(regend64);
+	ttype = adev->ops->get_tile_type(&loc);
+	for (i = 0; i < adev->num_kernel_regs; i++) {
+		const struct aie_tile_regs *regs;
+		u32 rttype, writable;
+
+		regs = &adev->kernel_regs[i];
+		rttype = (regs->attribute & AIE_REGS_ATTR_TILE_TYPE_MASK) >>
+			 AIE_REGS_ATTR_TILE_TYPE_SHIFT;
+		writable = (regs->attribute & AIE_REGS_ATTR_PERM_MASK) >>
+			   AIE_REGS_ATTR_PERM_SHIFT;
+		if (!(ttype & rttype))
+			continue;
+		if ((regoff >= regs->soff && regoff <= regs->eoff) ||
+		    (regend32 >= regs->soff && regend32 <= regs->eoff)) {
+			if (!writable) {
+				dev_err(&apart->dev,
+					"reg 0x%zx,0x%zx not writable.\n",
+					offset, len);
+				return -EINVAL;
+			}
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * aie_part_write_register() - AI engine partition write register
+ * @apart: AI engine partition
+ * @offset: AI engine register offset
+ * @len: len of data to write
+ * @data: data to write
+ * @mask: mask, if it is non 0, it is mask write.
+ * @return: number of bytes write for success, or negative value for failure.
+ *
+ * This function writes data to the specified registers.
+ * If the mask is non 0, it is mask write.
+ */
+static int aie_part_write_register(struct aie_partition *apart, size_t offset,
+				   size_t len, void *data, u32 mask)
+{
+	int ret;
+	void __iomem *va;
+
+	if (mask && len > sizeof(u32)) {
+		/* For mask write, only allow 32bit. */
+		dev_err(&apart->dev,
+			"failed mask write, len is more that 32bit.\n");
+		return -EINVAL;
+	}
+
+	/* offset is expected to be relative to the start of the partition */
+	offset += aie_cal_regoff(apart->adev, apart->range.start, 0);
+	ret = aie_part_reg_validation(apart, offset, len, 1);
+	if (ret < 0) {
+		dev_err(&apart->dev, "failed to write to 0x%zx,0x%zx.\n",
+			offset, len);
+		return ret;
+	}
+
+	va = apart->adev->base + offset;
+	if (!mask) {
+		if (len == sizeof(u32))
+			iowrite32(*((u32 *)data),  va);
+		else
+			memcpy_toio(va, data, len);
+	} else {
+		u32 val = ioread32(va);
+
+		val &= ~mask;
+		val |= *((u32 *)data) & mask;
+		iowrite32(val, va);
+	}
+
+	return (int)len;
+}
+
+/**
+ * aie_part_read_register() - AI engine partition read register
+ * @apart: AI engine partition
+ * @offset: AI engine register offset
+ * @len: len of data to read
+ * @data: pointer to the memory to store the read data
+ * @return: number of bytes read for success, or negative value for failure.
+ *
+ * This function reads data from the specified registers.
+ */
+static int aie_part_read_register(struct aie_partition *apart, size_t offset,
+				  size_t len, void *data)
+{
+	void __iomem *va;
+	int ret;
+
+	/* offset is expected to be relative to the start of the partition */
+	offset += aie_cal_regoff(apart->adev, apart->range.start, 0);
+	ret = aie_part_reg_validation(apart, offset, len, 0);
+	if (ret) {
+		dev_err(&apart->dev, "Invalid read request 0x%zx,0x%zx.\n",
+			offset, len);
+		return -EINVAL;
+	}
+
+	va = apart->adev->base + offset;
+	if (len == 4)
+		*((u32 *)data) = ioread32(va);
+	else
+		memcpy_fromio(data, va, len);
+
+	return (int)len;
+}
+
+/**
+ * aie_part_access_regs() - AI engine partition registers access
+ * @apart: AI engine partition
+ * @num_reqs: number of access requests
+ * @reqs: array of registers access
+ * @return: 0 for success, and negative value for failure.
+ *
+ * This function executes AI engine partition register access requests.
+ */
+static int aie_part_access_regs(struct aie_partition *apart, u32 num_reqs,
+				struct aie_reg_args *reqs)
+{
+	u32 i;
+
+	for (i = 0; i < num_reqs; i++) {
+		struct aie_reg_args *args = &reqs[i];
+		int ret;
+
+		if (args->op != AIE_REG_WRITE) {
+			dev_err(&apart->dev,
+				"Invalid register command type: %u.\n",
+				args->op);
+			return -EINVAL;
+		}
+		ret = aie_part_write_register(apart,
+					      (size_t)args->offset,
+					      sizeof(args->val),
+					      &args->val, args->mask);
+		if (ret < 0) {
+			dev_err(&apart->dev, "reg op %u failed: 0x%llx.\n",
+				args->op, args->offset);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * aie_part_create_event_bitmap() - create event bitmap for all modules in a
+ *				    given partition.
+ * @apart: AI engine partition
+ * @return: 0 for success, and negative value for failure.
+ */
+static int aie_part_create_event_bitmap(struct aie_partition *apart)
+{
+	struct aie_range range = apart->range;
+	u32 bitmap_sz;
+	u32 num_aie_module = range.size.col * (range.size.row - 1);
+	int ret;
+
+	bitmap_sz = num_aie_module * apart->adev->core_events->num_events;
+	ret = aie_resource_initialize(&apart->core_event_status, bitmap_sz);
+	if (ret) {
+		dev_err(&apart->dev,
+			"failed to initialize event status resource.\n");
+		return -ENOMEM;
+	}
+
+	bitmap_sz = num_aie_module * apart->adev->mem_events->num_events;
+	ret = aie_resource_initialize(&apart->mem_event_status, bitmap_sz);
+	if (ret) {
+		dev_err(&apart->dev,
+			"failed to initialize event status resource.\n");
+		return -ENOMEM;
+	}
+
+	bitmap_sz = range.size.col * apart->adev->pl_events->num_events;
+	ret = aie_resource_initialize(&apart->pl_event_status, bitmap_sz);
+	if (ret) {
+		dev_err(&apart->dev,
+			"failed to initialize event status resource.\n");
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+/**
+ * aie_part_create_l2_bitmap() - create bitmaps to record mask and status
+ *				 values for level 2 interrupt controllers.
+ * @apart: AI engine partition
+ * @return: 0 for success, and negative value for failure.
+ */
+static int aie_part_create_l2_bitmap(struct aie_partition *apart)
+{
+	struct aie_location loc;
+	u8 num_l2_ctrls = 0;
+	int ret;
+
+	loc.row = 0;
+	for (loc.col = apart->range.start.col;
+	     loc.col < apart->range.start.col + apart->range.size.col;
+	     loc.col++) {
+		u32 ttype = apart->adev->ops->get_tile_type(&loc);
+
+		if (ttype == AIE_TILE_TYPE_SHIMNOC)
+			num_l2_ctrls++;
+	}
+
+	ret = aie_resource_initialize(&apart->l2_mask, num_l2_ctrls *
+				      AIE_INTR_L2_CTRL_MASK_WIDTH);
+	if (ret) {
+		dev_err(&apart->dev,
+			"failed to initialize l2 mask resource.\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * aie_part_release_event_bitmap() - Deallocates event bitmap for all modules
+ *				     in a given partition.
+ * @apart: AI engine partition
+ * @return: 0 for success, and negative value for failure.
+ */
+static void aie_part_release_event_bitmap(struct aie_partition *apart)
+{
+	aie_resource_uninitialize(&apart->core_event_status);
+	aie_resource_uninitialize(&apart->mem_event_status);
+	aie_resource_uninitialize(&apart->pl_event_status);
+}
+
+static int aie_part_release(struct inode *inode, struct file *filp)
+{
+	struct aie_partition *apart = filp->private_data;
+	int ret;
+
+	ret = mutex_lock_interruptible(&apart->mlock);
+	if (ret)
+		return ret;
+
+	aie_part_release_dmabufs(apart);
+	aie_part_clean(apart);
+
+	apart->error_cb.cb = NULL;
+	apart->error_cb.priv = NULL;
+	apart->status = 0;
+	apart->error_to_report = 0;
+
+	aie_part_clear_cached_events(apart);
+	aie_resource_clear_all(&apart->l2_mask);
+
+	mutex_unlock(&apart->mlock);
+
+	return 0;
+}
+
+static ssize_t aie_part_write_iter(struct kiocb *iocb, struct iov_iter *from)
+{
+	struct file *filp = iocb->ki_filp;
+	struct aie_partition *apart = filp->private_data;
+	size_t len = iov_iter_count(from);
+	loff_t offset = iocb->ki_pos;
+	void *buf;
+	int ret;
+
+	buf = kzalloc(len, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	if (!copy_from_iter_full(buf, len, from)) {
+		kfree(buf);
+		return -EFAULT;
+	}
+
+	ret = mutex_lock_interruptible(&apart->mlock);
+	if (ret) {
+		kfree(buf);
+		return ret;
+	}
+
+	ret = aie_part_write_register(apart, (size_t)offset, len, buf, 0);
+	mutex_unlock(&apart->mlock);
+	kfree(buf);
+
+	return ret;
+}
+
+static ssize_t aie_part_read_iter(struct kiocb *iocb, struct iov_iter *to)
+{
+	struct file *filp = iocb->ki_filp;
+	struct aie_partition *apart = filp->private_data;
+	size_t len = iov_iter_count(to);
+	loff_t offset = iocb->ki_pos;
+	void *buf;
+	int ret;
+
+	buf = kzalloc(len, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	ret = mutex_lock_interruptible(&apart->mlock);
+	if (ret) {
+		kfree(buf);
+		return ret;
+	}
+
+	ret = aie_part_read_register(apart, (size_t)offset, len, buf);
+	mutex_unlock(&apart->mlock);
+	if (ret > 0) {
+		if (copy_to_iter(buf, ret, to) != len) {
+			dev_err(&apart->dev, "Failed to copy to read iter.\n");
+			ret = -EFAULT;
+		}
+	}
+	kfree(buf);
+
+	return ret;
+}
+
+static const struct vm_operations_struct aie_part_physical_vm_ops = {
+#ifdef CONFIG_HAVE_IOREMAP_PROT
+	.access = generic_access_phys,
+#endif
+};
+
+static int aie_part_mmap(struct file *fp, struct vm_area_struct *vma)
+{
+	struct aie_partition *apart = fp->private_data;
+	struct aie_device *adev = apart->adev;
+	unsigned long offset = vma->vm_pgoff * PAGE_SIZE;
+	phys_addr_t addr;
+	size_t size;
+
+	if (vma->vm_end < vma->vm_start)
+		return -EINVAL;
+	/* Only allow userspace directly read registers */
+	if (vma->vm_flags & VM_WRITE) {
+		dev_err(&apart->dev, "%s: do not support writable mmap.\n",
+			__func__);
+		return -EINVAL;
+	}
+	vma->vm_private_data = apart;
+	vma->vm_ops = &aie_part_physical_vm_ops;
+	size = apart->range.size.col << adev->col_shift;
+	if ((vma->vm_end - vma->vm_start) > (size - offset)) {
+		dev_err(&apart->dev,
+			"%s: size exceed.\n", __func__);
+		return -EINVAL;
+	}
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+	/* Calculate the partition address */
+	addr = adev->res->start;
+	addr += apart->range.start.col << adev->col_shift;
+	addr += apart->range.start.row << adev->row_shift;
+	addr += offset;
+	return remap_pfn_range(vma,
+			       vma->vm_start,
+			       addr >> PAGE_SHIFT,
+			       vma->vm_end - vma->vm_start,
+			       vma->vm_page_prot);
+}
+
+static long aie_part_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
+{
+	struct aie_partition *apart = fp->private_data;
+	void __user *argp = (void __user *)arg;
+	long ret;
+
+	switch (cmd) {
+	case AIE_REG_IOCTL:
+	{
+		struct aie_reg_args raccess;
+
+		if (copy_from_user(&raccess, argp, sizeof(raccess)))
+			return -EFAULT;
+
+		ret = mutex_lock_interruptible(&apart->mlock);
+		if (ret)
+			return ret;
+
+		ret = aie_part_access_regs(apart, 1, &raccess);
+		mutex_unlock(&apart->mlock);
+		break;
+	}
+	case AIE_GET_MEM_IOCTL:
+		return aie_mem_get_info(apart, arg);
+	case AIE_ATTACH_DMABUF_IOCTL:
+		return aie_part_attach_dmabuf_req(apart, argp);
+	case AIE_DETACH_DMABUF_IOCTL:
+		return aie_part_detach_dmabuf_req(apart, argp);
+	case AIE_SET_SHIMDMA_BD_IOCTL:
+		return aie_part_set_bd(apart, argp);
+	case AIE_SET_SHIMDMA_DMABUF_BD_IOCTL:
+		return aie_part_set_dmabuf_bd(apart, argp);
+	case AIE_REQUEST_TILES_IOCTL:
+		return aie_part_request_tiles_from_user(apart, argp);
+	case AIE_RELEASE_TILES_IOCTL:
+		return aie_part_release_tiles_from_user(apart, argp);
+	default:
+		dev_err(&apart->dev, "Invalid ioctl command %u.\n", cmd);
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+const struct file_operations aie_part_fops = {
+	.owner		= THIS_MODULE,
+	.release	= aie_part_release,
+	.read_iter	= aie_part_read_iter,
+	.write_iter	= aie_part_write_iter,
+	.mmap		= aie_part_mmap,
+	.unlocked_ioctl	= aie_part_ioctl,
+};
+
+/**
+ * aie_part_release_device() - release an AI engine partition instance
+ * @dev: AI engine partition device
+ *
+ * It will be called by device driver core when no one holds a valid
+ * pointer to @dev anymore.
+ */
+static void aie_part_release_device(struct device *dev)
+{
+	struct aie_partition *apart = dev_to_aiepart(dev);
+	struct aie_device *adev = apart->adev;
+	int ret;
+
+	ret = mutex_lock_interruptible(&adev->mlock);
+	if (ret) {
+		dev_warn(&apart->dev,
+			 "getting adev->mlock is interrupted by signal\n");
+	}
+
+	aie_resource_put_region(&adev->cols_res, apart->range.start.col,
+				apart->range.size.col);
+	aie_part_release_event_bitmap(apart);
+	aie_resource_uninitialize(&apart->l2_mask);
+	list_del(&apart->node);
+	mutex_unlock(&adev->mlock);
+	aie_fpga_free_bridge(apart);
+	aie_resource_uninitialize(&apart->cores_clk_state);
+	put_device(apart->dev.parent);
+}
+
+/**
+ * aie_part_create_mems_info() - creates array to store the AI engine partition
+ *				 different memories types information
+ * @apart: AI engine partition
+ * @return: 0 for success, negative value for failure
+ *
+ * This function will create array to store the information of different
+ * memories types in the partition. This array is stored in @apart->pmems.
+ */
+static int aie_part_create_mems_info(struct aie_partition *apart)
+{
+	unsigned int i, num_mems;
+
+	num_mems = apart->adev->ops->get_mem_info(&apart->range, NULL);
+	if (!num_mems)
+		return 0;
+
+	apart->pmems = devm_kcalloc(&apart->dev, num_mems,
+				    sizeof(struct aie_part_mem),
+				    GFP_KERNEL);
+	if (!apart->pmems)
+		return -ENOMEM;
+
+	apart->adev->ops->get_mem_info(&apart->range, apart->pmems);
+	for (i = 0; i < num_mems; i++) {
+		struct aie_mem *mem = &apart->pmems[i].mem;
+
+		apart->pmems[i].apart = apart;
+		apart->pmems[i].size = mem->size *
+				       mem->range.size.col *
+				       mem->range.size.row;
+	}
+	return 0;
+}
+
+/**
+ * aie_create_partition() - create AI engine partition instance
+ * @adev: AI engine device
+ * @range: AI engine partition range to check. A range describes a group
+ *	   of AI engine tiles.
+ * @return: created AI engine partition pointer for success, and PTR_ERR
+ *	    for failure.
+ *
+ * This function creates an AI engine partition instance.
+ * It creates AI engine partition, the AI engine partition device and
+ * the AI engine partition character device.
+ */
+static struct aie_partition *aie_create_partition(struct aie_device *adev,
+						  struct aie_range *range)
+{
+	struct aie_partition *apart;
+	struct device *dev;
+	char devname[32];
+	int ret;
+
+	ret = mutex_lock_interruptible(&adev->mlock);
+	if (ret)
+		return ERR_PTR(ret);
+
+	ret = aie_resource_check_region(&adev->cols_res, range->start.col,
+					range->size.col);
+	if (ret != range->start.col) {
+		dev_err(&adev->dev, "invalid partition (%u,%u)(%u,%u).\n",
+			range->start.col, range->start.row,
+			range->size.col, range->size.row);
+		mutex_unlock(&adev->mlock);
+		return ERR_PTR(-EINVAL);
+	}
+	ret = aie_resource_get_region(&adev->cols_res, range->start.col,
+				      range->size.col);
+	if (ret != range->start.col) {
+		dev_err(&adev->dev, "failed to get partition (%u,%u)(%u,%u).\n",
+			range->start.col, range->start.row,
+			range->size.col, range->size.row);
+		mutex_unlock(&adev->mlock);
+		return ERR_PTR(-EFAULT);
+	}
+	mutex_unlock(&adev->mlock);
+
+	apart = devm_kzalloc(&adev->dev, sizeof(*apart), GFP_KERNEL);
+	if (!apart)
+		return ERR_PTR(-ENOMEM);
+
+	apart->adev = adev;
+	INIT_LIST_HEAD(&apart->dbufs);
+	memcpy(&apart->range, range, sizeof(*range));
+	mutex_init(&apart->mlock);
+
+	/* Create AI engine partition device */
+	dev = &apart->dev;
+	device_initialize(dev);
+	dev->parent = &adev->dev;
+	dev->class = aie_class;
+	dev_set_drvdata(dev, apart);
+	snprintf(devname, sizeof(devname) - 1, "aiepart_%d_%d",
+		 apart->range.start.col, apart->range.size.col);
+	dev_set_name(dev, devname);
+	/* We can now rely on the release function for cleanup */
+	dev->release = aie_part_release_device;
+	ret = device_add(dev);
+	if (ret) {
+		dev_err(dev, "device_add failed: %d\n", ret);
+		put_device(dev);
+		return ERR_PTR(ret);
+	}
+
+	/* Set up the DMA mask */
+	dev->coherent_dma_mask = DMA_BIT_MASK(48);
+	dev->dma_mask = &dev->coherent_dma_mask;
+
+	/*
+	 * Create array to keep the information of the different types of tile
+	 * memories information of the AI engine partition.
+	 */
+	ret = aie_part_create_mems_info(apart);
+	if (ret) {
+		put_device(dev);
+		return ERR_PTR(ret);
+	}
+
+	ret = adev->ops->init_part_clk_state(apart);
+	if (ret) {
+		put_device(dev);
+		return ERR_PTR(ret);
+	}
+
+	/*
+	 * Create bitmap to record event status for each module in a
+	 * partition
+	 */
+	ret = aie_part_create_event_bitmap(apart);
+	if (ret < 0) {
+		dev_err(&apart->dev, "Failed to allocate event bitmap.\n");
+		put_device(dev);
+		return ERR_PTR(ret);
+	}
+
+	ret = aie_part_create_l2_bitmap(apart);
+	if (ret < 0) {
+		dev_err(&apart->dev, "Failed to allocate l2 bitmap.\n");
+		put_device(dev);
+		return ERR_PTR(ret);
+	}
+
+	ret = mutex_lock_interruptible(&adev->mlock);
+	if (ret) {
+		put_device(dev);
+		return ERR_PTR(ret);
+	}
+	list_add_tail(&apart->node, &adev->partitions);
+	mutex_unlock(&adev->mlock);
+	get_device(&adev->dev);
+	dev_dbg(dev, "created AIE partition device.\n");
+
+	return apart;
+}
+
+struct aie_partition *
+of_aie_part_probe(struct aie_device *adev, struct device_node *nc)
+{
+	struct aie_partition *apart;
+	struct aie_range range;
+	u32 partition_id, regs[4];
+	int ret;
+
+	/* Select device driver */
+	ret = of_property_read_u32_array(nc, "reg", regs, ARRAY_SIZE(regs));
+	if (ret < 0) {
+		dev_err(&adev->dev,
+			"probe %pOF failed, no tiles range information.\n",
+			nc);
+		return ERR_PTR(ret);
+	}
+	range.start.col = regs[0];
+	range.start.row = regs[1];
+	range.size.col = regs[2];
+	range.size.row = regs[3];
+
+	ret = of_property_read_u32_index(nc, "xlnx,partition-id", 0,
+					 &partition_id);
+	if (ret < 0) {
+		dev_err(&adev->dev,
+			"probe %pOF failed, no partition id.\n", nc);
+		return ERR_PTR(ret);
+	}
+
+	ret = mutex_lock_interruptible(&adev->mlock);
+	if (ret)
+		return ERR_PTR(ret);
+
+	apart = aie_get_partition_from_id(adev, partition_id);
+	mutex_unlock(&adev->mlock);
+	if (apart) {
+		dev_err(&adev->dev,
+			"probe failed: partition %u exists.\n",
+			partition_id);
+		return ERR_PTR(ret);
+	}
+
+	apart = aie_create_partition(adev, &range);
+	if (IS_ERR(apart)) {
+		dev_err(&adev->dev,
+			"%s: failed to create part(%u,%u),(%u,%u).\n",
+			__func__, range.start.col, range.start.row,
+			range.size.col, range.size.row);
+		return apart;
+	}
+
+	of_node_get(nc);
+	apart->dev.of_node = nc;
+	apart->dev.driver = adev->dev.parent->driver;
+	apart->partition_id = partition_id;
+	apart->error_cb.cb = NULL;
+	apart->error_cb.priv = NULL;
+
+	ret = of_dma_configure(&apart->dev, nc, true);
+	if (ret)
+		dev_warn(&apart->dev, "Failed to configure DMA.\n");
+
+	/* Create FPGA bridge for AI engine partition */
+	ret = aie_fpga_create_bridge(apart);
+	if (ret < 0)
+		dev_warn(&apart->dev, "failed to create fpga region.\n");
+
+	dev_info(&adev->dev,
+		 "AI engine part(%u,%u),(%u,%u), id %u is probed successfully.\n",
+		 range.start.col, range.start.row,
+		 range.size.col, range.size.row, apart->partition_id);
+
+	return apart;
+}
+
+/**
+ * aie_destroy_part() - destroy AI engine partition
+ * @apart: AI engine partition
+ *
+ * This function will remove AI engine partition.
+ */
+void aie_part_remove(struct aie_partition *apart)
+{
+	device_del(&apart->dev);
+	put_device(&apart->dev);
+}
+
+/**
+ * aie_part_has_regs_mmapped() - check if registers in the partition are mapped.
+ * @apart: AI engine partition
+ * @return: return true if there are registers mmaped, false otherwise.
+ *
+ * This function checks if there are registerss in the partition mmapped in the
+ * partition.
+ */
+bool aie_part_has_regs_mmapped(struct aie_partition *apart)
+{
+	struct address_space *mapping;
+
+	mapping = apart->filep->f_inode->i_mapping;
+	return mapping_mapped(mapping);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/xilinx-ai-engine/ai-engine-res.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/xilinx-ai-engine/ai-engine-res.c
@@ -0,0 +1,219 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx AI Engine device driver
+ *
+ * Copyright (C) 2020 Xilinx, Inc.
+ */
+
+#include <linux/bitmap.h>
+
+#include "ai-engine-internal.h"
+
+/**
+ * aie_resource_initialize() - initialize AI engine resource
+ * @res: pointer to AI engine resource
+ * @count: total number of element of this resource
+ * @return: 0 for success, negative value for failure.
+ *
+ * This function will initialize the data structure for the
+ * resource.
+ */
+int aie_resource_initialize(struct aie_resource *res, int count)
+{
+	if (!res || !count)
+		return -EINVAL;
+	res->bitmap = bitmap_zalloc(count, GFP_KERNEL);
+	if (!res->bitmap)
+		return -ENOMEM;
+	res->total = count;
+
+	return 0;
+}
+
+/**
+ * aie_resource_uninitialize() - uninitialize AI engine resource
+ * @res: pointer to AI engine resource
+ *
+ * This function will release the AI engine resource data members.
+ */
+void aie_resource_uninitialize(struct aie_resource *res)
+{
+	res->total = 0;
+	if (res->bitmap)
+		bitmap_free(res->bitmap);
+}
+
+/**
+ * aie_resource_check() - check availability of requested resource
+ * @res: pointer to AI engine resource to check
+ * @start: start index of the required resource, it will only be used if
+ *	   @continuous is 1. It will check the available resource starting from
+ *	   @start
+ * @count: number of requested element
+ * @return: start resource id if the requested number of resources are available
+ *	    It will return negative value of errors.
+ *
+ * This function will check the availability. It will return start resource id
+ * if the requested number of resources are available.
+ */
+int aie_resource_check_region(struct aie_resource *res,
+			      u32 start, u32 count)
+{
+	unsigned long id;
+
+	if (!res || !res->bitmap || !count)
+		return -EINVAL;
+	id = bitmap_find_next_zero_area(res->bitmap, res->total, start,
+					count, 0);
+	if (id >= res->total)
+		return -ERANGE;
+
+	return (int)id;
+}
+
+/**
+ * aie_resource_get_region() - get requested AI engine resource
+ * @res: pointer to AI engine resource to check
+ * @count: number of requested element
+ * @start: start index of the required resource
+ * @return: start resource id for success, and negative value for failure.
+ *
+ * This function check if the requested AI engine resource is available.
+ * If it is available, mark it used and return the start resource id.
+ */
+int aie_resource_get_region(struct aie_resource *res, u32 start, u32 count)
+{
+	unsigned long off;
+
+	if (!res || !res->bitmap || !count)
+		return -EINVAL;
+	off = bitmap_find_next_zero_area(res->bitmap, res->total, start,
+					 count, 0);
+	if (off >= res->total) {
+		pr_err("Failed to get available AI engine resource.\n");
+		return -ERANGE;
+	}
+	bitmap_set(res->bitmap, off, count);
+
+	return (int)off;
+}
+
+/**
+ * aie_resource_put_region() - release requested AI engine resource
+ * @res: pointer to AI engine resource to check
+ * @start: start index of the resource to release
+ * @count: number of elements to release
+ *
+ * This function release the requested AI engine resource.
+ */
+void aie_resource_put_region(struct aie_resource *res, int start, u32 count)
+{
+	if (!res || !count)
+		return;
+	bitmap_clear(res->bitmap, start, count);
+}
+
+/**
+ * aie_resource_set() - set the AI engine resource bits
+ * @res: pointer to AI engine resource
+ * @start: start bit to set
+ * @count: number of bits to set
+ * @return: 0 for success and negative value for failure
+ *
+ * This function sets the specified number bits in the resource.
+ */
+int aie_resource_set(struct aie_resource *res, u32 start, u32 count)
+{
+	if (!res || !res->bitmap || !count || start + count > res->total)
+		return -EINVAL;
+
+	bitmap_set(res->bitmap, start, count);
+	return 0;
+}
+
+/**
+ * aie_resource_cpy_from_arr32() - copies nbits from u32[] to bitmap.
+ * @res: pointer to AI engine resource
+ * @start: start bit in bitmap
+ * @src: source buffer
+ * @nbits: number of bits to copy from u32[]
+ * @return: 0 for success and negative value for failure
+ */
+int aie_resource_cpy_from_arr32(struct aie_resource *res, u32 start,
+				const u32 *src, u32 nbits)
+{
+	if (!res || !res->bitmap || !nbits || start + nbits  > res->total ||
+	    !src)
+		return -EINVAL;
+
+	bitmap_from_arr32(res->bitmap + BIT_WORD(start), src, nbits);
+	return 0;
+}
+
+/**
+ * aie_resource_cpy_to_arr32() - copies nbits to u32[] from bitmap.
+ * @res: pointer to AI engine resource
+ * @start: start bit in bitmap
+ * @dst: destination buffer
+ * @nbits: number of bits to copy to u32[]
+ * @return: 0 for success and negative value for failure
+ */
+int aie_resource_cpy_to_arr32(struct aie_resource *res, u32 start, u32 *dst,
+			      u32 nbits)
+{
+	if (!res || !res->bitmap || !nbits || start + nbits  > res->total ||
+	    !dst)
+		return -EINVAL;
+
+	bitmap_to_arr32(dst, res->bitmap + BIT_WORD(start), nbits);
+	return 0;
+}
+
+/**
+ * aie_resource_clear() - clear the AI engine resource bits
+ * @res: pointer to AI engine resource
+ * @start: start bit to set
+ * @count: number of bits to clear
+ * @return: 0 for success and negative value for failure
+ *
+ * This function clears the specified number bits in the resource.
+ */
+int aie_resource_clear(struct aie_resource *res, u32 start, u32 count)
+{
+	if (!res || !res->bitmap || !count || start + count > res->total)
+		return -EINVAL;
+
+	bitmap_clear(res->bitmap, start, count);
+	return 0;
+}
+
+/**
+ * aie_resource_clear_all() - clear all the AI engine resource bits
+ * @res: pointer to AI engine resource
+ * @return: 0 for success and negative value for failure
+ *
+ * This function clears all the bits in the resource.
+ */
+int aie_resource_clear_all(struct aie_resource *res)
+{
+	if (!res || !res->bitmap)
+		return -EINVAL;
+
+	bitmap_clear(res->bitmap, 0, res->total);
+	return 0;
+}
+
+/**
+ * aie_resource_testbit() - test if a bit is set in a AI engine resource
+ * @res: pointer to AI engine resource
+ * @bit: bit to check
+ * @return: true for set, false for not set
+ */
+bool aie_resource_testbit(struct aie_resource *res, u32 bit)
+{
+	if (!res || !res->bitmap || bit >= res->total)
+		return false;
+
+	/* Locate the unsigned long the required bit belongs to */
+	return test_bit(bit, res->bitmap);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/xilinx-ai-engine/ai-engine-reset.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/xilinx-ai-engine/ai-engine-reset.c
@@ -0,0 +1,248 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx AI Engine device driver resets implementation
+ *
+ * Copyright (C) 2020 Xilinx, Inc.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/io.h>
+
+#include "ai-engine-internal.h"
+
+/**
+ * aie_part_set_col_reset() - set AI engine column reset
+ * @apart: AI engine partition
+ * @col: column to reset
+ * @reset: true to assert reset, false to release reset
+ */
+static void aie_part_set_col_reset(struct aie_partition *apart, u32 col,
+				   bool reset)
+{
+	struct aie_device *adev = apart->adev;
+	const struct aie_single_reg_field *col_rst = adev->col_rst;
+	struct aie_location loc;
+	u32 regoff, val;
+
+	loc.row = 0;
+	loc.col = col;
+
+	val = aie_get_field_val(col_rst, (reset ? 1 : 0));
+	regoff = aie_cal_regoff(adev, loc, col_rst->regoff);
+	iowrite32(val, adev->base + regoff);
+}
+
+/**
+ * aie_part_set_col_clkbuf() - set AI engine column clock buffer
+ * @apart: AI engine partition
+ * @col: column to reset
+ * @enable: true to enable, false to disable
+ */
+static void aie_part_set_col_clkbuf(struct aie_partition *apart, u32 col,
+				    bool enable)
+{
+	struct aie_device *adev = apart->adev;
+	const struct aie_single_reg_field *col_clkbuf = adev->col_clkbuf;
+	struct aie_location loc;
+	u32 regoff, val;
+
+	loc.row = 0;
+	loc.col = col;
+
+	val = aie_get_field_val(col_clkbuf, (enable ? 1 : 0));
+	regoff = aie_cal_regoff(adev, loc, col_clkbuf->regoff);
+	iowrite32(val, adev->base + regoff);
+}
+
+/**
+ * aie_part_set_cols_reset() - set column reset of every column in a partition
+ * @apart: AI engine partition
+ * @reset: bool to assert reset, false to release reset
+ */
+static void aie_part_set_cols_reset(struct aie_partition *apart, bool reset)
+{
+	struct aie_range *range = &apart->range;
+	u32 c;
+
+	for (c = range->start.col; c < range->start.col + range->size.col;
+	     c++)
+		aie_part_set_col_reset(apart, c, reset);
+}
+
+/**
+ * aie_part_set_cols_clkbuf() - set column clock buffer of every column in a
+ *				partition
+ * @apart: AI engine partition
+ * @enable: true to enable, false to disable
+ */
+static void aie_part_set_cols_clkbuf(struct aie_partition *apart, bool enable)
+{
+	struct aie_range *range = &apart->range;
+	u32 c;
+
+	for (c = range->start.col; c < range->start.col + range->size.col;
+	     c++)
+		aie_part_set_col_clkbuf(apart, c, enable);
+}
+
+/**
+ * aie_part_clear_mems() - clear memories of every tile in a partition
+ * @apart: AI engine partition
+ */
+static void aie_part_clear_mems(struct aie_partition *apart)
+{
+	struct aie_device *adev = apart->adev;
+	struct aie_part_mem *pmems = apart->pmems;
+	u32 i, num_mems;
+
+	/* Get the number of different types of memories */
+	num_mems = adev->ops->get_mem_info(&apart->range, NULL);
+	if (!num_mems)
+		return;
+
+	/* Clear each type of memories in the partition */
+	for (i = 0; i < num_mems; i++) {
+		struct aie_mem *mem = &pmems[i].mem;
+		struct aie_range *range = &mem->range;
+		u32 c, r;
+
+		for (c = range->start.col;
+		     c < range->start.col + range->size.col; c++) {
+			for (r = range->start.row;
+			     r < range->start.row + range->size.row; r++) {
+				struct aie_location loc;
+				u32 memoff;
+
+				loc.col = c;
+				loc.row = r;
+				memoff = aie_cal_regoff(adev, loc, mem->offset);
+				memset_io(adev->base + memoff, 0, mem->size);
+			}
+		}
+	}
+}
+
+/**
+ * aie_part_clean() - reset and clear AI engine partition
+ * @apart: AI engine partition
+ * @return: 0 for success and negative value for failure
+ *
+ * This function will:
+ *  * gate all the columns
+ *  * reset AI engine partition columns
+ *  * reset AI engine shims
+ *  * clear the memories
+ *  * gate all the tiles in a partition.
+ *
+ * This function will not validate the partition, the caller will need to
+ * provide a valid AI engine partition.
+ */
+int aie_part_clean(struct aie_partition *apart)
+{
+	struct aie_device *adev = apart->adev;
+	int ret;
+
+	if (apart->cntrflag & XAIE_PART_NOT_RST_ON_RELEASE)
+		return 0;
+
+	aie_part_set_cols_clkbuf(apart, false);
+	aie_part_set_cols_reset(apart, true);
+
+	ret = apart->adev->ops->reset_shim(adev, &apart->range);
+	if (ret < 0)
+		return ret;
+
+	aie_part_clear_mems(apart);
+	aie_part_set_cols_clkbuf(apart, false);
+
+	return 0;
+}
+
+/**
+ * aie_part_reset() - reset AI engine partition
+ * @apart: AI engine partition
+ * @return: 0 for success and negative value for failure
+ *
+ * This function will:
+ * - gate all the columns
+ * - reset AI engine partition columns
+ * - reset AI engine shims
+ * - gate all the tiles in a partition.
+ *
+ * This function will not validate the partition, the caller will need to
+ * provide a valid AI engine partition.
+ */
+int aie_part_reset(struct aie_partition *apart)
+{
+	struct aie_device *adev = apart->adev;
+	int ret;
+
+	ret = mutex_lock_interruptible(&apart->mlock);
+	if (ret)
+		return ret;
+
+	/*
+	 * Check if any AI engine memories or registers in the
+	 * partition have been mapped. If yes, don't reset.
+	 */
+	if (aie_part_has_mem_mmapped(apart) ||
+	    aie_part_has_regs_mmapped(apart)) {
+		dev_err(&apart->dev,
+			"failed to reset, there are mmapped memories or registers.\n");
+		mutex_unlock(&apart->mlock);
+		return -EBUSY;
+	}
+
+	/* Clear tiles in use bitmap and clock state bitmap */
+	aie_resource_clear_all(&apart->tiles_inuse);
+	aie_resource_clear_all(&apart->cores_clk_state);
+
+	aie_part_set_cols_clkbuf(apart, false);
+	aie_part_set_cols_reset(apart, true);
+
+	ret = apart->adev->ops->reset_shim(adev, &apart->range);
+	if (ret < 0) {
+		return ret;
+		mutex_unlock(&apart->mlock);
+	}
+
+	aie_part_set_cols_clkbuf(apart, false);
+
+	aie_part_clear_cached_events(apart);
+	aie_resource_clear_all(&apart->l2_mask);
+
+	mutex_unlock(&apart->mlock);
+	return 0;
+}
+
+/**
+ * aie_part_post_reinit() - AI engine partition has been re-initialized
+ * @apart: AI engine partition
+ * @return: 0 for success and negative value for failure
+ *
+ * This function will:
+ * - scan which tiles are gated
+ * - update memories and registers mapping
+ *
+ * This function will scan which tiles are gated, and update the memories and
+ * registers setting. This function is called after the AI engine partition is
+ * reconfigured with PDI outside the AI engine driver.
+ */
+int aie_part_post_reinit(struct aie_partition *apart)
+{
+	int ret;
+
+	ret = mutex_lock_interruptible(&apart->mlock);
+	if (ret)
+		return ret;
+
+	ret = aie_part_scan_clk_state(apart);
+	mutex_unlock(&apart->mlock);
+	if (ret) {
+		dev_err(&apart->dev,
+			"failed to scan clock states after reset is done.\n");
+		return ret;
+	}
+
+	return 0;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/xilinx_flex_pm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/xilinx_flex_pm.c
@@ -0,0 +1,657 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx Flex Noc Performance Monitor driver.
+ * Copyright (c) 2019 Xilinx Inc.
+ */
+
+#include <linux/firmware/xlnx-zynqmp.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define to_xflex_dev_info(n)	((struct xflex_dev_info *)dev_get_drvdata(n))
+
+#define FPM_LAR_OFFSET			0xFB0
+#define FPM_UNLOCK			0xC5ACCE55
+
+#define FPM_RD_REQ_OFFSET		0x1000
+#define FPM_RD_RES_OFFSET		0x2000
+#define FPM_WR_REQ_OFFSET		0x3000
+#define FPM_WR_RES_OFFSET		0x4000
+
+#define FPM_PORT_SEL_OFFSET		0x134
+#define FPM_MAIN_CTRL_OFFSET		0x008
+#define FPM_SRC_SEL_OFFSET		0x138
+#define FPM_STATPERIOD			0x24
+#define FPM_CFGCTRL			0x0C
+#define FPM_LPD				0x4210002
+#define FPM_FPD				0x420c003
+
+#define FPM_VAL				0x300
+#define FPM_SRC				0x200
+#define FPM_WRRSP_L			0x70000
+#define FPM_WRREQ_L			0x60000
+#define FPM_RDRSP_L			0x50000
+#define FPM_RDREQ_L			0x40000
+#define FPM_PROBE_SHIFT			16
+#define FPM_COUNTER_OFFSET		0x14
+#define FPM_GLOBALEN			BIT(0)
+#define FPM_STATEN			BIT(3)
+#define FPM_STATCOND_DUMP		BIT(5)
+#define FPM_NUM_COUNTERS		4
+#define FPM_MAINCTL_DIS			0
+
+#define FPM_SRC_OFF			0x0
+#define FPM_SRC_CYCLE			0x1
+#define FPM_SRC_IDLE			0x2
+#define FPM_SRC_XFER			0x3
+#define FPM_SRC_BUSY			0x4
+#define FPM_SRC_WAIT			0x5
+#define FPM_SRC_PACKET			0x6
+
+/* Port values */
+#define FPM_PORT_LPD_AFIFS_AXI		0x0
+#define FPM_PORT_LPD_OCM		0x1
+#define FPM_PORT_LPD_OCMEXT		0x2
+#define FPM_PORT_PMC_RPU_AXI0		0x3
+
+#define FPM_PORT_FPDAXI			0x1
+#define FPM_PORT_PROTXPPU		0x2
+
+/**
+ * struct xflex_dev_info - Global Driver structure
+ * @dev: Device structure
+ * @baselpd: Iomapped LPD base address
+ * @basefpd: Iomapped FPD base address
+ * @funnel: Iomapped funnel register base address
+ * @counterid_lpd: LPD counter id
+ * @counterid_fpd: FPD counter id
+ * @mutex: avoid parallel access to device
+ */
+struct xflex_dev_info {
+	struct device *dev;
+	void __iomem *baselpd;
+	void __iomem *basefpd;
+	void __iomem *funnel;
+	u32 counterid_fpd;
+	u32 counterid_lpd;
+	struct mutex mutex; /* avoid parallel access to device */
+};
+
+/**
+ * enum xflex_sysfs_cmd_codes - sysfs command codes
+ * @XFLEX_GET_COUNTER_FPD: get the FPD counter value
+ * @XFLEX_SET_COUNTER_FPD: set the FPD counter value
+ * @XFLEX_GET_COUNTER_FPD_RDREQ: get the FPD read request count
+ * @XFLEX_GET_COUNTER_FPD_RDRSP: get the FPD read response count
+ * @XFLEX_GET_COUNTER_FPD_WRREQ: get the FPD write request count
+ * @XFLEX_GET_COUNTER_FPD_WRRSP: get the FPD write response count
+ * @XFLEX_GET_COUNTER_LPD_RDREQ: get the LPD read request count
+ * @XFLEX_GET_COUNTER_LPD_RDRSP: get the LPD read response count
+ * @XFLEX_GET_COUNTER_LPD_WRREQ: get the LPD write request count
+ * @XFLEX_GET_COUNTER_LPD_WRRSP: get the LPD write response count
+ * @XFLEX_SET_COUNTER_LPD: set the LPD counter value
+ * @XFLEX_SET_SRC_COUNTER_LPD: set the LPD source
+ * @XFLEX_SET_SRC_COUNTER_FPD: set the FPD source
+ * @XFLEX_SET_PORT_COUNTER_LPD: set the LPD port
+ * @XFLEX_SET_PORT_COUNTER_FPD: set the FPD port
+ */
+enum xflex_sysfs_cmd_codes {
+	XFLEX_GET_COUNTER_FPD = 0,
+	XFLEX_SET_COUNTER_FPD,
+	XFLEX_GET_COUNTER_FPD_RDREQ,
+	XFLEX_GET_COUNTER_FPD_RDRSP,
+	XFLEX_GET_COUNTER_FPD_WRREQ,
+	XFLEX_GET_COUNTER_FPD_WRRSP,
+	XFLEX_GET_COUNTER_LPD_RDREQ,
+	XFLEX_GET_COUNTER_LPD_RDRSP,
+	XFLEX_GET_COUNTER_LPD_WRREQ,
+	XFLEX_GET_COUNTER_LPD_WRRSP,
+	XFLEX_SET_COUNTER_LPD,
+	XFLEX_SET_SRC_COUNTER_LPD,
+	XFLEX_SET_SRC_COUNTER_FPD,
+	XFLEX_SET_PORT_COUNTER_LPD,
+	XFLEX_SET_PORT_COUNTER_FPD,
+};
+
+static inline void fpm_reg(void __iomem *base, u32 val, u32 offset)
+{
+	writel(val, base + FPM_RD_REQ_OFFSET + offset);
+	writel(val, base + FPM_RD_RES_OFFSET + offset);
+	writel(val, base + FPM_WR_REQ_OFFSET + offset);
+	writel(val, base + FPM_WR_RES_OFFSET + offset);
+}
+
+static void reset_default(struct device *dev, u32 counter, u32 domain)
+{
+	struct xflex_dev_info *flexpm = to_xflex_dev_info(dev);
+	void __iomem *base = flexpm->basefpd;
+	u32 offset;
+
+	if (domain == FPM_LPD)
+		base = flexpm->baselpd;
+
+	fpm_reg(base, FPM_MAINCTL_DIS, FPM_MAIN_CTRL_OFFSET);
+	fpm_reg(base, FPM_STATEN | FPM_STATCOND_DUMP, FPM_MAIN_CTRL_OFFSET);
+	fpm_reg(base, FPM_STATEN | FPM_STATCOND_DUMP, FPM_MAIN_CTRL_OFFSET);
+
+	offset = FPM_PORT_SEL_OFFSET + counter * FPM_COUNTER_OFFSET;
+	fpm_reg(base, FPM_PORT_LPD_OCM, offset);
+	offset = FPM_SRC_SEL_OFFSET + counter * FPM_COUNTER_OFFSET;
+	fpm_reg(base, FPM_SRC_PACKET, offset);
+
+	fpm_reg(base, 0, FPM_STATPERIOD);
+	fpm_reg(base, FPM_GLOBALEN, FPM_CFGCTRL);
+}
+
+/**
+ * xflex_sysfs_cmd - Implements sysfs operations
+ * @dev: Device structure
+ * @buf: Value to write
+ * @cmd: sysfs cmd
+ *
+ * Return: value read from the sysfs cmd on success and negative error code
+ *		otherwise.
+ */
+static int xflex_sysfs_cmd(struct device *dev, const char *buf,
+			   enum xflex_sysfs_cmd_codes cmd)
+{
+	struct xflex_dev_info *flexpm = to_xflex_dev_info(dev);
+	u32 domain, src, offset, reg, val, counter;
+	int ret;
+	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
+	u32 rdval = 0;
+	u32 pm_api_ret[4] = {0, 0, 0, 0};
+
+	if (IS_ERR_OR_NULL(eemi_ops))
+		return PTR_ERR(eemi_ops);
+
+	if (!eemi_ops->ioctl)
+		return -ENOTSUPP;
+
+	mutex_lock(&flexpm->mutex);
+
+	switch (cmd) {
+	case XFLEX_GET_COUNTER_LPD_WRRSP:
+		reg = flexpm->counterid_lpd | FPM_WRRSP_L | FPM_VAL;
+		ret = eemi_ops->ioctl(FPM_LPD, IOCTL_PROBE_COUNTER_READ,
+				      reg, 0, &pm_api_ret[0]);
+		if (ret < 0) {
+			dev_err(dev, "Counter read error %d\n", ret);
+			goto exit_unlock;
+		}
+
+		rdval = pm_api_ret[1];
+		break;
+
+	case XFLEX_GET_COUNTER_LPD_WRREQ:
+		reg = flexpm->counterid_lpd | FPM_WRREQ_L | FPM_VAL;
+		ret = eemi_ops->ioctl(FPM_LPD, IOCTL_PROBE_COUNTER_READ,
+				      reg, 0, &pm_api_ret[0]);
+		if (ret < 0) {
+			dev_err(dev, "Counter read error %d\n", ret);
+			goto exit_unlock;
+		}
+
+		rdval = pm_api_ret[1];
+		break;
+
+	case XFLEX_GET_COUNTER_LPD_RDRSP:
+		reg = flexpm->counterid_lpd | FPM_RDRSP_L | FPM_VAL;
+		ret = eemi_ops->ioctl(FPM_LPD, IOCTL_PROBE_COUNTER_READ,
+				      reg, 0, &pm_api_ret[0]);
+		if (ret < 0) {
+			dev_err(dev, "Counter read error %d\n", ret);
+			goto exit_unlock;
+		}
+
+		rdval = pm_api_ret[1];
+		break;
+
+	case XFLEX_GET_COUNTER_LPD_RDREQ:
+		reg = flexpm->counterid_lpd | FPM_RDREQ_L | FPM_VAL;
+		ret = eemi_ops->ioctl(FPM_LPD, IOCTL_PROBE_COUNTER_READ,
+				      reg, 0, &pm_api_ret[0]);
+		if (ret < 0) {
+			dev_err(dev, "Counter read error %d\n", ret);
+			goto exit_unlock;
+		}
+
+		rdval = pm_api_ret[1];
+		break;
+
+	case XFLEX_SET_COUNTER_LPD:
+		ret = kstrtou32(buf, 0, &val);
+		if (ret < 0)
+			goto exit_unlock;
+
+		flexpm->counterid_lpd = val;
+		reset_default(dev, val, FPM_LPD);
+		break;
+
+	case XFLEX_SET_PORT_COUNTER_FPD:
+		ret = kstrtou32(buf, 0, &val);
+		if (ret < 0)
+			goto exit_unlock;
+
+		counter = flexpm->counterid_fpd * FPM_COUNTER_OFFSET;
+		offset = FPM_PORT_SEL_OFFSET + counter * FPM_COUNTER_OFFSET;
+		fpm_reg(flexpm->basefpd, val, offset);
+		break;
+
+	case XFLEX_SET_PORT_COUNTER_LPD:
+		ret = kstrtou32(buf, 0, &val);
+		if (ret < 0)
+			goto exit_unlock;
+
+		counter = flexpm->counterid_lpd * FPM_COUNTER_OFFSET;
+		offset = FPM_PORT_SEL_OFFSET + counter * FPM_COUNTER_OFFSET;
+		fpm_reg(flexpm->baselpd, val, offset);
+		break;
+
+	case XFLEX_SET_SRC_COUNTER_LPD:
+		reg = flexpm->counterid_lpd;
+		domain = FPM_LPD;
+		ret = kstrtou32(buf, 0, &val);
+		if (ret < 0)
+			goto exit_unlock;
+
+		for (src = 0; src < FPM_NUM_COUNTERS; src++) {
+			reg = reg | FPM_SRC | (src << FPM_PROBE_SHIFT);
+			ret = eemi_ops->ioctl(domain, IOCTL_PROBE_COUNTER_WRITE,
+					      reg, val, NULL);
+			if (ret < 0) {
+				dev_err(dev, "Counter write error %d\n", ret);
+				goto exit_unlock;
+			}
+		}
+		break;
+
+	case XFLEX_SET_SRC_COUNTER_FPD:
+		reg = flexpm->counterid_fpd;
+		domain = FPM_FPD;
+		ret = kstrtou32(buf, 0, &val);
+		if (ret < 0)
+			goto exit_unlock;
+
+		for (src = 0; src < FPM_NUM_COUNTERS; src++) {
+			reg = reg | FPM_SRC | (src << FPM_PROBE_SHIFT);
+			ret = eemi_ops->ioctl(domain, IOCTL_PROBE_COUNTER_WRITE,
+					      reg, val, NULL);
+			if (ret < 0) {
+				dev_err(dev, "Counter write error %d\n", ret);
+				goto exit_unlock;
+			}
+		}
+		break;
+
+	case XFLEX_SET_COUNTER_FPD:
+		ret = kstrtou32(buf, 0, &val);
+		if (ret < 0)
+			goto exit_unlock;
+
+		flexpm->counterid_fpd = val;
+		reset_default(dev, val, FPM_FPD);
+		break;
+
+	case XFLEX_GET_COUNTER_FPD_WRRSP:
+		reg = flexpm->counterid_fpd | FPM_WRRSP_L | FPM_VAL;
+		ret = eemi_ops->ioctl(FPM_FPD, IOCTL_PROBE_COUNTER_READ,
+				      reg, 0, &pm_api_ret[0]);
+		if (ret < 0) {
+			dev_err(dev, "Counter read error %d\n", ret);
+			goto exit_unlock;
+		}
+
+		rdval = pm_api_ret[1];
+		break;
+
+	case XFLEX_GET_COUNTER_FPD_WRREQ:
+		reg = flexpm->counterid_fpd | FPM_WRREQ_L | FPM_VAL;
+		ret = eemi_ops->ioctl(FPM_FPD, IOCTL_PROBE_COUNTER_READ,
+				      reg, 0, &pm_api_ret[0]);
+		if (ret < 0) {
+			dev_err(dev, "Counter read error %d\n", ret);
+			goto exit_unlock;
+		}
+
+		rdval = pm_api_ret[1];
+		break;
+
+	case XFLEX_GET_COUNTER_FPD_RDRSP:
+		reg = flexpm->counterid_fpd | FPM_RDRSP_L | FPM_VAL;
+		ret = eemi_ops->ioctl(FPM_FPD, IOCTL_PROBE_COUNTER_READ,
+				      reg, 0, &pm_api_ret[0]);
+		if (ret < 0) {
+			dev_err(dev, "Counter read error %d\n", ret);
+			goto exit_unlock;
+		}
+
+		rdval = pm_api_ret[1];
+		break;
+
+	case XFLEX_GET_COUNTER_FPD_RDREQ:
+		reg = flexpm->counterid_fpd | FPM_RDREQ_L | FPM_VAL;
+		ret = eemi_ops->ioctl(FPM_FPD, IOCTL_PROBE_COUNTER_READ,
+				      reg, 0, &pm_api_ret[0]);
+		if (ret < 0) {
+			dev_err(dev, "Counter read error %d\n", ret);
+			goto exit_unlock;
+		}
+
+		rdval = pm_api_ret[1];
+		break;
+
+	default:
+		dev_err(dev, "Invalid option\n");
+		break;
+	}
+
+	mutex_unlock(&flexpm->mutex);
+	return rdval;
+
+exit_unlock:
+	mutex_unlock(&flexpm->mutex);
+	return ret;
+}
+
+/* Sysfs functions */
+
+static ssize_t counterfpd_wrreq_show(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	int rdval = xflex_sysfs_cmd(dev, buf, XFLEX_GET_COUNTER_FPD_WRREQ);
+
+	if (rdval < 0)
+		return 0;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", rdval);
+}
+static DEVICE_ATTR_RO(counterfpd_wrreq);
+
+static ssize_t counterfpd_wrrsp_show(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	int rdval = xflex_sysfs_cmd(dev, buf, XFLEX_GET_COUNTER_FPD_WRRSP);
+
+	if (rdval < 0)
+		return 0;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", rdval);
+}
+static DEVICE_ATTR_RO(counterfpd_wrrsp);
+
+static ssize_t counterfpd_rdreq_show(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	int rdval = xflex_sysfs_cmd(dev, buf, XFLEX_GET_COUNTER_FPD_RDREQ);
+
+	if (rdval < 0)
+		return 0;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", rdval);
+}
+static DEVICE_ATTR_RO(counterfpd_rdreq);
+
+static ssize_t counterfpd_rdrsp_show(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	int rdval = xflex_sysfs_cmd(dev, buf, XFLEX_GET_COUNTER_FPD_RDRSP);
+
+	if (rdval < 0)
+		return 0;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", rdval);
+}
+static DEVICE_ATTR_RO(counterfpd_rdrsp);
+
+static ssize_t counterlpd_wrreq_show(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	int rdval = xflex_sysfs_cmd(dev, buf, XFLEX_GET_COUNTER_LPD_WRREQ);
+
+	if (rdval < 0)
+		return 0;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", rdval);
+}
+static DEVICE_ATTR_RO(counterlpd_wrreq);
+
+static ssize_t counterlpd_wrrsp_show(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	int rdval = xflex_sysfs_cmd(dev, buf, XFLEX_GET_COUNTER_LPD_WRRSP);
+
+	if (rdval < 0)
+		return 0;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", rdval);
+}
+static DEVICE_ATTR_RO(counterlpd_wrrsp);
+
+static ssize_t counterlpd_rdreq_show(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	int rdval = xflex_sysfs_cmd(dev, buf, XFLEX_GET_COUNTER_LPD_RDREQ);
+
+	if (rdval < 0)
+		return 0;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", rdval);
+}
+static DEVICE_ATTR_RO(counterlpd_rdreq);
+
+static ssize_t counterlpd_rdrsp_show(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	int rdval = xflex_sysfs_cmd(dev, buf, XFLEX_GET_COUNTER_LPD_RDRSP);
+
+	if (rdval < 0)
+		return 0;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", rdval);
+}
+static DEVICE_ATTR_RO(counterlpd_rdrsp);
+
+static ssize_t counterlpdsrc_store(struct device *dev,
+				   struct device_attribute *attr,
+				   const char *buf, size_t size)
+{
+	xflex_sysfs_cmd(dev, buf, XFLEX_SET_SRC_COUNTER_LPD);
+
+	return size;
+}
+static DEVICE_ATTR_WO(counterlpdsrc);
+
+static ssize_t counterfpdsrc_store(struct device *dev,
+				   struct device_attribute *attr,
+				   const char *buf, size_t size)
+{
+	xflex_sysfs_cmd(dev, buf, XFLEX_SET_SRC_COUNTER_FPD);
+
+	return size;
+}
+static DEVICE_ATTR_WO(counterfpdsrc);
+
+static ssize_t counterlpdport_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t size)
+{
+	xflex_sysfs_cmd(dev, buf, XFLEX_SET_PORT_COUNTER_LPD);
+
+	return size;
+}
+static DEVICE_ATTR_WO(counterlpdport);
+
+static ssize_t counterfpdport_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t size)
+{
+	xflex_sysfs_cmd(dev, buf, XFLEX_SET_PORT_COUNTER_FPD);
+
+	return size;
+}
+static DEVICE_ATTR_WO(counterfpdport);
+
+static ssize_t counteridlpd_show(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	struct xflex_dev_info *flexpm = to_xflex_dev_info(dev);
+
+	return snprintf(buf, PAGE_SIZE, "%08d\n", flexpm->counterid_lpd);
+}
+
+static ssize_t counteridlpd_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t size)
+{
+	int ret;
+	struct xflex_dev_info *flexpm = to_xflex_dev_info(dev);
+
+	ret = kstrtou32(buf, 0, &flexpm->counterid_lpd);
+	if (ret < 0)
+		return ret;
+
+	reset_default(dev, flexpm->counterid_lpd, FPM_LPD);
+
+	return size;
+}
+static DEVICE_ATTR_RW(counteridlpd);
+
+static ssize_t counteridfpd_show(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	struct xflex_dev_info *flexpm = to_xflex_dev_info(dev);
+
+	return snprintf(buf, PAGE_SIZE, "%08d\n", flexpm->counterid_fpd);
+}
+
+static ssize_t counteridfpd_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t size)
+{
+	int ret;
+	struct xflex_dev_info *flexpm = to_xflex_dev_info(dev);
+
+	ret = kstrtou32(buf, 0, &flexpm->counterid_fpd);
+	if (ret < 0)
+		return ret;
+
+	return size;
+}
+static DEVICE_ATTR_RW(counteridfpd);
+
+static struct attribute *xflex_attrs[] = {
+	&dev_attr_counterlpdsrc.attr,
+	&dev_attr_counterlpdport.attr,
+	&dev_attr_counterfpdsrc.attr,
+	&dev_attr_counterfpdport.attr,
+
+	&dev_attr_counterlpd_rdreq.attr,
+	&dev_attr_counterlpd_wrreq.attr,
+	&dev_attr_counterlpd_rdrsp.attr,
+	&dev_attr_counterlpd_wrrsp.attr,
+
+	&dev_attr_counterfpd_rdreq.attr,
+	&dev_attr_counterfpd_wrreq.attr,
+	&dev_attr_counterfpd_rdrsp.attr,
+	&dev_attr_counterfpd_wrrsp.attr,
+
+	&dev_attr_counteridlpd.attr,
+	&dev_attr_counteridfpd.attr,
+	NULL,
+};
+
+ATTRIBUTE_GROUPS(xflex);
+
+/**
+ * xflex_probe - Driver probe function
+ * @pdev: Pointer to the platform_device structure
+ *
+ * This is the driver probe routine. It does all the memory
+ * allocation and creates sysfs entries for the device.
+ *
+ * Return: 0 on success and failure value on error
+ */
+static int xflex_probe(struct platform_device *pdev)
+{
+	struct xflex_dev_info *flexpm;
+	struct resource *res;
+	int err;
+	struct device *dev = &pdev->dev;
+
+	flexpm = devm_kzalloc(dev, sizeof(*flexpm), GFP_KERNEL);
+	if (!flexpm)
+		return -ENOMEM;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "baselpd");
+	flexpm->baselpd = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(flexpm->baselpd))
+		return PTR_ERR(flexpm->baselpd);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "basefpd");
+	flexpm->basefpd = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(flexpm->basefpd))
+		return PTR_ERR(flexpm->basefpd);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "funnel");
+	flexpm->funnel = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(flexpm->funnel))
+		return PTR_ERR(flexpm->funnel);
+
+	mutex_init(&flexpm->mutex);
+	writel(FPM_UNLOCK, flexpm->funnel + FPM_LAR_OFFSET);
+	writel(FPM_UNLOCK, flexpm->baselpd + FPM_LAR_OFFSET);
+
+	/* Create sysfs file entries for the device */
+	err = sysfs_create_groups(&dev->kobj, xflex_groups);
+	if (err < 0) {
+		dev_err(dev, "unable to create sysfs entries\n");
+		return err;
+	}
+
+	dev_set_drvdata(dev, flexpm);
+
+	return 0;
+}
+
+/**
+ * xflex_remove - Driver remove function
+ * @pdev: Pointer to the platform_device structure
+ *
+ * This function frees all the resources allocated to the device.
+ *
+ * Return: 0 always
+ */
+static int xflex_remove(struct platform_device *pdev)
+{
+	sysfs_remove_groups(&pdev->dev.kobj, xflex_groups);
+	return 0;
+}
+
+static const struct of_device_id xflex_of_match[] = {
+	{ .compatible = "xlnx,flexnoc-pm-2.7", },
+	{ /* end of table */ }
+};
+MODULE_DEVICE_TABLE(of, xflex_of_match);
+
+static struct platform_driver xflex_driver = {
+	.driver = {
+		.name = "xilinx-flex",
+		.of_match_table = xflex_of_match,
+	},
+	.probe = xflex_probe,
+	.remove = xflex_remove,
+};
+
+module_platform_driver(xflex_driver);
+
+MODULE_AUTHOR("Shubhrajyoti Datta <shubhrajyoti.datta@xilinx.com>");
+MODULE_DESCRIPTION("Xilinx Flexnoc performance monitor driver");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/xilinx_sdfec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/xilinx_sdfec.c
@@ -602,10 +602,10 @@
 			      const u32 depth)
 {
 	u32 reg = 0;
-	u32 res;
-	u32 n, i;
+	int res, i, nr_pages;
+	u32 n;
 	u32 *addr = NULL;
-	struct page *page[MAX_NUM_PAGES];
+	struct page *pages[MAX_NUM_PAGES];
 
 	/*
 	 * Writes that go beyond the length of
@@ -622,15 +622,22 @@
 	if ((len * XSDFEC_REG_WIDTH_JUMP) % PAGE_SIZE)
 		n += 1;
 
-	res = get_user_pages_fast((unsigned long)src_ptr, n, 0, page);
-	if (res < n) {
-		for (i = 0; i < res; i++)
-			put_page(page[i]);
+	if (WARN_ON_ONCE(n > INT_MAX))
+		return -EINVAL;
+
+	nr_pages = n;
+
+	res = get_user_pages_fast((unsigned long)src_ptr, nr_pages, 0, pages);
+	if (res < nr_pages) {
+		if (res > 0) {
+			for (i = 0; i < res; i++)
+				put_page(pages[i]);
+		}
 		return -EINVAL;
 	}
 
-	for (i = 0; i < n; i++) {
-		addr = kmap(page[i]);
+	for (i = 0; i < nr_pages; i++) {
+		addr = kmap(pages[i]);
 		do {
 			xsdfec_regwrite(xsdfec,
 					base_addr + ((offset + reg) *
@@ -639,7 +646,7 @@
 			reg++;
 		} while ((reg < len) &&
 			 ((reg * XSDFEC_REG_WIDTH_JUMP) % PAGE_SIZE));
-		put_page(page[i]);
+		put_page(pages[i]);
 	}
 	return reg;
 }
@@ -1025,25 +1032,25 @@
 }
 #endif
 
-static unsigned int xsdfec_poll(struct file *file, poll_table *wait)
+static __poll_t xsdfec_poll(struct file *file, poll_table *wait)
 {
-	unsigned int mask = 0;
+	__poll_t mask = 0;
 	struct xsdfec_dev *xsdfec;
 
 	xsdfec = container_of(file->private_data, struct xsdfec_dev, miscdev);
 
 	if (!xsdfec)
-		return POLLNVAL | POLLHUP;
+		return EPOLLNVAL | EPOLLHUP;
 
 	poll_wait(file, &xsdfec->waitq, wait);
 
 	/* XSDFEC ISR detected an error */
 	spin_lock_irqsave(&xsdfec->error_data_lock, xsdfec->flags);
 	if (xsdfec->state_updated)
-		mask |= POLLIN | POLLPRI;
+		mask |= EPOLLIN | EPOLLPRI;
 
 	if (xsdfec->stats_updated)
-		mask |= POLLIN | POLLRDNORM;
+		mask |= EPOLLIN | EPOLLRDNORM;
 	spin_unlock_irqrestore(&xsdfec->error_data_lock, xsdfec->flags);
 
 	return mask;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/misc/xilinx_trafgen.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/misc/xilinx_trafgen.c
@@ -0,0 +1,1654 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx AXI Traffic Generator driver.
+ *
+ * Copyright (c) 2013 - 2019 Xilinx Inc.
+ *
+ * Description:
+ * This driver is developed for AXI Traffic Generator IP, which is
+ * designed to generate AXI4 traffic which can be used to stress
+ * different modules/interconnect connected in the system. Different
+ * configurable options which are provided through sysfs entries
+ * allow the user to generate a wide variety of traffic based on
+ * their requirements.
+ */
+
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+/* Hw specific definitions */
+
+/* Internal RAM Offsets */
+#define XTG_PARAM_RAM_OFFSET	   0x1000  /* Parameter RAM offset */
+#define XTG_COMMAND_RAM_OFFSET	   0x8000  /* Command RAM offset */
+#define XTG_COMMAND_RAM_MSB_OFFSET 0xa000	/**< Command RAM MSB Offset */
+#define XTG_MASTER_RAM_INIT_OFFSET 0x10000 /* Master RAM initial offset(v1.0) */
+#define XTG_MASTER_RAM_OFFSET	   0xc000  /* Master RAM offset */
+#define XTG_WRITE_COMMAND_RAM_OFFSET	0x9000  /* Write Command RAM offset */
+
+/* Register Offsets */
+#define XTG_MCNTL_OFFSET	0x00	/* Master control */
+#define XTG_SCNTL_OFFSET	0x04	/* Slave control */
+#define XTG_ERR_STS_OFFSET	0x08	/* Error status  */
+#define XTG_ERR_EN_OFFSET	0x0C	/* Error enable */
+#define XTG_MSTERR_INTR_OFFSET	0x10	/* Master error interrupt enable */
+#define XTG_CFG_STS_OFFSET	0x14	/* Config status */
+#define XTG_STREAM_CNTL_OFFSET	0x30	/* Streaming Control */
+#define XTG_STREAM_CFG_OFFSET	0x34	/* Streaming Control */
+#define XTG_STREAM_TL_OFFSET	0x38    /* Streaming Transfer Length */
+#define XTG_STREAM_TKTS1_OFFSET	0x40    /* Streaming tkeep tstrb set1*/
+#define XTG_STREAM_TKTS2_OFFSET	0x44    /* Streaming tkeep tstrb set2*/
+#define XTG_STREAM_TKTS3_OFFSET	0x48    /* Streaming tkeep tstrb set3*/
+#define XTG_STREAM_TKTS4_OFFSET	0x4C    /* Streaming tkeep tstrb set4*/
+#define XTG_STATIC_CNTL_OFFSET	0x60	/* Static Control */
+#define XTG_STATIC_LEN_OFFSET	0x64	/* Static Length */
+
+/* Register Bitmasks/shifts */
+
+/* Master logic enable */
+#define XTG_MCNTL_MSTEN_MASK		0x00100000
+/* Loop enable */
+#define XTG_MCNTL_LOOPEN_MASK		0x00080000
+/* Slave error interrupt enable */
+#define XTG_SCNTL_ERREN_MASK		0x00008000
+/* Master complete interrupt enable */
+#define XTG_ERR_EN_MSTIRQEN_MASK	0x80000000
+/* Master error interrupt enable */
+#define XTG_MSTERR_INTR_MINTREN_MASK	0x00008000
+/* Master complete done status */
+#define XTG_ERR_STS_MSTDONE_MASK	0x80000000
+/* Error mask for error status/enable registers */
+#define XTG_ERR_ALL_ERRS_MASK		0x801F0003
+/* Core Revision shift */
+#define XTG_MCNTL_REV_SHIFT		24
+
+/* Axi Traffic Generator Command RAM Entry field mask/shifts */
+
+/* Command RAM entry masks */
+#define XTG_LEN_MASK		0xFF		/* Driven to a*_len line  */
+#define XTG_LOCK_MASK		0x1		/* Driven to a*_lock line */
+#define XTG_BURST_MASK		0x3		/* Driven to a*_burst line */
+#define XTG_SIZE_MASK		0x7		/* Driven to a*_size line */
+#define XTG_ID_MASK		0x1F		/* Driven to a*_id line */
+#define XTG_PROT_MASK		0x7		/* Driven to a*_prot line */
+#define XTG_LAST_ADDR_MASK	0x7		/* Last address */
+#define XTG_VALID_CMD_MASK	0x1		/* Valid Command */
+#define XTG_MSTRAM_INDEX_MASK	0x1FFF		/* Master RAM Index */
+#define XTG_OTHER_DEPEND_MASK	0x1FF		/* Other depend Command no */
+#define XTG_MY_DEPEND_MASK	0x1FF		/* My depend command no */
+#define XTG_QOS_MASK		0xF		/* Driven to a*_qos line */
+#define XTG_USER_MASK		0xFF		/* Driven to a*_user line */
+#define XTG_CACHE_MASK		0xF		/* Driven to a*_cache line */
+#define XTG_EXPECTED_RESP_MASK	0x7		/* Expected response */
+
+/* Command RAM entry shift values */
+#define XTG_LEN_SHIFT		0		/* Driven to a*_len line  */
+#define XTG_LOCK_SHIFT		8		/* Driven to a*_lock line */
+#define XTG_BURST_SHIFT		10		/* Driven to a*_burst line */
+#define XTG_SIZE_SHIFT		12		/* Driven to a*_size line */
+#define XTG_ID_SHIFT		15		/* Driven to a*_id line */
+#define XTG_PROT_SHIFT		21		/* Driven to a*_prot line */
+#define XTG_LAST_ADDR_SHIFT	28		/* Last address */
+#define XTG_VALID_CMD_SHIFT	31		/* Valid Command */
+#define XTG_MSTRAM_INDEX_SHIFT	0		/* Master RAM Index */
+#define XTG_OTHER_DEPEND_SHIFT	13		/* Other depend cmd num */
+#define XTG_MY_DEPEND_SHIFT	22		/* My depend cmd num */
+#define XTG_QOS_SHIFT		16		/* Driven to a*_qos line */
+#define XTG_USER_SHIFT		5		/* Driven to a*_user line */
+#define XTG_CACHE_SHIFT		4		/* Driven to a*_cache line */
+#define XTG_EXPECTED_RESP_SHIFT	0		/* Expected response */
+
+/* Axi Traffic Generator Parameter RAM Entry field mask/shifts */
+
+/* Parameter RAM Entry field shift values */
+#define XTG_PARAM_ADDRMODE_SHIFT	24	/* Address mode */
+#define XTG_PARAM_INTERVALMODE_SHIFT	26	/* Interval mode */
+#define XTG_PARAM_IDMODE_SHIFT		28	/* Id mode */
+#define XTG_PARAM_OP_SHIFT		29	/* Opcode */
+
+/* PARAM RAM Opcode shift values */
+#define XTG_PARAM_COUNT_SHIFT		0	/* Repeat/Delay count */
+#define XTG_PARAM_DELAYRANGE_SHIFT	0	/* Delay range */
+#define XTG_PARAM_DELAY_SHIFT		8	/* FIXED RPT delay count */
+#define XTG_PARAM_ADDRRANGE_SHIFT	20	/* Address range */
+
+/* Parameter RAM Entry field mask values */
+#define XTG_PARAM_ADDRMODE_MASK		0x3	/* Address mode */
+#define XTG_PARAM_INTERVALMODE_MASK	0x3	/* Interval mode */
+#define XTG_PARAM_IDMODE_MASK		0x1	/* Id mode */
+#define XTG_PARAM_OP_MASK		0x7	/* Opcode */
+
+/* PARAM RAM Opcode mask values */
+#define XTG_PARAM_COUNT_MASK		0xFFFFFF/* Repeat/Delay count */
+#define XTG_PARAM_DELAYRANGE_MASK	0xFF	/* Delay range */
+#define XTG_PARAM_DELAY_MASK		0xFFF	/* FIXED RPT delay count */
+#define XTG_PARAM_ADDRRANGE_MASK	0xF	/* Address range */
+
+/* PARAM RAM Opcode values */
+#define XTG_PARAM_OP_NOP		0x0	/* NOP mode */
+#define XTG_PARAM_OP_RPT		0x1	/* Repeat mode */
+#define XTG_PARAM_OP_DELAY		0x2	/* Delay mode */
+#define XTG_PARAM_OP_FIXEDRPT		0x3	/* Fixed repeat delay */
+
+/* Axi Traffic Generator Static Mode masks */
+#define XTG_STATIC_CNTL_TD_MASK		0x00000002	/* Transfer Done Mask */
+#define XTG_STATIC_CNTL_STEN_MASK	0x00000001	/* Static Enable Mask */
+#define XTG_STATIC_CNTL_RESET_MASK	0x00000000	/* Static Reset Mask */
+
+/* Axi Traffic Generator Stream Mode mask/shifts */
+#define XTG_STREAM_CNTL_STEN_MASK   0x00000001	/* Stream Enable Mask */
+#define XTG_STREAM_TL_TCNT_MASK	    0xFFFF0000	/* Transfer Count Mask */
+#define XTG_STREAM_TL_TLEN_MASK	    0x0000FFFF	/* Transfer Length Mask */
+#define XTG_STREAM_TL_TCNT_SHIFT    16		/* Transfer Count Shift */
+
+/* Driver Specific Definitions */
+
+#define MAX_NUM_ENTRIES	256	/* Number of command entries per region */
+
+#define VALID_SIG	0xa5a5a5a5	/* Valid unique identifier */
+
+/* Internal RAM Sizes */
+#define XTG_PRM_RAM_BLOCK_SIZE	0x400	/* PRAM Block size (1KB) */
+#define XTG_CMD_RAM_BLOCK_SIZE	0x1000	/* CRAM Block size (4KB) */
+#define XTG_EXTCMD_RAM_BLOCK_SIZE 0x400	/**< Extended CMDRAM Block Size (1KB) */
+#define XTG_PARAM_RAM_SIZE	0x800	/* Parameter RAM (2KB) */
+#define XTG_COMMAND_RAM_SIZE	0x2000	/* Command RAM (8KB) */
+#define XTG_EXTCMD_RAM_SIZE	0x800	/* Command RAM (2KB) */
+#define XTG_MASTER_RAM_SIZE	0x2000	/* Master RAM (8KB) */
+
+/* RAM Access Flags */
+#define XTG_READ_RAM		0x0	/* Read RAM flag */
+#define XTG_WRITE_RAM		0x1	/* Write RAM flag */
+#define XTG_WRITE_RAM_ZERO	0x2	/* Write Zero flag */
+
+/* Bytes per entry */
+#define XTG_CRAM_BYTES_PER_ENTRY	16 /* CRAM bytes per entry */
+#define XTG_PRAM_BYTES_PER_ENTRY	4  /* PRAM bytes per entry */
+
+/* Interrupt Definitions */
+#define XTG_MASTER_CMP_INTR	0x1	/* Master complete intr flag */
+#define XTG_MASTER_ERR_INTR	0x2	/* Master error intr flag */
+#define XTG_SLAVE_ERR_INTR	0x4	/* Slave error intr flag */
+
+/*
+ * Version value of the trafgen core.
+ * For the initial IP release the version(v1.0) value is 0x47
+ * From the v2.0 IP and onwards the value starts from  0x20.
+ * For eg:
+ * v2.1 -> 0x21
+ * v2.2 -> 0x22 ... so on.
+ *
+ */
+#define XTG_INIT_VERSION	0x47	/* Trafgen initial version(v1.0) */
+
+/* Macro */
+#define to_xtg_dev_info(n)	((struct xtg_dev_info *)dev_get_drvdata(n))
+
+#define CMD_WDS	0x4	/* No of words in command ram per command */
+#define EXT_WDS	0x1	/* No of words in extended ram per command */
+#define MSB_INDEX	0x4
+/**
+ * struct xtg_cram - Command RAM structure
+ * @addr: Address Driven to a*_addr line
+ * @valid_cmd: Valid Command
+ * @last_addr: Last address
+ * @prot: Driven to a*_prot line
+ * @id: Driven to a*_id line
+ * @size: Driven to a*_size line
+ * @burst: Driven to a*_burst line
+ * @lock: Driven to a*_lock line
+ * @length: Driven to a*_len line
+ * @my_dpnd: My Depend command number
+ * @other_dpnd: Other depend command number
+ * @mram_idx: Master RAM index
+ * @qos: Driven to a*_qos line
+ * @user: Driven to a*_user line
+ * @cache: Driven to a*_cache line
+ * @expected_resp: Expected response
+ * @index: Command Index
+ * @is_write_block: Write/Read block
+ * @is_valid_req: Unique signature
+ *
+ * FIXME: This structure is shared with the user application and
+ * hence need to be synchronized. We know these kind of structures
+ * should not be defined in the driver and this need to be fixed
+ * if found a proper placeholder (in uapi/).
+ */
+struct xtg_cram {
+	phys_addr_t addr;
+	u32 valid_cmd;
+	u32 last_addr;
+	u32 prot;
+	u32 id;
+	u32 size;
+	u32 burst;
+	u32 lock;
+	u32 length;
+	u32 my_dpnd;
+	u32 other_dpnd;
+	u32 mram_idx;
+	u32 qos;
+	u32 user;
+	u32 cache;
+	u32 expected_resp;
+	u16 index;
+	bool is_write_block;
+	u32 is_valid_req;
+};
+
+/**
+ * struct xtg_pram - Parameter RAM structure
+ * @op_cntl0: Control field 0
+ * @op_cntl1: Control field 1
+ * @op_cntl2: Control field 2
+ * @addr_mode: Address mode
+ * @interval_mode: Interval mode
+ * @id_mode: Id mode
+ * @opcode: Opcode
+ * @index: Command Index
+ * @is_write_block: Write/Read block
+ * @is_valid_req: Unique signature
+ *
+ * FIXME: This structure is shared with the user application and
+ * hence need to be synchronized. We know these kind of structures
+ * should not be defined in the driver and this need to be fixed
+ * if found a proper placeholder (in uapi/).
+ */
+struct xtg_pram {
+	u32 op_cntl0;
+	u32 op_cntl1;
+	u32 op_cntl2;
+	u32 addr_mode;
+	u32 interval_mode;
+	u32 id_mode;
+	u32 opcode;
+	u16 index;
+	bool is_write_block;
+	u32 is_valid_req;
+};
+
+/**
+ * struct xtg_dev_info - Global Driver structure
+ * @regs: Iomapped base address
+ * @dev: Device structure
+ * @phys_base_addr: Physical base address
+ * @last_rd_valid_idx: Last Read Valid Command Index
+ * @last_wr_valid_idx: Last Write Valid Command Index
+ * @id: Device instance id
+ * @xtg_mram_offset: MasterRam offset
+ * @clk: Input clock
+ */
+struct xtg_dev_info {
+	void __iomem *regs;
+	struct device *dev;
+	phys_addr_t phys_base_addr;
+	s16 last_rd_valid_idx;
+	s16 last_wr_valid_idx;
+	u32 id;
+	u32 xtg_mram_offset;
+	struct clk *clk;
+};
+
+/**
+ * enum xtg_sysfs_ioctl - Ioctl opcodes
+ * @XTG_GET_MASTER_CMP_STS: get master complete status
+ * @XTG_GET_SLV_CTRL_REG: get slave control reg status
+ * @XTG_GET_ERR_STS: get error status
+ * @XTG_GET_CFG_STS: get config status
+ * @XTG_GET_LAST_VALID_INDEX: get last valid index
+ * @XTG_GET_DEVICE_ID: get device id
+ * @XTG_GET_RESOURCE: get resource
+ * @XTG_GET_STATIC_ENABLE: get staic mode traffic genration state
+ * @XTG_GET_STATIC_BURSTLEN: get static mode burst length
+ * @XTG_GET_STATIC_TRANSFERDONE: get static transfer done
+ * @XTG_GET_STREAM_ENABLE : get strean mode traffic genration state
+ * @XTG_GET_STREAM_TRANSFERLEN: get streaming mode transfer length
+ * @XTG_GET_STREAM_TRANSFERCNT: get streaming mode transfer count
+ * @XTG_GET_MASTER_LOOP_EN: get master loop enable status
+ * @XTG_GET_STREAM_TKTS1: get stream tstrb and tkeep set1 values
+ * @XTG_GET_STREAM_TKTS2: get stream tstrb and tkeep set2 values
+ * @XTG_GET_STREAM_TKTS3: get stream tstrb and tkeep set3 values
+ * @XTG_GET_STREAM_TKTS4: get stream tstrb and tkeep set4 values
+ * @XTG_GET_STREAM_CFG: get stream configuration values
+ * @XTG_START_MASTER_LOGIC: start master logic
+ * @XTG_SET_SLV_CTRL_REG: set slave control
+ * @XTG_CLEAR_ERRORS: clear errors
+ * @XTG_ENABLE_ERRORS: enable errors
+ * @XTG_ENABLE_INTRS: enable interrupts
+ * @XTG_CLEAR_MRAM: clear master ram
+ * @XTG_CLEAR_CRAM: clear command ram
+ * @XTG_CLEAR_PRAM: clear parameter ram
+ * @XTG_SET_STATIC_ENABLE: enable static mode traffic genration
+ * @XTG_SET_STATIC_DISABLE: disable static mode traffic genration
+ * @XTG_SET_STATIC_BURSTLEN: set static mode burst length
+ * @XTG_SET_STATIC_TRANSFERDONE: set static transfer done
+ * @XTG_SET_STREAM_ENABLE: enable streaming mode traffic genration
+ * @XTG_SET_STREAM_DISABLE: disable streaming mode traffic genration
+ * @XTG_SET_STREAM_TRANSFERLEN: set streaming mode transfer length
+ * @XTG_SET_STREAM_TRANSFERCNT: set streaming mode transfer count
+ * @XTG_SET_STREAM_TKTS1: set stream tstrb and tkeep set1 values
+ * @XTG_SET_STREAM_TKTS2: set stream tstrb and tkeep set2 values
+ * @XTG_SET_STREAM_TKTS3: set stream tstrb and tkeep set3 values
+ * @XTG_SET_STREAM_TKTS4: set stream tstrb and tkeep set4 values
+ * @XTG_SET_STREAM_CFG: set stream configuration values
+ * @XTG_MASTER_LOOP_EN: enable master loop
+ */
+enum xtg_sysfs_ioctl_opcode {
+	XTG_GET_MASTER_CMP_STS,
+	XTG_GET_SLV_CTRL_REG,
+	XTG_GET_ERR_STS,
+	XTG_GET_CFG_STS,
+	XTG_GET_LAST_VALID_INDEX,
+	XTG_GET_DEVICE_ID,
+	XTG_GET_RESOURCE,
+	XTG_GET_STATIC_ENABLE,
+	XTG_GET_STATIC_BURSTLEN,
+	XTG_GET_STATIC_TRANSFERDONE,
+	XTG_GET_STREAM_ENABLE,
+	XTG_GET_STREAM_TRANSFERLEN,
+	XTG_GET_MASTER_LOOP_EN,
+	XTG_GET_STREAM_TKTS1,
+	XTG_GET_STREAM_TKTS2,
+	XTG_GET_STREAM_TKTS3,
+	XTG_GET_STREAM_TKTS4,
+	XTG_GET_STREAM_CFG,
+	XTG_GET_STREAM_TRANSFERCNT,
+	XTG_START_MASTER_LOGIC,
+	XTG_SET_SLV_CTRL_REG,
+	XTG_CLEAR_ERRORS,
+	XTG_ENABLE_ERRORS,
+	XTG_ENABLE_INTRS,
+	XTG_CLEAR_MRAM,
+	XTG_CLEAR_CRAM,
+	XTG_CLEAR_PRAM,
+	XTG_SET_STATIC_ENABLE,
+	XTG_SET_STATIC_DISABLE,
+	XTG_SET_STATIC_BURSTLEN,
+	XTG_SET_STATIC_TRANSFERDONE,
+	XTG_SET_STREAM_ENABLE,
+	XTG_SET_STREAM_DISABLE,
+	XTG_SET_STREAM_TRANSFERLEN,
+	XTG_SET_STREAM_TRANSFERCNT,
+	XTG_SET_STREAM_TKTS1,
+	XTG_SET_STREAM_TKTS2,
+	XTG_SET_STREAM_TKTS3,
+	XTG_SET_STREAM_TKTS4,
+	XTG_SET_STREAM_CFG,
+	XTG_MASTER_LOOP_EN
+};
+
+/**
+ * xtg_access_rams - Write/Read Master/Command/Parameter RAM
+ * @tg: Pointer to xtg_dev_info structure
+ * @where: Offset from base
+ * @count: Number of bytes to write/read
+ * @flags: Read/Write/Write Zero
+ * @data: Data pointer
+ */
+static void xtg_access_rams(struct xtg_dev_info *tg, int where,
+			    int count, int flags, u32 *data)
+{
+	u32 index;
+
+	switch (flags) {
+	case XTG_WRITE_RAM_ZERO:
+		memset_io(tg->regs + where, 0, count);
+#ifdef CONFIG_PHYS_ADDR_T_64BIT
+		writel(0x0, tg->regs + where +
+			(XTG_COMMAND_RAM_MSB_OFFSET - XTG_COMMAND_RAM_OFFSET) +
+			XTG_EXTCMD_RAM_BLOCK_SIZE - XTG_CMD_RAM_BLOCK_SIZE);
+#endif
+		break;
+	case XTG_WRITE_RAM:
+		for (index = 0; count > 0; index++, count -= 4)
+			writel(data[index], tg->regs + where + index * 4);
+#ifdef CONFIG_PHYS_ADDR_T_64BIT
+	/*
+	 * This additional logic is required only for command ram.
+	 * when writing to READ Command RAM write higher address to READ addr
+	 * RAM
+	 */
+	if (where >= XTG_COMMAND_RAM_OFFSET &&
+	    where < XTG_WRITE_COMMAND_RAM_OFFSET)
+		writel(data[MSB_INDEX],	tg->regs + XTG_COMMAND_RAM_OFFSET +
+			(where - XTG_COMMAND_RAM_OFFSET) / 4 +
+			(XTG_COMMAND_RAM_MSB_OFFSET - XTG_COMMAND_RAM_OFFSET));
+	/*
+	 * Writing to WRITE Command RAM write higher address to WRITE addr RAM
+	 */
+	if (where >=  XTG_WRITE_COMMAND_RAM_OFFSET &&
+	    where < XTG_COMMAND_RAM_MSB_OFFSET)
+		writel(data[MSB_INDEX],	tg->regs +
+			XTG_WRITE_COMMAND_RAM_OFFSET +
+			(where - XTG_WRITE_COMMAND_RAM_OFFSET) / 4 +
+			(XTG_COMMAND_RAM_MSB_OFFSET - XTG_COMMAND_RAM_OFFSET) +
+			XTG_EXTCMD_RAM_BLOCK_SIZE - XTG_CMD_RAM_BLOCK_SIZE);
+#endif
+		break;
+	case XTG_READ_RAM:
+		for (index = 0; count > 0; index++, count -= 4)
+			data[index] = readl(tg->regs + where + index * 4);
+#ifdef CONFIG_PHYS_ADDR_T_64BIT
+	if (where >= XTG_COMMAND_RAM_OFFSET &&
+	    where < XTG_WRITE_COMMAND_RAM_OFFSET)
+		data[MSB_INDEX] = readl(tg->regs + XTG_COMMAND_RAM_OFFSET +
+			(where - XTG_COMMAND_RAM_OFFSET) / 4 +
+			(XTG_COMMAND_RAM_MSB_OFFSET - XTG_COMMAND_RAM_OFFSET));
+
+	if (where >=  XTG_WRITE_COMMAND_RAM_OFFSET &&
+	    where < XTG_COMMAND_RAM_MSB_OFFSET)
+		data[MSB_INDEX] = readl(tg->regs +
+			XTG_WRITE_COMMAND_RAM_OFFSET +
+			(where - XTG_WRITE_COMMAND_RAM_OFFSET) / 4 +
+			(XTG_COMMAND_RAM_MSB_OFFSET - XTG_COMMAND_RAM_OFFSET) +
+			XTG_EXTCMD_RAM_BLOCK_SIZE - XTG_CMD_RAM_BLOCK_SIZE);
+#endif
+		break;
+	}
+}
+
+/**
+ * xtg_prepare_cmd_words - Prepares all four Command RAM words
+ * @tg: Pointer to xtg_dev_info structure
+ * @cmdp: Pointer to xtg_cram structure
+ * @cmd_words: Pointer to Command Words that needs to be prepared
+ */
+static void xtg_prepare_cmd_words(struct xtg_dev_info *tg,
+				  const struct xtg_cram *cmdp, u32 *cmd_words)
+{
+	/* Command Word 0 */
+	cmd_words[0] = lower_32_bits(cmdp->addr);
+
+	/* Command Word 4 */
+#ifdef CONFIG_PHYS_ADDR_T_64BIT
+	cmd_words[MSB_INDEX] = upper_32_bits(cmdp->addr);
+#endif
+
+	/* Command Word 1 */
+	cmd_words[1] = 0;
+	cmd_words[1] |= (cmdp->length & XTG_LEN_MASK) << XTG_LEN_SHIFT;
+	cmd_words[1] |= (cmdp->lock & XTG_LOCK_MASK) << XTG_LOCK_SHIFT;
+	cmd_words[1] |= (cmdp->burst & XTG_BURST_MASK) << XTG_BURST_SHIFT;
+	cmd_words[1] |= (cmdp->size & XTG_SIZE_MASK) << XTG_SIZE_SHIFT;
+	cmd_words[1] |= (cmdp->id & XTG_ID_MASK) << XTG_ID_SHIFT;
+	cmd_words[1] |= (cmdp->prot & XTG_PROT_MASK) << XTG_PROT_SHIFT;
+	cmd_words[1] |= (cmdp->last_addr & XTG_LAST_ADDR_MASK) <<
+					XTG_LAST_ADDR_SHIFT;
+	cmd_words[1] |= (cmdp->valid_cmd & XTG_VALID_CMD_MASK) <<
+					XTG_VALID_CMD_SHIFT;
+
+	/* Command Word 2 */
+	cmd_words[2] = 0;
+	cmd_words[2] |= (cmdp->mram_idx & XTG_MSTRAM_INDEX_MASK) <<
+					XTG_MSTRAM_INDEX_SHIFT;
+	cmd_words[2] |= (cmdp->other_dpnd & XTG_OTHER_DEPEND_MASK) <<
+					XTG_OTHER_DEPEND_SHIFT;
+	cmd_words[2] |= (cmdp->my_dpnd & XTG_MY_DEPEND_MASK) <<
+					XTG_MY_DEPEND_SHIFT;
+
+	/* Command Word 3 */
+	cmd_words[3] = 0;
+	cmd_words[3] |= (cmdp->qos & XTG_QOS_MASK) << XTG_QOS_SHIFT;
+	cmd_words[3] |= (cmdp->user & XTG_USER_MASK) << XTG_USER_SHIFT;
+	cmd_words[3] |= (cmdp->cache & XTG_CACHE_MASK) << XTG_CACHE_SHIFT;
+	cmd_words[3] |= (cmdp->expected_resp & XTG_EXPECTED_RESP_MASK) <<
+					XTG_EXPECTED_RESP_SHIFT;
+}
+
+/**
+ * xtg_prepare_param_words - Prepares Parameter RAM word
+ * @tg: Pointer to xtg_dev_info structure
+ * @cmdp: Pointer to xtg_pram structure
+ * @param_word: Pointer to Param Word that needs to be prepared
+ */
+static void xtg_prepare_param_word(struct xtg_dev_info *tg,
+				   const struct xtg_pram *cmdp, u32 *param_word)
+{
+	*param_word = 0;
+	*param_word |= (cmdp->opcode & XTG_PARAM_OP_MASK) << XTG_PARAM_OP_SHIFT;
+	*param_word |= (cmdp->addr_mode & XTG_PARAM_ADDRMODE_MASK) <<
+					XTG_PARAM_ADDRMODE_SHIFT;
+	*param_word |= (cmdp->id_mode & XTG_PARAM_IDMODE_MASK) <<
+					XTG_PARAM_IDMODE_SHIFT;
+	*param_word |= (cmdp->interval_mode & XTG_PARAM_INTERVALMODE_MASK) <<
+					XTG_PARAM_INTERVALMODE_SHIFT;
+
+	switch (cmdp->opcode) {
+	case XTG_PARAM_OP_RPT:
+	case XTG_PARAM_OP_DELAY:
+		*param_word |= (cmdp->op_cntl0 & XTG_PARAM_COUNT_MASK) <<
+					XTG_PARAM_COUNT_SHIFT;
+		break;
+
+	case XTG_PARAM_OP_FIXEDRPT:
+		*param_word |= (cmdp->op_cntl0 & XTG_PARAM_ADDRRANGE_MASK) <<
+					XTG_PARAM_ADDRRANGE_SHIFT;
+		*param_word |= (cmdp->op_cntl1 & XTG_PARAM_DELAY_MASK) <<
+					XTG_PARAM_DELAY_SHIFT;
+		*param_word |= (cmdp->op_cntl2 & XTG_PARAM_DELAYRANGE_MASK) <<
+					XTG_PARAM_DELAYRANGE_SHIFT;
+		break;
+
+	case XTG_PARAM_OP_NOP:
+		*param_word = 0;
+		break;
+	}
+}
+
+/**
+ * xtg_sysfs_ioctl - Implements sysfs operations
+ * @dev: Device structure
+ * @buf: Value to write
+ * @opcode: Ioctl opcode
+ *
+ * Return: value read from the sysfs opcode.
+ */
+static ssize_t xtg_sysfs_ioctl(struct device *dev, const char *buf,
+			       enum xtg_sysfs_ioctl_opcode opcode)
+{
+	struct xtg_dev_info *tg = to_xtg_dev_info(dev);
+	unsigned long wrval;
+	ssize_t status, rdval = 0;
+
+	if (opcode > XTG_GET_STREAM_TRANSFERCNT) {
+		status = kstrtoul(buf, 0, &wrval);
+		if (status < 0)
+			return status;
+	}
+
+	switch (opcode) {
+	case XTG_GET_MASTER_CMP_STS:
+		rdval = (readl(tg->regs + XTG_MCNTL_OFFSET) &
+				XTG_MCNTL_MSTEN_MASK) ? 1 : 0;
+		break;
+
+	case XTG_GET_MASTER_LOOP_EN:
+		rdval = (readl(tg->regs + XTG_MCNTL_OFFSET) &
+				XTG_MCNTL_LOOPEN_MASK) ? 1 : 0;
+		break;
+
+	case XTG_GET_SLV_CTRL_REG:
+		rdval = readl(tg->regs + XTG_SCNTL_OFFSET);
+		break;
+
+	case XTG_GET_ERR_STS:
+		rdval = readl(tg->regs + XTG_ERR_STS_OFFSET) &
+				XTG_ERR_ALL_ERRS_MASK;
+		break;
+
+	case XTG_GET_CFG_STS:
+		rdval = readl(tg->regs + XTG_CFG_STS_OFFSET);
+		break;
+
+	case XTG_GET_LAST_VALID_INDEX:
+		rdval = (((tg->last_wr_valid_idx << 16) & 0xffff0000) |
+				(tg->last_rd_valid_idx & 0xffff));
+		break;
+
+	case XTG_GET_DEVICE_ID:
+		rdval = tg->id;
+		break;
+
+	case XTG_GET_RESOURCE:
+		rdval = (unsigned long)tg->regs;
+		break;
+
+	case XTG_GET_STATIC_ENABLE:
+		rdval = readl(tg->regs + XTG_STATIC_CNTL_OFFSET);
+		break;
+
+	case XTG_GET_STATIC_BURSTLEN:
+		rdval = readl(tg->regs + XTG_STATIC_LEN_OFFSET);
+		break;
+
+	case XTG_GET_STATIC_TRANSFERDONE:
+		rdval = (readl(tg->regs + XTG_STATIC_CNTL_OFFSET) &
+				XTG_STATIC_CNTL_TD_MASK);
+		break;
+
+	case XTG_GET_STREAM_ENABLE:
+		rdval = readl(tg->regs + XTG_STREAM_CNTL_OFFSET);
+		break;
+
+	case XTG_GET_STREAM_TRANSFERLEN:
+		rdval = (readl(tg->regs + XTG_STREAM_TL_OFFSET) &
+				XTG_STREAM_TL_TLEN_MASK);
+		break;
+
+	case XTG_GET_STREAM_TRANSFERCNT:
+		rdval = ((readl(tg->regs + XTG_STREAM_TL_OFFSET) &
+				XTG_STREAM_TL_TCNT_MASK) >>
+				XTG_STREAM_TL_TCNT_SHIFT);
+		break;
+
+	case XTG_GET_STREAM_TKTS1:
+		rdval = readl(tg->regs + XTG_STREAM_TKTS1_OFFSET);
+		break;
+	case XTG_GET_STREAM_TKTS2:
+		rdval = readl(tg->regs + XTG_STREAM_TKTS2_OFFSET);
+		break;
+	case XTG_GET_STREAM_TKTS3:
+		rdval = readl(tg->regs + XTG_STREAM_TKTS3_OFFSET);
+		break;
+	case XTG_GET_STREAM_TKTS4:
+		rdval = readl(tg->regs + XTG_STREAM_TKTS4_OFFSET);
+		break;
+
+	case XTG_GET_STREAM_CFG:
+		rdval = (readl(tg->regs + XTG_STREAM_CFG_OFFSET));
+		break;
+
+	case XTG_START_MASTER_LOGIC:
+		if (wrval)
+			writel(readl(tg->regs + XTG_MCNTL_OFFSET) |
+					XTG_MCNTL_MSTEN_MASK,
+				tg->regs + XTG_MCNTL_OFFSET);
+		break;
+
+	case XTG_MASTER_LOOP_EN:
+		if (wrval)
+			writel(readl(tg->regs + XTG_MCNTL_OFFSET) |
+					XTG_MCNTL_LOOPEN_MASK,
+				tg->regs + XTG_MCNTL_OFFSET);
+		else
+			writel(readl(tg->regs + XTG_MCNTL_OFFSET) &
+					~XTG_MCNTL_LOOPEN_MASK,
+				tg->regs + XTG_MCNTL_OFFSET);
+		break;
+
+	case XTG_SET_SLV_CTRL_REG:
+		writel(wrval, tg->regs + XTG_SCNTL_OFFSET);
+		break;
+
+	case XTG_ENABLE_ERRORS:
+		wrval &= XTG_ERR_ALL_ERRS_MASK;
+		writel(wrval, tg->regs + XTG_ERR_EN_OFFSET);
+		break;
+
+	case XTG_CLEAR_ERRORS:
+		wrval &= XTG_ERR_ALL_ERRS_MASK;
+		writel(readl(tg->regs + XTG_ERR_STS_OFFSET) | wrval,
+		       tg->regs + XTG_ERR_STS_OFFSET);
+		break;
+
+	case XTG_ENABLE_INTRS:
+		if (wrval & XTG_MASTER_CMP_INTR) {
+			pr_info("Enabling Master Complete Interrupt\n");
+			writel(readl(tg->regs + XTG_ERR_EN_OFFSET) |
+					XTG_ERR_EN_MSTIRQEN_MASK,
+				tg->regs + XTG_ERR_EN_OFFSET);
+		}
+		if (wrval & XTG_MASTER_ERR_INTR) {
+			pr_info("Enabling Interrupt on Master Errors\n");
+			writel(readl(tg->regs + XTG_MSTERR_INTR_OFFSET) |
+					XTG_MSTERR_INTR_MINTREN_MASK,
+				tg->regs + XTG_MSTERR_INTR_OFFSET);
+		}
+		if (wrval & XTG_SLAVE_ERR_INTR) {
+			pr_info("Enabling Interrupt on Slave Errors\n");
+			writel(readl(tg->regs + XTG_SCNTL_OFFSET) |
+					XTG_SCNTL_ERREN_MASK,
+				tg->regs + XTG_SCNTL_OFFSET);
+		}
+		break;
+
+	case XTG_CLEAR_MRAM:
+		xtg_access_rams(tg, tg->xtg_mram_offset,
+				XTG_MASTER_RAM_SIZE,
+				XTG_WRITE_RAM_ZERO, NULL);
+		break;
+
+	case XTG_CLEAR_CRAM:
+		xtg_access_rams(tg, XTG_COMMAND_RAM_OFFSET,
+				XTG_COMMAND_RAM_SIZE,
+				XTG_WRITE_RAM_ZERO, NULL);
+		break;
+
+	case XTG_CLEAR_PRAM:
+		xtg_access_rams(tg, XTG_PARAM_RAM_OFFSET,
+				XTG_PARAM_RAM_SIZE,
+				XTG_WRITE_RAM_ZERO, NULL);
+		break;
+
+	case XTG_SET_STATIC_ENABLE:
+		if (wrval) {
+			wrval &= XTG_STATIC_CNTL_STEN_MASK;
+			writel(readl(tg->regs + XTG_STATIC_CNTL_OFFSET) | wrval,
+			       tg->regs + XTG_STATIC_CNTL_OFFSET);
+		} else {
+			writel(readl(tg->regs + XTG_STATIC_CNTL_OFFSET) &
+				~XTG_STATIC_CNTL_STEN_MASK,
+				tg->regs + XTG_STATIC_CNTL_OFFSET);
+		}
+		break;
+
+	case XTG_SET_STATIC_BURSTLEN:
+		writel(wrval, tg->regs + XTG_STATIC_LEN_OFFSET);
+		break;
+
+	case XTG_SET_STATIC_TRANSFERDONE:
+		wrval |= XTG_STATIC_CNTL_TD_MASK;
+		writel(readl(tg->regs + XTG_STATIC_CNTL_OFFSET) | wrval,
+		       tg->regs + XTG_STATIC_CNTL_OFFSET);
+		break;
+
+	case XTG_SET_STREAM_ENABLE:
+		if (wrval) {
+			rdval = readl(tg->regs + XTG_STREAM_CNTL_OFFSET);
+			rdval |= XTG_STREAM_CNTL_STEN_MASK,
+			writel(rdval,
+			       tg->regs + XTG_STREAM_CNTL_OFFSET);
+		} else {
+			writel(readl(tg->regs + XTG_STREAM_CNTL_OFFSET) &
+			       ~XTG_STREAM_CNTL_STEN_MASK,
+			       tg->regs + XTG_STREAM_CNTL_OFFSET);
+		}
+		break;
+
+	case XTG_SET_STREAM_TRANSFERLEN:
+		wrval &= XTG_STREAM_TL_TLEN_MASK;
+		rdval = readl(tg->regs + XTG_STREAM_TL_OFFSET);
+		rdval &= ~XTG_STREAM_TL_TLEN_MASK;
+		writel(rdval | wrval,
+		       tg->regs + XTG_STREAM_TL_OFFSET);
+		break;
+
+	case XTG_SET_STREAM_TRANSFERCNT:
+		wrval = ((wrval << XTG_STREAM_TL_TCNT_SHIFT) &
+				XTG_STREAM_TL_TCNT_MASK);
+		rdval = readl(tg->regs + XTG_STREAM_TL_OFFSET);
+		rdval = rdval & ~XTG_STREAM_TL_TCNT_MASK;
+		writel(rdval | wrval,
+		       tg->regs + XTG_STREAM_TL_OFFSET);
+		break;
+
+	case XTG_SET_STREAM_TKTS1:
+		writel(wrval, tg->regs + XTG_STREAM_TKTS1_OFFSET);
+		break;
+	case XTG_SET_STREAM_TKTS2:
+		writel(wrval, tg->regs + XTG_STREAM_TKTS2_OFFSET);
+		break;
+	case XTG_SET_STREAM_TKTS3:
+		writel(wrval, tg->regs + XTG_STREAM_TKTS3_OFFSET);
+		break;
+	case XTG_SET_STREAM_TKTS4:
+		writel(wrval, tg->regs + XTG_STREAM_TKTS4_OFFSET);
+		break;
+
+	case XTG_SET_STREAM_CFG:
+		writel(wrval, tg->regs + XTG_STREAM_CFG_OFFSET);
+		break;
+
+	default:
+		break;
+	}
+
+	return rdval;
+}
+
+/* Sysfs functions */
+
+static ssize_t id_show(struct device *dev,
+		       struct device_attribute *attr, char *buf)
+{
+	ssize_t rdval = xtg_sysfs_ioctl(dev, buf, XTG_GET_DEVICE_ID);
+
+	return snprintf(buf, PAGE_SIZE, "%zd\n", rdval);
+}
+static DEVICE_ATTR_RO(id);
+
+static ssize_t resource_show(struct device *dev,
+			     struct device_attribute *attr, char *buf)
+{
+	ssize_t rdval = xtg_sysfs_ioctl(dev, buf, XTG_GET_RESOURCE);
+
+	return snprintf(buf, PAGE_SIZE, "0x%08zx\n", rdval);
+}
+static DEVICE_ATTR_RO(resource);
+
+static ssize_t master_start_stop_show(struct device *dev,
+				      struct device_attribute *attr, char *buf)
+{
+	ssize_t rdval = xtg_sysfs_ioctl(dev, buf, XTG_GET_MASTER_CMP_STS);
+
+	return snprintf(buf, PAGE_SIZE, "%zd\n", rdval);
+}
+
+static ssize_t master_start_stop_store(struct device *dev,
+				       struct device_attribute *attr,
+				       const char *buf, size_t size)
+{
+	xtg_sysfs_ioctl(dev, buf, XTG_START_MASTER_LOGIC);
+
+	return size;
+}
+static DEVICE_ATTR_RW(master_start_stop);
+
+static ssize_t config_slave_status_show(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	ssize_t rdval = xtg_sysfs_ioctl(dev, buf, XTG_GET_SLV_CTRL_REG);
+
+	return snprintf(buf, PAGE_SIZE, "0x%08zx\n", rdval);
+}
+
+static ssize_t config_slave_status_store(struct device *dev,
+					 struct device_attribute *attr,
+					 const char *buf, size_t size)
+{
+	xtg_sysfs_ioctl(dev, buf, XTG_SET_SLV_CTRL_REG);
+
+	return size;
+}
+static DEVICE_ATTR_RW(config_slave_status);
+
+static ssize_t err_sts_show(struct device *dev,
+			    struct device_attribute *attr, char *buf)
+{
+	ssize_t rdval = xtg_sysfs_ioctl(dev, buf, XTG_GET_ERR_STS);
+
+	return snprintf(buf, PAGE_SIZE, "0x%08zx\n", rdval);
+}
+
+static ssize_t err_sts_store(struct device *dev,
+			     struct device_attribute *attr,
+			     const char *buf, size_t size)
+{
+	xtg_sysfs_ioctl(dev, buf, XTG_CLEAR_ERRORS);
+
+	return size;
+}
+static DEVICE_ATTR_RW(err_sts);
+
+static ssize_t err_en_store(struct device *dev,
+			    struct device_attribute *attr, const char *buf,
+			    size_t size)
+{
+	xtg_sysfs_ioctl(dev, buf, XTG_ENABLE_ERRORS);
+
+	return size;
+}
+static DEVICE_ATTR_WO(err_en);
+
+static ssize_t intr_en_store(struct device *dev,
+			     struct device_attribute *attr,
+			     const char *buf, size_t size)
+{
+	xtg_sysfs_ioctl(dev, buf, XTG_ENABLE_INTRS);
+
+	return size;
+}
+static DEVICE_ATTR_WO(intr_en);
+
+static ssize_t last_valid_index_show(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	ssize_t rdval = xtg_sysfs_ioctl(dev, buf, XTG_GET_LAST_VALID_INDEX);
+
+	return snprintf(buf, PAGE_SIZE, "0x%08zx\n", rdval);
+}
+static DEVICE_ATTR_RO(last_valid_index);
+
+static ssize_t config_sts_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	ssize_t rdval = xtg_sysfs_ioctl(dev, buf, XTG_GET_CFG_STS);
+
+	return snprintf(buf, PAGE_SIZE, "0x%08zx\n", rdval);
+}
+static DEVICE_ATTR_RO(config_sts);
+
+static ssize_t mram_clear_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t size)
+{
+	xtg_sysfs_ioctl(dev, buf, XTG_CLEAR_MRAM);
+
+	return size;
+}
+static DEVICE_ATTR_WO(mram_clear);
+
+static ssize_t cram_clear_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t size)
+{
+	xtg_sysfs_ioctl(dev, buf, XTG_CLEAR_CRAM);
+
+	return size;
+}
+static DEVICE_ATTR_WO(cram_clear);
+
+static ssize_t pram_clear_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t size)
+{
+	xtg_sysfs_ioctl(dev, buf, XTG_CLEAR_CRAM);
+
+	return size;
+}
+static DEVICE_ATTR_WO(pram_clear);
+
+static ssize_t static_enable_show(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	ssize_t rdval = xtg_sysfs_ioctl(dev, buf, XTG_GET_STATIC_ENABLE);
+
+	return snprintf(buf, PAGE_SIZE, "0x%08zx\n", rdval);
+}
+
+static ssize_t static_enable_store(struct device *dev,
+				   struct device_attribute *attr,
+				   const char *buf, size_t size)
+{
+	xtg_sysfs_ioctl(dev, buf, XTG_SET_STATIC_ENABLE);
+
+	return size;
+}
+static DEVICE_ATTR_RW(static_enable);
+
+static ssize_t static_burstlen_show(struct device *dev,
+				    struct device_attribute *attr, char *buf)
+{
+	ssize_t rdval = xtg_sysfs_ioctl(dev, buf, XTG_GET_STATIC_BURSTLEN);
+
+	return snprintf(buf, PAGE_SIZE, "%zd\n", rdval);
+}
+
+static ssize_t static_burstlen_store(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t size)
+{
+	xtg_sysfs_ioctl(dev, buf, XTG_SET_STATIC_BURSTLEN);
+
+	return size;
+}
+static DEVICE_ATTR_RW(static_burstlen);
+
+static ssize_t stream_cfg_show(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	ssize_t rdval = xtg_sysfs_ioctl(dev, buf, XTG_GET_STREAM_CFG);
+
+	return snprintf(buf, PAGE_SIZE, "%zd\n", rdval);
+}
+
+static ssize_t stream_cfg_store(struct device *dev,
+				struct device_attribute *attr, const char *buf,
+				size_t size)
+{
+	xtg_sysfs_ioctl(dev, buf, XTG_SET_STREAM_CFG);
+
+	return size;
+}
+static DEVICE_ATTR_RW(stream_cfg);
+
+static ssize_t stream_tkts4_show(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	ssize_t rdval = xtg_sysfs_ioctl(dev, buf, XTG_GET_STREAM_TKTS4);
+
+	return snprintf(buf, PAGE_SIZE, "%zd\n", rdval);
+}
+
+static ssize_t stream_tkts4_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t size)
+{
+	xtg_sysfs_ioctl(dev, buf, XTG_SET_STREAM_TKTS4);
+
+	return size;
+}
+static DEVICE_ATTR_RW(stream_tkts4);
+
+static ssize_t stream_tkts3_show(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	ssize_t rdval = xtg_sysfs_ioctl(dev, buf, XTG_GET_STREAM_TKTS3);
+
+	return snprintf(buf, PAGE_SIZE, "%zd\n", rdval);
+}
+
+static ssize_t stream_tkts3_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t size)
+{
+	xtg_sysfs_ioctl(dev, buf, XTG_SET_STREAM_TKTS3);
+
+	return size;
+}
+static DEVICE_ATTR_RW(stream_tkts3);
+
+static ssize_t stream_tkts2_show(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	ssize_t rdval = xtg_sysfs_ioctl(dev, buf, XTG_GET_STREAM_TKTS2);
+
+	return snprintf(buf, PAGE_SIZE, "%zd\n", rdval);
+}
+
+static ssize_t stream_tkts2_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t size)
+{
+	xtg_sysfs_ioctl(dev, buf, XTG_SET_STREAM_TKTS2);
+
+	return size;
+}
+static DEVICE_ATTR_RW(stream_tkts2);
+
+static ssize_t stream_tkts1_show(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	ssize_t rdval = xtg_sysfs_ioctl(dev, buf, XTG_GET_STREAM_TKTS1);
+
+	return snprintf(buf, PAGE_SIZE, "%zd\n", rdval);
+}
+
+static ssize_t stream_tkts1_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t size)
+{
+	xtg_sysfs_ioctl(dev, buf, XTG_SET_STREAM_TKTS1);
+
+	return size;
+}
+static DEVICE_ATTR_RW(stream_tkts1);
+
+static ssize_t static_transferdone_show(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	ssize_t rdval = xtg_sysfs_ioctl(dev, buf, XTG_GET_STATIC_TRANSFERDONE);
+
+	return snprintf(buf, PAGE_SIZE, "%zd\n", rdval);
+}
+
+static ssize_t static_transferdone_store(struct device *dev,
+					 struct device_attribute *attr,
+					 const char *buf, size_t size)
+{
+	xtg_sysfs_ioctl(dev, buf, XTG_SET_STATIC_TRANSFERDONE);
+
+	return size;
+}
+static DEVICE_ATTR_RW(static_transferdone);
+
+static ssize_t reset_static_transferdone_show(struct device *dev,
+					      struct device_attribute *attr,
+					      char *buf)
+{
+	ssize_t rdval = xtg_sysfs_ioctl(dev, buf, XTG_GET_STATIC_TRANSFERDONE);
+
+	if (rdval == XTG_STATIC_CNTL_RESET_MASK)
+		rdval = 1;
+	else
+		rdval = 0;
+	return snprintf(buf, PAGE_SIZE, "%zd\n", rdval);
+}
+static DEVICE_ATTR_RO(reset_static_transferdone);
+
+static ssize_t stream_enable_show(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	ssize_t rdval = xtg_sysfs_ioctl(dev, buf, XTG_GET_STREAM_ENABLE);
+
+	return snprintf(buf, PAGE_SIZE, "0x%08zx\n", rdval);
+}
+
+static ssize_t stream_enable_store(struct device *dev,
+				   struct device_attribute *attr,
+				   const char *buf, size_t size)
+{
+	xtg_sysfs_ioctl(dev, buf, XTG_SET_STREAM_ENABLE);
+
+	return size;
+}
+static DEVICE_ATTR_RW(stream_enable);
+
+static ssize_t stream_transferlen_show(struct device *dev,
+				       struct device_attribute *attr,
+				       char *buf)
+{
+	ssize_t rdval = xtg_sysfs_ioctl(dev, buf, XTG_GET_STREAM_TRANSFERLEN);
+
+	return snprintf(buf, PAGE_SIZE, "%zd\n", rdval);
+}
+
+static ssize_t stream_transferlen_store(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t size)
+{
+	xtg_sysfs_ioctl(dev, buf, XTG_SET_STREAM_TRANSFERLEN);
+
+	return size;
+}
+static DEVICE_ATTR_RW(stream_transferlen);
+
+static ssize_t stream_transfercnt_show(struct device *dev,
+				       struct device_attribute *attr,
+				       char *buf)
+{
+	ssize_t rdval = xtg_sysfs_ioctl(dev, buf, XTG_GET_STREAM_TRANSFERCNT);
+
+	return snprintf(buf, PAGE_SIZE, "%zd\n", rdval);
+}
+
+static ssize_t stream_transfercnt_store(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t size)
+{
+	xtg_sysfs_ioctl(dev, buf, XTG_SET_STREAM_TRANSFERCNT);
+
+	return size;
+}
+static DEVICE_ATTR_RW(stream_transfercnt);
+
+static ssize_t loop_enable_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	ssize_t rdval = xtg_sysfs_ioctl(dev, buf, XTG_GET_MASTER_LOOP_EN);
+
+	return snprintf(buf, PAGE_SIZE, "%zd\n", rdval);
+}
+
+static ssize_t loop_enable_store(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t size)
+{
+	xtg_sysfs_ioctl(dev, buf, XTG_MASTER_LOOP_EN);
+
+	return size;
+}
+static DEVICE_ATTR_RW(loop_enable);
+
+static ssize_t xtg_pram_read(struct file *filp, struct kobject *kobj,
+			     struct bin_attribute *bin_attr,
+			     char *buf, loff_t off, size_t count)
+{
+	pr_info("No read access to Parameter RAM\n");
+
+	return 0;
+}
+
+static ssize_t xtg_pram_write(struct file *filp, struct kobject *kobj,
+			      struct bin_attribute *bin_attr,
+			      char *buf, loff_t off, size_t count)
+{
+	struct xtg_dev_info *tg =
+		to_xtg_dev_info(container_of(kobj, struct device, kobj));
+	u32 *data = (u32 *)buf;
+	struct xtg_pram *cmdp = (struct xtg_pram *)buf;
+	u32 param_word;
+
+	if (off >= XTG_PARAM_RAM_SIZE) {
+		pr_err("Requested Write len exceeds 2K PRAM size\n");
+		return -ENOMEM;
+	}
+
+	if (count >= XTG_PARAM_RAM_SIZE)
+		count = XTG_PARAM_RAM_SIZE;
+
+	/* Program each command */
+	if (count == sizeof(struct xtg_pram)) {
+
+		if (!cmdp)
+			return -EINVAL;
+
+		if (cmdp->is_valid_req == VALID_SIG) {
+			/* Prepare parameter word */
+			xtg_prepare_param_word(tg, cmdp, &param_word);
+
+			count = XTG_PRAM_BYTES_PER_ENTRY;
+			data = &param_word;
+
+			/* Maximum command entries are 256 */
+			if (cmdp->index > MAX_NUM_ENTRIES)
+				return -EINVAL;
+
+			/* Calculate the block index */
+			if (cmdp->is_write_block)
+				off = XTG_PRM_RAM_BLOCK_SIZE +
+						cmdp->index * count;
+			else
+				off = cmdp->index * count;
+		}
+	}
+
+	off += XTG_PARAM_RAM_OFFSET;
+	xtg_access_rams(tg, off, count, XTG_WRITE_RAM, data);
+
+	return count;
+}
+
+static int xtg_pram_mmap(struct file *filp, struct kobject *kobj,
+			 struct bin_attribute *attr,
+			 struct vm_area_struct *vma)
+{
+	struct xtg_dev_info *tg =
+		to_xtg_dev_info(container_of(kobj, struct device, kobj));
+	int ret;
+
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+	vma->vm_flags |= VM_IO;
+
+	ret = remap_pfn_range(vma, vma->vm_start, (tg->phys_base_addr +
+			XTG_PARAM_RAM_OFFSET) >> PAGE_SHIFT,
+			XTG_PARAM_RAM_SIZE, vma->vm_page_prot);
+	return ret;
+}
+
+static struct bin_attribute xtg_pram_attr = {
+	.attr =	{
+		.name = "parameter_ram",
+		.mode = 0644,
+	},
+	.size = XTG_PARAM_RAM_SIZE,
+	.read = xtg_pram_read,
+	.write = xtg_pram_write,
+	.mmap = xtg_pram_mmap,
+};
+
+static ssize_t xtg_cram_read(struct file *filp, struct kobject *kobj,
+			     struct bin_attribute *bin_attr,
+			     char *buf, loff_t off, size_t count)
+{
+	struct xtg_dev_info *tg =
+		to_xtg_dev_info(container_of(kobj, struct device, kobj));
+
+	off += XTG_COMMAND_RAM_OFFSET;
+	xtg_access_rams(tg, off, count, XTG_READ_RAM, (u32 *)buf);
+
+	return count;
+}
+
+static ssize_t xtg_cram_write(struct file *filp, struct kobject *kobj,
+			      struct bin_attribute *bin_attr,
+			      char *buf, loff_t off, size_t count)
+{
+	struct xtg_dev_info *tg =
+		to_xtg_dev_info(container_of(kobj, struct device, kobj));
+	u32 *data = (u32 *)buf;
+	struct xtg_cram *cmdp = (struct xtg_cram *)buf;
+	u32 cmd_words[CMD_WDS + EXT_WDS];
+
+	if (off >= XTG_COMMAND_RAM_SIZE) {
+		pr_err("Requested Write len exceeds 8K CRAM size\n");
+		return -ENOMEM;
+	}
+
+	/* Program each command */
+	if (count == sizeof(struct xtg_cram)) {
+
+		if (!cmdp)
+			return -EINVAL;
+
+		if (cmdp->is_valid_req == VALID_SIG) {
+			/* Prepare command words */
+			xtg_prepare_cmd_words(tg, cmdp, cmd_words);
+			count = XTG_CRAM_BYTES_PER_ENTRY;
+			data = cmd_words;
+
+			/* Maximum command entries are 256 */
+			if (cmdp->index > MAX_NUM_ENTRIES)
+				return -EINVAL;
+
+			/* Calculate the block index */
+			if (cmdp->is_write_block)
+				off = XTG_CMD_RAM_BLOCK_SIZE +
+						cmdp->index * count;
+			else
+				off = cmdp->index * count;
+
+			/* Store the valid command index */
+			if (cmdp->valid_cmd) {
+				if (cmdp->is_write_block)
+					tg->last_wr_valid_idx =
+							cmdp->index;
+				else
+					tg->last_rd_valid_idx =
+							cmdp->index;
+			}
+		}
+	}
+
+	off += XTG_COMMAND_RAM_OFFSET;
+	xtg_access_rams(tg, off, count, XTG_WRITE_RAM, data);
+
+	return count;
+}
+
+static int xtg_cram_mmap(struct file *filp, struct kobject *kobj,
+			 struct bin_attribute *attr,
+			 struct vm_area_struct *vma)
+{
+	struct xtg_dev_info *tg =
+		to_xtg_dev_info(container_of(kobj, struct device, kobj));
+	int ret;
+
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+	vma->vm_flags |= VM_IO;
+
+	ret = remap_pfn_range(vma, vma->vm_start, (tg->phys_base_addr +
+			XTG_COMMAND_RAM_OFFSET) >> PAGE_SHIFT,
+			XTG_COMMAND_RAM_SIZE + XTG_EXTCMD_RAM_SIZE,
+			vma->vm_page_prot);
+	return ret;
+}
+
+static struct bin_attribute xtg_cram_attr = {
+	.attr =	{
+		.name = "command_ram",
+		.mode = 0644,
+	},
+	.size = XTG_COMMAND_RAM_SIZE,
+	.read = xtg_cram_read,
+	.write = xtg_cram_write,
+	.mmap = xtg_cram_mmap,
+};
+
+static ssize_t xtg_mram_read(struct file *filp, struct kobject *kobj,
+			     struct bin_attribute *bin_attr,
+			     char *buf, loff_t off, size_t count)
+{
+	struct xtg_dev_info *tg =
+		to_xtg_dev_info(container_of(kobj, struct device, kobj));
+
+	off += tg->xtg_mram_offset;
+	xtg_access_rams(tg, off, count, XTG_READ_RAM, (u32 *)buf);
+
+	return count;
+}
+
+static ssize_t xtg_mram_write(struct file *filp, struct kobject *kobj,
+			      struct bin_attribute *bin_attr,
+			      char *buf, loff_t off, size_t count)
+{
+	struct xtg_dev_info *tg =
+		to_xtg_dev_info(container_of(kobj, struct device, kobj));
+
+	if (off >= XTG_MASTER_RAM_SIZE) {
+		pr_err("Requested Write len exceeds 8K MRAM size\n");
+		return -ENOMEM;
+	}
+
+	off += tg->xtg_mram_offset;
+	xtg_access_rams(tg, off, count, XTG_WRITE_RAM, (u32 *)buf);
+
+	return count;
+}
+
+static int xtg_mram_mmap(struct file *filp, struct kobject *kobj,
+			 struct bin_attribute *attr,
+			 struct vm_area_struct *vma)
+{
+	struct xtg_dev_info *tg =
+		to_xtg_dev_info(container_of(kobj, struct device, kobj));
+	int ret;
+
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+	vma->vm_flags |= VM_IO;
+
+	ret = remap_pfn_range(vma, vma->vm_start, (tg->phys_base_addr +
+			tg->xtg_mram_offset) >> PAGE_SHIFT,
+			XTG_MASTER_RAM_SIZE,
+			vma->vm_page_prot);
+	return ret;
+}
+
+static struct bin_attribute xtg_mram_attr = {
+	.attr =	{
+		.name = "master_ram",
+		.mode = 0644,
+	},
+	.size = XTG_MASTER_RAM_SIZE,
+	.read = xtg_mram_read,
+	.write = xtg_mram_write,
+	.mmap = xtg_mram_mmap,
+};
+
+static struct bin_attribute *xtg_bin_attrs[] = {
+	&xtg_mram_attr,
+	&xtg_pram_attr,
+	&xtg_cram_attr,
+	NULL,
+};
+
+static const struct attribute *xtg_attrs[] = {
+	&dev_attr_id.attr,
+	&dev_attr_resource.attr,
+	&dev_attr_master_start_stop.attr,
+	&dev_attr_config_slave_status.attr,
+	&dev_attr_err_en.attr,
+	&dev_attr_err_sts.attr,
+	&dev_attr_intr_en.attr,
+	&dev_attr_last_valid_index.attr,
+	&dev_attr_config_sts.attr,
+	&dev_attr_mram_clear.attr,
+	&dev_attr_cram_clear.attr,
+	&dev_attr_pram_clear.attr,
+	&dev_attr_static_enable.attr,
+	&dev_attr_static_burstlen.attr,
+	&dev_attr_static_transferdone.attr,
+	&dev_attr_stream_transfercnt.attr,
+	&dev_attr_stream_transferlen.attr,
+	&dev_attr_stream_tkts1.attr,
+	&dev_attr_stream_tkts2.attr,
+	&dev_attr_stream_tkts3.attr,
+	&dev_attr_stream_tkts4.attr,
+	&dev_attr_stream_cfg.attr,
+	&dev_attr_stream_enable.attr,
+	&dev_attr_reset_static_transferdone.attr,
+	&dev_attr_loop_enable.attr,
+	NULL,
+};
+
+static const struct attribute_group xtg_attributes = {
+	.attrs = (struct attribute **)xtg_attrs,
+	.bin_attrs = xtg_bin_attrs,
+};
+
+/**
+ * xtg_cmp_intr_handler - Master Complete Interrupt handler
+ * @irq: IRQ number
+ * @data: Pointer to the xtg_dev_info structure
+ *
+ * Return: IRQ_HANDLED always
+ */
+static irqreturn_t xtg_cmp_intr_handler(int irq, void *data)
+{
+	struct xtg_dev_info *tg = (struct xtg_dev_info *)data;
+
+	writel(readl(tg->regs + XTG_ERR_STS_OFFSET) |
+	       XTG_ERR_STS_MSTDONE_MASK, tg->regs + XTG_ERR_STS_OFFSET);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * xtg_err_intr_handler - Master/Slave Error Interrupt handler
+ * @irq: IRQ number
+ * @data: Pointer to the xtg_dev_info structure
+ *
+ * Return: IRQ_HANDLED always
+ */
+static irqreturn_t xtg_err_intr_handler(int irq, void *data)
+{
+	struct xtg_dev_info *tg = (struct xtg_dev_info *)data;
+	u32 value;
+
+	value = readl(tg->regs + XTG_ERR_STS_OFFSET) &
+		      XTG_ERR_ALL_ERRS_MASK;
+
+	if (value) {
+		dev_err(tg->dev, "Found errors 0x%08x\n", value);
+		writel(readl(tg->regs + XTG_ERR_STS_OFFSET) | value,
+		       tg->regs + XTG_ERR_STS_OFFSET);
+	}
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * xtg_probe - Driver probe function
+ * @pdev: Pointer to the platform_device structure
+ *
+ * This is the driver probe routine. It does all the memory
+ * allocation and creates sysfs entries for the device.
+ *
+ * Return: 0 on success and failure value on error
+ */
+static int xtg_probe(struct platform_device *pdev)
+{
+	struct xtg_dev_info *tg;
+	struct device_node *node;
+	struct resource *res;
+	struct device *dev;
+	int err, irq, var;
+
+	tg = devm_kzalloc(&pdev->dev, sizeof(*tg), GFP_KERNEL);
+	if (!tg)
+		return -ENOMEM;
+
+	tg->dev = &pdev->dev;
+	dev = tg->dev;
+	node = pdev->dev.of_node;
+
+	/* Map the registers */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	tg->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(tg->regs))
+		return PTR_ERR(tg->regs);
+
+	/* Save physical base address */
+	tg->phys_base_addr = res->start;
+
+	/* Get the device instance id */
+	err = of_property_read_u32(node, "xlnx,device-id", &tg->id);
+	if (err < 0) {
+		dev_err(&pdev->dev, "unable to read property");
+		return err;
+	}
+
+	/* Map the error interrupt, if it exists in the device tree. */
+	irq = platform_get_irq_byname(pdev, "err-out");
+	if (irq < 0) {
+		dev_dbg(&pdev->dev, "unable to get err irq");
+	} else {
+		err = devm_request_irq(&pdev->dev, irq, xtg_err_intr_handler,
+				       0, dev_name(&pdev->dev), tg);
+		if (err < 0) {
+			dev_err(&pdev->dev, "unable to request irq %d", irq);
+			return err;
+		}
+	}
+
+	/* Map the completion interrupt, if it exists in the device tree. */
+	irq = platform_get_irq_byname(pdev, "irq-out");
+	if (irq < 0) {
+		dev_dbg(&pdev->dev, "unable to get cmp irq");
+	} else {
+		err = devm_request_irq(&pdev->dev, irq, xtg_cmp_intr_handler,
+				       0, dev_name(&pdev->dev), tg);
+		if (err < 0) {
+			dev_err(&pdev->dev, "unable to request irq %d", irq);
+			return err;
+		}
+	}
+
+	tg->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(tg->clk)) {
+		if (PTR_ERR(tg->clk) != -ENOENT) {
+			if (PTR_ERR(tg->clk) != -EPROBE_DEFER)
+				dev_err(&pdev->dev, "input clock not found\n");
+			return PTR_ERR(tg->clk);
+		}
+		tg->clk = NULL;
+	}
+
+	err = clk_prepare_enable(tg->clk);
+	if (err) {
+		dev_err(&pdev->dev, "Unable to enable clock.\n");
+		return err;
+	}
+
+	/*
+	 * Create sysfs file entries for the device
+	 */
+	err = sysfs_create_group(&dev->kobj, &xtg_attributes);
+	if (err < 0) {
+		dev_err(tg->dev, "unable to create sysfs entries\n");
+		clk_disable_unprepare(tg->clk);
+		return err;
+	}
+
+	/*
+	 * Initialize the write and read valid index values.
+	 * Possible range of values for these variables is <0 255>.
+	 */
+	tg->last_wr_valid_idx = -1;
+	tg->last_rd_valid_idx = -1;
+
+	dev_set_drvdata(&pdev->dev, tg);
+
+	/* Update the Proper MasterRam offset */
+	tg->xtg_mram_offset = XTG_MASTER_RAM_OFFSET;
+	var = readl(tg->regs + XTG_MCNTL_OFFSET) >> XTG_MCNTL_REV_SHIFT;
+	if (var == XTG_INIT_VERSION)
+		tg->xtg_mram_offset = XTG_MASTER_RAM_INIT_OFFSET;
+
+	dev_info(&pdev->dev, "Probing xilinx traffic generator success\n");
+
+	return 0;
+}
+
+/**
+ * xtg_remove - Driver remove function
+ * @pdev: Pointer to the platform_device structure
+ *
+ * This function frees all the resources allocated to the device.
+ *
+ * Return: 0 always
+ */
+static int xtg_remove(struct platform_device *pdev)
+{
+	struct xtg_dev_info *tg;
+	struct device *dev;
+
+	tg = dev_get_drvdata(&pdev->dev);
+	dev = tg->dev;
+	sysfs_remove_group(&dev->kobj, &xtg_attributes);
+	clk_disable_unprepare(tg->clk);
+
+	return 0;
+}
+
+static const struct of_device_id xtg_of_match[] = {
+	{ .compatible = "xlnx,axi-traffic-gen", },
+	{ /* end of table */ }
+};
+MODULE_DEVICE_TABLE(of, xtg_of_match);
+
+static struct platform_driver xtg_driver = {
+	.driver = {
+		.name = "xilinx-trafgen",
+		.of_match_table = xtg_of_match,
+	},
+	.probe = xtg_probe,
+	.remove = xtg_remove,
+};
+
+module_platform_driver(xtg_driver);
+
+MODULE_AUTHOR("Xilinx Inc.");
+MODULE_DESCRIPTION("Xilinx Traffic Generator driver");
+MODULE_LICENSE("GPL");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/core/block.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/core/block.c
@@ -249,6 +249,7 @@
 		goto out_put;
 	}
 	req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_BOOT_WP;
+	req_to_mmc_queue_req(req)->drv_op_result = -EIO;
 	blk_execute_rq(mq->queue, NULL, req, 0);
 	ret = req_to_mmc_queue_req(req)->drv_op_result;
 	blk_put_request(req);
@@ -344,6 +345,10 @@
 	struct mmc_ioc_cmd ic;
 	unsigned char *buf;
 	u64 buf_bytes;
+	unsigned int flags;
+#define MMC_BLK_IOC_DROP	BIT(0)	/* drop this mrq */
+#define MMC_BLK_IOC_SBC	BIT(1)	/* use mrq.sbc */
+
 	struct mmc_rpmb_data *rpmb;
 };
 
@@ -353,7 +358,7 @@
 	struct mmc_blk_ioc_data *idata;
 	int err;
 
-	idata = kmalloc(sizeof(*idata), GFP_KERNEL);
+	idata = kzalloc(sizeof(*idata), GFP_KERNEL);
 	if (!idata) {
 		err = -ENOMEM;
 		goto out;
@@ -408,38 +413,6 @@
 	return 0;
 }
 
-static int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status,
-				       u32 retries_max)
-{
-	int err;
-	u32 retry_count = 0;
-
-	if (!status || !retries_max)
-		return -EINVAL;
-
-	do {
-		err = __mmc_send_status(card, status, 5);
-		if (err)
-			break;
-
-		if (!R1_STATUS(*status) &&
-				(R1_CURRENT_STATE(*status) != R1_STATE_PRG))
-			break; /* RPMB programming operation complete */
-
-		/*
-		 * Rechedule to give the MMC device a chance to continue
-		 * processing the previous command without being polled too
-		 * frequently.
-		 */
-		usleep_range(1000, 5000);
-	} while (++retry_count < retries_max);
-
-	if (retry_count == retries_max)
-		err = -EPERM;
-
-	return err;
-}
-
 static int ioctl_do_sanitize(struct mmc_card *card)
 {
 	int err;
@@ -468,8 +441,60 @@
 	return err;
 }
 
+static inline bool mmc_blk_in_tran_state(u32 status)
+{
+	/*
+	 * Some cards mishandle the status bits, so make sure to check both the
+	 * busy indication and the card state.
+	 */
+	return status & R1_READY_FOR_DATA &&
+	       (R1_CURRENT_STATE(status) == R1_STATE_TRAN);
+}
+
+static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms,
+			    u32 *resp_errs)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
+	int err = 0;
+	u32 status;
+
+	do {
+		bool done = time_after(jiffies, timeout);
+
+		err = __mmc_send_status(card, &status, 5);
+		if (err) {
+			dev_err(mmc_dev(card->host),
+				"error %d requesting status\n", err);
+			return err;
+		}
+
+		/* Accumulate any response error bits seen */
+		if (resp_errs)
+			*resp_errs |= status;
+
+		/*
+		 * Timeout if the device never becomes ready for data and never
+		 * leaves the program state.
+		 */
+		if (done) {
+			dev_err(mmc_dev(card->host),
+				"Card stuck in wrong state! %s status: %#x\n",
+				 __func__, status);
+			return -ETIMEDOUT;
+		}
+
+		/*
+		 * Some cards mishandle the status bits,
+		 * so make sure to check both the busy
+		 * indication and the card state.
+		 */
+	} while (!mmc_blk_in_tran_state(status));
+
+	return err;
+}
+
 static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
-			       struct mmc_blk_ioc_data *idata)
+			       struct mmc_blk_ioc_data **idatas, int i)
 {
 	struct mmc_command cmd = {}, sbc = {};
 	struct mmc_data data = {};
@@ -477,11 +502,18 @@
 	struct scatterlist sg;
 	int err;
 	unsigned int target_part;
-	u32 status = 0;
+	struct mmc_blk_ioc_data *idata = idatas[i];
+	struct mmc_blk_ioc_data *prev_idata = NULL;
 
 	if (!card || !md || !idata)
 		return -EINVAL;
 
+	if (idata->flags & MMC_BLK_IOC_DROP)
+		return 0;
+
+	if (idata->flags & MMC_BLK_IOC_SBC && i > 0)
+		prev_idata = idatas[i - 1];
+
 	/*
 	 * The RPMB accesses comes in from the character device, so we
 	 * need to target these explicitly. Else we just target the
@@ -548,7 +580,7 @@
 			return err;
 	}
 
-	if (idata->rpmb) {
+	if (idata->rpmb || prev_idata) {
 		sbc.opcode = MMC_SET_BLOCK_COUNT;
 		/*
 		 * We don't do any blockcount validation because the max size
@@ -556,6 +588,8 @@
 		 * 'Reliable Write' bit here.
 		 */
 		sbc.arg = data.blocks | (idata->ic.write_flag & BIT(31));
+		if (prev_idata)
+			sbc.arg = prev_idata->ic.arg;
 		sbc.flags = MMC_RSP_R1 | MMC_CMD_AC;
 		mrq.sbc = &sbc;
 	}
@@ -572,6 +606,16 @@
 	}
 
 	mmc_wait_for_req(card->host, &mrq);
+	memcpy(&idata->ic.response, cmd.resp, sizeof(cmd.resp));
+
+	if (prev_idata) {
+		memcpy(&prev_idata->ic.response, sbc.resp, sizeof(sbc.resp));
+		if (sbc.error) {
+			dev_err(mmc_dev(card->host), "%s: sbc error %d\n",
+							__func__, sbc.error);
+			return sbc.error;
+		}
+	}
 
 	if (cmd.error) {
 		dev_err(mmc_dev(card->host), "%s: cmd error %d\n",
@@ -603,24 +647,30 @@
 	}
 
 	/*
+	 * Make sure to update CACHE_CTRL in case it was changed. The cache
+	 * will get turned back on if the card is re-initialized, e.g.
+	 * suspend/resume or hw reset in recovery.
+	 */
+	if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_CACHE_CTRL) &&
+	    (cmd.opcode == MMC_SWITCH)) {
+		u8 value = MMC_EXTRACT_VALUE_FROM_ARG(cmd.arg) & 1;
+
+		card->ext_csd.cache_ctrl = value;
+	}
+
+	/*
 	 * According to the SD specs, some commands require a delay after
 	 * issuing the command.
 	 */
 	if (idata->ic.postsleep_min_us)
 		usleep_range(idata->ic.postsleep_min_us, idata->ic.postsleep_max_us);
 
-	memcpy(&(idata->ic.response), cmd.resp, sizeof(cmd.resp));
-
-	if (idata->rpmb) {
+	if (idata->rpmb || (cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B) {
 		/*
-		 * Ensure RPMB command has completed by polling CMD13
+		 * Ensure RPMB/R1B command has completed by polling CMD13
 		 * "Send Status".
 		 */
-		err = ioctl_rpmb_card_status_poll(card, &status, 5);
-		if (err)
-			dev_err(mmc_dev(card->host),
-					"%s: Card Status=0x%08X, error %d\n",
-					__func__, status, err);
+		err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, NULL);
 	}
 
 	return err;
@@ -662,6 +712,7 @@
 	idatas[0] = idata;
 	req_to_mmc_queue_req(req)->drv_op =
 		rpmb ? MMC_DRV_OP_IOCTL_RPMB : MMC_DRV_OP_IOCTL;
+	req_to_mmc_queue_req(req)->drv_op_result = -EIO;
 	req_to_mmc_queue_req(req)->drv_op_data = idatas;
 	req_to_mmc_queue_req(req)->ioc_count = 1;
 	blk_execute_rq(mq->queue, NULL, req, 0);
@@ -731,6 +782,7 @@
 	}
 	req_to_mmc_queue_req(req)->drv_op =
 		rpmb ? MMC_DRV_OP_IOCTL_RPMB : MMC_DRV_OP_IOCTL;
+	req_to_mmc_queue_req(req)->drv_op_result = -EIO;
 	req_to_mmc_queue_req(req)->drv_op_data = idata;
 	req_to_mmc_queue_req(req)->ioc_count = num_of_cmds;
 	blk_execute_rq(mq->queue, NULL, req, 0);
@@ -821,9 +873,11 @@
 static int mmc_blk_part_switch_pre(struct mmc_card *card,
 				   unsigned int part_type)
 {
+	const unsigned int mask = EXT_CSD_PART_CONFIG_ACC_MASK;
+	const unsigned int rpmb = EXT_CSD_PART_CONFIG_ACC_RPMB;
 	int ret = 0;
 
-	if (part_type == EXT_CSD_PART_CONFIG_ACC_RPMB) {
+	if ((part_type & mask) == rpmb) {
 		if (card->ext_csd.cmdq_en) {
 			ret = mmc_cmdq_disable(card);
 			if (ret)
@@ -838,9 +892,11 @@
 static int mmc_blk_part_switch_post(struct mmc_card *card,
 				    unsigned int part_type)
 {
+	const unsigned int mask = EXT_CSD_PART_CONFIG_ACC_MASK;
+	const unsigned int rpmb = EXT_CSD_PART_CONFIG_ACC_RPMB;
 	int ret = 0;
 
-	if (part_type == EXT_CSD_PART_CONFIG_ACC_RPMB) {
+	if ((part_type & mask) == rpmb) {
 		mmc_retune_unpause(card->host);
 		if (card->reenable_cmdq && !card->ext_csd.cmdq_en)
 			ret = mmc_cmdq_enable(card);
@@ -970,58 +1026,6 @@
 	return ms;
 }
 
-static inline bool mmc_blk_in_tran_state(u32 status)
-{
-	/*
-	 * Some cards mishandle the status bits, so make sure to check both the
-	 * busy indication and the card state.
-	 */
-	return status & R1_READY_FOR_DATA &&
-	       (R1_CURRENT_STATE(status) == R1_STATE_TRAN);
-}
-
-static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms,
-			    struct request *req, u32 *resp_errs)
-{
-	unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
-	int err = 0;
-	u32 status;
-
-	do {
-		bool done = time_after(jiffies, timeout);
-
-		err = __mmc_send_status(card, &status, 5);
-		if (err) {
-			pr_err("%s: error %d requesting status\n",
-			       req->rq_disk->disk_name, err);
-			return err;
-		}
-
-		/* Accumulate any response error bits seen */
-		if (resp_errs)
-			*resp_errs |= status;
-
-		/*
-		 * Timeout if the device never becomes ready for data and never
-		 * leaves the program state.
-		 */
-		if (done) {
-			pr_err("%s: Card stuck in wrong state! %s %s status: %#x\n",
-				mmc_hostname(card->host),
-				req->rq_disk->disk_name, __func__, status);
-			return -ETIMEDOUT;
-		}
-
-		/*
-		 * Some cards mishandle the status bits,
-		 * so make sure to check both the busy
-		 * indication and the card state.
-		 */
-	} while (!mmc_blk_in_tran_state(status));
-
-	return err;
-}
-
 static int mmc_blk_reset(struct mmc_blk_data *md, struct mmc_host *host,
 			 int type)
 {
@@ -1056,6 +1060,20 @@
 	md->reset_done &= ~type;
 }
 
+static void mmc_blk_check_sbc(struct mmc_queue_req *mq_rq)
+{
+	struct mmc_blk_ioc_data **idata = mq_rq->drv_op_data;
+	int i;
+
+	for (i = 1; i < mq_rq->ioc_count; i++) {
+		if (idata[i - 1]->ic.opcode == MMC_SET_BLOCK_COUNT &&
+		    mmc_op_multi(idata[i]->ic.opcode)) {
+			idata[i - 1]->flags |= MMC_BLK_IOC_DROP;
+			idata[i]->flags |= MMC_BLK_IOC_SBC;
+		}
+	}
+}
+
 /*
  * The non-block commands come back from the block layer after it queued it and
  * processed it with all other requests and then they get issued in this
@@ -1078,16 +1096,27 @@
 
 	switch (mq_rq->drv_op) {
 	case MMC_DRV_OP_IOCTL:
+		if (card->ext_csd.cmdq_en) {
+			ret = mmc_cmdq_disable(card);
+			if (ret)
+				break;
+		}
+
+		mmc_blk_check_sbc(mq_rq);
+
+		fallthrough;
 	case MMC_DRV_OP_IOCTL_RPMB:
 		idata = mq_rq->drv_op_data;
 		for (i = 0, ret = 0; i < mq_rq->ioc_count; i++) {
-			ret = __mmc_blk_ioctl_cmd(card, md, idata[i]);
+			ret = __mmc_blk_ioctl_cmd(card, md, idata, i);
 			if (ret)
 				break;
 		}
 		/* Always switch back to main area after RPMB access */
 		if (rpmb_ioctl)
 			mmc_blk_part_switch(card, 0);
+		else if (card->reenable_cmdq && !card->ext_csd.cmdq_en)
+			mmc_cmdq_enable(card);
 		break;
 	case MMC_DRV_OP_BOOT_WP:
 		ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP,
@@ -1144,7 +1173,7 @@
 					 card->erase_arg == MMC_TRIM_ARG ?
 					 INAND_CMD38_ARG_TRIM :
 					 INAND_CMD38_ARG_ERASE,
-					 0);
+					 card->ext_csd.generic_cmd6_time);
 		}
 		if (!err)
 			err = mmc_erase(card, from, nr, card->erase_arg);
@@ -1186,7 +1215,7 @@
 				 arg == MMC_SECURE_TRIM1_ARG ?
 				 INAND_CMD38_ARG_SECTRIM1 :
 				 INAND_CMD38_ARG_SECERASE,
-				 0);
+				 card->ext_csd.generic_cmd6_time);
 		if (err)
 			goto out_retry;
 	}
@@ -1204,7 +1233,7 @@
 			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
 					 INAND_CMD38_ARG_EXT_CSD,
 					 INAND_CMD38_ARG_SECTRIM2,
-					 0);
+					 card->ext_csd.generic_cmd6_time);
 			if (err)
 				goto out_retry;
 		}
@@ -1454,6 +1483,7 @@
 	struct mmc_request *mrq = &mqrq->brq.mrq;
 	struct request_queue *q = req->q;
 	struct mmc_host *host = mq->card->host;
+	enum mmc_issue_type issue_type = mmc_issue_type(mq, req);
 	unsigned long flags;
 	bool put_card;
 	int err;
@@ -1477,13 +1507,15 @@
 			blk_mq_requeue_request(req, true);
 		else
 			__blk_mq_end_request(req, BLK_STS_OK);
+	} else if (mq->in_recovery) {
+		blk_mq_requeue_request(req, true);
 	} else {
 		blk_mq_end_request(req, BLK_STS_OK);
 	}
 
 	spin_lock_irqsave(&mq->lock, flags);
 
-	mq->in_flight[mmc_issue_type(mq, req)] -= 1;
+	mq->in_flight[issue_type] -= 1;
 
 	put_card = (mmc_tot_in_flight(mq) == 0);
 
@@ -1509,8 +1541,7 @@
 	err = mmc_cqe_recovery(host);
 	if (err)
 		mmc_blk_reset(mq->blkdata, host, MMC_BLK_CQE_RECOVERY);
-	else
-		mmc_blk_reset_success(mq->blkdata, MMC_BLK_CQE_RECOVERY);
+	mmc_blk_reset_success(mq->blkdata, MMC_BLK_CQE_RECOVERY);
 
 	pr_debug("%s: CQE recovery done\n", mmc_hostname(host));
 }
@@ -1529,7 +1560,7 @@
 	 */
 	if (mq->in_recovery)
 		mmc_blk_cqe_complete_rq(mq, req);
-	else
+	else if (likely(!blk_should_fake_timeout(req->q)))
 		blk_mq_complete_request(req);
 }
 
@@ -1671,7 +1702,7 @@
 
 	mmc_blk_send_stop(card, timeout);
 
-	err = card_busy_detect(card, timeout, req, NULL);
+	err = card_busy_detect(card, timeout, NULL);
 
 	mmc_retune_release(card->host);
 
@@ -1688,31 +1719,31 @@
 	struct mmc_card *card = mq->card;
 	struct mmc_host *host = card->host;
 	blk_status_t error = BLK_STS_OK;
-	int retries = 0;
 
 	do {
 		u32 status;
 		int err;
+		int retries = 0;
 
-		mmc_blk_rw_rq_prep(mqrq, card, 1, mq);
+		while (retries++ <= MMC_READ_SINGLE_RETRIES) {
+			mmc_blk_rw_rq_prep(mqrq, card, 1, mq);
 
-		mmc_wait_for_req(host, mrq);
+			mmc_wait_for_req(host, mrq);
 
-		err = mmc_send_status(card, &status);
-		if (err)
-			goto error_exit;
-
-		if (!mmc_host_is_spi(host) &&
-		    !mmc_blk_in_tran_state(status)) {
-			err = mmc_blk_fix_state(card, req);
+			err = mmc_send_status(card, &status);
 			if (err)
 				goto error_exit;
-		}
 
-		if (mrq->cmd->error && retries++ < MMC_READ_SINGLE_RETRIES)
-			continue;
+			if (!mmc_host_is_spi(host) &&
+			    !mmc_blk_in_tran_state(status)) {
+				err = mmc_blk_fix_state(card, req);
+				if (err)
+					goto error_exit;
+			}
 
-		retries = 0;
+			if (!mrq->cmd->error)
+				break;
+		}
 
 		if (mrq->cmd->error ||
 		    mrq->data->error ||
@@ -1895,7 +1926,7 @@
 	if (mmc_host_is_spi(card->host) || rq_data_dir(req) == READ)
 		return 0;
 
-	err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, req, &status);
+	err = card_busy_detect(card, MMC_BLK_TIMEOUT_MS, &status);
 
 	/*
 	 * Do not assume data transferred correctly if there are any error bits
@@ -1963,7 +1994,7 @@
 
 	if (mq->use_cqe)
 		mmc_blk_cqe_complete_rq(mq, req);
-	else
+	else if (likely(!blk_should_fake_timeout(req->q)))
 		mmc_blk_mq_complete_rq(mq, req);
 }
 
@@ -1984,14 +2015,14 @@
 	mmc_blk_urgent_bkops(mq, mqrq);
 }
 
-static void mmc_blk_mq_dec_in_flight(struct mmc_queue *mq, struct request *req)
+static void mmc_blk_mq_dec_in_flight(struct mmc_queue *mq, enum mmc_issue_type issue_type)
 {
 	unsigned long flags;
 	bool put_card;
 
 	spin_lock_irqsave(&mq->lock, flags);
 
-	mq->in_flight[mmc_issue_type(mq, req)] -= 1;
+	mq->in_flight[issue_type] -= 1;
 
 	put_card = (mmc_tot_in_flight(mq) == 0);
 
@@ -2003,6 +2034,7 @@
 
 static void mmc_blk_mq_post_req(struct mmc_queue *mq, struct request *req)
 {
+	enum mmc_issue_type issue_type = mmc_issue_type(mq, req);
 	struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req);
 	struct mmc_request *mrq = &mqrq->brq.mrq;
 	struct mmc_host *host = mq->card->host;
@@ -2015,10 +2047,10 @@
 	 */
 	if (mq->in_recovery)
 		mmc_blk_mq_complete_rq(mq, req);
-	else
+	else if (likely(!blk_should_fake_timeout(req->q)))
 		blk_mq_complete_request(req);
 
-	mmc_blk_mq_dec_in_flight(mq, req);
+	mmc_blk_mq_dec_in_flight(mq, issue_type);
 }
 
 void mmc_blk_mq_recovery(struct mmc_queue *mq)
@@ -2251,6 +2283,10 @@
 	case MMC_ISSUE_ASYNC:
 		switch (req_op(req)) {
 		case REQ_OP_FLUSH:
+			if (!mmc_cache_enabled(host)) {
+				blk_mq_end_request(req, BLK_STS_OK);
+				return MMC_REQ_FINISHED;
+			}
 			ret = mmc_blk_cqe_issue_flush(mq, req);
 			break;
 		case REQ_OP_READ:
@@ -2511,8 +2547,8 @@
 	struct mmc_rpmb_data *rpmb = container_of(inode->i_cdev,
 						  struct mmc_rpmb_data, chrdev);
 
-	put_device(&rpmb->dev);
 	mmc_blk_put(rpmb->md);
+	put_device(&rpmb->dev);
 
 	return 0;
 }
@@ -2752,6 +2788,7 @@
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 	req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_GET_CARD_STATUS;
+	req_to_mmc_queue_req(req)->drv_op_result = -EIO;
 	blk_execute_rq(mq->queue, NULL, req, 0);
 	ret = req_to_mmc_queue_req(req)->drv_op_result;
 	if (ret >= 0) {
@@ -2790,6 +2827,7 @@
 		goto out_free;
 	}
 	req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_GET_EXT_CSD;
+	req_to_mmc_queue_req(req)->drv_op_result = -EIO;
 	req_to_mmc_queue_req(req)->drv_op_data = &ext_csd;
 	blk_execute_rq(mq->queue, NULL, req, 0);
 	err = req_to_mmc_queue_req(req)->drv_op_result;
@@ -3097,4 +3135,3 @@
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Multimedia Card (MMC) block device driver");
-
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/core/bus.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/core/bus.c
@@ -15,6 +15,7 @@
 #include <linux/stat.h>
 #include <linux/of.h>
 #include <linux/pm_runtime.h>
+#include <linux/sysfs.h>
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
@@ -34,13 +35,13 @@
 
 	switch (card->type) {
 	case MMC_TYPE_MMC:
-		return sprintf(buf, "MMC\n");
+		return sysfs_emit(buf, "MMC\n");
 	case MMC_TYPE_SD:
-		return sprintf(buf, "SD\n");
+		return sysfs_emit(buf, "SD\n");
 	case MMC_TYPE_SDIO:
-		return sprintf(buf, "SDIO\n");
+		return sysfs_emit(buf, "SDIO\n");
 	case MMC_TYPE_SD_COMBO:
-		return sprintf(buf, "SDcombo\n");
+		return sysfs_emit(buf, "SDcombo\n");
 	default:
 		return -EFAULT;
 	}
@@ -134,6 +135,8 @@
 	if (dev->driver && drv->shutdown)
 		drv->shutdown(card);
 
+	__mmc_stop_host(host);
+
 	if (host->bus_ops->shutdown) {
 		ret = host->bus_ops->shutdown(host);
 		if (ret)
@@ -373,11 +376,6 @@
 	mmc_remove_card_debugfs(card);
 #endif
 
-	if (host->cqe_enabled) {
-		host->cqe_ops->cqe_disable(host);
-		host->cqe_enabled = false;
-	}
-
 	if (mmc_card_present(card)) {
 		if (mmc_host_is_spi(card->host)) {
 			pr_info("%s: SPI card removed\n",
@@ -390,6 +388,10 @@
 		of_node_put(card->dev.of_node);
 	}
 
+	if (host->cqe_enabled) {
+		host->cqe_ops->cqe_disable(host);
+		host->cqe_enabled = false;
+	}
+
 	put_device(&card->dev);
 }
-
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/core/bus.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/core/bus.h
@@ -9,6 +9,7 @@
 #define _MMC_CORE_BUS_H
 
 #include <linux/device.h>
+#include <linux/sysfs.h>
 
 struct mmc_host;
 struct mmc_card;
@@ -17,7 +18,7 @@
 static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *attr, char *buf)	\
 {										\
 	struct mmc_card *card = mmc_dev_to_card(dev);				\
-	return sprintf(buf, fmt, args);						\
+	return sysfs_emit(buf, fmt, args);					\
 }										\
 static DEVICE_ATTR(name, S_IRUGO, mmc_##name##_show, NULL)
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/core/core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/core/core.c
@@ -564,22 +564,27 @@
 	host->cqe_ops->cqe_recovery_start(host);
 
 	memset(&cmd, 0, sizeof(cmd));
-	cmd.opcode       = MMC_STOP_TRANSMISSION,
-	cmd.flags        = MMC_RSP_R1B | MMC_CMD_AC,
+	cmd.opcode       = MMC_STOP_TRANSMISSION;
+	cmd.flags        = MMC_RSP_R1B | MMC_CMD_AC;
 	cmd.flags       &= ~MMC_RSP_CRC; /* Ignore CRC */
-	cmd.busy_timeout = MMC_CQE_RECOVERY_TIMEOUT,
-	mmc_wait_for_cmd(host, &cmd, 0);
+	cmd.busy_timeout = MMC_CQE_RECOVERY_TIMEOUT;
+	mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
+
+	mmc_poll_for_busy(host->card, MMC_CQE_RECOVERY_TIMEOUT, true, true);
 
 	memset(&cmd, 0, sizeof(cmd));
 	cmd.opcode       = MMC_CMDQ_TASK_MGMT;
 	cmd.arg          = 1; /* Discard entire queue */
 	cmd.flags        = MMC_RSP_R1B | MMC_CMD_AC;
 	cmd.flags       &= ~MMC_RSP_CRC; /* Ignore CRC */
-	cmd.busy_timeout = MMC_CQE_RECOVERY_TIMEOUT,
-	err = mmc_wait_for_cmd(host, &cmd, 0);
+	cmd.busy_timeout = MMC_CQE_RECOVERY_TIMEOUT;
+	err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
 
 	host->cqe_ops->cqe_recovery_finish(host);
 
+	if (err)
+		err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES);
+
 	mmc_retune_release(host);
 
 	return err;
@@ -953,11 +958,14 @@
 
 	err = host->ops->execute_tuning(host, opcode);
 
-	if (err)
+	if (err) {
 		pr_err("%s: tuning execution failed: %d\n",
 			mmc_hostname(host), err);
-	else
+	} else {
+		host->retune_now = 0;
+		host->need_retune = 0;
 		mmc_retune_enable(host);
+	}
 
 	return err;
 }
@@ -1142,7 +1150,13 @@
 		mmc_power_cycle(host, ocr);
 	} else {
 		bit = fls(ocr) - 1;
-		ocr &= 3 << bit;
+		/*
+		 * The bit variable represents the highest voltage bit set in
+		 * the OCR register.
+		 * To keep a range of 2 values (e.g. 3.2V/3.3V and 3.3V/3.4V),
+		 * we must shift the mask '3' with (bit - 1).
+		 */
+		ocr &= 3 << (bit - 1);
 		if (bit != host->ios.vdd)
 			dev_warn(mmc_dev(host), "exceeding card's volts\n");
 	}
@@ -1221,7 +1235,7 @@
 
 	err = mmc_wait_for_cmd(host, &cmd, 0);
 	if (err)
-		return err;
+		goto power_cycle;
 
 	if (!mmc_host_is_spi(host) && (cmd.resp[0] & R1_ERROR))
 		return -EIO;
@@ -1469,8 +1483,7 @@
 	mmc_bus_put(host);
 }
 
-static void _mmc_detect_change(struct mmc_host *host, unsigned long delay,
-				bool cd_irq)
+void _mmc_detect_change(struct mmc_host *host, unsigned long delay, bool cd_irq)
 {
 	/*
 	 * If the device is configured as wakeup, we prevent a new sleep for
@@ -1548,6 +1561,11 @@
 		card->pref_erase = 0;
 }
 
+static bool is_trim_arg(unsigned int arg)
+{
+	return (arg & MMC_TRIM_OR_DISCARD_ARGS) && arg != MMC_DISCARD_ARG;
+}
+
 static unsigned int mmc_mmc_erase_timeout(struct mmc_card *card,
 				          unsigned int arg, unsigned int qty)
 {
@@ -1733,8 +1751,11 @@
 	 * the erase operation does not exceed the max_busy_timeout, we should
 	 * use R1B response. Or we need to prevent the host from doing hw busy
 	 * detection, which is done by converting to a R1 response instead.
+	 * Note, some hosts requires R1B, which also means they are on their own
+	 * when it comes to deal with the busy timeout.
 	 */
-	if (card->host->max_busy_timeout &&
+	if (!(card->host->caps & MMC_CAP_NEED_RSP_BUSY) &&
+	    card->host->max_busy_timeout &&
 	    busy_timeout > card->host->max_busy_timeout) {
 		cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
 	} else {
@@ -1876,7 +1897,7 @@
 	    !(card->ext_csd.sec_feature_support & EXT_CSD_SEC_ER_EN))
 		return -EOPNOTSUPP;
 
-	if (mmc_card_mmc(card) && (arg & MMC_TRIM_ARGS) &&
+	if (mmc_card_mmc(card) && is_trim_arg(arg) &&
 	    !(card->ext_csd.sec_feature_support & EXT_CSD_SEC_GB_CL_EN))
 		return -EOPNOTSUPP;
 
@@ -1906,7 +1927,7 @@
 	 * identified by the card->eg_boundary flag.
 	 */
 	rem = card->erase_size - (from % card->erase_size);
-	if ((arg & MMC_TRIM_ARGS) && (card->eg_boundary) && (nr > rem)) {
+	if ((arg & MMC_TRIM_OR_DISCARD_ARGS) && card->eg_boundary && nr > rem) {
 		err = mmc_do_erase(card, from, from + rem - 1, arg);
 		from += rem;
 		if ((err) || (to <= from))
@@ -2129,7 +2150,7 @@
 	ret = host->bus_ops->hw_reset(host);
 	mmc_bus_put(host);
 
-	if (ret)
+	if (ret < 0)
 		pr_warn("%s: tried to HW reset card, got error %d\n",
 			mmc_hostname(host), ret);
 
@@ -2297,11 +2318,8 @@
 
 	mmc_bus_get(host);
 
-	/*
-	 * if there is a _removable_ card registered, check whether it is
-	 * still present
-	 */
-	if (host->bus_ops && !host->bus_dead && mmc_card_is_removable(host))
+	/* Verify a registered card to be functional, else remove it. */
+	if (host->bus_ops && !host->bus_dead)
 		host->bus_ops->detect(host);
 
 	host->detect_change = 0;
@@ -2362,8 +2380,11 @@
 	_mmc_detect_change(host, 0, false);
 }
 
-void mmc_stop_host(struct mmc_host *host)
+void __mmc_stop_host(struct mmc_host *host)
 {
+	if (host->rescan_disable)
+		return;
+
 	if (host->slot.cd_irq >= 0) {
 		mmc_gpio_set_cd_wake(host, false);
 		disable_irq(host->slot.cd_irq);
@@ -2371,6 +2392,11 @@
 
 	host->rescan_disable = 1;
 	cancel_delayed_work_sync(&host->detect);
+}
+
+void mmc_stop_host(struct mmc_host *host)
+{
+	__mmc_stop_host(host);
 
 	/* clear pm flags now and let card drivers set them as needed */
 	host->pm_flags = 0;
@@ -2393,80 +2419,6 @@
 	mmc_release_host(host);
 }
 
-#ifdef CONFIG_PM_SLEEP
-/* Do the card removal on suspend if card is assumed removeable
- * Do that in pm notifier while userspace isn't yet frozen, so we will be able
-   to sync the card.
-*/
-static int mmc_pm_notify(struct notifier_block *notify_block,
-			unsigned long mode, void *unused)
-{
-	struct mmc_host *host = container_of(
-		notify_block, struct mmc_host, pm_notify);
-	unsigned long flags;
-	int err = 0;
-
-	switch (mode) {
-	case PM_HIBERNATION_PREPARE:
-	case PM_SUSPEND_PREPARE:
-	case PM_RESTORE_PREPARE:
-		spin_lock_irqsave(&host->lock, flags);
-		host->rescan_disable = 1;
-		spin_unlock_irqrestore(&host->lock, flags);
-		cancel_delayed_work_sync(&host->detect);
-
-		if (!host->bus_ops)
-			break;
-
-		/* Validate prerequisites for suspend */
-		if (host->bus_ops->pre_suspend)
-			err = host->bus_ops->pre_suspend(host);
-		if (!err)
-			break;
-
-		if (!mmc_card_is_removable(host)) {
-			dev_warn(mmc_dev(host),
-				 "pre_suspend failed for non-removable host: "
-				 "%d\n", err);
-			/* Avoid removing non-removable hosts */
-			break;
-		}
-
-		/* Calling bus_ops->remove() with a claimed host can deadlock */
-		host->bus_ops->remove(host);
-		mmc_claim_host(host);
-		mmc_detach_bus(host);
-		mmc_power_off(host);
-		mmc_release_host(host);
-		host->pm_flags = 0;
-		break;
-
-	case PM_POST_SUSPEND:
-	case PM_POST_HIBERNATION:
-	case PM_POST_RESTORE:
-
-		spin_lock_irqsave(&host->lock, flags);
-		host->rescan_disable = 0;
-		spin_unlock_irqrestore(&host->lock, flags);
-		_mmc_detect_change(host, 0, false);
-
-	}
-
-	return 0;
-}
-
-void mmc_register_pm_notifier(struct mmc_host *host)
-{
-	host->pm_notify.notifier_call = mmc_pm_notify;
-	register_pm_notifier(&host->pm_notify);
-}
-
-void mmc_unregister_pm_notifier(struct mmc_host *host)
-{
-	unregister_pm_notifier(&host->pm_notify);
-}
-#endif
-
 static int __init mmc_init(void)
 {
 	int ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/core/core.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/core/core.h
@@ -29,6 +29,7 @@
 	int (*shutdown)(struct mmc_host *);
 	int (*hw_reset)(struct mmc_host *);
 	int (*sw_reset)(struct mmc_host *);
+	bool (*cache_enabled)(struct mmc_host *);
 };
 
 void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops);
@@ -68,8 +69,11 @@
 
 void mmc_rescan(struct work_struct *work);
 void mmc_start_host(struct mmc_host *host);
+void __mmc_stop_host(struct mmc_host *host);
 void mmc_stop_host(struct mmc_host *host);
 
+void _mmc_detect_change(struct mmc_host *host, unsigned long delay,
+			bool cd_irq);
 int _mmc_detect_card_removed(struct mmc_host *host);
 int mmc_detect_card_removed(struct mmc_host *host);
 
@@ -91,14 +95,6 @@
 int mmc_hs200_to_hs400(struct mmc_card *card);
 int mmc_hs400_to_hs200(struct mmc_card *card);
 
-#ifdef CONFIG_PM_SLEEP
-void mmc_register_pm_notifier(struct mmc_host *host);
-void mmc_unregister_pm_notifier(struct mmc_host *host);
-#else
-static inline void mmc_register_pm_notifier(struct mmc_host *host) { }
-static inline void mmc_unregister_pm_notifier(struct mmc_host *host) { }
-#endif
-
 void mmc_wait_for_req_done(struct mmc_host *host, struct mmc_request *mrq);
 bool mmc_is_req_done(struct mmc_host *host, struct mmc_request *mrq);
 
@@ -169,4 +165,12 @@
 		host->ops->post_req(host, mrq, err);
 }
 
+static inline bool mmc_cache_enabled(struct mmc_host *host)
+{
+	if (host->bus_ops->cache_enabled)
+		return host->bus_ops->cache_enabled(host);
+
+	return false;
+}
+
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/core/host.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/core/host.c
@@ -33,6 +33,42 @@
 
 static DEFINE_IDA(mmc_host_ida);
 
+#ifdef CONFIG_PM_SLEEP
+static int mmc_host_class_prepare(struct device *dev)
+{
+	struct mmc_host *host = cls_dev_to_mmc_host(dev);
+
+	/*
+	 * It's safe to access the bus_ops pointer, as both userspace and the
+	 * workqueue for detecting cards are frozen at this point.
+	 */
+	if (!host->bus_ops)
+		return 0;
+
+	/* Validate conditions for system suspend. */
+	if (host->bus_ops->pre_suspend)
+		return host->bus_ops->pre_suspend(host);
+
+	return 0;
+}
+
+static void mmc_host_class_complete(struct device *dev)
+{
+	struct mmc_host *host = cls_dev_to_mmc_host(dev);
+
+	_mmc_detect_change(host, 0, false);
+}
+
+static const struct dev_pm_ops mmc_host_class_dev_pm_ops = {
+	.prepare = mmc_host_class_prepare,
+	.complete = mmc_host_class_complete,
+};
+
+#define MMC_HOST_CLASS_DEV_PM_OPS (&mmc_host_class_dev_pm_ops)
+#else
+#define MMC_HOST_CLASS_DEV_PM_OPS NULL
+#endif
+
 static void mmc_host_classdev_release(struct device *dev)
 {
 	struct mmc_host *host = cls_dev_to_mmc_host(dev);
@@ -40,9 +76,19 @@
 	kfree(host);
 }
 
+static int mmc_host_classdev_shutdown(struct device *dev)
+{
+	struct mmc_host *host = cls_dev_to_mmc_host(dev);
+
+	__mmc_stop_host(host);
+	return 0;
+}
+
 static struct class mmc_host_class = {
 	.name		= "mmc_host",
 	.dev_release	= mmc_host_classdev_release,
+	.shutdown_pre	= mmc_host_classdev_shutdown,
+	.pm		= MMC_HOST_CLASS_DEV_PM_OPS,
 };
 
 int mmc_register_host_class(void)
@@ -65,13 +111,12 @@
 
 /*
  * Pause re-tuning for a small set of operations.  The pause begins after the
- * next command and after first doing re-tuning.
+ * next command.
  */
 void mmc_retune_pause(struct mmc_host *host)
 {
 	if (!host->retune_paused) {
 		host->retune_paused = 1;
-		mmc_retune_needed(host);
 		mmc_retune_hold(host);
 	}
 }
@@ -176,7 +221,6 @@
 	u32 bus_width, drv_type, cd_debounce_delay_ms;
 	int ret;
 	bool cd_cap_invert, cd_gpio_invert = false;
-	bool ro_cap_invert, ro_gpio_invert = false;
 
 	if (!dev || !dev_fwnode(dev))
 		return 0;
@@ -255,9 +299,11 @@
 	}
 
 	/* Parse Write Protection */
-	ro_cap_invert = device_property_read_bool(dev, "wp-inverted");
 
-	ret = mmc_gpiod_request_ro(host, "wp", 0, 0, &ro_gpio_invert);
+	if (device_property_read_bool(dev, "wp-inverted"))
+		host->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
+
+	ret = mmc_gpiod_request_ro(host, "wp", 0, 0, NULL);
 	if (!ret)
 		dev_info(host->parent, "Got WP GPIO\n");
 	else if (ret != -ENOENT && ret != -ENOSYS)
@@ -266,10 +312,6 @@
 	if (device_property_read_bool(dev, "disable-wp"))
 		host->caps2 |= MMC_CAP2_NO_WRITE_PROTECT;
 
-	/* See the comment on CD inversion above */
-	if (ro_cap_invert ^ ro_gpio_invert)
-		host->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
-
 	if (device_property_read_bool(dev, "cap-sd-highspeed"))
 		host->caps |= MMC_CAP_SD_HIGHSPEED;
 	if (device_property_read_bool(dev, "cap-mmc-highspeed"))
@@ -454,6 +496,16 @@
 
 EXPORT_SYMBOL(mmc_alloc_host);
 
+static int mmc_validate_host_caps(struct mmc_host *host)
+{
+	if (host->caps & MMC_CAP_SDIO_IRQ && !host->ops->enable_sdio_irq) {
+		dev_warn(host->parent, "missing ->enable_sdio_irq() ops\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 /**
  *	mmc_add_host - initialise host hardware
  *	@host: mmc host
@@ -466,8 +518,9 @@
 {
 	int err;
 
-	WARN_ON((host->caps & MMC_CAP_SDIO_IRQ) &&
-		!host->ops->enable_sdio_irq);
+	err = mmc_validate_host_caps(host);
+	if (err)
+		return err;
 
 	err = device_add(&host->class_dev);
 	if (err)
@@ -480,8 +533,6 @@
 #endif
 
 	mmc_start_host(host);
-	mmc_register_pm_notifier(host);
-
 	return 0;
 }
 
@@ -497,7 +548,6 @@
  */
 void mmc_remove_host(struct mmc_host *host)
 {
-	mmc_unregister_pm_notifier(host);
 	mmc_stop_host(host);
 
 #ifdef CONFIG_DEBUG_FS
@@ -519,6 +569,7 @@
  */
 void mmc_free_host(struct mmc_host *host)
 {
+	cancel_delayed_work_sync(&host->detect);
 	mmc_pwrseq_free(host);
 	put_device(&host->class_dev);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/core/mmc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/core/mmc.c
@@ -12,6 +12,7 @@
 #include <linux/slab.h>
 #include <linux/stat.h>
 #include <linux/pm_runtime.h>
+#include <linux/sysfs.h>
 
 #include <linux/mmc/host.h>
 #include <linux/mmc/card.h>
@@ -297,7 +298,7 @@
 	}
 }
 
-static void mmc_part_add(struct mmc_card *card, unsigned int size,
+static void mmc_part_add(struct mmc_card *card, u64 size,
 			 unsigned int part_cfg, char *name, int idx, bool ro,
 			 int area_type)
 {
@@ -313,7 +314,7 @@
 {
 	int idx;
 	u8 hc_erase_grp_sz, hc_wp_grp_sz;
-	unsigned int part_size;
+	u64 part_size;
 
 	/*
 	 * General purpose partition feature support --
@@ -343,8 +344,7 @@
 				(ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3 + 1]
 				<< 8) +
 				ext_csd[EXT_CSD_GP_SIZE_MULT + idx * 3];
-			part_size *= (size_t)(hc_erase_grp_sz *
-				hc_wp_grp_sz);
+			part_size *= (hc_erase_grp_sz * hc_wp_grp_sz);
 			mmc_part_add(card, part_size << 19,
 				EXT_CSD_PART_CONFIG_ACC_GP0 + idx,
 				"gp%d", idx, false,
@@ -362,7 +362,7 @@
 static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
 {
 	int err = 0, idx;
-	unsigned int part_size;
+	u64 part_size;
 	struct device_node *np;
 	bool broken_hpi = false;
 
@@ -424,10 +424,6 @@
 
 		/* EXT_CSD value is in units of 10ms, but we store in ms */
 		card->ext_csd.part_time = 10 * ext_csd[EXT_CSD_PART_SWITCH_TIME];
-		/* Some eMMC set the value too low so set a minimum */
-		if (card->ext_csd.part_time &&
-		    card->ext_csd.part_time < MMC_MIN_PART_SWITCH_TIME)
-			card->ext_csd.part_time = MMC_MIN_PART_SWITCH_TIME;
 
 		/* Sleep / awake timeout in 100ns units */
 		if (sa_shift > 0 && sa_shift <= 0x17)
@@ -617,6 +613,17 @@
 		card->ext_csd.data_sector_size = 512;
 	}
 
+	/*
+	 * GENERIC_CMD6_TIME is to be used "unless a specific timeout is defined
+	 * when accessing a specific field", so use it here if there is no
+	 * PARTITION_SWITCH_TIME.
+	 */
+	if (!card->ext_csd.part_time)
+		card->ext_csd.part_time = card->ext_csd.generic_cmd6_time;
+	/* Some eMMC set the value too low so set a minimum */
+	if (card->ext_csd.part_time < MMC_MIN_PART_SWITCH_TIME)
+		card->ext_csd.part_time = MMC_MIN_PART_SWITCH_TIME;
+
 	/* eMMC v5 or later */
 	if (card->ext_csd.rev >= 7) {
 		memcpy(card->ext_csd.fwrev, &ext_csd[EXT_CSD_FIRMWARE_VERSION],
@@ -798,12 +805,11 @@
 {
 	struct mmc_card *card = mmc_dev_to_card(dev);
 
-	if (card->ext_csd.rev < 7) {
-		return sprintf(buf, "0x%x\n", card->cid.fwrev);
-	} else {
-		return sprintf(buf, "0x%*phN\n", MMC_FIRMWARE_LEN,
-			       card->ext_csd.fwrev);
-	}
+	if (card->ext_csd.rev < 7)
+		return sysfs_emit(buf, "0x%x\n", card->cid.fwrev);
+	else
+		return sysfs_emit(buf, "0x%*phN\n", MMC_FIRMWARE_LEN,
+				  card->ext_csd.fwrev);
 }
 
 static DEVICE_ATTR(fwrev, S_IRUGO, mmc_fwrev_show, NULL);
@@ -816,10 +822,10 @@
 	struct mmc_host *host = card->host;
 
 	if (card->csd.dsr_imp && host->dsr_req)
-		return sprintf(buf, "0x%x\n", host->dsr);
+		return sysfs_emit(buf, "0x%x\n", host->dsr);
 	else
 		/* return default DSR value */
-		return sprintf(buf, "0x%x\n", 0x404);
+		return sysfs_emit(buf, "0x%x\n", 0x404);
 }
 
 static DEVICE_ATTR(dsr, S_IRUGO, mmc_dsr_show, NULL);
@@ -985,10 +991,12 @@
 	static unsigned ext_csd_bits[] = {
 		EXT_CSD_BUS_WIDTH_8,
 		EXT_CSD_BUS_WIDTH_4,
+		EXT_CSD_BUS_WIDTH_1,
 	};
 	static unsigned bus_widths[] = {
 		MMC_BUS_WIDTH_8,
 		MMC_BUS_WIDTH_4,
+		MMC_BUS_WIDTH_1,
 	};
 	struct mmc_host *host = card->host;
 	unsigned idx, bus_width = 0;
@@ -1911,9 +1919,12 @@
 	 * If the max_busy_timeout of the host is specified, validate it against
 	 * the sleep cmd timeout. A failure means we need to prevent the host
 	 * from doing hw busy detection, which is done by converting to a R1
-	 * response instead of a R1B.
+	 * response instead of a R1B. Note, some hosts requires R1B, which also
+	 * means they are on their own when it comes to deal with the busy
+	 * timeout.
 	 */
-	if (host->max_busy_timeout && (timeout_ms > host->max_busy_timeout)) {
+	if (!(host->caps & MMC_CAP_NEED_RSP_BUSY) && host->max_busy_timeout &&
+	    (timeout_ms > host->max_busy_timeout)) {
 		cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
 	} else {
 		cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
@@ -2010,6 +2021,12 @@
 	}
 }
 
+static bool _mmc_cache_enabled(struct mmc_host *host)
+{
+	return host->card->ext_csd.cache_size > 0 &&
+	       host->card->ext_csd.cache_ctrl & 1;
+}
+
 static int _mmc_suspend(struct mmc_host *host, bool is_suspend)
 {
 	int err = 0;
@@ -2188,6 +2205,7 @@
 	.alive = mmc_alive,
 	.shutdown = mmc_shutdown,
 	.hw_reset = _mmc_hw_reset,
+	.cache_enabled = _mmc_cache_enabled,
 };
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/core/mmc_ops.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/core/mmc_ops.c
@@ -19,7 +19,9 @@
 #include "host.h"
 #include "mmc_ops.h"
 
-#define MMC_OPS_TIMEOUT_MS	(10 * 60 * 1000) /* 10 minute timeout */
+#define MMC_OPS_TIMEOUT_MS		(10 * 60 * 1000) /* 10min*/
+#define MMC_BKOPS_TIMEOUT_MS		(120 * 1000) /* 120s */
+#define MMC_CACHE_FLUSH_TIMEOUT_MS	(30 * 1000) /* 30s */
 
 static const u8 tuning_blk_pattern_4bit[] = {
 	0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc,
@@ -448,8 +450,8 @@
 	return __mmc_switch_status(card, true);
 }
 
-static int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,
-			bool send_status, bool retry_crc_err)
+int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,
+		      bool send_status, bool retry_crc_err)
 {
 	struct mmc_host *host = card->host;
 	int err;
@@ -458,10 +460,6 @@
 	bool expired = false;
 	bool busy = false;
 
-	/* We have an unspecified cmd timeout, use the fallback value. */
-	if (!timeout_ms)
-		timeout_ms = MMC_OPS_TIMEOUT_MS;
-
 	/*
 	 * In cases when not allowed to poll by using CMD13 or because we aren't
 	 * capable of polling by using ->card_busy(), then rely on waiting the
@@ -506,6 +504,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(mmc_poll_for_busy);
 
 /**
  *	__mmc_switch - modify EXT_CSD register
@@ -534,14 +533,22 @@
 
 	mmc_retune_hold(host);
 
+	if (!timeout_ms) {
+		pr_warn("%s: unspecified timeout for CMD6 - use generic\n",
+			mmc_hostname(host));
+		timeout_ms = card->ext_csd.generic_cmd6_time;
+	}
+
 	/*
 	 * If the cmd timeout and the max_busy_timeout of the host are both
 	 * specified, let's validate them. A failure means we need to prevent
 	 * the host from doing hw busy detection, which is done by converting
-	 * to a R1 response instead of a R1B.
+	 * to a R1 response instead of a R1B. Note, some hosts requires R1B,
+	 * which also means they are on their own when it comes to deal with the
+	 * busy timeout.
 	 */
-	if (timeout_ms && host->max_busy_timeout &&
-		(timeout_ms > host->max_busy_timeout))
+	if (!(host->caps & MMC_CAP_NEED_RSP_BUSY) &&
+	    host->max_busy_timeout && (timeout_ms > host->max_busy_timeout))
 		use_r1b_resp = false;
 
 	cmd.opcode = MMC_SWITCH;
@@ -552,10 +559,6 @@
 	cmd.flags = MMC_CMD_AC;
 	if (use_r1b_resp) {
 		cmd.flags |= MMC_RSP_SPI_R1B | MMC_RSP_R1B;
-		/*
-		 * A busy_timeout of zero means the host can decide to use
-		 * whatever value it finds suitable.
-		 */
 		cmd.busy_timeout = timeout_ms;
 	} else {
 		cmd.flags |= MMC_RSP_SPI_R1 | MMC_RSP_R1;
@@ -941,7 +944,7 @@
 	 * urgent levels by using an asynchronous background task, when idle.
 	 */
 	err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-			EXT_CSD_BKOPS_START, 1, MMC_OPS_TIMEOUT_MS);
+			 EXT_CSD_BKOPS_START, 1, MMC_BKOPS_TIMEOUT_MS);
 	if (err)
 		pr_warn("%s: Error %d starting bkops\n",
 			mmc_hostname(card->host), err);
@@ -957,11 +960,10 @@
 {
 	int err = 0;
 
-	if (mmc_card_mmc(card) &&
-			(card->ext_csd.cache_size > 0) &&
-			(card->ext_csd.cache_ctrl & 1)) {
+	if (mmc_cache_enabled(card->host)) {
 		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
-				EXT_CSD_FLUSH_CACHE, 1, 0);
+				 EXT_CSD_FLUSH_CACHE, 1,
+				 MMC_CACHE_FLUSH_TIMEOUT_MS);
 		if (err)
 			pr_err("%s: cache flush error %d\n",
 					mmc_hostname(card->host), err);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/core/mmc_ops.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/core/mmc_ops.h
@@ -31,6 +31,8 @@
 int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd);
 int mmc_switch_status(struct mmc_card *card);
 int __mmc_switch_status(struct mmc_card *card, bool crc_err_fatal);
+int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,
+		      bool send_status, bool retry_crc_err);
 int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
 		unsigned int timeout_ms, unsigned char timing,
 		bool use_busy_signal, bool send_status,	bool retry_crc_err);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/core/mmc_test.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/core/mmc_test.c
@@ -3097,13 +3097,13 @@
 	test->buffer = kzalloc(BUFFER_SIZE, GFP_KERNEL);
 #ifdef CONFIG_HIGHMEM
 	test->highmem = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, BUFFER_ORDER);
+	if (!test->highmem) {
+		count = -ENOMEM;
+		goto free_test_buffer;
+	}
 #endif
 
-#ifdef CONFIG_HIGHMEM
-	if (test->buffer && test->highmem) {
-#else
 	if (test->buffer) {
-#endif
 		mutex_lock(&mmc_test_lock);
 		mmc_test_run(test, testcase);
 		mutex_unlock(&mmc_test_lock);
@@ -3111,6 +3111,7 @@
 
 #ifdef CONFIG_HIGHMEM
 	__free_pages(test->highmem, BUFFER_ORDER);
+free_test_buffer:
 #endif
 	kfree(test->buffer);
 	kfree(test);
@@ -3167,7 +3168,8 @@
 	struct mmc_test_dbgfs_file *df;
 
 	if (card->debugfs_root)
-		debugfs_create_file(name, mode, card->debugfs_root, card, fops);
+		file = debugfs_create_file(name, mode, card->debugfs_root,
+					   card, fops);
 
 	df = kmalloc(sizeof(*df), GFP_KERNEL);
 	if (!df) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/core/queue.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/core/queue.c
@@ -107,11 +107,10 @@
 	case MMC_ISSUE_DCMD:
 		if (host->cqe_ops->cqe_timeout(host, mrq, &recovery_needed)) {
 			if (recovery_needed)
-				__mmc_cqe_recovery_notifier(mq);
+				mmc_cqe_recovery_notifier(mrq);
 			return BLK_EH_RESET_TIMER;
 		}
-		/* No timeout (XXX: huh? comment doesn't make much sense) */
-		blk_mq_complete_request(req);
+		/* The request has gone already */
 		return BLK_EH_DONE;
 	default:
 		/* Timeout is handled by mmc core */
@@ -125,18 +124,13 @@
 	struct request_queue *q = req->q;
 	struct mmc_queue *mq = q->queuedata;
 	unsigned long flags;
-	int ret;
+	bool ignore_tout;
 
 	spin_lock_irqsave(&mq->lock, flags);
-
-	if (mq->recovery_needed || !mq->use_cqe)
-		ret = BLK_EH_RESET_TIMER;
-	else
-		ret = mmc_cqe_timed_out(req);
-
+	ignore_tout = mq->recovery_needed || !mq->use_cqe;
 	spin_unlock_irqrestore(&mq->lock, flags);
 
-	return ret;
+	return ignore_tout ? BLK_EH_RESET_TIMER : mmc_cqe_timed_out(req);
 }
 
 static void mmc_mq_recovery_handler(struct work_struct *work)
@@ -190,7 +184,7 @@
 	q->limits.discard_granularity = card->pref_erase << 9;
 	/* granularity must not be greater than max. discard */
 	if (card->pref_erase > max_discard)
-		q->limits.discard_granularity = 0;
+		q->limits.discard_granularity = SECTOR_SIZE;
 	if (mmc_can_secure_erase_trim(card))
 		blk_queue_flag_set(QUEUE_FLAG_SECERASE, q);
 }
@@ -376,8 +370,10 @@
 		     "merging was advertised but not possible");
 	blk_queue_max_segments(mq->queue, mmc_get_max_segments(host));
 
-	if (mmc_card_mmc(card))
+	if (mmc_card_mmc(card) && card->ext_csd.data_sector_size) {
 		block_size = card->ext_csd.data_sector_size;
+		WARN_ON(block_size != 512 && block_size != 4096);
+	}
 
 	blk_queue_logical_block_size(mq->queue, block_size);
 	/*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/core/quirks.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/core/quirks.h
@@ -91,6 +91,20 @@
 		  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
 
 	/*
+	 * Kingston EMMC04G-M627 advertises TRIM but it does not seems to
+	 * support being used to offload WRITE_ZEROES.
+	 */
+	MMC_FIXUP("M62704", CID_MANFID_KINGSTON, 0x0100, add_quirk_mmc,
+		  MMC_QUIRK_TRIM_BROKEN),
+
+	/*
+	 * Micron MTFC4GACAJCN-1M advertises TRIM but it does not seems to
+	 * support being used to offload WRITE_ZEROES.
+	 */
+	MMC_FIXUP("Q2J54A", CID_MANFID_MICRON, 0x014e, add_quirk_mmc,
+		  MMC_QUIRK_TRIM_BROKEN),
+
+	/*
 	 *  On Some Kingston eMMCs, performing trim can result in
 	 *  unrecoverable data conrruption occasionally due to a firmware bug.
 	 */
@@ -119,7 +133,14 @@
 	END_FIXUP
 };
 
+
 static const struct mmc_fixup sdio_fixup_methods[] = {
+	SDIO_FIXUP(SDIO_VENDOR_ID_TI_WL1251, SDIO_DEVICE_ID_TI_WL1251,
+		   add_quirk, MMC_QUIRK_NONSTD_FUNC_IF),
+
+	SDIO_FIXUP(SDIO_VENDOR_ID_TI_WL1251, SDIO_DEVICE_ID_TI_WL1251,
+		   add_quirk, MMC_QUIRK_DISABLE_CD),
+
 	SDIO_FIXUP(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271,
 		   add_quirk, MMC_QUIRK_NONSTD_FUNC_IF),
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/core/regulator.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/core/regulator.c
@@ -258,3 +258,44 @@
 	return 0;
 }
 EXPORT_SYMBOL_GPL(mmc_regulator_get_supply);
+
+/**
+ * mmc_regulator_enable_vqmmc - enable VQMMC regulator for a host
+ * @mmc: the host to regulate
+ *
+ * Returns 0 or errno. Enables the regulator for vqmmc.
+ * Keeps track of the enable status for ensuring that calls to
+ * regulator_enable/disable are balanced.
+ */
+int mmc_regulator_enable_vqmmc(struct mmc_host *mmc)
+{
+	int ret = 0;
+
+	if (!IS_ERR(mmc->supply.vqmmc) && !mmc->vqmmc_enabled) {
+		ret = regulator_enable(mmc->supply.vqmmc);
+		if (ret < 0)
+			dev_err(mmc_dev(mmc), "enabling vqmmc regulator failed\n");
+		else
+			mmc->vqmmc_enabled = true;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(mmc_regulator_enable_vqmmc);
+
+/**
+ * mmc_regulator_disable_vqmmc - disable VQMMC regulator for a host
+ * @mmc: the host to regulate
+ *
+ * Returns 0 or errno. Disables the regulator for vqmmc.
+ * Keeps track of the enable status for ensuring that calls to
+ * regulator_enable/disable are balanced.
+ */
+void mmc_regulator_disable_vqmmc(struct mmc_host *mmc)
+{
+	if (!IS_ERR(mmc->supply.vqmmc) && mmc->vqmmc_enabled) {
+		regulator_disable(mmc->supply.vqmmc);
+		mmc->vqmmc_enabled = false;
+	}
+}
+EXPORT_SYMBOL_GPL(mmc_regulator_disable_vqmmc);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/core/sd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/core/sd.c
@@ -12,6 +12,7 @@
 #include <linux/slab.h>
 #include <linux/stat.h>
 #include <linux/pm_runtime.h>
+#include <linux/sysfs.h>
 
 #include <linux/mmc/host.h>
 #include <linux/mmc/card.h>
@@ -135,6 +136,9 @@
 			csd->erase_size = UNSTUFF_BITS(resp, 39, 7) + 1;
 			csd->erase_size <<= csd->write_blkbits - 9;
 		}
+
+		if (UNSTUFF_BITS(resp, 13, 1))
+			mmc_card_set_readonly(card);
 		break;
 	case 1:
 		/*
@@ -169,6 +173,9 @@
 		csd->write_blkbits = 9;
 		csd->write_partial = 0;
 		csd->erase_size = 1;
+
+		if (UNSTUFF_BITS(resp, 13, 1))
+			mmc_card_set_readonly(card);
 		break;
 	default:
 		pr_err("%s: unrecognised CSD structure version %d\n",
@@ -691,18 +698,16 @@
 MMC_DEV_ATTR(rca, "0x%04x\n", card->rca);
 
 
-static ssize_t mmc_dsr_show(struct device *dev,
-                           struct device_attribute *attr,
-                           char *buf)
-{
-       struct mmc_card *card = mmc_dev_to_card(dev);
-       struct mmc_host *host = card->host;
-
-       if (card->csd.dsr_imp && host->dsr_req)
-               return sprintf(buf, "0x%x\n", host->dsr);
-       else
-               /* return default DSR value */
-               return sprintf(buf, "0x%x\n", 0x404);
+static ssize_t mmc_dsr_show(struct device *dev, struct device_attribute *attr,
+			    char *buf)
+{
+	struct mmc_card *card = mmc_dev_to_card(dev);
+	struct mmc_host *host = card->host;
+
+	if (card->csd.dsr_imp && host->dsr_req)
+		return sysfs_emit(buf, "0x%x\n", host->dsr);
+	/* return default DSR value */
+	return sysfs_emit(buf, "0x%x\n", 0x404);
 }
 
 static DEVICE_ATTR(dsr, S_IRUGO, mmc_dsr_show, NULL);
@@ -787,11 +792,14 @@
 		return err;
 
 	/*
-	 * In case CCS and S18A in the response is set, start Signal Voltage
-	 * Switch procedure. SPI mode doesn't support CMD11.
+	 * In case the S18A bit is set in the response, let's start the signal
+	 * voltage switch procedure. SPI mode doesn't support CMD11.
+	 * Note that, according to the spec, the S18A bit is not valid unless
+	 * the CCS bit is set as well. We deliberately deviate from the spec in
+	 * regards to this, which allows UHS-I to be supported for SDSC cards.
 	 */
-	if (!mmc_host_is_spi(host) && rocr &&
-	   ((*rocr & 0x41000000) == 0x41000000)) {
+	if (!mmc_host_is_spi(host) && (ocr & SD_OCR_S18R) &&
+	    rocr && (*rocr & SD_ROCR_S18A)) {
 		err = mmc_set_uhs_voltage(host, pocr);
 		if (err == -EAGAIN) {
 			retries--;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/core/sdio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/core/sdio.c
@@ -379,6 +379,8 @@
 	if (card->type == MMC_TYPE_SD_COMBO)
 		max_dtr = min(max_dtr, mmc_sd_get_max_clock(card));
 
+	max_dtr = min_not_zero(max_dtr, card->quirk_max_rate);
+
 	return max_dtr;
 }
 
@@ -584,7 +586,7 @@
 	 */
 	err = mmc_send_io_op_cond(host, ocr, &rocr);
 	if (err)
-		goto err;
+		return err;
 
 	/*
 	 * For SPI, enable CRC as appropriate.
@@ -592,17 +594,15 @@
 	if (mmc_host_is_spi(host)) {
 		err = mmc_spi_set_crc(host, use_spi_crc);
 		if (err)
-			goto err;
+			return err;
 	}
 
 	/*
 	 * Allocate card structure.
 	 */
 	card = mmc_alloc_card(host, NULL);
-	if (IS_ERR(card)) {
-		err = PTR_ERR(card);
-		goto err;
-	}
+	if (IS_ERR(card))
+		return PTR_ERR(card);
 
 	if ((rocr & R4_MEMORY_PRESENT) &&
 	    mmc_sd_get_cid(host, ocr & rocr, card->raw_cid, NULL) == 0) {
@@ -610,19 +610,15 @@
 
 		if (oldcard && (oldcard->type != MMC_TYPE_SD_COMBO ||
 		    memcmp(card->raw_cid, oldcard->raw_cid, sizeof(card->raw_cid)) != 0)) {
-			mmc_remove_card(card);
-			pr_debug("%s: Perhaps the card was replaced\n",
-				mmc_hostname(host));
-			return -ENOENT;
+			err = -ENOENT;
+			goto mismatch;
 		}
 	} else {
 		card->type = MMC_TYPE_SDIO;
 
 		if (oldcard && oldcard->type != MMC_TYPE_SDIO) {
-			mmc_remove_card(card);
-			pr_debug("%s: Perhaps the card was replaced\n",
-				mmc_hostname(host));
-			return -ENOENT;
+			err = -ENOENT;
+			goto mismatch;
 		}
 	}
 
@@ -632,6 +628,8 @@
 	if (host->ops->init_card)
 		host->ops->init_card(host, card);
 
+	card->ocr = ocr_card;
+
 	/*
 	 * If the host and card support UHS-I mode request the card
 	 * to switch to 1.8V signaling level.  No 1.8v signalling if
@@ -677,7 +675,7 @@
 	if (!oldcard && card->type == MMC_TYPE_SD_COMBO) {
 		err = mmc_sd_get_csd(host, card);
 		if (err)
-			return err;
+			goto remove;
 
 		mmc_decode_cid(card);
 	}
@@ -704,7 +702,12 @@
 			mmc_set_timing(card->host, MMC_TIMING_SD_HS);
 		}
 
-		goto finish;
+		if (oldcard)
+			mmc_remove_card(card);
+		else
+			host->card = card;
+
+		return 0;
 	}
 
 	/*
@@ -718,9 +721,8 @@
 			/* Retry init sequence, but without R4_18V_PRESENT. */
 			retries = 0;
 			goto try_again;
-		} else {
-			goto remove;
 		}
+		return err;
 	}
 
 	/*
@@ -731,18 +733,16 @@
 		goto remove;
 
 	if (oldcard) {
-		int same = (card->cis.vendor == oldcard->cis.vendor &&
-			    card->cis.device == oldcard->cis.device);
-		mmc_remove_card(card);
-		if (!same) {
-			pr_debug("%s: Perhaps the card was replaced\n",
-				mmc_hostname(host));
-			return -ENOENT;
+		if (card->cis.vendor == oldcard->cis.vendor &&
+		    card->cis.device == oldcard->cis.device) {
+			mmc_remove_card(card);
+			card = oldcard;
+		} else {
+			err = -ENOENT;
+			goto mismatch;
 		}
-
-		card = oldcard;
 	}
-	card->ocr = ocr_card;
+
 	mmc_fixup_device(card, sdio_fixup_methods);
 
 	if (card->type == MMC_TYPE_SD_COMBO) {
@@ -801,16 +801,15 @@
 		err = -EINVAL;
 		goto remove;
 	}
-finish:
-	if (!oldcard)
-		host->card = card;
+
+	host->card = card;
 	return 0;
 
+mismatch:
+	pr_debug("%s: Perhaps the card was replaced\n", mmc_hostname(host));
 remove:
-	if (!oldcard)
+	if (oldcard != card)
 		mmc_remove_card(card);
-
-err:
 	return err;
 }
 
@@ -929,21 +928,37 @@
  */
 static int mmc_sdio_pre_suspend(struct mmc_host *host)
 {
-	int i, err = 0;
+	int i;
 
 	for (i = 0; i < host->card->sdio_funcs; i++) {
 		struct sdio_func *func = host->card->sdio_func[i];
 		if (func && sdio_func_present(func) && func->dev.driver) {
 			const struct dev_pm_ops *pmops = func->dev.driver->pm;
-			if (!pmops || !pmops->suspend || !pmops->resume) {
+			if (!pmops || !pmops->suspend || !pmops->resume)
 				/* force removal of entire card in that case */
-				err = -ENOSYS;
-				break;
-			}
+				goto remove;
 		}
 	}
 
-	return err;
+	return 0;
+
+remove:
+	if (!mmc_card_is_removable(host)) {
+		dev_warn(mmc_dev(host),
+			 "missing suspend/resume ops for non-removable SDIO card\n");
+		/* Don't remove a non-removable card - we can't re-detect it. */
+		return 0;
+	}
+
+	/* Remove the SDIO card and let it be re-detected later on. */
+	mmc_sdio_remove(host);
+	mmc_claim_host(host);
+	mmc_detach_bus(host);
+	mmc_power_off(host);
+	mmc_release_host(host);
+	host->pm_flags = 0;
+
+	return 0;
 }
 
 /*
@@ -1001,8 +1016,14 @@
 		}
 		err = mmc_sdio_reinit_card(host);
 	} else if (mmc_card_wake_sdio_irq(host)) {
-		/* We may have switched to 1-bit mode during suspend */
+		/*
+		 * We may have switched to 1-bit mode during suspend,
+		 * need to hold retuning, because tuning only supprt
+		 * 4-bit mode or 8 bit mode.
+		 */
+		mmc_retune_hold_now(host);
 		err = sdio_enable_4bit_bus(host->card);
+		mmc_retune_release(host);
 	}
 
 	if (err)
@@ -1048,9 +1069,35 @@
 	return ret;
 }
 
+/*
+ * SDIO HW reset
+ *
+ * Returns 0 if the HW reset was executed synchronously, returns 1 if the HW
+ * reset was asynchronously scheduled, else a negative error code.
+ */
 static int mmc_sdio_hw_reset(struct mmc_host *host)
 {
-	mmc_power_cycle(host, host->card->ocr);
+	struct mmc_card *card = host->card;
+
+	/*
+	 * In case the card is shared among multiple func drivers, reset the
+	 * card through a rescan work. In this way it will be removed and
+	 * re-detected, thus all func drivers becomes informed about it.
+	 */
+	if (atomic_read(&card->sdio_funcs_probed) > 1) {
+		if (mmc_card_removed(card))
+			return 1;
+		host->rescan_entered = 0;
+		mmc_card_set_removed(card);
+		_mmc_detect_change(host, 0, false);
+		return 1;
+	}
+
+	/*
+	 * A single func driver has been probed, then let's skip the heavy
+	 * hotplug dance above and execute the reset immediately.
+	 */
+	mmc_power_cycle(host, card->ocr);
 	return mmc_sdio_reinit_card(host);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/core/sdio_bus.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/core/sdio_bus.c
@@ -14,6 +14,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/pm_domain.h>
 #include <linux/acpi.h>
+#include <linux/sysfs.h>
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
@@ -35,7 +36,7 @@
 	struct sdio_func *func;						\
 									\
 	func = dev_to_sdio_func (dev);					\
-	return sprintf (buf, format_string, func->field);		\
+	return sysfs_emit(buf, format_string, func->field);		\
 }									\
 static DEVICE_ATTR_RO(field)
 
@@ -47,7 +48,7 @@
 {
 	struct sdio_func *func = dev_to_sdio_func (dev);
 
-	return sprintf(buf, "sdio:c%02Xv%04Xd%04X\n",
+	return sysfs_emit(buf, "sdio:c%02Xv%04Xd%04X\n",
 			func->class, func->vendor, func->device);
 }
 static DEVICE_ATTR_RO(modalias);
@@ -138,6 +139,8 @@
 	if (ret)
 		return ret;
 
+	atomic_inc(&func->card->sdio_funcs_probed);
+
 	/* Unbound SDIO functions are always suspended.
 	 * During probe, the function is set active and the usage count
 	 * is incremented.  If the driver supports runtime PM,
@@ -153,7 +156,10 @@
 	/* Set the default block size so the driver is sure it's something
 	 * sensible. */
 	sdio_claim_host(func);
-	ret = sdio_set_block_size(func, 0);
+	if (mmc_card_removed(func->card))
+		ret = -ENOMEDIUM;
+	else
+		ret = sdio_set_block_size(func, 0);
 	sdio_release_host(func);
 	if (ret)
 		goto disable_runtimepm;
@@ -165,6 +171,7 @@
 	return 0;
 
 disable_runtimepm:
+	atomic_dec(&func->card->sdio_funcs_probed);
 	if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
 		pm_runtime_put_noidle(dev);
 	dev_pm_domain_detach(dev, false);
@@ -181,6 +188,7 @@
 		pm_runtime_get_sync(dev);
 
 	drv->remove(func);
+	atomic_dec(&func->card->sdio_funcs_probed);
 
 	if (func->irq_handler) {
 		pr_warn("WARNING: driver %s did not remove its interrupt handler!\n",
@@ -259,7 +267,14 @@
 {
 	struct sdio_func *func = dev_to_sdio_func(dev);
 
-	sdio_free_func_cis(func);
+	if (!(func->card->quirks & MMC_QUIRK_NONSTD_SDIO))
+		sdio_free_func_cis(func);
+
+	/*
+	 * We have now removed the link to the tuples in the
+	 * card structure, so remove the reference.
+	 */
+	put_device(&func->card->dev);
 
 	kfree(func->info);
 	kfree(func->tmpbuf);
@@ -291,6 +306,12 @@
 
 	device_initialize(&func->dev);
 
+	/*
+	 * We may link to tuples in the card structure,
+	 * we need make sure we have a reference to it.
+	 */
+	get_device(&func->card->dev);
+
 	func->dev.parent = &card->dev;
 	func->dev.bus = &sdio_bus_type;
 	func->dev.release = sdio_release_func;
@@ -344,10 +365,9 @@
  */
 void sdio_remove_func(struct sdio_func *func)
 {
-	if (!sdio_func_present(func))
-		return;
+	if (sdio_func_present(func))
+		device_del(&func->dev);
 
-	device_del(&func->dev);
 	of_node_put(func->dev.of_node);
 	put_device(&func->dev);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/core/sdio_cis.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/core/sdio_cis.c
@@ -20,12 +20,17 @@
 #include "sdio_cis.h"
 #include "sdio_ops.h"
 
+#define SDIO_READ_CIS_TIMEOUT_MS  (10 * 1000) /* 10s */
+
 static int cistpl_vers_1(struct mmc_card *card, struct sdio_func *func,
 			 const unsigned char *buf, unsigned size)
 {
 	unsigned i, nr_strings;
 	char **buffer, *string;
 
+	if (size < 2)
+		return 0;
+
 	/* Find all null-terminated (including zero length) strings in
 	   the TPLLV1_INFO field. Trailing garbage is ignored. */
 	buf += 2;
@@ -263,6 +268,8 @@
 
 	do {
 		unsigned char tpl_code, tpl_link;
+		unsigned long timeout = jiffies +
+			msecs_to_jiffies(SDIO_READ_CIS_TIMEOUT_MS);
 
 		ret = mmc_io_rw_direct(card, 0, 0, ptr++, 0, &tpl_code);
 		if (ret)
@@ -315,6 +322,8 @@
 			prev = &this->next;
 
 			if (ret == -ENOENT) {
+				if (time_after(jiffies, timeout))
+					break;
 				/* warn about unknown tuples */
 				pr_warn_ratelimited("%s: queuing unknown"
 				       " CIS tuple 0x%02x (%u bytes)\n",
@@ -375,12 +384,6 @@
 		return ret;
 
 	/*
-	 * Since we've linked to tuples in the card structure,
-	 * we must make sure we have a reference to it.
-	 */
-	get_device(&func->card->dev);
-
-	/*
 	 * Vendor/device id is optional for function CIS, so
 	 * copy it from the card structure as needed.
 	 */
@@ -405,11 +408,5 @@
 	}
 
 	func->tuples = NULL;
-
-	/*
-	 * We have now removed the link to the tuples in the
-	 * card structure, so remove the reference.
-	 */
-	put_device(&func->card->dev);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/core/sdio_ops.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/core/sdio_ops.c
@@ -121,6 +121,7 @@
 	struct sg_table sgtable;
 	unsigned int nents, left_size, i;
 	unsigned int seg_size = card->host->max_seg_size;
+	int err;
 
 	WARN_ON(blksz == 0);
 
@@ -170,28 +171,32 @@
 
 	mmc_set_data_timeout(&data, card);
 
-	mmc_wait_for_req(card->host, &mrq);
+	mmc_pre_req(card->host, &mrq);
 
-	if (nents > 1)
-		sg_free_table(&sgtable);
+	mmc_wait_for_req(card->host, &mrq);
 
 	if (cmd.error)
-		return cmd.error;
-	if (data.error)
-		return data.error;
-
-	if (mmc_host_is_spi(card->host)) {
+		err = cmd.error;
+	else if (data.error)
+		err = data.error;
+	else if (mmc_host_is_spi(card->host))
 		/* host driver already reported errors */
-	} else {
-		if (cmd.resp[0] & R5_ERROR)
-			return -EIO;
-		if (cmd.resp[0] & R5_FUNCTION_NUMBER)
-			return -EINVAL;
-		if (cmd.resp[0] & R5_OUT_OF_RANGE)
-			return -ERANGE;
-	}
+		err = 0;
+	else if (cmd.resp[0] & R5_ERROR)
+		err = -EIO;
+	else if (cmd.resp[0] & R5_FUNCTION_NUMBER)
+		err = -EINVAL;
+	else if (cmd.resp[0] & R5_OUT_OF_RANGE)
+		err = -ERANGE;
+	else
+		err = 0;
+
+	mmc_post_req(card->host, &mrq, err);
+
+	if (nents > 1)
+		sg_free_table(&sgtable);
 
-	return 0;
+	return err;
 }
 
 int sdio_reset(struct mmc_host *host)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/core/slot-gpio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/core/slot-gpio.c
@@ -63,11 +63,15 @@
 int mmc_gpio_get_ro(struct mmc_host *host)
 {
 	struct mmc_gpio *ctx = host->slot.handler_priv;
+	int cansleep;
 
 	if (!ctx || !ctx->ro_gpio)
 		return -ENOSYS;
 
-	return gpiod_get_value_cansleep(ctx->ro_gpio);
+	cansleep = gpiod_cansleep(ctx->ro_gpio);
+	return cansleep ?
+		gpiod_get_value_cansleep(ctx->ro_gpio) :
+		gpiod_get_value(ctx->ro_gpio);
 }
 EXPORT_SYMBOL(mmc_gpio_get_ro);
 
@@ -241,6 +245,9 @@
 			return ret;
 	}
 
+	if (host->caps2 & MMC_CAP2_RO_ACTIVE_HIGH)
+		gpiod_toggle_active_low(desc);
+
 	if (gpio_invert)
 		*gpio_invert = !gpiod_is_active_low(desc);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/Kconfig
@@ -449,7 +449,7 @@
 
 config MMC_WBSD
 	tristate "Winbond W83L51xD SD/MMC Card Interface support"
-	depends on ISA_DMA_API
+	depends on ISA_DMA_API && !M68K
 	help
 	  This selects the Winbond(R) W83L51xD Secure digital and
 	  Multimedia card Interface.
@@ -466,11 +466,12 @@
 	  of Alcor Micro PCI-E card reader
 
 config MMC_AU1X
-	tristate "Alchemy AU1XX0 MMC Card Interface support"
+	bool "Alchemy AU1XX0 MMC Card Interface support"
 	depends on MIPS_ALCHEMY
+	depends on MMC=y
 	help
 	  This selects the AMD Alchemy(R) Multimedia card interface.
-	  If you have a Alchemy platform with a MMC slot, say Y or M here.
+	  If you have a Alchemy platform with a MMC slot, say Y here.
 
 	  If unsure, say N.
 
@@ -995,13 +996,14 @@
 
 config MMC_SDHCI_OMAP
 	tristate "TI SDHCI Controller Support"
+	depends on ARCH_OMAP2PLUS || ARCH_KEYSTONE || COMPILE_TEST
 	depends on MMC_SDHCI_PLTFM && OF
 	select THERMAL
 	imply TI_SOC_THERMAL
 	help
 	  This selects the Secure Digital Host Controller Interface (SDHCI)
-	  support present in TI's DRA7 SOCs. The controller supports
-	  SD/MMC/SDIO devices.
+	  support present in TI's Keystone/OMAP2+/DRA7 SOCs. The controller
+	  supports SD/MMC/SDIO devices.
 
 	  If you have a controller with this interface, say Y or M here.
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/alcor.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/alcor.c
@@ -1104,7 +1104,7 @@
 
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to get irq for data line\n");
-		return ret;
+		goto free_host;
 	}
 
 	mutex_init(&host->cmd_mutex);
@@ -1114,8 +1114,15 @@
 	alcor_hw_init(host);
 
 	dev_set_drvdata(&pdev->dev, host);
-	mmc_add_host(mmc);
+	ret = mmc_add_host(mmc);
+	if (ret)
+		goto free_host;
+
 	return 0;
+
+free_host:
+	mmc_free_host(mmc);
+	return ret;
 }
 
 static int alcor_pci_sdmmc_drv_remove(struct platform_device *pdev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/atmel-mci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/atmel-mci.c
@@ -1812,7 +1812,6 @@
 				atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
 				state = STATE_WAITING_NOTBUSY;
 			} else if (host->mrq->stop) {
-				atmci_writel(host, ATMCI_IER, ATMCI_CMDRDY);
 				atmci_send_stop_cmd(host, data);
 				state = STATE_SENDING_STOP;
 			} else {
@@ -1845,8 +1844,6 @@
 				 * command to send.
 				 */
 				if (host->mrq->stop) {
-					atmci_writel(host, ATMCI_IER,
-					             ATMCI_CMDRDY);
 					atmci_send_stop_cmd(host, data);
 					state = STATE_SENDING_STOP;
 				} else {
@@ -2217,6 +2214,7 @@
 {
 	struct mmc_host			*mmc;
 	struct atmel_mci_slot		*slot;
+	int ret;
 
 	mmc = mmc_alloc_host(sizeof(struct atmel_mci_slot), &host->pdev->dev);
 	if (!mmc)
@@ -2300,11 +2298,13 @@
 
 	host->slot[id] = slot;
 	mmc_regulator_get_supply(mmc);
-	mmc_add_host(mmc);
+	ret = mmc_add_host(mmc);
+	if (ret) {
+		mmc_free_host(mmc);
+		return ret;
+	}
 
 	if (gpio_is_valid(slot->detect_pin)) {
-		int ret;
-
 		timer_setup(&slot->detect_timer, atmci_detect_change, 0);
 
 		ret = request_irq(gpio_to_irq(slot->detect_pin),
@@ -2502,8 +2502,10 @@
 	/* Get MCI capabilities and set operations according to it */
 	atmci_get_cap(host);
 	ret = atmci_configure_dma(host);
-	if (ret == -EPROBE_DEFER)
+	if (ret == -EPROBE_DEFER) {
+		clk_disable_unprepare(host->mck);
 		goto err_dma_probe_defer;
+	}
 	if (ret == 0) {
 		host->prepare_data = &atmci_prepare_data_dma;
 		host->submit_data = &atmci_submit_data_dma;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/au1xmmc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/au1xmmc.c
@@ -1116,8 +1116,9 @@
 	if (host->platdata && host->platdata->cd_setup &&
 	    !(mmc->caps & MMC_CAP_NEEDS_POLL))
 		host->platdata->cd_setup(mmc, 0);
-out_clk:
+
 	clk_disable_unprepare(host->clk);
+out_clk:
 	clk_put(host->clk);
 out_irq:
 	free_irq(host->irq, host);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/bcm2835.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/bcm2835.c
@@ -1408,8 +1408,8 @@
 	host->max_clk = clk_get_rate(clk);
 
 	host->irq = platform_get_irq(pdev, 0);
-	if (host->irq <= 0) {
-		ret = -EINVAL;
+	if (host->irq < 0) {
+		ret = host->irq;
 		goto err;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/cavium-octeon.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/cavium-octeon.c
@@ -288,6 +288,7 @@
 		if (ret) {
 			dev_err(&pdev->dev, "Error populating slots\n");
 			octeon_mmc_set_shared_power(host, 0);
+			of_node_put(cn);
 			goto error;
 		}
 		i++;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/cavium-thunderx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/cavium-thunderx.c
@@ -138,8 +138,10 @@
 				continue;
 
 			ret = cvm_mmc_of_slot_probe(&host->slot_pdev[i]->dev, host);
-			if (ret)
+			if (ret) {
+				of_node_put(child_node);
 				goto error;
+			}
 		}
 		i++;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/cqhci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/cqhci.c
@@ -5,6 +5,7 @@
 #include <linux/delay.h>
 #include <linux/highmem.h>
 #include <linux/io.h>
+#include <linux/iopoll.h>
 #include <linux/module.h>
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
@@ -272,6 +273,9 @@
 
 	cqhci_writel(cq_host, cqcfg, CQHCI_CFG);
 
+	if (cqhci_readl(cq_host, CQHCI_CTL) & CQHCI_HALT)
+		cqhci_writel(cq_host, 0, CQHCI_CTL);
+
 	mmc->cqe_on = true;
 
 	if (cq_host->ops->enable)
@@ -298,16 +302,16 @@
 	cq_host->activated = false;
 }
 
-int cqhci_suspend(struct mmc_host *mmc)
+int cqhci_deactivate(struct mmc_host *mmc)
 {
 	struct cqhci_host *cq_host = mmc->cqe_private;
 
-	if (cq_host->enabled)
+	if (cq_host->enabled && cq_host->activated)
 		__cqhci_disable(cq_host);
 
 	return 0;
 }
-EXPORT_SYMBOL(cqhci_suspend);
+EXPORT_SYMBOL(cqhci_deactivate);
 
 int cqhci_resume(struct mmc_host *mmc)
 {
@@ -343,12 +347,16 @@
 /* CQHCI is idle and should halt immediately, so set a small timeout */
 #define CQHCI_OFF_TIMEOUT 100
 
+static u32 cqhci_read_ctl(struct cqhci_host *cq_host)
+{
+	return cqhci_readl(cq_host, CQHCI_CTL);
+}
+
 static void cqhci_off(struct mmc_host *mmc)
 {
 	struct cqhci_host *cq_host = mmc->cqe_private;
-	ktime_t timeout;
-	bool timed_out;
 	u32 reg;
+	int err;
 
 	if (!cq_host->enabled || !mmc->cqe_on || cq_host->recovery_halt)
 		return;
@@ -358,15 +366,9 @@
 
 	cqhci_writel(cq_host, CQHCI_HALT, CQHCI_CTL);
 
-	timeout = ktime_add_us(ktime_get(), CQHCI_OFF_TIMEOUT);
-	while (1) {
-		timed_out = ktime_compare(ktime_get(), timeout) > 0;
-		reg = cqhci_readl(cq_host, CQHCI_CTL);
-		if ((reg & CQHCI_HALT) || timed_out)
-			break;
-	}
-
-	if (timed_out)
+	err = readx_poll_timeout(cqhci_read_ctl, cq_host, reg,
+				 reg & CQHCI_HALT, 0, CQHCI_OFF_TIMEOUT);
+	if (err < 0)
 		pr_err("%s: cqhci: CQE stuck on\n", mmc_hostname(mmc));
 	else
 		pr_debug("%s: cqhci: CQE off\n", mmc_hostname(mmc));
@@ -876,8 +878,8 @@
 	ret = cqhci_tasks_cleared(cq_host);
 
 	if (!ret)
-		pr_debug("%s: cqhci: Failed to clear tasks\n",
-			 mmc_hostname(mmc));
+		pr_warn("%s: cqhci: Failed to clear tasks\n",
+			mmc_hostname(mmc));
 
 	return ret;
 }
@@ -910,7 +912,7 @@
 	ret = cqhci_halted(cq_host);
 
 	if (!ret)
-		pr_debug("%s: cqhci: Failed to halt\n", mmc_hostname(mmc));
+		pr_warn("%s: cqhci: Failed to halt\n", mmc_hostname(mmc));
 
 	return ret;
 }
@@ -918,10 +920,10 @@
 /*
  * After halting we expect to be able to use the command line. We interpret the
  * failure to halt to mean the data lines might still be in use (and the upper
- * layers will need to send a STOP command), so we set the timeout based on a
- * generous command timeout.
+ * layers will need to send a STOP command), however failing to halt complicates
+ * the recovery, so set a timeout that would reasonably allow I/O to complete.
  */
-#define CQHCI_START_HALT_TIMEOUT	5
+#define CQHCI_START_HALT_TIMEOUT	500
 
 static void cqhci_recovery_start(struct mmc_host *mmc)
 {
@@ -1009,28 +1011,28 @@
 
 	ok = cqhci_halt(mmc, CQHCI_FINISH_HALT_TIMEOUT);
 
-	if (!cqhci_clear_all_tasks(mmc, CQHCI_CLEAR_TIMEOUT))
-		ok = false;
-
 	/*
 	 * The specification contradicts itself, by saying that tasks cannot be
 	 * cleared if CQHCI does not halt, but if CQHCI does not halt, it should
 	 * be disabled/re-enabled, but not to disable before clearing tasks.
 	 * Have a go anyway.
 	 */
-	if (!ok) {
-		pr_debug("%s: cqhci: disable / re-enable\n", mmc_hostname(mmc));
-		cqcfg = cqhci_readl(cq_host, CQHCI_CFG);
-		cqcfg &= ~CQHCI_ENABLE;
-		cqhci_writel(cq_host, cqcfg, CQHCI_CFG);
-		cqcfg |= CQHCI_ENABLE;
-		cqhci_writel(cq_host, cqcfg, CQHCI_CFG);
-		/* Be sure that there are no tasks */
-		ok = cqhci_halt(mmc, CQHCI_FINISH_HALT_TIMEOUT);
-		if (!cqhci_clear_all_tasks(mmc, CQHCI_CLEAR_TIMEOUT))
-			ok = false;
-		WARN_ON(!ok);
-	}
+	if (!cqhci_clear_all_tasks(mmc, CQHCI_CLEAR_TIMEOUT))
+		ok = false;
+
+	/* Disable to make sure tasks really are cleared */
+	cqcfg = cqhci_readl(cq_host, CQHCI_CFG);
+	cqcfg &= ~CQHCI_ENABLE;
+	cqhci_writel(cq_host, cqcfg, CQHCI_CFG);
+
+	cqcfg = cqhci_readl(cq_host, CQHCI_CFG);
+	cqcfg |= CQHCI_ENABLE;
+	cqhci_writel(cq_host, cqcfg, CQHCI_CFG);
+
+	cqhci_halt(mmc, CQHCI_FINISH_HALT_TIMEOUT);
+
+	if (!ok)
+		cqhci_clear_all_tasks(mmc, CQHCI_CLEAR_TIMEOUT);
 
 	cqhci_recover_mrqs(cq_host);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/cqhci.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/cqhci.h
@@ -230,7 +230,11 @@
 		      int data_error);
 int cqhci_init(struct cqhci_host *cq_host, struct mmc_host *mmc, bool dma64);
 struct cqhci_host *cqhci_pltfm_init(struct platform_device *pdev);
-int cqhci_suspend(struct mmc_host *mmc);
+int cqhci_deactivate(struct mmc_host *mmc);
+static inline int cqhci_suspend(struct mmc_host *mmc)
+{
+	return cqhci_deactivate(mmc);
+}
 int cqhci_resume(struct mmc_host *mmc);
 
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/davinci_mmc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/davinci_mmc.c
@@ -1348,7 +1348,7 @@
 	return ret;
 }
 
-static int __exit davinci_mmcsd_remove(struct platform_device *pdev)
+static int davinci_mmcsd_remove(struct platform_device *pdev)
 {
 	struct mmc_davinci_host *host = platform_get_drvdata(pdev);
 
@@ -1376,8 +1376,12 @@
 static int davinci_mmcsd_resume(struct device *dev)
 {
 	struct mmc_davinci_host *host = dev_get_drvdata(dev);
+	int ret;
+
+	ret = clk_enable(host->clk);
+	if (ret)
+		return ret;
 
-	clk_enable(host->clk);
 	mmc_davinci_reset_ctrl(host, 0);
 
 	return 0;
@@ -1400,7 +1404,7 @@
 		.of_match_table = davinci_mmc_dt_ids,
 	},
 	.probe		= davinci_mmcsd_probe,
-	.remove		= __exit_p(davinci_mmcsd_remove),
+	.remove		= davinci_mmcsd_remove,
 	.id_table	= davinci_mmc_devtype,
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/dw_mmc-exynos.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/dw_mmc-exynos.c
@@ -462,6 +462,18 @@
 		}
 	}
 
+	/*
+	 * If there is no cadiates value, then it needs to return -EIO.
+	 * If there are candiates values and don't find bset clk sample value,
+	 * then use a first candiates clock sample value.
+	 */
+	for (i = 0; i < iter; i++) {
+		__c = ror8(candiates, i);
+		if ((__c & 0x1) == 0x1) {
+			loc = i;
+			goto out;
+		}
+	}
 out:
 	return loc;
 }
@@ -492,6 +504,8 @@
 		priv->tuned_sample = found;
 	} else {
 		ret = -EIO;
+		dev_warn(&mmc->class_dev,
+			"There is no candiates value about clksmpl!\n");
 	}
 
 	return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/dw_mmc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/dw_mmc.c
@@ -782,6 +782,7 @@
 	int ret = 0;
 
 	/* Set external dma config: burst size, burst width */
+	memset(&cfg, 0, sizeof(cfg));
 	cfg.dst_addr = host->phy_regs + fifo_offset;
 	cfg.src_addr = cfg.dst_addr;
 	cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
@@ -2012,13 +2013,14 @@
 				 * delayed. Allowing the transfer to take place
 				 * avoids races and keeps things simple.
 				 */
-				if (err != -ETIMEDOUT) {
+				if (err != -ETIMEDOUT &&
+				    host->dir_status == DW_MCI_RECV_STATUS) {
 					state = STATE_SENDING_DATA;
 					continue;
 				}
 
-				dw_mci_stop_dma(host);
 				send_stop_abort(host, data);
+				dw_mci_stop_dma(host);
 				state = STATE_SENDING_STOP;
 				break;
 			}
@@ -2042,10 +2044,10 @@
 			 */
 			if (test_and_clear_bit(EVENT_DATA_ERROR,
 					       &host->pending_events)) {
-				dw_mci_stop_dma(host);
 				if (!(host->data_status & (SDMMC_INT_DRTO |
 							   SDMMC_INT_EBE)))
 					send_stop_abort(host, data);
+				dw_mci_stop_dma(host);
 				state = STATE_DATA_ERROR;
 				break;
 			}
@@ -2078,10 +2080,10 @@
 			 */
 			if (test_and_clear_bit(EVENT_DATA_ERROR,
 					       &host->pending_events)) {
-				dw_mci_stop_dma(host);
 				if (!(host->data_status & (SDMMC_INT_DRTO |
 							   SDMMC_INT_EBE)))
 					send_stop_abort(host, data);
+				dw_mci_stop_dma(host);
 				state = STATE_DATA_ERROR;
 				break;
 			}
@@ -3177,6 +3179,10 @@
 	host->biu_clk = devm_clk_get(host->dev, "biu");
 	if (IS_ERR(host->biu_clk)) {
 		dev_dbg(host->dev, "biu clock not available\n");
+		ret = PTR_ERR(host->biu_clk);
+		if (ret == -EPROBE_DEFER)
+			return ret;
+
 	} else {
 		ret = clk_prepare_enable(host->biu_clk);
 		if (ret) {
@@ -3188,6 +3194,10 @@
 	host->ciu_clk = devm_clk_get(host->dev, "ciu");
 	if (IS_ERR(host->ciu_clk)) {
 		dev_dbg(host->dev, "ciu clock not available\n");
+		ret = PTR_ERR(host->ciu_clk);
+		if (ret == -EPROBE_DEFER)
+			goto err_clk_biu;
+
 		host->bus_hz = host->pdata->bus_hz;
 	} else {
 		ret = clk_prepare_enable(host->ciu_clk);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/jz4740_mmc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/jz4740_mmc.c
@@ -224,6 +224,26 @@
 		return PTR_ERR(host->dma_rx);
 	}
 
+	/*
+	 * Limit the maximum segment size in any SG entry according to
+	 * the parameters of the DMA engine device.
+	 */
+	if (host->dma_tx) {
+		struct device *dev = host->dma_tx->device->dev;
+		unsigned int max_seg_size = dma_get_max_seg_size(dev);
+
+		if (max_seg_size < host->mmc->max_seg_size)
+			host->mmc->max_seg_size = max_seg_size;
+	}
+
+	if (host->dma_rx) {
+		struct device *dev = host->dma_rx->device->dev;
+		unsigned int max_seg_size = dma_get_max_seg_size(dev);
+
+		if (max_seg_size < host->mmc->max_seg_size)
+			host->mmc->max_seg_size = max_seg_size;
+	}
+
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/meson-gx-mmc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/meson-gx-mmc.c
@@ -166,6 +166,7 @@
 
 	unsigned int bounce_buf_size;
 	void *bounce_buf;
+	void __iomem *bounce_iomem_buf;
 	dma_addr_t bounce_dma_addr;
 	struct sd_emmc_desc *descs;
 	dma_addr_t descs_dma_addr;
@@ -173,6 +174,8 @@
 	int irq;
 
 	bool vqmmc_enabled;
+	bool needs_pre_post_req;
+
 };
 
 #define CMD_CFG_LENGTH_MASK GENMASK(8, 0)
@@ -654,6 +657,8 @@
 	struct meson_host *host = mmc_priv(mmc);
 
 	host->cmd = NULL;
+	if (host->needs_pre_post_req)
+		meson_mmc_post_req(mmc, mrq, 0);
 	mmc_request_done(host->mmc, mrq);
 }
 
@@ -737,6 +742,53 @@
 	writel(start, host->regs + SD_EMMC_START);
 }
 
+/* local sg copy for dram_access_quirk */
+static void meson_mmc_copy_buffer(struct meson_host *host, struct mmc_data *data,
+				  size_t buflen, bool to_buffer)
+{
+	unsigned int sg_flags = SG_MITER_ATOMIC;
+	struct scatterlist *sgl = data->sg;
+	unsigned int nents = data->sg_len;
+	struct sg_mapping_iter miter;
+	unsigned int offset = 0;
+
+	if (to_buffer)
+		sg_flags |= SG_MITER_FROM_SG;
+	else
+		sg_flags |= SG_MITER_TO_SG;
+
+	sg_miter_start(&miter, sgl, nents, sg_flags);
+
+	while ((offset < buflen) && sg_miter_next(&miter)) {
+		unsigned int buf_offset = 0;
+		unsigned int len, left;
+		u32 *buf = miter.addr;
+
+		len = min(miter.length, buflen - offset);
+		left = len;
+
+		if (to_buffer) {
+			do {
+				writel(*buf++, host->bounce_iomem_buf + offset + buf_offset);
+
+				buf_offset += 4;
+				left -= 4;
+			} while (left);
+		} else {
+			do {
+				*buf++ = readl(host->bounce_iomem_buf + offset + buf_offset);
+
+				buf_offset += 4;
+				left -= 4;
+			} while (left);
+		}
+
+		offset += len;
+	}
+
+	sg_miter_stop(&miter);
+}
+
 static void meson_mmc_start_cmd(struct mmc_host *mmc, struct mmc_command *cmd)
 {
 	struct meson_host *host = mmc_priv(mmc);
@@ -751,7 +803,6 @@
 
 	cmd_cfg |= FIELD_PREP(CMD_CFG_CMD_INDEX_MASK, cmd->opcode);
 	cmd_cfg |= CMD_CFG_OWNER;  /* owned by CPU */
-	cmd_cfg |= CMD_CFG_ERROR; /* stop in case of error */
 
 	meson_mmc_set_response_bits(cmd, &cmd_cfg);
 
@@ -780,8 +831,11 @@
 		if (data->flags & MMC_DATA_WRITE) {
 			cmd_cfg |= CMD_CFG_DATA_WR;
 			WARN_ON(xfer_bytes > host->bounce_buf_size);
-			sg_copy_to_buffer(data->sg, data->sg_len,
-					  host->bounce_buf, xfer_bytes);
+			if (host->dram_access_quirk)
+				meson_mmc_copy_buffer(host, data, xfer_bytes, true);
+			else
+				sg_copy_to_buffer(data->sg, data->sg_len,
+						  host->bounce_buf, xfer_bytes);
 			dma_wmb();
 		}
 
@@ -800,28 +854,56 @@
 	writel(cmd->arg, host->regs + SD_EMMC_CMD_ARG);
 }
 
+static int meson_mmc_validate_dram_access(struct mmc_host *mmc, struct mmc_data *data)
+{
+	struct scatterlist *sg;
+	int i;
+
+	/* Reject request if any element offset or size is not 32bit aligned */
+	for_each_sg(data->sg, sg, data->sg_len, i) {
+		if (!IS_ALIGNED(sg->offset, sizeof(u32)) ||
+		    !IS_ALIGNED(sg->length, sizeof(u32))) {
+			dev_err(mmc_dev(mmc), "unaligned sg offset %u len %u\n",
+				data->sg->offset, data->sg->length);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
 static void meson_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
 {
 	struct meson_host *host = mmc_priv(mmc);
-	bool needs_pre_post_req = mrq->data &&
+	host->needs_pre_post_req = mrq->data &&
 			!(mrq->data->host_cookie & SD_EMMC_PRE_REQ_DONE);
 
-	if (needs_pre_post_req) {
+	/*
+	 * The memory at the end of the controller used as bounce buffer for
+	 * the dram_access_quirk only accepts 32bit read/write access,
+	 * check the aligment and length of the data before starting the request.
+	 */
+	if (host->dram_access_quirk && mrq->data) {
+		mrq->cmd->error = meson_mmc_validate_dram_access(mmc, mrq->data);
+		if (mrq->cmd->error) {
+			mmc_request_done(mmc, mrq);
+			return;
+		}
+	}
+
+	if (host->needs_pre_post_req) {
 		meson_mmc_get_transfer_mode(mmc, mrq);
 		if (!meson_mmc_desc_chain_mode(mrq->data))
-			needs_pre_post_req = false;
+			host->needs_pre_post_req = false;
 	}
 
-	if (needs_pre_post_req)
+	if (host->needs_pre_post_req)
 		meson_mmc_pre_req(mmc, mrq);
 
 	/* Stop execution */
 	writel(0, host->regs + SD_EMMC_START);
 
 	meson_mmc_start_cmd(mmc, mrq->sbc ?: mrq->cmd);
-
-	if (needs_pre_post_req)
-		meson_mmc_post_req(mmc, mrq, 0);
 }
 
 static void meson_mmc_read_resp(struct mmc_host *mmc, struct mmc_command *cmd)
@@ -890,11 +972,8 @@
 	if (status & (IRQ_END_OF_CHAIN | IRQ_RESP_STATUS)) {
 		if (data && !cmd->error)
 			data->bytes_xfered = data->blksz * data->blocks;
-		if (meson_mmc_bounce_buf_read(data) ||
-		    meson_mmc_get_next_command(cmd))
-			ret = IRQ_WAKE_THREAD;
-		else
-			ret = IRQ_HANDLED;
+
+		return IRQ_WAKE_THREAD;
 	}
 
 out:
@@ -906,9 +985,6 @@
 		writel(start, host->regs + SD_EMMC_START);
 	}
 
-	if (ret == IRQ_HANDLED)
-		meson_mmc_request_done(host->mmc, cmd->mrq);
-
 	return ret;
 }
 
@@ -950,8 +1026,11 @@
 	if (meson_mmc_bounce_buf_read(data)) {
 		xfer_bytes = data->blksz * data->blocks;
 		WARN_ON(xfer_bytes > host->bounce_buf_size);
-		sg_copy_from_buffer(data->sg, data->sg_len,
-				    host->bounce_buf, xfer_bytes);
+		if (host->dram_access_quirk)
+			meson_mmc_copy_buffer(host, data, xfer_bytes, false);
+		else
+			sg_copy_from_buffer(data->sg, data->sg_len,
+					    host->bounce_buf, xfer_bytes);
 	}
 
 	next_cmd = meson_mmc_get_next_command(cmd);
@@ -1151,9 +1230,11 @@
 
 	mmc->caps |= MMC_CAP_CMD23;
 	if (host->dram_access_quirk) {
+		/* Limit segments to 1 due to low available sram memory */
+		mmc->max_segs = 1;
 		/* Limit to the available sram memory */
-		mmc->max_segs = SD_EMMC_SRAM_DATA_BUF_LEN / mmc->max_blk_size;
-		mmc->max_blk_count = mmc->max_segs;
+		mmc->max_blk_count = SD_EMMC_SRAM_DATA_BUF_LEN /
+				     mmc->max_blk_size;
 	} else {
 		mmc->max_blk_count = CMD_CFG_LENGTH_MASK;
 		mmc->max_segs = SD_EMMC_DESC_BUF_LEN /
@@ -1177,7 +1258,7 @@
 		 * instead of the DDR memory
 		 */
 		host->bounce_buf_size = SD_EMMC_SRAM_DATA_BUF_LEN;
-		host->bounce_buf = host->regs + SD_EMMC_SRAM_DATA_BUF_OFF;
+		host->bounce_iomem_buf = host->regs + SD_EMMC_SRAM_DATA_BUF_OFF;
 		host->bounce_dma_addr = res->start + SD_EMMC_SRAM_DATA_BUF_OFF;
 	} else {
 		/* data bounce buffer */
@@ -1201,7 +1282,9 @@
 	}
 
 	mmc->ops = &meson_mmc_ops;
-	mmc_add_host(mmc);
+	ret = mmc_add_host(mmc);
+	if (ret)
+		goto err_free_irq;
 
 	return 0;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/meson-mx-sdio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/meson-mx-sdio.c
@@ -246,6 +246,9 @@
 
 	mrq = host->mrq;
 
+	if (host->cmd->error)
+		meson_mx_mmc_soft_reset(host);
+
 	host->mrq = NULL;
 	host->cmd = NULL;
 
@@ -357,14 +360,6 @@
 		meson_mx_mmc_start_cmd(mmc, mrq->cmd);
 }
 
-static int meson_mx_mmc_card_busy(struct mmc_host *mmc)
-{
-	struct meson_mx_mmc_host *host = mmc_priv(mmc);
-	u32 irqc = readl(host->base + MESON_MX_SDIO_IRQC);
-
-	return !!(irqc & MESON_MX_SDIO_IRQC_FORCE_DATA_DAT_MASK);
-}
-
 static void meson_mx_mmc_read_response(struct mmc_host *mmc,
 				       struct mmc_command *cmd)
 {
@@ -506,7 +501,6 @@
 static struct mmc_host_ops meson_mx_mmc_ops = {
 	.request		= meson_mx_mmc_request,
 	.set_ios		= meson_mx_mmc_set_ios,
-	.card_busy		= meson_mx_mmc_card_busy,
 	.get_cd			= mmc_gpio_get_cd,
 	.get_ro			= mmc_gpio_get_ro,
 };
@@ -570,7 +564,7 @@
 	mmc->f_max = clk_round_rate(host->cfg_div_clk,
 				    clk_get_rate(host->parent_clk));
 
-	mmc->caps |= MMC_CAP_ERASE | MMC_CAP_CMD23;
+	mmc->caps |= MMC_CAP_ERASE | MMC_CAP_CMD23 | MMC_CAP_WAIT_WHILE_BUSY;
 	mmc->ops = &meson_mx_mmc_ops;
 
 	ret = mmc_of_parse(mmc);
@@ -671,6 +665,11 @@
 	}
 
 	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		ret = irq;
+		goto error_free_mmc;
+	}
+
 	ret = devm_request_threaded_irq(host->controller_dev, irq,
 					meson_mx_mmc_irq,
 					meson_mx_mmc_irq_thread, IRQF_ONESHOT,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/mmc_spi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/mmc_spi.c
@@ -255,10 +255,6 @@
 	u8 	leftover = 0;
 	unsigned short rotator;
 	int 	i;
-	char	tag[32];
-
-	snprintf(tag, sizeof(tag), "  ... CMD%d response SPI_%s",
-		cmd->opcode, maptype(cmd));
 
 	/* Except for data block reads, the whole response will already
 	 * be stored in the scratch buffer.  It's somewhere after the
@@ -408,8 +404,9 @@
 	}
 
 	if (value < 0)
-		dev_dbg(&host->spi->dev, "%s: resp %04x %08x\n",
-			tag, cmd->resp[0], cmd->resp[1]);
+		dev_dbg(&host->spi->dev,
+			"  ... CMD%d response SPI_%s: resp %04x %08x\n",
+			cmd->opcode, maptype(cmd), cmd->resp[0], cmd->resp[1]);
 
 	/* disable chipselect on errors and some success cases */
 	if (value >= 0 && cs_on)
@@ -1134,17 +1131,22 @@
 	 * SPI protocol.  Another is that when chipselect is released while
 	 * the card returns BUSY status, the clock must issue several cycles
 	 * with chipselect high before the card will stop driving its output.
+	 *
+	 * SPI_CS_HIGH means "asserted" here. In some cases like when using
+	 * GPIOs for chip select, SPI_CS_HIGH is set but this will be logically
+	 * inverted by gpiolib, so if we want to ascertain to drive it high
+	 * we should toggle the default with an XOR as we do here.
 	 */
-	host->spi->mode |= SPI_CS_HIGH;
+	host->spi->mode ^= SPI_CS_HIGH;
 	if (spi_setup(host->spi) != 0) {
 		/* Just warn; most cards work without it. */
 		dev_warn(&host->spi->dev,
 				"can't change chip-select polarity\n");
-		host->spi->mode &= ~SPI_CS_HIGH;
+		host->spi->mode ^= SPI_CS_HIGH;
 	} else {
 		mmc_spi_readbytes(host, 18);
 
-		host->spi->mode &= ~SPI_CS_HIGH;
+		host->spi->mode ^= SPI_CS_HIGH;
 		if (spi_setup(host->spi) != 0) {
 			/* Wot, we can't get the same setup we had before? */
 			dev_err(&host->spi->dev,
@@ -1415,7 +1417,7 @@
 
 	status = mmc_add_host(mmc);
 	if (status != 0)
-		goto fail_add_host;
+		goto fail_glue_init;
 
 	/*
 	 * Index 0 is card detect
@@ -1423,7 +1425,7 @@
 	 */
 	status = mmc_gpiod_request_cd(mmc, NULL, 0, false, 1, NULL);
 	if (status == -EPROBE_DEFER)
-		goto fail_add_host;
+		goto fail_gpiod_request;
 	if (!status) {
 		/*
 		 * The platform has a CD GPIO signal that may support
@@ -1438,7 +1440,7 @@
 	/* Index 1 is write protect/read only */
 	status = mmc_gpiod_request_ro(mmc, NULL, 1, 0, NULL);
 	if (status == -EPROBE_DEFER)
-		goto fail_add_host;
+		goto fail_gpiod_request;
 	if (!status)
 		has_ro = true;
 
@@ -1452,7 +1454,7 @@
 				? ", cd polling" : "");
 	return 0;
 
-fail_add_host:
+fail_gpiod_request:
 	mmc_remove_host(mmc);
 fail_glue_init:
 	if (host->dma_dev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/mmci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/mmci.c
@@ -168,6 +168,8 @@
 	.cmdreg_srsp		= MCI_CPSM_RESPONSE,
 	.datalength_bits	= 24,
 	.datactrl_blocksz	= 11,
+	.datactrl_any_blocksz	= true,
+	.dma_power_of_2		= true,
 	.datactrl_mask_sdio	= MCI_DPSM_ST_SDIOEN,
 	.st_sdio		= true,
 	.st_clkdiv		= true,
@@ -201,6 +203,8 @@
 	.datactrl_mask_ddrmode	= MCI_DPSM_ST_DDRMODE,
 	.datalength_bits	= 24,
 	.datactrl_blocksz	= 11,
+	.datactrl_any_blocksz	= true,
+	.dma_power_of_2		= true,
 	.datactrl_mask_sdio	= MCI_DPSM_ST_SDIOEN,
 	.st_sdio		= true,
 	.st_clkdiv		= true,
@@ -260,6 +264,7 @@
 	.datacnt_useless	= true,
 	.datalength_bits	= 25,
 	.datactrl_blocksz	= 14,
+	.datactrl_any_blocksz	= true,
 	.stm32_idmabsize_mask	= GENMASK(12, 5),
 	.init			= sdmmc_variant_init,
 };
@@ -279,6 +284,7 @@
 	.data_cmd_enable	= MCI_CPSM_QCOM_DATCMD,
 	.datalength_bits	= 24,
 	.datactrl_blocksz	= 11,
+	.datactrl_any_blocksz	= true,
 	.pwrreg_powerup		= MCI_PWR_UP,
 	.f_max			= 208000000,
 	.explicit_mclk_control	= true,
@@ -447,10 +453,11 @@
 static int mmci_validate_data(struct mmci_host *host,
 			      struct mmc_data *data)
 {
+	struct variant_data *variant = host->variant;
+
 	if (!data)
 		return 0;
-
-	if (!is_power_of_2(data->blksz)) {
+	if (!is_power_of_2(data->blksz) && !variant->datactrl_any_blocksz) {
 		dev_err(mmc_dev(host->mmc),
 			"unsupported block size (%d bytes)\n", data->blksz);
 		return -EINVAL;
@@ -515,7 +522,9 @@
 		 "Submit MMCI DMA job, sglen %d blksz %04x blks %04x flags %08x\n",
 		 data->sg_len, data->blksz, data->blocks, data->flags);
 
-	host->ops->dma_start(host, &datactrl);
+	ret = host->ops->dma_start(host, &datactrl);
+	if (ret)
+		return ret;
 
 	/* Trigger the DMA transfer */
 	mmci_write_datactrlreg(host, datactrl);
@@ -822,6 +831,18 @@
 	if (data->blksz * data->blocks <= variant->fifosize)
 		return -EINVAL;
 
+	/*
+	 * This is necessary to get SDIO working on the Ux500. We do not yet
+	 * know if this is a bug in:
+	 * - The Ux500 DMA controller (DMA40)
+	 * - The MMCI DMA interface on the Ux500
+	 * some power of two blocks (such as 64 bytes) are sent regularly
+	 * during SDIO traffic and those work fine so for these we enable DMA
+	 * transfers.
+	 */
+	if (host->variant->dma_power_of_2 && !is_power_of_2(data->blksz))
+		return -EINVAL;
+
 	device = chan->device;
 	nr_sg = dma_map_sg(device->dev, data->sg, data->sg_len,
 			   mmc_get_dma_dir(data));
@@ -872,9 +893,14 @@
 int mmci_dmae_start(struct mmci_host *host, unsigned int *datactrl)
 {
 	struct mmci_dmae_priv *dmae = host->dma_priv;
+	int ret;
 
 	host->dma_in_progress = true;
-	dmaengine_submit(dmae->desc_current);
+	ret = dma_submit_error(dmaengine_submit(dmae->desc_current));
+	if (ret < 0) {
+		host->dma_in_progress = false;
+		return ret;
+	}
 	dma_async_issue_pending(dmae->cur);
 
 	*datactrl |= MCI_DPSM_DMAENABLE;
@@ -2053,7 +2079,9 @@
 	pm_runtime_set_autosuspend_delay(&dev->dev, 50);
 	pm_runtime_use_autosuspend(&dev->dev);
 
-	mmc_add_host(mmc);
+	ret = mmc_add_host(mmc);
+	if (ret)
+		goto clk_disable;
 
 	pm_runtime_put(&dev->dev);
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/mmci.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/mmci.h
@@ -278,7 +278,11 @@
  * @stm32_clkdiv: true if using a STM32-specific clock divider algorithm
  * @datactrl_mask_ddrmode: ddr mode mask in datactrl register.
  * @datactrl_mask_sdio: SDIO enable mask in datactrl register
- * @datactrl_blksz: block size in power of two
+ * @datactrl_blocksz: block size in power of two
+ * @datactrl_any_blocksz: true if block any block sizes are accepted by
+ *		  hardware, such as with some SDIO traffic that send
+ *		  odd packets.
+ * @dma_power_of_2: DMA only works with blocks that are a power of 2.
  * @datactrl_first: true if data must be setup before send command
  * @datacnt_useless: true if you could not use datacnt register to read
  *		     remaining data
@@ -323,6 +327,8 @@
 	unsigned int		datactrl_mask_ddrmode;
 	unsigned int		datactrl_mask_sdio;
 	unsigned int		datactrl_blocksz;
+	u8			datactrl_any_blocksz:1;
+	u8			dma_power_of_2:1;
 	u8			datactrl_first:1;
 	u8			datacnt_useless:1;
 	u8			st_sdio:1;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/mmci_stm32_sdmmc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/mmci_stm32_sdmmc.c
@@ -20,14 +20,19 @@
 	u32 idmasize;
 };
 
-struct sdmmc_priv {
+struct sdmmc_idma {
 	dma_addr_t sg_dma;
 	void *sg_cpu;
+	dma_addr_t bounce_dma_addr;
+	void *bounce_buf;
+	bool use_bounce_buffer;
 };
 
 int sdmmc_idma_validate_data(struct mmci_host *host,
 			     struct mmc_data *data)
 {
+	struct sdmmc_idma *idma = host->dma_priv;
+	struct device *dev = mmc_dev(host->mmc);
 	struct scatterlist *sg;
 	int i;
 
@@ -35,41 +40,69 @@
 	 * idma has constraints on idmabase & idmasize for each element
 	 * excepted the last element which has no constraint on idmasize
 	 */
+	idma->use_bounce_buffer = false;
 	for_each_sg(data->sg, sg, data->sg_len - 1, i) {
-		if (!IS_ALIGNED(sg_dma_address(data->sg), sizeof(u32)) ||
-		    !IS_ALIGNED(sg_dma_len(data->sg), SDMMC_IDMA_BURST)) {
-			dev_err(mmc_dev(host->mmc),
+		if (!IS_ALIGNED(sg->offset, sizeof(u32)) ||
+		    !IS_ALIGNED(sg->length, SDMMC_IDMA_BURST)) {
+			dev_dbg(mmc_dev(host->mmc),
 				"unaligned scatterlist: ofst:%x length:%d\n",
 				data->sg->offset, data->sg->length);
-			return -EINVAL;
+			goto use_bounce_buffer;
 		}
 	}
 
-	if (!IS_ALIGNED(sg_dma_address(data->sg), sizeof(u32))) {
-		dev_err(mmc_dev(host->mmc),
+	if (!IS_ALIGNED(sg->offset, sizeof(u32))) {
+		dev_dbg(mmc_dev(host->mmc),
 			"unaligned last scatterlist: ofst:%x length:%d\n",
 			data->sg->offset, data->sg->length);
-		return -EINVAL;
+		goto use_bounce_buffer;
 	}
 
 	return 0;
+
+use_bounce_buffer:
+	if (!idma->bounce_buf) {
+		idma->bounce_buf = dmam_alloc_coherent(dev,
+						       host->mmc->max_req_size,
+						       &idma->bounce_dma_addr,
+						       GFP_KERNEL);
+		if (!idma->bounce_buf) {
+			dev_err(dev, "Unable to map allocate DMA bounce buffer.\n");
+			return -ENOMEM;
+		}
+	}
+
+	idma->use_bounce_buffer = true;
+
+	return 0;
 }
 
 static int _sdmmc_idma_prep_data(struct mmci_host *host,
 				 struct mmc_data *data)
 {
-	int n_elem;
+	struct sdmmc_idma *idma = host->dma_priv;
 
-	n_elem = dma_map_sg(mmc_dev(host->mmc),
-			    data->sg,
-			    data->sg_len,
-			    mmc_get_dma_dir(data));
-
-	if (!n_elem) {
-		dev_err(mmc_dev(host->mmc), "dma_map_sg failed\n");
-		return -EINVAL;
-	}
+	if (idma->use_bounce_buffer) {
+		if (data->flags & MMC_DATA_WRITE) {
+			unsigned int xfer_bytes = data->blksz * data->blocks;
+
+			sg_copy_to_buffer(data->sg, data->sg_len,
+					  idma->bounce_buf, xfer_bytes);
+			dma_wmb();
+		}
+	} else {
+		int n_elem;
+
+		n_elem = dma_map_sg(mmc_dev(host->mmc),
+				    data->sg,
+				    data->sg_len,
+				    mmc_get_dma_dir(data));
 
+		if (!n_elem) {
+			dev_err(mmc_dev(host->mmc), "dma_map_sg failed\n");
+			return -EINVAL;
+		}
+	}
 	return 0;
 }
 
@@ -86,13 +119,24 @@
 static void sdmmc_idma_unprep_data(struct mmci_host *host,
 				   struct mmc_data *data, int err)
 {
-	dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
-		     mmc_get_dma_dir(data));
+	struct sdmmc_idma *idma = host->dma_priv;
+
+	if (idma->use_bounce_buffer) {
+		if (data->flags & MMC_DATA_READ) {
+			unsigned int xfer_bytes = data->blksz * data->blocks;
+
+			sg_copy_from_buffer(data->sg, data->sg_len,
+					    idma->bounce_buf, xfer_bytes);
+		}
+	} else {
+		dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
+			     mmc_get_dma_dir(data));
+	}
 }
 
 static int sdmmc_idma_setup(struct mmci_host *host)
 {
-	struct sdmmc_priv *idma;
+	struct sdmmc_idma *idma;
 
 	idma = devm_kzalloc(mmc_dev(host->mmc), sizeof(*idma), GFP_KERNEL);
 	if (!idma)
@@ -112,6 +156,8 @@
 		host->mmc->max_segs = SDMMC_LLI_BUF_LEN /
 			sizeof(struct sdmmc_lli_desc);
 		host->mmc->max_seg_size = host->variant->stm32_idmabsize_mask;
+
+		host->mmc->max_req_size = SZ_1M;
 	} else {
 		host->mmc->max_segs = 1;
 		host->mmc->max_seg_size = host->mmc->max_req_size;
@@ -123,14 +169,24 @@
 static int sdmmc_idma_start(struct mmci_host *host, unsigned int *datactrl)
 
 {
-	struct sdmmc_priv *idma = host->dma_priv;
+	struct sdmmc_idma *idma = host->dma_priv;
 	struct sdmmc_lli_desc *desc = (struct sdmmc_lli_desc *)idma->sg_cpu;
 	struct mmc_data *data = host->data;
 	struct scatterlist *sg;
 	int i;
 
-	if (!host->variant->dma_lli || data->sg_len == 1) {
-		writel_relaxed(sg_dma_address(data->sg),
+	host->dma_in_progress = true;
+
+	if (!host->variant->dma_lli || data->sg_len == 1 ||
+	    idma->use_bounce_buffer) {
+		u32 dma_addr;
+
+		if (idma->use_bounce_buffer)
+			dma_addr = idma->bounce_dma_addr;
+		else
+			dma_addr = sg_dma_address(data->sg);
+
+		writel_relaxed(dma_addr,
 			       host->base + MMCI_STM32_IDMABASE0R);
 		writel_relaxed(MMCI_STM32_IDMAEN,
 			       host->base + MMCI_STM32_IDMACTRLR);
@@ -159,9 +215,33 @@
 	return 0;
 }
 
+static void sdmmc_idma_error(struct mmci_host *host)
+{
+	struct mmc_data *data = host->data;
+	struct sdmmc_idma *idma = host->dma_priv;
+
+	if (!dma_inprogress(host))
+		return;
+
+	writel_relaxed(0, host->base + MMCI_STM32_IDMACTRLR);
+	host->dma_in_progress = false;
+	data->host_cookie = 0;
+
+	if (!idma->use_bounce_buffer)
+		dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
+			     mmc_get_dma_dir(data));
+}
+
 static void sdmmc_idma_finalize(struct mmci_host *host, struct mmc_data *data)
 {
+	if (!dma_inprogress(host))
+		return;
+
 	writel_relaxed(0, host->base + MMCI_STM32_IDMACTRLR);
+	host->dma_in_progress = false;
+
+	if (!data->host_cookie)
+		sdmmc_idma_unprep_data(host, data, 0);
 }
 
 static void mmci_sdmmc_set_clkreg(struct mmci_host *host, unsigned int desired)
@@ -290,6 +370,7 @@
 	.dma_setup = sdmmc_idma_setup,
 	.dma_start = sdmmc_idma_start,
 	.dma_finalize = sdmmc_idma_finalize,
+	.dma_error = sdmmc_idma_error,
 	.set_clkreg = mmci_sdmmc_set_clkreg,
 	.set_pwrreg = mmci_sdmmc_set_pwrreg,
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/moxart-mmc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/moxart-mmc.c
@@ -111,8 +111,8 @@
 #define CLK_DIV_MASK		0x7f
 
 /* REG_BUS_WIDTH */
-#define BUS_WIDTH_8		BIT(2)
-#define BUS_WIDTH_4		BIT(1)
+#define BUS_WIDTH_4_SUPPORT	BIT(3)
+#define BUS_WIDTH_4		BIT(2)
 #define BUS_WIDTH_1		BIT(0)
 
 #define MMC_VDD_360		23
@@ -339,13 +339,7 @@
 				return;
 			}
 			for (len = 0; len < remain && len < host->fifo_width;) {
-				/* SCR data must be read in big endian. */
-				if (data->mrq->cmd->opcode == SD_APP_SEND_SCR)
-					*sgp = ioread32be(host->base +
-							  REG_DATA_WINDOW);
-				else
-					*sgp = ioread32(host->base +
-							REG_DATA_WINDOW);
+				*sgp = ioread32(host->base + REG_DATA_WINDOW);
 				sgp++;
 				len += 4;
 			}
@@ -527,9 +521,6 @@
 	case MMC_BUS_WIDTH_4:
 		writel(BUS_WIDTH_4, host->base + REG_BUS_WIDTH);
 		break;
-	case MMC_BUS_WIDTH_8:
-		writel(BUS_WIDTH_8, host->base + REG_BUS_WIDTH);
-		break;
 	default:
 		writel(BUS_WIDTH_1, host->base + REG_BUS_WIDTH);
 		break;
@@ -631,6 +622,7 @@
 			 host->dma_chan_tx, host->dma_chan_rx);
 		host->have_dma = true;
 
+		memset(&cfg, 0, sizeof(cfg));
 		cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
 		cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
 
@@ -645,16 +637,8 @@
 		dmaengine_slave_config(host->dma_chan_rx, &cfg);
 	}
 
-	switch ((readl(host->base + REG_BUS_WIDTH) >> 3) & 3) {
-	case 1:
+	if (readl(host->base + REG_BUS_WIDTH) & BUS_WIDTH_4_SUPPORT)
 		mmc->caps |= MMC_CAP_4_BIT_DATA;
-		break;
-	case 2:
-		mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
-		break;
-	default:
-		break;
-	}
 
 	writel(0, host->base + REG_INTERRUPT_MASK);
 
@@ -670,7 +654,9 @@
 		goto out;
 
 	dev_set_drvdata(dev, mmc);
-	mmc_add_host(mmc);
+	ret = mmc_add_host(mmc);
+	if (ret)
+		goto out;
 
 	dev_dbg(dev, "IRQ=%d, FIFO is %d bytes\n", irq, host->fifo_width);
 
@@ -695,12 +681,12 @@
 		if (!IS_ERR(host->dma_chan_rx))
 			dma_release_channel(host->dma_chan_rx);
 		mmc_remove_host(mmc);
-		mmc_free_host(mmc);
 
 		writel(0, host->base + REG_INTERRUPT_MASK);
 		writel(0, host->base + REG_POWER_CONTROL);
 		writel(readl(host->base + REG_CLOCK_CONTROL) | CLK_OFF,
 		       host->base + REG_CLOCK_CONTROL);
+		mmc_free_host(mmc);
 	}
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/mtk-sd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/mtk-sd.c
@@ -22,6 +22,7 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
+#include <linux/reset.h>
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/core.h>
@@ -228,6 +229,7 @@
 #define MSDC_PATCH_BIT_SPCPUSH    (0x1 << 29)	/* RW */
 #define MSDC_PATCH_BIT_DECRCTMO   (0x1 << 30)	/* RW */
 
+#define MSDC_PATCH_BIT1_CMDTA     (0x7 << 3)    /* RW */
 #define MSDC_PATCH_BIT1_STOP_DLY  (0xf << 8)    /* RW */
 
 #define MSDC_PATCH_BIT2_CFGRESP   (0x1 << 15)   /* RW */
@@ -411,6 +413,7 @@
 	struct pinctrl_state *pins_uhs;
 	struct delayed_work req_timeout;
 	int irq;		/* host interrupt */
+	struct reset_control *reset;
 
 	struct clk *src_clk;	/* msdc source clock */
 	struct clk *h_clk;      /* msdc h_clk */
@@ -1017,13 +1020,13 @@
 static void msdc_request_done(struct msdc_host *host, struct mmc_request *mrq)
 {
 	unsigned long flags;
-	bool ret;
 
-	ret = cancel_delayed_work(&host->req_timeout);
-	if (!ret) {
-		/* delay work already running */
-		return;
-	}
+	/*
+	 * No need check the return value of cancel_delayed_work, as only ONE
+	 * path will go here!
+	 */
+	cancel_delayed_work(&host->req_timeout);
+
 	spin_lock_irqsave(&host->lock, flags);
 	host->mrq = NULL;
 	spin_unlock_irqrestore(&host->lock, flags);
@@ -1043,7 +1046,7 @@
 	bool done = false;
 	bool sbc_error;
 	unsigned long flags;
-	u32 *rsp = cmd->resp;
+	u32 *rsp;
 
 	if (mrq->sbc && cmd == mrq->cmd &&
 	    (events & (MSDC_INT_ACMDRDY | MSDC_INT_ACMDCRCERR
@@ -1064,6 +1067,7 @@
 
 	if (done)
 		return true;
+	rsp = cmd->resp;
 
 	sdr_clr_bits(host->base + MSDC_INTEN, cmd_ints_mask);
 
@@ -1251,7 +1255,7 @@
 static bool msdc_data_xfer_done(struct msdc_host *host, u32 events,
 				struct mmc_request *mrq, struct mmc_data *data)
 {
-	struct mmc_command *stop = data->stop;
+	struct mmc_command *stop;
 	unsigned long flags;
 	bool done;
 	unsigned int check_data = events &
@@ -1267,6 +1271,7 @@
 
 	if (done)
 		return true;
+	stop = data->stop;
 
 	if (check_data || (stop && stop->error)) {
 		dev_dbg(host->dev, "DMA status: 0x%8X\n",
@@ -1473,6 +1478,12 @@
 	u32 val;
 	u32 tune_reg = host->dev_comp->pad_tune_reg;
 
+	if (host->reset) {
+		reset_control_assert(host->reset);
+		usleep_range(10, 50);
+		reset_control_deassert(host->reset);
+	}
+
 	/* Configure to MMC/SD mode, clock free running */
 	sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_MODE | MSDC_CFG_CKPDN);
 
@@ -1881,6 +1892,7 @@
 
 	/* select EMMC50 PAD CMD tune */
 	sdr_set_bits(host->base + PAD_CMD_TUNE, BIT(0));
+	sdr_set_field(host->base + MSDC_PATCH_BIT1, MSDC_PATCH_BIT1_CMDTA, 2);
 
 	if (mmc->ios.timing == MMC_TIMING_MMC_HS200 ||
 	    mmc->ios.timing == MMC_TIMING_UHS_SDR104)
@@ -2230,9 +2242,14 @@
 	if (IS_ERR(host->src_clk_cg))
 		host->src_clk_cg = NULL;
 
+	host->reset = devm_reset_control_get_optional_exclusive(&pdev->dev,
+								"hrst");
+	if (IS_ERR(host->reset))
+		return PTR_ERR(host->reset);
+
 	host->irq = platform_get_irq(pdev, 0);
 	if (host->irq < 0) {
-		ret = -EINVAL;
+		ret = host->irq;
 		goto host_free;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/mvsdio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/mvsdio.c
@@ -696,17 +696,15 @@
 	struct mmc_host *mmc = NULL;
 	struct mvsd_host *host = NULL;
 	const struct mbus_dram_target_info *dram;
-	struct resource *r;
 	int ret, irq;
 
 	if (!np) {
 		dev_err(&pdev->dev, "no DT node\n");
 		return -ENODEV;
 	}
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	irq = platform_get_irq(pdev, 0);
-	if (!r || irq < 0)
-		return -ENXIO;
+	if (irq < 0)
+		return irq;
 
 	mmc = mmc_alloc_host(sizeof(struct mvsd_host), &pdev->dev);
 	if (!mmc) {
@@ -758,7 +756,7 @@
 
 	spin_lock_init(&host->lock);
 
-	host->base = devm_ioremap_resource(&pdev->dev, r);
+	host->base = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(host->base)) {
 		ret = PTR_ERR(host->base);
 		goto out;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/mxcmmc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/mxcmmc.c
@@ -1158,7 +1158,9 @@
 
 	timer_setup(&host->watchdog, mxcmci_watchdog, 0);
 
-	mmc_add_host(mmc);
+	ret = mmc_add_host(mmc);
+	if (ret)
+		goto out_free_dma;
 
 	return 0;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/mxs-mmc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/mxs-mmc.c
@@ -565,6 +565,11 @@
 };
 MODULE_DEVICE_TABLE(of, mxs_mmc_dt_ids);
 
+static void mxs_mmc_regulator_disable(void *regulator)
+{
+	regulator_disable(regulator);
+}
+
 static int mxs_mmc_probe(struct platform_device *pdev)
 {
 	const struct of_device_id *of_id =
@@ -606,6 +611,11 @@
 				"Failed to enable vmmc regulator: %d\n", ret);
 			goto out_mmc_free;
 		}
+
+		ret = devm_add_action_or_reset(&pdev->dev, mxs_mmc_regulator_disable,
+					       reg_vmmc);
+		if (ret)
+			goto out_mmc_free;
 	}
 
 	ssp->clk = devm_clk_get(&pdev->dev, NULL);
@@ -644,7 +654,7 @@
 
 	ret = mmc_of_parse(mmc);
 	if (ret)
-		goto out_clk_disable;
+		goto out_free_dma;
 
 	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/omap.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/omap.c
@@ -1344,7 +1344,7 @@
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0)
-		return -ENXIO;
+		return irq;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	host->virt_base = devm_ioremap_resource(&pdev->dev, res);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/omap_hsmmc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/omap_hsmmc.c
@@ -1512,6 +1512,36 @@
 
 	if (mmc_pdata(host)->init_card)
 		mmc_pdata(host)->init_card(card);
+	else if (card->type == MMC_TYPE_SDIO ||
+		 card->type == MMC_TYPE_SD_COMBO) {
+		struct device_node *np = mmc_dev(mmc)->of_node;
+
+		/*
+		 * REVISIT: should be moved to sdio core and made more
+		 * general e.g. by expanding the DT bindings of child nodes
+		 * to provide a mechanism to provide this information:
+		 * Documentation/devicetree/bindings/mmc/mmc-card.txt
+		 */
+
+		np = of_get_compatible_child(np, "ti,wl1251");
+		if (np) {
+			/*
+			 * We have TI wl1251 attached to MMC3. Pass this
+			 * information to the SDIO core because it can't be
+			 * probed by normal methods.
+			 */
+
+			dev_info(host->dev, "found wl1251\n");
+			card->quirks |= MMC_QUIRK_NONSTD_SDIO;
+			card->cccr.wide_bus = 1;
+			card->cis.vendor = 0x104c;
+			card->cis.device = 0x9066;
+			card->cis.blksize = 512;
+			card->cis.max_dtr = 24000000;
+			card->ocr = 0x80;
+			of_node_put(np);
+		}
+	}
 }
 
 static void omap_hsmmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
@@ -1813,9 +1843,11 @@
 	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	irq = platform_get_irq(pdev, 0);
-	if (res == NULL || irq < 0)
+	if (!res)
 		return -ENXIO;
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
 
 	base = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(base))
@@ -1968,7 +2000,9 @@
 	if (!ret)
 		mmc->caps |= MMC_CAP_SDIO_IRQ;
 
-	mmc_add_host(mmc);
+	ret = mmc_add_host(mmc);
+	if (ret)
+		goto err_irq;
 
 	if (mmc_pdata(host)->name != NULL) {
 		ret = device_create_file(&mmc->class_dev, &dev_attr_slot_name);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/pxamci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/pxamci.c
@@ -648,7 +648,7 @@
 
 	ret = pxamci_of_init(pdev, mmc);
 	if (ret)
-		return ret;
+		goto out;
 
 	host = mmc_priv(mmc);
 	host->mmc = mmc;
@@ -672,7 +672,7 @@
 
 	ret = pxamci_init_ocr(host);
 	if (ret < 0)
-		return ret;
+		goto out;
 
 	mmc->caps = 0;
 	host->cmdat = 0;
@@ -729,6 +729,7 @@
 
 		host->power = devm_gpiod_get_optional(dev, "power", GPIOD_OUT_LOW);
 		if (IS_ERR(host->power)) {
+			ret = PTR_ERR(host->power);
 			dev_err(dev, "Failed requesting gpio_power\n");
 			goto out;
 		}
@@ -740,16 +741,16 @@
 			goto out;
 		}
 
+		if (!host->pdata->gpio_card_ro_invert)
+			mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
+
 		ret = mmc_gpiod_request_ro(mmc, "wp", 0, 0, NULL);
 		if (ret && ret != -ENOENT) {
 			dev_err(dev, "Failed requesting gpio_ro\n");
 			goto out;
 		}
-		if (!ret) {
+		if (!ret)
 			host->use_ro_gpio = true;
-			mmc->caps2 |= host->pdata->gpio_card_ro_invert ?
-				0 : MMC_CAP2_RO_ACTIVE_HIGH;
-		}
 
 		if (host->pdata->init)
 			host->pdata->init(dev, pxamci_detect_irq, mmc);
@@ -760,7 +761,12 @@
 			dev_warn(dev, "gpio_ro and get_ro() both defined\n");
 	}
 
-	mmc_add_host(mmc);
+	ret = mmc_add_host(mmc);
+	if (ret) {
+		if (host->pdata && host->pdata->exit)
+			host->pdata->exit(dev, mmc);
+		goto out;
+	}
 
 	return 0;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/renesas_sdhi_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/renesas_sdhi_core.c
@@ -349,10 +349,10 @@
 			SH_MOBILE_SDHI_SCC_TMPPORT2_HS400OSEL) |
 			sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2));
 
-	/* Set the sampling clock selection range of HS400 mode */
 	sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DTCNTL,
 		       SH_MOBILE_SDHI_SCC_DTCNTL_TAPEN |
-		       0x4 << SH_MOBILE_SDHI_SCC_DTCNTL_TAPNUM_SHIFT);
+		       sd_scc_read32(host, priv,
+				     SH_MOBILE_SDHI_SCC_DTCNTL));
 
 
 	if (host->pdata->flags & TMIO_MMC_HAVE_4TAP_HS400)
@@ -874,6 +874,7 @@
 
 	tmio_mmc_host_remove(host);
 	renesas_sdhi_clk_disable(host);
+	tmio_mmc_host_free(host);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/renesas_sdhi_internal_dmac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/renesas_sdhi_internal_dmac.c
@@ -186,8 +186,8 @@
 			mmc_get_dma_dir(data)))
 		goto force_pio;
 
-	/* This DMAC cannot handle if buffer is not 8-bytes alignment */
-	if (!IS_ALIGNED(sg_dma_address(sg), 8))
+	/* This DMAC cannot handle if buffer is not 128-bytes alignment */
+	if (!IS_ALIGNED(sg_dma_address(sg), 128))
 		goto force_pio_with_unmap;
 
 	if (data->flags & MMC_DATA_READ) {
@@ -229,15 +229,12 @@
 					    DTRAN_CTRL_DM_START);
 }
 
-static void renesas_sdhi_internal_dmac_complete_tasklet_fn(unsigned long arg)
+static bool renesas_sdhi_internal_dmac_complete(struct tmio_mmc_host *host)
 {
-	struct tmio_mmc_host *host = (struct tmio_mmc_host *)arg;
 	enum dma_data_direction dir;
 
-	spin_lock_irq(&host->lock);
-
 	if (!host->data)
-		goto out;
+		return false;
 
 	if (host->data->flags & MMC_DATA_READ)
 		dir = DMA_FROM_DEVICE;
@@ -250,6 +247,17 @@
 	if (dir == DMA_FROM_DEVICE)
 		clear_bit(SDHI_INTERNAL_DMAC_RX_IN_USE, &global_flags);
 
+	return true;
+}
+
+static void renesas_sdhi_internal_dmac_complete_tasklet_fn(unsigned long arg)
+{
+	struct tmio_mmc_host *host = (struct tmio_mmc_host *)arg;
+
+	spin_lock_irq(&host->lock);
+	if (!renesas_sdhi_internal_dmac_complete(host))
+		goto out;
+
 	tmio_mmc_do_data_irq(host);
 out:
 	spin_unlock_irq(&host->lock);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/rtsx_pci_sdmmc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/rtsx_pci_sdmmc.c
@@ -37,10 +37,7 @@
 	bool			double_clk;
 	bool			eject;
 	bool			initial_mode;
-	int			power_state;
-#define SDMMC_POWER_ON		1
-#define SDMMC_POWER_OFF		0
-
+	int			prev_power_state;
 	int			sg_count;
 	s32			cookie;
 	int			cookie_sg_count;
@@ -539,9 +536,22 @@
 	return 0;
 }
 
+static inline void sd_enable_initial_mode(struct realtek_pci_sdmmc *host)
+{
+	rtsx_pci_write_register(host->pcr, SD_CFG1,
+			SD_CLK_DIVIDE_MASK, SD_CLK_DIVIDE_128);
+}
+
+static inline void sd_disable_initial_mode(struct realtek_pci_sdmmc *host)
+{
+	rtsx_pci_write_register(host->pcr, SD_CFG1,
+			SD_CLK_DIVIDE_MASK, SD_CLK_DIVIDE_0);
+}
+
 static int sd_rw_multi(struct realtek_pci_sdmmc *host, struct mmc_request *mrq)
 {
 	struct mmc_data *data = mrq->data;
+	int err;
 
 	if (host->sg_count < 0) {
 		data->error = host->sg_count;
@@ -550,22 +560,19 @@
 		return data->error;
 	}
 
-	if (data->flags & MMC_DATA_READ)
-		return sd_read_long_data(host, mrq);
+	if (data->flags & MMC_DATA_READ) {
+		if (host->initial_mode)
+			sd_disable_initial_mode(host);
 
-	return sd_write_long_data(host, mrq);
-}
+		err = sd_read_long_data(host, mrq);
 
-static inline void sd_enable_initial_mode(struct realtek_pci_sdmmc *host)
-{
-	rtsx_pci_write_register(host->pcr, SD_CFG1,
-			SD_CLK_DIVIDE_MASK, SD_CLK_DIVIDE_128);
-}
+		if (host->initial_mode)
+			sd_enable_initial_mode(host);
 
-static inline void sd_disable_initial_mode(struct realtek_pci_sdmmc *host)
-{
-	rtsx_pci_write_register(host->pcr, SD_CFG1,
-			SD_CLK_DIVIDE_MASK, SD_CLK_DIVIDE_0);
+		return err;
+	}
+
+	return sd_write_long_data(host, mrq);
 }
 
 static void sd_normal_rw(struct realtek_pci_sdmmc *host,
@@ -606,19 +613,22 @@
 		u8 sample_point, bool rx)
 {
 	struct rtsx_pcr *pcr = host->pcr;
-
+	u16 SD_VP_CTL = 0;
 	dev_dbg(sdmmc_dev(host), "%s(%s): sample_point = %d\n",
 			__func__, rx ? "RX" : "TX", sample_point);
 
 	rtsx_pci_write_register(pcr, CLK_CTL, CHANGE_CLK, CHANGE_CLK);
-	if (rx)
+	if (rx) {
+		SD_VP_CTL = SD_VPRX_CTL;
 		rtsx_pci_write_register(pcr, SD_VPRX_CTL,
 			PHASE_SELECT_MASK, sample_point);
-	else
+	} else {
+		SD_VP_CTL = SD_VPTX_CTL;
 		rtsx_pci_write_register(pcr, SD_VPTX_CTL,
 			PHASE_SELECT_MASK, sample_point);
-	rtsx_pci_write_register(pcr, SD_VPCLK0_CTL, PHASE_NOT_RESET, 0);
-	rtsx_pci_write_register(pcr, SD_VPCLK0_CTL, PHASE_NOT_RESET,
+	}
+	rtsx_pci_write_register(pcr, SD_VP_CTL, PHASE_NOT_RESET, 0);
+	rtsx_pci_write_register(pcr, SD_VP_CTL, PHASE_NOT_RESET,
 				PHASE_NOT_RESET);
 	rtsx_pci_write_register(pcr, CLK_CTL, CHANGE_CLK, 0);
 	rtsx_pci_write_register(pcr, SD_CFG1, SD_ASYNC_FIFO_NOT_RST, 0);
@@ -889,14 +899,21 @@
 	return err;
 }
 
-static int sd_power_on(struct realtek_pci_sdmmc *host)
+static int sd_power_on(struct realtek_pci_sdmmc *host, unsigned char power_mode)
 {
 	struct rtsx_pcr *pcr = host->pcr;
 	int err;
 
-	if (host->power_state == SDMMC_POWER_ON)
+	if (host->prev_power_state == MMC_POWER_ON)
 		return 0;
 
+	if (host->prev_power_state == MMC_POWER_UP) {
+		rtsx_pci_write_register(pcr, SD_BUS_STAT, SD_CLK_TOGGLE_EN, 0);
+		goto finish;
+	}
+
+	msleep(100);
+
 	rtsx_pci_init_cmd(pcr);
 	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SELECT, 0x07, SD_MOD_SEL);
 	rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SHARE_MODE,
@@ -915,11 +932,17 @@
 	if (err < 0)
 		return err;
 
+	mdelay(1);
+
 	err = rtsx_pci_write_register(pcr, CARD_OE, SD_OUTPUT_EN, SD_OUTPUT_EN);
 	if (err < 0)
 		return err;
 
-	host->power_state = SDMMC_POWER_ON;
+	/* send at least 74 clocks */
+	rtsx_pci_write_register(pcr, SD_BUS_STAT, SD_CLK_TOGGLE_EN, SD_CLK_TOGGLE_EN);
+
+finish:
+	host->prev_power_state = power_mode;
 	return 0;
 }
 
@@ -928,7 +951,7 @@
 	struct rtsx_pcr *pcr = host->pcr;
 	int err;
 
-	host->power_state = SDMMC_POWER_OFF;
+	host->prev_power_state = MMC_POWER_OFF;
 
 	rtsx_pci_init_cmd(pcr);
 
@@ -954,7 +977,7 @@
 	if (power_mode == MMC_POWER_OFF)
 		err = sd_power_off(host);
 	else
-		err = sd_power_on(host);
+		err = sd_power_on(host, power_mode);
 
 	return err;
 }
@@ -1389,10 +1412,11 @@
 
 	host = mmc_priv(mmc);
 	host->pcr = pcr;
+	mmc->ios.power_delay_ms = 5;
 	host->mmc = mmc;
 	host->pdev = pdev;
 	host->cookie = -1;
-	host->power_state = SDMMC_POWER_OFF;
+	host->prev_power_state = MMC_POWER_OFF;
 	INIT_WORK(&host->work, sd_request);
 	platform_set_drvdata(pdev, host);
 	pcr->slots[RTSX_SD_CARD].p_dev = pdev;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/rtsx_usb_sdmmc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/rtsx_usb_sdmmc.c
@@ -1338,6 +1338,7 @@
 #ifdef RTSX_USB_USE_LEDS_CLASS
 	int err;
 #endif
+	int ret;
 
 	ucr = usb_get_intfdata(to_usb_interface(pdev->dev.parent));
 	if (!ucr)
@@ -1374,7 +1375,15 @@
 	INIT_WORK(&host->led_work, rtsx_usb_update_led);
 
 #endif
-	mmc_add_host(mmc);
+	ret = mmc_add_host(mmc);
+	if (ret) {
+#ifdef RTSX_USB_USE_LEDS_CLASS
+		led_classdev_unregister(&host->led);
+#endif
+		mmc_free_host(mmc);
+		pm_runtime_disable(&pdev->dev);
+		return ret;
+	}
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/sdhci-acpi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/sdhci-acpi.c
@@ -532,6 +532,11 @@
 	.caps    = MMC_CAP_NONREMOVABLE,
 };
 
+struct amd_sdhci_host {
+	bool	tuned_clock;
+	bool	dll_enabled;
+};
+
 /* AMD sdhci reset dll register. */
 #define SDHCI_AMD_RESET_DLL_REGISTER    0x908
 
@@ -542,39 +547,96 @@
 	return MMC_SET_DRIVER_TYPE_A;
 }
 
-static void sdhci_acpi_amd_hs400_dll(struct sdhci_host *host)
+static void sdhci_acpi_amd_hs400_dll(struct sdhci_host *host, bool enable)
 {
+	struct sdhci_acpi_host *acpi_host = sdhci_priv(host);
+	struct amd_sdhci_host *amd_host = sdhci_acpi_priv(acpi_host);
+
 	/* AMD Platform requires dll setting */
 	sdhci_writel(host, 0x40003210, SDHCI_AMD_RESET_DLL_REGISTER);
 	usleep_range(10, 20);
-	sdhci_writel(host, 0x40033210, SDHCI_AMD_RESET_DLL_REGISTER);
+	if (enable)
+		sdhci_writel(host, 0x40033210, SDHCI_AMD_RESET_DLL_REGISTER);
+
+	amd_host->dll_enabled = enable;
 }
 
 /*
- * For AMD Platform it is required to disable the tuning
- * bit first controller to bring to HS Mode from HS200
- * mode, later enable to tune to HS400 mode.
+ * The initialization sequence for HS400 is:
+ *     HS->HS200->Perform Tuning->HS->HS400
+ *
+ * The re-tuning sequence is:
+ *     HS400->DDR52->HS->HS200->Perform Tuning->HS->HS400
+ *
+ * The AMD eMMC Controller can only use the tuned clock while in HS200 and HS400
+ * mode. If we switch to a different mode, we need to disable the tuned clock.
+ * If we have previously performed tuning and switch back to HS200 or
+ * HS400, we can re-enable the tuned clock.
+ *
  */
 static void amd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	struct sdhci_host *host = mmc_priv(mmc);
+	struct sdhci_acpi_host *acpi_host = sdhci_priv(host);
+	struct amd_sdhci_host *amd_host = sdhci_acpi_priv(acpi_host);
 	unsigned int old_timing = host->timing;
+	u16 val;
 
 	sdhci_set_ios(mmc, ios);
-	if (old_timing == MMC_TIMING_MMC_HS200 &&
-	    ios->timing == MMC_TIMING_MMC_HS)
-		sdhci_writew(host, 0x9, SDHCI_HOST_CONTROL2);
-	if (old_timing != MMC_TIMING_MMC_HS400 &&
-	    ios->timing == MMC_TIMING_MMC_HS400) {
-		sdhci_writew(host, 0x80, SDHCI_HOST_CONTROL2);
-		sdhci_acpi_amd_hs400_dll(host);
+
+	if (old_timing != host->timing && amd_host->tuned_clock) {
+		if (host->timing == MMC_TIMING_MMC_HS400 ||
+		    host->timing == MMC_TIMING_MMC_HS200) {
+			val = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+			val |= SDHCI_CTRL_TUNED_CLK;
+			sdhci_writew(host, val, SDHCI_HOST_CONTROL2);
+		} else {
+			val = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+			val &= ~SDHCI_CTRL_TUNED_CLK;
+			sdhci_writew(host, val, SDHCI_HOST_CONTROL2);
+		}
+
+		/* DLL is only required for HS400 */
+		if (host->timing == MMC_TIMING_MMC_HS400 &&
+		    !amd_host->dll_enabled)
+			sdhci_acpi_amd_hs400_dll(host, true);
 	}
 }
 
+static int amd_sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
+{
+	int err;
+	struct sdhci_host *host = mmc_priv(mmc);
+	struct sdhci_acpi_host *acpi_host = sdhci_priv(host);
+	struct amd_sdhci_host *amd_host = sdhci_acpi_priv(acpi_host);
+
+	amd_host->tuned_clock = false;
+
+	err = sdhci_execute_tuning(mmc, opcode);
+
+	if (!err && !host->tuning_err)
+		amd_host->tuned_clock = true;
+
+	return err;
+}
+
+static void amd_sdhci_reset(struct sdhci_host *host, u8 mask)
+{
+	struct sdhci_acpi_host *acpi_host = sdhci_priv(host);
+	struct amd_sdhci_host *amd_host = sdhci_acpi_priv(acpi_host);
+
+	if (mask & SDHCI_RESET_ALL) {
+		amd_host->tuned_clock = false;
+		sdhci_acpi_amd_hs400_dll(host, false);
+	}
+
+	sdhci_reset(host, mask);
+}
+
 static const struct sdhci_ops sdhci_acpi_ops_amd = {
 	.set_clock	= sdhci_set_clock,
 	.set_bus_width	= sdhci_set_bus_width,
-	.reset		= sdhci_reset,
+	.reset		= amd_sdhci_reset,
 	.set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
@@ -596,17 +658,58 @@
 	    (host->mmc->caps & MMC_CAP_1_8V_DDR))
 		host->mmc->caps2 = MMC_CAP2_HS400_1_8V;
 
+	/*
+	 * There are two types of presets out in the wild:
+	 * 1) Default/broken presets.
+	 *    These presets have two sets of problems:
+	 *    a) The clock divisor for SDR12, SDR25, and SDR50 is too small.
+	 *       This results in clock frequencies that are 2x higher than
+	 *       acceptable. i.e., SDR12 = 25 MHz, SDR25 = 50 MHz, SDR50 =
+	 *       100 MHz.x
+	 *    b) The HS200 and HS400 driver strengths don't match.
+	 *       By default, the SDR104 preset register has a driver strength of
+	 *       A, but the (internal) HS400 preset register has a driver
+	 *       strength of B. As part of initializing HS400, HS200 tuning
+	 *       needs to be performed. Having different driver strengths
+	 *       between tuning and operation is wrong. It results in different
+	 *       rise/fall times that lead to incorrect sampling.
+	 * 2) Firmware with properly initialized presets.
+	 *    These presets have proper clock divisors. i.e., SDR12 => 12MHz,
+	 *    SDR25 => 25 MHz, SDR50 => 50 MHz. Additionally the HS200 and
+	 *    HS400 preset driver strengths match.
+	 *
+	 *    Enabling presets for HS400 doesn't work for the following reasons:
+	 *    1) sdhci_set_ios has a hard coded list of timings that are used
+	 *       to determine if presets should be enabled.
+	 *    2) sdhci_get_preset_value is using a non-standard register to
+	 *       read out HS400 presets. The AMD controller doesn't support this
+	 *       non-standard register. In fact, it doesn't expose the HS400
+	 *       preset register anywhere in the SDHCI memory map. This results
+	 *       in reading a garbage value and using the wrong presets.
+	 *
+	 *       Since HS400 and HS200 presets must be identical, we could
+	 *       instead use the the SDR104 preset register.
+	 *
+	 *    If the above issues are resolved we could remove this quirk for
+	 *    firmware that that has valid presets (i.e., SDR12 <= 12 MHz).
+	 */
+	host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN;
+
 	host->mmc_host_ops.select_drive_strength = amd_select_drive_strength;
 	host->mmc_host_ops.set_ios = amd_set_ios;
+	host->mmc_host_ops.execute_tuning = amd_sdhci_execute_tuning;
 	return 0;
 }
 
 static const struct sdhci_acpi_slot sdhci_acpi_slot_amd_emmc = {
-	.chip   = &sdhci_acpi_chip_amd,
-	.caps   = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE,
-	.quirks = SDHCI_QUIRK_32BIT_DMA_ADDR | SDHCI_QUIRK_32BIT_DMA_SIZE |
-			SDHCI_QUIRK_32BIT_ADMA_SIZE,
+	.chip		= &sdhci_acpi_chip_amd,
+	.caps		= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE,
+	.quirks		= SDHCI_QUIRK_32BIT_DMA_ADDR |
+			  SDHCI_QUIRK_32BIT_DMA_SIZE |
+			  SDHCI_QUIRK_32BIT_ADMA_SIZE,
+	.quirks2	= SDHCI_QUIRK2_BROKEN_64_BIT_DMA,
 	.probe_slot     = sdhci_acpi_emmc_amd_probe_slot,
+	.priv_size	= sizeof(struct amd_sdhci_host),
 };
 
 struct sdhci_acpi_uid_slot {
@@ -732,7 +835,7 @@
 	host->ops	= &sdhci_acpi_ops_dflt;
 	host->irq	= platform_get_irq(pdev, 0);
 	if (host->irq < 0) {
-		err = -EINVAL;
+		err = host->irq;
 		goto err_free;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/sdhci-cadence.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/sdhci-cadence.c
@@ -11,6 +11,7 @@
 #include <linux/mmc/host.h>
 #include <linux/mmc/mmc.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 
 #include "sdhci-pltfm.h"
 
@@ -193,52 +194,6 @@
 	return FIELD_GET(SDHCI_CDNS_HRS06_MODE, tmp);
 }
 
-static void sdhci_cdns_set_uhs_signaling(struct sdhci_host *host,
-					 unsigned int timing)
-{
-	struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host);
-	u32 mode;
-
-	switch (timing) {
-	case MMC_TIMING_MMC_HS:
-		mode = SDHCI_CDNS_HRS06_MODE_MMC_SDR;
-		break;
-	case MMC_TIMING_MMC_DDR52:
-		mode = SDHCI_CDNS_HRS06_MODE_MMC_DDR;
-		break;
-	case MMC_TIMING_MMC_HS200:
-		mode = SDHCI_CDNS_HRS06_MODE_MMC_HS200;
-		break;
-	case MMC_TIMING_MMC_HS400:
-		if (priv->enhanced_strobe)
-			mode = SDHCI_CDNS_HRS06_MODE_MMC_HS400ES;
-		else
-			mode = SDHCI_CDNS_HRS06_MODE_MMC_HS400;
-		break;
-	default:
-		mode = SDHCI_CDNS_HRS06_MODE_SD;
-		break;
-	}
-
-	sdhci_cdns_set_emmc_mode(priv, mode);
-
-	/* For SD, fall back to the default handler */
-	if (mode == SDHCI_CDNS_HRS06_MODE_SD)
-		sdhci_set_uhs_signaling(host, timing);
-}
-
-static const struct sdhci_ops sdhci_cdns_ops = {
-	.set_clock = sdhci_set_clock,
-	.get_timeout_clock = sdhci_cdns_get_timeout_clock,
-	.set_bus_width = sdhci_set_bus_width,
-	.reset = sdhci_reset,
-	.set_uhs_signaling = sdhci_cdns_set_uhs_signaling,
-};
-
-static const struct sdhci_pltfm_data sdhci_cdns_pltfm_data = {
-	.ops = &sdhci_cdns_ops,
-};
-
 static int sdhci_cdns_set_tune_val(struct sdhci_host *host, unsigned int val)
 {
 	struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host);
@@ -272,23 +227,24 @@
 	return 0;
 }
 
-static int sdhci_cdns_execute_tuning(struct mmc_host *mmc, u32 opcode)
+/*
+ * In SD mode, software must not use the hardware tuning and instead perform
+ * an almost identical procedure to eMMC.
+ */
+static int sdhci_cdns_execute_tuning(struct sdhci_host *host, u32 opcode)
 {
-	struct sdhci_host *host = mmc_priv(mmc);
 	int cur_streak = 0;
 	int max_streak = 0;
 	int end_of_streak = 0;
 	int i;
 
 	/*
-	 * This handler only implements the eMMC tuning that is specific to
-	 * this controller.  Fall back to the standard method for SD timing.
+	 * Do not execute tuning for UHS_SDR50 or UHS_DDR50.
+	 * The delay is set by probe, based on the DT properties.
 	 */
-	if (host->timing != MMC_TIMING_MMC_HS200)
-		return sdhci_execute_tuning(mmc, opcode);
-
-	if (WARN_ON(opcode != MMC_SEND_TUNING_BLOCK_HS200))
-		return -EINVAL;
+	if (host->timing != MMC_TIMING_MMC_HS200 &&
+	    host->timing != MMC_TIMING_UHS_SDR104)
+		return 0;
 
 	for (i = 0; i < SDHCI_CDNS_MAX_TUNING_LOOP; i++) {
 		if (sdhci_cdns_set_tune_val(host, i) ||
@@ -311,6 +267,58 @@
 	return sdhci_cdns_set_tune_val(host, end_of_streak - max_streak / 2);
 }
 
+static void sdhci_cdns_set_uhs_signaling(struct sdhci_host *host,
+					 unsigned int timing)
+{
+	struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host);
+	u32 mode;
+
+	switch (timing) {
+	case MMC_TIMING_MMC_HS:
+		mode = SDHCI_CDNS_HRS06_MODE_MMC_SDR;
+		break;
+	case MMC_TIMING_MMC_DDR52:
+		mode = SDHCI_CDNS_HRS06_MODE_MMC_DDR;
+		break;
+	case MMC_TIMING_MMC_HS200:
+		mode = SDHCI_CDNS_HRS06_MODE_MMC_HS200;
+		break;
+	case MMC_TIMING_MMC_HS400:
+		if (priv->enhanced_strobe)
+			mode = SDHCI_CDNS_HRS06_MODE_MMC_HS400ES;
+		else
+			mode = SDHCI_CDNS_HRS06_MODE_MMC_HS400;
+		break;
+	default:
+		mode = SDHCI_CDNS_HRS06_MODE_SD;
+		break;
+	}
+
+	sdhci_cdns_set_emmc_mode(priv, mode);
+
+	/* For SD, fall back to the default handler */
+	if (mode == SDHCI_CDNS_HRS06_MODE_SD)
+		sdhci_set_uhs_signaling(host, timing);
+}
+
+static const struct sdhci_ops sdhci_cdns_ops = {
+	.set_clock = sdhci_set_clock,
+	.get_timeout_clock = sdhci_cdns_get_timeout_clock,
+	.set_bus_width = sdhci_set_bus_width,
+	.reset = sdhci_reset,
+	.platform_execute_tuning = sdhci_cdns_execute_tuning,
+	.set_uhs_signaling = sdhci_cdns_set_uhs_signaling,
+};
+
+static const struct sdhci_pltfm_data sdhci_cdns_uniphier_pltfm_data = {
+	.ops = &sdhci_cdns_ops,
+	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
+};
+
+static const struct sdhci_pltfm_data sdhci_cdns_pltfm_data = {
+	.ops = &sdhci_cdns_ops,
+};
+
 static void sdhci_cdns_hs400_enhanced_strobe(struct mmc_host *mmc,
 					     struct mmc_ios *ios)
 {
@@ -334,6 +342,7 @@
 static int sdhci_cdns_probe(struct platform_device *pdev)
 {
 	struct sdhci_host *host;
+	const struct sdhci_pltfm_data *data;
 	struct sdhci_pltfm_host *pltfm_host;
 	struct sdhci_cdns_priv *priv;
 	struct clk *clk;
@@ -350,8 +359,12 @@
 	if (ret)
 		return ret;
 
+	data = of_device_get_match_data(dev);
+	if (!data)
+		data = &sdhci_cdns_pltfm_data;
+
 	nr_phy_params = sdhci_cdns_phy_param_count(dev->of_node);
-	host = sdhci_pltfm_init(pdev, &sdhci_cdns_pltfm_data,
+	host = sdhci_pltfm_init(pdev, data,
 				struct_size(priv, phy_params, nr_phy_params));
 	if (IS_ERR(host)) {
 		ret = PTR_ERR(host);
@@ -366,7 +379,6 @@
 	priv->hrs_addr = host->ioaddr;
 	priv->enhanced_strobe = false;
 	host->ioaddr += SDHCI_CDNS_SRS_BASE;
-	host->mmc_host_ops.execute_tuning = sdhci_cdns_execute_tuning;
 	host->mmc_host_ops.hs400_enhanced_strobe =
 				sdhci_cdns_hs400_enhanced_strobe;
 	sdhci_enable_v4_mode(host);
@@ -431,7 +443,10 @@
 };
 
 static const struct of_device_id sdhci_cdns_match[] = {
-	{ .compatible = "socionext,uniphier-sd4hc" },
+	{
+		.compatible = "socionext,uniphier-sd4hc",
+		.data = &sdhci_cdns_uniphier_pltfm_data,
+	},
 	{ .compatible = "cdns,sd4hc" },
 	{ /* sentinel */ }
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/sdhci-cqhci.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/sdhci-cqhci.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright 2022 The Chromium OS Authors
+ *
+ * Support that applies to the combination of SDHCI and CQHCI, while not
+ * expressing a dependency between the two modules.
+ */
+
+#ifndef __MMC_HOST_SDHCI_CQHCI_H__
+#define __MMC_HOST_SDHCI_CQHCI_H__
+
+#include "cqhci.h"
+#include "sdhci.h"
+
+static inline void sdhci_and_cqhci_reset(struct sdhci_host *host, u8 mask)
+{
+	if ((host->mmc->caps2 & MMC_CAP2_CQE) && (mask & SDHCI_RESET_ALL) &&
+	    host->mmc->cqe_private)
+		cqhci_deactivate(host->mmc);
+
+	sdhci_reset(host, mask);
+}
+
+#endif /* __MMC_HOST_SDHCI_CQHCI_H__ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/sdhci-esdhc-imx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -24,6 +24,7 @@
 #include <linux/pinctrl/consumer.h>
 #include <linux/platform_data/mmc-esdhc-imx.h>
 #include <linux/pm_runtime.h>
+#include <linux/iopoll.h>
 #include "sdhci-pltfm.h"
 #include "sdhci-esdhc.h"
 #include "cqhci.h"
@@ -87,7 +88,9 @@
 #define ESDHC_STD_TUNING_EN		(1 << 24)
 /* NOTE: the minimum valid tuning start tap for mx6sl is 1 */
 #define ESDHC_TUNING_START_TAP_DEFAULT	0x1
-#define ESDHC_TUNING_START_TAP_MASK	0xff
+#define ESDHC_TUNING_START_TAP_MASK	0x7f
+#define ESDHC_TUNING_CMD_CRC_CHECK_DISABLE	(1 << 7)
+#define ESDHC_TUNING_STEP_DEFAULT	0x1
 #define ESDHC_TUNING_STEP_MASK		0x00070000
 #define ESDHC_TUNING_STEP_SHIFT		16
 
@@ -150,8 +153,8 @@
 #define ESDHC_FLAG_HS400		BIT(9)
 /*
  * The IP has errata ERR010450
- * uSDHC: Due to the I/O timing limit, for SDR mode, SD card clock can't
- * exceed 150MHz, for DDR mode, SD card clock can't exceed 45MHz.
+ * uSDHC: At 1.8V due to the I/O timing limit, for SDR mode, SD card
+ * clock can't exceed 150MHz, for DDR mode, SD card clock can't exceed 45MHz.
  */
 #define ESDHC_FLAG_ERR010450		BIT(10)
 /* The IP supports HS400ES mode */
@@ -217,8 +220,7 @@
 static struct esdhc_soc_data usdhc_imx8qxp_data = {
 	.flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING
 			| ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200
-			| ESDHC_FLAG_HS400 | ESDHC_FLAG_HS400_ES
-			| ESDHC_FLAG_CQHCI,
+			| ESDHC_FLAG_HS400 | ESDHC_FLAG_HS400_ES,
 };
 
 struct pltfm_imx_data {
@@ -775,7 +777,8 @@
 		| ESDHC_CLOCK_MASK);
 	sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
 
-	if (imx_data->socdata->flags & ESDHC_FLAG_ERR010450) {
+	if ((imx_data->socdata->flags & ESDHC_FLAG_ERR010450) &&
+	    (!(host->quirks2 & SDHCI_QUIRK2_NO_1_8_V))) {
 		unsigned int max_clock;
 
 		max_clock = imx_data->is_ddr ? 45000000 : 150000000;
@@ -1022,6 +1025,7 @@
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
 	u32 ctrl;
+	int ret;
 
 	/* Reset the tuning circuit */
 	if (esdhc_is_usdhc(imx_data)) {
@@ -1034,7 +1038,22 @@
 		} else if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) {
 			ctrl = readl(host->ioaddr + SDHCI_AUTO_CMD_STATUS);
 			ctrl &= ~ESDHC_MIX_CTRL_SMPCLK_SEL;
+			ctrl &= ~ESDHC_MIX_CTRL_EXE_TUNE;
 			writel(ctrl, host->ioaddr + SDHCI_AUTO_CMD_STATUS);
+			/* Make sure ESDHC_MIX_CTRL_EXE_TUNE cleared */
+			ret = readl_poll_timeout(host->ioaddr + SDHCI_AUTO_CMD_STATUS,
+				ctrl, !(ctrl & ESDHC_MIX_CTRL_EXE_TUNE), 1, 50);
+			if (ret == -ETIMEDOUT)
+				dev_warn(mmc_dev(host->mmc),
+				 "Warning! clear execute tuning bit failed\n");
+			/*
+			 * SDHCI_INT_DATA_AVAIL is W1C bit, set this bit will clear the
+			 * usdhc IP internal logic flag execute_tuning_with_clr_buf, which
+			 * will finally make sure the normal data transfer logic correct.
+			 */
+			ctrl = readl(host->ioaddr + SDHCI_INT_STATUS);
+			ctrl |= SDHCI_INT_DATA_AVAIL;
+			writel(ctrl, host->ioaddr + SDHCI_INT_STATUS);
 		}
 	}
 }
@@ -1164,7 +1183,8 @@
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
-	int tmp;
+	struct cqhci_host *cq_host = host->mmc->cqe_private;
+	u32 tmp;
 
 	if (esdhc_is_usdhc(imx_data)) {
 		/*
@@ -1217,18 +1237,37 @@
 
 		if (imx_data->socdata->flags & ESDHC_FLAG_STD_TUNING) {
 			tmp = readl(host->ioaddr + ESDHC_TUNING_CTRL);
-			tmp |= ESDHC_STD_TUNING_EN |
-				ESDHC_TUNING_START_TAP_DEFAULT;
-			if (imx_data->boarddata.tuning_start_tap) {
-				tmp &= ~ESDHC_TUNING_START_TAP_MASK;
+			tmp |= ESDHC_STD_TUNING_EN;
+
+			/*
+			 * ROM code or bootloader may config the start tap
+			 * and step, unmask them first.
+			 */
+			tmp &= ~(ESDHC_TUNING_START_TAP_MASK | ESDHC_TUNING_STEP_MASK);
+			if (imx_data->boarddata.tuning_start_tap)
 				tmp |= imx_data->boarddata.tuning_start_tap;
-			}
+			else
+				tmp |= ESDHC_TUNING_START_TAP_DEFAULT;
 
 			if (imx_data->boarddata.tuning_step) {
-				tmp &= ~ESDHC_TUNING_STEP_MASK;
 				tmp |= imx_data->boarddata.tuning_step
 					<< ESDHC_TUNING_STEP_SHIFT;
+			} else {
+				tmp |= ESDHC_TUNING_STEP_DEFAULT
+					<< ESDHC_TUNING_STEP_SHIFT;
 			}
+
+			/* Disable the CMD CRC check for tuning, if not, need to
+			 * add some delay after every tuning command, because
+			 * hardware standard tuning logic will directly go to next
+			 * step once it detect the CMD CRC error, will not wait for
+			 * the card side to finally send out the tuning data, trigger
+			 * the buffer read ready interrupt immediately. If usdhc send
+			 * the next tuning command some eMMC card will stuck, can't
+			 * response, block the tuning procedure or the first command
+			 * after the whole tuning procedure always can't get any response.
+			 */
+			 tmp |= ESDHC_TUNING_CMD_CRC_CHECK_DISABLE;
 			writel(tmp, host->ioaddr + ESDHC_TUNING_CTRL);
 		} else if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) {
 			/*
@@ -1240,6 +1279,21 @@
 			tmp &= ~ESDHC_STD_TUNING_EN;
 			writel(tmp, host->ioaddr + ESDHC_TUNING_CTRL);
 		}
+
+		/*
+		 * On i.MX8MM, we are running Dual Linux OS, with 1st Linux using SD Card
+		 * as rootfs storage, 2nd Linux using eMMC as rootfs storage. We let the
+		 * the 1st linux configure power/clock for the 2nd Linux.
+		 *
+		 * When the 2nd Linux is booting into rootfs stage, we let the 1st Linux
+		 * to destroy the 2nd linux, then restart the 2nd linux, we met SDHCI dump.
+		 * After we clear the pending interrupt and halt CQCTL, issue gone.
+		 */
+		if (cq_host) {
+			tmp = cqhci_readl(cq_host, CQHCI_IS);
+			cqhci_writel(cq_host, tmp, CQHCI_IS);
+			cqhci_writel(cq_host, CQHCI_HALT, CQHCI_CTL);
+		}
 	}
 }
 
@@ -1286,7 +1340,7 @@
 	 * system resume back.
 	 */
 	cqhci_writel(cq_host, 0, CQHCI_CTL);
-	if (cqhci_readl(cq_host, CQHCI_CTL) && CQHCI_HALT)
+	if (cqhci_readl(cq_host, CQHCI_CTL) & CQHCI_HALT)
 		dev_err(mmc_dev(host->mmc),
 			"failed to exit halt state when enable CQE\n");
 
@@ -1381,13 +1435,14 @@
 				host->mmc->parent->platform_data);
 	/* write_protect */
 	if (boarddata->wp_type == ESDHC_WP_GPIO) {
+		host->mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
+
 		err = mmc_gpiod_request_ro(host->mmc, "wp", 0, 0, NULL);
 		if (err) {
 			dev_err(mmc_dev(host->mmc),
 				"failed to request write-protect gpio!\n");
 			return err;
 		}
-		host->mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
 	}
 
 	/* card_detect */
@@ -1554,8 +1609,6 @@
 	if (err)
 		goto disable_ahb_clk;
 
-	host->tuning_delay = 1;
-
 	sdhci_esdhc_imx_hwinit(host);
 
 	err = sdhci_add_host(host);
@@ -1588,9 +1641,10 @@
 	struct sdhci_host *host = platform_get_drvdata(pdev);
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host);
-	int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
+	int dead;
 
 	pm_runtime_get_sync(&pdev->dev);
+	dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff);
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_put_noidle(&pdev->dev);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/sdhci-esdhc.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/sdhci-esdhc.h
@@ -51,6 +51,11 @@
 #define ESDHC_CLOCK_HCKEN		0x00000002
 #define ESDHC_CLOCK_IPGEN		0x00000001
 
+/* System Control 2 Register */
+#define ESDHC_SYSTEM_CONTROL_2		0x3c
+#define ESDHC_SMPCLKSEL			0x00800000
+#define ESDHC_EXTN			0x00400000
+
 /* Host Controller Capabilities Register 2 */
 #define ESDHC_CAPABILITIES_1		0x114
 
@@ -59,7 +64,16 @@
 #define ESDHC_HS400_WNDW_ADJUST		0x00000040
 #define ESDHC_HS400_MODE		0x00000010
 #define ESDHC_TB_EN			0x00000004
+#define ESDHC_TB_MODE_MASK		0x00000003
+#define ESDHC_TB_MODE_SW		0x00000003
+#define ESDHC_TB_MODE_3			0x00000002
+
+#define ESDHC_TBSTAT			0x124
+
 #define ESDHC_TBPTR			0x128
+#define ESDHC_WNDW_STRT_PTR_SHIFT	8
+#define ESDHC_WNDW_STRT_PTR_MASK	(0x7f << 8)
+#define ESDHC_WNDW_END_PTR_MASK		0x7f
 
 /* SD Clock Control Register */
 #define ESDHC_SDCLKCTL			0x144
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/sdhci-msm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/sdhci-msm.c
@@ -99,7 +99,7 @@
 
 #define CORE_PWRSAVE_DLL	BIT(3)
 
-#define DDR_CONFIG_POR_VAL	0x80040853
+#define DDR_CONFIG_POR_VAL	0x80040873
 
 
 #define INVALID_TUNING_PHASE	-1
@@ -148,8 +148,9 @@
 	u32 core_ddr_200_cfg;
 	u32 core_vendor_spec3;
 	u32 core_dll_config_2;
+	u32 core_dll_config_3;
+	u32 core_ddr_config_old; /* Applicable to sdcc minor ver < 0x49 */
 	u32 core_ddr_config;
-	u32 core_ddr_config_2;
 };
 
 static const struct sdhci_msm_offset sdhci_msm_v5_offset = {
@@ -177,8 +178,8 @@
 	.core_ddr_200_cfg = 0x224,
 	.core_vendor_spec3 = 0x250,
 	.core_dll_config_2 = 0x254,
-	.core_ddr_config = 0x258,
-	.core_ddr_config_2 = 0x25c,
+	.core_dll_config_3 = 0x258,
+	.core_ddr_config = 0x25c,
 };
 
 static const struct sdhci_msm_offset sdhci_msm_mci_offset = {
@@ -207,8 +208,8 @@
 	.core_ddr_200_cfg = 0x184,
 	.core_vendor_spec3 = 0x1b0,
 	.core_dll_config_2 = 0x1b4,
-	.core_ddr_config = 0x1b8,
-	.core_ddr_config_2 = 0x1bc,
+	.core_ddr_config_old = 0x1b8,
+	.core_ddr_config = 0x1bc,
 };
 
 struct sdhci_msm_variant_ops {
@@ -253,6 +254,7 @@
 	const struct sdhci_msm_offset *offset;
 	bool use_cdr;
 	u32 transfer_mode;
+	bool updated_ddr_cfg;
 };
 
 static const struct sdhci_msm_offset *sdhci_priv_msm_offset(struct sdhci_host *host)
@@ -924,8 +926,10 @@
 static int sdhci_msm_cm_dll_sdc4_calibration(struct sdhci_host *host)
 {
 	struct mmc_host *mmc = host->mmc;
-	u32 dll_status, config;
+	u32 dll_status, config, ddr_cfg_offset;
 	int ret;
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
 	const struct sdhci_msm_offset *msm_offset =
 					sdhci_priv_msm_offset(host);
 
@@ -938,8 +942,11 @@
 	 * bootloaders. In the future, if this changes, then the desired
 	 * values will need to be programmed appropriately.
 	 */
-	writel_relaxed(DDR_CONFIG_POR_VAL, host->ioaddr +
-			msm_offset->core_ddr_config);
+	if (msm_host->updated_ddr_cfg)
+		ddr_cfg_offset = msm_offset->core_ddr_config;
+	else
+		ddr_cfg_offset = msm_offset->core_ddr_config_old;
+	writel_relaxed(DDR_CONFIG_POR_VAL, host->ioaddr + ddr_cfg_offset);
 
 	if (mmc->ios.enhanced_strobe) {
 		config = readl_relaxed(host->ioaddr +
@@ -1089,7 +1096,7 @@
 static int sdhci_msm_execute_tuning(struct mmc_host *mmc, u32 opcode)
 {
 	struct sdhci_host *host = mmc_priv(mmc);
-	int tuning_seq_cnt = 3;
+	int tuning_seq_cnt = 10;
 	u8 phase, tuned_phases[16], tuned_phase_cnt = 0;
 	int rc;
 	struct mmc_ios ios = host->mmc->ios;
@@ -1106,6 +1113,12 @@
 	msm_host->use_cdr = true;
 
 	/*
+	 * Clear tuning_done flag before tuning to ensure proper
+	 * HS400 settings.
+	 */
+	msm_host->tuning_done = 0;
+
+	/*
 	 * For HS400 tuning in HS200 timing requires:
 	 * - select MCLK/2 in VENDOR_SPEC
 	 * - program MCLK to 400MHz (or nearest supported) in GCC
@@ -1139,6 +1152,22 @@
 	} while (++phase < ARRAY_SIZE(tuned_phases));
 
 	if (tuned_phase_cnt) {
+		if (tuned_phase_cnt == ARRAY_SIZE(tuned_phases)) {
+			/*
+			 * All phases valid is _almost_ as bad as no phases
+			 * valid.  Probably all phases are not really reliable
+			 * but we didn't detect where the unreliable place is.
+			 * That means we'll essentially be guessing and hoping
+			 * we get a good phase.  Better to try a few times.
+			 */
+			dev_dbg(mmc_dev(mmc), "%s: All phases valid; try again\n",
+				mmc_hostname(mmc));
+			if (--tuning_seq_cnt) {
+				tuned_phase_cnt = 0;
+				goto retry;
+			}
+		}
+
 		rc = msm_find_most_appropriate_phase(host, tuned_phases,
 						     tuned_phase_cnt);
 		if (rc < 0)
@@ -1560,6 +1589,23 @@
 	__sdhci_msm_set_clock(host, clock);
 }
 
+static void sdhci_msm_set_timeout(struct sdhci_host *host, struct mmc_command *cmd)
+{
+	u32 count, start = 15;
+
+	__sdhci_set_timeout(host, cmd);
+	count = sdhci_readb(host, SDHCI_TIMEOUT_CONTROL);
+	/*
+	 * Update software timeout value if its value is less than hardware data
+	 * timeout value. Qcom SoC hardware data timeout value was calculated
+	 * using 4 * MCLK * 2^(count + 13). where MCLK = 1 / host->clock.
+	 */
+	if (cmd && cmd->data && host->clock > 400000 &&
+	    host->clock <= 50000000 &&
+	    ((1 << (count + start)) > (10 * host->clock)))
+		host->data_timeout = 22LL * NSEC_PER_SEC;
+}
+
 /*
  * Platform specific register write functions. This is so that, if any
  * register write needs to be followed up by platform specific actions,
@@ -1709,6 +1755,7 @@
 static const struct of_device_id sdhci_msm_dt_match[] = {
 	{.compatible = "qcom,sdhci-msm-v4", .data = &sdhci_msm_mci_var},
 	{.compatible = "qcom,sdhci-msm-v5", .data = &sdhci_msm_v5_var},
+	{.compatible = "qcom,sdm670-sdhci", .data = &sdm845_sdhci_var},
 	{.compatible = "qcom,sdm845-sdhci", .data = &sdm845_sdhci_var},
 	{},
 };
@@ -1724,12 +1771,15 @@
 	.set_uhs_signaling = sdhci_msm_set_uhs_signaling,
 	.write_w = sdhci_msm_writew,
 	.write_b = sdhci_msm_writeb,
+	.set_timeout = sdhci_msm_set_timeout,
 };
 
 static const struct sdhci_pltfm_data sdhci_msm_pdata = {
 	.quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION |
 		  SDHCI_QUIRK_SINGLE_POWER_WRITE |
-		  SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
+		  SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN |
+		  SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12,
+
 	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
 	.ops = &sdhci_msm_ops,
 };
@@ -1899,6 +1949,9 @@
 				msm_offset->core_vendor_spec_capabilities0);
 	}
 
+	if (core_major == 1 && core_minor >= 0x49)
+		msm_host->updated_ddr_cfg = true;
+
 	/*
 	 * Power on reset state may trigger power irq if previous status of
 	 * PWRCTL was either BUS_ON or IO_HIGH_V. So before enabling pwr irq
@@ -1934,6 +1987,8 @@
 		goto clk_disable;
 	}
 
+	msm_host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_NEED_RSP_BUSY;
+
 	pm_runtime_get_noresume(&pdev->dev);
 	pm_runtime_set_active(&pdev->dev);
 	pm_runtime_enable(&pdev->dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/sdhci-of-arasan.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/sdhci-of-arasan.c
@@ -22,16 +22,37 @@
 #include <linux/phy/phy.h>
 #include <linux/regmap.h>
 #include <linux/of.h>
+#include <linux/firmware/xlnx-zynqmp.h>
+#include <linux/pinctrl/consumer.h>
 
 #include "cqhci.h"
+#include "sdhci-cqhci.h"
 #include "sdhci-pltfm.h"
 
 #define SDHCI_ARASAN_VENDOR_REGISTER	0x78
+
+#define SDHCI_ARASAN_ITAPDLY_REGISTER	0xF0F8
+#define SDHCI_ARASAN_ITAPDLY_SEL_MASK	0xFF
+
+#define SDHCI_ARASAN_OTAPDLY_REGISTER	0xF0FC
+#define SDHCI_ARASAN_OTAPDLY_SEL_MASK	0x3F
+
 #define SDHCI_ARASAN_CQE_BASE_ADDR	0x200
 #define VENDOR_ENHANCED_STROBE		BIT(0)
 
 #define PHY_CLK_TOO_SLOW_HZ		400000
 
+#define SDHCI_ITAPDLY_CHGWIN		0x200
+#define SDHCI_ITAPDLY_ENABLE		0x100
+#define SDHCI_OTAPDLY_ENABLE		0x40
+
+/* Default settings for ZynqMP Clock Phases */
+#define ZYNQMP_ICLK_PHASE {0, 63, 63, 0, 63,  0,   0, 183, 54,  0, 0}
+#define ZYNQMP_OCLK_PHASE {0, 72, 60, 0, 60, 72, 135, 48, 72, 135, 0}
+
+#define VERSAL_ICLK_PHASE {0, 132, 132, 0, 132, 0, 0, 162, 90, 0, 0}
+#define VERSAL_OCLK_PHASE {0,  60, 48, 0, 48, 72, 90, 36, 60, 90, 0}
+
 /*
  * On some SoCs the syscon area has a feature where the upper 16-bits of
  * each 32-bit register act as a write mask for the lower 16-bits.  This allows
@@ -72,15 +93,42 @@
 };
 
 /**
+ * struct sdhci_arasan_clk_data
+ * @sdcardclk_hw:	Struct for the clock we might provide to a PHY.
+ * @sdcardclk:		Pointer to normal 'struct clock' for sdcardclk_hw.
+ * @sampleclk_hw:	Struct for the clock we might provide to a PHY.
+ * @sampleclk:		Pointer to normal 'struct clock' for sampleclk_hw.
+ * @clk_phase_in:	Array of Input Clock Phase Delays for all speed modes
+ * @clk_phase_out:	Array of Output Clock Phase Delays for all speed modes
+ * @set_clk_delays:	Function pointer for setting Clock Delays
+ * @clk_of_data:	Platform specific runtime clock data storage pointer
+ */
+struct sdhci_arasan_clk_data {
+	struct clk_hw	sdcardclk_hw;
+	struct clk      *sdcardclk;
+	struct clk_hw	sampleclk_hw;
+	struct clk      *sampleclk;
+	int		clk_phase_in[MMC_TIMING_MMC_HS400 + 1];
+	int		clk_phase_out[MMC_TIMING_MMC_HS400 + 1];
+	void		(*set_clk_delays)(struct sdhci_host *host);
+	void		*clk_of_data;
+};
+
+struct sdhci_arasan_zynqmp_clk_data {
+	const struct zynqmp_eemi_ops *eemi_ops;
+};
+
+/**
  * struct sdhci_arasan_data
  * @host:		Pointer to the main SDHCI host structure.
  * @clk_ahb:		Pointer to the AHB clock
  * @phy:		Pointer to the generic phy
  * @is_phy_on:		True if the PHY is on; false if not.
- * @sdcardclk_hw:	Struct for the clock we might provide to a PHY.
- * @sdcardclk:		Pointer to normal 'struct clock' for sdcardclk_hw.
+ * @clk_data:		Struct for the Arasan Controller Clock Data.
  * @soc_ctl_base:	Pointer to regmap for syscon for soc_ctl registers.
  * @soc_ctl_map:	Map to get offsets into soc_ctl registers.
+ * @pinctrl:		Per-device pin control state holder.
+ * @pins_default:	Pinctrl state for a device.
  */
 struct sdhci_arasan_data {
 	struct sdhci_host *host;
@@ -89,11 +137,12 @@
 	bool		is_phy_on;
 
 	bool		has_cqe;
-	struct clk_hw	sdcardclk_hw;
-	struct clk      *sdcardclk;
+	struct sdhci_arasan_clk_data clk_data;
 
 	struct regmap	*soc_ctl_base;
 	const struct sdhci_arasan_soc_ctl_map *soc_ctl_map;
+	struct pinctrl *pinctrl;
+	struct pinctrl_state *pins_default;
 	unsigned int	quirks; /* Arasan deviations from spec */
 
 /* Controller does not have CD wired and will not function normally without */
@@ -101,6 +150,12 @@
 /* Controller immediately reports SDHCI_CLOCK_INT_STABLE after enabling the
  * internal clock even when the clock isn't stable */
 #define SDHCI_ARASAN_QUIRK_CLOCK_UNSTABLE BIT(1)
+/*
+ * Some of the Arasan variations might not have timing requirements
+ * met at 25MHz for Default Speed mode, those controllers work at
+ * 19MHz instead
+ */
+#define SDHCI_ARASAN_QUIRK_CLOCK_25_BROKEN BIT(2)
 };
 
 struct sdhci_arasan_of_data {
@@ -174,6 +229,7 @@
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
+	struct sdhci_arasan_clk_data *clk_data = &sdhci_arasan->clk_data;
 	bool ctrl_phy = false;
 
 	if (!IS_ERR(sdhci_arasan->phy)) {
@@ -192,7 +248,12 @@
 			 * through low speeds without power cycling.
 			 */
 			sdhci_set_clock(host, host->max_clk);
-			phy_power_on(sdhci_arasan->phy);
+			if (phy_power_on(sdhci_arasan->phy)) {
+				pr_err("%s: Cannot power on phy.\n",
+				       mmc_hostname(host->mmc));
+				return;
+			}
+
 			sdhci_arasan->is_phy_on = true;
 
 			/*
@@ -215,6 +276,20 @@
 		sdhci_arasan->is_phy_on = false;
 	}
 
+	if (sdhci_arasan->quirks & SDHCI_ARASAN_QUIRK_CLOCK_25_BROKEN) {
+		/*
+		 * Some of the Arasan variations might not have timing
+		 * requirements met at 25MHz for Default Speed mode,
+		 * those controllers work at 19MHz instead.
+		 */
+		if (clock == DEFAULT_SPEED_MAX_DTR)
+			clock = (DEFAULT_SPEED_MAX_DTR * 19) / 25;
+	}
+
+	/* Set the Input and Output Clock Phase Delays */
+	if (clk_data->set_clk_delays)
+		clk_data->set_clk_delays(host);
+
 	sdhci_set_clock(host, clock);
 
 	if (sdhci_arasan->quirks & SDHCI_ARASAN_QUIRK_CLOCK_UNSTABLE)
@@ -228,7 +303,12 @@
 		msleep(20);
 
 	if (ctrl_phy) {
-		phy_power_on(sdhci_arasan->phy);
+		if (phy_power_on(sdhci_arasan->phy)) {
+			pr_err("%s: Cannot power on phy.\n",
+			       mmc_hostname(host->mmc));
+			return;
+		}
+
 		sdhci_arasan->is_phy_on = true;
 	}
 }
@@ -254,7 +334,7 @@
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
 
-	sdhci_reset(host, mask);
+	sdhci_and_cqhci_reset(host, mask);
 
 	if (sdhci_arasan->quirks & SDHCI_ARASAN_QUIRK_FORCE_CDTEST) {
 		ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
@@ -318,6 +398,17 @@
 	.pdata = &sdhci_arasan_pdata,
 };
 
+static const struct sdhci_pltfm_data sdhci_arasan_zynqmp_pdata = {
+	.ops = &sdhci_arasan_ops,
+	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
+			SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN |
+			SDHCI_QUIRK2_STOP_WITH_TC,
+};
+
+static struct sdhci_arasan_of_data sdhci_arasan_zynqmp_data = {
+	.pdata = &sdhci_arasan_zynqmp_pdata,
+};
+
 static u32 sdhci_arasan_cqhci_irq(struct sdhci_host *host, u32 intmask)
 {
 	int cmd_error = 0;
@@ -416,7 +507,9 @@
 		ret = phy_power_off(sdhci_arasan->phy);
 		if (ret) {
 			dev_err(dev, "Cannot power off phy.\n");
-			sdhci_resume_host(host);
+			if (sdhci_resume_host(host))
+				dev_err(dev, "Cannot resume host.\n");
+
 			return ret;
 		}
 		sdhci_arasan->is_phy_on = false;
@@ -502,6 +595,14 @@
 		.compatible = "arasan,sdhci-4.9a",
 		.data = &sdhci_arasan_data,
 	},
+	{
+		.compatible = "xlnx,zynqmp-8.9a",
+		.data = &sdhci_arasan_zynqmp_data,
+	},
+	{
+		.compatible = "xlnx,versal-8.9a",
+		.data = &sdhci_arasan_zynqmp_data,
+	},
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, sdhci_arasan_of_match);
@@ -520,8 +621,10 @@
 						      unsigned long parent_rate)
 
 {
+	struct sdhci_arasan_clk_data *clk_data =
+		container_of(hw, struct sdhci_arasan_clk_data, sdcardclk_hw);
 	struct sdhci_arasan_data *sdhci_arasan =
-		container_of(hw, struct sdhci_arasan_data, sdcardclk_hw);
+		container_of(clk_data, struct sdhci_arasan_data, clk_data);
 	struct sdhci_host *host = sdhci_arasan->host;
 
 	return host->mmc->actual_clock;
@@ -532,6 +635,383 @@
 };
 
 /**
+ * sdhci_arasan_sampleclk_recalc_rate - Return the sampling clock rate
+ *
+ * Return the current actual rate of the sampling clock.  This can be used
+ * to communicate with out PHY.
+ *
+ * @hw:			Pointer to the hardware clock structure.
+ * @parent_rate		The parent rate (should be rate of clk_xin).
+ * Returns the sample clock rate.
+ */
+static unsigned long sdhci_arasan_sampleclk_recalc_rate(struct clk_hw *hw,
+						      unsigned long parent_rate)
+
+{
+	struct sdhci_arasan_clk_data *clk_data =
+		container_of(hw, struct sdhci_arasan_clk_data, sampleclk_hw);
+	struct sdhci_arasan_data *sdhci_arasan =
+		container_of(clk_data, struct sdhci_arasan_data, clk_data);
+	struct sdhci_host *host = sdhci_arasan->host;
+
+	return host->mmc->actual_clock;
+}
+
+static const struct clk_ops arasan_sampleclk_ops = {
+	.recalc_rate = sdhci_arasan_sampleclk_recalc_rate,
+};
+
+/**
+ * sdhci_zynqmp_sdcardclk_set_phase - Set the SD Output Clock Tap Delays
+ *
+ * Set the SD Output Clock Tap Delays for Output path
+ *
+ * @hw:			Pointer to the hardware clock structure.
+ * @degrees		The clock phase shift between 0 - 359.
+ * Return: 0 on success and error value on error
+ */
+static int sdhci_zynqmp_sdcardclk_set_phase(struct clk_hw *hw, int degrees)
+{
+	struct sdhci_arasan_clk_data *clk_data =
+		container_of(hw, struct sdhci_arasan_clk_data, sdcardclk_hw);
+	struct sdhci_arasan_data *sdhci_arasan =
+		container_of(clk_data, struct sdhci_arasan_data, clk_data);
+	struct sdhci_host *host = sdhci_arasan->host;
+	struct sdhci_arasan_zynqmp_clk_data *zynqmp_clk_data =
+		clk_data->clk_of_data;
+	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_clk_data->eemi_ops;
+	const char *clk_name = clk_hw_get_name(hw);
+	u32 node_id = !strcmp(clk_name, "clk_out_sd0") ? NODE_SD_0 : NODE_SD_1;
+	u8 tap_delay, tap_max = 0;
+	int ret;
+
+	/*
+	 * This is applicable for SDHCI_SPEC_300 and above
+	 * ZynqMP does not set phase for <=25MHz clock.
+	 * If degrees is zero, no need to do anything.
+	 */
+	if (host->version < SDHCI_SPEC_300)
+		return 0;
+
+	switch (host->timing) {
+	case MMC_TIMING_MMC_HS:
+	case MMC_TIMING_SD_HS:
+	case MMC_TIMING_UHS_SDR25:
+	case MMC_TIMING_UHS_DDR50:
+	case MMC_TIMING_MMC_DDR52:
+		/* For 50MHz clock, 30 Taps are available */
+		tap_max = 30;
+		break;
+	case MMC_TIMING_UHS_SDR50:
+		/* For 100MHz clock, 15 Taps are available */
+		tap_max = 15;
+		break;
+	case MMC_TIMING_UHS_SDR104:
+	case MMC_TIMING_MMC_HS200:
+		/* For 200MHz clock, 8 Taps are available */
+		tap_max = 8;
+	default:
+		break;
+	}
+
+	tap_delay = (degrees * tap_max) / 360;
+
+	/* Set the Clock Phase */
+	ret = eemi_ops->ioctl(node_id, IOCTL_SET_SD_TAPDELAY,
+			      PM_TAPDELAY_OUTPUT, tap_delay, NULL);
+	if (ret)
+		pr_err("Error setting Output Tap Delay\n");
+
+	eemi_ops->ioctl(node_id, IOCTL_SD_DLL_RESET,
+			PM_DLL_RESET_RELEASE, 0, NULL);
+
+	return ret;
+}
+
+static const struct clk_ops zynqmp_sdcardclk_ops = {
+	.recalc_rate = sdhci_arasan_sdcardclk_recalc_rate,
+	.set_phase = sdhci_zynqmp_sdcardclk_set_phase,
+};
+
+/**
+ * sdhci_zynqmp_sampleclk_set_phase - Set the SD Input Clock Tap Delays
+ *
+ * Set the SD Input Clock Tap Delays for Input path
+ *
+ * @hw:			Pointer to the hardware clock structure.
+ * @degrees		The clock phase shift between 0 - 359.
+ * Return: 0 on success and error value on error
+ */
+static int sdhci_zynqmp_sampleclk_set_phase(struct clk_hw *hw, int degrees)
+{
+	struct sdhci_arasan_clk_data *clk_data =
+		container_of(hw, struct sdhci_arasan_clk_data, sampleclk_hw);
+	struct sdhci_arasan_data *sdhci_arasan =
+		container_of(clk_data, struct sdhci_arasan_data, clk_data);
+	struct sdhci_host *host = sdhci_arasan->host;
+	struct sdhci_arasan_zynqmp_clk_data *zynqmp_clk_data =
+		clk_data->clk_of_data;
+	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_clk_data->eemi_ops;
+	const char *clk_name = clk_hw_get_name(hw);
+	u32 node_id = !strcmp(clk_name, "clk_in_sd0") ? NODE_SD_0 : NODE_SD_1;
+	u8 tap_delay, tap_max = 0;
+	int ret;
+
+	/*
+	 * This is applicable for SDHCI_SPEC_300 and above
+	 * ZynqMP does not set phase for <=25MHz clock.
+	 * If degrees is zero, no need to do anything.
+	 */
+	if (host->version < SDHCI_SPEC_300)
+		return 0;
+
+	eemi_ops->ioctl(node_id, IOCTL_SD_DLL_RESET,
+			PM_DLL_RESET_ASSERT, 0, NULL);
+
+	switch (host->timing) {
+	case MMC_TIMING_MMC_HS:
+	case MMC_TIMING_SD_HS:
+	case MMC_TIMING_UHS_SDR25:
+	case MMC_TIMING_UHS_DDR50:
+	case MMC_TIMING_MMC_DDR52:
+		/* For 50MHz clock, 120 Taps are available */
+		tap_max = 120;
+		break;
+	case MMC_TIMING_UHS_SDR50:
+		/* For 100MHz clock, 60 Taps are available */
+		tap_max = 60;
+		break;
+	case MMC_TIMING_UHS_SDR104:
+	case MMC_TIMING_MMC_HS200:
+		/* For 200MHz clock, 30 Taps are available */
+		tap_max = 30;
+	default:
+		break;
+	}
+
+	tap_delay = (degrees * tap_max) / 360;
+
+	/* Set the Clock Phase */
+	ret = eemi_ops->ioctl(node_id, IOCTL_SET_SD_TAPDELAY,
+			      PM_TAPDELAY_INPUT, tap_delay, NULL);
+	if (ret)
+		pr_err("Error setting Input Tap Delay\n");
+
+	return ret;
+}
+
+static const struct clk_ops zynqmp_sampleclk_ops = {
+	.recalc_rate = sdhci_arasan_sampleclk_recalc_rate,
+	.set_phase = sdhci_zynqmp_sampleclk_set_phase,
+};
+
+/**
+ * sdhci_versal_sdcardclk_set_phase - Set the SD Output Clock Tap Delays
+ *
+ * Set the SD Output Clock Tap Delays for Output path
+ *
+ * @hw:			Pointer to the hardware clock structure.
+ * @degrees		The clock phase shift between 0 - 359.
+ * Return: 0
+ */
+static int sdhci_versal_sdcardclk_set_phase(struct clk_hw *hw, int degrees)
+{
+	struct sdhci_arasan_clk_data *clk_data =
+		container_of(hw, struct sdhci_arasan_clk_data, sdcardclk_hw);
+	struct sdhci_arasan_data *sdhci_arasan =
+		container_of(clk_data, struct sdhci_arasan_data, clk_data);
+	struct sdhci_host *host = sdhci_arasan->host;
+	u8 tap_delay, tap_max = 0;
+
+	/*
+	 * This is applicable for SDHCI_SPEC_300 and above
+	 * Versal does not set phase for <=25MHz clock.
+	 * If degrees is zero, no need to do anything.
+	 */
+	if (host->version < SDHCI_SPEC_300)
+		return 0;
+
+	switch (host->timing) {
+	case MMC_TIMING_MMC_HS:
+	case MMC_TIMING_SD_HS:
+	case MMC_TIMING_UHS_SDR25:
+	case MMC_TIMING_UHS_DDR50:
+	case MMC_TIMING_MMC_DDR52:
+		/* For 50MHz clock, 30 Taps are available */
+		tap_max = 30;
+		break;
+	case MMC_TIMING_UHS_SDR50:
+		/* For 100MHz clock, 15 Taps are available */
+		tap_max = 15;
+		break;
+	case MMC_TIMING_UHS_SDR104:
+	case MMC_TIMING_MMC_HS200:
+		/* For 200MHz clock, 8 Taps are available */
+		tap_max = 8;
+	default:
+		break;
+	}
+
+	tap_delay = (degrees * tap_max) / 360;
+
+	/* Set the Clock Phase */
+	if (tap_delay) {
+		u32 regval;
+
+		regval = sdhci_readl(host, SDHCI_ARASAN_OTAPDLY_REGISTER);
+		regval |= SDHCI_OTAPDLY_ENABLE;
+		sdhci_writel(host, regval, SDHCI_ARASAN_OTAPDLY_REGISTER);
+		regval &= ~SDHCI_ARASAN_OTAPDLY_SEL_MASK;
+		regval |= tap_delay;
+		sdhci_writel(host, regval, SDHCI_ARASAN_OTAPDLY_REGISTER);
+	}
+
+	return 0;
+}
+
+static const struct clk_ops versal_sdcardclk_ops = {
+	.recalc_rate = sdhci_arasan_sdcardclk_recalc_rate,
+	.set_phase = sdhci_versal_sdcardclk_set_phase,
+};
+
+/**
+ * sdhci_versal_sampleclk_set_phase - Set the SD Input Clock Tap Delays
+ *
+ * Set the SD Input Clock Tap Delays for Input path
+ *
+ * @hw:			Pointer to the hardware clock structure.
+ * @degrees		The clock phase shift between 0 - 359.
+ * Return: 0
+ */
+static int sdhci_versal_sampleclk_set_phase(struct clk_hw *hw, int degrees)
+{
+	struct sdhci_arasan_clk_data *clk_data =
+		container_of(hw, struct sdhci_arasan_clk_data, sampleclk_hw);
+	struct sdhci_arasan_data *sdhci_arasan =
+		container_of(clk_data, struct sdhci_arasan_data, clk_data);
+	struct sdhci_host *host = sdhci_arasan->host;
+	u8 tap_delay, tap_max = 0;
+
+	/*
+	 * This is applicable for SDHCI_SPEC_300 and above
+	 * Versal does not set phase for <=25MHz clock.
+	 * If degrees is zero, no need to do anything.
+	 */
+	if (host->version < SDHCI_SPEC_300)
+		return 0;
+
+	switch (host->timing) {
+	case MMC_TIMING_MMC_HS:
+	case MMC_TIMING_SD_HS:
+	case MMC_TIMING_UHS_SDR25:
+	case MMC_TIMING_UHS_DDR50:
+	case MMC_TIMING_MMC_DDR52:
+		/* For 50MHz clock, 120 Taps are available */
+		tap_max = 120;
+		break;
+	case MMC_TIMING_UHS_SDR50:
+		/* For 100MHz clock, 60 Taps are available */
+		tap_max = 60;
+		break;
+	case MMC_TIMING_UHS_SDR104:
+	case MMC_TIMING_MMC_HS200:
+		/* For 200MHz clock, 30 Taps are available */
+		tap_max = 30;
+	default:
+		break;
+	}
+
+	tap_delay = (degrees * tap_max) / 360;
+
+	/* Set the Clock Phase */
+	if (tap_delay) {
+		u32 regval;
+
+		regval = sdhci_readl(host, SDHCI_ARASAN_ITAPDLY_REGISTER);
+		regval |= SDHCI_ITAPDLY_CHGWIN;
+		sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
+		regval |= SDHCI_ITAPDLY_ENABLE;
+		sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
+		regval &= ~SDHCI_ARASAN_ITAPDLY_SEL_MASK;
+		regval |= tap_delay;
+		sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
+		regval &= ~SDHCI_ITAPDLY_CHGWIN;
+		sdhci_writel(host, regval, SDHCI_ARASAN_ITAPDLY_REGISTER);
+	}
+
+	return 0;
+}
+
+static const struct clk_ops versal_sampleclk_ops = {
+	.recalc_rate = sdhci_arasan_sampleclk_recalc_rate,
+	.set_phase = sdhci_versal_sampleclk_set_phase,
+};
+static void arasan_zynqmp_dll_reset(struct sdhci_host *host, u32 deviceid)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
+	struct sdhci_arasan_zynqmp_clk_data *zynqmp_clk_data =
+		sdhci_arasan->clk_data.clk_of_data;
+	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_clk_data->eemi_ops;
+	u16 clk;
+	unsigned long timeout;
+
+	clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+	clk &= ~(SDHCI_CLOCK_CARD_EN | SDHCI_CLOCK_INT_EN);
+	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+
+	/* Issue DLL Reset */
+	eemi_ops->ioctl(deviceid, IOCTL_SD_DLL_RESET,
+			PM_DLL_RESET_PULSE, 0, NULL);
+
+	clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+	clk |= SDHCI_CLOCK_INT_EN;
+	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+
+	/* Wait max 20 ms */
+	timeout = 20;
+	while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
+				& SDHCI_CLOCK_INT_STABLE)) {
+		if (timeout == 0) {
+			dev_err(mmc_dev(host->mmc),
+				": Internal clock never stabilised.\n");
+			return;
+		}
+		timeout--;
+		mdelay(1);
+	}
+
+	clk |= SDHCI_CLOCK_CARD_EN;
+	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+}
+
+static int arasan_zynqmp_execute_tuning(struct mmc_host *mmc, u32 opcode)
+{
+	struct sdhci_host *host = mmc_priv(mmc);
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
+	struct clk_hw *hw = &sdhci_arasan->clk_data.sdcardclk_hw;
+	const char *clk_name = clk_hw_get_name(hw);
+	u32 device_id = !strcmp(clk_name, "clk_out_sd0") ? NODE_SD_0 :
+							   NODE_SD_1;
+	int err;
+
+	/* ZynqMP SD controller does not perform auto tuning in DDR50 mode */
+	if (mmc->ios.timing == MMC_TIMING_UHS_DDR50)
+		return 0;
+
+	arasan_zynqmp_dll_reset(host, device_id);
+
+	err = sdhci_execute_tuning(mmc, opcode);
+	if (err)
+		return err;
+
+	arasan_zynqmp_dll_reset(host, device_id);
+
+	return 0;
+}
+
+/**
  * sdhci_arasan_update_clockmultiplier - Set corecfg_clockmultiplier
  *
  * The corecfg_clockmultiplier is supposed to contain clock multiplier
@@ -593,7 +1073,7 @@
 	struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
 	const struct sdhci_arasan_soc_ctl_map *soc_ctl_map =
 		sdhci_arasan->soc_ctl_map;
-	u32 mhz = DIV_ROUND_CLOSEST(clk_get_rate(pltfm_host->clk), 1000000);
+	u32 mhz = DIV_ROUND_CLOSEST_ULL(clk_get_rate(pltfm_host->clk), 1000000);
 
 	/* Having a map is optional */
 	if (!soc_ctl_map)
@@ -609,39 +1089,143 @@
 	sdhci_arasan_syscon_write(host, &soc_ctl_map->baseclkfreq, mhz);
 }
 
+static void sdhci_arasan_set_clk_delays(struct sdhci_host *host)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
+	struct sdhci_arasan_clk_data *clk_data = &sdhci_arasan->clk_data;
+
+	clk_set_phase(clk_data->sampleclk,
+		      clk_data->clk_phase_in[host->timing]);
+	clk_set_phase(clk_data->sdcardclk,
+		      clk_data->clk_phase_out[host->timing]);
+}
+
+static void arasan_dt_read_clk_phase(struct device *dev,
+				     struct sdhci_arasan_clk_data *clk_data,
+				     unsigned int timing, const char *prop)
+{
+	struct device_node *np = dev->of_node;
+
+	u32 clk_phase[2] = {0};
+	int ret;
+
+	/*
+	 * Read Tap Delay values from DT, if the DT does not contain the
+	 * Tap Values then use the pre-defined values.
+	 */
+	ret = of_property_read_variable_u32_array(np, prop, &clk_phase[0],
+						  2, 0);
+	if (ret < 0) {
+		dev_dbg(dev, "Using predefined clock phase for %s = %d %d\n",
+			prop, clk_data->clk_phase_in[timing],
+			clk_data->clk_phase_out[timing]);
+		return;
+	}
+
+	/* The values read are Input and Output Clock Delays in order */
+	clk_data->clk_phase_in[timing] = clk_phase[0];
+	clk_data->clk_phase_out[timing] = clk_phase[1];
+}
+
+/**
+ * arasan_dt_parse_clk_phases - Read Clock Delay values from DT
+ *
+ * Called at initialization to parse the values of Clock Delays.
+ *
+ * @dev:		Pointer to our struct device.
+ * @clk_data:		Pointer to the Clock Data structure
+ */
+static void arasan_dt_parse_clk_phases(struct device *dev,
+				       struct sdhci_arasan_clk_data *clk_data)
+{
+	u32 mio_bank = 0;
+	int i;
+
+	/*
+	 * This has been kept as a pointer and is assigned a function here.
+	 * So that different controller variants can assign their own handling
+	 * function.
+	 */
+	clk_data->set_clk_delays = sdhci_arasan_set_clk_delays;
+
+	if (of_device_is_compatible(dev->of_node, "xlnx,zynqmp-8.9a")) {
+		u32 zynqmp_iclk_phase[MMC_TIMING_MMC_HS400 + 1] =
+			ZYNQMP_ICLK_PHASE;
+		u32 zynqmp_oclk_phase[MMC_TIMING_MMC_HS400 + 1] =
+			ZYNQMP_OCLK_PHASE;
+
+		of_property_read_u32(dev->of_node, "xlnx,mio-bank", &mio_bank);
+		if (mio_bank == 2) {
+			zynqmp_oclk_phase[MMC_TIMING_UHS_SDR104] = 90;
+			zynqmp_oclk_phase[MMC_TIMING_MMC_HS200] = 90;
+		}
+
+		for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) {
+			clk_data->clk_phase_in[i] = zynqmp_iclk_phase[i];
+			clk_data->clk_phase_out[i] = zynqmp_oclk_phase[i];
+		}
+	}
+
+	if (of_device_is_compatible(dev->of_node, "xlnx,versal-8.9a")) {
+		u32 versal_iclk_phase[MMC_TIMING_MMC_HS400 + 1] =
+			VERSAL_ICLK_PHASE;
+		u32 versal_oclk_phase[MMC_TIMING_MMC_HS400 + 1] =
+			VERSAL_OCLK_PHASE;
+
+		for (i = 0; i <= MMC_TIMING_MMC_HS400; i++) {
+			clk_data->clk_phase_in[i] = versal_iclk_phase[i];
+			clk_data->clk_phase_out[i] = versal_oclk_phase[i];
+		}
+	}
+
+	arasan_dt_read_clk_phase(dev, clk_data, MMC_TIMING_LEGACY,
+				 "clk-phase-legacy");
+	arasan_dt_read_clk_phase(dev, clk_data, MMC_TIMING_MMC_HS,
+				 "clk-phase-mmc-hs");
+	arasan_dt_read_clk_phase(dev, clk_data, MMC_TIMING_SD_HS,
+				 "clk-phase-sd-hs");
+	arasan_dt_read_clk_phase(dev, clk_data, MMC_TIMING_UHS_SDR12,
+				 "clk-phase-uhs-sdr12");
+	arasan_dt_read_clk_phase(dev, clk_data, MMC_TIMING_UHS_SDR25,
+				 "clk-phase-uhs-sdr25");
+	arasan_dt_read_clk_phase(dev, clk_data, MMC_TIMING_UHS_SDR50,
+				 "clk-phase-uhs-sdr50");
+	arasan_dt_read_clk_phase(dev, clk_data, MMC_TIMING_UHS_SDR104,
+				 "clk-phase-uhs-sdr104");
+	arasan_dt_read_clk_phase(dev, clk_data, MMC_TIMING_UHS_DDR50,
+				 "clk-phase-uhs-ddr50");
+	arasan_dt_read_clk_phase(dev, clk_data, MMC_TIMING_MMC_DDR52,
+				 "clk-phase-mmc-ddr52");
+	arasan_dt_read_clk_phase(dev, clk_data, MMC_TIMING_MMC_HS200,
+				 "clk-phase-mmc-hs200");
+	arasan_dt_read_clk_phase(dev, clk_data, MMC_TIMING_MMC_HS400,
+				 "clk-phase-mmc-hs400");
+}
+
 /**
- * sdhci_arasan_register_sdclk - Register the sdclk for a PHY to use
+ * sdhci_arasan_register_sdcardclk - Register the sdcardclk for a PHY to use
  *
  * Some PHY devices need to know what the actual card clock is.  In order for
  * them to find out, we'll provide a clock through the common clock framework
  * for them to query.
  *
- * Note: without seriously re-architecting SDHCI's clock code and testing on
- * all platforms, there's no way to create a totally beautiful clock here
- * with all clock ops implemented.  Instead, we'll just create a clock that can
- * be queried and set the CLK_GET_RATE_NOCACHE attribute to tell common clock
- * framework that we're doing things behind its back.  This should be sufficient
- * to create nice clean device tree bindings and later (if needed) we can try
- * re-architecting SDHCI if we see some benefit to it.
- *
  * @sdhci_arasan:	Our private data structure.
  * @clk_xin:		Pointer to the functional clock
  * @dev:		Pointer to our struct device.
  * Returns 0 on success and error value on error
  */
-static int sdhci_arasan_register_sdclk(struct sdhci_arasan_data *sdhci_arasan,
-				       struct clk *clk_xin,
-				       struct device *dev)
+static int
+sdhci_arasan_register_sdcardclk(struct sdhci_arasan_data *sdhci_arasan,
+				struct clk *clk_xin,
+				struct device *dev)
 {
+	struct sdhci_arasan_clk_data *clk_data = &sdhci_arasan->clk_data;
 	struct device_node *np = dev->of_node;
 	struct clk_init_data sdcardclk_init;
 	const char *parent_clk_name;
 	int ret;
 
-	/* Providing a clock to the PHY is optional; no error if missing */
-	if (!of_find_property(np, "#clock-cells", NULL))
-		return 0;
-
 	ret = of_property_read_string_index(np, "clock-output-names", 0,
 					    &sdcardclk_init.name);
 	if (ret) {
@@ -653,17 +1237,76 @@
 	sdcardclk_init.parent_names = &parent_clk_name;
 	sdcardclk_init.num_parents = 1;
 	sdcardclk_init.flags = CLK_GET_RATE_NOCACHE;
-	sdcardclk_init.ops = &arasan_sdcardclk_ops;
+	if (of_device_is_compatible(np, "xlnx,zynqmp-8.9a"))
+		sdcardclk_init.ops = &zynqmp_sdcardclk_ops;
+	else if (of_device_is_compatible(np, "xlnx,versal-8.9a"))
+		sdcardclk_init.ops = &versal_sdcardclk_ops;
+	else
+		sdcardclk_init.ops = &arasan_sdcardclk_ops;
 
-	sdhci_arasan->sdcardclk_hw.init = &sdcardclk_init;
-	sdhci_arasan->sdcardclk =
-		devm_clk_register(dev, &sdhci_arasan->sdcardclk_hw);
-	sdhci_arasan->sdcardclk_hw.init = NULL;
+	clk_data->sdcardclk_hw.init = &sdcardclk_init;
+	clk_data->sdcardclk =
+		devm_clk_register(dev, &clk_data->sdcardclk_hw);
+	clk_data->sdcardclk_hw.init = NULL;
 
 	ret = of_clk_add_provider(np, of_clk_src_simple_get,
-				  sdhci_arasan->sdcardclk);
+				  clk_data->sdcardclk);
 	if (ret)
-		dev_err(dev, "Failed to add clock provider\n");
+		dev_err(dev, "Failed to add sdcard clock provider\n");
+
+	return ret;
+}
+
+/**
+ * sdhci_arasan_register_sampleclk - Register the sampleclk for a PHY to use
+ *
+ * Some PHY devices need to know what the actual card clock is.  In order for
+ * them to find out, we'll provide a clock through the common clock framework
+ * for them to query.
+ *
+ * @sdhci_arasan:	Our private data structure.
+ * @clk_xin:		Pointer to the functional clock
+ * @dev:		Pointer to our struct device.
+ * Returns 0 on success and error value on error
+ */
+static int
+sdhci_arasan_register_sampleclk(struct sdhci_arasan_data *sdhci_arasan,
+				struct clk *clk_xin,
+				struct device *dev)
+{
+	struct sdhci_arasan_clk_data *clk_data = &sdhci_arasan->clk_data;
+	struct device_node *np = dev->of_node;
+	struct clk_init_data sampleclk_init;
+	const char *parent_clk_name;
+	int ret;
+
+	ret = of_property_read_string_index(np, "clock-output-names", 1,
+					    &sampleclk_init.name);
+	if (ret) {
+		dev_err(dev, "DT has #clock-cells but no clock-output-names\n");
+		return ret;
+	}
+
+	parent_clk_name = __clk_get_name(clk_xin);
+	sampleclk_init.parent_names = &parent_clk_name;
+	sampleclk_init.num_parents = 1;
+	sampleclk_init.flags = CLK_GET_RATE_NOCACHE;
+	if (of_device_is_compatible(np, "xlnx,zynqmp-8.9a"))
+		sampleclk_init.ops = &zynqmp_sampleclk_ops;
+	else if (of_device_is_compatible(np, "xlnx,versal-8.9a"))
+		sampleclk_init.ops = &versal_sampleclk_ops;
+	else
+		sampleclk_init.ops = &arasan_sampleclk_ops;
+
+	clk_data->sampleclk_hw.init = &sampleclk_init;
+	clk_data->sampleclk =
+		devm_clk_register(dev, &clk_data->sampleclk_hw);
+	clk_data->sampleclk_hw.init = NULL;
+
+	ret = of_clk_add_provider(np, of_clk_src_simple_get,
+				  clk_data->sampleclk);
+	if (ret)
+		dev_err(dev, "Failed to add sample clock provider\n");
 
 	return ret;
 }
@@ -686,6 +1329,54 @@
 	of_clk_del_provider(dev->of_node);
 }
 
+/**
+ * sdhci_arasan_register_sdclk - Register the sdcardclk for a PHY to use
+ *
+ * Some PHY devices need to know what the actual card clock is.  In order for
+ * them to find out, we'll provide a clock through the common clock framework
+ * for them to query.
+ *
+ * Note: without seriously re-architecting SDHCI's clock code and testing on
+ * all platforms, there's no way to create a totally beautiful clock here
+ * with all clock ops implemented.  Instead, we'll just create a clock that can
+ * be queried and set the CLK_GET_RATE_NOCACHE attribute to tell common clock
+ * framework that we're doing things behind its back.  This should be sufficient
+ * to create nice clean device tree bindings and later (if needed) we can try
+ * re-architecting SDHCI if we see some benefit to it.
+ *
+ * @sdhci_arasan:	Our private data structure.
+ * @clk_xin:		Pointer to the functional clock
+ * @dev:		Pointer to our struct device.
+ * Returns 0 on success and error value on error
+ */
+static int sdhci_arasan_register_sdclk(struct sdhci_arasan_data *sdhci_arasan,
+				       struct clk *clk_xin,
+				       struct device *dev)
+{
+	struct device_node *np = dev->of_node;
+	u32 num_clks = 0;
+	int ret;
+
+	/* Providing a clock to the PHY is optional; no error if missing */
+	if (of_property_read_u32(np, "#clock-cells", &num_clks) < 0)
+		return 0;
+
+	ret = sdhci_arasan_register_sdcardclk(sdhci_arasan, clk_xin, dev);
+	if (ret)
+		return ret;
+
+	if (num_clks) {
+		ret = sdhci_arasan_register_sampleclk(sdhci_arasan, clk_xin,
+						      dev);
+		if (ret) {
+			sdhci_arasan_unregister_sdclk(dev);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
 static int sdhci_arasan_add_host(struct sdhci_arasan_data *sdhci_arasan)
 {
 	struct sdhci_host *host = sdhci_arasan->host;
@@ -814,6 +1505,30 @@
 	if (ret)
 		goto clk_disable_all;
 
+	if (of_device_is_compatible(np, "xlnx,zynqmp-8.9a")) {
+		struct sdhci_arasan_zynqmp_clk_data *zynqmp_clk_data;
+		const struct zynqmp_eemi_ops *eemi_ops;
+
+		zynqmp_clk_data = devm_kzalloc(&pdev->dev,
+					       sizeof(*zynqmp_clk_data),
+					       GFP_KERNEL);
+		eemi_ops = zynqmp_pm_get_eemi_ops();
+		if (IS_ERR(eemi_ops)) {
+			ret = PTR_ERR(eemi_ops);
+			goto unreg_clk;
+		}
+
+		zynqmp_clk_data->eemi_ops = eemi_ops;
+		sdhci_arasan->clk_data.clk_of_data = zynqmp_clk_data;
+		host->mmc_host_ops.execute_tuning =
+			arasan_zynqmp_execute_tuning;
+
+		sdhci_arasan->quirks |= SDHCI_ARASAN_QUIRK_CLOCK_25_BROKEN;
+		host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
+	}
+
+	arasan_dt_parse_clk_phases(&pdev->dev, &sdhci_arasan->clk_data);
+
 	ret = mmc_of_parse(host->mmc);
 	if (ret) {
 		if (ret != -EPROBE_DEFER)
@@ -821,6 +1536,20 @@
 		goto unreg_clk;
 	}
 
+	sdhci_arasan->pinctrl = devm_pinctrl_get(&pdev->dev);
+	if (!IS_ERR(sdhci_arasan->pinctrl)) {
+		sdhci_arasan->pins_default =
+			pinctrl_lookup_state(sdhci_arasan->pinctrl,
+					     PINCTRL_STATE_DEFAULT);
+		if (IS_ERR(sdhci_arasan->pins_default)) {
+			dev_err(&pdev->dev, "Missing default pinctrl config\n");
+			return IS_ERR(sdhci_arasan->pins_default);
+		}
+
+		pinctrl_select_state(sdhci_arasan->pinctrl,
+				     sdhci_arasan->pins_default);
+	}
+
 	sdhci_arasan->phy = ERR_PTR(-ENODEV);
 	if (of_device_is_compatible(pdev->dev.of_node,
 				    "arasan,sdhci-5.1")) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/sdhci-of-aspeed.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/sdhci-of-aspeed.c
@@ -68,7 +68,7 @@
 	if (WARN_ON(clock > host->max_clk))
 		clock = host->max_clk;
 
-	for (div = 1; div < 256; div *= 2) {
+	for (div = 2; div < 256; div *= 2) {
 		if ((parent / div) <= clock)
 			break;
 	}
@@ -224,6 +224,7 @@
 	{ .compatible = "aspeed,ast2600-sdhci", },
 	{ }
 };
+MODULE_DEVICE_TABLE(of, aspeed_sdhci_of_match);
 
 static struct platform_driver aspeed_sdhci_driver = {
 	.driver		= {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/sdhci-of-at91.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/sdhci-of-at91.c
@@ -109,8 +109,13 @@
 static void sdhci_at91_set_uhs_signaling(struct sdhci_host *host,
 					 unsigned int timing)
 {
-	if (timing == MMC_TIMING_MMC_DDR52)
-		sdhci_writeb(host, SDMMC_MC1R_DDR, SDMMC_MC1R);
+	u8 mc1r;
+
+	if (timing == MMC_TIMING_MMC_DDR52) {
+		mc1r = sdhci_readb(host, SDMMC_MC1R);
+		mc1r |= SDMMC_MC1R_DDR;
+		sdhci_writeb(host, mc1r, SDMMC_MC1R);
+	}
 	sdhci_set_uhs_signaling(host, timing);
 }
 
@@ -118,7 +123,8 @@
 {
 	sdhci_reset(host, mask);
 
-	if (host->mmc->caps & MMC_CAP_NONREMOVABLE)
+	if ((host->mmc->caps & MMC_CAP_NONREMOVABLE)
+	    || mmc_gpio_get_cd(host->mmc) >= 0)
 		sdhci_at91_set_force_card_detect(host);
 }
 
@@ -324,19 +330,22 @@
 	priv->mainck = devm_clk_get(&pdev->dev, "baseclk");
 	if (IS_ERR(priv->mainck)) {
 		dev_err(&pdev->dev, "failed to get baseclk\n");
-		return PTR_ERR(priv->mainck);
+		ret = PTR_ERR(priv->mainck);
+		goto sdhci_pltfm_free;
 	}
 
 	priv->hclock = devm_clk_get(&pdev->dev, "hclock");
 	if (IS_ERR(priv->hclock)) {
 		dev_err(&pdev->dev, "failed to get hclock\n");
-		return PTR_ERR(priv->hclock);
+		ret = PTR_ERR(priv->hclock);
+		goto sdhci_pltfm_free;
 	}
 
 	priv->gck = devm_clk_get(&pdev->dev, "multclk");
 	if (IS_ERR(priv->gck)) {
 		dev_err(&pdev->dev, "failed to get multclk\n");
-		return PTR_ERR(priv->gck);
+		ret = PTR_ERR(priv->gck);
+		goto sdhci_pltfm_free;
 	}
 
 	ret = sdhci_at91_set_clks_presets(&pdev->dev);
@@ -394,8 +403,11 @@
 	 * detection procedure using the SDMCC_CD signal is bypassed.
 	 * This bit is reset when a software reset for all command is performed
 	 * so we need to implement our own reset function to set back this bit.
+	 *
+	 * WA: SAMA5D2 doesn't drive CMD if using CD GPIO line.
 	 */
-	if (host->mmc->caps & MMC_CAP_NONREMOVABLE)
+	if ((host->mmc->caps & MMC_CAP_NONREMOVABLE)
+	    || mmc_gpio_get_cd(host->mmc) >= 0)
 		sdhci_at91_set_force_card_detect(host);
 
 	pm_runtime_put_autosuspend(&pdev->dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/sdhci-of-dwcmshc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/sdhci-of-dwcmshc.c
@@ -58,6 +58,7 @@
 static const struct sdhci_pltfm_data sdhci_dwcmshc_pdata = {
 	.ops = &sdhci_dwcmshc_ops,
 	.quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
+	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
 };
 
 static int dwcmshc_probe(struct platform_device *pdev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/sdhci-of-esdhc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/sdhci-of-esdhc.c
@@ -77,8 +77,12 @@
 	bool quirk_incorrect_hostver;
 	bool quirk_limited_clk_division;
 	bool quirk_unreliable_pulse_detection;
-	bool quirk_fixup_tuning;
+	bool quirk_tuning_erratum_type1;
+	bool quirk_tuning_erratum_type2;
 	bool quirk_ignore_data_inhibit;
+	bool quirk_delay_before_data_reset;
+	bool quirk_trans_complete_erratum;
+	bool in_sw_tuning;
 	unsigned int peripheral_clock;
 	const struct esdhc_clk_fixup *clk_fixup;
 	u32 div_ratio;
@@ -120,6 +124,7 @@
 			return ret;
 		}
 	}
+
 	/*
 	 * The DAT[3:0] line signal levels and the CMD line signal level are
 	 * not compatible with standard SDHC register. The line signal levels
@@ -131,6 +136,16 @@
 		ret = value & 0x000fffff;
 		ret |= (value >> 4) & SDHCI_DATA_LVL_MASK;
 		ret |= (value << 1) & SDHCI_CMD_LVL;
+
+		/*
+		 * Some controllers have unreliable Data Line Active
+		 * bit for commands with busy signal. This affects
+		 * Command Inhibit (data) bit. Just ignore it since
+		 * MMC core driver has already polled card status
+		 * with CMD13 after any command with busy siganl.
+		 */
+		if (esdhc->quirk_ignore_data_inhibit)
+			ret &= ~SDHCI_DATA_INHIBIT;
 		return ret;
 	}
 
@@ -145,19 +160,6 @@
 		return ret;
 	}
 
-	/*
-	 * Some controllers have unreliable Data Line Active
-	 * bit for commands with busy signal. This affects
-	 * Command Inhibit (data) bit. Just ignore it since
-	 * MMC core driver has already polled card status
-	 * with CMD13 after any command with busy siganl.
-	 */
-	if ((spec_reg == SDHCI_PRESENT_STATE) &&
-	(esdhc->quirk_ignore_data_inhibit == true)) {
-		ret = value & ~SDHCI_DATA_INHIBIT;
-		return ret;
-	}
-
 	ret = value;
 	return ret;
 }
@@ -408,6 +410,8 @@
 
 static void esdhc_be_writew(struct sdhci_host *host, u16 val, int reg)
 {
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
 	int base = reg & ~0x3;
 	u32 value;
 	u32 ret;
@@ -416,10 +420,24 @@
 	ret = esdhc_writew_fixup(host, reg, val, value);
 	if (reg != SDHCI_TRANSFER_MODE)
 		iowrite32be(ret, host->ioaddr + base);
+
+	/* Starting SW tuning requires ESDHC_SMPCLKSEL to be set
+	 * 1us later after ESDHC_EXTN is set.
+	 */
+	if (base == ESDHC_SYSTEM_CONTROL_2) {
+		if (!(value & ESDHC_EXTN) && (ret & ESDHC_EXTN) &&
+		    esdhc->in_sw_tuning) {
+			udelay(1);
+			ret |= ESDHC_SMPCLKSEL;
+			iowrite32be(ret, host->ioaddr + base);
+		}
+	}
 }
 
 static void esdhc_le_writew(struct sdhci_host *host, u16 val, int reg)
 {
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
 	int base = reg & ~0x3;
 	u32 value;
 	u32 ret;
@@ -428,6 +446,18 @@
 	ret = esdhc_writew_fixup(host, reg, val, value);
 	if (reg != SDHCI_TRANSFER_MODE)
 		iowrite32(ret, host->ioaddr + base);
+
+	/* Starting SW tuning requires ESDHC_SMPCLKSEL to be set
+	 * 1us later after ESDHC_EXTN is set.
+	 */
+	if (base == ESDHC_SYSTEM_CONTROL_2) {
+		if (!(value & ESDHC_EXTN) && (ret & ESDHC_EXTN) &&
+		    esdhc->in_sw_tuning) {
+			udelay(1);
+			ret |= ESDHC_SMPCLKSEL;
+			iowrite32(ret, host->ioaddr + base);
+		}
+	}
 }
 
 static void esdhc_be_writeb(struct sdhci_host *host, u8 val, int reg)
@@ -487,12 +517,16 @@
 
 static int esdhc_of_enable_dma(struct sdhci_host *host)
 {
+	int ret;
 	u32 value;
 	struct device *dev = mmc_dev(host->mmc);
 
 	if (of_device_is_compatible(dev->of_node, "fsl,ls1043a-esdhc") ||
-	    of_device_is_compatible(dev->of_node, "fsl,ls1046a-esdhc"))
-		dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40));
+	    of_device_is_compatible(dev->of_node, "fsl,ls1046a-esdhc")) {
+		ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40));
+		if (ret)
+			return ret;
+	}
 
 	value = sdhci_readl(host, ESDHC_DMA_SYSCTL);
 
@@ -703,21 +737,58 @@
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
-	u32 val;
+	u32 val, bus_width = 0;
+
+	/*
+	 * Add delay to make sure all the DMA transfers are finished
+	 * for quirk.
+	 */
+	if (esdhc->quirk_delay_before_data_reset &&
+	    (mask & SDHCI_RESET_DATA) &&
+	    (host->flags & SDHCI_REQ_USE_DMA))
+		mdelay(5);
+
+	/*
+	 * Save bus-width for eSDHC whose vendor version is 2.2
+	 * or lower for data reset.
+	 */
+	if ((mask & SDHCI_RESET_DATA) &&
+	    (esdhc->vendor_ver <= VENDOR_V_22)) {
+		val = sdhci_readl(host, ESDHC_PROCTL);
+		bus_width = val & ESDHC_CTRL_BUSWIDTH_MASK;
+	}
 
 	sdhci_reset(host, mask);
 
-	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
-	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
+	/*
+	 * Restore bus-width setting and interrupt registers for eSDHC
+	 * whose vendor version is 2.2 or lower for data reset.
+	 */
+	if ((mask & SDHCI_RESET_DATA) &&
+	    (esdhc->vendor_ver <= VENDOR_V_22)) {
+		val = sdhci_readl(host, ESDHC_PROCTL);
+		val &= ~ESDHC_CTRL_BUSWIDTH_MASK;
+		val |= bus_width;
+		sdhci_writel(host, val, ESDHC_PROCTL);
 
-	if (of_find_compatible_node(NULL, NULL, "fsl,p2020-esdhc"))
-		mdelay(5);
+		sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+		sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
+	}
 
-	if (mask & SDHCI_RESET_ALL) {
+	/*
+	 * Some bits have to be cleaned manually for eSDHC whose spec
+	 * version is higher than 3.0 for all reset.
+	 */
+	if ((mask & SDHCI_RESET_ALL) &&
+	    (esdhc->spec_ver >= SDHCI_SPEC_300)) {
 		val = sdhci_readl(host, ESDHC_TBCTL);
 		val &= ~ESDHC_TB_EN;
 		sdhci_writel(host, val, ESDHC_TBCTL);
 
+		/*
+		 * Initialize eSDHC_DLLCFG1[DLL_PD_PULSE_STRETCH_SEL] to
+		 * 0 for quirk.
+		 */
 		if (esdhc->quirk_unreliable_pulse_detection) {
 			val = sdhci_readl(host, ESDHC_DLLCFG1);
 			val &= ~ESDHC_DLL_PD_PULSE_STRETCH_SEL;
@@ -771,6 +842,7 @@
 		scfg_node = of_find_matching_node(NULL, scfg_device_ids);
 		if (scfg_node)
 			scfg_base = of_iomap(scfg_node, 0);
+		of_node_put(scfg_node);
 		if (scfg_base) {
 			sdhciovselcr = SDHCIOVSELCR_TGLEN |
 				       SDHCIOVSELCR_VSELVAL;
@@ -796,16 +868,21 @@
 	}
 }
 
-static struct soc_device_attribute soc_fixup_tuning[] = {
+static struct soc_device_attribute soc_tuning_erratum_type1[] = {
+	{ .family = "QorIQ T1023", .revision = "1.0", },
 	{ .family = "QorIQ T1040", .revision = "1.0", },
 	{ .family = "QorIQ T2080", .revision = "1.0", },
-	{ .family = "QorIQ T1023", .revision = "1.0", },
 	{ .family = "QorIQ LS1021A", .revision = "1.0", },
-	{ .family = "QorIQ LS1080A", .revision = "1.0", },
-	{ .family = "QorIQ LS2080A", .revision = "1.0", },
+	{ },
+};
+
+static struct soc_device_attribute soc_tuning_erratum_type2[] = {
 	{ .family = "QorIQ LS1012A", .revision = "1.0", },
 	{ .family = "QorIQ LS1043A", .revision = "1.*", },
 	{ .family = "QorIQ LS1046A", .revision = "1.0", },
+	{ .family = "QorIQ LS1080A", .revision = "1.0", },
+	{ .family = "QorIQ LS2080A", .revision = "1.0", },
+	{ .family = "QorIQ LA1575A", .revision = "1.0", },
 	{ },
 };
 
@@ -829,15 +906,97 @@
 	esdhc_clock_enable(host, true);
 }
 
+static void esdhc_prepare_sw_tuning(struct sdhci_host *host, u8 *window_start,
+				    u8 *window_end)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
+	u8 tbstat_15_8, tbstat_7_0;
+	u32 val;
+
+	if (esdhc->quirk_tuning_erratum_type1) {
+		*window_start = 5 * esdhc->div_ratio;
+		*window_end = 3 * esdhc->div_ratio;
+		return;
+	}
+
+	/* Write TBCTL[11:8]=4'h8 */
+	val = sdhci_readl(host, ESDHC_TBCTL);
+	val &= ~(0xf << 8);
+	val |= 8 << 8;
+	sdhci_writel(host, val, ESDHC_TBCTL);
+
+	mdelay(1);
+
+	/* Read TBCTL[31:0] register and rewrite again */
+	val = sdhci_readl(host, ESDHC_TBCTL);
+	sdhci_writel(host, val, ESDHC_TBCTL);
+
+	mdelay(1);
+
+	/* Read the TBSTAT[31:0] register twice */
+	val = sdhci_readl(host, ESDHC_TBSTAT);
+	val = sdhci_readl(host, ESDHC_TBSTAT);
+
+	/* Reset data lines by setting ESDHCCTL[RSTD] */
+	sdhci_reset(host, SDHCI_RESET_DATA);
+	/* Write 32'hFFFF_FFFF to IRQSTAT register */
+	sdhci_writel(host, 0xFFFFFFFF, SDHCI_INT_STATUS);
+
+	/* If TBSTAT[15:8]-TBSTAT[7:0] > 4 * div_ratio
+	 * or TBSTAT[7:0]-TBSTAT[15:8] > 4 * div_ratio,
+	 * then program TBPTR[TB_WNDW_END_PTR] = 4 * div_ratio
+	 * and program TBPTR[TB_WNDW_START_PTR] = 8 * div_ratio.
+	 */
+	tbstat_7_0 = val & 0xff;
+	tbstat_15_8 = (val >> 8) & 0xff;
+
+	if (abs(tbstat_15_8 - tbstat_7_0) > (4 * esdhc->div_ratio)) {
+		*window_start = 8 * esdhc->div_ratio;
+		*window_end = 4 * esdhc->div_ratio;
+	} else {
+		*window_start = 5 * esdhc->div_ratio;
+		*window_end = 3 * esdhc->div_ratio;
+	}
+}
+
+static int esdhc_execute_sw_tuning(struct mmc_host *mmc, u32 opcode,
+				   u8 window_start, u8 window_end)
+{
+	struct sdhci_host *host = mmc_priv(mmc);
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
+	u32 val;
+	int ret;
+
+	/* Program TBPTR[TB_WNDW_END_PTR] and TBPTR[TB_WNDW_START_PTR] */
+	val = ((u32)window_start << ESDHC_WNDW_STRT_PTR_SHIFT) &
+	      ESDHC_WNDW_STRT_PTR_MASK;
+	val |= window_end & ESDHC_WNDW_END_PTR_MASK;
+	sdhci_writel(host, val, ESDHC_TBPTR);
+
+	/* Program the software tuning mode by setting TBCTL[TB_MODE]=2'h3 */
+	val = sdhci_readl(host, ESDHC_TBCTL);
+	val &= ~ESDHC_TB_MODE_MASK;
+	val |= ESDHC_TB_MODE_SW;
+	sdhci_writel(host, val, ESDHC_TBCTL);
+
+	esdhc->in_sw_tuning = true;
+	ret = sdhci_execute_tuning(mmc, opcode);
+	esdhc->in_sw_tuning = false;
+	return ret;
+}
+
 static int esdhc_execute_tuning(struct mmc_host *mmc, u32 opcode)
 {
 	struct sdhci_host *host = mmc_priv(mmc);
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
+	u8 window_start, window_end;
+	int ret, retries = 1;
 	bool hs400_tuning;
 	unsigned int clk;
 	u32 val;
-	int ret;
 
 	/* For tuning mode, the sd clock divisor value
 	 * must be larger than 3 according to reference manual.
@@ -846,39 +1005,84 @@
 	if (host->clock > clk)
 		esdhc_of_set_clock(host, clk);
 
-	if (esdhc->quirk_limited_clk_division &&
-	    host->flags & SDHCI_HS400_TUNING)
-		esdhc_of_set_clock(host, host->clock);
-
 	esdhc_tuning_block_enable(host, true);
 
+	/*
+	 * The eSDHC controller takes the data timeout value into account
+	 * during tuning. If the SD card is too slow sending the response, the
+	 * timer will expire and a "Buffer Read Ready" interrupt without data
+	 * is triggered. This leads to tuning errors.
+	 *
+	 * Just set the timeout to the maximum value because the core will
+	 * already take care of it in sdhci_send_tuning().
+	 */
+	sdhci_writeb(host, 0xe, SDHCI_TIMEOUT_CONTROL);
+
 	hs400_tuning = host->flags & SDHCI_HS400_TUNING;
-	ret = sdhci_execute_tuning(mmc, opcode);
 
-	if (hs400_tuning) {
-		val = sdhci_readl(host, ESDHC_SDTIMNGCTL);
-		val |= ESDHC_FLW_CTL_BG;
-		sdhci_writel(host, val, ESDHC_SDTIMNGCTL);
-	}
+	do {
+		if (esdhc->quirk_limited_clk_division &&
+		    hs400_tuning)
+			esdhc_of_set_clock(host, host->clock);
 
-	if (host->tuning_err == -EAGAIN && esdhc->quirk_fixup_tuning) {
+		/* Do HW tuning */
+		val = sdhci_readl(host, ESDHC_TBCTL);
+		val &= ~ESDHC_TB_MODE_MASK;
+		val |= ESDHC_TB_MODE_3;
+		sdhci_writel(host, val, ESDHC_TBCTL);
 
-		/* program TBPTR[TB_WNDW_END_PTR] = 3*DIV_RATIO and
-		 * program TBPTR[TB_WNDW_START_PTR] = 5*DIV_RATIO
-		 */
-		val = sdhci_readl(host, ESDHC_TBPTR);
-		val = (val & ~((0x7f << 8) | 0x7f)) |
-		(3 * esdhc->div_ratio) | ((5 * esdhc->div_ratio) << 8);
-		sdhci_writel(host, val, ESDHC_TBPTR);
+		ret = sdhci_execute_tuning(mmc, opcode);
+		if (ret)
+			break;
 
-		/* program the software tuning mode by setting
-		 * TBCTL[TB_MODE]=2'h3
+		/* If HW tuning fails and triggers erratum,
+		 * try workaround.
 		 */
-		val = sdhci_readl(host, ESDHC_TBCTL);
-		val |= 0x3;
-		sdhci_writel(host, val, ESDHC_TBCTL);
-		sdhci_execute_tuning(mmc, opcode);
+		ret = host->tuning_err;
+		if (ret == -EAGAIN &&
+		    (esdhc->quirk_tuning_erratum_type1 ||
+		     esdhc->quirk_tuning_erratum_type2)) {
+			/* Recover HS400 tuning flag */
+			if (hs400_tuning)
+				host->flags |= SDHCI_HS400_TUNING;
+			pr_info("%s: Hold on to use fixed sampling clock. Try SW tuning!\n",
+				mmc_hostname(mmc));
+			/* Do SW tuning */
+			esdhc_prepare_sw_tuning(host, &window_start,
+						&window_end);
+			ret = esdhc_execute_sw_tuning(mmc, opcode,
+						      window_start,
+						      window_end);
+			if (ret)
+				break;
+
+			/* Retry both HW/SW tuning with reduced clock. */
+			ret = host->tuning_err;
+			if (ret == -EAGAIN && retries) {
+				/* Recover HS400 tuning flag */
+				if (hs400_tuning)
+					host->flags |= SDHCI_HS400_TUNING;
+
+				clk = host->max_clk / (esdhc->div_ratio + 1);
+				esdhc_of_set_clock(host, clk);
+				pr_info("%s: Hold on to use fixed sampling clock. Try tuning with reduced clock!\n",
+					mmc_hostname(mmc));
+			} else {
+				break;
+			}
+		} else {
+			break;
+		}
+	} while (retries--);
+
+	if (ret) {
+		esdhc_tuning_block_enable(host, false);
+	} else if (hs400_tuning) {
+		val = sdhci_readl(host, ESDHC_SDTIMNGCTL);
+		val |= ESDHC_FLW_CTL_BG;
+		sdhci_writel(host, val, ESDHC_SDTIMNGCTL);
 	}
+
 	return ret;
 }
 
@@ -893,10 +1097,11 @@
 
 static u32 esdhc_irq(struct sdhci_host *host, u32 intmask)
 {
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
 	u32 command;
 
-	if (of_find_compatible_node(NULL, NULL,
-				"fsl,p2020-esdhc")) {
+	if (esdhc->quirk_trans_complete_erratum) {
 		command = SDHCI_GET_CMD(sdhci_readw(host,
 					SDHCI_COMMAND));
 		if (command == MMC_WRITE_MULTIPLE_BLOCK &&
@@ -1010,6 +1215,8 @@
 
 static struct soc_device_attribute soc_unreliable_pulse_detection[] = {
 	{ .family = "QorIQ LX2160A", .revision = "1.0", },
+	{ .family = "QorIQ LX2160A", .revision = "2.0", },
+	{ .family = "QorIQ LS1028A", .revision = "1.0", },
 	{ },
 };
 
@@ -1049,6 +1256,12 @@
 	if (match)
 		esdhc->clk_fixup = match->data;
 	np = pdev->dev.of_node;
+
+	if (of_device_is_compatible(np, "fsl,p2020-esdhc")) {
+		esdhc->quirk_delay_before_data_reset = true;
+		esdhc->quirk_trans_complete_erratum = true;
+	}
+
 	clk = of_clk_get(np, 0);
 	if (!IS_ERR(clk)) {
 		/*
@@ -1114,10 +1327,15 @@
 
 	pltfm_host = sdhci_priv(host);
 	esdhc = sdhci_pltfm_priv(pltfm_host);
-	if (soc_device_match(soc_fixup_tuning))
-		esdhc->quirk_fixup_tuning = true;
+	if (soc_device_match(soc_tuning_erratum_type1))
+		esdhc->quirk_tuning_erratum_type1 = true;
+	else
+		esdhc->quirk_tuning_erratum_type1 = false;
+
+	if (soc_device_match(soc_tuning_erratum_type2))
+		esdhc->quirk_tuning_erratum_type2 = true;
 	else
-		esdhc->quirk_fixup_tuning = false;
+		esdhc->quirk_tuning_erratum_type2 = false;
 
 	if (esdhc->vendor_ver == VENDOR_V_22)
 		host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23;
@@ -1126,8 +1344,8 @@
 		host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ;
 
 	if (of_find_compatible_node(NULL, NULL, "fsl,p2020-esdhc")) {
-		host->quirks2 |= SDHCI_QUIRK_RESET_AFTER_REQUEST;
-		host->quirks2 |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
+		host->quirks |= SDHCI_QUIRK_RESET_AFTER_REQUEST;
+		host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
 	}
 
 	if (of_device_is_compatible(np, "fsl,p5040-esdhc") ||
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/sdhci-omap.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/sdhci-omap.c
@@ -675,7 +675,8 @@
 {
 	struct mmc_host *mmc = host->mmc;
 
-	mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd);
+	if (!IS_ERR(mmc->supply.vmmc))
+		mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd);
 }
 
 static int sdhci_omap_enable_dma(struct sdhci_host *host)
@@ -1134,6 +1135,9 @@
 	host->mmc_host_ops.execute_tuning = sdhci_omap_execute_tuning;
 	host->mmc_host_ops.enable_sdio_irq = sdhci_omap_enable_sdio_irq;
 
+	/* R1B responses is required to properly manage HW busy detection. */
+	mmc->caps |= MMC_CAP_NEED_RSP_BUSY;
+
 	ret = sdhci_setup_host(host);
 	if (ret)
 		goto err_put_sync;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/sdhci-pci-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/sdhci-pci-core.c
@@ -21,11 +21,15 @@
 #include <linux/mmc/mmc.h>
 #include <linux/scatterlist.h>
 #include <linux/io.h>
+#include <linux/iopoll.h>
 #include <linux/gpio.h>
 #include <linux/pm_runtime.h>
+#include <linux/pm_qos.h>
+#include <linux/debugfs.h>
 #include <linux/mmc/slot-gpio.h>
 #include <linux/mmc/sdhci-pci-data.h>
 #include <linux/acpi.h>
+#include <linux/dmi.h>
 
 #ifdef CONFIG_X86
 #include <asm/iosf_mbi.h>
@@ -230,6 +234,14 @@
 	sdhci_dumpregs(mmc_priv(mmc));
 }
 
+static void sdhci_cqhci_reset(struct sdhci_host *host, u8 mask)
+{
+	if ((host->mmc->caps2 & MMC_CAP2_CQE) && (mask & SDHCI_RESET_ALL) &&
+	    host->mmc->cqe_private)
+		cqhci_deactivate(host->mmc);
+	sdhci_reset(host, mask);
+}
+
 /*****************************************************************************\
  *                                                                           *
  * Hardware specific quirk handling                                          *
@@ -508,8 +520,11 @@
 	int	drv_strength;
 	bool	d3_retune;
 	bool	rpm_retune_ok;
+	bool	needs_pwr_off;
 	u32	glk_rx_ctrl1;
 	u32	glk_tun_val;
+	u32	active_ltr;
+	u32	idle_ltr;
 };
 
 static const guid_t intel_dsm_guid =
@@ -599,6 +614,9 @@
 	struct sdhci_pci_slot *slot = sdhci_priv(host);
 	struct intel_host *intel_host = sdhci_pci_priv(slot);
 
+	if (!(mmc_driver_type_mask(intel_host->drv_strength) & card_drv))
+		return 0;
+
 	return intel_host->drv_strength;
 }
 
@@ -630,9 +648,25 @@
 static void sdhci_intel_set_power(struct sdhci_host *host, unsigned char mode,
 				  unsigned short vdd)
 {
+	struct sdhci_pci_slot *slot = sdhci_priv(host);
+	struct intel_host *intel_host = sdhci_pci_priv(slot);
 	int cntr;
 	u8 reg;
 
+	/*
+	 * Bus power may control card power, but a full reset still may not
+	 * reset the power, whereas a direct write to SDHCI_POWER_CONTROL can.
+	 * That might be needed to initialize correctly, if the card was left
+	 * powered on previously.
+	 */
+	if (intel_host->needs_pwr_off) {
+		intel_host->needs_pwr_off = false;
+		if (mode != MMC_POWER_OFF) {
+			sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
+			usleep_range(10000, 12500);
+		}
+	}
+
 	sdhci_set_power(host, mode, vdd);
 
 	if (mode == MMC_POWER_OFF)
@@ -652,6 +686,15 @@
 	}
 }
 
+static void sdhci_intel_set_uhs_signaling(struct sdhci_host *host,
+					  unsigned int timing)
+{
+	/* Set UHS timing to SDR25 for High Speed mode */
+	if (timing == MMC_TIMING_MMC_HS || timing == MMC_TIMING_SD_HS)
+		timing = MMC_TIMING_UHS_SDR25;
+	sdhci_set_uhs_signaling(host, timing);
+}
+
 #define INTEL_HS400_ES_REG 0x78
 #define INTEL_HS400_ES_BIT BIT(0)
 
@@ -708,7 +751,7 @@
 	.enable_dma		= sdhci_pci_enable_dma,
 	.set_bus_width		= sdhci_set_bus_width,
 	.reset			= sdhci_reset,
-	.set_uhs_signaling	= sdhci_set_uhs_signaling,
+	.set_uhs_signaling	= sdhci_intel_set_uhs_signaling,
 	.hw_reset		= sdhci_pci_hw_reset,
 };
 
@@ -717,8 +760,8 @@
 	.set_power		= sdhci_intel_set_power,
 	.enable_dma		= sdhci_pci_enable_dma,
 	.set_bus_width		= sdhci_set_bus_width,
-	.reset			= sdhci_reset,
-	.set_uhs_signaling	= sdhci_set_uhs_signaling,
+	.reset			= sdhci_cqhci_reset,
+	.set_uhs_signaling	= sdhci_intel_set_uhs_signaling,
 	.hw_reset		= sdhci_pci_hw_reset,
 	.irq			= sdhci_cqhci_irq,
 };
@@ -751,6 +794,108 @@
 	return 0;
 }
 
+#define INTEL_ACTIVELTR		0x804
+#define INTEL_IDLELTR		0x808
+
+#define INTEL_LTR_REQ		BIT(15)
+#define INTEL_LTR_SCALE_MASK	GENMASK(11, 10)
+#define INTEL_LTR_SCALE_1US	(2 << 10)
+#define INTEL_LTR_SCALE_32US	(3 << 10)
+#define INTEL_LTR_VALUE_MASK	GENMASK(9, 0)
+
+static void intel_cache_ltr(struct sdhci_pci_slot *slot)
+{
+	struct intel_host *intel_host = sdhci_pci_priv(slot);
+	struct sdhci_host *host = slot->host;
+
+	intel_host->active_ltr = readl(host->ioaddr + INTEL_ACTIVELTR);
+	intel_host->idle_ltr = readl(host->ioaddr + INTEL_IDLELTR);
+}
+
+static void intel_ltr_set(struct device *dev, s32 val)
+{
+	struct sdhci_pci_chip *chip = dev_get_drvdata(dev);
+	struct sdhci_pci_slot *slot = chip->slots[0];
+	struct intel_host *intel_host = sdhci_pci_priv(slot);
+	struct sdhci_host *host = slot->host;
+	u32 ltr;
+
+	pm_runtime_get_sync(dev);
+
+	/*
+	 * Program latency tolerance (LTR) accordingly what has been asked
+	 * by the PM QoS layer or disable it in case we were passed
+	 * negative value or PM_QOS_LATENCY_ANY.
+	 */
+	ltr = readl(host->ioaddr + INTEL_ACTIVELTR);
+
+	if (val == PM_QOS_LATENCY_ANY || val < 0) {
+		ltr &= ~INTEL_LTR_REQ;
+	} else {
+		ltr |= INTEL_LTR_REQ;
+		ltr &= ~INTEL_LTR_SCALE_MASK;
+		ltr &= ~INTEL_LTR_VALUE_MASK;
+
+		if (val > INTEL_LTR_VALUE_MASK) {
+			val >>= 5;
+			if (val > INTEL_LTR_VALUE_MASK)
+				val = INTEL_LTR_VALUE_MASK;
+			ltr |= INTEL_LTR_SCALE_32US | val;
+		} else {
+			ltr |= INTEL_LTR_SCALE_1US | val;
+		}
+	}
+
+	if (ltr == intel_host->active_ltr)
+		goto out;
+
+	writel(ltr, host->ioaddr + INTEL_ACTIVELTR);
+	writel(ltr, host->ioaddr + INTEL_IDLELTR);
+
+	/* Cache the values into lpss structure */
+	intel_cache_ltr(slot);
+out:
+	pm_runtime_put_autosuspend(dev);
+}
+
+static bool intel_use_ltr(struct sdhci_pci_chip *chip)
+{
+	switch (chip->pdev->device) {
+	case PCI_DEVICE_ID_INTEL_BYT_EMMC:
+	case PCI_DEVICE_ID_INTEL_BYT_EMMC2:
+	case PCI_DEVICE_ID_INTEL_BYT_SDIO:
+	case PCI_DEVICE_ID_INTEL_BYT_SD:
+	case PCI_DEVICE_ID_INTEL_BSW_EMMC:
+	case PCI_DEVICE_ID_INTEL_BSW_SDIO:
+	case PCI_DEVICE_ID_INTEL_BSW_SD:
+		return false;
+	default:
+		return true;
+	}
+}
+
+static void intel_ltr_expose(struct sdhci_pci_chip *chip)
+{
+	struct device *dev = &chip->pdev->dev;
+
+	if (!intel_use_ltr(chip))
+		return;
+
+	dev->power.set_latency_tolerance = intel_ltr_set;
+	dev_pm_qos_expose_latency_tolerance(dev);
+}
+
+static void intel_ltr_hide(struct sdhci_pci_chip *chip)
+{
+	struct device *dev = &chip->pdev->dev;
+
+	if (!intel_use_ltr(chip))
+		return;
+
+	dev_pm_qos_hide_latency_tolerance(dev);
+	dev->power.set_latency_tolerance = NULL;
+}
+
 static void byt_probe_slot(struct sdhci_pci_slot *slot)
 {
 	struct mmc_host_ops *ops = &slot->host->mmc_host_ops;
@@ -765,6 +910,43 @@
 	ops->start_signal_voltage_switch = intel_start_signal_voltage_switch;
 
 	device_property_read_u32(dev, "max-frequency", &mmc->f_max);
+
+	if (!mmc->slotno) {
+		slot->chip->slots[mmc->slotno] = slot;
+		intel_ltr_expose(slot->chip);
+	}
+}
+
+static void byt_add_debugfs(struct sdhci_pci_slot *slot)
+{
+	struct intel_host *intel_host = sdhci_pci_priv(slot);
+	struct mmc_host *mmc = slot->host->mmc;
+	struct dentry *dir = mmc->debugfs_root;
+
+	if (!intel_use_ltr(slot->chip))
+		return;
+
+	debugfs_create_x32("active_ltr", 0444, dir, &intel_host->active_ltr);
+	debugfs_create_x32("idle_ltr", 0444, dir, &intel_host->idle_ltr);
+
+	intel_cache_ltr(slot);
+}
+
+static int byt_add_host(struct sdhci_pci_slot *slot)
+{
+	int ret = sdhci_add_host(slot->host);
+
+	if (!ret)
+		byt_add_debugfs(slot);
+	return ret;
+}
+
+static void byt_remove_slot(struct sdhci_pci_slot *slot, int dead)
+{
+	struct mmc_host *mmc = slot->host->mmc;
+
+	if (!mmc->slotno)
+		intel_ltr_hide(slot->chip);
 }
 
 static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot)
@@ -782,11 +964,19 @@
 	return 0;
 }
 
+static bool glk_broken_cqhci(struct sdhci_pci_slot *slot)
+{
+	return slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_GLK_EMMC &&
+	       (dmi_match(DMI_BIOS_VENDOR, "LENOVO") ||
+		dmi_match(DMI_SYS_VENDOR, "IRBIS"));
+}
+
 static int glk_emmc_probe_slot(struct sdhci_pci_slot *slot)
 {
 	int ret = byt_emmc_probe_slot(slot);
 
-	slot->host->mmc->caps2 |= MMC_CAP2_CQE;
+	if (!glk_broken_cqhci(slot))
+		slot->host->mmc->caps2 |= MMC_CAP2_CQE;
 
 	if (slot->chip->pdev->device != PCI_DEVICE_ID_INTEL_GLK_EMMC) {
 		slot->host->mmc->caps2 |= MMC_CAP2_HS400_ES,
@@ -838,6 +1028,8 @@
 	if (ret)
 		goto cleanup;
 
+	byt_add_debugfs(slot);
+
 	return 0;
 
 cleanup:
@@ -964,6 +1156,14 @@
 	return 0;
 }
 
+static void byt_needs_pwr_off(struct sdhci_pci_slot *slot)
+{
+	struct intel_host *intel_host = sdhci_pci_priv(slot);
+	u8 reg = sdhci_readb(slot->host, SDHCI_POWER_CONTROL);
+
+	intel_host->needs_pwr_off = reg  & SDHCI_POWER_ON;
+}
+
 static int byt_sd_probe_slot(struct sdhci_pci_slot *slot)
 {
 	byt_probe_slot(slot);
@@ -981,6 +1181,8 @@
 	    slot->chip->pdev->subsystem_device == PCI_SUBDEVICE_ID_NI_78E3)
 		slot->host->mmc->caps2 |= MMC_CAP2_AVOID_3_3V;
 
+	byt_needs_pwr_off(slot);
+
 	return 0;
 }
 
@@ -1015,6 +1217,8 @@
 #endif
 	.allow_runtime_pm = true,
 	.probe_slot	= byt_emmc_probe_slot,
+	.add_host	= byt_add_host,
+	.remove_slot	= byt_remove_slot,
 	.quirks		= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC |
 			  SDHCI_QUIRK_NO_LED,
 	.quirks2	= SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
@@ -1028,6 +1232,7 @@
 	.allow_runtime_pm	= true,
 	.probe_slot		= glk_emmc_probe_slot,
 	.add_host		= glk_emmc_add_host,
+	.remove_slot		= byt_remove_slot,
 #ifdef CONFIG_PM_SLEEP
 	.suspend		= sdhci_cqhci_suspend,
 	.resume			= sdhci_cqhci_resume,
@@ -1058,6 +1263,8 @@
 			  SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
 	.allow_runtime_pm = true,
 	.probe_slot	= ni_byt_sdio_probe_slot,
+	.add_host	= byt_add_host,
+	.remove_slot	= byt_remove_slot,
 	.ops		= &sdhci_intel_byt_ops,
 	.priv_size	= sizeof(struct intel_host),
 };
@@ -1075,6 +1282,8 @@
 			SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
 	.allow_runtime_pm = true,
 	.probe_slot	= byt_sdio_probe_slot,
+	.add_host	= byt_add_host,
+	.remove_slot	= byt_remove_slot,
 	.ops		= &sdhci_intel_byt_ops,
 	.priv_size	= sizeof(struct intel_host),
 };
@@ -1094,6 +1303,8 @@
 	.allow_runtime_pm = true,
 	.own_cd_for_runtime_pm = true,
 	.probe_slot	= byt_sd_probe_slot,
+	.add_host	= byt_add_host,
+	.remove_slot	= byt_remove_slot,
 	.ops		= &sdhci_intel_byt_ops,
 	.priv_size	= sizeof(struct intel_host),
 };
@@ -1165,7 +1376,7 @@
 
 	ret = pci_read_config_byte(chip->pdev, 0xAE, &scratch);
 	if (ret)
-		return ret;
+		goto fail;
 
 	/*
 	 * Turn PMOS on [bit 0], set over current detection to 2.4 V
@@ -1176,7 +1387,10 @@
 	else
 		scratch &= ~0x47;
 
-	return pci_write_config_byte(chip->pdev, 0xAE, scratch);
+	ret = pci_write_config_byte(chip->pdev, 0xAE, scratch);
+
+fail:
+	return pcibios_err_to_errno(ret);
 }
 
 static int jmicron_probe(struct sdhci_pci_chip *chip)
@@ -1584,17 +1798,67 @@
 		}
 	}
 
+	pci_dev_put(smbus_dev);
+
 	if (gen == AMD_CHIPSET_BEFORE_ML || gen == AMD_CHIPSET_CZ)
 		chip->quirks2 |= SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD;
 
 	return 0;
 }
 
+static u32 sdhci_read_present_state(struct sdhci_host *host)
+{
+	return sdhci_readl(host, SDHCI_PRESENT_STATE);
+}
+
+static void amd_sdhci_reset(struct sdhci_host *host, u8 mask)
+{
+	struct sdhci_pci_slot *slot = sdhci_priv(host);
+	struct pci_dev *pdev = slot->chip->pdev;
+	u32 present_state;
+
+	/*
+	 * SDHC 0x7906 requires a hard reset to clear all internal state.
+	 * Otherwise it can get into a bad state where the DATA lines are always
+	 * read as zeros.
+	 */
+	if (pdev->device == 0x7906 && (mask & SDHCI_RESET_ALL)) {
+		pci_clear_master(pdev);
+
+		pci_save_state(pdev);
+
+		pci_set_power_state(pdev, PCI_D3cold);
+		pr_debug("%s: power_state=%u\n", mmc_hostname(host->mmc),
+			pdev->current_state);
+		pci_set_power_state(pdev, PCI_D0);
+
+		pci_restore_state(pdev);
+
+		/*
+		 * SDHCI_RESET_ALL says the card detect logic should not be
+		 * reset, but since we need to reset the entire controller
+		 * we should wait until the card detect logic has stabilized.
+		 *
+		 * This normally takes about 40ms.
+		 */
+		readx_poll_timeout(
+			sdhci_read_present_state,
+			host,
+			present_state,
+			present_state & SDHCI_CD_STABLE,
+			10000,
+			100000
+		);
+	}
+
+	return sdhci_reset(host, mask);
+}
+
 static const struct sdhci_ops amd_sdhci_pci_ops = {
 	.set_clock			= sdhci_set_clock,
 	.enable_dma			= sdhci_pci_enable_dma,
 	.set_bus_width			= sdhci_set_bus_width,
-	.reset				= sdhci_reset,
+	.reset				= amd_sdhci_reset,
 	.set_uhs_signaling		= sdhci_set_uhs_signaling,
 };
 
@@ -1673,6 +1937,11 @@
 	SDHCI_PCI_DEVICE(INTEL, CML_EMMC,  intel_glk_emmc),
 	SDHCI_PCI_DEVICE(INTEL, CML_SD,    intel_byt_sd),
 	SDHCI_PCI_DEVICE(INTEL, CMLH_SD,   intel_byt_sd),
+	SDHCI_PCI_DEVICE(INTEL, JSL_EMMC,  intel_glk_emmc),
+	SDHCI_PCI_DEVICE(INTEL, JSL_SD,    intel_byt_sd),
+	SDHCI_PCI_DEVICE(INTEL, LKF_EMMC,  intel_glk_emmc),
+	SDHCI_PCI_DEVICE(INTEL, LKF_SD,    intel_byt_sd),
+	SDHCI_PCI_DEVICE(INTEL, ADL_EMMC,  intel_glk_emmc),
 	SDHCI_PCI_DEVICE(O2, 8120,     o2),
 	SDHCI_PCI_DEVICE(O2, 8220,     o2),
 	SDHCI_PCI_DEVICE(O2, 8221,     o2),
@@ -2037,7 +2306,7 @@
 
 	ret = pci_read_config_byte(pdev, PCI_SLOT_INFO, &slots);
 	if (ret)
-		return ret;
+		return pcibios_err_to_errno(ret);
 
 	slots = PCI_SLOT_INFO_SLOTS(slots) + 1;
 	dev_dbg(&pdev->dev, "found %d slot(s)\n", slots);
@@ -2046,7 +2315,7 @@
 
 	ret = pci_read_config_byte(pdev, PCI_SLOT_INFO, &first_bar);
 	if (ret)
-		return ret;
+		return pcibios_err_to_errno(ret);
 
 	first_bar &= PCI_SLOT_INFO_FIRST_BAR_MASK;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/sdhci-pci-gli.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/sdhci-pci-gli.c
@@ -26,6 +26,9 @@
 #define   SDHCI_GLI_9750_DRIVING_2    GENMASK(27, 26)
 #define   GLI_9750_DRIVING_1_VALUE    0xFFF
 #define   GLI_9750_DRIVING_2_VALUE    0x3
+#define   SDHCI_GLI_9750_SEL_1        BIT(29)
+#define   SDHCI_GLI_9750_SEL_2        BIT(31)
+#define   SDHCI_GLI_9750_ALL_RST      (BIT(24)|BIT(25)|BIT(28)|BIT(30))
 
 #define SDHCI_GLI_9750_PLL	      0x864
 #define   SDHCI_GLI_9750_PLL_TX2_INV    BIT(23)
@@ -122,6 +125,8 @@
 				    GLI_9750_DRIVING_1_VALUE);
 	driving_value |= FIELD_PREP(SDHCI_GLI_9750_DRIVING_2,
 				    GLI_9750_DRIVING_2_VALUE);
+	driving_value &= ~(SDHCI_GLI_9750_SEL_1|SDHCI_GLI_9750_SEL_2|SDHCI_GLI_9750_ALL_RST);
+	driving_value |= SDHCI_GLI_9750_SEL_2;
 	sdhci_writel(host, driving_value, SDHCI_GLI_9750_DRIVING);
 
 	sw_ctrl_value &= ~SDHCI_GLI_9750_SW_CTRL_4;
@@ -262,10 +267,26 @@
 	return 0;
 }
 
+static void gli_pcie_enable_msi(struct sdhci_pci_slot *slot)
+{
+	int ret;
+
+	ret = pci_alloc_irq_vectors(slot->chip->pdev, 1, 1,
+				    PCI_IRQ_MSI | PCI_IRQ_MSIX);
+	if (ret < 0) {
+		pr_warn("%s: enable PCI MSI failed, error=%d\n",
+		       mmc_hostname(slot->host->mmc), ret);
+		return;
+	}
+
+	slot->host->irq = pci_irq_vector(slot->chip->pdev, 0);
+}
+
 static int gli_probe_slot_gl9750(struct sdhci_pci_slot *slot)
 {
 	struct sdhci_host *host = slot->host;
 
+	gli_pcie_enable_msi(slot);
 	slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO;
 	sdhci_enable_v4_mode(host);
 
@@ -276,6 +297,7 @@
 {
 	struct sdhci_host *host = slot->host;
 
+	gli_pcie_enable_msi(slot);
 	slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO;
 	sdhci_enable_v4_mode(host);
 
@@ -296,8 +318,13 @@
 	 *
 	 * Wait 5ms after set 1.8V signal enable in Host Control 2 register
 	 * to ensure 1.8V signal enable bit is set by GL9750/GL9755.
+	 *
+	 * ...however, the controller in the NUC10i3FNK4 (a 9755) requires
+	 * slightly longer than 5ms before the control register reports that
+	 * 1.8V is ready, and far longer still before the card will actually
+	 * work reliably.
 	 */
-	usleep_range(5000, 5500);
+	usleep_range(100000, 110000);
 }
 
 static void sdhci_gl9750_reset(struct sdhci_host *host, u8 mask)
@@ -317,6 +344,18 @@
 	return value;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int sdhci_pci_gli_resume(struct sdhci_pci_chip *chip)
+{
+	struct sdhci_pci_slot *slot = chip->slots[0];
+
+	pci_free_irq_vectors(slot->chip->pdev);
+	gli_pcie_enable_msi(slot);
+
+	return sdhci_pci_resume_host(chip);
+}
+#endif
+
 static const struct sdhci_ops sdhci_gl9755_ops = {
 	.set_clock		= sdhci_set_clock,
 	.enable_dma		= sdhci_pci_enable_dma,
@@ -331,6 +370,9 @@
 	.quirks2	= SDHCI_QUIRK2_BROKEN_DDR50,
 	.probe_slot	= gli_probe_slot_gl9755,
 	.ops            = &sdhci_gl9755_ops,
+#ifdef CONFIG_PM_SLEEP
+	.resume         = sdhci_pci_gli_resume,
+#endif
 };
 
 static const struct sdhci_ops sdhci_gl9750_ops = {
@@ -349,4 +391,7 @@
 	.quirks2	= SDHCI_QUIRK2_BROKEN_DDR50,
 	.probe_slot	= gli_probe_slot_gl9750,
 	.ops            = &sdhci_gl9750_ops,
+#ifdef CONFIG_PM_SLEEP
+	.resume         = sdhci_pci_gli_resume,
+#endif
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/sdhci-pci-o2micro.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/sdhci-pci-o2micro.c
@@ -31,6 +31,7 @@
 #define O2_SD_CAPS		0xE0
 #define O2_SD_ADMA1		0xE2
 #define O2_SD_ADMA2		0xE7
+#define O2_SD_MISC_CTRL2	0xF0
 #define O2_SD_INF_MOD		0xF1
 #define O2_SD_MISC_CTRL4	0xFC
 #define O2_SD_TUNING_CTRL	0x300
@@ -145,6 +146,8 @@
 
 	if (!(sdhci_readw(host, O2_PLL_DLL_WDT_CONTROL1) & O2_PLL_LOCK_STATUS))
 		sdhci_o2_enable_internal_clock(host);
+	else
+		sdhci_o2_wait_card_detect_stable(host);
 
 	return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
 }
@@ -561,6 +564,12 @@
 			slot->host->mmc_host_ops.get_cd = sdhci_o2_get_cd;
 		}
 
+		if (chip->pdev->device == PCI_DEVICE_ID_O2_SEABIRD1) {
+			slot->host->mmc_host_ops.get_cd = sdhci_o2_get_cd;
+			host->mmc->caps2 |= MMC_CAP2_NO_SDIO;
+			host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN;
+		}
+
 		host->mmc_host_ops.execute_tuning = sdhci_o2_execute_tuning;
 
 		if (chip->pdev->device != PCI_DEVICE_ID_O2_FUJIN2)
@@ -769,6 +778,12 @@
 		/* Set Tuning Windows to 5 */
 		pci_write_config_byte(chip->pdev,
 				O2_SD_TUNING_CTRL, 0x55);
+		//Adjust 1st and 2nd CD debounce time
+		pci_read_config_dword(chip->pdev, O2_SD_MISC_CTRL2, &scratch_32);
+		scratch_32 &= 0xFFE7FFFF;
+		scratch_32 |= 0x00180000;
+		pci_write_config_dword(chip->pdev, O2_SD_MISC_CTRL2, scratch_32);
+		pci_write_config_dword(chip->pdev, O2_SD_DETECT_SETTING, 1);
 		/* Lock WP */
 		ret = pci_read_config_byte(chip->pdev,
 					   O2_SD_LOCK_WP, &scratch);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/sdhci-pci.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/sdhci-pci.h
@@ -55,6 +55,11 @@
 #define PCI_DEVICE_ID_INTEL_CML_EMMC	0x02c4
 #define PCI_DEVICE_ID_INTEL_CML_SD	0x02f5
 #define PCI_DEVICE_ID_INTEL_CMLH_SD	0x06f5
+#define PCI_DEVICE_ID_INTEL_JSL_EMMC	0x4dc4
+#define PCI_DEVICE_ID_INTEL_JSL_SD	0x4df8
+#define PCI_DEVICE_ID_INTEL_LKF_EMMC	0x98c4
+#define PCI_DEVICE_ID_INTEL_LKF_SD	0x98f8
+#define PCI_DEVICE_ID_INTEL_ADL_EMMC	0x54c4
 
 #define PCI_DEVICE_ID_SYSKONNECT_8000	0x8000
 #define PCI_DEVICE_ID_VIA_95D0		0x95d0
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/sdhci-pxav3.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/sdhci-pxav3.c
@@ -401,6 +401,7 @@
 	if (!IS_ERR(pxa->clk_core))
 		clk_prepare_enable(pxa->clk_core);
 
+	host->mmc->caps |= MMC_CAP_NEED_RSP_BUSY;
 	/* enable 1/8V DDR capable */
 	host->mmc->caps |= MMC_CAP_1_8V_DDR;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/sdhci-sprd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/sdhci-sprd.c
@@ -223,13 +223,19 @@
 	div = ((div & 0x300) >> 2) | ((div & 0xFF) << 8);
 	sdhci_enable_clk(host, div);
 
-	/* enable auto gate sdhc_enable_auto_gate */
 	val = sdhci_readl(host, SDHCI_SPRD_REG_32_BUSY_POSI);
-	mask = SDHCI_SPRD_BIT_OUTR_CLK_AUTO_EN |
-	       SDHCI_SPRD_BIT_INNR_CLK_AUTO_EN;
-	if (mask != (val & mask)) {
-		val |= mask;
-		sdhci_writel(host, val, SDHCI_SPRD_REG_32_BUSY_POSI);
+	mask = SDHCI_SPRD_BIT_OUTR_CLK_AUTO_EN | SDHCI_SPRD_BIT_INNR_CLK_AUTO_EN;
+	/* Enable CLK_AUTO when the clock is greater than 400K. */
+	if (clk > 400000) {
+		if (mask != (val & mask)) {
+			val |= mask;
+			sdhci_writel(host, val, SDHCI_SPRD_REG_32_BUSY_POSI);
+		}
+	} else {
+		if (val & mask) {
+			val &= ~mask;
+			sdhci_writel(host, val, SDHCI_SPRD_REG_32_BUSY_POSI);
+		}
 	}
 }
 
@@ -295,7 +301,7 @@
 
 static unsigned int sdhci_sprd_get_min_clock(struct sdhci_host *host)
 {
-	return 400000;
+	return 100000;
 }
 
 static void sdhci_sprd_set_uhs_signaling(struct sdhci_host *host,
@@ -379,11 +385,33 @@
 	return 0;
 }
 
+static void sdhci_sprd_set_power(struct sdhci_host *host, unsigned char mode,
+				 unsigned short vdd)
+{
+	struct mmc_host *mmc = host->mmc;
+
+	switch (mode) {
+	case MMC_POWER_OFF:
+		mmc_regulator_set_ocr(host->mmc, mmc->supply.vmmc, 0);
+
+		mmc_regulator_disable_vqmmc(mmc);
+		break;
+	case MMC_POWER_ON:
+		mmc_regulator_enable_vqmmc(mmc);
+		break;
+	case MMC_POWER_UP:
+		mmc_regulator_set_ocr(host->mmc, mmc->supply.vmmc, vdd);
+		break;
+	}
+}
+
 static struct sdhci_ops sdhci_sprd_ops = {
 	.read_l = sdhci_sprd_readl,
 	.write_l = sdhci_sprd_writel,
+	.write_w = sdhci_sprd_writew,
 	.write_b = sdhci_sprd_writeb,
 	.set_clock = sdhci_sprd_set_clock,
+	.set_power = sdhci_sprd_set_power,
 	.get_max_clock = sdhci_sprd_get_max_clock,
 	.get_min_clock = sdhci_sprd_get_min_clock,
 	.set_bus_width = sdhci_set_bus_width,
@@ -430,7 +458,7 @@
 	}
 
 	if (IS_ERR(sprd_host->pinctrl))
-		return 0;
+		goto reset;
 
 	switch (ios->signal_voltage) {
 	case MMC_SIGNAL_VOLTAGE_180:
@@ -458,6 +486,8 @@
 
 	/* Wait for 300 ~ 500 us for pin state stable */
 	usleep_range(300, 500);
+
+reset:
 	sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
 
 	return 0;
@@ -625,6 +655,10 @@
 	host->caps1 &= ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_SDR104 |
 			 SDHCI_SUPPORT_DDR50);
 
+	ret = mmc_regulator_get_supply(host->mmc);
+	if (ret)
+		goto pm_runtime_disable;
+
 	ret = sdhci_setup_host(host);
 	if (ret)
 		goto pm_runtime_disable;
@@ -665,14 +699,14 @@
 {
 	struct sdhci_host *host = platform_get_drvdata(pdev);
 	struct sdhci_sprd_host *sprd_host = TO_SPRD_HOST(host);
-	struct mmc_host *mmc = host->mmc;
 
-	mmc_remove_host(mmc);
+	sdhci_remove_host(host, 0);
+
 	clk_disable_unprepare(sprd_host->clk_sdio);
 	clk_disable_unprepare(sprd_host->clk_enable);
 	clk_disable_unprepare(sprd_host->clk_2x_enable);
 
-	mmc_free_host(mmc);
+	sdhci_pltfm_free(pdev);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/sdhci-tegra.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/sdhci-tegra.c
@@ -24,6 +24,7 @@
 #include <linux/gpio/consumer.h>
 #include <linux/ktime.h>
 
+#include "sdhci-cqhci.h"
 #include "sdhci-pltfm.h"
 #include "cqhci.h"
 
@@ -100,6 +101,12 @@
 #define NVQUIRK_DIS_CARD_CLK_CONFIG_TAP			BIT(8)
 #define NVQUIRK_CQHCI_DCMD_R1B_CMD_TIMING		BIT(9)
 
+/*
+ * NVQUIRK_HAS_TMCLK is for SoC's having separate timeout clock for Tegra
+ * SDMMC hardware data timeout.
+ */
+#define NVQUIRK_HAS_TMCLK				BIT(10)
+
 /* SDMMC CQE Base Address for Tegra Host Ver 4.1 and Higher */
 #define SDHCI_TEGRA_CQE_BASE_ADDR			0xF000
 
@@ -130,6 +137,7 @@
 struct sdhci_tegra {
 	const struct sdhci_tegra_soc_data *soc_data;
 	struct gpio_desc *power_gpio;
+	struct clk *tmclk;
 	bool ddr_signaling;
 	bool pad_calib_required;
 	bool pad_control_available;
@@ -333,23 +341,6 @@
 	}
 }
 
-static void tegra_sdhci_hs400_enhanced_strobe(struct mmc_host *mmc,
-					      struct mmc_ios *ios)
-{
-	struct sdhci_host *host = mmc_priv(mmc);
-	u32 val;
-
-	val = sdhci_readl(host, SDHCI_TEGRA_VENDOR_SYS_SW_CTRL);
-
-	if (ios->enhanced_strobe)
-		val |= SDHCI_TEGRA_SYS_SW_CTRL_ENHANCED_STROBE;
-	else
-		val &= ~SDHCI_TEGRA_SYS_SW_CTRL_ENHANCED_STROBE;
-
-	sdhci_writel(host, val, SDHCI_TEGRA_VENDOR_SYS_SW_CTRL);
-
-}
-
 static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -357,7 +348,7 @@
 	const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
 	u32 misc_ctrl, clk_ctrl, pad_ctrl;
 
-	sdhci_reset(host, mask);
+	sdhci_and_cqhci_reset(host, mask);
 
 	if (!(mask & SDHCI_RESET_ALL))
 		return;
@@ -386,7 +377,7 @@
 			misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_DDR50;
 		if (soc_data->nvquirks & NVQUIRK_ENABLE_SDR104)
 			misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDR104;
-		if (soc_data->nvquirks & SDHCI_MISC_CTRL_ENABLE_SDR50)
+		if (soc_data->nvquirks & NVQUIRK_ENABLE_SDR50)
 			clk_ctrl |= SDHCI_CLOCK_CTRL_SDR50_TUNING_OVERRIDE;
 	}
 
@@ -761,6 +752,32 @@
 	}
 }
 
+static void tegra_sdhci_hs400_enhanced_strobe(struct mmc_host *mmc,
+					      struct mmc_ios *ios)
+{
+	struct sdhci_host *host = mmc_priv(mmc);
+	u32 val;
+
+	val = sdhci_readl(host, SDHCI_TEGRA_VENDOR_SYS_SW_CTRL);
+
+	if (ios->enhanced_strobe) {
+		val |= SDHCI_TEGRA_SYS_SW_CTRL_ENHANCED_STROBE;
+		/*
+		 * When CMD13 is sent from mmc_select_hs400es() after
+		 * switching to HS400ES mode, the bus is operating at
+		 * either MMC_HIGH_26_MAX_DTR or MMC_HIGH_52_MAX_DTR.
+		 * To meet Tegra SDHCI requirement at HS400ES mode, force SDHCI
+		 * interface clock to MMC_HS200_MAX_DTR (200 MHz) so that host
+		 * controller CAR clock and the interface clock are rate matched.
+		 */
+		tegra_sdhci_set_clock(host, MMC_HS200_MAX_DTR);
+	} else {
+		val &= ~SDHCI_TEGRA_SYS_SW_CTRL_ENHANCED_STROBE;
+	}
+
+	sdhci_writel(host, val, SDHCI_TEGRA_VENDOR_SYS_SW_CTRL);
+}
+
 static unsigned int tegra_sdhci_get_max_clock(struct sdhci_host *host)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -1283,7 +1300,6 @@
 		  SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
 		  SDHCI_QUIRK_SINGLE_POWER_WRITE |
 		  SDHCI_QUIRK_NO_HISPD_BIT |
-		  SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC |
 		  SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
 	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
 		   SDHCI_QUIRK2_BROKEN_HS200 |
@@ -1370,7 +1386,6 @@
 
 static const struct sdhci_pltfm_data sdhci_tegra210_pdata = {
 	.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
-		  SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
 		  SDHCI_QUIRK_SINGLE_POWER_WRITE |
 		  SDHCI_QUIRK_NO_HISPD_BIT |
 		  SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC |
@@ -1386,7 +1401,8 @@
 		    NVQUIRK_HAS_PADCALIB |
 		    NVQUIRK_DIS_CARD_CLK_CONFIG_TAP |
 		    NVQUIRK_ENABLE_SDR50 |
-		    NVQUIRK_ENABLE_SDR104,
+		    NVQUIRK_ENABLE_SDR104 |
+		    NVQUIRK_HAS_TMCLK,
 	.min_tap_delay = 106,
 	.max_tap_delay = 185,
 };
@@ -1407,7 +1423,6 @@
 
 static const struct sdhci_pltfm_data sdhci_tegra186_pdata = {
 	.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
-		  SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
 		  SDHCI_QUIRK_SINGLE_POWER_WRITE |
 		  SDHCI_QUIRK_NO_HISPD_BIT |
 		  SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC |
@@ -1424,6 +1439,7 @@
 		    NVQUIRK_DIS_CARD_CLK_CONFIG_TAP |
 		    NVQUIRK_ENABLE_SDR50 |
 		    NVQUIRK_ENABLE_SDR104 |
+		    NVQUIRK_HAS_TMCLK |
 		    NVQUIRK_CQHCI_DCMD_R1B_CMD_TIMING,
 	.min_tap_delay = 84,
 	.max_tap_delay = 136,
@@ -1436,7 +1452,8 @@
 		    NVQUIRK_HAS_PADCALIB |
 		    NVQUIRK_DIS_CARD_CLK_CONFIG_TAP |
 		    NVQUIRK_ENABLE_SDR50 |
-		    NVQUIRK_ENABLE_SDR104,
+		    NVQUIRK_ENABLE_SDR104 |
+		    NVQUIRK_HAS_TMCLK,
 	.min_tap_delay = 96,
 	.max_tap_delay = 139,
 };
@@ -1552,6 +1569,9 @@
 	if (tegra_host->soc_data->nvquirks & NVQUIRK_ENABLE_DDR50)
 		host->mmc->caps |= MMC_CAP_1_8V_DDR;
 
+	/* R1B responses is required to properly manage HW busy detection. */
+	host->mmc->caps |= MMC_CAP_NEED_RSP_BUSY;
+
 	tegra_sdhci_parse_dt(host);
 
 	tegra_host->power_gpio = devm_gpiod_get_optional(&pdev->dev, "power",
@@ -1561,6 +1581,43 @@
 		goto err_power_req;
 	}
 
+	/*
+	 * Tegra210 has a separate SDMMC_LEGACY_TM clock used for host
+	 * timeout clock and SW can choose TMCLK or SDCLK for hardware
+	 * data timeout through the bit USE_TMCLK_FOR_DATA_TIMEOUT of
+	 * the register SDHCI_TEGRA_VENDOR_SYS_SW_CTRL.
+	 *
+	 * USE_TMCLK_FOR_DATA_TIMEOUT bit default is set to 1 and SDMMC uses
+	 * 12Mhz TMCLK which is advertised in host capability register.
+	 * With TMCLK of 12Mhz provides maximum data timeout period that can
+	 * be achieved is 11s better than using SDCLK for data timeout.
+	 *
+	 * So, TMCLK is set to 12Mhz and kept enabled all the time on SoC's
+	 * supporting separate TMCLK.
+	 */
+
+	if (soc_data->nvquirks & NVQUIRK_HAS_TMCLK) {
+		clk = devm_clk_get(&pdev->dev, "tmclk");
+		if (IS_ERR(clk)) {
+			rc = PTR_ERR(clk);
+			if (rc == -EPROBE_DEFER)
+				goto err_power_req;
+
+			dev_warn(&pdev->dev, "failed to get tmclk: %d\n", rc);
+			clk = NULL;
+		}
+
+		clk_set_rate(clk, 12000000);
+		rc = clk_prepare_enable(clk);
+		if (rc) {
+			dev_err(&pdev->dev,
+				"failed to enable tmclk: %d\n", rc);
+			goto err_power_req;
+		}
+
+		tegra_host->tmclk = clk;
+	}
+
 	clk = devm_clk_get(mmc_dev(host->mmc), NULL);
 	if (IS_ERR(clk)) {
 		rc = PTR_ERR(clk);
@@ -1604,6 +1661,7 @@
 err_rst_get:
 	clk_disable_unprepare(pltfm_host->clk);
 err_clk_get:
+	clk_disable_unprepare(tegra_host->tmclk);
 err_power_req:
 err_parse_dt:
 	sdhci_pltfm_free(pdev);
@@ -1621,6 +1679,7 @@
 	reset_control_assert(tegra_host->rst);
 	usleep_range(2000, 4000);
 	clk_disable_unprepare(pltfm_host->clk);
+	clk_disable_unprepare(tegra_host->tmclk);
 
 	sdhci_pltfm_free(pdev);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/sdhci-xenon.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/sdhci-xenon.c
@@ -167,7 +167,12 @@
 	/* Disable tuning request and auto-retuning again */
 	xenon_retune_setup(host);
 
-	xenon_set_acg(host, true);
+	/*
+	 * The ACG should be turned off at the early init time, in order
+	 * to solve a possible issues with the 1.8V regulator stabilization.
+	 * The feature is enabled in later stage.
+	 */
+	xenon_set_acg(host, false);
 
 	xenon_set_sdclk_off_idle(host, sdhc_id, false);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/sdhci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/sdhci.c
@@ -9,6 +9,7 @@
  *     - JMicron (hardware and technical support)
  */
 
+#include <linux/bitfield.h>
 #include <linux/delay.h>
 #include <linux/ktime.h>
 #include <linux/highmem.h>
@@ -152,7 +153,7 @@
 	u32 present;
 
 	if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) ||
-	    !mmc_card_is_removable(host->mmc))
+	    !mmc_card_is_removable(host->mmc) || mmc_can_gpio_cd(host->mmc))
 		return;
 
 	if (enable) {
@@ -331,6 +332,7 @@
 	if (soft) {
 		/* force clock reconfiguration */
 		host->clock = 0;
+		host->reinit_uhs = true;
 		mmc->ops->set_ios(mmc, &mmc->ios);
 	}
 }
@@ -474,7 +476,7 @@
 {
 	unsigned long flags;
 	size_t blksize, len, chunk;
-	u32 uninitialized_var(scratch);
+	u32 scratch;
 	u8 *buf;
 
 	DBG("PIO reading\n");
@@ -749,7 +751,19 @@
 			len -= offset;
 		}
 
-		BUG_ON(len > 65536);
+		/*
+		 * The block layer forces a minimum segment size of PAGE_SIZE,
+		 * so 'len' can be too big here if PAGE_SIZE >= 64KiB. Write
+		 * multiple descriptors, noting that the ADMA table is sized
+		 * for 4KiB chunks anyway, so it will be big enough.
+		 */
+		while (len > host->max_adma) {
+			int n = 32 * 1024; /* 32KiB*/
+
+			__sdhci_adma_write_desc(host, &desc, addr, n, ADMA2_TRAN_VALID);
+			addr += n;
+			len -= n;
+		}
 
 		/* tran, valid */
 		if (len)
@@ -981,7 +995,7 @@
 	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
 }
 
-static void sdhci_set_data_timeout_irq(struct sdhci_host *host, bool enable)
+void sdhci_set_data_timeout_irq(struct sdhci_host *host, bool enable)
 {
 	if (enable)
 		host->ier |= SDHCI_INT_DATA_TIMEOUT;
@@ -990,28 +1004,31 @@
 	sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
 	sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
 }
+EXPORT_SYMBOL_GPL(sdhci_set_data_timeout_irq);
 
-static void sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd)
+void __sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd)
 {
-	u8 count;
-
-	if (host->ops->set_timeout) {
-		host->ops->set_timeout(host, cmd);
-	} else {
-		bool too_big = false;
+	bool too_big = false;
+	u8 count = sdhci_calc_timeout(host, cmd, &too_big);
 
-		count = sdhci_calc_timeout(host, cmd, &too_big);
+	if (too_big &&
+	    host->quirks2 & SDHCI_QUIRK2_DISABLE_HW_TIMEOUT) {
+		sdhci_calc_sw_timeout(host, cmd);
+		sdhci_set_data_timeout_irq(host, false);
+	} else if (!(host->ier & SDHCI_INT_DATA_TIMEOUT)) {
+		sdhci_set_data_timeout_irq(host, true);
+	}
 
-		if (too_big &&
-		    host->quirks2 & SDHCI_QUIRK2_DISABLE_HW_TIMEOUT) {
-			sdhci_calc_sw_timeout(host, cmd);
-			sdhci_set_data_timeout_irq(host, false);
-		} else if (!(host->ier & SDHCI_INT_DATA_TIMEOUT)) {
-			sdhci_set_data_timeout_irq(host, true);
-		}
+	sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL);
+}
+EXPORT_SYMBOL_GPL(__sdhci_set_timeout);
 
-		sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL);
-	}
+static void sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd)
+{
+	if (host->ops->set_timeout)
+		host->ops->set_timeout(host, cmd);
+	else
+		__sdhci_set_timeout(host, cmd);
 }
 
 static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
@@ -1087,6 +1104,8 @@
 		}
 	}
 
+	sdhci_config_dma(host);
+
 	if (host->flags & SDHCI_REQ_USE_DMA) {
 		int sg_cnt = sdhci_pre_dma_transfer(host, data, COOKIE_MAPPED);
 
@@ -1106,8 +1125,6 @@
 		}
 	}
 
-	sdhci_config_dma(host);
-
 	if (!(host->flags & SDHCI_REQ_USE_DMA)) {
 		int flags;
 
@@ -1159,9 +1176,11 @@
 	/*
 	 * In case of Version 4.10 or later, use of 'Auto CMD Auto
 	 * Select' is recommended rather than use of 'Auto CMD12
-	 * Enable' or 'Auto CMD23 Enable'.
+	 * Enable' or 'Auto CMD23 Enable'. We require Version 4 Mode
+	 * here because some controllers (e.g sdhci-of-dwmshc) expect it.
 	 */
-	if (host->version >= SDHCI_SPEC_410 && (use_cmd12 || use_cmd23)) {
+	if (host->version >= SDHCI_SPEC_410 && host->v4_mode &&
+	    (use_cmd12 || use_cmd23)) {
 		*mode |= SDHCI_TRNS_AUTO_SEL;
 
 		ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
@@ -1506,6 +1525,10 @@
 	u16 preset = 0;
 
 	switch (host->timing) {
+	case MMC_TIMING_MMC_HS:
+	case MMC_TIMING_SD_HS:
+		preset = sdhci_readw(host, SDHCI_PRESET_FOR_HIGH_SPEED);
+		break;
 	case MMC_TIMING_UHS_SDR12:
 		preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR12);
 		break;
@@ -1549,10 +1572,9 @@
 
 			clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
 			pre_val = sdhci_get_preset_value(host);
-			div = (pre_val & SDHCI_PRESET_SDCLK_FREQ_MASK)
-				>> SDHCI_PRESET_SDCLK_FREQ_SHIFT;
+			div = FIELD_GET(SDHCI_PRESET_SDCLK_FREQ_MASK, pre_val);
 			if (host->clk_mul &&
-				(pre_val & SDHCI_PRESET_CLKGEN_SEL_MASK)) {
+				(pre_val & SDHCI_PRESET_CLKGEN_SEL)) {
 				clk = SDHCI_PROG_CLOCK_MODE;
 				real_div = div + 1;
 				clk_mul = host->clk_mul;
@@ -1732,6 +1754,12 @@
 			break;
 		case MMC_VDD_32_33:
 		case MMC_VDD_33_34:
+		/*
+		 * 3.4 ~ 3.6V are valid only for those platforms where it's
+		 * known that the voltage range is supported by hardware.
+		 */
+		case MMC_VDD_34_35:
+		case MMC_VDD_35_36:
 			pwr = SDHCI_POWER_330;
 			break;
 		default:
@@ -1871,9 +1899,7 @@
 		ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
 	else if (timing == MMC_TIMING_UHS_SDR12)
 		ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
-	else if (timing == MMC_TIMING_SD_HS ||
-		 timing == MMC_TIMING_MMC_HS ||
-		 timing == MMC_TIMING_UHS_SDR25)
+	else if (timing == MMC_TIMING_UHS_SDR25)
 		ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
 	else if (timing == MMC_TIMING_UHS_SDR50)
 		ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
@@ -1886,11 +1912,46 @@
 }
 EXPORT_SYMBOL_GPL(sdhci_set_uhs_signaling);
 
+static bool sdhci_timing_has_preset(unsigned char timing)
+{
+	switch (timing) {
+	case MMC_TIMING_UHS_SDR12:
+	case MMC_TIMING_UHS_SDR25:
+	case MMC_TIMING_UHS_SDR50:
+	case MMC_TIMING_UHS_SDR104:
+	case MMC_TIMING_UHS_DDR50:
+	case MMC_TIMING_MMC_DDR52:
+		return true;
+	};
+	return false;
+}
+
+static bool sdhci_preset_needed(struct sdhci_host *host, unsigned char timing)
+{
+	return !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN) &&
+	       sdhci_timing_has_preset(timing);
+}
+
+static bool sdhci_presetable_values_change(struct sdhci_host *host, struct mmc_ios *ios)
+{
+	/*
+	 * Preset Values are: Driver Strength, Clock Generator and SDCLK/RCLK
+	 * Frequency. Check if preset values need to be enabled, or the Driver
+	 * Strength needs updating. Note, clock changes are handled separately.
+	 */
+	return !host->preset_enabled &&
+	       (sdhci_preset_needed(host, ios->timing) || host->drv_type != ios->drv_type);
+}
+
 void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	struct sdhci_host *host = mmc_priv(mmc);
+	bool reinit_uhs = host->reinit_uhs;
+	bool turning_on_clk = false;
 	u8 ctrl;
 
+	host->reinit_uhs = false;
+
 	if (ios->power_mode == MMC_POWER_UNDEFINED)
 		return;
 
@@ -1916,6 +1977,8 @@
 		sdhci_enable_preset_value(host, false);
 
 	if (!ios->clock || ios->clock != host->clock) {
+		turning_on_clk = ios->clock && !host->clock;
+
 		host->ops->set_clock(host, ios->clock);
 		host->clock = ios->clock;
 
@@ -1942,6 +2005,17 @@
 
 	host->ops->set_bus_width(host, ios->bus_width);
 
+	/*
+	 * Special case to avoid multiple clock changes during voltage
+	 * switching.
+	 */
+	if (!reinit_uhs &&
+	    turning_on_clk &&
+	    host->timing == ios->timing &&
+	    host->version >= SDHCI_SPEC_300 &&
+	    !sdhci_presetable_values_change(host, ios))
+		return;
+
 	ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
 
 	if (!(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT)) {
@@ -1985,6 +2059,7 @@
 			}
 
 			sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
+			host->drv_type = ios->drv_type;
 		} else {
 			/*
 			 * According to SDHC Spec v3.00, if the Preset Value
@@ -2012,19 +2087,14 @@
 		host->ops->set_uhs_signaling(host, ios->timing);
 		host->timing = ios->timing;
 
-		if (!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN) &&
-				((ios->timing == MMC_TIMING_UHS_SDR12) ||
-				 (ios->timing == MMC_TIMING_UHS_SDR25) ||
-				 (ios->timing == MMC_TIMING_UHS_SDR50) ||
-				 (ios->timing == MMC_TIMING_UHS_SDR104) ||
-				 (ios->timing == MMC_TIMING_UHS_DDR50) ||
-				 (ios->timing == MMC_TIMING_MMC_DDR52))) {
+		if (sdhci_preset_needed(host, ios->timing)) {
 			u16 preset;
 
 			sdhci_enable_preset_value(host, true);
 			preset = sdhci_get_preset_value(host);
-			ios->drv_type = (preset & SDHCI_PRESET_DRV_MASK)
-				>> SDHCI_PRESET_DRV_SHIFT;
+			ios->drv_type = FIELD_GET(SDHCI_PRESET_DRV_MASK,
+						  preset);
+			host->drv_type = ios->drv_type;
 		}
 
 		/* Re-enable SD Clock */
@@ -2071,26 +2141,29 @@
 
 static int sdhci_check_ro(struct sdhci_host *host)
 {
-	unsigned long flags;
+	bool allow_invert = false;
 	int is_readonly;
 
-	spin_lock_irqsave(&host->lock, flags);
-
-	if (host->flags & SDHCI_DEVICE_DEAD)
+	if (host->flags & SDHCI_DEVICE_DEAD) {
 		is_readonly = 0;
-	else if (host->ops->get_ro)
+	} else if (host->ops->get_ro) {
 		is_readonly = host->ops->get_ro(host);
-	else if (mmc_can_gpio_ro(host->mmc))
+	} else if (mmc_can_gpio_ro(host->mmc)) {
 		is_readonly = mmc_gpio_get_ro(host->mmc);
-	else
+		/* Do not invert twice */
+		allow_invert = !(host->mmc->caps2 & MMC_CAP2_RO_ACTIVE_HIGH);
+	} else {
 		is_readonly = !(sdhci_readl(host, SDHCI_PRESENT_STATE)
 				& SDHCI_WRITE_PROTECT);
+		allow_invert = true;
+	}
 
-	spin_unlock_irqrestore(&host->lock, flags);
+	if (is_readonly >= 0 &&
+	    allow_invert &&
+	    (host->quirks & SDHCI_QUIRK_INVERTED_WRITE_PROTECT))
+		is_readonly = !is_readonly;
 
-	/* This quirk needs to be replaced by a callback-function later */
-	return host->quirks & SDHCI_QUIRK_INVERTED_WRITE_PROTECT ?
-		!is_readonly : is_readonly;
+	return is_readonly;
 }
 
 #define SAMPLE_COUNT	5
@@ -2408,8 +2481,8 @@
 		sdhci_send_tuning(host, opcode);
 
 		if (!host->tuning_done) {
-			pr_info("%s: Tuning timeout, falling back to fixed sampling clock\n",
-				mmc_hostname(host->mmc));
+			pr_debug("%s: Tuning timeout, falling back to fixed sampling clock\n",
+				 mmc_hostname(host->mmc));
 			sdhci_abort_tuning(host, opcode);
 			return -ETIMEDOUT;
 		}
@@ -2645,6 +2718,37 @@
 	}
 
 	/*
+	 * The controller needs a reset of internal state machines
+	 * upon error conditions.
+	 */
+	if (sdhci_needs_reset(host, mrq)) {
+		/*
+		 * Do not finish until command and data lines are available for
+		 * reset. Note there can only be one other mrq, so it cannot
+		 * also be in mrqs_done, otherwise host->cmd and host->data_cmd
+		 * would both be null.
+		 */
+		if (host->cmd || host->data_cmd) {
+			spin_unlock_irqrestore(&host->lock, flags);
+			return true;
+		}
+
+		/* Some controllers need this kick or reset won't work here */
+		if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET)
+			/* This is to force an update */
+			host->ops->set_clock(host, host->clock);
+
+		/*
+		 * Spec says we should do both at the same time, but Ricoh
+		 * controllers do not like that.
+		 */
+		sdhci_do_reset(host, SDHCI_RESET_CMD);
+		sdhci_do_reset(host, SDHCI_RESET_DATA);
+
+		host->pending_reset = false;
+	}
+
+	/*
 	 * Always unmap the data buffers if they were mapped by
 	 * sdhci_prepare_data() whenever we finish with a request.
 	 * This avoids leaking DMA mappings on error.
@@ -2696,35 +2800,6 @@
 		}
 	}
 
-	/*
-	 * The controller needs a reset of internal state machines
-	 * upon error conditions.
-	 */
-	if (sdhci_needs_reset(host, mrq)) {
-		/*
-		 * Do not finish until command and data lines are available for
-		 * reset. Note there can only be one other mrq, so it cannot
-		 * also be in mrqs_done, otherwise host->cmd and host->data_cmd
-		 * would both be null.
-		 */
-		if (host->cmd || host->data_cmd) {
-			spin_unlock_irqrestore(&host->lock, flags);
-			return true;
-		}
-
-		/* Some controllers need this kick or reset won't work here */
-		if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET)
-			/* This is to force an update */
-			host->ops->set_clock(host, host->clock);
-
-		/* Spec says we should do both at the same time, but Ricoh
-		   controllers do not like that. */
-		sdhci_do_reset(host, SDHCI_RESET_CMD);
-		sdhci_do_reset(host, SDHCI_RESET_DATA);
-
-		host->pending_reset = false;
-	}
-
 	host->mrqs_done[i] = NULL;
 
 	spin_unlock_irqrestore(&host->lock, flags);
@@ -3300,6 +3375,7 @@
 		sdhci_init(host, 0);
 		host->pwr = 0;
 		host->clock = 0;
+		host->reinit_uhs = true;
 		mmc->ops->set_ios(mmc, &mmc->ios);
 	} else {
 		sdhci_init(host, (host->mmc->pm_flags & MMC_PM_KEEP_POWER));
@@ -3362,6 +3438,7 @@
 		/* Force clock and power re-program */
 		host->pwr = 0;
 		host->clock = 0;
+		host->reinit_uhs = true;
 		mmc->ops->start_signal_voltage_switch(mmc, &mmc->ios);
 		mmc->ops->set_ios(mmc, &mmc->ios);
 
@@ -3553,6 +3630,7 @@
 	 * descriptor for each segment, plus 1 for a nop end descriptor.
 	 */
 	host->adma_table_cnt = SDHCI_MAX_SEGS * 2 + 1;
+	host->max_adma = 65536;
 
 	return host;
 }
@@ -3758,6 +3836,9 @@
 		       mmc_hostname(mmc), host->version);
 	}
 
+	if (host->quirks & SDHCI_QUIRK_BROKEN_CQE)
+		mmc->caps2 &= ~MMC_CAP2_CQE;
+
 	if (host->quirks & SDHCI_QUIRK_FORCE_DMA)
 		host->flags |= SDHCI_USE_SDMA;
 	else if (!(host->caps & SDHCI_CAN_DO_SDMA))
@@ -3901,11 +3982,13 @@
 	if (host->ops->get_min_clock)
 		mmc->f_min = host->ops->get_min_clock(host);
 	else if (host->version >= SDHCI_SPEC_300) {
-		if (host->clk_mul) {
-			mmc->f_min = (host->max_clk * host->clk_mul) / 1024;
+		if (host->clk_mul)
 			max_clk = host->max_clk * host->clk_mul;
-		} else
-			mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300;
+		/*
+		 * Divided Clock Mode minimum clock rate is always less than
+		 * Programmable Clock Mode minimum clock rate.
+		 */
+		mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300;
 	} else
 		mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200;
 
@@ -4201,10 +4284,12 @@
 	 * be larger than 64 KiB though.
 	 */
 	if (host->flags & SDHCI_USE_ADMA) {
-		if (host->quirks & SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC)
+		if (host->quirks & SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC) {
+			host->max_adma = 65532; /* 32-bit alignment */
 			mmc->max_seg_size = 65535;
-		else
+		} else {
 			mmc->max_seg_size = 65536;
+		}
 	} else {
 		mmc->max_seg_size = mmc->max_req_size;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/sdhci.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/sdhci.h
@@ -9,6 +9,7 @@
 #ifndef __SDHCI_HW_H
 #define __SDHCI_HW_H
 
+#include <linux/bits.h>
 #include <linux/scatterlist.h>
 #include <linux/compiler.h>
 #include <linux/types.h>
@@ -261,18 +262,16 @@
 
 /* 60-FB reserved */
 
+#define SDHCI_PRESET_FOR_HIGH_SPEED	0x64
 #define SDHCI_PRESET_FOR_SDR12 0x66
 #define SDHCI_PRESET_FOR_SDR25 0x68
 #define SDHCI_PRESET_FOR_SDR50 0x6A
 #define SDHCI_PRESET_FOR_SDR104        0x6C
 #define SDHCI_PRESET_FOR_DDR50 0x6E
 #define SDHCI_PRESET_FOR_HS400 0x74 /* Non-standard */
-#define SDHCI_PRESET_DRV_MASK  0xC000
-#define SDHCI_PRESET_DRV_SHIFT  14
-#define SDHCI_PRESET_CLKGEN_SEL_MASK   0x400
-#define SDHCI_PRESET_CLKGEN_SEL_SHIFT	10
-#define SDHCI_PRESET_SDCLK_FREQ_MASK   0x3FF
-#define SDHCI_PRESET_SDCLK_FREQ_SHIFT	0
+#define SDHCI_PRESET_DRV_MASK		GENMASK(15, 14)
+#define SDHCI_PRESET_CLKGEN_SEL		BIT(10)
+#define SDHCI_PRESET_SDCLK_FREQ_MASK	GENMASK(9, 0)
 
 #define SDHCI_SLOT_INT_STATUS	0xFC
 
@@ -348,7 +347,8 @@
 
 /*
  * Maximum segments assuming a 512KiB maximum requisition size and a minimum
- * 4KiB page size.
+ * 4KiB page size. Note this also allows enough for multiple descriptors in
+ * case of PAGE_SIZE >= 64KiB.
  */
 #define SDHCI_MAX_SEGS		128
 
@@ -409,6 +409,8 @@
 #define SDHCI_QUIRK_BROKEN_CARD_DETECTION		(1<<15)
 /* Controller reports inverted write-protect state */
 #define SDHCI_QUIRK_INVERTED_WRITE_PROTECT		(1<<16)
+/* Controller has unusable command queue engine */
+#define SDHCI_QUIRK_BROKEN_CQE				(1<<17)
 /* Controller does not like fast PIO transfers */
 #define SDHCI_QUIRK_PIO_NEEDS_DELAY			(1<<18)
 /* Controller does not have a LED */
@@ -526,6 +528,8 @@
 
 	unsigned int clock;	/* Current clock (MHz) */
 	u8 pwr;			/* Current voltage */
+	u8 drv_type;		/* Current UHS-I driver type */
+	bool reinit_uhs;	/* Force UHS-related re-initialization */
 
 	bool runtime_suspended;	/* Host is runtime suspended */
 	bool bus_on;		/* Bus power prevents runtime suspend */
@@ -544,6 +548,7 @@
 	unsigned int blocks;	/* remaining PIO blocks */
 
 	int sg_count;		/* Mapped sg entries */
+	int max_adma;		/* Max. length in ADMA descriptor */
 
 	void *adma_table;	/* ADMA descriptor table */
 	void *align_buffer;	/* Bounce buffer */
@@ -793,5 +798,7 @@
 void sdhci_reset_tuning(struct sdhci_host *host);
 void sdhci_send_tuning(struct sdhci_host *host, u32 opcode);
 void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode);
+void sdhci_set_data_timeout_irq(struct sdhci_host *host, bool enable);
+void __sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd);
 
 #endif /* __SDHCI_HW_H */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/sdhci_am654.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/sdhci_am654.c
@@ -227,8 +227,6 @@
 		 */
 		case MMC_TIMING_SD_HS:
 		case MMC_TIMING_MMC_HS:
-		case MMC_TIMING_UHS_SDR12:
-		case MMC_TIMING_UHS_SDR25:
 			val &= ~SDHCI_CTRL_HISPD;
 		}
 	}
@@ -236,6 +234,22 @@
 	writeb(val, host->ioaddr + reg);
 }
 
+static int sdhci_am654_execute_tuning(struct mmc_host *mmc, u32 opcode)
+{
+	struct sdhci_host *host = mmc_priv(mmc);
+	int err = sdhci_execute_tuning(mmc, opcode);
+
+	if (err)
+		return err;
+	/*
+	 * Tuning data remains in the buffer after tuning.
+	 * Do a command and data reset to get rid of it
+	 */
+	sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
+
+	return 0;
+}
+
 static struct sdhci_ops sdhci_am654_ops = {
 	.get_max_clock = sdhci_pltfm_clk_get_max_clock,
 	.get_timeout_clock = sdhci_pltfm_clk_get_max_clock,
@@ -249,8 +263,7 @@
 
 static const struct sdhci_pltfm_data sdhci_am654_pdata = {
 	.ops = &sdhci_am654_ops,
-	.quirks = SDHCI_QUIRK_INVERTED_WRITE_PROTECT |
-		  SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12,
+	.quirks = SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12,
 	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
 };
 
@@ -272,8 +285,7 @@
 
 static const struct sdhci_pltfm_data sdhci_j721e_8bit_pdata = {
 	.ops = &sdhci_j721e_8bit_ops,
-	.quirks = SDHCI_QUIRK_INVERTED_WRITE_PROTECT |
-		  SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12,
+	.quirks = SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12,
 	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
 };
 
@@ -295,8 +307,7 @@
 
 static const struct sdhci_pltfm_data sdhci_j721e_4bit_pdata = {
 	.ops = &sdhci_j721e_4bit_ops,
-	.quirks = SDHCI_QUIRK_INVERTED_WRITE_PROTECT |
-		  SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12,
+	.quirks = SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12,
 	.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
 };
 
@@ -480,6 +491,8 @@
 		goto pm_runtime_put;
 	}
 
+	host->mmc_host_ops.execute_tuning = sdhci_am654_execute_tuning;
+
 	ret = sdhci_am654_init(host);
 	if (ret)
 		goto pm_runtime_put;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/sdhci_f_sdh30.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/sdhci_f_sdh30.c
@@ -50,9 +50,16 @@
 	bool enable_cmd_dat_delay;
 };
 
+static void *sdhci_f_sdhost_priv(struct sdhci_host *host)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+
+	return sdhci_pltfm_priv(pltfm_host);
+}
+
 static void sdhci_f_sdh30_soft_voltage_switch(struct sdhci_host *host)
 {
-	struct f_sdhost_priv *priv = sdhci_priv(host);
+	struct f_sdhost_priv *priv = sdhci_f_sdhost_priv(host);
 	u32 ctrl = 0;
 
 	usleep_range(2500, 3000);
@@ -85,7 +92,7 @@
 
 static void sdhci_f_sdh30_reset(struct sdhci_host *host, u8 mask)
 {
-	struct f_sdhost_priv *priv = sdhci_priv(host);
+	struct f_sdhost_priv *priv = sdhci_f_sdhost_priv(host);
 	u32 ctl;
 
 	if (sdhci_readw(host, SDHCI_CLOCK_CONTROL) == 0)
@@ -109,31 +116,32 @@
 	.set_uhs_signaling = sdhci_set_uhs_signaling,
 };
 
+static const struct sdhci_pltfm_data sdhci_f_sdh30_pltfm_data = {
+	.ops = &sdhci_f_sdh30_ops,
+	.quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC
+		| SDHCI_QUIRK_INVERTED_WRITE_PROTECT,
+	.quirks2 = SDHCI_QUIRK2_SUPPORT_SINGLE
+		|  SDHCI_QUIRK2_TUNING_WORK_AROUND,
+};
+
 static int sdhci_f_sdh30_probe(struct platform_device *pdev)
 {
 	struct sdhci_host *host;
 	struct device *dev = &pdev->dev;
-	struct resource *res;
-	int irq, ctrl = 0, ret = 0;
+	int ctrl = 0, ret = 0;
 	struct f_sdhost_priv *priv;
+	struct sdhci_pltfm_host *pltfm_host;
 	u32 reg = 0;
 
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0)
-		return irq;
-
-	host = sdhci_alloc_host(dev, sizeof(struct f_sdhost_priv));
+	host = sdhci_pltfm_init(pdev, &sdhci_f_sdh30_pltfm_data,
+				sizeof(struct f_sdhost_priv));
 	if (IS_ERR(host))
 		return PTR_ERR(host);
 
-	priv = sdhci_priv(host);
+	pltfm_host = sdhci_priv(host);
+	priv = sdhci_pltfm_priv(pltfm_host);
 	priv->dev = dev;
 
-	host->quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC |
-		       SDHCI_QUIRK_INVERTED_WRITE_PROTECT;
-	host->quirks2 = SDHCI_QUIRK2_SUPPORT_SINGLE |
-			SDHCI_QUIRK2_TUNING_WORK_AROUND;
-
 	priv->enable_cmd_dat_delay = device_property_read_bool(dev,
 						"fujitsu,cmd-dat-delay-select");
 
@@ -141,19 +149,6 @@
 	if (ret)
 		goto err;
 
-	platform_set_drvdata(pdev, host);
-
-	host->hw_name = "f_sdh30";
-	host->ops = &sdhci_f_sdh30_ops;
-	host->irq = irq;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	host->ioaddr = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(host->ioaddr)) {
-		ret = PTR_ERR(host->ioaddr);
-		goto err;
-	}
-
 	if (dev_of_node(dev)) {
 		sdhci_get_of_property(pdev);
 
@@ -194,6 +189,9 @@
 	if (reg & SDHCI_CAN_DO_8BIT)
 		priv->vendor_hs200 = F_SDH30_EMMC_HS200;
 
+	if (!(reg & SDHCI_TIMEOUT_CLK_MASK))
+		host->quirks |= SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK;
+
 	ret = sdhci_add_host(host);
 	if (ret)
 		goto err_add_host;
@@ -205,23 +203,22 @@
 err_clk:
 	clk_disable_unprepare(priv->clk_iface);
 err:
-	sdhci_free_host(host);
+	sdhci_pltfm_free(pdev);
+
 	return ret;
 }
 
 static int sdhci_f_sdh30_remove(struct platform_device *pdev)
 {
 	struct sdhci_host *host = platform_get_drvdata(pdev);
-	struct f_sdhost_priv *priv = sdhci_priv(host);
-
-	sdhci_remove_host(host, readl(host->ioaddr + SDHCI_INT_STATUS) ==
-			  0xffffffff);
+	struct f_sdhost_priv *priv = sdhci_f_sdhost_priv(host);
+	struct clk *clk_iface = priv->clk_iface;
+	struct clk *clk = priv->clk;
 
-	clk_disable_unprepare(priv->clk_iface);
-	clk_disable_unprepare(priv->clk);
+	sdhci_pltfm_unregister(pdev);
 
-	sdhci_free_host(host);
-	platform_set_drvdata(pdev, NULL);
+	clk_disable_unprepare(clk_iface);
+	clk_disable_unprepare(clk);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/sh_mmcif.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/sh_mmcif.c
@@ -1395,7 +1395,7 @@
 	irq[0] = platform_get_irq(pdev, 0);
 	irq[1] = platform_get_irq_optional(pdev, 1);
 	if (irq[0] < 0)
-		return -ENXIO;
+		return irq[0];
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	reg = devm_ioremap_resource(dev, res);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/sunxi-mmc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/sunxi-mmc.c
@@ -1314,8 +1314,8 @@
 		return ret;
 
 	host->irq = platform_get_irq(pdev, 0);
-	if (host->irq <= 0) {
-		ret = -EINVAL;
+	if (host->irq < 0) {
+		ret = host->irq;
 		goto error_disable_mmc;
 	}
 
@@ -1456,9 +1456,11 @@
 	struct sunxi_mmc_host *host = mmc_priv(mmc);
 
 	mmc_remove_host(mmc);
-	pm_runtime_force_suspend(&pdev->dev);
-	disable_irq(host->irq);
-	sunxi_mmc_disable(host);
+	pm_runtime_disable(&pdev->dev);
+	if (!pm_runtime_status_suspended(&pdev->dev)) {
+		disable_irq(host->irq);
+		sunxi_mmc_disable(host);
+	}
 	dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
 	mmc_free_host(mmc);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/tmio_mmc_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/tmio_mmc_core.c
@@ -217,6 +217,8 @@
 	else
 		mrq->cmd->error = -ETIMEDOUT;
 
+	/* No new calls yet, but disallow concurrent tmio_mmc_done_work() */
+	host->mrq = ERR_PTR(-EBUSY);
 	host->cmd = NULL;
 	host->data = NULL;
 
@@ -1184,7 +1186,7 @@
 	if (ret == -EPROBE_DEFER)
 		return ret;
 
-	mmc->caps |= MMC_CAP_4_BIT_DATA | pdata->capabilities;
+	mmc->caps |= MMC_CAP_ERASE | MMC_CAP_4_BIT_DATA | pdata->capabilities;
 	mmc->caps2 |= pdata->capabilities2;
 	mmc->max_segs = pdata->max_segs ? : 32;
 	mmc->max_blk_size = TMIO_MAX_BLK_SIZE;
@@ -1285,12 +1287,14 @@
 	cancel_work_sync(&host->done);
 	cancel_delayed_work_sync(&host->delayed_reset_work);
 	tmio_mmc_release_dma(host);
+	tmio_mmc_disable_mmc_irqs(host, TMIO_MASK_ALL);
 
-	pm_runtime_dont_use_autosuspend(&pdev->dev);
 	if (host->native_hotplug)
 		pm_runtime_put_noidle(&pdev->dev);
-	pm_runtime_put_sync(&pdev->dev);
+
 	pm_runtime_disable(&pdev->dev);
+	pm_runtime_dont_use_autosuspend(&pdev->dev);
+	pm_runtime_put_noidle(&pdev->dev);
 }
 EXPORT_SYMBOL_GPL(tmio_mmc_host_remove);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/toshsd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/toshsd.c
@@ -651,7 +651,9 @@
 	if (ret)
 		goto unmap;
 
-	mmc_add_host(mmc);
+	ret = mmc_add_host(mmc);
+	if (ret)
+		goto free_irq;
 
 	base = pci_resource_start(pdev, 0);
 	dev_dbg(&pdev->dev, "MMIO %pa, IRQ %d\n", &base, pdev->irq);
@@ -660,6 +662,8 @@
 
 	return 0;
 
+free_irq:
+	free_irq(pdev->irq, host);
 unmap:
 	pci_iounmap(pdev, host->ioaddr);
 release:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/uniphier-sd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/uniphier-sd.c
@@ -614,11 +614,6 @@
 		}
 	}
 
-	ret = devm_request_irq(dev, irq, tmio_mmc_irq, IRQF_SHARED,
-			       dev_name(dev), host);
-	if (ret)
-		goto free_host;
-
 	if (priv->caps & UNIPHIER_SD_CAP_EXTENDED_IP)
 		host->dma_ops = &uniphier_sd_internal_dma_ops;
 	else
@@ -644,10 +639,19 @@
 
 	ret = tmio_mmc_host_probe(host);
 	if (ret)
-		goto free_host;
+		goto disable_clk;
+
+	ret = devm_request_irq(dev, irq, tmio_mmc_irq, IRQF_SHARED,
+			       dev_name(dev), host);
+	if (ret)
+		goto remove_host;
 
 	return 0;
 
+remove_host:
+	tmio_mmc_host_remove(host);
+disable_clk:
+	uniphier_sd_clk_disable(host);
 free_host:
 	tmio_mmc_host_free(host);
 
@@ -660,6 +664,7 @@
 
 	tmio_mmc_host_remove(host);
 	uniphier_sd_clk_disable(host);
+	tmio_mmc_host_free(host);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/usdhi6rol0.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/usdhi6rol0.c
@@ -1743,8 +1743,10 @@
 	irq_cd = platform_get_irq_byname(pdev, "card detect");
 	irq_sd = platform_get_irq_byname(pdev, "data");
 	irq_sdio = platform_get_irq_byname(pdev, "SDIO");
-	if (irq_sd < 0 || irq_sdio < 0)
-		return -ENODEV;
+	if (irq_sd < 0)
+		return irq_sd;
+	if (irq_sdio < 0)
+		return irq_sdio;
 
 	mmc = mmc_alloc_host(sizeof(struct usdhi6_host), dev);
 	if (!mmc)
@@ -1803,6 +1805,7 @@
 
 	version = usdhi6_read(host, USDHI6_VERSION);
 	if ((version & 0xfff) != 0xa0d) {
+		ret = -EPERM;
 		dev_err(dev, "Version not recognized %x\n", version);
 		goto e_clk_off;
 	}
@@ -1860,10 +1863,12 @@
 
 	ret = mmc_add_host(mmc);
 	if (ret < 0)
-		goto e_clk_off;
+		goto e_release_dma;
 
 	return 0;
 
+e_release_dma:
+	usdhi6_dma_release(host);
 e_clk_off:
 	clk_disable_unprepare(host->clk);
 e_free_mmc:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/via-sdmmc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/via-sdmmc.c
@@ -319,6 +319,8 @@
 /* some devices need a very long delay for power to stabilize */
 #define VIA_CRDR_QUIRK_300MS_PWRDELAY	0x0001
 
+#define VIA_CMD_TIMEOUT_MS		1000
+
 static const struct pci_device_id via_ids[] = {
 	{PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_9530,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,},
@@ -551,14 +553,17 @@
 {
 	void __iomem *addrbase;
 	struct mmc_data *data;
+	unsigned int timeout_ms;
 	u32 cmdctrl = 0;
 
 	WARN_ON(host->cmd);
 
 	data = cmd->data;
-	mod_timer(&host->timer, jiffies + HZ);
 	host->cmd = cmd;
 
+	timeout_ms = cmd->busy_timeout ? cmd->busy_timeout : VIA_CMD_TIMEOUT_MS;
+	mod_timer(&host->timer, jiffies + msecs_to_jiffies(timeout_ms));
+
 	/*Command index*/
 	cmdctrl = cmd->opcode << 8;
 
@@ -852,6 +857,9 @@
 {
 	BUG_ON(intmask == 0);
 
+	if (!host->data)
+		return;
+
 	if (intmask & VIA_CRDR_SDSTS_DT)
 		host->data->error = -ETIMEDOUT;
 	else if (intmask & (VIA_CRDR_SDSTS_RC | VIA_CRDR_SDSTS_WC))
@@ -1146,7 +1154,9 @@
 	    pcidev->subsystem_device == 0x3891)
 		sdhost->quirks = VIA_CRDR_QUIRK_300MS_PWRDELAY;
 
-	mmc_add_host(mmc);
+	ret = mmc_add_host(mmc);
+	if (ret)
+		goto unmap;
 
 	return 0;
 
@@ -1254,11 +1264,14 @@
 static int via_sd_suspend(struct pci_dev *pcidev, pm_message_t state)
 {
 	struct via_crdr_mmc_host *host;
+	unsigned long flags;
 
 	host = pci_get_drvdata(pcidev);
 
+	spin_lock_irqsave(&host->lock, flags);
 	via_save_pcictrlreg(host);
 	via_save_sdcreg(host);
+	spin_unlock_irqrestore(&host->lock, flags);
 
 	pci_save_state(pcidev);
 	pci_enable_wake(pcidev, pci_choose_state(pcidev, state), 0);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/vub300.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/vub300.c
@@ -576,7 +576,7 @@
 				GET_SYSTEM_PORT_STATUS,
 				USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 				0x0000, 0x0000, &vub300->system_port_status,
-				sizeof(vub300->system_port_status), HZ);
+				sizeof(vub300->system_port_status), 1000);
 	if (sizeof(vub300->system_port_status) == retval)
 		new_system_port_status(vub300);
 }
@@ -1241,7 +1241,7 @@
 						SET_INTERRUPT_PSEUDOCODE,
 						USB_DIR_OUT | USB_TYPE_VENDOR |
 						USB_RECIP_DEVICE, 0x0000, 0x0000,
-						xfer_buffer, xfer_length, HZ);
+						xfer_buffer, xfer_length, 1000);
 			kfree(xfer_buffer);
 			if (retval < 0)
 				goto copy_error_message;
@@ -1284,7 +1284,7 @@
 						SET_TRANSFER_PSEUDOCODE,
 						USB_DIR_OUT | USB_TYPE_VENDOR |
 						USB_RECIP_DEVICE, 0x0000, 0x0000,
-						xfer_buffer, xfer_length, HZ);
+						xfer_buffer, xfer_length, 1000);
 			kfree(xfer_buffer);
 			if (retval < 0)
 				goto copy_error_message;
@@ -1715,6 +1715,9 @@
 	int bytes = 3 & less_cmd;
 	int words = less_cmd >> 2;
 	u8 *r = vub300->resp.response.command_response;
+
+	if (!resp_len)
+		return;
 	if (bytes == 3) {
 		cmd->resp[words] = (r[1 + (words << 2)] << 24)
 			| (r[2 + (words << 2)] << 16)
@@ -1991,7 +1994,7 @@
 		usb_control_msg(vub300->udev, usb_sndctrlpipe(vub300->udev, 0),
 				SET_CLOCK_SPEED,
 				USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-				0x00, 0x00, buf, buf_array_size, HZ);
+				0x00, 0x00, buf, buf_array_size, 1000);
 	if (retval != 8) {
 		dev_err(&vub300->udev->dev, "SET_CLOCK_SPEED"
 			" %dkHz failed with retval=%d\n", kHzClock, retval);
@@ -2013,14 +2016,14 @@
 		usb_control_msg(vub300->udev, usb_sndctrlpipe(vub300->udev, 0),
 				SET_SD_POWER,
 				USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-				0x0000, 0x0000, NULL, 0, HZ);
+				0x0000, 0x0000, NULL, 0, 1000);
 		/* must wait for the VUB300 u-proc to boot up */
 		msleep(600);
 	} else if ((ios->power_mode == MMC_POWER_UP) && !vub300->card_powered) {
 		usb_control_msg(vub300->udev, usb_sndctrlpipe(vub300->udev, 0),
 				SET_SD_POWER,
 				USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-				0x0001, 0x0000, NULL, 0, HZ);
+				0x0001, 0x0000, NULL, 0, 1000);
 		msleep(600);
 		vub300->card_powered = 1;
 	} else if (ios->power_mode == MMC_POWER_ON) {
@@ -2049,6 +2052,7 @@
 		return;
 	kref_get(&vub300->kref);
 	if (enable) {
+		set_current_state(TASK_RUNNING);
 		mutex_lock(&vub300->irq_mutex);
 		if (vub300->irqs_queued) {
 			vub300->irqs_queued -= 1;
@@ -2064,6 +2068,7 @@
 			vub300_queue_poll_work(vub300, 0);
 		}
 		mutex_unlock(&vub300->irq_mutex);
+		set_current_state(TASK_INTERRUPTIBLE);
 	} else {
 		vub300->irq_enabled = 0;
 	}
@@ -2282,14 +2287,14 @@
 				GET_HC_INF0,
 				USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 				0x0000, 0x0000, &vub300->hc_info,
-				sizeof(vub300->hc_info), HZ);
+				sizeof(vub300->hc_info), 1000);
 	if (retval < 0)
 		goto error5;
 	retval =
-		usb_control_msg(vub300->udev, usb_rcvctrlpipe(vub300->udev, 0),
+		usb_control_msg(vub300->udev, usb_sndctrlpipe(vub300->udev, 0),
 				SET_ROM_WAIT_STATES,
 				USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-				firmware_rom_wait_states, 0x0000, NULL, 0, HZ);
+				firmware_rom_wait_states, 0x0000, NULL, 0, 1000);
 	if (retval < 0)
 		goto error5;
 	dev_info(&vub300->udev->dev,
@@ -2304,16 +2309,17 @@
 				GET_SYSTEM_PORT_STATUS,
 				USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 				0x0000, 0x0000, &vub300->system_port_status,
-				sizeof(vub300->system_port_status), HZ);
+				sizeof(vub300->system_port_status), 1000);
 	if (retval < 0) {
-		goto error4;
+		goto error5;
 	} else if (sizeof(vub300->system_port_status) == retval) {
 		vub300->card_present =
 			(0x0001 & vub300->system_port_status.port_flags) ? 1 : 0;
 		vub300->read_only =
 			(0x0010 & vub300->system_port_status.port_flags) ? 1 : 0;
 	} else {
-		goto error4;
+		retval = -EINVAL;
+		goto error5;
 	}
 	usb_set_intfdata(interface, vub300);
 	INIT_DELAYED_WORK(&vub300->pollwork, vub300_pollwork_thread);
@@ -2336,8 +2342,13 @@
 			 "USB vub300 remote SDIO host controller[%d]"
 			 "connected with no SD/SDIO card inserted\n",
 			 interface_to_InterfaceNumber(interface));
-	mmc_add_host(mmc);
+	retval = mmc_add_host(mmc);
+	if (retval)
+		goto error6;
+
 	return 0;
+error6:
+	del_timer_sync(&vub300->inactivity_timer);
 error5:
 	mmc_free_host(mmc);
 	/*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/wbsd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/wbsd.c
@@ -1701,7 +1701,15 @@
 	 */
 	wbsd_init_device(host);
 
-	mmc_add_host(mmc);
+	ret = mmc_add_host(mmc);
+	if (ret) {
+		if (!pnp)
+			wbsd_chip_poweroff(host);
+
+		wbsd_release_resources(host);
+		wbsd_free_mmc(dev);
+		return ret;
+	}
 
 	pr_info("%s: W83L51xD", mmc_hostname(mmc));
 	if (host->chip_id != 0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mmc/host/wmt-sdmmc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mmc/host/wmt-sdmmc.c
@@ -849,7 +849,7 @@
 	if (IS_ERR(priv->clk_sdmmc)) {
 		dev_err(&pdev->dev, "Error getting clock\n");
 		ret = PTR_ERR(priv->clk_sdmmc);
-		goto fail5;
+		goto fail5_and_a_half;
 	}
 
 	ret = clk_prepare_enable(priv->clk_sdmmc);
@@ -859,13 +859,20 @@
 	/* configure the controller to a known 'ready' state */
 	wmt_reset_hardware(mmc);
 
-	mmc_add_host(mmc);
+	ret = mmc_add_host(mmc);
+	if (ret)
+		goto fail7;
 
 	dev_info(&pdev->dev, "WMT SDHC Controller initialized\n");
 
 	return 0;
+fail7:
+	clk_disable_unprepare(priv->clk_sdmmc);
 fail6:
 	clk_put(priv->clk_sdmmc);
+fail5_and_a_half:
+	dma_free_coherent(&pdev->dev, mmc->max_blk_count * 16,
+			  priv->dma_desc_buffer, priv->dma_desc_device_addr);
 fail5:
 	free_irq(dma_irq, priv);
 fail4:
@@ -882,7 +889,6 @@
 {
 	struct mmc_host *mmc;
 	struct wmt_mci_priv *priv;
-	struct resource *res;
 	u32 reg_tmp;
 
 	mmc = platform_get_drvdata(pdev);
@@ -910,9 +916,6 @@
 	clk_disable_unprepare(priv->clk_sdmmc);
 	clk_put(priv->clk_sdmmc);
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(res->start, resource_size(res));
-
 	mmc_free_host(mmc);
 
 	dev_info(&pdev->dev, "WMT MCI device removed\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/chips/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/chips/Kconfig
@@ -55,12 +55,14 @@
 	  LITTLE_ENDIAN_BYTE, if the bytes are reversed.
 
 config MTD_CFI_NOSWAP
+	depends on !ARCH_IXP4XX || CPU_BIG_ENDIAN
 	bool "NO"
 
 config MTD_CFI_BE_BYTE_SWAP
 	bool "BIG_ENDIAN_BYTE"
 
 config MTD_CFI_LE_BYTE_SWAP
+	depends on !ARCH_IXP4XX
 	bool "LITTLE_ENDIAN_BYTE"
 
 endchoice
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/chips/cfi_cmdset_0001.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -420,8 +420,25 @@
 		extra_size = 0;
 
 		/* Protection Register info */
-		extra_size += (extp->NumProtectionFields - 1) *
-			      sizeof(struct cfi_intelext_otpinfo);
+		if (extp->NumProtectionFields) {
+			struct cfi_intelext_otpinfo *otp =
+				(struct cfi_intelext_otpinfo *)&extp->extra[0];
+
+			extra_size += (extp->NumProtectionFields - 1) *
+				sizeof(struct cfi_intelext_otpinfo);
+
+			if (extp_size >= sizeof(*extp) + extra_size) {
+				int i;
+
+				/* Do some byteswapping if necessary */
+				for (i = 0; i < extp->NumProtectionFields - 1; i++) {
+					otp->ProtRegAddr = le32_to_cpu(otp->ProtRegAddr);
+					otp->FactGroups = le16_to_cpu(otp->FactGroups);
+					otp->UserGroups = le16_to_cpu(otp->UserGroups);
+					otp++;
+				}
+			}
+		}
 	}
 
 	if (extp->MinorVersion >= '1') {
@@ -695,14 +712,16 @@
 	 */
 	if (extp && extp->MajorVersion == '1' && extp->MinorVersion >= '3'
 	    && extp->FeatureSupport & (1 << 9)) {
+		int offs = 0;
 		struct cfi_private *newcfi;
 		struct flchip *chip;
 		struct flchip_shared *shared;
-		int offs, numregions, numparts, partshift, numvirtchips, i, j;
+		int numregions, numparts, partshift, numvirtchips, i, j;
 
 		/* Protection Register info */
-		offs = (extp->NumProtectionFields - 1) *
-		       sizeof(struct cfi_intelext_otpinfo);
+		if (extp->NumProtectionFields)
+			offs = (extp->NumProtectionFields - 1) *
+			       sizeof(struct cfi_intelext_otpinfo);
 
 		/* Burst Read info */
 		offs += extp->extra[offs+1]+2;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/chips/cfi_cmdset_0002.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -59,6 +59,10 @@
 #define CFI_SR_WBASB		BIT(3)
 #define CFI_SR_SLSB		BIT(1)
 
+enum cfi_quirks {
+	CFI_QUIRK_DQ_TRUE_DATA = BIT(0),
+};
+
 static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
 static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
 #if !FORCE_WORD_WRITE
@@ -119,23 +123,27 @@
 	struct cfi_pri_amdstd *extp = cfi->cmdset_priv;
 	u8 poll_mask = CFI_POLL_STATUS_REG | CFI_POLL_DQ;
 
-	return extp->MinorVersion >= '5' &&
+	return extp && extp->MinorVersion >= '5' &&
 		(extp->SoftwareFeatures & poll_mask) == CFI_POLL_STATUS_REG;
 }
 
-static void cfi_check_err_status(struct map_info *map, struct flchip *chip,
-				 unsigned long adr)
+static int cfi_check_err_status(struct map_info *map, struct flchip *chip,
+				unsigned long adr)
 {
 	struct cfi_private *cfi = map->fldrv_priv;
 	map_word status;
 
 	if (!cfi_use_status_reg(cfi))
-		return;
+		return 0;
 
 	cfi_send_gen_cmd(0x70, cfi->addr_unlock1, chip->start, map, cfi,
 			 cfi->device_type, NULL);
 	status = map_read(map, adr);
 
+	/* The error bits are invalid while the chip's busy */
+	if (!map_word_bitsset(map, status, CMD(CFI_SR_DRB)))
+		return 0;
+
 	if (map_word_bitsset(map, status, CMD(0x3a))) {
 		unsigned long chipstatus = MERGESTATUS(status);
 
@@ -151,7 +159,12 @@
 		if (chipstatus & CFI_SR_SLSB)
 			pr_err("%s sector write protected, status %lx\n",
 			       map->name, chipstatus);
+
+		/* Erase/Program status bits are set on the operation failure */
+		if (chipstatus & (CFI_SR_ESB | CFI_SR_PSB))
+			return 1;
 	}
+	return 0;
 }
 
 /* #define DEBUG_CFI_FEATURES */
@@ -423,6 +436,15 @@
 		mtd->name);
 }
 
+static void fixup_quirks(struct mtd_info *mtd)
+{
+	struct map_info *map = mtd->priv;
+	struct cfi_private *cfi = map->fldrv_priv;
+
+	if (cfi->mfr == CFI_MFR_AMD && cfi->id == 0x0c01)
+		cfi->quirks |= CFI_QUIRK_DQ_TRUE_DATA;
+}
+
 /* Used to fix CFI-Tables of chips without Extended Query Tables */
 static struct cfi_fixup cfi_nopri_fixup_table[] = {
 	{ CFI_MFR_SST, 0x234a, fixup_sst39vf }, /* SST39VF1602 */
@@ -461,6 +483,7 @@
 #if !FORCE_WORD_WRITE
 	{ CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers },
 #endif
+	{ CFI_MFR_ANY, CFI_ID_ANY, fixup_quirks },
 	{ 0, 0, NULL }
 };
 static struct cfi_fixup jedec_fixup_table[] = {
@@ -785,26 +808,29 @@
 	kfree(mtd->eraseregions);
 	kfree(mtd);
 	kfree(cfi->cmdset_priv);
-	kfree(cfi->cfiq);
 	return NULL;
 }
 
 /*
- * Return true if the chip is ready.
+ * Return true if the chip is ready and has the correct value.
  *
  * Ready is one of: read mode, query mode, erase-suspend-read mode (in any
  * non-suspended sector) and is indicated by no toggle bits toggling.
  *
+ * Error are indicated by toggling bits or bits held with the wrong value,
+ * or with bits toggling.
+ *
  * Note that anything more complicated than checking if no bits are toggling
  * (including checking DQ5 for an error status) is tricky to get working
  * correctly and is therefore not done	(particularly with interleaved chips
  * as each chip must be checked independently of the others).
  */
 static int __xipram chip_ready(struct map_info *map, struct flchip *chip,
-			       unsigned long addr)
+			       unsigned long addr, map_word *expected)
 {
 	struct cfi_private *cfi = map->fldrv_priv;
 	map_word d, t;
+	int ret;
 
 	if (cfi_use_status_reg(cfi)) {
 		map_word ready = CMD(CFI_SR_DRB);
@@ -814,61 +840,32 @@
 		 */
 		cfi_send_gen_cmd(0x70, cfi->addr_unlock1, chip->start, map, cfi,
 				 cfi->device_type, NULL);
-		d = map_read(map, addr);
+		t = map_read(map, addr);
 
-		return map_word_andequal(map, d, ready, ready);
+		return map_word_andequal(map, t, ready, ready);
 	}
 
 	d = map_read(map, addr);
 	t = map_read(map, addr);
 
-	return map_word_equal(map, d, t);
+	ret = map_word_equal(map, d, t);
+
+	if (!ret || !expected)
+		return ret;
+
+	return map_word_equal(map, t, *expected);
 }
 
-/*
- * Return true if the chip is ready and has the correct value.
- *
- * Ready is one of: read mode, query mode, erase-suspend-read mode (in any
- * non-suspended sector) and it is indicated by no bits toggling.
- *
- * Error are indicated by toggling bits or bits held with the wrong value,
- * or with bits toggling.
- *
- * Note that anything more complicated than checking if no bits are toggling
- * (including checking DQ5 for an error status) is tricky to get working
- * correctly and is therefore not done	(particularly with interleaved chips
- * as each chip must be checked independently of the others).
- *
- */
 static int __xipram chip_good(struct map_info *map, struct flchip *chip,
-			      unsigned long addr, map_word expected)
+			      unsigned long addr, map_word *expected)
 {
 	struct cfi_private *cfi = map->fldrv_priv;
-	map_word oldd, curd;
-
-	if (cfi_use_status_reg(cfi)) {
-		map_word ready = CMD(CFI_SR_DRB);
-		map_word err = CMD(CFI_SR_PSB | CFI_SR_ESB);
-		/*
-		 * For chips that support status register, check device
-		 * ready bit and Erase/Program status bit to know if
-		 * operation succeeded.
-		 */
-		cfi_send_gen_cmd(0x70, cfi->addr_unlock1, chip->start, map, cfi,
-				 cfi->device_type, NULL);
-		curd = map_read(map, addr);
-
-		if (map_word_andequal(map, curd, ready, ready))
-			return !map_word_bitsset(map, curd, err);
-
-		return 0;
-	}
+	map_word *datum = expected;
 
-	oldd = map_read(map, addr);
-	curd = map_read(map, addr);
+	if (cfi->quirks & CFI_QUIRK_DQ_TRUE_DATA)
+		datum = NULL;
 
-	return	map_word_equal(map, oldd, curd) &&
-		map_word_equal(map, curd, expected);
+	return chip_ready(map, chip, addr, datum);
 }
 
 static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode)
@@ -885,7 +882,7 @@
 
 	case FL_STATUS:
 		for (;;) {
-			if (chip_ready(map, chip, adr))
+			if (chip_ready(map, chip, adr, NULL))
 				break;
 
 			if (time_after(jiffies, timeo)) {
@@ -923,7 +920,7 @@
 		chip->state = FL_ERASE_SUSPENDING;
 		chip->erase_suspended = 1;
 		for (;;) {
-			if (chip_ready(map, chip, adr))
+			if (chip_ready(map, chip, adr, NULL))
 				break;
 
 			if (time_after(jiffies, timeo)) {
@@ -1455,7 +1452,7 @@
 	/* wait for chip to become ready */
 	timeo = jiffies + msecs_to_jiffies(2);
 	for (;;) {
-		if (chip_ready(map, chip, adr))
+		if (chip_ready(map, chip, adr, NULL))
 			break;
 
 		if (time_after(jiffies, timeo)) {
@@ -1691,7 +1688,7 @@
 		 * "chip_good" to avoid the failure due to scheduling.
 		 */
 		if (time_after(jiffies, timeo) &&
-		    !chip_good(map, chip, adr, datum)) {
+		    !chip_good(map, chip, adr, &datum)) {
 			xip_enable(map, chip, adr);
 			printk(KERN_WARNING "MTD %s(): software timeout\n", __func__);
 			xip_disable(map, chip, adr);
@@ -1699,8 +1696,11 @@
 			break;
 		}
 
-		if (chip_good(map, chip, adr, datum))
+		if (chip_good(map, chip, adr, &datum)) {
+			if (cfi_check_err_status(map, chip, adr))
+				ret = -EIO;
 			break;
+		}
 
 		/* Latency issues. Drop the lock, wait a while and retry */
 		UDELAY(map, chip, adr, 1);
@@ -1773,7 +1773,6 @@
 	ret = do_write_oneword_once(map, chip, adr, datum, mode, cfi);
 	if (ret) {
 		/* reset on all failures. */
-		cfi_check_err_status(map, chip, adr);
 		map_write(map, CMD(0xF0), chip->start);
 		/* FIXME - should have reset delay before continuing */
 
@@ -1969,13 +1968,18 @@
 		 * "chip_good" to avoid the failure due to scheduling.
 		 */
 		if (time_after(jiffies, timeo) &&
-		    !chip_good(map, chip, adr, datum)) {
+		    !chip_good(map, chip, adr, &datum)) {
+			pr_err("MTD %s(): software timeout, address:0x%.8lx.\n",
+			       __func__, adr);
 			ret = -EIO;
 			break;
 		}
 
-		if (chip_good(map, chip, adr, datum))
+		if (chip_good(map, chip, adr, &datum)) {
+			if (cfi_check_err_status(map, chip, adr))
+				ret = -EIO;
 			break;
+		}
 
 		/* Latency issues. Drop the lock, wait a while and retry */
 		UDELAY(map, chip, adr, 1);
@@ -2071,12 +2075,8 @@
 				chip->word_write_time);
 
 	ret = do_write_buffer_wait(map, chip, adr, datum);
-	if (ret) {
-		cfi_check_err_status(map, chip, adr);
+	if (ret)
 		do_write_buffer_reset(map, chip, cfi);
-		pr_err("MTD %s(): software timeout, address:0x%.8lx.\n",
-		       __func__, adr);
-	}
 
 	xip_enable(map, chip, adr);
 
@@ -2184,7 +2184,7 @@
 	 * If the driver thinks the chip is idle, and no toggle bits
 	 * are changing, then the chip is actually idle for sure.
 	 */
-	if (chip->state == FL_READY && chip_ready(map, chip, adr))
+	if (chip->state == FL_READY && chip_ready(map, chip, adr, NULL))
 		return 0;
 
 	/*
@@ -2201,7 +2201,7 @@
 
 		/* wait for the chip to become ready */
 		for (i = 0; i < jiffies_to_usecs(timeo); i++) {
-			if (chip_ready(map, chip, adr))
+			if (chip_ready(map, chip, adr, NULL))
 				return 0;
 
 			udelay(1);
@@ -2265,15 +2265,15 @@
 	map_write(map, datum, adr);
 
 	for (i = 0; i < jiffies_to_usecs(uWriteTimeout); i++) {
-		if (chip_ready(map, chip, adr))
+		if (chip_ready(map, chip, adr, NULL))
 			break;
 
 		udelay(1);
 	}
 
-	if (!chip_good(map, chip, adr, datum)) {
+	if (!chip_ready(map, chip, adr, &datum) ||
+	    cfi_check_err_status(map, chip, adr)) {
 		/* reset on all failures. */
-		cfi_check_err_status(map, chip, adr);
 		map_write(map, CMD(0xF0), chip->start);
 		/* FIXME - should have reset delay before continuing */
 
@@ -2413,6 +2413,7 @@
 	DECLARE_WAITQUEUE(wait, current);
 	int ret = 0;
 	int retry_cnt = 0;
+	map_word datum = map_word_ff(map);
 
 	adr = cfi->addr_unlock1;
 
@@ -2467,8 +2468,11 @@
 			chip->erase_suspended = 0;
 		}
 
-		if (chip_good(map, chip, adr, map_word_ff(map)))
+		if (chip_ready(map, chip, adr, &datum)) {
+			if (cfi_check_err_status(map, chip, adr))
+				ret = -EIO;
 			break;
+		}
 
 		if (time_after(jiffies, timeo)) {
 			printk(KERN_WARNING "MTD %s(): software timeout\n",
@@ -2483,7 +2487,6 @@
 	/* Did we succeed? */
 	if (ret) {
 		/* reset on all failures. */
-		cfi_check_err_status(map, chip, adr);
 		map_write(map, CMD(0xF0), chip->start);
 		/* FIXME - should have reset delay before continuing */
 
@@ -2510,6 +2513,7 @@
 	DECLARE_WAITQUEUE(wait, current);
 	int ret = 0;
 	int retry_cnt = 0;
+	map_word datum = map_word_ff(map);
 
 	adr += chip->start;
 
@@ -2564,8 +2568,11 @@
 			chip->erase_suspended = 0;
 		}
 
-		if (chip_good(map, chip, adr, map_word_ff(map)))
+		if (chip_ready(map, chip, adr, &datum)) {
+			if (cfi_check_err_status(map, chip, adr))
+				ret = -EIO;
 			break;
+		}
 
 		if (time_after(jiffies, timeo)) {
 			printk(KERN_WARNING "MTD %s(): software timeout\n",
@@ -2580,7 +2587,6 @@
 	/* Did we succeed? */
 	if (ret) {
 		/* reset on all failures. */
-		cfi_check_err_status(map, chip, adr);
 		map_write(map, CMD(0xF0), chip->start);
 		/* FIXME - should have reset delay before continuing */
 
@@ -2756,7 +2762,7 @@
 	 */
 	timeo = jiffies + msecs_to_jiffies(2000);	/* 2s max (un)locking */
 	for (;;) {
-		if (chip_ready(map, chip, adr))
+		if (chip_ready(map, chip, adr, NULL))
 			break;
 
 		if (time_after(jiffies, timeo)) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/chips/cfi_probe.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/chips/cfi_probe.c
@@ -198,6 +198,9 @@
 	__u32 base = 0;
 	int num_erase_regions = cfi_read_query(map, base + (0x10 + 28)*ofs_factor);
 	int i;
+	int extendedId1 = 0;
+	int extendedId2 = 0;
+	int extendedId3 = 0;
 	int addr_unlock1 = 0x555, addr_unlock2 = 0x2AA;
 
 	xip_enable(base, map, cfi);
@@ -222,6 +225,38 @@
 	for (i=0; i<(sizeof(struct cfi_ident) + num_erase_regions * 4); i++)
 		((unsigned char *)cfi->cfiq)[i] = cfi_read_query(map,base + (0x10 + i)*ofs_factor);
 
+	/* Note we put the device back into Read Mode BEFORE going into Auto
+	 * Select Mode, as some devices support nesting of modes, others
+	 * don't. This way should always work.
+	 * On cmdset 0001 the writes of 0xaa and 0x55 are not needed, and
+	 * so should be treated as nops or illegal (and so put the device
+	 * back into Read Mode, which is a nop in this case).
+	 */
+	cfi_send_gen_cmd(0xf0,     0, base, map, cfi, cfi->device_type, NULL);
+	cfi_send_gen_cmd(0xaa, 0x555, base, map, cfi, cfi->device_type, NULL);
+	cfi_send_gen_cmd(0x55, 0x2aa, base, map, cfi, cfi->device_type, NULL);
+	cfi_send_gen_cmd(0x90, 0x555, base, map, cfi, cfi->device_type, NULL);
+	cfi->mfr = cfi_read_query16(map, base);
+	cfi->id = cfi_read_query16(map, base + ofs_factor);
+
+	/* Get device ID cycle 1,2,3 for Numonyx/ST devices */
+	if ((cfi->mfr == CFI_MFR_INTEL || cfi->mfr == CFI_MFR_ST)
+		&& ((cfi->id & 0xff) == 0x7e)
+		&& (le16_to_cpu(cfi->cfiq->P_ID) == 0x0002)) {
+		extendedId1 = cfi_read_query16(map, base + 0x1 * ofs_factor);
+		extendedId2 = cfi_read_query16(map, base + 0xe * ofs_factor);
+		extendedId3 = cfi_read_query16(map, base + 0xf * ofs_factor);
+	}
+
+	/* Get AMD/Spansion extended JEDEC ID */
+	if (cfi->mfr == CFI_MFR_AMD && (cfi->id & 0xff) == 0x7e)
+		cfi->id = cfi_read_query(map, base + 0xe * ofs_factor) << 8 |
+			  cfi_read_query(map, base + 0xf * ofs_factor);
+
+	/* Put it back into Read Mode */
+	cfi_qry_mode_off(base, map, cfi);
+	xip_allowed(base, map);
+
 	/* Do any necessary byteswapping */
 	cfi->cfiq->P_ID = le16_to_cpu(cfi->cfiq->P_ID);
 
@@ -231,6 +266,16 @@
 	cfi->cfiq->InterfaceDesc = le16_to_cpu(cfi->cfiq->InterfaceDesc);
 	cfi->cfiq->MaxBufWriteSize = le16_to_cpu(cfi->cfiq->MaxBufWriteSize);
 
+   /* If the device is a M29EW used in 8-bit mode, adjust buffer size */
+	if ((cfi->cfiq->MaxBufWriteSize > 0x8) && (cfi->mfr == CFI_MFR_INTEL ||
+		 cfi->mfr == CFI_MFR_ST) && (extendedId1 == 0x7E) &&
+		 (extendedId2 == 0x22 || extendedId2 == 0x23 || extendedId2 == 0x28) &&
+		 (extendedId3 == 0x01)) {
+		cfi->cfiq->MaxBufWriteSize = 0x8;
+		pr_warning("Adjusted buffer size on Numonyx flash M29EW family");
+		pr_warning("in 8 bit mode\n");
+    }
+
 #ifdef DEBUG_CFI
 	/* Dump the information therein */
 	print_cfi_ident(cfi->cfiq);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/devices/docg3.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/devices/docg3.c
@@ -1975,9 +1975,14 @@
 		dev_err(dev, "No I/O memory resource defined\n");
 		return ret;
 	}
-	base = devm_ioremap(dev, ress->start, DOC_IOSPACE_SIZE);
 
 	ret = -ENOMEM;
+	base = devm_ioremap(dev, ress->start, DOC_IOSPACE_SIZE);
+	if (!base) {
+		dev_err(dev, "devm_ioremap dev failed\n");
+		return ret;
+	}
+
 	cascade = devm_kcalloc(dev, DOC_MAX_NBFLOORS, sizeof(*cascade),
 			       GFP_KERNEL);
 	if (!cascade)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/devices/mchp23k256.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/devices/mchp23k256.c
@@ -64,15 +64,17 @@
 	struct spi_transfer transfer[2] = {};
 	struct spi_message message;
 	unsigned char command[MAX_CMD_SIZE];
-	int ret;
+	int ret, cmd_len;
 
 	spi_message_init(&message);
 
+	cmd_len = mchp23k256_cmdsz(flash);
+
 	command[0] = MCHP23K256_CMD_WRITE;
 	mchp23k256_addr2cmd(flash, to, command);
 
 	transfer[0].tx_buf = command;
-	transfer[0].len = mchp23k256_cmdsz(flash);
+	transfer[0].len = cmd_len;
 	spi_message_add_tail(&transfer[0], &message);
 
 	transfer[1].tx_buf = buf;
@@ -88,8 +90,8 @@
 	if (ret)
 		return ret;
 
-	if (retlen && message.actual_length > sizeof(command))
-		*retlen += message.actual_length - sizeof(command);
+	if (retlen && message.actual_length > cmd_len)
+		*retlen += message.actual_length - cmd_len;
 
 	return 0;
 }
@@ -101,16 +103,18 @@
 	struct spi_transfer transfer[2] = {};
 	struct spi_message message;
 	unsigned char command[MAX_CMD_SIZE];
-	int ret;
+	int ret, cmd_len;
 
 	spi_message_init(&message);
 
+	cmd_len = mchp23k256_cmdsz(flash);
+
 	memset(&transfer, 0, sizeof(transfer));
 	command[0] = MCHP23K256_CMD_READ;
 	mchp23k256_addr2cmd(flash, from, command);
 
 	transfer[0].tx_buf = command;
-	transfer[0].len = mchp23k256_cmdsz(flash);
+	transfer[0].len = cmd_len;
 	spi_message_add_tail(&transfer[0], &message);
 
 	transfer[1].rx_buf = buf;
@@ -126,8 +130,8 @@
 	if (ret)
 		return ret;
 
-	if (retlen && message.actual_length > sizeof(command))
-		*retlen += message.actual_length - sizeof(command);
+	if (retlen && message.actual_length > cmd_len)
+		*retlen += message.actual_length - cmd_len;
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/devices/phram.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/devices/phram.c
@@ -243,22 +243,25 @@
 
 	ret = parse_num64(&start, token[1]);
 	if (ret) {
-		kfree(name);
 		parse_err("illegal start address\n");
+		goto error;
 	}
 
 	ret = parse_num64(&len, token[2]);
 	if (ret) {
-		kfree(name);
 		parse_err("illegal device length\n");
+		goto error;
 	}
 
 	ret = register_device(name, start, len);
-	if (!ret)
-		pr_info("%s device: %#llx at %#llx\n", name, len, start);
-	else
-		kfree(name);
+	if (ret)
+		goto error;
 
+	pr_info("%s device: %#llx at %#llx\n", name, len, start);
+	return 0;
+
+error:
+	kfree(name);
 	return ret;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/devices/powernv_flash.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/devices/powernv_flash.c
@@ -204,6 +204,9 @@
 	 * get them
 	 */
 	mtd->name = devm_kasprintf(dev, GFP_KERNEL, "%pOFP", dev->of_node);
+	if (!mtd->name)
+		return -ENOMEM;
+
 	mtd->type = MTD_NORFLASH;
 	mtd->flags = MTD_WRITEABLE;
 	mtd->size = size;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/devices/slram.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/devices/slram.c
@@ -296,10 +296,12 @@
 		T("slram: devname = %s\n", devname);
 		if ((!map) || (!(devstart = strsep(&map, ",")))) {
 			E("slram: No devicestart specified.\n");
+			break;
 		}
 		T("slram: devstart = %s\n", devstart);
 		if ((!map) || (!(devlength = strsep(&map, ",")))) {
 			E("slram: No devicelength / -end specified.\n");
+			break;
 		}
 		T("slram: devlength = %s\n", devlength);
 		if (parse_cmdline(devname, devstart, devlength) != 0) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/devices/spear_smi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/devices/spear_smi.c
@@ -592,6 +592,26 @@
 	return 0;
 }
 
+/*
+ * The purpose of this function is to ensure a memcpy_toio() with byte writes
+ * only. Its structure is inspired from the ARM implementation of _memcpy_toio()
+ * which also does single byte writes but cannot be used here as this is just an
+ * implementation detail and not part of the API. Not mentioning the comment
+ * stating that _memcpy_toio() should be optimized.
+ */
+static void spear_smi_memcpy_toio_b(volatile void __iomem *dest,
+				    const void *src, size_t len)
+{
+	const unsigned char *from = src;
+
+	while (len) {
+		len--;
+		writeb(*from, dest);
+		from++;
+		dest++;
+	}
+}
+
 static inline int spear_smi_cpy_toio(struct spear_smi *dev, u32 bank,
 		void __iomem *dest, const void *src, size_t len)
 {
@@ -614,7 +634,23 @@
 	ctrlreg1 = readl(dev->io_base + SMI_CR1);
 	writel((ctrlreg1 | WB_MODE) & ~SW_MODE, dev->io_base + SMI_CR1);
 
-	memcpy_toio(dest, src, len);
+	/*
+	 * In Write Burst mode (WB_MODE), the specs states that writes must be:
+	 * - incremental
+	 * - of the same size
+	 * The ARM implementation of memcpy_toio() will optimize the number of
+	 * I/O by using as much 4-byte writes as possible, surrounded by
+	 * 2-byte/1-byte access if:
+	 * - the destination is not 4-byte aligned
+	 * - the length is not a multiple of 4-byte.
+	 * Avoid this alternance of write access size by using our own 'byte
+	 * access' helper if at least one of the two conditions above is true.
+	 */
+	if (IS_ALIGNED(len, sizeof(u32)) &&
+	    IS_ALIGNED((uintptr_t)dest, sizeof(u32)))
+		memcpy_toio(dest, src, len);
+	else
+		spear_smi_memcpy_toio_b(dest, src, len);
 
 	writel(ctrlreg1, dev->io_base + SMI_CR1);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/devices/st_spi_fsm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/devices/st_spi_fsm.c
@@ -2116,10 +2116,12 @@
 		(long long)fsm->mtd.size, (long long)(fsm->mtd.size >> 20),
 		fsm->mtd.erasesize, (fsm->mtd.erasesize >> 10));
 
-	return mtd_device_register(&fsm->mtd, NULL, 0);
-
+	ret = mtd_device_register(&fsm->mtd, NULL, 0);
+	if (ret) {
 err_clk_unprepare:
-	clk_disable_unprepare(fsm->clk);
+		clk_disable_unprepare(fsm->clk);
+	}
+
 	return ret;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/lpddr/lpddr2_nvm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/lpddr/lpddr2_nvm.c
@@ -393,6 +393,17 @@
 	return lpddr2_nvm_do_block_op(mtd, start_add, len, LPDDR2_NVM_LOCK);
 }
 
+static const struct mtd_info lpddr2_nvm_mtd_info = {
+	.type		= MTD_RAM,
+	.writesize	= 1,
+	.flags		= (MTD_CAP_NVRAM | MTD_POWERUP_LOCK),
+	._read		= lpddr2_nvm_read,
+	._write		= lpddr2_nvm_write,
+	._erase		= lpddr2_nvm_erase,
+	._unlock	= lpddr2_nvm_unlock,
+	._lock		= lpddr2_nvm_lock,
+};
+
 /*
  * lpddr2_nvm driver probe method
  */
@@ -422,6 +433,8 @@
 
 	/* lpddr2_nvm address range */
 	add_range = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!add_range)
+		return -ENODEV;
 
 	/* Populate map_info data structure */
 	*map = (struct map_info) {
@@ -433,6 +446,7 @@
 		.pfow_base	= OW_BASE_ADDRESS,
 		.fldrv_priv	= pcm_data,
 	};
+
 	if (IS_ERR(map->virt))
 		return PTR_ERR(map->virt);
 
@@ -444,22 +458,13 @@
 		return PTR_ERR(pcm_data->ctl_regs);
 
 	/* Populate mtd_info data structure */
-	*mtd = (struct mtd_info) {
-		.dev		= { .parent = &pdev->dev },
-		.name		= pdev->dev.init_name,
-		.type		= MTD_RAM,
-		.priv		= map,
-		.size		= resource_size(add_range),
-		.erasesize	= ERASE_BLOCKSIZE * pcm_data->bus_width,
-		.writesize	= 1,
-		.writebufsize	= WRITE_BUFFSIZE * pcm_data->bus_width,
-		.flags		= (MTD_CAP_NVRAM | MTD_POWERUP_LOCK),
-		._read		= lpddr2_nvm_read,
-		._write		= lpddr2_nvm_write,
-		._erase		= lpddr2_nvm_erase,
-		._unlock	= lpddr2_nvm_unlock,
-		._lock		= lpddr2_nvm_lock,
-	};
+	*mtd = lpddr2_nvm_mtd_info;
+	mtd->dev.parent		= &pdev->dev;
+	mtd->name		= pdev->dev.init_name;
+	mtd->priv		= map;
+	mtd->size		= resource_size(add_range);
+	mtd->erasesize		= ERASE_BLOCKSIZE * pcm_data->bus_width;
+	mtd->writebufsize	= WRITE_BUFFSIZE * pcm_data->bus_width;
 
 	/* Verify the presence of the device looking for PFOW string */
 	if (!lpddr2_nvm_pfow_present(map)) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/lpddr/lpddr_cmds.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/lpddr/lpddr_cmds.c
@@ -68,7 +68,6 @@
 	shared = kmalloc_array(lpddr->numchips, sizeof(struct flchip_shared),
 						GFP_KERNEL);
 	if (!shared) {
-		kfree(lpddr);
 		kfree(mtd);
 		return NULL;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/maps/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/maps/Kconfig
@@ -303,7 +303,7 @@
 
 config MTD_IXP4XX
 	tristate "CFI Flash device mapped on Intel IXP4xx based systems"
-	depends on MTD_CFI && MTD_COMPLEX_MAPPINGS && ARCH_IXP4XX
+	depends on MTD_CFI && MTD_COMPLEX_MAPPINGS && ARCH_IXP4XX && MTD_CFI_ADV_OPTIONS
 	help
 	  This enables MTD access to flash devices on platforms based
 	  on Intel's IXP4xx family of network processors such as the
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/maps/physmap-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/maps/physmap-core.c
@@ -505,7 +505,7 @@
 		if (!info->maps[i].phys)
 			info->maps[i].phys = res->start;
 
-		info->win_order = get_bitmask_order(resource_size(res)) - 1;
+		info->win_order = fls64(resource_size(res)) - 1;
 		info->maps[i].size = BIT(info->win_order +
 					 (info->gpios ?
 					  info->gpios->ndescs : 0));
@@ -533,6 +533,17 @@
 		if (info->probe_type) {
 			info->mtds[i] = do_map_probe(info->probe_type,
 						     &info->maps[i]);
+
+			/* Fall back to mapping region as ROM */
+			if (!info->mtds[i] && IS_ENABLED(CONFIG_MTD_ROM) &&
+			    strcmp(info->probe_type, "map_rom")) {
+				dev_warn(&dev->dev,
+					 "map_probe() failed for type %s\n",
+					 info->probe_type);
+
+				info->mtds[i] = do_map_probe("map_rom",
+							     &info->maps[i]);
+			}
 		} else {
 			int j;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/maps/physmap-versatile.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/maps/physmap-versatile.c
@@ -93,6 +93,7 @@
 		return -ENODEV;
 	}
 	ebi_base = of_iomap(ebi, 0);
+	of_node_put(ebi);
 	if (!ebi_base)
 		return -ENODEV;
 
@@ -207,6 +208,7 @@
 
 		versatile_flashprot = (enum versatile_flashprot)devid->data;
 		rmap = syscon_node_to_regmap(sysnp);
+		of_node_put(sysnp);
 		if (IS_ERR(rmap))
 			return PTR_ERR(rmap);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/maps/pxa2xx-flash.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/maps/pxa2xx-flash.c
@@ -66,6 +66,7 @@
 	if (!info->map.virt) {
 		printk(KERN_WARNING "Failed to ioremap %s\n",
 		       info->map.name);
+		kfree(info);
 		return -ENOMEM;
 	}
 	info->map.cached = ioremap_cache(info->map.phys, info->map.size);
@@ -87,6 +88,7 @@
 		iounmap((void *)info->map.virt);
 		if (info->map.cached)
 			iounmap(info->map.cached);
+		kfree(info);
 		return -EIO;
 	}
 	info->mtd->dev.parent = &pdev->dev;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/mtd_blkdevs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/mtd_blkdevs.c
@@ -533,7 +533,7 @@
 {
 	struct mtd_blktrans_ops *tr;
 
-	if (mtd->type == MTD_ABSENT)
+	if (mtd->type == MTD_ABSENT || mtd->type == MTD_UBIVOLUME)
 		return;
 
 	list_for_each_entry(tr, &blktrans_majors, list)
@@ -576,7 +576,7 @@
 	list_add(&tr->list, &blktrans_majors);
 
 	mtd_for_each_device(mtd)
-		if (mtd->type != MTD_ABSENT)
+		if (mtd->type != MTD_ABSENT && mtd->type != MTD_UBIVOLUME)
 			tr->add_mtd(tr, mtd);
 
 	mutex_unlock(&mtd_table_mutex);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/mtdblock.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/mtdblock.c
@@ -150,7 +150,7 @@
 				mtdblk->cache_state = STATE_EMPTY;
 				ret = mtd_read(mtd, sect_start, sect_size,
 					       &retlen, mtdblk->cache_data);
-				if (ret)
+				if (ret && !mtd_is_bitflip(ret))
 					return ret;
 				if (retlen != sect_size)
 					return -EIO;
@@ -185,8 +185,12 @@
 	pr_debug("mtdblock: read on \"%s\" at 0x%lx, size 0x%x\n",
 			mtd->name, pos, len);
 
-	if (!sect_size)
-		return mtd_read(mtd, pos, len, &retlen, buf);
+	if (!sect_size) {
+		ret = mtd_read(mtd, pos, len, &retlen, buf);
+		if (ret && !mtd_is_bitflip(ret))
+			return ret;
+		return 0;
+	}
 
 	while (len > 0) {
 		unsigned long sect_start = (pos/sect_size)*sect_size;
@@ -206,7 +210,7 @@
 			memcpy (buf, mtdblk->cache_data + offset, size);
 		} else {
 			ret = mtd_read(mtd, pos, size, &retlen, buf);
-			if (ret)
+			if (ret && !mtd_is_bitflip(ret))
 				return ret;
 			if (retlen != size)
 				return -EIO;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/mtdchar.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/mtdchar.c
@@ -354,9 +354,6 @@
 	uint32_t retlen;
 	int ret = 0;
 
-	if (!(file->f_mode & FMODE_WRITE))
-		return -EPERM;
-
 	if (length > 4096)
 		return -EINVAL;
 
@@ -641,6 +638,48 @@
 
 	pr_debug("MTD_ioctl\n");
 
+	/*
+	 * Check the file mode to require "dangerous" commands to have write
+	 * permissions.
+	 */
+	switch (cmd) {
+	/* "safe" commands */
+	case MEMGETREGIONCOUNT:
+	case MEMGETREGIONINFO:
+	case MEMGETINFO:
+	case MEMREADOOB:
+	case MEMREADOOB64:
+	case MEMISLOCKED:
+	case MEMGETOOBSEL:
+	case MEMGETBADBLOCK:
+	case OTPSELECT:
+	case OTPGETREGIONCOUNT:
+	case OTPGETREGIONINFO:
+	case ECCGETLAYOUT:
+	case ECCGETSTATS:
+	case MTDFILEMODE:
+	case BLKPG:
+	case BLKRRPART:
+		break;
+
+	/* "dangerous" commands */
+	case MEMERASE:
+	case MEMERASE64:
+	case MEMLOCK:
+	case MEMUNLOCK:
+	case MEMSETBADBLOCK:
+	case MEMWRITEOOB:
+	case MEMWRITEOOB64:
+	case MEMWRITE:
+	case OTPLOCK:
+		if (!(file->f_mode & FMODE_WRITE))
+			return -EPERM;
+		break;
+
+	default:
+		return -ENOTTY;
+	}
+
 	switch (cmd) {
 	case MEMGETREGIONCOUNT:
 		if (copy_to_user(argp, &(mtd->numeraseregions), sizeof(int)))
@@ -688,9 +727,6 @@
 	{
 		struct erase_info *erase;
 
-		if(!(file->f_mode & FMODE_WRITE))
-			return -EPERM;
-
 		erase=kzalloc(sizeof(struct erase_info),GFP_KERNEL);
 		if (!erase)
 			ret = -ENOMEM;
@@ -983,9 +1019,6 @@
 		ret = 0;
 		break;
 	}
-
-	default:
-		ret = -ENOTTY;
 	}
 
 	return ret;
@@ -1029,6 +1062,11 @@
 		struct mtd_oob_buf32 buf;
 		struct mtd_oob_buf32 __user *buf_user = argp;
 
+		if (!(file->f_mode & FMODE_WRITE)) {
+			ret = -EPERM;
+			break;
+		}
+
 		if (copy_from_user(&buf, argp, sizeof(buf)))
 			ret = -EFAULT;
 		else
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/mtdcore.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/mtdcore.c
@@ -563,7 +563,7 @@
 
 	config.id = -1;
 	config.dev = &mtd->dev;
-	config.name = mtd->name;
+	config.name = dev_name(&mtd->dev);
 	config.owner = THIS_MODULE;
 	config.reg_read = mtd_nvmem_reg_read;
 	config.size = mtd->size;
@@ -673,8 +673,10 @@
 	dev_set_drvdata(&mtd->dev, mtd);
 	of_node_get(mtd_get_of_node(mtd));
 	error = device_register(&mtd->dev);
-	if (error)
+	if (error) {
+		put_device(&mtd->dev);
 		goto fail_added;
+	}
 
 	/* Add the nvmem provider */
 	error = mtd_nvmem_add(mtd);
@@ -727,8 +729,6 @@
 
 	mutex_lock(&mtd_table_mutex);
 
-	debugfs_remove_recursive(mtd->dbg.dfs_dir);
-
 	if (idr_find(&mtd_idr, mtd->index) != mtd) {
 		ret = -ENODEV;
 		goto out_error;
@@ -744,6 +744,8 @@
 		       mtd->index, mtd->name, mtd->usecount);
 		ret = -EBUSY;
 	} else {
+		debugfs_remove_recursive(mtd->dbg.dfs_dir);
+
 		/* Try to remove the NVMEM provider */
 		if (mtd->nvmem)
 			nvmem_unregister(mtd->nvmem);
@@ -825,6 +827,9 @@
 
 	/* Prefer parsed partitions over driver-provided fallback */
 	ret = parse_mtd_partitions(mtd, types, parser_data);
+	if (ret == -EPROBE_DEFER)
+		goto out;
+
 	if (ret > 0)
 		ret = 0;
 	else if (nr_parts)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/mtdoops.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/mtdoops.c
@@ -279,12 +279,13 @@
 	kmsg_dump_get_buffer(dumper, true, cxt->oops_buf + MTDOOPS_HEADER_SIZE,
 			     record_size - MTDOOPS_HEADER_SIZE, NULL);
 
-	/* Panics must be written immediately */
-	if (reason != KMSG_DUMP_OOPS)
+	if (reason != KMSG_DUMP_OOPS) {
+		/* Panics must be written immediately */
 		mtdoops_write(cxt, 1);
-
-	/* For other cases, schedule work to write it "nicely" */
-	schedule_work(&cxt->work_write);
+	} else {
+		/* For other cases, schedule work to write it "nicely" */
+		schedule_work(&cxt->work_write);
+	}
 }
 
 static void mtdoops_notify_add(struct mtd_info *mtd)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/bbt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/bbt.c
@@ -123,7 +123,7 @@
 		unsigned int rbits = bits_per_block + offs - BITS_PER_LONG;
 
 		pos[1] &= ~GENMASK(rbits - 1, 0);
-		pos[1] |= val >> rbits;
+		pos[1] |= val >> (bits_per_block - rbits);
 	}
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/onenand/generic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/onenand/generic.c
@@ -53,7 +53,12 @@
 	}
 
 	info->onenand.mmcontrol = pdata ? pdata->mmcontrol : NULL;
-	info->onenand.irq = platform_get_irq(pdev, 0);
+
+	err = platform_get_irq(pdev, 0);
+	if (err < 0)
+		goto out_iounmap;
+
+	info->onenand.irq = err;
 
 	info->mtd.dev.parent = &pdev->dev;
 	info->mtd.priv = &info->onenand;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/onenand/omap2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/onenand/omap2.c
@@ -328,7 +328,8 @@
 	struct dma_async_tx_descriptor *tx;
 	dma_cookie_t cookie;
 
-	tx = dmaengine_prep_dma_memcpy(c->dma_chan, dst, src, count, 0);
+	tx = dmaengine_prep_dma_memcpy(c->dma_chan, dst, src, count,
+				       DMA_CTRL_ACK | DMA_PREP_INTERRUPT);
 	if (!tx) {
 		dev_err(&c->pdev->dev, "Failed to prepare DMA memcpy\n");
 		return -EIO;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/onenand/onenand_base.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/onenand/onenand_base.c
@@ -1248,44 +1248,44 @@
 
 	stats = mtd->ecc_stats;
 
- 	/* Read-while-load method */
+	/* Read-while-load method */
 
- 	/* Do first load to bufferRAM */
- 	if (read < len) {
- 		if (!onenand_check_bufferram(mtd, from)) {
+	/* Do first load to bufferRAM */
+	if (read < len) {
+		if (!onenand_check_bufferram(mtd, from)) {
 			this->command(mtd, ONENAND_CMD_READ, from, writesize);
- 			ret = this->wait(mtd, FL_READING);
- 			onenand_update_bufferram(mtd, from, !ret);
+			ret = this->wait(mtd, FL_READING);
+			onenand_update_bufferram(mtd, from, !ret);
 			if (mtd_is_eccerr(ret))
 				ret = 0;
- 		}
- 	}
+		}
+	}
 
 	thislen = min_t(int, writesize, len - read);
 	column = from & (writesize - 1);
 	if (column + thislen > writesize)
 		thislen = writesize - column;
 
- 	while (!ret) {
- 		/* If there is more to load then start next load */
- 		from += thislen;
- 		if (read + thislen < len) {
+	while (!ret) {
+		/* If there is more to load then start next load */
+		from += thislen;
+		if (read + thislen < len) {
 			this->command(mtd, ONENAND_CMD_READ, from, writesize);
- 			/*
- 			 * Chip boundary handling in DDP
- 			 * Now we issued chip 1 read and pointed chip 1
+			/*
+			 * Chip boundary handling in DDP
+			 * Now we issued chip 1 read and pointed chip 1
 			 * bufferram so we have to point chip 0 bufferram.
- 			 */
- 			if (ONENAND_IS_DDP(this) &&
- 			    unlikely(from == (this->chipsize >> 1))) {
- 				this->write_word(ONENAND_DDP_CHIP0, this->base + ONENAND_REG_START_ADDRESS2);
- 				boundary = 1;
- 			} else
- 				boundary = 0;
- 			ONENAND_SET_PREV_BUFFERRAM(this);
- 		}
- 		/* While load is going, read from last bufferRAM */
- 		this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, thislen);
+			 */
+			if (ONENAND_IS_DDP(this) &&
+			    unlikely(from == (this->chipsize >> 1))) {
+				this->write_word(ONENAND_DDP_CHIP0, this->base + ONENAND_REG_START_ADDRESS2);
+				boundary = 1;
+			} else
+				boundary = 0;
+			ONENAND_SET_PREV_BUFFERRAM(this);
+		}
+		/* While load is going, read from last bufferRAM */
+		this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, thislen);
 
 		/* Read oob area if needed */
 		if (oobbuf) {
@@ -1301,24 +1301,24 @@
 			oobcolumn = 0;
 		}
 
- 		/* See if we are done */
- 		read += thislen;
- 		if (read == len)
- 			break;
- 		/* Set up for next read from bufferRAM */
- 		if (unlikely(boundary))
- 			this->write_word(ONENAND_DDP_CHIP1, this->base + ONENAND_REG_START_ADDRESS2);
- 		ONENAND_SET_NEXT_BUFFERRAM(this);
- 		buf += thislen;
+		/* See if we are done */
+		read += thislen;
+		if (read == len)
+			break;
+		/* Set up for next read from bufferRAM */
+		if (unlikely(boundary))
+			this->write_word(ONENAND_DDP_CHIP1, this->base + ONENAND_REG_START_ADDRESS2);
+		ONENAND_SET_NEXT_BUFFERRAM(this);
+		buf += thislen;
 		thislen = min_t(int, writesize, len - read);
- 		column = 0;
- 		cond_resched();
- 		/* Now wait for load */
- 		ret = this->wait(mtd, FL_READING);
- 		onenand_update_bufferram(mtd, from, !ret);
+		column = 0;
+		cond_resched();
+		/* Now wait for load */
+		ret = this->wait(mtd, FL_READING);
+		onenand_update_bufferram(mtd, from, !ret);
 		if (mtd_is_eccerr(ret))
 			ret = 0;
- 	}
+	}
 
 	/*
 	 * Return success, if no ECC failures, else -EBADMSG
@@ -2921,6 +2921,7 @@
 	ret = ONENAND_IS_4KB_PAGE(this) ?
 		onenand_mlc_read_ops_nolock(mtd, from, &ops) :
 		onenand_read_ops_nolock(mtd, from, &ops);
+	*retlen = ops.retlen;
 
 	/* Exit OTP access mode */
 	this->command(mtd, ONENAND_CMD_RESET, 0, 0);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/Kconfig
@@ -544,4 +544,18 @@
 	  load time (assuming you build diskonchip as a module) with the module
 	  parameter "inftl_bbt_write=1".
 
+config MTD_NAND_ARASAN
+	tristate "Support for Arasan Nand Flash controller"
+	depends on HAS_IOMEM &&  HAS_DMA
+	help
+	  Enables the driver for the Arasan Nand Flash controller on
+	  Zynq Ultrascale+ MPSoC.
+
+config MTD_NAND_PL353
+	tristate "ARM PL353 NAND Flash driver"
+	depends on MTD_RAW_NAND && ARM
+	depends on PL353_SMC
+	help
+	  Enables support for PrimeCell Static Memory Controller PL353
+
 endif # MTD_RAW_NAND
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/Makefile
@@ -57,6 +57,8 @@
 obj-$(CONFIG_MTD_NAND_TEGRA)		+= tegra_nand.o
 obj-$(CONFIG_MTD_NAND_STM32_FMC2)	+= stm32_fmc2_nand.o
 obj-$(CONFIG_MTD_NAND_MESON)		+= meson_nand.o
+obj-$(CONFIG_MTD_NAND_ARASAN)		+= arasan_nand.o
+obj-$(CONFIG_MTD_NAND_PL353)		+= pl353_nand.o
 
 nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o
 nand-objs += nand_onfi.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/arasan_nand.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/arasan_nand.c
@@ -0,0 +1,1527 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Arasan NAND Flash Controller Driver
+ *
+ * Copyright (C) 2014 - 2017 Xilinx, Inc.
+ * Author: Punnaiah Choudary Kalluri <punnaia@xilinx.com>
+ * Author: Naga Sureshkumar Relli <nagasure@xilinx.com>
+ *
+ */
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
+#include <linux/module.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/rawnand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mtd/nand_bch.h>
+#include "internals.h"
+#include <linux/pm_runtime.h>
+
+#define EVENT_TIMEOUT_MSEC	1000
+#define ANFC_PM_TIMEOUT		1000	/* ms */
+
+#define PKT_OFST		0x00
+#define PKT_CNT_SHIFT		12
+
+#define MEM_ADDR1_OFST		0x04
+#define MEM_ADDR2_OFST		0x08
+#define PG_ADDR_SHIFT		16
+#define BCH_MODE_SHIFT		25
+#define MEM_ADDR_MASK		GENMASK(7, 0)
+#define BCH_MODE_MASK		GENMASK(27, 25)
+#define CS_MASK			GENMASK(31, 30)
+#define CS_SHIFT		30
+
+#define CMD_OFST		0x0C
+#define ECC_ENABLE		BIT(31)
+#define DMA_EN_MASK		GENMASK(27, 26)
+#define DMA_ENABLE		0x2
+#define DMA_EN_SHIFT		26
+#define REG_PAGE_SIZE_SHIFT	23
+
+#define PROG_OFST		0x10
+#define PROG_PGRD		BIT(0)
+#define PROG_ERASE		BIT(2)
+#define PROG_STATUS		BIT(3)
+#define PROG_PGPROG		BIT(4)
+#define PROG_RDID		BIT(6)
+#define PROG_RDPARAM		BIT(7)
+#define PROG_RST		BIT(8)
+#define PROG_GET_FEATURE	BIT(9)
+#define PROG_SET_FEATURE	BIT(10)
+
+#define INTR_STS_EN_OFST	0x14
+#define INTR_SIG_EN_OFST	0x18
+#define XFER_COMPLETE		BIT(2)
+#define READ_READY		BIT(1)
+#define WRITE_READY		BIT(0)
+#define MBIT_ERROR		BIT(3)
+#define EVENT_MASK	(XFER_COMPLETE | READ_READY | WRITE_READY | MBIT_ERROR)
+
+#define INTR_STS_OFST		0x1C
+#define READY_STS_OFST		0x20
+#define DMA_ADDR1_OFST		0x24
+#define FLASH_STS_OFST		0x28
+#define DATA_PORT_OFST		0x30
+#define ECC_OFST		0x34
+#define BCH_EN_SHIFT		27
+#define ECC_SIZE_SHIFT		16
+
+#define ECC_ERR_CNT_OFST	0x38
+#define PAGE_ERR_CNT_MASK	GENMASK(16, 8)
+#define PKT_ERR_CNT_MASK	GENMASK(7, 0)
+
+#define ECC_SPR_CMD_OFST	0x3C
+#define CMD2_SHIFT		8
+#define ADDR_CYCLES_SHIFT	28
+
+#define ECC_ERR_CNT_1BIT_OFST	0x40
+#define ECC_ERR_CNT_2BIT_OFST	0x44
+#define DMA_ADDR0_OFST		0x50
+#define DATA_INTERFACE_OFST	0x6C
+#define ANFC_MAX_CHUNK_SIZE	0x4000
+#define ANFC_MAX_ADDR_CYCLES	7
+
+#define REG_PAGE_SIZE_512	0
+#define REG_PAGE_SIZE_1K	5
+#define REG_PAGE_SIZE_2K	1
+#define REG_PAGE_SIZE_4K	2
+#define REG_PAGE_SIZE_8K	3
+#define REG_PAGE_SIZE_16K	4
+
+#define TEMP_BUF_SIZE		1024
+#define NVDDR_MODE_PACKET_SIZE	8
+#define SDR_MODE_PACKET_SIZE	4
+
+#define ONFI_DATA_INTERFACE_NVDDR	BIT(4)
+#define NVDDR_MODE			BIT(9)
+#define NVDDR_TIMING_MODE_SHIFT		3
+#define SDR_MODE_DEFLT_FREQ	80000000
+#define COL_ROW_ADDR(pos, val)	(((val) & 0xFF) << (8 * (pos)))
+
+/*
+ * Arasan NAND controller can't detect errors beyond 24-bit in BCH
+ * For an erased page we observed that multibit error count as 16
+ * with 24-bit ECC. so if the count is equal to or greater than 16
+ * then we can say that its an uncorrectable ECC error.
+ */
+#define MULTI_BIT_ERR_CNT 16
+
+struct anfc_op {
+	u32 cmds[4];
+	u32 len;
+	u32 col;
+	u32 row;
+	unsigned int data_instr_idx;
+	const struct nand_op_instr *data_instr;
+};
+
+/**
+ * struct anfc_nand_chip - Defines the nand chip related information
+ * @node:		Used to store NAND chips into a list.
+ * @chip:		NAND chip information structure.
+ * @strength:		Bch or Hamming mode enable/disable.
+ * @ecc_strength:	Ecc strength 4.8/12/16.
+ * @eccval:		Ecc config value.
+ * @raddr_cycles:	Row address cycle information.
+ * @caddr_cycles:	Column address cycle information.
+ * @pktsize:		Packet size for read / write operation.
+ * @csnum:		chipselect number to be used.
+ * @spktsize:		Packet size in ddr mode for status operation.
+ * @inftimeval:		Data interface and timing mode information
+ */
+struct anfc_nand_chip {
+	struct list_head node;
+	struct nand_chip chip;
+	bool strength;
+	u32 ecc_strength;
+	u32 eccval;
+	u16 raddr_cycles;
+	u16 caddr_cycles;
+	u32 pktsize;
+	int csnum;
+	u32 spktsize;
+	u32 inftimeval;
+};
+
+/**
+ * struct anfc_nand_controller - Defines the Arasan NAND flash controller
+ *				 driver instance
+ * @controller:		base controller structure.
+ * @chips:		list of all nand chips attached to the ctrler.
+ * @dev:		Pointer to the device structure.
+ * @base:		Virtual address of the NAND flash device.
+ * @curr_cmd:		Current command issued.
+ * @clk_sys:		Pointer to the system clock.
+ * @clk_flash:		Pointer to the flash clock.
+ * @dma:		Dma enable/disable.
+ * @buf:		Buffer used for read/write byte operations.
+ * @irq:		irq number
+ * @bufshift:		Variable used for indexing buffer operation
+ * @csnum:		Chip select number currently inuse.
+ * @event:		Completion event for nand status events.
+ * @status:		Status of the flash device.
+ * @prog:		Used to initiate controller operations.
+ * @chip_active:	Used to check the chip select state, active or not.
+ */
+struct anfc_nand_controller {
+	struct nand_controller controller;
+	struct list_head chips;
+	struct device *dev;
+	void __iomem *base;
+	int curr_cmd;
+	struct clk *clk_sys;
+	struct clk *clk_flash;
+	int irq;
+	int csnum;
+	struct completion event;
+	int status;
+	u32 prog;
+	u8 buf[TEMP_BUF_SIZE];
+	bool chip_active;
+};
+
+static int anfc_ooblayout_ecc(struct mtd_info *mtd, int section,
+			      struct mtd_oob_region *oobregion)
+{
+	struct nand_chip *nand = mtd_to_nand(mtd);
+
+	if (section >= nand->ecc.steps)
+		return -ERANGE;
+
+	if (section)
+		return -ERANGE;
+
+	oobregion->length = nand->ecc.total;
+	oobregion->offset = mtd->oobsize - oobregion->length;
+
+	return 0;
+}
+
+static int anfc_ooblayout_free(struct mtd_info *mtd, int section,
+			       struct mtd_oob_region *oobregion)
+{
+	struct nand_chip *nand = mtd_to_nand(mtd);
+
+	if (section >= nand->ecc.steps)
+		return -ERANGE;
+
+	if (section)
+		return -ERANGE;
+
+	oobregion->offset = 2;
+	oobregion->length = mtd->oobsize - nand->ecc.total - 2;
+
+	return 0;
+}
+
+static const struct mtd_ooblayout_ops anfc_ooblayout_ops = {
+	.ecc = anfc_ooblayout_ecc,
+	.free = anfc_ooblayout_free,
+};
+
+/* Generic flash bbt decriptors */
+static u8 bbt_pattern[] = { 'B', 'b', 't', '0' };
+static u8 mirror_pattern[] = { '1', 't', 'b', 'B' };
+
+static struct nand_bbt_descr bbt_main_descr = {
+	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP |
+		NAND_BBM_SECONDPAGE,
+	.offs = 4,
+	.len = 4,
+	.veroffs = 20,
+	.maxblocks = 4,
+	.pattern = bbt_pattern
+};
+
+static struct nand_bbt_descr bbt_mirror_descr = {
+	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP |
+		NAND_BBM_SECONDPAGE,
+	.offs = 4,
+	.len = 4,
+	.veroffs = 20,
+	.maxblocks = 4,
+	.pattern = mirror_pattern
+};
+
+static inline struct anfc_nand_chip *to_anfc_nand(struct nand_chip *nand)
+{
+	return container_of(nand, struct anfc_nand_chip, chip);
+}
+
+static inline struct anfc_nand_controller *to_anfc(struct nand_controller *ctrl)
+{
+	return container_of(ctrl, struct anfc_nand_controller, controller);
+}
+
+static u8 anfc_page(u32 pagesize)
+{
+	switch (pagesize) {
+	case 512:
+		return REG_PAGE_SIZE_512;
+	case 1024:
+		return REG_PAGE_SIZE_1K;
+	case 2048:
+		return REG_PAGE_SIZE_2K;
+	case 4096:
+		return REG_PAGE_SIZE_4K;
+	case 8192:
+		return REG_PAGE_SIZE_8K;
+	case 16384:
+		return REG_PAGE_SIZE_16K;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static inline void anfc_enable_intrs(struct anfc_nand_controller *nfc, u32 val)
+{
+	writel(val, nfc->base + INTR_STS_EN_OFST);
+	writel(val, nfc->base + INTR_SIG_EN_OFST);
+}
+
+static inline void anfc_config_ecc(struct anfc_nand_controller *nfc, bool on)
+{
+	u32 val;
+
+	val = readl(nfc->base + CMD_OFST);
+	if (on)
+		val |= ECC_ENABLE;
+	else
+		val &= ~ECC_ENABLE;
+	writel(val, nfc->base + CMD_OFST);
+}
+
+static inline void anfc_config_dma(struct anfc_nand_controller *nfc, int on)
+{
+	u32 val;
+
+	val = readl(nfc->base + CMD_OFST);
+	val &= ~DMA_EN_MASK;
+	if (on)
+		val |= DMA_ENABLE << DMA_EN_SHIFT;
+	writel(val, nfc->base + CMD_OFST);
+}
+
+static inline int anfc_wait_for_event(struct anfc_nand_controller *nfc)
+{
+	return wait_for_completion_timeout(&nfc->event,
+					msecs_to_jiffies(EVENT_TIMEOUT_MSEC));
+}
+
+static inline void anfc_setpktszcnt(struct anfc_nand_controller *nfc,
+				    u32 pktsize, u32 pktcount)
+{
+	writel(pktsize | (pktcount << PKT_CNT_SHIFT), nfc->base + PKT_OFST);
+}
+
+static inline void anfc_set_eccsparecmd(struct anfc_nand_controller *nfc,
+					struct anfc_nand_chip *achip, u8 cmd1,
+					u8 cmd2)
+{
+	writel(cmd1 | (cmd2 << CMD2_SHIFT) |
+	       (achip->caddr_cycles << ADDR_CYCLES_SHIFT),
+	       nfc->base + ECC_SPR_CMD_OFST);
+}
+
+static void anfc_setpagecoladdr(struct anfc_nand_controller *nfc, u32 page,
+				u16 col)
+{
+	u32 val;
+
+	writel(col | (page << PG_ADDR_SHIFT), nfc->base + MEM_ADDR1_OFST);
+
+	val = readl(nfc->base + MEM_ADDR2_OFST);
+	val = (val & ~MEM_ADDR_MASK) |
+	      ((page >> PG_ADDR_SHIFT) & MEM_ADDR_MASK);
+	writel(val, nfc->base + MEM_ADDR2_OFST);
+}
+
+static void anfc_prepare_cmd(struct nand_chip *chip, u8 cmd1,
+			     u8 cmd2, u8 dmamode,
+			     u32 pagesize, u8 addrcycles)
+{
+	u32 regval;
+	struct anfc_nand_controller *nfc = to_anfc(chip->controller);
+
+	regval = cmd1 | (cmd2 << CMD2_SHIFT);
+	if (dmamode)
+		regval |= DMA_ENABLE << DMA_EN_SHIFT;
+	regval |= addrcycles << ADDR_CYCLES_SHIFT;
+	regval |= anfc_page(pagesize) << REG_PAGE_SIZE_SHIFT;
+	writel(regval, nfc->base + CMD_OFST);
+}
+
+static void anfc_rw_dma_op(struct mtd_info *mtd, u8 *buf, int len,
+			   bool do_read, u32 prog, int pktcount, int pktsize)
+{
+	dma_addr_t paddr;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct anfc_nand_controller *nfc = to_anfc(chip->controller);
+	struct anfc_nand_chip *achip = to_anfc_nand(chip);
+	u32 eccintr = 0, dir;
+
+	if (pktsize == 0)
+		pktsize = len;
+
+	anfc_setpktszcnt(nfc, pktsize, pktcount);
+
+	if (!achip->strength)
+		eccintr = MBIT_ERROR;
+
+	if (do_read)
+		dir = DMA_FROM_DEVICE;
+	else
+		dir = DMA_TO_DEVICE;
+	paddr = dma_map_single(nfc->dev, buf, len, dir);
+	if (dma_mapping_error(nfc->dev, paddr)) {
+		dev_err(nfc->dev, "Read buffer mapping error");
+		return;
+	}
+	writel(paddr, nfc->base + DMA_ADDR0_OFST);
+	writel((paddr >> 32), nfc->base + DMA_ADDR1_OFST);
+	anfc_enable_intrs(nfc, (XFER_COMPLETE | eccintr));
+	writel(prog, nfc->base + PROG_OFST);
+	anfc_wait_for_event(nfc);
+	dma_unmap_single(nfc->dev, paddr, len, dir);
+}
+
+static void anfc_rw_pio_op(struct mtd_info *mtd, u8 *buf, int len,
+			   bool do_read, int prog, int pktcount, int pktsize)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct anfc_nand_controller *nfc = to_anfc(chip->controller);
+	struct anfc_nand_chip *achip = to_anfc_nand(chip);
+	u32 *bufptr = (u32 *)buf;
+	u32 cnt = 0, intr = 0;
+
+	anfc_config_dma(nfc, 0);
+
+	if (pktsize == 0)
+		pktsize = len;
+
+	anfc_setpktszcnt(nfc, pktsize, pktcount);
+
+	if (!achip->strength)
+		intr = MBIT_ERROR;
+
+	if (do_read)
+		intr |= READ_READY;
+	else
+		intr |= WRITE_READY;
+	anfc_enable_intrs(nfc, intr);
+	writel(prog, nfc->base + PROG_OFST);
+	while (cnt < pktcount) {
+		anfc_wait_for_event(nfc);
+		cnt++;
+		if (cnt == pktcount)
+			anfc_enable_intrs(nfc, XFER_COMPLETE);
+		if (do_read)
+			ioread32_rep(nfc->base + DATA_PORT_OFST, bufptr,
+				     pktsize / 4);
+		else
+			iowrite32_rep(nfc->base + DATA_PORT_OFST, bufptr,
+				      pktsize / 4);
+		bufptr += (pktsize / 4);
+		if (cnt < pktcount)
+			anfc_enable_intrs(nfc, intr);
+	}
+	anfc_wait_for_event(nfc);
+}
+
+static void anfc_read_data_op(struct nand_chip *chip, u8 *buf, int len,
+			      int pktcount, int pktsize)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+
+	if (virt_addr_valid(buf))
+		anfc_rw_dma_op(mtd, buf, len, 1, PROG_PGRD, pktcount, pktsize);
+	else
+		anfc_rw_pio_op(mtd, buf, len, 1, PROG_PGRD, pktcount, pktsize);
+}
+
+static void anfc_write_data_op(struct nand_chip *chip, const u8 *buf,
+			       int len, int pktcount, int pktsize)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+
+	if (virt_addr_valid(buf))
+		anfc_rw_dma_op(mtd, (char *)buf, len, 0, PROG_PGPROG, pktcount,
+			       pktsize);
+	else
+		anfc_rw_pio_op(mtd, (char *)buf, len, 0, PROG_PGPROG, pktcount,
+			       pktsize);
+}
+
+static int anfc_read_page(struct nand_chip *chip, uint8_t *buf,
+			  int oob_required, int page)
+{
+	u32 ret;
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct anfc_nand_chip *achip = to_anfc_nand(chip);
+
+	ret = nand_read_page_op(chip, page, 0, NULL, 0);
+	if (ret)
+		return ret;
+
+	anfc_read_data_op(chip, buf, mtd->writesize,
+			  DIV_ROUND_UP(mtd->writesize, achip->pktsize),
+			  achip->pktsize);
+	if (oob_required)
+		chip->ecc.read_oob(chip, page);
+
+	return 0;
+}
+
+static int anfc_write_page(struct nand_chip *chip, const uint8_t *buf,
+			   int oob_required, int page)
+{
+	u32 ret;
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct anfc_nand_chip *achip = to_anfc_nand(chip);
+
+	ret = nand_prog_page_begin_op(chip, page, 0, NULL, 0);
+	if (ret)
+		return ret;
+
+	anfc_write_data_op(chip, buf, mtd->writesize,
+			   DIV_ROUND_UP(mtd->writesize, achip->pktsize),
+			   achip->pktsize);
+
+	if (oob_required)
+		chip->ecc.write_oob(chip, page);
+
+	return 0;
+}
+
+static int anfc_read_page_hwecc(struct nand_chip *chip, u8 *buf,
+				int oob_required, int page)
+{
+	struct anfc_nand_controller *nfc = to_anfc(chip->controller);
+	struct anfc_nand_chip *achip = to_anfc_nand(chip);
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	u8 *ecc_code = chip->ecc.code_buf;
+	u8 *p;
+	int eccsize = chip->ecc.size;
+	int eccbytes = chip->ecc.bytes;
+	int stat = 0, i;
+	u32 ret;
+	unsigned int max_bitflips = 0;
+	u32 eccsteps = chip->ecc.steps;
+	u32 one_bit_err = 0, multi_bit_err = 0;
+
+	ret = nand_read_page_op(chip, page, 0, NULL, 0);
+	if (ret)
+		return ret;
+	anfc_set_eccsparecmd(nfc, achip, NAND_CMD_RNDOUT, NAND_CMD_RNDOUTSTART);
+	anfc_config_ecc(nfc, true);
+	anfc_read_data_op(chip, buf, mtd->writesize,
+			  DIV_ROUND_UP(mtd->writesize, achip->pktsize),
+			  achip->pktsize);
+
+	if (achip->strength) {
+		/*
+		 * In BCH mode Arasan NAND controller can correct ECC upto
+		 * 24-bit Beyond that, it can't even detect errors.
+		 */
+		multi_bit_err = readl(nfc->base + ECC_ERR_CNT_OFST);
+		multi_bit_err = ((multi_bit_err & PAGE_ERR_CNT_MASK) >> 8);
+	} else {
+		/*
+		 * In Hamming mode Arasan NAND controller can correct ECC upto
+		 * 1-bit and can detect upto 2-bit errors.
+		 */
+		one_bit_err = readl(nfc->base + ECC_ERR_CNT_1BIT_OFST);
+		multi_bit_err = readl(nfc->base + ECC_ERR_CNT_2BIT_OFST);
+		/* Clear ecc error count register 1Bit, 2Bit */
+		writel(0x0, nfc->base + ECC_ERR_CNT_1BIT_OFST);
+		writel(0x0, nfc->base + ECC_ERR_CNT_2BIT_OFST);
+	}
+
+	anfc_config_ecc(nfc, false);
+	if (oob_required)
+		chip->ecc.read_oob(chip, page);
+
+	if (multi_bit_err || one_bit_err) {
+		if (!oob_required)
+			chip->ecc.read_oob(chip, page);
+
+		mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0,
+					   chip->ecc.total);
+		eccsteps = chip->ecc.steps;
+		p = buf;
+		for (i = 0; eccsteps; eccsteps--, i += eccbytes,
+		     p += eccsize) {
+			stat = nand_check_erased_ecc_chunk(p,
+							   chip->ecc.size,
+							   &ecc_code[i],
+							   eccbytes,
+							   NULL, 0,
+							   chip->ecc.strength);
+			if (stat < 0) {
+				stat = 0;
+			} else {
+				mtd->ecc_stats.corrected += stat;
+				max_bitflips = max_t(unsigned int, max_bitflips,
+						     stat);
+			}
+		}
+	}
+
+	return max_bitflips;
+}
+
+static int anfc_write_page_hwecc(struct nand_chip *chip, const u8 *buf,
+				 int oob_required, int page)
+{
+	int ret;
+	struct anfc_nand_controller *nfc = to_anfc(chip->controller);
+	struct anfc_nand_chip *achip = to_anfc_nand(chip);
+	struct mtd_info *mtd = nand_to_mtd(chip);
+
+	ret = nand_prog_page_begin_op(chip, page, 0, NULL, 0);
+	if (ret)
+		return ret;
+
+	anfc_set_eccsparecmd(nfc, achip, NAND_CMD_RNDIN, 0);
+	anfc_config_ecc(nfc, true);
+	anfc_write_data_op(chip, buf, mtd->writesize,
+			   DIV_ROUND_UP(mtd->writesize, achip->pktsize),
+			   achip->pktsize);
+
+	if (oob_required)
+		chip->ecc.write_oob(chip, page);
+
+	anfc_config_ecc(nfc, false);
+
+	return 0;
+}
+
+static int anfc_ecc_init(struct mtd_info *mtd,
+			 struct nand_ecc_ctrl *ecc, int ecc_mode)
+{
+	u32 ecc_addr;
+	unsigned int ecc_strength, steps;
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct anfc_nand_chip *achip = to_anfc_nand(chip);
+	struct anfc_nand_controller *nfc = to_anfc(chip->controller);
+
+	if (ecc_mode == NAND_ECC_ON_DIE) {
+		anfc_config_ecc(nfc, 0);
+		ecc->strength = 1;
+		ecc->bytes = 0;
+		ecc->size = mtd->writesize;
+		ecc->read_page = anfc_read_page;
+		ecc->write_page = anfc_write_page;
+		chip->bbt_td = &bbt_main_descr;
+		chip->bbt_md = &bbt_mirror_descr;
+	} else {
+		ecc->mode = NAND_ECC_HW;
+		ecc->read_page = anfc_read_page_hwecc;
+		ecc->write_page = anfc_write_page_hwecc;
+
+		mtd_set_ooblayout(mtd, &anfc_ooblayout_ops);
+		steps = mtd->writesize / chip->base.eccreq.step_size;
+
+		switch (chip->base.eccreq.strength) {
+		case 12:
+			ecc_strength = 0x1;
+			break;
+		case 8:
+			ecc_strength = 0x2;
+			break;
+		case 4:
+			ecc_strength = 0x3;
+			break;
+		case 24:
+			ecc_strength = 0x4;
+			break;
+		default:
+			ecc_strength = 0x0;
+		}
+		if (!ecc_strength)
+			ecc->total = 3 * steps;
+		else
+			ecc->total =
+			     DIV_ROUND_UP(fls(8 * chip->base.eccreq.step_size) *
+				 chip->base.eccreq.strength * steps, 8);
+		ecc->strength = chip->base.eccreq.strength;
+		ecc->size = chip->base.eccreq.step_size;
+		ecc->bytes = ecc->total / steps;
+		ecc->steps = steps;
+		achip->ecc_strength = ecc_strength;
+		achip->strength = achip->ecc_strength;
+		ecc_addr = mtd->writesize + (mtd->oobsize - ecc->total);
+		achip->eccval = ecc_addr | (ecc->total << ECC_SIZE_SHIFT) |
+				(achip->strength << BCH_EN_SHIFT);
+	}
+
+	if (chip->base.eccreq.step_size >= 1024)
+		achip->pktsize = 1024;
+	else
+		achip->pktsize = 512;
+
+	return 0;
+}
+
+/* NAND framework ->exec_op() hooks and related helpers */
+static void anfc_parse_instructions(struct nand_chip *chip,
+				    const struct nand_subop *subop,
+				    struct anfc_op *nfc_op)
+{
+	const struct nand_op_instr *instr = NULL;
+	struct anfc_nand_controller *nfc = to_anfc(chip->controller);
+	unsigned int op_id;
+	int i = 0;
+
+	memset(nfc_op, 0, sizeof(struct anfc_op));
+	for (op_id = 0; op_id < subop->ninstrs; op_id++) {
+		unsigned int naddrs;
+
+		instr = &subop->instrs[op_id];
+		switch (instr->type) {
+		case NAND_OP_CMD_INSTR:
+			if (op_id)
+				nfc_op->cmds[1] = instr->ctx.cmd.opcode;
+			else
+				nfc_op->cmds[0] = instr->ctx.cmd.opcode;
+			nfc->curr_cmd = nfc_op->cmds[0];
+			break;
+
+		case NAND_OP_ADDR_INSTR:
+			i = nand_subop_get_addr_start_off(subop, op_id);
+			naddrs = nand_subop_get_num_addr_cyc(subop,
+							     op_id);
+
+			for (; i < naddrs; i++) {
+				u8 val = instr->ctx.addr.addrs[i];
+
+				if (nfc_op->cmds[0] == NAND_CMD_ERASE1) {
+					nfc_op->row |= COL_ROW_ADDR(i, val);
+				} else {
+					if (i < 2)
+						nfc_op->col |= COL_ROW_ADDR(i,
+									val);
+					else
+						nfc_op->row |= COL_ROW_ADDR(i -
+									2, val);
+				}
+			}
+			break;
+		case NAND_OP_DATA_IN_INSTR:
+			nfc_op->data_instr = instr;
+			nfc_op->data_instr_idx = op_id;
+			break;
+		case NAND_OP_DATA_OUT_INSTR:
+			nfc_op->data_instr = instr;
+			nfc_op->data_instr_idx = op_id;
+			break;
+		case NAND_OP_WAITRDY_INSTR:
+			break;
+		}
+	}
+}
+
+static int anfc_reset_cmd_type_exec(struct nand_chip *chip,
+				    const struct nand_subop *subop)
+{
+	struct anfc_op nfc_op = {};
+	struct anfc_nand_controller *nfc = to_anfc(chip->controller);
+
+	anfc_parse_instructions(chip, subop, &nfc_op);
+
+	/*
+	 * Do not execute commands other than NAND_CMD_RESET
+	 * Other commands have their own patterns
+	 * If there is no pattern match, that means controller
+	 * is not supporting that pattern.
+	 */
+	if (nfc_op.cmds[0] != NAND_CMD_RESET)
+		return 0;
+
+	anfc_prepare_cmd(chip, nfc_op.cmds[0], 0, 0, 0, 0);
+	nfc->prog = PROG_RST;
+	anfc_enable_intrs(nfc, XFER_COMPLETE);
+	writel(nfc->prog, nfc->base + PROG_OFST);
+	anfc_wait_for_event(nfc);
+
+	return 0;
+}
+
+static int anfc_read_id_type_exec(struct nand_chip *chip,
+				  const struct nand_subop *subop)
+{
+	const struct nand_op_instr *instr;
+	struct anfc_op nfc_op = {};
+	unsigned int op_id, len;
+	struct anfc_nand_controller *nfc = to_anfc(chip->controller);
+	struct mtd_info *mtd = nand_to_mtd(chip);
+
+	anfc_parse_instructions(chip, subop, &nfc_op);
+	instr = nfc_op.data_instr;
+	op_id = nfc_op.data_instr_idx;
+	len = nand_subop_get_data_len(subop, op_id);
+	anfc_prepare_cmd(chip, nfc_op.cmds[0], 0, 0, 0, 1);
+	anfc_setpagecoladdr(nfc, nfc_op.row, nfc_op.col);
+	nfc->prog = PROG_RDID;
+	anfc_rw_pio_op(mtd, nfc->buf, roundup(len, 4), 1, PROG_RDID, 1, 0);
+	memcpy(instr->ctx.data.buf.in, nfc->buf, len);
+
+	return 0;
+}
+
+static int anfc_read_status_exec(struct nand_chip *chip,
+				 const struct nand_subop *subop)
+{
+	const struct nand_op_instr *instr;
+	struct anfc_op nfc_op = {};
+	unsigned int op_id, len;
+	struct anfc_nand_chip *achip = to_anfc_nand(chip);
+	struct anfc_nand_controller *nfc = to_anfc(chip->controller);
+
+	anfc_parse_instructions(chip, subop, &nfc_op);
+	instr = nfc_op.data_instr;
+	op_id = nfc_op.data_instr_idx;
+
+	anfc_prepare_cmd(chip, nfc_op.cmds[0], 0, 0, 0, 0);
+	anfc_setpktszcnt(nfc, achip->spktsize / 4, 1);
+	anfc_setpagecoladdr(nfc, nfc_op.row, nfc_op.col);
+	nfc->prog = PROG_STATUS;
+
+	anfc_enable_intrs(nfc, XFER_COMPLETE);
+	writel(nfc->prog, nfc->base + PROG_OFST);
+	anfc_wait_for_event(nfc);
+
+	if (!nfc_op.data_instr)
+		return 0;
+
+	len = nand_subop_get_data_len(subop, op_id);
+
+	/*
+	 * The Arasan NAND controller will update the status value
+	 * returned by the flash device in FLASH_STS register.
+	 */
+	nfc->status = readl(nfc->base + FLASH_STS_OFST);
+	memcpy(instr->ctx.data.buf.in, &nfc->status, len);
+
+	return 0;
+}
+
+static int anfc_erase_zerolenpg_read_type_exec(struct nand_chip *chip,
+					       const struct nand_subop *subop)
+{
+	const struct nand_op_instr *instr;
+	struct anfc_nand_chip *achip = to_anfc_nand(chip);
+	struct anfc_nand_controller *nfc = to_anfc(chip->controller);
+	struct anfc_op nfc_op = {};
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	u32 dma_mode = 0, write_size = 0, addrcycles = 0, len, op_id;
+
+	anfc_parse_instructions(chip, subop, &nfc_op);
+	instr = nfc_op.data_instr;
+	op_id = nfc_op.data_instr_idx;
+
+	if (nfc_op.cmds[0] == NAND_CMD_ERASE1) {
+		nfc->prog = PROG_ERASE;
+		addrcycles = achip->raddr_cycles;
+		nfc_op.col = nfc_op.row & 0xffff;
+		nfc_op.row = (nfc_op.row >> PG_ADDR_SHIFT) & 0xffff;
+	} else if (nfc_op.cmds[0] == NAND_CMD_READ0) {
+		nfc->prog = PROG_PGRD;
+		addrcycles = achip->raddr_cycles + achip->caddr_cycles;
+		write_size = mtd->writesize;
+		dma_mode = 1;
+	}
+
+	anfc_prepare_cmd(chip, nfc_op.cmds[0], nfc_op.cmds[1], dma_mode,
+			 write_size, addrcycles);
+	anfc_setpagecoladdr(nfc, nfc_op.row, nfc_op.col);
+
+	if (nfc_op.cmds[0] == NAND_CMD_ERASE1) {
+		anfc_enable_intrs(nfc, XFER_COMPLETE);
+		writel(nfc->prog, nfc->base + PROG_OFST);
+		anfc_wait_for_event(nfc);
+	}
+
+	if (!nfc_op.data_instr)
+		return 0;
+
+	len = nand_subop_get_data_len(subop, op_id);
+	anfc_read_data_op(chip, instr->ctx.data.buf.in, len, 1, 0);
+
+	return 0;
+}
+
+static int anfc_read_param_get_feature_sp_read_type_exec(struct nand_chip *chip,
+							 const struct nand_subop
+							 *subop)
+{
+	const struct nand_op_instr *instr;
+	struct anfc_nand_controller *nfc = to_anfc(chip->controller);
+	unsigned int op_id, len;
+	struct anfc_op nfc_op = {};
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct anfc_nand_chip *achip = to_anfc_nand(chip);
+	u32 dma_mode = 0, addrcycles = 1, write_size = 0;
+
+	anfc_parse_instructions(chip, subop, &nfc_op);
+	instr = nfc_op.data_instr;
+	op_id = nfc_op.data_instr_idx;
+
+	if (nfc_op.cmds[0] == NAND_CMD_PARAM) {
+		nfc->prog = PROG_RDPARAM;
+	} else if (nfc_op.cmds[0] == NAND_CMD_GET_FEATURES) {
+		nfc->prog = PROG_GET_FEATURE;
+	} else if (nfc_op.cmds[0] == NAND_CMD_READ0) {
+		nfc->prog = PROG_PGRD;
+		addrcycles = achip->raddr_cycles + achip->caddr_cycles;
+		write_size = mtd->writesize;
+		dma_mode = 1;
+	}
+
+	anfc_prepare_cmd(chip, nfc_op.cmds[0], 0, dma_mode, write_size,
+			 addrcycles);
+	anfc_setpagecoladdr(nfc, nfc_op.row, nfc_op.col);
+
+	if (!nfc_op.data_instr)
+		return 0;
+
+	len = nand_subop_get_data_len(subop, op_id);
+	anfc_rw_pio_op(mtd, nfc->buf, roundup(len, 4), 1, nfc->prog, 1, 0);
+	memcpy(instr->ctx.data.buf.in,  nfc->buf, len);
+
+	return 0;
+}
+
+static int anfc_random_datain_type_exec(struct nand_chip *chip,
+					const struct nand_subop *subop)
+{
+	const struct nand_op_instr *instr;
+	struct anfc_nand_controller *nfc = to_anfc(chip->controller);
+	unsigned int op_id, len;
+	struct anfc_op nfc_op = {};
+	struct mtd_info *mtd = nand_to_mtd(chip);
+
+	anfc_parse_instructions(chip, subop, &nfc_op);
+	instr = nfc_op.data_instr;
+	op_id = nfc_op.data_instr_idx;
+
+	len = nand_subop_get_data_len(subop, op_id);
+	anfc_rw_pio_op(mtd, nfc->buf, roundup(len, 4), 1, PROG_PGRD, 1, 0);
+	memcpy(instr->ctx.data.buf.in,  nfc->buf, len);
+
+	return 0;
+}
+
+static int anfc_setfeature_type_exec(struct nand_chip *chip,
+				     const struct nand_subop *subop)
+{
+	const struct nand_op_instr *instr;
+	struct anfc_nand_controller *nfc = to_anfc(chip->controller);
+	unsigned int op_id, len;
+	struct anfc_op nfc_op = {};
+
+	anfc_parse_instructions(chip, subop, &nfc_op);
+	nfc->prog = PROG_SET_FEATURE;
+	instr = nfc_op.data_instr;
+	op_id = nfc_op.data_instr_idx;
+	anfc_prepare_cmd(chip, nfc_op.cmds[0], 0, 0, 0, 1);
+	anfc_setpagecoladdr(nfc, nfc_op.row, nfc_op.col);
+
+	if (!nfc_op.data_instr)
+		return 0;
+
+	len = nand_subop_get_data_len(subop, op_id);
+	anfc_write_data_op(chip, (char *)instr->ctx.data.buf.out, len, 1, 0);
+
+	return 0;
+}
+
+static int anfc_change_read_column_type_exec(struct nand_chip *chip,
+					     const struct nand_subop *subop)
+{
+	const struct nand_op_instr *instr;
+	struct anfc_nand_controller *nfc = to_anfc(chip->controller);
+	unsigned int op_id, len;
+	struct anfc_op nfc_op = {};
+	struct mtd_info *mtd = nand_to_mtd(chip);
+
+	anfc_parse_instructions(chip, subop, &nfc_op);
+	nfc->prog = PROG_PGRD;
+	instr = nfc_op.data_instr;
+	op_id = nfc_op.data_instr_idx;
+
+	anfc_prepare_cmd(chip, nfc_op.cmds[0], nfc_op.cmds[1], 1,
+			 mtd->writesize, 2);
+	anfc_setpagecoladdr(nfc, nfc_op.row, nfc_op.col);
+
+	if (!nfc_op.data_instr)
+		return 0;
+
+	len = nand_subop_get_data_len(subop, op_id);
+	anfc_rw_pio_op(mtd, nfc->buf, roundup(len, 4), 1, nfc->prog, 1, 0);
+	memcpy(instr->ctx.data.buf.in, nfc->buf, len);
+
+	return 0;
+}
+
+static int anfc_page_read_type_exec(struct nand_chip *chip,
+				    const struct nand_subop *subop)
+{
+	const struct nand_op_instr *instr;
+	struct anfc_nand_chip *achip = to_anfc_nand(chip);
+	struct anfc_nand_controller *nfc = to_anfc(chip->controller);
+	unsigned int op_id, len;
+	struct anfc_op nfc_op = {};
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	u32 addrcycles;
+
+	anfc_parse_instructions(chip, subop, &nfc_op);
+	nfc->prog = PROG_PGRD;
+	instr = nfc_op.data_instr;
+	op_id = nfc_op.data_instr_idx;
+
+	addrcycles = achip->raddr_cycles + achip->caddr_cycles;
+
+	anfc_prepare_cmd(chip, nfc_op.cmds[0], nfc_op.cmds[1], 1,
+			 mtd->writesize, addrcycles);
+	anfc_setpagecoladdr(nfc, nfc_op.row, nfc_op.col);
+
+	if (!nfc_op.data_instr)
+		return 0;
+
+	len = nand_subop_get_data_len(subop, op_id);
+
+	anfc_rw_pio_op(mtd, nfc->buf, roundup(len, 4), 1, nfc->prog, 1, 0);
+	memcpy(instr->ctx.data.buf.in, nfc->buf, len);
+
+	return 0;
+}
+
+static int anfc_zero_len_page_write_type_exec(struct nand_chip *chip,
+					      const struct nand_subop *subop)
+{
+	struct anfc_nand_chip *achip = to_anfc_nand(chip);
+	struct anfc_nand_controller *nfc = to_anfc(chip->controller);
+	struct anfc_op nfc_op = {};
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	u32 addrcycles;
+
+	anfc_parse_instructions(chip, subop, &nfc_op);
+	nfc->prog = PROG_PGRD;
+	addrcycles = achip->raddr_cycles + achip->caddr_cycles;
+
+	anfc_prepare_cmd(chip, nfc_op.cmds[0], NAND_CMD_PAGEPROG, 1,
+			 mtd->writesize, addrcycles);
+	anfc_setpagecoladdr(nfc, nfc_op.row, nfc_op.col);
+
+	return 0;
+}
+
+static int anfc_page_write_type_exec(struct nand_chip *chip,
+				     const struct nand_subop *subop)
+{
+	const struct nand_op_instr *instr;
+	struct anfc_nand_chip *achip = to_anfc_nand(chip);
+	struct anfc_nand_controller *nfc = to_anfc(chip->controller);
+	unsigned int op_id, len;
+	struct anfc_op nfc_op = {};
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	u32 addrcycles;
+
+	anfc_parse_instructions(chip, subop, &nfc_op);
+	instr = nfc_op.data_instr;
+	op_id = nfc_op.data_instr_idx;
+	nfc->prog = PROG_PGPROG;
+
+	addrcycles = achip->raddr_cycles + achip->caddr_cycles;
+	anfc_prepare_cmd(chip, nfc_op.cmds[0], nfc_op.cmds[1], 1,
+			 mtd->writesize, addrcycles);
+	anfc_setpagecoladdr(nfc, nfc_op.row, nfc_op.col);
+	if (!nfc_op.data_instr)
+		return 0;
+
+	len = nand_subop_get_data_len(subop, op_id);
+	anfc_write_data_op(chip, (char *)instr->ctx.data.buf.out, len, 1, 0);
+
+	return 0;
+}
+
+static int anfc_page_write_nowait_type_exec(struct nand_chip *chip,
+					    const struct nand_subop *subop)
+{
+	const struct nand_op_instr *instr;
+	struct anfc_nand_chip *achip = to_anfc_nand(chip);
+	struct anfc_nand_controller *nfc = to_anfc(chip->controller);
+	struct anfc_op nfc_op = {};
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	u32 addrcycles;
+
+	anfc_parse_instructions(chip, subop, &nfc_op);
+	instr = nfc_op.data_instr;
+	nfc->prog = PROG_PGPROG;
+
+	addrcycles = achip->raddr_cycles + achip->caddr_cycles;
+	anfc_prepare_cmd(chip, nfc_op.cmds[0], NAND_CMD_PAGEPROG, 1,
+			 mtd->writesize, addrcycles);
+	anfc_setpagecoladdr(nfc, nfc_op.row, nfc_op.col);
+
+	if (!nfc_op.data_instr)
+		return 0;
+
+	anfc_write_data_op(chip, (char *)instr->ctx.data.buf.out,
+			   mtd->writesize, DIV_ROUND_UP(mtd->writesize,
+			   achip->pktsize), achip->pktsize);
+
+	return 0;
+}
+
+static const struct nand_op_parser anfc_op_parser = NAND_OP_PARSER(
+	/* Use a separate function for each pattern */
+	NAND_OP_PARSER_PATTERN(
+		anfc_random_datain_type_exec,
+		NAND_OP_PARSER_PAT_DATA_IN_ELEM(false, ANFC_MAX_CHUNK_SIZE)),
+	NAND_OP_PARSER_PATTERN(
+		anfc_change_read_column_type_exec,
+		NAND_OP_PARSER_PAT_CMD_ELEM(false),
+		NAND_OP_PARSER_PAT_ADDR_ELEM(false, ANFC_MAX_ADDR_CYCLES),
+		NAND_OP_PARSER_PAT_CMD_ELEM(false),
+		NAND_OP_PARSER_PAT_DATA_IN_ELEM(false, ANFC_MAX_CHUNK_SIZE)),
+	NAND_OP_PARSER_PATTERN(
+		anfc_page_read_type_exec,
+		NAND_OP_PARSER_PAT_CMD_ELEM(false),
+		NAND_OP_PARSER_PAT_ADDR_ELEM(false, ANFC_MAX_ADDR_CYCLES),
+		NAND_OP_PARSER_PAT_CMD_ELEM(false),
+		NAND_OP_PARSER_PAT_WAITRDY_ELEM(false),
+		NAND_OP_PARSER_PAT_DATA_IN_ELEM(false, ANFC_MAX_CHUNK_SIZE)),
+	NAND_OP_PARSER_PATTERN(
+		anfc_page_write_type_exec,
+		NAND_OP_PARSER_PAT_CMD_ELEM(false),
+		NAND_OP_PARSER_PAT_ADDR_ELEM(false, ANFC_MAX_ADDR_CYCLES),
+		NAND_OP_PARSER_PAT_DATA_OUT_ELEM(false, ANFC_MAX_CHUNK_SIZE),
+		NAND_OP_PARSER_PAT_CMD_ELEM(false),
+		NAND_OP_PARSER_PAT_WAITRDY_ELEM(true)),
+	NAND_OP_PARSER_PATTERN(
+		anfc_read_id_type_exec,
+		NAND_OP_PARSER_PAT_CMD_ELEM(false),
+		NAND_OP_PARSER_PAT_ADDR_ELEM(false, ANFC_MAX_ADDR_CYCLES),
+		NAND_OP_PARSER_PAT_DATA_IN_ELEM(false, ANFC_MAX_CHUNK_SIZE)),
+	NAND_OP_PARSER_PATTERN(
+		anfc_erase_zerolenpg_read_type_exec,
+		NAND_OP_PARSER_PAT_CMD_ELEM(false),
+		NAND_OP_PARSER_PAT_ADDR_ELEM(false, ANFC_MAX_ADDR_CYCLES),
+		NAND_OP_PARSER_PAT_CMD_ELEM(false),
+		NAND_OP_PARSER_PAT_WAITRDY_ELEM(false)),
+	NAND_OP_PARSER_PATTERN(
+		anfc_read_status_exec,
+		NAND_OP_PARSER_PAT_CMD_ELEM(false),
+		NAND_OP_PARSER_PAT_DATA_IN_ELEM(false, 1)),
+	NAND_OP_PARSER_PATTERN(
+		anfc_reset_cmd_type_exec,
+		NAND_OP_PARSER_PAT_CMD_ELEM(false),
+		NAND_OP_PARSER_PAT_WAITRDY_ELEM(false)),
+	NAND_OP_PARSER_PATTERN(
+		anfc_setfeature_type_exec,
+		NAND_OP_PARSER_PAT_CMD_ELEM(false),
+		NAND_OP_PARSER_PAT_ADDR_ELEM(false, ANFC_MAX_ADDR_CYCLES),
+		NAND_OP_PARSER_PAT_DATA_OUT_ELEM(false, ANFC_MAX_CHUNK_SIZE),
+		NAND_OP_PARSER_PAT_WAITRDY_ELEM(false)),
+	NAND_OP_PARSER_PATTERN(
+		anfc_page_write_nowait_type_exec,
+		NAND_OP_PARSER_PAT_CMD_ELEM(false),
+		NAND_OP_PARSER_PAT_ADDR_ELEM(false, ANFC_MAX_ADDR_CYCLES),
+		NAND_OP_PARSER_PAT_DATA_OUT_ELEM(false, ANFC_MAX_CHUNK_SIZE)),
+	NAND_OP_PARSER_PATTERN(
+		anfc_read_param_get_feature_sp_read_type_exec,
+		NAND_OP_PARSER_PAT_CMD_ELEM(false),
+		NAND_OP_PARSER_PAT_ADDR_ELEM(false, ANFC_MAX_ADDR_CYCLES),
+		NAND_OP_PARSER_PAT_WAITRDY_ELEM(false),
+		NAND_OP_PARSER_PAT_DATA_IN_ELEM(true, ANFC_MAX_CHUNK_SIZE)),
+	NAND_OP_PARSER_PATTERN(
+		anfc_zero_len_page_write_type_exec,
+		NAND_OP_PARSER_PAT_CMD_ELEM(false),
+		NAND_OP_PARSER_PAT_ADDR_ELEM(false, ANFC_MAX_ADDR_CYCLES)),
+	);
+
+static void anfc_select_chip(struct nand_chip *chip, int num)
+{
+	u32 val;
+	int ret;
+	struct anfc_nand_chip *achip = to_anfc_nand(chip);
+	struct anfc_nand_controller *nfc = to_anfc(chip->controller);
+
+	if (num < 0) {
+		nfc->chip_active = false;
+		pm_runtime_mark_last_busy(nfc->dev);
+		pm_runtime_put_autosuspend(nfc->dev);
+		return;
+	}
+
+	nfc->chip_active = true;
+	ret = pm_runtime_get_sync(nfc->dev);
+	if (ret < 0) {
+		dev_err(nfc->dev, "runtime_get_sync failed\n");
+		return;
+	}
+
+	val = readl(nfc->base + MEM_ADDR2_OFST);
+	val &= (val & ~(CS_MASK | BCH_MODE_MASK));
+	val |= (achip->csnum << CS_SHIFT) |
+	       (achip->ecc_strength << BCH_MODE_SHIFT);
+	writel(val, nfc->base + MEM_ADDR2_OFST);
+	nfc->csnum = achip->csnum;
+	writel(achip->eccval, nfc->base + ECC_OFST);
+	writel(achip->inftimeval, nfc->base + DATA_INTERFACE_OFST);
+}
+
+static int anfc_exec_op(struct nand_chip *chip,
+			const struct nand_operation *op,
+			bool check_only)
+{
+	anfc_select_chip(chip, op->cs);
+	return nand_op_parser_exec_op(chip, &anfc_op_parser,
+				      op, check_only);
+}
+
+static irqreturn_t anfc_irq_handler(int irq, void *ptr)
+{
+	struct anfc_nand_controller *nfc = ptr;
+	u32 status;
+
+	status = readl(nfc->base + INTR_STS_OFST);
+	if (status & EVENT_MASK) {
+		writel(status & EVENT_MASK, nfc->base + INTR_STS_OFST);
+		writel(0, nfc->base + INTR_STS_EN_OFST);
+		writel(0, nfc->base + INTR_SIG_EN_OFST);
+		complete(&nfc->event);
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
+static int anfc_nand_attach_chip(struct nand_chip *chip)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct anfc_nand_chip *achip = to_anfc_nand(chip);
+	u32 ret;
+
+	if (mtd->writesize <= SZ_512)
+		achip->caddr_cycles = 1;
+	else
+		achip->caddr_cycles = 2;
+
+	if (chip->options & NAND_ROW_ADDR_3)
+		achip->raddr_cycles = 3;
+	else
+		achip->raddr_cycles = 2;
+
+	chip->ecc.calc_buf = kmalloc(mtd->oobsize, GFP_KERNEL);
+	chip->ecc.code_buf = kmalloc(mtd->oobsize, GFP_KERNEL);
+	ret = anfc_ecc_init(mtd, &chip->ecc, chip->ecc.mode);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static const struct nand_controller_ops anfc_nand_controller_ops = {
+	.attach_chip = anfc_nand_attach_chip,
+	.exec_op = anfc_exec_op,
+};
+
+static int anfc_init_timing_mode(struct anfc_nand_controller *nfc,
+				 struct anfc_nand_chip *achip)
+{
+	struct nand_chip *chip = &achip->chip;
+	int mode, err;
+	u8 feature[ONFI_SUBFEATURE_PARAM_LEN];
+	u32 inftimeval;
+	bool change_sdr_clk = false;
+
+	memset(feature, 0, sizeof(feature));
+	/* Get nvddr timing modes */
+	mode = onfi_get_sync_timing_mode(chip) & 0xff;
+	if (!mode) {
+		mode = fls(onfi_get_async_timing_mode(chip)) - 1;
+		inftimeval = mode;
+		if (mode >= 2 && mode <= 5)
+			change_sdr_clk = true;
+	} else {
+		mode = fls(mode) - 1;
+		inftimeval = NVDDR_MODE | (mode << NVDDR_TIMING_MODE_SHIFT);
+		mode |= ONFI_DATA_INTERFACE_NVDDR;
+	}
+
+	feature[0] = mode;
+	nand_select_target(chip, achip->csnum);
+	anfc_prepare_cmd(chip, NAND_CMD_SET_FEATURES, 0, 0, 0, 1);
+	anfc_setpagecoladdr(nfc, 0x0, ONFI_FEATURE_ADDR_TIMING_MODE);
+
+	anfc_write_data_op(chip, feature, sizeof(feature), 1, 0);
+	nand_deselect_target(chip);
+
+	/*
+	 * SDR timing modes 2-5 will not work for the arasan nand when
+	 * freq > 90 MHz, so reduce the freq in SDR modes 2-5 to < 90Mhz
+	 */
+	if (change_sdr_clk) {
+		clk_disable_unprepare(nfc->clk_sys);
+		err = clk_set_rate(nfc->clk_sys, SDR_MODE_DEFLT_FREQ);
+		if (err) {
+			dev_err(nfc->dev, "Can't set the clock rate\n");
+			return err;
+		}
+		err = clk_prepare_enable(nfc->clk_sys);
+		if (err) {
+			dev_err(nfc->dev, "Unable to enable sys clock.\n");
+			clk_disable_unprepare(nfc->clk_sys);
+			return err;
+		}
+	}
+	achip->inftimeval = inftimeval;
+
+	if (mode & ONFI_DATA_INTERFACE_NVDDR)
+		achip->spktsize = NVDDR_MODE_PACKET_SIZE;
+
+	return 0;
+}
+
+static int anfc_nand_chip_init(struct anfc_nand_controller *nfc,
+			       struct anfc_nand_chip *anand_chip,
+			       struct device_node *np)
+{
+	struct nand_chip *chip = &anand_chip->chip;
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	int ret;
+
+	ret = of_property_read_u32(np, "reg", &anand_chip->csnum);
+	if (ret) {
+		dev_err(nfc->dev, "can't get chip-select\n");
+		return -ENXIO;
+	}
+	mtd->name = devm_kasprintf(nfc->dev, GFP_KERNEL, "arasan_nand.%d",
+				   anand_chip->csnum);
+	mtd->dev.parent = nfc->dev;
+	chip->controller = &nfc->controller;
+	chip->options = NAND_BUSWIDTH_AUTO | NAND_NO_SUBPAGE_WRITE;
+	chip->bbt_options = NAND_BBT_USE_FLASH;
+	chip->legacy.select_chip = anfc_select_chip;
+	nand_set_flash_node(chip, np);
+
+	anand_chip->spktsize = SDR_MODE_PACKET_SIZE;
+
+	ret = nand_scan(chip, 1);
+	if (ret) {
+		dev_err(nfc->dev, "nand_scan_tail for NAND failed\n");
+		return ret;
+	}
+	ret = anfc_init_timing_mode(nfc, anand_chip);
+	if (ret) {
+		dev_err(nfc->dev, "timing mode init failed\n");
+		return ret;
+	}
+
+	return mtd_device_register(mtd, NULL, 0);
+}
+
+static int anfc_probe(struct platform_device *pdev)
+{
+	struct anfc_nand_controller *nfc;
+	struct anfc_nand_chip *anand_chip;
+	struct device_node *np = pdev->dev.of_node, *child;
+	struct resource *res;
+	int err;
+
+	nfc = devm_kzalloc(&pdev->dev, sizeof(*nfc), GFP_KERNEL);
+	if (!nfc)
+		return -ENOMEM;
+
+	nand_controller_init(&nfc->controller);
+	INIT_LIST_HEAD(&nfc->chips);
+	init_completion(&nfc->event);
+	nfc->dev = &pdev->dev;
+	platform_set_drvdata(pdev, nfc);
+	nfc->csnum = -1;
+	nfc->controller.ops = &anfc_nand_controller_ops;
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	nfc->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(nfc->base))
+		return PTR_ERR(nfc->base);
+	nfc->irq = platform_get_irq(pdev, 0);
+	if (nfc->irq < 0)
+		return -ENXIO;
+
+	dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
+	err = devm_request_irq(&pdev->dev, nfc->irq, anfc_irq_handler,
+			       0, "arasannfc", nfc);
+	if (err)
+		return err;
+	nfc->clk_sys = devm_clk_get(&pdev->dev, "clk_sys");
+	if (IS_ERR(nfc->clk_sys)) {
+		dev_err(&pdev->dev, "sys clock not found.\n");
+		return PTR_ERR(nfc->clk_sys);
+	}
+
+	nfc->clk_flash = devm_clk_get(&pdev->dev, "clk_flash");
+	if (IS_ERR(nfc->clk_flash)) {
+		dev_err(&pdev->dev, "flash clock not found.\n");
+		return PTR_ERR(nfc->clk_flash);
+	}
+
+	err = clk_prepare_enable(nfc->clk_sys);
+	if (err) {
+		dev_err(&pdev->dev, "Unable to enable sys clock.\n");
+		return err;
+	}
+
+	err = clk_prepare_enable(nfc->clk_flash);
+	if (err) {
+		dev_err(&pdev->dev, "Unable to enable flash clock.\n");
+		goto clk_dis_sys;
+	}
+
+	pm_runtime_set_autosuspend_delay(nfc->dev, ANFC_PM_TIMEOUT);
+	pm_runtime_use_autosuspend(nfc->dev);
+	pm_runtime_set_active(nfc->dev);
+	pm_runtime_get_noresume(nfc->dev);
+	pm_runtime_enable(nfc->dev);
+	for_each_available_child_of_node(np, child) {
+		anand_chip = devm_kzalloc(&pdev->dev, sizeof(*anand_chip),
+					  GFP_KERNEL);
+		if (!anand_chip) {
+			of_node_put(child);
+			err = -ENOMEM;
+			goto nandchip_clean_up;
+		}
+		err = anfc_nand_chip_init(nfc, anand_chip, child);
+		if (err) {
+			devm_kfree(&pdev->dev, anand_chip);
+			continue;
+		}
+
+		list_add_tail(&anand_chip->node, &nfc->chips);
+	}
+	pm_runtime_mark_last_busy(nfc->dev);
+	pm_runtime_put_autosuspend(nfc->dev);
+	return 0;
+
+nandchip_clean_up:
+	list_for_each_entry(anand_chip, &nfc->chips, node)
+		nand_release(&anand_chip->chip);
+	pm_runtime_disable(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
+	clk_disable_unprepare(nfc->clk_flash);
+clk_dis_sys:
+	clk_disable_unprepare(nfc->clk_sys);
+
+	return err;
+}
+
+static int anfc_remove(struct platform_device *pdev)
+{
+	struct anfc_nand_controller *nfc = platform_get_drvdata(pdev);
+	struct anfc_nand_chip *anand_chip;
+
+	list_for_each_entry(anand_chip, &nfc->chips, node)
+		nand_release(&anand_chip->chip);
+	pm_runtime_disable(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
+	pm_runtime_dont_use_autosuspend(&pdev->dev);
+
+	clk_disable_unprepare(nfc->clk_sys);
+	clk_disable_unprepare(nfc->clk_flash);
+
+	return 0;
+}
+
+static const struct of_device_id anfc_ids[] = {
+	{ .compatible = "arasan,nfc-v3p10" },
+	{ .compatible = "xlnx,zynqmp-nand" },
+	{  }
+};
+MODULE_DEVICE_TABLE(of, anfc_ids);
+
+static int anfc_suspend(struct device *dev)
+{
+	return pm_runtime_put_sync(dev);
+}
+
+static int anfc_resume(struct device *dev)
+{
+	return pm_runtime_get_sync(dev);
+}
+
+static int __maybe_unused anfc_runtime_suspend(struct device *dev)
+{
+	struct anfc_nand_controller *nfc = dev_get_drvdata(dev);
+
+	clk_disable(nfc->clk_sys);
+	clk_disable(nfc->clk_flash);
+
+	return 0;
+}
+
+static int __maybe_unused anfc_runtime_idle(struct device *dev)
+{
+	struct anfc_nand_controller *nfc = dev_get_drvdata(dev);
+
+	if (nfc->chip_active)
+		return -EBUSY;
+
+	return 0;
+}
+
+static int __maybe_unused anfc_runtime_resume(struct device *dev)
+{
+	struct anfc_nand_controller *nfc = dev_get_drvdata(dev);
+	int ret;
+
+	ret = clk_enable(nfc->clk_sys);
+	if (ret) {
+		dev_err(dev, "Cannot enable sys clock.\n");
+		return ret;
+	}
+
+	ret = clk_enable(nfc->clk_flash);
+	if (ret) {
+		dev_err(dev, "Cannot enable flash clock.\n");
+		clk_disable(nfc->clk_sys);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct dev_pm_ops anfc_pm_ops = {
+	.resume = anfc_resume,
+	.suspend = anfc_suspend,
+	.runtime_resume = anfc_runtime_resume,
+	.runtime_suspend = anfc_runtime_suspend,
+	.runtime_idle = anfc_runtime_idle,
+};
+static struct platform_driver anfc_driver = {
+	.driver = {
+		.name = "arasan-nand-controller",
+		.of_match_table = anfc_ids,
+		.pm = &anfc_pm_ops,
+	},
+	.probe = anfc_probe,
+	.remove = anfc_remove,
+};
+module_platform_driver(anfc_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Xilinx, Inc");
+MODULE_DESCRIPTION("Arasan NAND Flash Controller Driver");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/atmel/nand-controller.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/atmel/nand-controller.c
@@ -402,6 +402,7 @@
 
 	dma_async_issue_pending(nc->dmac);
 	wait_for_completion(&finished);
+	dma_unmap_single(nc->dev, buf_dma, len, dir);
 
 	return 0;
 
@@ -813,10 +814,12 @@
 							  NULL, 0,
 							  chip->ecc.strength);
 
-		if (ret >= 0)
+		if (ret >= 0) {
+			mtd->ecc_stats.corrected += ret;
 			max_bitflips = max(ret, max_bitflips);
-		else
+		} else {
 			mtd->ecc_stats.failed++;
+		}
 
 		databuf += chip->ecc.size;
 		eccbuf += chip->ecc.bytes;
@@ -2002,13 +2005,15 @@
 	nc->mck = of_clk_get(dev->parent->of_node, 0);
 	if (IS_ERR(nc->mck)) {
 		dev_err(dev, "Failed to retrieve MCK clk\n");
-		return PTR_ERR(nc->mck);
+		ret = PTR_ERR(nc->mck);
+		goto out_release_dma;
 	}
 
 	np = of_parse_phandle(dev->parent->of_node, "atmel,smc", 0);
 	if (!np) {
 		dev_err(dev, "Missing or invalid atmel,smc property\n");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out_release_dma;
 	}
 
 	nc->smc = syscon_node_to_regmap(np);
@@ -2016,10 +2021,16 @@
 	if (IS_ERR(nc->smc)) {
 		ret = PTR_ERR(nc->smc);
 		dev_err(dev, "Could not get SMC regmap (err = %d)\n", ret);
-		return ret;
+		goto out_release_dma;
 	}
 
 	return 0;
+
+out_release_dma:
+	if (nc->dmac)
+		dma_release_channel(nc->dmac);
+
+	return ret;
 }
 
 static int
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/atmel/pmecc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/atmel/pmecc.c
@@ -362,7 +362,7 @@
 	size = ALIGN(size, sizeof(s32));
 	size += (req->ecc.strength + 1) * sizeof(s32) * 3;
 
-	user = kzalloc(size, GFP_KERNEL);
+	user = devm_kzalloc(pmecc->dev, size, GFP_KERNEL);
 	if (!user)
 		return ERR_PTR(-ENOMEM);
 
@@ -380,10 +380,8 @@
 	user->delta = user->dmu + req->ecc.strength + 1;
 
 	gf_tables = atmel_pmecc_get_gf_tables(req);
-	if (IS_ERR(gf_tables)) {
-		kfree(user);
+	if (IS_ERR(gf_tables))
 		return ERR_CAST(gf_tables);
-	}
 
 	user->gf_tables = gf_tables;
 
@@ -408,12 +406,6 @@
 }
 EXPORT_SYMBOL_GPL(atmel_pmecc_create_user);
 
-void atmel_pmecc_destroy_user(struct atmel_pmecc_user *user)
-{
-	kfree(user);
-}
-EXPORT_SYMBOL_GPL(atmel_pmecc_destroy_user);
-
 static int get_strength(struct atmel_pmecc_user *user)
 {
 	const int *strengths = user->pmecc->caps->strengths;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/atmel/pmecc.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/atmel/pmecc.h
@@ -55,8 +55,6 @@
 struct atmel_pmecc_user *
 atmel_pmecc_create_user(struct atmel_pmecc *pmecc,
 			struct atmel_pmecc_user_req *req);
-void atmel_pmecc_destroy_user(struct atmel_pmecc_user *user);
-
 void atmel_pmecc_reset(struct atmel_pmecc *pmecc);
 int atmel_pmecc_enable(struct atmel_pmecc_user *user, int op);
 void atmel_pmecc_disable(struct atmel_pmecc_user *user);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/brcmnand/brcmnand.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/brcmnand/brcmnand.c
@@ -197,6 +197,7 @@
 	unsigned int		max_page_size;
 	const unsigned int	*page_sizes;
 	unsigned int		max_oob;
+	u32			ecc_level_shift;
 	u32			features;
 
 	/* for low-power standby/resume only */
@@ -487,6 +488,34 @@
 	INTFC_CTLR_READY		= BIT(31),
 };
 
+/***********************************************************************
+ * NAND ACC CONTROL bitfield
+ *
+ * Some bits have remained constant throughout hardware revision, while
+ * others have shifted around.
+ ***********************************************************************/
+
+/* Constant for all versions (where supported) */
+enum {
+	/* See BRCMNAND_HAS_CACHE_MODE */
+	ACC_CONTROL_CACHE_MODE				= BIT(22),
+
+	/* See BRCMNAND_HAS_PREFETCH */
+	ACC_CONTROL_PREFETCH				= BIT(23),
+
+	ACC_CONTROL_PAGE_HIT				= BIT(24),
+	ACC_CONTROL_WR_PREEMPT				= BIT(25),
+	ACC_CONTROL_PARTIAL_PAGE			= BIT(26),
+	ACC_CONTROL_RD_ERASED				= BIT(27),
+	ACC_CONTROL_FAST_PGM_RDIN			= BIT(28),
+	ACC_CONTROL_WR_ECC				= BIT(30),
+	ACC_CONTROL_RD_ECC				= BIT(31),
+};
+
+#define	ACC_CONTROL_ECC_SHIFT			16
+/* Only for v7.2 */
+#define	ACC_CONTROL_ECC_EXT_SHIFT		13
+
 static inline u32 nand_readreg(struct brcmnand_controller *ctrl, u32 offs)
 {
 	return brcmnand_readl(ctrl->nand_base + offs);
@@ -537,8 +566,9 @@
 	} else {
 		ctrl->cs_offsets = brcmnand_cs_offsets;
 
-		/* v5.0 and earlier has a different CS0 offset layout */
-		if (ctrl->nand_version <= 0x0500)
+		/* v3.3-5.0 have a different CS0 offset layout */
+		if (ctrl->nand_version >= 0x0303 &&
+		    ctrl->nand_version <= 0x0500)
 			ctrl->cs0_offsets = brcmnand_cs_offsets_cs0;
 	}
 
@@ -589,6 +619,12 @@
 	else if (of_property_read_bool(ctrl->dev->of_node, "brcm,nand-has-wp"))
 		ctrl->features |= BRCMNAND_HAS_WP;
 
+	/* v7.2 has different ecc level shift in the acc register */
+	if (ctrl->nand_version == 0x0702)
+		ctrl->ecc_level_shift = ACC_CONTROL_ECC_EXT_SHIFT;
+	else
+		ctrl->ecc_level_shift = ACC_CONTROL_ECC_SHIFT;
+
 	return 0;
 }
 
@@ -751,30 +787,6 @@
 	return 0;
 }
 
-/***********************************************************************
- * NAND ACC CONTROL bitfield
- *
- * Some bits have remained constant throughout hardware revision, while
- * others have shifted around.
- ***********************************************************************/
-
-/* Constant for all versions (where supported) */
-enum {
-	/* See BRCMNAND_HAS_CACHE_MODE */
-	ACC_CONTROL_CACHE_MODE				= BIT(22),
-
-	/* See BRCMNAND_HAS_PREFETCH */
-	ACC_CONTROL_PREFETCH				= BIT(23),
-
-	ACC_CONTROL_PAGE_HIT				= BIT(24),
-	ACC_CONTROL_WR_PREEMPT				= BIT(25),
-	ACC_CONTROL_PARTIAL_PAGE			= BIT(26),
-	ACC_CONTROL_RD_ERASED				= BIT(27),
-	ACC_CONTROL_FAST_PGM_RDIN			= BIT(28),
-	ACC_CONTROL_WR_ECC				= BIT(30),
-	ACC_CONTROL_RD_ECC				= BIT(31),
-};
-
 static inline u32 brcmnand_spare_area_mask(struct brcmnand_controller *ctrl)
 {
 	if (ctrl->nand_version == 0x0702)
@@ -785,18 +797,15 @@
 		return GENMASK(5, 0);
 }
 
-#define NAND_ACC_CONTROL_ECC_SHIFT	16
-#define NAND_ACC_CONTROL_ECC_EXT_SHIFT	13
-
 static inline u32 brcmnand_ecc_level_mask(struct brcmnand_controller *ctrl)
 {
 	u32 mask = (ctrl->nand_version >= 0x0600) ? 0x1f : 0x0f;
 
-	mask <<= NAND_ACC_CONTROL_ECC_SHIFT;
+	mask <<= ACC_CONTROL_ECC_SHIFT;
 
 	/* v7.2 includes additional ECC levels */
-	if (ctrl->nand_version >= 0x0702)
-		mask |= 0x7 << NAND_ACC_CONTROL_ECC_EXT_SHIFT;
+	if (ctrl->nand_version == 0x0702)
+		mask |= 0x7 << ACC_CONTROL_ECC_EXT_SHIFT;
 
 	return mask;
 }
@@ -810,8 +819,8 @@
 
 	if (en) {
 		acc_control |= ecc_flags; /* enable RD/WR ECC */
-		acc_control |= host->hwcfg.ecc_level
-			       << NAND_ACC_CONTROL_ECC_SHIFT;
+		acc_control &= ~brcmnand_ecc_level_mask(ctrl);
+		acc_control |= host->hwcfg.ecc_level << ctrl->ecc_level_shift;
 	} else {
 		acc_control &= ~ecc_flags; /* disable RD/WR ECC */
 		acc_control &= ~brcmnand_ecc_level_mask(ctrl);
@@ -890,6 +899,14 @@
 		cpu_relax();
 	} while (time_after(limit, jiffies));
 
+	/*
+	 * do a final check after time out in case the CPU was busy and the driver
+	 * did not get enough time to perform the polling to avoid false alarms
+	 */
+	val = brcmnand_read_reg(ctrl, BRCMNAND_INTFC_STATUS);
+	if ((val & mask) == expected_val)
+		return 0;
+
 	dev_warn(ctrl->dev, "timeout on status poll (expected %x got %x)\n",
 		 expected_val, val & mask);
 
@@ -1019,11 +1036,14 @@
 		if (!section) {
 			/*
 			 * Small-page NAND use byte 6 for BBI while large-page
-			 * NAND use byte 0.
+			 * NAND use bytes 0 and 1.
 			 */
-			if (cfg->page_size > 512)
-				oobregion->offset++;
-			oobregion->length--;
+			if (cfg->page_size > 512) {
+				oobregion->offset += 2;
+				oobregion->length -= 2;
+			} else {
+				oobregion->length--;
+			}
 		}
 	}
 
@@ -1269,19 +1289,33 @@
 			     const u8 *oob, int sas, int sector_1k)
 {
 	int tbytes = sas << sector_1k;
-	int j;
+	int j, k = 0;
+	u32 last = 0xffffffff;
+	u8 *plast = (u8 *)&last;
 
 	/* Adjust OOB values for 1K sector size */
 	if (sector_1k && (i & 0x01))
 		tbytes = max(0, tbytes - (int)ctrl->max_oob);
 	tbytes = min_t(int, tbytes, ctrl->max_oob);
 
-	for (j = 0; j < tbytes; j += 4)
+	/*
+	 * tbytes may not be multiple of words. Make sure we don't read out of
+	 * the boundary and stop at last word.
+	 */
+	for (j = 0; (j + 3) < tbytes; j += 4)
 		oob_reg_write(ctrl, j,
 				(oob[j + 0] << 24) |
 				(oob[j + 1] << 16) |
 				(oob[j + 2] <<  8) |
 				(oob[j + 3] <<  0));
+
+	/* handle the remaing bytes */
+	while (j < tbytes)
+		plast[k++] = oob[j++];
+
+	if (tbytes & 0x3)
+		oob_reg_write(ctrl, (tbytes & ~0x3), (__force u32)cpu_to_be32(last));
+
 	return tbytes;
 }
 
@@ -1327,7 +1361,17 @@
 
 	dev_dbg(ctrl->dev, "send native cmd %d addr 0x%llx\n", cmd, cmd_addr);
 
-	BUG_ON(ctrl->cmd_pending != 0);
+	/*
+	 * If we came here through _panic_write and there is a pending
+	 * command, try to wait for it. If it times out, rather than
+	 * hitting BUG_ON, just return so we don't crash while crashing.
+	 */
+	if (oops_in_progress) {
+		if (ctrl->cmd_pending &&
+			bcmnand_ctrl_poll_status(ctrl, NAND_CTRL_RDY, NAND_CTRL_RDY, 0))
+			return;
+	} else
+		BUG_ON(ctrl->cmd_pending != 0);
 	ctrl->cmd_pending = cmd;
 
 	ret = bcmnand_ctrl_poll_status(ctrl, NAND_CTRL_RDY, NAND_CTRL_RDY, 0);
@@ -1752,7 +1796,7 @@
 					mtd->oobsize / trans,
 					host->hwcfg.sector_size_1k);
 
-		if (!ret) {
+		if (ret != -EBADMSG) {
 			*err_addr = brcmnand_get_uncorrecc_addr(ctrl);
 
 			if (*err_addr)
@@ -1787,28 +1831,31 @@
 static int brcmstb_nand_verify_erased_page(struct mtd_info *mtd,
 		  struct nand_chip *chip, void *buf, u64 addr)
 {
-	int i, sas;
-	void *oob = chip->oob_poi;
+	struct mtd_oob_region ecc;
+	int i;
 	int bitflips = 0;
 	int page = addr >> chip->page_shift;
 	int ret;
+	void *ecc_bytes;
 	void *ecc_chunk;
 
 	if (!buf)
 		buf = nand_get_data_buf(chip);
 
-	sas = mtd->oobsize / chip->ecc.steps;
-
 	/* read without ecc for verification */
 	ret = chip->ecc.read_page_raw(chip, buf, true, page);
 	if (ret)
 		return ret;
 
-	for (i = 0; i < chip->ecc.steps; i++, oob += sas) {
+	for (i = 0; i < chip->ecc.steps; i++) {
 		ecc_chunk = buf + chip->ecc.size * i;
-		ret = nand_check_erased_ecc_chunk(ecc_chunk,
-						  chip->ecc.size,
-						  oob, sas, NULL, 0,
+
+		mtd_ooblayout_ecc(mtd, i, &ecc);
+		ecc_bytes = chip->oob_poi + ecc.offset;
+
+		ret = nand_check_erased_ecc_chunk(ecc_chunk, chip->ecc.size,
+						  ecc_bytes, ecc.length,
+						  NULL, 0,
 						  chip->ecc.strength);
 		if (ret < 0)
 			return ret;
@@ -2154,7 +2201,7 @@
 
 	tmp = nand_readreg(ctrl, acc_control_offs);
 	tmp &= ~brcmnand_ecc_level_mask(ctrl);
-	tmp |= cfg->ecc_level << NAND_ACC_CONTROL_ECC_SHIFT;
+	tmp |= cfg->ecc_level << ctrl->ecc_level_shift;
 	tmp &= ~brcmnand_spare_area_mask(ctrl);
 	tmp |= cfg->spare_area_size;
 	nand_writereg(ctrl, acc_control_offs, tmp);
@@ -2357,6 +2404,12 @@
 
 	ret = brcmstb_choose_ecc_layout(host);
 
+	/* If OOB is written with ECC enabled it will cause ECC errors */
+	if (is_hamming_ecc(host->ctrl, &host->hwcfg)) {
+		chip->ecc.write_oob = brcmnand_write_oob_raw;
+		chip->ecc.read_oob = brcmnand_read_oob_raw;
+	}
+
 	return ret;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/cafe_nand.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/cafe_nand.c
@@ -757,7 +757,7 @@
 			  "CAFE NAND", mtd);
 	if (err) {
 		dev_warn(&pdev->dev, "Could not register IRQ %d\n", pdev->irq);
-		goto out_ior;
+		goto out_free_rs;
 	}
 
 	/* Disable master reset, enable NAND clock */
@@ -801,6 +801,8 @@
 	/* Disable NAND IRQ in global IRQ mask register */
 	cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK);
 	free_irq(pdev->irq, mtd);
+ out_free_rs:
+	free_rs(cafe->rs);
  out_ior:
 	pci_iounmap(pdev, cafe->mmio);
  out_free_mtd:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/diskonchip.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/diskonchip.c
@@ -53,7 +53,7 @@
 	0xe8000, 0xea000, 0xec000, 0xee000,
 #endif
 #endif
-	0xffffffff };
+};
 
 static struct mtd_info *doclist = NULL;
 
@@ -1221,7 +1221,7 @@
 		    (i == 0) && (ip->firstUnit > 0)) {
 			parts[0].name = " DiskOnChip IPL / Media Header partition";
 			parts[0].offset = 0;
-			parts[0].size = mtd->erasesize * ip->firstUnit;
+			parts[0].size = (uint64_t)mtd->erasesize * ip->firstUnit;
 			numparts = 1;
 		}
 
@@ -1609,13 +1609,10 @@
 		numchips = doc2001_init(mtd);
 
 	if ((ret = nand_scan(nand, numchips)) || (ret = doc->late_init(mtd))) {
-		/* DBB note: i believe nand_release is necessary here, as
+		/* DBB note: i believe nand_cleanup is necessary here, as
 		   buffers may have been allocated in nand_base.  Check with
 		   Thomas. FIX ME! */
-		/* nand_release will call mtd_device_unregister, but we
-		   haven't yet added it.  This is handled without incident by
-		   mtd_device_unregister, as far as I can tell. */
-		nand_release(nand);
+		nand_cleanup(nand);
 		goto fail;
 	}
 
@@ -1669,7 +1666,7 @@
 		if (ret < 0)
 			return ret;
 	} else {
-		for (i = 0; (doc_locations[i] != 0xffffffff); i++) {
+		for (i = 0; i < ARRAY_SIZE(doc_locations); i++) {
 			doc_probe(doc_locations[i]);
 		}
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/fsl_ifc_nand.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/fsl_ifc_nand.c
@@ -21,7 +21,7 @@
 
 #define ERR_BYTE		0xFF /* Value returned for read
 					bytes when read failed	*/
-#define IFC_TIMEOUT_MSECS	500  /* Maximum number of mSecs to wait
+#define IFC_TIMEOUT_MSECS	1000 /* Maximum timeout to wait
 					for IFC NAND Machine	*/
 
 struct fsl_ifc_ctrl;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/fsl_upm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/fsl_upm.c
@@ -62,7 +62,6 @@
 static void fun_wait_rnb(struct fsl_upm_nand *fun)
 {
 	if (fun->rnb_gpio[fun->mchip_number] >= 0) {
-		struct mtd_info *mtd = nand_to_mtd(&fun->chip);
 		int cnt = 1000000;
 
 		while (--cnt && !fun_chip_ready(&fun->chip))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/fsmc_nand.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/fsmc_nand.c
@@ -15,6 +15,7 @@
 
 #include <linux/clk.h>
 #include <linux/completion.h>
+#include <linux/delay.h>
 #include <linux/dmaengine.h>
 #include <linux/dma-direction.h>
 #include <linux/dma-mapping.h>
@@ -93,6 +94,14 @@
 
 #define FSMC_BUSY_WAIT_TIMEOUT	(1 * HZ)
 
+/*
+ * According to SPEAr300 Reference Manual (RM0082)
+ *  TOUDEL = 7ns (Output delay from the flip-flops to the board)
+ *  TINDEL = 5ns (Input delay from the board to the flipflop)
+ */
+#define TOUTDEL	7000
+#define TINDEL	5000
+
 struct fsmc_nand_timings {
 	u8 tclr;
 	u8 tar;
@@ -277,7 +286,7 @@
 {
 	unsigned long hclk = clk_get_rate(host->clk);
 	unsigned long hclkn = NSEC_PER_SEC / hclk;
-	u32 thiz, thold, twait, tset;
+	u32 thiz, thold, twait, tset, twait_min;
 
 	if (sdrt->tRC_min < 30000)
 		return -EOPNOTSUPP;
@@ -309,13 +318,6 @@
 	else if (tims->thold > FSMC_THOLD_MASK)
 		tims->thold = FSMC_THOLD_MASK;
 
-	twait = max(sdrt->tRP_min, sdrt->tWP_min);
-	tims->twait = DIV_ROUND_UP(twait / 1000, hclkn) - 1;
-	if (tims->twait == 0)
-		tims->twait = 1;
-	else if (tims->twait > FSMC_TWAIT_MASK)
-		tims->twait = FSMC_TWAIT_MASK;
-
 	tset = max(sdrt->tCS_min - sdrt->tWP_min,
 		   sdrt->tCEA_max - sdrt->tREA_max);
 	tims->tset = DIV_ROUND_UP(tset / 1000, hclkn) - 1;
@@ -324,6 +326,21 @@
 	else if (tims->tset > FSMC_TSET_MASK)
 		tims->tset = FSMC_TSET_MASK;
 
+	/*
+	 * According to SPEAr300 Reference Manual (RM0082) which gives more
+	 * information related to FSMSC timings than the SPEAr600 one (RM0305),
+	 *   twait >= tCEA - (tset * TCLK) + TOUTDEL + TINDEL
+	 */
+	twait_min = sdrt->tCEA_max - ((tims->tset + 1) * hclkn * 1000)
+		    + TOUTDEL + TINDEL;
+	twait = max3(sdrt->tRP_min, sdrt->tWP_min, twait_min);
+
+	tims->twait = DIV_ROUND_UP(twait / 1000, hclkn) - 1;
+	if (tims->twait == 0)
+		tims->twait = 1;
+	else if (tims->twait > FSMC_TWAIT_MASK)
+		tims->twait = FSMC_TWAIT_MASK;
+
 	return 0;
 }
 
@@ -650,6 +667,9 @@
 						instr->ctx.waitrdy.timeout_ms);
 			break;
 		}
+
+		if (instr->delay_ns)
+			ndelay(instr->delay_ns);
 	}
 
 	return ret;
@@ -1066,11 +1086,13 @@
 		host->read_dma_chan = dma_request_channel(mask, filter, NULL);
 		if (!host->read_dma_chan) {
 			dev_err(&pdev->dev, "Unable to get read dma channel\n");
+			ret = -ENODEV;
 			goto disable_clk;
 		}
 		host->write_dma_chan = dma_request_channel(mask, filter, NULL);
 		if (!host->write_dma_chan) {
 			dev_err(&pdev->dev, "Unable to get write dma channel\n");
+			ret = -ENODEV;
 			goto release_dma_read_chan;
 		}
 	}
@@ -1159,9 +1181,14 @@
 static int fsmc_nand_resume(struct device *dev)
 {
 	struct fsmc_nand_data *host = dev_get_drvdata(dev);
+	int ret;
 
 	if (host) {
-		clk_prepare_enable(host->clk);
+		ret = clk_prepare_enable(host->clk);
+		if (ret) {
+			dev_err(dev, "failed to enable clk\n");
+			return ret;
+		}
 		if (host->dev_timings)
 			fsmc_nand_setup(host, host->dev_timings);
 		nand_reset(&host->nand, 0);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
@@ -148,6 +148,12 @@
 	struct resources *r = &this->resources;
 	int ret;
 
+	ret = pm_runtime_get_sync(this->dev);
+	if (ret < 0) {
+		pm_runtime_put_noidle(this->dev);
+		return ret;
+	}
+
 	ret = gpmi_reset_block(r->gpmi_regs, false);
 	if (ret)
 		goto err_out;
@@ -179,8 +185,9 @@
 	 */
 	writel(BM_GPMI_CTRL1_DECOUPLE_CS, r->gpmi_regs + HW_GPMI_CTRL1_SET);
 
-	return 0;
 err_out:
+	pm_runtime_mark_last_busy(this->dev);
+	pm_runtime_put_autosuspend(this->dev);
 	return ret;
 }
 
@@ -535,8 +542,10 @@
 		return ret;
 
 	ret = pm_runtime_get_sync(this->dev);
-	if (ret < 0)
+	if (ret < 0) {
+		pm_runtime_put_autosuspend(this->dev);
 		return ret;
+	}
 
 	/*
 	* Due to erratum #2847 of the MX23, the BCH cannot be soft reset on this
@@ -636,14 +645,16 @@
 				     const struct nand_sdr_timings *sdr)
 {
 	struct gpmi_nfc_hardware_timing *hw = &this->hw;
+	struct resources *r = &this->resources;
 	unsigned int dll_threshold_ps = this->devdata->max_chain_delay;
 	unsigned int period_ps, reference_period_ps;
 	unsigned int data_setup_cycles, data_hold_cycles, addr_setup_cycles;
 	unsigned int tRP_ps;
 	bool use_half_period;
 	int sample_delay_ps, sample_delay_factor;
-	u16 busy_timeout_cycles;
+	unsigned int busy_timeout_cycles;
 	u8 wrn_dly_sel;
+	u64 busy_timeout_ps;
 
 	if (sdr->tRC_min >= 30000) {
 		/* ONFI non-EDO modes [0-3] */
@@ -659,18 +670,21 @@
 		wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY;
 	}
 
+	hw->clk_rate = clk_round_rate(r->clock[0], hw->clk_rate);
+
 	/* SDR core timings are given in picoseconds */
 	period_ps = div_u64((u64)NSEC_PER_SEC * 1000, hw->clk_rate);
 
 	addr_setup_cycles = TO_CYCLES(sdr->tALS_min, period_ps);
 	data_setup_cycles = TO_CYCLES(sdr->tDS_min, period_ps);
 	data_hold_cycles = TO_CYCLES(sdr->tDH_min, period_ps);
-	busy_timeout_cycles = TO_CYCLES(sdr->tWB_max + sdr->tR_max, period_ps);
+	busy_timeout_ps = max(sdr->tBERS_max, sdr->tPROG_max);
+	busy_timeout_cycles = TO_CYCLES(busy_timeout_ps, period_ps);
 
 	hw->timing0 = BF_GPMI_TIMING0_ADDRESS_SETUP(addr_setup_cycles) |
 		      BF_GPMI_TIMING0_DATA_HOLD(data_hold_cycles) |
 		      BF_GPMI_TIMING0_DATA_SETUP(data_setup_cycles);
-	hw->timing1 = BF_GPMI_TIMING1_BUSY_TIMEOUT(busy_timeout_cycles * 4096);
+	hw->timing1 = BF_GPMI_TIMING1_BUSY_TIMEOUT(DIV_ROUND_UP(busy_timeout_cycles, 4096));
 
 	/*
 	 * Derive NFC ideal delay from {3}:
@@ -701,14 +715,32 @@
 			      (use_half_period ? BM_GPMI_CTRL1_HALF_PERIOD : 0);
 }
 
-static void gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
+static int gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
 {
 	struct gpmi_nfc_hardware_timing *hw = &this->hw;
 	struct resources *r = &this->resources;
 	void __iomem *gpmi_regs = r->gpmi_regs;
 	unsigned int dll_wait_time_us;
+	int ret;
+
+	/* Clock dividers do NOT guarantee a clean clock signal on its output
+	 * during the change of the divide factor on i.MX6Q/UL/SX. On i.MX7/8,
+	 * all clock dividers provide these guarantee.
+	 */
+	if (GPMI_IS_MX6Q(this) || GPMI_IS_MX6SX(this))
+		clk_disable_unprepare(r->clock[0]);
+
+	ret = clk_set_rate(r->clock[0], hw->clk_rate);
+	if (ret) {
+		dev_err(this->dev, "cannot set clock rate to %lu Hz: %d\n", hw->clk_rate, ret);
+		return ret;
+	}
 
-	clk_set_rate(r->clock[0], hw->clk_rate);
+	if (GPMI_IS_MX6Q(this) || GPMI_IS_MX6SX(this)) {
+		ret = clk_prepare_enable(r->clock[0]);
+		if (ret)
+			return ret;
+	}
 
 	writel(hw->timing0, gpmi_regs + HW_GPMI_TIMING0);
 	writel(hw->timing1, gpmi_regs + HW_GPMI_TIMING1);
@@ -727,6 +759,8 @@
 
 	/* Wait for the DLL to settle. */
 	udelay(dll_wait_time_us);
+
+	return 0;
 }
 
 static int gpmi_setup_data_interface(struct nand_chip *chip, int chipnr,
@@ -1175,15 +1209,6 @@
 		r->clock[i] = clk;
 	}
 
-	if (GPMI_IS_MX6(this))
-		/*
-		 * Set the default value for the gpmi clock.
-		 *
-		 * If you want to use the ONFI nand which is in the
-		 * Synchronous Mode, you should change the clock as you need.
-		 */
-		clk_set_rate(r->clock[0], 22000000);
-
 	return 0;
 
 err_clock:
@@ -2399,7 +2424,7 @@
 	void *buf_read = NULL;
 	const void *buf_write = NULL;
 	bool direct = false;
-	struct completion *completion;
+	struct completion *dma_completion, *bch_completion;
 	unsigned long to;
 
 	this->ntransfers = 0;
@@ -2407,8 +2432,10 @@
 		this->transfers[i].direction = DMA_NONE;
 
 	ret = pm_runtime_get_sync(this->dev);
-	if (ret < 0)
+	if (ret < 0) {
+		pm_runtime_put_noidle(this->dev);
 		return ret;
+	}
 
 	/*
 	 * This driver currently supports only one NAND chip. Plus, dies share
@@ -2418,7 +2445,9 @@
 	 */
 	if (this->hw.must_apply_timings) {
 		this->hw.must_apply_timings = false;
-		gpmi_nfc_apply_timings(this);
+		ret = gpmi_nfc_apply_timings(this);
+		if (ret)
+			goto out_pm;
 	}
 
 	dev_dbg(this->dev, "%s: %d instructions\n", __func__, op->ninstrs);
@@ -2491,22 +2520,24 @@
 		       this->resources.bch_regs + HW_BCH_FLASH0LAYOUT1);
 	}
 
+	desc->callback = dma_irq_callback;
+	desc->callback_param = this;
+	dma_completion = &this->dma_done;
+	bch_completion = NULL;
+
+	init_completion(dma_completion);
+
 	if (this->bch && buf_read) {
 		writel(BM_BCH_CTRL_COMPLETE_IRQ_EN,
 		       this->resources.bch_regs + HW_BCH_CTRL_SET);
-		completion = &this->bch_done;
-	} else {
-		desc->callback = dma_irq_callback;
-		desc->callback_param = this;
-		completion = &this->dma_done;
+		bch_completion = &this->bch_done;
+		init_completion(bch_completion);
 	}
 
-	init_completion(completion);
-
 	dmaengine_submit(desc);
 	dma_async_issue_pending(get_dma_chan(this));
 
-	to = wait_for_completion_timeout(completion, msecs_to_jiffies(1000));
+	to = wait_for_completion_timeout(dma_completion, msecs_to_jiffies(1000));
 	if (!to) {
 		dev_err(this->dev, "DMA timeout, last DMA\n");
 		gpmi_dump_info(this);
@@ -2514,6 +2545,16 @@
 		goto unmap;
 	}
 
+	if (this->bch && buf_read) {
+		to = wait_for_completion_timeout(bch_completion, msecs_to_jiffies(1000));
+		if (!to) {
+			dev_err(this->dev, "BCH timeout, last DMA\n");
+			gpmi_dump_info(this);
+			ret = -ETIMEDOUT;
+			goto unmap;
+		}
+	}
+
 	writel(BM_BCH_CTRL_COMPLETE_IRQ_EN,
 	       this->resources.bch_regs + HW_BCH_CTRL_CLR);
 	gpmi_clear_bch(this);
@@ -2535,6 +2576,7 @@
 
 	this->bch = false;
 
+out_pm:
 	pm_runtime_mark_last_busy(this->dev);
 	pm_runtime_put_autosuspend(this->dev);
 
@@ -2575,7 +2617,7 @@
 	this->bch_geometry.auxiliary_size = 128;
 	ret = gpmi_alloc_dma_buffer(this);
 	if (ret)
-		goto err_out;
+		return ret;
 
 	nand_controller_init(&this->base);
 	this->base.ops = &gpmi_nand_controller_ops;
@@ -2722,6 +2764,10 @@
 		return ret;
 	}
 
+	/* Set flag to get timing setup restored for next exec_op */
+	if (this->hw.clk_rate)
+		this->hw.must_apply_timings = true;
+
 	/* re-init the BCH registers */
 	ret = bch_set_geometry(this);
 	if (ret) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/ingenic/ingenic_ecc.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/ingenic/ingenic_ecc.h
@@ -36,25 +36,25 @@
 void ingenic_ecc_release(struct ingenic_ecc *ecc);
 struct ingenic_ecc *of_ingenic_ecc_get(struct device_node *np);
 #else /* CONFIG_MTD_NAND_INGENIC_ECC */
-int ingenic_ecc_calculate(struct ingenic_ecc *ecc,
+static inline int ingenic_ecc_calculate(struct ingenic_ecc *ecc,
 			  struct ingenic_ecc_params *params,
 			  const u8 *buf, u8 *ecc_code)
 {
 	return -ENODEV;
 }
 
-int ingenic_ecc_correct(struct ingenic_ecc *ecc,
+static inline int ingenic_ecc_correct(struct ingenic_ecc *ecc,
 			struct ingenic_ecc_params *params, u8 *buf,
 			u8 *ecc_code)
 {
 	return -ENODEV;
 }
 
-void ingenic_ecc_release(struct ingenic_ecc *ecc)
+static inline void ingenic_ecc_release(struct ingenic_ecc *ecc)
 {
 }
 
-struct ingenic_ecc *of_ingenic_ecc_get(struct device_node *np)
+static inline struct ingenic_ecc *of_ingenic_ecc_get(struct device_node *np)
 {
 	return ERR_PTR(-ENODEV);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c
@@ -376,7 +376,7 @@
 
 	ret = mtd_device_register(mtd, NULL, 0);
 	if (ret) {
-		nand_release(chip);
+		nand_cleanup(chip);
 		return ret;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/lpc32xx_mlc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/lpc32xx_mlc.c
@@ -304,8 +304,9 @@
 	return 0;
 }
 
-static irqreturn_t lpc3xxx_nand_irq(int irq, struct lpc32xx_nand_host *host)
+static irqreturn_t lpc3xxx_nand_irq(int irq, void *data)
 {
+	struct lpc32xx_nand_host *host = data;
 	uint8_t sr;
 
 	/* Clear interrupt flag by reading status */
@@ -778,7 +779,7 @@
 		goto release_dma_chan;
 	}
 
-	if (request_irq(host->irq, (irq_handler_t)&lpc3xxx_nand_irq,
+	if (request_irq(host->irq, &lpc3xxx_nand_irq,
 			IRQF_TRIGGER_HIGH, DRV_NAME, host)) {
 		dev_err(&pdev->dev, "Error requesting NAND IRQ\n");
 		res = -ENXIO;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/marvell_nand.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/marvell_nand.c
@@ -707,7 +707,7 @@
 	 * In case the interrupt was not served in the required time frame,
 	 * check if the ISR was not served or if something went actually wrong.
 	 */
-	if (ret && !pending) {
+	if (!ret && !pending) {
 		dev_err(nfc->dev, "Timeout waiting for RB signal\n");
 		return -ETIMEDOUT;
 	}
@@ -1109,6 +1109,7 @@
 		.ndcb[2] = NDCB2_ADDR5_PAGE(page),
 	};
 	unsigned int oob_bytes = lt->spare_bytes + (raw ? lt->ecc_bytes : 0);
+	u8 status;
 	int ret;
 
 	/* NFCv2 needs more information about the operation being executed */
@@ -1142,7 +1143,18 @@
 
 	ret = marvell_nfc_wait_op(chip,
 				  PSEC_TO_MSEC(chip->data_interface.timings.sdr.tPROG_max));
-	return ret;
+	if (ret)
+		return ret;
+
+	/* Check write status on the chip side */
+	ret = nand_status_op(chip, &status);
+	if (ret)
+		return ret;
+
+	if (status & NAND_STATUS_FAIL)
+		return -EIO;
+
+	return 0;
 }
 
 static int marvell_nfc_hw_ecc_hmg_write_page_raw(struct nand_chip *chip,
@@ -1570,6 +1582,7 @@
 	int data_len = lt->data_bytes;
 	int spare_len = lt->spare_bytes;
 	int chunk, ret;
+	u8 status;
 
 	marvell_nfc_select_target(chip, chip->cur_cs);
 
@@ -1607,6 +1620,14 @@
 	if (ret)
 		return ret;
 
+	/* Check write status on the chip side */
+	ret = nand_status_op(chip, &status);
+	if (ret)
+		return ret;
+
+	if (status & NAND_STATUS_FAIL)
+		return -EIO;
+
 	return 0;
 }
 
@@ -2401,6 +2422,12 @@
 			NDTR1_WAIT_MODE;
 	}
 
+	/*
+	 * Reset nfc->selected_chip so the next command will cause the timing
+	 * registers to be updated in marvell_nfc_select_target().
+	 */
+	nfc->selected_chip = NULL;
+
 	return 0;
 }
 
@@ -2630,7 +2657,7 @@
 	chip->controller = &nfc->controller;
 	nand_set_flash_node(chip, np);
 
-	if (!of_property_read_bool(np, "marvell,nand-keep-config"))
+	if (of_property_read_bool(np, "marvell,nand-keep-config"))
 		chip->options |= NAND_KEEP_TIMINGS;
 
 	mtd = nand_to_mtd(chip);
@@ -2664,7 +2691,7 @@
 		ret = mtd_device_register(mtd, NULL, 0);
 	if (ret) {
 		dev_err(dev, "failed to register mtd device: %d\n", ret);
-		nand_release(chip);
+		nand_cleanup(chip);
 		return ret;
 	}
 
@@ -2673,6 +2700,16 @@
 	return 0;
 }
 
+static void marvell_nand_chips_cleanup(struct marvell_nfc *nfc)
+{
+	struct marvell_nand_chip *entry, *temp;
+
+	list_for_each_entry_safe(entry, temp, &nfc->chips, node) {
+		nand_release(&entry->chip);
+		list_del(&entry->node);
+	}
+}
+
 static int marvell_nand_chips_init(struct device *dev, struct marvell_nfc *nfc)
 {
 	struct device_node *np = dev->of_node;
@@ -2707,21 +2744,16 @@
 		ret = marvell_nand_chip_init(dev, nfc, nand_np);
 		if (ret) {
 			of_node_put(nand_np);
-			return ret;
+			goto cleanup_chips;
 		}
 	}
 
 	return 0;
-}
 
-static void marvell_nand_chips_cleanup(struct marvell_nfc *nfc)
-{
-	struct marvell_nand_chip *entry, *temp;
+cleanup_chips:
+	marvell_nand_chips_cleanup(nfc);
 
-	list_for_each_entry_safe(entry, temp, &nfc->chips, node) {
-		nand_release(&entry->chip);
-		list_del(&entry->node);
-	}
+	return ret;
 }
 
 static int marvell_nfc_init_dma(struct marvell_nfc *nfc)
@@ -2823,10 +2855,6 @@
 		regmap_update_bits(sysctrl_base, GENCONF_CLK_GATING_CTRL,
 				   GENCONF_CLK_GATING_CTRL_ND_GATE,
 				   GENCONF_CLK_GATING_CTRL_ND_GATE);
-
-		regmap_update_bits(sysctrl_base, GENCONF_ND_CLK_CTRL,
-				   GENCONF_ND_CLK_CTRL_EN,
-				   GENCONF_ND_CLK_CTRL_EN);
 	}
 
 	/* Configure the DMA if appropriate */
@@ -2975,8 +3003,10 @@
 		return ret;
 
 	ret = clk_prepare_enable(nfc->reg_clk);
-	if (ret < 0)
+	if (ret < 0) {
+		clk_disable_unprepare(nfc->core_clk);
 		return ret;
+	}
 
 	/*
 	 * Reset nfc->selected_chip so the next command will cause the timing
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/meson_nand.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/meson_nand.c
@@ -59,7 +59,7 @@
 #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages)	\
 	(								\
 		(cmd_dir)			|			\
-		((ran) << 19)			|			\
+		(ran)				|			\
 		((bch) << 14)			|			\
 		((short_mode) << 13)		|			\
 		(((page_size) & 0x7f) << 6)	|			\
@@ -72,6 +72,7 @@
 #define GENCMDIADDRH(aih, addr)		((aih) | (((addr) >> 16) & 0xffff))
 
 #define DMA_DIR(dir)		((dir) ? NFC_CMD_N2M : NFC_CMD_M2N)
+#define DMA_ADDR_ALIGN		8
 
 #define ECC_CHECK_RETURN_FF	(-1)
 
@@ -172,6 +173,7 @@
 
 	dma_addr_t daddr;
 	dma_addr_t iaddr;
+	u32 info_bytes;
 
 	unsigned long assigned_cs;
 };
@@ -275,7 +277,7 @@
 
 	if (raw) {
 		len = mtd->writesize + mtd->oobsize;
-		cmd = (len & GENMASK(5, 0)) | scrambler | DMA_DIR(dir);
+		cmd = (len & GENMASK(13, 0)) | scrambler | DMA_DIR(dir);
 		writel(cmd, nfc->reg_base + NFC_REG_CMD);
 		return;
 	}
@@ -454,7 +456,7 @@
 		if (ECC_ERR_CNT(*info) != ECC_UNCORRECTABLE) {
 			mtd->ecc_stats.corrected += ECC_ERR_CNT(*info);
 			*bitflips = max_t(u32, *bitflips, ECC_ERR_CNT(*info));
-			*correct_bitmap |= 1 >> i;
+			*correct_bitmap |= BIT_ULL(i);
 			continue;
 		}
 		if ((nand->options & NAND_NEED_SCRAMBLING) &&
@@ -499,6 +501,7 @@
 					 nfc->daddr, datalen, dir);
 			return ret;
 		}
+		nfc->info_bytes = infolen;
 		cmd = GENCMDIADDRL(NFC_CMD_AIL, nfc->iaddr);
 		writel(cmd, nfc->reg_base + NFC_REG_CMD);
 
@@ -510,14 +513,16 @@
 }
 
 static void meson_nfc_dma_buffer_release(struct nand_chip *nand,
-					 int infolen, int datalen,
+					 int datalen, int infolen,
 					 enum dma_data_direction dir)
 {
 	struct meson_nfc *nfc = nand_get_controller_data(nand);
 
 	dma_unmap_single(nfc->dev, nfc->daddr, datalen, dir);
-	if (infolen)
+	if (infolen) {
 		dma_unmap_single(nfc->dev, nfc->iaddr, infolen, dir);
+		nfc->info_bytes = 0;
+	}
 }
 
 static int meson_nfc_read_buf(struct nand_chip *nand, u8 *buf, int len)
@@ -536,7 +541,7 @@
 	if (ret)
 		goto out;
 
-	cmd = NFC_CMD_N2M | (len & GENMASK(5, 0));
+	cmd = NFC_CMD_N2M | (len & GENMASK(13, 0));
 	writel(cmd, nfc->reg_base + NFC_REG_CMD);
 
 	meson_nfc_drain_cmd(nfc);
@@ -560,7 +565,7 @@
 	if (ret)
 		return ret;
 
-	cmd = NFC_CMD_M2N | (len & GENMASK(5, 0));
+	cmd = NFC_CMD_M2N | (len & GENMASK(13, 0));
 	writel(cmd, nfc->reg_base + NFC_REG_CMD);
 
 	meson_nfc_drain_cmd(nfc);
@@ -706,6 +711,8 @@
 		usleep_range(10, 15);
 		/* info is updated by nfc dma engine*/
 		smp_rmb();
+		dma_sync_single_for_cpu(nfc->dev, nfc->iaddr, nfc->info_bytes,
+					DMA_FROM_DEVICE);
 		ret = *info & ECC_COMPLETE;
 	} while (!ret);
 }
@@ -800,7 +807,7 @@
 			u8 *data = buf + i * ecc->size;
 			u8 *oob = nand->oob_poi + i * (ecc->bytes + 2);
 
-			if (correct_bitmap & (1 << i))
+			if (correct_bitmap & BIT_ULL(i))
 				continue;
 			ret = nand_check_erased_ecc_chunk(data,	ecc->size,
 							  oob, ecc->bytes + 2,
@@ -832,6 +839,9 @@
 
 static bool meson_nfc_is_buffer_dma_safe(const void *buffer)
 {
+	if ((uintptr_t)buffer % DMA_ADDR_ALIGN)
+		return false;
+
 	if (virt_addr_valid(buffer) && (!object_is_on_stack(buffer)))
 		return true;
 	return false;
@@ -1041,9 +1051,12 @@
 
 	ret = clk_set_rate(nfc->device_clk, 24000000);
 	if (ret)
-		goto err_phase_rx;
+		goto err_disable_rx;
 
 	return 0;
+
+err_disable_rx:
+	clk_disable_unprepare(nfc->phase_rx);
 err_phase_rx:
 	clk_disable_unprepare(nfc->phase_tx);
 err_phase_tx:
@@ -1164,7 +1177,6 @@
 	struct meson_nfc *nfc = nand_get_controller_data(nand);
 	struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand);
 	struct mtd_info *mtd = nand_to_mtd(nand);
-	int nsectors = mtd->writesize / 1024;
 	int ret;
 
 	if (!mtd->name) {
@@ -1182,7 +1194,7 @@
 	nand->options |= NAND_NO_SUBPAGE_WRITE;
 
 	ret = nand_ecc_choose_conf(nand, nfc->data->ecc_caps,
-				   mtd->oobsize - 2 * nsectors);
+				   mtd->oobsize - 2);
 	if (ret) {
 		dev_err(nfc->dev, "failed to ECC init\n");
 		return -EINVAL;
@@ -1301,7 +1313,6 @@
 		if (ret)
 			return ret;
 
-		meson_nfc_free_buffer(&meson_chip->nand);
 		nand_cleanup(&meson_chip->nand);
 		list_del(&meson_chip->node);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/mpc5121_nfc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/mpc5121_nfc.c
@@ -290,7 +290,6 @@
 /* Control chips select signal on ADS5121 board */
 static void ads5121_select_chip(struct nand_chip *nand, int chip)
 {
-	struct mtd_info *mtd = nand_to_mtd(nand);
 	struct mpc5121_nfc_prv *prv = nand_get_controller_data(nand);
 	u8 v;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/mtk_ecc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/mtk_ecc.c
@@ -43,6 +43,7 @@
 
 struct mtk_ecc_caps {
 	u32 err_mask;
+	u32 err_shift;
 	const u8 *ecc_strength;
 	const u32 *ecc_regs;
 	u8 num_ecc_strength;
@@ -76,7 +77,7 @@
 };
 
 static const u8 ecc_strength_mt7622[] = {
-	4, 6, 8, 10, 12, 14, 16
+	4, 6, 8, 10, 12
 };
 
 enum mtk_ecc_regs {
@@ -221,7 +222,7 @@
 	for (i = 0; i < sectors; i++) {
 		offset = (i >> 2) << 2;
 		err = readl(ecc->regs + ECC_DECENUM0 + offset);
-		err = err >> ((i % 4) * 8);
+		err = err >> ((i % 4) * ecc->caps->err_shift);
 		err &= ecc->caps->err_mask;
 		if (err == ecc->caps->err_mask) {
 			/* uncorrectable errors */
@@ -449,6 +450,7 @@
 
 static const struct mtk_ecc_caps mtk_ecc_caps_mt2701 = {
 	.err_mask = 0x3f,
+	.err_shift = 8,
 	.ecc_strength = ecc_strength_mt2701,
 	.ecc_regs = mt2701_ecc_regs,
 	.num_ecc_strength = 20,
@@ -459,6 +461,7 @@
 
 static const struct mtk_ecc_caps mtk_ecc_caps_mt2712 = {
 	.err_mask = 0x7f,
+	.err_shift = 8,
 	.ecc_strength = ecc_strength_mt2712,
 	.ecc_regs = mt2712_ecc_regs,
 	.num_ecc_strength = 23,
@@ -468,10 +471,11 @@
 };
 
 static const struct mtk_ecc_caps mtk_ecc_caps_mt7622 = {
-	.err_mask = 0x3f,
+	.err_mask = 0x1f,
+	.err_shift = 5,
 	.ecc_strength = ecc_strength_mt7622,
 	.ecc_regs = mt7622_ecc_regs,
-	.num_ecc_strength = 7,
+	.num_ecc_strength = 5,
 	.ecc_mode_shift = 4,
 	.parity_bits = 13,
 	.pg_irq_sel = 0,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/mtk_nand.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/mtk_nand.c
@@ -1419,7 +1419,7 @@
 	ret = mtd_device_register(mtd, NULL, 0);
 	if (ret) {
 		dev_err(dev, "mtd parse partition error\n");
-		nand_release(nand);
+		nand_cleanup(nand);
 		return ret;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/nand_base.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/nand_base.c
@@ -292,12 +292,16 @@
 	struct mtd_info *mtd = nand_to_mtd(chip);
 	int last_page = ((mtd->erasesize - mtd->writesize) >>
 			 chip->page_shift) & chip->pagemask;
+	unsigned int bbm_flags = NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE
+		| NAND_BBM_LASTPAGE;
 
+	if (page == 0 && !(chip->options & bbm_flags))
+		return 0;
 	if (page == 0 && chip->options & NAND_BBM_FIRSTPAGE)
 		return 0;
-	else if (page <= 1 && chip->options & NAND_BBM_SECONDPAGE)
+	if (page <= 1 && chip->options & NAND_BBM_SECONDPAGE)
 		return 1;
-	else if (page <= last_page && chip->options & NAND_BBM_LASTPAGE)
+	if (page <= last_page && chip->options & NAND_BBM_LASTPAGE)
 		return last_page;
 
 	return -EINVAL;
@@ -355,16 +359,19 @@
  *
  * Return: -EBUSY if the chip has been suspended, 0 otherwise
  */
-static int nand_get_device(struct nand_chip *chip)
+static void nand_get_device(struct nand_chip *chip)
 {
-	mutex_lock(&chip->lock);
-	if (chip->suspended) {
+	/* Wait until the device is resumed. */
+	while (1) {
+		mutex_lock(&chip->lock);
+		if (!chip->suspended) {
+			mutex_lock(&chip->controller->lock);
+			return;
+		}
 		mutex_unlock(&chip->lock);
-		return -EBUSY;
-	}
-	mutex_lock(&chip->controller->lock);
 
-	return 0;
+		wait_event(chip->resume_wq, !chip->suspended);
+	}
 }
 
 /**
@@ -463,9 +470,11 @@
 	 * if we don't do this. I have no clue why, but I seem to have 'fixed'
 	 * it in the doc2000 driver in August 1999.  dwmw2.
 	 */
-	ret = nand_reset(chip, chipnr);
-	if (ret)
-		return ret;
+	if (chip->parameters.onfi->jedec_id == NAND_MFR_TOSHIBA) {
+		ret = nand_reset(chip, chipnr);
+		if (ret)
+			return ret;
+	}
 
 	nand_select_target(chip, chipnr);
 
@@ -589,9 +598,7 @@
 		nand_erase_nand(chip, &einfo, 0);
 
 		/* Write bad block marker to OOB */
-		ret = nand_get_device(chip);
-		if (ret)
-			return ret;
+		nand_get_device(chip);
 
 		ret = nand_markbad_bbm(chip, ofs);
 		nand_release_device(chip);
@@ -727,8 +734,14 @@
 int nand_gpio_waitrdy(struct nand_chip *chip, struct gpio_desc *gpiod,
 		      unsigned long timeout_ms)
 {
-	/* Wait until R/B pin indicates chip is ready or timeout occurs */
-	timeout_ms = jiffies + msecs_to_jiffies(timeout_ms);
+
+	/*
+	 * Wait until R/B pin indicates chip is ready or timeout occurs.
+	 * +1 below is necessary because if we are now in the last fraction
+	 * of jiffy and msecs_to_jiffies is 1 then we will wait only that
+	 * small jiffy fraction - possibly leading to false timeout.
+	 */
+	timeout_ms = jiffies + msecs_to_jiffies(timeout_ms) + 1;
 	do {
 		if (gpiod_get_value_cansleep(gpiod))
 			return 0;
@@ -3566,9 +3579,7 @@
 	    ops->mode != MTD_OPS_RAW)
 		return -ENOTSUPP;
 
-	ret = nand_get_device(chip);
-	if (ret)
-		return ret;
+	nand_get_device(chip);
 
 	if (!ops->datbuf)
 		ret = nand_do_read_oob(chip, from, ops);
@@ -4112,13 +4123,11 @@
 			  struct mtd_oob_ops *ops)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
-	int ret;
+	int ret = 0;
 
 	ops->retlen = 0;
 
-	ret = nand_get_device(chip);
-	if (ret)
-		return ret;
+	nand_get_device(chip);
 
 	switch (ops->mode) {
 	case MTD_OPS_PLACE_OOB:
@@ -4174,9 +4183,7 @@
 		return -EINVAL;
 
 	/* Grab the lock and see if the device is available */
-	ret = nand_get_device(chip);
-	if (ret)
-		return ret;
+	nand_get_device(chip);
 
 	/* Shift to get first page */
 	page = (int)(instr->addr >> chip->page_shift);
@@ -4263,7 +4270,7 @@
 	pr_debug("%s: called\n", __func__);
 
 	/* Grab the lock and see if the device is available */
-	WARN_ON(nand_get_device(chip));
+	nand_get_device(chip);
 	/* Release it and go back */
 	nand_release_device(chip);
 }
@@ -4280,9 +4287,7 @@
 	int ret;
 
 	/* Select the NAND device */
-	ret = nand_get_device(chip);
-	if (ret)
-		return ret;
+	nand_get_device(chip);
 
 	nand_select_target(chip, chipnr);
 
@@ -4344,6 +4349,8 @@
 		pr_err("%s called for a chip which is not in suspended state\n",
 			__func__);
 	mutex_unlock(&chip->lock);
+
+	wake_up_all(&chip->resume_wq);
 }
 
 /**
@@ -5004,6 +5011,7 @@
 	chip->cur_cs = -1;
 
 	mutex_init(&chip->lock);
+	init_waitqueue_head(&chip->resume_wq);
 
 	/* Enforce the right timings for reset/detection */
 	onfi_fill_data_interface(chip, NAND_SDR_IFACE, 0);
@@ -5903,6 +5911,8 @@
 	    chip->ecc.algo == NAND_ECC_BCH)
 		nand_bch_free((struct nand_bch_control *)chip->ecc.priv);
 
+	nanddev_cleanup(&chip->base);
+
 	/* Free bad block table memory */
 	kfree(chip->bbt);
 	kfree(chip->data_buf);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/nand_ecc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/nand_ecc.c
@@ -131,7 +131,7 @@
 	/* rp0..rp15..rp17 are the various accumulated parities (per byte) */
 	uint32_t rp0, rp1, rp2, rp3, rp4, rp5, rp6, rp7;
 	uint32_t rp8, rp9, rp10, rp11, rp12, rp13, rp14, rp15, rp16;
-	uint32_t uninitialized_var(rp17);	/* to make compiler happy */
+	uint32_t rp17;
 	uint32_t par;		/* the cumulative parity for all data */
 	uint32_t tmppar;	/* the cumulative parity for this iteration;
 				   for rp12, rp14 and rp16 at the end of the
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/nand_hynix.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/nand_hynix.c
@@ -402,7 +402,7 @@
 	if (ret)
 		pr_warn("failed to initialize read-retry infrastructure");
 
-	return 0;
+	return ret;
 }
 
 static void hynix_nand_extract_oobsize(struct nand_chip *chip,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/nand_micron.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/nand_micron.c
@@ -446,8 +446,10 @@
 	if (ret)
 		goto err_free_manuf_data;
 
+	chip->options |= NAND_BBM_FIRSTPAGE;
+
 	if (mtd->writesize == 2048)
-		chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
+		chip->options |= NAND_BBM_SECONDPAGE;
 
 	ondie = micron_supports_on_die_ecc(chip);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/nand_onfi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/nand_onfi.c
@@ -173,7 +173,7 @@
 		}
 
 		if (onfi_crc16(ONFI_CRC_BASE, (u8 *)&p[i], 254) ==
-				le16_to_cpu(p->crc)) {
+		    le16_to_cpu(p[i].crc)) {
 			if (i)
 				memcpy(p, &p[i], sizeof(*p));
 			break;
@@ -294,6 +294,8 @@
 	onfi->tR = le16_to_cpu(p->t_r);
 	onfi->tCCS = le16_to_cpu(p->t_ccs);
 	onfi->async_timing_mode = le16_to_cpu(p->async_timing_mode);
+	onfi->jedec_id = le16_to_cpu(p->jedec_id);
+	onfi->src_sync_timing_mode = le16_to_cpu(p->src_sync_timing_mode);
 	onfi->vendor_revision = le16_to_cpu(p->vendor_revision);
 	memcpy(onfi->vendor, p->vendor, sizeof(p->vendor));
 	chip->parameters.onfi = onfi;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/nand_timings.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/nand_timings.c
@@ -314,10 +314,9 @@
 		/* microseconds -> picoseconds */
 		timings->tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX;
 		timings->tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX;
-		timings->tR_max = 1000000ULL * 200000000ULL;
 
-		/* nanoseconds -> picoseconds */
-		timings->tCCS_min = 1000UL * 500000;
+		timings->tR_max = 200000000;
+		timings->tCCS_min = 500000;
 	}
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/omap_elm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/omap_elm.c
@@ -174,17 +174,17 @@
 			switch (info->bch_type) {
 			case BCH8_ECC:
 				/* syndrome fragment 0 = ecc[9-12B] */
-				val = cpu_to_be32(*(u32 *) &ecc[9]);
+				val = (__force u32)cpu_to_be32(*(u32 *)&ecc[9]);
 				elm_write_reg(info, offset, val);
 
 				/* syndrome fragment 1 = ecc[5-8B] */
 				offset += 4;
-				val = cpu_to_be32(*(u32 *) &ecc[5]);
+				val = (__force u32)cpu_to_be32(*(u32 *)&ecc[5]);
 				elm_write_reg(info, offset, val);
 
 				/* syndrome fragment 2 = ecc[1-4B] */
 				offset += 4;
-				val = cpu_to_be32(*(u32 *) &ecc[1]);
+				val = (__force u32)cpu_to_be32(*(u32 *)&ecc[1]);
 				elm_write_reg(info, offset, val);
 
 				/* syndrome fragment 3 = ecc[0B] */
@@ -194,35 +194,35 @@
 				break;
 			case BCH4_ECC:
 				/* syndrome fragment 0 = ecc[20-52b] bits */
-				val = (cpu_to_be32(*(u32 *) &ecc[3]) >> 4) |
+				val = ((__force u32)cpu_to_be32(*(u32 *)&ecc[3]) >> 4) |
 					((ecc[2] & 0xf) << 28);
 				elm_write_reg(info, offset, val);
 
 				/* syndrome fragment 1 = ecc[0-20b] bits */
 				offset += 4;
-				val = cpu_to_be32(*(u32 *) &ecc[0]) >> 12;
+				val = (__force u32)cpu_to_be32(*(u32 *)&ecc[0]) >> 12;
 				elm_write_reg(info, offset, val);
 				break;
 			case BCH16_ECC:
-				val = cpu_to_be32(*(u32 *) &ecc[22]);
+				val = (__force u32)cpu_to_be32(*(u32 *)&ecc[22]);
 				elm_write_reg(info, offset, val);
 				offset += 4;
-				val = cpu_to_be32(*(u32 *) &ecc[18]);
+				val = (__force u32)cpu_to_be32(*(u32 *)&ecc[18]);
 				elm_write_reg(info, offset, val);
 				offset += 4;
-				val = cpu_to_be32(*(u32 *) &ecc[14]);
+				val = (__force u32)cpu_to_be32(*(u32 *)&ecc[14]);
 				elm_write_reg(info, offset, val);
 				offset += 4;
-				val = cpu_to_be32(*(u32 *) &ecc[10]);
+				val = (__force u32)cpu_to_be32(*(u32 *)&ecc[10]);
 				elm_write_reg(info, offset, val);
 				offset += 4;
-				val = cpu_to_be32(*(u32 *) &ecc[6]);
+				val = (__force u32)cpu_to_be32(*(u32 *)&ecc[6]);
 				elm_write_reg(info, offset, val);
 				offset += 4;
-				val = cpu_to_be32(*(u32 *) &ecc[2]);
+				val = (__force u32)cpu_to_be32(*(u32 *)&ecc[2]);
 				elm_write_reg(info, offset, val);
 				offset += 4;
-				val = cpu_to_be32(*(u32 *) &ecc[0]) >> 16;
+				val = (__force u32)cpu_to_be32(*(u32 *)&ecc[0]) >> 16;
 				elm_write_reg(info, offset, val);
 				break;
 			default:
@@ -411,6 +411,7 @@
 	pm_runtime_enable(&pdev->dev);
 	if (pm_runtime_get_sync(&pdev->dev) < 0) {
 		ret = -EINVAL;
+		pm_runtime_put_sync(&pdev->dev);
 		pm_runtime_disable(&pdev->dev);
 		dev_err(&pdev->dev, "can't enable clock\n");
 		return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/orion_nand.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/orion_nand.c
@@ -180,7 +180,7 @@
 	mtd->name = "orion_nand";
 	ret = mtd_device_register(mtd, board->parts, board->nr_parts);
 	if (ret) {
-		nand_release(nc);
+		nand_cleanup(nc);
 		goto no_dev;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/oxnas_nand.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/oxnas_nand.c
@@ -32,6 +32,7 @@
 	void __iomem *io_base;
 	struct clk *clk;
 	struct nand_chip *chips[OXNAS_NAND_MAX_CHIPS];
+	unsigned int nchips;
 };
 
 static uint8_t oxnas_nand_read_byte(struct nand_chip *chip)
@@ -79,9 +80,9 @@
 	struct nand_chip *chip;
 	struct mtd_info *mtd;
 	struct resource *res;
-	int nchips = 0;
 	int count = 0;
 	int err = 0;
+	int i;
 
 	/* Allocate memory for the device structure (and zero it) */
 	oxnas = devm_kzalloc(&pdev->dev, sizeof(*oxnas),
@@ -140,17 +141,15 @@
 			goto err_release_child;
 
 		err = mtd_device_register(mtd, NULL, 0);
-		if (err) {
-			nand_release(chip);
-			goto err_release_child;
-		}
+		if (err)
+			goto err_cleanup_nand;
 
-		oxnas->chips[nchips] = chip;
-		++nchips;
+		oxnas->chips[oxnas->nchips] = chip;
+		++oxnas->nchips;
 	}
 
 	/* Exit if no chips found */
-	if (!nchips) {
+	if (!oxnas->nchips) {
 		err = -ENODEV;
 		goto err_clk_unprepare;
 	}
@@ -159,8 +158,17 @@
 
 	return 0;
 
+err_cleanup_nand:
+	nand_cleanup(chip);
 err_release_child:
 	of_node_put(nand_np);
+
+	for (i = 0; i < oxnas->nchips; i++) {
+		chip = oxnas->chips[i];
+		WARN_ON(mtd_device_unregister(nand_to_mtd(chip)));
+		nand_cleanup(chip);
+	}
+
 err_clk_unprepare:
 	clk_disable_unprepare(oxnas->clk);
 	return err;
@@ -169,9 +177,13 @@
 static int oxnas_nand_remove(struct platform_device *pdev)
 {
 	struct oxnas_nand_ctrl *oxnas = platform_get_drvdata(pdev);
+	struct nand_chip *chip;
+	int i;
 
-	if (oxnas->chips[0])
-		nand_release(oxnas->chips[0]);
+	for (i = 0; i < oxnas->nchips; i++) {
+		chip = oxnas->chips[i];
+		nand_release(chip);
+	}
 
 	clk_disable_unprepare(oxnas->clk);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/pasemi_nand.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/pasemi_nand.c
@@ -146,7 +146,7 @@
 	if (mtd_device_register(pasemi_nand_mtd, NULL, 0)) {
 		dev_err(dev, "Unable to register MTD device\n");
 		err = -ENODEV;
-		goto out_lpc;
+		goto out_cleanup_nand;
 	}
 
 	dev_info(dev, "PA Semi NAND flash at %pR, control at I/O %x\n", &res,
@@ -154,6 +154,8 @@
 
 	return 0;
 
+ out_cleanup_nand:
+	nand_cleanup(chip);
  out_lpc:
 	release_region(lpcctl, 4);
  out_ior:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/pl353_nand.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/pl353_nand.c
@@ -0,0 +1,1232 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ARM PL353 NAND flash controller driver
+ *
+ * Copyright (C) 2017 Xilinx, Inc
+ * Author: Punnaiah chowdary kalluri <punnaiah@xilinx.com>
+ * Author: Naga Sureshkumar Relli <nagasure@xilinx.com>
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/rawnand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/pl353-smc.h>
+#include <linux/clk.h>
+
+#define PL353_NAND_DRIVER_NAME "pl353-nand"
+
+/* NAND flash driver defines */
+#define PL353_NAND_ECC_SIZE	512	/* Size of data for ECC operation */
+
+/* AXI Address definitions */
+#define START_CMD_SHIFT		3
+#define END_CMD_SHIFT		11
+#define END_CMD_VALID_SHIFT	20
+#define ADDR_CYCLES_SHIFT	21
+#define CLEAR_CS_SHIFT		21
+#define ECC_LAST_SHIFT		10
+#define COMMAND_PHASE		(0 << 19)
+#define DATA_PHASE		BIT(19)
+#define GET_ADDR(pos, val)	(((val) & 0xFF) << (8 * (pos)))
+
+#define PL353_NAND_ECC_LAST	BIT(ECC_LAST_SHIFT)	/* Set ECC_Last */
+#define PL353_NAND_CLEAR_CS	BIT(CLEAR_CS_SHIFT)	/* Clear chip select */
+
+#define PL353_NAND_ECC_BUSY_TIMEOUT	(1 * HZ)
+#define PL353_NAND_DEV_BUSY_TIMEOUT	(1 * HZ)
+#define PL353_NAND_LAST_TRANSFER_LENGTH	4
+#define PL353_NAND_ECC_VALID_SHIFT	24
+#define PL353_NAND_ECC_VALID_MASK	0x40
+#define PL353_ECC_BITS_BYTEOFF_MASK	0x1FF
+#define PL353_ECC_BITS_BITOFF_MASK	0x7
+#define PL353_ECC_BIT_MASK		0xFFF
+#define PL353_TREA_MAX_VALUE		1
+#define PL353_MAX_ECC_CHUNKS		4
+#define PL353_MAX_ECC_BYTES		3
+#define PL353_MAX_CHUNK_SIZE		2112
+
+struct pl353_nfc_op {
+	u32 cmnds[2];
+	u32 addrs;
+	unsigned int data_instr_idx;
+	unsigned int rdy_timeout_ms;
+	unsigned int rdy_delay_ns;
+	const struct nand_op_instr *data_instr;
+};
+
+/**
+ * struct pl353_nand_controller - Defines the NAND flash controller driver
+ *				  instance
+ * @controller:		NAND controller structure
+ * @chip:		NAND chip information structure
+ * @dev:		Parent device (used to print error messages)
+ * @regs:		Virtual address of the NAND flash device
+ * @dataphase_addrflags:Flags required for data phase transfers
+ * @addr_cycles:	Address cycles
+ * @mclk_rate:		Clock rate of the Memory controller
+ * @buswidth:		Bus width 8 or 16
+ */
+struct pl353_nand_controller {
+	struct nand_controller controller;
+	struct nand_chip chip;
+	struct device *dev;
+	void __iomem *regs;
+	u32 dataphase_addrflags;
+	u8 addr_cycles;
+	ulong mclk_rate;
+	u32 buswidth;
+};
+
+static inline struct pl353_nand_controller *
+			to_pl353_nand(struct nand_chip *chip)
+{
+	return container_of(chip, struct pl353_nand_controller, chip);
+}
+
+static int pl353_ecc_ooblayout16_ecc(struct mtd_info *mtd, int section,
+				     struct mtd_oob_region *oobregion)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+
+	if (section >= chip->ecc.steps)
+		return -ERANGE;
+
+	oobregion->offset = (section * chip->ecc.bytes);
+	oobregion->length = chip->ecc.bytes;
+
+	return 0;
+}
+
+static int pl353_ecc_ooblayout16_free(struct mtd_info *mtd, int section,
+				      struct mtd_oob_region *oobregion)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+
+	if (section >= chip->ecc.steps)
+		return -ERANGE;
+
+	oobregion->offset = (section * chip->ecc.bytes) + 8;
+	oobregion->length = 8;
+
+	return 0;
+}
+
+static const struct mtd_ooblayout_ops pl353_ecc_ooblayout16_ops = {
+	.ecc = pl353_ecc_ooblayout16_ecc,
+	.free = pl353_ecc_ooblayout16_free,
+};
+
+static int pl353_ecc_ooblayout64_ecc(struct mtd_info *mtd, int section,
+				     struct mtd_oob_region *oobregion)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+
+	if (section >= chip->ecc.steps)
+		return -ERANGE;
+
+	oobregion->offset = (section * chip->ecc.bytes) + 52;
+	oobregion->length = chip->ecc.bytes;
+
+	return 0;
+}
+
+static int pl353_ecc_ooblayout64_free(struct mtd_info *mtd, int section,
+				      struct mtd_oob_region *oobregion)
+{
+	if (section)
+		return -ERANGE;
+
+	oobregion->offset = 2;
+	oobregion->length = 50;
+
+	return 0;
+}
+
+static const struct mtd_ooblayout_ops pl353_ecc_ooblayout64_ops = {
+	.ecc = pl353_ecc_ooblayout64_ecc,
+	.free = pl353_ecc_ooblayout64_free,
+};
+
+/* Generic flash bbt decriptors */
+static u8 bbt_pattern[] = { 'B', 'b', 't', '0' };
+static u8 mirror_pattern[] = { '1', 't', 'b', 'B' };
+
+static struct nand_bbt_descr bbt_main_descr = {
+	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+	.offs = 4,
+	.len = 4,
+	.veroffs = 20,
+	.maxblocks = 4,
+	.pattern = bbt_pattern
+};
+
+static struct nand_bbt_descr bbt_mirror_descr = {
+	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
+		| NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+	.offs = 4,
+	.len = 4,
+	.veroffs = 20,
+	.maxblocks = 4,
+	.pattern = mirror_pattern
+};
+
+static void pl353_nfc_force_byte_access(struct nand_chip *chip,
+					bool force_8bit)
+{
+	int ret;
+	struct pl353_nand_controller *xnfc =
+		container_of(chip, struct pl353_nand_controller, chip);
+
+	if (xnfc->buswidth == 8)
+		return;
+
+	if (force_8bit)
+		ret = pl353_smc_set_buswidth(PL353_SMC_MEM_WIDTH_8);
+	else
+		ret = pl353_smc_set_buswidth(PL353_SMC_MEM_WIDTH_16);
+
+	if (ret)
+		dev_err(xnfc->dev, "Error in Buswidth\n");
+}
+
+static inline int pl353_wait_for_dev_ready(struct nand_chip *chip)
+{
+	unsigned long timeout = jiffies + PL353_NAND_DEV_BUSY_TIMEOUT;
+
+	while (!pl353_smc_get_nand_int_status_raw()) {
+		if (time_after_eq(jiffies, timeout)) {
+			pr_err("%s timed out\n", __func__);
+			return -ETIMEDOUT;
+		}
+		cond_resched();
+	}
+
+	pl353_smc_clr_nand_int();
+
+	return 0;
+}
+
+/**
+ * pl353_nand_read_data_op - read chip data into buffer
+ * @chip:	Pointer to the NAND chip info structure
+ * @in:		Pointer to the buffer to store read data
+ * @len:	Number of bytes to read
+ * @force_8bit:	Force 8-bit bus access
+ * Return:	Always return zero
+ */
+static void pl353_nand_read_data_op(struct nand_chip *chip, u8 *in,
+				    unsigned int len, bool force_8bit)
+{
+	struct pl353_nand_controller *xnfc = to_pl353_nand(chip);
+	int i;
+
+	if (force_8bit)
+		pl353_nfc_force_byte_access(chip, true);
+
+	if ((IS_ALIGNED((uint32_t)in, sizeof(uint32_t)) &&
+	     IS_ALIGNED(len, sizeof(uint32_t))) || !force_8bit) {
+		u32 *ptr = (u32 *)in;
+
+		len /= 4;
+		for (i = 0; i < len; i++)
+			ptr[i] = readl(xnfc->regs + xnfc->dataphase_addrflags);
+	} else {
+		for (i = 0; i < len; i++)
+			in[i] = readb(xnfc->regs + xnfc->dataphase_addrflags);
+	}
+
+	if (force_8bit)
+		pl353_nfc_force_byte_access(chip, false);
+}
+
+/**
+ * pl353_nand_write_data_op - write buffer to chip
+ * @chip:	Pointer to the nand_chip structure
+ * @buf:	Pointer to the buffer to store write data
+ * @len:	Number of bytes to write
+ * @force_8bit:	Force 8-bit bus access
+ */
+static void pl353_nand_write_data_op(struct nand_chip *chip, const u8 *buf,
+				     int len, bool force_8bit)
+{
+	struct pl353_nand_controller *xnfc = to_pl353_nand(chip);
+	int i;
+
+	if (force_8bit)
+		pl353_nfc_force_byte_access(chip, true);
+
+	if ((IS_ALIGNED((uint32_t)buf, sizeof(uint32_t)) &&
+	     IS_ALIGNED(len, sizeof(uint32_t))) || !force_8bit) {
+		u32 *ptr = (u32 *)buf;
+
+		len /= 4;
+		for (i = 0; i < len; i++)
+			writel(ptr[i], xnfc->regs + xnfc->dataphase_addrflags);
+	} else {
+		for (i = 0; i < len; i++)
+			writeb(buf[i], xnfc->regs + xnfc->dataphase_addrflags);
+	}
+
+	if (force_8bit)
+		pl353_nfc_force_byte_access(chip, false);
+}
+
+static inline int pl353_wait_for_ecc_done(void)
+{
+	unsigned long timeout = jiffies + PL353_NAND_ECC_BUSY_TIMEOUT;
+
+	while (pl353_smc_ecc_is_busy()) {
+		if (time_after_eq(jiffies, timeout)) {
+			pr_err("%s timed out\n", __func__);
+			return -ETIMEDOUT;
+		}
+		cond_resched();
+	}
+
+	return 0;
+}
+
+/**
+ * pl353_nand_calculate_hwecc - Calculate Hardware ECC
+ * @chip:	Pointer to the nand_chip structure
+ * @data:	Pointer to the page data
+ * @ecc:	Pointer to the ECC buffer where ECC data needs to be stored
+ *
+ * This function retrieves the Hardware ECC data from the controller and returns
+ * ECC data back to the MTD subsystem.
+ * It operates on a number of 512 byte blocks of NAND memory and can be
+ * programmed to store the ECC codes after the data in memory. For writes,
+ * the ECC is written to the spare area of the page. For reads, the result of
+ * a block ECC check are made available to the device driver.
+ *
+ * ------------------------------------------------------------------------
+ * |               n * 512 blocks                  | extra  | ecc    |     |
+ * |                                               | block  | codes  |     |
+ * ------------------------------------------------------------------------
+ *
+ * The ECC calculation uses a simple Hamming code, using 1-bit correction 2-bit
+ * detection. It starts when a valid read or write command with a 512 byte
+ * aligned address is detected on the memory interface.
+ *
+ * Return:	0 on success or error value on failure
+ */
+static int pl353_nand_calculate_hwecc(struct nand_chip *chip,
+				      const u8 *data, u8 *ecc)
+{
+	u32 ecc_value;
+	u8 chunk, ecc_byte, ecc_status;
+
+	for (chunk = 0; chunk < PL353_MAX_ECC_CHUNKS; chunk++) {
+		/* Read ECC value for each block */
+		ecc_value = pl353_smc_get_ecc_val(chunk);
+		ecc_status = (ecc_value >> PL353_NAND_ECC_VALID_SHIFT);
+
+		/* ECC value valid */
+		if (ecc_status & PL353_NAND_ECC_VALID_MASK) {
+			for (ecc_byte = 0; ecc_byte < PL353_MAX_ECC_BYTES;
+			     ecc_byte++) {
+				/* Copy ECC bytes to MTD buffer */
+				*ecc = ~ecc_value & 0xFF;
+				ecc_value = ecc_value >> 8;
+				ecc++;
+			}
+		} else {
+			pr_warn("%s status failed\n", __func__);
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * pl353_nand_correct_data - ECC correction function
+ * @chip:	Pointer to the nand_chip structure
+ * @buf:	Pointer to the page data
+ * @read_ecc:	Pointer to the ECC value read from spare data area
+ * @calc_ecc:	Pointer to the calculated ECC value
+ *
+ * This function corrects the ECC single bit errors & detects 2-bit errors.
+ *
+ * Return:	0 if no ECC errors found
+ *		1 if single bit error found and corrected.
+ *		-1 if multiple uncorrectable ECC errors found.
+ */
+static int pl353_nand_correct_data(struct nand_chip *chip, unsigned char *buf,
+				   unsigned char *read_ecc,
+				   unsigned char *calc_ecc)
+{
+	unsigned char bit_addr;
+	unsigned int byte_addr;
+	unsigned short ecc_odd, ecc_even, read_ecc_lower, read_ecc_upper;
+	unsigned short calc_ecc_lower, calc_ecc_upper;
+
+	read_ecc_lower = (read_ecc[0] | (read_ecc[1] << 8)) &
+			  PL353_ECC_BIT_MASK;
+	read_ecc_upper = ((read_ecc[1] >> 4) | (read_ecc[2] << 4)) &
+			  PL353_ECC_BIT_MASK;
+
+	calc_ecc_lower = (calc_ecc[0] | (calc_ecc[1] << 8)) &
+			  PL353_ECC_BIT_MASK;
+	calc_ecc_upper = ((calc_ecc[1] >> 4) | (calc_ecc[2] << 4)) &
+			  PL353_ECC_BIT_MASK;
+
+	ecc_odd = read_ecc_lower ^ calc_ecc_lower;
+	ecc_even = read_ecc_upper ^ calc_ecc_upper;
+
+	/* no error */
+	if (!ecc_odd && !ecc_even)
+		return 0;
+
+	if (ecc_odd == (~ecc_even & PL353_ECC_BIT_MASK)) {
+		/* bits [11:3] of error code is byte offset */
+		byte_addr = (ecc_odd >> 3) & PL353_ECC_BITS_BYTEOFF_MASK;
+		/* bits [2:0] of error code is bit offset */
+		bit_addr = ecc_odd & PL353_ECC_BITS_BITOFF_MASK;
+		/* Toggling error bit */
+		buf[byte_addr] ^= (BIT(bit_addr));
+		return 1;
+	}
+
+	/* one error in parity */
+	if (hweight32(ecc_odd | ecc_even) == 1)
+		return 1;
+
+	/* Uncorrectable error */
+	return -1;
+}
+
+static void pl353_prepare_cmd(struct nand_chip *chip,
+			      int page, int column, int start_cmd, int end_cmd,
+			      bool read)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct pl353_nand_controller *xnfc = to_pl353_nand(chip);
+	unsigned long cmd_phase_data = 0;
+	u32 end_cmd_valid = 0, cmdphase_addrflags;
+
+	end_cmd_valid = read ? 1 : 0;
+	cmdphase_addrflags = ((xnfc->addr_cycles
+			      << ADDR_CYCLES_SHIFT) |
+			      (end_cmd_valid << END_CMD_VALID_SHIFT) |
+			      (COMMAND_PHASE) |
+			      (end_cmd << END_CMD_SHIFT) |
+			      (start_cmd << START_CMD_SHIFT));
+
+	/* Get the data phase address */
+	xnfc->dataphase_addrflags = ((0x0 << CLEAR_CS_SHIFT) |
+				(0 << END_CMD_VALID_SHIFT) |
+			  (DATA_PHASE) |
+			  (end_cmd << END_CMD_SHIFT) |
+			  (0x0 << ECC_LAST_SHIFT));
+
+	if (chip->options & NAND_BUSWIDTH_16)
+		column /= 2;
+
+	cmd_phase_data = column;
+	if (mtd->writesize > PL353_NAND_ECC_SIZE) {
+		cmd_phase_data |= page << 16;
+
+		/* Another address cycle for devices > 128MiB */
+		if (chip->options & NAND_ROW_ADDR_3) {
+			writel_relaxed(cmd_phase_data,
+				       xnfc->regs + cmdphase_addrflags);
+			cmd_phase_data = (page >> 16);
+		}
+	} else {
+		cmd_phase_data |= page << 8;
+	}
+
+	writel_relaxed(cmd_phase_data, xnfc->regs + cmdphase_addrflags);
+}
+
+/**
+ * pl353_nand_read_oob - [REPLACEABLE] the most common OOB data read function
+ * @chip:	Pointer to the nand_chip structure
+ * @chip:	Pointer to the nand_chip structure
+ * @page:	Page number to read
+ *
+ * Return:	Always return zero
+ */
+static int pl353_nand_read_oob(struct nand_chip *chip,
+			       int page)
+{
+	struct pl353_nand_controller *xnfc = to_pl353_nand(chip);
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	u8 *p;
+
+	if (mtd->writesize < PL353_NAND_ECC_SIZE)
+		return 0;
+
+	pl353_prepare_cmd(chip, page, mtd->writesize, NAND_CMD_READ0,
+			  NAND_CMD_READSTART, 1);
+	if (pl353_wait_for_dev_ready(chip))
+		return -ETIMEDOUT;
+
+	p = chip->oob_poi;
+	pl353_nand_read_data_op(chip, p,
+				(mtd->oobsize -
+				PL353_NAND_LAST_TRANSFER_LENGTH), false);
+	p += (mtd->oobsize - PL353_NAND_LAST_TRANSFER_LENGTH);
+	xnfc->dataphase_addrflags |= PL353_NAND_CLEAR_CS;
+	pl353_nand_read_data_op(chip, p, PL353_NAND_LAST_TRANSFER_LENGTH,
+				false);
+
+	return 0;
+}
+
+/**
+ * pl353_nand_write_oob - [REPLACEABLE] the most common OOB data write function
+ * @chip:	Pointer to the nand_chip structure
+ * @chip:	Pointer to the NAND chip info structure
+ * @page:	Page number to write
+ *
+ * Return:	Zero on success and EIO on failure
+ */
+static int pl353_nand_write_oob(struct nand_chip *chip,
+				int page)
+{
+	struct pl353_nand_controller *xnfc = to_pl353_nand(chip);
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	const u8 *buf = chip->oob_poi;
+
+	pl353_prepare_cmd(chip, page, mtd->writesize, NAND_CMD_SEQIN,
+			  NAND_CMD_PAGEPROG, 0);
+
+	pl353_nand_write_data_op(chip, buf,
+				 (mtd->oobsize -
+				 PL353_NAND_LAST_TRANSFER_LENGTH), false);
+	buf += (mtd->oobsize - PL353_NAND_LAST_TRANSFER_LENGTH);
+	xnfc->dataphase_addrflags |= PL353_NAND_CLEAR_CS;
+	xnfc->dataphase_addrflags |= (1 << END_CMD_VALID_SHIFT);
+	pl353_nand_write_data_op(chip, buf, PL353_NAND_LAST_TRANSFER_LENGTH,
+				 false);
+	if (pl353_wait_for_dev_ready(chip))
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+/**
+ * pl353_nand_read_page_raw - [Intern] read page data without ecc
+ * @chip:		Pointer to the nand_chip structure
+ * @buf:		Pointer to the data buffer
+ * @oob_required:	Caller requires OOB data read to chip->oob_poi
+ * @page:		Page number to read
+ *
+ * Return:	Always return zero
+ */
+static int pl353_nand_read_page_raw(struct nand_chip *chip,
+				    u8 *buf, int oob_required, int page)
+{
+	struct pl353_nand_controller *xnfc = to_pl353_nand(chip);
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	u8 *p;
+
+	pl353_prepare_cmd(chip, page, 0, NAND_CMD_READ0,
+			  NAND_CMD_READSTART, 1);
+	if (pl353_wait_for_dev_ready(chip))
+		return -ETIMEDOUT;
+	if (!buf)
+		return 0;
+	pl353_nand_read_data_op(chip, buf, mtd->writesize, false);
+	p = chip->oob_poi;
+	pl353_nand_read_data_op(chip, p,
+				(mtd->oobsize -
+				PL353_NAND_LAST_TRANSFER_LENGTH), false);
+	p += (mtd->oobsize - PL353_NAND_LAST_TRANSFER_LENGTH);
+	xnfc->dataphase_addrflags |= PL353_NAND_CLEAR_CS;
+	pl353_nand_read_data_op(chip, p, PL353_NAND_LAST_TRANSFER_LENGTH,
+				false);
+
+	return 0;
+}
+
+/**
+ * pl353_nand_write_page_raw - [Intern] raw page write function
+ * @chip:		Pointer to the nand_chip structure
+ * @buf:		Pointer to the data buffer
+ * @oob_required:	Caller requires OOB data read to chip->oob_poi
+ * @page:		Page number to write
+ *
+ * Return:	Always return zero
+ */
+static int pl353_nand_write_page_raw(struct nand_chip *chip,
+				     const u8 *buf, int oob_required,
+				     int page)
+{
+	struct pl353_nand_controller *xnfc = to_pl353_nand(chip);
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	u8 *p;
+
+	pl353_prepare_cmd(chip, page, 0, NAND_CMD_SEQIN,
+			  NAND_CMD_PAGEPROG, 0);
+	pl353_nand_write_data_op(chip, buf, mtd->writesize, false);
+	p = chip->oob_poi;
+	pl353_nand_write_data_op(chip, p,
+				 (mtd->oobsize -
+				 PL353_NAND_LAST_TRANSFER_LENGTH), false);
+	p += (mtd->oobsize - PL353_NAND_LAST_TRANSFER_LENGTH);
+	xnfc->dataphase_addrflags |= PL353_NAND_CLEAR_CS;
+	xnfc->dataphase_addrflags |= (1 << END_CMD_VALID_SHIFT);
+	pl353_nand_write_data_op(chip, p, PL353_NAND_LAST_TRANSFER_LENGTH,
+				 false);
+	if (pl353_wait_for_dev_ready(chip))
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+/**
+ * nand_write_page_hwecc - Hardware ECC based page write function
+ * @chip:		Pointer to the nand_chip structure
+ * @buf:		Pointer to the data buffer
+ * @oob_required:	Caller requires OOB data read to chip->oob_poi
+ * @page:		Page number to write
+ *
+ * This functions writes data and hardware generated ECC values in to the page.
+ *
+ * Return:	Always return zero
+ */
+static int pl353_nand_write_page_hwecc(struct nand_chip *chip,
+				       const u8 *buf, int oob_required,
+				       int page)
+{
+	int eccsize = chip->ecc.size;
+	int eccsteps = chip->ecc.steps;
+	u8 *ecc_calc = chip->ecc.calc_buf;
+	u8 *oob_ptr;
+	const u8 *p = buf;
+	u32 ret;
+	struct pl353_nand_controller *xnfc = to_pl353_nand(chip);
+	struct mtd_info *mtd = nand_to_mtd(chip);
+
+	pl353_prepare_cmd(chip, page, 0, NAND_CMD_SEQIN,
+			  NAND_CMD_PAGEPROG, 0);
+
+	for ( ; (eccsteps - 1); eccsteps--) {
+		pl353_nand_write_data_op(chip, p, eccsize, false);
+		p += eccsize;
+	}
+
+	pl353_nand_write_data_op(chip, p,
+				 (eccsize - PL353_NAND_LAST_TRANSFER_LENGTH),
+				 false);
+	p += (eccsize - PL353_NAND_LAST_TRANSFER_LENGTH);
+
+	/* Set ECC Last bit to 1 */
+	xnfc->dataphase_addrflags |= PL353_NAND_ECC_LAST;
+	pl353_nand_write_data_op(chip, p, PL353_NAND_LAST_TRANSFER_LENGTH,
+				 false);
+
+	/* Wait till the ECC operation is complete or timeout */
+	ret = pl353_wait_for_ecc_done();
+	if (ret)
+		dev_err(xnfc->dev, "ECC Timeout\n");
+
+	p = buf;
+	ret = chip->ecc.calculate(chip, p, &ecc_calc[0]);
+	if (ret)
+		return ret;
+
+	/* Wait for ECC to be calculated and read the error values */
+	ret = mtd_ooblayout_set_eccbytes(mtd, ecc_calc, chip->oob_poi,
+					 0, chip->ecc.total);
+	if (ret)
+		return ret;
+
+	/* Clear ECC last bit */
+	xnfc->dataphase_addrflags &= ~PL353_NAND_ECC_LAST;
+
+	/* Write the spare area with ECC bytes */
+	oob_ptr = chip->oob_poi;
+	pl353_nand_write_data_op(chip, oob_ptr,
+				 (mtd->oobsize -
+				 PL353_NAND_LAST_TRANSFER_LENGTH), false);
+
+	xnfc->dataphase_addrflags |= PL353_NAND_CLEAR_CS;
+	xnfc->dataphase_addrflags |= (1 << END_CMD_VALID_SHIFT);
+	oob_ptr += (mtd->oobsize - PL353_NAND_LAST_TRANSFER_LENGTH);
+	pl353_nand_write_data_op(chip, oob_ptr, PL353_NAND_LAST_TRANSFER_LENGTH,
+				 false);
+	if (pl353_wait_for_dev_ready(chip))
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+/**
+ * pl353_nand_read_page_hwecc - Hardware ECC based page read function
+ * @chip:		Pointer to the nand_chip structure
+ * @buf:		Pointer to the buffer to store read data
+ * @oob_required:	Caller requires OOB data read to chip->oob_poi
+ * @page:		Page number to read
+ *
+ * This functions reads data and checks the data integrity by comparing
+ * hardware generated ECC values and read ECC values from spare area.
+ * There is a limitation in SMC controller, that we must set ECC LAST on
+ * last data phase access, to tell ECC block not to expect any data further.
+ * Ex:  When number of ECC STEPS are 4, then till 3 we will write to flash
+ * using SMC with HW ECC enabled. And for the last ECC STEP, we will subtract
+ * 4bytes from page size, and will initiate a transfer. And the remaining 4 as
+ * one more transfer with ECC_LAST bit set in NAND data phase register to
+ * notify ECC block not to expect any more data. The last block should be align
+ * with end of 512 byte block. Because of this limitation, we are not using
+ * core routines.
+ *
+ * Return:	0 always and updates ECC operation status in to MTD structure
+ */
+static int pl353_nand_read_page_hwecc(struct nand_chip *chip,
+				      u8 *buf, int oob_required, int page)
+{
+	struct pl353_nand_controller *xnfc = to_pl353_nand(chip);
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	int i, stat, eccsize = chip->ecc.size;
+	int eccbytes = chip->ecc.bytes;
+	int eccsteps = chip->ecc.steps;
+	unsigned int max_bitflips = 0;
+	u8 *p = buf;
+	u8 *ecc_calc = chip->ecc.calc_buf;
+	u8 *ecc = chip->ecc.code_buf;
+	u8 *oob_ptr;
+	u32 ret;
+
+	pl353_prepare_cmd(chip, page, 0, NAND_CMD_READ0,
+			  NAND_CMD_READSTART, 1);
+	if (pl353_wait_for_dev_ready(chip))
+		return -ETIMEDOUT;
+
+	for ( ; (eccsteps - 1); eccsteps--) {
+		pl353_nand_read_data_op(chip, p, eccsize, false);
+		p += eccsize;
+	}
+
+	pl353_nand_read_data_op(chip, p,
+				(eccsize - PL353_NAND_LAST_TRANSFER_LENGTH),
+				false);
+	p += (eccsize - PL353_NAND_LAST_TRANSFER_LENGTH);
+
+	/* Set ECC Last bit to 1 */
+	xnfc->dataphase_addrflags |= PL353_NAND_ECC_LAST;
+	pl353_nand_read_data_op(chip, p, PL353_NAND_LAST_TRANSFER_LENGTH,
+				false);
+
+	/* Wait till the ECC operation is complete or timeout */
+	ret = pl353_wait_for_ecc_done();
+	if (ret)
+		dev_err(xnfc->dev, "ECC Timeout\n");
+
+	/* Read the calculated ECC value */
+	p = buf;
+	ret = chip->ecc.calculate(chip, p, &ecc_calc[0]);
+	if (ret)
+		return ret;
+
+	/* Clear ECC last bit */
+	xnfc->dataphase_addrflags &= ~PL353_NAND_ECC_LAST;
+
+	/* Read the stored ECC value */
+	oob_ptr = chip->oob_poi;
+	pl353_nand_read_data_op(chip, oob_ptr,
+				(mtd->oobsize -
+				PL353_NAND_LAST_TRANSFER_LENGTH), false);
+
+	/* de-assert chip select */
+	xnfc->dataphase_addrflags |= PL353_NAND_CLEAR_CS;
+	oob_ptr += (mtd->oobsize - PL353_NAND_LAST_TRANSFER_LENGTH);
+	pl353_nand_read_data_op(chip, oob_ptr, PL353_NAND_LAST_TRANSFER_LENGTH,
+				false);
+
+	ret = mtd_ooblayout_get_eccbytes(mtd, ecc, chip->oob_poi, 0,
+					 chip->ecc.total);
+	if (ret)
+		return ret;
+
+	eccsteps = chip->ecc.steps;
+	p = buf;
+
+	/* Check ECC error for all blocks and correct if it is correctable */
+	for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+		stat = chip->ecc.correct(chip, p, &ecc[i], &ecc_calc[i]);
+		if (stat < 0) {
+			mtd->ecc_stats.failed++;
+		} else {
+			mtd->ecc_stats.corrected += stat;
+			max_bitflips = max_t(unsigned int, max_bitflips, stat);
+		}
+	}
+
+	return max_bitflips;
+}
+
+static int pl353_nand_exec_op_cmd(struct nand_chip *chip,
+				  const struct nand_subop *subop)
+{
+	struct pl353_nfc_op nfc_op = {};
+	struct pl353_nand_controller *xnfc = to_pl353_nand(chip);
+	unsigned long end_cmd_valid = 0;
+	unsigned int op_id, len;
+	bool reading;
+	u32 cmdphase_addrflags;
+	const struct nand_op_instr *instr = NULL;
+	int i;
+	u32 col = 0, row = 0;
+	u32 naddrs = 0;
+
+	memset(&nfc_op, 0, sizeof(struct pl353_nfc_op));
+	for (op_id = 0; op_id < subop->ninstrs; op_id++) {
+		instr = &subop->instrs[op_id];
+
+		switch (instr->type) {
+		case NAND_OP_CMD_INSTR:
+			if (op_id) {
+				nfc_op.cmnds[1] = instr->ctx.cmd.opcode;
+
+				/*
+				 * end_cmd_valid is set when there is a
+				 * command cycle followed by Address cycle
+				 */
+				if (naddrs)
+					end_cmd_valid = 1;
+			} else {
+				nfc_op.cmnds[0] = instr->ctx.cmd.opcode;
+				end_cmd_valid = 0;
+			}
+
+			break;
+
+		case NAND_OP_ADDR_INSTR:
+			i = nand_subop_get_addr_start_off(subop, op_id);
+			naddrs = nand_subop_get_num_addr_cyc(subop,
+							     op_id);
+			for (i = 0; i < min_t(unsigned int, 4, naddrs); i++)
+				col |= instr->ctx.addr.addrs[i] << (8 * i);
+
+			if (naddrs >= 5)
+				row = instr->ctx.addr.addrs[4];
+
+			if (naddrs >= 6)
+				row |= (instr->ctx.addr.addrs[5] << 8);
+
+			break;
+
+		case NAND_OP_DATA_IN_INSTR:
+		case NAND_OP_DATA_OUT_INSTR:
+			nfc_op.data_instr = instr;
+			nfc_op.data_instr_idx = op_id;
+			break;
+
+		case NAND_OP_WAITRDY_INSTR:
+			nfc_op.rdy_timeout_ms = instr->ctx.waitrdy.timeout_ms;
+			nfc_op.rdy_delay_ns = instr->delay_ns;
+			break;
+		}
+	}
+
+	instr = nfc_op.data_instr;
+	op_id = nfc_op.data_instr_idx;
+
+	/* Clear interrupts */
+	pl353_smc_clr_nand_int();
+
+	cmdphase_addrflags = ((naddrs << ADDR_CYCLES_SHIFT) |
+			 (end_cmd_valid << END_CMD_VALID_SHIFT) |
+			 (COMMAND_PHASE) |
+			 (nfc_op.cmnds[1] << END_CMD_SHIFT) |
+			 (nfc_op.cmnds[0] << START_CMD_SHIFT));
+
+	xnfc->dataphase_addrflags = ((0x0 << CLEAR_CS_SHIFT) |
+			  (0 << END_CMD_VALID_SHIFT) |
+			  (DATA_PHASE) |
+			  (nfc_op.cmnds[0] << END_CMD_SHIFT) |
+			  (0x0 << ECC_LAST_SHIFT));
+
+	if (naddrs >= 2) {
+		writel_relaxed(col, xnfc->regs + cmdphase_addrflags);
+		writel_relaxed(row, xnfc->regs + cmdphase_addrflags);
+	} else {
+		writel_relaxed(col, xnfc->regs + cmdphase_addrflags);
+	}
+
+	if (!nfc_op.data_instr) {
+		if (nfc_op.rdy_timeout_ms) {
+			if (pl353_wait_for_dev_ready(chip))
+				return -ETIMEDOUT;
+		}
+		return 0;
+	}
+
+	reading = (nfc_op.data_instr->type == NAND_OP_DATA_IN_INSTR);
+	len = nand_subop_get_data_len(subop, op_id);
+
+	if (!reading) {
+		pl353_nand_write_data_op(chip, instr->ctx.data.buf.out,
+					 len, instr->ctx.data.force_8bit);
+		if (nfc_op.rdy_timeout_ms) {
+			if (pl353_wait_for_dev_ready(chip))
+				return -ETIMEDOUT;
+		}
+		ndelay(nfc_op.rdy_delay_ns);
+	} else {
+		ndelay(nfc_op.rdy_delay_ns);
+
+		if (nfc_op.rdy_timeout_ms) {
+			if (pl353_wait_for_dev_ready(chip))
+				return -ETIMEDOUT;
+		}
+
+		pl353_nand_read_data_op(chip, instr->ctx.data.buf.in, len,
+					instr->ctx.data.force_8bit);
+	}
+
+	return 0;
+}
+
+static const struct nand_op_parser pl353_nfc_op_parser = NAND_OP_PARSER(
+	NAND_OP_PARSER_PATTERN(pl353_nand_exec_op_cmd,
+		NAND_OP_PARSER_PAT_CMD_ELEM(true),
+		NAND_OP_PARSER_PAT_ADDR_ELEM(true, 7),
+		NAND_OP_PARSER_PAT_CMD_ELEM(true),
+		NAND_OP_PARSER_PAT_WAITRDY_ELEM(true),
+		NAND_OP_PARSER_PAT_DATA_IN_ELEM(true, PL353_MAX_CHUNK_SIZE)),
+	NAND_OP_PARSER_PATTERN(pl353_nand_exec_op_cmd,
+		NAND_OP_PARSER_PAT_CMD_ELEM(true),
+		NAND_OP_PARSER_PAT_ADDR_ELEM(true, 7),
+		NAND_OP_PARSER_PAT_DATA_OUT_ELEM(true, PL353_MAX_CHUNK_SIZE),
+		NAND_OP_PARSER_PAT_CMD_ELEM(true),
+		NAND_OP_PARSER_PAT_WAITRDY_ELEM(true)),
+	NAND_OP_PARSER_PATTERN(pl353_nand_exec_op_cmd,
+		NAND_OP_PARSER_PAT_DATA_OUT_ELEM(false, PL353_MAX_CHUNK_SIZE),
+		NAND_OP_PARSER_PAT_WAITRDY_ELEM(true)),
+	);
+
+static int pl353_nfc_exec_op(struct nand_chip *chip,
+			     const struct nand_operation *op,
+			     bool check_only)
+{
+	return nand_op_parser_exec_op(chip, &pl353_nfc_op_parser,
+					      op, check_only);
+}
+
+/**
+ * pl353_nand_ecc_init - Initialize the ecc information as per the ecc mode
+ * @mtd:	Pointer to the mtd_info structure
+ * @ecc:	Pointer to ECC control structure
+ * @ecc_mode:	ondie ecc status
+ *
+ * This function initializes the ecc block and functional pointers as per the
+ * ecc mode
+ *
+ * Return:	0 on success or negative errno.
+ */
+static int pl353_nand_ecc_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc,
+			       int ecc_mode)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct pl353_nand_controller *xnfc = to_pl353_nand(chip);
+	int ret = 0;
+
+	ecc->read_oob = pl353_nand_read_oob;
+	ecc->write_oob = pl353_nand_write_oob;
+	ecc->write_page_raw = pl353_nand_write_page_raw;
+	ecc->read_page_raw = pl353_nand_read_page_raw;
+
+	if (ecc_mode == NAND_ECC_ON_DIE) {
+		ecc->write_page = pl353_nand_write_page_raw;
+		ecc->read_page = pl353_nand_read_page_raw;
+
+		/*
+		 * On-Die ECC spare bytes offset 8 is used for ECC codes
+		 * Use the BBT pattern descriptors
+		 */
+		chip->bbt_td = &bbt_main_descr;
+		chip->bbt_md = &bbt_mirror_descr;
+		ret = pl353_smc_set_ecc_mode(PL353_SMC_ECCMODE_BYPASS);
+		if (ret)
+			return ret;
+
+	} else {
+		ecc->mode = NAND_ECC_HW;
+
+		/* Hardware ECC generates 3 bytes ECC code for each 512 bytes */
+		ecc->bytes = 3;
+		ecc->strength = 1;
+		ecc->calculate = pl353_nand_calculate_hwecc;
+		ecc->correct = pl353_nand_correct_data;
+		ecc->read_page = pl353_nand_read_page_hwecc;
+		ecc->size = PL353_NAND_ECC_SIZE;
+		ecc->read_page = pl353_nand_read_page_hwecc;
+		ecc->write_page = pl353_nand_write_page_hwecc;
+		pl353_smc_set_ecc_pg_size(mtd->writesize);
+		switch (mtd->writesize) {
+		case SZ_512:
+		case SZ_1K:
+		case SZ_2K:
+			pl353_smc_set_ecc_mode(PL353_SMC_ECCMODE_APB);
+			break;
+		default:
+			ecc->calculate = nand_calculate_ecc;
+			ecc->correct = nand_correct_data;
+			ecc->size = 256;
+			break;
+		}
+
+		if (mtd->oobsize == 16) {
+			mtd_set_ooblayout(mtd, &pl353_ecc_ooblayout16_ops);
+		} else if (mtd->oobsize == 64) {
+			mtd_set_ooblayout(mtd, &pl353_ecc_ooblayout64_ops);
+		} else {
+			dev_err(xnfc->dev, "Unsupported oob Layout\n");
+			ret = -ENXIO;
+		}
+	}
+
+	return ret;
+}
+
+static int pl353_nfc_setup_data_interface(struct nand_chip *chip, int csline,
+					  const struct nand_data_interface
+					  *conf)
+{
+	struct pl353_nand_controller *xnfc = to_pl353_nand(chip);
+	const struct nand_sdr_timings *sdr;
+	u32 timings[7], mckperiodps;
+
+	if (csline == NAND_DATA_IFACE_CHECK_ONLY)
+		return 0;
+
+	sdr = nand_get_sdr_timings(conf);
+	if (IS_ERR(sdr))
+		return PTR_ERR(sdr);
+
+	/*
+	 * SDR timings are given in pico-seconds while NFC timings must be
+	 * expressed in NAND controller clock cycles.
+	 */
+	mckperiodps = NSEC_PER_SEC / xnfc->mclk_rate;
+	mckperiodps *= 1000;
+
+	if (sdr->tRC_min <= 20000)
+		/*
+		 * PL353 SMC needs one extra read cycle in SDR Mode 5
+		 * This is not written anywhere in the datasheet but
+		 * the results observed during testing.
+		 */
+		timings[0] = DIV_ROUND_UP(sdr->tRC_min, mckperiodps) + 1;
+	else
+		timings[0] = DIV_ROUND_UP(sdr->tRC_min, mckperiodps);
+
+	timings[1] = DIV_ROUND_UP(sdr->tWC_min, mckperiodps);
+
+	/*
+	 * For all SDR modes, PL353 SMC needs tREA max value as 1,
+	 * Results observed during testing.
+	 */
+	timings[2] = PL353_TREA_MAX_VALUE;
+	timings[3] = DIV_ROUND_UP(sdr->tWP_min, mckperiodps);
+	timings[4] = DIV_ROUND_UP(sdr->tCLR_min, mckperiodps);
+	timings[5] = DIV_ROUND_UP(sdr->tAR_min, mckperiodps);
+	timings[6] = DIV_ROUND_UP(sdr->tRR_min, mckperiodps);
+	pl353_smc_set_cycles(timings);
+
+	return 0;
+}
+
+static int pl353_nand_attach_chip(struct nand_chip *chip)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct pl353_nand_controller *xnfc = to_pl353_nand(chip);
+	int ret;
+
+	if (chip->options & NAND_BUSWIDTH_16) {
+		ret = pl353_smc_set_buswidth(PL353_SMC_MEM_WIDTH_16);
+		if (ret) {
+			dev_err(xnfc->dev, "Set BusWidth failed\n");
+			return ret;
+		}
+	}
+
+	if (mtd->writesize <= SZ_512)
+		xnfc->addr_cycles = 1;
+	else
+		xnfc->addr_cycles = 2;
+
+	if (chip->options & NAND_ROW_ADDR_3)
+		xnfc->addr_cycles += 3;
+	else
+		xnfc->addr_cycles += 2;
+
+	ret = pl353_nand_ecc_init(mtd, &chip->ecc, chip->ecc.mode);
+	if (ret) {
+		dev_err(xnfc->dev, "ECC init failed\n");
+		return ret;
+	}
+
+	if (!mtd->name) {
+		/*
+		 * If the new bindings are used and the bootloader has not been
+		 * updated to pass a new mtdparts parameter on the cmdline, you
+		 * should define the following property in your NAND node, ie:
+		 *
+		 *	label = "pl353-nand";
+		 *
+		 * This way, mtd->name will be set by the core when
+		 * nand_set_flash_node() is called.
+		 */
+		mtd->name = devm_kasprintf(xnfc->dev, GFP_KERNEL,
+					   "%s", PL353_NAND_DRIVER_NAME);
+		if (!mtd->name) {
+			dev_err(xnfc->dev, "Failed to allocate mtd->name\n");
+			return -ENOMEM;
+		}
+	}
+
+	return 0;
+}
+
+static const struct nand_controller_ops pl353_nand_controller_ops = {
+	.attach_chip = pl353_nand_attach_chip,
+	.exec_op = pl353_nfc_exec_op,
+	.setup_data_interface = pl353_nfc_setup_data_interface,
+};
+
+/**
+ * pl353_nand_probe - Probe method for the NAND driver
+ * @pdev:	Pointer to the platform_device structure
+ *
+ * This function initializes the driver data structures and the hardware.
+ * The NAND driver has dependency with the pl353_smc memory controller
+ * driver for initializing the NAND timing parameters, bus width, ECC modes,
+ * control and status information.
+ *
+ * Return:	0 on success or error value on failure
+ */
+static int pl353_nand_probe(struct platform_device *pdev)
+{
+	struct pl353_nand_controller *xnfc;
+	struct mtd_info *mtd;
+	struct nand_chip *chip;
+	struct resource *res;
+	struct device_node *np, *dn;
+	struct clk *mclk;
+	u32 ret, val = 0;
+
+	xnfc = devm_kzalloc(&pdev->dev, sizeof(*xnfc), GFP_KERNEL);
+	if (!xnfc)
+		return -ENOMEM;
+
+	xnfc->dev = &pdev->dev;
+	nand_controller_init(&xnfc->controller);
+	xnfc->controller.ops = &pl353_nand_controller_ops;
+
+	/* Map physical address of NAND flash */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	xnfc->regs = devm_ioremap_resource(xnfc->dev, res);
+	if (IS_ERR(xnfc->regs))
+		return PTR_ERR(xnfc->regs);
+
+	chip = &xnfc->chip;
+	chip->controller = &xnfc->controller;
+	mtd = nand_to_mtd(chip);
+	nand_set_controller_data(chip, xnfc);
+	mtd->priv = chip;
+	mtd->owner = THIS_MODULE;
+	nand_set_flash_node(chip, xnfc->dev->of_node);
+
+	np = of_get_next_parent(xnfc->dev->of_node);
+	mclk = of_clk_get_by_name(np, "memclk");
+	if (IS_ERR(mclk)) {
+		dev_err(xnfc->dev, "Failed to retrieve MCK clk\n");
+		return PTR_ERR(mclk);
+	}
+
+	xnfc->mclk_rate = clk_get_rate(mclk);
+	dn = nand_get_flash_node(chip);
+	ret = of_property_read_u32(dn, "nand-bus-width", &val);
+	if (ret)
+		val = 8;
+
+	xnfc->buswidth = val;
+
+	/* Set the device option and flash width */
+	chip->options = NAND_BUSWIDTH_AUTO;
+	chip->bbt_options = NAND_BBT_USE_FLASH;
+	platform_set_drvdata(pdev, xnfc);
+	ret = nand_scan(chip, 1);
+	if (ret) {
+		dev_err(xnfc->dev, "could not scan the nand chip\n");
+		return ret;
+	}
+
+	ret = mtd_device_register(mtd, NULL, 0);
+	if (ret) {
+		dev_err(xnfc->dev, "Failed to register mtd device: %d\n", ret);
+		nand_cleanup(chip);
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * pl353_nand_remove - Remove method for the NAND driver
+ * @pdev:	Pointer to the platform_device structure
+ *
+ * This function is called if the driver module is being unloaded. It frees all
+ * resources allocated to the device.
+ *
+ * Return:	0 on success or error value on failure
+ */
+static int pl353_nand_remove(struct platform_device *pdev)
+{
+	struct pl353_nand_controller *xnfc = platform_get_drvdata(pdev);
+	struct mtd_info *mtd = nand_to_mtd(&xnfc->chip);
+	struct nand_chip *chip = mtd_to_nand(mtd);
+
+	/* Release resources, unregister device */
+	nand_release(chip);
+
+	return 0;
+}
+
+/* Match table for device tree binding */
+static const struct of_device_id pl353_nand_of_match[] = {
+	{ .compatible = "arm,pl353-nand-r2p1" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, pl353_nand_of_match);
+
+/*
+ * pl353_nand_driver - This structure defines the NAND subsystem platform driver
+ */
+static struct platform_driver pl353_nand_driver = {
+	.probe		= pl353_nand_probe,
+	.remove		= pl353_nand_remove,
+	.driver		= {
+		.name	= PL353_NAND_DRIVER_NAME,
+		.of_match_table = pl353_nand_of_match,
+	},
+};
+
+module_platform_driver(pl353_nand_driver);
+
+MODULE_AUTHOR("Xilinx, Inc.");
+MODULE_ALIAS("platform:" PL353_NAND_DRIVER_NAME);
+MODULE_DESCRIPTION("ARM PL353 NAND Flash Driver");
+MODULE_LICENSE("GPL");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/plat_nand.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/plat_nand.c
@@ -92,7 +92,7 @@
 	if (!err)
 		return err;
 
-	nand_release(&data->chip);
+	nand_cleanup(&data->chip);
 out:
 	if (pdata->ctrl.remove)
 		pdata->ctrl.remove(pdev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/qcom_nandc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/qcom_nandc.c
@@ -2,7 +2,6 @@
 /*
  * Copyright (c) 2016, The Linux Foundation. All rights reserved.
  */
-
 #include <linux/clk.h>
 #include <linux/slab.h>
 #include <linux/bitops.h>
@@ -459,11 +458,13 @@
  * among different NAND controllers.
  * @ecc_modes - ecc mode for NAND
  * @is_bam - whether NAND controller is using BAM
+ * @is_qpic - whether NAND CTRL is part of qpic IP
  * @dev_cmd_reg_start - NAND_DEV_CMD_* registers starting offset
  */
 struct qcom_nandc_props {
 	u32 ecc_modes;
 	bool is_bam;
+	bool is_qpic;
 	u32 dev_cmd_reg_start;
 };
 
@@ -1568,6 +1569,8 @@
 	struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
 	int i;
 
+	nandc_read_buffer_sync(nandc, true);
+
 	for (i = 0; i < cw_cnt; i++) {
 		u32 flash = le32_to_cpu(nandc->reg_read_buf[i]);
 
@@ -2751,7 +2754,8 @@
 	u32 nand_ctrl;
 
 	/* kill onenand */
-	nandc_write(nandc, SFLASHC_BURST_CFG, 0);
+	if (!nandc->props->is_qpic)
+		nandc_write(nandc, SFLASHC_BURST_CFG, 0);
 	nandc_write(nandc, dev_cmd_reg_addr(nandc, NAND_DEV_CMD_VLD),
 		    NAND_DEV_CMD_VLD_VAL);
 
@@ -2845,7 +2849,7 @@
 	struct device *dev = nandc->dev;
 	struct device_node *dn = dev->of_node, *child;
 	struct qcom_nand_host *host;
-	int ret;
+	int ret = -ENODEV;
 
 	for_each_available_child_of_node(dn, child) {
 		host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
@@ -2863,10 +2867,7 @@
 		list_add_tail(&host->node, &nandc->host_list);
 	}
 
-	if (list_empty(&nandc->host_list))
-		return -ENODEV;
-
-	return 0;
+	return ret;
 }
 
 /* parse custom DT properties here */
@@ -2942,10 +2943,6 @@
 	if (!nandc->base_dma)
 		return -ENXIO;
 
-	ret = qcom_nandc_alloc(nandc);
-	if (ret)
-		goto err_nandc_alloc;
-
 	ret = clk_prepare_enable(nandc->core_clk);
 	if (ret)
 		goto err_core_clk;
@@ -2954,6 +2951,10 @@
 	if (ret)
 		goto err_aon_clk;
 
+	ret = qcom_nandc_alloc(nandc);
+	if (ret)
+		goto err_nandc_alloc;
+
 	ret = qcom_nandc_setup(nandc);
 	if (ret)
 		goto err_setup;
@@ -2965,15 +2966,14 @@
 	return 0;
 
 err_setup:
+	qcom_nandc_unalloc(nandc);
+err_nandc_alloc:
 	clk_disable_unprepare(nandc->aon_clk);
 err_aon_clk:
 	clk_disable_unprepare(nandc->core_clk);
 err_core_clk:
-	qcom_nandc_unalloc(nandc);
-err_nandc_alloc:
-	dma_unmap_resource(dev, res->start, resource_size(res),
+	dma_unmap_resource(dev, nandc->base_dma, resource_size(res),
 			   DMA_BIDIRECTIONAL, 0);
-
 	return ret;
 }
 
@@ -3007,12 +3007,14 @@
 static const struct qcom_nandc_props ipq4019_nandc_props = {
 	.ecc_modes = (ECC_BCH_4BIT | ECC_BCH_8BIT),
 	.is_bam = true,
+	.is_qpic = true,
 	.dev_cmd_reg_start = 0x0,
 };
 
 static const struct qcom_nandc_props ipq8074_nandc_props = {
 	.ecc_modes = (ECC_BCH_4BIT | ECC_BCH_8BIT),
 	.is_bam = true,
+	.is_qpic = true,
 	.dev_cmd_reg_start = 0x7000,
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/s3c2410.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/s3c2410.c
@@ -291,7 +291,7 @@
 	int tacls_max = (info->cpu_type == TYPE_S3C2412) ? 8 : 4;
 	int tacls, twrph0, twrph1;
 	unsigned long clkrate = clk_get_rate(info->clk);
-	unsigned long uninitialized_var(set), cfg, uninitialized_var(mask);
+	unsigned long set, cfg, mask;
 	unsigned long flags;
 
 	/* calculate the timing information for the controller */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/sh_flctl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/sh_flctl.c
@@ -384,7 +384,8 @@
 	dma_addr_t dma_addr;
 	dma_cookie_t cookie;
 	uint32_t reg;
-	int ret;
+	int ret = 0;
+	unsigned long time_left;
 
 	if (dir == DMA_FROM_DEVICE) {
 		chan = flctl->chan_fifo0_rx;
@@ -425,13 +426,14 @@
 		goto out;
 	}
 
-	ret =
+	time_left =
 	wait_for_completion_timeout(&flctl->dma_complete,
 				msecs_to_jiffies(3000));
 
-	if (ret <= 0) {
+	if (time_left == 0) {
 		dmaengine_terminate_all(chan);
 		dev_err(&flctl->pdev->dev, "wait_for_completion_timeout\n");
+		ret = -ETIMEDOUT;
 	}
 
 out:
@@ -441,7 +443,7 @@
 
 	dma_unmap_single(chan->device->dev, dma_addr, len, dir);
 
-	/* ret > 0 is success */
+	/* ret == 0 is success */
 	return ret;
 }
 
@@ -465,7 +467,7 @@
 
 	/* initiate DMA transfer */
 	if (flctl->chan_fifo0_rx && rlen >= 32 &&
-		flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_FROM_DEVICE) > 0)
+		!flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_FROM_DEVICE))
 			goto convert;	/* DMA success */
 
 	/* do polling transfer */
@@ -524,7 +526,7 @@
 
 	/* initiate DMA transfer */
 	if (flctl->chan_fifo0_tx && rlen >= 32 &&
-		flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_TO_DEVICE) > 0)
+		!flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_TO_DEVICE))
 			return;	/* DMA success */
 
 	/* do polling transfer */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/sharpsl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/sharpsl.c
@@ -183,7 +183,7 @@
 	return 0;
 
 err_add:
-	nand_release(this);
+	nand_cleanup(this);
 
 err_scan:
 	iounmap(sharpsl->io);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/socrates_nand.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/socrates_nand.c
@@ -169,7 +169,7 @@
 	if (!res)
 		return res;
 
-	nand_release(nand_chip);
+	nand_cleanup(nand_chip);
 
 out:
 	iounmap(host->io_base);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -37,6 +37,7 @@
 /* Max ECC buffer length */
 #define FMC2_MAX_ECC_BUF_LEN		(FMC2_BCHDSRS_LEN * FMC2_MAX_SG)
 
+#define FMC2_TIMEOUT_US			1000
 #define FMC2_TIMEOUT_MS			1000
 
 /* Timings */
@@ -53,6 +54,8 @@
 #define FMC2_PMEM			0x88
 #define FMC2_PATT			0x8c
 #define FMC2_HECCR			0x94
+#define FMC2_ISR			0x184
+#define FMC2_ICR			0x188
 #define FMC2_CSQCR			0x200
 #define FMC2_CSQCFGR1			0x204
 #define FMC2_CSQCFGR2			0x208
@@ -118,6 +121,12 @@
 #define FMC2_PATT_ATTHIZ(x)		(((x) & 0xff) << 24)
 #define FMC2_PATT_DEFAULT		0x0a0a0a0a
 
+/* Register: FMC2_ISR */
+#define FMC2_ISR_IHLF			BIT(1)
+
+/* Register: FMC2_ICR */
+#define FMC2_ICR_CIHLF			BIT(1)
+
 /* Register: FMC2_CSQCR */
 #define FMC2_CSQCR_CSQSTART		BIT(0)
 
@@ -1322,6 +1331,31 @@
 		stm32_fmc2_set_buswidth_16(fmc2, true);
 }
 
+static int stm32_fmc2_waitrdy(struct nand_chip *chip, unsigned long timeout_ms)
+{
+	struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+	const struct nand_sdr_timings *timings;
+	u32 isr, sr;
+
+	/* Check if there is no pending requests to the NAND flash */
+	if (readl_relaxed_poll_timeout_atomic(fmc2->io_base + FMC2_SR, sr,
+					      sr & FMC2_SR_NWRF, 1,
+					      FMC2_TIMEOUT_US))
+		dev_warn(fmc2->dev, "Waitrdy timeout\n");
+
+	/* Wait tWB before R/B# signal is low */
+	timings = nand_get_sdr_timings(&chip->data_interface);
+	ndelay(PSEC_TO_NSEC(timings->tWB_max));
+
+	/* R/B# signal is low, clear high level flag */
+	writel_relaxed(FMC2_ICR_CIHLF, fmc2->io_base + FMC2_ICR);
+
+	/* Wait R/B# signal is high */
+	return readl_relaxed_poll_timeout_atomic(fmc2->io_base + FMC2_ISR,
+						 isr, isr & FMC2_ISR_IHLF,
+						 5, 1000 * timeout_ms);
+}
+
 static int stm32_fmc2_exec_op(struct nand_chip *chip,
 			      const struct nand_operation *op,
 			      bool check_only)
@@ -1366,8 +1400,8 @@
 			break;
 
 		case NAND_OP_WAITRDY_INSTR:
-			ret = nand_soft_waitrdy(chip,
-						instr->ctx.waitrdy.timeout_ms);
+			ret = stm32_fmc2_waitrdy(chip,
+						 instr->ctx.waitrdy.timeout_ms);
 			break;
 		}
 	}
@@ -1558,6 +1592,9 @@
 	if (IS_ERR(sdrt))
 		return PTR_ERR(sdrt);
 
+	if (sdrt->tRC_min < 30000)
+		return -EOPNOTSUPP;
+
 	if (chipnr == NAND_DATA_IFACE_CHECK_ONLY)
 		return 0;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/sunxi_nand.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/sunxi_nand.c
@@ -1587,7 +1587,7 @@
 	if (section < ecc->steps)
 		oobregion->length = 4;
 	else
-		oobregion->offset = mtd->oobsize - oobregion->offset;
+		oobregion->length = mtd->oobsize - oobregion->offset;
 
 	return 0;
 }
@@ -2003,7 +2003,7 @@
 	ret = mtd_device_register(mtd, NULL, 0);
 	if (ret) {
 		dev_err(dev, "failed to register mtd device: %d\n", ret);
-		nand_release(nand);
+		nand_cleanup(nand);
 		return ret;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/tmio_nand.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/tmio_nand.c
@@ -448,7 +448,7 @@
 	if (!retval)
 		return retval;
 
-	nand_release(nand_chip);
+	nand_cleanup(nand_chip);
 
 err_irq:
 	tmio_hw_stop(dev, tmio);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/vf610_nfc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/vf610_nfc.c
@@ -850,8 +850,10 @@
 	}
 
 	of_id = of_match_device(vf610_nfc_dt_ids, &pdev->dev);
-	if (!of_id)
-		return -ENODEV;
+	if (!of_id) {
+		err = -ENODEV;
+		goto err_disable_clk;
+	}
 
 	nfc->variant = (enum vf610_nfc_variant)of_id->data;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/raw/xway_nand.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/raw/xway_nand.c
@@ -210,7 +210,7 @@
 
 	err = mtd_device_register(mtd, NULL, 0);
 	if (err)
-		nand_release(&data->chip);
+		nand_cleanup(&data->chip);
 
 	return err;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/spi/core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/spi/core.c
@@ -568,18 +568,18 @@
 static bool spinand_isbad(struct nand_device *nand, const struct nand_pos *pos)
 {
 	struct spinand_device *spinand = nand_to_spinand(nand);
+	u8 marker[2] = { };
 	struct nand_page_io_req req = {
 		.pos = *pos,
-		.ooblen = 2,
+		.ooblen = sizeof(marker),
 		.ooboffs = 0,
-		.oobbuf.in = spinand->oobbuf,
+		.oobbuf.in = marker,
 		.mode = MTD_OPS_RAW,
 	};
 
-	memset(spinand->oobbuf, 0, 2);
 	spinand_select_target(spinand, pos->target);
 	spinand_read_page(spinand, &req, false);
-	if (spinand->oobbuf[0] != 0xff || spinand->oobbuf[1] != 0xff)
+	if (marker[0] != 0xff || marker[1] != 0xff)
 		return true;
 
 	return false;
@@ -603,15 +603,16 @@
 static int spinand_markbad(struct nand_device *nand, const struct nand_pos *pos)
 {
 	struct spinand_device *spinand = nand_to_spinand(nand);
+	u8 marker[2] = { };
 	struct nand_page_io_req req = {
 		.pos = *pos,
 		.ooboffs = 0,
-		.ooblen = 2,
-		.oobbuf.out = spinand->oobbuf,
+		.ooblen = sizeof(marker),
+		.oobbuf.out = marker,
+		.mode = MTD_OPS_RAW,
 	};
 	int ret;
 
-	/* Erase block before marking it bad. */
 	ret = spinand_select_target(spinand, pos->target);
 	if (ret)
 		return ret;
@@ -620,9 +621,6 @@
 	if (ret)
 		return ret;
 
-	spinand_erase_op(spinand, pos);
-
-	memset(spinand->oobbuf, 0, 2);
 	return spinand_write_page(spinand, &req);
 }
 
@@ -1051,6 +1049,10 @@
 
 	mtd->oobavail = ret;
 
+	/* Propagate ECC information to mtd_info */
+	mtd->ecc_strength = nand->eccreq.strength;
+	mtd->ecc_step_size = nand->eccreq.step_size;
+
 	return 0;
 
 err_cleanup_nanddev:
@@ -1131,12 +1133,14 @@
 	{ .name = "spi-nand" },
 	{ /* sentinel */ },
 };
+MODULE_DEVICE_TABLE(spi, spinand_ids);
 
 #ifdef CONFIG_OF
 static const struct of_device_id spinand_of_ids[] = {
 	{ .compatible = "spi-nand" },
 	{ /* sentinel */ },
 };
+MODULE_DEVICE_TABLE(of, spinand_of_ids);
 #endif
 
 static struct spi_mem_driver spinand_drv = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/spi/gigadevice.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/spi/gigadevice.c
@@ -21,7 +21,7 @@
 #define GD5FXGQ4UXFXXG_STATUS_ECC_UNCOR_ERROR	(7 << 4)
 
 static SPINAND_OP_VARIANTS(read_cache_variants,
-		SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
+		SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 1, NULL, 0),
 		SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
 		SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
 		SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0),
@@ -29,7 +29,7 @@
 		SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
 
 static SPINAND_OP_VARIANTS(read_cache_variants_f,
-		SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
+		SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 1, NULL, 0),
 		SPINAND_PAGE_READ_FROM_CACHE_X4_OP_3A(0, 1, NULL, 0),
 		SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
 		SPINAND_PAGE_READ_FROM_CACHE_X2_OP_3A(0, 1, NULL, 0),
@@ -201,7 +201,7 @@
 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
 					      &write_cache_variants,
 					      &update_cache_variants),
-		     0,
+		     SPINAND_HAS_QE_BIT,
 		     SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
 				     gd5fxgq4xa_ecc_get_status)),
 	SPINAND_INFO("GD5F2GQ4xA", 0xF2,
@@ -210,7 +210,7 @@
 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
 					      &write_cache_variants,
 					      &update_cache_variants),
-		     0,
+		     SPINAND_HAS_QE_BIT,
 		     SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
 				     gd5fxgq4xa_ecc_get_status)),
 	SPINAND_INFO("GD5F4GQ4xA", 0xF4,
@@ -219,7 +219,7 @@
 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
 					      &write_cache_variants,
 					      &update_cache_variants),
-		     0,
+		     SPINAND_HAS_QE_BIT,
 		     SPINAND_ECCINFO(&gd5fxgq4xa_ooblayout,
 				     gd5fxgq4xa_ecc_get_status)),
 	SPINAND_INFO("GD5F1GQ4UExxG", 0xd1,
@@ -228,7 +228,7 @@
 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
 					      &write_cache_variants,
 					      &update_cache_variants),
-		     0,
+		     SPINAND_HAS_QE_BIT,
 		     SPINAND_ECCINFO(&gd5fxgq4_variant2_ooblayout,
 				     gd5fxgq4uexxg_ecc_get_status)),
 	SPINAND_INFO("GD5F1GQ4UFxxG", 0xb148,
@@ -237,7 +237,7 @@
 		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_f,
 					      &write_cache_variants,
 					      &update_cache_variants),
-		     0,
+		     SPINAND_HAS_QE_BIT,
 		     SPINAND_ECCINFO(&gd5fxgq4_variant2_ooblayout,
 				     gd5fxgq4ufxxg_ecc_get_status)),
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/spi/macronix.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/spi/macronix.c
@@ -116,6 +116,121 @@
 					      &update_cache_variants),
 		     SPINAND_HAS_QE_BIT,
 		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
+	SPINAND_INFO("MX35LF2GE4AD", 0x26,
+		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),
+		     NAND_ECCREQ(8, 512),
+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+					      &write_cache_variants,
+					      &update_cache_variants),
+		     SPINAND_HAS_QE_BIT,
+		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
+	SPINAND_INFO("MX35LF4GE4AD", 0x37,
+		     NAND_MEMORG(1, 4096, 128, 64, 2048, 40, 1, 1, 1),
+		     NAND_ECCREQ(8, 512),
+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+					      &write_cache_variants,
+					      &update_cache_variants),
+		     SPINAND_HAS_QE_BIT,
+		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
+	SPINAND_INFO("MX35LF2G14AC", 0x20,
+		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 2, 1, 1),
+		     NAND_ECCREQ(4, 512),
+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+					      &write_cache_variants,
+					      &update_cache_variants),
+		     SPINAND_HAS_QE_BIT,
+		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
+				     mx35lf1ge4ab_ecc_get_status)),
+	SPINAND_INFO("MX35UF4G24AD", 0xb5,
+		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 2, 1, 1),
+		     NAND_ECCREQ(8, 512),
+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+					      &write_cache_variants,
+					      &update_cache_variants),
+		     SPINAND_HAS_QE_BIT,
+		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
+				     mx35lf1ge4ab_ecc_get_status)),
+	SPINAND_INFO("MX35UF4GE4AD", 0xb7,
+		     NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
+		     NAND_ECCREQ(8, 512),
+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+					      &write_cache_variants,
+					      &update_cache_variants),
+		     SPINAND_HAS_QE_BIT,
+		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
+				     mx35lf1ge4ab_ecc_get_status)),
+	SPINAND_INFO("MX35UF2G14AC", 0xa0,
+		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 2, 1, 1),
+		     NAND_ECCREQ(4, 512),
+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+					      &write_cache_variants,
+					      &update_cache_variants),
+		     SPINAND_HAS_QE_BIT,
+		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
+				     mx35lf1ge4ab_ecc_get_status)),
+	SPINAND_INFO("MX35UF2G24AD", 0xa4,
+		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1),
+		     NAND_ECCREQ(8, 512),
+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+					      &write_cache_variants,
+					      &update_cache_variants),
+		     SPINAND_HAS_QE_BIT,
+		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
+				     mx35lf1ge4ab_ecc_get_status)),
+	SPINAND_INFO("MX35UF2GE4AD", 0xa6,
+		     NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
+		     NAND_ECCREQ(8, 512),
+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+					      &write_cache_variants,
+					      &update_cache_variants),
+		     SPINAND_HAS_QE_BIT,
+		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
+				     mx35lf1ge4ab_ecc_get_status)),
+	SPINAND_INFO("MX35UF2GE4AC", 0xa2,
+		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),
+		     NAND_ECCREQ(4, 512),
+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+					      &write_cache_variants,
+					      &update_cache_variants),
+		     SPINAND_HAS_QE_BIT,
+		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
+				     mx35lf1ge4ab_ecc_get_status)),
+	SPINAND_INFO("MX35UF1G14AC", 0x90,
+		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
+		     NAND_ECCREQ(4, 512),
+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+					      &write_cache_variants,
+					      &update_cache_variants),
+		     SPINAND_HAS_QE_BIT,
+		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
+				     mx35lf1ge4ab_ecc_get_status)),
+	SPINAND_INFO("MX35UF1G24AD", 0x94,
+		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
+		     NAND_ECCREQ(8, 512),
+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+					      &write_cache_variants,
+					      &update_cache_variants),
+		     SPINAND_HAS_QE_BIT,
+		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
+				     mx35lf1ge4ab_ecc_get_status)),
+	SPINAND_INFO("MX35UF1GE4AD", 0x96,
+		     NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
+		     NAND_ECCREQ(8, 512),
+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+					      &write_cache_variants,
+					      &update_cache_variants),
+		     SPINAND_HAS_QE_BIT,
+		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
+				     mx35lf1ge4ab_ecc_get_status)),
+	SPINAND_INFO("MX35UF1GE4AC", 0x92,
+		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
+		     NAND_ECCREQ(4, 512),
+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+					      &write_cache_variants,
+					      &update_cache_variants),
+		     SPINAND_HAS_QE_BIT,
+		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
+				     mx35lf1ge4ab_ecc_get_status)),
 };
 
 static int macronix_spinand_detect(struct spinand_device *spinand)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/spi/micron.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/spi/micron.c
@@ -12,7 +12,7 @@
 
 #define SPINAND_MFR_MICRON		0x2c
 
-#define MICRON_STATUS_ECC_MASK		GENMASK(7, 4)
+#define MICRON_STATUS_ECC_MASK		GENMASK(6, 4)
 #define MICRON_STATUS_ECC_NO_BITFLIPS	(0 << 4)
 #define MICRON_STATUS_ECC_1TO3_BITFLIPS	(1 << 4)
 #define MICRON_STATUS_ECC_4TO6_BITFLIPS	(3 << 4)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/nand/spi/toshiba.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/nand/spi/toshiba.c
@@ -60,7 +60,7 @@
 {
 	struct nand_device *nand = spinand_to_nand(spinand);
 	u8 mbf = 0;
-	struct spi_mem_op op = SPINAND_GET_FEATURE_OP(0x30, &mbf);
+	struct spi_mem_op op = SPINAND_GET_FEATURE_OP(0x30, spinand->scratchbuf);
 
 	switch (status & STATUS_ECC_MASK) {
 	case STATUS_ECC_NO_BITFLIPS:
@@ -79,7 +79,7 @@
 		if (spi_mem_exec_op(spinand->spimem, &op))
 			return nand->eccreq.strength;
 
-		mbf >>= 4;
+		mbf = *(spinand->scratchbuf) >> 4;
 
 		if (WARN_ON(mbf > nand->eccreq.strength || !mbf))
 			return nand->eccreq.strength;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/parsers/afs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/parsers/afs.c
@@ -126,8 +126,8 @@
 	 * Static checks cannot see that we bail out if we have an error
 	 * reading the footer.
 	 */
-	u_int uninitialized_var(iis_ptr);
-	u_int uninitialized_var(img_ptr);
+	u_int iis_ptr;
+	u_int img_ptr;
 	u_int ptr;
 	size_t sz;
 	int ret;
@@ -370,10 +370,8 @@
 	return i;
 
 out_free_parts:
-	while (i >= 0) {
+	while (--i >= 0)
 		kfree(parts[i].name);
-		i--;
-	}
 	kfree(parts);
 	*pparts = NULL;
 	return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/parsers/cmdlinepart.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/parsers/cmdlinepart.c
@@ -218,12 +218,41 @@
 		struct cmdline_mtd_partition *this_mtd;
 		struct mtd_partition *parts;
 		int mtd_id_len, num_parts;
-		char *p, *mtd_id;
+		char *p, *mtd_id, *semicol, *open_parenth;
+
+		/*
+		 * Replace the first ';' by a NULL char so strrchr can work
+		 * properly.
+		 */
+		semicol = strchr(s, ';');
+		if (semicol)
+			*semicol = '\0';
+
+		/*
+		 * make sure that part-names with ":" will not be handled as
+		 * part of the mtd-id with an ":"
+		 */
+		open_parenth = strchr(s, '(');
+		if (open_parenth)
+			*open_parenth = '\0';
 
 		mtd_id = s;
 
-		/* fetch <mtd-id> */
-		p = strchr(s, ':');
+		/*
+		 * fetch <mtd-id>. We use strrchr to ignore all ':' that could
+		 * be present in the MTD name, only the last one is interpreted
+		 * as an <mtd-id>/<part-definition> separator.
+		 */
+		p = strrchr(s, ':');
+
+		/* Restore the '(' now. */
+		if (open_parenth)
+			*open_parenth = '(';
+
+		/* Restore the ';' now. */
+		if (semicol)
+			*semicol = ';';
+
 		if (!p) {
 			pr_err("no mtd-id\n");
 			return -EINVAL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/parsers/parser_imagetag.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/parsers/parser_imagetag.c
@@ -83,6 +83,7 @@
 			pr_err("invalid rootfs address: %*ph\n",
 				(int)sizeof(buf->flash_image_start),
 				buf->flash_image_start);
+			ret = -EINVAL;
 			goto out;
 		}
 
@@ -92,6 +93,7 @@
 			pr_err("invalid kernel address: %*ph\n",
 				(int)sizeof(buf->kernel_address),
 				buf->kernel_address);
+			ret = -EINVAL;
 			goto out;
 		}
 
@@ -100,6 +102,7 @@
 			pr_err("invalid kernel length: %*ph\n",
 				(int)sizeof(buf->kernel_length),
 				buf->kernel_length);
+			ret = -EINVAL;
 			goto out;
 		}
 
@@ -108,6 +111,7 @@
 			pr_err("invalid total length: %*ph\n",
 				(int)sizeof(buf->total_length),
 				buf->total_length);
+			ret = -EINVAL;
 			goto out;
 		}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/parsers/redboot.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/parsers/redboot.c
@@ -45,6 +45,7 @@
 static void parse_redboot_of(struct mtd_info *master)
 {
 	struct device_node *np;
+	struct device_node *npart;
 	u32 dirblock;
 	int ret;
 
@@ -52,7 +53,12 @@
 	if (!np)
 		return;
 
-	ret = of_property_read_u32(np, "fis-index-block", &dirblock);
+	npart = of_get_child_by_name(np, "partitions");
+	if (!npart)
+		return;
+
+	ret = of_property_read_u32(npart, "fis-index-block", &dirblock);
+	of_node_put(npart);
 	if (ret)
 		return;
 
@@ -96,7 +102,7 @@
 			offset -= master->erasesize;
 		}
 	} else {
-		offset = directory * master->erasesize;
+		offset = (unsigned long) directory * master->erasesize;
 		while (mtd_block_isbad(master, offset)) {
 			offset += master->erasesize;
 			if (offset == master->size)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/parsers/sharpslpart.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/parsers/sharpslpart.c
@@ -165,10 +165,10 @@
 
 static int sharpsl_nand_init_ftl(struct mtd_info *mtd, struct sharpsl_ftl *ftl)
 {
-	unsigned int block_num, log_num, phymax;
+	unsigned int block_num, phymax;
+	int i, ret, log_num;
 	loff_t block_adr;
 	u8 *oob;
-	int i, ret;
 
 	oob = kzalloc(mtd->oobsize, GFP_KERNEL);
 	if (!oob)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/sm_ftl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/sm_ftl.c
@@ -1097,9 +1097,9 @@
 {
 	struct sm_ftl *ftl = dev->priv;
 
-	mutex_lock(&ftl->mutex);
 	del_timer_sync(&ftl->timer);
 	cancel_work_sync(&ftl->flush_work);
+	mutex_lock(&ftl->mutex);
 	sm_cache_flush(ftl);
 	mutex_unlock(&ftl->mutex);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/spi-nor/cadence-quadspi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/spi-nor/cadence-quadspi.c
@@ -25,15 +25,21 @@
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/reset.h>
+#include <linux/firmware/xlnx-zynqmp.h>
 #include <linux/sched.h>
+#include <linux/of_gpio.h>
 #include <linux/spi/spi.h>
 #include <linux/timer.h>
+#include <linux/workqueue.h>
 
 #define CQSPI_NAME			"cadence-qspi"
 #define CQSPI_MAX_CHIPSELECT		16
 
 /* Quirks */
 #define CQSPI_NEEDS_WR_DELAY		BIT(0)
+#define CQSPI_DISABLE_DAC_MODE		BIT(1)
+#define CQSPI_SUPPORT_RESET		BIT(5)
+#define CQSPI_HAS_DMA			BIT(7)
 
 /* Capabilities mask */
 #define CQSPI_BASE_HWCAPS_MASK					\
@@ -77,9 +83,6 @@
 	dma_addr_t		mmap_phys_base;
 
 	int			current_cs;
-	int			current_page_size;
-	int			current_erase_size;
-	int			current_addr_width;
 	unsigned long		master_ref_clk_hz;
 	bool			is_decoded_cs;
 	u32			fifo_depth;
@@ -88,6 +91,23 @@
 	u32			trigger_address;
 	u32			wr_delay;
 	struct cqspi_flash_pdata f_pdata[CQSPI_MAX_CHIPSELECT];
+	bool			read_dma;
+	void			*rxbuf;
+	int			bytes_to_rx;
+	int			bytes_to_dma;
+	loff_t			addr;
+	dma_addr_t		dma_addr;
+	u8			edge_mode;
+	bool			extra_dummy;
+	u8			access_mode;
+	bool			unalined_byte_cnt;
+	u8			dll_mode;
+	struct completion	tuning_complete;
+	struct completion	request_complete;
+	int (*indirect_read_dma)(struct spi_nor *nor, u_char *rxbuf,
+				 loff_t from_addr, size_t n_rx);
+	int (*flash_reset)(struct cqspi_st *cqspi, u8 reset_type);
+	const struct zynqmp_eemi_ops *eemi_ops;
 };
 
 struct cqspi_driver_platdata {
@@ -98,6 +118,8 @@
 /* Operation timeout value */
 #define CQSPI_TIMEOUT_MS			500
 #define CQSPI_READ_TIMEOUT_MS			10
+#define CQSPI_TUNING_TIMEOUT_MS			5000
+#define CQSPI_TUNING_PERIODICITY_MS		300000
 
 /* Instruction type */
 #define CQSPI_INST_TYPE_SINGLE			0
@@ -111,13 +133,20 @@
 
 #define CQSPI_STIG_DATA_LEN_MAX			8
 
+/* Edge mode */
+#define CQSPI_EDGE_MODE_SDR			0
+#define CQSPI_EDGE_MODE_DDR			1
+
 /* Register map */
 #define CQSPI_REG_CONFIG			0x00
 #define CQSPI_REG_CONFIG_ENABLE_MASK		BIT(0)
+#define CQSPI_REG_CONFIG_PHY_ENABLE_MASK	BIT(3)
 #define CQSPI_REG_CONFIG_ENB_DIR_ACC_CTRL	BIT(7)
 #define CQSPI_REG_CONFIG_DECODE_MASK		BIT(9)
 #define CQSPI_REG_CONFIG_CHIPSELECT_LSB		10
 #define CQSPI_REG_CONFIG_DMA_MASK		BIT(15)
+#define CQSPI_REG_CONFIG_AHB_ADDR_REMAP_MASK	BIT(16)
+#define CQSPI_REG_CONFIG_DTR_PROT_EN_MASK    BIT(24)
 #define CQSPI_REG_CONFIG_BAUD_LSB		19
 #define CQSPI_REG_CONFIG_IDLE_LSB		31
 #define CQSPI_REG_CONFIG_CHIPSELECT_MASK	0xF
@@ -137,6 +166,7 @@
 
 #define CQSPI_REG_WR_INSTR			0x08
 #define CQSPI_REG_WR_INSTR_OPCODE_LSB		0
+#define CQSPI_REG_WR_INSTR_OPCODE_MASK		0xFF
 #define CQSPI_REG_WR_INSTR_TYPE_ADDR_LSB	12
 #define CQSPI_REG_WR_INSTR_TYPE_DATA_LSB	16
 
@@ -151,6 +181,7 @@
 #define CQSPI_REG_DELAY_TSHSL_MASK		0xFF
 
 #define CQSPI_REG_READCAPTURE			0x10
+#define CQSPI_REG_READCAPTURE_DQS_ENABLE	BIT(8)
 #define CQSPI_REG_READCAPTURE_BYPASS_LSB	0
 #define CQSPI_REG_READCAPTURE_DELAY_LSB		1
 #define CQSPI_REG_READCAPTURE_DELAY_MASK	0xF
@@ -171,6 +202,7 @@
 #define CQSPI_REG_DMA_BURST_LSB			8
 #define CQSPI_REG_DMA_SINGLE_MASK		0xFF
 #define CQSPI_REG_DMA_BURST_MASK		0xFF
+#define CQSPI_REG_DMA_VAL				0x602
 
 #define CQSPI_REG_REMAP				0x24
 #define CQSPI_REG_MODE_BIT			0x28
@@ -181,8 +213,13 @@
 #define CQSPI_REG_SDRAMLEVEL_RD_MASK		0xFFFF
 #define CQSPI_REG_SDRAMLEVEL_WR_MASK		0xFFFF
 
+#define CQSPI_REG_WRCOMPLETION			0x38
+#define CQSPI_REG_WRCOMPLETION_POLLCNT_MASK	0xFF0000
+#define CQSPI_REG_WRCOMPLETION_POLLCNY_LSB	16
+
 #define CQSPI_REG_IRQSTATUS			0x40
 #define CQSPI_REG_IRQMASK			0x44
+#define CQSPI_REG_ECO				0x48
 
 #define CQSPI_REG_INDIRECTRD			0x60
 #define CQSPI_REG_INDIRECTRD_START_MASK		BIT(0)
@@ -196,6 +233,7 @@
 #define CQSPI_REG_CMDCTRL			0x90
 #define CQSPI_REG_CMDCTRL_EXECUTE_MASK		BIT(0)
 #define CQSPI_REG_CMDCTRL_INPROGRESS_MASK	BIT(1)
+#define CQSPI_REG_CMDCTRL_DUMMY_BYTES_LSB	7
 #define CQSPI_REG_CMDCTRL_WR_BYTES_LSB		12
 #define CQSPI_REG_CMDCTRL_WR_EN_LSB		15
 #define CQSPI_REG_CMDCTRL_ADD_BYTES_LSB		16
@@ -206,6 +244,7 @@
 #define CQSPI_REG_CMDCTRL_WR_BYTES_MASK		0x7
 #define CQSPI_REG_CMDCTRL_ADD_BYTES_MASK	0x3
 #define CQSPI_REG_CMDCTRL_RD_BYTES_MASK		0x7
+#define CQSPI_REG_CMDCTRL_DUMMY_BYTES_MASK      0x1F
 
 #define CQSPI_REG_INDIRECTWR			0x70
 #define CQSPI_REG_INDIRECTWR_START_MASK		BIT(0)
@@ -216,12 +255,42 @@
 #define CQSPI_REG_INDIRECTWRSTARTADDR		0x78
 #define CQSPI_REG_INDIRECTWRBYTES		0x7C
 
+#define CQSPI_REG_INDTRIG_ADDRRANGE			0x80
+#define CQSPI_REG_INDTRIG_ADDRRANGE_WIDTH	0x6
+
 #define CQSPI_REG_CMDADDRESS			0x94
 #define CQSPI_REG_CMDREADDATALOWER		0xA0
 #define CQSPI_REG_CMDREADDATAUPPER		0xA4
 #define CQSPI_REG_CMDWRITEDATALOWER		0xA8
 #define CQSPI_REG_CMDWRITEDATAUPPER		0xAC
 
+#define CQSPI_REG_PHY_CONFIG			0xB4
+#define CQSPI_REG_PHY_CONFIG_RESYNC_FLD_MASK	0x80000000
+#define CQSPI_REG_PHY_CONFIG_RESET_FLD_MASK	0x40000000
+#define CQSPI_REG_PHY_CONFIG_TX_DLL_DLY_LSB	16
+
+#define CQSPI_REG_PHY_MASTER_CTRL		0xB8
+#define CQSPI_REG_DLL_LOWER			0xBC
+#define CQSPI_REG_DLL_LOWER_LPBK_LOCK_MASK	0x8000
+#define CQSPI_REG_DLL_LOWER_DLL_LOCK_MASK	0x1
+
+#define CQSPI_REG_DMA_SRC_ADDR			0x1000
+#define CQSPI_REG_DMA_DST_ADDR			0x1800
+#define CQSPI_REG_DMA_DST_SIZE			0x1804
+#define CQSPI_REG_DMA_DST_STS			0x1808
+#define CQSPI_REG_DMA_DST_CTRL			0x180C
+#define CQSPI_REG_DMA_DST_CTRL_VAL		0xF43FFA00
+
+#define CQSPI_REG_DMA_DTS_I_STS			0x1814
+#define CQSPI_REG_DMA_DST_I_EN			0x1818
+#define CQSPI_REG_DMA_DST_I_EN_DONE		BIT(1)
+
+#define CQSPI_REG_DMA_DST_I_DIS			0x181C
+#define CQSPI_REG_DMA_DST_I_DIS_DONE	BIT(1)
+#define CQSPI_REG_DMA_DST_ALL_I_DIS_MASK	0xFE
+#define CQSPI_REG_DMA_DST_I_MASK		0x1820
+#define CQSPI_REG_DMA_DST_ADDR_MSB		0x1828
+
 /* Interrupt status bits */
 #define CQSPI_REG_IRQ_MODE_ERR			BIT(0)
 #define CQSPI_REG_IRQ_UNDERFLOW			BIT(1)
@@ -241,6 +310,30 @@
 					 CQSPI_REG_IRQ_UNDERFLOW)
 
 #define CQSPI_IRQ_STATUS_MASK		0x1FFFF
+#define CQSPI_MIO_NODE_ID_12		0x14108027
+#define CQSPI_READ_ID			0x9F
+#define CQSPI_FAST_READ                 0x0C
+#define CQSPI_READ_ID_LEN		6
+#define TERA_MACRO			1000000000000l
+
+#define CQSPI_RESET_TYPE_HWPIN		0
+
+#define CQSPI_DMA_MODE		0
+#define CQSPI_LINEAR_MODE	1
+
+#define RESET_OSPI		0xc10402e
+#define DEV_OSPI		0x1822402a
+
+#define SILICON_VER_MASK	0xFF
+#define SILICON_VER_1		0x10
+#define CQSPI_DLL_MODE_MASTER	0
+#define CQSPI_DLL_MODE_BYPASS	1
+#define TAP_GRAN_SEL_MIN_FREQ	120000000
+#define CQSPI_TX_TAP_MASTER	0x19
+#define CQSPI_MAX_DLL_TAPS	128
+
+#define CQSPI_CS0	0
+#define CQSPI_CS1	1
 
 static int cqspi_wait_for_bit(void __iomem *reg, const u32 mask, bool clr)
 {
@@ -266,25 +359,6 @@
 	return reg & CQSPI_REG_SDRAMLEVEL_RD_MASK;
 }
 
-static irqreturn_t cqspi_irq_handler(int this_irq, void *dev)
-{
-	struct cqspi_st *cqspi = dev;
-	unsigned int irq_status;
-
-	/* Read interrupt status */
-	irq_status = readl(cqspi->iobase + CQSPI_REG_IRQSTATUS);
-
-	/* Clear interrupt */
-	writel(irq_status, cqspi->iobase + CQSPI_REG_IRQSTATUS);
-
-	irq_status &= CQSPI_IRQ_MASK_RD | CQSPI_IRQ_MASK_WR;
-
-	if (irq_status)
-		complete(&cqspi->transfer_complete);
-
-	return IRQ_HANDLED;
-}
-
 static unsigned int cqspi_calc_rdreg(struct spi_nor *nor, const u8 opcode)
 {
 	struct cqspi_flash_pdata *f_pdata = nor->priv;
@@ -354,6 +428,99 @@
 	return cqspi_wait_idle(cqspi);
 }
 
+static void process_dma_irq(struct cqspi_st *cqspi)
+{
+	struct platform_device *pdev = cqspi->pdev;
+	struct device *dev = &pdev->dev;
+	unsigned int rem;
+	unsigned int reg;
+	unsigned int data;
+	u8 addr_bytes;
+	u8 opcode;
+	u8 dummy_cycles;
+
+	/* Disable DMA interrupt */
+	writel(CQSPI_REG_DMA_DST_I_DIS_DONE,
+	       cqspi->iobase + CQSPI_REG_DMA_DST_I_DIS);
+
+	/* Clear indirect completion status */
+	writel(CQSPI_REG_INDIRECTRD_DONE_MASK,
+	       cqspi->iobase + CQSPI_REG_INDIRECTRD);
+	dma_unmap_single(dev, cqspi->dma_addr, cqspi->bytes_to_dma,
+			 DMA_FROM_DEVICE);
+	rem = cqspi->bytes_to_rx - cqspi->bytes_to_dma;
+
+	/* Read unaligned data in STIG */
+	if (rem) {
+		cqspi->rxbuf += cqspi->bytes_to_dma;
+		writel(cqspi->addr + cqspi->bytes_to_dma,
+		       cqspi->iobase + CQSPI_REG_CMDADDRESS);
+		if (cqspi->edge_mode == CQSPI_EDGE_MODE_DDR) {
+			opcode = (u8)readl(cqspi->iobase + CQSPI_REG_RD_INSTR);
+			dummy_cycles = (readl(cqspi->iobase +
+					CQSPI_REG_RD_INSTR) >>
+					CQSPI_REG_RD_INSTR_DUMMY_LSB) &
+					CQSPI_REG_RD_INSTR_DUMMY_MASK;
+		} else {
+			opcode = CQSPI_FAST_READ;
+			dummy_cycles = 8;
+			writel((dummy_cycles << CQSPI_REG_RD_INSTR_DUMMY_LSB) |
+				opcode, cqspi->iobase + CQSPI_REG_RD_INSTR);
+		}
+		addr_bytes = readl(cqspi->iobase + CQSPI_REG_SIZE) &
+				CQSPI_REG_SIZE_ADDRESS_MASK;
+		reg = opcode << CQSPI_REG_CMDCTRL_OPCODE_LSB;
+		reg |= (0x1 << CQSPI_REG_CMDCTRL_RD_EN_LSB);
+		reg |= (0x1 << CQSPI_REG_CMDCTRL_ADDR_EN_LSB);
+		reg |= (addr_bytes & CQSPI_REG_CMDCTRL_ADD_BYTES_MASK) <<
+			CQSPI_REG_CMDCTRL_ADD_BYTES_LSB;
+		reg |= (dummy_cycles & CQSPI_REG_CMDCTRL_DUMMY_BYTES_MASK) <<
+			CQSPI_REG_CMDCTRL_DUMMY_BYTES_LSB;
+		cqspi->unalined_byte_cnt = false;
+		if (cqspi->edge_mode == CQSPI_EDGE_MODE_DDR &&
+		    ((rem % 2) != 0)) {
+			cqspi->unalined_byte_cnt = true;
+		}
+		/* 0 means 1 byte. */
+		reg |= (((rem - 1 + cqspi->unalined_byte_cnt) &
+			CQSPI_REG_CMDCTRL_RD_BYTES_MASK) <<
+			CQSPI_REG_CMDCTRL_RD_BYTES_LSB);
+		cqspi_exec_flash_cmd(cqspi, reg);
+		data = readl(cqspi->iobase + CQSPI_REG_CMDREADDATALOWER);
+
+		/* Put the read value into rx_buf */
+		memcpy(cqspi->rxbuf, &data, rem);
+	}
+}
+
+static irqreturn_t cqspi_irq_handler(int this_irq, void *dev)
+{
+	struct cqspi_st *cqspi = dev;
+	unsigned int irq_status;
+	unsigned int dma_status;
+
+	/* Read interrupt status */
+	irq_status = readl(cqspi->iobase + CQSPI_REG_IRQSTATUS);
+	irq_status &= CQSPI_IRQ_MASK_RD | CQSPI_IRQ_MASK_WR;
+
+	/* Clear interrupt */
+	if (irq_status)
+		writel(irq_status, cqspi->iobase + CQSPI_REG_IRQSTATUS);
+
+	/* Read DMA interrupt status */
+	dma_status = readl(cqspi->iobase + CQSPI_REG_DMA_DTS_I_STS);
+	dma_status &= CQSPI_REG_DMA_DST_I_EN_DONE;
+
+	/* Clear DMA interrupt */
+	if (dma_status)
+		writel(dma_status, cqspi->iobase + CQSPI_REG_DMA_DTS_I_STS);
+
+	if (irq_status || dma_status)
+		complete(&cqspi->transfer_complete);
+
+	return IRQ_HANDLED;
+}
+
 static int cqspi_command_read(struct spi_nor *nor,
 			      const u8 *txbuf, const unsigned n_tx,
 			      u8 *rxbuf, const unsigned n_rx)
@@ -365,6 +532,7 @@
 	unsigned int reg;
 	unsigned int read_len;
 	int status;
+	u8 dummy_cycles;
 
 	if (!n_rx || n_rx > CQSPI_STIG_DATA_LEN_MAX || !rxbuf) {
 		dev_err(nor->dev, "Invalid input argument, len %d rxbuf 0x%p\n",
@@ -382,6 +550,14 @@
 	/* 0 means 1 byte. */
 	reg |= (((n_rx - 1) & CQSPI_REG_CMDCTRL_RD_BYTES_MASK)
 		<< CQSPI_REG_CMDCTRL_RD_BYTES_LSB);
+	if (cqspi->edge_mode == CQSPI_EDGE_MODE_DDR)
+		dummy_cycles = 8;
+	else
+		dummy_cycles = 0;
+	if (cqspi->extra_dummy)
+		dummy_cycles++;
+	reg |= ((dummy_cycles & CQSPI_REG_CMDCTRL_DUMMY_BYTES_MASK)
+			<< CQSPI_REG_CMDCTRL_DUMMY_BYTES_LSB);
 	status = cqspi_exec_flash_cmd(cqspi, reg);
 	if (status)
 		return status;
@@ -421,11 +597,24 @@
 		return -EINVAL;
 	}
 
+	reg = f_pdata->data_width << CQSPI_REG_WR_INSTR_TYPE_DATA_LSB;
+	reg |= f_pdata->addr_width << CQSPI_REG_WR_INSTR_TYPE_ADDR_LSB;
+	writel(reg, reg_base + CQSPI_REG_WR_INSTR);
+	reg = cqspi_calc_rdreg(nor, opcode);
+	writel(reg, reg_base + CQSPI_REG_RD_INSTR);
+
 	reg = opcode << CQSPI_REG_CMDCTRL_OPCODE_LSB;
 	if (n_tx) {
 		reg |= (0x1 << CQSPI_REG_CMDCTRL_WR_EN_LSB);
 		reg |= ((n_tx - 1) & CQSPI_REG_CMDCTRL_WR_BYTES_MASK)
 			<< CQSPI_REG_CMDCTRL_WR_BYTES_LSB;
+		if (nor->is_addrvalid) {
+			reg |= (0x1 << CQSPI_REG_CMDCTRL_ADDR_EN_LSB);
+			reg |= ((nor->addr_width - 1) &
+				CQSPI_REG_CMDCTRL_ADD_BYTES_MASK) <<
+				CQSPI_REG_CMDCTRL_ADD_BYTES_LSB;
+			writel(nor->reg_addr, reg_base + CQSPI_REG_CMDADDRESS);
+		}
 		data = 0;
 		write_len = (n_tx > 4) ? 4 : n_tx;
 		memcpy(&data, txbuf, write_len);
@@ -475,20 +664,29 @@
 	/* Setup dummy clock cycles */
 	dummy_clk = nor->read_dummy;
 	if (dummy_clk > CQSPI_DUMMY_CLKS_MAX)
-		dummy_clk = CQSPI_DUMMY_CLKS_MAX;
-
-	if (dummy_clk / 8) {
-		reg |= (1 << CQSPI_REG_RD_INSTR_MODE_EN_LSB);
-		/* Set mode bits high to ensure chip doesn't enter XIP */
-		writel(0xFF, reg_base + CQSPI_REG_MODE_BIT);
-
-		/* Need to subtract the mode byte (8 clocks). */
-		if (f_pdata->inst_width != CQSPI_INST_TYPE_QUAD)
-			dummy_clk -= 8;
+		return -EOPNOTSUPP;
 
+	if (!(nor->flags & SNOR_F_BROKEN_OCTAL_DDR)) {
+		if (cqspi->extra_dummy)
+			dummy_clk++;
 		if (dummy_clk)
 			reg |= (dummy_clk & CQSPI_REG_RD_INSTR_DUMMY_MASK)
 			       << CQSPI_REG_RD_INSTR_DUMMY_LSB;
+	} else {
+		if (dummy_clk / 8) {
+			reg |= (1 << CQSPI_REG_RD_INSTR_MODE_EN_LSB);
+			/* Set mode bit high to ensure chip doesn't enter XIP */
+			writel(0xFF, reg_base + CQSPI_REG_MODE_BIT);
+
+			/* Need to subtract the mode byte (8 clocks). */
+			if (f_pdata->inst_width != CQSPI_INST_TYPE_QUAD)
+				dummy_clk -= 8;
+
+			if (dummy_clk)
+				reg |= (dummy_clk &
+					CQSPI_REG_RD_INSTR_DUMMY_MASK)
+				       << CQSPI_REG_RD_INSTR_DUMMY_LSB;
+		}
 	}
 
 	writel(reg, reg_base + CQSPI_REG_RD_INSTR);
@@ -512,10 +710,36 @@
 	unsigned int mod_bytes = n_rx % 4;
 	unsigned int bytes_to_read = 0;
 	u8 *rxbuf_end = rxbuf + n_rx;
+	u8 *rxbuf_start = rxbuf;
 	int ret = 0;
+	u32 reg;
+	u8 extra_bytes = 0;
+
+	reg = readl(cqspi->iobase + CQSPI_REG_CONFIG);
+	reg &= ~CQSPI_REG_CONFIG_DMA_MASK;
+	writel(reg, cqspi->iobase + CQSPI_REG_CONFIG);
+
+	if (cqspi->eemi_ops && cqspi->access_mode == CQSPI_DMA_MODE) {
+		cqspi_wait_idle(cqspi);
+		cqspi->eemi_ops->ioctl(DEV_OSPI, IOCTL_OSPI_MUX_SELECT,
+				       PM_OSPI_MUX_SEL_LINEAR, 0, NULL);
+		cqspi->access_mode = CQSPI_LINEAR_MODE;
+		cqspi_wait_idle(cqspi);
+	}
 
 	writel(from_addr, reg_base + CQSPI_REG_INDIRECTRDSTARTADDR);
-	writel(remaining, reg_base + CQSPI_REG_INDIRECTRDBYTES);
+	if (cqspi->edge_mode == CQSPI_EDGE_MODE_DDR &&
+	    ((from_addr % 2) != 0) && !cqspi->unalined_byte_cnt) {
+		if (!cqspi->unalined_byte_cnt) {
+			extra_bytes = 2;
+			mod_bytes += 1;
+		} else if (((n_rx + 1) % 4) != 0) {
+			mod_bytes += 1;
+		}
+	}
+
+	writel(remaining + cqspi->unalined_byte_cnt +
+		extra_bytes, reg_base + CQSPI_REG_INDIRECTRDBYTES);
 
 	/* Clear all interrupts. */
 	writel(CQSPI_IRQ_STATUS_MASK, reg_base + CQSPI_REG_IRQSTATUS);
@@ -547,12 +771,26 @@
 			bytes_to_read = round_down(bytes_to_read, 4);
 			/* Read 4 byte word chunks then single bytes */
 			if (bytes_to_read) {
-				ioread32_rep(ahb_base, rxbuf,
-					     (bytes_to_read / 4));
+				u8 offset = 0;
+
+				if (cqspi->edge_mode == CQSPI_EDGE_MODE_DDR &&
+				    ((from_addr % 2) != 0) && rxbuf ==
+				    rxbuf_start) {
+					unsigned int temp = ioread32(ahb_base);
+
+					temp >>= 8;
+					memcpy(rxbuf, &temp, 3);
+					bytes_to_read -= 1;
+					offset = 3;
+				}
+				if (bytes_to_read >= 4)
+					ioread32_rep(ahb_base, rxbuf + offset,
+						     (bytes_to_read / 4));
 			} else if (!word_remain && mod_bytes) {
 				unsigned int temp = ioread32(ahb_base);
 
-				bytes_to_read = mod_bytes;
+				bytes_to_read = remaining > mod_bytes ?
+						remaining : mod_bytes;
 				memcpy(rxbuf, &temp, min((unsigned int)
 							 (rxbuf_end - rxbuf),
 							 bytes_to_read));
@@ -593,7 +831,7 @@
 	return ret;
 }
 
-static int cqspi_write_setup(struct spi_nor *nor)
+static int cqspi_write_setup(struct spi_nor *nor, const u8 opcode)
 {
 	unsigned int reg;
 	struct cqspi_flash_pdata *f_pdata = nor->priv;
@@ -601,9 +839,11 @@
 	void __iomem *reg_base = cqspi->iobase;
 
 	/* Set opcode. */
-	reg = nor->program_opcode << CQSPI_REG_WR_INSTR_OPCODE_LSB;
+	reg = opcode << CQSPI_REG_WR_INSTR_OPCODE_LSB;
+	reg |= f_pdata->data_width << CQSPI_REG_WR_INSTR_TYPE_DATA_LSB;
+	reg |= f_pdata->addr_width << CQSPI_REG_WR_INSTR_TYPE_ADDR_LSB;
 	writel(reg, reg_base + CQSPI_REG_WR_INSTR);
-	reg = cqspi_calc_rdreg(nor, nor->program_opcode);
+	reg = cqspi_calc_rdreg(nor, opcode);
 	writel(reg, reg_base + CQSPI_REG_RD_INSTR);
 
 	reg = readl(reg_base + CQSPI_REG_SIZE);
@@ -623,9 +863,23 @@
 	unsigned int remaining = n_tx;
 	unsigned int write_bytes;
 	int ret;
+	u32 reg;
+
+	reg = readl(cqspi->iobase + CQSPI_REG_CONFIG);
+	reg &= ~CQSPI_REG_CONFIG_DMA_MASK;
+	writel(reg, cqspi->iobase + CQSPI_REG_CONFIG);
+
+	if (cqspi->eemi_ops && cqspi->access_mode == CQSPI_DMA_MODE) {
+		cqspi_wait_idle(cqspi);
+		cqspi->eemi_ops->ioctl(DEV_OSPI, IOCTL_OSPI_MUX_SELECT,
+				       PM_OSPI_MUX_SEL_LINEAR, 0, NULL);
+		cqspi->access_mode = CQSPI_LINEAR_MODE;
+		cqspi_wait_idle(cqspi);
+	}
 
 	writel(to_addr, reg_base + CQSPI_REG_INDIRECTWRSTARTADDR);
-	writel(remaining, reg_base + CQSPI_REG_INDIRECTWRBYTES);
+	writel(remaining + cqspi->unalined_byte_cnt,
+	       reg_base + CQSPI_REG_INDIRECTWRBYTES);
 
 	/* Clear all interrupts. */
 	writel(CQSPI_IRQ_STATUS_MASK, reg_base + CQSPI_REG_IRQSTATUS);
@@ -736,32 +990,6 @@
 	writel(reg, reg_base + CQSPI_REG_CONFIG);
 }
 
-static void cqspi_configure_cs_and_sizes(struct spi_nor *nor)
-{
-	struct cqspi_flash_pdata *f_pdata = nor->priv;
-	struct cqspi_st *cqspi = f_pdata->cqspi;
-	void __iomem *iobase = cqspi->iobase;
-	unsigned int reg;
-
-	/* configure page size and block size. */
-	reg = readl(iobase + CQSPI_REG_SIZE);
-	reg &= ~(CQSPI_REG_SIZE_PAGE_MASK << CQSPI_REG_SIZE_PAGE_LSB);
-	reg &= ~(CQSPI_REG_SIZE_BLOCK_MASK << CQSPI_REG_SIZE_BLOCK_LSB);
-	reg &= ~CQSPI_REG_SIZE_ADDRESS_MASK;
-	reg |= (nor->page_size << CQSPI_REG_SIZE_PAGE_LSB);
-	reg |= (ilog2(nor->mtd.erasesize) << CQSPI_REG_SIZE_BLOCK_LSB);
-	reg |= (nor->addr_width - 1);
-	writel(reg, iobase + CQSPI_REG_SIZE);
-
-	/* configure the chip select */
-	cqspi_chipselect(nor);
-
-	/* Store the new configuration of the controller */
-	cqspi->current_page_size = nor->page_size;
-	cqspi->current_erase_size = nor->mtd.erasesize;
-	cqspi->current_addr_width = nor->addr_width;
-}
-
 static unsigned int calculate_ticks_for_ns(const unsigned int ref_clk_hz,
 					   const unsigned int ns_val)
 {
@@ -867,18 +1095,13 @@
 	int switch_cs = (cqspi->current_cs != f_pdata->cs);
 	int switch_ck = (cqspi->sclk != sclk);
 
-	if ((cqspi->current_page_size != nor->page_size) ||
-	    (cqspi->current_erase_size != nor->mtd.erasesize) ||
-	    (cqspi->current_addr_width != nor->addr_width))
-		switch_cs = 1;
-
 	if (switch_cs || switch_ck)
 		cqspi_controller_enable(cqspi, 0);
 
 	/* Switch chip select. */
 	if (switch_cs) {
 		cqspi->current_cs = f_pdata->cs;
-		cqspi_configure_cs_and_sizes(nor);
+		cqspi_chipselect(nor);
 	}
 
 	/* Setup baudrate divisor and delays */
@@ -902,6 +1125,11 @@
 	f_pdata->addr_width = CQSPI_INST_TYPE_SINGLE;
 	f_pdata->data_width = CQSPI_INST_TYPE_SINGLE;
 
+	if (nor->flags & SNOR_F_UPPER_CS)
+		f_pdata->cs = CQSPI_CS1;
+	else
+		f_pdata->cs = CQSPI_CS0;
+
 	if (read) {
 		switch (nor->read_proto) {
 		case SNOR_PROTO_1_1_1:
@@ -916,6 +1144,37 @@
 		case SNOR_PROTO_1_1_8:
 			f_pdata->data_width = CQSPI_INST_TYPE_OCTAL;
 			break;
+		case SNOR_PROTO_8_8_8:
+			if (f_pdata->cqspi->edge_mode == CQSPI_EDGE_MODE_DDR) {
+				f_pdata->inst_width = CQSPI_INST_TYPE_OCTAL;
+				f_pdata->addr_width = CQSPI_INST_TYPE_OCTAL;
+				f_pdata->data_width = CQSPI_INST_TYPE_OCTAL;
+			}
+			break;
+		default:
+			return -EINVAL;
+		}
+	} else {
+		switch (nor->write_proto) {
+		case SNOR_PROTO_1_1_1:
+			f_pdata->data_width = CQSPI_INST_TYPE_SINGLE;
+			break;
+		case SNOR_PROTO_1_1_2:
+			f_pdata->data_width = CQSPI_INST_TYPE_DUAL;
+			break;
+		case SNOR_PROTO_1_1_4:
+			f_pdata->data_width = CQSPI_INST_TYPE_QUAD;
+			break;
+		case SNOR_PROTO_1_1_8:
+			f_pdata->data_width = CQSPI_INST_TYPE_OCTAL;
+			break;
+		case SNOR_PROTO_8_8_8:
+			if (f_pdata->cqspi->edge_mode == CQSPI_EDGE_MODE_DDR) {
+				f_pdata->inst_width = CQSPI_INST_TYPE_OCTAL;
+				f_pdata->addr_width = CQSPI_INST_TYPE_OCTAL;
+				f_pdata->data_width = CQSPI_INST_TYPE_OCTAL;
+			}
+			break;
 		default:
 			return -EINVAL;
 		}
@@ -933,14 +1192,30 @@
 	struct cqspi_st *cqspi = f_pdata->cqspi;
 	int ret;
 
+	reinit_completion(&cqspi->request_complete);
+
+	if (cqspi->edge_mode == CQSPI_EDGE_MODE_DDR &&
+	    !cqspi->tuning_complete.done) {
+		if (!wait_for_completion_timeout(&cqspi->tuning_complete,
+			msecs_to_jiffies(CQSPI_TUNING_TIMEOUT_MS))) {
+			return -ETIMEDOUT;
+		}
+	}
+
 	ret = cqspi_set_protocol(nor, 0);
 	if (ret)
 		return ret;
 
-	ret = cqspi_write_setup(nor);
+	ret = cqspi_write_setup(nor, nor->program_opcode);
 	if (ret)
 		return ret;
 
+	cqspi->unalined_byte_cnt = false;
+	if (cqspi->edge_mode == CQSPI_EDGE_MODE_DDR &&
+	    ((len % 2) != 0)) {
+		cqspi->unalined_byte_cnt = true;
+	}
+
 	if (f_pdata->use_direct_mode) {
 		memcpy_toio(cqspi->ahb_base + to, buf, len);
 		ret = cqspi_wait_idle(cqspi);
@@ -1021,7 +1296,20 @@
 			  size_t len, u_char *buf)
 {
 	struct cqspi_flash_pdata *f_pdata = nor->priv;
+	struct cqspi_st *cqspi = f_pdata->cqspi;
+	u64 dma_align = (u64)(uintptr_t)buf;
 	int ret;
+	bool use_dma = true;
+
+	reinit_completion(&cqspi->request_complete);
+
+	if (cqspi->edge_mode == CQSPI_EDGE_MODE_DDR &&
+	    !cqspi->tuning_complete.done) {
+		if (!wait_for_completion_timeout(&cqspi->tuning_complete,
+			msecs_to_jiffies(CQSPI_TUNING_TIMEOUT_MS))) {
+			return -ETIMEDOUT;
+		}
+	}
 
 	ret = cqspi_set_protocol(nor, 1);
 	if (ret)
@@ -1031,26 +1319,52 @@
 	if (ret)
 		return ret;
 
-	if (f_pdata->use_direct_mode)
+	cqspi->unalined_byte_cnt = false;
+	if (cqspi->edge_mode == CQSPI_EDGE_MODE_DDR) {
+		if ((len % 2) != 0)
+			cqspi->unalined_byte_cnt = true;
+		if ((from % 2) != 0)
+			use_dma = 0;
+	}
+
+	if (f_pdata->use_direct_mode) {
 		ret = cqspi_direct_read_execute(nor, buf, from, len);
-	else
+	} else if (cqspi->read_dma && virt_addr_valid(buf) && use_dma &&
+		   cqspi->indirect_read_dma && len >= 4 &&
+		   ((dma_align & 0x3) == 0) && !is_vmalloc_addr(buf)) {
+		ret = cqspi->indirect_read_dma(nor, buf, from, len);
+	} else {
 		ret = cqspi_indirect_read_execute(nor, buf, from, len);
+	}
 	if (ret)
 		return ret;
 
+	complete(&cqspi->request_complete);
+
 	return len;
 }
 
 static int cqspi_erase(struct spi_nor *nor, loff_t offs)
 {
+	struct cqspi_flash_pdata *f_pdata = nor->priv;
+	struct cqspi_st *cqspi = f_pdata->cqspi;
 	int ret;
 
+	reinit_completion(&cqspi->request_complete);
+
+	if (cqspi->edge_mode == CQSPI_EDGE_MODE_DDR &&
+	    !cqspi->tuning_complete.done) {
+		if (!wait_for_completion_timeout(&cqspi->tuning_complete,
+			msecs_to_jiffies(CQSPI_TUNING_TIMEOUT_MS))) {
+			return -ETIMEDOUT;
+		}
+	}
+
 	ret = cqspi_set_protocol(nor, 0);
 	if (ret)
 		return ret;
 
-	/* Send write enable, then erase commands. */
-	ret = nor->write_reg(nor, SPINOR_OP_WREN, NULL, 0);
+	ret = cqspi_write_setup(nor, nor->erase_opcode);
 	if (ret)
 		return ret;
 
@@ -1082,23 +1396,58 @@
 
 static int cqspi_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
 {
+	struct cqspi_flash_pdata *f_pdata = nor->priv;
+	struct cqspi_st *cqspi = f_pdata->cqspi;
 	int ret;
 
+	reinit_completion(&cqspi->request_complete);
+
+	if (cqspi->edge_mode == CQSPI_EDGE_MODE_DDR &&
+	    !cqspi->tuning_complete.done) {
+		if (!wait_for_completion_timeout(&cqspi->tuning_complete,
+			msecs_to_jiffies(CQSPI_TUNING_TIMEOUT_MS))) {
+			return -ETIMEDOUT;
+		}
+	}
+
 	ret = cqspi_set_protocol(nor, 0);
-	if (!ret)
+	if (!ret) {
+		if (cqspi->edge_mode == CQSPI_EDGE_MODE_DDR)
+			len = ((len % 2) != 0) ? (len + 1) : len;
 		ret = cqspi_command_read(nor, &opcode, 1, buf, len);
+	}
+
+	if ((opcode == SPINOR_OP_RDFSR && ((FSR_READY & buf[0]) != 0)) ||
+		(SPINOR_OP_RDSR != opcode && SPINOR_OP_RDFSR != opcode)) {
+		complete(&cqspi->request_complete);
+	}
 
 	return ret;
 }
 
 static int cqspi_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
 {
+	struct cqspi_flash_pdata *f_pdata = nor->priv;
+	struct cqspi_st *cqspi = f_pdata->cqspi;
 	int ret;
 
+	reinit_completion(&cqspi->request_complete);
+
+	if (cqspi->edge_mode == CQSPI_EDGE_MODE_DDR &&
+	    !cqspi->tuning_complete.done) {
+		if (!wait_for_completion_timeout(&cqspi->tuning_complete,
+			msecs_to_jiffies(CQSPI_TUNING_TIMEOUT_MS))) {
+			return -ETIMEDOUT;
+		}
+	}
+
 	ret = cqspi_set_protocol(nor, 0);
 	if (!ret)
 		ret = cqspi_command_write(nor, opcode, buf, len);
 
+	if (opcode != SPINOR_OP_WREN)
+		complete(&cqspi->request_complete);
+
 	return ret;
 }
 
@@ -1167,6 +1516,217 @@
 	return 0;
 }
 
+static int cqspi_setdlldelay(struct spi_nor *nor)
+{
+	struct cqspi_flash_pdata *f_pdata = nor->priv;
+	struct cqspi_st *cqspi = f_pdata->cqspi;
+	int i;
+	u8 j;
+	int ret;
+	u8 id[CQSPI_READ_ID_LEN];
+	bool rxtapfound = false;
+	u8 min_rxtap = 0;
+	u8 max_rxtap = 0;
+	u8 avg_rxtap;
+	bool id_matched;
+	u32 txtap = 0;
+	u8 max_tap;
+	s8 max_windowsize = -1;
+	u8 windowsize;
+	u8 dummy_incr;
+	u8 dummy_flag = 0;
+	u8 count;
+	u8 opcode = CQSPI_READ_ID;
+
+	max_tap = ((TERA_MACRO / cqspi->master_ref_clk_hz) / 160);
+	if (cqspi->dll_mode == CQSPI_DLL_MODE_MASTER) {
+		/* Drive DLL reset bit to low */
+		writel(0, cqspi->iobase + CQSPI_REG_PHY_CONFIG);
+
+		/* Set initial delay value */
+		writel(0x4, cqspi->iobase + CQSPI_REG_PHY_MASTER_CTRL);
+
+		/* Set DLL reset bit */
+		writel(CQSPI_REG_PHY_CONFIG_RESET_FLD_MASK,
+		       cqspi->iobase + CQSPI_REG_PHY_CONFIG);
+
+		/* Check for loopback lock */
+		ret = cqspi_wait_for_bit(cqspi->iobase + CQSPI_REG_DLL_LOWER,
+					 CQSPI_REG_DLL_LOWER_LPBK_LOCK_MASK, 0);
+		if (ret) {
+			dev_err(nor->dev,
+				"Loopback lock bit error (%i)\n", ret);
+			return ret;
+		}
+
+		/* Re-synchronize slave DLLs */
+		writel(CQSPI_REG_PHY_CONFIG_RESET_FLD_MASK,
+		       cqspi->iobase + CQSPI_REG_PHY_CONFIG);
+		writel(CQSPI_REG_PHY_CONFIG_RESET_FLD_MASK |
+		       CQSPI_REG_PHY_CONFIG_RESYNC_FLD_MASK,
+		       cqspi->iobase + CQSPI_REG_PHY_CONFIG);
+
+		txtap = CQSPI_TX_TAP_MASTER <<
+			CQSPI_REG_PHY_CONFIG_TX_DLL_DLY_LSB;
+		max_tap = CQSPI_MAX_DLL_TAPS;
+	}
+
+	cqspi->extra_dummy = false;
+	for (dummy_incr = 0; dummy_incr <= 1; dummy_incr++) {
+		if (dummy_incr)
+			cqspi->extra_dummy = true;
+		for (i = 0; i <= max_tap; i++) {
+			writel((txtap | i |
+			       CQSPI_REG_PHY_CONFIG_RESET_FLD_MASK),
+			       cqspi->iobase + CQSPI_REG_PHY_CONFIG);
+			writel((CQSPI_REG_PHY_CONFIG_RESYNC_FLD_MASK | txtap |
+			       i | CQSPI_REG_PHY_CONFIG_RESET_FLD_MASK),
+			       cqspi->iobase + CQSPI_REG_PHY_CONFIG);
+			if (cqspi->dll_mode == CQSPI_DLL_MODE_MASTER) {
+				ret = cqspi_wait_for_bit(cqspi->iobase +
+							 CQSPI_REG_DLL_LOWER,
+					CQSPI_REG_DLL_LOWER_DLL_LOCK_MASK, 0);
+				if (ret)
+					return ret;
+			}
+			count = 0;
+			do {
+				count += 1;
+				ret = cqspi_set_protocol(nor, 0);
+				if (!ret)
+					ret = cqspi_command_read(nor, &opcode,
+						1, id, CQSPI_READ_ID_LEN);
+				if (ret < 0) {
+					dev_err(nor->dev,
+						"error %d reading JEDEC ID\n",
+						ret);
+					return ret;
+				}
+				id_matched = true;
+				for (j = 0; j < CQSPI_READ_ID_LEN; j++) {
+					if (nor->device_id[j] != id[j]) {
+						id_matched = false;
+						break;
+					}
+				}
+			} while (id_matched && (count <= 10));
+
+			if (id_matched) {
+				if (!rxtapfound) {
+					min_rxtap = i;
+					max_rxtap = i;
+					rxtapfound = true;
+				} else {
+					max_rxtap = i;
+				}
+			}
+			if (!id_matched || i == max_tap) {
+				if (rxtapfound) {
+					windowsize = max_rxtap - min_rxtap + 1;
+					if (windowsize > max_windowsize) {
+						dummy_flag = dummy_incr;
+						max_windowsize = windowsize;
+						avg_rxtap = (max_rxtap +
+								min_rxtap) / 2;
+					}
+					i = max_tap;
+					rxtapfound = false;
+				}
+			}
+		}
+		if (!dummy_incr) {
+			rxtapfound = false;
+			min_rxtap = 0;
+			max_rxtap = 0;
+		}
+	}
+	if (!dummy_flag)
+		cqspi->extra_dummy = false;
+	if (max_windowsize < 3)
+		return -EINVAL;
+
+	writel((txtap | avg_rxtap | CQSPI_REG_PHY_CONFIG_RESET_FLD_MASK),
+	       cqspi->iobase + CQSPI_REG_PHY_CONFIG);
+	writel((CQSPI_REG_PHY_CONFIG_RESYNC_FLD_MASK | txtap | avg_rxtap |
+	       CQSPI_REG_PHY_CONFIG_RESET_FLD_MASK),
+	       cqspi->iobase + CQSPI_REG_PHY_CONFIG);
+	if (cqspi->dll_mode == CQSPI_DLL_MODE_MASTER) {
+		ret = cqspi_wait_for_bit(cqspi->iobase + CQSPI_REG_DLL_LOWER,
+					 CQSPI_REG_DLL_LOWER_DLL_LOCK_MASK, 0);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static void cqspi_periodictuning(struct work_struct *work)
+{
+	struct delayed_work *d = to_delayed_work(work);
+	struct spi_nor *nor = container_of(d, struct spi_nor, complete_work);
+	struct cqspi_flash_pdata *f_pdata = nor->priv;
+	struct cqspi_st *cqspi = f_pdata->cqspi;
+	int ret;
+
+	if (!cqspi->request_complete.done)
+		wait_for_completion(&cqspi->request_complete);
+
+	reinit_completion(&cqspi->tuning_complete);
+	ret = cqspi_setdlldelay(nor);
+	complete_all(&cqspi->tuning_complete);
+	if (ret) {
+		dev_err(nor->dev,
+			"Setting dll delay error (%i)\n", ret);
+	} else {
+		schedule_delayed_work(&nor->complete_work,
+			msecs_to_jiffies(CQSPI_TUNING_PERIODICITY_MS));
+	}
+}
+
+static void cqspi_setup_ddrmode(struct spi_nor *nor)
+{
+	struct cqspi_flash_pdata *f_pdata = nor->priv;
+	struct cqspi_st *cqspi = f_pdata->cqspi;
+	u32 reg;
+
+	cqspi_controller_enable(cqspi, 0);
+
+	reg = readl(cqspi->iobase + CQSPI_REG_CONFIG);
+	reg |= (CQSPI_REG_CONFIG_PHY_ENABLE_MASK);
+	writel(reg, cqspi->iobase + CQSPI_REG_CONFIG);
+
+	/* Program POLL_CNT */
+	reg = readl(cqspi->iobase + CQSPI_REG_WRCOMPLETION);
+	reg &= ~CQSPI_REG_WRCOMPLETION_POLLCNT_MASK;
+	writel(reg, cqspi->iobase + CQSPI_REG_WRCOMPLETION);
+
+	reg |= (0x3 << CQSPI_REG_WRCOMPLETION_POLLCNY_LSB);
+	writel(reg, cqspi->iobase + CQSPI_REG_WRCOMPLETION);
+
+	reg = readl(cqspi->iobase + CQSPI_REG_CONFIG);
+	reg |= CQSPI_REG_CONFIG_DTR_PROT_EN_MASK;
+	writel(reg, cqspi->iobase + CQSPI_REG_CONFIG);
+
+	reg = readl(cqspi->iobase + CQSPI_REG_READCAPTURE);
+	reg |= CQSPI_REG_READCAPTURE_DQS_ENABLE;
+	writel(reg, cqspi->iobase + CQSPI_REG_READCAPTURE);
+
+	cqspi->edge_mode = CQSPI_EDGE_MODE_DDR;
+
+	cqspi_controller_enable(cqspi, 1);
+}
+
+static int cqspi_setup_edgemode(struct spi_nor *nor)
+{
+	int ret;
+
+	cqspi_setup_ddrmode(nor);
+
+	ret = cqspi_setdlldelay(nor);
+
+	return ret;
+}
+
 static void cqspi_controller_init(struct cqspi_st *cqspi)
 {
 	u32 reg;
@@ -1176,8 +1736,14 @@
 	/* Configure the remap address register, no remap */
 	writel(0, cqspi->iobase + CQSPI_REG_REMAP);
 
+	/* Reset the Delay lines */
+	writel(CQSPI_REG_PHY_CONFIG_RESET_FLD_MASK,
+	       cqspi->iobase + CQSPI_REG_PHY_CONFIG);
+
 	/* Disable all interrupts. */
 	writel(0, cqspi->iobase + CQSPI_REG_IRQMASK);
+	writel(CQSPI_REG_DMA_DST_ALL_I_DIS_MASK,
+	       cqspi->iobase + CQSPI_REG_DMA_DST_I_DIS);
 
 	/* Configure the SRAM split to 1:1 . */
 	writel(cqspi->fifo_depth / 2, cqspi->iobase + CQSPI_REG_SRAMPARTITION);
@@ -1193,15 +1759,207 @@
 	writel(cqspi->fifo_depth * cqspi->fifo_width / 8,
 	       cqspi->iobase + CQSPI_REG_INDIRECTWRWATERMARK);
 
-	/* Enable Direct Access Controller */
 	reg = readl(cqspi->iobase + CQSPI_REG_CONFIG);
-	reg |= CQSPI_REG_CONFIG_ENB_DIR_ACC_CTRL;
+	reg &= ~CQSPI_REG_CONFIG_DTR_PROT_EN_MASK;
+	reg &= ~CQSPI_REG_CONFIG_PHY_ENABLE_MASK;
+	if (cqspi->read_dma) {
+		reg &= ~CQSPI_REG_CONFIG_ENB_DIR_ACC_CTRL;
+		reg |= CQSPI_REG_CONFIG_DMA_MASK;
+	} else {
+		/* Enable Direct Access Controller */
+		reg |= CQSPI_REG_CONFIG_ENB_DIR_ACC_CTRL;
+	}
 	writel(reg, cqspi->iobase + CQSPI_REG_CONFIG);
 
 	cqspi_controller_enable(cqspi, 1);
 }
 
-static void cqspi_request_mmap_dma(struct cqspi_st *cqspi)
+static int cqspi_versal_flash_reset(struct cqspi_st *cqspi, u8 reset_type)
+{
+	struct platform_device *pdev = cqspi->pdev;
+	int ret;
+	int gpio;
+	enum of_gpio_flags flags;
+
+	if (reset_type == CQSPI_RESET_TYPE_HWPIN) {
+		gpio = of_get_named_gpio_flags(pdev->dev.of_node,
+					       "reset-gpios", 0, &flags);
+		if (!gpio_is_valid(gpio))
+			return -EIO;
+		ret = devm_gpio_request_one(&pdev->dev, gpio, flags,
+					    "flash-reset");
+		if (ret) {
+			dev_err(&pdev->dev,
+				"failed to get reset-gpios: %d\n", ret);
+			return -EIO;
+		}
+
+		/* Request for PIN */
+		cqspi->eemi_ops->pinctrl_request(CQSPI_MIO_NODE_ID_12);
+
+		/* Enable hysteresis in cmos receiver */
+		cqspi->eemi_ops->pinctrl_set_config(CQSPI_MIO_NODE_ID_12,
+			PM_PINCTRL_CONFIG_SCHMITT_CMOS,
+			PM_PINCTRL_INPUT_TYPE_SCHMITT);
+
+		/* Set the direction as output and enable the output */
+		gpio_direction_output(gpio, 1);
+
+		/* Disable Tri-state */
+		cqspi->eemi_ops->pinctrl_set_config(CQSPI_MIO_NODE_ID_12,
+			PM_PINCTRL_CONFIG_TRI_STATE,
+			PM_PINCTRL_TRI_STATE_DISABLE);
+		udelay(1);
+
+		/* Set value 0 to pin */
+		gpio_set_value(gpio, 0);
+		udelay(1);
+
+		/* Set value 1 to pin */
+		gpio_set_value(gpio, 1);
+		udelay(1);
+	} else {
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int cqspi_versal_indirect_read_dma(struct spi_nor *nor, u_char *rxbuf,
+					  loff_t from_addr, size_t n_rx)
+{
+	struct cqspi_flash_pdata *f_pdata = nor->priv;
+	struct cqspi_st *cqspi = f_pdata->cqspi;
+	void __iomem *reg_base = cqspi->iobase;
+	unsigned int rx_rem;
+	int ret = 0;
+	u32 reg;
+
+	rx_rem = n_rx % 4;
+	cqspi->bytes_to_rx = n_rx;
+	cqspi->bytes_to_dma = (n_rx - rx_rem);
+	cqspi->addr = from_addr;
+	cqspi->rxbuf = rxbuf;
+
+	if (cqspi->eemi_ops && cqspi->access_mode == CQSPI_LINEAR_MODE) {
+		cqspi_wait_idle(cqspi);
+		reg = readl(cqspi->iobase + CQSPI_REG_PHY_CONFIG);
+
+		if (cqspi->dll_mode != CQSPI_DLL_MODE_MASTER) {
+			/* Issue controller reset */
+			cqspi->eemi_ops->reset_assert(RESET_OSPI,
+						      PM_RESET_ACTION_ASSERT);
+		}
+		cqspi->eemi_ops->ioctl(DEV_OSPI, IOCTL_OSPI_MUX_SELECT,
+				       PM_OSPI_MUX_SEL_DMA, 0, NULL);
+		cqspi->access_mode = CQSPI_DMA_MODE;
+		if (cqspi->dll_mode != CQSPI_DLL_MODE_MASTER) {
+			cqspi->eemi_ops->reset_assert(RESET_OSPI,
+						      PM_RESET_ACTION_RELEASE);
+		}
+		cqspi_wait_idle(cqspi);
+		if (cqspi->dll_mode != CQSPI_DLL_MODE_MASTER) {
+			cqspi_controller_init(cqspi);
+			cqspi->current_cs = -1;
+			cqspi->sclk = 0;
+
+			ret = cqspi_set_protocol(nor, 1);
+			if (ret)
+				return ret;
+
+			if (cqspi->edge_mode == CQSPI_EDGE_MODE_DDR) {
+				cqspi_setup_ddrmode(nor);
+				writel(CQSPI_REG_PHY_CONFIG_RESYNC_FLD_MASK |
+				       reg, cqspi->iobase +
+				       CQSPI_REG_PHY_CONFIG);
+			}
+
+			ret = cqspi_read_setup(nor);
+			if (ret)
+				return ret;
+		}
+	}
+
+	reg = readl(cqspi->iobase + CQSPI_REG_CONFIG);
+	reg |= CQSPI_REG_CONFIG_DMA_MASK;
+	writel(reg, cqspi->iobase + CQSPI_REG_CONFIG);
+
+	writel(from_addr, reg_base + CQSPI_REG_INDIRECTRDSTARTADDR);
+	writel(cqspi->bytes_to_dma, reg_base + CQSPI_REG_INDIRECTRDBYTES);
+	writel(CQSPI_REG_INDTRIG_ADDRRANGE_WIDTH,
+	       reg_base + CQSPI_REG_INDTRIG_ADDRRANGE);
+
+	/* Clear all interrupts. */
+	writel(CQSPI_IRQ_STATUS_MASK, reg_base + CQSPI_REG_IRQSTATUS);
+
+	/* Enable DMA done interrupt */
+	writel(CQSPI_REG_DMA_DST_I_EN_DONE,
+	       reg_base + CQSPI_REG_DMA_DST_I_EN);
+
+	/* Default DMA periph configuration */
+	writel(CQSPI_REG_DMA_VAL, reg_base + CQSPI_REG_DMA);
+
+	cqspi->dma_addr = dma_map_single(nor->dev, rxbuf, cqspi->bytes_to_dma,
+					 DMA_FROM_DEVICE);
+	if (dma_mapping_error(nor->dev, cqspi->dma_addr)) {
+		dev_err(nor->dev, "ERR:rxdma:memory not mapped\n");
+		goto failrd;
+	}
+	/* Configure DMA Dst address */
+	writel(lower_32_bits(cqspi->dma_addr),
+	       reg_base + CQSPI_REG_DMA_DST_ADDR);
+	writel(upper_32_bits(cqspi->dma_addr),
+	       reg_base + CQSPI_REG_DMA_DST_ADDR_MSB);
+
+	/* Configure DMA Src read address */
+	writel(cqspi->trigger_address, reg_base + CQSPI_REG_DMA_SRC_ADDR);
+
+	/* Set DMA destination size */
+	writel(cqspi->bytes_to_dma, reg_base + CQSPI_REG_DMA_DST_SIZE);
+
+	/* Set DMA destination control */
+	writel(CQSPI_REG_DMA_DST_CTRL_VAL, reg_base + CQSPI_REG_DMA_DST_CTRL);
+
+	writel(CQSPI_REG_INDIRECTRD_START_MASK,
+	       reg_base + CQSPI_REG_INDIRECTRD);
+
+	reinit_completion(&cqspi->transfer_complete);
+
+	if (!wait_for_completion_timeout(&cqspi->transfer_complete,
+			msecs_to_jiffies(CQSPI_READ_TIMEOUT_MS))) {
+		ret = -ETIMEDOUT;
+		goto failrd;
+	}
+
+	/* Check indirect done status */
+	ret = cqspi_wait_for_bit(reg_base + CQSPI_REG_INDIRECTRD,
+				 CQSPI_REG_INDIRECTRD_DONE_MASK, 0);
+	if (ret) {
+		dev_err(nor->dev,
+			"Indirect read completion error (%i)\n", ret);
+		goto failrd;
+	}
+
+	process_dma_irq(cqspi);
+
+	return 0;
+
+failrd:
+	/* Disable DMA interrupt */
+	writel(CQSPI_REG_DMA_DST_I_DIS_DONE,
+	       reg_base + CQSPI_REG_DMA_DST_I_DIS);
+
+	dma_unmap_single(nor->dev, cqspi->dma_addr, cqspi->bytes_to_dma,
+			 DMA_DEV_TO_MEM);
+
+	/* Cancel the indirect read */
+	writel(CQSPI_REG_INDIRECTWR_CANCEL_MASK,
+	       reg_base + CQSPI_REG_INDIRECTRD);
+
+	return ret;
+}
+
+static int cqspi_request_mmap_dma(struct cqspi_st *cqspi)
 {
 	dma_cap_mask_t mask;
 
@@ -1210,10 +1968,16 @@
 
 	cqspi->rx_chan = dma_request_chan_by_mask(&mask);
 	if (IS_ERR(cqspi->rx_chan)) {
-		dev_err(&cqspi->pdev->dev, "No Rx DMA available\n");
+		int ret = PTR_ERR(cqspi->rx_chan);
+
+		if (ret != -EPROBE_DEFER)
+			dev_err(&cqspi->pdev->dev, "No Rx DMA available\n");
 		cqspi->rx_chan = NULL;
+		return ret;
 	}
 	init_completion(&cqspi->rx_dma_complete);
+
+	return 0;
 }
 
 static int cqspi_setup_flash(struct cqspi_st *cqspi, struct device_node *np)
@@ -1223,7 +1987,7 @@
 	const struct cqspi_driver_platdata *ddata;
 	struct spi_nor_hwcaps hwcaps;
 	struct cqspi_flash_pdata *f_pdata;
-	struct spi_nor *nor;
+	struct spi_nor *nor = NULL;
 	struct mtd_info *mtd;
 	unsigned int cs;
 	int i, ret;
@@ -1281,6 +2045,13 @@
 			goto err;
 		}
 
+		if (ddata->quirks & CQSPI_SUPPORT_RESET) {
+			ret = cqspi->flash_reset(cqspi,
+						 CQSPI_RESET_TYPE_HWPIN);
+			if (ret)
+				goto err;
+		}
+
 		ret = spi_nor_scan(nor, NULL, &hwcaps);
 		if (ret)
 			goto err;
@@ -1291,16 +2062,31 @@
 
 		f_pdata->registered = true;
 
-		if (mtd->size <= cqspi->ahb_size) {
+		if (mtd->size <= cqspi->ahb_size &&
+		    !((ddata->quirks & CQSPI_DISABLE_DAC_MODE) || cqspi->read_dma)) {
 			f_pdata->use_direct_mode = true;
 			dev_dbg(nor->dev, "using direct mode for %s\n",
 				mtd->name);
 
-			if (!cqspi->rx_chan)
-				cqspi_request_mmap_dma(cqspi);
+			if (!cqspi->rx_chan) {
+				ret = cqspi_request_mmap_dma(cqspi);
+				if (ret == -EPROBE_DEFER)
+					goto err;
+			}
 		}
 	}
 
+	if (nor && !(nor->flags & SNOR_F_BROKEN_OCTAL_DDR)) {
+		ret = cqspi_setup_edgemode(nor);
+		if (ret)
+			goto err;
+		complete_all(&cqspi->tuning_complete);
+		complete_all(&cqspi->request_complete);
+		INIT_DELAYED_WORK(&nor->complete_work, cqspi_periodictuning);
+		schedule_delayed_work(&nor->complete_work,
+				msecs_to_jiffies(CQSPI_TUNING_PERIODICITY_MS));
+	}
+
 	return 0;
 
 err:
@@ -1321,6 +2107,8 @@
 	const struct cqspi_driver_platdata *ddata;
 	int ret;
 	int irq;
+	u32 idcode;
+	u32 version;
 
 	cqspi = devm_kzalloc(dev, sizeof(*cqspi), GFP_KERNEL);
 	if (!cqspi)
@@ -1363,13 +2151,13 @@
 	cqspi->ahb_size = resource_size(res_ahb);
 
 	init_completion(&cqspi->transfer_complete);
+	init_completion(&cqspi->tuning_complete);
+	init_completion(&cqspi->request_complete);
 
 	/* Obtain IRQ line. */
 	irq = platform_get_irq(pdev, 0);
-	if (irq < 0) {
-		dev_err(dev, "Cannot obtain IRQ.\n");
+	if (irq < 0)
 		return -ENXIO;
-	}
 
 	pm_runtime_enable(dev);
 	ret = pm_runtime_get_sync(dev);
@@ -1409,6 +2197,35 @@
 		cqspi->wr_delay = 5 * DIV_ROUND_UP(NSEC_PER_SEC,
 						   cqspi->master_ref_clk_hz);
 
+	if (ddata && (ddata->quirks & CQSPI_HAS_DMA)) {
+		dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
+		cqspi->read_dma = true;
+	}
+
+	if (of_device_is_compatible(pdev->dev.of_node,
+				    "xlnx,versal-ospi-1.0")) {
+		cqspi->eemi_ops = zynqmp_pm_get_eemi_ops();
+		if (IS_ERR(cqspi->eemi_ops))
+			return PTR_ERR(cqspi->eemi_ops);
+		if (cqspi->read_dma)
+			cqspi->indirect_read_dma =
+				cqspi_versal_indirect_read_dma;
+		cqspi->flash_reset = cqspi_versal_flash_reset;
+		cqspi->access_mode = CQSPI_DMA_MODE;
+		cqspi->dll_mode = CQSPI_DLL_MODE_BYPASS;
+
+		ret = cqspi->eemi_ops->get_chipid(&idcode, &version);
+		if (ret < 0) {
+			dev_err(dev, "Cannot get chipid is %d\n", ret);
+			goto probe_clk_failed;
+		}
+		if ((version & SILICON_VER_MASK) != SILICON_VER_1) {
+			cqspi->dll_mode = CQSPI_DLL_MODE_MASTER;
+			if (cqspi->master_ref_clk_hz >= TAP_GRAN_SEL_MIN_FREQ)
+				writel(0x1, cqspi->iobase + CQSPI_REG_ECO);
+		}
+	}
+
 	ret = devm_request_irq(dev, irq, cqspi_irq_handler, 0,
 			       pdev->name, cqspi);
 	if (ret) {
@@ -1420,6 +2237,9 @@
 	cqspi_controller_init(cqspi);
 	cqspi->current_cs = -1;
 	cqspi->sclk = 0;
+	cqspi->extra_dummy = false;
+	cqspi->edge_mode = CQSPI_EDGE_MODE_SDR;
+	cqspi->unalined_byte_cnt = false;
 
 	ret = cqspi_setup_flash(cqspi, np);
 	if (ret) {
@@ -1464,17 +2284,30 @@
 static int cqspi_suspend(struct device *dev)
 {
 	struct cqspi_st *cqspi = dev_get_drvdata(dev);
+	struct spi_master *master = dev_get_drvdata(dev);
+	int ret;
 
+	ret = spi_master_suspend(master);
 	cqspi_controller_enable(cqspi, 0);
-	return 0;
+
+	clk_disable_unprepare(cqspi->clk);
+
+	return ret;
 }
 
 static int cqspi_resume(struct device *dev)
 {
 	struct cqspi_st *cqspi = dev_get_drvdata(dev);
+	struct spi_master *master = dev_get_drvdata(dev);
 
-	cqspi_controller_enable(cqspi, 1);
-	return 0;
+	clk_prepare_enable(cqspi->clk);
+	cqspi_wait_idle(cqspi);
+	cqspi_controller_init(cqspi);
+
+	cqspi->current_cs = -1;
+	cqspi->sclk = 0;
+
+	return spi_master_resume(master);
 }
 
 static const struct dev_pm_ops cqspi__dev_pm_ops = {
@@ -1489,6 +2322,7 @@
 
 static const struct cqspi_driver_platdata cdns_qspi = {
 	.hwcaps_mask = CQSPI_BASE_HWCAPS_MASK,
+	.quirks = CQSPI_DISABLE_DAC_MODE,
 };
 
 static const struct cqspi_driver_platdata k2g_qspi = {
@@ -1501,6 +2335,13 @@
 	.quirks = CQSPI_NEEDS_WR_DELAY,
 };
 
+static const struct cqspi_driver_platdata versal_ospi = {
+	.hwcaps_mask = (SNOR_HWCAPS_READ | SNOR_HWCAPS_READ_FAST |
+			SNOR_HWCAPS_PP | SNOR_HWCAPS_PP_8_8_8 |
+			SNOR_HWCAPS_READ_1_1_8 | SNOR_HWCAPS_READ_8_8_8),
+	.quirks = CQSPI_HAS_DMA | CQSPI_SUPPORT_RESET,
+};
+
 static const struct of_device_id cqspi_dt_ids[] = {
 	{
 		.compatible = "cdns,qspi-nor",
@@ -1514,6 +2355,10 @@
 		.compatible = "ti,am654-ospi",
 		.data = &am654_ospi,
 	},
+	{
+		.compatible = "xlnx,versal-ospi-1.0",
+		.data = (void *)&versal_ospi,
+	},
 	{ /* end of table */ }
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/spi-nor/hisi-sfc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/spi-nor/hisi-sfc.c
@@ -396,8 +396,10 @@
 
 	for_each_available_child_of_node(dev->of_node, np) {
 		ret = hisi_spi_nor_register(np, host);
-		if (ret)
+		if (ret) {
+			of_node_put(np);
 			goto fail;
+		}
 
 		if (host->num_chip == HIFMC_MAX_CHIP_NUM) {
 			dev_warn(dev, "Flash device number exceeds the maximum chipselect number\n");
@@ -472,7 +474,6 @@
 
 	hisi_spi_nor_unregister_all(host);
 	mutex_destroy(&host->lock);
-	clk_disable_unprepare(host->clk);
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/spi-nor/intel-spi-pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/spi-nor/intel-spi-pci.c
@@ -61,6 +61,7 @@
 
 static const struct pci_device_id intel_spi_pci_ids[] = {
 	{ PCI_VDEVICE(INTEL, 0x02a4), (unsigned long)&bxt_info },
+	{ PCI_VDEVICE(INTEL, 0x06a4), (unsigned long)&bxt_info },
 	{ PCI_VDEVICE(INTEL, 0x18e0), (unsigned long)&bxt_info },
 	{ PCI_VDEVICE(INTEL, 0x19e0), (unsigned long)&bxt_info },
 	{ PCI_VDEVICE(INTEL, 0x34a4), (unsigned long)&bxt_info },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/spi-nor/intel-spi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/spi-nor/intel-spi.c
@@ -113,7 +113,7 @@
 #define ERASE_OPCODE_SHIFT		8
 #define ERASE_OPCODE_MASK		(0xff << ERASE_OPCODE_SHIFT)
 #define ERASE_64K_OPCODE_SHIFT		16
-#define ERASE_64K_OPCODE_MASK		(0xff << ERASE_OPCODE_SHIFT)
+#define ERASE_64K_OPCODE_MASK		(0xff << ERASE_64K_OPCODE_SHIFT)
 
 #define INTEL_SPI_TIMEOUT		5000 /* ms */
 #define INTEL_SPI_FIFO_SZ		64
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/spi-nor/spi-nor.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/spi-nor/spi-nor.c
@@ -22,6 +22,7 @@
 #include <linux/sched/task_stack.h>
 #include <linux/spi/flash.h>
 #include <linux/mtd/spi-nor.h>
+#include <linux/spi/spi.h>
 
 /* Define max times to check status register before we give up. */
 
@@ -37,7 +38,6 @@
  */
 #define CHIP_ERASE_2MB_READY_WAIT_JIFFIES	(40UL * HZ)
 
-#define SPI_NOR_MAX_ID_LEN	6
 #define SPI_NOR_MAX_ADDR_WIDTH	4
 
 struct sfdp_parameter_header {
@@ -196,7 +196,7 @@
 	u16		page_size;
 	u16		addr_width;
 
-	u16		flags;
+	u32		flags;
 #define SECT_4K			BIT(0)	/* SPINOR_OP_BE_4K works uniformly */
 #define SPI_NOR_NO_ERASE	BIT(1)	/* No erase command needed */
 #define SST_WRITE		BIT(2)	/* use SST byte programming */
@@ -233,7 +233,12 @@
 #define SPI_NOR_SKIP_SFDP	BIT(13)	/* Skip parsing of SFDP tables */
 #define USE_CLSR		BIT(14)	/* use CLSR command */
 #define SPI_NOR_OCTAL_READ	BIT(15)	/* Flash supports Octal Read */
+#define	SST_GLOBAL_PROT_UNLK	BIT(16)	/* Unlock the Global protection for
+					 * sst flashes
+					 */
+#define SPI_NOR_OCTAL_WRITE	BIT(17) /* Flash supports Octal Write */
 
+	int	(*quad_enable)(struct spi_nor *nor);
 	/* Part specific fixup hooks. */
 	const struct spi_nor_fixups *fixups;
 };
@@ -396,23 +401,27 @@
 static int read_sr(struct spi_nor *nor)
 {
 	int ret;
+	int len;
 
+	nor->isparallel ? (len = 2) : (len = 1);
 	if (nor->spimem) {
 		struct spi_mem_op op =
 			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDSR, 1),
 				   SPI_MEM_OP_NO_ADDR,
 				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_DATA_IN(1, nor->bouncebuf, 1));
+				   SPI_MEM_OP_DATA_IN(len, nor->bouncebuf, 1));
 
 		ret = spi_mem_exec_op(nor->spimem, &op);
 	} else {
-		ret = nor->read_reg(nor, SPINOR_OP_RDSR, nor->bouncebuf, 1);
+		ret = nor->read_reg(nor, SPINOR_OP_RDSR, nor->bouncebuf, len);
 	}
 
 	if (ret < 0) {
 		pr_err("error %d reading SR\n", (int) ret);
 		return ret;
 	}
+	if (nor->isparallel)
+		nor->bouncebuf[0] |= nor->bouncebuf[1];
 
 	return nor->bouncebuf[0];
 }
@@ -425,23 +434,27 @@
 static int read_fsr(struct spi_nor *nor)
 {
 	int ret;
+	int len;
 
+	nor->isparallel ? (len = 2) : (len = 1);
 	if (nor->spimem) {
 		struct spi_mem_op op =
 			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDFSR, 1),
 				   SPI_MEM_OP_NO_ADDR,
 				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_DATA_IN(1, nor->bouncebuf, 1));
+				   SPI_MEM_OP_DATA_IN(len, nor->bouncebuf, 1));
 
 		ret = spi_mem_exec_op(nor->spimem, &op);
 	} else {
-		ret = nor->read_reg(nor, SPINOR_OP_RDFSR, nor->bouncebuf, 1);
+		ret = nor->read_reg(nor, SPINOR_OP_RDFSR, nor->bouncebuf, len);
 	}
 
 	if (ret < 0) {
 		pr_err("error %d reading FSR\n", ret);
 		return ret;
 	}
+	if (nor->isparallel)
+		nor->bouncebuf[0] &= nor->bouncebuf[1];
 
 	return nor->bouncebuf[0];
 }
@@ -599,6 +612,16 @@
 
 static void spi_nor_set_4byte_opcodes(struct spi_nor *nor)
 {
+	/* Do some manufacturer fixups first */
+	switch (JEDEC_MFR(nor->info)) {
+	case SNOR_MFR_SPANSION:
+		/* No small sector erase for 4-byte command set */
+		nor->erase_opcode = SPINOR_OP_SE;
+		nor->mtd.erasesize = nor->info->sector_size;
+		break;
+	default:
+		break;
+	}
 	nor->read_opcode = spi_nor_convert_3to4_read(nor->read_opcode);
 	nor->program_opcode = spi_nor_convert_3to4_program(nor->program_opcode);
 	nor->erase_opcode = spi_nor_convert_3to4_erase(nor->erase_opcode);
@@ -663,21 +686,50 @@
 	return nor->write_reg(nor, SPINOR_OP_BRWR, nor->bouncebuf, 1);
 }
 
-static int spi_nor_write_ear(struct spi_nor *nor, u8 ear)
+static int spi_nor_write_ear(struct spi_nor *nor, u32 ear)
 {
-	nor->bouncebuf[0] = ear;
+	u8 code = SPINOR_OP_WREAR;
+	u8 addr;
+	int ret;
+	struct mtd_info *mtd = &nor->mtd;
+
+
+	if (mtd->size <= (0x1000000) << nor->shift)
+		return 0;
+
+	ear = ear % (u32)mtd->size;
+	addr = ear >> 24;
+
+	if (!nor->isstacked && addr == nor->curbank)
+		return 0;
+
+	if (nor->isstacked && mtd->size <= 0x2000000)
+		return 0;
+
+	if (nor->jedec_id == CFI_MFR_AMD)
+		code = SPINOR_OP_BRWR;
+	if (nor->jedec_id == CFI_MFR_ST ||
+	    nor->jedec_id == CFI_MFR_MACRONIX ||
+	    nor->jedec_id == SNOR_MFR_ISSI) {
+		write_enable(nor);
+		code = SPINOR_OP_WREAR;
+	}
+	nor->bouncebuf[0] = addr;
 
 	if (nor->spimem) {
 		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WREAR, 1),
+			SPI_MEM_OP(SPI_MEM_OP_CMD(code, 1),
 				   SPI_MEM_OP_NO_ADDR,
 				   SPI_MEM_OP_NO_DUMMY,
 				   SPI_MEM_OP_DATA_OUT(1, nor->bouncebuf, 1));
 
-		return spi_mem_exec_op(nor->spimem, &op);
+		ret = spi_mem_exec_op(nor->spimem, &op);
+	} else {
+		ret =  nor->write_reg(nor, code, nor->bouncebuf, 1);
 	}
+	nor->curbank = addr;
 
-	return nor->write_reg(nor, SPINOR_OP_WREAR, nor->bouncebuf, 1);
+	return ret;
 }
 
 static int winbond_set_4byte(struct spi_nor *nor, bool enable)
@@ -715,6 +767,49 @@
 	return nor->read_reg(nor, SPINOR_OP_XRDSR, sr, 1);
 }
 
+/**
+ * read_ear - Get the extended/bank address register value
+ * @nor:	Pointer to the flash control structure
+ * @info:	Pointer to the flash info structure
+ *
+ * This routine reads the Extended/bank address register value
+ *
+ * Return:	Negative if error occurred.
+ */
+static int read_ear(struct spi_nor *nor, struct flash_info *info)
+{
+	int ret;
+	u8 code;
+
+	/* This is actually Spansion */
+	if (JEDEC_MFR(info) == CFI_MFR_AMD)
+		code = SPINOR_OP_BRRD;
+	/* This is actually Micron */
+	else if (JEDEC_MFR(info) == CFI_MFR_ST ||
+		 JEDEC_MFR(info) == CFI_MFR_MACRONIX ||
+		 JEDEC_MFR(info) == SNOR_MFR_ISSI)
+		code = SPINOR_OP_RDEAR;
+	else
+		return -EINVAL;
+	if (nor->spimem) {
+		struct spi_mem_op op =
+			SPI_MEM_OP(SPI_MEM_OP_CMD(code, 1),
+				   SPI_MEM_OP_NO_ADDR,
+				   SPI_MEM_OP_NO_DUMMY,
+				   SPI_MEM_OP_DATA_IN(1, nor->bouncebuf, 1));
+
+		ret = spi_mem_exec_op(nor->spimem, &op);
+	} else {
+		ret = nor->read_reg(nor, code, nor->bouncebuf, 1);
+	}
+	if (ret < 0) {
+		pr_err("error %d reading EAR\n", ret);
+		return ret;
+	}
+
+	return nor->bouncebuf[0];
+}
+
 static int s3an_sr_ready(struct spi_nor *nor)
 {
 	int ret;
@@ -853,12 +948,68 @@
 }
 
 /*
+ * Write status Register and configuration register with 2 bytes
+ * The first byte will be written to the status register, while the
+ * second byte will be written to the configuration register.
+ * Return negative if error occurred.
+ */
+static int write_sr_cr(struct spi_nor *nor, u8 *sr_cr)
+{
+	int ret;
+
+	write_enable(nor);
+
+	if (nor->spimem) {
+		struct spi_mem_op op =
+			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRSR, 1),
+				   SPI_MEM_OP_NO_ADDR,
+				   SPI_MEM_OP_NO_DUMMY,
+				   SPI_MEM_OP_DATA_OUT(2, sr_cr, 1));
+
+		ret = spi_mem_exec_op(nor->spimem, &op);
+	} else {
+		ret = nor->write_reg(nor, SPINOR_OP_WRSR, sr_cr, 2);
+	}
+
+	if (ret < 0) {
+		dev_err(nor->dev,
+			"error while writing configuration register\n");
+		return -EINVAL;
+	}
+
+	ret = spi_nor_wait_till_ready(nor);
+	if (ret) {
+		dev_err(nor->dev,
+			"timeout while writing configuration register\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static inline void update_cs_flag(struct spi_nor *nor, u8 is_upper)
+{
+	if (is_upper) {
+		if (nor->spi)
+			nor->spi->master->flags |= SPI_MASTER_U_PAGE;
+		else
+			nor->flags |= SNOR_F_UPPER_CS;
+	} else {
+		if (nor->spi)
+			nor->spi->master->flags &= ~SPI_MASTER_U_PAGE;
+		else
+			nor->flags &= ~SNOR_F_UPPER_CS;
+	}
+}
+
+/*
  * Erase the whole flash memory
  *
  * Returns 0 if successful, non-zero otherwise.
  */
 static int erase_chip(struct spi_nor *nor)
 {
+	u32 ret;
 	dev_dbg(nor->dev, " %lldKiB\n", (long long)(nor->mtd.size >> 10));
 
 	if (nor->spimem) {
@@ -867,11 +1018,33 @@
 				   SPI_MEM_OP_NO_ADDR,
 				   SPI_MEM_OP_NO_DUMMY,
 				   SPI_MEM_OP_NO_DATA);
+		if (nor->isstacked)
+			nor->spi->master->flags &= ~SPI_MASTER_U_PAGE;
+		ret = spi_mem_exec_op(nor->spimem, &op);
+		if (ret)
+			return ret;
 
-		return spi_mem_exec_op(nor->spimem, &op);
+		if (nor->isstacked) {
+			/* Wait until previous write command finished */
+			ret = spi_nor_wait_till_ready(nor);
+			if (ret)
+				return ret;
+			nor->spi->master->flags |= SPI_MASTER_U_PAGE;
+			ret = spi_mem_exec_op(nor->spimem, &op);
+		}
+		return ret;
 	}
 
-	return nor->write_reg(nor, SPINOR_OP_CHIP_ERASE, NULL, 0);
+	if (nor->isstacked)
+		nor->flags &= ~SNOR_F_UPPER_CS;
+
+	ret = nor->write_reg(nor, SPINOR_OP_CHIP_ERASE, NULL, 0);
+	if (nor->isstacked && !ret) {
+		nor->flags |= SNOR_F_UPPER_CS;
+		write_enable(nor);
+		ret = nor->write_reg(nor, SPINOR_OP_CHIP_ERASE, NULL, 0);
+	}
+	return ret;
 }
 
 static int spi_nor_lock_and_prep(struct spi_nor *nor, enum spi_nor_ops ops)
@@ -1010,15 +1183,18 @@
 			continue;
 
 		erase = &map->erase_type[i];
-
-		/* Don't erase more than what the user has asked for. */
-		if (erase->size > len)
+		if (!erase->size)
 			continue;
 
 		/* Alignment is not mandatory for overlaid regions */
-		if (region->offset & SNOR_OVERLAID_REGION)
+		if (region->offset & SNOR_OVERLAID_REGION &&
+		    region->size <= len)
 			return erase;
 
+		/* Don't erase more than what the user has asked for. */
+		if (erase->size > len)
+			continue;
+
 		spi_nor_div_by_erase_size(erase, addr, &rem);
 		if (rem)
 			continue;
@@ -1152,6 +1328,7 @@
 			goto destroy_erase_cmd_list;
 
 		if (prev_erase != erase ||
+		    erase->size != cmd->size ||
 		    region->offset & SNOR_OVERLAID_REGION) {
 			cmd = spi_nor_init_erase_cmd(region, erase);
 			if (IS_ERR(cmd)) {
@@ -1239,7 +1416,7 @@
 static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
 {
 	struct spi_nor *nor = mtd_to_spi_nor(mtd);
-	u32 addr, len;
+	u32 addr, len, offset;
 	uint32_t rem;
 	int ret;
 
@@ -1292,8 +1469,29 @@
 	} else if (spi_nor_has_uniform_erase(nor)) {
 		while (len) {
 			write_enable(nor);
+			offset = addr;
+			if (nor->isparallel == 1)
+				offset /= 2;
+			if (nor->isstacked == 1) {
+				if (offset >= (mtd->size / 2)) {
+					offset = offset - (mtd->size / 2);
+					update_cs_flag(nor, 1);
+				} else {
+					update_cs_flag(nor, 0);
+				}
+			}
+			if (nor->addr_width == 3) {
+				/* Update Extended Address Register */
+				ret = spi_nor_write_ear(nor, offset);
+				if (ret)
+					goto erase_err;
+			}
+			ret = spi_nor_wait_till_ready(nor);
+			if (ret)
+				goto erase_err;
 
-			ret = spi_nor_erase_sector(nor, addr);
+			write_enable(nor);
+			ret = spi_nor_erase_sector(nor, offset);
 			if (ret)
 				goto erase_err;
 
@@ -1320,6 +1518,118 @@
 	return ret;
 }
 
+static inline u16 min_lockable_sectors(struct spi_nor *nor,
+				       u16 n_sectors)
+{
+	u16 lock_granularity;
+
+	/*
+	 * Revisit - SST (not used by us) has the same JEDEC ID as micron but
+	 * protected area table is similar to that of spansion.
+	 */
+	lock_granularity = max(1, n_sectors / M25P_MAX_LOCKABLE_SECTORS);
+	if (nor->jedec_id == CFI_MFR_ST)	/* Micron */
+		lock_granularity = 1;
+
+	return lock_granularity;
+}
+
+static inline uint32_t get_protected_area_start(struct spi_nor *nor,
+						u8 lock_bits)
+{
+	u16 n_sectors;
+	u32 sector_size;
+	u64 mtd_size;
+	struct mtd_info *mtd = &nor->mtd;
+
+	n_sectors = nor->n_sectors;
+	sector_size = nor->sector_size;
+	mtd_size = mtd->size;
+
+	if (nor->isparallel) {
+		sector_size = (nor->sector_size >> 1);
+		mtd_size = (mtd->size >> 1);
+	}
+	if (nor->isstacked) {
+		n_sectors = (nor->n_sectors >> 1);
+		mtd_size = (mtd->size >> 1);
+	}
+
+	return mtd_size - (1 << (lock_bits - 1)) *
+		min_lockable_sectors(nor, n_sectors) * sector_size;
+}
+
+static u8 min_protected_area_including_offset(struct spi_nor *nor,
+					      uint32_t offset)
+{
+	u8 lock_bits, lockbits_limit;
+
+	/*
+	 * Revisit - SST (not used by us) has the same JEDEC ID as micron but
+	 * protected area table is similar to that of spansion.
+	 * Mircon has 4 block protect bits.
+	 */
+	lockbits_limit = 7;
+	if (nor->jedec_id == CFI_MFR_ST)	/* Micron */
+		lockbits_limit = 15;
+
+	for (lock_bits = 1; lock_bits < lockbits_limit; lock_bits++) {
+		if (offset >= get_protected_area_start(nor, lock_bits))
+			break;
+	}
+	return lock_bits;
+}
+
+static int write_sr_modify_protection(struct spi_nor *nor, u8 status,
+				      u8 lock_bits)
+{
+	u8 status_new, bp_mask;
+	u8 val[2];
+
+	status_new = status & ~SR_BP_BIT_MASK;
+	bp_mask = (lock_bits << SR_BP_BIT_OFFSET) & SR_BP_BIT_MASK;
+
+	/* Micron */
+	if (nor->jedec_id == CFI_MFR_ST) {
+		/* To support chips with more than 896 sectors (56MB) */
+		status_new &= ~SR_BP3;
+
+		/* Protected area starts from top */
+		status_new &= ~SR_BP_TB;
+
+		if (lock_bits > 7)
+			bp_mask |= SR_BP3;
+	}
+
+	if (nor->is_lock)
+		status_new |= bp_mask;
+
+	write_enable(nor);
+
+	/* For spansion flashes */
+	if (nor->jedec_id == CFI_MFR_AMD) {
+		val[1] = read_cr(nor);
+		val[0] |= status_new;
+		if (write_sr_cr(nor, val) < 0)
+			return 1;
+	} else {
+		if (write_sr(nor, status_new) < 0)
+			return 1;
+	}
+	return 0;
+}
+
+static u8 bp_bits_from_sr(struct spi_nor *nor, u8 status)
+{
+	u8 ret;
+
+	ret = (((status) & SR_BP_BIT_MASK) >> SR_BP_BIT_OFFSET);
+	if (nor->jedec_id == 0x20)
+		ret |= ((status & SR_BP3) >> (SR_BP_BIT_OFFSET + 1));
+
+	return ret;
+}
+
 /* Write status register and ensure bits in mask match written values */
 static int write_sr_and_check(struct spi_nor *nor, u8 status_new, u8 mask)
 {
@@ -1616,13 +1926,42 @@
 {
 	struct spi_nor *nor = mtd_to_spi_nor(mtd);
 	int ret;
+	u8 status;
+	u8 lock_bits;
 
 	ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_LOCK);
 	if (ret)
 		return ret;
 
+	if (nor->isparallel == 1)
+		ofs = ofs >> nor->shift;
+
+	if (nor->isstacked == 1) {
+		if (ofs >= (mtd->size / 2)) {
+			ofs = ofs - (mtd->size / 2);
+			update_cs_flag(nor, 1);
+		} else {
+			update_cs_flag(nor, 0);
+		}
+	}
 	ret = nor->params.locking_ops->lock(nor, ofs, len);
+	/* Wait until finished previous command */
+	ret = spi_nor_wait_till_ready(nor);
+	if (ret)
+		goto err;
+
+	status = read_sr(nor);
+
+	lock_bits = min_protected_area_including_offset(nor, ofs);
 
+	/* Only modify protection if it will not unlock other areas */
+	if (lock_bits > bp_bits_from_sr(nor, status)) {
+		nor->is_lock = 1;
+		ret = write_sr_modify_protection(nor, status, lock_bits);
+	} else {
+		dev_err(nor->dev, "trying to unlock already locked area\n");
+	}
+err:
 	spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_UNLOCK);
 	return ret;
 }
@@ -1631,13 +1970,42 @@
 {
 	struct spi_nor *nor = mtd_to_spi_nor(mtd);
 	int ret;
+	u8 status;
+	u8 lock_bits;
 
 	ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_UNLOCK);
 	if (ret)
 		return ret;
 
+	if (nor->isparallel == 1)
+		ofs = ofs >> nor->shift;
+
+	if (nor->isstacked == 1) {
+		if (ofs >= (mtd->size / 2)) {
+			ofs = ofs - (mtd->size / 2);
+			update_cs_flag(nor, 1);
+		} else {
+			update_cs_flag(nor, 0);
+		}
+	}
 	ret = nor->params.locking_ops->unlock(nor, ofs, len);
+	/* Wait until finished previous command */
+	ret = spi_nor_wait_till_ready(nor);
+	if (ret)
+		goto err;
+
+	status = read_sr(nor);
 
+	lock_bits = min_protected_area_including_offset(nor, ofs + len) - 1;
+
+	/* Only modify protection if it will not lock other areas */
+	if (lock_bits < bp_bits_from_sr(nor, status)) {
+		nor->is_lock = 0;
+		ret = write_sr_modify_protection(nor, status, lock_bits);
+	} else {
+		dev_err(nor->dev, "trying to lock already unlocked area\n");
+	}
+err:
 	spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_LOCK);
 	return ret;
 }
@@ -1657,46 +2025,6 @@
 	return ret;
 }
 
-/*
- * Write status Register and configuration register with 2 bytes
- * The first byte will be written to the status register, while the
- * second byte will be written to the configuration register.
- * Return negative if error occurred.
- */
-static int write_sr_cr(struct spi_nor *nor, u8 *sr_cr)
-{
-	int ret;
-
-	write_enable(nor);
-
-	if (nor->spimem) {
-		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRSR, 1),
-				   SPI_MEM_OP_NO_ADDR,
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_DATA_OUT(2, sr_cr, 1));
-
-		ret = spi_mem_exec_op(nor->spimem, &op);
-	} else {
-		ret = nor->write_reg(nor, SPINOR_OP_WRSR, sr_cr, 2);
-	}
-
-	if (ret < 0) {
-		dev_err(nor->dev,
-			"error while writing configuration register\n");
-		return -EINVAL;
-	}
-
-	ret = spi_nor_wait_till_ready(nor);
-	if (ret) {
-		dev_err(nor->dev,
-			"timeout while writing configuration register\n");
-		return ret;
-	}
-
-	return 0;
-}
-
 /**
  * macronix_quad_enable() - set QE bit in Status Register.
  * @nor:	pointer to a 'struct spi_nor'
@@ -1826,6 +2154,7 @@
 	struct device *dev = nor->dev;
 	u8 *sr_cr = nor->bouncebuf;
 	int ret;
+	u8 cr_new;
 
 	/* Check current Quad Enable bit value. */
 	ret = read_cr(nor);
@@ -1837,7 +2166,11 @@
 	if (ret & CR_QUAD_EN_SPAN)
 		return 0;
 
-	sr_cr[1] = ret | CR_QUAD_EN_SPAN;
+	/*
+	 * Cannot write to sr_cr[1] directly, will be overwritten in read_sr()
+	 * in case nor->isparallel is set.
+	 */
+	cr_new = ret | CR_QUAD_EN_SPAN;
 
 	/* Keep the current value of the Status Register. */
 	ret = read_sr(nor);
@@ -1846,6 +2179,7 @@
 		return -EINVAL;
 	}
 	sr_cr[0] = ret;
+	sr_cr[1] = cr_new;
 
 	ret = write_sr_cr(nor, sr_cr);
 	if (ret)
@@ -2154,7 +2488,7 @@
  * For historical (and compatibility) reasons (before we got above config) some
  * old entries may be missing 4K flag.
  */
-static const struct flash_info spi_nor_ids[] = {
+static struct flash_info spi_nor_ids[] = {
 	/* Atmel -- some are (confusingly) marketed as "DataFlash" */
 	{ "at25fs010",  INFO(0x1f6601, 0, 32 * 1024,   4, SECT_4K) },
 	{ "at25fs040",  INFO(0x1f6604, 0, 64 * 1024,   8, SECT_4K) },
@@ -2244,29 +2578,62 @@
 	{ "640s33b",  INFO(0x898913, 0, 64 * 1024, 128, 0) },
 
 	/* ISSI */
+	{ "is25wp080d", INFO(0x9d7014, 0, 64 * 1024, 32, SECT_4K |
+		SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK) },
+	{ "is25wp016d", INFO(0x9d7015, 0, 64 * 1024, 32, SECT_4K |
+		SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK) },
 	{ "is25cd512",  INFO(0x7f9d20, 0, 32 * 1024,   2, SECT_4K) },
 	{ "is25lq040b", INFO(0x9d4013, 0, 64 * 1024,   8,
 			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
 	{ "is25lp016d", INFO(0x9d6015, 0, 64 * 1024,  32,
 			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
 	{ "is25lp080d", INFO(0x9d6014, 0, 64 * 1024,  16,
-			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			SPI_NOR_HAS_LOCK) },
 	{ "is25lp032",  INFO(0x9d6016, 0, 64 * 1024,  64,
-			SECT_4K | SPI_NOR_DUAL_READ) },
+			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_HAS_LOCK) },
 	{ "is25lp064",  INFO(0x9d6017, 0, 64 * 1024, 128,
-			SECT_4K | SPI_NOR_DUAL_READ) },
+			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_HAS_LOCK) },
 	{ "is25lp128",  INFO(0x9d6018, 0, 64 * 1024, 256,
-			SECT_4K | SPI_NOR_DUAL_READ) },
+			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_HAS_LOCK) },
 	{ "is25lp256",  INFO(0x9d6019, 0, 64 * 1024, 512,
 			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-			SPI_NOR_4B_OPCODES)
+			SPI_NOR_4B_OPCODES | SPI_NOR_HAS_LOCK)
 			.fixups = &is25lp256_fixups },
+	{ "is25wp256d", INFO(0x9d7019, 0, 64 * 1024, 512,
+			SECT_4K | SPI_NOR_DUAL_READ |
+			SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK |
+			SPI_NOR_4B_OPCODES) },
 	{ "is25wp032",  INFO(0x9d7016, 0, 64 * 1024,  64,
-			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			SPI_NOR_HAS_LOCK) },
 	{ "is25wp064",  INFO(0x9d7017, 0, 64 * 1024, 128,
-			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ
+			 | SPI_NOR_HAS_LOCK) },
 	{ "is25wp128",  INFO(0x9d7018, 0, 64 * 1024, 256,
 			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+	{ "is25wp256", INFO(0x9d7019, 0, 64 * 1024, 512,
+			    SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			    SPI_NOR_4B_OPCODES)
+		       .fixups = &is25lp256_fixups },
+	{ "is25lp512m", INFO(0x9d601a, 0, 64 * 1024, 1024,
+			SECT_4K | SPI_NOR_DUAL_READ |
+			SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK) },
+	{ "is25wp512m", INFO(0x9d701a, 0, 64 * 1024, 1024,
+			SECT_4K | SPI_NOR_DUAL_READ |
+			SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK |
+			SPI_NOR_4B_OPCODES) },
+	{ "is25lp01g", INFO(0x9d601b, 0, 64 * 1024, 2048,
+			SECT_4K | SPI_NOR_DUAL_READ |
+			SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK |
+			SPI_NOR_4B_OPCODES) },
+	{ "is25wp01g", INFO(0x9d701b, 0, 64 * 1024, 2048,
+			SECT_4K | SPI_NOR_DUAL_READ |
+			SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK |
+			SPI_NOR_4B_OPCODES) },
+	{ "is25wx256",  INFO(0x9d5b19, 0, 128 * 1024, 256,
+			     SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ |
+			     SPI_NOR_OCTAL_WRITE | SPI_NOR_4B_OPCODES) },
 
 	/* Macronix */
 	{ "mx25l512e",   INFO(0xc22010, 0, 64 * 1024,   1, SECT_4K) },
@@ -2297,6 +2664,14 @@
 	{ "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
 	{ "mx66u51235f", INFO(0xc2253a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
 	{ "mx66l1g45g",  INFO(0xc2201b, 0, 64 * 1024, 2048, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+	{ "mx66u1g45g",  INFO(0xc2253b, 0, 64 * 1024, 2048, SECT_4K |
+			SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+	{ "mx66l2g45g",  INFO(0xc2201c, 0, 64 * 1024, 4096, SECT_4K |
+			SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			SPI_NOR_4B_OPCODES) },
+	{ "mx66u2g45g",  INFO(0xc2253c, 0, 64 * 1024, 4096, SECT_4K |
+			SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			SPI_NOR_4B_OPCODES) },
 	{ "mx66l1g55g",  INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) },
 
 	/* Micron <--> ST Micro */
@@ -2305,31 +2680,50 @@
 	{ "n25q032a",	 INFO(0x20bb16, 0, 64 * 1024,   64, SPI_NOR_QUAD_READ) },
 	{ "n25q064",     INFO(0x20ba17, 0, 64 * 1024,  128, SECT_4K | SPI_NOR_QUAD_READ) },
 	{ "n25q064a",    INFO(0x20bb17, 0, 64 * 1024,  128, SECT_4K | SPI_NOR_QUAD_READ) },
-	{ "n25q128a11",  INFO(0x20bb18, 0, 64 * 1024,  256, SECT_4K | SPI_NOR_QUAD_READ) },
-	{ "n25q128a13",  INFO(0x20ba18, 0, 64 * 1024,  256, SECT_4K | SPI_NOR_QUAD_READ) },
-	{ "n25q256a",    INFO(0x20ba19, 0, 64 * 1024,  512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+	{ "n25q128a11",  INFO(0x20bb18, 0, 64 * 1024,  256, SECT_4K |
+			SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK) },
+	{ "n25q128a13",  INFO(0x20ba18, 0, 64 * 1024,  256, SECT_4K |
+			SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK) },
+	{ "n25q256a",    INFO(0x20ba19, 0, 64 * 1024,  512, SECT_4K |
+			SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_FSR |
+			SPI_NOR_HAS_LOCK) },
 	{ "n25q256ax1",  INFO(0x20bb19, 0, 64 * 1024,  512, SECT_4K | SPI_NOR_QUAD_READ) },
-	{ "n25q512ax3",  INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
-	{ "n25q00",      INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
-	{ "n25q00a",     INFO(0x20bb21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
+	{ "n25q512ax3",  INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K |
+			USE_FSR | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK) },
+	{ "n25q00",      INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K |
+			USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE |
+			SPI_NOR_HAS_LOCK | SPI_NOR_HAS_LOCK) },
+	{ "n25q00a",     INFO(0x20bb21, 0, 64 * 1024, 2048, SECT_4K |
+			USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE |
+			SPI_NOR_HAS_LOCK) },
 	{ "mt25ql02g",   INFO(0x20ba22, 0, 64 * 1024, 4096,
 			      SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
-			      NO_CHIP_ERASE) },
+			      NO_CHIP_ERASE | SPI_NOR_HAS_LOCK) },
 	{ "mt25qu512a (n25q512a)", INFO(0x20bb20, 0, 64 * 1024, 1024,
 					SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
 					SPI_NOR_QUAD_READ |
-					SPI_NOR_4B_OPCODES) },
-	{ "mt25qu02g",   INFO(0x20bb22, 0, 64 * 1024, 4096, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
+					SPI_NOR_HAS_LOCK) },
+	{ "mt25qu02g",   INFO(0x20bb22, 0, 64 * 1024, 4096, SECT_4K |
+			USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE |
+			SPI_NOR_HAS_LOCK) },
 
 	/* Micron */
 	{
 		"mt35xu512aba", INFO(0x2c5b1a, 0, 128 * 1024, 512,
 			SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ |
-			SPI_NOR_4B_OPCODES)
+			SPI_NOR_OCTAL_WRITE | SPI_NOR_4B_OPCODES)
 	},
+	{ "mt35xu01g",  INFO(0x2c5b1b, 0, 128 * 1024, 1024,
+			    SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ |
+			    SPI_NOR_OCTAL_WRITE | SPI_NOR_4B_OPCODES) },
 	{ "mt35xu02g",  INFO(0x2c5b1c, 0, 128 * 1024, 2048,
 			     SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ |
-			     SPI_NOR_4B_OPCODES) },
+			     SPI_NOR_OCTAL_WRITE | SPI_NOR_4B_OPCODES) },
+
+	/* Cypress */
+	{ "GD25LX256E",  INFO(0xc86819, 0, 64 * 1024, 512,
+			     SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ |
+			     SPI_NOR_OCTAL_WRITE | SPI_NOR_4B_OPCODES) },
 
 	/* PMC */
 	{ "pm25lv512",   INFO(0,        0, 32 * 1024,    2, SECT_4K_PMC) },
@@ -2342,9 +2736,11 @@
 	{ "s25sl032p",  INFO(0x010215, 0x4d00,  64 * 1024,  64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
 	{ "s25sl064p",  INFO(0x010216, 0x4d00,  64 * 1024, 128, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
 	{ "s25fl128s0", INFO6(0x012018, 0x4d0080, 256 * 1024, 64,
-			SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
+			SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR |
+			SPI_NOR_HAS_LOCK) },
 	{ "s25fl128s1", INFO6(0x012018, 0x4d0180, 64 * 1024, 256,
-			SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
+			SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR |
+			SPI_NOR_HAS_LOCK) },
 	{ "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, USE_CLSR) },
 	{ "s25fl256s1", INFO(0x010219, 0x4d01,  64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
 	{ "s25fl512s",  INFO6(0x010220, 0x4d0080, 256 * 1024, 256,
@@ -2373,6 +2769,8 @@
 	{ "s25fl064l",  INFO(0x016017,      0,  64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
 	{ "s25fl128l",  INFO(0x016018,      0,  64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
 	{ "s25fl256l",  INFO(0x016019,      0,  64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
+	{ "sst26wf016B", INFO(0xbf2651, 0, 64 * 1024, 32,
+			SECT_4K | SST_GLOBAL_PROT_UNLK) },
 
 	/* SST -- large erase sizes are "overlays", "sectors" are 4K */
 	{ "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024,  8, SECT_4K | SST_WRITE) },
@@ -2389,6 +2787,8 @@
 	{ "sst25wf080",  INFO(0xbf2505, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) },
 	{ "sst26wf016b", INFO(0xbf2651, 0, 64 * 1024, 32, SECT_4K |
 			      SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+	{ "sst26vf016b", INFO(0xbf2641, 0, 64 * 1024, 32,
+			      SECT_4K | SST_GLOBAL_PROT_UNLK) },
 	{ "sst26vf064b", INFO(0xbf2643, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
 
 	/* ST Microelectronics -- newer production may have feature updates */
@@ -2528,6 +2928,9 @@
 		return ERR_PTR(tmp);
 	}
 
+	for (tmp = 0; tmp < SPI_NOR_MAX_ID_LEN; tmp++)
+		nor->device_id[tmp] = id[tmp];
+
 	for (tmp = 0; tmp < ARRAY_SIZE(spi_nor_ids) - 1; tmp++) {
 		info = &spi_nor_ids[tmp];
 		if (info->id_len) {
@@ -2545,19 +2948,108 @@
 {
 	struct spi_nor *nor = mtd_to_spi_nor(mtd);
 	int ret;
+	u32 offset = from;
+	u32 stack_shift = 0;
+	u32 read_len = 0;
+	u32 rem_bank_len = 0;
+	u8 bank;
+	u8 is_ofst_odd = 0;
+	u8 cur_bank;
+	u8 nxt_bank;
+	u32 bank_size;
+	u_char *ptr;
 
+#define OFFSET_16_MB 0x1000000
 	dev_dbg(nor->dev, "from 0x%08x, len %zd\n", (u32)from, len);
 
+	if (nor->isparallel && (offset & 1)) {
+		/* We can hit this case when we use file system like ubifs */
+		from = (loff_t)(from - 1);
+		len = (size_t)(len + 1);
+		is_ofst_odd = 1;
+		ptr = kmalloc(len, GFP_KERNEL);
+		if (!ptr)
+			return -ENOMEM;
+
+	} else {
+		ptr = buf;
+	}
 	ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_READ);
-	if (ret)
+	if (ret) {
+		if (is_ofst_odd == 1)
+			kfree(ptr);
 		return ret;
+	}
 
 	while (len) {
-		loff_t addr = from;
+		if (nor->addr_width == 3) {
+			bank = (u32)from / (OFFSET_16_MB << nor->shift);
+			rem_bank_len = ((OFFSET_16_MB << nor->shift) *
+							(bank + 1)) - from;
+		}
+		offset = from;
+		if (nor->isparallel == 1)
+			offset /= 2;
+		if (nor->isstacked == 1) {
+			stack_shift = 1;
+			if (offset >= (mtd->size / 2)) {
+				offset = offset - (mtd->size / 2);
+				update_cs_flag(nor, 1);
+			} else {
+				update_cs_flag(nor, 0);
+			}
+		}
+		if (nor->addr_width == 4) {
+			/*
+			 * Some flash devices like N25Q512 have multiple dies
+			 * in it. Read operation in these devices is bounded
+			 * by its die segment. In a continuous read, across
+			 * multiple dies, when the last byte of the selected
+			 * die segment is read, the next byte read is the
+			 * first byte of the same die segment. This is Die
+			 * cross over issue. So to handle this issue, split
+			 * a read transaction, that spans across multiple
+			 * banks, into one read per bank. Bank size is 16MB
+			 * for single and dual stacked mode and 32MB for dual
+			 * parallel mode.
+			 */
+			if (nor->spi && nor->spi->multi_die) {
+				bank_size = (OFFSET_16_MB << nor->shift);
+				cur_bank = offset / bank_size;
+				nxt_bank = (offset + len) / bank_size;
+				if (cur_bank != nxt_bank)
+					rem_bank_len = ((bank_size *
+							(cur_bank + 1)) -
+							offset) << nor->shift;
+				else
+					rem_bank_len = (mtd->size >>
+							stack_shift) -
+							(offset << nor->shift);
+			} else {
+				rem_bank_len = (mtd->size >> stack_shift) -
+						(offset << nor->shift);
+			}
+		}
+		if (nor->addr_width == 3) {
+			ret = spi_nor_write_ear(nor, offset);
+			if (ret) {
+				dev_err(nor->dev, "While writing ear register\n");
+				goto read_err;
+			}
+		}
+		if (len < rem_bank_len)
+			read_len = len;
+		else
+			read_len = rem_bank_len;
+
+		/* Wait till previous write/erase is done. */
+		ret = spi_nor_wait_till_ready(nor);
+		if (ret)
+			goto read_err;
 
-		addr = spi_nor_convert_addr(nor, addr);
+		offset = spi_nor_convert_addr(nor, offset);
 
-		ret = spi_nor_read_data(nor, addr, len, buf);
+		ret = spi_nor_read_data(nor, (offset), read_len, ptr);
 		if (ret == 0) {
 			/* We shouldn't see 0-length reads */
 			ret = -EIO;
@@ -2567,14 +3059,23 @@
 			goto read_err;
 
 		WARN_ON(ret > len);
-		*retlen += ret;
+		if (is_ofst_odd == 1) {
+			memcpy(buf, (ptr + 1), (len - 1));
+			*retlen += (ret - 1);
+		} else {
+			*retlen += ret;
+		}
 		buf += ret;
+		if (!is_ofst_odd)
+			ptr += ret;
 		from += ret;
 		len -= ret;
 	}
 	ret = 0;
 
 read_err:
+	if (is_ofst_odd == 1)
+		kfree(ptr);
 	spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_READ);
 	return ret;
 }
@@ -2669,8 +3170,29 @@
 	struct spi_nor *nor = mtd_to_spi_nor(mtd);
 	size_t page_offset, page_remain, i;
 	ssize_t ret;
+	u32 offset, stack_shift = 0;
+	u8 bank = 0;
+	u32 rem_bank_len = 0;
 
+#define OFFSET_16_MB 0x1000000
 	dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len);
+	/*
+	 * Cannot write to odd offset in parallel mode,
+	 * so write 2 bytes first
+	 */
+	if (nor->isparallel && (to & 1)) {
+		u8 two[2] = {0xff, buf[0]};
+		size_t local_retlen;
+
+		ret = spi_nor_write(mtd, to & ~1, 2, &local_retlen, two);
+		if (ret < 0)
+			return ret;
+
+		*retlen += 1; /* We've written only one actual byte */
+		++buf;
+		--len;
+		++to;
+	}
 
 	ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_WRITE);
 	if (ret)
@@ -2680,6 +3202,11 @@
 		ssize_t written;
 		loff_t addr = to + i;
 
+		if (nor->addr_width == 3) {
+			bank = (u32)to / (OFFSET_16_MB << nor->shift);
+			rem_bank_len = ((OFFSET_16_MB << nor->shift) *
+							(bank + 1)) - to;
+		}
 		/*
 		 * If page_size is a power of two, the offset can be quickly
 		 * calculated with an AND operation. On the other cases we
@@ -2695,14 +3222,57 @@
 
 			page_offset = do_div(aux, nor->page_size);
 		}
-		/* the size of data remaining on the first page */
-		page_remain = min_t(size_t,
-				    nor->page_size - page_offset, len - i);
+		offset = (to + i);
+		if (nor->isparallel == 1)
+			offset /= 2;
+
+		if (nor->isstacked == 1) {
+			stack_shift = 1;
+			if (offset >= (mtd->size / 2)) {
+				offset = offset - (mtd->size / 2);
+				update_cs_flag(nor, 1);
+			} else {
+				update_cs_flag(nor, 0);
+			}
+		}
 
-		addr = spi_nor_convert_addr(nor, addr);
+		/* Die cross over issue is not handled */
+		if (nor->addr_width == 4)
+			rem_bank_len = (mtd->size >> stack_shift) - offset;
+		if (nor->addr_width == 3) {
+			ret = spi_nor_write_ear(nor, offset);
+			if (ret) {
+				dev_err(nor->dev, "While writing ear register\n");
+				goto write_err;
+			}
+		}
+		if (nor->isstacked == 1) {
+			if ((len - i) <= rem_bank_len) {
+				page_remain = min_t(size_t,
+						    nor->page_size -
+						    page_offset, len - i);
+			} else {
+				/*
+				 * the size of data remaining
+				 * on the first page
+				 */
+				page_remain = min_t(size_t,
+						    nor->page_size -
+						    page_offset, rem_bank_len);
+			}
+		} else {
+			page_remain = min_t(size_t,
+					    nor->page_size -
+					    page_offset, len - i);
+		}
+		ret = spi_nor_wait_till_ready(nor);
+		if (ret)
+			goto write_err;
+
+		offset = spi_nor_convert_addr(nor, offset);
 
 		write_enable(nor);
-		ret = spi_nor_write_data(nor, addr, page_remain, buf + i);
+		ret = spi_nor_write_data(nor, (offset), page_remain, buf + i);
 		if (ret < 0)
 			goto write_err;
 		written = ret;
@@ -2712,6 +3282,13 @@
 			goto write_err;
 		*retlen += written;
 		i += written;
+		if (written != page_remain) {
+			dev_err(nor->dev,
+				"While writing %zu bytes written %zd bytes\n",
+				page_remain, written);
+			ret = -EIO;
+			goto write_err;
+		}
 	}
 
 write_err:
@@ -2865,7 +3442,7 @@
  */
 static int spi_nor_read_raw(struct spi_nor *nor, u32 addr, size_t len, u8 *buf)
 {
-	int ret;
+	ssize_t ret;
 
 	while (len) {
 		ret = spi_nor_read_data(nor, addr, len, buf);
@@ -3471,6 +4048,9 @@
 	map->uniform_erase_type = map->uniform_region.offset &
 				  SNOR_ERASE_TYPE_MASK;
 
+	if (params->size > 0x1000000 && nor->addr_width == 3) {
+		return -EINVAL;
+	}
 	/* Stop here if not JESD216 rev A or later. */
 	if (bfpt_header->length < BFPT_DWORD_MAX)
 		return spi_nor_post_bfpt_fixups(nor, bfpt_header, &bfpt,
@@ -3699,7 +4279,7 @@
 	int i;
 
 	for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++) {
-		if (!(erase_type & BIT(i)))
+		if (!(erase[i].size && erase_type & BIT(erase[i].idx)))
 			continue;
 		if (region->size & erase[i].size_mask) {
 			spi_nor_region_mark_overlay(region);
@@ -3769,6 +4349,7 @@
 		offset = (region[i].offset & ~SNOR_ERASE_FLAGS_MASK) +
 			 region[i].size;
 	}
+	spi_nor_region_mark_end(&region[i - 1]);
 
 	save_uniform_erase_type = map->uniform_erase_type;
 	map->uniform_erase_type = spi_nor_sort_erase_mask(map,
@@ -3792,8 +4373,6 @@
 		if (!(regions_erase_type & BIT(erase[i].idx)))
 			spi_nor_set_erase_type(&erase[i], 0, 0xFF);
 
-	spi_nor_region_mark_end(&region[i - 1]);
-
 	return 0;
 }
 
@@ -4271,6 +4850,9 @@
 	u32 wanted_size = nor->info->sector_size;
 	int i;
 
+	if (mtd->erasesize &&
+	    JEDEC_MFR(nor->info) != SNOR_MFR_SPANSION)
+		return 0;
 	/*
 	 * The previous implementation handling Sector Erase commands assumed
 	 * that the SPI flash memory has an uniform layout then used only one
@@ -4290,6 +4872,9 @@
 			return -EINVAL;
 		nor->erase_opcode = erase->opcode;
 		mtd->erasesize = erase->size;
+		if (nor->shift)
+			mtd->erasesize = mtd->erasesize << nor->shift;
+
 		return 0;
 	}
 
@@ -4338,6 +4923,12 @@
 		 * Yet another reason to switch to spi-mem.
 		 */
 		ignored_mask = SNOR_HWCAPS_X_X_X;
+		if (!(nor->flags & SNOR_F_BROKEN_OCTAL_DDR)) {
+			if (hwcaps->mask & SNOR_HWCAPS_READ_8_8_8)
+				ignored_mask &= ~SNOR_HWCAPS_READ_8_8_8;
+			if (hwcaps->mask & SNOR_HWCAPS_PP_8_8_8)
+				ignored_mask &= ~SNOR_HWCAPS_PP_8_8_8;
+		}
 		if (shared_mask & ignored_mask) {
 			dev_dbg(nor->dev,
 				"SPI n-n-n protocols are not supported.\n");
@@ -4381,6 +4972,34 @@
 	return nor->params.setup(nor, hwcaps);
 }
 
+static int spi_nor_switch_micron_octal_ddr(struct spi_nor *nor)
+{
+	u8 cr = SPINOR_VCR_OCTAL_DDR;
+	int ret;
+
+	nor->addr_width = 3;
+	nor->is_addrvalid = true;
+	nor->reg_addr = 0x0;
+	if (nor->isstacked)
+		nor->flags &= ~SNOR_F_UPPER_CS;
+	write_enable(nor);
+	ret = nor->write_reg(nor, SPINOR_OP_WRCR, &cr, 1);
+	if (nor->isstacked && !ret) {
+		nor->flags |= SNOR_F_UPPER_CS;
+		write_enable(nor);
+		ret = nor->write_reg(nor, SPINOR_OP_WRCR, &cr, 1);
+	}
+	nor->is_addrvalid = false;
+	nor->addr_width = 4;
+	if (ret < 0) {
+		dev_err(nor->dev,
+			"error while writing configuration register\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static void macronix_set_default_init(struct spi_nor *nor)
 {
 	nor->params.quad_enable = macronix_quad_enable;
@@ -4443,11 +5062,10 @@
 
 	memcpy(&sfdp_params, &nor->params, sizeof(sfdp_params));
 
-	if (spi_nor_parse_sfdp(nor, &sfdp_params)) {
+	if (spi_nor_parse_sfdp(nor, &nor->params)) {
+		memcpy(&nor->params, &sfdp_params, sizeof(nor->params));
 		nor->addr_width = 0;
 		nor->flags &= ~SNOR_F_4B_OPCODES;
-	} else {
-		memcpy(&nor->params, &sfdp_params, sizeof(nor->params));
 	}
 }
 
@@ -4512,6 +5130,12 @@
 		spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_1_1_8],
 					  0, 8, SPINOR_OP_READ_1_1_8,
 					  SNOR_PROTO_1_1_8);
+		if (!(nor->flags & SNOR_F_BROKEN_OCTAL_DDR)) {
+			params->hwcaps.mask |= SNOR_HWCAPS_READ_8_8_8;
+			spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_8_8_8],
+						  0, 16, SPINOR_OP_READ_1_1_8,
+						  SNOR_PROTO_8_8_8);
+		}
 	}
 
 	/* Page Program settings. */
@@ -4519,6 +5143,18 @@
 	spi_nor_set_pp_settings(&params->page_programs[SNOR_CMD_PP],
 				SPINOR_OP_PP, SNOR_PROTO_1_1_1);
 
+	if (info->flags & SPI_NOR_OCTAL_WRITE) {
+		params->hwcaps.mask |= SNOR_HWCAPS_PP_1_1_8;
+		spi_nor_set_pp_settings(&params->page_programs[SNOR_CMD_PP_1_1_8],
+					SPINOR_OP_PP_1_1_8, SNOR_PROTO_1_1_8);
+		if (!(nor->flags & SNOR_F_BROKEN_OCTAL_DDR)) {
+			params->hwcaps.mask |= SNOR_HWCAPS_PP_8_8_8;
+			spi_nor_set_pp_settings(&params->page_programs[SNOR_CMD_PP_8_8_8],
+						SPINOR_OP_PP_1_1_8,
+						SNOR_PROTO_8_8_8);
+		}
+	}
+
 	/*
 	 * Sector Erase settings. Sort Erase Types in ascending order, with the
 	 * smallest erase size starting at BIT(0).
@@ -4544,9 +5180,7 @@
 
 static void spansion_post_sfdp_fixups(struct spi_nor *nor)
 {
-	struct mtd_info *mtd = &nor->mtd;
-
-	if (mtd->size <= SZ_16M)
+	if (nor->params.size <= SZ_16M)
 		return;
 
 	nor->flags |= SNOR_F_4B_OPCODES;
@@ -4679,6 +5313,18 @@
 {
 	int err;
 
+	/*
+	 * Atmel, SST, Intel/Numonyx, and others serial NOR tend to power up
+	 * with the software protection bits set
+	 */
+	if (JEDEC_MFR(nor->info) == SNOR_MFR_ATMEL ||
+	    JEDEC_MFR(nor->info) == SNOR_MFR_INTEL ||
+	    JEDEC_MFR(nor->info) == SNOR_MFR_SST ||
+	    nor->flags & SNOR_F_HAS_LOCK) {
+		write_enable(nor);
+		write_sr(nor, 0);
+		spi_nor_wait_till_ready(nor);
+	}
 	if (nor->clear_sr_bp) {
 		if (nor->params.quad_enable == spansion_quad_enable)
 			nor->clear_sr_bp = spi_nor_spansion_clear_sr_bp;
@@ -4697,7 +5343,8 @@
 		return err;
 	}
 
-	if (nor->addr_width == 4 && !(nor->flags & SNOR_F_4B_OPCODES)) {
+	if (nor->addr_width == 4 && !(nor->flags & SNOR_F_4B_OPCODES) &&
+	    (JEDEC_MFR(nor->info) != SNOR_MFR_SPANSION)) {
 		/*
 		 * If the RESET# pin isn't hooked up properly, or the system
 		 * otherwise doesn't perform a reset command in the boot
@@ -4730,7 +5377,9 @@
 {
 	/* restore the addressing mode */
 	if (nor->addr_width == 4 && !(nor->flags & SNOR_F_4B_OPCODES) &&
-	    nor->flags & SNOR_F_BROKEN_RESET)
+	    (nor->flags & SNOR_F_BROKEN_RESET) &&
+	    (JEDEC_MFR(nor->info) != SNOR_MFR_SPANSION) &&
+	    !(nor->flags & SNOR_F_4B_OPCODES))
 		nor->params.set_4byte(nor, false);
 }
 EXPORT_SYMBOL_GPL(spi_nor_restore);
@@ -4749,13 +5398,55 @@
 
 static int spi_nor_set_addr_width(struct spi_nor *nor)
 {
+	struct device_node *np = spi_nor_get_flash_node(nor);
+	struct device_node *np_spi;
 	if (nor->addr_width) {
 		/* already configured from SFDP */
 	} else if (nor->info->addr_width) {
 		nor->addr_width = nor->info->addr_width;
 	} else if (nor->mtd.size > 0x1000000) {
-		/* enable 4-byte addressing if the device exceeds 16MiB */
-		nor->addr_width = 4;
+#ifdef CONFIG_OF
+		np_spi = of_get_next_parent(np);
+		if (of_property_match_string(np_spi, "compatible",
+					     "xlnx,zynq-qspi-1.0") >= 0) {
+			int status;
+
+			nor->addr_width = 3;
+			nor->params.set_4byte(nor, false);
+			status = read_ear(nor, (struct flash_info *)nor->info);
+			if (status < 0)
+				dev_warn(nor->dev, "failed to read ear reg\n");
+			else
+				nor->curbank = status & EAR_SEGMENT_MASK;
+		} else {
+#endif
+			/*
+			 * enable 4-byte addressing if the
+			 * device exceeds 16MiB
+			 */
+			nor->addr_width = 4;
+			if (JEDEC_MFR(nor->info) == SNOR_MFR_SPANSION ||
+			    nor->flags & SNOR_F_4B_OPCODES) {
+				spi_nor_set_4byte_opcodes(nor);
+			} else {
+				np_spi = of_get_next_parent(np);
+				if (of_property_match_string(np_spi,
+							     "compatible",
+							     "xlnx,xps-spi-2.00.a") >= 0) {
+					nor->addr_width = 3;
+					nor->params.set_4byte(nor, false);
+				} else {
+					nor->params.set_4byte(nor, true);
+					if (nor->isstacked) {
+						update_cs_flag(nor, 1);
+						nor->params.set_4byte(nor, true);
+						update_cs_flag(nor, 0);
+					}
+				}
+			}
+#ifdef CONFIG_OF
+		}
+#endif
 	} else {
 		nor->addr_width = 3;
 	}
@@ -4784,8 +5475,8 @@
 					 info->id_len, info->id);
 }
 
-static const struct flash_info *spi_nor_get_flash_info(struct spi_nor *nor,
-						       const char *name)
+static struct flash_info *spi_nor_get_flash_info(struct spi_nor *nor,
+						 const char *name)
 {
 	const struct flash_info *info = NULL;
 
@@ -4806,7 +5497,7 @@
 
 		jinfo = spi_nor_read_id(nor);
 		if (IS_ERR(jinfo)) {
-			return jinfo;
+			return (struct flash_info *)jinfo;
 		} else if (jinfo != info) {
 			/*
 			 * JEDEC knows better, so overwrite platform ID. We
@@ -4821,19 +5512,21 @@
 		}
 	}
 
-	return info;
+	return (struct flash_info *)info;
 }
 
 int spi_nor_scan(struct spi_nor *nor, const char *name,
 		 const struct spi_nor_hwcaps *hwcaps)
 {
-	const struct flash_info *info;
+	struct flash_info *info = NULL;
 	struct device *dev = nor->dev;
 	struct mtd_info *mtd = &nor->mtd;
 	struct device_node *np = spi_nor_get_flash_node(nor);
 	struct spi_nor_flash_parameter *params = &nor->params;
 	int ret;
 	int i;
+	struct device_node *np_spi;
+	u32 is_dual;
 
 	ret = spi_nor_check(nor);
 	if (ret)
@@ -4879,6 +5572,11 @@
 	if (info->flags & SPI_NOR_HAS_LOCK)
 		nor->flags |= SNOR_F_HAS_LOCK;
 
+	if (((u16)JEDEC_MFR(nor->info) != SNOR_MFR_MICRON) &&
+	    ((u16)JEDEC_MFR(nor->info) != SNOR_MFR_CYPRESS) &&
+	    ((u16)JEDEC_MFR(nor->info) != SNOR_MFR_ISSI))
+		nor->flags |= SNOR_F_BROKEN_OCTAL_DDR;
+
 	/*
 	 * Atmel, SST, Intel/Numonyx, and others serial NOR tend to power up
 	 * with the software protection bits set.
@@ -4886,8 +5584,26 @@
 	if (JEDEC_MFR(nor->info) == SNOR_MFR_ATMEL ||
 	    JEDEC_MFR(nor->info) == SNOR_MFR_INTEL ||
 	    JEDEC_MFR(nor->info) == SNOR_MFR_SST ||
-	    nor->info->flags & SPI_NOR_HAS_LOCK)
-		nor->clear_sr_bp = spi_nor_clear_sr_bp;
+	    nor->flags & SNOR_F_HAS_LOCK) {
+		write_enable(nor);
+		write_sr(nor, 0);
+		if (info->flags & SST_GLOBAL_PROT_UNLK) {
+			write_enable(nor);
+			if (nor->spimem) {
+				struct spi_mem_op op =
+					SPI_MEM_OP(SPI_MEM_OP_CMD(GLOBAL_BLKPROT_UNLK, 1),
+						   SPI_MEM_OP_NO_ADDR,
+						   SPI_MEM_OP_NO_DUMMY,
+						   SPI_MEM_OP_NO_DATA);
+
+				spi_mem_exec_op(nor->spimem, &op);
+			} else {
+				/* Unlock global write protection bits */
+				nor->write_reg(nor, GLOBAL_BLKPROT_UNLK, NULL, 0);
+			}
+		}
+		spi_nor_wait_till_ready(nor);
+	}
 
 	/* Init flash parameters based on flash_info struct and SFDP */
 	spi_nor_init_params(nor);
@@ -4901,6 +5617,75 @@
 	mtd->size = params->size;
 	mtd->_erase = spi_nor_erase;
 	mtd->_read = spi_nor_read;
+	nor->page_size = params->page_size;
+#ifdef CONFIG_OF
+	np_spi = of_get_next_parent(np);
+	if (((of_property_match_string(np_spi, "compatible",
+				       "xlnx,zynq-qspi-1.0") >= 0) ||
+		(of_property_match_string(np_spi, "compatible",
+				"xlnx,zynqmp-qspi-1.0") >= 0)) ||
+		(of_property_match_string(np_spi, "compatible",
+				"xlnx,versal-qspi-1.0") >= 0) ||
+		(of_property_match_string(np_spi, "compatible",
+				"xlnx,versal-ospi-1.0") >= 0)) {
+		if (of_property_read_u32(np_spi, "is-dual",
+					 &is_dual) < 0) {
+			/* Default to single if prop not defined */
+			nor->shift = 0;
+			nor->isstacked = 0;
+			nor->isparallel = 0;
+		} else {
+			if (is_dual == 1) {
+				/* dual parallel */
+				nor->shift = 1;
+				info->sector_size <<= nor->shift;
+				info->page_size <<= nor->shift;
+				mtd->size <<= nor->shift;
+				nor->isparallel = 1;
+				nor->isstacked = 0;
+				nor->spi->master->flags |=
+						(SPI_MASTER_DATA_STRIPE
+						| SPI_MASTER_BOTH_CS);
+			} else {
+#ifdef CONFIG_SPI_ZYNQ_QSPI_DUAL_STACKED
+				/* dual stacked */
+				nor->shift = 0;
+				mtd->size <<= 1;
+				info->n_sectors <<= 1;
+				nor->isstacked = 1;
+				nor->isparallel = 0;
+#else
+				u32 is_stacked;
+
+				if (of_property_read_u32(np_spi,
+							 "is-stacked",
+							 &is_stacked) < 0) {
+					is_stacked = 0;
+				}
+				if (is_stacked) {
+					/* dual stacked */
+					nor->shift = 0;
+
+					mtd->size <<= 1;
+					info->n_sectors <<= 1;
+					nor->isstacked = 1;
+					nor->isparallel = 0;
+				} else {
+					/* single */
+					nor->shift = 0;
+					nor->isstacked = 0;
+					nor->isparallel = 0;
+				}
+#endif
+			}
+		}
+	}
+#else
+	/* Default to single */
+	nor->shift = 0;
+	nor->isstacked = 0;
+	nor->isparallel = 0;
+#endif
 	mtd->_resume = spi_nor_resume;
 
 	if (nor->params.locking_ops) {
@@ -4928,7 +5713,7 @@
 		mtd->flags |= MTD_NO_ERASE;
 
 	mtd->dev.parent = dev;
-	nor->page_size = params->page_size;
+	nor->jedec_id = info->id[0];
 	mtd->writebufsize = nor->page_size;
 
 	if (of_property_read_bool(np, "broken-flash-reset"))
@@ -4965,6 +5750,14 @@
 		mtd->name, (long long)mtd->size, (long long)(mtd->size >> 20),
 		mtd->erasesize, mtd->erasesize / 1024, mtd->numeraseregions);
 
+	if (hwcaps->mask & (SNOR_HWCAPS_READ_8_8_8 | SNOR_HWCAPS_PP_8_8_8)) {
+		if (!(nor->flags & SNOR_F_BROKEN_OCTAL_DDR)) {
+			ret = spi_nor_switch_micron_octal_ddr(nor);
+			if (ret)
+				return ret;
+		}
+	}
+
 	if (mtd->numeraseregions)
 		for (i = 0; i < mtd->numeraseregions; i++)
 			dev_dbg(dev,
@@ -5002,6 +5795,7 @@
 
 	spi_mem_set_drvdata(spimem, nor);
 
+	nor->spi = spi;
 	if (data && data->name)
 		nor->mtd.name = data->name;
 
@@ -5058,6 +5852,9 @@
 {
 	struct spi_nor *nor = spi_mem_get_drvdata(spimem);
 
+	if (nor->addr_width == 3 &&
+	    (nor->mtd.size >> nor->shift) > 0x1000000)
+		spi_nor_write_ear(nor, 0);
 	spi_nor_restore(nor);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/tests/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/tests/Makefile
@@ -1,19 +1,19 @@
 # SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_MTD_TESTS) += mtd_oobtest.o
-obj-$(CONFIG_MTD_TESTS) += mtd_pagetest.o
-obj-$(CONFIG_MTD_TESTS) += mtd_readtest.o
-obj-$(CONFIG_MTD_TESTS) += mtd_speedtest.o
-obj-$(CONFIG_MTD_TESTS) += mtd_stresstest.o
-obj-$(CONFIG_MTD_TESTS) += mtd_subpagetest.o
-obj-$(CONFIG_MTD_TESTS) += mtd_torturetest.o
-obj-$(CONFIG_MTD_TESTS) += mtd_nandecctest.o
-obj-$(CONFIG_MTD_TESTS) += mtd_nandbiterrs.o
+obj-$(CONFIG_MTD_TESTS) += mtd_oobtest.o mtd_test.o
+obj-$(CONFIG_MTD_TESTS) += mtd_pagetest.o mtd_test.o
+obj-$(CONFIG_MTD_TESTS) += mtd_readtest.o mtd_test.o
+obj-$(CONFIG_MTD_TESTS) += mtd_speedtest.o mtd_test.o
+obj-$(CONFIG_MTD_TESTS) += mtd_stresstest.o mtd_test.o
+obj-$(CONFIG_MTD_TESTS) += mtd_subpagetest.o mtd_test.o
+obj-$(CONFIG_MTD_TESTS) += mtd_torturetest.o mtd_test.o
+obj-$(CONFIG_MTD_TESTS) += mtd_nandecctest.o mtd_test.o
+obj-$(CONFIG_MTD_TESTS) += mtd_nandbiterrs.o mtd_test.o
 
-mtd_oobtest-objs := oobtest.o mtd_test.o
-mtd_pagetest-objs := pagetest.o mtd_test.o
-mtd_readtest-objs := readtest.o mtd_test.o
-mtd_speedtest-objs := speedtest.o mtd_test.o
-mtd_stresstest-objs := stresstest.o mtd_test.o
-mtd_subpagetest-objs := subpagetest.o mtd_test.o
-mtd_torturetest-objs := torturetest.o mtd_test.o
-mtd_nandbiterrs-objs := nandbiterrs.o mtd_test.o
+mtd_oobtest-objs := oobtest.o
+mtd_pagetest-objs := pagetest.o
+mtd_readtest-objs := readtest.o
+mtd_speedtest-objs := speedtest.o
+mtd_stresstest-objs := stresstest.o
+mtd_subpagetest-objs := subpagetest.o
+mtd_torturetest-objs := torturetest.o
+mtd_nandbiterrs-objs := nandbiterrs.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/tests/mtd_test.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/tests/mtd_test.c
@@ -25,6 +25,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(mtdtest_erase_eraseblock);
 
 static int is_block_bad(struct mtd_info *mtd, unsigned int ebnum)
 {
@@ -57,6 +58,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(mtdtest_scan_for_bad_eraseblocks);
 
 int mtdtest_erase_good_eraseblocks(struct mtd_info *mtd, unsigned char *bbt,
 				unsigned int eb, int ebcnt)
@@ -75,6 +77,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(mtdtest_erase_good_eraseblocks);
 
 int mtdtest_read(struct mtd_info *mtd, loff_t addr, size_t size, void *buf)
 {
@@ -92,6 +95,7 @@
 
 	return err;
 }
+EXPORT_SYMBOL_GPL(mtdtest_read);
 
 int mtdtest_write(struct mtd_info *mtd, loff_t addr, size_t size,
 		const void *buf)
@@ -107,3 +111,8 @@
 
 	return err;
 }
+EXPORT_SYMBOL_GPL(mtdtest_write);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("MTD function test helpers");
+MODULE_AUTHOR("Akinobu Mita");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/ubi/attach.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/ubi/attach.c
@@ -1447,7 +1447,7 @@
 	return err;
 }
 
-static struct ubi_attach_info *alloc_ai(void)
+static struct ubi_attach_info *alloc_ai(const char *slab_name)
 {
 	struct ubi_attach_info *ai;
 
@@ -1461,7 +1461,7 @@
 	INIT_LIST_HEAD(&ai->alien);
 	INIT_LIST_HEAD(&ai->fastmap);
 	ai->volumes = RB_ROOT;
-	ai->aeb_slab_cache = kmem_cache_create("ubi_aeb_slab_cache",
+	ai->aeb_slab_cache = kmem_cache_create(slab_name,
 					       sizeof(struct ubi_ainf_peb),
 					       0, 0, NULL);
 	if (!ai->aeb_slab_cache) {
@@ -1491,7 +1491,7 @@
 
 	err = -ENOMEM;
 
-	scan_ai = alloc_ai();
+	scan_ai = alloc_ai("ubi_aeb_slab_cache_fastmap");
 	if (!scan_ai)
 		goto out;
 
@@ -1557,7 +1557,7 @@
 	int err;
 	struct ubi_attach_info *ai;
 
-	ai = alloc_ai();
+	ai = alloc_ai("ubi_aeb_slab_cache");
 	if (!ai)
 		return -ENOMEM;
 
@@ -1575,7 +1575,7 @@
 		if (err > 0 || mtd_is_eccerr(err)) {
 			if (err != UBI_NO_FASTMAP) {
 				destroy_ai(ai);
-				ai = alloc_ai();
+				ai = alloc_ai("ubi_aeb_slab_cache");
 				if (!ai)
 					return -ENOMEM;
 
@@ -1614,7 +1614,7 @@
 	if (ubi->fm && ubi_dbg_chk_fastmap(ubi)) {
 		struct ubi_attach_info *scan_ai;
 
-		scan_ai = alloc_ai();
+		scan_ai = alloc_ai("ubi_aeb_slab_cache_dbg_chk_fastmap");
 		if (!scan_ai) {
 			err = -ENOMEM;
 			goto out_wl;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/ubi/build.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/ubi/build.c
@@ -350,9 +350,6 @@
 	 * we still can use 'ubi->ubi_num'.
 	 */
 	ubi = container_of(dev, struct ubi_device, dev);
-	ubi = ubi_get_device(ubi->ubi_num);
-	if (!ubi)
-		return -ENODEV;
 
 	if (attr == &dev_eraseblock_size)
 		ret = sprintf(buf, "%d\n", ubi->leb_size);
@@ -381,7 +378,6 @@
 	else
 		ret = -EINVAL;
 
-	ubi_put_device(ubi);
 	return ret;
 }
 
@@ -471,6 +467,7 @@
 			err = ubi_add_volume(ubi, ubi->volumes[i]);
 			if (err) {
 				ubi_err(ubi, "cannot add volume %d", i);
+				ubi->volumes[i] = NULL;
 				goto out_volumes;
 			}
 		}
@@ -664,6 +661,21 @@
 						ubi->vid_hdr_aloffset;
 	}
 
+	/*
+	 * Memory allocation for VID header is ubi->vid_hdr_alsize
+	 * which is described in comments in io.c.
+	 * Make sure VID header shift + UBI_VID_HDR_SIZE not exceeds
+	 * ubi->vid_hdr_alsize, so that all vid header operations
+	 * won't access memory out of bounds.
+	 */
+	if ((ubi->vid_hdr_shift + UBI_VID_HDR_SIZE) > ubi->vid_hdr_alsize) {
+		ubi_err(ubi, "Invalid VID header offset %d, VID header shift(%d)"
+			" + VID header size(%zu) > VID header aligned size(%d).",
+			ubi->vid_hdr_offset, ubi->vid_hdr_shift,
+			UBI_VID_HDR_SIZE, ubi->vid_hdr_alsize);
+		return -EINVAL;
+	}
+
 	/* Similar for the data offset */
 	ubi->leb_start = ubi->vid_hdr_offset + UBI_VID_HDR_SIZE;
 	ubi->leb_start = ALIGN(ubi->leb_start, ubi->min_io_size);
@@ -853,6 +865,13 @@
 		return -EINVAL;
 	}
 
+	/* UBI cannot work on flashes with zero erasesize. */
+	if (!mtd->erasesize) {
+		pr_err("ubi: refuse attaching mtd%d - zero erasesize flash is not supported\n",
+			mtd->index);
+		return -EINVAL;
+	}
+
 	if (ubi_num == UBI_DEV_NUM_AUTO) {
 		/* Search for an empty slot in the @ubi_devices array */
 		for (ubi_num = 0; ubi_num < UBI_MAX_DEVICES; ubi_num++)
@@ -956,9 +975,6 @@
 			goto out_detach;
 	}
 
-	/* Make device "available" before it becomes accessible via sysfs */
-	ubi_devices[ubi_num] = ubi;
-
 	err = uif_init(ubi);
 	if (err)
 		goto out_detach;
@@ -1003,6 +1019,7 @@
 	wake_up_process(ubi->bgt_thread);
 	spin_unlock(&ubi->wl_lock);
 
+	ubi_devices[ubi_num] = ubi;
 	ubi_notify_all(ubi, UBI_VOLUME_ADDED, NULL);
 	return ubi_num;
 
@@ -1011,7 +1028,6 @@
 out_uif:
 	uif_close(ubi);
 out_detach:
-	ubi_devices[ubi_num] = NULL;
 	ubi_wl_close(ubi);
 	ubi_free_internal_volumes(ubi);
 	vfree(ubi->vtbl);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/ubi/debug.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/ubi/debug.c
@@ -392,9 +392,6 @@
 {
 	struct ubi_device *ubi = s->private;
 
-	if (*pos == 0)
-		return SEQ_START_TOKEN;
-
 	if (*pos < ubi->peb_count)
 		return pos;
 
@@ -408,8 +405,6 @@
 {
 	struct ubi_device *ubi = s->private;
 
-	if (v == SEQ_START_TOKEN)
-		return pos;
 	(*pos)++;
 
 	if (*pos < ubi->peb_count)
@@ -431,11 +426,8 @@
 	int err;
 
 	/* If this is the start, print a header */
-	if (iter == SEQ_START_TOKEN) {
-		seq_puts(s,
-			 "physical_block_number\terase_count\tblock_status\tread_status\n");
-		return 0;
-	}
+	if (*block_number == 0)
+		seq_puts(s, "physical_block_number\terase_count\n");
 
 	err = ubi_io_is_bad(ubi, *block_number);
 	if (err)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/ubi/eba.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/ubi/eba.c
@@ -599,7 +599,7 @@
 	int err, pnum, scrub = 0, vol_id = vol->vol_id;
 	struct ubi_vid_io_buf *vidb;
 	struct ubi_vid_hdr *vid_hdr;
-	uint32_t uninitialized_var(crc);
+	uint32_t crc;
 
 	err = leb_read_lock(ubi, vol_id, lnum);
 	if (err)
@@ -947,7 +947,7 @@
 				  int offset, int len)
 {
 	struct ubi_device *ubi = vol->ubi;
-	int pnum, opnum, err, vol_id = vol->vol_id;
+	int pnum, opnum, err, err2, vol_id = vol->vol_id;
 
 	pnum = ubi_wl_get_peb(ubi);
 	if (pnum < 0) {
@@ -982,10 +982,19 @@
 out_put:
 	up_read(&ubi->fm_eba_sem);
 
-	if (err && pnum >= 0)
-		err = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1);
-	else if (!err && opnum >= 0)
-		err = ubi_wl_put_peb(ubi, vol_id, lnum, opnum, 0);
+	if (err && pnum >= 0) {
+		err2 = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1);
+		if (err2) {
+			ubi_warn(ubi, "failed to return physical eraseblock %d, error %d",
+				 pnum, err2);
+		}
+	} else if (!err && opnum >= 0) {
+		err2 = ubi_wl_put_peb(ubi, vol_id, lnum, opnum, 0);
+		if (err2) {
+			ubi_warn(ubi, "failed to return physical eraseblock %d, error %d",
+				 opnum, err2);
+		}
+	}
 
 	return err;
 }
@@ -1551,6 +1560,7 @@
 					  GFP_KERNEL);
 		if (!fm_eba[i]) {
 			ret = -ENOMEM;
+			kfree(scan_eba[i]);
 			goto out_free;
 		}
 
@@ -1586,7 +1596,7 @@
 	}
 
 out_free:
-	for (i = 0; i < num_volumes; i++) {
+	while (--i >= 0) {
 		if (!ubi->volumes[i])
 			continue;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/ubi/fastmap-wl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/ubi/fastmap-wl.c
@@ -39,6 +39,13 @@
 	return victim;
 }
 
+static inline void return_unused_peb(struct ubi_device *ubi,
+				     struct ubi_wl_entry *e)
+{
+	wl_tree_add(e, &ubi->free);
+	ubi->free_count++;
+}
+
 /**
  * return_unused_pool_pebs - returns unused PEB to the free tree.
  * @ubi: UBI device description object
@@ -52,23 +59,10 @@
 
 	for (i = pool->used; i < pool->size; i++) {
 		e = ubi->lookuptbl[pool->pebs[i]];
-		wl_tree_add(e, &ubi->free);
-		ubi->free_count++;
+		return_unused_peb(ubi, e);
 	}
 }
 
-static int anchor_pebs_available(struct rb_root *root)
-{
-	struct rb_node *p;
-	struct ubi_wl_entry *e;
-
-	ubi_rb_for_each_entry(p, e, root, u.rb)
-		if (e->pnum < UBI_FM_MAX_START)
-			return 1;
-
-	return 0;
-}
-
 /**
  * ubi_wl_get_fm_peb - find a physical erase block with a given maximal number.
  * @ubi: UBI device description object
@@ -277,8 +271,26 @@
 int ubi_ensure_anchor_pebs(struct ubi_device *ubi)
 {
 	struct ubi_work *wrk;
+	struct ubi_wl_entry *anchor;
 
 	spin_lock(&ubi->wl_lock);
+
+	/* Do we already have an anchor? */
+	if (ubi->fm_anchor) {
+		spin_unlock(&ubi->wl_lock);
+		return 0;
+	}
+
+	/* See if we can find an anchor PEB on the list of free PEBs */
+	anchor = ubi_wl_get_fm_peb(ubi, 1);
+	if (anchor) {
+		ubi->fm_anchor = anchor;
+		spin_unlock(&ubi->wl_lock);
+		return 0;
+	}
+
+	/* No luck, trigger wear leveling to produce a new anchor PEB */
+	ubi->fm_do_produce_anchor = 1;
 	if (ubi->wl_scheduled) {
 		spin_unlock(&ubi->wl_lock);
 		return 0;
@@ -294,7 +306,6 @@
 		return -ENOMEM;
 	}
 
-	wrk->anchor = 1;
 	wrk->func = &wear_leveling_worker;
 	__schedule_ubi_work(ubi, wrk);
 	return 0;
@@ -356,6 +367,11 @@
 	return_unused_pool_pebs(ubi, &ubi->fm_pool);
 	return_unused_pool_pebs(ubi, &ubi->fm_wl_pool);
 
+	if (ubi->fm_anchor) {
+		return_unused_peb(ubi, ubi->fm_anchor);
+		ubi->fm_anchor = NULL;
+	}
+
 	if (ubi->fm) {
 		for (i = 0; i < ubi->fm->used_blocks; i++)
 			kfree(ubi->fm->e[i]);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/ubi/fastmap.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/ubi/fastmap.c
@@ -64,7 +64,7 @@
 		return 0;
 
 	for (pnum = 0; pnum < ubi->peb_count; pnum++) {
-		if (test_bit(pnum, seen) && ubi->lookuptbl[pnum]) {
+		if (!test_bit(pnum, seen) && ubi->lookuptbl[pnum]) {
 			ubi_err(ubi, "self-check failed for PEB %d, fastmap didn't see it", pnum);
 			ret = -EINVAL;
 		}
@@ -86,9 +86,10 @@
 		sizeof(struct ubi_fm_scan_pool) +
 		sizeof(struct ubi_fm_scan_pool) +
 		(ubi->peb_count * sizeof(struct ubi_fm_ec)) +
-		(sizeof(struct ubi_fm_eba) +
-		(ubi->peb_count * sizeof(__be32))) +
-		sizeof(struct ubi_fm_volhdr) * UBI_MAX_VOLUMES;
+		((sizeof(struct ubi_fm_eba) +
+		  sizeof(struct ubi_fm_volhdr)) *
+		 (UBI_MAX_VOLUMES + UBI_INT_VOL_COUNT)) +
+		(ubi->peb_count * sizeof(__be32));
 	return roundup(size, ubi->leb_size);
 }
 
@@ -468,7 +469,9 @@
 			if (err == UBI_IO_FF_BITFLIPS)
 				scrub = 1;
 
-			add_aeb(ai, free, pnum, ec, scrub);
+			ret = add_aeb(ai, free, pnum, ec, scrub);
+			if (ret)
+				goto out;
 			continue;
 		} else if (err == 0 || err == UBI_IO_BITFLIPS) {
 			dbg_bld("Found non empty PEB:%i in pool", pnum);
@@ -638,8 +641,10 @@
 		if (fm_pos >= fm_size)
 			goto fail_bad;
 
-		add_aeb(ai, &ai->free, be32_to_cpu(fmec->pnum),
-			be32_to_cpu(fmec->ec), 0);
+		ret = add_aeb(ai, &ai->free, be32_to_cpu(fmec->pnum),
+			      be32_to_cpu(fmec->ec), 0);
+		if (ret)
+			goto fail;
 	}
 
 	/* read EC values from used list */
@@ -649,8 +654,10 @@
 		if (fm_pos >= fm_size)
 			goto fail_bad;
 
-		add_aeb(ai, &used, be32_to_cpu(fmec->pnum),
-			be32_to_cpu(fmec->ec), 0);
+		ret = add_aeb(ai, &used, be32_to_cpu(fmec->pnum),
+			      be32_to_cpu(fmec->ec), 0);
+		if (ret)
+			goto fail;
 	}
 
 	/* read EC values from scrub list */
@@ -660,8 +667,10 @@
 		if (fm_pos >= fm_size)
 			goto fail_bad;
 
-		add_aeb(ai, &used, be32_to_cpu(fmec->pnum),
-			be32_to_cpu(fmec->ec), 1);
+		ret = add_aeb(ai, &used, be32_to_cpu(fmec->pnum),
+			      be32_to_cpu(fmec->ec), 1);
+		if (ret)
+			goto fail;
 	}
 
 	/* read EC values from erase list */
@@ -671,8 +680,10 @@
 		if (fm_pos >= fm_size)
 			goto fail_bad;
 
-		add_aeb(ai, &ai->erase, be32_to_cpu(fmec->pnum),
-			be32_to_cpu(fmec->ec), 1);
+		ret = add_aeb(ai, &ai->erase, be32_to_cpu(fmec->pnum),
+			      be32_to_cpu(fmec->ec), 1);
+		if (ret)
+			goto fail;
 	}
 
 	ai->mean_ec = div_u64(ai->ec_sum, ai->ec_count);
@@ -1137,7 +1148,7 @@
 	struct rb_node *tmp_rb;
 	int ret, i, j, free_peb_count, used_peb_count, vol_count;
 	int scrub_peb_count, erase_peb_count;
-	unsigned long *seen_pebs = NULL;
+	unsigned long *seen_pebs;
 
 	fm_raw = ubi->fm_buf;
 	memset(ubi->fm_buf, 0, ubi->fm_size);
@@ -1151,7 +1162,7 @@
 	dvbuf = new_fm_vbuf(ubi, UBI_FM_DATA_VOLUME_ID);
 	if (!dvbuf) {
 		ret = -ENOMEM;
-		goto out_kfree;
+		goto out_free_avbuf;
 	}
 
 	avhdr = ubi_get_vid_hdr(avbuf);
@@ -1160,7 +1171,7 @@
 	seen_pebs = init_seen(ubi);
 	if (IS_ERR(seen_pebs)) {
 		ret = PTR_ERR(seen_pebs);
-		goto out_kfree;
+		goto out_free_dvbuf;
 	}
 
 	spin_lock(&ubi->volumes_lock);
@@ -1328,7 +1339,7 @@
 	ret = ubi_io_write_vid_hdr(ubi, new_fm->e[0]->pnum, avbuf);
 	if (ret) {
 		ubi_err(ubi, "unable to write vid_hdr to fastmap SB!");
-		goto out_kfree;
+		goto out_free_seen;
 	}
 
 	for (i = 0; i < new_fm->used_blocks; i++) {
@@ -1350,7 +1361,7 @@
 		if (ret) {
 			ubi_err(ubi, "unable to write vid_hdr to PEB %i!",
 				new_fm->e[i]->pnum);
-			goto out_kfree;
+			goto out_free_seen;
 		}
 	}
 
@@ -1360,7 +1371,7 @@
 		if (ret) {
 			ubi_err(ubi, "unable to write fastmap to PEB %i!",
 				new_fm->e[i]->pnum);
-			goto out_kfree;
+			goto out_free_seen;
 		}
 	}
 
@@ -1370,10 +1381,13 @@
 	ret = self_check_seen(ubi, seen_pebs);
 	dbg_bld("fastmap written!");
 
-out_kfree:
-	ubi_free_vid_buf(avbuf);
-	ubi_free_vid_buf(dvbuf);
+out_free_seen:
 	free_seen(seen_pebs);
+out_free_dvbuf:
+	ubi_free_vid_buf(dvbuf);
+out_free_avbuf:
+	ubi_free_vid_buf(avbuf);
+
 out:
 	return ret;
 }
@@ -1540,14 +1554,6 @@
 		return 0;
 	}
 
-	ret = ubi_ensure_anchor_pebs(ubi);
-	if (ret) {
-		up_write(&ubi->fm_eba_sem);
-		up_write(&ubi->work_sem);
-		up_write(&ubi->fm_protect);
-		return ret;
-	}
-
 	new_fm = kzalloc(sizeof(*new_fm), GFP_KERNEL);
 	if (!new_fm) {
 		up_write(&ubi->fm_eba_sem);
@@ -1618,7 +1624,8 @@
 	}
 
 	spin_lock(&ubi->wl_lock);
-	tmp_e = ubi_wl_get_fm_peb(ubi, 1);
+	tmp_e = ubi->fm_anchor;
+	ubi->fm_anchor = NULL;
 	spin_unlock(&ubi->wl_lock);
 
 	if (old_fm) {
@@ -1670,6 +1677,9 @@
 	up_write(&ubi->work_sem);
 	up_write(&ubi->fm_protect);
 	kfree(old_fm);
+
+	ubi_ensure_anchor_pebs(ubi);
+
 	return ret;
 
 err:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/ubi/ubi.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/ubi/ubi.h
@@ -491,6 +491,8 @@
  * @fm_work: fastmap work queue
  * @fm_work_scheduled: non-zero if fastmap work was scheduled
  * @fast_attach: non-zero if UBI was attached by fastmap
+ * @fm_anchor: The next anchor PEB to use for fastmap
+ * @fm_do_produce_anchor: If true produce an anchor PEB in wl
  *
  * @used: RB-tree of used physical eraseblocks
  * @erroneous: RB-tree of erroneous used physical eraseblocks
@@ -599,6 +601,8 @@
 	struct work_struct fm_work;
 	int fm_work_scheduled;
 	int fast_attach;
+	struct ubi_wl_entry *fm_anchor;
+	int fm_do_produce_anchor;
 
 	/* Wear-leveling sub-system's stuff */
 	struct rb_root used;
@@ -789,7 +793,6 @@
  * @vol_id: the volume ID on which this erasure is being performed
  * @lnum: the logical eraseblock number
  * @torture: if the physical eraseblock has to be tortured
- * @anchor: produce a anchor PEB to by used by fastmap
  *
  * The @func pointer points to the worker function. If the @shutdown argument is
  * not zero, the worker has to free the resources and exit immediately as the
@@ -805,7 +808,6 @@
 	int vol_id;
 	int lnum;
 	int torture;
-	int anchor;
 };
 
 #include "debug.h"
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/ubi/vmt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/ubi/vmt.c
@@ -56,16 +56,11 @@
 {
 	int ret;
 	struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev);
-	struct ubi_device *ubi;
-
-	ubi = ubi_get_device(vol->ubi->ubi_num);
-	if (!ubi)
-		return -ENODEV;
+	struct ubi_device *ubi = vol->ubi;
 
 	spin_lock(&ubi->volumes_lock);
 	if (!ubi->volumes[vol->vol_id]) {
 		spin_unlock(&ubi->volumes_lock);
-		ubi_put_device(ubi);
 		return -ENODEV;
 	}
 	/* Take a reference to prevent volume removal */
@@ -103,7 +98,6 @@
 	vol->ref_count -= 1;
 	ubi_assert(vol->ref_count >= 0);
 	spin_unlock(&ubi->volumes_lock);
-	ubi_put_device(ubi);
 	return ret;
 }
 
@@ -315,7 +309,6 @@
 	ubi->volumes[vol_id] = NULL;
 	ubi->vol_count -= 1;
 	spin_unlock(&ubi->volumes_lock);
-	ubi_eba_destroy_table(eba_tbl);
 out_acc:
 	spin_lock(&ubi->volumes_lock);
 	ubi->rsvd_pebs -= vol->reserved_pebs;
@@ -471,7 +464,7 @@
 		for (i = 0; i < -pebs; i++) {
 			err = ubi_eba_unmap_leb(ubi, vol, reserved_pebs + i);
 			if (err)
-				goto out_acc;
+				goto out_free;
 		}
 		spin_lock(&ubi->volumes_lock);
 		ubi->rsvd_pebs += pebs;
@@ -519,8 +512,10 @@
 		ubi->avail_pebs += pebs;
 		spin_unlock(&ubi->volumes_lock);
 	}
+	return err;
+
 out_free:
-	kfree(new_eba_tbl);
+	ubi_eba_destroy_table(new_eba_tbl);
 	return err;
 }
 
@@ -587,6 +582,7 @@
 	if (err) {
 		ubi_err(ubi, "cannot add character device for volume %d, error %d",
 			vol_id, err);
+		vol_release(&vol->dev);
 		return err;
 	}
 
@@ -597,15 +593,14 @@
 	vol->dev.groups = volume_dev_groups;
 	dev_set_name(&vol->dev, "%s_%d", ubi->ubi_name, vol->vol_id);
 	err = device_register(&vol->dev);
-	if (err)
-		goto out_cdev;
+	if (err) {
+		cdev_del(&vol->cdev);
+		put_device(&vol->dev);
+		return err;
+	}
 
 	self_check_volumes(ubi);
 	return err;
-
-out_cdev:
-	cdev_del(&vol->cdev);
-	return err;
 }
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/ubi/vtbl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/ubi/vtbl.c
@@ -791,6 +791,12 @@
 	 * The number of supported volumes is limited by the eraseblock size
 	 * and by the UBI_MAX_VOLUMES constant.
 	 */
+
+	if (ubi->leb_size < UBI_VTBL_RECORD_SIZE) {
+		ubi_err(ubi, "LEB size too small for a volume record");
+		return -EINVAL;
+	}
+
 	ubi->vtbl_slots = ubi->leb_size / UBI_VTBL_RECORD_SIZE;
 	if (ubi->vtbl_slots > UBI_MAX_VOLUMES)
 		ubi->vtbl_slots = UBI_MAX_VOLUMES;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/ubi/wl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/ubi/wl.c
@@ -339,13 +339,6 @@
 		}
 	}
 
-	/* If no fastmap has been written and this WL entry can be used
-	 * as anchor PEB, hold it back and return the second best WL entry
-	 * such that fastmap can use the anchor PEB later. */
-	if (prev_e && !ubi->fm_disabled &&
-	    !ubi->fm && e->pnum < UBI_FM_MAX_START)
-		return prev_e;
-
 	return e;
 }
 
@@ -583,6 +576,7 @@
  * @vol_id: the volume ID that last used this PEB
  * @lnum: the last used logical eraseblock number for the PEB
  * @torture: if the physical eraseblock has to be tortured
+ * @nested: denotes whether the work_sem is already held
  *
  * This function returns zero in case of success and a %-ENOMEM in case of
  * failure.
@@ -656,9 +650,6 @@
 {
 	int err, scrubbing = 0, torture = 0, protect = 0, erroneous = 0;
 	int erase = 0, keep = 0, vol_id = -1, lnum = -1;
-#ifdef CONFIG_MTD_UBI_FASTMAP
-	int anchor = wrk->anchor;
-#endif
 	struct ubi_wl_entry *e1, *e2;
 	struct ubi_vid_io_buf *vidb;
 	struct ubi_vid_hdr *vid_hdr;
@@ -698,11 +689,7 @@
 	}
 
 #ifdef CONFIG_MTD_UBI_FASTMAP
-	/* Check whether we need to produce an anchor PEB */
-	if (!anchor)
-		anchor = !anchor_pebs_available(&ubi->free);
-
-	if (anchor) {
+	if (ubi->fm_do_produce_anchor) {
 		e1 = find_anchor_wl_entry(&ubi->used);
 		if (!e1)
 			goto out_cancel;
@@ -719,6 +706,7 @@
 		self_check_in_wl_tree(ubi, e1, &ubi->used);
 		rb_erase(&e1->u.rb, &ubi->used);
 		dbg_wl("anchor-move PEB %d to PEB %d", e1->pnum, e2->pnum);
+		ubi->fm_do_produce_anchor = 0;
 	} else if (!ubi->scrub.rb_node) {
 #else
 	if (!ubi->scrub.rb_node) {
@@ -836,7 +824,14 @@
 			goto out_not_moved;
 		}
 		if (err == MOVE_RETRY) {
-			scrubbing = 1;
+			/*
+			 * For source PEB:
+			 * 1. The scrubbing is set for scrub type PEB, it will
+			 *    be put back into ubi->scrub list.
+			 * 2. Non-scrub type PEB will be put back into ubi->used
+			 *    list.
+			 */
+			keep = 1;
 			dst_leb_clean = 1;
 			goto out_not_moved;
 		}
@@ -892,8 +887,11 @@
 
 	err = do_sync_erase(ubi, e1, vol_id, lnum, 0);
 	if (err) {
-		if (e2)
+		if (e2) {
+			spin_lock(&ubi->wl_lock);
 			wl_entry_destroy(ubi, e2);
+			spin_unlock(&ubi->wl_lock);
+		}
 		goto out_ro;
 	}
 
@@ -975,11 +973,11 @@
 	spin_lock(&ubi->wl_lock);
 	ubi->move_from = ubi->move_to = NULL;
 	ubi->move_to_put = ubi->wl_scheduled = 0;
+	wl_entry_destroy(ubi, e1);
+	wl_entry_destroy(ubi, e2);
 	spin_unlock(&ubi->wl_lock);
 
 	ubi_free_vid_buf(vidb);
-	wl_entry_destroy(ubi, e1);
-	wl_entry_destroy(ubi, e2);
 
 out_ro:
 	ubi_ro_mode(ubi);
@@ -1051,7 +1049,6 @@
 		goto out_cancel;
 	}
 
-	wrk->anchor = 0;
 	wrk->func = &wear_leveling_worker;
 	if (nested)
 		__schedule_ubi_work(ubi, wrk);
@@ -1071,8 +1068,6 @@
  * __erase_worker - physical eraseblock erase worker function.
  * @ubi: UBI device description object
  * @wl_wrk: the work object
- * @shutdown: non-zero if the worker has to free memory and exit
- * because the WL sub-system is shutting down
  *
  * This function erases a physical eraseblock and perform torture testing if
  * needed. It also takes care about marking the physical eraseblock bad if
@@ -1093,8 +1088,15 @@
 	err = sync_erase(ubi, e, wl_wrk->torture);
 	if (!err) {
 		spin_lock(&ubi->wl_lock);
-		wl_tree_add(e, &ubi->free);
-		ubi->free_count++;
+
+		if (!ubi->fm_anchor && e->pnum < UBI_FM_MAX_START) {
+			ubi->fm_anchor = e;
+			ubi->fm_do_produce_anchor = 0;
+		} else {
+			wl_tree_add(e, &ubi->free);
+			ubi->free_count++;
+		}
+
 		spin_unlock(&ubi->wl_lock);
 
 		/*
@@ -1115,16 +1117,20 @@
 		int err1;
 
 		/* Re-schedule the LEB for erasure */
-		err1 = schedule_erase(ubi, e, vol_id, lnum, 0, false);
+		err1 = schedule_erase(ubi, e, vol_id, lnum, 0, true);
 		if (err1) {
+			spin_lock(&ubi->wl_lock);
 			wl_entry_destroy(ubi, e);
+			spin_unlock(&ubi->wl_lock);
 			err = err1;
 			goto out_ro;
 		}
 		return err;
 	}
 
+	spin_lock(&ubi->wl_lock);
 	wl_entry_destroy(ubi, e);
+	spin_unlock(&ubi->wl_lock);
 	if (err != -EIO)
 		/*
 		 * If this is not %-EIO, we have no idea what to do. Scheduling
@@ -1240,6 +1246,18 @@
 retry:
 	spin_lock(&ubi->wl_lock);
 	e = ubi->lookuptbl[pnum];
+	if (!e) {
+		/*
+		 * This wl entry has been removed for some errors by other
+		 * process (eg. wear leveling worker), corresponding process
+		 * (except __erase_worker, which cannot concurrent with
+		 * ubi_wl_put_peb) will set ubi ro_mode at the same time,
+		 * just ignore this wl entry.
+		 */
+		spin_unlock(&ubi->wl_lock);
+		up_read(&ubi->fm_protect);
+		return 0;
+	}
 	if (e == ubi->move_from) {
 		/*
 		 * User is putting the physical eraseblock which was selected to
@@ -1636,6 +1654,19 @@
 		    !ubi->thread_enabled || ubi_dbg_is_bgt_disabled(ubi)) {
 			set_current_state(TASK_INTERRUPTIBLE);
 			spin_unlock(&ubi->wl_lock);
+
+			/*
+			 * Check kthread_should_stop() after we set the task
+			 * state to guarantee that we either see the stop bit
+			 * and exit or the task state is reset to runnable such
+			 * that it's not scheduled out indefinitely and detects
+			 * the stop bit at kthread_should_stop().
+			 */
+			if (kthread_should_stop()) {
+				set_current_state(TASK_RUNNING);
+				break;
+			}
+
 			schedule();
 			continue;
 		}
@@ -1882,6 +1913,9 @@
 	if (err)
 		goto out_free;
 
+#ifdef CONFIG_MTD_UBI_FASTMAP
+	ubi_ensure_anchor_pebs(ubi);
+#endif
 	return 0;
 
 out_free:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/mtd/ubi/wl.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/mtd/ubi/wl.h
@@ -2,7 +2,6 @@
 #ifndef UBI_WL_H
 #define UBI_WL_H
 #ifdef CONFIG_MTD_UBI_FASTMAP
-static int anchor_pebs_available(struct rb_root *root);
 static void update_fastmap_work_fn(struct work_struct *wrk);
 static struct ubi_wl_entry *find_anchor_wl_entry(struct rb_root *root);
 static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/Kconfig
@@ -106,6 +106,7 @@
 config IFB
 	tristate "Intermediate Functional Block support"
 	depends on NET_CLS_ACT
+	select NET_REDIRECT
 	---help---
 	  This is an intermediate driver that allows sharing of
 	  resources.
@@ -153,22 +154,22 @@
 	select NET_L3_MASTER_DEV
 
 config IPVLAN
-    tristate "IP-VLAN support"
-    depends on INET
-    depends on IPV6 || !IPV6
-    ---help---
-      This allows one to create virtual devices off of a main interface
-      and packets will be delivered based on the dest L3 (IPv6/IPv4 addr)
-      on packets. All interfaces (including the main interface) share L2
-      making it transparent to the connected L2 switch.
+	tristate "IP-VLAN support"
+	depends on INET
+	depends on IPV6 || !IPV6
+	---help---
+	  This allows one to create virtual devices off of a main interface
+	  and packets will be delivered based on the dest L3 (IPv6/IPv4 addr)
+	  on packets. All interfaces (including the main interface) share L2
+	  making it transparent to the connected L2 switch.
 
-      Ipvlan devices can be added using the "ip" command from the
-      iproute2 package starting with the iproute2-3.19 release:
+	  Ipvlan devices can be added using the "ip" command from the
+	  iproute2 package starting with the iproute2-3.19 release:
 
-      "ip link add link <main-dev> [ NAME ] type ipvlan"
+	  "ip link add link <main-dev> [ NAME ] type ipvlan"
 
-      To compile this driver as a module, choose M here: the module
-      will be called ipvlan.
+	  To compile this driver as a module, choose M here: the module
+	  will be called ipvlan.
 
 config IPVTAP
 	tristate "IP-VLAN based tap driver"
@@ -185,11 +186,11 @@
 	  will be called ipvtap.
 
 config VXLAN
-       tristate "Virtual eXtensible Local Area Network (VXLAN)"
-       depends on INET
-       select NET_UDP_TUNNEL
-       select GRO_CELLS
-       ---help---
+	tristate "Virtual eXtensible Local Area Network (VXLAN)"
+	depends on INET
+	select NET_UDP_TUNNEL
+	select GRO_CELLS
+	---help---
 	  This allows one to create vxlan virtual interfaces that provide
 	  Layer 2 Networks over Layer 3 Networks. VXLAN is often used
 	  to tunnel virtual network infrastructure in virtualized environments.
@@ -200,12 +201,12 @@
 	  will be called vxlan.
 
 config GENEVE
-       tristate "Generic Network Virtualization Encapsulation"
-       depends on INET
-       depends on IPV6 || !IPV6
-       select NET_UDP_TUNNEL
-       select GRO_CELLS
-       ---help---
+	tristate "Generic Network Virtualization Encapsulation"
+	depends on INET
+	depends on IPV6 || !IPV6
+	select NET_UDP_TUNNEL
+	select GRO_CELLS
+	---help---
 	  This allows one to create geneve virtual interfaces that provide
 	  Layer 2 Networks over Layer 3 Networks. GENEVE is often used
 	  to tunnel virtual network infrastructure in virtualized environments.
@@ -244,8 +245,8 @@
 config NETCONSOLE
 	tristate "Network console logging support"
 	---help---
-	If you want to log kernel messages over the network, enable this.
-	See <file:Documentation/networking/netconsole.txt> for details.
+	  If you want to log kernel messages over the network, enable this.
+	  See <file:Documentation/networking/netconsole.txt> for details.
 
 config NETCONSOLE_DYNAMIC
 	bool "Dynamic reconfiguration of logging targets"
@@ -362,12 +363,12 @@
 	  support enables VRF devices.
 
 config VSOCKMON
-    tristate "Virtual vsock monitoring device"
-    depends on VHOST_VSOCK
-    ---help---
-     This option enables a monitoring net device for vsock sockets. It is
-     mostly intended for developers or support to debug vsock issues. If
-     unsure, say N.
+	tristate "Virtual vsock monitoring device"
+	depends on VHOST_VSOCK
+	---help---
+	  This option enables a monitoring net device for vsock sockets. It is
+	  mostly intended for developers or support to debug vsock issues. If
+	  unsure, say N.
 
 endif # NET_CORE
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/appletalk/cops.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/appletalk/cops.c
@@ -325,6 +325,8 @@
 			break;
 	}
 
+	dev->base_addr = ioaddr;
+
 	/* Reserve any actual interrupt. */
 	if (dev->irq) {
 		retval = request_irq(dev->irq, cops_interrupt, 0, dev->name, dev);
@@ -332,8 +334,6 @@
 			goto err_out;
 	}
 
-	dev->base_addr = ioaddr;
-
         lp = netdev_priv(dev);
         spin_lock_init(&lp->lock);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/arcnet/arc-rimi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/arcnet/arc-rimi.c
@@ -332,7 +332,7 @@
 		dev->irq = 9;
 
 	if (arcrimi_probe(dev)) {
-		free_netdev(dev);
+		free_arcdev(dev);
 		return -EIO;
 	}
 
@@ -349,7 +349,7 @@
 	iounmap(lp->mem_start);
 	release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1);
 	free_irq(dev->irq, dev);
-	free_netdev(dev);
+	free_arcdev(dev);
 }
 
 #ifndef MODULE
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/arcnet/arcdevice.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/arcnet/arcdevice.h
@@ -186,6 +186,8 @@
 #define ARC_IS_5MBIT    1   /* card default speed is 5MBit */
 #define ARC_CAN_10MBIT  2   /* card uses COM20022, supporting 10MBit,
 				 but default is 2.5MBit. */
+#define ARC_HAS_LED     4   /* card has software controlled LEDs */
+#define ARC_HAS_ROTARY  8   /* card has rotary encoder */
 
 /* information needed to define an encapsulation driver */
 struct ArcProto {
@@ -298,6 +300,10 @@
 
 	int excnak_pending;    /* We just got an excesive nak interrupt */
 
+	/* RESET flag handling */
+	int reset_in_progress;
+	struct work_struct reset_work;
+
 	struct {
 		uint16_t sequence;	/* sequence number (incs with each packet) */
 		__be16 aborted_seq;
@@ -350,7 +356,9 @@
 
 void arcnet_unregister_proto(struct ArcProto *proto);
 irqreturn_t arcnet_interrupt(int irq, void *dev_id);
+
 struct net_device *alloc_arcdev(const char *name);
+void free_arcdev(struct net_device *dev);
 
 int arcnet_open(struct net_device *dev);
 int arcnet_close(struct net_device *dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/arcnet/arcnet.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/arcnet/arcnet.c
@@ -387,10 +387,44 @@
 	struct arcnet_local *lp = from_timer(lp, t, timer);
 	struct net_device *dev = lp->dev;
 
-	if (!netif_carrier_ok(dev)) {
+	spin_lock_irq(&lp->lock);
+
+	if (!lp->reset_in_progress && !netif_carrier_ok(dev)) {
 		netif_carrier_on(dev);
 		netdev_info(dev, "link up\n");
 	}
+
+	spin_unlock_irq(&lp->lock);
+}
+
+static void reset_device_work(struct work_struct *work)
+{
+	struct arcnet_local *lp;
+	struct net_device *dev;
+
+	lp = container_of(work, struct arcnet_local, reset_work);
+	dev = lp->dev;
+
+	/* Do not bring the network interface back up if an ifdown
+	 * was already done.
+	 */
+	if (!netif_running(dev) || !lp->reset_in_progress)
+		return;
+
+	rtnl_lock();
+
+	/* Do another check, in case of an ifdown that was triggered in
+	 * the small race window between the exit condition above and
+	 * acquiring RTNL.
+	 */
+	if (!netif_running(dev) || !lp->reset_in_progress)
+		goto out;
+
+	dev_close(dev);
+	dev_open(dev, NULL);
+
+out:
+	rtnl_unlock();
 }
 
 static void arcnet_reply_tasklet(unsigned long data)
@@ -434,7 +468,7 @@
 
 	ret = sock_queue_err_skb(sk, ackskb);
 	if (ret)
-		kfree_skb(ackskb);
+		dev_kfree_skb_irq(ackskb);
 
 	local_irq_enable();
 };
@@ -452,12 +486,25 @@
 		lp->dev = dev;
 		spin_lock_init(&lp->lock);
 		timer_setup(&lp->timer, arcnet_timer, 0);
+		INIT_WORK(&lp->reset_work, reset_device_work);
 	}
 
 	return dev;
 }
 EXPORT_SYMBOL(alloc_arcdev);
 
+void free_arcdev(struct net_device *dev)
+{
+	struct arcnet_local *lp = netdev_priv(dev);
+
+	/* Do not cancel this at ->ndo_close(), as the workqueue itself
+	 * indirectly calls the ifdown path through dev_close().
+	 */
+	cancel_work_sync(&lp->reset_work);
+	free_netdev(dev);
+}
+EXPORT_SYMBOL(free_arcdev);
+
 /* Open/initialize the board.  This is called sometime after booting when
  * the 'ifconfig' program is run.
  *
@@ -587,6 +634,10 @@
 
 	/* shut down the card */
 	lp->hw.close(dev);
+
+	/* reset counters */
+	lp->reset_in_progress = 0;
+
 	module_put(lp->hw.owner);
 	return 0;
 }
@@ -820,6 +871,9 @@
 
 	spin_lock_irqsave(&lp->lock, flags);
 
+	if (lp->reset_in_progress)
+		goto out;
+
 	/* RESET flag was enabled - if device is not running, we must
 	 * clear it right away (but nothing else).
 	 */
@@ -852,11 +906,14 @@
 		if (status & RESETflag) {
 			arc_printk(D_NORMAL, dev, "spurious reset (status=%Xh)\n",
 				   status);
-			arcnet_close(dev);
-			arcnet_open(dev);
+
+			lp->reset_in_progress = 1;
+			netif_stop_queue(dev);
+			netif_carrier_off(dev);
+			schedule_work(&lp->reset_work);
 
 			/* get out of the interrupt handler! */
-			break;
+			goto out;
 		}
 		/* RX is inhibited - we must have received something.
 		 * Prepare to receive into the next buffer.
@@ -1052,6 +1109,7 @@
 	udelay(1);
 	lp->hw.intmask(dev, lp->intmask);
 
+out:
 	spin_unlock_irqrestore(&lp->lock, flags);
 	return retval;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/arcnet/com20020-isa.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/arcnet/com20020-isa.c
@@ -169,7 +169,7 @@
 		dev->irq = 9;
 
 	if (com20020isa_probe(dev)) {
-		free_netdev(dev);
+		free_arcdev(dev);
 		return -EIO;
 	}
 
@@ -182,7 +182,7 @@
 	unregister_netdev(my_dev);
 	free_irq(my_dev->irq, my_dev);
 	release_region(my_dev->base_addr, ARCNET_TOTAL_SIZE);
-	free_netdev(my_dev);
+	free_arcdev(my_dev);
 }
 
 #ifndef MODULE
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/arcnet/com20020-pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/arcnet/com20020-pci.c
@@ -127,6 +127,8 @@
 	int i, ioaddr, ret;
 	struct resource *r;
 
+	ret = 0;
+
 	if (pci_enable_device(pdev))
 		return -EIO;
 
@@ -136,9 +138,14 @@
 		return -ENOMEM;
 
 	ci = (struct com20020_pci_card_info *)id->driver_data;
+	if (!ci)
+		return -EINVAL;
+
 	priv->ci = ci;
 	mm = &ci->misc_map;
 
+	pci_set_drvdata(pdev, priv);
+
 	INIT_LIST_HEAD(&priv->list_dev);
 
 	if (mm->size) {
@@ -161,7 +168,7 @@
 		dev = alloc_arcdev(device);
 		if (!dev) {
 			ret = -ENOMEM;
-			goto out_port;
+			break;
 		}
 		dev->dev_port = i;
 
@@ -178,7 +185,7 @@
 			pr_err("IO region %xh-%xh already allocated\n",
 			       ioaddr, ioaddr + cm->size - 1);
 			ret = -EBUSY;
-			goto out_port;
+			goto err_free_arcdev;
 		}
 
 		/* Dummy access after Reset
@@ -206,76 +213,94 @@
 		if (!strncmp(ci->name, "EAE PLX-PCI FB2", 15))
 			lp->backplane = 1;
 
-		/* Get the dev_id from the PLX rotary coder */
-		if (!strncmp(ci->name, "EAE PLX-PCI MA1", 15))
-			dev_id_mask = 0x3;
-		dev->dev_id = (inb(priv->misc + ci->rotary) >> 4) & dev_id_mask;
-
-		snprintf(dev->name, sizeof(dev->name), "arc%d-%d", dev->dev_id, i);
+		if (ci->flags & ARC_HAS_ROTARY) {
+			/* Get the dev_id from the PLX rotary coder */
+			if (!strncmp(ci->name, "EAE PLX-PCI MA1", 15))
+				dev_id_mask = 0x3;
+			dev->dev_id = (inb(priv->misc + ci->rotary) >> 4) & dev_id_mask;
+			snprintf(dev->name, sizeof(dev->name), "arc%d-%d", dev->dev_id, i);
+		}
 
 		if (arcnet_inb(ioaddr, COM20020_REG_R_STATUS) == 0xFF) {
 			pr_err("IO address %Xh is empty!\n", ioaddr);
 			ret = -EIO;
-			goto out_port;
+			goto err_free_arcdev;
 		}
 		if (com20020_check(dev)) {
 			ret = -EIO;
-			goto out_port;
+			goto err_free_arcdev;
 		}
 
+		ret = com20020_found(dev, IRQF_SHARED);
+		if (ret)
+			goto err_free_arcdev;
+
 		card = devm_kzalloc(&pdev->dev, sizeof(struct com20020_dev),
 				    GFP_KERNEL);
 		if (!card) {
 			ret = -ENOMEM;
-			goto out_port;
+			goto err_free_arcdev;
 		}
 
 		card->index = i;
 		card->pci_priv = priv;
-		card->tx_led.brightness_set = led_tx_set;
-		card->tx_led.default_trigger = devm_kasprintf(&pdev->dev,
-						GFP_KERNEL, "arc%d-%d-tx",
-						dev->dev_id, i);
-		card->tx_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
-						"pci:green:tx:%d-%d",
-						dev->dev_id, i);
-
-		card->tx_led.dev = &dev->dev;
-		card->recon_led.brightness_set = led_recon_set;
-		card->recon_led.default_trigger = devm_kasprintf(&pdev->dev,
-						GFP_KERNEL, "arc%d-%d-recon",
-						dev->dev_id, i);
-		card->recon_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
-						"pci:red:recon:%d-%d",
-						dev->dev_id, i);
-		card->recon_led.dev = &dev->dev;
-		card->dev = dev;
-
-		ret = devm_led_classdev_register(&pdev->dev, &card->tx_led);
-		if (ret)
-			goto out_port;
-
-		ret = devm_led_classdev_register(&pdev->dev, &card->recon_led);
-		if (ret)
-			goto out_port;
 
-		dev_set_drvdata(&dev->dev, card);
+		if (ci->flags & ARC_HAS_LED) {
+			card->tx_led.brightness_set = led_tx_set;
+			card->tx_led.default_trigger = devm_kasprintf(&pdev->dev,
+							GFP_KERNEL, "arc%d-%d-tx",
+							dev->dev_id, i);
+			if (!card->tx_led.default_trigger) {
+				ret = -ENOMEM;
+				goto err_free_arcdev;
+			}
+			card->tx_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
+							"pci:green:tx:%d-%d",
+							dev->dev_id, i);
+			if (!card->tx_led.name) {
+				ret = -ENOMEM;
+				goto err_free_arcdev;
+			}
+			card->tx_led.dev = &dev->dev;
+			card->recon_led.brightness_set = led_recon_set;
+			card->recon_led.default_trigger = devm_kasprintf(&pdev->dev,
+							GFP_KERNEL, "arc%d-%d-recon",
+							dev->dev_id, i);
+			if (!card->recon_led.default_trigger) {
+				ret = -ENOMEM;
+				goto err_free_arcdev;
+			}
+			card->recon_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
+							"pci:red:recon:%d-%d",
+							dev->dev_id, i);
+			if (!card->recon_led.name) {
+				ret = -ENOMEM;
+				goto err_free_arcdev;
+			}
+			card->recon_led.dev = &dev->dev;
+
+			ret = devm_led_classdev_register(&pdev->dev, &card->tx_led);
+			if (ret)
+				goto err_free_arcdev;
+
+			ret = devm_led_classdev_register(&pdev->dev, &card->recon_led);
+			if (ret)
+				goto err_free_arcdev;
 
-		ret = com20020_found(dev, IRQF_SHARED);
-		if (ret)
-			goto out_port;
-
-		devm_arcnet_led_init(dev, dev->dev_id, i);
+			dev_set_drvdata(&dev->dev, card);
+			devm_arcnet_led_init(dev, dev->dev_id, i);
+		}
 
+		card->dev = dev;
 		list_add(&card->list, &priv->list_dev);
-	}
+		continue;
 
-	pci_set_drvdata(pdev, priv);
-
-	return 0;
-
-out_port:
-	com20020pci_remove(pdev);
+err_free_arcdev:
+		free_arcdev(dev);
+		break;
+	}
+	if (ret)
+		com20020pci_remove(pdev);
 	return ret;
 }
 
@@ -291,7 +316,7 @@
 
 		unregister_netdev(dev);
 		free_irq(dev->irq, dev);
-		free_netdev(dev);
+		free_arcdev(dev);
 	}
 }
 
@@ -322,7 +347,7 @@
 };
 
 static struct com20020_pci_card_info card_info_sohard = {
-	.name = "PLX-PCI",
+	.name = "SOHARD SH ARC-PCI",
 	.devcount = 1,
 	/* SOHARD needs PCI base addr 4 */
 	.chan_map_tbl = {
@@ -357,7 +382,7 @@
 		},
 	},
 	.rotary = 0x0,
-	.flags = ARC_CAN_10MBIT,
+	.flags = ARC_HAS_ROTARY | ARC_HAS_LED | ARC_CAN_10MBIT,
 };
 
 static struct com20020_pci_card_info card_info_eae_ma1 = {
@@ -389,7 +414,7 @@
 		},
 	},
 	.rotary = 0x0,
-	.flags = ARC_CAN_10MBIT,
+	.flags = ARC_HAS_ROTARY | ARC_HAS_LED | ARC_CAN_10MBIT,
 };
 
 static struct com20020_pci_card_info card_info_eae_fb2 = {
@@ -414,7 +439,7 @@
 		},
 	},
 	.rotary = 0x0,
-	.flags = ARC_CAN_10MBIT,
+	.flags = ARC_HAS_ROTARY | ARC_HAS_LED | ARC_CAN_10MBIT,
 };
 
 static const struct pci_device_id com20020pci_id_table[] = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/arcnet/com20020_cs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/arcnet/com20020_cs.c
@@ -177,7 +177,7 @@
 		dev = info->dev;
 		if (dev) {
 			dev_dbg(&link->dev, "kfree...\n");
-			free_netdev(dev);
+			free_arcdev(dev);
 		}
 		dev_dbg(&link->dev, "kfree2...\n");
 		kfree(info);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/arcnet/com90io.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/arcnet/com90io.c
@@ -396,7 +396,7 @@
 	err = com90io_probe(dev);
 
 	if (err) {
-		free_netdev(dev);
+		free_arcdev(dev);
 		return err;
 	}
 
@@ -419,7 +419,7 @@
 
 	free_irq(dev->irq, dev);
 	release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
-	free_netdev(dev);
+	free_arcdev(dev);
 }
 
 module_init(com90io_init)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/arcnet/com90xx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/arcnet/com90xx.c
@@ -554,7 +554,7 @@
 err_release_mem:
 	release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1);
 err_free_dev:
-	free_netdev(dev);
+	free_arcdev(dev);
 	return -EIO;
 }
 
@@ -672,7 +672,7 @@
 		release_region(dev->base_addr, ARCNET_TOTAL_SIZE);
 		release_mem_region(dev->mem_start,
 				   dev->mem_end - dev->mem_start + 1);
-		free_netdev(dev);
+		free_arcdev(dev);
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/bonding/bond_3ad.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/bonding/bond_3ad.c
@@ -233,7 +233,7 @@
 	if (bond == NULL)
 		return 0;
 
-	return BOND_AD_INFO(bond).agg_select_timer ? 1 : 0;
+	return atomic_read(&BOND_AD_INFO(bond).agg_select_timer) ? 1 : 0;
 }
 
 /**
@@ -1013,8 +1013,8 @@
 				if (port->aggregator &&
 				    port->aggregator->is_active &&
 				    !__port_is_enabled(port)) {
-
 					__enable_port(port);
+					*update_slave_arr = true;
 				}
 			}
 			break;
@@ -1529,6 +1529,7 @@
 			slave_err(bond->dev, port->slave->dev,
 				  "Port %d did not find a suitable aggregator\n",
 				  port->actor_port_number);
+			return;
 		}
 	}
 	/* if all aggregator's ports are READY_N == TRUE, set ready=TRUE
@@ -1770,6 +1771,7 @@
 			     port = port->next_port_in_aggregator) {
 				__enable_port(port);
 			}
+			*update_slave_arr = true;
 		}
 	}
 
@@ -1984,7 +1986,7 @@
  */
 void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout)
 {
-	BOND_AD_INFO(bond).agg_select_timer = timeout;
+	atomic_set(&BOND_AD_INFO(bond).agg_select_timer, timeout);
 }
 
 /**
@@ -1996,30 +1998,24 @@
  */
 void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution)
 {
-	/* check that the bond is not initialized yet */
-	if (!MAC_ADDRESS_EQUAL(&(BOND_AD_INFO(bond).system.sys_mac_addr),
-				bond->dev->dev_addr)) {
-
-		BOND_AD_INFO(bond).aggregator_identifier = 0;
-
-		BOND_AD_INFO(bond).system.sys_priority =
-			bond->params.ad_actor_sys_prio;
-		if (is_zero_ether_addr(bond->params.ad_actor_system))
-			BOND_AD_INFO(bond).system.sys_mac_addr =
-			    *((struct mac_addr *)bond->dev->dev_addr);
-		else
-			BOND_AD_INFO(bond).system.sys_mac_addr =
-			    *((struct mac_addr *)bond->params.ad_actor_system);
+	BOND_AD_INFO(bond).aggregator_identifier = 0;
+	BOND_AD_INFO(bond).system.sys_priority =
+		bond->params.ad_actor_sys_prio;
+	if (is_zero_ether_addr(bond->params.ad_actor_system))
+		BOND_AD_INFO(bond).system.sys_mac_addr =
+		    *((struct mac_addr *)bond->dev->dev_addr);
+	else
+		BOND_AD_INFO(bond).system.sys_mac_addr =
+		    *((struct mac_addr *)bond->params.ad_actor_system);
 
-		/* initialize how many times this module is called in one
-		 * second (should be about every 100ms)
-		 */
-		ad_ticks_per_sec = tick_resolution;
+	/* initialize how many times this module is called in one
+	 * second (should be about every 100ms)
+	 */
+	ad_ticks_per_sec = tick_resolution;
 
-		bond_3ad_initiate_agg_selection(bond,
-						AD_AGGREGATOR_SELECTION_TIMER *
-						ad_ticks_per_sec);
-	}
+	bond_3ad_initiate_agg_selection(bond,
+					AD_AGGREGATOR_SELECTION_TIMER *
+					ad_ticks_per_sec);
 }
 
 /**
@@ -2217,7 +2213,8 @@
 				temp_aggregator->num_of_ports--;
 				if (__agg_active_ports(temp_aggregator) == 0) {
 					select_new_active_agg = temp_aggregator->is_active;
-					ad_clear_agg(temp_aggregator);
+					if (temp_aggregator->num_of_ports == 0)
+						ad_clear_agg(temp_aggregator);
 					if (select_new_active_agg) {
 						slave_info(bond->dev, slave->dev, "Removing an active aggregator\n");
 						/* select new active aggregator */
@@ -2268,6 +2265,28 @@
 }
 
 /**
+ * bond_agg_timer_advance - advance agg_select_timer
+ * @bond:  bonding structure
+ *
+ * Return true when agg_select_timer reaches 0.
+ */
+static bool bond_agg_timer_advance(struct bonding *bond)
+{
+	int val, nval;
+
+	while (1) {
+		val = atomic_read(&BOND_AD_INFO(bond).agg_select_timer);
+		if (!val)
+			return false;
+		nval = val - 1;
+		if (atomic_cmpxchg(&BOND_AD_INFO(bond).agg_select_timer,
+				   val, nval) == val)
+			break;
+	}
+	return nval == 0;
+}
+
+/**
  * bond_3ad_state_machine_handler - handle state machines timeout
  * @bond: bonding struct to work on
  *
@@ -2302,9 +2321,7 @@
 	if (!bond_has_slaves(bond))
 		goto re_arm;
 
-	/* check if agg_select_timer timer after initialize is timed out */
-	if (BOND_AD_INFO(bond).agg_select_timer &&
-	    !(--BOND_AD_INFO(bond).agg_select_timer)) {
+	if (bond_agg_timer_advance(bond)) {
 		slave = bond_first_slave_rcu(bond);
 		port = slave ? &(SLAVE_AD_INFO(slave)->port) : NULL;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/bonding/bond_alb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/bonding/bond_alb.c
@@ -50,11 +50,6 @@
 };
 #pragma pack()
 
-static inline struct arp_pkt *arp_pkt(const struct sk_buff *skb)
-{
-	return (struct arp_pkt *)skb_network_header(skb);
-}
-
 /* Forward declaration */
 static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[],
 				      bool strict_match);
@@ -553,10 +548,11 @@
 	spin_unlock(&bond->mode_lock);
 }
 
-static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bond)
+static struct slave *rlb_choose_channel(struct sk_buff *skb,
+					struct bonding *bond,
+					const struct arp_pkt *arp)
 {
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
-	struct arp_pkt *arp = arp_pkt(skb);
 	struct slave *assigned_slave, *curr_active_slave;
 	struct rlb_client_info *client_info;
 	u32 hash_index = 0;
@@ -653,18 +649,22 @@
  */
 static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond)
 {
-	struct arp_pkt *arp = arp_pkt(skb);
 	struct slave *tx_slave = NULL;
+	struct arp_pkt *arp;
 
-	/* Don't modify or load balance ARPs that do not originate locally
-	 * (e.g.,arrive via a bridge).
+	if (!pskb_network_may_pull(skb, sizeof(*arp)))
+		return NULL;
+	arp = (struct arp_pkt *)skb_network_header(skb);
+
+	/* Don't modify or load balance ARPs that do not originate
+	 * from the bond itself or a VLAN directly above the bond.
 	 */
-	if (!bond_slave_has_mac_rx(bond, arp->mac_src))
+	if (!bond_slave_has_mac_rcu(bond, arp->mac_src))
 		return NULL;
 
 	if (arp->op_code == htons(ARPOP_REPLY)) {
 		/* the arp must be sent on the selected rx channel */
-		tx_slave = rlb_choose_channel(skb, bond);
+		tx_slave = rlb_choose_channel(skb, bond, arp);
 		if (tx_slave)
 			bond_hw_addr_copy(arp->mac_src, tx_slave->dev->dev_addr,
 					  tx_slave->dev->addr_len);
@@ -676,7 +676,7 @@
 		 * When the arp reply is received the entry will be updated
 		 * with the correct unicast address of the client.
 		 */
-		tx_slave = rlb_choose_channel(skb, bond);
+		tx_slave = rlb_choose_channel(skb, bond, arp);
 
 		/* The ARP reply packets must be delayed so that
 		 * they can cancel out the influence of the ARP request.
@@ -970,7 +970,8 @@
 	if (netif_is_macvlan(upper) && !strict_match) {
 		tags = bond_verify_device_path(bond->dev, upper, 0);
 		if (IS_ERR_OR_NULL(tags))
-			BUG();
+			return -ENOMEM;
+
 		alb_send_lp_vid(slave, upper->dev_addr,
 				tags[0].vlan_proto, tags[0].vlan_id);
 		kfree(tags);
@@ -1276,12 +1277,12 @@
 		return res;
 
 	if (rlb_enabled) {
-		bond->alb_info.rlb_enabled = 1;
 		res = rlb_initialize(bond);
 		if (res) {
 			tlb_deinitialize(bond);
 			return res;
 		}
+		bond->alb_info.rlb_enabled = 1;
 	} else {
 		bond->alb_info.rlb_enabled = 0;
 	}
@@ -1360,7 +1361,7 @@
 				struct bond_up_slave *slaves;
 				unsigned int count;
 
-				slaves = rcu_dereference(bond->slave_arr);
+				slaves = rcu_dereference(bond->usable_slaves);
 				count = slaves ? READ_ONCE(slaves->count) : 0;
 				if (likely(count))
 					tx_slave = slaves->arr[hash_index %
@@ -1383,26 +1384,31 @@
 	bool do_tx_balance = true;
 	u32 hash_index = 0;
 	const u8 *hash_start = NULL;
-	struct ipv6hdr *ip6hdr;
 
 	skb_reset_mac_header(skb);
 	eth_data = eth_hdr(skb);
 
 	switch (ntohs(skb->protocol)) {
 	case ETH_P_IP: {
-		const struct iphdr *iph = ip_hdr(skb);
+		const struct iphdr *iph;
 
 		if (is_broadcast_ether_addr(eth_data->h_dest) ||
-		    iph->daddr == ip_bcast ||
-		    iph->protocol == IPPROTO_IGMP) {
+		    !pskb_network_may_pull(skb, sizeof(*iph))) {
+			do_tx_balance = false;
+			break;
+		}
+		iph = ip_hdr(skb);
+		if (iph->daddr == ip_bcast || iph->protocol == IPPROTO_IGMP) {
 			do_tx_balance = false;
 			break;
 		}
 		hash_start = (char *)&(iph->daddr);
 		hash_size = sizeof(iph->daddr);
-	}
 		break;
-	case ETH_P_IPV6:
+	}
+	case ETH_P_IPV6: {
+		const struct ipv6hdr *ip6hdr;
+
 		/* IPv6 doesn't really use broadcast mac address, but leave
 		 * that here just in case.
 		 */
@@ -1419,7 +1425,11 @@
 			break;
 		}
 
-		/* Additianally, DAD probes should not be tx-balanced as that
+		if (!pskb_network_may_pull(skb, sizeof(*ip6hdr))) {
+			do_tx_balance = false;
+			break;
+		}
+		/* Additionally, DAD probes should not be tx-balanced as that
 		 * will lead to false positives for duplicate addresses and
 		 * prevent address configuration from working.
 		 */
@@ -1429,17 +1439,26 @@
 			break;
 		}
 
-		hash_start = (char *)&(ipv6_hdr(skb)->daddr);
-		hash_size = sizeof(ipv6_hdr(skb)->daddr);
+		hash_start = (char *)&ip6hdr->daddr;
+		hash_size = sizeof(ip6hdr->daddr);
 		break;
-	case ETH_P_IPX:
-		if (ipx_hdr(skb)->ipx_checksum != IPX_NO_CHECKSUM) {
+	}
+	case ETH_P_IPX: {
+		const struct ipxhdr *ipxhdr;
+
+		if (pskb_network_may_pull(skb, sizeof(*ipxhdr))) {
+			do_tx_balance = false;
+			break;
+		}
+		ipxhdr = (struct ipxhdr *)skb_network_header(skb);
+
+		if (ipxhdr->ipx_checksum != IPX_NO_CHECKSUM) {
 			/* something is wrong with this packet */
 			do_tx_balance = false;
 			break;
 		}
 
-		if (ipx_hdr(skb)->ipx_type != IPX_TYPE_NCP) {
+		if (ipxhdr->ipx_type != IPX_TYPE_NCP) {
 			/* The only protocol worth balancing in
 			 * this family since it has an "ARP" like
 			 * mechanism
@@ -1448,9 +1467,11 @@
 			break;
 		}
 
+		eth_data = eth_hdr(skb);
 		hash_start = (char *)eth_data->h_dest;
 		hash_size = ETH_ALEN;
 		break;
+	}
 	case ETH_P_ARP:
 		do_tx_balance = false;
 		if (bond_info->rlb_enabled)
@@ -1474,7 +1495,7 @@
 			struct bond_up_slave *slaves;
 			unsigned int count;
 
-			slaves = rcu_dereference(bond->slave_arr);
+			slaves = rcu_dereference(bond->usable_slaves);
 			count = slaves ? READ_ONCE(slaves->count) : 0;
 			if (likely(count))
 				tx_slave = slaves->arr[bond_xmit_hash(bond, skb) %
@@ -1494,14 +1515,14 @@
 	struct slave *slave;
 
 	if (!bond_has_slaves(bond)) {
-		bond_info->tx_rebalance_counter = 0;
+		atomic_set(&bond_info->tx_rebalance_counter, 0);
 		bond_info->lp_counter = 0;
 		goto re_arm;
 	}
 
 	rcu_read_lock();
 
-	bond_info->tx_rebalance_counter++;
+	atomic_inc(&bond_info->tx_rebalance_counter);
 	bond_info->lp_counter++;
 
 	/* send learning packets */
@@ -1523,7 +1544,7 @@
 	}
 
 	/* rebalance tx traffic */
-	if (bond_info->tx_rebalance_counter >= BOND_TLB_REBALANCE_TICKS) {
+	if (atomic_read(&bond_info->tx_rebalance_counter) >= BOND_TLB_REBALANCE_TICKS) {
 		bond_for_each_slave_rcu(bond, slave, iter) {
 			tlb_clear_slave(bond, slave, 1);
 			if (slave == rcu_access_pointer(bond->curr_active_slave)) {
@@ -1533,7 +1554,7 @@
 				bond_info->unbalanced_load = 0;
 			}
 		}
-		bond_info->tx_rebalance_counter = 0;
+		atomic_set(&bond_info->tx_rebalance_counter, 0);
 	}
 
 	if (bond_info->rlb_enabled) {
@@ -1603,7 +1624,8 @@
 	tlb_init_slave(slave);
 
 	/* order a rebalance ASAP */
-	bond->alb_info.tx_rebalance_counter = BOND_TLB_REBALANCE_TICKS;
+	atomic_set(&bond->alb_info.tx_rebalance_counter,
+		   BOND_TLB_REBALANCE_TICKS);
 
 	if (bond->alb_info.rlb_enabled)
 		bond->alb_info.rlb_rebalance = 1;
@@ -1640,7 +1662,8 @@
 			rlb_clear_slave(bond, slave);
 	} else if (link == BOND_LINK_UP) {
 		/* order a rebalance ASAP */
-		bond_info->tx_rebalance_counter = BOND_TLB_REBALANCE_TICKS;
+		atomic_set(&bond_info->tx_rebalance_counter,
+			   BOND_TLB_REBALANCE_TICKS);
 		if (bond->alb_info.rlb_enabled) {
 			bond->alb_info.rlb_rebalance = 1;
 			/* If the updelay module parameter is smaller than the
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/bonding/bond_debugfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/bonding/bond_debugfs.c
@@ -76,7 +76,7 @@
 
 	d = debugfs_rename(bonding_debug_root, bond->debug_dir,
 			   bonding_debug_root, bond->dev->name);
-	if (d) {
+	if (!IS_ERR(d)) {
 		bond->debug_dir = d;
 	} else {
 		netdev_warn(bond->dev, "failed to reregister, so just unregister old one\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/bonding/bond_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/bonding/bond_main.c
@@ -784,16 +784,10 @@
 	return bestslave;
 }
 
+/* must be called in RCU critical section or with RTNL held */
 static bool bond_should_notify_peers(struct bonding *bond)
 {
-	struct slave *slave;
-
-	rcu_read_lock();
-	slave = rcu_dereference(bond->curr_active_slave);
-	rcu_read_unlock();
-
-	netdev_dbg(bond->dev, "bond_should_notify_peers: slave %s\n",
-		   slave ? slave->dev->name : "NULL");
+	struct slave *slave = rcu_dereference_rtnl(bond->curr_active_slave);
 
 	if (!slave || !bond->send_peer_notif ||
 	    bond->send_peer_notif %
@@ -802,6 +796,9 @@
 	    test_bit(__LINK_STATE_LINKWATCH_PENDING, &slave->dev->state))
 		return false;
 
+	netdev_dbg(bond->dev, "bond_should_notify_peers: slave %s\n",
+		   slave ? slave->dev->name : "NULL");
+
 	return true;
 }
 
@@ -1144,14 +1141,26 @@
 static void bond_setup_by_slave(struct net_device *bond_dev,
 				struct net_device *slave_dev)
 {
+	bool was_up = !!(bond_dev->flags & IFF_UP);
+
+	dev_close(bond_dev);
+
 	bond_dev->header_ops	    = slave_dev->header_ops;
 
 	bond_dev->type		    = slave_dev->type;
 	bond_dev->hard_header_len   = slave_dev->hard_header_len;
+	bond_dev->needed_headroom   = slave_dev->needed_headroom;
 	bond_dev->addr_len	    = slave_dev->addr_len;
 
 	memcpy(bond_dev->broadcast, slave_dev->broadcast,
 		slave_dev->addr_len);
+
+	if (slave_dev->flags & IFF_POINTOPOINT) {
+		bond_dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST);
+		bond_dev->flags |= (IFF_POINTOPOINT | IFF_NOARP);
+	}
+	if (was_up)
+		dev_open(bond_dev, NULL);
 }
 
 /* On bonding slaves other than the currently active slave, suppress
@@ -1218,7 +1227,7 @@
 	skb->dev = bond->dev;
 
 	if (BOND_MODE(bond) == BOND_MODE_ALB &&
-	    bond->dev->priv_flags & IFF_BRIDGE_PORT &&
+	    netif_is_bridge_port(bond->dev) &&
 	    skb->pkt_type == PACKET_HOST) {
 
 		if (unlikely(skb_cow_head(skb,
@@ -1292,7 +1301,39 @@
 	slave->dev->flags &= ~IFF_SLAVE;
 }
 
-static struct slave *bond_alloc_slave(struct bonding *bond)
+static void slave_kobj_release(struct kobject *kobj)
+{
+	struct slave *slave = to_slave(kobj);
+	struct bonding *bond = bond_get_bond_by_slave(slave);
+
+	cancel_delayed_work_sync(&slave->notify_work);
+	if (BOND_MODE(bond) == BOND_MODE_8023AD)
+		kfree(SLAVE_AD_INFO(slave));
+
+	kfree(slave);
+}
+
+static struct kobj_type slave_ktype = {
+	.release = slave_kobj_release,
+#ifdef CONFIG_SYSFS
+	.sysfs_ops = &slave_sysfs_ops,
+#endif
+};
+
+static int bond_kobj_init(struct slave *slave)
+{
+	int err;
+
+	err = kobject_init_and_add(&slave->kobj, &slave_ktype,
+				   &(slave->dev->dev.kobj), "bonding_slave");
+	if (err)
+		kobject_put(&slave->kobj);
+
+	return err;
+}
+
+static struct slave *bond_alloc_slave(struct bonding *bond,
+				      struct net_device *slave_dev)
 {
 	struct slave *slave = NULL;
 
@@ -1300,30 +1341,25 @@
 	if (!slave)
 		return NULL;
 
+	slave->bond = bond;
+	slave->dev = slave_dev;
+	INIT_DELAYED_WORK(&slave->notify_work, bond_netdev_notify_work);
+
+	if (bond_kobj_init(slave))
+		return NULL;
+
 	if (BOND_MODE(bond) == BOND_MODE_8023AD) {
 		SLAVE_AD_INFO(slave) = kzalloc(sizeof(struct ad_slave_info),
 					       GFP_KERNEL);
 		if (!SLAVE_AD_INFO(slave)) {
-			kfree(slave);
+			kobject_put(&slave->kobj);
 			return NULL;
 		}
 	}
-	INIT_DELAYED_WORK(&slave->notify_work, bond_netdev_notify_work);
 
 	return slave;
 }
 
-static void bond_free_slave(struct slave *slave)
-{
-	struct bonding *bond = bond_get_bond_by_slave(slave);
-
-	cancel_delayed_work_sync(&slave->notify_work);
-	if (BOND_MODE(bond) == BOND_MODE_8023AD)
-		kfree(SLAVE_AD_INFO(slave));
-
-	kfree(slave);
-}
-
 static void bond_fill_ifbond(struct bonding *bond, struct ifbond *info)
 {
 	info->bond_mode = BOND_MODE(bond);
@@ -1507,14 +1543,12 @@
 			goto err_undo_flags;
 	}
 
-	new_slave = bond_alloc_slave(bond);
+	new_slave = bond_alloc_slave(bond, slave_dev);
 	if (!new_slave) {
 		res = -ENOMEM;
 		goto err_undo_flags;
 	}
 
-	new_slave->bond = bond;
-	new_slave->dev = slave_dev;
 	/* Set the new_slave's queue_id to be zero.  Queue ID mapping
 	 * is set via sysfs or module option if desired.
 	 */
@@ -1836,7 +1870,7 @@
 	dev_set_mtu(slave_dev, new_slave->original_mtu);
 
 err_free:
-	bond_free_slave(new_slave);
+	kobject_put(&new_slave->kobj);
 
 err_undo_flags:
 	/* Enslave of first slave has failed and we need to fix master's mac */
@@ -1900,7 +1934,6 @@
 	/* recompute stats just before removing the slave */
 	bond_get_stats(bond->dev, &bond->bond_stats);
 
-	bond_upper_dev_unlink(bond, slave);
 	/* unregister rx_handler early so bond_handle_frame wouldn't be called
 	 * for this slave anymore.
 	 */
@@ -1909,6 +1942,8 @@
 	if (BOND_MODE(bond) == BOND_MODE_8023AD)
 		bond_3ad_unbind_slave(slave);
 
+	bond_upper_dev_unlink(bond, slave);
+
 	if (bond_mode_can_use_xmit_hash(bond))
 		bond_update_slave_arr(bond, slave);
 
@@ -1952,10 +1987,9 @@
 		bond_select_active_slave(bond);
 	}
 
-	if (!bond_has_slaves(bond)) {
-		bond_set_carrier(bond);
+	bond_set_carrier(bond);
+	if (!bond_has_slaves(bond))
 		eth_hw_addr_random(bond_dev);
-	}
 
 	unblock_netpoll_tx();
 	synchronize_rcu();
@@ -2016,7 +2050,7 @@
 	if (!netif_is_bond_master(slave_dev))
 		slave_dev->priv_flags &= ~IFF_BONDING;
 
-	bond_free_slave(slave);
+	kobject_put(&slave->kobj);
 
 	return 0;
 }
@@ -2037,7 +2071,8 @@
 	int ret;
 
 	ret = __bond_release_one(bond_dev, slave_dev, false, true);
-	if (ret == 0 && !bond_has_slaves(bond)) {
+	if (ret == 0 && !bond_has_slaves(bond) &&
+	    bond_dev->reg_state != NETREG_UNREGISTERING) {
 		bond_dev->priv_flags |= IFF_DISABLE_NETPOLL;
 		netdev_info(bond_dev, "Destroying bond\n");
 		bond_remove_proc_entry(bond);
@@ -2075,12 +2110,21 @@
 /* called with rcu_read_lock() */
 static int bond_miimon_inspect(struct bonding *bond)
 {
+	bool ignore_updelay = false;
 	int link_state, commit = 0;
 	struct list_head *iter;
 	struct slave *slave;
-	bool ignore_updelay;
 
-	ignore_updelay = !rcu_dereference(bond->curr_active_slave);
+	if (BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP) {
+		ignore_updelay = !rcu_dereference(bond->curr_active_slave);
+	} else {
+		struct bond_up_slave *usable_slaves;
+
+		usable_slaves = rcu_dereference(bond->usable_slaves);
+
+		if (usable_slaves && usable_slaves->count == 0)
+			ignore_updelay = true;
+	}
 
 	bond_for_each_slave_rcu(bond, slave, iter) {
 		bond_propose_link_state(slave, BOND_LINK_NOCHANGE);
@@ -2225,9 +2269,6 @@
 			} else if (BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP) {
 				/* make it immediately active */
 				bond_set_active_slave(slave);
-			} else if (slave != primary) {
-				/* prevent it from being the active one */
-				bond_set_backup_slave(slave);
 			}
 
 			slave_info(bond->dev, slave->dev, "link status definitely up, %u Mbps %s duplex\n",
@@ -2780,6 +2821,9 @@
 			if (bond_time_in_interval(bond, last_rx, 1)) {
 				bond_propose_link_state(slave, BOND_LINK_UP);
 				commit++;
+			} else if (slave->link == BOND_LINK_BACK) {
+				bond_propose_link_state(slave, BOND_LINK_FAIL);
+				commit++;
 			}
 			continue;
 		}
@@ -2888,6 +2932,19 @@
 
 			continue;
 
+		case BOND_LINK_FAIL:
+			bond_set_slave_link_state(slave, BOND_LINK_FAIL,
+						  BOND_SLAVE_NOTIFY_NOW);
+			bond_set_slave_inactive_flags(slave,
+						      BOND_SLAVE_NOTIFY_NOW);
+
+			/* A slave has just been enslaved and has become
+			 * the current active slave.
+			 */
+			if (rtnl_dereference(bond->curr_active_slave))
+				RCU_INIT_POINTER(bond->current_arp_slave, NULL);
+			continue;
+
 		default:
 			slave_err(bond->dev, slave->dev,
 				  "impossible: link_new_state %d on slave\n",
@@ -2938,8 +2995,6 @@
 			return should_notify_rtnl;
 	}
 
-	bond_set_slave_inactive_flags(curr_arp_slave, BOND_SLAVE_NOTIFY_LATER);
-
 	bond_for_each_slave_rcu(bond, slave, iter) {
 		if (!found && !before && bond_slave_is_up(slave))
 			before = slave;
@@ -3033,9 +3088,11 @@
 		if (!rtnl_trylock())
 			return;
 
-		if (should_notify_peers)
+		if (should_notify_peers) {
+			bond->send_peer_notif--;
 			call_netdevice_notifiers(NETDEV_NOTIFY_PEERS,
 						 bond->dev);
+		}
 		if (should_notify_rtnl) {
 			bond_slave_state_notify(bond);
 			bond_slave_link_notify(bond);
@@ -3190,7 +3247,11 @@
 		unblock_netpoll_tx();
 		break;
 	case NETDEV_FEAT_CHANGE:
-		bond_compute_features(bond);
+		if (!bond->notifier_ctx) {
+			bond->notifier_ctx = true;
+			bond_compute_features(bond);
+			bond->notifier_ctx = false;
+		}
 		break;
 	case NETDEV_RESEND_IGMP:
 		/* Propagate to master device */
@@ -3439,6 +3500,47 @@
 	}
 }
 
+#ifdef CONFIG_LOCKDEP
+static int bond_get_lowest_level_rcu(struct net_device *dev)
+{
+	struct net_device *ldev, *next, *now, *dev_stack[MAX_NEST_DEV + 1];
+	struct list_head *niter, *iter, *iter_stack[MAX_NEST_DEV + 1];
+	int cur = 0, max = 0;
+
+	now = dev;
+	iter = &dev->adj_list.lower;
+
+	while (1) {
+		next = NULL;
+		while (1) {
+			ldev = netdev_next_lower_dev_rcu(now, &iter);
+			if (!ldev)
+				break;
+
+			next = ldev;
+			niter = &ldev->adj_list.lower;
+			dev_stack[cur] = now;
+			iter_stack[cur++] = iter;
+			if (max <= cur)
+				max = cur;
+			break;
+		}
+
+		if (!next) {
+			if (!cur)
+				return max;
+			next = dev_stack[--cur];
+			niter = iter_stack[cur];
+		}
+
+		now = next;
+		iter = niter;
+	}
+
+	return max;
+}
+#endif
+
 static void bond_get_stats(struct net_device *bond_dev,
 			   struct rtnl_link_stats64 *stats)
 {
@@ -3446,11 +3548,17 @@
 	struct rtnl_link_stats64 temp;
 	struct list_head *iter;
 	struct slave *slave;
+	int nest_level = 0;
 
-	spin_lock(&bond->stats_lock);
-	memcpy(stats, &bond->bond_stats, sizeof(*stats));
 
 	rcu_read_lock();
+#ifdef CONFIG_LOCKDEP
+	nest_level = bond_get_lowest_level_rcu(bond_dev);
+#endif
+
+	spin_lock_nested(&bond->stats_lock, nest_level);
+	memcpy(stats, &bond->bond_stats, sizeof(*stats));
+
 	bond_for_each_slave_rcu(bond, slave, iter) {
 		const struct rtnl_link_stats64 *new =
 			dev_get_stats(slave->dev, &temp);
@@ -3460,10 +3568,10 @@
 		/* save off the slave stats for the next run */
 		memcpy(&slave->slave_stats, new, sizeof(*new));
 	}
-	rcu_read_unlock();
 
 	memcpy(&bond->bond_stats, stats, sizeof(*stats));
 	spin_unlock(&bond->stats_lock);
+	rcu_read_unlock();
 }
 
 static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd)
@@ -3553,6 +3661,8 @@
 	case BOND_RELEASE_OLD:
 	case SIOCBONDRELEASE:
 		res = bond_release(bond_dev, slave_dev);
+		if (!res)
+			netdev_update_lockdep_key(slave_dev);
 		break;
 	case BOND_SETHWADDR_OLD:
 	case SIOCBONDSETHWADDR:
@@ -3612,32 +3722,35 @@
 	const struct net_device_ops *slave_ops;
 	struct neigh_parms parms;
 	struct slave *slave;
-	int ret;
+	int ret = 0;
 
-	slave = bond_first_slave(bond);
+	rcu_read_lock();
+	slave = bond_first_slave_rcu(bond);
 	if (!slave)
-		return 0;
+		goto out;
 	slave_ops = slave->dev->netdev_ops;
 	if (!slave_ops->ndo_neigh_setup)
-		return 0;
-
-	parms.neigh_setup = NULL;
-	parms.neigh_cleanup = NULL;
-	ret = slave_ops->ndo_neigh_setup(slave->dev, &parms);
-	if (ret)
-		return ret;
+		goto out;
 
-	/* Assign slave's neigh_cleanup to neighbour in case cleanup is called
-	 * after the last slave has been detached.  Assumes that all slaves
-	 * utilize the same neigh_cleanup (true at this writing as only user
-	 * is ipoib).
+	/* TODO: find another way [1] to implement this.
+	 * Passing a zeroed structure is fragile,
+	 * but at least we do not pass garbage.
+	 *
+	 * [1] One way would be that ndo_neigh_setup() never touch
+	 *     struct neigh_parms, but propagate the new neigh_setup()
+	 *     back to ___neigh_create() / neigh_parms_alloc()
 	 */
-	n->parms->neigh_cleanup = parms.neigh_cleanup;
+	memset(&parms, 0, sizeof(parms));
+	ret = slave_ops->ndo_neigh_setup(slave->dev, &parms);
 
-	if (!parms.neigh_setup)
-		return 0;
+	if (ret)
+		goto out;
 
-	return parms.neigh_setup(n);
+	if (parms.neigh_setup)
+		ret = parms.neigh_setup(n);
+out:
+	rcu_read_unlock();
+	return ret;
 }
 
 /* The bonding ndo_neigh_setup is called at init time beofre any
@@ -3948,6 +4061,29 @@
 	bond_slave_arr_work_rearm(bond, 1);
 }
 
+static void bond_skip_slave(struct bond_up_slave *slaves,
+			    struct slave *skipslave)
+{
+	int idx;
+
+	/* Rare situation where caller has asked to skip a specific
+	 * slave but allocation failed (most likely!). BTW this is
+	 * only possible when the call is initiated from
+	 * __bond_release_one(). In this situation; overwrite the
+	 * skipslave entry in the array with the last entry from the
+	 * array to avoid a situation where the xmit path may choose
+	 * this to-be-skipped slave to send a packet out.
+	 */
+	for (idx = 0; slaves && idx < slaves->count; idx++) {
+		if (skipslave == slaves->arr[idx]) {
+			slaves->arr[idx] =
+				slaves->arr[slaves->count - 1];
+			slaves->count--;
+			break;
+		}
+	}
+}
+
 /* Build the usable slaves array in control path for modes that use xmit-hash
  * to determine the slave interface -
  * (a) BOND_MODE_8023AD
@@ -3958,9 +4094,9 @@
  */
 int bond_update_slave_arr(struct bonding *bond, struct slave *skipslave)
 {
+	struct bond_up_slave *usable_slaves, *old_usable_slaves;
 	struct slave *slave;
 	struct list_head *iter;
-	struct bond_up_slave *new_arr, *old_arr;
 	int agg_id = 0;
 	int ret = 0;
 
@@ -3968,11 +4104,10 @@
 	WARN_ON(lockdep_is_held(&bond->mode_lock));
 #endif
 
-	new_arr = kzalloc(offsetof(struct bond_up_slave, arr[bond->slave_cnt]),
-			  GFP_KERNEL);
-	if (!new_arr) {
+	usable_slaves = kzalloc(struct_size(usable_slaves, arr,
+					    bond->slave_cnt), GFP_KERNEL);
+	if (!usable_slaves) {
 		ret = -ENOMEM;
-		pr_err("Failed to build slave-array.\n");
 		goto out;
 	}
 	if (BOND_MODE(bond) == BOND_MODE_8023AD) {
@@ -3980,14 +4115,14 @@
 
 		if (bond_3ad_get_active_agg_info(bond, &ad_info)) {
 			pr_debug("bond_3ad_get_active_agg_info failed\n");
-			kfree_rcu(new_arr, rcu);
+			kfree_rcu(usable_slaves, rcu);
 			/* No active aggragator means it's not safe to use
 			 * the previous array.
 			 */
-			old_arr = rtnl_dereference(bond->slave_arr);
-			if (old_arr) {
-				RCU_INIT_POINTER(bond->slave_arr, NULL);
-				kfree_rcu(old_arr, rcu);
+			old_usable_slaves = rtnl_dereference(bond->usable_slaves);
+			if (old_usable_slaves) {
+				RCU_INIT_POINTER(bond->usable_slaves, NULL);
+				kfree_rcu(old_usable_slaves, rcu);
 			}
 			goto out;
 		}
@@ -4007,37 +4142,20 @@
 			continue;
 
 		slave_dbg(bond->dev, slave->dev, "Adding slave to tx hash array[%d]\n",
-			  new_arr->count);
+			  usable_slaves->count);
 
-		new_arr->arr[new_arr->count++] = slave;
+		usable_slaves->arr[usable_slaves->count++] = slave;
 	}
 
-	old_arr = rtnl_dereference(bond->slave_arr);
-	rcu_assign_pointer(bond->slave_arr, new_arr);
-	if (old_arr)
-		kfree_rcu(old_arr, rcu);
+	old_usable_slaves = rtnl_dereference(bond->usable_slaves);
+	rcu_assign_pointer(bond->usable_slaves, usable_slaves);
+	if (old_usable_slaves)
+		kfree_rcu(old_usable_slaves, rcu);
 out:
-	if (ret != 0 && skipslave) {
-		int idx;
+	if (ret != 0 && skipslave)
+		bond_skip_slave(rtnl_dereference(bond->usable_slaves),
+				skipslave);
 
-		/* Rare situation where caller has asked to skip a specific
-		 * slave but allocation failed (most likely!). BTW this is
-		 * only possible when the call is initiated from
-		 * __bond_release_one(). In this situation; overwrite the
-		 * skipslave entry in the array with the last entry from the
-		 * array to avoid a situation where the xmit path may choose
-		 * this to-be-skipped slave to send a packet out.
-		 */
-		old_arr = rtnl_dereference(bond->slave_arr);
-		for (idx = 0; old_arr != NULL && idx < old_arr->count; idx++) {
-			if (skipslave == old_arr->arr[idx]) {
-				old_arr->arr[idx] =
-				    old_arr->arr[old_arr->count-1];
-				old_arr->count--;
-				break;
-			}
-		}
-	}
 	return ret;
 }
 
@@ -4053,7 +4171,7 @@
 	struct bond_up_slave *slaves;
 	unsigned int count;
 
-	slaves = rcu_dereference(bond->slave_arr);
+	slaves = rcu_dereference(bond->usable_slaves);
 	count = slaves ? READ_ONCE(slaves->count) : 0;
 	if (likely(count)) {
 		slave = slaves->arr[bond_xmit_hash(bond, skb) % count];
@@ -4197,13 +4315,23 @@
 	return ret;
 }
 
+static u32 bond_mode_bcast_speed(struct slave *slave, u32 speed)
+{
+	if (speed == 0 || speed == SPEED_UNKNOWN)
+		speed = slave->speed;
+	else
+		speed = min(speed, slave->speed);
+
+	return speed;
+}
+
 static int bond_ethtool_get_link_ksettings(struct net_device *bond_dev,
 					   struct ethtool_link_ksettings *cmd)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
-	unsigned long speed = 0;
 	struct list_head *iter;
 	struct slave *slave;
+	u32 speed = 0;
 
 	cmd->base.duplex = DUPLEX_UNKNOWN;
 	cmd->base.port = PORT_OTHER;
@@ -4215,8 +4343,13 @@
 	 */
 	bond_for_each_slave(bond, slave, iter) {
 		if (bond_slave_can_tx(slave)) {
-			if (slave->speed != SPEED_UNKNOWN)
-				speed += slave->speed;
+			if (slave->speed != SPEED_UNKNOWN) {
+				if (BOND_MODE(bond) == BOND_MODE_BROADCAST)
+					speed = bond_mode_bcast_speed(slave,
+								      speed);
+				else
+					speed += slave->speed;
+			}
 			if (cmd->base.duplex == DUPLEX_UNKNOWN &&
 			    slave->duplex != DUPLEX_UNKNOWN)
 				cmd->base.duplex = slave->duplex;
@@ -4321,7 +4454,9 @@
 
 	bond_dev->hw_features = BOND_VLAN_FEATURES |
 				NETIF_F_HW_VLAN_CTAG_RX |
-				NETIF_F_HW_VLAN_CTAG_FILTER;
+				NETIF_F_HW_VLAN_CTAG_FILTER |
+				NETIF_F_HW_VLAN_STAG_RX |
+				NETIF_F_HW_VLAN_STAG_FILTER;
 
 	bond_dev->hw_features |= NETIF_F_GSO_ENCAP_ALL | NETIF_F_GSO_UDP_L4;
 	bond_dev->features |= bond_dev->hw_features;
@@ -4345,9 +4480,9 @@
 		__bond_release_one(bond_dev, slave->dev, true, true);
 	netdev_info(bond_dev, "Released all slaves\n");
 
-	arr = rtnl_dereference(bond->slave_arr);
+	arr = rtnl_dereference(bond->usable_slaves);
 	if (arr) {
-		RCU_INIT_POINTER(bond->slave_arr, NULL);
+		RCU_INIT_POINTER(bond->usable_slaves, NULL);
 		kfree_rcu(arr, rcu);
 	}
 
@@ -4757,6 +4892,8 @@
 	if (!bond->wq)
 		return -ENOMEM;
 
+	bond->notifier_ctx = false;
+
 	spin_lock_init(&bond->stats_lock);
 	lockdep_register_key(&bond->stats_lock_key);
 	lockdep_set_class(&bond->stats_lock, &bond->stats_lock_key);
@@ -4815,15 +4952,19 @@
 	bond_dev->rtnl_link_ops = &bond_link_ops;
 
 	res = register_netdevice(bond_dev);
+	if (res < 0) {
+		free_netdev(bond_dev);
+		rtnl_unlock();
+
+		return res;
+	}
 
 	netif_carrier_off(bond_dev);
 
 	bond_work_init_all(bond);
 
 	rtnl_unlock();
-	if (res < 0)
-		free_netdev(bond_dev);
-	return res;
+	return 0;
 }
 
 static int __net_init bond_net_init(struct net *net)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/bonding/bond_netlink.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/bonding/bond_netlink.c
@@ -456,11 +456,10 @@
 		return err;
 
 	err = register_netdevice(bond_dev);
-
-	netif_carrier_off(bond_dev);
 	if (!err) {
 		struct bonding *bond = netdev_priv(bond_dev);
 
+		netif_carrier_off(bond_dev);
 		bond_work_init_all(bond);
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/bonding/bond_options.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/bonding/bond_options.c
@@ -1084,9 +1084,9 @@
 	__be32 target;
 
 	if (newval->string) {
-		if (!in4_pton(newval->string+1, -1, (u8 *)&target, -1, NULL)) {
-			netdev_err(bond->dev, "invalid ARP target %pI4 specified\n",
-				   &target);
+		if (strlen(newval->string) < 1 ||
+		    !in4_pton(newval->string + 1, -1, (u8 *)&target, -1, NULL)) {
+			netdev_err(bond->dev, "invalid ARP target specified\n");
 			return ret;
 		}
 		if (newval->string[0] == '+')
@@ -1398,6 +1398,8 @@
 	case '-':
 		slave_dbg(bond->dev, dev, "Releasing interface\n");
 		ret = bond_release(bond->dev, dev);
+		if (!ret)
+			netdev_update_lockdep_key(dev);
 		break;
 
 	default:
@@ -1450,7 +1452,7 @@
 		mac = (u8 *)&newval->value;
 	}
 
-	if (!is_valid_ether_addr(mac))
+	if (is_multicast_ether_addr(mac))
 		goto err;
 
 	netdev_dbg(bond->dev, "Setting ad_actor_system to %pM\n", mac);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/bonding/bond_sysfs_slave.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/bonding/bond_sysfs_slave.c
@@ -108,20 +108,19 @@
 }
 static SLAVE_ATTR_RO(ad_partner_oper_port_state);
 
-static const struct slave_attribute *slave_attrs[] = {
-	&slave_attr_state,
-	&slave_attr_mii_status,
-	&slave_attr_link_failure_count,
-	&slave_attr_perm_hwaddr,
-	&slave_attr_queue_id,
-	&slave_attr_ad_aggregator_id,
-	&slave_attr_ad_actor_oper_port_state,
-	&slave_attr_ad_partner_oper_port_state,
+static const struct attribute *slave_attrs[] = {
+	&slave_attr_state.attr,
+	&slave_attr_mii_status.attr,
+	&slave_attr_link_failure_count.attr,
+	&slave_attr_perm_hwaddr.attr,
+	&slave_attr_queue_id.attr,
+	&slave_attr_ad_aggregator_id.attr,
+	&slave_attr_ad_actor_oper_port_state.attr,
+	&slave_attr_ad_partner_oper_port_state.attr,
 	NULL
 };
 
 #define to_slave_attr(_at) container_of(_at, struct slave_attribute, attr)
-#define to_slave(obj)	container_of(obj, struct slave, kobj)
 
 static ssize_t slave_show(struct kobject *kobj,
 			  struct attribute *attr, char *buf)
@@ -132,43 +131,16 @@
 	return slave_attr->show(slave, buf);
 }
 
-static const struct sysfs_ops slave_sysfs_ops = {
+const struct sysfs_ops slave_sysfs_ops = {
 	.show = slave_show,
 };
 
-static struct kobj_type slave_ktype = {
-#ifdef CONFIG_SYSFS
-	.sysfs_ops = &slave_sysfs_ops,
-#endif
-};
-
 int bond_sysfs_slave_add(struct slave *slave)
 {
-	const struct slave_attribute **a;
-	int err;
-
-	err = kobject_init_and_add(&slave->kobj, &slave_ktype,
-				   &(slave->dev->dev.kobj), "bonding_slave");
-	if (err)
-		return err;
-
-	for (a = slave_attrs; *a; ++a) {
-		err = sysfs_create_file(&slave->kobj, &((*a)->attr));
-		if (err) {
-			kobject_put(&slave->kobj);
-			return err;
-		}
-	}
-
-	return 0;
+	return sysfs_create_files(&slave->kobj, slave_attrs);
 }
 
 void bond_sysfs_slave_del(struct slave *slave)
 {
-	const struct slave_attribute **a;
-
-	for (a = slave_attrs; *a; ++a)
-		sysfs_remove_file(&slave->kobj, &((*a)->attr));
-
-	kobject_put(&slave->kobj);
+	sysfs_remove_files(&slave->kobj, slave_attrs);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/caif/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/caif/Kconfig
@@ -10,37 +10,37 @@
 	depends on CAIF && TTY
 	default n
 	---help---
-	The CAIF TTY transport driver is a Line Discipline (ldisc)
-	identified as N_CAIF. When this ldisc is opened from user space
-	it will redirect the TTY's traffic into the CAIF stack.
+	  The CAIF TTY transport driver is a Line Discipline (ldisc)
+	  identified as N_CAIF. When this ldisc is opened from user space
+	  it will redirect the TTY's traffic into the CAIF stack.
 
 config CAIF_SPI_SLAVE
 	tristate "CAIF SPI transport driver for slave interface"
 	depends on CAIF && HAS_DMA
 	default n
 	---help---
-	The CAIF Link layer SPI Protocol driver for Slave SPI interface.
-	This driver implements a platform driver to accommodate for a
-	platform specific SPI device. A sample CAIF SPI Platform device is
-	provided in Documentation/networking/caif/spi_porting.txt
+	  The CAIF Link layer SPI Protocol driver for Slave SPI interface.
+	  This driver implements a platform driver to accommodate for a
+	  platform specific SPI device. A sample CAIF SPI Platform device is
+	  provided in <file:Documentation/networking/caif/spi_porting.txt>.
 
 config CAIF_SPI_SYNC
 	bool "Next command and length in start of frame"
 	depends on CAIF_SPI_SLAVE
 	default n
 	---help---
-	Putting the next command and length in the start of the frame can
-	help to synchronize to the next transfer in case of over or under-runs.
-	This option also needs to be enabled on the modem.
+	  Putting the next command and length in the start of the frame can
+	  help to synchronize to the next transfer in case of over or under-runs.
+	  This option also needs to be enabled on the modem.
 
 config CAIF_HSI
-       tristate "CAIF HSI transport driver"
-       depends on CAIF
-       default n
-       ---help---
-       The caif low level driver for CAIF over HSI.
-       Be aware that if you enable this then you also need to
-       enable a low-level HSI driver.
+	tristate "CAIF HSI transport driver"
+	depends on CAIF
+	default n
+	---help---
+	  The CAIF low level driver for CAIF over HSI.
+	  Be aware that if you enable this then you also need to
+	  enable a low-level HSI driver.
 
 config CAIF_VIRTIO
 	tristate "CAIF virtio transport driver"
@@ -50,7 +50,7 @@
 	select GENERIC_ALLOCATOR
 	default n
 	---help---
-	The caif driver for CAIF over Virtio.
+	  The CAIF driver for CAIF over Virtio.
 
 if CAIF_VIRTIO
 source "drivers/vhost/Kconfig.vringh"
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/caif/caif_serial.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/caif/caif_serial.c
@@ -270,7 +270,6 @@
 {
 	struct ser_device *ser;
 
-	BUG_ON(dev == NULL);
 	ser = netdev_priv(dev);
 
 	/* Send flow off once, on high water mark */
@@ -352,6 +351,7 @@
 	rtnl_lock();
 	result = register_netdevice(dev);
 	if (result) {
+		tty_kref_put(tty);
 		rtnl_unlock();
 		free_netdev(dev);
 		return -ENODEV;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/caif/caif_virtio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/caif/caif_virtio.c
@@ -723,13 +723,21 @@
 	/* Carrier is off until netdevice is opened */
 	netif_carrier_off(netdev);
 
+	/* serialize netdev register + virtio_device_ready() with ndo_open() */
+	rtnl_lock();
+
 	/* register Netdev */
-	err = register_netdev(netdev);
+	err = register_netdevice(netdev);
 	if (err) {
+		rtnl_unlock();
 		dev_err(&vdev->dev, "Unable to register netdev (%d)\n", err);
 		goto err;
 	}
 
+	virtio_device_ready(vdev);
+
+	rtnl_unlock();
+
 	debugfs_init(cfv);
 
 	return 0;
@@ -738,7 +746,7 @@
 
 	if (cfv->vr_rx)
 		vdev->vringh_config->del_vrhs(cfv->vdev);
-	if (cfv->vdev)
+	if (cfv->vq_tx)
 		vdev->config->del_vqs(cfv->vdev);
 	free_netdev(netdev);
 	return err;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/Kconfig
@@ -123,6 +123,7 @@
 config CAN_KVASER_PCIEFD
 	depends on PCI
 	tristate "Kvaser PCIe FD cards"
+	select CRC32
 	  help
 	  This is a driver for the Kvaser PCI Express CAN FD family.
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/Makefile
@@ -7,12 +7,7 @@
 obj-$(CONFIG_CAN_VXCAN)		+= vxcan.o
 obj-$(CONFIG_CAN_SLCAN)		+= slcan.o
 
-obj-$(CONFIG_CAN_DEV)		+= can-dev.o
-can-dev-y			+= dev.o
-can-dev-y			+= rx-offload.o
-
-can-dev-$(CONFIG_CAN_LEDS)	+= led.o
-
+obj-y				+= dev/
 obj-y				+= rcar/
 obj-y				+= spi/
 obj-y				+= usb/
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/c_can/c_can.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/c_can/c_can.c
@@ -212,18 +212,6 @@
 	.brp_inc = 1,
 };
 
-static inline void c_can_pm_runtime_enable(const struct c_can_priv *priv)
-{
-	if (priv->device)
-		pm_runtime_enable(priv->device);
-}
-
-static inline void c_can_pm_runtime_disable(const struct c_can_priv *priv)
-{
-	if (priv->device)
-		pm_runtime_disable(priv->device);
-}
-
 static inline void c_can_pm_runtime_get_sync(const struct c_can_priv *priv)
 {
 	if (priv->device)
@@ -1013,7 +1001,6 @@
 
 	/* common for all type of bus errors */
 	priv->can.can_stats.bus_error++;
-	stats->rx_errors++;
 
 	/* propagate the error condition to the CAN stack */
 	skb = alloc_can_err_skb(dev, &cf);
@@ -1030,26 +1017,32 @@
 	case LEC_STUFF_ERROR:
 		netdev_dbg(dev, "stuff error\n");
 		cf->data[2] |= CAN_ERR_PROT_STUFF;
+		stats->rx_errors++;
 		break;
 	case LEC_FORM_ERROR:
 		netdev_dbg(dev, "form error\n");
 		cf->data[2] |= CAN_ERR_PROT_FORM;
+		stats->rx_errors++;
 		break;
 	case LEC_ACK_ERROR:
 		netdev_dbg(dev, "ack error\n");
 		cf->data[3] = CAN_ERR_PROT_LOC_ACK;
+		stats->tx_errors++;
 		break;
 	case LEC_BIT1_ERROR:
 		netdev_dbg(dev, "bit1 error\n");
 		cf->data[2] |= CAN_ERR_PROT_BIT1;
+		stats->tx_errors++;
 		break;
 	case LEC_BIT0_ERROR:
 		netdev_dbg(dev, "bit0 error\n");
 		cf->data[2] |= CAN_ERR_PROT_BIT0;
+		stats->tx_errors++;
 		break;
 	case LEC_CRC_ERROR:
 		netdev_dbg(dev, "CRC error\n");
 		cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
+		stats->rx_errors++;
 		break;
 	default:
 		break;
@@ -1334,7 +1327,6 @@
 
 int register_c_can_dev(struct net_device *dev)
 {
-	struct c_can_priv *priv = netdev_priv(dev);
 	int err;
 
 	/* Deactivate pins to prevent DRA7 DCAN IP from being
@@ -1344,28 +1336,19 @@
 	 */
 	pinctrl_pm_select_sleep_state(dev->dev.parent);
 
-	c_can_pm_runtime_enable(priv);
-
 	dev->flags |= IFF_ECHO;	/* we support local echo */
 	dev->netdev_ops = &c_can_netdev_ops;
 
 	err = register_candev(dev);
-	if (err)
-		c_can_pm_runtime_disable(priv);
-	else
+	if (!err)
 		devm_can_led_init(dev);
-
 	return err;
 }
 EXPORT_SYMBOL_GPL(register_c_can_dev);
 
 void unregister_c_can_dev(struct net_device *dev)
 {
-	struct c_can_priv *priv = netdev_priv(dev);
-
 	unregister_candev(dev);
-
-	c_can_pm_runtime_disable(priv);
 }
 EXPORT_SYMBOL_GPL(unregister_c_can_dev);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/c_can/c_can_pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/c_can/c_can_pci.c
@@ -239,12 +239,13 @@
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct c_can_priv *priv = netdev_priv(dev);
+	void __iomem *addr = priv->base;
 
 	unregister_c_can_dev(dev);
 
 	free_c_can_dev(dev);
 
-	pci_iounmap(pdev, priv->base);
+	pci_iounmap(pdev, addr);
 	pci_disable_msi(pdev);
 	pci_clear_master(pdev);
 	pci_release_regions(pdev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/c_can/c_can_platform.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/c_can/c_can_platform.c
@@ -29,6 +29,7 @@
 #include <linux/list.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
 #include <linux/clk.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -385,17 +386,20 @@
 	platform_set_drvdata(pdev, dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
+	pm_runtime_enable(priv->device);
 	ret = register_c_can_dev(dev);
 	if (ret) {
 		dev_err(&pdev->dev, "registering %s failed (err=%d)\n",
 			KBUILD_MODNAME, ret);
-		goto exit_free_device;
+		goto exit_pm_runtime;
 	}
 
 	dev_info(&pdev->dev, "%s device registered (regs=%p, irq=%d)\n",
 		 KBUILD_MODNAME, priv->base, dev->irq);
 	return 0;
 
+exit_pm_runtime:
+	pm_runtime_disable(priv->device);
 exit_free_device:
 	free_c_can_dev(dev);
 exit:
@@ -407,9 +411,10 @@
 static int c_can_plat_remove(struct platform_device *pdev)
 {
 	struct net_device *dev = platform_get_drvdata(pdev);
+	struct c_can_priv *priv = netdev_priv(dev);
 
 	unregister_c_can_dev(dev);
-
+	pm_runtime_disable(priv->device);
 	free_c_can_dev(dev);
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/cc770/cc770_isa.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/cc770/cc770_isa.c
@@ -264,22 +264,24 @@
 	if (err) {
 		dev_err(&pdev->dev,
 			"couldn't register device (err=%d)\n", err);
-		goto exit_unmap;
+		goto exit_free;
 	}
 
 	dev_info(&pdev->dev, "device registered (reg_base=0x%p, irq=%d)\n",
 		 priv->reg_base, dev->irq);
 	return 0;
 
- exit_unmap:
+exit_free:
+	free_cc770dev(dev);
+exit_unmap:
 	if (mem[idx])
 		iounmap(base);
- exit_release:
+exit_release:
 	if (mem[idx])
 		release_mem_region(mem[idx], iosize);
 	else
 		release_region(port[idx], iosize);
- exit:
+exit:
 	return err;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/dev/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/dev/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_CAN_DEV)		+= can-dev.o
+can-dev-y			+= dev.o
+can-dev-y			+= rx-offload.o
+
+can-dev-$(CONFIG_CAN_LEDS)	+= led.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/dev/dev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/dev/dev.c
@@ -0,0 +1,1314 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (C) 2005 Marc Kleine-Budde, Pengutronix
+ * Copyright (C) 2006 Andrey Volkov, Varma Electronics
+ * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/workqueue.h>
+#include <linux/can.h>
+#include <linux/can/can-ml.h>
+#include <linux/can/dev.h>
+#include <linux/can/skb.h>
+#include <linux/can/netlink.h>
+#include <linux/can/led.h>
+#include <linux/of.h>
+#include <net/rtnetlink.h>
+
+#define MOD_DESC "CAN device driver interface"
+
+MODULE_DESCRIPTION(MOD_DESC);
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
+
+/* CAN DLC to real data length conversion helpers */
+
+static const u8 dlc2len[] = {0, 1, 2, 3, 4, 5, 6, 7,
+			     8, 12, 16, 20, 24, 32, 48, 64};
+
+/* get data length from can_dlc with sanitized can_dlc */
+u8 can_dlc2len(u8 can_dlc)
+{
+	return dlc2len[can_dlc & 0x0F];
+}
+EXPORT_SYMBOL_GPL(can_dlc2len);
+
+static const u8 len2dlc[] = {0, 1, 2, 3, 4, 5, 6, 7, 8,		/* 0 - 8 */
+			     9, 9, 9, 9,			/* 9 - 12 */
+			     10, 10, 10, 10,			/* 13 - 16 */
+			     11, 11, 11, 11,			/* 17 - 20 */
+			     12, 12, 12, 12,			/* 21 - 24 */
+			     13, 13, 13, 13, 13, 13, 13, 13,	/* 25 - 32 */
+			     14, 14, 14, 14, 14, 14, 14, 14,	/* 33 - 40 */
+			     14, 14, 14, 14, 14, 14, 14, 14,	/* 41 - 48 */
+			     15, 15, 15, 15, 15, 15, 15, 15,	/* 49 - 56 */
+			     15, 15, 15, 15, 15, 15, 15, 15};	/* 57 - 64 */
+
+/* map the sanitized data length to an appropriate data length code */
+u8 can_len2dlc(u8 len)
+{
+	if (unlikely(len > 64))
+		return 0xF;
+
+	return len2dlc[len];
+}
+EXPORT_SYMBOL_GPL(can_len2dlc);
+
+#ifdef CONFIG_CAN_CALC_BITTIMING
+#define CAN_CALC_MAX_ERROR 50 /* in one-tenth of a percent */
+#define CAN_CALC_SYNC_SEG 1
+
+/* Bit-timing calculation derived from:
+ *
+ * Code based on LinCAN sources and H8S2638 project
+ * Copyright 2004-2006 Pavel Pisa - DCE FELK CVUT cz
+ * Copyright 2005      Stanislav Marek
+ * email: pisa@cmp.felk.cvut.cz
+ *
+ * Calculates proper bit-timing parameters for a specified bit-rate
+ * and sample-point, which can then be used to set the bit-timing
+ * registers of the CAN controller. You can find more information
+ * in the header file linux/can/netlink.h.
+ */
+static int
+can_update_sample_point(const struct can_bittiming_const *btc,
+			unsigned int sample_point_nominal, unsigned int tseg,
+			unsigned int *tseg1_ptr, unsigned int *tseg2_ptr,
+			unsigned int *sample_point_error_ptr)
+{
+	unsigned int sample_point_error, best_sample_point_error = UINT_MAX;
+	unsigned int sample_point, best_sample_point = 0;
+	unsigned int tseg1, tseg2;
+	int i;
+
+	for (i = 0; i <= 1; i++) {
+		tseg2 = tseg + CAN_CALC_SYNC_SEG -
+			(sample_point_nominal * (tseg + CAN_CALC_SYNC_SEG)) /
+			1000 - i;
+		tseg2 = clamp(tseg2, btc->tseg2_min, btc->tseg2_max);
+		tseg1 = tseg - tseg2;
+		if (tseg1 > btc->tseg1_max) {
+			tseg1 = btc->tseg1_max;
+			tseg2 = tseg - tseg1;
+		}
+
+		sample_point = 1000 * (tseg + CAN_CALC_SYNC_SEG - tseg2) /
+			(tseg + CAN_CALC_SYNC_SEG);
+		sample_point_error = abs(sample_point_nominal - sample_point);
+
+		if (sample_point <= sample_point_nominal &&
+		    sample_point_error < best_sample_point_error) {
+			best_sample_point = sample_point;
+			best_sample_point_error = sample_point_error;
+			*tseg1_ptr = tseg1;
+			*tseg2_ptr = tseg2;
+		}
+	}
+
+	if (sample_point_error_ptr)
+		*sample_point_error_ptr = best_sample_point_error;
+
+	return best_sample_point;
+}
+
+static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt,
+			      const struct can_bittiming_const *btc)
+{
+	struct can_priv *priv = netdev_priv(dev);
+	unsigned int bitrate;			/* current bitrate */
+	unsigned int bitrate_error;		/* difference between current and nominal value */
+	unsigned int best_bitrate_error = UINT_MAX;
+	unsigned int sample_point_error;	/* difference between current and nominal value */
+	unsigned int best_sample_point_error = UINT_MAX;
+	unsigned int sample_point_nominal;	/* nominal sample point */
+	unsigned int best_tseg = 0;		/* current best value for tseg */
+	unsigned int best_brp = 0;		/* current best value for brp */
+	unsigned int brp, tsegall, tseg, tseg1 = 0, tseg2 = 0;
+	u64 v64;
+
+	/* Use CiA recommended sample points */
+	if (bt->sample_point) {
+		sample_point_nominal = bt->sample_point;
+	} else {
+		if (bt->bitrate > 800000)
+			sample_point_nominal = 750;
+		else if (bt->bitrate > 500000)
+			sample_point_nominal = 800;
+		else
+			sample_point_nominal = 875;
+	}
+
+	/* tseg even = round down, odd = round up */
+	for (tseg = (btc->tseg1_max + btc->tseg2_max) * 2 + 1;
+	     tseg >= (btc->tseg1_min + btc->tseg2_min) * 2; tseg--) {
+		tsegall = CAN_CALC_SYNC_SEG + tseg / 2;
+
+		/* Compute all possible tseg choices (tseg=tseg1+tseg2) */
+		brp = priv->clock.freq / (tsegall * bt->bitrate) + tseg % 2;
+
+		/* choose brp step which is possible in system */
+		brp = (brp / btc->brp_inc) * btc->brp_inc;
+		if (brp < btc->brp_min || brp > btc->brp_max)
+			continue;
+
+		bitrate = priv->clock.freq / (brp * tsegall);
+		bitrate_error = abs(bt->bitrate - bitrate);
+
+		/* tseg brp biterror */
+		if (bitrate_error > best_bitrate_error)
+			continue;
+
+		/* reset sample point error if we have a better bitrate */
+		if (bitrate_error < best_bitrate_error)
+			best_sample_point_error = UINT_MAX;
+
+		can_update_sample_point(btc, sample_point_nominal, tseg / 2,
+					&tseg1, &tseg2, &sample_point_error);
+		if (sample_point_error > best_sample_point_error)
+			continue;
+
+		best_sample_point_error = sample_point_error;
+		best_bitrate_error = bitrate_error;
+		best_tseg = tseg / 2;
+		best_brp = brp;
+
+		if (bitrate_error == 0 && sample_point_error == 0)
+			break;
+	}
+
+	if (best_bitrate_error) {
+		/* Error in one-tenth of a percent */
+		v64 = (u64)best_bitrate_error * 1000;
+		do_div(v64, bt->bitrate);
+		bitrate_error = (u32)v64;
+		if (bitrate_error > CAN_CALC_MAX_ERROR) {
+			netdev_err(dev,
+				   "bitrate error %d.%d%% too high\n",
+				   bitrate_error / 10, bitrate_error % 10);
+			return -EDOM;
+		}
+		netdev_warn(dev, "bitrate error %d.%d%%\n",
+			    bitrate_error / 10, bitrate_error % 10);
+	}
+
+	/* real sample point */
+	bt->sample_point = can_update_sample_point(btc, sample_point_nominal,
+						   best_tseg, &tseg1, &tseg2,
+						   NULL);
+
+	v64 = (u64)best_brp * 1000 * 1000 * 1000;
+	do_div(v64, priv->clock.freq);
+	bt->tq = (u32)v64;
+	bt->prop_seg = tseg1 / 2;
+	bt->phase_seg1 = tseg1 - bt->prop_seg;
+	bt->phase_seg2 = tseg2;
+
+	/* check for sjw user settings */
+	if (!bt->sjw || !btc->sjw_max) {
+		bt->sjw = 1;
+	} else {
+		/* bt->sjw is at least 1 -> sanitize upper bound to sjw_max */
+		if (bt->sjw > btc->sjw_max)
+			bt->sjw = btc->sjw_max;
+		/* bt->sjw must not be higher than tseg2 */
+		if (tseg2 < bt->sjw)
+			bt->sjw = tseg2;
+	}
+
+	bt->brp = best_brp;
+
+	/* real bitrate */
+	bt->bitrate = priv->clock.freq /
+		(bt->brp * (CAN_CALC_SYNC_SEG + tseg1 + tseg2));
+
+	return 0;
+}
+#else /* !CONFIG_CAN_CALC_BITTIMING */
+static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt,
+			      const struct can_bittiming_const *btc)
+{
+	netdev_err(dev, "bit-timing calculation not available\n");
+	return -EINVAL;
+}
+#endif /* CONFIG_CAN_CALC_BITTIMING */
+
+/* Checks the validity of the specified bit-timing parameters prop_seg,
+ * phase_seg1, phase_seg2 and sjw and tries to determine the bitrate
+ * prescaler value brp. You can find more information in the header
+ * file linux/can/netlink.h.
+ */
+static int can_fixup_bittiming(struct net_device *dev, struct can_bittiming *bt,
+			       const struct can_bittiming_const *btc)
+{
+	struct can_priv *priv = netdev_priv(dev);
+	int tseg1, alltseg;
+	u64 brp64;
+
+	tseg1 = bt->prop_seg + bt->phase_seg1;
+	if (!bt->sjw)
+		bt->sjw = 1;
+	if (bt->sjw > btc->sjw_max ||
+	    tseg1 < btc->tseg1_min || tseg1 > btc->tseg1_max ||
+	    bt->phase_seg2 < btc->tseg2_min || bt->phase_seg2 > btc->tseg2_max)
+		return -ERANGE;
+
+	brp64 = (u64)priv->clock.freq * (u64)bt->tq;
+	if (btc->brp_inc > 1)
+		do_div(brp64, btc->brp_inc);
+	brp64 += 500000000UL - 1;
+	do_div(brp64, 1000000000UL); /* the practicable BRP */
+	if (btc->brp_inc > 1)
+		brp64 *= btc->brp_inc;
+	bt->brp = (u32)brp64;
+
+	if (bt->brp < btc->brp_min || bt->brp > btc->brp_max)
+		return -EINVAL;
+
+	alltseg = bt->prop_seg + bt->phase_seg1 + bt->phase_seg2 + 1;
+	bt->bitrate = priv->clock.freq / (bt->brp * alltseg);
+	bt->sample_point = ((tseg1 + 1) * 1000) / alltseg;
+
+	return 0;
+}
+
+/* Checks the validity of predefined bitrate settings */
+static int
+can_validate_bitrate(struct net_device *dev, struct can_bittiming *bt,
+		     const u32 *bitrate_const,
+		     const unsigned int bitrate_const_cnt)
+{
+	struct can_priv *priv = netdev_priv(dev);
+	unsigned int i;
+
+	for (i = 0; i < bitrate_const_cnt; i++) {
+		if (bt->bitrate == bitrate_const[i])
+			break;
+	}
+
+	if (i >= priv->bitrate_const_cnt)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int can_get_bittiming(struct net_device *dev, struct can_bittiming *bt,
+			     const struct can_bittiming_const *btc,
+			     const u32 *bitrate_const,
+			     const unsigned int bitrate_const_cnt)
+{
+	int err;
+
+	/* Depending on the given can_bittiming parameter structure the CAN
+	 * timing parameters are calculated based on the provided bitrate OR
+	 * alternatively the CAN timing parameters (tq, prop_seg, etc.) are
+	 * provided directly which are then checked and fixed up.
+	 */
+	if (!bt->tq && bt->bitrate && btc)
+		err = can_calc_bittiming(dev, bt, btc);
+	else if (bt->tq && !bt->bitrate && btc)
+		err = can_fixup_bittiming(dev, bt, btc);
+	else if (!bt->tq && bt->bitrate && bitrate_const)
+		err = can_validate_bitrate(dev, bt, bitrate_const,
+					   bitrate_const_cnt);
+	else
+		err = -EINVAL;
+
+	return err;
+}
+
+static void can_update_state_error_stats(struct net_device *dev,
+					 enum can_state new_state)
+{
+	struct can_priv *priv = netdev_priv(dev);
+
+	if (new_state <= priv->state)
+		return;
+
+	switch (new_state) {
+	case CAN_STATE_ERROR_WARNING:
+		priv->can_stats.error_warning++;
+		break;
+	case CAN_STATE_ERROR_PASSIVE:
+		priv->can_stats.error_passive++;
+		break;
+	case CAN_STATE_BUS_OFF:
+		priv->can_stats.bus_off++;
+		break;
+	default:
+		break;
+	}
+}
+
+static int can_tx_state_to_frame(struct net_device *dev, enum can_state state)
+{
+	switch (state) {
+	case CAN_STATE_ERROR_ACTIVE:
+		return CAN_ERR_CRTL_ACTIVE;
+	case CAN_STATE_ERROR_WARNING:
+		return CAN_ERR_CRTL_TX_WARNING;
+	case CAN_STATE_ERROR_PASSIVE:
+		return CAN_ERR_CRTL_TX_PASSIVE;
+	default:
+		return 0;
+	}
+}
+
+static int can_rx_state_to_frame(struct net_device *dev, enum can_state state)
+{
+	switch (state) {
+	case CAN_STATE_ERROR_ACTIVE:
+		return CAN_ERR_CRTL_ACTIVE;
+	case CAN_STATE_ERROR_WARNING:
+		return CAN_ERR_CRTL_RX_WARNING;
+	case CAN_STATE_ERROR_PASSIVE:
+		return CAN_ERR_CRTL_RX_PASSIVE;
+	default:
+		return 0;
+	}
+}
+
+void can_change_state(struct net_device *dev, struct can_frame *cf,
+		      enum can_state tx_state, enum can_state rx_state)
+{
+	struct can_priv *priv = netdev_priv(dev);
+	enum can_state new_state = max(tx_state, rx_state);
+
+	if (unlikely(new_state == priv->state)) {
+		netdev_warn(dev, "%s: oops, state did not change", __func__);
+		return;
+	}
+
+	netdev_dbg(dev, "New error state: %d\n", new_state);
+
+	can_update_state_error_stats(dev, new_state);
+	priv->state = new_state;
+
+	if (!cf)
+		return;
+
+	if (unlikely(new_state == CAN_STATE_BUS_OFF)) {
+		cf->can_id |= CAN_ERR_BUSOFF;
+		return;
+	}
+
+	cf->can_id |= CAN_ERR_CRTL;
+	cf->data[1] |= tx_state >= rx_state ?
+		       can_tx_state_to_frame(dev, tx_state) : 0;
+	cf->data[1] |= tx_state <= rx_state ?
+		       can_rx_state_to_frame(dev, rx_state) : 0;
+}
+EXPORT_SYMBOL_GPL(can_change_state);
+
+/* Local echo of CAN messages
+ *
+ * CAN network devices *should* support a local echo functionality
+ * (see Documentation/networking/can.rst). To test the handling of CAN
+ * interfaces that do not support the local echo both driver types are
+ * implemented. In the case that the driver does not support the echo
+ * the IFF_ECHO remains clear in dev->flags. This causes the PF_CAN core
+ * to perform the echo as a fallback solution.
+ */
+static void can_flush_echo_skb(struct net_device *dev)
+{
+	struct can_priv *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &dev->stats;
+	int i;
+
+	for (i = 0; i < priv->echo_skb_max; i++) {
+		if (priv->echo_skb[i]) {
+			kfree_skb(priv->echo_skb[i]);
+			priv->echo_skb[i] = NULL;
+			stats->tx_dropped++;
+			stats->tx_aborted_errors++;
+		}
+	}
+}
+
+/* Put the skb on the stack to be looped backed locally lateron
+ *
+ * The function is typically called in the start_xmit function
+ * of the device driver. The driver must protect access to
+ * priv->echo_skb, if necessary.
+ */
+void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
+		      unsigned int idx)
+{
+	struct can_priv *priv = netdev_priv(dev);
+
+	BUG_ON(idx >= priv->echo_skb_max);
+
+	/* check flag whether this packet has to be looped back */
+	if (!(dev->flags & IFF_ECHO) || skb->pkt_type != PACKET_LOOPBACK ||
+	    (skb->protocol != htons(ETH_P_CAN) &&
+	     skb->protocol != htons(ETH_P_CANFD))) {
+		kfree_skb(skb);
+		return;
+	}
+
+	if (!priv->echo_skb[idx]) {
+		skb = can_create_echo_skb(skb);
+		if (!skb)
+			return;
+
+		/* make settings for echo to reduce code in irq context */
+		skb->pkt_type = PACKET_BROADCAST;
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+		skb->dev = dev;
+
+		/* save this skb for tx interrupt echo handling */
+		priv->echo_skb[idx] = skb;
+	} else {
+		/* locking problem with netif_stop_queue() ?? */
+		netdev_err(dev, "%s: BUG! echo_skb is occupied!\n", __func__);
+		kfree_skb(skb);
+	}
+}
+EXPORT_SYMBOL_GPL(can_put_echo_skb);
+
+struct sk_buff *
+__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr)
+{
+	struct can_priv *priv = netdev_priv(dev);
+
+	if (idx >= priv->echo_skb_max) {
+		netdev_err(dev, "%s: BUG! Trying to access can_priv::echo_skb out of bounds (%u/max %u)\n",
+			   __func__, idx, priv->echo_skb_max);
+		return NULL;
+	}
+
+	if (priv->echo_skb[idx]) {
+		/* Using "struct canfd_frame::len" for the frame
+		 * length is supported on both CAN and CANFD frames.
+		 */
+		struct sk_buff *skb = priv->echo_skb[idx];
+		struct canfd_frame *cf = (struct canfd_frame *)skb->data;
+
+		/* get the real payload length for netdev statistics */
+		if (cf->can_id & CAN_RTR_FLAG)
+			*len_ptr = 0;
+		else
+			*len_ptr = cf->len;
+
+		priv->echo_skb[idx] = NULL;
+
+		return skb;
+	}
+
+	return NULL;
+}
+
+/* Get the skb from the stack and loop it back locally
+ *
+ * The function is typically called when the TX done interrupt
+ * is handled in the device driver. The driver must protect
+ * access to priv->echo_skb, if necessary.
+ */
+unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx)
+{
+	struct sk_buff *skb;
+	u8 len;
+
+	skb = __can_get_echo_skb(dev, idx, &len);
+	if (!skb)
+		return 0;
+
+	skb_get(skb);
+	if (netif_rx(skb) == NET_RX_SUCCESS)
+		dev_consume_skb_any(skb);
+	else
+		dev_kfree_skb_any(skb);
+
+	return len;
+}
+EXPORT_SYMBOL_GPL(can_get_echo_skb);
+
+/* Remove the skb from the stack and free it.
+ *
+ * The function is typically called when TX failed.
+ */
+void can_free_echo_skb(struct net_device *dev, unsigned int idx)
+{
+	struct can_priv *priv = netdev_priv(dev);
+
+	BUG_ON(idx >= priv->echo_skb_max);
+
+	if (priv->echo_skb[idx]) {
+		dev_kfree_skb_any(priv->echo_skb[idx]);
+		priv->echo_skb[idx] = NULL;
+	}
+}
+EXPORT_SYMBOL_GPL(can_free_echo_skb);
+
+/* CAN device restart for bus-off recovery */
+static void can_restart(struct net_device *dev)
+{
+	struct can_priv *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &dev->stats;
+	struct sk_buff *skb;
+	struct can_frame *cf;
+	int err;
+
+	if (netif_carrier_ok(dev))
+		netdev_err(dev, "Attempt to restart for bus-off recovery, but carrier is OK?\n");
+
+	/* No synchronization needed because the device is bus-off and
+	 * no messages can come in or go out.
+	 */
+	can_flush_echo_skb(dev);
+
+	/* send restart message upstream */
+	skb = alloc_can_err_skb(dev, &cf);
+	if (!skb) {
+		err = -ENOMEM;
+		goto restart;
+	}
+	cf->can_id |= CAN_ERR_RESTARTED;
+
+	stats->rx_packets++;
+	stats->rx_bytes += cf->can_dlc;
+
+	netif_rx_ni(skb);
+
+restart:
+	netdev_dbg(dev, "restarted\n");
+	priv->can_stats.restarts++;
+
+	/* Now restart the device */
+	netif_carrier_on(dev);
+	err = priv->do_set_mode(dev, CAN_MODE_START);
+	if (err) {
+		netdev_err(dev, "Error %d during restart", err);
+		netif_carrier_off(dev);
+	}
+}
+
+static void can_restart_work(struct work_struct *work)
+{
+	struct delayed_work *dwork = to_delayed_work(work);
+	struct can_priv *priv = container_of(dwork, struct can_priv,
+					     restart_work);
+
+	can_restart(priv->dev);
+}
+
+int can_restart_now(struct net_device *dev)
+{
+	struct can_priv *priv = netdev_priv(dev);
+
+	/* A manual restart is only permitted if automatic restart is
+	 * disabled and the device is in the bus-off state
+	 */
+	if (priv->restart_ms)
+		return -EINVAL;
+	if (priv->state != CAN_STATE_BUS_OFF)
+		return -EBUSY;
+
+	cancel_delayed_work_sync(&priv->restart_work);
+	can_restart(dev);
+
+	return 0;
+}
+
+/* CAN bus-off
+ *
+ * This functions should be called when the device goes bus-off to
+ * tell the netif layer that no more packets can be sent or received.
+ * If enabled, a timer is started to trigger bus-off recovery.
+ */
+void can_bus_off(struct net_device *dev)
+{
+	struct can_priv *priv = netdev_priv(dev);
+
+	netdev_info(dev, "bus-off\n");
+
+	netif_carrier_off(dev);
+
+	if (priv->restart_ms)
+		schedule_delayed_work(&priv->restart_work,
+				      msecs_to_jiffies(priv->restart_ms));
+}
+EXPORT_SYMBOL_GPL(can_bus_off);
+
+static void can_setup(struct net_device *dev)
+{
+	dev->type = ARPHRD_CAN;
+	dev->mtu = CAN_MTU;
+	dev->hard_header_len = 0;
+	dev->addr_len = 0;
+	dev->tx_queue_len = 10;
+
+	/* New-style flags. */
+	dev->flags = IFF_NOARP;
+	dev->features = NETIF_F_HW_CSUM;
+}
+
+struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf)
+{
+	struct sk_buff *skb;
+
+	skb = netdev_alloc_skb(dev, sizeof(struct can_skb_priv) +
+			       sizeof(struct can_frame));
+	if (unlikely(!skb))
+		return NULL;
+
+	skb->protocol = htons(ETH_P_CAN);
+	skb->pkt_type = PACKET_BROADCAST;
+	skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+	skb_reset_mac_header(skb);
+	skb_reset_network_header(skb);
+	skb_reset_transport_header(skb);
+
+	can_skb_reserve(skb);
+	can_skb_prv(skb)->ifindex = dev->ifindex;
+	can_skb_prv(skb)->skbcnt = 0;
+
+	*cf = skb_put_zero(skb, sizeof(struct can_frame));
+
+	return skb;
+}
+EXPORT_SYMBOL_GPL(alloc_can_skb);
+
+struct sk_buff *alloc_canfd_skb(struct net_device *dev,
+				struct canfd_frame **cfd)
+{
+	struct sk_buff *skb;
+
+	skb = netdev_alloc_skb(dev, sizeof(struct can_skb_priv) +
+			       sizeof(struct canfd_frame));
+	if (unlikely(!skb))
+		return NULL;
+
+	skb->protocol = htons(ETH_P_CANFD);
+	skb->pkt_type = PACKET_BROADCAST;
+	skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+	skb_reset_mac_header(skb);
+	skb_reset_network_header(skb);
+	skb_reset_transport_header(skb);
+
+	can_skb_reserve(skb);
+	can_skb_prv(skb)->ifindex = dev->ifindex;
+	can_skb_prv(skb)->skbcnt = 0;
+
+	*cfd = skb_put_zero(skb, sizeof(struct canfd_frame));
+
+	return skb;
+}
+EXPORT_SYMBOL_GPL(alloc_canfd_skb);
+
+struct sk_buff *alloc_can_err_skb(struct net_device *dev, struct can_frame **cf)
+{
+	struct sk_buff *skb;
+
+	skb = alloc_can_skb(dev, cf);
+	if (unlikely(!skb))
+		return NULL;
+
+	(*cf)->can_id = CAN_ERR_FLAG;
+	(*cf)->can_dlc = CAN_ERR_DLC;
+
+	return skb;
+}
+EXPORT_SYMBOL_GPL(alloc_can_err_skb);
+
+/* Allocate and setup space for the CAN network device */
+struct net_device *alloc_candev_mqs(int sizeof_priv, unsigned int echo_skb_max,
+				    unsigned int txqs, unsigned int rxqs)
+{
+	struct can_ml_priv *can_ml;
+	struct net_device *dev;
+	struct can_priv *priv;
+	int size;
+
+	/* We put the driver's priv, the CAN mid layer priv and the
+	 * echo skb into the netdevice's priv. The memory layout for
+	 * the netdev_priv is like this:
+	 *
+	 * +-------------------------+
+	 * | driver's priv           |
+	 * +-------------------------+
+	 * | struct can_ml_priv      |
+	 * +-------------------------+
+	 * | array of struct sk_buff |
+	 * +-------------------------+
+	 */
+
+	size = ALIGN(sizeof_priv, NETDEV_ALIGN) + sizeof(struct can_ml_priv);
+
+	if (echo_skb_max)
+		size = ALIGN(size, sizeof(struct sk_buff *)) +
+			echo_skb_max * sizeof(struct sk_buff *);
+
+	dev = alloc_netdev_mqs(size, "can%d", NET_NAME_UNKNOWN, can_setup,
+			       txqs, rxqs);
+	if (!dev)
+		return NULL;
+
+	priv = netdev_priv(dev);
+	priv->dev = dev;
+
+	can_ml = (void *)priv + ALIGN(sizeof_priv, NETDEV_ALIGN);
+	can_set_ml_priv(dev, can_ml);
+
+	if (echo_skb_max) {
+		priv->echo_skb_max = echo_skb_max;
+		priv->echo_skb = (void *)priv +
+			(size - echo_skb_max * sizeof(struct sk_buff *));
+	}
+
+	priv->state = CAN_STATE_STOPPED;
+
+	INIT_DELAYED_WORK(&priv->restart_work, can_restart_work);
+
+	return dev;
+}
+EXPORT_SYMBOL_GPL(alloc_candev_mqs);
+
+/* Free space of the CAN network device */
+void free_candev(struct net_device *dev)
+{
+	free_netdev(dev);
+}
+EXPORT_SYMBOL_GPL(free_candev);
+
+/* changing MTU and control mode for CAN/CANFD devices */
+int can_change_mtu(struct net_device *dev, int new_mtu)
+{
+	struct can_priv *priv = netdev_priv(dev);
+
+	/* Do not allow changing the MTU while running */
+	if (dev->flags & IFF_UP)
+		return -EBUSY;
+
+	/* allow change of MTU according to the CANFD ability of the device */
+	switch (new_mtu) {
+	case CAN_MTU:
+		/* 'CANFD-only' controllers can not switch to CAN_MTU */
+		if (priv->ctrlmode_static & CAN_CTRLMODE_FD)
+			return -EINVAL;
+
+		priv->ctrlmode &= ~CAN_CTRLMODE_FD;
+		break;
+
+	case CANFD_MTU:
+		/* check for potential CANFD ability */
+		if (!(priv->ctrlmode_supported & CAN_CTRLMODE_FD) &&
+		    !(priv->ctrlmode_static & CAN_CTRLMODE_FD))
+			return -EINVAL;
+
+		priv->ctrlmode |= CAN_CTRLMODE_FD;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	dev->mtu = new_mtu;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(can_change_mtu);
+
+/* Common open function when the device gets opened.
+ *
+ * This function should be called in the open function of the device
+ * driver.
+ */
+int open_candev(struct net_device *dev)
+{
+	struct can_priv *priv = netdev_priv(dev);
+
+	if (!priv->bittiming.bitrate) {
+		netdev_err(dev, "bit-timing not yet defined\n");
+		return -EINVAL;
+	}
+
+	/* For CAN FD the data bitrate has to be >= the arbitration bitrate */
+	if ((priv->ctrlmode & CAN_CTRLMODE_FD) &&
+	    (!priv->data_bittiming.bitrate ||
+	     priv->data_bittiming.bitrate < priv->bittiming.bitrate)) {
+		netdev_err(dev, "incorrect/missing data bit-timing\n");
+		return -EINVAL;
+	}
+
+	/* Switch carrier on if device was stopped while in bus-off state */
+	if (!netif_carrier_ok(dev))
+		netif_carrier_on(dev);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(open_candev);
+
+#ifdef CONFIG_OF
+/* Common function that can be used to understand the limitation of
+ * a transceiver when it provides no means to determine these limitations
+ * at runtime.
+ */
+void of_can_transceiver(struct net_device *dev)
+{
+	struct device_node *dn;
+	struct can_priv *priv = netdev_priv(dev);
+	struct device_node *np = dev->dev.parent->of_node;
+	int ret;
+
+	dn = of_get_child_by_name(np, "can-transceiver");
+	if (!dn)
+		return;
+
+	ret = of_property_read_u32(dn, "max-bitrate", &priv->bitrate_max);
+	of_node_put(dn);
+	if ((ret && ret != -EINVAL) || (!ret && !priv->bitrate_max))
+		netdev_warn(dev, "Invalid value for transceiver max bitrate. Ignoring bitrate limit.\n");
+}
+EXPORT_SYMBOL_GPL(of_can_transceiver);
+#endif
+
+/* Common close function for cleanup before the device gets closed.
+ *
+ * This function should be called in the close function of the device
+ * driver.
+ */
+void close_candev(struct net_device *dev)
+{
+	struct can_priv *priv = netdev_priv(dev);
+
+	cancel_delayed_work_sync(&priv->restart_work);
+	can_flush_echo_skb(dev);
+}
+EXPORT_SYMBOL_GPL(close_candev);
+
+/* CAN netlink interface */
+static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = {
+	[IFLA_CAN_STATE]	= { .type = NLA_U32 },
+	[IFLA_CAN_CTRLMODE]	= { .len = sizeof(struct can_ctrlmode) },
+	[IFLA_CAN_RESTART_MS]	= { .type = NLA_U32 },
+	[IFLA_CAN_RESTART]	= { .type = NLA_U32 },
+	[IFLA_CAN_BITTIMING]	= { .len = sizeof(struct can_bittiming) },
+	[IFLA_CAN_BITTIMING_CONST]
+				= { .len = sizeof(struct can_bittiming_const) },
+	[IFLA_CAN_CLOCK]	= { .len = sizeof(struct can_clock) },
+	[IFLA_CAN_BERR_COUNTER]	= { .len = sizeof(struct can_berr_counter) },
+	[IFLA_CAN_DATA_BITTIMING]
+				= { .len = sizeof(struct can_bittiming) },
+	[IFLA_CAN_DATA_BITTIMING_CONST]
+				= { .len = sizeof(struct can_bittiming_const) },
+	[IFLA_CAN_TERMINATION]	= { .type = NLA_U16 },
+};
+
+static int can_validate(struct nlattr *tb[], struct nlattr *data[],
+			struct netlink_ext_ack *extack)
+{
+	bool is_can_fd = false;
+
+	/* Make sure that valid CAN FD configurations always consist of
+	 * - nominal/arbitration bittiming
+	 * - data bittiming
+	 * - control mode with CAN_CTRLMODE_FD set
+	 */
+
+	if (!data)
+		return 0;
+
+	if (data[IFLA_CAN_CTRLMODE]) {
+		struct can_ctrlmode *cm = nla_data(data[IFLA_CAN_CTRLMODE]);
+
+		is_can_fd = cm->flags & cm->mask & CAN_CTRLMODE_FD;
+	}
+
+	if (is_can_fd) {
+		if (!data[IFLA_CAN_BITTIMING] || !data[IFLA_CAN_DATA_BITTIMING])
+			return -EOPNOTSUPP;
+	}
+
+	if (data[IFLA_CAN_DATA_BITTIMING]) {
+		if (!is_can_fd || !data[IFLA_CAN_BITTIMING])
+			return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+static int can_changelink(struct net_device *dev, struct nlattr *tb[],
+			  struct nlattr *data[],
+			  struct netlink_ext_ack *extack)
+{
+	struct can_priv *priv = netdev_priv(dev);
+	int err;
+
+	/* We need synchronization with dev->stop() */
+	ASSERT_RTNL();
+
+	if (data[IFLA_CAN_BITTIMING]) {
+		struct can_bittiming bt;
+
+		/* Do not allow changing bittiming while running */
+		if (dev->flags & IFF_UP)
+			return -EBUSY;
+
+		/* Calculate bittiming parameters based on
+		 * bittiming_const if set, otherwise pass bitrate
+		 * directly via do_set_bitrate(). Bail out if neither
+		 * is given.
+		 */
+		if (!priv->bittiming_const && !priv->do_set_bittiming)
+			return -EOPNOTSUPP;
+
+		memcpy(&bt, nla_data(data[IFLA_CAN_BITTIMING]), sizeof(bt));
+		err = can_get_bittiming(dev, &bt,
+					priv->bittiming_const,
+					priv->bitrate_const,
+					priv->bitrate_const_cnt);
+		if (err)
+			return err;
+
+		if (priv->bitrate_max && bt.bitrate > priv->bitrate_max) {
+			netdev_err(dev, "arbitration bitrate surpasses transceiver capabilities of %d bps\n",
+				   priv->bitrate_max);
+			return -EINVAL;
+		}
+
+		memcpy(&priv->bittiming, &bt, sizeof(bt));
+
+		if (priv->do_set_bittiming) {
+			/* Finally, set the bit-timing registers */
+			err = priv->do_set_bittiming(dev);
+			if (err)
+				return err;
+		}
+	}
+
+	if (data[IFLA_CAN_CTRLMODE]) {
+		struct can_ctrlmode *cm;
+		u32 ctrlstatic;
+		u32 maskedflags;
+
+		/* Do not allow changing controller mode while running */
+		if (dev->flags & IFF_UP)
+			return -EBUSY;
+		cm = nla_data(data[IFLA_CAN_CTRLMODE]);
+		ctrlstatic = priv->ctrlmode_static;
+		maskedflags = cm->flags & cm->mask;
+
+		/* check whether provided bits are allowed to be passed */
+		if (cm->mask & ~(priv->ctrlmode_supported | ctrlstatic))
+			return -EOPNOTSUPP;
+
+		/* do not check for static fd-non-iso if 'fd' is disabled */
+		if (!(maskedflags & CAN_CTRLMODE_FD))
+			ctrlstatic &= ~CAN_CTRLMODE_FD_NON_ISO;
+
+		/* make sure static options are provided by configuration */
+		if ((maskedflags & ctrlstatic) != ctrlstatic)
+			return -EOPNOTSUPP;
+
+		/* clear bits to be modified and copy the flag values */
+		priv->ctrlmode &= ~cm->mask;
+		priv->ctrlmode |= maskedflags;
+
+		/* CAN_CTRLMODE_FD can only be set when driver supports FD */
+		if (priv->ctrlmode & CAN_CTRLMODE_FD)
+			dev->mtu = CANFD_MTU;
+		else
+			dev->mtu = CAN_MTU;
+	}
+
+	if (data[IFLA_CAN_RESTART_MS]) {
+		/* Do not allow changing restart delay while running */
+		if (dev->flags & IFF_UP)
+			return -EBUSY;
+		priv->restart_ms = nla_get_u32(data[IFLA_CAN_RESTART_MS]);
+	}
+
+	if (data[IFLA_CAN_RESTART]) {
+		/* Do not allow a restart while not running */
+		if (!(dev->flags & IFF_UP))
+			return -EINVAL;
+		err = can_restart_now(dev);
+		if (err)
+			return err;
+	}
+
+	if (data[IFLA_CAN_DATA_BITTIMING]) {
+		struct can_bittiming dbt;
+
+		/* Do not allow changing bittiming while running */
+		if (dev->flags & IFF_UP)
+			return -EBUSY;
+
+		/* Calculate bittiming parameters based on
+		 * data_bittiming_const if set, otherwise pass bitrate
+		 * directly via do_set_bitrate(). Bail out if neither
+		 * is given.
+		 */
+		if (!priv->data_bittiming_const && !priv->do_set_data_bittiming)
+			return -EOPNOTSUPP;
+
+		memcpy(&dbt, nla_data(data[IFLA_CAN_DATA_BITTIMING]),
+		       sizeof(dbt));
+		err = can_get_bittiming(dev, &dbt,
+					priv->data_bittiming_const,
+					priv->data_bitrate_const,
+					priv->data_bitrate_const_cnt);
+		if (err)
+			return err;
+
+		if (priv->bitrate_max && dbt.bitrate > priv->bitrate_max) {
+			netdev_err(dev, "canfd data bitrate surpasses transceiver capabilities of %d bps\n",
+				   priv->bitrate_max);
+			return -EINVAL;
+		}
+
+		memcpy(&priv->data_bittiming, &dbt, sizeof(dbt));
+
+		if (priv->do_set_data_bittiming) {
+			/* Finally, set the bit-timing registers */
+			err = priv->do_set_data_bittiming(dev);
+			if (err)
+				return err;
+		}
+	}
+
+	if (data[IFLA_CAN_TERMINATION]) {
+		const u16 termval = nla_get_u16(data[IFLA_CAN_TERMINATION]);
+		const unsigned int num_term = priv->termination_const_cnt;
+		unsigned int i;
+
+		if (!priv->do_set_termination)
+			return -EOPNOTSUPP;
+
+		/* check whether given value is supported by the interface */
+		for (i = 0; i < num_term; i++) {
+			if (termval == priv->termination_const[i])
+				break;
+		}
+		if (i >= num_term)
+			return -EINVAL;
+
+		/* Finally, set the termination value */
+		err = priv->do_set_termination(dev, termval);
+		if (err)
+			return err;
+
+		priv->termination = termval;
+	}
+
+	return 0;
+}
+
+static size_t can_get_size(const struct net_device *dev)
+{
+	struct can_priv *priv = netdev_priv(dev);
+	size_t size = 0;
+
+	if (priv->bittiming.bitrate)				/* IFLA_CAN_BITTIMING */
+		size += nla_total_size(sizeof(struct can_bittiming));
+	if (priv->bittiming_const)				/* IFLA_CAN_BITTIMING_CONST */
+		size += nla_total_size(sizeof(struct can_bittiming_const));
+	size += nla_total_size(sizeof(struct can_clock));	/* IFLA_CAN_CLOCK */
+	size += nla_total_size(sizeof(u32));			/* IFLA_CAN_STATE */
+	size += nla_total_size(sizeof(struct can_ctrlmode));	/* IFLA_CAN_CTRLMODE */
+	size += nla_total_size(sizeof(u32));			/* IFLA_CAN_RESTART_MS */
+	if (priv->do_get_berr_counter)				/* IFLA_CAN_BERR_COUNTER */
+		size += nla_total_size(sizeof(struct can_berr_counter));
+	if (priv->data_bittiming.bitrate)			/* IFLA_CAN_DATA_BITTIMING */
+		size += nla_total_size(sizeof(struct can_bittiming));
+	if (priv->data_bittiming_const)				/* IFLA_CAN_DATA_BITTIMING_CONST */
+		size += nla_total_size(sizeof(struct can_bittiming_const));
+	if (priv->termination_const) {
+		size += nla_total_size(sizeof(priv->termination));		/* IFLA_CAN_TERMINATION */
+		size += nla_total_size(sizeof(*priv->termination_const) *	/* IFLA_CAN_TERMINATION_CONST */
+				       priv->termination_const_cnt);
+	}
+	if (priv->bitrate_const)				/* IFLA_CAN_BITRATE_CONST */
+		size += nla_total_size(sizeof(*priv->bitrate_const) *
+				       priv->bitrate_const_cnt);
+	if (priv->data_bitrate_const)				/* IFLA_CAN_DATA_BITRATE_CONST */
+		size += nla_total_size(sizeof(*priv->data_bitrate_const) *
+				       priv->data_bitrate_const_cnt);
+	size += sizeof(priv->bitrate_max);			/* IFLA_CAN_BITRATE_MAX */
+
+	return size;
+}
+
+static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
+{
+	struct can_priv *priv = netdev_priv(dev);
+	struct can_ctrlmode cm = {.flags = priv->ctrlmode};
+	struct can_berr_counter bec = { };
+	enum can_state state = priv->state;
+
+	if (priv->do_get_state)
+		priv->do_get_state(dev, &state);
+
+	if ((priv->bittiming.bitrate &&
+	     nla_put(skb, IFLA_CAN_BITTIMING,
+		     sizeof(priv->bittiming), &priv->bittiming)) ||
+
+	    (priv->bittiming_const &&
+	     nla_put(skb, IFLA_CAN_BITTIMING_CONST,
+		     sizeof(*priv->bittiming_const), priv->bittiming_const)) ||
+
+	    nla_put(skb, IFLA_CAN_CLOCK, sizeof(priv->clock), &priv->clock) ||
+	    nla_put_u32(skb, IFLA_CAN_STATE, state) ||
+	    nla_put(skb, IFLA_CAN_CTRLMODE, sizeof(cm), &cm) ||
+	    nla_put_u32(skb, IFLA_CAN_RESTART_MS, priv->restart_ms) ||
+
+	    (priv->do_get_berr_counter &&
+	     !priv->do_get_berr_counter(dev, &bec) &&
+	     nla_put(skb, IFLA_CAN_BERR_COUNTER, sizeof(bec), &bec)) ||
+
+	    (priv->data_bittiming.bitrate &&
+	     nla_put(skb, IFLA_CAN_DATA_BITTIMING,
+		     sizeof(priv->data_bittiming), &priv->data_bittiming)) ||
+
+	    (priv->data_bittiming_const &&
+	     nla_put(skb, IFLA_CAN_DATA_BITTIMING_CONST,
+		     sizeof(*priv->data_bittiming_const),
+		     priv->data_bittiming_const)) ||
+
+	    (priv->termination_const &&
+	     (nla_put_u16(skb, IFLA_CAN_TERMINATION, priv->termination) ||
+	      nla_put(skb, IFLA_CAN_TERMINATION_CONST,
+		      sizeof(*priv->termination_const) *
+		      priv->termination_const_cnt,
+		      priv->termination_const))) ||
+
+	    (priv->bitrate_const &&
+	     nla_put(skb, IFLA_CAN_BITRATE_CONST,
+		     sizeof(*priv->bitrate_const) *
+		     priv->bitrate_const_cnt,
+		     priv->bitrate_const)) ||
+
+	    (priv->data_bitrate_const &&
+	     nla_put(skb, IFLA_CAN_DATA_BITRATE_CONST,
+		     sizeof(*priv->data_bitrate_const) *
+		     priv->data_bitrate_const_cnt,
+		     priv->data_bitrate_const)) ||
+
+	    (nla_put(skb, IFLA_CAN_BITRATE_MAX,
+		     sizeof(priv->bitrate_max),
+		     &priv->bitrate_max))
+	    )
+
+		return -EMSGSIZE;
+
+	return 0;
+}
+
+static size_t can_get_xstats_size(const struct net_device *dev)
+{
+	return sizeof(struct can_device_stats);
+}
+
+static int can_fill_xstats(struct sk_buff *skb, const struct net_device *dev)
+{
+	struct can_priv *priv = netdev_priv(dev);
+
+	if (nla_put(skb, IFLA_INFO_XSTATS,
+		    sizeof(priv->can_stats), &priv->can_stats))
+		goto nla_put_failure;
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+
+static int can_newlink(struct net *src_net, struct net_device *dev,
+		       struct nlattr *tb[], struct nlattr *data[],
+		       struct netlink_ext_ack *extack)
+{
+	return -EOPNOTSUPP;
+}
+
+static void can_dellink(struct net_device *dev, struct list_head *head)
+{
+}
+
+static struct rtnl_link_ops can_link_ops __read_mostly = {
+	.kind		= "can",
+	.netns_refund	= true,
+	.maxtype	= IFLA_CAN_MAX,
+	.policy		= can_policy,
+	.setup		= can_setup,
+	.validate	= can_validate,
+	.newlink	= can_newlink,
+	.changelink	= can_changelink,
+	.dellink	= can_dellink,
+	.get_size	= can_get_size,
+	.fill_info	= can_fill_info,
+	.get_xstats_size = can_get_xstats_size,
+	.fill_xstats	= can_fill_xstats,
+};
+
+/* Register the CAN network device */
+int register_candev(struct net_device *dev)
+{
+	struct can_priv *priv = netdev_priv(dev);
+
+	/* Ensure termination_const, termination_const_cnt and
+	 * do_set_termination consistency. All must be either set or
+	 * unset.
+	 */
+	if ((!priv->termination_const != !priv->termination_const_cnt) ||
+	    (!priv->termination_const != !priv->do_set_termination))
+		return -EINVAL;
+
+	if (!priv->bitrate_const != !priv->bitrate_const_cnt)
+		return -EINVAL;
+
+	if (!priv->data_bitrate_const != !priv->data_bitrate_const_cnt)
+		return -EINVAL;
+
+	dev->rtnl_link_ops = &can_link_ops;
+	netif_carrier_off(dev);
+
+	return register_netdev(dev);
+}
+EXPORT_SYMBOL_GPL(register_candev);
+
+/* Unregister the CAN network device */
+void unregister_candev(struct net_device *dev)
+{
+	unregister_netdev(dev);
+}
+EXPORT_SYMBOL_GPL(unregister_candev);
+
+/* Test if a network device is a candev based device
+ * and return the can_priv* if so.
+ */
+struct can_priv *safe_candev_priv(struct net_device *dev)
+{
+	if (dev->type != ARPHRD_CAN || dev->rtnl_link_ops != &can_link_ops)
+		return NULL;
+
+	return netdev_priv(dev);
+}
+EXPORT_SYMBOL_GPL(safe_candev_priv);
+
+static __init int can_dev_init(void)
+{
+	int err;
+
+	can_led_notifier_init();
+
+	err = rtnl_link_register(&can_link_ops);
+	if (!err)
+		pr_info(MOD_DESC "\n");
+
+	return err;
+}
+module_init(can_dev_init);
+
+static __exit void can_dev_exit(void)
+{
+	rtnl_link_unregister(&can_link_ops);
+
+	can_led_notifier_exit();
+}
+module_exit(can_dev_exit);
+
+MODULE_ALIAS_RTNL_LINK("can");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/dev/rx-offload.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/dev/rx-offload.c
@@ -0,0 +1,395 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2014 David Jander, Protonic Holland
+ * Copyright (C) 2014-2017 Pengutronix, Marc Kleine-Budde <kernel@pengutronix.de>
+ */
+
+#include <linux/can/dev.h>
+#include <linux/can/rx-offload.h>
+
+struct can_rx_offload_cb {
+	u32 timestamp;
+};
+
+static inline struct can_rx_offload_cb *can_rx_offload_get_cb(struct sk_buff *skb)
+{
+	BUILD_BUG_ON(sizeof(struct can_rx_offload_cb) > sizeof(skb->cb));
+
+	return (struct can_rx_offload_cb *)skb->cb;
+}
+
+static inline bool can_rx_offload_le(struct can_rx_offload *offload, unsigned int a, unsigned int b)
+{
+	if (offload->inc)
+		return a <= b;
+	else
+		return a >= b;
+}
+
+static inline unsigned int can_rx_offload_inc(struct can_rx_offload *offload, unsigned int *val)
+{
+	if (offload->inc)
+		return (*val)++;
+	else
+		return (*val)--;
+}
+
+static int can_rx_offload_napi_poll(struct napi_struct *napi, int quota)
+{
+	struct can_rx_offload *offload = container_of(napi, struct can_rx_offload, napi);
+	struct net_device *dev = offload->dev;
+	struct net_device_stats *stats = &dev->stats;
+	struct sk_buff *skb;
+	int work_done = 0;
+
+	while ((work_done < quota) &&
+	       (skb = skb_dequeue(&offload->skb_queue))) {
+		struct can_frame *cf = (struct can_frame *)skb->data;
+
+		work_done++;
+		stats->rx_packets++;
+		stats->rx_bytes += cf->can_dlc;
+		netif_receive_skb(skb);
+	}
+
+	if (work_done < quota) {
+		napi_complete_done(napi, work_done);
+
+		/* Check if there was another interrupt */
+		if (!skb_queue_empty(&offload->skb_queue))
+			napi_reschedule(&offload->napi);
+	}
+
+	can_led_event(offload->dev, CAN_LED_EVENT_RX);
+
+	return work_done;
+}
+
+static inline void __skb_queue_add_sort(struct sk_buff_head *head, struct sk_buff *new,
+					int (*compare)(struct sk_buff *a, struct sk_buff *b))
+{
+	struct sk_buff *pos, *insert = NULL;
+
+	skb_queue_reverse_walk(head, pos) {
+		const struct can_rx_offload_cb *cb_pos, *cb_new;
+
+		cb_pos = can_rx_offload_get_cb(pos);
+		cb_new = can_rx_offload_get_cb(new);
+
+		netdev_dbg(new->dev,
+			   "%s: pos=0x%08x, new=0x%08x, diff=%10d, queue_len=%d\n",
+			   __func__,
+			   cb_pos->timestamp, cb_new->timestamp,
+			   cb_new->timestamp - cb_pos->timestamp,
+			   skb_queue_len(head));
+
+		if (compare(pos, new) < 0)
+			continue;
+		insert = pos;
+		break;
+	}
+	if (!insert)
+		__skb_queue_head(head, new);
+	else
+		__skb_queue_after(head, insert, new);
+}
+
+static int can_rx_offload_compare(struct sk_buff *a, struct sk_buff *b)
+{
+	const struct can_rx_offload_cb *cb_a, *cb_b;
+
+	cb_a = can_rx_offload_get_cb(a);
+	cb_b = can_rx_offload_get_cb(b);
+
+	/* Substract two u32 and return result as int, to keep
+	 * difference steady around the u32 overflow.
+	 */
+	return cb_b->timestamp - cb_a->timestamp;
+}
+
+/**
+ * can_rx_offload_offload_one() - Read one CAN frame from HW
+ * @offload: pointer to rx_offload context
+ * @n: number of mailbox to read
+ *
+ * The task of this function is to read a CAN frame from mailbox @n
+ * from the device and return the mailbox's content as a struct
+ * sk_buff.
+ *
+ * If the struct can_rx_offload::skb_queue exceeds the maximal queue
+ * length (struct can_rx_offload::skb_queue_len_max) or no skb can be
+ * allocated, the mailbox contents is discarded by reading it into an
+ * overflow buffer. This way the mailbox is marked as free by the
+ * driver.
+ *
+ * Return: A pointer to skb containing the CAN frame on success.
+ *
+ *         NULL if the mailbox @n is empty.
+ *
+ *         ERR_PTR() in case of an error
+ */
+static struct sk_buff *
+can_rx_offload_offload_one(struct can_rx_offload *offload, unsigned int n)
+{
+	struct sk_buff *skb = NULL, *skb_error = NULL;
+	struct can_rx_offload_cb *cb;
+	struct can_frame *cf;
+	int ret;
+
+	if (likely(skb_queue_len(&offload->skb_queue) <
+		   offload->skb_queue_len_max)) {
+		skb = alloc_can_skb(offload->dev, &cf);
+		if (unlikely(!skb))
+			skb_error = ERR_PTR(-ENOMEM);	/* skb alloc failed */
+	} else {
+		skb_error = ERR_PTR(-ENOBUFS);		/* skb_queue is full */
+	}
+
+	/* If queue is full or skb not available, drop by reading into
+	 * overflow buffer.
+	 */
+	if (unlikely(skb_error)) {
+		struct can_frame cf_overflow;
+		u32 timestamp;
+
+		ret = offload->mailbox_read(offload, &cf_overflow,
+					    &timestamp, n);
+
+		/* Mailbox was empty. */
+		if (unlikely(!ret))
+			return NULL;
+
+		/* Mailbox has been read and we're dropping it or
+		 * there was a problem reading the mailbox.
+		 *
+		 * Increment error counters in any case.
+		 */
+		offload->dev->stats.rx_dropped++;
+		offload->dev->stats.rx_fifo_errors++;
+
+		/* There was a problem reading the mailbox, propagate
+		 * error value.
+		 */
+		if (unlikely(ret < 0))
+			return ERR_PTR(ret);
+
+		return skb_error;
+	}
+
+	cb = can_rx_offload_get_cb(skb);
+	ret = offload->mailbox_read(offload, cf, &cb->timestamp, n);
+
+	/* Mailbox was empty. */
+	if (unlikely(!ret)) {
+		kfree_skb(skb);
+		return NULL;
+	}
+
+	/* There was a problem reading the mailbox, propagate error value. */
+	if (unlikely(ret < 0)) {
+		kfree_skb(skb);
+
+		offload->dev->stats.rx_dropped++;
+		offload->dev->stats.rx_fifo_errors++;
+
+		return ERR_PTR(ret);
+	}
+
+	/* Mailbox was read. */
+	return skb;
+}
+
+int can_rx_offload_irq_offload_timestamp(struct can_rx_offload *offload, u64 pending)
+{
+	struct sk_buff_head skb_queue;
+	unsigned int i;
+
+	__skb_queue_head_init(&skb_queue);
+
+	for (i = offload->mb_first;
+	     can_rx_offload_le(offload, i, offload->mb_last);
+	     can_rx_offload_inc(offload, &i)) {
+		struct sk_buff *skb;
+
+		if (!(pending & BIT_ULL(i)))
+			continue;
+
+		skb = can_rx_offload_offload_one(offload, i);
+		if (IS_ERR_OR_NULL(skb))
+			continue;
+
+		__skb_queue_add_sort(&skb_queue, skb, can_rx_offload_compare);
+	}
+
+	if (!skb_queue_empty(&skb_queue)) {
+		unsigned long flags;
+		u32 queue_len;
+
+		spin_lock_irqsave(&offload->skb_queue.lock, flags);
+		skb_queue_splice_tail(&skb_queue, &offload->skb_queue);
+		spin_unlock_irqrestore(&offload->skb_queue.lock, flags);
+
+		if ((queue_len = skb_queue_len(&offload->skb_queue)) >
+		    (offload->skb_queue_len_max / 8))
+			netdev_dbg(offload->dev, "%s: queue_len=%d\n",
+				   __func__, queue_len);
+
+		can_rx_offload_schedule(offload);
+	}
+
+	return skb_queue_len(&skb_queue);
+}
+EXPORT_SYMBOL_GPL(can_rx_offload_irq_offload_timestamp);
+
+int can_rx_offload_irq_offload_fifo(struct can_rx_offload *offload)
+{
+	struct sk_buff *skb;
+	int received = 0;
+
+	while (1) {
+		skb = can_rx_offload_offload_one(offload, 0);
+		if (IS_ERR(skb))
+			continue;
+		if (!skb)
+			break;
+
+		skb_queue_tail(&offload->skb_queue, skb);
+		received++;
+	}
+
+	if (received)
+		can_rx_offload_schedule(offload);
+
+	return received;
+}
+EXPORT_SYMBOL_GPL(can_rx_offload_irq_offload_fifo);
+
+int can_rx_offload_queue_sorted(struct can_rx_offload *offload,
+				struct sk_buff *skb, u32 timestamp)
+{
+	struct can_rx_offload_cb *cb;
+	unsigned long flags;
+
+	if (skb_queue_len(&offload->skb_queue) >
+	    offload->skb_queue_len_max) {
+		dev_kfree_skb_any(skb);
+		return -ENOBUFS;
+	}
+
+	cb = can_rx_offload_get_cb(skb);
+	cb->timestamp = timestamp;
+
+	spin_lock_irqsave(&offload->skb_queue.lock, flags);
+	__skb_queue_add_sort(&offload->skb_queue, skb, can_rx_offload_compare);
+	spin_unlock_irqrestore(&offload->skb_queue.lock, flags);
+
+	can_rx_offload_schedule(offload);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(can_rx_offload_queue_sorted);
+
+unsigned int can_rx_offload_get_echo_skb(struct can_rx_offload *offload,
+					 unsigned int idx, u32 timestamp)
+{
+	struct net_device *dev = offload->dev;
+	struct net_device_stats *stats = &dev->stats;
+	struct sk_buff *skb;
+	u8 len;
+	int err;
+
+	skb = __can_get_echo_skb(dev, idx, &len);
+	if (!skb)
+		return 0;
+
+	err = can_rx_offload_queue_sorted(offload, skb, timestamp);
+	if (err) {
+		stats->rx_errors++;
+		stats->tx_fifo_errors++;
+	}
+
+	return len;
+}
+EXPORT_SYMBOL_GPL(can_rx_offload_get_echo_skb);
+
+int can_rx_offload_queue_tail(struct can_rx_offload *offload,
+			      struct sk_buff *skb)
+{
+	if (skb_queue_len(&offload->skb_queue) >
+	    offload->skb_queue_len_max) {
+		dev_kfree_skb_any(skb);
+		return -ENOBUFS;
+	}
+
+	skb_queue_tail(&offload->skb_queue, skb);
+	can_rx_offload_schedule(offload);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(can_rx_offload_queue_tail);
+
+static int can_rx_offload_init_queue(struct net_device *dev, struct can_rx_offload *offload, unsigned int weight)
+{
+	offload->dev = dev;
+
+	/* Limit queue len to 4x the weight (rounted to next power of two) */
+	offload->skb_queue_len_max = 2 << fls(weight);
+	offload->skb_queue_len_max *= 4;
+	skb_queue_head_init(&offload->skb_queue);
+
+	can_rx_offload_reset(offload);
+	netif_napi_add(dev, &offload->napi, can_rx_offload_napi_poll, weight);
+
+	dev_dbg(dev->dev.parent, "%s: skb_queue_len_max=%d\n",
+		__func__, offload->skb_queue_len_max);
+
+	return 0;
+}
+
+int can_rx_offload_add_timestamp(struct net_device *dev, struct can_rx_offload *offload)
+{
+	unsigned int weight;
+
+	if (offload->mb_first > BITS_PER_LONG_LONG ||
+	    offload->mb_last > BITS_PER_LONG_LONG || !offload->mailbox_read)
+		return -EINVAL;
+
+	if (offload->mb_first < offload->mb_last) {
+		offload->inc = true;
+		weight = offload->mb_last - offload->mb_first;
+	} else {
+		offload->inc = false;
+		weight = offload->mb_first - offload->mb_last;
+	}
+
+	return can_rx_offload_init_queue(dev, offload, weight);
+}
+EXPORT_SYMBOL_GPL(can_rx_offload_add_timestamp);
+
+int can_rx_offload_add_fifo(struct net_device *dev, struct can_rx_offload *offload, unsigned int weight)
+{
+	if (!offload->mailbox_read)
+		return -EINVAL;
+
+	return can_rx_offload_init_queue(dev, offload, weight);
+}
+EXPORT_SYMBOL_GPL(can_rx_offload_add_fifo);
+
+void can_rx_offload_enable(struct can_rx_offload *offload)
+{
+	can_rx_offload_reset(offload);
+	napi_enable(&offload->napi);
+}
+EXPORT_SYMBOL_GPL(can_rx_offload_enable);
+
+void can_rx_offload_del(struct can_rx_offload *offload)
+{
+	netif_napi_del(&offload->napi);
+	skb_queue_purge(&offload->skb_queue);
+}
+EXPORT_SYMBOL_GPL(can_rx_offload_del);
+
+void can_rx_offload_reset(struct can_rx_offload *offload)
+{
+}
+EXPORT_SYMBOL_GPL(can_rx_offload_reset);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/flexcan.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/flexcan.c
@@ -321,8 +321,7 @@
 
 static const struct flexcan_devtype_data fsl_ls1021a_r2_devtype_data = {
 	.quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
-		FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_BROKEN_PERR_STATE |
-		FLEXCAN_QUIRK_USE_OFF_TIMESTAMP,
+		FLEXCAN_QUIRK_BROKEN_PERR_STATE | FLEXCAN_QUIRK_USE_OFF_TIMESTAMP,
 };
 
 static const struct can_bittiming_const flexcan_bittiming_const = {
@@ -389,6 +388,34 @@
 		(&priv->regs->mb[bank][priv->mb_size * mb_index]);
 }
 
+static int flexcan_low_power_enter_ack(struct flexcan_priv *priv)
+{
+	struct flexcan_regs __iomem *regs = priv->regs;
+	unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
+
+	while (timeout-- && !(priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
+		udelay(10);
+
+	if (!(priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
+static int flexcan_low_power_exit_ack(struct flexcan_priv *priv)
+{
+	struct flexcan_regs __iomem *regs = priv->regs;
+	unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
+
+	while (timeout-- && (priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
+		udelay(10);
+
+	if (priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
 static void flexcan_enable_wakeup_irq(struct flexcan_priv *priv, bool enable)
 {
 	struct flexcan_regs __iomem *regs = priv->regs;
@@ -407,7 +434,6 @@
 static inline int flexcan_enter_stop_mode(struct flexcan_priv *priv)
 {
 	struct flexcan_regs __iomem *regs = priv->regs;
-	unsigned int ackval;
 	u32 reg_mcr;
 
 	reg_mcr = priv->read(&regs->mcr);
@@ -418,36 +444,24 @@
 	regmap_update_bits(priv->stm.gpr, priv->stm.req_gpr,
 			   1 << priv->stm.req_bit, 1 << priv->stm.req_bit);
 
-	/* get stop acknowledgment */
-	if (regmap_read_poll_timeout(priv->stm.gpr, priv->stm.ack_gpr,
-				     ackval, ackval & (1 << priv->stm.ack_bit),
-				     0, FLEXCAN_TIMEOUT_US))
-		return -ETIMEDOUT;
-
-	return 0;
+	return flexcan_low_power_enter_ack(priv);
 }
 
 static inline int flexcan_exit_stop_mode(struct flexcan_priv *priv)
 {
 	struct flexcan_regs __iomem *regs = priv->regs;
-	unsigned int ackval;
 	u32 reg_mcr;
 
 	/* remove stop request */
 	regmap_update_bits(priv->stm.gpr, priv->stm.req_gpr,
 			   1 << priv->stm.req_bit, 0);
 
-	/* get stop acknowledgment */
-	if (regmap_read_poll_timeout(priv->stm.gpr, priv->stm.ack_gpr,
-				     ackval, !(ackval & (1 << priv->stm.ack_bit)),
-				     0, FLEXCAN_TIMEOUT_US))
-		return -ETIMEDOUT;
 
 	reg_mcr = priv->read(&regs->mcr);
 	reg_mcr &= ~FLEXCAN_MCR_SLF_WAK;
 	priv->write(reg_mcr, &regs->mcr);
 
-	return 0;
+	return flexcan_low_power_exit_ack(priv);
 }
 
 static inline void flexcan_error_irq_enable(const struct flexcan_priv *priv)
@@ -506,49 +520,41 @@
 static int flexcan_chip_enable(struct flexcan_priv *priv)
 {
 	struct flexcan_regs __iomem *regs = priv->regs;
-	unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
 	u32 reg;
 
 	reg = priv->read(&regs->mcr);
 	reg &= ~FLEXCAN_MCR_MDIS;
 	priv->write(reg, &regs->mcr);
 
-	while (timeout-- && (priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
-		udelay(10);
-
-	if (priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK)
-		return -ETIMEDOUT;
-
-	return 0;
+	return flexcan_low_power_exit_ack(priv);
 }
 
 static int flexcan_chip_disable(struct flexcan_priv *priv)
 {
 	struct flexcan_regs __iomem *regs = priv->regs;
-	unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
 	u32 reg;
 
 	reg = priv->read(&regs->mcr);
 	reg |= FLEXCAN_MCR_MDIS;
 	priv->write(reg, &regs->mcr);
 
-	while (timeout-- && !(priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
-		udelay(10);
-
-	if (!(priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
-		return -ETIMEDOUT;
-
-	return 0;
+	return flexcan_low_power_enter_ack(priv);
 }
 
 static int flexcan_chip_freeze(struct flexcan_priv *priv)
 {
 	struct flexcan_regs __iomem *regs = priv->regs;
-	unsigned int timeout = 1000 * 1000 * 10 / priv->can.bittiming.bitrate;
+	unsigned int timeout;
+	u32 bitrate = priv->can.bittiming.bitrate;
 	u32 reg;
 
+	if (bitrate)
+		timeout = 1000 * 1000 * 10 / bitrate;
+	else
+		timeout = FLEXCAN_TIMEOUT_US / 10;
+
 	reg = priv->read(&regs->mcr);
-	reg |= FLEXCAN_MCR_HALT;
+	reg |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT;
 	priv->write(reg, &regs->mcr);
 
 	while (timeout-- && !(priv->read(&regs->mcr) & FLEXCAN_MCR_FRZ_ACK))
@@ -614,8 +620,10 @@
 	int err;
 
 	err = pm_runtime_get_sync(priv->dev);
-	if (err < 0)
+	if (err < 0) {
+		pm_runtime_put_noidle(priv->dev);
 		return err;
+	}
 
 	err = __flexcan_get_berr_counter(dev, bec);
 
@@ -1055,10 +1063,13 @@
 
 	flexcan_set_bittiming(dev);
 
+	/* set freeze, halt */
+	err = flexcan_chip_freeze(priv);
+	if (err)
+		goto out_chip_disable;
+
 	/* MCR
 	 *
-	 * enable freeze
-	 * halt now
 	 * only supervisor access
 	 * enable warning int
 	 * enable individual RX masking
@@ -1067,9 +1078,8 @@
 	 */
 	reg_mcr = priv->read(&regs->mcr);
 	reg_mcr &= ~FLEXCAN_MCR_MAXMB(0xff);
-	reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT | FLEXCAN_MCR_SUPV |
-		FLEXCAN_MCR_WRN_EN | FLEXCAN_MCR_IRMQ | FLEXCAN_MCR_IDAM_C |
-		FLEXCAN_MCR_MAXMB(priv->tx_mb_idx);
+	reg_mcr |= FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN | FLEXCAN_MCR_IRMQ |
+		FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_MAXMB(priv->tx_mb_idx);
 
 	/* MCR
 	 *
@@ -1200,14 +1210,10 @@
 		priv->write(reg_mecr, &regs->mecr);
 	}
 
-	err = flexcan_transceiver_enable(priv);
-	if (err)
-		goto out_chip_disable;
-
 	/* synchronize with the can bus */
 	err = flexcan_chip_unfreeze(priv);
 	if (err)
-		goto out_transceiver_disable;
+		goto out_chip_disable;
 
 	priv->can.state = CAN_STATE_ERROR_ACTIVE;
 
@@ -1224,25 +1230,28 @@
 
 	return 0;
 
- out_transceiver_disable:
-	flexcan_transceiver_disable(priv);
  out_chip_disable:
 	flexcan_chip_disable(priv);
 	return err;
 }
 
-/* flexcan_chip_stop
+/* __flexcan_chip_stop
  *
- * this functions is entered with clocks enabled
+ * this function is entered with clocks enabled
  */
-static void flexcan_chip_stop(struct net_device *dev)
+static int __flexcan_chip_stop(struct net_device *dev, bool disable_on_error)
 {
 	struct flexcan_priv *priv = netdev_priv(dev);
 	struct flexcan_regs __iomem *regs = priv->regs;
+	int err;
 
 	/* freeze + disable module */
-	flexcan_chip_freeze(priv);
-	flexcan_chip_disable(priv);
+	err = flexcan_chip_freeze(priv);
+	if (err && !disable_on_error)
+		return err;
+	err = flexcan_chip_disable(priv);
+	if (err && !disable_on_error)
+		goto out_chip_unfreeze;
 
 	/* Disable all interrupts */
 	priv->write(0, &regs->imask2);
@@ -1250,8 +1259,24 @@
 	priv->write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL,
 		    &regs->ctrl);
 
-	flexcan_transceiver_disable(priv);
 	priv->can.state = CAN_STATE_STOPPED;
+
+	return 0;
+
+ out_chip_unfreeze:
+	flexcan_chip_unfreeze(priv);
+
+	return err;
+}
+
+static inline int flexcan_chip_stop_disable_on_error(struct net_device *dev)
+{
+	return __flexcan_chip_stop(dev, true);
+}
+
+static inline int flexcan_chip_stop(struct net_device *dev)
+{
+	return __flexcan_chip_stop(dev, false);
 }
 
 static int flexcan_open(struct net_device *dev)
@@ -1260,17 +1285,23 @@
 	int err;
 
 	err = pm_runtime_get_sync(priv->dev);
-	if (err < 0)
+	if (err < 0) {
+		pm_runtime_put_noidle(priv->dev);
 		return err;
+	}
 
 	err = open_candev(dev);
 	if (err)
 		goto out_runtime_put;
 
-	err = request_irq(dev->irq, flexcan_irq, IRQF_SHARED, dev->name, dev);
+	err = flexcan_transceiver_enable(priv);
 	if (err)
 		goto out_close;
 
+	err = request_irq(dev->irq, flexcan_irq, IRQF_SHARED, dev->name, dev);
+	if (err)
+		goto out_transceiver_disable;
+
 	priv->mb_size = sizeof(struct flexcan_mb) + CAN_MAX_DLEN;
 	priv->mb_count = (sizeof(priv->regs->mb[0]) / priv->mb_size) +
 			 (sizeof(priv->regs->mb[1]) / priv->mb_size);
@@ -1326,6 +1357,8 @@
 	can_rx_offload_del(&priv->offload);
  out_free_irq:
 	free_irq(dev->irq, dev);
+ out_transceiver_disable:
+	flexcan_transceiver_disable(priv);
  out_close:
 	close_candev(dev);
  out_runtime_put:
@@ -1340,10 +1373,11 @@
 
 	netif_stop_queue(dev);
 	can_rx_offload_disable(&priv->offload);
-	flexcan_chip_stop(dev);
+	flexcan_chip_stop_disable_on_error(dev);
 
 	can_rx_offload_del(&priv->offload);
 	free_irq(dev->irq, dev);
+	flexcan_transceiver_disable(priv);
 
 	close_candev(dev);
 	pm_runtime_put(priv->dev);
@@ -1406,10 +1440,14 @@
 	if (err)
 		goto out_chip_disable;
 
-	/* set freeze, halt and activate FIFO, restrict register access */
+	/* set freeze, halt */
+	err = flexcan_chip_freeze(priv);
+	if (err)
+		goto out_chip_disable;
+
+	/* activate FIFO, restrict register access */
 	reg = priv->read(&regs->mcr);
-	reg |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT |
-		FLEXCAN_MCR_FEN | FLEXCAN_MCR_SUPV;
+	reg |=  FLEXCAN_MCR_FEN | FLEXCAN_MCR_SUPV;
 	priv->write(reg, &regs->mcr);
 
 	/* Currently we only support newer versions of this core
@@ -1654,6 +1692,8 @@
 {
 	struct net_device *dev = platform_get_drvdata(pdev);
 
+	device_set_wakeup_enable(&pdev->dev, false);
+	device_set_wakeup_capable(&pdev->dev, false);
 	unregister_flexcandev(dev);
 	pm_runtime_disable(&pdev->dev);
 	free_candev(dev);
@@ -1680,13 +1720,12 @@
 			err = flexcan_chip_disable(priv);
 			if (err)
 				return err;
-
-			err = pm_runtime_force_suspend(device);
 		}
 		netif_stop_queue(dev);
 		netif_device_detach(dev);
+
+		priv->can.state = CAN_STATE_SLEEPING;
 	}
-	priv->can.state = CAN_STATE_SLEEPING;
 
 	return err;
 }
@@ -1697,19 +1736,19 @@
 	struct flexcan_priv *priv = netdev_priv(dev);
 	int err = 0;
 
-	priv->can.state = CAN_STATE_ERROR_ACTIVE;
 	if (netif_running(dev)) {
 		netif_device_attach(dev);
 		netif_start_queue(dev);
 		if (device_may_wakeup(device)) {
 			disable_irq_wake(dev->irq);
-		} else {
-			err = pm_runtime_force_resume(device);
+			err = flexcan_exit_stop_mode(priv);
 			if (err)
 				return err;
-
+		} else {
 			err = flexcan_chip_enable(priv);
 		}
+
+		priv->can.state = CAN_STATE_ERROR_ACTIVE;
 	}
 
 	return err;
@@ -1738,8 +1777,16 @@
 	struct net_device *dev = dev_get_drvdata(device);
 	struct flexcan_priv *priv = netdev_priv(dev);
 
-	if (netif_running(dev) && device_may_wakeup(device))
-		flexcan_enable_wakeup_irq(priv, true);
+	if (netif_running(dev)) {
+		int err;
+
+		if (device_may_wakeup(device))
+			flexcan_enable_wakeup_irq(priv, true);
+
+		err = pm_runtime_force_suspend(device);
+		if (err)
+			return err;
+	}
 
 	return 0;
 }
@@ -1748,13 +1795,16 @@
 {
 	struct net_device *dev = dev_get_drvdata(device);
 	struct flexcan_priv *priv = netdev_priv(dev);
-	int err;
 
-	if (netif_running(dev) && device_may_wakeup(device)) {
-		flexcan_enable_wakeup_irq(priv, false);
-		err = flexcan_exit_stop_mode(priv);
+	if (netif_running(dev)) {
+		int err;
+
+		err = pm_runtime_force_resume(device);
 		if (err)
 			return err;
+
+		if (device_may_wakeup(device))
+			flexcan_enable_wakeup_irq(priv, false);
 	}
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/grcan.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/grcan.c
@@ -241,13 +241,14 @@
 		.rxsize		= GRCAN_DEFAULT_BUFFER_SIZE,	\
 		}
 
-#define GRCAN_TXBUG_SAFE_GRLIB_VERSION	0x4100
+#define GRCAN_TXBUG_SAFE_GRLIB_VERSION	4100
 #define GRLIB_VERSION_MASK		0xffff
 
 /* GRCAN private data structure */
 struct grcan_priv {
 	struct can_priv can;	/* must be the first member */
 	struct net_device *dev;
+	struct device *ofdev_dev;
 	struct napi_struct napi;
 
 	struct grcan_registers __iomem *regs;	/* ioremap'ed registers */
@@ -924,7 +925,7 @@
 	struct grcan_priv *priv = netdev_priv(dev);
 	struct grcan_dma *dma = &priv->dma;
 
-	dma_free_coherent(&dev->dev, dma->base_size, dma->base_buf,
+	dma_free_coherent(priv->ofdev_dev, dma->base_size, dma->base_buf,
 			  dma->base_handle);
 	memset(dma, 0, sizeof(*dma));
 }
@@ -949,7 +950,7 @@
 
 	/* Extra GRCAN_BUFFER_ALIGNMENT to allow for alignment */
 	dma->base_size = lsize + ssize + GRCAN_BUFFER_ALIGNMENT;
-	dma->base_buf = dma_alloc_coherent(&dev->dev,
+	dma->base_buf = dma_alloc_coherent(priv->ofdev_dev,
 					   dma->base_size,
 					   &dma->base_handle,
 					   GFP_KERNEL);
@@ -1113,8 +1114,10 @@
 
 	priv->closing = true;
 	if (priv->need_txbug_workaround) {
+		spin_unlock_irqrestore(&priv->lock, flags);
 		del_timer_sync(&priv->hang_timer);
 		del_timer_sync(&priv->rr_timer);
+		spin_lock_irqsave(&priv->lock, flags);
 	}
 	netif_stop_queue(dev);
 	grcan_stop_hardware(dev);
@@ -1134,7 +1137,7 @@
 	return 0;
 }
 
-static int grcan_transmit_catch_up(struct net_device *dev, int budget)
+static void grcan_transmit_catch_up(struct net_device *dev)
 {
 	struct grcan_priv *priv = netdev_priv(dev);
 	unsigned long flags;
@@ -1142,7 +1145,7 @@
 
 	spin_lock_irqsave(&priv->lock, flags);
 
-	work_done = catch_up_echo_skb(dev, budget, true);
+	work_done = catch_up_echo_skb(dev, -1, true);
 	if (work_done) {
 		if (!priv->resetting && !priv->closing &&
 		    !(priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY))
@@ -1156,8 +1159,6 @@
 	}
 
 	spin_unlock_irqrestore(&priv->lock, flags);
-
-	return work_done;
 }
 
 static int grcan_receive(struct net_device *dev, int budget)
@@ -1239,19 +1240,13 @@
 	struct net_device *dev = priv->dev;
 	struct grcan_registers __iomem *regs = priv->regs;
 	unsigned long flags;
-	int tx_work_done, rx_work_done;
-	int rx_budget = budget / 2;
-	int tx_budget = budget - rx_budget;
+	int work_done;
 
-	/* Half of the budget for receiveing messages */
-	rx_work_done = grcan_receive(dev, rx_budget);
+	work_done = grcan_receive(dev, budget);
 
-	/* Half of the budget for transmitting messages as that can trigger echo
-	 * frames being received
-	 */
-	tx_work_done = grcan_transmit_catch_up(dev, tx_budget);
+	grcan_transmit_catch_up(dev);
 
-	if (rx_work_done < rx_budget && tx_work_done < tx_budget) {
+	if (work_done < budget) {
 		napi_complete(napi);
 
 		/* Guarantee no interference with a running reset that otherwise
@@ -1268,7 +1263,7 @@
 		spin_unlock_irqrestore(&priv->lock, flags);
 	}
 
-	return rx_work_done + tx_work_done;
+	return work_done;
 }
 
 /* Work tx bug by waiting while for the risky situation to clear. If that fails,
@@ -1600,6 +1595,7 @@
 	memcpy(&priv->config, &grcan_module_config,
 	       sizeof(struct grcan_device_config));
 	priv->dev = dev;
+	priv->ofdev_dev = &ofdev->dev;
 	priv->regs = base;
 	priv->can.bittiming_const = &grcan_bittiming_const;
 	priv->can.do_set_bittiming = grcan_set_bittiming;
@@ -1652,6 +1648,7 @@
 static int grcan_probe(struct platform_device *ofdev)
 {
 	struct device_node *np = ofdev->dev.of_node;
+	struct device_node *sysid_parent;
 	struct resource *res;
 	u32 sysid, ambafreq;
 	int irq, err;
@@ -1661,10 +1658,14 @@
 	/* Compare GRLIB version number with the first that does not
 	 * have the tx bug (see start_xmit)
 	 */
-	err = of_property_read_u32(np, "systemid", &sysid);
-	if (!err && ((sysid & GRLIB_VERSION_MASK)
-		     >= GRCAN_TXBUG_SAFE_GRLIB_VERSION))
-		txbug = false;
+	sysid_parent = of_find_node_by_path("/ambapp0");
+	if (sysid_parent) {
+		err = of_property_read_u32(sysid_parent, "systemid", &sysid);
+		if (!err && ((sysid & GRLIB_VERSION_MASK) >=
+			     GRCAN_TXBUG_SAFE_GRLIB_VERSION))
+			txbug = false;
+		of_node_put(sysid_parent);
+	}
 
 	err = of_property_read_u32(np, "freq", &ambafreq);
 	if (err) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/janz-ican3.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/janz-ican3.c
@@ -1451,7 +1451,7 @@
 
 	/* process all communication messages */
 	while (true) {
-		struct ican3_msg uninitialized_var(msg);
+		struct ican3_msg msg;
 		ret = ican3_recv_msg(mod, &msg);
 		if (ret)
 			break;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/kvaser_pciefd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/kvaser_pciefd.c
@@ -57,6 +57,7 @@
 #define KVASER_PCIEFD_KCAN_STAT_REG 0x418
 #define KVASER_PCIEFD_KCAN_MODE_REG 0x41c
 #define KVASER_PCIEFD_KCAN_BTRN_REG 0x420
+#define KVASER_PCIEFD_KCAN_BUS_LOAD_REG 0x424
 #define KVASER_PCIEFD_KCAN_BTRD_REG 0x428
 #define KVASER_PCIEFD_KCAN_PWM_REG 0x430
 /* Loopback control register */
@@ -69,10 +70,12 @@
 #define KVASER_PCIEFD_SYSID_BUILD_REG (KVASER_PCIEFD_SYSID_BASE + 0x14)
 /* Shared receive buffer registers */
 #define KVASER_PCIEFD_SRB_BASE 0x1f200
+#define KVASER_PCIEFD_SRB_FIFO_LAST_REG (KVASER_PCIEFD_SRB_BASE + 0x1f4)
 #define KVASER_PCIEFD_SRB_CMD_REG (KVASER_PCIEFD_SRB_BASE + 0x200)
 #define KVASER_PCIEFD_SRB_IEN_REG (KVASER_PCIEFD_SRB_BASE + 0x204)
 #define KVASER_PCIEFD_SRB_IRQ_REG (KVASER_PCIEFD_SRB_BASE + 0x20c)
 #define KVASER_PCIEFD_SRB_STAT_REG (KVASER_PCIEFD_SRB_BASE + 0x210)
+#define KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG (KVASER_PCIEFD_SRB_BASE + 0x214)
 #define KVASER_PCIEFD_SRB_CTRL_REG (KVASER_PCIEFD_SRB_BASE + 0x218)
 /* EPCS flash controller registers */
 #define KVASER_PCIEFD_SPI_BASE 0x1fc00
@@ -109,6 +112,9 @@
 /* DMA support */
 #define KVASER_PCIEFD_SRB_STAT_DMA BIT(24)
 
+/* SRB current packet level */
+#define KVASER_PCIEFD_SRB_RX_NR_PACKETS_MASK 0xff
+
 /* DMA Enable */
 #define KVASER_PCIEFD_SRB_CTRL_DMA_ENABLE BIT(0)
 
@@ -247,6 +253,9 @@
 #define KVASER_PCIEFD_SPACK_EWLR BIT(23)
 #define KVASER_PCIEFD_SPACK_EPLR BIT(24)
 
+/* Kvaser KCAN_EPACK second word */
+#define KVASER_PCIEFD_EPACK_DIR_TX BIT(0)
+
 struct kvaser_pciefd;
 
 struct kvaser_pciefd_can {
@@ -287,12 +296,12 @@
 static const struct can_bittiming_const kvaser_pciefd_bittiming_const = {
 	.name = KVASER_PCIEFD_DRV_NAME,
 	.tseg1_min = 1,
-	.tseg1_max = 255,
+	.tseg1_max = 512,
 	.tseg2_min = 1,
 	.tseg2_max = 32,
 	.sjw_max = 16,
 	.brp_min = 1,
-	.brp_max = 4096,
+	.brp_max = 8192,
 	.brp_inc = 1,
 };
 
@@ -524,7 +533,7 @@
 	      KVASER_PCIEFD_KCAN_IRQ_TOF | KVASER_PCIEFD_KCAN_IRQ_ABD |
 	      KVASER_PCIEFD_KCAN_IRQ_TAE | KVASER_PCIEFD_KCAN_IRQ_TAL |
 	      KVASER_PCIEFD_KCAN_IRQ_FDIC | KVASER_PCIEFD_KCAN_IRQ_BPP |
-	      KVASER_PCIEFD_KCAN_IRQ_TAR | KVASER_PCIEFD_KCAN_IRQ_TFD;
+	      KVASER_PCIEFD_KCAN_IRQ_TAR;
 
 	iowrite32(msk, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
 
@@ -552,6 +561,8 @@
 
 	if (can->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
 		mode |= KVASER_PCIEFD_KCAN_MODE_LOM;
+	else
+		mode &= ~KVASER_PCIEFD_KCAN_MODE_LOM;
 
 	mode |= KVASER_PCIEFD_KCAN_MODE_EEN;
 	mode |= KVASER_PCIEFD_KCAN_MODE_EPEN;
@@ -570,7 +581,7 @@
 
 	spin_lock_irqsave(&can->lock, irq);
 	iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
-	iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD | KVASER_PCIEFD_KCAN_IRQ_TFD,
+	iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD,
 		  can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
 
 	status = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_STAT_REG);
@@ -613,7 +624,7 @@
 	iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
 	iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
 
-	iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD | KVASER_PCIEFD_KCAN_IRQ_TFD,
+	iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD,
 		  can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
 
 	mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG);
@@ -715,6 +726,7 @@
 		iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
 		del_timer(&can->bec_poll_timer);
 	}
+	can->can.state = CAN_STATE_STOPPED;
 	close_candev(netdev);
 
 	return ret;
@@ -947,6 +959,9 @@
 		timer_setup(&can->bec_poll_timer, kvaser_pciefd_bec_poll_timer,
 			    0);
 
+		/* Disable Bus load reporting */
+		iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_BUS_LOAD_REG);
+
 		tx_npackets = ioread32(can->reg_base +
 				       KVASER_PCIEFD_KCAN_TX_NPACKETS_REG);
 		if (((tx_npackets >> KVASER_PCIEFD_KCAN_TX_NPACKETS_MAX_SHIFT) &
@@ -994,8 +1009,7 @@
 		SET_NETDEV_DEV(netdev, &pcie->pci->dev);
 
 		iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG);
-		iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD |
-			  KVASER_PCIEFD_KCAN_IRQ_TFD,
+		iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD,
 			  can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
 
 		pcie->can[i] = can;
@@ -1045,6 +1059,7 @@
 {
 	int i;
 	u32 srb_status;
+	u32 srb_packet_count;
 	dma_addr_t dma_addr[KVASER_PCIEFD_DMA_COUNT];
 
 	/* Disable the DMA */
@@ -1072,6 +1087,15 @@
 		  KVASER_PCIEFD_SRB_CMD_RDB1,
 		  pcie->reg_base + KVASER_PCIEFD_SRB_CMD_REG);
 
+	/* Empty Rx FIFO */
+	srb_packet_count = ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG) &
+			   KVASER_PCIEFD_SRB_RX_NR_PACKETS_MASK;
+	while (srb_packet_count) {
+		/* Drop current packet in FIFO */
+		ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_FIFO_LAST_REG);
+		srb_packet_count--;
+	}
+
 	srb_status = ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_STAT_REG);
 	if (!(srb_status & KVASER_PCIEFD_SRB_STAT_DI)) {
 		dev_err(&pcie->pci->dev, "DMA not idle before enabling\n");
@@ -1279,7 +1303,10 @@
 
 	can->err_rep_cnt++;
 	can->can.can_stats.bus_error++;
-	stats->rx_errors++;
+	if (p->header[1] & KVASER_PCIEFD_EPACK_DIR_TX)
+		stats->tx_errors++;
+	else
+		stats->rx_errors++;
 
 	can->bec.txerr = bec.txerr;
 	can->bec.rxerr = bec.rxerr;
@@ -1411,9 +1438,6 @@
 		cmd = KVASER_PCIEFD_KCAN_CMD_AT;
 		cmd |= ++can->cmd_seq << KVASER_PCIEFD_KCAN_CMD_SEQ_SHIFT;
 		iowrite32(cmd, can->reg_base + KVASER_PCIEFD_KCAN_CMD_REG);
-
-		iowrite32(KVASER_PCIEFD_KCAN_IRQ_TFD,
-			  can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG);
 	} else if (p->header[0] & KVASER_PCIEFD_SPACK_IDET &&
 		   p->header[0] & KVASER_PCIEFD_SPACK_IRM &&
 		   cmdseq == (p->header[1] & KVASER_PCIEFD_PACKET_SEQ_MSK) &&
@@ -1702,15 +1726,6 @@
 	if (irq & KVASER_PCIEFD_KCAN_IRQ_TOF)
 		netdev_err(can->can.dev, "Tx FIFO overflow\n");
 
-	if (irq & KVASER_PCIEFD_KCAN_IRQ_TFD) {
-		u8 count = ioread32(can->reg_base +
-				    KVASER_PCIEFD_KCAN_TX_NPACKETS_REG) & 0xff;
-
-		if (count == 0)
-			iowrite32(KVASER_PCIEFD_KCAN_CTRL_EFLUSH,
-				  can->reg_base + KVASER_PCIEFD_KCAN_CTRL_REG);
-	}
-
 	if (irq & KVASER_PCIEFD_KCAN_IRQ_BPP)
 		netdev_err(can->can.dev,
 			   "Fail to change bittiming, when not in reset mode\n");
@@ -1812,6 +1827,11 @@
 	if (err)
 		goto err_teardown_can_ctrls;
 
+	err = request_irq(pcie->pci->irq, kvaser_pciefd_irq_handler,
+			  IRQF_SHARED, KVASER_PCIEFD_DRV_NAME, pcie);
+	if (err)
+		goto err_teardown_can_ctrls;
+
 	iowrite32(KVASER_PCIEFD_SRB_IRQ_DPD0 | KVASER_PCIEFD_SRB_IRQ_DPD1,
 		  pcie->reg_base + KVASER_PCIEFD_SRB_IRQ_REG);
 
@@ -1832,11 +1852,6 @@
 	iowrite32(KVASER_PCIEFD_SRB_CMD_RDB1,
 		  pcie->reg_base + KVASER_PCIEFD_SRB_CMD_REG);
 
-	err = request_irq(pcie->pci->irq, kvaser_pciefd_irq_handler,
-			  IRQF_SHARED, KVASER_PCIEFD_DRV_NAME, pcie);
-	if (err)
-		goto err_teardown_can_ctrls;
-
 	err = kvaser_pciefd_reg_candev(pcie);
 	if (err)
 		goto err_free_irq;
@@ -1844,6 +1859,8 @@
 	return 0;
 
 err_free_irq:
+	/* Disable PCI interrupts */
+	iowrite32(0, pcie->reg_base + KVASER_PCIEFD_IEN_REG);
 	free_irq(pcie->pci->irq, pcie);
 
 err_teardown_can_ctrls:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/m_can/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/m_can/Kconfig
@@ -16,7 +16,8 @@
 
 config CAN_M_CAN_TCAN4X5X
 	depends on CAN_M_CAN
-	depends on REGMAP_SPI
+	depends on SPI
+	select REGMAP_SPI
 	tristate "TCAN4X5X M_CAN device"
 	---help---
 	  Say Y here if you want support for Texas Instruments TCAN4x5x
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/m_can/m_can.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/m_can/m_can.c
@@ -206,15 +206,15 @@
 
 /* Interrupts for version 3.0.x */
 #define IR_ERR_LEC_30X	(IR_STE	| IR_FOE | IR_ACKE | IR_BE | IR_CRCE)
-#define IR_ERR_BUS_30X	(IR_ERR_LEC_30X | IR_WDI | IR_ELO | IR_BEU | \
-			 IR_BEC | IR_TOO | IR_MRAF | IR_TSW | IR_TEFL | \
-			 IR_RF1L | IR_RF0L)
+#define IR_ERR_BUS_30X	(IR_ERR_LEC_30X | IR_WDI | IR_BEU | IR_BEC | \
+			 IR_TOO | IR_MRAF | IR_TSW | IR_TEFL | IR_RF1L | \
+			 IR_RF0L)
 #define IR_ERR_ALL_30X	(IR_ERR_STATE | IR_ERR_BUS_30X)
 /* Interrupts for version >= 3.1.x */
 #define IR_ERR_LEC_31X	(IR_PED | IR_PEA)
-#define IR_ERR_BUS_31X      (IR_ERR_LEC_31X | IR_WDI | IR_ELO | IR_BEU | \
-			 IR_BEC | IR_TOO | IR_MRAF | IR_TSW | IR_TEFL | \
-			 IR_RF1L | IR_RF0L)
+#define IR_ERR_BUS_31X      (IR_ERR_LEC_31X | IR_WDI | IR_BEU | IR_BEC | \
+			 IR_TOO | IR_MRAF | IR_TSW | IR_TEFL | IR_RF1L | \
+			 IR_RF0L)
 #define IR_ERR_ALL_31X	(IR_ERR_STATE | IR_ERR_BUS_31X)
 
 /* Interrupt Line Select (ILS) */
@@ -379,10 +379,6 @@
 		cccr &= ~CCCR_CSR;
 
 	if (enable) {
-		/* Clear the Clock stop request if it was set */
-		if (cccr & CCCR_CSR)
-			cccr &= ~CCCR_CSR;
-
 		/* enable m_can configuration */
 		m_can_write(cdev, M_CAN_CCCR, cccr | CCCR_INIT);
 		udelay(5);
@@ -505,9 +501,6 @@
 	}
 
 	while ((rxfs & RXFS_FFL_MASK) && (quota > 0)) {
-		if (rxfs & RXFS_RFL)
-			netdev_warn(dev, "Rx FIFO 0 Message Lost\n");
-
 		m_can_read_fifo(dev, rxfs);
 
 		quota--;
@@ -664,7 +657,7 @@
 	unsigned int ecr;
 
 	switch (new_state) {
-	case CAN_STATE_ERROR_ACTIVE:
+	case CAN_STATE_ERROR_WARNING:
 		/* error warning state */
 		cdev->can.can_stats.error_warning++;
 		cdev->can.state = CAN_STATE_ERROR_WARNING;
@@ -693,7 +686,7 @@
 	__m_can_get_berr_counter(dev, &bec);
 
 	switch (new_state) {
-	case CAN_STATE_ERROR_ACTIVE:
+	case CAN_STATE_ERROR_WARNING:
 		/* error warning state */
 		cf->can_id |= CAN_ERR_CRTL;
 		cf->data[1] = (bec.txerr > bec.rxerr) ?
@@ -758,8 +751,6 @@
 {
 	if (irqstatus & IR_WDI)
 		netdev_err(dev, "Message RAM Watchdog event due to missing READY\n");
-	if (irqstatus & IR_ELO)
-		netdev_err(dev, "Error Logging Overflow\n");
 	if (irqstatus & IR_BEU)
 		netdev_err(dev, "Bit Error Uncorrected\n");
 	if (irqstatus & IR_BEC)
@@ -846,7 +837,7 @@
 {
 	struct m_can_classdev *cdev = netdev_priv(dev);
 
-	m_can_rx_handler(dev, 1);
+	m_can_rx_handler(dev, M_CAN_NAPI_WEIGHT);
 
 	m_can_enable_all_interrupts(cdev);
 
@@ -913,6 +904,8 @@
 	struct net_device_stats *stats = &dev->stats;
 	u32 ir;
 
+	if (pm_runtime_suspended(cdev->dev))
+		return IRQ_NONE;
 	ir = m_can_read(cdev, M_CAN_IR);
 	if (!ir)
 		return IRQ_NONE;
@@ -988,7 +981,7 @@
 	.name = KBUILD_MODNAME,
 	.tseg1_min = 2,		/* Time segment 1 = prop_seg + phase_seg1 */
 	.tseg1_max = 256,
-	.tseg2_min = 1,		/* Time segment 2 = phase_seg2 */
+	.tseg2_min = 2,		/* Time segment 2 = phase_seg2 */
 	.tseg2_max = 128,
 	.sjw_max = 128,
 	.brp_min = 1,
@@ -1335,6 +1328,8 @@
 						&m_can_data_bittiming_const_31X;
 		break;
 	case 32:
+	case 33:
+		/* Support both MCAN version v3.2.x and v3.3.0 */
 		m_can_dev->can.bittiming_const = m_can_dev->bit_timing ?
 			m_can_dev->bit_timing : &m_can_bittiming_const_31X;
 
@@ -1366,6 +1361,9 @@
 	/* disable all interrupts */
 	m_can_disable_all_interrupts(cdev);
 
+	/* Set init mode to disengage from the network */
+	m_can_config_endisable(cdev, true);
+
 	/* set the state as STOPPED */
 	cdev->can.state = CAN_STATE_STOPPED;
 }
@@ -1418,6 +1416,8 @@
 	int i;
 	int putidx;
 
+	cdev->tx_skb = NULL;
+
 	/* Generate ID field for TX buffer Element */
 	/* Common to all supported M_CAN versions */
 	if (cf->can_id & CAN_EFF_FLAG) {
@@ -1443,8 +1443,6 @@
 					 M_CAN_FIFO_DATA(i / 4),
 					 *(u32 *)(cf->data + i));
 
-		can_put_echo_skb(skb, dev, 0);
-
 		if (cdev->can.ctrlmode & CAN_CTRLMODE_FD) {
 			cccr = m_can_read(cdev, M_CAN_CCCR);
 			cccr &= ~(CCCR_CMR_MASK << CCCR_CMR_SHIFT);
@@ -1461,6 +1459,9 @@
 			m_can_write(cdev, M_CAN_CCCR, cccr);
 		}
 		m_can_write(cdev, M_CAN_TXBTIE, 0x1);
+
+		can_put_echo_skb(skb, dev, 0);
+
 		m_can_write(cdev, M_CAN_TXBAR, 0x1);
 		/* End of xmit function for version 3.0.x */
 	} else {
@@ -1534,7 +1535,6 @@
 						tx_work);
 
 	m_can_tx_handler(cdev);
-	cdev->tx_skb = NULL;
 }
 
 static netdev_tx_t m_can_start_xmit(struct sk_buff *skb,
@@ -1600,7 +1600,7 @@
 		INIT_WORK(&cdev->tx_work, m_can_tx_work_queue);
 
 		err = request_threaded_irq(dev->irq, NULL, m_can_isr,
-					   IRQF_ONESHOT | IRQF_TRIGGER_FALLING,
+					   IRQF_ONESHOT,
 					   dev->name, dev);
 	} else {
 		err = request_irq(dev->irq, m_can_isr, IRQF_SHARED, dev->name,
@@ -1764,6 +1764,12 @@
 }
 EXPORT_SYMBOL_GPL(m_can_class_allocate_dev);
 
+void m_can_class_free_dev(struct net_device *net)
+{
+	free_candev(net);
+}
+EXPORT_SYMBOL_GPL(m_can_class_free_dev);
+
 int m_can_class_register(struct m_can_classdev *m_can_dev)
 {
 	int ret;
@@ -1859,8 +1865,6 @@
 {
 	unregister_candev(m_can_dev->net);
 
-	m_can_clk_stop(m_can_dev);
-
 	free_candev(m_can_dev->net);
 }
 EXPORT_SYMBOL_GPL(m_can_class_unregister);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/m_can/m_can.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/m_can/m_can.h
@@ -99,6 +99,7 @@
 };
 
 struct m_can_classdev *m_can_class_allocate_dev(struct device *dev);
+void m_can_class_free_dev(struct net_device *net);
 int m_can_class_register(struct m_can_classdev *cdev);
 void m_can_class_unregister(struct m_can_classdev *cdev);
 int m_can_class_get_clocks(struct m_can_classdev *cdev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/m_can/m_can_platform.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/m_can/m_can_platform.c
@@ -144,8 +144,6 @@
 	struct net_device *ndev = dev_get_drvdata(dev);
 	struct m_can_classdev *mcan_class = netdev_priv(ndev);
 
-	m_can_class_suspend(dev);
-
 	clk_disable_unprepare(mcan_class->cclk);
 	clk_disable_unprepare(mcan_class->hclk);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/m_can/tcan4x5x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/m_can/tcan4x5x.c
@@ -88,7 +88,7 @@
 
 #define TCAN4X5X_MRAM_START 0x8000
 #define TCAN4X5X_MCAN_OFFSET 0x1000
-#define TCAN4X5X_MAX_REGISTER 0x8fff
+#define TCAN4X5X_MAX_REGISTER 0x8ffc
 
 #define TCAN4X5X_CLEAR_ALL_INT 0xffffffff
 #define TCAN4X5X_SET_ALL_INT 0xffffffff
@@ -126,30 +126,6 @@
 	int reg_offset;
 };
 
-static struct can_bittiming_const tcan4x5x_bittiming_const = {
-	.name = DEVICE_NAME,
-	.tseg1_min = 2,
-	.tseg1_max = 31,
-	.tseg2_min = 2,
-	.tseg2_max = 16,
-	.sjw_max = 16,
-	.brp_min = 1,
-	.brp_max = 32,
-	.brp_inc = 1,
-};
-
-static struct can_bittiming_const tcan4x5x_data_bittiming_const = {
-	.name = DEVICE_NAME,
-	.tseg1_min = 1,
-	.tseg1_max = 32,
-	.tseg2_min = 1,
-	.tseg2_max = 16,
-	.sjw_max = 16,
-	.brp_min = 1,
-	.brp_max = 32,
-	.brp_inc = 1,
-};
-
 static void tcan4x5x_check_wake(struct tcan4x5x_priv *priv)
 {
 	int wake_state = 0;
@@ -164,6 +140,28 @@
 	}
 }
 
+static int tcan4x5x_reset(struct tcan4x5x_priv *priv)
+{
+	int ret = 0;
+
+	if (priv->reset_gpio) {
+		gpiod_set_value(priv->reset_gpio, 1);
+
+		/* tpulse_width minimum 30us */
+		usleep_range(30, 100);
+		gpiod_set_value(priv->reset_gpio, 0);
+	} else {
+		ret = regmap_write(priv->regmap, TCAN4X5X_CONFIG,
+				   TCAN4X5X_SW_RESET);
+		if (ret)
+			return ret;
+	}
+
+	usleep_range(700, 1000);
+
+	return ret;
+}
+
 static int regmap_spi_gather_write(void *context, const void *reg,
 				   size_t reg_len, const void *val,
 				   size_t val_len)
@@ -293,11 +291,6 @@
 	if (ret)
 		return ret;
 
-	ret = tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_MCAN_INT_REG,
-				      TCAN4X5X_ENABLE_MCAN_INT);
-	if (ret)
-		return ret;
-
 	ret = tcan4x5x_write_tcan_reg(cdev, TCAN4X5X_INT_FLAGS,
 				      TCAN4X5X_CLEAR_ALL_INT);
 	if (ret)
@@ -327,20 +320,21 @@
 	if (ret)
 		return ret;
 
+	/* Zero out the MCAN buffers */
+	m_can_init_ram(cdev);
+
 	ret = regmap_update_bits(tcan4x5x->regmap, TCAN4X5X_CONFIG,
 				 TCAN4X5X_MODE_SEL_MASK, TCAN4X5X_MODE_NORMAL);
 	if (ret)
 		return ret;
 
-	/* Zero out the MCAN buffers */
-	m_can_init_ram(cdev);
-
 	return ret;
 }
 
 static int tcan4x5x_parse_config(struct m_can_classdev *cdev)
 {
 	struct tcan4x5x_priv *tcan4x5x = cdev->device_data;
+	int ret;
 
 	tcan4x5x->device_wake_gpio = devm_gpiod_get(cdev->dev, "device-wake",
 						    GPIOD_OUT_HIGH);
@@ -354,6 +348,10 @@
 	if (IS_ERR(tcan4x5x->reset_gpio))
 		tcan4x5x->reset_gpio = NULL;
 
+	ret = tcan4x5x_reset(tcan4x5x);
+	if (ret)
+		return ret;
+
 	tcan4x5x->device_state_gpio = devm_gpiod_get_optional(cdev->dev,
 							      "device-state",
 							      GPIOD_IN);
@@ -422,8 +420,6 @@
 	mcan_class->dev = &spi->dev;
 	mcan_class->ops = &tcan4x5x_ops;
 	mcan_class->is_peripheral = true;
-	mcan_class->bit_timing = &tcan4x5x_bittiming_const;
-	mcan_class->data_timing = &tcan4x5x_data_bittiming_const;
 	mcan_class->net->irq = spi->irq;
 
 	spi_set_drvdata(spi, priv);
@@ -440,9 +436,17 @@
 
 	priv->regmap = devm_regmap_init(&spi->dev, &tcan4x5x_bus,
 					&spi->dev, &tcan4x5x_regmap);
+	if (IS_ERR(priv->regmap)) {
+		ret = PTR_ERR(priv->regmap);
+		goto out_clk;
+	}
 
 	tcan4x5x_power_enable(priv->power, 1);
 
+	ret = tcan4x5x_init(mcan_class);
+	if (ret)
+		goto out_power;
+
 	ret = m_can_class_register(mcan_class);
 	if (ret)
 		goto out_power;
@@ -466,10 +470,10 @@
 {
 	struct tcan4x5x_priv *priv = spi_get_drvdata(spi);
 
-	tcan4x5x_power_enable(priv->power, 0);
-
 	m_can_class_unregister(priv->mcan_dev);
 
+	tcan4x5x_power_enable(priv->power, 0);
+
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/mscan/mpc5xxx_can.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/mscan/mpc5xxx_can.c
@@ -325,14 +325,14 @@
 					       &mscan_clksrc);
 	if (!priv->can.clock.freq) {
 		dev_err(&ofdev->dev, "couldn't get MSCAN clock properties\n");
-		goto exit_free_mscan;
+		goto exit_put_clock;
 	}
 
 	err = register_mscandev(dev, mscan_clksrc);
 	if (err) {
 		dev_err(&ofdev->dev, "registering %s failed (err=%d)\n",
 			DRV_NAME, err);
-		goto exit_free_mscan;
+		goto exit_put_clock;
 	}
 
 	dev_info(&ofdev->dev, "MSCAN at 0x%p, irq %d, clock %d Hz\n",
@@ -340,7 +340,9 @@
 
 	return 0;
 
-exit_free_mscan:
+exit_put_clock:
+	if (data->put_clock)
+		data->put_clock(ofdev);
 	free_candev(dev);
 exit_dispose_irq:
 	irq_dispose_mapping(irq);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/mscan/mscan.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/mscan/mscan.c
@@ -381,13 +381,12 @@
 	struct net_device *dev = napi->dev;
 	struct mscan_regs __iomem *regs = priv->reg_base;
 	struct net_device_stats *stats = &dev->stats;
-	int npackets = 0;
-	int ret = 1;
+	int work_done = 0;
 	struct sk_buff *skb;
 	struct can_frame *frame;
 	u8 canrflg;
 
-	while (npackets < quota) {
+	while (work_done < quota) {
 		canrflg = in_8(&regs->canrflg);
 		if (!(canrflg & (MSCAN_RXF | MSCAN_ERR_IF)))
 			break;
@@ -408,18 +407,18 @@
 
 		stats->rx_packets++;
 		stats->rx_bytes += frame->can_dlc;
-		npackets++;
+		work_done++;
 		netif_receive_skb(skb);
 	}
 
-	if (!(in_8(&regs->canrflg) & (MSCAN_RXF | MSCAN_ERR_IF))) {
-		napi_complete(&priv->napi);
-		clear_bit(F_RX_PROGRESS, &priv->flags);
-		if (priv->can.state < CAN_STATE_BUS_OFF)
-			out_8(&regs->canrier, priv->shadow_canrier);
-		ret = 0;
+	if (work_done < quota) {
+		if (likely(napi_complete_done(&priv->napi, work_done))) {
+			clear_bit(F_RX_PROGRESS, &priv->flags);
+			if (priv->can.state < CAN_STATE_BUS_OFF)
+				out_8(&regs->canrier, priv->shadow_canrier);
+		}
 	}
-	return ret;
+	return work_done;
 }
 
 static irqreturn_t mscan_isr(int irq, void *dev_id)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/pch_can.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/pch_can.c
@@ -489,6 +489,7 @@
 	if (!skb)
 		return;
 
+	errc = ioread32(&priv->regs->errc);
 	if (status & PCH_BUS_OFF) {
 		pch_can_set_tx_all(priv, 0);
 		pch_can_set_rx_all(priv, 0);
@@ -496,9 +497,11 @@
 		cf->can_id |= CAN_ERR_BUSOFF;
 		priv->can.can_stats.bus_off++;
 		can_bus_off(ndev);
+	} else {
+		cf->data[6] = errc & PCH_TEC;
+		cf->data[7] = (errc & PCH_REC) >> 8;
 	}
 
-	errc = ioread32(&priv->regs->errc);
 	/* Warning interrupt. */
 	if (status & PCH_EWARN) {
 		state = CAN_STATE_ERROR_WARNING;
@@ -556,9 +559,6 @@
 		break;
 	}
 
-	cf->data[6] = errc & PCH_TEC;
-	cf->data[7] = (errc & PCH_REC) >> 8;
-
 	priv->can.state = state;
 	netif_receive_skb(skb);
 
@@ -692,11 +692,11 @@
 			cf->data[i + 1] = data_reg >> 8;
 		}
 
-		netif_receive_skb(skb);
 		rcv_pkts++;
 		stats->rx_packets++;
 		quota--;
 		stats->rx_bytes += cf->can_dlc;
+		netif_receive_skb(skb);
 
 		pch_fifo_thresh(priv, obj_num);
 		obj_num++;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/peak_canfd/peak_canfd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/peak_canfd/peak_canfd.c
@@ -232,6 +232,20 @@
 	return pucan_write_cmd(priv);
 }
 
+static int pucan_netif_rx(struct sk_buff *skb, __le32 ts_low, __le32 ts_high)
+{
+	struct skb_shared_hwtstamps *hwts = skb_hwtstamps(skb);
+	u64 ts_us;
+
+	ts_us = (u64)le32_to_cpu(ts_high) << 32;
+	ts_us |= le32_to_cpu(ts_low);
+
+	/* IP core timestamps are µs. */
+	hwts->hwtstamp = ns_to_ktime(ts_us * NSEC_PER_USEC);
+
+	return netif_rx(skb);
+}
+
 /* handle the reception of one CAN frame */
 static int pucan_handle_can_rx(struct peak_canfd_priv *priv,
 			       struct pucan_rx_msg *msg)
@@ -248,8 +262,7 @@
 		cf_len = get_can_dlc(pucan_msg_get_dlc(msg));
 
 	/* if this frame is an echo, */
-	if ((rx_msg_flags & PUCAN_MSG_LOOPED_BACK) &&
-	    !(rx_msg_flags & PUCAN_MSG_SELF_RECEIVE)) {
+	if (rx_msg_flags & PUCAN_MSG_LOOPED_BACK) {
 		unsigned long flags;
 
 		spin_lock_irqsave(&priv->echo_lock, flags);
@@ -263,7 +276,13 @@
 		netif_wake_queue(priv->ndev);
 
 		spin_unlock_irqrestore(&priv->echo_lock, flags);
-		return 0;
+
+		/* if this frame is only an echo, stop here. Otherwise,
+		 * continue to push this application self-received frame into
+		 * its own rx queue.
+		 */
+		if (!(rx_msg_flags & PUCAN_MSG_SELF_RECEIVE))
+			return 0;
 	}
 
 	/* otherwise, it should be pushed into rx fifo */
@@ -299,7 +318,7 @@
 	stats->rx_bytes += cf->len;
 	stats->rx_packets++;
 
-	netif_rx(skb);
+	pucan_netif_rx(skb, msg->ts_low, msg->ts_high);
 
 	return 0;
 }
@@ -333,8 +352,8 @@
 				return err;
 		}
 
-		/* start network queue (echo_skb array is empty) */
-		netif_start_queue(ndev);
+		/* wake network queue up (echo_skb array is empty) */
+		netif_wake_queue(ndev);
 
 		return 0;
 	}
@@ -393,7 +412,7 @@
 
 	stats->rx_packets++;
 	stats->rx_bytes += cf->can_dlc;
-	netif_rx(skb);
+	pucan_netif_rx(skb, msg->ts_low, msg->ts_high);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/rcar/rcar_can.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/rcar/rcar_can.c
@@ -235,11 +235,8 @@
 	if (eifr & (RCAR_CAN_EIFR_EWIF | RCAR_CAN_EIFR_EPIF)) {
 		txerr = readb(&priv->regs->tecr);
 		rxerr = readb(&priv->regs->recr);
-		if (skb) {
+		if (skb)
 			cf->can_id |= CAN_ERR_CRTL;
-			cf->data[6] = txerr;
-			cf->data[7] = rxerr;
-		}
 	}
 	if (eifr & RCAR_CAN_EIFR_BEIF) {
 		int rx_errors = 0, tx_errors = 0;
@@ -339,6 +336,9 @@
 		can_bus_off(ndev);
 		if (skb)
 			cf->can_id |= CAN_ERR_BUSOFF;
+	} else if (skb) {
+		cf->data[6] = txerr;
+		cf->data[7] = rxerr;
 	}
 	if (eifr & RCAR_CAN_EIFR_ORIF) {
 		netdev_dbg(priv->ndev, "Receive overrun error interrupt\n");
@@ -848,10 +848,12 @@
 	struct rcar_can_priv *priv = netdev_priv(ndev);
 	u16 ctlr;
 
-	if (netif_running(ndev)) {
-		netif_stop_queue(ndev);
-		netif_device_detach(ndev);
-	}
+	if (!netif_running(ndev))
+		return 0;
+
+	netif_stop_queue(ndev);
+	netif_device_detach(ndev);
+
 	ctlr = readw(&priv->regs->ctlr);
 	ctlr |= RCAR_CAN_CTLR_CANM_HALT;
 	writew(ctlr, &priv->regs->ctlr);
@@ -870,6 +872,9 @@
 	u16 ctlr;
 	int err;
 
+	if (!netif_running(ndev))
+		return 0;
+
 	err = clk_enable(priv->clk);
 	if (err) {
 		netdev_err(ndev, "clk_enable() failed, error %d\n", err);
@@ -883,10 +888,9 @@
 	writew(ctlr, &priv->regs->ctlr);
 	priv->can.state = CAN_STATE_ERROR_ACTIVE;
 
-	if (netif_running(ndev)) {
-		netif_device_attach(ndev);
-		netif_start_queue(ndev);
-	}
+	netif_device_attach(ndev);
+	netif_start_queue(ndev);
+
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/rcar/rcar_canfd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/rcar/rcar_canfd.c
@@ -1075,7 +1075,7 @@
 	struct rcar_canfd_global *gpriv = dev_id;
 	struct net_device *ndev;
 	struct rcar_canfd_channel *priv;
-	u32 sts, gerfl;
+	u32 sts, cc, gerfl;
 	u32 ch, ridx;
 
 	/* Global error interrupts still indicate a condition specific
@@ -1093,7 +1093,9 @@
 
 		/* Handle Rx interrupts */
 		sts = rcar_canfd_read(priv->base, RCANFD_RFSTS(ridx));
-		if (likely(sts & RCANFD_RFSTS_RFIF)) {
+		cc = rcar_canfd_read(priv->base, RCANFD_RFCC(ridx));
+		if (likely(sts & RCANFD_RFSTS_RFIF &&
+			   cc & RCANFD_RFCC_RFIE)) {
 			if (napi_schedule_prep(&priv->napi)) {
 				/* Disable Rx FIFO interrupts */
 				rcar_canfd_clear_bit(priv->base,
@@ -1598,15 +1600,15 @@
 
 	netif_napi_add(ndev, &priv->napi, rcar_canfd_rx_poll,
 		       RCANFD_NAPI_WEIGHT);
+	spin_lock_init(&priv->tx_lock);
+	devm_can_led_init(ndev);
+	gpriv->ch[priv->channel] = priv;
 	err = register_candev(ndev);
 	if (err) {
 		dev_err(&pdev->dev,
 			"register_candev() failed, error %d\n", err);
 		goto fail_candev;
 	}
-	spin_lock_init(&priv->tx_lock);
-	devm_can_led_init(ndev);
-	gpriv->ch[priv->channel] = priv;
 	dev_info(&pdev->dev, "device registered (channel %u)\n", priv->channel);
 	return 0;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/sja1000/ems_pcmcia.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/sja1000/ems_pcmcia.c
@@ -235,7 +235,12 @@
 			free_sja1000dev(dev);
 	}
 
-	err = request_irq(dev->irq, &ems_pcmcia_interrupt, IRQF_SHARED,
+	if (!card->channels) {
+		err = -ENODEV;
+		goto failure_cleanup;
+	}
+
+	err = request_irq(pdev->irq, &ems_pcmcia_interrupt, IRQF_SHARED,
 			  DRV_NAME, card);
 	if (!err)
 		return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/sja1000/peak_pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/sja1000/peak_pci.c
@@ -731,16 +731,15 @@
 		struct net_device *prev_dev = chan->prev_dev;
 
 		dev_info(&pdev->dev, "removing device %s\n", dev->name);
+		/* do that only for first channel */
+		if (!prev_dev && chan->pciec_card)
+			peak_pciec_remove(chan->pciec_card);
 		unregister_sja1000dev(dev);
 		free_sja1000dev(dev);
 		dev = prev_dev;
 
-		if (!dev) {
-			/* do that only for first channel */
-			if (chan->pciec_card)
-				peak_pciec_remove(chan->pciec_card);
+		if (!dev)
 			break;
-		}
 		priv = netdev_priv(dev);
 		chan = priv->priv;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/sja1000/sja1000.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/sja1000/sja1000.c
@@ -405,9 +405,6 @@
 	txerr = priv->read_reg(priv, SJA1000_TXERR);
 	rxerr = priv->read_reg(priv, SJA1000_RXERR);
 
-	cf->data[6] = txerr;
-	cf->data[7] = rxerr;
-
 	if (isrc & IRQ_DOI) {
 		/* data overrun interrupt */
 		netdev_dbg(dev, "data overrun interrupt\n");
@@ -429,6 +426,10 @@
 		else
 			state = CAN_STATE_ERROR_ACTIVE;
 	}
+	if (state != CAN_STATE_BUS_OFF) {
+		cf->data[6] = txerr;
+		cf->data[7] = rxerr;
+	}
 	if (isrc & IRQ_BEI) {
 		/* bus error interrupt */
 		priv->can.can_stats.bus_error++;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/sja1000/sja1000_isa.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/sja1000/sja1000_isa.c
@@ -202,22 +202,24 @@
 	if (err) {
 		dev_err(&pdev->dev, "registering %s failed (err=%d)\n",
 			DRV_NAME, err);
-		goto exit_unmap;
+		goto exit_free;
 	}
 
 	dev_info(&pdev->dev, "%s device registered (reg_base=0x%p, irq=%d)\n",
 		 DRV_NAME, priv->reg_base, dev->irq);
 	return 0;
 
- exit_unmap:
+exit_free:
+	free_sja1000dev(dev);
+exit_unmap:
 	if (mem[idx])
 		iounmap(base);
- exit_release:
+exit_release:
 	if (mem[idx])
 		release_mem_region(mem[idx], iosize);
 	else
 		release_region(port[idx], iosize);
- exit:
+exit:
 	return err;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/slcan.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/slcan.c
@@ -148,7 +148,7 @@
 	u32 tmpid;
 	char *cmd = sl->rbuff;
 
-	cf.can_id = 0;
+	memset(&cf, 0, sizeof(cf));
 
 	switch (*cmd) {
 	case 'r':
@@ -187,8 +187,6 @@
 	else
 		return;
 
-	*(u64 *) (&cf.data) = 0; /* clear payload */
-
 	/* RTR frames may have a dlc > 0 but they never have any data bytes */
 	if (!(cf.can_id & CAN_RTR_FLAG)) {
 		for (i = 0; i < cf.can_dlc; i++) {
@@ -344,9 +342,16 @@
  */
 static void slcan_write_wakeup(struct tty_struct *tty)
 {
-	struct slcan *sl = tty->disc_data;
+	struct slcan *sl;
+
+	rcu_read_lock();
+	sl = rcu_dereference(tty->disc_data);
+	if (!sl)
+		goto out;
 
 	schedule_work(&sl->tx_work);
+out:
+	rcu_read_unlock();
 }
 
 /* Send a can_frame to a TTY queue. */
@@ -514,6 +519,7 @@
 	int i;
 	char name[IFNAMSIZ];
 	struct net_device *dev = NULL;
+	struct can_ml_priv *can_ml;
 	struct slcan       *sl;
 	int size;
 
@@ -536,7 +542,8 @@
 
 	dev->base_addr  = i;
 	sl = netdev_priv(dev);
-	dev->ml_priv = (void *)sl + ALIGN(sizeof(*sl), NETDEV_ALIGN);
+	can_ml = (void *)sl + ALIGN(sizeof(*sl), NETDEV_ALIGN);
+	can_set_ml_priv(dev, can_ml);
 
 	/* Initialize channel control data */
 	sl->magic = SLCAN_MAGIC;
@@ -617,7 +624,11 @@
 	sl->tty = NULL;
 	tty->disc_data = NULL;
 	clear_bit(SLF_INUSE, &sl->flags);
+	slc_free_netdev(sl->dev);
+	/* do not call free_netdev before rtnl_unlock */
+	rtnl_unlock();
 	free_netdev(sl->dev);
+	return err;
 
 err_exit:
 	rtnl_unlock();
@@ -643,10 +654,11 @@
 		return;
 
 	spin_lock_bh(&sl->lock);
-	tty->disc_data = NULL;
+	rcu_assign_pointer(tty->disc_data, NULL);
 	sl->tty = NULL;
 	spin_unlock_bh(&sl->lock);
 
+	synchronize_rcu();
 	flush_work(&sl->tx_work);
 
 	/* Flush network side */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/softing/softing_cs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/softing/softing_cs.c
@@ -293,7 +293,7 @@
 	return 0;
 
 platform_failed:
-	kfree(dev);
+	platform_device_put(pdev);
 mem_failed:
 pcmcia_bad:
 pcmcia_failed:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/softing/softing_fw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/softing/softing_fw.c
@@ -565,18 +565,19 @@
 		if (ret < 0)
 			goto failed;
 	}
-	/* enable_error_frame */
-	/*
+
+	/* enable_error_frame
+	 *
 	 * Error reporting is switched off at the moment since
 	 * the receiving of them is not yet 100% verified
 	 * This should be enabled sooner or later
-	 *
-	if (error_reporting) {
+	 */
+	if (0 && error_reporting) {
 		ret = softing_fct_cmd(card, 51, "enable_error_frame");
 		if (ret < 0)
 			goto failed;
 	}
-	*/
+
 	/* initialize interface */
 	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 2]);
 	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 4]);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/softing/softing_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/softing/softing_main.c
@@ -382,8 +382,13 @@
 
 	/* check or determine and set bittime */
 	ret = open_candev(ndev);
-	if (!ret)
-		ret = softing_startstop(ndev, 1);
+	if (ret)
+		return ret;
+
+	ret = softing_startstop(ndev, 1);
+	if (ret < 0)
+		close_candev(ndev);
+
 	return ret;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/spi/hi311x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/spi/hi311x.c
@@ -218,7 +218,7 @@
 	return ret;
 }
 
-static u8 hi3110_cmd(struct spi_device *spi, u8 command)
+static int hi3110_cmd(struct spi_device *spi, u8 command)
 {
 	struct hi3110_priv *priv = spi_get_drvdata(spi);
 
@@ -670,20 +670,22 @@
 
 			txerr = hi3110_read(spi, HI3110_READ_TEC);
 			rxerr = hi3110_read(spi, HI3110_READ_REC);
-			cf->data[6] = txerr;
-			cf->data[7] = rxerr;
 			tx_state = txerr >= rxerr ? new_state : 0;
 			rx_state = txerr <= rxerr ? new_state : 0;
 			can_change_state(net, cf, tx_state, rx_state);
-			netif_rx_ni(skb);
 
 			if (new_state == CAN_STATE_BUS_OFF) {
+				netif_rx_ni(skb);
 				can_bus_off(net);
 				if (priv->can.restart_ms == 0) {
 					priv->force_quit = 1;
 					hi3110_hw_sleep(spi);
 					break;
 				}
+			} else {
+				cf->data[6] = txerr;
+				cf->data[7] = rxerr;
+				netif_rx_ni(skb);
 			}
 		}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/spi/mcp251x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/spi/mcp251x.c
@@ -756,9 +756,6 @@
 
 		mcp251x_read_2regs(spi, CANINTF, &intf, &eflag);
 
-		/* mask out flags we don't care about */
-		intf &= CANINTF_RX | CANINTF_TX | CANINTF_ERR;
-
 		/* receive buffer 0 */
 		if (intf & CANINTF_RX0IF) {
 			mcp251x_hw_rx(spi, 0);
@@ -768,6 +765,18 @@
 			if (mcp251x_is_2510(spi))
 				mcp251x_write_bits(spi, CANINTF,
 						   CANINTF_RX0IF, 0x00);
+
+			/* check if buffer 1 is already known to be full, no need to re-read */
+			if (!(intf & CANINTF_RX1IF)) {
+				u8 intf1, eflag1;
+
+				/* intf needs to be read again to avoid a race condition */
+				mcp251x_read_2regs(spi, CANINTF, &intf1, &eflag1);
+
+				/* combine flags from both operations for error handling */
+				intf |= intf1;
+				eflag |= eflag1;
+			}
 		}
 
 		/* receive buffer 1 */
@@ -778,6 +787,9 @@
 				clear_intf |= CANINTF_RX1IF;
 		}
 
+		/* mask out flags we don't care about */
+		intf &= CANINTF_RX | CANINTF_TX | CANINTF_ERR;
+
 		/* any error or tx interrupt we need to clear? */
 		if (intf & (CANINTF_ERR | CANINTF_TX))
 			clear_intf |= intf & (CANINTF_ERR | CANINTF_TX);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/sun4i_can.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/sun4i_can.c
@@ -525,11 +525,6 @@
 	rxerr = (errc >> 16) & 0xFF;
 	txerr = errc & 0xFF;
 
-	if (skb) {
-		cf->data[6] = txerr;
-		cf->data[7] = rxerr;
-	}
-
 	if (isrc & SUN4I_INT_DATA_OR) {
 		/* data overrun interrupt */
 		netdev_dbg(dev, "data overrun interrupt\n");
@@ -560,15 +555,17 @@
 		else
 			state = CAN_STATE_ERROR_ACTIVE;
 	}
+	if (skb && state != CAN_STATE_BUS_OFF) {
+		cf->data[6] = txerr;
+		cf->data[7] = rxerr;
+	}
 	if (isrc & SUN4I_INT_BUS_ERR) {
 		/* bus error interrupt */
 		netdev_dbg(dev, "bus error interrupt\n");
 		priv->can.can_stats.bus_error++;
-		stats->rx_errors++;
+		ecc = readl(priv->base + SUN4I_REG_STA_ADDR);
 
 		if (likely(skb)) {
-			ecc = readl(priv->base + SUN4I_REG_STA_ADDR);
-
 			cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
 
 			switch (ecc & SUN4I_STA_MASK_ERR) {
@@ -586,9 +583,15 @@
 					       >> 16;
 				break;
 			}
-			/* error occurred during transmission? */
-			if ((ecc & SUN4I_STA_ERR_DIR) == 0)
+		}
+
+		/* error occurred during transmission? */
+		if ((ecc & SUN4I_STA_ERR_DIR) == 0) {
+			if (likely(skb))
 				cf->data[2] |= CAN_ERR_PROT_TX;
+			stats->tx_errors++;
+		} else {
+			stats->rx_errors++;
 		}
 	}
 	if (isrc & SUN4I_INT_ERR_PASSIVE) {
@@ -615,10 +618,10 @@
 		tx_state = txerr >= rxerr ? state : 0;
 		rx_state = txerr <= rxerr ? state : 0;
 
-		if (likely(skb))
-			can_change_state(dev, cf, tx_state, rx_state);
-		else
-			priv->can.state = state;
+		/* The skb allocation might fail, but can_change_state()
+		 * handles cf == NULL.
+		 */
+		can_change_state(dev, cf, tx_state, rx_state);
 		if (state == CAN_STATE_BUS_OFF)
 			can_bus_off(dev);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/ti_hecc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/ti_hecc.c
@@ -873,7 +873,8 @@
 	priv->base = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(priv->base)) {
 		dev_err(&pdev->dev, "hecc ioremap failed\n");
-		return PTR_ERR(priv->base);
+		err = PTR_ERR(priv->base);
+		goto probe_exit_candev;
 	}
 
 	/* handle hecc-ram memory */
@@ -886,7 +887,8 @@
 	priv->hecc_ram = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(priv->hecc_ram)) {
 		dev_err(&pdev->dev, "hecc-ram ioremap failed\n");
-		return PTR_ERR(priv->hecc_ram);
+		err = PTR_ERR(priv->hecc_ram);
+		goto probe_exit_candev;
 	}
 
 	/* handle mbx memory */
@@ -899,13 +901,14 @@
 	priv->mbx = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(priv->mbx)) {
 		dev_err(&pdev->dev, "mbx ioremap failed\n");
-		return PTR_ERR(priv->mbx);
+		err = PTR_ERR(priv->mbx);
+		goto probe_exit_candev;
 	}
 
 	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	if (!irq) {
 		dev_err(&pdev->dev, "No irq resource\n");
-		goto probe_exit;
+		goto probe_exit_candev;
 	}
 
 	priv->ndev = ndev;
@@ -936,7 +939,7 @@
 	err = clk_prepare_enable(priv->clk);
 	if (err) {
 		dev_err(&pdev->dev, "clk_prepare_enable() failed\n");
-		goto probe_exit_clk;
+		goto probe_exit_release_clk;
 	}
 
 	priv->offload.mailbox_read = ti_hecc_mailbox_read;
@@ -945,7 +948,7 @@
 	err = can_rx_offload_add_timestamp(ndev, &priv->offload);
 	if (err) {
 		dev_err(&pdev->dev, "can_rx_offload_add_timestamp() failed\n");
-		goto probe_exit_clk;
+		goto probe_exit_disable_clk;
 	}
 
 	err = register_candev(ndev);
@@ -963,11 +966,13 @@
 
 probe_exit_offload:
 	can_rx_offload_del(&priv->offload);
-probe_exit_clk:
+probe_exit_disable_clk:
+	clk_disable_unprepare(priv->clk);
+probe_exit_release_clk:
 	clk_put(priv->clk);
 probe_exit_candev:
 	free_candev(ndev);
-probe_exit:
+
 	return err;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/usb/ems_usb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/usb/ems_usb.c
@@ -194,7 +194,7 @@
 	__le32 ts_sec;	/* timestamp in seconds */
 	__le32 ts_nsec;	/* timestamp in nano seconds */
 
-	union {
+	union __packed {
 		u8 generic[64];
 		struct cpc_can_msg can_msg;
 		struct cpc_can_params can_params;
@@ -255,6 +255,8 @@
 	unsigned int free_slots; /* remember number of available slots */
 
 	struct ems_cpc_msg active_params; /* active controller parameters */
+	void *rxbuf[MAX_RX_URBS];
+	dma_addr_t rxbuf_dma[MAX_RX_URBS];
 };
 
 static void ems_usb_read_interrupt_callback(struct urb *urb)
@@ -587,6 +589,7 @@
 	for (i = 0; i < MAX_RX_URBS; i++) {
 		struct urb *urb = NULL;
 		u8 *buf = NULL;
+		dma_addr_t buf_dma;
 
 		/* create a URB, and a buffer for it */
 		urb = usb_alloc_urb(0, GFP_KERNEL);
@@ -596,7 +599,7 @@
 		}
 
 		buf = usb_alloc_coherent(dev->udev, RX_BUFFER_SIZE, GFP_KERNEL,
-					 &urb->transfer_dma);
+					 &buf_dma);
 		if (!buf) {
 			netdev_err(netdev, "No memory left for USB buffer\n");
 			usb_free_urb(urb);
@@ -604,6 +607,8 @@
 			break;
 		}
 
+		urb->transfer_dma = buf_dma;
+
 		usb_fill_bulk_urb(urb, dev->udev, usb_rcvbulkpipe(dev->udev, 2),
 				  buf, RX_BUFFER_SIZE,
 				  ems_usb_read_bulk_callback, dev);
@@ -619,6 +624,9 @@
 			break;
 		}
 
+		dev->rxbuf[i] = buf;
+		dev->rxbuf_dma[i] = buf_dma;
+
 		/* Drop reference, USB core will take care of freeing it */
 		usb_free_urb(urb);
 	}
@@ -684,6 +692,10 @@
 
 	usb_kill_anchored_urbs(&dev->rx_submitted);
 
+	for (i = 0; i < MAX_RX_URBS; ++i)
+		usb_free_coherent(dev->udev, RX_BUFFER_SIZE,
+				  dev->rxbuf[i], dev->rxbuf_dma[i]);
+
 	usb_kill_anchored_urbs(&dev->tx_submitted);
 	atomic_set(&dev->active_tx_urbs, 0);
 
@@ -811,7 +823,6 @@
 
 		usb_unanchor_urb(urb);
 		usb_free_coherent(dev->udev, size, buf, urb->transfer_dma);
-		dev_kfree_skb(skb);
 
 		atomic_dec(&dev->active_tx_urbs);
 
@@ -1053,7 +1064,6 @@
 
 	if (dev) {
 		unregister_netdev(dev->netdev);
-		free_candev(dev->netdev);
 
 		unlink_all_urbs(dev);
 
@@ -1061,6 +1071,8 @@
 
 		kfree(dev->intr_in_buffer);
 		kfree(dev->tx_msg_buffer);
+
+		free_candev(dev->netdev);
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/usb/esd_usb2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/usb/esd_usb2.c
@@ -195,6 +195,8 @@
 	int net_count;
 	u32 version;
 	int rxinitdone;
+	void *rxbuf[MAX_RX_URBS];
+	dma_addr_t rxbuf_dma[MAX_RX_URBS];
 };
 
 struct esd_usb2_net_priv {
@@ -222,8 +224,12 @@
 	if (id == ESD_EV_CAN_ERROR_EXT) {
 		u8 state = msg->msg.rx.data[0];
 		u8 ecc = msg->msg.rx.data[1];
-		u8 txerr = msg->msg.rx.data[2];
-		u8 rxerr = msg->msg.rx.data[3];
+		u8 rxerr = msg->msg.rx.data[2];
+		u8 txerr = msg->msg.rx.data[3];
+
+		netdev_dbg(priv->netdev,
+			   "CAN_ERR_EV_EXT: dlc=%#02x state=%02x ecc=%02x rec=%02x tec=%02x\n",
+			   msg->msg.rx.dlc, state, ecc, rxerr, txerr);
 
 		skb = alloc_can_err_skb(priv->netdev, &cf);
 		if (skb == NULL) {
@@ -251,6 +257,8 @@
 				break;
 			default:
 				priv->can.state = CAN_STATE_ERROR_ACTIVE;
+				txerr = 0;
+				rxerr = 0;
 				break;
 			}
 		} else {
@@ -270,7 +278,6 @@
 				cf->data[2] |= CAN_ERR_PROT_STUFF;
 				break;
 			default:
-				cf->data[3] = ecc & SJA1000_ECC_SEG;
 				break;
 			}
 
@@ -278,6 +285,9 @@
 			if (!(ecc & SJA1000_ECC_DIR))
 				cf->data[2] |= CAN_ERR_PROT_TX;
 
+			/* Bit stream position in CAN frame as the error was detected */
+			cf->data[3] = ecc & SJA1000_ECC_SEG;
+
 			if (priv->can.state == CAN_STATE_ERROR_WARNING ||
 			    priv->can.state == CAN_STATE_ERROR_PASSIVE) {
 				cf->data[1] = (txerr > rxerr) ?
@@ -544,6 +554,7 @@
 	for (i = 0; i < MAX_RX_URBS; i++) {
 		struct urb *urb = NULL;
 		u8 *buf = NULL;
+		dma_addr_t buf_dma;
 
 		/* create a URB, and a buffer for it */
 		urb = usb_alloc_urb(0, GFP_KERNEL);
@@ -553,7 +564,7 @@
 		}
 
 		buf = usb_alloc_coherent(dev->udev, RX_BUFFER_SIZE, GFP_KERNEL,
-					 &urb->transfer_dma);
+					 &buf_dma);
 		if (!buf) {
 			dev_warn(dev->udev->dev.parent,
 				 "No memory left for USB buffer\n");
@@ -561,6 +572,8 @@
 			goto freeurb;
 		}
 
+		urb->transfer_dma = buf_dma;
+
 		usb_fill_bulk_urb(urb, dev->udev,
 				  usb_rcvbulkpipe(dev->udev, 1),
 				  buf, RX_BUFFER_SIZE,
@@ -573,8 +586,12 @@
 			usb_unanchor_urb(urb);
 			usb_free_coherent(dev->udev, RX_BUFFER_SIZE, buf,
 					  urb->transfer_dma);
+			goto freeurb;
 		}
 
+		dev->rxbuf[i] = buf;
+		dev->rxbuf_dma[i] = buf_dma;
+
 freeurb:
 		/* Drop reference, USB core will take care of freeing it */
 		usb_free_urb(urb);
@@ -662,6 +679,11 @@
 	int i, j;
 
 	usb_kill_anchored_urbs(&dev->rx_submitted);
+
+	for (i = 0; i < MAX_RX_URBS; ++i)
+		usb_free_coherent(dev->udev, RX_BUFFER_SIZE,
+				  dev->rxbuf[i], dev->rxbuf_dma[i]);
+
 	for (i = 0; i < dev->net_count; i++) {
 		priv = dev->nets[i];
 		if (priv) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/usb/gs_usb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/usb/gs_usb.c
@@ -63,21 +63,27 @@
 };
 
 /* data types passed between host and device */
+
+/* The firmware on the original USB2CAN by Geschwister Schneider
+ * Technologie Entwicklungs- und Vertriebs UG exchanges all data
+ * between the host and the device in host byte order. This is done
+ * with the struct gs_host_config::byte_order member, which is sent
+ * first to indicate the desired byte order.
+ *
+ * The widely used open source firmware candleLight doesn't support
+ * this feature and exchanges the data in little endian byte order.
+ */
 struct gs_host_config {
-	u32 byte_order;
+	__le32 byte_order;
 } __packed;
-/* All data exchanged between host and device is exchanged in host byte order,
- * thanks to the struct gs_host_config byte_order member, which is sent first
- * to indicate the desired byte order.
- */
 
 struct gs_device_config {
 	u8 reserved1;
 	u8 reserved2;
 	u8 reserved3;
 	u8 icount;
-	u32 sw_version;
-	u32 hw_version;
+	__le32 sw_version;
+	__le32 hw_version;
 } __packed;
 
 #define GS_CAN_MODE_NORMAL               0
@@ -87,26 +93,26 @@
 #define GS_CAN_MODE_ONE_SHOT             BIT(3)
 
 struct gs_device_mode {
-	u32 mode;
-	u32 flags;
+	__le32 mode;
+	__le32 flags;
 } __packed;
 
 struct gs_device_state {
-	u32 state;
-	u32 rxerr;
-	u32 txerr;
+	__le32 state;
+	__le32 rxerr;
+	__le32 txerr;
 } __packed;
 
 struct gs_device_bittiming {
-	u32 prop_seg;
-	u32 phase_seg1;
-	u32 phase_seg2;
-	u32 sjw;
-	u32 brp;
+	__le32 prop_seg;
+	__le32 phase_seg1;
+	__le32 phase_seg2;
+	__le32 sjw;
+	__le32 brp;
 } __packed;
 
 struct gs_identify_mode {
-	u32 mode;
+	__le32 mode;
 } __packed;
 
 #define GS_CAN_FEATURE_LISTEN_ONLY      BIT(0)
@@ -117,23 +123,23 @@
 #define GS_CAN_FEATURE_IDENTIFY         BIT(5)
 
 struct gs_device_bt_const {
-	u32 feature;
-	u32 fclk_can;
-	u32 tseg1_min;
-	u32 tseg1_max;
-	u32 tseg2_min;
-	u32 tseg2_max;
-	u32 sjw_max;
-	u32 brp_min;
-	u32 brp_max;
-	u32 brp_inc;
+	__le32 feature;
+	__le32 fclk_can;
+	__le32 tseg1_min;
+	__le32 tseg1_max;
+	__le32 tseg2_min;
+	__le32 tseg2_max;
+	__le32 sjw_max;
+	__le32 brp_min;
+	__le32 brp_max;
+	__le32 brp_inc;
 } __packed;
 
 #define GS_CAN_FLAG_OVERFLOW 1
 
 struct gs_host_frame {
 	u32 echo_id;
-	u32 can_id;
+	__le32 can_id;
 
 	u8 can_dlc;
 	u8 channel;
@@ -178,14 +184,16 @@
 
 	struct usb_anchor tx_submitted;
 	atomic_t active_tx_urbs;
+	void *rxbuf[GS_MAX_RX_URBS];
+	dma_addr_t rxbuf_dma[GS_MAX_RX_URBS];
 };
 
 /* usb interface struct */
 struct gs_usb {
 	struct gs_can *canch[GS_MAX_INTF];
 	struct usb_anchor rx_submitted;
-	atomic_t active_channels;
 	struct usb_device *udev;
+	u8 active_channels;
 };
 
 /* 'allocate' a tx context.
@@ -314,7 +322,7 @@
 
 	/* device reports out of range channel id */
 	if (hf->channel >= GS_MAX_INTF)
-		goto resubmit_urb;
+		goto device_detach;
 
 	dev = usbcan->canch[hf->channel];
 
@@ -329,13 +337,13 @@
 		if (!skb)
 			return;
 
-		cf->can_id = hf->can_id;
+		cf->can_id = le32_to_cpu(hf->can_id);
 
 		cf->can_dlc = get_can_dlc(hf->can_dlc);
 		memcpy(cf->data, hf->data, 8);
 
 		/* ERROR frames tell us information about the controller */
-		if (hf->can_id & CAN_ERR_FLAG)
+		if (le32_to_cpu(hf->can_id) & CAN_ERR_FLAG)
 			gs_update_state(dev, cf);
 
 		netdev->stats.rx_packets++;
@@ -373,6 +381,9 @@
 	}
 
 	if (hf->flags & GS_CAN_FLAG_OVERFLOW) {
+		stats->rx_over_errors++;
+		stats->rx_errors++;
+
 		skb = alloc_can_err_skb(netdev, &cf);
 		if (!skb)
 			goto resubmit_urb;
@@ -380,8 +391,6 @@
 		cf->can_id |= CAN_ERR_CRTL;
 		cf->can_dlc = CAN_ERR_DLC;
 		cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
-		stats->rx_over_errors++;
-		stats->rx_errors++;
 		netif_rx(skb);
 	}
 
@@ -399,6 +408,7 @@
 
 	/* USB failure take down all interfaces */
 	if (rc == -ENODEV) {
+ device_detach:
 		for (rc = 0; rc < GS_MAX_INTF; rc++) {
 			if (usbcan->canch[rc])
 				netif_device_detach(usbcan->canch[rc]->netdev);
@@ -418,11 +428,11 @@
 	if (!dbt)
 		return -ENOMEM;
 
-	dbt->prop_seg = bt->prop_seg;
-	dbt->phase_seg1 = bt->phase_seg1;
-	dbt->phase_seg2 = bt->phase_seg2;
-	dbt->sjw = bt->sjw;
-	dbt->brp = bt->brp;
+	dbt->prop_seg = cpu_to_le32(bt->prop_seg);
+	dbt->phase_seg1 = cpu_to_le32(bt->phase_seg1);
+	dbt->phase_seg2 = cpu_to_le32(bt->phase_seg2);
+	dbt->sjw = cpu_to_le32(bt->sjw);
+	dbt->brp = cpu_to_le32(bt->brp);
 
 	/* request bit timings */
 	rc = usb_control_msg(interface_to_usbdev(intf),
@@ -500,10 +510,12 @@
 
 	hf->echo_id = idx;
 	hf->channel = dev->channel;
+	hf->flags = 0;
+	hf->reserved = 0;
 
 	cf = (struct can_frame *)skb->data;
 
-	hf->can_id = cf->can_id;
+	hf->can_id = cpu_to_le32(cf->can_id);
 	hf->can_dlc = cf->can_dlc;
 	memcpy(hf->data, cf->data, cf->can_dlc);
 
@@ -573,15 +585,17 @@
 	int rc, i;
 	struct gs_device_mode *dm;
 	u32 ctrlmode;
+	u32 flags = 0;
 
 	rc = open_candev(netdev);
 	if (rc)
 		return rc;
 
-	if (atomic_add_return(1, &parent->active_channels) == 1) {
+	if (!parent->active_channels) {
 		for (i = 0; i < GS_MAX_RX_URBS; i++) {
 			struct urb *urb;
 			u8 *buf;
+			dma_addr_t buf_dma;
 
 			/* alloc rx urb */
 			urb = usb_alloc_urb(0, GFP_KERNEL);
@@ -592,7 +606,7 @@
 			buf = usb_alloc_coherent(dev->udev,
 						 sizeof(struct gs_host_frame),
 						 GFP_KERNEL,
-						 &urb->transfer_dma);
+						 &buf_dma);
 			if (!buf) {
 				netdev_err(netdev,
 					   "No memory left for USB buffer\n");
@@ -600,6 +614,8 @@
 				return -ENOMEM;
 			}
 
+			urb->transfer_dma = buf_dma;
+
 			/* fill, anchor, and submit rx urb */
 			usb_fill_bulk_urb(urb,
 					  dev->udev,
@@ -623,10 +639,17 @@
 					   rc);
 
 				usb_unanchor_urb(urb);
+				usb_free_coherent(dev->udev,
+						  sizeof(struct gs_host_frame),
+						  buf,
+						  buf_dma);
 				usb_free_urb(urb);
 				break;
 			}
 
+			dev->rxbuf[i] = buf;
+			dev->rxbuf_dma[i] = buf_dma;
+
 			/* Drop reference,
 			 * USB core will take care of freeing it
 			 */
@@ -640,24 +663,25 @@
 
 	/* flags */
 	ctrlmode = dev->can.ctrlmode;
-	dm->flags = 0;
 
 	if (ctrlmode & CAN_CTRLMODE_LOOPBACK)
-		dm->flags |= GS_CAN_MODE_LOOP_BACK;
+		flags |= GS_CAN_MODE_LOOP_BACK;
 	else if (ctrlmode & CAN_CTRLMODE_LISTENONLY)
-		dm->flags |= GS_CAN_MODE_LISTEN_ONLY;
+		flags |= GS_CAN_MODE_LISTEN_ONLY;
 
 	/* Controller is not allowed to retry TX
 	 * this mode is unavailable on atmels uc3c hardware
 	 */
 	if (ctrlmode & CAN_CTRLMODE_ONE_SHOT)
-		dm->flags |= GS_CAN_MODE_ONE_SHOT;
+		flags |= GS_CAN_MODE_ONE_SHOT;
 
 	if (ctrlmode & CAN_CTRLMODE_3_SAMPLES)
-		dm->flags |= GS_CAN_MODE_TRIPLE_SAMPLE;
+		flags |= GS_CAN_MODE_TRIPLE_SAMPLE;
 
 	/* finally start device */
-	dm->mode = GS_CAN_MODE_START;
+	dev->can.state = CAN_STATE_ERROR_ACTIVE;
+	dm->mode = cpu_to_le32(GS_CAN_MODE_START);
+	dm->flags = cpu_to_le32(flags);
 	rc = usb_control_msg(interface_to_usbdev(dev->iface),
 			     usb_sndctrlpipe(interface_to_usbdev(dev->iface), 0),
 			     GS_USB_BREQ_MODE,
@@ -672,13 +696,13 @@
 	if (rc < 0) {
 		netdev_err(netdev, "Couldn't start device (err=%d)\n", rc);
 		kfree(dm);
+		dev->can.state = CAN_STATE_STOPPED;
 		return rc;
 	}
 
 	kfree(dm);
 
-	dev->can.state = CAN_STATE_ERROR_ACTIVE;
-
+	parent->active_channels++;
 	if (!(dev->can.ctrlmode & CAN_CTRLMODE_LISTENONLY))
 		netif_start_queue(netdev);
 
@@ -690,17 +714,27 @@
 	int rc;
 	struct gs_can *dev = netdev_priv(netdev);
 	struct gs_usb *parent = dev->parent;
+	unsigned int i;
 
 	netif_stop_queue(netdev);
 
 	/* Stop polling */
-	if (atomic_dec_and_test(&parent->active_channels))
+	parent->active_channels--;
+	if (!parent->active_channels) {
 		usb_kill_anchored_urbs(&parent->rx_submitted);
+		for (i = 0; i < GS_MAX_RX_URBS; i++)
+			usb_free_coherent(dev->udev,
+					  sizeof(struct gs_host_frame),
+					  dev->rxbuf[i],
+					  dev->rxbuf_dma[i]);
+	}
 
 	/* Stop sending URBs */
 	usb_kill_anchored_urbs(&dev->tx_submitted);
 	atomic_set(&dev->active_tx_urbs, 0);
 
+	dev->can.state = CAN_STATE_STOPPED;
+
 	/* reset the device */
 	rc = gs_cmd_reset(dev);
 	if (rc < 0)
@@ -737,9 +771,9 @@
 		return -ENOMEM;
 
 	if (do_identify)
-		imode->mode = GS_CAN_IDENTIFY_ON;
+		imode->mode = cpu_to_le32(GS_CAN_IDENTIFY_ON);
 	else
-		imode->mode = GS_CAN_IDENTIFY_OFF;
+		imode->mode = cpu_to_le32(GS_CAN_IDENTIFY_OFF);
 
 	rc = usb_control_msg(interface_to_usbdev(dev->iface),
 			     usb_sndctrlpipe(interface_to_usbdev(dev->iface),
@@ -790,6 +824,7 @@
 	struct net_device *netdev;
 	int rc;
 	struct gs_device_bt_const *bt_const;
+	u32 feature;
 
 	bt_const = kmalloc(sizeof(*bt_const), GFP_KERNEL);
 	if (!bt_const)
@@ -830,14 +865,14 @@
 
 	/* dev settup */
 	strcpy(dev->bt_const.name, "gs_usb");
-	dev->bt_const.tseg1_min = bt_const->tseg1_min;
-	dev->bt_const.tseg1_max = bt_const->tseg1_max;
-	dev->bt_const.tseg2_min = bt_const->tseg2_min;
-	dev->bt_const.tseg2_max = bt_const->tseg2_max;
-	dev->bt_const.sjw_max = bt_const->sjw_max;
-	dev->bt_const.brp_min = bt_const->brp_min;
-	dev->bt_const.brp_max = bt_const->brp_max;
-	dev->bt_const.brp_inc = bt_const->brp_inc;
+	dev->bt_const.tseg1_min = le32_to_cpu(bt_const->tseg1_min);
+	dev->bt_const.tseg1_max = le32_to_cpu(bt_const->tseg1_max);
+	dev->bt_const.tseg2_min = le32_to_cpu(bt_const->tseg2_min);
+	dev->bt_const.tseg2_max = le32_to_cpu(bt_const->tseg2_max);
+	dev->bt_const.sjw_max = le32_to_cpu(bt_const->sjw_max);
+	dev->bt_const.brp_min = le32_to_cpu(bt_const->brp_min);
+	dev->bt_const.brp_max = le32_to_cpu(bt_const->brp_max);
+	dev->bt_const.brp_inc = le32_to_cpu(bt_const->brp_inc);
 
 	dev->udev = interface_to_usbdev(intf);
 	dev->iface = intf;
@@ -854,28 +889,29 @@
 
 	/* can settup */
 	dev->can.state = CAN_STATE_STOPPED;
-	dev->can.clock.freq = bt_const->fclk_can;
+	dev->can.clock.freq = le32_to_cpu(bt_const->fclk_can);
 	dev->can.bittiming_const = &dev->bt_const;
 	dev->can.do_set_bittiming = gs_usb_set_bittiming;
 
 	dev->can.ctrlmode_supported = 0;
 
-	if (bt_const->feature & GS_CAN_FEATURE_LISTEN_ONLY)
+	feature = le32_to_cpu(bt_const->feature);
+	if (feature & GS_CAN_FEATURE_LISTEN_ONLY)
 		dev->can.ctrlmode_supported |= CAN_CTRLMODE_LISTENONLY;
 
-	if (bt_const->feature & GS_CAN_FEATURE_LOOP_BACK)
+	if (feature & GS_CAN_FEATURE_LOOP_BACK)
 		dev->can.ctrlmode_supported |= CAN_CTRLMODE_LOOPBACK;
 
-	if (bt_const->feature & GS_CAN_FEATURE_TRIPLE_SAMPLE)
+	if (feature & GS_CAN_FEATURE_TRIPLE_SAMPLE)
 		dev->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES;
 
-	if (bt_const->feature & GS_CAN_FEATURE_ONE_SHOT)
+	if (feature & GS_CAN_FEATURE_ONE_SHOT)
 		dev->can.ctrlmode_supported |= CAN_CTRLMODE_ONE_SHOT;
 
 	SET_NETDEV_DEV(netdev, &intf->dev);
 
-	if (dconf->sw_version > 1)
-		if (bt_const->feature & GS_CAN_FEATURE_IDENTIFY)
+	if (le32_to_cpu(dconf->sw_version) > 1)
+		if (feature & GS_CAN_FEATURE_IDENTIFY)
 			netdev->ethtool_ops = &gs_usb_ethtool_ops;
 
 	kfree(bt_const);
@@ -910,7 +946,7 @@
 	if (!hconf)
 		return -ENOMEM;
 
-	hconf->byte_order = 0x0000beef;
+	hconf->byte_order = cpu_to_le32(0x0000beef);
 
 	/* send host config */
 	rc = usb_control_msg(interface_to_usbdev(intf),
@@ -918,7 +954,7 @@
 			     GS_USB_BREQ_HOST_FORMAT,
 			     USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
 			     1,
-			     intf->altsetting[0].desc.bInterfaceNumber,
+			     intf->cur_altsetting->desc.bInterfaceNumber,
 			     hconf,
 			     sizeof(*hconf),
 			     1000);
@@ -941,7 +977,7 @@
 			     GS_USB_BREQ_DEVICE_CONFIG,
 			     USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
 			     1,
-			     intf->altsetting[0].desc.bInterfaceNumber,
+			     intf->cur_altsetting->desc.bInterfaceNumber,
 			     dconf,
 			     sizeof(*dconf),
 			     1000);
@@ -971,8 +1007,6 @@
 
 	init_usb_anchor(&dev->rx_submitted);
 
-	atomic_set(&dev->active_channels, 0);
-
 	usb_set_intfdata(intf, dev);
 	dev->udev = interface_to_usbdev(intf);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/usb/kvaser_usb/kvaser_usb.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/usb/kvaser_usb/kvaser_usb.h
@@ -35,9 +35,10 @@
 #define KVASER_USB_RX_BUFFER_SIZE		3072
 #define KVASER_USB_MAX_NET_DEVICES		5
 
-/* USB devices features */
-#define KVASER_USB_HAS_SILENT_MODE		BIT(0)
-#define KVASER_USB_HAS_TXRX_ERRORS		BIT(1)
+/* Kvaser USB device quirks */
+#define KVASER_USB_QUIRK_HAS_SILENT_MODE	BIT(0)
+#define KVASER_USB_QUIRK_HAS_TXRX_ERRORS	BIT(1)
+#define KVASER_USB_QUIRK_IGNORE_CLK_FREQ	BIT(2)
 
 /* Device capabilities */
 #define KVASER_USB_CAP_BERR_CAP			0x01
@@ -65,12 +66,7 @@
 struct kvaser_usb_dev_card_data {
 	u32 ctrlmode_supported;
 	u32 capabilities;
-	union {
-		struct {
-			enum kvaser_usb_leaf_family family;
-		} leaf;
-		struct kvaser_usb_dev_card_data_hydra hydra;
-	};
+	struct kvaser_usb_dev_card_data_hydra hydra;
 };
 
 /* Context for an outstanding, not yet ACKed, transmission */
@@ -80,11 +76,19 @@
 	int dlc;
 };
 
+struct kvaser_usb_busparams {
+	__le32 bitrate;
+	u8 tseg1;
+	u8 tseg2;
+	u8 sjw;
+	u8 nsamples;
+} __packed;
+
 struct kvaser_usb {
 	struct usb_device *udev;
 	struct usb_interface *intf;
 	struct kvaser_usb_net_priv *nets[KVASER_USB_MAX_NET_DEVICES];
-	const struct kvaser_usb_dev_ops *ops;
+	const struct kvaser_usb_driver_info *driver_info;
 	const struct kvaser_usb_dev_cfg *cfg;
 
 	struct usb_endpoint_descriptor *bulk_in, *bulk_out;
@@ -108,13 +112,19 @@
 	struct can_priv can;
 	struct can_berr_counter bec;
 
+	/* subdriver-specific data */
+	void *sub_priv;
+
 	struct kvaser_usb *dev;
 	struct net_device *netdev;
 	int channel;
 
-	struct completion start_comp, stop_comp, flush_comp;
+	struct completion start_comp, stop_comp, flush_comp,
+			  get_busparams_comp;
 	struct usb_anchor tx_submitted;
 
+	struct kvaser_usb_busparams busparams_nominal, busparams_data;
+
 	spinlock_t tx_contexts_lock; /* lock for active_tx_contexts */
 	int active_tx_contexts;
 	struct kvaser_usb_tx_urb_context tx_contexts[];
@@ -124,11 +134,15 @@
  * struct kvaser_usb_dev_ops - Device specific functions
  * @dev_set_mode:		used for can.do_set_mode
  * @dev_set_bittiming:		used for can.do_set_bittiming
+ * @dev_get_busparams:		readback arbitration busparams
  * @dev_set_data_bittiming:	used for can.do_set_data_bittiming
+ * @dev_get_data_busparams:	readback data busparams
  * @dev_get_berr_counter:	used for can.do_get_berr_counter
  *
  * @dev_setup_endpoints:	setup USB in and out endpoints
  * @dev_init_card:		initialize card
+ * @dev_init_channel:		initialize channel
+ * @dev_remove_channel:		uninitialize channel
  * @dev_get_software_info:	get software info
  * @dev_get_software_details:	get software details
  * @dev_get_card_info:		get card info
@@ -144,12 +158,18 @@
  */
 struct kvaser_usb_dev_ops {
 	int (*dev_set_mode)(struct net_device *netdev, enum can_mode mode);
-	int (*dev_set_bittiming)(struct net_device *netdev);
-	int (*dev_set_data_bittiming)(struct net_device *netdev);
+	int (*dev_set_bittiming)(const struct net_device *netdev,
+				 const struct kvaser_usb_busparams *busparams);
+	int (*dev_get_busparams)(struct kvaser_usb_net_priv *priv);
+	int (*dev_set_data_bittiming)(const struct net_device *netdev,
+				      const struct kvaser_usb_busparams *busparams);
+	int (*dev_get_data_busparams)(struct kvaser_usb_net_priv *priv);
 	int (*dev_get_berr_counter)(const struct net_device *netdev,
 				    struct can_berr_counter *bec);
 	int (*dev_setup_endpoints)(struct kvaser_usb *dev);
 	int (*dev_init_card)(struct kvaser_usb *dev);
+	int (*dev_init_channel)(struct kvaser_usb_net_priv *priv);
+	void (*dev_remove_channel)(struct kvaser_usb_net_priv *priv);
 	int (*dev_get_software_info)(struct kvaser_usb *dev);
 	int (*dev_get_software_details)(struct kvaser_usb *dev);
 	int (*dev_get_card_info)(struct kvaser_usb *dev);
@@ -166,6 +186,12 @@
 				  int *cmd_len, u16 transid);
 };
 
+struct kvaser_usb_driver_info {
+	u32 quirks;
+	enum kvaser_usb_leaf_family family;
+	const struct kvaser_usb_dev_ops *ops;
+};
+
 struct kvaser_usb_dev_cfg {
 	const struct can_clock clock;
 	const unsigned int timestamp_freq;
@@ -176,6 +202,8 @@
 extern const struct kvaser_usb_dev_ops kvaser_usb_hydra_dev_ops;
 extern const struct kvaser_usb_dev_ops kvaser_usb_leaf_dev_ops;
 
+void kvaser_usb_unlink_tx_urbs(struct kvaser_usb_net_priv *priv);
+
 int kvaser_usb_recv_cmd(const struct kvaser_usb *dev, void *cmd, int len,
 			int *actual_len);
 
@@ -185,4 +213,7 @@
 			      int len);
 
 int kvaser_usb_can_rx_over_error(struct net_device *netdev);
+
+extern const struct can_bittiming_const kvaser_usb_flexc_bittiming_const;
+
 #endif /* KVASER_USB_H */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
@@ -79,104 +79,135 @@
 #define USB_ATI_MEMO_PRO_2HS_V2_PRODUCT_ID	269
 #define USB_HYBRID_PRO_CANLIN_PRODUCT_ID	270
 
-static inline bool kvaser_is_leaf(const struct usb_device_id *id)
-{
-	return (id->idProduct >= USB_LEAF_DEVEL_PRODUCT_ID &&
-		id->idProduct <= USB_CAN_R_PRODUCT_ID) ||
-		(id->idProduct >= USB_LEAF_LITE_V2_PRODUCT_ID &&
-		 id->idProduct <= USB_MINI_PCIE_2HS_PRODUCT_ID);
-}
+static const struct kvaser_usb_driver_info kvaser_usb_driver_info_hydra = {
+	.quirks = 0,
+	.ops = &kvaser_usb_hydra_dev_ops,
+};
 
-static inline bool kvaser_is_usbcan(const struct usb_device_id *id)
-{
-	return id->idProduct >= USB_USBCAN_REVB_PRODUCT_ID &&
-	       id->idProduct <= USB_MEMORATOR_PRODUCT_ID;
-}
+static const struct kvaser_usb_driver_info kvaser_usb_driver_info_usbcan = {
+	.quirks = KVASER_USB_QUIRK_HAS_TXRX_ERRORS |
+		  KVASER_USB_QUIRK_HAS_SILENT_MODE,
+	.family = KVASER_USBCAN,
+	.ops = &kvaser_usb_leaf_dev_ops,
+};
 
-static inline bool kvaser_is_hydra(const struct usb_device_id *id)
-{
-	return id->idProduct >= USB_BLACKBIRD_V2_PRODUCT_ID &&
-	       id->idProduct <= USB_HYBRID_PRO_CANLIN_PRODUCT_ID;
-}
+static const struct kvaser_usb_driver_info kvaser_usb_driver_info_leaf = {
+	.quirks = KVASER_USB_QUIRK_IGNORE_CLK_FREQ,
+	.family = KVASER_LEAF,
+	.ops = &kvaser_usb_leaf_dev_ops,
+};
+
+static const struct kvaser_usb_driver_info kvaser_usb_driver_info_leaf_err = {
+	.quirks = KVASER_USB_QUIRK_HAS_TXRX_ERRORS |
+		  KVASER_USB_QUIRK_IGNORE_CLK_FREQ,
+	.family = KVASER_LEAF,
+	.ops = &kvaser_usb_leaf_dev_ops,
+};
+
+static const struct kvaser_usb_driver_info kvaser_usb_driver_info_leaf_err_listen = {
+	.quirks = KVASER_USB_QUIRK_HAS_TXRX_ERRORS |
+		  KVASER_USB_QUIRK_HAS_SILENT_MODE |
+		  KVASER_USB_QUIRK_IGNORE_CLK_FREQ,
+	.family = KVASER_LEAF,
+	.ops = &kvaser_usb_leaf_dev_ops,
+};
+
+static const struct kvaser_usb_driver_info kvaser_usb_driver_info_leafimx = {
+	.quirks = 0,
+	.family = KVASER_LEAF,
+	.ops = &kvaser_usb_leaf_dev_ops,
+};
 
 static const struct usb_device_id kvaser_usb_table[] = {
-	/* Leaf USB product IDs */
-	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_DEVEL_PRODUCT_ID) },
-	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_PRODUCT_ID) },
+	/* Leaf M32C USB product IDs */
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_DEVEL_PRODUCT_ID),
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_PRODUCT_ID),
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
 	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_PRODUCT_ID),
-		.driver_info = KVASER_USB_HAS_TXRX_ERRORS |
-			       KVASER_USB_HAS_SILENT_MODE },
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
 	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_PRODUCT_ID),
-		.driver_info = KVASER_USB_HAS_TXRX_ERRORS |
-			       KVASER_USB_HAS_SILENT_MODE },
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
 	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_LS_PRODUCT_ID),
-		.driver_info = KVASER_USB_HAS_TXRX_ERRORS |
-			       KVASER_USB_HAS_SILENT_MODE },
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
 	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_SWC_PRODUCT_ID),
-		.driver_info = KVASER_USB_HAS_TXRX_ERRORS |
-			       KVASER_USB_HAS_SILENT_MODE },
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
 	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_LIN_PRODUCT_ID),
-		.driver_info = KVASER_USB_HAS_TXRX_ERRORS |
-			       KVASER_USB_HAS_SILENT_MODE },
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
 	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_LS_PRODUCT_ID),
-		.driver_info = KVASER_USB_HAS_TXRX_ERRORS |
-			       KVASER_USB_HAS_SILENT_MODE },
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
 	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_SWC_PRODUCT_ID),
-		.driver_info = KVASER_USB_HAS_TXRX_ERRORS |
-			       KVASER_USB_HAS_SILENT_MODE },
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
 	{ USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO2_DEVEL_PRODUCT_ID),
-		.driver_info = KVASER_USB_HAS_TXRX_ERRORS |
-			       KVASER_USB_HAS_SILENT_MODE },
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
 	{ USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO2_HSHS_PRODUCT_ID),
-		.driver_info = KVASER_USB_HAS_TXRX_ERRORS |
-			       KVASER_USB_HAS_SILENT_MODE },
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
 	{ USB_DEVICE(KVASER_VENDOR_ID, USB_UPRO_HSHS_PRODUCT_ID),
-		.driver_info = KVASER_USB_HAS_TXRX_ERRORS },
-	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_GI_PRODUCT_ID) },
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_GI_PRODUCT_ID),
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf },
 	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_OBDII_PRODUCT_ID),
-		.driver_info = KVASER_USB_HAS_TXRX_ERRORS |
-			       KVASER_USB_HAS_SILENT_MODE },
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err_listen },
 	{ USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO2_HSLS_PRODUCT_ID),
-		.driver_info = KVASER_USB_HAS_TXRX_ERRORS },
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err },
 	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_CH_PRODUCT_ID),
-		.driver_info = KVASER_USB_HAS_TXRX_ERRORS },
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err },
 	{ USB_DEVICE(KVASER_VENDOR_ID, USB_BLACKBIRD_SPRO_PRODUCT_ID),
-		.driver_info = KVASER_USB_HAS_TXRX_ERRORS },
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err },
 	{ USB_DEVICE(KVASER_VENDOR_ID, USB_OEM_MERCURY_PRODUCT_ID),
-		.driver_info = KVASER_USB_HAS_TXRX_ERRORS },
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err },
 	{ USB_DEVICE(KVASER_VENDOR_ID, USB_OEM_LEAF_PRODUCT_ID),
-		.driver_info = KVASER_USB_HAS_TXRX_ERRORS },
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err },
 	{ USB_DEVICE(KVASER_VENDOR_ID, USB_CAN_R_PRODUCT_ID),
-		.driver_info = KVASER_USB_HAS_TXRX_ERRORS },
-	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_V2_PRODUCT_ID) },
-	{ USB_DEVICE(KVASER_VENDOR_ID, USB_MINI_PCIE_HS_PRODUCT_ID) },
-	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LIGHT_HS_V2_OEM_PRODUCT_ID) },
-	{ USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_LIGHT_2HS_PRODUCT_ID) },
-	{ USB_DEVICE(KVASER_VENDOR_ID, USB_MINI_PCIE_2HS_PRODUCT_ID) },
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leaf_err },
+
+	/* Leaf i.MX28 USB product IDs */
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_V2_PRODUCT_ID),
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leafimx },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_MINI_PCIE_HS_PRODUCT_ID),
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leafimx },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LIGHT_HS_V2_OEM_PRODUCT_ID),
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leafimx },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_LIGHT_2HS_PRODUCT_ID),
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leafimx },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_MINI_PCIE_2HS_PRODUCT_ID),
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_leafimx },
 
 	/* USBCANII USB product IDs */
 	{ USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN2_PRODUCT_ID),
-		.driver_info = KVASER_USB_HAS_TXRX_ERRORS },
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_usbcan },
 	{ USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_REVB_PRODUCT_ID),
-		.driver_info = KVASER_USB_HAS_TXRX_ERRORS },
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_usbcan },
 	{ USB_DEVICE(KVASER_VENDOR_ID, USB_MEMORATOR_PRODUCT_ID),
-		.driver_info = KVASER_USB_HAS_TXRX_ERRORS },
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_usbcan },
 	{ USB_DEVICE(KVASER_VENDOR_ID, USB_VCI2_PRODUCT_ID),
-		.driver_info = KVASER_USB_HAS_TXRX_ERRORS },
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_usbcan },
 
 	/* Minihydra USB product IDs */
-	{ USB_DEVICE(KVASER_VENDOR_ID, USB_BLACKBIRD_V2_PRODUCT_ID) },
-	{ USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO_PRO_5HS_PRODUCT_ID) },
-	{ USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_PRO_5HS_PRODUCT_ID) },
-	{ USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_LIGHT_4HS_PRODUCT_ID) },
-	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_HS_V2_PRODUCT_ID) },
-	{ USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_PRO_2HS_V2_PRODUCT_ID) },
-	{ USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO_2HS_PRODUCT_ID) },
-	{ USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO_PRO_2HS_V2_PRODUCT_ID) },
-	{ USB_DEVICE(KVASER_VENDOR_ID, USB_HYBRID_CANLIN_PRODUCT_ID) },
-	{ USB_DEVICE(KVASER_VENDOR_ID, USB_ATI_USBCAN_PRO_2HS_V2_PRODUCT_ID) },
-	{ USB_DEVICE(KVASER_VENDOR_ID, USB_ATI_MEMO_PRO_2HS_V2_PRODUCT_ID) },
-	{ USB_DEVICE(KVASER_VENDOR_ID, USB_HYBRID_PRO_CANLIN_PRODUCT_ID) },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_BLACKBIRD_V2_PRODUCT_ID),
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO_PRO_5HS_PRODUCT_ID),
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_PRO_5HS_PRODUCT_ID),
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_LIGHT_4HS_PRODUCT_ID),
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_HS_V2_PRODUCT_ID),
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_USBCAN_PRO_2HS_V2_PRODUCT_ID),
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO_2HS_PRODUCT_ID),
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO_PRO_2HS_V2_PRODUCT_ID),
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_HYBRID_CANLIN_PRODUCT_ID),
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_ATI_USBCAN_PRO_2HS_V2_PRODUCT_ID),
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_ATI_MEMO_PRO_2HS_V2_PRODUCT_ID),
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
+	{ USB_DEVICE(KVASER_VENDOR_ID, USB_HYBRID_PRO_CANLIN_PRODUCT_ID),
+		.driver_info = (kernel_ulong_t)&kvaser_usb_driver_info_hydra },
 	{ }
 };
 MODULE_DEVICE_TABLE(usb, kvaser_usb_table);
@@ -235,7 +266,7 @@
 	}
 	usb_free_urb(urb);
 
-	return 0;
+	return err;
 }
 
 int kvaser_usb_can_rx_over_error(struct net_device *netdev)
@@ -267,6 +298,7 @@
 static void kvaser_usb_read_bulk_callback(struct urb *urb)
 {
 	struct kvaser_usb *dev = urb->context;
+	const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops;
 	int err;
 	unsigned int i;
 
@@ -283,8 +315,8 @@
 		goto resubmit_urb;
 	}
 
-	dev->ops->dev_read_bulk_callback(dev, urb->transfer_buffer,
-					 urb->actual_length);
+	ops->dev_read_bulk_callback(dev, urb->transfer_buffer,
+				    urb->actual_length);
 
 resubmit_urb:
 	usb_fill_bulk_urb(urb, dev->udev,
@@ -378,21 +410,18 @@
 {
 	struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
 	struct kvaser_usb *dev = priv->dev;
+	const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops;
 	int err;
 
 	err = open_candev(netdev);
 	if (err)
 		return err;
 
-	err = kvaser_usb_setup_rx_urbs(dev);
+	err = ops->dev_set_opt_mode(priv);
 	if (err)
 		goto error;
 
-	err = dev->ops->dev_set_opt_mode(priv);
-	if (err)
-		goto error;
-
-	err = dev->ops->dev_start_chip(priv);
+	err = ops->dev_start_chip(priv);
 	if (err) {
 		netdev_warn(netdev, "Cannot start device, error %d\n", err);
 		goto error;
@@ -421,7 +450,7 @@
 /* This method might sleep. Do not call it in the atomic context
  * of URB completions.
  */
-static void kvaser_usb_unlink_tx_urbs(struct kvaser_usb_net_priv *priv)
+void kvaser_usb_unlink_tx_urbs(struct kvaser_usb_net_priv *priv)
 {
 	usb_kill_anchored_urbs(&priv->tx_submitted);
 	kvaser_usb_reset_tx_urb_contexts(priv);
@@ -449,22 +478,23 @@
 {
 	struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
 	struct kvaser_usb *dev = priv->dev;
+	const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops;
 	int err;
 
 	netif_stop_queue(netdev);
 
-	err = dev->ops->dev_flush_queue(priv);
+	err = ops->dev_flush_queue(priv);
 	if (err)
 		netdev_warn(netdev, "Cannot flush queue, error %d\n", err);
 
-	if (dev->ops->dev_reset_chip) {
-		err = dev->ops->dev_reset_chip(dev, priv->channel);
+	if (ops->dev_reset_chip) {
+		err = ops->dev_reset_chip(dev, priv->channel);
 		if (err)
 			netdev_warn(netdev, "Cannot reset card, error %d\n",
 				    err);
 	}
 
-	err = dev->ops->dev_stop_chip(priv);
+	err = ops->dev_stop_chip(priv);
 	if (err)
 		netdev_warn(netdev, "Cannot stop device, error %d\n", err);
 
@@ -477,6 +507,93 @@
 	return 0;
 }
 
+static int kvaser_usb_set_bittiming(struct net_device *netdev)
+{
+	struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
+	struct kvaser_usb *dev = priv->dev;
+	const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops;
+	struct can_bittiming *bt = &priv->can.bittiming;
+
+	struct kvaser_usb_busparams busparams;
+	int tseg1 = bt->prop_seg + bt->phase_seg1;
+	int tseg2 = bt->phase_seg2;
+	int sjw = bt->sjw;
+	int err = -EOPNOTSUPP;
+
+	busparams.bitrate = cpu_to_le32(bt->bitrate);
+	busparams.sjw = (u8)sjw;
+	busparams.tseg1 = (u8)tseg1;
+	busparams.tseg2 = (u8)tseg2;
+	if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
+		busparams.nsamples = 3;
+	else
+		busparams.nsamples = 1;
+
+	err = ops->dev_set_bittiming(netdev, &busparams);
+	if (err)
+		return err;
+
+	err = kvaser_usb_setup_rx_urbs(priv->dev);
+	if (err)
+		return err;
+
+	err = ops->dev_get_busparams(priv);
+	if (err) {
+		/* Treat EOPNOTSUPP as success */
+		if (err == -EOPNOTSUPP)
+			err = 0;
+		return err;
+	}
+
+	if (memcmp(&busparams, &priv->busparams_nominal,
+		   sizeof(priv->busparams_nominal)) != 0)
+		err = -EINVAL;
+
+	return err;
+}
+
+static int kvaser_usb_set_data_bittiming(struct net_device *netdev)
+{
+	struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
+	struct kvaser_usb *dev = priv->dev;
+	const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops;
+	struct can_bittiming *dbt = &priv->can.data_bittiming;
+
+	struct kvaser_usb_busparams busparams;
+	int tseg1 = dbt->prop_seg + dbt->phase_seg1;
+	int tseg2 = dbt->phase_seg2;
+	int sjw = dbt->sjw;
+	int err;
+
+	if (!ops->dev_set_data_bittiming ||
+	    !ops->dev_get_data_busparams)
+		return -EOPNOTSUPP;
+
+	busparams.bitrate = cpu_to_le32(dbt->bitrate);
+	busparams.sjw = (u8)sjw;
+	busparams.tseg1 = (u8)tseg1;
+	busparams.tseg2 = (u8)tseg2;
+	busparams.nsamples = 1;
+
+	err = ops->dev_set_data_bittiming(netdev, &busparams);
+	if (err)
+		return err;
+
+	err = kvaser_usb_setup_rx_urbs(priv->dev);
+	if (err)
+		return err;
+
+	err = ops->dev_get_data_busparams(priv);
+	if (err)
+		return err;
+
+	if (memcmp(&busparams, &priv->busparams_data,
+		   sizeof(priv->busparams_data)) != 0)
+		err = -EINVAL;
+
+	return err;
+}
+
 static void kvaser_usb_write_bulk_callback(struct urb *urb)
 {
 	struct kvaser_usb_tx_urb_context *context = urb->context;
@@ -503,6 +620,7 @@
 {
 	struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
 	struct kvaser_usb *dev = priv->dev;
+	const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops;
 	struct net_device_stats *stats = &netdev->stats;
 	struct kvaser_usb_tx_urb_context *context = NULL;
 	struct urb *urb;
@@ -545,8 +663,8 @@
 		goto freeurb;
 	}
 
-	buf = dev->ops->dev_frame_to_cmd(priv, skb, &context->dlc, &cmd_len,
-					 context->echo_index);
+	buf = ops->dev_frame_to_cmd(priv, skb, &context->dlc, &cmd_len,
+				    context->echo_index);
 	if (!buf) {
 		stats->tx_dropped++;
 		dev_kfree_skb(skb);
@@ -611,6 +729,7 @@
 
 static void kvaser_usb_remove_interfaces(struct kvaser_usb *dev)
 {
+	const struct kvaser_usb_dev_ops *ops = dev->driver_info->ops;
 	int i;
 
 	for (i = 0; i < dev->nchannels; i++) {
@@ -626,19 +745,23 @@
 		if (!dev->nets[i])
 			continue;
 
+		if (ops->dev_remove_channel)
+			ops->dev_remove_channel(dev->nets[i]);
+
 		free_candev(dev->nets[i]->netdev);
 	}
 }
 
-static int kvaser_usb_init_one(struct kvaser_usb *dev,
-			       const struct usb_device_id *id, int channel)
+static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel)
 {
 	struct net_device *netdev;
 	struct kvaser_usb_net_priv *priv;
+	const struct kvaser_usb_driver_info *driver_info = dev->driver_info;
+	const struct kvaser_usb_dev_ops *ops = driver_info->ops;
 	int err;
 
-	if (dev->ops->dev_reset_chip) {
-		err = dev->ops->dev_reset_chip(dev, channel);
+	if (ops->dev_reset_chip) {
+		err = ops->dev_reset_chip(dev, channel);
 		if (err)
 			return err;
 	}
@@ -655,6 +778,8 @@
 	init_usb_anchor(&priv->tx_submitted);
 	init_completion(&priv->start_comp);
 	init_completion(&priv->stop_comp);
+	init_completion(&priv->flush_comp);
+	init_completion(&priv->get_busparams_comp);
 	priv->can.ctrlmode_supported = 0;
 
 	priv->dev = dev;
@@ -667,20 +792,19 @@
 	priv->can.state = CAN_STATE_STOPPED;
 	priv->can.clock.freq = dev->cfg->clock.freq;
 	priv->can.bittiming_const = dev->cfg->bittiming_const;
-	priv->can.do_set_bittiming = dev->ops->dev_set_bittiming;
-	priv->can.do_set_mode = dev->ops->dev_set_mode;
-	if ((id->driver_info & KVASER_USB_HAS_TXRX_ERRORS) ||
+	priv->can.do_set_bittiming = kvaser_usb_set_bittiming;
+	priv->can.do_set_mode = ops->dev_set_mode;
+	if ((driver_info->quirks & KVASER_USB_QUIRK_HAS_TXRX_ERRORS) ||
 	    (priv->dev->card_data.capabilities & KVASER_USB_CAP_BERR_CAP))
-		priv->can.do_get_berr_counter = dev->ops->dev_get_berr_counter;
-	if (id->driver_info & KVASER_USB_HAS_SILENT_MODE)
+		priv->can.do_get_berr_counter = ops->dev_get_berr_counter;
+	if (driver_info->quirks & KVASER_USB_QUIRK_HAS_SILENT_MODE)
 		priv->can.ctrlmode_supported |= CAN_CTRLMODE_LISTENONLY;
 
 	priv->can.ctrlmode_supported |= dev->card_data.ctrlmode_supported;
 
 	if (priv->can.ctrlmode_supported & CAN_CTRLMODE_FD) {
 		priv->can.data_bittiming_const = dev->cfg->data_bittiming_const;
-		priv->can.do_set_data_bittiming =
-					dev->ops->dev_set_data_bittiming;
+		priv->can.do_set_data_bittiming = kvaser_usb_set_data_bittiming;
 	}
 
 	netdev->flags |= IFF_ECHO;
@@ -692,17 +816,26 @@
 
 	dev->nets[channel] = priv;
 
+	if (ops->dev_init_channel) {
+		err = ops->dev_init_channel(priv);
+		if (err)
+			goto err;
+	}
+
 	err = register_candev(netdev);
 	if (err) {
 		dev_err(&dev->intf->dev, "Failed to register CAN device\n");
-		free_candev(netdev);
-		dev->nets[channel] = NULL;
-		return err;
+		goto err;
 	}
 
 	netdev_dbg(netdev, "device registered\n");
 
 	return 0;
+
+err:
+	free_candev(netdev);
+	dev->nets[channel] = NULL;
+	return err;
 }
 
 static int kvaser_usb_probe(struct usb_interface *intf,
@@ -711,29 +844,22 @@
 	struct kvaser_usb *dev;
 	int err;
 	int i;
+	const struct kvaser_usb_driver_info *driver_info;
+	const struct kvaser_usb_dev_ops *ops;
+
+	driver_info = (const struct kvaser_usb_driver_info *)id->driver_info;
+	if (!driver_info)
+		return -ENODEV;
 
 	dev = devm_kzalloc(&intf->dev, sizeof(*dev), GFP_KERNEL);
 	if (!dev)
 		return -ENOMEM;
 
-	if (kvaser_is_leaf(id)) {
-		dev->card_data.leaf.family = KVASER_LEAF;
-		dev->ops = &kvaser_usb_leaf_dev_ops;
-	} else if (kvaser_is_usbcan(id)) {
-		dev->card_data.leaf.family = KVASER_USBCAN;
-		dev->ops = &kvaser_usb_leaf_dev_ops;
-	} else if (kvaser_is_hydra(id)) {
-		dev->ops = &kvaser_usb_hydra_dev_ops;
-	} else {
-		dev_err(&intf->dev,
-			"Product ID (%d) is not a supported Kvaser USB device\n",
-			id->idProduct);
-		return -ENODEV;
-	}
-
 	dev->intf = intf;
+	dev->driver_info = driver_info;
+	ops = driver_info->ops;
 
-	err = dev->ops->dev_setup_endpoints(dev);
+	err = ops->dev_setup_endpoints(dev);
 	if (err) {
 		dev_err(&intf->dev, "Cannot get usb endpoint(s)");
 		return err;
@@ -747,22 +873,22 @@
 
 	dev->card_data.ctrlmode_supported = 0;
 	dev->card_data.capabilities = 0;
-	err = dev->ops->dev_init_card(dev);
+	err = ops->dev_init_card(dev);
 	if (err) {
 		dev_err(&intf->dev,
 			"Failed to initialize card, error %d\n", err);
 		return err;
 	}
 
-	err = dev->ops->dev_get_software_info(dev);
+	err = ops->dev_get_software_info(dev);
 	if (err) {
 		dev_err(&intf->dev,
 			"Cannot get software info, error %d\n", err);
 		return err;
 	}
 
-	if (dev->ops->dev_get_software_details) {
-		err = dev->ops->dev_get_software_details(dev);
+	if (ops->dev_get_software_details) {
+		err = ops->dev_get_software_details(dev);
 		if (err) {
 			dev_err(&intf->dev,
 				"Cannot get software details, error %d\n", err);
@@ -780,14 +906,14 @@
 
 	dev_dbg(&intf->dev, "Max outstanding tx = %d URBs\n", dev->max_tx_urbs);
 
-	err = dev->ops->dev_get_card_info(dev);
+	err = ops->dev_get_card_info(dev);
 	if (err) {
 		dev_err(&intf->dev, "Cannot get card info, error %d\n", err);
 		return err;
 	}
 
-	if (dev->ops->dev_get_capabilities) {
-		err = dev->ops->dev_get_capabilities(dev);
+	if (ops->dev_get_capabilities) {
+		err = ops->dev_get_capabilities(dev);
 		if (err) {
 			dev_err(&intf->dev,
 				"Cannot get capabilities, error %d\n", err);
@@ -797,7 +923,7 @@
 	}
 
 	for (i = 0; i < dev->nchannels; i++) {
-		err = kvaser_usb_init_one(dev, id, i);
+		err = kvaser_usb_init_one(dev, i);
 		if (err) {
 			kvaser_usb_remove_interfaces(dev);
 			return err;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c
@@ -43,6 +43,8 @@
 
 /* Minihydra command IDs */
 #define CMD_SET_BUSPARAMS_REQ			16
+#define CMD_GET_BUSPARAMS_REQ			17
+#define CMD_GET_BUSPARAMS_RESP			18
 #define CMD_GET_CHIP_STATE_REQ			19
 #define CMD_CHIP_STATE_EVENT			20
 #define CMD_SET_DRIVERMODE_REQ			21
@@ -193,21 +195,26 @@
 #define KVASER_USB_HYDRA_BUS_MODE_CANFD_ISO	0x01
 #define KVASER_USB_HYDRA_BUS_MODE_NONISO	0x02
 struct kvaser_cmd_set_busparams {
-	__le32 bitrate;
-	u8 tseg1;
-	u8 tseg2;
-	u8 sjw;
-	u8 nsamples;
+	struct kvaser_usb_busparams busparams_nominal;
 	u8 reserved0[4];
-	__le32 bitrate_d;
-	u8 tseg1_d;
-	u8 tseg2_d;
-	u8 sjw_d;
-	u8 nsamples_d;
+	struct kvaser_usb_busparams busparams_data;
 	u8 canfd_mode;
 	u8 reserved1[7];
 } __packed;
 
+/* Busparam type */
+#define KVASER_USB_HYDRA_BUSPARAM_TYPE_CAN	0x00
+#define KVASER_USB_HYDRA_BUSPARAM_TYPE_CANFD	0x01
+struct kvaser_cmd_get_busparams_req {
+	u8 type;
+	u8 reserved[27];
+} __packed;
+
+struct kvaser_cmd_get_busparams_res {
+	struct kvaser_usb_busparams busparams;
+	u8 reserved[20];
+} __packed;
+
 /* Ctrl modes */
 #define KVASER_USB_HYDRA_CTRLMODE_NORMAL	0x01
 #define KVASER_USB_HYDRA_CTRLMODE_LISTEN	0x02
@@ -278,6 +285,8 @@
 		struct kvaser_cmd_error_event error_event;
 
 		struct kvaser_cmd_set_busparams set_busparams_req;
+		struct kvaser_cmd_get_busparams_req get_busparams_req;
+		struct kvaser_cmd_get_busparams_res get_busparams_res;
 
 		struct kvaser_cmd_chip_state_event chip_state_event;
 
@@ -293,6 +302,7 @@
 #define KVASER_USB_HYDRA_CF_FLAG_OVERRUN	BIT(1)
 #define KVASER_USB_HYDRA_CF_FLAG_REMOTE_FRAME	BIT(4)
 #define KVASER_USB_HYDRA_CF_FLAG_EXTENDED_ID	BIT(5)
+#define KVASER_USB_HYDRA_CF_FLAG_TX_ACK		BIT(6)
 /* CAN frame flags. Used in ext_rx_can and ext_tx_can */
 #define KVASER_USB_HYDRA_CF_FLAG_OSM_NACK	BIT(12)
 #define KVASER_USB_HYDRA_CF_FLAG_ABL		BIT(13)
@@ -359,6 +369,10 @@
 	} __packed;
 } __packed;
 
+struct kvaser_usb_net_hydra_priv {
+	int pending_get_busparams_type;
+};
+
 static const struct can_bittiming_const kvaser_usb_hydra_kcan_bittiming_c = {
 	.name = "kvaser_usb_kcan",
 	.tseg1_min = 1,
@@ -367,11 +381,11 @@
 	.tseg2_max = 32,
 	.sjw_max = 16,
 	.brp_min = 1,
-	.brp_max = 4096,
+	.brp_max = 8192,
 	.brp_inc = 1,
 };
 
-static const struct can_bittiming_const kvaser_usb_hydra_flexc_bittiming_c = {
+const struct can_bittiming_const kvaser_usb_flexc_bittiming_const = {
 	.name = "kvaser_usb_flex",
 	.tseg1_min = 4,
 	.tseg1_max = 16,
@@ -504,6 +518,7 @@
 					    u8 cmd_no, int channel)
 {
 	struct kvaser_cmd *cmd;
+	size_t cmd_len;
 	int err;
 
 	cmd = kcalloc(1, sizeof(struct kvaser_cmd), GFP_KERNEL);
@@ -511,6 +526,7 @@
 		return -ENOMEM;
 
 	cmd->header.cmd_no = cmd_no;
+	cmd_len = kvaser_usb_hydra_cmd_size(cmd);
 	if (channel < 0) {
 		kvaser_usb_hydra_set_cmd_dest_he
 				(cmd, KVASER_USB_HYDRA_HE_ADDRESS_ILLEGAL);
@@ -527,7 +543,7 @@
 	kvaser_usb_hydra_set_cmd_transid
 				(cmd, kvaser_usb_hydra_get_next_transid(dev));
 
-	err = kvaser_usb_send_cmd(dev, cmd, kvaser_usb_hydra_cmd_size(cmd));
+	err = kvaser_usb_send_cmd(dev, cmd, cmd_len);
 	if (err)
 		goto end;
 
@@ -543,6 +559,7 @@
 {
 	struct kvaser_cmd *cmd;
 	struct kvaser_usb *dev = priv->dev;
+	size_t cmd_len;
 	int err;
 
 	cmd = kcalloc(1, sizeof(struct kvaser_cmd), GFP_ATOMIC);
@@ -550,14 +567,14 @@
 		return -ENOMEM;
 
 	cmd->header.cmd_no = cmd_no;
+	cmd_len = kvaser_usb_hydra_cmd_size(cmd);
 
 	kvaser_usb_hydra_set_cmd_dest_he
 		(cmd, dev->card_data.hydra.channel_to_he[priv->channel]);
 	kvaser_usb_hydra_set_cmd_transid
 				(cmd, kvaser_usb_hydra_get_next_transid(dev));
 
-	err = kvaser_usb_send_cmd_async(priv, cmd,
-					kvaser_usb_hydra_cmd_size(cmd));
+	err = kvaser_usb_send_cmd_async(priv, cmd, cmd_len);
 	if (err)
 		kfree(cmd);
 
@@ -701,6 +718,7 @@
 {
 	struct kvaser_usb_dev_card_data *card_data = &dev->card_data;
 	struct kvaser_cmd *cmd;
+	size_t cmd_len;
 	u32 value = 0;
 	u32 mask = 0;
 	u16 cap_cmd_res;
@@ -712,13 +730,14 @@
 		return -ENOMEM;
 
 	cmd->header.cmd_no = CMD_GET_CAPABILITIES_REQ;
+	cmd_len = kvaser_usb_hydra_cmd_size(cmd);
 	cmd->cap_req.cap_cmd = cpu_to_le16(cap_cmd_req);
 
 	kvaser_usb_hydra_set_cmd_dest_he(cmd, card_data->hydra.sysdbg_he);
 	kvaser_usb_hydra_set_cmd_transid
 				(cmd, kvaser_usb_hydra_get_next_transid(dev));
 
-	err = kvaser_usb_send_cmd(dev, cmd, kvaser_usb_hydra_cmd_size(cmd));
+	err = kvaser_usb_send_cmd(dev, cmd, cmd_len);
 	if (err)
 		goto end;
 
@@ -812,6 +831,39 @@
 	complete(&priv->flush_comp);
 }
 
+static void kvaser_usb_hydra_get_busparams_reply(const struct kvaser_usb *dev,
+						 const struct kvaser_cmd *cmd)
+{
+	struct kvaser_usb_net_priv *priv;
+	struct kvaser_usb_net_hydra_priv *hydra;
+
+	priv = kvaser_usb_hydra_net_priv_from_cmd(dev, cmd);
+	if (!priv)
+		return;
+
+	hydra = priv->sub_priv;
+	if (!hydra)
+		return;
+
+	switch (hydra->pending_get_busparams_type) {
+	case KVASER_USB_HYDRA_BUSPARAM_TYPE_CAN:
+		memcpy(&priv->busparams_nominal, &cmd->get_busparams_res.busparams,
+		       sizeof(priv->busparams_nominal));
+		break;
+	case KVASER_USB_HYDRA_BUSPARAM_TYPE_CANFD:
+		memcpy(&priv->busparams_data, &cmd->get_busparams_res.busparams,
+		       sizeof(priv->busparams_nominal));
+		break;
+	default:
+		dev_warn(&dev->intf->dev, "Unknown get_busparams_type %d\n",
+			 hydra->pending_get_busparams_type);
+		break;
+	}
+	hydra->pending_get_busparams_type = -1;
+
+	complete(&priv->get_busparams_comp);
+}
+
 static void
 kvaser_usb_hydra_bus_status_to_can_state(const struct kvaser_usb_net_priv *priv,
 					 u8 bus_status,
@@ -890,8 +942,10 @@
 	    new_state < CAN_STATE_BUS_OFF)
 		priv->can.can_stats.restarts++;
 
-	cf->data[6] = bec->txerr;
-	cf->data[7] = bec->rxerr;
+	if (new_state != CAN_STATE_BUS_OFF) {
+		cf->data[6] = bec->txerr;
+		cf->data[7] = bec->rxerr;
+	}
 
 	stats = &netdev->stats;
 	stats->rx_packets++;
@@ -1045,8 +1099,10 @@
 	shhwtstamps->hwtstamp = hwtstamp;
 
 	cf->can_id |= CAN_ERR_BUSERROR;
-	cf->data[6] = bec.txerr;
-	cf->data[7] = bec.rxerr;
+	if (new_state != CAN_STATE_BUS_OFF) {
+		cf->data[6] = bec.txerr;
+		cf->data[7] = bec.rxerr;
+	}
 
 	stats->rx_packets++;
 	stats->rx_bytes += cf->can_dlc;
@@ -1095,6 +1151,7 @@
 	struct kvaser_usb_net_priv *priv;
 	unsigned long irq_flags;
 	bool one_shot_fail = false;
+	bool is_err_frame = false;
 	u16 transid = kvaser_usb_hydra_get_cmd_transid(cmd);
 
 	priv = kvaser_usb_hydra_net_priv_from_cmd(dev, cmd);
@@ -1113,10 +1170,13 @@
 			kvaser_usb_hydra_one_shot_fail(priv, cmd_ext);
 			one_shot_fail = true;
 		}
+
+		is_err_frame = flags & KVASER_USB_HYDRA_CF_FLAG_TX_ACK &&
+			       flags & KVASER_USB_HYDRA_CF_FLAG_ERROR_FRAME;
 	}
 
 	context = &priv->tx_contexts[transid % dev->max_tx_urbs];
-	if (!one_shot_fail) {
+	if (!one_shot_fail && !is_err_frame) {
 		struct net_device_stats *stats = &priv->netdev->stats;
 
 		stats->tx_packets++;
@@ -1290,6 +1350,10 @@
 		kvaser_usb_hydra_state_event(dev, cmd);
 		break;
 
+	case CMD_GET_BUSPARAMS_RESP:
+		kvaser_usb_hydra_get_busparams_reply(dev, cmd);
+		break;
+
 	case CMD_ERROR_EVENT:
 		kvaser_usb_hydra_error_event(dev, cmd);
 		break;
@@ -1490,15 +1554,61 @@
 	return err;
 }
 
-static int kvaser_usb_hydra_set_bittiming(struct net_device *netdev)
+static int kvaser_usb_hydra_get_busparams(struct kvaser_usb_net_priv *priv,
+					  int busparams_type)
+{
+	struct kvaser_usb *dev = priv->dev;
+	struct kvaser_usb_net_hydra_priv *hydra = priv->sub_priv;
+	struct kvaser_cmd *cmd;
+	size_t cmd_len;
+	int err;
+
+	if (!hydra)
+		return -EINVAL;
+
+	cmd = kcalloc(1, sizeof(struct kvaser_cmd), GFP_KERNEL);
+	if (!cmd)
+		return -ENOMEM;
+
+	cmd->header.cmd_no = CMD_GET_BUSPARAMS_REQ;
+	cmd_len = kvaser_usb_hydra_cmd_size(cmd);
+	kvaser_usb_hydra_set_cmd_dest_he
+		(cmd, dev->card_data.hydra.channel_to_he[priv->channel]);
+	kvaser_usb_hydra_set_cmd_transid
+				(cmd, kvaser_usb_hydra_get_next_transid(dev));
+	cmd->get_busparams_req.type = busparams_type;
+	hydra->pending_get_busparams_type = busparams_type;
+
+	reinit_completion(&priv->get_busparams_comp);
+
+	err = kvaser_usb_send_cmd(dev, cmd, cmd_len);
+	if (err)
+		return err;
+
+	if (!wait_for_completion_timeout(&priv->get_busparams_comp,
+					 msecs_to_jiffies(KVASER_USB_TIMEOUT)))
+		return -ETIMEDOUT;
+
+	return err;
+}
+
+static int kvaser_usb_hydra_get_nominal_busparams(struct kvaser_usb_net_priv *priv)
+{
+	return kvaser_usb_hydra_get_busparams(priv, KVASER_USB_HYDRA_BUSPARAM_TYPE_CAN);
+}
+
+static int kvaser_usb_hydra_get_data_busparams(struct kvaser_usb_net_priv *priv)
+{
+	return kvaser_usb_hydra_get_busparams(priv, KVASER_USB_HYDRA_BUSPARAM_TYPE_CANFD);
+}
+
+static int kvaser_usb_hydra_set_bittiming(const struct net_device *netdev,
+					  const struct kvaser_usb_busparams *busparams)
 {
 	struct kvaser_cmd *cmd;
 	struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
-	struct can_bittiming *bt = &priv->can.bittiming;
 	struct kvaser_usb *dev = priv->dev;
-	int tseg1 = bt->prop_seg + bt->phase_seg1;
-	int tseg2 = bt->phase_seg2;
-	int sjw = bt->sjw;
+	size_t cmd_len;
 	int err;
 
 	cmd = kcalloc(1, sizeof(struct kvaser_cmd), GFP_KERNEL);
@@ -1506,33 +1616,29 @@
 		return -ENOMEM;
 
 	cmd->header.cmd_no = CMD_SET_BUSPARAMS_REQ;
-	cmd->set_busparams_req.bitrate = cpu_to_le32(bt->bitrate);
-	cmd->set_busparams_req.sjw = (u8)sjw;
-	cmd->set_busparams_req.tseg1 = (u8)tseg1;
-	cmd->set_busparams_req.tseg2 = (u8)tseg2;
-	cmd->set_busparams_req.nsamples = 1;
+	cmd_len = kvaser_usb_hydra_cmd_size(cmd);
+	memcpy(&cmd->set_busparams_req.busparams_nominal, busparams,
+	       sizeof(cmd->set_busparams_req.busparams_nominal));
 
 	kvaser_usb_hydra_set_cmd_dest_he
 		(cmd, dev->card_data.hydra.channel_to_he[priv->channel]);
 	kvaser_usb_hydra_set_cmd_transid
 				(cmd, kvaser_usb_hydra_get_next_transid(dev));
 
-	err = kvaser_usb_send_cmd(dev, cmd, kvaser_usb_hydra_cmd_size(cmd));
+	err = kvaser_usb_send_cmd(dev, cmd, cmd_len);
 
 	kfree(cmd);
 
 	return err;
 }
 
-static int kvaser_usb_hydra_set_data_bittiming(struct net_device *netdev)
+static int kvaser_usb_hydra_set_data_bittiming(const struct net_device *netdev,
+					       const struct kvaser_usb_busparams *busparams)
 {
 	struct kvaser_cmd *cmd;
 	struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
-	struct can_bittiming *dbt = &priv->can.data_bittiming;
 	struct kvaser_usb *dev = priv->dev;
-	int tseg1 = dbt->prop_seg + dbt->phase_seg1;
-	int tseg2 = dbt->phase_seg2;
-	int sjw = dbt->sjw;
+	size_t cmd_len;
 	int err;
 
 	cmd = kcalloc(1, sizeof(struct kvaser_cmd), GFP_KERNEL);
@@ -1540,11 +1646,9 @@
 		return -ENOMEM;
 
 	cmd->header.cmd_no = CMD_SET_BUSPARAMS_FD_REQ;
-	cmd->set_busparams_req.bitrate_d = cpu_to_le32(dbt->bitrate);
-	cmd->set_busparams_req.sjw_d = (u8)sjw;
-	cmd->set_busparams_req.tseg1_d = (u8)tseg1;
-	cmd->set_busparams_req.tseg2_d = (u8)tseg2;
-	cmd->set_busparams_req.nsamples_d = 1;
+	cmd_len = kvaser_usb_hydra_cmd_size(cmd);
+	memcpy(&cmd->set_busparams_req.busparams_data, busparams,
+	       sizeof(cmd->set_busparams_req.busparams_data));
 
 	if (priv->can.ctrlmode & CAN_CTRLMODE_FD) {
 		if (priv->can.ctrlmode & CAN_CTRLMODE_FD_NON_ISO)
@@ -1560,7 +1664,7 @@
 	kvaser_usb_hydra_set_cmd_transid
 				(cmd, kvaser_usb_hydra_get_next_transid(dev));
 
-	err = kvaser_usb_send_cmd(dev, cmd, kvaser_usb_hydra_cmd_size(cmd));
+	err = kvaser_usb_send_cmd(dev, cmd, cmd_len);
 
 	kfree(cmd);
 
@@ -1590,7 +1694,7 @@
 	struct usb_endpoint_descriptor *ep;
 	int i;
 
-	iface_desc = &dev->intf->altsetting[0];
+	iface_desc = dev->intf->cur_altsetting;
 
 	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
 		ep = &iface_desc->endpoint[i].desc;
@@ -1651,6 +1755,19 @@
 	return 0;
 }
 
+static int kvaser_usb_hydra_init_channel(struct kvaser_usb_net_priv *priv)
+{
+	struct kvaser_usb_net_hydra_priv *hydra;
+
+	hydra = devm_kzalloc(&priv->dev->intf->dev, sizeof(*hydra), GFP_KERNEL);
+	if (!hydra)
+		return -ENOMEM;
+
+	priv->sub_priv = hydra;
+
+	return 0;
+}
+
 static int kvaser_usb_hydra_get_software_info(struct kvaser_usb *dev)
 {
 	struct kvaser_cmd cmd;
@@ -1675,6 +1792,7 @@
 static int kvaser_usb_hydra_get_software_details(struct kvaser_usb *dev)
 {
 	struct kvaser_cmd *cmd;
+	size_t cmd_len;
 	int err;
 	u32 flags;
 	struct kvaser_usb_dev_card_data *card_data = &dev->card_data;
@@ -1684,6 +1802,7 @@
 		return -ENOMEM;
 
 	cmd->header.cmd_no = CMD_GET_SOFTWARE_DETAILS_REQ;
+	cmd_len = kvaser_usb_hydra_cmd_size(cmd);
 	cmd->sw_detail_req.use_ext_cmd = 1;
 	kvaser_usb_hydra_set_cmd_dest_he
 				(cmd, KVASER_USB_HYDRA_HE_ADDRESS_ILLEGAL);
@@ -1691,7 +1810,7 @@
 	kvaser_usb_hydra_set_cmd_transid
 				(cmd, kvaser_usb_hydra_get_next_transid(dev));
 
-	err = kvaser_usb_send_cmd(dev, cmd, kvaser_usb_hydra_cmd_size(cmd));
+	err = kvaser_usb_send_cmd(dev, cmd, cmd_len);
 	if (err)
 		goto end;
 
@@ -1807,6 +1926,7 @@
 {
 	struct kvaser_usb *dev = priv->dev;
 	struct kvaser_cmd *cmd;
+	size_t cmd_len;
 	int err;
 
 	if ((priv->can.ctrlmode &
@@ -1822,6 +1942,7 @@
 		return -ENOMEM;
 
 	cmd->header.cmd_no = CMD_SET_DRIVERMODE_REQ;
+	cmd_len = kvaser_usb_hydra_cmd_size(cmd);
 	kvaser_usb_hydra_set_cmd_dest_he
 		(cmd, dev->card_data.hydra.channel_to_he[priv->channel]);
 	kvaser_usb_hydra_set_cmd_transid
@@ -1831,7 +1952,7 @@
 	else
 		cmd->set_ctrlmode.mode = KVASER_USB_HYDRA_CTRLMODE_NORMAL;
 
-	err = kvaser_usb_send_cmd(dev, cmd, kvaser_usb_hydra_cmd_size(cmd));
+	err = kvaser_usb_send_cmd(dev, cmd, cmd_len);
 	kfree(cmd);
 
 	return err;
@@ -1841,7 +1962,7 @@
 {
 	int err;
 
-	init_completion(&priv->start_comp);
+	reinit_completion(&priv->start_comp);
 
 	err = kvaser_usb_hydra_send_simple_cmd(priv->dev, CMD_START_CHIP_REQ,
 					       priv->channel);
@@ -1859,7 +1980,7 @@
 {
 	int err;
 
-	init_completion(&priv->stop_comp);
+	reinit_completion(&priv->stop_comp);
 
 	/* Make sure we do not report invalid BUS_OFF from CMD_CHIP_STATE_EVENT
 	 * see comment in kvaser_usb_hydra_update_state()
@@ -1882,7 +2003,7 @@
 {
 	int err;
 
-	init_completion(&priv->flush_comp);
+	reinit_completion(&priv->flush_comp);
 
 	err = kvaser_usb_hydra_send_simple_cmd(priv->dev, CMD_FLUSH_QUEUE,
 					       priv->channel);
@@ -1993,10 +2114,13 @@
 const struct kvaser_usb_dev_ops kvaser_usb_hydra_dev_ops = {
 	.dev_set_mode = kvaser_usb_hydra_set_mode,
 	.dev_set_bittiming = kvaser_usb_hydra_set_bittiming,
+	.dev_get_busparams = kvaser_usb_hydra_get_nominal_busparams,
 	.dev_set_data_bittiming = kvaser_usb_hydra_set_data_bittiming,
+	.dev_get_data_busparams = kvaser_usb_hydra_get_data_busparams,
 	.dev_get_berr_counter = kvaser_usb_hydra_get_berr_counter,
 	.dev_setup_endpoints = kvaser_usb_hydra_setup_endpoints,
 	.dev_init_card = kvaser_usb_hydra_init_card,
+	.dev_init_channel = kvaser_usb_hydra_init_channel,
 	.dev_get_software_info = kvaser_usb_hydra_get_software_info,
 	.dev_get_software_details = kvaser_usb_hydra_get_software_details,
 	.dev_get_card_info = kvaser_usb_hydra_get_card_info,
@@ -2024,5 +2148,5 @@
 		.freq = 24000000,
 	},
 	.timestamp_freq = 1,
-	.bittiming_const = &kvaser_usb_hydra_flexc_bittiming_c,
+	.bittiming_const = &kvaser_usb_flexc_bittiming_const,
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
@@ -20,6 +20,7 @@
 #include <linux/string.h>
 #include <linux/types.h>
 #include <linux/usb.h>
+#include <linux/workqueue.h>
 
 #include <linux/can.h>
 #include <linux/can/dev.h>
@@ -28,10 +29,6 @@
 
 #include "kvaser_usb.h"
 
-/* Forward declaration */
-static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg;
-
-#define CAN_USB_CLOCK			8000000
 #define MAX_USBCAN_NET_DEVICES		2
 
 /* Command header size */
@@ -59,6 +56,9 @@
 #define CMD_RX_EXT_MESSAGE		14
 #define CMD_TX_EXT_MESSAGE		15
 #define CMD_SET_BUS_PARAMS		16
+#define CMD_GET_BUS_PARAMS		17
+#define CMD_GET_BUS_PARAMS_REPLY	18
+#define CMD_GET_CHIP_STATE		19
 #define CMD_CHIP_STATE_EVENT		20
 #define CMD_SET_CTRL_MODE		21
 #define CMD_RESET_CHIP			24
@@ -73,13 +73,24 @@
 #define CMD_GET_CARD_INFO_REPLY		35
 #define CMD_GET_SOFTWARE_INFO		38
 #define CMD_GET_SOFTWARE_INFO_REPLY	39
+#define CMD_ERROR_EVENT			45
 #define CMD_FLUSH_QUEUE			48
 #define CMD_TX_ACKNOWLEDGE		50
 #define CMD_CAN_ERROR_EVENT		51
 #define CMD_FLUSH_QUEUE_REPLY		68
+#define CMD_GET_CAPABILITIES_REQ	95
+#define CMD_GET_CAPABILITIES_RESP	96
 
 #define CMD_LEAF_LOG_MESSAGE		106
 
+/* Leaf frequency options */
+#define KVASER_USB_LEAF_SWOPTION_FREQ_MASK 0x60
+#define KVASER_USB_LEAF_SWOPTION_FREQ_16_MHZ_CLK 0
+#define KVASER_USB_LEAF_SWOPTION_FREQ_32_MHZ_CLK BIT(5)
+#define KVASER_USB_LEAF_SWOPTION_FREQ_24_MHZ_CLK BIT(6)
+
+#define KVASER_USB_LEAF_SWOPTION_EXT_CAP BIT(12)
+
 /* error factors */
 #define M16C_EF_ACKE			BIT(0)
 #define M16C_EF_CRCE			BIT(1)
@@ -98,16 +109,6 @@
 #define USBCAN_ERROR_STATE_RX_ERROR	BIT(1)
 #define USBCAN_ERROR_STATE_BUSERROR	BIT(2)
 
-/* bittiming parameters */
-#define KVASER_USB_TSEG1_MIN		1
-#define KVASER_USB_TSEG1_MAX		16
-#define KVASER_USB_TSEG2_MIN		1
-#define KVASER_USB_TSEG2_MAX		8
-#define KVASER_USB_SJW_MAX		4
-#define KVASER_USB_BRP_MIN		1
-#define KVASER_USB_BRP_MAX		64
-#define KVASER_USB_BRP_INC		1
-
 /* ctrl modes */
 #define KVASER_CTRL_MODE_NORMAL		1
 #define KVASER_CTRL_MODE_SILENT		2
@@ -164,11 +165,7 @@
 struct kvaser_cmd_busparams {
 	u8 tid;
 	u8 channel;
-	__le32 bitrate;
-	u8 tseg1;
-	u8 tseg2;
-	u8 sjw;
-	u8 no_samp;
+	struct kvaser_usb_busparams busparams;
 } __packed;
 
 struct kvaser_cmd_tx_can {
@@ -237,7 +234,7 @@
 	u8 tid;
 } __packed;
 
-struct leaf_cmd_error_event {
+struct leaf_cmd_can_error_event {
 	u8 tid;
 	u8 flags;
 	__le16 time[3];
@@ -249,7 +246,7 @@
 	u8 error_factor;
 } __packed;
 
-struct usbcan_cmd_error_event {
+struct usbcan_cmd_can_error_event {
 	u8 tid;
 	u8 padding;
 	u8 tx_errors_count_ch0;
@@ -261,6 +258,28 @@
 	__le16 time;
 } __packed;
 
+/* CMD_ERROR_EVENT error codes */
+#define KVASER_USB_LEAF_ERROR_EVENT_TX_QUEUE_FULL 0x8
+#define KVASER_USB_LEAF_ERROR_EVENT_PARAM 0x9
+
+struct leaf_cmd_error_event {
+	u8 tid;
+	u8 error_code;
+	__le16 timestamp[3];
+	__le16 padding;
+	__le16 info1;
+	__le16 info2;
+} __packed;
+
+struct usbcan_cmd_error_event {
+	u8 tid;
+	u8 error_code;
+	__le16 info1;
+	__le16 info2;
+	__le16 timestamp;
+	__le16 padding;
+} __packed;
+
 struct kvaser_cmd_ctrl_mode {
 	u8 tid;
 	u8 channel;
@@ -285,6 +304,28 @@
 	u8 data[8];
 } __packed;
 
+/* Sub commands for cap_req and cap_res */
+#define KVASER_USB_LEAF_CAP_CMD_LISTEN_MODE 0x02
+#define KVASER_USB_LEAF_CAP_CMD_ERR_REPORT 0x05
+struct kvaser_cmd_cap_req {
+	__le16 padding0;
+	__le16 cap_cmd;
+	__le16 padding1;
+	__le16 channel;
+} __packed;
+
+/* Status codes for cap_res */
+#define KVASER_USB_LEAF_CAP_STAT_OK 0x00
+#define KVASER_USB_LEAF_CAP_STAT_NOT_IMPL 0x01
+#define KVASER_USB_LEAF_CAP_STAT_UNAVAIL 0x02
+struct kvaser_cmd_cap_res {
+	__le16 padding;
+	__le16 cap_cmd;
+	__le16 status;
+	__le32 mask;
+	__le32 value;
+} __packed;
+
 struct kvaser_cmd {
 	u8 len;
 	u8 id;
@@ -300,14 +341,18 @@
 			struct leaf_cmd_softinfo softinfo;
 			struct leaf_cmd_rx_can rx_can;
 			struct leaf_cmd_chip_state_event chip_state_event;
-			struct leaf_cmd_error_event error_event;
+			struct leaf_cmd_can_error_event can_error_event;
 			struct leaf_cmd_log_message log_message;
+			struct leaf_cmd_error_event error_event;
+			struct kvaser_cmd_cap_req cap_req;
+			struct kvaser_cmd_cap_res cap_res;
 		} __packed leaf;
 
 		union {
 			struct usbcan_cmd_softinfo softinfo;
 			struct usbcan_cmd_rx_can rx_can;
 			struct usbcan_cmd_chip_state_event chip_state_event;
+			struct usbcan_cmd_can_error_event can_error_event;
 			struct usbcan_cmd_error_event error_event;
 		} __packed usbcan;
 
@@ -317,6 +362,42 @@
 	} u;
 } __packed;
 
+#define CMD_SIZE_ANY 0xff
+#define kvaser_fsize(field) sizeof_field(struct kvaser_cmd, field)
+
+static const u8 kvaser_usb_leaf_cmd_sizes_leaf[] = {
+	[CMD_START_CHIP_REPLY]		= kvaser_fsize(u.simple),
+	[CMD_STOP_CHIP_REPLY]		= kvaser_fsize(u.simple),
+	[CMD_GET_CARD_INFO_REPLY]	= kvaser_fsize(u.cardinfo),
+	[CMD_TX_ACKNOWLEDGE]		= kvaser_fsize(u.tx_acknowledge_header),
+	[CMD_GET_SOFTWARE_INFO_REPLY]	= kvaser_fsize(u.leaf.softinfo),
+	[CMD_RX_STD_MESSAGE]		= kvaser_fsize(u.leaf.rx_can),
+	[CMD_RX_EXT_MESSAGE]		= kvaser_fsize(u.leaf.rx_can),
+	[CMD_LEAF_LOG_MESSAGE]		= kvaser_fsize(u.leaf.log_message),
+	[CMD_CHIP_STATE_EVENT]		= kvaser_fsize(u.leaf.chip_state_event),
+	[CMD_CAN_ERROR_EVENT]		= kvaser_fsize(u.leaf.can_error_event),
+	[CMD_GET_CAPABILITIES_RESP]	= kvaser_fsize(u.leaf.cap_res),
+	[CMD_GET_BUS_PARAMS_REPLY]	= kvaser_fsize(u.busparams),
+	[CMD_ERROR_EVENT]		= kvaser_fsize(u.leaf.error_event),
+	/* ignored events: */
+	[CMD_FLUSH_QUEUE_REPLY]		= CMD_SIZE_ANY,
+};
+
+static const u8 kvaser_usb_leaf_cmd_sizes_usbcan[] = {
+	[CMD_START_CHIP_REPLY]		= kvaser_fsize(u.simple),
+	[CMD_STOP_CHIP_REPLY]		= kvaser_fsize(u.simple),
+	[CMD_GET_CARD_INFO_REPLY]	= kvaser_fsize(u.cardinfo),
+	[CMD_TX_ACKNOWLEDGE]		= kvaser_fsize(u.tx_acknowledge_header),
+	[CMD_GET_SOFTWARE_INFO_REPLY]	= kvaser_fsize(u.usbcan.softinfo),
+	[CMD_RX_STD_MESSAGE]		= kvaser_fsize(u.usbcan.rx_can),
+	[CMD_RX_EXT_MESSAGE]		= kvaser_fsize(u.usbcan.rx_can),
+	[CMD_CHIP_STATE_EVENT]		= kvaser_fsize(u.usbcan.chip_state_event),
+	[CMD_CAN_ERROR_EVENT]		= kvaser_fsize(u.usbcan.can_error_event),
+	[CMD_ERROR_EVENT]		= kvaser_fsize(u.usbcan.error_event),
+	/* ignored events: */
+	[CMD_USBCAN_CLOCK_OVERFLOW_EVENT] = CMD_SIZE_ANY,
+};
+
 /* Summary of a kvaser error event, for a unified Leaf/Usbcan error
  * handling. Some discrepancies between the two families exist:
  *
@@ -340,6 +421,113 @@
 	};
 };
 
+struct kvaser_usb_net_leaf_priv {
+	struct kvaser_usb_net_priv *net;
+
+	struct delayed_work chip_state_req_work;
+};
+
+static const struct can_bittiming_const kvaser_usb_leaf_m16c_bittiming_const = {
+	.name = "kvaser_usb_ucii",
+	.tseg1_min = 4,
+	.tseg1_max = 16,
+	.tseg2_min = 2,
+	.tseg2_max = 8,
+	.sjw_max = 4,
+	.brp_min = 1,
+	.brp_max = 16,
+	.brp_inc = 1,
+};
+
+static const struct can_bittiming_const kvaser_usb_leaf_m32c_bittiming_const = {
+	.name = "kvaser_usb_leaf",
+	.tseg1_min = 3,
+	.tseg1_max = 16,
+	.tseg2_min = 2,
+	.tseg2_max = 8,
+	.sjw_max = 4,
+	.brp_min = 2,
+	.brp_max = 128,
+	.brp_inc = 2,
+};
+
+static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_usbcan_dev_cfg = {
+	.clock = {
+		.freq = 8000000,
+	},
+	.timestamp_freq = 1,
+	.bittiming_const = &kvaser_usb_leaf_m16c_bittiming_const,
+};
+
+static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_m32c_dev_cfg = {
+	.clock = {
+		.freq = 16000000,
+	},
+	.timestamp_freq = 1,
+	.bittiming_const = &kvaser_usb_leaf_m32c_bittiming_const,
+};
+
+static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_imx_dev_cfg_16mhz = {
+	.clock = {
+		.freq = 16000000,
+	},
+	.timestamp_freq = 1,
+	.bittiming_const = &kvaser_usb_flexc_bittiming_const,
+};
+
+static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_imx_dev_cfg_24mhz = {
+	.clock = {
+		.freq = 24000000,
+	},
+	.timestamp_freq = 1,
+	.bittiming_const = &kvaser_usb_flexc_bittiming_const,
+};
+
+static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_imx_dev_cfg_32mhz = {
+	.clock = {
+		.freq = 32000000,
+	},
+	.timestamp_freq = 1,
+	.bittiming_const = &kvaser_usb_flexc_bittiming_const,
+};
+
+static int kvaser_usb_leaf_verify_size(const struct kvaser_usb *dev,
+				       const struct kvaser_cmd *cmd)
+{
+	/* buffer size >= cmd->len ensured by caller */
+	u8 min_size = 0;
+
+	switch (dev->driver_info->family) {
+	case KVASER_LEAF:
+		if (cmd->id < ARRAY_SIZE(kvaser_usb_leaf_cmd_sizes_leaf))
+			min_size = kvaser_usb_leaf_cmd_sizes_leaf[cmd->id];
+		break;
+	case KVASER_USBCAN:
+		if (cmd->id < ARRAY_SIZE(kvaser_usb_leaf_cmd_sizes_usbcan))
+			min_size = kvaser_usb_leaf_cmd_sizes_usbcan[cmd->id];
+		break;
+	}
+
+	if (min_size == CMD_SIZE_ANY)
+		return 0;
+
+	if (min_size) {
+		min_size += CMD_HEADER_LEN;
+		if (cmd->len >= min_size)
+			return 0;
+
+		dev_err_ratelimited(&dev->intf->dev,
+				    "Received command %u too short (size %u, needed %u)",
+				    cmd->id, cmd->len, min_size);
+		return -EIO;
+	}
+
+	dev_warn_ratelimited(&dev->intf->dev,
+			     "Unhandled command (%d, size %d)\n",
+			     cmd->id, cmd->len);
+	return -EINVAL;
+}
+
 static void *
 kvaser_usb_leaf_frame_to_cmd(const struct kvaser_usb_net_priv *priv,
 			     const struct sk_buff *skb, int *frame_len,
@@ -359,7 +547,7 @@
 				      sizeof(struct kvaser_cmd_tx_can);
 		cmd->u.tx_can.channel = priv->channel;
 
-		switch (dev->card_data.leaf.family) {
+		switch (dev->driver_info->family) {
 		case KVASER_LEAF:
 			cmd_tx_can_flags = &cmd->u.tx_can.leaf.flags;
 			break;
@@ -447,6 +635,9 @@
 end:
 	kfree(buf);
 
+	if (err == 0)
+		err = kvaser_usb_leaf_verify_size(dev, cmd);
+
 	return err;
 }
 
@@ -471,6 +662,37 @@
 	return rc;
 }
 
+static void kvaser_usb_leaf_get_software_info_leaf(struct kvaser_usb *dev,
+						   const struct leaf_cmd_softinfo *softinfo)
+{
+	u32 sw_options = le32_to_cpu(softinfo->sw_options);
+
+	dev->fw_version = le32_to_cpu(softinfo->fw_version);
+	dev->max_tx_urbs = le16_to_cpu(softinfo->max_outstanding_tx);
+
+	if (sw_options & KVASER_USB_LEAF_SWOPTION_EXT_CAP)
+		dev->card_data.capabilities |= KVASER_USB_CAP_EXT_CAP;
+
+	if (dev->driver_info->quirks & KVASER_USB_QUIRK_IGNORE_CLK_FREQ) {
+		/* Firmware expects bittiming parameters calculated for 16MHz
+		 * clock, regardless of the actual clock
+		 */
+		dev->cfg = &kvaser_usb_leaf_m32c_dev_cfg;
+	} else {
+		switch (sw_options & KVASER_USB_LEAF_SWOPTION_FREQ_MASK) {
+		case KVASER_USB_LEAF_SWOPTION_FREQ_16_MHZ_CLK:
+			dev->cfg = &kvaser_usb_leaf_imx_dev_cfg_16mhz;
+			break;
+		case KVASER_USB_LEAF_SWOPTION_FREQ_24_MHZ_CLK:
+			dev->cfg = &kvaser_usb_leaf_imx_dev_cfg_24mhz;
+			break;
+		case KVASER_USB_LEAF_SWOPTION_FREQ_32_MHZ_CLK:
+			dev->cfg = &kvaser_usb_leaf_imx_dev_cfg_32mhz;
+			break;
+		}
+	}
+}
+
 static int kvaser_usb_leaf_get_software_info_inner(struct kvaser_usb *dev)
 {
 	struct kvaser_cmd cmd;
@@ -484,16 +706,15 @@
 	if (err)
 		return err;
 
-	switch (dev->card_data.leaf.family) {
+	switch (dev->driver_info->family) {
 	case KVASER_LEAF:
-		dev->fw_version = le32_to_cpu(cmd.u.leaf.softinfo.fw_version);
-		dev->max_tx_urbs =
-			le16_to_cpu(cmd.u.leaf.softinfo.max_outstanding_tx);
+		kvaser_usb_leaf_get_software_info_leaf(dev, &cmd.u.leaf.softinfo);
 		break;
 	case KVASER_USBCAN:
 		dev->fw_version = le32_to_cpu(cmd.u.usbcan.softinfo.fw_version);
 		dev->max_tx_urbs =
 			le16_to_cpu(cmd.u.usbcan.softinfo.max_outstanding_tx);
+		dev->cfg = &kvaser_usb_leaf_usbcan_dev_cfg;
 		break;
 	}
 
@@ -532,13 +753,123 @@
 
 	dev->nchannels = cmd.u.cardinfo.nchannels;
 	if (dev->nchannels > KVASER_USB_MAX_NET_DEVICES ||
-	    (dev->card_data.leaf.family == KVASER_USBCAN &&
+	    (dev->driver_info->family == KVASER_USBCAN &&
 	     dev->nchannels > MAX_USBCAN_NET_DEVICES))
 		return -EINVAL;
 
 	return 0;
 }
 
+static int kvaser_usb_leaf_get_single_capability(struct kvaser_usb *dev,
+						 u16 cap_cmd_req, u16 *status)
+{
+	struct kvaser_usb_dev_card_data *card_data = &dev->card_data;
+	struct kvaser_cmd *cmd;
+	u32 value = 0;
+	u32 mask = 0;
+	u16 cap_cmd_res;
+	int err;
+	int i;
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd)
+		return -ENOMEM;
+
+	cmd->id = CMD_GET_CAPABILITIES_REQ;
+	cmd->u.leaf.cap_req.cap_cmd = cpu_to_le16(cap_cmd_req);
+	cmd->len = CMD_HEADER_LEN + sizeof(struct kvaser_cmd_cap_req);
+
+	err = kvaser_usb_send_cmd(dev, cmd, cmd->len);
+	if (err)
+		goto end;
+
+	err = kvaser_usb_leaf_wait_cmd(dev, CMD_GET_CAPABILITIES_RESP, cmd);
+	if (err)
+		goto end;
+
+	*status = le16_to_cpu(cmd->u.leaf.cap_res.status);
+
+	if (*status != KVASER_USB_LEAF_CAP_STAT_OK)
+		goto end;
+
+	cap_cmd_res = le16_to_cpu(cmd->u.leaf.cap_res.cap_cmd);
+	switch (cap_cmd_res) {
+	case KVASER_USB_LEAF_CAP_CMD_LISTEN_MODE:
+	case KVASER_USB_LEAF_CAP_CMD_ERR_REPORT:
+		value = le32_to_cpu(cmd->u.leaf.cap_res.value);
+		mask = le32_to_cpu(cmd->u.leaf.cap_res.mask);
+		break;
+	default:
+		dev_warn(&dev->intf->dev, "Unknown capability command %u\n",
+			 cap_cmd_res);
+		break;
+	}
+
+	for (i = 0; i < dev->nchannels; i++) {
+		if (BIT(i) & (value & mask)) {
+			switch (cap_cmd_res) {
+			case KVASER_USB_LEAF_CAP_CMD_LISTEN_MODE:
+				card_data->ctrlmode_supported |=
+						CAN_CTRLMODE_LISTENONLY;
+				break;
+			case KVASER_USB_LEAF_CAP_CMD_ERR_REPORT:
+				card_data->capabilities |=
+						KVASER_USB_CAP_BERR_CAP;
+				break;
+			}
+		}
+	}
+
+end:
+	kfree(cmd);
+
+	return err;
+}
+
+static int kvaser_usb_leaf_get_capabilities_leaf(struct kvaser_usb *dev)
+{
+	int err;
+	u16 status;
+
+	if (!(dev->card_data.capabilities & KVASER_USB_CAP_EXT_CAP)) {
+		dev_info(&dev->intf->dev,
+			 "No extended capability support. Upgrade device firmware.\n");
+		return 0;
+	}
+
+	err = kvaser_usb_leaf_get_single_capability(dev,
+						    KVASER_USB_LEAF_CAP_CMD_LISTEN_MODE,
+						    &status);
+	if (err)
+		return err;
+	if (status)
+		dev_info(&dev->intf->dev,
+			 "KVASER_USB_LEAF_CAP_CMD_LISTEN_MODE failed %u\n",
+			 status);
+
+	err = kvaser_usb_leaf_get_single_capability(dev,
+						    KVASER_USB_LEAF_CAP_CMD_ERR_REPORT,
+						    &status);
+	if (err)
+		return err;
+	if (status)
+		dev_info(&dev->intf->dev,
+			 "KVASER_USB_LEAF_CAP_CMD_ERR_REPORT failed %u\n",
+			 status);
+
+	return 0;
+}
+
+static int kvaser_usb_leaf_get_capabilities(struct kvaser_usb *dev)
+{
+	int err = 0;
+
+	if (dev->driver_info->family == KVASER_LEAF)
+		err = kvaser_usb_leaf_get_capabilities_leaf(dev);
+
+	return err;
+}
+
 static void kvaser_usb_leaf_tx_acknowledge(const struct kvaser_usb *dev,
 					   const struct kvaser_cmd *cmd)
 {
@@ -567,7 +898,7 @@
 	context = &priv->tx_contexts[tid % dev->max_tx_urbs];
 
 	/* Sometimes the state change doesn't come after a bus-off event */
-	if (priv->can.restart_ms && priv->can.state >= CAN_STATE_BUS_OFF) {
+	if (priv->can.restart_ms && priv->can.state == CAN_STATE_BUS_OFF) {
 		struct sk_buff *skb;
 		struct can_frame *cf;
 
@@ -608,7 +939,7 @@
 	struct kvaser_cmd *cmd;
 	int err;
 
-	cmd = kmalloc(sizeof(*cmd), GFP_ATOMIC);
+	cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC);
 	if (!cmd)
 		return -ENOMEM;
 
@@ -623,6 +954,16 @@
 	return err;
 }
 
+static void kvaser_usb_leaf_chip_state_req_work(struct work_struct *work)
+{
+	struct kvaser_usb_net_leaf_priv *leaf =
+		container_of(work, struct kvaser_usb_net_leaf_priv,
+			     chip_state_req_work.work);
+	struct kvaser_usb_net_priv *priv = leaf->net;
+
+	kvaser_usb_leaf_simple_cmd_async(priv, CMD_GET_CHIP_STATE);
+}
+
 static void
 kvaser_usb_leaf_rx_error_update_can_state(struct kvaser_usb_net_priv *priv,
 					const struct kvaser_usb_err_summary *es,
@@ -641,20 +982,16 @@
 		new_state = CAN_STATE_BUS_OFF;
 	} else if (es->status & M16C_STATE_BUS_PASSIVE) {
 		new_state = CAN_STATE_ERROR_PASSIVE;
-	} else if (es->status & M16C_STATE_BUS_ERROR) {
+	} else if ((es->status & M16C_STATE_BUS_ERROR) &&
+		   cur_state >= CAN_STATE_BUS_OFF) {
 		/* Guard against spurious error events after a busoff */
-		if (cur_state < CAN_STATE_BUS_OFF) {
-			if (es->txerr >= 128 || es->rxerr >= 128)
-				new_state = CAN_STATE_ERROR_PASSIVE;
-			else if (es->txerr >= 96 || es->rxerr >= 96)
-				new_state = CAN_STATE_ERROR_WARNING;
-			else if (cur_state > CAN_STATE_ERROR_ACTIVE)
-				new_state = CAN_STATE_ERROR_ACTIVE;
-		}
-	}
-
-	if (!es->status)
+	} else if (es->txerr >= 128 || es->rxerr >= 128) {
+		new_state = CAN_STATE_ERROR_PASSIVE;
+	} else if (es->txerr >= 96 || es->rxerr >= 96) {
+		new_state = CAN_STATE_ERROR_WARNING;
+	} else {
 		new_state = CAN_STATE_ERROR_ACTIVE;
+	}
 
 	if (new_state != cur_state) {
 		tx_state = (es->txerr >= es->rxerr) ? new_state : 0;
@@ -664,11 +1001,11 @@
 	}
 
 	if (priv->can.restart_ms &&
-	    cur_state >= CAN_STATE_BUS_OFF &&
+	    cur_state == CAN_STATE_BUS_OFF &&
 	    new_state < CAN_STATE_BUS_OFF)
 		priv->can.can_stats.restarts++;
 
-	switch (dev->card_data.leaf.family) {
+	switch (dev->driver_info->family) {
 	case KVASER_LEAF:
 		if (es->leaf.error_factor) {
 			priv->can.can_stats.bus_error++;
@@ -698,6 +1035,7 @@
 	struct sk_buff *skb;
 	struct net_device_stats *stats;
 	struct kvaser_usb_net_priv *priv;
+	struct kvaser_usb_net_leaf_priv *leaf;
 	enum can_state old_state, new_state;
 
 	if (es->channel >= dev->nchannels) {
@@ -707,8 +1045,13 @@
 	}
 
 	priv = dev->nets[es->channel];
+	leaf = priv->sub_priv;
 	stats = &priv->netdev->stats;
 
+	/* Ignore e.g. state change to bus-off reported just after stopping */
+	if (!netif_running(priv->netdev))
+		return;
+
 	/* Update all of the CAN interface's state and error counters before
 	 * trying any memory allocation that can actually fail with -ENOMEM.
 	 *
@@ -723,6 +1066,14 @@
 	kvaser_usb_leaf_rx_error_update_can_state(priv, es, &tmp_cf);
 	new_state = priv->can.state;
 
+	/* If there are errors, request status updates periodically as we do
+	 * not get automatic notifications of improved state.
+	 */
+	if (new_state < CAN_STATE_BUS_OFF &&
+	    (es->rxerr || es->txerr || new_state == CAN_STATE_ERROR_PASSIVE))
+		schedule_delayed_work(&leaf->chip_state_req_work,
+				      msecs_to_jiffies(500));
+
 	skb = alloc_can_err_skb(priv->netdev, &cf);
 	if (!skb) {
 		stats->rx_dropped++;
@@ -740,14 +1091,14 @@
 		}
 
 		if (priv->can.restart_ms &&
-		    old_state >= CAN_STATE_BUS_OFF &&
+		    old_state == CAN_STATE_BUS_OFF &&
 		    new_state < CAN_STATE_BUS_OFF) {
 			cf->can_id |= CAN_ERR_RESTARTED;
 			netif_carrier_on(priv->netdev);
 		}
 	}
 
-	switch (dev->card_data.leaf.family) {
+	switch (dev->driver_info->family) {
 	case KVASER_LEAF:
 		if (es->leaf.error_factor) {
 			cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_PROT;
@@ -774,8 +1125,10 @@
 		break;
 	}
 
-	cf->data[6] = es->txerr;
-	cf->data[7] = es->rxerr;
+	if (new_state != CAN_STATE_BUS_OFF) {
+		cf->data[6] = es->txerr;
+		cf->data[7] = es->rxerr;
+	}
 
 	stats->rx_packets++;
 	stats->rx_bytes += cf->can_dlc;
@@ -838,11 +1191,11 @@
 
 	case CMD_CAN_ERROR_EVENT:
 		es.channel = 0;
-		es.status = cmd->u.usbcan.error_event.status_ch0;
-		es.txerr = cmd->u.usbcan.error_event.tx_errors_count_ch0;
-		es.rxerr = cmd->u.usbcan.error_event.rx_errors_count_ch0;
+		es.status = cmd->u.usbcan.can_error_event.status_ch0;
+		es.txerr = cmd->u.usbcan.can_error_event.tx_errors_count_ch0;
+		es.rxerr = cmd->u.usbcan.can_error_event.rx_errors_count_ch0;
 		es.usbcan.other_ch_status =
-			cmd->u.usbcan.error_event.status_ch1;
+			cmd->u.usbcan.can_error_event.status_ch1;
 		kvaser_usb_leaf_usbcan_conditionally_rx_error(dev, &es);
 
 		/* The USBCAN firmware supports up to 2 channels.
@@ -850,13 +1203,13 @@
 		 */
 		if (dev->nchannels == MAX_USBCAN_NET_DEVICES) {
 			es.channel = 1;
-			es.status = cmd->u.usbcan.error_event.status_ch1;
+			es.status = cmd->u.usbcan.can_error_event.status_ch1;
 			es.txerr =
-				cmd->u.usbcan.error_event.tx_errors_count_ch1;
+				cmd->u.usbcan.can_error_event.tx_errors_count_ch1;
 			es.rxerr =
-				cmd->u.usbcan.error_event.rx_errors_count_ch1;
+				cmd->u.usbcan.can_error_event.rx_errors_count_ch1;
 			es.usbcan.other_ch_status =
-				cmd->u.usbcan.error_event.status_ch0;
+				cmd->u.usbcan.can_error_event.status_ch0;
 			kvaser_usb_leaf_usbcan_conditionally_rx_error(dev, &es);
 		}
 		break;
@@ -873,11 +1226,11 @@
 
 	switch (cmd->id) {
 	case CMD_CAN_ERROR_EVENT:
-		es.channel = cmd->u.leaf.error_event.channel;
-		es.status = cmd->u.leaf.error_event.status;
-		es.txerr = cmd->u.leaf.error_event.tx_errors_count;
-		es.rxerr = cmd->u.leaf.error_event.rx_errors_count;
-		es.leaf.error_factor = cmd->u.leaf.error_event.error_factor;
+		es.channel = cmd->u.leaf.can_error_event.channel;
+		es.status = cmd->u.leaf.can_error_event.status;
+		es.txerr = cmd->u.leaf.can_error_event.tx_errors_count;
+		es.rxerr = cmd->u.leaf.can_error_event.rx_errors_count;
+		es.leaf.error_factor = cmd->u.leaf.can_error_event.error_factor;
 		break;
 	case CMD_LEAF_LOG_MESSAGE:
 		es.channel = cmd->u.leaf.log_message.channel;
@@ -939,7 +1292,7 @@
 	stats = &priv->netdev->stats;
 
 	if ((cmd->u.rx_can_header.flag & MSG_FLAG_ERROR_FRAME) &&
-	    (dev->card_data.leaf.family == KVASER_LEAF &&
+	    (dev->driver_info->family == KVASER_LEAF &&
 	     cmd->id == CMD_LEAF_LOG_MESSAGE)) {
 		kvaser_usb_leaf_leaf_rx_error(dev, cmd);
 		return;
@@ -955,7 +1308,7 @@
 		return;
 	}
 
-	switch (dev->card_data.leaf.family) {
+	switch (dev->driver_info->family) {
 	case KVASER_LEAF:
 		rx_data = cmd->u.leaf.rx_can.data;
 		break;
@@ -970,7 +1323,7 @@
 		return;
 	}
 
-	if (dev->card_data.leaf.family == KVASER_LEAF && cmd->id ==
+	if (dev->driver_info->family == KVASER_LEAF && cmd->id ==
 	    CMD_LEAF_LOG_MESSAGE) {
 		cf->can_id = le32_to_cpu(cmd->u.leaf.log_message.id);
 		if (cf->can_id & KVASER_EXTENDED_FRAME)
@@ -1009,6 +1362,74 @@
 	netif_rx(skb);
 }
 
+static void kvaser_usb_leaf_error_event_parameter(const struct kvaser_usb *dev,
+						  const struct kvaser_cmd *cmd)
+{
+	u16 info1 = 0;
+
+	switch (dev->driver_info->family) {
+	case KVASER_LEAF:
+		info1 = le16_to_cpu(cmd->u.leaf.error_event.info1);
+		break;
+	case KVASER_USBCAN:
+		info1 = le16_to_cpu(cmd->u.usbcan.error_event.info1);
+		break;
+	}
+
+	/* info1 will contain the offending cmd_no */
+	switch (info1) {
+	case CMD_SET_CTRL_MODE:
+		dev_warn(&dev->intf->dev,
+			 "CMD_SET_CTRL_MODE error in parameter\n");
+		break;
+
+	case CMD_SET_BUS_PARAMS:
+		dev_warn(&dev->intf->dev,
+			 "CMD_SET_BUS_PARAMS error in parameter\n");
+		break;
+
+	default:
+		dev_warn(&dev->intf->dev,
+			 "Unhandled parameter error event cmd_no (%u)\n",
+			 info1);
+		break;
+	}
+}
+
+static void kvaser_usb_leaf_error_event(const struct kvaser_usb *dev,
+					const struct kvaser_cmd *cmd)
+{
+	u8 error_code = 0;
+
+	switch (dev->driver_info->family) {
+	case KVASER_LEAF:
+		error_code = cmd->u.leaf.error_event.error_code;
+		break;
+	case KVASER_USBCAN:
+		error_code = cmd->u.usbcan.error_event.error_code;
+		break;
+	}
+
+	switch (error_code) {
+	case KVASER_USB_LEAF_ERROR_EVENT_TX_QUEUE_FULL:
+		/* Received additional CAN message, when firmware TX queue is
+		 * already full. Something is wrong with the driver.
+		 * This should never happen!
+		 */
+		dev_err(&dev->intf->dev,
+			"Received error event TX_QUEUE_FULL\n");
+		break;
+	case KVASER_USB_LEAF_ERROR_EVENT_PARAM:
+		kvaser_usb_leaf_error_event_parameter(dev, cmd);
+		break;
+
+	default:
+		dev_warn(&dev->intf->dev,
+			 "Unhandled error event (%d)\n", error_code);
+		break;
+	}
+}
+
 static void kvaser_usb_leaf_start_chip_reply(const struct kvaser_usb *dev,
 					     const struct kvaser_cmd *cmd)
 {
@@ -1049,9 +1470,31 @@
 	complete(&priv->stop_comp);
 }
 
+static void kvaser_usb_leaf_get_busparams_reply(const struct kvaser_usb *dev,
+						const struct kvaser_cmd *cmd)
+{
+	struct kvaser_usb_net_priv *priv;
+	u8 channel = cmd->u.busparams.channel;
+
+	if (channel >= dev->nchannels) {
+		dev_err(&dev->intf->dev,
+			"Invalid channel number (%d)\n", channel);
+		return;
+	}
+
+	priv = dev->nets[channel];
+	memcpy(&priv->busparams_nominal, &cmd->u.busparams.busparams,
+	       sizeof(priv->busparams_nominal));
+
+	complete(&priv->get_busparams_comp);
+}
+
 static void kvaser_usb_leaf_handle_command(const struct kvaser_usb *dev,
 					   const struct kvaser_cmd *cmd)
 {
+	if (kvaser_usb_leaf_verify_size(dev, cmd) < 0)
+		return;
+
 	switch (cmd->id) {
 	case CMD_START_CHIP_REPLY:
 		kvaser_usb_leaf_start_chip_reply(dev, cmd);
@@ -1067,14 +1510,14 @@
 		break;
 
 	case CMD_LEAF_LOG_MESSAGE:
-		if (dev->card_data.leaf.family != KVASER_LEAF)
+		if (dev->driver_info->family != KVASER_LEAF)
 			goto warn;
 		kvaser_usb_leaf_rx_can_msg(dev, cmd);
 		break;
 
 	case CMD_CHIP_STATE_EVENT:
 	case CMD_CAN_ERROR_EVENT:
-		if (dev->card_data.leaf.family == KVASER_LEAF)
+		if (dev->driver_info->family == KVASER_LEAF)
 			kvaser_usb_leaf_leaf_rx_error(dev, cmd);
 		else
 			kvaser_usb_leaf_usbcan_rx_error(dev, cmd);
@@ -1084,14 +1527,22 @@
 		kvaser_usb_leaf_tx_acknowledge(dev, cmd);
 		break;
 
+	case CMD_ERROR_EVENT:
+		kvaser_usb_leaf_error_event(dev, cmd);
+		break;
+
+	case CMD_GET_BUS_PARAMS_REPLY:
+		kvaser_usb_leaf_get_busparams_reply(dev, cmd);
+		break;
+
 	/* Ignored commands */
 	case CMD_USBCAN_CLOCK_OVERFLOW_EVENT:
-		if (dev->card_data.leaf.family != KVASER_USBCAN)
+		if (dev->driver_info->family != KVASER_USBCAN)
 			goto warn;
 		break;
 
 	case CMD_FLUSH_QUEUE_REPLY:
-		if (dev->card_data.leaf.family != KVASER_LEAF)
+		if (dev->driver_info->family != KVASER_LEAF)
 			goto warn;
 		break;
 
@@ -1140,7 +1591,7 @@
 	struct kvaser_cmd *cmd;
 	int rc;
 
-	cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
 	if (!cmd)
 		return -ENOMEM;
 
@@ -1164,7 +1615,7 @@
 {
 	int err;
 
-	init_completion(&priv->start_comp);
+	reinit_completion(&priv->start_comp);
 
 	err = kvaser_usb_leaf_send_simple_cmd(priv->dev, CMD_START_CHIP,
 					      priv->channel);
@@ -1180,9 +1631,12 @@
 
 static int kvaser_usb_leaf_stop_chip(struct kvaser_usb_net_priv *priv)
 {
+	struct kvaser_usb_net_leaf_priv *leaf = priv->sub_priv;
 	int err;
 
-	init_completion(&priv->stop_comp);
+	reinit_completion(&priv->stop_comp);
+
+	cancel_delayed_work(&leaf->chip_state_req_work);
 
 	err = kvaser_usb_leaf_send_simple_cmd(priv->dev, CMD_STOP_CHIP,
 					      priv->channel);
@@ -1206,7 +1660,7 @@
 	struct kvaser_cmd *cmd;
 	int rc;
 
-	cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
 	if (!cmd)
 		return -ENOMEM;
 
@@ -1225,28 +1679,40 @@
 {
 	struct kvaser_usb_dev_card_data *card_data = &dev->card_data;
 
-	dev->cfg = &kvaser_usb_leaf_dev_cfg;
 	card_data->ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES;
 
 	return 0;
 }
 
-static const struct can_bittiming_const kvaser_usb_leaf_bittiming_const = {
-	.name = "kvaser_usb",
-	.tseg1_min = KVASER_USB_TSEG1_MIN,
-	.tseg1_max = KVASER_USB_TSEG1_MAX,
-	.tseg2_min = KVASER_USB_TSEG2_MIN,
-	.tseg2_max = KVASER_USB_TSEG2_MAX,
-	.sjw_max = KVASER_USB_SJW_MAX,
-	.brp_min = KVASER_USB_BRP_MIN,
-	.brp_max = KVASER_USB_BRP_MAX,
-	.brp_inc = KVASER_USB_BRP_INC,
-};
+static int kvaser_usb_leaf_init_channel(struct kvaser_usb_net_priv *priv)
+{
+	struct kvaser_usb_net_leaf_priv *leaf;
+
+	leaf = devm_kzalloc(&priv->dev->intf->dev, sizeof(*leaf), GFP_KERNEL);
+	if (!leaf)
+		return -ENOMEM;
 
-static int kvaser_usb_leaf_set_bittiming(struct net_device *netdev)
+	leaf->net = priv;
+	INIT_DELAYED_WORK(&leaf->chip_state_req_work,
+			  kvaser_usb_leaf_chip_state_req_work);
+
+	priv->sub_priv = leaf;
+
+	return 0;
+}
+
+static void kvaser_usb_leaf_remove_channel(struct kvaser_usb_net_priv *priv)
+{
+	struct kvaser_usb_net_leaf_priv *leaf = priv->sub_priv;
+
+	if (leaf)
+		cancel_delayed_work_sync(&leaf->chip_state_req_work);
+}
+
+static int kvaser_usb_leaf_set_bittiming(const struct net_device *netdev,
+					 const struct kvaser_usb_busparams *busparams)
 {
 	struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
-	struct can_bittiming *bt = &priv->can.bittiming;
 	struct kvaser_usb *dev = priv->dev;
 	struct kvaser_cmd *cmd;
 	int rc;
@@ -1259,15 +1725,8 @@
 	cmd->len = CMD_HEADER_LEN + sizeof(struct kvaser_cmd_busparams);
 	cmd->u.busparams.channel = priv->channel;
 	cmd->u.busparams.tid = 0xff;
-	cmd->u.busparams.bitrate = cpu_to_le32(bt->bitrate);
-	cmd->u.busparams.sjw = bt->sjw;
-	cmd->u.busparams.tseg1 = bt->prop_seg + bt->phase_seg1;
-	cmd->u.busparams.tseg2 = bt->phase_seg2;
-
-	if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
-		cmd->u.busparams.no_samp = 3;
-	else
-		cmd->u.busparams.no_samp = 1;
+	memcpy(&cmd->u.busparams.busparams, busparams,
+	       sizeof(cmd->u.busparams.busparams));
 
 	rc = kvaser_usb_send_cmd(dev, cmd, cmd->len);
 
@@ -1275,6 +1734,27 @@
 	return rc;
 }
 
+static int kvaser_usb_leaf_get_busparams(struct kvaser_usb_net_priv *priv)
+{
+	int err;
+
+	if (priv->dev->driver_info->family == KVASER_USBCAN)
+		return -EOPNOTSUPP;
+
+	reinit_completion(&priv->get_busparams_comp);
+
+	err = kvaser_usb_leaf_send_simple_cmd(priv->dev, CMD_GET_BUS_PARAMS,
+					      priv->channel);
+	if (err)
+		return err;
+
+	if (!wait_for_completion_timeout(&priv->get_busparams_comp,
+					 msecs_to_jiffies(KVASER_USB_TIMEOUT)))
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
 static int kvaser_usb_leaf_set_mode(struct net_device *netdev,
 				    enum can_mode mode)
 {
@@ -1283,9 +1763,13 @@
 
 	switch (mode) {
 	case CAN_MODE_START:
+		kvaser_usb_unlink_tx_urbs(priv);
+
 		err = kvaser_usb_leaf_simple_cmd_async(priv, CMD_START_CHIP);
 		if (err)
 			return err;
+
+		priv->can.state = CAN_STATE_ERROR_ACTIVE;
 		break;
 	default:
 		return -EOPNOTSUPP;
@@ -1310,7 +1794,7 @@
 	struct usb_endpoint_descriptor *endpoint;
 	int i;
 
-	iface_desc = &dev->intf->altsetting[0];
+	iface_desc = dev->intf->cur_altsetting;
 
 	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
 		endpoint = &iface_desc->endpoint[i].desc;
@@ -1332,14 +1816,18 @@
 const struct kvaser_usb_dev_ops kvaser_usb_leaf_dev_ops = {
 	.dev_set_mode = kvaser_usb_leaf_set_mode,
 	.dev_set_bittiming = kvaser_usb_leaf_set_bittiming,
+	.dev_get_busparams = kvaser_usb_leaf_get_busparams,
 	.dev_set_data_bittiming = NULL,
+	.dev_get_data_busparams = NULL,
 	.dev_get_berr_counter = kvaser_usb_leaf_get_berr_counter,
 	.dev_setup_endpoints = kvaser_usb_leaf_setup_endpoints,
 	.dev_init_card = kvaser_usb_leaf_init_card,
+	.dev_init_channel = kvaser_usb_leaf_init_channel,
+	.dev_remove_channel = kvaser_usb_leaf_remove_channel,
 	.dev_get_software_info = kvaser_usb_leaf_get_software_info,
 	.dev_get_software_details = NULL,
 	.dev_get_card_info = kvaser_usb_leaf_get_card_info,
-	.dev_get_capabilities = NULL,
+	.dev_get_capabilities = kvaser_usb_leaf_get_capabilities,
 	.dev_set_opt_mode = kvaser_usb_leaf_set_opt_mode,
 	.dev_start_chip = kvaser_usb_leaf_start_chip,
 	.dev_stop_chip = kvaser_usb_leaf_stop_chip,
@@ -1348,11 +1836,3 @@
 	.dev_read_bulk_callback = kvaser_usb_leaf_read_bulk_callback,
 	.dev_frame_to_cmd = kvaser_usb_leaf_frame_to_cmd,
 };
-
-static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_dev_cfg = {
-	.clock = {
-		.freq = CAN_USB_CLOCK,
-	},
-	.timestamp_freq = 1,
-	.bittiming_const = &kvaser_usb_leaf_bittiming_const,
-};
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/usb/mcba_usb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/usb/mcba_usb.c
@@ -33,10 +33,6 @@
 #define MCBA_USB_RX_BUFF_SIZE 64
 #define MCBA_USB_TX_BUFF_SIZE (sizeof(struct mcba_usb_msg))
 
-/* MCBA endpoint numbers */
-#define MCBA_USB_EP_IN 1
-#define MCBA_USB_EP_OUT 1
-
 /* Microchip command id */
 #define MBCA_CMD_RECEIVE_MESSAGE 0xE3
 #define MBCA_CMD_I_AM_ALIVE_FROM_CAN 0xF5
@@ -51,6 +47,10 @@
 #define MCBA_VER_REQ_USB 1
 #define MCBA_VER_REQ_CAN 2
 
+/* Drive the CAN_RES signal LOW "0" to activate R24 and R25 */
+#define MCBA_VER_TERMINATION_ON 0
+#define MCBA_VER_TERMINATION_OFF 1
+
 #define MCBA_SIDL_EXID_MASK 0x8
 #define MCBA_DLC_MASK 0xf
 #define MCBA_DLC_RTR_MASK 0x40
@@ -82,6 +82,10 @@
 	bool can_ka_first_pass;
 	bool can_speed_check;
 	atomic_t free_ctx_cnt;
+	void *rxbuf[MCBA_MAX_RX_URBS];
+	dma_addr_t rxbuf_dma[MCBA_MAX_RX_URBS];
+	int rx_pipe;
+	int tx_pipe;
 };
 
 /* CAN frame */
@@ -270,10 +274,8 @@
 
 	memcpy(buf, usb_msg, MCBA_USB_TX_BUFF_SIZE);
 
-	usb_fill_bulk_urb(urb, priv->udev,
-			  usb_sndbulkpipe(priv->udev, MCBA_USB_EP_OUT), buf,
-			  MCBA_USB_TX_BUFF_SIZE, mcba_usb_write_bulk_callback,
-			  ctx);
+	usb_fill_bulk_urb(urb, priv->udev, priv->tx_pipe, buf, MCBA_USB_TX_BUFF_SIZE,
+			  mcba_usb_write_bulk_callback, ctx);
 
 	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 	usb_anchor_urb(urb, &priv->tx_submitted);
@@ -326,8 +328,6 @@
 	if (!ctx)
 		return NETDEV_TX_BUSY;
 
-	can_put_echo_skb(skb, priv->netdev, ctx->ndx);
-
 	if (cf->can_id & CAN_EFF_FLAG) {
 		/* SIDH    | SIDL                 | EIDH   | EIDL
 		 * 28 - 21 | 20 19 18 x x x 17 16 | 15 - 8 | 7 - 0
@@ -357,6 +357,8 @@
 	if (cf->can_id & CAN_RTR_FLAG)
 		usb_msg.dlc |= MCBA_DLC_RTR_MASK;
 
+	can_put_echo_skb(skb, priv->netdev, ctx->ndx);
+
 	err = mcba_usb_xmit(priv, (struct mcba_usb_msg *)&usb_msg, ctx);
 	if (err)
 		goto xmit_failed;
@@ -366,7 +368,6 @@
 xmit_failed:
 	can_free_echo_skb(priv->netdev, ctx->ndx);
 	mcba_usb_free_ctx(ctx);
-	dev_kfree_skb(skb);
 	stats->tx_dropped++;
 
 	return NETDEV_TX_OK;
@@ -472,7 +473,7 @@
 		priv->usb_ka_first_pass = false;
 	}
 
-	if (msg->termination_state)
+	if (msg->termination_state == MCBA_VER_TERMINATION_ON)
 		priv->can.termination = MCBA_TERMINATION_ENABLED;
 	else
 		priv->can.termination = MCBA_TERMINATION_DISABLED;
@@ -609,7 +610,7 @@
 resubmit_urb:
 
 	usb_fill_bulk_urb(urb, priv->udev,
-			  usb_rcvbulkpipe(priv->udev, MCBA_USB_EP_OUT),
+			  priv->rx_pipe,
 			  urb->transfer_buffer, MCBA_USB_RX_BUFF_SIZE,
 			  mcba_usb_read_bulk_callback, priv);
 
@@ -633,6 +634,7 @@
 	for (i = 0; i < MCBA_MAX_RX_URBS; i++) {
 		struct urb *urb = NULL;
 		u8 *buf;
+		dma_addr_t buf_dma;
 
 		/* create a URB, and a buffer for it */
 		urb = usb_alloc_urb(0, GFP_KERNEL);
@@ -642,7 +644,7 @@
 		}
 
 		buf = usb_alloc_coherent(priv->udev, MCBA_USB_RX_BUFF_SIZE,
-					 GFP_KERNEL, &urb->transfer_dma);
+					 GFP_KERNEL, &buf_dma);
 		if (!buf) {
 			netdev_err(netdev, "No memory left for USB buffer\n");
 			usb_free_urb(urb);
@@ -650,8 +652,10 @@
 			break;
 		}
 
+		urb->transfer_dma = buf_dma;
+
 		usb_fill_bulk_urb(urb, priv->udev,
-				  usb_rcvbulkpipe(priv->udev, MCBA_USB_EP_IN),
+				  priv->rx_pipe,
 				  buf, MCBA_USB_RX_BUFF_SIZE,
 				  mcba_usb_read_bulk_callback, priv);
 		urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
@@ -661,11 +665,14 @@
 		if (err) {
 			usb_unanchor_urb(urb);
 			usb_free_coherent(priv->udev, MCBA_USB_RX_BUFF_SIZE,
-					  buf, urb->transfer_dma);
+					  buf, buf_dma);
 			usb_free_urb(urb);
 			break;
 		}
 
+		priv->rxbuf[i] = buf;
+		priv->rxbuf_dma[i] = buf_dma;
+
 		/* Drop reference, USB core will take care of freeing it */
 		usb_free_urb(urb);
 	}
@@ -708,7 +715,14 @@
 
 static void mcba_urb_unlink(struct mcba_priv *priv)
 {
+	int i;
+
 	usb_kill_anchored_urbs(&priv->rx_submitted);
+
+	for (i = 0; i < MCBA_MAX_RX_URBS; ++i)
+		usb_free_coherent(priv->udev, MCBA_USB_RX_BUFF_SIZE,
+				  priv->rxbuf[i], priv->rxbuf_dma[i]);
+
 	usb_kill_anchored_urbs(&priv->tx_submitted);
 }
 
@@ -779,9 +793,9 @@
 	};
 
 	if (term == MCBA_TERMINATION_ENABLED)
-		usb_msg.termination = 1;
+		usb_msg.termination = MCBA_VER_TERMINATION_ON;
 	else
-		usb_msg.termination = 0;
+		usb_msg.termination = MCBA_VER_TERMINATION_OFF;
 
 	mcba_usb_xmit_cmd(priv, (struct mcba_usb_msg *)&usb_msg);
 
@@ -795,6 +809,13 @@
 	struct mcba_priv *priv;
 	int err = -ENOMEM;
 	struct usb_device *usbdev = interface_to_usbdev(intf);
+	struct usb_endpoint_descriptor *in, *out;
+
+	err = usb_find_common_endpoints(intf->cur_altsetting, &in, &out, NULL, NULL);
+	if (err) {
+		dev_err(&intf->dev, "Can't find endpoints\n");
+		return err;
+	}
 
 	netdev = alloc_candev(sizeof(struct mcba_priv), MCBA_MAX_TX_URBS);
 	if (!netdev) {
@@ -840,6 +861,9 @@
 		goto cleanup_free_candev;
 	}
 
+	priv->rx_pipe = usb_rcvbulkpipe(priv->udev, in->bEndpointAddress);
+	priv->tx_pipe = usb_sndbulkpipe(priv->udev, out->bEndpointAddress);
+
 	devm_can_led_init(netdev);
 
 	/* Start USB dev only if we have successfully registered CAN device */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/usb/peak_usb/pcan_usb_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/usb/peak_usb/pcan_usb_core.c
@@ -130,14 +130,55 @@
 	/* protect from getting time before setting now */
 	if (ktime_to_ns(time_ref->tv_host)) {
 		u64 delta_us;
+		s64 delta_ts = 0;
 
-		delta_us = ts - time_ref->ts_dev_2;
-		if (ts < time_ref->ts_dev_2)
-			delta_us &= (1 << time_ref->adapter->ts_used_bits) - 1;
+		/* General case: dev_ts_1 < dev_ts_2 < ts, with:
+		 *
+		 * - dev_ts_1 = previous sync timestamp
+		 * - dev_ts_2 = last sync timestamp
+		 * - ts = event timestamp
+		 * - ts_period = known sync period (theoretical)
+		 *             ~ dev_ts2 - dev_ts1
+		 * *but*:
+		 *
+		 * - time counters wrap (see adapter->ts_used_bits)
+		 * - sometimes, dev_ts_1 < ts < dev_ts2
+		 *
+		 * "normal" case (sync time counters increase):
+		 * must take into account case when ts wraps (tsw)
+		 *
+		 *      < ts_period > <          >
+		 *     |             |            |
+		 *  ---+--------+----+-------0-+--+-->
+		 *     ts_dev_1 |    ts_dev_2  |
+		 *              ts             tsw
+		 */
+		if (time_ref->ts_dev_1 < time_ref->ts_dev_2) {
+			/* case when event time (tsw) wraps */
+			if (ts < time_ref->ts_dev_1)
+				delta_ts = BIT_ULL(time_ref->adapter->ts_used_bits);
+
+		/* Otherwise, sync time counter (ts_dev_2) has wrapped:
+		 * handle case when event time (tsn) hasn't.
+		 *
+		 *      < ts_period > <          >
+		 *     |             |            |
+		 *  ---+--------+--0-+---------+--+-->
+		 *     ts_dev_1 |    ts_dev_2  |
+		 *              tsn            ts
+		 */
+		} else if (time_ref->ts_dev_1 < ts) {
+			delta_ts = -BIT_ULL(time_ref->adapter->ts_used_bits);
+		}
+
+		/* add delay between last sync and event timestamps */
+		delta_ts += (signed int)(ts - time_ref->ts_dev_2);
 
-		delta_us += time_ref->ts_total;
+		/* add time from beginning to last sync */
+		delta_ts += time_ref->ts_total;
 
-		delta_us *= time_ref->adapter->us_per_ts_scale;
+		/* convert ticks number into microseconds */
+		delta_us = delta_ts * time_ref->adapter->us_per_ts_scale;
 		delta_us >>= time_ref->adapter->us_per_ts_shift;
 
 		*time = ktime_add_us(time_ref->tv_host_0, delta_us);
@@ -815,7 +856,7 @@
 	if (dev->adapter->dev_set_bus) {
 		err = dev->adapter->dev_set_bus(dev, 0);
 		if (err)
-			goto lbl_unregister_candev;
+			goto adap_dev_free;
 	}
 
 	/* get device number early */
@@ -827,6 +868,10 @@
 
 	return 0;
 
+adap_dev_free:
+	if (dev->adapter->dev_free)
+		dev->adapter->dev_free(dev);
+
 lbl_unregister_candev:
 	unregister_candev(netdev);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/usb/peak_usb/pcan_usb_fd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/usb/peak_usb/pcan_usb_fd.c
@@ -468,12 +468,18 @@
 				     struct pucan_msg *rx_msg)
 {
 	struct pucan_rx_msg *rm = (struct pucan_rx_msg *)rx_msg;
-	struct peak_usb_device *dev = usb_if->dev[pucan_msg_get_channel(rm)];
-	struct net_device *netdev = dev->netdev;
+	struct peak_usb_device *dev;
+	struct net_device *netdev;
 	struct canfd_frame *cfd;
 	struct sk_buff *skb;
 	const u16 rx_msg_flags = le16_to_cpu(rm->flags);
 
+	if (pucan_msg_get_channel(rm) >= ARRAY_SIZE(usb_if->dev))
+		return -ENOMEM;
+
+	dev = usb_if->dev[pucan_msg_get_channel(rm)];
+	netdev = dev->netdev;
+
 	if (rx_msg_flags & PUCAN_MSG_EXT_DATA_LEN) {
 		/* CANFD frame case */
 		skb = alloc_canfd_skb(netdev, &cfd);
@@ -506,11 +512,11 @@
 	else
 		memcpy(cfd->data, rm->d, cfd->len);
 
-	peak_usb_netif_rx(skb, &usb_if->time_ref, le32_to_cpu(rm->ts_low));
-
 	netdev->stats.rx_packets++;
 	netdev->stats.rx_bytes += cfd->len;
 
+	peak_usb_netif_rx(skb, &usb_if->time_ref, le32_to_cpu(rm->ts_low));
+
 	return 0;
 }
 
@@ -519,15 +525,21 @@
 				     struct pucan_msg *rx_msg)
 {
 	struct pucan_status_msg *sm = (struct pucan_status_msg *)rx_msg;
-	struct peak_usb_device *dev = usb_if->dev[pucan_stmsg_get_channel(sm)];
-	struct pcan_usb_fd_device *pdev =
-			container_of(dev, struct pcan_usb_fd_device, dev);
+	struct pcan_usb_fd_device *pdev;
 	enum can_state new_state = CAN_STATE_ERROR_ACTIVE;
 	enum can_state rx_state, tx_state;
-	struct net_device *netdev = dev->netdev;
+	struct peak_usb_device *dev;
+	struct net_device *netdev;
 	struct can_frame *cf;
 	struct sk_buff *skb;
 
+	if (pucan_stmsg_get_channel(sm) >= ARRAY_SIZE(usb_if->dev))
+		return -ENOMEM;
+
+	dev = usb_if->dev[pucan_stmsg_get_channel(sm)];
+	pdev = container_of(dev, struct pcan_usb_fd_device, dev);
+	netdev = dev->netdev;
+
 	/* nothing should be sent while in BUS_OFF state */
 	if (dev->can.state == CAN_STATE_BUS_OFF)
 		return 0;
@@ -539,11 +551,10 @@
 	} else if (sm->channel_p_w_b & PUCAN_BUS_WARNING) {
 		new_state = CAN_STATE_ERROR_WARNING;
 	} else {
-		/* no error bit (so, no error skb, back to active state) */
-		dev->can.state = CAN_STATE_ERROR_ACTIVE;
+		/* back to (or still in) ERROR_ACTIVE state */
+		new_state = CAN_STATE_ERROR_ACTIVE;
 		pdev->bec.txerr = 0;
 		pdev->bec.rxerr = 0;
-		return 0;
 	}
 
 	/* state hasn't changed */
@@ -566,11 +577,11 @@
 	if (!skb)
 		return -ENOMEM;
 
-	peak_usb_netif_rx(skb, &usb_if->time_ref, le32_to_cpu(sm->ts_low));
-
 	netdev->stats.rx_packets++;
 	netdev->stats.rx_bytes += cf->can_dlc;
 
+	peak_usb_netif_rx(skb, &usb_if->time_ref, le32_to_cpu(sm->ts_low));
+
 	return 0;
 }
 
@@ -579,9 +590,14 @@
 				    struct pucan_msg *rx_msg)
 {
 	struct pucan_error_msg *er = (struct pucan_error_msg *)rx_msg;
-	struct peak_usb_device *dev = usb_if->dev[pucan_ermsg_get_channel(er)];
-	struct pcan_usb_fd_device *pdev =
-			container_of(dev, struct pcan_usb_fd_device, dev);
+	struct pcan_usb_fd_device *pdev;
+	struct peak_usb_device *dev;
+
+	if (pucan_ermsg_get_channel(er) >= ARRAY_SIZE(usb_if->dev))
+		return -EINVAL;
+
+	dev = usb_if->dev[pucan_ermsg_get_channel(er)];
+	pdev = container_of(dev, struct pcan_usb_fd_device, dev);
 
 	/* keep a trace of tx and rx error counters for later use */
 	pdev->bec.txerr = er->tx_err_cnt;
@@ -595,11 +611,17 @@
 				      struct pucan_msg *rx_msg)
 {
 	struct pcan_ufd_ovr_msg *ov = (struct pcan_ufd_ovr_msg *)rx_msg;
-	struct peak_usb_device *dev = usb_if->dev[pufd_omsg_get_channel(ov)];
-	struct net_device *netdev = dev->netdev;
+	struct peak_usb_device *dev;
+	struct net_device *netdev;
 	struct can_frame *cf;
 	struct sk_buff *skb;
 
+	if (pufd_omsg_get_channel(ov) >= ARRAY_SIZE(usb_if->dev))
+		return -EINVAL;
+
+	dev = usb_if->dev[pufd_omsg_get_channel(ov)];
+	netdev = dev->netdev;
+
 	/* allocate an skb to store the error frame */
 	skb = alloc_can_err_skb(netdev, &cf);
 	if (!skb)
@@ -716,6 +738,9 @@
 	u16 tx_msg_size, tx_msg_flags;
 	u8 can_dlc;
 
+	if (cfd->len > CANFD_MAX_DLEN)
+		return -EINVAL;
+
 	tx_msg_size = ALIGN(sizeof(struct pucan_tx_msg) + cfd->len, 4);
 	tx_msg->size = cpu_to_le16(tx_msg_size);
 	tx_msg->type = cpu_to_le16(PUCAN_MSG_CAN_TX);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/usb/ucan.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/usb/ucan.c
@@ -792,7 +792,7 @@
 			  up);
 
 	usb_anchor_urb(urb, &up->rx_urbs);
-	ret = usb_submit_urb(urb, GFP_KERNEL);
+	ret = usb_submit_urb(urb, GFP_ATOMIC);
 
 	if (ret < 0) {
 		netdev_err(up->netdev,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/usb/usb_8dev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/usb/usb_8dev.c
@@ -137,7 +137,8 @@
 	u8 *cmd_msg_buffer;
 
 	struct mutex usb_8dev_cmd_lock;
-
+	void *rxbuf[MAX_RX_URBS];
+	dma_addr_t rxbuf_dma[MAX_RX_URBS];
 };
 
 /* tx frame */
@@ -441,9 +442,10 @@
 
 	if (rx_errors)
 		stats->rx_errors++;
-
-	cf->data[6] = txerr;
-	cf->data[7] = rxerr;
+	if (priv->can.state != CAN_STATE_BUS_OFF) {
+		cf->data[6] = txerr;
+		cf->data[7] = rxerr;
+	}
 
 	priv->bec.txerr = txerr;
 	priv->bec.rxerr = rxerr;
@@ -669,9 +671,20 @@
 	atomic_inc(&priv->active_tx_urbs);
 
 	err = usb_submit_urb(urb, GFP_ATOMIC);
-	if (unlikely(err))
-		goto failed;
-	else if (atomic_read(&priv->active_tx_urbs) >= MAX_TX_URBS)
+	if (unlikely(err)) {
+		can_free_echo_skb(netdev, context->echo_index);
+
+		usb_unanchor_urb(urb);
+		usb_free_coherent(priv->udev, size, buf, urb->transfer_dma);
+
+		atomic_dec(&priv->active_tx_urbs);
+
+		if (err == -ENODEV)
+			netif_device_detach(netdev);
+		else
+			netdev_warn(netdev, "failed tx_urb %d\n", err);
+		stats->tx_dropped++;
+	} else if (atomic_read(&priv->active_tx_urbs) >= MAX_TX_URBS)
 		/* Slow down tx path */
 		netif_stop_queue(netdev);
 
@@ -690,19 +703,6 @@
 
 	return NETDEV_TX_BUSY;
 
-failed:
-	can_free_echo_skb(netdev, context->echo_index);
-
-	usb_unanchor_urb(urb);
-	usb_free_coherent(priv->udev, size, buf, urb->transfer_dma);
-
-	atomic_dec(&priv->active_tx_urbs);
-
-	if (err == -ENODEV)
-		netif_device_detach(netdev);
-	else
-		netdev_warn(netdev, "failed tx_urb %d\n", err);
-
 nomembuf:
 	usb_free_urb(urb);
 
@@ -733,6 +733,7 @@
 	for (i = 0; i < MAX_RX_URBS; i++) {
 		struct urb *urb = NULL;
 		u8 *buf;
+		dma_addr_t buf_dma;
 
 		/* create a URB, and a buffer for it */
 		urb = usb_alloc_urb(0, GFP_KERNEL);
@@ -742,7 +743,7 @@
 		}
 
 		buf = usb_alloc_coherent(priv->udev, RX_BUFFER_SIZE, GFP_KERNEL,
-					 &urb->transfer_dma);
+					 &buf_dma);
 		if (!buf) {
 			netdev_err(netdev, "No memory left for USB buffer\n");
 			usb_free_urb(urb);
@@ -750,6 +751,8 @@
 			break;
 		}
 
+		urb->transfer_dma = buf_dma;
+
 		usb_fill_bulk_urb(urb, priv->udev,
 				  usb_rcvbulkpipe(priv->udev,
 						  USB_8DEV_ENDP_DATA_RX),
@@ -767,6 +770,9 @@
 			break;
 		}
 
+		priv->rxbuf[i] = buf;
+		priv->rxbuf_dma[i] = buf_dma;
+
 		/* Drop reference, USB core will take care of freeing it */
 		usb_free_urb(urb);
 	}
@@ -836,6 +842,10 @@
 
 	usb_kill_anchored_urbs(&priv->rx_submitted);
 
+	for (i = 0; i < MAX_RX_URBS; ++i)
+		usb_free_coherent(priv->udev, RX_BUFFER_SIZE,
+				  priv->rxbuf[i], priv->rxbuf_dma[i]);
+
 	usb_kill_anchored_urbs(&priv->tx_submitted);
 	atomic_set(&priv->active_tx_urbs, 0);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/vcan.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/vcan.c
@@ -153,7 +153,7 @@
 	dev->addr_len		= 0;
 	dev->tx_queue_len	= 0;
 	dev->flags		= IFF_NOARP;
-	dev->ml_priv		= netdev_priv(dev);
+	can_set_ml_priv(dev, netdev_priv(dev));
 
 	/* set flags according to driver capabilities */
 	if (echo)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/vxcan.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/vxcan.c
@@ -39,6 +39,7 @@
 	struct net_device *peer;
 	struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
 	struct net_device_stats *peerstats, *srcstats = &dev->stats;
+	u8 len;
 
 	if (can_dropped_invalid_skb(dev, skb))
 		return NETDEV_TX_OK;
@@ -61,12 +62,13 @@
 	skb->dev        = peer;
 	skb->ip_summed  = CHECKSUM_UNNECESSARY;
 
+	len = cfd->len;
 	if (netif_rx_ni(skb) == NET_RX_SUCCESS) {
 		srcstats->tx_packets++;
-		srcstats->tx_bytes += cfd->len;
+		srcstats->tx_bytes += len;
 		peerstats = &peer->stats;
 		peerstats->rx_packets++;
-		peerstats->rx_bytes += cfd->len;
+		peerstats->rx_bytes += len;
 	}
 
 out_unlock:
@@ -139,15 +141,19 @@
 
 static void vxcan_setup(struct net_device *dev)
 {
+	struct can_ml_priv *can_ml;
+
 	dev->type		= ARPHRD_CAN;
 	dev->mtu		= CANFD_MTU;
 	dev->hard_header_len	= 0;
 	dev->addr_len		= 0;
 	dev->tx_queue_len	= 0;
-	dev->flags		= (IFF_NOARP|IFF_ECHO);
+	dev->flags		= IFF_NOARP;
 	dev->netdev_ops		= &vxcan_netdev_ops;
 	dev->needs_free_netdev	= true;
-	dev->ml_priv		= netdev_priv(dev) + ALIGN(sizeof(struct vxcan_priv), NETDEV_ALIGN);
+
+	can_ml = netdev_priv(dev) + ALIGN(sizeof(struct vxcan_priv), NETDEV_ALIGN);
+	can_set_ml_priv(dev, can_ml);
 }
 
 /* forward declaration for rtnl_create_link() */
@@ -173,12 +179,7 @@
 
 		nla_peer = data[VXCAN_INFO_PEER];
 		ifmp = nla_data(nla_peer);
-		err = rtnl_nla_parse_ifla(peer_tb,
-					  nla_data(nla_peer) +
-					  sizeof(struct ifinfomsg),
-					  nla_len(nla_peer) -
-					  sizeof(struct ifinfomsg),
-					  NULL);
+		err = rtnl_nla_parse_ifinfomsg(peer_tb, nla_peer, extack);
 		if (err < 0)
 			return err;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/can/xilinx_can.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/can/xilinx_can.c
@@ -60,6 +60,8 @@
 	XCAN_TXMSG_BASE_OFFSET	= 0x0100, /* TX Message Space */
 	XCAN_RXMSG_BASE_OFFSET	= 0x1100, /* RX Message Space */
 	XCAN_RXMSG_2_BASE_OFFSET	= 0x2100, /* RX Message Space */
+	XCAN_AFR_2_MASK_OFFSET	= 0x0A00, /* Acceptance Filter MASK */
+	XCAN_AFR_2_ID_OFFSET	= 0x0A04, /* Acceptance Filter ID */
 };
 
 #define XCAN_FRAME_ID_OFFSET(frame_base)	((frame_base) + 0x00)
@@ -194,7 +196,7 @@
  */
 struct xcan_priv {
 	struct can_priv can;
-	spinlock_t tx_lock;
+	spinlock_t tx_lock; /* Lock for synchronizing TX interrupt handling */
 	unsigned int tx_head;
 	unsigned int tx_tail;
 	unsigned int tx_max;
@@ -237,7 +239,7 @@
 };
 
 /* AXI CANFD Data Bittiming constants as per AXI CANFD 1.0 specs */
-static struct can_bittiming_const xcan_data_bittiming_const_canfd = {
+static const struct can_bittiming_const xcan_data_bittiming_const_canfd = {
 	.name = DRIVER_NAME,
 	.tseg1_min = 1,
 	.tseg1_max = 16,
@@ -257,20 +259,20 @@
 	.tseg2_min = 1,
 	.tseg2_max = 128,
 	.sjw_max = 128,
-	.brp_min = 1,
+	.brp_min = 2,
 	.brp_max = 256,
 	.brp_inc = 1,
 };
 
 /* AXI CANFD 2.0 Data Bittiming constants as per AXI CANFD 2.0 spec */
-static struct can_bittiming_const xcan_data_bittiming_const_canfd2 = {
+static const struct can_bittiming_const xcan_data_bittiming_const_canfd2 = {
 	.name = DRIVER_NAME,
 	.tseg1_min = 1,
 	.tseg1_max = 32,
 	.tseg2_min = 1,
 	.tseg2_max = 16,
 	.sjw_max = 16,
-	.brp_min = 1,
+	.brp_min = 2,
 	.brp_max = 256,
 	.brp_inc = 1,
 };
@@ -400,7 +402,7 @@
 				XCAN_SR_CONFIG_MASK;
 	if (!is_config_mode) {
 		netdev_alert(ndev,
-		     "BUG! Cannot set bittiming - CAN is not in config mode\n");
+			     "BUG! Cannot set bittiming - CAN is not in config mode\n");
 		return -EPERM;
 	}
 
@@ -470,7 +472,13 @@
 	if (err < 0)
 		return err;
 
-	/* Enable interrupts */
+	/* Enable interrupts
+	 *
+	 * We enable the ERROR interrupt even with
+	 * CAN_CTRLMODE_BERR_REPORTING disabled as there is no
+	 * dedicated interrupt for a state change to
+	 * ERROR_WARNING/ERROR_PASSIVE.
+	 */
 	ier = XCAN_IXR_TXOK_MASK | XCAN_IXR_BSOFF_MASK |
 		XCAN_IXR_WKUP_MASK | XCAN_IXR_SLP_MASK |
 		XCAN_IXR_ERROR_MASK | XCAN_IXR_RXOFLW_MASK |
@@ -482,11 +490,10 @@
 	priv->write_reg(priv, XCAN_IER_OFFSET, ier);
 
 	/* Check whether it is loopback mode or normal mode  */
-	if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {
+	if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)
 		reg_msr = XCAN_MSR_LBACK_MASK;
-	} else {
+	else
 		reg_msr = 0x0;
-	}
 
 	/* enable the first extended filter, if any, as cores with extended
 	 * filtering default to non-receipt if all filters are disabled
@@ -537,16 +544,17 @@
 
 /**
  * xcan_write_frame - Write a frame to HW
- * @priv:		Driver private data structure
+ * @ndev:		Pointer to net_device structure
  * @skb:		sk_buff pointer that contains data to be Txed
  * @frame_offset:	Register offset to write the frame to
  */
-static void xcan_write_frame(struct xcan_priv *priv, struct sk_buff *skb,
+static void xcan_write_frame(struct net_device *ndev, struct sk_buff *skb,
 			     int frame_offset)
 {
 	u32 id, dlc, data[2] = {0, 0};
 	struct canfd_frame *cf = (struct canfd_frame *)skb->data;
 	u32 ramoff, dwindex = 0, i;
+	struct xcan_priv *priv = netdev_priv(ndev);
 
 	/* Watch carefully on the bit sequence */
 	if (cf->can_id & CAN_EFF_FLAG) {
@@ -582,6 +590,14 @@
 		dlc |= XCAN_DLCR_EDL_MASK;
 	}
 
+	if (!(priv->devtype.flags & XCAN_FLAG_TX_MAILBOXES) &&
+	    (priv->devtype.flags & XCAN_FLAG_TXFEMP))
+		can_put_echo_skb(skb, ndev, priv->tx_head % priv->tx_max);
+	else
+		can_put_echo_skb(skb, ndev, 0);
+
+	priv->tx_head++;
+
 	priv->write_reg(priv, XCAN_FRAME_ID_OFFSET(frame_offset), id);
 	/* If the CAN frame is RTR frame this write triggers transmission
 	 * (not on CAN FD)
@@ -633,13 +649,9 @@
 			XCAN_SR_TXFLL_MASK))
 		return -ENOSPC;
 
-	can_put_echo_skb(skb, ndev, priv->tx_head % priv->tx_max);
-
 	spin_lock_irqsave(&priv->tx_lock, flags);
 
-	priv->tx_head++;
-
-	xcan_write_frame(priv, skb, XCAN_TXFIFO_OFFSET);
+	xcan_write_frame(ndev, skb, XCAN_TXFIFO_OFFSET);
 
 	/* Clear TX-FIFO-empty interrupt for xcan_tx_interrupt() */
 	if (priv->tx_max > 1)
@@ -670,13 +682,9 @@
 		     BIT(XCAN_TX_MAILBOX_IDX)))
 		return -ENOSPC;
 
-	can_put_echo_skb(skb, ndev, 0);
-
 	spin_lock_irqsave(&priv->tx_lock, flags);
 
-	priv->tx_head++;
-
-	xcan_write_frame(priv, skb,
+	xcan_write_frame(ndev, skb,
 			 XCAN_TXMSG_FRAME_OFFSET(XCAN_TX_MAILBOX_IDX));
 
 	/* Mark buffer as ready for transmit */
@@ -981,12 +989,9 @@
 {
 	struct xcan_priv *priv = netdev_priv(ndev);
 	struct net_device_stats *stats = &ndev->stats;
-	struct can_frame *cf;
-	struct sk_buff *skb;
+	struct can_frame cf = { };
 	u32 err_status;
 
-	skb = alloc_can_err_skb(ndev, &cf);
-
 	err_status = priv->read_reg(priv, XCAN_ESR_OFFSET);
 	priv->write_reg(priv, XCAN_ESR_OFFSET, err_status);
 
@@ -996,32 +1001,27 @@
 		/* Leave device in Config Mode in bus-off state */
 		priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_RESET_MASK);
 		can_bus_off(ndev);
-		if (skb)
-			cf->can_id |= CAN_ERR_BUSOFF;
+		cf.can_id |= CAN_ERR_BUSOFF;
 	} else {
 		enum can_state new_state = xcan_current_error_state(ndev);
 
 		if (new_state != priv->can.state)
-			xcan_set_error_state(ndev, new_state, skb ? cf : NULL);
+			xcan_set_error_state(ndev, new_state, &cf);
 	}
 
 	/* Check for Arbitration lost interrupt */
 	if (isr & XCAN_IXR_ARBLST_MASK) {
 		priv->can.can_stats.arbitration_lost++;
-		if (skb) {
-			cf->can_id |= CAN_ERR_LOSTARB;
-			cf->data[0] = CAN_ERR_LOSTARB_UNSPEC;
-		}
+		cf.can_id |= CAN_ERR_LOSTARB;
+		cf.data[0] = CAN_ERR_LOSTARB_UNSPEC;
 	}
 
 	/* Check for RX FIFO Overflow interrupt */
 	if (isr & XCAN_IXR_RXOFLW_MASK) {
 		stats->rx_over_errors++;
 		stats->rx_errors++;
-		if (skb) {
-			cf->can_id |= CAN_ERR_CRTL;
-			cf->data[1] |= CAN_ERR_CRTL_RX_OVERFLOW;
-		}
+		cf.can_id |= CAN_ERR_CRTL;
+		cf.data[1] |= CAN_ERR_CRTL_RX_OVERFLOW;
 	}
 
 	/* Check for RX Match Not Finished interrupt */
@@ -1029,68 +1029,77 @@
 		stats->rx_dropped++;
 		stats->rx_errors++;
 		netdev_err(ndev, "RX match not finished, frame discarded\n");
-		if (skb) {
-			cf->can_id |= CAN_ERR_CRTL;
-			cf->data[1] |= CAN_ERR_CRTL_UNSPEC;
-		}
+		cf.can_id |= CAN_ERR_CRTL;
+		cf.data[1] |= CAN_ERR_CRTL_UNSPEC;
 	}
 
 	/* Check for error interrupt */
 	if (isr & XCAN_IXR_ERROR_MASK) {
-		if (skb)
-			cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+		bool berr_reporting = false;
+
+		if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) {
+			berr_reporting = true;
+			cf.can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+		}
 
 		/* Check for Ack error interrupt */
 		if (err_status & XCAN_ESR_ACKER_MASK) {
 			stats->tx_errors++;
-			if (skb) {
-				cf->can_id |= CAN_ERR_ACK;
-				cf->data[3] = CAN_ERR_PROT_LOC_ACK;
+			if (berr_reporting) {
+				cf.can_id |= CAN_ERR_ACK;
+				cf.data[3] = CAN_ERR_PROT_LOC_ACK;
 			}
 		}
 
 		/* Check for Bit error interrupt */
 		if (err_status & XCAN_ESR_BERR_MASK) {
 			stats->tx_errors++;
-			if (skb) {
-				cf->can_id |= CAN_ERR_PROT;
-				cf->data[2] = CAN_ERR_PROT_BIT;
+			if (berr_reporting) {
+				cf.can_id |= CAN_ERR_PROT;
+				cf.data[2] = CAN_ERR_PROT_BIT;
 			}
 		}
 
 		/* Check for Stuff error interrupt */
 		if (err_status & XCAN_ESR_STER_MASK) {
 			stats->rx_errors++;
-			if (skb) {
-				cf->can_id |= CAN_ERR_PROT;
-				cf->data[2] = CAN_ERR_PROT_STUFF;
+			if (berr_reporting) {
+				cf.can_id |= CAN_ERR_PROT;
+				cf.data[2] = CAN_ERR_PROT_STUFF;
 			}
 		}
 
 		/* Check for Form error interrupt */
 		if (err_status & XCAN_ESR_FMER_MASK) {
 			stats->rx_errors++;
-			if (skb) {
-				cf->can_id |= CAN_ERR_PROT;
-				cf->data[2] = CAN_ERR_PROT_FORM;
+			if (berr_reporting) {
+				cf.can_id |= CAN_ERR_PROT;
+				cf.data[2] = CAN_ERR_PROT_FORM;
 			}
 		}
 
 		/* Check for CRC error interrupt */
 		if (err_status & XCAN_ESR_CRCER_MASK) {
 			stats->rx_errors++;
-			if (skb) {
-				cf->can_id |= CAN_ERR_PROT;
-				cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
+			if (berr_reporting) {
+				cf.can_id |= CAN_ERR_PROT;
+				cf.data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
 			}
 		}
 		priv->can.can_stats.bus_error++;
 	}
 
-	if (skb) {
-		stats->rx_packets++;
-		stats->rx_bytes += cf->can_dlc;
-		netif_rx(skb);
+	if (cf.can_id) {
+		struct can_frame *skb_cf;
+		struct sk_buff *skb = alloc_can_err_skb(ndev, &skb_cf);
+
+		if (skb) {
+			skb_cf->can_id |= cf.can_id;
+			memcpy(skb_cf->data, cf.data, CAN_ERR_DLC);
+			stats->rx_packets++;
+			stats->rx_bytes += CAN_ERR_DLC;
+			netif_rx(skb);
+		}
 	}
 
 	netdev_dbg(ndev, "%s: error status register:0x%x\n",
@@ -1360,9 +1369,13 @@
 static void xcan_chip_stop(struct net_device *ndev)
 {
 	struct xcan_priv *priv = netdev_priv(ndev);
+	int ret;
 
 	/* Disable interrupts and leave the can in configuration mode */
-	set_reset_mode(ndev);
+	ret = set_reset_mode(ndev);
+	if (ret < 0)
+		netdev_dbg(ndev, "set_reset_mode() Failed\n");
+
 	priv->can.state = CAN_STATE_STOPPED;
 }
 
@@ -1382,7 +1395,7 @@
 	if (ret < 0) {
 		netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n",
 			   __func__, ret);
-		return ret;
+		goto err;
 	}
 
 	ret = request_irq(ndev->irq, xcan_interrupt, priv->irq_flags,
@@ -1466,6 +1479,7 @@
 	if (ret < 0) {
 		netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n",
 			   __func__, ret);
+		pm_runtime_put(priv->dev);
 		return ret;
 	}
 
@@ -1659,7 +1673,7 @@
 	void __iomem *addr;
 	int ret;
 	int rx_max, tx_max;
-	int hw_tx_max, hw_rx_max;
+	u32 hw_tx_max = 0, hw_rx_max = 0;
 	const char *hw_tx_max_property;
 
 	/* Get the virtual base address for the device */
@@ -1713,7 +1727,7 @@
 	 */
 	if (!(devtype->flags & XCAN_FLAG_TX_MAILBOXES) &&
 	    (devtype->flags & XCAN_FLAG_TXFEMP))
-		tx_max = min(hw_tx_max, 2);
+		tx_max = min(hw_tx_max, 2U);
 	else
 		tx_max = 1;
 
@@ -1750,7 +1764,12 @@
 	spin_lock_init(&priv->tx_lock);
 
 	/* Get IRQ for the device */
-	ndev->irq = platform_get_irq(pdev, 0);
+	ret = platform_get_irq(pdev, 0);
+	if (ret < 0)
+		goto err_free;
+
+	ndev->irq = ret;
+
 	ndev->flags |= IFF_ECHO;	/* We support local echo */
 
 	platform_set_drvdata(pdev, ndev);
@@ -1768,7 +1787,8 @@
 
 	priv->bus_clk = devm_clk_get(&pdev->dev, devtype->bus_clk_name);
 	if (IS_ERR(priv->bus_clk)) {
-		dev_err(&pdev->dev, "bus clock not found\n");
+		if (PTR_ERR(priv->bus_clk) != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "bus clock not found\n");
 		ret = PTR_ERR(priv->bus_clk);
 		goto err_free;
 	}
@@ -1781,7 +1801,7 @@
 	if (ret < 0) {
 		netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n",
 			   __func__, ret);
-		goto err_pmdisable;
+		goto err_disableclks;
 	}
 
 	if (priv->read_reg(priv, XCAN_SR_OFFSET) != XCAN_SR_CONFIG_MASK) {
@@ -1803,6 +1823,11 @@
 
 	pm_runtime_put(&pdev->dev);
 
+	if (priv->devtype.flags & XCAN_FLAG_CANFD_2) {
+		priv->write_reg(priv, XCAN_AFR_2_ID_OFFSET, 0x00000000);
+		priv->write_reg(priv, XCAN_AFR_2_MASK_OFFSET, 0x00000000);
+	}
+
 	netdev_dbg(ndev, "reg_base=0x%p irq=%d clock=%d, tx buffers: actual %d, using %d\n",
 		   priv->reg_base, ndev->irq, priv->can.clock.freq,
 		   hw_tx_max, priv->tx_max);
@@ -1811,7 +1836,6 @@
 
 err_disableclks:
 	pm_runtime_put(priv->dev);
-err_pmdisable:
 	pm_runtime_disable(&pdev->dev);
 err_free:
 	free_candev(ndev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/Kconfig
@@ -77,6 +77,7 @@
 config NET_DSA_SMSC_LAN9303
 	tristate
 	select NET_DSA_TAG_LAN9303
+	select REGMAP
 	---help---
 	  This enables support for the SMSC/Microchip LAN9303 3 port ethernet
 	  switch chips.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/b53/b53_common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/b53/b53_common.c
@@ -347,7 +347,7 @@
 	 * frames should be flooded or not.
 	 */
 	b53_read8(dev, B53_CTRL_PAGE, B53_IP_MULTICAST_CTRL, &mgmt);
-	mgmt |= B53_UC_FWD_EN | B53_MC_FWD_EN;
+	mgmt |= B53_UC_FWD_EN | B53_MC_FWD_EN | B53_IPMC_FWD_EN;
 	b53_write8(dev, B53_CTRL_PAGE, B53_IP_MULTICAST_CTRL, mgmt);
 }
 
@@ -514,6 +514,19 @@
 }
 EXPORT_SYMBOL(b53_imp_vlan_setup);
 
+static void b53_port_set_learning(struct b53_device *dev, int port,
+				  bool learning)
+{
+	u16 reg;
+
+	b53_read16(dev, B53_CTRL_PAGE, B53_DIS_LEARNING, &reg);
+	if (learning)
+		reg &= ~BIT(port);
+	else
+		reg |= BIT(port);
+	b53_write16(dev, B53_CTRL_PAGE, B53_DIS_LEARNING, reg);
+}
+
 int b53_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy)
 {
 	struct b53_device *dev = ds->priv;
@@ -526,6 +539,9 @@
 
 	cpu_port = ds->ports[port].cpu_dp->index;
 
+	b53_br_egress_floods(ds, port, true, true);
+	b53_port_set_learning(dev, port, false);
+
 	if (dev->ops->irq_enable)
 		ret = dev->ops->irq_enable(dev, port);
 	if (ret)
@@ -641,6 +657,9 @@
 	b53_write8(dev, B53_CTRL_PAGE, B53_PORT_CTRL(port), port_ctrl);
 
 	b53_brcm_hdr_setup(dev->ds, port);
+
+	b53_br_egress_floods(dev->ds, port, true, true);
+	b53_port_set_learning(dev, port, false);
 }
 
 static void b53_enable_mib(struct b53_device *dev)
@@ -676,7 +695,7 @@
 		b53_do_vlan_op(dev, VTA_CMD_CLEAR);
 	}
 
-	b53_enable_vlan(dev, false, ds->vlan_filtering);
+	b53_enable_vlan(dev, dev->vlan_enabled, ds->vlan_filtering);
 
 	b53_for_each_port(dev, i)
 		b53_write16(dev, B53_VLAN_PAGE,
@@ -977,13 +996,6 @@
 			b53_disable_port(ds, port);
 	}
 
-	/* Let DSA handle the case were multiple bridges span the same switch
-	 * device and different VLAN awareness settings are requested, which
-	 * would be breaking filtering semantics for any of the other bridge
-	 * devices. (not hardware supported)
-	 */
-	ds->vlan_filtering_is_global = true;
-
 	return ret;
 }
 
@@ -1326,7 +1338,7 @@
 	if ((is5325(dev) || is5365(dev)) && vlan->vid_begin == 0)
 		return -EOPNOTSUPP;
 
-	if (vlan->vid_end > dev->num_vlans)
+	if (vlan->vid_end >= dev->num_vlans)
 		return -ERANGE;
 
 	b53_enable_vlan(dev, true, ds->vlan_filtering);
@@ -1349,6 +1361,9 @@
 
 		b53_get_vlan_entry(dev, vid, vl);
 
+		if (vid == 0 && vid == b53_default_pvid(dev))
+			untagged = true;
+
 		vl->members |= BIT(port);
 		if (untagged && !dsa_is_cpu_port(ds, port))
 			vl->untag |= BIT(port);
@@ -1434,6 +1449,10 @@
 		reg |= ARLTBL_RW;
 	else
 		reg &= ~ARLTBL_RW;
+	if (dev->vlan_enabled)
+		reg &= ~ARLTBL_IVL_SVL_SELECT;
+	else
+		reg |= ARLTBL_IVL_SVL_SELECT;
 	b53_write8(dev, B53_ARLIO_PAGE, B53_ARLTBL_RW_CTRL, reg);
 
 	return b53_arl_op_wait(dev);
@@ -1443,6 +1462,7 @@
 			u16 vid, struct b53_arl_entry *ent, u8 *idx,
 			bool is_valid)
 {
+	DECLARE_BITMAP(free_bins, B53_ARLTBL_MAX_BIN_ENTRIES);
 	unsigned int i;
 	int ret;
 
@@ -1450,6 +1470,8 @@
 	if (ret)
 		return ret;
 
+	bitmap_zero(free_bins, dev->num_arl_entries);
+
 	/* Read the bins */
 	for (i = 0; i < dev->num_arl_entries; i++) {
 		u64 mac_vid;
@@ -1461,13 +1483,24 @@
 			   B53_ARLTBL_DATA_ENTRY(i), &fwd_entry);
 		b53_arl_to_entry(ent, mac_vid, fwd_entry);
 
-		if (!(fwd_entry & ARLTBL_VALID))
+		if (!(fwd_entry & ARLTBL_VALID)) {
+			set_bit(i, free_bins);
 			continue;
+		}
 		if ((mac_vid & ARLTBL_MAC_MASK) != mac)
 			continue;
+		if (dev->vlan_enabled &&
+		    ((mac_vid >> ARLTBL_VID_S) & ARLTBL_VID_MASK) != vid)
+			continue;
 		*idx = i;
+		return 0;
 	}
 
+	if (bitmap_weight(free_bins, dev->num_arl_entries) == 0)
+		return -ENOSPC;
+
+	*idx = find_first_bit(free_bins, dev->num_arl_entries);
+
 	return -ENOENT;
 }
 
@@ -1497,10 +1530,23 @@
 	if (op)
 		return ret;
 
-	/* We could not find a matching MAC, so reset to a new entry */
-	if (ret) {
+	switch (ret) {
+	case -ETIMEDOUT:
+		return ret;
+	case -ENOSPC:
+		dev_dbg(dev->dev, "{%pM,%.4d} no space left in ARL\n",
+			addr, vid);
+		return is_valid ? ret : 0;
+	case -ENOENT:
+		/* We could not find a matching MAC, so reset to a new entry */
+		dev_dbg(dev->dev, "{%pM,%.4d} not found, using idx: %d\n",
+			addr, vid, idx);
 		fwd_entry = 0;
-		idx = 1;
+		break;
+	default:
+		dev_dbg(dev->dev, "{%pM,%.4d} found, using idx: %d\n",
+			addr, vid, idx);
+		break;
 	}
 
 	memset(&ent, 0, sizeof(ent));
@@ -1667,6 +1713,8 @@
 	b53_write16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port), pvlan);
 	dev->ports[port].vlan_ctl_mask = pvlan;
 
+	b53_port_set_learning(dev, port, true);
+
 	return 0;
 }
 EXPORT_SYMBOL(b53_br_join);
@@ -1714,6 +1762,7 @@
 		vl->untag |= BIT(port) | BIT(cpu_port);
 		b53_set_vlan_entry(dev, pvid, vl);
 	}
+	b53_port_set_learning(dev, port, false);
 }
 EXPORT_SYMBOL(b53_br_leave);
 
@@ -1766,19 +1815,26 @@
 	struct b53_device *dev = ds->priv;
 	u16 uc, mc;
 
-	b53_read16(dev, B53_CTRL_PAGE, B53_UC_FWD_EN, &uc);
+	b53_read16(dev, B53_CTRL_PAGE, B53_UC_FLOOD_MASK, &uc);
 	if (unicast)
 		uc |= BIT(port);
 	else
 		uc &= ~BIT(port);
-	b53_write16(dev, B53_CTRL_PAGE, B53_UC_FWD_EN, uc);
+	b53_write16(dev, B53_CTRL_PAGE, B53_UC_FLOOD_MASK, uc);
 
-	b53_read16(dev, B53_CTRL_PAGE, B53_MC_FWD_EN, &mc);
+	b53_read16(dev, B53_CTRL_PAGE, B53_MC_FLOOD_MASK, &mc);
 	if (multicast)
 		mc |= BIT(port);
 	else
 		mc &= ~BIT(port);
-	b53_write16(dev, B53_CTRL_PAGE, B53_MC_FWD_EN, mc);
+	b53_write16(dev, B53_CTRL_PAGE, B53_MC_FLOOD_MASK, mc);
+
+	b53_read16(dev, B53_CTRL_PAGE, B53_IPMC_FLOOD_MASK, &mc);
+	if (multicast)
+		mc |= BIT(port);
+	else
+		mc &= ~BIT(port);
+	b53_write16(dev, B53_CTRL_PAGE, B53_IPMC_FLOOD_MASK, mc);
 
 	return 0;
 
@@ -2298,9 +2354,8 @@
 			dev->cpu_port = 5;
 	}
 
-	/* cpu port is always last */
-	dev->num_ports = dev->cpu_port + 1;
 	dev->enabled_ports |= BIT(dev->cpu_port);
+	dev->num_ports = fls(dev->enabled_ports);
 
 	/* Include non standard CPU port built-in PHYs to be probed */
 	if (is539x(dev) || is531x5(dev)) {
@@ -2356,6 +2411,13 @@
 	dev->priv = priv;
 	dev->ops = ops;
 	ds->ops = &b53_switch_ops;
+	/* Let DSA handle the case were multiple bridges span the same switch
+	 * device and different VLAN awareness settings are requested, which
+	 * would be breaking filtering semantics for any of the other bridge
+	 * devices. (not hardware supported)
+	 */
+	ds->vlan_filtering_is_global = true;
+
 	mutex_init(&dev->reg_mutex);
 	mutex_init(&dev->stats_mutex);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/b53/b53_mmap.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/b53/b53_mmap.c
@@ -215,6 +215,18 @@
 	return 0;
 }
 
+static int b53_mmap_phy_read16(struct b53_device *dev, int addr, int reg,
+			       u16 *value)
+{
+	return -EIO;
+}
+
+static int b53_mmap_phy_write16(struct b53_device *dev, int addr, int reg,
+				u16 value)
+{
+	return -EIO;
+}
+
 static const struct b53_io_ops b53_mmap_ops = {
 	.read8 = b53_mmap_read8,
 	.read16 = b53_mmap_read16,
@@ -226,6 +238,8 @@
 	.write32 = b53_mmap_write32,
 	.write48 = b53_mmap_write48,
 	.write64 = b53_mmap_write64,
+	.phy_read16 = b53_mmap_phy_read16,
+	.phy_write16 = b53_mmap_phy_write16,
 };
 
 static int b53_mmap_probe(struct platform_device *pdev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/b53/b53_regs.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/b53/b53_regs.h
@@ -115,6 +115,7 @@
 #define B53_UC_FLOOD_MASK		0x32
 #define B53_MC_FLOOD_MASK		0x34
 #define B53_IPMC_FLOOD_MASK		0x36
+#define B53_DIS_LEARNING		0x3c
 
 /*
  * Override Ports 0-7 State on devices with xMII interfaces (8 bit)
@@ -292,6 +293,7 @@
 /* ARL Table Read/Write Register (8 bit) */
 #define B53_ARLTBL_RW_CTRL		0x00
 #define    ARLTBL_RW			BIT(0)
+#define    ARLTBL_IVL_SVL_SELECT	BIT(6)
 #define    ARLTBL_START_DONE		BIT(7)
 
 /* MAC Address Index Register (48 bit) */
@@ -304,7 +306,7 @@
  *
  * BCM5325 and BCM5365 share most definitions below
  */
-#define B53_ARLTBL_MAC_VID_ENTRY(n)	(0x10 * (n))
+#define B53_ARLTBL_MAC_VID_ENTRY(n)	((0x10 * (n)) + 0x10)
 #define   ARLTBL_MAC_MASK		0xffffffffffffULL
 #define   ARLTBL_VID_S			48
 #define   ARLTBL_VID_MASK_25		0xff
@@ -316,13 +318,16 @@
 #define   ARLTBL_VALID_25		BIT(63)
 
 /* ARL Table Data Entry N Registers (32 bit) */
-#define B53_ARLTBL_DATA_ENTRY(n)	((0x10 * (n)) + 0x08)
+#define B53_ARLTBL_DATA_ENTRY(n)	((0x10 * (n)) + 0x18)
 #define   ARLTBL_DATA_PORT_ID_MASK	0x1ff
 #define   ARLTBL_TC(tc)			((3 & tc) << 11)
 #define   ARLTBL_AGE			BIT(14)
 #define   ARLTBL_STATIC			BIT(15)
 #define   ARLTBL_VALID			BIT(16)
 
+/* Maximum number of bin entries in the ARL for all switches */
+#define B53_ARLTBL_MAX_BIN_ENTRIES	4
+
 /* ARL Search Control Register (8 bit) */
 #define B53_ARL_SRCH_CTL		0x50
 #define B53_ARL_SRCH_CTL_25		0x20
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/bcm_sf2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/bcm_sf2.c
@@ -69,6 +69,7 @@
 		/* Force link status for IMP port */
 		reg = core_readl(priv, offset);
 		reg |= (MII_SW_OR | LINK_STS);
+		reg &= ~GMII_SPEED_UP_2G;
 		core_writel(priv, reg, offset);
 
 		/* Enable Broadcast, Multicast, Unicast forwarding to IMP port */
@@ -171,11 +172,6 @@
 	reg &= ~P_TXQ_PSM_VDD(port);
 	core_writel(priv, reg, CORE_MEM_PSM_VDD_CTRL);
 
-	/* Enable learning */
-	reg = core_readl(priv, CORE_DIS_LEARN);
-	reg &= ~BIT(port);
-	core_writel(priv, reg, CORE_DIS_LEARN);
-
 	/* Enable Broadcom tags for that port if requested */
 	if (priv->brcm_tag_mask & BIT(port))
 		b53_brcm_hdr_setup(ds, port);
@@ -420,15 +416,19 @@
 	/* Find our integrated MDIO bus node */
 	dn = of_find_compatible_node(NULL, NULL, "brcm,unimac-mdio");
 	priv->master_mii_bus = of_mdio_find_bus(dn);
-	if (!priv->master_mii_bus)
+	if (!priv->master_mii_bus) {
+		of_node_put(dn);
 		return -EPROBE_DEFER;
+	}
 
 	get_device(&priv->master_mii_bus->dev);
 	priv->master_mii_dn = dn;
 
 	priv->slave_mii_bus = devm_mdiobus_alloc(ds->dev);
-	if (!priv->slave_mii_bus)
+	if (!priv->slave_mii_bus) {
+		of_node_put(dn);
 		return -ENOMEM;
+	}
 
 	priv->slave_mii_bus->priv = priv;
 	priv->slave_mii_bus->name = "sf2 slave mii";
@@ -458,7 +458,7 @@
 	priv->slave_mii_bus->parent = ds->dev->parent;
 	priv->slave_mii_bus->phy_mask = ~priv->indir_phy_mask;
 
-	err = of_mdiobus_register(priv->slave_mii_bus, dn);
+	err = mdiobus_register(priv->slave_mii_bus);
 	if (err && dn)
 		of_node_put(dn);
 
@@ -479,8 +479,10 @@
 	 * in bits 15:8 and the patch level in bits 7:0 which is exactly what
 	 * the REG_PHY_REVISION register layout is.
 	 */
-
-	return priv->hw_params.gphy_rev;
+	if (priv->int_phy_mask & BIT(port))
+		return priv->hw_params.gphy_rev;
+	else
+		return 0;
 }
 
 static void bcm_sf2_sw_validate(struct dsa_switch *ds, int port,
@@ -600,6 +602,11 @@
 		reg |= LINK_STS;
 	if (state->duplex == DUPLEX_FULL)
 		reg |= DUPLX_MODE;
+	if (state->pause & MLO_PAUSE_TXRX_MASK) {
+		if (state->pause & MLO_PAUSE_TX)
+			reg |= TXFLOW_CNTL;
+		reg |= RXFLOW_CNTL;
+	}
 
 	core_writel(priv, reg, offset);
 }
@@ -1052,6 +1059,7 @@
 	const struct bcm_sf2_of_data *data;
 	struct b53_platform_data *pdata;
 	struct dsa_switch_ops *ops;
+	struct device_node *ports;
 	struct bcm_sf2_priv *priv;
 	struct b53_device *dev;
 	struct dsa_switch *ds;
@@ -1114,7 +1122,13 @@
 	set_bit(0, priv->cfp.used);
 	set_bit(0, priv->cfp.unique);
 
-	bcm_sf2_identify_ports(priv, dn->child);
+	/* Balance of_node_put() done by of_find_node_by_name() */
+	of_node_get(dn);
+	ports = of_find_node_by_name(dn, "ports");
+	if (ports) {
+		bcm_sf2_identify_ports(priv, ports);
+		of_node_put(ports);
+	}
 
 	priv->irq0 = irq_of_parse_and_map(dn, 0);
 	priv->irq1 = irq_of_parse_and_map(dn, 1);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/bcm_sf2_cfp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/bcm_sf2_cfp.c
@@ -358,7 +358,7 @@
 		return -EINVAL;
 	}
 
-	ip_frag = be32_to_cpu(fs->m_ext.data[0]);
+	ip_frag = !!(be32_to_cpu(fs->h_ext.data[0]) & 1);
 
 	/* Locate the first rule available */
 	if (fs->location == RX_CLS_LOC_ANY)
@@ -542,14 +542,14 @@
 static struct cfp_rule *bcm_sf2_cfp_rule_find(struct bcm_sf2_priv *priv,
 					      int port, u32 location)
 {
-	struct cfp_rule *rule = NULL;
+	struct cfp_rule *rule;
 
 	list_for_each_entry(rule, &priv->cfp.rules_list, next) {
 		if (rule->port == port && rule->fs.location == location)
-			break;
+			return rule;
 	}
 
-	return rule;
+	return NULL;
 }
 
 static int bcm_sf2_cfp_rule_cmp(struct bcm_sf2_priv *priv, int port,
@@ -569,7 +569,7 @@
 
 		if (rule->fs.flow_type != fs->flow_type ||
 		    rule->fs.ring_cookie != fs->ring_cookie ||
-		    rule->fs.m_ext.data[0] != fs->m_ext.data[0])
+		    rule->fs.h_ext.data[0] != fs->h_ext.data[0])
 			continue;
 
 		switch (fs->flow_type & ~FLOW_EXT) {
@@ -621,7 +621,7 @@
 		return -EINVAL;
 	}
 
-	ip_frag = be32_to_cpu(fs->m_ext.data[0]);
+	ip_frag = !!(be32_to_cpu(fs->h_ext.data[0]) & 1);
 
 	layout = &udf_tcpip6_layout;
 	slice_num = bcm_sf2_get_slice_number(layout, 0);
@@ -882,17 +882,14 @@
 	     fs->m_ext.data[1]))
 		return -EINVAL;
 
-	if (fs->location != RX_CLS_LOC_ANY && fs->location >= CFP_NUM_RULES)
+	if (fs->location != RX_CLS_LOC_ANY &&
+	    fs->location > bcm_sf2_cfp_rule_size(priv))
 		return -EINVAL;
 
 	if (fs->location != RX_CLS_LOC_ANY &&
 	    test_bit(fs->location, priv->cfp.used))
 		return -EBUSY;
 
-	if (fs->location != RX_CLS_LOC_ANY &&
-	    fs->location > bcm_sf2_cfp_rule_size(priv))
-		return -EINVAL;
-
 	ret = bcm_sf2_cfp_rule_cmp(priv, port, fs);
 	if (ret == 0)
 		return -EEXIST;
@@ -973,7 +970,7 @@
 	struct cfp_rule *rule;
 	int ret;
 
-	if (loc >= CFP_NUM_RULES)
+	if (loc > bcm_sf2_cfp_rule_size(priv))
 		return -EINVAL;
 
 	/* Refuse deleting unused rules, and those that are not unique since
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/dsa_loop.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/dsa_loop.c
@@ -329,6 +329,17 @@
 
 #define NUM_FIXED_PHYS	(DSA_LOOP_NUM_PORTS - 2)
 
+static void dsa_loop_phydevs_unregister(void)
+{
+	unsigned int i;
+
+	for (i = 0; i < NUM_FIXED_PHYS; i++)
+		if (!IS_ERR(phydevs[i])) {
+			fixed_phy_unregister(phydevs[i]);
+			phy_device_free(phydevs[i]);
+		}
+}
+
 static int __init dsa_loop_init(void)
 {
 	struct fixed_phy_status status = {
@@ -336,26 +347,27 @@
 		.speed = SPEED_100,
 		.duplex = DUPLEX_FULL,
 	};
-	unsigned int i;
+	unsigned int i, ret;
 
 	for (i = 0; i < NUM_FIXED_PHYS; i++)
 		phydevs[i] = fixed_phy_register(PHY_POLL, &status, NULL);
 
-	return mdio_driver_register(&dsa_loop_drv);
+	ret = mdio_driver_register(&dsa_loop_drv);
+	if (ret)
+		dsa_loop_phydevs_unregister();
+
+	return ret;
 }
 module_init(dsa_loop_init);
 
 static void __exit dsa_loop_exit(void)
 {
-	unsigned int i;
-
 	mdio_driver_unregister(&dsa_loop_drv);
-	for (i = 0; i < NUM_FIXED_PHYS; i++)
-		if (!IS_ERR(phydevs[i]))
-			fixed_phy_unregister(phydevs[i]);
+	dsa_loop_phydevs_unregister();
 }
 module_exit(dsa_loop_exit);
 
+MODULE_SOFTDEP("pre: dsa_loop_bdinfo");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Florian Fainelli");
 MODULE_DESCRIPTION("DSA loopback driver");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/lan9303-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/lan9303-core.c
@@ -557,12 +557,12 @@
 	return 0;
 }
 
-typedef void alr_loop_cb_t(struct lan9303 *chip, u32 dat0, u32 dat1,
-			   int portmap, void *ctx);
+typedef int alr_loop_cb_t(struct lan9303 *chip, u32 dat0, u32 dat1,
+			  int portmap, void *ctx);
 
-static void lan9303_alr_loop(struct lan9303 *chip, alr_loop_cb_t *cb, void *ctx)
+static int lan9303_alr_loop(struct lan9303 *chip, alr_loop_cb_t *cb, void *ctx)
 {
-	int i;
+	int ret = 0, i;
 
 	mutex_lock(&chip->alr_mutex);
 	lan9303_write_switch_reg(chip, LAN9303_SWE_ALR_CMD,
@@ -582,13 +582,17 @@
 						LAN9303_ALR_DAT1_PORT_BITOFFS;
 		portmap = alrport_2_portmap[alrport];
 
-		cb(chip, dat0, dat1, portmap, ctx);
+		ret = cb(chip, dat0, dat1, portmap, ctx);
+		if (ret)
+			break;
 
 		lan9303_write_switch_reg(chip, LAN9303_SWE_ALR_CMD,
 					 LAN9303_ALR_CMD_GET_NEXT);
 		lan9303_write_switch_reg(chip, LAN9303_SWE_ALR_CMD, 0);
 	}
 	mutex_unlock(&chip->alr_mutex);
+
+	return ret;
 }
 
 static void alr_reg_to_mac(u32 dat0, u32 dat1, u8 mac[6])
@@ -606,18 +610,20 @@
 };
 
 /* Clear learned (non-static) entry on given port */
-static void alr_loop_cb_del_port_learned(struct lan9303 *chip, u32 dat0,
-					 u32 dat1, int portmap, void *ctx)
+static int alr_loop_cb_del_port_learned(struct lan9303 *chip, u32 dat0,
+					u32 dat1, int portmap, void *ctx)
 {
 	struct del_port_learned_ctx *del_ctx = ctx;
 	int port = del_ctx->port;
 
 	if (((BIT(port) & portmap) == 0) || (dat1 & LAN9303_ALR_DAT1_STATIC))
-		return;
+		return 0;
 
 	/* learned entries has only one port, we can just delete */
 	dat1 &= ~LAN9303_ALR_DAT1_VALID; /* delete entry */
 	lan9303_alr_make_entry_raw(chip, dat0, dat1);
+
+	return 0;
 }
 
 struct port_fdb_dump_ctx {
@@ -626,19 +632,19 @@
 	dsa_fdb_dump_cb_t *cb;
 };
 
-static void alr_loop_cb_fdb_port_dump(struct lan9303 *chip, u32 dat0,
-				      u32 dat1, int portmap, void *ctx)
+static int alr_loop_cb_fdb_port_dump(struct lan9303 *chip, u32 dat0,
+				     u32 dat1, int portmap, void *ctx)
 {
 	struct port_fdb_dump_ctx *dump_ctx = ctx;
 	u8 mac[ETH_ALEN];
 	bool is_static;
 
 	if ((BIT(dump_ctx->port) & portmap) == 0)
-		return;
+		return 0;
 
 	alr_reg_to_mac(dat0, dat1, mac);
 	is_static = !!(dat1 & LAN9303_ALR_DAT1_STATIC);
-	dump_ctx->cb(mac, 0, is_static, dump_ctx->data);
+	return dump_ctx->cb(mac, 0, is_static, dump_ctx->data);
 }
 
 /* Set a static ALR entry. Delete entry if port_map is zero */
@@ -951,7 +957,7 @@
 	{ .offset = LAN9303_MAC_TX_BRDCST_CNT_0, .name = "TxBroad", },
 	{ .offset = LAN9303_MAC_TX_PAUSE_CNT_0, .name = "TxPause", },
 	{ .offset = LAN9303_MAC_TX_MULCST_CNT_0, .name = "TxMulti", },
-	{ .offset = LAN9303_MAC_RX_UNDSZE_CNT_0, .name = "TxUnderRun", },
+	{ .offset = LAN9303_MAC_RX_UNDSZE_CNT_0, .name = "RxShort", },
 	{ .offset = LAN9303_MAC_TX_64_CNT_0, .name = "Tx64Byte", },
 	{ .offset = LAN9303_MAC_TX_127_CNT_0, .name = "Tx128Byte", },
 	{ .offset = LAN9303_MAC_TX_255_CNT_0, .name = "Tx256Byte", },
@@ -995,9 +1001,11 @@
 		ret = lan9303_read_switch_port(
 			chip, port, lan9303_mib[u].offset, &reg);
 
-		if (ret)
+		if (ret) {
 			dev_warn(chip->dev, "Reading status port %d reg %u failed\n",
 				 port, lan9303_mib[u].offset);
+			reg = 0;
+		}
 		data[u] = reg;
 	}
 }
@@ -1179,8 +1187,6 @@
 	struct lan9303 *chip = ds->priv;
 
 	dev_dbg(chip->dev, "%s(%d, %pM, %d)\n", __func__, port, addr, vid);
-	if (vid)
-		return -EOPNOTSUPP;
 
 	return lan9303_alr_add_port(chip, addr, port, false);
 }
@@ -1192,8 +1198,6 @@
 	struct lan9303 *chip = ds->priv;
 
 	dev_dbg(chip->dev, "%s(%d, %pM, %d)\n", __func__, port, addr, vid);
-	if (vid)
-		return -EOPNOTSUPP;
 	lan9303_alr_del_port(chip, addr, port);
 
 	return 0;
@@ -1210,9 +1214,7 @@
 	};
 
 	dev_dbg(chip->dev, "%s(%d)\n", __func__, port);
-	lan9303_alr_loop(chip, alr_loop_cb_fdb_port_dump, &dump_ctx);
-
-	return 0;
+	return lan9303_alr_loop(chip, alr_loop_cb_fdb_port_dump, &dump_ctx);
 }
 
 static int lan9303_port_mdb_prepare(struct dsa_switch *ds, int port,
@@ -1299,7 +1301,7 @@
 				     struct device_node *np)
 {
 	chip->reset_gpio = devm_gpiod_get_optional(chip->dev, "reset",
-						   GPIOD_OUT_LOW);
+						   GPIOD_OUT_HIGH);
 	if (IS_ERR(chip->reset_gpio))
 		return PTR_ERR(chip->reset_gpio);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/lan9303_mdio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/lan9303_mdio.c
@@ -32,7 +32,7 @@
 	struct lan9303_mdio *sw_dev = (struct lan9303_mdio *)ctx;
 
 	reg <<= 2; /* reg num to offset */
-	mutex_lock(&sw_dev->device->bus->mdio_lock);
+	mutex_lock_nested(&sw_dev->device->bus->mdio_lock, MDIO_MUTEX_NESTED);
 	lan9303_mdio_real_write(sw_dev->device, reg, val & 0xffff);
 	lan9303_mdio_real_write(sw_dev->device, reg + 2, (val >> 16) & 0xffff);
 	mutex_unlock(&sw_dev->device->bus->mdio_lock);
@@ -50,7 +50,7 @@
 	struct lan9303_mdio *sw_dev = (struct lan9303_mdio *)ctx;
 
 	reg <<= 2; /* reg num to offset */
-	mutex_lock(&sw_dev->device->bus->mdio_lock);
+	mutex_lock_nested(&sw_dev->device->bus->mdio_lock, MDIO_MUTEX_NESTED);
 	*val = lan9303_mdio_real_read(sw_dev->device, reg);
 	*val |= (lan9303_mdio_real_read(sw_dev->device, reg + 2) << 16);
 	mutex_unlock(&sw_dev->device->bus->mdio_lock);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/lantiq_gswip.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/lantiq_gswip.c
@@ -26,6 +26,7 @@
  */
 
 #include <linux/clk.h>
+#include <linux/delay.h>
 #include <linux/etherdevice.h>
 #include <linux/firmware.h>
 #include <linux/if_bridge.h>
@@ -91,11 +92,13 @@
 					 GSWIP_MDIO_PHY_FDUP_MASK)
 
 /* GSWIP MII Registers */
-#define GSWIP_MII_CFG0			0x00
-#define GSWIP_MII_CFG1			0x02
-#define GSWIP_MII_CFG5			0x04
+#define GSWIP_MII_CFGp(p)		(0x2 * (p))
+#define  GSWIP_MII_CFG_RESET		BIT(15)
 #define  GSWIP_MII_CFG_EN		BIT(14)
+#define  GSWIP_MII_CFG_ISOLATE		BIT(13)
 #define  GSWIP_MII_CFG_LDCLKDIS		BIT(12)
+#define  GSWIP_MII_CFG_RGMII_IBS	BIT(8)
+#define  GSWIP_MII_CFG_RMII_CLK		BIT(7)
 #define  GSWIP_MII_CFG_MODE_MIIP	0x0
 #define  GSWIP_MII_CFG_MODE_MIIM	0x1
 #define  GSWIP_MII_CFG_MODE_RMIIP	0x2
@@ -191,6 +194,23 @@
 #define GSWIP_PCE_DEFPVID(p)		(0x486 + ((p) * 0xA))
 
 #define GSWIP_MAC_FLEN			0x8C5
+#define GSWIP_MAC_CTRL_0p(p)		(0x903 + ((p) * 0xC))
+#define  GSWIP_MAC_CTRL_0_PADEN		BIT(8)
+#define  GSWIP_MAC_CTRL_0_FCS_EN	BIT(7)
+#define  GSWIP_MAC_CTRL_0_FCON_MASK	0x0070
+#define  GSWIP_MAC_CTRL_0_FCON_AUTO	0x0000
+#define  GSWIP_MAC_CTRL_0_FCON_RX	0x0010
+#define  GSWIP_MAC_CTRL_0_FCON_TX	0x0020
+#define  GSWIP_MAC_CTRL_0_FCON_RXTX	0x0030
+#define  GSWIP_MAC_CTRL_0_FCON_NONE	0x0040
+#define  GSWIP_MAC_CTRL_0_FDUP_MASK	0x000C
+#define  GSWIP_MAC_CTRL_0_FDUP_AUTO	0x0000
+#define  GSWIP_MAC_CTRL_0_FDUP_EN	0x0004
+#define  GSWIP_MAC_CTRL_0_FDUP_DIS	0x000C
+#define  GSWIP_MAC_CTRL_0_GMII_MASK	0x0003
+#define  GSWIP_MAC_CTRL_0_GMII_AUTO	0x0000
+#define  GSWIP_MAC_CTRL_0_GMII_MII	0x0001
+#define  GSWIP_MAC_CTRL_0_GMII_RGMII	0x0002
 #define GSWIP_MAC_CTRL_2p(p)		(0x905 + ((p) * 0xC))
 #define GSWIP_MAC_CTRL_2_MLEN		BIT(3) /* Maximum Untagged Frame Lnegth */
 
@@ -209,7 +229,7 @@
 #define GSWIP_SDMA_PCTRLp(p)		(0xBC0 + ((p) * 0x6))
 #define  GSWIP_SDMA_PCTRL_EN		BIT(0)	/* SDMA Port Enable */
 #define  GSWIP_SDMA_PCTRL_FCEN		BIT(1)	/* Flow Control Enable */
-#define  GSWIP_SDMA_PCTRL_PAUFWD	BIT(1)	/* Pause Frame Forwarding */
+#define  GSWIP_SDMA_PCTRL_PAUFWD	BIT(3)	/* Pause Frame Forwarding */
 
 #define GSWIP_TABLE_ACTIVE_VLAN		0x01
 #define GSWIP_TABLE_VLAN_MAPPING	0x02
@@ -391,17 +411,9 @@
 static void gswip_mii_mask_cfg(struct gswip_priv *priv, u32 clear, u32 set,
 			       int port)
 {
-	switch (port) {
-	case 0:
-		gswip_mii_mask(priv, clear, set, GSWIP_MII_CFG0);
-		break;
-	case 1:
-		gswip_mii_mask(priv, clear, set, GSWIP_MII_CFG1);
-		break;
-	case 5:
-		gswip_mii_mask(priv, clear, set, GSWIP_MII_CFG5);
-		break;
-	}
+	/* There's no MII_CFG register for the CPU port */
+	if (!dsa_is_cpu_port(priv->ds, port))
+		gswip_mii_mask(priv, clear, set, GSWIP_MII_CFGp(port));
 }
 
 static void gswip_mii_mask_pcdu(struct gswip_priv *priv, u32 clear, u32 set,
@@ -662,16 +674,13 @@
 			  GSWIP_SDMA_PCTRLp(port));
 
 	if (!dsa_is_cpu_port(ds, port)) {
-		u32 macconf = GSWIP_MDIO_PHY_LINK_AUTO |
-			      GSWIP_MDIO_PHY_SPEED_AUTO |
-			      GSWIP_MDIO_PHY_FDUP_AUTO |
-			      GSWIP_MDIO_PHY_FCONTX_AUTO |
-			      GSWIP_MDIO_PHY_FCONRX_AUTO |
-			      (phydev->mdio.addr & GSWIP_MDIO_PHY_ADDR_MASK);
-
-		gswip_mdio_w(priv, macconf, GSWIP_MDIO_PHYp(port));
-		/* Activate MDIO auto polling */
-		gswip_mdio_mask(priv, 0, BIT(port), GSWIP_MDIO_MDC_CFG0);
+		u32 mdio_phy = 0;
+
+		if (phydev)
+			mdio_phy = phydev->mdio.addr & GSWIP_MDIO_PHY_ADDR_MASK;
+
+		gswip_mdio_mask(priv, GSWIP_MDIO_PHY_ADDR_MASK, mdio_phy,
+				GSWIP_MDIO_PHYp(port));
 	}
 
 	return 0;
@@ -684,14 +693,6 @@
 	if (!dsa_is_user_port(ds, port))
 		return;
 
-	if (!dsa_is_cpu_port(ds, port)) {
-		gswip_mdio_mask(priv, GSWIP_MDIO_PHY_LINK_DOWN,
-				GSWIP_MDIO_PHY_LINK_MASK,
-				GSWIP_MDIO_PHYp(port));
-		/* Deactivate MDIO auto polling */
-		gswip_mdio_mask(priv, BIT(port), 0, GSWIP_MDIO_MDC_CFG0);
-	}
-
 	gswip_switch_mask(priv, GSWIP_FDMA_PCTRL_EN, 0,
 			  GSWIP_FDMA_PCTRLp(port));
 	gswip_switch_mask(priv, GSWIP_SDMA_PCTRL_EN, 0,
@@ -799,15 +800,32 @@
 	gswip_switch_w(priv, BIT(cpu_port), GSWIP_PCE_PMAP2);
 	gswip_switch_w(priv, BIT(cpu_port), GSWIP_PCE_PMAP3);
 
-	/* disable PHY auto polling */
+	/* Deactivate MDIO PHY auto polling. Some PHYs as the AR8030 have an
+	 * interoperability problem with this auto polling mechanism because
+	 * their status registers think that the link is in a different state
+	 * than it actually is. For the AR8030 it has the BMSR_ESTATEN bit set
+	 * as well as ESTATUS_1000_TFULL and ESTATUS_1000_XFULL. This makes the
+	 * auto polling state machine consider the link being negotiated with
+	 * 1Gbit/s. Since the PHY itself is a Fast Ethernet RMII PHY this leads
+	 * to the switch port being completely dead (RX and TX are both not
+	 * working).
+	 * Also with various other PHY / port combinations (PHY11G GPHY, PHY22F
+	 * GPHY, external RGMII PEF7071/7072) any traffic would stop. Sometimes
+	 * it would work fine for a few minutes to hours and then stop, on
+	 * other device it would no traffic could be sent or received at all.
+	 * Testing shows that when PHY auto polling is disabled these problems
+	 * go away.
+	 */
 	gswip_mdio_w(priv, 0x0, GSWIP_MDIO_MDC_CFG0);
+
 	/* Configure the MDIO Clock 2.5 MHz */
 	gswip_mdio_mask(priv, 0xff, 0x09, GSWIP_MDIO_MDC_CFG1);
 
-	/* Disable the xMII link */
-	gswip_mii_mask_cfg(priv, GSWIP_MII_CFG_EN, 0, 0);
-	gswip_mii_mask_cfg(priv, GSWIP_MII_CFG_EN, 0, 1);
-	gswip_mii_mask_cfg(priv, GSWIP_MII_CFG_EN, 0, 5);
+	/* Disable the xMII interface and clear it's isolation bit */
+	for (i = 0; i < priv->hw_info->max_ports; i++)
+		gswip_mii_mask_cfg(priv,
+				   GSWIP_MII_CFG_EN | GSWIP_MII_CFG_ISOLATE,
+				   0, i);
 
 	/* enable special tag insertion on cpu port */
 	gswip_switch_mask(priv, 0, GSWIP_FDMA_PCTRL_STEN,
@@ -819,7 +837,8 @@
 
 	gswip_switch_mask(priv, 0, GSWIP_MAC_CTRL_2_MLEN,
 			  GSWIP_MAC_CTRL_2p(cpu_port));
-	gswip_switch_w(priv, VLAN_ETH_FRAME_LEN + 8, GSWIP_MAC_FLEN);
+	gswip_switch_w(priv, VLAN_ETH_FRAME_LEN + 8 + ETH_FCS_LEN,
+		       GSWIP_MAC_FLEN);
 	gswip_switch_mask(priv, 0, GSWIP_BM_QUEUE_GCTRL_GL_MOD,
 			  GSWIP_BM_QUEUE_GCTRL);
 
@@ -1381,11 +1400,17 @@
 		addr[1] = mac_bridge.key[2] & 0xff;
 		addr[0] = (mac_bridge.key[2] >> 8) & 0xff;
 		if (mac_bridge.val[1] & GSWIP_TABLE_MAC_BRIDGE_STATIC) {
-			if (mac_bridge.val[0] & BIT(port))
-				cb(addr, 0, true, data);
+			if (mac_bridge.val[0] & BIT(port)) {
+				err = cb(addr, 0, true, data);
+				if (err)
+					return err;
+			}
 		} else {
-			if (((mac_bridge.val[0] & GENMASK(7, 4)) >> 4) == port)
-				cb(addr, 0, false, data);
+			if (((mac_bridge.val[0] & GENMASK(7, 4)) >> 4) == port) {
+				err = cb(addr, 0, false, data);
+				if (err)
+					return err;
+			}
 		}
 	}
 	return 0;
@@ -1429,11 +1454,12 @@
 	phylink_set(mask, Pause);
 	phylink_set(mask, Asym_Pause);
 
-	/* With the exclusion of MII and Reverse MII, we support Gigabit,
-	 * including Half duplex
+	/* With the exclusion of MII, Reverse MII and Reduced MII, we
+	 * support Gigabit, including Half duplex
 	 */
 	if (state->interface != PHY_INTERFACE_MODE_MII &&
-	    state->interface != PHY_INTERFACE_MODE_REVMII) {
+	    state->interface != PHY_INTERFACE_MODE_REVMII &&
+	    state->interface != PHY_INTERFACE_MODE_RMII) {
 		phylink_set(mask, 1000baseT_Full);
 		phylink_set(mask, 1000baseT_Half);
 	}
@@ -1451,10 +1477,117 @@
 
 unsupported:
 	bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
-	dev_err(ds->dev, "Unsupported interface: %d\n", state->interface);
+	dev_err(ds->dev, "Unsupported interface '%s' for port %d\n",
+		phy_modes(state->interface), port);
 	return;
 }
 
+static void gswip_port_set_link(struct gswip_priv *priv, int port, bool link)
+{
+	u32 mdio_phy;
+
+	if (link)
+		mdio_phy = GSWIP_MDIO_PHY_LINK_UP;
+	else
+		mdio_phy = GSWIP_MDIO_PHY_LINK_DOWN;
+
+	gswip_mdio_mask(priv, GSWIP_MDIO_PHY_LINK_MASK, mdio_phy,
+			GSWIP_MDIO_PHYp(port));
+}
+
+static void gswip_port_set_speed(struct gswip_priv *priv, int port, int speed,
+				 phy_interface_t interface)
+{
+	u32 mdio_phy = 0, mii_cfg = 0, mac_ctrl_0 = 0;
+
+	switch (speed) {
+	case SPEED_10:
+		mdio_phy = GSWIP_MDIO_PHY_SPEED_M10;
+
+		if (interface == PHY_INTERFACE_MODE_RMII)
+			mii_cfg = GSWIP_MII_CFG_RATE_M50;
+		else
+			mii_cfg = GSWIP_MII_CFG_RATE_M2P5;
+
+		mac_ctrl_0 = GSWIP_MAC_CTRL_0_GMII_MII;
+		break;
+
+	case SPEED_100:
+		mdio_phy = GSWIP_MDIO_PHY_SPEED_M100;
+
+		if (interface == PHY_INTERFACE_MODE_RMII)
+			mii_cfg = GSWIP_MII_CFG_RATE_M50;
+		else
+			mii_cfg = GSWIP_MII_CFG_RATE_M25;
+
+		mac_ctrl_0 = GSWIP_MAC_CTRL_0_GMII_MII;
+		break;
+
+	case SPEED_1000:
+		mdio_phy = GSWIP_MDIO_PHY_SPEED_G1;
+
+		mii_cfg = GSWIP_MII_CFG_RATE_M125;
+
+		mac_ctrl_0 = GSWIP_MAC_CTRL_0_GMII_RGMII;
+		break;
+	}
+
+	gswip_mdio_mask(priv, GSWIP_MDIO_PHY_SPEED_MASK, mdio_phy,
+			GSWIP_MDIO_PHYp(port));
+	gswip_mii_mask_cfg(priv, GSWIP_MII_CFG_RATE_MASK, mii_cfg, port);
+	gswip_switch_mask(priv, GSWIP_MAC_CTRL_0_GMII_MASK, mac_ctrl_0,
+			  GSWIP_MAC_CTRL_0p(port));
+}
+
+static void gswip_port_set_duplex(struct gswip_priv *priv, int port, int duplex)
+{
+	u32 mac_ctrl_0, mdio_phy;
+
+	if (duplex == DUPLEX_FULL) {
+		mac_ctrl_0 = GSWIP_MAC_CTRL_0_FDUP_EN;
+		mdio_phy = GSWIP_MDIO_PHY_FDUP_EN;
+	} else {
+		mac_ctrl_0 = GSWIP_MAC_CTRL_0_FDUP_DIS;
+		mdio_phy = GSWIP_MDIO_PHY_FDUP_DIS;
+	}
+
+	gswip_switch_mask(priv, GSWIP_MAC_CTRL_0_FDUP_MASK, mac_ctrl_0,
+			  GSWIP_MAC_CTRL_0p(port));
+	gswip_mdio_mask(priv, GSWIP_MDIO_PHY_FDUP_MASK, mdio_phy,
+			GSWIP_MDIO_PHYp(port));
+}
+
+static void gswip_port_set_pause(struct gswip_priv *priv, int port,
+				 bool tx_pause, bool rx_pause)
+{
+	u32 mac_ctrl_0, mdio_phy;
+
+	if (tx_pause && rx_pause) {
+		mac_ctrl_0 = GSWIP_MAC_CTRL_0_FCON_RXTX;
+		mdio_phy = GSWIP_MDIO_PHY_FCONTX_EN |
+			   GSWIP_MDIO_PHY_FCONRX_EN;
+	} else if (tx_pause) {
+		mac_ctrl_0 = GSWIP_MAC_CTRL_0_FCON_TX;
+		mdio_phy = GSWIP_MDIO_PHY_FCONTX_EN |
+			   GSWIP_MDIO_PHY_FCONRX_DIS;
+	} else if (rx_pause) {
+		mac_ctrl_0 = GSWIP_MAC_CTRL_0_FCON_RX;
+		mdio_phy = GSWIP_MDIO_PHY_FCONTX_DIS |
+			   GSWIP_MDIO_PHY_FCONRX_EN;
+	} else {
+		mac_ctrl_0 = GSWIP_MAC_CTRL_0_FCON_NONE;
+		mdio_phy = GSWIP_MDIO_PHY_FCONTX_DIS |
+			   GSWIP_MDIO_PHY_FCONRX_DIS;
+	}
+
+	gswip_switch_mask(priv, GSWIP_MAC_CTRL_0_FCON_MASK,
+			  mac_ctrl_0, GSWIP_MAC_CTRL_0p(port));
+	gswip_mdio_mask(priv,
+			GSWIP_MDIO_PHY_FCONTX_MASK |
+			GSWIP_MDIO_PHY_FCONRX_MASK,
+			mdio_phy, GSWIP_MDIO_PHYp(port));
+}
+
 static void gswip_phylink_mac_config(struct dsa_switch *ds, int port,
 				     unsigned int mode,
 				     const struct phylink_link_state *state)
@@ -1486,7 +1619,16 @@
 			"Unsupported interface: %d\n", state->interface);
 		return;
 	}
-	gswip_mii_mask_cfg(priv, GSWIP_MII_CFG_MODE_MASK, miicfg, port);
+
+	gswip_mii_mask_cfg(priv,
+			   GSWIP_MII_CFG_MODE_MASK | GSWIP_MII_CFG_RMII_CLK |
+			   GSWIP_MII_CFG_RGMII_IBS | GSWIP_MII_CFG_LDCLKDIS,
+			   miicfg, port);
+
+	gswip_port_set_speed(priv, port, state->speed, state->interface);
+	gswip_port_set_duplex(priv, port, state->duplex);
+	gswip_port_set_pause(priv, port, !!(state->pause & MLO_PAUSE_TX),
+			     !!(state->pause & MLO_PAUSE_RX));
 
 	switch (state->interface) {
 	case PHY_INTERFACE_MODE_RGMII_ID:
@@ -1511,6 +1653,9 @@
 	struct gswip_priv *priv = ds->priv;
 
 	gswip_mii_mask_cfg(priv, GSWIP_MII_CFG_EN, 0, port);
+
+	if (!dsa_is_cpu_port(ds, port))
+		gswip_port_set_link(priv, port, false);
 }
 
 static void gswip_phylink_mac_link_up(struct dsa_switch *ds, int port,
@@ -1520,9 +1665,10 @@
 {
 	struct gswip_priv *priv = ds->priv;
 
-	/* Enable the xMII interface only for the external PHY */
-	if (interface != PHY_INTERFACE_MODE_INTERNAL)
-		gswip_mii_mask_cfg(priv, 0, GSWIP_MII_CFG_EN, port);
+	if (!dsa_is_cpu_port(ds, port))
+		gswip_port_set_link(priv, port, true);
+
+	gswip_mii_mask_cfg(priv, 0, GSWIP_MII_CFG_EN, port);
 }
 
 static void gswip_get_strings(struct dsa_switch *ds, int port, u32 stringset,
@@ -1812,11 +1958,23 @@
 	for_each_available_child_of_node(gphy_fw_list_np, gphy_fw_np) {
 		err = gswip_gphy_fw_probe(priv, &priv->gphy_fw[i],
 					  gphy_fw_np, i);
-		if (err)
+		if (err) {
+			of_node_put(gphy_fw_np);
 			goto remove_gphy;
+		}
 		i++;
 	}
 
+	/* The standalone PHY11G requires 300ms to be fully
+	 * initialized and ready for any MDIO communication after being
+	 * taken out of reset. For the SoC-internal GPHY variant there
+	 * is no (known) documentation for the minimum time after a
+	 * reset. Use the same value as for the standalone variant as
+	 * some users have reported internal PHYs not being detected
+	 * without any delay.
+	 */
+	msleep(300);
+
 	return 0;
 
 remove_gphy:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/microchip/ksz8795.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/microchip/ksz8795.c
@@ -1267,6 +1267,9 @@
 			return -ENOMEM;
 	}
 
+	/* set the real number of ports */
+	dev->ds->num_ports = dev->port_cnt;
+
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/microchip/ksz8795_spi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/microchip/ksz8795_spi.c
@@ -86,12 +86,23 @@
 };
 MODULE_DEVICE_TABLE(of, ksz8795_dt_ids);
 
+static const struct spi_device_id ksz8795_spi_ids[] = {
+	{ "ksz8765" },
+	{ "ksz8794" },
+	{ "ksz8795" },
+	{ "ksz8863" },
+	{ "ksz8873" },
+	{ },
+};
+MODULE_DEVICE_TABLE(spi, ksz8795_spi_ids);
+
 static struct spi_driver ksz8795_spi_driver = {
 	.driver = {
 		.name	= "ksz8795-switch",
 		.owner	= THIS_MODULE,
 		.of_match_table = of_match_ptr(ksz8795_dt_ids),
 	},
+	.id_table = ksz8795_spi_ids,
 	.probe	= ksz8795_spi_probe,
 	.remove	= ksz8795_spi_remove,
 	.shutdown = ksz8795_spi_shutdown,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/microchip/ksz9477.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/microchip/ksz9477.c
@@ -206,10 +206,8 @@
 			   SPI_AUTO_EDGE_DETECTION, 0);
 
 	/* default configuration */
-	ksz_read8(dev, REG_SW_LUE_CTRL_1, &data8);
-	data8 = SW_AGING_ENABLE | SW_LINK_AUTO_AGING |
-	      SW_SRC_ADDR_FILTER | SW_FLUSH_STP_TABLE | SW_FLUSH_MSTP_TABLE;
-	ksz_write8(dev, REG_SW_LUE_CTRL_1, data8);
+	ksz_write8(dev, REG_SW_LUE_CTRL_1,
+		   SW_AGING_ENABLE | SW_LINK_AUTO_AGING | SW_SRC_ADDR_FILTER);
 
 	/* disable interrupts */
 	ksz_write32(dev, REG_SW_INT_MASK__4, SWITCH_INT_MASK);
@@ -682,10 +680,10 @@
 		ksz_read32(dev, REG_SW_ALU_VAL_D, &alu_table[3]);
 
 		/* clear forwarding port */
-		alu_table[2] &= ~BIT(port);
+		alu_table[1] &= ~BIT(port);
 
 		/* if there is no port to forward, clear table */
-		if ((alu_table[2] & ALU_V_PORT_MAP) == 0) {
+		if ((alu_table[1] & ALU_V_PORT_MAP) == 0) {
 			alu_table[0] = 0;
 			alu_table[1] = 0;
 			alu_table[2] = 0;
@@ -766,6 +764,9 @@
 			goto exit;
 		}
 
+		if (!(ksz_data & ALU_VALID))
+			continue;
+
 		/* read ALU table */
 		ksz9477_read_table(dev, alu_table);
 
@@ -973,23 +974,6 @@
 			     PORT_MIRROR_SNIFFER, false);
 }
 
-static void ksz9477_phy_setup(struct ksz_device *dev, int port,
-			      struct phy_device *phy)
-{
-	/* Only apply to port with PHY. */
-	if (port >= dev->phy_port_cnt)
-		return;
-
-	/* The MAC actually cannot run in 1000 half-duplex mode. */
-	phy_remove_link_mode(phy,
-			     ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
-
-	/* PHY does not support gigabit. */
-	if (!(dev->features & GBIT_SUPPORT))
-		phy_remove_link_mode(phy,
-				     ETHTOOL_LINK_MODE_1000baseT_Full_BIT);
-}
-
 static bool ksz9477_get_gbit(struct ksz_device *dev, u8 data)
 {
 	bool gbit;
@@ -1537,6 +1521,7 @@
 		.num_statics = 16,
 		.cpu_ports = 0x7F,	/* can be configured as cpu port */
 		.port_cnt = 7,		/* total physical port count */
+		.phy_errata_9477 = true,
 	},
 };
 
@@ -1587,6 +1572,9 @@
 			return -ENOMEM;
 	}
 
+	/* set the real number of ports */
+	dev->ds->num_ports = dev->port_cnt;
+
 	return 0;
 }
 
@@ -1599,7 +1587,6 @@
 	.get_port_addr = ksz9477_get_port_addr,
 	.cfg_port_member = ksz9477_cfg_port_member,
 	.flush_dyn_mac_table = ksz9477_flush_dyn_mac_table,
-	.phy_setup = ksz9477_phy_setup,
 	.port_setup = ksz9477_port_setup,
 	.r_mib_cnt = ksz9477_r_mib_cnt,
 	.r_mib_pkt = ksz9477_r_mib_pkt,
@@ -1613,7 +1600,29 @@
 
 int ksz9477_switch_register(struct ksz_device *dev)
 {
-	return ksz_switch_register(dev, &ksz9477_dev_ops);
+	int ret, i;
+	struct phy_device *phydev;
+
+	ret = ksz_switch_register(dev, &ksz9477_dev_ops);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < dev->phy_port_cnt; ++i) {
+		if (!dsa_is_user_port(dev->ds, i))
+			continue;
+
+		phydev = dsa_to_port(dev->ds, i)->slave->phydev;
+
+		/* The MAC actually cannot run in 1000 half-duplex mode. */
+		phy_remove_link_mode(phydev,
+				     ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
+
+		/* PHY does not support gigabit. */
+		if (!(dev->features & GBIT_SUPPORT))
+			phy_remove_link_mode(phydev,
+					     ETHTOOL_LINK_MODE_1000baseT_Full_BIT);
+	}
+	return ret;
 }
 EXPORT_SYMBOL(ksz9477_switch_register);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/microchip/ksz9477_spi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/microchip/ksz9477_spi.c
@@ -88,12 +88,24 @@
 };
 MODULE_DEVICE_TABLE(of, ksz9477_dt_ids);
 
+static const struct spi_device_id ksz9477_spi_ids[] = {
+	{ "ksz9477" },
+	{ "ksz9897" },
+	{ "ksz9893" },
+	{ "ksz9563" },
+	{ "ksz8563" },
+	{ "ksz9567" },
+	{ },
+};
+MODULE_DEVICE_TABLE(spi, ksz9477_spi_ids);
+
 static struct spi_driver ksz9477_spi_driver = {
 	.driver = {
 		.name	= "ksz9477-switch",
 		.owner	= THIS_MODULE,
 		.of_match_table = of_match_ptr(ksz9477_dt_ids),
 	},
+	.id_table = ksz9477_spi_ids,
 	.probe	= ksz9477_spi_probe,
 	.remove	= ksz9477_spi_remove,
 	.shutdown = ksz9477_spi_shutdown,
@@ -101,6 +113,12 @@
 
 module_spi_driver(ksz9477_spi_driver);
 
+MODULE_ALIAS("spi:ksz9477");
+MODULE_ALIAS("spi:ksz9897");
+MODULE_ALIAS("spi:ksz9893");
+MODULE_ALIAS("spi:ksz9563");
+MODULE_ALIAS("spi:ksz8563");
+MODULE_ALIAS("spi:ksz9567");
 MODULE_AUTHOR("Woojung Huh <Woojung.Huh@microchip.com>");
 MODULE_DESCRIPTION("Microchip KSZ9477 Series Switch SPI access Driver");
 MODULE_LICENSE("GPL");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/microchip/ksz_common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/microchip/ksz_common.c
@@ -366,8 +366,6 @@
 
 	/* setup slave port */
 	dev->dev_ops->port_setup(dev, port, false);
-	if (dev->dev_ops->phy_setup)
-		dev->dev_ops->phy_setup(dev, port, phy);
 
 	/* port_stp_state_set() will be called after to enable the port so
 	 * there is no need to do anything.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/microchip/ksz_common.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/microchip/ksz_common.h
@@ -120,8 +120,6 @@
 	u32 (*get_port_addr)(int port, int offset);
 	void (*cfg_port_member)(struct ksz_device *dev, int port, u8 member);
 	void (*flush_dyn_mac_table)(struct ksz_device *dev, int port);
-	void (*phy_setup)(struct ksz_device *dev, int port,
-			  struct phy_device *phy);
 	void (*port_cleanup)(struct ksz_device *dev, int port);
 	void (*port_setup)(struct ksz_device *dev, int port, bool cpu_port);
 	void (*r_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 *val);
@@ -217,12 +215,8 @@
 	int ret;
 
 	ret = regmap_bulk_read(dev->regmap[2], reg, value, 2);
-	if (!ret) {
-		/* Ick! ToDo: Add 64bit R/W to regmap on 32bit systems */
-		value[0] = swab32(value[0]);
-		value[1] = swab32(value[1]);
-		*val = swab64((u64)*value);
-	}
+	if (!ret)
+		*val = (u64)value[0] << 32 | value[1];
 
 	return ret;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/mt7530.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/mt7530.c
@@ -45,6 +45,7 @@
 	MIB_DESC(2, 0x48, "TxBytes"),
 	MIB_DESC(1, 0x60, "RxDrop"),
 	MIB_DESC(1, 0x64, "RxFiltering"),
+	MIB_DESC(1, 0x68, "RxUnicast"),
 	MIB_DESC(1, 0x6c, "RxMulticast"),
 	MIB_DESC(1, 0x70, "RxBroadcast"),
 	MIB_DESC(1, 0x74, "RxAlignErr"),
@@ -67,58 +68,6 @@
 };
 
 static int
-mt7623_trgmii_write(struct mt7530_priv *priv,  u32 reg, u32 val)
-{
-	int ret;
-
-	ret =  regmap_write(priv->ethernet, TRGMII_BASE(reg), val);
-	if (ret < 0)
-		dev_err(priv->dev,
-			"failed to priv write register\n");
-	return ret;
-}
-
-static u32
-mt7623_trgmii_read(struct mt7530_priv *priv, u32 reg)
-{
-	int ret;
-	u32 val;
-
-	ret = regmap_read(priv->ethernet, TRGMII_BASE(reg), &val);
-	if (ret < 0) {
-		dev_err(priv->dev,
-			"failed to priv read register\n");
-		return ret;
-	}
-
-	return val;
-}
-
-static void
-mt7623_trgmii_rmw(struct mt7530_priv *priv, u32 reg,
-		  u32 mask, u32 set)
-{
-	u32 val;
-
-	val = mt7623_trgmii_read(priv, reg);
-	val &= ~mask;
-	val |= set;
-	mt7623_trgmii_write(priv, reg, val);
-}
-
-static void
-mt7623_trgmii_set(struct mt7530_priv *priv, u32 reg, u32 val)
-{
-	mt7623_trgmii_rmw(priv, reg, 0, val);
-}
-
-static void
-mt7623_trgmii_clear(struct mt7530_priv *priv, u32 reg, u32 val)
-{
-	mt7623_trgmii_rmw(priv, reg, val, 0);
-}
-
-static int
 core_read_mmd_indirect(struct mt7530_priv *priv, int prtad, int devad)
 {
 	struct mii_bus *bus = priv->bus;
@@ -448,9 +397,9 @@
 	case PHY_INTERFACE_MODE_TRGMII:
 		trgint = 1;
 		if (priv->id == ID_MT7621) {
-			/* PLL frequency: 150MHz: 1.2GBit */
+			/* PLL frequency: 125MHz: 1.0GBit */
 			if (xtal == HWTRAP_XTAL_40MHZ)
-				ncpo1 = 0x0780;
+				ncpo1 = 0x0640;
 			if (xtal == HWTRAP_XTAL_25MHZ)
 				ncpo1 = 0x0a00;
 		} else { /* PLL frequency: 250MHz: 2.0Gbit */
@@ -530,27 +479,6 @@
 		for (i = 0 ; i < NUM_TRGMII_CTRL; i++)
 			mt7530_rmw(priv, MT7530_TRGMII_RD(i),
 				   RD_TAP_MASK, RD_TAP(16));
-	else
-		if (priv->id != ID_MT7621)
-			mt7623_trgmii_set(priv, GSW_INTF_MODE,
-					  INTF_MODE_TRGMII);
-
-	return 0;
-}
-
-static int
-mt7623_pad_clk_setup(struct dsa_switch *ds)
-{
-	struct mt7530_priv *priv = ds->priv;
-	int i;
-
-	for (i = 0 ; i < NUM_TRGMII_CTRL; i++)
-		mt7623_trgmii_write(priv, GSW_TRGMII_TD_ODT(i),
-				    TD_DM_DRVP(8) | TD_DM_DRVN(8));
-
-	mt7623_trgmii_set(priv, GSW_TRGMII_RCK_CTRL, RX_RST | RXC_DQSISEL);
-	mt7623_trgmii_clear(priv, GSW_TRGMII_RCK_CTRL, RX_RST);
-
 	return 0;
 }
 
@@ -566,7 +494,7 @@
 static void
 mt7530_port_set_status(struct mt7530_priv *priv, int port, int enable)
 {
-	u32 mask = PMCR_TX_EN | PMCR_RX_EN;
+	u32 mask = PMCR_TX_EN | PMCR_RX_EN | PMCR_FORCE_LNK;
 
 	if (enable)
 		mt7530_set(priv, MT7530_PMCR_P(port), mask);
@@ -712,14 +640,11 @@
 	mt7530_write(priv, MT7530_PVC_P(port),
 		     PORT_SPEC_TAG);
 
-	/* Disable auto learning on the cpu port */
-	mt7530_set(priv, MT7530_PSC_P(port), SA_DIS);
-
-	/* Unknown unicast frame fordwarding to the cpu port */
-	mt7530_set(priv, MT7530_MFC, UNU_FFP(BIT(port)));
+	/* Unknown multicast frame forwarding to the cpu port */
+	mt7530_rmw(priv, MT7530_MFC, UNM_FFP_MASK, UNM_FFP(BIT(port)));
 
 	/* Set CPU port number */
-	if (priv->id == ID_MT7621)
+	if (priv->id == ID_MT7530 || priv->id == ID_MT7621)
 		mt7530_rmw(priv, MT7530_MFC, CPU_MASK, CPU_EN | CPU_PORT(port));
 
 	/* CPU port gets connected to all user ports of
@@ -857,8 +782,9 @@
 	 */
 	mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK,
 		   MT7530_PORT_MATRIX_MODE);
-	mt7530_rmw(priv, MT7530_PVC_P(port), VLAN_ATTR_MASK,
-		   VLAN_ATTR(MT7530_VLAN_TRANSPARENT));
+	mt7530_rmw(priv, MT7530_PVC_P(port), VLAN_ATTR_MASK | PVC_EG_TAG_MASK,
+		   VLAN_ATTR(MT7530_VLAN_TRANSPARENT) |
+		   PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT));
 
 	for (i = 0; i < MT7530_NUM_PORTS; i++) {
 		if (dsa_is_user_port(ds, i) &&
@@ -874,8 +800,8 @@
 	if (all_user_ports_removed) {
 		mt7530_write(priv, MT7530_PCR_P(MT7530_CPU_PORT),
 			     PCR_MATRIX(dsa_user_ports(priv->ds)));
-		mt7530_write(priv, MT7530_PVC_P(MT7530_CPU_PORT),
-			     PORT_SPEC_TAG);
+		mt7530_write(priv, MT7530_PVC_P(MT7530_CPU_PORT), PORT_SPEC_TAG
+			     | PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT));
 	}
 }
 
@@ -884,25 +810,23 @@
 {
 	struct mt7530_priv *priv = ds->priv;
 
-	/* The real fabric path would be decided on the membership in the
-	 * entry of VLAN table. PCR_MATRIX set up here with ALL_MEMBERS
-	 * means potential VLAN can be consisting of certain subset of all
-	 * ports.
-	 */
-	mt7530_rmw(priv, MT7530_PCR_P(port),
-		   PCR_MATRIX_MASK, PCR_MATRIX(MT7530_ALL_MEMBERS));
-
 	/* Trapped into security mode allows packet forwarding through VLAN
-	 * table lookup.
+	 * table lookup. CPU port is set to fallback mode to let untagged
+	 * frames pass through.
 	 */
-	mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK,
-		   MT7530_PORT_SECURITY_MODE);
+	if (dsa_is_cpu_port(ds, port))
+		mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK,
+			   MT7530_PORT_FALLBACK_MODE);
+	else
+		mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK,
+			   MT7530_PORT_SECURITY_MODE);
 
 	/* Set the port as a user port which is to be able to recognize VID
 	 * from incoming packets before fetching entry within the VLAN table.
 	 */
-	mt7530_rmw(priv, MT7530_PVC_P(port), VLAN_ATTR_MASK,
-		   VLAN_ATTR(MT7530_VLAN_USER));
+	mt7530_rmw(priv, MT7530_PVC_P(port), VLAN_ATTR_MASK | PVC_EG_TAG_MASK,
+		   VLAN_ATTR(MT7530_VLAN_USER) |
+		   PVC_EG_TAG(MT7530_VLAN_EG_DISABLED));
 }
 
 static void
@@ -918,11 +842,8 @@
 		/* Remove this port from the port matrix of the other ports
 		 * in the same bridge. If the port is disabled, port matrix
 		 * is kept and not being setup until the port becomes enabled.
-		 * And the other port's port matrix cannot be broken when the
-		 * other port is still a VLAN-aware port.
 		 */
-		if (dsa_is_user_port(ds, i) && i != port &&
-		   !dsa_port_is_vlan_filtering(&ds->ports[i])) {
+		if (dsa_is_user_port(ds, i) && i != port) {
 			if (dsa_to_port(ds, i)->bridge_dev != bridge)
 				continue;
 			if (priv->ports[i].enable)
@@ -1255,10 +1176,6 @@
 	dn = ds->ports[MT7530_CPU_PORT].master->dev.of_node->parent;
 
 	if (priv->id == ID_MT7530) {
-		priv->ethernet = syscon_node_to_regmap(dn);
-		if (IS_ERR(priv->ethernet))
-			return PTR_ERR(priv->ethernet);
-
 		regulator_set_voltage(priv->core_pwr, 1000000, 1000000);
 		ret = regulator_enable(priv->core_pwr);
 		if (ret < 0) {
@@ -1321,8 +1238,6 @@
 	/* Enable and reset MIB counters */
 	mt7530_mib_reset(ds);
 
-	mt7530_clear(priv, MT7530_MFC, UNU_FFP_MASK);
-
 	for (i = 0; i < MT7530_NUM_PORTS; i++) {
 		/* Disable forwarding by default on all ports */
 		mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK,
@@ -1332,6 +1247,10 @@
 			mt7530_cpu_port_enable(priv, i);
 		else
 			mt7530_port_disable(ds, i);
+
+		/* Enable consistent egress tag */
+		mt7530_rmw(priv, MT7530_PVC_P(i), PVC_EG_TAG_MASK,
+			   PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT));
 	}
 
 	/* Setup port 5 */
@@ -1353,6 +1272,9 @@
 				continue;
 
 			phy_node = of_parse_phandle(mac_np, "phy-handle", 0);
+			if (!phy_node)
+				continue;
+
 			if (phy_node->parent == priv->dev->of_node->parent) {
 				interface = of_get_phy_mode(mac_np);
 				id = of_mdio_parse_addr(ds->dev, phy_node);
@@ -1413,14 +1335,6 @@
 		/* Setup TX circuit incluing relevant PAD and driving */
 		mt7530_pad_clk_setup(ds, state->interface);
 
-		if (priv->id == ID_MT7530) {
-			/* Setup RX circuit, relevant PAD and driving on the
-			 * host which must be placed after the setup on the
-			 * device side is all finished.
-			 */
-			mt7623_pad_clk_setup(ds);
-		}
-
 		priv->p6_interface = state->interface;
 		break;
 	default:
@@ -1439,7 +1353,7 @@
 	mcr_new &= ~(PMCR_FORCE_SPEED_1000 | PMCR_FORCE_SPEED_100 |
 		     PMCR_FORCE_FDX | PMCR_TX_FC_EN | PMCR_RX_FC_EN);
 	mcr_new |= PMCR_IFG_XMIT(1) | PMCR_MAC_MODE | PMCR_BACKOFF_EN |
-		   PMCR_BACKPR_EN | PMCR_FORCE_MODE | PMCR_FORCE_LNK;
+		   PMCR_BACKPR_EN | PMCR_FORCE_MODE;
 
 	/* Are we connected to external phy */
 	if (port == 5 && dsa_is_user_port(ds, 5))
@@ -1532,7 +1446,7 @@
 		phylink_set(mask, 100baseT_Full);
 
 		if (state->interface != PHY_INTERFACE_MODE_MII) {
-			phylink_set(mask, 1000baseT_Half);
+			/* This switch only supports 1G full-duplex. */
 			phylink_set(mask, 1000baseT_Full);
 			if (port == 5)
 				phylink_set(mask, 1000baseX_Full);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/mt7530.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/mt7530.h
@@ -31,6 +31,7 @@
 #define MT7530_MFC			0x10
 #define  BC_FFP(x)			(((x) & 0xff) << 24)
 #define  UNM_FFP(x)			(((x) & 0xff) << 16)
+#define  UNM_FFP_MASK			UNM_FFP(~0)
 #define  UNU_FFP(x)			(((x) & 0xff) << 8)
 #define  UNU_FFP_MASK			UNU_FFP(~0)
 #define  CPU_EN				BIT(7)
@@ -147,6 +148,12 @@
 	/* Port Matrix Mode: Frames are forwarded by the PCR_MATRIX members. */
 	MT7530_PORT_MATRIX_MODE = PORT_VLAN(0),
 
+	/* Fallback Mode: Forward received frames with ingress ports that do
+	 * not belong to the VLAN member. Frames whose VID is not listed on
+	 * the VLAN table are forwarded by the PCR_MATRIX members.
+	 */
+	MT7530_PORT_FALLBACK_MODE = PORT_VLAN(1),
+
 	/* Security Mode: Discard any frame due to ingress membership
 	 * violation or VID missed on the VLAN table.
 	 */
@@ -167,9 +174,16 @@
 /* Register for port vlan control */
 #define MT7530_PVC_P(x)			(0x2010 + ((x) * 0x100))
 #define  PORT_SPEC_TAG			BIT(5)
+#define  PVC_EG_TAG(x)			(((x) & 0x7) << 8)
+#define  PVC_EG_TAG_MASK		PVC_EG_TAG(7)
 #define  VLAN_ATTR(x)			(((x) & 0x3) << 6)
 #define  VLAN_ATTR_MASK			VLAN_ATTR(3)
 
+enum mt7530_vlan_port_eg_tag {
+	MT7530_VLAN_EG_DISABLED = 0,
+	MT7530_VLAN_EG_CONSISTENT = 1,
+};
+
 enum mt7530_vlan_port_attr {
 	MT7530_VLAN_USER = 0,
 	MT7530_VLAN_TRANSPARENT = 3,
@@ -268,7 +282,6 @@
 
 /* Registers for TRGMII on the both side */
 #define MT7530_TRGMII_RCK_CTRL		0x7a00
-#define GSW_TRGMII_RCK_CTRL		0x300
 #define  RX_RST				BIT(31)
 #define  RXC_DQSISEL			BIT(30)
 #define  DQSI1_TAP_MASK			(0x7f << 8)
@@ -277,31 +290,24 @@
 #define  DQSI0_TAP(x)			((x) & 0x7f)
 
 #define MT7530_TRGMII_RCK_RTT		0x7a04
-#define GSW_TRGMII_RCK_RTT		0x304
 #define  DQS1_GATE			BIT(31)
 #define  DQS0_GATE			BIT(30)
 
 #define MT7530_TRGMII_RD(x)		(0x7a10 + (x) * 8)
-#define GSW_TRGMII_RD(x)		(0x310 + (x) * 8)
 #define  BSLIP_EN			BIT(31)
 #define  EDGE_CHK			BIT(30)
 #define  RD_TAP_MASK			0x7f
 #define  RD_TAP(x)			((x) & 0x7f)
 
-#define GSW_TRGMII_TXCTRL		0x340
 #define MT7530_TRGMII_TXCTRL		0x7a40
 #define  TRAIN_TXEN			BIT(31)
 #define  TXC_INV			BIT(30)
 #define  TX_RST				BIT(28)
 
 #define MT7530_TRGMII_TD_ODT(i)		(0x7a54 + 8 * (i))
-#define GSW_TRGMII_TD_ODT(i)		(0x354 + 8 * (i))
 #define  TD_DM_DRVP(x)			((x) & 0xf)
 #define  TD_DM_DRVN(x)			(((x) & 0xf) << 4)
 
-#define GSW_INTF_MODE			0x390
-#define  INTF_MODE_TRGMII		BIT(1)
-
 #define MT7530_TRGMII_TCK_CTRL		0x7a78
 #define  TCK_TAP(x)			(((x) & 0xf) << 8)
 
@@ -434,7 +440,6 @@
  * @ds:			The pointer to the dsa core structure
  * @bus:		The bus used for the device and built-in PHY
  * @rstc:		The pointer to reset control used by MCM
- * @ethernet:		The regmap used for access TRGMII-based registers
  * @core_pwr:		The power supplied into the core
  * @io_pwr:		The power supplied into the I/O
  * @reset:		The descriptor for GPIO line tied to its reset pin
@@ -451,7 +456,6 @@
 	struct dsa_switch	*ds;
 	struct mii_bus		*bus;
 	struct reset_control	*rstc;
-	struct regmap		*ethernet;
 	struct regulator	*core_pwr;
 	struct regulator	*io_pwr;
 	struct gpio_desc	*reset;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/mv88e6060.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/mv88e6060.c
@@ -117,6 +117,9 @@
 	int addr = REG_PORT(p);
 	int ret;
 
+	if (dsa_is_unused_port(priv->ds, p))
+		return 0;
+
 	/* Do not force flow control, disable Ingress and Egress
 	 * Header tagging, disable VLAN tunneling, and set the port
 	 * state to Forwarding.  Additionally, if this is the CPU
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/mv88e6xxx/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/mv88e6xxx/Makefile
@@ -14,3 +14,7 @@
 mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_PTP) += ptp.o
 mv88e6xxx-objs += serdes.o
 mv88e6xxx-objs += smi.o
+mv88e6xxx-objs += trace.o
+
+# for tracing framework to find trace.h
+CFLAGS_trace.o := -I$(src)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/mv88e6xxx/chip.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/mv88e6xxx/chip.c
@@ -115,8 +115,8 @@
 {
 	struct mv88e6xxx_mdio_bus *mdio_bus;
 
-	mdio_bus = list_first_entry(&chip->mdios, struct mv88e6xxx_mdio_bus,
-				    list);
+	mdio_bus = list_first_entry_or_null(&chip->mdios,
+					    struct mv88e6xxx_mdio_bus, list);
 	if (!mdio_bus)
 		return NULL;
 
@@ -1517,7 +1517,11 @@
 		if (!entry.portvec)
 			entry.state = 0;
 	} else {
-		entry.portvec |= BIT(port);
+		if (state == MV88E6XXX_G1_ATU_DATA_STATE_UC_STATIC)
+			entry.portvec = BIT(port);
+		else
+			entry.portvec |= BIT(port);
+
 		entry.state = state;
 	}
 
@@ -2139,10 +2143,22 @@
 
 	/* If there is a GPIO connected to the reset pin, toggle it */
 	if (gpiod) {
+		/* If the switch has just been reset and not yet completed
+		 * loading EEPROM, the reset may interrupt the I2C transaction
+		 * mid-byte, causing the first EEPROM read after the reset
+		 * from the wrong location resulting in the switch booting
+		 * to wrong mode and inoperable.
+		 */
+		if (chip->info->ops->get_eeprom)
+			mv88e6xxx_g2_eeprom_wait(chip);
+
 		gpiod_set_value_cansleep(gpiod, 1);
 		usleep_range(10000, 20000);
 		gpiod_set_value_cansleep(gpiod, 0);
 		usleep_range(10000, 20000);
+
+		if (chip->info->ops->get_eeprom)
+			mv88e6xxx_g2_eeprom_wait(chip);
 	}
 }
 
@@ -2427,9 +2443,14 @@
 	 * If this is the upstream port for this switch, enable
 	 * forwarding of unknown unicasts and multicasts.
 	 */
-	reg = MV88E6XXX_PORT_CTL0_IGMP_MLD_SNOOP |
-		MV88E6185_PORT_CTL0_USE_TAG | MV88E6185_PORT_CTL0_USE_IP |
+	reg = MV88E6185_PORT_CTL0_USE_TAG | MV88E6185_PORT_CTL0_USE_IP |
 		MV88E6XXX_PORT_CTL0_STATE_FORWARDING;
+	/* Forward any IPv4 IGMP or IPv6 MLD frames received
+	 * by a USER port to the CPU port to allow snooping.
+	 */
+	if (dsa_is_user_port(ds, port))
+		reg |= MV88E6XXX_PORT_CTL0_IGMP_MLD_SNOOP;
+
 	err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);
 	if (err)
 		return err;
@@ -2760,10 +2781,17 @@
 	return err;
 }
 
+/* prod_id for switch families which do not have a PHY model number */
+static const u16 family_prod_id_table[] = {
+	[MV88E6XXX_FAMILY_6341] = MV88E6XXX_PORT_SWITCH_ID_PROD_6341,
+	[MV88E6XXX_FAMILY_6390] = MV88E6XXX_PORT_SWITCH_ID_PROD_6390,
+};
+
 static int mv88e6xxx_mdio_read(struct mii_bus *bus, int phy, int reg)
 {
 	struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv;
 	struct mv88e6xxx_chip *chip = mdio_bus->chip;
+	u16 prod_id;
 	u16 val;
 	int err;
 
@@ -2774,23 +2802,12 @@
 	err = chip->info->ops->phy_read(chip, bus, phy, reg, &val);
 	mv88e6xxx_reg_unlock(chip);
 
-	if (reg == MII_PHYSID2) {
-		/* Some internal PHYs don't have a model number. */
-		if (chip->info->family != MV88E6XXX_FAMILY_6165)
-			/* Then there is the 6165 family. It gets is
-			 * PHYs correct. But it can also have two
-			 * SERDES interfaces in the PHY address
-			 * space. And these don't have a model
-			 * number. But they are not PHYs, so we don't
-			 * want to give them something a PHY driver
-			 * will recognise.
-			 *
-			 * Use the mv88e6390 family model number
-			 * instead, for anything which really could be
-			 * a PHY,
-			 */
-			if (!(val & 0x3f0))
-				val |= MV88E6XXX_PORT_SWITCH_ID_PROD_6390 >> 4;
+	/* Some internal PHYs don't have a model number. */
+	if (reg == MII_PHYSID2 && !(val & 0x3f0) &&
+	    chip->info->family < ARRAY_SIZE(family_prod_id_table)) {
+		prod_id = family_prod_id_table[chip->info->family];
+		if (prod_id)
+			val |= prod_id >> 4;
 	}
 
 	return err ? err : val;
@@ -2908,6 +2925,7 @@
 	 */
 	child = of_get_child_by_name(np, "mdio");
 	err = mv88e6xxx_mdio_register(chip, child, false);
+	of_node_put(child);
 	if (err)
 		return err;
 
@@ -3060,10 +3078,10 @@
 	.port_set_duplex = mv88e6xxx_port_set_duplex,
 	.port_set_speed = mv88e6185_port_set_speed,
 	.port_tag_remap = mv88e6095_port_tag_remap,
+	.port_set_policy = mv88e6352_port_set_policy,
 	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
 	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
 	.port_set_ether_type = mv88e6351_port_set_ether_type,
-	.port_set_jumbo_size = mv88e6165_port_set_jumbo_size,
 	.port_egress_rate_limiting = mv88e6095_port_egress_rate_limiting,
 	.port_pause_limit = mv88e6097_port_pause_limit,
 	.port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit,
@@ -3191,7 +3209,7 @@
 	.port_set_cmode = mv88e6341_port_set_cmode,
 	.port_setup_message_port = mv88e6xxx_setup_message_port,
 	.stats_snapshot = mv88e6390_g1_stats_snapshot,
-	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
+	.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
 	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
 	.stats_get_strings = mv88e6320_stats_get_strings,
 	.stats_get_stats = mv88e6390_stats_get_stats,
@@ -3714,6 +3732,7 @@
 	.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
 	.port_set_speed = mv88e6250_port_set_speed,
 	.port_tag_remap = mv88e6095_port_tag_remap,
+	.port_set_policy = mv88e6352_port_set_policy,
 	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
 	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
 	.port_set_ether_type = mv88e6351_port_set_ether_type,
@@ -3867,6 +3886,7 @@
 	.set_cpu_port = mv88e6095_g1_set_cpu_port,
 	.set_egress_port = mv88e6095_g1_set_egress_port,
 	.watchdog_ops = &mv88e6390_watchdog_ops,
+	.mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
 	.reset = mv88e6352_g1_reset,
 	.vtu_getnext = mv88e6185_g1_vtu_getnext,
 	.vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
@@ -3905,7 +3925,7 @@
 	.port_set_cmode = mv88e6341_port_set_cmode,
 	.port_setup_message_port = mv88e6xxx_setup_message_port,
 	.stats_snapshot = mv88e6390_g1_stats_snapshot,
-	.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
+	.stats_set_histogram = mv88e6390_g1_stats_set_histogram,
 	.stats_get_sset_count = mv88e6320_stats_get_sset_count,
 	.stats_get_strings = mv88e6320_stats_get_strings,
 	.stats_get_stats = mv88e6390_stats_get_stats,
@@ -3915,6 +3935,7 @@
 	.mgmt_rsvd2cpu =  mv88e6390_g1_mgmt_rsvd2cpu,
 	.pot_clear = mv88e6xxx_g2_pot_clear,
 	.reset = mv88e6352_g1_reset,
+	.rmu_disable = mv88e6390_g1_rmu_disable,
 	.vtu_getnext = mv88e6352_g1_vtu_getnext,
 	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
 	.serdes_power = mv88e6390_serdes_power,
@@ -3981,6 +4002,7 @@
 	.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
 	.port_set_speed = mv88e6185_port_set_speed,
 	.port_tag_remap = mv88e6095_port_tag_remap,
+	.port_set_policy = mv88e6352_port_set_policy,
 	.port_set_frame_mode = mv88e6351_port_set_frame_mode,
 	.port_set_egress_floods = mv88e6352_port_set_egress_floods,
 	.port_set_ether_type = mv88e6351_port_set_ether_type,
@@ -4003,6 +4025,7 @@
 	.mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
 	.pot_clear = mv88e6xxx_g2_pot_clear,
 	.reset = mv88e6352_g1_reset,
+	.rmu_disable = mv88e6390_g1_rmu_disable,
 	.vtu_getnext = mv88e6352_g1_vtu_getnext,
 	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
 	.avb_ops = &mv88e6352_avb_ops,
@@ -4177,6 +4200,7 @@
 		.family = MV88E6XXX_FAMILY_6097,
 		.name = "Marvell 88E6085",
 		.num_databases = 4096,
+		.num_macs = 8192,
 		.num_ports = 10,
 		.num_internal_phys = 5,
 		.max_vid = 4095,
@@ -4199,6 +4223,7 @@
 		.family = MV88E6XXX_FAMILY_6095,
 		.name = "Marvell 88E6095/88E6095F",
 		.num_databases = 256,
+		.num_macs = 8192,
 		.num_ports = 11,
 		.num_internal_phys = 0,
 		.max_vid = 4095,
@@ -4219,6 +4244,7 @@
 		.family = MV88E6XXX_FAMILY_6097,
 		.name = "Marvell 88E6097/88E6097F",
 		.num_databases = 4096,
+		.num_macs = 8192,
 		.num_ports = 11,
 		.num_internal_phys = 8,
 		.max_vid = 4095,
@@ -4241,6 +4267,7 @@
 		.family = MV88E6XXX_FAMILY_6165,
 		.name = "Marvell 88E6123",
 		.num_databases = 4096,
+		.num_macs = 1024,
 		.num_ports = 3,
 		.num_internal_phys = 5,
 		.max_vid = 4095,
@@ -4263,6 +4290,7 @@
 		.family = MV88E6XXX_FAMILY_6185,
 		.name = "Marvell 88E6131",
 		.num_databases = 256,
+		.num_macs = 8192,
 		.num_ports = 8,
 		.num_internal_phys = 0,
 		.max_vid = 4095,
@@ -4282,7 +4310,8 @@
 		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6141,
 		.family = MV88E6XXX_FAMILY_6341,
 		.name = "Marvell 88E6141",
-		.num_databases = 4096,
+		.num_databases = 256,
+		.num_macs = 2048,
 		.num_ports = 6,
 		.num_internal_phys = 5,
 		.num_gpio = 11,
@@ -4306,6 +4335,7 @@
 		.family = MV88E6XXX_FAMILY_6165,
 		.name = "Marvell 88E6161",
 		.num_databases = 4096,
+		.num_macs = 1024,
 		.num_ports = 6,
 		.num_internal_phys = 5,
 		.max_vid = 4095,
@@ -4329,6 +4359,7 @@
 		.family = MV88E6XXX_FAMILY_6165,
 		.name = "Marvell 88E6165",
 		.num_databases = 4096,
+		.num_macs = 8192,
 		.num_ports = 6,
 		.num_internal_phys = 0,
 		.max_vid = 4095,
@@ -4352,6 +4383,7 @@
 		.family = MV88E6XXX_FAMILY_6351,
 		.name = "Marvell 88E6171",
 		.num_databases = 4096,
+		.num_macs = 8192,
 		.num_ports = 7,
 		.num_internal_phys = 5,
 		.max_vid = 4095,
@@ -4374,6 +4406,7 @@
 		.family = MV88E6XXX_FAMILY_6352,
 		.name = "Marvell 88E6172",
 		.num_databases = 4096,
+		.num_macs = 8192,
 		.num_ports = 7,
 		.num_internal_phys = 5,
 		.num_gpio = 15,
@@ -4397,6 +4430,7 @@
 		.family = MV88E6XXX_FAMILY_6351,
 		.name = "Marvell 88E6175",
 		.num_databases = 4096,
+		.num_macs = 8192,
 		.num_ports = 7,
 		.num_internal_phys = 5,
 		.max_vid = 4095,
@@ -4419,6 +4453,7 @@
 		.family = MV88E6XXX_FAMILY_6352,
 		.name = "Marvell 88E6176",
 		.num_databases = 4096,
+		.num_macs = 8192,
 		.num_ports = 7,
 		.num_internal_phys = 5,
 		.num_gpio = 15,
@@ -4442,6 +4477,7 @@
 		.family = MV88E6XXX_FAMILY_6185,
 		.name = "Marvell 88E6185",
 		.num_databases = 256,
+		.num_macs = 8192,
 		.num_ports = 10,
 		.num_internal_phys = 0,
 		.max_vid = 4095,
@@ -4462,6 +4498,7 @@
 		.family = MV88E6XXX_FAMILY_6390,
 		.name = "Marvell 88E6190",
 		.num_databases = 4096,
+		.num_macs = 16384,
 		.num_ports = 11,	/* 10 + Z80 */
 		.num_internal_phys = 9,
 		.num_gpio = 16,
@@ -4485,6 +4522,7 @@
 		.family = MV88E6XXX_FAMILY_6390,
 		.name = "Marvell 88E6190X",
 		.num_databases = 4096,
+		.num_macs = 16384,
 		.num_ports = 11,	/* 10 + Z80 */
 		.num_internal_phys = 9,
 		.num_gpio = 16,
@@ -4508,6 +4546,7 @@
 		.family = MV88E6XXX_FAMILY_6390,
 		.name = "Marvell 88E6191",
 		.num_databases = 4096,
+		.num_macs = 16384,
 		.num_ports = 11,	/* 10 + Z80 */
 		.num_internal_phys = 9,
 		.max_vid = 8191,
@@ -4558,6 +4597,7 @@
 		.family = MV88E6XXX_FAMILY_6352,
 		.name = "Marvell 88E6240",
 		.num_databases = 4096,
+		.num_macs = 8192,
 		.num_ports = 7,
 		.num_internal_phys = 5,
 		.num_gpio = 15,
@@ -4628,6 +4668,7 @@
 		.family = MV88E6XXX_FAMILY_6320,
 		.name = "Marvell 88E6320",
 		.num_databases = 4096,
+		.num_macs = 8192,
 		.num_ports = 7,
 		.num_internal_phys = 5,
 		.num_gpio = 15,
@@ -4652,6 +4693,7 @@
 		.family = MV88E6XXX_FAMILY_6320,
 		.name = "Marvell 88E6321",
 		.num_databases = 4096,
+		.num_macs = 8192,
 		.num_ports = 7,
 		.num_internal_phys = 5,
 		.num_gpio = 15,
@@ -4674,7 +4716,8 @@
 		.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6341,
 		.family = MV88E6XXX_FAMILY_6341,
 		.name = "Marvell 88E6341",
-		.num_databases = 4096,
+		.num_databases = 256,
+		.num_macs = 2048,
 		.num_internal_phys = 5,
 		.num_ports = 6,
 		.num_gpio = 11,
@@ -4699,6 +4742,7 @@
 		.family = MV88E6XXX_FAMILY_6351,
 		.name = "Marvell 88E6350",
 		.num_databases = 4096,
+		.num_macs = 8192,
 		.num_ports = 7,
 		.num_internal_phys = 5,
 		.max_vid = 4095,
@@ -4721,6 +4765,7 @@
 		.family = MV88E6XXX_FAMILY_6351,
 		.name = "Marvell 88E6351",
 		.num_databases = 4096,
+		.num_macs = 8192,
 		.num_ports = 7,
 		.num_internal_phys = 5,
 		.max_vid = 4095,
@@ -4743,6 +4788,7 @@
 		.family = MV88E6XXX_FAMILY_6352,
 		.name = "Marvell 88E6352",
 		.num_databases = 4096,
+		.num_macs = 8192,
 		.num_ports = 7,
 		.num_internal_phys = 5,
 		.num_gpio = 15,
@@ -4766,6 +4812,7 @@
 		.family = MV88E6XXX_FAMILY_6390,
 		.name = "Marvell 88E6390",
 		.num_databases = 4096,
+		.num_macs = 16384,
 		.num_ports = 11,	/* 10 + Z80 */
 		.num_internal_phys = 9,
 		.num_gpio = 16,
@@ -4789,6 +4836,7 @@
 		.family = MV88E6XXX_FAMILY_6390,
 		.name = "Marvell 88E6390X",
 		.num_databases = 4096,
+		.num_macs = 16384,
 		.num_ports = 11,	/* 10 + Z80 */
 		.num_internal_phys = 9,
 		.num_gpio = 16,
@@ -5083,7 +5131,7 @@
 		goto out;
 	}
 	if (chip->reset)
-		usleep_range(1000, 2000);
+		usleep_range(10000, 20000);
 
 	err = mv88e6xxx_detect(chip);
 	if (err)
@@ -5103,13 +5151,13 @@
 	err = mv88e6xxx_switch_reset(chip);
 	mv88e6xxx_reg_unlock(chip);
 	if (err)
-		goto out;
+		goto out_phy;
 
 	if (np) {
 		chip->irq = of_irq_get(np, 0);
 		if (chip->irq == -EPROBE_DEFER) {
 			err = chip->irq;
-			goto out;
+			goto out_phy;
 		}
 	}
 
@@ -5128,7 +5176,7 @@
 	mv88e6xxx_reg_unlock(chip);
 
 	if (err)
-		goto out;
+		goto out_phy;
 
 	if (chip->info->g2_irqs > 0) {
 		err = mv88e6xxx_g2_irq_setup(chip);
@@ -5168,6 +5216,8 @@
 		mv88e6xxx_g1_irq_free(chip);
 	else
 		mv88e6xxx_irq_poll_free(chip);
+out_phy:
+	mv88e6xxx_phy_destroy(chip);
 out:
 	if (pdata)
 		dev_put(pdata->netdev);
@@ -5185,7 +5235,6 @@
 		mv88e6xxx_ptp_free(chip);
 	}
 
-	mv88e6xxx_phy_destroy(chip);
 	mv88e6xxx_unregister_switch(chip);
 	mv88e6xxx_mdios_unregister(chip);
 
@@ -5199,6 +5248,8 @@
 		mv88e6xxx_g1_irq_free(chip);
 	else
 		mv88e6xxx_irq_poll_free(chip);
+
+	mv88e6xxx_phy_destroy(chip);
 }
 
 static const struct of_device_id mv88e6xxx_of_match[] = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/mv88e6xxx/chip.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/mv88e6xxx/chip.h
@@ -94,6 +94,7 @@
 	u16 prod_num;
 	const char *name;
 	unsigned int num_databases;
+	unsigned int num_macs;
 	unsigned int num_ports;
 	unsigned int num_internal_phys;
 	unsigned int num_gpio;
@@ -609,6 +610,11 @@
 	return chip->info->num_databases;
 }
 
+static inline unsigned int mv88e6xxx_num_macs(struct  mv88e6xxx_chip *chip)
+{
+	return chip->info->num_macs;
+}
+
 static inline unsigned int mv88e6xxx_num_ports(struct mv88e6xxx_chip *chip)
 {
 	return chip->info->num_ports;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/mv88e6xxx/global1.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/mv88e6xxx/global1.c
@@ -332,6 +332,11 @@
 {
 	u16 ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_CPU_DEST;
 
+	/* Use the default high priority for management frames sent to
+	 * the CPU.
+	 */
+	port |= MV88E6390_G1_MONITOR_MGMT_CTL_PTR_CPU_DEST_MGMTPRI;
+
 	return mv88e6390_g1_monitor_write(chip, ptr, port);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/mv88e6xxx/global1.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/mv88e6xxx/global1.h
@@ -210,6 +210,7 @@
 #define MV88E6390_G1_MONITOR_MGMT_CTL_PTR_INGRESS_DEST		0x2000
 #define MV88E6390_G1_MONITOR_MGMT_CTL_PTR_EGRESS_DEST		0x2100
 #define MV88E6390_G1_MONITOR_MGMT_CTL_PTR_CPU_DEST		0x3000
+#define MV88E6390_G1_MONITOR_MGMT_CTL_PTR_CPU_DEST_MGMTPRI	0x00e0
 #define MV88E6390_G1_MONITOR_MGMT_CTL_DATA_MASK			0x00ff
 
 /* Offset 0x1C: Global Control 2 */
@@ -338,5 +339,6 @@
 int mv88e6xxx_g1_vtu_flush(struct mv88e6xxx_chip *chip);
 int mv88e6xxx_g1_vtu_prob_irq_setup(struct mv88e6xxx_chip *chip);
 void mv88e6xxx_g1_vtu_prob_irq_free(struct mv88e6xxx_chip *chip);
+int mv88e6xxx_g1_atu_get_next(struct mv88e6xxx_chip *chip, u16 fid);
 
 #endif /* _MV88E6XXX_GLOBAL1_H */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/mv88e6xxx/global1_atu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/mv88e6xxx/global1_atu.c
@@ -12,6 +12,7 @@
 
 #include "chip.h"
 #include "global1.h"
+#include "trace.h"
 
 /* Offset 0x01: ATU FID Register */
 
@@ -82,6 +83,19 @@
 	return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_ATU_OP, bit, 0);
 }
 
+static int mv88e6xxx_g1_read_atu_violation(struct mv88e6xxx_chip *chip)
+{
+	int err;
+
+	err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_ATU_OP,
+				 MV88E6XXX_G1_ATU_OP_BUSY |
+				 MV88E6XXX_G1_ATU_OP_GET_CLR_VIOLATION);
+	if (err)
+		return err;
+
+	return mv88e6xxx_g1_atu_op_wait(chip);
+}
+
 static int mv88e6xxx_g1_atu_op(struct mv88e6xxx_chip *chip, u16 fid, u16 op)
 {
 	u16 val;
@@ -122,6 +136,46 @@
 	return mv88e6xxx_g1_atu_op_wait(chip);
 }
 
+int mv88e6xxx_g1_atu_get_next(struct mv88e6xxx_chip *chip, u16 fid)
+{
+	return mv88e6xxx_g1_atu_op(chip, fid, MV88E6XXX_G1_ATU_OP_GET_NEXT_DB);
+}
+
+static int mv88e6xxx_g1_atu_fid_read(struct mv88e6xxx_chip *chip, u16 *fid)
+{
+	u16 val = 0, upper = 0, op = 0;
+	int err = -EOPNOTSUPP;
+
+	if (mv88e6xxx_num_databases(chip) > 256) {
+		err = mv88e6xxx_g1_read(chip, MV88E6352_G1_ATU_FID, &val);
+		val &= 0xfff;
+		if (err)
+			return err;
+	} else {
+		err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_ATU_OP, &op);
+		if (err)
+			return err;
+		if (mv88e6xxx_num_databases(chip) > 64) {
+			/* ATU DBNum[7:4] are located in ATU Control 15:12 */
+			err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_ATU_CTL,
+						&upper);
+			if (err)
+				return err;
+
+			upper = (upper >> 8) & 0x00f0;
+		} else if (mv88e6xxx_num_databases(chip) > 16) {
+			/* ATU DBNum[5:4] are located in ATU Operation 9:8 */
+			upper = (op >> 4) & 0x30;
+		}
+
+		/* ATU DBNum[3:0] are located in ATU Operation 3:0 */
+		val = (op & 0xf) | upper;
+	}
+	*fid = val;
+
+	return err;
+}
+
 /* Offset 0x0C: ATU Data Register */
 
 static int mv88e6xxx_g1_atu_data_read(struct mv88e6xxx_chip *chip,
@@ -316,14 +370,12 @@
 {
 	struct mv88e6xxx_chip *chip = dev_id;
 	struct mv88e6xxx_atu_entry entry;
-	int spid;
-	int err;
-	u16 val;
+	int err, spid;
+	u16 val, fid;
 
 	mv88e6xxx_reg_lock(chip);
 
-	err = mv88e6xxx_g1_atu_op(chip, 0,
-				  MV88E6XXX_G1_ATU_OP_GET_CLR_VIOLATION);
+	err = mv88e6xxx_g1_read_atu_violation(chip);
 	if (err)
 		goto out;
 
@@ -331,6 +383,10 @@
 	if (err)
 		goto out;
 
+	err = mv88e6xxx_g1_atu_fid_read(chip, &fid);
+	if (err)
+		goto out;
+
 	err = mv88e6xxx_g1_atu_data_read(chip, &entry);
 	if (err)
 		goto out;
@@ -348,24 +404,25 @@
 	}
 
 	if (val & MV88E6XXX_G1_ATU_OP_MEMBER_VIOLATION) {
-		dev_err_ratelimited(chip->dev,
-				    "ATU member violation for %pM portvec %x spid %d\n",
-				    entry.mac, entry.portvec, spid);
+		trace_mv88e6xxx_atu_member_violation(chip->dev, spid,
+						     entry.portvec, entry.mac,
+						     fid);
 		chip->ports[spid].atu_member_violation++;
 	}
 
 	if (val & MV88E6XXX_G1_ATU_OP_MISS_VIOLATION) {
-		dev_err_ratelimited(chip->dev,
-				    "ATU miss violation for %pM portvec %x spid %d\n",
-				    entry.mac, entry.portvec, spid);
+		trace_mv88e6xxx_atu_miss_violation(chip->dev, spid,
+						   entry.portvec, entry.mac,
+						   fid);
 		chip->ports[spid].atu_miss_violation++;
 	}
 
 	if (val & MV88E6XXX_G1_ATU_OP_FULL_VIOLATION) {
-		dev_err_ratelimited(chip->dev,
-				    "ATU full violation for %pM portvec %x spid %d\n",
-				    entry.mac, entry.portvec, spid);
-		chip->ports[spid].atu_full_violation++;
+		trace_mv88e6xxx_atu_full_violation(chip->dev, spid,
+						   entry.portvec, entry.mac,
+						   fid);
+		if (spid < ARRAY_SIZE(chip->ports))
+			chip->ports[spid].atu_full_violation++;
 	}
 	mv88e6xxx_reg_unlock(chip);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/mv88e6xxx/global1_vtu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/mv88e6xxx/global1_vtu.c
@@ -125,11 +125,9 @@
  * Offset 0x08: VTU/STU Data Register 2
  * Offset 0x09: VTU/STU Data Register 3
  */
-
-static int mv88e6185_g1_vtu_data_read(struct mv88e6xxx_chip *chip,
-				      struct mv88e6xxx_vtu_entry *entry)
+static int mv88e6185_g1_vtu_stu_data_read(struct mv88e6xxx_chip *chip,
+					  u16 *regs)
 {
-	u16 regs[3];
 	int i;
 
 	/* Read all 3 VTU/STU Data registers */
@@ -142,12 +140,45 @@
 			return err;
 	}
 
-	/* Extract MemberTag and PortState data */
+	return 0;
+}
+
+static int mv88e6185_g1_vtu_data_read(struct mv88e6xxx_chip *chip,
+				      struct mv88e6xxx_vtu_entry *entry)
+{
+	u16 regs[3];
+	int err;
+	int i;
+
+	err = mv88e6185_g1_vtu_stu_data_read(chip, regs);
+	if (err)
+		return err;
+
+	/* Extract MemberTag data */
 	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
 		unsigned int member_offset = (i % 4) * 4;
-		unsigned int state_offset = member_offset + 2;
 
 		entry->member[i] = (regs[i / 4] >> member_offset) & 0x3;
+	}
+
+	return 0;
+}
+
+static int mv88e6185_g1_stu_data_read(struct mv88e6xxx_chip *chip,
+				      struct mv88e6xxx_vtu_entry *entry)
+{
+	u16 regs[3];
+	int err;
+	int i;
+
+	err = mv88e6185_g1_vtu_stu_data_read(chip, regs);
+	if (err)
+		return err;
+
+	/* Extract PortState data */
+	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
+		unsigned int state_offset = (i % 4) * 4 + 2;
+
 		entry->state[i] = (regs[i / 4] >> state_offset) & 0x3;
 	}
 
@@ -320,6 +351,10 @@
 		if (err)
 			return err;
 
+		err = mv88e6185_g1_stu_data_read(chip, entry);
+		if (err)
+			return err;
+
 		/* VTU DBNum[3:0] are located in VTU Operation 3:0
 		 * VTU DBNum[5:4] are located in VTU Operation 9:8
 		 */
@@ -349,6 +384,10 @@
 		if (err)
 			return err;
 
+		err = mv88e6185_g1_stu_data_read(chip, entry);
+		if (err)
+			return err;
+
 		/* VTU DBNum[3:0] are located in VTU Operation 3:0
 		 * VTU DBNum[7:4] are located in VTU Operation 11:8
 		 */
@@ -374,16 +413,20 @@
 		return err;
 
 	if (entry->valid) {
-		/* Fetch (and mask) VLAN PortState data from the STU */
-		err = mv88e6xxx_g1_vtu_stu_get(chip, entry);
+		err = mv88e6185_g1_vtu_data_read(chip, entry);
 		if (err)
 			return err;
 
-		err = mv88e6185_g1_vtu_data_read(chip, entry);
+		err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
 		if (err)
 			return err;
 
-		err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
+		/* Fetch VLAN PortState data from the STU */
+		err = mv88e6xxx_g1_vtu_stu_get(chip, entry);
+		if (err)
+			return err;
+
+		err = mv88e6185_g1_stu_data_read(chip, entry);
 		if (err)
 			return err;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/mv88e6xxx/global2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/mv88e6xxx/global2.c
@@ -280,6 +280,19 @@
 	return err;
 }
 
+/* Offset 0x0E: ATU Statistics */
+
+int mv88e6xxx_g2_atu_stats_set(struct mv88e6xxx_chip *chip, u16 kind, u16 bin)
+{
+	return mv88e6xxx_g2_write(chip, MV88E6XXX_G2_ATU_STATS,
+				  kind | bin);
+}
+
+int mv88e6xxx_g2_atu_stats_get(struct mv88e6xxx_chip *chip, u16 *stats)
+{
+	return mv88e6xxx_g2_read(chip, MV88E6XXX_G2_ATU_STATS, stats);
+}
+
 /* Offset 0x0F: Priority Override Table */
 
 static int mv88e6xxx_g2_pot_write(struct mv88e6xxx_chip *chip, int pointer,
@@ -310,7 +323,7 @@
  * Offset 0x15: EEPROM Addr (for 8-bit data access)
  */
 
-static int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip)
+int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip)
 {
 	int bit = __bf_shf(MV88E6XXX_G2_EEPROM_CMD_BUSY);
 	int err;
@@ -1083,6 +1096,13 @@
 {
 	int err, irq, virq;
 
+	chip->g2_irq.masked = ~0;
+	mv88e6xxx_reg_lock(chip);
+	err = mv88e6xxx_g2_int_mask(chip, ~chip->g2_irq.masked);
+	mv88e6xxx_reg_unlock(chip);
+	if (err)
+		return err;
+
 	chip->g2_irq.domain = irq_domain_add_simple(
 		chip->dev->of_node, 16, 0, &mv88e6xxx_g2_irq_domain_ops, chip);
 	if (!chip->g2_irq.domain)
@@ -1092,7 +1112,6 @@
 		irq_create_mapping(chip->g2_irq.domain, irq);
 
 	chip->g2_irq.chip = mv88e6xxx_g2_irq_chip;
-	chip->g2_irq.masked = ~0;
 
 	chip->device_irq = irq_find_mapping(chip->g1_irq.domain,
 					    MV88E6XXX_G1_STS_IRQ_DEVICE);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/mv88e6xxx/global2.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/mv88e6xxx/global2.h
@@ -113,7 +113,16 @@
 #define MV88E6XXX_G2_SWITCH_MAC_DATA_MASK	0x00ff
 
 /* Offset 0x0E: ATU Stats Register */
-#define MV88E6XXX_G2_ATU_STATS		0x0e
+#define MV88E6XXX_G2_ATU_STATS				0x0e
+#define MV88E6XXX_G2_ATU_STATS_BIN_0			(0x0 << 14)
+#define MV88E6XXX_G2_ATU_STATS_BIN_1			(0x1 << 14)
+#define MV88E6XXX_G2_ATU_STATS_BIN_2			(0x2 << 14)
+#define MV88E6XXX_G2_ATU_STATS_BIN_3			(0x3 << 14)
+#define MV88E6XXX_G2_ATU_STATS_MODE_ALL			(0x0 << 12)
+#define MV88E6XXX_G2_ATU_STATS_MODE_ALL_DYNAMIC		(0x1 << 12)
+#define MV88E6XXX_G2_ATU_STATS_MODE_FID_ALL		(0x2 << 12)
+#define MV88E6XXX_G2_ATU_STATS_MODE_FID_ALL_DYNAMIC	(0x3 << 12)
+#define MV88E6XXX_G2_ATU_STATS_MASK			0x0fff
 
 /* Offset 0x0F: Priority Override Table */
 #define MV88E6XXX_G2_PRIO_OVERRIDE		0x0f
@@ -340,6 +349,7 @@
 
 int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip, int target,
 				      int port);
+int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip);
 
 extern const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops;
 extern const struct mv88e6xxx_irq_ops mv88e6250_watchdog_ops;
@@ -353,6 +363,8 @@
 
 int mv88e6xxx_g2_scratch_gpio_set_smi(struct mv88e6xxx_chip *chip,
 				      bool external);
+int mv88e6xxx_g2_atu_stats_set(struct mv88e6xxx_chip *chip, u16 kind, u16 bin);
+int mv88e6xxx_g2_atu_stats_get(struct mv88e6xxx_chip *chip, u16 *stats);
 
 #else /* !CONFIG_NET_DSA_MV88E6XXX_GLOBAL2 */
 
@@ -514,6 +526,18 @@
 {
 	return -EOPNOTSUPP;
 }
+
+static inline int mv88e6xxx_g2_atu_stats_set(struct mv88e6xxx_chip *chip,
+					     u16 kind, u16 bin)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline int mv88e6xxx_g2_atu_stats_get(struct mv88e6xxx_chip *chip,
+					     u16 *stats)
+{
+	return -EOPNOTSUPP;
+}
 
 #endif /* CONFIG_NET_DSA_MV88E6XXX_GLOBAL2 */
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/mv88e6xxx/phy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/mv88e6xxx/phy.c
@@ -197,7 +197,10 @@
 
 static void mv88e6xxx_phy_ppu_state_destroy(struct mv88e6xxx_chip *chip)
 {
+	mutex_lock(&chip->ppu_mutex);
 	del_timer_sync(&chip->ppu_timer);
+	cancel_work_sync(&chip->ppu_work);
+	mutex_unlock(&chip->ppu_mutex);
 }
 
 int mv88e6185_phy_ppu_read(struct mv88e6xxx_chip *chip, struct mii_bus *bus,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/mv88e6xxx/port.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/mv88e6xxx/port.c
@@ -393,7 +393,7 @@
 }
 
 static int mv88e6xxx_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
-				    phy_interface_t mode)
+				    phy_interface_t mode, bool force)
 {
 	u8 lane;
 	u16 cmode;
@@ -427,8 +427,8 @@
 		cmode = 0;
 	}
 
-	/* cmode doesn't change, nothing to do for us */
-	if (cmode == chip->ports[port].cmode)
+	/* cmode doesn't change, nothing to do for us unless forced */
+	if (cmode == chip->ports[port].cmode && !force)
 		return 0;
 
 	lane = mv88e6xxx_serdes_get_lane(chip, port);
@@ -484,7 +484,7 @@
 	if (port != 9 && port != 10)
 		return -EOPNOTSUPP;
 
-	return mv88e6xxx_port_set_cmode(chip, port, mode);
+	return mv88e6xxx_port_set_cmode(chip, port, mode, false);
 }
 
 int mv88e6390_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
@@ -504,7 +504,7 @@
 		break;
 	}
 
-	return mv88e6xxx_port_set_cmode(chip, port, mode);
+	return mv88e6xxx_port_set_cmode(chip, port, mode, false);
 }
 
 static int mv88e6341_port_set_cmode_writable(struct mv88e6xxx_chip *chip,
@@ -555,7 +555,7 @@
 	if (err)
 		return err;
 
-	return mv88e6xxx_port_set_cmode(chip, port, mode);
+	return mv88e6xxx_port_set_cmode(chip, port, mode, true);
 }
 
 int mv88e6185_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/mv88e6xxx/trace.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/mv88e6xxx/trace.c
@@ -0,0 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Copyright 2022 NXP
+ */
+
+#define CREATE_TRACE_POINTS
+#include "trace.h"
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/mv88e6xxx/trace.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/mv88e6xxx/trace.h
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* Copyright 2022 NXP
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM	mv88e6xxx
+
+#if !defined(_MV88E6XXX_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _MV88E6XXX_TRACE_H
+
+#include <linux/device.h>
+#include <linux/if_ether.h>
+#include <linux/tracepoint.h>
+
+DECLARE_EVENT_CLASS(mv88e6xxx_atu_violation,
+
+	TP_PROTO(const struct device *dev, int spid, u16 portvec,
+		 const unsigned char *addr, u16 fid),
+
+	TP_ARGS(dev, spid, portvec, addr, fid),
+
+	TP_STRUCT__entry(
+		__string(name, dev_name(dev))
+		__field(int, spid)
+		__field(u16, portvec)
+		__array(unsigned char, addr, ETH_ALEN)
+		__field(u16, fid)
+	),
+
+	TP_fast_assign(
+		__assign_str(name, dev_name(dev));
+		__entry->spid = spid;
+		__entry->portvec = portvec;
+		memcpy(__entry->addr, addr, ETH_ALEN);
+		__entry->fid = fid;
+	),
+
+	TP_printk("dev %s spid %d portvec 0x%x addr %pM fid %u",
+		  __get_str(name), __entry->spid, __entry->portvec,
+		  __entry->addr, __entry->fid)
+);
+
+DEFINE_EVENT(mv88e6xxx_atu_violation, mv88e6xxx_atu_member_violation,
+	     TP_PROTO(const struct device *dev, int spid, u16 portvec,
+		      const unsigned char *addr, u16 fid),
+	     TP_ARGS(dev, spid, portvec, addr, fid));
+
+DEFINE_EVENT(mv88e6xxx_atu_violation, mv88e6xxx_atu_miss_violation,
+	     TP_PROTO(const struct device *dev, int spid, u16 portvec,
+		      const unsigned char *addr, u16 fid),
+	     TP_ARGS(dev, spid, portvec, addr, fid));
+
+DEFINE_EVENT(mv88e6xxx_atu_violation, mv88e6xxx_atu_full_violation,
+	     TP_PROTO(const struct device *dev, int spid, u16 portvec,
+		      const unsigned char *addr, u16 fid),
+	     TP_ARGS(dev, spid, portvec, addr, fid));
+
+#endif /* _MV88E6XXX_TRACE_H */
+
+/* We don't want to use include/trace/events */
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE	trace
+/* This part must be outside protection */
+#include <trace/define_trace.h>
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/realtek-smi-core.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/realtek-smi-core.h
@@ -25,6 +25,9 @@
 	const char	*name;
 };
 
+/**
+ * struct rtl8366_vlan_mc - Virtual LAN member configuration
+ */
 struct rtl8366_vlan_mc {
 	u16	vid;
 	u16	untag;
@@ -119,7 +122,6 @@
 int rtl8366_mc_is_used(struct realtek_smi *smi, int mc_index, int *used);
 int rtl8366_set_vlan(struct realtek_smi *smi, int vid, u32 member,
 		     u32 untag, u32 fid);
-int rtl8366_get_pvid(struct realtek_smi *smi, int port, int *val);
 int rtl8366_set_pvid(struct realtek_smi *smi, unsigned int port,
 		     unsigned int vid);
 int rtl8366_enable_vlan4k(struct realtek_smi *smi, bool enable);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/rtl8366.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/rtl8366.c
@@ -36,113 +36,66 @@
 }
 EXPORT_SYMBOL_GPL(rtl8366_mc_is_used);
 
-int rtl8366_set_vlan(struct realtek_smi *smi, int vid, u32 member,
-		     u32 untag, u32 fid)
+/**
+ * rtl8366_obtain_mc() - retrieve or allocate a VLAN member configuration
+ * @smi: the Realtek SMI device instance
+ * @vid: the VLAN ID to look up or allocate
+ * @vlanmc: the pointer will be assigned to a pointer to a valid member config
+ * if successful
+ * @return: index of a new member config or negative error number
+ */
+static int rtl8366_obtain_mc(struct realtek_smi *smi, int vid,
+			     struct rtl8366_vlan_mc *vlanmc)
 {
 	struct rtl8366_vlan_4k vlan4k;
 	int ret;
 	int i;
 
-	/* Update the 4K table */
-	ret = smi->ops->get_vlan_4k(smi, vid, &vlan4k);
-	if (ret)
-		return ret;
-
-	vlan4k.member = member;
-	vlan4k.untag = untag;
-	vlan4k.fid = fid;
-	ret = smi->ops->set_vlan_4k(smi, &vlan4k);
-	if (ret)
-		return ret;
-
-	/* Try to find an existing MC entry for this VID */
+	/* Try to find an existing member config entry for this VID */
 	for (i = 0; i < smi->num_vlan_mc; i++) {
-		struct rtl8366_vlan_mc vlanmc;
-
-		ret = smi->ops->get_vlan_mc(smi, i, &vlanmc);
-		if (ret)
+		ret = smi->ops->get_vlan_mc(smi, i, vlanmc);
+		if (ret) {
+			dev_err(smi->dev, "error searching for VLAN MC %d for VID %d\n",
+				i, vid);
 			return ret;
-
-		if (vid == vlanmc.vid) {
-			/* update the MC entry */
-			vlanmc.member = member;
-			vlanmc.untag = untag;
-			vlanmc.fid = fid;
-
-			ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
-			break;
 		}
-	}
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(rtl8366_set_vlan);
 
-int rtl8366_get_pvid(struct realtek_smi *smi, int port, int *val)
-{
-	struct rtl8366_vlan_mc vlanmc;
-	int ret;
-	int index;
-
-	ret = smi->ops->get_mc_index(smi, port, &index);
-	if (ret)
-		return ret;
-
-	ret = smi->ops->get_vlan_mc(smi, index, &vlanmc);
-	if (ret)
-		return ret;
-
-	*val = vlanmc.vid;
-	return 0;
-}
-EXPORT_SYMBOL_GPL(rtl8366_get_pvid);
-
-int rtl8366_set_pvid(struct realtek_smi *smi, unsigned int port,
-		     unsigned int vid)
-{
-	struct rtl8366_vlan_mc vlanmc;
-	struct rtl8366_vlan_4k vlan4k;
-	int ret;
-	int i;
-
-	/* Try to find an existing MC entry for this VID */
-	for (i = 0; i < smi->num_vlan_mc; i++) {
-		ret = smi->ops->get_vlan_mc(smi, i, &vlanmc);
-		if (ret)
-			return ret;
-
-		if (vid == vlanmc.vid) {
-			ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
-			if (ret)
-				return ret;
-
-			ret = smi->ops->set_mc_index(smi, port, i);
-			return ret;
-		}
+		if (vid == vlanmc->vid)
+			return i;
 	}
 
 	/* We have no MC entry for this VID, try to find an empty one */
 	for (i = 0; i < smi->num_vlan_mc; i++) {
-		ret = smi->ops->get_vlan_mc(smi, i, &vlanmc);
-		if (ret)
+		ret = smi->ops->get_vlan_mc(smi, i, vlanmc);
+		if (ret) {
+			dev_err(smi->dev, "error searching for VLAN MC %d for VID %d\n",
+				i, vid);
 			return ret;
+		}
 
-		if (vlanmc.vid == 0 && vlanmc.member == 0) {
+		if (vlanmc->vid == 0 && vlanmc->member == 0) {
 			/* Update the entry from the 4K table */
 			ret = smi->ops->get_vlan_4k(smi, vid, &vlan4k);
-			if (ret)
+			if (ret) {
+				dev_err(smi->dev, "error looking for 4K VLAN MC %d for VID %d\n",
+					i, vid);
 				return ret;
+			}
 
-			vlanmc.vid = vid;
-			vlanmc.member = vlan4k.member;
-			vlanmc.untag = vlan4k.untag;
-			vlanmc.fid = vlan4k.fid;
-			ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
-			if (ret)
+			vlanmc->vid = vid;
+			vlanmc->member = vlan4k.member;
+			vlanmc->untag = vlan4k.untag;
+			vlanmc->fid = vlan4k.fid;
+			ret = smi->ops->set_vlan_mc(smi, i, vlanmc);
+			if (ret) {
+				dev_err(smi->dev, "unable to set/update VLAN MC %d for VID %d\n",
+					i, vid);
 				return ret;
+			}
 
-			ret = smi->ops->set_mc_index(smi, port, i);
-			return ret;
+			dev_dbg(smi->dev, "created new MC at index %d for VID %d\n",
+				i, vid);
+			return i;
 		}
 	}
 
@@ -160,24 +113,110 @@
 			if (ret)
 				return ret;
 
-			vlanmc.vid = vid;
-			vlanmc.member = vlan4k.member;
-			vlanmc.untag = vlan4k.untag;
-			vlanmc.fid = vlan4k.fid;
-			ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
-			if (ret)
+			vlanmc->vid = vid;
+			vlanmc->member = vlan4k.member;
+			vlanmc->untag = vlan4k.untag;
+			vlanmc->fid = vlan4k.fid;
+			ret = smi->ops->set_vlan_mc(smi, i, vlanmc);
+			if (ret) {
+				dev_err(smi->dev, "unable to set/update VLAN MC %d for VID %d\n",
+					i, vid);
 				return ret;
-
-			ret = smi->ops->set_mc_index(smi, port, i);
-			return ret;
+			}
+			dev_dbg(smi->dev, "recycled MC at index %i for VID %d\n",
+				i, vid);
+			return i;
 		}
 	}
 
-	dev_err(smi->dev,
-		"all VLAN member configurations are in use\n");
-
+	dev_err(smi->dev, "all VLAN member configurations are in use\n");
 	return -ENOSPC;
 }
+
+int rtl8366_set_vlan(struct realtek_smi *smi, int vid, u32 member,
+		     u32 untag, u32 fid)
+{
+	struct rtl8366_vlan_mc vlanmc;
+	struct rtl8366_vlan_4k vlan4k;
+	int mc;
+	int ret;
+
+	if (!smi->ops->is_vlan_valid(smi, vid))
+		return -EINVAL;
+
+	dev_dbg(smi->dev,
+		"setting VLAN%d 4k members: 0x%02x, untagged: 0x%02x\n",
+		vid, member, untag);
+
+	/* Update the 4K table */
+	ret = smi->ops->get_vlan_4k(smi, vid, &vlan4k);
+	if (ret)
+		return ret;
+
+	vlan4k.member |= member;
+	vlan4k.untag |= untag;
+	vlan4k.fid = fid;
+	ret = smi->ops->set_vlan_4k(smi, &vlan4k);
+	if (ret)
+		return ret;
+
+	dev_dbg(smi->dev,
+		"resulting VLAN%d 4k members: 0x%02x, untagged: 0x%02x\n",
+		vid, vlan4k.member, vlan4k.untag);
+
+	/* Find or allocate a member config for this VID */
+	ret = rtl8366_obtain_mc(smi, vid, &vlanmc);
+	if (ret < 0)
+		return ret;
+	mc = ret;
+
+	/* Update the MC entry */
+	vlanmc.member |= member;
+	vlanmc.untag |= untag;
+	vlanmc.fid = fid;
+
+	/* Commit updates to the MC entry */
+	ret = smi->ops->set_vlan_mc(smi, mc, &vlanmc);
+	if (ret)
+		dev_err(smi->dev, "failed to commit changes to VLAN MC index %d for VID %d\n",
+			mc, vid);
+	else
+		dev_dbg(smi->dev,
+			"resulting VLAN%d MC members: 0x%02x, untagged: 0x%02x\n",
+			vid, vlanmc.member, vlanmc.untag);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(rtl8366_set_vlan);
+
+int rtl8366_set_pvid(struct realtek_smi *smi, unsigned int port,
+		     unsigned int vid)
+{
+	struct rtl8366_vlan_mc vlanmc;
+	int mc;
+	int ret;
+
+	if (!smi->ops->is_vlan_valid(smi, vid))
+		return -EINVAL;
+
+	/* Find or allocate a member config for this VID */
+	ret = rtl8366_obtain_mc(smi, vid, &vlanmc);
+	if (ret < 0)
+		return ret;
+	mc = ret;
+
+	ret = smi->ops->set_mc_index(smi, port, mc);
+	if (ret) {
+		dev_err(smi->dev, "set PVID: failed to set MC index %d for port %d\n",
+			mc, port);
+		return ret;
+	}
+
+	dev_dbg(smi->dev, "set PVID: the PVID for port %d set to %d using existing MC index %d\n",
+		port, vid, mc);
+
+	return 0;
+}
 EXPORT_SYMBOL_GPL(rtl8366_set_pvid);
 
 int rtl8366_enable_vlan4k(struct realtek_smi *smi, bool enable)
@@ -376,7 +415,8 @@
 		if (!smi->ops->is_vlan_valid(smi, vid))
 			return;
 
-	dev_info(smi->dev, "add VLAN on port %d, %s, %s\n",
+	dev_info(smi->dev, "add VLAN %d on port %d, %s, %s\n",
+		 vlan->vid_begin,
 		 port,
 		 untagged ? "untagged" : "tagged",
 		 pvid ? " PVID" : "no PVID");
@@ -384,36 +424,31 @@
 	if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port))
 		dev_err(smi->dev, "port is DSA or CPU port\n");
 
-	for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
-		int pvid_val = 0;
-
-		dev_info(smi->dev, "add VLAN %04x\n", vid);
+	for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
 		member |= BIT(port);
 
 		if (untagged)
 			untag |= BIT(port);
 
-		/* To ensure that we have a valid MC entry for this VLAN,
-		 * initialize the port VLAN ID here.
-		 */
-		ret = rtl8366_get_pvid(smi, port, &pvid_val);
-		if (ret < 0) {
-			dev_err(smi->dev, "could not lookup PVID for port %d\n",
-				port);
-			return;
-		}
-		if (pvid_val == 0) {
-			ret = rtl8366_set_pvid(smi, port, vid);
-			if (ret < 0)
-				return;
-		}
-	}
+		ret = rtl8366_set_vlan(smi, vid, member, untag, 0);
+		if (ret)
+			dev_err(smi->dev,
+				"failed to set up VLAN %04x",
+				vid);
 
-	ret = rtl8366_set_vlan(smi, port, member, untag, 0);
-	if (ret)
-		dev_err(smi->dev,
-			"failed to set up VLAN %04x",
-			vid);
+		if (!pvid)
+			continue;
+
+		ret = rtl8366_set_pvid(smi, port, vid);
+		if (ret)
+			dev_err(smi->dev,
+				"failed to set PVID on port %d to VLAN %04x",
+				port, vid);
+
+		if (!ret)
+			dev_dbg(smi->dev, "VLAN add: added VLAN %d with PVID on port %d\n",
+				vid, port);
+	}
 }
 EXPORT_SYMBOL_GPL(rtl8366_vlan_add);
 
@@ -439,13 +474,19 @@
 				return ret;
 
 			if (vid == vlanmc.vid) {
-				/* clear VLAN member configurations */
-				vlanmc.vid = 0;
-				vlanmc.priority = 0;
-				vlanmc.member = 0;
-				vlanmc.untag = 0;
-				vlanmc.fid = 0;
-
+				/* Remove this port from the VLAN */
+				vlanmc.member &= ~BIT(port);
+				vlanmc.untag &= ~BIT(port);
+				/*
+				 * If no ports are members of this VLAN
+				 * anymore then clear the whole member
+				 * config so it can be reused.
+				 */
+				if (!vlanmc.member && vlanmc.untag) {
+					vlanmc.vid = 0;
+					vlanmc.priority = 0;
+					vlanmc.fid = 0;
+				}
 				ret = smi->ops->set_vlan_mc(smi, i, &vlanmc);
 				if (ret) {
 					dev_err(smi->dev,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/rtl8366rb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/rtl8366rb.c
@@ -1264,12 +1264,12 @@
 
 static bool rtl8366rb_is_vlan_valid(struct realtek_smi *smi, unsigned int vlan)
 {
-	unsigned int max = RTL8366RB_NUM_VLANS;
+	unsigned int max = RTL8366RB_NUM_VLANS - 1;
 
 	if (smi->vlan4k_enabled)
 		max = RTL8366RB_NUM_VIDS - 1;
 
-	if (vlan == 0 || vlan >= max)
+	if (vlan == 0 || vlan > max)
 		return false;
 
 	return true;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/sja1105/sja1105_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/sja1105/sja1105_main.c
@@ -178,6 +178,7 @@
 		default:
 			dev_err(dev, "Unsupported PHY mode %s!\n",
 				phy_modes(ports[i].phy_mode));
+			return -EINVAL;
 		}
 
 		mii->phy_mac[i] = ports[i].role;
@@ -594,15 +595,15 @@
 	int i;
 
 	for (i = 0; i < SJA1105_NUM_PORTS; i++) {
-		if (ports->role == XMII_MAC)
+		if (ports[i].role == XMII_MAC)
 			continue;
 
-		if (ports->phy_mode == PHY_INTERFACE_MODE_RGMII_RXID ||
-		    ports->phy_mode == PHY_INTERFACE_MODE_RGMII_ID)
+		if (ports[i].phy_mode == PHY_INTERFACE_MODE_RGMII_RXID ||
+		    ports[i].phy_mode == PHY_INTERFACE_MODE_RGMII_ID)
 			priv->rgmii_rx_delay[i] = true;
 
-		if (ports->phy_mode == PHY_INTERFACE_MODE_RGMII_TXID ||
-		    ports->phy_mode == PHY_INTERFACE_MODE_RGMII_ID)
+		if (ports[i].phy_mode == PHY_INTERFACE_MODE_RGMII_TXID ||
+		    ports[i].phy_mode == PHY_INTERFACE_MODE_RGMII_ID)
 			priv->rgmii_tx_delay[i] = true;
 
 		if ((priv->rgmii_rx_delay[i] || priv->rgmii_tx_delay[i]) &&
@@ -619,7 +620,7 @@
 	struct device *dev = &priv->spidev->dev;
 	struct device_node *child;
 
-	for_each_child_of_node(ports_node, child) {
+	for_each_available_child_of_node(ports_node, child) {
 		struct device_node *phy_node;
 		int phy_mode;
 		u32 index;
@@ -991,10 +992,11 @@
 int sja1105et_fdb_add(struct dsa_switch *ds, int port,
 		      const unsigned char *addr, u16 vid)
 {
-	struct sja1105_l2_lookup_entry l2_lookup = {0};
+	struct sja1105_l2_lookup_entry l2_lookup = {0}, tmp;
 	struct sja1105_private *priv = ds->priv;
 	struct device *dev = ds->dev;
 	int last_unused = -1;
+	int start, end, i;
 	int bin, way, rc;
 
 	bin = sja1105et_fdb_hash(priv, addr, vid);
@@ -1006,7 +1008,7 @@
 		 * mask? If yes, we need to do nothing. If not, we need
 		 * to rewrite the entry by adding this port to it.
 		 */
-		if (l2_lookup.destports & BIT(port))
+		if ((l2_lookup.destports & BIT(port)) && l2_lookup.lockeds)
 			return 0;
 		l2_lookup.destports |= BIT(port);
 	} else {
@@ -1037,6 +1039,7 @@
 						     index, NULL, false);
 		}
 	}
+	l2_lookup.lockeds = true;
 	l2_lookup.index = sja1105et_fdb_index(bin, way);
 
 	rc = sja1105_dynamic_config_write(priv, BLK_IDX_L2_LOOKUP,
@@ -1045,6 +1048,29 @@
 	if (rc < 0)
 		return rc;
 
+	/* Invalidate a dynamically learned entry if that exists */
+	start = sja1105et_fdb_index(bin, 0);
+	end = sja1105et_fdb_index(bin, way);
+
+	for (i = start; i < end; i++) {
+		rc = sja1105_dynamic_config_read(priv, BLK_IDX_L2_LOOKUP,
+						 i, &tmp);
+		if (rc == -ENOENT)
+			continue;
+		if (rc)
+			return rc;
+
+		if (tmp.macaddr != ether_addr_to_u64(addr) || tmp.vlanid != vid)
+			continue;
+
+		rc = sja1105_dynamic_config_write(priv, BLK_IDX_L2_LOOKUP,
+						  i, NULL, false);
+		if (rc)
+			return rc;
+
+		break;
+	}
+
 	return sja1105_static_fdb_change(priv, port, &l2_lookup, true);
 }
 
@@ -1086,7 +1112,7 @@
 int sja1105pqrs_fdb_add(struct dsa_switch *ds, int port,
 			const unsigned char *addr, u16 vid)
 {
-	struct sja1105_l2_lookup_entry l2_lookup = {0};
+	struct sja1105_l2_lookup_entry l2_lookup = {0}, tmp;
 	struct sja1105_private *priv = ds->priv;
 	int rc, i;
 
@@ -1107,10 +1133,10 @@
 	rc = sja1105_dynamic_config_read(priv, BLK_IDX_L2_LOOKUP,
 					 SJA1105_SEARCH, &l2_lookup);
 	if (rc == 0) {
-		/* Found and this port is already in the entry's
+		/* Found a static entry and this port is already in the entry's
 		 * port mask => job done
 		 */
-		if (l2_lookup.destports & BIT(port))
+		if ((l2_lookup.destports & BIT(port)) && l2_lookup.lockeds)
 			return 0;
 		/* l2_lookup.index is populated by the switch in case it
 		 * found something.
@@ -1133,16 +1159,46 @@
 		dev_err(ds->dev, "FDB is full, cannot add entry.\n");
 		return -EINVAL;
 	}
-	l2_lookup.lockeds = true;
 	l2_lookup.index = i;
 
 skip_finding_an_index:
+	l2_lookup.lockeds = true;
+
 	rc = sja1105_dynamic_config_write(priv, BLK_IDX_L2_LOOKUP,
 					  l2_lookup.index, &l2_lookup,
 					  true);
 	if (rc < 0)
 		return rc;
 
+	/* The switch learns dynamic entries and looks up the FDB left to
+	 * right. It is possible that our addition was concurrent with the
+	 * dynamic learning of the same address, so now that the static entry
+	 * has been installed, we are certain that address learning for this
+	 * particular address has been turned off, so the dynamic entry either
+	 * is in the FDB at an index smaller than the static one, or isn't (it
+	 * can also be at a larger index, but in that case it is inactive
+	 * because the static FDB entry will match first, and the dynamic one
+	 * will eventually age out). Search for a dynamically learned address
+	 * prior to our static one and invalidate it.
+	 */
+	tmp = l2_lookup;
+
+	rc = sja1105_dynamic_config_read(priv, BLK_IDX_L2_LOOKUP,
+					 SJA1105_SEARCH, &tmp);
+	if (rc < 0) {
+		dev_err(ds->dev,
+			"port %d failed to read back entry for %pM vid %d: %pe\n",
+			port, addr, vid, ERR_PTR(rc));
+		return rc;
+	}
+
+	if (tmp.index < l2_lookup.index) {
+		rc = sja1105_dynamic_config_write(priv, BLK_IDX_L2_LOOKUP,
+						  tmp.index, NULL, false);
+		if (rc < 0)
+			return rc;
+	}
+
 	return sja1105_static_fdb_change(priv, port, &l2_lookup, true);
 }
 
@@ -1256,7 +1312,9 @@
 		/* We need to hide the dsa_8021q VLANs from the user. */
 		if (!dsa_port_is_vlan_filtering(&ds->ports[port]))
 			l2_lookup.vlanid = 0;
-		cb(macaddr, l2_lookup.vlanid, l2_lookup.lockeds, data);
+		rc = cb(macaddr, l2_lookup.vlanid, l2_lookup.lockeds, data);
+		if (rc)
+			return rc;
 	}
 	return 0;
 }
@@ -1389,6 +1447,8 @@
 	int speed_mbps[SJA1105_NUM_PORTS];
 	int rc, i;
 
+	mutex_lock(&priv->mgmt_lock);
+
 	mac = priv->static_config.tables[BLK_IDX_MAC_CONFIG].entries;
 
 	/* Back up the dynamic link speed changed by sja1105_adjust_port_config
@@ -1420,6 +1480,8 @@
 			goto out;
 	}
 out:
+	mutex_unlock(&priv->mgmt_lock);
+
 	return rc;
 }
 
@@ -1556,8 +1618,8 @@
 
 	if (enabled) {
 		/* Enable VLAN filtering. */
-		tpid  = ETH_P_8021AD;
-		tpid2 = ETH_P_8021Q;
+		tpid  = ETH_P_8021Q;
+		tpid2 = ETH_P_8021AD;
 	} else {
 		/* Disable VLAN filtering. */
 		tpid  = ETH_P_SJA1105;
@@ -1566,9 +1628,9 @@
 
 	table = &priv->static_config.tables[BLK_IDX_GENERAL_PARAMS];
 	general_params = table->entries;
-	/* EtherType used to identify outer tagged (S-tag) VLAN traffic */
-	general_params->tpid = tpid;
 	/* EtherType used to identify inner tagged (C-tag) VLAN traffic */
+	general_params->tpid = tpid;
+	/* EtherType used to identify outer tagged (S-tag) VLAN traffic */
 	general_params->tpid2 = tpid2;
 	/* When VLAN filtering is on, we need to at least be able to
 	 * decode management traffic through the "backup plan".
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/sja1105/sja1105_static_config.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/sja1105/sja1105_static_config.c
@@ -142,6 +142,9 @@
 	return size;
 }
 
+/* TPID and TPID2 are intentionally reversed so that semantic
+ * compatibility with E/T is kept.
+ */
 static size_t
 sja1105pqrs_general_params_entry_packing(void *buf, void *entry_ptr,
 					 enum packing_op op)
@@ -166,9 +169,9 @@
 	sja1105_packing(buf, &entry->mirr_port,   141, 139, size, op);
 	sja1105_packing(buf, &entry->vlmarker,    138, 107, size, op);
 	sja1105_packing(buf, &entry->vlmask,      106,  75, size, op);
-	sja1105_packing(buf, &entry->tpid,         74,  59, size, op);
+	sja1105_packing(buf, &entry->tpid2,        74,  59, size, op);
 	sja1105_packing(buf, &entry->ignore2stf,   58,  58, size, op);
-	sja1105_packing(buf, &entry->tpid2,        57,  42, size, op);
+	sja1105_packing(buf, &entry->tpid,         57,  42, size, op);
 	sja1105_packing(buf, &entry->queue_ts,     41,  41, size, op);
 	sja1105_packing(buf, &entry->egrmirrvid,   40,  29, size, op);
 	sja1105_packing(buf, &entry->egrmirrpcp,   28,  26, size, op);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/dsa/vitesse-vsc73xx-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/dsa/vitesse-vsc73xx-core.c
@@ -34,7 +34,7 @@
 #define VSC73XX_BLOCK_ANALYZER	0x2 /* Only subblock 0 */
 #define VSC73XX_BLOCK_MII	0x3 /* Subblocks 0 and 1 */
 #define VSC73XX_BLOCK_MEMINIT	0x3 /* Only subblock 2 */
-#define VSC73XX_BLOCK_CAPTURE	0x4 /* Only subblock 2 */
+#define VSC73XX_BLOCK_CAPTURE	0x4 /* Subblocks 0-4, 6, 7 */
 #define VSC73XX_BLOCK_ARBITER	0x5 /* Only subblock 0 */
 #define VSC73XX_BLOCK_SYSTEM	0x7 /* Only subblock 0 */
 
@@ -360,13 +360,19 @@
 		break;
 
 	case VSC73XX_BLOCK_MII:
-	case VSC73XX_BLOCK_CAPTURE:
 	case VSC73XX_BLOCK_ARBITER:
 		switch (subblock) {
 		case 0 ... 1:
 			return 1;
 		}
 		break;
+	case VSC73XX_BLOCK_CAPTURE:
+		switch (subblock) {
+		case 0 ... 4:
+		case 6 ... 7:
+			return 1;
+		}
+		break;
 	}
 
 	return 0;
@@ -531,7 +537,7 @@
 		return 0;
 	}
 
-	cmd = (phy << 21) | (regnum << 16);
+	cmd = (phy << 21) | (regnum << 16) | val;
 	ret = vsc73xx_write(vsc, VSC73XX_BLOCK_MII, 0, 1, cmd);
 	if (ret)
 		return ret;
@@ -1108,6 +1114,8 @@
 
 	vsc->gc.label = devm_kasprintf(vsc->dev, GFP_KERNEL, "VSC%04x",
 				       vsc->chipid);
+	if (!vsc->gc.label)
+		return -ENOMEM;
 	vsc->gc.ngpio = 4;
 	vsc->gc.owner = THIS_MODULE;
 	vsc->gc.parent = vsc->dev;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/3com/3c589_cs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/3com/3c589_cs.c
@@ -196,6 +196,7 @@
 {
 	struct el3_private *lp;
 	struct net_device *dev;
+	int ret;
 
 	dev_dbg(&link->dev, "3c589_attach()\n");
 
@@ -219,7 +220,15 @@
 
 	dev->ethtool_ops = &netdev_ethtool_ops;
 
-	return tc589_config(link);
+	ret = tc589_config(link);
+	if (ret)
+		goto err_free_netdev;
+
+	return 0;
+
+err_free_netdev:
+	free_netdev(dev);
+	return ret;
 }
 
 static void tc589_detach(struct pcmcia_device *link)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/8390/mcf8390.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/8390/mcf8390.c
@@ -406,12 +406,12 @@
 static int mcf8390_probe(struct platform_device *pdev)
 {
 	struct net_device *dev;
-	struct resource *mem, *irq;
+	struct resource *mem;
 	resource_size_t msize;
-	int ret;
+	int ret, irq;
 
-	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (irq == NULL) {
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
 		dev_err(&pdev->dev, "no IRQ specified?\n");
 		return -ENXIO;
 	}
@@ -434,7 +434,7 @@
 	SET_NETDEV_DEV(dev, &pdev->dev);
 	platform_set_drvdata(pdev, dev);
 
-	dev->irq = irq->start;
+	dev->irq = irq;
 	dev->base_addr = mem->start;
 
 	ret = mcf8390_init(dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/Kconfig
@@ -100,6 +100,7 @@
 config KORINA
 	tristate "Korina (IDT RC32434) Ethernet support"
 	depends on MIKROTIK_RB532
+	select CRC32
 	---help---
 	  If you have a Mikrotik RouterBoard 500 or IDT RC32434
 	  based system say Y. Otherwise say N.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/aeroflex/greth.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/aeroflex/greth.c
@@ -258,6 +258,7 @@
 			if (dma_mapping_error(greth->dev, dma_addr)) {
 				if (netif_msg_ifup(greth))
 					dev_err(greth->dev, "Could not create initial DMA mapping\n");
+				dev_kfree_skb(skb);
 				goto cleanup;
 			}
 			greth->rx_skbuff[i] = skb;
@@ -483,7 +484,7 @@
 
 	if (unlikely(skb->len > MAX_FRAME_SIZE)) {
 		dev->stats.tx_errors++;
-		goto out;
+		goto len_error;
 	}
 
 	/* Save skb pointer. */
@@ -574,6 +575,7 @@
 map_error:
 	if (net_ratelimit())
 		dev_warn(greth->dev, "Could not create TX DMA mapping\n");
+len_error:
 	dev_kfree_skb(skb);
 out:
 	return err;
@@ -1541,10 +1543,11 @@
 	mdiobus_unregister(greth->mdio);
 
 	unregister_netdev(ndev);
-	free_netdev(ndev);
 
 	of_iounmap(&of_dev->resource[0], greth->regs, resource_size(&of_dev->resource[0]));
 
+	free_netdev(ndev);
+
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/allwinner/sun4i-emac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/allwinner/sun4i-emac.c
@@ -432,7 +432,7 @@
 /* Hardware start transmission.
  * Send a packet to media from the upper layer.
  */
-static int emac_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t emac_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct emac_board_info *db = netdev_priv(dev);
 	unsigned long channel;
@@ -440,7 +440,7 @@
 
 	channel = db->tx_fifo_stat & 3;
 	if (channel == 3)
-		return 1;
+		return NETDEV_TX_BUSY;
 
 	channel = (channel == 1 ? 1 : 0);
 
@@ -845,13 +845,13 @@
 	db->clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(db->clk)) {
 		ret = PTR_ERR(db->clk);
-		goto out_iounmap;
+		goto out_dispose_mapping;
 	}
 
 	ret = clk_prepare_enable(db->clk);
 	if (ret) {
 		dev_err(&pdev->dev, "Error couldn't enable clock (%d)\n", ret);
-		goto out_iounmap;
+		goto out_dispose_mapping;
 	}
 
 	ret = sunxi_sram_claim(&pdev->dev);
@@ -910,6 +910,8 @@
 	sunxi_sram_release(&pdev->dev);
 out_clk_disable_unprepare:
 	clk_disable_unprepare(db->clk);
+out_dispose_mapping:
+	irq_dispose_mapping(ndev->irq);
 out_iounmap:
 	iounmap(db->membase);
 out:
@@ -928,6 +930,7 @@
 	unregister_netdev(ndev);
 	sunxi_sram_release(&pdev->dev);
 	clk_disable_unprepare(db->clk);
+	irq_dispose_mapping(ndev->irq);
 	iounmap(db->membase);
 	free_netdev(ndev);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/altera/altera_tse_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/altera/altera_tse_main.c
@@ -163,7 +163,8 @@
 	mdio = mdiobus_alloc();
 	if (mdio == NULL) {
 		netdev_err(dev, "Error allocating MDIO bus\n");
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto put_node;
 	}
 
 	mdio->name = ALTERA_TSE_RESOURCE_NAME;
@@ -180,6 +181,7 @@
 			   mdio->id);
 		goto out_free_mdio;
 	}
+	of_node_put(mdio_node);
 
 	if (netif_msg_drv(priv))
 		netdev_info(dev, "MDIO bus %s: created\n", mdio->id);
@@ -189,6 +191,8 @@
 out_free_mdio:
 	mdiobus_free(mdio);
 	mdio = NULL;
+put_node:
+	of_node_put(mdio_node);
 	return ret;
 }
 
@@ -1431,16 +1435,19 @@
 		priv->rxdescmem_busaddr = dma_res->start;
 
 	} else {
+		ret = -ENODEV;
 		goto err_free_netdev;
 	}
 
-	if (!dma_set_mask(priv->device, DMA_BIT_MASK(priv->dmaops->dmamask)))
+	if (!dma_set_mask(priv->device, DMA_BIT_MASK(priv->dmaops->dmamask))) {
 		dma_set_coherent_mask(priv->device,
 				      DMA_BIT_MASK(priv->dmaops->dmamask));
-	else if (!dma_set_mask(priv->device, DMA_BIT_MASK(32)))
+	} else if (!dma_set_mask(priv->device, DMA_BIT_MASK(32))) {
 		dma_set_coherent_mask(priv->device, DMA_BIT_MASK(32));
-	else
+	} else {
+		ret = -EIO;
 		goto err_free_netdev;
+	}
 
 	/* MAC address space */
 	ret = request_and_map(pdev, "control_port", &control_port,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/amazon/ena/ena_admin_defs.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/amazon/ena/ena_admin_defs.h
@@ -1,37 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
 /*
- * Copyright 2015 - 2016 Amazon.com, Inc. or its affiliates.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
+ * Copyright 2015-2020 Amazon.com, Inc. or its affiliates. All rights reserved.
  */
 #ifndef _ENA_ADMIN_H_
 #define _ENA_ADMIN_H_
 
+#define ENA_ADMIN_RSS_KEY_PARTS              10
 
 enum ena_admin_aq_opcode {
 	ENA_ADMIN_CREATE_SQ                         = 1,
@@ -55,6 +29,7 @@
 	ENA_ADMIN_RESOURCE_BUSY                     = 7,
 };
 
+/* subcommands for the set/get feature admin commands */
 enum ena_admin_aq_feature_id {
 	ENA_ADMIN_DEVICE_ATTRIBUTES                 = 1,
 	ENA_ADMIN_MAX_QUEUES_NUM                    = 2,
@@ -63,7 +38,7 @@
 	ENA_ADMIN_MAX_QUEUES_EXT                    = 7,
 	ENA_ADMIN_RSS_HASH_FUNCTION                 = 10,
 	ENA_ADMIN_STATELESS_OFFLOAD_CONFIG          = 11,
-	ENA_ADMIN_RSS_REDIRECTION_TABLE_CONFIG      = 12,
+	ENA_ADMIN_RSS_INDIRECTION_TABLE_CONFIG      = 12,
 	ENA_ADMIN_MTU                               = 14,
 	ENA_ADMIN_RSS_HASH_INPUT                    = 18,
 	ENA_ADMIN_INTERRUPT_MODERATION              = 20,
@@ -117,6 +92,8 @@
 enum ena_admin_get_stats_type {
 	ENA_ADMIN_GET_STATS_TYPE_BASIC              = 0,
 	ENA_ADMIN_GET_STATS_TYPE_EXTENDED           = 1,
+	/* extra HW stats for specific network interface */
+	ENA_ADMIN_GET_STATS_TYPE_ENI                = 2,
 };
 
 enum ena_admin_get_stats_scope {
@@ -193,7 +170,7 @@
 	u16 extended_status;
 
 	/* indicates to the driver which AQ entry has been consumed by the
-	 *    device and could be reused
+	 * device and could be reused
 	 */
 	u16 sq_head_indx;
 };
@@ -238,8 +215,8 @@
 	 */
 	u8 sq_caps_3;
 
-	/* associated completion queue id. This CQ must be created prior to
-	 *    SQ creation
+	/* associated completion queue id. This CQ must be created prior to SQ
+	 * creation
 	 */
 	u16 cq_idx;
 
@@ -378,7 +355,7 @@
 	u16 queue_idx;
 
 	/* device id, value 0xFFFF means mine. only privileged device can get
-	 *    stats of other device
+	 * stats of other device
 	 */
 	u16 device_id;
 };
@@ -404,12 +381,49 @@
 	u32 rx_drops_low;
 
 	u32 rx_drops_high;
+
+	u32 tx_drops_low;
+
+	u32 tx_drops_high;
+};
+
+/* ENI Statistics Command. */
+struct ena_admin_eni_stats {
+	/* The number of packets shaped due to inbound aggregate BW
+	 * allowance being exceeded
+	 */
+	u64 bw_in_allowance_exceeded;
+
+	/* The number of packets shaped due to outbound aggregate BW
+	 * allowance being exceeded
+	 */
+	u64 bw_out_allowance_exceeded;
+
+	/* The number of packets shaped due to PPS allowance being exceeded */
+	u64 pps_allowance_exceeded;
+
+	/* The number of packets shaped due to connection tracking
+	 * allowance being exceeded and leading to failure in establishment
+	 * of new connections
+	 */
+	u64 conntrack_allowance_exceeded;
+
+	/* The number of packets shaped due to linklocal packet rate
+	 * allowance being exceeded
+	 */
+	u64 linklocal_allowance_exceeded;
 };
 
 struct ena_admin_acq_get_stats_resp {
 	struct ena_admin_acq_common_desc acq_common_desc;
 
-	struct ena_admin_basic_stats basic_stats;
+	union {
+		u64 raw[7];
+
+		struct ena_admin_basic_stats basic_stats;
+
+		struct ena_admin_eni_stats eni_stats;
+	} u;
 };
 
 struct ena_admin_get_set_feature_common_desc {
@@ -436,7 +450,9 @@
 
 	u32 device_version;
 
-	/* bitmap of ena_admin_aq_feature_id */
+	/* bitmap of ena_admin_aq_feature_id, which represents supported
+	 * subcommands for the set/get feature admin commands.
+	 */
 	u32 supported_features;
 
 	u32 reserved3;
@@ -487,37 +503,65 @@
 	ENA_ADMIN_MULTIPLE_DESCS_PER_ENTRY          = 2,
 };
 
+enum ena_admin_accel_mode_feat {
+	ENA_ADMIN_DISABLE_META_CACHING              = 0,
+	ENA_ADMIN_LIMIT_TX_BURST                    = 1,
+};
+
+struct ena_admin_accel_mode_get {
+	/* bit field of enum ena_admin_accel_mode_feat */
+	u16 supported_flags;
+
+	/* maximum burst size between two doorbells. The size is in bytes */
+	u16 max_tx_burst_size;
+};
+
+struct ena_admin_accel_mode_set {
+	/* bit field of enum ena_admin_accel_mode_feat */
+	u16 enabled_flags;
+
+	u16 reserved;
+};
+
+struct ena_admin_accel_mode_req {
+	union {
+		u32 raw[2];
+
+		struct ena_admin_accel_mode_get get;
+
+		struct ena_admin_accel_mode_set set;
+	} u;
+};
+
 struct ena_admin_feature_llq_desc {
 	u32 max_llq_num;
 
 	u32 max_llq_depth;
 
-	/*  specify the header locations the device supports. bitfield of
-	 *    enum ena_admin_llq_header_location.
+	/* specify the header locations the device supports. bitfield of enum
+	 * ena_admin_llq_header_location.
 	 */
 	u16 header_location_ctrl_supported;
 
 	/* the header location the driver selected to use. */
 	u16 header_location_ctrl_enabled;
 
-	/* if inline header is specified - this is the size of descriptor
-	 *    list entry. If header in a separate ring is specified - this is
-	 *    the size of header ring entry. bitfield of enum
-	 *    ena_admin_llq_ring_entry_size. specify the entry sizes the device
-	 *    supports
+	/* if inline header is specified - this is the size of descriptor list
+	 * entry. If header in a separate ring is specified - this is the size
+	 * of header ring entry. bitfield of enum ena_admin_llq_ring_entry_size.
+	 * specify the entry sizes the device supports
 	 */
 	u16 entry_size_ctrl_supported;
 
 	/* the entry size the driver selected to use. */
 	u16 entry_size_ctrl_enabled;
 
-	/* valid only if inline header is specified. First entry associated
-	 *    with the packet includes descriptors and header. Rest of the
-	 *    entries occupied by descriptors. This parameter defines the max
-	 *    number of descriptors precedding the header in the first entry.
-	 *    The field is bitfield of enum
-	 *    ena_admin_llq_num_descs_before_header and specify the values the
-	 *    device supports
+	/* valid only if inline header is specified. First entry associated with
+	 * the packet includes descriptors and header. Rest of the entries
+	 * occupied by descriptors. This parameter defines the max number of
+	 * descriptors precedding the header in the first entry. The field is
+	 * bitfield of enum ena_admin_llq_num_descs_before_header and specify
+	 * the values the device supports
 	 */
 	u16 desc_num_before_header_supported;
 
@@ -525,17 +569,20 @@
 	u16 desc_num_before_header_enabled;
 
 	/* valid only if inline was chosen. bitfield of enum
-	 *    ena_admin_llq_stride_ctrl
+	 * ena_admin_llq_stride_ctrl
 	 */
 	u16 descriptors_stride_ctrl_supported;
 
 	/* the stride control the driver selected to use */
 	u16 descriptors_stride_ctrl_enabled;
 
-	/* Maximum size in bytes taken by llq entries in a single tx burst.
-	 * Set to 0 when there is no such limit.
+	/* reserved */
+	u32 reserved1;
+
+	/* accelerated low latency queues requirement. driver needs to
+	 * support those requirements in order to use accelerated llq
 	 */
-	u32 max_tx_burst_size;
+	struct ena_admin_accel_mode_req accel_mode;
 };
 
 struct ena_admin_queue_ext_feature_fields {
@@ -557,8 +604,8 @@
 
 	u32 max_tx_header_size;
 
-	/* Maximum Descriptors number, including meta descriptor, allowed for
-	 * a single Tx packet
+	/* Maximum Descriptors number, including meta descriptor, allowed for a
+	 * single Tx packet
 	 */
 	u16 max_per_packet_tx_descs;
 
@@ -581,8 +628,8 @@
 
 	u32 max_header_size;
 
-	/* Maximum Descriptors number, including meta descriptor, allowed for
-	 *    a single Tx packet
+	/* Maximum Descriptors number, including meta descriptor, allowed for a
+	 * single Tx packet
 	 */
 	u16 max_packet_tx_descs;
 
@@ -670,11 +717,11 @@
 };
 
 struct ena_admin_feature_rss_flow_hash_control {
-	u32 keys_num;
+	u32 key_parts;
 
 	u32 reserved;
 
-	u32 key[10];
+	u32 key[ENA_ADMIN_RSS_KEY_PARTS];
 };
 
 struct ena_admin_feature_rss_flow_hash_function {
@@ -764,8 +811,8 @@
 	ENA_ADMIN_OS_DPDK                           = 3,
 	ENA_ADMIN_OS_FREEBSD                        = 4,
 	ENA_ADMIN_OS_IPXE                           = 5,
-	ENA_ADMIN_OS_ESXI			    = 6,
-	ENA_ADMIN_OS_GROUPS_NUM			    = 6,
+	ENA_ADMIN_OS_ESXI                           = 6,
+	ENA_ADMIN_OS_GROUPS_NUM                     = 6,
 };
 
 struct ena_admin_host_info {
@@ -809,9 +856,12 @@
 
 	u16 reserved;
 
-	/* 1 :0 : reserved
+	/* 0 : reserved
+	 * 1 : rx_offset
 	 * 2 : interrupt_moderation
-	 * 31:3 : reserved
+	 * 3 : rx_buf_mirroring
+	 * 4 : rss_configurable_function_key
+	 * 31:5 : reserved
 	 */
 	u32 driver_supported_features;
 };
@@ -967,7 +1017,7 @@
 struct ena_admin_aenq_common_desc {
 	u16 group;
 
-	u16 syndrom;
+	u16 syndrome;
 
 	/* 0 : phase
 	 * 7:1 : reserved - MBZ
@@ -991,7 +1041,7 @@
 	ENA_ADMIN_AENQ_GROUPS_NUM                   = 5,
 };
 
-enum ena_admin_aenq_notification_syndrom {
+enum ena_admin_aenq_notification_syndrome {
 	ENA_ADMIN_SUSPEND                           = 0,
 	ENA_ADMIN_RESUME                            = 1,
 	ENA_ADMIN_UPDATE_HINTS                      = 2,
@@ -1017,6 +1067,10 @@
 	u32 rx_drops_low;
 
 	u32 rx_drops_high;
+
+	u32 tx_drops_low;
+
+	u32 tx_drops_high;
 };
 
 struct ena_admin_ena_mmio_req_read_less_resp {
@@ -1116,8 +1170,14 @@
 #define ENA_ADMIN_HOST_INFO_DEVICE_MASK                     GENMASK(7, 3)
 #define ENA_ADMIN_HOST_INFO_BUS_SHIFT                       8
 #define ENA_ADMIN_HOST_INFO_BUS_MASK                        GENMASK(15, 8)
+#define ENA_ADMIN_HOST_INFO_RX_OFFSET_SHIFT                 1
+#define ENA_ADMIN_HOST_INFO_RX_OFFSET_MASK                  BIT(1)
 #define ENA_ADMIN_HOST_INFO_INTERRUPT_MODERATION_SHIFT      2
 #define ENA_ADMIN_HOST_INFO_INTERRUPT_MODERATION_MASK       BIT(2)
+#define ENA_ADMIN_HOST_INFO_RX_BUF_MIRRORING_SHIFT          3
+#define ENA_ADMIN_HOST_INFO_RX_BUF_MIRRORING_MASK           BIT(3)
+#define ENA_ADMIN_HOST_INFO_RSS_CONFIGURABLE_FUNCTION_KEY_SHIFT 4
+#define ENA_ADMIN_HOST_INFO_RSS_CONFIGURABLE_FUNCTION_KEY_MASK BIT(4)
 
 /* aenq_common_desc */
 #define ENA_ADMIN_AENQ_COMMON_DESC_PHASE_MASK               BIT(0)
@@ -1125,4 +1185,4 @@
 /* aenq_link_change_desc */
 #define ENA_ADMIN_AENQ_LINK_CHANGE_DESC_LINK_STATUS_MASK    BIT(0)
 
-#endif /*_ENA_ADMIN_H_ */
+#endif /* _ENA_ADMIN_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/amazon/ena/ena_com.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/amazon/ena/ena_com.c
@@ -1,33 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
 /*
- * Copyright 2015 Amazon.com, Inc. or its affiliates.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
+ * Copyright 2015-2020 Amazon.com, Inc. or its affiliates. All rights reserved.
  */
 
 #include "ena_com.h"
@@ -62,7 +35,9 @@
 
 #define ENA_REGS_ADMIN_INTR_MASK 1
 
-#define ENA_POLL_MS	5
+#define ENA_MIN_ADMIN_POLL_US 100
+
+#define ENA_MAX_ADMIN_POLL_US 5000
 
 /*****************************************************************************/
 /*****************************************************************************/
@@ -96,7 +71,7 @@
 				       dma_addr_t addr)
 {
 	if ((addr & GENMASK_ULL(ena_dev->dma_addr_bits - 1, 0)) != addr) {
-		pr_err("dma address has more bits that the device supports\n");
+		pr_err("DMA address has more bits that the device supports\n");
 		return -EINVAL;
 	}
 
@@ -106,16 +81,16 @@
 	return 0;
 }
 
-static int ena_com_admin_init_sq(struct ena_com_admin_queue *queue)
+static int ena_com_admin_init_sq(struct ena_com_admin_queue *admin_queue)
 {
-	struct ena_com_admin_sq *sq = &queue->sq;
-	u16 size = ADMIN_SQ_SIZE(queue->q_depth);
+	struct ena_com_admin_sq *sq = &admin_queue->sq;
+	u16 size = ADMIN_SQ_SIZE(admin_queue->q_depth);
 
-	sq->entries = dma_alloc_coherent(queue->q_dmadev, size, &sq->dma_addr,
-					 GFP_KERNEL);
+	sq->entries = dma_alloc_coherent(admin_queue->q_dmadev, size,
+					 &sq->dma_addr, GFP_KERNEL);
 
 	if (!sq->entries) {
-		pr_err("memory allocation failed\n");
+		pr_err("Memory allocation failed\n");
 		return -ENOMEM;
 	}
 
@@ -128,16 +103,16 @@
 	return 0;
 }
 
-static int ena_com_admin_init_cq(struct ena_com_admin_queue *queue)
+static int ena_com_admin_init_cq(struct ena_com_admin_queue *admin_queue)
 {
-	struct ena_com_admin_cq *cq = &queue->cq;
-	u16 size = ADMIN_CQ_SIZE(queue->q_depth);
+	struct ena_com_admin_cq *cq = &admin_queue->cq;
+	u16 size = ADMIN_CQ_SIZE(admin_queue->q_depth);
 
-	cq->entries = dma_alloc_coherent(queue->q_dmadev, size, &cq->dma_addr,
-					 GFP_KERNEL);
+	cq->entries = dma_alloc_coherent(admin_queue->q_dmadev, size,
+					 &cq->dma_addr, GFP_KERNEL);
 
 	if (!cq->entries) {
-		pr_err("memory allocation failed\n");
+		pr_err("Memory allocation failed\n");
 		return -ENOMEM;
 	}
 
@@ -147,20 +122,20 @@
 	return 0;
 }
 
-static int ena_com_admin_init_aenq(struct ena_com_dev *dev,
+static int ena_com_admin_init_aenq(struct ena_com_dev *ena_dev,
 				   struct ena_aenq_handlers *aenq_handlers)
 {
-	struct ena_com_aenq *aenq = &dev->aenq;
+	struct ena_com_aenq *aenq = &ena_dev->aenq;
 	u32 addr_low, addr_high, aenq_caps;
 	u16 size;
 
-	dev->aenq.q_depth = ENA_ASYNC_QUEUE_DEPTH;
+	ena_dev->aenq.q_depth = ENA_ASYNC_QUEUE_DEPTH;
 	size = ADMIN_AENQ_SIZE(ENA_ASYNC_QUEUE_DEPTH);
-	aenq->entries = dma_alloc_coherent(dev->dmadev, size, &aenq->dma_addr,
-					   GFP_KERNEL);
+	aenq->entries = dma_alloc_coherent(ena_dev->dmadev, size,
+					   &aenq->dma_addr, GFP_KERNEL);
 
 	if (!aenq->entries) {
-		pr_err("memory allocation failed\n");
+		pr_err("Memory allocation failed\n");
 		return -ENOMEM;
 	}
 
@@ -170,18 +145,18 @@
 	addr_low = ENA_DMA_ADDR_TO_UINT32_LOW(aenq->dma_addr);
 	addr_high = ENA_DMA_ADDR_TO_UINT32_HIGH(aenq->dma_addr);
 
-	writel(addr_low, dev->reg_bar + ENA_REGS_AENQ_BASE_LO_OFF);
-	writel(addr_high, dev->reg_bar + ENA_REGS_AENQ_BASE_HI_OFF);
+	writel(addr_low, ena_dev->reg_bar + ENA_REGS_AENQ_BASE_LO_OFF);
+	writel(addr_high, ena_dev->reg_bar + ENA_REGS_AENQ_BASE_HI_OFF);
 
 	aenq_caps = 0;
-	aenq_caps |= dev->aenq.q_depth & ENA_REGS_AENQ_CAPS_AENQ_DEPTH_MASK;
+	aenq_caps |= ena_dev->aenq.q_depth & ENA_REGS_AENQ_CAPS_AENQ_DEPTH_MASK;
 	aenq_caps |= (sizeof(struct ena_admin_aenq_entry)
 		      << ENA_REGS_AENQ_CAPS_AENQ_ENTRY_SIZE_SHIFT) &
 		     ENA_REGS_AENQ_CAPS_AENQ_ENTRY_SIZE_MASK;
-	writel(aenq_caps, dev->reg_bar + ENA_REGS_AENQ_CAPS_OFF);
+	writel(aenq_caps, ena_dev->reg_bar + ENA_REGS_AENQ_CAPS_OFF);
 
 	if (unlikely(!aenq_handlers)) {
-		pr_err("aenq handlers pointer is NULL\n");
+		pr_err("AENQ handlers pointer is NULL\n");
 		return -EINVAL;
 	}
 
@@ -197,26 +172,31 @@
 	atomic_dec(&queue->outstanding_cmds);
 }
 
-static struct ena_comp_ctx *get_comp_ctxt(struct ena_com_admin_queue *queue,
+static struct ena_comp_ctx *get_comp_ctxt(struct ena_com_admin_queue *admin_queue,
 					  u16 command_id, bool capture)
 {
-	if (unlikely(command_id >= queue->q_depth)) {
-		pr_err("command id is larger than the queue size. cmd_id: %u queue size %d\n",
-		       command_id, queue->q_depth);
+	if (unlikely(command_id >= admin_queue->q_depth)) {
+		pr_err("Command id is larger than the queue size. cmd_id: %u queue size %d\n",
+		       command_id, admin_queue->q_depth);
+		return NULL;
+	}
+
+	if (unlikely(!admin_queue->comp_ctx)) {
+		pr_err("Completion context is NULL\n");
 		return NULL;
 	}
 
-	if (unlikely(queue->comp_ctx[command_id].occupied && capture)) {
+	if (unlikely(admin_queue->comp_ctx[command_id].occupied && capture)) {
 		pr_err("Completion context is occupied\n");
 		return NULL;
 	}
 
 	if (capture) {
-		atomic_inc(&queue->outstanding_cmds);
-		queue->comp_ctx[command_id].occupied = true;
+		atomic_inc(&admin_queue->outstanding_cmds);
+		admin_queue->comp_ctx[command_id].occupied = true;
 	}
 
-	return &queue->comp_ctx[command_id];
+	return &admin_queue->comp_ctx[command_id];
 }
 
 static struct ena_comp_ctx *__ena_com_submit_admin_cmd(struct ena_com_admin_queue *admin_queue,
@@ -237,7 +217,7 @@
 	/* In case of queue FULL */
 	cnt = (u16)atomic_read(&admin_queue->outstanding_cmds);
 	if (cnt >= admin_queue->q_depth) {
-		pr_debug("admin queue is full.\n");
+		pr_debug("Admin queue is full.\n");
 		admin_queue->stats.out_of_space++;
 		return ERR_PTR(-ENOSPC);
 	}
@@ -277,20 +257,21 @@
 	return comp_ctx;
 }
 
-static int ena_com_init_comp_ctxt(struct ena_com_admin_queue *queue)
+static int ena_com_init_comp_ctxt(struct ena_com_admin_queue *admin_queue)
 {
-	size_t size = queue->q_depth * sizeof(struct ena_comp_ctx);
+	size_t size = admin_queue->q_depth * sizeof(struct ena_comp_ctx);
 	struct ena_comp_ctx *comp_ctx;
 	u16 i;
 
-	queue->comp_ctx = devm_kzalloc(queue->q_dmadev, size, GFP_KERNEL);
-	if (unlikely(!queue->comp_ctx)) {
-		pr_err("memory allocation failed\n");
+	admin_queue->comp_ctx =
+		devm_kzalloc(admin_queue->q_dmadev, size, GFP_KERNEL);
+	if (unlikely(!admin_queue->comp_ctx)) {
+		pr_err("Memory allocation failed\n");
 		return -ENOMEM;
 	}
 
-	for (i = 0; i < queue->q_depth; i++) {
-		comp_ctx = get_comp_ctxt(queue, i, false);
+	for (i = 0; i < admin_queue->q_depth; i++) {
+		comp_ctx = get_comp_ctxt(admin_queue, i, false);
 		if (comp_ctx)
 			init_completion(&comp_ctx->wait_event);
 	}
@@ -356,7 +337,7 @@
 		}
 
 		if (!io_sq->desc_addr.virt_addr) {
-			pr_err("memory allocation failed\n");
+			pr_err("Memory allocation failed\n");
 			return -ENOMEM;
 		}
 	}
@@ -369,8 +350,8 @@
 			ENA_COM_BOUNCE_BUFFER_CNTRL_CNT;
 		io_sq->bounce_buf_ctrl.next_to_use = 0;
 
-		size = io_sq->bounce_buf_ctrl.buffer_size *
-			 io_sq->bounce_buf_ctrl.buffers_num;
+		size = (size_t)io_sq->bounce_buf_ctrl.buffer_size *
+			io_sq->bounce_buf_ctrl.buffers_num;
 
 		dev_node = dev_to_node(ena_dev->dmadev);
 		set_dev_node(ena_dev->dmadev, ctx->numa_node);
@@ -382,7 +363,7 @@
 				devm_kzalloc(ena_dev->dmadev, size, GFP_KERNEL);
 
 		if (!io_sq->bounce_buf_ctrl.base_buffer) {
-			pr_err("bounce buffer memory allocation failed\n");
+			pr_err("Bounce buffer memory allocation failed\n");
 			return -ENOMEM;
 		}
 
@@ -396,6 +377,8 @@
 		       0x0, io_sq->llq_info.desc_list_entry_size);
 		io_sq->llq_buf_ctrl.descs_left_in_line =
 			io_sq->llq_info.descs_num_before_header;
+		io_sq->disable_meta_caching =
+			io_sq->llq_info.disable_meta_caching;
 
 		if (io_sq->llq_info.max_entries_in_tx_burst > 0)
 			io_sq->entries_in_tx_burst_left =
@@ -440,7 +423,7 @@
 	}
 
 	if (!io_cq->cdesc_addr.virt_addr) {
-		pr_err("memory allocation failed\n");
+		pr_err("Memory allocation failed\n");
 		return -ENOMEM;
 	}
 
@@ -516,10 +499,7 @@
 static int ena_com_comp_status_to_errno(u8 comp_status)
 {
 	if (unlikely(comp_status != 0))
-		pr_err("admin command failed[%u]\n", comp_status);
-
-	if (unlikely(comp_status > ENA_ADMIN_UNKNOWN_ERROR))
-		return -EINVAL;
+		pr_err("Admin command failed[%u]\n", comp_status);
 
 	switch (comp_status) {
 	case ENA_ADMIN_SUCCESS:
@@ -533,9 +513,18 @@
 	case ENA_ADMIN_ILLEGAL_PARAMETER:
 	case ENA_ADMIN_UNKNOWN_ERROR:
 		return -EINVAL;
+	case ENA_ADMIN_RESOURCE_BUSY:
+		return -EAGAIN;
 	}
 
-	return 0;
+	return -EINVAL;
+}
+
+static void ena_delay_exponential_backoff_us(u32 exp, u32 delay_us)
+{
+	delay_us = max_t(u32, ENA_MIN_ADMIN_POLL_US, delay_us);
+	delay_us = min_t(u32, delay_us * (1U << exp), ENA_MAX_ADMIN_POLL_US);
+	usleep_range(delay_us, 2 * delay_us);
 }
 
 static int ena_com_wait_and_process_admin_cq_polling(struct ena_comp_ctx *comp_ctx,
@@ -544,6 +533,7 @@
 	unsigned long flags = 0;
 	unsigned long timeout;
 	int ret;
+	u32 exp = 0;
 
 	timeout = jiffies + usecs_to_jiffies(admin_queue->completion_timeout);
 
@@ -567,7 +557,8 @@
 			goto err;
 		}
 
-		msleep(ENA_POLL_MS);
+		ena_delay_exponential_backoff_us(exp++,
+						 admin_queue->ena_dev->ena_min_poll_delay_us);
 	}
 
 	if (unlikely(comp_ctx->status == ENA_CMD_ABORTED)) {
@@ -588,7 +579,7 @@
 	return ret;
 }
 
-/**
+/*
  * Set the LLQ configurations of the firmware
  *
  * The driver provides only the enabled feature values to the device,
@@ -613,6 +604,10 @@
 	cmd.u.llq.desc_num_before_header_enabled = llq_info->descs_num_before_header;
 	cmd.u.llq.descriptors_stride_ctrl_enabled = llq_info->desc_stride_ctrl;
 
+	cmd.u.llq.accel_mode.u.set.enabled_flags =
+		BIT(ENA_ADMIN_DISABLE_META_CACHING) |
+		BIT(ENA_ADMIN_LIMIT_TX_BURST);
+
 	ret = ena_com_execute_admin_command(admin_queue,
 					    (struct ena_admin_aq_entry *)&cmd,
 					    sizeof(cmd),
@@ -630,6 +625,7 @@
 				   struct ena_llq_configurations *llq_default_cfg)
 {
 	struct ena_com_llq_info *llq_info = &ena_dev->llq_info;
+	struct ena_admin_accel_mode_get llq_accel_mode_get;
 	u16 supported_feat;
 	int rc;
 
@@ -697,8 +693,7 @@
 		/* The desc list entry size should be whole multiply of 8
 		 * This requirement comes from __iowrite64_copy()
 		 */
-		pr_err("illegal entry size %d\n",
-		       llq_info->desc_list_entry_size);
+		pr_err("Illegal entry size %d\n", llq_info->desc_list_entry_size);
 		return -EINVAL;
 	}
 
@@ -730,9 +725,17 @@
 		       llq_default_cfg->llq_num_decs_before_header,
 		       supported_feat, llq_info->descs_num_before_header);
 	}
+	/* Check for accelerated queue supported */
+	llq_accel_mode_get = llq_features->accel_mode.u.get;
 
-	llq_info->max_entries_in_tx_burst =
-		(u16)(llq_features->max_tx_burst_size /	llq_default_cfg->llq_ring_entry_size_value);
+	llq_info->disable_meta_caching =
+		!!(llq_accel_mode_get.supported_flags &
+		   BIT(ENA_ADMIN_DISABLE_META_CACHING));
+
+	if (llq_accel_mode_get.supported_flags & BIT(ENA_ADMIN_LIMIT_TX_BURST))
+		llq_info->max_entries_in_tx_burst =
+			llq_accel_mode_get.max_tx_burst_size /
+			llq_default_cfg->llq_ring_entry_size_value;
 
 	rc = ena_com_set_llq(ena_dev);
 	if (rc)
@@ -770,7 +773,7 @@
 			if (admin_queue->auto_polling)
 				admin_queue->polling = true;
 		} else {
-			pr_err("The ena device doesn't send a completion for the admin cmd %d status %d\n",
+			pr_err("The ena device didn't send a completion for the admin cmd %d status %d\n",
 			       comp_ctx->cmd_opcode, comp_ctx->status);
 		}
 		/* Check if shifted to polling mode.
@@ -831,7 +834,7 @@
 	}
 
 	if (unlikely(i == timeout)) {
-		pr_err("reading reg failed for timeout. expected: req id[%hu] offset[%hu] actual: req id[%hu] offset[%hu]\n",
+		pr_err("Reading reg failed for timeout. expected: req id[%hu] offset[%hu] actual: req id[%hu] offset[%hu]\n",
 		       mmio_read->seq_num, offset, read_resp->req_id,
 		       read_resp->reg_off);
 		ret = ENA_MMIO_READ_TIMEOUT;
@@ -898,7 +901,7 @@
 					    sizeof(destroy_resp));
 
 	if (unlikely(ret && (ret != -ENODEV)))
-		pr_err("failed to destroy io sq error: %d\n", ret);
+		pr_err("Failed to destroy io sq error: %d\n", ret);
 
 	return ret;
 }
@@ -938,12 +941,13 @@
 static int wait_for_reset_state(struct ena_com_dev *ena_dev, u32 timeout,
 				u16 exp_state)
 {
-	u32 val, i;
+	u32 val, exp = 0;
+	unsigned long timeout_stamp;
 
-	/* Convert timeout from resolution of 100ms to ENA_POLL_MS */
-	timeout = (timeout * 100) / ENA_POLL_MS;
+	/* Convert timeout from resolution of 100ms to us resolution. */
+	timeout_stamp = jiffies + usecs_to_jiffies(100 * 1000 * timeout);
 
-	for (i = 0; i < timeout; i++) {
+	while (1) {
 		val = ena_com_reg_bar_read32(ena_dev, ENA_REGS_DEV_STS_OFF);
 
 		if (unlikely(val == ENA_MMIO_READ_TIMEOUT)) {
@@ -955,10 +959,11 @@
 			exp_state)
 			return 0;
 
-		msleep(ENA_POLL_MS);
-	}
+		if (time_is_before_jiffies(timeout_stamp))
+			return -ETIME;
 
-	return -ETIME;
+		ena_delay_exponential_backoff_us(exp++, ena_dev->ena_min_poll_delay_us);
+	}
 }
 
 static bool ena_com_check_supported_feature_id(struct ena_com_dev *ena_dev,
@@ -1005,7 +1010,7 @@
 				   &get_cmd.control_buffer.address,
 				   control_buf_dma_addr);
 	if (unlikely(ret)) {
-		pr_err("memory address set failed\n");
+		pr_err("Memory address set failed\n");
 		return ret;
 	}
 
@@ -1041,10 +1046,31 @@
 				      feature_ver);
 }
 
+static void ena_com_hash_key_fill_default_key(struct ena_com_dev *ena_dev)
+{
+	struct ena_admin_feature_rss_flow_hash_control *hash_key =
+		(ena_dev->rss).hash_key;
+
+	netdev_rss_key_fill(&hash_key->key, sizeof(hash_key->key));
+	/* The key buffer is stored in the device in an array of
+	 * uint32 elements.
+	 */
+	hash_key->key_parts = ENA_ADMIN_RSS_KEY_PARTS;
+}
+
+int ena_com_get_current_hash_function(struct ena_com_dev *ena_dev)
+{
+	return ena_dev->rss.hash_func;
+}
+
 static int ena_com_hash_key_allocate(struct ena_com_dev *ena_dev)
 {
 	struct ena_rss *rss = &ena_dev->rss;
 
+	if (!ena_com_check_supported_feature_id(ena_dev,
+						ENA_ADMIN_RSS_HASH_FUNCTION))
+		return -EOPNOTSUPP;
+
 	rss->hash_key =
 		dma_alloc_coherent(ena_dev->dmadev, sizeof(*rss->hash_key),
 				   &rss->hash_key_dma_addr, GFP_KERNEL);
@@ -1098,13 +1124,13 @@
 	int ret;
 
 	ret = ena_com_get_feature(ena_dev, &get_resp,
-				  ENA_ADMIN_RSS_REDIRECTION_TABLE_CONFIG, 0);
+				  ENA_ADMIN_RSS_INDIRECTION_TABLE_CONFIG, 0);
 	if (unlikely(ret))
 		return ret;
 
 	if ((get_resp.u.ind_table.min_size > log_size) ||
 	    (get_resp.u.ind_table.max_size < log_size)) {
-		pr_err("indirect table size doesn't fit. requested size: %d while min is:%d and max %d\n",
+		pr_err("Indirect table size doesn't fit. requested size: %d while min is:%d and max %d\n",
 		       1 << log_size, 1 << get_resp.u.ind_table.min_size,
 		       1 << get_resp.u.ind_table.max_size);
 		return -EINVAL;
@@ -1197,7 +1223,7 @@
 					   &create_cmd.sq_ba,
 					   io_sq->desc_addr.phys_addr);
 		if (unlikely(ret)) {
-			pr_err("memory address set failed\n");
+			pr_err("Memory address set failed\n");
 			return ret;
 		}
 	}
@@ -1226,7 +1252,7 @@
 			cmd_completion.llq_descriptors_offset);
 	}
 
-	pr_debug("created sq[%u], depth[%u]\n", io_sq->idx, io_sq->q_depth);
+	pr_debug("Created sq[%u], depth[%u]\n", io_sq->idx, io_sq->q_depth);
 
 	return ret;
 }
@@ -1254,40 +1280,12 @@
 	return 0;
 }
 
-static int ena_com_ind_tbl_convert_from_device(struct ena_com_dev *ena_dev)
-{
-	u16 dev_idx_to_host_tbl[ENA_TOTAL_NUM_QUEUES] = { (u16)-1 };
-	struct ena_rss *rss = &ena_dev->rss;
-	u8 idx;
-	u16 i;
-
-	for (i = 0; i < ENA_TOTAL_NUM_QUEUES; i++)
-		dev_idx_to_host_tbl[ena_dev->io_sq_queues[i].idx] = i;
-
-	for (i = 0; i < 1 << rss->tbl_log_size; i++) {
-		if (rss->rss_ind_tbl[i].cq_idx > ENA_TOTAL_NUM_QUEUES)
-			return -EINVAL;
-		idx = (u8)rss->rss_ind_tbl[i].cq_idx;
-
-		if (dev_idx_to_host_tbl[idx] > ENA_TOTAL_NUM_QUEUES)
-			return -EINVAL;
-
-		rss->host_rss_ind_tbl[i] = dev_idx_to_host_tbl[idx];
-	}
-
-	return 0;
-}
-
 static void ena_com_update_intr_delay_resolution(struct ena_com_dev *ena_dev,
 						 u16 intr_delay_resolution)
 {
-	/* Initial value of intr_delay_resolution might be 0 */
-	u16 prev_intr_delay_resolution =
-		ena_dev->intr_delay_resolution ?
-		ena_dev->intr_delay_resolution :
-		ENA_DEFAULT_INTR_DELAY_RESOLUTION;
+	u16 prev_intr_delay_resolution = ena_dev->intr_delay_resolution;
 
-	if (!intr_delay_resolution) {
+	if (unlikely(!intr_delay_resolution)) {
 		pr_err("Illegal intr_delay_resolution provided. Going to use default 1 usec resolution\n");
 		intr_delay_resolution = ENA_DEFAULT_INTR_DELAY_RESOLUTION;
 	}
@@ -1367,7 +1365,7 @@
 				   &create_cmd.cq_ba,
 				   io_cq->cdesc_addr.phys_addr);
 	if (unlikely(ret)) {
-		pr_err("memory address set failed\n");
+		pr_err("Memory address set failed\n");
 		return ret;
 	}
 
@@ -1396,7 +1394,7 @@
 			(u32 __iomem *)((uintptr_t)ena_dev->reg_bar +
 			cmd_completion.numa_node_register_offset);
 
-	pr_debug("created cq[%u], depth[%u]\n", io_cq->idx, io_cq->q_depth);
+	pr_debug("Created cq[%u], depth[%u]\n", io_cq->idx, io_cq->q_depth);
 
 	return ret;
 }
@@ -1441,11 +1439,13 @@
 {
 	struct ena_com_admin_queue *admin_queue = &ena_dev->admin_queue;
 	unsigned long flags = 0;
+	u32 exp = 0;
 
 	spin_lock_irqsave(&admin_queue->q_lock, flags);
 	while (atomic_read(&admin_queue->outstanding_cmds) != 0) {
 		spin_unlock_irqrestore(&admin_queue->q_lock, flags);
-		msleep(ENA_POLL_MS);
+		ena_delay_exponential_backoff_us(exp++,
+						 ena_dev->ena_min_poll_delay_us);
 		spin_lock_irqsave(&admin_queue->q_lock, flags);
 	}
 	spin_unlock_irqrestore(&admin_queue->q_lock, flags);
@@ -1587,12 +1587,12 @@
 		return -ETIME;
 	}
 
-	pr_info("ena device version: %d.%d\n",
+	pr_info("ENA device version: %d.%d\n",
 		(ver & ENA_REGS_VERSION_MAJOR_VERSION_MASK) >>
 			ENA_REGS_VERSION_MAJOR_VERSION_SHIFT,
 		ver & ENA_REGS_VERSION_MINOR_VERSION_MASK);
 
-	pr_info("ena controller version: %d.%d.%d implementation version %d\n",
+	pr_info("ENA controller version: %d.%d.%d implementation version %d\n",
 		(ctrl_ver & ENA_REGS_CONTROLLER_VERSION_MAJOR_VERSION_MASK) >>
 			ENA_REGS_CONTROLLER_VERSION_MAJOR_VERSION_SHIFT,
 		(ctrl_ver & ENA_REGS_CONTROLLER_VERSION_MINOR_VERSION_MASK) >>
@@ -1615,6 +1615,19 @@
 	return 0;
 }
 
+static void
+ena_com_free_ena_admin_queue_comp_ctx(struct ena_com_dev *ena_dev,
+				      struct ena_com_admin_queue *admin_queue)
+
+{
+	if (!admin_queue->comp_ctx)
+		return;
+
+	devm_kfree(ena_dev->dmadev, admin_queue->comp_ctx);
+
+	admin_queue->comp_ctx = NULL;
+}
+
 void ena_com_admin_destroy(struct ena_com_dev *ena_dev)
 {
 	struct ena_com_admin_queue *admin_queue = &ena_dev->admin_queue;
@@ -1623,9 +1636,8 @@
 	struct ena_com_aenq *aenq = &ena_dev->aenq;
 	u16 size;
 
-	if (admin_queue->comp_ctx)
-		devm_kfree(ena_dev->dmadev, admin_queue->comp_ctx);
-	admin_queue->comp_ctx = NULL;
+	ena_com_free_ena_admin_queue_comp_ctx(ena_dev, admin_queue);
+
 	size = ADMIN_SQ_SIZE(admin_queue->q_depth);
 	if (sq->entries)
 		dma_free_coherent(ena_dev->dmadev, size, sq->entries,
@@ -1793,6 +1805,7 @@
 	if (ret)
 		goto error;
 
+	admin_queue->ena_dev = ena_dev;
 	admin_queue->running_state = true;
 
 	return 0;
@@ -1902,6 +1915,7 @@
 
 	memcpy(&get_feat_ctx->dev_attr, &get_resp.u.dev_attr,
 	       sizeof(get_resp.u.dev_attr));
+
 	ena_dev->supported_features = get_resp.u.dev_attr.supported_features;
 
 	if (ena_dev->supported_features & BIT(ENA_ADMIN_MAX_QUEUES_EXT)) {
@@ -1980,10 +1994,10 @@
 /* ena_handle_specific_aenq_event:
  * return the handler that is relevant to the specific event group
  */
-static ena_aenq_handler ena_com_get_specific_aenq_cb(struct ena_com_dev *dev,
+static ena_aenq_handler ena_com_get_specific_aenq_cb(struct ena_com_dev *ena_dev,
 						     u16 group)
 {
-	struct ena_aenq_handlers *aenq_handlers = dev->aenq.aenq_handlers;
+	struct ena_aenq_handlers *aenq_handlers = ena_dev->aenq.aenq_handlers;
 
 	if ((group < ENA_MAX_HANDLERS) && aenq_handlers->handlers[group])
 		return aenq_handlers->handlers[group];
@@ -1995,12 +2009,12 @@
  * handles the aenq incoming events.
  * pop events from the queue and apply the specific handler
  */
-void ena_com_aenq_intr_handler(struct ena_com_dev *dev, void *data)
+void ena_com_aenq_intr_handler(struct ena_com_dev *ena_dev, void *data)
 {
 	struct ena_admin_aenq_entry *aenq_e;
 	struct ena_admin_aenq_common_desc *aenq_common;
-	struct ena_com_aenq *aenq  = &dev->aenq;
-	unsigned long long timestamp;
+	struct ena_com_aenq *aenq  = &ena_dev->aenq;
+	u64 timestamp;
 	ena_aenq_handler handler_cb;
 	u16 masked_head, processed = 0;
 	u8 phase;
@@ -2018,14 +2032,14 @@
 		 */
 		dma_rmb();
 
-		timestamp =
-			(unsigned long long)aenq_common->timestamp_low |
-			((unsigned long long)aenq_common->timestamp_high << 32);
-		pr_debug("AENQ! Group[%x] Syndrom[%x] timestamp: [%llus]\n",
-			 aenq_common->group, aenq_common->syndrom, timestamp);
+		timestamp = (u64)aenq_common->timestamp_low |
+			((u64)aenq_common->timestamp_high << 32);
+
+		pr_debug("AENQ! Group[%x] Syndrome[%x] timestamp: [%llus]\n",
+			 aenq_common->group, aenq_common->syndrome, timestamp);
 
 		/* Handle specific event*/
-		handler_cb = ena_com_get_specific_aenq_cb(dev,
+		handler_cb = ena_com_get_specific_aenq_cb(ena_dev,
 							  aenq_common->group);
 		handler_cb(data, aenq_e); /* call the actual event handler*/
 
@@ -2051,7 +2065,7 @@
 	/* write the aenq doorbell after all AENQ descriptors were read */
 	mb();
 	writel_relaxed((u32)aenq->head,
-		       dev->reg_bar + ENA_REGS_AENQ_HEAD_DB_OFF);
+		       ena_dev->reg_bar + ENA_REGS_AENQ_HEAD_DB_OFF);
 }
 
 int ena_com_dev_reset(struct ena_com_dev *ena_dev,
@@ -2143,6 +2157,21 @@
 	return ret;
 }
 
+int ena_com_get_eni_stats(struct ena_com_dev *ena_dev,
+			  struct ena_admin_eni_stats *stats)
+{
+	struct ena_com_stats_ctx ctx;
+	int ret;
+
+	memset(&ctx, 0x0, sizeof(ctx));
+	ret = ena_get_dev_stats(ena_dev, &ctx, ENA_ADMIN_GET_STATS_TYPE_ENI);
+	if (likely(ret == 0))
+		memcpy(stats, &ctx.get_resp.u.eni_stats,
+		       sizeof(ctx.get_resp.u.eni_stats));
+
+	return ret;
+}
+
 int ena_com_get_dev_basic_stats(struct ena_com_dev *ena_dev,
 				struct ena_admin_basic_stats *stats)
 {
@@ -2152,8 +2181,8 @@
 	memset(&ctx, 0x0, sizeof(ctx));
 	ret = ena_get_dev_stats(ena_dev, &ctx, ENA_ADMIN_GET_STATS_TYPE_BASIC);
 	if (likely(ret == 0))
-		memcpy(stats, &ctx.get_resp.basic_stats,
-		       sizeof(ctx.get_resp.basic_stats));
+		memcpy(stats, &ctx.get_resp.u.basic_stats,
+		       sizeof(ctx.get_resp.u.basic_stats));
 
 	return ret;
 }
@@ -2249,7 +2278,7 @@
 				   &cmd.control_buffer.address,
 				   rss->hash_key_dma_addr);
 	if (unlikely(ret)) {
-		pr_err("memory address set failed\n");
+		pr_err("Memory address set failed\n");
 		return ret;
 	}
 
@@ -2273,12 +2302,14 @@
 			       enum ena_admin_hash_functions func,
 			       const u8 *key, u16 key_len, u32 init_val)
 {
-	struct ena_rss *rss = &ena_dev->rss;
+	struct ena_admin_feature_rss_flow_hash_control *hash_key;
 	struct ena_admin_get_feat_resp get_resp;
-	struct ena_admin_feature_rss_flow_hash_control *hash_key =
-		rss->hash_key;
+	enum ena_admin_hash_functions old_func;
+	struct ena_rss *rss = &ena_dev->rss;
 	int rc;
 
+	hash_key = rss->hash_key;
+
 	/* Make sure size is a mult of DWs */
 	if (unlikely(key_len & 0x3))
 		return -EINVAL;
@@ -2290,22 +2321,23 @@
 	if (unlikely(rc))
 		return rc;
 
-	if (!((1 << func) & get_resp.u.flow_hash_func.supported_func)) {
+	if (!(BIT(func) & get_resp.u.flow_hash_func.supported_func)) {
 		pr_err("Flow hash function %d isn't supported\n", func);
 		return -EOPNOTSUPP;
 	}
 
 	switch (func) {
 	case ENA_ADMIN_TOEPLITZ:
-		if (key_len > sizeof(hash_key->key)) {
-			pr_err("key len (%hu) is bigger than the max supported (%zu)\n",
-			       key_len, sizeof(hash_key->key));
-			return -EINVAL;
+		if (key) {
+			if (key_len != sizeof(hash_key->key)) {
+				pr_err("key len (%hu) doesn't equal the supported size (%zu)\n",
+				       key_len, sizeof(hash_key->key));
+				return -EINVAL;
+			}
+			memcpy(hash_key->key, key, key_len);
+			rss->hash_init_val = init_val;
+			hash_key->key_parts = key_len / sizeof(hash_key->key[0]);
 		}
-
-		memcpy(hash_key->key, key, key_len);
-		rss->hash_init_val = init_val;
-		hash_key->keys_num = key_len >> 2;
 		break;
 	case ENA_ADMIN_CRC32:
 		rss->hash_init_val = init_val;
@@ -2315,26 +2347,27 @@
 		return -EINVAL;
 	}
 
+	old_func = rss->hash_func;
 	rss->hash_func = func;
 	rc = ena_com_set_hash_function(ena_dev);
 
 	/* Restore the old function */
 	if (unlikely(rc))
-		ena_com_get_hash_function(ena_dev, NULL, NULL);
+		rss->hash_func = old_func;
 
 	return rc;
 }
 
 int ena_com_get_hash_function(struct ena_com_dev *ena_dev,
-			      enum ena_admin_hash_functions *func,
-			      u8 *key)
+			      enum ena_admin_hash_functions *func)
 {
 	struct ena_rss *rss = &ena_dev->rss;
 	struct ena_admin_get_feat_resp get_resp;
-	struct ena_admin_feature_rss_flow_hash_control *hash_key =
-		rss->hash_key;
 	int rc;
 
+	if (unlikely(!func))
+		return -EINVAL;
+
 	rc = ena_com_get_feature_ex(ena_dev, &get_resp,
 				    ENA_ADMIN_RSS_HASH_FUNCTION,
 				    rss->hash_key_dma_addr,
@@ -2342,12 +2375,24 @@
 	if (unlikely(rc))
 		return rc;
 
-	rss->hash_func = get_resp.u.flow_hash_func.selected_func;
-	if (func)
-		*func = rss->hash_func;
+	/* ffs() returns 1 in case the lsb is set */
+	rss->hash_func = ffs(get_resp.u.flow_hash_func.selected_func);
+	if (rss->hash_func)
+		rss->hash_func--;
+
+	*func = rss->hash_func;
+
+	return 0;
+}
+
+int ena_com_get_hash_key(struct ena_com_dev *ena_dev, u8 *key)
+{
+	struct ena_admin_feature_rss_flow_hash_control *hash_key =
+		ena_dev->rss.hash_key;
 
 	if (key)
-		memcpy(key, hash_key->key, (size_t)(hash_key->keys_num) << 2);
+		memcpy(key, hash_key->key,
+		       (size_t)(hash_key->key_parts) * sizeof(hash_key->key[0]));
 
 	return 0;
 }
@@ -2403,7 +2448,7 @@
 				   &cmd.control_buffer.address,
 				   rss->hash_ctrl_dma_addr);
 	if (unlikely(ret)) {
-		pr_err("memory address set failed\n");
+		pr_err("Memory address set failed\n");
 		return ret;
 	}
 	cmd.control_buffer.length = sizeof(*hash_ctrl);
@@ -2464,7 +2509,7 @@
 		available_fields = hash_ctrl->selected_fields[i].fields &
 				hash_ctrl->supported_fields[i].fields;
 		if (available_fields != hash_ctrl->selected_fields[i].fields) {
-			pr_err("hash control doesn't support all the desire configuration. proto %x supported %x selected %x\n",
+			pr_err("Hash control doesn't support all the desire configuration. proto %x supported %x selected %x\n",
 			       i, hash_ctrl->supported_fields[i].fields,
 			       hash_ctrl->selected_fields[i].fields);
 			return -EOPNOTSUPP;
@@ -2502,7 +2547,7 @@
 	/* Make sure all the fields are supported */
 	supported_fields = hash_ctrl->supported_fields[proto].fields;
 	if ((hash_fields & supported_fields) != hash_fields) {
-		pr_err("proto %d doesn't support the required fields %x. supports only: %x\n",
+		pr_err("Proto %d doesn't support the required fields %x. supports only: %x\n",
 		       proto, hash_fields, supported_fields);
 	}
 
@@ -2542,9 +2587,9 @@
 	int ret;
 
 	if (!ena_com_check_supported_feature_id(
-		    ena_dev, ENA_ADMIN_RSS_REDIRECTION_TABLE_CONFIG)) {
+		    ena_dev, ENA_ADMIN_RSS_INDIRECTION_TABLE_CONFIG)) {
 		pr_debug("Feature %d isn't supported\n",
-			 ENA_ADMIN_RSS_REDIRECTION_TABLE_CONFIG);
+			 ENA_ADMIN_RSS_INDIRECTION_TABLE_CONFIG);
 		return -EOPNOTSUPP;
 	}
 
@@ -2559,7 +2604,7 @@
 	cmd.aq_common_descriptor.opcode = ENA_ADMIN_SET_FEATURE;
 	cmd.aq_common_descriptor.flags =
 		ENA_ADMIN_AQ_COMMON_DESC_CTRL_DATA_INDIRECT_MASK;
-	cmd.feat_common.feature_id = ENA_ADMIN_RSS_REDIRECTION_TABLE_CONFIG;
+	cmd.feat_common.feature_id = ENA_ADMIN_RSS_INDIRECTION_TABLE_CONFIG;
 	cmd.u.ind_table.size = rss->tbl_log_size;
 	cmd.u.ind_table.inline_index = 0xFFFFFFFF;
 
@@ -2567,7 +2612,7 @@
 				   &cmd.control_buffer.address,
 				   rss->rss_ind_tbl_dma_addr);
 	if (unlikely(ret)) {
-		pr_err("memory address set failed\n");
+		pr_err("Memory address set failed\n");
 		return ret;
 	}
 
@@ -2597,7 +2642,7 @@
 		sizeof(struct ena_admin_rss_ind_table_entry);
 
 	rc = ena_com_get_feature_ex(ena_dev, &get_resp,
-				    ENA_ADMIN_RSS_REDIRECTION_TABLE_CONFIG,
+				    ENA_ADMIN_RSS_INDIRECTION_TABLE_CONFIG,
 				    rss->rss_ind_tbl_dma_addr,
 				    tbl_size, 0);
 	if (unlikely(rc))
@@ -2606,10 +2651,6 @@
 	if (!ind_tbl)
 		return 0;
 
-	rc = ena_com_ind_tbl_convert_from_device(ena_dev);
-	if (unlikely(rc))
-		return rc;
-
 	for (i = 0; i < (1 << rss->tbl_log_size); i++)
 		ind_tbl[i] = rss->host_rss_ind_tbl[i];
 
@@ -2626,8 +2667,14 @@
 	if (unlikely(rc))
 		goto err_indr_tbl;
 
+	/* The following function might return unsupported in case the
+	 * device doesn't support setting the key / hash function. We can safely
+	 * ignore this error and have indirection table support only.
+	 */
 	rc = ena_com_hash_key_allocate(ena_dev);
-	if (unlikely(rc))
+	if (likely(!rc))
+		ena_com_hash_key_fill_default_key(ena_dev);
+	else if (rc != -EOPNOTSUPP)
 		goto err_hash_key;
 
 	rc = ena_com_hash_ctrl_init(ena_dev);
@@ -2678,8 +2725,7 @@
 
 	host_attr->debug_area_virt_addr =
 		dma_alloc_coherent(ena_dev->dmadev, debug_area_size,
-				   &host_attr->debug_area_dma_addr,
-				   GFP_KERNEL);
+				   &host_attr->debug_area_dma_addr, GFP_KERNEL);
 	if (unlikely(!host_attr->debug_area_virt_addr)) {
 		host_attr->debug_area_size = 0;
 		return -ENOMEM;
@@ -2736,7 +2782,7 @@
 				   &cmd.u.host_attr.debug_ba,
 				   host_attr->debug_area_dma_addr);
 	if (unlikely(ret)) {
-		pr_err("memory address set failed\n");
+		pr_err("Memory address set failed\n");
 		return ret;
 	}
 
@@ -2744,7 +2790,7 @@
 				   &cmd.u.host_attr.os_info_ba,
 				   host_attr->host_info_dma_addr);
 	if (unlikely(ret)) {
-		pr_err("memory address set failed\n");
+		pr_err("Memory address set failed\n");
 		return ret;
 	}
 
@@ -2863,7 +2909,7 @@
 		(llq_info->descs_num_before_header * sizeof(struct ena_eth_io_tx_desc));
 
 	if (unlikely(ena_dev->tx_max_header_size == 0)) {
-		pr_err("the size of the LLQ entry is smaller than needed\n");
+		pr_err("The size of the LLQ entry is smaller than needed\n");
 		return -EINVAL;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/amazon/ena/ena_com.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/amazon/ena/ena_com.h
@@ -1,33 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
 /*
- * Copyright 2015 Amazon.com, Inc. or its affiliates.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
+ * Copyright 2015-2020 Amazon.com, Inc. or its affiliates. All rights reserved.
  */
 
 #ifndef ENA_COM
@@ -44,6 +17,7 @@
 #include <linux/spinlock.h>
 #include <linux/types.h>
 #include <linux/wait.h>
+#include <linux/netdevice.h>
 
 #include "ena_common_defs.h"
 #include "ena_admin_defs.h"
@@ -53,9 +27,9 @@
 #undef pr_fmt
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-#define ENA_MAX_NUM_IO_QUEUES		128U
+#define ENA_MAX_NUM_IO_QUEUES 128U
 /* We need to queues for each IO (on for Tx and one for Rx) */
-#define ENA_TOTAL_NUM_QUEUES		(2 * (ENA_MAX_NUM_IO_QUEUES))
+#define ENA_TOTAL_NUM_QUEUES (2 * (ENA_MAX_NUM_IO_QUEUES))
 
 #define ENA_MAX_HANDLERS 256
 
@@ -72,13 +46,15 @@
 /*****************************************************************************/
 /* ENA adaptive interrupt moderation settings */
 
-#define ENA_INTR_INITIAL_TX_INTERVAL_USECS		196
-#define ENA_INTR_INITIAL_RX_INTERVAL_USECS		0
-#define ENA_DEFAULT_INTR_DELAY_RESOLUTION		1
+#define ENA_INTR_INITIAL_TX_INTERVAL_USECS 64
+#define ENA_INTR_INITIAL_RX_INTERVAL_USECS 0
+#define ENA_DEFAULT_INTR_DELAY_RESOLUTION 1
+
+#define ENA_HASH_KEY_SIZE 40
 
-#define ENA_HW_HINTS_NO_TIMEOUT				0xFFFF
+#define ENA_HW_HINTS_NO_TIMEOUT	0xFFFF
 
-#define ENA_FEATURE_MAX_QUEUE_EXT_VER	1
+#define ENA_FEATURE_MAX_QUEUE_EXT_VER 1
 
 struct ena_llq_configurations {
 	enum ena_admin_llq_header_location llq_header_location;
@@ -124,6 +100,7 @@
 	u16 descs_num_before_header;
 	u16 descs_per_entry;
 	u16 max_entries_in_tx_burst;
+	bool disable_meta_caching;
 };
 
 struct ena_com_io_cq {
@@ -186,6 +163,8 @@
 	enum queue_direction direction;
 	enum ena_admin_placement_policy_type mem_queue_type;
 
+	bool disable_meta_caching;
+
 	u32 msix_vector;
 	struct ena_com_tx_meta cached_tx_meta;
 	struct ena_com_llq_info llq_info;
@@ -227,15 +206,16 @@
 };
 
 struct ena_com_stats_admin {
-	u32 aborted_cmd;
-	u32 submitted_cmd;
-	u32 completed_cmd;
-	u32 out_of_space;
-	u32 no_completion;
+	u64 aborted_cmd;
+	u64 submitted_cmd;
+	u64 completed_cmd;
+	u64 out_of_space;
+	u64 no_completion;
 };
 
 struct ena_com_admin_queue {
 	void *q_dmadev;
+	struct ena_com_dev *ena_dev;
 	spinlock_t q_lock; /* spinlock for the admin queue */
 
 	struct ena_comp_ctx *comp_ctx;
@@ -348,6 +328,8 @@
 	struct ena_intr_moder_entry *intr_moder_tbl;
 
 	struct ena_com_llq_info llq_info;
+
+	u32 ena_min_poll_delay_us;
 };
 
 struct ena_com_dev_get_features_ctx {
@@ -392,7 +374,7 @@
  */
 int ena_com_mmio_reg_read_request_init(struct ena_com_dev *ena_dev);
 
-/* ena_com_set_mmio_read_mode - Enable/disable the mmio reg read mechanism
+/* ena_com_set_mmio_read_mode - Enable/disable the indirect mmio reg read mechanism
  * @ena_dev: ENA communication layer struct
  * @readless_supported: readless mode (enable/disable)
  */
@@ -500,18 +482,6 @@
  */
 void ena_com_set_admin_polling_mode(struct ena_com_dev *ena_dev, bool polling);
 
-/* ena_com_set_admin_polling_mode - Get the admin completion queue polling mode
- * @ena_dev: ENA communication layer struct
- *
- * Get the admin completion mode.
- * If polling mode is on, ena_com_execute_admin_command will perform a
- * polling on the admin completion queue for the commands completion,
- * otherwise it will wait on wait event.
- *
- * @return state
- */
-bool ena_com_get_ena_admin_polling_mode(struct ena_com_dev *ena_dev);
-
 /* ena_com_set_admin_auto_polling_mode - Enable autoswitch to polling mode
  * @ena_dev: ENA communication layer struct
  * @polling: Enable/Disable polling mode
@@ -526,7 +496,7 @@
 /* ena_com_admin_q_comp_intr_handler - admin queue interrupt handler
  * @ena_dev: ENA communication layer struct
  *
- * This method go over the admin completion queue and wake up all the pending
+ * This method goes over the admin completion queue and wakes up all the pending
  * threads that wait on the commands wait event.
  *
  * @note: Should be called after MSI-X interrupt.
@@ -536,10 +506,10 @@
 /* ena_com_aenq_intr_handler - AENQ interrupt handler
  * @ena_dev: ENA communication layer struct
  *
- * This method go over the async event notification queue and call the proper
+ * This method goes over the async event notification queue and calls the proper
  * aenq handler.
  */
-void ena_com_aenq_intr_handler(struct ena_com_dev *dev, void *data);
+void ena_com_aenq_intr_handler(struct ena_com_dev *ena_dev, void *data);
 
 /* ena_com_abort_admin_commands - Abort all the outstanding admin commands.
  * @ena_dev: ENA communication layer struct
@@ -553,14 +523,14 @@
 /* ena_com_wait_for_abort_completion - Wait for admin commands abort.
  * @ena_dev: ENA communication layer struct
  *
- * This method wait until all the outstanding admin commands will be completed.
+ * This method waits until all the outstanding admin commands are completed.
  */
 void ena_com_wait_for_abort_completion(struct ena_com_dev *ena_dev);
 
 /* ena_com_validate_version - Validate the device parameters
  * @ena_dev: ENA communication layer struct
  *
- * This method validate the device parameters are the same as the saved
+ * This method verifies the device parameters are the same as the saved
  * parameters in ena_dev.
  * This method is useful after device reset, to validate the device mac address
  * and the device offloads are the same as before the reset.
@@ -619,6 +589,15 @@
 int ena_com_get_dev_basic_stats(struct ena_com_dev *ena_dev,
 				struct ena_admin_basic_stats *stats);
 
+/* ena_com_get_eni_stats - Get extended network interface statistics
+ * @ena_dev: ENA communication layer struct
+ * @stats: stats return value
+ *
+ * @return: 0 on Success and negative value otherwise.
+ */
+int ena_com_get_eni_stats(struct ena_com_dev *ena_dev,
+			  struct ena_admin_eni_stats *stats);
+
 /* ena_com_set_dev_mtu - Configure the device mtu.
  * @ena_dev: ENA communication layer struct
  * @mtu: mtu value
@@ -655,6 +634,14 @@
  */
 void ena_com_rss_destroy(struct ena_com_dev *ena_dev);
 
+/* ena_com_get_current_hash_function - Get RSS hash function
+ * @ena_dev: ENA communication layer struct
+ *
+ * Return the current hash function.
+ * @return: 0 or one of the ena_admin_hash_functions values.
+ */
+int ena_com_get_current_hash_function(struct ena_com_dev *ena_dev);
+
 /* ena_com_fill_hash_function - Fill RSS hash function
  * @ena_dev: ENA communication layer struct
  * @func: The hash function (Toeplitz or crc)
@@ -686,23 +673,32 @@
  */
 int ena_com_set_hash_function(struct ena_com_dev *ena_dev);
 
-/* ena_com_get_hash_function - Retrieve the hash function and the hash key
- * from the device.
+/* ena_com_get_hash_function - Retrieve the hash function from the device.
  * @ena_dev: ENA communication layer struct
  * @func: hash function
- * @key: hash key
  *
- * Retrieve the hash function and the hash key from the device.
+ * Retrieve the hash function from the device.
  *
- * @note: If the caller called ena_com_fill_hash_function but didn't flash
+ * @note: If the caller called ena_com_fill_hash_function but didn't flush
  * it to the device, the new configuration will be lost.
  *
  * @return: 0 on Success and negative value otherwise.
  */
 int ena_com_get_hash_function(struct ena_com_dev *ena_dev,
-			      enum ena_admin_hash_functions *func,
-			      u8 *key);
+			      enum ena_admin_hash_functions *func);
 
+/* ena_com_get_hash_key - Retrieve the hash key
+ * @ena_dev: ENA communication layer struct
+ * @key: hash key
+ *
+ * Retrieve the hash key.
+ *
+ * @note: If the caller called ena_com_fill_hash_key but didn't flush
+ * it to the device, the new configuration will be lost.
+ *
+ * @return: 0 on Success and negative value otherwise.
+ */
+int ena_com_get_hash_key(struct ena_com_dev *ena_dev, u8 *key);
 /* ena_com_fill_hash_ctrl - Fill RSS hash control
  * @ena_dev: ENA communication layer struct.
  * @proto: The protocol to configure.
@@ -737,7 +733,7 @@
  *
  * Retrieve the hash control from the device.
  *
- * @note, If the caller called ena_com_fill_hash_ctrl but didn't flash
+ * @note: If the caller called ena_com_fill_hash_ctrl but didn't flush
  * it to the device, the new configuration will be lost.
  *
  * @return: 0 on Success and negative value otherwise.
@@ -789,7 +785,7 @@
  *
  * Retrieve the RSS indirection table from the device.
  *
- * @note: If the caller called ena_com_indirect_table_fill_entry but didn't flash
+ * @note: If the caller called ena_com_indirect_table_fill_entry but didn't flush
  * it to the device, the new configuration will be lost.
  *
  * @return: 0 on Success and negative value otherwise.
@@ -815,14 +811,14 @@
 /* ena_com_delete_debug_area - Free the debug area resources.
  * @ena_dev: ENA communication layer struct
  *
- * Free the allocate debug area.
+ * Free the allocated debug area.
  */
 void ena_com_delete_debug_area(struct ena_com_dev *ena_dev);
 
 /* ena_com_delete_host_info - Free the host info resources.
  * @ena_dev: ENA communication layer struct
  *
- * Free the allocate host info.
+ * Free the allocated host info.
  */
 void ena_com_delete_host_info(struct ena_com_dev *ena_dev);
 
@@ -863,9 +859,9 @@
  * @cmd_completion: command completion return value.
  * @cmd_comp_size: command completion size.
 
- * Submit an admin command and then wait until the device will return a
+ * Submit an admin command and then wait until the device returns a
  * completion.
- * The completion will be copyed into cmd_comp.
+ * The completion will be copied into cmd_comp.
  *
  * @return - 0 on success, negative value on failure.
  */
@@ -928,7 +924,7 @@
 /* ena_com_config_dev_mode - Configure the placement policy of the device.
  * @ena_dev: ENA communication layer struct
  * @llq_features: LLQ feature descriptor, retrieve via
- *                ena_com_get_dev_attr_feat.
+ *		   ena_com_get_dev_attr_feat.
  * @ena_llq_config: The default driver LLQ parameters configurations
  */
 int ena_com_config_dev_mode(struct ena_com_dev *ena_dev,
@@ -954,7 +950,7 @@
  * @intr_reg: interrupt register to update.
  * @rx_delay_interval: Rx interval in usecs
  * @tx_delay_interval: Tx interval in usecs
- * @unmask: unask enable/disable
+ * @unmask: unmask enable/disable
  *
  * Prepare interrupt update register with the supplied parameters.
  */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/amazon/ena/ena_common_defs.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/amazon/ena/ena_common_defs.h
@@ -1,33 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
 /*
- * Copyright 2015 - 2016 Amazon.com, Inc. or its affiliates.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
+ * Copyright 2015-2020 Amazon.com, Inc. or its affiliates. All rights reserved.
  */
 #ifndef _ENA_COMMON_H_
 #define _ENA_COMMON_H_
@@ -45,4 +18,4 @@
 	u16 reserved16;
 };
 
-#endif /*_ENA_COMMON_H_ */
+#endif /* _ENA_COMMON_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/amazon/ena/ena_eth_com.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/amazon/ena/ena_eth_com.c
@@ -1,33 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
 /*
- * Copyright 2015 Amazon.com, Inc. or its affiliates.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
+ * Copyright 2015-2020 Amazon.com, Inc. or its affiliates. All rights reserved.
  */
 
 #include "ena_eth_com.h"
@@ -45,8 +18,9 @@
 	cdesc = (struct ena_eth_io_rx_cdesc_base *)(io_cq->cdesc_addr.virt_addr
 			+ (head_masked * io_cq->cdesc_entry_size_in_bytes));
 
-	desc_phase = (READ_ONCE(cdesc->status) & ENA_ETH_IO_RX_CDESC_BASE_PHASE_MASK) >>
-			ENA_ETH_IO_RX_CDESC_BASE_PHASE_SHIFT;
+	desc_phase = (READ_ONCE(cdesc->status) &
+		      ENA_ETH_IO_RX_CDESC_BASE_PHASE_MASK) >>
+		     ENA_ETH_IO_RX_CDESC_BASE_PHASE_SHIFT;
 
 	if (desc_phase != expected_phase)
 		return NULL;
@@ -89,7 +63,7 @@
 		}
 
 		io_sq->entries_in_tx_burst_left--;
-		pr_debug("decreasing entries_in_tx_burst_left of queue %d to %d\n",
+		pr_debug("Decreasing entries_in_tx_burst_left of queue %d to %d\n",
 			 io_sq->qid, io_sq->entries_in_tx_burst_left);
 	}
 
@@ -128,12 +102,12 @@
 
 	if (unlikely((header_offset + header_len) >
 		     llq_info->desc_list_entry_size)) {
-		pr_err("trying to write header larger than llq entry can accommodate\n");
+		pr_err("Trying to write header larger than llq entry can accommodate\n");
 		return -EFAULT;
 	}
 
 	if (unlikely(!bounce_buffer)) {
-		pr_err("bounce buffer is NULL\n");
+		pr_err("Bounce buffer is NULL\n");
 		return -EFAULT;
 	}
 
@@ -151,7 +125,7 @@
 	bounce_buffer = pkt_ctrl->curr_bounce_buf;
 
 	if (unlikely(!bounce_buffer)) {
-		pr_err("bounce buffer is NULL\n");
+		pr_err("Bounce buffer is NULL\n");
 		return NULL;
 	}
 
@@ -262,8 +236,9 @@
 
 		ena_com_cq_inc_head(io_cq);
 		count++;
-		last = (READ_ONCE(cdesc->status) & ENA_ETH_IO_RX_CDESC_BASE_LAST_MASK) >>
-			ENA_ETH_IO_RX_CDESC_BASE_LAST_SHIFT;
+		last = (READ_ONCE(cdesc->status) &
+			ENA_ETH_IO_RX_CDESC_BASE_LAST_MASK) >>
+		       ENA_ETH_IO_RX_CDESC_BASE_LAST_SHIFT;
 	} while (!last);
 
 	if (last) {
@@ -275,7 +250,7 @@
 		io_cq->cur_rx_pkt_cdesc_count = 0;
 		io_cq->cur_rx_pkt_cdesc_start_idx = head_masked;
 
-		pr_debug("ena q_id: %d packets were completed. first desc idx %u descs# %d\n",
+		pr_debug("ENA q_id: %d packets were completed. first desc idx %u descs# %d\n",
 			 io_cq->qid, *first_cdesc_idx, count);
 	} else {
 		io_cq->cur_rx_pkt_cdesc_count += count;
@@ -285,13 +260,15 @@
 	return count;
 }
 
-static int ena_com_create_and_store_tx_meta_desc(struct ena_com_io_sq *io_sq,
-							struct ena_com_tx_ctx *ena_tx_ctx)
+static int ena_com_create_meta(struct ena_com_io_sq *io_sq,
+			       struct ena_com_tx_meta *ena_meta)
 {
 	struct ena_eth_io_tx_meta_desc *meta_desc = NULL;
-	struct ena_com_tx_meta *ena_meta = &ena_tx_ctx->ena_meta;
 
 	meta_desc = get_sq_desc(io_sq);
+	if (unlikely(!meta_desc))
+		return -EFAULT;
+
 	memset(meta_desc, 0x0, sizeof(struct ena_eth_io_tx_meta_desc));
 
 	meta_desc->len_ctrl |= ENA_ETH_IO_TX_META_DESC_META_DESC_MASK;
@@ -299,7 +276,7 @@
 	meta_desc->len_ctrl |= ENA_ETH_IO_TX_META_DESC_EXT_VALID_MASK;
 
 	/* bits 0-9 of the mss */
-	meta_desc->word2 |= (ena_meta->mss <<
+	meta_desc->word2 |= ((u32)ena_meta->mss <<
 		ENA_ETH_IO_TX_META_DESC_MSS_LO_SHIFT) &
 		ENA_ETH_IO_TX_META_DESC_MSS_LO_MASK;
 	/* bits 10-13 of the mss */
@@ -309,33 +286,57 @@
 
 	/* Extended meta desc */
 	meta_desc->len_ctrl |= ENA_ETH_IO_TX_META_DESC_ETH_META_TYPE_MASK;
-	meta_desc->len_ctrl |= ENA_ETH_IO_TX_META_DESC_META_STORE_MASK;
-	meta_desc->len_ctrl |= (io_sq->phase <<
+	meta_desc->len_ctrl |= ((u32)io_sq->phase <<
 		ENA_ETH_IO_TX_META_DESC_PHASE_SHIFT) &
 		ENA_ETH_IO_TX_META_DESC_PHASE_MASK;
 
 	meta_desc->len_ctrl |= ENA_ETH_IO_TX_META_DESC_FIRST_MASK;
+	meta_desc->len_ctrl |= ENA_ETH_IO_TX_META_DESC_META_STORE_MASK;
+
 	meta_desc->word2 |= ena_meta->l3_hdr_len &
 		ENA_ETH_IO_TX_META_DESC_L3_HDR_LEN_MASK;
 	meta_desc->word2 |= (ena_meta->l3_hdr_offset <<
 		ENA_ETH_IO_TX_META_DESC_L3_HDR_OFF_SHIFT) &
 		ENA_ETH_IO_TX_META_DESC_L3_HDR_OFF_MASK;
 
-	meta_desc->word2 |= (ena_meta->l4_hdr_len <<
+	meta_desc->word2 |= ((u32)ena_meta->l4_hdr_len <<
 		ENA_ETH_IO_TX_META_DESC_L4_HDR_LEN_IN_WORDS_SHIFT) &
 		ENA_ETH_IO_TX_META_DESC_L4_HDR_LEN_IN_WORDS_MASK;
 
-	meta_desc->len_ctrl |= ENA_ETH_IO_TX_META_DESC_META_STORE_MASK;
+	return ena_com_sq_update_tail(io_sq);
+}
 
-	/* Cached the meta desc */
-	memcpy(&io_sq->cached_tx_meta, ena_meta,
-	       sizeof(struct ena_com_tx_meta));
+static int ena_com_create_and_store_tx_meta_desc(struct ena_com_io_sq *io_sq,
+						 struct ena_com_tx_ctx *ena_tx_ctx,
+						 bool *have_meta)
+{
+	struct ena_com_tx_meta *ena_meta = &ena_tx_ctx->ena_meta;
 
-	return ena_com_sq_update_tail(io_sq);
+	/* When disable meta caching is set, don't bother to save the meta and
+	 * compare it to the stored version, just create the meta
+	 */
+	if (io_sq->disable_meta_caching) {
+		if (unlikely(!ena_tx_ctx->meta_valid))
+			return -EINVAL;
+
+		*have_meta = true;
+		return ena_com_create_meta(io_sq, ena_meta);
+	}
+
+	if (ena_com_meta_desc_changed(io_sq, ena_tx_ctx)) {
+		*have_meta = true;
+		/* Cache the meta desc */
+		memcpy(&io_sq->cached_tx_meta, ena_meta,
+		       sizeof(struct ena_com_tx_meta));
+		return ena_com_create_meta(io_sq, ena_meta);
+	}
+
+	*have_meta = false;
+	return 0;
 }
 
 static void ena_com_rx_set_flags(struct ena_com_rx_ctx *ena_rx_ctx,
-					struct ena_eth_io_rx_cdesc_base *cdesc)
+				 struct ena_eth_io_rx_cdesc_base *cdesc)
 {
 	ena_rx_ctx->l3_proto = cdesc->status &
 		ENA_ETH_IO_RX_CDESC_BASE_L3_PROTO_IDX_MASK;
@@ -356,7 +357,7 @@
 		(cdesc->status & ENA_ETH_IO_RX_CDESC_BASE_IPV4_FRAG_MASK) >>
 		ENA_ETH_IO_RX_CDESC_BASE_IPV4_FRAG_SHIFT;
 
-	pr_debug("ena_rx_ctx->l3_proto %d ena_rx_ctx->l4_proto %d\nena_rx_ctx->l3_csum_err %d ena_rx_ctx->l4_csum_err %d\nhash frag %d frag: %d cdesc_status: %x\n",
+	pr_debug("l3_proto %d l4_proto %d l3_csum_err %d l4_csum_err %d hash %d frag %d cdesc_status %x\n",
 		 ena_rx_ctx->l3_proto, ena_rx_ctx->l4_proto,
 		 ena_rx_ctx->l3_csum_err, ena_rx_ctx->l4_csum_err,
 		 ena_rx_ctx->hash, ena_rx_ctx->frag, cdesc->status);
@@ -389,7 +390,7 @@
 	}
 
 	if (unlikely(header_len > io_sq->tx_max_header_size)) {
-		pr_err("header size is too large %d max header: %d\n",
+		pr_err("Header size is too large %d max header: %d\n",
 		       header_len, io_sq->tx_max_header_size);
 		return -EINVAL;
 	}
@@ -402,12 +403,10 @@
 	if (unlikely(rc))
 		return rc;
 
-	have_meta = ena_tx_ctx->meta_valid && ena_com_meta_desc_changed(io_sq,
-			ena_tx_ctx);
-	if (have_meta) {
-		rc = ena_com_create_and_store_tx_meta_desc(io_sq, ena_tx_ctx);
-		if (unlikely(rc))
-			return rc;
+	rc = ena_com_create_and_store_tx_meta_desc(io_sq, ena_tx_ctx, &have_meta);
+	if (unlikely(rc)) {
+		pr_err("Failed to create and store tx meta desc\n");
+		return rc;
 	}
 
 	/* If the caller doesn't want to send packets */
@@ -426,16 +425,16 @@
 	if (!have_meta)
 		desc->len_ctrl |= ENA_ETH_IO_TX_DESC_FIRST_MASK;
 
-	desc->buff_addr_hi_hdr_sz |= (header_len <<
+	desc->buff_addr_hi_hdr_sz |= ((u32)header_len <<
 		ENA_ETH_IO_TX_DESC_HEADER_LENGTH_SHIFT) &
 		ENA_ETH_IO_TX_DESC_HEADER_LENGTH_MASK;
-	desc->len_ctrl |= (io_sq->phase << ENA_ETH_IO_TX_DESC_PHASE_SHIFT) &
+	desc->len_ctrl |= ((u32)io_sq->phase << ENA_ETH_IO_TX_DESC_PHASE_SHIFT) &
 		ENA_ETH_IO_TX_DESC_PHASE_MASK;
 
 	desc->len_ctrl |= ENA_ETH_IO_TX_DESC_COMP_REQ_MASK;
 
 	/* Bits 0-9 */
-	desc->meta_ctrl |= (ena_tx_ctx->req_id <<
+	desc->meta_ctrl |= ((u32)ena_tx_ctx->req_id <<
 		ENA_ETH_IO_TX_DESC_REQ_ID_LO_SHIFT) &
 		ENA_ETH_IO_TX_DESC_REQ_ID_LO_MASK;
 
@@ -481,7 +480,7 @@
 
 			memset(desc, 0x0, sizeof(struct ena_eth_io_tx_desc));
 
-			desc->len_ctrl |= (io_sq->phase <<
+			desc->len_ctrl |= ((u32)io_sq->phase <<
 				ENA_ETH_IO_TX_DESC_PHASE_SHIFT) &
 				ENA_ETH_IO_TX_DESC_PHASE_MASK;
 		}
@@ -517,9 +516,10 @@
 {
 	struct ena_com_rx_buf_info *ena_buf = &ena_rx_ctx->ena_bufs[0];
 	struct ena_eth_io_rx_cdesc_base *cdesc = NULL;
+	u16 q_depth = io_cq->q_depth;
 	u16 cdesc_idx = 0;
 	u16 nb_hw_desc;
-	u16 i;
+	u16 i = 0;
 
 	WARN(io_cq->direction != ENA_COM_IO_QUEUE_DIRECTION_RX, "wrong Q type");
 
@@ -529,7 +529,7 @@
 		return 0;
 	}
 
-	pr_debug("fetch rx packet: queue %d completed desc: %d\n", io_cq->qid,
+	pr_debug("Fetch rx packet: queue %d completed desc: %d\n", io_cq->qid,
 		 nb_hw_desc);
 
 	if (unlikely(nb_hw_desc > ena_rx_ctx->max_bufs)) {
@@ -538,13 +538,21 @@
 		return -ENOSPC;
 	}
 
-	for (i = 0; i < nb_hw_desc; i++) {
+	cdesc = ena_com_rx_cdesc_idx_to_ptr(io_cq, cdesc_idx);
+	ena_rx_ctx->pkt_offset = cdesc->offset;
+
+	do {
+		ena_buf[i].len = cdesc->length;
+		ena_buf[i].req_id = cdesc->req_id;
+		if (unlikely(ena_buf[i].req_id >= q_depth))
+			return -EIO;
+
+		if (++i >= nb_hw_desc)
+			break;
+
 		cdesc = ena_com_rx_cdesc_idx_to_ptr(io_cq, cdesc_idx + i);
 
-		ena_buf->len = cdesc->length;
-		ena_buf->req_id = cdesc->req_id;
-		ena_buf++;
-	}
+	} while (1);
 
 	/* Update SQ head ptr */
 	io_sq->next_to_comp += nb_hw_desc;
@@ -578,10 +586,10 @@
 
 	desc->length = ena_buf->len;
 
-	desc->ctrl = ENA_ETH_IO_RX_DESC_FIRST_MASK;
-	desc->ctrl |= ENA_ETH_IO_RX_DESC_LAST_MASK;
-	desc->ctrl |= io_sq->phase & ENA_ETH_IO_RX_DESC_PHASE_MASK;
-	desc->ctrl |= ENA_ETH_IO_RX_DESC_COMP_REQ_MASK;
+	desc->ctrl = ENA_ETH_IO_RX_DESC_FIRST_MASK |
+		     ENA_ETH_IO_RX_DESC_LAST_MASK |
+		     (io_sq->phase & ENA_ETH_IO_RX_DESC_PHASE_MASK) |
+		     ENA_ETH_IO_RX_DESC_COMP_REQ_MASK;
 
 	desc->req_id = req_id;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/amazon/ena/ena_eth_com.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/amazon/ena/ena_eth_com.h
@@ -1,33 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
 /*
- * Copyright 2015 Amazon.com, Inc. or its affiliates.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
+ * Copyright 2015-2020 Amazon.com, Inc. or its affiliates. All rights reserved.
  */
 
 #ifndef ENA_ETH_COM_H_
@@ -73,6 +46,7 @@
 	u32 hash;
 	u16 descs;
 	int max_bufs;
+	u8 pkt_offset;
 };
 
 int ena_com_prepare_tx(struct ena_com_io_sq *io_sq,
@@ -95,7 +69,7 @@
 	writel(intr_reg->intr_control, io_cq->unmask_reg);
 }
 
-static inline int ena_com_free_desc(struct ena_com_io_sq *io_sq)
+static inline int ena_com_free_q_entries(struct ena_com_io_sq *io_sq)
 {
 	u16 tail, next_to_comp, cnt;
 
@@ -113,7 +87,7 @@
 	int temp;
 
 	if (io_sq->mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_HOST)
-		return ena_com_free_desc(io_sq) >= required_buffers;
+		return ena_com_free_q_entries(io_sq) >= required_buffers;
 
 	/* This calculation doesn't need to be 100% accurate. So to reduce
 	 * the calculation overhead just Subtract 2 lines from the free descs
@@ -122,7 +96,7 @@
 	 */
 	temp = required_buffers / io_sq->llq_info.descs_per_entry + 2;
 
-	return ena_com_free_desc(io_sq) > temp;
+	return ena_com_free_q_entries(io_sq) > temp;
 }
 
 static inline bool ena_com_meta_desc_changed(struct ena_com_io_sq *io_sq,
@@ -156,7 +130,8 @@
 	llq_info = &io_sq->llq_info;
 	num_descs = ena_tx_ctx->num_bufs;
 
-	if (unlikely(ena_com_meta_desc_changed(io_sq, ena_tx_ctx)))
+	if (llq_info->disable_meta_caching ||
+	    unlikely(ena_com_meta_desc_changed(io_sq, ena_tx_ctx)))
 		++num_descs;
 
 	if (num_descs > llq_info->descs_num_before_header) {
@@ -165,7 +140,7 @@
 						   llq_info->descs_per_entry);
 	}
 
-	pr_debug("queue: %d num_descs: %d num_entries_needed: %d\n", io_sq->qid,
+	pr_debug("Queue: %d num_descs: %d num_entries_needed: %d\n", io_sq->qid,
 		 num_descs, num_entries_needed);
 
 	return num_entries_needed > io_sq->entries_in_tx_burst_left;
@@ -176,13 +151,13 @@
 	u16 max_entries_in_tx_burst = io_sq->llq_info.max_entries_in_tx_burst;
 	u16 tail = io_sq->tail;
 
-	pr_debug("write submission queue doorbell for queue: %d tail: %d\n",
+	pr_debug("Write submission queue doorbell for queue: %d tail: %d\n",
 		 io_sq->qid, tail);
 
 	writel(tail, io_sq->db_addr);
 
 	if (is_llq_max_tx_burst_exists(io_sq)) {
-		pr_debug("reset available entries in tx burst for queue %d to %d\n",
+		pr_debug("Reset available entries in tx burst for queue %d to %d\n",
 			 io_sq->qid, max_entries_in_tx_burst);
 		io_sq->entries_in_tx_burst_left = max_entries_in_tx_burst;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/amazon/ena/ena_eth_io_defs.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/amazon/ena/ena_eth_io_defs.h
@@ -1,33 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
 /*
- * Copyright 2015 - 2016 Amazon.com, Inc. or its affiliates.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
+ * Copyright 2015-2020 Amazon.com, Inc. or its affiliates. All rights reserved.
  */
 #ifndef _ENA_ETH_IO_H_
 #define _ENA_ETH_IO_H_
@@ -264,7 +237,9 @@
 
 	u16 sub_qid;
 
-	u16 reserved;
+	u8 offset;
+
+	u8 reserved;
 };
 
 /* 8-word format */
@@ -412,4 +387,4 @@
 #define ENA_ETH_IO_NUMA_NODE_CFG_REG_ENABLED_SHIFT          31
 #define ENA_ETH_IO_NUMA_NODE_CFG_REG_ENABLED_MASK           BIT(31)
 
-#endif /*_ENA_ETH_IO_H_ */
+#endif /* _ENA_ETH_IO_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/amazon/ena/ena_ethtool.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/amazon/ena/ena_ethtool.c
@@ -1,33 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
 /*
- * Copyright 2015 Amazon.com, Inc. or its affiliates.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
+ * Copyright 2015-2020 Amazon.com, Inc. or its affiliates. All rights reserved.
  */
 
 #include <linux/pci.h>
@@ -41,12 +14,17 @@
 
 #define ENA_STAT_ENA_COM_ENTRY(stat) { \
 	.name = #stat, \
-	.stat_offset = offsetof(struct ena_com_stats_admin, stat) \
+	.stat_offset = offsetof(struct ena_com_stats_admin, stat) / sizeof(u64) \
 }
 
 #define ENA_STAT_ENTRY(stat, stat_type) { \
 	.name = #stat, \
-	.stat_offset = offsetof(struct ena_stats_##stat_type, stat) \
+	.stat_offset = offsetof(struct ena_stats_##stat_type, stat) / sizeof(u64) \
+}
+
+#define ENA_STAT_HW_ENTRY(stat, stat_type) { \
+	.name = #stat, \
+	.stat_offset = offsetof(struct ena_admin_##stat_type, stat) / sizeof(u64) \
 }
 
 #define ENA_STAT_RX_ENTRY(stat) \
@@ -58,6 +36,9 @@
 #define ENA_STAT_GLOBAL_ENTRY(stat) \
 	ENA_STAT_ENTRY(stat, dev)
 
+#define ENA_STAT_ENI_ENTRY(stat) \
+	ENA_STAT_HW_ENTRY(stat, eni_stats)
+
 static const struct ena_stats ena_stats_global_strings[] = {
 	ENA_STAT_GLOBAL_ENTRY(tx_timeout),
 	ENA_STAT_GLOBAL_ENTRY(suspend),
@@ -68,6 +49,14 @@
 	ENA_STAT_GLOBAL_ENTRY(admin_q_pause),
 };
 
+static const struct ena_stats ena_stats_eni_strings[] = {
+	ENA_STAT_ENI_ENTRY(bw_in_allowance_exceeded),
+	ENA_STAT_ENI_ENTRY(bw_out_allowance_exceeded),
+	ENA_STAT_ENI_ENTRY(pps_allowance_exceeded),
+	ENA_STAT_ENI_ENTRY(conntrack_allowance_exceeded),
+	ENA_STAT_ENI_ENTRY(linklocal_allowance_exceeded),
+};
+
 static const struct ena_stats ena_stats_tx_strings[] = {
 	ENA_STAT_TX_ENTRY(cnt),
 	ENA_STAT_TX_ENTRY(bytes),
@@ -83,6 +72,7 @@
 	ENA_STAT_TX_ENTRY(bad_req_id),
 	ENA_STAT_TX_ENTRY(llq_buffer_copy),
 	ENA_STAT_TX_ENTRY(missed_tx),
+	ENA_STAT_TX_ENTRY(unmask_interrupt),
 };
 
 static const struct ena_stats ena_stats_rx_strings[] = {
@@ -99,6 +89,11 @@
 	ENA_STAT_RX_ENTRY(bad_req_id),
 	ENA_STAT_RX_ENTRY(empty_rx_ring),
 	ENA_STAT_RX_ENTRY(csum_unchecked),
+	ENA_STAT_RX_ENTRY(xdp_aborted),
+	ENA_STAT_RX_ENTRY(xdp_drop),
+	ENA_STAT_RX_ENTRY(xdp_pass),
+	ENA_STAT_RX_ENTRY(xdp_tx),
+	ENA_STAT_RX_ENTRY(xdp_invalid),
 };
 
 static const struct ena_stats ena_stats_ena_com_strings[] = {
@@ -109,10 +104,12 @@
 	ENA_STAT_ENA_COM_ENTRY(no_completion),
 };
 
-#define ENA_STATS_ARRAY_GLOBAL	ARRAY_SIZE(ena_stats_global_strings)
-#define ENA_STATS_ARRAY_TX	ARRAY_SIZE(ena_stats_tx_strings)
-#define ENA_STATS_ARRAY_RX	ARRAY_SIZE(ena_stats_rx_strings)
-#define ENA_STATS_ARRAY_ENA_COM	ARRAY_SIZE(ena_stats_ena_com_strings)
+#define ENA_STATS_ARRAY_GLOBAL		ARRAY_SIZE(ena_stats_global_strings)
+#define ENA_STATS_ARRAY_TX		ARRAY_SIZE(ena_stats_tx_strings)
+#define ENA_STATS_ARRAY_RX		ARRAY_SIZE(ena_stats_rx_strings)
+#define ENA_STATS_ARRAY_ENA_COM		ARRAY_SIZE(ena_stats_ena_com_strings)
+#define ENA_STATS_ARRAY_ENI(adapter)	\
+	(ARRAY_SIZE(ena_stats_eni_strings) * (adapter)->eni_stats_supported)
 
 static void ena_safe_update_stat(u64 *src, u64 *dst,
 				 struct u64_stats_sync *syncp)
@@ -133,29 +130,30 @@
 	u64 *ptr;
 	int i, j;
 
-	for (i = 0; i < adapter->num_queues; i++) {
+	for (i = 0; i < adapter->num_io_queues + adapter->xdp_num_queues; i++) {
 		/* Tx stats */
 		ring = &adapter->tx_ring[i];
 
 		for (j = 0; j < ENA_STATS_ARRAY_TX; j++) {
 			ena_stats = &ena_stats_tx_strings[j];
 
-			ptr = (u64 *)((uintptr_t)&ring->tx_stats +
-				(uintptr_t)ena_stats->stat_offset);
+			ptr = (u64 *)&ring->tx_stats + ena_stats->stat_offset;
 
 			ena_safe_update_stat(ptr, (*data)++, &ring->syncp);
 		}
+		/* XDP TX queues don't have a RX queue counterpart */
+		if (!ENA_IS_XDP_INDEX(adapter, i)) {
+			/* Rx stats */
+			ring = &adapter->rx_ring[i];
 
-		/* Rx stats */
-		ring = &adapter->rx_ring[i];
-
-		for (j = 0; j < ENA_STATS_ARRAY_RX; j++) {
-			ena_stats = &ena_stats_rx_strings[j];
+			for (j = 0; j < ENA_STATS_ARRAY_RX; j++) {
+				ena_stats = &ena_stats_rx_strings[j];
 
-			ptr = (u64 *)((uintptr_t)&ring->rx_stats +
-				(uintptr_t)ena_stats->stat_offset);
+				ptr = (u64 *)&ring->rx_stats +
+					ena_stats->stat_offset;
 
-			ena_safe_update_stat(ptr, (*data)++, &ring->syncp);
+				ena_safe_update_stat(ptr, (*data)++, &ring->syncp);
+			}
 		}
 	}
 }
@@ -163,24 +161,23 @@
 static void ena_dev_admin_queue_stats(struct ena_adapter *adapter, u64 **data)
 {
 	const struct ena_stats *ena_stats;
-	u32 *ptr;
+	u64 *ptr;
 	int i;
 
 	for (i = 0; i < ENA_STATS_ARRAY_ENA_COM; i++) {
 		ena_stats = &ena_stats_ena_com_strings[i];
 
-		ptr = (u32 *)((uintptr_t)&adapter->ena_dev->admin_queue.stats +
-			(uintptr_t)ena_stats->stat_offset);
+		ptr = (u64 *)&adapter->ena_dev->admin_queue.stats +
+			ena_stats->stat_offset;
 
 		*(*data)++ = *ptr;
 	}
 }
 
-static void ena_get_ethtool_stats(struct net_device *netdev,
-				  struct ethtool_stats *stats,
-				  u64 *data)
+static void ena_get_stats(struct ena_adapter *adapter,
+			  u64 *data,
+			  bool eni_stats_needed)
 {
-	struct ena_adapter *adapter = netdev_priv(netdev);
 	const struct ena_stats *ena_stats;
 	u64 *ptr;
 	int i;
@@ -188,16 +185,48 @@
 	for (i = 0; i < ENA_STATS_ARRAY_GLOBAL; i++) {
 		ena_stats = &ena_stats_global_strings[i];
 
-		ptr = (u64 *)((uintptr_t)&adapter->dev_stats +
-			(uintptr_t)ena_stats->stat_offset);
+		ptr = (u64 *)&adapter->dev_stats + ena_stats->stat_offset;
 
 		ena_safe_update_stat(ptr, data++, &adapter->syncp);
 	}
 
+	if (eni_stats_needed) {
+		ena_update_hw_stats(adapter);
+		for (i = 0; i < ENA_STATS_ARRAY_ENI(adapter); i++) {
+			ena_stats = &ena_stats_eni_strings[i];
+
+			ptr = (u64 *)&adapter->eni_stats +
+				ena_stats->stat_offset;
+
+			ena_safe_update_stat(ptr, data++, &adapter->syncp);
+		}
+	}
+
 	ena_queue_stats(adapter, &data);
 	ena_dev_admin_queue_stats(adapter, &data);
 }
 
+static void ena_get_ethtool_stats(struct net_device *netdev,
+				  struct ethtool_stats *stats,
+				  u64 *data)
+{
+	struct ena_adapter *adapter = netdev_priv(netdev);
+
+	ena_get_stats(adapter, data, adapter->eni_stats_supported);
+}
+
+static int ena_get_sw_stats_count(struct ena_adapter *adapter)
+{
+	return adapter->num_io_queues * (ENA_STATS_ARRAY_TX + ENA_STATS_ARRAY_RX)
+		+ adapter->xdp_num_queues * ENA_STATS_ARRAY_TX
+		+ ENA_STATS_ARRAY_GLOBAL + ENA_STATS_ARRAY_ENA_COM;
+}
+
+static int ena_get_hw_stats_count(struct ena_adapter *adapter)
+{
+	return ENA_STATS_ARRAY_ENI(adapter);
+}
+
 int ena_get_sset_count(struct net_device *netdev, int sset)
 {
 	struct ena_adapter *adapter = netdev_priv(netdev);
@@ -205,31 +234,38 @@
 	if (sset != ETH_SS_STATS)
 		return -EOPNOTSUPP;
 
-	return  adapter->num_queues * (ENA_STATS_ARRAY_TX + ENA_STATS_ARRAY_RX)
-		+ ENA_STATS_ARRAY_GLOBAL + ENA_STATS_ARRAY_ENA_COM;
+	return ena_get_sw_stats_count(adapter) + ena_get_hw_stats_count(adapter);
 }
 
 static void ena_queue_strings(struct ena_adapter *adapter, u8 **data)
 {
 	const struct ena_stats *ena_stats;
+	bool is_xdp;
 	int i, j;
 
-	for (i = 0; i < adapter->num_queues; i++) {
+	for (i = 0; i < adapter->num_io_queues + adapter->xdp_num_queues; i++) {
+		is_xdp = ENA_IS_XDP_INDEX(adapter, i);
 		/* Tx stats */
 		for (j = 0; j < ENA_STATS_ARRAY_TX; j++) {
 			ena_stats = &ena_stats_tx_strings[j];
 
 			snprintf(*data, ETH_GSTRING_LEN,
-				 "queue_%u_tx_%s", i, ena_stats->name);
-			 (*data) += ETH_GSTRING_LEN;
+				 "queue_%u_%s_%s", i,
+				 is_xdp ? "xdp_tx" : "tx", ena_stats->name);
+			(*data) += ETH_GSTRING_LEN;
 		}
-		/* Rx stats */
-		for (j = 0; j < ENA_STATS_ARRAY_RX; j++) {
-			ena_stats = &ena_stats_rx_strings[j];
 
-			snprintf(*data, ETH_GSTRING_LEN,
-				 "queue_%u_rx_%s", i, ena_stats->name);
-			(*data) += ETH_GSTRING_LEN;
+		if (!is_xdp) {
+			/* RX stats, in XDP there isn't a RX queue
+			 * counterpart
+			 */
+			for (j = 0; j < ENA_STATS_ARRAY_RX; j++) {
+				ena_stats = &ena_stats_rx_strings[j];
+
+				snprintf(*data, ETH_GSTRING_LEN,
+					 "queue_%u_rx_%s", i, ena_stats->name);
+				(*data) += ETH_GSTRING_LEN;
+			}
 		}
 	}
 }
@@ -248,26 +284,43 @@
 	}
 }
 
-static void ena_get_strings(struct net_device *netdev, u32 sset, u8 *data)
+static void ena_get_strings(struct ena_adapter *adapter,
+			    u8 *data,
+			    bool eni_stats_needed)
 {
-	struct ena_adapter *adapter = netdev_priv(netdev);
 	const struct ena_stats *ena_stats;
 	int i;
 
-	if (sset != ETH_SS_STATS)
-		return;
-
 	for (i = 0; i < ENA_STATS_ARRAY_GLOBAL; i++) {
 		ena_stats = &ena_stats_global_strings[i];
-
 		memcpy(data, ena_stats->name, ETH_GSTRING_LEN);
 		data += ETH_GSTRING_LEN;
 	}
 
+	if (eni_stats_needed) {
+		for (i = 0; i < ENA_STATS_ARRAY_ENI(adapter); i++) {
+			ena_stats = &ena_stats_eni_strings[i];
+			memcpy(data, ena_stats->name, ETH_GSTRING_LEN);
+			data += ETH_GSTRING_LEN;
+		}
+	}
+
 	ena_queue_strings(adapter, &data);
 	ena_com_dev_strings(&data);
 }
 
+static void ena_get_ethtool_strings(struct net_device *netdev,
+				    u32 sset,
+				    u8 *data)
+{
+	struct ena_adapter *adapter = netdev_priv(netdev);
+
+	if (sset != ETH_SS_STATS)
+		return;
+
+	ena_get_strings(adapter, data, adapter->eni_stats_supported);
+}
+
 static int ena_get_link_ksettings(struct net_device *netdev,
 				  struct ethtool_link_ksettings *link_ksettings)
 {
@@ -306,19 +359,16 @@
 	struct ena_adapter *adapter = netdev_priv(net_dev);
 	struct ena_com_dev *ena_dev = adapter->ena_dev;
 
-	if (!ena_com_interrupt_moderation_supported(ena_dev)) {
-		/* the devie doesn't support interrupt moderation */
+	if (!ena_com_interrupt_moderation_supported(ena_dev))
 		return -EOPNOTSUPP;
-	}
 
 	coalesce->tx_coalesce_usecs =
 		ena_com_get_nonadaptive_moderation_interval_tx(ena_dev) *
 			ena_dev->intr_delay_resolution;
 
-	if (!ena_com_get_adaptive_moderation_enabled(ena_dev))
-		coalesce->rx_coalesce_usecs =
-			ena_com_get_nonadaptive_moderation_interval_rx(ena_dev)
-			* ena_dev->intr_delay_resolution;
+	coalesce->rx_coalesce_usecs =
+		ena_com_get_nonadaptive_moderation_interval_rx(ena_dev)
+		* ena_dev->intr_delay_resolution;
 
 	coalesce->use_adaptive_rx_coalesce =
 		ena_com_get_adaptive_moderation_enabled(ena_dev);
@@ -326,25 +376,25 @@
 	return 0;
 }
 
-static void ena_update_tx_rings_intr_moderation(struct ena_adapter *adapter)
+static void ena_update_tx_rings_nonadaptive_intr_moderation(struct ena_adapter *adapter)
 {
 	unsigned int val;
 	int i;
 
 	val = ena_com_get_nonadaptive_moderation_interval_tx(adapter->ena_dev);
 
-	for (i = 0; i < adapter->num_queues; i++)
+	for (i = 0; i < adapter->num_io_queues; i++)
 		adapter->tx_ring[i].smoothed_interval = val;
 }
 
-static void ena_update_rx_rings_intr_moderation(struct ena_adapter *adapter)
+static void ena_update_rx_rings_nonadaptive_intr_moderation(struct ena_adapter *adapter)
 {
 	unsigned int val;
 	int i;
 
 	val = ena_com_get_nonadaptive_moderation_interval_rx(adapter->ena_dev);
 
-	for (i = 0; i < adapter->num_queues; i++)
+	for (i = 0; i < adapter->num_io_queues; i++)
 		adapter->rx_ring[i].smoothed_interval = val;
 }
 
@@ -355,35 +405,30 @@
 	struct ena_com_dev *ena_dev = adapter->ena_dev;
 	int rc;
 
-	if (!ena_com_interrupt_moderation_supported(ena_dev)) {
-		/* the devie doesn't support interrupt moderation */
+	if (!ena_com_interrupt_moderation_supported(ena_dev))
 		return -EOPNOTSUPP;
-	}
 
 	rc = ena_com_update_nonadaptive_moderation_interval_tx(ena_dev,
 							       coalesce->tx_coalesce_usecs);
 	if (rc)
 		return rc;
 
-	ena_update_tx_rings_intr_moderation(adapter);
-
-	if (coalesce->use_adaptive_rx_coalesce) {
-		if (!ena_com_get_adaptive_moderation_enabled(ena_dev))
-			ena_com_enable_adaptive_moderation(ena_dev);
-		return 0;
-	}
+	ena_update_tx_rings_nonadaptive_intr_moderation(adapter);
 
 	rc = ena_com_update_nonadaptive_moderation_interval_rx(ena_dev,
 							       coalesce->rx_coalesce_usecs);
 	if (rc)
 		return rc;
 
-	ena_update_rx_rings_intr_moderation(adapter);
+	ena_update_rx_rings_nonadaptive_intr_moderation(adapter);
 
-	if (!coalesce->use_adaptive_rx_coalesce) {
-		if (ena_com_get_adaptive_moderation_enabled(ena_dev))
-			ena_com_disable_adaptive_moderation(ena_dev);
-	}
+	if ((coalesce->use_adaptive_rx_coalesce) &&
+	    (!ena_com_get_adaptive_moderation_enabled(ena_dev)))
+		ena_com_enable_adaptive_moderation(ena_dev);
+
+	if ((!coalesce->use_adaptive_rx_coalesce) &&
+	    (ena_com_get_adaptive_moderation_enabled(ena_dev)))
+		ena_com_disable_adaptive_moderation(ena_dev);
 
 	return 0;
 }
@@ -408,7 +453,6 @@
 	struct ena_adapter *adapter = netdev_priv(dev);
 
 	strlcpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
-	strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version));
 	strlcpy(info->bus_info, pci_name(adapter->pdev),
 		sizeof(info->bus_info));
 }
@@ -612,7 +656,7 @@
 
 	switch (info->cmd) {
 	case ETHTOOL_GRXRINGS:
-		info->data = adapter->num_queues;
+		info->data = adapter->num_io_queues;
 		rc = 0;
 		break;
 	case ETHTOOL_GRXFH:
@@ -640,6 +684,54 @@
 	return ENA_HASH_KEY_SIZE;
 }
 
+static int ena_indirection_table_set(struct ena_adapter *adapter,
+				     const u32 *indir)
+{
+	struct ena_com_dev *ena_dev = adapter->ena_dev;
+	int i, rc;
+
+	for (i = 0; i < ENA_RX_RSS_TABLE_SIZE; i++) {
+		rc = ena_com_indirect_table_fill_entry(ena_dev,
+						       i,
+						       ENA_IO_RXQ_IDX(indir[i]));
+		if (unlikely(rc)) {
+			netif_err(adapter, drv, adapter->netdev,
+				  "Cannot fill indirect table (index is too large)\n");
+			return rc;
+		}
+	}
+
+	rc = ena_com_indirect_table_set(ena_dev);
+	if (rc) {
+		netif_err(adapter, drv, adapter->netdev,
+			  "Cannot set indirect table\n");
+		return rc == -EPERM ? -EOPNOTSUPP : rc;
+	}
+	return rc;
+}
+
+static int ena_indirection_table_get(struct ena_adapter *adapter, u32 *indir)
+{
+	struct ena_com_dev *ena_dev = adapter->ena_dev;
+	int i, rc;
+
+	if (!indir)
+		return 0;
+
+	rc = ena_com_indirect_table_get(ena_dev, indir);
+	if (rc)
+		return rc;
+
+	/* Our internal representation of the indices is: even indices
+	 * for Tx and uneven indices for Rx. We need to convert the Rx
+	 * indices to be consecutive
+	 */
+	for (i = 0; i < ENA_RX_RSS_TABLE_SIZE; i++)
+		indir[i] = ENA_IO_RXQ_IDX_TO_COMBINED_IDX(indir[i]);
+
+	return rc;
+}
+
 static int ena_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
 			u8 *hfunc)
 {
@@ -648,11 +740,22 @@
 	u8 func;
 	int rc;
 
-	rc = ena_com_indirect_table_get(adapter->ena_dev, indir);
+	rc = ena_indirection_table_get(adapter, indir);
 	if (rc)
 		return rc;
 
-	rc = ena_com_get_hash_function(adapter->ena_dev, &ena_func, key);
+	/* We call this function in order to check if the device
+	 * supports getting/setting the hash function.
+	 */
+	rc = ena_com_get_hash_function(adapter->ena_dev, &ena_func);
+	if (rc) {
+		if (rc == -EOPNOTSUPP)
+			rc = 0;
+
+		return rc;
+	}
+
+	rc = ena_com_get_hash_key(adapter->ena_dev, key);
 	if (rc)
 		return rc;
 
@@ -661,7 +764,7 @@
 		func = ETH_RSS_HASH_TOP;
 		break;
 	case ENA_ADMIN_CRC32:
-		func = ETH_RSS_HASH_XOR;
+		func = ETH_RSS_HASH_CRC32;
 		break;
 	default:
 		netif_err(adapter, drv, netdev,
@@ -672,7 +775,7 @@
 	if (hfunc)
 		*hfunc = func;
 
-	return rc;
+	return 0;
 }
 
 static int ena_set_rxfh(struct net_device *netdev, const u32 *indir,
@@ -680,34 +783,23 @@
 {
 	struct ena_adapter *adapter = netdev_priv(netdev);
 	struct ena_com_dev *ena_dev = adapter->ena_dev;
-	enum ena_admin_hash_functions func;
-	int rc, i;
+	enum ena_admin_hash_functions func = 0;
+	int rc;
 
 	if (indir) {
-		for (i = 0; i < ENA_RX_RSS_TABLE_SIZE; i++) {
-			rc = ena_com_indirect_table_fill_entry(ena_dev,
-							       i,
-							       ENA_IO_RXQ_IDX(indir[i]));
-			if (unlikely(rc)) {
-				netif_err(adapter, drv, netdev,
-					  "Cannot fill indirect table (index is too large)\n");
-				return rc;
-			}
-		}
-
-		rc = ena_com_indirect_table_set(ena_dev);
-		if (rc) {
-			netif_err(adapter, drv, netdev,
-				  "Cannot set indirect table\n");
-			return rc == -EPERM ? -EOPNOTSUPP : rc;
-		}
+		rc = ena_indirection_table_set(adapter, indir);
+		if (rc)
+			return rc;
 	}
 
 	switch (hfunc) {
+	case ETH_RSS_HASH_NO_CHANGE:
+		func = ena_com_get_current_hash_function(ena_dev);
+		break;
 	case ETH_RSS_HASH_TOP:
 		func = ENA_ADMIN_TOEPLITZ;
 		break;
-	case ETH_RSS_HASH_XOR:
+	case ETH_RSS_HASH_CRC32:
 		func = ENA_ADMIN_CRC32;
 		break;
 	default:
@@ -716,7 +808,7 @@
 		return -EOPNOTSUPP;
 	}
 
-	if (key) {
+	if (key || func) {
 		rc = ena_com_fill_hash_function(ena_dev, func, key,
 						ENA_HASH_KEY_SIZE,
 						0xFFFFFFFF);
@@ -734,14 +826,22 @@
 {
 	struct ena_adapter *adapter = netdev_priv(netdev);
 
-	channels->max_rx = adapter->num_queues;
-	channels->max_tx = adapter->num_queues;
-	channels->max_other = 0;
-	channels->max_combined = 0;
-	channels->rx_count = adapter->num_queues;
-	channels->tx_count = adapter->num_queues;
-	channels->other_count = 0;
-	channels->combined_count = 0;
+	channels->max_combined = adapter->max_num_io_queues;
+	channels->combined_count = adapter->num_io_queues;
+}
+
+static int ena_set_channels(struct net_device *netdev,
+			    struct ethtool_channels *channels)
+{
+	struct ena_adapter *adapter = netdev_priv(netdev);
+	u32 count = channels->combined_count;
+	/* The check for max value is already done in ethtool */
+	if (count < ENA_MIN_NUM_IO_QUEUES ||
+	    (ena_xdp_present(adapter) &&
+	    !ena_xdp_legal_queue_count(adapter, channels->combined_count)))
+		return -EINVAL;
+
+	return ena_update_queue_count(adapter, count);
 }
 
 static int ena_get_tunable(struct net_device *netdev,
@@ -798,7 +898,7 @@
 	.get_ringparam		= ena_get_ringparam,
 	.set_ringparam		= ena_set_ringparam,
 	.get_sset_count         = ena_get_sset_count,
-	.get_strings		= ena_get_strings,
+	.get_strings		= ena_get_ethtool_strings,
 	.get_ethtool_stats      = ena_get_ethtool_stats,
 	.get_rxnfc		= ena_get_rxnfc,
 	.set_rxnfc		= ena_set_rxnfc,
@@ -807,8 +907,10 @@
 	.get_rxfh		= ena_get_rxfh,
 	.set_rxfh		= ena_set_rxfh,
 	.get_channels		= ena_get_channels,
+	.set_channels		= ena_set_channels,
 	.get_tunable		= ena_get_tunable,
 	.set_tunable		= ena_set_tunable,
+	.get_ts_info            = ethtool_op_get_ts_info,
 };
 
 void ena_set_ethtool_ops(struct net_device *netdev)
@@ -824,7 +926,7 @@
 	int strings_num;
 	int i, rc;
 
-	strings_num = ena_get_sset_count(netdev, ETH_SS_STATS);
+	strings_num = ena_get_sw_stats_count(adapter);
 	if (strings_num <= 0) {
 		netif_err(adapter, drv, netdev, "Can't get stats num\n");
 		return;
@@ -835,7 +937,7 @@
 				   GFP_ATOMIC);
 	if (!strings_buf) {
 		netif_err(adapter, drv, netdev,
-			  "failed to alloc strings_buf\n");
+			  "Failed to allocate strings_buf\n");
 		return;
 	}
 
@@ -844,13 +946,13 @@
 				GFP_ATOMIC);
 	if (!data_buf) {
 		netif_err(adapter, drv, netdev,
-			  "failed to allocate data buf\n");
+			  "Failed to allocate data buf\n");
 		devm_kfree(&adapter->pdev->dev, strings_buf);
 		return;
 	}
 
-	ena_get_strings(netdev, ETH_SS_STATS, strings_buf);
-	ena_get_ethtool_stats(netdev, NULL, data_buf);
+	ena_get_strings(adapter, strings_buf, false);
+	ena_get_stats(adapter, data_buf, false);
 
 	/* If there is a buffer, dump stats, otherwise print them to dmesg */
 	if (buf)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/amazon/ena/ena_netdev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/amazon/ena/ena_netdev.c
@@ -1,33 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
 /*
- * Copyright 2015 Amazon.com, Inc. or its affiliates.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
+ * Copyright 2015-2020 Amazon.com, Inc. or its affiliates. All rights reserved.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -36,7 +9,6 @@
 #include <linux/cpu_rmap.h>
 #endif /* CONFIG_RFS_ACCEL */
 #include <linux/ethtool.h>
-#include <linux/if_vlan.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/numa.h>
@@ -47,14 +19,12 @@
 #include <net/ip.h>
 
 #include "ena_netdev.h"
+#include <linux/bpf_trace.h>
 #include "ena_pci_id_tbl.h"
 
-static char version[] = DEVICE_NAME " v" DRV_MODULE_VERSION "\n";
-
 MODULE_AUTHOR("Amazon.com, Inc. or its affiliates");
 MODULE_DESCRIPTION(DEVICE_NAME);
 MODULE_LICENSE("GPL");
-MODULE_VERSION(DRV_MODULE_VERSION);
 
 /* Time in jiffies before concluding the transmitter is hung. */
 #define TX_TIMEOUT  (5 * HZ)
@@ -78,6 +48,36 @@
 static void ena_destroy_device(struct ena_adapter *adapter, bool graceful);
 static int ena_restore_device(struct ena_adapter *adapter);
 
+static void ena_init_io_rings(struct ena_adapter *adapter,
+			      int first_index, int count);
+static void ena_init_napi_in_range(struct ena_adapter *adapter, int first_index,
+				   int count);
+static void ena_del_napi_in_range(struct ena_adapter *adapter, int first_index,
+				  int count);
+static int ena_setup_tx_resources(struct ena_adapter *adapter, int qid);
+static int ena_setup_tx_resources_in_range(struct ena_adapter *adapter,
+					   int first_index,
+					   int count);
+static int ena_create_io_tx_queue(struct ena_adapter *adapter, int qid);
+static void ena_free_tx_resources(struct ena_adapter *adapter, int qid);
+static int ena_clean_xdp_irq(struct ena_ring *xdp_ring, u32 budget);
+static void ena_destroy_all_tx_queues(struct ena_adapter *adapter);
+static void ena_free_all_io_tx_resources(struct ena_adapter *adapter);
+static void ena_napi_disable_in_range(struct ena_adapter *adapter,
+				      int first_index, int count);
+static void ena_napi_enable_in_range(struct ena_adapter *adapter,
+				     int first_index, int count);
+static int ena_up(struct ena_adapter *adapter);
+static void ena_down(struct ena_adapter *adapter);
+static void ena_unmask_interrupt(struct ena_ring *tx_ring,
+				 struct ena_ring *rx_ring);
+static void ena_update_ring_numa_node(struct ena_ring *tx_ring,
+				      struct ena_ring *rx_ring);
+static void ena_unmap_tx_buff(struct ena_ring *tx_ring,
+			      struct ena_tx_buffer *tx_info);
+static int ena_create_io_tx_queues_in_range(struct ena_adapter *adapter,
+					    int first_index, int count);
+
 static void ena_tx_timeout(struct net_device *dev)
 {
 	struct ena_adapter *adapter = netdev_priv(dev);
@@ -101,7 +101,7 @@
 {
 	int i;
 
-	for (i = 0; i < adapter->num_queues; i++)
+	for (i = 0; i < adapter->num_io_queues; i++)
 		adapter->rx_ring[i].mtu = mtu;
 }
 
@@ -112,7 +112,7 @@
 
 	ret = ena_com_set_dev_mtu(adapter->ena_dev, new_mtu);
 	if (!ret) {
-		netif_dbg(adapter, drv, dev, "set MTU to %d\n", new_mtu);
+		netif_dbg(adapter, drv, dev, "Set MTU to %d\n", new_mtu);
 		update_rx_ring_mtu(adapter, new_mtu);
 		dev->mtu = new_mtu;
 	} else {
@@ -123,16 +123,472 @@
 	return ret;
 }
 
+static int ena_xmit_common(struct net_device *dev,
+			   struct ena_ring *ring,
+			   struct ena_tx_buffer *tx_info,
+			   struct ena_com_tx_ctx *ena_tx_ctx,
+			   u16 next_to_use,
+			   u32 bytes)
+{
+	struct ena_adapter *adapter = netdev_priv(dev);
+	int rc, nb_hw_desc;
+
+	if (unlikely(ena_com_is_doorbell_needed(ring->ena_com_io_sq,
+						ena_tx_ctx))) {
+		netif_dbg(adapter, tx_queued, dev,
+			  "llq tx max burst size of queue %d achieved, writing doorbell to send burst\n",
+			  ring->qid);
+		ena_com_write_sq_doorbell(ring->ena_com_io_sq);
+	}
+
+	/* prepare the packet's descriptors to dma engine */
+	rc = ena_com_prepare_tx(ring->ena_com_io_sq, ena_tx_ctx,
+				&nb_hw_desc);
+
+	/* In case there isn't enough space in the queue for the packet,
+	 * we simply drop it. All other failure reasons of
+	 * ena_com_prepare_tx() are fatal and therefore require a device reset.
+	 */
+	if (unlikely(rc)) {
+		netif_err(adapter, tx_queued, dev,
+			  "Failed to prepare tx bufs\n");
+		u64_stats_update_begin(&ring->syncp);
+		ring->tx_stats.prepare_ctx_err++;
+		u64_stats_update_end(&ring->syncp);
+		if (rc != -ENOMEM) {
+			adapter->reset_reason =
+				ENA_REGS_RESET_DRIVER_INVALID_STATE;
+			set_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags);
+		}
+		return rc;
+	}
+
+	u64_stats_update_begin(&ring->syncp);
+	ring->tx_stats.cnt++;
+	ring->tx_stats.bytes += bytes;
+	u64_stats_update_end(&ring->syncp);
+
+	tx_info->tx_descs = nb_hw_desc;
+	tx_info->last_jiffies = jiffies;
+	tx_info->print_once = 0;
+
+	ring->next_to_use = ENA_TX_RING_IDX_NEXT(next_to_use,
+						 ring->ring_size);
+	return 0;
+}
+
+/* This is the XDP napi callback. XDP queues use a separate napi callback
+ * than Rx/Tx queues.
+ */
+static int ena_xdp_io_poll(struct napi_struct *napi, int budget)
+{
+	struct ena_napi *ena_napi = container_of(napi, struct ena_napi, napi);
+	u32 xdp_work_done, xdp_budget;
+	struct ena_ring *xdp_ring;
+	int napi_comp_call = 0;
+	int ret;
+
+	xdp_ring = ena_napi->xdp_ring;
+	xdp_ring->first_interrupt = ena_napi->first_interrupt;
+
+	xdp_budget = budget;
+
+	if (!test_bit(ENA_FLAG_DEV_UP, &xdp_ring->adapter->flags) ||
+	    test_bit(ENA_FLAG_TRIGGER_RESET, &xdp_ring->adapter->flags)) {
+		napi_complete_done(napi, 0);
+		return 0;
+	}
+
+	xdp_work_done = ena_clean_xdp_irq(xdp_ring, xdp_budget);
+
+	/* If the device is about to reset or down, avoid unmask
+	 * the interrupt and return 0 so NAPI won't reschedule
+	 */
+	if (unlikely(!test_bit(ENA_FLAG_DEV_UP, &xdp_ring->adapter->flags))) {
+		napi_complete_done(napi, 0);
+		ret = 0;
+	} else if (xdp_budget > xdp_work_done) {
+		napi_comp_call = 1;
+		if (napi_complete_done(napi, xdp_work_done))
+			ena_unmask_interrupt(xdp_ring, NULL);
+		ena_update_ring_numa_node(xdp_ring, NULL);
+		ret = xdp_work_done;
+	} else {
+		ret = xdp_budget;
+	}
+
+	u64_stats_update_begin(&xdp_ring->syncp);
+	xdp_ring->tx_stats.napi_comp += napi_comp_call;
+	xdp_ring->tx_stats.tx_poll++;
+	u64_stats_update_end(&xdp_ring->syncp);
+
+	return ret;
+}
+
+static int ena_xdp_tx_map_buff(struct ena_ring *xdp_ring,
+			       struct ena_tx_buffer *tx_info,
+			       struct xdp_buff *xdp,
+			       void **push_hdr,
+			       u32 *push_len)
+{
+	struct ena_adapter *adapter = xdp_ring->adapter;
+	struct ena_com_buf *ena_buf;
+	dma_addr_t dma = 0;
+	u32 size;
+
+	tx_info->xdpf = convert_to_xdp_frame(xdp);
+	size = tx_info->xdpf->len;
+	ena_buf = tx_info->bufs;
+
+	/* llq push buffer */
+	*push_len = min_t(u32, size, xdp_ring->tx_max_header_size);
+	*push_hdr = tx_info->xdpf->data;
+
+	if (size - *push_len > 0) {
+		dma = dma_map_single(xdp_ring->dev,
+				     *push_hdr + *push_len,
+				     size - *push_len,
+				     DMA_TO_DEVICE);
+		if (unlikely(dma_mapping_error(xdp_ring->dev, dma)))
+			goto error_report_dma_error;
+
+		tx_info->map_linear_data = 1;
+		tx_info->num_of_bufs = 1;
+	}
+
+	ena_buf->paddr = dma;
+	ena_buf->len = size;
+
+	return 0;
+
+error_report_dma_error:
+	u64_stats_update_begin(&xdp_ring->syncp);
+	xdp_ring->tx_stats.dma_mapping_err++;
+	u64_stats_update_end(&xdp_ring->syncp);
+	netif_warn(adapter, tx_queued, adapter->netdev, "Failed to map xdp buff\n");
+
+	xdp_return_frame_rx_napi(tx_info->xdpf);
+	tx_info->xdpf = NULL;
+	tx_info->num_of_bufs = 0;
+
+	return -EINVAL;
+}
+
+static int ena_xdp_xmit_buff(struct net_device *dev,
+			     struct xdp_buff *xdp,
+			     int qid,
+			     struct ena_rx_buffer *rx_info)
+{
+	struct ena_adapter *adapter = netdev_priv(dev);
+	struct ena_com_tx_ctx ena_tx_ctx = {};
+	struct ena_tx_buffer *tx_info;
+	struct ena_ring *xdp_ring;
+	u16 next_to_use, req_id;
+	int rc;
+	void *push_hdr;
+	u32 push_len;
+
+	xdp_ring = &adapter->tx_ring[qid];
+	next_to_use = xdp_ring->next_to_use;
+	req_id = xdp_ring->free_ids[next_to_use];
+	tx_info = &xdp_ring->tx_buffer_info[req_id];
+	tx_info->num_of_bufs = 0;
+	page_ref_inc(rx_info->page);
+	tx_info->xdp_rx_page = rx_info->page;
+
+	rc = ena_xdp_tx_map_buff(xdp_ring, tx_info, xdp, &push_hdr, &push_len);
+	if (unlikely(rc))
+		goto error_drop_packet;
+
+	ena_tx_ctx.ena_bufs = tx_info->bufs;
+	ena_tx_ctx.push_header = push_hdr;
+	ena_tx_ctx.num_bufs = tx_info->num_of_bufs;
+	ena_tx_ctx.req_id = req_id;
+	ena_tx_ctx.header_len = push_len;
+
+	rc = ena_xmit_common(dev,
+			     xdp_ring,
+			     tx_info,
+			     &ena_tx_ctx,
+			     next_to_use,
+			     xdp->data_end - xdp->data);
+	if (rc)
+		goto error_unmap_dma;
+	/* trigger the dma engine. ena_com_write_sq_doorbell()
+	 * has a mb
+	 */
+	ena_com_write_sq_doorbell(xdp_ring->ena_com_io_sq);
+	u64_stats_update_begin(&xdp_ring->syncp);
+	xdp_ring->tx_stats.doorbells++;
+	u64_stats_update_end(&xdp_ring->syncp);
+
+	return NETDEV_TX_OK;
+
+error_unmap_dma:
+	ena_unmap_tx_buff(xdp_ring, tx_info);
+	tx_info->xdpf = NULL;
+error_drop_packet:
+	__free_page(tx_info->xdp_rx_page);
+	return NETDEV_TX_OK;
+}
+
+static int ena_xdp_execute(struct ena_ring *rx_ring,
+			   struct xdp_buff *xdp,
+			   struct ena_rx_buffer *rx_info)
+{
+	struct bpf_prog *xdp_prog;
+	u32 verdict = XDP_PASS;
+	u64 *xdp_stat;
+
+	rcu_read_lock();
+	xdp_prog = READ_ONCE(rx_ring->xdp_bpf_prog);
+
+	if (!xdp_prog)
+		goto out;
+
+	verdict = bpf_prog_run_xdp(xdp_prog, xdp);
+
+	if (verdict == XDP_TX) {
+		ena_xdp_xmit_buff(rx_ring->netdev,
+				  xdp,
+				  rx_ring->qid + rx_ring->adapter->num_io_queues,
+				  rx_info);
+
+		xdp_stat = &rx_ring->rx_stats.xdp_tx;
+	} else if (unlikely(verdict == XDP_ABORTED)) {
+		trace_xdp_exception(rx_ring->netdev, xdp_prog, verdict);
+		xdp_stat = &rx_ring->rx_stats.xdp_aborted;
+	} else if (unlikely(verdict == XDP_DROP)) {
+		xdp_stat = &rx_ring->rx_stats.xdp_drop;
+	} else if (unlikely(verdict == XDP_PASS)) {
+		xdp_stat = &rx_ring->rx_stats.xdp_pass;
+	} else {
+		bpf_warn_invalid_xdp_action(verdict);
+		xdp_stat = &rx_ring->rx_stats.xdp_invalid;
+	}
+
+	u64_stats_update_begin(&rx_ring->syncp);
+	(*xdp_stat)++;
+	u64_stats_update_end(&rx_ring->syncp);
+out:
+	rcu_read_unlock();
+
+	return verdict;
+}
+
+static void ena_init_all_xdp_queues(struct ena_adapter *adapter)
+{
+	adapter->xdp_first_ring = adapter->num_io_queues;
+	adapter->xdp_num_queues = adapter->num_io_queues;
+
+	ena_init_io_rings(adapter,
+			  adapter->xdp_first_ring,
+			  adapter->xdp_num_queues);
+}
+
+static int ena_setup_and_create_all_xdp_queues(struct ena_adapter *adapter)
+{
+	int rc = 0;
+
+	rc = ena_setup_tx_resources_in_range(adapter, adapter->xdp_first_ring,
+					     adapter->xdp_num_queues);
+	if (rc)
+		goto setup_err;
+
+	rc = ena_create_io_tx_queues_in_range(adapter,
+					      adapter->xdp_first_ring,
+					      adapter->xdp_num_queues);
+	if (rc)
+		goto create_err;
+
+	return 0;
+
+create_err:
+	ena_free_all_io_tx_resources(adapter);
+setup_err:
+	return rc;
+}
+
+/* Provides a way for both kernel and bpf-prog to know
+ * more about the RX-queue a given XDP frame arrived on.
+ */
+static int ena_xdp_register_rxq_info(struct ena_ring *rx_ring)
+{
+	int rc;
+
+	rc = xdp_rxq_info_reg(&rx_ring->xdp_rxq, rx_ring->netdev, rx_ring->qid);
+
+	if (rc) {
+		netif_err(rx_ring->adapter, ifup, rx_ring->netdev,
+			  "Failed to register xdp rx queue info. RX queue num %d rc: %d\n",
+			  rx_ring->qid, rc);
+		goto err;
+	}
+
+	rc = xdp_rxq_info_reg_mem_model(&rx_ring->xdp_rxq, MEM_TYPE_PAGE_SHARED,
+					NULL);
+
+	if (rc) {
+		netif_err(rx_ring->adapter, ifup, rx_ring->netdev,
+			  "Failed to register xdp rx queue info memory model. RX queue num %d rc: %d\n",
+			  rx_ring->qid, rc);
+		xdp_rxq_info_unreg(&rx_ring->xdp_rxq);
+	}
+
+err:
+	return rc;
+}
+
+static void ena_xdp_unregister_rxq_info(struct ena_ring *rx_ring)
+{
+	xdp_rxq_info_unreg_mem_model(&rx_ring->xdp_rxq);
+	xdp_rxq_info_unreg(&rx_ring->xdp_rxq);
+}
+
+static void ena_xdp_exchange_program_rx_in_range(struct ena_adapter *adapter,
+						 struct bpf_prog *prog,
+						 int first, int count)
+{
+	struct ena_ring *rx_ring;
+	int i = 0;
+
+	for (i = first; i < count; i++) {
+		rx_ring = &adapter->rx_ring[i];
+		xchg(&rx_ring->xdp_bpf_prog, prog);
+		if (prog) {
+			ena_xdp_register_rxq_info(rx_ring);
+			rx_ring->rx_headroom = XDP_PACKET_HEADROOM;
+		} else {
+			ena_xdp_unregister_rxq_info(rx_ring);
+			rx_ring->rx_headroom = 0;
+		}
+	}
+}
+
+static void ena_xdp_exchange_program(struct ena_adapter *adapter,
+				     struct bpf_prog *prog)
+{
+	struct bpf_prog *old_bpf_prog = xchg(&adapter->xdp_bpf_prog, prog);
+
+	ena_xdp_exchange_program_rx_in_range(adapter,
+					     prog,
+					     0,
+					     adapter->num_io_queues);
+
+	if (old_bpf_prog)
+		bpf_prog_put(old_bpf_prog);
+}
+
+static int ena_destroy_and_free_all_xdp_queues(struct ena_adapter *adapter)
+{
+	bool was_up;
+	int rc;
+
+	was_up = test_bit(ENA_FLAG_DEV_UP, &adapter->flags);
+
+	if (was_up)
+		ena_down(adapter);
+
+	adapter->xdp_first_ring = 0;
+	adapter->xdp_num_queues = 0;
+	ena_xdp_exchange_program(adapter, NULL);
+	if (was_up) {
+		rc = ena_up(adapter);
+		if (rc)
+			return rc;
+	}
+	return 0;
+}
+
+static int ena_xdp_set(struct net_device *netdev, struct netdev_bpf *bpf)
+{
+	struct ena_adapter *adapter = netdev_priv(netdev);
+	struct bpf_prog *prog = bpf->prog;
+	struct bpf_prog *old_bpf_prog;
+	int rc, prev_mtu;
+	bool is_up;
+
+	is_up = test_bit(ENA_FLAG_DEV_UP, &adapter->flags);
+	rc = ena_xdp_allowed(adapter);
+	if (rc == ENA_XDP_ALLOWED) {
+		old_bpf_prog = adapter->xdp_bpf_prog;
+		if (prog) {
+			if (!is_up) {
+				ena_init_all_xdp_queues(adapter);
+			} else if (!old_bpf_prog) {
+				ena_down(adapter);
+				ena_init_all_xdp_queues(adapter);
+			}
+			ena_xdp_exchange_program(adapter, prog);
+
+			if (is_up && !old_bpf_prog) {
+				rc = ena_up(adapter);
+				if (rc)
+					return rc;
+			}
+		} else if (old_bpf_prog) {
+			rc = ena_destroy_and_free_all_xdp_queues(adapter);
+			if (rc)
+				return rc;
+		}
+
+		prev_mtu = netdev->max_mtu;
+		netdev->max_mtu = prog ? ENA_XDP_MAX_MTU : adapter->max_mtu;
+
+		if (!old_bpf_prog)
+			netif_info(adapter, drv, adapter->netdev,
+				   "XDP program is set, changing the max_mtu from %d to %d",
+				   prev_mtu, netdev->max_mtu);
+
+	} else if (rc == ENA_XDP_CURRENT_MTU_TOO_LARGE) {
+		netif_err(adapter, drv, adapter->netdev,
+			  "Failed to set xdp program, the current MTU (%d) is larger than the maximum allowed MTU (%lu) while xdp is on",
+			  netdev->mtu, ENA_XDP_MAX_MTU);
+		NL_SET_ERR_MSG_MOD(bpf->extack,
+				   "Failed to set xdp program, the current MTU is larger than the maximum allowed MTU. Check the dmesg for more info");
+		return -EINVAL;
+	} else if (rc == ENA_XDP_NO_ENOUGH_QUEUES) {
+		netif_err(adapter, drv, adapter->netdev,
+			  "Failed to set xdp program, the Rx/Tx channel count should be at most half of the maximum allowed channel count. The current queue count (%d), the maximal queue count (%d)\n",
+			  adapter->num_io_queues, adapter->max_num_io_queues);
+		NL_SET_ERR_MSG_MOD(bpf->extack,
+				   "Failed to set xdp program, there is no enough space for allocating XDP queues, Check the dmesg for more info");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* This is the main xdp callback, it's used by the kernel to set/unset the xdp
+ * program as well as to query the current xdp program id.
+ */
+static int ena_xdp(struct net_device *netdev, struct netdev_bpf *bpf)
+{
+	struct ena_adapter *adapter = netdev_priv(netdev);
+
+	switch (bpf->command) {
+	case XDP_SETUP_PROG:
+		return ena_xdp_set(netdev, bpf);
+	case XDP_QUERY_PROG:
+		bpf->prog_id = adapter->xdp_bpf_prog ?
+			adapter->xdp_bpf_prog->aux->id : 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
 static int ena_init_rx_cpu_rmap(struct ena_adapter *adapter)
 {
 #ifdef CONFIG_RFS_ACCEL
 	u32 i;
 	int rc;
 
-	adapter->netdev->rx_cpu_rmap = alloc_irq_cpu_rmap(adapter->num_queues);
+	adapter->netdev->rx_cpu_rmap = alloc_irq_cpu_rmap(adapter->num_io_queues);
 	if (!adapter->netdev->rx_cpu_rmap)
 		return -ENOMEM;
-	for (i = 0; i < adapter->num_queues; i++) {
+	for (i = 0; i < adapter->num_io_queues; i++) {
 		int irq_idx = ENA_IO_IRQ_IDX(i);
 
 		rc = irq_cpu_rmap_add(adapter->netdev->rx_cpu_rmap,
@@ -164,7 +620,8 @@
 	u64_stats_init(&ring->syncp);
 }
 
-static void ena_init_io_rings(struct ena_adapter *adapter)
+static void ena_init_io_rings(struct ena_adapter *adapter,
+			      int first_index, int count)
 {
 	struct ena_com_dev *ena_dev;
 	struct ena_ring *txr, *rxr;
@@ -172,13 +629,12 @@
 
 	ena_dev = adapter->ena_dev;
 
-	for (i = 0; i < adapter->num_queues; i++) {
+	for (i = first_index; i < first_index + count; i++) {
 		txr = &adapter->tx_ring[i];
 		rxr = &adapter->rx_ring[i];
 
-		/* TX/RX common ring state */
+		/* TX common ring state */
 		ena_init_io_rings_common(adapter, txr, i);
-		ena_init_io_rings_common(adapter, rxr, i);
 
 		/* TX specific ring state */
 		txr->ring_size = adapter->requested_tx_ring_size;
@@ -187,15 +643,22 @@
 		txr->sgl_size = adapter->max_tx_sgl_size;
 		txr->smoothed_interval =
 			ena_com_get_nonadaptive_moderation_interval_tx(ena_dev);
+		txr->disable_meta_caching = adapter->disable_meta_caching;
 
-		/* RX specific ring state */
-		rxr->ring_size = adapter->requested_rx_ring_size;
-		rxr->rx_copybreak = adapter->rx_copybreak;
-		rxr->sgl_size = adapter->max_rx_sgl_size;
-		rxr->smoothed_interval =
-			ena_com_get_nonadaptive_moderation_interval_rx(ena_dev);
-		rxr->empty_rx_queue = 0;
-		adapter->ena_napi[i].dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE;
+		/* Don't init RX queues for xdp queues */
+		if (!ENA_IS_XDP_INDEX(adapter, i)) {
+			/* RX common ring state */
+			ena_init_io_rings_common(adapter, rxr, i);
+
+			/* RX specific ring state */
+			rxr->ring_size = adapter->requested_rx_ring_size;
+			rxr->rx_copybreak = adapter->rx_copybreak;
+			rxr->sgl_size = adapter->max_rx_sgl_size;
+			rxr->smoothed_interval =
+				ena_com_get_nonadaptive_moderation_interval_rx(ena_dev);
+			rxr->empty_rx_queue = 0;
+			adapter->ena_napi[i].dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE;
+		}
 	}
 }
 
@@ -285,16 +748,13 @@
 	tx_ring->push_buf_intermediate_buf = NULL;
 }
 
-/* ena_setup_all_tx_resources - allocate I/O Tx queues resources for All queues
- * @adapter: private structure
- *
- * Return 0 on success, negative on failure
- */
-static int ena_setup_all_tx_resources(struct ena_adapter *adapter)
+static int ena_setup_tx_resources_in_range(struct ena_adapter *adapter,
+					   int first_index,
+					   int count)
 {
 	int i, rc = 0;
 
-	for (i = 0; i < adapter->num_queues; i++) {
+	for (i = first_index; i < first_index + count; i++) {
 		rc = ena_setup_tx_resources(adapter, i);
 		if (rc)
 			goto err_setup_tx;
@@ -308,40 +768,31 @@
 		  "Tx queue %d: allocation failed\n", i);
 
 	/* rewind the index freeing the rings as we go */
-	while (i--)
+	while (first_index < i--)
 		ena_free_tx_resources(adapter, i);
 	return rc;
 }
 
-/* ena_free_all_io_tx_resources - Free I/O Tx Resources for All Queues
- * @adapter: board private structure
- *
- * Free all transmit software resources
- */
-static void ena_free_all_io_tx_resources(struct ena_adapter *adapter)
+static void ena_free_all_io_tx_resources_in_range(struct ena_adapter *adapter,
+						  int first_index, int count)
 {
 	int i;
 
-	for (i = 0; i < adapter->num_queues; i++)
+	for (i = first_index; i < first_index + count; i++)
 		ena_free_tx_resources(adapter, i);
 }
 
-static int validate_rx_req_id(struct ena_ring *rx_ring, u16 req_id)
+/* ena_free_all_io_tx_resources - Free I/O Tx Resources for All Queues
+ * @adapter: board private structure
+ *
+ * Free all transmit software resources
+ */
+static void ena_free_all_io_tx_resources(struct ena_adapter *adapter)
 {
-	if (likely(req_id < rx_ring->ring_size))
-		return 0;
-
-	netif_err(rx_ring->adapter, rx_err, rx_ring->netdev,
-		  "Invalid rx req_id: %hu\n", req_id);
-
-	u64_stats_update_begin(&rx_ring->syncp);
-	rx_ring->rx_stats.bad_req_id++;
-	u64_stats_update_end(&rx_ring->syncp);
-
-	/* Trigger device reset */
-	rx_ring->adapter->reset_reason = ENA_REGS_RESET_INV_RX_REQ_ID;
-	set_bit(ENA_FLAG_TRIGGER_RESET, &rx_ring->adapter->flags);
-	return -EFAULT;
+	ena_free_all_io_tx_resources_in_range(adapter,
+					      0,
+					      adapter->xdp_num_queues +
+					      adapter->num_io_queues);
 }
 
 /* ena_setup_rx_resources - allocate I/O Rx resources (Descriptors)
@@ -428,7 +879,7 @@
 {
 	int i, rc = 0;
 
-	for (i = 0; i < adapter->num_queues; i++) {
+	for (i = 0; i < adapter->num_io_queues; i++) {
 		rc = ena_setup_rx_resources(adapter, i);
 		if (rc)
 			goto err_setup_rx;
@@ -456,17 +907,21 @@
 {
 	int i;
 
-	for (i = 0; i < adapter->num_queues; i++)
+	for (i = 0; i < adapter->num_io_queues; i++)
 		ena_free_rx_resources(adapter, i);
 }
 
 static int ena_alloc_rx_page(struct ena_ring *rx_ring,
 				    struct ena_rx_buffer *rx_info, gfp_t gfp)
 {
+	int headroom = rx_ring->rx_headroom;
 	struct ena_com_buf *ena_buf;
 	struct page *page;
 	dma_addr_t dma;
 
+	/* restore page offset value in case it has been changed by device */
+	rx_info->page_offset = headroom;
+
 	/* if previous allocated page is not used */
 	if (unlikely(rx_info->page))
 		return 0;
@@ -479,8 +934,11 @@
 		return -ENOMEM;
 	}
 
+	/* To enable NIC-side port-mirroring, AKA SPAN port,
+	 * we make the buffer readable from the nic as well
+	 */
 	dma = dma_map_page(rx_ring->dev, page, 0, ENA_PAGE_SIZE,
-			   DMA_FROM_DEVICE);
+			   DMA_BIDIRECTIONAL);
 	if (unlikely(dma_mapping_error(rx_ring->dev, dma))) {
 		u64_stats_update_begin(&rx_ring->syncp);
 		rx_ring->rx_stats.dma_mapping_err++;
@@ -490,13 +948,12 @@
 		return -EIO;
 	}
 	netif_dbg(rx_ring->adapter, rx_status, rx_ring->netdev,
-		  "alloc page %p, rx_info %p\n", page, rx_info);
+		  "Allocate page %p, rx_info %p\n", page, rx_info);
 
 	rx_info->page = page;
-	rx_info->page_offset = 0;
 	ena_buf = &rx_info->ena_buf;
-	ena_buf->paddr = dma;
-	ena_buf->len = ENA_PAGE_SIZE;
+	ena_buf->paddr = dma + headroom;
+	ena_buf->len = ENA_PAGE_SIZE - headroom;
 
 	return 0;
 }
@@ -513,8 +970,9 @@
 		return;
 	}
 
-	dma_unmap_page(rx_ring->dev, ena_buf->paddr, ENA_PAGE_SIZE,
-		       DMA_FROM_DEVICE);
+	dma_unmap_page(rx_ring->dev, ena_buf->paddr - rx_ring->rx_headroom,
+		       ENA_PAGE_SIZE,
+		       DMA_BIDIRECTIONAL);
 
 	__free_page(page);
 	rx_info->page = NULL;
@@ -532,18 +990,14 @@
 		struct ena_rx_buffer *rx_info;
 
 		req_id = rx_ring->free_ids[next_to_use];
-		rc = validate_rx_req_id(rx_ring, req_id);
-		if (unlikely(rc < 0))
-			break;
 
 		rx_info = &rx_ring->rx_buffer_info[req_id];
 
-
 		rc = ena_alloc_rx_page(rx_ring, rx_info,
 				       GFP_ATOMIC | __GFP_COMP);
 		if (unlikely(rc < 0)) {
 			netif_warn(rx_ring->adapter, rx_err, rx_ring->netdev,
-				   "failed to alloc buffer for rx queue %d\n",
+				   "Failed to allocate buffer for rx queue %d\n",
 				   rx_ring->qid);
 			break;
 		}
@@ -552,7 +1006,7 @@
 						req_id);
 		if (unlikely(rc)) {
 			netif_warn(rx_ring->adapter, rx_status, rx_ring->netdev,
-				   "failed to add buffer for rx queue %d\n",
+				   "Failed to add buffer for rx queue %d\n",
 				   rx_ring->qid);
 			break;
 		}
@@ -564,9 +1018,9 @@
 		u64_stats_update_begin(&rx_ring->syncp);
 		rx_ring->rx_stats.refil_partial++;
 		u64_stats_update_end(&rx_ring->syncp);
-		netdev_warn(rx_ring->netdev,
-			    "refilled rx qid %d with only %d buffers (from %d)\n",
-			    rx_ring->qid, i, num);
+		netif_warn(rx_ring->adapter, rx_err, rx_ring->netdev,
+			   "Refilled rx qid %d with only %d buffers (from %d)\n",
+			   rx_ring->qid, i, num);
 	}
 
 	/* ena_com_write_sq_doorbell issues a wmb() */
@@ -600,14 +1054,14 @@
 	struct ena_ring *rx_ring;
 	int i, rc, bufs_num;
 
-	for (i = 0; i < adapter->num_queues; i++) {
+	for (i = 0; i < adapter->num_io_queues; i++) {
 		rx_ring = &adapter->rx_ring[i];
 		bufs_num = rx_ring->ring_size - 1;
 		rc = ena_refill_rx_bufs(rx_ring, bufs_num);
 
 		if (unlikely(rc != bufs_num))
 			netif_warn(rx_ring->adapter, rx_status, rx_ring->netdev,
-				   "refilling Queue %d failed. allocated %d buffers from: %d\n",
+				   "Refilling Queue %d failed. allocated %d buffers from: %d\n",
 				   i, rc, bufs_num);
 	}
 }
@@ -616,12 +1070,12 @@
 {
 	int i;
 
-	for (i = 0; i < adapter->num_queues; i++)
+	for (i = 0; i < adapter->num_io_queues; i++)
 		ena_free_rx_bufs(adapter, i);
 }
 
-static void ena_unmap_tx_skb(struct ena_ring *tx_ring,
-				    struct ena_tx_buffer *tx_info)
+static void ena_unmap_tx_buff(struct ena_ring *tx_ring,
+			      struct ena_tx_buffer *tx_info)
 {
 	struct ena_com_buf *ena_buf;
 	u32 cnt;
@@ -656,8 +1110,11 @@
 static void ena_free_tx_bufs(struct ena_ring *tx_ring)
 {
 	bool print_once = true;
+	bool is_xdp_ring;
 	u32 i;
 
+	is_xdp_ring = ENA_IS_XDP_INDEX(tx_ring->adapter, tx_ring->qid);
+
 	for (i = 0; i < tx_ring->ring_size; i++) {
 		struct ena_tx_buffer *tx_info = &tx_ring->tx_buffer_info[i];
 
@@ -665,22 +1122,27 @@
 			continue;
 
 		if (print_once) {
-			netdev_notice(tx_ring->netdev,
-				      "free uncompleted tx skb qid %d idx 0x%x\n",
-				      tx_ring->qid, i);
+			netif_notice(tx_ring->adapter, ifdown, tx_ring->netdev,
+				     "Free uncompleted tx skb qid %d idx 0x%x\n",
+				     tx_ring->qid, i);
 			print_once = false;
 		} else {
-			netdev_dbg(tx_ring->netdev,
-				   "free uncompleted tx skb qid %d idx 0x%x\n",
-				   tx_ring->qid, i);
+			netif_dbg(tx_ring->adapter, ifdown, tx_ring->netdev,
+				  "Free uncompleted tx skb qid %d idx 0x%x\n",
+				  tx_ring->qid, i);
 		}
 
-		ena_unmap_tx_skb(tx_ring, tx_info);
+		ena_unmap_tx_buff(tx_ring, tx_info);
 
-		dev_kfree_skb_any(tx_info->skb);
+		if (is_xdp_ring)
+			xdp_return_frame(tx_info->xdpf);
+		else
+			dev_kfree_skb_any(tx_info->skb);
 	}
-	netdev_tx_reset_queue(netdev_get_tx_queue(tx_ring->netdev,
-						  tx_ring->qid));
+
+	if (!is_xdp_ring)
+		netdev_tx_reset_queue(netdev_get_tx_queue(tx_ring->netdev,
+							  tx_ring->qid));
 }
 
 static void ena_free_all_tx_bufs(struct ena_adapter *adapter)
@@ -688,7 +1150,7 @@
 	struct ena_ring *tx_ring;
 	int i;
 
-	for (i = 0; i < adapter->num_queues; i++) {
+	for (i = 0; i < adapter->num_io_queues + adapter->xdp_num_queues; i++) {
 		tx_ring = &adapter->tx_ring[i];
 		ena_free_tx_bufs(tx_ring);
 	}
@@ -699,7 +1161,7 @@
 	u16 ena_qid;
 	int i;
 
-	for (i = 0; i < adapter->num_queues; i++) {
+	for (i = 0; i < adapter->num_io_queues + adapter->xdp_num_queues; i++) {
 		ena_qid = ENA_IO_TXQ_IDX(i);
 		ena_com_destroy_io_queue(adapter->ena_dev, ena_qid);
 	}
@@ -710,7 +1172,7 @@
 	u16 ena_qid;
 	int i;
 
-	for (i = 0; i < adapter->num_queues; i++) {
+	for (i = 0; i < adapter->num_io_queues; i++) {
 		ena_qid = ENA_IO_RXQ_IDX(i);
 		cancel_work_sync(&adapter->ena_napi[i].dim.work);
 		ena_com_destroy_io_queue(adapter->ena_dev, ena_qid);
@@ -723,6 +1185,32 @@
 	ena_destroy_all_rx_queues(adapter);
 }
 
+static int handle_invalid_req_id(struct ena_ring *ring, u16 req_id,
+				 struct ena_tx_buffer *tx_info, bool is_xdp)
+{
+	if (tx_info)
+		netif_err(ring->adapter,
+			  tx_done,
+			  ring->netdev,
+			  "tx_info doesn't have valid %s",
+			   is_xdp ? "xdp frame" : "skb");
+	else
+		netif_err(ring->adapter,
+			  tx_done,
+			  ring->netdev,
+			  "Invalid req_id: %hu\n",
+			  req_id);
+
+	u64_stats_update_begin(&ring->syncp);
+	ring->tx_stats.bad_req_id++;
+	u64_stats_update_end(&ring->syncp);
+
+	/* Trigger device reset */
+	ring->adapter->reset_reason = ENA_REGS_RESET_INV_TX_REQ_ID;
+	set_bit(ENA_FLAG_TRIGGER_RESET, &ring->adapter->flags);
+	return -EFAULT;
+}
+
 static int validate_tx_req_id(struct ena_ring *tx_ring, u16 req_id)
 {
 	struct ena_tx_buffer *tx_info = NULL;
@@ -733,21 +1221,20 @@
 			return 0;
 	}
 
-	if (tx_info)
-		netif_err(tx_ring->adapter, tx_done, tx_ring->netdev,
-			  "tx_info doesn't have valid skb\n");
-	else
-		netif_err(tx_ring->adapter, tx_done, tx_ring->netdev,
-			  "Invalid req_id: %hu\n", req_id);
+	return handle_invalid_req_id(tx_ring, req_id, tx_info, false);
+}
 
-	u64_stats_update_begin(&tx_ring->syncp);
-	tx_ring->tx_stats.bad_req_id++;
-	u64_stats_update_end(&tx_ring->syncp);
+static int validate_xdp_req_id(struct ena_ring *xdp_ring, u16 req_id)
+{
+	struct ena_tx_buffer *tx_info = NULL;
 
-	/* Trigger device reset */
-	tx_ring->adapter->reset_reason = ENA_REGS_RESET_INV_TX_REQ_ID;
-	set_bit(ENA_FLAG_TRIGGER_RESET, &tx_ring->adapter->flags);
-	return -EFAULT;
+	if (likely(req_id < xdp_ring->ring_size)) {
+		tx_info = &xdp_ring->tx_buffer_info[req_id];
+		if (likely(tx_info->xdpf))
+			return 0;
+	}
+
+	return handle_invalid_req_id(xdp_ring, req_id, tx_info, true);
 }
 
 static int ena_clean_tx_irq(struct ena_ring *tx_ring, u32 budget)
@@ -786,7 +1273,7 @@
 		tx_info->skb = NULL;
 		tx_info->last_jiffies = 0;
 
-		ena_unmap_tx_skb(tx_ring, tx_info);
+		ena_unmap_tx_buff(tx_ring, tx_info);
 
 		netif_dbg(tx_ring->adapter, tx_done, tx_ring->netdev,
 			  "tx_poll: q %d skb %p completed\n", tx_ring->qid,
@@ -871,6 +1358,7 @@
 
 	len = ena_bufs[buf].len;
 	req_id = ena_bufs[buf].req_id;
+
 	rx_info = &rx_ring->rx_buffer_info[req_id];
 
 	if (unlikely(!rx_info->page)) {
@@ -885,7 +1373,8 @@
 
 	/* save virt address of first buffer */
 	va = page_address(rx_info->page) + rx_info->page_offset;
-	prefetch(va + NET_IP_ALIGN);
+
+	prefetch(va);
 
 	if (len <= rx_ring->rx_copybreak) {
 		skb = ena_alloc_skb(rx_ring, false);
@@ -893,7 +1382,7 @@
 			return NULL;
 
 		netif_dbg(rx_ring->adapter, rx_status, rx_ring->netdev,
-			  "rx allocated small packet. len %d. data_len %d\n",
+			  "RX allocated small packet. len %d. data_len %d\n",
 			  skb->len, skb->data_len);
 
 		/* sync this buffer for CPU use */
@@ -922,13 +1411,13 @@
 	do {
 		dma_unmap_page(rx_ring->dev,
 			       dma_unmap_addr(&rx_info->ena_buf, paddr),
-			       ENA_PAGE_SIZE, DMA_FROM_DEVICE);
+			       ENA_PAGE_SIZE, DMA_BIDIRECTIONAL);
 
 		skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, rx_info->page,
 				rx_info->page_offset, len, ENA_PAGE_SIZE);
 
 		netif_dbg(rx_ring->adapter, rx_status, rx_ring->netdev,
-			  "rx skb updated. len %d. data_len %d\n",
+			  "RX skb updated. len %d. data_len %d\n",
 			  skb->len, skb->data_len);
 
 		rx_info->page = NULL;
@@ -943,6 +1432,7 @@
 		buf++;
 		len = ena_bufs[buf].len;
 		req_id = ena_bufs[buf].req_id;
+
 		rx_info = &rx_ring->rx_buffer_info[req_id];
 	} while (1);
 
@@ -1037,6 +1527,32 @@
 	}
 }
 
+static int ena_xdp_handle_buff(struct ena_ring *rx_ring, struct xdp_buff *xdp)
+{
+	struct ena_rx_buffer *rx_info;
+	int ret;
+
+	rx_info = &rx_ring->rx_buffer_info[rx_ring->ena_bufs[0].req_id];
+	xdp->data = page_address(rx_info->page) + rx_info->page_offset;
+	xdp_set_data_meta_invalid(xdp);
+	xdp->data_hard_start = page_address(rx_info->page);
+	xdp->data_end = xdp->data + rx_ring->ena_bufs[0].len;
+	/* If for some reason we received a bigger packet than
+	 * we expect, then we simply drop it
+	 */
+	if (unlikely(rx_ring->ena_bufs[0].len > ENA_XDP_MAX_MTU))
+		return XDP_DROP;
+
+	ret = ena_xdp_execute(rx_ring, xdp, rx_info);
+
+	/* The xdp program might expand the headers */
+	if (ret == XDP_PASS) {
+		rx_info->page_offset = xdp->data - xdp->data_hard_start;
+		rx_ring->ena_bufs[0].len = xdp->data_end - xdp->data;
+	}
+
+	return ret;
+}
 /* ena_clean_rx_irq - Cleanup RX irq
  * @rx_ring: RX ring to clean
  * @napi: napi handler
@@ -1048,26 +1564,32 @@
 			    u32 budget)
 {
 	u16 next_to_clean = rx_ring->next_to_clean;
-	u32 res_budget, work_done;
-
 	struct ena_com_rx_ctx ena_rx_ctx;
+	struct ena_rx_buffer *rx_info;
 	struct ena_adapter *adapter;
+	u32 res_budget, work_done;
+	int rx_copybreak_pkt = 0;
+	int refill_threshold;
 	struct sk_buff *skb;
 	int refill_required;
-	int refill_threshold;
-	int rc = 0;
+	struct xdp_buff xdp;
 	int total_len = 0;
-	int rx_copybreak_pkt = 0;
+	int xdp_verdict;
+	int rc = 0;
 	int i;
 
 	netif_dbg(rx_ring->adapter, rx_status, rx_ring->netdev,
 		  "%s qid %d\n", __func__, rx_ring->qid);
 	res_budget = budget;
+	xdp.rxq = &rx_ring->xdp_rxq;
 
 	do {
+		xdp_verdict = XDP_PASS;
+		skb = NULL;
 		ena_rx_ctx.ena_bufs = rx_ring->ena_bufs;
 		ena_rx_ctx.max_bufs = rx_ring->sgl_size;
 		ena_rx_ctx.descs = 0;
+		ena_rx_ctx.pkt_offset = 0;
 		rc = ena_com_rx_pkt(rx_ring->ena_com_io_cq,
 				    rx_ring->ena_com_io_sq,
 				    &ena_rx_ctx);
@@ -1077,17 +1599,34 @@
 		if (unlikely(ena_rx_ctx.descs == 0))
 			break;
 
+		/* First descriptor might have an offset set by the device */
+		rx_info = &rx_ring->rx_buffer_info[rx_ring->ena_bufs[0].req_id];
+		rx_info->page_offset += ena_rx_ctx.pkt_offset;
+
 		netif_dbg(rx_ring->adapter, rx_status, rx_ring->netdev,
 			  "rx_poll: q %d got packet from ena. descs #: %d l3 proto %d l4 proto %d hash: %x\n",
 			  rx_ring->qid, ena_rx_ctx.descs, ena_rx_ctx.l3_proto,
 			  ena_rx_ctx.l4_proto, ena_rx_ctx.hash);
 
+		if (ena_xdp_present_ring(rx_ring))
+			xdp_verdict = ena_xdp_handle_buff(rx_ring, &xdp);
+
 		/* allocate skb and fill it */
-		skb = ena_rx_skb(rx_ring, rx_ring->ena_bufs, ena_rx_ctx.descs,
-				 &next_to_clean);
+		if (xdp_verdict == XDP_PASS)
+			skb = ena_rx_skb(rx_ring,
+					 rx_ring->ena_bufs,
+					 ena_rx_ctx.descs,
+					 &next_to_clean);
 
-		/* exit if we failed to retrieve a buffer */
 		if (unlikely(!skb)) {
+			/* The page might not actually be freed here since the
+			 * page reference count is incremented in
+			 * ena_xdp_xmit_buff(), and it will be decreased only
+			 * when send completion was received from the device
+			 */
+			if (xdp_verdict == XDP_TX)
+				ena_free_rx_page(rx_ring,
+						 &rx_ring->rx_buffer_info[rx_ring->ena_bufs[0].req_id]);
 			for (i = 0; i < ena_rx_ctx.descs; i++) {
 				rx_ring->free_ids[next_to_clean] =
 					rx_ring->ena_bufs[i].req_id;
@@ -1095,6 +1634,10 @@
 					ENA_RX_RING_IDX_NEXT(next_to_clean,
 							     rx_ring->ring_size);
 			}
+			if (xdp_verdict != XDP_PASS) {
+				res_budget--;
+				continue;
+			}
 			break;
 		}
 
@@ -1126,7 +1669,7 @@
 
 	rx_ring->next_to_clean = next_to_clean;
 
-	refill_required = ena_com_free_desc(rx_ring->ena_com_io_sq);
+	refill_required = ena_com_free_q_entries(rx_ring->ena_com_io_sq);
 	refill_threshold =
 		min_t(int, rx_ring->ring_size / ENA_RX_REFILL_THRESH_DIVIDER,
 		      ENA_RX_REFILL_THRESH_PACKET);
@@ -1142,12 +1685,18 @@
 error:
 	adapter = netdev_priv(rx_ring->netdev);
 
-	u64_stats_update_begin(&rx_ring->syncp);
-	rx_ring->rx_stats.bad_desc_num++;
-	u64_stats_update_end(&rx_ring->syncp);
+	if (rc == -ENOSPC) {
+		u64_stats_update_begin(&rx_ring->syncp);
+		rx_ring->rx_stats.bad_desc_num++;
+		u64_stats_update_end(&rx_ring->syncp);
+		adapter->reset_reason = ENA_REGS_RESET_TOO_MANY_RX_DESCS;
+	} else {
+		u64_stats_update_begin(&rx_ring->syncp);
+		rx_ring->rx_stats.bad_req_id++;
+		u64_stats_update_end(&rx_ring->syncp);
+		adapter->reset_reason = ENA_REGS_RESET_INV_RX_REQ_ID;
+	}
 
-	/* Too many desc from the device. Trigger reset */
-	adapter->reset_reason = ENA_REGS_RESET_TOO_MANY_RX_DESCS;
 	set_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags);
 
 	return 0;
@@ -1188,9 +1737,14 @@
 					struct ena_ring *rx_ring)
 {
 	struct ena_eth_io_intr_reg intr_reg;
-	u32 rx_interval = ena_com_get_adaptive_moderation_enabled(rx_ring->ena_dev) ?
-		rx_ring->smoothed_interval :
-		ena_com_get_nonadaptive_moderation_interval_rx(rx_ring->ena_dev);
+	u32 rx_interval = 0;
+	/* Rx ring can be NULL when for XDP tx queues which don't have an
+	 * accompanying rx_ring pair.
+	 */
+	if (rx_ring)
+		rx_interval = ena_com_get_adaptive_moderation_enabled(rx_ring->ena_dev) ?
+			rx_ring->smoothed_interval :
+			ena_com_get_nonadaptive_moderation_interval_rx(rx_ring->ena_dev);
 
 	/* Update intr register: rx intr delay,
 	 * tx intr delay and interrupt unmask
@@ -1200,11 +1754,16 @@
 				tx_ring->smoothed_interval,
 				true);
 
+	u64_stats_update_begin(&tx_ring->syncp);
+	tx_ring->tx_stats.unmask_interrupt++;
+	u64_stats_update_end(&tx_ring->syncp);
+
 	/* It is a shared MSI-X.
 	 * Tx and Rx CQ have pointer to it.
 	 * So we use one of them to reach the intr reg
+	 * The Tx ring is used because the rx_ring is NULL for XDP queues
 	 */
-	ena_com_unmask_intr(rx_ring->ena_com_io_cq, &intr_reg);
+	ena_com_unmask_intr(tx_ring->ena_com_io_cq, &intr_reg);
 }
 
 static void ena_update_ring_numa_node(struct ena_ring *tx_ring,
@@ -1222,24 +1781,84 @@
 
 	if (numa_node != NUMA_NO_NODE) {
 		ena_com_update_numa_node(tx_ring->ena_com_io_cq, numa_node);
-		ena_com_update_numa_node(rx_ring->ena_com_io_cq, numa_node);
+		if (rx_ring)
+			ena_com_update_numa_node(rx_ring->ena_com_io_cq,
+						 numa_node);
 	}
 
 	tx_ring->cpu = cpu;
-	rx_ring->cpu = cpu;
+	if (rx_ring)
+		rx_ring->cpu = cpu;
 
 	return;
 out:
 	put_cpu();
 }
 
+static int ena_clean_xdp_irq(struct ena_ring *xdp_ring, u32 budget)
+{
+	u32 total_done = 0;
+	u16 next_to_clean;
+	u32 tx_bytes = 0;
+	int tx_pkts = 0;
+	u16 req_id;
+	int rc;
+
+	if (unlikely(!xdp_ring))
+		return 0;
+	next_to_clean = xdp_ring->next_to_clean;
+
+	while (tx_pkts < budget) {
+		struct ena_tx_buffer *tx_info;
+		struct xdp_frame *xdpf;
+
+		rc = ena_com_tx_comp_req_id_get(xdp_ring->ena_com_io_cq,
+						&req_id);
+		if (rc)
+			break;
+
+		rc = validate_xdp_req_id(xdp_ring, req_id);
+		if (rc)
+			break;
+
+		tx_info = &xdp_ring->tx_buffer_info[req_id];
+		xdpf = tx_info->xdpf;
+
+		tx_info->xdpf = NULL;
+		tx_info->last_jiffies = 0;
+		ena_unmap_tx_buff(xdp_ring, tx_info);
+
+		netif_dbg(xdp_ring->adapter, tx_done, xdp_ring->netdev,
+			  "tx_poll: q %d skb %p completed\n", xdp_ring->qid,
+			  xdpf);
+
+		tx_bytes += xdpf->len;
+		tx_pkts++;
+		total_done += tx_info->tx_descs;
+
+		__free_page(tx_info->xdp_rx_page);
+		xdp_ring->free_ids[next_to_clean] = req_id;
+		next_to_clean = ENA_TX_RING_IDX_NEXT(next_to_clean,
+						     xdp_ring->ring_size);
+	}
+
+	xdp_ring->next_to_clean = next_to_clean;
+	ena_com_comp_ack(xdp_ring->ena_com_io_sq, total_done);
+	ena_com_update_dev_comp_head(xdp_ring->ena_com_io_cq);
+
+	netif_dbg(xdp_ring->adapter, tx_done, xdp_ring->netdev,
+		  "tx_poll: q %d done. total pkts: %d\n",
+		  xdp_ring->qid, tx_pkts);
+
+	return tx_pkts;
+}
+
 static int ena_io_poll(struct napi_struct *napi, int budget)
 {
 	struct ena_napi *ena_napi = container_of(napi, struct ena_napi, napi);
 	struct ena_ring *tx_ring, *rx_ring;
-
-	u32 tx_work_done;
-	u32 rx_work_done;
+	int tx_work_done;
+	int rx_work_done = 0;
 	int tx_budget;
 	int napi_comp_call = 0;
 	int ret;
@@ -1247,6 +1866,9 @@
 	tx_ring = ena_napi->tx_ring;
 	rx_ring = ena_napi->rx_ring;
 
+	tx_ring->first_interrupt = ena_napi->first_interrupt;
+	rx_ring->first_interrupt = ena_napi->first_interrupt;
+
 	tx_budget = tx_ring->ring_size / ENA_TX_POLL_BUDGET_DIVIDER;
 
 	if (!test_bit(ENA_FLAG_DEV_UP, &tx_ring->adapter->flags) ||
@@ -1256,7 +1878,11 @@
 	}
 
 	tx_work_done = ena_clean_tx_irq(tx_ring, tx_budget);
-	rx_work_done = ena_clean_rx_irq(rx_ring, napi, budget);
+	/* On netpoll the budget is zero and the handler should only clean the
+	 * tx completions.
+	 */
+	if (likely(budget))
+		rx_work_done = ena_clean_rx_irq(rx_ring, napi, budget);
 
 	/* If the device is about to reset or down, avoid unmask
 	 * the interrupt and return 0 so NAPI won't reschedule
@@ -1272,7 +1898,10 @@
 		/* Update numa and unmask the interrupt only when schedule
 		 * from the interrupt context (vs from sk_busy_loop)
 		 */
-		if (napi_complete_done(napi, rx_work_done)) {
+		if (napi_complete_done(napi, rx_work_done) &&
+		    READ_ONCE(ena_napi->interrupts_masked)) {
+			smp_rmb(); /* make sure interrupts_masked is read */
+			WRITE_ONCE(ena_napi->interrupts_masked, false);
 			/* We apply adaptive moderation on Rx path only.
 			 * Tx uses static interrupt moderation.
 			 */
@@ -1318,8 +1947,10 @@
 {
 	struct ena_napi *ena_napi = data;
 
-	ena_napi->tx_ring->first_interrupt = true;
-	ena_napi->rx_ring->first_interrupt = true;
+	ena_napi->first_interrupt = true;
+
+	WRITE_ONCE(ena_napi->interrupts_masked, true);
+	smp_wmb(); /* write interrupts_masked before calling napi */
 
 	napi_schedule_irqoff(&ena_napi->napi);
 
@@ -1331,7 +1962,7 @@
  * the number of potential io queues is the minimum of what the device
  * supports and the number of vCPUs.
  */
-static int ena_enable_msix(struct ena_adapter *adapter, int num_queues)
+static int ena_enable_msix(struct ena_adapter *adapter)
 {
 	int msix_vecs, irq_cnt;
 
@@ -1342,9 +1973,9 @@
 	}
 
 	/* Reserved the max msix vectors we might need */
-	msix_vecs = ENA_MAX_MSIX_VEC(num_queues);
+	msix_vecs = ENA_MAX_MSIX_VEC(adapter->max_num_io_queues);
 	netif_dbg(adapter, probe, adapter->netdev,
-		  "trying to enable MSI-X, vectors %d\n", msix_vecs);
+		  "Trying to enable MSI-X, vectors %d\n", msix_vecs);
 
 	irq_cnt = pci_alloc_irq_vectors(adapter->pdev, ENA_MIN_MSIX_VEC,
 					msix_vecs, PCI_IRQ_MSIX);
@@ -1357,9 +1988,9 @@
 
 	if (irq_cnt != msix_vecs) {
 		netif_notice(adapter, probe, adapter->netdev,
-			     "enable only %d MSI-X (out of %d), reduce the number of queues\n",
+			     "Enable only %d MSI-X (out of %d), reduce the number of queues\n",
 			     irq_cnt, msix_vecs);
-		adapter->num_queues = irq_cnt - ENA_ADMIN_MSIX_VEC;
+		adapter->num_io_queues = irq_cnt - ENA_ADMIN_MSIX_VEC;
 	}
 
 	if (ena_init_rx_cpu_rmap(adapter))
@@ -1394,10 +2025,12 @@
 {
 	struct net_device *netdev;
 	int irq_idx, i, cpu;
+	int io_queue_count;
 
 	netdev = adapter->netdev;
+	io_queue_count = adapter->num_io_queues + adapter->xdp_num_queues;
 
-	for (i = 0; i < adapter->num_queues; i++) {
+	for (i = 0; i < io_queue_count; i++) {
 		irq_idx = ENA_IO_IRQ_IDX(i);
 		cpu = i % num_online_cpus();
 
@@ -1425,12 +2058,12 @@
 			 irq->data);
 	if (rc) {
 		netif_err(adapter, probe, adapter->netdev,
-			  "failed to request admin irq\n");
+			  "Failed to request admin irq\n");
 		return rc;
 	}
 
 	netif_dbg(adapter, probe, adapter->netdev,
-		  "set affinity hint of mgmnt irq.to 0x%lx (irq vector: %d)\n",
+		  "Set affinity hint of mgmnt irq.to 0x%lx (irq vector: %d)\n",
 		  irq->affinity_hint_mask.bits[0], irq->vector);
 
 	irq_set_affinity_hint(irq->vector, &irq->affinity_hint_mask);
@@ -1440,6 +2073,7 @@
 
 static int ena_request_io_irq(struct ena_adapter *adapter)
 {
+	u32 io_queue_count = adapter->num_io_queues + adapter->xdp_num_queues;
 	unsigned long flags = 0;
 	struct ena_irq *irq;
 	int rc = 0, i, k;
@@ -1450,7 +2084,7 @@
 		return -EINVAL;
 	}
 
-	for (i = ENA_IO_IRQ_FIRST_IDX; i < adapter->msix_vecs; i++) {
+	for (i = ENA_IO_IRQ_FIRST_IDX; i < ENA_MAX_MSIX_VEC(io_queue_count); i++) {
 		irq = &adapter->irq_tbl[i];
 		rc = request_irq(irq->vector, irq->handler, flags, irq->name,
 				 irq->data);
@@ -1462,7 +2096,7 @@
 		}
 
 		netif_dbg(adapter, ifup, adapter->netdev,
-			  "set affinity hint of irq. index %d to 0x%lx (irq vector: %d)\n",
+			  "Set affinity hint of irq. index %d to 0x%lx (irq vector: %d)\n",
 			  i, irq->affinity_hint_mask.bits[0], irq->vector);
 
 		irq_set_affinity_hint(irq->vector, &irq->affinity_hint_mask);
@@ -1491,6 +2125,7 @@
 
 static void ena_free_io_irq(struct ena_adapter *adapter)
 {
+	u32 io_queue_count = adapter->num_io_queues + adapter->xdp_num_queues;
 	struct ena_irq *irq;
 	int i;
 
@@ -1501,7 +2136,7 @@
 	}
 #endif /* CONFIG_RFS_ACCEL */
 
-	for (i = ENA_IO_IRQ_FIRST_IDX; i < adapter->msix_vecs; i++) {
+	for (i = ENA_IO_IRQ_FIRST_IDX; i < ENA_MAX_MSIX_VEC(io_queue_count); i++) {
 		irq = &adapter->irq_tbl[i];
 		irq_set_affinity_hint(irq->vector, NULL);
 		free_irq(irq->vector, irq->data);
@@ -1516,54 +2151,70 @@
 
 static void ena_disable_io_intr_sync(struct ena_adapter *adapter)
 {
+	u32 io_queue_count = adapter->num_io_queues + adapter->xdp_num_queues;
 	int i;
 
 	if (!netif_running(adapter->netdev))
 		return;
 
-	for (i = ENA_IO_IRQ_FIRST_IDX; i < adapter->msix_vecs; i++)
+	for (i = ENA_IO_IRQ_FIRST_IDX; i < ENA_MAX_MSIX_VEC(io_queue_count); i++)
 		synchronize_irq(adapter->irq_tbl[i].vector);
 }
 
-static void ena_del_napi(struct ena_adapter *adapter)
+static void ena_del_napi_in_range(struct ena_adapter *adapter,
+				  int first_index,
+				  int count)
 {
 	int i;
 
-	for (i = 0; i < adapter->num_queues; i++)
+	for (i = first_index; i < first_index + count; i++) {
 		netif_napi_del(&adapter->ena_napi[i].napi);
+
+		WARN_ON(!ENA_IS_XDP_INDEX(adapter, i) &&
+			adapter->ena_napi[i].xdp_ring);
+	}
 }
 
-static void ena_init_napi(struct ena_adapter *adapter)
+static void ena_init_napi_in_range(struct ena_adapter *adapter,
+				   int first_index, int count)
 {
-	struct ena_napi *napi;
 	int i;
 
-	for (i = 0; i < adapter->num_queues; i++) {
-		napi = &adapter->ena_napi[i];
+	for (i = first_index; i < first_index + count; i++) {
+		struct ena_napi *napi = &adapter->ena_napi[i];
 
 		netif_napi_add(adapter->netdev,
-			       &adapter->ena_napi[i].napi,
-			       ena_io_poll,
+			       &napi->napi,
+			       ENA_IS_XDP_INDEX(adapter, i) ? ena_xdp_io_poll : ena_io_poll,
 			       ENA_NAPI_BUDGET);
-		napi->rx_ring = &adapter->rx_ring[i];
-		napi->tx_ring = &adapter->tx_ring[i];
+
+		if (!ENA_IS_XDP_INDEX(adapter, i)) {
+			napi->rx_ring = &adapter->rx_ring[i];
+			napi->tx_ring = &adapter->tx_ring[i];
+		} else {
+			napi->xdp_ring = &adapter->tx_ring[i];
+		}
 		napi->qid = i;
 	}
 }
 
-static void ena_napi_disable_all(struct ena_adapter *adapter)
+static void ena_napi_disable_in_range(struct ena_adapter *adapter,
+				      int first_index,
+				      int count)
 {
 	int i;
 
-	for (i = 0; i < adapter->num_queues; i++)
+	for (i = first_index; i < first_index + count; i++)
 		napi_disable(&adapter->ena_napi[i].napi);
 }
 
-static void ena_napi_enable_all(struct ena_adapter *adapter)
+static void ena_napi_enable_in_range(struct ena_adapter *adapter,
+				     int first_index,
+				     int count)
 {
 	int i;
 
-	for (i = 0; i < adapter->num_queues; i++)
+	for (i = first_index; i < first_index + count; i++)
 		napi_enable(&adapter->ena_napi[i].napi);
 }
 
@@ -1616,7 +2267,9 @@
 	/* enable transmits */
 	netif_tx_start_all_queues(adapter->netdev);
 
-	ena_napi_enable_all(adapter);
+	ena_napi_enable_in_range(adapter,
+				 0,
+				 adapter->xdp_num_queues + adapter->num_io_queues);
 
 	return 0;
 }
@@ -1668,12 +2321,13 @@
 	return rc;
 }
 
-static int ena_create_all_io_tx_queues(struct ena_adapter *adapter)
+static int ena_create_io_tx_queues_in_range(struct ena_adapter *adapter,
+					    int first_index, int count)
 {
 	struct ena_com_dev *ena_dev = adapter->ena_dev;
 	int rc, i;
 
-	for (i = 0; i < adapter->num_queues; i++) {
+	for (i = first_index; i < first_index + count; i++) {
 		rc = ena_create_io_tx_queue(adapter, i);
 		if (rc)
 			goto create_err;
@@ -1682,7 +2336,7 @@
 	return 0;
 
 create_err:
-	while (i--)
+	while (i-- > first_index)
 		ena_com_destroy_io_queue(ena_dev, ENA_IO_TXQ_IDX(i));
 
 	return rc;
@@ -1727,13 +2381,15 @@
 		netif_err(adapter, ifup, adapter->netdev,
 			  "Failed to get RX queue handlers. RX queue num %d rc: %d\n",
 			  qid, rc);
-		ena_com_destroy_io_queue(ena_dev, ena_qid);
-		return rc;
+		goto err;
 	}
 
 	ena_com_update_numa_node(rx_ring->ena_com_io_cq, ctx.numa_node);
 
 	return rc;
+err:
+	ena_com_destroy_io_queue(ena_dev, ena_qid);
+	return rc;
 }
 
 static int ena_create_all_io_rx_queues(struct ena_adapter *adapter)
@@ -1741,7 +2397,7 @@
 	struct ena_com_dev *ena_dev = adapter->ena_dev;
 	int rc, i;
 
-	for (i = 0; i < adapter->num_queues; i++) {
+	for (i = 0; i < adapter->num_io_queues; i++) {
 		rc = ena_create_io_rx_queue(adapter, i);
 		if (rc)
 			goto create_err;
@@ -1760,11 +2416,12 @@
 }
 
 static void set_io_rings_size(struct ena_adapter *adapter,
-				     int new_tx_size, int new_rx_size)
+			      int new_tx_size,
+			      int new_rx_size)
 {
 	int i;
 
-	for (i = 0; i < adapter->num_queues; i++) {
+	for (i = 0; i < adapter->num_io_queues; i++) {
 		adapter->tx_ring[i].ring_size = new_tx_size;
 		adapter->rx_ring[i].ring_size = new_rx_size;
 	}
@@ -1797,11 +2454,21 @@
 			  adapter->requested_rx_ring_size);
 
 	while (1) {
-		rc = ena_setup_all_tx_resources(adapter);
+		if (ena_xdp_present(adapter)) {
+			rc = ena_setup_and_create_all_xdp_queues(adapter);
+
+			if (rc)
+				goto err_setup_tx;
+		}
+		rc = ena_setup_tx_resources_in_range(adapter,
+						     0,
+						     adapter->num_io_queues);
 		if (rc)
 			goto err_setup_tx;
 
-		rc = ena_create_all_io_tx_queues(adapter);
+		rc = ena_create_io_tx_queues_in_range(adapter,
+						      0,
+						      adapter->num_io_queues);
 		if (rc)
 			goto err_create_tx_queues;
 
@@ -1867,10 +2534,11 @@
 
 static int ena_up(struct ena_adapter *adapter)
 {
-	int rc, i;
+	int io_queue_count, rc, i;
 
-	netdev_dbg(adapter->netdev, "%s\n", __func__);
+	netif_dbg(adapter, ifup, adapter->netdev, "%s\n", __func__);
 
+	io_queue_count = adapter->num_io_queues + adapter->xdp_num_queues;
 	ena_setup_io_intr(adapter);
 
 	/* napi poll functions should be initialized before running
@@ -1878,7 +2546,7 @@
 	 * interrupt, causing the ISR to fire immediately while the poll
 	 * function wasn't set yet, causing a null dereference
 	 */
-	ena_init_napi(adapter);
+	ena_init_napi_in_range(adapter, 0, io_queue_count);
 
 	rc = ena_request_io_irq(adapter);
 	if (rc)
@@ -1902,14 +2570,14 @@
 	set_bit(ENA_FLAG_DEV_UP, &adapter->flags);
 
 	/* Enable completion queues interrupt */
-	for (i = 0; i < adapter->num_queues; i++)
+	for (i = 0; i < adapter->num_io_queues; i++)
 		ena_unmask_interrupt(&adapter->tx_ring[i],
 				     &adapter->rx_ring[i]);
 
 	/* schedule napi in case we had pending packets
 	 * from the last time we disable napi
 	 */
-	for (i = 0; i < adapter->num_queues; i++)
+	for (i = 0; i < io_queue_count; i++)
 		napi_schedule(&adapter->ena_napi[i].napi);
 
 	return rc;
@@ -1922,13 +2590,15 @@
 err_create_queues_with_backoff:
 	ena_free_io_irq(adapter);
 err_req_irq:
-	ena_del_napi(adapter);
+	ena_del_napi_in_range(adapter, 0, io_queue_count);
 
 	return rc;
 }
 
 static void ena_down(struct ena_adapter *adapter)
 {
+	int io_queue_count = adapter->num_io_queues + adapter->xdp_num_queues;
+
 	netif_info(adapter, ifdown, adapter->netdev, "%s\n", __func__);
 
 	clear_bit(ENA_FLAG_DEV_UP, &adapter->flags);
@@ -1941,7 +2611,7 @@
 	netif_tx_disable(adapter->netdev);
 
 	/* After this point the napi handler won't enable the tx queue */
-	ena_napi_disable_all(adapter);
+	ena_napi_disable_in_range(adapter, 0, io_queue_count);
 
 	/* After destroy the queue there won't be any new interrupts */
 
@@ -1950,7 +2620,8 @@
 
 		rc = ena_com_dev_reset(adapter->ena_dev, adapter->reset_reason);
 		if (rc)
-			dev_err(&adapter->pdev->dev, "Device reset failed\n");
+			netif_err(adapter, ifdown, adapter->netdev,
+				  "Device reset failed\n");
 		/* stop submitting admin commands on a device that was reset */
 		ena_com_set_admin_running_state(adapter->ena_dev, false);
 	}
@@ -1959,7 +2630,7 @@
 
 	ena_disable_io_intr_sync(adapter);
 	ena_free_io_irq(adapter);
-	ena_del_napi(adapter);
+	ena_del_napi_in_range(adapter, 0, io_queue_count);
 
 	ena_free_all_tx_bufs(adapter);
 	ena_free_all_rx_bufs(adapter);
@@ -1984,13 +2655,13 @@
 	int rc;
 
 	/* Notify the stack of the actual queue counts. */
-	rc = netif_set_real_num_tx_queues(netdev, adapter->num_queues);
+	rc = netif_set_real_num_tx_queues(netdev, adapter->num_io_queues);
 	if (rc) {
 		netif_err(adapter, ifup, netdev, "Can't set num tx queues\n");
 		return rc;
 	}
 
-	rc = netif_set_real_num_rx_queues(netdev, adapter->num_queues);
+	rc = netif_set_real_num_rx_queues(netdev, adapter->num_io_queues);
 	if (rc) {
 		netif_err(adapter, ifup, netdev, "Can't set num rx queues\n");
 		return rc;
@@ -2043,17 +2714,59 @@
 			   u32 new_tx_size,
 			   u32 new_rx_size)
 {
-	bool dev_up;
+	bool dev_was_up;
 
-	dev_up = test_bit(ENA_FLAG_DEV_UP, &adapter->flags);
+	dev_was_up = test_bit(ENA_FLAG_DEV_UP, &adapter->flags);
 	ena_close(adapter->netdev);
 	adapter->requested_tx_ring_size = new_tx_size;
 	adapter->requested_rx_ring_size = new_rx_size;
-	ena_init_io_rings(adapter);
-	return dev_up ? ena_up(adapter) : 0;
+	ena_init_io_rings(adapter,
+			  0,
+			  adapter->xdp_num_queues +
+			  adapter->num_io_queues);
+	return dev_was_up ? ena_up(adapter) : 0;
 }
 
-static void ena_tx_csum(struct ena_com_tx_ctx *ena_tx_ctx, struct sk_buff *skb)
+int ena_update_queue_count(struct ena_adapter *adapter, u32 new_channel_count)
+{
+	struct ena_com_dev *ena_dev = adapter->ena_dev;
+	int prev_channel_count;
+	bool dev_was_up;
+
+	dev_was_up = test_bit(ENA_FLAG_DEV_UP, &adapter->flags);
+	ena_close(adapter->netdev);
+	prev_channel_count = adapter->num_io_queues;
+	adapter->num_io_queues = new_channel_count;
+	if (ena_xdp_present(adapter) &&
+	    ena_xdp_allowed(adapter) == ENA_XDP_ALLOWED) {
+		adapter->xdp_first_ring = new_channel_count;
+		adapter->xdp_num_queues = new_channel_count;
+		if (prev_channel_count > new_channel_count)
+			ena_xdp_exchange_program_rx_in_range(adapter,
+							     NULL,
+							     new_channel_count,
+							     prev_channel_count);
+		else
+			ena_xdp_exchange_program_rx_in_range(adapter,
+							     adapter->xdp_bpf_prog,
+							     prev_channel_count,
+							     new_channel_count);
+	}
+
+	/* We need to destroy the rss table so that the indirection
+	 * table will be reinitialized by ena_up()
+	 */
+	ena_com_rss_destroy(ena_dev);
+	ena_init_io_rings(adapter,
+			  0,
+			  adapter->xdp_num_queues +
+			  adapter->num_io_queues);
+	return dev_was_up ? ena_open(adapter->netdev) : 0;
+}
+
+static void ena_tx_csum(struct ena_com_tx_ctx *ena_tx_ctx,
+			struct sk_buff *skb,
+			bool disable_meta_caching)
 {
 	u32 mss = skb_shinfo(skb)->gso_size;
 	struct ena_com_tx_meta *ena_meta = &ena_tx_ctx->ena_meta;
@@ -2097,7 +2810,9 @@
 		ena_meta->l3_hdr_len = skb_network_header_len(skb);
 		ena_meta->l3_hdr_offset = skb_network_offset(skb);
 		ena_tx_ctx->meta_valid = 1;
-
+	} else if (disable_meta_caching) {
+		memset(ena_meta, 0, sizeof(*ena_meta));
+		ena_tx_ctx->meta_valid = 1;
 	} else {
 		ena_tx_ctx->meta_valid = 0;
 	}
@@ -2228,12 +2943,12 @@
 	u64_stats_update_begin(&tx_ring->syncp);
 	tx_ring->tx_stats.dma_mapping_err++;
 	u64_stats_update_end(&tx_ring->syncp);
-	netdev_warn(adapter->netdev, "failed to map skb\n");
+	netif_warn(adapter, tx_queued, adapter->netdev, "Failed to map skb\n");
 
 	tx_info->skb = NULL;
 
 	tx_info->num_of_bufs += i;
-	ena_unmap_tx_skb(tx_ring, tx_info);
+	ena_unmap_tx_buff(tx_ring, tx_info);
 
 	return -EINVAL;
 }
@@ -2248,7 +2963,7 @@
 	struct netdev_queue *txq;
 	void *push_hdr;
 	u16 next_to_use, req_id, header_len;
-	int qid, rc, nb_hw_desc;
+	int qid, rc;
 
 	netif_dbg(adapter, tx_queued, dev, "%s skb %p\n", __func__, skb);
 	/*  Determine which tx ring we will be placed on */
@@ -2281,52 +2996,19 @@
 	ena_tx_ctx.header_len = header_len;
 
 	/* set flags and meta data */
-	ena_tx_csum(&ena_tx_ctx, skb);
-
-	if (unlikely(ena_com_is_doorbell_needed(tx_ring->ena_com_io_sq, &ena_tx_ctx))) {
-		netif_dbg(adapter, tx_queued, dev,
-			  "llq tx max burst size of queue %d achieved, writing doorbell to send burst\n",
-			  qid);
-		ena_com_write_sq_doorbell(tx_ring->ena_com_io_sq);
-	}
-
-	/* prepare the packet's descriptors to dma engine */
-	rc = ena_com_prepare_tx(tx_ring->ena_com_io_sq, &ena_tx_ctx,
-				&nb_hw_desc);
+	ena_tx_csum(&ena_tx_ctx, skb, tx_ring->disable_meta_caching);
 
-	/* ena_com_prepare_tx() can't fail due to overflow of tx queue,
-	 * since the number of free descriptors in the queue is checked
-	 * after sending the previous packet. In case there isn't enough
-	 * space in the queue for the next packet, it is stopped
-	 * until there is again enough available space in the queue.
-	 * All other failure reasons of ena_com_prepare_tx() are fatal
-	 * and therefore require a device reset.
-	 */
-	if (unlikely(rc)) {
-		netif_err(adapter, tx_queued, dev,
-			  "failed to prepare tx bufs\n");
-		u64_stats_update_begin(&tx_ring->syncp);
-		tx_ring->tx_stats.prepare_ctx_err++;
-		u64_stats_update_end(&tx_ring->syncp);
-		adapter->reset_reason = ENA_REGS_RESET_DRIVER_INVALID_STATE;
-		set_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags);
+	rc = ena_xmit_common(dev,
+			     tx_ring,
+			     tx_info,
+			     &ena_tx_ctx,
+			     next_to_use,
+			     skb->len);
+	if (rc)
 		goto error_unmap_dma;
-	}
 
 	netdev_tx_sent_queue(txq, skb->len);
 
-	u64_stats_update_begin(&tx_ring->syncp);
-	tx_ring->tx_stats.cnt++;
-	tx_ring->tx_stats.bytes += skb->len;
-	u64_stats_update_end(&tx_ring->syncp);
-
-	tx_info->tx_descs = nb_hw_desc;
-	tx_info->last_jiffies = jiffies;
-	tx_info->print_once = 0;
-
-	tx_ring->next_to_use = ENA_TX_RING_IDX_NEXT(next_to_use,
-		tx_ring->ring_size);
-
 	/* stop the queue when no more space available, the packet can have up
 	 * to sgl_size + 2. one for the meta descriptor and one for header
 	 * (if the header is larger than tx_max_header_size).
@@ -2373,7 +3055,7 @@
 	return NETDEV_TX_OK;
 
 error_unmap_dma:
-	ena_unmap_tx_skb(tx_ring, tx_info);
+	ena_unmap_tx_buff(tx_ring, tx_info);
 	tx_info->skb = NULL;
 
 error_drop_packet:
@@ -2381,32 +3063,16 @@
 	return NETDEV_TX_OK;
 }
 
-static u16 ena_select_queue(struct net_device *dev, struct sk_buff *skb,
-			    struct net_device *sb_dev)
-{
-	u16 qid;
-	/* we suspect that this is good for in--kernel network services that
-	 * want to loop incoming skb rx to tx in normal user generated traffic,
-	 * most probably we will not get to this
-	 */
-	if (skb_rx_queue_recorded(skb))
-		qid = skb_get_rx_queue(skb);
-	else
-		qid = netdev_pick_tx(dev, skb, NULL);
-
-	return qid;
-}
-
-static void ena_config_host_info(struct ena_com_dev *ena_dev,
-				 struct pci_dev *pdev)
+static void ena_config_host_info(struct ena_com_dev *ena_dev, struct pci_dev *pdev)
 {
+	struct device *dev = &pdev->dev;
 	struct ena_admin_host_info *host_info;
 	int rc;
 
 	/* Allocate only the host info */
 	rc = ena_com_allocate_host_info(ena_dev);
 	if (rc) {
-		pr_err("Cannot allocate host info\n");
+		dev_err(dev, "Cannot allocate host info\n");
 		return;
 	}
 
@@ -2421,21 +3087,24 @@
 	strncpy(host_info->os_dist_str, utsname()->release,
 		sizeof(host_info->os_dist_str) - 1);
 	host_info->driver_version =
-		(DRV_MODULE_VER_MAJOR) |
-		(DRV_MODULE_VER_MINOR << ENA_ADMIN_HOST_INFO_MINOR_SHIFT) |
-		(DRV_MODULE_VER_SUBMINOR << ENA_ADMIN_HOST_INFO_SUB_MINOR_SHIFT) |
+		(DRV_MODULE_GEN_MAJOR) |
+		(DRV_MODULE_GEN_MINOR << ENA_ADMIN_HOST_INFO_MINOR_SHIFT) |
+		(DRV_MODULE_GEN_SUBMINOR << ENA_ADMIN_HOST_INFO_SUB_MINOR_SHIFT) |
 		("K"[0] << ENA_ADMIN_HOST_INFO_MODULE_TYPE_SHIFT);
 	host_info->num_cpus = num_online_cpus();
 
 	host_info->driver_supported_features =
-		ENA_ADMIN_HOST_INFO_INTERRUPT_MODERATION_MASK;
+		ENA_ADMIN_HOST_INFO_RX_OFFSET_MASK |
+		ENA_ADMIN_HOST_INFO_INTERRUPT_MODERATION_MASK |
+		ENA_ADMIN_HOST_INFO_RX_BUF_MIRRORING_MASK |
+		ENA_ADMIN_HOST_INFO_RSS_CONFIGURABLE_FUNCTION_KEY_MASK;
 
 	rc = ena_com_set_host_attributes(ena_dev);
 	if (rc) {
 		if (rc == -EOPNOTSUPP)
-			pr_warn("Cannot set host attributes\n");
+			dev_warn(dev, "Cannot set host attributes\n");
 		else
-			pr_err("Cannot set host attributes\n");
+			dev_err(dev, "Cannot set host attributes\n");
 
 		goto err;
 	}
@@ -2463,7 +3132,8 @@
 
 	rc = ena_com_allocate_debug_area(adapter->ena_dev, debug_area_size);
 	if (rc) {
-		pr_err("Cannot allocate debug area\n");
+		netif_err(adapter, drv, adapter->netdev,
+			  "Cannot allocate debug area\n");
 		return;
 	}
 
@@ -2483,6 +3153,19 @@
 	ena_com_delete_debug_area(adapter->ena_dev);
 }
 
+int ena_update_hw_stats(struct ena_adapter *adapter)
+{
+	int rc = 0;
+
+	rc = ena_com_get_eni_stats(adapter->ena_dev, &adapter->eni_stats);
+	if (rc) {
+		dev_info_once(&adapter->pdev->dev, "Failed to get ENI stats\n");
+		return rc;
+	}
+
+	return 0;
+}
+
 static void ena_get_stats64(struct net_device *netdev,
 			    struct rtnl_link_stats64 *stats)
 {
@@ -2490,12 +3173,13 @@
 	struct ena_ring *rx_ring, *tx_ring;
 	unsigned int start;
 	u64 rx_drops;
+	u64 tx_drops;
 	int i;
 
 	if (!test_bit(ENA_FLAG_DEV_UP, &adapter->flags))
 		return;
 
-	for (i = 0; i < adapter->num_queues; i++) {
+	for (i = 0; i < adapter->num_io_queues; i++) {
 		u64 bytes, packets;
 
 		tx_ring = &adapter->tx_ring[i];
@@ -2524,9 +3208,11 @@
 	do {
 		start = u64_stats_fetch_begin_irq(&adapter->syncp);
 		rx_drops = adapter->dev_stats.rx_drops;
+		tx_drops = adapter->dev_stats.tx_drops;
 	} while (u64_stats_fetch_retry_irq(&adapter->syncp, start));
 
 	stats->rx_dropped = rx_drops;
+	stats->tx_dropped = tx_drops;
 
 	stats->multicast = 0;
 	stats->collisions = 0;
@@ -2546,12 +3232,12 @@
 	.ndo_open		= ena_open,
 	.ndo_stop		= ena_close,
 	.ndo_start_xmit		= ena_start_xmit,
-	.ndo_select_queue	= ena_select_queue,
 	.ndo_get_stats64	= ena_get_stats64,
 	.ndo_tx_timeout		= ena_tx_timeout,
 	.ndo_change_mtu		= ena_change_mtu,
 	.ndo_set_mac_address	= NULL,
 	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_bpf		= ena_xdp,
 };
 
 static int ena_device_validate_params(struct ena_adapter *adapter,
@@ -2577,10 +3263,71 @@
 	return 0;
 }
 
+static void set_default_llq_configurations(struct ena_llq_configurations *llq_config)
+{
+	llq_config->llq_header_location = ENA_ADMIN_INLINE_HEADER;
+	llq_config->llq_stride_ctrl = ENA_ADMIN_MULTIPLE_DESCS_PER_ENTRY;
+	llq_config->llq_num_decs_before_header = ENA_ADMIN_LLQ_NUM_DESCS_BEFORE_HEADER_2;
+	llq_config->llq_ring_entry_size = ENA_ADMIN_LIST_ENTRY_SIZE_128B;
+	llq_config->llq_ring_entry_size_value = 128;
+}
+
+static int ena_set_queues_placement_policy(struct pci_dev *pdev,
+					   struct ena_com_dev *ena_dev,
+					   struct ena_admin_feature_llq_desc *llq,
+					   struct ena_llq_configurations *llq_default_configurations)
+{
+	int rc;
+	u32 llq_feature_mask;
+
+	llq_feature_mask = 1 << ENA_ADMIN_LLQ;
+	if (!(ena_dev->supported_features & llq_feature_mask)) {
+		dev_err(&pdev->dev,
+			"LLQ is not supported Fallback to host mode policy.\n");
+		ena_dev->tx_mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_HOST;
+		return 0;
+	}
+
+	rc = ena_com_config_dev_mode(ena_dev, llq, llq_default_configurations);
+	if (unlikely(rc)) {
+		dev_err(&pdev->dev,
+			"Failed to configure the device mode.  Fallback to host mode policy.\n");
+		ena_dev->tx_mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_HOST;
+	}
+
+	return 0;
+}
+
+static int ena_map_llq_mem_bar(struct pci_dev *pdev, struct ena_com_dev *ena_dev,
+			       int bars)
+{
+	bool has_mem_bar = !!(bars & BIT(ENA_MEM_BAR));
+
+	if (!has_mem_bar) {
+		if (ena_dev->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV) {
+			dev_err(&pdev->dev,
+				"ENA device does not expose LLQ bar. Fallback to host mode policy.\n");
+			ena_dev->tx_mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_HOST;
+		}
+
+		return 0;
+	}
+
+	ena_dev->mem_bar = devm_ioremap_wc(&pdev->dev,
+					   pci_resource_start(pdev, ENA_MEM_BAR),
+					   pci_resource_len(pdev, ENA_MEM_BAR));
+
+	if (!ena_dev->mem_bar)
+		return -EFAULT;
+
+	return 0;
+}
+
 static int ena_device_init(struct ena_com_dev *ena_dev, struct pci_dev *pdev,
 			   struct ena_com_dev_get_features_ctx *get_feat_ctx,
 			   bool *wd_state)
 {
+	struct ena_llq_configurations llq_config;
 	struct device *dev = &pdev->dev;
 	bool readless_supported;
 	u32 aenq_groups;
@@ -2589,7 +3336,7 @@
 
 	rc = ena_com_mmio_reg_read_request_init(ena_dev);
 	if (rc) {
-		dev_err(dev, "failed to init mmio read less\n");
+		dev_err(dev, "Failed to init mmio read less\n");
 		return rc;
 	}
 
@@ -2607,7 +3354,7 @@
 
 	rc = ena_com_validate_version(ena_dev);
 	if (rc) {
-		dev_err(dev, "device version is too low\n");
+		dev_err(dev, "Device version is too low\n");
 		goto err_mmio_read_less;
 	}
 
@@ -2618,16 +3365,9 @@
 		goto err_mmio_read_less;
 	}
 
-	rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(dma_width));
+	rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(dma_width));
 	if (rc) {
-		dev_err(dev, "pci_set_dma_mask failed 0x%x\n", rc);
-		goto err_mmio_read_less;
-	}
-
-	rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(dma_width));
-	if (rc) {
-		dev_err(dev, "err_pci_set_consistent_dma_mask failed 0x%x\n",
-			rc);
+		dev_err(dev, "dma_set_mask_and_coherent failed %d\n", rc);
 		goto err_mmio_read_less;
 	}
 
@@ -2671,6 +3411,15 @@
 
 	*wd_state = !!(aenq_groups & BIT(ENA_ADMIN_KEEP_ALIVE));
 
+	set_default_llq_configurations(&llq_config);
+
+	rc = ena_set_queues_placement_policy(pdev, ena_dev, &get_feat_ctx->llq,
+					     &llq_config);
+	if (rc) {
+		dev_err(dev, "ENA device init failed\n");
+		goto err_admin_init;
+	}
+
 	return 0;
 
 err_admin_init:
@@ -2682,14 +3431,13 @@
 	return rc;
 }
 
-static int ena_enable_msix_and_set_admin_interrupts(struct ena_adapter *adapter,
-						    int io_vectors)
+static int ena_enable_msix_and_set_admin_interrupts(struct ena_adapter *adapter)
 {
 	struct ena_com_dev *ena_dev = adapter->ena_dev;
 	struct device *dev = &adapter->pdev->dev;
 	int rc;
 
-	rc = ena_enable_msix(adapter, io_vectors);
+	rc = ena_enable_msix(adapter);
 	if (rc) {
 		dev_err(dev, "Can not reserve msix vectors\n");
 		return rc;
@@ -2754,6 +3502,7 @@
 
 	ena_com_mmio_reg_read_request_destroy(ena_dev);
 
+	/* return reset reason to default value */
 	adapter->reset_reason = ENA_REGS_RESET_NORMAL;
 
 	clear_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags);
@@ -2782,8 +3531,7 @@
 		goto err_device_destroy;
 	}
 
-	rc = ena_enable_msix_and_set_admin_interrupts(adapter,
-						      adapter->num_queues);
+	rc = ena_enable_msix_and_set_admin_interrupts(adapter);
 	if (rc) {
 		dev_err(&pdev->dev, "Enable MSI-X failed\n");
 		goto err_device_destroy;
@@ -2804,9 +3552,10 @@
 		netif_carrier_on(adapter->netdev);
 
 	mod_timer(&adapter->timer_service, round_jiffies(jiffies + HZ));
-	dev_err(&pdev->dev,
-		"Device reset completed successfully, Driver info: %s\n",
-		version);
+	adapter->last_keep_alive_jiffies = jiffies;
+	dev_err(&pdev->dev, "Device reset completed successfully\n");
+
+	dev_err(&pdev->dev, "Device reset completed successfully\n");
 
 	return rc;
 err_disable_msix:
@@ -2831,16 +3580,14 @@
 {
 	struct ena_adapter *adapter =
 		container_of(work, struct ena_adapter, reset_task);
-	struct pci_dev *pdev = adapter->pdev;
 
-	if (unlikely(!test_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags))) {
-		dev_err(&pdev->dev,
-			"device reset schedule while reset bit is off\n");
-		return;
-	}
 	rtnl_lock();
-	ena_destroy_device(adapter, false);
-	ena_restore_device(adapter);
+
+	if (likely(test_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags))) {
+		ena_destroy_device(adapter, false);
+		ena_restore_device(adapter);
+	}
+
 	rtnl_unlock();
 }
 
@@ -2922,7 +3669,7 @@
 	}
 
 	u64_stats_update_begin(&tx_ring->syncp);
-	tx_ring->tx_stats.missed_tx = missed_tx;
+	tx_ring->tx_stats.missed_tx += missed_tx;
 	u64_stats_update_end(&tx_ring->syncp);
 
 	return rc;
@@ -2933,7 +3680,9 @@
 	struct ena_ring *tx_ring;
 	struct ena_ring *rx_ring;
 	int i, budget, rc;
+	int io_queue_count;
 
+	io_queue_count = adapter->xdp_num_queues + adapter->num_io_queues;
 	/* Make sure the driver doesn't turn the device in other process */
 	smp_rmb();
 
@@ -2948,7 +3697,7 @@
 
 	budget = ENA_MONITORED_TX_QUEUES;
 
-	for (i = adapter->last_monitored_tx_qid; i < adapter->num_queues; i++) {
+	for (i = adapter->last_monitored_tx_qid; i < io_queue_count; i++) {
 		tx_ring = &adapter->tx_ring[i];
 		rx_ring = &adapter->rx_ring[i];
 
@@ -2956,7 +3705,8 @@
 		if (unlikely(rc))
 			return;
 
-		rc = check_for_rx_interrupt_queue(adapter, rx_ring);
+		rc =  !ENA_IS_XDP_INDEX(adapter, i) ?
+			check_for_rx_interrupt_queue(adapter, rx_ring) : 0;
 		if (unlikely(rc))
 			return;
 
@@ -2965,7 +3715,7 @@
 			break;
 	}
 
-	adapter->last_monitored_tx_qid = i % adapter->num_queues;
+	adapter->last_monitored_tx_qid = i % io_queue_count;
 }
 
 /* trigger napi schedule after 2 consecutive detections */
@@ -2995,11 +3745,10 @@
 	if (test_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags))
 		return;
 
-	for (i = 0; i < adapter->num_queues; i++) {
+	for (i = 0; i < adapter->num_io_queues; i++) {
 		rx_ring = &adapter->rx_ring[i];
 
-		refill_required =
-			ena_com_free_desc(rx_ring->ena_com_io_sq);
+		refill_required = ena_com_free_q_entries(rx_ring->ena_com_io_sq);
 		if (unlikely(refill_required == (rx_ring->ring_size - 1))) {
 			rx_ring->empty_rx_queue++;
 
@@ -3009,7 +3758,7 @@
 				u64_stats_update_end(&rx_ring->syncp);
 
 				netif_err(adapter, drv, adapter->netdev,
-					  "trigger refill for ring %d\n", i);
+					  "Trigger refill for ring %d\n", i);
 
 				napi_schedule(rx_ring->napi);
 				rx_ring->empty_rx_queue = 0;
@@ -3031,8 +3780,8 @@
 	if (adapter->keep_alive_timeout == ENA_HW_HINTS_NO_TIMEOUT)
 		return;
 
-	keep_alive_expired = round_jiffies(adapter->last_keep_alive_jiffies +
-					   adapter->keep_alive_timeout);
+	keep_alive_expired = adapter->last_keep_alive_jiffies +
+			     adapter->keep_alive_timeout;
 	if (unlikely(time_is_before_jiffies(keep_alive_expired))) {
 		netif_err(adapter, drv, adapter->netdev,
 			  "Keep alive watchdog timeout.\n");
@@ -3134,19 +3883,19 @@
 	}
 
 	/* Reset the timer */
-	mod_timer(&adapter->timer_service, jiffies + HZ);
+	mod_timer(&adapter->timer_service, round_jiffies(jiffies + HZ));
 }
 
-static int ena_calc_io_queue_num(struct pci_dev *pdev,
-				 struct ena_com_dev *ena_dev,
-				 struct ena_com_dev_get_features_ctx *get_feat_ctx)
+static u32 ena_calc_max_io_queue_num(struct pci_dev *pdev,
+				     struct ena_com_dev *ena_dev,
+				     struct ena_com_dev_get_features_ctx *get_feat_ctx)
 {
-	int io_tx_sq_num, io_tx_cq_num, io_rx_num, io_queue_num;
+	u32 io_tx_sq_num, io_tx_cq_num, io_rx_num, max_num_io_queues;
 
 	if (ena_dev->supported_features & BIT(ENA_ADMIN_MAX_QUEUES_EXT)) {
 		struct ena_admin_queue_ext_feature_fields *max_queue_ext =
 			&get_feat_ctx->max_queue_ext.max_queue_ext;
-		io_rx_num = min_t(int, max_queue_ext->max_rx_sq_num,
+		io_rx_num = min_t(u32, max_queue_ext->max_rx_sq_num,
 				  max_queue_ext->max_rx_cq_num);
 
 		io_tx_sq_num = max_queue_ext->max_tx_sq_num;
@@ -3156,73 +3905,25 @@
 			&get_feat_ctx->max_queues;
 		io_tx_sq_num = max_queues->max_sq_num;
 		io_tx_cq_num = max_queues->max_cq_num;
-		io_rx_num = min_t(int, io_tx_sq_num, io_tx_cq_num);
+		io_rx_num = min_t(u32, io_tx_sq_num, io_tx_cq_num);
 	}
 
 	/* In case of LLQ use the llq fields for the tx SQ/CQ */
 	if (ena_dev->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV)
 		io_tx_sq_num = get_feat_ctx->llq.max_llq_num;
 
-	io_queue_num = min_t(int, num_online_cpus(), ENA_MAX_NUM_IO_QUEUES);
-	io_queue_num = min_t(int, io_queue_num, io_rx_num);
-	io_queue_num = min_t(int, io_queue_num, io_tx_sq_num);
-	io_queue_num = min_t(int, io_queue_num, io_tx_cq_num);
+	max_num_io_queues = min_t(u32, num_online_cpus(), ENA_MAX_NUM_IO_QUEUES);
+	max_num_io_queues = min_t(u32, max_num_io_queues, io_rx_num);
+	max_num_io_queues = min_t(u32, max_num_io_queues, io_tx_sq_num);
+	max_num_io_queues = min_t(u32, max_num_io_queues, io_tx_cq_num);
 	/* 1 IRQ for for mgmnt and 1 IRQs for each IO direction */
-	io_queue_num = min_t(int, io_queue_num, pci_msix_vec_count(pdev) - 1);
-	if (unlikely(!io_queue_num)) {
+	max_num_io_queues = min_t(u32, max_num_io_queues, pci_msix_vec_count(pdev) - 1);
+	if (unlikely(!max_num_io_queues)) {
 		dev_err(&pdev->dev, "The device doesn't have io queues\n");
 		return -EFAULT;
 	}
 
-	return io_queue_num;
-}
-
-static int ena_set_queues_placement_policy(struct pci_dev *pdev,
-					   struct ena_com_dev *ena_dev,
-					   struct ena_admin_feature_llq_desc *llq,
-					   struct ena_llq_configurations *llq_default_configurations)
-{
-	bool has_mem_bar;
-	int rc;
-	u32 llq_feature_mask;
-
-	llq_feature_mask = 1 << ENA_ADMIN_LLQ;
-	if (!(ena_dev->supported_features & llq_feature_mask)) {
-		dev_err(&pdev->dev,
-			"LLQ is not supported Fallback to host mode policy.\n");
-		ena_dev->tx_mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_HOST;
-		return 0;
-	}
-
-	has_mem_bar = pci_select_bars(pdev, IORESOURCE_MEM) & BIT(ENA_MEM_BAR);
-
-	rc = ena_com_config_dev_mode(ena_dev, llq, llq_default_configurations);
-	if (unlikely(rc)) {
-		dev_err(&pdev->dev,
-			"Failed to configure the device mode.  Fallback to host mode policy.\n");
-		ena_dev->tx_mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_HOST;
-		return 0;
-	}
-
-	/* Nothing to config, exit */
-	if (ena_dev->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_HOST)
-		return 0;
-
-	if (!has_mem_bar) {
-		dev_err(&pdev->dev,
-			"ENA device does not expose LLQ bar. Fallback to host mode policy.\n");
-		ena_dev->tx_mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_HOST;
-		return 0;
-	}
-
-	ena_dev->mem_bar = devm_ioremap_wc(&pdev->dev,
-					   pci_resource_start(pdev, ENA_MEM_BAR),
-					   pci_resource_len(pdev, ENA_MEM_BAR));
-
-	if (!ena_dev->mem_bar)
-		return -EFAULT;
-
-	return 0;
+	return max_num_io_queues;
 }
 
 static void ena_set_dev_offloads(struct ena_com_dev_get_features_ctx *feat,
@@ -3302,7 +4003,7 @@
 	}
 
 	for (i = 0; i < ENA_RX_RSS_TABLE_SIZE; i++) {
-		val = ethtool_rxfh_indir_default(i, adapter->num_queues);
+		val = ethtool_rxfh_indir_default(i, adapter->num_io_queues);
 		rc = ena_com_indirect_table_fill_entry(ena_dev, i,
 						       ENA_IO_RXQ_IDX(val));
 		if (unlikely(rc && (rc != -EOPNOTSUPP))) {
@@ -3311,7 +4012,7 @@
 		}
 	}
 
-	rc = ena_com_fill_hash_function(ena_dev, ENA_ADMIN_CRC32, NULL,
+	rc = ena_com_fill_hash_function(ena_dev, ENA_ADMIN_TOEPLITZ, NULL,
 					ENA_HASH_KEY_SIZE, 0xFFFFFFFF);
 	if (unlikely(rc && (rc != -EOPNOTSUPP))) {
 		dev_err(dev, "Cannot fill hash function\n");
@@ -3340,16 +4041,8 @@
 	pci_release_selected_regions(pdev, release_bars);
 }
 
-static void set_default_llq_configurations(struct ena_llq_configurations *llq_config)
-{
-	llq_config->llq_header_location = ENA_ADMIN_INLINE_HEADER;
-	llq_config->llq_ring_entry_size = ENA_ADMIN_LIST_ENTRY_SIZE_128B;
-	llq_config->llq_stride_ctrl = ENA_ADMIN_MULTIPLE_DESCS_PER_ENTRY;
-	llq_config->llq_num_decs_before_header = ENA_ADMIN_LLQ_NUM_DESCS_BEFORE_HEADER_2;
-	llq_config->llq_ring_entry_size_value = 128;
-}
 
-static int ena_calc_queue_size(struct ena_calc_queue_size_ctx *ctx)
+static int ena_calc_io_queue_size(struct ena_calc_queue_size_ctx *ctx)
 {
 	struct ena_admin_feature_llq_desc *llq = &ctx->get_feat_ctx->llq;
 	struct ena_com_dev *ena_dev = ctx->ena_dev;
@@ -3358,7 +4051,7 @@
 	u32 max_tx_queue_size;
 	u32 max_rx_queue_size;
 
-	if (ctx->ena_dev->supported_features & BIT(ENA_ADMIN_MAX_QUEUES_EXT)) {
+	if (ena_dev->supported_features & BIT(ENA_ADMIN_MAX_QUEUES_EXT)) {
 		struct ena_admin_queue_ext_feature_fields *max_queue_ext =
 			&ctx->get_feat_ctx->max_queue_ext.max_queue_ext;
 		max_rx_queue_size = min_t(u32, max_queue_ext->max_rx_cq_depth,
@@ -3427,27 +4120,30 @@
  */
 static int ena_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
+	struct ena_calc_queue_size_ctx calc_queue_ctx = {};
 	struct ena_com_dev_get_features_ctx get_feat_ctx;
-	struct ena_calc_queue_size_ctx calc_queue_ctx = { 0 };
-	struct ena_llq_configurations llq_config;
 	struct ena_com_dev *ena_dev = NULL;
 	struct ena_adapter *adapter;
-	int io_queue_num, bars, rc;
 	struct net_device *netdev;
 	static int adapters_found;
-	char *queue_type_str;
+	u32 max_num_io_queues;
 	bool wd_state;
+	int bars, rc;
 
 	dev_dbg(&pdev->dev, "%s\n", __func__);
 
-	dev_info_once(&pdev->dev, "%s", version);
-
 	rc = pci_enable_device_mem(pdev);
 	if (rc) {
 		dev_err(&pdev->dev, "pci_enable_device_mem() failed!\n");
 		return rc;
 	}
 
+	rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(ENA_MAX_PHYS_ADDR_SIZE_BITS));
+	if (rc) {
+		dev_err(&pdev->dev, "dma_set_mask_and_coherent failed %d\n", rc);
+		goto err_disable_device;
+	}
+
 	pci_set_master(pdev);
 
 	ena_dev = vzalloc(sizeof(*ena_dev));
@@ -3468,56 +4164,48 @@
 					pci_resource_start(pdev, ENA_REG_BAR),
 					pci_resource_len(pdev, ENA_REG_BAR));
 	if (!ena_dev->reg_bar) {
-		dev_err(&pdev->dev, "failed to remap regs bar\n");
+		dev_err(&pdev->dev, "Failed to remap regs bar\n");
 		rc = -EFAULT;
 		goto err_free_region;
 	}
 
+	ena_dev->ena_min_poll_delay_us = ENA_ADMIN_POLL_DELAY_US;
+
 	ena_dev->dmadev = &pdev->dev;
 
 	rc = ena_device_init(ena_dev, pdev, &get_feat_ctx, &wd_state);
 	if (rc) {
-		dev_err(&pdev->dev, "ena device init failed\n");
+		dev_err(&pdev->dev, "ENA device init failed\n");
 		if (rc == -ETIME)
 			rc = -EPROBE_DEFER;
 		goto err_free_region;
 	}
 
-	set_default_llq_configurations(&llq_config);
-
-	rc = ena_set_queues_placement_policy(pdev, ena_dev, &get_feat_ctx.llq,
-					     &llq_config);
+	rc = ena_map_llq_mem_bar(pdev, ena_dev, bars);
 	if (rc) {
-		dev_err(&pdev->dev, "ena device init failed\n");
-		goto err_device_destroy;
+		dev_err(&pdev->dev, "ENA llq bar mapping failed\n");
+		goto err_free_ena_dev;
 	}
 
 	calc_queue_ctx.ena_dev = ena_dev;
 	calc_queue_ctx.get_feat_ctx = &get_feat_ctx;
 	calc_queue_ctx.pdev = pdev;
 
-	/* Initial Tx and RX interrupt delay. Assumes 1 usec granularity.
-	* Updated during device initialization with the real granularity
-	*/
+	/* Initial TX and RX interrupt delay. Assumes 1 usec granularity.
+	 * Updated during device initialization with the real granularity
+	 */
 	ena_dev->intr_moder_tx_interval = ENA_INTR_INITIAL_TX_INTERVAL_USECS;
 	ena_dev->intr_moder_rx_interval = ENA_INTR_INITIAL_RX_INTERVAL_USECS;
 	ena_dev->intr_delay_resolution = ENA_DEFAULT_INTR_DELAY_RESOLUTION;
-	io_queue_num = ena_calc_io_queue_num(pdev, ena_dev, &get_feat_ctx);
-	rc = ena_calc_queue_size(&calc_queue_ctx);
-	if (rc || io_queue_num <= 0) {
+	max_num_io_queues = ena_calc_max_io_queue_num(pdev, ena_dev, &get_feat_ctx);
+	rc = ena_calc_io_queue_size(&calc_queue_ctx);
+	if (rc || !max_num_io_queues) {
 		rc = -EFAULT;
 		goto err_device_destroy;
 	}
 
-	dev_info(&pdev->dev, "creating %d io queues. rx queue size: %d tx queue size. %d LLQ is %s\n",
-		 io_queue_num,
-		 calc_queue_ctx.rx_queue_size,
-		 calc_queue_ctx.tx_queue_size,
-		 (ena_dev->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV) ?
-		 "ENABLED" : "DISABLED");
-
 	/* dev zeroed in init_etherdev */
-	netdev = alloc_etherdev_mq(sizeof(struct ena_adapter), io_queue_num);
+	netdev = alloc_etherdev_mq(sizeof(struct ena_adapter), max_num_io_queues);
 	if (!netdev) {
 		dev_err(&pdev->dev, "alloc_etherdev_mq failed\n");
 		rc = -ENOMEM;
@@ -3545,10 +4233,19 @@
 	adapter->max_tx_sgl_size = calc_queue_ctx.max_tx_sgl_size;
 	adapter->max_rx_sgl_size = calc_queue_ctx.max_rx_sgl_size;
 
-	adapter->num_queues = io_queue_num;
+	adapter->num_io_queues = max_num_io_queues;
+	adapter->max_num_io_queues = max_num_io_queues;
 	adapter->last_monitored_tx_qid = 0;
 
+	adapter->xdp_first_ring = 0;
+	adapter->xdp_num_queues = 0;
+
 	adapter->rx_copybreak = ENA_DEFAULT_RX_COPYBREAK;
+	if (ena_dev->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV)
+		adapter->disable_meta_caching =
+			!!(get_feat_ctx.llq.accel_mode.u.get.supported_flags &
+			   BIT(ENA_ADMIN_DISABLE_META_CACHING));
+
 	adapter->wd_state = wd_state;
 
 	snprintf(adapter->name, ENA_NAME_MAX_LEN, "ena_%d", adapters_found);
@@ -3559,7 +4256,10 @@
 			"Failed to query interrupt moderation feature\n");
 		goto err_netdev_destroy;
 	}
-	ena_init_io_rings(adapter);
+	ena_init_io_rings(adapter,
+			  0,
+			  adapter->xdp_num_queues +
+			  adapter->num_io_queues);
 
 	netdev->netdev_ops = &ena_netdev_ops;
 	netdev->watchdog_timeo = TX_TIMEOUT;
@@ -3569,7 +4269,7 @@
 
 	u64_stats_init(&adapter->syncp);
 
-	rc = ena_enable_msix_and_set_admin_interrupts(adapter, io_queue_num);
+	rc = ena_enable_msix_and_set_admin_interrupts(adapter);
 	if (rc) {
 		dev_err(&pdev->dev,
 			"Failed to enable and set the admin interrupts\n");
@@ -3583,6 +4283,11 @@
 
 	ena_config_debug_area(adapter);
 
+	if (!ena_update_hw_stats(adapter))
+		adapter->eni_stats_supported = true;
+	else
+		adapter->eni_stats_supported = false;
+
 	memcpy(adapter->netdev->perm_addr, adapter->mac_addr, netdev->addr_len);
 
 	netif_carrier_off(netdev);
@@ -3605,15 +4310,10 @@
 	timer_setup(&adapter->timer_service, ena_timer_service, 0);
 	mod_timer(&adapter->timer_service, round_jiffies(jiffies + HZ));
 
-	if (ena_dev->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_HOST)
-		queue_type_str = "Regular";
-	else
-		queue_type_str = "Low Latency";
-
 	dev_info(&pdev->dev,
-		 "%s found at mem %lx, mac addr %pM Queues %d, Placement policy: %s\n",
+		 "%s found at mem %lx, mac addr %pM\n",
 		 DEVICE_NAME, (long)pci_resource_start(pdev, 0),
-		 netdev->dev_addr, io_queue_num, queue_type_str);
+		 netdev->dev_addr);
 
 	set_bit(ENA_FLAG_DEVICE_RUNNING, &adapter->flags);
 
@@ -3648,13 +4348,15 @@
 
 /*****************************************************************************/
 
-/* ena_remove - Device Removal Routine
+/* __ena_shutoff - Helper used in both PCI remove/shutdown routines
  * @pdev: PCI device information struct
+ * @shutdown: Is it a shutdown operation? If false, means it is a removal
  *
- * ena_remove is called by the PCI subsystem to alert the driver
- * that it should release a PCI device.
+ * __ena_shutoff is a helper routine that does the real work on shutdown and
+ * removal paths; the difference between those paths is with regards to whether
+ * dettach or unregister the netdevice.
  */
-static void ena_remove(struct pci_dev *pdev)
+static void __ena_shutoff(struct pci_dev *pdev, bool shutdown)
 {
 	struct ena_adapter *adapter = pci_get_drvdata(pdev);
 	struct ena_com_dev *ena_dev;
@@ -3669,17 +4371,25 @@
 		netdev->rx_cpu_rmap = NULL;
 	}
 #endif /* CONFIG_RFS_ACCEL */
-	del_timer_sync(&adapter->timer_service);
 
+	/* Make sure timer and reset routine won't be called after
+	 * freeing device resources.
+	 */
+	del_timer_sync(&adapter->timer_service);
 	cancel_work_sync(&adapter->reset_task);
 
-	rtnl_lock();
+	rtnl_lock(); /* lock released inside the below if-else block */
+	adapter->reset_reason = ENA_REGS_RESET_SHUTDOWN;
 	ena_destroy_device(adapter, true);
-	rtnl_unlock();
-
-	unregister_netdev(netdev);
-
-	free_netdev(netdev);
+	if (shutdown) {
+		netif_device_detach(netdev);
+		dev_close(netdev);
+		rtnl_unlock();
+	} else {
+		rtnl_unlock();
+		unregister_netdev(netdev);
+		free_netdev(netdev);
+	}
 
 	ena_com_rss_destroy(ena_dev);
 
@@ -3694,13 +4404,36 @@
 	vfree(ena_dev);
 }
 
-#ifdef CONFIG_PM
-/* ena_suspend - PM suspend callback
+/* ena_remove - Device Removal Routine
+ * @pdev: PCI device information struct
+ *
+ * ena_remove is called by the PCI subsystem to alert the driver
+ * that it should release a PCI device.
+ */
+
+static void ena_remove(struct pci_dev *pdev)
+{
+	__ena_shutoff(pdev, false);
+}
+
+/* ena_shutdown - Device Shutdown Routine
  * @pdev: PCI device information struct
- * @state:power state
+ *
+ * ena_shutdown is called by the PCI subsystem to alert the driver that
+ * a shutdown/reboot (or kexec) is happening and device must be disabled.
  */
-static int ena_suspend(struct pci_dev *pdev,  pm_message_t state)
+
+static void ena_shutdown(struct pci_dev *pdev)
 {
+	__ena_shutoff(pdev, true);
+}
+
+/* ena_suspend - PM suspend callback
+ * @dev_d: Device information struct
+ */
+static int __maybe_unused ena_suspend(struct device *dev_d)
+{
+	struct pci_dev *pdev = to_pci_dev(dev_d);
 	struct ena_adapter *adapter = pci_get_drvdata(pdev);
 
 	u64_stats_update_begin(&adapter->syncp);
@@ -3710,7 +4443,7 @@
 	rtnl_lock();
 	if (unlikely(test_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags))) {
 		dev_err(&pdev->dev,
-			"ignoring device reset request as the device is being suspended\n");
+			"Ignoring device reset request as the device is being suspended\n");
 		clear_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags);
 	}
 	ena_destroy_device(adapter, true);
@@ -3719,12 +4452,11 @@
 }
 
 /* ena_resume - PM resume callback
- * @pdev: PCI device information struct
- *
+ * @dev_d: Device information struct
  */
-static int ena_resume(struct pci_dev *pdev)
+static int __maybe_unused ena_resume(struct device *dev_d)
 {
-	struct ena_adapter *adapter = pci_get_drvdata(pdev);
+	struct ena_adapter *adapter = dev_get_drvdata(dev_d);
 	int rc;
 
 	u64_stats_update_begin(&adapter->syncp);
@@ -3736,24 +4468,21 @@
 	rtnl_unlock();
 	return rc;
 }
-#endif
+
+static SIMPLE_DEV_PM_OPS(ena_pm_ops, ena_suspend, ena_resume);
 
 static struct pci_driver ena_pci_driver = {
 	.name		= DRV_MODULE_NAME,
 	.id_table	= ena_pci_tbl,
 	.probe		= ena_probe,
 	.remove		= ena_remove,
-#ifdef CONFIG_PM
-	.suspend    = ena_suspend,
-	.resume     = ena_resume,
-#endif
+	.shutdown	= ena_shutdown,
+	.driver.pm	= &ena_pm_ops,
 	.sriov_configure = pci_sriov_configure_simple,
 };
 
 static int __init ena_init(void)
 {
-	pr_info("%s", version);
-
 	ena_wq = create_singlethread_workqueue(DRV_MODULE_NAME);
 	if (!ena_wq) {
 		pr_err("Failed to create workqueue\n");
@@ -3789,7 +4518,7 @@
 		ENA_ADMIN_AENQ_LINK_CHANGE_DESC_LINK_STATUS_MASK;
 
 	if (status) {
-		netdev_dbg(adapter->netdev, "%s\n", __func__);
+		netif_dbg(adapter, ifup, adapter->netdev, "%s\n", __func__);
 		set_bit(ENA_FLAG_LINK_UP, &adapter->flags);
 		if (!test_bit(ENA_FLAG_ONGOING_RESET, &adapter->flags))
 			netif_carrier_on(adapter->netdev);
@@ -3805,14 +4534,20 @@
 	struct ena_adapter *adapter = (struct ena_adapter *)adapter_data;
 	struct ena_admin_aenq_keep_alive_desc *desc;
 	u64 rx_drops;
+	u64 tx_drops;
 
 	desc = (struct ena_admin_aenq_keep_alive_desc *)aenq_e;
 	adapter->last_keep_alive_jiffies = jiffies;
 
 	rx_drops = ((u64)desc->rx_drops_high << 32) | desc->rx_drops_low;
+	tx_drops = ((u64)desc->tx_drops_high << 32) | desc->tx_drops_low;
 
 	u64_stats_update_begin(&adapter->syncp);
+	/* These stats are accumulated by the device, so the counters indicate
+	 * all drops since last reset.
+	 */
 	adapter->dev_stats.rx_drops = rx_drops;
+	adapter->dev_stats.tx_drops = tx_drops;
 	u64_stats_update_end(&adapter->syncp);
 }
 
@@ -3827,7 +4562,7 @@
 	     aenq_e->aenq_common_desc.group,
 	     ENA_ADMIN_NOTIFICATION);
 
-	switch (aenq_e->aenq_common_desc.syndrom) {
+	switch (aenq_e->aenq_common_desc.syndrome) {
 	case ENA_ADMIN_UPDATE_HINTS:
 		hints = (struct ena_admin_ena_hw_hints *)
 			(&aenq_e->inline_data_w4);
@@ -3836,7 +4571,7 @@
 	default:
 		netif_err(adapter, drv, adapter->netdev,
 			  "Invalid aenq notification link state %d\n",
-			  aenq_e->aenq_common_desc.syndrom);
+			  aenq_e->aenq_common_desc.syndrome);
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/amazon/ena/ena_netdev.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/amazon/ena/ena_netdev.h
@@ -1,33 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
 /*
- * Copyright 2015 Amazon.com, Inc. or its affiliates.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
+ * Copyright 2015-2020 Amazon.com, Inc. or its affiliates. All rights reserved.
  */
 
 #ifndef ENA_H
@@ -36,6 +9,7 @@
 #include <linux/bitops.h>
 #include <linux/dim.h>
 #include <linux/etherdevice.h>
+#include <linux/if_vlan.h>
 #include <linux/inetdevice.h>
 #include <linux/interrupt.h>
 #include <linux/netdevice.h>
@@ -44,17 +18,11 @@
 #include "ena_com.h"
 #include "ena_eth_com.h"
 
-#define DRV_MODULE_VER_MAJOR	2
-#define DRV_MODULE_VER_MINOR	1
-#define DRV_MODULE_VER_SUBMINOR 0
+#define DRV_MODULE_GEN_MAJOR	2
+#define DRV_MODULE_GEN_MINOR	1
+#define DRV_MODULE_GEN_SUBMINOR 0
 
 #define DRV_MODULE_NAME		"ena"
-#ifndef DRV_MODULE_VERSION
-#define DRV_MODULE_VERSION \
-	__stringify(DRV_MODULE_VER_MAJOR) "."	\
-	__stringify(DRV_MODULE_VER_MINOR) "."	\
-	__stringify(DRV_MODULE_VER_SUBMINOR) "K"
-#endif
 
 #define DEVICE_NAME	"Elastic Network Adapter (ENA)"
 
@@ -68,7 +36,7 @@
  * 16kB.
  */
 #if PAGE_SIZE > SZ_16K
-#define ENA_PAGE_SIZE SZ_16K
+#define ENA_PAGE_SIZE (_AC(SZ_16K, UL))
 #else
 #define ENA_PAGE_SIZE PAGE_SIZE
 #endif
@@ -82,6 +50,8 @@
 #define ENA_DEFAULT_RING_SIZE	(1024)
 #define ENA_MIN_RING_SIZE	(256)
 
+#define ENA_MIN_NUM_IO_QUEUES	(1)
+
 #define ENA_TX_WAKEUP_THRESH		(MAX_SKB_FRAGS + 2)
 #define ENA_DEFAULT_RX_COPYBREAK	(256 - NET_IP_ALIGN)
 
@@ -101,8 +71,6 @@
 #define ENA_RX_RSS_TABLE_LOG_SIZE  7
 #define ENA_RX_RSS_TABLE_SIZE	(1 << ENA_RX_RSS_TABLE_LOG_SIZE)
 
-#define ENA_HASH_KEY_SIZE	40
-
 /* The number of tx packet completions that will be handled each NAPI poll
  * cycle is ring_size / ENA_TX_POLL_BUDGET_DIVIDER.
  */
@@ -127,11 +95,15 @@
 
 #define ENA_IO_TXQ_IDX(q)	(2 * (q))
 #define ENA_IO_RXQ_IDX(q)	(2 * (q) + 1)
+#define ENA_IO_TXQ_IDX_TO_COMBINED_IDX(q)	((q) / 2)
+#define ENA_IO_RXQ_IDX_TO_COMBINED_IDX(q)	(((q) - 1) / 2)
 
 #define ENA_MGMNT_IRQ_IDX		0
 #define ENA_IO_IRQ_FIRST_IDX		1
 #define ENA_IO_IRQ_IDX(q)		(ENA_IO_IRQ_FIRST_IDX + (q))
 
+#define ENA_ADMIN_POLL_DELAY_US 100
+
 /* ENA device should send keep alive msg every 1 sec.
  * We wait for 6 sec just to be on the safe side.
  */
@@ -140,6 +112,18 @@
 
 #define ENA_MMIO_DISABLE_REG_READ	BIT(0)
 
+/* The max MTU size is configured to be the ethernet frame size without
+ * the overhead of the ethernet header, which can have a VLAN header, and
+ * a frame check sequence (FCS).
+ * The buffer size we share with the device is defined to be ENA_PAGE_SIZE
+ */
+
+#define ENA_XDP_MAX_MTU (ENA_PAGE_SIZE - ETH_HLEN - ETH_FCS_LEN - \
+				VLAN_HLEN - XDP_PACKET_HEADROOM)
+
+#define ENA_IS_XDP_INDEX(adapter, index) (((index) >= (adapter)->xdp_first_ring) && \
+	((index) < (adapter)->xdp_first_ring + (adapter)->xdp_num_queues))
+
 struct ena_irq {
 	irq_handler_t handler;
 	void *data;
@@ -153,6 +137,9 @@
 	struct napi_struct napi ____cacheline_aligned;
 	struct ena_ring *tx_ring;
 	struct ena_ring *rx_ring;
+	struct ena_ring *xdp_ring;
+	bool first_interrupt;
+	bool interrupts_masked;
 	u32 qid;
 	struct dim dim;
 };
@@ -161,10 +148,10 @@
 	struct ena_com_dev_get_features_ctx *get_feat_ctx;
 	struct ena_com_dev *ena_dev;
 	struct pci_dev *pdev;
-	u16 tx_queue_size;
-	u16 rx_queue_size;
-	u16 max_tx_queue_size;
-	u16 max_rx_queue_size;
+	u32 tx_queue_size;
+	u32 rx_queue_size;
+	u32 max_tx_queue_size;
+	u32 max_rx_queue_size;
 	u16 max_tx_sgl_size;
 	u16 max_rx_sgl_size;
 };
@@ -178,6 +165,17 @@
 	/* num of buffers used by this skb */
 	u32 num_of_bufs;
 
+	/* XDP buffer structure which is used for sending packets in
+	 * the xdp queues
+	 */
+	struct xdp_frame *xdpf;
+	/* The rx page for the rx buffer that was received in rx and
+	 * re transmitted on xdp tx queues as a result of XDP_TX action.
+	 * We need to free the page once we finished cleaning the buffer in
+	 * clean_xdp_irq()
+	 */
+	struct page *xdp_rx_page;
+
 	/* Indicate if bufs[0] map the linear data of the skb. */
 	u8 map_linear_data;
 
@@ -218,6 +216,7 @@
 	u64 bad_req_id;
 	u64 llq_buffer_copy;
 	u64 missed_tx;
+	u64 unmask_interrupt;
 };
 
 struct ena_stats_rx {
@@ -234,6 +233,11 @@
 	u64 bad_req_id;
 	u64 empty_rx_ring;
 	u64 csum_unchecked;
+	u64 xdp_aborted;
+	u64 xdp_drop;
+	u64 xdp_pass;
+	u64 xdp_tx;
+	u64 xdp_invalid;
 };
 
 struct ena_ring {
@@ -256,10 +260,13 @@
 	struct ena_adapter *adapter;
 	struct ena_com_io_cq *ena_com_io_cq;
 	struct ena_com_io_sq *ena_com_io_sq;
+	struct bpf_prog *xdp_bpf_prog;
+	struct xdp_rxq_info xdp_rxq;
 
 	u16 next_to_use;
 	u16 next_to_clean;
 	u16 rx_copybreak;
+	u16 rx_headroom;
 	u16 qid;
 	u16 mtu;
 	u16 sgl_size;
@@ -268,6 +275,7 @@
 	u8 tx_max_header_size;
 
 	bool first_interrupt;
+	bool disable_meta_caching;
 	u16 no_interrupt_event_cnt;
 
 	/* cpu for TPH */
@@ -300,6 +308,7 @@
 	u64 interface_down;
 	u64 admin_q_pause;
 	u64 rx_drops;
+	u64 tx_drops;
 };
 
 enum ena_flags_t {
@@ -324,7 +333,8 @@
 	u32 rx_copybreak;
 	u32 max_mtu;
 
-	int num_queues;
+	u32 num_io_queues;
+	u32 max_num_io_queues;
 
 	int msix_vecs;
 
@@ -367,15 +377,22 @@
 
 	bool wd_state;
 	bool dev_up_before_reset;
+	bool disable_meta_caching;
 	unsigned long last_keep_alive_jiffies;
 
 	struct u64_stats_sync syncp;
 	struct ena_stats_dev dev_stats;
+	struct ena_admin_eni_stats eni_stats;
+	bool eni_stats_supported;
 
 	/* last queue index that was checked for uncompleted tx packets */
 	u32 last_monitored_tx_qid;
 
 	enum ena_regs_reset_reason_types reset_reason;
+
+	struct bpf_prog *xdp_bpf_prog;
+	u32 xdp_first_ring;
+	u32 xdp_num_queues;
 };
 
 void ena_set_ethtool_ops(struct net_device *netdev);
@@ -384,10 +401,53 @@
 
 void ena_dump_stats_to_buf(struct ena_adapter *adapter, u8 *buf);
 
+int ena_update_hw_stats(struct ena_adapter *adapter);
+
 int ena_update_queue_sizes(struct ena_adapter *adapter,
 			   u32 new_tx_size,
 			   u32 new_rx_size);
 
+int ena_update_queue_count(struct ena_adapter *adapter, u32 new_channel_count);
+
 int ena_get_sset_count(struct net_device *netdev, int sset);
 
+enum ena_xdp_errors_t {
+	ENA_XDP_ALLOWED = 0,
+	ENA_XDP_CURRENT_MTU_TOO_LARGE,
+	ENA_XDP_NO_ENOUGH_QUEUES,
+};
+
+static inline bool ena_xdp_queues_present(struct ena_adapter *adapter)
+{
+	return adapter->xdp_first_ring != 0;
+}
+
+static inline bool ena_xdp_present(struct ena_adapter *adapter)
+{
+	return !!adapter->xdp_bpf_prog;
+}
+
+static inline bool ena_xdp_present_ring(struct ena_ring *ring)
+{
+	return !!ring->xdp_bpf_prog;
+}
+
+static inline int ena_xdp_legal_queue_count(struct ena_adapter *adapter,
+					    u32 queues)
+{
+	return 2 * queues <= adapter->max_num_io_queues;
+}
+
+static inline enum ena_xdp_errors_t ena_xdp_allowed(struct ena_adapter *adapter)
+{
+	enum ena_xdp_errors_t rc = ENA_XDP_ALLOWED;
+
+	if (adapter->netdev->mtu > ENA_XDP_MAX_MTU)
+		rc = ENA_XDP_CURRENT_MTU_TOO_LARGE;
+	else if (!ena_xdp_legal_queue_count(adapter, adapter->num_io_queues))
+		rc = ENA_XDP_NO_ENOUGH_QUEUES;
+
+	return rc;
+}
+
 #endif /* !(ENA_H) */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/amazon/ena/ena_pci_id_tbl.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/amazon/ena/ena_pci_id_tbl.h
@@ -1,33 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
 /*
- * Copyright 2015 Amazon.com, Inc. or its affiliates.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
+ * Copyright 2015-2020 Amazon.com, Inc. or its affiliates. All rights reserved.
  */
 
 #ifndef ENA_PCI_ID_TBL_H_
@@ -53,10 +26,15 @@
 #define PCI_DEV_ID_ENA_LLQ_VF	0xec21
 #endif
 
+#ifndef PCI_DEV_ID_ENA_RESRV0
+#define PCI_DEV_ID_ENA_RESRV0	0x0051
+#endif
+
 #define ENA_PCI_ID_TABLE_ENTRY(devid) \
 	{PCI_DEVICE(PCI_VENDOR_ID_AMAZON, devid)},
 
 static const struct pci_device_id ena_pci_tbl[] = {
+	ENA_PCI_ID_TABLE_ENTRY(PCI_DEV_ID_ENA_RESRV0)
 	ENA_PCI_ID_TABLE_ENTRY(PCI_DEV_ID_ENA_PF)
 	ENA_PCI_ID_TABLE_ENTRY(PCI_DEV_ID_ENA_LLQ_PF)
 	ENA_PCI_ID_TABLE_ENTRY(PCI_DEV_ID_ENA_VF)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/amazon/ena/ena_regs_defs.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/amazon/ena/ena_regs_defs.h
@@ -1,33 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
 /*
- * Copyright 2015 - 2016 Amazon.com, Inc. or its affiliates.
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the
- * BSD license below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
+ * Copyright 2015-2020 Amazon.com, Inc. or its affiliates. All rights reserved.
  */
 #ifndef _ENA_REGS_H_
 #define _ENA_REGS_H_
@@ -154,4 +127,4 @@
 #define ENA_REGS_RSS_IND_ENTRY_UPDATE_CQ_IDX_SHIFT          16
 #define ENA_REGS_RSS_IND_ENTRY_UPDATE_CQ_IDX_MASK           0xffff0000
 
-#endif /*_ENA_REGS_H_ */
+#endif /* _ENA_REGS_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/amd/atarilance.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/amd/atarilance.c
@@ -825,7 +825,7 @@
 	lp->memcpy_f( PKTBUF_ADDR(head), (void *)skb->data, skb->len );
 	head->flag = TMD1_OWN_CHIP | TMD1_ENP | TMD1_STP;
 	dev->stats.tx_bytes += skb->len;
-	dev_kfree_skb( skb );
+	dev_consume_skb_irq(skb);
 	lp->cur_tx++;
 	while( lp->cur_tx >= TX_RING_SIZE && lp->dirty_tx >= TX_RING_SIZE ) {
 		lp->cur_tx -= TX_RING_SIZE;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/amd/lance.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/amd/lance.c
@@ -997,7 +997,7 @@
 		skb_copy_from_linear_data(skb, &lp->tx_bounce_buffs[entry], skb->len);
 		lp->tx_ring[entry].base =
 			((u32)isa_virt_to_bus((lp->tx_bounce_buffs + entry)) & 0xffffff) | 0x83000000;
-		dev_kfree_skb(skb);
+		dev_consume_skb_irq(skb);
 	} else {
 		lp->tx_skbuff[entry] = skb;
 		lp->tx_ring[entry].base = ((u32)isa_virt_to_bus(skb->data) & 0xffffff) | 0x83000000;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/amd/mvme147.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/amd/mvme147.c
@@ -106,10 +106,6 @@
 	address = address >> 8;
 	dev->dev_addr[3] = address&0xff;
 
-	printk("%s: MVME147 at 0x%08lx, irq %d, Hardware Address %pM\n",
-	       dev->name, dev->base_addr, MVME147_LANCE_IRQ,
-	       dev->dev_addr);
-
 	lp = netdev_priv(dev);
 	lp->ram = __get_dma_pages(GFP_ATOMIC, 3);	/* 32K */
 	if (!lp->ram) {
@@ -139,6 +135,9 @@
 		return ERR_PTR(err);
 	}
 
+	netdev_info(dev, "MVME147 at 0x%08lx, irq %d, Hardware Address %pM\n",
+		    dev->base_addr, MVME147_LANCE_IRQ, dev->dev_addr);
+
 	return dev;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/amd/nmclan_cs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/amd/nmclan_cs.c
@@ -652,7 +652,7 @@
     } else {
       pr_notice("mace id not found: %x %x should be 0x40 0x?9\n",
 		sig[0], sig[1]);
-      return -ENODEV;
+      goto failed;
     }
   }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/amd/pcnet32.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/amd/pcnet32.c
@@ -1548,8 +1548,7 @@
 	}
 	pci_set_master(pdev);
 
-	ioaddr = pci_resource_start(pdev, 0);
-	if (!ioaddr) {
+	if (!pci_resource_len(pdev, 0)) {
 		if (pcnet32_debug & NETIF_MSG_PROBE)
 			pr_err("card has no PCI IO resources, aborting\n");
 		err = -ENODEV;
@@ -1562,6 +1561,8 @@
 			pr_err("architecture does not support 32bit PCI busmaster DMA\n");
 		goto err_disable_dev;
 	}
+
+	ioaddr = pci_resource_start(pdev, 0);
 	if (!request_region(ioaddr, PCNET32_TOTAL_SIZE, "pcnet32_probe_pci")) {
 		if (pcnet32_debug & NETIF_MSG_PROBE)
 			pr_err("io address range already allocated\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/amd/xgbe/xgbe-common.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/amd/xgbe/xgbe-common.h
@@ -1279,10 +1279,18 @@
 #define MDIO_PMA_10GBR_FECCTRL		0x00ab
 #endif
 
+#ifndef MDIO_PMA_RX_CTRL1
+#define MDIO_PMA_RX_CTRL1		0x8051
+#endif
+
 #ifndef MDIO_PCS_DIG_CTRL
 #define MDIO_PCS_DIG_CTRL		0x8000
 #endif
 
+#ifndef MDIO_PCS_DIGITAL_STAT
+#define MDIO_PCS_DIGITAL_STAT		0x8010
+#endif
+
 #ifndef MDIO_AN_XNP
 #define MDIO_AN_XNP			0x0016
 #endif
@@ -1323,6 +1331,10 @@
 #define MDIO_VEND2_PMA_CDR_CONTROL	0x8056
 #endif
 
+#ifndef MDIO_VEND2_PMA_MISC_CTRL0
+#define MDIO_VEND2_PMA_MISC_CTRL0	0x8090
+#endif
+
 #ifndef MDIO_CTRL1_SPEED1G
 #define MDIO_CTRL1_SPEED1G		(MDIO_CTRL1_SPEED10G & ~BMCR_SPEED100)
 #endif
@@ -1358,6 +1370,8 @@
 #define XGBE_KR_TRAINING_ENABLE		BIT(1)
 
 #define XGBE_PCS_CL37_BP		BIT(12)
+#define XGBE_PCS_PSEQ_STATE_MASK	0x1c
+#define XGBE_PCS_PSEQ_STATE_POWER_GOOD	0x10
 
 #define XGBE_AN_CL37_INT_CMPLT		BIT(0)
 #define XGBE_AN_CL37_INT_MASK		0x01
@@ -1375,6 +1389,14 @@
 #define XGBE_PMA_CDR_TRACK_EN_OFF	0x00
 #define XGBE_PMA_CDR_TRACK_EN_ON	0x01
 
+#define XGBE_PMA_RX_RST_0_MASK		BIT(4)
+#define XGBE_PMA_RX_RST_0_RESET_ON	0x10
+#define XGBE_PMA_RX_RST_0_RESET_OFF	0x00
+
+#define XGBE_PMA_PLL_CTRL_MASK		BIT(15)
+#define XGBE_PMA_PLL_CTRL_ENABLE	BIT(15)
+#define XGBE_PMA_PLL_CTRL_DISABLE	0x0000
+
 /* Bit setting and getting macros
  *  The get macro will extract the current bit field value from within
  *  the variable
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -524,19 +524,28 @@
 	netif_dbg(pdata, drv, pdata->netdev, "VXLAN acceleration disabled\n");
 }
 
+static unsigned int xgbe_get_fc_queue_count(struct xgbe_prv_data *pdata)
+{
+	unsigned int max_q_count = XGMAC_MAX_FLOW_CONTROL_QUEUES;
+
+	/* From MAC ver 30H the TFCR is per priority, instead of per queue */
+	if (XGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER) >= 0x30)
+		return max_q_count;
+	else
+		return min_t(unsigned int, pdata->tx_q_count, max_q_count);
+}
+
 static int xgbe_disable_tx_flow_control(struct xgbe_prv_data *pdata)
 {
-	unsigned int max_q_count, q_count;
 	unsigned int reg, reg_val;
-	unsigned int i;
+	unsigned int i, q_count;
 
 	/* Clear MTL flow control */
 	for (i = 0; i < pdata->rx_q_count; i++)
 		XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, EHFC, 0);
 
 	/* Clear MAC flow control */
-	max_q_count = XGMAC_MAX_FLOW_CONTROL_QUEUES;
-	q_count = min_t(unsigned int, pdata->tx_q_count, max_q_count);
+	q_count = xgbe_get_fc_queue_count(pdata);
 	reg = MAC_Q0TFCR;
 	for (i = 0; i < q_count; i++) {
 		reg_val = XGMAC_IOREAD(pdata, reg);
@@ -553,9 +562,8 @@
 {
 	struct ieee_pfc *pfc = pdata->pfc;
 	struct ieee_ets *ets = pdata->ets;
-	unsigned int max_q_count, q_count;
 	unsigned int reg, reg_val;
-	unsigned int i;
+	unsigned int i, q_count;
 
 	/* Set MTL flow control */
 	for (i = 0; i < pdata->rx_q_count; i++) {
@@ -579,8 +587,7 @@
 	}
 
 	/* Set MAC flow control */
-	max_q_count = XGMAC_MAX_FLOW_CONTROL_QUEUES;
-	q_count = min_t(unsigned int, pdata->tx_q_count, max_q_count);
+	q_count = xgbe_get_fc_queue_count(pdata);
 	reg = MAC_Q0TFCR;
 	for (i = 0; i < q_count; i++) {
 		reg_val = XGMAC_IOREAD(pdata, reg);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -514,7 +514,7 @@
 				xgbe_disable_rx_tx_ints(pdata);
 
 				/* Turn on polling */
-				__napi_schedule_irqoff(&pdata->napi);
+				__napi_schedule(&pdata->napi);
 			}
 		} else {
 			/* Don't clear Rx/Tx status if doing per channel DMA
@@ -682,10 +682,24 @@
 static void xgbe_service_timer(struct timer_list *t)
 {
 	struct xgbe_prv_data *pdata = from_timer(pdata, t, service_timer);
+	struct xgbe_channel *channel;
+	unsigned int i;
 
 	queue_work(pdata->dev_workqueue, &pdata->service_work);
 
 	mod_timer(&pdata->service_timer, jiffies + HZ);
+
+	if (!pdata->tx_usecs)
+		return;
+
+	for (i = 0; i < pdata->channel_count; i++) {
+		channel = pdata->channel[i];
+		if (!channel->tx_ring || channel->tx_timer_active)
+			break;
+		channel->tx_timer_active = 1;
+		mod_timer(&channel->tx_timer,
+			  jiffies + usecs_to_jiffies(pdata->tx_usecs));
+	}
 }
 
 static void xgbe_init_timers(struct xgbe_prv_data *pdata)
@@ -721,7 +735,9 @@
 		if (!channel->tx_ring)
 			break;
 
+		/* Deactivate the Tx timer */
 		del_timer_sync(&channel->tx_timer);
+		channel->tx_timer_active = 0;
 	}
 }
 
@@ -1137,6 +1153,9 @@
 
 	devm_free_irq(pdata->dev, pdata->dev_irq, pdata);
 
+	tasklet_kill(&pdata->tasklet_dev);
+	tasklet_kill(&pdata->tasklet_ecc);
+
 	if (pdata->vdata->ecc_support && (pdata->dev_irq != pdata->ecc_irq))
 		devm_free_irq(pdata->dev, pdata->ecc_irq, pdata);
 
@@ -1443,6 +1462,7 @@
 		return;
 
 	netif_tx_stop_all_queues(netdev);
+	netif_carrier_off(pdata->netdev);
 
 	xgbe_stop_timers(pdata);
 	flush_workqueue(pdata->dev_workqueue);
@@ -2764,6 +2784,14 @@
 			buf2_len = xgbe_rx_buf2_len(rdata, packet, len);
 			len += buf2_len;
 
+			if (buf2_len > rdata->rx.buf.dma_len) {
+				/* Hardware inconsistency within the descriptors
+				 * that has resulted in a length underflow.
+				 */
+				error = 1;
+				goto skip_data;
+			}
+
 			if (!skb) {
 				skb = xgbe_create_skb(pdata, napi, rdata,
 						      buf1_len);
@@ -2793,8 +2821,10 @@
 		if (!last || context_next)
 			goto read_again;
 
-		if (!skb)
+		if (!skb || error) {
+			dev_kfree_skb(skb);
 			goto next_packet;
+		}
 
 		/* Be sure we don't exceed the configured MTU */
 		max_len = netdev->mtu + ETH_HLEN;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
@@ -314,10 +314,15 @@
 
 	cmd->base.phy_address = pdata->phy.address;
 
-	cmd->base.autoneg = pdata->phy.autoneg;
-	cmd->base.speed = pdata->phy.speed;
-	cmd->base.duplex = pdata->phy.duplex;
+	if (netif_carrier_ok(netdev)) {
+		cmd->base.speed = pdata->phy.speed;
+		cmd->base.duplex = pdata->phy.duplex;
+	} else {
+		cmd->base.speed = SPEED_UNKNOWN;
+		cmd->base.duplex = DUPLEX_UNKNOWN;
+	}
 
+	cmd->base.autoneg = pdata->phy.autoneg;
 	cmd->base.port = PORT_NONE;
 
 	XGBE_LM_COPY(cmd, supported, lks, supported);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c
@@ -447,8 +447,10 @@
 	xgbe_i2c_disable(pdata);
 	xgbe_i2c_clear_all_interrupts(pdata);
 
-	if (pdata->dev_irq != pdata->i2c_irq)
+	if (pdata->dev_irq != pdata->i2c_irq) {
 		devm_free_irq(pdata->dev, pdata->i2c_irq, pdata);
+		tasklet_kill(&pdata->tasklet_i2c);
+	}
 }
 
 static int xgbe_i2c_start(struct xgbe_prv_data *pdata)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
@@ -496,6 +496,7 @@
 	reg |= XGBE_KR_TRAINING_ENABLE;
 	reg |= XGBE_KR_TRAINING_START;
 	XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg);
+	pdata->kr_start_time = jiffies;
 
 	netif_dbg(pdata, link, pdata->netdev,
 		  "KR training initiated\n");
@@ -632,6 +633,8 @@
 
 	xgbe_switch_mode(pdata);
 
+	pdata->an_result = XGBE_AN_READY;
+
 	xgbe_an_restart(pdata);
 
 	return XGBE_AN_INCOMPAT_LINK;
@@ -1175,7 +1178,19 @@
 	if (pdata->phy.duplex != DUPLEX_FULL)
 		return -EINVAL;
 
-	xgbe_set_mode(pdata, mode);
+	/* Force the mode change for SFI in Fixed PHY config.
+	 * Fixed PHY configs needs PLL to be enabled while doing mode set.
+	 * When the SFP module isn't connected during boot, driver assumes
+	 * AN is ON and attempts autonegotiation. However, if the connected
+	 * SFP comes up in Fixed PHY config, the link will not come up as
+	 * PLL isn't enabled while the initial mode set command is issued.
+	 * So, force the mode change for SFI in Fixed PHY configuration to
+	 * fix link issues.
+	 */
+	if (mode == XGBE_MODE_SFI)
+		xgbe_change_mode(pdata, mode);
+	else
+		xgbe_set_mode(pdata, mode);
 
 	return 0;
 }
@@ -1275,9 +1290,30 @@
 static void xgbe_check_link_timeout(struct xgbe_prv_data *pdata)
 {
 	unsigned long link_timeout;
+	unsigned long kr_time;
+	int wait;
 
 	link_timeout = pdata->link_check + (XGBE_LINK_TIMEOUT * HZ);
 	if (time_after(jiffies, link_timeout)) {
+		if ((xgbe_cur_mode(pdata) == XGBE_MODE_KR) &&
+		    pdata->phy.autoneg == AUTONEG_ENABLE) {
+			/* AN restart should not happen while KR training is in progress.
+			 * The while loop ensures no AN restart during KR training,
+			 * waits up to 500ms and AN restart is triggered only if KR
+			 * training is failed.
+			 */
+			wait = XGBE_KR_TRAINING_WAIT_ITER;
+			while (wait--) {
+				kr_time = pdata->kr_start_time +
+					  msecs_to_jiffies(XGBE_AN_MS_TIMEOUT);
+				if (time_after(jiffies, kr_time))
+					break;
+				/* AN restart is not required, if AN result is COMPLETE */
+				if (pdata->an_result == XGBE_AN_COMPLETE)
+					return;
+				usleep_range(10000, 11000);
+			}
+		}
 		netif_dbg(pdata, link, pdata->netdev, "AN link timeout\n");
 		xgbe_phy_config_aneg(pdata);
 	}
@@ -1288,7 +1324,7 @@
 	return pdata->phy_if.phy_impl.an_outcome(pdata);
 }
 
-static void xgbe_phy_status_result(struct xgbe_prv_data *pdata)
+static bool xgbe_phy_status_result(struct xgbe_prv_data *pdata)
 {
 	struct ethtool_link_ksettings *lks = &pdata->phy.lks;
 	enum xgbe_mode mode;
@@ -1323,8 +1359,13 @@
 
 	pdata->phy.duplex = DUPLEX_FULL;
 
-	if (xgbe_set_mode(pdata, mode) && pdata->an_again)
+	if (!xgbe_set_mode(pdata, mode))
+		return false;
+
+	if (pdata->an_again)
 		xgbe_phy_reconfig_aneg(pdata);
+
+	return true;
 }
 
 static void xgbe_phy_status(struct xgbe_prv_data *pdata)
@@ -1345,7 +1386,7 @@
 							     &an_restart);
 	if (an_restart) {
 		xgbe_phy_config_aneg(pdata);
-		return;
+		goto adjust_link;
 	}
 
 	if (pdata->phy.link) {
@@ -1354,7 +1395,8 @@
 			return;
 		}
 
-		xgbe_phy_status_result(pdata);
+		if (xgbe_phy_status_result(pdata))
+			return;
 
 		if (test_bit(XGBE_LINK_INIT, &pdata->dev_state))
 			clear_bit(XGBE_LINK_INIT, &pdata->dev_state);
@@ -1390,13 +1432,14 @@
 	/* Disable auto-negotiation */
 	xgbe_an_disable_all(pdata);
 
-	if (pdata->dev_irq != pdata->an_irq)
+	if (pdata->dev_irq != pdata->an_irq) {
 		devm_free_irq(pdata->dev, pdata->an_irq, pdata);
+		tasklet_kill(&pdata->tasklet_an);
+	}
 
 	pdata->phy_if.phy_impl.stop(pdata);
 
 	pdata->phy.link = 0;
-	netif_carrier_off(pdata->netdev);
 
 	xgbe_phy_adjust_link(pdata);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/amd/xgbe/xgbe-pci.c
@@ -418,6 +418,9 @@
 
 	pci_free_irq_vectors(pdata->pcidev);
 
+	/* Disable all interrupts in the hardware */
+	XP_IOWRITE(pdata, XP_INT_EN, 0x0);
+
 	xgbe_free_pdata(pdata);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
@@ -188,6 +188,7 @@
 	XGBE_SFP_CABLE_UNKNOWN = 0,
 	XGBE_SFP_CABLE_ACTIVE,
 	XGBE_SFP_CABLE_PASSIVE,
+	XGBE_SFP_CABLE_FIBER,
 };
 
 enum xgbe_sfp_base {
@@ -235,9 +236,7 @@
 
 #define XGBE_SFP_BASE_BR			12
 #define XGBE_SFP_BASE_BR_1GBE_MIN		0x0a
-#define XGBE_SFP_BASE_BR_1GBE_MAX		0x0d
 #define XGBE_SFP_BASE_BR_10GBE_MIN		0x64
-#define XGBE_SFP_BASE_BR_10GBE_MAX		0x68
 
 #define XGBE_SFP_BASE_CU_CABLE_LEN		18
 
@@ -283,6 +282,8 @@
 #define XGBE_BEL_FUSE_VENDOR	"BEL-FUSE        "
 #define XGBE_BEL_FUSE_PARTNO	"1GBT-SFP06      "
 
+#define XGBE_MOLEX_VENDOR	"Molex Inc.      "
+
 struct xgbe_sfp_ascii {
 	union {
 		char vendor[XGBE_SFP_BASE_VENDOR_NAME_LEN + 1];
@@ -822,25 +823,22 @@
 static bool xgbe_phy_sfp_bit_rate(struct xgbe_sfp_eeprom *sfp_eeprom,
 				  enum xgbe_sfp_speed sfp_speed)
 {
-	u8 *sfp_base, min, max;
+	u8 *sfp_base, min;
 
 	sfp_base = sfp_eeprom->base;
 
 	switch (sfp_speed) {
 	case XGBE_SFP_SPEED_1000:
 		min = XGBE_SFP_BASE_BR_1GBE_MIN;
-		max = XGBE_SFP_BASE_BR_1GBE_MAX;
 		break;
 	case XGBE_SFP_SPEED_10000:
 		min = XGBE_SFP_BASE_BR_10GBE_MIN;
-		max = XGBE_SFP_BASE_BR_10GBE_MAX;
 		break;
 	default:
 		return false;
 	}
 
-	return ((sfp_base[XGBE_SFP_BASE_BR] >= min) &&
-		(sfp_base[XGBE_SFP_BASE_BR] <= max));
+	return sfp_base[XGBE_SFP_BASE_BR] >= min;
 }
 
 static void xgbe_phy_free_phy_device(struct xgbe_prv_data *pdata)
@@ -857,7 +855,6 @@
 
 static bool xgbe_phy_finisar_phy_quirks(struct xgbe_prv_data *pdata)
 {
-	__ETHTOOL_DECLARE_LINK_MODE_MASK(supported) = { 0, };
 	struct xgbe_phy_data *phy_data = pdata->phy_data;
 	unsigned int phy_id = phy_data->phydev->phy_id;
 
@@ -879,14 +876,7 @@
 	phy_write(phy_data->phydev, 0x04, 0x0d01);
 	phy_write(phy_data->phydev, 0x00, 0x9140);
 
-	linkmode_set_bit_array(phy_10_100_features_array,
-			       ARRAY_SIZE(phy_10_100_features_array),
-			       supported);
-	linkmode_set_bit_array(phy_gbit_features_array,
-			       ARRAY_SIZE(phy_gbit_features_array),
-			       supported);
-
-	linkmode_copy(phy_data->phydev->supported, supported);
+	linkmode_copy(phy_data->phydev->supported, PHY_GBIT_FEATURES);
 
 	phy_support_asym_pause(phy_data->phydev);
 
@@ -898,7 +888,6 @@
 
 static bool xgbe_phy_belfuse_phy_quirks(struct xgbe_prv_data *pdata)
 {
-	__ETHTOOL_DECLARE_LINK_MODE_MASK(supported) = { 0, };
 	struct xgbe_phy_data *phy_data = pdata->phy_data;
 	struct xgbe_sfp_eeprom *sfp_eeprom = &phy_data->sfp_eeprom;
 	unsigned int phy_id = phy_data->phydev->phy_id;
@@ -921,6 +910,9 @@
 	if ((phy_id & 0xfffffff0) != 0x03625d10)
 		return false;
 
+	/* Reset PHY - wait for self-clearing reset bit to clear */
+	genphy_soft_reset(phy_data->phydev);
+
 	/* Disable RGMII mode */
 	phy_write(phy_data->phydev, 0x18, 0x7007);
 	reg = phy_read(phy_data->phydev, 0x18);
@@ -959,13 +951,7 @@
 	reg = phy_read(phy_data->phydev, 0x00);
 	phy_write(phy_data->phydev, 0x00, reg & ~0x00800);
 
-	linkmode_set_bit_array(phy_10_100_features_array,
-			       ARRAY_SIZE(phy_10_100_features_array),
-			       supported);
-	linkmode_set_bit_array(phy_gbit_features_array,
-			       ARRAY_SIZE(phy_gbit_features_array),
-			       supported);
-	linkmode_copy(phy_data->phydev->supported, supported);
+	linkmode_copy(phy_data->phydev->supported, PHY_GBIT_FEATURES);
 	phy_support_asym_pause(phy_data->phydev);
 
 	netif_dbg(pdata, drv, pdata->netdev,
@@ -1138,16 +1124,21 @@
 	phy_data->sfp_tx_fault = xgbe_phy_check_sfp_tx_fault(phy_data);
 	phy_data->sfp_rx_los = xgbe_phy_check_sfp_rx_los(phy_data);
 
-	/* Assume ACTIVE cable unless told it is PASSIVE */
+	/* Assume FIBER cable unless told otherwise */
 	if (sfp_base[XGBE_SFP_BASE_CABLE] & XGBE_SFP_BASE_CABLE_PASSIVE) {
 		phy_data->sfp_cable = XGBE_SFP_CABLE_PASSIVE;
 		phy_data->sfp_cable_len = sfp_base[XGBE_SFP_BASE_CU_CABLE_LEN];
-	} else {
+	} else if (sfp_base[XGBE_SFP_BASE_CABLE] & XGBE_SFP_BASE_CABLE_ACTIVE) {
 		phy_data->sfp_cable = XGBE_SFP_CABLE_ACTIVE;
+	} else {
+		phy_data->sfp_cable = XGBE_SFP_CABLE_FIBER;
 	}
 
 	/* Determine the type of SFP */
-	if (sfp_base[XGBE_SFP_BASE_10GBE_CC] & XGBE_SFP_BASE_10GBE_CC_SR)
+	if (phy_data->sfp_cable != XGBE_SFP_CABLE_FIBER &&
+	    xgbe_phy_sfp_bit_rate(sfp_eeprom, XGBE_SFP_SPEED_10000))
+		phy_data->sfp_base = XGBE_SFP_BASE_10000_CR;
+	else if (sfp_base[XGBE_SFP_BASE_10GBE_CC] & XGBE_SFP_BASE_10GBE_CC_SR)
 		phy_data->sfp_base = XGBE_SFP_BASE_10000_SR;
 	else if (sfp_base[XGBE_SFP_BASE_10GBE_CC] & XGBE_SFP_BASE_10GBE_CC_LR)
 		phy_data->sfp_base = XGBE_SFP_BASE_10000_LR;
@@ -1163,9 +1154,6 @@
 		phy_data->sfp_base = XGBE_SFP_BASE_1000_CX;
 	else if (sfp_base[XGBE_SFP_BASE_1GBE_CC] & XGBE_SFP_BASE_1GBE_CC_T)
 		phy_data->sfp_base = XGBE_SFP_BASE_1000_T;
-	else if ((phy_data->sfp_cable == XGBE_SFP_CABLE_PASSIVE) &&
-		 xgbe_phy_sfp_bit_rate(sfp_eeprom, XGBE_SFP_SPEED_10000))
-		phy_data->sfp_base = XGBE_SFP_BASE_10000_CR;
 
 	switch (phy_data->sfp_base) {
 	case XGBE_SFP_BASE_1000_T:
@@ -1948,16 +1936,53 @@
 	xgbe_phy_put_comm_ownership(pdata);
 }
 
+static void xgbe_phy_rx_reset(struct xgbe_prv_data *pdata)
+{
+	int reg;
+
+	reg = XMDIO_READ_BITS(pdata, MDIO_MMD_PCS, MDIO_PCS_DIGITAL_STAT,
+			      XGBE_PCS_PSEQ_STATE_MASK);
+	if (reg == XGBE_PCS_PSEQ_STATE_POWER_GOOD) {
+		/* Mailbox command timed out, reset of RX block is required.
+		 * This can be done by asseting the reset bit and wait for
+		 * its compeletion.
+		 */
+		XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_RX_CTRL1,
+				 XGBE_PMA_RX_RST_0_MASK, XGBE_PMA_RX_RST_0_RESET_ON);
+		ndelay(20);
+		XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_RX_CTRL1,
+				 XGBE_PMA_RX_RST_0_MASK, XGBE_PMA_RX_RST_0_RESET_OFF);
+		usleep_range(40, 50);
+		netif_err(pdata, link, pdata->netdev, "firmware mailbox reset performed\n");
+	}
+}
+
+static void xgbe_phy_pll_ctrl(struct xgbe_prv_data *pdata, bool enable)
+{
+	XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_VEND2_PMA_MISC_CTRL0,
+			 XGBE_PMA_PLL_CTRL_MASK,
+			 enable ? XGBE_PMA_PLL_CTRL_ENABLE
+				: XGBE_PMA_PLL_CTRL_DISABLE);
+
+	/* Wait for command to complete */
+	usleep_range(100, 200);
+}
+
 static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata,
 					unsigned int cmd, unsigned int sub_cmd)
 {
 	unsigned int s0 = 0;
 	unsigned int wait;
 
+	/* Disable PLL re-initialization during FW command processing */
+	xgbe_phy_pll_ctrl(pdata, false);
+
 	/* Log if a previous command did not complete */
-	if (XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS))
+	if (XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS)) {
 		netif_dbg(pdata, link, pdata->netdev,
 			  "firmware mailbox not ready for command\n");
+		xgbe_phy_rx_reset(pdata);
+	}
 
 	/* Construct the command */
 	XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, cmd);
@@ -1972,13 +1997,20 @@
 	wait = XGBE_RATECHANGE_COUNT;
 	while (wait--) {
 		if (!XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS))
-			return;
+			goto reenable_pll;
 
 		usleep_range(1000, 2000);
 	}
 
 	netif_dbg(pdata, link, pdata->netdev,
 		  "firmware mailbox command did not complete\n");
+
+	/* Reset on error */
+	xgbe_phy_rx_reset(pdata);
+
+reenable_pll:
+	/* Enable PLL re-initialization */
+	xgbe_phy_pll_ctrl(pdata, true);
 }
 
 static void xgbe_phy_rrc(struct xgbe_prv_data *pdata)
@@ -2575,6 +2607,14 @@
 	if (reg & MDIO_STAT1_LSTATUS)
 		return 1;
 
+	if (pdata->phy.autoneg == AUTONEG_ENABLE &&
+	    phy_data->port_mode == XGBE_PORT_MODE_BACKPLANE) {
+		if (!test_bit(XGBE_LINK_INIT, &pdata->dev_state)) {
+			netif_carrier_off(pdata->netdev);
+			*an_restart = 1;
+		}
+	}
+
 	/* No link, attempt a receiver reset cycle */
 	if (phy_data->rrc_count++ > XGBE_RRC_FREQUENCY) {
 		phy_data->rrc_count = 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/amd/xgbe/xgbe.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/amd/xgbe/xgbe.h
@@ -181,9 +181,9 @@
 #define XGBE_DMA_SYS_AWCR	0x30303030
 
 /* DMA cache settings - PCI device */
-#define XGBE_DMA_PCI_ARCR	0x00000003
-#define XGBE_DMA_PCI_AWCR	0x13131313
-#define XGBE_DMA_PCI_AWARCR	0x00000313
+#define XGBE_DMA_PCI_ARCR	0x000f0f0f
+#define XGBE_DMA_PCI_AWCR	0x0f0f0f0f
+#define XGBE_DMA_PCI_AWARCR	0x00000f0f
 
 /* DMA channel interrupt modes */
 #define XGBE_IRQ_MODE_EDGE	0
@@ -290,6 +290,7 @@
 /* Auto-negotiation */
 #define XGBE_AN_MS_TIMEOUT		500
 #define XGBE_LINK_TIMEOUT		5
+#define XGBE_KR_TRAINING_WAIT_ITER	50
 
 #define XGBE_SGMII_AN_LINK_STATUS	BIT(1)
 #define XGBE_SGMII_AN_LINK_SPEED	(BIT(2) | BIT(3))
@@ -1266,6 +1267,7 @@
 	unsigned int parallel_detect;
 	unsigned int fec_ability;
 	unsigned long an_start;
+	unsigned long kr_start_time;
 	enum xgbe_an_mode an_mode;
 
 	/* I2C support */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/apm/xgene-v2/main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/apm/xgene-v2/main.c
@@ -677,11 +677,13 @@
 	ret = register_netdev(ndev);
 	if (ret) {
 		netdev_err(ndev, "Failed to register netdev\n");
-		goto err;
+		goto err_mdio_remove;
 	}
 
 	return 0;
 
+err_mdio_remove:
+	xge_mdio_remove(ndev);
 err:
 	free_netdev(ndev);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -696,6 +696,12 @@
 	buf_pool->rx_skb[skb_index] = NULL;
 
 	datalen = xgene_enet_get_data_len(le64_to_cpu(raw_desc->m1));
+
+	/* strip off CRC as HW isn't doing this */
+	nv = GET_VAL(NV, le64_to_cpu(raw_desc->m0));
+	if (!nv)
+		datalen -= 4;
+
 	skb_put(skb, datalen);
 	prefetch(skb->data - NET_IP_ALIGN);
 	skb->protocol = eth_type_trans(skb, ndev);
@@ -717,12 +723,8 @@
 		}
 	}
 
-	nv = GET_VAL(NV, le64_to_cpu(raw_desc->m0));
-	if (!nv) {
-		/* strip off CRC as HW isn't doing this */
-		datalen -= 4;
+	if (!nv)
 		goto skip_jumbo;
-	}
 
 	slots = page_pool->slots - 1;
 	head = page_pool->head;
@@ -1002,8 +1004,10 @@
 
 	xgene_enet_napi_enable(pdata);
 	ret = xgene_enet_register_irq(ndev);
-	if (ret)
+	if (ret) {
+		xgene_enet_napi_disable(pdata);
 		return ret;
+	}
 
 	if (ndev->phydev) {
 		phy_start(ndev->phydev);
@@ -2020,7 +2024,7 @@
 	int ret;
 
 	ndev = alloc_etherdev_mqs(sizeof(struct xgene_enet_pdata),
-				  XGENE_NUM_RX_RING, XGENE_NUM_TX_RING);
+				  XGENE_NUM_TX_RING, XGENE_NUM_RX_RING);
 	if (!ndev)
 		return -ENOMEM;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
@@ -18,6 +18,7 @@
 #include <linux/of_platform.h>
 #include <linux/of_net.h>
 #include <linux/of_mdio.h>
+#include <linux/mdio/mdio-xgene.h>
 #include <linux/module.h>
 #include <net/ip.h>
 #include <linux/prefetch.h>
@@ -26,7 +27,6 @@
 #include "xgene_enet_hw.h"
 #include "xgene_enet_cle.h"
 #include "xgene_enet_ring2.h"
-#include "../../../phy/mdio-xgene.h"
 
 #define XGENE_DRV_VERSION	"v1.0"
 #define ETHER_MIN_PACKET	64
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/apple/bmac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/apple/bmac.c
@@ -1182,7 +1182,7 @@
 	int i;
 	unsigned short data;
 
-	for (i = 0; i < 6; i++)
+	for (i = 0; i < 3; i++)
 		{
 			reset_and_select_srom(dev);
 			data = read_srom(dev, i + EnetAddressOffset/2, SROMAddressBits);
@@ -1511,7 +1511,7 @@
 	i = bp->tx_empty;
 	++dev->stats.tx_errors;
 	if (i != bp->tx_fill) {
-		dev_kfree_skb(bp->tx_bufs[i]);
+		dev_kfree_skb_irq(bp->tx_bufs[i]);
 		bp->tx_bufs[i] = NULL;
 		if (++i >= N_TX_RING) i = 0;
 		bp->tx_empty = i;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/apple/mace.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/apple/mace.c
@@ -841,7 +841,7 @@
     if (mp->tx_bad_runt) {
 	mp->tx_bad_runt = 0;
     } else if (i != mp->tx_fill) {
-	dev_kfree_skb(mp->tx_bufs[i]);
+	dev_kfree_skb_irq(mp->tx_bufs[i]);
 	if (++i >= N_TX_RING)
 	    i = 0;
 	mp->tx_empty = i;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/aquantia/atlantic/aq_filters.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/aquantia/atlantic/aq_filters.c
@@ -158,7 +158,7 @@
 	}
 
 	if ((aq_nic->ndev->features & NETIF_F_HW_VLAN_CTAG_FILTER) &&
-	    (!test_bit(be16_to_cpu(fsp->h_ext.vlan_tci),
+	    (!test_bit(be16_to_cpu(fsp->h_ext.vlan_tci) & VLAN_VID_MASK,
 		       aq_nic->active_vlans))) {
 		netdev_err(aq_nic->ndev,
 			   "ethtool: unknown vlan-id specified");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
@@ -230,7 +230,7 @@
 
 	struct aq_stats_s *(*hw_get_hw_stats)(struct aq_hw_s *self);
 
-	int (*hw_get_fw_version)(struct aq_hw_s *self, u32 *fw_version);
+	u32 (*hw_get_fw_version)(struct aq_hw_s *self);
 
 	int (*hw_set_offload)(struct aq_hw_s *self,
 			      struct aq_nic_cfg_s *aq_nic_cfg);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/aquantia/atlantic/aq_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/aquantia/atlantic/aq_main.c
@@ -66,8 +66,10 @@
 		goto err_exit;
 
 	err = aq_nic_start(aq_nic);
-	if (err < 0)
+	if (err < 0) {
+		aq_nic_stop(aq_nic);
 		goto err_exit;
+	}
 
 err_exit:
 	if (err < 0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
@@ -467,8 +467,10 @@
 				     dx_buff->len,
 				     DMA_TO_DEVICE);
 
-	if (unlikely(dma_mapping_error(aq_nic_get_dev(self), dx_buff->pa)))
+	if (unlikely(dma_mapping_error(aq_nic_get_dev(self), dx_buff->pa))) {
+		ret = 0;
 		goto exit;
+	}
 
 	first = dx_buff;
 	dx_buff->len_pkt = skb->len;
@@ -598,10 +600,6 @@
 	if (likely(frags)) {
 		err = self->aq_hw_ops->hw_ring_tx_xmit(self->aq_hw,
 						       ring, frags);
-		if (err >= 0) {
-			++ring->stats.tx.packets;
-			ring->stats.tx.bytes += skb->len;
-		}
 	} else {
 		err = NETDEV_TX_BUSY;
 	}
@@ -692,6 +690,9 @@
 	u32 *regs_buff = p;
 	int err = 0;
 
+	if (unlikely(!self->aq_hw_ops->hw_get_regs))
+		return -EOPNOTSUPP;
+
 	regs->version = 1;
 
 	err = self->aq_hw_ops->hw_get_regs(self->aq_hw,
@@ -706,6 +707,9 @@
 
 int aq_nic_get_regs_count(struct aq_nic_s *self)
 {
+	if (unlikely(!self->aq_hw_ops->hw_get_regs))
+		return 0;
+
 	return self->aq_nic_cfg.aq_hw_caps->mac_regs_count;
 }
 
@@ -899,7 +903,6 @@
 		default:
 			err = -1;
 			goto err_exit;
-		break;
 		}
 		if (!(self->aq_nic_cfg.aq_hw_caps->link_speed_msk & rate)) {
 			err = -1;
@@ -928,11 +931,7 @@
 
 u32 aq_nic_get_fw_version(struct aq_nic_s *self)
 {
-	u32 fw_version = 0U;
-
-	self->aq_hw_ops->hw_get_fw_version(self->aq_hw, &fw_version);
-
-	return fw_version;
+	return self->aq_hw_ops->hw_get_fw_version(self->aq_hw);
 }
 
 int aq_nic_stop(struct aq_nic_s *self)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
@@ -56,7 +56,7 @@
 	{ AQ_DEVICE_ID_D108,	AQ_HWREV_2,	&hw_atl_ops_b0, &hw_atl_b0_caps_aqc108, },
 	{ AQ_DEVICE_ID_D109,	AQ_HWREV_2,	&hw_atl_ops_b0, &hw_atl_b0_caps_aqc109, },
 
-	{ AQ_DEVICE_ID_AQC100,	AQ_HWREV_ANY,	&hw_atl_ops_b1, &hw_atl_b0_caps_aqc107, },
+	{ AQ_DEVICE_ID_AQC100,	AQ_HWREV_ANY,	&hw_atl_ops_b1, &hw_atl_b0_caps_aqc100, },
 	{ AQ_DEVICE_ID_AQC107,	AQ_HWREV_ANY,	&hw_atl_ops_b1, &hw_atl_b0_caps_aqc107, },
 	{ AQ_DEVICE_ID_AQC108,	AQ_HWREV_ANY,	&hw_atl_ops_b1, &hw_atl_b0_caps_aqc108, },
 	{ AQ_DEVICE_ID_AQC109,	AQ_HWREV_ANY,	&hw_atl_ops_b1, &hw_atl_b0_caps_aqc109, },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
@@ -92,8 +92,8 @@
 	return 0;
 }
 
-static struct aq_ring_s *aq_ring_alloc(struct aq_ring_s *self,
-				       struct aq_nic_s *aq_nic)
+static int aq_ring_alloc(struct aq_ring_s *self,
+			 struct aq_nic_s *aq_nic)
 {
 	int err = 0;
 
@@ -115,44 +115,29 @@
 err_exit:
 	if (err < 0) {
 		aq_ring_free(self);
-		self = NULL;
 	}
-	return self;
+
+	return err;
 }
 
-struct aq_ring_s *aq_ring_tx_alloc(struct aq_ring_s *self,
-				   struct aq_nic_s *aq_nic,
-				   unsigned int idx,
-				   struct aq_nic_cfg_s *aq_nic_cfg)
+int aq_ring_tx_alloc(struct aq_ring_s *self,
+		     struct aq_nic_s *aq_nic,
+		     unsigned int idx,
+		     struct aq_nic_cfg_s *aq_nic_cfg)
 {
-	int err = 0;
-
 	self->aq_nic = aq_nic;
 	self->idx = idx;
 	self->size = aq_nic_cfg->txds;
 	self->dx_size = aq_nic_cfg->aq_hw_caps->txd_size;
 
-	self = aq_ring_alloc(self, aq_nic);
-	if (!self) {
-		err = -ENOMEM;
-		goto err_exit;
-	}
-
-err_exit:
-	if (err < 0) {
-		aq_ring_free(self);
-		self = NULL;
-	}
-	return self;
+	return aq_ring_alloc(self, aq_nic);
 }
 
-struct aq_ring_s *aq_ring_rx_alloc(struct aq_ring_s *self,
-				   struct aq_nic_s *aq_nic,
-				   unsigned int idx,
-				   struct aq_nic_cfg_s *aq_nic_cfg)
+int aq_ring_rx_alloc(struct aq_ring_s *self,
+		     struct aq_nic_s *aq_nic,
+		     unsigned int idx,
+		     struct aq_nic_cfg_s *aq_nic_cfg)
 {
-	int err = 0;
-
 	self->aq_nic = aq_nic;
 	self->idx = idx;
 	self->size = aq_nic_cfg->rxds;
@@ -163,18 +148,7 @@
 	if (aq_nic_cfg->rxpageorder > self->page_order)
 		self->page_order = aq_nic_cfg->rxpageorder;
 
-	self = aq_ring_alloc(self, aq_nic);
-	if (!self) {
-		err = -ENOMEM;
-		goto err_exit;
-	}
-
-err_exit:
-	if (err < 0) {
-		aq_ring_free(self);
-		self = NULL;
-	}
-	return self;
+	return aq_ring_alloc(self, aq_nic);
 }
 
 int aq_ring_init(struct aq_ring_s *self)
@@ -243,9 +217,12 @@
 			}
 		}
 
-		if (unlikely(buff->is_eop))
-			dev_kfree_skb_any(buff->skb);
+		if (unlikely(buff->is_eop)) {
+			++self->stats.rx.packets;
+			self->stats.tx.bytes += buff->skb->len;
 
+			dev_kfree_skb_any(buff->skb);
+		}
 		buff->pa = 0U;
 		buff->eop_index = 0xffffU;
 		self->sw_head = aq_ring_next_dx(self, self->sw_head);
@@ -302,6 +279,10 @@
 		if (!buff->is_eop) {
 			buff_ = buff;
 			do {
+				if (buff_->next >= self->size) {
+					err = -EIO;
+					goto err_exit;
+				}
 				next_ = buff_->next,
 				buff_ = &self->buff_ring[next_];
 				is_rsc_completed =
@@ -324,6 +305,10 @@
 			if (buff->is_error || buff->is_cso_err) {
 				buff_ = buff;
 				do {
+					if (buff_->next >= self->size) {
+						err = -EIO;
+						goto err_exit;
+					}
 					next_ = buff_->next,
 					buff_ = &self->buff_ring[next_];
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/aquantia/atlantic/aq_ring.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/aquantia/atlantic/aq_ring.h
@@ -153,14 +153,14 @@
 		self->sw_head - self->sw_tail - 1);
 }
 
-struct aq_ring_s *aq_ring_tx_alloc(struct aq_ring_s *self,
-				   struct aq_nic_s *aq_nic,
-				   unsigned int idx,
-				   struct aq_nic_cfg_s *aq_nic_cfg);
-struct aq_ring_s *aq_ring_rx_alloc(struct aq_ring_s *self,
-				   struct aq_nic_s *aq_nic,
-				   unsigned int idx,
-				   struct aq_nic_cfg_s *aq_nic_cfg);
+int aq_ring_tx_alloc(struct aq_ring_s *self,
+		     struct aq_nic_s *aq_nic,
+		     unsigned int idx,
+		     struct aq_nic_cfg_s *aq_nic_cfg);
+int aq_ring_rx_alloc(struct aq_ring_s *self,
+		     struct aq_nic_s *aq_nic,
+		     unsigned int idx,
+		     struct aq_nic_cfg_s *aq_nic_cfg);
 int aq_ring_init(struct aq_ring_s *self);
 void aq_ring_rx_deinit(struct aq_ring_s *self);
 void aq_ring_free(struct aq_ring_s *self);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/aquantia/atlantic/aq_vec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/aquantia/atlantic/aq_vec.c
@@ -133,21 +133,18 @@
 						self->tx_rings,
 						self->aq_ring_param.vec_idx);
 
-		ring = aq_ring_tx_alloc(&self->ring[i][AQ_VEC_TX_ID], aq_nic,
-					idx_ring, aq_nic_cfg);
-		if (!ring) {
-			err = -ENOMEM;
+		ring = &self->ring[i][AQ_VEC_TX_ID];
+		err = aq_ring_tx_alloc(ring, aq_nic, idx_ring, aq_nic_cfg);
+		if (err)
 			goto err_exit;
-		}
 
 		++self->tx_rings;
 
 		aq_nic_set_tx_ring(aq_nic, idx_ring, ring);
 
-		ring = aq_ring_rx_alloc(&self->ring[i][AQ_VEC_RX_ID], aq_nic,
-					idx_ring, aq_nic_cfg);
-		if (!ring) {
-			err = -ENOMEM;
+		ring = &self->ring[i][AQ_VEC_RX_ID];
+		err = aq_ring_rx_alloc(ring, aq_nic, idx_ring, aq_nic_cfg);
+		if (err) {
 			goto err_exit;
 		}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c
@@ -776,7 +776,7 @@
 	int err = 0;
 
 	if (count > (HW_ATL_A0_MAC_MAX - HW_ATL_A0_MAC_MIN)) {
-		err = EBADRQC;
+		err = -EBADRQC;
 		goto err_exit;
 	}
 	for (self->aq_nic_cfg->mc_list_count = 0U;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
@@ -674,6 +674,13 @@
 		err = -ENXIO;
 		goto err_exit;
 	}
+
+	/* Validate that the new hw_head_ is reasonable. */
+	if (hw_head_ >= ring->size) {
+		err = -ENXIO;
+		goto err_exit;
+	}
+
 	ring->hw_head = hw_head_;
 	err = aq_hw_err_from_flags(self);
 
@@ -1097,7 +1104,7 @@
 	return aq_hw_err_from_flags(self);
 }
 
-/**
+/*
  * @brief Set VLAN filter table
  * @details Configure VLAN filter table to accept (and assign the queue) traffic
  *  for the particular vlan ids.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c
@@ -1597,7 +1597,7 @@
 	for (i = 0; i < 4; ++i)
 		aq_hw_write_reg(aq_hw,
 				HW_ATL_RPF_L3_SRCA_ADR(location + i),
-				ipv6_src[i]);
+				ipv6_src[3 - i]);
 }
 
 void hw_atl_rpfl3l4_ipv6_dest_addr_set(struct aq_hw_s *aq_hw, u8 location,
@@ -1608,7 +1608,7 @@
 	for (i = 0; i < 4; ++i)
 		aq_hw_write_reg(aq_hw,
 				HW_ATL_RPF_L3_DSTA_ADR(location + i),
-				ipv6_dest[i]);
+				ipv6_dest[3 - i]);
 }
 
 u32 hw_atl_sem_ram_get(struct aq_hw_s *self)
@@ -1616,6 +1616,16 @@
 	return hw_atl_reg_glb_cpu_sem_get(self, HW_ATL_FW_SM_RAM);
 }
 
+u32 hw_atl_sem_reset1_get(struct aq_hw_s *self)
+{
+	return hw_atl_reg_glb_cpu_sem_get(self, HW_ATL_FW_SM_RESET1);
+}
+
+u32 hw_atl_sem_reset2_get(struct aq_hw_s *self)
+{
+	return hw_atl_reg_glb_cpu_sem_get(self, HW_ATL_FW_SM_RESET2);
+}
+
 u32 hw_atl_scrpad_get(struct aq_hw_s *aq_hw, u32 scratch_scp)
 {
 	return aq_hw_read_reg(aq_hw,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h
@@ -755,6 +755,9 @@
 /* get global microprocessor ram semaphore */
 u32 hw_atl_sem_ram_get(struct aq_hw_s *self);
 
+u32 hw_atl_sem_reset1_get(struct aq_hw_s *self);
+u32 hw_atl_sem_reset2_get(struct aq_hw_s *self);
+
 /* get global microprocessor scratch pad register */
 u32 hw_atl_scrpad_get(struct aq_hw_s *aq_hw, u32 scratch_scp);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h
@@ -2564,7 +2564,7 @@
  */
 
  /* Register address for bitfield pif_rpf_l3_da0_i[31:0] */
-#define HW_ATL_RPF_L3_DSTA_ADR(location) (0x000053B0 + (location) * 0x4)
+#define HW_ATL_RPF_L3_DSTA_ADR(filter) (0x000053D0 + (filter) * 0x4)
 /* Bitmask for bitfield l3_da0[1F:0] */
 #define HW_ATL_RPF_L3_DSTA_MSK 0xFFFFFFFFu
 /* Inverted bitmask for bitfield l3_da0[1F:0] */
@@ -2576,6 +2576,10 @@
 /* Default value of bitfield l3_da0[1F:0] */
 #define HW_ATL_RPF_L3_DSTA_DEFAULT 0x0
 
+#define HW_ATL_MIF_RESET_TIMEOUT_ADR 0x00000348
+
 #define HW_ATL_FW_SM_RAM        0x2U
+#define HW_ATL_FW_SM_RESET1     0x3U
+#define HW_ATL_FW_SM_RESET2     0x4U
 
 #endif /* HW_ATL_LLH_INTERNAL_H */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
@@ -22,6 +22,7 @@
 #define HW_ATL_MIF_ADDR         0x0208U
 #define HW_ATL_MIF_VAL          0x020CU
 
+#define HW_ATL_MPI_RPC_ADDR     0x0334U
 #define HW_ATL_RPC_CONTROL_ADR  0x0338U
 #define HW_ATL_RPC_STATE_ADR    0x033CU
 
@@ -44,19 +45,18 @@
 #define HW_ATL_FW_VER_1X 0x01050006U
 #define HW_ATL_FW_VER_2X 0x02000000U
 #define HW_ATL_FW_VER_3X 0x03000000U
+#define HW_ATL_FW_VER_4X 0x04000000U
 
 #define FORCE_FLASHLESS 0
 
-static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual);
-
 static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self,
-				      enum hal_atl_utils_fw_state_e state);
-
+		enum hal_atl_utils_fw_state_e state);
 static u32 hw_atl_utils_get_mpi_mbox_tid(struct aq_hw_s *self);
 static u32 hw_atl_utils_mpi_get_state(struct aq_hw_s *self);
 static u32 hw_atl_utils_mif_cmd_get(struct aq_hw_s *self);
 static u32 hw_atl_utils_mif_addr_get(struct aq_hw_s *self);
 static u32 hw_atl_utils_rpc_state_get(struct aq_hw_s *self);
+static u32 aq_fw1x_rpc_get(struct aq_hw_s *self);
 
 int hw_atl_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops)
 {
@@ -67,22 +67,21 @@
 		return err;
 
 	hw_atl_utils_hw_chip_features_init(self,
-					   &self->chip_features);
+			&self->chip_features);
 
-	hw_atl_utils_get_fw_version(self, &self->fw_ver_actual);
+	self->fw_ver_actual = hw_atl_utils_get_fw_version(self);
 
-	if (hw_atl_utils_ver_match(HW_ATL_FW_VER_1X,
-				   self->fw_ver_actual) == 0) {
+	if (hw_atl_utils_ver_match(HW_ATL_FW_VER_1X, self->fw_ver_actual)) {
 		*fw_ops = &aq_fw_1x_ops;
-	} else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_2X,
-					  self->fw_ver_actual) == 0) {
+	} else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_2X, self->fw_ver_actual)) {
+		*fw_ops = &aq_fw_2x_ops;
+	} else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_3X, self->fw_ver_actual)) {
 		*fw_ops = &aq_fw_2x_ops;
-	} else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_3X,
-					  self->fw_ver_actual) == 0) {
+	} else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_4X, self->fw_ver_actual)) {
 		*fw_ops = &aq_fw_2x_ops;
 	} else {
 		aq_pr_err("Bad FW version detected: %x\n",
-			  self->fw_ver_actual);
+				self->fw_ver_actual);
 		return -EOPNOTSUPP;
 	}
 	self->aq_fw_ops = *fw_ops;
@@ -121,7 +120,7 @@
 
 	for (k = 0; k < 1000; k++) {
 		u32 flb_status = aq_hw_read_reg(self,
-						HW_ATL_MPI_DAISY_CHAIN_STATUS);
+				HW_ATL_MPI_DAISY_CHAIN_STATUS);
 
 		flb_status = flb_status & 0x10;
 		if (flb_status)
@@ -144,8 +143,8 @@
 	hw_atl_rx_rx_reg_res_dis_set(self, 0U);
 	hw_atl_tx_tx_reg_res_dis_set(self, 0U);
 	aq_hw_write_reg_bit(self, HW_ATL_MAC_PHY_CONTROL,
-			    BIT(HW_ATL_MAC_PHY_MPI_RESET_BIT),
-			    HW_ATL_MAC_PHY_MPI_RESET_BIT, 0x0);
+			BIT(HW_ATL_MAC_PHY_MPI_RESET_BIT),
+			HW_ATL_MAC_PHY_MPI_RESET_BIT, 0x0);
 	gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR);
 	aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR, (gsr & 0xBFFF) | 0x8000);
 
@@ -186,8 +185,8 @@
 	hw_atl_rx_rx_reg_res_dis_set(self, 0U);
 	hw_atl_tx_tx_reg_res_dis_set(self, 0U);
 	aq_hw_write_reg_bit(self, HW_ATL_MAC_PHY_CONTROL,
-			    BIT(HW_ATL_MAC_PHY_MPI_RESET_BIT),
-			    HW_ATL_MAC_PHY_MPI_RESET_BIT, 0x0);
+			BIT(HW_ATL_MAC_PHY_MPI_RESET_BIT),
+			HW_ATL_MAC_PHY_MPI_RESET_BIT, 0x0);
 	gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR);
 	aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR,
 			(gsr & 0xFFFFBFFF) | 0x8000);
@@ -238,14 +237,15 @@
 int hw_atl_utils_soft_reset(struct aq_hw_s *self)
 {
 	int k;
+	int ver = hw_atl_utils_get_fw_version(self);
 	u32 boot_exit_code = 0;
 	u32 val;
 
 	for (k = 0; k < 1000; ++k) {
 		u32 flb_status = aq_hw_read_reg(self,
-						HW_ATL_MPI_DAISY_CHAIN_STATUS);
+				HW_ATL_MPI_DAISY_CHAIN_STATUS);
 		boot_exit_code = aq_hw_read_reg(self,
-						HW_ATL_MPI_BOOT_EXIT_CODE);
+				HW_ATL_MPI_BOOT_EXIT_CODE);
 		if (flb_status != 0x06000000 || boot_exit_code != 0)
 			break;
 	}
@@ -257,22 +257,41 @@
 
 	self->rbl_enabled = (boot_exit_code != 0);
 
-	/* FW 1.x may bootup in an invalid POWER state (WOL feature).
-	 * We should work around this by forcing its state back to DEINIT
-	 */
-	if (!hw_atl_utils_ver_match(HW_ATL_FW_VER_1X,
-				    aq_hw_read_reg(self,
-						   HW_ATL_MPI_FW_VERSION))) {
+	if (hw_atl_utils_ver_match(HW_ATL_FW_VER_1X, ver)) {
 		int err = 0;
 
+		/* FW 1.x may bootup in an invalid POWER state (WOL feature).
+		 * We should work around this by forcing its state back to DEINIT
+		 */
 		hw_atl_utils_mpi_set_state(self, MPI_DEINIT);
 		err = readx_poll_timeout_atomic(hw_atl_utils_mpi_get_state,
-						self, val,
-						(val & HW_ATL_MPI_STATE_MSK) ==
-						 MPI_DEINIT,
-						10, 10000U);
+				self, val,
+				(val & HW_ATL_MPI_STATE_MSK) ==
+				MPI_DEINIT,
+				10, 10000U);
 		if (err)
 			return err;
+	} else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_4X, ver)) {
+		u64 sem_timeout = aq_hw_read_reg(self, HW_ATL_MIF_RESET_TIMEOUT_ADR);
+
+		/* Acquire 2 semaphores before issuing reset for FW 4.x */
+		if (sem_timeout > 3000)
+			sem_timeout = 3000;
+		sem_timeout = sem_timeout * 1000;
+
+		if (sem_timeout != 0) {
+			int err;
+
+			err = readx_poll_timeout_atomic(hw_atl_sem_reset1_get, self, val,
+							val == 1U, 1U, sem_timeout);
+			if (err)
+				aq_pr_err("reset sema1 timeout");
+
+			err = readx_poll_timeout_atomic(hw_atl_sem_reset2_get, self, val,
+							val == 1U, 1U, sem_timeout);
+			if (err)
+				aq_pr_err("reset sema2 timeout");
+		}
 	}
 
 	if (self->rbl_enabled)
@@ -282,14 +301,14 @@
 }
 
 int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a,
-				  u32 *p, u32 cnt)
+		u32 *p, u32 cnt)
 {
 	int err = 0;
 	u32 val;
 
 	err = readx_poll_timeout_atomic(hw_atl_sem_ram_get,
-					self, val, val == 1U,
-					1U, 10000U);
+			self, val, val == 1U,
+			1U, 10000U);
 
 	if (err < 0) {
 		bool is_locked;
@@ -309,13 +328,13 @@
 
 		if (IS_CHIP_FEATURE(REVISION_B1))
 			err = readx_poll_timeout_atomic(hw_atl_utils_mif_addr_get,
-							self, val, val != a,
-							1U, 1000U);
+					self, val, val != a,
+					1U, 1000U);
 		else
 			err = readx_poll_timeout_atomic(hw_atl_utils_mif_cmd_get,
-							self, val,
-							!(val & 0x100),
-							1U, 1000U);
+					self, val,
+					!(val & 0x100),
+					1U, 1000U);
 
 		*(p++) = aq_hw_read_reg(self, HW_ATL_MIF_VAL);
 		a += 4;
@@ -328,14 +347,14 @@
 }
 
 static int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p,
-					 u32 cnt)
+		u32 cnt)
 {
 	u32 val;
 	int err = 0;
 
 	err = readx_poll_timeout_atomic(hw_atl_sem_ram_get, self,
-					val, val == 1U,
-					10U, 100000U);
+			val, val == 1U,
+			10U, 100000U);
 	if (err < 0)
 		goto err_exit;
 
@@ -349,10 +368,10 @@
 			hw_atl_mcp_up_force_intr_set(self, 1);
 			/* 1000 times by 10us = 10ms */
 			err = readx_poll_timeout_atomic(hw_atl_scrpad12_get,
-							self, val,
-							(val & 0xF0000000) !=
-							0x80000000,
-							10U, 10000U);
+					self, val,
+					(val & 0xF0000000) !=
+					0x80000000,
+					10U, 10000U);
 		}
 	} else {
 		u32 offset = 0;
@@ -364,9 +383,9 @@
 			aq_hw_write_reg(self, 0x200, 0xC000);
 
 			err = readx_poll_timeout_atomic(hw_atl_utils_mif_cmd_get,
-							self, val,
-							(val & 0x100) == 0,
-							1000U, 10000U);
+					self, val,
+					(val & 0x100) == 0,
+					1000U, 10000U);
 		}
 	}
 
@@ -376,19 +395,21 @@
 	return err;
 }
 
-static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual)
+bool hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual)
 {
-	int err = 0;
 	const u32 dw_major_mask = 0xff000000U;
 	const u32 dw_minor_mask = 0x00ffffffU;
+	bool ver_match;
 
-	err = (dw_major_mask & (ver_expected ^ ver_actual)) ? -EOPNOTSUPP : 0;
-	if (err < 0)
+	ver_match = (dw_major_mask & (ver_expected ^ ver_actual)) ? false : true;
+	if (!ver_match)
 		goto err_exit;
-	err = ((dw_minor_mask & ver_expected) > (dw_minor_mask & ver_actual)) ?
-		-EOPNOTSUPP : 0;
+
+	ver_match = ((dw_minor_mask & ver_expected) > (dw_minor_mask & ver_actual)) ?
+		false : true;
+
 err_exit:
-	return err;
+	return ver_match;
 }
 
 static int hw_atl_utils_init_ucp(struct aq_hw_s *self,
@@ -413,6 +434,10 @@
 					self, self->mbox_addr,
 					self->mbox_addr != 0U,
 					1000U, 10000U);
+	err = readx_poll_timeout_atomic(aq_fw1x_rpc_get, self,
+					self->rpc_addr,
+					self->rpc_addr != 0U,
+					1000U, 100000U);
 
 	return err;
 }
@@ -469,8 +494,19 @@
 						self, fw.val,
 						sw.tid == fw.tid,
 						1000U, 100000U);
+		if (err < 0)
+			goto err_exit;
+
+		err = aq_hw_err_from_flags(self);
+		if (err < 0)
+			goto err_exit;
 
 		if (fw.len == 0xFFFFU) {
+			if (sw.len > sizeof(self->rpc)) {
+				printk(KERN_INFO "Invalid sw len: %x\n", sw.len);
+				err = -EINVAL;
+				goto err_exit;
+			}
 			err = hw_atl_utils_fw_rpc_call(self, sw.len);
 			if (err < 0)
 				goto err_exit;
@@ -479,6 +515,11 @@
 
 	if (rpc) {
 		if (fw.len) {
+			if (fw.len > sizeof(self->rpc)) {
+				printk(KERN_INFO "Invalid fw len: %x\n", fw.len);
+				err = -EINVAL;
+				goto err_exit;
+			}
 			err =
 			hw_atl_utils_fw_downld_dwords(self,
 						      self->rpc_addr,
@@ -840,10 +881,9 @@
 	return 0;
 }
 
-int hw_atl_utils_get_fw_version(struct aq_hw_s *self, u32 *fw_version)
+u32 hw_atl_utils_get_fw_version(struct aq_hw_s *self)
 {
-	*fw_version = aq_hw_read_reg(self, 0x18U);
-	return 0;
+	return aq_hw_read_reg(self, HW_ATL_MPI_FW_VERSION);
 }
 
 static int aq_fw1x_set_wol(struct aq_hw_s *self, bool wol_enabled, u8 *mac)
@@ -950,6 +990,11 @@
 	return aq_hw_read_reg(self, HW_ATL_RPC_STATE_ADR);
 }
 
+static u32 aq_fw1x_rpc_get(struct aq_hw_s *self)
+{
+	return aq_hw_read_reg(self, HW_ATL_MPI_RPC_ADDR);
+}
+
 const struct aq_fw_ops aq_fw_1x_ops = {
 	.init = hw_atl_utils_mpi_create,
 	.deinit = hw_atl_fw1x_deinit,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h
@@ -466,7 +466,7 @@
 
 int hw_atl_utils_hw_deinit(struct aq_hw_s *self);
 
-int hw_atl_utils_get_fw_version(struct aq_hw_s *self, u32 *fw_version);
+u32 hw_atl_utils_get_fw_version(struct aq_hw_s *self);
 
 int hw_atl_utils_update_stats(struct aq_hw_s *self);
 
@@ -482,6 +482,8 @@
 int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self,
 			     struct hw_atl_utils_fw_rpc **rpc);
 
+bool hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual);
+
 extern const struct aq_fw_ops aq_fw_1x_ops;
 extern const struct aq_fw_ops aq_fw_2x_ops;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/arc/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/arc/Kconfig
@@ -21,6 +21,7 @@
 	depends on ARC || ARCH_ROCKCHIP || COMPILE_TEST
 	select MII
 	select PHYLIB
+	select CRC32
 
 config ARC_EMAC
 	tristate "ARC EMAC support"
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/arc/emac_mdio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/arc/emac_mdio.c
@@ -153,6 +153,7 @@
 	if (IS_ERR(data->reset_gpio)) {
 		error = PTR_ERR(data->reset_gpio);
 		dev_err(priv->dev, "Failed to request gpio: %d\n", error);
+		mdiobus_free(bus);
 		return error;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/atheros/ag71xx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/atheros/ag71xx.c
@@ -222,8 +222,6 @@
 #define AG71XX_REG_RX_SM	0x01b0
 #define AG71XX_REG_TX_SM	0x01b4
 
-#define ETH_SWITCH_HEADER_LEN	2
-
 #define AG71XX_DEFAULT_MSG_ENABLE	\
 	(NETIF_MSG_DRV			\
 	| NETIF_MSG_PROBE		\
@@ -553,7 +551,8 @@
 	ag->mdio_reset = of_reset_control_get_exclusive(np, "mdio");
 	if (IS_ERR(ag->mdio_reset)) {
 		netif_err(ag, probe, ndev, "Failed to get reset mdio.\n");
-		return PTR_ERR(ag->mdio_reset);
+		err = PTR_ERR(ag->mdio_reset);
+		goto mdio_err_put_clk;
 	}
 
 	mii_bus->name = "ag71xx_mdio";
@@ -783,7 +782,7 @@
 
 static unsigned int ag71xx_max_frame_len(unsigned int mtu)
 {
-	return ETH_SWITCH_HEADER_LEN + ETH_HLEN + VLAN_HLEN + mtu + ETH_FCS_LEN;
+	return ETH_HLEN + VLAN_HLEN + mtu + ETH_FCS_LEN;
 }
 
 static void ag71xx_hw_set_macaddr(struct ag71xx *ag, unsigned char *mac)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/atheros/alx/ethtool.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/atheros/alx/ethtool.c
@@ -46,6 +46,8 @@
 #include "reg.h"
 #include "hw.h"
 
+extern const bool enable_wol;
+
 /* The order of these strings must match the order of the fields in
  * struct alx_hw_stats
  * See hw.h
@@ -281,9 +283,8 @@
 	spin_lock(&alx->stats_lock);
 
 	alx_update_hw_stats(hw);
-	BUILD_BUG_ON(sizeof(hw->stats) - offsetof(struct alx_hw_stats, rx_ok) <
-		     ALX_NUM_STATS * sizeof(u64));
-	memcpy(data, &hw->stats.rx_ok, ALX_NUM_STATS * sizeof(u64));
+	BUILD_BUG_ON(sizeof(hw->stats) != ALX_NUM_STATS * sizeof(u64));
+	memcpy(data, &hw->stats, sizeof(hw->stats));
 
 	spin_unlock(&alx->stats_lock);
 }
@@ -310,11 +311,50 @@
 	}
 }
 
+static void alx_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
+{
+	struct alx_priv *alx = netdev_priv(netdev);
+	struct alx_hw *hw = &alx->hw;
+
+	if (!enable_wol)
+		return;
+
+	wol->supported = WAKE_MAGIC | WAKE_PHY;
+	wol->wolopts = 0;
+
+	if (hw->sleep_ctrl & ALX_SLEEP_WOL_MAGIC)
+		wol->wolopts |= WAKE_MAGIC;
+	if (hw->sleep_ctrl & ALX_SLEEP_WOL_PHY)
+		wol->wolopts |= WAKE_PHY;
+}
+
+static int alx_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
+{
+	struct alx_priv *alx = netdev_priv(netdev);
+	struct alx_hw *hw = &alx->hw;
+
+	if (!enable_wol || (wol->wolopts & ~(WAKE_MAGIC | WAKE_PHY)))
+		return -EOPNOTSUPP;
+
+	hw->sleep_ctrl = 0;
+
+	if (wol->wolopts & WAKE_MAGIC)
+		hw->sleep_ctrl |= ALX_SLEEP_WOL_MAGIC;
+	if (wol->wolopts & WAKE_PHY)
+		hw->sleep_ctrl |= ALX_SLEEP_WOL_PHY;
+
+	device_set_wakeup_enable(&alx->hw.pdev->dev, hw->sleep_ctrl);
+
+	return 0;
+}
+
 const struct ethtool_ops alx_ethtool_ops = {
 	.get_pauseparam	= alx_get_pauseparam,
 	.set_pauseparam	= alx_set_pauseparam,
 	.get_msglevel	= alx_get_msglevel,
 	.set_msglevel	= alx_set_msglevel,
+	.get_wol	= alx_get_wol,
+	.set_wol	= alx_set_wol,
 	.get_link	= ethtool_op_get_link,
 	.get_strings	= alx_get_strings,
 	.get_sset_count	= alx_get_sset_count,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/atheros/alx/hw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/atheros/alx/hw.c
@@ -332,6 +332,16 @@
 	alx_write_mem32(hw, ALX_STAD1, val);
 }
 
+static void alx_enable_osc(struct alx_hw *hw)
+{
+	u32 val;
+
+	/* rising edge */
+	val = alx_read_mem32(hw, ALX_MISC);
+	alx_write_mem32(hw, ALX_MISC, val & ~ALX_MISC_INTNLOSC_OPEN);
+	alx_write_mem32(hw, ALX_MISC, val | ALX_MISC_INTNLOSC_OPEN);
+}
+
 static void alx_reset_osc(struct alx_hw *hw, u8 rev)
 {
 	u32 val, val2;
@@ -774,7 +784,6 @@
 	return err;
 }
 
-
 void alx_post_phy_link(struct alx_hw *hw)
 {
 	u16 phy_val, len, agc;
@@ -848,6 +857,65 @@
 	}
 }
 
+/* NOTE:
+ *    1. phy link must be established before calling this function
+ *    2. wol option (pattern,magic,link,etc.) is configed before call it.
+ */
+int alx_pre_suspend(struct alx_hw *hw, int speed, u8 duplex)
+{
+	u32 master, mac, phy, val;
+	int err = 0;
+
+	master = alx_read_mem32(hw, ALX_MASTER);
+	master &= ~ALX_MASTER_PCLKSEL_SRDS;
+	mac = hw->rx_ctrl;
+	/* 10/100 half */
+	ALX_SET_FIELD(mac, ALX_MAC_CTRL_SPEED,  ALX_MAC_CTRL_SPEED_10_100);
+	mac &= ~(ALX_MAC_CTRL_FULLD | ALX_MAC_CTRL_RX_EN | ALX_MAC_CTRL_TX_EN);
+
+	phy = alx_read_mem32(hw, ALX_PHY_CTRL);
+	phy &= ~(ALX_PHY_CTRL_DSPRST_OUT | ALX_PHY_CTRL_CLS);
+	phy |= ALX_PHY_CTRL_RST_ANALOG | ALX_PHY_CTRL_HIB_PULSE |
+	       ALX_PHY_CTRL_HIB_EN;
+
+	/* without any activity  */
+	if (!(hw->sleep_ctrl & ALX_SLEEP_ACTIVE)) {
+		err = alx_write_phy_reg(hw, ALX_MII_IER, 0);
+		if (err)
+			return err;
+		phy |= ALX_PHY_CTRL_IDDQ | ALX_PHY_CTRL_POWER_DOWN;
+	} else {
+		if (hw->sleep_ctrl & (ALX_SLEEP_WOL_MAGIC | ALX_SLEEP_CIFS))
+			mac |= ALX_MAC_CTRL_RX_EN | ALX_MAC_CTRL_BRD_EN;
+		if (hw->sleep_ctrl & ALX_SLEEP_CIFS)
+			mac |= ALX_MAC_CTRL_TX_EN;
+		if (duplex == DUPLEX_FULL)
+			mac |= ALX_MAC_CTRL_FULLD;
+		if (speed == SPEED_1000)
+			ALX_SET_FIELD(mac, ALX_MAC_CTRL_SPEED,
+				      ALX_MAC_CTRL_SPEED_1000);
+		phy |= ALX_PHY_CTRL_DSPRST_OUT;
+		err = alx_write_phy_ext(hw, ALX_MIIEXT_ANEG,
+					ALX_MIIEXT_S3DIG10,
+					ALX_MIIEXT_S3DIG10_SL);
+		if (err)
+			return err;
+	}
+
+	alx_enable_osc(hw);
+	hw->rx_ctrl = mac;
+	alx_write_mem32(hw, ALX_MASTER, master);
+	alx_write_mem32(hw, ALX_MAC_CTRL, mac);
+	alx_write_mem32(hw, ALX_PHY_CTRL, phy);
+
+	/* set val of PDLL D3PLLOFF */
+	val = alx_read_mem32(hw, ALX_PDLL_TRNS1);
+	val |= ALX_PDLL_TRNS1_D3PLLOFF_EN;
+	alx_write_mem32(hw, ALX_PDLL_TRNS1, val);
+
+	return 0;
+}
+
 bool alx_phy_configured(struct alx_hw *hw)
 {
 	u32 cfg, hw_cfg;
@@ -920,6 +988,26 @@
 	return alx_read_phy_reg(hw, ALX_MII_ISR, &isr);
 }
 
+int alx_config_wol(struct alx_hw *hw)
+{
+	u32 wol = 0;
+	int err = 0;
+
+	/* turn on magic packet event */
+	if (hw->sleep_ctrl & ALX_SLEEP_WOL_MAGIC)
+		wol |= ALX_WOL0_MAGIC_EN | ALX_WOL0_PME_MAGIC_EN;
+
+	/* turn on link up event */
+	if (hw->sleep_ctrl & ALX_SLEEP_WOL_PHY) {
+		wol |=  ALX_WOL0_LINK_EN | ALX_WOL0_PME_LINK;
+		/* only link up can wake up */
+		err = alx_write_phy_reg(hw, ALX_MII_IER, ALX_IER_LINK_UP);
+	}
+	alx_write_mem32(hw, ALX_WOL0, wol);
+
+	return err;
+}
+
 void alx_disable_rss(struct alx_hw *hw)
 {
 	u32 ctrl = alx_read_mem32(hw, ALX_RXQ0);
@@ -1044,6 +1132,70 @@
 	alx_post_write(hw);
 }
 
+int alx_select_powersaving_speed(struct alx_hw *hw, int *speed, u8 *duplex)
+{
+	int i, err;
+	u16 lpa;
+
+	err = alx_read_phy_link(hw);
+	if (err)
+		return err;
+
+	if (hw->link_speed == SPEED_UNKNOWN) {
+		*speed = SPEED_UNKNOWN;
+		*duplex = DUPLEX_UNKNOWN;
+		return 0;
+	}
+
+	err = alx_read_phy_reg(hw, MII_LPA, &lpa);
+	if (err)
+		return err;
+
+	if (!(lpa & LPA_LPACK)) {
+		*speed = hw->link_speed;
+		return 0;
+	}
+
+	if (lpa & LPA_10FULL) {
+		*speed = SPEED_10;
+		*duplex = DUPLEX_FULL;
+	} else if (lpa & LPA_10HALF) {
+		*speed = SPEED_10;
+		*duplex = DUPLEX_HALF;
+	} else if (lpa & LPA_100FULL) {
+		*speed = SPEED_100;
+		*duplex = DUPLEX_FULL;
+	} else {
+		*speed = SPEED_100;
+		*duplex = DUPLEX_HALF;
+	}
+
+	if (*speed == hw->link_speed && *duplex == hw->duplex)
+		return 0;
+	err = alx_write_phy_reg(hw, ALX_MII_IER, 0);
+	if (err)
+		return err;
+	err = alx_setup_speed_duplex(hw, alx_speed_to_ethadv(*speed, *duplex) |
+					ADVERTISED_Autoneg, ALX_FC_ANEG |
+					ALX_FC_RX | ALX_FC_TX);
+	if (err)
+		return err;
+
+	/* wait for linkup */
+	for (i = 0; i < ALX_MAX_SETUP_LNK_CYCLE; i++) {
+		msleep(100);
+
+		err = alx_read_phy_link(hw);
+		if (err < 0)
+			return err;
+		if (hw->link_speed != SPEED_UNKNOWN)
+			break;
+	}
+	if (i == ALX_MAX_SETUP_LNK_CYCLE)
+		return -ETIMEDOUT;
+
+	return 0;
+}
 
 bool alx_get_phy_info(struct alx_hw *hw)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/atheros/alx/hw.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/atheros/alx/hw.h
@@ -487,6 +487,8 @@
 	u8 flowctrl;
 	u32 adv_cfg;
 
+	u32 sleep_ctrl;
+
 	spinlock_t mdio_lock;
 	struct mdio_if_info mdio;
 	u16 phy_id[2];
@@ -549,12 +551,14 @@
 void alx_enable_aspm(struct alx_hw *hw, bool l0s_en, bool l1_en);
 int alx_setup_speed_duplex(struct alx_hw *hw, u32 ethadv, u8 flowctrl);
 void alx_post_phy_link(struct alx_hw *hw);
+int alx_pre_suspend(struct alx_hw *hw, int speed, u8 duplex);
 int alx_read_phy_reg(struct alx_hw *hw, u16 reg, u16 *phy_data);
 int alx_write_phy_reg(struct alx_hw *hw, u16 reg, u16 phy_data);
 int alx_read_phy_ext(struct alx_hw *hw, u8 dev, u16 reg, u16 *pdata);
 int alx_write_phy_ext(struct alx_hw *hw, u8 dev, u16 reg, u16 data);
 int alx_read_phy_link(struct alx_hw *hw);
 int alx_clear_phy_intr(struct alx_hw *hw);
+int alx_config_wol(struct alx_hw *hw);
 void alx_cfg_mac_flowcontrol(struct alx_hw *hw, u8 fc);
 void alx_start_mac(struct alx_hw *hw);
 int alx_reset_mac(struct alx_hw *hw);
@@ -563,6 +567,7 @@
 void alx_configure_basic(struct alx_hw *hw);
 void alx_mask_msix(struct alx_hw *hw, int index, bool mask);
 void alx_disable_rss(struct alx_hw *hw);
+int alx_select_powersaving_speed(struct alx_hw *hw, int *speed, u8 *duplex);
 bool alx_get_phy_info(struct alx_hw *hw);
 void alx_update_hw_stats(struct alx_hw *hw);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/atheros/alx/main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/atheros/alx/main.c
@@ -51,6 +51,11 @@
 
 static const char alx_drv_name[] = "alx";
 
+/* disable WoL by default */
+bool enable_wol;
+module_param(enable_wol, bool, 0644);
+MODULE_PARM_DESC(enable_wol, "Enable Wake on Lan feature");
+
 static void alx_free_txbuf(struct alx_tx_queue *txq, int entry)
 {
 	struct alx_buffer *txb = &txq->bufs[entry];
@@ -1069,6 +1074,7 @@
 	alx->dev->max_mtu = ALX_MAX_FRAME_LEN(ALX_MAX_FRAME_SIZE);
 	alx->tx_ringsz = 256;
 	alx->rx_ringsz = 512;
+	hw->sleep_ctrl = ALX_SLEEP_WOL_MAGIC | ALX_SLEEP_WOL_PHY;
 	hw->imt = 200;
 	alx->int_mask = ALX_ISR_MISC;
 	hw->dma_chnl = hw->max_dma_chnl;
@@ -1249,8 +1255,12 @@
 
 static void __alx_stop(struct alx_priv *alx)
 {
-	alx_halt(alx);
 	alx_free_irq(alx);
+
+	cancel_work_sync(&alx->link_check_wk);
+	cancel_work_sync(&alx->reset_wk);
+
+	alx_halt(alx);
 	alx_free_rings(alx);
 	alx_free_napis(alx);
 }
@@ -1343,6 +1353,66 @@
 	return 0;
 }
 
+static int __alx_shutdown(struct pci_dev *pdev, bool *wol_en)
+{
+	struct alx_priv *alx = pci_get_drvdata(pdev);
+	struct net_device *netdev = alx->dev;
+	struct alx_hw *hw = &alx->hw;
+	int err, speed;
+	u8 duplex;
+
+	netif_device_detach(netdev);
+
+	if (netif_running(netdev))
+		__alx_stop(alx);
+
+#ifdef CONFIG_PM_SLEEP
+	err = pci_save_state(pdev);
+	if (err)
+		return err;
+#endif
+
+	err = alx_select_powersaving_speed(hw, &speed, &duplex);
+	if (err)
+		return err;
+	err = alx_clear_phy_intr(hw);
+	if (err)
+		return err;
+	err = alx_pre_suspend(hw, speed, duplex);
+	if (err)
+		return err;
+	err = alx_config_wol(hw);
+	if (err)
+		return err;
+
+	*wol_en = false;
+	if (hw->sleep_ctrl & ALX_SLEEP_ACTIVE) {
+		netif_info(alx, wol, netdev,
+			   "wol: ctrl=%X, speed=%X\n",
+			   hw->sleep_ctrl, speed);
+		device_set_wakeup_enable(&pdev->dev, true);
+		*wol_en = true;
+	}
+
+	pci_disable_device(pdev);
+
+	return 0;
+}
+
+static void alx_shutdown(struct pci_dev *pdev)
+{
+	int err;
+	bool wol_en;
+
+	err = __alx_shutdown(pdev, &wol_en);
+	if (!err) {
+		pci_wake_from_d3(pdev, wol_en);
+		pci_set_power_state(pdev, PCI_D3hot);
+	} else {
+		dev_err(&pdev->dev, "shutdown fail %d\n", err);
+	}
+}
+
 static void alx_link_check(struct work_struct *work)
 {
 	struct alx_priv *alx;
@@ -1836,6 +1906,8 @@
 		goto out_unmap;
 	}
 
+	device_set_wakeup_enable(&pdev->dev, hw->sleep_ctrl);
+
 	netdev_info(netdev,
 		    "Qualcomm Atheros AR816x/AR817x Ethernet [%pM]\n",
 		    netdev->dev_addr);
@@ -1848,6 +1920,7 @@
 	free_netdev(netdev);
 out_pci_release:
 	pci_release_mem_regions(pdev);
+	pci_disable_pcie_error_reporting(pdev);
 out_pci_disable:
 	pci_disable_device(pdev);
 	return err;
@@ -1858,9 +1931,6 @@
 	struct alx_priv *alx = pci_get_drvdata(pdev);
 	struct alx_hw *hw = &alx->hw;
 
-	cancel_work_sync(&alx->link_check_wk);
-	cancel_work_sync(&alx->reset_wk);
-
 	/* restore permanent mac address */
 	alx_set_macaddr(hw, hw->perm_addr);
 
@@ -1877,41 +1947,95 @@
 #ifdef CONFIG_PM_SLEEP
 static int alx_suspend(struct device *dev)
 {
-	struct alx_priv *alx = dev_get_drvdata(dev);
+	struct pci_dev *pdev = to_pci_dev(dev);
+	int err;
+	bool wol_en;
+
+	err = __alx_shutdown(pdev, &wol_en);
+	if (err) {
+		dev_err(&pdev->dev, "shutdown fail in suspend %d\n", err);
+		return err;
+	}
+
+	if (wol_en) {
+		pci_prepare_to_sleep(pdev);
+	} else {
+		pci_wake_from_d3(pdev, false);
+		pci_set_power_state(pdev, PCI_D3hot);
+	}
 
-	if (!netif_running(alx->dev))
-		return 0;
-	netif_device_detach(alx->dev);
-	__alx_stop(alx);
 	return 0;
 }
 
 static int alx_resume(struct device *dev)
 {
-	struct alx_priv *alx = dev_get_drvdata(dev);
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct alx_priv *alx = pci_get_drvdata(pdev);
+	struct net_device *netdev = alx->dev;
 	struct alx_hw *hw = &alx->hw;
 	int err;
 
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+	pci_save_state(pdev);
+
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+	pci_enable_wake(pdev, PCI_D3cold, 0);
+
+	hw->link_speed = SPEED_UNKNOWN;
+	alx->int_mask = ALX_ISR_MISC;
+
+	alx_reset_pcie(hw);
 	alx_reset_phy(hw);
 
-	if (!netif_running(alx->dev))
-		return 0;
-	netif_device_attach(alx->dev);
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+	pci_save_state(pdev);
 
-	rtnl_lock();
-	err = __alx_open(alx, true);
-	rtnl_unlock();
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+	pci_enable_wake(pdev, PCI_D3cold, 0);
+
+	hw->link_speed = SPEED_UNKNOWN;
+	alx->int_mask = ALX_ISR_MISC;
+
+	alx_reset_pcie(hw);
+	alx_reset_phy(hw);
+
+	err = alx_reset_mac(hw);
+	if (err) {
+		netif_err(alx, hw, alx->dev,
+			  "resume:reset_mac fail %d\n", err);
+		return -EIO;
+	}
+
+	err = alx_setup_speed_duplex(hw, hw->adv_cfg, hw->flowctrl);
+	if (err) {
+		netif_err(alx, hw, alx->dev,
+			  "resume:setup_speed_duplex fail %d\n", err);
+		return -EIO;
+	}
+
+	if (netif_running(netdev)) {
+		rtnl_lock();
+		err = __alx_open(alx, true);
+		rtnl_unlock();
+		if (err)
+			return err;
+	}
+
+	netif_device_attach(netdev);
 
 	return err;
 }
+#endif
 
+#ifdef CONFIG_PM_SLEEP
 static SIMPLE_DEV_PM_OPS(alx_pm_ops, alx_suspend, alx_resume);
 #define ALX_PM_OPS      (&alx_pm_ops)
 #else
 #define ALX_PM_OPS      NULL
 #endif
 
-
 static pci_ers_result_t alx_pci_error_detected(struct pci_dev *pdev,
 					       pci_channel_state_t state)
 {
@@ -1954,6 +2078,8 @@
 	}
 
 	pci_set_master(pdev);
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+	pci_enable_wake(pdev, PCI_D3cold, 0);
 
 	alx_reset_pcie(hw);
 	if (!alx_reset_mac(hw))
@@ -2008,6 +2134,7 @@
 	.id_table    = alx_pci_tbl,
 	.probe       = alx_probe,
 	.remove      = alx_remove,
+	.shutdown    = alx_shutdown,
 	.err_handler = &alx_err_handlers,
 	.driver.pm   = ALX_PM_OPS,
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -1989,8 +1989,11 @@
 			real_len = (((unsigned char *)ip_hdr(skb) - skb->data)
 					+ ntohs(ip_hdr(skb)->tot_len));
 
-			if (real_len < skb->len)
-				pskb_trim(skb, real_len);
+			if (real_len < skb->len) {
+				err = pskb_trim(skb, real_len);
+				if (err)
+					return err;
+			}
 
 			hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb));
 			if (unlikely(skb->len == hdr_len)) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
@@ -868,10 +868,13 @@
 		netdev_err(adapter->netdev, "offset(%d) > ring size(%d) !!\n",
 			   offset, adapter->ring_size);
 		err = -1;
-		goto failed;
+		goto free_buffer;
 	}
 
 	return 0;
+free_buffer:
+	kfree(tx_ring->tx_buffer);
+	tx_ring->tx_buffer = NULL;
 failed:
 	if (adapter->ring_vir_addr != NULL) {
 		pci_free_consistent(pdev, adapter->ring_size,
@@ -1638,8 +1641,11 @@
 			real_len = (((unsigned char *)ip_hdr(skb) - skb->data)
 					+ ntohs(ip_hdr(skb)->tot_len));
 
-			if (real_len < skb->len)
-				pskb_trim(skb, real_len);
+			if (real_len < skb->len) {
+				err = pskb_trim(skb, real_len);
+				if (err)
+					return err;
+			}
 
 			hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb));
 			if (unlikely(skb->len == hdr_len)) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/broadcom/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/broadcom/Makefile
@@ -16,3 +16,8 @@
 obj-$(CONFIG_BGMAC_PLATFORM) += bgmac-platform.o
 obj-$(CONFIG_SYSTEMPORT) += bcmsysport.o
 obj-$(CONFIG_BNXT) += bnxt/
+
+# FIXME: temporarily silence -Warray-bounds on non W=1+ builds
+ifndef KBUILD_EXTRA_WARN
+CFLAGS_tg3.o += -Wno-array-bounds
+endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/broadcom/b44.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/broadcom/b44.c
@@ -1519,8 +1519,10 @@
 	int ethaddr_bytes = ETH_ALEN;
 
 	memset(ppattern + offset, 0xff, magicsync);
-	for (j = 0; j < magicsync; j++)
-		set_bit(len++, (unsigned long *) pmask);
+	for (j = 0; j < magicsync; j++) {
+		pmask[len >> 3] |= BIT(len & 7);
+		len++;
+	}
 
 	for (j = 0; j < B44_MAX_PATTERNS; j++) {
 		if ((B44_PATTERN_SIZE - len) >= ETH_ALEN)
@@ -1532,7 +1534,8 @@
 		for (k = 0; k< ethaddr_bytes; k++) {
 			ppattern[offset + magicsync +
 				(j * ETH_ALEN) + k] = macaddr[k];
-			set_bit(len++, (unsigned long *) pmask);
+			pmask[len >> 3] |= BIT(len & 7);
+			len++;
 		}
 	}
 	return len - 1;
@@ -2030,12 +2033,14 @@
 		bp->flags |= B44_FLAG_TX_PAUSE;
 	else
 		bp->flags &= ~B44_FLAG_TX_PAUSE;
-	if (bp->flags & B44_FLAG_PAUSE_AUTO) {
-		b44_halt(bp);
-		b44_init_rings(bp);
-		b44_init_hw(bp, B44_FULL_RESET);
-	} else {
-		__b44_set_flow_ctrl(bp, bp->flags);
+	if (netif_running(dev)) {
+		if (bp->flags & B44_FLAG_PAUSE_AUTO) {
+			b44_halt(bp);
+			b44_init_rings(bp);
+			b44_init_hw(bp, B44_FULL_RESET);
+		} else {
+			__b44_set_flow_ctrl(bp, bp->flags);
+		}
 	}
 	spin_unlock_irq(&bp->lock);
 
@@ -2388,7 +2393,8 @@
 		goto err_out_free_dev;
 	}
 
-	if (dma_set_mask_and_coherent(sdev->dma_dev, DMA_BIT_MASK(30))) {
+	err = dma_set_mask_and_coherent(sdev->dma_dev, DMA_BIT_MASK(30));
+	if (err) {
 		dev_err(sdev->dev,
 			"Required 30BIT DMA mask unsupported by the system\n");
 		goto err_out_powerdown;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/broadcom/bcmsysport.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/broadcom/bcmsysport.c
@@ -666,7 +666,8 @@
 	dma_addr_t mapping;
 
 	/* Allocate a new SKB for a new packet */
-	skb = netdev_alloc_skb(priv->netdev, RX_BUF_LENGTH);
+	skb = __netdev_alloc_skb(priv->netdev, RX_BUF_LENGTH,
+				 GFP_ATOMIC | __GFP_NOWARN);
 	if (!skb) {
 		priv->mib.alloc_rx_buff_failed++;
 		netif_err(priv, rx_err, ndev, "SKB alloc failed\n");
@@ -1276,11 +1277,11 @@
 	struct bcm_sysport_priv *priv = netdev_priv(dev);
 	struct device *kdev = &priv->pdev->dev;
 	struct bcm_sysport_tx_ring *ring;
+	unsigned long flags, desc_flags;
 	struct bcm_sysport_cb *cb;
 	struct netdev_queue *txq;
 	u32 len_status, addr_lo;
 	unsigned int skb_len;
-	unsigned long flags;
 	dma_addr_t mapping;
 	u16 queue;
 	int ret;
@@ -1315,6 +1316,7 @@
 		netif_err(priv, tx_err, dev, "DMA map failed at %p (len=%d)\n",
 			  skb->data, skb_len);
 		ret = NETDEV_TX_OK;
+		dev_kfree_skb_any(skb);
 		goto out;
 	}
 
@@ -1338,8 +1340,10 @@
 	ring->desc_count--;
 
 	/* Ports are latched, so write upper address first */
+	spin_lock_irqsave(&priv->desc_lock, desc_flags);
 	tdma_writel(priv, len_status, TDMA_WRITE_PORT_HI(ring->index));
 	tdma_writel(priv, addr_lo, TDMA_WRITE_PORT_LO(ring->index));
+	spin_unlock_irqrestore(&priv->desc_lock, desc_flags);
 
 	/* Check ring space and update SW control flow */
 	if (ring->desc_count == 0)
@@ -1969,6 +1973,7 @@
 	}
 
 	/* Initialize both hardware and software ring */
+	spin_lock_init(&priv->desc_lock);
 	for (i = 0; i < dev->num_tx_queues; i++) {
 		ret = bcm_sysport_init_tx_ring(priv, i);
 		if (ret) {
@@ -2135,7 +2140,7 @@
 		return -ENOSPC;
 
 	index = find_first_zero_bit(priv->filters, RXCHK_BRCM_TAG_MAX);
-	if (index > RXCHK_BRCM_TAG_MAX)
+	if (index >= RXCHK_BRCM_TAG_MAX)
 		return -ENOSPC;
 
 	/* Location is the classification ID, and index is the position
@@ -2323,7 +2328,7 @@
 		ring->switch_queue = qp;
 		ring->switch_port = port;
 		ring->inspect = true;
-		priv->ring_map[q + port * num_tx_queues] = ring;
+		priv->ring_map[qp + port * num_tx_queues] = ring;
 		qp++;
 	}
 
@@ -2338,7 +2343,7 @@
 	struct net_device *slave_dev;
 	unsigned int num_tx_queues;
 	struct net_device *dev;
-	unsigned int q, port;
+	unsigned int q, qp, port;
 
 	priv = container_of(nb, struct bcm_sysport_priv, dsa_notifier);
 	if (priv->netdev != info->master)
@@ -2364,7 +2369,8 @@
 			continue;
 
 		ring->inspect = false;
-		priv->ring_map[q + port * num_tx_queues] = NULL;
+		qp = ring->switch_queue;
+		priv->ring_map[qp + port * num_tx_queues] = NULL;
 	}
 
 	return 0;
@@ -2451,8 +2457,10 @@
 	priv->tx_rings = devm_kcalloc(&pdev->dev, txq,
 				      sizeof(struct bcm_sysport_tx_ring),
 				      GFP_KERNEL);
-	if (!priv->tx_rings)
-		return -ENOMEM;
+	if (!priv->tx_rings) {
+		ret = -ENOMEM;
+		goto err_free_netdev;
+	}
 
 	priv->is_lite = params->is_lite;
 	priv->num_rx_desc_words = params->num_rx_desc_words;
@@ -2516,6 +2524,7 @@
 			 NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
 	dev->hw_features |= dev->features;
 	dev->vlan_features |= dev->features;
+	dev->max_mtu = UMAC_MAX_MTU_SIZE;
 
 	/* Request the WOL interrupt and advertise suspend if available */
 	priv->wol_irq_disabled = 1;
@@ -2727,6 +2736,9 @@
 
 	umac_reset(priv);
 
+	/* Disable the UniMAC RX/TX */
+	umac_enable_set(priv, CMD_RX_EN | CMD_TX_EN, 0);
+
 	/* We may have been suspended and never received a WOL event that
 	 * would turn off MPD detection, take care of that now
 	 */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/broadcom/bcmsysport.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/broadcom/bcmsysport.h
@@ -742,6 +742,7 @@
 	int			wol_irq;
 
 	/* Transmit rings */
+	spinlock_t		desc_lock;
 	struct bcm_sysport_tx_ring *tx_rings;
 
 	/* Receive queue */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/broadcom/bgmac-bcma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/broadcom/bgmac-bcma.c
@@ -228,12 +228,12 @@
 		bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
 		bgmac->feature_flags |= BGMAC_FEAT_FLW_CTRL1;
 		bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_PHY;
-		if (ci->pkg == BCMA_PKG_ID_BCM47188 ||
-		    ci->pkg == BCMA_PKG_ID_BCM47186) {
+		if ((ci->id == BCMA_CHIP_ID_BCM5357 && ci->pkg == BCMA_PKG_ID_BCM47186) ||
+		    (ci->id == BCMA_CHIP_ID_BCM53572 && ci->pkg == BCMA_PKG_ID_BCM47188)) {
 			bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_RGMII;
 			bgmac->feature_flags |= BGMAC_FEAT_IOST_ATTACHED;
 		}
-		if (ci->pkg == BCMA_PKG_ID_BCM5358)
+		if (ci->id == BCMA_CHIP_ID_BCM5357 && ci->pkg == BCMA_PKG_ID_BCM5358)
 			bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_EPHYRMII;
 		break;
 	case BCMA_CHIP_ID_BCM53573:
@@ -323,7 +323,6 @@
 	bcma_mdio_mii_unregister(bgmac->mii_bus);
 	bgmac_enet_remove(bgmac);
 	bcma_set_drvdata(core, NULL);
-	kfree(bgmac);
 }
 
 static struct bcma_driver bgmac_bcma_driver = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/broadcom/bgmac-platform.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/broadcom/bgmac-platform.c
@@ -171,6 +171,7 @@
 static int bgmac_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
+	struct device_node *phy_node;
 	struct bgmac *bgmac;
 	struct resource *regs;
 	const u8 *mac_addr;
@@ -237,7 +238,9 @@
 	bgmac->cco_ctl_maskset = platform_bgmac_cco_ctl_maskset;
 	bgmac->get_bus_clock = platform_bgmac_get_bus_clock;
 	bgmac->cmn_maskset32 = platform_bgmac_cmn_maskset32;
-	if (of_parse_phandle(np, "phy-handle", 0)) {
+	phy_node = of_parse_phandle(np, "phy-handle", 0);
+	if (phy_node) {
+		of_node_put(phy_node);
 		bgmac->phy_connect = platform_phy_connect;
 	} else {
 		bgmac->phy_connect = bgmac_phy_connect_direct;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/broadcom/bgmac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/broadcom/bgmac.c
@@ -189,8 +189,8 @@
 	}
 
 	slot->skb = skb;
-	ring->end += nr_frags + 1;
 	netdev_sent_queue(net_dev, skb->len);
+	ring->end += nr_frags + 1;
 
 	wmb();
 
@@ -890,13 +890,13 @@
 
 		if (iost & BGMAC_BCMA_IOST_ATTACHED) {
 			flags = BGMAC_BCMA_IOCTL_SW_CLKEN;
-			if (!bgmac->has_robosw)
+			if (bgmac->in_init || !bgmac->has_robosw)
 				flags |= BGMAC_BCMA_IOCTL_SW_RESET;
 		}
 		bgmac_clk_enable(bgmac, flags);
 	}
 
-	if (iost & BGMAC_BCMA_IOST_ATTACHED && !bgmac->has_robosw)
+	if (iost & BGMAC_BCMA_IOST_ATTACHED && (bgmac->in_init || !bgmac->has_robosw))
 		bgmac_idm_write(bgmac, BCMA_IOCTL,
 				bgmac_idm_read(bgmac, BCMA_IOCTL) &
 				~BGMAC_BCMA_IOCTL_SW_RESET);
@@ -1447,7 +1447,7 @@
 	int err;
 
 	phy_dev = fixed_phy_register(PHY_POLL, &fphy_status, NULL);
-	if (!phy_dev || IS_ERR(phy_dev)) {
+	if (IS_ERR(phy_dev)) {
 		dev_err(bgmac->dev, "Failed to register fixed PHY device\n");
 		return -ENODEV;
 	}
@@ -1489,6 +1489,8 @@
 	struct net_device *net_dev = bgmac->net_dev;
 	int err;
 
+	bgmac->in_init = true;
+
 	bgmac_chip_intrs_off(bgmac);
 
 	net_dev->irq = bgmac->irq;
@@ -1538,6 +1540,8 @@
 	net_dev->hw_features = net_dev->features;
 	net_dev->vlan_features = net_dev->features;
 
+	bgmac->in_init = false;
+
 	err = register_netdev(bgmac->net_dev);
 	if (err) {
 		dev_err(bgmac->dev, "Cannot register net device\n");
@@ -1564,7 +1568,6 @@
 	phy_disconnect(bgmac->net_dev->phydev);
 	netif_napi_del(&bgmac->napi);
 	bgmac_dma_free(bgmac);
-	free_netdev(bgmac->net_dev);
 }
 EXPORT_SYMBOL_GPL(bgmac_enet_remove);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/broadcom/bgmac.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/broadcom/bgmac.h
@@ -511,6 +511,8 @@
 	int irq;
 	u32 int_mask;
 
+	bool in_init;
+
 	/* Current MAC state */
 	int mac_speed;
 	int mac_duplex;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/broadcom/bnx2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/broadcom/bnx2.c
@@ -1461,7 +1461,7 @@
 static void
 bnx2_enable_forced_2g5(struct bnx2 *bp)
 {
-	u32 uninitialized_var(bmcr);
+	u32 bmcr;
 	int err;
 
 	if (!(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE))
@@ -1505,7 +1505,7 @@
 static void
 bnx2_disable_forced_2g5(struct bnx2 *bp)
 {
-	u32 uninitialized_var(bmcr);
+	u32 bmcr;
 	int err;
 
 	if (!(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE))
@@ -8249,9 +8249,9 @@
 		BNX2_WR(bp, PCI_COMMAND, reg);
 	} else if ((BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A1) &&
 		!(bp->flags & BNX2_FLAG_PCIX)) {
-
 		dev_err(&pdev->dev,
 			"5706 A1 can only be used in a PCIX bus, aborting\n");
+		rc = -EPERM;
 		goto err_out_unmap;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -1256,7 +1256,7 @@
 
 struct bnx2x_fw_stats_req {
 	struct stats_query_header hdr;
-	struct stats_query_entry query[FP_SB_MAX_E1x+
+	struct stats_query_entry query[FP_SB_MAX_E2 +
 		BNX2X_FIRST_QUEUE_QUERY_IDX];
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -787,6 +787,7 @@
 			BNX2X_ERR("skb_put is about to fail...  pad %d  len %d  rx_buf_size %d\n",
 				  pad, len, fp->rx_buf_size);
 			bnx2x_panic();
+			bnx2x_frag_free(fp, new_data);
 			return;
 		}
 #endif
@@ -2666,7 +2667,8 @@
 	}
 
 	/* Allocated memory for FW statistics  */
-	if (bnx2x_alloc_fw_stats_mem(bp))
+	rc = bnx2x_alloc_fw_stats_mem(bp);
+	if (rc)
 		LOAD_ERROR_EXIT(bp, load_error0);
 
 	/* request pf to initialize status blocks */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
@@ -1004,9 +1004,6 @@
 static inline void bnx2x_free_rx_mem_pool(struct bnx2x *bp,
 					  struct bnx2x_alloc_pool *pool)
 {
-	if (!pool->page)
-		return;
-
 	put_page(pool->page);
 
 	pool->page = NULL;
@@ -1017,6 +1014,9 @@
 {
 	int i;
 
+	if (!fp->page_pool.page)
+		return;
+
 	if (fp->mode == TPA_MODE_DISABLED)
 		return;
 
@@ -1109,7 +1109,7 @@
 		for (i = 0; i < E1H_FUNC_MAX / 2; i++) {
 			u32 func_config =
 				MF_CFG_RD(bp,
-					  func_mf_config[BP_PORT(bp) + 2 * i].
+					  func_mf_config[BP_PATH(bp) + 2 * i].
 					  config);
 			func_num +=
 				((func_config & FUNC_MF_CFG_FUNC_HIDE) ? 0 : 1);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init.h
@@ -296,7 +296,6 @@
  *    possible, the driver should only write the valid vnics into the internal
  *    ram according to the appropriate port mode.
  */
-#define BITS_TO_BYTES(x) ((x)/8)
 
 /* CMNG constants, as derived from system spec calculations */
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h
@@ -635,11 +635,13 @@
 {
 	int i, rc;
 	struct bnx2x_ilt *ilt = BP_ILT(bp);
-	struct ilt_client_info *ilt_cli = &ilt->clients[cli_num];
+	struct ilt_client_info *ilt_cli;
 
 	if (!ilt || !ilt->lines)
 		return -1;
 
+	ilt_cli = &ilt->clients[cli_num];
+
 	if (ilt_cli->flags & (ILT_CLIENT_SKIP_INIT | ILT_CLIENT_SKIP_MEM))
 		return 0;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -9976,10 +9976,18 @@
  */
 static void bnx2x_parity_recover(struct bnx2x *bp)
 {
-	bool global = false;
 	u32 error_recovered, error_unrecovered;
-	bool is_parity;
+	bool is_parity, global = false;
+#ifdef CONFIG_BNX2X_SRIOV
+	int vf_idx;
+
+	for (vf_idx = 0; vf_idx < bp->requested_nr_virtfn; vf_idx++) {
+		struct bnx2x_virtf *vf = BP_VF(bp, vf_idx);
 
+		if (vf)
+			vf->state = VF_LOST;
+	}
+#endif
 	DP(NETIF_MSG_HW, "Handling parity\n");
 	while (1) {
 		switch (bp->recovery_state) {
@@ -14259,10 +14267,6 @@
 
 	/* Stop Tx */
 	bnx2x_tx_disable(bp);
-	/* Delete all NAPI objects */
-	bnx2x_del_all_napi(bp);
-	if (CNIC_LOADED(bp))
-		bnx2x_del_all_napi_cnic(bp);
 	netdev_reset_tc(bp->dev);
 
 	del_timer_sync(&bp->timer);
@@ -14367,6 +14371,11 @@
 		bnx2x_drain_tx_queues(bp);
 		bnx2x_send_unload_req(bp, UNLOAD_RECOVERY);
 		bnx2x_netif_stop(bp, 1);
+		bnx2x_del_all_napi(bp);
+
+		if (CNIC_LOADED(bp))
+			bnx2x_del_all_napi_cnic(bp);
+
 		bnx2x_free_irq(bp);
 
 		/* Report UNLOAD_DONE to MCP */
@@ -14417,11 +14426,16 @@
 	bp->fw_seq = SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) &
 							DRV_MSG_SEQ_NUMBER_MASK;
 
-	if (netif_running(dev))
-		bnx2x_nic_load(bp, LOAD_NORMAL);
+	if (netif_running(dev)) {
+		if (bnx2x_nic_load(bp, LOAD_NORMAL)) {
+			netdev_err(bp->dev, "Error during driver initialization, try unloading/reloading the driver\n");
+			goto done;
+		}
+	}
 
 	netif_device_attach(dev);
 
+done:
 	rtnl_unlock();
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
@@ -807,16 +807,20 @@
 
 static u8 bnx2x_vf_is_pcie_pending(struct bnx2x *bp, u8 abs_vfid)
 {
-	struct pci_dev *dev;
 	struct bnx2x_virtf *vf = bnx2x_vf_by_abs_fid(bp, abs_vfid);
+	struct pci_dev *dev;
+	bool pending;
 
 	if (!vf)
 		return false;
 
 	dev = pci_get_domain_bus_and_slot(vf->domain, vf->bus, vf->devfn);
-	if (dev)
-		return bnx2x_is_pcie_pending(dev);
-	return false;
+	if (!dev)
+		return false;
+	pending = bnx2x_is_pcie_pending(dev);
+	pci_dev_put(dev);
+
+	return pending;
 }
 
 int bnx2x_vf_flr_clnup_epilog(struct bnx2x *bp, u8 abs_vfid)
@@ -1245,8 +1249,10 @@
 		goto failed;
 
 	/* SR-IOV capability was enabled but there are no VFs*/
-	if (iov->total == 0)
+	if (iov->total == 0) {
+		err = 0;
 		goto failed;
+	}
 
 	iov->nr_virtfn = min_t(u16, iov->total, num_vfs_param);
 
@@ -2397,15 +2403,21 @@
 	/* send the ramrod on all the queues of the PF */
 	for_each_eth_queue(bp, i) {
 		struct bnx2x_fastpath *fp = &bp->fp[i];
+		int tx_idx;
 
 		/* Set the appropriate Queue object */
 		q_params.q_obj = &bnx2x_sp_obj(bp, fp).q_obj;
 
-		/* Update the Queue state */
-		rc = bnx2x_queue_state_change(bp, &q_params);
-		if (rc) {
-			BNX2X_ERR("Failed to configure Tx switching\n");
-			return rc;
+		for (tx_idx = FIRST_TX_COS_INDEX;
+		     tx_idx < fp->max_cos; tx_idx++) {
+			q_params.params.update.cid_index = tx_idx;
+
+			/* Update the Queue state */
+			rc = bnx2x_queue_state_change(bp, &q_params);
+			if (rc) {
+				BNX2X_ERR("Failed to configure Tx switching\n");
+				return rc;
+			}
 		}
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
@@ -139,6 +139,7 @@
 #define VF_ACQUIRED	1	/* VF acquired, but not initialized */
 #define VF_ENABLED	2	/* VF Enabled */
 #define VF_RESET	3	/* VF FLR'd, pending cleanup */
+#define VF_LOST		4	/* Recovery while VFs are loaded */
 
 	bool flr_clnup_stage;	/* true during flr cleanup */
 	bool malicious;		/* true if FW indicated so, until FLR */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
@@ -2107,6 +2107,18 @@
 {
 	int i;
 
+	if (vf->state == VF_LOST) {
+		/* Just ack the FW and return if VFs are lost
+		 * in case of parity error. VFs are supposed to be timedout
+		 * on waiting for PF response.
+		 */
+		DP(BNX2X_MSG_IOV,
+		   "VF 0x%x lost, not handling the request\n", vf->abs_vfid);
+
+		storm_memset_vf_mbx_ack(bp, vf->abs_vfid);
+		return;
+	}
+
 	/* check if tlv type is known */
 	if (bnx2x_tlv_supported(mbx->first_tlv.tl.type)) {
 		/* Lock the per vf op mutex and note the locker's identity.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -125,7 +125,10 @@
 	NETXTREME_E_VF,
 	NETXTREME_C_VF,
 	NETXTREME_S_VF,
+	NETXTREME_C_VF_HV,
+	NETXTREME_E_VF_HV,
 	NETXTREME_E_P5_VF,
+	NETXTREME_E_P5_VF_HV,
 };
 
 /* indexed by enum above */
@@ -173,7 +176,10 @@
 	[NETXTREME_E_VF] = { "Broadcom NetXtreme-E Ethernet Virtual Function" },
 	[NETXTREME_C_VF] = { "Broadcom NetXtreme-C Ethernet Virtual Function" },
 	[NETXTREME_S_VF] = { "Broadcom NetXtreme-S Ethernet Virtual Function" },
+	[NETXTREME_C_VF_HV] = { "Broadcom NetXtreme-C Virtual Function for Hyper-V" },
+	[NETXTREME_E_VF_HV] = { "Broadcom NetXtreme-E Virtual Function for Hyper-V" },
 	[NETXTREME_E_P5_VF] = { "Broadcom BCM5750X NetXtreme-E Ethernet Virtual Function" },
+	[NETXTREME_E_P5_VF_HV] = { "Broadcom BCM5750X NetXtreme-E Virtual Function for Hyper-V" },
 };
 
 static const struct pci_device_id bnxt_pci_tbl[] = {
@@ -215,25 +221,35 @@
 	{ PCI_VDEVICE(BROADCOM, 0x1750), .driver_data = BCM57508 },
 	{ PCI_VDEVICE(BROADCOM, 0x1751), .driver_data = BCM57504 },
 	{ PCI_VDEVICE(BROADCOM, 0x1752), .driver_data = BCM57502 },
-	{ PCI_VDEVICE(BROADCOM, 0x1800), .driver_data = BCM57508_NPAR },
+	{ PCI_VDEVICE(BROADCOM, 0x1800), .driver_data = BCM57502_NPAR },
 	{ PCI_VDEVICE(BROADCOM, 0x1801), .driver_data = BCM57504_NPAR },
-	{ PCI_VDEVICE(BROADCOM, 0x1802), .driver_data = BCM57502_NPAR },
-	{ PCI_VDEVICE(BROADCOM, 0x1803), .driver_data = BCM57508_NPAR },
+	{ PCI_VDEVICE(BROADCOM, 0x1802), .driver_data = BCM57508_NPAR },
+	{ PCI_VDEVICE(BROADCOM, 0x1803), .driver_data = BCM57502_NPAR },
 	{ PCI_VDEVICE(BROADCOM, 0x1804), .driver_data = BCM57504_NPAR },
-	{ PCI_VDEVICE(BROADCOM, 0x1805), .driver_data = BCM57502_NPAR },
+	{ PCI_VDEVICE(BROADCOM, 0x1805), .driver_data = BCM57508_NPAR },
 	{ PCI_VDEVICE(BROADCOM, 0xd802), .driver_data = BCM58802 },
 	{ PCI_VDEVICE(BROADCOM, 0xd804), .driver_data = BCM58804 },
 #ifdef CONFIG_BNXT_SRIOV
 	{ PCI_VDEVICE(BROADCOM, 0x1606), .driver_data = NETXTREME_E_VF },
+	{ PCI_VDEVICE(BROADCOM, 0x1607), .driver_data = NETXTREME_E_VF_HV },
+	{ PCI_VDEVICE(BROADCOM, 0x1608), .driver_data = NETXTREME_E_VF_HV },
 	{ PCI_VDEVICE(BROADCOM, 0x1609), .driver_data = NETXTREME_E_VF },
+	{ PCI_VDEVICE(BROADCOM, 0x16bd), .driver_data = NETXTREME_E_VF_HV },
 	{ PCI_VDEVICE(BROADCOM, 0x16c1), .driver_data = NETXTREME_E_VF },
+	{ PCI_VDEVICE(BROADCOM, 0x16c2), .driver_data = NETXTREME_C_VF_HV },
+	{ PCI_VDEVICE(BROADCOM, 0x16c3), .driver_data = NETXTREME_C_VF_HV },
+	{ PCI_VDEVICE(BROADCOM, 0x16c4), .driver_data = NETXTREME_E_VF_HV },
+	{ PCI_VDEVICE(BROADCOM, 0x16c5), .driver_data = NETXTREME_E_VF_HV },
 	{ PCI_VDEVICE(BROADCOM, 0x16cb), .driver_data = NETXTREME_C_VF },
 	{ PCI_VDEVICE(BROADCOM, 0x16d3), .driver_data = NETXTREME_E_VF },
 	{ PCI_VDEVICE(BROADCOM, 0x16dc), .driver_data = NETXTREME_E_VF },
 	{ PCI_VDEVICE(BROADCOM, 0x16e1), .driver_data = NETXTREME_C_VF },
 	{ PCI_VDEVICE(BROADCOM, 0x16e5), .driver_data = NETXTREME_C_VF },
+	{ PCI_VDEVICE(BROADCOM, 0x16e6), .driver_data = NETXTREME_C_VF_HV },
 	{ PCI_VDEVICE(BROADCOM, 0x1806), .driver_data = NETXTREME_E_P5_VF },
 	{ PCI_VDEVICE(BROADCOM, 0x1807), .driver_data = NETXTREME_E_P5_VF },
+	{ PCI_VDEVICE(BROADCOM, 0x1808), .driver_data = NETXTREME_E_P5_VF_HV },
+	{ PCI_VDEVICE(BROADCOM, 0x1809), .driver_data = NETXTREME_E_P5_VF_HV },
 	{ PCI_VDEVICE(BROADCOM, 0xd800), .driver_data = NETXTREME_S_VF },
 #endif
 	{ 0 }
@@ -263,7 +279,9 @@
 static bool bnxt_vf_pciid(enum board_idx idx)
 {
 	return (idx == NETXTREME_C_VF || idx == NETXTREME_E_VF ||
-		idx == NETXTREME_S_VF || idx == NETXTREME_E_P5_VF);
+		idx == NETXTREME_S_VF || idx == NETXTREME_C_VF_HV ||
+		idx == NETXTREME_E_VF_HV || idx == NETXTREME_E_P5_VF ||
+		idx == NETXTREME_E_P5_VF_HV);
 }
 
 #define DB_CP_REARM_FLAGS	(DB_KEY_CP | DB_IDX_VALID)
@@ -342,6 +360,26 @@
 	return md_dst->u.port_info.port_id;
 }
 
+static bool bnxt_txr_netif_try_stop_queue(struct bnxt *bp,
+					  struct bnxt_tx_ring_info *txr,
+					  struct netdev_queue *txq)
+{
+	netif_tx_stop_queue(txq);
+
+	/* netif_tx_stop_queue() must be done before checking
+	 * tx index in bnxt_tx_avail() below, because in
+	 * bnxt_tx_int(), we update tx index before checking for
+	 * netif_tx_queue_stopped().
+	 */
+	smp_mb();
+	if (bnxt_tx_avail(bp, txr) >= bp->tx_wake_thresh) {
+		netif_tx_wake_queue(txq);
+		return false;
+	}
+
+	return true;
+}
+
 static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct bnxt *bp = netdev_priv(dev);
@@ -369,8 +407,8 @@
 
 	free_size = bnxt_tx_avail(bp, txr);
 	if (unlikely(free_size < skb_shinfo(skb)->nr_frags + 2)) {
-		netif_tx_stop_queue(txq);
-		return NETDEV_TX_BUSY;
+		if (bnxt_txr_netif_try_stop_queue(bp, txr, txq))
+			return NETDEV_TX_BUSY;
 	}
 
 	length = skb->len;
@@ -579,16 +617,7 @@
 		if (netdev_xmit_more() && !tx_buf->is_push)
 			bnxt_db_write(bp, &txr->tx_db, prod);
 
-		netif_tx_stop_queue(txq);
-
-		/* netif_tx_stop_queue() must be done before checking
-		 * tx index in bnxt_tx_avail() below, because in
-		 * bnxt_tx_int(), we update tx index before checking for
-		 * netif_tx_queue_stopped().
-		 */
-		smp_mb();
-		if (bnxt_tx_avail(bp, txr) > bp->tx_wake_thresh)
-			netif_tx_wake_queue(txq);
+		bnxt_txr_netif_try_stop_queue(bp, txr, txq);
 	}
 	return NETDEV_TX_OK;
 
@@ -672,14 +701,9 @@
 	smp_mb();
 
 	if (unlikely(netif_tx_queue_stopped(txq)) &&
-	    (bnxt_tx_avail(bp, txr) > bp->tx_wake_thresh)) {
-		__netif_tx_lock(txq, smp_processor_id());
-		if (netif_tx_queue_stopped(txq) &&
-		    bnxt_tx_avail(bp, txr) > bp->tx_wake_thresh &&
-		    txr->dev_state != BNXT_DEV_STATE_CLOSING)
-			netif_tx_wake_queue(txq);
-		__netif_tx_unlock(txq);
-	}
+	    bnxt_tx_avail(bp, txr) >= bp->tx_wake_thresh &&
+	    READ_ONCE(txr->dev_state) != BNXT_DEV_STATE_CLOSING)
+		netif_tx_wake_queue(txq);
 }
 
 static struct page *__bnxt_alloc_rx_page(struct bnxt *bp, dma_addr_t *mapping,
@@ -942,6 +966,7 @@
 	dma_addr -= bp->rx_dma_offset;
 	dma_unmap_page_attrs(&bp->pdev->dev, dma_addr, PAGE_SIZE, bp->rx_dir,
 			     DMA_ATTR_WEAK_ORDERING);
+	page_pool_release_page(rxr->page_pool, page);
 
 	if (unlikely(!payload))
 		payload = eth_get_headlen(bp->dev, data_ptr, len);
@@ -1142,6 +1167,9 @@
 
 static void bnxt_queue_fw_reset_work(struct bnxt *bp, unsigned long delay)
 {
+	if (!(test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)))
+		return;
+
 	if (BNXT_PF(bp))
 		queue_delayed_work(bnxt_pf_wq, &bp->fw_reset_task, delay);
 	else
@@ -1156,14 +1184,6 @@
 		schedule_work(&bp->sp_task);
 }
 
-static void bnxt_cancel_sp_work(struct bnxt *bp)
-{
-	if (BNXT_PF(bp))
-		flush_workqueue(bnxt_pf_wq);
-	else
-		cancel_work_sync(&bp->sp_task);
-}
-
 static void bnxt_sched_reset(struct bnxt *bp, struct bnxt_rx_ring_info *rxr)
 {
 	if (!rxr->bnapi->in_reset) {
@@ -1704,6 +1724,10 @@
 	if (!RX_CMP_VALID(rxcmp1, tmp_raw_cons))
 		return -EBUSY;
 
+	/* The valid test of the entry must be done first before
+	 * reading any further.
+	 */
+	dma_rmb();
 	prod = rxr->rx_prod;
 
 	if (cmp_type == CMP_TYPE_RX_L2_TPA_START_CMP) {
@@ -1732,12 +1756,14 @@
 
 	cons = rxcmp->rx_cmp_opaque;
 	if (unlikely(cons != rxr->rx_next_cons)) {
-		int rc1 = bnxt_discard_rx(bp, cpr, raw_cons, rxcmp);
+		int rc1 = bnxt_discard_rx(bp, cpr, &tmp_raw_cons, rxcmp);
 
 		netdev_warn(bp->dev, "RX cons %x != expected cons %x\n",
 			    cons, rxr->rx_next_cons);
 		bnxt_sched_reset(bp, rxr);
-		return rc1;
+		if (rc1)
+			return rc1;
+		goto next_rx_no_prod_no_len;
 	}
 	rx_buf = &rxr->rx_buf_ring[cons];
 	data = rx_buf->data;
@@ -1767,8 +1793,12 @@
 
 		rc = -EIO;
 		if (rx_err & RX_CMPL_ERRORS_BUFFER_ERROR_MASK) {
-			netdev_warn(bp->dev, "RX buffer error %x\n", rx_err);
-			bnxt_sched_reset(bp, rxr);
+			bnapi->cp_ring.rx_buf_errors++;
+			if (!(bp->flags & BNXT_FLAG_CHIP_P5)) {
+				netdev_warn(bp->dev, "RX buffer error %x\n",
+					    rx_err);
+				bnxt_sched_reset(bp, rxr);
+			}
 		}
 		goto next_rx_no_len;
 	}
@@ -1892,6 +1922,10 @@
 	if (!RX_CMP_VALID(rxcmp1, tmp_raw_cons))
 		return -EBUSY;
 
+	/* The valid test of the entry must be done first before
+	 * reading any further.
+	 */
+	dma_rmb();
 	cmp_type = RX_CMP_TYPE(rxcmp);
 	if (cmp_type == CMP_TYPE_RX_L2_CMP) {
 		rxcmp1->rx_cmp_cfa_code_errors_v2 |=
@@ -1991,6 +2025,9 @@
 	case ASYNC_EVENT_CMPL_EVENT_ID_RESET_NOTIFY: {
 		u32 data1 = le32_to_cpu(cmpl->event_data1);
 
+		if (!bp->fw_health)
+			goto async_event_process_exit;
+
 		bp->fw_reset_timestamp = jiffies;
 		bp->fw_reset_min_dsecs = cmpl->timestamp_lo;
 		if (!bp->fw_reset_min_dsecs)
@@ -2169,7 +2206,7 @@
 		if (TX_CMP_TYPE(txcmp) == CMP_TYPE_TX_L2_CMP) {
 			tx_pkts++;
 			/* return full budget so NAPI will complete. */
-			if (unlikely(tx_pkts > bp->tx_wake_thresh)) {
+			if (unlikely(tx_pkts >= bp->tx_wake_thresh)) {
 				rx_pkts = budget;
 				raw_cons = NEXT_RAW_CMP(raw_cons);
 				if (budget)
@@ -2285,6 +2322,10 @@
 		if (!TX_CMP_VALID(txcmp, raw_cons))
 			break;
 
+		/* The valid test of the entry must be done first before
+		 * reading any further.
+		 */
+		dma_rmb();
 		if ((TX_CMP_TYPE(txcmp) & 0x30) == 0x10) {
 			tmp_raw_cons = NEXT_RAW_CMP(raw_cons);
 			cp_cons = RING_CMP(tmp_raw_cons);
@@ -2706,7 +2747,7 @@
 
 static void bnxt_free_tpa_info(struct bnxt *bp)
 {
-	int i;
+	int i, j;
 
 	for (i = 0; i < bp->rx_nr_rings; i++) {
 		struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i];
@@ -2714,8 +2755,10 @@
 		kfree(rxr->rx_tpa_idx_map);
 		rxr->rx_tpa_idx_map = NULL;
 		if (rxr->rx_tpa) {
-			kfree(rxr->rx_tpa[0].agg_arr);
-			rxr->rx_tpa[0].agg_arr = NULL;
+			for (j = 0; j < bp->max_tpa; j++) {
+				kfree(rxr->rx_tpa[j].agg_arr);
+				rxr->rx_tpa[j].agg_arr = NULL;
+			}
 		}
 		kfree(rxr->rx_tpa);
 		rxr->rx_tpa = NULL;
@@ -2724,14 +2767,13 @@
 
 static int bnxt_alloc_tpa_info(struct bnxt *bp)
 {
-	int i, j, total_aggs = 0;
+	int i, j;
 
 	bp->max_tpa = MAX_TPA;
 	if (bp->flags & BNXT_FLAG_CHIP_P5) {
 		if (!bp->max_tpa_v2)
 			return 0;
 		bp->max_tpa = max_t(u16, bp->max_tpa_v2, MAX_TPA_P5);
-		total_aggs = bp->max_tpa * MAX_SKB_FRAGS;
 	}
 
 	for (i = 0; i < bp->rx_nr_rings; i++) {
@@ -2745,12 +2787,12 @@
 
 		if (!(bp->flags & BNXT_FLAG_CHIP_P5))
 			continue;
-		agg = kcalloc(total_aggs, sizeof(*agg), GFP_KERNEL);
-		rxr->rx_tpa[0].agg_arr = agg;
-		if (!agg)
-			return -ENOMEM;
-		for (j = 1; j < bp->max_tpa; j++)
-			rxr->rx_tpa[j].agg_arr = agg + j * MAX_SKB_FRAGS;
+		for (j = 0; j < bp->max_tpa; j++) {
+			agg = kcalloc(MAX_SKB_FRAGS, sizeof(*agg), GFP_KERNEL);
+			if (!agg)
+				return -ENOMEM;
+			rxr->rx_tpa[j].agg_arr = agg;
+		}
 		rxr->rx_tpa_idx_map = kzalloc(sizeof(*rxr->rx_tpa_idx_map),
 					      GFP_KERNEL);
 		if (!rxr->rx_tpa_idx_map)
@@ -3288,7 +3330,7 @@
 	u16 i;
 
 	bp->tx_wake_thresh = max_t(int, bp->tx_ring_size / 2,
-				   MAX_SKB_FRAGS + 1);
+				   BNXT_MIN_TX_DESC_CNT);
 
 	for (i = 0; i < bp->tx_nr_rings; i++) {
 		struct bnxt_tx_ring_info *txr = &bp->tx_ring[i];
@@ -3415,7 +3457,7 @@
  */
 void bnxt_set_ring_params(struct bnxt *bp)
 {
-	u32 ring_size, rx_size, rx_space;
+	u32 ring_size, rx_size, rx_space, max_rx_cmpl;
 	u32 agg_factor = 0, agg_ring_size = 0;
 
 	/* 8 for CRC and VLAN */
@@ -3471,7 +3513,15 @@
 	bp->tx_nr_pages = bnxt_calc_nr_ring_pages(ring_size, TX_DESC_CNT);
 	bp->tx_ring_mask = (bp->tx_nr_pages * TX_DESC_CNT) - 1;
 
-	ring_size = bp->rx_ring_size * (2 + agg_factor) + bp->tx_ring_size;
+	max_rx_cmpl = bp->rx_ring_size;
+	/* MAX TPA needs to be added because TPA_START completions are
+	 * immediately recycled, so the TPA completions are not bound by
+	 * the RX ring size.
+	 */
+	if (bp->flags & BNXT_FLAG_TPA)
+		max_rx_cmpl += bp->max_tpa;
+	/* RX and TPA completions are 32-byte, all others are 16-byte */
+	ring_size = max_rx_cmpl * 2 + agg_ring_size + bp->tx_ring_size;
 	bp->cp_ring_size = ring_size;
 
 	bp->cp_nr_pages = bnxt_calc_nr_ring_pages(ring_size, CP_DESC_CNT);
@@ -4183,7 +4233,8 @@
 	u32 bar_offset = BNXT_GRCPF_REG_CHIMP_COMM;
 	u16 dst = BNXT_HWRM_CHNL_CHIMP;
 
-	if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state))
+	if (BNXT_NO_FW_ACCESS(bp) &&
+	    le16_to_cpu(req->req_type) != HWRM_FUNC_RESET)
 		return -EBUSY;
 
 	if (msg_len > BNXT_HWRM_MAX_REQ_LEN) {
@@ -4434,8 +4485,9 @@
 			    FUNC_DRV_RGTR_REQ_ENABLES_VER);
 
 	req.os_type = cpu_to_le16(FUNC_DRV_RGTR_REQ_OS_TYPE_LINUX);
-	flags = FUNC_DRV_RGTR_REQ_FLAGS_16BIT_VER_MODE |
-		FUNC_DRV_RGTR_REQ_FLAGS_HOT_RESET_SUPPORT;
+	flags = FUNC_DRV_RGTR_REQ_FLAGS_16BIT_VER_MODE;
+	if (bp->fw_cap & BNXT_FW_CAP_HOT_RESET)
+		flags |= FUNC_DRV_RGTR_REQ_FLAGS_HOT_RESET_SUPPORT;
 	if (bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY)
 		flags |= FUNC_DRV_RGTR_REQ_FLAGS_ERROR_RECOVERY_SUPPORT;
 	req.flags = cpu_to_le32(flags);
@@ -5517,7 +5569,7 @@
 	struct hwrm_ring_free_output *resp = bp->hwrm_cmd_resp_addr;
 	u16 error_code;
 
-	if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state))
+	if (BNXT_NO_FW_ACCESS(bp))
 		return 0;
 
 	bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_RING_FREE, cmpl_ring_id, -1);
@@ -6170,7 +6222,7 @@
 		tmr = bnxt_usec_to_coal_tmr(bp, hw_coal->coal_ticks_irq);
 		val = clamp_t(u16, tmr, 1,
 			      coal_cap->cmpl_aggr_dma_tmr_during_int_max);
-		req->cmpl_aggr_dma_tmr_during_int = cpu_to_le16(tmr);
+		req->cmpl_aggr_dma_tmr_during_int = cpu_to_le16(val);
 		req->enables |=
 			cpu_to_le16(BNXT_COAL_CMPL_AGGR_TMR_DURING_INT_ENABLE);
 	}
@@ -6640,7 +6692,7 @@
 	int rc;
 
 	if (!mem_size)
-		return 0;
+		return -EINVAL;
 
 	ctx_pg->nr_pages = DIV_ROUND_UP(mem_size, BNXT_PAGE_SIZE);
 	if (ctx_pg->nr_pages > MAX_CTX_TOTAL_PAGES) {
@@ -6854,12 +6906,12 @@
 	}
 	ena |= FUNC_BACKING_STORE_CFG_REQ_DFLT_ENABLES;
 	rc = bnxt_hwrm_func_backing_store_cfg(bp, ena);
-	if (rc)
+	if (rc) {
 		netdev_err(bp->dev, "Failed configuring context mem, rc = %d.\n",
 			   rc);
-	else
-		ctx->flags |= BNXT_CTX_FLAG_INITED;
-
+		return rc;
+	}
+	ctx->flags |= BNXT_CTX_FLAG_INITED;
 	return 0;
 }
 
@@ -6970,7 +7022,6 @@
 
 		pf->fw_fid = le16_to_cpu(resp->fid);
 		pf->port_id = le16_to_cpu(resp->port_id);
-		bp->dev->dev_port = pf->port_id;
 		memcpy(pf->mac_addr, resp->mac_address, ETH_ALEN);
 		pf->first_vf_id = le16_to_cpu(resp->first_vf_id);
 		pf->max_vfs = le16_to_cpu(resp->max_vfs);
@@ -7092,14 +7143,6 @@
 	rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
 	if (rc)
 		goto err_recovery_out;
-	if (!fw_health) {
-		fw_health = kzalloc(sizeof(*fw_health), GFP_KERNEL);
-		bp->fw_health = fw_health;
-		if (!fw_health) {
-			rc = -ENOMEM;
-			goto err_recovery_out;
-		}
-	}
 	fw_health->flags = le32_to_cpu(resp->flags);
 	if ((fw_health->flags & ERROR_RECOVERY_QCFG_RESP_FLAGS_CO_CPU) &&
 	    !(bp->fw_cap & BNXT_FW_CAP_KONG_MB_CHNL)) {
@@ -7386,14 +7429,22 @@
 		pri2cos = &resp2->pri0_cos_queue_id;
 		for (i = 0; i < 8; i++) {
 			u8 queue_id = pri2cos[i];
+			u8 queue_idx;
 
+			/* Per port queue IDs start from 0, 10, 20, etc */
+			queue_idx = queue_id % 10;
+			if (queue_idx > BNXT_MAX_QUEUE) {
+				bp->pri2cos_valid = false;
+				goto qstats_done;
+			}
 			for (j = 0; j < bp->max_q; j++) {
 				if (bp->q_ids[j] == queue_id)
-					bp->pri2cos[i] = j;
+					bp->pri2cos_idx[i] = queue_idx;
 			}
 		}
 		bp->pri2cos_valid = 1;
 	}
+qstats_done:
 	mutex_unlock(&bp->hwrm_cmd_lock);
 	return rc;
 }
@@ -7432,7 +7483,7 @@
 
 	if (set_tpa)
 		tpa_flags = bp->flags & BNXT_FLAG_TPA;
-	else if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state))
+	else if (BNXT_NO_FW_ACCESS(bp))
 		return 0;
 	for (i = 0; i < bp->nr_vnics; i++) {
 		rc = bnxt_hwrm_vnic_set_tpa(bp, i, tpa_flags);
@@ -7730,6 +7781,9 @@
 		goto err_out;
 	}
 
+	if (BNXT_VF(bp))
+		bnxt_hwrm_func_qcfg(bp);
+
 	rc = bnxt_setup_vnic(bp, 0);
 	if (rc)
 		goto err_out;
@@ -7873,7 +7927,7 @@
 	int tcs, i;
 
 	tcs = netdev_get_num_tc(dev);
-	if (tcs > 1) {
+	if (tcs) {
 		int i, off, count;
 
 		for (i = 0; i < tcs; i++) {
@@ -7912,10 +7966,18 @@
 	bp->irq_tbl[0].handler = bnxt_inta;
 }
 
+static int bnxt_init_int_mode(struct bnxt *bp);
+
 static int bnxt_setup_int_mode(struct bnxt *bp)
 {
 	int rc;
 
+	if (!bp->irq_tbl) {
+		rc = bnxt_init_int_mode(bp);
+		if (rc || !bp->irq_tbl)
+			return rc ?: -ENODEV;
+	}
+
 	if (bp->flags & BNXT_FLAG_USING_MSIX)
 		bnxt_setup_msix(bp);
 	else
@@ -8100,7 +8162,7 @@
 
 static int bnxt_init_int_mode(struct bnxt *bp)
 {
-	int rc = 0;
+	int rc = -ENODEV;
 
 	if (bp->flags & BNXT_FLAG_MSIX_CAP)
 		rc = bnxt_init_msix(bp);
@@ -8147,10 +8209,14 @@
 		netdev_err(bp->dev, "ring reservation/IRQ init failure rc: %d\n", rc);
 		return rc;
 	}
-	if (tcs && (bp->tx_nr_rings_per_tc * tcs != bp->tx_nr_rings)) {
+	if (tcs && (bp->tx_nr_rings_per_tc * tcs !=
+		    bp->tx_nr_rings - bp->tx_nr_rings_xdp)) {
 		netdev_err(bp->dev, "tx ring reservation failure\n");
 		netdev_reset_tc(bp->dev);
-		bp->tx_nr_rings_per_tc = bp->tx_nr_rings;
+		if (bp->tx_nr_rings_xdp)
+			bp->tx_nr_rings_per_tc = bp->tx_nr_rings_xdp;
+		else
+			bp->tx_nr_rings_per_tc = bp->tx_nr_rings;
 		return -ENOMEM;
 	}
 	return 0;
@@ -8300,10 +8366,9 @@
 	for (i = 0; i < bp->cp_nr_rings; i++) {
 		struct bnxt_cp_ring_info *cpr = &bp->bnapi[i]->cp_ring;
 
+		napi_disable(&bp->bnapi[i]->napi);
 		if (bp->bnapi[i]->rx_ring)
 			cancel_work_sync(&cpr->dim.work);
-
-		napi_disable(&bp->bnapi[i]->napi);
 	}
 }
 
@@ -8331,12 +8396,15 @@
 	if (bp->tx_ring) {
 		for (i = 0; i < bp->tx_nr_rings; i++) {
 			txr = &bp->tx_ring[i];
-			txr->dev_state = BNXT_DEV_STATE_CLOSING;
+			WRITE_ONCE(txr->dev_state, BNXT_DEV_STATE_CLOSING);
 		}
 	}
+	/* Make sure napi polls see @dev_state change */
+	synchronize_net();
+	/* Drop carrier first to prevent TX timeout */
+	netif_carrier_off(bp->dev);
 	/* Stop all TX queues */
 	netif_tx_disable(bp->dev);
-	netif_carrier_off(bp->dev);
 }
 
 void bnxt_tx_enable(struct bnxt *bp)
@@ -8346,8 +8414,10 @@
 
 	for (i = 0; i < bp->tx_nr_rings; i++) {
 		txr = &bp->tx_ring[i];
-		txr->dev_state = 0;
+		WRITE_ONCE(txr->dev_state, 0);
 	}
+	/* Make sure napi polls see @dev_state change */
+	synchronize_net();
 	netif_tx_wake_all_queues(bp->dev);
 	if (bp->link_info.link_up)
 		netif_carrier_on(bp->dev);
@@ -8362,6 +8432,11 @@
 		u16 fec;
 
 		netif_carrier_on(bp->dev);
+		speed = bnxt_fw_to_ethtool_speed(bp->link_info.link_speed);
+		if (speed == SPEED_UNKNOWN) {
+			netdev_info(bp->dev, "NIC Link is Up, speed unknown\n");
+			return;
+		}
 		if (bp->link_info.duplex == BNXT_LINK_DUPLEX_FULL)
 			duplex = "full";
 		else
@@ -8374,7 +8449,6 @@
 			flow_ctrl = "ON - receive";
 		else
 			flow_ctrl = "none";
-		speed = bnxt_fw_to_ethtool_speed(bp->link_info.link_speed);
 		netdev_info(bp->dev, "NIC Link is Up, %u Mbps %s duplex, Flow control: %s\n",
 			    speed, duplex, flow_ctrl);
 		if (bp->flags & BNXT_FLAG_EEE_CAP)
@@ -8730,7 +8804,8 @@
 {
 	struct hwrm_func_drv_if_change_output *resp = bp->hwrm_cmd_resp_addr;
 	struct hwrm_func_drv_if_change_input req = {0};
-	bool resc_reinit = false, fw_reset = false;
+	bool fw_reset = !bp->irq_tbl;
+	bool resc_reinit = false;
 	u32 flags = 0;
 	int rc;
 
@@ -8758,10 +8833,14 @@
 
 	if (test_bit(BNXT_STATE_IN_FW_RESET, &bp->state) && !fw_reset) {
 		netdev_err(bp->dev, "RESET_DONE not set during FW reset.\n");
+		set_bit(BNXT_STATE_ABORT_ERR, &bp->state);
 		return -ENODEV;
 	}
 	if (resc_reinit || fw_reset) {
 		if (fw_reset) {
+			bnxt_free_ctx_mem(bp);
+			kfree(bp->ctx);
+			bp->ctx = NULL;
 			rc = bnxt_fw_init_one(bp);
 			if (rc) {
 				set_bit(BNXT_STATE_ABORT_ERR, &bp->state);
@@ -8913,16 +8992,19 @@
 	struct hwrm_temp_monitor_query_input req = {0};
 	struct hwrm_temp_monitor_query_output *resp;
 	struct bnxt *bp = dev_get_drvdata(dev);
-	u32 temp = 0;
+	u32 len = 0;
+	int rc;
 
 	resp = bp->hwrm_cmd_resp_addr;
 	bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_TEMP_MONITOR_QUERY, -1, -1);
 	mutex_lock(&bp->hwrm_cmd_lock);
-	if (!_hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT))
-		temp = resp->temp * 1000; /* display millidegree */
+	rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+	if (!rc)
+		len = sprintf(buf, "%u\n", resp->temp * 1000); /* display millidegree */
 	mutex_unlock(&bp->hwrm_cmd_lock);
-
-	return sprintf(buf, "%u\n", temp);
+	if (rc)
+		return rc;
+	return len;
 }
 static SENSOR_DEVICE_ATTR(temp1_input, 0444, bnxt_show_temp, NULL, 0);
 
@@ -8942,7 +9024,16 @@
 
 static void bnxt_hwmon_open(struct bnxt *bp)
 {
+	struct hwrm_temp_monitor_query_input req = {0};
 	struct pci_dev *pdev = bp->pdev;
+	int rc;
+
+	bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_TEMP_MONITOR_QUERY, -1, -1);
+	rc = hwrm_send_message_silent(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+	if (rc == -EACCES || rc == -EOPNOTSUPP) {
+		bnxt_hwmon_close(bp);
+		return;
+	}
 
 	if (bp->hwmon_dev)
 		return;
@@ -9104,15 +9195,15 @@
 		}
 	}
 
-	bnxt_enable_napi(bp);
-	bnxt_debug_dev_init(bp);
-
 	rc = bnxt_init_nic(bp, irq_re_init);
 	if (rc) {
 		netdev_err(bp->dev, "bnxt_init_nic err: %x\n", rc);
-		goto open_err;
+		goto open_err_irq;
 	}
 
+	bnxt_enable_napi(bp);
+	bnxt_debug_dev_init(bp);
+
 	if (link_re_init) {
 		mutex_lock(&bp->link_lock);
 		rc = bnxt_update_phy_setting(bp);
@@ -9143,10 +9234,6 @@
 		bnxt_vf_reps_open(bp);
 	return 0;
 
-open_err:
-	bnxt_debug_dev_exit(bp);
-	bnxt_disable_napi(bp);
-
 open_err_irq:
 	bnxt_del_napi(bp);
 
@@ -9162,7 +9249,10 @@
 {
 	int rc = 0;
 
-	rc = __bnxt_open_nic(bp, irq_re_init, link_re_init);
+	if (test_bit(BNXT_STATE_ABORT_ERR, &bp->state))
+		rc = -EIO;
+	if (!rc)
+		rc = __bnxt_open_nic(bp, irq_re_init, link_re_init);
 	if (rc) {
 		netdev_err(bp->dev, "nic open fail (rc: %x)\n", rc);
 		dev_close(bp->dev);
@@ -9178,6 +9268,12 @@
 {
 	int rc = 0;
 
+	if (test_bit(BNXT_STATE_ABORT_ERR, &bp->state)) {
+		netdev_err(bp->dev, "A previous firmware reset has not completed, aborting half open\n");
+		rc = -ENODEV;
+		goto half_open_err;
+	}
+
 	rc = bnxt_alloc_mem(bp, false);
 	if (rc) {
 		netdev_err(bp->dev, "bnxt_alloc_mem err: %x\n", rc);
@@ -9270,14 +9366,10 @@
 	bnxt_debug_dev_exit(bp);
 	bnxt_disable_napi(bp);
 	del_timer_sync(&bp->timer);
-	if (test_bit(BNXT_STATE_IN_FW_RESET, &bp->state) &&
-	    pci_is_enabled(bp->pdev))
-		pci_disable_device(bp->pdev);
-
 	bnxt_free_skbs(bp);
 
 	/* Save ring stats before shutdown */
-	if (bp->bnapi)
+	if (bp->bnapi && irq_re_init)
 		bnxt_get_ring_stats(bp, &bp->net_stats_prev);
 	if (irq_re_init) {
 		bnxt_free_irq(bp);
@@ -9707,7 +9799,7 @@
 
 	if (bp->flags & BNXT_FLAG_CHIP_P5)
 		return bnxt_rfs_supported(bp);
-	if (!(bp->flags & BNXT_FLAG_MSIX_CAP) || !bnxt_can_reserve_rings(bp))
+	if (!(bp->flags & BNXT_FLAG_MSIX_CAP) || !bnxt_can_reserve_rings(bp) || !bp->rx_nr_rings)
 		return false;
 
 	vnics = 1 + bp->rx_nr_rings;
@@ -9747,6 +9839,7 @@
 					   netdev_features_t features)
 {
 	struct bnxt *bp = netdev_priv(dev);
+	netdev_features_t vlan_features;
 
 	if ((features & NETIF_F_NTUPLE) && !bnxt_rfs_capable(bp))
 		features &= ~NETIF_F_NTUPLE;
@@ -9763,12 +9856,14 @@
 	/* Both CTAG and STAG VLAN accelaration on the RX side have to be
 	 * turned on or off together.
 	 */
-	if ((features & (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX)) !=
-	    (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX)) {
+	vlan_features = features & (NETIF_F_HW_VLAN_CTAG_RX |
+				    NETIF_F_HW_VLAN_STAG_RX);
+	if (vlan_features != (NETIF_F_HW_VLAN_CTAG_RX |
+			      NETIF_F_HW_VLAN_STAG_RX)) {
 		if (dev->features & NETIF_F_HW_VLAN_CTAG_RX)
 			features &= ~(NETIF_F_HW_VLAN_CTAG_RX |
 				      NETIF_F_HW_VLAN_STAG_RX);
-		else
+		else if (vlan_features)
 			features |= NETIF_F_HW_VLAN_CTAG_RX |
 				    NETIF_F_HW_VLAN_STAG_RX;
 	}
@@ -9927,12 +10022,15 @@
 	if (netif_running(bp->dev)) {
 		int rc;
 
-		if (!silent)
+		if (silent) {
+			bnxt_close_nic(bp, false, false);
+			bnxt_open_nic(bp, false, false);
+		} else {
 			bnxt_ulp_stop(bp);
-		bnxt_close_nic(bp, false, false);
-		rc = bnxt_open_nic(bp, false, false);
-		if (!silent && !rc)
-			bnxt_ulp_start(bp);
+			bnxt_close_nic(bp, true, false);
+			rc = bnxt_open_nic(bp, true, false);
+			bnxt_ulp_start(bp, rc);
+		}
 	}
 }
 
@@ -9950,8 +10048,7 @@
 	struct bnxt_fw_health *fw_health = bp->fw_health;
 	u32 val;
 
-	if (!fw_health || !fw_health->enabled ||
-	    test_bit(BNXT_STATE_IN_FW_RESET, &bp->state))
+	if (!fw_health->enabled || test_bit(BNXT_STATE_IN_FW_RESET, &bp->state))
 		return;
 
 	if (fw_health->tmr_counter) {
@@ -9982,7 +10079,7 @@
 	struct bnxt *bp = from_timer(bp, t, timer);
 	struct net_device *dev = bp->dev;
 
-	if (!netif_running(dev))
+	if (!netif_running(dev) || !test_bit(BNXT_STATE_OPEN, &bp->state))
 		return;
 
 	if (atomic_read(&bp->intr_sem) != 0)
@@ -10050,8 +10147,15 @@
 {
 	__bnxt_close_nic(bp, true, false);
 	bnxt_ulp_irq_stop(bp);
+	/* When firmware is fatal state, disable PCI device to prevent
+	 * any potential bad DMAs before freeing kernel memory.
+	 */
+	if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state))
+		pci_disable_device(bp->pdev);
 	bnxt_clear_int_mode(bp);
 	bnxt_hwrm_func_drv_unrgtr(bp);
+	if (pci_is_enabled(bp->pdev))
+		pci_disable_device(bp->pdev);
 	bnxt_free_ctx_mem(bp);
 	kfree(bp->ctx);
 	bp->ctx = NULL;
@@ -10236,6 +10340,8 @@
 		bnxt_cfg_ntp_filters(bp);
 	if (test_and_clear_bit(BNXT_HWRM_EXEC_FWD_REQ_SP_EVENT, &bp->sp_event))
 		bnxt_hwrm_exec_fwd_req(bp);
+	if (test_and_clear_bit(BNXT_HWRM_PF_UNLOAD_SP_EVENT, &bp->sp_event))
+		netdev_info(bp->dev, "Receive PF driver unload event!\n");
 	if (test_and_clear_bit(BNXT_VXLAN_ADD_PORT_SP_EVENT, &bp->sp_event)) {
 		bnxt_hwrm_tunnel_dst_port_alloc(
 			bp, bp->vxlan_port,
@@ -10412,6 +10518,23 @@
 	bp->stats_coal_ticks = BNXT_DEF_STATS_COAL_TICKS;
 }
 
+static void bnxt_alloc_fw_health(struct bnxt *bp)
+{
+	if (bp->fw_health)
+		return;
+
+	if (!(bp->fw_cap & BNXT_FW_CAP_HOT_RESET) &&
+	    !(bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY))
+		return;
+
+	bp->fw_health = kzalloc(sizeof(*bp->fw_health), GFP_KERNEL);
+	if (!bp->fw_health) {
+		netdev_warn(bp->dev, "Failed to allocate fw_health\n");
+		bp->fw_cap &= ~BNXT_FW_CAP_HOT_RESET;
+		bp->fw_cap &= ~BNXT_FW_CAP_ERROR_RECOVERY;
+	}
+}
+
 static int bnxt_fw_init_one_p1(struct bnxt *bp)
 {
 	int rc;
@@ -10458,6 +10581,7 @@
 		netdev_warn(bp->dev, "hwrm query adv flow mgnt failure rc: %d\n",
 			    rc);
 
+	bnxt_alloc_fw_health(bp);
 	rc = bnxt_hwrm_error_recovery_qcfg(bp);
 	if (rc)
 		netdev_warn(bp->dev, "hwrm query error recovery failure rc: %d\n",
@@ -10526,6 +10650,8 @@
 	bnxt_hwrm_coal_params_qcaps(bp);
 }
 
+static int bnxt_probe_phy(struct bnxt *bp, bool fw_dflt);
+
 static int bnxt_fw_init_one(struct bnxt *bp)
 {
 	int rc;
@@ -10540,9 +10666,18 @@
 		netdev_err(bp->dev, "Firmware init phase 2 failed\n");
 		return rc;
 	}
+	rc = bnxt_probe_phy(bp, false);
+	if (rc)
+		return rc;
 	rc = bnxt_approve_mac(bp, bp->dev->dev_addr, false);
 	if (rc)
 		return rc;
+
+	/* In case fw capabilities have changed, destroy the unneeded
+	 * reporters and create newly capable ones.
+	 */
+	bnxt_dl_fw_reporters_destroy(bp, false);
+	bnxt_dl_fw_reporters_create(bp);
 	bnxt_fw_init_one_p3(bp);
 	return 0;
 }
@@ -10637,6 +10772,10 @@
 		}
 		bp->fw_reset_timestamp = jiffies;
 		rtnl_lock();
+		if (test_bit(BNXT_STATE_ABORT_ERR, &bp->state)) {
+			rtnl_unlock();
+			goto fw_reset_abort;
+		}
 		bnxt_fw_reset_close(bp);
 		if (bp->fw_cap & BNXT_FW_CAP_ERR_RECOVER_RELOAD) {
 			bp->fw_reset_state = BNXT_FW_RESET_STATE_POLL_FW_DOWN;
@@ -10676,8 +10815,7 @@
 		bnxt_queue_fw_reset_work(bp, bp->fw_reset_min_dsecs * HZ / 10);
 		return;
 	case BNXT_FW_RESET_STATE_ENABLE_DEV:
-		if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state) &&
-		    bp->fw_health) {
+		if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state)) {
 			u32 val;
 
 			val = bnxt_fw_health_readl(bp,
@@ -10769,7 +10907,8 @@
 	if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)) != 0 &&
 	    dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)) != 0) {
 		dev_err(&pdev->dev, "System does not support DMA, aborting\n");
-		goto init_err_disable;
+		rc = -EIO;
+		goto init_err_release;
 	}
 
 	pci_set_master(pdev);
@@ -10862,13 +11001,13 @@
 	struct bnxt *bp = netdev_priv(dev);
 
 	if (netif_running(dev))
-		bnxt_close_nic(bp, false, false);
+		bnxt_close_nic(bp, true, false);
 
 	dev->mtu = new_mtu;
 	bnxt_set_ring_params(bp);
 
 	if (netif_running(dev))
-		return bnxt_open_nic(bp, false, false);
+		return bnxt_open_nic(bp, true, false);
 
 	return 0;
 }
@@ -10966,11 +11105,23 @@
 	struct flow_keys *keys1 = &f1->fkeys;
 	struct flow_keys *keys2 = &f2->fkeys;
 
-	if (keys1->addrs.v4addrs.src == keys2->addrs.v4addrs.src &&
-	    keys1->addrs.v4addrs.dst == keys2->addrs.v4addrs.dst &&
-	    keys1->ports.ports == keys2->ports.ports &&
-	    keys1->basic.ip_proto == keys2->basic.ip_proto &&
-	    keys1->basic.n_proto == keys2->basic.n_proto &&
+	if (keys1->basic.n_proto != keys2->basic.n_proto ||
+	    keys1->basic.ip_proto != keys2->basic.ip_proto)
+		return false;
+
+	if (keys1->basic.n_proto == htons(ETH_P_IP)) {
+		if (keys1->addrs.v4addrs.src != keys2->addrs.v4addrs.src ||
+		    keys1->addrs.v4addrs.dst != keys2->addrs.v4addrs.dst)
+			return false;
+	} else {
+		if (memcmp(&keys1->addrs.v6addrs.src, &keys2->addrs.v6addrs.src,
+			   sizeof(keys1->addrs.v6addrs.src)) ||
+		    memcmp(&keys1->addrs.v6addrs.dst, &keys2->addrs.v6addrs.dst,
+			   sizeof(keys1->addrs.v6addrs.dst)))
+			return false;
+	}
+
+	if (keys1->ports.ports == keys2->ports.ports &&
 	    keys1->control.flags == keys2->control.flags &&
 	    ether_addr_equal(f1->src_mac_addr, f2->src_mac_addr) &&
 	    ether_addr_equal(f1->dst_mac_addr, f2->dst_mac_addr))
@@ -11041,8 +11192,8 @@
 	rcu_read_lock();
 	hlist_for_each_entry_rcu(fltr, head, hash) {
 		if (bnxt_fltr_match(fltr, new_fltr)) {
+			rc = fltr->sw_id;
 			rcu_read_unlock();
-			rc = 0;
 			goto err_free;
 		}
 	}
@@ -11117,8 +11268,6 @@
 			}
 		}
 	}
-	if (test_and_clear_bit(BNXT_HWRM_PF_UNLOAD_SP_EVENT, &bp->sp_event))
-		netdev_info(bp->dev, "Receive PF driver unload event!");
 }
 
 #else
@@ -11262,7 +11411,7 @@
 		return -EOPNOTSUPP;
 
 	/* The PF and it's VF-reps only support the switchdev framework */
-	if (!BNXT_PF(bp))
+	if (!BNXT_PF(bp) || !(bp->flags & BNXT_FLAG_DSN_VALID))
 		return -EOPNOTSUPP;
 
 	ppid->id_len = sizeof(bp->switch_id);
@@ -11318,17 +11467,21 @@
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct bnxt *bp = netdev_priv(dev);
 
-	if (BNXT_PF(bp)) {
+	if (BNXT_PF(bp))
 		bnxt_sriov_disable(bp);
-		bnxt_dl_unregister(bp);
-	}
 
 	pci_disable_pcie_error_reporting(pdev);
 	unregister_netdev(dev);
-	bnxt_shutdown_tc(bp);
-	bnxt_cancel_sp_work(bp);
+	clear_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
+	/* Flush any pending tasks */
+	cancel_work_sync(&bp->sp_task);
+	cancel_delayed_work_sync(&bp->fw_reset_task);
 	bp->sp_event = 0;
 
+	bnxt_dl_fw_reporters_destroy(bp, true);
+	bnxt_dl_unregister(bp);
+	bnxt_shutdown_tc(bp);
+
 	bnxt_clear_int_mode(bp);
 	bnxt_hwrm_func_drv_unrgtr(bp);
 	bnxt_free_hwrm_resources(bp);
@@ -11337,6 +11490,8 @@
 	bnxt_dcb_free(bp);
 	kfree(bp->edev);
 	bp->edev = NULL;
+	kfree(bp->fw_health);
+	bp->fw_health = NULL;
 	bnxt_cleanup_pci(bp);
 	bnxt_free_ctx_mem(bp);
 	kfree(bp->ctx);
@@ -11552,6 +11707,10 @@
 		bp->rx_nr_rings++;
 		bp->cp_nr_rings++;
 	}
+	if (rc) {
+		bp->tx_nr_rings = 0;
+		bp->rx_nr_rings = 0;
+	}
 	return rc;
 }
 
@@ -11574,10 +11733,9 @@
 		goto init_dflt_ring_err;
 
 	bp->tx_nr_rings_per_tc = bp->tx_nr_rings;
-	if (bnxt_rfs_supported(bp) && bnxt_rfs_capable(bp)) {
-		bp->flags |= BNXT_FLAG_RFS;
-		bp->dev->features |= NETIF_F_NTUPLE;
-	}
+
+	bnxt_set_dflt_rfs(bp);
+
 init_dflt_ring_err:
 	bnxt_ulp_irq_restart(bp, rc);
 	return rc;
@@ -11652,6 +11810,7 @@
 	put_unaligned_le32(dw, &dsn[0]);
 	pci_read_config_dword(pdev, pos + 4, &dw);
 	put_unaligned_le32(dw, &dsn[4]);
+	bp->flags |= BNXT_FLAG_DSN_VALID;
 	return 0;
 }
 
@@ -11668,6 +11827,14 @@
 	if (version_printed++ == 0)
 		pr_info("%s", version);
 
+	/* Clear any pending DMA transactions from crash kernel
+	 * while loading driver in capture kernel.
+	 */
+	if (is_kdump_kernel()) {
+		pci_clear_master(pdev);
+		pcie_flr(pdev);
+	}
+
 	max_irqs = bnxt_get_max_irq(pdev);
 	dev = alloc_etherdev_mq(sizeof(*bp), max_irqs);
 	if (!dev)
@@ -11763,9 +11930,7 @@
 
 	if (BNXT_PF(bp)) {
 		/* Read the adapter's DSN to use as the eswitch switch_id */
-		rc = bnxt_pcie_dsn_get(bp, bp->switch_id);
-		if (rc)
-			goto init_err_pci_clean;
+		bnxt_pcie_dsn_get(bp, bp->switch_id);
 	}
 
 	/* MTU range: 60 - FW defined max */
@@ -11806,39 +11971,46 @@
 				create_singlethread_workqueue("bnxt_pf_wq");
 			if (!bnxt_pf_wq) {
 				dev_err(&pdev->dev, "Unable to create workqueue.\n");
+				rc = -ENOMEM;
 				goto init_err_pci_clean;
 			}
 		}
 		bnxt_init_tc(bp);
 	}
 
+	bnxt_dl_register(bp);
+
 	rc = register_netdev(dev);
 	if (rc)
-		goto init_err_cleanup_tc;
+		goto init_err_cleanup;
 
 	if (BNXT_PF(bp))
-		bnxt_dl_register(bp);
+		devlink_port_type_eth_set(&bp->dl_port, bp->dev);
+	bnxt_dl_fw_reporters_create(bp);
 
 	netdev_info(dev, "%s found at mem %lx, node addr %pM\n",
 		    board_info[ent->driver_data].name,
 		    (long)pci_resource_start(pdev, 0), dev->dev_addr);
 	pcie_print_link_status(pdev);
 
+	pci_save_state(pdev);
 	return 0;
 
-init_err_cleanup_tc:
+init_err_cleanup:
+	bnxt_dl_unregister(bp);
 	bnxt_shutdown_tc(bp);
 	bnxt_clear_int_mode(bp);
 
 init_err_pci_clean:
 	bnxt_free_hwrm_short_cmd_req(bp);
 	bnxt_free_hwrm_resources(bp);
-	bnxt_free_ctx_mem(bp);
-	kfree(bp->ctx);
-	bp->ctx = NULL;
+	bnxt_ethtool_free(bp);
 	kfree(bp->fw_health);
 	bp->fw_health = NULL;
 	bnxt_cleanup_pci(bp);
+	bnxt_free_ctx_mem(bp);
+	kfree(bp->ctx);
+	bp->ctx = NULL;
 
 init_err_free:
 	free_netdev(dev);
@@ -11862,10 +12034,10 @@
 		dev_close(dev);
 
 	bnxt_ulp_shutdown(bp);
+	bnxt_clear_int_mode(bp);
+	pci_disable_device(pdev);
 
 	if (system_state == SYSTEM_POWER_OFF) {
-		bnxt_clear_int_mode(bp);
-		pci_disable_device(pdev);
 		pci_wake_from_d3(pdev, bp->wol);
 		pci_set_power_state(pdev, PCI_D3hot);
 	}
@@ -11954,6 +12126,9 @@
 		return PCI_ERS_RESULT_DISCONNECT;
 	}
 
+	if (state == pci_channel_io_frozen)
+		set_bit(BNXT_STATE_PCI_CHANNEL_IO_FROZEN, &bp->state);
+
 	if (netif_running(netdev))
 		bnxt_close(netdev);
 
@@ -11977,7 +12152,7 @@
 {
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct bnxt *bp = netdev_priv(netdev);
-	int err = 0;
+	int err = 0, off;
 	pci_ers_result_t result = PCI_ERS_RESULT_DISCONNECT;
 
 	netdev_info(bp->dev, "PCI Slot Reset\n");
@@ -11989,23 +12164,41 @@
 			"Cannot re-enable PCI device after reset.\n");
 	} else {
 		pci_set_master(pdev);
+		/* Upon fatal error, our device internal logic that latches to
+		 * BAR value is getting reset and will restore only upon
+		 * rewritting the BARs.
+		 *
+		 * As pci_restore_state() does not re-write the BARs if the
+		 * value is same as saved value earlier, driver needs to
+		 * write the BARs to 0 to force restore, in case of fatal error.
+		 */
+		if (test_and_clear_bit(BNXT_STATE_PCI_CHANNEL_IO_FROZEN,
+				       &bp->state)) {
+			for (off = PCI_BASE_ADDRESS_0;
+			     off <= PCI_BASE_ADDRESS_5; off += 4)
+				pci_write_config_dword(bp->pdev, off, 0);
+		}
+		pci_restore_state(pdev);
+		pci_save_state(pdev);
 
 		err = bnxt_hwrm_func_reset(bp);
 		if (!err && netif_running(netdev))
 			err = bnxt_open(netdev);
 
-		if (!err) {
+		if (!err)
 			result = PCI_ERS_RESULT_RECOVERED;
-			bnxt_ulp_start(bp);
-		}
+		bnxt_ulp_start(bp, err);
 	}
 
-	if (result != PCI_ERS_RESULT_RECOVERED && netif_running(netdev))
-		dev_close(netdev);
+	if (result != PCI_ERS_RESULT_RECOVERED) {
+		if (netif_running(netdev))
+			dev_close(netdev);
+		pci_disable_device(pdev);
+	}
 
 	rtnl_unlock();
 
-	return PCI_ERS_RESULT_RECOVERED;
+	return result;
 }
 
 /**
@@ -12047,8 +12240,16 @@
 
 static int __init bnxt_init(void)
 {
+	int err;
+
 	bnxt_debug_init();
-	return pci_register_driver(&bnxt_pci_driver);
+	err = pci_register_driver(&bnxt_pci_driver);
+	if (err) {
+		bnxt_debug_exit();
+		return err;
+	}
+
+	return 0;
 }
 
 static void __exit bnxt_exit(void)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/broadcom/bnxt/bnxt.h
@@ -559,7 +559,8 @@
 #define BNXT_MAX_MTU		9500
 #define BNXT_MAX_PAGE_MODE_MTU	\
 	((unsigned int)PAGE_SIZE - VLAN_ETH_HLEN - NET_IP_ALIGN -	\
-	 XDP_PACKET_HEADROOM)
+	 XDP_PACKET_HEADROOM - \
+	 SKB_DATA_ALIGN((unsigned int)sizeof(struct skb_shared_info)))
 
 #define BNXT_MIN_PKT_SIZE	52
 
@@ -601,6 +602,11 @@
 #define BNXT_MAX_RX_JUM_DESC_CNT	(RX_DESC_CNT * MAX_RX_AGG_PAGES - 1)
 #define BNXT_MAX_TX_DESC_CNT		(TX_DESC_CNT * MAX_TX_PAGES - 1)
 
+/* Minimum TX BDs for a TX packet with MAX_SKB_FRAGS + 1.  We need one extra
+ * BD because the first TX BD is always a long BD.
+ */
+#define BNXT_MIN_TX_DESC_CNT		(MAX_SKB_FRAGS + 2)
+
 #define RX_RING(x)	(((x) & ~(RX_DESC_CNT - 1)) >> (BNXT_PAGE_SHIFT - 4))
 #define RX_IDX(x)	((x) & (RX_DESC_CNT - 1))
 
@@ -927,6 +933,7 @@
 	dma_addr_t		hw_stats_map;
 	u32			hw_stats_ctx_id;
 	u64			rx_l4_csum_errors;
+	u64			rx_buf_errors;
 	u64			missed_irqs;
 
 	struct bnxt_ring_struct	cp_ring_struct;
@@ -1057,7 +1064,6 @@
 #define BNXT_VF_LINK_FORCED	0x4
 #define BNXT_VF_LINK_UP		0x8
 #define BNXT_VF_TRUST		0x10
-	u32	func_flags; /* func cfg flags */
 	u32	min_tx_rate;
 	u32	max_tx_rate;
 	void	*hwrm_cmd_req_addr;
@@ -1509,6 +1515,7 @@
 	#define BNXT_FLAG_NO_AGG_RINGS	0x20000
 	#define BNXT_FLAG_RX_PAGE_MODE	0x40000
 	#define BNXT_FLAG_MULTI_HOST	0x100000
+	#define BNXT_FLAG_DSN_VALID	0x200000
 	#define BNXT_FLAG_DOUBLE_DB	0x400000
 	#define BNXT_FLAG_CHIP_NITRO_A0	0x1000000
 	#define BNXT_FLAG_DIM		0x2000000
@@ -1626,6 +1633,11 @@
 #define BNXT_STATE_IN_FW_RESET	4
 #define BNXT_STATE_ABORT_ERR	5
 #define BNXT_STATE_FW_FATAL_COND	6
+#define BNXT_STATE_PCI_CHANNEL_IO_FROZEN	8
+
+#define BNXT_NO_FW_ACCESS(bp)					\
+	(test_bit(BNXT_STATE_FW_FATAL_COND, &(bp)->state) ||	\
+	 pci_channel_offline((bp)->pdev))
 
 	struct bnxt_irq	*irq_tbl;
 	int			total_irqs;
@@ -1657,6 +1669,7 @@
 	#define BNXT_FW_CAP_PCIE_STATS_SUPPORTED	0x00020000
 	#define BNXT_FW_CAP_EXT_STATS_SUPPORTED		0x00040000
 	#define BNXT_FW_CAP_ERR_RECOVER_RELOAD		0x00100000
+	#define BNXT_FW_CAP_HOT_RESET			0x00200000
 
 #define BNXT_NEW_RM(bp)		((bp)->fw_cap & BNXT_FW_CAP_NEW_RM)
 	u32			hwrm_spec_code;
@@ -1685,7 +1698,7 @@
 	u16			fw_rx_stats_ext_size;
 	u16			fw_tx_stats_ext_size;
 	u16			hw_ring_stats_size;
-	u8			pri2cos[8];
+	u8			pri2cos_idx[8];
 	u8			pri2cos_valid;
 
 	u16			hwrm_max_req_len;
@@ -1902,9 +1915,6 @@
 	case HWRM_CFA_ENCAP_RECORD_FREE:
 	case HWRM_CFA_DECAP_FILTER_ALLOC:
 	case HWRM_CFA_DECAP_FILTER_FREE:
-	case HWRM_CFA_NTUPLE_FILTER_ALLOC:
-	case HWRM_CFA_NTUPLE_FILTER_FREE:
-	case HWRM_CFA_NTUPLE_FILTER_CFG:
 	case HWRM_CFA_EM_FLOW_ALLOC:
 	case HWRM_CFA_EM_FLOW_FREE:
 	case HWRM_CFA_EM_FLOW_CFG:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c
@@ -479,24 +479,26 @@
 {
 	struct bnxt *bp = netdev_priv(dev);
 	struct ieee_ets *my_ets = bp->ieee_ets;
+	int rc;
 
 	ets->ets_cap = bp->max_tc;
 
 	if (!my_ets) {
-		int rc;
-
 		if (bp->dcbx_cap & DCB_CAP_DCBX_HOST)
 			return 0;
 
 		my_ets = kzalloc(sizeof(*my_ets), GFP_KERNEL);
 		if (!my_ets)
-			return 0;
+			return -ENOMEM;
 		rc = bnxt_hwrm_queue_cos2bw_qcfg(bp, my_ets);
 		if (rc)
-			return 0;
+			goto error;
 		rc = bnxt_hwrm_queue_pri2cos_qcfg(bp, my_ets);
 		if (rc)
-			return 0;
+			goto error;
+
+		/* cache result */
+		bp->ieee_ets = my_ets;
 	}
 
 	ets->cbs = my_ets->cbs;
@@ -505,6 +507,9 @@
 	memcpy(ets->tc_tsa, my_ets->tc_tsa, sizeof(ets->tc_tsa));
 	memcpy(ets->prio_tc, my_ets->prio_tc, sizeof(ets->prio_tc));
 	return 0;
+error:
+	kfree(my_ets);
+	return rc;
 }
 
 static int bnxt_dcbnl_ieee_setets(struct net_device *dev, struct ieee_ets *ets)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
@@ -19,11 +19,10 @@
 				     struct devlink_fmsg *fmsg)
 {
 	struct bnxt *bp = devlink_health_reporter_priv(reporter);
-	struct bnxt_fw_health *health = bp->fw_health;
 	u32 val, health_status;
 	int rc;
 
-	if (!health || test_bit(BNXT_STATE_IN_FW_RESET, &bp->state))
+	if (test_bit(BNXT_STATE_IN_FW_RESET, &bp->state))
 		return 0;
 
 	val = bnxt_fw_health_readl(bp, BNXT_FW_HEALTH_REG);
@@ -103,21 +102,15 @@
 	.recover = bnxt_fw_fatal_recover,
 };
 
-static void bnxt_dl_fw_reporters_create(struct bnxt *bp)
+void bnxt_dl_fw_reporters_create(struct bnxt *bp)
 {
 	struct bnxt_fw_health *health = bp->fw_health;
 
-	if (!health)
+	if (!bp->dl || !health)
 		return;
 
-	health->fw_reporter =
-		devlink_health_reporter_create(bp->dl, &bnxt_dl_fw_reporter_ops,
-					       0, false, bp);
-	if (IS_ERR(health->fw_reporter)) {
-		netdev_warn(bp->dev, "Failed to create FW health reporter, rc = %ld\n",
-			    PTR_ERR(health->fw_reporter));
-		health->fw_reporter = NULL;
-	}
+	if (!(bp->fw_cap & BNXT_FW_CAP_HOT_RESET) || health->fw_reset_reporter)
+		goto err_recovery;
 
 	health->fw_reset_reporter =
 		devlink_health_reporter_create(bp->dl,
@@ -127,8 +120,30 @@
 		netdev_warn(bp->dev, "Failed to create FW fatal health reporter, rc = %ld\n",
 			    PTR_ERR(health->fw_reset_reporter));
 		health->fw_reset_reporter = NULL;
+		bp->fw_cap &= ~BNXT_FW_CAP_HOT_RESET;
+	}
+
+err_recovery:
+	if (!(bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY))
+		return;
+
+	if (!health->fw_reporter) {
+		health->fw_reporter =
+			devlink_health_reporter_create(bp->dl,
+						       &bnxt_dl_fw_reporter_ops,
+						       0, false, bp);
+		if (IS_ERR(health->fw_reporter)) {
+			netdev_warn(bp->dev, "Failed to create FW health reporter, rc = %ld\n",
+				    PTR_ERR(health->fw_reporter));
+			health->fw_reporter = NULL;
+			bp->fw_cap &= ~BNXT_FW_CAP_ERROR_RECOVERY;
+			return;
+		}
 	}
 
+	if (health->fw_fatal_reporter)
+		return;
+
 	health->fw_fatal_reporter =
 		devlink_health_reporter_create(bp->dl,
 					       &bnxt_dl_fw_fatal_reporter_ops,
@@ -137,24 +152,35 @@
 		netdev_warn(bp->dev, "Failed to create FW fatal health reporter, rc = %ld\n",
 			    PTR_ERR(health->fw_fatal_reporter));
 		health->fw_fatal_reporter = NULL;
+		bp->fw_cap &= ~BNXT_FW_CAP_ERROR_RECOVERY;
 	}
 }
 
-static void bnxt_dl_fw_reporters_destroy(struct bnxt *bp)
+void bnxt_dl_fw_reporters_destroy(struct bnxt *bp, bool all)
 {
 	struct bnxt_fw_health *health = bp->fw_health;
 
-	if (!health)
+	if (!bp->dl || !health)
 		return;
 
-	if (health->fw_reporter)
-		devlink_health_reporter_destroy(health->fw_reporter);
-
-	if (health->fw_reset_reporter)
+	if ((all || !(bp->fw_cap & BNXT_FW_CAP_HOT_RESET)) &&
+	    health->fw_reset_reporter) {
 		devlink_health_reporter_destroy(health->fw_reset_reporter);
+		health->fw_reset_reporter = NULL;
+	}
 
-	if (health->fw_fatal_reporter)
+	if ((bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY) && !all)
+		return;
+
+	if (health->fw_reporter) {
+		devlink_health_reporter_destroy(health->fw_reporter);
+		health->fw_reporter = NULL;
+	}
+
+	if (health->fw_fatal_reporter) {
 		devlink_health_reporter_destroy(health->fw_fatal_reporter);
+		health->fw_fatal_reporter = NULL;
+	}
 }
 
 void bnxt_devlink_health_report(struct bnxt *bp, unsigned long event)
@@ -162,9 +188,6 @@
 	struct bnxt_fw_health *fw_health = bp->fw_health;
 	struct bnxt_fw_reporter_ctx fw_reporter_ctx;
 
-	if (!fw_health)
-		return;
-
 	fw_reporter_ctx.sp_event = event;
 	switch (event) {
 	case BNXT_FW_RESET_NOTIFY_SP_EVENT:
@@ -203,6 +226,8 @@
 #endif /* CONFIG_BNXT_SRIOV */
 };
 
+static const struct devlink_ops bnxt_vf_dl_ops;
+
 enum bnxt_dl_param_id {
 	BNXT_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX,
 	BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK,
@@ -311,10 +336,17 @@
 	} else {
 		rc = hwrm_send_message_silent(bp, msg, msg_len,
 					      HWRM_CMD_TIMEOUT);
-		if (!rc)
+		if (!rc) {
 			bnxt_copy_from_nvm_data(val, data,
 						nvm_param.nvm_num_bits,
 						nvm_param.dl_num_bytes);
+		} else {
+			struct hwrm_err_output *resp = bp->hwrm_cmd_resp_addr;
+
+			if (resp->cmd_err ==
+				NVM_GET_VARIABLE_CMD_ERR_CODE_VAR_NOT_EXIST)
+				rc = -EOPNOTSUPP;
+		}
 	}
 	dma_free_coherent(&bp->pdev->dev, sizeof(*data), data, data_dma_addr);
 	if (rc == -EACCES)
@@ -409,7 +441,10 @@
 		return -ENOTSUPP;
 	}
 
-	dl = devlink_alloc(&bnxt_dl_ops, sizeof(struct bnxt_dl));
+	if (BNXT_PF(bp))
+		dl = devlink_alloc(&bnxt_dl_ops, sizeof(struct bnxt_dl));
+	else
+		dl = devlink_alloc(&bnxt_vf_dl_ops, sizeof(struct bnxt_dl));
 	if (!dl) {
 		netdev_warn(bp->dev, "devlink_alloc failed");
 		return -ENOMEM;
@@ -428,6 +463,9 @@
 		goto err_dl_free;
 	}
 
+	if (!BNXT_PF(bp))
+		return 0;
+
 	rc = devlink_params_register(dl, bnxt_dl_params,
 				     ARRAY_SIZE(bnxt_dl_params));
 	if (rc) {
@@ -444,7 +482,6 @@
 		netdev_err(bp->dev, "devlink_port_register failed");
 		goto err_dl_param_unreg;
 	}
-	devlink_port_type_eth_set(&bp->dl_port, bp->dev);
 
 	rc = devlink_port_params_register(&bp->dl_port, bnxt_dl_port_params,
 					  ARRAY_SIZE(bnxt_dl_port_params));
@@ -455,8 +492,6 @@
 
 	devlink_params_publish(dl);
 
-	bnxt_dl_fw_reporters_create(bp);
-
 	return 0;
 
 err_dl_port_unreg:
@@ -479,12 +514,14 @@
 	if (!dl)
 		return;
 
-	bnxt_dl_fw_reporters_destroy(bp);
-	devlink_port_params_unregister(&bp->dl_port, bnxt_dl_port_params,
-				       ARRAY_SIZE(bnxt_dl_port_params));
-	devlink_port_unregister(&bp->dl_port);
-	devlink_params_unregister(dl, bnxt_dl_params,
-				  ARRAY_SIZE(bnxt_dl_params));
+	if (BNXT_PF(bp)) {
+		devlink_port_params_unregister(&bp->dl_port,
+					       bnxt_dl_port_params,
+					       ARRAY_SIZE(bnxt_dl_port_params));
+		devlink_port_unregister(&bp->dl_port);
+		devlink_params_unregister(dl, bnxt_dl_params,
+					  ARRAY_SIZE(bnxt_dl_params));
+	}
 	devlink_unregister(dl);
 	devlink_free(dl);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h
@@ -39,7 +39,7 @@
 #define NVM_OFF_DIS_GRE_VER_CHECK	171
 #define NVM_OFF_ENABLE_SRIOV		401
 
-#define BNXT_MSIX_VEC_MAX	1280
+#define BNXT_MSIX_VEC_MAX	512
 #define BNXT_MSIX_VEC_MIN_MAX	128
 
 enum bnxt_nvm_dir_type {
@@ -57,6 +57,8 @@
 };
 
 void bnxt_devlink_health_report(struct bnxt *bp, unsigned long event);
+void bnxt_dl_fw_reporters_create(struct bnxt *bp);
+void bnxt_dl_fw_reporters_destroy(struct bnxt *bp, bool all);
 int bnxt_dl_register(struct bnxt *bp);
 void bnxt_dl_unregister(struct bnxt *bp);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
@@ -124,7 +124,7 @@
 	}
 
 reset_coalesce:
-	if (netif_running(dev)) {
+	if (test_bit(BNXT_STATE_OPEN, &bp->state)) {
 		if (update_stats) {
 			rc = bnxt_close_nic(bp, true, false);
 			if (!rc)
@@ -173,6 +173,7 @@
 
 static const char * const bnxt_ring_sw_stats_str[] = {
 	"rx_l4_csum_errors",
+	"rx_buf_errors",
 	"missed_irqs",
 };
 
@@ -552,6 +553,7 @@
 		for (k = 0; k < stat_fields; j++, k++)
 			buf[j] = le64_to_cpu(hw_stats[k]);
 		buf[j++] = cpr->rx_l4_csum_errors;
+		buf[j++] = cpr->rx_buf_errors;
 		buf[j++] = cpr->missed_irqs;
 
 		bnxt_sw_func_stats[RX_TOTAL_DISCARDS].counter +=
@@ -587,25 +589,25 @@
 		if (bp->pri2cos_valid) {
 			for (i = 0; i < 8; i++, j++) {
 				long n = bnxt_rx_bytes_pri_arr[i].base_off +
-					 bp->pri2cos[i];
+					 bp->pri2cos_idx[i];
 
 				buf[j] = le64_to_cpu(*(rx_port_stats_ext + n));
 			}
 			for (i = 0; i < 8; i++, j++) {
 				long n = bnxt_rx_pkts_pri_arr[i].base_off +
-					 bp->pri2cos[i];
+					 bp->pri2cos_idx[i];
 
 				buf[j] = le64_to_cpu(*(rx_port_stats_ext + n));
 			}
 			for (i = 0; i < 8; i++, j++) {
 				long n = bnxt_tx_bytes_pri_arr[i].base_off +
-					 bp->pri2cos[i];
+					 bp->pri2cos_idx[i];
 
 				buf[j] = le64_to_cpu(*(tx_port_stats_ext + n));
 			}
 			for (i = 0; i < 8; i++, j++) {
 				long n = bnxt_tx_pkts_pri_arr[i].base_off +
-					 bp->pri2cos[i];
+					 bp->pri2cos_idx[i];
 
 				buf[j] = le64_to_cpu(*(tx_port_stats_ext + n));
 			}
@@ -742,7 +744,7 @@
 
 	if ((ering->rx_pending > BNXT_MAX_RX_DESC_CNT) ||
 	    (ering->tx_pending > BNXT_MAX_TX_DESC_CNT) ||
-	    (ering->tx_pending <= MAX_SKB_FRAGS))
+	    (ering->tx_pending < BNXT_MIN_TX_DESC_CNT))
 		return -EINVAL;
 
 	if (netif_running(dev))
@@ -767,7 +769,7 @@
 	int max_tx_sch_inputs;
 
 	/* Get the most up-to-date max_tx_sch_inputs. */
-	if (BNXT_NEW_RM(bp))
+	if (netif_running(dev) && BNXT_NEW_RM(bp))
 		bnxt_hwrm_func_resc_qcaps(bp, false);
 	max_tx_sch_inputs = hw_resc->max_tx_sch_inputs;
 
@@ -1663,14 +1665,15 @@
 	if (!BNXT_SINGLE_PF(bp))
 		return -EOPNOTSUPP;
 
+	mutex_lock(&bp->link_lock);
 	if (epause->autoneg) {
-		if (!(link_info->autoneg & BNXT_AUTONEG_SPEED))
-			return -EINVAL;
+		if (!(link_info->autoneg & BNXT_AUTONEG_SPEED)) {
+			rc = -EINVAL;
+			goto pause_exit;
+		}
 
 		link_info->autoneg |= BNXT_AUTONEG_FLOW_CTRL;
-		if (bp->hwrm_spec_code >= 0x10201)
-			link_info->req_flow_ctrl =
-				PORT_PHY_CFG_REQ_AUTO_PAUSE_AUTONEG_PAUSE;
+		link_info->req_flow_ctrl = 0;
 	} else {
 		/* when transition from auto pause to force pause,
 		 * force a link change
@@ -1688,6 +1691,9 @@
 
 	if (netif_running(dev))
 		rc = bnxt_hwrm_set_pause(bp);
+
+pause_exit:
+	mutex_unlock(&bp->link_lock);
 	return rc;
 }
 
@@ -2003,8 +2009,8 @@
 	struct hwrm_nvm_install_update_output *resp = bp->hwrm_cmd_resp_addr;
 	struct hwrm_nvm_install_update_input install = {0};
 	const struct firmware *fw;
-	int rc, hwrm_err = 0;
 	u32 item_len;
+	int rc = 0;
 	u16 index;
 
 	bnxt_hwrm_fw_set_time(bp);
@@ -2048,15 +2054,14 @@
 			memcpy(kmem, fw->data, fw->size);
 			modify.host_src_addr = cpu_to_le64(dma_handle);
 
-			hwrm_err = hwrm_send_message(bp, &modify,
-						     sizeof(modify),
-						     FLASH_PACKAGE_TIMEOUT);
+			rc = hwrm_send_message(bp, &modify, sizeof(modify),
+					       FLASH_PACKAGE_TIMEOUT);
 			dma_free_coherent(&bp->pdev->dev, fw->size, kmem,
 					  dma_handle);
 		}
 	}
 	release_firmware(fw);
-	if (rc || hwrm_err)
+	if (rc)
 		goto err_exit;
 
 	if ((install_type & 0xffff) == 0)
@@ -2065,20 +2070,19 @@
 	install.install_type = cpu_to_le32(install_type);
 
 	mutex_lock(&bp->hwrm_cmd_lock);
-	hwrm_err = _hwrm_send_message(bp, &install, sizeof(install),
-				      INSTALL_PACKAGE_TIMEOUT);
-	if (hwrm_err) {
+	rc = _hwrm_send_message(bp, &install, sizeof(install),
+				INSTALL_PACKAGE_TIMEOUT);
+	if (rc) {
 		u8 error_code = ((struct hwrm_err_output *)resp)->cmd_err;
 
 		if (resp->error_code && error_code ==
 		    NVM_INSTALL_UPDATE_CMD_ERR_CODE_FRAG_ERR) {
 			install.flags |= cpu_to_le16(
 			       NVM_INSTALL_UPDATE_REQ_FLAGS_ALLOWED_TO_DEFRAG);
-			hwrm_err = _hwrm_send_message(bp, &install,
-						      sizeof(install),
-						      INSTALL_PACKAGE_TIMEOUT);
+			rc = _hwrm_send_message(bp, &install, sizeof(install),
+						INSTALL_PACKAGE_TIMEOUT);
 		}
-		if (hwrm_err)
+		if (rc)
 			goto flash_pkg_exit;
 	}
 
@@ -2090,7 +2094,7 @@
 flash_pkg_exit:
 	mutex_unlock(&bp->hwrm_cmd_lock);
 err_exit:
-	if (hwrm_err == -EACCES)
+	if (rc == -EACCES)
 		bnxt_print_admin_err(bp);
 	return rc;
 }
@@ -2158,6 +2162,9 @@
 	if (rc != 0)
 		return rc;
 
+	if (!dir_entries || !entry_length)
+		return -EIO;
+
 	/* Insert 2 bytes of directory info (count and size of entries) */
 	if (len < 2)
 		return -EINVAL;
@@ -2391,8 +2398,7 @@
 	struct bnxt *bp = netdev_priv(dev);
 	struct ethtool_eee *eee = &bp->eee;
 	struct bnxt_link_info *link_info = &bp->link_info;
-	u32 advertising =
-		 _bnxt_fw_to_ethtool_adv_spds(link_info->advertising, 0);
+	u32 advertising;
 	int rc = 0;
 
 	if (!BNXT_SINGLE_PF(bp))
@@ -2401,19 +2407,23 @@
 	if (!(bp->flags & BNXT_FLAG_EEE_CAP))
 		return -EOPNOTSUPP;
 
+	mutex_lock(&bp->link_lock);
+	advertising = _bnxt_fw_to_ethtool_adv_spds(link_info->advertising, 0);
 	if (!edata->eee_enabled)
 		goto eee_ok;
 
 	if (!(link_info->autoneg & BNXT_AUTONEG_SPEED)) {
 		netdev_warn(dev, "EEE requires autoneg\n");
-		return -EINVAL;
+		rc = -EINVAL;
+		goto eee_exit;
 	}
 	if (edata->tx_lpi_enabled) {
 		if (bp->lpi_tmr_hi && (edata->tx_lpi_timer > bp->lpi_tmr_hi ||
 				       edata->tx_lpi_timer < bp->lpi_tmr_lo)) {
 			netdev_warn(dev, "Valid LPI timer range is %d and %d microsecs\n",
 				    bp->lpi_tmr_lo, bp->lpi_tmr_hi);
-			return -EINVAL;
+			rc = -EINVAL;
+			goto eee_exit;
 		} else if (!bp->lpi_tmr_hi) {
 			edata->tx_lpi_timer = eee->tx_lpi_timer;
 		}
@@ -2423,7 +2433,8 @@
 	} else if (edata->advertised & ~advertising) {
 		netdev_warn(dev, "EEE advertised %x must be a subset of autoneg advertised speeds %x\n",
 			    edata->advertised, advertising);
-		return -EINVAL;
+		rc = -EINVAL;
+		goto eee_exit;
 	}
 
 	eee->advertised = edata->advertised;
@@ -2435,6 +2446,8 @@
 	if (netif_running(dev))
 		rc = bnxt_hwrm_set_link_setting(bp, false, true);
 
+eee_exit:
+	mutex_unlock(&bp->link_lock);
 	return rc;
 }
 
@@ -2569,7 +2582,7 @@
 	/* Read A2 portion of the EEPROM */
 	if (length) {
 		start -= ETH_MODULE_SFF_8436_LEN;
-		rc = bnxt_read_sfp_module_eeprom_info(bp, I2C_DEV_ADDR_A2, 1,
+		rc = bnxt_read_sfp_module_eeprom_info(bp, I2C_DEV_ADDR_A2, 0,
 						      start, length, data);
 	}
 	return rc;
@@ -3062,8 +3075,15 @@
 			}
 		}
 
-		if (info->dest_buf)
-			memcpy(info->dest_buf + off, dma_buf, len);
+		if (info->dest_buf) {
+			if ((info->seg_start + off + len) <=
+			    BNXT_COREDUMP_BUF_LEN(info->buf_len)) {
+				memcpy(info->dest_buf + off, dma_buf, len);
+			} else {
+				rc = -ENOBUFS;
+				break;
+			}
+		}
 
 		if (cmn_req->req_type ==
 				cpu_to_le16(HWRM_DBG_COREDUMP_RETRIEVE))
@@ -3117,7 +3137,7 @@
 
 static int bnxt_hwrm_dbg_coredump_retrieve(struct bnxt *bp, u16 component_id,
 					   u16 segment_id, u32 *seg_len,
-					   void *buf, u32 offset)
+					   void *buf, u32 buf_len, u32 offset)
 {
 	struct hwrm_dbg_coredump_retrieve_input req = {0};
 	struct bnxt_hwrm_dbg_dma_info info = {NULL};
@@ -3132,8 +3152,11 @@
 				seq_no);
 	info.data_len_off = offsetof(struct hwrm_dbg_coredump_retrieve_output,
 				     data_len);
-	if (buf)
+	if (buf) {
 		info.dest_buf = buf + offset;
+		info.buf_len = buf_len;
+		info.seg_start = offset;
+	}
 
 	rc = bnxt_hwrm_dbg_dma_data(bp, &req, sizeof(req), &info);
 	if (!rc)
@@ -3223,14 +3246,17 @@
 static int bnxt_get_coredump(struct bnxt *bp, void *buf, u32 *dump_len)
 {
 	u32 ver_get_resp_len = sizeof(struct hwrm_ver_get_output);
+	u32 offset = 0, seg_hdr_len, seg_record_len, buf_len = 0;
 	struct coredump_segment_record *seg_record = NULL;
-	u32 offset = 0, seg_hdr_len, seg_record_len;
 	struct bnxt_coredump_segment_hdr seg_hdr;
 	struct bnxt_coredump coredump = {NULL};
 	time64_t start_time;
 	u16 start_utc;
 	int rc = 0, i;
 
+	if (buf)
+		buf_len = *dump_len;
+
 	start_time = ktime_get_real_seconds();
 	start_utc = sys_tz.tz_minuteswest * 60;
 	seg_hdr_len = sizeof(seg_hdr);
@@ -3263,6 +3289,12 @@
 		u32 duration = 0, seg_len = 0;
 		unsigned long start, end;
 
+		if (buf && ((offset + seg_hdr_len) >
+			    BNXT_COREDUMP_BUF_LEN(buf_len))) {
+			rc = -ENOBUFS;
+			goto err;
+		}
+
 		start = jiffies;
 
 		rc = bnxt_hwrm_dbg_coredump_initiate(bp, comp_id, seg_id);
@@ -3275,9 +3307,11 @@
 
 		/* Write segment data into the buffer */
 		rc = bnxt_hwrm_dbg_coredump_retrieve(bp, comp_id, seg_id,
-						     &seg_len, buf,
+						     &seg_len, buf, buf_len,
 						     offset + seg_hdr_len);
-		if (rc)
+		if (rc && rc == -ENOBUFS)
+			goto err;
+		else if (rc)
 			netdev_err(bp->dev,
 				   "Failed to retrieve coredump for seg = %d\n",
 				   seg_record->segment_id);
@@ -3307,7 +3341,8 @@
 					  rc);
 	kfree(coredump.data);
 	*dump_len += sizeof(struct bnxt_coredump_record);
-
+	if (rc == -ENOBUFS)
+		netdev_err(bp->dev, "Firmware returned large coredump buffer");
 	return rc;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h
@@ -31,6 +31,8 @@
 	u16		total_segs;
 };
 
+#define BNXT_COREDUMP_BUF_LEN(len) ((len) - sizeof(struct bnxt_coredump_record))
+
 struct bnxt_hwrm_dbg_dma_info {
 	void *dest_buf;
 	int dest_buf_size;
@@ -38,6 +40,8 @@
 	u16 seq_off;
 	u16 data_len_off;
 	u16 segs;
+	u32 seg_start;
+	u32 buf_len;
 };
 
 struct hwrm_dbg_cmn_input {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c
@@ -85,11 +85,10 @@
 	if (old_setting == setting)
 		return 0;
 
-	func_flags = vf->func_flags;
 	if (setting)
-		func_flags |= FUNC_CFG_REQ_FLAGS_SRC_MAC_ADDR_CHECK_ENABLE;
+		func_flags = FUNC_CFG_REQ_FLAGS_SRC_MAC_ADDR_CHECK_ENABLE;
 	else
-		func_flags |= FUNC_CFG_REQ_FLAGS_SRC_MAC_ADDR_CHECK_DISABLE;
+		func_flags = FUNC_CFG_REQ_FLAGS_SRC_MAC_ADDR_CHECK_DISABLE;
 	/*TODO: if the driver supports VLAN filter on guest VLAN,
 	 * the spoof check should also include vlan anti-spoofing
 	 */
@@ -98,7 +97,6 @@
 	req.flags = cpu_to_le32(func_flags);
 	rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
 	if (!rc) {
-		vf->func_flags = func_flags;
 		if (setting)
 			vf->flags |= BNXT_VF_SPOOFCHK;
 		else
@@ -230,7 +228,6 @@
 	memcpy(vf->mac_addr, mac, ETH_ALEN);
 	bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_CFG, -1, -1);
 	req.fid = cpu_to_le16(vf->fw_fid);
-	req.flags = cpu_to_le32(vf->func_flags);
 	req.enables = cpu_to_le32(FUNC_CFG_REQ_ENABLES_DFLT_MAC_ADDR);
 	memcpy(req.dflt_mac_addr, mac, ETH_ALEN);
 	return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
@@ -268,7 +265,6 @@
 
 	bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_CFG, -1, -1);
 	req.fid = cpu_to_le16(vf->fw_fid);
-	req.flags = cpu_to_le32(vf->func_flags);
 	req.dflt_vlan = cpu_to_le16(vlan_tag);
 	req.enables = cpu_to_le32(FUNC_CFG_REQ_ENABLES_DFLT_VLAN);
 	rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
@@ -307,7 +303,6 @@
 		return 0;
 	bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_CFG, -1, -1);
 	req.fid = cpu_to_le16(vf->fw_fid);
-	req.flags = cpu_to_le32(vf->func_flags);
 	req.enables = cpu_to_le32(FUNC_CFG_REQ_ENABLES_MAX_BW);
 	req.max_bw = cpu_to_le32(max_tx_rate);
 	req.enables |= cpu_to_le32(FUNC_CFG_REQ_ENABLES_MIN_BW);
@@ -403,6 +398,7 @@
 		}
 	}
 
+	bp->pf.active_vfs = 0;
 	kfree(bp->pf.vf);
 	bp->pf.vf = NULL;
 }
@@ -479,7 +475,6 @@
 	vf = &bp->pf.vf[vf_id];
 	bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_FUNC_CFG, -1, -1);
 	req.fid = cpu_to_le16(vf->fw_fid);
-	req.flags = cpu_to_le32(vf->func_flags);
 
 	if (is_valid_ether_addr(vf->mac_addr)) {
 		req.enables |= cpu_to_le32(FUNC_CFG_REQ_ENABLES_DFLT_MAC_ADDR);
@@ -602,7 +597,7 @@
 		hw_resc->max_stat_ctxs -= le16_to_cpu(req.min_stat_ctx) * n;
 		hw_resc->max_vnics -= le16_to_cpu(req.min_vnics) * n;
 		if (bp->flags & BNXT_FLAG_CHIP_P5)
-			hw_resc->max_irqs -= vf_msix * n;
+			hw_resc->max_nqs -= vf_msix;
 
 		rc = pf->active_vfs;
 	}
@@ -839,7 +834,6 @@
 
 	bnxt_free_vf_resources(bp);
 
-	bp->pf.active_vfs = 0;
 	/* Reclaim all resources for the PF. */
 	rtnl_lock();
 	bnxt_restore_pf_fw_resources(bp);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c
@@ -113,8 +113,10 @@
 {
 	struct net_device *dev = edev->net;
 	struct bnxt *bp = netdev_priv(dev);
+	struct bnxt_hw_resc *hw_resc;
 	int max_idx, max_cp_rings;
 	int avail_msix, idx;
+	int total_vecs;
 	int rc = 0;
 
 	ASSERT_RTNL();
@@ -142,7 +144,10 @@
 	}
 	edev->ulp_tbl[ulp_id].msix_base = idx;
 	edev->ulp_tbl[ulp_id].msix_requested = avail_msix;
-	if (bp->total_irqs < (idx + avail_msix)) {
+	hw_resc = &bp->hw_resc;
+	total_vecs = idx + avail_msix;
+	if (bp->total_irqs < total_vecs ||
+	    (BNXT_NEW_RM(bp) && hw_resc->resv_irqs < total_vecs)) {
 		if (netif_running(dev)) {
 			bnxt_close_nic(bp, true, false);
 			rc = bnxt_open_nic(bp, true, false);
@@ -156,7 +161,6 @@
 	}
 
 	if (BNXT_NEW_RM(bp)) {
-		struct bnxt_hw_resc *hw_resc = &bp->hw_resc;
 		int resv_msix;
 
 		resv_msix = hw_resc->resv_irqs - bp->cp_nr_rings;
@@ -182,7 +186,7 @@
 
 	edev->ulp_tbl[ulp_id].msix_requested = 0;
 	edev->flags &= ~BNXT_EN_FLAG_MSIX_REQUESTED;
-	if (netif_running(dev)) {
+	if (netif_running(dev) && !(edev->flags & BNXT_EN_FLAG_ULP_STOPPED)) {
 		bnxt_close_nic(bp, true, false);
 		bnxt_open_nic(bp, true, false);
 	}
@@ -212,8 +216,12 @@
 
 int bnxt_get_ulp_stat_ctxs(struct bnxt *bp)
 {
-	if (bnxt_ulp_registered(bp->edev, BNXT_ROCE_ULP))
-		return BNXT_MIN_ROCE_STAT_CTXS;
+	if (bnxt_ulp_registered(bp->edev, BNXT_ROCE_ULP)) {
+		struct bnxt_en_dev *edev = bp->edev;
+
+		if (edev->ulp_tbl[BNXT_ROCE_ULP].msix_requested)
+			return BNXT_MIN_ROCE_STAT_CTXS;
+	}
 
 	return 0;
 }
@@ -266,6 +274,7 @@
 	if (!edev)
 		return;
 
+	edev->flags |= BNXT_EN_FLAG_ULP_STOPPED;
 	for (i = 0; i < BNXT_MAX_ULP; i++) {
 		struct bnxt_ulp *ulp = &edev->ulp_tbl[i];
 
@@ -276,7 +285,7 @@
 	}
 }
 
-void bnxt_ulp_start(struct bnxt *bp)
+void bnxt_ulp_start(struct bnxt *bp, int err)
 {
 	struct bnxt_en_dev *edev = bp->edev;
 	struct bnxt_ulp_ops *ops;
@@ -285,6 +294,11 @@
 	if (!edev)
 		return;
 
+	edev->flags &= ~BNXT_EN_FLAG_ULP_STOPPED;
+
+	if (err)
+		return;
+
 	for (i = 0; i < BNXT_MAX_ULP; i++) {
 		struct bnxt_ulp *ulp = &edev->ulp_tbl[i];
 
@@ -459,13 +473,14 @@
 		if (!edev)
 			return ERR_PTR(-ENOMEM);
 		edev->en_ops = &bnxt_en_ops_tbl;
-		if (bp->flags & BNXT_FLAG_ROCEV1_CAP)
-			edev->flags |= BNXT_EN_FLAG_ROCEV1_CAP;
-		if (bp->flags & BNXT_FLAG_ROCEV2_CAP)
-			edev->flags |= BNXT_EN_FLAG_ROCEV2_CAP;
 		edev->net = dev;
 		edev->pdev = bp->pdev;
 		bp->edev = edev;
 	}
+	edev->flags &= ~BNXT_EN_FLAG_ROCE_CAP;
+	if (bp->flags & BNXT_FLAG_ROCEV1_CAP)
+		edev->flags |= BNXT_EN_FLAG_ROCEV1_CAP;
+	if (bp->flags & BNXT_FLAG_ROCEV2_CAP)
+		edev->flags |= BNXT_EN_FLAG_ROCEV2_CAP;
 	return bp->edev;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.h
@@ -64,6 +64,7 @@
 	#define BNXT_EN_FLAG_ROCE_CAP		(BNXT_EN_FLAG_ROCEV1_CAP | \
 						 BNXT_EN_FLAG_ROCEV2_CAP)
 	#define BNXT_EN_FLAG_MSIX_REQUESTED	0x4
+	#define BNXT_EN_FLAG_ULP_STOPPED	0x8
 	const struct bnxt_en_ops	*en_ops;
 	struct bnxt_ulp			ulp_tbl[BNXT_MAX_ULP];
 };
@@ -92,7 +93,7 @@
 int bnxt_get_ulp_msix_base(struct bnxt *bp);
 int bnxt_get_ulp_stat_ctxs(struct bnxt *bp);
 void bnxt_ulp_stop(struct bnxt *bp);
-void bnxt_ulp_start(struct bnxt *bp);
+void bnxt_ulp_start(struct bnxt *bp, int err);
 void bnxt_ulp_sriov_cfg(struct bnxt *bp, int num_vfs);
 void bnxt_ulp_shutdown(struct bnxt *bp);
 void bnxt_ulp_irq_stop(struct bnxt *bp);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
@@ -398,6 +398,9 @@
 	struct net_device *dev;
 	int rc, i;
 
+	if (!(bp->flags & BNXT_FLAG_DSN_VALID))
+		return -ENODEV;
+
 	bp->vf_reps = kcalloc(num_vfs, sizeof(vf_rep), GFP_KERNEL);
 	if (!bp->vf_reps)
 		return -ENOMEM;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -69,6 +69,9 @@
 #define GENET_RDMA_REG_OFF	(priv->hw_params->rdma_offset + \
 				TOTAL_DESC * DMA_DESC_SIZE)
 
+/* Forward declarations */
+static void bcmgenet_set_rx_mode(struct net_device *dev);
+
 static inline void bcmgenet_writel(u32 value, void __iomem *offset)
 {
 	/* MIPS chips strapped for BE will automagically configure the
@@ -995,6 +998,8 @@
 	if (netif_running(dev))
 		bcmgenet_update_mib_counters(priv);
 
+	dev->netdev_ops->ndo_get_stats(dev);
+
 	for (i = 0; i < BCMGENET_STATS_LEN; i++) {
 		const struct bcmgenet_stats *s;
 		char *p;
@@ -1013,7 +1018,8 @@
 	}
 }
 
-static void bcmgenet_eee_enable_set(struct net_device *dev, bool enable)
+void bcmgenet_eee_enable_set(struct net_device *dev, bool enable,
+			     bool tx_lpi_enabled)
 {
 	struct bcmgenet_priv *priv = netdev_priv(dev);
 	u32 off = priv->hw_params->tbuf_offset + TBUF_ENERGY_CTRL;
@@ -1033,7 +1039,7 @@
 
 	/* Enable EEE and switch to a 27Mhz clock automatically */
 	reg = bcmgenet_readl(priv->base + off);
-	if (enable)
+	if (tx_lpi_enabled)
 		reg |= TBUF_EEE_EN | TBUF_PM_EN;
 	else
 		reg &= ~(TBUF_EEE_EN | TBUF_PM_EN);
@@ -1054,6 +1060,7 @@
 
 	priv->eee.eee_enabled = enable;
 	priv->eee.eee_active = enable;
+	priv->eee.tx_lpi_enabled = tx_lpi_enabled;
 }
 
 static int bcmgenet_get_eee(struct net_device *dev, struct ethtool_eee *e)
@@ -1069,6 +1076,7 @@
 
 	e->eee_enabled = p->eee_enabled;
 	e->eee_active = p->eee_active;
+	e->tx_lpi_enabled = p->tx_lpi_enabled;
 	e->tx_lpi_timer = bcmgenet_umac_readl(priv, UMAC_EEE_LPI_TIMER);
 
 	return phy_ethtool_get_eee(dev->phydev, e);
@@ -1078,7 +1086,6 @@
 {
 	struct bcmgenet_priv *priv = netdev_priv(dev);
 	struct ethtool_eee *p = &priv->eee;
-	int ret = 0;
 
 	if (GENET_IS_V1(priv))
 		return -EOPNOTSUPP;
@@ -1089,16 +1096,11 @@
 	p->eee_enabled = e->eee_enabled;
 
 	if (!p->eee_enabled) {
-		bcmgenet_eee_enable_set(dev, false);
+		bcmgenet_eee_enable_set(dev, false, false);
 	} else {
-		ret = phy_init_eee(dev->phydev, 0);
-		if (ret) {
-			netif_err(priv, hw, dev, "EEE initialization failed\n");
-			return ret;
-		}
-
+		p->eee_active = phy_init_eee(dev->phydev, false) >= 0;
 		bcmgenet_umac_writel(priv, e->tx_lpi_timer, UMAC_EEE_LPI_TIMER);
-		bcmgenet_eee_enable_set(dev, true);
+		bcmgenet_eee_enable_set(dev, p->eee_active, e->tx_lpi_enabled);
 	}
 
 	return phy_ethtool_set_eee(dev->phydev, e);
@@ -1182,7 +1184,8 @@
 
 	switch (mode) {
 	case GENET_POWER_PASSIVE:
-		reg &= ~(EXT_PWR_DOWN_DLL | EXT_PWR_DOWN_BIAS);
+		reg &= ~(EXT_PWR_DOWN_DLL | EXT_PWR_DOWN_BIAS |
+			 EXT_ENERGY_DET_MASK);
 		if (GENET_IS_V5(priv)) {
 			reg &= ~(EXT_PWR_DOWN_PHY_EN |
 				 EXT_PWR_DOWN_PHY_RD |
@@ -1541,6 +1544,11 @@
 	return skb;
 }
 
+static void bcmgenet_hide_tsb(struct sk_buff *skb)
+{
+	__skb_pull(skb, sizeof(struct status_64));
+}
+
 static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct bcmgenet_priv *priv = netdev_priv(dev);
@@ -1586,11 +1594,6 @@
 		goto out;
 	}
 
-	if (skb_padto(skb, ETH_ZLEN)) {
-		ret = NETDEV_TX_OK;
-		goto out;
-	}
-
 	/* Retain how many bytes will be sent on the wire, without TSB inserted
 	 * by transmit checksum offload
 	 */
@@ -1639,8 +1642,13 @@
 		len_stat = (size << DMA_BUFLENGTH_SHIFT) |
 			   (priv->hw_params->qtag_mask << DMA_TX_QTAG_SHIFT);
 
+		/* Note: if we ever change from DMA_TX_APPEND_CRC below we
+		 * will need to restore software padding of "runt" packets
+		 */
+		len_stat |= DMA_TX_APPEND_CRC;
+
 		if (!i) {
-			len_stat |= DMA_TX_APPEND_CRC | DMA_SOP;
+			len_stat |= DMA_SOP;
 			if (skb->ip_summed == CHECKSUM_PARTIAL)
 				len_stat |= DMA_TX_DO_CSUM;
 		}
@@ -1651,6 +1659,8 @@
 	}
 
 	GENET_CB(skb)->last_cb = tx_cb_ptr;
+
+	bcmgenet_hide_tsb(skb);
 	skb_tx_timestamp(skb);
 
 	/* Decrement total BD count and advance our write pointer */
@@ -1695,7 +1705,8 @@
 	dma_addr_t mapping;
 
 	/* Allocate a new Rx skb */
-	skb = netdev_alloc_skb(priv->dev, priv->rx_buf_len + SKB_ALIGNMENT);
+	skb = __netdev_alloc_skb(priv->dev, priv->rx_buf_len + SKB_ALIGNMENT,
+				 GFP_ATOMIC | __GFP_NOWARN);
 	if (!skb) {
 		priv->mib.alloc_rx_buff_failed++;
 		netif_err(priv, rx_err, priv->dev,
@@ -1811,6 +1822,14 @@
 			  __func__, p_index, ring->c_index,
 			  ring->read_ptr, dma_length_status);
 
+		if (unlikely(len > RX_BUF_LENGTH)) {
+			netif_err(priv, rx_status, dev, "oversized packet\n");
+			dev->stats.rx_length_errors++;
+			dev->stats.rx_errors++;
+			dev_kfree_skb_any(skb);
+			goto next;
+		}
+
 		if (unlikely(!(dma_flag & DMA_EOP) || !(dma_flag & DMA_SOP))) {
 			netif_err(priv, rx_status, dev,
 				  "dropping fragmented packet!\n");
@@ -1971,12 +1990,18 @@
 {
 	u32 reg;
 
+	spin_lock_bh(&priv->reg_lock);
 	reg = bcmgenet_umac_readl(priv, UMAC_CMD);
+	if (reg & CMD_SW_RESET) {
+		spin_unlock_bh(&priv->reg_lock);
+		return;
+	}
 	if (enable)
 		reg |= mask;
 	else
 		reg &= ~mask;
 	bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+	spin_unlock_bh(&priv->reg_lock);
 
 	/* UniMAC stops on a packet boundary, wait for a full-size packet
 	 * to be processed
@@ -1991,11 +2016,11 @@
 	bcmgenet_rbuf_ctrl_set(priv, 0);
 	udelay(10);
 
-	/* disable MAC while updating its registers */
-	bcmgenet_umac_writel(priv, 0, UMAC_CMD);
-
-	/* issue soft reset with (rg)mii loopback to ensure a stable rxclk */
-	bcmgenet_umac_writel(priv, CMD_SW_RESET | CMD_LCL_LOOP_EN, UMAC_CMD);
+	/* issue soft reset and disable MAC while updating its registers */
+	spin_lock_bh(&priv->reg_lock);
+	bcmgenet_umac_writel(priv, CMD_SW_RESET, UMAC_CMD);
+	udelay(2);
+	spin_unlock_bh(&priv->reg_lock);
 }
 
 static void bcmgenet_intr_disable(struct bcmgenet_priv *priv)
@@ -2164,8 +2189,8 @@
 				  DMA_END_ADDR);
 
 	/* Initialize Tx NAPI */
-	netif_napi_add(priv->dev, &ring->napi, bcmgenet_tx_poll,
-		       NAPI_POLL_WEIGHT);
+	netif_tx_napi_add(priv->dev, &ring->napi, bcmgenet_tx_poll,
+			  NAPI_POLL_WEIGHT);
 }
 
 /* Initialize a RDMA ring */
@@ -2777,17 +2802,23 @@
 }
 
 /* Returns a reusable dma control register value */
-static u32 bcmgenet_dma_disable(struct bcmgenet_priv *priv)
+static u32 bcmgenet_dma_disable(struct bcmgenet_priv *priv, bool flush_rx)
 {
+	unsigned int i;
 	u32 reg;
 	u32 dma_ctrl;
 
 	/* disable DMA */
 	dma_ctrl = 1 << (DESC_INDEX + DMA_RING_BUF_EN_SHIFT) | DMA_EN;
+	for (i = 0; i < priv->hw_params->tx_queues; i++)
+		dma_ctrl |= (1 << (i + DMA_RING_BUF_EN_SHIFT));
 	reg = bcmgenet_tdma_readl(priv, DMA_CTRL);
 	reg &= ~dma_ctrl;
 	bcmgenet_tdma_writel(priv, reg, DMA_CTRL);
 
+	dma_ctrl = 1 << (DESC_INDEX + DMA_RING_BUF_EN_SHIFT) | DMA_EN;
+	for (i = 0; i < priv->hw_params->rx_queues; i++)
+		dma_ctrl |= (1 << (i + DMA_RING_BUF_EN_SHIFT));
 	reg = bcmgenet_rdma_readl(priv, DMA_CTRL);
 	reg &= ~dma_ctrl;
 	bcmgenet_rdma_writel(priv, reg, DMA_CTRL);
@@ -2796,6 +2827,14 @@
 	udelay(10);
 	bcmgenet_umac_writel(priv, 0, UMAC_TX_FLUSH);
 
+	if (flush_rx) {
+		reg = bcmgenet_rbuf_ctrl_get(priv);
+		bcmgenet_rbuf_ctrl_set(priv, reg | BIT(0));
+		udelay(10);
+		bcmgenet_rbuf_ctrl_set(priv, reg);
+		udelay(10);
+	}
+
 	return dma_ctrl;
 }
 
@@ -2849,6 +2888,9 @@
 	struct bcmgenet_priv *priv = netdev_priv(dev);
 
 	/* Start the network engine */
+	netif_addr_lock_bh(dev);
+	bcmgenet_set_rx_mode(dev);
+	netif_addr_unlock_bh(dev);
 	bcmgenet_enable_rx_napi(priv);
 
 	umac_enable_set(priv, CMD_TX_EN | CMD_RX_EN, true);
@@ -2890,14 +2932,8 @@
 
 	bcmgenet_set_hw_addr(priv, dev->dev_addr);
 
-	if (priv->internal_phy) {
-		reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
-		reg |= EXT_ENERGY_DET_MASK;
-		bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
-	}
-
-	/* Disable RX/TX DMA and flush TX queues */
-	dma_ctrl = bcmgenet_dma_disable(priv);
+	/* Disable RX/TX DMA and flush TX and RX queues */
+	dma_ctrl = bcmgenet_dma_disable(priv, true);
 
 	/* Reinitialize TDMA and RDMA and SW housekeeping */
 	ret = bcmgenet_init_dma(priv);
@@ -2952,7 +2988,7 @@
 	return ret;
 }
 
-static void bcmgenet_netif_stop(struct net_device *dev)
+static void bcmgenet_netif_stop(struct net_device *dev, bool stop_phy)
 {
 	struct bcmgenet_priv *priv = netdev_priv(dev);
 
@@ -2967,7 +3003,8 @@
 	/* Disable MAC transmit. TX DMA disabled must be done before this */
 	umac_enable_set(priv, CMD_TX_EN, false);
 
-	phy_stop(dev->phydev);
+	if (stop_phy)
+		phy_stop(dev->phydev);
 	bcmgenet_disable_rx_napi(priv);
 	bcmgenet_intr_disable(priv);
 
@@ -2993,7 +3030,7 @@
 
 	netif_dbg(priv, ifdown, dev, "bcmgenet_close\n");
 
-	bcmgenet_netif_stop(dev);
+	bcmgenet_netif_stop(dev, false);
 
 	/* Really kill the PHY state machine and disconnect from it */
 	phy_disconnect(dev->phydev);
@@ -3117,16 +3154,19 @@
 	 * 3. The number of filters needed exceeds the number filters
 	 *    supported by the hardware.
 	*/
+	spin_lock(&priv->reg_lock);
 	reg = bcmgenet_umac_readl(priv, UMAC_CMD);
 	if ((dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) ||
 	    (nfilter > MAX_MDF_FILTER)) {
 		reg |= CMD_PROMISC;
 		bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+		spin_unlock(&priv->reg_lock);
 		bcmgenet_umac_writel(priv, 0, UMAC_MDF_CTRL);
 		return;
 	} else {
 		reg &= ~CMD_PROMISC;
 		bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+		spin_unlock(&priv->reg_lock);
 	}
 
 	/* update MDF filter */
@@ -3204,6 +3244,7 @@
 	dev->stats.rx_packets = rx_packets;
 	dev->stats.rx_errors = rx_errors;
 	dev->stats.rx_missed_errors = rx_errors;
+	dev->stats.rx_dropped = rx_dropped;
 	return &dev->stats;
 }
 
@@ -3483,6 +3524,7 @@
 		goto err;
 	}
 
+	spin_lock_init(&priv->reg_lock);
 	spin_lock_init(&priv->lock);
 
 	SET_NETDEV_DEV(dev, &pdev->dev);
@@ -3500,10 +3542,12 @@
 
 	/* Request the WOL interrupt and advertise suspend if available */
 	priv->wol_irq_disabled = true;
-	err = devm_request_irq(&pdev->dev, priv->wol_irq, bcmgenet_wol_isr, 0,
-			       dev->name, priv);
-	if (!err)
-		device_set_wakeup_capable(&pdev->dev, 1);
+	if (priv->wol_irq > 0) {
+		err = devm_request_irq(&pdev->dev, priv->wol_irq,
+				       bcmgenet_wol_isr, 0, dev->name, priv);
+		if (!err)
+			device_set_wakeup_capable(&pdev->dev, 1);
+	}
 
 	/* Set the needed headroom to account for any possible
 	 * features enabling/disabling at runtime
@@ -3578,8 +3622,10 @@
 	clk_disable_unprepare(priv->clk);
 
 	err = register_netdev(dev);
-	if (err)
+	if (err) {
+		bcmgenet_mii_exit(dev);
 		goto err;
+	}
 
 	return err;
 
@@ -3609,7 +3655,6 @@
 	struct bcmgenet_priv *priv = netdev_priv(dev);
 	unsigned long dma_ctrl;
 	int ret;
-	u32 reg;
 
 	if (!netif_running(dev))
 		return 0;
@@ -3641,17 +3686,11 @@
 
 	bcmgenet_set_hw_addr(priv, dev->dev_addr);
 
-	if (priv->internal_phy) {
-		reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
-		reg |= EXT_ENERGY_DET_MASK;
-		bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
-	}
-
 	if (priv->wolopts)
 		bcmgenet_power_up(priv, GENET_POWER_WOL_MAGIC);
 
 	/* Disable RX/TX DMA and flush TX queues */
-	dma_ctrl = bcmgenet_dma_disable(priv);
+	dma_ctrl = bcmgenet_dma_disable(priv, false);
 
 	/* Reinitialize TDMA and RDMA and SW housekeeping */
 	ret = bcmgenet_init_dma(priv);
@@ -3666,9 +3705,6 @@
 	if (!device_may_wakeup(d))
 		phy_resume(dev->phydev);
 
-	if (priv->eee.eee_enabled)
-		bcmgenet_eee_enable_set(dev, true);
-
 	bcmgenet_netif_start(dev);
 
 	netif_device_attach(dev);
@@ -3693,7 +3729,7 @@
 
 	netif_device_detach(dev);
 
-	bcmgenet_netif_stop(dev);
+	bcmgenet_netif_stop(dev, true);
 
 	if (!device_may_wakeup(d))
 		phy_suspend(dev->phydev);
@@ -3733,3 +3769,4 @@
 MODULE_DESCRIPTION("Broadcom GENET Ethernet controller driver");
 MODULE_ALIAS("platform:bcmgenet");
 MODULE_LICENSE("GPL");
+MODULE_SOFTDEP("pre: mdio-bcm-unimac");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/broadcom/genet/bcmgenet.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/broadcom/genet/bcmgenet.h
@@ -14,6 +14,7 @@
 #include <linux/if_vlan.h>
 #include <linux/phy.h>
 #include <linux/dim.h>
+#include <linux/ethtool.h>
 
 /* total number of Buffer Descriptors, same for Rx/Tx */
 #define TOTAL_DESC				256
@@ -607,6 +608,8 @@
 /* device context */
 struct bcmgenet_priv {
 	void __iomem *base;
+	/* reg_lock: lock to serialize access to shared registers */
+	spinlock_t reg_lock;
 	enum bcmgenet_version version;
 	struct net_device *dev;
 
@@ -674,6 +677,7 @@
 	/* WOL */
 	struct clk *clk_wol;
 	u32 wolopts;
+	u8 sopass[SOPASS_MAX];
 
 	struct bcmgenet_mib_counters mib;
 
@@ -734,4 +738,7 @@
 void bcmgenet_wol_power_up_cfg(struct bcmgenet_priv *priv,
 			       enum bcmgenet_power_mode mode);
 
+void bcmgenet_eee_enable_set(struct net_device *dev, bool enable,
+			     bool tx_lpi_enabled);
+
 #endif /* __BCMGENET_H__ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c
@@ -41,18 +41,20 @@
 void bcmgenet_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
 	struct bcmgenet_priv *priv = netdev_priv(dev);
-	u32 reg;
+	struct device *kdev = &priv->pdev->dev;
+
+	if (!device_can_wakeup(kdev)) {
+		wol->supported = 0;
+		wol->wolopts = 0;
+		return;
+	}
 
 	wol->supported = WAKE_MAGIC | WAKE_MAGICSECURE;
 	wol->wolopts = priv->wolopts;
 	memset(wol->sopass, 0, sizeof(wol->sopass));
 
-	if (wol->wolopts & WAKE_MAGICSECURE) {
-		reg = bcmgenet_umac_readl(priv, UMAC_MPD_PW_MS);
-		put_unaligned_be16(reg, &wol->sopass[0]);
-		reg = bcmgenet_umac_readl(priv, UMAC_MPD_PW_LS);
-		put_unaligned_be32(reg, &wol->sopass[2]);
-	}
+	if (wol->wolopts & WAKE_MAGICSECURE)
+		memcpy(wol->sopass, priv->sopass, sizeof(priv->sopass));
 }
 
 /* ethtool function - set WOL (Wake on LAN) settings.
@@ -62,7 +64,6 @@
 {
 	struct bcmgenet_priv *priv = netdev_priv(dev);
 	struct device *kdev = &priv->pdev->dev;
-	u32 reg;
 
 	if (!device_can_wakeup(kdev))
 		return -ENOTSUPP;
@@ -70,17 +71,8 @@
 	if (wol->wolopts & ~(WAKE_MAGIC | WAKE_MAGICSECURE))
 		return -EINVAL;
 
-	reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL);
-	if (wol->wolopts & WAKE_MAGICSECURE) {
-		bcmgenet_umac_writel(priv, get_unaligned_be16(&wol->sopass[0]),
-				     UMAC_MPD_PW_MS);
-		bcmgenet_umac_writel(priv, get_unaligned_be32(&wol->sopass[2]),
-				     UMAC_MPD_PW_LS);
-		reg |= MPD_PW_EN;
-	} else {
-		reg &= ~MPD_PW_EN;
-	}
-	bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL);
+	if (wol->wolopts & WAKE_MAGICSECURE)
+		memcpy(priv->sopass, wol->sopass, sizeof(priv->sopass));
 
 	/* Flag the device and relevant IRQ as wakeup capable */
 	if (wol->wolopts) {
@@ -120,6 +112,14 @@
 	return retries;
 }
 
+static void bcmgenet_set_mpd_password(struct bcmgenet_priv *priv)
+{
+	bcmgenet_umac_writel(priv, get_unaligned_be16(&priv->sopass[0]),
+			     UMAC_MPD_PW_MS);
+	bcmgenet_umac_writel(priv, get_unaligned_be32(&priv->sopass[2]),
+			     UMAC_MPD_PW_LS);
+}
+
 int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
 				enum bcmgenet_power_mode mode)
 {
@@ -132,21 +132,31 @@
 		return -EINVAL;
 	}
 
-	/* disable RX */
+	/* Can't suspend with WoL if MAC is still in reset */
+	spin_lock_bh(&priv->reg_lock);
 	reg = bcmgenet_umac_readl(priv, UMAC_CMD);
+	if (reg & CMD_SW_RESET)
+		reg &= ~CMD_SW_RESET;
+
+	/* disable RX */
 	reg &= ~CMD_RX_EN;
 	bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+	spin_unlock_bh(&priv->reg_lock);
 	mdelay(10);
 
 	reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL);
 	reg |= MPD_EN;
+	if (priv->wolopts & WAKE_MAGICSECURE) {
+		bcmgenet_set_mpd_password(priv);
+		reg |= MPD_PW_EN;
+	}
 	bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL);
 
 	/* Do not leave UniMAC in MPD mode only */
 	retries = bcmgenet_poll_wol_status(priv);
 	if (retries < 0) {
 		reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL);
-		reg &= ~MPD_EN;
+		reg &= ~(MPD_EN | MPD_PW_EN);
 		bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL);
 		return retries;
 	}
@@ -155,6 +165,7 @@
 		  retries);
 
 	/* Enable CRC forward */
+	spin_lock_bh(&priv->reg_lock);
 	reg = bcmgenet_umac_readl(priv, UMAC_CMD);
 	priv->crc_fwd_en = 1;
 	reg |= CMD_CRC_FWD;
@@ -162,12 +173,7 @@
 	/* Receiver must be enabled for WOL MP detection */
 	reg |= CMD_RX_EN;
 	bcmgenet_umac_writel(priv, reg, UMAC_CMD);
-
-	if (priv->hw_params->flags & GENET_HAS_EXT) {
-		reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT);
-		reg &= ~EXT_ENERGY_DET_MASK;
-		bcmgenet_ext_writel(priv, reg, EXT_EXT_PWR_MGMT);
-	}
+	spin_unlock_bh(&priv->reg_lock);
 
 	return 0;
 }
@@ -185,12 +191,14 @@
 	reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL);
 	if (!(reg & MPD_EN))
 		return;	/* already powered up so skip the rest */
-	reg &= ~MPD_EN;
+	reg &= ~(MPD_EN | MPD_PW_EN);
 	bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL);
 
 	/* Disable CRC Forward */
+	spin_lock_bh(&priv->reg_lock);
 	reg = bcmgenet_umac_readl(priv, UMAC_CMD);
 	reg &= ~CMD_CRC_FWD;
 	bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+	spin_unlock_bh(&priv->reg_lock);
 	priv->crc_fwd_en = 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/broadcom/genet/bcmmii.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/broadcom/genet/bcmmii.c
@@ -25,6 +25,7 @@
 
 #include "bcmgenet.h"
 
+
 /* setup netdev link state when PHY link status change and
  * update UMAC and RGMII block when link up
  */
@@ -90,12 +91,25 @@
 		reg |= RGMII_LINK;
 		bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL);
 
+		spin_lock_bh(&priv->reg_lock);
 		reg = bcmgenet_umac_readl(priv, UMAC_CMD);
 		reg &= ~((CMD_SPEED_MASK << CMD_SPEED_SHIFT) |
 			       CMD_HD_EN |
 			       CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE);
 		reg |= cmd_bits;
+		if (reg & CMD_SW_RESET) {
+			reg &= ~CMD_SW_RESET;
+			bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+			udelay(2);
+			reg |= CMD_TX_EN | CMD_RX_EN;
+		}
 		bcmgenet_umac_writel(priv, reg, UMAC_CMD);
+		spin_unlock_bh(&priv->reg_lock);
+
+		priv->eee.eee_active = phy_init_eee(phydev, 0) >= 0;
+		bcmgenet_eee_enable_set(dev,
+					priv->eee.eee_enabled && priv->eee.eee_active,
+					priv->eee.tx_lpi_enabled);
 	} else {
 		/* done if nothing has changed */
 		if (!status_changed)
@@ -181,38 +195,8 @@
 	const char *phy_name = NULL;
 	u32 id_mode_dis = 0;
 	u32 port_ctrl;
-	int bmcr = -1;
-	int ret;
 	u32 reg;
 
-	/* MAC clocking workaround during reset of umac state machines */
-	reg = bcmgenet_umac_readl(priv, UMAC_CMD);
-	if (reg & CMD_SW_RESET) {
-		/* An MII PHY must be isolated to prevent TXC contention */
-		if (priv->phy_interface == PHY_INTERFACE_MODE_MII) {
-			ret = phy_read(phydev, MII_BMCR);
-			if (ret >= 0) {
-				bmcr = ret;
-				ret = phy_write(phydev, MII_BMCR,
-						bmcr | BMCR_ISOLATE);
-			}
-			if (ret) {
-				netdev_err(dev, "failed to isolate PHY\n");
-				return ret;
-			}
-		}
-		/* Switch MAC clocking to RGMII generated clock */
-		bcmgenet_sys_writel(priv, PORT_MODE_EXT_GPHY, SYS_PORT_CTRL);
-		/* Ensure 5 clks with Rx disabled
-		 * followed by 5 clks with Reset asserted
-		 */
-		udelay(4);
-		reg &= ~(CMD_SW_RESET | CMD_LCL_LOOP_EN);
-		bcmgenet_umac_writel(priv, reg, UMAC_CMD);
-		/* Ensure 5 more clocks before Rx is enabled */
-		udelay(2);
-	}
-
 	priv->ext_phy = !priv->internal_phy &&
 			(priv->phy_interface != PHY_INTERFACE_MODE_MOCA);
 
@@ -244,9 +228,6 @@
 		phy_set_max_speed(phydev, SPEED_100);
 		bcmgenet_sys_writel(priv,
 				    PORT_MODE_EXT_EPHY, SYS_PORT_CTRL);
-		/* Restore the MII PHY after isolation */
-		if (bmcr >= 0)
-			phy_write(phydev, MII_BMCR, bmcr);
 		break;
 
 	case PHY_INTERFACE_MODE_REVMII:
@@ -290,6 +271,7 @@
 	 * block for the interface to work
 	 */
 	if (priv->ext_phy) {
+		mutex_lock(&phydev->lock);
 		reg = bcmgenet_ext_readl(priv, EXT_RGMII_OOB_CTRL);
 		reg |= id_mode_dis;
 		if (GENET_IS_V1(priv) || GENET_IS_V2(priv) || GENET_IS_V3(priv))
@@ -297,6 +279,7 @@
 		else
 			reg |= RGMII_MODE_EN;
 		bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL);
+		mutex_unlock(&phydev->lock);
 	}
 
 	if (init)
@@ -426,6 +409,10 @@
 	int id, ret;
 
 	pres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!pres) {
+		dev_err(&pdev->dev, "Invalid resource\n");
+		return -EINVAL;
+	}
 	memset(&res, 0, sizeof(res));
 	memset(&ppd, 0, sizeof(ppd));
 
@@ -561,7 +548,7 @@
 		};
 
 		phydev = fixed_phy_register(PHY_POLL, &fphy_status, NULL);
-		if (!phydev || IS_ERR(phydev)) {
+		if (IS_ERR(phydev)) {
 			dev_err(kdev, "failed to register fixed PHY device\n");
 			return -ENODEV;
 		}
@@ -614,5 +601,7 @@
 	if (of_phy_is_fixed_link(dn))
 		of_phy_deregister_fixed_link(dn);
 	of_node_put(priv->phy_dn);
+	clk_prepare_enable(priv->clk);
 	platform_device_unregister(priv->mii_pdev);
+	clk_disable_unprepare(priv->clk);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/broadcom/tg3.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/broadcom/tg3.c
@@ -55,6 +55,7 @@
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
 #include <linux/crc32poly.h>
+#include <linux/dmi.h>
 
 #include <net/checksum.h>
 #include <net/ip.h>
@@ -230,6 +231,7 @@
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_MODULE_VERSION);
 MODULE_FIRMWARE(FIRMWARE_TG3);
+MODULE_FIRMWARE(FIRMWARE_TG357766);
 MODULE_FIRMWARE(FIRMWARE_TG3TSO);
 MODULE_FIRMWARE(FIRMWARE_TG3TSO5);
 
@@ -6459,6 +6461,14 @@
 	int i;
 	u32 *regs;
 
+	/* If it is a PCI error, all registers will be 0xffff,
+	 * we don't dump them out, just report the error and return
+	 */
+	if (tp->pdev->error_state != pci_channel_io_normal) {
+		netdev_err(tp->dev, "PCI channel ERROR!\n");
+		return;
+	}
+
 	regs = kzalloc(TG3_REG_BLK_SIZE, GFP_ATOMIC);
 	if (!regs)
 		return;
@@ -6869,7 +6879,7 @@
 				       desc_idx, *post_ptr);
 		drop_it_no_recycle:
 			/* Other statistics kept track of by card. */
-			tp->rx_dropped++;
+			tnapi->rx_dropped++;
 			goto next_pkt;
 		}
 
@@ -7227,8 +7237,8 @@
 
 static inline void tg3_reset_task_cancel(struct tg3 *tp)
 {
-	cancel_work_sync(&tp->reset_task);
-	tg3_flag_clear(tp, RESET_TASK_PENDING);
+	if (test_and_clear_bit(TG3_FLAG_RESET_TASK_PENDING, tp->tg3_flags))
+		cancel_work_sync(&tp->reset_task);
 	tg3_flag_clear(tp, TX_RECOVERY_PENDING);
 }
 
@@ -7895,8 +7905,10 @@
 
 	segs = skb_gso_segment(skb, tp->dev->features &
 				    ~(NETIF_F_TSO | NETIF_F_TSO6));
-	if (IS_ERR(segs) || !segs)
+	if (IS_ERR(segs) || !segs) {
+		tnapi->tx_dropped++;
 		goto tg3_tso_bug_end;
+	}
 
 	do {
 		nskb = segs;
@@ -8168,7 +8180,7 @@
 drop:
 	dev_kfree_skb_any(skb);
 drop_nofree:
-	tp->tx_dropped++;
+	tnapi->tx_dropped++;
 	return NETDEV_TX_OK;
 }
 
@@ -9347,7 +9359,7 @@
 /* tp->lock is held. */
 static int tg3_halt(struct tg3 *tp, int kind, bool silent)
 {
-	int err;
+	int err, i;
 
 	tg3_stop_fw(tp);
 
@@ -9368,6 +9380,13 @@
 
 		/* And make sure the next sample is new data */
 		memset(tp->hw_stats, 0, sizeof(struct tg3_hw_stats));
+
+		for (i = 0; i < TG3_IRQ_MAX_VECS; ++i) {
+			struct tg3_napi *tnapi = &tp->napi[i];
+
+			tnapi->rx_dropped = 0;
+			tnapi->tx_dropped = 0;
+		}
 	}
 
 	return err;
@@ -11195,7 +11214,8 @@
 	rtnl_lock();
 	tg3_full_lock(tp, 0);
 
-	if (!netif_running(tp->dev)) {
+	if (tp->pcierr_recovery || !netif_running(tp->dev) ||
+	    tp->pdev->error_state != pci_channel_io_normal) {
 		tg3_flag_clear(tp, RESET_TASK_PENDING);
 		tg3_full_unlock(tp);
 		rtnl_unlock();
@@ -11219,18 +11239,27 @@
 
 	tg3_halt(tp, RESET_KIND_SHUTDOWN, 0);
 	err = tg3_init_hw(tp, true);
-	if (err)
+	if (err) {
+		tg3_full_unlock(tp);
+		tp->irq_sync = 0;
+		tg3_napi_enable(tp);
+		/* Clear this flag so that tg3_reset_task_cancel() will not
+		 * call cancel_work_sync() and wait forever.
+		 */
+		tg3_flag_clear(tp, RESET_TASK_PENDING);
+		dev_close(tp->dev);
 		goto out;
+	}
 
 	tg3_netif_start(tp);
 
-out:
 	tg3_full_unlock(tp);
 
 	if (!err)
 		tg3_phy_start(tp);
 
 	tg3_flag_clear(tp, RESET_TASK_PENDING);
+out:
 	rtnl_unlock();
 }
 
@@ -11915,6 +11944,9 @@
 {
 	struct rtnl_link_stats64 *old_stats = &tp->net_stats_prev;
 	struct tg3_hw_stats *hw_stats = tp->hw_stats;
+	unsigned long rx_dropped;
+	unsigned long tx_dropped;
+	int i;
 
 	stats->rx_packets = old_stats->rx_packets +
 		get_stat64(&hw_stats->rx_ucast_packets) +
@@ -11961,8 +11993,26 @@
 	stats->rx_missed_errors = old_stats->rx_missed_errors +
 		get_stat64(&hw_stats->rx_discards);
 
-	stats->rx_dropped = tp->rx_dropped;
-	stats->tx_dropped = tp->tx_dropped;
+	/* Aggregate per-queue counters. The per-queue counters are updated
+	 * by a single writer, race-free. The result computed by this loop
+	 * might not be 100% accurate (counters can be updated in the middle of
+	 * the loop) but the next tg3_get_nstats() will recompute the current
+	 * value so it is acceptable.
+	 *
+	 * Note that these counters wrap around at 4G on 32bit machines.
+	 */
+	rx_dropped = (unsigned long)(old_stats->rx_dropped);
+	tx_dropped = (unsigned long)(old_stats->tx_dropped);
+
+	for (i = 0; i < tp->irq_cnt; i++) {
+		struct tg3_napi *tnapi = &tp->napi[i];
+
+		rx_dropped += tnapi->rx_dropped;
+		tx_dropped += tnapi->tx_dropped;
+	}
+
+	stats->rx_dropped = rx_dropped;
+	stats->tx_dropped = tx_dropped;
 }
 
 static int tg3_get_regs_len(struct net_device *dev)
@@ -17766,6 +17816,9 @@
 	} else
 		persist_dma_mask = dma_mask = DMA_BIT_MASK(64);
 
+	if (tg3_asic_rev(tp) == ASIC_REV_57766)
+		persist_dma_mask = DMA_BIT_MASK(31);
+
 	/* Configure DMA attributes. */
 	if (dma_mask > DMA_BIT_MASK(32)) {
 		err = pci_set_dma_mask(pdev, dma_mask);
@@ -18140,12 +18193,59 @@
 
 static SIMPLE_DEV_PM_OPS(tg3_pm_ops, tg3_suspend, tg3_resume);
 
+/* Systems where ACPI _PTS (Prepare To Sleep) S5 will result in a fatal
+ * PCIe AER event on the tg3 device if the tg3 device is not, or cannot
+ * be, powered down.
+ */
+static const struct dmi_system_id tg3_restart_aer_quirk_table[] = {
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R440"),
+		},
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R540"),
+		},
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R640"),
+		},
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R650"),
+		},
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R740"),
+		},
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R750"),
+		},
+	},
+	{}
+};
+
 static void tg3_shutdown(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct tg3 *tp = netdev_priv(dev);
 
+	tg3_reset_task_cancel(tp);
+
 	rtnl_lock();
+
 	netif_device_detach(dev);
 
 	if (netif_running(dev))
@@ -18153,8 +18253,23 @@
 
 	if (system_state == SYSTEM_POWER_OFF)
 		tg3_power_down(tp);
+	else if (system_state == SYSTEM_RESTART &&
+		 dmi_first_match(tg3_restart_aer_quirk_table) &&
+		 pdev->current_state != PCI_D3cold &&
+		 pdev->current_state != PCI_UNKNOWN) {
+		/* Disable PCIe AER on the tg3 to avoid a fatal
+		 * error during this system restart.
+		 */
+		pcie_capability_clear_word(pdev, PCI_EXP_DEVCTL,
+					   PCI_EXP_DEVCTL_CERE |
+					   PCI_EXP_DEVCTL_NFERE |
+					   PCI_EXP_DEVCTL_FERE |
+					   PCI_EXP_DEVCTL_URRE);
+	}
 
 	rtnl_unlock();
+
+	pci_disable_device(pdev);
 }
 
 /**
@@ -18174,10 +18289,13 @@
 
 	netdev_info(netdev, "PCI I/O error detected\n");
 
+	/* Want to make sure that the reset task doesn't run */
+	tg3_reset_task_cancel(tp);
+
 	rtnl_lock();
 
-	/* We probably don't have netdev yet */
-	if (!netdev || !netif_running(netdev))
+	/* Could be second call or maybe we don't have netdev yet */
+	if (!netdev || tp->pcierr_recovery || !netif_running(netdev))
 		goto done;
 
 	/* We needn't recover from permanent error */
@@ -18190,9 +18308,6 @@
 
 	tg3_timer_stop(tp);
 
-	/* Want to make sure that the reset task doesn't run */
-	tg3_reset_task_cancel(tp);
-
 	netif_device_detach(netdev);
 
 	/* Clean up software state, even if MMIO is blocked */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/broadcom/tg3.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/broadcom/tg3.h
@@ -3018,6 +3018,7 @@
 	u16				*rx_rcb_prod_idx;
 	struct tg3_rx_prodring_set	prodring;
 	struct tg3_rx_buffer_desc	*rx_rcb;
+	unsigned long			rx_dropped;
 
 	u32				tx_prod	____cacheline_aligned;
 	u32				tx_cons;
@@ -3026,6 +3027,7 @@
 	u32				prodmbox;
 	struct tg3_tx_buffer_desc	*tx_ring;
 	struct tg3_tx_ring_info		*tx_buffers;
+	unsigned long			tx_dropped;
 
 	dma_addr_t			status_mapping;
 	dma_addr_t			rx_rcb_mapping;
@@ -3219,8 +3221,6 @@
 
 
 	/* begin "everything else" cacheline(s) section */
-	unsigned long			rx_dropped;
-	unsigned long			tx_dropped;
 	struct rtnl_link_stats64	net_stats_prev;
 	struct tg3_ethtool_stats	estats_prev;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/brocade/bna/bna_types.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/brocade/bna/bna_types.h
@@ -410,7 +410,7 @@
 /* Tx object */
 
 /* Tx datapath control structure */
-#define BNA_Q_NAME_SIZE		16
+#define BNA_Q_NAME_SIZE		(IFNAMSIZ + 6)
 struct bna_tcb {
 	/* Fast path */
 	void			**sw_qpt;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/brocade/bna/bnad.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/brocade/bna/bnad.c
@@ -1535,8 +1535,9 @@
 
 	for (i = 0; i < num_txqs; i++) {
 		vector_num = tx_info->tcb[i]->intr_vector;
-		sprintf(tx_info->tcb[i]->name, "%s TXQ %d", bnad->netdev->name,
-				tx_id + tx_info->tcb[i]->id);
+		snprintf(tx_info->tcb[i]->name, BNA_Q_NAME_SIZE, "%s TXQ %d",
+			 bnad->netdev->name,
+			 tx_id + tx_info->tcb[i]->id);
 		err = request_irq(bnad->msix_table[vector_num].vector,
 				  (irq_handler_t)bnad_msix_tx, 0,
 				  tx_info->tcb[i]->name,
@@ -1586,9 +1587,9 @@
 
 	for (i = 0; i < num_rxps; i++) {
 		vector_num = rx_info->rx_ctrl[i].ccb->intr_vector;
-		sprintf(rx_info->rx_ctrl[i].ccb->name, "%s CQ %d",
-			bnad->netdev->name,
-			rx_id + rx_info->rx_ctrl[i].ccb->id);
+		snprintf(rx_info->rx_ctrl[i].ccb->name, BNA_Q_NAME_SIZE,
+			 "%s CQ %d", bnad->netdev->name,
+			 rx_id + rx_info->rx_ctrl[i].ccb->id);
 		err = request_irq(bnad->msix_table[vector_num].vector,
 				  (irq_handler_t)bnad_msix_rx, 0,
 				  rx_info->rx_ctrl[i].ccb->name,
@@ -3282,7 +3283,7 @@
 {
 	int err, mtu;
 	struct bnad *bnad = netdev_priv(netdev);
-	u32 rx_count = 0, frame, new_frame;
+	u32 frame, new_frame;
 
 	mutex_lock(&bnad->conf_mutex);
 
@@ -3298,12 +3299,9 @@
 		/* only when transition is over 4K */
 		if ((frame <= 4096 && new_frame > 4096) ||
 		    (frame > 4096 && new_frame <= 4096))
-			rx_count = bnad_reinit_rx(bnad);
+			bnad_reinit_rx(bnad);
 	}
 
-	/* rx_count > 0 - new rx created
-	 *	- Linux set err = 0 and return
-	 */
 	err = bnad_mtu_set(bnad, new_frame);
 	if (err)
 		err = -EBUSY;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/brocade/bna/bnad_debugfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/brocade/bna/bnad_debugfs.c
@@ -312,7 +312,7 @@
 	void *kern_buf;
 
 	/* Copy the user space buf */
-	kern_buf = memdup_user(buf, nbytes);
+	kern_buf = memdup_user_nul(buf, nbytes);
 	if (IS_ERR(kern_buf))
 		return PTR_ERR(kern_buf);
 
@@ -372,7 +372,7 @@
 	void *kern_buf;
 
 	/* Copy the user space buf */
-	kern_buf = memdup_user(buf, nbytes);
+	kern_buf = memdup_user_nul(buf, nbytes);
 	if (IS_ERR(kern_buf))
 		return PTR_ERR(kern_buf);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/cadence/macb.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/cadence/macb.h
@@ -79,6 +79,7 @@
 #define GEM_NCFGR		0x0004 /* Network Config */
 #define GEM_USRIO		0x000c /* User IO */
 #define GEM_DMACFG		0x0010 /* DMA Configuration */
+#define GEM_PBUFRXCUT		0x0044 /* RX Partial Store and Forward */
 #define GEM_JML			0x0048 /* Jumbo Max Length */
 #define GEM_HRB			0x0080 /* Hash Bottom */
 #define GEM_HRT			0x0084 /* Hash Top */
@@ -90,6 +91,9 @@
 #define GEM_SA3T		0x009C /* Specific3 Top */
 #define GEM_SA4B		0x00A0 /* Specific4 Bottom */
 #define GEM_SA4T		0x00A4 /* Specific4 Top */
+#define GEM_WOL			0x00B8 /* Wake on LAN */
+#define GEM_RXPTPUNI		0x00D4 /* PTP RX Unicast address */
+#define GEM_TXPTPUNI		0x00D8 /* PTP TX Unicast address */
 #define GEM_EFTSH		0x00e8 /* PTP Event Frame Transmitted Seconds Register 47:32 */
 #define GEM_EFRSH		0x00ec /* PTP Event Frame Received Seconds Register 47:32 */
 #define GEM_PEFTSH		0x00f0 /* PTP Peer Event Frame Transmitted Seconds Register 47:32 */
@@ -155,6 +159,7 @@
 #define GEM_PEFTN		0x01f4 /* PTP Peer Event Frame Tx Ns */
 #define GEM_PEFRSL		0x01f8 /* PTP Peer Event Frame Rx Sec Low */
 #define GEM_PEFRN		0x01fc /* PTP Peer Event Frame Rx Ns */
+#define GEM_PCSCNTRL		0x0200 /* PCS Control */
 #define GEM_DCFG1		0x0280 /* Design Config 1 */
 #define GEM_DCFG2		0x0284 /* Design Config 2 */
 #define GEM_DCFG3		0x0288 /* Design Config 3 */
@@ -227,6 +232,8 @@
 #define MACB_TZQ_OFFSET		12 /* Transmit zero quantum pause frame */
 #define MACB_TZQ_SIZE		1
 #define MACB_SRTSM_OFFSET	15
+#define MACB_PTPUNI_OFFSET			20
+#define MACB_PTPUNI_SIZE			1
 #define MACB_OSSMODE_OFFSET 24 /* Enable One Step Synchro Mode */
 #define MACB_OSSMODE_SIZE	1
 
@@ -314,6 +321,11 @@
 #define GEM_ADDR64_OFFSET	30 /* Address bus width - 64b or 32b */
 #define GEM_ADDR64_SIZE		1
 
+/* Bitfields in PBUFRXCUT */
+#define GEM_WTRMRK_OFFSET	0 /* Watermark value offset */
+#define GEM_WTRMRK_SIZE		12
+#define GEM_ENCUTTHRU_OFFSET	31 /* Enable RX partial store and forward */
+#define GEM_ENCUTTHRU_SIZE	1
 
 /* Bitfields in NSR */
 #define MACB_NSR_LINK_OFFSET	0 /* pcs_link_state */
@@ -376,7 +388,7 @@
 #define MACB_PFR_SIZE		1
 #define MACB_PTZ_OFFSET		13 /* Enable pause time zero interrupt */
 #define MACB_PTZ_SIZE		1
-#define MACB_WOL_OFFSET		14 /* Enable wake-on-lan interrupt */
+#define MACB_WOL_OFFSET		28 /* Enable WOL received interrupt */
 #define MACB_WOL_SIZE		1
 #define MACB_DRQFR_OFFSET	18 /* PTP Delay Request Frame Received */
 #define MACB_DRQFR_SIZE		1
@@ -455,6 +467,10 @@
 #define MACB_REV_OFFSET				0
 #define MACB_REV_SIZE				16
 
+/* Bitfields in PCSCNTRL */
+#define GEM_PCSAUTONEG_OFFSET			12
+#define GEM_PCSAUTONEG_SIZE			1
+
 /* Bitfields in DCFG1. */
 #define GEM_IRQCOR_OFFSET			23
 #define GEM_IRQCOR_SIZE				1
@@ -568,6 +584,9 @@
 #define GEM_T2OFST_OFFSET			0 /* offset value */
 #define GEM_T2OFST_SIZE				7
 
+/* Bitfields in queue pointer registers */
+#define GEM_RBQP_DISABLE	0x1
+
 /* Offset for screener type 2 compare values (T2CMPOFST).
  * Note the offset is applied after the specified point,
  * e.g. GEM_T2COMPOFST_ETYPE denotes the EtherType field, so an offset
@@ -645,6 +664,11 @@
 #define MACB_CAPS_GEM_HAS_PTP			0x00000040
 #define MACB_CAPS_BD_RD_PREFETCH		0x00000080
 #define MACB_CAPS_NEEDS_RSTONUBR		0x00000100
+#define MACB_CAPS_PCS				0x00000400
+#define MACB_CAPS_PARTIAL_STORE_FORWARD		0x00000800
+#define MACB_CAPS_WOL				0x00000200
+#define MACB_CAPS_NEED_TSUCLK			0x00001000
+#define MACB_CAPS_QUEUE_DISABLE			0x00002000
 #define MACB_CAPS_FIFO_MODE			0x10000000
 #define MACB_CAPS_GIGABIT_MODE_AVAILABLE	0x20000000
 #define MACB_CAPS_SG_DISABLED			0x40000000
@@ -1160,6 +1184,7 @@
 	u32	(*macb_reg_readl)(struct macb *bp, int offset);
 	void	(*macb_reg_writel)(struct macb *bp, int offset, u32 value);
 
+	struct macb_dma_desc	*rx_ring_tieoff;
 	size_t			rx_buffer_size;
 
 	unsigned int		rx_ring_size;
@@ -1177,11 +1202,15 @@
 	struct clk		*rx_clk;
 	struct clk		*tsu_clk;
 	struct net_device	*dev;
+	/* Protects hw_stats and ethtool_stats */
+	spinlock_t		stats_lock;
 	union {
 		struct macb_stats	macb;
 		struct gem_stats	gem;
 	}			hw_stats;
 
+	dma_addr_t		rx_ring_tieoff_dma;
+
 	struct macb_or_gem_ops	macbgem_ops;
 
 	struct mii_bus		*mii_bus;
@@ -1208,6 +1237,9 @@
 
 	u32			wol;
 
+	/* holds value of rx watermark value for pbuf_rxcutthru register */
+	u16			rx_watermark;
+
 	struct macb_ptp_info	*ptp_info;	/* macb-ptp interface */
 #ifdef MACB_EXT_DESC
 	uint8_t hw_dma_cap;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/cadence/macb_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/cadence/macb_main.c
@@ -36,6 +36,8 @@
 #include <linux/tcp.h>
 #include <linux/iopoll.h>
 #include <linux/pm_runtime.h>
+#include <linux/crc32.h>
+#include <linux/inetdevice.h>
 #include "macb.h"
 
 /* This structure is only used for MACB on SiFive FU540 devices */
@@ -73,19 +75,15 @@
 /* Max length of transmit frame must be a multiple of 8 bytes */
 #define MACB_TX_LEN_ALIGN	8
 #define MACB_MAX_TX_LEN		((unsigned int)((1 << MACB_TX_FRMLEN_SIZE) - 1) & ~((unsigned int)(MACB_TX_LEN_ALIGN - 1)))
-#define GEM_MAX_TX_LEN		((unsigned int)((1 << GEM_TX_FRMLEN_SIZE) - 1) & ~((unsigned int)(MACB_TX_LEN_ALIGN - 1)))
+#define GEM_MAX_TX_LEN		(unsigned int)(0x3FC0)
 
 #define GEM_MTU_MIN_SIZE	ETH_MIN_MTU
 #define MACB_NETIF_LSO		NETIF_F_TSO
 
-#define MACB_WOL_HAS_MAGIC_PACKET	(0x1 << 0)
-#define MACB_WOL_ENABLED		(0x1 << 1)
-
 /* Graceful stop timeouts in us. We should allow up to
  * 1 frame time (10 Mbits/s, full-duplex, ignoring collisions)
  */
-#define MACB_HALT_TIMEOUT	1230
-
+#define MACB_HALT_TIMEOUT	14000
 #define MACB_PM_TIMEOUT  100 /* ms */
 
 #define MACB_MDIO_TIMEOUT	1000000 /* in usecs */
@@ -278,6 +276,9 @@
 	top = cpu_to_le16(*((u16 *)(bp->dev->dev_addr + 4)));
 	macb_or_gem_writel(bp, SA1T, top);
 
+	gem_writel(bp, RXPTPUNI, bottom);
+	gem_writel(bp, TXPTPUNI, bottom);
+
 	/* Clear unused address register sets */
 	macb_or_gem_writel(bp, SA2B, 0);
 	macb_or_gem_writel(bp, SA2T, 0);
@@ -330,8 +331,10 @@
 	int status;
 
 	status = pm_runtime_get_sync(&bp->pdev->dev);
-	if (status < 0)
+	if (status < 0) {
+		pm_runtime_put_noidle(&bp->pdev->dev);
 		goto mdio_pm_exit;
+	}
 
 	status = macb_mdio_wait_for_idle(bp);
 	if (status < 0)
@@ -363,8 +366,10 @@
 	int status;
 
 	status = pm_runtime_get_sync(&bp->pdev->dev);
-	if (status < 0)
+	if (status < 0) {
+		pm_runtime_put_noidle(&bp->pdev->dev);
 		goto mdio_pm_exit;
+	}
 
 	status = macb_mdio_wait_for_idle(bp);
 	if (status < 0)
@@ -575,7 +580,7 @@
 
 static int macb_mii_init(struct macb *bp)
 {
-	struct device_node *np;
+	struct device_node *np, *mdio_np;
 	int err = -ENXIO;
 
 	/* Enable management port */
@@ -593,12 +598,18 @@
 	snprintf(bp->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
 		 bp->pdev->name, bp->pdev->id);
 	bp->mii_bus->priv = bp;
-	bp->mii_bus->parent = &bp->pdev->dev;
+	bp->mii_bus->parent = &bp->dev->dev;
 
 	dev_set_drvdata(&bp->dev->dev, bp->mii_bus);
 
 	np = bp->pdev->dev.of_node;
-	if (np && of_phy_is_fixed_link(np)) {
+	mdio_np = of_get_child_by_name(np, "mdio");
+	if (mdio_np) {
+		of_node_put(mdio_np);
+		err = of_mdiobus_register(bp->mii_bus, mdio_np);
+		if (err)
+			goto err_out_free_mdiobus;
+	} else if (np && of_phy_is_fixed_link(np)) {
 		if (of_phy_register_fixed_link(np) < 0) {
 			dev_err(&bp->pdev->dev,
 				"broken fixed-link specification %pOF\n", np);
@@ -711,6 +722,10 @@
 	}
 #endif
 	addr |= MACB_BF(RX_WADDR, MACB_BFEXT(RX_WADDR, desc->addr));
+#ifdef CONFIG_MACB_USE_HWSTAMP
+	if (bp->hw_dma_cap & HW_DMA_CAP_PTP)
+		addr &= ~GEM_BIT(DMA_RXVALID);
+#endif
 	return addr;
 }
 
@@ -724,6 +739,7 @@
 	struct sk_buff		*skb;
 	unsigned int		tail;
 	unsigned long		flags;
+	bool			halt_timeout = false;
 
 	netdev_vdbg(bp->dev, "macb_tx_error_task: q = %u, t = %u, h = %u\n",
 		    (unsigned int)(queue - bp->queues),
@@ -744,9 +760,11 @@
 	 * (in case we have just queued new packets)
 	 * macb/gem must be halted to write TBQP register
 	 */
-	if (macb_halt_tx(bp))
-		/* Just complain for now, reinitializing TX path can be good */
+	if (macb_halt_tx(bp)) {
 		netdev_err(bp->dev, "BUG: halt tx timed out\n");
+		macb_writel(bp, NCR, macb_readl(bp, NCR) & (~MACB_BIT(TE)));
+		halt_timeout = true;
+	}
 
 	/* Treat frames in TX queue including the ones that caused the error.
 	 * Free transmit buffers in upper layer.
@@ -817,6 +835,9 @@
 	macb_writel(bp, TSR, macb_readl(bp, TSR));
 	queue_writel(queue, IER, MACB_TX_INT_FLAGS);
 
+	if (halt_timeout)
+		macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TE));
+
 	/* Now we are ready to start transmission again */
 	netif_tx_start_all_queues(bp->dev);
 	macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART));
@@ -919,7 +940,6 @@
 		/* Make hw descriptor updates visible to CPU */
 		rmb();
 
-		queue->rx_prepared_head++;
 		desc = macb_rx_desc(queue, entry);
 
 		if (!queue->rx_skbuff[entry]) {
@@ -958,6 +978,7 @@
 			dma_wmb();
 			desc->addr &= ~MACB_BIT(RX_USED);
 		}
+		queue->rx_prepared_head++;
 	}
 
 	/* Make descriptor updates visible to hardware */
@@ -988,6 +1009,15 @@
 	 */
 }
 
+static int macb_validate_hw_csum(struct sk_buff *skb)
+{
+	u32 pkt_csum = *((u32 *)&skb->data[skb->len - ETH_FCS_LEN]);
+	u32 csum  = ~crc32_le(~0, skb_mac_header(skb),
+			skb->len + ETH_HLEN - ETH_FCS_LEN);
+
+	return (pkt_csum != csum);
+}
+
 static int gem_rx(struct macb_queue *queue, struct napi_struct *napi,
 		  int budget)
 {
@@ -1049,6 +1079,16 @@
 				 bp->rx_buffer_size, DMA_FROM_DEVICE);
 
 		skb->protocol = eth_type_trans(skb, bp->dev);
+
+		/* Validate MAC fcs if RX checsum offload disabled */
+		if (!(bp->dev->features & NETIF_F_RXCSUM)) {
+			if (macb_validate_hw_csum(skb)) {
+				netdev_err(bp->dev, "incorrect FCS\n");
+				bp->dev->stats.rx_dropped++;
+				break;
+			}
+		}
+
 		skb_checksum_none_assert(skb);
 		if (bp->dev->features & NETIF_F_RXCSUM &&
 		    !(bp->dev->flags & IFF_PROMISC) &&
@@ -1146,6 +1186,19 @@
 			break;
 	}
 
+	/* Validate MAC fcs if RX checsum offload disabled */
+	if (!(bp->dev->features & NETIF_F_RXCSUM)) {
+		if (macb_validate_hw_csum(skb)) {
+			netdev_err(bp->dev, "incorrect FCS\n");
+			bp->dev->stats.rx_dropped++;
+
+			/* Make descriptor updates visible to hardware */
+			wmb();
+
+			return 1;
+		}
+	}
+
 	/* Make descriptor updates visible to hardware */
 	wmb();
 
@@ -1275,7 +1328,14 @@
 	if (work_done < budget) {
 		napi_complete_done(napi, work_done);
 
-		/* Packets received while interrupts were disabled */
+		/* RSR bits only seem to propagate to raise interrupts when
+		 * interrupts are enabled at the time, so if bits are already
+		 * set due to packets received while interrupts were disabled,
+		 * they will not cause another interrupt to be generated when
+		 * interrupts are re-enabled.
+		 * Check for this case here. This has been seen to happen
+		 * around 30% of the time under heavy network load.
+		 */
 		status = macb_readl(bp, RSR);
 		if (status) {
 			if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
@@ -1283,6 +1343,22 @@
 			napi_reschedule(napi);
 		} else {
 			queue_writel(queue, IER, bp->rx_intr_mask);
+
+			/* In rare cases, packets could have been received in
+			 * the window between the check above and re-enabling
+			 * interrupts. Therefore, a double-check is required
+			 * to avoid losing a wakeup. This can potentially race
+			 * with the interrupt handler doing the same actions
+			 * if an interrupt is raised just after enabling them,
+			 * but this should be harmless.
+			 */
+			status = macb_readl(bp, RSR);
+			if (unlikely(status)) {
+				queue_writel(queue, IDR, bp->rx_intr_mask);
+				if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
+					queue_writel(queue, ISR, MACB_BIT(RCOMP));
+				napi_schedule(napi);
+			}
 		}
 	}
 
@@ -1347,6 +1423,7 @@
 	unsigned int head = queue->tx_head;
 	unsigned int tail = queue->tx_tail;
 	struct macb *bp = queue->bp;
+	unsigned int head_idx, tbqp;
 
 	if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
 		queue_writel(queue, ISR, MACB_BIT(TXUBR));
@@ -1354,6 +1431,13 @@
 	if (head == tail)
 		return;
 
+	tbqp = queue_readl(queue, TBQP) / macb_dma_desc_get_size(bp);
+	tbqp = macb_adj_dma_desc_idx(bp, macb_tx_ring_wrap(bp, tbqp));
+	head_idx = macb_adj_dma_desc_idx(bp, macb_tx_ring_wrap(bp, head));
+
+	if (tbqp == head_idx)
+		return;
+
 	macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART));
 }
 
@@ -1372,6 +1456,12 @@
 	spin_lock(&bp->lock);
 
 	while (status) {
+		if (status & MACB_BIT(WOL)) {
+			if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
+				queue_writel(queue, ISR, MACB_BIT(WOL));
+			break;
+		}
+
 		/* close possible race with dev_close */
 		if (unlikely(!netif_running(dev))) {
 			queue_writel(queue, IDR, -1);
@@ -1440,10 +1530,12 @@
 
 		if (status & MACB_BIT(ISR_ROVR)) {
 			/* We missed at least one packet */
+			spin_lock(&bp->stats_lock);
 			if (macb_is_gem(bp))
 				bp->hw_stats.gem.rx_overruns++;
 			else
 				bp->hw_stats.macb.rx_overruns++;
+			spin_unlock(&bp->stats_lock);
 
 			if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
 				queue_writel(queue, ISR, MACB_BIT(ISR_ROVR));
@@ -1622,7 +1714,8 @@
 			ctrl |= MACB_BF(TX_LSO, lso_ctrl);
 			ctrl |= MACB_BF(TX_TCP_SEQ_SRC, seq_ctrl);
 			if ((bp->dev->features & NETIF_F_HW_CSUM) &&
-			    skb->ip_summed != CHECKSUM_PARTIAL && !lso_ctrl)
+			    skb->ip_summed != CHECKSUM_PARTIAL && !lso_ctrl &&
+			    (skb->data_len == 0))
 				ctrl |= MACB_BIT(TX_NOCRC);
 		} else
 			/* Only set MSS/MFS on payload descriptors
@@ -1665,15 +1758,13 @@
 	/* Validate LSO compatibility */
 
 	/* there is only one buffer */
-	if (!skb_is_nonlinear(skb))
+	if (!skb_is_nonlinear(skb) || (ip_hdr(skb)->protocol != IPPROTO_UDP))
 		return features;
 
 	/* length of header */
 	hdrlen = skb_transport_offset(skb);
-	if (ip_hdr(skb)->protocol == IPPROTO_TCP)
-		hdrlen += tcp_hdrlen(skb);
 
-	/* For LSO:
+	/* For UFO only:
 	 * When software supplies two or more payload buffers all payload buffers
 	 * apart from the last must be a multiple of 8 bytes in size.
 	 */
@@ -1712,25 +1803,24 @@
 
 static int macb_pad_and_fcs(struct sk_buff **skb, struct net_device *ndev)
 {
-	bool cloned = skb_cloned(*skb) || skb_header_cloned(*skb);
+	bool cloned = skb_cloned(*skb) || skb_header_cloned(*skb) ||
+		      skb_is_nonlinear(*skb);
 	int padlen = ETH_ZLEN - (*skb)->len;
-	int headroom = skb_headroom(*skb);
 	int tailroom = skb_tailroom(*skb);
 	struct sk_buff *nskb;
 	u32 fcs;
 
+	/* Not available for GSO and fragments */
 	if (!(ndev->features & NETIF_F_HW_CSUM) ||
 	    !((*skb)->ip_summed != CHECKSUM_PARTIAL) ||
-	    skb_shinfo(*skb)->gso_size)	/* Not available for GSO */
+	    skb_shinfo(*skb)->gso_size ||
+	    ((*skb)->data_len > 0))
 		return 0;
 
 	if (padlen <= 0) {
 		/* FCS could be appeded to tailroom. */
 		if (tailroom >= ETH_FCS_LEN)
 			goto add_fcs;
-		/* FCS could be appeded by moving data to headroom. */
-		else if (!cloned && headroom + tailroom >= ETH_FCS_LEN)
-			padlen = 0;
 		/* No room for FCS, need to reallocate skb. */
 		else
 			padlen = ETH_FCS_LEN;
@@ -1739,10 +1829,7 @@
 		padlen += ETH_FCS_LEN;
 	}
 
-	if (!cloned && headroom + tailroom >= padlen) {
-		(*skb)->data = memmove((*skb)->head, (*skb)->data, (*skb)->len);
-		skb_set_tail_pointer(*skb, (*skb)->len);
-	} else {
+	if (cloned || tailroom < padlen) {
 		nskb = skb_copy_expand(*skb, 0, padlen, GFP_ATOMIC);
 		if (!nskb)
 			return -ENOMEM;
@@ -1775,7 +1862,7 @@
 	unsigned long flags;
 	unsigned int desc_cnt, nr_frags, frag_size, f;
 	unsigned int hdrlen;
-	bool is_lso, is_udp = 0;
+	bool is_lso, is_udp = false;
 	netdev_tx_t ret = NETDEV_TX_OK;
 
 	if (macb_clear_csum(skb)) {
@@ -1937,6 +2024,12 @@
 
 	bp->macbgem_ops.mog_free_rx_buffers(bp);
 
+	if (bp->rx_ring_tieoff) {
+		dma_free_coherent(&bp->pdev->dev, macb_dma_desc_get_size(bp),
+				  bp->rx_ring_tieoff, bp->rx_ring_tieoff_dma);
+		bp->rx_ring_tieoff = NULL;
+	}
+
 	for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
 		kfree(queue->tx_skb);
 		queue->tx_skb = NULL;
@@ -2026,6 +2119,16 @@
 	if (bp->macbgem_ops.mog_alloc_rx_buffers(bp))
 		goto out_err;
 
+	/* Required for tie off descriptor for PM cases */
+	if (!(bp->caps & MACB_CAPS_QUEUE_DISABLE)) {
+		bp->rx_ring_tieoff = dma_alloc_coherent(&bp->pdev->dev,
+							macb_dma_desc_get_size(bp),
+							&bp->rx_ring_tieoff_dma,
+							GFP_KERNEL);
+		if (!bp->rx_ring_tieoff)
+			goto out_err;
+	}
+
 	return 0;
 
 out_err:
@@ -2033,6 +2136,19 @@
 	return -ENOMEM;
 }
 
+static void macb_init_tieoff(struct macb *bp)
+{
+	struct macb_dma_desc *d = bp->rx_ring_tieoff;
+
+	if (bp->num_queues > 1) {
+		/* Setup a wrapping descriptor with no free slots
+		 * (WRAP and USED) to tie off/disable unused RX queues.
+		 */
+		macb_set_addr(bp, d, MACB_BIT(RX_WRAP) | MACB_BIT(RX_USED));
+		d->ctrl = 0;
+	}
+}
+
 static void gem_init_rings(struct macb *bp)
 {
 	struct macb_queue *queue;
@@ -2056,6 +2172,9 @@
 		gem_rx_refill(queue);
 	}
 
+	if (!(bp->caps & MACB_CAPS_QUEUE_DISABLE))
+		macb_init_tieoff(bp);
+
 }
 
 static void macb_init_rings(struct macb *bp)
@@ -2073,6 +2192,8 @@
 	bp->queues[0].tx_head = 0;
 	bp->queues[0].tx_tail = 0;
 	desc->ctrl |= MACB_BIT(TX_WRAP);
+
+	macb_init_tieoff(bp);
 }
 
 static void macb_reset_hw(struct macb *bp)
@@ -2095,6 +2216,10 @@
 	macb_writel(bp, TSR, -1);
 	macb_writel(bp, RSR, -1);
 
+	/* Disable RX partial store and forward and reset watermark value */
+	if (bp->caps & MACB_CAPS_PARTIAL_STORE_FORWARD)
+		gem_writel(bp, PBUFRXCUT, 0xFFF);
+
 	/* Disable all interrupts */
 	for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
 		queue_writel(queue, IDR, -1);
@@ -2234,7 +2359,11 @@
 		config |= GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL);
 	config |= MACB_BF(RBOF, NET_IP_ALIGN);	/* Make eth data aligned */
 	config |= MACB_BIT(PAE);		/* PAuse Enable */
-	config |= MACB_BIT(DRFCS);		/* Discard Rx FCS */
+
+	/* Do not discard Rx FCS if RX checsum offload disabled */
+	if (bp->dev->features & NETIF_F_RXCSUM)
+		config |= MACB_BIT(DRFCS);		/* Discard Rx FCS */
+
 	if (bp->caps & MACB_CAPS_JUMBO)
 		config |= MACB_BIT(JFRAME);	/* Enable jumbo frames */
 	else
@@ -2250,13 +2379,24 @@
 	if ((bp->caps & MACB_CAPS_JUMBO) && bp->jumbo_max_len)
 		gem_writel(bp, JML, bp->jumbo_max_len);
 	bp->speed = SPEED_10;
-	bp->duplex = DUPLEX_HALF;
+	if (bp->caps & MACB_CAPS_PARTIAL_STORE_FORWARD)
+		bp->duplex = DUPLEX_FULL;
+	else
+		bp->duplex = DUPLEX_HALF;
 	bp->rx_frm_len_mask = MACB_RX_FRMLEN_MASK;
 	if (bp->caps & MACB_CAPS_JUMBO)
 		bp->rx_frm_len_mask = MACB_RX_JFRMLEN_MASK;
 
 	macb_configure_dma(bp);
 
+	/* Enable RX partial store and forward and set watermark */
+	if (bp->caps & MACB_CAPS_PARTIAL_STORE_FORWARD) {
+		gem_writel(bp, PBUFRXCUT,
+			   (gem_readl(bp, PBUFRXCUT) &
+			   GEM_BF(WTRMRK, bp->rx_watermark)) |
+			   GEM_BIT(ENCUTTHRU));
+	}
+
 	/* Initialize TX and RX buffers */
 	for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
 		queue_writel(queue, RBQP, lower_32_bits(queue->rx_ring_dma));
@@ -2277,8 +2417,14 @@
 			     MACB_BIT(HRESP));
 	}
 
+	if ((bp->phy_interface == PHY_INTERFACE_MODE_SGMII) &&
+	    (bp->caps & MACB_CAPS_PCS))
+		gem_writel(bp, PCSCNTRL,
+			   gem_readl(bp, PCSCNTRL) | GEM_BIT(PCSAUTONEG));
+
 	/* Enable TX and RX */
-	macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(RE) | MACB_BIT(TE));
+	macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(RE) | MACB_BIT(TE) |
+		    MACB_BIT(PTPUNI));
 }
 
 /* The hash address register is 64 bits long and takes up two
@@ -2439,6 +2585,12 @@
 	bp->macbgem_ops.mog_init_rings(bp);
 	macb_init_hw(bp);
 
+	/* Since this driver uses runtime handling of clocks, initiate a phy
+	 * reset if the attached phy requires it. Check return to see if phy
+	 * was reset and then do a phy initialization.
+	 */
+	if (phy_reset_after_clk_enable(dev->phydev) == 1)
+		phy_init_hw(dev->phydev);
 	/* schedule a link state check */
 	phy_start(dev->phydev);
 
@@ -2529,6 +2681,10 @@
 	struct gem_stats *hwstat = &bp->hw_stats.gem;
 	struct net_device_stats *nstat = &bp->dev->stats;
 
+	if (!netif_running(bp->dev))
+		return nstat;
+
+	spin_lock_irq(&bp->stats_lock);
 	gem_update_stats(bp);
 
 	nstat->rx_errors = (hwstat->rx_frame_check_sequence_errors +
@@ -2558,6 +2714,7 @@
 	nstat->tx_aborted_errors = hwstat->tx_excessive_collisions;
 	nstat->tx_carrier_errors = hwstat->tx_carrier_sense_errors;
 	nstat->tx_fifo_errors = hwstat->tx_underrun;
+	spin_unlock_irq(&bp->stats_lock);
 
 	return nstat;
 }
@@ -2565,12 +2722,13 @@
 static void gem_get_ethtool_stats(struct net_device *dev,
 				  struct ethtool_stats *stats, u64 *data)
 {
-	struct macb *bp;
+	struct macb *bp = netdev_priv(dev);
 
-	bp = netdev_priv(dev);
+	spin_lock_irq(&bp->stats_lock);
 	gem_update_stats(bp);
 	memcpy(data, &bp->ethtool_stats, sizeof(u64)
 			* (GEM_STATS_LEN + QUEUE_STATS_LEN * MACB_MAX_QUEUES));
+	spin_unlock_irq(&bp->stats_lock);
 }
 
 static int gem_get_sset_count(struct net_device *dev, int sset)
@@ -2620,6 +2778,7 @@
 		return gem_get_stats(bp);
 
 	/* read stats from hardware */
+	spin_lock_irq(&bp->stats_lock);
 	macb_update_stats(bp);
 
 	/* Convert HW stats into netdevice stats */
@@ -2653,6 +2812,7 @@
 	nstat->tx_carrier_errors = hwstat->tx_carrier_errors;
 	nstat->tx_fifo_errors = hwstat->tx_underruns;
 	/* Don't know about heartbeat or window errors... */
+	spin_unlock_irq(&bp->stats_lock);
 
 	return nstat;
 }
@@ -2702,11 +2862,11 @@
 	wol->supported = 0;
 	wol->wolopts = 0;
 
-	if (bp->wol & MACB_WOL_HAS_MAGIC_PACKET) {
-		wol->supported = WAKE_MAGIC;
+	if (bp->caps & MACB_CAPS_WOL) {
+		wol->supported = WAKE_ARP;
 
-		if (bp->wol & MACB_WOL_ENABLED)
-			wol->wolopts |= WAKE_MAGIC;
+		if (bp->wol)
+			wol->wolopts |= WAKE_ARP;
 	}
 }
 
@@ -2714,16 +2874,16 @@
 {
 	struct macb *bp = netdev_priv(netdev);
 
-	if (!(bp->wol & MACB_WOL_HAS_MAGIC_PACKET) ||
-	    (wol->wolopts & ~WAKE_MAGIC))
+	if (!(bp->caps & MACB_CAPS_WOL) ||
+	    (wol->wolopts & ~WAKE_ARP))
 		return -EOPNOTSUPP;
 
-	if (wol->wolopts & WAKE_MAGIC)
-		bp->wol |= MACB_WOL_ENABLED;
+	if (wol->wolopts & WAKE_ARP)
+		bp->wol = 1;
 	else
-		bp->wol &= ~MACB_WOL_ENABLED;
+		bp->wol = 0;
 
-	device_set_wakeup_enable(&bp->pdev->dev, bp->wol & MACB_WOL_ENABLED);
+	device_set_wakeup_enable(&bp->dev->dev, bp->wol);
 
 	return 0;
 }
@@ -2908,6 +3068,9 @@
 	bool cmp_b = false;
 	bool cmp_c = false;
 
+	if (!macb_is_gem(bp))
+		return;
+
 	tp4sp_v = &(fs->h_u.tcp_ip4_spec);
 	tp4sp_m = &(fs->m_u.tcp_ip4_spec);
 
@@ -3162,8 +3325,6 @@
 	.get_regs		= macb_get_regs,
 	.get_link		= ethtool_op_get_link,
 	.get_ts_info		= ethtool_op_get_ts_info,
-	.get_wol		= macb_get_wol,
-	.set_wol		= macb_set_wol,
 	.get_link_ksettings     = phy_ethtool_get_link_ksettings,
 	.set_link_ksettings     = phy_ethtool_set_link_ksettings,
 	.get_ringparam		= macb_get_ringparam,
@@ -3184,6 +3345,8 @@
 	.set_ringparam		= macb_set_ringparam,
 	.get_rxnfc			= gem_get_rxnfc,
 	.set_rxnfc			= gem_set_rxnfc,
+	.get_wol		= macb_get_wol,
+	.set_wol		= macb_set_wol,
 };
 
 static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
@@ -3279,6 +3442,7 @@
 {
 	struct net_device *netdev = bp->dev;
 	netdev_features_t features = netdev->features;
+	struct ethtool_rx_fs_item *item;
 
 	/* TX checksum offload */
 	macb_set_txcsum_feature(bp, features);
@@ -3287,6 +3451,9 @@
 	macb_set_rxcsum_feature(bp, features);
 
 	/* RX Flow Filters */
+	list_for_each_entry(item, &bp->rx_fs_list.list, list)
+		gem_prog_cmp_regs(bp, &item->fs);
+
 	macb_set_rxflow_feature(bp, features);
 }
 
@@ -3314,10 +3481,29 @@
 				const struct macb_config *dt_conf)
 {
 	u32 dcfg;
+	int retval;
 
 	if (dt_conf)
 		bp->caps = dt_conf->caps;
 
+	/* By default we set to partial store and forward mode for zynqmp.
+	 * Disable if not set in devicetree.
+	 */
+	if (bp->caps & MACB_CAPS_PARTIAL_STORE_FORWARD) {
+		retval = of_property_read_u16(bp->pdev->dev.of_node,
+					      "rx-watermark",
+					      &bp->rx_watermark);
+
+		/* Disable partial store and forward in case of error or
+		 * invalid watermark value
+		 */
+		if (retval || bp->rx_watermark > 0xFFF) {
+			dev_info(&bp->pdev->dev,
+				 "Not enabling partial store and forward\n");
+			bp->caps &= ~MACB_CAPS_PARTIAL_STORE_FORWARD;
+		}
+	}
+
 	if (hw_is_gem(bp->regs, bp->native_io)) {
 		bp->caps |= MACB_CAPS_MACB_IS_GEM;
 
@@ -3565,6 +3751,8 @@
 	/* Checksum offload is only available on gem with packet buffer */
 	if (macb_is_gem(bp) && !(bp->caps & MACB_CAPS_FIFO_MODE))
 		dev->hw_features |= NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
+	if (bp->caps & MACB_CAPS_PARTIAL_STORE_FORWARD)
+		dev->hw_features &= ~NETIF_F_RXCSUM;
 	if (bp->caps & MACB_CAPS_SG_DISABLED)
 		dev->hw_features &= ~NETIF_F_SG;
 	dev->features = dev->hw_features;
@@ -3576,6 +3764,7 @@
 	reg = gem_readl(bp, DCFG8);
 	bp->max_tuples = min((GEM_BFEXT(SCR2CMP, reg) / 3),
 			GEM_BFEXT(T2SCR, reg));
+	INIT_LIST_HEAD(&bp->rx_fs_list.list);
 	if (bp->max_tuples > 0) {
 		/* also needs one ethtype match to check IPv4 */
 		if (GEM_BFEXT(SCR2ETH, reg) > 0) {
@@ -3586,7 +3775,6 @@
 			/* Filtering is supported in hw but don't enable it in kernel now */
 			dev->hw_features |= NETIF_F_NTUPLE;
 			/* init Rx flow definitions */
-			INIT_LIST_HEAD(&bp->rx_fs_list.list);
 			bp->rx_fs_list.count = 0;
 			spin_lock_init(&bp->rx_fs_lock);
 		} else
@@ -3616,6 +3804,11 @@
 		val |= GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL);
 	macb_writel(bp, NCFGR, val);
 
+	if ((bp->phy_interface == PHY_INTERFACE_MODE_SGMII) &&
+	    (bp->caps & MACB_CAPS_PCS))
+		gem_writel(bp, PCSCNTRL,
+			   gem_readl(bp, PCSCNTRL) | GEM_BIT(PCSAUTONEG));
+
 	return 0;
 }
 
@@ -3688,6 +3881,12 @@
 	u32 ctl;
 	int ret;
 
+	ret = pm_runtime_get_sync(&lp->pdev->dev);
+	if (ret < 0) {
+		pm_runtime_put_noidle(&lp->pdev->dev);
+		return ret;
+	}
+
 	/* Clear internal statistics */
 	ctl = macb_readl(lp, NCR);
 	macb_writel(lp, NCR, ctl | MACB_BIT(CLRSTAT));
@@ -3696,7 +3895,7 @@
 
 	ret = at91ether_start(dev);
 	if (ret)
-		return ret;
+		goto pm_exit;
 
 	/* Enable MAC interrupts */
 	macb_writel(lp, IER, MACB_BIT(RCOMP)	|
@@ -3713,6 +3912,10 @@
 	netif_start_queue(dev);
 
 	return 0;
+
+pm_exit:
+	pm_runtime_put_sync(&lp->pdev->dev);
+	return ret;
 }
 
 /* Close the interface */
@@ -3748,7 +3951,7 @@
 			  q->rx_buffers, q->rx_buffers_dma);
 	q->rx_buffers = NULL;
 
-	return 0;
+	return pm_runtime_put(&lp->pdev->dev);
 }
 
 /* Transmit packet */
@@ -4027,7 +4230,7 @@
 	mgmt->rate = 0;
 	mgmt->hw.init = &init;
 
-	*tx_clk = clk_register(NULL, &mgmt->hw);
+	*tx_clk = devm_clk_register(&pdev->dev, &mgmt->hw);
 	if (IS_ERR(*tx_clk))
 		return PTR_ERR(*tx_clk);
 
@@ -4042,15 +4245,9 @@
 
 static int fu540_c000_init(struct platform_device *pdev)
 {
-	struct resource *res;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	if (!res)
-		return -ENODEV;
-
-	mgmt->reg = ioremap(res->start, resource_size(res));
-	if (!mgmt->reg)
-		return -ENOMEM;
+	mgmt->reg = devm_platform_ioremap_resource(pdev, 1);
+	if (IS_ERR(mgmt->reg))
+		return PTR_ERR(mgmt->reg);
 
 	return macb_init(pdev);
 }
@@ -4122,7 +4319,20 @@
 static const struct macb_config zynqmp_config = {
 	.caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE |
 			MACB_CAPS_JUMBO |
-			MACB_CAPS_GEM_HAS_PTP | MACB_CAPS_BD_RD_PREFETCH,
+			MACB_CAPS_GEM_HAS_PTP | MACB_CAPS_BD_RD_PREFETCH |
+			MACB_CAPS_PCS |
+		MACB_CAPS_PARTIAL_STORE_FORWARD | MACB_CAPS_WOL,
+	.dma_burst_length = 16,
+	.clk_init = macb_clk_init,
+	.init = macb_init,
+	.jumbo_max_len = 10240,
+};
+
+static const struct macb_config versal_config = {
+	.caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_JUMBO |
+		MACB_CAPS_GEM_HAS_PTP | MACB_CAPS_BD_RD_PREFETCH |
+		MACB_CAPS_PCS |	MACB_CAPS_PARTIAL_STORE_FORWARD |
+		MACB_CAPS_WOL | MACB_CAPS_NEED_TSUCLK | MACB_CAPS_QUEUE_DISABLE,
 	.dma_burst_length = 16,
 	.clk_init = macb_clk_init,
 	.init = macb_init,
@@ -4154,6 +4364,7 @@
 	{ .compatible = "cdns,zynqmp-gem", .data = &zynqmp_config},
 	{ .compatible = "cdns,zynq-gem", .data = &zynq_config },
 	{ .compatible = "sifive,fu540-c000-gem", .data = &fu540_c000_config },
+	{ .compatible = "cdns,versal-gem", .data = &versal_config},
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, macb_dt_ids);
@@ -4185,7 +4396,7 @@
 	struct net_device *dev;
 	struct resource *regs;
 	void __iomem *mem;
-	const char *mac;
+	const u8 *mac;
 	struct macb *bp;
 	int err, val;
 
@@ -4241,29 +4452,23 @@
 	}
 	bp->num_queues = num_queues;
 	bp->queue_mask = queue_mask;
-	if (macb_config)
-		bp->dma_burst_length = macb_config->dma_burst_length;
+	bp->dma_burst_length = macb_config->dma_burst_length;
 	bp->pclk = pclk;
 	bp->hclk = hclk;
 	bp->tx_clk = tx_clk;
 	bp->rx_clk = rx_clk;
 	bp->tsu_clk = tsu_clk;
-	if (macb_config)
-		bp->jumbo_max_len = macb_config->jumbo_max_len;
-
-	bp->wol = 0;
-	if (of_get_property(np, "magic-packet", NULL))
-		bp->wol |= MACB_WOL_HAS_MAGIC_PACKET;
-	device_init_wakeup(&pdev->dev, bp->wol & MACB_WOL_HAS_MAGIC_PACKET);
+	bp->jumbo_max_len = macb_config->jumbo_max_len;
 
 	spin_lock_init(&bp->lock);
+	spin_lock_init(&bp->stats_lock);
 
 	/* setup capabilities */
 	macb_configure_caps(bp, macb_config);
 
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
 	if (GEM_BFEXT(DAW64, gem_readl(bp, DCFG6))) {
-		dma_set_mask(&pdev->dev, DMA_BIT_MASK(44));
+		dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(39));
 		bp->hw_dma_cap |= HW_DMA_CAP_64B;
 	}
 #endif
@@ -4319,24 +4524,26 @@
 	err = init(pdev);
 	if (err)
 		goto err_out_free_netdev;
+	err = register_netdev(dev);
+	if (err) {
+		dev_err(&pdev->dev, "Cannot register net device, aborting.\n");
+		goto err_out_free_netdev;
+	}
 
 	err = macb_mii_init(bp);
 	if (err)
-		goto err_out_free_netdev;
+		goto err_out_unregister_netdev;
 
 	phydev = dev->phydev;
 
 	netif_carrier_off(dev);
 
-	err = register_netdev(dev);
-	if (err) {
-		dev_err(&pdev->dev, "Cannot register net device, aborting.\n");
-		goto err_out_unregister_mdio;
-	}
-
 	tasklet_init(&bp->hresp_err_tasklet, macb_hresp_error_task,
 		     (unsigned long)bp);
 
+	if (bp->caps & MACB_CAPS_WOL)
+		device_set_wakeup_capable(&pdev->dev, 1);
+
 	phy_attached_info(phydev);
 
 	netdev_info(dev, "Cadence %s rev 0x%08x at 0x%08lx irq %d (%pM)\n",
@@ -4348,20 +4555,14 @@
 
 	return 0;
 
-err_out_unregister_mdio:
-	phy_disconnect(dev->phydev);
-	mdiobus_unregister(bp->mii_bus);
-	of_node_put(bp->phy_node);
-	if (np && of_phy_is_fixed_link(np))
-		of_phy_deregister_fixed_link(np);
-	mdiobus_free(bp->mii_bus);
+err_out_unregister_netdev:
+	unregister_netdev(dev);
 
 err_out_free_netdev:
 	free_netdev(dev);
 
 err_disable_clocks:
 	clk_disable_unprepare(tx_clk);
-	clk_unregister(tx_clk);
 	clk_disable_unprepare(hclk);
 	clk_disable_unprepare(pclk);
 	clk_disable_unprepare(rx_clk);
@@ -4392,11 +4593,11 @@
 		mdiobus_free(bp->mii_bus);
 
 		unregister_netdev(dev);
+		tasklet_kill(&bp->hresp_err_tasklet);
 		pm_runtime_disable(&pdev->dev);
 		pm_runtime_dont_use_autosuspend(&pdev->dev);
 		if (!pm_runtime_suspended(&pdev->dev)) {
 			clk_disable_unprepare(bp->tx_clk);
-			clk_unregister(bp->tx_clk);
 			clk_disable_unprepare(bp->hclk);
 			clk_disable_unprepare(bp->pclk);
 			clk_disable_unprepare(bp->rx_clk);
@@ -4417,16 +4618,53 @@
 	struct macb_queue *queue = bp->queues;
 	unsigned long flags;
 	unsigned int q;
+	u32 ctrl, arpipmask;
 
 	if (!netif_running(netdev))
 		return 0;
 
+	if (device_may_wakeup(dev)) {
+		spin_lock_irqsave(&bp->lock, flags);
+		ctrl = macb_readl(bp, NCR);
+		ctrl &= ~(MACB_BIT(TE) | MACB_BIT(RE));
+		macb_writel(bp, NCR, ctrl);
+		/* Tie off RX queues */
+		for (q = 0, queue = bp->queues; q < bp->num_queues;
+		     ++q, ++queue) {
+			if (bp->caps & MACB_CAPS_QUEUE_DISABLE)
+				queue_writel(queue, RBQP, GEM_RBQP_DISABLE);
+			else
+				queue_writel(queue, RBQP,
+					     lower_32_bits(bp->rx_ring_tieoff_dma));
+		}
+		ctrl = macb_readl(bp, NCR);
+		ctrl |= MACB_BIT(RE);
+		macb_writel(bp, NCR, ctrl);
+		gem_writel(bp, NCFGR, gem_readl(bp, NCFGR) & ~MACB_BIT(NBC));
+		macb_writel(bp, TSR, -1);
+		macb_writel(bp, RSR, -1);
+		macb_readl(bp, ISR);
+		if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
+			macb_writel(bp, ISR, -1);
 
-	if (bp->wol & MACB_WOL_ENABLED) {
+		/* Enable WOL (Q0 only) and disable all other interrupts */
 		macb_writel(bp, IER, MACB_BIT(WOL));
-		macb_writel(bp, WOL, MACB_BIT(MAG));
+		for (q = 1, queue = bp->queues; q < bp->num_queues;
+		     ++q, ++queue) {
+			queue_writel(queue, IDR, bp->rx_intr_mask |
+						 MACB_TX_INT_FLAGS |
+						 MACB_BIT(HRESP));
+		}
+
+		arpipmask = cpu_to_be32p(&bp->dev->ip_ptr->ifa_list->ifa_local)
+					 & 0xFFFF;
+		gem_writel(bp, WOL, MACB_BIT(ARP) | arpipmask);
+		spin_unlock_irqrestore(&bp->lock, flags);
 		enable_irq_wake(bp->queues[0].irq);
 		netif_device_detach(netdev);
+		for (q = 0, queue = bp->queues; q < bp->num_queues;
+		     ++q, ++queue)
+			napi_disable(&queue->napi);
 	} else {
 		netif_device_detach(netdev);
 		for (q = 0, queue = bp->queues; q < bp->num_queues;
@@ -4445,10 +4683,10 @@
 			bp->pm_data.scrt2 = gem_readl_n(bp, ETHT, SCRT2_ETHT);
 	}
 
-	netif_carrier_off(netdev);
 	if (bp->ptp_info)
 		bp->ptp_info->ptp_remove(netdev);
-	pm_runtime_force_suspend(dev);
+	if (!device_may_wakeup(dev))
+		pm_runtime_force_suspend(dev);
 
 	return 0;
 }
@@ -4458,17 +4696,29 @@
 	struct net_device *netdev = dev_get_drvdata(dev);
 	struct macb *bp = netdev_priv(netdev);
 	struct macb_queue *queue = bp->queues;
+	unsigned long flags;
 	unsigned int q;
 
 	if (!netif_running(netdev))
 		return 0;
 
-	pm_runtime_force_resume(dev);
+	if (!device_may_wakeup(dev))
+		pm_runtime_force_resume(dev);
 
-	if (bp->wol & MACB_WOL_ENABLED) {
+	if (device_may_wakeup(dev)) {
+		spin_lock_irqsave(&bp->lock, flags);
 		macb_writel(bp, IDR, MACB_BIT(WOL));
-		macb_writel(bp, WOL, 0);
+		gem_writel(bp, WOL, 0);
+		/* Clear Q0 ISR as WOL was enabled on Q0 */
+		if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
+			macb_writel(bp, ISR, -1);
 		disable_irq_wake(bp->queues[0].irq);
+		spin_unlock_irqrestore(&bp->lock, flags);
+		macb_writel(bp, NCR, MACB_BIT(MPE));
+		for (q = 0, queue = bp->queues; q < bp->num_queues;
+		     ++q, ++queue)
+			napi_enable(&queue->napi);
+		netif_carrier_on(netdev);
 	} else {
 		macb_writel(bp, NCR, MACB_BIT(MPE));
 
@@ -4502,13 +4752,16 @@
 	struct net_device *netdev = dev_get_drvdata(dev);
 	struct macb *bp = netdev_priv(netdev);
 
-	if (!(device_may_wakeup(&bp->dev->dev))) {
+	if (!(device_may_wakeup(dev))) {
 		clk_disable_unprepare(bp->tx_clk);
 		clk_disable_unprepare(bp->hclk);
 		clk_disable_unprepare(bp->pclk);
 		clk_disable_unprepare(bp->rx_clk);
 	}
-	clk_disable_unprepare(bp->tsu_clk);
+
+	if (!(device_may_wakeup(dev) &&
+	      (bp->caps & MACB_CAPS_NEED_TSUCLK)))
+		clk_disable_unprepare(bp->tsu_clk);
 
 	return 0;
 }
@@ -4518,13 +4771,16 @@
 	struct net_device *netdev = dev_get_drvdata(dev);
 	struct macb *bp = netdev_priv(netdev);
 
-	if (!(device_may_wakeup(&bp->dev->dev))) {
+	if (!(device_may_wakeup(dev))) {
 		clk_prepare_enable(bp->pclk);
 		clk_prepare_enable(bp->hclk);
 		clk_prepare_enable(bp->tx_clk);
 		clk_prepare_enable(bp->rx_clk);
 	}
-	clk_prepare_enable(bp->tsu_clk);
+
+	if (!(device_may_wakeup(dev) &&
+	      (bp->caps & MACB_CAPS_NEED_TSUCLK)))
+		clk_prepare_enable(bp->tsu_clk);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/cadence/macb_pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/cadence/macb_pci.c
@@ -112,9 +112,9 @@
 	struct platform_device *plat_dev = pci_get_drvdata(pdev);
 	struct macb_platform_data *plat_data = dev_get_platdata(&plat_dev->dev);
 
-	platform_device_unregister(plat_dev);
 	clk_unregister(plat_data->pclk);
 	clk_unregister(plat_data->hclk);
+	platform_device_unregister(plat_dev);
 }
 
 static const struct pci_device_id dev_id_table[] = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/cadence/macb_ptp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/cadence/macb_ptp.c
@@ -242,6 +242,7 @@
 			    u32 dma_desc_ts_2, struct timespec64 *ts)
 {
 	struct timespec64 tsu;
+	bool sec_rollover = false;
 
 	ts->tv_sec = (GEM_BFEXT(DMA_SECH, dma_desc_ts_2) << GEM_DMA_SECL_SIZE) |
 			GEM_BFEXT(DMA_SECL, dma_desc_ts_1);
@@ -259,9 +260,12 @@
 	 */
 	if ((ts->tv_sec & (GEM_DMA_SEC_TOP >> 1)) &&
 	    !(tsu.tv_sec & (GEM_DMA_SEC_TOP >> 1)))
-		ts->tv_sec -= GEM_DMA_SEC_TOP;
+		sec_rollover = true;
+
+	ts->tv_sec |= ((~GEM_DMA_SEC_MASK) & tsu.tv_sec);
 
-	ts->tv_sec += ((~GEM_DMA_SEC_MASK) & tsu.tv_sec);
+	if (sec_rollover)
+		ts->tv_sec -= GEM_DMA_SEC_TOP;
 
 	return 0;
 }
@@ -275,6 +279,12 @@
 
 	if (GEM_BFEXT(DMA_RXVALID, desc->addr)) {
 		desc_ptp = macb_ptp_desc(bp, desc);
+		/* Unlikely but check */
+		if (!desc_ptp) {
+			dev_warn_ratelimited(&bp->pdev->dev,
+					     "Timestamp not supported in BD\n");
+			return;
+		}
 		gem_hw_timestamp(bp, desc_ptp->ts_1, desc_ptp->ts_2, &ts);
 		memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps));
 		shhwtstamps->hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
@@ -307,8 +317,11 @@
 	if (CIRC_SPACE(head, tail, PTP_TS_BUFFER_SIZE) == 0)
 		return -ENOMEM;
 
-	skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
 	desc_ptp = macb_ptp_desc(queue->bp, desc);
+	/* Unlikely but check */
+	if (!desc_ptp)
+		return -EINVAL;
+	skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
 	tx_timestamp = &queue->tx_timestamps[head];
 	tx_timestamp->skb = skb;
 	/* ensure ts_1/ts_2 is loaded after ctrl (TX_USED check) */
@@ -385,11 +398,14 @@
 void gem_ptp_remove(struct net_device *ndev)
 {
 	struct macb *bp = netdev_priv(ndev);
+	unsigned long flags;
 
 	if (bp->ptp_clock)
 		ptp_clock_unregister(bp->ptp_clock);
 
+	spin_lock_irqsave(&bp->tsu_clk_lock, flags);
 	gem_ptp_clear_timer(bp);
+	spin_unlock_irqrestore(&bp->tsu_clk_lock, flags);
 
 	dev_info(&bp->pdev->dev, "%s ptp clock unregistered.\n",
 		 GEM_PTP_TIMER_NAME);
@@ -462,7 +478,7 @@
 			return -ERANGE;
 		/* fall through */
 	case HWTSTAMP_TX_ON:
-		tx_bd_control = TSTAMP_ALL_FRAMES;
+		tx_bd_control = TSTAMP_ALL_PTP_FRAMES;
 		break;
 	default:
 		return -ERANGE;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c
@@ -420,7 +420,7 @@
 	 * bits 32:47 indicate the PVF num.
 	 */
 	for (q_no = 0; q_no < ern; q_no++) {
-		reg_val = oct->pcie_port << CN23XX_PKT_INPUT_CTL_MAC_NUM_POS;
+		reg_val = (u64)oct->pcie_port << CN23XX_PKT_INPUT_CTL_MAC_NUM_POS;
 
 		/* for VF assigned queues. */
 		if (q_no < oct->sriov_info.pf_srn) {
@@ -1167,7 +1167,7 @@
 		oct->pf_num = ((fdl_bit >> CN23XX_PCIE_SRIOV_FDL_BIT_POS) &
 			       CN23XX_PCIE_SRIOV_FDL_MASK);
 	} else {
-		ret = EINVAL;
+		ret = -EINVAL;
 
 		/* Under some virtual environments, extended PCI regs are
 		 * inaccessible, in which case the above read will have failed.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_regs.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_regs.h
@@ -521,7 +521,7 @@
 #define    CN23XX_BAR1_INDEX_OFFSET                3
 
 #define    CN23XX_PEM_BAR1_INDEX_REG(port, idx)		\
-		(CN23XX_PEM_BAR1_INDEX_START + ((port) << CN23XX_PEM_OFFSET) + \
+		(CN23XX_PEM_BAR1_INDEX_START + (((u64)port) << CN23XX_PEM_OFFSET) + \
 		 ((idx) << CN23XX_BAR1_INDEX_OFFSET))
 
 /*############################ DPI #########################*/
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/cavium/liquidio/cn66xx_regs.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/cavium/liquidio/cn66xx_regs.h
@@ -412,7 +412,7 @@
 	   | CN6XXX_INTR_M0UNWI_ERR             \
 	   | CN6XXX_INTR_M1UPB0_ERR             \
 	   | CN6XXX_INTR_M1UPWI_ERR             \
-	   | CN6XXX_INTR_M1UPB0_ERR             \
+	   | CN6XXX_INTR_M1UNB0_ERR             \
 	   | CN6XXX_INTR_M1UNWI_ERR             \
 	   | CN6XXX_INTR_INSTR_DB_OF_ERR        \
 	   | CN6XXX_INTR_SLIST_DB_OF_ERR        \
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -1179,7 +1179,7 @@
  * @param lio per-network private data
  * @param start_stop whether to start or stop
  */
-static void send_rx_ctrl_cmd(struct lio *lio, int start_stop)
+static int send_rx_ctrl_cmd(struct lio *lio, int start_stop)
 {
 	struct octeon_soft_command *sc;
 	union octnet_cmd *ncmd;
@@ -1187,15 +1187,15 @@
 	int retval;
 
 	if (oct->props[lio->ifidx].rx_on == start_stop)
-		return;
+		return 0;
 
 	sc = (struct octeon_soft_command *)
 		octeon_alloc_soft_command(oct, OCTNET_CMD_SIZE,
 					  16, 0);
 	if (!sc) {
 		netif_info(lio, rx_err, lio->netdev,
-			   "Failed to allocate octeon_soft_command\n");
-		return;
+			   "Failed to allocate octeon_soft_command struct\n");
+		return -ENOMEM;
 	}
 
 	ncmd = (union octnet_cmd *)sc->virtdptr;
@@ -1218,18 +1218,19 @@
 	if (retval == IQ_SEND_FAILED) {
 		netif_info(lio, rx_err, lio->netdev, "Failed to send RX Control message\n");
 		octeon_free_soft_command(oct, sc);
-		return;
 	} else {
 		/* Sleep on a wait queue till the cond flag indicates that the
 		 * response arrived or timed-out.
 		 */
 		retval = wait_for_sc_completion_timeout(oct, sc, 0);
 		if (retval)
-			return;
+			return retval;
 
 		oct->props[lio->ifidx].rx_on = start_stop;
 		WRITE_ONCE(sc->caller_is_done, true);
 	}
+
+	return retval;
 }
 
 /**
@@ -1816,6 +1817,7 @@
 	struct octeon_device_priv *oct_priv =
 		(struct octeon_device_priv *)oct->priv;
 	struct napi_struct *napi, *n;
+	int ret = 0;
 
 	if (oct->props[lio->ifidx].napi_enabled == 0) {
 		tasklet_disable(&oct_priv->droq_tasklet);
@@ -1834,13 +1836,10 @@
 
 	ifstate_set(lio, LIO_IFSTATE_RUNNING);
 
-	if (OCTEON_CN23XX_PF(oct)) {
-		if (!oct->msix_on)
-			if (setup_tx_poll_fn(netdev))
-				return -1;
-	} else {
-		if (setup_tx_poll_fn(netdev))
-			return -1;
+	if (!OCTEON_CN23XX_PF(oct) || !oct->msix_on) {
+		ret = setup_tx_poll_fn(netdev);
+		if (ret)
+			goto err_poll;
 	}
 
 	netif_tx_start_all_queues(netdev);
@@ -1851,7 +1850,9 @@
 	netif_info(lio, ifup, lio->netdev, "Interface Open, ready for traffic\n");
 
 	/* tell Octeon to start forwarding packets to host */
-	send_rx_ctrl_cmd(lio, 1);
+	ret = send_rx_ctrl_cmd(lio, 1);
+	if (ret)
+		goto err_rx_ctrl;
 
 	/* start periodical statistics fetch */
 	INIT_DELAYED_WORK(&lio->stats_wk.work, lio_fetch_stats);
@@ -1863,6 +1864,27 @@
 		 netdev->name);
 
 	return 0;
+
+err_rx_ctrl:
+	if (!OCTEON_CN23XX_PF(oct) || !oct->msix_on)
+		cleanup_tx_poll_fn(netdev);
+err_poll:
+	if (lio->ptp_clock) {
+		ptp_clock_unregister(lio->ptp_clock);
+		lio->ptp_clock = NULL;
+	}
+
+	if (oct->props[lio->ifidx].napi_enabled == 1) {
+		list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list)
+			napi_disable(napi);
+
+		oct->props[lio->ifidx].napi_enabled = 0;
+
+		if (OCTEON_CN23XX_PF(oct))
+			oct->droq[0]->ops.poll_mode = 0;
+	}
+
+	return ret;
 }
 
 /**
@@ -1876,6 +1898,7 @@
 	struct octeon_device_priv *oct_priv =
 		(struct octeon_device_priv *)oct->priv;
 	struct napi_struct *napi, *n;
+	int ret = 0;
 
 	ifstate_reset(lio, LIO_IFSTATE_RUNNING);
 
@@ -1892,7 +1915,9 @@
 	lio->link_changes++;
 
 	/* Tell Octeon that nic interface is down. */
-	send_rx_ctrl_cmd(lio, 0);
+	ret = send_rx_ctrl_cmd(lio, 0);
+	if (ret)
+		return ret;
 
 	if (OCTEON_CN23XX_PF(oct)) {
 		if (!oct->msix_on)
@@ -1927,7 +1952,7 @@
 
 	dev_info(&oct->pci_dev->dev, "%s interface is stopped\n", netdev->name);
 
-	return 0;
+	return ret;
 }
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
@@ -598,7 +598,7 @@
  * @param lio per-network private data
  * @param start_stop whether to start or stop
  */
-static void send_rx_ctrl_cmd(struct lio *lio, int start_stop)
+static int send_rx_ctrl_cmd(struct lio *lio, int start_stop)
 {
 	struct octeon_device *oct = (struct octeon_device *)lio->oct_dev;
 	struct octeon_soft_command *sc;
@@ -606,11 +606,16 @@
 	int retval;
 
 	if (oct->props[lio->ifidx].rx_on == start_stop)
-		return;
+		return 0;
 
 	sc = (struct octeon_soft_command *)
 		octeon_alloc_soft_command(oct, OCTNET_CMD_SIZE,
 					  16, 0);
+	if (!sc) {
+		netif_info(lio, rx_err, lio->netdev,
+			   "Failed to allocate octeon_soft_command struct\n");
+		return -ENOMEM;
+	}
 
 	ncmd = (union octnet_cmd *)sc->virtdptr;
 
@@ -638,11 +643,13 @@
 		 */
 		retval = wait_for_sc_completion_timeout(oct, sc, 0);
 		if (retval)
-			return;
+			return retval;
 
 		oct->props[lio->ifidx].rx_on = start_stop;
 		WRITE_ONCE(sc->caller_is_done, true);
 	}
+
+	return retval;
 }
 
 /**
@@ -909,6 +916,7 @@
 	struct octeon_device_priv *oct_priv =
 		(struct octeon_device_priv *)oct->priv;
 	struct napi_struct *napi, *n;
+	int ret = 0;
 
 	if (!oct->props[lio->ifidx].napi_enabled) {
 		tasklet_disable(&oct_priv->droq_tasklet);
@@ -935,11 +943,13 @@
 					(LIQUIDIO_NDEV_STATS_POLL_TIME_MS));
 
 	/* tell Octeon to start forwarding packets to host */
-	send_rx_ctrl_cmd(lio, 1);
+	ret = send_rx_ctrl_cmd(lio, 1);
+	if (ret)
+		return ret;
 
 	dev_info(&oct->pci_dev->dev, "%s interface is opened\n", netdev->name);
 
-	return 0;
+	return ret;
 }
 
 /**
@@ -953,9 +963,12 @@
 	struct octeon_device_priv *oct_priv =
 		(struct octeon_device_priv *)oct->priv;
 	struct napi_struct *napi, *n;
+	int ret = 0;
 
 	/* tell Octeon to stop forwarding packets to host */
-	send_rx_ctrl_cmd(lio, 0);
+	ret = send_rx_ctrl_cmd(lio, 0);
+	if (ret)
+		return ret;
 
 	netif_info(lio, ifdown, lio->netdev, "Stopping interface!\n");
 	/* Inform that netif carrier is down */
@@ -989,7 +1002,7 @@
 
 	dev_info(&oct->pci_dev->dev, "%s interface is stopped\n", netdev->name);
 
-	return 0;
+	return ret;
 }
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c
@@ -272,13 +272,12 @@
 				pg_info->page_offset;
 			memcpy(skb->data, va, MIN_SKB_SIZE);
 			skb_put(skb, MIN_SKB_SIZE);
+			skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
+					pg_info->page,
+					pg_info->page_offset + MIN_SKB_SIZE,
+					len - MIN_SKB_SIZE,
+					LIO_RXBUFFER_SZ);
 		}
-
-		skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
-				pg_info->page,
-				pg_info->page_offset + MIN_SKB_SIZE,
-				len - MIN_SKB_SIZE,
-				LIO_RXBUFFER_SZ);
 	} else {
 		struct octeon_skb_page_info *pg_info =
 			((struct octeon_skb_page_info *)(skb->cb));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c
@@ -235,6 +235,11 @@
 
 		/* Put it in the ring.  */
 		p->rx_ring[p->rx_next_fill] = re.d64;
+		/* Make sure there is no reorder of filling the ring and ringing
+		 * the bell
+		 */
+		wmb();
+
 		dma_sync_single_for_device(p->dev, p->rx_ring_handle,
 					   ring_size_to_bytes(OCTEON_MGMT_RX_RING_SIZE),
 					   DMA_BIDIRECTIONAL);
@@ -1217,7 +1222,7 @@
 	 */
 	if (netdev->phydev) {
 		netif_carrier_off(netdev);
-		phy_start_aneg(netdev->phydev);
+		phy_start(netdev->phydev);
 	}
 
 	netif_wake_queue(netdev);
@@ -1245,8 +1250,10 @@
 	napi_disable(&p->napi);
 	netif_stop_queue(netdev);
 
-	if (netdev->phydev)
+	if (netdev->phydev) {
+		phy_stop(netdev->phydev);
 		phy_disconnect(netdev->phydev);
+	}
 
 	netif_carrier_off(netdev);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/cavium/thunder/nic_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/cavium/thunder/nic_main.c
@@ -1193,7 +1193,7 @@
 		dev_err(&nic->pdev->dev,
 			"Request for #%d msix vectors failed, returned %d\n",
 			   nic->num_vec, ret);
-		return 1;
+		return ret;
 	}
 
 	/* Register mailbox interrupt handler */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -1226,7 +1226,7 @@
 	if (ret < 0) {
 		netdev_err(nic->netdev,
 			   "Req for #%d msix vectors failed\n", nic->num_vec);
-		return 1;
+		return ret;
 	}
 
 	sprintf(nic->irq_name[irq], "%s Mbox", "NICVF");
@@ -1245,7 +1245,7 @@
 	if (!nicvf_check_pf_ready(nic)) {
 		nicvf_disable_intr(nic, NICVF_INTR_MBOX, 0);
 		nicvf_unregister_interrupts(nic);
-		return 1;
+		return -EIO;
 	}
 
 	return 0;
@@ -2047,11 +2047,11 @@
 	/* Save message data locally to prevent them from
 	 * being overwritten by next ndo_set_rx_mode call().
 	 */
-	spin_lock(&nic->rx_mode_wq_lock);
+	spin_lock_bh(&nic->rx_mode_wq_lock);
 	mode = vf_work->mode;
 	mc = vf_work->mc;
 	vf_work->mc = NULL;
-	spin_unlock(&nic->rx_mode_wq_lock);
+	spin_unlock_bh(&nic->rx_mode_wq_lock);
 
 	__nicvf_set_rx_mode_task(mode, mc, nic);
 }
@@ -2185,6 +2185,9 @@
 		nic->max_queues *= 2;
 	nic->ptp_clock = ptp_clock;
 
+	/* Initialize mutex that serializes usage of VF's mailbox */
+	mutex_init(&nic->rx_mode_mtx);
+
 	/* MAP VF's configuration registers */
 	nic->reg_base = pcim_iomap(pdev, PCI_CFG_REG_BAR_NUM, 0);
 	if (!nic->reg_base) {
@@ -2261,12 +2264,11 @@
 
 	INIT_WORK(&nic->rx_mode_work.work, nicvf_set_rx_mode_task);
 	spin_lock_init(&nic->rx_mode_wq_lock);
-	mutex_init(&nic->rx_mode_mtx);
 
 	err = register_netdev(netdev);
 	if (err) {
 		dev_err(dev, "Failed to register netdevice\n");
-		goto err_unregister_interrupts;
+		goto err_destroy_workqueue;
 	}
 
 	nic->msg_enable = debug;
@@ -2275,6 +2277,8 @@
 
 	return 0;
 
+err_destroy_workqueue:
+	destroy_workqueue(nic->nicvf_rx_mode_wq);
 err_unregister_interrupts:
 	nicvf_unregister_interrupts(nic);
 err_free_netdev:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
@@ -776,7 +776,7 @@
 	mbx.rq.msg = NIC_MBOX_MSG_RQ_CFG;
 	mbx.rq.qs_num = qs->vnic_id;
 	mbx.rq.rq_num = qidx;
-	mbx.rq.cfg = (rq->caching << 26) | (rq->cq_qs << 19) |
+	mbx.rq.cfg = ((u64)rq->caching << 26) | (rq->cq_qs << 19) |
 			  (rq->cq_idx << 16) | (rq->cont_rbdr_qs << 9) |
 			  (rq->cont_qs_rbdr_idx << 8) |
 			  (rq->start_rbdr_qs << 1) | (rq->start_qs_rbdr_idx);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
@@ -410,10 +410,19 @@
 	lmac = &bgx->lmac[lmacid];
 
 	cfg = bgx_reg_read(bgx, lmacid, BGX_CMRX_CFG);
-	if (enable)
+	if (enable) {
 		cfg |= CMR_PKT_RX_EN | CMR_PKT_TX_EN;
-	else
+
+		/* enable TX FIFO Underflow interrupt */
+		bgx_reg_modify(bgx, lmacid, BGX_GMP_GMI_TXX_INT_ENA_W1S,
+			       GMI_TXX_INT_UNDFLW);
+	} else {
 		cfg &= ~(CMR_PKT_RX_EN | CMR_PKT_TX_EN);
+
+		/* Disable TX FIFO Underflow interrupt */
+		bgx_reg_modify(bgx, lmacid, BGX_GMP_GMI_TXX_INT_ENA_W1C,
+			       GMI_TXX_INT_UNDFLW);
+	}
 	bgx_reg_write(bgx, lmacid, BGX_CMRX_CFG, cfg);
 
 	if (bgx->is_rgx)
@@ -1115,7 +1124,7 @@
 				       phy_interface_mode(lmac->lmac_type)))
 			return -ENODEV;
 
-		phy_start_aneg(lmac->phydev);
+		phy_start(lmac->phydev);
 		return 0;
 	}
 
@@ -1429,8 +1438,10 @@
 		return AE_OK;
 	}
 
-	if (strncmp(string.pointer, bgx_sel, 4))
+	if (strncmp(string.pointer, bgx_sel, 4)) {
+		kfree(string.pointer);
 		return AE_OK;
+	}
 
 	acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
 			    bgx_acpi_register_phy, NULL, bgx, NULL);
@@ -1535,6 +1546,48 @@
 	return bgx_init_of_phy(bgx);
 }
 
+static irqreturn_t bgx_intr_handler(int irq, void *data)
+{
+	struct bgx *bgx = (struct bgx *)data;
+	u64 status, val;
+	int lmac;
+
+	for (lmac = 0; lmac < bgx->lmac_count; lmac++) {
+		status = bgx_reg_read(bgx, lmac, BGX_GMP_GMI_TXX_INT);
+		if (status & GMI_TXX_INT_UNDFLW) {
+			pci_err(bgx->pdev, "BGX%d lmac%d UNDFLW\n",
+				bgx->bgx_id, lmac);
+			val = bgx_reg_read(bgx, lmac, BGX_CMRX_CFG);
+			val &= ~CMR_EN;
+			bgx_reg_write(bgx, lmac, BGX_CMRX_CFG, val);
+			val |= CMR_EN;
+			bgx_reg_write(bgx, lmac, BGX_CMRX_CFG, val);
+		}
+		/* clear interrupts */
+		bgx_reg_write(bgx, lmac, BGX_GMP_GMI_TXX_INT, status);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static void bgx_register_intr(struct pci_dev *pdev)
+{
+	struct bgx *bgx = pci_get_drvdata(pdev);
+	int ret;
+
+	ret = pci_alloc_irq_vectors(pdev, BGX_LMAC_VEC_OFFSET,
+				    BGX_LMAC_VEC_OFFSET, PCI_IRQ_ALL_TYPES);
+	if (ret < 0) {
+		pci_err(pdev, "Req for #%d msix vectors failed\n",
+			BGX_LMAC_VEC_OFFSET);
+		return;
+	}
+	ret = pci_request_irq(pdev, GMPX_GMI_TX_INT, bgx_intr_handler, NULL,
+			      bgx, "BGX%d", bgx->bgx_id);
+	if (ret)
+		pci_free_irq(pdev, GMPX_GMI_TX_INT, bgx);
+}
+
 static int bgx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	int err;
@@ -1550,7 +1603,7 @@
 
 	pci_set_drvdata(pdev, bgx);
 
-	err = pci_enable_device(pdev);
+	err = pcim_enable_device(pdev);
 	if (err) {
 		dev_err(dev, "Failed to enable PCI device\n");
 		pci_set_drvdata(pdev, NULL);
@@ -1604,6 +1657,8 @@
 
 	bgx_init_hw(bgx);
 
+	bgx_register_intr(pdev);
+
 	/* Enable all LMACs */
 	for (lmac = 0; lmac < bgx->lmac_count; lmac++) {
 		err = bgx_lmac_enable(bgx, lmac);
@@ -1620,6 +1675,7 @@
 
 err_enable:
 	bgx_vnic[bgx->bgx_id] = NULL;
+	pci_free_irq(pdev, GMPX_GMI_TX_INT, bgx);
 err_release_regions:
 	pci_release_regions(pdev);
 err_disable_device:
@@ -1637,6 +1693,8 @@
 	for (lmac = 0; lmac < bgx->lmac_count; lmac++)
 		bgx_lmac_disable(bgx, lmac);
 
+	pci_free_irq(pdev, GMPX_GMI_TX_INT, bgx);
+
 	bgx_vnic[bgx->bgx_id] = NULL;
 	pci_release_regions(pdev);
 	pci_disable_device(pdev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/cavium/thunder/thunder_bgx.h
@@ -180,6 +180,15 @@
 #define BGX_GMP_GMI_TXX_BURST		0x38228
 #define BGX_GMP_GMI_TXX_MIN_PKT		0x38240
 #define BGX_GMP_GMI_TXX_SGMII_CTL	0x38300
+#define BGX_GMP_GMI_TXX_INT		0x38500
+#define BGX_GMP_GMI_TXX_INT_W1S		0x38508
+#define BGX_GMP_GMI_TXX_INT_ENA_W1C	0x38510
+#define BGX_GMP_GMI_TXX_INT_ENA_W1S	0x38518
+#define  GMI_TXX_INT_PTP_LOST			BIT_ULL(4)
+#define  GMI_TXX_INT_LATE_COL			BIT_ULL(3)
+#define  GMI_TXX_INT_XSDEF			BIT_ULL(2)
+#define  GMI_TXX_INT_XSCOL			BIT_ULL(1)
+#define  GMI_TXX_INT_UNDFLW			BIT_ULL(0)
 
 #define BGX_MSIX_VEC_0_29_ADDR		0x400000 /* +(0..29) << 4 */
 #define BGX_MSIX_VEC_0_29_CTL		0x400008
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/chelsio/cxgb/cxgb2.c
@@ -1153,6 +1153,7 @@
 	if (!adapter->registered_device_map) {
 		pr_err("%s: could not register any net devices\n",
 		       pci_name(pdev));
+		err = -EINVAL;
 		goto out_release_adapter_res;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
@@ -1303,6 +1303,7 @@
 		if (ret < 0) {
 			CH_ERR(adap, "failed to bind qsets, err %d\n", ret);
 			t3_intr_disable(adap);
+			quiesce_rx(adap);
 			free_irq_resources(adap);
 			err = ret;
 			goto out;
@@ -2448,6 +2449,8 @@
 
 		if (!is_offload(adapter))
 			return -EOPNOTSUPP;
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
 		if (!(adapter->flags & FULL_INIT_DONE))
 			return -EIO;	/* need the memory controllers */
 		if (copy_from_user(&t, useraddr, sizeof(t)))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/chelsio/cxgb3/sge.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/chelsio/cxgb3/sge.c
@@ -3176,6 +3176,7 @@
 			  GFP_KERNEL | __GFP_COMP);
 	if (!avail) {
 		CH_ALERT(adapter, "free list queue 0 initialization failed\n");
+		ret = -ENOMEM;
 		goto err;
 	}
 	if (avail < q->fl[0].size)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/chelsio/cxgb3/t3_hw.c
@@ -3677,6 +3677,8 @@
 	    MAC_STATS_ACCUM_SECS : (MAC_STATS_ACCUM_SECS * 10);
 	adapter->params.pci.vpd_cap_addr =
 	    pci_find_capability(adapter->pdev, PCI_CAP_ID_VPD);
+	if (!adapter->params.pci.vpd_cap_addr)
+		return -ENODEV;
 	ret = get_vpd_params(adapter, &adapter->params.vpd);
 	if (ret < 0)
 		return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c
@@ -1054,9 +1054,9 @@
 	}
 }
 
-static unsigned long cudbg_mem_region_size(struct cudbg_init *pdbg_init,
-					   struct cudbg_error *cudbg_err,
-					   u8 mem_type)
+static int cudbg_mem_region_size(struct cudbg_init *pdbg_init,
+				 struct cudbg_error *cudbg_err,
+				 u8 mem_type, unsigned long *region_size)
 {
 	struct adapter *padap = pdbg_init->adap;
 	struct cudbg_meminfo mem_info;
@@ -1065,15 +1065,23 @@
 
 	memset(&mem_info, 0, sizeof(struct cudbg_meminfo));
 	rc = cudbg_fill_meminfo(padap, &mem_info);
-	if (rc)
+	if (rc) {
+		cudbg_err->sys_err = rc;
 		return rc;
+	}
 
 	cudbg_t4_fwcache(pdbg_init, cudbg_err);
 	rc = cudbg_meminfo_get_mem_index(padap, &mem_info, mem_type, &mc_idx);
-	if (rc)
+	if (rc) {
+		cudbg_err->sys_err = rc;
 		return rc;
+	}
+
+	if (region_size)
+		*region_size = mem_info.avail[mc_idx].limit -
+			       mem_info.avail[mc_idx].base;
 
-	return mem_info.avail[mc_idx].limit - mem_info.avail[mc_idx].base;
+	return 0;
 }
 
 static int cudbg_collect_mem_region(struct cudbg_init *pdbg_init,
@@ -1081,7 +1089,12 @@
 				    struct cudbg_error *cudbg_err,
 				    u8 mem_type)
 {
-	unsigned long size = cudbg_mem_region_size(pdbg_init, cudbg_err, mem_type);
+	unsigned long size = 0;
+	int rc;
+
+	rc = cudbg_mem_region_size(pdbg_init, cudbg_err, mem_type, &size);
+	if (rc)
+		return rc;
 
 	return cudbg_read_fw_mem(pdbg_init, dbg_buff, mem_type, size,
 				 cudbg_err);
@@ -1380,11 +1393,25 @@
 	struct cudbg_buffer temp_buff = { 0 };
 	struct sge_qbase_reg_field *sge_qbase;
 	struct ireg_buf *ch_sge_dbg;
+	u8 padap_running = 0;
 	int i, rc;
+	u32 size;
 
-	rc = cudbg_get_buff(pdbg_init, dbg_buff,
-			    sizeof(*ch_sge_dbg) * 2 + sizeof(*sge_qbase),
-			    &temp_buff);
+	/* Accessing SGE_QBASE_MAP[0-3] and SGE_QBASE_INDEX regs can
+	 * lead to SGE missing doorbells under heavy traffic. So, only
+	 * collect them when adapter is idle.
+	 */
+	for_each_port(padap, i) {
+		padap_running = netif_running(padap->port[i]);
+		if (padap_running)
+			break;
+	}
+
+	size = sizeof(*ch_sge_dbg) * 2;
+	if (!padap_running)
+		size += sizeof(*sge_qbase);
+
+	rc = cudbg_get_buff(pdbg_init, dbg_buff, size, &temp_buff);
 	if (rc)
 		return rc;
 
@@ -1406,7 +1433,8 @@
 		ch_sge_dbg++;
 	}
 
-	if (CHELSIO_CHIP_VERSION(padap->params.chip) > CHELSIO_T5) {
+	if (CHELSIO_CHIP_VERSION(padap->params.chip) > CHELSIO_T5 &&
+	    !padap_running) {
 		sge_qbase = (struct sge_qbase_reg_field *)ch_sge_dbg;
 		/* 1 addr reg SGE_QBASE_INDEX and 4 data reg
 		 * SGE_QBASE_MAP[0-3]
@@ -1967,7 +1995,6 @@
 	u8 mem_type[CTXT_INGRESS + 1] = { 0 };
 	struct cudbg_buffer temp_buff = { 0 };
 	struct cudbg_ch_cntxt *buff;
-	u64 *dst_off, *src_off;
 	u8 *ctx_buf;
 	u8 i, k;
 	int rc;
@@ -2036,8 +2063,11 @@
 		}
 
 		for (j = 0; j < max_ctx_qid; j++) {
+			__be64 *dst_off;
+			u64 *src_off;
+
 			src_off = (u64 *)(ctx_buf + j * SGE_CTXT_SIZE);
-			dst_off = (u64 *)buff->data;
+			dst_off = (__be64 *)buff->data;
 
 			/* The data is stored in 64-bit cpu order.  Convert it
 			 * to big endian before parsing.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -503,6 +503,7 @@
 
 	enum cc_pause  requested_fc;     /* flow control user has requested */
 	enum cc_pause  fc;               /* actual link flow control */
+	enum cc_pause  advertised_fc;    /* actual advertised flow control */
 
 	enum cc_fec    requested_fec;	 /* Forward Error Correction: */
 	enum cc_fec    fec;		 /* requested and actual in use */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
@@ -70,8 +70,7 @@
 static void *seq_tab_next(struct seq_file *seq, void *v, loff_t *pos)
 {
 	v = seq_tab_get_idx(seq->private, *pos + 1);
-	if (v)
-		++*pos;
+	++(*pos);
 	return v;
 }
 
@@ -2691,7 +2690,7 @@
 	seq_printf(seq, "%-12s", s); \
 	for (i = 0; i < n; ++i) \
 		seq_printf(seq, " %16" fmt_spec, v); \
-		seq_putc(seq, '\n'); \
+	seq_putc(seq, '\n'); \
 } while (0)
 #define S(s, v) S3("s", s, v)
 #define T3(fmt_spec, s, v) S3(fmt_spec, s, tx[i].v)
@@ -2996,6 +2995,9 @@
 	int tot_uld_entries = 0;
 	int i;
 
+	if (!is_uld(adap))
+		goto lld_only;
+
 	mutex_lock(&uld_mutex);
 	for (i = 0; i < CXGB4_TX_MAX; i++)
 		tot_uld_entries += sge_qinfo_uld_txq_entries(adap, i);
@@ -3006,6 +3008,7 @@
 	}
 	mutex_unlock(&uld_mutex);
 
+lld_only:
 	return DIV_ROUND_UP(adap->sge.ethqsets, 4) +
 	       tot_uld_entries +
 	       DIV_ROUND_UP(MAX_CTRL_QUEUES, 4) + 1;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c
@@ -793,8 +793,8 @@
 	struct port_info *p = netdev_priv(dev);
 
 	epause->autoneg = (p->link_cfg.requested_fc & PAUSE_AUTONEG) != 0;
-	epause->rx_pause = (p->link_cfg.fc & PAUSE_RX) != 0;
-	epause->tx_pause = (p->link_cfg.fc & PAUSE_TX) != 0;
+	epause->rx_pause = (p->link_cfg.advertised_fc & PAUSE_RX) != 0;
+	epause->tx_pause = (p->link_cfg.advertised_fc & PAUSE_TX) != 0;
 }
 
 static int set_pauseparam(struct net_device *dev,
@@ -1466,12 +1466,15 @@
 		if (ret)
 			return ret;
 
-		if (!sff8472_comp || (sff_diag_type & 4)) {
+		if (!sff8472_comp || (sff_diag_type & SFP_DIAG_ADDRMODE)) {
 			modinfo->type = ETH_MODULE_SFF_8079;
 			modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
 		} else {
 			modinfo->type = ETH_MODULE_SFF_8472;
-			modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
+			if (sff_diag_type & SFP_DIAG_IMPLEMENTED)
+				modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
+			else
+				modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN / 2;
 		}
 		break;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c
@@ -145,13 +145,13 @@
 	int err;
 
 	/* do a set-tcb for smac-sel and CWR bit.. */
-	err = set_tcb_tflag(adap, f, f->tid, TF_CCTRL_CWR_S, 1, 1);
-	if (err)
-		goto smac_err;
-
 	err = set_tcb_field(adap, f, f->tid, TCB_SMAC_SEL_W,
 			    TCB_SMAC_SEL_V(TCB_SMAC_SEL_M),
 			    TCB_SMAC_SEL_V(f->smt->idx), 1);
+	if (err)
+		goto smac_err;
+
+	err = set_tcb_tflag(adap, f, f->tid, TF_CCTRL_CWR_S, 1, 1);
 	if (!err)
 		return 0;
 
@@ -165,37 +165,40 @@
 			   unsigned int tid, bool dip, bool sip, bool dp,
 			   bool sp)
 {
+	u8 *nat_lp = (u8 *)&f->fs.nat_lport;
+	u8 *nat_fp = (u8 *)&f->fs.nat_fport;
+
 	if (dip) {
 		if (f->fs.type) {
 			set_tcb_field(adap, f, tid, TCB_SND_UNA_RAW_W,
 				      WORD_MASK, f->fs.nat_lip[15] |
 				      f->fs.nat_lip[14] << 8 |
 				      f->fs.nat_lip[13] << 16 |
-				      f->fs.nat_lip[12] << 24, 1);
+				      (u64)f->fs.nat_lip[12] << 24, 1);
 
 			set_tcb_field(adap, f, tid, TCB_SND_UNA_RAW_W + 1,
 				      WORD_MASK, f->fs.nat_lip[11] |
 				      f->fs.nat_lip[10] << 8 |
 				      f->fs.nat_lip[9] << 16 |
-				      f->fs.nat_lip[8] << 24, 1);
+				      (u64)f->fs.nat_lip[8] << 24, 1);
 
 			set_tcb_field(adap, f, tid, TCB_SND_UNA_RAW_W + 2,
 				      WORD_MASK, f->fs.nat_lip[7] |
 				      f->fs.nat_lip[6] << 8 |
 				      f->fs.nat_lip[5] << 16 |
-				      f->fs.nat_lip[4] << 24, 1);
+				      (u64)f->fs.nat_lip[4] << 24, 1);
 
 			set_tcb_field(adap, f, tid, TCB_SND_UNA_RAW_W + 3,
 				      WORD_MASK, f->fs.nat_lip[3] |
 				      f->fs.nat_lip[2] << 8 |
 				      f->fs.nat_lip[1] << 16 |
-				      f->fs.nat_lip[0] << 24, 1);
+				      (u64)f->fs.nat_lip[0] << 24, 1);
 		} else {
 			set_tcb_field(adap, f, tid, TCB_RX_FRAG3_LEN_RAW_W,
 				      WORD_MASK, f->fs.nat_lip[3] |
 				      f->fs.nat_lip[2] << 8 |
 				      f->fs.nat_lip[1] << 16 |
-				      f->fs.nat_lip[0] << 24, 1);
+				      (u64)f->fs.nat_lip[0] << 24, 1);
 		}
 	}
 
@@ -205,25 +208,25 @@
 				      WORD_MASK, f->fs.nat_fip[15] |
 				      f->fs.nat_fip[14] << 8 |
 				      f->fs.nat_fip[13] << 16 |
-				      f->fs.nat_fip[12] << 24, 1);
+				      (u64)f->fs.nat_fip[12] << 24, 1);
 
 			set_tcb_field(adap, f, tid, TCB_RX_FRAG2_PTR_RAW_W + 1,
 				      WORD_MASK, f->fs.nat_fip[11] |
 				      f->fs.nat_fip[10] << 8 |
 				      f->fs.nat_fip[9] << 16 |
-				      f->fs.nat_fip[8] << 24, 1);
+				      (u64)f->fs.nat_fip[8] << 24, 1);
 
 			set_tcb_field(adap, f, tid, TCB_RX_FRAG2_PTR_RAW_W + 2,
 				      WORD_MASK, f->fs.nat_fip[7] |
 				      f->fs.nat_fip[6] << 8 |
 				      f->fs.nat_fip[5] << 16 |
-				      f->fs.nat_fip[4] << 24, 1);
+				      (u64)f->fs.nat_fip[4] << 24, 1);
 
 			set_tcb_field(adap, f, tid, TCB_RX_FRAG2_PTR_RAW_W + 3,
 				      WORD_MASK, f->fs.nat_fip[3] |
 				      f->fs.nat_fip[2] << 8 |
 				      f->fs.nat_fip[1] << 16 |
-				      f->fs.nat_fip[0] << 24, 1);
+				      (u64)f->fs.nat_fip[0] << 24, 1);
 
 		} else {
 			set_tcb_field(adap, f, tid,
@@ -231,13 +234,14 @@
 				      WORD_MASK, f->fs.nat_fip[3] |
 				      f->fs.nat_fip[2] << 8 |
 				      f->fs.nat_fip[1] << 16 |
-				      f->fs.nat_fip[0] << 24, 1);
+				      (u64)f->fs.nat_fip[0] << 24, 1);
 		}
 	}
 
 	set_tcb_field(adap, f, tid, TCB_PDU_HDR_LEN_W, WORD_MASK,
-		      (dp ? f->fs.nat_lport : 0) |
-		      (sp ? f->fs.nat_fport << 16 : 0), 1);
+		      (dp ? (nat_lp[1] | nat_lp[0] << 8) : 0) |
+		      (sp ? (nat_fp[1] << 16 | (u64)nat_fp[0] << 24) : 0),
+		      1);
 }
 
 /* Validate filter spec against configuration done on the card. */
@@ -608,6 +612,7 @@
 		      FW_FILTER_WR_DIRSTEERHASH_V(f->fs.dirsteerhash) |
 		      FW_FILTER_WR_LPBK_V(f->fs.action == FILTER_SWITCH) |
 		      FW_FILTER_WR_DMAC_V(f->fs.newdmac) |
+		      FW_FILTER_WR_SMAC_V(f->fs.newsmac) |
 		      FW_FILTER_WR_INSVLAN_V(f->fs.newvlan == VLAN_INSERT ||
 					     f->fs.newvlan == VLAN_REWRITE) |
 		      FW_FILTER_WR_RMVLAN_V(f->fs.newvlan == VLAN_REMOVE ||
@@ -625,7 +630,8 @@
 		 FW_FILTER_WR_OVLAN_VLD_V(f->fs.val.ovlan_vld) |
 		 FW_FILTER_WR_IVLAN_VLDM_V(f->fs.mask.ivlan_vld) |
 		 FW_FILTER_WR_OVLAN_VLDM_V(f->fs.mask.ovlan_vld));
-	fwr->smac_sel = 0;
+	if (f->fs.newsmac)
+		fwr->smac_sel = f->smt->idx;
 	fwr->rx_chan_rx_rpl_iq =
 		htons(FW_FILTER_WR_RX_CHAN_V(0) |
 		      FW_FILTER_WR_RX_RPL_IQ_V(adapter->sge.fw_evtq.abs_id));
@@ -656,6 +662,9 @@
 	fwr->fpm = htons(f->fs.mask.fport);
 
 	if (adapter->params.filter2_wr_support) {
+		u8 *nat_lp = (u8 *)&f->fs.nat_lport;
+		u8 *nat_fp = (u8 *)&f->fs.nat_fport;
+
 		fwr->natmode_to_ulp_type =
 			FW_FILTER2_WR_ULP_TYPE_V(f->fs.nat_mode ?
 						 ULP_MODE_TCPDDP :
@@ -663,8 +672,8 @@
 			FW_FILTER2_WR_NATMODE_V(f->fs.nat_mode);
 		memcpy(fwr->newlip, f->fs.nat_lip, sizeof(fwr->newlip));
 		memcpy(fwr->newfip, f->fs.nat_fip, sizeof(fwr->newfip));
-		fwr->newlport = htons(f->fs.nat_lport);
-		fwr->newfport = htons(f->fs.nat_fport);
+		fwr->newlport = htons(nat_lp[1] | nat_lp[0] << 8);
+		fwr->newfport = htons(nat_fp[1] | nat_fp[0] << 8);
 	}
 
 	/* Mark the filter as "pending" and ship off the Filter Work Request.
@@ -769,7 +778,7 @@
 				cxgb4_del_filter(dev, i, &f->fs);
 		}
 
-		sb = t4_read_reg(adapter, LE_DB_SRVR_START_INDEX_A);
+		sb = adapter->tids.stid_base;
 		for (i = 0; i < sb; i++) {
 			f = (struct filter_entry *)adapter->tids.tid_tab[i];
 
@@ -832,16 +841,16 @@
 		struct in_addr *addr;
 
 		addr = (struct in_addr *)ipmask;
-		if (addr->s_addr == 0xffffffff)
+		if (addr->s_addr == htonl(0xffffffff))
 			return true;
 	} else if (family == AF_INET6) {
 		struct in6_addr *addr6;
 
 		addr6 = (struct in6_addr *)ipmask;
-		if (addr6->s6_addr32[0] == 0xffffffff &&
-		    addr6->s6_addr32[1] == 0xffffffff &&
-		    addr6->s6_addr32[2] == 0xffffffff &&
-		    addr6->s6_addr32[3] == 0xffffffff)
+		if (addr6->s6_addr32[0] == htonl(0xffffffff) &&
+		    addr6->s6_addr32[1] == htonl(0xffffffff) &&
+		    addr6->s6_addr32[2] == htonl(0xffffffff) &&
+		    addr6->s6_addr32[3] == htonl(0xffffffff))
 			return true;
 	}
 	return false;
@@ -960,7 +969,8 @@
 	 * in the Compressed Filter Tuple.
 	 */
 	if (tp->vlan_shift >= 0 && fs->mask.ivlan)
-		ntuple |= (FT_VLAN_VLD_F | fs->val.ivlan) << tp->vlan_shift;
+		ntuple |= (u64)(FT_VLAN_VLD_F |
+				fs->val.ivlan) << tp->vlan_shift;
 
 	if (tp->port_shift >= 0 && fs->mask.iport)
 		ntuple |= (u64)fs->val.iport << tp->port_shift;
@@ -1041,11 +1051,8 @@
 			    TX_QUEUE_V(f->fs.nat_mode) |
 			    T5_OPT_2_VALID_F |
 			    RX_CHANNEL_V(cxgb4_port_e2cchan(f->dev)) |
-			    CONG_CNTRL_V((f->fs.action == FILTER_DROP) |
-					 (f->fs.dirsteer << 1)) |
 			    PACE_V((f->fs.maskhash) |
-				   ((f->fs.dirsteerhash) << 1)) |
-			    CCTRL_ECN_V(f->fs.action == FILTER_SWITCH));
+				   ((f->fs.dirsteerhash) << 1)));
 }
 
 static void mk_act_open_req(struct filter_entry *f, struct sk_buff *skb,
@@ -1081,11 +1088,8 @@
 			    TX_QUEUE_V(f->fs.nat_mode) |
 			    T5_OPT_2_VALID_F |
 			    RX_CHANNEL_V(cxgb4_port_e2cchan(f->dev)) |
-			    CONG_CNTRL_V((f->fs.action == FILTER_DROP) |
-					 (f->fs.dirsteer << 1)) |
 			    PACE_V((f->fs.maskhash) |
-				   ((f->fs.dirsteerhash) << 1)) |
-			    CCTRL_ECN_V(f->fs.action == FILTER_SWITCH));
+				   ((f->fs.dirsteerhash) << 1)));
 }
 
 static int cxgb4_set_hash_filter(struct net_device *dev,
@@ -1610,13 +1614,16 @@
 static int configure_filter_tcb(struct adapter *adap, unsigned int tid,
 				struct filter_entry *f)
 {
-	if (f->fs.hitcnts)
+	if (f->fs.hitcnts) {
 		set_tcb_field(adap, f, tid, TCB_TIMESTAMP_W,
-			      TCB_TIMESTAMP_V(TCB_TIMESTAMP_M) |
+			      TCB_TIMESTAMP_V(TCB_TIMESTAMP_M),
+			      TCB_TIMESTAMP_V(0ULL),
+			      1);
+		set_tcb_field(adap, f, tid, TCB_RTT_TS_RECENT_AGE_W,
 			      TCB_RTT_TS_RECENT_AGE_V(TCB_RTT_TS_RECENT_AGE_M),
-			      TCB_TIMESTAMP_V(0ULL) |
 			      TCB_RTT_TS_RECENT_AGE_V(0ULL),
 			      1);
+	}
 
 	if (f->fs.newdmac)
 		set_tcb_tflag(adap, f, tid, TF_CCTRL_ECE_S, 1,
@@ -1738,6 +1745,20 @@
 			}
 			return;
 		}
+		switch (f->fs.action) {
+		case FILTER_PASS:
+			if (f->fs.dirsteer)
+				set_tcb_tflag(adap, f, tid,
+					      TF_DIRECT_STEER_S, 1, 1);
+			break;
+		case FILTER_DROP:
+			set_tcb_tflag(adap, f, tid, TF_DROP_S, 1, 1);
+			break;
+		case FILTER_SWITCH:
+			set_tcb_tflag(adap, f, tid, TF_LPBK_S, 1, 1);
+			break;
+		}
+
 		break;
 
 	default:
@@ -1798,22 +1819,11 @@
 			if (ctx)
 				ctx->result = 0;
 		} else if (ret == FW_FILTER_WR_FLT_ADDED) {
-			int err = 0;
-
-			if (f->fs.newsmac)
-				err = configure_filter_smac(adap, f);
-
-			if (!err) {
-				f->pending = 0;  /* async setup completed */
-				f->valid = 1;
-				if (ctx) {
-					ctx->result = 0;
-					ctx->tid = idx;
-				}
-			} else {
-				clear_filter(adap, f);
-				if (ctx)
-					ctx->result = err;
+			f->pending = 0;  /* async setup completed */
+			f->valid = 1;
+			if (ctx) {
+				ctx->result = 0;
+				ctx->tid = idx;
 			}
 		} else {
 			/* Something went wrong.  Issue a warning about the
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -2245,6 +2245,9 @@
 {
 	unsigned int i;
 
+	if (!is_uld(adap))
+		return;
+
 	mutex_lock(&uld_mutex);
 	list_del(&adap->list_node);
 
@@ -2504,7 +2507,7 @@
 
 	/* Clear out filter specifications */
 	memset(&f->fs, 0, sizeof(struct ch_filter_specification));
-	f->fs.val.lport = cpu_to_be16(sport);
+	f->fs.val.lport = be16_to_cpu(sport);
 	f->fs.mask.lport  = ~0;
 	val = (u8 *)&sip;
 	if ((val[0] | val[1] | val[2] | val[3]) != 0) {
@@ -3032,7 +3035,6 @@
 		return ret;
 
 	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-	pi->xact_addr_filt = ret;
 	return 0;
 }
 
@@ -6153,10 +6155,13 @@
 		 */
 		destroy_workqueue(adapter->workq);
 
-		if (is_uld(adapter)) {
-			detach_ulds(adapter);
-			t4_uld_clean_up(adapter);
-		}
+		detach_ulds(adapter);
+
+		for_each_port(adapter, i)
+			if (adapter->port[i]->reg_state == NETREG_REGISTERED)
+				unregister_netdev(adapter->port[i]);
+
+		t4_uld_clean_up(adapter);
 
 		adap_free_hma_mem(adapter);
 
@@ -6164,10 +6169,6 @@
 
 		cxgb4_free_mps_ref_entries(adapter);
 
-		for_each_port(adapter, i)
-			if (adapter->port[i]->reg_state == NETREG_REGISTERED)
-				unregister_netdev(adapter->port[i]);
-
 		debugfs_remove_recursive(adapter->debugfs_root);
 
 		if (!is_t4(adapter->params.chip))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/chelsio/cxgb4/cxgb4_mps.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/chelsio/cxgb4/cxgb4_mps.c
@@ -229,7 +229,7 @@
 {
 	struct mps_entries_ref *mps_entry, *tmp;
 
-	if (!list_empty(&adap->mps_ref))
+	if (list_empty(&adap->mps_ref))
 		return;
 
 	spin_lock(&adap->mps_ref_lock);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ptp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ptp.c
@@ -246,6 +246,9 @@
 			     FW_PTP_CMD_PORTID_V(0));
 	c.retval_len16 = cpu_to_be32(FW_CMD_LEN16_V(sizeof(c) / 16));
 	c.u.ts.sc = FW_PTP_SC_ADJ_FTIME;
+	c.u.ts.sign = (delta < 0) ? 1 : 0;
+	if (delta < 0)
+		delta = -delta;
 	c.u.ts.tm = cpu_to_be64(delta);
 
 	err = t4_wr_mbox(adapter, adapter->mbox, &c, sizeof(c), NULL);
@@ -308,32 +311,17 @@
  */
 static int cxgb4_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
 {
-	struct adapter *adapter = (struct adapter *)container_of(ptp,
-				   struct adapter, ptp_clock_info);
-	struct fw_ptp_cmd c;
+	struct adapter *adapter = container_of(ptp, struct adapter,
+					       ptp_clock_info);
 	u64 ns;
-	int err;
 
-	memset(&c, 0, sizeof(c));
-	c.op_to_portid = cpu_to_be32(FW_CMD_OP_V(FW_PTP_CMD) |
-				     FW_CMD_REQUEST_F |
-				     FW_CMD_READ_F |
-				     FW_PTP_CMD_PORTID_V(0));
-	c.retval_len16 = cpu_to_be32(FW_CMD_LEN16_V(sizeof(c) / 16));
-	c.u.ts.sc = FW_PTP_SC_GET_TIME;
-
-	err = t4_wr_mbox(adapter, adapter->mbox, &c, sizeof(c), &c);
-	if (err < 0) {
-		dev_err(adapter->pdev_dev,
-			"PTP: %s error %d\n", __func__, -err);
-		return err;
-	}
+	ns = t4_read_reg(adapter, T5_PORT_REG(0, MAC_PORT_PTP_SUM_LO_A));
+	ns |= (u64)t4_read_reg(adapter,
+			       T5_PORT_REG(0, MAC_PORT_PTP_SUM_HI_A)) << 32;
 
 	/* convert to timespec*/
-	ns = be64_to_cpu(c.u.ts.tm);
 	*ts = ns_to_timespec64(ns);
-
-	return err;
+	return 0;
 }
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
@@ -58,12 +58,91 @@
 	PEDIT_FIELDS(IP6_, DST_63_32, 4, nat_lip, 4),
 	PEDIT_FIELDS(IP6_, DST_95_64, 4, nat_lip, 8),
 	PEDIT_FIELDS(IP6_, DST_127_96, 4, nat_lip, 12),
-	PEDIT_FIELDS(TCP_, SPORT, 2, nat_fport, 0),
-	PEDIT_FIELDS(TCP_, DPORT, 2, nat_lport, 0),
-	PEDIT_FIELDS(UDP_, SPORT, 2, nat_fport, 0),
-	PEDIT_FIELDS(UDP_, DPORT, 2, nat_lport, 0),
 };
 
+static const struct cxgb4_natmode_config cxgb4_natmode_config_array[] = {
+	/* Default supported NAT modes */
+	{
+		.chip = CHELSIO_T5,
+		.flags = CXGB4_ACTION_NATMODE_NONE,
+		.natmode = NAT_MODE_NONE,
+	},
+	{
+		.chip = CHELSIO_T5,
+		.flags = CXGB4_ACTION_NATMODE_DIP,
+		.natmode = NAT_MODE_DIP,
+	},
+	{
+		.chip = CHELSIO_T5,
+		.flags = CXGB4_ACTION_NATMODE_DIP | CXGB4_ACTION_NATMODE_DPORT,
+		.natmode = NAT_MODE_DIP_DP,
+	},
+	{
+		.chip = CHELSIO_T5,
+		.flags = CXGB4_ACTION_NATMODE_DIP | CXGB4_ACTION_NATMODE_DPORT |
+			 CXGB4_ACTION_NATMODE_SIP,
+		.natmode = NAT_MODE_DIP_DP_SIP,
+	},
+	{
+		.chip = CHELSIO_T5,
+		.flags = CXGB4_ACTION_NATMODE_DIP | CXGB4_ACTION_NATMODE_DPORT |
+			 CXGB4_ACTION_NATMODE_SPORT,
+		.natmode = NAT_MODE_DIP_DP_SP,
+	},
+	{
+		.chip = CHELSIO_T5,
+		.flags = CXGB4_ACTION_NATMODE_SIP | CXGB4_ACTION_NATMODE_SPORT,
+		.natmode = NAT_MODE_SIP_SP,
+	},
+	{
+		.chip = CHELSIO_T5,
+		.flags = CXGB4_ACTION_NATMODE_DIP | CXGB4_ACTION_NATMODE_SIP |
+			 CXGB4_ACTION_NATMODE_SPORT,
+		.natmode = NAT_MODE_DIP_SIP_SP,
+	},
+	{
+		.chip = CHELSIO_T5,
+		.flags = CXGB4_ACTION_NATMODE_DIP | CXGB4_ACTION_NATMODE_SIP |
+			 CXGB4_ACTION_NATMODE_DPORT |
+			 CXGB4_ACTION_NATMODE_SPORT,
+		.natmode = NAT_MODE_ALL,
+	},
+	/* T6+ can ignore L4 ports when they're disabled. */
+	{
+		.chip = CHELSIO_T6,
+		.flags = CXGB4_ACTION_NATMODE_SIP,
+		.natmode = NAT_MODE_SIP_SP,
+	},
+	{
+		.chip = CHELSIO_T6,
+		.flags = CXGB4_ACTION_NATMODE_DIP | CXGB4_ACTION_NATMODE_SPORT,
+		.natmode = NAT_MODE_DIP_DP_SP,
+	},
+	{
+		.chip = CHELSIO_T6,
+		.flags = CXGB4_ACTION_NATMODE_DIP | CXGB4_ACTION_NATMODE_SIP,
+		.natmode = NAT_MODE_ALL,
+	},
+};
+
+static void cxgb4_action_natmode_tweak(struct ch_filter_specification *fs,
+				       u8 natmode_flags)
+{
+	u8 i = 0;
+
+	/* Translate the enabled NAT 4-tuple fields to one of the
+	 * hardware supported NAT mode configurations. This ensures
+	 * that we pick a valid combination, where the disabled fields
+	 * do not get overwritten to 0.
+	 */
+	for (i = 0; i < ARRAY_SIZE(cxgb4_natmode_config_array); i++) {
+		if (cxgb4_natmode_config_array[i].flags == natmode_flags) {
+			fs->nat_mode = cxgb4_natmode_config_array[i].natmode;
+			return;
+		}
+	}
+}
+
 static struct ch_tc_flower_entry *allocate_flower_entry(void)
 {
 	struct ch_tc_flower_entry *new = kzalloc(sizeof(*new), GFP_KERNEL);
@@ -156,14 +235,14 @@
 		struct flow_match_ports match;
 
 		flow_rule_match_ports(rule, &match);
-		fs->val.lport = cpu_to_be16(match.key->dst);
-		fs->mask.lport = cpu_to_be16(match.mask->dst);
-		fs->val.fport = cpu_to_be16(match.key->src);
-		fs->mask.fport = cpu_to_be16(match.mask->src);
+		fs->val.lport = be16_to_cpu(match.key->dst);
+		fs->mask.lport = be16_to_cpu(match.mask->dst);
+		fs->val.fport = be16_to_cpu(match.key->src);
+		fs->mask.fport = be16_to_cpu(match.mask->src);
 
 		/* also initialize nat_lport/fport to same values */
-		fs->nat_lport = cpu_to_be16(match.key->dst);
-		fs->nat_fport = cpu_to_be16(match.key->src);
+		fs->nat_lport = fs->val.lport;
+		fs->nat_fport = fs->val.fport;
 	}
 
 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) {
@@ -291,7 +370,8 @@
 }
 
 static void process_pedit_field(struct ch_filter_specification *fs, u32 val,
-				u32 mask, u32 offset, u8 htype)
+				u32 mask, u32 offset, u8 htype,
+				u8 *natmode_flags)
 {
 	switch (htype) {
 	case FLOW_ACT_MANGLE_HDR_TYPE_ETH:
@@ -316,74 +396,104 @@
 		switch (offset) {
 		case PEDIT_IP4_SRC:
 			offload_pedit(fs, val, mask, IP4_SRC);
+			*natmode_flags |= CXGB4_ACTION_NATMODE_SIP;
 			break;
 		case PEDIT_IP4_DST:
 			offload_pedit(fs, val, mask, IP4_DST);
+			*natmode_flags |= CXGB4_ACTION_NATMODE_DIP;
 		}
-		fs->nat_mode = NAT_MODE_ALL;
 		break;
 	case FLOW_ACT_MANGLE_HDR_TYPE_IP6:
 		switch (offset) {
 		case PEDIT_IP6_SRC_31_0:
 			offload_pedit(fs, val, mask, IP6_SRC_31_0);
+			*natmode_flags |= CXGB4_ACTION_NATMODE_SIP;
 			break;
 		case PEDIT_IP6_SRC_63_32:
 			offload_pedit(fs, val, mask, IP6_SRC_63_32);
+			*natmode_flags |=  CXGB4_ACTION_NATMODE_SIP;
 			break;
 		case PEDIT_IP6_SRC_95_64:
 			offload_pedit(fs, val, mask, IP6_SRC_95_64);
+			*natmode_flags |= CXGB4_ACTION_NATMODE_SIP;
 			break;
 		case PEDIT_IP6_SRC_127_96:
 			offload_pedit(fs, val, mask, IP6_SRC_127_96);
+			*natmode_flags |= CXGB4_ACTION_NATMODE_SIP;
 			break;
 		case PEDIT_IP6_DST_31_0:
 			offload_pedit(fs, val, mask, IP6_DST_31_0);
+			*natmode_flags |= CXGB4_ACTION_NATMODE_DIP;
 			break;
 		case PEDIT_IP6_DST_63_32:
 			offload_pedit(fs, val, mask, IP6_DST_63_32);
+			*natmode_flags |= CXGB4_ACTION_NATMODE_DIP;
 			break;
 		case PEDIT_IP6_DST_95_64:
 			offload_pedit(fs, val, mask, IP6_DST_95_64);
+			*natmode_flags |= CXGB4_ACTION_NATMODE_DIP;
 			break;
 		case PEDIT_IP6_DST_127_96:
 			offload_pedit(fs, val, mask, IP6_DST_127_96);
+			*natmode_flags |= CXGB4_ACTION_NATMODE_DIP;
 		}
-		fs->nat_mode = NAT_MODE_ALL;
 		break;
 	case FLOW_ACT_MANGLE_HDR_TYPE_TCP:
 		switch (offset) {
 		case PEDIT_TCP_SPORT_DPORT:
-			if (~mask & PEDIT_TCP_UDP_SPORT_MASK)
-				offload_pedit(fs, cpu_to_be32(val) >> 16,
-					      cpu_to_be32(mask) >> 16,
-					      TCP_SPORT);
-			else
-				offload_pedit(fs, cpu_to_be32(val),
-					      cpu_to_be32(mask), TCP_DPORT);
+			if (~mask & PEDIT_TCP_UDP_SPORT_MASK) {
+				fs->nat_fport = val;
+				*natmode_flags |= CXGB4_ACTION_NATMODE_SPORT;
+			} else {
+				fs->nat_lport = val >> 16;
+				*natmode_flags |= CXGB4_ACTION_NATMODE_DPORT;
+			}
 		}
-		fs->nat_mode = NAT_MODE_ALL;
 		break;
 	case FLOW_ACT_MANGLE_HDR_TYPE_UDP:
 		switch (offset) {
 		case PEDIT_UDP_SPORT_DPORT:
-			if (~mask & PEDIT_TCP_UDP_SPORT_MASK)
-				offload_pedit(fs, cpu_to_be32(val) >> 16,
-					      cpu_to_be32(mask) >> 16,
-					      UDP_SPORT);
-			else
-				offload_pedit(fs, cpu_to_be32(val),
-					      cpu_to_be32(mask), UDP_DPORT);
+			if (~mask & PEDIT_TCP_UDP_SPORT_MASK) {
+				fs->nat_fport = val;
+				*natmode_flags |= CXGB4_ACTION_NATMODE_SPORT;
+			} else {
+				fs->nat_lport = val >> 16;
+				*natmode_flags |= CXGB4_ACTION_NATMODE_DPORT;
+			}
 		}
-		fs->nat_mode = NAT_MODE_ALL;
+		break;
 	}
 }
 
+static int cxgb4_action_natmode_validate(struct net_device *dev,
+					 struct adapter *adap, u8 natmode_flags)
+{
+	u8 i = 0;
+
+	/* Extract the NAT mode to enable based on what 4-tuple fields
+	 * are enabled to be overwritten. This ensures that the
+	 * disabled fields don't get overwritten to 0.
+	 */
+	for (i = 0; i < ARRAY_SIZE(cxgb4_natmode_config_array); i++) {
+		const struct cxgb4_natmode_config *c;
+
+		c = &cxgb4_natmode_config_array[i];
+		if (CHELSIO_CHIP_VERSION(adap->params.chip) >= c->chip &&
+		    natmode_flags == c->flags)
+			return 0;
+	}
+	netdev_err(dev, "%s: Unsupported NAT mode 4-tuple combination\n",
+		   __func__);
+	return -EOPNOTSUPP;
+}
+
 static void cxgb4_process_flow_actions(struct net_device *in,
 				       struct flow_cls_offload *cls,
 				       struct ch_filter_specification *fs)
 {
 	struct flow_rule *rule = flow_cls_offload_flow_rule(cls);
 	struct flow_action_entry *act;
+	u8 natmode_flags = 0;
 	int i;
 
 	flow_action_for_each(i, act, &rule->action) {
@@ -434,13 +544,17 @@
 			val = act->mangle.val;
 			offset = act->mangle.offset;
 
-			process_pedit_field(fs, val, mask, offset, htype);
+			process_pedit_field(fs, val, mask, offset, htype,
+					    &natmode_flags);
 			}
 			break;
 		default:
 			break;
 		}
 	}
+	if (natmode_flags)
+		cxgb4_action_natmode_tweak(fs, natmode_flags);
+
 }
 
 static bool valid_l4_mask(u32 mask)
@@ -457,7 +571,8 @@
 }
 
 static bool valid_pedit_action(struct net_device *dev,
-			       const struct flow_action_entry *act)
+			       const struct flow_action_entry *act,
+			       u8 *natmode_flags)
 {
 	u32 mask, offset;
 	u8 htype;
@@ -482,7 +597,10 @@
 	case FLOW_ACT_MANGLE_HDR_TYPE_IP4:
 		switch (offset) {
 		case PEDIT_IP4_SRC:
+			*natmode_flags |= CXGB4_ACTION_NATMODE_SIP;
+			break;
 		case PEDIT_IP4_DST:
+			*natmode_flags |= CXGB4_ACTION_NATMODE_DIP;
 			break;
 		default:
 			netdev_err(dev, "%s: Unsupported pedit field\n",
@@ -496,10 +614,13 @@
 		case PEDIT_IP6_SRC_63_32:
 		case PEDIT_IP6_SRC_95_64:
 		case PEDIT_IP6_SRC_127_96:
+			*natmode_flags |= CXGB4_ACTION_NATMODE_SIP;
+			break;
 		case PEDIT_IP6_DST_31_0:
 		case PEDIT_IP6_DST_63_32:
 		case PEDIT_IP6_DST_95_64:
 		case PEDIT_IP6_DST_127_96:
+			*natmode_flags |= CXGB4_ACTION_NATMODE_DIP;
 			break;
 		default:
 			netdev_err(dev, "%s: Unsupported pedit field\n",
@@ -515,6 +636,10 @@
 					   __func__);
 				return false;
 			}
+			if (~mask & PEDIT_TCP_UDP_SPORT_MASK)
+				*natmode_flags |= CXGB4_ACTION_NATMODE_SPORT;
+			else
+				*natmode_flags |= CXGB4_ACTION_NATMODE_DPORT;
 			break;
 		default:
 			netdev_err(dev, "%s: Unsupported pedit field\n",
@@ -530,6 +655,10 @@
 					   __func__);
 				return false;
 			}
+			if (~mask & PEDIT_TCP_UDP_SPORT_MASK)
+				*natmode_flags |= CXGB4_ACTION_NATMODE_SPORT;
+			else
+				*natmode_flags |= CXGB4_ACTION_NATMODE_DPORT;
 			break;
 		default:
 			netdev_err(dev, "%s: Unsupported pedit field\n",
@@ -548,10 +677,12 @@
 				       struct flow_cls_offload *cls)
 {
 	struct flow_rule *rule = flow_cls_offload_flow_rule(cls);
+	struct adapter *adap = netdev2adap(dev);
 	struct flow_action_entry *act;
 	bool act_redir = false;
 	bool act_pedit = false;
 	bool act_vlan = false;
+	u8 natmode_flags = 0;
 	int i;
 
 	flow_action_for_each(i, act, &rule->action) {
@@ -561,7 +692,6 @@
 			/* Do nothing */
 			break;
 		case FLOW_ACTION_REDIRECT: {
-			struct adapter *adap = netdev2adap(dev);
 			struct net_device *n_dev, *target_dev;
 			unsigned int i;
 			bool found = false;
@@ -611,7 +741,8 @@
 			}
 			break;
 		case FLOW_ACTION_MANGLE: {
-			bool pedit_valid = valid_pedit_action(dev, act);
+			bool pedit_valid = valid_pedit_action(dev, act,
+							      &natmode_flags);
 
 			if (!pedit_valid)
 				return -EOPNOTSUPP;
@@ -630,6 +761,14 @@
 		return -EINVAL;
 	}
 
+	if (act_pedit) {
+		int ret;
+
+		ret = cxgb4_action_natmode_validate(dev, adap, natmode_flags);
+		if (ret)
+			return ret;
+	}
+
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.h
@@ -108,6 +108,21 @@
 #define PEDIT_TCP_SPORT_DPORT		0x0
 #define PEDIT_UDP_SPORT_DPORT		0x0
 
+enum cxgb4_action_natmode_flags {
+	CXGB4_ACTION_NATMODE_NONE = 0,
+	CXGB4_ACTION_NATMODE_DIP = (1 << 0),
+	CXGB4_ACTION_NATMODE_SIP = (1 << 1),
+	CXGB4_ACTION_NATMODE_DPORT = (1 << 2),
+	CXGB4_ACTION_NATMODE_SPORT = (1 << 3),
+};
+
+/* TC PEDIT action to NATMODE translation entry */
+struct cxgb4_natmode_config {
+	enum chip_type chip;
+	u8 flags;
+	u8 natmode;
+};
+
 int cxgb4_tc_flower_replace(struct net_device *dev,
 			    struct flow_cls_offload *cls);
 int cxgb4_tc_flower_destroy(struct net_device *dev,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c
@@ -47,7 +47,7 @@
 			     bool next_header)
 {
 	unsigned int i, j;
-	u32 val, mask;
+	__be32 val, mask;
 	int off, err;
 	bool found;
 
@@ -216,7 +216,7 @@
 		const struct cxgb4_next_header *next;
 		bool found = false;
 		unsigned int i, j;
-		u32 val, mask;
+		__be32 val, mask;
 		int off;
 
 		if (t->table[link_uhtid - 1].link_handle) {
@@ -230,10 +230,10 @@
 
 		/* Try to find matches that allow jumps to next header. */
 		for (i = 0; next[i].jump; i++) {
-			if (next[i].offoff != cls->knode.sel->offoff ||
-			    next[i].shift != cls->knode.sel->offshift ||
-			    next[i].mask != cls->knode.sel->offmask ||
-			    next[i].offset != cls->knode.sel->off)
+			if (next[i].sel.offoff != cls->knode.sel->offoff ||
+			    next[i].sel.offshift != cls->knode.sel->offshift ||
+			    next[i].sel.offmask != cls->knode.sel->offmask ||
+			    next[i].sel.off != cls->knode.sel->off)
 				continue;
 
 			/* Found a possible candidate.  Find a key that
@@ -245,9 +245,9 @@
 				val = cls->knode.sel->keys[j].val;
 				mask = cls->knode.sel->keys[j].mask;
 
-				if (next[i].match_off == off &&
-				    next[i].match_val == val &&
-				    next[i].match_mask == mask) {
+				if (next[i].key.off == off &&
+				    next[i].key.val == val &&
+				    next[i].key.mask == mask) {
 					found = true;
 					break;
 				}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32_parse.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32_parse.h
@@ -38,12 +38,12 @@
 struct cxgb4_match_field {
 	int off; /* Offset from the beginning of the header to match */
 	/* Fill the value/mask pair in the spec if matched */
-	int (*val)(struct ch_filter_specification *f, u32 val, u32 mask);
+	int (*val)(struct ch_filter_specification *f, __be32 val, __be32 mask);
 };
 
 /* IPv4 match fields */
 static inline int cxgb4_fill_ipv4_tos(struct ch_filter_specification *f,
-				      u32 val, u32 mask)
+				      __be32 val, __be32 mask)
 {
 	f->val.tos  = (ntohl(val)  >> 16) & 0x000000FF;
 	f->mask.tos = (ntohl(mask) >> 16) & 0x000000FF;
@@ -52,7 +52,7 @@
 }
 
 static inline int cxgb4_fill_ipv4_frag(struct ch_filter_specification *f,
-				       u32 val, u32 mask)
+				       __be32 val, __be32 mask)
 {
 	u32 mask_val;
 	u8 frag_val;
@@ -74,7 +74,7 @@
 }
 
 static inline int cxgb4_fill_ipv4_proto(struct ch_filter_specification *f,
-					u32 val, u32 mask)
+					__be32 val, __be32 mask)
 {
 	f->val.proto  = (ntohl(val)  >> 16) & 0x000000FF;
 	f->mask.proto = (ntohl(mask) >> 16) & 0x000000FF;
@@ -83,7 +83,7 @@
 }
 
 static inline int cxgb4_fill_ipv4_src_ip(struct ch_filter_specification *f,
-					 u32 val, u32 mask)
+					 __be32 val, __be32 mask)
 {
 	memcpy(&f->val.fip[0],  &val,  sizeof(u32));
 	memcpy(&f->mask.fip[0], &mask, sizeof(u32));
@@ -92,7 +92,7 @@
 }
 
 static inline int cxgb4_fill_ipv4_dst_ip(struct ch_filter_specification *f,
-					 u32 val, u32 mask)
+					 __be32 val, __be32 mask)
 {
 	memcpy(&f->val.lip[0],  &val,  sizeof(u32));
 	memcpy(&f->mask.lip[0], &mask, sizeof(u32));
@@ -111,7 +111,7 @@
 
 /* IPv6 match fields */
 static inline int cxgb4_fill_ipv6_tos(struct ch_filter_specification *f,
-				      u32 val, u32 mask)
+				      __be32 val, __be32 mask)
 {
 	f->val.tos  = (ntohl(val)  >> 20) & 0x000000FF;
 	f->mask.tos = (ntohl(mask) >> 20) & 0x000000FF;
@@ -120,7 +120,7 @@
 }
 
 static inline int cxgb4_fill_ipv6_proto(struct ch_filter_specification *f,
-					u32 val, u32 mask)
+					__be32 val, __be32 mask)
 {
 	f->val.proto  = (ntohl(val)  >> 8) & 0x000000FF;
 	f->mask.proto = (ntohl(mask) >> 8) & 0x000000FF;
@@ -129,7 +129,7 @@
 }
 
 static inline int cxgb4_fill_ipv6_src_ip0(struct ch_filter_specification *f,
-					  u32 val, u32 mask)
+					  __be32 val, __be32 mask)
 {
 	memcpy(&f->val.fip[0],  &val,  sizeof(u32));
 	memcpy(&f->mask.fip[0], &mask, sizeof(u32));
@@ -138,7 +138,7 @@
 }
 
 static inline int cxgb4_fill_ipv6_src_ip1(struct ch_filter_specification *f,
-					  u32 val, u32 mask)
+					  __be32 val, __be32 mask)
 {
 	memcpy(&f->val.fip[4],  &val,  sizeof(u32));
 	memcpy(&f->mask.fip[4], &mask, sizeof(u32));
@@ -147,7 +147,7 @@
 }
 
 static inline int cxgb4_fill_ipv6_src_ip2(struct ch_filter_specification *f,
-					  u32 val, u32 mask)
+					  __be32 val, __be32 mask)
 {
 	memcpy(&f->val.fip[8],  &val,  sizeof(u32));
 	memcpy(&f->mask.fip[8], &mask, sizeof(u32));
@@ -156,7 +156,7 @@
 }
 
 static inline int cxgb4_fill_ipv6_src_ip3(struct ch_filter_specification *f,
-					  u32 val, u32 mask)
+					  __be32 val, __be32 mask)
 {
 	memcpy(&f->val.fip[12],  &val,  sizeof(u32));
 	memcpy(&f->mask.fip[12], &mask, sizeof(u32));
@@ -165,7 +165,7 @@
 }
 
 static inline int cxgb4_fill_ipv6_dst_ip0(struct ch_filter_specification *f,
-					  u32 val, u32 mask)
+					  __be32 val, __be32 mask)
 {
 	memcpy(&f->val.lip[0],  &val,  sizeof(u32));
 	memcpy(&f->mask.lip[0], &mask, sizeof(u32));
@@ -174,7 +174,7 @@
 }
 
 static inline int cxgb4_fill_ipv6_dst_ip1(struct ch_filter_specification *f,
-					  u32 val, u32 mask)
+					  __be32 val, __be32 mask)
 {
 	memcpy(&f->val.lip[4],  &val,  sizeof(u32));
 	memcpy(&f->mask.lip[4], &mask, sizeof(u32));
@@ -183,7 +183,7 @@
 }
 
 static inline int cxgb4_fill_ipv6_dst_ip2(struct ch_filter_specification *f,
-					  u32 val, u32 mask)
+					  __be32 val, __be32 mask)
 {
 	memcpy(&f->val.lip[8],  &val,  sizeof(u32));
 	memcpy(&f->mask.lip[8], &mask, sizeof(u32));
@@ -192,7 +192,7 @@
 }
 
 static inline int cxgb4_fill_ipv6_dst_ip3(struct ch_filter_specification *f,
-					  u32 val, u32 mask)
+					  __be32 val, __be32 mask)
 {
 	memcpy(&f->val.lip[12],  &val,  sizeof(u32));
 	memcpy(&f->mask.lip[12], &mask, sizeof(u32));
@@ -216,7 +216,7 @@
 
 /* TCP/UDP match */
 static inline int cxgb4_fill_l4_ports(struct ch_filter_specification *f,
-				      u32 val, u32 mask)
+				      __be32 val, __be32 mask)
 {
 	f->val.fport  = ntohl(val)  >> 16;
 	f->mask.fport = ntohl(mask) >> 16;
@@ -237,19 +237,13 @@
 };
 
 struct cxgb4_next_header {
-	unsigned int offset; /* Offset to next header */
-	/* offset, shift, and mask added to offset above
+	/* Offset, shift, and mask added to beginning of the header
 	 * to get to next header.  Useful when using a header
 	 * field's value to jump to next header such as IHL field
 	 * in IPv4 header.
 	 */
-	unsigned int offoff;
-	u32 shift;
-	u32 mask;
-	/* match criteria to make this jump */
-	unsigned int match_off;
-	u32 match_val;
-	u32 match_mask;
+	struct tc_u32_sel sel;
+	struct tc_u32_key key;
 	/* location of jump to make */
 	const struct cxgb4_match_field *jump;
 };
@@ -258,26 +252,74 @@
  * IPv4 header.
  */
 static const struct cxgb4_next_header cxgb4_ipv4_jumps[] = {
-	{ .offset = 0, .offoff = 0, .shift = 6, .mask = 0xF,
-	  .match_off = 8, .match_val = 0x600, .match_mask = 0xFF00,
-	  .jump = cxgb4_tcp_fields },
-	{ .offset = 0, .offoff = 0, .shift = 6, .mask = 0xF,
-	  .match_off = 8, .match_val = 0x1100, .match_mask = 0xFF00,
-	  .jump = cxgb4_udp_fields },
-	{ .jump = NULL }
+	{
+		/* TCP Jump */
+		.sel = {
+			.off = 0,
+			.offoff = 0,
+			.offshift = 6,
+			.offmask = cpu_to_be16(0x0f00),
+		},
+		.key = {
+			.off = 8,
+			.val = cpu_to_be32(0x00060000),
+			.mask = cpu_to_be32(0x00ff0000),
+		},
+		.jump = cxgb4_tcp_fields,
+	},
+	{
+		/* UDP Jump */
+		.sel = {
+			.off = 0,
+			.offoff = 0,
+			.offshift = 6,
+			.offmask = cpu_to_be16(0x0f00),
+		},
+		.key = {
+			.off = 8,
+			.val = cpu_to_be32(0x00110000),
+			.mask = cpu_to_be32(0x00ff0000),
+		},
+		.jump = cxgb4_udp_fields,
+	},
+	{ .jump = NULL },
 };
 
 /* Accept a rule with a jump directly past the 40 Bytes of IPv6 fixed header
  * to get to transport layer header.
  */
 static const struct cxgb4_next_header cxgb4_ipv6_jumps[] = {
-	{ .offset = 0x28, .offoff = 0, .shift = 0, .mask = 0,
-	  .match_off = 4, .match_val = 0x60000, .match_mask = 0xFF0000,
-	  .jump = cxgb4_tcp_fields },
-	{ .offset = 0x28, .offoff = 0, .shift = 0, .mask = 0,
-	  .match_off = 4, .match_val = 0x110000, .match_mask = 0xFF0000,
-	  .jump = cxgb4_udp_fields },
-	{ .jump = NULL }
+	{
+		/* TCP Jump */
+		.sel = {
+			.off = 40,
+			.offoff = 0,
+			.offshift = 0,
+			.offmask = 0,
+		},
+		.key = {
+			.off = 4,
+			.val = cpu_to_be32(0x00000600),
+			.mask = cpu_to_be32(0x0000ff00),
+		},
+		.jump = cxgb4_tcp_fields,
+	},
+	{
+		/* UDP Jump */
+		.sel = {
+			.off = 40,
+			.offoff = 0,
+			.offshift = 0,
+			.offmask = 0,
+		},
+		.key = {
+			.off = 4,
+			.val = cpu_to_be32(0x00001100),
+			.mask = cpu_to_be32(0x0000ff00),
+		},
+		.jump = cxgb4_udp_fields,
+	},
+	{ .jump = NULL },
 };
 
 struct cxgb4_link {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/chelsio/cxgb4/cxgb4_thermal.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/chelsio/cxgb4/cxgb4_thermal.c
@@ -62,6 +62,7 @@
 int cxgb4_thermal_init(struct adapter *adap)
 {
 	struct ch_thermal *ch_thermal = &adap->ch_thermal;
+	char ch_tz_name[THERMAL_NAME_LENGTH];
 	int num_trip = CXGB4_NUM_TRIPS;
 	u32 param, val;
 	int ret;
@@ -82,7 +83,8 @@
 		ch_thermal->trip_type = THERMAL_TRIP_CRITICAL;
 	}
 
-	ch_thermal->tzdev = thermal_zone_device_register("cxgb4", num_trip,
+	snprintf(ch_tz_name, sizeof(ch_tz_name), "cxgb4_%s", adap->name);
+	ch_thermal->tzdev = thermal_zone_device_register(ch_tz_name, num_trip,
 							 0, adap,
 							 &cxgb4_thermal_ops,
 							 NULL, 0, 0);
@@ -97,7 +99,9 @@
 
 int cxgb4_thermal_remove(struct adapter *adap)
 {
-	if (adap->ch_thermal.tzdev)
+	if (adap->ch_thermal.tzdev) {
 		thermal_zone_device_unregister(adap->ch_thermal.tzdev);
+		adap->ch_thermal.tzdev = NULL;
+	}
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c
@@ -638,6 +638,9 @@
 {
 	unsigned int i;
 
+	if (!is_uld(adap))
+		return;
+
 	mutex_lock(&uld_mutex);
 	for (i = 0; i < CXGB4_ULD_MAX; i++) {
 		if (!adap->uld[i].handle)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
@@ -44,6 +44,9 @@
 
 #define MAX_ULD_QSETS 16
 
+/* ulp_mem_io + ulptx_idata + payload + padding */
+#define MAX_IMM_ULPTX_WR_LEN (32 + 8 + 256 + 8)
+
 /* CPL message priority levels */
 enum {
 	CPL_PRIORITY_DATA     = 0,  /* data messages */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/chelsio/cxgb4/l2t.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/chelsio/cxgb4/l2t.c
@@ -507,40 +507,19 @@
 EXPORT_SYMBOL(cxgb4_select_ntuple);
 
 /*
- * Called when address resolution fails for an L2T entry to handle packets
- * on the arpq head.  If a packet specifies a failure handler it is invoked,
- * otherwise the packet is sent to the device.
- */
-static void handle_failed_resolution(struct adapter *adap, struct l2t_entry *e)
-{
-	struct sk_buff *skb;
-
-	while ((skb = __skb_dequeue(&e->arpq)) != NULL) {
-		const struct l2t_skb_cb *cb = L2T_SKB_CB(skb);
-
-		spin_unlock(&e->lock);
-		if (cb->arp_err_handler)
-			cb->arp_err_handler(cb->handle, skb);
-		else
-			t4_ofld_send(adap, skb);
-		spin_lock(&e->lock);
-	}
-}
-
-/*
  * Called when the host's neighbor layer makes a change to some entry that is
  * loaded into the HW L2 table.
  */
 void t4_l2t_update(struct adapter *adap, struct neighbour *neigh)
 {
-	struct l2t_entry *e;
-	struct sk_buff_head *arpq = NULL;
-	struct l2t_data *d = adap->l2t;
 	unsigned int addr_len = neigh->tbl->key_len;
 	u32 *addr = (u32 *) neigh->primary_key;
-	int ifidx = neigh->dev->ifindex;
-	int hash = addr_hash(d, addr, addr_len, ifidx);
+	int hash, ifidx = neigh->dev->ifindex;
+	struct sk_buff_head *arpq = NULL;
+	struct l2t_data *d = adap->l2t;
+	struct l2t_entry *e;
 
+	hash = addr_hash(d, addr, addr_len, ifidx);
 	read_lock_bh(&d->lock);
 	for (e = d->l2tab[hash].first; e; e = e->next)
 		if (!addreq(e, addr) && e->ifindex == ifidx) {
@@ -573,8 +552,25 @@
 			write_l2e(adap, e, 0);
 	}
 
-	if (arpq)
-		handle_failed_resolution(adap, e);
+	if (arpq) {
+		struct sk_buff *skb;
+
+		/* Called when address resolution fails for an L2T
+		 * entry to handle packets on the arpq head. If a
+		 * packet specifies a failure handler it is invoked,
+		 * otherwise the packet is sent to the device.
+		 */
+		while ((skb = __skb_dequeue(&e->arpq)) != NULL) {
+			const struct l2t_skb_cb *cb = L2T_SKB_CB(skb);
+
+			spin_unlock(&e->lock);
+			if (cb->arp_err_handler)
+				cb->arp_err_handler(cb->handle, skb);
+			else
+				t4_ofld_send(adap, skb);
+			spin_lock(&e->lock);
+		}
+	}
 	spin_unlock_bh(&e->lock);
 }
 
@@ -682,8 +678,7 @@
 static void *l2t_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
 	v = l2t_get_idx(seq, *pos);
-	if (v)
-		++*pos;
+	++(*pos);
 	return v;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/chelsio/cxgb4/sge.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/chelsio/cxgb4/sge.c
@@ -1324,8 +1324,9 @@
 int t4_sge_eth_txq_egress_update(struct adapter *adap, struct sge_eth_txq *eq,
 				 int maxreclaim)
 {
+	unsigned int reclaimed, hw_cidx;
 	struct sge_txq *q = &eq->q;
-	unsigned int reclaimed;
+	int hw_in_use;
 
 	if (!q->in_use || !__netif_tx_trylock(eq->txq))
 		return 0;
@@ -1333,12 +1334,17 @@
 	/* Reclaim pending completed TX Descriptors. */
 	reclaimed = reclaim_completed_tx(adap, &eq->q, maxreclaim, true);
 
+	hw_cidx = ntohs(READ_ONCE(q->stat->cidx));
+	hw_in_use = q->pidx - hw_cidx;
+	if (hw_in_use < 0)
+		hw_in_use += q->size;
+
 	/* If the TX Queue is currently stopped and there's now more than half
 	 * the queue available, restart it.  Otherwise bail out since the rest
 	 * of what we want do here is with the possibility of shipping any
 	 * currently buffered Coalesced TX Work Request.
 	 */
-	if (netif_tx_queue_stopped(eq->txq) && txq_avail(q) > (q->size / 2)) {
+	if (netif_tx_queue_stopped(eq->txq) && hw_in_use < (q->size / 2)) {
 		netif_tx_wake_queue(eq->txq);
 		eq->q.restarts++;
 	}
@@ -1469,16 +1475,7 @@
 		 * has opened up.
 		 */
 		eth_txq_stop(q);
-
-		/* If we're using the SGE Doorbell Queue Timer facility, we
-		 * don't need to ask the Firmware to send us Egress Queue CIDX
-		 * Updates: the Hardware will do this automatically.  And
-		 * since we send the Ingress Queue CIDX Updates to the
-		 * corresponding Ethernet Response Queue, we'll get them very
-		 * quickly.
-		 */
-		if (!q->dbqt)
-			wr_mid |= FW_WR_EQUEQ_F | FW_WR_EQUIQ_F;
+		wr_mid |= FW_WR_EQUEQ_F | FW_WR_EQUIQ_F;
 	}
 
 	wr = (void *)&q->q.desc[q->q.pidx];
@@ -1792,16 +1789,7 @@
 		 * has opened up.
 		 */
 		eth_txq_stop(txq);
-
-		/* If we're using the SGE Doorbell Queue Timer facility, we
-		 * don't need to ask the Firmware to send us Egress Queue CIDX
-		 * Updates: the Hardware will do this automatically.  And
-		 * since we send the Ingress Queue CIDX Updates to the
-		 * corresponding Ethernet Response Queue, we'll get them very
-		 * quickly.
-		 */
-		if (!txq->dbqt)
-			wr_mid |= FW_WR_EQUEQ_F | FW_WR_EQUIQ_F;
+		wr_mid |= FW_WR_EQUEQ_F | FW_WR_EQUIQ_F;
 	}
 
 	/* Start filling in our Work Request.  Note that we do _not_ handle
@@ -2170,17 +2158,22 @@
  *	@skb: the packet
  *
  *	Returns true if a packet can be sent as an offload WR with immediate
- *	data.  We currently use the same limit as for Ethernet packets.
+ *	data.
+ *	FW_OFLD_TX_DATA_WR limits the payload to 255 bytes due to 8-bit field.
+ *      However, FW_ULPTX_WR commands have a 256 byte immediate only
+ *      payload limit.
  */
 static inline int is_ofld_imm(const struct sk_buff *skb)
 {
 	struct work_request_hdr *req = (struct work_request_hdr *)skb->data;
 	unsigned long opcode = FW_WR_OP_G(ntohl(req->wr_hi));
 
-	if (opcode == FW_CRYPTO_LOOKASIDE_WR)
+	if (unlikely(opcode == FW_ULPTX_WR))
+		return skb->len <= MAX_IMM_ULPTX_WR_LEN;
+	else if (opcode == FW_CRYPTO_LOOKASIDE_WR)
 		return skb->len <= SGE_MAX_WR_LEN;
 	else
-		return skb->len <= MAX_IMM_TX_PKT_LEN;
+		return skb->len <= MAX_IMM_OFLD_TX_DATA_WR_LEN;
 }
 
 /**
@@ -2453,6 +2446,7 @@
 	txq_info = adap->sge.uld_txq_info[tx_uld_type];
 	if (unlikely(!txq_info)) {
 		WARN_ON(true);
+		kfree_skb(skb);
 		return NET_XMIT_DROP;
 	}
 
@@ -2828,7 +2822,7 @@
 
 	hwtstamps = skb_hwtstamps(skb);
 	memset(hwtstamps, 0, sizeof(*hwtstamps));
-	hwtstamps->hwtstamp = ns_to_ktime(be64_to_cpu(*((u64 *)data)));
+	hwtstamps->hwtstamp = ns_to_ktime(get_unaligned_be64(data));
 
 	return RX_PTP_PKT_SUC;
 }
@@ -2924,26 +2918,6 @@
 	}
 
 	txq = &s->ethtxq[pi->first_qset + rspq->idx];
-
-	/* We've got the Hardware Consumer Index Update in the Egress Update
-	 * message.  If we're using the SGE Doorbell Queue Timer mechanism,
-	 * these Egress Update messages will be our sole CIDX Updates we get
-	 * since we don't want to chew up PCIe bandwidth for both Ingress
-	 * Messages and Status Page writes.  However, The code which manages
-	 * reclaiming successfully DMA'ed TX Work Requests uses the CIDX value
-	 * stored in the Status Page at the end of the TX Queue.  It's easiest
-	 * to simply copy the CIDX Update value from the Egress Update message
-	 * to the Status Page.  Also note that no Endian issues need to be
-	 * considered here since both are Big Endian and we're just copying
-	 * bytes consistently ...
-	 */
-	if (txq->dbqt) {
-		struct cpl_sge_egr_update *egr;
-
-		egr = (struct cpl_sge_egr_update *)rsp;
-		WRITE_ONCE(txq->q.stat->cidx, egr->cidx);
-	}
-
 	t4_sge_eth_txq_egress_update(adapter, txq, -1);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
@@ -2093,7 +2093,8 @@
 		0x1190, 0x1194,
 		0x11a0, 0x11a4,
 		0x11b0, 0x11b4,
-		0x11fc, 0x1274,
+		0x11fc, 0x123c,
+		0x1254, 0x1274,
 		0x1280, 0x133c,
 		0x1800, 0x18fc,
 		0x3000, 0x302c,
@@ -3499,7 +3500,7 @@
 	drv_fw = &fw_info->fw_hdr;
 
 	/* Read the header of the firmware on the card */
-	ret = -t4_read_flash(adap, FLASH_FW_START,
+	ret = t4_read_flash(adap, FLASH_FW_START,
 			    sizeof(*card_fw) / sizeof(uint32_t),
 			    (uint32_t *)card_fw, 1);
 	if (ret == 0) {
@@ -3528,8 +3529,8 @@
 		   should_install_fs_fw(adap, card_fw_usable,
 					be32_to_cpu(fs_fw->fw_ver),
 					be32_to_cpu(card_fw->fw_ver))) {
-		ret = -t4_fw_upgrade(adap, adap->mbox, fw_data,
-				     fw_size, 0);
+		ret = t4_fw_upgrade(adap, adap->mbox, fw_data,
+				    fw_size, 0);
 		if (ret != 0) {
 			dev_err(adap->pdev_dev,
 				"failed to install firmware: %d\n", ret);
@@ -3560,7 +3561,7 @@
 			FW_HDR_FW_VER_MICRO_G(c), FW_HDR_FW_VER_BUILD_G(c),
 			FW_HDR_FW_VER_MAJOR_G(k), FW_HDR_FW_VER_MINOR_G(k),
 			FW_HDR_FW_VER_MICRO_G(k), FW_HDR_FW_VER_BUILD_G(k));
-		ret = EINVAL;
+		ret = -EINVAL;
 		goto bye;
 	}
 
@@ -3748,7 +3749,7 @@
 		 FW_PARAMS_PARAM_Z_V(FW_PARAMS_PARAM_DEV_PHYFW_VERSION));
 	ret = t4_query_params(adap, adap->mbox, adap->pf, 0, 1,
 			      &param, &val);
-	if (ret < 0)
+	if (ret)
 		return ret;
 	*phy_fw_ver = val;
 	return 0;
@@ -3849,6 +3850,8 @@
 		 FW_PARAMS_PARAM_Z_V(FW_PARAMS_PARAM_DEV_PHYFW_DOWNLOAD));
 	ret = t4_set_params_timeout(adap, adap->mbox, adap->pf, 0, 1,
 				    &param, &val, 30000);
+	if (ret)
+		return ret;
 
 	/* If we have version number support, then check to see that the new
 	 * firmware got loaded properly.
@@ -4089,7 +4092,8 @@
 		if (cc_pause & PAUSE_TX)
 			fw_pause |= FW_PORT_CAP32_802_3_PAUSE;
 		else
-			fw_pause |= FW_PORT_CAP32_802_3_ASM_DIR;
+			fw_pause |= FW_PORT_CAP32_802_3_ASM_DIR |
+				    FW_PORT_CAP32_802_3_PAUSE;
 	} else if (cc_pause & PAUSE_TX) {
 		fw_pause |= FW_PORT_CAP32_802_3_ASM_DIR;
 	}
@@ -8563,17 +8567,17 @@
 void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
 {
 	const struct fw_port_cmd *cmd = (const void *)rpl;
-	int action = FW_PORT_CMD_ACTION_G(be32_to_cpu(cmd->action_to_len16));
-	struct adapter *adapter = pi->adapter;
+	fw_port_cap32_t pcaps, acaps, lpacaps, linkattr;
 	struct link_config *lc = &pi->link_cfg;
-	int link_ok, linkdnrc;
-	enum fw_port_type port_type;
+	struct adapter *adapter = pi->adapter;
+	unsigned int speed, fc, fec, adv_fc;
 	enum fw_port_module_type mod_type;
-	unsigned int speed, fc, fec;
-	fw_port_cap32_t pcaps, acaps, lpacaps, linkattr;
+	int action, link_ok, linkdnrc;
+	enum fw_port_type port_type;
 
 	/* Extract the various fields from the Port Information message.
 	 */
+	action = FW_PORT_CMD_ACTION_G(be32_to_cpu(cmd->action_to_len16));
 	switch (action) {
 	case FW_PORT_ACTION_GET_PORT_INFO: {
 		u32 lstatus = be32_to_cpu(cmd->u.info.lstatus_to_modtype);
@@ -8611,6 +8615,7 @@
 	}
 
 	fec = fwcap_to_cc_fec(acaps);
+	adv_fc = fwcap_to_cc_pause(acaps);
 	fc = fwcap_to_cc_pause(linkattr);
 	speed = fwcap_to_speed(linkattr);
 
@@ -8667,7 +8672,9 @@
 	}
 
 	if (link_ok != lc->link_ok || speed != lc->speed ||
-	    fc != lc->fc || fec != lc->fec) {	/* something changed */
+	    fc != lc->fc || adv_fc != lc->advertised_fc ||
+	    fec != lc->fec) {
+		/* something changed */
 		if (!link_ok && lc->link_ok) {
 			lc->link_down_rc = linkdnrc;
 			dev_warn_ratelimited(adapter->pdev_dev,
@@ -8677,6 +8684,7 @@
 		}
 		lc->link_ok = link_ok;
 		lc->speed = speed;
+		lc->advertised_fc = adv_fc;
 		lc->fc = fc;
 		lc->fec = fec;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h
@@ -293,6 +293,8 @@
 #define I2C_PAGE_SIZE		0x100
 #define SFP_DIAG_TYPE_ADDR	0x5c
 #define SFP_DIAG_TYPE_LEN	0x1
+#define SFP_DIAG_ADDRMODE	BIT(2)
+#define SFP_DIAG_IMPLEMENTED	BIT(6)
 #define SFF_8472_COMP_ADDR	0x5e
 #define SFF_8472_COMP_LEN	0x1
 #define SFF_REV_ADDR		0x1
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/chelsio/cxgb4/t4_pci_id_tbl.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/chelsio/cxgb4/t4_pci_id_tbl.h
@@ -219,6 +219,7 @@
 	CH_PCI_ID_TABLE_FENTRY(0x6089), /* Custom T62100-KR */
 	CH_PCI_ID_TABLE_FENTRY(0x608a), /* Custom T62100-CR */
 	CH_PCI_ID_TABLE_FENTRY(0x608b), /* Custom T6225-CR */
+	CH_PCI_ID_TABLE_FENTRY(0x6092), /* Custom T62100-CR-LOM */
 CH_PCI_DEVICE_ID_TABLE_DEFINE_END;
 
 #endif /* __T4_PCI_ID_TBL_H__ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
@@ -1900,6 +1900,9 @@
 
 #define MAC_PORT_CFG2_A 0x818
 
+#define MAC_PORT_PTP_SUM_LO_A 0x990
+#define MAC_PORT_PTP_SUM_HI_A 0x994
+
 #define MPS_CMN_CTL_A	0x9000
 
 #define COUNTPAUSEMCRX_S    5
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/chelsio/cxgb4/t4_tcb.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/chelsio/cxgb4/t4_tcb.h
@@ -50,6 +50,10 @@
 #define TCB_RQ_START_M		0x3ffffffULL
 #define TCB_RQ_START_V(x)	((x) << TCB_RQ_START_S)
 
+#define TF_DROP_S		22
+#define TF_DIRECT_STEER_S	23
+#define TF_LPBK_S		59
+
 #define TF_CCTRL_ECE_S		60
 #define TF_CCTRL_CWR_S		61
 #define TF_CCTRL_RFR_S		62
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
@@ -860,7 +860,7 @@
 	 */
 	err = t4vf_update_port_info(pi);
 	if (err < 0)
-		return err;
+		goto err_unwind;
 
 	/*
 	 * Note that this interface is up and start everything up ...
@@ -1690,8 +1690,8 @@
 	struct port_info *pi = netdev_priv(dev);
 
 	pauseparam->autoneg = (pi->link_cfg.requested_fc & PAUSE_AUTONEG) != 0;
-	pauseparam->rx_pause = (pi->link_cfg.fc & PAUSE_RX) != 0;
-	pauseparam->tx_pause = (pi->link_cfg.fc & PAUSE_TX) != 0;
+	pauseparam->rx_pause = (pi->link_cfg.advertised_fc & PAUSE_RX) != 0;
+	pauseparam->tx_pause = (pi->link_cfg.advertised_fc & PAUSE_TX) != 0;
 }
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h
@@ -135,6 +135,7 @@
 
 	enum cc_pause	requested_fc;	/* flow control user has requested */
 	enum cc_pause	fc;		/* actual link flow control */
+	enum cc_pause   advertised_fc;  /* actual advertised flow control */
 
 	enum cc_fec	auto_fec;	/* Forward Error Correction: */
 	enum cc_fec	requested_fec;	/*   "automatic" (IEEE 802.3), */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c
@@ -1913,16 +1913,16 @@
 static void t4vf_handle_get_port_info(struct port_info *pi,
 				      const struct fw_port_cmd *cmd)
 {
-	int action = FW_PORT_CMD_ACTION_G(be32_to_cpu(cmd->action_to_len16));
-	struct adapter *adapter = pi->adapter;
+	fw_port_cap32_t pcaps, acaps, lpacaps, linkattr;
 	struct link_config *lc = &pi->link_cfg;
-	int link_ok, linkdnrc;
-	enum fw_port_type port_type;
+	struct adapter *adapter = pi->adapter;
+	unsigned int speed, fc, fec, adv_fc;
 	enum fw_port_module_type mod_type;
-	unsigned int speed, fc, fec;
-	fw_port_cap32_t pcaps, acaps, lpacaps, linkattr;
+	int action, link_ok, linkdnrc;
+	enum fw_port_type port_type;
 
 	/* Extract the various fields from the Port Information message. */
+	action = FW_PORT_CMD_ACTION_G(be32_to_cpu(cmd->action_to_len16));
 	switch (action) {
 	case FW_PORT_ACTION_GET_PORT_INFO: {
 		u32 lstatus = be32_to_cpu(cmd->u.info.lstatus_to_modtype);
@@ -1982,6 +1982,7 @@
 	}
 
 	fec = fwcap_to_cc_fec(acaps);
+	adv_fc = fwcap_to_cc_pause(acaps);
 	fc = fwcap_to_cc_pause(linkattr);
 	speed = fwcap_to_speed(linkattr);
 
@@ -2012,7 +2013,9 @@
 	}
 
 	if (link_ok != lc->link_ok || speed != lc->speed ||
-	    fc != lc->fc || fec != lc->fec) {	/* something changed */
+	    fc != lc->fc || adv_fc != lc->advertised_fc ||
+	    fec != lc->fec) {
+		/* something changed */
 		if (!link_ok && lc->link_ok) {
 			lc->link_down_rc = linkdnrc;
 			dev_warn_ratelimited(adapter->pdev_dev,
@@ -2022,6 +2025,7 @@
 		}
 		lc->link_ok = link_ok;
 		lc->speed = speed;
+		lc->advertised_fc = adv_fc;
 		lc->fc = fc;
 		lc->fec = fec;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/chelsio/libcxgb/libcxgb_cm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/chelsio/libcxgb/libcxgb_cm.c
@@ -32,6 +32,7 @@
 
 #include <linux/tcp.h>
 #include <linux/ipv6.h>
+#include <net/inet_ecn.h>
 #include <net/route.h>
 #include <net/ip6_route.h>
 
@@ -99,7 +100,7 @@
 
 	rt = ip_route_output_ports(&init_net, &fl4, NULL, peer_ip, local_ip,
 				   peer_port, local_port, IPPROTO_TCP,
-				   tos, 0);
+				   tos & ~INET_ECN_MASK, 0);
 	if (IS_ERR(rt))
 		return NULL;
 	n = dst_neigh_lookup(&rt->dst, &peer_ip);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/cisco/enic/enic.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/cisco/enic/enic.h
@@ -171,6 +171,7 @@
 	u16 num_vfs;
 #endif
 	spinlock_t enic_api_lock;
+	bool enic_api_busy;
 	struct enic_port_profile *pp;
 
 	/* work queue cache line section */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/cisco/enic/enic_api.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/cisco/enic/enic_api.c
@@ -34,6 +34,12 @@
 	struct vnic_dev *vdev = enic->vdev;
 
 	spin_lock(&enic->enic_api_lock);
+	while (enic->enic_api_busy) {
+		spin_unlock(&enic->enic_api_lock);
+		cpu_relax();
+		spin_lock(&enic->enic_api_lock);
+	}
+
 	spin_lock_bh(&enic->devcmd_lock);
 
 	vnic_dev_cmd_proxy_by_index_start(vdev, vf);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/cisco/enic/enic_ethtool.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/cisco/enic/enic_ethtool.c
@@ -454,7 +454,6 @@
 		break;
 	default:
 		return -EINVAL;
-		break;
 	}
 
 	fsp->h_u.tcp_ip4_spec.ip4src = flow_get_u32_src(&n->keys);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/cisco/enic/enic_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -803,7 +803,7 @@
 	return err;
 }
 
-static inline void enic_queue_wq_skb(struct enic *enic,
+static inline int enic_queue_wq_skb(struct enic *enic,
 	struct vnic_wq *wq, struct sk_buff *skb)
 {
 	unsigned int mss = skb_shinfo(skb)->gso_size;
@@ -849,6 +849,7 @@
 		wq->to_use = buf->next;
 		dev_kfree_skb(skb);
 	}
+	return err;
 }
 
 /* netif_tx_lock held, process context with BHs disabled, or BH */
@@ -892,7 +893,8 @@
 		return NETDEV_TX_BUSY;
 	}
 
-	enic_queue_wq_skb(enic, wq, skb);
+	if (enic_queue_wq_skb(enic, wq, skb))
+		goto error;
 
 	if (vnic_wq_desc_avail(wq) < MAX_SKB_FRAGS + ENIC_DESC_MAX_SPLITS)
 		netif_tx_stop_queue(txq);
@@ -900,6 +902,7 @@
 	if (!netdev_xmit_more() || netif_xmit_stopped(txq))
 		vnic_wq_doorbell(wq);
 
+error:
 	spin_unlock(&enic->wq_lock[txq_map]);
 
 	return NETDEV_TX_OK;
@@ -1149,18 +1152,30 @@
 	pp->request = nla_get_u8(port[IFLA_PORT_REQUEST]);
 
 	if (port[IFLA_PORT_PROFILE]) {
+		if (nla_len(port[IFLA_PORT_PROFILE]) != PORT_PROFILE_MAX) {
+			memcpy(pp, &prev_pp, sizeof(*pp));
+			return -EINVAL;
+		}
 		pp->set |= ENIC_SET_NAME;
 		memcpy(pp->name, nla_data(port[IFLA_PORT_PROFILE]),
 			PORT_PROFILE_MAX);
 	}
 
 	if (port[IFLA_PORT_INSTANCE_UUID]) {
+		if (nla_len(port[IFLA_PORT_INSTANCE_UUID]) != PORT_UUID_MAX) {
+			memcpy(pp, &prev_pp, sizeof(*pp));
+			return -EINVAL;
+		}
 		pp->set |= ENIC_SET_INSTANCE;
 		memcpy(pp->instance_uuid,
 			nla_data(port[IFLA_PORT_INSTANCE_UUID]), PORT_UUID_MAX);
 	}
 
 	if (port[IFLA_PORT_HOST_UUID]) {
+		if (nla_len(port[IFLA_PORT_HOST_UUID]) != PORT_UUID_MAX) {
+			memcpy(pp, &prev_pp, sizeof(*pp));
+			return -EINVAL;
+		}
 		pp->set |= ENIC_SET_HOST;
 		memcpy(pp->host_uuid,
 			nla_data(port[IFLA_PORT_HOST_UUID]), PORT_UUID_MAX);
@@ -2013,10 +2028,10 @@
 		napi_disable(&enic->napi[i]);
 
 	netif_carrier_off(netdev);
-	netif_tx_disable(netdev);
 	if (vnic_dev_get_intr_mode(enic->vdev) == VNIC_DEV_INTR_MODE_MSIX)
 		for (i = 0; i < enic->wq_count; i++)
 			napi_disable(&enic->napi[enic_cq_wq(enic, i)]);
+	netif_tx_disable(netdev);
 
 	if (!enic_is_dynamic(enic) && !enic_is_sriov_vf(enic))
 		enic_dev_del_station_addr(enic);
@@ -2142,8 +2157,6 @@
 	int done;
 	int err;
 
-	BUG_ON(in_interrupt());
-
 	err = start(vdev, arg);
 	if (err)
 		return err;
@@ -2331,6 +2344,13 @@
 		rss_hash_bits, rss_base_cpu, rss_enable);
 }
 
+static void enic_set_api_busy(struct enic *enic, bool busy)
+{
+	spin_lock(&enic->enic_api_lock);
+	enic->enic_api_busy = busy;
+	spin_unlock(&enic->enic_api_lock);
+}
+
 static void enic_reset(struct work_struct *work)
 {
 	struct enic *enic = container_of(work, struct enic, reset);
@@ -2340,7 +2360,9 @@
 
 	rtnl_lock();
 
-	spin_lock(&enic->enic_api_lock);
+	/* Stop any activity from infiniband */
+	enic_set_api_busy(enic, true);
+
 	enic_stop(enic->netdev);
 	enic_dev_soft_reset(enic);
 	enic_reset_addr_lists(enic);
@@ -2348,7 +2370,10 @@
 	enic_set_rss_nic_cfg(enic);
 	enic_dev_set_ig_vlan_rewrite_mode(enic);
 	enic_open(enic->netdev);
-	spin_unlock(&enic->enic_api_lock);
+
+	/* Allow infiniband to fiddle with the device again */
+	enic_set_api_busy(enic, false);
+
 	call_netdevice_notifiers(NETDEV_REBOOT, enic->netdev);
 
 	rtnl_unlock();
@@ -2360,7 +2385,9 @@
 
 	rtnl_lock();
 
-	spin_lock(&enic->enic_api_lock);
+	/* Stop any activity from infiniband */
+	enic_set_api_busy(enic, true);
+
 	enic_dev_hang_notify(enic);
 	enic_stop(enic->netdev);
 	enic_dev_hang_reset(enic);
@@ -2369,7 +2396,10 @@
 	enic_set_rss_nic_cfg(enic);
 	enic_dev_set_ig_vlan_rewrite_mode(enic);
 	enic_open(enic->netdev);
-	spin_unlock(&enic->enic_api_lock);
+
+	/* Allow infiniband to fiddle with the device again */
+	enic_set_api_busy(enic, false);
+
 	call_netdevice_notifiers(NETDEV_REBOOT, enic->netdev);
 
 	rtnl_unlock();
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/cortina/gemini.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/cortina/gemini.c
@@ -81,8 +81,7 @@
 #define GMAC0_IRQ4_8 (GMAC0_MIB_INT_BIT | GMAC0_RX_OVERRUN_INT_BIT)
 
 #define GMAC_OFFLOAD_FEATURES (NETIF_F_SG | NETIF_F_IP_CSUM | \
-		NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM | \
-		NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6)
+			       NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM)
 
 /**
  * struct gmac_queue_page - page buffer per-page info
@@ -304,21 +303,21 @@
 	switch (phydev->speed) {
 	case 1000:
 		status.bits.speed = GMAC_SPEED_1000;
-		if (phydev->interface == PHY_INTERFACE_MODE_RGMII)
+		if (phy_interface_mode_is_rgmii(phydev->interface))
 			status.bits.mii_rmii = GMAC_PHY_RGMII_1000;
 		netdev_dbg(netdev, "connect %s to RGMII @ 1Gbit\n",
 			   phydev_name(phydev));
 		break;
 	case 100:
 		status.bits.speed = GMAC_SPEED_100;
-		if (phydev->interface == PHY_INTERFACE_MODE_RGMII)
+		if (phy_interface_mode_is_rgmii(phydev->interface))
 			status.bits.mii_rmii = GMAC_PHY_RGMII_100_10;
 		netdev_dbg(netdev, "connect %s to RGMII @ 100 Mbit\n",
 			   phydev_name(phydev));
 		break;
 	case 10:
 		status.bits.speed = GMAC_SPEED_10;
-		if (phydev->interface == PHY_INTERFACE_MODE_RGMII)
+		if (phy_interface_mode_is_rgmii(phydev->interface))
 			status.bits.mii_rmii = GMAC_PHY_RGMII_100_10;
 		netdev_dbg(netdev, "connect %s to RGMII @ 10 Mbit\n",
 			   phydev_name(phydev));
@@ -388,6 +387,9 @@
 		status.bits.mii_rmii = GMAC_PHY_GMII;
 		break;
 	case PHY_INTERFACE_MODE_RGMII:
+	case PHY_INTERFACE_MODE_RGMII_ID:
+	case PHY_INTERFACE_MODE_RGMII_TXID:
+	case PHY_INTERFACE_MODE_RGMII_RXID:
 		netdev_dbg(netdev,
 			   "RGMII: set GMAC0 and GMAC1 to MII/RGMII mode\n");
 		status.bits.mii_rmii = GMAC_PHY_RGMII_100_10;
@@ -429,8 +431,8 @@
 		.val = CONFIG0_MAXLEN_1536,
 	},
 	{
-		.max_l3_len = 1542,
-		.val = CONFIG0_MAXLEN_1542,
+		.max_l3_len = 1548,
+		.val = CONFIG0_MAXLEN_1548,
 	},
 	{
 		.max_l3_len = 9212,
@@ -576,6 +578,8 @@
 
 	if (port->txq_dma_base & ~DMA_Q_BASE_MASK) {
 		dev_warn(geth->dev, "TX queue base is not aligned\n");
+		dma_free_coherent(geth->dev, len * sizeof(*desc_ring),
+				  desc_ring, port->txq_dma_base);
 		kfree(skb_tab);
 		return -ENOMEM;
 	}
@@ -1110,10 +1114,13 @@
 {
 	struct gemini_ethernet_port *port = netdev_priv(netdev);
 	struct gemini_ethernet *geth = port->geth;
+	unsigned long flags;
 	u32 val, mask;
 
 	netdev_dbg(netdev, "%s device %d\n", __func__, netdev->dev_id);
 
+	spin_lock_irqsave(&geth->irq_lock, flags);
+
 	mask = GMAC0_IRQ0_TXQ0_INTS << (6 * netdev->dev_id + txq);
 
 	if (en)
@@ -1122,6 +1129,8 @@
 	val = readl(geth->base + GLOBAL_INTERRUPT_ENABLE_0_REG);
 	val = en ? val | mask : val & ~mask;
 	writel(val, geth->base + GLOBAL_INTERRUPT_ENABLE_0_REG);
+
+	spin_unlock_irqrestore(&geth->irq_lock, flags);
 }
 
 static void gmac_tx_irq(struct net_device *netdev, unsigned int txq_num)
@@ -1145,25 +1154,37 @@
 	struct gmac_txdesc *txd;
 	skb_frag_t *skb_frag;
 	dma_addr_t mapping;
-	unsigned short mtu;
 	void *buffer;
+	int ret;
 
-	mtu  = ETH_HLEN;
-	mtu += netdev->mtu;
-	if (skb->protocol == htons(ETH_P_8021Q))
-		mtu += VLAN_HLEN;
-
+	/* TODO: implement proper TSO using MTU in word3 */
 	word1 = skb->len;
 	word3 = SOF_BIT;
 
-	if (word1 > mtu) {
-		word1 |= TSS_MTU_ENABLE_BIT;
-		word3 |= mtu;
-	}
-
-	if (skb->ip_summed != CHECKSUM_NONE) {
+	if (skb->len >= ETH_FRAME_LEN) {
+		/* Hardware offloaded checksumming isn't working on frames
+		 * bigger than 1514 bytes. A hypothesis about this is that the
+		 * checksum buffer is only 1518 bytes, so when the frames get
+		 * bigger they get truncated, or the last few bytes get
+		 * overwritten by the FCS.
+		 *
+		 * Just use software checksumming and bypass on bigger frames.
+		 */
+		if (skb->ip_summed == CHECKSUM_PARTIAL) {
+			ret = skb_checksum_help(skb);
+			if (ret)
+				return ret;
+		}
+		word1 |= TSS_BYPASS_BIT;
+	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
 		int tcp = 0;
 
+		/* We do not switch off the checksumming on non TCP/UDP
+		 * frames: as is shown from tests, the checksumming engine
+		 * is smart enough to see that a frame is not actually TCP
+		 * or UDP and then just pass it through without any changes
+		 * to the frame.
+		 */
 		if (skb->protocol == htons(ETH_P_IP)) {
 			word1 |= TSS_IP_CHKSUM_BIT;
 			tcp = ip_hdr(skb)->protocol == IPPROTO_TCP;
@@ -1405,15 +1426,19 @@
 	union gmac_rxdesc_3 word3;
 	struct page *page = NULL;
 	unsigned int page_offs;
+	unsigned long flags;
 	unsigned short r, w;
 	union dma_rwptr rw;
 	dma_addr_t mapping;
 	int frag_nr = 0;
 
+	spin_lock_irqsave(&geth->irq_lock, flags);
 	rw.bits32 = readl(ptr_reg);
 	/* Reset interrupt as all packages until here are taken into account */
 	writel(DEFAULT_Q0_INT_BIT << netdev->dev_id,
 	       geth->base + GLOBAL_INTERRUPT_STATUS_1_REG);
+	spin_unlock_irqrestore(&geth->irq_lock, flags);
+
 	r = rw.bits.rptr;
 	w = rw.bits.wptr;
 
@@ -1716,10 +1741,9 @@
 		gmac_update_hw_stats(netdev);
 
 	if (val & (GMAC0_RX_OVERRUN_INT_BIT << (netdev->dev_id * 8))) {
+		spin_lock(&geth->irq_lock);
 		writel(GMAC0_RXDERR_INT_BIT << (netdev->dev_id * 8),
 		       geth->base + GLOBAL_INTERRUPT_STATUS_4_REG);
-
-		spin_lock(&geth->irq_lock);
 		u64_stats_update_begin(&port->ir_stats_syncp);
 		++port->stats.rx_fifo_errors;
 		u64_stats_update_end(&port->ir_stats_syncp);
@@ -1988,15 +2012,6 @@
 	return 0;
 }
 
-static netdev_features_t gmac_fix_features(struct net_device *netdev,
-					   netdev_features_t features)
-{
-	if (netdev->mtu + ETH_HLEN + VLAN_HLEN > MTU_SIZE_BIT_MASK)
-		features &= ~GMAC_OFFLOAD_FEATURES;
-
-	return features;
-}
-
 static int gmac_set_features(struct net_device *netdev,
 			     netdev_features_t features)
 {
@@ -2217,7 +2232,6 @@
 	.ndo_set_mac_address	= gmac_set_mac_address,
 	.ndo_get_stats64	= gmac_get_stats64,
 	.ndo_change_mtu		= gmac_change_mtu,
-	.ndo_fix_features	= gmac_fix_features,
 	.ndo_set_features	= gmac_set_features,
 };
 
@@ -2386,7 +2400,7 @@
 
 	dev_info(dev, "probe %s ID %d\n", dev_name(dev), id);
 
-	netdev = alloc_etherdev_mq(sizeof(*port), TX_QUEUE_NUM);
+	netdev = devm_alloc_etherdev_mqs(dev, sizeof(*port), TX_QUEUE_NUM, TX_QUEUE_NUM);
 	if (!netdev) {
 		dev_err(dev, "Can't allocate ethernet device #%d\n", id);
 		return -ENOMEM;
@@ -2443,7 +2457,8 @@
 	port->reset = devm_reset_control_get_exclusive(dev, NULL);
 	if (IS_ERR(port->reset)) {
 		dev_err(dev, "no reset\n");
-		return PTR_ERR(port->reset);
+		ret = PTR_ERR(port->reset);
+		goto unprepare;
 	}
 	reset_control_reset(port->reset);
 	usleep_range(100, 500);
@@ -2470,11 +2485,12 @@
 
 	netdev->hw_features = GMAC_OFFLOAD_FEATURES;
 	netdev->features |= GMAC_OFFLOAD_FEATURES | NETIF_F_GRO;
-	/* We can handle jumbo frames up to 10236 bytes so, let's accept
-	 * payloads of 10236 bytes minus VLAN and ethernet header
+	/* We can receive jumbo frames up to 10236 bytes but only
+	 * transmit 2047 bytes so, let's accept payloads of 2047
+	 * bytes minus VLAN and ethernet header
 	 */
 	netdev->min_mtu = ETH_MIN_MTU;
-	netdev->max_mtu = 10236 - VLAN_ETH_HLEN;
+	netdev->max_mtu = MTU_SIZE_BIT_MASK - VLAN_ETH_HLEN;
 
 	port->freeq_refill = 0;
 	netif_napi_add(netdev, &port->napi, gmac_napi_poll,
@@ -2499,23 +2515,24 @@
 					port_names[port->id],
 					port);
 	if (ret)
-		return ret;
+		goto unprepare;
 
 	ret = register_netdev(netdev);
-	if (!ret) {
+	if (ret)
+		goto unprepare;
+
+	netdev_info(netdev,
+		    "irq %d, DMA @ 0x%pap, GMAC @ 0x%pap\n",
+		    port->irq, &dmares->start,
+		    &gmacres->start);
+	ret = gmac_setup_phy(netdev);
+	if (ret)
 		netdev_info(netdev,
-			    "irq %d, DMA @ 0x%pap, GMAC @ 0x%pap\n",
-			    port->irq, &dmares->start,
-			    &gmacres->start);
-		ret = gmac_setup_phy(netdev);
-		if (ret)
-			netdev_info(netdev,
-				    "PHY init failed, deferring to ifup time\n");
-		return 0;
-	}
+			    "PHY init failed, deferring to ifup time\n");
+	return 0;
 
-	port->netdev = NULL;
-	free_netdev(netdev);
+unprepare:
+	clk_disable_unprepare(port->pclk);
 	return ret;
 }
 
@@ -2524,7 +2541,6 @@
 	struct gemini_ethernet_port *port = platform_get_drvdata(pdev);
 
 	gemini_port_remove(port);
-	free_netdev(port->netdev);
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/cortina/gemini.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/cortina/gemini.h
@@ -502,7 +502,7 @@
 #define SOF_BIT			0x80000000
 #define EOF_BIT			0x40000000
 #define EOFIE_BIT		BIT(29)
-#define MTU_SIZE_BIT_MASK	0x1fff
+#define MTU_SIZE_BIT_MASK	0x7ff /* Max MTU 2047 bytes */
 
 /* GMAC Tx Descriptor */
 struct gmac_txdesc {
@@ -787,7 +787,7 @@
 #define  CONFIG0_MAXLEN_1536	0
 #define  CONFIG0_MAXLEN_1518	1
 #define  CONFIG0_MAXLEN_1522	2
-#define  CONFIG0_MAXLEN_1542	3
+#define  CONFIG0_MAXLEN_1548	3
 #define  CONFIG0_MAXLEN_9k	4	/* 9212 */
 #define  CONFIG0_MAXLEN_10k	5	/* 10236 */
 #define  CONFIG0_MAXLEN_1518__6	6
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/davicom/dm9000.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/davicom/dm9000.c
@@ -134,6 +134,8 @@
 	u32		wake_state;
 
 	int		ip_summed;
+
+	struct regulator *power_supply;
 };
 
 /* debug code */
@@ -1405,6 +1407,8 @@
 	mac_addr = of_get_mac_address(np);
 	if (!IS_ERR(mac_addr))
 		ether_addr_copy(pdata->dev_addr, mac_addr);
+	else if (PTR_ERR(mac_addr) == -EPROBE_DEFER)
+		return ERR_CAST(mac_addr);
 
 	return pdata;
 }
@@ -1452,7 +1456,7 @@
 		if (ret) {
 			dev_err(dev, "failed to request reset gpio %d: %d\n",
 				reset_gpios, ret);
-			return -ENODEV;
+			goto out_regulator_disable;
 		}
 
 		/* According to manual PWRST# Low Period Min 1ms */
@@ -1464,14 +1468,18 @@
 
 	if (!pdata) {
 		pdata = dm9000_parse_dt(&pdev->dev);
-		if (IS_ERR(pdata))
-			return PTR_ERR(pdata);
+		if (IS_ERR(pdata)) {
+			ret = PTR_ERR(pdata);
+			goto out_regulator_disable;
+		}
 	}
 
 	/* Init network device */
 	ndev = alloc_etherdev(sizeof(struct board_info));
-	if (!ndev)
-		return -ENOMEM;
+	if (!ndev) {
+		ret = -ENOMEM;
+		goto out_regulator_disable;
+	}
 
 	SET_NETDEV_DEV(ndev, &pdev->dev);
 
@@ -1482,6 +1490,8 @@
 
 	db->dev = &pdev->dev;
 	db->ndev = ndev;
+	if (!IS_ERR(power))
+		db->power_supply = power;
 
 	spin_lock_init(&db->lock);
 	mutex_init(&db->addr_lock);
@@ -1504,7 +1514,7 @@
 		goto out;
 	}
 
-	db->irq_wake = platform_get_irq(pdev, 1);
+	db->irq_wake = platform_get_irq_optional(pdev, 1);
 	if (db->irq_wake >= 0) {
 		dev_dbg(db->dev, "wakeup irq %d\n", db->irq_wake);
 
@@ -1706,6 +1716,10 @@
 	dm9000_release_board(pdev, db);
 	free_netdev(ndev);
 
+out_regulator_disable:
+	if (!IS_ERR(power))
+		regulator_disable(power);
+
 	return ret;
 }
 
@@ -1763,9 +1777,13 @@
 dm9000_drv_remove(struct platform_device *pdev)
 {
 	struct net_device *ndev = platform_get_drvdata(pdev);
+	struct board_info *dm = to_dm9000_board(ndev);
 
 	unregister_netdev(ndev);
-	dm9000_release_board(pdev, netdev_priv(ndev));
+	dm9000_release_board(pdev, dm);
+	if (dm->power_supply)
+		regulator_disable(dm->power_supply);
+
 	free_netdev(ndev);		/* free device structure */
 
 	dev_dbg(&pdev->dev, "released and freed device\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/dec/tulip/de2104x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/dec/tulip/de2104x.c
@@ -91,7 +91,7 @@
 #define DSL			CONFIG_DE2104X_DSL
 #endif
 
-#define DE_RX_RING_SIZE		64
+#define DE_RX_RING_SIZE		128
 #define DE_TX_RING_SIZE		64
 #define DE_RING_BYTES		\
 		((sizeof(struct de_desc) * DE_RX_RING_SIZE) +	\
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/dec/tulip/de4x5.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/dec/tulip/de4x5.c
@@ -4708,6 +4708,10 @@
         lp->ibn = 3;
         lp->active = *p++;
 	if (MOTO_SROM_BUG) lp->active = 0;
+	/* if (MOTO_SROM_BUG) statement indicates lp->active could
+	 * be 8 (i.e. the size of array lp->phy) */
+	if (WARN_ON(lp->active >= ARRAY_SIZE(lp->phy)))
+		return -EINVAL;
 	lp->phy[lp->active].gep = (*p ? p : NULL); p += (2 * (*p) + 1);
 	lp->phy[lp->active].rst = (*p ? p : NULL); p += (2 * (*p) + 1);
 	lp->phy[lp->active].mc  = get_unaligned_le16(p); p += 2;
@@ -4927,11 +4931,11 @@
 	u_char breg[2];
     } a;
     int i, r2, r3, ret=0;*/
-    int r2, r3;
+    int r2;
 
     /* Read r2 and r3 */
     r2 = mii_rd(MII_ID0, phyaddr, ioaddr);
-    r3 = mii_rd(MII_ID1, phyaddr, ioaddr);
+    mii_rd(MII_ID1, phyaddr, ioaddr);
                                                 /* SEEQ and Cypress way * /
     / * Shuffle r2 and r3 * /
     a.reg=0;
@@ -4999,19 +5003,23 @@
 	}
 	if ((j == limit) && (i < DE4X5_MAX_MII)) {
 	    for (k=0; k < DE4X5_MAX_PHY && lp->phy[k].id; k++);
-	    lp->phy[k].addr = i;
-	    lp->phy[k].id = id;
-	    lp->phy[k].spd.reg = GENERIC_REG;      /* ANLPA register         */
-	    lp->phy[k].spd.mask = GENERIC_MASK;    /* 100Mb/s technologies   */
-	    lp->phy[k].spd.value = GENERIC_VALUE;  /* TX & T4, H/F Duplex    */
-	    lp->mii_cnt++;
-	    lp->active++;
-	    printk("%s: Using generic MII device control. If the board doesn't operate,\nplease mail the following dump to the author:\n", dev->name);
-	    j = de4x5_debug;
-	    de4x5_debug |= DEBUG_MII;
-	    de4x5_dbg_mii(dev, k);
-	    de4x5_debug = j;
-	    printk("\n");
+	    if (k < DE4X5_MAX_PHY) {
+		lp->phy[k].addr = i;
+		lp->phy[k].id = id;
+		lp->phy[k].spd.reg = GENERIC_REG;      /* ANLPA register         */
+		lp->phy[k].spd.mask = GENERIC_MASK;    /* 100Mb/s technologies   */
+		lp->phy[k].spd.value = GENERIC_VALUE;  /* TX & T4, H/F Duplex    */
+		lp->mii_cnt++;
+		lp->active++;
+		printk("%s: Using generic MII device control. If the board doesn't operate,\nplease mail the following dump to the author:\n", dev->name);
+		j = de4x5_debug;
+		de4x5_debug |= DEBUG_MII;
+		de4x5_dbg_mii(dev, k);
+		de4x5_debug = j;
+		printk("\n");
+	    } else {
+		goto purgatory;
+	    }
 	}
     }
   purgatory:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/dec/tulip/dmfe.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/dec/tulip/dmfe.c
@@ -2214,15 +2214,16 @@
 	if (cr6set)
 		dmfe_cr6_user_set = cr6set;
 
- 	switch(mode) {
-   	case DMFE_10MHF:
+	switch (mode) {
+	case DMFE_10MHF:
 	case DMFE_100MHF:
 	case DMFE_10MFD:
 	case DMFE_100MFD:
 	case DMFE_1M_HPNA:
 		dmfe_media_mode = mode;
 		break;
-	default:dmfe_media_mode = DMFE_AUTO;
+	default:
+		dmfe_media_mode = DMFE_AUTO;
 		break;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/dec/tulip/media.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/dec/tulip/media.c
@@ -319,13 +319,8 @@
 			break;
 		}
 		case 5: case 6: {
-			u16 setup[5];
-
 			new_csr6 = 0; /* FIXME */
 
-			for (i = 0; i < 5; i++)
-				setup[i] = get_u16(&p[i*2 + 1]);
-
 			if (startup && mtable->has_reset) {
 				struct medialeaf *rleaf = &mtable->mleaf[mtable->has_reset];
 				unsigned char *rst = rleaf->leafdata;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/dec/tulip/tulip_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/dec/tulip/tulip_core.c
@@ -1410,8 +1410,10 @@
 
 	/* alloc_etherdev ensures aligned and zeroed private structures */
 	dev = alloc_etherdev (sizeof (*tp));
-	if (!dev)
+	if (!dev) {
+		pci_disable_device(pdev);
 		return -ENOMEM;
+	}
 
 	SET_NETDEV_DEV(dev, &pdev->dev);
 	if (pci_resource_len (pdev, 0) < tulip_tbl[chip_idx].io_size) {
@@ -1788,6 +1790,7 @@
 
 err_out_free_netdev:
 	free_netdev (dev);
+	pci_disable_device(pdev);
 	return -ENODEV;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/dec/tulip/uli526x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/dec/tulip/uli526x.c
@@ -1809,8 +1809,8 @@
 	if (cr6set)
 		uli526x_cr6_user_set = cr6set;
 
- 	switch (mode) {
-   	case ULI526X_10MHF:
+	switch (mode) {
+	case ULI526X_10MHF:
 	case ULI526X_100MHF:
 	case ULI526X_10MFD:
 	case ULI526X_100MFD:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/dec/tulip/winbond-840.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/dec/tulip/winbond-840.c
@@ -367,7 +367,7 @@
 	int i, option = find_cnt < MAX_UNITS ? options[find_cnt] : 0;
 	void __iomem *ioaddr;
 
-	i = pci_enable_device(pdev);
+	i = pcim_enable_device(pdev);
 	if (i) return i;
 
 	pci_set_master(pdev);
@@ -389,7 +389,7 @@
 
 	ioaddr = pci_iomap(pdev, TULIP_BAR, netdev_res_size);
 	if (!ioaddr)
-		goto err_out_free_res;
+		goto err_out_netdev;
 
 	for (i = 0; i < 3; i++)
 		((__le16 *)dev->dev_addr)[i] = cpu_to_le16(eeprom_read(ioaddr, i));
@@ -468,8 +468,6 @@
 
 err_out_cleardev:
 	pci_iounmap(pdev, ioaddr);
-err_out_free_res:
-	pci_release_regions(pdev);
 err_out_netdev:
 	free_netdev (dev);
 	return -ENODEV;
@@ -1535,7 +1533,6 @@
 	if (dev) {
 		struct netdev_private *np = netdev_priv(dev);
 		unregister_netdev(dev);
-		pci_release_regions(pdev);
 		pci_iounmap(pdev, np->base_addr);
 		free_netdev(dev);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/dnet.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/dnet.c
@@ -553,11 +553,11 @@
 
 	skb_tx_timestamp(skb);
 
+	spin_unlock_irqrestore(&bp->lock, flags);
+
 	/* free the buffer */
 	dev_kfree_skb(skb);
 
-	spin_unlock_irqrestore(&bp->lock, flags);
-
 	return NETDEV_TX_OK;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/ec_bhf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/ec_bhf.c
@@ -576,10 +576,12 @@
 	struct ec_bhf_priv *priv = netdev_priv(net_dev);
 
 	unregister_netdev(net_dev);
-	free_netdev(net_dev);
 
 	pci_iounmap(dev, priv->dma_io);
 	pci_iounmap(dev, priv->io);
+
+	free_netdev(net_dev);
+
 	pci_release_regions(dev);
 	pci_clear_master(dev);
 	pci_disable_device(dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/emulex/benet/be.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/emulex/benet/be.h
@@ -564,7 +564,7 @@
 	struct be_dma_mem mbox_mem_alloced;
 
 	struct be_mcc_obj mcc_obj;
-	struct mutex mcc_lock;	/* For serializing mcc cmds to BE card */
+	spinlock_t mcc_lock;	/* For serializing mcc cmds to BE card */
 	spinlock_t mcc_cq_lock;
 
 	u16 cfg_num_rx_irqs;		/* configured via set-channels */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/emulex/benet/be_cmds.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -550,7 +550,7 @@
 	int num = 0, status = 0;
 	struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
 
-	spin_lock_bh(&adapter->mcc_cq_lock);
+	spin_lock(&adapter->mcc_cq_lock);
 
 	while ((compl = be_mcc_compl_get(adapter))) {
 		if (compl->flags & CQE_FLAGS_ASYNC_MASK) {
@@ -566,14 +566,14 @@
 	if (num)
 		be_cq_notify(adapter, mcc_obj->cq.id, mcc_obj->rearm_cq, num);
 
-	spin_unlock_bh(&adapter->mcc_cq_lock);
+	spin_unlock(&adapter->mcc_cq_lock);
 	return status;
 }
 
 /* Wait till no more pending mcc requests are present */
 static int be_mcc_wait_compl(struct be_adapter *adapter)
 {
-#define mcc_timeout		12000 /* 12s timeout */
+#define mcc_timeout		120000 /* 12s timeout */
 	int i, status = 0;
 	struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
 
@@ -581,11 +581,13 @@
 		if (be_check_error(adapter, BE_ERROR_ANY))
 			return -EIO;
 
+		local_bh_disable();
 		status = be_process_mcc(adapter);
+		local_bh_enable();
 
 		if (atomic_read(&mcc_obj->q.used) == 0)
 			break;
-		usleep_range(500, 1000);
+		udelay(100);
 	}
 	if (i == mcc_timeout) {
 		dev_err(&adapter->pdev->dev, "FW not responding\n");
@@ -863,7 +865,7 @@
 static int be_cmd_lock(struct be_adapter *adapter)
 {
 	if (use_mcc(adapter)) {
-		mutex_lock(&adapter->mcc_lock);
+		spin_lock_bh(&adapter->mcc_lock);
 		return 0;
 	} else {
 		return mutex_lock_interruptible(&adapter->mbox_lock);
@@ -874,7 +876,7 @@
 static void be_cmd_unlock(struct be_adapter *adapter)
 {
 	if (use_mcc(adapter))
-		return mutex_unlock(&adapter->mcc_lock);
+		return spin_unlock_bh(&adapter->mcc_lock);
 	else
 		return mutex_unlock(&adapter->mbox_lock);
 }
@@ -1044,7 +1046,7 @@
 	struct be_cmd_req_mac_query *req;
 	int status;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -1073,7 +1075,7 @@
 	}
 
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -1085,7 +1087,7 @@
 	struct be_cmd_req_pmac_add *req;
 	int status;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -1110,7 +1112,7 @@
 	}
 
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 
 	 if (base_status(status) == MCC_STATUS_UNAUTHORIZED_REQUEST)
 		status = -EPERM;
@@ -1128,7 +1130,7 @@
 	if (pmac_id == -1)
 		return 0;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -1148,7 +1150,7 @@
 	status = be_mcc_notify_wait(adapter);
 
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -1411,7 +1413,7 @@
 	struct be_dma_mem *q_mem = &rxq->dma_mem;
 	int status;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -1441,7 +1443,7 @@
 	}
 
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -1505,7 +1507,7 @@
 	struct be_cmd_req_q_destroy *req;
 	int status;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -1522,7 +1524,7 @@
 	q->created = false;
 
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -1590,7 +1592,7 @@
 	struct be_cmd_req_hdr *hdr;
 	int status = 0;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -1618,7 +1620,7 @@
 	adapter->stats_cmd_sent = true;
 
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -1634,7 +1636,7 @@
 			    CMD_SUBSYSTEM_ETH))
 		return -EPERM;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -1657,7 +1659,7 @@
 	adapter->stats_cmd_sent = true;
 
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -1694,7 +1696,7 @@
 	struct be_cmd_req_link_status *req;
 	int status;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	if (link_status)
 		*link_status = LINK_DOWN;
@@ -1733,7 +1735,7 @@
 	}
 
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -1744,7 +1746,7 @@
 	struct be_cmd_req_get_cntl_addnl_attribs *req;
 	int status = 0;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -1759,7 +1761,7 @@
 
 	status = be_mcc_notify(adapter);
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -1808,7 +1810,7 @@
 	if (!get_fat_cmd.va)
 		return -ENOMEM;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	while (total_size) {
 		buf_size = min(total_size, (u32)60*1024);
@@ -1846,9 +1848,9 @@
 		log_offset += buf_size;
 	}
 err:
+	spin_unlock_bh(&adapter->mcc_lock);
 	dma_free_coherent(&adapter->pdev->dev, get_fat_cmd.size,
 			  get_fat_cmd.va, get_fat_cmd.dma);
-	mutex_unlock(&adapter->mcc_lock);
 	return status;
 }
 
@@ -1859,7 +1861,7 @@
 	struct be_cmd_req_get_fw_version *req;
 	int status;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -1882,7 +1884,7 @@
 			sizeof(adapter->fw_on_flash));
 	}
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -1896,7 +1898,7 @@
 	struct be_cmd_req_modify_eq_delay *req;
 	int status = 0, i;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -1919,7 +1921,7 @@
 
 	status = be_mcc_notify(adapter);
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -1946,7 +1948,7 @@
 	struct be_cmd_req_vlan_config *req;
 	int status;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -1968,7 +1970,7 @@
 
 	status = be_mcc_notify_wait(adapter);
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -1979,7 +1981,7 @@
 	struct be_cmd_req_rx_filter *req = mem->va;
 	int status;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -2012,7 +2014,7 @@
 
 	status = be_mcc_notify_wait(adapter);
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -2043,7 +2045,7 @@
 			    CMD_SUBSYSTEM_COMMON))
 		return -EPERM;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -2063,7 +2065,7 @@
 	status = be_mcc_notify_wait(adapter);
 
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 
 	if (base_status(status) == MCC_STATUS_FEATURE_NOT_SUPPORTED)
 		return  -EOPNOTSUPP;
@@ -2082,7 +2084,7 @@
 			    CMD_SUBSYSTEM_COMMON))
 		return -EPERM;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -2105,7 +2107,7 @@
 	}
 
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -2186,7 +2188,7 @@
 	if (!(be_if_cap_flags(adapter) & BE_IF_FLAGS_RSS))
 		return 0;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -2211,7 +2213,7 @@
 
 	status = be_mcc_notify_wait(adapter);
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -2223,7 +2225,7 @@
 	struct be_cmd_req_enable_disable_beacon *req;
 	int status;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -2244,7 +2246,7 @@
 	status = be_mcc_notify_wait(adapter);
 
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -2255,7 +2257,7 @@
 	struct be_cmd_req_get_beacon_state *req;
 	int status;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -2279,13 +2281,13 @@
 	}
 
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
 /* Uses sync mcc */
 int be_cmd_read_port_transceiver_data(struct be_adapter *adapter,
-				      u8 page_num, u8 *data)
+				      u8 page_num, u32 off, u32 len, u8 *data)
 {
 	struct be_dma_mem cmd;
 	struct be_mcc_wrb *wrb;
@@ -2303,7 +2305,7 @@
 		return -ENOMEM;
 	}
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -2319,13 +2321,13 @@
 	req->port = cpu_to_le32(adapter->hba_port_num);
 	req->page_num = cpu_to_le32(page_num);
 	status = be_mcc_notify_wait(adapter);
-	if (!status) {
+	if (!status && len > 0) {
 		struct be_cmd_resp_port_type *resp = cmd.va;
 
-		memcpy(data, resp->page_data, PAGE_DATA_LEN);
+		memcpy(data, resp->page_data + off, len);
 	}
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma);
 	return status;
 }
@@ -2342,7 +2344,7 @@
 	void *ctxt = NULL;
 	int status;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 	adapter->flash_status = 0;
 
 	wrb = wrb_from_mccq(adapter);
@@ -2384,7 +2386,7 @@
 	if (status)
 		goto err_unlock;
 
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 
 	if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
 					 msecs_to_jiffies(60000)))
@@ -2403,7 +2405,7 @@
 	return status;
 
 err_unlock:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -2413,7 +2415,7 @@
 	int status;
 
 	status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0,
-						   page_data);
+						   0, PAGE_DATA_LEN, page_data);
 	if (!status) {
 		switch (adapter->phy.interface_type) {
 		case PHY_TYPE_QSFP:
@@ -2438,7 +2440,7 @@
 	int status;
 
 	status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0,
-						   page_data);
+						   0, PAGE_DATA_LEN, page_data);
 	if (!status) {
 		strlcpy(adapter->phy.vendor_name, page_data +
 			SFP_VENDOR_NAME_OFFSET, SFP_VENDOR_NAME_LEN - 1);
@@ -2457,7 +2459,7 @@
 	struct be_mcc_wrb *wrb;
 	int status;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -2475,7 +2477,7 @@
 
 	status = be_mcc_notify_wait(adapter);
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -2488,7 +2490,7 @@
 	struct lancer_cmd_resp_read_object *resp;
 	int status;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -2522,7 +2524,7 @@
 	}
 
 err_unlock:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -2534,7 +2536,7 @@
 	struct be_cmd_write_flashrom *req;
 	int status;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 	adapter->flash_status = 0;
 
 	wrb = wrb_from_mccq(adapter);
@@ -2559,7 +2561,7 @@
 	if (status)
 		goto err_unlock;
 
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 
 	if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
 					 msecs_to_jiffies(40000)))
@@ -2570,7 +2572,7 @@
 	return status;
 
 err_unlock:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -2581,7 +2583,7 @@
 	struct be_mcc_wrb *wrb;
 	int status;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -2608,7 +2610,7 @@
 		memcpy(flashed_crc, req->crc, 4);
 
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -3214,7 +3216,7 @@
 	struct be_cmd_req_acpi_wol_magic_config *req;
 	int status;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -3231,7 +3233,7 @@
 	status = be_mcc_notify_wait(adapter);
 
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -3246,7 +3248,7 @@
 			    CMD_SUBSYSTEM_LOWLEVEL))
 		return -EPERM;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -3269,7 +3271,7 @@
 	if (status)
 		goto err_unlock;
 
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 
 	if (!wait_for_completion_timeout(&adapter->et_cmd_compl,
 					 msecs_to_jiffies(SET_LB_MODE_TIMEOUT)))
@@ -3278,7 +3280,7 @@
 	return status;
 
 err_unlock:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -3295,7 +3297,7 @@
 			    CMD_SUBSYSTEM_LOWLEVEL))
 		return -EPERM;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -3321,7 +3323,7 @@
 	if (status)
 		goto err;
 
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 
 	wait_for_completion(&adapter->et_cmd_compl);
 	resp = embedded_payload(wrb);
@@ -3329,7 +3331,7 @@
 
 	return status;
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -3345,7 +3347,7 @@
 			    CMD_SUBSYSTEM_LOWLEVEL))
 		return -EPERM;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -3379,7 +3381,7 @@
 	}
 
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -3390,7 +3392,7 @@
 	struct be_cmd_req_seeprom_read *req;
 	int status;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -3406,7 +3408,7 @@
 	status = be_mcc_notify_wait(adapter);
 
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -3421,7 +3423,7 @@
 			    CMD_SUBSYSTEM_COMMON))
 		return -EPERM;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -3466,7 +3468,7 @@
 	}
 	dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma);
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -3476,7 +3478,7 @@
 	struct be_cmd_req_set_qos *req;
 	int status;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -3496,7 +3498,7 @@
 	status = be_mcc_notify_wait(adapter);
 
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -3608,7 +3610,7 @@
 	struct be_cmd_req_get_fn_privileges *req;
 	int status;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -3640,7 +3642,7 @@
 	}
 
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -3652,7 +3654,7 @@
 	struct be_cmd_req_set_fn_privileges *req;
 	int status;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -3672,7 +3674,7 @@
 
 	status = be_mcc_notify_wait(adapter);
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -3704,7 +3706,7 @@
 		return -ENOMEM;
 	}
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -3768,7 +3770,7 @@
 	}
 
 out:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	dma_free_coherent(&adapter->pdev->dev, get_mac_list_cmd.size,
 			  get_mac_list_cmd.va, get_mac_list_cmd.dma);
 	return status;
@@ -3828,7 +3830,7 @@
 	if (!cmd.va)
 		return -ENOMEM;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -3850,7 +3852,7 @@
 
 err:
 	dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma);
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -3886,7 +3888,7 @@
 			    CMD_SUBSYSTEM_COMMON))
 		return -EPERM;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -3927,7 +3929,7 @@
 	status = be_mcc_notify_wait(adapter);
 
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -3941,7 +3943,7 @@
 	int status;
 	u16 vid;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -3988,7 +3990,7 @@
 	}
 
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -4187,7 +4189,7 @@
 	struct be_cmd_req_set_ext_fat_caps *req;
 	int status;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -4203,7 +4205,7 @@
 
 	status = be_mcc_notify_wait(adapter);
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -4681,7 +4683,7 @@
 	if (iface == 0xFFFFFFFF)
 		return -1;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -4698,7 +4700,7 @@
 
 	status = be_mcc_notify_wait(adapter);
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -4732,7 +4734,7 @@
 	struct be_cmd_resp_get_iface_list *resp;
 	int status;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -4753,7 +4755,7 @@
 	}
 
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -4847,7 +4849,7 @@
 	if (BEx_chip(adapter))
 		return 0;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -4865,7 +4867,7 @@
 	req->enable = 1;
 	status = be_mcc_notify_wait(adapter);
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -4938,7 +4940,7 @@
 	u32 link_config = 0;
 	int status;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -4966,7 +4968,7 @@
 
 	status = be_mcc_notify_wait(adapter);
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -4997,8 +4999,7 @@
 	struct be_mcc_wrb *wrb;
 	int status;
 
-	if (mutex_lock_interruptible(&adapter->mcc_lock))
-		return -1;
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -5036,7 +5037,7 @@
 		dev_info(&adapter->pdev->dev,
 			 "Adapter does not support HW error recovery\n");
 
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 
@@ -5050,7 +5051,7 @@
 	struct be_cmd_resp_hdr *resp;
 	int status;
 
-	mutex_lock(&adapter->mcc_lock);
+	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
 	if (!wrb) {
@@ -5073,7 +5074,7 @@
 	memcpy(wrb_payload, resp, sizeof(*resp) + resp->response_length);
 	be_dws_le_to_cpu(wrb_payload, sizeof(*resp) + resp->response_length);
 err:
-	mutex_unlock(&adapter->mcc_lock);
+	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
 EXPORT_SYMBOL(be_roce_mcc_cmd);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/emulex/benet/be_cmds.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/emulex/benet/be_cmds.h
@@ -2427,7 +2427,7 @@
 int be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num,
 			    u32 *state);
 int be_cmd_read_port_transceiver_data(struct be_adapter *adapter,
-				      u8 page_num, u8 *data);
+				      u8 page_num, u32 off, u32 len, u8 *data);
 int be_cmd_query_cable_type(struct be_adapter *adapter);
 int be_cmd_query_sfp_info(struct be_adapter *adapter);
 int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/emulex/benet/be_ethtool.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/emulex/benet/be_ethtool.c
@@ -1339,7 +1339,7 @@
 		return -EOPNOTSUPP;
 
 	status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0,
-						   page_data);
+						   0, PAGE_DATA_LEN, page_data);
 	if (!status) {
 		if (!page_data[SFP_PLUS_SFF_8472_COMP]) {
 			modinfo->type = ETH_MODULE_SFF_8079;
@@ -1357,25 +1357,32 @@
 {
 	struct be_adapter *adapter = netdev_priv(netdev);
 	int status;
+	u32 begin, end;
 
 	if (!check_privilege(adapter, MAX_PRIVILEGES))
 		return -EOPNOTSUPP;
 
-	status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0,
-						   data);
-	if (status)
-		goto err;
-
-	if (eeprom->offset + eeprom->len > PAGE_DATA_LEN) {
-		status = be_cmd_read_port_transceiver_data(adapter,
-							   TR_PAGE_A2,
-							   data +
-							   PAGE_DATA_LEN);
+	begin = eeprom->offset;
+	end = eeprom->offset + eeprom->len;
+
+	if (begin < PAGE_DATA_LEN) {
+		status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0, begin,
+							   min_t(u32, end, PAGE_DATA_LEN) - begin,
+							   data);
+		if (status)
+			goto err;
+
+		data += PAGE_DATA_LEN - begin;
+		begin = PAGE_DATA_LEN;
+	}
+
+	if (end > PAGE_DATA_LEN) {
+		status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A2,
+							   begin - PAGE_DATA_LEN,
+							   end - begin, data);
 		if (status)
 			goto err;
 	}
-	if (eeprom->offset)
-		memcpy(data, data + eeprom->offset, eeprom->len);
 err:
 	return be_cmd_status(status);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/emulex/benet/be_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/emulex/benet/be_main.c
@@ -1137,10 +1137,11 @@
 	eth_hdr_len = ntohs(skb->protocol) == ETH_P_8021Q ?
 						VLAN_ETH_HLEN : ETH_HLEN;
 	if (skb->len <= 60 &&
-	    (lancer_chip(adapter) || skb_vlan_tag_present(skb)) &&
-	    is_ipv4_pkt(skb)) {
+	    (lancer_chip(adapter) || BE3_chip(adapter) ||
+	     skb_vlan_tag_present(skb)) && is_ipv4_pkt(skb)) {
 		ip = (struct iphdr *)ip_hdr(skb);
-		pskb_trim(skb, eth_hdr_len + ntohs(ip->tot_len));
+		if (unlikely(pskb_trim(skb, eth_hdr_len + ntohs(ip->tot_len))))
+			goto tx_drop;
 	}
 
 	/* If vlan tag is already inlined in the packet, skip HW VLAN
@@ -1382,10 +1383,8 @@
 	be_get_wrb_params_from_skb(adapter, skb, &wrb_params);
 
 	wrb_cnt = be_xmit_enqueue(adapter, txo, skb, &wrb_params);
-	if (unlikely(!wrb_cnt)) {
-		dev_kfree_skb_any(skb);
-		goto drop;
-	}
+	if (unlikely(!wrb_cnt))
+		goto drop_skb;
 
 	/* if os2bmc is enabled and if the pkt is destined to bmc,
 	 * enqueue the pkt a 2nd time with mgmt bit set.
@@ -1394,7 +1393,7 @@
 		BE_WRB_F_SET(wrb_params.features, OS2BMC, 1);
 		wrb_cnt = be_xmit_enqueue(adapter, txo, skb, &wrb_params);
 		if (unlikely(!wrb_cnt))
-			goto drop;
+			goto drop_skb;
 		else
 			skb_get(skb);
 	}
@@ -1408,6 +1407,8 @@
 		be_xmit_flush(adapter, txo);
 
 	return NETDEV_TX_OK;
+drop_skb:
+	dev_kfree_skb_any(skb);
 drop:
 	tx_stats(txo)->tx_drv_drops++;
 	/* Flush the already enqueued tx requests */
@@ -5631,7 +5632,9 @@
 	 * mcc completions
 	 */
 	if (!netif_running(adapter->netdev)) {
+		local_bh_disable();
 		be_process_mcc(adapter);
+		local_bh_enable();
 		goto reschedule;
 	}
 
@@ -5800,8 +5803,8 @@
 	}
 
 	mutex_init(&adapter->mbox_lock);
-	mutex_init(&adapter->mcc_lock);
 	mutex_init(&adapter->rx_filter_lock);
+	spin_lock_init(&adapter->mcc_lock);
 	spin_lock_init(&adapter->mcc_cq_lock);
 	init_completion(&adapter->et_cmd_compl);
 
@@ -6030,6 +6033,7 @@
 unmap_bars:
 	be_unmap_pci_bars(adapter);
 free_netdev:
+	pci_disable_pcie_error_reporting(pdev);
 	free_netdev(netdev);
 rel_reg:
 	pci_release_regions(pdev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/ethoc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/ethoc.c
@@ -1207,7 +1207,7 @@
 	ret = mdiobus_register(priv->mdio);
 	if (ret) {
 		dev_err(&netdev->dev, "failed to register MDIO bus\n");
-		goto free2;
+		goto free3;
 	}
 
 	ret = ethoc_mdio_probe(netdev);
@@ -1239,6 +1239,7 @@
 	netif_napi_del(&priv->napi);
 error:
 	mdiobus_unregister(priv->mdio);
+free3:
 	mdiobus_free(priv->mdio);
 free2:
 	clk_disable_unprepare(priv->clk);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/ezchip/nps_enet.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/ezchip/nps_enet.c
@@ -610,7 +610,7 @@
 
 	/* Get IRQ number */
 	priv->irq = platform_get_irq(pdev, 0);
-	if (!priv->irq) {
+	if (priv->irq < 0) {
 		dev_err(dev, "failed to retrieve <irq Rx-Tx> value from device tree\n");
 		err = -ENODEV;
 		goto out_netdev;
@@ -645,8 +645,8 @@
 	struct nps_enet_priv *priv = netdev_priv(ndev);
 
 	unregister_netdev(ndev);
-	free_netdev(ndev);
 	netif_napi_del(&priv->napi);
+	free_netdev(ndev);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/faraday/ftgmac100.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/faraday/ftgmac100.c
@@ -567,7 +567,7 @@
 	(*processed)++;
 	return true;
 
- drop:
+drop:
 	/* Clean rxdes0 (which resets own bit) */
 	rxdes->rxdes0 = cpu_to_le32(status & priv->rxdes0_edorr_mask);
 	priv->rx_pointer = ftgmac100_next_rx_pointer(priv, pointer);
@@ -651,6 +651,11 @@
 	ftgmac100_free_tx_packet(priv, pointer, skb, txdes, ctl_stat);
 	txdes->txdes0 = cpu_to_le32(ctl_stat & priv->txdes0_edotr_mask);
 
+	/* Ensure the descriptor config is visible before setting the tx
+	 * pointer.
+	 */
+	smp_wmb();
+
 	priv->tx_clean_pointer = ftgmac100_next_tx_pointer(priv, pointer);
 
 	return true;
@@ -804,6 +809,11 @@
 	dma_wmb();
 	first->txdes0 = cpu_to_le32(f_ctl_stat);
 
+	/* Ensure the descriptor config is visible before setting the tx
+	 * pointer.
+	 */
+	smp_wmb();
+
 	/* Update next TX pointer */
 	priv->tx_pointer = pointer;
 
@@ -824,7 +834,7 @@
 
 	return NETDEV_TX_OK;
 
- dma_err:
+dma_err:
 	if (net_ratelimit())
 		netdev_err(netdev, "map tx fragment failed\n");
 
@@ -846,7 +856,7 @@
 	 * last fragment, so we know ftgmac100_free_tx_packet()
 	 * hasn't freed the skb yet.
 	 */
- drop:
+drop:
 	/* Drop the packet */
 	dev_kfree_skb_any(skb);
 	netdev->stats.tx_dropped++;
@@ -1307,6 +1317,7 @@
 	 */
 	if (unlikely(priv->need_mac_restart)) {
 		ftgmac100_start_hw(priv);
+		priv->need_mac_restart = false;
 
 		/* Re-enable "bad" interrupts */
 		iowrite32(FTGMAC100_INT_BAD,
@@ -1417,7 +1428,7 @@
 	ftgmac100_init_all(priv, true);
 
 	netdev_dbg(netdev, "Reset done !\n");
- bail:
+bail:
 	if (priv->mii_bus)
 		mutex_unlock(&priv->mii_bus->mdio_lock);
 	if (netdev->phydev)
@@ -1488,15 +1499,15 @@
 
 	return 0;
 
- err_ncsi:
+err_ncsi:
 	napi_disable(&priv->napi);
 	netif_stop_queue(netdev);
- err_alloc:
+err_alloc:
 	ftgmac100_free_buffers(priv);
 	free_irq(netdev->irq, netdev);
- err_irq:
+err_irq:
 	netif_napi_del(&priv->napi);
- err_hw:
+err_hw:
 	iowrite32(0, priv->base + FTGMAC100_OFFSET_IER);
 	ftgmac100_free_rings(priv);
 	return err;
@@ -1733,6 +1744,19 @@
 			FTGMAC_100MHZ);
 }
 
+static bool ftgmac100_has_child_node(struct device_node *np, const char *name)
+{
+	struct device_node *child_np = of_get_child_by_name(np, name);
+	bool ret = false;
+
+	if (child_np) {
+		ret = true;
+		of_node_put(child_np);
+	}
+
+	return ret;
+}
+
 static int ftgmac100_probe(struct platform_device *pdev)
 {
 	struct resource *res;
@@ -1807,6 +1831,11 @@
 		priv->rxdes0_edorr_mask = BIT(30);
 		priv->txdes0_edotr_mask = BIT(30);
 		priv->is_aspeed = true;
+		/* Disable ast2600 problematic HW arbitration */
+		if (of_device_is_compatible(np, "aspeed,ast2600-mac")) {
+			iowrite32(FTGMAC100_TM_DEFAULT,
+				  priv->base + FTGMAC100_OFFSET_TM);
+		}
 	} else {
 		priv->rxdes0_edorr_mask = BIT(15);
 		priv->txdes0_edotr_mask = BIT(15);
@@ -1815,14 +1844,17 @@
 	if (np && of_get_property(np, "use-ncsi", NULL)) {
 		if (!IS_ENABLED(CONFIG_NET_NCSI)) {
 			dev_err(&pdev->dev, "NCSI stack not enabled\n");
+			err = -EINVAL;
 			goto err_ncsi_dev;
 		}
 
 		dev_info(&pdev->dev, "Using NCSI interface\n");
 		priv->use_ncsi = true;
 		priv->ndev = ncsi_register_dev(netdev, ftgmac100_ncsi_handler);
-		if (!priv->ndev)
+		if (!priv->ndev) {
+			err = -EINVAL;
 			goto err_ncsi_dev;
+		}
 	} else if (np && of_get_property(np, "phy-handle", NULL)) {
 		struct phy_device *phy;
 
@@ -1830,6 +1862,7 @@
 					     &ftgmac100_adjust_link);
 		if (!phy) {
 			dev_err(&pdev->dev, "Failed to connect to phy\n");
+			err = -EINVAL;
 			goto err_setup_mdio;
 		}
 
@@ -1840,7 +1873,7 @@
 
 		/* Display what we found */
 		phy_attached_info(phy);
-	} else if (np && !of_get_child_by_name(np, "mdio")) {
+	} else if (np && !ftgmac100_has_child_node(np, "mdio")) {
 		/* Support legacy ASPEED devicetree descriptions that decribe a
 		 * MAC with an embedded MDIO controller but have no "mdio"
 		 * child node. Automatically scan the MDIO bus for available
@@ -1870,6 +1903,11 @@
 	/* AST2400  doesn't have working HW checksum generation */
 	if (np && (of_device_is_compatible(np, "aspeed,ast2400-mac")))
 		netdev->hw_features &= ~NETIF_F_HW_CSUM;
+
+	/* AST2600 tx checksum with NCSI is broken */
+	if (priv->use_ncsi && of_device_is_compatible(np, "aspeed,ast2600-mac"))
+		netdev->hw_features &= ~NETIF_F_HW_CSUM;
+
 	if (np && of_get_property(np, "no-hw-checksum", NULL))
 		netdev->hw_features &= ~(NETIF_F_HW_CSUM | NETIF_F_RXCSUM);
 	netdev->features |= netdev->hw_features;
@@ -1886,6 +1924,8 @@
 	return 0;
 
 err_ncsi_dev:
+	if (priv->ndev)
+		ncsi_unregister_dev(priv->ndev);
 err_register_netdev:
 	ftgmac100_destroy_mdio(netdev);
 err_setup_mdio:
@@ -1906,6 +1946,8 @@
 	netdev = platform_get_drvdata(pdev);
 	priv = netdev_priv(netdev);
 
+	if (priv->ndev)
+		ncsi_unregister_dev(priv->ndev);
 	unregister_netdev(netdev);
 
 	clk_disable_unprepare(priv->clk);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/faraday/ftgmac100.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/faraday/ftgmac100.h
@@ -84,7 +84,7 @@
 			    FTGMAC100_INT_RPKT_BUF)
 
 /* All the interrupts we care about */
-#define FTGMAC100_INT_ALL (FTGMAC100_INT_RPKT_BUF  |  \
+#define FTGMAC100_INT_ALL (FTGMAC100_INT_RXTX  |  \
 			   FTGMAC100_INT_BAD)
 
 /*
@@ -170,6 +170,14 @@
 #define FTGMAC100_MACCR_SW_RST		(1 << 31)
 
 /*
+ * test mode control register
+ */
+#define FTGMAC100_TM_RQ_TX_VALID_DIS (1 << 28)
+#define FTGMAC100_TM_RQ_RR_IDLE_PREV (1 << 27)
+#define FTGMAC100_TM_DEFAULT                                                   \
+	(FTGMAC100_TM_RQ_TX_VALID_DIS | FTGMAC100_TM_RQ_RR_IDLE_PREV)
+
+/*
  * PHY control register
  */
 #define FTGMAC100_PHYCR_MDC_CYCTHR_MASK	0x3f
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/Kconfig
@@ -77,6 +77,7 @@
 	depends on QUICC_ENGINE
 	select FSL_PQ_MDIO
 	select PHYLIB
+	select FIXED_PHY
 	---help---
 	  This driver supports the Gigabit Ethernet mode of the QUICC Engine,
 	  which is available on some Freescale SOCs.
@@ -90,6 +91,7 @@
 	depends on HAS_DMA
 	select FSL_PQ_MDIO
 	select PHYLIB
+	select FIXED_PHY
 	select CRC32
 	---help---
 	  This driver supports the Gigabit TSEC on the MPC83xx, MPC85xx,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/dpaa/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/dpaa/Kconfig
@@ -3,6 +3,7 @@
 	tristate "DPAA Ethernet"
 	depends on FSL_DPAA && FSL_FMAN
 	select PHYLIB
+	select FIXED_PHY
 	select FSL_FMAN_MAC
 	---help---
 	  Data Path Acceleration Architecture Ethernet driver,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -1600,13 +1600,15 @@
  * Skb freeing is not handled here.
  *
  * This function may be called on error paths in the Tx function, so guard
- * against cases when not all fd relevant fields were filled in.
+ * against cases when not all fd relevant fields were filled in. To avoid
+ * reading the invalid transmission timestamp for the error paths set ts to
+ * false.
  *
  * Return the skb backpointer, since for S/G frames the buffer containing it
  * gets freed here.
  */
 static struct sk_buff *dpaa_cleanup_tx_fd(const struct dpaa_priv *priv,
-					  const struct qm_fd *fd)
+					  const struct qm_fd *fd, bool ts)
 {
 	const enum dma_data_direction dma_dir = DMA_TO_DEVICE;
 	struct device *dev = priv->net_dev->dev.parent;
@@ -1620,18 +1622,6 @@
 	skbh = (struct sk_buff **)phys_to_virt(addr);
 	skb = *skbh;
 
-	if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
-		memset(&shhwtstamps, 0, sizeof(shhwtstamps));
-
-		if (!fman_port_get_tstamp(priv->mac_dev->port[TX], (void *)skbh,
-					  &ns)) {
-			shhwtstamps.hwtstamp = ns_to_ktime(ns);
-			skb_tstamp_tx(skb, &shhwtstamps);
-		} else {
-			dev_warn(dev, "fman_port_get_tstamp failed!\n");
-		}
-	}
-
 	if (unlikely(qm_fd_get_format(fd) == qm_fd_sg)) {
 		nr_frags = skb_shinfo(skb)->nr_frags;
 		dma_unmap_single(dev, addr,
@@ -1654,14 +1644,29 @@
 			dma_unmap_page(dev, qm_sg_addr(&sgt[i]),
 				       qm_sg_entry_get_len(&sgt[i]), dma_dir);
 		}
-
-		/* Free the page frag that we allocated on Tx */
-		skb_free_frag(phys_to_virt(addr));
 	} else {
 		dma_unmap_single(dev, addr,
 				 skb_tail_pointer(skb) - (u8 *)skbh, dma_dir);
 	}
 
+	/* DMA unmapping is required before accessing the HW provided info */
+	if (ts && priv->tx_tstamp &&
+	    skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
+		memset(&shhwtstamps, 0, sizeof(shhwtstamps));
+
+		if (!fman_port_get_tstamp(priv->mac_dev->port[TX], (void *)skbh,
+					  &ns)) {
+			shhwtstamps.hwtstamp = ns_to_ktime(ns);
+			skb_tstamp_tx(skb, &shhwtstamps);
+		} else {
+			dev_warn(dev, "fman_port_get_tstamp failed!\n");
+		}
+	}
+
+	if (qm_fd_get_format(fd) == qm_fd_sg)
+		/* Free the page frag that we allocated on Tx */
+		skb_free_frag(phys_to_virt(addr));
+
 	return skb;
 }
 
@@ -2048,12 +2053,12 @@
 dpaa_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
 {
 	const int queue_mapping = skb_get_queue_mapping(skb);
-	bool nonlinear = skb_is_nonlinear(skb);
 	struct rtnl_link_stats64 *percpu_stats;
 	struct dpaa_percpu_priv *percpu_priv;
 	struct netdev_queue *txq;
 	struct dpaa_priv *priv;
 	struct qm_fd fd;
+	bool nonlinear;
 	int offset = 0;
 	int err = 0;
 
@@ -2063,6 +2068,13 @@
 
 	qm_fd_clear_fd(&fd);
 
+	/* Packet data is always read as 32-bit words, so zero out any part of
+	 * the skb which might be sent if we have to pad the packet
+	 */
+	if (__skb_put_padto(skb, ETH_ZLEN, false))
+		goto enomem;
+
+	nonlinear = skb_is_nonlinear(skb);
 	if (!nonlinear) {
 		/* We're going to store the skb backpointer at the beginning
 		 * of the data buffer, so we need a privately owned skb
@@ -2114,7 +2126,7 @@
 	if (likely(dpaa_xmit(priv, percpu_stats, queue_mapping, &fd) == 0))
 		return NETDEV_TX_OK;
 
-	dpaa_cleanup_tx_fd(priv, &fd);
+	dpaa_cleanup_tx_fd(priv, &fd, false);
 skb_to_fd_failed:
 enomem:
 	percpu_stats->tx_errors++;
@@ -2160,7 +2172,7 @@
 
 	percpu_priv->stats.tx_errors++;
 
-	skb = dpaa_cleanup_tx_fd(priv, fd);
+	skb = dpaa_cleanup_tx_fd(priv, fd, false);
 	dev_kfree_skb(skb);
 }
 
@@ -2200,7 +2212,7 @@
 
 	percpu_priv->tx_confirm++;
 
-	skb = dpaa_cleanup_tx_fd(priv, fd);
+	skb = dpaa_cleanup_tx_fd(priv, fd, true);
 
 	consume_skb(skb);
 }
@@ -2430,7 +2442,7 @@
 	percpu_priv->stats.tx_fifo_errors++;
 	count_ern(percpu_priv, msg);
 
-	skb = dpaa_cleanup_tx_fd(priv, fd);
+	skb = dpaa_cleanup_tx_fd(priv, fd, false);
 	dev_kfree_skb_any(skb);
 }
 
@@ -2478,6 +2490,9 @@
 	mac_dev->adjust_link(mac_dev);
 }
 
+/* The Aquantia PHYs are capable of performing rate adaptation */
+#define PHY_VEND_AQUANTIA	0x03a1b400
+
 static int dpaa_phy_init(struct net_device *net_dev)
 {
 	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
@@ -2496,9 +2511,14 @@
 		return -ENODEV;
 	}
 
-	/* Remove any features not supported by the controller */
-	ethtool_convert_legacy_u32_to_link_mode(mask, mac_dev->if_support);
-	linkmode_and(phy_dev->supported, phy_dev->supported, mask);
+	/* Unless the PHY is capable of rate adaptation */
+	if (mac_dev->phy_if != PHY_INTERFACE_MODE_XGMII ||
+	    ((phy_dev->drv->phy_id & GENMASK(31, 10)) != PHY_VEND_AQUANTIA)) {
+		/* remove any features not supported by the controller */
+		ethtool_convert_legacy_u32_to_link_mode(mask,
+							mac_dev->if_support);
+		linkmode_and(phy_dev->supported, phy_dev->supported, mask);
+	}
 
 	phy_support_asym_pause(phy_dev);
 
@@ -2757,9 +2777,7 @@
 	headroom = (u16)(bl->priv_data_size + DPAA_PARSE_RESULTS_SIZE +
 		DPAA_TIME_STAMP_SIZE + DPAA_HASH_RESULTS_SIZE);
 
-	return DPAA_FD_DATA_ALIGNMENT ? ALIGN(headroom,
-					      DPAA_FD_DATA_ALIGNMENT) :
-					headroom;
+	return ALIGN(headroom, DPAA_FD_DATA_ALIGNMENT);
 }
 
 static int dpaa_eth_probe(struct platform_device *pdev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c
@@ -506,11 +506,15 @@
 	info->phc_index = -1;
 
 	fman_node = of_get_parent(mac_node);
-	if (fman_node)
+	if (fman_node) {
 		ptp_node = of_parse_phandle(fman_node, "ptimer-handle", 0);
+		of_node_put(fman_node);
+	}
 
-	if (ptp_node)
+	if (ptp_node) {
 		ptp_dev = of_find_device_by_node(ptp_node);
+		of_node_put(ptp_node);
+	}
 
 	if (ptp_dev)
 		ptp = platform_get_drvdata(ptp_dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
@@ -86,7 +86,7 @@
 	for (i = 1; i < DPAA2_ETH_MAX_SG_ENTRIES; i++) {
 		addr = dpaa2_sg_get_addr(&sgt[i]);
 		sg_vaddr = dpaa2_iova_to_virt(priv->iommu_domain, addr);
-		dma_unmap_page(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
+		dma_unmap_page(dev, addr, priv->rx_buf_size,
 			       DMA_BIDIRECTIONAL);
 
 		free_pages((unsigned long)sg_vaddr, 0);
@@ -144,7 +144,7 @@
 		/* Get the address and length from the S/G entry */
 		sg_addr = dpaa2_sg_get_addr(sge);
 		sg_vaddr = dpaa2_iova_to_virt(priv->iommu_domain, sg_addr);
-		dma_unmap_page(dev, sg_addr, DPAA2_ETH_RX_BUF_SIZE,
+		dma_unmap_page(dev, sg_addr, priv->rx_buf_size,
 			       DMA_BIDIRECTIONAL);
 
 		sg_length = dpaa2_sg_get_len(sge);
@@ -185,7 +185,7 @@
 				(page_address(page) - page_address(head_page));
 
 			skb_add_rx_frag(skb, i - 1, head_page, page_offset,
-					sg_length, DPAA2_ETH_RX_BUF_SIZE);
+					sg_length, priv->rx_buf_size);
 		}
 
 		if (dpaa2_sg_is_final(sge))
@@ -211,7 +211,7 @@
 
 	for (i = 0; i < count; i++) {
 		vaddr = dpaa2_iova_to_virt(priv->iommu_domain, buf_array[i]);
-		dma_unmap_page(dev, buf_array[i], DPAA2_ETH_RX_BUF_SIZE,
+		dma_unmap_page(dev, buf_array[i], priv->rx_buf_size,
 			       DMA_BIDIRECTIONAL);
 		free_pages((unsigned long)vaddr, 0);
 	}
@@ -331,7 +331,7 @@
 		break;
 	case XDP_REDIRECT:
 		dma_unmap_page(priv->net_dev->dev.parent, addr,
-			       DPAA2_ETH_RX_BUF_SIZE, DMA_BIDIRECTIONAL);
+			       priv->rx_buf_size, DMA_BIDIRECTIONAL);
 		ch->buf_count--;
 		xdp.data_hard_start = vaddr;
 		err = xdp_do_redirect(priv->net_dev, &xdp, xdp_prog);
@@ -370,7 +370,7 @@
 	trace_dpaa2_rx_fd(priv->net_dev, fd);
 
 	vaddr = dpaa2_iova_to_virt(priv->iommu_domain, addr);
-	dma_sync_single_for_cpu(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
+	dma_sync_single_for_cpu(dev, addr, priv->rx_buf_size,
 				DMA_BIDIRECTIONAL);
 
 	fas = dpaa2_get_fas(vaddr, false);
@@ -389,13 +389,13 @@
 			return;
 		}
 
-		dma_unmap_page(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
+		dma_unmap_page(dev, addr, priv->rx_buf_size,
 			       DMA_BIDIRECTIONAL);
 		skb = build_linear_skb(ch, fd, vaddr);
 	} else if (fd_format == dpaa2_fd_sg) {
 		WARN_ON(priv->xdp_prog);
 
-		dma_unmap_page(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
+		dma_unmap_page(dev, addr, priv->rx_buf_size,
 			       DMA_BIDIRECTIONAL);
 		skb = build_frag_skb(priv, ch, buf_data);
 		free_pages((unsigned long)vaddr, 0);
@@ -963,7 +963,7 @@
 		if (!page)
 			goto err_alloc;
 
-		addr = dma_map_page(dev, page, 0, DPAA2_ETH_RX_BUF_SIZE,
+		addr = dma_map_page(dev, page, 0, priv->rx_buf_size,
 				    DMA_BIDIRECTIONAL);
 		if (unlikely(dma_mapping_error(dev, addr)))
 			goto err_map;
@@ -971,9 +971,9 @@
 		buf_array[i] = addr;
 
 		/* tracing point */
-		trace_dpaa2_eth_buf_seed(priv->net_dev,
-					 page, DPAA2_ETH_RX_BUF_RAW_SIZE,
-					 addr, DPAA2_ETH_RX_BUF_SIZE,
+		trace_dpaa2_eth_buf_seed(priv->net_dev, page_address(page),
+					 DPAA2_ETH_RX_BUF_RAW_SIZE,
+					 addr, priv->rx_buf_size,
 					 bpid);
 	}
 
@@ -1680,7 +1680,7 @@
 	int mfl, linear_mfl;
 
 	mfl = DPAA2_ETH_L2_MAX_FRM(mtu);
-	linear_mfl = DPAA2_ETH_RX_BUF_SIZE - DPAA2_ETH_RX_HWA_SIZE -
+	linear_mfl = priv->rx_buf_size - DPAA2_ETH_RX_HWA_SIZE -
 		     dpaa2_eth_rx_head_room(priv) - XDP_PACKET_HEADROOM;
 
 	if (mfl > linear_mfl) {
@@ -1945,11 +1945,14 @@
 static int update_xps(struct dpaa2_eth_priv *priv)
 {
 	struct net_device *net_dev = priv->net_dev;
-	struct cpumask xps_mask;
-	struct dpaa2_eth_fq *fq;
 	int i, num_queues, netdev_queues;
+	struct dpaa2_eth_fq *fq;
+	cpumask_var_t xps_mask;
 	int err = 0;
 
+	if (!alloc_cpumask_var(&xps_mask, GFP_KERNEL))
+		return -ENOMEM;
+
 	num_queues = dpaa2_eth_queue_count(priv);
 	netdev_queues = (net_dev->num_tc ? : 1) * num_queues;
 
@@ -1959,16 +1962,17 @@
 	for (i = 0; i < netdev_queues; i++) {
 		fq = &priv->fq[i % num_queues];
 
-		cpumask_clear(&xps_mask);
-		cpumask_set_cpu(fq->target_cpu, &xps_mask);
+		cpumask_clear(xps_mask);
+		cpumask_set_cpu(fq->target_cpu, xps_mask);
 
-		err = netif_set_xps_queue(net_dev, &xps_mask, i);
+		err = netif_set_xps_queue(net_dev, xps_mask, i);
 		if (err) {
 			netdev_warn_once(net_dev, "Error setting XPS queue\n");
 			break;
 		}
 	}
 
+	free_cpumask_var(xps_mask);
 	return err;
 }
 
@@ -1981,7 +1985,7 @@
 	int i;
 
 	if (type != TC_SETUP_QDISC_MQPRIO)
-		return -EINVAL;
+		return -EOPNOTSUPP;
 
 	mqprio->hw = TC_MQPRIO_HW_OFFLOAD_TCS;
 	num_queues = dpaa2_eth_queue_count(priv);
@@ -1993,7 +1997,7 @@
 	if (num_tc  > dpaa2_eth_tc_count(priv)) {
 		netdev_err(net_dev, "Max %d traffic classes supported\n",
 			   dpaa2_eth_tc_count(priv));
-		return -EINVAL;
+		return -EOPNOTSUPP;
 	}
 
 	if (!num_tc) {
@@ -2090,7 +2094,7 @@
 free:
 	fsl_mc_object_free(dpcon);
 
-	return NULL;
+	return ERR_PTR(err);
 }
 
 static void free_dpcon(struct dpaa2_eth_priv *priv,
@@ -2114,8 +2118,8 @@
 		return NULL;
 
 	channel->dpcon = setup_dpcon(priv);
-	if (IS_ERR_OR_NULL(channel->dpcon)) {
-		err = PTR_ERR_OR_ZERO(channel->dpcon);
+	if (IS_ERR(channel->dpcon)) {
+		err = PTR_ERR(channel->dpcon);
 		goto err_setup;
 	}
 
@@ -2432,6 +2436,11 @@
 	else
 		rx_buf_align = DPAA2_ETH_RX_BUF_ALIGN;
 
+	/* We need to ensure that the buffer size seen by WRIOP is a multiple
+	 * of 64 or 256 bytes depending on the WRIOP version.
+	 */
+	priv->rx_buf_size = ALIGN_DOWN(DPAA2_ETH_RX_BUF_SIZE, rx_buf_align);
+
 	/* tx buffer */
 	buf_layout.private_data_size = DPAA2_ETH_SWA_SIZE;
 	buf_layout.pass_timestamp = true;
@@ -2649,8 +2658,10 @@
 
 	priv->cls_rules = devm_kzalloc(dev, sizeof(struct dpaa2_eth_cls_rule) *
 				       dpaa2_eth_fs_count(priv), GFP_KERNEL);
-	if (!priv->cls_rules)
+	if (!priv->cls_rules) {
+		err = -ENOMEM;
 		goto close;
+	}
 
 	return 0;
 
@@ -3096,7 +3107,7 @@
 	pools_params.num_dpbp = 1;
 	pools_params.pools[0].dpbp_id = priv->dpbp_dev->obj_desc.id;
 	pools_params.pools[0].backup_pool = 0;
-	pools_params.pools[0].buffer_size = DPAA2_ETH_RX_BUF_SIZE;
+	pools_params.pools[0].buffer_size = priv->rx_buf_size;
 	err = dpni_set_pools(priv->mc_io, 0, priv->mc_token, &pools_params);
 	if (err) {
 		dev_err(dev, "dpni_set_pools() failed\n");
@@ -3609,10 +3620,10 @@
 
 	fsl_mc_portal_free(priv->mc_io);
 
-	free_netdev(net_dev);
-
 	dev_dbg(net_dev->dev.parent, "Removed interface %s\n", net_dev->name);
 
+	free_netdev(net_dev);
+
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h
@@ -373,6 +373,7 @@
 	u16 tx_data_offset;
 
 	struct fsl_mc_device *dpbp_dev;
+	u16 rx_buf_size;
 	u16 bpid;
 	struct iommu_domain *iommu_domain;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/dpaa2/dpaa2-ethtool.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/dpaa2/dpaa2-ethtool.c
@@ -216,7 +216,7 @@
 		if (err == -EINVAL)
 			/* Older firmware versions don't support all pages */
 			memset(&dpni_stats, 0, sizeof(dpni_stats));
-		else
+		else if (err)
 			netdev_warn(net_dev, "dpni_get_stats(%d) failed\n", j);
 
 		num_cnt = dpni_stats_page_size[j] / sizeof(u64);
@@ -590,7 +590,7 @@
 
 static int update_cls_rule(struct net_device *net_dev,
 			   struct ethtool_rx_flow_spec *new_fs,
-			   int location)
+			   unsigned int location)
 {
 	struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
 	struct dpaa2_eth_cls_rule *rule;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp.c
@@ -148,7 +148,7 @@
 	base = of_iomap(node, 0);
 	if (!base) {
 		err = -ENOMEM;
-		goto err_close;
+		goto err_put;
 	}
 
 	err = fsl_mc_allocate_irqs(mc_dev);
@@ -160,10 +160,10 @@
 	irq = mc_dev->irqs[0];
 	ptp_qoriq->irq = irq->msi_desc->irq;
 
-	err = devm_request_threaded_irq(dev, ptp_qoriq->irq, NULL,
-					dpaa2_ptp_irq_handler_thread,
-					IRQF_NO_SUSPEND | IRQF_ONESHOT,
-					dev_name(dev), ptp_qoriq);
+	err = request_threaded_irq(ptp_qoriq->irq, NULL,
+				   dpaa2_ptp_irq_handler_thread,
+				   IRQF_NO_SUSPEND | IRQF_ONESHOT,
+				   dev_name(dev), ptp_qoriq);
 	if (err < 0) {
 		dev_err(dev, "devm_request_threaded_irq(): %d\n", err);
 		goto err_free_mc_irq;
@@ -173,22 +173,26 @@
 				   DPRTC_IRQ_INDEX, 1);
 	if (err < 0) {
 		dev_err(dev, "dprtc_set_irq_enable(): %d\n", err);
-		goto err_free_mc_irq;
+		goto err_free_threaded_irq;
 	}
 
 	err = ptp_qoriq_init(ptp_qoriq, base, &dpaa2_ptp_caps);
 	if (err)
-		goto err_free_mc_irq;
+		goto err_free_threaded_irq;
 
 	dpaa2_phc_index = ptp_qoriq->phc_index;
 	dev_set_drvdata(dev, ptp_qoriq);
 
 	return 0;
 
+err_free_threaded_irq:
+	free_irq(ptp_qoriq->irq, ptp_qoriq);
 err_free_mc_irq:
 	fsl_mc_free_irqs(mc_dev);
 err_unmap:
 	iounmap(base);
+err_put:
+	of_node_put(node);
 err_close:
 	dprtc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
 err_free_mcp:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/enetc/enetc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -254,7 +254,7 @@
 	/* disable interrupts */
 	enetc_wr_reg(v->rbier, 0);
 
-	for_each_set_bit(i, &v->tx_rings_map, v->count_tx_rings)
+	for_each_set_bit(i, &v->tx_rings_map, ENETC_MAX_NUM_TXQS)
 		enetc_wr_reg(v->tbier_base + ENETC_BDR_OFF(i), 0);
 
 	napi_schedule_irqoff(&v->napi);
@@ -290,7 +290,7 @@
 	/* enable interrupts */
 	enetc_wr_reg(v->rbier, ENETC_RBIER_RXTIE);
 
-	for_each_set_bit(i, &v->tx_rings_map, v->count_tx_rings)
+	for_each_set_bit(i, &v->tx_rings_map, ENETC_MAX_NUM_TXQS)
 		enetc_wr_reg(v->tbier_base + ENETC_BDR_OFF(i),
 			     ENETC_TBIER_TXTIE);
 
@@ -942,7 +942,7 @@
 		enetc_free_tx_ring(priv->tx_ring[i]);
 }
 
-static int enetc_alloc_cbdr(struct device *dev, struct enetc_cbdr *cbdr)
+int enetc_alloc_cbdr(struct device *dev, struct enetc_cbdr *cbdr)
 {
 	int size = cbdr->bd_count * sizeof(struct enetc_cbd);
 
@@ -963,7 +963,7 @@
 	return 0;
 }
 
-static void enetc_free_cbdr(struct device *dev, struct enetc_cbdr *cbdr)
+void enetc_free_cbdr(struct device *dev, struct enetc_cbdr *cbdr)
 {
 	int size = cbdr->bd_count * sizeof(struct enetc_cbd);
 
@@ -971,7 +971,7 @@
 	cbdr->bd_base = NULL;
 }
 
-static void enetc_setup_cbdr(struct enetc_hw *hw, struct enetc_cbdr *cbdr)
+void enetc_setup_cbdr(struct enetc_hw *hw, struct enetc_cbdr *cbdr)
 {
 	/* set CBDR cache attributes */
 	enetc_wr(hw, ENETC_SICAR2,
@@ -991,7 +991,7 @@
 	cbdr->cir = hw->reg + ENETC_SICBDRCIR;
 }
 
-static void enetc_clear_cbdr(struct enetc_hw *hw)
+void enetc_clear_cbdr(struct enetc_hw *hw)
 {
 	enetc_wr(hw, ENETC_SICBDRMR, 0);
 }
@@ -1016,13 +1016,12 @@
 	return 0;
 }
 
-static int enetc_configure_si(struct enetc_ndev_priv *priv)
+int enetc_configure_si(struct enetc_ndev_priv *priv)
 {
 	struct enetc_si *si = priv->si;
 	struct enetc_hw *hw = &si->hw;
 	int err;
 
-	enetc_setup_cbdr(hw, &si->cbd_ring);
 	/* set SI cache attributes */
 	enetc_wr(hw, ENETC_SICAR0,
 		 ENETC_SICAR_RD_COHERENT | ENETC_SICAR_WR_COHERENT);
@@ -1068,6 +1067,8 @@
 	if (err)
 		return err;
 
+	enetc_setup_cbdr(&si->hw, &si->cbd_ring);
+
 	priv->cls_rules = kcalloc(si->num_fs_entries, sizeof(*priv->cls_rules),
 				  GFP_KERNEL);
 	if (!priv->cls_rules) {
@@ -1075,14 +1076,8 @@
 		goto err_alloc_cls;
 	}
 
-	err = enetc_configure_si(priv);
-	if (err)
-		goto err_config_si;
-
 	return 0;
 
-err_config_si:
-	kfree(priv->cls_rules);
 err_alloc_cls:
 	enetc_clear_cbdr(&si->hw);
 	enetc_free_cbdr(priv->dev, &si->cbd_ring);
@@ -1151,7 +1146,12 @@
 
 	enetc_rxbdr_wr(hw, idx, ENETC_RBBSR, ENETC_RXB_DMA_SIZE);
 
+	/* Also prepare the consumer index in case page allocation never
+	 * succeeds. In that case, hardware will never advance producer index
+	 * to match consumer index, and will drop all frames.
+	 */
 	enetc_rxbdr_wr(hw, idx, ENETC_RBPIR, 0);
+	enetc_rxbdr_wr(hw, idx, ENETC_RBCIR, 1);
 
 	/* enable Rx ints by setting pkt thr to 1 */
 	enetc_rxbdr_wr(hw, idx, ENETC_RBICIR0, ENETC_RBICIR0_ICEN | 0x1);
@@ -1227,7 +1227,6 @@
 static int enetc_setup_irqs(struct enetc_ndev_priv *priv)
 {
 	struct pci_dev *pdev = priv->si->pdev;
-	cpumask_t cpu_mask;
 	int i, j, err;
 
 	for (i = 0; i < priv->bdr_int_num; i++) {
@@ -1254,9 +1253,7 @@
 
 			enetc_wr(hw, ENETC_SIMSITRV(idx), entry);
 		}
-		cpumask_clear(&cpu_mask);
-		cpumask_set_cpu(i % num_online_cpus(), &cpu_mask);
-		irq_set_affinity_hint(irq, &cpu_mask);
+		irq_set_affinity_hint(irq, get_cpu_mask(i % num_online_cpus()));
 	}
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/enetc/enetc.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -221,6 +221,7 @@
 void enetc_init_si_rings_params(struct enetc_ndev_priv *priv);
 int enetc_alloc_si_resources(struct enetc_ndev_priv *priv);
 void enetc_free_si_resources(struct enetc_ndev_priv *priv);
+int enetc_configure_si(struct enetc_ndev_priv *priv);
 
 int enetc_open(struct net_device *ndev);
 int enetc_close(struct net_device *ndev);
@@ -236,6 +237,10 @@
 void enetc_set_ethtool_ops(struct net_device *ndev);
 
 /* control buffer descriptor ring (CBDR) */
+int enetc_alloc_cbdr(struct device *dev, struct enetc_cbdr *cbdr);
+void enetc_free_cbdr(struct device *dev, struct enetc_cbdr *cbdr);
+void enetc_setup_cbdr(struct enetc_hw *hw, struct enetc_cbdr *cbdr);
+void enetc_clear_cbdr(struct enetc_hw *hw);
 int enetc_set_mac_flt_entry(struct enetc_si *si, int index,
 			    char *mac_addr, int si_map);
 int enetc_clear_mac_flt_entry(struct enetc_si *si, int index);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
@@ -141,8 +141,8 @@
 	{ ENETC_PM0_R255,   "MAC rx 128-255 byte packets" },
 	{ ENETC_PM0_R511,   "MAC rx 256-511 byte packets" },
 	{ ENETC_PM0_R1023,  "MAC rx 512-1023 byte packets" },
-	{ ENETC_PM0_R1518,  "MAC rx 1024-1518 byte packets" },
-	{ ENETC_PM0_R1519X, "MAC rx 1519 to max-octet packets" },
+	{ ENETC_PM0_R1522,  "MAC rx 1024-1522 byte packets" },
+	{ ENETC_PM0_R1523X, "MAC rx 1523 to max-octet packets" },
 	{ ENETC_PM0_ROVR,   "MAC rx oversized packets" },
 	{ ENETC_PM0_RJBR,   "MAC rx jabber packets" },
 	{ ENETC_PM0_RFRG,   "MAC rx fragment packets" },
@@ -155,15 +155,19 @@
 	{ ENETC_PM0_TFRM,   "MAC tx frames" },
 	{ ENETC_PM0_TFCS,   "MAC tx fcs errors" },
 	{ ENETC_PM0_TVLAN,  "MAC tx VLAN frames" },
-	{ ENETC_PM0_TERR,   "MAC tx frames" },
+	{ ENETC_PM0_TERR,   "MAC tx frame errors" },
 	{ ENETC_PM0_TUCA,   "MAC tx unicast frames" },
 	{ ENETC_PM0_TMCA,   "MAC tx multicast frames" },
 	{ ENETC_PM0_TBCA,   "MAC tx broadcast frames" },
 	{ ENETC_PM0_TPKT,   "MAC tx packets" },
 	{ ENETC_PM0_TUND,   "MAC tx undersized packets" },
+	{ ENETC_PM0_T64,    "MAC tx 64 byte packets" },
 	{ ENETC_PM0_T127,   "MAC tx 65-127 byte packets" },
+	{ ENETC_PM0_T255,   "MAC tx 128-255 byte packets" },
+	{ ENETC_PM0_T511,   "MAC tx 256-511 byte packets" },
 	{ ENETC_PM0_T1023,  "MAC tx 512-1023 byte packets" },
-	{ ENETC_PM0_T1518,  "MAC tx 1024-1518 byte packets" },
+	{ ENETC_PM0_T1522,  "MAC tx 1024-1522 byte packets" },
+	{ ENETC_PM0_T1523X, "MAC tx 1523 to max-octet packets" },
 	{ ENETC_PM0_TCNP,   "MAC tx control packets" },
 	{ ENETC_PM0_TDFR,   "MAC tx deferred packets" },
 	{ ENETC_PM0_TMCOL,  "MAC tx multiple collisions" },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/enetc/enetc_hw.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/enetc/enetc_hw.h
@@ -181,6 +181,8 @@
 #define ENETC_PTCCBSR0(n)	(0x1110 + (n) * 8) /* n = 0 to 7*/
 #define ENETC_PTCCBSR1(n)	(0x1114 + (n) * 8) /* n = 0 to 7*/
 #define ENETC_RSSHASH_KEY_SIZE	40
+#define ENETC_PRSSCAPR		0x1404
+#define ENETC_PRSSCAPR_GET_NUM_RSS(val)	(BIT((val) & 0xf) * 32)
 #define ENETC_PRSSK(n)		(0x1410 + (n) * 4) /* n = [0..9] */
 #define ENETC_PSIVLANFMR	0x1700
 #define ENETC_PSIVLANFMR_VS	BIT(0)
@@ -239,8 +241,8 @@
 #define ENETC_PM0_R255		0x8180
 #define ENETC_PM0_R511		0x8188
 #define ENETC_PM0_R1023		0x8190
-#define ENETC_PM0_R1518		0x8198
-#define ENETC_PM0_R1519X	0x81A0
+#define ENETC_PM0_R1522		0x8198
+#define ENETC_PM0_R1523X	0x81A0
 #define ENETC_PM0_ROVR		0x81A8
 #define ENETC_PM0_RJBR		0x81B0
 #define ENETC_PM0_RFRG		0x81B8
@@ -259,9 +261,13 @@
 #define ENETC_PM0_TBCA		0x8250
 #define ENETC_PM0_TPKT		0x8260
 #define ENETC_PM0_TUND		0x8268
+#define ENETC_PM0_T64		0x8270
 #define ENETC_PM0_T127		0x8278
+#define ENETC_PM0_T255		0x8280
+#define ENETC_PM0_T511		0x8288
 #define ENETC_PM0_T1023		0x8290
-#define ENETC_PM0_T1518		0x8298
+#define ENETC_PM0_T1522		0x8298
+#define ENETC_PM0_T1523X	0x82A0
 #define ENETC_PM0_TCNP		0x82C0
 #define ENETC_PM0_TDFR		0x82D0
 #define ENETC_PM0_TMCOL		0x82D8
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -809,6 +809,71 @@
 		of_node_put(priv->phy_node);
 }
 
+/* Initialize the entire shared memory for the flow steering entries
+ * of this port (PF + VFs)
+ */
+static int enetc_init_port_rfs_memory(struct enetc_si *si)
+{
+	struct enetc_cmd_rfse rfse = {0};
+	struct enetc_hw *hw = &si->hw;
+	int num_rfs, i, err = 0;
+	u32 val;
+
+	val = enetc_port_rd(hw, ENETC_PRFSCAPR);
+	num_rfs = ENETC_PRFSCAPR_GET_NUM_RFS(val);
+
+	for (i = 0; i < num_rfs; i++) {
+		err = enetc_set_fs_entry(si, &rfse, i);
+		if (err)
+			break;
+	}
+
+	return err;
+}
+
+static int enetc_init_port_rss_memory(struct enetc_si *si)
+{
+	struct enetc_hw *hw = &si->hw;
+	int num_rss, err;
+	int *rss_table;
+	u32 val;
+
+	val = enetc_port_rd(hw, ENETC_PRSSCAPR);
+	num_rss = ENETC_PRSSCAPR_GET_NUM_RSS(val);
+	if (!num_rss)
+		return 0;
+
+	rss_table = kcalloc(num_rss, sizeof(*rss_table), GFP_KERNEL);
+	if (!rss_table)
+		return -ENOMEM;
+
+	err = enetc_set_rss_table(si, rss_table, num_rss);
+
+	kfree(rss_table);
+
+	return err;
+}
+
+static void enetc_init_unused_port(struct enetc_si *si)
+{
+	struct device *dev = &si->pdev->dev;
+	struct enetc_hw *hw = &si->hw;
+	int err;
+
+	si->cbd_ring.bd_count = ENETC_CBDR_DEFAULT_SIZE;
+	err = enetc_alloc_cbdr(dev, &si->cbd_ring);
+	if (err)
+		return;
+
+	enetc_setup_cbdr(hw, &si->cbd_ring);
+
+	enetc_init_port_rfs_memory(si);
+	enetc_init_port_rss_memory(si);
+
+	enetc_clear_cbdr(hw);
+	enetc_free_cbdr(dev, &si->cbd_ring);
+}
+
 static int enetc_pf_probe(struct pci_dev *pdev,
 			  const struct pci_device_id *ent)
 {
@@ -818,11 +883,6 @@
 	struct enetc_pf *pf;
 	int err;
 
-	if (pdev->dev.of_node && !of_device_is_available(pdev->dev.of_node)) {
-		dev_info(&pdev->dev, "device is disabled, skipping\n");
-		return -ENODEV;
-	}
-
 	err = enetc_pci_probe(pdev, KBUILD_MODNAME, sizeof(*pf));
 	if (err) {
 		dev_err(&pdev->dev, "PCI probing failed\n");
@@ -836,6 +896,13 @@
 		goto err_map_pf_space;
 	}
 
+	if (pdev->dev.of_node && !of_device_is_available(pdev->dev.of_node)) {
+		enetc_init_unused_port(si);
+		dev_info(&pdev->dev, "device is disabled, skipping\n");
+		err = -ENODEV;
+		goto err_device_disabled;
+	}
+
 	pf = enetc_si_priv(si);
 	pf->si = si;
 	pf->total_vfs = pci_sriov_get_totalvfs(pdev);
@@ -863,6 +930,24 @@
 		goto err_alloc_si_res;
 	}
 
+	err = enetc_init_port_rfs_memory(si);
+	if (err) {
+		dev_err(&pdev->dev, "Failed to initialize RFS memory\n");
+		goto err_init_port_rfs;
+	}
+
+	err = enetc_init_port_rss_memory(si);
+	if (err) {
+		dev_err(&pdev->dev, "Failed to initialize RSS memory\n");
+		goto err_init_port_rss;
+	}
+
+	err = enetc_configure_si(priv);
+	if (err) {
+		dev_err(&pdev->dev, "Failed to configure SI\n");
+		goto err_config_si;
+	}
+
 	err = enetc_alloc_msix(priv);
 	if (err) {
 		dev_err(&pdev->dev, "MSIX alloc failed\n");
@@ -885,14 +970,19 @@
 	return 0;
 
 err_reg_netdev:
+	enetc_mdio_remove(pf);
 	enetc_of_put_phy(priv);
 	enetc_free_msix(priv);
+err_config_si:
+err_init_port_rss:
+err_init_port_rfs:
 err_alloc_msix:
 	enetc_free_si_resources(priv);
 err_alloc_si_res:
 	si->ndev = NULL;
 	free_netdev(ndev);
 err_alloc_netdev:
+err_device_disabled:
 err_map_pf_space:
 	enetc_pci_remove(pdev);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/enetc/enetc_ptp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/enetc/enetc_ptp.c
@@ -8,7 +8,7 @@
 #include "enetc.h"
 
 int enetc_phc_index = -1;
-EXPORT_SYMBOL(enetc_phc_index);
+EXPORT_SYMBOL_GPL(enetc_phc_index);
 
 static struct ptp_clock_info enetc_ptp_caps = {
 	.owner		= THIS_MODULE,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/enetc/enetc_vf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/enetc/enetc_vf.c
@@ -94,6 +94,8 @@
 	if (err)
 		return err;
 
+	eth_hw_addr_set(ndev, saddr->sa_data);
+
 	return 0;
 }
 
@@ -189,6 +191,12 @@
 		goto err_alloc_si_res;
 	}
 
+	err = enetc_configure_si(priv);
+	if (err) {
+		dev_err(&pdev->dev, "Failed to configure SI\n");
+		goto err_config_si;
+	}
+
 	err = enetc_alloc_msix(priv);
 	if (err) {
 		dev_err(&pdev->dev, "MSIX alloc failed\n");
@@ -208,6 +216,7 @@
 
 err_reg_netdev:
 	enetc_free_msix(priv);
+err_config_si:
 err_alloc_msix:
 	enetc_free_si_resources(priv);
 err_alloc_si_res:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/fec.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/fec.h
@@ -373,6 +373,9 @@
 #define FEC_ENET_WAKEUP	((uint)0x00020000)	/* Wakeup request */
 #define FEC_ENET_TXF	(FEC_ENET_TXF_0 | FEC_ENET_TXF_1 | FEC_ENET_TXF_2)
 #define FEC_ENET_RXF	(FEC_ENET_RXF_0 | FEC_ENET_RXF_1 | FEC_ENET_RXF_2)
+#define FEC_ENET_RXF_GET(X)	(((X) == 0) ? FEC_ENET_RXF_0 :	\
+				(((X) == 1) ? FEC_ENET_RXF_1 :	\
+				FEC_ENET_RXF_2))
 #define FEC_ENET_TS_AVAIL       ((uint)0x00010000)
 #define FEC_ENET_TS_TIMER       ((uint)0x00008000)
 
@@ -488,6 +491,12 @@
 	struct  sk_buff *rx_skbuff[RX_RING_SIZE];
 };
 
+struct fec_stop_mode_gpr {
+	struct regmap *gpr;
+	u8 reg;
+	u8 bit;
+};
+
 /* The FEC buffer descriptors track the ring buffers.  The rx_bd_base and
  * tx_bd_base always point to the base of the buffer descriptors.  The
  * cur_rx and cur_tx point to the currently available buffer.
@@ -562,6 +571,7 @@
 	int hwts_tx_en;
 	struct delayed_work time_keep;
 	struct regulator *reg_phy;
+	struct fec_stop_mode_gpr stop_gpr;
 
 	unsigned int tx_align;
 	unsigned int rx_align;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/fec_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/fec_main.c
@@ -62,6 +62,8 @@
 #include <linux/if_vlan.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/prefetch.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
 #include <soc/imx/cpuidle.h>
 
 #include <asm/cacheflush.h>
@@ -84,6 +86,56 @@
 #define FEC_ENET_OPD_V	0xFFF0
 #define FEC_MDIO_PM_TIMEOUT  100 /* ms */
 
+struct fec_devinfo {
+	u32 quirks;
+	u8 stop_gpr_reg;
+	u8 stop_gpr_bit;
+};
+
+static const struct fec_devinfo fec_imx25_info = {
+	.quirks = FEC_QUIRK_USE_GASKET | FEC_QUIRK_MIB_CLEAR |
+		  FEC_QUIRK_HAS_FRREG,
+};
+
+static const struct fec_devinfo fec_imx27_info = {
+	.quirks = FEC_QUIRK_MIB_CLEAR | FEC_QUIRK_HAS_FRREG,
+};
+
+static const struct fec_devinfo fec_imx28_info = {
+	.quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME |
+		  FEC_QUIRK_SINGLE_MDIO | FEC_QUIRK_HAS_RACC |
+		  FEC_QUIRK_HAS_FRREG,
+};
+
+static const struct fec_devinfo fec_imx6q_info = {
+	.quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
+		  FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
+		  FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR006358 |
+		  FEC_QUIRK_HAS_RACC,
+	.stop_gpr_reg = 0x34,
+	.stop_gpr_bit = 27,
+};
+
+static const struct fec_devinfo fec_mvf600_info = {
+	.quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_RACC,
+};
+
+static const struct fec_devinfo fec_imx6x_info = {
+	.quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
+		  FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
+		  FEC_QUIRK_HAS_VLAN | FEC_QUIRK_HAS_AVB |
+		  FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE |
+		  FEC_QUIRK_HAS_RACC | FEC_QUIRK_HAS_COALESCE,
+};
+
+static const struct fec_devinfo fec_imx6ul_info = {
+	.quirks = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
+		  FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
+		  FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR007885 |
+		  FEC_QUIRK_BUG_CAPTURE | FEC_QUIRK_HAS_RACC |
+		  FEC_QUIRK_HAS_COALESCE,
+};
+
 static struct platform_device_id fec_devtype[] = {
 	{
 		/* keep it for coldfire */
@@ -91,39 +143,25 @@
 		.driver_data = 0,
 	}, {
 		.name = "imx25-fec",
-		.driver_data = FEC_QUIRK_USE_GASKET | FEC_QUIRK_MIB_CLEAR |
-			       FEC_QUIRK_HAS_FRREG,
+		.driver_data = (kernel_ulong_t)&fec_imx25_info,
 	}, {
 		.name = "imx27-fec",
-		.driver_data = FEC_QUIRK_MIB_CLEAR | FEC_QUIRK_HAS_FRREG,
+		.driver_data = (kernel_ulong_t)&fec_imx27_info,
 	}, {
 		.name = "imx28-fec",
-		.driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME |
-				FEC_QUIRK_SINGLE_MDIO | FEC_QUIRK_HAS_RACC |
-				FEC_QUIRK_HAS_FRREG,
+		.driver_data = (kernel_ulong_t)&fec_imx28_info,
 	}, {
 		.name = "imx6q-fec",
-		.driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
-				FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
-				FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR006358 |
-				FEC_QUIRK_HAS_RACC,
+		.driver_data = (kernel_ulong_t)&fec_imx6q_info,
 	}, {
 		.name = "mvf600-fec",
-		.driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_RACC,
+		.driver_data = (kernel_ulong_t)&fec_mvf600_info,
 	}, {
 		.name = "imx6sx-fec",
-		.driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
-				FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
-				FEC_QUIRK_HAS_VLAN | FEC_QUIRK_HAS_AVB |
-				FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE |
-				FEC_QUIRK_HAS_RACC | FEC_QUIRK_HAS_COALESCE,
+		.driver_data = (kernel_ulong_t)&fec_imx6x_info,
 	}, {
 		.name = "imx6ul-fec",
-		.driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
-				FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
-				FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR007885 |
-				FEC_QUIRK_BUG_CAPTURE | FEC_QUIRK_HAS_RACC |
-				FEC_QUIRK_HAS_COALESCE,
+		.driver_data = (kernel_ulong_t)&fec_imx6ul_info,
 	}, {
 		/* sentinel */
 	}
@@ -185,8 +223,8 @@
 #define PKT_MINBUF_SIZE		64
 
 /* FEC receive acceleration */
-#define FEC_RACC_IPDIS		(1 << 1)
-#define FEC_RACC_PRODIS		(1 << 2)
+#define FEC_RACC_IPDIS		BIT(1)
+#define FEC_RACC_PRODIS		BIT(2)
 #define FEC_RACC_SHIFT16	BIT(7)
 #define FEC_RACC_OPTIONS	(FEC_RACC_IPDIS | FEC_RACC_PRODIS)
 
@@ -218,8 +256,23 @@
 #define FEC_MMFR_TA		(2 << 16)
 #define FEC_MMFR_DATA(v)	(v & 0xffff)
 /* FEC ECR bits definition */
-#define FEC_ECR_MAGICEN		(1 << 2)
-#define FEC_ECR_SLEEP		(1 << 3)
+#define FEC_ECR_RESET           BIT(0)
+#define FEC_ECR_ETHEREN         BIT(1)
+#define FEC_ECR_MAGICEN         BIT(2)
+#define FEC_ECR_SLEEP           BIT(3)
+#define FEC_ECR_EN1588          BIT(4)
+#define FEC_ECR_BYTESWP         BIT(8)
+/* FEC RCR bits definition */
+#define FEC_RCR_LOOP            BIT(0)
+#define FEC_RCR_HALFDPX         BIT(1)
+#define FEC_RCR_MII             BIT(2)
+#define FEC_RCR_PROMISC         BIT(3)
+#define FEC_RCR_BC_REJ          BIT(4)
+#define FEC_RCR_FLOWCTL         BIT(5)
+#define FEC_RCR_RMII            BIT(8)
+#define FEC_RCR_10BASET         BIT(9)
+/* TX WMARK bits */
+#define FEC_TXWMRK_STRFWD       BIT(8)
 
 #define FEC_MII_TIMEOUT		30000 /* us */
 
@@ -588,7 +641,7 @@
 		dev_kfree_skb_any(skb);
 		if (net_ratelimit())
 			netdev_err(ndev, "Tx DMA memory map failed\n");
-		return NETDEV_TX_BUSY;
+		return NETDEV_TX_OK;
 	}
 
 	bdp->cbd_datlen = cpu_to_fec16(size);
@@ -650,7 +703,7 @@
 			dev_kfree_skb_any(skb);
 			if (net_ratelimit())
 				netdev_err(ndev, "Tx DMA memory map failed\n");
-			return NETDEV_TX_BUSY;
+			return NETDEV_TX_OK;
 		}
 	}
 
@@ -679,6 +732,8 @@
 	int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
 	int total_len, data_left;
 	struct bufdesc *bdp = txq->bd.cur;
+	struct bufdesc *tmp_bdp;
+	struct bufdesc_ex *ebdp;
 	struct tso_t tso;
 	unsigned int index = 0;
 	int ret;
@@ -752,7 +807,34 @@
 	return 0;
 
 err_release:
-	/* TODO: Release all used data descriptors for TSO */
+	/* Release all used data descriptors for TSO */
+	tmp_bdp = txq->bd.cur;
+
+	while (tmp_bdp != bdp) {
+		/* Unmap data buffers */
+		if (tmp_bdp->cbd_bufaddr &&
+		    !IS_TSO_HEADER(txq, fec32_to_cpu(tmp_bdp->cbd_bufaddr)))
+			dma_unmap_single(&fep->pdev->dev,
+					 fec32_to_cpu(tmp_bdp->cbd_bufaddr),
+					 fec16_to_cpu(tmp_bdp->cbd_datlen),
+					 DMA_TO_DEVICE);
+
+		/* Clear standard buffer descriptor fields */
+		tmp_bdp->cbd_sc = 0;
+		tmp_bdp->cbd_datlen = 0;
+		tmp_bdp->cbd_bufaddr = 0;
+
+		/* Handle extended descriptor if enabled */
+		if (fep->bufdesc_ex) {
+			ebdp = (struct bufdesc_ex *)tmp_bdp;
+			ebdp->cbd_esc = 0;
+		}
+
+		tmp_bdp = fec_enet_get_nextdesc(tmp_bdp, &txq->bd);
+	}
+
+	dev_kfree_skb_any(skb);
+
 	return ret;
 }
 
@@ -915,7 +997,7 @@
 	u32 val;
 	u32 temp_mac[2];
 	u32 rcntl = OPT_FRAME_SIZE | 0x04;
-	u32 ecntl = 0x2; /* ETHEREN */
+	u32 ecntl = FEC_ECR_ETHEREN;
 
 	/* Whack a reset.  We should wait for this.
 	 * For i.MX6SX SOC, enet use AXI bus, we use disable MAC
@@ -991,18 +1073,18 @@
 		    fep->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID)
 			rcntl |= (1 << 6);
 		else if (fep->phy_interface == PHY_INTERFACE_MODE_RMII)
-			rcntl |= (1 << 8);
+			rcntl |= FEC_RCR_RMII;
 		else
-			rcntl &= ~(1 << 8);
+			rcntl &= ~FEC_RCR_RMII;
 
 		/* 1G, 100M or 10M */
 		if (ndev->phydev) {
 			if (ndev->phydev->speed == SPEED_1000)
 				ecntl |= (1 << 5);
 			else if (ndev->phydev->speed == SPEED_100)
-				rcntl &= ~(1 << 9);
+				rcntl &= ~FEC_RCR_10BASET;
 			else
-				rcntl |= (1 << 9);
+				rcntl |= FEC_RCR_10BASET;
 		}
 	} else {
 #ifdef FEC_MIIGSK_ENR
@@ -1061,13 +1143,13 @@
 
 	if (fep->quirks & FEC_QUIRK_ENET_MAC) {
 		/* enable ENET endian swap */
-		ecntl |= (1 << 8);
+		ecntl |= FEC_ECR_BYTESWP;
 		/* enable ENET store and forward mode */
-		writel(1 << 8, fep->hwp + FEC_X_WMRK);
+		writel(FEC_TXWMRK_STRFWD, fep->hwp + FEC_X_WMRK);
 	}
 
 	if (fep->bufdesc_ex)
-		ecntl |= (1 << 4);
+		ecntl |= FEC_ECR_EN1588;
 
 #ifndef CONFIG_M5272
 	/* Enable the MIB statistic event counters */
@@ -1092,12 +1174,29 @@
 
 }
 
+static void fec_enet_stop_mode(struct fec_enet_private *fep, bool enabled)
+{
+	struct fec_platform_data *pdata = fep->pdev->dev.platform_data;
+	struct fec_stop_mode_gpr *stop_gpr = &fep->stop_gpr;
+
+	if (stop_gpr->gpr) {
+		if (enabled)
+			regmap_update_bits(stop_gpr->gpr, stop_gpr->reg,
+					   BIT(stop_gpr->bit),
+					   BIT(stop_gpr->bit));
+		else
+			regmap_update_bits(stop_gpr->gpr, stop_gpr->reg,
+					   BIT(stop_gpr->bit), 0);
+	} else if (pdata && pdata->sleep_mode_enable) {
+		pdata->sleep_mode_enable(enabled);
+	}
+}
+
 static void
 fec_stop(struct net_device *ndev)
 {
 	struct fec_enet_private *fep = netdev_priv(ndev);
-	struct fec_platform_data *pdata = fep->pdev->dev.platform_data;
-	u32 rmii_mode = readl(fep->hwp + FEC_R_CNTRL) & (1 << 8);
+	u32 rmii_mode = readl(fep->hwp + FEC_R_CNTRL) & FEC_RCR_RMII;
 	u32 val;
 
 	/* We cannot expect a graceful transmit stop without link !!! */
@@ -1116,7 +1215,7 @@
 		if (fep->quirks & FEC_QUIRK_HAS_AVB) {
 			writel(0, fep->hwp + FEC_ECNTRL);
 		} else {
-			writel(1, fep->hwp + FEC_ECNTRL);
+			writel(FEC_ECR_RESET, fep->hwp + FEC_ECNTRL);
 			udelay(10);
 		}
 		writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
@@ -1125,20 +1224,23 @@
 		val = readl(fep->hwp + FEC_ECNTRL);
 		val |= (FEC_ECR_MAGICEN | FEC_ECR_SLEEP);
 		writel(val, fep->hwp + FEC_ECNTRL);
-
-		if (pdata && pdata->sleep_mode_enable)
-			pdata->sleep_mode_enable(true);
+		fec_enet_stop_mode(fep, true);
 	}
 	writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
 
 	/* We have to keep ENET enabled to have MII interrupt stay working */
 	if (fep->quirks & FEC_QUIRK_ENET_MAC &&
 		!(fep->wol_flag & FEC_WOL_FLAG_SLEEP_ON)) {
-		writel(2, fep->hwp + FEC_ECNTRL);
+		writel(FEC_ECR_ETHEREN, fep->hwp + FEC_ECNTRL);
 		writel(rmii_mode, fep->hwp + FEC_R_CNTRL);
 	}
-}
 
+	if (fep->bufdesc_ex) {
+		val = readl(fep->hwp + FEC_ECNTRL);
+		val |= FEC_ECR_EN1588;
+		writel(val, fep->hwp + FEC_ECNTRL);
+	}
+}
 
 static void
 fec_timeout(struct net_device *ndev)
@@ -1391,7 +1493,7 @@
 			break;
 		pkt_received++;
 
-		writel(FEC_ENET_RXF, fep->hwp + FEC_IEVENT);
+		writel(FEC_ENET_RXF_GET(queue_id), fep->hwp + FEC_IEVENT);
 
 		/* Check for errors. */
 		status ^= BD_ENET_RX_LAST;
@@ -1742,6 +1844,7 @@
 
 		/* if any of the above changed restart the FEC */
 		if (status_change) {
+			netif_stop_queue(ndev);
 			napi_disable(&fep->napi);
 			netif_tx_lock_bh(ndev);
 			fec_restart(ndev);
@@ -1751,6 +1854,7 @@
 		}
 	} else {
 		if (fep->link) {
+			netif_stop_queue(ndev);
 			napi_disable(&fep->napi);
 			netif_tx_lock_bh(ndev);
 			fec_stop(ndev);
@@ -1892,6 +1996,27 @@
 	return ret;
 }
 
+static void fec_enet_phy_reset_after_clk_enable(struct net_device *ndev)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	struct phy_device *phy_dev = ndev->phydev;
+
+	if (phy_dev) {
+		phy_reset_after_clk_enable(phy_dev);
+	} else if (fep->phy_node) {
+		/*
+		 * If the PHY still is not bound to the MAC, but there is
+		 * OF PHY node and a matching PHY device instance already,
+		 * use the OF PHY node to obtain the PHY device instance,
+		 * and then use that PHY device instance when triggering
+		 * the PHY reset.
+		 */
+		phy_dev = of_phy_find_device(fep->phy_node);
+		phy_reset_after_clk_enable(phy_dev);
+		put_device(&phy_dev->mdio.dev);
+	}
+}
+
 static int fec_enet_clk_enable(struct net_device *ndev, bool enable)
 {
 	struct fec_enet_private *fep = netdev_priv(ndev);
@@ -1918,7 +2043,7 @@
 		if (ret)
 			goto failed_clk_ref;
 
-		phy_reset_after_clk_enable(ndev->phydev);
+		fec_enet_phy_reset_after_clk_enable(ndev);
 	} else {
 		clk_disable_unprepare(fep->clk_enet_out);
 		if (fep->clk_ptp) {
@@ -2199,8 +2324,14 @@
 {
 	struct fec_enet_private *fep = netdev_priv(ndev);
 	u32 __iomem *theregs = (u32 __iomem *)fep->hwp;
+	struct device *dev = &fep->pdev->dev;
 	u32 *buf = (u32 *)regbuf;
 	u32 i, off;
+	int ret;
+
+	ret = pm_runtime_get_sync(dev);
+	if (ret < 0)
+		return;
 
 	regs->version = fec_enet_register_version;
 
@@ -2216,6 +2347,9 @@
 		off >>= 2;
 		buf[off] = readl(&theregs[off]);
 	}
+
+	pm_runtime_mark_last_busy(dev);
+	pm_runtime_put_autosuspend(dev);
 }
 
 static int fec_enet_get_ts_info(struct net_device *ndev,
@@ -2520,15 +2654,15 @@
 		return -EINVAL;
 	}
 
-	cycle = fec_enet_us_to_itr_clock(ndev, fep->rx_time_itr);
+	cycle = fec_enet_us_to_itr_clock(ndev, ec->rx_coalesce_usecs);
 	if (cycle > 0xFFFF) {
 		dev_err(dev, "Rx coalesced usec exceed hardware limitation\n");
 		return -EINVAL;
 	}
 
-	cycle = fec_enet_us_to_itr_clock(ndev, fep->tx_time_itr);
+	cycle = fec_enet_us_to_itr_clock(ndev, ec->tx_coalesce_usecs);
 	if (cycle > 0xFFFF) {
-		dev_err(dev, "Rx coalesced usec exceed hardware limitation\n");
+		dev_err(dev, "Tx coalesced usec exceed hardware limitation\n");
 		return -EINVAL;
 	}
 
@@ -2920,16 +3054,16 @@
 	/* Init MAC prior to mii bus probe */
 	fec_restart(ndev);
 
-	/* Probe and connect to PHY when open the interface */
-	ret = fec_enet_mii_probe(ndev);
-	if (ret)
-		goto err_enet_mii_probe;
-
 	/* Call phy_reset_after_clk_enable() again if it failed during
 	 * phy_reset_after_clk_enable() before because the PHY wasn't probed.
 	 */
 	if (reset_again)
-		phy_reset_after_clk_enable(ndev->phydev);
+		fec_enet_phy_reset_after_clk_enable(ndev);
+
+	/* Probe and connect to PHY when open the interface */
+	ret = fec_enet_mii_probe(ndev);
+	if (ret)
+		goto err_enet_mii_probe;
 
 	if (fep->quirks & FEC_QUIRK_ERR006687)
 		imx6q_cpuidle_fec_irqs_used();
@@ -3074,29 +3208,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/**
- * fec_poll_controller - FEC Poll controller function
- * @dev: The FEC network adapter
- *
- * Polled functionality used by netconsole and others in non interrupt mode
- *
- */
-static void fec_poll_controller(struct net_device *dev)
-{
-	int i;
-	struct fec_enet_private *fep = netdev_priv(dev);
-
-	for (i = 0; i < FEC_IRQ_NUM; i++) {
-		if (fep->irq[i] > 0) {
-			disable_irq(fep->irq[i]);
-			fec_enet_interrupt(fep->irq[i], dev);
-			enable_irq(fep->irq[i]);
-		}
-	}
-}
-#endif
-
 static inline void fec_enet_set_netdev_features(struct net_device *netdev,
 	netdev_features_t features)
 {
@@ -3145,9 +3256,6 @@
 	.ndo_tx_timeout		= fec_timeout,
 	.ndo_set_mac_address	= fec_set_mac_address,
 	.ndo_do_ioctl		= fec_enet_ioctl,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= fec_poll_controller,
-#endif
 	.ndo_set_features	= fec_set_features,
 };
 
@@ -3191,7 +3299,9 @@
 		return ret;
 	}
 
-	fec_enet_alloc_queue(ndev);
+	ret = fec_enet_alloc_queue(ndev);
+	if (ret)
+		return ret;
 
 	bd_size = (fep->total_tx_ring_size + fep->total_rx_ring_size) * dsize;
 
@@ -3199,7 +3309,8 @@
 	cbd_base = dmam_alloc_coherent(&fep->pdev->dev, bd_size, &bd_dma,
 				       GFP_KERNEL);
 	if (!cbd_base) {
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto free_queue_mem;
 	}
 
 	/* Get the Ethernet address */
@@ -3277,6 +3388,18 @@
 		fec_enet_update_ethtool_stats(ndev);
 
 	return 0;
+
+free_queue_mem:
+	fec_enet_free_queue(ndev);
+	return ret;
+}
+
+static void fec_enet_deinit(struct net_device *ndev)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+
+	netif_napi_del(&fep->napi);
+	fec_enet_free_queue(ndev);
 }
 
 #ifdef CONFIG_OF
@@ -3389,6 +3512,37 @@
 	return irq_cnt;
 }
 
+static int fec_enet_init_stop_mode(struct fec_enet_private *fep,
+				   struct fec_devinfo *dev_info,
+				   struct device_node *np)
+{
+	struct device_node *gpr_np;
+	int ret = 0;
+
+	if (!dev_info)
+		return 0;
+
+	gpr_np = of_parse_phandle(np, "gpr", 0);
+	if (!gpr_np)
+		return 0;
+
+	fep->stop_gpr.gpr = syscon_node_to_regmap(gpr_np);
+	if (IS_ERR(fep->stop_gpr.gpr)) {
+		dev_err(&fep->pdev->dev, "could not find gpr regmap\n");
+		ret = PTR_ERR(fep->stop_gpr.gpr);
+		fep->stop_gpr.gpr = NULL;
+		goto out;
+	}
+
+	fep->stop_gpr.reg = dev_info->stop_gpr_reg;
+	fep->stop_gpr.bit = dev_info->stop_gpr_bit;
+
+out:
+	of_node_put(gpr_np);
+
+	return ret;
+}
+
 static int
 fec_probe(struct platform_device *pdev)
 {
@@ -3403,6 +3557,7 @@
 	int num_rx_qs;
 	char irq_name[8];
 	int irq_cnt;
+	struct fec_devinfo *dev_info;
 
 	fec_enet_get_queue_num(pdev, &num_tx_qs, &num_rx_qs);
 
@@ -3420,7 +3575,9 @@
 	of_id = of_match_device(fec_dt_ids, &pdev->dev);
 	if (of_id)
 		pdev->id_entry = of_id->data;
-	fep->quirks = pdev->id_entry->driver_data;
+	dev_info = (struct fec_devinfo *)pdev->id_entry->driver_data;
+	if (dev_info)
+		fep->quirks = dev_info->quirks;
 
 	fep->netdev = ndev;
 	fep->num_rx_queues = num_rx_qs;
@@ -3454,6 +3611,10 @@
 	if (of_get_property(np, "fsl,magic-packet", NULL))
 		fep->wol_flag |= FEC_WOL_HAS_MAGIC_PACKET;
 
+	ret = fec_enet_init_stop_mode(fep, dev_info, np);
+	if (ret)
+		goto failed_stop_mode;
+
 	phy_node = of_parse_phandle(np, "phy-handle", 0);
 	if (!phy_node && of_phy_is_fixed_link(np)) {
 		ret = of_phy_register_fixed_link(np);
@@ -3605,13 +3766,14 @@
 	fec_enet_mii_remove(fep);
 failed_mii_init:
 failed_irq:
+	fec_enet_deinit(ndev);
 failed_init:
 	fec_ptp_stop(pdev);
-	if (fep->reg_phy)
-		regulator_disable(fep->reg_phy);
 failed_reset:
 	pm_runtime_put_noidle(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
+	if (fep->reg_phy)
+		regulator_disable(fep->reg_phy);
 failed_regulator:
 	clk_disable_unprepare(fep->clk_ahb);
 failed_clk_ahb:
@@ -3622,6 +3784,7 @@
 	if (of_phy_is_fixed_link(np))
 		of_phy_deregister_fixed_link(np);
 	of_node_put(phy_node);
+failed_stop_mode:
 failed_phy:
 	dev_id--;
 failed_ioremap:
@@ -3640,7 +3803,9 @@
 
 	ret = pm_runtime_get_sync(&pdev->dev);
 	if (ret < 0)
-		return ret;
+		dev_err(&pdev->dev,
+			"Failed to resume device in remove callback (%pe)\n",
+			ERR_PTR(ret));
 
 	cancel_work_sync(&fep->tx_timeout_work);
 	fec_ptp_stop(pdev);
@@ -3652,13 +3817,19 @@
 	if (of_phy_is_fixed_link(np))
 		of_phy_deregister_fixed_link(np);
 	of_node_put(fep->phy_node);
-	free_netdev(ndev);
 
-	clk_disable_unprepare(fep->clk_ahb);
-	clk_disable_unprepare(fep->clk_ipg);
+	/* After pm_runtime_get_sync() failed, the clks are still off, so skip
+	 * disabling them again.
+	 */
+	if (ret >= 0) {
+		clk_disable_unprepare(fep->clk_ahb);
+		clk_disable_unprepare(fep->clk_ipg);
+	}
 	pm_runtime_put_noidle(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 
+	fec_enet_deinit(ndev);
+	free_netdev(ndev);
 	return 0;
 }
 
@@ -3699,7 +3870,6 @@
 {
 	struct net_device *ndev = dev_get_drvdata(dev);
 	struct fec_enet_private *fep = netdev_priv(ndev);
-	struct fec_platform_data *pdata = fep->pdev->dev.platform_data;
 	int ret;
 	int val;
 
@@ -3717,8 +3887,8 @@
 			goto failed_clk;
 		}
 		if (fep->wol_flag & FEC_WOL_FLAG_ENABLE) {
-			if (pdata && pdata->sleep_mode_enable)
-				pdata->sleep_mode_enable(false);
+			fec_enet_stop_mode(fep, false);
+
 			val = readl(fep->hwp + FEC_ECNTRL);
 			val &= ~(FEC_ECR_MAGICEN | FEC_ECR_SLEEP);
 			writel(val, fep->hwp + FEC_ECNTRL);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/fec_mpc52xx_phy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/fec_mpc52xx_phy.c
@@ -92,7 +92,7 @@
 		goto out_free;
 	}
 
-	snprintf(bus->id, MII_BUS_ID_SIZE, "%x", res.start);
+	snprintf(bus->id, MII_BUS_ID_SIZE, "%pa", &res.start);
 	bus->priv = priv;
 
 	bus->parent = dev;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/fec_ptp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/fec_ptp.c
@@ -108,14 +108,13 @@
 		return -EINVAL;
 	}
 
-	if (fep->pps_enable == enable)
-		return 0;
-
-	fep->pps_channel = DEFAULT_PPS_CHANNEL;
-	fep->reload_period = PPS_OUPUT_RELOAD_PERIOD;
-
 	spin_lock_irqsave(&fep->tmreg_lock, flags);
 
+	if (fep->pps_enable == enable) {
+		spin_unlock_irqrestore(&fep->tmreg_lock, flags);
+		return 0;
+	}
+
 	if (enable) {
 		/* clear capture or output compare interrupt status if have.
 		 */
@@ -141,11 +140,7 @@
 		 * NSEC_PER_SEC - ts.tv_nsec. Add the remaining nanoseconds
 		 * to current timer would be next second.
 		 */
-		tempval = readl(fep->hwp + FEC_ATIME_CTRL);
-		tempval |= FEC_T_CTRL_CAPTURE;
-		writel(tempval, fep->hwp + FEC_ATIME_CTRL);
-
-		tempval = readl(fep->hwp + FEC_ATIME);
+		tempval = fep->cc.read(&fep->cc);
 		/* Convert the ptp local counter to 1588 timestamp */
 		ns = timecounter_cyc2time(&fep->tc, tempval);
 		ts = ns_to_timespec64(ns);
@@ -220,15 +215,13 @@
 {
 	struct fec_enet_private *fep =
 		container_of(cc, struct fec_enet_private, cc);
-	const struct platform_device_id *id_entry =
-		platform_get_device_id(fep->pdev);
 	u32 tempval;
 
 	tempval = readl(fep->hwp + FEC_ATIME_CTRL);
 	tempval |= FEC_T_CTRL_CAPTURE;
 	writel(tempval, fep->hwp + FEC_ATIME_CTRL);
 
-	if (id_entry->driver_data & FEC_QUIRK_BUG_CAPTURE)
+	if (fep->quirks & FEC_QUIRK_BUG_CAPTURE)
 		udelay(1);
 
 	return readl(fep->hwp + FEC_ATIME);
@@ -382,9 +375,16 @@
 	u64 ns;
 	unsigned long flags;
 
+	mutex_lock(&adapter->ptp_clk_mutex);
+	/* Check the ptp clock */
+	if (!adapter->ptp_clk_on) {
+		mutex_unlock(&adapter->ptp_clk_mutex);
+		return -EINVAL;
+	}
 	spin_lock_irqsave(&adapter->tmreg_lock, flags);
 	ns = timecounter_read(&adapter->tc);
 	spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
+	mutex_unlock(&adapter->ptp_clk_mutex);
 
 	*ts = ns_to_timespec64(ns);
 
@@ -445,6 +445,9 @@
 	int ret = 0;
 
 	if (rq->type == PTP_CLK_REQ_PPS) {
+		fep->pps_channel = DEFAULT_PPS_CHANNEL;
+		fep->reload_period = PPS_OUPUT_RELOAD_PERIOD;
+
 		ret = fec_ptp_enable_pps(fep, on);
 
 		return ret;
@@ -592,6 +595,10 @@
 	fep->ptp_caps.enable = fec_ptp_enable;
 
 	fep->cycle_speed = clk_get_rate(fep->clk_ptp);
+	if (!fep->cycle_speed) {
+		fep->cycle_speed = NSEC_PER_SEC;
+		dev_err(&fep->pdev->dev, "clk_ptp clock rate is zero\n");
+	}
 	fep->ptp_inc = NSEC_PER_SEC / fep->cycle_speed;
 
 	spin_lock_init(&fep->tmreg_lock);
@@ -628,6 +635,9 @@
 	struct net_device *ndev = platform_get_drvdata(pdev);
 	struct fec_enet_private *fep = netdev_priv(ndev);
 
+	if (fep->pps_enable)
+		fec_ptp_enable_pps(fep, 0);
+
 	cancel_delayed_work_sync(&fep->time_keep);
 	if (fep->ptp_clock)
 		ptp_clock_unregister(fep->ptp_clock);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/fman/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/fman/Kconfig
@@ -8,3 +8,31 @@
 	help
 		Freescale Data-Path Acceleration Architecture Frame Manager
 		(FMan) support
+
+config DPAA_ERRATUM_A050385
+	bool
+	depends on ARM64 && FSL_DPAA
+	default y
+	help
+		DPAA FMan erratum A050385 software workaround implementation:
+		align buffers, data start, SG fragment length to avoid FMan DMA
+		splits.
+		FMAN DMA read or writes under heavy traffic load may cause FMAN
+		internal resource leak thus stopping further packet processing.
+		The FMAN internal queue can overflow when FMAN splits single
+		read or write transactions into multiple smaller transactions
+		such that more than 17 AXI transactions are in flight from FMAN
+		to interconnect. When the FMAN internal queue overflows, it can
+		stall further packet processing. The issue can occur with any
+		one of the following three conditions:
+		1. FMAN AXI transaction crosses 4K address boundary (Errata
+		A010022)
+		2. FMAN DMA address for an AXI transaction is not 16 byte
+		aligned, i.e. the last 4 bits of an address are non-zero
+		3. Scatter Gather (SG) frames have more than one SG buffer in
+		the SG list and any one of the buffers, except the last
+		buffer in the SG list has data size that is not a multiple
+		of 16 bytes, i.e., other than 16, 32, 48, 64, etc.
+		With any one of the above three conditions present, there is
+		likelihood of stalled FMAN packet processing, especially under
+		stress with multiple ports injecting line-rate traffic.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/fman/fman.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/fman/fman.c
@@ -1,5 +1,6 @@
 /*
  * Copyright 2008-2015 Freescale Semiconductor Inc.
+ * Copyright 2020 NXP
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -566,6 +567,10 @@
 	u32 qmi_def_tnums_thresh;
 };
 
+#ifdef CONFIG_DPAA_ERRATUM_A050385
+static bool fman_has_err_a050385;
+#endif
+
 static irqreturn_t fman_exceptions(struct fman *fman,
 				   enum fman_exceptions exception)
 {
@@ -1391,8 +1396,7 @@
 {
 	struct fman_fpm_regs __iomem *fpm_rg = fman->fpm_regs;
 	u16 fm_clk_freq = fman->state->fm_clk_freq;
-	u32 tmp, intgr, ts_freq;
-	u64 frac;
+	u32 tmp, intgr, ts_freq, frac;
 
 	ts_freq = (u32)(1 << fman->state->count1_micro_bit);
 	/* configure timestamp so that bit 8 will count 1 microsecond
@@ -2514,6 +2518,14 @@
 }
 EXPORT_SYMBOL(fman_bind);
 
+#ifdef CONFIG_DPAA_ERRATUM_A050385
+bool fman_has_errata_a050385(void)
+{
+	return fman_has_err_a050385;
+}
+EXPORT_SYMBOL(fman_has_errata_a050385);
+#endif
+
 static irqreturn_t fman_err_irq(int irq, void *handle)
 {
 	struct fman *fman = (struct fman *)handle;
@@ -2841,6 +2853,11 @@
 		goto fman_free;
 	}
 
+#ifdef CONFIG_DPAA_ERRATUM_A050385
+	fman_has_err_a050385 =
+		of_property_read_bool(fm_node, "fsl,erratum-a050385");
+#endif
+
 	return fman;
 
 fman_node_put:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/fman/fman.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/fman/fman.h
@@ -1,5 +1,6 @@
 /*
  * Copyright 2008-2015 Freescale Semiconductor Inc.
+ * Copyright 2020 NXP
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -398,6 +399,10 @@
 
 int fman_get_rx_extra_headroom(void);
 
+#ifdef CONFIG_DPAA_ERRATUM_A050385
+bool fman_has_errata_a050385(void);
+#endif
+
 struct fman *fman_bind(struct device *dev);
 
 #endif /* __FM_H */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/fman/fman_dtsec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/fman/fman_dtsec.c
@@ -1205,7 +1205,7 @@
 		list_for_each(pos,
 			      &dtsec->multicast_addr_hash->lsts[bucket]) {
 			hash_entry = ETH_HASH_ENTRY_OBJ(pos);
-			if (hash_entry->addr == addr) {
+			if (hash_entry && hash_entry->addr == addr) {
 				list_del_init(&hash_entry->node);
 				kfree(hash_entry);
 				break;
@@ -1218,7 +1218,7 @@
 		list_for_each(pos,
 			      &dtsec->unicast_addr_hash->lsts[bucket]) {
 			hash_entry = ETH_HASH_ENTRY_OBJ(pos);
-			if (hash_entry->addr == addr) {
+			if (hash_entry && hash_entry->addr == addr) {
 				list_del_init(&hash_entry->node);
 				kfree(hash_entry);
 				break;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/fman/fman_mac.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/fman/fman_mac.h
@@ -252,7 +252,7 @@
 	struct eth_hash_t *hash;
 
 	/* Allocate address hash table */
-	hash = kmalloc_array(size, sizeof(struct eth_hash_t *), GFP_KERNEL);
+	hash = kmalloc(sizeof(*hash), GFP_KERNEL);
 	if (!hash)
 		return NULL;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/fman/fman_memac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/fman/fman_memac.c
@@ -110,7 +110,7 @@
 /* Interface Mode Register (IF_MODE) */
 
 #define IF_MODE_MASK		0x00000003 /* 30-31 Mask on i/f mode bits */
-#define IF_MODE_XGMII		0x00000000 /* 30-31 XGMII (10G) interface */
+#define IF_MODE_10G		0x00000000 /* 30-31 10G interface */
 #define IF_MODE_GMII		0x00000002 /* 30-31 GMII (1G) interface */
 #define IF_MODE_RGMII		0x00000004
 #define IF_MODE_RGMII_AUTO	0x00008000
@@ -440,7 +440,7 @@
 	tmp = 0;
 	switch (phy_if) {
 	case PHY_INTERFACE_MODE_XGMII:
-		tmp |= IF_MODE_XGMII;
+		tmp |= IF_MODE_10G;
 		break;
 	default:
 		tmp |= IF_MODE_GMII;
@@ -856,7 +856,6 @@
 
 	tmp = ioread32be(&regs->command_config);
 	tmp &= ~CMD_CFG_PFC_MODE;
-	priority = 0;
 
 	iowrite32be(tmp, &regs->command_config);
 
@@ -986,7 +985,7 @@
 
 	list_for_each(pos, &memac->multicast_addr_hash->lsts[hash]) {
 		hash_entry = ETH_HASH_ENTRY_OBJ(pos);
-		if (hash_entry->addr == addr) {
+		if (hash_entry && hash_entry->addr == addr) {
 			list_del_init(&hash_entry->node);
 			kfree(hash_entry);
 			break;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/fman/fman_port.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/fman/fman_port.c
@@ -1756,6 +1756,7 @@
 	struct fman_port *port;
 	struct fman *fman;
 	struct device_node *fm_node, *port_node;
+	struct platform_device *fm_pdev;
 	struct resource res;
 	struct resource *dev_res;
 	u32 val;
@@ -1780,19 +1781,25 @@
 		goto return_err;
 	}
 
-	fman = dev_get_drvdata(&of_find_device_by_node(fm_node)->dev);
+	fm_pdev = of_find_device_by_node(fm_node);
 	of_node_put(fm_node);
-	if (!fman) {
+	if (!fm_pdev) {
 		err = -EINVAL;
 		goto return_err;
 	}
 
+	fman = dev_get_drvdata(&fm_pdev->dev);
+	if (!fman) {
+		err = -EINVAL;
+		goto put_device;
+	}
+
 	err = of_property_read_u32(port_node, "cell-index", &val);
 	if (err) {
 		dev_err(port->dev, "%s: reading cell-index for %pOF failed\n",
 			__func__, port_node);
 		err = -EINVAL;
-		goto return_err;
+		goto put_device;
 	}
 	port_id = (u8)val;
 	port->dts_params.id = port_id;
@@ -1826,7 +1833,7 @@
 	}  else {
 		dev_err(port->dev, "%s: Illegal port type\n", __func__);
 		err = -EINVAL;
-		goto return_err;
+		goto put_device;
 	}
 
 	port->dts_params.type = port_type;
@@ -1840,7 +1847,7 @@
 			dev_err(port->dev, "%s: incorrect qman-channel-id\n",
 				__func__);
 			err = -EINVAL;
-			goto return_err;
+			goto put_device;
 		}
 		port->dts_params.qman_channel_id = qman_channel_id;
 	}
@@ -1850,7 +1857,7 @@
 		dev_err(port->dev, "%s: of_address_to_resource() failed\n",
 			__func__);
 		err = -ENOMEM;
-		goto return_err;
+		goto put_device;
 	}
 
 	port->dts_params.fman = fman;
@@ -1875,6 +1882,8 @@
 
 	return 0;
 
+put_device:
+	put_device(&fm_pdev->dev);
 return_err:
 	of_node_put(port_node);
 free_port:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/fman/fman_tgec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/fman/fman_tgec.c
@@ -630,7 +630,7 @@
 
 	list_for_each(pos, &tgec->multicast_addr_hash->lsts[hash]) {
 		hash_entry = ETH_HASH_ENTRY_OBJ(pos);
-		if (hash_entry->addr == addr) {
+		if (hash_entry && hash_entry->addr == addr) {
 			list_del_init(&hash_entry->node);
 			kfree(hash_entry);
 			break;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/fman/mac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/fman/mac.c
@@ -94,14 +94,17 @@
 		__func__, ex);
 }
 
-static void set_fman_mac_params(struct mac_device *mac_dev,
-				struct fman_mac_params *params)
+static int set_fman_mac_params(struct mac_device *mac_dev,
+			       struct fman_mac_params *params)
 {
 	struct mac_priv_s *priv = mac_dev->priv;
 
 	params->base_addr = (typeof(params->base_addr))
 		devm_ioremap(priv->dev, mac_dev->res->start,
 			     resource_size(mac_dev->res));
+	if (!params->base_addr)
+		return -ENOMEM;
+
 	memcpy(&params->addr, mac_dev->addr, sizeof(mac_dev->addr));
 	params->max_speed	= priv->max_speed;
 	params->phy_if		= mac_dev->phy_if;
@@ -112,6 +115,8 @@
 	params->event_cb	= mac_exception;
 	params->dev_id		= mac_dev;
 	params->internal_phy_node = priv->internal_phy_node;
+
+	return 0;
 }
 
 static int tgec_initialization(struct mac_device *mac_dev)
@@ -123,7 +128,9 @@
 
 	priv = mac_dev->priv;
 
-	set_fman_mac_params(mac_dev, &params);
+	err = set_fman_mac_params(mac_dev, &params);
+	if (err)
+		goto _return;
 
 	mac_dev->fman_mac = tgec_config(&params);
 	if (!mac_dev->fman_mac) {
@@ -169,7 +176,9 @@
 
 	priv = mac_dev->priv;
 
-	set_fman_mac_params(mac_dev, &params);
+	err = set_fman_mac_params(mac_dev, &params);
+	if (err)
+		goto _return;
 
 	mac_dev->fman_mac = dtsec_config(&params);
 	if (!mac_dev->fman_mac) {
@@ -218,7 +227,9 @@
 
 	priv = mac_dev->priv;
 
-	set_fman_mac_params(mac_dev, &params);
+	err = set_fman_mac_params(mac_dev, &params);
+	if (err)
+		goto _return;
 
 	if (priv->max_speed == SPEED_10000)
 		params.phy_if = PHY_INTERFACE_MODE_XGMII;
@@ -874,12 +885,21 @@
 	return err;
 }
 
+static int mac_remove(struct platform_device *pdev)
+{
+	struct mac_device *mac_dev = platform_get_drvdata(pdev);
+
+	platform_device_unregister(mac_dev->priv->eth_dev);
+	return 0;
+}
+
 static struct platform_driver mac_driver = {
 	.driver = {
 		.name		= KBUILD_MODNAME,
 		.of_match_table	= mac_match,
 	},
 	.probe		= mac_probe,
+	.remove		= mac_remove,
 };
 
 builtin_platform_driver(mac_driver);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/fs_enet/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/fs_enet/Kconfig
@@ -1,9 +1,9 @@
 # SPDX-License-Identifier: GPL-2.0-only
 config FS_ENET
-       tristate "Freescale Ethernet Driver"
-       depends on NET_VENDOR_FREESCALE && (CPM1 || CPM2 || PPC_MPC512x)
-       select MII
-       select PHYLIB
+	tristate "Freescale Ethernet Driver"
+	depends on NET_VENDOR_FREESCALE && (CPM1 || CPM2 || PPC_MPC512x)
+	select MII
+	select PHYLIB
 
 config FS_ENET_MPC5121_FEC
 	def_bool y if (FS_ENET && PPC_MPC512x)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/fs_enet/mac-fec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/fs_enet/mac-fec.c
@@ -98,7 +98,7 @@
 		return -EINVAL;
 
 	fep->fec.fecp = of_iomap(ofdev->dev.of_node, 0);
-	if (!fep->fcc.fccp)
+	if (!fep->fec.fecp)
 		return -EINVAL;
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c
@@ -126,7 +126,7 @@
 	 * we get is an int, and the odds of multiple bitbang mdio buses
 	 * is low enough that it's not worth going too crazy.
 	 */
-	snprintf(bus->id, MII_BUS_ID_SIZE, "%x", res.start);
+	snprintf(bus->id, MII_BUS_ID_SIZE, "%pa", &res.start);
 
 	data = of_get_property(np, "fsl,mdio-pin", &len);
 	if (!data || len != 4)
@@ -223,3 +223,4 @@
 };
 
 module_platform_driver(fs_enet_bb_mdio_driver);
+MODULE_LICENSE("GPL");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/fs_enet/mii-fec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/fs_enet/mii-fec.c
@@ -224,3 +224,4 @@
 };
 
 module_platform_driver(fs_enet_fec_mdio_driver);
+MODULE_LICENSE("GPL");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/gianfar.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/gianfar.c
@@ -366,7 +366,11 @@
 
 static int gfar_set_mac_addr(struct net_device *dev, void *p)
 {
-	eth_mac_addr(dev, p);
+	int ret;
+
+	ret = eth_mac_addr(dev, p);
+	if (ret)
+		return ret;
 
 	gfar_set_mac_for_addr(dev, 0, dev->dev_addr);
 
@@ -751,8 +755,10 @@
 				continue;
 
 			err = gfar_parse_group(child, priv, model);
-			if (err)
+			if (err) {
+				of_node_put(child);
 				goto err_grp_init;
+			}
 		}
 	} else { /* SQ_SG_MODE */
 		err = gfar_parse_group(np, priv, model);
@@ -1824,20 +1830,12 @@
 		fcb_len = GMAC_FCB_LEN + GMAC_TXPAL_LEN;
 
 	/* make space for additional header when fcb is needed */
-	if (fcb_len && unlikely(skb_headroom(skb) < fcb_len)) {
-		struct sk_buff *skb_new;
-
-		skb_new = skb_realloc_headroom(skb, fcb_len);
-		if (!skb_new) {
+	if (fcb_len) {
+		if (unlikely(skb_cow_head(skb, fcb_len))) {
 			dev->stats.tx_errors++;
 			dev_kfree_skb_any(skb);
 			return NETDEV_TX_OK;
 		}
-
-		if (skb->sk)
-			skb_set_owner_w(skb_new, skb->sk);
-		dev_consume_skb_any(skb);
-		skb = skb_new;
 	}
 
 	/* total number of fragments in the SKB */
@@ -2204,13 +2202,17 @@
 	skb_dirtytx = tx_queue->skb_dirtytx;
 
 	while ((skb = tx_queue->tx_skbuff[skb_dirtytx])) {
+		bool do_tstamp;
+
+		do_tstamp = (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
+			    priv->hwts_tx_en;
 
 		frags = skb_shinfo(skb)->nr_frags;
 
 		/* When time stamping, one additional TxBD must be freed.
 		 * Also, we need to dma_unmap_single() the TxPAL.
 		 */
-		if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS))
+		if (unlikely(do_tstamp))
 			nr_txbds = frags + 2;
 		else
 			nr_txbds = frags + 1;
@@ -2224,7 +2226,7 @@
 		    (lstatus & BD_LENGTH_MASK))
 			break;
 
-		if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) {
+		if (unlikely(do_tstamp)) {
 			next = next_txbd(bdp, base, tx_ring_size);
 			buflen = be16_to_cpu(next->length) +
 				 GMAC_FCB_LEN + GMAC_TXPAL_LEN;
@@ -2234,7 +2236,7 @@
 		dma_unmap_single(priv->dev, be32_to_cpu(bdp->bufPtr),
 				 buflen, DMA_TO_DEVICE);
 
-		if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) {
+		if (unlikely(do_tstamp)) {
 			struct skb_shared_hwtstamps shhwtstamps;
 			u64 *ns = (u64 *)(((uintptr_t)skb->data + 0x10) &
 					  ~0x7UL);
@@ -2390,6 +2392,10 @@
 		if (lstatus & BD_LFLAG(RXBD_LAST))
 			size -= skb->len;
 
+		WARN(size < 0, "gianfar: rx fragment size underflow");
+		if (size < 0)
+			return false;
+
 		skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page,
 				rxb->page_offset + RXBUF_ALIGNMENT,
 				size, GFAR_RXB_TRUESIZE);
@@ -2552,6 +2558,17 @@
 		if (lstatus & BD_LFLAG(RXBD_EMPTY))
 			break;
 
+		/* lost RXBD_LAST descriptor due to overrun */
+		if (skb &&
+		    (lstatus & BD_LFLAG(RXBD_FIRST))) {
+			/* discard faulty buffer */
+			dev_kfree_skb(skb);
+			skb = NULL;
+			rx_queue->stats.rx_dropped++;
+
+			/* can continue normally */
+		}
+
 		/* order rx buffer descriptor reads */
 		rmb();
 
@@ -3371,7 +3388,7 @@
 
 	if (dev->features & NETIF_F_IP_CSUM ||
 	    priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER)
-		dev->needed_headroom = GMAC_FCB_LEN;
+		dev->needed_headroom = GMAC_FCB_LEN + GMAC_TXPAL_LEN;
 
 	/* Initializing some of the rx/tx queue level parameters */
 	for (i = 0; i < priv->num_tx_queues; i++) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/gianfar_ethtool.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/gianfar_ethtool.c
@@ -1489,6 +1489,7 @@
 	ptp_node = of_find_compatible_node(NULL, NULL, "fsl,etsec-ptp");
 	if (ptp_node) {
 		ptp_dev = of_find_device_by_node(ptp_node);
+		of_node_put(ptp_node);
 		if (ptp_dev)
 			ptp = platform_get_drvdata(ptp_dev);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/ucc_geth.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/ucc_geth.c
@@ -42,6 +42,7 @@
 #include <soc/fsl/qe/ucc.h>
 #include <soc/fsl/qe/ucc_fast.h>
 #include <asm/machdep.h>
+#include <net/sch_generic.h>
 
 #include "ucc_geth.h"
 
@@ -1548,11 +1549,8 @@
 
 static void ugeth_quiesce(struct ucc_geth_private *ugeth)
 {
-	/* Prevent any further xmits, plus detach the device. */
-	netif_device_detach(ugeth->ndev);
-
-	/* Wait for any current xmits to finish. */
-	netif_tx_disable(ugeth->ndev);
+	/* Prevent any further xmits */
+	netif_tx_stop_all_queues(ugeth->ndev);
 
 	/* Disable the interrupt to avoid NAPI rescheduling. */
 	disable_irq(ugeth->ug_info->uf_info.irq);
@@ -1565,7 +1563,10 @@
 {
 	napi_enable(&ugeth->napi);
 	enable_irq(ugeth->ug_info->uf_info.irq);
-	netif_device_attach(ugeth->ndev);
+
+	/* allow to xmit again  */
+	netif_tx_wake_all_queues(ugeth->ndev);
+	__netdev_watchdog_up(ugeth->ndev);
 }
 
 /* Called every time the controller might need to be made
@@ -3889,6 +3890,7 @@
 	INIT_WORK(&ugeth->timeout_work, ucc_geth_timeout_work);
 	netif_napi_add(dev, &ugeth->napi, ucc_geth_poll, 64);
 	dev->mtu = 1500;
+	dev->max_mtu = 1518;
 
 	ugeth->msg_enable = netif_msg_init(debug.msg_enable, UGETH_MSG_DEFAULT);
 	ugeth->phy_interface = phy_interface;
@@ -3934,12 +3936,12 @@
 	struct device_node *np = ofdev->dev.of_node;
 
 	unregister_netdev(dev);
-	free_netdev(dev);
 	ucc_geth_memclean(ugeth);
 	if (of_phy_is_fixed_link(np))
 		of_phy_deregister_fixed_link(np);
 	of_node_put(ugeth->ug_info->tbi_node);
 	of_node_put(ugeth->ug_info->phy_node);
+	free_netdev(dev);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/ucc_geth.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/ucc_geth.h
@@ -576,7 +576,14 @@
 	u32 vtagtable[0x8];	/* 8 4-byte VLAN tags */
 	u32 tqptr;		/* a base pointer to the Tx Queues Memory
 				   Region */
-	u8 res2[0x80 - 0x74];
+	u8 res2[0x78 - 0x74];
+	u64 snums_en;
+	u32 l2l3baseptr;	/* top byte consists of a few other bit fields */
+
+	u16 mtu[8];
+	u8 res3[0xa8 - 0x94];
+	u32 wrrtablebase;	/* top byte is reserved */
+	u8 res4[0xc0 - 0xac];
 } __packed;
 
 /* structure representing Extended Filtering Global Parameters in PRAM */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/freescale/xgmac_mdio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/freescale/xgmac_mdio.c
@@ -49,6 +49,7 @@
 struct mdio_fsl_priv {
 	struct	tgec_mdio_controller __iomem *mdio_base;
 	bool	is_little_endian;
+	bool	has_a011043;
 };
 
 static u32 xgmac_read32(void __iomem *regs,
@@ -226,7 +227,8 @@
 		return ret;
 
 	/* Return all Fs if nothing was there */
-	if (xgmac_read32(&regs->mdio_stat, endian) & MDIO_STAT_RD_ER) {
+	if ((xgmac_read32(&regs->mdio_stat, endian) & MDIO_STAT_RD_ER) &&
+	    !priv->has_a011043) {
 		dev_err(&bus->dev,
 			"Error while reading PHY%d reg at %d.%hhu\n",
 			phy_id, dev_addr, regnum);
@@ -274,6 +276,9 @@
 	priv->is_little_endian = of_property_read_bool(pdev->dev.of_node,
 						       "little-endian");
 
+	priv->has_a011043 = of_property_read_bool(pdev->dev.of_node,
+						  "fsl,erratum-a011043");
+
 	ret = of_mdiobus_register(bus, np);
 	if (ret) {
 		dev_err(&pdev->dev, "cannot register MDIO bus\n");
@@ -296,9 +301,10 @@
 static int xgmac_mdio_remove(struct platform_device *pdev)
 {
 	struct mii_bus *bus = platform_get_drvdata(pdev);
+	struct mdio_fsl_priv *priv = bus->priv;
 
 	mdiobus_unregister(bus);
-	iounmap(bus->priv);
+	iounmap(priv->mdio_base);
 	mdiobus_free(bus);
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/fujitsu/fmvj18x_cs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/fujitsu/fmvj18x_cs.c
@@ -548,8 +548,8 @@
 
     base = ioremap(link->resource[2]->start, resource_size(link->resource[2]));
     if (!base) {
-	    pcmcia_release_window(link, link->resource[2]);
-	    return -ENOMEM;
+	pcmcia_release_window(link, link->resource[2]);
+	return -1;
     }
 
     pcmcia_map_mem_page(link, link->resource[2], 0);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/google/gve/gve.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/google/gve/gve.h
@@ -391,7 +391,7 @@
 				    gve_num_tx_qpls(priv));
 
 	/* we are out of rx qpls */
-	if (id == priv->qpl_cfg.qpl_map_size)
+	if (id == gve_num_tx_qpls(priv) + gve_num_rx_qpls(priv))
 		return NULL;
 
 	set_bit(id, priv->qpl_cfg.qpl_id_map);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/google/gve/gve_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/google/gve/gve_main.c
@@ -30,6 +30,7 @@
 {
 	struct gve_priv *priv = netdev_priv(dev);
 	unsigned int start;
+	u64 packets, bytes;
 	int ring;
 
 	if (priv->rx) {
@@ -37,10 +38,12 @@
 			do {
 				start =
 				  u64_stats_fetch_begin(&priv->rx[ring].statss);
-				s->rx_packets += priv->rx[ring].rpackets;
-				s->rx_bytes += priv->rx[ring].rbytes;
+				packets = priv->rx[ring].rpackets;
+				bytes = priv->rx[ring].rbytes;
 			} while (u64_stats_fetch_retry(&priv->rx[ring].statss,
 						       start));
+			s->rx_packets += packets;
+			s->rx_bytes += bytes;
 		}
 	}
 	if (priv->tx) {
@@ -48,10 +51,12 @@
 			do {
 				start =
 				  u64_stats_fetch_begin(&priv->tx[ring].statss);
-				s->tx_packets += priv->tx[ring].pkt_done;
-				s->tx_bytes += priv->tx[ring].bytes_done;
+				packets = priv->tx[ring].pkt_done;
+				bytes = priv->tx[ring].bytes_done;
 			} while (u64_stats_fetch_retry(&priv->tx[ring].statss,
 						       start));
+			s->tx_packets += packets;
+			s->tx_bytes += bytes;
 		}
 	}
 }
@@ -121,7 +126,7 @@
 	/* Double check we have no extra work.
 	 * Ensure unmask synchronizes with checking for work.
 	 */
-	dma_rmb();
+	mb();
 	if (block->tx)
 		reschedule |= gve_tx_poll(block, -1);
 	if (block->rx)
@@ -161,6 +166,7 @@
 		int vecs_left = new_num_ntfy_blks % 2;
 
 		priv->num_ntfy_blks = new_num_ntfy_blks;
+		priv->mgmt_msix_idx = priv->num_ntfy_blks;
 		priv->tx_cfg.max_queues = min_t(int, priv->tx_cfg.max_queues,
 						vecs_per_type);
 		priv->rx_cfg.max_queues = min_t(int, priv->rx_cfg.max_queues,
@@ -241,20 +247,22 @@
 {
 	int i;
 
-	/* Free the irqs */
-	for (i = 0; i < priv->num_ntfy_blks; i++) {
-		struct gve_notify_block *block = &priv->ntfy_blocks[i];
-		int msix_idx = i;
-
-		irq_set_affinity_hint(priv->msix_vectors[msix_idx].vector,
-				      NULL);
-		free_irq(priv->msix_vectors[msix_idx].vector, block);
+	if (priv->msix_vectors) {
+		/* Free the irqs */
+		for (i = 0; i < priv->num_ntfy_blks; i++) {
+			struct gve_notify_block *block = &priv->ntfy_blocks[i];
+			int msix_idx = i;
+
+			irq_set_affinity_hint(priv->msix_vectors[msix_idx].vector,
+					      NULL);
+			free_irq(priv->msix_vectors[msix_idx].vector, block);
+		}
+		free_irq(priv->msix_vectors[priv->mgmt_msix_idx].vector, priv);
 	}
 	dma_free_coherent(&priv->pdev->dev,
 			  priv->num_ntfy_blks * sizeof(*priv->ntfy_blocks),
 			  priv->ntfy_blocks, priv->ntfy_block_bus);
 	priv->ntfy_blocks = NULL;
-	free_irq(priv->msix_vectors[priv->mgmt_msix_idx].vector, priv);
 	pci_disable_msix(priv->pdev);
 	kvfree(priv->msix_vectors);
 	priv->msix_vectors = NULL;
@@ -544,7 +552,7 @@
 	}
 
 	qpl->id = id;
-	qpl->num_entries = pages;
+	qpl->num_entries = 0;
 	qpl->pages = kvzalloc(pages * sizeof(*qpl->pages), GFP_KERNEL);
 	/* caller handles clean up */
 	if (!qpl->pages)
@@ -562,6 +570,7 @@
 		/* caller handles clean up */
 		if (err)
 			return -ENOMEM;
+		qpl->num_entries++;
 	}
 	priv->num_registered_pages += pages;
 
@@ -1114,8 +1123,8 @@
 
 	gve_write_version(&reg_bar->driver_version);
 	/* Get max queues to alloc etherdev */
-	max_rx_queues = ioread32be(&reg_bar->max_tx_queues);
-	max_tx_queues = ioread32be(&reg_bar->max_rx_queues);
+	max_tx_queues = ioread32be(&reg_bar->max_tx_queues);
+	max_rx_queues = ioread32be(&reg_bar->max_rx_queues);
 	/* Alloc and setup the netdev and priv */
 	dev = alloc_etherdev_mqs(sizeof(*priv), max_tx_queues, max_rx_queues);
 	if (!dev) {
@@ -1166,13 +1175,16 @@
 
 	err = register_netdev(dev);
 	if (err)
-		goto abort_with_wq;
+		goto abort_with_gve_init;
 
 	dev_info(&pdev->dev, "GVE version %s\n", gve_version_str);
 	gve_clear_probe_in_progress(priv);
 	queue_work(priv->gve_wq, &priv->service_task);
 	return 0;
 
+abort_with_gve_init:
+	gve_teardown_priv_resources(priv);
+
 abort_with_wq:
 	destroy_workqueue(priv->gve_wq);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/google/gve/gve_rx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/google/gve/gve_rx.c
@@ -418,8 +418,6 @@
 	rx->cnt = cnt;
 	rx->fill_cnt += work_done;
 
-	/* restock desc ring slots */
-	dma_wmb();	/* Ensure descs are visible before ringing doorbell */
 	gve_rx_write_doorbell(priv, rx);
 	return gve_rx_work_pending(rx);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/google/gve/gve_tx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/google/gve/gve_tx.c
@@ -207,10 +207,12 @@
 		goto abort_with_info;
 
 	tx->tx_fifo.qpl = gve_assign_tx_qpl(priv);
+	if (!tx->tx_fifo.qpl)
+		goto abort_with_desc;
 
 	/* map Tx FIFO */
 	if (gve_tx_fifo_init(priv, &tx->tx_fifo))
-		goto abort_with_desc;
+		goto abort_with_qpl;
 
 	tx->q_resources =
 		dma_alloc_coherent(hdev,
@@ -229,6 +231,8 @@
 
 abort_with_fifo:
 	gve_tx_fifo_release(priv, &tx->tx_fifo);
+abort_with_qpl:
+	gve_unassign_qpl(priv, tx->tx_fifo.qpl->id);
 abort_with_desc:
 	dma_free_coherent(hdev, bytes, tx->desc, tx->bus);
 	tx->desc = NULL;
@@ -478,7 +482,7 @@
 	struct gve_tx_ring *tx;
 	int nsegs;
 
-	WARN(skb_get_queue_mapping(skb) > priv->tx_cfg.num_queues,
+	WARN(skb_get_queue_mapping(skb) >= priv->tx_cfg.num_queues,
 	     "skb queue index out of range");
 	tx = &priv->tx[skb_get_queue_mapping(skb)];
 	if (unlikely(gve_maybe_stop_tx(tx, skb))) {
@@ -487,10 +491,6 @@
 		 * may have added descriptors without ringing the doorbell.
 		 */
 
-		/* Ensure tx descs from a prior gve_tx are visible before
-		 * ringing doorbell.
-		 */
-		dma_wmb();
 		gve_tx_put_doorbell(priv, tx->q_resources, tx->req);
 		return NETDEV_TX_BUSY;
 	}
@@ -505,8 +505,6 @@
 	if (!netif_xmit_stopped(tx->netdev_txq) && netdev_xmit_more())
 		return NETDEV_TX_OK;
 
-	/* Ensure tx descs are visible before ringing doorbell */
-	dma_wmb();
 	gve_tx_put_doorbell(priv, tx->q_resources, tx->req);
 	return NETDEV_TX_OK;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/hisilicon/hip04_eth.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/hisilicon/hip04_eth.c
@@ -131,7 +131,7 @@
 /* buf unit size is cache_line_size, which is 64, so the shift is 6 */
 #define PPE_BUF_SIZE_SHIFT		6
 #define PPE_TX_BUF_HOLD			BIT(31)
-#define CACHE_LINE_MASK			0x3F
+#define SOC_CACHE_LINE_MASK		0x3F
 #else
 #define PPE_CFG_QOS_VMID_GRP_SHIFT	8
 #define PPE_CFG_RX_CTRL_ALIGN_SHIFT	11
@@ -531,8 +531,8 @@
 #if defined(CONFIG_HI13X1_GMAC)
 	desc->cfg = (__force u32)cpu_to_be32(TX_CLEAR_WB | TX_FINISH_CACHE_INV
 		| TX_RELEASE_TO_PPE | priv->port << TX_POOL_SHIFT);
-	desc->data_offset = (__force u32)cpu_to_be32(phys & CACHE_LINE_MASK);
-	desc->send_addr =  (__force u32)cpu_to_be32(phys & ~CACHE_LINE_MASK);
+	desc->data_offset = (__force u32)cpu_to_be32(phys & SOC_CACHE_LINE_MASK);
+	desc->send_addr =  (__force u32)cpu_to_be32(phys & ~SOC_CACHE_LINE_MASK);
 #else
 	desc->cfg = (__force u32)cpu_to_be32(TX_CLEAR_WB | TX_FINISH_CACHE_INV);
 	desc->send_addr = (__force u32)cpu_to_be32(phys);
@@ -543,9 +543,9 @@
 	skb_tx_timestamp(skb);
 
 	hip04_set_xmit_desc(priv, phys);
-	priv->tx_head = TX_NEXT(tx_head);
 	count++;
 	netdev_sent_queue(ndev, skb->len);
+	priv->tx_head = TX_NEXT(tx_head);
 
 	stats->tx_bytes += skb->len;
 	stats->tx_packets++;
@@ -955,6 +955,7 @@
 	priv->tx_coalesce_timer.function = tx_done;
 
 	priv->map = syscon_node_to_regmap(arg.np);
+	of_node_put(arg.np);
 	if (IS_ERR(priv->map)) {
 		dev_warn(d, "no syscon hisilicon,hip04-ppe\n");
 		ret = PTR_ERR(priv->map);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/hisilicon/hisi_femac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/hisilicon/hisi_femac.c
@@ -283,7 +283,7 @@
 		skb->protocol = eth_type_trans(skb, dev);
 		napi_gro_receive(&priv->napi, skb);
 		dev->stats.rx_packets++;
-		dev->stats.rx_bytes += skb->len;
+		dev->stats.rx_bytes += len;
 next:
 		pos = (pos + 1) % rxq->num;
 		if (rx_pkts_num >= limit)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/hisilicon/hix5hd2_gmac.c
@@ -550,7 +550,7 @@
 		skb->protocol = eth_type_trans(skb, dev);
 		napi_gro_receive(&priv->napi, skb);
 		dev->stats.rx_packets++;
-		dev->stats.rx_bytes += skb->len;
+		dev->stats.rx_bytes += len;
 next:
 		pos = dma_ring_incr(pos, RX_DESC_NUM);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/hisilicon/hns/hnae.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/hisilicon/hns/hnae.c
@@ -419,8 +419,10 @@
 	hdev->cls_dev.release = hnae_release;
 	(void)dev_set_name(&hdev->cls_dev, "hnae%d", hdev->id);
 	ret = device_register(&hdev->cls_dev);
-	if (ret)
+	if (ret) {
+		put_device(&hdev->cls_dev);
 		return ret;
+	}
 
 	__module_get(THIS_MODULE);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c
@@ -66,6 +66,27 @@
 	}
 }
 
+static u32 hns_mac_link_anti_shake(struct mac_driver *mac_ctrl_drv)
+{
+#define HNS_MAC_LINK_WAIT_TIME 5
+#define HNS_MAC_LINK_WAIT_CNT 40
+
+	u32 link_status = 0;
+	int i;
+
+	if (!mac_ctrl_drv->get_link_status)
+		return link_status;
+
+	for (i = 0; i < HNS_MAC_LINK_WAIT_CNT; i++) {
+		msleep(HNS_MAC_LINK_WAIT_TIME);
+		mac_ctrl_drv->get_link_status(mac_ctrl_drv, &link_status);
+		if (!link_status)
+			break;
+	}
+
+	return link_status;
+}
+
 void hns_mac_get_link_status(struct hns_mac_cb *mac_cb, u32 *link_status)
 {
 	struct mac_driver *mac_ctrl_drv;
@@ -83,6 +104,14 @@
 							       &sfp_prsnt);
 		if (!ret)
 			*link_status = *link_status && sfp_prsnt;
+
+		/* for FIBER port, it may have a fake link up.
+		 * when the link status changes from down to up, we need to do
+		 * anti-shake. the anti-shake time is base on tests.
+		 * only FIBER port need to do this.
+		 */
+		if (*link_status && !mac_cb->link)
+			*link_status = hns_mac_link_anti_shake(mac_ctrl_drv);
 	}
 
 	mac_cb->link = *link_status;
@@ -904,6 +933,7 @@
 			mac_cb->cpld_ctrl = NULL;
 		} else {
 			syscon = syscon_node_to_regmap(cpld_args.np);
+			of_node_put(cpld_args.np);
 			if (IS_ERR_OR_NULL(syscon)) {
 				dev_dbg(mac_cb->dev, "no cpld-syscon found!\n");
 				mac_cb->cpld_ctrl = NULL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c
@@ -398,6 +398,10 @@
 		return;
 
 	if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) {
+		/* DSAF_MAX_PORT_NUM is 6, but DSAF_GE_NUM is 8.
+		   We need check to prevent array overflow */
+		if (port >= DSAF_MAX_PORT_NUM)
+			return;
 		reg_val_1  = 0x1 << port;
 		port_rst_off = dsaf_dev->mac_cb[port]->port_rst_off;
 		/* there is difference between V1 and V2 in register.*/
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/hisilicon/hns/hns_enet.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/hisilicon/hns/hns_enet.c
@@ -565,7 +565,6 @@
 	skb = *out_skb = napi_alloc_skb(&ring_data->napi,
 					HNS_RX_HEAD_SIZE);
 	if (unlikely(!skb)) {
-		netdev_err(ndev, "alloc rx skb fail\n");
 		ring->stats.sw_err_cnt++;
 		return -ENOMEM;
 	}
@@ -1056,7 +1055,6 @@
 		container_of(napi, struct hns_nic_ring_data, napi);
 	struct hnae_ring *ring = ring_data->ring;
 
-try_again:
 	clean_complete += ring_data->poll_one(
 				ring_data, budget - clean_complete,
 				ring_data->ex_process);
@@ -1066,7 +1064,7 @@
 			napi_complete(napi);
 			ring->q->handle->dev->ops->toggle_ring_irq(ring, 0);
 		} else {
-			goto try_again;
+			return budget;
 		}
 	}
 
@@ -1679,8 +1677,10 @@
 			for (j = 0; j < fetch_num; j++) {
 				/* alloc one skb and init */
 				skb = hns_assemble_skb(ndev);
-				if (!skb)
+				if (!skb) {
+					ret = -ENOMEM;
 					goto out;
+				}
 				rd = &tx_ring_data(priv, skb->queue_mapping);
 				hns_nic_net_xmit_hw(ndev, skb, rd);
 
@@ -2298,8 +2298,10 @@
 			priv->enet_ver = AE_VERSION_1;
 		else if (acpi_dev_found(hns_enet_acpi_match[1].id))
 			priv->enet_ver = AE_VERSION_2;
-		else
-			return -ENXIO;
+		else {
+			ret = -ENXIO;
+			goto out_read_prop_fail;
+		}
 
 		/* try to find port-idx-in-ae first */
 		ret = acpi_node_get_property_reference(dev->fwnode,
@@ -2315,7 +2317,8 @@
 		priv->fwnode = args.fwnode;
 	} else {
 		dev_err(dev, "cannot read cfg data from OF or acpi\n");
-		return -ENXIO;
+		ret = -ENXIO;
+		goto out_read_prop_fail;
 	}
 
 	ret = device_property_read_u32(dev, "port-idx-in-ae", &port_id);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
@@ -415,6 +415,10 @@
 	/* for mutl buffer*/
 	new_skb = skb_copy(skb, GFP_ATOMIC);
 	dev_kfree_skb_any(skb);
+	if (!new_skb) {
+		netdev_err(ndev, "skb alloc failed\n");
+		return;
+	}
 	skb = new_skb;
 
 	check_ok = 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/hisilicon/hns3/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/hisilicon/hns3/Makefile
@@ -3,6 +3,8 @@
 # Makefile for the HISILICON network device drivers.
 #
 
+ccflags-y += -I$(srctree)/$(src)
+
 obj-$(CONFIG_HNS3) += hns3pf/
 obj-$(CONFIG_HNS3) += hns3vf/
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h
@@ -45,8 +45,10 @@
 	HCLGE_MBX_GET_LINK_MODE,	/* (VF -> PF) get the link mode of pf */
 	HCLGE_MBX_PUSH_VLAN_INFO,	/* (PF -> VF) push port base vlan */
 	HCLGE_MBX_GET_MEDIA_TYPE,       /* (VF -> PF) get media type */
+	HCLGE_MBX_PUSH_PROMISC_INFO,	/* (PF -> VF) push vf promisc info */
+	HCLGE_MBX_VF_UNINIT,            /* (VF -> PF) vf is unintializing */
 
-	HCLGE_MBX_GET_VF_FLR_STATUS = 200, /* (M7 -> PF) get vf reset status */
+	HCLGE_MBX_GET_VF_FLR_STATUS = 200, /* (M7 -> PF) get vf flr status */
 	HCLGE_MBX_PUSH_LINK_STATUS,	/* (M7 -> PF) get port link status */
 	HCLGE_MBX_NCSI_ERROR,		/* (M7 -> PF) receive a NCSI error */
 };
@@ -71,7 +73,7 @@
 };
 
 #define HCLGE_MBX_MAX_MSG_SIZE	16
-#define HCLGE_MBX_MAX_RESP_DATA_SIZE	8
+#define HCLGE_MBX_MAX_RESP_DATA_SIZE	8U
 #define HCLGE_MBX_RING_MAP_BASIC_MSG_NUM	3
 #define HCLGE_MBX_RING_NODE_VARIABLE_NUM	3
 
@@ -123,7 +125,7 @@
 #define hclge_mbx_ring_ptr_move_crq(crq) \
 	(crq->next_to_use = (crq->next_to_use + 1) % crq->desc_num)
 #define hclge_mbx_tail_ptr_move_arq(arq) \
-	(arq.tail = (arq.tail + 1) % HCLGE_MBX_MAX_ARQ_MSG_SIZE)
+		(arq.tail = (arq.tail + 1) % HCLGE_MBX_MAX_ARQ_MSG_NUM)
 #define hclge_mbx_head_ptr_move_arq(arq) \
-		(arq.head = (arq.head + 1) % HCLGE_MBX_MAX_ARQ_MSG_SIZE)
+		(arq.head = (arq.head + 1) % HCLGE_MBX_MAX_ARQ_MSG_NUM)
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/hisilicon/hns3/hnae3.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/hisilicon/hns3/hnae3.c
@@ -10,6 +10,30 @@
 static LIST_HEAD(hnae3_client_list);
 static LIST_HEAD(hnae3_ae_dev_list);
 
+void hnae3_unregister_ae_algo_prepare(struct hnae3_ae_algo *ae_algo)
+{
+	const struct pci_device_id *pci_id;
+	struct hnae3_ae_dev *ae_dev;
+
+	if (!ae_algo)
+		return;
+
+	list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
+		if (!hnae3_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))
+			continue;
+
+		pci_id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
+		if (!pci_id)
+			continue;
+		if (IS_ENABLED(CONFIG_PCI_IOV)) {
+			device_lock(&ae_dev->pdev->dev);
+			pci_disable_sriov(ae_dev->pdev);
+			device_unlock(&ae_dev->pdev->dev);
+		}
+	}
+}
+EXPORT_SYMBOL(hnae3_unregister_ae_algo_prepare);
+
 /* we are keeping things simple and using single lock for all the
  * list. This is a non-critical code so other updations, if happen
  * in parallel, can wait.
@@ -146,7 +170,7 @@
 		return;
 
 	mutex_lock(&hnae3_common_lock);
-
+	/* one system should only have one client for every type */
 	list_for_each_entry(client_tmp, &hnae3_client_list, node) {
 		if (client_tmp->type == client->type) {
 			existed = true;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/hisilicon/hns3/hnae3.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/hisilicon/hns3/hnae3.h
@@ -77,6 +77,7 @@
 	((ring)->p = ((ring)->p - 1 + (ring)->desc_num) % (ring)->desc_num)
 
 enum hns_desc_type {
+	DESC_TYPE_UNKNOWN,
 	DESC_TYPE_SKB,
 	DESC_TYPE_PAGE,
 };
@@ -130,7 +131,6 @@
 	HNAE3_MODULE_TYPE_CR		= 0x04,
 	HNAE3_MODULE_TYPE_KR		= 0x05,
 	HNAE3_MODULE_TYPE_TP		= 0x06,
-
 };
 
 enum hnae3_fec_mode {
@@ -165,11 +165,7 @@
 	HNAE3_IMP_RESET,
 	HNAE3_UNKNOWN_RESET,
 	HNAE3_NONE_RESET,
-};
-
-enum hnae3_flr_state {
-	HNAE3_FLR_DOWN,
-	HNAE3_FLR_DONE,
+	HNAE3_MAX_RESET,
 };
 
 enum hnae3_port_base_vlan_state {
@@ -366,6 +362,19 @@
  *   Enable/disable HW GRO
  * add_arfs_entry
  *   Check the 5-tuples of flow, and create flow director rule
+ * get_vf_config
+ *   Get the VF configuration setting by the host
+ * set_vf_link_state
+ *   Set VF link status
+ * set_vf_spoofchk
+ *   Enable/disable spoof check for specified vf
+ * set_vf_trust
+ *   Enable/disable trust for specified vf, if the vf being trusted, then
+ *   it can enable promisc mode
+ * set_vf_rate
+ *   Set the max tx rate of specified vf.
+ * set_vf_mac
+ *   Configure the default MAC for specified VF
  */
 struct hnae3_ae_ops {
 	int (*init_ae_dev)(struct hnae3_ae_dev *ae_dev);
@@ -531,6 +540,16 @@
 	int (*mac_connect_phy)(struct hnae3_handle *handle);
 	void (*mac_disconnect_phy)(struct hnae3_handle *handle);
 	void (*restore_vlan_table)(struct hnae3_handle *handle);
+	int (*get_vf_config)(struct hnae3_handle *handle, int vf,
+			     struct ifla_vf_info *ivf);
+	int (*set_vf_link_state)(struct hnae3_handle *handle, int vf,
+				 int link_state);
+	int (*set_vf_spoofchk)(struct hnae3_handle *handle, int vf,
+			       bool enable);
+	int (*set_vf_trust)(struct hnae3_handle *handle, int vf, bool enable);
+	int (*set_vf_rate)(struct hnae3_handle *handle, int vf,
+			   int min_tx_rate, int max_tx_rate, bool force);
+	int (*set_vf_mac)(struct hnae3_handle *handle, int vf, u8 *p);
 };
 
 struct hnae3_dcb_ops {
@@ -553,7 +572,7 @@
 	const struct pci_device_id *pdev_id_table;
 };
 
-#define HNAE3_INT_NAME_LEN        (IFNAMSIZ + 16)
+#define HNAE3_INT_NAME_LEN        32
 #define HNAE3_ITR_COUNTDOWN_START 100
 
 struct hnae3_tc_info {
@@ -665,6 +684,7 @@
 int hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev);
 void hnae3_unregister_ae_dev(struct hnae3_ae_dev *ae_dev);
 
+void hnae3_unregister_ae_algo_prepare(struct hnae3_ae_algo *ae_algo);
 void hnae3_unregister_ae_algo(struct hnae3_ae_algo *ae_algo);
 void hnae3_register_ae_algo(struct hnae3_ae_algo *ae_algo);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
@@ -16,15 +16,14 @@
 			       const char *cmd_buf)
 {
 	struct hns3_nic_priv *priv = h->priv;
-	struct hns3_nic_ring_data *ring_data;
 	struct hns3_enet_ring *ring;
 	u32 base_add_l, base_add_h;
 	u32 queue_num, queue_max;
 	u32 value, i = 0;
 	int cnt;
 
-	if (!priv->ring_data) {
-		dev_err(&h->pdev->dev, "ring_data is NULL\n");
+	if (!priv->ring) {
+		dev_err(&h->pdev->dev, "priv->ring is NULL\n");
 		return -EFAULT;
 	}
 
@@ -44,7 +43,6 @@
 		return -EINVAL;
 	}
 
-	ring_data = priv->ring_data;
 	for (i = queue_num; i < queue_max; i++) {
 		/* Each cycle needs to determine whether the instance is reset,
 		 * to prevent reference to invalid memory. And need to ensure
@@ -54,73 +52,73 @@
 		    test_bit(HNS3_NIC_STATE_RESETTING, &priv->state))
 			return -EPERM;
 
-		ring = ring_data[(u32)(i + h->kinfo.num_tqps)].ring;
+		ring = &priv->ring[(u32)(i + h->kinfo.num_tqps)];
 		base_add_h = readl_relaxed(ring->tqp->io_base +
 					   HNS3_RING_RX_RING_BASEADDR_H_REG);
 		base_add_l = readl_relaxed(ring->tqp->io_base +
 					   HNS3_RING_RX_RING_BASEADDR_L_REG);
-		dev_info(&h->pdev->dev, "RX(%d) BASE ADD: 0x%08x%08x\n", i,
+		dev_info(&h->pdev->dev, "RX(%u) BASE ADD: 0x%08x%08x\n", i,
 			 base_add_h, base_add_l);
 
 		value = readl_relaxed(ring->tqp->io_base +
 				      HNS3_RING_RX_RING_BD_NUM_REG);
-		dev_info(&h->pdev->dev, "RX(%d) RING BD NUM: %u\n", i, value);
+		dev_info(&h->pdev->dev, "RX(%u) RING BD NUM: %u\n", i, value);
 
 		value = readl_relaxed(ring->tqp->io_base +
 				      HNS3_RING_RX_RING_BD_LEN_REG);
-		dev_info(&h->pdev->dev, "RX(%d) RING BD LEN: %u\n", i, value);
+		dev_info(&h->pdev->dev, "RX(%u) RING BD LEN: %u\n", i, value);
 
 		value = readl_relaxed(ring->tqp->io_base +
 				      HNS3_RING_RX_RING_TAIL_REG);
-		dev_info(&h->pdev->dev, "RX(%d) RING TAIL: %u\n", i, value);
+		dev_info(&h->pdev->dev, "RX(%u) RING TAIL: %u\n", i, value);
 
 		value = readl_relaxed(ring->tqp->io_base +
 				      HNS3_RING_RX_RING_HEAD_REG);
-		dev_info(&h->pdev->dev, "RX(%d) RING HEAD: %u\n", i, value);
+		dev_info(&h->pdev->dev, "RX(%u) RING HEAD: %u\n", i, value);
 
 		value = readl_relaxed(ring->tqp->io_base +
 				      HNS3_RING_RX_RING_FBDNUM_REG);
-		dev_info(&h->pdev->dev, "RX(%d) RING FBDNUM: %u\n", i, value);
+		dev_info(&h->pdev->dev, "RX(%u) RING FBDNUM: %u\n", i, value);
 
 		value = readl_relaxed(ring->tqp->io_base +
 				      HNS3_RING_RX_RING_PKTNUM_RECORD_REG);
-		dev_info(&h->pdev->dev, "RX(%d) RING PKTNUM: %u\n", i, value);
+		dev_info(&h->pdev->dev, "RX(%u) RING PKTNUM: %u\n", i, value);
 
-		ring = ring_data[i].ring;
+		ring = &priv->ring[i];
 		base_add_h = readl_relaxed(ring->tqp->io_base +
 					   HNS3_RING_TX_RING_BASEADDR_H_REG);
 		base_add_l = readl_relaxed(ring->tqp->io_base +
 					   HNS3_RING_TX_RING_BASEADDR_L_REG);
-		dev_info(&h->pdev->dev, "TX(%d) BASE ADD: 0x%08x%08x\n", i,
+		dev_info(&h->pdev->dev, "TX(%u) BASE ADD: 0x%08x%08x\n", i,
 			 base_add_h, base_add_l);
 
 		value = readl_relaxed(ring->tqp->io_base +
 				      HNS3_RING_TX_RING_BD_NUM_REG);
-		dev_info(&h->pdev->dev, "TX(%d) RING BD NUM: %u\n", i, value);
+		dev_info(&h->pdev->dev, "TX(%u) RING BD NUM: %u\n", i, value);
 
 		value = readl_relaxed(ring->tqp->io_base +
 				      HNS3_RING_TX_RING_TC_REG);
-		dev_info(&h->pdev->dev, "TX(%d) RING TC: %u\n", i, value);
+		dev_info(&h->pdev->dev, "TX(%u) RING TC: %u\n", i, value);
 
 		value = readl_relaxed(ring->tqp->io_base +
 				      HNS3_RING_TX_RING_TAIL_REG);
-		dev_info(&h->pdev->dev, "TX(%d) RING TAIL: %u\n", i, value);
+		dev_info(&h->pdev->dev, "TX(%u) RING TAIL: %u\n", i, value);
 
 		value = readl_relaxed(ring->tqp->io_base +
 				      HNS3_RING_TX_RING_HEAD_REG);
-		dev_info(&h->pdev->dev, "TX(%d) RING HEAD: %u\n", i, value);
+		dev_info(&h->pdev->dev, "TX(%u) RING HEAD: %u\n", i, value);
 
 		value = readl_relaxed(ring->tqp->io_base +
 				      HNS3_RING_TX_RING_FBDNUM_REG);
-		dev_info(&h->pdev->dev, "TX(%d) RING FBDNUM: %u\n", i, value);
+		dev_info(&h->pdev->dev, "TX(%u) RING FBDNUM: %u\n", i, value);
 
 		value = readl_relaxed(ring->tqp->io_base +
 				      HNS3_RING_TX_RING_OFFSET_REG);
-		dev_info(&h->pdev->dev, "TX(%d) RING OFFSET: %u\n", i, value);
+		dev_info(&h->pdev->dev, "TX(%u) RING OFFSET: %u\n", i, value);
 
 		value = readl_relaxed(ring->tqp->io_base +
 				      HNS3_RING_TX_RING_PKTNUM_RECORD_REG);
-		dev_info(&h->pdev->dev, "TX(%d) RING PKTNUM: %u\n\n", i,
+		dev_info(&h->pdev->dev, "TX(%u) RING PKTNUM: %u\n\n", i,
 			 value);
 	}
 
@@ -130,7 +128,6 @@
 static int hns3_dbg_queue_map(struct hnae3_handle *h)
 {
 	struct hns3_nic_priv *priv = h->priv;
-	struct hns3_nic_ring_data *ring_data;
 	int i;
 
 	if (!h->ae_algo->ops->get_global_queue_id)
@@ -143,15 +140,12 @@
 		u16 global_qid;
 
 		global_qid = h->ae_algo->ops->get_global_queue_id(h, i);
-		ring_data = &priv->ring_data[i];
-		if (!ring_data || !ring_data->ring ||
-		    !ring_data->ring->tqp_vector)
+		if (!priv->ring || !priv->ring[i].tqp_vector)
 			continue;
 
 		dev_info(&h->pdev->dev,
 			 "      %4d            %4d            %4d\n",
-			 i, global_qid,
-			 ring_data->ring->tqp_vector->vector_irq);
+			 i, global_qid, priv->ring[i].tqp_vector->vector_irq);
 	}
 
 	return 0;
@@ -160,7 +154,6 @@
 static int hns3_dbg_bd_info(struct hnae3_handle *h, const char *cmd_buf)
 {
 	struct hns3_nic_priv *priv = h->priv;
-	struct hns3_nic_ring_data *ring_data;
 	struct hns3_desc *rx_desc, *tx_desc;
 	struct device *dev = &h->pdev->dev;
 	struct hns3_enet_ring *ring;
@@ -183,8 +176,7 @@
 		return -EINVAL;
 	}
 
-	ring_data = priv->ring_data;
-	ring  = ring_data[q_num].ring;
+	ring = &priv->ring[q_num];
 	value = readl_relaxed(ring->tqp->io_base + HNS3_RING_TX_RING_TAIL_REG);
 	tx_index = (cnt == 1) ? value : tx_index;
 
@@ -198,39 +190,46 @@
 	addr = le64_to_cpu(tx_desc->addr);
 	dev_info(dev, "TX Queue Num: %u, BD Index: %u\n", q_num, tx_index);
 	dev_info(dev, "(TX)addr: %pad\n", &addr);
-	dev_info(dev, "(TX)vlan_tag: %u\n", tx_desc->tx.vlan_tag);
-	dev_info(dev, "(TX)send_size: %u\n", tx_desc->tx.send_size);
+	dev_info(dev, "(TX)vlan_tag: %u\n", le16_to_cpu(tx_desc->tx.vlan_tag));
+	dev_info(dev, "(TX)send_size: %u\n",
+		 le16_to_cpu(tx_desc->tx.send_size));
 	dev_info(dev, "(TX)vlan_tso: %u\n", tx_desc->tx.type_cs_vlan_tso);
 	dev_info(dev, "(TX)l2_len: %u\n", tx_desc->tx.l2_len);
 	dev_info(dev, "(TX)l3_len: %u\n", tx_desc->tx.l3_len);
 	dev_info(dev, "(TX)l4_len: %u\n", tx_desc->tx.l4_len);
-	dev_info(dev, "(TX)vlan_tag: %u\n", tx_desc->tx.outer_vlan_tag);
-	dev_info(dev, "(TX)tv: %u\n", tx_desc->tx.tv);
+	dev_info(dev, "(TX)vlan_tag: %u\n",
+		 le16_to_cpu(tx_desc->tx.outer_vlan_tag));
+	dev_info(dev, "(TX)tv: %u\n", le16_to_cpu(tx_desc->tx.tv));
 	dev_info(dev, "(TX)vlan_msec: %u\n", tx_desc->tx.ol_type_vlan_msec);
 	dev_info(dev, "(TX)ol2_len: %u\n", tx_desc->tx.ol2_len);
 	dev_info(dev, "(TX)ol3_len: %u\n", tx_desc->tx.ol3_len);
 	dev_info(dev, "(TX)ol4_len: %u\n", tx_desc->tx.ol4_len);
-	dev_info(dev, "(TX)paylen: %u\n", tx_desc->tx.paylen);
-	dev_info(dev, "(TX)vld_ra_ri: %u\n", tx_desc->tx.bdtp_fe_sc_vld_ra_ri);
-	dev_info(dev, "(TX)mss: %u\n", tx_desc->tx.mss);
+	dev_info(dev, "(TX)paylen: %u\n", le32_to_cpu(tx_desc->tx.paylen));
+	dev_info(dev, "(TX)vld_ra_ri: %u\n",
+		 le16_to_cpu(tx_desc->tx.bdtp_fe_sc_vld_ra_ri));
+	dev_info(dev, "(TX)mss: %u\n", le16_to_cpu(tx_desc->tx.mss));
 
-	ring  = ring_data[q_num + h->kinfo.num_tqps].ring;
+	ring = &priv->ring[q_num + h->kinfo.num_tqps];
 	value = readl_relaxed(ring->tqp->io_base + HNS3_RING_RX_RING_TAIL_REG);
 	rx_index = (cnt == 1) ? value : tx_index;
-	rx_desc	 = &ring->desc[rx_index];
+	rx_desc = &ring->desc[rx_index];
 
 	addr = le64_to_cpu(rx_desc->addr);
 	dev_info(dev, "RX Queue Num: %u, BD Index: %u\n", q_num, rx_index);
 	dev_info(dev, "(RX)addr: %pad\n", &addr);
-	dev_info(dev, "(RX)l234_info: %u\n", rx_desc->rx.l234_info);
-	dev_info(dev, "(RX)pkt_len: %u\n", rx_desc->rx.pkt_len);
-	dev_info(dev, "(RX)size: %u\n", rx_desc->rx.size);
-	dev_info(dev, "(RX)rss_hash: %u\n", rx_desc->rx.rss_hash);
-	dev_info(dev, "(RX)fd_id: %u\n", rx_desc->rx.fd_id);
-	dev_info(dev, "(RX)vlan_tag: %u\n", rx_desc->rx.vlan_tag);
-	dev_info(dev, "(RX)o_dm_vlan_id_fb: %u\n", rx_desc->rx.o_dm_vlan_id_fb);
-	dev_info(dev, "(RX)ot_vlan_tag: %u\n", rx_desc->rx.ot_vlan_tag);
-	dev_info(dev, "(RX)bd_base_info: %u\n", rx_desc->rx.bd_base_info);
+	dev_info(dev, "(RX)l234_info: %u\n",
+		 le32_to_cpu(rx_desc->rx.l234_info));
+	dev_info(dev, "(RX)pkt_len: %u\n", le16_to_cpu(rx_desc->rx.pkt_len));
+	dev_info(dev, "(RX)size: %u\n", le16_to_cpu(rx_desc->rx.size));
+	dev_info(dev, "(RX)rss_hash: %u\n", le32_to_cpu(rx_desc->rx.rss_hash));
+	dev_info(dev, "(RX)fd_id: %u\n", le16_to_cpu(rx_desc->rx.fd_id));
+	dev_info(dev, "(RX)vlan_tag: %u\n", le16_to_cpu(rx_desc->rx.vlan_tag));
+	dev_info(dev, "(RX)o_dm_vlan_id_fb: %u\n",
+		 le16_to_cpu(rx_desc->rx.o_dm_vlan_id_fb));
+	dev_info(dev, "(RX)ot_vlan_tag: %u\n",
+		 le16_to_cpu(rx_desc->rx.ot_vlan_tag));
+	dev_info(dev, "(RX)bd_base_info: %u\n",
+		 le32_to_cpu(rx_desc->rx.bd_base_info));
 
 	return 0;
 }
@@ -261,6 +260,8 @@
 	dev_info(&h->pdev->dev, "dump m7 info\n");
 	dev_info(&h->pdev->dev, "dump ncl_config <offset> <length>(in hex)\n");
 	dev_info(&h->pdev->dev, "dump mac tnl status\n");
+	dev_info(&h->pdev->dev, "dump loopback\n");
+	dev_info(&h->pdev->dev, "dump qs shaper [qs id]\n");
 
 	memset(printf_buf, 0, HNS3_DBG_BUF_LEN);
 	strncat(printf_buf, "dump reg [[bios common] [ssu <port_id>]",
@@ -298,8 +299,8 @@
 	if (!buf)
 		return -ENOMEM;
 
-	len = snprintf(buf, HNS3_DBG_READ_LEN, "%s\n",
-		       "Please echo help to cmd to get help information");
+	len = scnprintf(buf, HNS3_DBG_READ_LEN, "%s\n",
+			"Please echo help to cmd to get help information");
 	uncopy_bytes = copy_to_user(buffer, buf, len);
 
 	kfree(buf);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
@@ -21,9 +21,16 @@
 #include <net/pkt_cls.h>
 #include <net/tcp.h>
 #include <net/vxlan.h>
+#include <net/geneve.h>
 
 #include "hnae3.h"
 #include "hns3_enet.h"
+/* All hns3 tracepoints are defined by the include below, which
+ * must be included exactly once across the whole kernel with
+ * CREATE_TRACE_POINTS defined
+ */
+#define CREATE_TRACE_POINTS
+#include "hns3_trace.h"
 
 #define hns3_set_field(origin, shift, val)	((origin) |= ((val) << (shift)))
 #define hns3_tx_bd_count(S)	DIV_ROUND_UP(S, HNS3_MAX_BD_SIZE)
@@ -54,6 +61,9 @@
 #define HNS3_INNER_VLAN_TAG	1
 #define HNS3_OUTER_VLAN_TAG	2
 
+#define HNS3_MIN_TX_LEN		33U
+#define HNS3_MIN_TUN_PKT_LEN	65U
+
 /* hns3_pci_tbl - PCI Device ID Table
  *
  * Last entry must be all 0s
@@ -127,18 +137,21 @@
 			continue;
 
 		if (tqp_vectors->tx_group.ring && tqp_vectors->rx_group.ring) {
-			snprintf(tqp_vectors->name, HNAE3_INT_NAME_LEN - 1,
-				 "%s-%s-%d", priv->netdev->name, "TxRx",
-				 txrx_int_idx++);
+			snprintf(tqp_vectors->name, HNAE3_INT_NAME_LEN,
+				 "%s-%s-%s-%d", hns3_driver_name,
+				 pci_name(priv->ae_handle->pdev),
+				 "TxRx", txrx_int_idx++);
 			txrx_int_idx++;
 		} else if (tqp_vectors->rx_group.ring) {
-			snprintf(tqp_vectors->name, HNAE3_INT_NAME_LEN - 1,
-				 "%s-%s-%d", priv->netdev->name, "Rx",
-				 rx_int_idx++);
+			snprintf(tqp_vectors->name, HNAE3_INT_NAME_LEN,
+				 "%s-%s-%s-%d", hns3_driver_name,
+				 pci_name(priv->ae_handle->pdev),
+				 "Rx", rx_int_idx++);
 		} else if (tqp_vectors->tx_group.ring) {
-			snprintf(tqp_vectors->name, HNAE3_INT_NAME_LEN - 1,
-				 "%s-%s-%d", priv->netdev->name, "Tx",
-				 tx_int_idx++);
+			snprintf(tqp_vectors->name, HNAE3_INT_NAME_LEN,
+				 "%s-%s-%s-%d", hns3_driver_name,
+				 pci_name(priv->ae_handle->pdev),
+				 "Tx", tx_int_idx++);
 		} else {
 			/* Skip this unused q_vector */
 			continue;
@@ -155,6 +168,8 @@
 			return ret;
 		}
 
+		disable_irq(tqp_vectors->vector_irq);
+
 		irq_set_affinity_hint(tqp_vectors->vector_irq,
 				      &tqp_vectors->affinity_mask);
 
@@ -173,6 +188,7 @@
 static void hns3_vector_enable(struct hns3_enet_tqp_vector *tqp_vector)
 {
 	napi_enable(&tqp_vector->napi);
+	enable_irq(tqp_vector->vector_irq);
 
 	/* enable vector */
 	hns3_mask_vector_irq(tqp_vector, 1);
@@ -372,18 +388,6 @@
 	if (ret)
 		return ret;
 
-	/* the device can work without cpu rmap, only aRFS needs it */
-	ret = hns3_set_rx_cpu_rmap(netdev);
-	if (ret)
-		netdev_warn(netdev, "set rx cpu rmap fail, ret=%d!\n", ret);
-
-	/* get irq resource for all vectors */
-	ret = hns3_nic_init_irq(priv);
-	if (ret) {
-		netdev_err(netdev, "init irq failed! ret=%d\n", ret);
-		goto free_rmap;
-	}
-
 	clear_bit(HNS3_NIC_STATE_DOWN, &priv->state);
 
 	/* enable the vectors */
@@ -396,22 +400,15 @@
 
 	/* start the ae_dev */
 	ret = h->ae_algo->ops->start ? h->ae_algo->ops->start(h) : 0;
-	if (ret)
-		goto out_start_err;
-
-	return 0;
-
-out_start_err:
-	set_bit(HNS3_NIC_STATE_DOWN, &priv->state);
-	while (j--)
-		hns3_tqp_disable(h->kinfo.tqp[j]);
+	if (ret) {
+		set_bit(HNS3_NIC_STATE_DOWN, &priv->state);
+		while (j--)
+			hns3_tqp_disable(h->kinfo.tqp[j]);
 
-	for (j = i - 1; j >= 0; j--)
-		hns3_vector_disable(&priv->tqp_vector[j]);
+		for (j = i - 1; j >= 0; j--)
+			hns3_vector_disable(&priv->tqp_vector[j]);
+	}
 
-	hns3_nic_uninit_irq(priv);
-free_rmap:
-	hns3_free_rx_cpu_rmap(netdev);
 	return ret;
 }
 
@@ -448,6 +445,11 @@
 	if (hns3_nic_resetting(netdev))
 		return -EBUSY;
 
+	if (!test_bit(HNS3_NIC_STATE_DOWN, &priv->state)) {
+		netdev_warn(netdev, "net open repeatedly!\n");
+		return 0;
+	}
+
 	netif_carrier_off(netdev);
 
 	ret = hns3_nic_set_real_num_queue(netdev);
@@ -483,7 +485,7 @@
 
 	for (i = 0; i < h->kinfo.num_tqps; i++) {
 		dev_queue = netdev_get_tx_queue(ndev,
-						priv->ring_data[i].queue_index);
+						priv->ring[i].queue_index);
 		netdev_tx_reset_queue(dev_queue);
 	}
 }
@@ -508,11 +510,6 @@
 	if (ops->stop)
 		ops->stop(priv->ae_handle);
 
-	hns3_free_rx_cpu_rmap(netdev);
-
-	/* free irq resources */
-	hns3_nic_uninit_irq(priv);
-
 	/* delay ring buffer clearing to hns3_reset_notify_uninit_enet
 	 * during reset process, because driver may not be able
 	 * to disable the ring through firmware when downing the netdev.
@@ -536,8 +533,8 @@
 	if (h->ae_algo->ops->set_timer_task)
 		h->ae_algo->ops->set_timer_task(priv->ae_handle, false);
 
-	netif_tx_stop_all_queues(netdev);
 	netif_carrier_off(netdev);
+	netif_tx_disable(netdev);
 
 	hns3_nic_net_down(netdev);
 
@@ -681,7 +678,7 @@
 		return 0;
 
 	ret = skb_cow_head(skb, 0);
-	if (unlikely(ret))
+	if (unlikely(ret < 0))
 		return ret;
 
 	l3.hdr = skb_network_header(skb);
@@ -734,6 +731,8 @@
 	/* get MSS for TSO */
 	*mss = skb_shinfo(skb)->gso_size;
 
+	trace_hns3_tso(skb);
+
 	return 0;
 }
 
@@ -793,7 +792,7 @@
  * and it is udp packet, which has a dest port as the IANA assigned.
  * the hardware is expected to do the checksum offload, but the
  * hardware will not do the checksum offload when udp dest port is
- * 4789.
+ * 4789, 4790 or 6081.
  */
 static bool hns3_tunnel_csum_bug(struct sk_buff *skb)
 {
@@ -802,11 +801,11 @@
 	l4.hdr = skb_transport_header(skb);
 
 	if (!(!skb->encapsulation &&
-	      l4.udp->dest == htons(IANA_VXLAN_UDP_PORT)))
+	      (l4.udp->dest == htons(IANA_VXLAN_UDP_PORT) ||
+	      l4.udp->dest == htons(GENEVE_UDP_PORT) ||
+	      l4.udp->dest == htons(4790))))
 		return false;
 
-	skb_checksum_help(skb);
-
 	return true;
 }
 
@@ -884,8 +883,7 @@
 			/* the stack computes the IP header already,
 			 * driver calculate l4 checksum when not TSO.
 			 */
-			skb_checksum_help(skb);
-			return 0;
+			return skb_checksum_help(skb);
 		}
 
 		hns3_set_outer_l2l3l4(skb, ol4_proto, ol_type_vlan_len_msec);
@@ -929,8 +927,11 @@
 			       l4.tcp->doff);
 		break;
 	case IPPROTO_UDP:
-		if (hns3_tunnel_csum_bug(skb))
-			break;
+		if (hns3_tunnel_csum_bug(skb)) {
+			int ret = skb_put_padto(skb, HNS3_MIN_TUN_PKT_LEN);
+
+			return ret ? ret : skb_checksum_help(skb);
+		}
 
 		hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4CS_B, 1);
 		hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4T_S,
@@ -955,21 +956,12 @@
 		/* the stack computes the IP header already,
 		 * driver calculate l4 checksum when not TSO.
 		 */
-		skb_checksum_help(skb);
-		return 0;
+		return skb_checksum_help(skb);
 	}
 
 	return 0;
 }
 
-static void hns3_set_txbd_baseinfo(u16 *bdtp_fe_sc_vld_ra_ri, int frag_end)
-{
-	/* Config bd buffer end */
-	if (!!frag_end)
-		hns3_set_field(*bdtp_fe_sc_vld_ra_ri, HNS3_TXD_FE_B, 1U);
-	hns3_set_field(*bdtp_fe_sc_vld_ra_ri, HNS3_TXD_VLD_B, 1U);
-}
-
 static int hns3_handle_vtags(struct hns3_enet_ring *tx_ring,
 			     struct sk_buff *skb)
 {
@@ -1062,7 +1054,7 @@
 		skb_reset_mac_len(skb);
 
 		ret = hns3_get_l4_protocol(skb, &ol4_proto, &il4_proto);
-		if (unlikely(ret)) {
+		if (unlikely(ret < 0)) {
 			u64_stats_update_begin(&ring->syncp);
 			ring->stats.tx_l4_proto_err++;
 			u64_stats_update_end(&ring->syncp);
@@ -1072,7 +1064,7 @@
 		ret = hns3_set_l2l3l4(skb, ol4_proto, il4_proto,
 				      &type_cs_vlan_tso,
 				      &ol_type_vlan_len_msec);
-		if (unlikely(ret)) {
+		if (unlikely(ret < 0)) {
 			u64_stats_update_begin(&ring->syncp);
 			ring->stats.tx_l2l3l4_err++;
 			u64_stats_update_end(&ring->syncp);
@@ -1081,7 +1073,7 @@
 
 		ret = hns3_set_tso(skb, &paylen, &mss,
 				   &type_cs_vlan_tso);
-		if (unlikely(ret)) {
+		if (unlikely(ret < 0)) {
 			u64_stats_update_begin(&ring->syncp);
 			ring->stats.tx_tso_err++;
 			u64_stats_update_end(&ring->syncp);
@@ -1102,9 +1094,10 @@
 }
 
 static int hns3_fill_desc(struct hns3_enet_ring *ring, void *priv,
-			  unsigned int size, int frag_end,
-			  enum hns_desc_type type)
+			  unsigned int size, enum hns_desc_type type)
 {
+#define HNS3_LIKELY_BD_NUM	1
+
 	struct hns3_desc_cb *desc_cb = &ring->desc_cb[ring->next_to_use];
 	struct hns3_desc *desc = &ring->desc[ring->next_to_use];
 	struct device *dev = ring_to_dev(ring);
@@ -1118,7 +1111,7 @@
 		int ret;
 
 		ret = hns3_fill_skb_desc(ring, skb, desc);
-		if (unlikely(ret))
+		if (unlikely(ret < 0))
 			return ret;
 
 		dma = dma_map_single(dev, skb->data, size, DMA_TO_DEVICE);
@@ -1137,19 +1130,17 @@
 	desc_cb->length = size;
 
 	if (likely(size <= HNS3_MAX_BD_SIZE)) {
-		u16 bdtp_fe_sc_vld_ra_ri = 0;
-
 		desc_cb->priv = priv;
 		desc_cb->dma = dma;
 		desc_cb->type = type;
 		desc->addr = cpu_to_le64(dma);
 		desc->tx.send_size = cpu_to_le16(size);
-		hns3_set_txbd_baseinfo(&bdtp_fe_sc_vld_ra_ri, frag_end);
 		desc->tx.bdtp_fe_sc_vld_ra_ri =
-			cpu_to_le16(bdtp_fe_sc_vld_ra_ri);
+			cpu_to_le16(BIT(HNS3_TXD_VLD_B));
 
+		trace_hns3_tx_desc(ring, ring->next_to_use);
 		ring_ptr_move_fw(ring, next_to_use);
-		return 0;
+		return HNS3_LIKELY_BD_NUM;
 	}
 
 	frag_buf_num = hns3_tx_bd_count(size);
@@ -1158,8 +1149,6 @@
 
 	/* When frag size is bigger than hardware limit, split this frag */
 	for (k = 0; k < frag_buf_num; k++) {
-		u16 bdtp_fe_sc_vld_ra_ri = 0;
-
 		/* The txbd's baseinfo of DESC_TYPE_PAGE & DESC_TYPE_SKB */
 		desc_cb->priv = priv;
 		desc_cb->dma = dma + HNS3_MAX_BD_SIZE * k;
@@ -1170,12 +1159,10 @@
 		desc->addr = cpu_to_le64(dma + HNS3_MAX_BD_SIZE * k);
 		desc->tx.send_size = cpu_to_le16((k == frag_buf_num - 1) ?
 				     (u16)sizeoflast : (u16)HNS3_MAX_BD_SIZE);
-		hns3_set_txbd_baseinfo(&bdtp_fe_sc_vld_ra_ri,
-				       frag_end && (k == frag_buf_num - 1) ?
-						1 : 0);
 		desc->tx.bdtp_fe_sc_vld_ra_ri =
-				cpu_to_le16(bdtp_fe_sc_vld_ra_ri);
+				cpu_to_le16(BIT(HNS3_TXD_VLD_B));
 
+		trace_hns3_tx_desc(ring, ring->next_to_use);
 		/* move ring pointer to next */
 		ring_ptr_move_fw(ring, next_to_use);
 
@@ -1183,23 +1170,78 @@
 		desc = &ring->desc[ring->next_to_use];
 	}
 
-	return 0;
+	return frag_buf_num;
 }
 
-static unsigned int hns3_nic_bd_num(struct sk_buff *skb)
+static unsigned int hns3_skb_bd_num(struct sk_buff *skb, unsigned int *bd_size,
+				    unsigned int bd_num)
 {
-	unsigned int bd_num;
+	unsigned int size;
 	int i;
 
-	/* if the total len is within the max bd limit */
-	if (likely(skb->len <= HNS3_MAX_BD_SIZE))
-		return skb_shinfo(skb)->nr_frags + 1;
+	size = skb_headlen(skb);
+	while (size > HNS3_MAX_BD_SIZE) {
+		bd_size[bd_num++] = HNS3_MAX_BD_SIZE;
+		size -= HNS3_MAX_BD_SIZE;
+
+		if (bd_num > HNS3_MAX_TSO_BD_NUM)
+			return bd_num;
+	}
 
-	bd_num = hns3_tx_bd_count(skb_headlen(skb));
+	if (size) {
+		bd_size[bd_num++] = size;
+		if (bd_num > HNS3_MAX_TSO_BD_NUM)
+			return bd_num;
+	}
 
 	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
 		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-		bd_num += hns3_tx_bd_count(skb_frag_size(frag));
+		size = skb_frag_size(frag);
+		if (!size)
+			continue;
+
+		while (size > HNS3_MAX_BD_SIZE) {
+			bd_size[bd_num++] = HNS3_MAX_BD_SIZE;
+			size -= HNS3_MAX_BD_SIZE;
+
+			if (bd_num > HNS3_MAX_TSO_BD_NUM)
+				return bd_num;
+		}
+
+		bd_size[bd_num++] = size;
+		if (bd_num > HNS3_MAX_TSO_BD_NUM)
+			return bd_num;
+	}
+
+	return bd_num;
+}
+
+static unsigned int hns3_tx_bd_num(struct sk_buff *skb, unsigned int *bd_size)
+{
+	struct sk_buff *frag_skb;
+	unsigned int bd_num = 0;
+
+	/* If the total len is within the max bd limit */
+	if (likely(skb->len <= HNS3_MAX_BD_SIZE && !skb_has_frag_list(skb) &&
+		   skb_shinfo(skb)->nr_frags < HNS3_MAX_NON_TSO_BD_NUM))
+		return skb_shinfo(skb)->nr_frags + 1U;
+
+	/* The below case will always be linearized, return
+	 * HNS3_MAX_BD_NUM_TSO + 1U to make sure it is linearized.
+	 */
+	if (unlikely(skb->len > HNS3_MAX_TSO_SIZE ||
+		     (!skb_is_gso(skb) && skb->len > HNS3_MAX_NON_TSO_SIZE)))
+		return HNS3_MAX_TSO_BD_NUM + 1U;
+
+	bd_num = hns3_skb_bd_num(skb, bd_size, bd_num);
+
+	if (!skb_has_frag_list(skb) || bd_num > HNS3_MAX_TSO_BD_NUM)
+		return bd_num;
+
+	skb_walk_frags(skb, frag_skb) {
+		bd_num = hns3_skb_bd_num(frag_skb, bd_size, bd_num);
+		if (bd_num > HNS3_MAX_TSO_BD_NUM)
+			return bd_num;
 	}
 
 	return bd_num;
@@ -1218,26 +1260,26 @@
  * 7 frags to to be larger than gso header len + mss, and the remaining
  * continuous 7 frags to be larger than MSS except the last 7 frags.
  */
-static bool hns3_skb_need_linearized(struct sk_buff *skb)
+static bool hns3_skb_need_linearized(struct sk_buff *skb, unsigned int *bd_size,
+				     unsigned int bd_num)
 {
-	int bd_limit = HNS3_MAX_BD_NUM_NORMAL - 1;
 	unsigned int tot_len = 0;
 	int i;
 
-	for (i = 0; i < bd_limit; i++)
-		tot_len += skb_frag_size(&skb_shinfo(skb)->frags[i]);
+	for (i = 0; i < HNS3_MAX_NON_TSO_BD_NUM - 1U; i++)
+		tot_len += bd_size[i];
 
-	/* ensure headlen + the first 7 frags is greater than mss + header
-	 * and the first 7 frags is greater than mss.
-	 */
-	if (((tot_len + skb_headlen(skb)) < (skb_shinfo(skb)->gso_size +
-	    hns3_gso_hdr_len(skb))) || (tot_len < skb_shinfo(skb)->gso_size))
+	/* ensure the first 8 frags is greater than mss + header */
+	if (tot_len + bd_size[HNS3_MAX_NON_TSO_BD_NUM - 1U] <
+	    skb_shinfo(skb)->gso_size + hns3_gso_hdr_len(skb))
 		return true;
 
-	/* ensure the remaining continuous 7 buffer is greater than mss */
-	for (i = 0; i < (skb_shinfo(skb)->nr_frags - bd_limit - 1); i++) {
-		tot_len -= skb_frag_size(&skb_shinfo(skb)->frags[i]);
-		tot_len += skb_frag_size(&skb_shinfo(skb)->frags[i + bd_limit]);
+	/* ensure every continuous 7 buffer is greater than mss
+	 * except the last one.
+	 */
+	for (i = 0; i < bd_num - HNS3_MAX_NON_TSO_BD_NUM; i++) {
+		tot_len -= bd_size[i];
+		tot_len += bd_size[i + HNS3_MAX_NON_TSO_BD_NUM - 1U];
 
 		if (tot_len < skb_shinfo(skb)->gso_size)
 			return true;
@@ -1246,31 +1288,40 @@
 	return false;
 }
 
+void hns3_shinfo_pack(struct skb_shared_info *shinfo, __u32 *size)
+{
+	int i = 0;
+
+	for (i = 0; i < MAX_SKB_FRAGS; i++)
+		size[i] = skb_frag_size(&shinfo->frags[i]);
+}
+
 static int hns3_nic_maybe_stop_tx(struct hns3_enet_ring *ring,
-				  struct sk_buff **out_skb)
+				  struct net_device *netdev,
+				  struct sk_buff *skb)
 {
-	struct sk_buff *skb = *out_skb;
+	struct hns3_nic_priv *priv = netdev_priv(netdev);
+	unsigned int bd_size[HNS3_MAX_TSO_BD_NUM + 1U];
 	unsigned int bd_num;
 
-	bd_num = hns3_nic_bd_num(skb);
-	if (unlikely(bd_num > HNS3_MAX_BD_NUM_NORMAL)) {
-		struct sk_buff *new_skb;
-
-		if (skb_is_gso(skb) && bd_num <= HNS3_MAX_BD_NUM_TSO &&
-		    !hns3_skb_need_linearized(skb))
+	bd_num = hns3_tx_bd_num(skb, bd_size);
+	if (unlikely(bd_num > HNS3_MAX_NON_TSO_BD_NUM)) {
+		if (bd_num <= HNS3_MAX_TSO_BD_NUM && skb_is_gso(skb) &&
+		    !hns3_skb_need_linearized(skb, bd_size, bd_num)) {
+			trace_hns3_over_8bd(skb);
 			goto out;
+		}
 
-		/* manual split the send packet */
-		new_skb = skb_copy(skb, GFP_ATOMIC);
-		if (!new_skb)
+		if (__skb_linearize(skb))
 			return -ENOMEM;
-		dev_kfree_skb_any(skb);
-		*out_skb = new_skb;
 
-		bd_num = hns3_nic_bd_num(new_skb);
-		if ((skb_is_gso(new_skb) && bd_num > HNS3_MAX_BD_NUM_TSO) ||
-		    (!skb_is_gso(new_skb) && bd_num > HNS3_MAX_BD_NUM_NORMAL))
+		bd_num = hns3_tx_bd_count(skb->len);
+		if ((skb_is_gso(skb) && bd_num > HNS3_MAX_TSO_BD_NUM) ||
+		    (!skb_is_gso(skb) &&
+		     bd_num > HNS3_MAX_NON_TSO_BD_NUM)) {
+			trace_hns3_over_8bd(skb);
 			return -ENOMEM;
+		}
 
 		u64_stats_update_begin(&ring->syncp);
 		ring->stats.tx_copy++;
@@ -1278,10 +1329,23 @@
 	}
 
 out:
-	if (unlikely(ring_space(ring) < bd_num))
-		return -EBUSY;
+	if (likely(ring_space(ring) >= bd_num))
+		return bd_num;
 
-	return bd_num;
+	netif_stop_subqueue(netdev, ring->queue_index);
+	smp_mb(); /* Memory barrier before checking ring_space */
+
+	/* Start queue in case hns3_clean_tx_ring has just made room
+	 * available and has not seen the queue stopped state performed
+	 * by netif_stop_subqueue above.
+	 */
+	if (ring_space(ring) >= bd_num && netif_carrier_ok(netdev) &&
+	    !test_bit(HNS3_NIC_STATE_DOWN, &priv->state)) {
+		netif_start_subqueue(netdev, ring->queue_index);
+		return bd_num;
+	}
+
+	return -EBUSY;
 }
 
 static void hns3_clear_desc(struct hns3_enet_ring *ring, int next_to_use_orig)
@@ -1290,6 +1354,10 @@
 	unsigned int i;
 
 	for (i = 0; i < ring->desc_num; i++) {
+		struct hns3_desc *desc = &ring->desc[ring->next_to_use];
+
+		memset(desc, 0, sizeof(*desc));
+
 		/* check if this is where we started */
 		if (ring->next_to_use == next_to_use_orig)
 			break;
@@ -1297,6 +1365,9 @@
 		/* rollback one */
 		ring_ptr_move_bw(ring, next_to_use);
 
+		if (!ring->desc_cb[ring->next_to_use].dma)
+			continue;
+
 		/* unmap the descriptor dma address */
 		if (ring->desc_cb[ring->next_to_use].type == DESC_TYPE_SKB)
 			dma_unmap_single(dev,
@@ -1311,76 +1382,107 @@
 
 		ring->desc_cb[ring->next_to_use].length = 0;
 		ring->desc_cb[ring->next_to_use].dma = 0;
+		ring->desc_cb[ring->next_to_use].type = DESC_TYPE_UNKNOWN;
 	}
 }
 
+static int hns3_fill_skb_to_desc(struct hns3_enet_ring *ring,
+				 struct sk_buff *skb, enum hns_desc_type type)
+{
+	unsigned int size = skb_headlen(skb);
+	int i, ret, bd_num = 0;
+
+	if (size) {
+		ret = hns3_fill_desc(ring, skb, size, type);
+		if (unlikely(ret < 0))
+			return ret;
+
+		bd_num += ret;
+	}
+
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+		size = skb_frag_size(frag);
+		if (!size)
+			continue;
+
+		ret = hns3_fill_desc(ring, frag, size, DESC_TYPE_PAGE);
+		if (unlikely(ret < 0))
+			return ret;
+
+		bd_num += ret;
+	}
+
+	return bd_num;
+}
+
 netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev)
 {
 	struct hns3_nic_priv *priv = netdev_priv(netdev);
-	struct hns3_nic_ring_data *ring_data =
-		&tx_ring_data(priv, skb->queue_mapping);
-	struct hns3_enet_ring *ring = ring_data->ring;
+	struct hns3_enet_ring *ring = &priv->ring[skb->queue_mapping];
 	struct netdev_queue *dev_queue;
-	skb_frag_t *frag;
-	int next_to_use_head;
-	int buf_num;
-	int seg_num;
-	int size;
+	int pre_ntu, next_to_use_head;
+	struct sk_buff *frag_skb;
+	int bd_num = 0;
 	int ret;
-	int i;
+
+	/* Hardware can only handle short frames above 32 bytes */
+	if (skb_put_padto(skb, HNS3_MIN_TX_LEN))
+		return NETDEV_TX_OK;
 
 	/* Prefetch the data used later */
 	prefetch(skb->data);
 
-	buf_num = hns3_nic_maybe_stop_tx(ring, &skb);
-	if (unlikely(buf_num <= 0)) {
-		if (buf_num == -EBUSY) {
+	ret = hns3_nic_maybe_stop_tx(ring, netdev, skb);
+	if (unlikely(ret <= 0)) {
+		if (ret == -EBUSY) {
 			u64_stats_update_begin(&ring->syncp);
 			ring->stats.tx_busy++;
 			u64_stats_update_end(&ring->syncp);
-			goto out_net_tx_busy;
-		} else if (buf_num == -ENOMEM) {
+			return NETDEV_TX_BUSY;
+		} else if (ret == -ENOMEM) {
 			u64_stats_update_begin(&ring->syncp);
 			ring->stats.sw_err_cnt++;
 			u64_stats_update_end(&ring->syncp);
 		}
 
-		hns3_rl_err(netdev, "xmit error: %d!\n", buf_num);
+		hns3_rl_err(netdev, "xmit error: %d!\n", ret);
 		goto out_err_tx_ok;
 	}
 
-	/* No. of segments (plus a header) */
-	seg_num = skb_shinfo(skb)->nr_frags + 1;
-	/* Fill the first part */
-	size = skb_headlen(skb);
-
 	next_to_use_head = ring->next_to_use;
 
-	ret = hns3_fill_desc(ring, skb, size, seg_num == 1 ? 1 : 0,
-			     DESC_TYPE_SKB);
-	if (unlikely(ret))
+	ret = hns3_fill_skb_to_desc(ring, skb, DESC_TYPE_SKB);
+	if (unlikely(ret < 0))
 		goto fill_err;
 
-	/* Fill the fragments */
-	for (i = 1; i < seg_num; i++) {
-		frag = &skb_shinfo(skb)->frags[i - 1];
-		size = skb_frag_size(frag);
+	bd_num += ret;
 
-		ret = hns3_fill_desc(ring, frag, size,
-				     seg_num - 1 == i ? 1 : 0,
-				     DESC_TYPE_PAGE);
+	if (!skb_has_frag_list(skb))
+		goto out;
 
-		if (unlikely(ret))
+	skb_walk_frags(skb, frag_skb) {
+		ret = hns3_fill_skb_to_desc(ring, frag_skb, DESC_TYPE_PAGE);
+		if (unlikely(ret < 0))
 			goto fill_err;
+
+		bd_num += ret;
 	}
+out:
+	pre_ntu = ring->next_to_use ? (ring->next_to_use - 1) :
+					(ring->desc_num - 1);
+	ring->desc[pre_ntu].tx.bdtp_fe_sc_vld_ra_ri |=
+				cpu_to_le16(BIT(HNS3_TXD_FE_B));
+	trace_hns3_tx_desc(ring, pre_ntu);
 
 	/* Complete translate all packets */
-	dev_queue = netdev_get_tx_queue(netdev, ring_data->queue_index);
+	dev_queue = netdev_get_tx_queue(netdev, ring->queue_index);
 	netdev_tx_sent_queue(dev_queue, skb->len);
 
 	wmb(); /* Commit all data before submit */
 
-	hnae3_queue_xmit(ring->tqp, buf_num);
+	hnae3_queue_xmit(ring->tqp, bd_num);
 
 	return NETDEV_TX_OK;
 
@@ -1390,12 +1492,6 @@
 out_err_tx_ok:
 	dev_kfree_skb_any(skb);
 	return NETDEV_TX_OK;
-
-out_net_tx_busy:
-	netif_stop_subqueue(netdev, ring_data->queue_index);
-	smp_mb(); /* Commit all data before submit */
-
-	return NETDEV_TX_BUSY;
 }
 
 static int hns3_nic_net_set_mac_address(struct net_device *netdev, void *p)
@@ -1413,6 +1509,16 @@
 		return 0;
 	}
 
+	/* For VF device, if there is a perm_addr, then the user will not
+	 * be allowed to change the address.
+	 */
+	if (!hns3_is_phys_func(h->pdev) &&
+	    !is_zero_ether_addr(netdev->perm_addr)) {
+		netdev_err(netdev, "has permanent MAC %pM, user MAC %pM not allow\n",
+			   netdev->perm_addr, mac_addr->sa_data);
+		return -EPERM;
+	}
+
 	ret = h->ae_algo->ops->set_mac_addr(h, mac_addr->sa_data, false);
 	if (ret) {
 		netdev_err(netdev, "set_mac_address fail, ret=%d!\n", ret);
@@ -1477,6 +1583,37 @@
 	return 0;
 }
 
+static netdev_features_t hns3_features_check(struct sk_buff *skb,
+					     struct net_device *dev,
+					     netdev_features_t features)
+{
+#define HNS3_MAX_HDR_LEN	480U
+#define HNS3_MAX_L4_HDR_LEN	60U
+
+	size_t len;
+
+	if (skb->ip_summed != CHECKSUM_PARTIAL)
+		return features;
+
+	if (skb->encapsulation)
+		len = skb_inner_transport_header(skb) - skb->data;
+	else
+		len = skb_transport_header(skb) - skb->data;
+
+	/* Assume L4 is 60 byte as TCP is the only protocol with a
+	 * a flexible value, and it's max len is 60 bytes.
+	 */
+	len += HNS3_MAX_L4_HDR_LEN;
+
+	/* Hardware only supports checksum on the skb with a max header
+	 * len of 480 bytes.
+	 */
+	if (len > HNS3_MAX_HDR_LEN)
+		features &= ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
+
+	return features;
+}
+
 static void hns3_nic_get_stats64(struct net_device *netdev,
 				 struct rtnl_link_stats64 *stats)
 {
@@ -1505,7 +1642,7 @@
 
 	for (idx = 0; idx < queue_num; idx++) {
 		/* fetch the tx stats */
-		ring = priv->ring_data[idx].ring;
+		ring = &priv->ring[idx];
 		do {
 			start = u64_stats_fetch_begin_irq(&ring->syncp);
 			tx_bytes += ring->stats.tx_bytes;
@@ -1523,7 +1660,7 @@
 		} while (u64_stats_fetch_retry_irq(&ring->syncp, start));
 
 		/* fetch the rx stats */
-		ring = priv->ring_data[idx + queue_num].ring;
+		ring = &priv->ring[idx + queue_num];
 		do {
 			start = u64_stats_fetch_begin_irq(&ring->syncp);
 			rx_bytes += ring->stats.rx_bytes;
@@ -1590,7 +1727,7 @@
 	netif_dbg(h, drv, netdev, "setup tc: num_tc=%u\n", tc);
 
 	return (kinfo->dcb_ops && kinfo->dcb_ops->setup_tc) ?
-		kinfo->dcb_ops->setup_tc(h, tc, prio_tc) : -EOPNOTSUPP;
+		kinfo->dcb_ops->setup_tc(h, tc ? tc : 1, prio_tc) : -EOPNOTSUPP;
 }
 
 static int hns3_nic_setup_tc(struct net_device *dev, enum tc_setup_type type,
@@ -1633,8 +1770,8 @@
 	int ret = -EIO;
 
 	netif_dbg(h, drv, netdev,
-		  "set vf vlan: vf=%d, vlan=%u, qos=%u, vlan_proto=%u\n",
-		  vf, vlan, qos, vlan_proto);
+		  "set vf vlan: vf=%d, vlan=%u, qos=%u, vlan_proto=0x%x\n",
+		  vf, vlan, qos, ntohs(vlan_proto));
 
 	if (h->ae_algo->ops->set_vf_vlan_filter)
 		ret = h->ae_algo->ops->set_vf_vlan_filter(h, vf, vlan,
@@ -1643,6 +1780,29 @@
 	return ret;
 }
 
+static int hns3_set_vf_spoofchk(struct net_device *netdev, int vf, bool enable)
+{
+	struct hnae3_handle *handle = hns3_get_handle(netdev);
+
+	if (hns3_nic_resetting(netdev))
+		return -EBUSY;
+
+	if (!handle->ae_algo->ops->set_vf_spoofchk)
+		return -EOPNOTSUPP;
+
+	return handle->ae_algo->ops->set_vf_spoofchk(handle, vf, enable);
+}
+
+static int hns3_set_vf_trust(struct net_device *netdev, int vf, bool enable)
+{
+	struct hnae3_handle *handle = hns3_get_handle(netdev);
+
+	if (!handle->ae_algo->ops->set_vf_trust)
+		return -EOPNOTSUPP;
+
+	return handle->ae_algo->ops->set_vf_trust(handle, vf, enable);
+}
+
 static int hns3_nic_change_mtu(struct net_device *netdev, int new_mtu)
 {
 	struct hnae3_handle *h = hns3_get_handle(netdev);
@@ -1671,7 +1831,7 @@
 {
 	struct hns3_nic_priv *priv = netdev_priv(ndev);
 	struct hnae3_handle *h = hns3_get_handle(ndev);
-	struct hns3_enet_ring *tx_ring = NULL;
+	struct hns3_enet_ring *tx_ring;
 	struct napi_struct *napi;
 	int timeout_queue = 0;
 	int hw_head, hw_tail;
@@ -1692,6 +1852,9 @@
 		    time_after(jiffies,
 			       (trans_start + ndev->watchdog_timeo))) {
 			timeout_queue = i;
+			netdev_info(ndev, "queue state: 0x%lx, delta msecs: %u\n",
+				    q->state,
+				    jiffies_to_msecs(jiffies - trans_start));
 			break;
 		}
 	}
@@ -1705,7 +1868,7 @@
 
 	priv->tx_timeout_count++;
 
-	tx_ring = priv->ring_data[timeout_queue].ring;
+	tx_ring = &priv->ring[timeout_queue];
 	napi = &tx_ring->tqp_vector->napi;
 
 	netdev_info(ndev,
@@ -1805,6 +1968,57 @@
 }
 #endif
 
+static int hns3_nic_get_vf_config(struct net_device *ndev, int vf,
+				  struct ifla_vf_info *ivf)
+{
+	struct hnae3_handle *h = hns3_get_handle(ndev);
+
+	if (!h->ae_algo->ops->get_vf_config)
+		return -EOPNOTSUPP;
+
+	return h->ae_algo->ops->get_vf_config(h, vf, ivf);
+}
+
+static int hns3_nic_set_vf_link_state(struct net_device *ndev, int vf,
+				      int link_state)
+{
+	struct hnae3_handle *h = hns3_get_handle(ndev);
+
+	if (!h->ae_algo->ops->set_vf_link_state)
+		return -EOPNOTSUPP;
+
+	return h->ae_algo->ops->set_vf_link_state(h, vf, link_state);
+}
+
+static int hns3_nic_set_vf_rate(struct net_device *ndev, int vf,
+				int min_tx_rate, int max_tx_rate)
+{
+	struct hnae3_handle *h = hns3_get_handle(ndev);
+
+	if (!h->ae_algo->ops->set_vf_rate)
+		return -EOPNOTSUPP;
+
+	return h->ae_algo->ops->set_vf_rate(h, vf, min_tx_rate, max_tx_rate,
+					    false);
+}
+
+static int hns3_nic_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
+{
+	struct hnae3_handle *h = hns3_get_handle(netdev);
+
+	if (!h->ae_algo->ops->set_vf_mac)
+		return -EOPNOTSUPP;
+
+	if (is_multicast_ether_addr(mac)) {
+		netdev_err(netdev,
+			   "Invalid MAC:%pM specified. Could not set MAC\n",
+			   mac);
+		return -EINVAL;
+	}
+
+	return h->ae_algo->ops->set_vf_mac(h, vf_id, mac);
+}
+
 static const struct net_device_ops hns3_nic_netdev_ops = {
 	.ndo_open		= hns3_nic_net_open,
 	.ndo_stop		= hns3_nic_net_stop,
@@ -1814,16 +2028,22 @@
 	.ndo_do_ioctl		= hns3_nic_do_ioctl,
 	.ndo_change_mtu		= hns3_nic_change_mtu,
 	.ndo_set_features	= hns3_nic_set_features,
+	.ndo_features_check	= hns3_features_check,
 	.ndo_get_stats64	= hns3_nic_get_stats64,
 	.ndo_setup_tc		= hns3_nic_setup_tc,
 	.ndo_set_rx_mode	= hns3_nic_set_rx_mode,
 	.ndo_vlan_rx_add_vid	= hns3_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid	= hns3_vlan_rx_kill_vid,
 	.ndo_set_vf_vlan	= hns3_ndo_set_vf_vlan,
+	.ndo_set_vf_spoofchk	= hns3_set_vf_spoofchk,
+	.ndo_set_vf_trust	= hns3_set_vf_trust,
 #ifdef CONFIG_RFS_ACCEL
 	.ndo_rx_flow_steer	= hns3_rx_flow_steer,
 #endif
-
+	.ndo_get_vf_config	= hns3_nic_get_vf_config,
+	.ndo_set_vf_link_state	= hns3_nic_set_vf_link_state,
+	.ndo_set_vf_rate	= hns3_nic_set_vf_rate,
+	.ndo_set_vf_mac		= hns3_nic_set_vf_mac,
 };
 
 bool hns3_is_phys_func(struct pci_dev *pdev)
@@ -1843,7 +2063,7 @@
 	case HNAE3_DEV_ID_100G_RDMA_DCB_PFC_VF:
 		return false;
 	default:
-		dev_warn(&pdev->dev, "un-recognized pci device-id %d",
+		dev_warn(&pdev->dev, "un-recognized pci device-id %u",
 			 dev_id);
 	}
 
@@ -2026,7 +2246,7 @@
 {
 	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);
 
-	dev_info(&pdev->dev, "hns3 flr prepare\n");
+	dev_info(&pdev->dev, "FLR prepare\n");
 	if (ae_dev && ae_dev->ops && ae_dev->ops->flr_prepare)
 		ae_dev->ops->flr_prepare(ae_dev);
 }
@@ -2035,7 +2255,7 @@
 {
 	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);
 
-	dev_info(&pdev->dev, "hns3 flr done\n");
+	dev_info(&pdev->dev, "FLR done\n");
 	if (ae_dev && ae_dev->ops && ae_dev->ops->flr_done)
 		ae_dev->ops->flr_done(ae_dev);
 }
@@ -2069,9 +2289,8 @@
 		NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_GSO |
 		NETIF_F_GRO | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_GSO_GRE |
 		NETIF_F_GSO_GRE_CSUM | NETIF_F_GSO_UDP_TUNNEL |
-		NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_SCTP_CRC;
-
-	netdev->hw_enc_features |= NETIF_F_TSO_MANGLEID;
+		NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_SCTP_CRC |
+		NETIF_F_TSO_MANGLEID | NETIF_F_FRAGLIST;
 
 	netdev->gso_partial_features |= NETIF_F_GSO_GRE_CSUM;
 
@@ -2081,21 +2300,24 @@
 		NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_GSO |
 		NETIF_F_GRO | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_GSO_GRE |
 		NETIF_F_GSO_GRE_CSUM | NETIF_F_GSO_UDP_TUNNEL |
-		NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_SCTP_CRC;
+		NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_SCTP_CRC |
+		NETIF_F_FRAGLIST;
 
 	netdev->vlan_features |=
 		NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM |
 		NETIF_F_SG | NETIF_F_GSO | NETIF_F_GRO |
 		NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_GSO_GRE |
 		NETIF_F_GSO_GRE_CSUM | NETIF_F_GSO_UDP_TUNNEL |
-		NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_SCTP_CRC;
+		NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_SCTP_CRC |
+		NETIF_F_FRAGLIST;
 
 	netdev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
 		NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
 		NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_GSO |
 		NETIF_F_GRO | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_GSO_GRE |
 		NETIF_F_GSO_GRE_CSUM | NETIF_F_GSO_UDP_TUNNEL |
-		NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_SCTP_CRC;
+		NETIF_F_GSO_UDP_TUNNEL_CSUM | NETIF_F_SCTP_CRC |
+		NETIF_F_FRAGLIST;
 
 	if (pdev->revision >= 0x21) {
 		netdev->hw_features |= NETIF_F_GRO_HW;
@@ -2320,21 +2542,22 @@
 
 void hns3_clean_tx_ring(struct hns3_enet_ring *ring)
 {
-	struct net_device *netdev = ring->tqp->handle->kinfo.netdev;
+	struct net_device *netdev = ring_to_netdev(ring);
 	struct hns3_nic_priv *priv = netdev_priv(netdev);
 	struct netdev_queue *dev_queue;
 	int bytes, pkts;
 	int head;
 
 	head = readl_relaxed(ring->tqp->io_base + HNS3_RING_TX_RING_HEAD_REG);
-	rmb(); /* Make sure head is ready before touch any data */
 
 	if (is_ring_empty(ring) || head == ring->next_to_clean)
 		return; /* no data to poll */
 
+	rmb(); /* Make sure head is ready before touch any data */
+
 	if (unlikely(!is_valid_clean_head(ring, head))) {
-		netdev_err(netdev, "wrong head (%d, %d-%d)\n", head,
-			   ring->next_to_use, ring->next_to_clean);
+		hns3_rl_err(netdev, "wrong head (%d, %d-%d)\n", head,
+			    ring->next_to_use, ring->next_to_clean);
 
 		u64_stats_update_begin(&ring->syncp);
 		ring->stats.io_err_cnt++;
@@ -2357,8 +2580,8 @@
 	dev_queue = netdev_get_tx_queue(netdev, ring->tqp->tqp_index);
 	netdev_tx_completed_queue(dev_queue, pkts, bytes);
 
-	if (unlikely(pkts && netif_carrier_ok(netdev) &&
-		     (ring_space(ring) > HNS3_MAX_BD_PER_PKT))) {
+	if (unlikely(netif_carrier_ok(netdev) &&
+		     ring_space(ring) > HNS3_MAX_TSO_BD_NUM)) {
 		/* Make sure that anybody stopping the queue after this
 		 * sees the new next_to_clean.
 		 */
@@ -2401,7 +2624,7 @@
 				ring->stats.sw_err_cnt++;
 				u64_stats_update_end(&ring->syncp);
 
-				hns3_rl_err(ring->tqp_vector->napi.dev,
+				hns3_rl_err(ring_to_netdev(ring),
 					    "alloc rx buffer failed: %d\n",
 					    ret);
 				break;
@@ -2420,6 +2643,12 @@
 	writel_relaxed(i, ring->tqp->io_base + HNS3_RING_RX_RING_HEAD_REG);
 }
 
+static bool hns3_page_is_reusable(struct page *page)
+{
+	return page_to_nid(page) == numa_mem_id() &&
+		!page_is_pfmemalloc(page);
+}
+
 static void hns3_nic_reuse_page(struct sk_buff *skb, int i,
 				struct hns3_enet_ring *ring, int pull_len,
 				struct hns3_desc_cb *desc_cb)
@@ -2434,7 +2663,7 @@
 	/* Avoid re-using remote pages, or the stack is still using the page
 	 * when page_offset rollback to zero, flag default unreuse
 	 */
-	if (unlikely(page_to_nid(desc_cb->priv) != numa_mem_id()) ||
+	if (unlikely(!hns3_page_is_reusable(desc_cb->priv)) ||
 	    (!desc_cb->page_offset && page_count(desc_cb->priv) > 1))
 		return;
 
@@ -2504,13 +2733,16 @@
 	skb->csum_start = (unsigned char *)th - skb->head;
 	skb->csum_offset = offsetof(struct tcphdr, check);
 	skb->ip_summed = CHECKSUM_PARTIAL;
+
+	trace_hns3_gro(skb);
+
 	return 0;
 }
 
 static void hns3_rx_checksum(struct hns3_enet_ring *ring, struct sk_buff *skb,
 			     u32 l234info, u32 bd_base_info, u32 ol_info)
 {
-	struct net_device *netdev = ring->tqp->handle->kinfo.netdev;
+	struct net_device *netdev = ring_to_netdev(ring);
 	int l3_type, l4_type;
 	int ol4_type;
 
@@ -2624,9 +2856,8 @@
 static int hns3_alloc_skb(struct hns3_enet_ring *ring, unsigned int length,
 			  unsigned char *va)
 {
-#define HNS3_NEED_ADD_FRAG	1
 	struct hns3_desc_cb *desc_cb = &ring->desc_cb[ring->next_to_clean];
-	struct net_device *netdev = ring->tqp->handle->kinfo.netdev;
+	struct net_device *netdev = ring_to_netdev(ring);
 	struct sk_buff *skb;
 
 	ring->skb = napi_alloc_skb(&ring->tqp_vector->napi, HNS3_RX_HEAD_SIZE);
@@ -2641,6 +2872,7 @@
 		return -ENOMEM;
 	}
 
+	trace_hns3_rx_desc(ring);
 	prefetchw(skb->data);
 
 	ring->pending_buf = 1;
@@ -2650,7 +2882,7 @@
 		memcpy(__skb_put(skb, length), va, ALIGN(length, sizeof(long)));
 
 		/* We can reuse buffer as-is, just make sure it is local */
-		if (likely(page_to_nid(desc_cb->priv) == numa_mem_id()))
+		if (likely(hns3_page_is_reusable(desc_cb->priv)))
 			desc_cb->reuse_flag = 1;
 		else /* This page cannot be reused so discard it */
 			put_page(desc_cb->priv);
@@ -2668,33 +2900,19 @@
 			    desc_cb);
 	ring_ptr_move_fw(ring, next_to_clean);
 
-	return HNS3_NEED_ADD_FRAG;
+	return 0;
 }
 
-static int hns3_add_frag(struct hns3_enet_ring *ring, struct hns3_desc *desc,
-			 struct sk_buff **out_skb, bool pending)
+static int hns3_add_frag(struct hns3_enet_ring *ring)
 {
-	struct sk_buff *skb = *out_skb;
-	struct sk_buff *head_skb = *out_skb;
+	struct sk_buff *skb = ring->skb;
+	struct sk_buff *head_skb = skb;
 	struct sk_buff *new_skb;
 	struct hns3_desc_cb *desc_cb;
-	struct hns3_desc *pre_desc;
+	struct hns3_desc *desc;
 	u32 bd_base_info;
-	int pre_bd;
-
-	/* if there is pending bd, the SW param next_to_clean has moved
-	 * to next and the next is NULL
-	 */
-	if (pending) {
-		pre_bd = (ring->next_to_clean - 1 + ring->desc_num) %
-			 ring->desc_num;
-		pre_desc = &ring->desc[pre_bd];
-		bd_base_info = le32_to_cpu(pre_desc->rx.bd_base_info);
-	} else {
-		bd_base_info = le32_to_cpu(desc->rx.bd_base_info);
-	}
 
-	while (!(bd_base_info & BIT(HNS3_RXD_FE_B))) {
+	do {
 		desc = &ring->desc[ring->next_to_clean];
 		desc_cb = &ring->desc_cb[ring->next_to_clean];
 		bd_base_info = le32_to_cpu(desc->rx.bd_base_info);
@@ -2704,10 +2922,9 @@
 			return -ENXIO;
 
 		if (unlikely(ring->frag_num >= MAX_SKB_FRAGS)) {
-			new_skb = napi_alloc_skb(&ring->tqp_vector->napi,
-						 HNS3_RX_HEAD_SIZE);
+			new_skb = napi_alloc_skb(&ring->tqp_vector->napi, 0);
 			if (unlikely(!new_skb)) {
-				hns3_rl_err(ring->tqp_vector->napi.dev,
+				hns3_rl_err(ring_to_netdev(ring),
 					    "alloc rx fraglist skb fail\n");
 				return -ENXIO;
 			}
@@ -2730,9 +2947,10 @@
 		}
 
 		hns3_nic_reuse_page(skb, ring->frag_num++, ring, 0, desc_cb);
+		trace_hns3_rx_desc(ring);
 		ring_ptr_move_fw(ring, next_to_clean);
 		ring->pending_buf++;
-	}
+	} while (!(bd_base_info & BIT(HNS3_RXD_FE_B)));
 
 	return 0;
 }
@@ -2783,7 +3001,7 @@
 
 static int hns3_handle_bdinfo(struct hns3_enet_ring *ring, struct sk_buff *skb)
 {
-	struct net_device *netdev = ring->tqp->handle->kinfo.netdev;
+	struct net_device *netdev = ring_to_netdev(ring);
 	enum hns3_pkt_l2t_type l2_frame_type;
 	u32 bd_base_info, l234info, ol_info;
 	struct hns3_desc *desc;
@@ -2858,8 +3076,7 @@
 	return 0;
 }
 
-static int hns3_handle_rx_bd(struct hns3_enet_ring *ring,
-			     struct sk_buff **out_skb)
+static int hns3_handle_rx_bd(struct hns3_enet_ring *ring)
 {
 	struct sk_buff *skb = ring->skb;
 	struct hns3_desc_cb *desc_cb;
@@ -2897,32 +3114,27 @@
 
 	if (!skb) {
 		ret = hns3_alloc_skb(ring, length, ring->va);
-		*out_skb = skb = ring->skb;
+		skb = ring->skb;
 
 		if (ret < 0) /* alloc buffer fail */
 			return ret;
-		if (ret > 0) { /* need add frag */
-			ret = hns3_add_frag(ring, desc, &skb, false);
+		if (!(bd_base_info & BIT(HNS3_RXD_FE_B))) { /* need add frag */
+			ret = hns3_add_frag(ring);
 			if (ret)
 				return ret;
-
-			/* As the head data may be changed when GRO enable, copy
-			 * the head data in after other data rx completed
-			 */
-			memcpy(skb->data, ring->va,
-			       ALIGN(ring->pull_len, sizeof(long)));
 		}
 	} else {
-		ret = hns3_add_frag(ring, desc, &skb, true);
+		ret = hns3_add_frag(ring);
 		if (ret)
 			return ret;
+	}
 
-		/* As the head data may be changed when GRO enable, copy
-		 * the head data in after other data rx completed
-		 */
+	/* As the head data may be changed when GRO enable, copy
+	 * the head data in after other data rx completed
+	 */
+	if (skb->len > HNS3_RX_HEAD_SIZE)
 		memcpy(skb->data, ring->va,
 		       ALIGN(ring->pull_len, sizeof(long)));
-	}
 
 	ret = hns3_handle_bdinfo(ring, skb);
 	if (unlikely(ret)) {
@@ -2931,8 +3143,6 @@
 	}
 
 	skb_record_rx_queue(skb, ring->tqp->tqp_index);
-	*out_skb = skb;
-
 	return 0;
 }
 
@@ -2941,17 +3151,19 @@
 {
 #define RCB_NOF_ALLOC_RX_BUFF_ONCE 16
 	int unused_count = hns3_desc_unused(ring);
-	struct sk_buff *skb = ring->skb;
 	int recv_pkts = 0;
 	int recv_bds = 0;
 	int err, num;
 
 	num = readl_relaxed(ring->tqp->io_base + HNS3_RING_RX_RING_FBDNUM_REG);
-	rmb(); /* Make sure num taken effect before the other data is touched */
-
 	num -= unused_count;
 	unused_count -= ring->pending_buf;
 
+	if (num <= 0)
+		goto out;
+
+	rmb(); /* Make sure num taken effect before the other data is touched */
+
 	while (recv_pkts < budget && recv_bds < num) {
 		/* Reuse or realloc buffers */
 		if (unused_count >= RCB_NOF_ALLOC_RX_BUFF_ONCE) {
@@ -2961,27 +3173,19 @@
 		}
 
 		/* Poll one pkt */
-		err = hns3_handle_rx_bd(ring, &skb);
-		if (unlikely(!skb)) /* This fault cannot be repaired */
-			goto out;
-
-		if (err == -ENXIO) { /* Do not get FE for the packet */
+		err = hns3_handle_rx_bd(ring);
+		/* Do not get FE for the packet or failed to alloc skb */
+		if (unlikely(!ring->skb || err == -ENXIO)) {
 			goto out;
-		} else if (unlikely(err)) {  /* Do jump the err */
-			recv_bds += ring->pending_buf;
-			unused_count += ring->pending_buf;
-			ring->skb = NULL;
-			ring->pending_buf = 0;
-			continue;
+		} else if (likely(!err)) {
+			rx_fn(ring, ring->skb);
+			recv_pkts++;
 		}
 
-		rx_fn(ring, skb);
 		recv_bds += ring->pending_buf;
 		unused_count += ring->pending_buf;
 		ring->skb = NULL;
 		ring->pending_buf = 0;
-
-		recv_pkts++;
 	}
 
 out:
@@ -3303,7 +3507,6 @@
 
 static int hns3_nic_init_vector_data(struct hns3_nic_priv *priv)
 {
-	struct hnae3_ring_chain_node vector_ring_chain;
 	struct hnae3_handle *h = priv->ae_handle;
 	struct hns3_enet_tqp_vector *tqp_vector;
 	int ret = 0;
@@ -3324,17 +3527,19 @@
 		tqp_vector = &priv->tqp_vector[vector_i];
 
 		hns3_add_ring_to_group(&tqp_vector->tx_group,
-				       priv->ring_data[i].ring);
+				       &priv->ring[i]);
 
 		hns3_add_ring_to_group(&tqp_vector->rx_group,
-				       priv->ring_data[i + tqp_num].ring);
+				       &priv->ring[i + tqp_num]);
 
-		priv->ring_data[i].ring->tqp_vector = tqp_vector;
-		priv->ring_data[i + tqp_num].ring->tqp_vector = tqp_vector;
+		priv->ring[i].tqp_vector = tqp_vector;
+		priv->ring[i + tqp_num].tqp_vector = tqp_vector;
 		tqp_vector->num_tqps++;
 	}
 
 	for (i = 0; i < priv->vector_num; i++) {
+		struct hnae3_ring_chain_node vector_ring_chain;
+
 		tqp_vector = &priv->tqp_vector[i];
 
 		tqp_vector->rx_group.total_bytes = 0;
@@ -3436,26 +3641,25 @@
 		if (!tqp_vector->rx_group.ring && !tqp_vector->tx_group.ring)
 			continue;
 
-		hns3_get_vector_ring_chain(tqp_vector, &vector_ring_chain);
+		/* Since the mapping can be overwritten, when fail to get the
+		 * chain between vector and ring, we should go on to deal with
+		 * the remaining options.
+		 */
+		if (hns3_get_vector_ring_chain(tqp_vector, &vector_ring_chain))
+			dev_warn(priv->dev, "failed to get ring chain\n");
 
 		h->ae_algo->ops->unmap_ring_from_vector(h,
 			tqp_vector->vector_irq, &vector_ring_chain);
 
 		hns3_free_vector_ring_chain(tqp_vector, &vector_ring_chain);
 
-		if (tqp_vector->irq_init_flag == HNS3_VECTOR_INITED) {
-			irq_set_affinity_hint(tqp_vector->vector_irq, NULL);
-			free_irq(tqp_vector->vector_irq, tqp_vector);
-			tqp_vector->irq_init_flag = HNS3_VECTOR_NOT_INITED;
-		}
-
 		hns3_clear_ring_group(&tqp_vector->rx_group);
 		hns3_clear_ring_group(&tqp_vector->tx_group);
 		netif_napi_del(&priv->tqp_vector[i].napi);
 	}
 }
 
-static int hns3_nic_dealloc_vector_data(struct hns3_nic_priv *priv)
+static void hns3_nic_dealloc_vector_data(struct hns3_nic_priv *priv)
 {
 	struct hnae3_handle *h = priv->ae_handle;
 	struct pci_dev *pdev = h->pdev;
@@ -3467,35 +3671,28 @@
 		tqp_vector = &priv->tqp_vector[i];
 		ret = h->ae_algo->ops->put_vector(h, tqp_vector->vector_irq);
 		if (ret)
-			return ret;
+			return;
 	}
 
 	devm_kfree(&pdev->dev, priv->tqp_vector);
-	return 0;
 }
 
-static int hns3_ring_get_cfg(struct hnae3_queue *q, struct hns3_nic_priv *priv,
-			     unsigned int ring_type)
+static void hns3_ring_get_cfg(struct hnae3_queue *q, struct hns3_nic_priv *priv,
+			      unsigned int ring_type)
 {
-	struct hns3_nic_ring_data *ring_data = priv->ring_data;
 	int queue_num = priv->ae_handle->kinfo.num_tqps;
-	struct pci_dev *pdev = priv->ae_handle->pdev;
 	struct hns3_enet_ring *ring;
 	int desc_num;
 
-	ring = devm_kzalloc(&pdev->dev, sizeof(*ring), GFP_KERNEL);
-	if (!ring)
-		return -ENOMEM;
-
 	if (ring_type == HNAE3_RING_TYPE_TX) {
+		ring = &priv->ring[q->tqp_index];
 		desc_num = priv->ae_handle->kinfo.num_tx_desc;
-		ring_data[q->tqp_index].ring = ring;
-		ring_data[q->tqp_index].queue_index = q->tqp_index;
+		ring->queue_index = q->tqp_index;
 		ring->io_base = (u8 __iomem *)q->io_base + HNS3_TX_REG_OFFSET;
 	} else {
+		ring = &priv->ring[q->tqp_index + queue_num];
 		desc_num = priv->ae_handle->kinfo.num_rx_desc;
-		ring_data[q->tqp_index + queue_num].ring = ring;
-		ring_data[q->tqp_index + queue_num].queue_index = q->tqp_index;
+		ring->queue_index = q->tqp_index;
 		ring->io_base = q->io_base;
 	}
 
@@ -3510,76 +3707,41 @@
 	ring->desc_num = desc_num;
 	ring->next_to_use = 0;
 	ring->next_to_clean = 0;
-
-	return 0;
 }
 
-static int hns3_queue_to_ring(struct hnae3_queue *tqp,
-			      struct hns3_nic_priv *priv)
+static void hns3_queue_to_ring(struct hnae3_queue *tqp,
+			       struct hns3_nic_priv *priv)
 {
-	int ret;
-
-	ret = hns3_ring_get_cfg(tqp, priv, HNAE3_RING_TYPE_TX);
-	if (ret)
-		return ret;
-
-	ret = hns3_ring_get_cfg(tqp, priv, HNAE3_RING_TYPE_RX);
-	if (ret) {
-		devm_kfree(priv->dev, priv->ring_data[tqp->tqp_index].ring);
-		return ret;
-	}
-
-	return 0;
+	hns3_ring_get_cfg(tqp, priv, HNAE3_RING_TYPE_TX);
+	hns3_ring_get_cfg(tqp, priv, HNAE3_RING_TYPE_RX);
 }
 
 static int hns3_get_ring_config(struct hns3_nic_priv *priv)
 {
 	struct hnae3_handle *h = priv->ae_handle;
 	struct pci_dev *pdev = h->pdev;
-	int i, ret;
+	int i;
 
-	priv->ring_data =  devm_kzalloc(&pdev->dev,
-					array3_size(h->kinfo.num_tqps,
-						    sizeof(*priv->ring_data),
-						    2),
-					GFP_KERNEL);
-	if (!priv->ring_data)
+	priv->ring = devm_kzalloc(&pdev->dev,
+				  array3_size(h->kinfo.num_tqps,
+					      sizeof(*priv->ring), 2),
+				  GFP_KERNEL);
+	if (!priv->ring)
 		return -ENOMEM;
 
-	for (i = 0; i < h->kinfo.num_tqps; i++) {
-		ret = hns3_queue_to_ring(h->kinfo.tqp[i], priv);
-		if (ret)
-			goto err;
-	}
+	for (i = 0; i < h->kinfo.num_tqps; i++)
+		hns3_queue_to_ring(h->kinfo.tqp[i], priv);
 
 	return 0;
-err:
-	while (i--) {
-		devm_kfree(priv->dev, priv->ring_data[i].ring);
-		devm_kfree(priv->dev,
-			   priv->ring_data[i + h->kinfo.num_tqps].ring);
-	}
-
-	devm_kfree(&pdev->dev, priv->ring_data);
-	priv->ring_data = NULL;
-	return ret;
 }
 
 static void hns3_put_ring_config(struct hns3_nic_priv *priv)
 {
-	struct hnae3_handle *h = priv->ae_handle;
-	int i;
-
-	if (!priv->ring_data)
+	if (!priv->ring)
 		return;
 
-	for (i = 0; i < h->kinfo.num_tqps; i++) {
-		devm_kfree(priv->dev, priv->ring_data[i].ring);
-		devm_kfree(priv->dev,
-			   priv->ring_data[i + h->kinfo.num_tqps].ring);
-	}
-	devm_kfree(priv->dev, priv->ring_data);
-	priv->ring_data = NULL;
+	devm_kfree(priv->dev, priv->ring);
+	priv->ring = NULL;
 }
 
 static int hns3_alloc_ring_memory(struct hns3_enet_ring *ring)
@@ -3696,7 +3858,7 @@
 		for (j = 0; j < tc_info->tqp_count; j++) {
 			struct hnae3_queue *q;
 
-			q = priv->ring_data[tc_info->tqp_offset + j].ring->tqp;
+			q = priv->ring[tc_info->tqp_offset + j].tqp;
 			hns3_write_dev(q, HNS3_RING_TX_RING_TC_REG,
 				       tc_info->tc);
 		}
@@ -3711,21 +3873,21 @@
 	int ret;
 
 	for (i = 0; i < ring_num; i++) {
-		ret = hns3_alloc_ring_memory(priv->ring_data[i].ring);
+		ret = hns3_alloc_ring_memory(&priv->ring[i]);
 		if (ret) {
 			dev_err(priv->dev,
 				"Alloc ring memory fail! ret=%d\n", ret);
 			goto out_when_alloc_ring_memory;
 		}
 
-		u64_stats_init(&priv->ring_data[i].ring->syncp);
+		u64_stats_init(&priv->ring[i].syncp);
 	}
 
 	return 0;
 
 out_when_alloc_ring_memory:
 	for (j = i - 1; j >= 0; j--)
-		hns3_fini_ring(priv->ring_data[j].ring);
+		hns3_fini_ring(&priv->ring[j]);
 
 	return -ENOMEM;
 }
@@ -3736,30 +3898,31 @@
 	int i;
 
 	for (i = 0; i < h->kinfo.num_tqps; i++) {
-		hns3_fini_ring(priv->ring_data[i].ring);
-		hns3_fini_ring(priv->ring_data[i + h->kinfo.num_tqps].ring);
+		hns3_fini_ring(&priv->ring[i]);
+		hns3_fini_ring(&priv->ring[i + h->kinfo.num_tqps]);
 	}
 	return 0;
 }
 
 /* Set mac addr if it is configured. or leave it to the AE driver */
-static int hns3_init_mac_addr(struct net_device *netdev, bool init)
+static int hns3_init_mac_addr(struct net_device *netdev)
 {
 	struct hns3_nic_priv *priv = netdev_priv(netdev);
 	struct hnae3_handle *h = priv->ae_handle;
-	u8 mac_addr_temp[ETH_ALEN];
+	u8 mac_addr_temp[ETH_ALEN] = {0};
 	int ret = 0;
 
-	if (h->ae_algo->ops->get_mac_addr && init) {
+	if (h->ae_algo->ops->get_mac_addr)
 		h->ae_algo->ops->get_mac_addr(h, mac_addr_temp);
-		ether_addr_copy(netdev->dev_addr, mac_addr_temp);
-	}
 
 	/* Check if the MAC address is valid, if not get a random one */
-	if (!is_valid_ether_addr(netdev->dev_addr)) {
+	if (!is_valid_ether_addr(mac_addr_temp)) {
 		eth_hw_addr_random(netdev);
 		dev_warn(priv->dev, "using random MAC address %pM\n",
 			 netdev->dev_addr);
+	} else {
+		ether_addr_copy(netdev->dev_addr, mac_addr_temp);
+		ether_addr_copy(netdev->perm_addr, mac_addr_temp);
 	}
 
 	if (h->ae_algo->ops->set_mac_addr)
@@ -3827,14 +3990,14 @@
 	struct hnae3_knic_private_info *kinfo = &priv->ae_handle->kinfo;
 
 	dev_info(priv->dev, "MAC address: %pM\n", priv->netdev->dev_addr);
-	dev_info(priv->dev, "Task queue pairs numbers: %d\n", kinfo->num_tqps);
-	dev_info(priv->dev, "RSS size: %d\n", kinfo->rss_size);
-	dev_info(priv->dev, "Allocated RSS size: %d\n", kinfo->req_rss_size);
-	dev_info(priv->dev, "RX buffer length: %d\n", kinfo->rx_buf_len);
-	dev_info(priv->dev, "Desc num per TX queue: %d\n", kinfo->num_tx_desc);
-	dev_info(priv->dev, "Desc num per RX queue: %d\n", kinfo->num_rx_desc);
-	dev_info(priv->dev, "Total number of enabled TCs: %d\n", kinfo->num_tc);
-	dev_info(priv->dev, "Max mtu size: %d\n", priv->netdev->max_mtu);
+	dev_info(priv->dev, "Task queue pairs numbers: %u\n", kinfo->num_tqps);
+	dev_info(priv->dev, "RSS size: %u\n", kinfo->rss_size);
+	dev_info(priv->dev, "Allocated RSS size: %u\n", kinfo->req_rss_size);
+	dev_info(priv->dev, "RX buffer length: %u\n", kinfo->rx_buf_len);
+	dev_info(priv->dev, "Desc num per TX queue: %u\n", kinfo->num_tx_desc);
+	dev_info(priv->dev, "Desc num per RX queue: %u\n", kinfo->num_rx_desc);
+	dev_info(priv->dev, "Total number of enabled TCs: %u\n", kinfo->num_tc);
+	dev_info(priv->dev, "Max mtu size: %u\n", priv->netdev->max_mtu);
 }
 
 static int hns3_client_init(struct hnae3_handle *handle)
@@ -3863,7 +4026,7 @@
 	handle->kinfo.netdev = netdev;
 	handle->priv = (void *)priv;
 
-	hns3_init_mac_addr(netdev, true);
+	hns3_init_mac_addr(netdev);
 
 	hns3_set_default_feature(netdev);
 
@@ -3897,7 +4060,7 @@
 	ret = hns3_init_all_ring(priv);
 	if (ret) {
 		ret = -ENOMEM;
-		goto out_init_ring_data;
+		goto out_init_ring;
 	}
 
 	ret = hns3_init_phy(netdev);
@@ -3910,6 +4073,18 @@
 		goto out_reg_netdev_fail;
 	}
 
+	/* the device can work without cpu rmap, only aRFS needs it */
+	ret = hns3_set_rx_cpu_rmap(netdev);
+	if (ret)
+		dev_warn(priv->dev, "set rx cpu rmap fail, ret=%d\n", ret);
+
+	ret = hns3_nic_init_irq(priv);
+	if (ret) {
+		dev_err(priv->dev, "init irq failed! ret=%d\n", ret);
+		hns3_free_rx_cpu_rmap(netdev);
+		goto out_init_irq_fail;
+	}
+
 	ret = hns3_client_start(handle);
 	if (ret) {
 		dev_err(priv->dev, "hns3_client_start fail! ret=%d\n", ret);
@@ -3931,17 +4106,20 @@
 	return ret;
 
 out_client_start:
+	hns3_free_rx_cpu_rmap(netdev);
+	hns3_nic_uninit_irq(priv);
+out_init_irq_fail:
 	unregister_netdev(netdev);
 out_reg_netdev_fail:
 	hns3_uninit_phy(netdev);
 out_init_phy:
 	hns3_uninit_all_ring(priv);
-out_init_ring_data:
+out_init_ring:
 	hns3_nic_uninit_vector_data(priv);
 out_init_vector_data:
 	hns3_nic_dealloc_vector_data(priv);
 out_alloc_vector_data:
-	priv->ring_data = NULL;
+	priv->ring = NULL;
 out_get_ring_cfg:
 	priv->ae_handle = NULL;
 	free_netdev(netdev);
@@ -3968,15 +4146,17 @@
 		goto out_netdev_free;
 	}
 
+	hns3_free_rx_cpu_rmap(netdev);
+
+	hns3_nic_uninit_irq(priv);
+
 	hns3_del_all_fd_rules(netdev, true);
 
 	hns3_clear_all_ring(handle, true);
 
 	hns3_nic_uninit_vector_data(priv);
 
-	ret = hns3_nic_dealloc_vector_data(priv);
-	if (ret)
-		netdev_err(netdev, "dealloc vector error\n");
+	hns3_nic_dealloc_vector_data(priv);
 
 	ret = hns3_uninit_all_ring(priv);
 	if (ret)
@@ -3984,9 +4164,8 @@
 
 	hns3_put_ring_config(priv);
 
-	hns3_dbg_uninit(handle);
-
 out_netdev_free:
+	hns3_dbg_uninit(handle);
 	free_netdev(netdev);
 }
 
@@ -3998,8 +4177,8 @@
 		return;
 
 	if (linkup) {
-		netif_carrier_on(netdev);
 		netif_tx_wake_all_queues(netdev);
+		netif_carrier_on(netdev);
 		if (netif_msg_link(handle))
 			netdev_info(netdev, "link up\n");
 	} else {
@@ -4102,7 +4281,7 @@
 				/* if alloc new buffer fail, exit directly
 				 * and reclear in up flow.
 				 */
-				netdev_warn(ring->tqp->handle->kinfo.netdev,
+				netdev_warn(ring_to_netdev(ring),
 					    "reserve buffer map failed, ret = %d\n",
 					    ret);
 				return ret;
@@ -4148,10 +4327,10 @@
 	for (i = 0; i < h->kinfo.num_tqps; i++) {
 		struct hns3_enet_ring *ring;
 
-		ring = priv->ring_data[i].ring;
+		ring = &priv->ring[i];
 		hns3_clear_tx_ring(ring);
 
-		ring = priv->ring_data[i + h->kinfo.num_tqps].ring;
+		ring = &priv->ring[i + h->kinfo.num_tqps];
 		/* Continue to clear other rings even if clearing some
 		 * rings failed.
 		 */
@@ -4175,16 +4354,16 @@
 		if (ret)
 			return ret;
 
-		hns3_init_ring_hw(priv->ring_data[i].ring);
+		hns3_init_ring_hw(&priv->ring[i]);
 
 		/* We need to clear tx ring here because self test will
 		 * use the ring and will not run down before up
 		 */
-		hns3_clear_tx_ring(priv->ring_data[i].ring);
-		priv->ring_data[i].ring->next_to_clean = 0;
-		priv->ring_data[i].ring->next_to_use = 0;
+		hns3_clear_tx_ring(&priv->ring[i]);
+		priv->ring[i].next_to_clean = 0;
+		priv->ring[i].next_to_use = 0;
 
-		rx_ring = priv->ring_data[i + h->kinfo.num_tqps].ring;
+		rx_ring = &priv->ring[i + h->kinfo.num_tqps];
 		hns3_init_ring_hw(rx_ring);
 		ret = hns3_clear_rx_ring(rx_ring);
 		if (ret)
@@ -4261,6 +4440,11 @@
 	struct hns3_nic_priv *priv = netdev_priv(kinfo->netdev);
 	int ret = 0;
 
+	if (!test_bit(HNS3_NIC_STATE_INITED, &priv->state)) {
+		netdev_err(kinfo->netdev, "device is not initialized yet\n");
+		return -EFAULT;
+	}
+
 	clear_bit(HNS3_NIC_STATE_RESETTING, &priv->state);
 
 	if (netif_running(kinfo->netdev)) {
@@ -4303,17 +4487,32 @@
 	if (ret)
 		goto err_uninit_vector;
 
+	/* the device can work without cpu rmap, only aRFS needs it */
+	ret = hns3_set_rx_cpu_rmap(netdev);
+	if (ret)
+		dev_warn(priv->dev, "set rx cpu rmap fail, ret=%d\n", ret);
+
+	ret = hns3_nic_init_irq(priv);
+	if (ret) {
+		dev_err(priv->dev, "init irq failed! ret=%d\n", ret);
+		hns3_free_rx_cpu_rmap(netdev);
+		goto err_init_irq_fail;
+	}
+
 	ret = hns3_client_start(handle);
 	if (ret) {
 		dev_err(priv->dev, "hns3_client_start fail! ret=%d\n", ret);
-		goto err_uninit_ring;
+		goto err_client_start_fail;
 	}
 
 	set_bit(HNS3_NIC_STATE_INITED, &priv->state);
 
 	return ret;
 
-err_uninit_ring:
+err_client_start_fail:
+	hns3_free_rx_cpu_rmap(netdev);
+	hns3_nic_uninit_irq(priv);
+err_init_irq_fail:
 	hns3_uninit_all_ring(priv);
 err_uninit_vector:
 	hns3_nic_uninit_vector_data(priv);
@@ -4331,7 +4530,7 @@
 	bool vlan_filter_enable;
 	int ret;
 
-	ret = hns3_init_mac_addr(netdev, false);
+	ret = hns3_init_mac_addr(netdev);
 	if (ret)
 		return ret;
 
@@ -4358,11 +4557,16 @@
 	struct hns3_nic_priv *priv = netdev_priv(netdev);
 	int ret;
 
+	if (!test_bit(HNS3_NIC_STATE_DOWN, &priv->state))
+		hns3_nic_net_stop(netdev);
+
 	if (!test_and_clear_bit(HNS3_NIC_STATE_INITED, &priv->state)) {
 		netdev_warn(netdev, "already uninitialized\n");
 		return 0;
 	}
 
+	hns3_free_rx_cpu_rmap(netdev);
+	hns3_nic_uninit_irq(priv);
 	hns3_clear_all_ring(handle, true);
 	hns3_reset_tx_queue(priv->ae_handle);
 
@@ -4370,9 +4574,7 @@
 
 	hns3_store_coal(priv);
 
-	ret = hns3_nic_dealloc_vector_data(priv);
-	if (ret)
-		netdev_err(netdev, "dealloc vector error\n");
+	hns3_nic_dealloc_vector_data(priv);
 
 	ret = hns3_uninit_all_ring(priv);
 	if (ret)
@@ -4454,7 +4656,7 @@
 	if (new_tqp_num > hns3_get_max_available_channels(h) ||
 	    new_tqp_num < 1) {
 		dev_err(&netdev->dev,
-			"Change tqps fail, the tqp range is from 1 to %d",
+			"Change tqps fail, the tqp range is from 1 to %u",
 			hns3_get_max_available_channels(h));
 		return -EINVAL;
 	}
@@ -4538,7 +4740,7 @@
 	pr_info("%s: %s\n", hns3_driver_name, hns3_copyright);
 
 	client.type = HNAE3_CLIENT_KNIC;
-	snprintf(client.name, HNAE3_CLIENT_NAME_LENGTH - 1, "%s",
+	snprintf(client.name, HNAE3_CLIENT_NAME_LENGTH, "%s",
 		 hns3_driver_name);
 
 	client.ops = &client_ops;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
@@ -76,7 +76,7 @@
 #define HNS3_RING_NAME_LEN			16
 #define HNS3_BUFFER_SIZE_2048			2048
 #define HNS3_RING_MAX_PENDING			32760
-#define HNS3_RING_MIN_PENDING			24
+#define HNS3_RING_MIN_PENDING			72
 #define HNS3_RING_BD_MULTIPLE			8
 /* max frame size of mac */
 #define HNS3_MAC_MAX_FRAME			9728
@@ -186,7 +186,7 @@
 #define HNS3_TXD_MSS_S				0
 #define HNS3_TXD_MSS_M				(0x3fff << HNS3_TXD_MSS_S)
 
-#define HNS3_TX_LAST_SIZE_M                    0xffff
+#define HNS3_TX_LAST_SIZE_M			0xffff
 
 #define HNS3_VECTOR_TX_IRQ			BIT_ULL(0)
 #define HNS3_VECTOR_RX_IRQ			BIT_ULL(1)
@@ -195,9 +195,13 @@
 #define HNS3_VECTOR_INITED			1
 
 #define HNS3_MAX_BD_SIZE			65535
-#define HNS3_MAX_BD_NUM_NORMAL			8
-#define HNS3_MAX_BD_NUM_TSO			63
-#define HNS3_MAX_BD_PER_PKT			MAX_SKB_FRAGS
+#define HNS3_MAX_NON_TSO_BD_NUM			8U
+#define HNS3_MAX_TSO_BD_NUM			63U
+#define HNS3_MAX_TSO_SIZE \
+	(HNS3_MAX_BD_SIZE * HNS3_MAX_TSO_BD_NUM)
+
+#define HNS3_MAX_NON_TSO_SIZE \
+	(HNS3_MAX_BD_SIZE * HNS3_MAX_NON_TSO_BD_NUM)
 
 #define HNS3_VECTOR_GL0_OFFSET			0x100
 #define HNS3_VECTOR_GL1_OFFSET			0x200
@@ -309,7 +313,7 @@
 
 	u16 reuse_flag;
 
-       /* desc type, used by the ring user to mark the type of the priv data */
+	/* desc type, used by the ring user to mark the type of the priv data */
 	u16 type;
 };
 
@@ -405,6 +409,7 @@
 	struct hns3_enet_ring *next;
 	struct hns3_enet_tqp_vector *tqp_vector;
 	struct hnae3_queue *tqp;
+	int queue_index;
 	struct device *dev; /* will be used for DMA mapping of descriptors */
 
 	/* statistic */
@@ -430,18 +435,7 @@
 	int pending_buf;
 	struct sk_buff *skb;
 	struct sk_buff *tail_skb;
-};
-
-struct hns_queue;
-
-struct hns3_nic_ring_data {
-	struct hns3_enet_ring *ring;
-	struct napi_struct napi;
-	int queue_index;
-	int (*poll_one)(struct hns3_nic_ring_data *, int, void *);
-	void (*ex_process)(struct hns3_nic_ring_data *, struct sk_buff *);
-	void (*fini_process)(struct hns3_nic_ring_data *);
-};
+} ____cacheline_internodealigned_in_smp;
 
 enum hns3_flow_level_range {
 	HNS3_FLOW_LOW = 0,
@@ -518,7 +512,7 @@
 	 * the cb for nic to manage the ring buffer, the first half of the
 	 * array is for tx_ring and vice versa for the second half
 	 */
-	struct hns3_nic_ring_data *ring_data;
+	struct hns3_enet_ring *ring;
 	struct hns3_enet_tqp_vector *tqp_vector;
 	u16 vector_num;
 
@@ -613,11 +607,11 @@
 
 #define ring_to_dev(ring) ((ring)->dev)
 
+#define ring_to_netdev(ring)	((ring)->tqp_vector->napi.dev)
+
 #define ring_to_dma_dir(ring) (HNAE3_IS_TX_RING(ring) ? \
 	DMA_TO_DEVICE : DMA_FROM_DEVICE)
 
-#define tx_ring_data(priv, idx) ((priv)->ring_data[idx])
-
 #define hns3_buf_size(_ring) ((_ring)->buf_size)
 
 static inline unsigned int hns3_page_order(struct hns3_enet_ring *ring)
@@ -679,4 +673,5 @@
 void hns3_dbg_uninit(struct hnae3_handle *handle);
 void hns3_dbg_register_debugfs(const char *debugfs_dir_name);
 void hns3_dbg_unregister_debugfs(void);
+void hns3_shinfo_pack(struct skb_shared_info *shinfo, __u32 *size);
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
@@ -174,18 +174,21 @@
 {
 	struct hns3_enet_tqp_vector *tqp_vector = ring->tqp_vector;
 	unsigned char *packet = skb->data;
+	u32 len = skb_headlen(skb);
 	u32 i;
 
-	for (i = 0; i < skb->len; i++)
+	len = min_t(u32, len, HNS3_NIC_LB_TEST_PACKET_SIZE);
+
+	for (i = 0; i < len; i++)
 		if (packet[i] != (unsigned char)(i & 0xff))
 			break;
 
 	/* The packet is correctly received */
-	if (i == skb->len)
+	if (i == HNS3_NIC_LB_TEST_PACKET_SIZE)
 		tqp_vector->rx_group.total_packets++;
 	else
 		print_hex_dump(KERN_ERR, "selftest:", DUMP_PREFIX_OFFSET, 16, 1,
-			       skb->data, skb->len, true);
+			       skb->data, len, true);
 
 	dev_kfree_skb_any(skb);
 }
@@ -198,7 +201,7 @@
 
 	kinfo = &h->kinfo;
 	for (i = kinfo->num_tqps; i < kinfo->num_tqps * 2; i++) {
-		struct hns3_enet_ring *ring = priv->ring_data[i].ring;
+		struct hns3_enet_ring *ring = &priv->ring[i];
 		struct hns3_enet_ring_group *rx_group;
 		u64 pre_rx_pkt;
 
@@ -221,7 +224,7 @@
 	u32 i;
 
 	for (i = start_ringid; i <= end_ringid; i++) {
-		struct hns3_enet_ring *ring = priv->ring_data[i].ring;
+		struct hns3_enet_ring *ring = &priv->ring[i];
 
 		hns3_clean_tx_ring(ring);
 	}
@@ -423,9 +426,8 @@
 			data[ETH_GSTRING_LEN - 1] = '\0';
 
 			/* first, prepend the prefix string */
-			n1 = snprintf(data, MAX_PREFIX_SIZE, "%s%d_",
-				      prefix, i);
-			n1 = min_t(uint, n1, MAX_PREFIX_SIZE - 1);
+			n1 = scnprintf(data, MAX_PREFIX_SIZE, "%s%d_",
+				       prefix, i);
 			size_left = (ETH_GSTRING_LEN - 1) - n1;
 
 			/* now, concatenate the stats string to it */
@@ -486,7 +488,7 @@
 
 	/* get stats for Tx */
 	for (i = 0; i < kinfo->num_tqps; i++) {
-		ring = nic_priv->ring_data[i].ring;
+		ring = &nic_priv->ring[i];
 		for (j = 0; j < HNS3_TXQ_STATS_COUNT; j++) {
 			stat = (u8 *)ring + hns3_txq_stats[j].stats_offset;
 			*data++ = *(u64 *)stat;
@@ -495,7 +497,7 @@
 
 	/* get stats for Rx */
 	for (i = 0; i < kinfo->num_tqps; i++) {
-		ring = nic_priv->ring_data[i + kinfo->num_tqps].ring;
+		ring = &nic_priv->ring[i + kinfo->num_tqps];
 		for (j = 0; j < HNS3_RXQ_STATS_COUNT; j++) {
 			stat = (u8 *)ring + hns3_rxq_stats[j].stats_offset;
 			*data++ = *(u64 *)stat;
@@ -598,8 +600,8 @@
 	param->tx_max_pending = HNS3_RING_MAX_PENDING;
 	param->rx_max_pending = HNS3_RING_MAX_PENDING;
 
-	param->tx_pending = priv->ring_data[0].ring->desc_num;
-	param->rx_pending = priv->ring_data[queue_num].ring->desc_num;
+	param->tx_pending = priv->ring[0].desc_num;
+	param->rx_pending = priv->ring[queue_num].desc_num;
 }
 
 static void hns3_get_pauseparam(struct net_device *netdev,
@@ -673,7 +675,9 @@
 		hns3_get_ksettings(h, cmd);
 		break;
 	case HNAE3_MEDIA_TYPE_FIBER:
-		if (module_type == HNAE3_MODULE_TYPE_CR)
+		if (module_type == HNAE3_MODULE_TYPE_UNKNOWN)
+			cmd->base.port = PORT_OTHER;
+		else if (module_type == HNAE3_MODULE_TYPE_CR)
 			cmd->base.port = PORT_DA;
 		else
 			cmd->base.port = PORT_FIBRE;
@@ -737,7 +741,7 @@
 	if (ops->get_media_type)
 		ops->get_media_type(handle, &media_type, &module_type);
 
-	if (cmd->base.duplex != DUPLEX_FULL &&
+	if (cmd->base.duplex == DUPLEX_HALF &&
 	    media_type != HNAE3_MEDIA_TYPE_COPPER) {
 		netdev_err(netdev,
 			   "only copper port supports half duplex!");
@@ -901,9 +905,8 @@
 	h->kinfo.num_rx_desc = rx_desc_num;
 
 	for (i = 0; i < h->kinfo.num_tqps; i++) {
-		priv->ring_data[i].ring->desc_num = tx_desc_num;
-		priv->ring_data[i + h->kinfo.num_tqps].ring->desc_num =
-			rx_desc_num;
+		priv->ring[i].desc_num = tx_desc_num;
+		priv->ring[i + h->kinfo.num_tqps].desc_num = rx_desc_num;
 	}
 }
 
@@ -919,7 +922,7 @@
 		return NULL;
 
 	for (i = 0; i < handle->kinfo.num_tqps * 2; i++) {
-		memcpy(&tmp_rings[i], priv->ring_data[i].ring,
+		memcpy(&tmp_rings[i], &priv->ring[i],
 		       sizeof(struct hns3_enet_ring));
 		tmp_rings[i].skb = NULL;
 	}
@@ -967,8 +970,8 @@
 	/* Hardware requires that its descriptors must be multiple of eight */
 	new_tx_desc_num = ALIGN(param->tx_pending, HNS3_RING_BD_MULTIPLE);
 	new_rx_desc_num = ALIGN(param->rx_pending, HNS3_RING_BD_MULTIPLE);
-	old_tx_desc_num = priv->ring_data[0].ring->desc_num;
-	old_rx_desc_num = priv->ring_data[queue_num].ring->desc_num;
+	old_tx_desc_num = priv->ring[0].desc_num;
+	old_rx_desc_num = priv->ring[queue_num].desc_num;
 	if (old_tx_desc_num == new_tx_desc_num &&
 	    old_rx_desc_num == new_rx_desc_num)
 		return 0;
@@ -981,7 +984,7 @@
 	}
 
 	netdev_info(ndev,
-		    "Changing Tx/Rx ring depth from %d/%d to %d/%d\n",
+		    "Changing Tx/Rx ring depth from %u/%u to %u/%u\n",
 		    old_tx_desc_num, old_rx_desc_num,
 		    new_tx_desc_num, new_rx_desc_num);
 
@@ -997,7 +1000,7 @@
 		hns3_change_all_ring_bd_num(priv, old_tx_desc_num,
 					    old_rx_desc_num);
 		for (i = 0; i < h->kinfo.num_tqps * 2; i++)
-			memcpy(priv->ring_data[i].ring, &tmp_rings[i],
+			memcpy(&priv->ring[i], &tmp_rings[i],
 			       sizeof(struct hns3_enet_ring));
 	} else {
 		for (i = 0; i < h->kinfo.num_tqps * 2; i++)
@@ -1093,13 +1096,13 @@
 
 	if (queue >= queue_num) {
 		netdev_err(netdev,
-			   "Invalid queue value %d! Queue max id=%d\n",
+			   "Invalid queue value %u! Queue max id=%u\n",
 			   queue, queue_num - 1);
 		return -EINVAL;
 	}
 
-	tx_vector = priv->ring_data[queue].ring->tqp_vector;
-	rx_vector = priv->ring_data[queue_num + queue].ring->tqp_vector;
+	tx_vector = priv->ring[queue].tqp_vector;
+	rx_vector = priv->ring[queue_num + queue].tqp_vector;
 
 	cmd->use_adaptive_tx_coalesce =
 			tx_vector->tx_group.coal.gl_adapt_enable;
@@ -1143,14 +1146,14 @@
 	rx_gl = hns3_gl_round_down(cmd->rx_coalesce_usecs);
 	if (rx_gl != cmd->rx_coalesce_usecs) {
 		netdev_info(netdev,
-			    "rx_usecs(%d) rounded down to %d, because it must be multiple of 2.\n",
+			    "rx_usecs(%u) rounded down to %u, because it must be multiple of 2.\n",
 			    cmd->rx_coalesce_usecs, rx_gl);
 	}
 
 	tx_gl = hns3_gl_round_down(cmd->tx_coalesce_usecs);
 	if (tx_gl != cmd->tx_coalesce_usecs) {
 		netdev_info(netdev,
-			    "tx_usecs(%d) rounded down to %d, because it must be multiple of 2.\n",
+			    "tx_usecs(%u) rounded down to %u, because it must be multiple of 2.\n",
 			    cmd->tx_coalesce_usecs, tx_gl);
 	}
 
@@ -1178,7 +1181,7 @@
 	rl = hns3_rl_round_down(cmd->rx_coalesce_usecs_high);
 	if (rl != cmd->rx_coalesce_usecs_high) {
 		netdev_info(netdev,
-			    "usecs_high(%d) rounded down to %d, because it must be multiple of 4.\n",
+			    "usecs_high(%u) rounded down to %u, because it must be multiple of 4.\n",
 			    cmd->rx_coalesce_usecs_high, rl);
 	}
 
@@ -1207,7 +1210,7 @@
 	if (cmd->use_adaptive_tx_coalesce == 1 ||
 	    cmd->use_adaptive_rx_coalesce == 1) {
 		netdev_info(netdev,
-			    "adaptive-tx=%d and adaptive-rx=%d, tx_usecs or rx_usecs will changed dynamically.\n",
+			    "adaptive-tx=%u and adaptive-rx=%u, tx_usecs or rx_usecs will changed dynamically.\n",
 			    cmd->use_adaptive_tx_coalesce,
 			    cmd->use_adaptive_rx_coalesce);
 	}
@@ -1224,8 +1227,8 @@
 	struct hnae3_handle *h = priv->ae_handle;
 	int queue_num = h->kinfo.num_tqps;
 
-	tx_vector = priv->ring_data[queue].ring->tqp_vector;
-	rx_vector = priv->ring_data[queue_num + queue].ring->tqp_vector;
+	tx_vector = priv->ring[queue].tqp_vector;
+	rx_vector = priv->ring[queue_num + queue].tqp_vector;
 
 	tx_vector->tx_group.coal.gl_adapt_enable =
 				cmd->use_adaptive_tx_coalesce;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/hisilicon/hns3/hns3_trace.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/hisilicon/hns3/hns3_trace.h
@@ -0,0 +1,139 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (c) 2018-2019 Hisilicon Limited. */
+
+/* This must be outside ifdef _HNS3_TRACE_H */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM hns3
+
+#if !defined(_HNS3_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
+#define _HNS3_TRACE_H_
+
+#include <linux/tracepoint.h>
+
+#define DESC_NR		(sizeof(struct hns3_desc) / sizeof(u32))
+
+DECLARE_EVENT_CLASS(hns3_skb_template,
+	TP_PROTO(struct sk_buff *skb),
+	TP_ARGS(skb),
+
+	TP_STRUCT__entry(
+		__field(unsigned int, headlen)
+		__field(unsigned int, len)
+		__field(__u8, nr_frags)
+		__field(__u8, ip_summed)
+		__field(unsigned int, hdr_len)
+		__field(unsigned short, gso_size)
+		__field(unsigned short, gso_segs)
+		__field(unsigned int, gso_type)
+		__field(bool, fraglist)
+		__array(__u32, size, MAX_SKB_FRAGS)
+	),
+
+	TP_fast_assign(
+		__entry->headlen = skb_headlen(skb);
+		__entry->len = skb->len;
+		__entry->nr_frags = skb_shinfo(skb)->nr_frags;
+		__entry->gso_size = skb_shinfo(skb)->gso_size;
+		__entry->gso_segs = skb_shinfo(skb)->gso_segs;
+		__entry->gso_type = skb_shinfo(skb)->gso_type;
+		__entry->hdr_len = skb->encapsulation ?
+		skb_inner_transport_offset(skb) + inner_tcp_hdrlen(skb) :
+		skb_transport_offset(skb) + tcp_hdrlen(skb);
+		__entry->ip_summed = skb->ip_summed;
+		__entry->fraglist = skb_has_frag_list(skb);
+		hns3_shinfo_pack(skb_shinfo(skb), __entry->size);
+	),
+
+	TP_printk(
+		"len: %u, %u, %u, cs: %u, gso: %u, %u, %x, frag(%d %u): %s",
+		__entry->headlen, __entry->len, __entry->hdr_len,
+		__entry->ip_summed, __entry->gso_size, __entry->gso_segs,
+		__entry->gso_type, __entry->fraglist, __entry->nr_frags,
+		__print_array(__entry->size, MAX_SKB_FRAGS, sizeof(__u32))
+	)
+);
+
+DEFINE_EVENT(hns3_skb_template, hns3_over_8bd,
+	TP_PROTO(struct sk_buff *skb),
+	TP_ARGS(skb));
+
+DEFINE_EVENT(hns3_skb_template, hns3_gro,
+	TP_PROTO(struct sk_buff *skb),
+	TP_ARGS(skb));
+
+DEFINE_EVENT(hns3_skb_template, hns3_tso,
+	TP_PROTO(struct sk_buff *skb),
+	TP_ARGS(skb));
+
+TRACE_EVENT(hns3_tx_desc,
+	TP_PROTO(struct hns3_enet_ring *ring, int cur_ntu),
+	TP_ARGS(ring, cur_ntu),
+
+	TP_STRUCT__entry(
+		__field(int, index)
+		__field(int, ntu)
+		__field(int, ntc)
+		__field(dma_addr_t, desc_dma)
+		__array(u32, desc, DESC_NR)
+		__string(devname, ring->tqp->handle->kinfo.netdev->name)
+	),
+
+	TP_fast_assign(
+		__entry->index = ring->tqp->tqp_index;
+		__entry->ntu = ring->next_to_use;
+		__entry->ntc = ring->next_to_clean;
+		__entry->desc_dma = ring->desc_dma_addr,
+		memcpy(__entry->desc, &ring->desc[cur_ntu],
+		       sizeof(struct hns3_desc));
+		__assign_str(devname, ring->tqp->handle->kinfo.netdev->name);
+	),
+
+	TP_printk(
+		"%s-%d-%d/%d desc(%pad): %s",
+		__get_str(devname), __entry->index, __entry->ntu,
+		__entry->ntc, &__entry->desc_dma,
+		__print_array(__entry->desc, DESC_NR, sizeof(u32))
+	)
+);
+
+TRACE_EVENT(hns3_rx_desc,
+	TP_PROTO(struct hns3_enet_ring *ring),
+	TP_ARGS(ring),
+
+	TP_STRUCT__entry(
+		__field(int, index)
+		__field(int, ntu)
+		__field(int, ntc)
+		__field(dma_addr_t, desc_dma)
+		__field(dma_addr_t, buf_dma)
+		__array(u32, desc, DESC_NR)
+		__string(devname, ring->tqp->handle->kinfo.netdev->name)
+	),
+
+	TP_fast_assign(
+		__entry->index = ring->tqp->tqp_index;
+		__entry->ntu = ring->next_to_use;
+		__entry->ntc = ring->next_to_clean;
+		__entry->desc_dma = ring->desc_dma_addr;
+		__entry->buf_dma = ring->desc_cb[ring->next_to_clean].dma;
+		memcpy(__entry->desc, &ring->desc[ring->next_to_clean],
+		       sizeof(struct hns3_desc));
+		__assign_str(devname, ring->tqp->handle->kinfo.netdev->name);
+	),
+
+	TP_printk(
+		"%s-%d-%d/%d desc(%pad) buf(%pad): %s",
+		__get_str(devname), __entry->index, __entry->ntu,
+		__entry->ntc, &__entry->desc_dma, &__entry->buf_dma,
+		__print_array(__entry->desc, DESC_NR, sizeof(u32))
+	)
+);
+
+#endif /* _HNS3_TRACE_H_ */
+
+/* This must be outside ifdef _HNS3_TRACE_H */
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE hns3_trace
+#include <trace/define_trace.h>
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
@@ -145,7 +145,7 @@
 	rmb(); /* Make sure head is ready before touch any data */
 
 	if (!is_valid_csq_clean_head(csq, head)) {
-		dev_warn(&hdev->pdev->dev, "wrong cmd head (%d, %d-%d)\n", head,
+		dev_warn(&hdev->pdev->dev, "wrong cmd head (%u, %d-%d)\n", head,
 			 csq->next_to_use, csq->next_to_clean);
 		dev_warn(&hdev->pdev->dev,
 			 "Disabling any further commands to IMP firmware\n");
@@ -314,11 +314,10 @@
 		} while (timeout < hw->cmq.tx_timeout);
 	}
 
-	if (!complete) {
+	if (!complete)
 		retval = -EBADE;
-	} else {
+	else
 		retval = hclge_cmd_check_retval(hw, desc, num, ntc);
-	}
 
 	/* Clean the command send queue */
 	handle = hclge_cmd_csq_clean(hw);
@@ -480,19 +479,6 @@
 	hclge_write_dev(hw, HCLGE_NIC_CRQ_TAIL_REG, 0);
 }
 
-static void hclge_destroy_queue(struct hclge_cmq_ring *ring)
-{
-	spin_lock(&ring->lock);
-	hclge_free_cmd_desc(ring);
-	spin_unlock(&ring->lock);
-}
-
-static void hclge_destroy_cmd_queue(struct hclge_hw *hw)
-{
-	hclge_destroy_queue(&hw->cmq.csq);
-	hclge_destroy_queue(&hw->cmq.crq);
-}
-
 void hclge_cmd_uninit(struct hclge_dev *hdev)
 {
 	spin_lock_bh(&hdev->hw.cmq.csq.lock);
@@ -502,5 +488,6 @@
 	spin_unlock(&hdev->hw.cmq.crq.lock);
 	spin_unlock_bh(&hdev->hw.cmq.csq.lock);
 
-	hclge_destroy_cmd_queue(&hdev->hw);
+	hclge_free_cmd_desc(&hdev->hw.cmq.csq);
+	hclge_free_cmd_desc(&hdev->hw.cmq.crq);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
@@ -5,8 +5,11 @@
 #define __HCLGE_CMD_H
 #include <linux/types.h>
 #include <linux/io.h>
+#include <linux/etherdevice.h>
+#include "hnae3.h"
 
 #define HCLGE_CMDQ_TX_TIMEOUT		30000
+#define HCLGE_DESC_DATA_LEN		6
 
 struct hclge_dev;
 struct hclge_desc {
@@ -18,7 +21,7 @@
 	__le16 flag;
 	__le16 retval;
 	__le16 rsv;
-	__le32 data[6];
+	__le32 data[HCLGE_DESC_DATA_LEN];
 };
 
 struct hclge_cmq_ring {
@@ -61,6 +64,7 @@
 struct hclge_misc_vector {
 	u8 __iomem *addr;
 	int vector_irq;
+	char name[HNAE3_INT_NAME_LEN];
 };
 
 struct hclge_cmq {
@@ -244,7 +248,7 @@
 	/* QCN commands */
 	HCLGE_OPC_QCN_MOD_CFG		= 0x1A01,
 	HCLGE_OPC_QCN_GRP_TMPLT_CFG	= 0x1A02,
-	HCLGE_OPC_QCN_SHAPPING_IR_CFG	= 0x1A03,
+	HCLGE_OPC_QCN_SHAPPING_CFG	= 0x1A03,
 	HCLGE_OPC_QCN_SHAPPING_BS_CFG	= 0x1A04,
 	HCLGE_OPC_QCN_QSET_LINK_CFG	= 0x1A05,
 	HCLGE_OPC_QCN_RP_STATUS_GET	= 0x1A06,
@@ -257,8 +261,12 @@
 	/* Led command */
 	HCLGE_OPC_LED_STATUS_CFG	= 0xB000,
 
+	/* clear hardware resource command */
+	HCLGE_OPC_CLEAR_HW_RESOURCE	= 0x700B,
+
 	/* NCL config command */
 	HCLGE_OPC_QUERY_NCL_CONFIG	= 0x7011,
+
 	/* M7 stats command */
 	HCLGE_OPC_M7_STATS_BD		= 0x7012,
 	HCLGE_OPC_M7_STATS_INFO		= 0x7013,
@@ -428,8 +436,10 @@
 #define HCLGE_PF_MAC_NUM_MASK	0x3
 #define HCLGE_PF_STATE_MAIN	BIT(HCLGE_PF_STATE_MAIN_B)
 #define HCLGE_PF_STATE_DONE	BIT(HCLGE_PF_STATE_DONE_B)
+#define HCLGE_VF_RST_STATUS_CMD	4
+
 struct hclge_func_status_cmd {
-	__le32  vf_rst_state[4];
+	__le32  vf_rst_state[HCLGE_VF_RST_STATUS_CMD];
 	u8 pf_state;
 	u8 mac_id;
 	u8 rsv1;
@@ -485,10 +495,12 @@
 #define HCLGE_CFG_UMV_TBL_SPACE_S	16
 #define HCLGE_CFG_UMV_TBL_SPACE_M	GENMASK(31, 16)
 
+#define HCLGE_CFG_CMD_CNT		4
+
 struct hclge_cfg_param_cmd {
 	__le32 offset;
 	__le32 rsv;
-	__le32 param[4];
+	__le32 param[HCLGE_CFG_CMD_CNT];
 };
 
 #define HCLGE_MAC_MODE		0x0
@@ -712,8 +724,7 @@
 	u8      flags;
 	u8      resp_code;
 	__le16  vlan_tag;
-	__le32  mac_addr_hi32;
-	__le16  mac_addr_lo16;
+	u8      mac_addr[ETH_ALEN];
 	__le16  rsv1;
 	__le16  ethter_type;
 	__le16  egress_port;
@@ -758,20 +769,27 @@
 	u8 rsv2[19];
 };
 
+#define HCLGE_VLAN_ID_OFFSET_STEP	160
+#define HCLGE_VLAN_BYTE_SIZE		8
+#define	HCLGE_VLAN_OFFSET_BITMAP \
+	(HCLGE_VLAN_ID_OFFSET_STEP / HCLGE_VLAN_BYTE_SIZE)
+
 struct hclge_vlan_filter_pf_cfg_cmd {
 	u8 vlan_offset;
 	u8 vlan_cfg;
 	u8 rsv[2];
-	u8 vlan_offset_bitmap[20];
+	u8 vlan_offset_bitmap[HCLGE_VLAN_OFFSET_BITMAP];
 };
 
+#define HCLGE_MAX_VF_BYTES  16
+
 struct hclge_vlan_filter_vf_cfg_cmd {
 	__le16 vlan_id;
 	u8  resp_code;
 	u8  rsv;
 	u8  vlan_cfg;
 	u8  rsv1[3];
-	u8  vf_bitmap[16];
+	u8  vf_bitmap[HCLGE_MAX_VF_BYTES];
 };
 
 #define HCLGE_SWITCH_ANTI_SPOOF_B	0U
@@ -806,6 +824,7 @@
 #define HCLGE_CFG_NIC_ROCE_SEL_B	4
 #define HCLGE_ACCEPT_TAG2_B		5
 #define HCLGE_ACCEPT_UNTAG2_B		6
+#define HCLGE_VF_NUM_PER_BYTE		8
 
 struct hclge_vport_vtag_tx_cfg_cmd {
 	u8 vport_vlan_cfg;
@@ -813,7 +832,7 @@
 	u8 rsv1[2];
 	__le16 def_vlan_tag1;
 	__le16 def_vlan_tag2;
-	u8 vf_bitmap[8];
+	u8 vf_bitmap[HCLGE_VF_NUM_PER_BYTE];
 	u8 rsv2[8];
 };
 
@@ -825,7 +844,7 @@
 	u8 vport_vlan_cfg;
 	u8 vf_offset;
 	u8 rsv1[6];
-	u8 vf_bitmap[8];
+	u8 vf_bitmap[HCLGE_VF_NUM_PER_BYTE];
 	u8 rsv2[8];
 };
 
@@ -864,7 +883,7 @@
 	u8	flags;
 	u8	resp_code;
 	__le16  vlan_tag;
-	u8      mac_addr[6];
+	u8      mac_addr[ETH_ALEN];
 	__le16  index;
 	__le16	ethter_type;
 	__le16  egress_port;
@@ -1018,16 +1037,16 @@
 #define HCLGE_FD_AD_DROP_B		0
 #define HCLGE_FD_AD_DIRECT_QID_B	1
 #define HCLGE_FD_AD_QID_S		2
-#define HCLGE_FD_AD_QID_M		GENMASK(12, 2)
+#define HCLGE_FD_AD_QID_M		GENMASK(11, 2)
 #define HCLGE_FD_AD_USE_COUNTER_B	12
 #define HCLGE_FD_AD_COUNTER_NUM_S	13
 #define HCLGE_FD_AD_COUNTER_NUM_M	GENMASK(20, 13)
 #define HCLGE_FD_AD_NXT_STEP_B		20
 #define HCLGE_FD_AD_NXT_KEY_S		21
-#define HCLGE_FD_AD_NXT_KEY_M		GENMASK(26, 21)
+#define HCLGE_FD_AD_NXT_KEY_M		GENMASK(25, 21)
 #define HCLGE_FD_AD_WR_RULE_ID_B	0
 #define HCLGE_FD_AD_RULE_ID_S		1
-#define HCLGE_FD_AD_RULE_ID_M		GENMASK(13, 1)
+#define HCLGE_FD_AD_RULE_ID_M		GENMASK(12, 1)
 
 struct hclge_fd_ad_config_cmd {
 	u8 stage;
@@ -1090,9 +1109,6 @@
 				enum hclge_opcode_type opcode, bool is_read);
 void hclge_cmd_reuse_desc(struct hclge_desc *desc, bool is_read);
 
-int hclge_cmd_set_promisc_mode(struct hclge_dev *hdev,
-			       struct hclge_promisc_param *param);
-
 enum hclge_cmd_status hclge_cmd_mdio_write(struct hclge_hw *hw,
 					   struct hclge_desc *desc);
 enum hclge_cmd_status hclge_cmd_mdio_read(struct hclge_hw *hw,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c
@@ -87,7 +87,7 @@
 	for (i = 0; i < HNAE3_MAX_USER_PRIO; i++) {
 		if (prio_tc[i] >= num_tc) {
 			dev_err(&hdev->pdev->dev,
-				"prio_tc[%u] checking failed, %u >= num_tc(%u)\n",
+				"prio_tc[%d] checking failed, %u >= num_tc(%u)\n",
 				i, prio_tc[i], num_tc);
 			return -EINVAL;
 		}
@@ -124,7 +124,7 @@
 	if (ret)
 		return ret;
 
-	for (i = 0; i < hdev->tc_max; i++) {
+	for (i = 0; i < HNAE3_MAX_TC; i++) {
 		switch (ets->tc_tsa[i]) {
 		case IEEE_8021QAZ_TSA_STRICT:
 			if (hdev->tm_info.tc_info[i].tc_sch_mode !=
@@ -132,6 +132,15 @@
 				*changed = true;
 			break;
 		case IEEE_8021QAZ_TSA_ETS:
+			/* The hardware will switch to sp mode if bandwidth is
+			 * 0, so limit ets bandwidth must be greater than 0.
+			 */
+			if (!ets->tc_tx_bw[i]) {
+				dev_err(&hdev->pdev->dev,
+					"tc%u ets bw cannot be 0\n", i);
+				return -EINVAL;
+			}
+
 			if (hdev->tm_info.tc_info[i].tc_sch_mode !=
 				HCLGE_SCH_MODE_DWRR)
 				*changed = true;
@@ -281,21 +290,12 @@
 	u64 requests[HNAE3_MAX_TC], indications[HNAE3_MAX_TC];
 	struct hclge_vport *vport = hclge_get_vport(h);
 	struct hclge_dev *hdev = vport->back;
-	u8 i, j, pfc_map, *prio_tc;
 	int ret;
+	u8 i;
 
 	memset(pfc, 0, sizeof(*pfc));
 	pfc->pfc_cap = hdev->pfc_max;
-	prio_tc = hdev->tm_info.prio_tc;
-	pfc_map = hdev->tm_info.hw_pfc_map;
-
-	/* Pfc setting is based on TC */
-	for (i = 0; i < hdev->tm_info.num_tc; i++) {
-		for (j = 0; j < HNAE3_MAX_USER_PRIO; j++) {
-			if ((prio_tc[j] == i) && (pfc_map & BIT(i)))
-				pfc->pfc_en |= BIT(j);
-		}
-	}
+	pfc->pfc_en = hdev->tm_info.pfc_en;
 
 	ret = hclge_pfc_tx_stats_get(hdev, requests);
 	if (ret)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
@@ -73,8 +73,6 @@
 
 static int hclge_dbg_get_dfx_bd_num(struct hclge_dev *hdev, int offset)
 {
-#define HCLGE_GET_DFX_REG_TYPE_CNT	4
-
 	struct hclge_desc desc[HCLGE_GET_DFX_REG_TYPE_CNT];
 	int entries_per_desc;
 	int index;
@@ -89,7 +87,7 @@
 
 	entries_per_desc = ARRAY_SIZE(desc[0].data);
 	index = offset % entries_per_desc;
-	return (int)desc[offset / entries_per_desc].data[index];
+	return le32_to_cpu(desc[offset / entries_per_desc].data[index]);
 }
 
 static int hclge_dbg_cmd_send(struct hclge_dev *hdev,
@@ -145,15 +143,13 @@
 		return;
 	}
 
-	buf_len	 = sizeof(struct hclge_desc) * bd_num;
+	buf_len	= sizeof(struct hclge_desc) * bd_num;
 	desc_src = kzalloc(buf_len, GFP_KERNEL);
-	if (!desc_src) {
-		dev_err(&hdev->pdev->dev, "call kzalloc failed\n");
+	if (!desc_src)
 		return;
-	}
 
 	desc = desc_src;
-	ret  = hclge_dbg_cmd_send(hdev, desc, index, bd_num, reg_msg->cmd);
+	ret = hclge_dbg_cmd_send(hdev, desc, index, bd_num, reg_msg->cmd);
 	if (ret) {
 		kfree(desc_src);
 		return;
@@ -169,7 +165,7 @@
 		if (dfx_message->flag)
 			dev_info(&hdev->pdev->dev, "%s: 0x%x\n",
 				 dfx_message->message,
-				 desc->data[i % entries_per_desc]);
+				 le32_to_cpu(desc->data[i % entries_per_desc]));
 
 		dfx_message++;
 	}
@@ -181,6 +177,7 @@
 {
 	struct device *dev = &hdev->pdev->dev;
 	struct hclge_dbg_bitmap_cmd *bitmap;
+	enum hclge_opcode_type cmd;
 	int rq_id, pri_id, qset_id;
 	int port_id, nq_id, pg_id;
 	struct hclge_desc desc[2];
@@ -195,10 +192,10 @@
 		return;
 	}
 
-	ret = hclge_dbg_cmd_send(hdev, desc, qset_id, 1,
-				 HCLGE_OPC_QSET_DFX_STS);
+	cmd = HCLGE_OPC_QSET_DFX_STS;
+	ret = hclge_dbg_cmd_send(hdev, desc, qset_id, 1, cmd);
 	if (ret)
-		return;
+		goto err_dcb_cmd_send;
 
 	bitmap = (struct hclge_dbg_bitmap_cmd *)&desc[0].data[1];
 	dev_info(dev, "roce_qset_mask: 0x%x\n", bitmap->bit0);
@@ -206,75 +203,90 @@
 	dev_info(dev, "qs_shaping_pass: 0x%x\n", bitmap->bit2);
 	dev_info(dev, "qs_bp_sts: 0x%x\n", bitmap->bit3);
 
-	ret = hclge_dbg_cmd_send(hdev, desc, pri_id, 1, HCLGE_OPC_PRI_DFX_STS);
+	cmd = HCLGE_OPC_PRI_DFX_STS;
+	ret = hclge_dbg_cmd_send(hdev, desc, pri_id, 1, cmd);
 	if (ret)
-		return;
+		goto err_dcb_cmd_send;
 
 	bitmap = (struct hclge_dbg_bitmap_cmd *)&desc[0].data[1];
 	dev_info(dev, "pri_mask: 0x%x\n", bitmap->bit0);
 	dev_info(dev, "pri_cshaping_pass: 0x%x\n", bitmap->bit1);
 	dev_info(dev, "pri_pshaping_pass: 0x%x\n", bitmap->bit2);
 
-	ret = hclge_dbg_cmd_send(hdev, desc, pg_id, 1, HCLGE_OPC_PG_DFX_STS);
+	cmd = HCLGE_OPC_PG_DFX_STS;
+	ret = hclge_dbg_cmd_send(hdev, desc, pg_id, 1, cmd);
 	if (ret)
-		return;
+		goto err_dcb_cmd_send;
 
 	bitmap = (struct hclge_dbg_bitmap_cmd *)&desc[0].data[1];
 	dev_info(dev, "pg_mask: 0x%x\n", bitmap->bit0);
 	dev_info(dev, "pg_cshaping_pass: 0x%x\n", bitmap->bit1);
 	dev_info(dev, "pg_pshaping_pass: 0x%x\n", bitmap->bit2);
 
-	ret = hclge_dbg_cmd_send(hdev, desc, port_id, 1,
-				 HCLGE_OPC_PORT_DFX_STS);
+	cmd = HCLGE_OPC_PORT_DFX_STS;
+	ret = hclge_dbg_cmd_send(hdev, desc, port_id, 1, cmd);
 	if (ret)
-		return;
+		goto err_dcb_cmd_send;
 
 	bitmap = (struct hclge_dbg_bitmap_cmd *)&desc[0].data[1];
 	dev_info(dev, "port_mask: 0x%x\n", bitmap->bit0);
 	dev_info(dev, "port_shaping_pass: 0x%x\n", bitmap->bit1);
 
-	ret = hclge_dbg_cmd_send(hdev, desc, nq_id, 1, HCLGE_OPC_SCH_NQ_CNT);
+	cmd = HCLGE_OPC_SCH_NQ_CNT;
+	ret = hclge_dbg_cmd_send(hdev, desc, nq_id, 1, cmd);
 	if (ret)
-		return;
+		goto err_dcb_cmd_send;
 
-	dev_info(dev, "sch_nq_cnt: 0x%x\n", desc[0].data[1]);
+	dev_info(dev, "sch_nq_cnt: 0x%x\n", le32_to_cpu(desc[0].data[1]));
 
-	ret = hclge_dbg_cmd_send(hdev, desc, nq_id, 1, HCLGE_OPC_SCH_RQ_CNT);
+	cmd = HCLGE_OPC_SCH_RQ_CNT;
+	ret = hclge_dbg_cmd_send(hdev, desc, nq_id, 1, cmd);
 	if (ret)
-		return;
+		goto err_dcb_cmd_send;
 
-	dev_info(dev, "sch_rq_cnt: 0x%x\n", desc[0].data[1]);
+	dev_info(dev, "sch_rq_cnt: 0x%x\n", le32_to_cpu(desc[0].data[1]));
 
-	ret = hclge_dbg_cmd_send(hdev, desc, 0, 2, HCLGE_OPC_TM_INTERNAL_STS);
+	cmd = HCLGE_OPC_TM_INTERNAL_STS;
+	ret = hclge_dbg_cmd_send(hdev, desc, 0, 2, cmd);
 	if (ret)
-		return;
+		goto err_dcb_cmd_send;
 
-	dev_info(dev, "pri_bp: 0x%x\n", desc[0].data[1]);
-	dev_info(dev, "fifo_dfx_info: 0x%x\n", desc[0].data[2]);
-	dev_info(dev, "sch_roce_fifo_afull_gap: 0x%x\n", desc[0].data[3]);
-	dev_info(dev, "tx_private_waterline: 0x%x\n", desc[0].data[4]);
-	dev_info(dev, "tm_bypass_en: 0x%x\n", desc[0].data[5]);
-	dev_info(dev, "SSU_TM_BYPASS_EN: 0x%x\n", desc[1].data[0]);
-	dev_info(dev, "SSU_RESERVE_CFG: 0x%x\n", desc[1].data[1]);
+	dev_info(dev, "pri_bp: 0x%x\n", le32_to_cpu(desc[0].data[1]));
+	dev_info(dev, "fifo_dfx_info: 0x%x\n", le32_to_cpu(desc[0].data[2]));
+	dev_info(dev, "sch_roce_fifo_afull_gap: 0x%x\n",
+		 le32_to_cpu(desc[0].data[3]));
+	dev_info(dev, "tx_private_waterline: 0x%x\n",
+		 le32_to_cpu(desc[0].data[4]));
+	dev_info(dev, "tm_bypass_en: 0x%x\n", le32_to_cpu(desc[0].data[5]));
+	dev_info(dev, "SSU_TM_BYPASS_EN: 0x%x\n", le32_to_cpu(desc[1].data[0]));
+	dev_info(dev, "SSU_RESERVE_CFG: 0x%x\n", le32_to_cpu(desc[1].data[1]));
 
-	ret = hclge_dbg_cmd_send(hdev, desc, port_id, 1,
-				 HCLGE_OPC_TM_INTERNAL_CNT);
+	cmd = HCLGE_OPC_TM_INTERNAL_CNT;
+	ret = hclge_dbg_cmd_send(hdev, desc, port_id, 1, cmd);
 	if (ret)
-		return;
+		goto err_dcb_cmd_send;
 
-	dev_info(dev, "SCH_NIC_NUM: 0x%x\n", desc[0].data[1]);
-	dev_info(dev, "SCH_ROCE_NUM: 0x%x\n", desc[0].data[2]);
+	dev_info(dev, "SCH_NIC_NUM: 0x%x\n", le32_to_cpu(desc[0].data[1]));
+	dev_info(dev, "SCH_ROCE_NUM: 0x%x\n", le32_to_cpu(desc[0].data[2]));
 
-	ret = hclge_dbg_cmd_send(hdev, desc, port_id, 1,
-				 HCLGE_OPC_TM_INTERNAL_STS_1);
+	cmd = HCLGE_OPC_TM_INTERNAL_STS_1;
+	ret = hclge_dbg_cmd_send(hdev, desc, port_id, 1, cmd);
 	if (ret)
-		return;
+		goto err_dcb_cmd_send;
+
+	dev_info(dev, "TC_MAP_SEL: 0x%x\n", le32_to_cpu(desc[0].data[1]));
+	dev_info(dev, "IGU_PFC_PRI_EN: 0x%x\n", le32_to_cpu(desc[0].data[2]));
+	dev_info(dev, "MAC_PFC_PRI_EN: 0x%x\n", le32_to_cpu(desc[0].data[3]));
+	dev_info(dev, "IGU_PRI_MAP_TC_CFG: 0x%x\n",
+		 le32_to_cpu(desc[0].data[4]));
+	dev_info(dev, "IGU_TX_PRI_MAP_TC_CFG: 0x%x\n",
+		 le32_to_cpu(desc[0].data[5]));
+	return;
 
-	dev_info(dev, "TC_MAP_SEL: 0x%x\n", desc[0].data[1]);
-	dev_info(dev, "IGU_PFC_PRI_EN: 0x%x\n", desc[0].data[2]);
-	dev_info(dev, "MAC_PFC_PRI_EN: 0x%x\n", desc[0].data[3]);
-	dev_info(dev, "IGU_PRI_MAP_TC_CFG: 0x%x\n", desc[0].data[4]);
-	dev_info(dev, "IGU_TX_PRI_MAP_TC_CFG: 0x%x\n", desc[0].data[5]);
+err_dcb_cmd_send:
+	dev_err(&hdev->pdev->dev,
+		"failed to dump dcb dfx, cmd = %#x, ret = %d\n",
+		cmd, ret);
 }
 
 static void hclge_dbg_dump_reg_cmd(struct hclge_dev *hdev, const char *cmd_buf)
@@ -308,8 +320,9 @@
 				  char *false_buf)
 {
 	if (flag)
-		dev_info(&hdev->pdev->dev, "%s(%d): %s\n", title_buf, index,
-			 true_buf);
+		dev_info(&hdev->pdev->dev, "%s(%d): %s weight: %u\n",
+			 title_buf, index, true_buf,
+			 hdev->tm_info.pg_info[0].tc_dwrr[index]);
 	else
 		dev_info(&hdev->pdev->dev, "%s(%d): %s\n", title_buf, index,
 			 false_buf);
@@ -337,7 +350,8 @@
 
 	ets_weight = (struct hclge_ets_tc_weight_cmd *)desc.data;
 
-	dev_info(&hdev->pdev->dev, "dump tc\n");
+	dev_info(&hdev->pdev->dev, "dump tc: %u tc enabled\n",
+		 hdev->tm_info.num_tc);
 	dev_info(&hdev->pdev->dev, "weight_offset: %u\n",
 		 ets_weight->weight_offset);
 
@@ -364,7 +378,7 @@
 	pg_shap_cfg_cmd = (struct hclge_pg_shapping_cmd *)desc.data;
 	dev_info(&hdev->pdev->dev, "PG_C pg_id: %u\n", pg_shap_cfg_cmd->pg_id);
 	dev_info(&hdev->pdev->dev, "PG_C pg_shapping: 0x%x\n",
-		 pg_shap_cfg_cmd->pg_shapping_para);
+		 le32_to_cpu(pg_shap_cfg_cmd->pg_shapping_para));
 
 	cmd = HCLGE_OPC_TM_PG_P_SHAPPING;
 	hclge_cmd_setup_basic_desc(&desc, cmd, true);
@@ -375,7 +389,7 @@
 	pg_shap_cfg_cmd = (struct hclge_pg_shapping_cmd *)desc.data;
 	dev_info(&hdev->pdev->dev, "PG_P pg_id: %u\n", pg_shap_cfg_cmd->pg_id);
 	dev_info(&hdev->pdev->dev, "PG_P pg_shapping: 0x%x\n",
-		 pg_shap_cfg_cmd->pg_shapping_para);
+		 le32_to_cpu(pg_shap_cfg_cmd->pg_shapping_para));
 
 	cmd = HCLGE_OPC_TM_PORT_SHAPPING;
 	hclge_cmd_setup_basic_desc(&desc, cmd, true);
@@ -385,7 +399,7 @@
 
 	port_shap_cfg_cmd = (struct hclge_port_shapping_cmd *)desc.data;
 	dev_info(&hdev->pdev->dev, "PORT port_shapping: 0x%x\n",
-		 port_shap_cfg_cmd->port_shapping_para);
+		 le32_to_cpu(port_shap_cfg_cmd->port_shapping_para));
 
 	cmd = HCLGE_OPC_TM_PG_SCH_MODE_CFG;
 	hclge_cmd_setup_basic_desc(&desc, cmd, true);
@@ -393,7 +407,8 @@
 	if (ret)
 		goto err_tm_pg_cmd_send;
 
-	dev_info(&hdev->pdev->dev, "PG_SCH pg_id: %u\n", desc.data[0]);
+	dev_info(&hdev->pdev->dev, "PG_SCH pg_id: %u\n",
+		 le32_to_cpu(desc.data[0]));
 
 	cmd = HCLGE_OPC_TM_PRI_SCH_MODE_CFG;
 	hclge_cmd_setup_basic_desc(&desc, cmd, true);
@@ -401,7 +416,8 @@
 	if (ret)
 		goto err_tm_pg_cmd_send;
 
-	dev_info(&hdev->pdev->dev, "PRI_SCH pri_id: %u\n", desc.data[0]);
+	dev_info(&hdev->pdev->dev, "PRI_SCH pri_id: %u\n",
+		 le32_to_cpu(desc.data[0]));
 
 	cmd = HCLGE_OPC_TM_QS_SCH_MODE_CFG;
 	hclge_cmd_setup_basic_desc(&desc, cmd, true);
@@ -409,7 +425,8 @@
 	if (ret)
 		goto err_tm_pg_cmd_send;
 
-	dev_info(&hdev->pdev->dev, "QS_SCH qs_id: %u\n", desc.data[0]);
+	dev_info(&hdev->pdev->dev, "QS_SCH qs_id: %u\n",
+		 le32_to_cpu(desc.data[0]));
 
 	if (!hnae3_dev_dcb_supported(hdev)) {
 		dev_info(&hdev->pdev->dev,
@@ -429,7 +446,7 @@
 	dev_info(&hdev->pdev->dev, "BP_TO_QSET qs_group_id: 0x%x\n",
 		 bp_to_qs_map_cmd->qs_group_id);
 	dev_info(&hdev->pdev->dev, "BP_TO_QSET qs_bit_map: 0x%x\n",
-		 bp_to_qs_map_cmd->qs_bit_map);
+		 le32_to_cpu(bp_to_qs_map_cmd->qs_bit_map));
 	return;
 
 err_tm_pg_cmd_send:
@@ -471,7 +488,7 @@
 
 	qs_to_pri_map = (struct hclge_qs_to_pri_link_cmd *)desc.data;
 	dev_info(&hdev->pdev->dev, "QS_TO_PRI qs_id: %u\n",
-		 qs_to_pri_map->qs_id);
+		 le16_to_cpu(qs_to_pri_map->qs_id));
 	dev_info(&hdev->pdev->dev, "QS_TO_PRI priority: %u\n",
 		 qs_to_pri_map->priority);
 	dev_info(&hdev->pdev->dev, "QS_TO_PRI link_vld: %u\n",
@@ -484,9 +501,10 @@
 		goto err_tm_cmd_send;
 
 	nq_to_qs_map = (struct hclge_nq_to_qs_link_cmd *)desc.data;
-	dev_info(&hdev->pdev->dev, "NQ_TO_QS nq_id: %u\n", nq_to_qs_map->nq_id);
+	dev_info(&hdev->pdev->dev, "NQ_TO_QS nq_id: %u\n",
+		 le16_to_cpu(nq_to_qs_map->nq_id));
 	dev_info(&hdev->pdev->dev, "NQ_TO_QS qset_id: 0x%x\n",
-		 nq_to_qs_map->qset_id);
+		 le16_to_cpu(nq_to_qs_map->qset_id));
 
 	cmd = HCLGE_OPC_TM_PG_WEIGHT;
 	hclge_cmd_setup_basic_desc(&desc, cmd, true);
@@ -505,7 +523,8 @@
 		goto err_tm_cmd_send;
 
 	qs_weight = (struct hclge_qs_weight_cmd *)desc.data;
-	dev_info(&hdev->pdev->dev, "QS qs_id: %u\n", qs_weight->qs_id);
+	dev_info(&hdev->pdev->dev, "QS qs_id: %u\n",
+		 le16_to_cpu(qs_weight->qs_id));
 	dev_info(&hdev->pdev->dev, "QS dwrr: %u\n", qs_weight->dwrr);
 
 	cmd = HCLGE_OPC_TM_PRI_WEIGHT;
@@ -527,7 +546,7 @@
 	shap_cfg_cmd = (struct hclge_pri_shapping_cmd *)desc.data;
 	dev_info(&hdev->pdev->dev, "PRI_C pri_id: %u\n", shap_cfg_cmd->pri_id);
 	dev_info(&hdev->pdev->dev, "PRI_C pri_shapping: 0x%x\n",
-		 shap_cfg_cmd->pri_shapping_para);
+		 le32_to_cpu(shap_cfg_cmd->pri_shapping_para));
 
 	cmd = HCLGE_OPC_TM_PRI_P_SHAPPING;
 	hclge_cmd_setup_basic_desc(&desc, cmd, true);
@@ -538,7 +557,7 @@
 	shap_cfg_cmd = (struct hclge_pri_shapping_cmd *)desc.data;
 	dev_info(&hdev->pdev->dev, "PRI_P pri_id: %u\n", shap_cfg_cmd->pri_id);
 	dev_info(&hdev->pdev->dev, "PRI_P pri_shapping: 0x%x\n",
-		 shap_cfg_cmd->pri_shapping_para);
+		 le32_to_cpu(shap_cfg_cmd->pri_shapping_para));
 
 	hclge_dbg_dump_tm_pg(hdev);
 
@@ -574,7 +593,7 @@
 	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
 	if (ret)
 		goto err_tm_map_cmd_send;
-	qset_id = nq_to_qs_map->qset_id & 0x3FF;
+	qset_id = le16_to_cpu(nq_to_qs_map->qset_id) & 0x3FF;
 
 	cmd = HCLGE_OPC_TM_QS_TO_PRI_LINK;
 	map = (struct hclge_qs_to_pri_link_cmd *)desc.data;
@@ -614,7 +633,8 @@
 		if (ret)
 			goto err_tm_map_cmd_send;
 
-		qset_maping[group_id] = bp_to_qs_map_cmd->qs_bit_map;
+		qset_maping[group_id] =
+			le32_to_cpu(bp_to_qs_map_cmd->qs_bit_map);
 	}
 
 	dev_info(&hdev->pdev->dev, "index | tm bp qset maping:\n");
@@ -658,7 +678,7 @@
 	dev_info(&hdev->pdev->dev, "pause_trans_gap: 0x%x\n",
 		 pause_param->pause_trans_gap);
 	dev_info(&hdev->pdev->dev, "pause_trans_time: 0x%x\n",
-		 pause_param->pause_trans_time);
+		 le16_to_cpu(pause_param->pause_trans_time));
 }
 
 static void hclge_dbg_dump_qos_pri_map(struct hclge_dev *hdev)
@@ -712,7 +732,7 @@
 	tx_buf_cmd = (struct hclge_tx_buff_alloc_cmd *)desc[0].data;
 	for (i = 0; i < HCLGE_MAX_TC_NUM; i++)
 		dev_info(&hdev->pdev->dev, "tx_packet_buf_tc_%d: 0x%x\n", i,
-			 tx_buf_cmd->tx_pkt_buff[i]);
+			 le16_to_cpu(tx_buf_cmd->tx_pkt_buff[i]));
 
 	cmd = HCLGE_OPC_RX_PRIV_BUFF_ALLOC;
 	hclge_cmd_setup_basic_desc(desc, cmd, true);
@@ -724,10 +744,10 @@
 	rx_buf_cmd = (struct hclge_rx_priv_buff_cmd *)desc[0].data;
 	for (i = 0; i < HCLGE_MAX_TC_NUM; i++)
 		dev_info(&hdev->pdev->dev, "rx_packet_buf_tc_%d: 0x%x\n", i,
-			 rx_buf_cmd->buf_num[i]);
+			 le16_to_cpu(rx_buf_cmd->buf_num[i]));
 
 	dev_info(&hdev->pdev->dev, "rx_share_buf: 0x%x\n",
-		 rx_buf_cmd->shared_buf);
+		 le16_to_cpu(rx_buf_cmd->shared_buf));
 
 	cmd = HCLGE_OPC_RX_COM_WL_ALLOC;
 	hclge_cmd_setup_basic_desc(desc, cmd, true);
@@ -738,7 +758,8 @@
 	rx_com_wl = (struct hclge_rx_com_wl *)desc[0].data;
 	dev_info(&hdev->pdev->dev, "\n");
 	dev_info(&hdev->pdev->dev, "rx_com_wl: high: 0x%x, low: 0x%x\n",
-		 rx_com_wl->com_wl.high, rx_com_wl->com_wl.low);
+		 le16_to_cpu(rx_com_wl->com_wl.high),
+		 le16_to_cpu(rx_com_wl->com_wl.low));
 
 	cmd = HCLGE_OPC_RX_GBL_PKT_CNT;
 	hclge_cmd_setup_basic_desc(desc, cmd, true);
@@ -749,7 +770,8 @@
 	rx_packet_cnt = (struct hclge_rx_com_wl *)desc[0].data;
 	dev_info(&hdev->pdev->dev,
 		 "rx_global_packet_cnt: high: 0x%x, low: 0x%x\n",
-		 rx_packet_cnt->com_wl.high, rx_packet_cnt->com_wl.low);
+		 le16_to_cpu(rx_packet_cnt->com_wl.high),
+		 le16_to_cpu(rx_packet_cnt->com_wl.low));
 	dev_info(&hdev->pdev->dev, "\n");
 
 	if (!hnae3_dev_dcb_supported(hdev)) {
@@ -769,14 +791,16 @@
 	for (i = 0; i < HCLGE_TC_NUM_ONE_DESC; i++)
 		dev_info(&hdev->pdev->dev,
 			 "rx_priv_wl_tc_%d: high: 0x%x, low: 0x%x\n", i,
-			 rx_priv_wl->tc_wl[i].high, rx_priv_wl->tc_wl[i].low);
+			 le16_to_cpu(rx_priv_wl->tc_wl[i].high),
+			 le16_to_cpu(rx_priv_wl->tc_wl[i].low));
 
 	rx_priv_wl = (struct hclge_rx_priv_wl_buf *)desc[1].data;
 	for (i = 0; i < HCLGE_TC_NUM_ONE_DESC; i++)
 		dev_info(&hdev->pdev->dev,
 			 "rx_priv_wl_tc_%d: high: 0x%x, low: 0x%x\n",
 			 i + HCLGE_TC_NUM_ONE_DESC,
-			 rx_priv_wl->tc_wl[i].high, rx_priv_wl->tc_wl[i].low);
+			 le16_to_cpu(rx_priv_wl->tc_wl[i].high),
+			 le16_to_cpu(rx_priv_wl->tc_wl[i].low));
 
 	cmd = HCLGE_OPC_RX_COM_THRD_ALLOC;
 	hclge_cmd_setup_basic_desc(&desc[0], cmd, true);
@@ -791,16 +815,16 @@
 	for (i = 0; i < HCLGE_TC_NUM_ONE_DESC; i++)
 		dev_info(&hdev->pdev->dev,
 			 "rx_com_thrd_tc_%d: high: 0x%x, low: 0x%x\n", i,
-			 rx_com_thrd->com_thrd[i].high,
-			 rx_com_thrd->com_thrd[i].low);
+			 le16_to_cpu(rx_com_thrd->com_thrd[i].high),
+			 le16_to_cpu(rx_com_thrd->com_thrd[i].low));
 
 	rx_com_thrd = (struct hclge_rx_com_thrd *)desc[1].data;
 	for (i = 0; i < HCLGE_TC_NUM_ONE_DESC; i++)
 		dev_info(&hdev->pdev->dev,
 			 "rx_com_thrd_tc_%d: high: 0x%x, low: 0x%x\n",
 			 i + HCLGE_TC_NUM_ONE_DESC,
-			 rx_com_thrd->com_thrd[i].high,
-			 rx_com_thrd->com_thrd[i].low);
+			 le16_to_cpu(rx_com_thrd->com_thrd[i].high),
+			 le16_to_cpu(rx_com_thrd->com_thrd[i].low));
 	return;
 
 err_qos_cmd_send:
@@ -813,6 +837,7 @@
 	struct hclge_mac_ethertype_idx_rd_cmd *req0;
 	char printf_buf[HCLGE_DBG_BUF_LEN];
 	struct hclge_desc desc;
+	u32 msg_egress_port;
 	int ret, i;
 
 	dev_info(&hdev->pdev->dev, "mng tab:\n");
@@ -845,7 +870,8 @@
 		memset(printf_buf, 0, HCLGE_DBG_BUF_LEN);
 		snprintf(printf_buf, HCLGE_DBG_BUF_LEN,
 			 "%02u   |%02x:%02x:%02x:%02x:%02x:%02x|",
-			 req0->index, req0->mac_addr[0], req0->mac_addr[1],
+			 le16_to_cpu(req0->index),
+			 req0->mac_addr[0], req0->mac_addr[1],
 			 req0->mac_addr[2], req0->mac_addr[3],
 			 req0->mac_addr[4], req0->mac_addr[5]);
 
@@ -853,27 +879,28 @@
 			 HCLGE_DBG_BUF_LEN - strlen(printf_buf),
 			 "%x   |%04x |%x   |%04x|%x   |%02x   |%02x   |",
 			 !!(req0->flags & HCLGE_DBG_MNG_MAC_MASK_B),
-			 req0->ethter_type,
+			 le16_to_cpu(req0->ethter_type),
 			 !!(req0->flags & HCLGE_DBG_MNG_ETHER_MASK_B),
-			 req0->vlan_tag & HCLGE_DBG_MNG_VLAN_TAG,
+			 le16_to_cpu(req0->vlan_tag) & HCLGE_DBG_MNG_VLAN_TAG,
 			 !!(req0->flags & HCLGE_DBG_MNG_VLAN_MASK_B),
 			 req0->i_port_bitmap, req0->i_port_direction);
 
+		msg_egress_port = le16_to_cpu(req0->egress_port);
 		snprintf(printf_buf + strlen(printf_buf),
 			 HCLGE_DBG_BUF_LEN - strlen(printf_buf),
-			 "%d     |%d    |%02d   |%04d|%x\n",
-			 !!(req0->egress_port & HCLGE_DBG_MNG_E_TYPE_B),
-			 req0->egress_port & HCLGE_DBG_MNG_PF_ID,
-			 (req0->egress_port >> 3) & HCLGE_DBG_MNG_VF_ID,
-			 req0->egress_queue,
-			 !!(req0->egress_port & HCLGE_DBG_MNG_DROP_B));
+			 "%x     |%x    |%02x   |%04x|%x\n",
+			 !!(msg_egress_port & HCLGE_DBG_MNG_E_TYPE_B),
+			 msg_egress_port & HCLGE_DBG_MNG_PF_ID,
+			 (msg_egress_port >> 3) & HCLGE_DBG_MNG_VF_ID,
+			 le16_to_cpu(req0->egress_queue),
+			 !!(msg_egress_port & HCLGE_DBG_MNG_DROP_B));
 
 		dev_info(&hdev->pdev->dev, "%s", printf_buf);
 	}
 }
 
-static void hclge_dbg_fd_tcam_read(struct hclge_dev *hdev, u8 stage,
-				   bool sel_x, u32 loc)
+static int hclge_dbg_fd_tcam_read(struct hclge_dev *hdev, u8 stage,
+				  bool sel_x, u32 loc)
 {
 	struct hclge_fd_tcam_config_1_cmd *req1;
 	struct hclge_fd_tcam_config_2_cmd *req2;
@@ -898,7 +925,7 @@
 
 	ret = hclge_cmd_send(&hdev->hw, desc, 3);
 	if (ret)
-		return;
+		return ret;
 
 	dev_info(&hdev->pdev->dev, " read result tcam key %s(%u):\n",
 		 sel_x ? "x" : "y", loc);
@@ -917,19 +944,79 @@
 	req = (u32 *)req3->tcam_data;
 	for (i = 0; i < 5; i++)
 		dev_info(&hdev->pdev->dev, "%08x\n", *req++);
+
+	return ret;
+}
+
+static int hclge_dbg_get_rules_location(struct hclge_dev *hdev, u16 *rule_locs)
+{
+	struct hclge_fd_rule *rule;
+	struct hlist_node *node;
+	int cnt = 0;
+
+	spin_lock_bh(&hdev->fd_rule_lock);
+	hlist_for_each_entry_safe(rule, node, &hdev->fd_rule_list, rule_node) {
+		rule_locs[cnt] = rule->location;
+		cnt++;
+	}
+	spin_unlock_bh(&hdev->fd_rule_lock);
+
+	if (cnt != hdev->hclge_fd_rule_num)
+		return -EINVAL;
+
+	return cnt;
 }
 
 static void hclge_dbg_fd_tcam(struct hclge_dev *hdev)
 {
-	u32 i;
+	int i, ret, rule_cnt;
+	u16 *rule_locs;
+
+	if (!hnae3_dev_fd_supported(hdev)) {
+		dev_err(&hdev->pdev->dev,
+			"Only FD-supported dev supports dump fd tcam\n");
+		return;
+	}
+
+	if (!hdev->hclge_fd_rule_num ||
+	    !hdev->fd_cfg.rule_num[HCLGE_FD_STAGE_1])
+		return;
+
+	rule_locs = kcalloc(hdev->fd_cfg.rule_num[HCLGE_FD_STAGE_1],
+			    sizeof(u16), GFP_KERNEL);
+	if (!rule_locs)
+		return;
+
+	rule_cnt = hclge_dbg_get_rules_location(hdev, rule_locs);
+	if (rule_cnt <= 0) {
+		dev_err(&hdev->pdev->dev,
+			"failed to get rule number, ret = %d\n", rule_cnt);
+		kfree(rule_locs);
+		return;
+	}
+
+	for (i = 0; i < rule_cnt; i++) {
+		ret = hclge_dbg_fd_tcam_read(hdev, 0, true, rule_locs[i]);
+		if (ret) {
+			dev_err(&hdev->pdev->dev,
+				"failed to get fd tcam key x, ret = %d\n", ret);
+			kfree(rule_locs);
+			return;
+		}
 
-	for (i = 0; i < hdev->fd_cfg.rule_num[0]; i++) {
-		hclge_dbg_fd_tcam_read(hdev, 0, true, i);
-		hclge_dbg_fd_tcam_read(hdev, 0, false, i);
+		ret = hclge_dbg_fd_tcam_read(hdev, 0, false, rule_locs[i]);
+		if (ret) {
+			dev_err(&hdev->pdev->dev,
+				"failed to get fd tcam key y, ret = %d\n", ret);
+			kfree(rule_locs);
+			return;
+		}
 	}
+
+	kfree(rule_locs);
 }
 
-static void hclge_dbg_dump_rst_info(struct hclge_dev *hdev)
+void hclge_dbg_dump_rst_info(struct hclge_dev *hdev)
 {
 	dev_info(&hdev->pdev->dev, "PF reset count: %u\n",
 		 hdev->rst_stats.pf_rst_cnt);
@@ -945,8 +1032,6 @@
 		 hdev->rst_stats.hw_reset_done_cnt);
 	dev_info(&hdev->pdev->dev, "reset count: %u\n",
 		 hdev->rst_stats.reset_cnt);
-	dev_info(&hdev->pdev->dev, "reset count: %u\n",
-		 hdev->rst_stats.reset_cnt);
 	dev_info(&hdev->pdev->dev, "reset fail count: %u\n",
 		 hdev->rst_stats.reset_fail_cnt);
 	dev_info(&hdev->pdev->dev, "vector0 interrupt enable status: 0x%x\n",
@@ -961,6 +1046,15 @@
 		 hclge_read_dev(&hdev->hw, HCLGE_NIC_CSQ_DEPTH_REG));
 	dev_info(&hdev->pdev->dev, "function reset status: 0x%x\n",
 		 hclge_read_dev(&hdev->hw, HCLGE_FUN_RST_ING));
+	dev_info(&hdev->pdev->dev, "hdev state: 0x%lx\n", hdev->state);
+}
+
+static void hclge_dbg_dump_serv_info(struct hclge_dev *hdev)
+{
+	dev_info(&hdev->pdev->dev, "last_serv_processed: %lu\n",
+		 hdev->last_serv_processed);
+	dev_info(&hdev->pdev->dev, "last_serv_cnt: %lu\n",
+		 hdev->serv_processed_cnt);
 }
 
 static void hclge_dbg_get_m7_stats_info(struct hclge_dev *hdev)
@@ -986,11 +1080,8 @@
 
 	buf_len	 = sizeof(struct hclge_desc) * bd_num;
 	desc_src = kzalloc(buf_len, GFP_KERNEL);
-	if (!desc_src) {
-		dev_err(&hdev->pdev->dev,
-			"allocate desc for get_m7_stats failed\n");
+	if (!desc_src)
 		return;
-	}
 
 	desc_tmp = desc_src;
 	ret  = hclge_dbg_cmd_send(hdev, desc_tmp, 0, bd_num,
@@ -1053,7 +1144,7 @@
 				      const char *cmd_buf)
 {
 #define HCLGE_MAX_NCL_CONFIG_OFFSET	4096
-#define HCLGE_MAX_NCL_CONFIG_LENGTH	(20 + 24 * 4)
+#define HCLGE_NCL_CONFIG_LENGTH_IN_EACH_CMD	(20 + 24 * 4)
 
 	struct hclge_desc desc[HCLGE_CMD_NCL_CONFIG_BD_NUM];
 	int bd_num = HCLGE_CMD_NCL_CONFIG_BD_NUM;
@@ -1077,8 +1168,8 @@
 
 	while (length > 0) {
 		data0 = offset;
-		if (length >= HCLGE_MAX_NCL_CONFIG_LENGTH)
-			data0 |= HCLGE_MAX_NCL_CONFIG_LENGTH << 16;
+		if (length >= HCLGE_NCL_CONFIG_LENGTH_IN_EACH_CMD)
+			data0 |= HCLGE_NCL_CONFIG_LENGTH_IN_EACH_CMD << 16;
 		else
 			data0 |= length << 16;
 		ret = hclge_dbg_cmd_send(hdev, desc, data0, bd_num,
@@ -1090,6 +1181,57 @@
 	}
 }
 
+static void hclge_dbg_dump_loopback(struct hclge_dev *hdev,
+				    const char *cmd_buf)
+{
+	struct phy_device *phydev = hdev->hw.mac.phydev;
+	struct hclge_config_mac_mode_cmd *req_app;
+	struct hclge_serdes_lb_cmd *req_serdes;
+	struct hclge_desc desc;
+	u8 loopback_en;
+	int ret;
+
+	req_app = (struct hclge_config_mac_mode_cmd *)desc.data;
+	req_serdes = (struct hclge_serdes_lb_cmd *)desc.data;
+
+	dev_info(&hdev->pdev->dev, "mac id: %u\n", hdev->hw.mac.mac_id);
+
+	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CONFIG_MAC_MODE, true);
+	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+	if (ret) {
+		dev_err(&hdev->pdev->dev,
+			"failed to dump app loopback status, ret = %d\n", ret);
+		return;
+	}
+
+	loopback_en = hnae3_get_bit(le32_to_cpu(req_app->txrx_pad_fcs_loop_en),
+				    HCLGE_MAC_APP_LP_B);
+	dev_info(&hdev->pdev->dev, "app loopback: %s\n",
+		 loopback_en ? "on" : "off");
+
+	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_SERDES_LOOPBACK, true);
+	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+	if (ret) {
+		dev_err(&hdev->pdev->dev,
+			"failed to dump serdes loopback status, ret = %d\n",
+			ret);
+		return;
+	}
+
+	loopback_en = req_serdes->enable & HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B;
+	dev_info(&hdev->pdev->dev, "serdes serial loopback: %s\n",
+		 loopback_en ? "on" : "off");
+
+	loopback_en = req_serdes->enable &
+			HCLGE_CMD_SERDES_PARALLEL_INNER_LOOP_B;
+	dev_info(&hdev->pdev->dev, "serdes parallel loopback: %s\n",
+		 loopback_en ? "on" : "off");
+
+	if (phydev)
+		dev_info(&hdev->pdev->dev, "phy loopback: %s\n",
+			 phydev->loopback_enabled ? "on" : "off");
+}
+
 /* hclge_dbg_dump_mac_tnl_status: print message about mac tnl interrupt
  * @hdev: pointer to struct hclge_dev
  */
@@ -1110,10 +1252,87 @@
 	}
 }
 
+static void hclge_dbg_dump_qs_shaper_single(struct hclge_dev *hdev, u16 qsid)
+{
+	struct hclge_qs_shapping_cmd *shap_cfg_cmd;
+	u8 ir_u, ir_b, ir_s, bs_b, bs_s;
+	struct hclge_desc desc;
+	u32 shapping_para;
+	int ret;
+
+	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QCN_SHAPPING_CFG, true);
+
+	shap_cfg_cmd = (struct hclge_qs_shapping_cmd *)desc.data;
+	shap_cfg_cmd->qs_id = cpu_to_le16(qsid);
+
+	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+	if (ret) {
+		dev_err(&hdev->pdev->dev,
+			"qs%u failed to get tx_rate, ret=%d\n",
+			qsid, ret);
+		return;
+	}
+
+	shapping_para = le32_to_cpu(shap_cfg_cmd->qs_shapping_para);
+	ir_b = hclge_tm_get_field(shapping_para, IR_B);
+	ir_u = hclge_tm_get_field(shapping_para, IR_U);
+	ir_s = hclge_tm_get_field(shapping_para, IR_S);
+	bs_b = hclge_tm_get_field(shapping_para, BS_B);
+	bs_s = hclge_tm_get_field(shapping_para, BS_S);
+
+	dev_info(&hdev->pdev->dev,
+		 "qs%u ir_b:%u, ir_u:%u, ir_s:%u, bs_b:%u, bs_s:%u\n",
+		 qsid, ir_b, ir_u, ir_s, bs_b, bs_s);
+}
+
+static void hclge_dbg_dump_qs_shaper_all(struct hclge_dev *hdev)
+{
+	struct hnae3_knic_private_info *kinfo;
+	struct hclge_vport *vport;
+	int vport_id, i;
+
+	for (vport_id = 0; vport_id <= pci_num_vf(hdev->pdev); vport_id++) {
+		vport = &hdev->vport[vport_id];
+		kinfo = &vport->nic.kinfo;
+
+		dev_info(&hdev->pdev->dev, "qs cfg of vport%d:\n", vport_id);
+
+		for (i = 0; i < kinfo->num_tc; i++) {
+			u16 qsid = vport->qs_offset + i;
+
+			hclge_dbg_dump_qs_shaper_single(hdev, qsid);
+		}
+	}
+}
+
+static void hclge_dbg_dump_qs_shaper(struct hclge_dev *hdev,
+				     const char *cmd_buf)
+{
+#define HCLGE_MAX_QSET_NUM 1024
+
+	u16 qsid;
+	int ret;
+
+	ret = kstrtou16(cmd_buf, 0, &qsid);
+	if (ret) {
+		hclge_dbg_dump_qs_shaper_all(hdev);
+		return;
+	}
+
+	if (qsid >= HCLGE_MAX_QSET_NUM) {
+		dev_err(&hdev->pdev->dev, "qsid(%u) out of range[0-1023]\n",
+			qsid);
+		return;
+	}
+
+	hclge_dbg_dump_qs_shaper_single(hdev, qsid);
+}
+
 int hclge_dbg_run_cmd(struct hnae3_handle *handle, const char *cmd_buf)
 {
 #define DUMP_REG	"dump reg"
 #define DUMP_TM_MAP	"dump tm map"
+#define DUMP_LOOPBACK	"dump loopback"
 
 	struct hclge_vport *vport = hclge_get_vport(handle);
 	struct hclge_dev *hdev = vport->back;
@@ -1138,6 +1357,8 @@
 		hclge_dbg_dump_reg_cmd(hdev, &cmd_buf[sizeof(DUMP_REG)]);
 	} else if (strncmp(cmd_buf, "dump reset info", 15) == 0) {
 		hclge_dbg_dump_rst_info(hdev);
+	} else if (strncmp(cmd_buf, "dump serv info", 14) == 0) {
+		hclge_dbg_dump_serv_info(hdev);
 	} else if (strncmp(cmd_buf, "dump m7 info", 12) == 0) {
 		hclge_dbg_get_m7_stats_info(hdev);
 	} else if (strncmp(cmd_buf, "dump ncl_config", 15) == 0) {
@@ -1145,6 +1366,12 @@
 					  &cmd_buf[sizeof("dump ncl_config")]);
 	} else if (strncmp(cmd_buf, "dump mac tnl status", 19) == 0) {
 		hclge_dbg_dump_mac_tnl_status(hdev);
+	} else if (strncmp(cmd_buf, DUMP_LOOPBACK,
+		   strlen(DUMP_LOOPBACK)) == 0) {
+		hclge_dbg_dump_loopback(hdev, &cmd_buf[sizeof(DUMP_LOOPBACK)]);
+	} else if (strncmp(cmd_buf, "dump qs shaper", 14) == 0) {
+		hclge_dbg_dump_qs_shaper(hdev,
+					 &cmd_buf[sizeof("dump qs shaper")]);
 	} else {
 		dev_info(&hdev->pdev->dev, "unknown command\n");
 		return -EINVAL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h
@@ -35,8 +35,6 @@
 
 #define HCLGE_DBG_DFX_SSU_2_OFFSET 12
 
-#pragma pack(1)
-
 struct hclge_qos_pri_map_cmd {
 	u8 pri0_tc  : 4,
 	   pri1_tc  : 4;
@@ -85,8 +83,6 @@
 	struct hclge_dbg_reg_common_msg reg_msg;
 };
 
-#pragma pack()
-
 static struct hclge_dbg_dfx_message hclge_dbg_bios_common_reg[] = {
 	{false, "Reserved"},
 	{true,	"BP_CPU_STATE"},
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.c
@@ -505,7 +505,7 @@
 
 static const struct hclge_hw_error hclge_ssu_port_based_err_int[] = {
 	{ .int_msk = BIT(0), .msg = "roc_pkt_without_key_port",
-	  .reset_level = HNAE3_GLOBAL_RESET },
+	  .reset_level = HNAE3_FUNC_RESET },
 	{ .int_msk = BIT(1), .msg = "tpu_pkt_without_key_port",
 	  .reset_level = HNAE3_GLOBAL_RESET },
 	{ .int_msk = BIT(2), .msg = "igu_pkt_without_key_port",
@@ -599,7 +599,7 @@
 
 static const struct hclge_hw_error hclge_ssu_port_based_pf_int[] = {
 	{ .int_msk = BIT(0), .msg = "roc_pkt_without_key_port",
-	  .reset_level = HNAE3_GLOBAL_RESET },
+	  .reset_level = HNAE3_FUNC_RESET },
 	{ .int_msk = BIT(9), .msg = "low_water_line_err_port",
 	  .reset_level = HNAE3_NONE_RESET },
 	{ .int_msk = BIT(10), .msg = "hi_water_line_err_port",
@@ -753,8 +753,9 @@
 
 	/* configure IGU,EGU error interrupts */
 	hclge_cmd_setup_basic_desc(&desc, HCLGE_IGU_COMMON_INT_EN, false);
+	desc.data[0] = cpu_to_le32(HCLGE_IGU_ERR_INT_TYPE);
 	if (en)
-		desc.data[0] = cpu_to_le32(HCLGE_IGU_ERR_INT_EN);
+		desc.data[0] |= cpu_to_le32(HCLGE_IGU_ERR_INT_EN);
 
 	desc.data[1] = cpu_to_le32(HCLGE_IGU_ERR_INT_EN_MASK);
 
@@ -1667,9 +1668,6 @@
 		hclge_handle_rocee_ras_error(ae_dev);
 	}
 
-	if (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state))
-		goto out;
-
 	if (ae_dev->hw_err_reset_req)
 		return PCI_ERS_RESULT_NEED_RESET;
 
@@ -1747,7 +1745,7 @@
 
 	if (vf_id) {
 		if (vf_id >= hdev->num_alloc_vport) {
-			dev_err(dev, "invalid vf id(%d)\n", vf_id);
+			dev_err(dev, "invalid vf id(%u)\n", vf_id);
 			return;
 		}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_err.h
@@ -33,7 +33,8 @@
 #define HCLGE_TQP_ECC_ERR_INT_EN_MASK	0x0FFF
 #define HCLGE_MSIX_SRAM_ECC_ERR_INT_EN_MASK	0x0F000000
 #define HCLGE_MSIX_SRAM_ECC_ERR_INT_EN	0x0F000000
-#define HCLGE_IGU_ERR_INT_EN	0x0000066F
+#define HCLGE_IGU_ERR_INT_EN	0x0000000F
+#define HCLGE_IGU_ERR_INT_TYPE	0x00000660
 #define HCLGE_IGU_ERR_INT_EN_MASK	0x000F
 #define HCLGE_IGU_TNL_ERR_INT_EN    0x0002AABF
 #define HCLGE_IGU_TNL_ERR_INT_EN_MASK  0x003F
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -55,6 +55,8 @@
 
 #define HCLGE_LINK_STATUS_MS	10
 
+#define HCLGE_VF_VPORT_START_NUM	1
+
 static int hclge_set_mac_mtu(struct hclge_dev *hdev, int new_mps);
 static int hclge_init_vlan_config(struct hclge_dev *hdev);
 static void hclge_sync_vlan_filter(struct hclge_dev *hdev);
@@ -70,6 +72,8 @@
 
 static struct hnae3_ae_algo ae_algo;
 
+static struct workqueue_struct *hclge_wq;
+
 static const struct pci_device_id ae_algo_pci_tbl[] = {
 	{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_GE), 0},
 	{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_25GE), 0},
@@ -323,8 +327,7 @@
 	{
 		.flags = HCLGE_MAC_MGR_MASK_VLAN_B,
 		.ethter_type = cpu_to_le16(ETH_P_LLDP),
-		.mac_addr_hi32 = cpu_to_le32(htonl(0x0180C200)),
-		.mac_addr_lo16 = cpu_to_le16(htons(0x000E)),
+		.mac_addr = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e},
 		.i_port_bitmap = 0x1,
 	},
 };
@@ -415,7 +418,7 @@
 {
 #define HCLGE_MAC_CMD_NUM 21
 
-	u64 *data = (u64 *)(&hdev->hw_stats.mac_stats);
+	u64 *data = (u64 *)(&hdev->mac_stats);
 	struct hclge_desc desc[HCLGE_MAC_CMD_NUM];
 	__le64 *desc_data;
 	int i, k, n;
@@ -452,7 +455,7 @@
 
 static int hclge_mac_update_stats_complete(struct hclge_dev *hdev, u32 desc_num)
 {
-	u64 *data = (u64 *)(&hdev->hw_stats.mac_stats);
+	u64 *data = (u64 *)(&hdev->mac_stats);
 	struct hclge_desc *desc;
 	__le64 *desc_data;
 	u16 i, k, n;
@@ -746,7 +749,8 @@
 		handle->flags |= HNAE3_SUPPORT_SERDES_SERIAL_LOOPBACK;
 		handle->flags |= HNAE3_SUPPORT_SERDES_PARALLEL_LOOPBACK;
 
-		if (hdev->hw.mac.phydev) {
+		if (hdev->hw.mac.phydev && hdev->hw.mac.phydev->drv &&
+		    hdev->hw.mac.phydev->drv->set_loopback) {
 			count += 1;
 			handle->flags |= HNAE3_SUPPORT_PHY_LOOPBACK;
 		}
@@ -801,7 +805,7 @@
 	struct hclge_dev *hdev = vport->back;
 	u64 *p;
 
-	p = hclge_comm_get_stats(&hdev->hw_stats.mac_stats, g_mac_stats_string,
+	p = hclge_comm_get_stats(&hdev->mac_stats, g_mac_stats_string,
 				 ARRAY_SIZE(g_mac_stats_string), data);
 	p = hclge_tqps_get_stats(handle, p);
 }
@@ -814,13 +818,15 @@
 
 	hclge_update_stats(handle, NULL);
 
-	mac_stats->tx_pause_cnt = hdev->hw_stats.mac_stats.mac_tx_mac_pause_num;
-	mac_stats->rx_pause_cnt = hdev->hw_stats.mac_stats.mac_rx_mac_pause_num;
+	mac_stats->tx_pause_cnt = hdev->mac_stats.mac_tx_mac_pause_num;
+	mac_stats->rx_pause_cnt = hdev->mac_stats.mac_rx_mac_pause_num;
 }
 
 static int hclge_parse_func_status(struct hclge_dev *hdev,
 				   struct hclge_func_status_cmd *status)
 {
+#define HCLGE_MAC_ID_MASK	0xF
+
 	if (!(status->pf_state & HCLGE_PF_STATE_DONE))
 		return -EINVAL;
 
@@ -830,6 +836,7 @@
 	else
 		hdev->flag &= ~HCLGE_FLAG_MAIN;
 
+	hdev->hw.mac.mac_id = status->mac_id & HCLGE_MAC_ID_MASK;
 	return 0;
 }
 
@@ -1194,6 +1201,35 @@
 		hclge_parse_backplane_link_mode(hdev, speed_ability);
 }
 
+static u32 hclge_get_max_speed(u8 speed_ability)
+{
+	if (speed_ability & HCLGE_SUPPORT_100G_BIT)
+		return HCLGE_MAC_SPEED_100G;
+
+	if (speed_ability & HCLGE_SUPPORT_50G_BIT)
+		return HCLGE_MAC_SPEED_50G;
+
+	if (speed_ability & HCLGE_SUPPORT_40G_BIT)
+		return HCLGE_MAC_SPEED_40G;
+
+	if (speed_ability & HCLGE_SUPPORT_25G_BIT)
+		return HCLGE_MAC_SPEED_25G;
+
+	if (speed_ability & HCLGE_SUPPORT_10G_BIT)
+		return HCLGE_MAC_SPEED_10G;
+
+	if (speed_ability & HCLGE_SUPPORT_1G_BIT)
+		return HCLGE_MAC_SPEED_1G;
+
+	if (speed_ability & HCLGE_SUPPORT_100M_BIT)
+		return HCLGE_MAC_SPEED_100M;
+
+	if (speed_ability & HCLGE_SUPPORT_10M_BIT)
+		return HCLGE_MAC_SPEED_10M;
+
+	return HCLGE_MAC_SPEED_1G;
+}
+
 static void hclge_parse_cfg(struct hclge_cfg *cfg, struct hclge_desc *desc)
 {
 	struct hclge_cfg_param_cmd *req;
@@ -1327,9 +1363,10 @@
 
 static int hclge_configure(struct hclge_dev *hdev)
 {
+	const struct cpumask *cpumask = cpu_online_mask;
 	struct hclge_cfg cfg;
 	unsigned int i;
-	int ret;
+	int node, ret;
 
 	ret = hclge_get_cfg(hdev, &cfg);
 	if (ret) {
@@ -1364,9 +1401,11 @@
 
 	hclge_parse_link_mode(hdev, cfg.speed_ability);
 
+	hdev->hw.mac.max_speed = hclge_get_max_speed(cfg.speed_ability);
+
 	if ((hdev->tc_max > HNAE3_MAX_TC) ||
 	    (hdev->tc_max < 1)) {
-		dev_warn(&hdev->pdev->dev, "TC num = %d.\n",
+		dev_warn(&hdev->pdev->dev, "TC num = %u.\n",
 			 hdev->tc_max);
 		hdev->tc_max = 1;
 	}
@@ -1389,11 +1428,12 @@
 
 	hclge_init_kdump_kernel_config(hdev);
 
-	/* Set the init affinity based on pci func number */
-	i = cpumask_weight(cpumask_of_node(dev_to_node(&hdev->pdev->dev)));
-	i = i ? PCI_FUNC(hdev->pdev->devfn) % i : 0;
-	cpumask_set_cpu(cpumask_local_spread(i, dev_to_node(&hdev->pdev->dev)),
-			&hdev->affinity_mask);
+	/* Set the affinity based on numa node */
+	node = dev_to_node(&hdev->pdev->dev);
+	if (node != NUMA_NO_NODE)
+		cpumask = cpumask_of_node(node);
+
+	cpumask_copy(&hdev->affinity_mask, cpumask);
 
 	return ret;
 }
@@ -1626,7 +1666,7 @@
 	num_vport = hdev->num_vmdq_vport + hdev->num_req_vfs + 1;
 
 	if (hdev->num_tqps < num_vport) {
-		dev_err(&hdev->pdev->dev, "tqps(%d) is less than vports(%d)",
+		dev_err(&hdev->pdev->dev, "tqps(%u) is less than vports(%d)",
 			hdev->num_tqps, num_vport);
 		return -EINVAL;
 	}
@@ -1649,6 +1689,7 @@
 	for (i = 0; i < num_vport; i++) {
 		vport->back = hdev;
 		vport->vport_id = i;
+		vport->vf_info.link_state = IFLA_VF_LINK_STATE_AUTO;
 		vport->mps = HCLGE_MAC_DEFAULT_FRAME;
 		vport->port_base_vlan_cfg.state = HNAE3_PORT_BASE_VLAN_DISABLE;
 		vport->rxvlan_cfg.rx_vlan_offload_en = true;
@@ -2312,7 +2353,7 @@
 	}
 	if (vectors < hdev->num_msi)
 		dev_warn(&hdev->pdev->dev,
-			 "requested %d MSI/MSI-X, but allocated %d MSI/MSI-X\n",
+			 "requested %u MSI/MSI-X, but allocated %d MSI/MSI-X\n",
 			 hdev->num_msi, vectors);
 
 	hdev->num_msi = vectors;
@@ -2417,10 +2458,12 @@
 
 int hclge_cfg_mac_speed_dup(struct hclge_dev *hdev, int speed, u8 duplex)
 {
+	struct hclge_mac *mac = &hdev->hw.mac;
 	int ret;
 
 	duplex = hclge_check_speed_dup(duplex, speed);
-	if (hdev->hw.mac.speed == speed && hdev->hw.mac.duplex == duplex)
+	if (!mac->support_autoneg && mac->speed == speed &&
+	    mac->duplex == duplex)
 		return 0;
 
 	ret = hclge_cfg_mac_speed_dup_hw(hdev, speed, duplex);
@@ -2583,7 +2626,10 @@
 	int ret;
 
 	hdev->support_sfp_query = true;
-	hdev->hw.mac.duplex = HCLGE_MAC_FULL;
+
+	if (!test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state))
+		hdev->hw.mac.duplex = HCLGE_MAC_FULL;
+
 	ret = hclge_cfg_mac_speed_dup_hw(hdev, hdev->hw.mac.speed,
 					 hdev->hw.mac.duplex);
 	if (ret) {
@@ -2632,31 +2678,27 @@
 
 static void hclge_mbx_task_schedule(struct hclge_dev *hdev)
 {
-	if (!test_bit(HCLGE_STATE_CMD_DISABLE, &hdev->state) &&
+	if (!test_bit(HCLGE_STATE_REMOVING, &hdev->state) &&
 	    !test_and_set_bit(HCLGE_STATE_MBX_SERVICE_SCHED, &hdev->state))
-		queue_work_on(cpumask_first(&hdev->affinity_mask), system_wq,
-			      &hdev->mbx_service_task);
+		mod_delayed_work_on(cpumask_first(&hdev->affinity_mask),
+				    hclge_wq, &hdev->service_task, 0);
 }
 
 static void hclge_reset_task_schedule(struct hclge_dev *hdev)
 {
 	if (!test_bit(HCLGE_STATE_REMOVING, &hdev->state) &&
 	    !test_and_set_bit(HCLGE_STATE_RST_SERVICE_SCHED, &hdev->state))
-		queue_work_on(cpumask_first(&hdev->affinity_mask), system_wq,
-			      &hdev->rst_service_task);
+		mod_delayed_work_on(cpumask_first(&hdev->affinity_mask),
+				    hclge_wq, &hdev->service_task, 0);
 }
 
 void hclge_task_schedule(struct hclge_dev *hdev, unsigned long delay_time)
 {
-	if (!test_bit(HCLGE_STATE_DOWN, &hdev->state) &&
-	    !test_bit(HCLGE_STATE_REMOVING, &hdev->state) &&
-	    !test_and_set_bit(HCLGE_STATE_SERVICE_SCHED, &hdev->state)) {
-		hdev->hw_stats.stats_timer++;
-		hdev->fd_arfs_expire_timer++;
+	if (!test_bit(HCLGE_STATE_REMOVING, &hdev->state) &&
+	    !test_bit(HCLGE_STATE_RST_FAIL, &hdev->state))
 		mod_delayed_work_on(cpumask_first(&hdev->affinity_mask),
-				    system_wq, &hdev->service_task,
+				    hclge_wq, &hdev->service_task,
 				    delay_time);
-	}
 }
 
 static int hclge_get_mac_link_status(struct hclge_dev *hdev)
@@ -2715,6 +2757,10 @@
 
 	if (!client)
 		return;
+
+	if (test_and_set_bit(HCLGE_STATE_LINK_UPDATING, &hdev->state))
+		return;
+
 	state = hclge_get_mac_phy_link(hdev);
 	if (state != hdev->hw.mac.link) {
 		for (i = 0; i < hdev->num_vmdq_vport + 1; i++) {
@@ -2728,6 +2774,8 @@
 		}
 		hdev->hw.mac.link = state;
 	}
+
+	clear_bit(HCLGE_STATE_LINK_UPDATING, &hdev->state);
 }
 
 static void hclge_update_port_capability(struct hclge_mac *mac)
@@ -2744,7 +2792,7 @@
 	else if (mac->media_type == HNAE3_MEDIA_TYPE_COPPER)
 		mac->module_type = HNAE3_MODULE_TYPE_TP;
 
-	if (mac->support_autoneg == true) {
+	if (mac->support_autoneg) {
 		linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, mac->supported);
 		linkmode_copy(mac->advertising, mac->supported);
 	} else {
@@ -2798,6 +2846,12 @@
 		return ret;
 	}
 
+	/* In some case, mac speed get from IMP may be 0, it shouldn't be
+	 * set to mac->speed.
+	 */
+	if (!le32_to_cpu(resp->speed))
+		return 0;
+
 	mac->speed = le32_to_cpu(resp->speed);
 	/* if resp->speed_ability is 0, it means it's an old version
 	 * firmware, do not update these params
@@ -2871,6 +2925,65 @@
 	return hdev->hw.mac.link;
 }
 
+static struct hclge_vport *hclge_get_vf_vport(struct hclge_dev *hdev, int vf)
+{
+	if (pci_num_vf(hdev->pdev) == 0) {
+		dev_err(&hdev->pdev->dev,
+			"SRIOV is disabled, can not get vport(%d) info.\n", vf);
+		return NULL;
+	}
+
+	if (vf < 0 || vf >= pci_num_vf(hdev->pdev)) {
+		dev_err(&hdev->pdev->dev,
+			"vf id(%d) is out of range(0 <= vfid < %d)\n",
+			vf, pci_num_vf(hdev->pdev));
+		return NULL;
+	}
+
+	/* VF start from 1 in vport */
+	vf += HCLGE_VF_VPORT_START_NUM;
+	return &hdev->vport[vf];
+}
+
+static int hclge_get_vf_config(struct hnae3_handle *handle, int vf,
+			       struct ifla_vf_info *ivf)
+{
+	struct hclge_vport *vport = hclge_get_vport(handle);
+	struct hclge_dev *hdev = vport->back;
+
+	vport = hclge_get_vf_vport(hdev, vf);
+	if (!vport)
+		return -EINVAL;
+
+	ivf->vf = vf;
+	ivf->linkstate = vport->vf_info.link_state;
+	ivf->spoofchk = vport->vf_info.spoofchk;
+	ivf->trusted = vport->vf_info.trusted;
+	ivf->min_tx_rate = 0;
+	ivf->max_tx_rate = vport->vf_info.max_tx_rate;
+	ivf->vlan = vport->port_base_vlan_cfg.vlan_info.vlan_tag;
+	ivf->vlan_proto = htons(vport->port_base_vlan_cfg.vlan_info.vlan_proto);
+	ivf->qos = vport->port_base_vlan_cfg.vlan_info.qos;
+	ether_addr_copy(ivf->mac, vport->vf_info.mac);
+
+	return 0;
+}
+
+static int hclge_set_vf_link_state(struct hnae3_handle *handle, int vf,
+				   int link_state)
+{
+	struct hclge_vport *vport = hclge_get_vport(handle);
+	struct hclge_dev *hdev = vport->back;
+
+	vport = hclge_get_vf_vport(hdev, vf);
+	if (!vport)
+		return -EINVAL;
+
+	vport->vf_info.link_state = link_state;
+
+	return 0;
+}
+
 static u32 hclge_check_event_cause(struct hclge_dev *hdev, u32 *clearval)
 {
 	u32 rst_src_reg, cmdq_src_reg, msix_src_reg;
@@ -2909,8 +3022,6 @@
 
 	/* check for vector0 msix event source */
 	if (msix_src_reg & HCLGE_VECTOR0_REG_MSIX_MASK) {
-		dev_info(&hdev->pdev->dev, "received event 0x%x\n",
-			 msix_src_reg);
 		*clearval = msix_src_reg;
 		return HCLGE_VECTOR0_EVENT_ERR;
 	}
@@ -2934,8 +3045,13 @@
 static void hclge_clear_event_cause(struct hclge_dev *hdev, u32 event_type,
 				    u32 regclr)
 {
+#define HCLGE_IMP_RESET_DELAY		5
+
 	switch (event_type) {
 	case HCLGE_VECTOR0_EVENT_RST:
+		if (regclr == BIT(HCLGE_VECTOR0_IMPRESET_INT_B))
+			mdelay(HCLGE_IMP_RESET_DELAY);
+
 		hclge_write_dev(&hdev->hw, HCLGE_MISC_RESET_STS_REG, regclr);
 		break;
 	case HCLGE_VECTOR0_EVENT_MBX:
@@ -3083,8 +3199,10 @@
 	hclge_get_misc_vector(hdev);
 
 	/* this would be explicitly freed in the end */
+	snprintf(hdev->misc_vector.name, HNAE3_INT_NAME_LEN, "%s-misc-%s",
+		 HCLGE_NAME, pci_name(hdev->pdev));
 	ret = request_irq(hdev->misc_vector.vector_irq, hclge_misc_irq_handle,
-			  0, "hclge_misc", hdev);
+			  0, hdev->misc_vector.name, hdev);
 	if (ret) {
 		hclge_free_vector(hdev, 0);
 		dev_err(&hdev->pdev->dev, "request misc irq(%d) fail\n",
@@ -3158,7 +3276,8 @@
 static int hclge_reset_wait(struct hclge_dev *hdev)
 {
 #define HCLGE_RESET_WATI_MS	100
-#define HCLGE_RESET_WAIT_CNT	200
+#define HCLGE_RESET_WAIT_CNT	350
+
 	u32 val, reg, reg_bit;
 	u32 cnt = 0;
 
@@ -3175,8 +3294,6 @@
 		reg = HCLGE_FUN_RST_ING;
 		reg_bit = HCLGE_FUN_RST_ING_B;
 		break;
-	case HNAE3_FLR_RESET:
-		break;
 	default:
 		dev_err(&hdev->pdev->dev,
 			"Wait for unsupported reset type: %d\n",
@@ -3184,20 +3301,6 @@
 		return -EINVAL;
 	}
 
-	if (hdev->reset_type == HNAE3_FLR_RESET) {
-		while (!test_bit(HNAE3_FLR_DONE, &hdev->flr_state) &&
-		       cnt++ < HCLGE_RESET_WAIT_CNT)
-			msleep(HCLGE_RESET_WATI_MS);
-
-		if (!test_bit(HNAE3_FLR_DONE, &hdev->flr_state)) {
-			dev_err(&hdev->pdev->dev,
-				"flr wait timeout: %d\n", cnt);
-			return -EBUSY;
-		}
-
-		return 0;
-	}
-
 	val = hclge_read_dev(&hdev->hw, reg);
 	while (hnae3_get_bit(val, reg_bit) && cnt < HCLGE_RESET_WAIT_CNT) {
 		msleep(HCLGE_RESET_WATI_MS);
@@ -3241,7 +3344,7 @@
 		ret = hclge_set_vf_rst(hdev, vport->vport_id, reset);
 		if (ret) {
 			dev_err(&hdev->pdev->dev,
-				"set vf(%d) rst failed %d!\n",
+				"set vf(%u) rst failed %d!\n",
 				vport->vport_id, ret);
 			return ret;
 		}
@@ -3256,14 +3359,26 @@
 		ret = hclge_inform_reset_assert_to_vf(vport);
 		if (ret)
 			dev_warn(&hdev->pdev->dev,
-				 "inform reset to vf(%d) failed %d!\n",
+				 "inform reset to vf(%u) failed %d!\n",
 				 vport->vport_id, ret);
 	}
 
 	return 0;
 }
 
-static int hclge_func_reset_sync_vf(struct hclge_dev *hdev)
+static void hclge_mailbox_service_task(struct hclge_dev *hdev)
+{
+	if (!test_and_clear_bit(HCLGE_STATE_MBX_SERVICE_SCHED, &hdev->state) ||
+	    test_bit(HCLGE_STATE_CMD_DISABLE, &hdev->state) ||
+	    test_and_set_bit(HCLGE_STATE_MBX_HANDLING, &hdev->state))
+		return;
+
+	hclge_mbx_handler(hdev);
+
+	clear_bit(HCLGE_STATE_MBX_HANDLING, &hdev->state);
+}
+
+static void hclge_func_reset_sync_vf(struct hclge_dev *hdev)
 {
 	struct hclge_pf_rst_sync_cmd *req;
 	struct hclge_desc desc;
@@ -3274,26 +3389,28 @@
 	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QUERY_VF_RST_RDY, true);
 
 	do {
+		/* vf need to down netdev by mbx during PF or FLR reset */
+		hclge_mailbox_service_task(hdev);
+
 		ret = hclge_cmd_send(&hdev->hw, &desc, 1);
 		/* for compatible with old firmware, wait
 		 * 100 ms for VF to stop IO
 		 */
 		if (ret == -EOPNOTSUPP) {
 			msleep(HCLGE_RESET_SYNC_TIME);
-			return 0;
+			return;
 		} else if (ret) {
-			dev_err(&hdev->pdev->dev, "sync with VF fail %d!\n",
-				ret);
-			return ret;
+			dev_warn(&hdev->pdev->dev, "sync with VF fail %d!\n",
+				 ret);
+			return;
 		} else if (req->all_vf_ready) {
-			return 0;
+			return;
 		}
 		msleep(HCLGE_PF_RESET_SYNC_TIME);
 		hclge_cmd_reuse_desc(&desc, true);
 	} while (cnt++ < HCLGE_PF_RESET_SYNC_CNT);
 
-	dev_err(&hdev->pdev->dev, "sync with VF timeout!\n");
-	return -ETIME;
+	dev_warn(&hdev->pdev->dev, "sync with VF timeout!\n");
 }
 
 void hclge_report_hw_error(struct hclge_dev *hdev,
@@ -3353,7 +3470,7 @@
 	u32 val;
 
 	if (hclge_get_hw_reset_stat(handle)) {
-		dev_info(&pdev->dev, "Hardware reset not finish\n");
+		dev_info(&pdev->dev, "hardware reset not finish\n");
 		dev_info(&pdev->dev, "func_rst_reg:0x%x, global_rst_reg:0x%x\n",
 			 hclge_read_dev(&hdev->hw, HCLGE_FUN_RST_ING),
 			 hclge_read_dev(&hdev->hw, HCLGE_GLOBAL_RESET_REG));
@@ -3362,26 +3479,20 @@
 
 	switch (hdev->reset_type) {
 	case HNAE3_GLOBAL_RESET:
+		dev_info(&pdev->dev, "global reset requested\n");
 		val = hclge_read_dev(&hdev->hw, HCLGE_GLOBAL_RESET_REG);
 		hnae3_set_bit(val, HCLGE_GLOBAL_RESET_BIT, 1);
 		hclge_write_dev(&hdev->hw, HCLGE_GLOBAL_RESET_REG, val);
-		dev_info(&pdev->dev, "Global Reset requested\n");
 		break;
 	case HNAE3_FUNC_RESET:
-		dev_info(&pdev->dev, "PF Reset requested\n");
+		dev_info(&pdev->dev, "PF reset requested\n");
 		/* schedule again to check later */
 		set_bit(HNAE3_FUNC_RESET, &hdev->reset_pending);
 		hclge_reset_task_schedule(hdev);
 		break;
-	case HNAE3_FLR_RESET:
-		dev_info(&pdev->dev, "FLR requested\n");
-		/* schedule again to check later */
-		set_bit(HNAE3_FLR_RESET, &hdev->reset_pending);
-		hclge_reset_task_schedule(hdev);
-		break;
 	default:
 		dev_warn(&pdev->dev,
-			 "Unsupported reset type: %d\n", hdev->reset_type);
+			 "unsupported reset type: %d\n", hdev->reset_type);
 		break;
 	}
 }
@@ -3394,10 +3505,15 @@
 
 	/* first, resolve any unknown reset type to the known type(s) */
 	if (test_bit(HNAE3_UNKNOWN_RESET, addr)) {
+		u32 msix_sts_reg = hclge_read_dev(&hdev->hw,
+					HCLGE_VECTOR0_PF_OTHER_INT_STS_REG);
 		/* we will intentionally ignore any errors from this function
 		 *  as we will end up in *some* reset request in any case
 		 */
-		hclge_handle_hw_msix_error(hdev, addr);
+		if (hclge_handle_hw_msix_error(hdev, addr))
+			dev_info(&hdev->pdev->dev, "received msix interrupt 0x%x\n",
+				 msix_sts_reg);
+
 		clear_bit(HNAE3_UNKNOWN_RESET, addr);
 		/* We defered the clearing of the error event which caused
 		 * interrupt since it was not posssible to do that in
@@ -3462,23 +3578,6 @@
 	hclge_enable_vector(&hdev->misc_vector, true);
 }
 
-static int hclge_reset_prepare_down(struct hclge_dev *hdev)
-{
-	int ret = 0;
-
-	switch (hdev->reset_type) {
-	case HNAE3_FUNC_RESET:
-		/* fall through */
-	case HNAE3_FLR_RESET:
-		ret = hclge_set_all_vf_rst(hdev, true);
-		break;
-	default:
-		break;
-	}
-
-	return ret;
-}
-
 static void hclge_reset_handshake(struct hclge_dev *hdev, bool enable)
 {
 	u32 reg_val;
@@ -3492,6 +3591,19 @@
 	hclge_write_dev(&hdev->hw, HCLGE_NIC_CSQ_DEPTH_REG, reg_val);
 }
 
+static int hclge_func_reset_notify_vf(struct hclge_dev *hdev)
+{
+	int ret;
+
+	ret = hclge_set_all_vf_rst(hdev, true);
+	if (ret)
+		return ret;
+
+	hclge_func_reset_sync_vf(hdev);
+
+	return 0;
+}
+
 static int hclge_reset_prepare_wait(struct hclge_dev *hdev)
 {
 	u32 reg_val;
@@ -3499,10 +3611,7 @@
 
 	switch (hdev->reset_type) {
 	case HNAE3_FUNC_RESET:
-		/* to confirm whether all running VF is ready
-		 * before request PF reset
-		 */
-		ret = hclge_func_reset_sync_vf(hdev);
+		ret = hclge_func_reset_notify_vf(hdev);
 		if (ret)
 			return ret;
 
@@ -3522,16 +3631,9 @@
 		hdev->rst_stats.pf_rst_cnt++;
 		break;
 	case HNAE3_FLR_RESET:
-		/* to confirm whether all running VF is ready
-		 * before request PF reset
-		 */
-		ret = hclge_func_reset_sync_vf(hdev);
+		ret = hclge_func_reset_notify_vf(hdev);
 		if (ret)
 			return ret;
-
-		set_bit(HCLGE_STATE_CMD_DISABLE, &hdev->state);
-		set_bit(HNAE3_FLR_DOWN, &hdev->flr_state);
-		hdev->rst_stats.flr_rst_cnt++;
 		break;
 	case HNAE3_IMP_RESET:
 		hclge_handle_imp_error(hdev);
@@ -3569,7 +3671,7 @@
 		hdev->rst_stats.reset_fail_cnt++;
 		set_bit(hdev->reset_type, &hdev->reset_pending);
 		dev_info(&hdev->pdev->dev,
-			 "re-schedule reset task(%d)\n",
+			 "re-schedule reset task(%u)\n",
 			 hdev->rst_stats.reset_fail_cnt);
 		return true;
 	}
@@ -3580,6 +3682,11 @@
 	hclge_reset_handshake(hdev, true);
 
 	dev_err(&hdev->pdev->dev, "Reset fail!\n");
+
+	hclge_dbg_dump_rst_info(hdev);
+
+	set_bit(HCLGE_STATE_RST_FAIL, &hdev->state);
+
 	return false;
 }
 
@@ -3655,10 +3762,9 @@
 	return hclge_notify_client(hdev, HNAE3_RESTORE_CLIENT);
 }
 
-static void hclge_reset(struct hclge_dev *hdev)
+static int hclge_reset_prepare(struct hclge_dev *hdev)
 {
 	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev);
-	enum hnae3_reset_type reset_level;
 	int ret;
 
 	/* Initialize ae_dev reset status as well, in case enet layer wants to
@@ -3669,45 +3775,41 @@
 	/* perform reset of the stack & ae device for a client */
 	ret = hclge_notify_roce_client(hdev, HNAE3_DOWN_CLIENT);
 	if (ret)
-		goto err_reset;
-
-	ret = hclge_reset_prepare_down(hdev);
-	if (ret)
-		goto err_reset;
+		return ret;
 
 	rtnl_lock();
 	ret = hclge_notify_client(hdev, HNAE3_DOWN_CLIENT);
-	if (ret)
-		goto err_reset_lock;
-
 	rtnl_unlock();
-
-	ret = hclge_reset_prepare_wait(hdev);
 	if (ret)
-		goto err_reset;
+		return ret;
 
-	if (hclge_reset_wait(hdev))
-		goto err_reset;
+	return hclge_reset_prepare_wait(hdev);
+}
+
+static int hclge_reset_rebuild(struct hclge_dev *hdev)
+{
+	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev);
+	enum hnae3_reset_type reset_level;
+	int ret;
 
 	hdev->rst_stats.hw_reset_done_cnt++;
 
 	ret = hclge_notify_roce_client(hdev, HNAE3_UNINIT_CLIENT);
 	if (ret)
-		goto err_reset;
+		return ret;
 
 	rtnl_lock();
-
 	ret = hclge_reset_stack(hdev);
+	rtnl_unlock();
 	if (ret)
-		goto err_reset_lock;
+		return ret;
 
 	hclge_clear_reset_cause(hdev);
 
 	ret = hclge_reset_prepare_up(hdev);
 	if (ret)
-		goto err_reset_lock;
+		return ret;
 
-	rtnl_unlock();
 
 	ret = hclge_notify_roce_client(hdev, HNAE3_INIT_CLIENT);
 	/* ignore RoCE notify error if it fails HCLGE_RESET_MAX_FAIL_CNT - 1
@@ -3715,24 +3817,23 @@
 	 */
 	if (ret &&
 	    hdev->rst_stats.reset_fail_cnt < HCLGE_RESET_MAX_FAIL_CNT - 1)
-		goto err_reset;
+		return ret;
 
 	rtnl_lock();
-
 	ret = hclge_notify_client(hdev, HNAE3_UP_CLIENT);
-	if (ret)
-		goto err_reset_lock;
-
 	rtnl_unlock();
+	if (ret)
+		return ret;
 
 	ret = hclge_notify_roce_client(hdev, HNAE3_UP_CLIENT);
 	if (ret)
-		goto err_reset;
+		return ret;
 
 	hdev->last_reset_time = jiffies;
 	hdev->rst_stats.reset_fail_cnt = 0;
 	hdev->rst_stats.reset_done_cnt++;
 	ae_dev->reset_type = HNAE3_NONE_RESET;
+	clear_bit(HCLGE_STATE_RST_FAIL, &hdev->state);
 
 	/* if default_reset_request has a higher level reset request,
 	 * it should be handled as soon as possible. since some errors
@@ -3743,10 +3844,22 @@
 	if (reset_level != HNAE3_NONE_RESET)
 		set_bit(reset_level, &hdev->reset_request);
 
+	return 0;
+}
+
+static void hclge_reset(struct hclge_dev *hdev)
+{
+	if (hclge_reset_prepare(hdev))
+		goto err_reset;
+
+	if (hclge_reset_wait(hdev))
+		goto err_reset;
+
+	if (hclge_reset_rebuild(hdev))
+		goto err_reset;
+
 	return;
 
-err_reset_lock:
-	rtnl_unlock();
 err_reset:
 	if (hclge_reset_err_handle(hdev))
 		hclge_reset_task_schedule(hdev);
@@ -3779,12 +3892,13 @@
 				  HCLGE_RESET_INTERVAL))) {
 		mod_timer(&hdev->reset_timer, jiffies + HCLGE_RESET_INTERVAL);
 		return;
-	} else if (hdev->default_reset_request)
+	} else if (hdev->default_reset_request) {
 		hdev->reset_level =
 			hclge_get_reset_level(ae_dev,
 					      &hdev->default_reset_request);
-	else if (time_after(jiffies, (hdev->last_reset_time + 4 * 5 * HZ)))
+	} else if (time_after(jiffies, (hdev->last_reset_time + 4 * 5 * HZ))) {
 		hdev->reset_level = HNAE3_FUNC_RESET;
+	}
 
 	dev_info(&hdev->pdev->dev, "received reset event, reset type is %d\n",
 		 hdev->reset_level);
@@ -3846,34 +3960,18 @@
 	hdev->reset_type = HNAE3_NONE_RESET;
 }
 
-static void hclge_reset_service_task(struct work_struct *work)
+static void hclge_reset_service_task(struct hclge_dev *hdev)
 {
-	struct hclge_dev *hdev =
-		container_of(work, struct hclge_dev, rst_service_task);
-
-	if (test_and_set_bit(HCLGE_STATE_RST_HANDLING, &hdev->state))
+	if (!test_and_clear_bit(HCLGE_STATE_RST_SERVICE_SCHED, &hdev->state))
 		return;
 
-	clear_bit(HCLGE_STATE_RST_SERVICE_SCHED, &hdev->state);
+	down(&hdev->reset_sem);
+	set_bit(HCLGE_STATE_RST_HANDLING, &hdev->state);
 
 	hclge_reset_subtask(hdev);
 
 	clear_bit(HCLGE_STATE_RST_HANDLING, &hdev->state);
-}
-
-static void hclge_mailbox_service_task(struct work_struct *work)
-{
-	struct hclge_dev *hdev =
-		container_of(work, struct hclge_dev, mbx_service_task);
-
-	if (test_and_set_bit(HCLGE_STATE_MBX_HANDLING, &hdev->state))
-		return;
-
-	clear_bit(HCLGE_STATE_MBX_SERVICE_SCHED, &hdev->state);
-
-	hclge_mbx_handler(hdev);
-
-	clear_bit(HCLGE_STATE_MBX_HANDLING, &hdev->state);
+	up(&hdev->reset_sem);
 }
 
 static void hclge_update_vport_alive(struct hclge_dev *hdev)
@@ -3893,28 +3991,62 @@
 	}
 }
 
-static void hclge_service_task(struct work_struct *work)
+static void hclge_periodic_service_task(struct hclge_dev *hdev)
 {
-	struct hclge_dev *hdev =
-		container_of(work, struct hclge_dev, service_task.work);
+	unsigned long delta = round_jiffies_relative(HZ);
 
-	clear_bit(HCLGE_STATE_SERVICE_SCHED, &hdev->state);
+	/* Always handle the link updating to make sure link state is
+	 * updated when it is triggered by mbx.
+	 */
+	hclge_update_link_status(hdev);
 
-	if (hdev->hw_stats.stats_timer >= HCLGE_STATS_TIMER_INTERVAL) {
-		hclge_update_stats_for_all(hdev);
-		hdev->hw_stats.stats_timer = 0;
+	if (time_is_after_jiffies(hdev->last_serv_processed + HZ)) {
+		delta = jiffies - hdev->last_serv_processed;
+
+		if (delta < round_jiffies_relative(HZ)) {
+			delta = round_jiffies_relative(HZ) - delta;
+			goto out;
+		}
 	}
 
-	hclge_update_port_info(hdev);
-	hclge_update_link_status(hdev);
+	hdev->serv_processed_cnt++;
 	hclge_update_vport_alive(hdev);
+
+	if (test_bit(HCLGE_STATE_DOWN, &hdev->state)) {
+		hdev->last_serv_processed = jiffies;
+		goto out;
+	}
+
+	if (!(hdev->serv_processed_cnt % HCLGE_STATS_TIMER_INTERVAL))
+		hclge_update_stats_for_all(hdev);
+
+	hclge_update_port_info(hdev);
 	hclge_sync_vlan_filter(hdev);
-	if (hdev->fd_arfs_expire_timer >= HCLGE_FD_ARFS_EXPIRE_TIMER_INTERVAL) {
+
+	if (!(hdev->serv_processed_cnt % HCLGE_ARFS_EXPIRE_INTERVAL))
 		hclge_rfs_filter_expire(hdev);
-		hdev->fd_arfs_expire_timer = 0;
-	}
 
-	hclge_task_schedule(hdev, round_jiffies_relative(HZ));
+	hdev->last_serv_processed = jiffies;
+
+out:
+	hclge_task_schedule(hdev, delta);
+}
+
+static void hclge_service_task(struct work_struct *work)
+{
+	struct hclge_dev *hdev =
+		container_of(work, struct hclge_dev, service_task.work);
+
+	hclge_reset_service_task(hdev);
+	hclge_mailbox_service_task(hdev);
+	hclge_periodic_service_task(hdev);
+
+	/* Handle reset and mbx again in case periodical task delays the
+	 * handling by calling hclge_task_schedule() in
+	 * hclge_periodic_service_task().
+	 */
+	hclge_reset_service_task(hdev);
+	hclge_mailbox_service_task(hdev);
 }
 
 struct hclge_vport *hclge_get_vport(struct hnae3_handle *handle)
@@ -3985,7 +4117,7 @@
 	vector_id = hclge_get_vector_index(hdev, vector);
 	if (vector_id < 0) {
 		dev_err(&hdev->pdev->dev,
-			"Get vector index fail. vector_id =%d\n", vector_id);
+			"Get vector index fail. vector = %d\n", vector);
 		return vector_id;
 	}
 
@@ -4415,7 +4547,7 @@
 	 */
 	if (rss_size > HCLGE_RSS_TC_SIZE_7 || rss_size == 0) {
 		dev_err(&hdev->pdev->dev,
-			"Configure rss tc size failed, invalid TC_SIZE = %d\n",
+			"Configure rss tc size failed, invalid TC_SIZE = %u\n",
 			rss_size);
 		return -EINVAL;
 	}
@@ -4560,7 +4692,7 @@
 	vector_id = hclge_get_vector_index(hdev, vector);
 	if (vector_id < 0) {
 		dev_err(&hdev->pdev->dev,
-			"Get vector index fail. vector_id =%d\n", vector_id);
+			"failed to get vector index. vector=%d\n", vector);
 		return vector_id;
 	}
 
@@ -4593,8 +4725,8 @@
 	return ret;
 }
 
-int hclge_cmd_set_promisc_mode(struct hclge_dev *hdev,
-			       struct hclge_promisc_param *param)
+static int hclge_cmd_set_promisc_mode(struct hclge_dev *hdev,
+				      struct hclge_promisc_param *param)
 {
 	struct hclge_promisc_cfg_cmd *req;
 	struct hclge_desc desc;
@@ -4621,8 +4753,9 @@
 	return ret;
 }
 
-void hclge_promisc_param_init(struct hclge_promisc_param *param, bool en_uc,
-			      bool en_mc, bool en_bc, int vport_id)
+static void hclge_promisc_param_init(struct hclge_promisc_param *param,
+				     bool en_uc, bool en_mc, bool en_bc,
+				     int vport_id)
 {
 	if (!param)
 		return;
@@ -4637,12 +4770,21 @@
 	param->vf_id = vport_id;
 }
 
+int hclge_set_vport_promisc_mode(struct hclge_vport *vport, bool en_uc_pmc,
+				 bool en_mc_pmc, bool en_bc_pmc)
+{
+	struct hclge_dev *hdev = vport->back;
+	struct hclge_promisc_param param;
+
+	hclge_promisc_param_init(&param, en_uc_pmc, en_mc_pmc, en_bc_pmc,
+				 vport->vport_id);
+	return hclge_cmd_set_promisc_mode(hdev, &param);
+}
+
 static int hclge_set_promisc_mode(struct hnae3_handle *handle, bool en_uc_pmc,
 				  bool en_mc_pmc)
 {
 	struct hclge_vport *vport = hclge_get_vport(handle);
-	struct hclge_dev *hdev = vport->back;
-	struct hclge_promisc_param param;
 	bool en_bc_pmc = true;
 
 	/* For revision 0x20, if broadcast promisc enabled, vlan filter is
@@ -4652,9 +4794,8 @@
 	if (handle->pdev->revision == 0x20)
 		en_bc_pmc = handle->netdev_flags & HNAE3_BPE ? true : false;
 
-	hclge_promisc_param_init(&param, en_uc_pmc, en_mc_pmc, en_bc_pmc,
-				 vport->vport_id);
-	return hclge_cmd_set_promisc_mode(hdev, &param);
+	return hclge_set_vport_promisc_mode(vport, en_uc_pmc, en_mc_pmc,
+					    en_bc_pmc);
 }
 
 static int hclge_get_fd_mode(struct hclge_dev *hdev, u8 *fd_mode)
@@ -4756,7 +4897,7 @@
 		break;
 	default:
 		dev_err(&hdev->pdev->dev,
-			"Unsupported flow director mode %d\n",
+			"Unsupported flow director mode %u\n",
 			hdev->fd_cfg.fd_mode);
 		return -EOPNOTSUPP;
 	}
@@ -4905,9 +5046,9 @@
 	case BIT(INNER_SRC_MAC):
 		for (i = 0; i < ETH_ALEN; i++) {
 			calc_x(key_x[ETH_ALEN - 1 - i], rule->tuples.src_mac[i],
-			       rule->tuples.src_mac[i]);
+			       rule->tuples_mask.src_mac[i]);
 			calc_y(key_y[ETH_ALEN - 1 - i], rule->tuples.src_mac[i],
-			       rule->tuples.src_mac[i]);
+			       rule->tuples_mask.src_mac[i]);
 		}
 
 		return true;
@@ -5086,7 +5227,7 @@
 				   true);
 	if (ret) {
 		dev_err(&hdev->pdev->dev,
-			"fd key_y config fail, loc=%d, ret=%d\n",
+			"fd key_y config fail, loc=%u, ret=%d\n",
 			rule->queue_id, ret);
 		return ret;
 	}
@@ -5095,7 +5236,7 @@
 				   true);
 	if (ret)
 		dev_err(&hdev->pdev->dev,
-			"fd key_x config fail, loc=%d, ret=%d\n",
+			"fd key_x config fail, loc=%u, ret=%d\n",
 			rule->queue_id, ret);
 	return ret;
 }
@@ -5344,7 +5485,7 @@
 		}
 	} else if (!is_add) {
 		dev_err(&hdev->pdev->dev,
-			"delete fail, rule %d is inexistent\n",
+			"delete fail, rule %u is inexistent\n",
 			location);
 		return -EINVAL;
 	}
@@ -5584,7 +5725,7 @@
 
 		if (vf > hdev->num_req_vfs) {
 			dev_err(&hdev->pdev->dev,
-				"Error: vf id (%d) > max vf num (%d)\n",
+				"Error: vf id (%u) > max vf num (%u)\n",
 				vf, hdev->num_req_vfs);
 			return -EINVAL;
 		}
@@ -5594,7 +5735,7 @@
 
 		if (ring >= tqps) {
 			dev_err(&hdev->pdev->dev,
-				"Error: queue id (%d) > max tqp num (%d)\n",
+				"Error: queue id (%u) > max tqp num (%u)\n",
 				ring, tqps - 1);
 			return -EINVAL;
 		}
@@ -5625,9 +5766,9 @@
 	/* to avoid rule conflict, when user configure rule by ethtool,
 	 * we need to clear all arfs rules
 	 */
+	spin_lock_bh(&hdev->fd_rule_lock);
 	hclge_clear_arfs_rules(handle);
 
-	spin_lock_bh(&hdev->fd_rule_lock);
 	ret = hclge_fd_config_rule(hdev, rule);
 
 	spin_unlock_bh(&hdev->fd_rule_lock);
@@ -5653,7 +5794,7 @@
 
 	if (!hclge_fd_rule_exist(hdev, fs->location)) {
 		dev_err(&hdev->pdev->dev,
-			"Delete fail, rule %d is inexistent\n", fs->location);
+			"Delete fail, rule %u is inexistent\n", fs->location);
 		return -ENOENT;
 	}
 
@@ -5670,6 +5811,7 @@
 	return ret;
 }
 
+/* make sure being called after lock up with fd_rule_lock */
 static void hclge_del_all_fd_entries(struct hnae3_handle *handle,
 				     bool clear_list)
 {
@@ -5682,7 +5824,6 @@
 	if (!hnae3_dev_fd_supported(hdev))
 		return;
 
-	spin_lock_bh(&hdev->fd_rule_lock);
 	for_each_set_bit(location, hdev->fd_bmap,
 			 hdev->fd_cfg.rule_num[HCLGE_FD_STAGE_1])
 		hclge_fd_tcam_config(hdev, HCLGE_FD_STAGE_1, true, location,
@@ -5699,8 +5840,6 @@
 		bitmap_zero(hdev->fd_bmap,
 			    hdev->fd_cfg.rule_num[HCLGE_FD_STAGE_1]);
 	}
-
-	spin_unlock_bh(&hdev->fd_rule_lock);
 }
 
 static int hclge_restore_fd_entries(struct hnae3_handle *handle)
@@ -5730,7 +5869,7 @@
 
 		if (ret) {
 			dev_warn(&hdev->pdev->dev,
-				 "Restore rule %d failed, remove it\n",
+				 "Restore rule %u failed, remove it\n",
 				 rule->location);
 			clear_bit(rule->location, hdev->fd_bmap);
 			hlist_del(&rule->rule_node);
@@ -5938,8 +6077,7 @@
 		fs->h_ext.vlan_tci = cpu_to_be16(rule->tuples.vlan_tag1);
 		fs->m_ext.vlan_tci =
 				rule->unused_tuple & BIT(INNER_VLAN_TAG_FST) ?
-				cpu_to_be16(VLAN_VID_MASK) :
-				cpu_to_be16(rule->tuples_mask.vlan_tag1);
+				0 : cpu_to_be16(rule->tuples_mask.vlan_tag1);
 	}
 
 	if (fs->flow_type & FLOW_MAC_EXT) {
@@ -6003,6 +6141,9 @@
 static void hclge_fd_get_flow_tuples(const struct flow_keys *fkeys,
 				     struct hclge_fd_rule_tuples *tuples)
 {
+#define flow_ip6_src fkeys->addrs.v6addrs.src.in6_u.u6_addr32
+#define flow_ip6_dst fkeys->addrs.v6addrs.dst.in6_u.u6_addr32
+
 	tuples->ether_proto = be16_to_cpu(fkeys->basic.n_proto);
 	tuples->ip_proto = fkeys->basic.ip_proto;
 	tuples->dst_port = be16_to_cpu(fkeys->ports.dst);
@@ -6011,12 +6152,12 @@
 		tuples->src_ip[3] = be32_to_cpu(fkeys->addrs.v4addrs.src);
 		tuples->dst_ip[3] = be32_to_cpu(fkeys->addrs.v4addrs.dst);
 	} else {
-		memcpy(tuples->src_ip,
-		       fkeys->addrs.v6addrs.src.in6_u.u6_addr32,
-		       sizeof(tuples->src_ip));
-		memcpy(tuples->dst_ip,
-		       fkeys->addrs.v6addrs.dst.in6_u.u6_addr32,
-		       sizeof(tuples->dst_ip));
+		int i;
+
+		for (i = 0; i < IPV6_SIZE; i++) {
+			tuples->src_ip[i] = be32_to_cpu(flow_ip6_src[i]);
+			tuples->dst_ip[i] = be32_to_cpu(flow_ip6_dst[i]);
+		}
 	}
 }
 
@@ -6064,7 +6205,7 @@
 				      u16 flow_id, struct flow_keys *fkeys)
 {
 	struct hclge_vport *vport = hclge_get_vport(handle);
-	struct hclge_fd_rule_tuples new_tuples;
+	struct hclge_fd_rule_tuples new_tuples = {};
 	struct hclge_dev *hdev = vport->back;
 	struct hclge_fd_rule *rule;
 	u16 tmp_queue_id;
@@ -6074,20 +6215,18 @@
 	if (!hnae3_dev_fd_supported(hdev))
 		return -EOPNOTSUPP;
 
-	memset(&new_tuples, 0, sizeof(new_tuples));
-	hclge_fd_get_flow_tuples(fkeys, &new_tuples);
-
-	spin_lock_bh(&hdev->fd_rule_lock);
-
 	/* when there is already fd rule existed add by user,
 	 * arfs should not work
 	 */
+	spin_lock_bh(&hdev->fd_rule_lock);
 	if (hdev->fd_active_type == HCLGE_FD_EP_ACTIVE) {
 		spin_unlock_bh(&hdev->fd_rule_lock);
 
 		return -EOPNOTSUPP;
 	}
 
+	hclge_fd_get_flow_tuples(fkeys, &new_tuples);
+
 	/* check is there flow director filter existed for this flow,
 	 * if not, create a new filter for it;
 	 * if filter exist with different queue id, modify the filter;
@@ -6172,6 +6311,7 @@
 #endif
 }
 
+/* make sure being called after lock up with fd_rule_lock */
 static void hclge_clear_arfs_rules(struct hnae3_handle *handle)
 {
 #ifdef CONFIG_RFS_ACCEL
@@ -6216,10 +6356,14 @@
 
 	hdev->fd_en = enable;
 	clear = hdev->fd_active_type == HCLGE_FD_ARFS_ACTIVE;
-	if (!enable)
+
+	if (!enable) {
+		spin_lock_bh(&hdev->fd_rule_lock);
 		hclge_del_all_fd_entries(handle, clear);
-	else
+		spin_unlock_bh(&hdev->fd_rule_lock);
+	} else {
 		hclge_restore_fd_entries(handle);
+	}
 }
 
 static void hclge_cfg_mac_mode(struct hclge_dev *hdev, bool enable)
@@ -6631,6 +6775,19 @@
 	}
 }
 
+static void hclge_flush_link_update(struct hclge_dev *hdev)
+{
+#define HCLGE_FLUSH_LINK_TIMEOUT	100000
+
+	unsigned long last = hdev->serv_processed_cnt;
+	int i = 0;
+
+	while (test_bit(HCLGE_STATE_LINK_UPDATING, &hdev->state) &&
+	       i++ < HCLGE_FLUSH_LINK_TIMEOUT &&
+	       last == hdev->serv_processed_cnt)
+		usleep_range(1, 1);
+}
+
 static void hclge_set_timer_task(struct hnae3_handle *handle, bool enable)
 {
 	struct hclge_vport *vport = hclge_get_vport(handle);
@@ -6639,12 +6796,12 @@
 	if (enable) {
 		hclge_task_schedule(hdev, round_jiffies_relative(HZ));
 	} else {
-		/* Set the DOWN flag here to disable the service to be
-		 * scheduled again
-		 */
+		/* Set the DOWN flag here to disable link updating */
 		set_bit(HCLGE_STATE_DOWN, &hdev->state);
-		cancel_delayed_work_sync(&hdev->service_task);
-		clear_bit(HCLGE_STATE_SERVICE_SCHED, &hdev->state);
+
+		/* flush memory to make sure DOWN is seen by service task */
+		smp_mb__before_atomic();
+		hclge_flush_link_update(hdev);
 	}
 }
 
@@ -6673,17 +6830,22 @@
 	int i;
 
 	set_bit(HCLGE_STATE_DOWN, &hdev->state);
-
+	spin_lock_bh(&hdev->fd_rule_lock);
 	hclge_clear_arfs_rules(handle);
+	spin_unlock_bh(&hdev->fd_rule_lock);
 
-	/* If it is not PF reset, the firmware will disable the MAC,
+	/* If it is not PF reset or FLR, the firmware will disable the MAC,
 	 * so it only need to stop phy here.
 	 */
-	if (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state) &&
-	    hdev->reset_type != HNAE3_FUNC_RESET) {
-		hclge_mac_stop_phy(hdev);
-		hclge_update_link_status(hdev);
-		return;
+	if (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state)) {
+		hclge_pfc_pause_en_cfg(hdev, HCLGE_PFC_TX_RX_DISABLE,
+				       HCLGE_PFC_DISABLE);
+		if (hdev->reset_type != HNAE3_FUNC_RESET &&
+		    hdev->reset_type != HNAE3_FLR_RESET) {
+			hclge_mac_stop_phy(hdev);
+			hclge_update_link_status(hdev);
+			return;
+		}
 	}
 
 	for (i = 0; i < handle->kinfo.num_tqps; i++)
@@ -6735,7 +6897,7 @@
 
 	if (cmdq_resp) {
 		dev_err(&hdev->pdev->dev,
-			"cmdq execute failed for get_mac_vlan_cmd_status,status=%d.\n",
+			"cmdq execute failed for get_mac_vlan_cmd_status,status=%u.\n",
 			cmdq_resp);
 		return -EIO;
 	}
@@ -6987,7 +7149,7 @@
 
 	if (allocated_size < hdev->wanted_umv_size)
 		dev_warn(&hdev->pdev->dev,
-			 "Alloc umv space failed, want %d, get %d\n",
+			 "Alloc umv space failed, want %u, get %u\n",
 			 hdev->wanted_umv_size, allocated_size);
 
 	mutex_init(&hdev->umv_mutex);
@@ -7155,7 +7317,7 @@
 
 	/* check if we just hit the duplicate */
 	if (!ret) {
-		dev_warn(&hdev->pdev->dev, "VF %d mac(%pM) exists\n",
+		dev_warn(&hdev->pdev->dev, "VF %u mac(%pM) exists\n",
 			 vport->vport_id, addr);
 		return 0;
 	}
@@ -7225,7 +7387,6 @@
 		return -EINVAL;
 	}
 	memset(&req, 0, sizeof(req));
-	hnae3_set_bit(req.entry_type, HCLGE_MAC_VLAN_BIT0_EN_B, 0);
 	hclge_prepare_mac_addr(&req, addr, true);
 	status = hclge_lookup_mac_vlan_tbl(vport, &req, desc, true);
 	if (status) {
@@ -7270,7 +7431,6 @@
 	}
 
 	memset(&req, 0, sizeof(req));
-	hnae3_set_bit(req.entry_type, HCLGE_MAC_VLAN_BIT0_EN_B, 0);
 	hclge_prepare_mac_addr(&req, addr, true);
 	status = hclge_lookup_mac_vlan_tbl(vport, &req, desc, true);
 	if (!status) {
@@ -7336,7 +7496,7 @@
 	mc_flag = is_write_tbl && mac_type == HCLGE_MAC_ADDR_MC;
 
 	list_for_each_entry_safe(mac_cfg, tmp, list, node) {
-		if (strncmp(mac_cfg->mac_addr, mac_addr, ETH_ALEN) == 0) {
+		if (ether_addr_equal(mac_cfg->mac_addr, mac_addr)) {
 			if (uc_flag && mac_cfg->hd_tbl_status)
 				hclge_rm_uc_addr_common(vport, mac_addr);
 
@@ -7380,7 +7540,6 @@
 	struct hclge_vport *vport;
 	int i;
 
-	mutex_lock(&hdev->vport_cfg_mutex);
 	for (i = 0; i < hdev->num_alloc_vport; i++) {
 		vport = &hdev->vport[i];
 		list_for_each_entry_safe(mac, tmp, &vport->uc_mac_list, node) {
@@ -7393,7 +7552,6 @@
 			kfree(mac);
 		}
 	}
-	mutex_unlock(&hdev->vport_cfg_mutex);
 }
 
 static int hclge_get_mac_ethertype_cmd_status(struct hclge_dev *hdev,
@@ -7408,7 +7566,7 @@
 
 	if (cmdq_resp) {
 		dev_err(&hdev->pdev->dev,
-			"cmdq execute failed for get_mac_ethertype_cmd_status, status=%d.\n",
+			"cmdq execute failed for get_mac_ethertype_cmd_status, status=%u.\n",
 			cmdq_resp);
 		return -EIO;
 	}
@@ -7430,7 +7588,7 @@
 		break;
 	default:
 		dev_err(&hdev->pdev->dev,
-			"add mac ethertype failed for undefined, code=%d.\n",
+			"add mac ethertype failed for undefined, code=%u.\n",
 			resp_code);
 		return_status = -EIO;
 	}
@@ -7438,6 +7596,73 @@
 	return return_status;
 }
 
+static bool hclge_check_vf_mac_exist(struct hclge_vport *vport, int vf_idx,
+				     u8 *mac_addr)
+{
+	struct hclge_mac_vlan_tbl_entry_cmd req;
+	struct hclge_dev *hdev = vport->back;
+	struct hclge_desc desc;
+	u16 egress_port = 0;
+	int i;
+
+	if (is_zero_ether_addr(mac_addr))
+		return false;
+
+	memset(&req, 0, sizeof(req));
+	hnae3_set_field(egress_port, HCLGE_MAC_EPORT_VFID_M,
+			HCLGE_MAC_EPORT_VFID_S, vport->vport_id);
+	req.egress_port = cpu_to_le16(egress_port);
+	hclge_prepare_mac_addr(&req, mac_addr, false);
+
+	if (hclge_lookup_mac_vlan_tbl(vport, &req, &desc, false) != -ENOENT)
+		return true;
+
+	vf_idx += HCLGE_VF_VPORT_START_NUM;
+	for (i = hdev->num_vmdq_vport + 1; i < hdev->num_alloc_vport; i++)
+		if (i != vf_idx &&
+		    ether_addr_equal(mac_addr, hdev->vport[i].vf_info.mac))
+			return true;
+
+	return false;
+}
+
+static int hclge_set_vf_mac(struct hnae3_handle *handle, int vf,
+			    u8 *mac_addr)
+{
+	struct hclge_vport *vport = hclge_get_vport(handle);
+	struct hclge_dev *hdev = vport->back;
+
+	vport = hclge_get_vf_vport(hdev, vf);
+	if (!vport)
+		return -EINVAL;
+
+	if (ether_addr_equal(mac_addr, vport->vf_info.mac)) {
+		dev_info(&hdev->pdev->dev,
+			 "Specified MAC(=%pM) is same as before, no change committed!\n",
+			 mac_addr);
+		return 0;
+	}
+
+	if (hclge_check_vf_mac_exist(vport, vf, mac_addr)) {
+		dev_err(&hdev->pdev->dev, "Specified MAC(=%pM) exists!\n",
+			mac_addr);
+		return -EEXIST;
+	}
+
+	ether_addr_copy(vport->vf_info.mac, mac_addr);
+
+	if (test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state)) {
+		dev_info(&hdev->pdev->dev,
+			 "MAC of VF %d has been set to %pM, and it will be reinitialized!\n",
+			 vf, mac_addr);
+		return hclge_inform_reset_assert_to_vf(vport);
+	}
+
+	dev_info(&hdev->pdev->dev, "MAC of VF %d has been set to %pM\n",
+		 vf, mac_addr);
+	return 0;
+}
+
 static int hclge_add_mgr_tbl(struct hclge_dev *hdev,
 			     const struct hclge_mac_mgr_tbl_entry_cmd *req)
 {
@@ -7558,16 +7783,27 @@
 	struct hclge_desc desc;
 	int ret;
 
-	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_VLAN_FILTER_CTRL, false);
-
+	/* read current vlan filter parameter */
+	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_VLAN_FILTER_CTRL, true);
 	req = (struct hclge_vlan_filter_ctrl_cmd *)desc.data;
 	req->vlan_type = vlan_type;
-	req->vlan_fe = filter_en ? fe_type : 0;
 	req->vf_id = vf_id;
 
 	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+	if (ret) {
+		dev_err(&hdev->pdev->dev,
+			"failed to get vlan filter config, ret = %d.\n", ret);
+		return ret;
+	}
+
+	/* modify and write new config parameter */
+	hclge_cmd_reuse_desc(&desc, false);
+	req->vlan_fe = filter_en ?
+			(req->vlan_fe | fe_type) : (req->vlan_fe & ~fe_type);
+
+	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
 	if (ret)
-		dev_err(&hdev->pdev->dev, "set vlan filter fail, ret =%d.\n",
+		dev_err(&hdev->pdev->dev, "failed to set vlan filter, ret = %d.\n",
 			ret);
 
 	return ret;
@@ -7610,7 +7846,7 @@
 				    bool is_kill, u16 vlan,
 				    __be16 proto)
 {
-#define HCLGE_MAX_VF_BYTES  16
+	struct hclge_vport *vport = &hdev->vport[vfid];
 	struct hclge_vlan_filter_vf_cfg_cmd *req0;
 	struct hclge_vlan_filter_vf_cfg_cmd *req1;
 	struct hclge_desc desc[2];
@@ -7619,10 +7855,18 @@
 	int ret;
 
 	/* if vf vlan table is full, firmware will close vf vlan filter, it
-	 * is unable and unnecessary to add new vlan id to vf vlan filter
+	 * is unable and unnecessary to add new vlan id to vf vlan filter.
+	 * If spoof check is enable, and vf vlan is full, it shouldn't add
+	 * new vlan, because tx packets with these vlan id will be dropped.
 	 */
-	if (test_bit(vfid, hdev->vf_vlan_full) && !is_kill)
+	if (test_bit(vfid, hdev->vf_vlan_full) && !is_kill) {
+		if (vport->vf_info.spoofchk && vlan) {
+			dev_err(&hdev->pdev->dev,
+				"Can't add vlan due to spoof check is on and vf vlan table is full\n");
+			return -EPERM;
+		}
 		return 0;
+	}
 
 	hclge_cmd_setup_basic_desc(&desc[0],
 				   HCLGE_OPC_VLAN_FILTER_VF_CFG, false);
@@ -7666,7 +7910,7 @@
 		}
 
 		dev_err(&hdev->pdev->dev,
-			"Add vf vlan filter fail, ret =%d.\n",
+			"Add vf vlan filter fail, ret =%u.\n",
 			req0->resp_code);
 	} else {
 #define HCLGE_VF_VLAN_DEL_NO_FOUND	1
@@ -7682,7 +7926,7 @@
 			return 0;
 
 		dev_err(&hdev->pdev->dev,
-			"Kill vf vlan filter fail, ret =%d.\n",
+			"Kill vf vlan filter fail, ret =%u.\n",
 			req0->resp_code);
 	}
 
@@ -7701,9 +7945,10 @@
 
 	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_VLAN_FILTER_PF_CFG, false);
 
-	vlan_offset_160 = vlan_id / 160;
-	vlan_offset_byte = (vlan_id % 160) / 8;
-	vlan_offset_byte_val = 1 << (vlan_id % 8);
+	vlan_offset_160 = vlan_id / HCLGE_VLAN_ID_OFFSET_STEP;
+	vlan_offset_byte = (vlan_id % HCLGE_VLAN_ID_OFFSET_STEP) /
+			   HCLGE_VLAN_BYTE_SIZE;
+	vlan_offset_byte_val = 1 << (vlan_id % HCLGE_VLAN_BYTE_SIZE);
 
 	req = (struct hclge_vlan_filter_pf_cfg_cmd *)desc.data;
 	req->vlan_offset = vlan_offset_160;
@@ -7731,7 +7976,7 @@
 				       proto);
 	if (ret) {
 		dev_err(&hdev->pdev->dev,
-			"Set %d vport vlan filter config fail, ret =%d.\n",
+			"Set %u vport vlan filter config fail, ret =%d.\n",
 			vport_id, ret);
 		return ret;
 	}
@@ -7743,7 +7988,7 @@
 
 	if (!is_kill && test_and_set_bit(vport_id, hdev->vlan_table[vlan_id])) {
 		dev_err(&hdev->pdev->dev,
-			"Add port vlan failed, vport %d is already in vlan %d\n",
+			"Add port vlan failed, vport %u is already in vlan %u\n",
 			vport_id, vlan_id);
 		return -EINVAL;
 	}
@@ -7751,7 +7996,7 @@
 	if (is_kill &&
 	    !test_and_clear_bit(vport_id, hdev->vlan_table[vlan_id])) {
 		dev_err(&hdev->pdev->dev,
-			"Delete port vlan failed, vport %d is not in vlan %d\n",
+			"Delete port vlan failed, vport %u is not in vlan %u\n",
 			vport_id, vlan_id);
 		return -EINVAL;
 	}
@@ -7999,7 +8244,11 @@
 static void hclge_add_vport_vlan_table(struct hclge_vport *vport, u16 vlan_id,
 				       bool writen_to_tbl)
 {
-	struct hclge_vport_vlan_cfg *vlan;
+	struct hclge_vport_vlan_cfg *vlan, *tmp;
+
+	list_for_each_entry_safe(vlan, tmp, &vport->vlan_list, node)
+		if (vlan->vlan_id == vlan_id)
+			return;
 
 	vlan = kzalloc(sizeof(*vlan), GFP_KERNEL);
 	if (!vlan)
@@ -8076,6 +8325,7 @@
 			kfree(vlan);
 		}
 	}
+	clear_bit(vport->vport_id, hdev->vf_vlan_full);
 }
 
 void hclge_uninit_vport_vlan_table(struct hclge_dev *hdev)
@@ -8084,7 +8334,6 @@
 	struct hclge_vport *vport;
 	int i;
 
-	mutex_lock(&hdev->vport_cfg_mutex);
 	for (i = 0; i < hdev->num_alloc_vport; i++) {
 		vport = &hdev->vport[i];
 		list_for_each_entry_safe(vlan, tmp, &vport->vlan_list, node) {
@@ -8092,7 +8341,6 @@
 			kfree(vlan);
 		}
 	}
-	mutex_unlock(&hdev->vport_cfg_mutex);
 }
 
 static void hclge_restore_vlan_table(struct hnae3_handle *handle)
@@ -8104,7 +8352,6 @@
 	u16 state, vlan_id;
 	int i;
 
-	mutex_lock(&hdev->vport_cfg_mutex);
 	for (i = 0; i < hdev->num_alloc_vport; i++) {
 		vport = &hdev->vport[i];
 		vlan_proto = vport->port_base_vlan_cfg.vlan_info.vlan_proto;
@@ -8119,16 +8366,17 @@
 		}
 
 		list_for_each_entry_safe(vlan, tmp, &vport->vlan_list, node) {
-			if (vlan->hd_tbl_status)
-				hclge_set_vlan_filter_hw(hdev,
-							 htons(ETH_P_8021Q),
-							 vport->vport_id,
-							 vlan->vlan_id,
-							 false);
+			int ret;
+
+			if (!vlan->hd_tbl_status)
+				continue;
+			ret = hclge_set_vlan_filter_hw(hdev, htons(ETH_P_8021Q),
+						       vport->vport_id,
+						       vlan->vlan_id, false);
+			if (ret)
+				break;
 		}
 	}
-
-	mutex_unlock(&hdev->vport_cfg_mutex);
 }
 
 int hclge_en_hw_strip_rxvtag(struct hnae3_handle *handle, bool enable)
@@ -8262,13 +8510,16 @@
 	if (hdev->pdev->revision == 0x20)
 		return -EOPNOTSUPP;
 
+	vport = hclge_get_vf_vport(hdev, vfid);
+	if (!vport)
+		return -EINVAL;
+
 	/* qos is a 3 bits value, so can not be bigger than 7 */
-	if (vfid >= hdev->num_alloc_vfs || vlan > VLAN_N_VID - 1 || qos > 7)
+	if (vlan > VLAN_N_VID - 1 || qos > 7)
 		return -EINVAL;
 	if (proto != htons(ETH_P_8021Q))
 		return -EPROTONOSUPPORT;
 
-	vport = &hdev->vport[vfid];
 	state = hclge_get_port_base_vlan_state(vport,
 					       vport->port_base_vlan_cfg.state,
 					       vlan);
@@ -8279,27 +8530,40 @@
 	vlan_info.qos = qos;
 	vlan_info.vlan_proto = ntohs(proto);
 
-	/* update port based VLAN for PF */
-	if (!vfid) {
-		hclge_notify_client(hdev, HNAE3_DOWN_CLIENT);
-		ret = hclge_update_port_base_vlan_cfg(vport, state, &vlan_info);
-		hclge_notify_client(hdev, HNAE3_UP_CLIENT);
-
-		return ret;
-	}
-
 	if (!test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state)) {
 		return hclge_update_port_base_vlan_cfg(vport, state,
 						       &vlan_info);
 	} else {
 		ret = hclge_push_vf_port_base_vlan_info(&hdev->vport[0],
-							(u8)vfid, state,
+							vport->vport_id, state,
 							vlan, qos,
 							ntohs(proto));
 		return ret;
 	}
 }
 
+static void hclge_clear_vf_vlan(struct hclge_dev *hdev)
+{
+	struct hclge_vlan_info *vlan_info;
+	struct hclge_vport *vport;
+	int ret;
+	int vf;
+
+	/* clear port base vlan for all vf */
+	for (vf = HCLGE_VF_VPORT_START_NUM; vf < hdev->num_alloc_vport; vf++) {
+		vport = &hdev->vport[vf];
+		vlan_info = &vport->port_base_vlan_cfg.vlan_info;
+
+		ret = hclge_set_vlan_filter_hw(hdev, htons(ETH_P_8021Q),
+					       vport->vport_id,
+					       vlan_info->vlan_tag, true);
+		if (ret)
+			dev_err(&hdev->pdev->dev,
+				"failed to clear vf vlan for vf%d, ret = %d\n",
+				vf - HCLGE_VF_VPORT_START_NUM, ret);
+	}
+}
+
 int hclge_set_vlan_filter(struct hnae3_handle *handle, __be16 proto,
 			  u16 vlan_id, bool is_kill)
 {
@@ -8330,11 +8594,11 @@
 	}
 
 	if (!ret) {
-		if (is_kill)
-			hclge_rm_vport_vlan_table(vport, vlan_id, false);
-		else
+		if (!is_kill)
 			hclge_add_vport_vlan_table(vport, vlan_id,
 						   writen_to_tbl);
+		else if (is_kill && vlan_id != 0)
+			hclge_rm_vport_vlan_table(vport, vlan_id, false);
 	} else if (is_kill) {
 		/* when remove hw vlan filter failed, record the vlan id,
 		 * and try to remove it from hw later, to be consistence
@@ -8404,6 +8668,7 @@
 	struct hclge_dev *hdev = vport->back;
 	int i, max_frm_size, ret;
 
+	/* HW supprt 2 layer vlan */
 	max_frm_size = new_mtu + ETH_HLEN + ETH_FCS_LEN + 2 * VLAN_HLEN;
 	if (max_frm_size < HCLGE_MAC_MIN_FRAME ||
 	    max_frm_size > HCLGE_MAC_MAX_FRAME)
@@ -8555,12 +8820,19 @@
 
 void hclge_reset_vf_queue(struct hclge_vport *vport, u16 queue_id)
 {
+	struct hnae3_handle *handle = &vport->nic;
 	struct hclge_dev *hdev = vport->back;
 	int reset_try_times = 0;
 	int reset_status;
 	u16 queue_gid;
 	int ret;
 
+	if (queue_id >= handle->kinfo.num_tqps) {
+		dev_warn(&hdev->pdev->dev, "Invalid vf queue id(%u)\n",
+			 queue_id);
+		return;
+	}
+
 	queue_gid = hclge_covert_handle_qid_global(&vport->nic, queue_id);
 
 	ret = hclge_send_reset_tqp_cmd(hdev, queue_gid, true);
@@ -8819,16 +9091,16 @@
 
 	dev_info(dev, "PF info begin:\n");
 
-	dev_info(dev, "Task queue pairs numbers: %d\n", hdev->num_tqps);
-	dev_info(dev, "Desc num per TX queue: %d\n", hdev->num_tx_desc);
-	dev_info(dev, "Desc num per RX queue: %d\n", hdev->num_rx_desc);
-	dev_info(dev, "Numbers of vports: %d\n", hdev->num_alloc_vport);
-	dev_info(dev, "Numbers of vmdp vports: %d\n", hdev->num_vmdq_vport);
-	dev_info(dev, "Numbers of VF for this PF: %d\n", hdev->num_req_vfs);
-	dev_info(dev, "HW tc map: %d\n", hdev->hw_tc_map);
-	dev_info(dev, "Total buffer size for TX/RX: %d\n", hdev->pkt_buf_size);
-	dev_info(dev, "TX buffer size for each TC: %d\n", hdev->tx_buf_size);
-	dev_info(dev, "DV buffer size for each TC: %d\n", hdev->dv_buf_size);
+	dev_info(dev, "Task queue pairs numbers: %u\n", hdev->num_tqps);
+	dev_info(dev, "Desc num per TX queue: %u\n", hdev->num_tx_desc);
+	dev_info(dev, "Desc num per RX queue: %u\n", hdev->num_rx_desc);
+	dev_info(dev, "Numbers of vports: %u\n", hdev->num_alloc_vport);
+	dev_info(dev, "Numbers of vmdp vports: %u\n", hdev->num_vmdq_vport);
+	dev_info(dev, "Numbers of VF for this PF: %u\n", hdev->num_req_vfs);
+	dev_info(dev, "HW tc map: 0x%x\n", hdev->hw_tc_map);
+	dev_info(dev, "Total buffer size for TX/RX: %u\n", hdev->pkt_buf_size);
+	dev_info(dev, "TX buffer size for each TC: %u\n", hdev->tx_buf_size);
+	dev_info(dev, "DV buffer size for each TC: %u\n", hdev->dv_buf_size);
 	dev_info(dev, "This is %s PF\n",
 		 hdev->flag & HCLGE_FLAG_MAIN ? "main" : "not main");
 	dev_info(dev, "DCB %s\n",
@@ -8844,10 +9116,9 @@
 {
 	struct hnae3_client *client = vport->nic.client;
 	struct hclge_dev *hdev = ae_dev->priv;
-	int rst_cnt;
+	int rst_cnt = hdev->rst_stats.reset_cnt;
 	int ret;
 
-	rst_cnt = hdev->rst_stats.reset_cnt;
 	ret = client->ops->init_instance(&vport->nic);
 	if (ret)
 		return ret;
@@ -8947,7 +9218,6 @@
 
 		switch (client->type) {
 		case HNAE3_CLIENT_KNIC:
-
 			hdev->nic_client = client;
 			vport->nic.client = client;
 			ret = hclge_init_nic_client_instance(ae_dev, vport);
@@ -9087,6 +9357,7 @@
 	set_bit(HCLGE_STATE_DOWN, &hdev->state);
 	clear_bit(HCLGE_STATE_RST_SERVICE_SCHED, &hdev->state);
 	clear_bit(HCLGE_STATE_RST_HANDLING, &hdev->state);
+	clear_bit(HCLGE_STATE_RST_FAIL, &hdev->state);
 	clear_bit(HCLGE_STATE_MBX_SERVICE_SCHED, &hdev->state);
 	clear_bit(HCLGE_STATE_MBX_HANDLING, &hdev->state);
 }
@@ -9100,38 +9371,57 @@
 		del_timer_sync(&hdev->reset_timer);
 	if (hdev->service_task.work.func)
 		cancel_delayed_work_sync(&hdev->service_task);
-	if (hdev->rst_service_task.func)
-		cancel_work_sync(&hdev->rst_service_task);
-	if (hdev->mbx_service_task.func)
-		cancel_work_sync(&hdev->mbx_service_task);
 }
 
 static void hclge_flr_prepare(struct hnae3_ae_dev *ae_dev)
 {
-#define HCLGE_FLR_WAIT_MS	100
-#define HCLGE_FLR_WAIT_CNT	50
-	struct hclge_dev *hdev = ae_dev->priv;
-	int cnt = 0;
+#define HCLGE_FLR_RETRY_WAIT_MS	500
+#define HCLGE_FLR_RETRY_CNT	5
 
-	clear_bit(HNAE3_FLR_DOWN, &hdev->flr_state);
-	clear_bit(HNAE3_FLR_DONE, &hdev->flr_state);
-	set_bit(HNAE3_FLR_RESET, &hdev->default_reset_request);
-	hclge_reset_event(hdev->pdev, NULL);
+	struct hclge_dev *hdev = ae_dev->priv;
+	int retry_cnt = 0;
+	int ret;
 
-	while (!test_bit(HNAE3_FLR_DOWN, &hdev->flr_state) &&
-	       cnt++ < HCLGE_FLR_WAIT_CNT)
-		msleep(HCLGE_FLR_WAIT_MS);
+retry:
+	down(&hdev->reset_sem);
+	set_bit(HCLGE_STATE_RST_HANDLING, &hdev->state);
+	hdev->reset_type = HNAE3_FLR_RESET;
+	ret = hclge_reset_prepare(hdev);
+	if (ret) {
+		dev_err(&hdev->pdev->dev, "fail to prepare FLR, ret=%d\n",
+			ret);
+		if (hdev->reset_pending ||
+		    retry_cnt++ < HCLGE_FLR_RETRY_CNT) {
+			dev_err(&hdev->pdev->dev,
+				"reset_pending:0x%lx, retry_cnt:%d\n",
+				hdev->reset_pending, retry_cnt);
+			clear_bit(HCLGE_STATE_RST_HANDLING, &hdev->state);
+			up(&hdev->reset_sem);
+			msleep(HCLGE_FLR_RETRY_WAIT_MS);
+			goto retry;
+		}
+	}
 
-	if (!test_bit(HNAE3_FLR_DOWN, &hdev->flr_state))
-		dev_err(&hdev->pdev->dev,
-			"flr wait down timeout: %d\n", cnt);
+	/* disable misc vector before FLR done */
+	hclge_enable_vector(&hdev->misc_vector, false);
+	set_bit(HCLGE_STATE_CMD_DISABLE, &hdev->state);
+	hdev->rst_stats.flr_rst_cnt++;
 }
 
 static void hclge_flr_done(struct hnae3_ae_dev *ae_dev)
 {
 	struct hclge_dev *hdev = ae_dev->priv;
+	int ret;
 
-	set_bit(HNAE3_FLR_DONE, &hdev->flr_state);
+	hclge_enable_vector(&hdev->misc_vector, true);
+
+	ret = hclge_reset_rebuild(hdev);
+	if (ret)
+		dev_err(&hdev->pdev->dev, "fail to rebuild, ret=%d\n", ret);
+
+	hdev->reset_type = HNAE3_NONE_RESET;
+	clear_bit(HCLGE_STATE_RST_HANDLING, &hdev->state);
+	up(&hdev->reset_sem);
 }
 
 static void hclge_clear_resetting_state(struct hclge_dev *hdev)
@@ -9146,11 +9436,33 @@
 		ret = hclge_set_vf_rst(hdev, vport->vport_id, false);
 		if (ret)
 			dev_warn(&hdev->pdev->dev,
-				 "clear vf(%d) rst failed %d!\n",
+				 "clear vf(%u) rst failed %d!\n",
 				 vport->vport_id, ret);
 	}
 }
 
+static int hclge_clear_hw_resource(struct hclge_dev *hdev)
+{
+	struct hclge_desc desc;
+	int ret;
+
+	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CLEAR_HW_RESOURCE, false);
+
+	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+	/* This new command is only supported by new firmware, it will
+	 * fail with older firmware. Error value -EOPNOSUPP can only be
+	 * returned by older firmware running this command, to keep code
+	 * backward compatible we will override this value and return
+	 * success.
+	 */
+	if (ret && ret != -EOPNOTSUPP) {
+		dev_err(&hdev->pdev->dev,
+			"failed to clear hw resource, ret = %d\n", ret);
+		return ret;
+	}
+	return 0;
+}
+
 static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
 {
 	struct pci_dev *pdev = ae_dev->pdev;
@@ -9168,11 +9480,13 @@
 	hdev->reset_type = HNAE3_NONE_RESET;
 	hdev->reset_level = HNAE3_FUNC_RESET;
 	ae_dev->priv = hdev;
+
+	/* HW supprt 2 layer vlan */
 	hdev->mps = ETH_FRAME_LEN + ETH_FCS_LEN + 2 * VLAN_HLEN;
 
 	mutex_init(&hdev->vport_lock);
-	mutex_init(&hdev->vport_cfg_mutex);
 	spin_lock_init(&hdev->fd_rule_lock);
+	sema_init(&hdev->reset_sem, 1);
 
 	ret = hclge_pci_init(hdev);
 	if (ret) {
@@ -9192,6 +9506,10 @@
 	if (ret)
 		goto err_cmd_uninit;
 
+	ret  = hclge_clear_hw_resource(hdev);
+	if (ret)
+		goto err_cmd_uninit;
+
 	ret = hclge_get_cap(hdev);
 	if (ret) {
 		dev_err(&pdev->dev, "get hw capability error, ret = %d.\n",
@@ -9306,8 +9624,6 @@
 
 	timer_setup(&hdev->reset_timer, hclge_reset_timer, 0);
 	INIT_DELAYED_WORK(&hdev->service_task, hclge_service_task);
-	INIT_WORK(&hdev->rst_service_task, hclge_reset_service_task);
-	INIT_WORK(&hdev->mbx_service_task, hclge_mailbox_service_task);
 
 	/* Setup affinity after service timer setup because add_timer_on
 	 * is called in affinity notify.
@@ -9341,6 +9657,8 @@
 	dev_info(&hdev->pdev->dev, "%s driver initialization finished.\n",
 		 HCLGE_DRIVER_NAME);
 
+	hclge_task_schedule(hdev, round_jiffies_relative(HZ));
+
 	return 0;
 
 err_mdiobus_unreg:
@@ -9363,7 +9681,220 @@
 
 static void hclge_stats_clear(struct hclge_dev *hdev)
 {
-	memset(&hdev->hw_stats, 0, sizeof(hdev->hw_stats));
+	memset(&hdev->mac_stats, 0, sizeof(hdev->mac_stats));
+}
+
+static int hclge_set_mac_spoofchk(struct hclge_dev *hdev, int vf, bool enable)
+{
+	return hclge_config_switch_param(hdev, vf, enable,
+					 HCLGE_SWITCH_ANTI_SPOOF_MASK);
+}
+
+static int hclge_set_vlan_spoofchk(struct hclge_dev *hdev, int vf, bool enable)
+{
+	return hclge_set_vlan_filter_ctrl(hdev, HCLGE_FILTER_TYPE_VF,
+					  HCLGE_FILTER_FE_NIC_INGRESS_B,
+					  enable, vf);
+}
+
+static int hclge_set_vf_spoofchk_hw(struct hclge_dev *hdev, int vf, bool enable)
+{
+	int ret;
+
+	ret = hclge_set_mac_spoofchk(hdev, vf, enable);
+	if (ret) {
+		dev_err(&hdev->pdev->dev,
+			"Set vf %d mac spoof check %s failed, ret=%d\n",
+			vf, enable ? "on" : "off", ret);
+		return ret;
+	}
+
+	ret = hclge_set_vlan_spoofchk(hdev, vf, enable);
+	if (ret)
+		dev_err(&hdev->pdev->dev,
+			"Set vf %d vlan spoof check %s failed, ret=%d\n",
+			vf, enable ? "on" : "off", ret);
+
+	return ret;
+}
+
+static int hclge_set_vf_spoofchk(struct hnae3_handle *handle, int vf,
+				 bool enable)
+{
+	struct hclge_vport *vport = hclge_get_vport(handle);
+	struct hclge_dev *hdev = vport->back;
+	u32 new_spoofchk = enable ? 1 : 0;
+	int ret;
+
+	if (hdev->pdev->revision == 0x20)
+		return -EOPNOTSUPP;
+
+	vport = hclge_get_vf_vport(hdev, vf);
+	if (!vport)
+		return -EINVAL;
+
+	if (vport->vf_info.spoofchk == new_spoofchk)
+		return 0;
+
+	if (enable && test_bit(vport->vport_id, hdev->vf_vlan_full))
+		dev_warn(&hdev->pdev->dev,
+			 "vf %d vlan table is full, enable spoof check may cause its packet send fail\n",
+			 vf);
+	else if (enable && hclge_is_umv_space_full(vport))
+		dev_warn(&hdev->pdev->dev,
+			 "vf %d mac table is full, enable spoof check may cause its packet send fail\n",
+			 vf);
+
+	ret = hclge_set_vf_spoofchk_hw(hdev, vport->vport_id, enable);
+	if (ret)
+		return ret;
+
+	vport->vf_info.spoofchk = new_spoofchk;
+	return 0;
+}
+
+static int hclge_reset_vport_spoofchk(struct hclge_dev *hdev)
+{
+	struct hclge_vport *vport = hdev->vport;
+	int ret;
+	int i;
+
+	if (hdev->pdev->revision == 0x20)
+		return 0;
+
+	/* resume the vf spoof check state after reset */
+	for (i = 0; i < hdev->num_alloc_vport; i++) {
+		ret = hclge_set_vf_spoofchk_hw(hdev, vport->vport_id,
+					       vport->vf_info.spoofchk);
+		if (ret)
+			return ret;
+
+		vport++;
+	}
+
+	return 0;
+}
+
+static int hclge_set_vf_trust(struct hnae3_handle *handle, int vf, bool enable)
+{
+	struct hclge_vport *vport = hclge_get_vport(handle);
+	struct hclge_dev *hdev = vport->back;
+	u32 new_trusted = enable ? 1 : 0;
+	bool en_bc_pmc;
+	int ret;
+
+	vport = hclge_get_vf_vport(hdev, vf);
+	if (!vport)
+		return -EINVAL;
+
+	if (vport->vf_info.trusted == new_trusted)
+		return 0;
+
+	/* Disable promisc mode for VF if it is not trusted any more. */
+	if (!enable && vport->vf_info.promisc_enable) {
+		en_bc_pmc = hdev->pdev->revision != 0x20;
+		ret = hclge_set_vport_promisc_mode(vport, false, false,
+						   en_bc_pmc);
+		if (ret)
+			return ret;
+		vport->vf_info.promisc_enable = 0;
+		hclge_inform_vf_promisc_info(vport);
+	}
+
+	vport->vf_info.trusted = new_trusted;
+
+	return 0;
+}
+
+static void hclge_reset_vf_rate(struct hclge_dev *hdev)
+{
+	int ret;
+	int vf;
+
+	/* reset vf rate to default value */
+	for (vf = HCLGE_VF_VPORT_START_NUM; vf < hdev->num_alloc_vport; vf++) {
+		struct hclge_vport *vport = &hdev->vport[vf];
+
+		vport->vf_info.max_tx_rate = 0;
+		ret = hclge_tm_qs_shaper_cfg(vport, vport->vf_info.max_tx_rate);
+		if (ret)
+			dev_err(&hdev->pdev->dev,
+				"vf%d failed to reset to default, ret=%d\n",
+				vf - HCLGE_VF_VPORT_START_NUM, ret);
+	}
+}
+
+static int hclge_vf_rate_param_check(struct hclge_dev *hdev, int vf,
+				     int min_tx_rate, int max_tx_rate)
+{
+	if (min_tx_rate != 0 ||
+	    max_tx_rate < 0 || max_tx_rate > hdev->hw.mac.max_speed) {
+		dev_err(&hdev->pdev->dev,
+			"min_tx_rate:%d [0], max_tx_rate:%d [0, %u]\n",
+			min_tx_rate, max_tx_rate, hdev->hw.mac.max_speed);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int hclge_set_vf_rate(struct hnae3_handle *handle, int vf,
+			     int min_tx_rate, int max_tx_rate, bool force)
+{
+	struct hclge_vport *vport = hclge_get_vport(handle);
+	struct hclge_dev *hdev = vport->back;
+	int ret;
+
+	ret = hclge_vf_rate_param_check(hdev, vf, min_tx_rate, max_tx_rate);
+	if (ret)
+		return ret;
+
+	vport = hclge_get_vf_vport(hdev, vf);
+	if (!vport)
+		return -EINVAL;
+
+	if (!force && max_tx_rate == vport->vf_info.max_tx_rate)
+		return 0;
+
+	ret = hclge_tm_qs_shaper_cfg(vport, max_tx_rate);
+	if (ret)
+		return ret;
+
+	vport->vf_info.max_tx_rate = max_tx_rate;
+
+	return 0;
+}
+
+static int hclge_resume_vf_rate(struct hclge_dev *hdev)
+{
+	struct hnae3_handle *handle = &hdev->vport->nic;
+	struct hclge_vport *vport;
+	int ret;
+	int vf;
+
+	/* resume the vf max_tx_rate after reset */
+	for (vf = 0; vf < pci_num_vf(hdev->pdev); vf++) {
+		vport = hclge_get_vf_vport(hdev, vf);
+		if (!vport)
+			return -EINVAL;
+
+		/* zero means max rate, after reset, firmware already set it to
+		 * max rate, so just continue.
+		 */
+		if (!vport->vf_info.max_tx_rate)
+			continue;
+
+		ret = hclge_set_vf_rate(handle, vf, 0,
+					vport->vf_info.max_tx_rate, true);
+		if (ret) {
+			dev_err(&hdev->pdev->dev,
+				"vf%d failed to resume tx_rate:%u, ret=%d\n",
+				vf, vport->vf_info.max_tx_rate, ret);
+			return ret;
+		}
+	}
+
+	return 0;
 }
 
 static void hclge_reset_vport_state(struct hclge_dev *hdev)
@@ -9437,12 +9968,22 @@
 		return ret;
 	}
 
+	ret = init_mgr_tbl(hdev);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"failed to reinit manager table, ret = %d\n", ret);
+		return ret;
+	}
+
 	ret = hclge_init_fd_config(hdev);
 	if (ret) {
 		dev_err(&pdev->dev, "fd table init fail, ret=%d\n", ret);
 		return ret;
 	}
 
+	/* Log and clear the hw errors those already occurred */
+	hclge_handle_all_hns_hw_errors(ae_dev);
+
 	/* Re-enable the hw error interrupts because
 	 * the interrupts get disabled on global reset.
 	 */
@@ -9465,6 +10006,13 @@
 	}
 
 	hclge_reset_vport_state(hdev);
+	ret = hclge_reset_vport_spoofchk(hdev);
+	if (ret)
+		return ret;
+
+	ret = hclge_resume_vf_rate(hdev);
+	if (ret)
+		return ret;
 
 	dev_info(&pdev->dev, "Reset done, %s driver initialization finished.\n",
 		 HCLGE_DRIVER_NAME);
@@ -9477,6 +10025,8 @@
 	struct hclge_dev *hdev = ae_dev->priv;
 	struct hclge_mac *mac = &hdev->hw.mac;
 
+	hclge_reset_vf_rate(hdev);
+	hclge_clear_vf_vlan(hdev);
 	hclge_misc_affinity_teardown(hdev);
 	hclge_state_uninit(hdev);
 
@@ -9500,7 +10050,6 @@
 	mutex_destroy(&hdev->vport_lock);
 	hclge_uninit_vport_mac_table(hdev);
 	hclge_uninit_vport_vlan_table(hdev);
-	mutex_destroy(&hdev->vport_cfg_mutex);
 	ae_dev->priv = NULL;
 }
 
@@ -9541,8 +10090,8 @@
 	u16 tc_offset[HCLGE_MAX_TC_NUM] = {0};
 	struct hclge_dev *hdev = vport->back;
 	u16 tc_size[HCLGE_MAX_TC_NUM] = {0};
-	int cur_rss_size = kinfo->rss_size;
-	int cur_tqps = kinfo->num_tqps;
+	u16 cur_rss_size = kinfo->rss_size;
+	u16 cur_tqps = kinfo->num_tqps;
 	u16 tc_valid[HCLGE_MAX_TC_NUM];
 	u16 roundup_size;
 	u32 *rss_indir;
@@ -9596,7 +10145,7 @@
 out:
 	if (!ret)
 		dev_info(&hdev->pdev->dev,
-			 "Channels changed, rss_size from %d to %d, tqps from %d to %d",
+			 "Channels changed, rss_size from %u to %u, tqps from %u to %u",
 			 cur_rss_size, kinfo->rss_size,
 			 cur_tqps, kinfo->rss_size * kinfo->num_tc);
 
@@ -9762,10 +10311,8 @@
 				    int *bd_num_list,
 				    u32 type_num)
 {
-#define HCLGE_DFX_REG_BD_NUM	4
-
 	u32 entries_per_desc, desc_index, index, offset, i;
-	struct hclge_desc desc[HCLGE_DFX_REG_BD_NUM];
+	struct hclge_desc desc[HCLGE_GET_DFX_REG_TYPE_CNT];
 	int ret;
 
 	ret = hclge_query_bd_num_cmd_send(hdev, desc);
@@ -9834,8 +10381,9 @@
 static int hclge_get_dfx_reg_len(struct hclge_dev *hdev, int *len)
 {
 	u32 dfx_reg_type_num = ARRAY_SIZE(hclge_dfx_bd_offset_list);
-	int data_len_per_desc, data_len, bd_num, i;
+	int data_len_per_desc, bd_num, i;
 	int bd_num_list[BD_LIST_MAX_NUM];
+	u32 data_len;
 	int ret;
 
 	ret = hclge_get_dfx_reg_bd_num(hdev, bd_num_list, dfx_reg_type_num);
@@ -9878,10 +10426,8 @@
 
 	buf_len = sizeof(*desc_src) * bd_num_max;
 	desc_src = kzalloc(buf_len, GFP_KERNEL);
-	if (!desc_src) {
-		dev_err(&hdev->pdev->dev, "%s kzalloc failed\n", __func__);
+	if (!desc_src)
 		return -ENOMEM;
-	}
 
 	for (i = 0; i < dfx_reg_type_num; i++) {
 		bd_num = bd_num_list[i];
@@ -10199,6 +10745,12 @@
 	.mac_connect_phy = hclge_mac_connect_phy,
 	.mac_disconnect_phy = hclge_mac_disconnect_phy,
 	.restore_vlan_table = hclge_restore_vlan_table,
+	.get_vf_config = hclge_get_vf_config,
+	.set_vf_link_state = hclge_set_vf_link_state,
+	.set_vf_spoofchk = hclge_set_vf_spoofchk,
+	.set_vf_trust = hclge_set_vf_trust,
+	.set_vf_rate = hclge_set_vf_rate,
+	.set_vf_mac = hclge_set_vf_mac,
 };
 
 static struct hnae3_ae_algo ae_algo = {
@@ -10210,6 +10762,12 @@
 {
 	pr_info("%s is initializing\n", HCLGE_NAME);
 
+	hclge_wq = alloc_workqueue("%s", WQ_MEM_RECLAIM, 0, HCLGE_NAME);
+	if (!hclge_wq) {
+		pr_err("%s: failed to create workqueue\n", HCLGE_NAME);
+		return -ENOMEM;
+	}
+
 	hnae3_register_ae_algo(&ae_algo);
 
 	return 0;
@@ -10217,7 +10775,9 @@
 
 static void hclge_exit(void)
 {
+	hnae3_unregister_ae_algo_prepare(&ae_algo);
 	hnae3_unregister_ae_algo(&ae_algo);
+	destroy_workqueue(hclge_wq);
 }
 module_init(hclge_init);
 module_exit(hclge_exit);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
@@ -139,9 +139,10 @@
 #define HCLGE_PHY_MDIX_STATUS_B		6
 #define HCLGE_PHY_SPEED_DUP_RESOLVE_B	11
 
+#define HCLGE_GET_DFX_REG_TYPE_CNT	4
+
 /* Factor used to calculate offset and bitmap of VF num */
 #define HCLGE_VF_NUM_PER_CMD           64
-#define HCLGE_VF_NUM_PER_BYTE          8
 
 enum HLCGE_PORT_TYPE {
 	HOST_PORT,
@@ -209,13 +210,14 @@
 	HCLGE_STATE_NIC_REGISTERED,
 	HCLGE_STATE_ROCE_REGISTERED,
 	HCLGE_STATE_SERVICE_INITED,
-	HCLGE_STATE_SERVICE_SCHED,
 	HCLGE_STATE_RST_SERVICE_SCHED,
 	HCLGE_STATE_RST_HANDLING,
 	HCLGE_STATE_MBX_SERVICE_SCHED,
 	HCLGE_STATE_MBX_HANDLING,
 	HCLGE_STATE_STATISTICS_UPDATING,
 	HCLGE_STATE_CMD_DISABLE,
+	HCLGE_STATE_LINK_UPDATING,
+	HCLGE_STATE_RST_FAIL,
 	HCLGE_STATE_MAX
 };
 
@@ -226,8 +228,6 @@
 	HCLGE_VECTOR0_EVENT_OTHER,
 };
 
-#define HCLGE_MPF_ENBALE 1
-
 enum HCLGE_MAC_SPEED {
 	HCLGE_MAC_SPEED_UNKNOWN = 0,		/* unknown */
 	HCLGE_MAC_SPEED_10M	= 10,		/* 10 Mbps */
@@ -249,6 +249,7 @@
 #define QUERY_ACTIVE_SPEED	1
 
 struct hclge_mac {
+	u8 mac_id;
 	u8 phy_addr;
 	u8 flag;
 	u8 media_type;	/* port media type, e.g. fibre/copper/backplane */
@@ -258,6 +259,7 @@
 	u8 support_autoneg;
 	u8 speed_type;	/* 0: sfp speed, 1: active speed */
 	u32 speed;
+	u32 max_speed;
 	u32 speed_ability; /* speed ability supported by current media */
 	u32 module_type; /* sub media type, e.g. kr/cr/sr/lr */
 	u32 fec_mode; /* active fec mode */
@@ -456,11 +458,7 @@
 	u64 mac_rx_ctrl_pkt_num;
 };
 
-#define HCLGE_STATS_TIMER_INTERVAL	(60 * 5)
-struct hclge_hw_stats {
-	struct hclge_mac_stats      mac_stats;
-	u32 stats_timer;
-};
+#define HCLGE_STATS_TIMER_INTERVAL	300UL
 
 struct hclge_vlan_type_cfg {
 	u16 rx_ot_fst_vlan_type;
@@ -551,7 +549,7 @@
 
 /* assigned by firmware, the real filter number for each pf may be less */
 #define MAX_FD_FILTER_NUM	4096
-#define HCLGE_FD_ARFS_EXPIRE_TIMER_INTERVAL	5
+#define HCLGE_ARFS_EXPIRE_INTERVAL	5UL
 
 enum HCLGE_FD_ACTIVE_RULE_TYPE {
 	HCLGE_FD_RULE_NONE,
@@ -655,7 +653,6 @@
 	u32 hw_reset_done_cnt;	/* the number of HW reset has completed */
 	u32 pf_rst_cnt;		/* the number of PF reset */
 	u32 flr_rst_cnt;	/* the number of FLR */
-	u32 core_rst_cnt;	/* the number of CORE reset */
 	u32 global_rst_cnt;	/* the number of GLOBAL */
 	u32 imp_rst_cnt;	/* the number of IMP reset */
 	u32 reset_cnt;		/* the number of reset */
@@ -715,7 +712,7 @@
 	struct hnae3_ae_dev *ae_dev;
 	struct hclge_hw hw;
 	struct hclge_misc_vector misc_vector;
-	struct hclge_hw_stats hw_stats;
+	struct hclge_mac_stats mac_stats;
 	unsigned long state;
 	unsigned long flr_state;
 	unsigned long last_reset_time;
@@ -726,6 +723,7 @@
 	unsigned long reset_request;	/* reset has been requested */
 	unsigned long reset_pending;	/* client rst is pending to be served */
 	struct hclge_rst_stats rst_stats;
+	struct semaphore reset_sem;	/* protect reset process */
 	u32 fw_version;
 	u16 num_vmdq_vport;		/* Num vmdq vport this PF has set up */
 	u16 num_tqps;			/* Num task queue pairs of this PF */
@@ -777,8 +775,6 @@
 	unsigned long service_timer_previous;
 	struct timer_list reset_timer;
 	struct delayed_work service_task;
-	struct work_struct rst_service_task;
-	struct work_struct mbx_service_task;
 
 	bool cur_promisc;
 	int num_alloc_vfs;	/* Actual number of VFs allocated */
@@ -814,7 +810,8 @@
 	struct hlist_head fd_rule_list;
 	spinlock_t fd_rule_lock; /* protect fd_rule_list and fd_bmap */
 	u16 hclge_fd_rule_num;
-	u16 fd_arfs_expire_timer;
+	unsigned long serv_processed_cnt;
+	unsigned long last_serv_processed;
 	unsigned long fd_bmap[BITS_TO_LONGS(MAX_FD_FILTER_NUM)];
 	enum HCLGE_FD_ACTIVE_RULE_TYPE fd_active_type;
 	u8 fd_en;
@@ -828,8 +825,6 @@
 	u16 share_umv_size;
 	struct mutex umv_mutex; /* protect share_umv_size */
 
-	struct mutex vport_cfg_mutex;   /* Protect stored vf table */
-
 	DECLARE_KFIFO(mac_tnl_log, struct hclge_mac_tnl_stats,
 		      HCLGE_MAC_TNL_LOG_SIZE);
 
@@ -886,6 +881,15 @@
 	struct hclge_vlan_info vlan_info;
 };
 
+struct hclge_vf_info {
+	int link_state;
+	u8 mac[ETH_ALEN];
+	u32 spoofchk;
+	u32 max_tx_rate;
+	u32 trusted;
+	u16 promisc_enable;
+};
+
 struct hclge_vport {
 	u16 alloc_tqps;	/* Allocated Tx/Rx queues */
 
@@ -917,15 +921,15 @@
 	unsigned long state;
 	unsigned long last_active_jiffies;
 	u32 mps; /* Max packet size */
+	struct hclge_vf_info vf_info;
 
 	struct list_head uc_mac_list;   /* Store VF unicast table */
 	struct list_head mc_mac_list;   /* Store VF multicast table */
 	struct list_head vlan_list;     /* Store VF vlan table */
 };
 
-void hclge_promisc_param_init(struct hclge_promisc_param *param, bool en_uc,
-			      bool en_mc, bool en_bc, int vport_id);
-
+int hclge_set_vport_promisc_mode(struct hclge_vport *vport, bool en_uc_pmc,
+				 bool en_mc_pmc, bool en_bc_pmc);
 int hclge_add_uc_addr_common(struct hclge_vport *vport,
 			     const unsigned char *addr);
 int hclge_rm_uc_addr_common(struct hclge_vport *vport,
@@ -994,4 +998,6 @@
 				struct hclge_desc *desc);
 void hclge_report_hw_error(struct hclge_dev *hdev,
 			   enum hnae3_hw_error_type type);
+void hclge_inform_vf_promisc_info(struct hclge_vport *vport);
+void hclge_dbg_dump_rst_info(struct hclge_dev *hdev);
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
@@ -26,7 +26,7 @@
 
 	if (resp_data_len > HCLGE_MBX_MAX_RESP_DATA_SIZE) {
 		dev_err(&hdev->pdev->dev,
-			"PF fail to gen resp to VF len %d exceeds max len %d\n",
+			"PF fail to gen resp to VF len %u exceeds max len %u\n",
 			resp_data_len,
 			HCLGE_MBX_MAX_RESP_DATA_SIZE);
 		/* If resp_data_len is too long, set the value to max length
@@ -64,6 +64,13 @@
 	enum hclge_cmd_status status;
 	struct hclge_desc desc;
 
+	if (msg_len > HCLGE_MBX_MAX_MSG_SIZE) {
+		dev_err(&hdev->pdev->dev,
+			"msg data length(=%u) exceeds maximum(=%u)\n",
+			msg_len, HCLGE_MBX_MAX_MSG_SIZE);
+		return -EMSGSIZE;
+	}
+
 	resp_pf_to_vf = (struct hclge_mbx_pf_to_vf_cmd *)desc.data;
 
 	hclge_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_MBX_PF_TO_VF, false);
@@ -86,10 +93,12 @@
 int hclge_inform_reset_assert_to_vf(struct hclge_vport *vport)
 {
 	struct hclge_dev *hdev = vport->back;
-	enum hnae3_reset_type reset_type;
+	u16 reset_type;
 	u8 msg_data[2];
 	u8 dest_vfid;
 
+	BUILD_BUG_ON(HNAE3_MAX_RESET > U16_MAX);
+
 	dest_vfid = (u8)vport->vport_id;
 
 	if (hdev->reset_type == HNAE3_FUNC_RESET)
@@ -205,12 +214,38 @@
 static int hclge_set_vf_promisc_mode(struct hclge_vport *vport,
 				     struct hclge_mbx_vf_to_pf_cmd *req)
 {
-	bool en_bc = req->msg[1] ? true : false;
-	struct hclge_promisc_param param;
+#define HCLGE_MBX_BC_INDEX	1
+#define HCLGE_MBX_UC_INDEX	2
+#define HCLGE_MBX_MC_INDEX	3
+
+	bool en_bc = req->msg[HCLGE_MBX_BC_INDEX] ? true : false;
+	bool en_uc = req->msg[HCLGE_MBX_UC_INDEX] ? true : false;
+	bool en_mc = req->msg[HCLGE_MBX_MC_INDEX] ? true : false;
+	int ret;
+
+	if (!vport->vf_info.trusted) {
+		en_uc = false;
+		en_mc = false;
+	}
+
+	ret = hclge_set_vport_promisc_mode(vport, en_uc, en_mc, en_bc);
+	if (req->mbx_need_resp)
+		hclge_gen_resp_to_vf(vport, req, ret, NULL, 0);
+
+	vport->vf_info.promisc_enable = (en_uc || en_mc) ? 1 : 0;
+
+	return ret;
+}
+
+void hclge_inform_vf_promisc_info(struct hclge_vport *vport)
+{
+	u8 dest_vfid = (u8)vport->vport_id;
+	u8 msg_data[2];
 
-	/* vf is not allowed to enable unicast/multicast broadcast */
-	hclge_promisc_param_init(&param, false, false, en_bc, vport->vport_id);
-	return hclge_cmd_set_promisc_mode(vport->back, &param);
+	memcpy(&msg_data[0], &vport->vf_info.promisc_enable, sizeof(u16));
+
+	hclge_send_mbx_msg(vport, msg_data, sizeof(msg_data),
+			   HCLGE_MBX_PUSH_PROMISC_INFO, dest_vfid);
 }
 
 static int hclge_set_vf_uc_mac_addr(struct hclge_vport *vport,
@@ -223,6 +258,20 @@
 	if (mbx_req->msg[1] == HCLGE_MBX_MAC_VLAN_UC_MODIFY) {
 		const u8 *old_addr = (const u8 *)(&mbx_req->msg[8]);
 
+		/* If VF MAC has been configured by the host then it
+		 * cannot be overridden by the MAC specified by the VM.
+		 */
+		if (!is_zero_ether_addr(vport->vf_info.mac) &&
+		    !ether_addr_equal(mac_addr, vport->vf_info.mac)) {
+			status = -EPERM;
+			goto out;
+		}
+
+		if (!is_valid_ether_addr(mac_addr)) {
+			status = -EINVAL;
+			goto out;
+		}
+
 		hclge_rm_uc_addr_common(vport, old_addr);
 		status = hclge_add_uc_addr_common(vport, mac_addr);
 		if (status) {
@@ -245,11 +294,12 @@
 						 false, HCLGE_MAC_ADDR_UC);
 	} else {
 		dev_err(&hdev->pdev->dev,
-			"failed to set unicast mac addr, unknown subcode %d\n",
+			"failed to set unicast mac addr, unknown subcode %u\n",
 			mbx_req->msg[1]);
 		return -EIO;
 	}
 
+out:
 	if (mbx_req->mbx_need_resp & HCLGE_MBX_NEED_RESP_BIT)
 		hclge_gen_resp_to_vf(vport, mbx_req, status, NULL, 0);
 
@@ -278,7 +328,7 @@
 						 false, HCLGE_MAC_ADDR_MC);
 	} else {
 		dev_err(&hdev->pdev->dev,
-			"failed to set mcast mac addr, unknown subcode %d\n",
+			"failed to set mcast mac addr, unknown subcode %u\n",
 			mbx_req->msg[1]);
 		return -EIO;
 	}
@@ -324,6 +374,9 @@
 		proto =  msg_cmd->proto;
 		status = hclge_set_vlan_filter(handle, cpu_to_be16(proto),
 					       vlan, is_kill);
+		if (mbx_req->mbx_need_resp)
+			return hclge_gen_resp_to_vf(vport, mbx_req, status,
+						    NULL, 0);
 	} else if (msg_cmd->subcode == HCLGE_MBX_VLAN_RX_OFF_CFG) {
 		struct hnae3_handle *handle = &vport->nic;
 		bool en = msg_cmd->is_kill ? true : false;
@@ -398,6 +451,13 @@
 				    HCLGE_TQPS_RSS_INFO_LEN);
 }
 
+static int hclge_get_vf_mac_addr(struct hclge_vport *vport,
+				 struct hclge_mbx_vf_to_pf_cmd *mbx_req)
+{
+	return hclge_gen_resp_to_vf(vport, mbx_req, 0, vport->vf_info.mac,
+				    ETH_ALEN);
+}
+
 static int hclge_get_vf_queue_depth(struct hclge_vport *vport,
 				    struct hclge_mbx_vf_to_pf_cmd *mbx_req,
 				    bool gen_resp)
@@ -428,6 +488,9 @@
 static int hclge_get_link_info(struct hclge_vport *vport,
 			       struct hclge_mbx_vf_to_pf_cmd *mbx_req)
 {
+#define HCLGE_VF_LINK_STATE_UP		1U
+#define HCLGE_VF_LINK_STATE_DOWN	0U
+
 	struct hclge_dev *hdev = vport->back;
 	u16 link_status;
 	u8 msg_data[8];
@@ -435,7 +498,19 @@
 	u16 duplex;
 
 	/* mac.link can only be 0 or 1 */
-	link_status = (u16)hdev->hw.mac.link;
+	switch (vport->vf_info.link_state) {
+	case IFLA_VF_LINK_STATE_ENABLE:
+		link_status = HCLGE_VF_LINK_STATE_UP;
+		break;
+	case IFLA_VF_LINK_STATE_DISABLE:
+		link_status = HCLGE_VF_LINK_STATE_DOWN;
+		break;
+	case IFLA_VF_LINK_STATE_AUTO:
+	default:
+		link_status = (u16)hdev->hw.mac.link;
+		break;
+	}
+
 	duplex = hdev->hw.mac.duplex;
 	memcpy(&msg_data[0], &link_status, sizeof(u16));
 	memcpy(&msg_data[2], &hdev->hw.mac.speed, sizeof(u32));
@@ -455,7 +530,7 @@
 	unsigned long advertising;
 	unsigned long supported;
 	unsigned long send_data;
-	u8 msg_data[10];
+	u8 msg_data[10] = {};
 	u8 dest_vfid;
 
 	advertising = hdev->hw.mac.advertising[0];
@@ -489,7 +564,7 @@
 	struct hclge_dev *hdev = vport->back;
 	int ret;
 
-	dev_warn(&hdev->pdev->dev, "PF received VF reset request from VF %d!",
+	dev_warn(&hdev->pdev->dev, "PF received VF reset request from VF %u!",
 		 vport->vport_id);
 
 	ret = hclge_func_reset_cmd(hdev, vport->vport_id);
@@ -524,7 +599,8 @@
 	qid_in_pf = hclge_covert_handle_qid_global(&vport->nic, queue_id);
 	memcpy(resp_data, &qid_in_pf, sizeof(qid_in_pf));
 
-	return hclge_gen_resp_to_vf(vport, mbx_req, 0, resp_data, 2);
+	return hclge_gen_resp_to_vf(vport, mbx_req, 0, resp_data,
+				    sizeof(resp_data));
 }
 
 static int hclge_get_rss_key(struct hclge_vport *vport,
@@ -568,7 +644,6 @@
 #define LINK_STATUS_OFFSET	1
 #define LINK_FAIL_CODE_OFFSET	2
 
-	clear_bit(HCLGE_STATE_SERVICE_SCHED, &hdev->state);
 	hclge_task_schedule(hdev, 0);
 
 	if (!req->msg[LINK_STATUS_OFFSET])
@@ -614,7 +689,7 @@
 		flag = le16_to_cpu(crq->desc[crq->next_to_use].flag);
 		if (unlikely(!hnae3_get_bit(flag, HCLGE_CMDQ_RX_OUTVLD_B))) {
 			dev_warn(&hdev->pdev->dev,
-				 "dropped invalid mailbox message, code = %d\n",
+				 "dropped invalid mailbox message, code = %u\n",
 				 req->msg[0]);
 
 			/* dropping/not processing this invalid message */
@@ -731,13 +806,12 @@
 			hclge_get_link_mode(vport, req);
 			break;
 		case HCLGE_MBX_GET_VF_FLR_STATUS:
-			mutex_lock(&hdev->vport_cfg_mutex);
+		case HCLGE_MBX_VF_UNINIT:
 			hclge_rm_vport_all_mac_table(vport, true,
 						     HCLGE_MAC_ADDR_UC);
 			hclge_rm_vport_all_mac_table(vport, true,
 						     HCLGE_MAC_ADDR_MC);
 			hclge_rm_vport_all_vlan_table(vport, true);
-			mutex_unlock(&hdev->vport_cfg_mutex);
 			break;
 		case HCLGE_MBX_GET_MEDIA_TYPE:
 			ret = hclge_get_vf_media_type(vport, req);
@@ -749,12 +823,19 @@
 		case HCLGE_MBX_PUSH_LINK_STATUS:
 			hclge_handle_link_change_event(hdev, req);
 			break;
+		case HCLGE_MBX_GET_MAC_ADDR:
+			ret = hclge_get_vf_mac_addr(vport, req);
+			if (ret)
+				dev_err(&hdev->pdev->dev,
+					"PF failed(%d) to get MAC for VF\n",
+					ret);
+			break;
 		case HCLGE_MBX_NCSI_ERROR:
 			hclge_handle_ncsi_error(hdev);
 			break;
 		default:
 			dev_err(&hdev->pdev->dev,
-				"un-supported mailbox message, code = %d\n",
+				"un-supported mailbox message, code = %u\n",
 				req->msg[0]);
 			break;
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
@@ -134,7 +134,7 @@
 			 "no phy device is connected to mdio bus\n");
 		return 0;
 	} else if (hdev->hw.mac.phy_addr >= PHY_MAX_ADDR) {
-		dev_err(&hdev->pdev->dev, "phy_addr(%d) is too large.\n",
+		dev_err(&hdev->pdev->dev, "phy_addr(%u) is too large.\n",
 			hdev->hw.mac.phy_addr);
 		return -EINVAL;
 	}
@@ -255,6 +255,8 @@
 	if (!phydev)
 		return;
 
+	phy_loopback(phydev, false);
+
 	phy_start(phydev);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
@@ -46,7 +46,7 @@
 #define DIVISOR_CLK		(1000 * 8)
 #define DIVISOR_IR_B_126	(126 * DIVISOR_CLK)
 
-	const u16 tick_array[HCLGE_SHAPER_LVL_CNT] = {
+	static const u16 tick_array[HCLGE_SHAPER_LVL_CNT] = {
 		6 * 256,        /* Prioriy level */
 		6 * 32,         /* Prioriy group level */
 		6 * 8,          /* Port level */
@@ -170,8 +170,8 @@
 	return hclge_cmd_send(&hdev->hw, &desc, 1);
 }
 
-static int hclge_pfc_pause_en_cfg(struct hclge_dev *hdev, u8 tx_rx_bitmap,
-				  u8 pfc_bitmap)
+int hclge_pfc_pause_en_cfg(struct hclge_dev *hdev, u8 tx_rx_bitmap,
+			   u8 pfc_bitmap)
 {
 	struct hclge_desc desc;
 	struct hclge_pfc_en_cmd *pfc = (struct hclge_pfc_en_cmd *)desc.data;
@@ -511,6 +511,49 @@
 	return hclge_cmd_send(&hdev->hw, &desc, 1);
 }
 
+int hclge_tm_qs_shaper_cfg(struct hclge_vport *vport, int max_tx_rate)
+{
+	struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo;
+	struct hclge_qs_shapping_cmd *shap_cfg_cmd;
+	struct hclge_dev *hdev = vport->back;
+	struct hclge_desc desc;
+	u8 ir_b, ir_u, ir_s;
+	u32 shaper_para;
+	int ret, i;
+
+	if (!max_tx_rate)
+		max_tx_rate = HCLGE_ETHER_MAX_RATE;
+
+	ret = hclge_shaper_para_calc(max_tx_rate, HCLGE_SHAPER_LVL_QSET,
+				     &ir_b, &ir_u, &ir_s);
+	if (ret)
+		return ret;
+
+	shaper_para = hclge_tm_get_shapping_para(ir_b, ir_u, ir_s,
+						 HCLGE_SHAPER_BS_U_DEF,
+						 HCLGE_SHAPER_BS_S_DEF);
+
+	for (i = 0; i < kinfo->num_tc; i++) {
+		hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QCN_SHAPPING_CFG,
+					   false);
+
+		shap_cfg_cmd = (struct hclge_qs_shapping_cmd *)desc.data;
+		shap_cfg_cmd->qs_id = cpu_to_le16(vport->qs_offset + i);
+		shap_cfg_cmd->qs_shapping_para = cpu_to_le32(shaper_para);
+
+		ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+		if (ret) {
+			dev_err(&hdev->pdev->dev,
+				"vf%u, qs%u failed to set tx_rate:%d, ret=%d\n",
+				vport->vport_id, shap_cfg_cmd->qs_id,
+				max_tx_rate, ret);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
 static void hclge_tm_vport_tc_info_update(struct hclge_vport *vport)
 {
 	struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo;
@@ -523,7 +566,7 @@
 	 */
 	kinfo->num_tc = vport->vport_id ? 1 :
 			min_t(u16, vport->alloc_tqps, hdev->tm_info.num_tc);
-	vport->qs_offset = (vport->vport_id ? hdev->tm_info.num_tc : 0) +
+	vport->qs_offset = (vport->vport_id ? HNAE3_MAX_TC : 0) +
 				(vport->vport_id ? (vport->vport_id - 1) : 0);
 
 	max_rss_size = min_t(u16, hdev->rss_size_max,
@@ -532,7 +575,7 @@
 	/* Set to user value, no larger than max_rss_size. */
 	if (kinfo->req_rss_size != kinfo->rss_size && kinfo->req_rss_size &&
 	    kinfo->req_rss_size <= max_rss_size) {
-		dev_info(&hdev->pdev->dev, "rss changes from %d to %d\n",
+		dev_info(&hdev->pdev->dev, "rss changes from %u to %u\n",
 			 kinfo->rss_size, kinfo->req_rss_size);
 		kinfo->rss_size = kinfo->req_rss_size;
 	} else if (kinfo->rss_size > max_rss_size ||
@@ -633,6 +676,8 @@
 		hdev->tm_info.pg_info[i].tc_bit_map = hdev->hw_tc_map;
 		for (k = 0; k < hdev->tm_info.num_tc; k++)
 			hdev->tm_info.pg_info[i].tc_dwrr[k] = BW_PERCENT;
+		for (; k < HNAE3_MAX_TC; k++)
+			hdev->tm_info.pg_info[i].tc_dwrr[k] = 0;
 	}
 }
 
@@ -972,7 +1017,6 @@
 
 static int hclge_tm_ets_tc_dwrr_cfg(struct hclge_dev *hdev)
 {
-#define DEFAULT_TC_WEIGHT	1
 #define DEFAULT_TC_OFFSET	14
 
 	struct hclge_ets_tc_weight_cmd *ets_weight;
@@ -985,13 +1029,7 @@
 	for (i = 0; i < HNAE3_MAX_TC; i++) {
 		struct hclge_pg_info *pg_info;
 
-		ets_weight->tc_weight[i] = DEFAULT_TC_WEIGHT;
-
-		if (!(hdev->hw_tc_map & BIT(i)))
-			continue;
-
-		pg_info =
-			&hdev->tm_info.pg_info[hdev->tm_info.tc_info[i].pgid];
+		pg_info = &hdev->tm_info.pg_info[hdev->tm_info.tc_info[i].pgid];
 		ets_weight->tc_weight[i] = pg_info->tc_dwrr[i];
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h
@@ -96,6 +96,12 @@
 	__le32 pg_shapping_para;
 };
 
+struct hclge_qs_shapping_cmd {
+	__le16 qs_id;
+	u8 rsvd[2];
+	__le32 qs_shapping_para;
+};
+
 #define HCLGE_BP_GRP_NUM		32
 #define HCLGE_BP_SUB_GRP_ID_S		0
 #define HCLGE_BP_SUB_GRP_ID_M		GENMASK(4, 0)
@@ -109,6 +115,9 @@
 	u32 rsvd1;
 };
 
+#define HCLGE_PFC_DISABLE	0
+#define HCLGE_PFC_TX_RX_DISABLE	0
+
 struct hclge_pfc_en_cmd {
 	u8 tx_rx_en_bitmap;
 	u8 pri_en_bitmap;
@@ -150,8 +159,12 @@
 void hclge_tm_pfc_info_update(struct hclge_dev *hdev);
 int hclge_tm_dwrr_cfg(struct hclge_dev *hdev);
 int hclge_tm_init_hw(struct hclge_dev *hdev, bool init);
+int hclge_pfc_pause_en_cfg(struct hclge_dev *hdev, u8 tx_rx_bitmap,
+			   u8 pfc_bitmap);
 int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx);
 int hclge_pause_addr_cfg(struct hclge_dev *hdev, const u8 *mac_addr);
 int hclge_pfc_rx_stats_get(struct hclge_dev *hdev, u64 *stats);
 int hclge_pfc_tx_stats_get(struct hclge_dev *hdev, u64 *stats);
+int hclge_tm_qs_shaper_cfg(struct hclge_vport *vport, int max_tx_rate);
+
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c
@@ -50,7 +50,7 @@
 	rmb(); /* Make sure head is ready before touch any data */
 
 	if (!hclgevf_is_valid_csq_clean_head(csq, head)) {
-		dev_warn(&hdev->pdev->dev, "wrong cmd head (%d, %d-%d)\n", head,
+		dev_warn(&hdev->pdev->dev, "wrong cmd head (%u, %d-%d)\n", head,
 			 csq->next_to_use, csq->next_to_clean);
 		dev_warn(&hdev->pdev->dev,
 			 "Disabling any further commands to IMP firmware\n");
@@ -92,9 +92,9 @@
 	u32 reg_val;
 
 	if (ring->flag == HCLGEVF_TYPE_CSQ) {
-		reg_val = (u32)ring->desc_dma_addr;
+		reg_val = lower_32_bits(ring->desc_dma_addr);
 		hclgevf_write_dev(hw, HCLGEVF_NIC_CSQ_BASEADDR_L_REG, reg_val);
-		reg_val = (u32)((ring->desc_dma_addr >> 31) >> 1);
+		reg_val = upper_32_bits(ring->desc_dma_addr);
 		hclgevf_write_dev(hw, HCLGEVF_NIC_CSQ_BASEADDR_H_REG, reg_val);
 
 		reg_val = hclgevf_read_dev(hw, HCLGEVF_NIC_CSQ_DEPTH_REG);
@@ -105,9 +105,9 @@
 		hclgevf_write_dev(hw, HCLGEVF_NIC_CSQ_HEAD_REG, 0);
 		hclgevf_write_dev(hw, HCLGEVF_NIC_CSQ_TAIL_REG, 0);
 	} else {
-		reg_val = (u32)ring->desc_dma_addr;
+		reg_val = lower_32_bits(ring->desc_dma_addr);
 		hclgevf_write_dev(hw, HCLGEVF_NIC_CRQ_BASEADDR_L_REG, reg_val);
-		reg_val = (u32)((ring->desc_dma_addr >> 31) >> 1);
+		reg_val = upper_32_bits(ring->desc_dma_addr);
 		hclgevf_write_dev(hw, HCLGEVF_NIC_CRQ_BASEADDR_H_REG, reg_val);
 
 		reg_val = (ring->desc_num >> HCLGEVF_NIC_CMQ_DESC_NUM_S);
@@ -443,7 +443,7 @@
 {
 	spin_lock_bh(&hdev->hw.cmq.csq.lock);
 	spin_lock(&hdev->hw.cmq.crq.lock);
-	clear_bit(HCLGEVF_STATE_CMD_DISABLE, &hdev->state);
+	set_bit(HCLGEVF_STATE_CMD_DISABLE, &hdev->state);
 	hclgevf_cmd_uninit_regs(&hdev->hw);
 	spin_unlock(&hdev->hw.cmq.crq.lock);
 	spin_unlock_bh(&hdev->hw.cmq.csq.lock);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
@@ -16,6 +16,8 @@
 static int hclgevf_reset_hdev(struct hclgevf_dev *hdev);
 static struct hnae3_ae_algo ae_algovf;
 
+static struct workqueue_struct *hclgevf_wq;
+
 static const struct pci_device_id ae_algovf_pci_tbl[] = {
 	{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_100G_VF), 0},
 	{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_100G_RDMA_DCB_PFC_VF), 0},
@@ -440,6 +442,9 @@
 	struct hnae3_client *rclient;
 	struct hnae3_client *client;
 
+	if (test_and_set_bit(HCLGEVF_STATE_LINK_UPDATING, &hdev->state))
+		return;
+
 	client = handle->client;
 	rclient = hdev->roce_client;
 
@@ -452,6 +457,8 @@
 			rclient->ops->link_status_change(rhandle, !!link_state);
 		hdev->hw.mac.link = link_state;
 	}
+
+	clear_bit(HCLGEVF_STATE_LINK_UPDATING, &hdev->state);
 }
 
 static void hclgevf_update_link_mode(struct hclgevf_dev *hdev)
@@ -644,9 +651,9 @@
 	roundup_size = ilog2(roundup_size);
 
 	for (i = 0; i < HCLGEVF_MAX_TC_NUM; i++) {
-		tc_valid[i] = !!(hdev->hw_tc_map & BIT(i));
+		tc_valid[i] = 1;
 		tc_size[i] = roundup_size;
-		tc_offset[i] = rss_size * i;
+		tc_offset[i] = (hdev->hw_tc_map & BIT(i)) ? rss_size * i : 0;
 	}
 
 	hclgevf_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_RSS_TC_MODE, false);
@@ -1113,6 +1120,7 @@
 }
 
 static int hclgevf_cmd_set_promisc_mode(struct hclgevf_dev *hdev,
+					bool en_uc_pmc, bool en_mc_pmc,
 					bool en_bc_pmc)
 {
 	struct hclge_mbx_vf_to_pf_cmd *req;
@@ -1120,10 +1128,11 @@
 	int ret;
 
 	req = (struct hclge_mbx_vf_to_pf_cmd *)desc.data;
-
 	hclgevf_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_MBX_VF_TO_PF, false);
 	req->msg[0] = HCLGE_MBX_SET_PROMISC_MODE;
 	req->msg[1] = en_bc_pmc ? 1 : 0;
+	req->msg[2] = en_uc_pmc ? 1 : 0;
+	req->msg[3] = en_mc_pmc ? 1 : 0;
 
 	ret = hclgevf_cmd_send(&hdev->hw, &desc, 1);
 	if (ret)
@@ -1133,9 +1142,17 @@
 	return ret;
 }
 
-static int hclgevf_set_promisc_mode(struct hclgevf_dev *hdev, bool en_bc_pmc)
+static int hclgevf_set_promisc_mode(struct hnae3_handle *handle, bool en_uc_pmc,
+				    bool en_mc_pmc)
 {
-	return hclgevf_cmd_set_promisc_mode(hdev, en_bc_pmc);
+	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
+	struct pci_dev *pdev = hdev->pdev;
+	bool en_bc_pmc;
+
+	en_bc_pmc = pdev->revision != 0x20;
+
+	return hclgevf_cmd_set_promisc_mode(hdev, en_uc_pmc, en_mc_pmc,
+					    en_bc_pmc);
 }
 
 static int hclgevf_tqp_enable(struct hclgevf_dev *hdev, unsigned int tqp_id,
@@ -1174,11 +1191,37 @@
 	}
 }
 
+static int hclgevf_get_host_mac_addr(struct hclgevf_dev *hdev, u8 *p)
+{
+	u8 host_mac[ETH_ALEN];
+	int status;
+
+	status = hclgevf_send_mbx_msg(hdev, HCLGE_MBX_GET_MAC_ADDR, 0, NULL, 0,
+				      true, host_mac, ETH_ALEN);
+	if (status) {
+		dev_err(&hdev->pdev->dev,
+			"fail to get VF MAC from host %d", status);
+		return status;
+	}
+
+	ether_addr_copy(p, host_mac);
+
+	return 0;
+}
+
 static void hclgevf_get_mac_addr(struct hnae3_handle *handle, u8 *p)
 {
 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
+	u8 host_mac_addr[ETH_ALEN];
+
+	if (hclgevf_get_host_mac_addr(hdev, host_mac_addr))
+		return;
 
-	ether_addr_copy(p, hdev->hw.mac.mac_addr);
+	hdev->has_pf_mac = !is_zero_ether_addr(host_mac_addr);
+	if (hdev->has_pf_mac)
+		ether_addr_copy(p, host_mac_addr);
+	else
+		ether_addr_copy(p, hdev->hw.mac.mac_addr);
 }
 
 static int hclgevf_set_mac_addr(struct hnae3_handle *handle, void *p,
@@ -1273,14 +1316,13 @@
 	msg_data[0] = is_kill;
 	memcpy(&msg_data[1], &vlan_id, sizeof(vlan_id));
 	memcpy(&msg_data[3], &proto, sizeof(proto));
-	ret = hclgevf_send_mbx_msg(hdev, HCLGE_MBX_SET_VLAN,
-				   HCLGE_MBX_VLAN_FILTER, msg_data,
-				   HCLGEVF_VLAN_MBX_MSG_LEN, false, NULL, 0);
-
 	/* when remove hw vlan filter failed, record the vlan id,
 	 * and try to remove it from hw later, to be consistence
 	 * with stack.
 	 */
+	ret = hclgevf_send_mbx_msg(hdev, HCLGE_MBX_SET_VLAN,
+				   HCLGE_MBX_VLAN_FILTER, msg_data,
+				   HCLGEVF_VLAN_MBX_MSG_LEN, true, NULL, 0);
 	if (is_kill && ret)
 		set_bit(vlan_id, hdev->vlan_del_fail_bmap);
 
@@ -1368,32 +1410,6 @@
 	return ret;
 }
 
-static void hclgevf_flr_done(struct hnae3_ae_dev *ae_dev)
-{
-	struct hclgevf_dev *hdev = ae_dev->priv;
-
-	set_bit(HNAE3_FLR_DONE, &hdev->flr_state);
-}
-
-static int hclgevf_flr_poll_timeout(struct hclgevf_dev *hdev,
-				    unsigned long delay_us,
-				    unsigned long wait_cnt)
-{
-	unsigned long cnt = 0;
-
-	while (!test_bit(HNAE3_FLR_DONE, &hdev->flr_state) &&
-	       cnt++ < wait_cnt)
-		usleep_range(delay_us, delay_us * 2);
-
-	if (!test_bit(HNAE3_FLR_DONE, &hdev->flr_state)) {
-		dev_err(&hdev->pdev->dev,
-			"flr wait timeout\n");
-		return -ETIMEDOUT;
-	}
-
-	return 0;
-}
-
 static int hclgevf_reset_wait(struct hclgevf_dev *hdev)
 {
 #define HCLGEVF_RESET_WAIT_US	20000
@@ -1404,11 +1420,7 @@
 	u32 val;
 	int ret;
 
-	if (hdev->reset_type == HNAE3_FLR_RESET)
-		return hclgevf_flr_poll_timeout(hdev,
-						HCLGEVF_RESET_WAIT_US,
-						HCLGEVF_RESET_WAIT_CNT);
-	else if (hdev->reset_type == HNAE3_VF_RESET)
+	if (hdev->reset_type == HNAE3_VF_RESET)
 		ret = readl_poll_timeout(hdev->hw.io_base +
 					 HCLGEVF_VF_RST_ING, val,
 					 !(val & HCLGEVF_VF_RST_ING_BIT),
@@ -1432,7 +1444,10 @@
 	 * might happen in case reset assertion was made by PF. Yes, this also
 	 * means we might end up waiting bit more even for VF reset.
 	 */
-	msleep(5000);
+	if (hdev->reset_type == HNAE3_VF_FULL_RESET)
+		msleep(5000);
+	else
+		msleep(500);
 
 	return 0;
 }
@@ -1480,7 +1495,8 @@
 	/* clear handshake status with IMP */
 	hclgevf_reset_handshake(hdev, false);
 
-	return 0;
+	/* bring up the nic to enable TX/RX again */
+	return hclgevf_notify_client(hdev, HNAE3_UP_CLIENT);
 }
 
 static int hclgevf_reset_prepare_wait(struct hclgevf_dev *hdev)
@@ -1489,18 +1505,10 @@
 
 	int ret = 0;
 
-	switch (hdev->reset_type) {
-	case HNAE3_VF_FUNC_RESET:
+	if (hdev->reset_type == HNAE3_VF_FUNC_RESET) {
 		ret = hclgevf_send_mbx_msg(hdev, HCLGE_MBX_RESET, 0, NULL,
 					   0, true, NULL, sizeof(u8));
 		hdev->rst_stats.vf_func_rst_cnt++;
-		break;
-	case HNAE3_FLR_RESET:
-		set_bit(HNAE3_FLR_DOWN, &hdev->flr_state);
-		hdev->rst_stats.flr_rst_cnt++;
-		break;
-	default:
-		break;
 	}
 
 	set_bit(HCLGEVF_STATE_CMD_DISABLE, &hdev->state);
@@ -1513,12 +1521,39 @@
 	return ret;
 }
 
+static void hclgevf_dump_rst_info(struct hclgevf_dev *hdev)
+{
+	dev_info(&hdev->pdev->dev, "VF function reset count: %u\n",
+		 hdev->rst_stats.vf_func_rst_cnt);
+	dev_info(&hdev->pdev->dev, "FLR reset count: %u\n",
+		 hdev->rst_stats.flr_rst_cnt);
+	dev_info(&hdev->pdev->dev, "VF reset count: %u\n",
+		 hdev->rst_stats.vf_rst_cnt);
+	dev_info(&hdev->pdev->dev, "reset done count: %u\n",
+		 hdev->rst_stats.rst_done_cnt);
+	dev_info(&hdev->pdev->dev, "HW reset done count: %u\n",
+		 hdev->rst_stats.hw_rst_done_cnt);
+	dev_info(&hdev->pdev->dev, "reset count: %u\n",
+		 hdev->rst_stats.rst_cnt);
+	dev_info(&hdev->pdev->dev, "reset fail count: %u\n",
+		 hdev->rst_stats.rst_fail_cnt);
+	dev_info(&hdev->pdev->dev, "vector0 interrupt enable status: 0x%x\n",
+		 hclgevf_read_dev(&hdev->hw, HCLGEVF_MISC_VECTOR_REG_BASE));
+	dev_info(&hdev->pdev->dev, "vector0 interrupt status: 0x%x\n",
+		 hclgevf_read_dev(&hdev->hw, HCLGEVF_VECTOR0_CMDQ_STAT_REG));
+	dev_info(&hdev->pdev->dev, "handshake status: 0x%x\n",
+		 hclgevf_read_dev(&hdev->hw, HCLGEVF_CMDQ_TX_DEPTH_REG));
+	dev_info(&hdev->pdev->dev, "function reset status: 0x%x\n",
+		 hclgevf_read_dev(&hdev->hw, HCLGEVF_RST_ING));
+	dev_info(&hdev->pdev->dev, "hdev state: 0x%lx\n", hdev->state);
+}
+
 static void hclgevf_reset_err_handle(struct hclgevf_dev *hdev)
 {
 	/* recover handshake status with IMP when reset fail */
 	hclgevf_reset_handshake(hdev, true);
 	hdev->rst_stats.rst_fail_cnt++;
-	dev_err(&hdev->pdev->dev, "failed to reset VF(%d)\n",
+	dev_err(&hdev->pdev->dev, "failed to reset VF(%u)\n",
 		hdev->rst_stats.rst_fail_cnt);
 
 	if (hdev->rst_stats.rst_fail_cnt < HCLGEVF_RESET_MAX_FAIL_CNT)
@@ -1527,10 +1562,13 @@
 	if (hclgevf_is_reset_pending(hdev)) {
 		set_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state);
 		hclgevf_reset_task_schedule(hdev);
+	} else {
+		set_bit(HCLGEVF_STATE_RST_FAIL, &hdev->state);
+		hclgevf_dump_rst_info(hdev);
 	}
 }
 
-static int hclgevf_reset(struct hclgevf_dev *hdev)
+static int hclgevf_reset_prepare(struct hclgevf_dev *hdev)
 {
 	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev);
 	int ret;
@@ -1540,61 +1578,64 @@
 	 */
 	ae_dev->reset_type = hdev->reset_type;
 	hdev->rst_stats.rst_cnt++;
-	rtnl_lock();
 
+	rtnl_lock();
 	/* bring down the nic to stop any ongoing TX/RX */
 	ret = hclgevf_notify_client(hdev, HNAE3_DOWN_CLIENT);
-	if (ret)
-		goto err_reset_lock;
-
 	rtnl_unlock();
-
-	ret = hclgevf_reset_prepare_wait(hdev);
 	if (ret)
-		goto err_reset;
+		return ret;
 
-	/* check if VF could successfully fetch the hardware reset completion
-	 * status from the hardware
-	 */
-	ret = hclgevf_reset_wait(hdev);
-	if (ret) {
-		/* can't do much in this situation, will disable VF */
-		dev_err(&hdev->pdev->dev,
-			"VF failed(=%d) to fetch H/W reset completion status\n",
-			ret);
-		goto err_reset;
-	}
+	return hclgevf_reset_prepare_wait(hdev);
+}
+
+static int hclgevf_reset_rebuild(struct hclgevf_dev *hdev)
+{
+	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev);
+	int ret;
 
 	hdev->rst_stats.hw_rst_done_cnt++;
 
 	rtnl_lock();
-
 	/* now, re-initialize the nic client and ae device */
 	ret = hclgevf_reset_stack(hdev);
+	rtnl_unlock();
 	if (ret) {
 		dev_err(&hdev->pdev->dev, "failed to reset VF stack\n");
-		goto err_reset_lock;
+		return ret;
 	}
 
-	/* bring up the nic to enable TX/RX again */
-	ret = hclgevf_notify_client(hdev, HNAE3_UP_CLIENT);
-	if (ret)
-		goto err_reset_lock;
-
-	rtnl_unlock();
-
 	hdev->last_reset_time = jiffies;
 	ae_dev->reset_type = HNAE3_NONE_RESET;
 	hdev->rst_stats.rst_done_cnt++;
 	hdev->rst_stats.rst_fail_cnt = 0;
+	clear_bit(HCLGEVF_STATE_RST_FAIL, &hdev->state);
+
+	return 0;
+}
+
+static void hclgevf_reset(struct hclgevf_dev *hdev)
+{
+	if (hclgevf_reset_prepare(hdev))
+		goto err_reset;
+
+	/* check if VF could successfully fetch the hardware reset completion
+	 * status from the hardware
+	 */
+	if (hclgevf_reset_wait(hdev)) {
+		/* can't do much in this situation, will disable VF */
+		dev_err(&hdev->pdev->dev,
+			"failed to fetch H/W reset completion status\n");
+		goto err_reset;
+	}
+
+	if (hclgevf_reset_rebuild(hdev))
+		goto err_reset;
+
+	return;
 
-	return ret;
-err_reset_lock:
-	rtnl_unlock();
 err_reset:
 	hclgevf_reset_err_handle(hdev);
-
-	return ret;
 }
 
 static enum hnae3_reset_type hclgevf_get_reset_level(struct hclgevf_dev *hdev,
@@ -1657,25 +1698,60 @@
 	set_bit(rst_type, &hdev->default_reset_request);
 }
 
+static void hclgevf_enable_vector(struct hclgevf_misc_vector *vector, bool en)
+{
+	writel(en ? 1 : 0, vector->addr);
+}
+
 static void hclgevf_flr_prepare(struct hnae3_ae_dev *ae_dev)
 {
-#define HCLGEVF_FLR_WAIT_MS	100
-#define HCLGEVF_FLR_WAIT_CNT	50
+#define HCLGEVF_FLR_RETRY_WAIT_MS	500
+#define HCLGEVF_FLR_RETRY_CNT		5
+
 	struct hclgevf_dev *hdev = ae_dev->priv;
-	int cnt = 0;
+	int retry_cnt = 0;
+	int ret;
 
-	clear_bit(HNAE3_FLR_DOWN, &hdev->flr_state);
-	clear_bit(HNAE3_FLR_DONE, &hdev->flr_state);
-	set_bit(HNAE3_FLR_RESET, &hdev->default_reset_request);
-	hclgevf_reset_event(hdev->pdev, NULL);
+retry:
+	down(&hdev->reset_sem);
+	set_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state);
+	hdev->reset_type = HNAE3_FLR_RESET;
+	ret = hclgevf_reset_prepare(hdev);
+	if (ret) {
+		dev_err(&hdev->pdev->dev, "fail to prepare FLR, ret=%d\n",
+			ret);
+		if (hdev->reset_pending ||
+		    retry_cnt++ < HCLGEVF_FLR_RETRY_CNT) {
+			dev_err(&hdev->pdev->dev,
+				"reset_pending:0x%lx, retry_cnt:%d\n",
+				hdev->reset_pending, retry_cnt);
+			clear_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state);
+			up(&hdev->reset_sem);
+			msleep(HCLGEVF_FLR_RETRY_WAIT_MS);
+			goto retry;
+		}
+	}
 
-	while (!test_bit(HNAE3_FLR_DOWN, &hdev->flr_state) &&
-	       cnt++ < HCLGEVF_FLR_WAIT_CNT)
-		msleep(HCLGEVF_FLR_WAIT_MS);
+	/* disable misc vector before FLR done */
+	hclgevf_enable_vector(&hdev->misc_vector, false);
+	hdev->rst_stats.flr_rst_cnt++;
+}
 
-	if (!test_bit(HNAE3_FLR_DOWN, &hdev->flr_state))
-		dev_err(&hdev->pdev->dev,
-			"flr wait down timeout: %d\n", cnt);
+static void hclgevf_flr_done(struct hnae3_ae_dev *ae_dev)
+{
+	struct hclgevf_dev *hdev = ae_dev->priv;
+	int ret;
+
+	hclgevf_enable_vector(&hdev->misc_vector, true);
+
+	ret = hclgevf_reset_rebuild(hdev);
+	if (ret)
+		dev_warn(&hdev->pdev->dev, "fail to rebuild, ret=%d\n",
+			 ret);
+
+	hdev->reset_type = HNAE3_NONE_RESET;
+	clear_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state);
+	up(&hdev->reset_sem);
 }
 
 static u32 hclgevf_get_fw_version(struct hnae3_handle *handle)
@@ -1702,60 +1778,37 @@
 
 void hclgevf_reset_task_schedule(struct hclgevf_dev *hdev)
 {
-	if (!test_bit(HCLGEVF_STATE_RST_SERVICE_SCHED, &hdev->state) &&
-	    !test_bit(HCLGEVF_STATE_REMOVING, &hdev->state)) {
-		set_bit(HCLGEVF_STATE_RST_SERVICE_SCHED, &hdev->state);
-		schedule_work(&hdev->rst_service_task);
-	}
+	if (!test_bit(HCLGEVF_STATE_REMOVING, &hdev->state) &&
+	    !test_and_set_bit(HCLGEVF_STATE_RST_SERVICE_SCHED,
+			      &hdev->state))
+		mod_delayed_work(hclgevf_wq, &hdev->service_task, 0);
 }
 
 void hclgevf_mbx_task_schedule(struct hclgevf_dev *hdev)
 {
-	if (!test_bit(HCLGEVF_STATE_MBX_SERVICE_SCHED, &hdev->state) &&
-	    !test_bit(HCLGEVF_STATE_MBX_HANDLING, &hdev->state)) {
-		set_bit(HCLGEVF_STATE_MBX_SERVICE_SCHED, &hdev->state);
-		schedule_work(&hdev->mbx_service_task);
-	}
-}
-
-static void hclgevf_task_schedule(struct hclgevf_dev *hdev)
-{
-	if (!test_bit(HCLGEVF_STATE_DOWN, &hdev->state)  &&
-	    !test_and_set_bit(HCLGEVF_STATE_SERVICE_SCHED, &hdev->state))
-		schedule_work(&hdev->service_task);
-}
-
-static void hclgevf_deferred_task_schedule(struct hclgevf_dev *hdev)
-{
-	/* if we have any pending mailbox event then schedule the mbx task */
-	if (hdev->mbx_event_pending)
-		hclgevf_mbx_task_schedule(hdev);
-
-	if (test_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state))
-		hclgevf_reset_task_schedule(hdev);
+	if (!test_bit(HCLGEVF_STATE_REMOVING, &hdev->state) &&
+	    !test_and_set_bit(HCLGEVF_STATE_MBX_SERVICE_SCHED,
+			      &hdev->state))
+		mod_delayed_work(hclgevf_wq, &hdev->service_task, 0);
 }
 
-static void hclgevf_service_timer(struct timer_list *t)
+static void hclgevf_task_schedule(struct hclgevf_dev *hdev,
+				  unsigned long delay)
 {
-	struct hclgevf_dev *hdev = from_timer(hdev, t, service_timer);
-
-	mod_timer(&hdev->service_timer, jiffies +
-		  HCLGEVF_GENERAL_TASK_INTERVAL * HZ);
-
-	hdev->stats_timer++;
-	hclgevf_task_schedule(hdev);
+	if (!test_bit(HCLGEVF_STATE_REMOVING, &hdev->state) &&
+	    !test_bit(HCLGEVF_STATE_RST_FAIL, &hdev->state))
+		mod_delayed_work(hclgevf_wq, &hdev->service_task, delay);
 }
 
-static void hclgevf_reset_service_task(struct work_struct *work)
+static void hclgevf_reset_service_task(struct hclgevf_dev *hdev)
 {
-	struct hclgevf_dev *hdev =
-		container_of(work, struct hclgevf_dev, rst_service_task);
-	int ret;
+#define	HCLGEVF_MAX_RESET_ATTEMPTS_CNT	3
 
-	if (test_and_set_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state))
+	if (!test_and_clear_bit(HCLGEVF_STATE_RST_SERVICE_SCHED, &hdev->state))
 		return;
 
-	clear_bit(HCLGEVF_STATE_RST_SERVICE_SCHED, &hdev->state);
+	down(&hdev->reset_sem);
+	set_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state);
 
 	if (test_and_clear_bit(HCLGEVF_RESET_PENDING,
 			       &hdev->reset_state)) {
@@ -1769,12 +1822,8 @@
 		hdev->last_reset_time = jiffies;
 		while ((hdev->reset_type =
 			hclgevf_get_reset_level(hdev, &hdev->reset_pending))
-		       != HNAE3_NONE_RESET) {
-			ret = hclgevf_reset(hdev);
-			if (ret)
-				dev_err(&hdev->pdev->dev,
-					"VF stack reset failed %d.\n", ret);
-		}
+		       != HNAE3_NONE_RESET)
+			hclgevf_reset(hdev);
 	} else if (test_and_clear_bit(HCLGEVF_RESET_REQUESTED,
 				      &hdev->reset_state)) {
 		/* we could be here when either of below happens:
@@ -1800,7 +1849,7 @@
 		 * We cannot do much for 2. but to check first we can try reset
 		 * our PCIe + stack and see if it alleviates the problem.
 		 */
-		if (hdev->reset_attempts > 3) {
+		if (hdev->reset_attempts > HCLGEVF_MAX_RESET_ATTEMPTS_CNT) {
 			/* prepare for full reset of stack + pcie interface */
 			set_bit(HNAE3_VF_FULL_RESET, &hdev->reset_pending);
 
@@ -1815,42 +1864,29 @@
 		hclgevf_reset_task_schedule(hdev);
 	}
 
+	hdev->reset_type = HNAE3_NONE_RESET;
 	clear_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state);
+	up(&hdev->reset_sem);
 }
 
-static void hclgevf_mailbox_service_task(struct work_struct *work)
+static void hclgevf_mailbox_service_task(struct hclgevf_dev *hdev)
 {
-	struct hclgevf_dev *hdev;
-
-	hdev = container_of(work, struct hclgevf_dev, mbx_service_task);
+	if (!test_and_clear_bit(HCLGEVF_STATE_MBX_SERVICE_SCHED, &hdev->state))
+		return;
 
 	if (test_and_set_bit(HCLGEVF_STATE_MBX_HANDLING, &hdev->state))
 		return;
 
-	clear_bit(HCLGEVF_STATE_MBX_SERVICE_SCHED, &hdev->state);
-
 	hclgevf_mbx_async_handler(hdev);
 
 	clear_bit(HCLGEVF_STATE_MBX_HANDLING, &hdev->state);
 }
 
-static void hclgevf_keep_alive_timer(struct timer_list *t)
+static void hclgevf_keep_alive(struct hclgevf_dev *hdev)
 {
-	struct hclgevf_dev *hdev = from_timer(hdev, t, keep_alive_timer);
-
-	schedule_work(&hdev->keep_alive_task);
-	mod_timer(&hdev->keep_alive_timer, jiffies +
-		  HCLGEVF_KEEP_ALIVE_TASK_INTERVAL * HZ);
-}
-
-static void hclgevf_keep_alive_task(struct work_struct *work)
-{
-	struct hclgevf_dev *hdev;
 	u8 respmsg;
 	int ret;
 
-	hdev = container_of(work, struct hclgevf_dev, keep_alive_task);
-
 	if (test_bit(HCLGEVF_STATE_CMD_DISABLE, &hdev->state))
 		return;
 
@@ -1861,19 +1897,32 @@
 			"VF sends keep alive cmd failed(=%d)\n", ret);
 }
 
-static void hclgevf_service_task(struct work_struct *work)
+static void hclgevf_periodic_service_task(struct hclgevf_dev *hdev)
 {
-	struct hnae3_handle *handle;
-	struct hclgevf_dev *hdev;
+	unsigned long delta = round_jiffies_relative(HZ);
+	struct hnae3_handle *handle = &hdev->nic;
 
-	hdev = container_of(work, struct hclgevf_dev, service_task);
-	handle = &hdev->nic;
+	if (time_is_after_jiffies(hdev->last_serv_processed + HZ)) {
+		delta = jiffies - hdev->last_serv_processed;
 
-	if (hdev->stats_timer >= HCLGEVF_STATS_TIMER_INTERVAL) {
-		hclgevf_tqps_update_stats(handle);
-		hdev->stats_timer = 0;
+		if (delta < round_jiffies_relative(HZ)) {
+			delta = round_jiffies_relative(HZ) - delta;
+			goto out;
+		}
+	}
+
+	hdev->serv_processed_cnt++;
+	if (!(hdev->serv_processed_cnt % HCLGEVF_KEEP_ALIVE_TASK_INTERVAL))
+		hclgevf_keep_alive(hdev);
+
+	if (test_bit(HCLGEVF_STATE_DOWN, &hdev->state)) {
+		hdev->last_serv_processed = jiffies;
+		goto out;
 	}
 
+	if (!(hdev->serv_processed_cnt % HCLGEVF_STATS_TIMER_INTERVAL))
+		hclgevf_tqps_update_stats(handle);
+
 	/* request the link status from the PF. PF would be able to tell VF
 	 * about such updates in future so we might remove this later
 	 */
@@ -1883,9 +1932,27 @@
 
 	hclgevf_sync_vlan_filter(hdev);
 
-	hclgevf_deferred_task_schedule(hdev);
+	hdev->last_serv_processed = jiffies;
 
-	clear_bit(HCLGEVF_STATE_SERVICE_SCHED, &hdev->state);
+out:
+	hclgevf_task_schedule(hdev, delta);
+}
+
+static void hclgevf_service_task(struct work_struct *work)
+{
+	struct hclgevf_dev *hdev = container_of(work, struct hclgevf_dev,
+						service_task.work);
+
+	hclgevf_reset_service_task(hdev);
+	hclgevf_mailbox_service_task(hdev);
+	hclgevf_periodic_service_task(hdev);
+
+	/* Handle reset and mbx again in case periodical task delays the
+	 * handling by calling hclgevf_task_schedule() in
+	 * hclgevf_periodic_service_task()
+	 */
+	hclgevf_reset_service_task(hdev);
+	hclgevf_mailbox_service_task(hdev);
 }
 
 static void hclgevf_clear_event_cause(struct hclgevf_dev *hdev, u32 regclr)
@@ -1938,16 +2005,14 @@
 		return HCLGEVF_VECTOR0_EVENT_MBX;
 	}
 
-	dev_dbg(&hdev->pdev->dev, "vector 0 interrupt from unknown source\n");
+	/* print other vector0 event source */
+	dev_info(&hdev->pdev->dev,
+		 "vector 0 interrupt from unknown source, cmdq_src = %#x\n",
+		 cmdq_stat_reg);
 
 	return HCLGEVF_VECTOR0_EVENT_OTHER;
 }
 
-static void hclgevf_enable_vector(struct hclgevf_misc_vector *vector, bool en)
-{
-	writel(en ? 1 : 0, vector->addr);
-}
-
 static irqreturn_t hclgevf_misc_irq_handle(int irq, void *data)
 {
 	enum hclgevf_evt_cause event_cause;
@@ -1956,6 +2021,8 @@
 
 	hclgevf_enable_vector(&hdev->misc_vector, false);
 	event_cause = hclgevf_check_evt_cause(hdev, &clearval);
+	if (event_cause != HCLGEVF_VECTOR0_EVENT_OTHER)
+		hclgevf_clear_event_cause(hdev, clearval);
 
 	switch (event_cause) {
 	case HCLGEVF_VECTOR0_EVENT_RST:
@@ -1968,10 +2035,7 @@
 		break;
 	}
 
-	if (event_cause != HCLGEVF_VECTOR0_EVENT_OTHER) {
-		hclgevf_clear_event_cause(hdev, clearval);
-		hclgevf_enable_vector(&hdev->misc_vector, true);
-	}
+	hclgevf_enable_vector(&hdev->misc_vector, true);
 
 	return IRQ_HANDLED;
 }
@@ -2103,7 +2167,6 @@
 		ret = hclgevf_set_rss_input_tuple(hdev, rss_cfg);
 		if (ret)
 			return ret;
-
 	}
 
 	/* Initialize RSS indirect table */
@@ -2119,20 +2182,45 @@
 
 static int hclgevf_init_vlan_config(struct hclgevf_dev *hdev)
 {
+	struct hnae3_handle *nic = &hdev->nic;
+	int ret;
+
+	ret = hclgevf_en_hw_strip_rxvtag(nic, true);
+	if (ret) {
+		dev_err(&hdev->pdev->dev,
+			"failed to enable rx vlan offload, ret = %d\n", ret);
+		return ret;
+	}
+
 	return hclgevf_set_vlan_filter(&hdev->nic, htons(ETH_P_8021Q), 0,
 				       false);
 }
 
+static void hclgevf_flush_link_update(struct hclgevf_dev *hdev)
+{
+#define HCLGEVF_FLUSH_LINK_TIMEOUT	100000
+
+	unsigned long last = hdev->serv_processed_cnt;
+	int i = 0;
+
+	while (test_bit(HCLGEVF_STATE_LINK_UPDATING, &hdev->state) &&
+	       i++ < HCLGEVF_FLUSH_LINK_TIMEOUT &&
+	       last == hdev->serv_processed_cnt)
+		usleep_range(1, 1);
+}
+
 static void hclgevf_set_timer_task(struct hnae3_handle *handle, bool enable)
 {
 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
 
 	if (enable) {
-		mod_timer(&hdev->service_timer, jiffies + HZ);
+		hclgevf_task_schedule(hdev, 0);
 	} else {
-		del_timer_sync(&hdev->service_timer);
-		cancel_work_sync(&hdev->service_task);
-		clear_bit(HCLGEVF_STATE_SERVICE_SCHED, &hdev->state);
+		set_bit(HCLGEVF_STATE_DOWN, &hdev->state);
+
+		/* flush memory to make sure DOWN is seen by service task */
+		smp_mb__before_atomic();
+		hclgevf_flush_link_update(hdev);
 	}
 }
 
@@ -2140,14 +2228,14 @@
 {
 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
 
+	clear_bit(HCLGEVF_STATE_DOWN, &hdev->state);
+
 	hclgevf_reset_tqp_stats(handle);
 
 	hclgevf_request_link_info(hdev);
 
 	hclgevf_update_link_mode(hdev);
 
-	clear_bit(HCLGEVF_STATE_DOWN, &hdev->state);
-
 	return 0;
 }
 
@@ -2179,16 +2267,12 @@
 
 static int hclgevf_client_start(struct hnae3_handle *handle)
 {
-	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
 	int ret;
 
 	ret = hclgevf_set_alive(handle, true);
 	if (ret)
 		return ret;
 
-	mod_timer(&hdev->keep_alive_timer, jiffies +
-		  HCLGEVF_KEEP_ALIVE_TASK_INTERVAL * HZ);
-
 	return 0;
 }
 
@@ -2201,27 +2285,18 @@
 	if (ret)
 		dev_warn(&hdev->pdev->dev,
 			 "%s failed %d\n", __func__, ret);
-
-	del_timer_sync(&hdev->keep_alive_timer);
-	cancel_work_sync(&hdev->keep_alive_task);
 }
 
 static void hclgevf_state_init(struct hclgevf_dev *hdev)
 {
-	/* setup tasks for the MBX */
-	INIT_WORK(&hdev->mbx_service_task, hclgevf_mailbox_service_task);
 	clear_bit(HCLGEVF_STATE_MBX_SERVICE_SCHED, &hdev->state);
 	clear_bit(HCLGEVF_STATE_MBX_HANDLING, &hdev->state);
+	clear_bit(HCLGEVF_STATE_RST_FAIL, &hdev->state);
 
-	/* setup tasks for service timer */
-	timer_setup(&hdev->service_timer, hclgevf_service_timer, 0);
-
-	INIT_WORK(&hdev->service_task, hclgevf_service_task);
-	clear_bit(HCLGEVF_STATE_SERVICE_SCHED, &hdev->state);
-
-	INIT_WORK(&hdev->rst_service_task, hclgevf_reset_service_task);
+	INIT_DELAYED_WORK(&hdev->service_task, hclgevf_service_task);
 
 	mutex_init(&hdev->mbx_resp.mbx_mutex);
+	sema_init(&hdev->reset_sem, 1);
 
 	/* bring the device down */
 	set_bit(HCLGEVF_STATE_DOWN, &hdev->state);
@@ -2232,18 +2307,8 @@
 	set_bit(HCLGEVF_STATE_DOWN, &hdev->state);
 	set_bit(HCLGEVF_STATE_REMOVING, &hdev->state);
 
-	if (hdev->keep_alive_timer.function)
-		del_timer_sync(&hdev->keep_alive_timer);
-	if (hdev->keep_alive_task.func)
-		cancel_work_sync(&hdev->keep_alive_task);
-	if (hdev->service_timer.function)
-		del_timer_sync(&hdev->service_timer);
-	if (hdev->service_task.func)
-		cancel_work_sync(&hdev->service_task);
-	if (hdev->mbx_service_task.func)
-		cancel_work_sync(&hdev->mbx_service_task);
-	if (hdev->rst_service_task.func)
-		cancel_work_sync(&hdev->rst_service_task);
+	if (hdev->service_task.work.func)
+		cancel_delayed_work_sync(&hdev->service_task);
 
 	mutex_destroy(&hdev->mbx_resp.mbx_mutex);
 }
@@ -2272,7 +2337,7 @@
 	}
 	if (vectors < hdev->num_msi)
 		dev_warn(&hdev->pdev->dev,
-			 "requested %d MSI/MSI-X, but allocated %d MSI/MSI-X\n",
+			 "requested %u MSI/MSI-X, but allocated %d MSI/MSI-X\n",
 			 hdev->num_msi, vectors);
 
 	hdev->num_msi = vectors;
@@ -2317,8 +2382,10 @@
 
 	hclgevf_get_misc_vector(hdev);
 
+	snprintf(hdev->misc_vector.name, HNAE3_INT_NAME_LEN, "%s-misc-%s",
+		 HCLGEVF_NAME, pci_name(hdev->pdev));
 	ret = request_irq(hdev->misc_vector.vector_irq, hclgevf_misc_irq_handle,
-			  0, "hclgevf_cmd", hdev);
+			  0, hdev->misc_vector.name, hdev);
 	if (ret) {
 		dev_err(&hdev->pdev->dev, "VF failed to request misc irq(%d)\n",
 			hdev->misc_vector.vector_irq);
@@ -2348,12 +2415,12 @@
 
 	dev_info(dev, "VF info begin:\n");
 
-	dev_info(dev, "Task queue pairs numbers: %d\n", hdev->num_tqps);
-	dev_info(dev, "Desc num per TX queue: %d\n", hdev->num_tx_desc);
-	dev_info(dev, "Desc num per RX queue: %d\n", hdev->num_rx_desc);
-	dev_info(dev, "Numbers of vports: %d\n", hdev->num_alloc_vport);
-	dev_info(dev, "HW tc map: %d\n", hdev->hw_tc_map);
-	dev_info(dev, "PF media type of this VF: %d\n",
+	dev_info(dev, "Task queue pairs numbers: %u\n", hdev->num_tqps);
+	dev_info(dev, "Desc num per TX queue: %u\n", hdev->num_tx_desc);
+	dev_info(dev, "Desc num per RX queue: %u\n", hdev->num_rx_desc);
+	dev_info(dev, "Numbers of vports: %u\n", hdev->num_alloc_vport);
+	dev_info(dev, "HW tc map: 0x%x\n", hdev->hw_tc_map);
+	dev_info(dev, "PF media type of this VF: %u\n",
 		 hdev->hw.mac.media_type);
 
 	dev_info(dev, "VF info end.\n");
@@ -2583,7 +2650,8 @@
 	struct pci_dev *pdev = hdev->pdev;
 	int ret = 0;
 
-	if (hdev->reset_type == HNAE3_VF_FULL_RESET &&
+	if ((hdev->reset_type == HNAE3_VF_FULL_RESET ||
+	     hdev->reset_type == HNAE3_FLR_RESET) &&
 	    test_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state)) {
 		hclgevf_misc_irq_uninit(hdev);
 		hclgevf_uninit_msi(hdev);
@@ -2648,12 +2716,6 @@
 		return ret;
 	}
 
-	if (pdev->revision >= 0x21) {
-		ret = hclgevf_set_promisc_mode(hdev, true);
-		if (ret)
-			return ret;
-	}
-
 	dev_info(&hdev->pdev->dev, "Reset done\n");
 
 	return 0;
@@ -2696,6 +2758,7 @@
 
 	hclgevf_state_init(hdev);
 	hdev->reset_level = HNAE3_VF_FUNC_RESET;
+	hdev->reset_type = HNAE3_NONE_RESET;
 
 	ret = hclgevf_misc_irq_init(hdev);
 	if (ret) {
@@ -2728,17 +2791,6 @@
 	if (ret)
 		goto err_config;
 
-	/* vf is not allowed to enable unicast/multicast promisc mode.
-	 * For revision 0x20, default to disable broadcast promisc mode,
-	 * firmware makes sure broadcast packets can be accepted.
-	 * For revision 0x21, default to enable broadcast promisc mode.
-	 */
-	if (pdev->revision >= 0x21) {
-		ret = hclgevf_set_promisc_mode(hdev, true);
-		if (ret)
-			goto err_config;
-	}
-
 	/* Initialize RSS for this VF */
 	ret = hclgevf_rss_init_hw(hdev);
 	if (ret) {
@@ -2758,6 +2810,8 @@
 	dev_info(&hdev->pdev->dev, "finished initializing %s driver\n",
 		 HCLGEVF_DRIVER_NAME);
 
+	hclgevf_task_schedule(hdev, round_jiffies_relative(HZ));
+
 	return 0;
 
 err_config:
@@ -2777,19 +2831,21 @@
 {
 	hclgevf_state_uninit(hdev);
 
+	hclgevf_send_mbx_msg(hdev, HCLGE_MBX_VF_UNINIT, 0, NULL, 0,
+			     false, NULL, 0);
+
 	if (test_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state)) {
 		hclgevf_misc_irq_uninit(hdev);
 		hclgevf_uninit_msi(hdev);
 	}
 
-	hclgevf_pci_uninit(hdev);
 	hclgevf_cmd_uninit(hdev);
+	hclgevf_pci_uninit(hdev);
 }
 
 static int hclgevf_init_ae_dev(struct hnae3_ae_dev *ae_dev)
 {
 	struct pci_dev *pdev = ae_dev->pdev;
-	struct hclgevf_dev *hdev;
 	int ret;
 
 	ret = hclgevf_alloc_hdev(ae_dev);
@@ -2804,10 +2860,6 @@
 		return ret;
 	}
 
-	hdev = ae_dev->priv;
-	timer_setup(&hdev->keep_alive_timer, hclgevf_keep_alive_timer, 0);
-	INIT_WORK(&hdev->keep_alive_task, hclgevf_keep_alive_task);
-
 	return 0;
 }
 
@@ -3152,6 +3204,7 @@
 	.get_global_queue_id = hclgevf_get_qid_global,
 	.set_timer_task = hclgevf_set_timer_task,
 	.get_link_mode = hclgevf_get_link_mode,
+	.set_promisc_mode = hclgevf_set_promisc_mode,
 };
 
 static struct hnae3_ae_algo ae_algovf = {
@@ -3163,6 +3216,12 @@
 {
 	pr_info("%s is initializing\n", HCLGEVF_NAME);
 
+	hclgevf_wq = alloc_workqueue("%s", WQ_MEM_RECLAIM, 0, HCLGEVF_NAME);
+	if (!hclgevf_wq) {
+		pr_err("%s: failed to create workqueue\n", HCLGEVF_NAME);
+		return -ENOMEM;
+	}
+
 	hnae3_register_ae_algo(&ae_algovf);
 
 	return 0;
@@ -3171,6 +3230,7 @@
 static void hclgevf_exit(void)
 {
 	hnae3_unregister_ae_algo(&ae_algovf);
+	destroy_workqueue(hclgevf_wq);
 }
 module_init(hclgevf_init);
 module_exit(hclgevf_exit);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h
@@ -142,16 +142,15 @@
 	HCLGEVF_STATE_REMOVING,
 	HCLGEVF_STATE_NIC_REGISTERED,
 	/* task states */
-	HCLGEVF_STATE_SERVICE_SCHED,
 	HCLGEVF_STATE_RST_SERVICE_SCHED,
 	HCLGEVF_STATE_RST_HANDLING,
 	HCLGEVF_STATE_MBX_SERVICE_SCHED,
 	HCLGEVF_STATE_MBX_HANDLING,
 	HCLGEVF_STATE_CMD_DISABLE,
+	HCLGEVF_STATE_LINK_UPDATING,
+	HCLGEVF_STATE_RST_FAIL,
 };
 
-#define HCLGEVF_MPF_ENBALE 1
-
 struct hclgevf_mac {
 	u8 media_type;
 	u8 module_type;
@@ -222,6 +221,7 @@
 struct hclgevf_misc_vector {
 	u8 __iomem *addr;
 	int vector_irq;
+	char name[HNAE3_INT_NAME_LEN];
 };
 
 struct hclgevf_rst_stats {
@@ -253,6 +253,7 @@
 	unsigned long reset_state;	/* requested, pending */
 	struct hclgevf_rst_stats rst_stats;
 	u32 reset_attempts;
+	struct semaphore reset_sem;	/* protect reset process */
 
 	u32 fw_version;
 	u16 num_tqps;		/* num task queue pairs of this PF */
@@ -266,6 +267,7 @@
 	u16 num_tx_desc;	/* desc num of per tx queue */
 	u16 num_rx_desc;	/* desc num of per rx queue */
 	u8 hw_tc_map;
+	u8 has_pf_mac;
 
 	u16 num_msi;
 	u16 num_msi_left;
@@ -284,12 +286,7 @@
 	struct hclgevf_mbx_resp_status mbx_resp; /* mailbox response */
 	struct hclgevf_mbx_arq_ring arq; /* mailbox async rx queue */
 
-	struct timer_list service_timer;
-	struct timer_list keep_alive_timer;
-	struct work_struct service_task;
-	struct work_struct keep_alive_task;
-	struct work_struct rst_service_task;
-	struct work_struct mbx_service_task;
+	struct delayed_work service_task;
 
 	struct hclgevf_tqp *htqp;
 
@@ -299,7 +296,8 @@
 	struct hnae3_client *nic_client;
 	struct hnae3_client *roce_client;
 	u32 flag;
-	u32 stats_timer;
+	unsigned long serv_processed_cnt;
+	unsigned long last_serv_processed;
 };
 
 static inline bool hclgevf_is_reset_pending(struct hclgevf_dev *hdev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c
@@ -33,7 +33,7 @@
 
 	if (resp_len > HCLGE_MBX_MAX_RESP_DATA_SIZE) {
 		dev_err(&hdev->pdev->dev,
-			"VF mbx response len(=%d) exceeds maximum(=%d)\n",
+			"VF mbx response len(=%u) exceeds maximum(=%u)\n",
 			resp_len,
 			HCLGE_MBX_MAX_RESP_DATA_SIZE);
 		return -EINVAL;
@@ -49,7 +49,7 @@
 
 	if (i >= HCLGEVF_MAX_TRY_TIMES) {
 		dev_err(&hdev->pdev->dev,
-			"VF could not get mbx(%d,%d) resp(=%d) from PF in %d tries\n",
+			"VF could not get mbx(%u,%u) resp(=%d) from PF in %d tries\n",
 			code0, code1, hdev->mbx_resp.received_resp, i);
 		return -EIO;
 	}
@@ -68,10 +68,10 @@
 
 	if (!(r_code0 == code0 && r_code1 == code1 && !mbx_resp->resp_status)) {
 		dev_err(&hdev->pdev->dev,
-			"VF could not match resp code(code0=%d,code1=%d), %d\n",
+			"VF could not match resp code(code0=%u,code1=%u), %d\n",
 			code0, code1, mbx_resp->resp_status);
 		dev_err(&hdev->pdev->dev,
-			"VF could not match resp r_code(r_code0=%d,r_code1=%d)\n",
+			"VF could not match resp r_code(r_code0=%u,r_code1=%u)\n",
 			r_code0, r_code1);
 		return -EIO;
 	}
@@ -168,7 +168,7 @@
 		flag = le16_to_cpu(crq->desc[crq->next_to_use].flag);
 		if (unlikely(!hnae3_get_bit(flag, HCLGEVF_CMDQ_RX_OUTVLD_B))) {
 			dev_warn(&hdev->pdev->dev,
-				 "dropped invalid mailbox message, code = %d\n",
+				 "dropped invalid mailbox message, code = %u\n",
 				 req->msg[0]);
 
 			/* dropping/not processing this invalid message */
@@ -187,7 +187,7 @@
 		case HCLGE_MBX_PF_VF_RESP:
 			if (resp->received_resp)
 				dev_warn(&hdev->pdev->dev,
-					 "VF mbx resp flag not clear(%d)\n",
+					 "VF mbx resp flag not clear(%u)\n",
 					 req->msg[1]);
 			resp->received_resp = true;
 
@@ -205,6 +205,7 @@
 		case HCLGE_MBX_ASSERTING_RESET:
 		case HCLGE_MBX_LINK_STAT_MODE:
 		case HCLGE_MBX_PUSH_VLAN_INFO:
+		case HCLGE_MBX_PUSH_PROMISC_INFO:
 			/* set this mbx event as pending. This is required as we
 			 * might loose interrupt event when mbx task is busy
 			 * handling. This shall be cleared when mbx task just
@@ -218,7 +219,7 @@
 			if (atomic_read(&hdev->arq.count) >=
 			    HCLGE_MBX_MAX_ARQ_MSG_NUM) {
 				dev_warn(&hdev->pdev->dev,
-					 "Async Q full, dropping msg(%d)\n",
+					 "Async Q full, dropping msg(%u)\n",
 					 req->msg[1]);
 				break;
 			}
@@ -235,7 +236,7 @@
 			break;
 		default:
 			dev_err(&hdev->pdev->dev,
-				"VF received unsupported(%d) mbx msg from PF\n",
+				"VF received unsupported(%u) mbx msg from PF\n",
 				req->msg[0]);
 			break;
 		}
@@ -248,6 +249,14 @@
 			  crq->next_to_use);
 }
 
+static void hclgevf_parse_promisc_info(struct hclgevf_dev *hdev,
+				       u16 promisc_info)
+{
+	if (!promisc_info)
+		dev_info(&hdev->pdev->dev,
+			 "Promisc mode is closed by host for being untrusted.\n");
+}
+
 void hclgevf_mbx_async_handler(struct hclgevf_dev *hdev)
 {
 	enum hnae3_reset_type reset_type;
@@ -313,9 +322,12 @@
 			hclgevf_update_port_base_vlan_info(hdev, state,
 							   (u8 *)vlan_info, 8);
 			break;
+		case HCLGE_MBX_PUSH_PROMISC_INFO:
+			hclgevf_parse_promisc_info(hdev, msg_q[1]);
+			break;
 		default:
 			dev_err(&hdev->pdev->dev,
-				"fetched unsupported(%d) message from arq\n",
+				"fetched unsupported(%u) message from arq\n",
 				msg_q[0]);
 			break;
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/hisilicon/hns_mdio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/hisilicon/hns_mdio.c
@@ -498,6 +498,7 @@
 						MDIO_SC_RESET_ST;
 				}
 			}
+			of_node_put(reg_args.np);
 		} else {
 			dev_warn(&pdev->dev, "find syscon ret = %#x\n", ret);
 			mdio_dev->subctrl_vbase = NULL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c
@@ -389,7 +389,8 @@
 
 	spin_unlock_bh(&cmdq->cmdq_lock);
 
-	if (!wait_for_completion_timeout(&done, CMDQ_TIMEOUT)) {
+	if (!wait_for_completion_timeout(&done,
+					 msecs_to_jiffies(CMDQ_TIMEOUT))) {
 		spin_lock_bh(&cmdq->cmdq_lock);
 
 		if (cmdq->errcode[curr_prod_idx] == &errcode)
@@ -623,6 +624,8 @@
 	if (!CMDQ_WQE_COMPLETED(be32_to_cpu(ctrl->ctrl_info)))
 		return -EBUSY;
 
+	dma_rmb();
+
 	errcode = CMDQ_WQE_ERRCODE_GET(be32_to_cpu(status->status_info), VAL);
 
 	cmdq_sync_cmd_handler(cmdq, ci, errcode);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c
@@ -297,6 +297,7 @@
 	}
 
 	hw_ioctxt.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
+	hw_ioctxt.ppf_idx = HINIC_HWIF_PPF_IDX(hwif);
 
 	hw_ioctxt.set_cmdq_depth = HW_IOCTXT_SET_CMDQ_DEPTH_DEFAULT;
 	hw_ioctxt.cmdq_depth = 0;
@@ -359,50 +360,6 @@
 	return -EFAULT;
 }
 
-static int wait_for_io_stopped(struct hinic_hwdev *hwdev)
-{
-	struct hinic_cmd_io_status cmd_io_status;
-	struct hinic_hwif *hwif = hwdev->hwif;
-	struct pci_dev *pdev = hwif->pdev;
-	struct hinic_pfhwdev *pfhwdev;
-	unsigned long end;
-	u16 out_size;
-	int err;
-
-	if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
-		dev_err(&pdev->dev, "Unsupported PCI Function type\n");
-		return -EINVAL;
-	}
-
-	pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
-
-	cmd_io_status.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
-
-	end = jiffies + msecs_to_jiffies(IO_STATUS_TIMEOUT);
-	do {
-		err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM,
-					HINIC_COMM_CMD_IO_STATUS_GET,
-					&cmd_io_status, sizeof(cmd_io_status),
-					&cmd_io_status, &out_size,
-					HINIC_MGMT_MSG_SYNC);
-		if ((err) || (out_size != sizeof(cmd_io_status))) {
-			dev_err(&pdev->dev, "Failed to get IO status, ret = %d\n",
-				err);
-			return err;
-		}
-
-		if (cmd_io_status.status == IO_STOPPED) {
-			dev_info(&pdev->dev, "IO stopped\n");
-			return 0;
-		}
-
-		msleep(20);
-	} while (time_before(jiffies, end));
-
-	dev_err(&pdev->dev, "Wait for IO stopped - Timeout\n");
-	return -ETIMEDOUT;
-}
-
 /**
  * clear_io_resource - set the IO resources as not active in the NIC
  * @hwdev: the NIC HW device
@@ -422,11 +379,8 @@
 		return -EINVAL;
 	}
 
-	err = wait_for_io_stopped(hwdev);
-	if (err) {
-		dev_err(&pdev->dev, "IO has not stopped yet\n");
-		return err;
-	}
+	/* sleep 100ms to wait for firmware stopping I/O */
+	msleep(100);
 
 	cmd_clear_io_res.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h
@@ -151,8 +151,8 @@
 
 	u8      lro_en;
 	u8      rsvd3;
+	u8      ppf_idx;
 	u8      rsvd4;
-	u8      rsvd5;
 
 	u16     rq_depth;
 	u16     rx_buf_sz_idx;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c
@@ -188,7 +188,7 @@
  * eq_update_ci - update the HW cons idx of event queue
  * @eq: the event queue to update the cons idx for
  **/
-static void eq_update_ci(struct hinic_eq *eq)
+static void eq_update_ci(struct hinic_eq *eq, u32 arm_state)
 {
 	u32 val, addr = EQ_CONS_IDX_REG_ADDR(eq);
 
@@ -202,7 +202,7 @@
 
 	val |= HINIC_EQ_CI_SET(eq->cons_idx, IDX)    |
 	       HINIC_EQ_CI_SET(eq->wrapped, WRAPPED) |
-	       HINIC_EQ_CI_SET(EQ_ARMED, INT_ARMED);
+	       HINIC_EQ_CI_SET(arm_state, INT_ARMED);
 
 	val |= HINIC_EQ_CI_SET(eq_cons_idx_checksum_set(val), XOR_CHKSUM);
 
@@ -235,6 +235,8 @@
 		if (HINIC_EQ_ELEM_DESC_GET(aeqe_desc, WRAPPED) == eq->wrapped)
 			break;
 
+		dma_rmb();
+
 		event = HINIC_EQ_ELEM_DESC_GET(aeqe_desc, TYPE);
 		if (event >= HINIC_MAX_AEQ_EVENTS) {
 			dev_err(&pdev->dev, "Unknown AEQ Event %d\n", event);
@@ -347,7 +349,7 @@
 	else if (eq->type == HINIC_CEQ)
 		ceq_irq_handler(eq);
 
-	eq_update_ci(eq);
+	eq_update_ci(eq, EQ_ARMED);
 }
 
 /**
@@ -702,7 +704,7 @@
 	}
 
 	set_eq_ctrls(eq);
-	eq_update_ci(eq);
+	eq_update_ci(eq, EQ_ARMED);
 
 	err = alloc_eq_pages(eq);
 	if (err) {
@@ -752,18 +754,28 @@
  **/
 static void remove_eq(struct hinic_eq *eq)
 {
-	struct msix_entry *entry = &eq->msix_entry;
-
-	free_irq(entry->vector, eq);
+	hinic_set_msix_state(eq->hwif, eq->msix_entry.entry,
+			     HINIC_MSIX_DISABLE);
+	free_irq(eq->msix_entry.vector, eq);
 
 	if (eq->type == HINIC_AEQ) {
 		struct hinic_eq_work *aeq_work = &eq->aeq_work;
 
 		cancel_work_sync(&aeq_work->work);
+		/* clear aeq_len to avoid hw access host memory */
+		hinic_hwif_write_reg(eq->hwif,
+				     HINIC_CSR_AEQ_CTRL_1_ADDR(eq->q_id), 0);
 	} else if (eq->type == HINIC_CEQ) {
 		tasklet_kill(&eq->ceq_tasklet);
+		/* clear ceq_len to avoid hw access host memory */
+		hinic_hwif_write_reg(eq->hwif,
+				     HINIC_CSR_CEQ_CTRL_1_ADDR(eq->q_id), 0);
 	}
 
+	/* update cons_idx to avoid invalid interrupt */
+	eq->cons_idx = hinic_hwif_read_reg(eq->hwif, EQ_PROD_IDX_REG_ADDR(eq));
+	eq_update_ci(eq, EQ_NOT_ARMED);
+
 	free_eq_pages(eq);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h
@@ -137,6 +137,7 @@
 #define HINIC_HWIF_FUNC_IDX(hwif)       ((hwif)->attr.func_idx)
 #define HINIC_HWIF_PCI_INTF(hwif)       ((hwif)->attr.pci_intf_idx)
 #define HINIC_HWIF_PF_IDX(hwif)         ((hwif)->attr.pf_idx)
+#define HINIC_HWIF_PPF_IDX(hwif)        ((hwif)->attr.ppf_idx)
 
 #define HINIC_FUNC_TYPE(hwif)           ((hwif)->attr.func_type)
 #define HINIC_IS_PF(hwif)               (HINIC_FUNC_TYPE(hwif) == HINIC_PF)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/huawei/hinic/hinic_hw_mgmt.c
@@ -43,7 +43,9 @@
 
 #define MSG_NOT_RESP                    0xFFFF
 
-#define MGMT_MSG_TIMEOUT                1000
+#define MGMT_MSG_TIMEOUT                5000
+
+#define SET_FUNC_PORT_MGMT_TIMEOUT	25000
 
 #define mgmt_to_pfhwdev(pf_mgmt)        \
 		container_of(pf_mgmt, struct hinic_pfhwdev, pf_to_mgmt)
@@ -238,12 +240,13 @@
 			    u8 *buf_in, u16 in_size,
 			    u8 *buf_out, u16 *out_size,
 			    enum mgmt_direction_type direction,
-			    u16 resp_msg_id)
+			    u16 resp_msg_id, u32 timeout)
 {
 	struct hinic_hwif *hwif = pf_to_mgmt->hwif;
 	struct pci_dev *pdev = hwif->pdev;
 	struct hinic_recv_msg *recv_msg;
 	struct completion *recv_done;
+	unsigned long timeo;
 	u16 msg_id;
 	int err;
 
@@ -267,7 +270,9 @@
 		goto unlock_sync_msg;
 	}
 
-	if (!wait_for_completion_timeout(recv_done, MGMT_MSG_TIMEOUT)) {
+	timeo = msecs_to_jiffies(timeout ? timeout : MGMT_MSG_TIMEOUT);
+
+	if (!wait_for_completion_timeout(recv_done, timeo)) {
 		dev_err(&pdev->dev, "MGMT timeout, MSG id = %d\n", msg_id);
 		err = -ETIMEDOUT;
 		goto unlock_sync_msg;
@@ -341,6 +346,7 @@
 {
 	struct hinic_hwif *hwif = pf_to_mgmt->hwif;
 	struct pci_dev *pdev = hwif->pdev;
+	u32 timeout = 0;
 
 	if (sync != HINIC_MGMT_MSG_SYNC) {
 		dev_err(&pdev->dev, "Invalid MGMT msg type\n");
@@ -352,9 +358,12 @@
 		return -EINVAL;
 	}
 
+	if (cmd == HINIC_PORT_CMD_SET_FUNC_STATE)
+		timeout = SET_FUNC_PORT_MGMT_TIMEOUT;
+
 	return msg_to_mgmt_sync(pf_to_mgmt, mod, cmd, buf_in, in_size,
 				buf_out, out_size, MGMT_DIRECT_SEND,
-				MSG_NOT_RESP);
+				MSG_NOT_RESP, timeout);
 }
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h
@@ -94,6 +94,7 @@
 
 	struct hinic_wq         *wq;
 
+	struct cpumask		affinity_mask;
 	u32                     irq;
 	u16                     msix_entry;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/huawei/hinic/hinic_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/huawei/hinic/hinic_main.c
@@ -161,6 +161,7 @@
 		hinic_clean_txq(&nic_dev->txqs[j]);
 
 	devm_kfree(&netdev->dev, nic_dev->txqs);
+	nic_dev->txqs = NULL;
 	return err;
 }
 
@@ -221,6 +222,7 @@
 		hinic_clean_rxq(&nic_dev->rxqs[j]);
 
 	devm_kfree(&netdev->dev, nic_dev->rxqs);
+	nic_dev->rxqs = NULL;
 	return err;
 }
 
@@ -356,7 +358,8 @@
 	if (!num_cpus)
 		num_cpus = num_online_cpus();
 
-	nic_dev->num_qps = min_t(u16, nic_dev->max_qps, num_cpus);
+	nic_dev->num_qps = hinic_hwdev_num_qps(hwdev);
+	nic_dev->num_qps = min_t(u16, nic_dev->num_qps, num_cpus);
 
 	nic_dev->rss_limit = nic_dev->num_qps;
 	nic_dev->num_rss = nic_dev->num_qps;
@@ -482,7 +485,6 @@
 {
 	struct hinic_dev *nic_dev = netdev_priv(netdev);
 	unsigned int flags;
-	int err;
 
 	down(&nic_dev->mgmt_lock);
 
@@ -496,20 +498,9 @@
 
 	up(&nic_dev->mgmt_lock);
 
-	err = hinic_port_set_func_state(nic_dev, HINIC_FUNC_PORT_DISABLE);
-	if (err) {
-		netif_err(nic_dev, drv, netdev,
-			  "Failed to set func port state\n");
-		nic_dev->flags |= (flags & HINIC_INTF_UP);
-		return err;
-	}
+	hinic_port_set_state(nic_dev, HINIC_PORT_DISABLE);
 
-	err = hinic_port_set_state(nic_dev, HINIC_PORT_DISABLE);
-	if (err) {
-		netif_err(nic_dev, drv, netdev, "Failed to set port state\n");
-		nic_dev->flags |= (flags & HINIC_INTF_UP);
-		return err;
-	}
+	hinic_port_set_func_state(nic_dev, HINIC_FUNC_PORT_DISABLE);
 
 	if (nic_dev->flags & HINIC_RSS_ENABLE) {
 		hinic_rss_deinit(nic_dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/huawei/hinic/hinic_rx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/huawei/hinic/hinic_rx.c
@@ -350,6 +350,9 @@
 		if (!rq_wqe)
 			break;
 
+		/* make sure we read rx_done before packet length */
+		dma_rmb();
+
 		cqe = rq->cqe[ci];
 		status =  be32_to_cpu(cqe->status);
 		hinic_rq_get_sge(rxq->rq, rq_wqe, ci, &sge);
@@ -475,7 +478,6 @@
 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
 	struct hinic_rq *rq = rxq->rq;
 	struct hinic_qp *qp;
-	struct cpumask mask;
 	int err;
 
 	rx_add_napi(rxq);
@@ -492,8 +494,8 @@
 	}
 
 	qp = container_of(rq, struct hinic_qp, rq);
-	cpumask_set_cpu(qp->q_id % num_online_cpus(), &mask);
-	return irq_set_affinity_hint(rq->irq, &mask);
+	cpumask_set_cpu(qp->q_id % num_online_cpus(), &rq->affinity_mask);
+	return irq_set_affinity_hint(rq->irq, &rq->affinity_mask);
 }
 
 static void rx_free_irq(struct hinic_rxq *rxq)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/huawei/hinic/hinic_tx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/huawei/hinic/hinic_tx.c
@@ -45,7 +45,7 @@
 
 #define HW_CONS_IDX(sq)                 be16_to_cpu(*(u16 *)((sq)->hw_ci_addr))
 
-#define MIN_SKB_LEN                     17
+#define MIN_SKB_LEN			32
 
 #define	MAX_PAYLOAD_OFFSET	        221
 #define TRANSPORT_OFFSET(l4_hdr, skb)	((u32)((l4_hdr) - (skb)->data))
@@ -622,6 +622,8 @@
 	do {
 		hw_ci = HW_CONS_IDX(sq) & wq->mask;
 
+		dma_rmb();
+
 		/* Reading a WQEBB to get real WQE size and consumer index. */
 		sq_wqe = hinic_sq_read_wqebb(sq, &skb, &wqe_size, &sw_ci);
 		if ((!sq_wqe) ||
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/i825xx/82596.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/i825xx/82596.c
@@ -1155,7 +1155,7 @@
 			err = -ENODEV;
 			goto out;
 		}
-		memcpy(eth_addr, (void *) 0xfffc1f2c, ETH_ALEN);	/* YUCK! Get addr from NOVRAM */
+		memcpy(eth_addr, absolute_pointer(0xfffc1f2c), ETH_ALEN); /* YUCK! Get addr from NOVRAM */
 		dev->base_addr = MVME_I596_BASE;
 		dev->irq = (unsigned) MVME16x_IRQ_I596;
 		goto found;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/i825xx/sni_82596.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/i825xx/sni_82596.c
@@ -123,9 +123,10 @@
 	netdevice->dev_addr[5] = readb(eth_addr + 0x06);
 	iounmap(eth_addr);
 
-	if (!netdevice->irq) {
+	if (netdevice->irq < 0) {
 		printk(KERN_ERR "%s: IRQ not found for i82596 at 0x%lx\n",
 			__FILE__, netdevice->base_addr);
+		retval = netdevice->irq;
 		goto probe_failed;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/i825xx/sun3_82586.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/i825xx/sun3_82586.c
@@ -990,7 +990,7 @@
 	{
 #ifdef DEBUG
 		printk("%s: xmitter timed out, try to restart! stat: %02x\n",dev->name,p->scb->cus);
-		printk("%s: command-stats: %04x %04x\n",dev->name,swab16(p->xmit_cmds[0]->cmd_status),swab16(p->xmit_cmds[1]->cmd_status));
+		printk("%s: command-stats: %04x\n", dev->name, swab16(p->xmit_cmds[0]->cmd_status));
 		printk("%s: check, whether you set the right interrupt number!\n",dev->name);
 #endif
 		sun3_82586_close(dev);
@@ -1015,6 +1015,7 @@
 	if(skb->len > XMIT_BUFF_SIZE)
 	{
 		printk("%s: Sorry, max. framelength is %d bytes. The length of your frame is %d bytes.\n",dev->name,XMIT_BUFF_SIZE,skb->len);
+		dev_kfree_skb(skb);
 		return NETDEV_TX_OK;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/ibm/ehea/ehea_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/ibm/ehea/ehea_main.c
@@ -2617,10 +2617,8 @@
 	u16 dummy16 = 0;
 
 	cb0 = (void *)get_zeroed_page(GFP_KERNEL);
-	if (!cb0) {
-		ret = -ENOMEM;
-		goto out;
-	}
+	if (!cb0)
+		return -ENOMEM;
 
 	for (i = 0; i < (port->num_def_qps); i++) {
 		struct ehea_port_res *pr =  &port->port_res[i];
@@ -2640,6 +2638,7 @@
 					    cb0);
 		if (hret != H_SUCCESS) {
 			netdev_err(dev, "query_ehea_qp failed (1)\n");
+			ret = -EFAULT;
 			goto out;
 		}
 
@@ -2652,6 +2651,7 @@
 					     &dummy64, &dummy16, &dummy16);
 		if (hret != H_SUCCESS) {
 			netdev_err(dev, "modify_ehea_qp failed (1)\n");
+			ret = -EFAULT;
 			goto out;
 		}
 
@@ -2660,6 +2660,7 @@
 					    cb0);
 		if (hret != H_SUCCESS) {
 			netdev_err(dev, "query_ehea_qp failed (2)\n");
+			ret = -EFAULT;
 			goto out;
 		}
 
@@ -2896,6 +2897,7 @@
 	ret = of_device_register(&port->ofdev);
 	if (ret) {
 		pr_err("failed to register device. ret=%d\n", ret);
+		put_device(&port->ofdev.dev);
 		goto out;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/ibm/emac/mal.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/ibm/emac/mal.c
@@ -576,7 +576,7 @@
 		printk(KERN_ERR "%pOF: Support for 405EZ not enabled!\n",
 				ofdev->dev.of_node);
 		err = -ENODEV;
-		goto fail;
+		goto fail_unmap;
 #endif
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/ibm/ibmveth.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/ibm/ibmveth.c
@@ -196,7 +196,7 @@
 	unsigned long offset;
 
 	for (offset = 0; offset < length; offset += SMP_CACHE_BYTES)
-		asm("dcbfl %0,%1" :: "b" (addr), "r" (offset));
+		asm("dcbf %0,%1,1" :: "b" (addr), "r" (offset));
 }
 
 /* replenish the buffers for a pool.  note that we don't need to
@@ -1317,6 +1317,7 @@
 			int offset = ibmveth_rxq_frame_offset(adapter);
 			int csum_good = ibmveth_rxq_csum_good(adapter);
 			int lrg_pkt = ibmveth_rxq_large_packet(adapter);
+			__sum16 iph_check = 0;
 
 			skb = ibmveth_rxq_get_buffer(adapter);
 
@@ -1353,16 +1354,26 @@
 			skb_put(skb, length);
 			skb->protocol = eth_type_trans(skb, netdev);
 
-			if (csum_good) {
-				skb->ip_summed = CHECKSUM_UNNECESSARY;
-				ibmveth_rx_csum_helper(skb, adapter);
+			/* PHYP without PLSO support places a -1 in the ip
+			 * checksum for large send frames.
+			 */
+			if (skb->protocol == cpu_to_be16(ETH_P_IP)) {
+				struct iphdr *iph = (struct iphdr *)skb->data;
+
+				iph_check = iph->check;
 			}
 
-			if (length > netdev->mtu + ETH_HLEN) {
+			if ((length > netdev->mtu + ETH_HLEN) ||
+			    lrg_pkt || iph_check == 0xffff) {
 				ibmveth_rx_mss_helper(skb, mss, lrg_pkt);
 				adapter->rx_large_packets++;
 			}
 
+			if (csum_good) {
+				skb->ip_summed = CHECKSUM_UNNECESSARY;
+				ibmveth_rx_csum_helper(skb, adapter);
+			}
+
 			napi_gro_receive(napi, skb);	/* send it up */
 
 			netdev->stats.rx_packets++;
@@ -1682,7 +1693,7 @@
 	}
 
 	netdev->min_mtu = IBMVETH_MIN_MTU;
-	netdev->max_mtu = ETH_MAX_MTU;
+	netdev->max_mtu = ETH_MAX_MTU - IBMVETH_BUFF_OH;
 
 	memcpy(netdev->dev_addr, mac_addr_p, ETH_ALEN);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/ibm/ibmvnic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/ibm/ibmvnic.c
@@ -176,7 +176,7 @@
 	ltb->map_id = adapter->map_id;
 	adapter->map_id++;
 
-	init_completion(&adapter->fw_done);
+	reinit_completion(&adapter->fw_done);
 	rc = send_request_map(adapter, ltb->addr,
 			      ltb->size, ltb->map_id);
 	if (rc) {
@@ -202,8 +202,13 @@
 	if (!ltb->buff)
 		return;
 
+	/* VIOS automatically unmaps the long term buffer at remote
+	 * end for the following resets:
+	 * FAILOVER, MOBILITY, TIMEOUT.
+	 */
 	if (adapter->reset_reason != VNIC_RESET_FAILOVER &&
-	    adapter->reset_reason != VNIC_RESET_MOBILITY)
+	    adapter->reset_reason != VNIC_RESET_MOBILITY &&
+	    adapter->reset_reason != VNIC_RESET_TIMEOUT)
 		send_request_unmap(adapter, ltb->map_id);
 	dma_free_coherent(dev, ltb->size, ltb->buff, ltb->addr);
 }
@@ -215,7 +220,7 @@
 
 	memset(ltb->buff, 0, ltb->size);
 
-	init_completion(&adapter->fw_done);
+	reinit_completion(&adapter->fw_done);
 	rc = send_request_map(adapter, ltb->addr, ltb->size, ltb->map_id);
 	if (rc)
 		return rc;
@@ -416,6 +421,9 @@
 	int i, j, rc;
 	u64 *size_array;
 
+	if (!adapter->rx_pool)
+		return -1;
+
 	size_array = (u64 *)((u8 *)(adapter->login_rsp_buf) +
 		be32_to_cpu(adapter->login_rsp_buf->off_rxadd_buff_size));
 
@@ -586,6 +594,9 @@
 	int tx_scrqs;
 	int i, rc;
 
+	if (!adapter->tx_pool)
+		return -1;
+
 	tx_scrqs = be32_to_cpu(adapter->login_rsp_buf->num_txsubm_subcrqs);
 	for (i = 0; i < tx_scrqs; i++) {
 		rc = reset_one_tx_pool(adapter, &adapter->tso_pool[i]);
@@ -683,8 +694,11 @@
 
 	adapter->tso_pool = kcalloc(tx_subcrqs,
 				    sizeof(struct ibmvnic_tx_pool), GFP_KERNEL);
-	if (!adapter->tso_pool)
+	if (!adapter->tso_pool) {
+		kfree(adapter->tx_pool);
+		adapter->tx_pool = NULL;
 		return -1;
+	}
 
 	adapter->num_active_tx_pools = tx_subcrqs;
 
@@ -779,12 +793,13 @@
 	struct ibmvnic_adapter *adapter = netdev_priv(netdev);
 	unsigned long timeout = msecs_to_jiffies(30000);
 	int retry_count = 0;
+	int retries = 10;
 	bool retry;
 	int rc;
 
 	do {
 		retry = false;
-		if (retry_count > IBMVNIC_MAX_QUEUES) {
+		if (retry_count > retries) {
 			netdev_warn(netdev, "Login attempts exceeded\n");
 			return -1;
 		}
@@ -799,11 +814,23 @@
 
 		if (!wait_for_completion_timeout(&adapter->init_done,
 						 timeout)) {
-			netdev_warn(netdev, "Login timed out\n");
-			return -1;
+			netdev_warn(netdev, "Login timed out, retrying...\n");
+			retry = true;
+			adapter->init_done_rc = 0;
+			retry_count++;
+			continue;
 		}
 
-		if (adapter->init_done_rc == PARTIALSUCCESS) {
+		if (adapter->init_done_rc == ABORTED) {
+			netdev_warn(netdev, "Login aborted, retrying...\n");
+			retry = true;
+			adapter->init_done_rc = 0;
+			retry_count++;
+			/* FW or device may be busy, so
+			 * wait a bit before retrying login
+			 */
+			msleep(500);
+		} else if (adapter->init_done_rc == PARTIALSUCCESS) {
 			retry_count++;
 			release_sub_crqs(adapter, 1);
 
@@ -846,12 +873,22 @@
 
 static void release_login_buffer(struct ibmvnic_adapter *adapter)
 {
+	if (!adapter->login_buf)
+		return;
+
+	dma_unmap_single(&adapter->vdev->dev, adapter->login_buf_token,
+			 adapter->login_buf_sz, DMA_TO_DEVICE);
 	kfree(adapter->login_buf);
 	adapter->login_buf = NULL;
 }
 
 static void release_login_rsp_buffer(struct ibmvnic_adapter *adapter)
 {
+	if (!adapter->login_rsp_buf)
+		return;
+
+	dma_unmap_single(&adapter->vdev->dev, adapter->login_rsp_buf_token,
+			 adapter->login_rsp_buf_sz, DMA_FROM_DEVICE);
 	kfree(adapter->login_rsp_buf);
 	adapter->login_rsp_buf = NULL;
 }
@@ -943,7 +980,7 @@
 	if (adapter->vpd->buff)
 		len = adapter->vpd->len;
 
-	init_completion(&adapter->fw_done);
+	reinit_completion(&adapter->fw_done);
 	crq.get_vpd_size.first = IBMVNIC_CRQ_CMD;
 	crq.get_vpd_size.cmd = GET_VPD_SIZE;
 	rc = ibmvnic_send_crq(adapter, &crq);
@@ -1057,8 +1094,7 @@
 
 	rc = set_link_state(adapter, IBMVNIC_LOGICAL_LNK_UP);
 	if (rc) {
-		for (i = 0; i < adapter->req_rx_queues; i++)
-			napi_disable(&adapter->napi[i]);
+		ibmvnic_napi_disable(adapter);
 		release_resources(adapter);
 		return rc;
 	}
@@ -1090,18 +1126,27 @@
 	if (adapter->state != VNIC_CLOSED) {
 		rc = ibmvnic_login(netdev);
 		if (rc)
-			return rc;
+			goto out;
 
 		rc = init_resources(adapter);
 		if (rc) {
 			netdev_err(netdev, "failed to initialize resources\n");
 			release_resources(adapter);
-			return rc;
+			goto out;
 		}
 	}
 
 	rc = __ibmvnic_open(netdev);
 
+out:
+	/*
+	 * If open fails due to a pending failover, set device state and
+	 * return. Device operation will be handled by reset routine.
+	 */
+	if (rc && adapter->failover_pending) {
+		adapter->state = VNIC_OPEN;
+		rc = 0;
+	}
 	return rc;
 }
 
@@ -1226,10 +1271,8 @@
 
 	adapter->state = VNIC_CLOSING;
 	rc = set_link_state(adapter, IBMVNIC_LOGICAL_LNK_DN);
-	if (rc)
-		return rc;
 	adapter->state = VNIC_CLOSED;
-	return 0;
+	return rc;
 }
 
 static int ibmvnic_close(struct net_device *netdev)
@@ -1419,6 +1462,7 @@
 	dma_addr_t data_dma_addr;
 	struct netdev_queue *txq;
 	unsigned long lpar_rc;
+	unsigned int skblen;
 	union sub_crq tx_crq;
 	unsigned int offset;
 	int num_entries = 1;
@@ -1429,8 +1473,6 @@
 	netdev_tx_t ret = NETDEV_TX_OK;
 
 	if (test_bit(0, &adapter->resetting)) {
-		if (!netif_subqueue_stopped(netdev, skb))
-			netif_stop_subqueue(netdev, queue_num);
 		dev_kfree_skb_any(skb);
 
 		tx_send_failed++;
@@ -1492,16 +1534,32 @@
 		skb_copy_from_linear_data(skb, dst, skb->len);
 	}
 
+	/* post changes to long_term_buff *dst before VIOS accessing it */
+	dma_wmb();
+
 	tx_pool->consumer_index =
 	    (tx_pool->consumer_index + 1) % tx_pool->num_buffers;
 
 	tx_buff = &tx_pool->tx_buff[index];
+
+	/* Sanity checks on our free map to make sure it points to an index
+	 * that is not being occupied by another skb. If skb memory is
+	 * not freed then we see congestion control kick in and halt tx.
+	 */
+	if (unlikely(tx_buff->skb)) {
+		dev_warn_ratelimited(dev, "TX free map points to untracked skb (%s %d idx=%d)\n",
+				     skb_is_gso(skb) ? "tso_pool" : "tx_pool",
+				     queue_num, index);
+		dev_kfree_skb_any(tx_buff->skb);
+	}
+
 	tx_buff->skb = skb;
 	tx_buff->data_dma[0] = data_dma_addr;
 	tx_buff->data_len[0] = skb->len;
 	tx_buff->index = index;
 	tx_buff->pool_index = queue_num;
 	tx_buff->last_frag = true;
+	skblen = skb->len;
 
 	memset(&tx_crq, 0, sizeof(tx_crq));
 	tx_crq.v1.first = IBMVNIC_CRQ_CMD;
@@ -1604,7 +1662,7 @@
 	}
 
 	tx_packets++;
-	tx_bytes += skb->len;
+	tx_bytes += skblen;
 	txq->trans_start = jiffies;
 	ret = NETDEV_TX_OK;
 	goto out;
@@ -1689,7 +1747,7 @@
 	crq.change_mac_addr.cmd = CHANGE_MAC_ADDR;
 	ether_addr_copy(&crq.change_mac_addr.mac_addr[0], dev_addr);
 
-	init_completion(&adapter->fw_done);
+	reinit_completion(&adapter->fw_done);
 	rc = ibmvnic_send_crq(adapter, &crq);
 	if (rc) {
 		rc = -EIO;
@@ -1716,6 +1774,9 @@
 	int rc;
 
 	rc = 0;
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EADDRNOTAVAIL;
+
 	ether_addr_copy(adapter->mac_addr, addr->sa_data);
 	if (adapter->state != VNIC_PROBED)
 		rc = __ibmvnic_set_mac(netdev, addr->sa_data);
@@ -1813,12 +1874,19 @@
 	u64 old_num_rx_queues, old_num_tx_queues;
 	u64 old_num_rx_slots, old_num_tx_slots;
 	struct net_device *netdev = adapter->netdev;
-	int i, rc;
+	int rc;
 
 	netdev_dbg(adapter->netdev, "Re-setting driver (%d)\n",
 		   rwi->reset_reason);
 
 	rtnl_lock();
+	/*
+	 * Now that we have the rtnl lock, clear any pending failover.
+	 * This will ensure ibmvnic_open() has either completed or will
+	 * block until failover is complete.
+	 */
+	if (rwi->reset_reason == VNIC_RESET_FAILOVER)
+		adapter->failover_pending = false;
 
 	netif_carrier_off(netdev);
 	adapter->reset_reason = rwi->reset_reason;
@@ -1865,13 +1933,18 @@
 			release_sub_crqs(adapter, 1);
 		} else {
 			rc = ibmvnic_reset_crq(adapter);
-			if (!rc)
+			if (rc == H_CLOSED || rc == H_SUCCESS) {
 				rc = vio_enable_interrupts(adapter->vdev);
+				if (rc)
+					netdev_err(adapter->netdev,
+						   "Reset failed to enable interrupts. rc=%d\n",
+						   rc);
+			}
 		}
 
 		if (rc) {
 			netdev_err(adapter->netdev,
-				   "Couldn't initialize crq. rc=%d\n", rc);
+				   "Reset couldn't initialize crq. rc=%d\n", rc);
 			goto out;
 		}
 
@@ -1900,7 +1973,10 @@
 		    adapter->req_rx_add_entries_per_subcrq !=
 		    old_num_rx_slots ||
 		    adapter->req_tx_entries_per_subcrq !=
-		    old_num_tx_slots) {
+		    old_num_tx_slots ||
+		    !adapter->rx_pool ||
+		    !adapter->tso_pool ||
+		    !adapter->tx_pool) {
 			release_rx_pools(adapter);
 			release_tx_pools(adapter);
 			release_napi(adapter);
@@ -1912,12 +1988,18 @@
 
 		} else {
 			rc = reset_tx_pools(adapter);
-			if (rc)
+			if (rc) {
+				netdev_dbg(adapter->netdev, "reset tx pools failed (%d)\n",
+						rc);
 				goto out;
+			}
 
 			rc = reset_rx_pools(adapter);
-			if (rc)
+			if (rc) {
+				netdev_dbg(adapter->netdev, "reset rx pools failed (%d)\n",
+						rc);
 				goto out;
+			}
 		}
 		ibmvnic_disable_irqs(adapter);
 	}
@@ -1937,12 +2019,11 @@
 	/* refresh device's multicast list */
 	ibmvnic_set_multi(netdev);
 
-	/* kick napi */
-	for (i = 0; i < adapter->req_rx_queues; i++)
-		napi_schedule(&adapter->napi[i]);
-
-	if (adapter->reset_reason != VNIC_RESET_FAILOVER)
+	if (adapter->reset_reason == VNIC_RESET_FAILOVER ||
+	    adapter->reset_reason == VNIC_RESET_MOBILITY) {
 		call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, netdev);
+		call_netdevice_notifiers(NETDEV_RESEND_IGMP, netdev);
+	}
 
 	rc = 0;
 
@@ -2012,6 +2093,9 @@
 	if (rc)
 		return IBMVNIC_OPEN_FAILED;
 
+	call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, netdev);
+	call_netdevice_notifiers(NETDEV_RESEND_IGMP, netdev);
+
 	return 0;
 }
 
@@ -2075,6 +2159,13 @@
 			/* CHANGE_PARAM requestor holds rtnl_lock */
 			rc = do_change_param_reset(adapter, rwi, reset_state);
 		} else if (adapter->force_reset_recovery) {
+			/*
+			 * Since we are doing a hard reset now, clear the
+			 * failover_pending flag so we don't ignore any
+			 * future MOBILITY or other resets.
+			 */
+			adapter->failover_pending = false;
+
 			/* Transport event occurred during previous reset */
 			if (adapter->wait_for_reset) {
 				/* Previous was CHANGE_PARAM; caller locked */
@@ -2138,9 +2229,15 @@
 	unsigned long flags;
 	int ret;
 
+	/*
+	 * If failover is pending don't schedule any other reset.
+	 * Instead let the failover complete. If there is already a
+	 * a failover reset scheduled, we will detect and drop the
+	 * duplicate reset when walking the ->rwi_list below.
+	 */
 	if (adapter->state == VNIC_REMOVING ||
 	    adapter->state == VNIC_REMOVED ||
-	    adapter->failover_pending) {
+	    (adapter->failover_pending && reason != VNIC_RESET_FAILOVER)) {
 		ret = EBUSY;
 		netdev_dbg(netdev, "Adapter removing or pending failover, skipping reset\n");
 		goto err;
@@ -2175,8 +2272,10 @@
 	 * flush reset queue and process this reset
 	 */
 	if (adapter->force_reset_recovery && !list_empty(&adapter->rwi_list)) {
-		list_for_each_safe(entry, tmp_entry, &adapter->rwi_list)
+		list_for_each_safe(entry, tmp_entry, &adapter->rwi_list) {
 			list_del(entry);
+			kfree(list_entry(entry, struct ibmvnic_rwi, list));
+		}
 	}
 	rwi->reset_reason = reason;
 	list_add_tail(&rwi->list, &adapter->rwi_list);
@@ -2193,6 +2292,12 @@
 {
 	struct ibmvnic_adapter *adapter = netdev_priv(dev);
 
+	if (test_bit(0, &adapter->resetting)) {
+		netdev_err(adapter->netdev,
+			   "Adapter is resetting, skip timeout reset\n");
+		return;
+	}
+
 	ibmvnic_reset(adapter, VNIC_RESET_TIMEOUT);
 }
 
@@ -2234,6 +2339,12 @@
 
 		if (!pending_scrq(adapter, adapter->rx_scrq[scrq_num]))
 			break;
+		/* The queue entry at the current index is peeked at above
+		 * to determine that there is a valid descriptor awaiting
+		 * processing. We want to be sure that the current slot
+		 * holds a valid descriptor before reading its contents.
+		 */
+		dma_rmb();
 		next = ibmvnic_next_scrq(adapter, adapter->rx_scrq[scrq_num]);
 		rx_buff =
 		    (struct ibmvnic_rx_buff *)be64_to_cpu(next->
@@ -2258,6 +2369,8 @@
 		offset = be16_to_cpu(next->rx_comp.off_frame_data);
 		flags = next->rx_comp.flags;
 		skb = rx_buff->skb;
+		/* load long_term_buff before copying to skb */
+		dma_rmb();
 		skb_copy_to_linear_data(skb, rx_buff->data + offset,
 					length);
 
@@ -2316,7 +2429,7 @@
 	adapter->fallback.rx_entries = adapter->req_rx_add_entries_per_subcrq;
 	adapter->fallback.tx_entries = adapter->req_tx_entries_per_subcrq;
 
-	init_completion(&adapter->reset_done);
+	reinit_completion(&adapter->reset_done);
 	adapter->wait_for_reset = true;
 	rc = ibmvnic_reset(adapter, VNIC_RESET_CHANGE_PARAM);
 	if (rc)
@@ -2332,7 +2445,7 @@
 		adapter->desired.rx_entries = adapter->fallback.rx_entries;
 		adapter->desired.tx_entries = adapter->fallback.tx_entries;
 
-		init_completion(&adapter->reset_done);
+		reinit_completion(&adapter->reset_done);
 		adapter->wait_for_reset = true;
 		rc = ibmvnic_reset(adapter, VNIC_RESET_CHANGE_PARAM);
 		if (rc)
@@ -2603,7 +2716,7 @@
 	    cpu_to_be32(sizeof(struct ibmvnic_statistics));
 
 	/* Wait for data to be written */
-	init_completion(&adapter->stats_done);
+	reinit_completion(&adapter->stats_done);
 	rc = ibmvnic_send_crq(adapter, &crq);
 	if (rc)
 		return;
@@ -2694,6 +2807,9 @@
 {
 	int i, rc;
 
+	if (!adapter->tx_scrq || !adapter->rx_scrq)
+		return -EINVAL;
+
 	for (i = 0; i < adapter->req_tx_queues; i++) {
 		netdev_dbg(adapter->netdev, "Re-setting tx_scrq[%d]\n", i);
 		rc = reset_one_sub_crq_queue(adapter, adapter->tx_scrq[i]);
@@ -2912,13 +3028,18 @@
 		unsigned int pool = scrq->pool_index;
 		int num_entries = 0;
 
+		/* The queue entry at the current index is peeked at above
+		 * to determine that there is a valid descriptor awaiting
+		 * processing. We want to be sure that the current slot
+		 * holds a valid descriptor before reading its contents.
+		 */
+		dma_rmb();
+
 		next = ibmvnic_next_scrq(adapter, scrq);
 		for (i = 0; i < next->tx_comp.num_comps; i++) {
-			if (next->tx_comp.rcs[i]) {
+			if (next->tx_comp.rcs[i])
 				dev_err(dev, "tx error %x\n",
 					next->tx_comp.rcs[i]);
-				continue;
-			}
 			index = be32_to_cpu(next->tx_comp.correlators[i]);
 			if (index & IBMVNIC_TSO_POOL_MASK) {
 				tx_pool = &adapter->tso_pool[pool];
@@ -3067,7 +3188,7 @@
 req_tx_irq_failed:
 	for (j = 0; j < i; j++) {
 		free_irq(adapter->tx_scrq[j]->irq, adapter->tx_scrq[j]);
-		irq_dispose_mapping(adapter->rx_scrq[j]->irq);
+		irq_dispose_mapping(adapter->tx_scrq[j]->irq);
 	}
 	release_sub_crqs(adapter, 1);
 	return rc;
@@ -3163,11 +3284,25 @@
 	struct device *dev = &adapter->vdev->dev;
 	union ibmvnic_crq crq;
 	int max_entries;
+	int cap_reqs;
+
+	/* We send out 6 or 7 REQUEST_CAPABILITY CRQs below (depending on
+	 * the PROMISC flag). Initialize this count upfront. When the tasklet
+	 * receives a response to all of these, it will send the next protocol
+	 * message (QUERY_IP_OFFLOAD).
+	 */
+	if (!(adapter->netdev->flags & IFF_PROMISC) ||
+	    adapter->promisc_supported)
+		cap_reqs = 7;
+	else
+		cap_reqs = 6;
 
 	if (!retry) {
 		/* Sub-CRQ entries are 32 byte long */
 		int entries_page = 4 * PAGE_SIZE / (sizeof(u64) * 4);
 
+		atomic_set(&adapter->running_cap_crqs, cap_reqs);
+
 		if (adapter->min_tx_entries_per_subcrq > entries_page ||
 		    adapter->min_rx_add_entries_per_subcrq > entries_page) {
 			dev_err(dev, "Fatal, invalid entries per sub-crq\n");
@@ -3228,44 +3363,45 @@
 					adapter->opt_rx_comp_queues;
 
 		adapter->req_rx_add_queues = adapter->max_rx_add_queues;
+	} else {
+		atomic_add(cap_reqs, &adapter->running_cap_crqs);
 	}
-
 	memset(&crq, 0, sizeof(crq));
 	crq.request_capability.first = IBMVNIC_CRQ_CMD;
 	crq.request_capability.cmd = REQUEST_CAPABILITY;
 
 	crq.request_capability.capability = cpu_to_be16(REQ_TX_QUEUES);
 	crq.request_capability.number = cpu_to_be64(adapter->req_tx_queues);
-	atomic_inc(&adapter->running_cap_crqs);
+	cap_reqs--;
 	ibmvnic_send_crq(adapter, &crq);
 
 	crq.request_capability.capability = cpu_to_be16(REQ_RX_QUEUES);
 	crq.request_capability.number = cpu_to_be64(adapter->req_rx_queues);
-	atomic_inc(&adapter->running_cap_crqs);
+	cap_reqs--;
 	ibmvnic_send_crq(adapter, &crq);
 
 	crq.request_capability.capability = cpu_to_be16(REQ_RX_ADD_QUEUES);
 	crq.request_capability.number = cpu_to_be64(adapter->req_rx_add_queues);
-	atomic_inc(&adapter->running_cap_crqs);
+	cap_reqs--;
 	ibmvnic_send_crq(adapter, &crq);
 
 	crq.request_capability.capability =
 	    cpu_to_be16(REQ_TX_ENTRIES_PER_SUBCRQ);
 	crq.request_capability.number =
 	    cpu_to_be64(adapter->req_tx_entries_per_subcrq);
-	atomic_inc(&adapter->running_cap_crqs);
+	cap_reqs--;
 	ibmvnic_send_crq(adapter, &crq);
 
 	crq.request_capability.capability =
 	    cpu_to_be16(REQ_RX_ADD_ENTRIES_PER_SUBCRQ);
 	crq.request_capability.number =
 	    cpu_to_be64(adapter->req_rx_add_entries_per_subcrq);
-	atomic_inc(&adapter->running_cap_crqs);
+	cap_reqs--;
 	ibmvnic_send_crq(adapter, &crq);
 
 	crq.request_capability.capability = cpu_to_be16(REQ_MTU);
 	crq.request_capability.number = cpu_to_be64(adapter->req_mtu);
-	atomic_inc(&adapter->running_cap_crqs);
+	cap_reqs--;
 	ibmvnic_send_crq(adapter, &crq);
 
 	if (adapter->netdev->flags & IFF_PROMISC) {
@@ -3273,16 +3409,21 @@
 			crq.request_capability.capability =
 			    cpu_to_be16(PROMISC_REQUESTED);
 			crq.request_capability.number = cpu_to_be64(1);
-			atomic_inc(&adapter->running_cap_crqs);
+			cap_reqs--;
 			ibmvnic_send_crq(adapter, &crq);
 		}
 	} else {
 		crq.request_capability.capability =
 		    cpu_to_be16(PROMISC_REQUESTED);
 		crq.request_capability.number = cpu_to_be64(0);
-		atomic_inc(&adapter->running_cap_crqs);
+		cap_reqs--;
 		ibmvnic_send_crq(adapter, &crq);
 	}
+
+	/* Keep at end to catch any discrepancy between expected and actual
+	 * CRQs sent.
+	 */
+	WARN_ON(cap_reqs != 0);
 }
 
 static int pending_scrq(struct ibmvnic_adapter *adapter,
@@ -3312,6 +3453,11 @@
 	}
 	spin_unlock_irqrestore(&scrq->lock, flags);
 
+	/* Ensure that the entire buffer descriptor has been
+	 * loaded before reading its contents
+	 */
+	dma_rmb();
+
 	return entry;
 }
 
@@ -3682,118 +3828,132 @@
 static void send_cap_queries(struct ibmvnic_adapter *adapter)
 {
 	union ibmvnic_crq crq;
+	int cap_reqs;
+
+	/* We send out 25 QUERY_CAPABILITY CRQs below.  Initialize this count
+	 * upfront. When the tasklet receives a response to all of these, it
+	 * can send out the next protocol messaage (REQUEST_CAPABILITY).
+	 */
+	cap_reqs = 25;
+
+	atomic_set(&adapter->running_cap_crqs, cap_reqs);
 
-	atomic_set(&adapter->running_cap_crqs, 0);
 	memset(&crq, 0, sizeof(crq));
 	crq.query_capability.first = IBMVNIC_CRQ_CMD;
 	crq.query_capability.cmd = QUERY_CAPABILITY;
 
 	crq.query_capability.capability = cpu_to_be16(MIN_TX_QUEUES);
-	atomic_inc(&adapter->running_cap_crqs);
 	ibmvnic_send_crq(adapter, &crq);
+	cap_reqs--;
 
 	crq.query_capability.capability = cpu_to_be16(MIN_RX_QUEUES);
-	atomic_inc(&adapter->running_cap_crqs);
 	ibmvnic_send_crq(adapter, &crq);
+	cap_reqs--;
 
 	crq.query_capability.capability = cpu_to_be16(MIN_RX_ADD_QUEUES);
-	atomic_inc(&adapter->running_cap_crqs);
 	ibmvnic_send_crq(adapter, &crq);
+	cap_reqs--;
 
 	crq.query_capability.capability = cpu_to_be16(MAX_TX_QUEUES);
-	atomic_inc(&adapter->running_cap_crqs);
 	ibmvnic_send_crq(adapter, &crq);
+	cap_reqs--;
 
 	crq.query_capability.capability = cpu_to_be16(MAX_RX_QUEUES);
-	atomic_inc(&adapter->running_cap_crqs);
 	ibmvnic_send_crq(adapter, &crq);
+	cap_reqs--;
 
 	crq.query_capability.capability = cpu_to_be16(MAX_RX_ADD_QUEUES);
-	atomic_inc(&adapter->running_cap_crqs);
 	ibmvnic_send_crq(adapter, &crq);
+	cap_reqs--;
 
 	crq.query_capability.capability =
 	    cpu_to_be16(MIN_TX_ENTRIES_PER_SUBCRQ);
-	atomic_inc(&adapter->running_cap_crqs);
 	ibmvnic_send_crq(adapter, &crq);
+	cap_reqs--;
 
 	crq.query_capability.capability =
 	    cpu_to_be16(MIN_RX_ADD_ENTRIES_PER_SUBCRQ);
-	atomic_inc(&adapter->running_cap_crqs);
 	ibmvnic_send_crq(adapter, &crq);
+	cap_reqs--;
 
 	crq.query_capability.capability =
 	    cpu_to_be16(MAX_TX_ENTRIES_PER_SUBCRQ);
-	atomic_inc(&adapter->running_cap_crqs);
 	ibmvnic_send_crq(adapter, &crq);
+	cap_reqs--;
 
 	crq.query_capability.capability =
 	    cpu_to_be16(MAX_RX_ADD_ENTRIES_PER_SUBCRQ);
-	atomic_inc(&adapter->running_cap_crqs);
 	ibmvnic_send_crq(adapter, &crq);
+	cap_reqs--;
 
 	crq.query_capability.capability = cpu_to_be16(TCP_IP_OFFLOAD);
-	atomic_inc(&adapter->running_cap_crqs);
 	ibmvnic_send_crq(adapter, &crq);
+	cap_reqs--;
 
 	crq.query_capability.capability = cpu_to_be16(PROMISC_SUPPORTED);
-	atomic_inc(&adapter->running_cap_crqs);
 	ibmvnic_send_crq(adapter, &crq);
+	cap_reqs--;
 
 	crq.query_capability.capability = cpu_to_be16(MIN_MTU);
-	atomic_inc(&adapter->running_cap_crqs);
 	ibmvnic_send_crq(adapter, &crq);
+	cap_reqs--;
 
 	crq.query_capability.capability = cpu_to_be16(MAX_MTU);
-	atomic_inc(&adapter->running_cap_crqs);
 	ibmvnic_send_crq(adapter, &crq);
+	cap_reqs--;
 
 	crq.query_capability.capability = cpu_to_be16(MAX_MULTICAST_FILTERS);
-	atomic_inc(&adapter->running_cap_crqs);
 	ibmvnic_send_crq(adapter, &crq);
+	cap_reqs--;
 
 	crq.query_capability.capability = cpu_to_be16(VLAN_HEADER_INSERTION);
-	atomic_inc(&adapter->running_cap_crqs);
 	ibmvnic_send_crq(adapter, &crq);
+	cap_reqs--;
 
 	crq.query_capability.capability = cpu_to_be16(RX_VLAN_HEADER_INSERTION);
-	atomic_inc(&adapter->running_cap_crqs);
 	ibmvnic_send_crq(adapter, &crq);
+	cap_reqs--;
 
 	crq.query_capability.capability = cpu_to_be16(MAX_TX_SG_ENTRIES);
-	atomic_inc(&adapter->running_cap_crqs);
 	ibmvnic_send_crq(adapter, &crq);
+	cap_reqs--;
 
 	crq.query_capability.capability = cpu_to_be16(RX_SG_SUPPORTED);
-	atomic_inc(&adapter->running_cap_crqs);
 	ibmvnic_send_crq(adapter, &crq);
+	cap_reqs--;
 
 	crq.query_capability.capability = cpu_to_be16(OPT_TX_COMP_SUB_QUEUES);
-	atomic_inc(&adapter->running_cap_crqs);
 	ibmvnic_send_crq(adapter, &crq);
+	cap_reqs--;
 
 	crq.query_capability.capability = cpu_to_be16(OPT_RX_COMP_QUEUES);
-	atomic_inc(&adapter->running_cap_crqs);
 	ibmvnic_send_crq(adapter, &crq);
+	cap_reqs--;
 
 	crq.query_capability.capability =
 			cpu_to_be16(OPT_RX_BUFADD_Q_PER_RX_COMP_Q);
-	atomic_inc(&adapter->running_cap_crqs);
 	ibmvnic_send_crq(adapter, &crq);
+	cap_reqs--;
 
 	crq.query_capability.capability =
 			cpu_to_be16(OPT_TX_ENTRIES_PER_SUBCRQ);
-	atomic_inc(&adapter->running_cap_crqs);
 	ibmvnic_send_crq(adapter, &crq);
+	cap_reqs--;
 
 	crq.query_capability.capability =
 			cpu_to_be16(OPT_RXBA_ENTRIES_PER_SUBCRQ);
-	atomic_inc(&adapter->running_cap_crqs);
 	ibmvnic_send_crq(adapter, &crq);
+	cap_reqs--;
 
 	crq.query_capability.capability = cpu_to_be16(TX_RX_DESC_REQ);
-	atomic_inc(&adapter->running_cap_crqs);
+
 	ibmvnic_send_crq(adapter, &crq);
+	cap_reqs--;
+
+	/* Keep at end to catch any discrepancy between expected and actual
+	 * CRQs sent.
+	 */
+	WARN_ON(cap_reqs != 0);
 }
 
 static void handle_vpd_size_rsp(union ibmvnic_crq *crq,
@@ -4040,8 +4200,13 @@
 		dev_err(dev, "Error %ld in CHANGE_MAC_ADDR_RSP\n", rc);
 		goto out;
 	}
+	/* crq->change_mac_addr.mac_addr is the requested one
+	 * crq->change_mac_addr_rsp.mac_addr is the returned valid one.
+	 */
 	ether_addr_copy(netdev->dev_addr,
 			&crq->change_mac_addr_rsp.mac_addr[0]);
+	ether_addr_copy(adapter->mac_addr,
+			&crq->change_mac_addr_rsp.mac_addr[0]);
 out:
 	complete(&adapter->fw_done);
 	return rc;
@@ -4055,6 +4220,8 @@
 	char *name;
 
 	atomic_dec(&adapter->running_cap_crqs);
+	netdev_dbg(adapter->netdev, "Outstanding request-caps: %d\n",
+		   atomic_read(&adapter->running_cap_crqs));
 	switch (be16_to_cpu(crq->request_capability_rsp.capability)) {
 	case REQ_TX_QUEUES:
 		req_value = &adapter->req_tx_queues;
@@ -4155,11 +4322,6 @@
 	struct ibmvnic_login_buffer *login = adapter->login_buf;
 	int i;
 
-	dma_unmap_single(dev, adapter->login_buf_token, adapter->login_buf_sz,
-			 DMA_TO_DEVICE);
-	dma_unmap_single(dev, adapter->login_rsp_buf_token,
-			 adapter->login_rsp_buf_sz, DMA_FROM_DEVICE);
-
 	/* If the number of queues requested can't be allocated by the
 	 * server, the login response will return with code 1. We will need
 	 * to resend the login buffer with fewer queues requested.
@@ -4170,6 +4332,14 @@
 		return 0;
 	}
 
+	if (adapter->failover_pending) {
+		adapter->init_done_rc = -EAGAIN;
+		netdev_dbg(netdev, "Failover pending, ignoring login response\n");
+		complete(&adapter->init_done);
+		/* login response buffer will be released on reset */
+		return 0;
+	}
+
 	netdev->mtu = adapter->req_mtu - ETH_HLEN;
 
 	netdev_dbg(adapter->netdev, "Login Response Buffer:\n");
@@ -4408,7 +4578,7 @@
 	memset(&crq, 0, sizeof(crq));
 	crq.query_phys_parms.first = IBMVNIC_CRQ_CMD;
 	crq.query_phys_parms.cmd = QUERY_PHYS_PARMS;
-	init_completion(&adapter->fw_done);
+	reinit_completion(&adapter->fw_done);
 	rc = ibmvnic_send_crq(adapter, &crq);
 	if (rc)
 		return rc;
@@ -4438,7 +4608,7 @@
 	case IBMVNIC_1GBPS:
 		adapter->speed = SPEED_1000;
 		break;
-	case IBMVNIC_10GBP:
+	case IBMVNIC_10GBPS:
 		adapter->speed = SPEED_10000;
 		break;
 	case IBMVNIC_25GBPS:
@@ -4453,6 +4623,9 @@
 	case IBMVNIC_100GBPS:
 		adapter->speed = SPEED_100000;
 		break;
+	case IBMVNIC_200GBPS:
+		adapter->speed = SPEED_200000;
+		break;
 	default:
 		if (netif_carrier_ok(netdev))
 			netdev_warn(netdev, "Unknown speed 0x%08x\n", rspeed);
@@ -4486,12 +4659,26 @@
 		case IBMVNIC_CRQ_INIT:
 			dev_info(dev, "Partner initialized\n");
 			adapter->from_passive_init = true;
-			adapter->failover_pending = false;
 			if (!completion_done(&adapter->init_done)) {
 				complete(&adapter->init_done);
 				adapter->init_done_rc = -EIO;
 			}
-			ibmvnic_reset(adapter, VNIC_RESET_FAILOVER);
+			rc = ibmvnic_reset(adapter, VNIC_RESET_FAILOVER);
+			if (rc && rc != -EBUSY) {
+				/* We were unable to schedule the failover
+				 * reset either because the adapter was still
+				 * probing (eg: during kexec) or we could not
+				 * allocate memory. Clear the failover_pending
+				 * flag since no one else will. We ignore
+				 * EBUSY because it means either FAILOVER reset
+				 * is already scheduled or the adapter is
+				 * being removed.
+				 */
+				netdev_err(netdev,
+					   "Error %ld scheduling failover reset\n",
+					   rc);
+				adapter->failover_pending = false;
+			}
 			break;
 		case IBMVNIC_CRQ_INIT_COMPLETE:
 			dev_info(dev, "Partner initialization complete\n");
@@ -4535,12 +4722,10 @@
 			dev_err(dev, "Error %ld in VERSION_EXCHG_RSP\n", rc);
 			break;
 		}
-		dev_info(dev, "Partner protocol version is %d\n",
-			 crq->version_exchange_rsp.version);
-		if (be16_to_cpu(crq->version_exchange_rsp.version) <
-		    ibmvnic_version)
-			ibmvnic_version =
+		ibmvnic_version =
 			    be16_to_cpu(crq->version_exchange_rsp.version);
+		dev_info(dev, "Partner protocol version is %d\n",
+			 ibmvnic_version);
 		send_cap_queries(adapter);
 		break;
 	case QUERY_CAPABILITY_RSP:
@@ -4650,15 +4835,15 @@
 	while (!done) {
 		/* Pull all the valid messages off the CRQ */
 		while ((crq = ibmvnic_next_crq(adapter)) != NULL) {
+			/* This barrier makes sure ibmvnic_next_crq()'s
+			 * crq->generic.first & IBMVNIC_CRQ_CMD_RSP is loaded
+			 * before ibmvnic_handle_crq()'s
+			 * switch(gen_crq->first) and switch(gen_crq->cmd).
+			 */
+			dma_rmb();
 			ibmvnic_handle_crq(crq, adapter);
 			crq->generic.first = 0;
 		}
-
-		/* remain in tasklet until all
-		 * capabilities responses are received
-		 */
-		if (!adapter->wait_capability)
-			done = true;
 	}
 	/* if capabilities CRQ's were sent in this tasklet, the following
 	 * tasklet must wait until all responses are received
@@ -4696,6 +4881,9 @@
 	} while (rc == H_BUSY || H_IS_LONG_BUSY(rc));
 
 	/* Clean out the queue */
+	if (!crq->msgs)
+		return -EINVAL;
+
 	memset(crq->msgs, 0, PAGE_SIZE);
 	crq->cur = 0;
 	crq->active = false;
@@ -4797,6 +4985,9 @@
 	crq->cur = 0;
 	spin_lock_init(&crq->lock);
 
+	/* process any CRQs that were queued before we enabled interrupts */
+	tasklet_schedule(&adapter->tasklet);
+
 	return retrc;
 
 req_irq_failed:
@@ -4850,6 +5041,15 @@
 			release_sub_crqs(adapter, 0);
 			rc = init_sub_crqs(adapter);
 		} else {
+			/* no need to reinitialize completely, but we do
+			 * need to clean up transmits that were in flight
+			 * when we processed the reset.  Failure to do so
+			 * will confound the upper layer, usually TCP, by
+			 * creating the illusion of transmits that are
+			 * awaiting completion.
+			 */
+			clean_tx_pools(adapter);
+
 			rc = reset_sub_crq_queues(adapter);
 		}
 	} else {
@@ -4960,6 +5160,9 @@
 	INIT_LIST_HEAD(&adapter->rwi_list);
 	spin_lock_init(&adapter->rwi_lock);
 	init_completion(&adapter->init_done);
+	init_completion(&adapter->fw_done);
+	init_completion(&adapter->reset_done);
+	init_completion(&adapter->stats_done);
 	clear_bit(0, &adapter->resetting);
 
 	do {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/ibm/ibmvnic.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/ibm/ibmvnic.h
@@ -373,7 +373,7 @@
 #define IBMVNIC_10MBPS		0x40000000
 #define IBMVNIC_100MBPS		0x20000000
 #define IBMVNIC_1GBPS		0x10000000
-#define IBMVNIC_10GBP		0x08000000
+#define IBMVNIC_10GBPS		0x08000000
 #define IBMVNIC_40GBPS		0x04000000
 #define IBMVNIC_100GBPS		0x02000000
 #define IBMVNIC_25GBPS		0x01000000
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/e100.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/e100.c
@@ -1398,7 +1398,7 @@
 	u8 phy_type;
 	int without_mii;
 
-	phy_type = (nic->eeprom[eeprom_phy_iface] >> 8) & 0x0f;
+	phy_type = (le16_to_cpu(nic->eeprom[eeprom_phy_iface]) >> 8) & 0x0f;
 
 	switch (phy_type) {
 	case NoSuchPhy: /* Non-MII PHY; UNTESTED! */
@@ -1518,7 +1518,7 @@
 		mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr);
 	} else if ((nic->mac >= mac_82550_D102) || ((nic->flags & ich) &&
 	   (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) &&
-		(nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) {
+	   (le16_to_cpu(nic->eeprom[eeprom_cnfg_mdix]) & eeprom_mdix_enabled))) {
 		/* enable/disable MDI/MDI-X auto-switching. */
 		mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG,
 				nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH);
@@ -1745,11 +1745,8 @@
 	dma_addr = pci_map_single(nic->pdev,
 				  skb->data, skb->len, PCI_DMA_TODEVICE);
 	/* If we can't map the skb, have the upper layer try later */
-	if (pci_dma_mapping_error(nic->pdev, dma_addr)) {
-		dev_kfree_skb_any(skb);
-		skb = NULL;
+	if (pci_dma_mapping_error(nic->pdev, dma_addr))
 		return -ENOMEM;
-	}
 
 	/*
 	 * Use the last 4 bytes of the SKB payload packet as the CRC, used for
@@ -2266,9 +2263,9 @@
 {
 	/* ASF can be enabled from eeprom */
 	return (nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) &&
-	   (nic->eeprom[eeprom_config_asf] & eeprom_asf) &&
-	   !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) &&
-	   ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE);
+	   (le16_to_cpu(nic->eeprom[eeprom_config_asf]) & eeprom_asf) &&
+	   !(le16_to_cpu(nic->eeprom[eeprom_config_asf]) & eeprom_gcl) &&
+	   ((le16_to_cpu(nic->eeprom[eeprom_smbus_addr]) & 0xFF) != 0xFE);
 }
 
 static int e100_up(struct nic *nic)
@@ -2435,11 +2432,15 @@
 		sizeof(info->bus_info));
 }
 
-#define E100_PHY_REGS 0x1C
+#define E100_PHY_REGS 0x1D
 static int e100_get_regs_len(struct net_device *netdev)
 {
 	struct nic *nic = netdev_priv(netdev);
-	return 1 + E100_PHY_REGS + sizeof(nic->mem->dump_buf);
+
+	/* We know the number of registers, and the size of the dump buffer.
+	 * Calculate the total size in bytes.
+	 */
+	return (1 + E100_PHY_REGS) * sizeof(u32) + sizeof(nic->mem->dump_buf);
 }
 
 static void e100_get_regs(struct net_device *netdev,
@@ -2453,14 +2454,18 @@
 	buff[0] = ioread8(&nic->csr->scb.cmd_hi) << 24 |
 		ioread8(&nic->csr->scb.cmd_lo) << 16 |
 		ioread16(&nic->csr->scb.status);
-	for (i = E100_PHY_REGS; i >= 0; i--)
-		buff[1 + E100_PHY_REGS - i] =
-			mdio_read(netdev, nic->mii.phy_id, i);
+	for (i = 0; i < E100_PHY_REGS; i++)
+		/* Note that we read the registers in reverse order. This
+		 * ordering is the ABI apparently used by ethtool and other
+		 * applications.
+		 */
+		buff[1 + i] = mdio_read(netdev, nic->mii.phy_id,
+					E100_PHY_REGS - 1 - i);
 	memset(nic->mem->dump_buf, 0, sizeof(nic->mem->dump_buf));
 	e100_exec_cb(nic, NULL, e100_dump);
 	msleep(10);
-	memcpy(&buff[2 + E100_PHY_REGS], nic->mem->dump_buf,
-		sizeof(nic->mem->dump_buf));
+	memcpy(&buff[1 + E100_PHY_REGS], nic->mem->dump_buf,
+	       sizeof(nic->mem->dump_buf));
 }
 
 static void e100_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
@@ -2924,7 +2929,7 @@
 
 	/* Wol magic packet can be enabled from eeprom */
 	if ((nic->mac >= mac_82558_D101_A4) &&
-	   (nic->eeprom[eeprom_id] & eeprom_id_wol)) {
+	   (le16_to_cpu(nic->eeprom[eeprom_id]) & eeprom_id_wol)) {
 		nic->flags |= wol_magic;
 		device_set_wakeup_enable(&pdev->dev, true);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -542,8 +542,13 @@
 	WARN_ON(in_interrupt());
 	while (test_and_set_bit(__E1000_RESETTING, &adapter->flags))
 		msleep(1);
-	e1000_down(adapter);
-	e1000_up(adapter);
+
+	/* only run the task if not already down */
+	if (!test_bit(__E1000_DOWN, &adapter->flags)) {
+		e1000_down(adapter);
+		e1000_up(adapter);
+	}
+
 	clear_bit(__E1000_RESETTING, &adapter->flags);
 }
 
@@ -1433,10 +1438,15 @@
 	struct e1000_hw *hw = &adapter->hw;
 	int count = E1000_CHECK_RESET_COUNT;
 
-	while (test_bit(__E1000_RESETTING, &adapter->flags) && count--)
+	while (test_and_set_bit(__E1000_RESETTING, &adapter->flags) && count--)
 		usleep_range(10000, 20000);
 
-	WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags));
+	WARN_ON(count < 0);
+
+	/* signal that we're down so that the reset task will no longer run */
+	set_bit(__E1000_DOWN, &adapter->flags);
+	clear_bit(__E1000_RESETTING, &adapter->flags);
+
 	e1000_down(adapter);
 	e1000_power_down_phy(adapter);
 	e1000_free_irq(adapter);
@@ -3140,8 +3150,9 @@
 		hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
 		if (skb->data_len && hdr_len == len) {
 			switch (hw->mac_type) {
+			case e1000_82544: {
 				unsigned int pull_size;
-			case e1000_82544:
+
 				/* Make sure we have room to chop off 4 bytes,
 				 * and that the end alignment will work out to
 				 * this hardware's requirements
@@ -3162,6 +3173,7 @@
 				}
 				len = skb_headlen(skb);
 				break;
+			}
 			default:
 				/* do nothing */
 				break;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/e1000e/82571.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/e1000e/82571.c
@@ -899,6 +899,8 @@
 	} else {
 		data &= ~IGP02E1000_PM_D0_LPLU;
 		ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data);
+		if (ret_val)
+			return ret_val;
 		/* LPLU and SmartSpeed are mutually exclusive.  LPLU is used
 		 * during Dx states where the power conservation is most
 		 * important.  During driver activity we should enable
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/e1000e/e1000.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/e1000e/e1000.h
@@ -185,13 +185,12 @@
 
 /* board specific private data structure */
 struct e1000_adapter {
+	struct timer_list watchdog_timer;
 	struct timer_list phy_info_timer;
 	struct timer_list blink_timer;
 
 	struct work_struct reset_task;
-	struct delayed_work watchdog_task;
-
-	struct workqueue_struct *e1000_workqueue;
+	struct work_struct watchdog_task;
 
 	const struct e1000_info *ei;
 
@@ -577,7 +576,6 @@
 
 #define er32(reg)	__er32(hw, E1000_##reg)
 
-s32 __ew32_prepare(struct e1000_hw *hw);
 void __ew32(struct e1000_hw *hw, unsigned long reg, u32 val);
 
 #define ew32(reg, val)	__ew32(hw, E1000_##reg, (val))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/e1000e/hw.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/e1000e/hw.h
@@ -86,6 +86,12 @@
 #define E1000_DEV_ID_PCH_ICP_I219_V8		0x15E0
 #define E1000_DEV_ID_PCH_ICP_I219_LM9		0x15E1
 #define E1000_DEV_ID_PCH_ICP_I219_V9		0x15E2
+#define E1000_DEV_ID_PCH_CMP_I219_LM10		0x0D4E
+#define E1000_DEV_ID_PCH_CMP_I219_V10		0x0D4F
+#define E1000_DEV_ID_PCH_CMP_I219_LM11		0x0D4C
+#define E1000_DEV_ID_PCH_CMP_I219_V11		0x0D4D
+#define E1000_DEV_ID_PCH_CMP_I219_LM12		0x0D53
+#define E1000_DEV_ID_PCH_CMP_I219_V12		0x0D55
 
 #define E1000_REVISION_4	4
 
@@ -662,6 +668,7 @@
 	bool kmrn_lock_loss_workaround_enabled;
 	struct e1000_shadow_ram shadow_ram[E1000_ICH8_SHADOW_RAM_WORDS];
 	bool nvm_k1_enabled;
+	bool disable_k1_off;
 	bool eee_disable;
 	u16 eee_lp_ability;
 	enum e1000_ulp_state ulp_state;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/e1000e/ich8lan.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/e1000e/ich8lan.c
@@ -995,6 +995,8 @@
 {
 	u32 reg = link << (E1000_LTRV_REQ_SHIFT + E1000_LTRV_NOSNOOP_SHIFT) |
 	    link << E1000_LTRV_REQ_SHIFT | E1000_LTRV_SEND;
+	u32 max_ltr_enc_d = 0;	/* maximum LTR decoded by platform */
+	u32 lat_enc_d = 0;	/* latency decoded */
 	u16 lat_enc = 0;	/* latency encoded */
 
 	if (link) {
@@ -1048,7 +1050,17 @@
 				     E1000_PCI_LTR_CAP_LPT + 2, &max_nosnoop);
 		max_ltr_enc = max_t(u16, max_snoop, max_nosnoop);
 
-		if (lat_enc > max_ltr_enc)
+		lat_enc_d = (lat_enc & E1000_LTRV_VALUE_MASK) *
+			     (1U << (E1000_LTRV_SCALE_FACTOR *
+			     ((lat_enc & E1000_LTRV_SCALE_MASK)
+			     >> E1000_LTRV_SCALE_SHIFT)));
+
+		max_ltr_enc_d = (max_ltr_enc & E1000_LTRV_VALUE_MASK) *
+				 (1U << (E1000_LTRV_SCALE_FACTOR *
+				 ((max_ltr_enc & E1000_LTRV_SCALE_MASK)
+				 >> E1000_LTRV_SCALE_SHIFT)));
+
+		if (lat_enc_d > max_ltr_enc_d)
 			lat_enc = max_ltr_enc;
 	}
 
@@ -1237,9 +1249,9 @@
 			ew32(H2ME, mac_reg);
 		}
 
-		/* Poll up to 300msec for ME to clear ULP_CFG_DONE. */
+		/* Poll up to 2.5sec for ME to clear ULP_CFG_DONE. */
 		while (er32(FWSM) & E1000_FWSM_ULP_CFG_DONE) {
-			if (i++ == 30) {
+			if (i++ == 250) {
 				ret_val = -E1000_ERR_PHY;
 				goto out;
 			}
@@ -1538,6 +1550,9 @@
 				fextnvm6 &= ~E1000_FEXTNVM6_K1_OFF_ENABLE;
 		}
 
+		if (hw->dev_spec.ich8lan.disable_k1_off == true)
+			fextnvm6 &= ~E1000_FEXTNVM6_K1_OFF_ENABLE;
+
 		ew32(FEXTNVM6, fextnvm6);
 	}
 
@@ -4084,13 +4099,17 @@
 		return ret_val;
 
 	if (!(data & valid_csum_mask)) {
-		data |= valid_csum_mask;
-		ret_val = e1000_write_nvm(hw, word, 1, &data);
-		if (ret_val)
-			return ret_val;
-		ret_val = e1000e_update_nvm_checksum(hw);
-		if (ret_val)
-			return ret_val;
+		e_dbg("NVM Checksum Invalid\n");
+
+		if (hw->mac.type < e1000_pch_cnp) {
+			data |= valid_csum_mask;
+			ret_val = e1000_write_nvm(hw, word, 1, &data);
+			if (ret_val)
+				return ret_val;
+			ret_val = e1000e_update_nvm_checksum(hw);
+			if (ret_val)
+				return ret_val;
+		}
 	}
 
 	return e1000e_validate_nvm_checksum_generic(hw);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/e1000e/ich8lan.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/e1000e/ich8lan.h
@@ -274,8 +274,11 @@
 
 /* Latency Tolerance Reporting */
 #define E1000_LTRV			0x000F8
+#define E1000_LTRV_VALUE_MASK		0x000003FF
 #define E1000_LTRV_SCALE_MAX		5
 #define E1000_LTRV_SCALE_FACTOR		5
+#define E1000_LTRV_SCALE_SHIFT		10
+#define E1000_LTRV_SCALE_MASK		0x00001C00
 #define E1000_LTRV_REQ_SHIFT		15
 #define E1000_LTRV_NOSNOOP_SHIFT	16
 #define E1000_LTRV_SEND			(1 << 30)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/e1000e/netdev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -119,14 +119,12 @@
  * has bit 24 set while ME is accessing MAC CSR registers, wait if it is set
  * and try again a number of times.
  **/
-s32 __ew32_prepare(struct e1000_hw *hw)
+static void __ew32_prepare(struct e1000_hw *hw)
 {
 	s32 i = E1000_ICH_FWSM_PCIM2PCI_COUNT;
 
 	while ((er32(FWSM) & E1000_ICH_FWSM_PCIM2PCI) && --i)
 		udelay(50);
-
-	return i;
 }
 
 void __ew32(struct e1000_hw *hw, unsigned long reg, u32 val)
@@ -607,11 +605,11 @@
 {
 	struct e1000_adapter *adapter = rx_ring->adapter;
 	struct e1000_hw *hw = &adapter->hw;
-	s32 ret_val = __ew32_prepare(hw);
 
+	__ew32_prepare(hw);
 	writel(i, rx_ring->tail);
 
-	if (unlikely(!ret_val && (i != readl(rx_ring->tail)))) {
+	if (unlikely(i != readl(rx_ring->tail))) {
 		u32 rctl = er32(RCTL);
 
 		ew32(RCTL, rctl & ~E1000_RCTL_EN);
@@ -624,11 +622,11 @@
 {
 	struct e1000_adapter *adapter = tx_ring->adapter;
 	struct e1000_hw *hw = &adapter->hw;
-	s32 ret_val = __ew32_prepare(hw);
 
+	__ew32_prepare(hw);
 	writel(i, tx_ring->tail);
 
-	if (unlikely(!ret_val && (i != readl(tx_ring->tail)))) {
+	if (unlikely(i != readl(tx_ring->tail))) {
 		u32 tctl = er32(TCTL);
 
 		ew32(TCTL, tctl & ~E1000_TCTL_EN);
@@ -1780,8 +1778,7 @@
 		}
 		/* guard against interrupt when we're going down */
 		if (!test_bit(__E1000_DOWN, &adapter->state))
-			mod_delayed_work(adapter->e1000_workqueue,
-					 &adapter->watchdog_task, HZ);
+			mod_timer(&adapter->watchdog_timer, jiffies + 1);
 	}
 
 	/* Reset on uncorrectable ECC error */
@@ -1861,8 +1858,7 @@
 		}
 		/* guard against interrupt when we're going down */
 		if (!test_bit(__E1000_DOWN, &adapter->state))
-			mod_delayed_work(adapter->e1000_workqueue,
-					 &adapter->watchdog_task, HZ);
+			mod_timer(&adapter->watchdog_timer, jiffies + 1);
 	}
 
 	/* Reset on uncorrectable ECC error */
@@ -1907,8 +1903,7 @@
 		hw->mac.get_link_status = true;
 		/* guard against interrupt when we're going down */
 		if (!test_bit(__E1000_DOWN, &adapter->state))
-			mod_delayed_work(adapter->e1000_workqueue,
-					 &adapter->watchdog_task, HZ);
+			mod_timer(&adapter->watchdog_timer, jiffies + 1);
 	}
 
 	if (!test_bit(__E1000_DOWN, &adapter->state))
@@ -4281,6 +4276,7 @@
 
 	napi_synchronize(&adapter->napi);
 
+	del_timer_sync(&adapter->watchdog_timer);
 	del_timer_sync(&adapter->phy_info_timer);
 
 	spin_lock(&adapter->stats64_lock);
@@ -4715,12 +4711,12 @@
 
 	pm_runtime_get_sync(&pdev->dev);
 
-	if (!test_bit(__E1000_DOWN, &adapter->state)) {
+	if (netif_device_present(netdev)) {
 		e1000e_down(adapter, true);
 		e1000_free_irq(adapter);
 
 		/* Link status message must follow this format */
-		pr_info("%s NIC Link is Down\n", adapter->netdev->name);
+		pr_info("%s NIC Link is Down\n", netdev->name);
 	}
 
 	napi_disable(&adapter->napi);
@@ -5152,11 +5148,25 @@
 	}
 }
 
+/**
+ * e1000_watchdog - Timer Call-back
+ * @data: pointer to adapter cast into an unsigned long
+ **/
+static void e1000_watchdog(struct timer_list *t)
+{
+	struct e1000_adapter *adapter = from_timer(adapter, t, watchdog_timer);
+
+	/* Do the rest outside of interrupt context */
+	schedule_work(&adapter->watchdog_task);
+
+	/* TODO: make this use queue_delayed_work() */
+}
+
 static void e1000_watchdog_task(struct work_struct *work)
 {
 	struct e1000_adapter *adapter = container_of(work,
 						     struct e1000_adapter,
-						     watchdog_task.work);
+						     watchdog_task);
 	struct net_device *netdev = adapter->netdev;
 	struct e1000_mac_info *mac = &adapter->hw.mac;
 	struct e1000_phy_info *phy = &adapter->hw.phy;
@@ -5189,18 +5199,20 @@
 			pm_runtime_resume(netdev->dev.parent);
 
 			/* Checking if MAC is in DMoff state*/
-			pcim_state = er32(STATUS);
-			while (pcim_state & E1000_STATUS_PCIM_STATE) {
-				if (tries++ == dmoff_exit_timeout) {
-					e_dbg("Error in exiting dmoff\n");
-					break;
-				}
-				usleep_range(10000, 20000);
+			if (er32(FWSM) & E1000_ICH_FWSM_FW_VALID) {
 				pcim_state = er32(STATUS);
-
-				/* Checking if MAC exited DMoff state */
-				if (!(pcim_state & E1000_STATUS_PCIM_STATE))
-					e1000_phy_hw_reset(&adapter->hw);
+				while (pcim_state & E1000_STATUS_PCIM_STATE) {
+					if (tries++ == dmoff_exit_timeout) {
+						e_dbg("Error in exiting dmoff\n");
+						break;
+					}
+					usleep_range(10000, 20000);
+					pcim_state = er32(STATUS);
+
+					/* Checking if MAC exited DMoff state */
+					if (!(pcim_state & E1000_STATUS_PCIM_STATE))
+						e1000_phy_hw_reset(&adapter->hw);
+				}
 			}
 
 			/* update snapshot of PHY registers on LSC */
@@ -5258,27 +5270,6 @@
 				ew32(TARC(0), tarc0);
 			}
 
-			/* disable TSO for pcie and 10/100 speeds, to avoid
-			 * some hardware issues
-			 */
-			if (!(adapter->flags & FLAG_TSO_FORCE)) {
-				switch (adapter->link_speed) {
-				case SPEED_10:
-				case SPEED_100:
-					e_info("10/100 speed: disabling TSO\n");
-					netdev->features &= ~NETIF_F_TSO;
-					netdev->features &= ~NETIF_F_TSO6;
-					break;
-				case SPEED_1000:
-					netdev->features |= NETIF_F_TSO;
-					netdev->features |= NETIF_F_TSO6;
-					break;
-				default:
-					/* oops */
-					break;
-				}
-			}
-
 			/* enable transmits in the hardware, need to do this
 			 * after setting TARC(0)
 			 */
@@ -5404,9 +5395,8 @@
 
 	/* Reset the timer */
 	if (!test_bit(__E1000_DOWN, &adapter->state))
-		queue_delayed_work(adapter->e1000_workqueue,
-				   &adapter->watchdog_task,
-				   round_jiffies(2 * HZ));
+		mod_timer(&adapter->watchdog_timer,
+			  round_jiffies(jiffies + 2 * HZ));
 }
 
 #define E1000_TX_FLAGS_CSUM		0x00000001
@@ -5901,9 +5891,9 @@
 		e1000_tx_queue(tx_ring, tx_flags, count);
 		/* Make sure there is space in the ring for the next send. */
 		e1000_maybe_stop_tx(tx_ring,
-				    (MAX_SKB_FRAGS *
+				    ((MAX_SKB_FRAGS + 1) *
 				     DIV_ROUND_UP(PAGE_SIZE,
-						  adapter->tx_fifo_limit) + 2));
+						  adapter->tx_fifo_limit) + 4));
 
 		if (!netdev_xmit_more() ||
 		    netif_xmit_stopped(netdev_get_tx_queue(netdev, 0))) {
@@ -5940,15 +5930,19 @@
 	struct e1000_adapter *adapter;
 	adapter = container_of(work, struct e1000_adapter, reset_task);
 
+	rtnl_lock();
 	/* don't run the task if already down */
-	if (test_bit(__E1000_DOWN, &adapter->state))
+	if (test_bit(__E1000_DOWN, &adapter->state)) {
+		rtnl_unlock();
 		return;
+	}
 
 	if (!(adapter->flags & FLAG_RESTART_NOW)) {
 		e1000e_dump(adapter);
 		e_err("Reset adapter unexpectedly\n");
 	}
 	e1000e_reinit_locked(adapter);
+	rtnl_unlock();
 }
 
 /**
@@ -6294,14 +6288,186 @@
 	pm_runtime_put_sync(netdev->dev.parent);
 }
 
+/* S0ix implementation */
+static void e1000e_s0ix_entry_flow(struct e1000_adapter *adapter)
+{
+	struct e1000_hw *hw = &adapter->hw;
+	u32 mac_data;
+	u16 phy_data;
+
+	/* Disable the periodic inband message,
+	 * don't request PCIe clock in K1 page770_17[10:9] = 10b
+	 */
+	e1e_rphy(hw, HV_PM_CTRL, &phy_data);
+	phy_data &= ~HV_PM_CTRL_K1_CLK_REQ;
+	phy_data |= BIT(10);
+	e1e_wphy(hw, HV_PM_CTRL, phy_data);
+
+	/* Make sure we don't exit K1 every time a new packet arrives
+	 * 772_29[5] = 1 CS_Mode_Stay_In_K1
+	 */
+	e1e_rphy(hw, I217_CGFREG, &phy_data);
+	phy_data |= BIT(5);
+	e1e_wphy(hw, I217_CGFREG, phy_data);
+
+	/* Change the MAC/PHY interface to SMBus
+	 * Force the SMBus in PHY page769_23[0] = 1
+	 * Force the SMBus in MAC CTRL_EXT[11] = 1
+	 */
+	e1e_rphy(hw, CV_SMB_CTRL, &phy_data);
+	phy_data |= CV_SMB_CTRL_FORCE_SMBUS;
+	e1e_wphy(hw, CV_SMB_CTRL, phy_data);
+	mac_data = er32(CTRL_EXT);
+	mac_data |= E1000_CTRL_EXT_FORCE_SMBUS;
+	ew32(CTRL_EXT, mac_data);
+
+	/* DFT control: PHY bit: page769_20[0] = 1
+	 * Gate PPW via EXTCNF_CTRL - set 0x0F00[7] = 1
+	 */
+	e1e_rphy(hw, I82579_DFT_CTRL, &phy_data);
+	phy_data |= BIT(0);
+	e1e_wphy(hw, I82579_DFT_CTRL, phy_data);
+
+	mac_data = er32(EXTCNF_CTRL);
+	mac_data |= E1000_EXTCNF_CTRL_GATE_PHY_CFG;
+	ew32(EXTCNF_CTRL, mac_data);
+
+	/* Check MAC Tx/Rx packet buffer pointers.
+	 * Reset MAC Tx/Rx packet buffer pointers to suppress any
+	 * pending traffic indication that would prevent power gating.
+	 */
+	mac_data = er32(TDFH);
+	if (mac_data)
+		ew32(TDFH, 0);
+	mac_data = er32(TDFT);
+	if (mac_data)
+		ew32(TDFT, 0);
+	mac_data = er32(TDFHS);
+	if (mac_data)
+		ew32(TDFHS, 0);
+	mac_data = er32(TDFTS);
+	if (mac_data)
+		ew32(TDFTS, 0);
+	mac_data = er32(TDFPC);
+	if (mac_data)
+		ew32(TDFPC, 0);
+	mac_data = er32(RDFH);
+	if (mac_data)
+		ew32(RDFH, 0);
+	mac_data = er32(RDFT);
+	if (mac_data)
+		ew32(RDFT, 0);
+	mac_data = er32(RDFHS);
+	if (mac_data)
+		ew32(RDFHS, 0);
+	mac_data = er32(RDFTS);
+	if (mac_data)
+		ew32(RDFTS, 0);
+	mac_data = er32(RDFPC);
+	if (mac_data)
+		ew32(RDFPC, 0);
+
+	/* Enable the Dynamic Power Gating in the MAC */
+	mac_data = er32(FEXTNVM7);
+	mac_data |= BIT(22);
+	ew32(FEXTNVM7, mac_data);
+
+	/* Disable the time synchronization clock */
+	mac_data = er32(FEXTNVM7);
+	mac_data |= BIT(31);
+	mac_data &= ~BIT(0);
+	ew32(FEXTNVM7, mac_data);
+
+	/* Dynamic Power Gating Enable */
+	mac_data = er32(CTRL_EXT);
+	mac_data |= BIT(3);
+	ew32(CTRL_EXT, mac_data);
+
+	/* Enable the Dynamic Clock Gating in the DMA and MAC */
+	mac_data = er32(CTRL_EXT);
+	mac_data |= E1000_CTRL_EXT_DMA_DYN_CLK_EN;
+	ew32(CTRL_EXT, mac_data);
+
+	/* No MAC DPG gating SLP_S0 in modern standby
+	 * Switch the logic of the lanphypc to use PMC counter
+	 */
+	mac_data = er32(FEXTNVM5);
+	mac_data |= BIT(7);
+	ew32(FEXTNVM5, mac_data);
+}
+
+static void e1000e_s0ix_exit_flow(struct e1000_adapter *adapter)
+{
+	struct e1000_hw *hw = &adapter->hw;
+	u32 mac_data;
+	u16 phy_data;
+
+	/* Disable the Dynamic Power Gating in the MAC */
+	mac_data = er32(FEXTNVM7);
+	mac_data &= 0xFFBFFFFF;
+	ew32(FEXTNVM7, mac_data);
+
+	/* Enable the time synchronization clock */
+	mac_data = er32(FEXTNVM7);
+	mac_data |= BIT(0);
+	ew32(FEXTNVM7, mac_data);
+
+	/* Disable Dynamic Power Gating */
+	mac_data = er32(CTRL_EXT);
+	mac_data &= 0xFFFFFFF7;
+	ew32(CTRL_EXT, mac_data);
+
+	/* Disable the Dynamic Clock Gating in the DMA and MAC */
+	mac_data = er32(CTRL_EXT);
+	mac_data &= 0xFFF7FFFF;
+	ew32(CTRL_EXT, mac_data);
+
+	/* Revert the lanphypc logic to use the internal Gbe counter
+	 * and not the PMC counter
+	 */
+	mac_data = er32(FEXTNVM5);
+	mac_data &= 0xFFFFFF7F;
+	ew32(FEXTNVM5, mac_data);
+
+	/* Enable the periodic inband message,
+	 * Request PCIe clock in K1 page770_17[10:9] =01b
+	 */
+	e1e_rphy(hw, HV_PM_CTRL, &phy_data);
+	phy_data &= 0xFBFF;
+	phy_data |= HV_PM_CTRL_K1_CLK_REQ;
+	e1e_wphy(hw, HV_PM_CTRL, phy_data);
+
+	/* Return back configuration
+	 * 772_29[5] = 0 CS_Mode_Stay_In_K1
+	 */
+	e1e_rphy(hw, I217_CGFREG, &phy_data);
+	phy_data &= 0xFFDF;
+	e1e_wphy(hw, I217_CGFREG, phy_data);
+
+	/* Change the MAC/PHY interface to Kumeran
+	 * Unforce the SMBus in PHY page769_23[0] = 0
+	 * Unforce the SMBus in MAC CTRL_EXT[11] = 0
+	 */
+	e1e_rphy(hw, CV_SMB_CTRL, &phy_data);
+	phy_data &= ~CV_SMB_CTRL_FORCE_SMBUS;
+	e1e_wphy(hw, CV_SMB_CTRL, phy_data);
+	mac_data = er32(CTRL_EXT);
+	mac_data &= ~E1000_CTRL_EXT_FORCE_SMBUS;
+	ew32(CTRL_EXT, mac_data);
+}
+
 static int e1000e_pm_freeze(struct device *dev)
 {
 	struct net_device *netdev = dev_get_drvdata(dev);
 	struct e1000_adapter *adapter = netdev_priv(netdev);
+	bool present;
+
+	rtnl_lock();
 
+	present = netif_device_present(netdev);
 	netif_device_detach(netdev);
 
-	if (netif_running(netdev)) {
+	if (present && netif_running(netdev)) {
 		int count = E1000_CHECK_RESET_COUNT;
 
 		while (test_bit(__E1000_RESETTING, &adapter->state) && count--)
@@ -6313,6 +6479,8 @@
 		e1000e_down(adapter, false);
 		e1000_free_irq(adapter);
 	}
+	rtnl_unlock();
+
 	e1000e_reset_interrupt_capability(adapter);
 
 	/* Allow time for pending master requests to run */
@@ -6326,11 +6494,17 @@
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
-	u32 ctrl, ctrl_ext, rctl, status;
-	/* Runtime suspend should only enable wakeup for link changes */
-	u32 wufc = runtime ? E1000_WUFC_LNKC : adapter->wol;
+	u32 ctrl, ctrl_ext, rctl, status, wufc;
 	int retval = 0;
 
+	/* Runtime suspend should only enable wakeup for link changes */
+	if (runtime)
+		wufc = E1000_WUFC_LNKC;
+	else if (device_may_wakeup(&pdev->dev))
+		wufc = adapter->wol;
+	else
+		wufc = 0;
+
 	status = er32(STATUS);
 	if (status & E1000_STATUS_LU)
 		wufc &= ~E1000_WUFC_LNKC;
@@ -6387,7 +6561,7 @@
 	if (adapter->hw.phy.type == e1000_phy_igp_3) {
 		e1000e_igp3_phy_powerdown_workaround_ich8lan(&adapter->hw);
 	} else if (hw->mac.type >= e1000_pch_lpt) {
-		if (!(wufc & (E1000_WUFC_EX | E1000_WUFC_MC | E1000_WUFC_BC)))
+		if (wufc && !(wufc & (E1000_WUFC_EX | E1000_WUFC_MC | E1000_WUFC_BC)))
 			/* ULP does not support wake from unicast, multicast
 			 * or broadcast.
 			 */
@@ -6560,6 +6734,30 @@
 	__e1000e_disable_aspm(pdev, state, 1);
 }
 
+static int e1000e_pm_thaw(struct device *dev)
+{
+	struct net_device *netdev = dev_get_drvdata(dev);
+	struct e1000_adapter *adapter = netdev_priv(netdev);
+	int rc = 0;
+
+	e1000e_set_interrupt_capability(adapter);
+
+	rtnl_lock();
+	if (netif_running(netdev)) {
+		rc = e1000_request_irq(adapter);
+		if (rc)
+			goto err_irq;
+
+		e1000e_up(adapter);
+	}
+
+	netif_device_attach(netdev);
+err_irq:
+	rtnl_unlock();
+
+	return rc;
+}
+
 #ifdef CONFIG_PM
 static int __e1000_resume(struct pci_dev *pdev)
 {
@@ -6627,29 +6825,12 @@
 }
 
 #ifdef CONFIG_PM_SLEEP
-static int e1000e_pm_thaw(struct device *dev)
-{
-	struct net_device *netdev = dev_get_drvdata(dev);
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-
-	e1000e_set_interrupt_capability(adapter);
-	if (netif_running(netdev)) {
-		u32 err = e1000_request_irq(adapter);
-
-		if (err)
-			return err;
-
-		e1000e_up(adapter);
-	}
-
-	netif_device_attach(netdev);
-
-	return 0;
-}
-
 static int e1000e_pm_suspend(struct device *dev)
 {
+	struct net_device *netdev = pci_get_drvdata(to_pci_dev(dev));
+	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct pci_dev *pdev = to_pci_dev(dev);
+	struct e1000_hw *hw = &adapter->hw;
 	int rc;
 
 	e1000e_flush_lpic(pdev);
@@ -6660,14 +6841,25 @@
 	if (rc)
 		e1000e_pm_thaw(dev);
 
+	/* Introduce S0ix implementation */
+	if (hw->mac.type >= e1000_pch_cnp)
+		e1000e_s0ix_entry_flow(adapter);
+
 	return rc;
 }
 
 static int e1000e_pm_resume(struct device *dev)
 {
+	struct net_device *netdev = pci_get_drvdata(to_pci_dev(dev));
+	struct e1000_adapter *adapter = netdev_priv(netdev);
 	struct pci_dev *pdev = to_pci_dev(dev);
+	struct e1000_hw *hw = &adapter->hw;
 	int rc;
 
+	/* Introduce S0ix implementation */
+	if (hw->mac.type >= e1000_pch_cnp)
+		e1000e_s0ix_exit_flow(adapter);
+
 	rc = __e1000_resume(pdev);
 	if (rc)
 		return rc;
@@ -6818,16 +7010,11 @@
 static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev,
 						pci_channel_state_t state)
 {
-	struct net_device *netdev = pci_get_drvdata(pdev);
-	struct e1000_adapter *adapter = netdev_priv(netdev);
-
-	netif_device_detach(netdev);
+	e1000e_pm_freeze(&pdev->dev);
 
 	if (state == pci_channel_io_perm_failure)
 		return PCI_ERS_RESULT_DISCONNECT;
 
-	if (netif_running(netdev))
-		e1000e_down(adapter, true);
 	pci_disable_device(pdev);
 
 	/* Request a slot slot reset. */
@@ -6893,10 +7080,7 @@
 
 	e1000_init_manageability_pt(adapter);
 
-	if (netif_running(netdev))
-		e1000e_up(adapter);
-
-	netif_device_attach(netdev);
+	e1000e_pm_thaw(&pdev->dev);
 
 	/* If the controller has AMT, do not set DRV_LOAD until the interface
 	 * is up.  For all other cases, let the f/w know that the h/w is now
@@ -7196,6 +7380,32 @@
 			    NETIF_F_RXCSUM |
 			    NETIF_F_HW_CSUM);
 
+	/* disable TSO for pcie and 10/100 speeds to avoid
+	 * some hardware issues and for i219 to fix transfer
+	 * speed being capped at 60%
+	 */
+	if (!(adapter->flags & FLAG_TSO_FORCE)) {
+		switch (adapter->link_speed) {
+		case SPEED_10:
+		case SPEED_100:
+			e_info("10/100 speed: disabling TSO\n");
+			netdev->features &= ~NETIF_F_TSO;
+			netdev->features &= ~NETIF_F_TSO6;
+			break;
+		case SPEED_1000:
+			netdev->features |= NETIF_F_TSO;
+			netdev->features |= NETIF_F_TSO6;
+			break;
+		default:
+			/* oops */
+			break;
+		}
+		if (hw->mac.type == e1000_pch_spt) {
+			netdev->features &= ~NETIF_F_TSO;
+			netdev->features &= ~NETIF_F_TSO6;
+		}
+	}
+
 	/* Set user-changeable features (subset of all device features) */
 	netdev->hw_features = netdev->features;
 	netdev->hw_features |= NETIF_F_RXFCS;
@@ -7259,21 +7469,11 @@
 		goto err_eeprom;
 	}
 
-	adapter->e1000_workqueue = alloc_workqueue("%s", WQ_MEM_RECLAIM, 0,
-						   e1000e_driver_name);
-
-	if (!adapter->e1000_workqueue) {
-		err = -ENOMEM;
-		goto err_workqueue;
-	}
-
-	INIT_DELAYED_WORK(&adapter->watchdog_task, e1000_watchdog_task);
-	queue_delayed_work(adapter->e1000_workqueue, &adapter->watchdog_task,
-			   0);
-
+	timer_setup(&adapter->watchdog_timer, e1000_watchdog, 0);
 	timer_setup(&adapter->phy_info_timer, e1000_update_phy_info, 0);
 
 	INIT_WORK(&adapter->reset_task, e1000_reset_task);
+	INIT_WORK(&adapter->watchdog_task, e1000_watchdog_task);
 	INIT_WORK(&adapter->downshift_task, e1000e_downshift_workaround);
 	INIT_WORK(&adapter->update_phy_task, e1000e_update_phy_task);
 	INIT_WORK(&adapter->print_hang_task, e1000_print_hw_hang);
@@ -7367,9 +7567,6 @@
 	return 0;
 
 err_register:
-	flush_workqueue(adapter->e1000_workqueue);
-	destroy_workqueue(adapter->e1000_workqueue);
-err_workqueue:
 	if (!(adapter->flags & FLAG_HAS_AMT))
 		e1000e_release_hw_control(adapter);
 err_eeprom:
@@ -7387,6 +7584,7 @@
 err_ioremap:
 	free_netdev(netdev);
 err_alloc_etherdev:
+	pci_disable_pcie_error_reporting(pdev);
 	pci_release_mem_regions(pdev);
 err_pci_reg:
 err_dma:
@@ -7407,26 +7605,22 @@
 {
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct e1000_adapter *adapter = netdev_priv(netdev);
-	bool down = test_bit(__E1000_DOWN, &adapter->state);
 
 	e1000e_ptp_remove(adapter);
 
 	/* The timers may be rescheduled, so explicitly disable them
 	 * from being rescheduled.
 	 */
-	if (!down)
-		set_bit(__E1000_DOWN, &adapter->state);
+	set_bit(__E1000_DOWN, &adapter->state);
+	del_timer_sync(&adapter->watchdog_timer);
 	del_timer_sync(&adapter->phy_info_timer);
 
 	cancel_work_sync(&adapter->reset_task);
+	cancel_work_sync(&adapter->watchdog_task);
 	cancel_work_sync(&adapter->downshift_task);
 	cancel_work_sync(&adapter->update_phy_task);
 	cancel_work_sync(&adapter->print_hang_task);
 
-	cancel_delayed_work(&adapter->watchdog_task);
-	flush_workqueue(adapter->e1000_workqueue);
-	destroy_workqueue(adapter->e1000_workqueue);
-
 	if (adapter->flags & FLAG_HAS_HW_TIMESTAMP) {
 		cancel_work_sync(&adapter->tx_hwtstamp_work);
 		if (adapter->tx_hwtstamp_skb) {
@@ -7435,9 +7629,6 @@
 		}
 	}
 
-	/* Don't lie to e1000_close() down the road. */
-	if (!down)
-		clear_bit(__E1000_DOWN, &adapter->state);
 	unregister_netdev(netdev);
 
 	if (pci_dev_run_wake(pdev))
@@ -7567,6 +7758,12 @@
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_ICP_I219_V8), board_pch_cnp },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_ICP_I219_LM9), board_pch_cnp },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_ICP_I219_V9), board_pch_cnp },
+	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_CMP_I219_LM10), board_pch_cnp },
+	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_CMP_I219_V10), board_pch_cnp },
+	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_CMP_I219_LM11), board_pch_cnp },
+	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_CMP_I219_V11), board_pch_cnp },
+	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_CMP_I219_LM12), board_pch_spt },
+	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_CMP_I219_V12), board_pch_spt },
 
 	{ 0, 0, 0, 0, 0, 0, 0 }	/* terminate list */
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/e1000e/phy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/e1000e/phy.c
@@ -203,7 +203,7 @@
 	 * Increasing the time out as testing showed failures with
 	 * the lower time out
 	 */
-	for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
+	for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 10); i++) {
 		udelay(50);
 		mdic = er32(MDIC);
 		if (mdic & E1000_MDIC_READY)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/e1000e/regs.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/e1000e/regs.h
@@ -18,6 +18,7 @@
 #define E1000_FEXTNVM	0x00028	/* Future Extended NVM - RW */
 #define E1000_FEXTNVM3	0x0003C	/* Future Extended NVM 3 - RW */
 #define E1000_FEXTNVM4	0x00024	/* Future Extended NVM 4 - RW */
+#define E1000_FEXTNVM5	0x00014	/* Future Extended NVM 5 - RW */
 #define E1000_FEXTNVM6	0x00010	/* Future Extended NVM 6 - RW */
 #define E1000_FEXTNVM7	0x000E4	/* Future Extended NVM 7 - RW */
 #define E1000_FEXTNVM9	0x5BB4	/* Future Extended NVM 9 - RW */
@@ -234,4 +235,7 @@
 #define E1000_RXMTRL	0x0B634	/* Time sync Rx EtherType and Msg Type - RW */
 #define E1000_RXUDP	0x0B638	/* Time Sync Rx UDP Port - RW */
 
+/* PHY registers */
+#define I82579_DFT_CTRL	PHY_REG(769, 20)
+
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
@@ -2230,6 +2230,7 @@
 err_ioremap:
 	free_netdev(netdev);
 err_alloc_netdev:
+	pci_disable_pcie_error_reporting(pdev);
 	pci_release_mem_regions(pdev);
 err_pci_reg:
 err_dma:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/i40e/i40e.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/i40e/i40e.h
@@ -129,6 +129,7 @@
 	__I40E_RESET_INTR_RECEIVED,
 	__I40E_REINIT_REQUESTED,
 	__I40E_PF_RESET_REQUESTED,
+	__I40E_PF_RESET_AND_REBUILD_REQUESTED,
 	__I40E_CORE_RESET_REQUESTED,
 	__I40E_GLOBAL_RESET_REQUESTED,
 	__I40E_EMP_RESET_INTR_RECEIVED,
@@ -150,11 +151,15 @@
 	__I40E_CLIENT_RESET,
 	__I40E_VIRTCHNL_OP_PENDING,
 	__I40E_RECOVERY_MODE,
+	__I40E_VF_RESETS_DISABLED,	/* disable resets during i40e_remove */
+	__I40E_VFS_RELEASING,
 	/* This must be last as it determines the size of the BITMAP */
 	__I40E_STATE_SIZE__,
 };
 
 #define I40E_PF_RESET_FLAG	BIT_ULL(__I40E_PF_RESET_REQUESTED)
+#define I40E_PF_RESET_AND_REBUILD_FLAG	\
+	BIT_ULL(__I40E_PF_RESET_AND_REBUILD_REQUESTED)
 
 /* VSI state flags */
 enum i40e_vsi_state_t {
@@ -164,6 +169,7 @@
 	__I40E_VSI_OVERFLOW_PROMISC,
 	__I40E_VSI_REINIT_REQUESTED,
 	__I40E_VSI_DOWN_REQUESTED,
+	__I40E_VSI_RELEASING,
 	/* This must be last as it determines the size of the BITMAP */
 	__I40E_VSI_STATE_SIZE__,
 };
@@ -176,7 +182,6 @@
 
 struct i40e_lump_tracking {
 	u16 num_entries;
-	u16 search_hint;
 	u16 list[0];
 #define I40E_PILE_VALID_BIT  0x8000
 #define I40E_IWARP_IRQ_PILE_ID  (I40E_PILE_VALID_BIT - 2)
@@ -751,12 +756,12 @@
 	struct rtnl_link_stats64 net_stats_offsets;
 	struct i40e_eth_stats eth_stats;
 	struct i40e_eth_stats eth_stats_offsets;
-	u32 tx_restart;
-	u32 tx_busy;
+	u64 tx_restart;
+	u64 tx_busy;
 	u64 tx_linearize;
 	u64 tx_force_wb;
-	u32 rx_buf_failed;
-	u32 rx_page_failed;
+	u64 rx_buf_failed;
+	u64 rx_page_failed;
 
 	/* These are containers of ring pointers, allocated at run-time */
 	struct i40e_ring **rx_rings;
@@ -1118,6 +1123,7 @@
 					    const u8 *macaddr);
 int i40e_del_mac_filter(struct i40e_vsi *vsi, const u8 *macaddr);
 bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi);
+int i40e_count_filters(struct i40e_vsi *vsi);
 struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, const u8 *macaddr);
 void i40e_vlan_stripping_enable(struct i40e_vsi *vsi);
 #ifdef CONFIG_I40E_DCB
@@ -1141,6 +1147,7 @@
 void i40e_ptp_restore_hw_time(struct i40e_pf *pf);
 void i40e_ptp_init(struct i40e_pf *pf);
 void i40e_ptp_stop(struct i40e_pf *pf);
+int i40e_update_adq_vsi_queues(struct i40e_vsi *vsi, int vsi_offset);
 int i40e_is_vsi_uplink_mode_veb(struct i40e_vsi *vsi);
 i40e_status i40e_get_partition_bw_setting(struct i40e_pf *pf);
 i40e_status i40e_set_partition_bw_setting(struct i40e_pf *pf);
@@ -1151,7 +1158,7 @@
 
 static inline bool i40e_enabled_xdp_vsi(struct i40e_vsi *vsi)
 {
-	return !!vsi->xdp_prog;
+	return !!READ_ONCE(vsi->xdp_prog);
 }
 
 int i40e_create_queue_channel(struct i40e_vsi *vsi, struct i40e_channel *ch);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
@@ -1211,7 +1211,7 @@
 #define I40E_AQC_SET_VSI_PROMISC_BROADCAST	0x04
 #define I40E_AQC_SET_VSI_DEFAULT		0x08
 #define I40E_AQC_SET_VSI_PROMISC_VLAN		0x10
-#define I40E_AQC_SET_VSI_PROMISC_TX		0x8000
+#define I40E_AQC_SET_VSI_PROMISC_RX_ONLY	0x8000
 	__le16	seid;
 #define I40E_AQC_VSI_PROM_CMD_SEID_MASK		0x3FF
 	__le16	vlan_tag;
@@ -1893,8 +1893,10 @@
 	I40E_PHY_TYPE_25GBASE_LR		= 0x22,
 	I40E_PHY_TYPE_25GBASE_AOC		= 0x23,
 	I40E_PHY_TYPE_25GBASE_ACC		= 0x24,
-	I40E_PHY_TYPE_2_5GBASE_T		= 0x30,
-	I40E_PHY_TYPE_5GBASE_T			= 0x31,
+	I40E_PHY_TYPE_2_5GBASE_T		= 0x26,
+	I40E_PHY_TYPE_5GBASE_T			= 0x27,
+	I40E_PHY_TYPE_2_5GBASE_T_LINK_STATUS	= 0x30,
+	I40E_PHY_TYPE_5GBASE_T_LINK_STATUS	= 0x31,
 	I40E_PHY_TYPE_MAX,
 	I40E_PHY_TYPE_NOT_SUPPORTED_HIGH_TEMP	= 0xFD,
 	I40E_PHY_TYPE_EMPTY			= 0xFE,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/i40e/i40e_alloc.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/i40e/i40e_alloc.h
@@ -20,16 +20,11 @@
 };
 
 /* prototype for functions used for dynamic memory allocation */
-i40e_status i40e_allocate_dma_mem(struct i40e_hw *hw,
-					    struct i40e_dma_mem *mem,
-					    enum i40e_memory_type type,
-					    u64 size, u32 alignment);
-i40e_status i40e_free_dma_mem(struct i40e_hw *hw,
-					struct i40e_dma_mem *mem);
-i40e_status i40e_allocate_virt_mem(struct i40e_hw *hw,
-					     struct i40e_virt_mem *mem,
-					     u32 size);
-i40e_status i40e_free_virt_mem(struct i40e_hw *hw,
-					 struct i40e_virt_mem *mem);
+int i40e_allocate_dma_mem(struct i40e_hw *hw, struct i40e_dma_mem *mem,
+			  enum i40e_memory_type type, u64 size, u32 alignment);
+int i40e_free_dma_mem(struct i40e_hw *hw, struct i40e_dma_mem *mem);
+int i40e_allocate_virt_mem(struct i40e_hw *hw, struct i40e_virt_mem *mem,
+			   u32 size);
+int i40e_free_virt_mem(struct i40e_hw *hw, struct i40e_virt_mem *mem);
 
 #endif /* _I40E_ALLOC_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/i40e/i40e_client.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/i40e/i40e_client.c
@@ -178,6 +178,10 @@
 			"Cannot locate client instance close routine\n");
 		return;
 	}
+	if (!test_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state)) {
+		dev_dbg(&pf->pdev->dev, "Client is not open, abort close\n");
+		return;
+	}
 	cdev->client->ops->close(&cdev->lan_info, cdev->client, reset);
 	clear_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state);
 	i40e_client_release_qvlist(&cdev->lan_info);
@@ -376,7 +380,7 @@
 				/* Remove failed client instance */
 				clear_bit(__I40E_CLIENT_INSTANCE_OPENED,
 					  &cdev->state);
-				i40e_client_del_instance(pf);
+				return;
 			}
 		}
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/i40e/i40e_common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/i40e/i40e_common.c
@@ -29,6 +29,7 @@
 		case I40E_DEV_ID_QSFP_C:
 		case I40E_DEV_ID_10G_BASE_T:
 		case I40E_DEV_ID_10G_BASE_T4:
+		case I40E_DEV_ID_10G_BASE_T_BC:
 		case I40E_DEV_ID_10G_B:
 		case I40E_DEV_ID_10G_SFP:
 		case I40E_DEV_ID_20G_KR2:
@@ -1156,8 +1157,8 @@
 		break;
 	case I40E_PHY_TYPE_100BASE_TX:
 	case I40E_PHY_TYPE_1000BASE_T:
-	case I40E_PHY_TYPE_2_5GBASE_T:
-	case I40E_PHY_TYPE_5GBASE_T:
+	case I40E_PHY_TYPE_2_5GBASE_T_LINK_STATUS:
+	case I40E_PHY_TYPE_5GBASE_T_LINK_STATUS:
 	case I40E_PHY_TYPE_10GBASE_T:
 		media = I40E_MEDIA_TYPE_BASET;
 		break;
@@ -1341,7 +1342,7 @@
 		     I40E_PFLAN_QALLOC_FIRSTQ_SHIFT;
 	j = (val & I40E_PFLAN_QALLOC_LASTQ_MASK) >>
 	    I40E_PFLAN_QALLOC_LASTQ_SHIFT;
-	if (val & I40E_PFLAN_QALLOC_VALID_MASK)
+	if (val & I40E_PFLAN_QALLOC_VALID_MASK && j >= base_queue)
 		num_queues = (j - base_queue) + 1;
 	else
 		num_queues = 0;
@@ -1351,7 +1352,7 @@
 	    I40E_PF_VT_PFALLOC_FIRSTVF_SHIFT;
 	j = (val & I40E_PF_VT_PFALLOC_LASTVF_MASK) >>
 	    I40E_PF_VT_PFALLOC_LASTVF_SHIFT;
-	if (val & I40E_PF_VT_PFALLOC_VALID_MASK)
+	if (val & I40E_PF_VT_PFALLOC_VALID_MASK && j >= i)
 		num_vfs = (j - i) + 1;
 	else
 		num_vfs = 0;
@@ -1441,9 +1442,9 @@
 	u32 gpio_val = 0;
 	u32 port;
 
-	if (!hw->func_caps.led[idx])
+	if (!I40E_IS_X710TL_DEVICE(hw->device_id) &&
+	    !hw->func_caps.led[idx])
 		return 0;
-
 	gpio_val = rd32(hw, I40E_GLGEN_GPIO_CTL(idx));
 	port = (gpio_val & I40E_GLGEN_GPIO_CTL_PRT_NUM_MASK) >>
 		I40E_GLGEN_GPIO_CTL_PRT_NUM_SHIFT;
@@ -1462,8 +1463,15 @@
 #define I40E_FILTER_ACTIVITY 0xE
 #define I40E_LINK_ACTIVITY 0xC
 #define I40E_MAC_ACTIVITY 0xD
+#define I40E_FW_LED BIT(4)
+#define I40E_LED_MODE_VALID (I40E_GLGEN_GPIO_CTL_LED_MODE_MASK >> \
+			     I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT)
+
 #define I40E_LED0 22
 
+#define I40E_PIN_FUNC_SDP 0x0
+#define I40E_PIN_FUNC_LED 0x1
+
 /**
  * i40e_led_get - return current on/off mode
  * @hw: pointer to the hw struct
@@ -1508,8 +1516,10 @@
 {
 	int i;
 
-	if (mode & 0xfffffff0)
+	if (mode & ~I40E_LED_MODE_VALID) {
 		hw_dbg(hw, "invalid mode passed in %X\n", mode);
+		return;
+	}
 
 	/* as per the documentation GPIO 22-29 are the LED
 	 * GPIO pins named LED0..LED7
@@ -1519,6 +1529,20 @@
 
 		if (!gpio_val)
 			continue;
+
+		if (I40E_IS_X710TL_DEVICE(hw->device_id)) {
+			u32 pin_func = 0;
+
+			if (mode & I40E_FW_LED)
+				pin_func = I40E_PIN_FUNC_SDP;
+			else
+				pin_func = I40E_PIN_FUNC_LED;
+
+			gpio_val &= ~I40E_GLGEN_GPIO_CTL_PIN_FUNC_MASK;
+			gpio_val |= ((pin_func <<
+				     I40E_GLGEN_GPIO_CTL_PIN_FUNC_SHIFT) &
+				     I40E_GLGEN_GPIO_CTL_PIN_FUNC_MASK);
+		}
 		gpio_val &= ~I40E_GLGEN_GPIO_CTL_LED_MODE_MASK;
 		/* this & is a bit of paranoia, but serves as a range check */
 		gpio_val |= ((mode << I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT) &
@@ -1950,6 +1974,21 @@
 }
 
 /**
+ * i40e_is_aq_api_ver_ge
+ * @aq: pointer to AdminQ info containing HW API version to compare
+ * @maj: API major value
+ * @min: API minor value
+ *
+ * Assert whether current HW API version is greater/equal than provided.
+ **/
+static bool i40e_is_aq_api_ver_ge(struct i40e_adminq_info *aq, u16 maj,
+				  u16 min)
+{
+	return (aq->api_maj_ver > maj ||
+		(aq->api_maj_ver == maj && aq->api_min_ver >= min));
+}
+
+/**
  * i40e_aq_add_vsi
  * @hw: pointer to the hw struct
  * @vsi_ctx: pointer to a vsi context struct
@@ -2074,18 +2113,16 @@
 
 	if (set) {
 		flags |= I40E_AQC_SET_VSI_PROMISC_UNICAST;
-		if (rx_only_promisc &&
-		    (((hw->aq.api_maj_ver == 1) && (hw->aq.api_min_ver >= 5)) ||
-		     (hw->aq.api_maj_ver > 1)))
-			flags |= I40E_AQC_SET_VSI_PROMISC_TX;
+		if (rx_only_promisc && i40e_is_aq_api_ver_ge(&hw->aq, 1, 5))
+			flags |= I40E_AQC_SET_VSI_PROMISC_RX_ONLY;
 	}
 
 	cmd->promiscuous_flags = cpu_to_le16(flags);
 
 	cmd->valid_flags = cpu_to_le16(I40E_AQC_SET_VSI_PROMISC_UNICAST);
-	if (((hw->aq.api_maj_ver >= 1) && (hw->aq.api_min_ver >= 5)) ||
-	    (hw->aq.api_maj_ver > 1))
-		cmd->valid_flags |= cpu_to_le16(I40E_AQC_SET_VSI_PROMISC_TX);
+	if (i40e_is_aq_api_ver_ge(&hw->aq, 1, 5))
+		cmd->valid_flags |=
+			cpu_to_le16(I40E_AQC_SET_VSI_PROMISC_RX_ONLY);
 
 	cmd->seid = cpu_to_le16(seid);
 	status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
@@ -2182,11 +2219,17 @@
 	i40e_fill_default_direct_cmd_desc(&desc,
 					  i40e_aqc_opc_set_vsi_promiscuous_modes);
 
-	if (enable)
+	if (enable) {
 		flags |= I40E_AQC_SET_VSI_PROMISC_UNICAST;
+		if (i40e_is_aq_api_ver_ge(&hw->aq, 1, 5))
+			flags |= I40E_AQC_SET_VSI_PROMISC_RX_ONLY;
+	}
 
 	cmd->promiscuous_flags = cpu_to_le16(flags);
 	cmd->valid_flags = cpu_to_le16(I40E_AQC_SET_VSI_PROMISC_UNICAST);
+	if (i40e_is_aq_api_ver_ge(&hw->aq, 1, 5))
+		cmd->valid_flags |=
+			cpu_to_le16(I40E_AQC_SET_VSI_PROMISC_RX_ONLY);
 	cmd->seid = cpu_to_le16(seid);
 	cmd->vlan_tag = cpu_to_le16(vid | I40E_AQC_SET_VSI_VLAN_VALID);
 
@@ -2571,9 +2614,16 @@
 		if (status)
 			return status;
 
-		hw->phy.link_info.req_fec_info =
-			abilities.fec_cfg_curr_mod_ext_info &
-			(I40E_AQ_REQUEST_FEC_KR | I40E_AQ_REQUEST_FEC_RS);
+		if (abilities.fec_cfg_curr_mod_ext_info &
+		    I40E_AQ_ENABLE_FEC_AUTO)
+			hw->phy.link_info.req_fec_info =
+				(I40E_AQ_REQUEST_FEC_KR |
+				 I40E_AQ_REQUEST_FEC_RS);
+		else
+			hw->phy.link_info.req_fec_info =
+				abilities.fec_cfg_curr_mod_ext_info &
+				(I40E_AQ_REQUEST_FEC_KR |
+				 I40E_AQ_REQUEST_FEC_RS);
 
 		memcpy(hw->phy.link_info.module_type, &abilities.module_type,
 		       sizeof(hw->phy.link_info.module_type));
@@ -4885,6 +4935,7 @@
 		break;
 	case I40E_DEV_ID_10G_BASE_T:
 	case I40E_DEV_ID_10G_BASE_T4:
+	case I40E_DEV_ID_10G_BASE_T_BC:
 	case I40E_DEV_ID_10G_BASE_T_X722:
 	case I40E_DEV_ID_25G_B:
 	case I40E_DEV_ID_25G_SFP28:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/i40e/i40e_dcb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/i40e/i40e_dcb.c
@@ -889,7 +889,9 @@
 
 		ret = i40e_read_nvm_module_data(hw,
 						I40E_SR_EMP_SR_SETTINGS_PTR,
-						offset, 1,
+						offset,
+						I40E_LLDP_CURRENT_STATUS_OFFSET,
+						I40E_LLDP_CURRENT_STATUS_SIZE,
 						&lldp_cfg.adminstatus);
 	} else {
 		ret = i40e_read_lldp_cfg(hw, &lldp_cfg);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/i40e/i40e_dcb.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/i40e/i40e_dcb.h
@@ -32,6 +32,9 @@
 #define I40E_CEE_MAX_FEAT_TYPE		3
 #define I40E_LLDP_CURRENT_STATUS_XL710_OFFSET	0x2B
 #define I40E_LLDP_CURRENT_STATUS_X722_OFFSET	0x31
+#define I40E_LLDP_CURRENT_STATUS_OFFSET		1
+#define I40E_LLDP_CURRENT_STATUS_SIZE		1
+
 /* Defines for LLDP TLV header */
 #define I40E_LLDP_TLV_LEN_SHIFT		0
 #define I40E_LLDP_TLV_LEN_MASK		(0x01FF << I40E_LLDP_TLV_LEN_SHIFT)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
@@ -234,7 +234,7 @@
 		 (unsigned long int)vsi->net_stats_offsets.rx_compressed,
 		 (unsigned long int)vsi->net_stats_offsets.tx_compressed);
 	dev_info(&pf->pdev->dev,
-		 "    tx_restart = %d, tx_busy = %d, rx_buf_failed = %d, rx_page_failed = %d\n",
+		 "    tx_restart = %llu, tx_busy = %llu, rx_buf_failed = %llu, rx_page_failed = %llu\n",
 		 vsi->tx_restart, vsi->tx_busy,
 		 vsi->rx_buf_failed, vsi->rx_page_failed);
 	rcu_read_lock();
@@ -505,6 +505,14 @@
 		dev_info(&pf->pdev->dev, "vsi %d not found\n", vsi_seid);
 		return;
 	}
+	if (vsi->type != I40E_VSI_MAIN &&
+	    vsi->type != I40E_VSI_FDIR &&
+	    vsi->type != I40E_VSI_VMDQ2) {
+		dev_info(&pf->pdev->dev,
+			 "vsi %d type %d descriptor rings not available\n",
+			 vsi_seid, vsi->type);
+		return;
+	}
 	if (ring_id >= vsi->num_queue_pairs || ring_id < 0) {
 		dev_info(&pf->pdev->dev, "ring %d not found\n", ring_id);
 		return;
@@ -1755,7 +1763,7 @@
 void i40e_dbg_init(void)
 {
 	i40e_dbg_root = debugfs_create_dir(i40e_driver_name, NULL);
-	if (!i40e_dbg_root)
+	if (IS_ERR(i40e_dbg_root))
 		pr_info("init of debugfs failed\n");
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/i40e/i40e_devids.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/i40e/i40e_devids.h
@@ -23,6 +23,8 @@
 #define I40E_DEV_ID_10G_BASE_T_BC	0x15FF
 #define I40E_DEV_ID_10G_B		0x104F
 #define I40E_DEV_ID_10G_SFP		0x104E
+#define I40E_IS_X710TL_DEVICE(d) \
+	((d) == I40E_DEV_ID_10G_BASE_T_BC)
 #define I40E_DEV_ID_KX_X722		0x37CE
 #define I40E_DEV_ID_QSFP_X722		0x37CF
 #define I40E_DEV_ID_SFP_X722		0x37D0
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/i40e/i40e_diag.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/i40e/i40e_diag.c
@@ -44,7 +44,7 @@
 	return 0;
 }
 
-struct i40e_diag_reg_test_info i40e_reg_list[] = {
+const struct i40e_diag_reg_test_info i40e_reg_list[] = {
 	/* offset               mask         elements   stride */
 	{I40E_QTX_CTL(0),       0x0000FFBF, 1,
 		I40E_QTX_CTL(1) - I40E_QTX_CTL(0)},
@@ -78,27 +78,28 @@
 {
 	i40e_status ret_code = 0;
 	u32 reg, mask;
+	u32 elements;
 	u32 i, j;
 
 	for (i = 0; i40e_reg_list[i].offset != 0 &&
 					     !ret_code; i++) {
 
+		elements = i40e_reg_list[i].elements;
 		/* set actual reg range for dynamically allocated resources */
 		if (i40e_reg_list[i].offset == I40E_QTX_CTL(0) &&
 		    hw->func_caps.num_tx_qp != 0)
-			i40e_reg_list[i].elements = hw->func_caps.num_tx_qp;
+			elements = hw->func_caps.num_tx_qp;
 		if ((i40e_reg_list[i].offset == I40E_PFINT_ITRN(0, 0) ||
 		     i40e_reg_list[i].offset == I40E_PFINT_ITRN(1, 0) ||
 		     i40e_reg_list[i].offset == I40E_PFINT_ITRN(2, 0) ||
 		     i40e_reg_list[i].offset == I40E_QINT_TQCTL(0) ||
 		     i40e_reg_list[i].offset == I40E_QINT_RQCTL(0)) &&
 		    hw->func_caps.num_msix_vectors != 0)
-			i40e_reg_list[i].elements =
-				hw->func_caps.num_msix_vectors - 1;
+			elements = hw->func_caps.num_msix_vectors - 1;
 
 		/* test register access */
 		mask = i40e_reg_list[i].mask;
-		for (j = 0; j < i40e_reg_list[i].elements && !ret_code; j++) {
+		for (j = 0; j < elements && !ret_code; j++) {
 			reg = i40e_reg_list[i].offset +
 			      (j * i40e_reg_list[i].stride);
 			ret_code = i40e_diag_reg_pattern_test(hw, reg, mask);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/i40e/i40e_diag.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/i40e/i40e_diag.h
@@ -20,7 +20,7 @@
 	u32 stride;	/* bytes between each element */
 };
 
-extern struct i40e_diag_reg_test_info i40e_reg_list[];
+extern const struct i40e_diag_reg_test_info i40e_reg_list[];
 
 i40e_status i40e_diag_reg_test(struct i40e_hw *hw);
 i40e_status i40e_diag_eeprom_test(struct i40e_hw *hw);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
@@ -232,6 +232,8 @@
 	I40E_STAT(struct i40e_vsi, _name, _stat)
 #define I40E_VEB_STAT(_name, _stat) \
 	I40E_STAT(struct i40e_veb, _name, _stat)
+#define I40E_VEB_TC_STAT(_name, _stat) \
+	I40E_STAT(struct i40e_cp_veb_tc_stats, _name, _stat)
 #define I40E_PFC_STAT(_name, _stat) \
 	I40E_STAT(struct i40e_pfc_stats, _name, _stat)
 #define I40E_QUEUE_STAT(_name, _stat) \
@@ -266,11 +268,18 @@
 	I40E_VEB_STAT("veb.rx_unknown_protocol", stats.rx_unknown_protocol),
 };
 
+struct i40e_cp_veb_tc_stats {
+	u64 tc_rx_packets;
+	u64 tc_rx_bytes;
+	u64 tc_tx_packets;
+	u64 tc_tx_bytes;
+};
+
 static const struct i40e_stats i40e_gstrings_veb_tc_stats[] = {
-	I40E_VEB_STAT("veb.tc_%u_tx_packets", tc_stats.tc_tx_packets),
-	I40E_VEB_STAT("veb.tc_%u_tx_bytes", tc_stats.tc_tx_bytes),
-	I40E_VEB_STAT("veb.tc_%u_rx_packets", tc_stats.tc_rx_packets),
-	I40E_VEB_STAT("veb.tc_%u_rx_bytes", tc_stats.tc_rx_bytes),
+	I40E_VEB_TC_STAT("veb.tc_%u_tx_packets", tc_tx_packets),
+	I40E_VEB_TC_STAT("veb.tc_%u_tx_bytes", tc_tx_bytes),
+	I40E_VEB_TC_STAT("veb.tc_%u_rx_packets", tc_rx_packets),
+	I40E_VEB_TC_STAT("veb.tc_%u_rx_bytes", tc_rx_bytes),
 };
 
 static const struct i40e_stats i40e_gstrings_misc_stats[] = {
@@ -722,7 +731,14 @@
 	ethtool_link_ksettings_add_link_mode(ks, supported, FEC_RS);
 	ethtool_link_ksettings_add_link_mode(ks, supported, FEC_BASER);
 
-	if (I40E_AQ_SET_FEC_REQUEST_RS & req_fec_info) {
+	if ((I40E_AQ_SET_FEC_REQUEST_RS & req_fec_info) &&
+	    (I40E_AQ_SET_FEC_REQUEST_KR & req_fec_info)) {
+		ethtool_link_ksettings_add_link_mode(ks, advertising,
+						     FEC_NONE);
+		ethtool_link_ksettings_add_link_mode(ks, advertising,
+						     FEC_BASER);
+		ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_RS);
+	} else if (I40E_AQ_SET_FEC_REQUEST_RS & req_fec_info) {
 		ethtool_link_ksettings_add_link_mode(ks, advertising, FEC_RS);
 	} else if (I40E_AQ_SET_FEC_REQUEST_KR & req_fec_info) {
 		ethtool_link_ksettings_add_link_mode(ks, advertising,
@@ -730,12 +746,6 @@
 	} else {
 		ethtool_link_ksettings_add_link_mode(ks, advertising,
 						     FEC_NONE);
-		if (I40E_AQ_SET_FEC_AUTO & req_fec_info) {
-			ethtool_link_ksettings_add_link_mode(ks, advertising,
-							     FEC_RS);
-			ethtool_link_ksettings_add_link_mode(ks, advertising,
-							     FEC_BASER);
-		}
 	}
 }
 
@@ -829,8 +839,8 @@
 							     10000baseT_Full);
 		break;
 	case I40E_PHY_TYPE_10GBASE_T:
-	case I40E_PHY_TYPE_5GBASE_T:
-	case I40E_PHY_TYPE_2_5GBASE_T:
+	case I40E_PHY_TYPE_5GBASE_T_LINK_STATUS:
+	case I40E_PHY_TYPE_2_5GBASE_T_LINK_STATUS:
 	case I40E_PHY_TYPE_1000BASE_T:
 	case I40E_PHY_TYPE_100BASE_TX:
 		ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg);
@@ -967,7 +977,7 @@
 	default:
 		/* if we got here and link is up something bad is afoot */
 		netdev_info(netdev,
-			    "WARNING: Link is up but PHY type 0x%x is not recognized.\n",
+			    "WARNING: Link is up but PHY type 0x%x is not recognized, or incorrect cable is in use\n",
 			    hw_link_info->phy_type);
 	}
 
@@ -1097,6 +1107,7 @@
 
 	/* Set flow control settings */
 	ethtool_link_ksettings_add_link_mode(ks, supported, Pause);
+	ethtool_link_ksettings_add_link_mode(ks, supported, Asym_Pause);
 
 	switch (hw->fc.requested_mode) {
 	case I40E_FC_FULL:
@@ -1248,8 +1259,7 @@
 			if (ethtool_link_ksettings_test_link_mode(&safe_ks,
 								  supported,
 								  Autoneg) &&
-			    hw->phy.link_info.phy_type !=
-			    I40E_PHY_TYPE_10GBASE_T) {
+			    hw->phy.media_type != I40E_MEDIA_TYPE_BASET) {
 				netdev_info(netdev, "Autoneg cannot be disabled on this phy\n");
 				err = -EINVAL;
 				goto done;
@@ -1395,7 +1405,8 @@
 
 		memset(&config, 0, sizeof(config));
 		config.phy_type = abilities.phy_type;
-		config.abilities = abilities.abilities;
+		config.abilities = abilities.abilities |
+				   I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
 		config.phy_type_ext = abilities.phy_type_ext;
 		config.link_speed = abilities.link_speed;
 		config.eee_capability = abilities.eee_capability;
@@ -1437,6 +1448,7 @@
 	struct i40e_hw *hw = &pf->hw;
 	i40e_status status = 0;
 	int err = 0;
+	u8 fec_cfg;
 
 	/* Get the current phy config */
 	memset(&abilities, 0, sizeof(abilities));
@@ -1448,18 +1460,16 @@
 	}
 
 	fecparam->fec = 0;
-	if (abilities.fec_cfg_curr_mod_ext_info & I40E_AQ_SET_FEC_AUTO)
+	fec_cfg = abilities.fec_cfg_curr_mod_ext_info;
+	if (fec_cfg & I40E_AQ_SET_FEC_AUTO)
 		fecparam->fec |= ETHTOOL_FEC_AUTO;
-	if ((abilities.fec_cfg_curr_mod_ext_info &
-	     I40E_AQ_SET_FEC_REQUEST_RS) ||
-	    (abilities.fec_cfg_curr_mod_ext_info &
-	     I40E_AQ_SET_FEC_ABILITY_RS))
+	else if (fec_cfg & (I40E_AQ_SET_FEC_REQUEST_RS |
+		 I40E_AQ_SET_FEC_ABILITY_RS))
 		fecparam->fec |= ETHTOOL_FEC_RS;
-	if ((abilities.fec_cfg_curr_mod_ext_info &
-	     I40E_AQ_SET_FEC_REQUEST_KR) ||
-	    (abilities.fec_cfg_curr_mod_ext_info & I40E_AQ_SET_FEC_ABILITY_KR))
+	else if (fec_cfg & (I40E_AQ_SET_FEC_REQUEST_KR |
+		 I40E_AQ_SET_FEC_ABILITY_KR))
 		fecparam->fec |= ETHTOOL_FEC_BASER;
-	if (abilities.fec_cfg_curr_mod_ext_info == 0)
+	if (fec_cfg == 0)
 		fecparam->fec |= ETHTOOL_FEC_OFF;
 
 	if (hw->phy.link_info.fec_info & I40E_AQ_CONFIG_FEC_KR_ENA)
@@ -2213,6 +2223,29 @@
 }
 
 /**
+ * i40e_get_veb_tc_stats - copy VEB TC statistics to formatted structure
+ * @tc: the TC statistics in VEB structure (veb->tc_stats)
+ * @i: the index of traffic class in (veb->tc_stats) structure to copy
+ *
+ * Copy VEB TC statistics from structure of arrays (veb->tc_stats) to
+ * one dimensional structure i40e_cp_veb_tc_stats.
+ * Produce formatted i40e_cp_veb_tc_stats structure of the VEB TC
+ * statistics for the given TC.
+ **/
+static struct i40e_cp_veb_tc_stats
+i40e_get_veb_tc_stats(struct i40e_veb_tc_stats *tc, unsigned int i)
+{
+	struct i40e_cp_veb_tc_stats veb_tc = {
+		.tc_rx_packets = tc->tc_rx_packets[i],
+		.tc_rx_bytes = tc->tc_rx_bytes[i],
+		.tc_tx_packets = tc->tc_tx_packets[i],
+		.tc_tx_bytes = tc->tc_tx_bytes[i],
+	};
+
+	return veb_tc;
+}
+
+/**
  * i40e_get_pfc_stats - copy HW PFC statistics to formatted structure
  * @pf: the PF device structure
  * @i: the priority value to copy
@@ -2296,8 +2329,16 @@
 			       i40e_gstrings_veb_stats);
 
 	for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
-		i40e_add_ethtool_stats(&data, veb_stats ? veb : NULL,
-				       i40e_gstrings_veb_tc_stats);
+		if (veb_stats) {
+			struct i40e_cp_veb_tc_stats veb_tc =
+				i40e_get_veb_tc_stats(&veb->tc_stats, i);
+
+			i40e_add_ethtool_stats(&data, &veb_tc,
+					       i40e_gstrings_veb_tc_stats);
+		} else {
+			i40e_add_ethtool_stats(&data, NULL,
+					       i40e_gstrings_veb_tc_stats);
+		}
 
 	i40e_add_ethtool_stats(&data, pf, i40e_gstrings_stats);
 
@@ -2537,15 +2578,16 @@
 
 		set_bit(__I40E_TESTING, pf->state);
 
+		if (test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state) ||
+		    test_bit(__I40E_RESET_INTR_RECEIVED, pf->state)) {
+			dev_warn(&pf->pdev->dev,
+				 "Cannot start offline testing when PF is in reset state.\n");
+			goto skip_ol_tests;
+		}
+
 		if (i40e_active_vfs(pf) || i40e_active_vmdqs(pf)) {
 			dev_warn(&pf->pdev->dev,
 				 "Please take active VFs and Netqueues offline and restart the adapter before running NIC diagnostics\n");
-			data[I40E_ETH_TEST_REG]		= 1;
-			data[I40E_ETH_TEST_EEPROM]	= 1;
-			data[I40E_ETH_TEST_INTR]	= 1;
-			data[I40E_ETH_TEST_LINK]	= 1;
-			eth_test->flags |= ETH_TEST_FL_FAILED;
-			clear_bit(__I40E_TESTING, pf->state);
 			goto skip_ol_tests;
 		}
 
@@ -2592,9 +2634,17 @@
 		data[I40E_ETH_TEST_INTR] = 0;
 	}
 
-skip_ol_tests:
-
 	netif_info(pf, drv, netdev, "testing finished\n");
+	return;
+
+skip_ol_tests:
+	data[I40E_ETH_TEST_REG]		= 1;
+	data[I40E_ETH_TEST_EEPROM]	= 1;
+	data[I40E_ETH_TEST_INTR]	= 1;
+	data[I40E_ETH_TEST_LINK]	= 1;
+	eth_test->flags |= ETH_TEST_FL_FAILED;
+	clear_bit(__I40E_TESTING, pf->state);
+	netif_info(pf, drv, netdev, "testing failed\n");
 }
 
 static void i40e_get_wol(struct net_device *netdev,
@@ -3032,10 +3082,17 @@
 
 		if (cmd->flow_type == TCP_V4_FLOW ||
 		    cmd->flow_type == UDP_V4_FLOW) {
-			if (i_set & I40E_L3_SRC_MASK)
-				cmd->data |= RXH_IP_SRC;
-			if (i_set & I40E_L3_DST_MASK)
-				cmd->data |= RXH_IP_DST;
+			if (hw->mac.type == I40E_MAC_X722) {
+				if (i_set & I40E_X722_L3_SRC_MASK)
+					cmd->data |= RXH_IP_SRC;
+				if (i_set & I40E_X722_L3_DST_MASK)
+					cmd->data |= RXH_IP_DST;
+			} else {
+				if (i_set & I40E_L3_SRC_MASK)
+					cmd->data |= RXH_IP_SRC;
+				if (i_set & I40E_L3_DST_MASK)
+					cmd->data |= RXH_IP_DST;
+			}
 		} else if (cmd->flow_type == TCP_V6_FLOW ||
 			  cmd->flow_type == UDP_V6_FLOW) {
 			if (i_set & I40E_L3_V6_SRC_MASK)
@@ -3342,12 +3399,15 @@
 
 /**
  * i40e_get_rss_hash_bits - Read RSS Hash bits from register
+ * @hw: hw structure
  * @nfc: pointer to user request
  * @i_setc: bits currently set
  *
  * Returns value of bits to be set per user request
  **/
-static u64 i40e_get_rss_hash_bits(struct ethtool_rxnfc *nfc, u64 i_setc)
+static u64 i40e_get_rss_hash_bits(struct i40e_hw *hw,
+				  struct ethtool_rxnfc *nfc,
+				  u64 i_setc)
 {
 	u64 i_set = i_setc;
 	u64 src_l3 = 0, dst_l3 = 0;
@@ -3366,8 +3426,13 @@
 		dst_l3 = I40E_L3_V6_DST_MASK;
 	} else if (nfc->flow_type == TCP_V4_FLOW ||
 		  nfc->flow_type == UDP_V4_FLOW) {
-		src_l3 = I40E_L3_SRC_MASK;
-		dst_l3 = I40E_L3_DST_MASK;
+		if (hw->mac.type == I40E_MAC_X722) {
+			src_l3 = I40E_X722_L3_SRC_MASK;
+			dst_l3 = I40E_X722_L3_DST_MASK;
+		} else {
+			src_l3 = I40E_L3_SRC_MASK;
+			dst_l3 = I40E_L3_DST_MASK;
+		}
 	} else {
 		/* Any other flow type are not supported here */
 		return i_set;
@@ -3385,6 +3450,7 @@
 	return i_set;
 }
 
+#define FLOW_PCTYPES_SIZE 64
 /**
  * i40e_set_rss_hash_opt - Enable/Disable flow types for RSS hash
  * @pf: pointer to the physical function struct
@@ -3397,9 +3463,11 @@
 	struct i40e_hw *hw = &pf->hw;
 	u64 hena = (u64)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(0)) |
 		   ((u64)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(1)) << 32);
-	u8 flow_pctype = 0;
+	DECLARE_BITMAP(flow_pctypes, FLOW_PCTYPES_SIZE);
 	u64 i_set, i_setc;
 
+	bitmap_zero(flow_pctypes, FLOW_PCTYPES_SIZE);
+
 	if (pf->flags & I40E_FLAG_MFP_ENABLED) {
 		dev_err(&pf->pdev->dev,
 			"Change of RSS hash input set is not supported when MFP mode is enabled\n");
@@ -3415,36 +3483,35 @@
 
 	switch (nfc->flow_type) {
 	case TCP_V4_FLOW:
-		flow_pctype = I40E_FILTER_PCTYPE_NONF_IPV4_TCP;
+		set_bit(I40E_FILTER_PCTYPE_NONF_IPV4_TCP, flow_pctypes);
 		if (pf->hw_features & I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE)
-			hena |=
-			  BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK);
+			set_bit(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK,
+				flow_pctypes);
 		break;
 	case TCP_V6_FLOW:
-		flow_pctype = I40E_FILTER_PCTYPE_NONF_IPV6_TCP;
+		set_bit(I40E_FILTER_PCTYPE_NONF_IPV6_TCP, flow_pctypes);
 		if (pf->hw_features & I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE)
-			hena |=
-			  BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK);
-		if (pf->hw_features & I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE)
-			hena |=
-			  BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK);
+			set_bit(I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK,
+				flow_pctypes);
 		break;
 	case UDP_V4_FLOW:
-		flow_pctype = I40E_FILTER_PCTYPE_NONF_IPV4_UDP;
-		if (pf->hw_features & I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE)
-			hena |=
-			  BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) |
-			  BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP);
-
+		set_bit(I40E_FILTER_PCTYPE_NONF_IPV4_UDP, flow_pctypes);
+		if (pf->hw_features & I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE) {
+			set_bit(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP,
+				flow_pctypes);
+			set_bit(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP,
+				flow_pctypes);
+		}
 		hena |= BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4);
 		break;
 	case UDP_V6_FLOW:
-		flow_pctype = I40E_FILTER_PCTYPE_NONF_IPV6_UDP;
-		if (pf->hw_features & I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE)
-			hena |=
-			  BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) |
-			  BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP);
-
+		set_bit(I40E_FILTER_PCTYPE_NONF_IPV6_UDP, flow_pctypes);
+		if (pf->hw_features & I40E_HW_MULTIPLE_TCP_UDP_RSS_PCTYPE) {
+			set_bit(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP,
+				flow_pctypes);
+			set_bit(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP,
+				flow_pctypes);
+		}
 		hena |= BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6);
 		break;
 	case AH_ESP_V4_FLOW:
@@ -3477,17 +3544,20 @@
 		return -EINVAL;
 	}
 
-	if (flow_pctype) {
-		i_setc = (u64)i40e_read_rx_ctl(hw, I40E_GLQF_HASH_INSET(0,
-					       flow_pctype)) |
-			((u64)i40e_read_rx_ctl(hw, I40E_GLQF_HASH_INSET(1,
-					       flow_pctype)) << 32);
-		i_set = i40e_get_rss_hash_bits(nfc, i_setc);
-		i40e_write_rx_ctl(hw, I40E_GLQF_HASH_INSET(0, flow_pctype),
-				  (u32)i_set);
-		i40e_write_rx_ctl(hw, I40E_GLQF_HASH_INSET(1, flow_pctype),
-				  (u32)(i_set >> 32));
-		hena |= BIT_ULL(flow_pctype);
+	if (bitmap_weight(flow_pctypes, FLOW_PCTYPES_SIZE)) {
+		u8 flow_id;
+
+		for_each_set_bit(flow_id, flow_pctypes, FLOW_PCTYPES_SIZE) {
+			i_setc = (u64)i40e_read_rx_ctl(hw, I40E_GLQF_HASH_INSET(0, flow_id)) |
+				 ((u64)i40e_read_rx_ctl(hw, I40E_GLQF_HASH_INSET(1, flow_id)) << 32);
+			i_set = i40e_get_rss_hash_bits(&pf->hw, nfc, i_setc);
+
+			i40e_write_rx_ctl(hw, I40E_GLQF_HASH_INSET(0, flow_id),
+					  (u32)i_set);
+			i40e_write_rx_ctl(hw, I40E_GLQF_HASH_INSET(1, flow_id),
+					  (u32)(i_set >> 32));
+			hena |= BIT_ULL(flow_id);
+		}
 	}
 
 	i40e_write_rx_ctl(hw, I40E_PFQF_HENA(0), (u32)hena);
@@ -4163,11 +4233,7 @@
 			return -EOPNOTSUPP;
 
 		/* First 4 bytes of L4 header */
-		if (usr_ip4_spec->l4_4_bytes == htonl(0xFFFFFFFF))
-			new_mask |= I40E_L4_SRC_MASK | I40E_L4_DST_MASK;
-		else if (!usr_ip4_spec->l4_4_bytes)
-			new_mask &= ~(I40E_L4_SRC_MASK | I40E_L4_DST_MASK);
-		else
+		if (usr_ip4_spec->l4_4_bytes)
 			return -EOPNOTSUPP;
 
 		/* Filtering on Type of Service is not supported. */
@@ -4874,7 +4940,7 @@
 	enum i40e_admin_queue_err adq_err;
 	struct i40e_vsi *vsi = np->vsi;
 	struct i40e_pf *pf = vsi->back;
-	bool is_reset_needed;
+	u32 reset_needed = 0;
 	i40e_status status;
 	u32 i, j;
 
@@ -4919,9 +4985,11 @@
 flags_complete:
 	changed_flags = orig_flags ^ new_flags;
 
-	is_reset_needed = !!(changed_flags & (I40E_FLAG_VEB_STATS_ENABLED |
-		I40E_FLAG_LEGACY_RX | I40E_FLAG_SOURCE_PRUNING_DISABLED |
-		I40E_FLAG_DISABLE_FW_LLDP));
+	if (changed_flags & I40E_FLAG_DISABLE_FW_LLDP)
+		reset_needed = I40E_PF_RESET_AND_REBUILD_FLAG;
+	if (changed_flags & (I40E_FLAG_VEB_STATS_ENABLED |
+	    I40E_FLAG_LEGACY_RX | I40E_FLAG_SOURCE_PRUNING_DISABLED))
+		reset_needed = BIT(__I40E_PF_RESET_REQUESTED);
 
 	/* Before we finalize any flag changes, we need to perform some
 	 * checks to ensure that the changes are supported and safe.
@@ -5038,12 +5106,16 @@
 				case I40E_AQ_RC_EEXIST:
 					dev_warn(&pf->pdev->dev,
 						 "FW LLDP agent is already running\n");
-					is_reset_needed = false;
+					reset_needed = 0;
 					break;
 				case I40E_AQ_RC_EPERM:
 					dev_warn(&pf->pdev->dev,
 						 "Device configuration forbids SW from starting the LLDP agent.\n");
 					return -EINVAL;
+				case I40E_AQ_RC_EAGAIN:
+					dev_warn(&pf->pdev->dev,
+						 "Stop FW LLDP agent command is still being processed, please try again in a second.\n");
+					return -EBUSY;
 				default:
 					dev_warn(&pf->pdev->dev,
 						 "Starting FW LLDP agent failed: error: %s, %s\n",
@@ -5067,8 +5139,8 @@
 	/* Issue reset to cause things to take effect, as additional bits
 	 * are added we will need to create a mask of bits requiring reset
 	 */
-	if (is_reset_needed)
-		i40e_do_reset(pf, BIT(__I40E_PF_RESET_REQUESTED), true);
+	if (reset_needed)
+		i40e_do_reset(pf, reset_needed, true);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -44,6 +44,8 @@
 static void i40e_determine_queue_usage(struct i40e_pf *pf);
 static int i40e_setup_pf_filter_control(struct i40e_pf *pf);
 static void i40e_prep_for_reset(struct i40e_pf *pf, bool lock_acquired);
+static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit,
+				   bool lock_acquired);
 static int i40e_reset(struct i40e_pf *pf);
 static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired);
 static int i40e_setup_misc_vector_for_recovery_mode(struct i40e_pf *pf);
@@ -105,6 +107,30 @@
 
 static struct workqueue_struct *i40e_wq;
 
+static void netdev_hw_addr_refcnt(struct i40e_mac_filter *f,
+				  struct net_device *netdev, int delta)
+{
+	struct netdev_hw_addr_list *ha_list;
+	struct netdev_hw_addr *ha;
+
+	if (!f || !netdev)
+		return;
+
+	if (is_unicast_ether_addr(f->macaddr) || is_link_local_ether_addr(f->macaddr))
+		ha_list = &netdev->uc;
+	else
+		ha_list = &netdev->mc;
+
+	netdev_hw_addr_list_for_each(ha, ha_list) {
+		if (ether_addr_equal(ha->addr, f->macaddr)) {
+			ha->refcount += delta;
+			if (ha->refcount <= 0)
+				ha->refcount = 1;
+			break;
+		}
+	}
+}
+
 /**
  * i40e_allocate_dma_mem_d - OS specific memory alloc for shared code
  * @hw:   pointer to the HW structure
@@ -184,10 +210,6 @@
  * @id: an owner id to stick on the items assigned
  *
  * Returns the base item index of the lump, or negative for error
- *
- * The search_hint trick and lack of advanced fit-finding only work
- * because we're highly likely to have all the same size lump requests.
- * Linear search time and any fragmentation should be minimal.
  **/
 static int i40e_get_lump(struct i40e_pf *pf, struct i40e_lump_tracking *pile,
 			 u16 needed, u16 id)
@@ -202,8 +224,21 @@
 		return -EINVAL;
 	}
 
-	/* start the linear search with an imperfect hint */
-	i = pile->search_hint;
+	/* Allocate last queue in the pile for FDIR VSI queue
+	 * so it doesn't fragment the qp_pile
+	 */
+	if (pile == pf->qp_pile && pf->vsi[id]->type == I40E_VSI_FDIR) {
+		if (pile->list[pile->num_entries - 1] & I40E_PILE_VALID_BIT) {
+			dev_err(&pf->pdev->dev,
+				"Cannot allocate queue %d for I40E_VSI_FDIR\n",
+				pile->num_entries - 1);
+			return -ENOMEM;
+		}
+		pile->list[pile->num_entries - 1] = id | I40E_PILE_VALID_BIT;
+		return pile->num_entries - 1;
+	}
+
+	i = 0;
 	while (i < pile->num_entries) {
 		/* skip already allocated entries */
 		if (pile->list[i] & I40E_PILE_VALID_BIT) {
@@ -222,7 +257,6 @@
 			for (j = 0; j < needed; j++)
 				pile->list[i+j] = id | I40E_PILE_VALID_BIT;
 			ret = i;
-			pile->search_hint = i + j;
 			break;
 		}
 
@@ -245,7 +279,7 @@
 {
 	int valid_id = (id | I40E_PILE_VALID_BIT);
 	int count = 0;
-	int i;
+	u16 i;
 
 	if (!pile || index >= pile->num_entries)
 		return -EINVAL;
@@ -257,8 +291,6 @@
 		count++;
 	}
 
-	if (count && index < pile->search_hint)
-		pile->search_hint = index;
 
 	return count;
 }
@@ -383,7 +415,9 @@
 		set_bit(__I40E_GLOBAL_RESET_REQUESTED, pf->state);
 		break;
 	default:
-		netdev_err(netdev, "tx_timeout recovery unsuccessful\n");
+		netdev_err(netdev, "tx_timeout recovery unsuccessful, device is in non-recoverable state.\n");
+		set_bit(__I40E_DOWN_REQUESTED, pf->state);
+		set_bit(__I40E_VSI_DOWN_REQUESTED, vsi->state);
 		break;
 	}
 
@@ -458,11 +492,15 @@
 		i40e_get_netdev_stats_struct_tx(ring, stats);
 
 		if (i40e_enabled_xdp_vsi(vsi)) {
-			ring++;
+			ring = READ_ONCE(vsi->xdp_rings[i]);
+			if (!ring)
+				continue;
 			i40e_get_netdev_stats_struct_tx(ring, stats);
 		}
 
-		ring++;
+		ring = READ_ONCE(vsi->rx_rings[i]);
+		if (!ring)
+			continue;
 		do {
 			start   = u64_stats_fetch_begin_irq(&ring->syncp);
 			packets = ring->stats.packets;
@@ -774,9 +812,9 @@
 	struct rtnl_link_stats64 *ns;   /* netdev stats */
 	struct i40e_eth_stats *oes;
 	struct i40e_eth_stats *es;     /* device's eth stats */
-	u32 tx_restart, tx_busy;
+	u64 tx_restart, tx_busy;
 	struct i40e_ring *p;
-	u32 rx_page, rx_buf;
+	u64 rx_page, rx_buf;
 	u64 bytes, packets;
 	unsigned int start;
 	u64 tx_linearize;
@@ -806,6 +844,8 @@
 	for (q = 0; q < vsi->num_queue_pairs; q++) {
 		/* locate Tx ring */
 		p = READ_ONCE(vsi->tx_rings[q]);
+		if (!p)
+			continue;
 
 		do {
 			start = u64_stats_fetch_begin_irq(&p->syncp);
@@ -819,8 +859,11 @@
 		tx_linearize += p->tx_stats.tx_linearize;
 		tx_force_wb += p->tx_stats.tx_force_wb;
 
-		/* Rx queue is part of the same block as Tx queue */
-		p = &p[1];
+		/* locate Rx ring */
+		p = READ_ONCE(vsi->rx_rings[q]);
+		if (!p)
+			continue;
+
 		do {
 			start = u64_stats_fetch_begin_irq(&p->syncp);
 			packets = p->stats.packets;
@@ -1110,6 +1153,25 @@
 }
 
 /**
+ * i40e_count_filters - counts VSI mac filters
+ * @vsi: the VSI to be searched
+ *
+ * Returns count of mac filters
+ **/
+int i40e_count_filters(struct i40e_vsi *vsi)
+{
+	struct i40e_mac_filter *f;
+	struct hlist_node *h;
+	int bkt;
+	int cnt = 0;
+
+	hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist)
+		++cnt;
+
+	return cnt;
+}
+
+/**
  * i40e_find_filter - Search VSI filter list for specific mac/vlan filter
  * @vsi: the VSI to be searched
  * @macaddr: the MAC address
@@ -1765,6 +1827,7 @@
 				     bool is_add)
 {
 	struct i40e_pf *pf = vsi->back;
+	u16 num_tc_qps = 0;
 	u16 sections = 0;
 	u8 netdev_tc = 0;
 	u16 numtc = 1;
@@ -1772,13 +1835,37 @@
 	u8 offset;
 	u16 qmap;
 	int i;
-	u16 num_tc_qps = 0;
 
 	sections = I40E_AQ_VSI_PROP_QUEUE_MAP_VALID;
 	offset = 0;
+	/* zero out queue mapping, it will get updated on the end of the function */
+	memset(ctxt->info.queue_mapping, 0, sizeof(ctxt->info.queue_mapping));
+
+	if (vsi->type == I40E_VSI_MAIN) {
+		/* This code helps add more queue to the VSI if we have
+		 * more cores than RSS can support, the higher cores will
+		 * be served by ATR or other filters. Furthermore, the
+		 * non-zero req_queue_pairs says that user requested a new
+		 * queue count via ethtool's set_channels, so use this
+		 * value for queues distribution across traffic classes
+		 * We need at least one queue pair for the interface
+		 * to be usable as we see in else statement.
+		 */
+		if (vsi->req_queue_pairs > 0)
+			vsi->num_queue_pairs = vsi->req_queue_pairs;
+		else if (pf->flags & I40E_FLAG_MSIX_ENABLED)
+			vsi->num_queue_pairs = pf->num_lan_msix;
+		else
+			vsi->num_queue_pairs = 1;
+	}
 
 	/* Number of queues per enabled TC */
-	num_tc_qps = vsi->alloc_queue_pairs;
+	if (vsi->type == I40E_VSI_MAIN ||
+	    (vsi->type == I40E_VSI_SRIOV && vsi->num_queue_pairs != 0))
+		num_tc_qps = vsi->num_queue_pairs;
+	else
+		num_tc_qps = vsi->alloc_queue_pairs;
+
 	if (enabled_tc && (vsi->back->flags & I40E_FLAG_DCB_ENABLED)) {
 		/* Find numtc from enabled TC bitmap */
 		for (i = 0, numtc = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
@@ -1856,15 +1943,11 @@
 		}
 		ctxt->info.tc_mapping[i] = cpu_to_le16(qmap);
 	}
-
-	/* Set actual Tx/Rx queue pairs */
-	vsi->num_queue_pairs = offset;
-	if ((vsi->type == I40E_VSI_MAIN) && (numtc == 1)) {
-		if (vsi->req_queue_pairs > 0)
-			vsi->num_queue_pairs = vsi->req_queue_pairs;
-		else if (pf->flags & I40E_FLAG_MSIX_ENABLED)
-			vsi->num_queue_pairs = pf->num_lan_msix;
-	}
+	/* Do not change previously set num_queue_pairs for PFs and VFs*/
+	if ((vsi->type == I40E_VSI_MAIN && numtc != 1) ||
+	    (vsi->type == I40E_VSI_SRIOV && vsi->num_queue_pairs == 0) ||
+	    (vsi->type != I40E_VSI_MAIN && vsi->type != I40E_VSI_SRIOV))
+		vsi->num_queue_pairs = offset;
 
 	/* Scheduler section valid can only be set for ADD VSI */
 	if (is_add) {
@@ -1994,6 +2077,7 @@
 	hlist_for_each_entry_safe(new, h, from, hlist) {
 		/* We can simply free the wrapper structure */
 		hlist_del(&new->hlist);
+		netdev_hw_addr_refcnt(new->f, vsi->netdev, -1);
 		kfree(new);
 	}
 }
@@ -2341,6 +2425,10 @@
 						       &tmp_add_list,
 						       &tmp_del_list,
 						       vlan_filters);
+
+		hlist_for_each_entry(new, &tmp_add_list, hlist)
+			netdev_hw_addr_refcnt(new->f, vsi->netdev, 1);
+
 		if (retval)
 			goto err_no_memory_locked;
 
@@ -2473,6 +2561,7 @@
 			if (new->f->state == I40E_FILTER_NEW)
 				new->f->state = new->state;
 			hlist_del(&new->hlist);
+			netdev_hw_addr_refcnt(new->f, vsi->netdev, -1);
 			kfree(new);
 		}
 		spin_unlock_bh(&vsi->mac_filter_hash_lock);
@@ -2536,8 +2625,7 @@
 				 i40e_stat_str(hw, aq_ret),
 				 i40e_aq_str(hw, hw->aq.asq_last_status));
 		} else {
-			dev_info(&pf->pdev->dev, "%s is %s allmulti mode.\n",
-				 vsi->netdev->name,
+			dev_info(&pf->pdev->dev, "%s allmulti mode.\n",
 				 cur_multipromisc ? "entering" : "leaving");
 		}
 	}
@@ -2592,14 +2680,15 @@
 		return;
 	if (!test_and_clear_bit(__I40E_MACVLAN_SYNC_PENDING, pf->state))
 		return;
-	if (test_and_set_bit(__I40E_VF_DISABLE, pf->state)) {
+	if (test_bit(__I40E_VF_DISABLE, pf->state)) {
 		set_bit(__I40E_MACVLAN_SYNC_PENDING, pf->state);
 		return;
 	}
 
 	for (v = 0; v < pf->num_alloc_vsi; v++) {
 		if (pf->vsi[v] &&
-		    (pf->vsi[v]->flags & I40E_VSI_FLAG_FILTER_CHANGED)) {
+		    (pf->vsi[v]->flags & I40E_VSI_FLAG_FILTER_CHANGED) &&
+		    !test_bit(__I40E_VSI_RELEASING, pf->vsi[v]->state)) {
 			int ret = i40e_sync_vsi_filters(pf->vsi[v]);
 
 			if (ret) {
@@ -2610,7 +2699,6 @@
 			}
 		}
 	}
-	clear_bit(__I40E_VF_DISABLE, pf->state);
 }
 
 /**
@@ -2639,7 +2727,7 @@
 	struct i40e_pf *pf = vsi->back;
 
 	if (i40e_enabled_xdp_vsi(vsi)) {
-		int frame_size = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
+		int frame_size = new_mtu + I40E_PACKET_HDR_PAD;
 
 		if (frame_size > i40e_max_xdp_frame_size(vsi))
 			return -EINVAL;
@@ -3534,14 +3622,14 @@
 		q_vector->rx.target_itr =
 			ITR_TO_REG(vsi->rx_rings[i]->itr_setting);
 		wr32(hw, I40E_PFINT_ITRN(I40E_RX_ITR, vector - 1),
-		     q_vector->rx.target_itr);
+		     q_vector->rx.target_itr >> 1);
 		q_vector->rx.current_itr = q_vector->rx.target_itr;
 
 		q_vector->tx.next_update = jiffies + 1;
 		q_vector->tx.target_itr =
 			ITR_TO_REG(vsi->tx_rings[i]->itr_setting);
 		wr32(hw, I40E_PFINT_ITRN(I40E_TX_ITR, vector - 1),
-		     q_vector->tx.target_itr);
+		     q_vector->tx.target_itr >> 1);
 		q_vector->tx.current_itr = q_vector->tx.target_itr;
 
 		wr32(hw, I40E_PFINT_RATEN(vector - 1),
@@ -3646,11 +3734,11 @@
 	/* set the ITR configuration */
 	q_vector->rx.next_update = jiffies + 1;
 	q_vector->rx.target_itr = ITR_TO_REG(vsi->rx_rings[0]->itr_setting);
-	wr32(hw, I40E_PFINT_ITR0(I40E_RX_ITR), q_vector->rx.target_itr);
+	wr32(hw, I40E_PFINT_ITR0(I40E_RX_ITR), q_vector->rx.target_itr >> 1);
 	q_vector->rx.current_itr = q_vector->rx.target_itr;
 	q_vector->tx.next_update = jiffies + 1;
 	q_vector->tx.target_itr = ITR_TO_REG(vsi->tx_rings[0]->itr_setting);
-	wr32(hw, I40E_PFINT_ITR0(I40E_TX_ITR), q_vector->tx.target_itr);
+	wr32(hw, I40E_PFINT_ITR0(I40E_TX_ITR), q_vector->tx.target_itr >> 1);
 	q_vector->tx.current_itr = q_vector->tx.target_itr;
 
 	i40e_enable_misc_int_causes(pf);
@@ -3979,8 +4067,16 @@
 	}
 
 	if (icr0 & I40E_PFINT_ICR0_VFLR_MASK) {
-		ena_mask &= ~I40E_PFINT_ICR0_ENA_VFLR_MASK;
-		set_bit(__I40E_VFLR_EVENT_PENDING, pf->state);
+		/* disable any further VFLR event notifications */
+		if (test_bit(__I40E_VF_RESETS_DISABLED, pf->state)) {
+			u32 reg = rd32(hw, I40E_PFINT_ICR0_ENA);
+
+			reg &= ~I40E_PFINT_ICR0_VFLR_MASK;
+			wr32(hw, I40E_PFINT_ICR0_ENA, reg);
+		} else {
+			ena_mask &= ~I40E_PFINT_ICR0_ENA_VFLR_MASK;
+			set_bit(__I40E_VFLR_EVENT_PENDING, pf->state);
+		}
 	}
 
 	if (icr0 & I40E_PFINT_ICR0_GRST_MASK) {
@@ -4386,11 +4482,10 @@
 }
 
 /**
- * i40e_vsi_control_tx - Start or stop a VSI's rings
+ * i40e_vsi_enable_tx - Start a VSI's rings
  * @vsi: the VSI being configured
- * @enable: start or stop the rings
  **/
-static int i40e_vsi_control_tx(struct i40e_vsi *vsi, bool enable)
+static int i40e_vsi_enable_tx(struct i40e_vsi *vsi)
 {
 	struct i40e_pf *pf = vsi->back;
 	int i, pf_q, ret = 0;
@@ -4399,7 +4494,7 @@
 	for (i = 0; i < vsi->num_queue_pairs; i++, pf_q++) {
 		ret = i40e_control_wait_tx_q(vsi->seid, pf,
 					     pf_q,
-					     false /*is xdp*/, enable);
+					     false /*is xdp*/, true);
 		if (ret)
 			break;
 
@@ -4408,7 +4503,7 @@
 
 		ret = i40e_control_wait_tx_q(vsi->seid, pf,
 					     pf_q + vsi->alloc_queue_pairs,
-					     true /*is xdp*/, enable);
+					     true /*is xdp*/, true);
 		if (ret)
 			break;
 	}
@@ -4506,32 +4601,25 @@
 }
 
 /**
- * i40e_vsi_control_rx - Start or stop a VSI's rings
+ * i40e_vsi_enable_rx - Start a VSI's rings
  * @vsi: the VSI being configured
- * @enable: start or stop the rings
  **/
-static int i40e_vsi_control_rx(struct i40e_vsi *vsi, bool enable)
+static int i40e_vsi_enable_rx(struct i40e_vsi *vsi)
 {
 	struct i40e_pf *pf = vsi->back;
 	int i, pf_q, ret = 0;
 
 	pf_q = vsi->base_queue;
 	for (i = 0; i < vsi->num_queue_pairs; i++, pf_q++) {
-		ret = i40e_control_wait_rx_q(pf, pf_q, enable);
+		ret = i40e_control_wait_rx_q(pf, pf_q, true);
 		if (ret) {
 			dev_info(&pf->pdev->dev,
-				 "VSI seid %d Rx ring %d %sable timeout\n",
-				 vsi->seid, pf_q, (enable ? "en" : "dis"));
+				 "VSI seid %d Rx ring %d enable timeout\n",
+				 vsi->seid, pf_q);
 			break;
 		}
 	}
 
-	/* Due to HW errata, on Rx disable only, the register can indicate done
-	 * before it really is. Needs 50ms to be sure
-	 */
-	if (!enable)
-		mdelay(50);
-
 	return ret;
 }
 
@@ -4544,29 +4632,47 @@
 	int ret = 0;
 
 	/* do rx first for enable and last for disable */
-	ret = i40e_vsi_control_rx(vsi, true);
+	ret = i40e_vsi_enable_rx(vsi);
 	if (ret)
 		return ret;
-	ret = i40e_vsi_control_tx(vsi, true);
+	ret = i40e_vsi_enable_tx(vsi);
 
 	return ret;
 }
 
+#define I40E_DISABLE_TX_GAP_MSEC	50
+
 /**
  * i40e_vsi_stop_rings - Stop a VSI's rings
  * @vsi: the VSI being configured
  **/
 void i40e_vsi_stop_rings(struct i40e_vsi *vsi)
 {
+	struct i40e_pf *pf = vsi->back;
+	int pf_q, err, q_end;
+
 	/* When port TX is suspended, don't wait */
 	if (test_bit(__I40E_PORT_SUSPENDED, vsi->back->state))
 		return i40e_vsi_stop_rings_no_wait(vsi);
 
-	/* do rx first for enable and last for disable
-	 * Ignore return value, we need to shutdown whatever we can
-	 */
-	i40e_vsi_control_tx(vsi, false);
-	i40e_vsi_control_rx(vsi, false);
+	q_end = vsi->base_queue + vsi->num_queue_pairs;
+	for (pf_q = vsi->base_queue; pf_q < q_end; pf_q++)
+		i40e_pre_tx_queue_cfg(&pf->hw, (u32)pf_q, false);
+
+	for (pf_q = vsi->base_queue; pf_q < q_end; pf_q++) {
+		err = i40e_control_wait_rx_q(pf, pf_q, false);
+		if (err)
+			dev_info(&pf->pdev->dev,
+				 "VSI seid %d Rx ring %d dissable timeout\n",
+				 vsi->seid, pf_q);
+	}
+
+	msleep(I40E_DISABLE_TX_GAP_MSEC);
+	pf_q = vsi->base_queue;
+	for (pf_q = vsi->base_queue; pf_q < q_end; pf_q++)
+		wr32(&pf->hw, I40E_QTX_ENA(pf_q), 0);
+
+	i40e_vsi_wait_queues_disabled(vsi);
 }
 
 /**
@@ -4790,7 +4896,8 @@
 {
 	int i;
 
-	i40e_free_misc_vector(pf);
+	if (test_bit(__I40E_MISC_IRQ_REQUESTED, pf->state))
+		i40e_free_misc_vector(pf);
 
 	i40e_put_lump(pf->irq_pile, pf->iwarp_base_vector,
 		      I40E_IWARP_IRQ_PILE_ID);
@@ -4977,7 +5084,7 @@
 {
 	int v, ret = 0;
 
-	for (v = 0; v < pf->hw.func_caps.num_vsis; v++) {
+	for (v = 0; v < pf->num_alloc_vsi; v++) {
 		if (pf->vsi[v]) {
 			ret = i40e_vsi_wait_queues_disabled(pf->vsi[v]);
 			if (ret)
@@ -5344,6 +5451,58 @@
 }
 
 /**
+ * i40e_update_adq_vsi_queues - update queue mapping for ADq VSI
+ * @vsi: the VSI being reconfigured
+ * @vsi_offset: offset from main VF VSI
+ */
+int i40e_update_adq_vsi_queues(struct i40e_vsi *vsi, int vsi_offset)
+{
+	struct i40e_vsi_context ctxt = {};
+	struct i40e_pf *pf;
+	struct i40e_hw *hw;
+	int ret;
+
+	if (!vsi)
+		return I40E_ERR_PARAM;
+	pf = vsi->back;
+	hw = &pf->hw;
+
+	ctxt.seid = vsi->seid;
+	ctxt.pf_num = hw->pf_id;
+	ctxt.vf_num = vsi->vf_id + hw->func_caps.vf_base_id + vsi_offset;
+	ctxt.uplink_seid = vsi->uplink_seid;
+	ctxt.connection_type = I40E_AQ_VSI_CONN_TYPE_NORMAL;
+	ctxt.flags = I40E_AQ_VSI_TYPE_VF;
+	ctxt.info = vsi->info;
+
+	i40e_vsi_setup_queue_map(vsi, &ctxt, vsi->tc_config.enabled_tc,
+				 false);
+	if (vsi->reconfig_rss) {
+		vsi->rss_size = min_t(int, pf->alloc_rss_size,
+				      vsi->num_queue_pairs);
+		ret = i40e_vsi_config_rss(vsi);
+		if (ret) {
+			dev_info(&pf->pdev->dev, "Failed to reconfig rss for num_queues\n");
+			return ret;
+		}
+		vsi->reconfig_rss = false;
+	}
+
+	ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
+	if (ret) {
+		dev_info(&pf->pdev->dev, "Update vsi config failed, err %s aq_err %s\n",
+			 i40e_stat_str(hw, ret),
+			 i40e_aq_str(hw, hw->aq.asq_last_status));
+		return ret;
+	}
+	/* update the local VSI info with updated queue map */
+	i40e_vsi_update_queue_map(vsi, &ctxt);
+	vsi->info.valid_sections = 0;
+
+	return ret;
+}
+
+/**
  * i40e_vsi_config_tc - Configure VSI Tx Scheduler for given TC map
  * @vsi: VSI to be configured
  * @enabled_tc: TC bitmap
@@ -5505,6 +5664,26 @@
 }
 
 /**
+ * i40e_bw_bytes_to_mbits - Convert max_tx_rate from bytes to mbits
+ * @vsi: Pointer to vsi structure
+ * @max_tx_rate: max TX rate in bytes to be converted into Mbits
+ *
+ * Helper function to convert units before send to set BW limit
+ **/
+static u64 i40e_bw_bytes_to_mbits(struct i40e_vsi *vsi, u64 max_tx_rate)
+{
+	if (max_tx_rate < I40E_BW_MBPS_DIVISOR) {
+		dev_warn(&vsi->back->pdev->dev,
+			 "Setting max tx rate to minimum usable value of 50Mbps.\n");
+		max_tx_rate = I40E_BW_CREDIT_DIVISOR;
+	} else {
+		do_div(max_tx_rate, I40E_BW_MBPS_DIVISOR);
+	}
+
+	return max_tx_rate;
+}
+
+/**
  * i40e_set_bw_limit - setup BW limit for Tx traffic based on max_tx_rate
  * @vsi: VSI to be configured
  * @seid: seid of the channel/VSI
@@ -5526,10 +5705,10 @@
 			max_tx_rate, seid);
 		return -EINVAL;
 	}
-	if (max_tx_rate && max_tx_rate < 50) {
+	if (max_tx_rate && max_tx_rate < I40E_BW_CREDIT_DIVISOR) {
 		dev_warn(&pf->pdev->dev,
 			 "Setting max tx rate to minimum usable value of 50Mbps.\n");
-		max_tx_rate = 50;
+		max_tx_rate = I40E_BW_CREDIT_DIVISOR;
 	}
 
 	/* Tx rate credits are in values of 50Mbps, 0 is disabled */
@@ -5634,24 +5813,6 @@
 }
 
 /**
- * i40e_is_any_channel - channel exist or not
- * @vsi: ptr to VSI to which channels are associated with
- *
- * Returns true or false if channel(s) exist for associated VSI or not
- **/
-static bool i40e_is_any_channel(struct i40e_vsi *vsi)
-{
-	struct i40e_channel *ch, *ch_tmp;
-
-	list_for_each_entry_safe(ch, ch_tmp, &vsi->ch_list, list) {
-		if (ch->initialized)
-			return true;
-	}
-
-	return false;
-}
-
-/**
  * i40e_get_max_queues_for_channel
  * @vsi: ptr to VSI to which channels are associated with
  *
@@ -6158,26 +6319,15 @@
 	/* By default we are in VEPA mode, if this is the first VF/VMDq
 	 * VSI to be added switch to VEB mode.
 	 */
-	if ((!(pf->flags & I40E_FLAG_VEB_MODE_ENABLED)) ||
-	    (!i40e_is_any_channel(vsi))) {
-		if (!is_power_of_2(vsi->tc_config.tc_info[0].qcount)) {
-			dev_dbg(&pf->pdev->dev,
-				"Failed to create channel. Override queues (%u) not power of 2\n",
-				vsi->tc_config.tc_info[0].qcount);
-			return -EINVAL;
-		}
 
-		if (!(pf->flags & I40E_FLAG_VEB_MODE_ENABLED)) {
-			pf->flags |= I40E_FLAG_VEB_MODE_ENABLED;
+	if (!(pf->flags & I40E_FLAG_VEB_MODE_ENABLED)) {
+		pf->flags |= I40E_FLAG_VEB_MODE_ENABLED;
 
-			if (vsi->type == I40E_VSI_MAIN) {
-				if (pf->flags & I40E_FLAG_TC_MQPRIO)
-					i40e_do_reset(pf, I40E_PF_RESET_FLAG,
-						      true);
-				else
-					i40e_do_reset_safe(pf,
-							   I40E_PF_RESET_FLAG);
-			}
+		if (vsi->type == I40E_VSI_MAIN) {
+			if (pf->flags & I40E_FLAG_TC_MQPRIO)
+				i40e_do_reset(pf, I40E_PF_RESET_FLAG, true);
+			else
+				i40e_do_reset_safe(pf, I40E_PF_RESET_FLAG);
 		}
 		/* now onwards for main VSI, number of queues will be value
 		 * of TC0's queue count
@@ -6804,8 +6954,8 @@
 	for (i = 0; i < vsi->num_queue_pairs; i++) {
 		i40e_clean_tx_ring(vsi->tx_rings[i]);
 		if (i40e_enabled_xdp_vsi(vsi)) {
-			/* Make sure that in-progress ndo_xdp_xmit
-			 * calls are completed.
+			/* Make sure that in-progress ndo_xdp_xmit and
+			 * ndo_xsk_wakeup calls are completed.
 			 */
 			synchronize_rcu();
 			i40e_clean_tx_ring(vsi->xdp_rings[i]);
@@ -6851,6 +7001,8 @@
 	}
 	if (vsi->num_queue_pairs <
 	    (mqprio_qopt->qopt.offset[i] + mqprio_qopt->qopt.count[i])) {
+		dev_err(&vsi->back->pdev->dev,
+			"Failed to create traffic channel, insufficient number of queues.\n");
 		return -EINVAL;
 	}
 	if (sum_max_rate > i40e_get_link_speed(vsi)) {
@@ -7019,42 +7171,43 @@
 static int i40e_fwd_ring_up(struct i40e_vsi *vsi, struct net_device *vdev,
 			    struct i40e_fwd_adapter *fwd)
 {
+	struct i40e_channel *ch = NULL, *ch_tmp, *iter;
 	int ret = 0, num_tc = 1,  i, aq_err;
-	struct i40e_channel *ch, *ch_tmp;
 	struct i40e_pf *pf = vsi->back;
 	struct i40e_hw *hw = &pf->hw;
 
-	if (list_empty(&vsi->macvlan_list))
-		return -EINVAL;
-
 	/* Go through the list and find an available channel */
-	list_for_each_entry_safe(ch, ch_tmp, &vsi->macvlan_list, list) {
-		if (!i40e_is_channel_macvlan(ch)) {
-			ch->fwd = fwd;
+	list_for_each_entry_safe(iter, ch_tmp, &vsi->macvlan_list, list) {
+		if (!i40e_is_channel_macvlan(iter)) {
+			iter->fwd = fwd;
 			/* record configuration for macvlan interface in vdev */
 			for (i = 0; i < num_tc; i++)
 				netdev_bind_sb_channel_queue(vsi->netdev, vdev,
 							     i,
-							     ch->num_queue_pairs,
-							     ch->base_queue);
-			for (i = 0; i < ch->num_queue_pairs; i++) {
+							     iter->num_queue_pairs,
+							     iter->base_queue);
+			for (i = 0; i < iter->num_queue_pairs; i++) {
 				struct i40e_ring *tx_ring, *rx_ring;
 				u16 pf_q;
 
-				pf_q = ch->base_queue + i;
+				pf_q = iter->base_queue + i;
 
 				/* Get to TX ring ptr */
 				tx_ring = vsi->tx_rings[pf_q];
-				tx_ring->ch = ch;
+				tx_ring->ch = iter;
 
 				/* Get the RX ring ptr */
 				rx_ring = vsi->rx_rings[pf_q];
-				rx_ring->ch = ch;
+				rx_ring->ch = iter;
 			}
+			ch = iter;
 			break;
 		}
 	}
 
+	if (!ch)
+		return -EINVAL;
+
 	/* Guarantee all rings are updated before we update the
 	 * MAC address filter.
 	 */
@@ -7168,6 +7321,7 @@
 		ch->num_queue_pairs = qcnt;
 		if (!i40e_setup_channel(pf, vsi, ch)) {
 			ret = -EINVAL;
+			kfree(ch);
 			goto err_free;
 		}
 		ch->parent_vsi = vsi;
@@ -7466,17 +7620,25 @@
 			    vsi->seid);
 		need_reset = true;
 		goto exit;
-	} else {
-		dev_info(&vsi->back->pdev->dev,
-			 "Setup channel (id:%u) utilizing num_queues %d\n",
-			 vsi->seid, vsi->tc_config.tc_info[0].qcount);
+	} else if (enabled_tc &&
+		   (!is_power_of_2(vsi->tc_config.tc_info[0].qcount))) {
+		netdev_info(netdev,
+			    "Failed to create channel. Override queues (%u) not power of 2\n",
+			    vsi->tc_config.tc_info[0].qcount);
+		ret = -EINVAL;
+		need_reset = true;
+		goto exit;
 	}
 
+	dev_info(&vsi->back->pdev->dev,
+		 "Setup channel (id:%u) utilizing num_queues %d\n",
+		 vsi->seid, vsi->tc_config.tc_info[0].qcount);
+
 	if (pf->flags & I40E_FLAG_TC_MQPRIO) {
 		if (vsi->mqprio_qopt.max_rate[0]) {
-			u64 max_tx_rate = vsi->mqprio_qopt.max_rate[0];
+			u64 max_tx_rate = i40e_bw_bytes_to_mbits(vsi,
+						  vsi->mqprio_qopt.max_rate[0]);
 
-			do_div(max_tx_rate, I40E_BW_MBPS_DIVISOR);
 			ret = i40e_set_bw_limit(vsi, vsi->seid, max_tx_rate);
 			if (!ret) {
 				u64 credits = max_tx_rate;
@@ -7592,6 +7754,8 @@
 	if (filter->flags >= ARRAY_SIZE(flag_table))
 		return I40E_ERR_CONFIG;
 
+	memset(&cld_filter, 0, sizeof(cld_filter));
+
 	/* copy element needed to add cloud filter from filter */
 	i40e_set_cld_element(filter, &cld_filter);
 
@@ -7655,10 +7819,13 @@
 		return -EOPNOTSUPP;
 
 	/* adding filter using src_port/src_ip is not supported at this stage */
-	if (filter->src_port || filter->src_ipv4 ||
+	if (filter->src_port ||
+	    (filter->src_ipv4 && filter->n_proto != ETH_P_IPV6) ||
 	    !ipv6_addr_any(&filter->ip.v6.src_ip6))
 		return -EOPNOTSUPP;
 
+	memset(&cld_filter, 0, sizeof(cld_filter));
+
 	/* copy element needed to add cloud filter from filter */
 	i40e_set_cld_element(filter, &cld_filter.element);
 
@@ -7682,7 +7849,7 @@
 			cpu_to_le16(I40E_AQC_ADD_CLOUD_FILTER_MAC_VLAN_PORT);
 		}
 
-	} else if (filter->dst_ipv4 ||
+	} else if ((filter->dst_ipv4 && filter->n_proto != ETH_P_IPV6) ||
 		   !ipv6_addr_any(&filter->ip.v6.dst_ip6)) {
 		cld_filter.element.flags =
 				cpu_to_le16(I40E_AQC_ADD_CLOUD_FILTER_IP_PORT);
@@ -7992,6 +8159,11 @@
 		return -EOPNOTSUPP;
 	}
 
+	if (!tc) {
+		dev_err(&pf->pdev->dev, "Unable to add filter because of invalid destination");
+		return -EINVAL;
+	}
+
 	if (test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state) ||
 	    test_bit(__I40E_RESET_INTR_RECEIVED, pf->state))
 		return -EBUSY;
@@ -8031,9 +8203,8 @@
 		err = i40e_add_del_cloud_filter(vsi, filter, true);
 
 	if (err) {
-		dev_err(&pf->pdev->dev,
-			"Failed to add cloud filter, err %s\n",
-			i40e_stat_str(&pf->hw, err));
+		dev_err(&pf->pdev->dev, "Failed to add cloud filter, err %d\n",
+			err);
 		goto err;
 	}
 
@@ -8219,6 +8390,27 @@
 }
 
 /**
+ * i40e_netif_set_realnum_tx_rx_queues - Update number of tx/rx queues
+ * @vsi: vsi structure
+ *
+ * This updates netdev's number of tx/rx queues
+ *
+ * Returns status of setting tx/rx queues
+ **/
+static int i40e_netif_set_realnum_tx_rx_queues(struct i40e_vsi *vsi)
+{
+	int ret;
+
+	ret = netif_set_real_num_rx_queues(vsi->netdev,
+					   vsi->num_queue_pairs);
+	if (ret)
+		return ret;
+
+	return netif_set_real_num_tx_queues(vsi->netdev,
+					    vsi->num_queue_pairs);
+}
+
+/**
  * i40e_vsi_open -
  * @vsi: the VSI to open
  *
@@ -8254,13 +8446,7 @@
 			goto err_setup_rx;
 
 		/* Notify the stack of the actual queue counts. */
-		err = netif_set_real_num_tx_queues(vsi->netdev,
-						   vsi->num_queue_pairs);
-		if (err)
-			goto err_set_queues;
-
-		err = netif_set_real_num_rx_queues(vsi->netdev,
-						   vsi->num_queue_pairs);
+		err = i40e_netif_set_realnum_tx_rx_queues(vsi);
 		if (err)
 			goto err_set_queues;
 
@@ -8269,6 +8455,8 @@
 			 dev_driver_string(&pf->pdev->dev),
 			 dev_name(&pf->pdev->dev));
 		err = i40e_vsi_request_irq(vsi, int_name);
+		if (err)
+			goto err_setup_rx;
 
 	} else {
 		err = -EINVAL;
@@ -8461,6 +8649,13 @@
 		dev_dbg(&pf->pdev->dev, "PFR requested\n");
 		i40e_handle_reset_warning(pf, lock_acquired);
 
+	} else if (reset_flags & I40E_PF_RESET_AND_REBUILD_FLAG) {
+		/* Request a PF Reset
+		 *
+		 * Resets PF and reinitializes PFs VSI.
+		 */
+		i40e_prep_for_reset(pf, lock_acquired);
+		i40e_reset_and_rebuild(pf, true, lock_acquired);
 		dev_info(&pf->pdev->dev,
 			 pf->flags & I40E_FLAG_DISABLE_FW_LLDP ?
 			 "FW LLDP is disabled\n" :
@@ -9572,7 +9767,7 @@
 		if (pf->hw.aq.asq_last_status == I40E_AQ_RC_ENOMEM) {
 			/* retry with a larger buffer */
 			buf_len = data_size;
-		} else if (pf->hw.aq.asq_last_status != I40E_AQ_RC_OK) {
+		} else if (pf->hw.aq.asq_last_status != I40E_AQ_RC_OK || err) {
 			dev_info(&pf->pdev->dev,
 				 "capability discovery failed, err %s aq_err %s\n",
 				 i40e_stat_str(&pf->hw, err),
@@ -9784,6 +9979,21 @@
 }
 
 /**
+ * i40e_clean_xps_state - clean xps state for every tx_ring
+ * @vsi: ptr to the VSI
+ **/
+static void i40e_clean_xps_state(struct i40e_vsi *vsi)
+{
+	int i;
+
+	if (vsi->tx_rings)
+		for (i = 0; i < vsi->num_queue_pairs; i++)
+			if (vsi->tx_rings[i])
+				clear_bit(__I40E_TX_XPS_INIT_DONE,
+					  vsi->tx_rings[i]->state);
+}
+
+/**
  * i40e_prep_for_reset - prep for the core to reset
  * @pf: board private structure
  * @lock_acquired: indicates whether or not the lock has been acquired
@@ -9814,8 +10024,10 @@
 		rtnl_unlock();
 
 	for (v = 0; v < pf->num_alloc_vsi; v++) {
-		if (pf->vsi[v])
+		if (pf->vsi[v]) {
+			i40e_clean_xps_state(pf->vsi[v]);
 			pf->vsi[v]->seid = 0;
+		}
 	}
 
 	i40e_shutdown_adminq(&pf->hw);
@@ -9924,22 +10136,19 @@
  **/
 static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired)
 {
-	int old_recovery_mode_bit = test_bit(__I40E_RECOVERY_MODE, pf->state);
+	const bool is_recovery_mode_reported = i40e_check_recovery_mode(pf);
 	struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi];
 	struct i40e_hw *hw = &pf->hw;
-	u8 set_fc_aq_fail = 0;
 	i40e_status ret;
 	u32 val;
 	int v;
 
 	if (test_bit(__I40E_EMP_RESET_INTR_RECEIVED, pf->state) &&
-	    i40e_check_recovery_mode(pf)) {
+	    is_recovery_mode_reported)
 		i40e_set_ethtool_ops(pf->vsi[pf->lan_vsi]->netdev);
-	}
 
 	if (test_bit(__I40E_DOWN, pf->state) &&
-	    !test_bit(__I40E_RECOVERY_MODE, pf->state) &&
-	    !old_recovery_mode_bit)
+	    !test_bit(__I40E_RECOVERY_MODE, pf->state))
 		goto clear_recovery;
 	dev_dbg(&pf->pdev->dev, "Rebuilding internal switch\n");
 
@@ -9953,15 +10162,9 @@
 	}
 	i40e_get_oem_version(&pf->hw);
 
-	if (test_bit(__I40E_EMP_RESET_INTR_RECEIVED, pf->state) &&
-	    ((hw->aq.fw_maj_ver == 4 && hw->aq.fw_min_ver <= 33) ||
-	     hw->aq.fw_maj_ver < 4) && hw->mac.type == I40E_MAC_XL710) {
-		/* The following delay is necessary for 4.33 firmware and older
-		 * to recover after EMP reset. 200 ms should suffice but we
-		 * put here 300 ms to be sure that FW is ready to operate
-		 * after reset.
-		 */
-		mdelay(300);
+	if (test_and_clear_bit(__I40E_EMP_RESET_INTR_RECEIVED, pf->state)) {
+		/* The following delay is necessary for firmware update. */
+		mdelay(1000);
 	}
 
 	/* re-verify the eeprom if we just had an EMP reset */
@@ -9972,13 +10175,12 @@
 	 * accordingly with regard to resources initialization
 	 * and deinitialization
 	 */
-	if (test_bit(__I40E_RECOVERY_MODE, pf->state) ||
-	    old_recovery_mode_bit) {
+	if (test_bit(__I40E_RECOVERY_MODE, pf->state)) {
 		if (i40e_get_capabilities(pf,
 					  i40e_aqc_opc_list_func_capabilities))
 			goto end_unlock;
 
-		if (test_bit(__I40E_RECOVERY_MODE, pf->state)) {
+		if (is_recovery_mode_reported) {
 			/* we're staying in recovery mode so we'll reinitialize
 			 * misc vector here
 			 */
@@ -10053,13 +10255,6 @@
 			 i40e_stat_str(&pf->hw, ret),
 			 i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status));
 
-	/* make sure our flow control settings are restored */
-	ret = i40e_set_fc(&pf->hw, &set_fc_aq_fail, true);
-	if (ret)
-		dev_dbg(&pf->pdev->dev, "setting flow control: ret = %s last_status = %s\n",
-			i40e_stat_str(&pf->hw, ret),
-			i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status));
-
 	/* Rebuild the VSIs and VEBs that existed before reset.
 	 * They are still in our local switch element arrays, so only
 	 * need to rebuild the switch model in the HW.
@@ -10114,10 +10309,10 @@
 	}
 
 	if (vsi->mqprio_qopt.max_rate[0]) {
-		u64 max_tx_rate = vsi->mqprio_qopt.max_rate[0];
+		u64 max_tx_rate = i40e_bw_bytes_to_mbits(vsi,
+						  vsi->mqprio_qopt.max_rate[0]);
 		u64 credits = 0;
 
-		do_div(max_tx_rate, I40E_BW_MBPS_DIVISOR);
 		ret = i40e_set_bw_limit(vsi, vsi->seid, max_tx_rate);
 		if (ret)
 			goto end_unlock;
@@ -10166,8 +10361,11 @@
 					     pf->hw.aq.asq_last_status));
 	}
 	/* reinit the misc interrupt */
-	if (pf->flags & I40E_FLAG_MSIX_ENABLED)
+	if (pf->flags & I40E_FLAG_MSIX_ENABLED) {
 		ret = i40e_setup_misc_vector(pf);
+		if (ret)
+			goto end_unlock;
+	}
 
 	/* Add a filter to drop all Flow control frames from any VSI from being
 	 * transmitted. By doing so we stop a malicious VF from sending out
@@ -10815,10 +11013,10 @@
 	if (vsi->tx_rings && vsi->tx_rings[0]) {
 		for (i = 0; i < vsi->alloc_queue_pairs; i++) {
 			kfree_rcu(vsi->tx_rings[i], rcu);
-			vsi->tx_rings[i] = NULL;
-			vsi->rx_rings[i] = NULL;
+			WRITE_ONCE(vsi->tx_rings[i], NULL);
+			WRITE_ONCE(vsi->rx_rings[i], NULL);
 			if (vsi->xdp_rings)
-				vsi->xdp_rings[i] = NULL;
+				WRITE_ONCE(vsi->xdp_rings[i], NULL);
 		}
 	}
 }
@@ -10852,7 +11050,7 @@
 		if (vsi->back->hw_features & I40E_HW_WB_ON_ITR_CAPABLE)
 			ring->flags = I40E_TXR_FLAGS_WB_ON_ITR;
 		ring->itr_setting = pf->tx_itr_default;
-		vsi->tx_rings[i] = ring++;
+		WRITE_ONCE(vsi->tx_rings[i], ring++);
 
 		if (!i40e_enabled_xdp_vsi(vsi))
 			goto setup_rx;
@@ -10870,7 +11068,7 @@
 			ring->flags = I40E_TXR_FLAGS_WB_ON_ITR;
 		set_ring_xdp(ring);
 		ring->itr_setting = pf->tx_itr_default;
-		vsi->xdp_rings[i] = ring++;
+		WRITE_ONCE(vsi->xdp_rings[i], ring++);
 
 setup_rx:
 		ring->queue_index = i;
@@ -10883,7 +11081,7 @@
 		ring->size = 0;
 		ring->dcb_tc = 0;
 		ring->itr_setting = pf->rx_itr_default;
-		vsi->rx_rings[i] = ring;
+		WRITE_ONCE(vsi->rx_rings[i], ring);
 	}
 
 	return 0;
@@ -11264,7 +11462,6 @@
 		return -ENOMEM;
 
 	pf->irq_pile->num_entries = vectors;
-	pf->irq_pile->search_hint = 0;
 
 	/* track first vector for misc interrupts, ignore return */
 	(void)i40e_get_lump(pf, pf->irq_pile, 1, I40E_PILE_VALID_BIT - 1);
@@ -11396,7 +11593,7 @@
 
 	/* associate no queues to the misc vector */
 	wr32(hw, I40E_PFINT_LNKLST0, I40E_QUEUE_END_OF_LIST);
-	wr32(hw, I40E_PFINT_ITR0(I40E_RX_ITR), I40E_ITR_8K);
+	wr32(hw, I40E_PFINT_ITR0(I40E_RX_ITR), I40E_ITR_8K >> 1);
 
 	i40e_flush(hw);
 
@@ -11742,6 +11939,8 @@
 	struct i40e_aqc_configure_partition_bw_data bw_data;
 	i40e_status status;
 
+	memset(&bw_data, 0, sizeof(bw_data));
+
 	/* Set the valid bit for this PF */
 	bw_data.pf_valid_bits = cpu_to_le16(BIT(pf->hw.pf_id));
 	bw_data.max_bw[pf->hw.pf_id] = pf->max_bw & I40E_ALT_BW_VALUE_MASK;
@@ -11848,6 +12047,7 @@
 {
 	int err = 0;
 	int size;
+	u16 pow;
 
 	/* Set default capability flags */
 	pf->flags = I40E_FLAG_RX_CSUM_ENABLED |
@@ -11866,6 +12066,11 @@
 	pf->rss_table_size = pf->hw.func_caps.rss_table_size;
 	pf->rss_size_max = min_t(int, pf->rss_size_max,
 				 pf->hw.func_caps.num_tx_qp);
+
+	/* find the next higher power-of-2 of num cpus */
+	pow = roundup_pow_of_two(num_online_cpus());
+	pf->rss_size_max = min_t(int, pf->rss_size_max, pow);
+
 	if (pf->hw.func_caps.rss) {
 		pf->flags |= I40E_FLAG_RSS_ENABLED;
 		pf->alloc_rss_size = min_t(int, pf->rss_size_max,
@@ -12007,7 +12212,6 @@
 		goto sw_init_done;
 	}
 	pf->qp_pile->num_entries = pf->hw.func_caps.num_tx_qp;
-	pf->qp_pile->search_hint = 0;
 
 	pf->tx_timeout_recovery_level = 1;
 
@@ -12359,6 +12563,8 @@
 	}
 
 	br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
+	if (!br_spec)
+		return -EINVAL;
 
 	nla_for_each_nested(attr, br_spec, rem) {
 		__u16 mode;
@@ -12526,8 +12732,12 @@
 
 	old_prog = xchg(&vsi->xdp_prog, prog);
 
-	if (need_reset)
+	if (need_reset) {
+		if (!prog)
+			/* Wait until ndo_xsk_wakeup completes. */
+			synchronize_rcu();
 		i40e_reset_and_rebuild(pf, true, true);
+	}
 
 	for (i = 0; i < vsi->num_queue_pairs; i++)
 		WRITE_ONCE(vsi->rx_rings[i]->xdp_prog, vsi->xdp_prog);
@@ -12847,6 +13057,7 @@
 	.ndo_poll_controller	= i40e_netpoll,
 #endif
 	.ndo_setup_tc		= __i40e_setup_tc,
+	.ndo_select_queue	= i40e_lan_select_queue,
 	.ndo_set_features	= i40e_set_features,
 	.ndo_set_vf_mac		= i40e_ndo_set_vf_mac,
 	.ndo_set_vf_vlan	= i40e_ndo_set_vf_port_vlan,
@@ -13280,15 +13491,15 @@
 		vsi->id = ctxt.vsi_number;
 	}
 
-	vsi->active_filters = 0;
-	clear_bit(__I40E_VSI_OVERFLOW_PROMISC, vsi->state);
 	spin_lock_bh(&vsi->mac_filter_hash_lock);
+	vsi->active_filters = 0;
 	/* If macvlan filters already exist, force them to get loaded */
 	hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) {
 		f->state = I40E_FILTER_NEW;
 		f_count++;
 	}
 	spin_unlock_bh(&vsi->mac_filter_hash_lock);
+	clear_bit(__I40E_VSI_OVERFLOW_PROMISC, vsi->state);
 
 	if (f_count) {
 		vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
@@ -13338,7 +13549,7 @@
 		dev_info(&pf->pdev->dev, "Can't remove PF VSI\n");
 		return -ENODEV;
 	}
-
+	set_bit(__I40E_VSI_RELEASING, vsi->state);
 	uplink_seid = vsi->uplink_seid;
 	if (vsi->type != I40E_VSI_SRIOV) {
 		if (vsi->netdev_registered) {
@@ -13670,6 +13881,9 @@
 		ret = i40e_config_netdev(vsi);
 		if (ret)
 			goto err_netdev;
+		ret = i40e_netif_set_realnum_tx_rx_queues(vsi);
+		if (ret)
+			goto err_netdev;
 		ret = register_netdev(vsi->netdev);
 		if (ret)
 			goto err_netdev;
@@ -14637,6 +14851,7 @@
 	int err;
 	int v_idx;
 
+	pci_set_drvdata(pf->pdev, pf);
 	pci_save_state(pf->pdev);
 
 	/* set up periodic task facility */
@@ -14672,12 +14887,16 @@
 	 * in order to register the netdev
 	 */
 	v_idx = i40e_vsi_mem_alloc(pf, I40E_VSI_MAIN);
-	if (v_idx < 0)
+	if (v_idx < 0) {
+		err = v_idx;
 		goto err_switch_setup;
+	}
 	pf->lan_vsi = v_idx;
 	vsi = pf->vsi[v_idx];
-	if (!vsi)
+	if (!vsi) {
+		err = -EFAULT;
 		goto err_switch_setup;
+	}
 	vsi->alloc_queue_pairs = 1;
 	err = i40e_config_netdev(vsi);
 	if (err)
@@ -14736,7 +14955,6 @@
 	int err;
 	u32 val;
 	u32 i;
-	u8 set_fc_aq_fail;
 
 	err = pci_enable_device_mem(pdev);
 	if (err)
@@ -14911,8 +15129,8 @@
 
 	if (hw->aq.api_maj_ver == I40E_FW_API_VERSION_MAJOR &&
 	    hw->aq.api_min_ver > I40E_FW_MINOR_VERSION(hw))
-		dev_info(&pdev->dev,
-			 "The driver for the device detected a newer version of the NVM image v%u.%u than expected v%u.%u. Please install the most recent version of the network driver.\n",
+		dev_dbg(&pdev->dev,
+			"The driver for the device detected a newer version of the NVM image v%u.%u than v%u.%u.\n",
 			 hw->aq.api_maj_ver,
 			 hw->aq.api_min_ver,
 			 I40E_FW_API_VERSION_MAJOR,
@@ -15058,24 +15276,6 @@
 	}
 	INIT_LIST_HEAD(&pf->vsi[pf->lan_vsi]->ch_list);
 
-	/* Make sure flow control is set according to current settings */
-	err = i40e_set_fc(hw, &set_fc_aq_fail, true);
-	if (set_fc_aq_fail & I40E_SET_FC_AQ_FAIL_GET)
-		dev_dbg(&pf->pdev->dev,
-			"Set fc with err %s aq_err %s on get_phy_cap\n",
-			i40e_stat_str(hw, err),
-			i40e_aq_str(hw, hw->aq.asq_last_status));
-	if (set_fc_aq_fail & I40E_SET_FC_AQ_FAIL_SET)
-		dev_dbg(&pf->pdev->dev,
-			"Set fc with err %s aq_err %s on set_phy_config\n",
-			i40e_stat_str(hw, err),
-			i40e_aq_str(hw, hw->aq.asq_last_status));
-	if (set_fc_aq_fail & I40E_SET_FC_AQ_FAIL_UPDATE)
-		dev_dbg(&pf->pdev->dev,
-			"Set fc with err %s aq_err %s on get_link_info\n",
-			i40e_stat_str(hw, err),
-			i40e_aq_str(hw, hw->aq.asq_last_status));
-
 	/* if FDIR VSI was set up, start it now */
 	for (i = 0; i < pf->num_alloc_vsi; i++) {
 		if (pf->vsi[i] && pf->vsi[i]->type == I40E_VSI_FDIR) {
@@ -15132,6 +15332,8 @@
 		if (err) {
 			dev_info(&pdev->dev,
 				 "setup of misc vector failed: %d\n", err);
+			i40e_cloud_filter_exit(pf);
+			i40e_fdir_teardown(pf);
 			goto err_vsis;
 		}
 	}
@@ -15328,6 +15530,14 @@
 	i40e_write_rx_ctl(hw, I40E_PFQF_HENA(0), 0);
 	i40e_write_rx_ctl(hw, I40E_PFQF_HENA(1), 0);
 
+	while (test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state))
+		usleep_range(1000, 2000);
+
+	if (pf->flags & I40E_FLAG_SRIOV_ENABLED) {
+		set_bit(__I40E_VF_RESETS_DISABLED, pf->state);
+		i40e_free_vfs(pf);
+		pf->flags &= ~I40E_FLAG_SRIOV_ENABLED;
+	}
 	/* no more scheduling of any task */
 	set_bit(__I40E_SUSPENDED, pf->state);
 	set_bit(__I40E_DOWN, pf->state);
@@ -15354,11 +15564,6 @@
 	 */
 	i40e_notify_client_of_netdev_close(pf->vsi[pf->lan_vsi], false);
 
-	if (pf->flags & I40E_FLAG_SRIOV_ENABLED) {
-		i40e_free_vfs(pf);
-		pf->flags &= ~I40E_FLAG_SRIOV_ENABLED;
-	}
-
 	i40e_fdir_teardown(pf);
 
 	/* If there is a switch structure or any orphans, remove them.
@@ -15373,11 +15578,15 @@
 			i40e_switch_branch_release(pf->veb[i]);
 	}
 
-	/* Now we can shutdown the PF's VSI, just before we kill
+	/* Now we can shutdown the PF's VSIs, just before we kill
 	 * adminq and hmc.
 	 */
-	if (pf->vsi[pf->lan_vsi])
-		i40e_vsi_release(pf->vsi[pf->lan_vsi]);
+	for (i = pf->num_alloc_vsi; i--;)
+		if (pf->vsi[i]) {
+			i40e_vsi_close(pf->vsi[i]);
+			i40e_vsi_release(pf->vsi[i]);
+			pf->vsi[i] = NULL;
+		}
 
 	i40e_cloud_filter_exit(pf);
 
@@ -15526,6 +15735,9 @@
 	struct i40e_pf *pf = pci_get_drvdata(pdev);
 
 	i40e_reset_and_rebuild(pf, false, false);
+#ifdef CONFIG_PCI_IOV
+	i40e_restore_all_vfs_msi_state(pdev);
+#endif /* CONFIG_PCI_IOV */
 }
 
 /**
@@ -15778,7 +15990,7 @@
 	 * since we need to be able to guarantee forward progress even under
 	 * memory pressure.
 	 */
-	i40e_wq = alloc_workqueue("%s", WQ_MEM_RECLAIM, 0, i40e_driver_name);
+	i40e_wq = alloc_workqueue("%s", 0, 0, i40e_driver_name);
 	if (!i40e_wq) {
 		pr_err("%s: Failed to create workqueue\n", i40e_driver_name);
 		return -ENOMEM;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/i40e/i40e_nvm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/i40e/i40e_nvm.c
@@ -210,11 +210,11 @@
  * @hw: pointer to the HW structure.
  * @module_pointer: module pointer location in words from the NVM beginning
  * @offset: offset in words from module start
- * @words: number of words to write
- * @data: buffer with words to write to the Shadow RAM
+ * @words: number of words to read
+ * @data: buffer with words to read to the Shadow RAM
  * @last_command: tells the AdminQ that this is the last command
  *
- * Writes a 16 bit words buffer to the Shadow RAM using the admin command.
+ * Reads a 16 bit words buffer to the Shadow RAM using the admin command.
  **/
 static i40e_status i40e_read_nvm_aq(struct i40e_hw *hw,
 				    u8 module_pointer, u32 offset,
@@ -234,18 +234,18 @@
 	 */
 	if ((offset + words) > hw->nvm.sr_size)
 		i40e_debug(hw, I40E_DEBUG_NVM,
-			   "NVM write error: offset %d beyond Shadow RAM limit %d\n",
+			   "NVM read error: offset %d beyond Shadow RAM limit %d\n",
 			   (offset + words), hw->nvm.sr_size);
 	else if (words > I40E_SR_SECTOR_SIZE_IN_WORDS)
-		/* We can write only up to 4KB (one sector), in one AQ write */
+		/* We can read only up to 4KB (one sector), in one AQ write */
 		i40e_debug(hw, I40E_DEBUG_NVM,
-			   "NVM write fail error: tried to write %d words, limit is %d.\n",
+			   "NVM read fail error: tried to read %d words, limit is %d.\n",
 			   words, I40E_SR_SECTOR_SIZE_IN_WORDS);
 	else if (((offset + (words - 1)) / I40E_SR_SECTOR_SIZE_IN_WORDS)
 		 != (offset / I40E_SR_SECTOR_SIZE_IN_WORDS))
-		/* A single write cannot spread over two sectors */
+		/* A single read cannot spread over two sectors */
 		i40e_debug(hw, I40E_DEBUG_NVM,
-			   "NVM write error: cannot spread over two sectors in a single write offset=%d words=%d\n",
+			   "NVM read error: cannot spread over two sectors in a single read offset=%d words=%d\n",
 			   offset, words);
 	else
 		ret_code = i40e_aq_read_nvm(hw, module_pointer,
@@ -323,20 +323,24 @@
 
 /**
  * i40e_read_nvm_module_data - Reads NVM Buffer to specified memory location
- * @hw: pointer to the HW structure
+ * @hw: Pointer to the HW structure
  * @module_ptr: Pointer to module in words with respect to NVM beginning
- * @offset: offset in words from module start
+ * @module_offset: Offset in words from module start
+ * @data_offset: Offset in words from reading data area start
  * @words_data_size: Words to read from NVM
  * @data_ptr: Pointer to memory location where resulting buffer will be stored
  **/
-i40e_status i40e_read_nvm_module_data(struct i40e_hw *hw,
-				      u8 module_ptr, u16 offset,
-				      u16 words_data_size,
-				      u16 *data_ptr)
+enum i40e_status_code i40e_read_nvm_module_data(struct i40e_hw *hw,
+						u8 module_ptr,
+						u16 module_offset,
+						u16 data_offset,
+						u16 words_data_size,
+						u16 *data_ptr)
 {
 	i40e_status status;
+	u16 specific_ptr = 0;
 	u16 ptr_value = 0;
-	u32 flat_offset;
+	u32 offset = 0;
 
 	if (module_ptr != 0) {
 		status = i40e_read_nvm_word(hw, module_ptr, &ptr_value);
@@ -352,36 +356,35 @@
 
 	/* Pointer not initialized */
 	if (ptr_value == I40E_NVM_INVALID_PTR_VAL ||
-	    ptr_value == I40E_NVM_INVALID_VAL)
+	    ptr_value == I40E_NVM_INVALID_VAL) {
+		i40e_debug(hw, I40E_DEBUG_ALL, "Pointer not initialized.\n");
 		return I40E_ERR_BAD_PTR;
+	}
 
 	/* Check whether the module is in SR mapped area or outside */
 	if (ptr_value & I40E_PTR_TYPE) {
 		/* Pointer points outside of the Shared RAM mapped area */
-		ptr_value &= ~I40E_PTR_TYPE;
+		i40e_debug(hw, I40E_DEBUG_ALL,
+			   "Reading nvm data failed. Pointer points outside of the Shared RAM mapped area.\n");
 
-		/* PtrValue in 4kB units, need to convert to words */
-		ptr_value /= 2;
-		flat_offset = ((u32)ptr_value * 0x1000) + (u32)offset;
-		status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
-		if (!status) {
-			status = i40e_aq_read_nvm(hw, 0, 2 * flat_offset,
-						  2 * words_data_size,
-						  data_ptr, true, NULL);
-			i40e_release_nvm(hw);
-			if (status) {
-				i40e_debug(hw, I40E_DEBUG_ALL,
-					   "Reading nvm aq failed.Error code: %d.\n",
-					   status);
-				return I40E_ERR_NVM;
-			}
-		} else {
-			return I40E_ERR_NVM;
-		}
+		return I40E_ERR_PARAM;
 	} else {
 		/* Read from the Shadow RAM */
-		status = i40e_read_nvm_buffer(hw, ptr_value + offset,
-					      &words_data_size, data_ptr);
+
+		status = i40e_read_nvm_word(hw, ptr_value + module_offset,
+					    &specific_ptr);
+		if (status) {
+			i40e_debug(hw, I40E_DEBUG_ALL,
+				   "Reading nvm word failed.Error code: %d.\n",
+				   status);
+			return I40E_ERR_NVM;
+		}
+
+		offset = ptr_value + module_offset + specific_ptr +
+			data_offset;
+
+		status = i40e_read_nvm_buffer(hw, offset, &words_data_size,
+					      data_ptr);
 		if (status) {
 			i40e_debug(hw, I40E_DEBUG_ALL,
 				   "Reading nvm buffer failed.Error code: %d.\n",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/i40e/i40e_prototype.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/i40e/i40e_prototype.h
@@ -315,10 +315,12 @@
 void i40e_release_nvm(struct i40e_hw *hw);
 i40e_status i40e_read_nvm_word(struct i40e_hw *hw, u16 offset,
 					 u16 *data);
-i40e_status i40e_read_nvm_module_data(struct i40e_hw *hw,
-				      u8 module_ptr, u16 offset,
-				      u16 words_data_size,
-				      u16 *data_ptr);
+enum i40e_status_code i40e_read_nvm_module_data(struct i40e_hw *hw,
+						u8 module_ptr,
+						u16 module_offset,
+						u16 data_offset,
+						u16 words_data_size,
+						u16 *data_ptr);
 i40e_status i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset,
 				 u16 *words, u16 *data);
 i40e_status i40e_update_nvm_checksum(struct i40e_hw *hw);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -1195,6 +1195,11 @@
 	rc->total_packets = 0;
 }
 
+static struct i40e_rx_buffer *i40e_rx_bi(struct i40e_ring *rx_ring, u32 idx)
+{
+	return &rx_ring->rx_bi[idx];
+}
+
 /**
  * i40e_reuse_rx_page - page flip buffer and store it back on the ring
  * @rx_ring: rx descriptor ring to store buffers on
@@ -1208,7 +1213,7 @@
 	struct i40e_rx_buffer *new_buff;
 	u16 nta = rx_ring->next_to_alloc;
 
-	new_buff = &rx_ring->rx_bi[nta];
+	new_buff = i40e_rx_bi(rx_ring, nta);
 
 	/* update, and store next to alloc */
 	nta++;
@@ -1272,7 +1277,7 @@
 	ntc = rx_ring->next_to_clean;
 
 	/* fetch, update, and store next to clean */
-	rx_buffer = &rx_ring->rx_bi[ntc++];
+	rx_buffer = i40e_rx_bi(rx_ring, ntc++);
 	ntc = (ntc < rx_ring->count) ? ntc : 0;
 	rx_ring->next_to_clean = ntc;
 
@@ -1361,7 +1366,7 @@
 
 	/* Free all the Rx ring sk_buffs */
 	for (i = 0; i < rx_ring->count; i++) {
-		struct i40e_rx_buffer *rx_bi = &rx_ring->rx_bi[i];
+		struct i40e_rx_buffer *rx_bi = i40e_rx_bi(rx_ring, i);
 
 		if (!rx_bi->page)
 			continue;
@@ -1576,7 +1581,7 @@
 		return false;
 
 	rx_desc = I40E_RX_DESC(rx_ring, ntu);
-	bi = &rx_ring->rx_bi[ntu];
+	bi = i40e_rx_bi(rx_ring, ntu);
 
 	do {
 		if (!i40e_alloc_mapped_page(rx_ring, bi))
@@ -1598,7 +1603,7 @@
 		ntu++;
 		if (unlikely(ntu == rx_ring->count)) {
 			rx_desc = I40E_RX_DESC(rx_ring, 0);
-			bi = rx_ring->rx_bi;
+			bi = i40e_rx_bi(rx_ring, 0);
 			ntu = 0;
 		}
 
@@ -1864,6 +1869,7 @@
  * the adapter for another receive
  *
  * @rx_buffer: buffer containing the page
+ * @rx_buffer_pgcnt: buffer page refcount pre xdp_do_redirect() call
  *
  * If page is reusable, rx_buffer->page_offset is adjusted to point to
  * an unused region in the page.
@@ -1886,7 +1892,8 @@
  *
  * In either case, if the page is reusable its refcount is increased.
  **/
-static bool i40e_can_reuse_rx_page(struct i40e_rx_buffer *rx_buffer)
+static bool i40e_can_reuse_rx_page(struct i40e_rx_buffer *rx_buffer,
+				   int rx_buffer_pgcnt)
 {
 	unsigned int pagecnt_bias = rx_buffer->pagecnt_bias;
 	struct page *page = rx_buffer->page;
@@ -1897,7 +1904,7 @@
 
 #if (PAGE_SIZE < 8192)
 	/* if we are only owner of page we can reuse it */
-	if (unlikely((page_count(page) - pagecnt_bias) > 1))
+	if (unlikely((rx_buffer_pgcnt - pagecnt_bias) > 1))
 		return false;
 #else
 #define I40E_LAST_OFFSET \
@@ -1956,17 +1963,25 @@
  * i40e_get_rx_buffer - Fetch Rx buffer and synchronize data for use
  * @rx_ring: rx descriptor ring to transact packets on
  * @size: size of buffer to add to skb
+ * @rx_buffer_pgcnt: buffer page refcount
  *
  * This function will pull an Rx buffer from the ring and synchronize it
  * for use by the CPU.
  */
 static struct i40e_rx_buffer *i40e_get_rx_buffer(struct i40e_ring *rx_ring,
-						 const unsigned int size)
+						 const unsigned int size,
+						 int *rx_buffer_pgcnt)
 {
 	struct i40e_rx_buffer *rx_buffer;
 
-	rx_buffer = &rx_ring->rx_bi[rx_ring->next_to_clean];
-	prefetchw(rx_buffer->page);
+	rx_buffer = i40e_rx_bi(rx_ring, rx_ring->next_to_clean);
+	*rx_buffer_pgcnt =
+#if (PAGE_SIZE < 8192)
+		page_count(rx_buffer->page);
+#else
+		0;
+#endif
+	prefetch_page_address(rx_buffer->page);
 
 	/* we are reusing so sync this buffer for CPU use */
 	dma_sync_single_range_for_cpu(rx_ring->dev,
@@ -2120,14 +2135,16 @@
  * i40e_put_rx_buffer - Clean up used buffer and either recycle or free
  * @rx_ring: rx descriptor ring to transact packets on
  * @rx_buffer: rx buffer to pull data from
+ * @rx_buffer_pgcnt: rx buffer page refcount pre xdp_do_redirect() call
  *
  * This function will clean up the contents of the rx_buffer.  It will
  * either recycle the buffer or unmap it and free the associated resources.
  */
 static void i40e_put_rx_buffer(struct i40e_ring *rx_ring,
-			       struct i40e_rx_buffer *rx_buffer)
+			       struct i40e_rx_buffer *rx_buffer,
+			       int rx_buffer_pgcnt)
 {
-	if (i40e_can_reuse_rx_page(rx_buffer)) {
+	if (i40e_can_reuse_rx_page(rx_buffer, rx_buffer_pgcnt)) {
 		/* hand second half of page back to the ring */
 		i40e_reuse_rx_page(rx_ring, rx_buffer);
 	} else {
@@ -2216,15 +2233,20 @@
 	case XDP_TX:
 		xdp_ring = rx_ring->vsi->xdp_rings[rx_ring->queue_index];
 		result = i40e_xmit_xdp_tx_ring(xdp, xdp_ring);
+		if (result == I40E_XDP_CONSUMED)
+			goto out_failure;
 		break;
 	case XDP_REDIRECT:
 		err = xdp_do_redirect(rx_ring->netdev, xdp, xdp_prog);
-		result = !err ? I40E_XDP_REDIR : I40E_XDP_CONSUMED;
+		if (err)
+			goto out_failure;
+		result = I40E_XDP_REDIR;
 		break;
 	default:
 		bpf_warn_invalid_xdp_action(act);
 		/* fall through */
 	case XDP_ABORTED:
+out_failure:
 		trace_xdp_exception(rx_ring->netdev, xdp_prog, act);
 		/* fall through -- handle aborts by dropping packet */
 	case XDP_DROP:
@@ -2340,6 +2362,7 @@
 	while (likely(total_rx_packets < (unsigned int)budget)) {
 		struct i40e_rx_buffer *rx_buffer;
 		union i40e_rx_desc *rx_desc;
+		int rx_buffer_pgcnt;
 		unsigned int size;
 		u64 qword;
 
@@ -2379,7 +2402,7 @@
 			break;
 
 		i40e_trace(clean_rx_irq, rx_ring, rx_desc, skb);
-		rx_buffer = i40e_get_rx_buffer(rx_ring, size);
+		rx_buffer = i40e_get_rx_buffer(rx_ring, size, &rx_buffer_pgcnt);
 
 		/* retrieve a buffer from the ring */
 		if (!skb) {
@@ -2419,7 +2442,7 @@
 			break;
 		}
 
-		i40e_put_rx_buffer(rx_ring, rx_buffer);
+		i40e_put_rx_buffer(rx_ring, rx_buffer, rx_buffer_pgcnt);
 		cleaned_count++;
 
 		if (i40e_is_non_eop(rx_ring, rx_desc, skb))
@@ -2646,7 +2669,7 @@
 		return budget;
 	}
 
-	if (vsi->back->flags & I40E_TXR_FLAGS_WB_ON_ITR)
+	if (q_vector->tx.ring[0].flags & I40E_TXR_FLAGS_WB_ON_ITR)
 		q_vector->arm_wb_state = false;
 
 	/* Exit the polling mode, but don't re-enable interrupts if stack might
@@ -3075,13 +3098,16 @@
 
 			l4_proto = ip.v4->protocol;
 		} else if (*tx_flags & I40E_TX_FLAGS_IPV6) {
+			int ret;
+
 			tunnel |= I40E_TX_CTX_EXT_IP_IPV6;
 
 			exthdr = ip.hdr + sizeof(*ip.v6);
 			l4_proto = ip.v6->nexthdr;
-			if (l4.hdr != exthdr)
-				ipv6_skip_exthdr(skb, exthdr - skb->data,
-						 &l4_proto, &frag_off);
+			ret = ipv6_skip_exthdr(skb, exthdr - skb->data,
+					       &l4_proto, &frag_off);
+			if (ret < 0)
+				return -1;
 		}
 
 		/* define outer transport */
@@ -3495,6 +3521,55 @@
 	return -1;
 }
 
+static u16 i40e_swdcb_skb_tx_hash(struct net_device *dev,
+				  const struct sk_buff *skb,
+				  u16 num_tx_queues)
+{
+	u32 jhash_initval_salt = 0xd631614b;
+	u32 hash;
+
+	if (skb->sk && skb->sk->sk_hash)
+		hash = skb->sk->sk_hash;
+	else
+		hash = (__force u16)skb->protocol ^ skb->hash;
+
+	hash = jhash_1word(hash, jhash_initval_salt);
+
+	return (u16)(((u64)hash * num_tx_queues) >> 32);
+}
+
+u16 i40e_lan_select_queue(struct net_device *netdev,
+			  struct sk_buff *skb,
+			  struct net_device __always_unused *sb_dev)
+{
+	struct i40e_netdev_priv *np = netdev_priv(netdev);
+	struct i40e_vsi *vsi = np->vsi;
+	struct i40e_hw *hw;
+	u16 qoffset;
+	u16 qcount;
+	u8 tclass;
+	u16 hash;
+	u8 prio;
+
+	/* is DCB enabled at all? */
+	if (vsi->tc_config.numtc == 1)
+		return netdev_pick_tx(netdev, skb, sb_dev);
+
+	prio = skb->priority;
+	hw = &vsi->back->hw;
+	tclass = hw->local_dcbx_config.etscfg.prioritytable[prio];
+	/* sanity check */
+	if (unlikely(!(vsi->tc_config.enabled_tc & BIT(tclass))))
+		tclass = 0;
+
+	/* select a queue assigned for the given TC */
+	qcount = vsi->tc_config.tc_info[tclass].qcount;
+	hash = i40e_swdcb_skb_tx_hash(netdev, skb, qcount);
+
+	qoffset = vsi->tc_config.tc_info[tclass].qoffset;
+	return qoffset + hash;
+}
+
 /**
  * i40e_xmit_xdp_ring - transmits an XDP buffer to an XDP Tx ring
  * @xdp: data to transmit
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/i40e/i40e_txrx.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/i40e/i40e_txrx.h
@@ -481,6 +481,8 @@
 
 bool i40e_alloc_rx_buffers(struct i40e_ring *rxr, u16 cleaned_count);
 netdev_tx_t i40e_lan_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
+u16 i40e_lan_select_queue(struct net_device *netdev, struct sk_buff *skb,
+			  struct net_device *sb_dev);
 void i40e_clean_tx_ring(struct i40e_ring *tx_ring);
 void i40e_clean_rx_ring(struct i40e_ring *rx_ring);
 int i40e_setup_tx_descriptors(struct i40e_ring *tx_ring);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/i40e/i40e_type.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/i40e/i40e_type.h
@@ -253,11 +253,8 @@
 #define I40E_CAP_PHY_TYPE_25GBASE_ACC BIT_ULL(I40E_PHY_TYPE_25GBASE_ACC + \
 					     I40E_PHY_TYPE_OFFSET)
 /* Offset for 2.5G/5G PHY Types value to bit number conversion */
-#define I40E_PHY_TYPE_OFFSET2 (-10)
-#define I40E_CAP_PHY_TYPE_2_5GBASE_T BIT_ULL(I40E_PHY_TYPE_2_5GBASE_T + \
-					     I40E_PHY_TYPE_OFFSET2)
-#define I40E_CAP_PHY_TYPE_5GBASE_T BIT_ULL(I40E_PHY_TYPE_5GBASE_T + \
-					     I40E_PHY_TYPE_OFFSET2)
+#define I40E_CAP_PHY_TYPE_2_5GBASE_T BIT_ULL(I40E_PHY_TYPE_2_5GBASE_T)
+#define I40E_CAP_PHY_TYPE_5GBASE_T BIT_ULL(I40E_PHY_TYPE_5GBASE_T)
 #define I40E_HW_CAP_MAX_GPIO			30
 /* Capabilities of a PF or a VF or the whole device */
 struct i40e_hw_capabilities {
@@ -1473,6 +1470,10 @@
 #define I40E_PFQF_CTL_0_HASHLUTSIZE_512	0x00010000
 
 /* INPUT SET MASK for RSS, flow director, and flexible payload */
+#define I40E_X722_L3_SRC_SHIFT		49
+#define I40E_X722_L3_SRC_MASK		(0x3ULL << I40E_X722_L3_SRC_SHIFT)
+#define I40E_X722_L3_DST_SHIFT		41
+#define I40E_X722_L3_DST_MASK		(0x3ULL << I40E_X722_L3_DST_SHIFT)
 #define I40E_L3_SRC_SHIFT		47
 #define I40E_L3_SRC_MASK		(0x3ULL << I40E_L3_SRC_SHIFT)
 #define I40E_L3_V6_SRC_SHIFT		43
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
@@ -55,12 +55,7 @@
 
 	pfe.event = VIRTCHNL_EVENT_LINK_CHANGE;
 	pfe.severity = PF_EVENT_SEVERITY_INFO;
-
-	/* Always report link is down if the VF queues aren't enabled */
-	if (!vf->queues_enabled) {
-		pfe.event_data.link_event.link_status = false;
-		pfe.event_data.link_event.link_speed = 0;
-	} else if (vf->link_forced) {
+	if (vf->link_forced) {
 		pfe.event_data.link_event.link_status = vf->link_up;
 		pfe.event_data.link_event.link_speed =
 			(vf->link_up ? VIRTCHNL_LINK_SPEED_40GB : 0);
@@ -70,7 +65,6 @@
 		pfe.event_data.link_event.link_speed =
 			i40e_virtchnl_link_speed(ls->link_speed);
 	}
-
 	i40e_aq_send_msg_to_vf(hw, abs_vf_id, VIRTCHNL_OP_EVENT,
 			       0, (u8 *)&pfe, sizeof(pfe), NULL);
 }
@@ -105,6 +99,32 @@
 			     (u8 *)&pfe, sizeof(struct virtchnl_pf_event));
 }
 
+#ifdef CONFIG_PCI_IOV
+void i40e_restore_all_vfs_msi_state(struct pci_dev *pdev)
+{
+	u16 vf_id;
+	u16 pos;
+
+	/* Continue only if this is a PF */
+	if (!pdev->is_physfn)
+		return;
+
+	if (!pci_num_vf(pdev))
+		return;
+
+	pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV);
+	if (pos) {
+		struct pci_dev *vf_dev = NULL;
+
+		pci_read_config_word(pdev, pos + PCI_SRIOV_VF_DID, &vf_id);
+		while ((vf_dev = pci_get_device(pdev->vendor, vf_id, vf_dev))) {
+			if (vf_dev->is_virtfn && vf_dev->physfn == pdev)
+				pci_restore_msi_state(vf_dev);
+		}
+	}
+}
+#endif /* CONFIG_PCI_IOV */
+
 /**
  * i40e_vc_notify_vf_reset
  * @vf: pointer to the VF structure
@@ -136,16 +156,18 @@
 /***********************misc routines*****************************/
 
 /**
- * i40e_vc_disable_vf
+ * i40e_vc_reset_vf
  * @vf: pointer to the VF info
- *
- * Disable the VF through a SW reset.
+ * @notify_vf: notify vf about reset or not
+ * Reset VF handler.
  **/
-static inline void i40e_vc_disable_vf(struct i40e_vf *vf)
+static void i40e_vc_reset_vf(struct i40e_vf *vf, bool notify_vf)
 {
+	struct i40e_pf *pf = vf->pf;
 	int i;
 
-	i40e_vc_notify_vf_reset(vf);
+	if (notify_vf)
+		i40e_vc_notify_vf_reset(vf);
 
 	/* We want to ensure that an actual reset occurs initiated after this
 	 * function was called. However, we do not want to wait forever, so
@@ -153,14 +175,24 @@
 	 * ensure a reset.
 	 */
 	for (i = 0; i < 20; i++) {
+		/* If PF is in VFs releasing state reset VF is impossible,
+		 * so leave it.
+		 */
+		if (test_bit(__I40E_VFS_RELEASING, pf->state))
+			return;
 		if (i40e_reset_vf(vf, false))
 			return;
 		usleep_range(10000, 20000);
 	}
 
-	dev_warn(&vf->pf->pdev->dev,
-		 "Failed to initiate reset for VF %d after 200 milliseconds\n",
-		 vf->vf_id);
+	if (notify_vf)
+		dev_warn(&vf->pf->pdev->dev,
+			 "Failed to initiate reset for VF %d after 200 milliseconds\n",
+			 vf->vf_id);
+	else
+		dev_dbg(&vf->pf->pdev->dev,
+			"Failed to initiate reset for VF %d after 200 milliseconds\n",
+			vf->vf_id);
 }
 
 /**
@@ -621,14 +653,13 @@
 				    u16 vsi_queue_id,
 				    struct virtchnl_rxq_info *info)
 {
+	u16 pf_queue_id = i40e_vc_get_pf_queue_id(vf, vsi_id, vsi_queue_id);
 	struct i40e_pf *pf = vf->pf;
+	struct i40e_vsi *vsi = pf->vsi[vf->lan_vsi_idx];
 	struct i40e_hw *hw = &pf->hw;
 	struct i40e_hmc_obj_rxq rx_ctx;
-	u16 pf_queue_id;
 	int ret = 0;
 
-	pf_queue_id = i40e_vc_get_pf_queue_id(vf, vsi_id, vsi_queue_id);
-
 	/* clear the context structure first */
 	memset(&rx_ctx, 0, sizeof(struct i40e_hmc_obj_rxq));
 
@@ -666,6 +697,10 @@
 	}
 	rx_ctx.rxmax = info->max_pkt_size;
 
+	/* if port VLAN is configured increase the max packet size */
+	if (vsi->info.pvid)
+		rx_ctx.rxmax += VLAN_HLEN;
+
 	/* enable 32bytes desc always */
 	rx_ctx.dsize = 1;
 
@@ -955,7 +990,6 @@
 		i40e_vsi_release(pf->vsi[vf->lan_vsi_idx]);
 		vf->lan_vsi_idx = 0;
 		vf->lan_vsi_id = 0;
-		vf->num_mac = 0;
 	}
 
 	/* do the accounting and remove additional ADq VSI's */
@@ -1107,39 +1141,98 @@
 	return -EIO;
 }
 
-static inline int i40e_getnum_vf_vsi_vlan_filters(struct i40e_vsi *vsi);
+/**
+ * __i40e_getnum_vf_vsi_vlan_filters
+ * @vsi: pointer to the vsi
+ *
+ * called to get the number of VLANs offloaded on this VF
+ **/
+static int __i40e_getnum_vf_vsi_vlan_filters(struct i40e_vsi *vsi)
+{
+	struct i40e_mac_filter *f;
+	u16 num_vlans = 0, bkt;
+
+	hash_for_each(vsi->mac_filter_hash, bkt, f, hlist) {
+		if (f->vlan >= 0 && f->vlan <= I40E_MAX_VLANID)
+			num_vlans++;
+	}
+
+	return num_vlans;
+}
 
 /**
- * i40e_config_vf_promiscuous_mode
- * @vf: pointer to the VF info
- * @vsi_id: VSI id
- * @allmulti: set MAC L2 layer multicast promiscuous enable/disable
- * @alluni: set MAC L2 layer unicast promiscuous enable/disable
+ * i40e_getnum_vf_vsi_vlan_filters
+ * @vsi: pointer to the vsi
  *
- * Called from the VF to configure the promiscuous mode of
- * VF vsis and from the VF reset path to reset promiscuous mode.
+ * wrapper for __i40e_getnum_vf_vsi_vlan_filters() with spinlock held
  **/
-static i40e_status i40e_config_vf_promiscuous_mode(struct i40e_vf *vf,
-						   u16 vsi_id,
-						   bool allmulti,
-						   bool alluni)
+static int i40e_getnum_vf_vsi_vlan_filters(struct i40e_vsi *vsi)
+{
+	int num_vlans;
+
+	spin_lock_bh(&vsi->mac_filter_hash_lock);
+	num_vlans = __i40e_getnum_vf_vsi_vlan_filters(vsi);
+	spin_unlock_bh(&vsi->mac_filter_hash_lock);
+
+	return num_vlans;
+}
+
+/**
+ * i40e_get_vlan_list_sync
+ * @vsi: pointer to the VSI
+ * @num_vlans: number of VLANs in mac_filter_hash, returned to caller
+ * @vlan_list: list of VLANs present in mac_filter_hash, returned to caller.
+ *             This array is allocated here, but has to be freed in caller.
+ *
+ * Called to get number of VLANs and VLAN list present in mac_filter_hash.
+ **/
+static void i40e_get_vlan_list_sync(struct i40e_vsi *vsi, u16 *num_vlans,
+				    s16 **vlan_list)
 {
-	struct i40e_pf *pf = vf->pf;
-	struct i40e_hw *hw = &pf->hw;
 	struct i40e_mac_filter *f;
-	i40e_status aq_ret = 0;
-	struct i40e_vsi *vsi;
+	int i = 0;
 	int bkt;
 
-	vsi = i40e_find_vsi_from_id(pf, vsi_id);
-	if (!i40e_vc_isvalid_vsi_id(vf, vsi_id) || !vsi)
-		return I40E_ERR_PARAM;
+	spin_lock_bh(&vsi->mac_filter_hash_lock);
+	*num_vlans = __i40e_getnum_vf_vsi_vlan_filters(vsi);
+	*vlan_list = kcalloc(*num_vlans, sizeof(**vlan_list), GFP_ATOMIC);
+	if (!(*vlan_list))
+		goto err;
 
-	if (vf->port_vlan_id) {
-		aq_ret = i40e_aq_set_vsi_mc_promisc_on_vlan(hw, vsi->seid,
-							    allmulti,
-							    vf->port_vlan_id,
-							    NULL);
+	hash_for_each(vsi->mac_filter_hash, bkt, f, hlist) {
+		if (f->vlan < 0 || f->vlan > I40E_MAX_VLANID)
+			continue;
+		(*vlan_list)[i++] = f->vlan;
+	}
+err:
+	spin_unlock_bh(&vsi->mac_filter_hash_lock);
+}
+
+/**
+ * i40e_set_vsi_promisc
+ * @vf: pointer to the VF struct
+ * @seid: VSI number
+ * @multi_enable: set MAC L2 layer multicast promiscuous enable/disable
+ *                for a given VLAN
+ * @unicast_enable: set MAC L2 layer unicast promiscuous enable/disable
+ *                  for a given VLAN
+ * @vl: List of VLANs - apply filter for given VLANs
+ * @num_vlans: Number of elements in @vl
+ **/
+static i40e_status
+i40e_set_vsi_promisc(struct i40e_vf *vf, u16 seid, bool multi_enable,
+		     bool unicast_enable, s16 *vl, u16 num_vlans)
+{
+	i40e_status aq_ret, aq_tmp = 0;
+	struct i40e_pf *pf = vf->pf;
+	struct i40e_hw *hw = &pf->hw;
+	int i;
+
+	/* No VLAN to set promisc on, set on VSI */
+	if (!num_vlans || !vl) {
+		aq_ret = i40e_aq_set_vsi_multicast_promiscuous(hw, seid,
+							       multi_enable,
+							       NULL);
 		if (aq_ret) {
 			int aq_err = pf->hw.aq.asq_last_status;
 
@@ -1148,13 +1241,14 @@
 				vf->vf_id,
 				i40e_stat_str(&pf->hw, aq_ret),
 				i40e_aq_str(&pf->hw, aq_err));
+
 			return aq_ret;
 		}
 
-		aq_ret = i40e_aq_set_vsi_uc_promisc_on_vlan(hw, vsi->seid,
-							    alluni,
-							    vf->port_vlan_id,
-							    NULL);
+		aq_ret = i40e_aq_set_vsi_unicast_promiscuous(hw, seid,
+							     unicast_enable,
+							     NULL, true);
+
 		if (aq_ret) {
 			int aq_err = pf->hw.aq.asq_last_status;
 
@@ -1164,68 +1258,94 @@
 				i40e_stat_str(&pf->hw, aq_ret),
 				i40e_aq_str(&pf->hw, aq_err));
 		}
+
 		return aq_ret;
-	} else if (i40e_getnum_vf_vsi_vlan_filters(vsi)) {
-		hash_for_each(vsi->mac_filter_hash, bkt, f, hlist) {
-			if (f->vlan < 0 || f->vlan > I40E_MAX_VLANID)
-				continue;
-			aq_ret = i40e_aq_set_vsi_mc_promisc_on_vlan(hw,
-								    vsi->seid,
-								    allmulti,
-								    f->vlan,
-								    NULL);
-			if (aq_ret) {
-				int aq_err = pf->hw.aq.asq_last_status;
+	}
 
-				dev_err(&pf->pdev->dev,
-					"Could not add VLAN %d to multicast promiscuous domain err %s aq_err %s\n",
-					f->vlan,
-					i40e_stat_str(&pf->hw, aq_ret),
-					i40e_aq_str(&pf->hw, aq_err));
-			}
+	for (i = 0; i < num_vlans; i++) {
+		aq_ret = i40e_aq_set_vsi_mc_promisc_on_vlan(hw, seid,
+							    multi_enable,
+							    vl[i], NULL);
+		if (aq_ret) {
+			int aq_err = pf->hw.aq.asq_last_status;
 
-			aq_ret = i40e_aq_set_vsi_uc_promisc_on_vlan(hw,
-								    vsi->seid,
-								    alluni,
-								    f->vlan,
-								    NULL);
-			if (aq_ret) {
-				int aq_err = pf->hw.aq.asq_last_status;
+			dev_err(&pf->pdev->dev,
+				"VF %d failed to set multicast promiscuous mode err %s aq_err %s\n",
+				vf->vf_id,
+				i40e_stat_str(&pf->hw, aq_ret),
+				i40e_aq_str(&pf->hw, aq_err));
 
-				dev_err(&pf->pdev->dev,
-					"Could not add VLAN %d to Unicast promiscuous domain err %s aq_err %s\n",
-					f->vlan,
-					i40e_stat_str(&pf->hw, aq_ret),
-					i40e_aq_str(&pf->hw, aq_err));
-			}
+			if (!aq_tmp)
+				aq_tmp = aq_ret;
+		}
+
+		aq_ret = i40e_aq_set_vsi_uc_promisc_on_vlan(hw, seid,
+							    unicast_enable,
+							    vl[i], NULL);
+		if (aq_ret) {
+			int aq_err = pf->hw.aq.asq_last_status;
+
+			dev_err(&pf->pdev->dev,
+				"VF %d failed to set unicast promiscuous mode err %s aq_err %s\n",
+				vf->vf_id,
+				i40e_stat_str(&pf->hw, aq_ret),
+				i40e_aq_str(&pf->hw, aq_err));
+
+			if (!aq_tmp)
+				aq_tmp = aq_ret;
 		}
-		return aq_ret;
 	}
-	aq_ret = i40e_aq_set_vsi_multicast_promiscuous(hw, vsi->seid, allmulti,
-						       NULL);
-	if (aq_ret) {
-		int aq_err = pf->hw.aq.asq_last_status;
 
-		dev_err(&pf->pdev->dev,
-			"VF %d failed to set multicast promiscuous mode err %s aq_err %s\n",
-			vf->vf_id,
-			i40e_stat_str(&pf->hw, aq_ret),
-			i40e_aq_str(&pf->hw, aq_err));
+	if (aq_tmp)
+		aq_ret = aq_tmp;
+
+	return aq_ret;
+}
+
+/**
+ * i40e_config_vf_promiscuous_mode
+ * @vf: pointer to the VF info
+ * @vsi_id: VSI id
+ * @allmulti: set MAC L2 layer multicast promiscuous enable/disable
+ * @alluni: set MAC L2 layer unicast promiscuous enable/disable
+ *
+ * Called from the VF to configure the promiscuous mode of
+ * VF vsis and from the VF reset path to reset promiscuous mode.
+ **/
+static i40e_status i40e_config_vf_promiscuous_mode(struct i40e_vf *vf,
+						   u16 vsi_id,
+						   bool allmulti,
+						   bool alluni)
+{
+	i40e_status aq_ret = I40E_SUCCESS;
+	struct i40e_pf *pf = vf->pf;
+	struct i40e_vsi *vsi;
+	u16 num_vlans;
+	s16 *vl;
+
+	vsi = i40e_find_vsi_from_id(pf, vsi_id);
+	if (!i40e_vc_isvalid_vsi_id(vf, vsi_id) || !vsi)
+		return I40E_ERR_PARAM;
+
+	if (vf->port_vlan_id) {
+		aq_ret = i40e_set_vsi_promisc(vf, vsi->seid, allmulti,
+					      alluni, &vf->port_vlan_id, 1);
 		return aq_ret;
-	}
+	} else if (i40e_getnum_vf_vsi_vlan_filters(vsi)) {
+		i40e_get_vlan_list_sync(vsi, &num_vlans, &vl);
 
-	aq_ret = i40e_aq_set_vsi_unicast_promiscuous(hw, vsi->seid, alluni,
-						     NULL, true);
-	if (aq_ret) {
-		int aq_err = pf->hw.aq.asq_last_status;
+		if (!vl)
+			return I40E_ERR_NO_MEMORY;
 
-		dev_err(&pf->pdev->dev,
-			"VF %d failed to set unicast promiscuous mode err %s aq_err %s\n",
-			vf->vf_id,
-			i40e_stat_str(&pf->hw, aq_ret),
-			i40e_aq_str(&pf->hw, aq_err));
+		aq_ret = i40e_set_vsi_promisc(vf, vsi->seid, allmulti, alluni,
+					      vl, num_vlans);
+		kfree(vl);
+		return aq_ret;
 	}
 
+	/* no VLANs to set on, set on VSI */
+	aq_ret = i40e_set_vsi_promisc(vf, vsi->seid, allmulti, alluni,
+				      NULL, 0);
 	return aq_ret;
 }
 
@@ -1335,7 +1455,8 @@
  * @vf: pointer to the VF structure
  * @flr: VFLR was issued or not
  *
- * Returns true if the VF is reset, false otherwise.
+ * Returns true if the VF is in reset, resets successfully, or resets
+ * are disabled and false otherwise.
  **/
 bool i40e_reset_vf(struct i40e_vf *vf, bool flr)
 {
@@ -1345,11 +1466,16 @@
 	u32 reg;
 	int i;
 
-	/* If the VFs have been disabled, this means something else is
-	 * resetting the VF, so we shouldn't continue.
-	 */
-	if (test_and_set_bit(__I40E_VF_DISABLE, pf->state))
-		return false;
+	if (test_bit(__I40E_VF_RESETS_DISABLED, pf->state))
+		return true;
+
+	/* Bail out if VFs are disabled. */
+	if (test_bit(__I40E_VF_DISABLE, pf->state))
+		return true;
+
+	/* If VF is being reset already we don't need to continue. */
+	if (test_and_set_bit(I40E_VF_STATE_RESETTING, &vf->vf_states))
+		return true;
 
 	i40e_trigger_vf_reset(vf, flr);
 
@@ -1385,7 +1511,8 @@
 	i40e_cleanup_reset_vf(vf);
 
 	i40e_flush(hw);
-	clear_bit(__I40E_VF_DISABLE, pf->state);
+	usleep_range(20000, 40000);
+	clear_bit(I40E_VF_STATE_RESETTING, &vf->vf_states);
 
 	return true;
 }
@@ -1406,8 +1533,8 @@
 {
 	struct i40e_hw *hw = &pf->hw;
 	struct i40e_vf *vf;
-	int i, v;
 	u32 reg;
+	int i;
 
 	/* If we don't have any VFs, then there is nothing to reset */
 	if (!pf->num_alloc_vfs)
@@ -1418,8 +1545,11 @@
 		return false;
 
 	/* Begin reset on all VFs at once */
-	for (v = 0; v < pf->num_alloc_vfs; v++)
-		i40e_trigger_vf_reset(&pf->vf[v], flr);
+	for (vf = &pf->vf[0]; vf < &pf->vf[pf->num_alloc_vfs]; ++vf) {
+		/* If VF is being reset no need to trigger reset again */
+		if (!test_bit(I40E_VF_STATE_RESETTING, &vf->vf_states))
+			i40e_trigger_vf_reset(vf, flr);
+	}
 
 	/* HW requires some time to make sure it can flush the FIFO for a VF
 	 * when it resets it. Poll the VPGEN_VFRSTAT register for each VF in
@@ -1427,22 +1557,23 @@
 	 * the VFs using a simple iterator that increments once that VF has
 	 * finished resetting.
 	 */
-	for (i = 0, v = 0; i < 10 && v < pf->num_alloc_vfs; i++) {
+	for (i = 0, vf = &pf->vf[0]; i < 10 && vf < &pf->vf[pf->num_alloc_vfs]; ++i) {
 		usleep_range(10000, 20000);
 
 		/* Check each VF in sequence, beginning with the VF to fail
 		 * the previous check.
 		 */
-		while (v < pf->num_alloc_vfs) {
-			vf = &pf->vf[v];
-			reg = rd32(hw, I40E_VPGEN_VFRSTAT(vf->vf_id));
-			if (!(reg & I40E_VPGEN_VFRSTAT_VFRD_MASK))
-				break;
+		while (vf < &pf->vf[pf->num_alloc_vfs]) {
+			if (!test_bit(I40E_VF_STATE_RESETTING, &vf->vf_states)) {
+				reg = rd32(hw, I40E_VPGEN_VFRSTAT(vf->vf_id));
+				if (!(reg & I40E_VPGEN_VFRSTAT_VFRD_MASK))
+					break;
+			}
 
 			/* If the current VF has finished resetting, move on
 			 * to the next VF in sequence.
 			 */
-			v++;
+			++vf;
 		}
 	}
 
@@ -1452,31 +1583,39 @@
 	/* Display a warning if at least one VF didn't manage to reset in
 	 * time, but continue on with the operation.
 	 */
-	if (v < pf->num_alloc_vfs)
+	if (vf < &pf->vf[pf->num_alloc_vfs])
 		dev_err(&pf->pdev->dev, "VF reset check timeout on VF %d\n",
-			pf->vf[v].vf_id);
+			vf->vf_id);
 	usleep_range(10000, 20000);
 
 	/* Begin disabling all the rings associated with VFs, but do not wait
 	 * between each VF.
 	 */
-	for (v = 0; v < pf->num_alloc_vfs; v++) {
+	for (vf = &pf->vf[0]; vf < &pf->vf[pf->num_alloc_vfs]; ++vf) {
 		/* On initial reset, we don't have any queues to disable */
-		if (pf->vf[v].lan_vsi_idx == 0)
+		if (vf->lan_vsi_idx == 0)
 			continue;
 
-		i40e_vsi_stop_rings_no_wait(pf->vsi[pf->vf[v].lan_vsi_idx]);
+		/* If VF is reset in another thread just continue */
+		if (test_bit(I40E_VF_STATE_RESETTING, &vf->vf_states))
+			continue;
+
+		i40e_vsi_stop_rings_no_wait(pf->vsi[vf->lan_vsi_idx]);
 	}
 
 	/* Now that we've notified HW to disable all of the VF rings, wait
 	 * until they finish.
 	 */
-	for (v = 0; v < pf->num_alloc_vfs; v++) {
+	for (vf = &pf->vf[0]; vf < &pf->vf[pf->num_alloc_vfs]; ++vf) {
 		/* On initial reset, we don't have any queues to disable */
-		if (pf->vf[v].lan_vsi_idx == 0)
+		if (vf->lan_vsi_idx == 0)
+			continue;
+
+		/* If VF is reset in another thread just continue */
+		if (test_bit(I40E_VF_STATE_RESETTING, &vf->vf_states))
 			continue;
 
-		i40e_vsi_wait_queues_disabled(pf->vsi[pf->vf[v].lan_vsi_idx]);
+		i40e_vsi_wait_queues_disabled(pf->vsi[vf->lan_vsi_idx]);
 	}
 
 	/* Hw may need up to 50ms to finish disabling the RX queues. We
@@ -1485,10 +1624,16 @@
 	mdelay(50);
 
 	/* Finish the reset on each VF */
-	for (v = 0; v < pf->num_alloc_vfs; v++)
-		i40e_cleanup_reset_vf(&pf->vf[v]);
+	for (vf = &pf->vf[0]; vf < &pf->vf[pf->num_alloc_vfs]; ++vf) {
+		/* If VF is reset in another thread just continue */
+		if (test_bit(I40E_VF_STATE_RESETTING, &vf->vf_states))
+			continue;
+
+		i40e_cleanup_reset_vf(vf);
+	}
 
 	i40e_flush(hw);
+	usleep_range(20000, 40000);
 	clear_bit(__I40E_VF_DISABLE, pf->state);
 
 	return true;
@@ -1508,11 +1653,22 @@
 
 	if (!pf->vf)
 		return;
+
+	set_bit(__I40E_VFS_RELEASING, pf->state);
 	while (test_and_set_bit(__I40E_VF_DISABLE, pf->state))
 		usleep_range(1000, 2000);
 
 	i40e_notify_client_of_vf_enable(pf, 0);
 
+	/* Disable IOV before freeing resources. This lets any VF drivers
+	 * running in the host get themselves cleaned up before we yank
+	 * the carpet out from underneath their feet.
+	 */
+	if (!pci_vfs_assigned(pf->pdev))
+		pci_disable_sriov(pf->pdev);
+	else
+		dev_warn(&pf->pdev->dev, "VFs are assigned - not disabling SR-IOV\n");
+
 	/* Amortize wait time by stopping all VFs at the same time */
 	for (i = 0; i < pf->num_alloc_vfs; i++) {
 		if (test_bit(I40E_VF_STATE_INIT, &pf->vf[i].vf_states))
@@ -1528,15 +1684,6 @@
 		i40e_vsi_wait_queues_disabled(pf->vsi[pf->vf[i].lan_vsi_idx]);
 	}
 
-	/* Disable IOV before freeing resources. This lets any VF drivers
-	 * running in the host get themselves cleaned up before we yank
-	 * the carpet out from underneath their feet.
-	 */
-	if (!pci_vfs_assigned(pf->pdev))
-		pci_disable_sriov(pf->pdev);
-	else
-		dev_warn(&pf->pdev->dev, "VFs are assigned - not disabling SR-IOV\n");
-
 	/* free up VF resources */
 	tmp = pf->num_alloc_vfs;
 	pf->num_alloc_vfs = 0;
@@ -1565,6 +1712,7 @@
 		}
 	}
 	clear_bit(__I40E_VF_DISABLE, pf->state);
+	clear_bit(__I40E_VFS_RELEASING, pf->state);
 }
 
 #ifdef CONFIG_PCI_IOV
@@ -1700,7 +1848,7 @@
 	if (num_vfs) {
 		if (!(pf->flags & I40E_FLAG_VEB_MODE_ENABLED)) {
 			pf->flags |= I40E_FLAG_VEB_MODE_ENABLED;
-			i40e_do_reset_safe(pf, I40E_PF_RESET_FLAG);
+			i40e_do_reset_safe(pf, I40E_PF_RESET_AND_REBUILD_FLAG);
 		}
 		ret = i40e_pci_sriov_enable(pdev, num_vfs);
 		goto sriov_configure_out;
@@ -1709,7 +1857,7 @@
 	if (!pci_vfs_assigned(pf->pdev)) {
 		i40e_free_vfs(pf);
 		pf->flags &= ~I40E_FLAG_VEB_MODE_ENABLED;
-		i40e_do_reset_safe(pf, I40E_PF_RESET_FLAG);
+		i40e_do_reset_safe(pf, I40E_PF_RESET_AND_REBUILD_FLAG);
 	} else {
 		dev_warn(&pdev->dev, "Unable to free VFs because some are assigned to VMs.\n");
 		ret = -EINVAL;
@@ -1795,6 +1943,32 @@
 }
 
 /**
+ * i40e_sync_vf_state
+ * @vf: pointer to the VF info
+ * @state: VF state
+ *
+ * Called from a VF message to synchronize the service with a potential
+ * VF reset state
+ **/
+static bool i40e_sync_vf_state(struct i40e_vf *vf, enum i40e_vf_states state)
+{
+	int i;
+
+	/* When handling some messages, it needs VF state to be set.
+	 * It is possible that this flag is cleared during VF reset,
+	 * so there is a need to wait until the end of the reset to
+	 * handle the request message correctly.
+	 */
+	for (i = 0; i < I40E_VF_STATE_WAIT_COUNT; i++) {
+		if (test_bit(state, &vf->vf_states))
+			return true;
+		usleep_range(10000, 20000);
+	}
+
+	return test_bit(state, &vf->vf_states);
+}
+
+/**
  * i40e_vc_get_version_msg
  * @vf: pointer to the VF info
  * @msg: pointer to the msg buffer
@@ -1838,6 +2012,25 @@
 }
 
 /**
+ * i40e_vc_get_max_frame_size
+ * @vf: pointer to the VF
+ *
+ * Max frame size is determined based on the current port's max frame size and
+ * whether a port VLAN is configured on this VF. The VF is not aware whether
+ * it's in a port VLAN so the PF needs to account for this in max frame size
+ * checks and sending the max frame size to the VF.
+ **/
+static u16 i40e_vc_get_max_frame_size(struct i40e_vf *vf)
+{
+	u16 max_frame_size = vf->pf->hw.phy.link_info.max_frame_size;
+
+	if (vf->port_vlan_id)
+		max_frame_size -= VLAN_HLEN;
+
+	return max_frame_size;
+}
+
+/**
  * i40e_vc_get_vf_resources_msg
  * @vf: pointer to the VF info
  * @msg: pointer to the msg buffer
@@ -1854,7 +2047,7 @@
 	size_t len = 0;
 	int ret;
 
-	if (!test_bit(I40E_VF_STATE_INIT, &vf->vf_states)) {
+	if (!i40e_sync_vf_state(vf, I40E_VF_STATE_INIT)) {
 		aq_ret = I40E_ERR_PARAM;
 		goto err;
 	}
@@ -1937,6 +2130,7 @@
 	vfres->max_vectors = pf->hw.func_caps.num_msix_vectors_vf;
 	vfres->rss_key_size = I40E_HKEY_ARRAY_SIZE;
 	vfres->rss_lut_size = I40E_VF_HLUT_ARRAY_SIZE;
+	vfres->max_mtu = i40e_vc_get_max_frame_size(vf);
 
 	if (vf->lan_vsi_idx) {
 		vfres->vsi_res[0].vsi_id = vf->lan_vsi_id;
@@ -1960,39 +2154,6 @@
 }
 
 /**
- * i40e_vc_reset_vf_msg
- * @vf: pointer to the VF info
- *
- * called from the VF to reset itself,
- * unlike other virtchnl messages, PF driver
- * doesn't send the response back to the VF
- **/
-static void i40e_vc_reset_vf_msg(struct i40e_vf *vf)
-{
-	if (test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states))
-		i40e_reset_vf(vf, false);
-}
-
-/**
- * i40e_getnum_vf_vsi_vlan_filters
- * @vsi: pointer to the vsi
- *
- * called to get the number of VLANs offloaded on this VF
- **/
-static inline int i40e_getnum_vf_vsi_vlan_filters(struct i40e_vsi *vsi)
-{
-	struct i40e_mac_filter *f;
-	int num_vlans = 0, bkt;
-
-	hash_for_each(vsi->mac_filter_hash, bkt, f, hlist) {
-		if (f->vlan >= 0 && f->vlan <= I40E_MAX_VLANID)
-			num_vlans++;
-	}
-
-	return num_vlans;
-}
-
-/**
  * i40e_vc_config_promiscuous_mode_msg
  * @vf: pointer to the VF info
  * @msg: pointer to the msg buffer
@@ -2009,7 +2170,7 @@
 	bool allmulti = false;
 	bool alluni = false;
 
-	if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) {
+	if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) {
 		aq_ret = I40E_ERR_PARAM;
 		goto err_out;
 	}
@@ -2090,13 +2251,14 @@
 	struct virtchnl_vsi_queue_config_info *qci =
 	    (struct virtchnl_vsi_queue_config_info *)msg;
 	struct virtchnl_queue_pair_info *qpi;
-	struct i40e_pf *pf = vf->pf;
 	u16 vsi_id, vsi_queue_id = 0;
-	u16 num_qps_all = 0;
+	struct i40e_pf *pf = vf->pf;
 	i40e_status aq_ret = 0;
 	int i, j = 0, idx = 0;
+	struct i40e_vsi *vsi;
+	u16 num_qps_all = 0;
 
-	if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) {
+	if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) {
 		aq_ret = I40E_ERR_PARAM;
 		goto error_param;
 	}
@@ -2112,7 +2274,7 @@
 	}
 
 	if (vf->adq_enabled) {
-		for (i = 0; i < I40E_MAX_VF_VSI; i++)
+		for (i = 0; i < vf->num_tc; i++)
 			num_qps_all += vf->ch[i].num_qps;
 		if (num_qps_all != qci->num_queue_pairs) {
 			aq_ret = I40E_ERR_PARAM;
@@ -2183,9 +2345,15 @@
 		pf->vsi[vf->lan_vsi_idx]->num_queue_pairs =
 			qci->num_queue_pairs;
 	} else {
-		for (i = 0; i < vf->num_tc; i++)
-			pf->vsi[vf->ch[i].vsi_idx]->num_queue_pairs =
-			       vf->ch[i].num_qps;
+		for (i = 0; i < vf->num_tc; i++) {
+			vsi = pf->vsi[vf->ch[i].vsi_idx];
+			vsi->num_queue_pairs = vf->ch[i].num_qps;
+
+			if (i40e_update_adq_vsi_queues(vsi, i)) {
+				aq_ret = I40E_ERR_CONFIG;
+				goto error_param;
+			}
+		}
 	}
 
 error_param:
@@ -2238,7 +2406,7 @@
 	i40e_status aq_ret = 0;
 	int i;
 
-	if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) {
+	if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) {
 		aq_ret = I40E_ERR_PARAM;
 		goto error_param;
 	}
@@ -2323,6 +2491,22 @@
 }
 
 /**
+ * i40e_vc_validate_vqs_bitmaps - validate Rx/Tx queue bitmaps from VIRTHCHNL
+ * @vqs: virtchnl_queue_select structure containing bitmaps to validate
+ *
+ * Returns true if validation was successful, else false.
+ */
+static bool i40e_vc_validate_vqs_bitmaps(struct virtchnl_queue_select *vqs)
+{
+	if ((!vqs->rx_queues && !vqs->tx_queues) ||
+	    vqs->rx_queues >= BIT(I40E_MAX_VF_QUEUES) ||
+	    vqs->tx_queues >= BIT(I40E_MAX_VF_QUEUES))
+		return false;
+
+	return true;
+}
+
+/**
  * i40e_vc_enable_queues_msg
  * @vf: pointer to the VF info
  * @msg: pointer to the msg buffer
@@ -2347,7 +2531,7 @@
 		goto error_param;
 	}
 
-	if ((0 == vqs->rx_queues) && (0 == vqs->tx_queues)) {
+	if (!i40e_vc_validate_vqs_bitmaps(vqs)) {
 		aq_ret = I40E_ERR_PARAM;
 		goto error_param;
 	}
@@ -2373,8 +2557,6 @@
 		}
 	}
 
-	vf->queues_enabled = true;
-
 error_param:
 	/* send the response to the VF */
 	return i40e_vc_send_resp_to_vf(vf, VIRTCHNL_OP_ENABLE_QUEUES,
@@ -2396,10 +2578,7 @@
 	struct i40e_pf *pf = vf->pf;
 	i40e_status aq_ret = 0;
 
-	/* Immediately mark queues as disabled */
-	vf->queues_enabled = false;
-
-	if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) {
+	if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) {
 		aq_ret = I40E_ERR_PARAM;
 		goto error_param;
 	}
@@ -2409,9 +2588,7 @@
 		goto error_param;
 	}
 
-	if ((vqs->rx_queues == 0 && vqs->tx_queues == 0) ||
-	    vqs->rx_queues > I40E_MAX_VF_QUEUES ||
-	    vqs->tx_queues > I40E_MAX_VF_QUEUES) {
+	if (!i40e_vc_validate_vqs_bitmaps(vqs)) {
 		aq_ret = I40E_ERR_PARAM;
 		goto error_param;
 	}
@@ -2434,6 +2611,59 @@
 }
 
 /**
+ * i40e_check_enough_queue - find big enough queue number
+ * @vf: pointer to the VF info
+ * @needed: the number of items needed
+ *
+ * Returns the base item index of the queue, or negative for error
+ **/
+static int i40e_check_enough_queue(struct i40e_vf *vf, u16 needed)
+{
+	unsigned int  i, cur_queues, more, pool_size;
+	struct i40e_lump_tracking *pile;
+	struct i40e_pf *pf = vf->pf;
+	struct i40e_vsi *vsi;
+
+	vsi = pf->vsi[vf->lan_vsi_idx];
+	cur_queues = vsi->alloc_queue_pairs;
+
+	/* if current allocated queues are enough for need */
+	if (cur_queues >= needed)
+		return vsi->base_queue;
+
+	pile = pf->qp_pile;
+	if (cur_queues > 0) {
+		/* if the allocated queues are not zero
+		 * just check if there are enough queues for more
+		 * behind the allocated queues.
+		 */
+		more = needed - cur_queues;
+		for (i = vsi->base_queue + cur_queues;
+			i < pile->num_entries; i++) {
+			if (pile->list[i] & I40E_PILE_VALID_BIT)
+				break;
+
+			if (more-- == 1)
+				/* there is enough */
+				return vsi->base_queue;
+		}
+	}
+
+	pool_size = 0;
+	for (i = 0; i < pile->num_entries; i++) {
+		if (pile->list[i] & I40E_PILE_VALID_BIT) {
+			pool_size = 0;
+			continue;
+		}
+		if (needed <= ++pool_size)
+			/* there is enough */
+			return i;
+	}
+
+	return -ENOMEM;
+}
+
+/**
  * i40e_vc_request_queues_msg
  * @vf: pointer to the VF info
  * @msg: pointer to the msg buffer
@@ -2451,7 +2681,7 @@
 	u8 cur_pairs = vf->num_queue_pairs;
 	struct i40e_pf *pf = vf->pf;
 
-	if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states))
+	if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE))
 		return -EINVAL;
 
 	if (req_pairs > I40E_MAX_VF_QUEUES) {
@@ -2467,11 +2697,16 @@
 			 req_pairs - cur_pairs,
 			 pf->queues_left);
 		vfres->num_queue_pairs = pf->queues_left + cur_pairs;
+	} else if (i40e_check_enough_queue(vf, req_pairs) < 0) {
+		dev_warn(&pf->pdev->dev,
+			 "VF %d requested %d more queues, but there is not enough for it.\n",
+			 vf->vf_id,
+			 req_pairs - cur_pairs);
+		vfres->num_queue_pairs = cur_pairs;
 	} else {
 		/* successful request */
 		vf->num_req_queues = req_pairs;
-		i40e_vc_notify_vf_reset(vf);
-		i40e_reset_vf(vf, false);
+		i40e_vc_reset_vf(vf, true);
 		return 0;
 	}
 
@@ -2497,7 +2732,7 @@
 
 	memset(&stats, 0, sizeof(struct i40e_eth_stats));
 
-	if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) {
+	if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) {
 		aq_ret = I40E_ERR_PARAM;
 		goto error_param;
 	}
@@ -2521,6 +2756,24 @@
 				      (u8 *)&stats, sizeof(stats));
 }
 
+/**
+ * i40e_can_vf_change_mac
+ * @vf: pointer to the VF info
+ *
+ * Return true if the VF is allowed to change its MAC filters, false otherwise
+ */
+static bool i40e_can_vf_change_mac(struct i40e_vf *vf)
+{
+	/* If the VF MAC address has been set administratively (via the
+	 * ndo_set_vf_mac command), then deny permission to the VF to
+	 * add/delete unicast MAC addresses, unless the VF is trusted
+	 */
+	if (vf->pf_set_mac && !vf->trusted)
+		return false;
+
+	return true;
+}
+
 /* If the VF is not trusted restrict the number of MAC/VLAN it can program
  * MAC filters: 16 for multicast, 1 for MAC, 1 for broadcast
  */
@@ -2548,20 +2801,12 @@
 					   struct virtchnl_ether_addr_list *al)
 {
 	struct i40e_pf *pf = vf->pf;
+	struct i40e_vsi *vsi = pf->vsi[vf->lan_vsi_idx];
+	int mac2add_cnt = 0;
 	int i;
 
-	/* If this VF is not privileged, then we can't add more than a limited
-	 * number of addresses. Check to make sure that the additions do not
-	 * push us over the limit.
-	 */
-	if (!test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps) &&
-	    (vf->num_mac + al->num_elements) > I40E_VC_MAX_MAC_ADDR_PER_VF) {
-		dev_err(&pf->pdev->dev,
-			"Cannot add more MAC addresses, VF is not trusted, switch the VF to trusted to add more functionality\n");
-		return -EPERM;
-	}
-
 	for (i = 0; i < al->num_elements; i++) {
+		struct i40e_mac_filter *f;
 		u8 *addr = al->list[i].addr;
 
 		if (is_broadcast_ether_addr(addr) ||
@@ -2578,15 +2823,31 @@
 		 * The VF may request to set the MAC address filter already
 		 * assigned to it so do not return an error in that case.
 		 */
-		if (!test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps) &&
-		    !is_multicast_ether_addr(addr) && vf->pf_set_mac &&
+		if (!i40e_can_vf_change_mac(vf) &&
+		    !is_multicast_ether_addr(addr) &&
 		    !ether_addr_equal(addr, vf->default_lan_addr.addr)) {
 			dev_err(&pf->pdev->dev,
 				"VF attempting to override administratively set MAC address, bring down and up the VF interface to resume normal operation\n");
 			return -EPERM;
 		}
+
+		/*count filters that really will be added*/
+		f = i40e_find_mac(vsi, addr);
+		if (!f)
+			++mac2add_cnt;
 	}
 
+	/* If this VF is not privileged, then we can't add more than a limited
+	 * number of addresses. Check to make sure that the additions do not
+	 * push us over the limit.
+	 */
+	if (!test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps) &&
+	    (i40e_count_filters(vsi) + mac2add_cnt) >
+		    I40E_VC_MAX_MAC_ADDR_PER_VF) {
+		dev_err(&pf->pdev->dev,
+			"Cannot add more MAC addresses, VF is not trusted, switch the VF to trusted to add more functionality\n");
+		return -EPERM;
+	}
 	return 0;
 }
 
@@ -2606,7 +2867,7 @@
 	i40e_status ret = 0;
 	int i;
 
-	if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) ||
+	if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE) ||
 	    !i40e_vc_isvalid_vsi_id(vf, al->vsi_id)) {
 		ret = I40E_ERR_PARAM;
 		goto error_param;
@@ -2640,9 +2901,11 @@
 				ret = I40E_ERR_PARAM;
 				spin_unlock_bh(&vsi->mac_filter_hash_lock);
 				goto error_param;
-			} else {
-				vf->num_mac++;
 			}
+			if (is_valid_ether_addr(al->list[i].addr) &&
+			    is_zero_ether_addr(vf->default_lan_addr.addr))
+				ether_addr_copy(vf->default_lan_addr.addr,
+						al->list[i].addr);
 		}
 	}
 	spin_unlock_bh(&vsi->mac_filter_hash_lock);
@@ -2670,12 +2933,13 @@
 {
 	struct virtchnl_ether_addr_list *al =
 	    (struct virtchnl_ether_addr_list *)msg;
+	bool was_unimac_deleted = false;
 	struct i40e_pf *pf = vf->pf;
 	struct i40e_vsi *vsi = NULL;
 	i40e_status ret = 0;
 	int i;
 
-	if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) ||
+	if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE) ||
 	    !i40e_vc_isvalid_vsi_id(vf, al->vsi_id)) {
 		ret = I40E_ERR_PARAM;
 		goto error_param;
@@ -2689,29 +2953,29 @@
 			ret = I40E_ERR_INVALID_MAC_ADDR;
 			goto error_param;
 		}
-
-		if (vf->pf_set_mac &&
-		    ether_addr_equal(al->list[i].addr,
-				     vf->default_lan_addr.addr)) {
-			dev_err(&pf->pdev->dev,
-				"MAC addr %pM has been set by PF, cannot delete it for VF %d, reset VF to change MAC addr\n",
-				vf->default_lan_addr.addr, vf->vf_id);
-			ret = I40E_ERR_PARAM;
-			goto error_param;
-		}
 	}
 	vsi = pf->vsi[vf->lan_vsi_idx];
 
 	spin_lock_bh(&vsi->mac_filter_hash_lock);
 	/* delete addresses from the list */
-	for (i = 0; i < al->num_elements; i++)
+	for (i = 0; i < al->num_elements; i++) {
+		const u8 *addr = al->list[i].addr;
+
+		/* Allow to delete VF primary MAC only if it was not set
+		 * administratively by PF or if VF is trusted.
+		 */
+		if (ether_addr_equal(addr, vf->default_lan_addr.addr) &&
+		    i40e_can_vf_change_mac(vf))
+			was_unimac_deleted = true;
+		else
+			continue;
+
 		if (i40e_del_mac_filter(vsi, al->list[i].addr)) {
 			ret = I40E_ERR_INVALID_MAC_ADDR;
 			spin_unlock_bh(&vsi->mac_filter_hash_lock);
 			goto error_param;
-		} else {
-			vf->num_mac--;
 		}
+	}
 
 	spin_unlock_bh(&vsi->mac_filter_hash_lock);
 
@@ -2721,10 +2985,25 @@
 		dev_err(&pf->pdev->dev, "Unable to program VF %d MAC filters, error %d\n",
 			vf->vf_id, ret);
 
+	if (vf->trusted && was_unimac_deleted) {
+		struct i40e_mac_filter *f;
+		struct hlist_node *h;
+		u8 *macaddr = NULL;
+		int bkt;
+
+		/* set last unicast mac address as default */
+		spin_lock_bh(&vsi->mac_filter_hash_lock);
+		hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) {
+			if (is_valid_ether_addr(f->macaddr))
+				macaddr = f->macaddr;
+		}
+		if (macaddr)
+			ether_addr_copy(vf->default_lan_addr.addr, macaddr);
+		spin_unlock_bh(&vsi->mac_filter_hash_lock);
+	}
 error_param:
 	/* send the response to the VF */
-	return i40e_vc_send_resp_to_vf(vf, VIRTCHNL_OP_DEL_ETH_ADDR,
-				       ret);
+	return i40e_vc_send_resp_to_vf(vf, VIRTCHNL_OP_DEL_ETH_ADDR, ret);
 }
 
 /**
@@ -2814,7 +3093,7 @@
 	i40e_status aq_ret = 0;
 	int i;
 
-	if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) ||
+	if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE) ||
 	    !i40e_vc_isvalid_vsi_id(vf, vfl->vsi_id)) {
 		aq_ret = I40E_ERR_PARAM;
 		goto error_param;
@@ -2934,9 +3213,9 @@
 	struct i40e_vsi *vsi = NULL;
 	i40e_status aq_ret = 0;
 
-	if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) ||
+	if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE) ||
 	    !i40e_vc_isvalid_vsi_id(vf, vrk->vsi_id) ||
-	    (vrk->key_len != I40E_HKEY_ARRAY_SIZE)) {
+	    vrk->key_len != I40E_HKEY_ARRAY_SIZE) {
 		aq_ret = I40E_ERR_PARAM;
 		goto err;
 	}
@@ -2965,9 +3244,9 @@
 	i40e_status aq_ret = 0;
 	u16 i;
 
-	if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states) ||
+	if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE) ||
 	    !i40e_vc_isvalid_vsi_id(vf, vrl->vsi_id) ||
-	    (vrl->lut_entries != I40E_VF_HLUT_ARRAY_SIZE)) {
+	    vrl->lut_entries != I40E_VF_HLUT_ARRAY_SIZE) {
 		aq_ret = I40E_ERR_PARAM;
 		goto err;
 	}
@@ -3000,7 +3279,7 @@
 	i40e_status aq_ret = 0;
 	int len = 0;
 
-	if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) {
+	if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) {
 		aq_ret = I40E_ERR_PARAM;
 		goto err;
 	}
@@ -3036,7 +3315,7 @@
 	struct i40e_hw *hw = &pf->hw;
 	i40e_status aq_ret = 0;
 
-	if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) {
+	if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) {
 		aq_ret = I40E_ERR_PARAM;
 		goto err;
 	}
@@ -3061,7 +3340,7 @@
 	i40e_status aq_ret = 0;
 	struct i40e_vsi *vsi;
 
-	if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) {
+	if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) {
 		aq_ret = I40E_ERR_PARAM;
 		goto err;
 	}
@@ -3087,7 +3366,7 @@
 	i40e_status aq_ret = 0;
 	struct i40e_vsi *vsi;
 
-	if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) {
+	if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) {
 		aq_ret = I40E_ERR_PARAM;
 		goto err;
 	}
@@ -3120,16 +3399,16 @@
 	bool found = false;
 	int bkt;
 
-	if (!tc_filter->action) {
+	if (tc_filter->action != VIRTCHNL_ACTION_TC_REDIRECT) {
 		dev_info(&pf->pdev->dev,
-			 "VF %d: Currently ADq doesn't support Drop Action\n",
-			 vf->vf_id);
+			 "VF %d: ADQ doesn't support this action (%d)\n",
+			 vf->vf_id, tc_filter->action);
 		goto err;
 	}
 
 	/* action_meta is TC number here to which the filter is applied */
 	if (!tc_filter->action_meta ||
-	    tc_filter->action_meta > I40E_MAX_VF_VSI) {
+	    tc_filter->action_meta > vf->num_tc) {
 		dev_info(&pf->pdev->dev, "VF %d: Invalid TC number %u\n",
 			 vf->vf_id, tc_filter->action_meta);
 		goto err;
@@ -3314,7 +3593,7 @@
 	i40e_status aq_ret = 0;
 	int i, ret;
 
-	if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) {
+	if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) {
 		aq_ret = I40E_ERR_PARAM;
 		goto err;
 	}
@@ -3445,7 +3724,7 @@
 	i40e_status aq_ret = 0;
 	int i, ret;
 
-	if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) {
+	if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) {
 		aq_ret = I40E_ERR_PARAM;
 		goto err_out;
 	}
@@ -3554,7 +3833,7 @@
 	i40e_status aq_ret = 0;
 	u64 speed = 0;
 
-	if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) {
+	if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) {
 		aq_ret = I40E_ERR_PARAM;
 		goto err;
 	}
@@ -3661,15 +3940,9 @@
 
 	/* set this flag only after making sure all inputs are sane */
 	vf->adq_enabled = true;
-	/* num_req_queues is set when user changes number of queues via ethtool
-	 * and this causes issue for default VSI(which depends on this variable)
-	 * when ADq is enabled, hence reset it.
-	 */
-	vf->num_req_queues = 0;
 
 	/* reset the VF in order to allocate resources */
-	i40e_vc_notify_vf_reset(vf);
-	i40e_reset_vf(vf, false);
+	i40e_vc_reset_vf(vf, true);
 
 	return I40E_SUCCESS;
 
@@ -3689,7 +3962,7 @@
 	struct i40e_pf *pf = vf->pf;
 	i40e_status aq_ret = 0;
 
-	if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) {
+	if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE)) {
 		aq_ret = I40E_ERR_PARAM;
 		goto err;
 	}
@@ -3709,8 +3982,7 @@
 	}
 
 	/* reset the VF in order to allocate resources */
-	i40e_vc_notify_vf_reset(vf);
-	i40e_reset_vf(vf, false);
+	i40e_vc_reset_vf(vf, true);
 
 	return I40E_SUCCESS;
 
@@ -3772,7 +4044,7 @@
 		i40e_vc_notify_vf_link_state(vf);
 		break;
 	case VIRTCHNL_OP_RESET_VF:
-		i40e_vc_reset_vf_msg(vf);
+		i40e_vc_reset_vf(vf, false);
 		ret = 0;
 		break;
 	case VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE:
@@ -3962,20 +4234,16 @@
 		goto error_param;
 
 	vf = &pf->vf[vf_id];
-	vsi = pf->vsi[vf->lan_vsi_idx];
 
 	/* When the VF is resetting wait until it is done.
 	 * It can take up to 200 milliseconds,
 	 * but wait for up to 300 milliseconds to be safe.
-	 * If the VF is indeed in reset, the vsi pointer has
-	 * to show on the newly loaded vsi under pf->vsi[id].
+	 * Acquire the VSI pointer only after the VF has been
+	 * properly initialized.
 	 */
 	for (i = 0; i < 15; i++) {
-		if (test_bit(I40E_VF_STATE_INIT, &vf->vf_states)) {
-			if (i > 0)
-				vsi = pf->vsi[vf->lan_vsi_idx];
+		if (test_bit(I40E_VF_STATE_INIT, &vf->vf_states))
 			break;
-		}
 		msleep(20);
 	}
 	if (!test_bit(I40E_VF_STATE_INIT, &vf->vf_states)) {
@@ -3984,6 +4252,7 @@
 		ret = -EAGAIN;
 		goto error_param;
 	}
+	vsi = pf->vsi[vf->lan_vsi_idx];
 
 	if (is_multicast_ether_addr(mac)) {
 		dev_err(&pf->pdev->dev,
@@ -4029,7 +4298,7 @@
 	/* Force the VF interface down so it has to bring up with new MAC
 	 * address
 	 */
-	i40e_vc_disable_vf(vf);
+	i40e_vc_reset_vf(vf, true);
 	dev_info(&pf->pdev->dev, "Bring down and up the VF interface to make this change effective.\n");
 
 error_param:
@@ -4038,34 +4307,6 @@
 }
 
 /**
- * i40e_vsi_has_vlans - True if VSI has configured VLANs
- * @vsi: pointer to the vsi
- *
- * Check if a VSI has configured any VLANs. False if we have a port VLAN or if
- * we have no configured VLANs. Do not call while holding the
- * mac_filter_hash_lock.
- */
-static bool i40e_vsi_has_vlans(struct i40e_vsi *vsi)
-{
-	bool have_vlans;
-
-	/* If we have a port VLAN, then the VSI cannot have any VLANs
-	 * configured, as all MAC/VLAN filters will be assigned to the PVID.
-	 */
-	if (vsi->info.pvid)
-		return false;
-
-	/* Since we don't have a PVID, we know that if the device is in VLAN
-	 * mode it must be because of a VLAN filter configured on this VSI.
-	 */
-	spin_lock_bh(&vsi->mac_filter_hash_lock);
-	have_vlans = i40e_is_vsi_in_vlan(vsi);
-	spin_unlock_bh(&vsi->mac_filter_hash_lock);
-
-	return have_vlans;
-}
-
-/**
  * i40e_ndo_set_vf_port_vlan
  * @netdev: network interface device structure
  * @vf_id: VF identifier
@@ -4121,19 +4362,6 @@
 		/* duplicate request, so just return success */
 		goto error_pvid;
 
-	if (i40e_vsi_has_vlans(vsi)) {
-		dev_err(&pf->pdev->dev,
-			"VF %d has already configured VLAN filters and the administrator is requesting a port VLAN override.\nPlease unload and reload the VF driver for this change to take effect.\n",
-			vf_id);
-		/* Administrator Error - knock the VF offline until he does
-		 * the right thing by reconfiguring his network correctly
-		 * and then reloading the VF driver.
-		 */
-		i40e_vc_disable_vf(vf);
-		/* During reset the VF got a new VSI, so refresh the pointer. */
-		vsi = pf->vsi[vf->lan_vsi_idx];
-	}
-
 	/* Locked once because multiple functions below iterate list */
 	spin_lock_bh(&vsi->mac_filter_hash_lock);
 
@@ -4219,6 +4447,10 @@
 	 */
 	vf->port_vlan_id = le16_to_cpu(vsi->info.pvid);
 
+	i40e_vc_reset_vf(vf, true);
+	/* During reset the VF got a new VSI, so refresh a pointer. */
+	vsi = pf->vsi[vf->lan_vsi_idx];
+
 	ret = i40e_config_vf_promiscuous_mode(vf, vsi->id, allmulti, alluni);
 	if (ret) {
 		dev_err(&pf->pdev->dev, "Unable to config vf promiscuous mode\n");
@@ -4514,7 +4746,7 @@
 		goto out;
 
 	vf->trusted = setting;
-	i40e_vc_disable_vf(vf);
+	i40e_vc_reset_vf(vf, true);
 	dev_info(&pf->pdev->dev, "VF %u is now %strusted\n",
 		 vf_id, setting ? "" : "un");
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h
@@ -19,6 +19,8 @@
 
 #define I40E_MAX_VF_PROMISC_FLAGS	3
 
+#define I40E_VF_STATE_WAIT_COUNT	20
+
 /* Various queue ctrls */
 enum i40e_queue_ctrl {
 	I40E_QUEUE_CTRL_UNKNOWN = 0,
@@ -39,6 +41,7 @@
 	I40E_VF_STATE_MC_PROMISC,
 	I40E_VF_STATE_UC_PROMISC,
 	I40E_VF_STATE_PRE_ENABLE,
+	I40E_VF_STATE_RESETTING
 };
 
 /* VF capabilities */
@@ -99,9 +102,7 @@
 	unsigned int tx_rate;	/* Tx bandwidth limit in Mbps */
 	bool link_forced;
 	bool link_up;		/* only valid if VF link is forced */
-	bool queues_enabled;	/* true if the VF queues are enabled */
 	bool spoofchk;
-	u16 num_mac;
 	u16 num_vlan;
 
 	/* ADq related variables */
@@ -139,5 +140,8 @@
 
 void i40e_vc_notify_link_state(struct i40e_pf *pf);
 void i40e_vc_notify_reset(struct i40e_pf *pf);
+#ifdef CONFIG_PCI_IOV
+void i40e_restore_all_vfs_msi_state(struct pci_dev *pdev);
+#endif /* CONFIG_PCI_IOV */
 
 #endif /* _I40E_VIRTCHNL_PF_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/i40e/i40e_xsk.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/i40e/i40e_xsk.c
@@ -9,6 +9,11 @@
 #include "i40e_txrx_common.h"
 #include "i40e_xsk.h"
 
+static struct i40e_rx_buffer *i40e_rx_bi(struct i40e_ring *rx_ring, u32 idx)
+{
+	return &rx_ring->rx_bi[idx];
+}
+
 /**
  * i40e_xsk_umem_dma_map - DMA maps all UMEM memory for the netdev
  * @vsi: Current VSI
@@ -207,21 +212,28 @@
 
 	xdp->handle = xsk_umem_adjust_offset(umem, xdp->handle, offset);
 
+	if (likely(act == XDP_REDIRECT)) {
+		err = xdp_do_redirect(rx_ring->netdev, xdp, xdp_prog);
+		if (err)
+			goto out_failure;
+		rcu_read_unlock();
+		return I40E_XDP_REDIR;
+	}
+
 	switch (act) {
 	case XDP_PASS:
 		break;
 	case XDP_TX:
 		xdp_ring = rx_ring->vsi->xdp_rings[rx_ring->queue_index];
 		result = i40e_xmit_xdp_tx_ring(xdp, xdp_ring);
-		break;
-	case XDP_REDIRECT:
-		err = xdp_do_redirect(rx_ring->netdev, xdp, xdp_prog);
-		result = !err ? I40E_XDP_REDIR : I40E_XDP_CONSUMED;
+		if (result == I40E_XDP_CONSUMED)
+			goto out_failure;
 		break;
 	default:
 		bpf_warn_invalid_xdp_action(act);
 		/* fall through */
 	case XDP_ABORTED:
+out_failure:
 		trace_xdp_exception(rx_ring->netdev, xdp_prog, act);
 		/* fallthrough -- handle aborts by dropping packet */
 	case XDP_DROP:
@@ -321,7 +333,7 @@
 	bool ok = true;
 
 	rx_desc = I40E_RX_DESC(rx_ring, ntu);
-	bi = &rx_ring->rx_bi[ntu];
+	bi = i40e_rx_bi(rx_ring, ntu);
 	do {
 		if (!alloc(rx_ring, bi)) {
 			ok = false;
@@ -340,7 +352,7 @@
 
 		if (unlikely(ntu == rx_ring->count)) {
 			rx_desc = I40E_RX_DESC(rx_ring, 0);
-			bi = rx_ring->rx_bi;
+			bi = i40e_rx_bi(rx_ring, 0);
 			ntu = 0;
 		}
 
@@ -402,7 +414,7 @@
 {
 	struct i40e_rx_buffer *bi;
 
-	bi = &rx_ring->rx_bi[rx_ring->next_to_clean];
+	bi = i40e_rx_bi(rx_ring, rx_ring->next_to_clean);
 
 	/* we are reusing so sync this buffer for CPU use */
 	dma_sync_single_range_for_cpu(rx_ring->dev,
@@ -424,7 +436,8 @@
 static void i40e_reuse_rx_buffer_zc(struct i40e_ring *rx_ring,
 				    struct i40e_rx_buffer *old_bi)
 {
-	struct i40e_rx_buffer *new_bi = &rx_ring->rx_bi[rx_ring->next_to_alloc];
+	struct i40e_rx_buffer *new_bi = i40e_rx_bi(rx_ring,
+						   rx_ring->next_to_alloc);
 	u16 nta = rx_ring->next_to_alloc;
 
 	/* update, and store next to alloc */
@@ -456,7 +469,7 @@
 	mask = rx_ring->xsk_umem->chunk_mask;
 
 	nta = rx_ring->next_to_alloc;
-	bi = &rx_ring->rx_bi[nta];
+	bi = i40e_rx_bi(rx_ring, nta);
 
 	nta++;
 	rx_ring->next_to_alloc = (nta < rx_ring->count) ? nta : 0;
@@ -492,13 +505,11 @@
 	struct sk_buff *skb;
 
 	/* allocate a skb to store the frags */
-	skb = __napi_alloc_skb(&rx_ring->q_vector->napi,
-			       xdp->data_end - xdp->data_hard_start,
+	skb = __napi_alloc_skb(&rx_ring->q_vector->napi, datasize,
 			       GFP_ATOMIC | __GFP_NOWARN);
 	if (unlikely(!skb))
 		return NULL;
 
-	skb_reserve(skb, xdp->data - xdp->data_hard_start);
 	memcpy(__skb_put(skb, datasize), xdp->data, datasize);
 	if (metasize)
 		skb_metadata_set(skb, metasize);
@@ -787,8 +798,12 @@
 {
 	struct i40e_netdev_priv *np = netdev_priv(dev);
 	struct i40e_vsi *vsi = np->vsi;
+	struct i40e_pf *pf = vsi->back;
 	struct i40e_ring *ring;
 
+	if (test_bit(__I40E_CONFIG_BUSY, pf->state))
+		return -EAGAIN;
+
 	if (test_bit(__I40E_VSI_DOWN, vsi->state))
 		return -ENETDOWN;
 
@@ -820,7 +835,7 @@
 	u16 i;
 
 	for (i = 0; i < rx_ring->count; i++) {
-		struct i40e_rx_buffer *rx_bi = &rx_ring->rx_bi[i];
+		struct i40e_rx_buffer *rx_bi = i40e_rx_bi(rx_ring, i);
 
 		if (!rx_bi->addr)
 			continue;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/iavf/iavf.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/iavf/iavf.h
@@ -86,6 +86,11 @@
 #define IAVF_HKEY_ARRAY_SIZE ((IAVF_VFQF_HKEY_MAX_INDEX + 1) * 4)
 #define IAVF_HLUT_ARRAY_SIZE ((IAVF_VFQF_HLUT_MAX_INDEX + 1) * 4)
 #define IAVF_MBPS_DIVISOR	125000 /* divisor to convert to Mbps */
+#define IAVF_MBPS_QUANTA	50
+
+#define IAVF_VIRTCHNL_VF_RESOURCE_SIZE (sizeof(struct virtchnl_vf_resource) + \
+					(IAVF_MAX_VF_VSI * \
+					 sizeof(struct virtchnl_vsi_resource)))
 
 /* MAX_MSIX_Q_VECTORS of these are allocated,
  * but we only use one per queue-specific vector.
@@ -130,6 +135,7 @@
 struct iavf_mac_filter {
 	struct list_head list;
 	u8 macaddr[ETH_ALEN];
+	bool is_new_mac;	/* filter is new, wait for PF decision */
 	bool remove;		/* filter needs to be removed */
 	bool add;		/* filter needs to be added */
 };
@@ -306,6 +312,14 @@
 	bool netdev_registered;
 	bool link_up;
 	enum virtchnl_link_speed link_speed;
+	/* This is only populated if the VIRTCHNL_VF_CAP_ADV_LINK_SPEED is set
+	 * in vf_res->vf_cap_flags. Use ADV_LINK_SUPPORT macro to determine if
+	 * this field is valid. This field should be used going forward and the
+	 * enum virtchnl_link_speed above should be considered the legacy way of
+	 * storing/communicating link speeds.
+	 */
+	u32 link_speed_mbps;
+
 	enum virtchnl_ops current_op;
 #define CLIENT_ALLOWED(_a) ((_a)->vf_res ? \
 			    (_a)->vf_res->vf_cap_flags & \
@@ -322,6 +336,8 @@
 			VIRTCHNL_VF_OFFLOAD_RSS_PF)))
 #define VLAN_ALLOWED(_a) ((_a)->vf_res->vf_cap_flags & \
 			  VIRTCHNL_VF_OFFLOAD_VLAN)
+#define ADV_LINK_SUPPORT(_a) ((_a)->vf_res->vf_cap_flags & \
+			      VIRTCHNL_VF_CAP_ADV_LINK_SPEED)
 	struct virtchnl_vf_resource *vf_res; /* incl. all VSIs */
 	struct virtchnl_vsi_resource *vsi_res; /* our LAN VSI */
 	struct virtchnl_version_info pf_version;
@@ -369,7 +385,7 @@
 void iavf_update_stats(struct iavf_adapter *adapter);
 void iavf_reset_interrupt_capability(struct iavf_adapter *adapter);
 int iavf_init_interrupt_scheme(struct iavf_adapter *adapter);
-void iavf_irq_enable_queues(struct iavf_adapter *adapter, u32 mask);
+void iavf_irq_enable_queues(struct iavf_adapter *adapter);
 void iavf_free_all_tx_resources(struct iavf_adapter *adapter);
 void iavf_free_all_rx_resources(struct iavf_adapter *adapter);
 
@@ -415,4 +431,6 @@
 void iavf_disable_channels(struct iavf_adapter *adapter);
 void iavf_add_cloud_filter(struct iavf_adapter *adapter);
 void iavf_del_cloud_filter(struct iavf_adapter *adapter);
+struct iavf_mac_filter *iavf_add_filter(struct iavf_adapter *adapter,
+					const u8 *macaddr);
 #endif /* _IAVF_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/iavf/iavf_adminq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/iavf/iavf_adminq.c
@@ -324,6 +324,7 @@
 static enum iavf_status iavf_init_asq(struct iavf_hw *hw)
 {
 	enum iavf_status ret_code = 0;
+	int i;
 
 	if (hw->aq.asq.count > 0) {
 		/* queue already initialized */
@@ -354,12 +355,17 @@
 	/* initialize base registers */
 	ret_code = iavf_config_asq_regs(hw);
 	if (ret_code)
-		goto init_adminq_free_rings;
+		goto init_free_asq_bufs;
 
 	/* success! */
 	hw->aq.asq.count = hw->aq.num_asq_entries;
 	goto init_adminq_exit;
 
+init_free_asq_bufs:
+	for (i = 0; i < hw->aq.num_asq_entries; i++)
+		iavf_free_dma_mem(hw, &hw->aq.asq.r.asq_bi[i]);
+	iavf_free_virt_mem(hw, &hw->aq.asq.dma_head);
+
 init_adminq_free_rings:
 	iavf_free_adminq_asq(hw);
 
@@ -383,6 +389,7 @@
 static enum iavf_status iavf_init_arq(struct iavf_hw *hw)
 {
 	enum iavf_status ret_code = 0;
+	int i;
 
 	if (hw->aq.arq.count > 0) {
 		/* queue already initialized */
@@ -413,12 +420,16 @@
 	/* initialize base registers */
 	ret_code = iavf_config_arq_regs(hw);
 	if (ret_code)
-		goto init_adminq_free_rings;
+		goto init_free_arq_bufs;
 
 	/* success! */
 	hw->aq.arq.count = hw->aq.num_arq_entries;
 	goto init_adminq_exit;
 
+init_free_arq_bufs:
+	for (i = 0; i < hw->aq.num_arq_entries; i++)
+		iavf_free_dma_mem(hw, &hw->aq.arq.r.arq_bi[i]);
+	iavf_free_virt_mem(hw, &hw->aq.arq.dma_head);
 init_adminq_free_rings:
 	iavf_free_adminq_arq(hw);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/iavf/iavf_common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/iavf/iavf_common.c
@@ -662,7 +662,7 @@
 	/* Non Tunneled IPv6 */
 	IAVF_PTT(88, IP, IPV6, FRG, NONE, NONE, NOF, NONE, PAY3),
 	IAVF_PTT(89, IP, IPV6, NOF, NONE, NONE, NOF, NONE, PAY3),
-	IAVF_PTT(90, IP, IPV6, NOF, NONE, NONE, NOF, UDP,  PAY3),
+	IAVF_PTT(90, IP, IPV6, NOF, NONE, NONE, NOF, UDP,  PAY4),
 	IAVF_PTT_UNUSED_ENTRY(91),
 	IAVF_PTT(92, IP, IPV6, NOF, NONE, NONE, NOF, TCP,  PAY4),
 	IAVF_PTT(93, IP, IPV6, NOF, NONE, NONE, NOF, SCTP, PAY4),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/iavf/iavf_ethtool.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/iavf/iavf_ethtool.c
@@ -278,7 +278,18 @@
 	ethtool_link_ksettings_zero_link_mode(cmd, supported);
 	cmd->base.autoneg = AUTONEG_DISABLE;
 	cmd->base.port = PORT_NONE;
-	/* Set speed and duplex */
+	cmd->base.duplex = DUPLEX_FULL;
+
+	if (ADV_LINK_SUPPORT(adapter)) {
+		if (adapter->link_speed_mbps &&
+		    adapter->link_speed_mbps < U32_MAX)
+			cmd->base.speed = adapter->link_speed_mbps;
+		else
+			cmd->base.speed = SPEED_UNKNOWN;
+
+		return 0;
+	}
+
 	switch (adapter->link_speed) {
 	case IAVF_LINK_SPEED_40GB:
 		cmd->base.speed = SPEED_40000;
@@ -306,7 +317,6 @@
 	default:
 		break;
 	}
-	cmd->base.duplex = DUPLEX_FULL;
 
 	return 0;
 }
@@ -602,23 +612,44 @@
 	if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
 		return -EINVAL;
 
-	new_tx_count = clamp_t(u32, ring->tx_pending,
-			       IAVF_MIN_TXD,
-			       IAVF_MAX_TXD);
-	new_tx_count = ALIGN(new_tx_count, IAVF_REQ_DESCRIPTOR_MULTIPLE);
-
-	new_rx_count = clamp_t(u32, ring->rx_pending,
-			       IAVF_MIN_RXD,
-			       IAVF_MAX_RXD);
-	new_rx_count = ALIGN(new_rx_count, IAVF_REQ_DESCRIPTOR_MULTIPLE);
+	if (ring->tx_pending > IAVF_MAX_TXD ||
+	    ring->tx_pending < IAVF_MIN_TXD ||
+	    ring->rx_pending > IAVF_MAX_RXD ||
+	    ring->rx_pending < IAVF_MIN_RXD) {
+		netdev_err(netdev, "Descriptors requested (Tx: %d / Rx: %d) out of range [%d-%d] (increment %d)\n",
+			   ring->tx_pending, ring->rx_pending, IAVF_MIN_TXD,
+			   IAVF_MAX_RXD, IAVF_REQ_DESCRIPTOR_MULTIPLE);
+		return -EINVAL;
+	}
+
+	new_tx_count = ALIGN(ring->tx_pending, IAVF_REQ_DESCRIPTOR_MULTIPLE);
+	if (new_tx_count != ring->tx_pending)
+		netdev_info(netdev, "Requested Tx descriptor count rounded up to %d\n",
+			    new_tx_count);
+
+	new_rx_count = ALIGN(ring->rx_pending, IAVF_REQ_DESCRIPTOR_MULTIPLE);
+	if (new_rx_count != ring->rx_pending)
+		netdev_info(netdev, "Requested Rx descriptor count rounded up to %d\n",
+			    new_rx_count);
 
 	/* if nothing to do return success */
 	if ((new_tx_count == adapter->tx_desc_count) &&
-	    (new_rx_count == adapter->rx_desc_count))
+	    (new_rx_count == adapter->rx_desc_count)) {
+		netdev_dbg(netdev, "Nothing to change, descriptor count is same as requested\n");
 		return 0;
+	}
+
+	if (new_tx_count != adapter->tx_desc_count) {
+		netdev_dbg(netdev, "Changing Tx descriptor count from %d to %d\n",
+			   adapter->tx_desc_count, new_tx_count);
+		adapter->tx_desc_count = new_tx_count;
+	}
 
-	adapter->tx_desc_count = new_tx_count;
-	adapter->rx_desc_count = new_rx_count;
+	if (new_rx_count != adapter->rx_desc_count) {
+		netdev_dbg(netdev, "Changing Rx descriptor count from %d to %d\n",
+			   adapter->rx_desc_count, new_rx_count);
+		adapter->rx_desc_count = new_rx_count;
+	}
 
 	if (netif_running(netdev)) {
 		adapter->flags |= IAVF_FLAG_RESET_NEEDED;
@@ -709,12 +740,31 @@
  *
  * Change the ITR settings for a specific queue.
  **/
-static void iavf_set_itr_per_queue(struct iavf_adapter *adapter,
-				   struct ethtool_coalesce *ec, int queue)
+static int iavf_set_itr_per_queue(struct iavf_adapter *adapter,
+				  struct ethtool_coalesce *ec, int queue)
 {
 	struct iavf_ring *rx_ring = &adapter->rx_rings[queue];
 	struct iavf_ring *tx_ring = &adapter->tx_rings[queue];
 	struct iavf_q_vector *q_vector;
+	u16 itr_setting;
+
+	itr_setting = rx_ring->itr_setting & ~IAVF_ITR_DYNAMIC;
+
+	if (ec->rx_coalesce_usecs != itr_setting &&
+	    ec->use_adaptive_rx_coalesce) {
+		netif_info(adapter, drv, adapter->netdev,
+			   "Rx interrupt throttling cannot be changed if adaptive-rx is enabled\n");
+		return -EINVAL;
+	}
+
+	itr_setting = tx_ring->itr_setting & ~IAVF_ITR_DYNAMIC;
+
+	if (ec->tx_coalesce_usecs != itr_setting &&
+	    ec->use_adaptive_tx_coalesce) {
+		netif_info(adapter, drv, adapter->netdev,
+			   "Tx interrupt throttling cannot be changed if adaptive-tx is enabled\n");
+		return -EINVAL;
+	}
 
 	rx_ring->itr_setting = ITR_REG_ALIGN(ec->rx_coalesce_usecs);
 	tx_ring->itr_setting = ITR_REG_ALIGN(ec->tx_coalesce_usecs);
@@ -737,6 +787,7 @@
 	 * the Tx and Rx ITR values based on the values we have entered
 	 * into the q_vector, no need to write the values now.
 	 */
+	return 0;
 }
 
 /**
@@ -778,9 +829,11 @@
 	 */
 	if (queue < 0) {
 		for (i = 0; i < adapter->num_active_queues; i++)
-			iavf_set_itr_per_queue(adapter, ec, i);
+			if (iavf_set_itr_per_queue(adapter, ec, i))
+				return -EINVAL;
 	} else if (queue < adapter->num_active_queues) {
-		iavf_set_itr_per_queue(adapter, ec, queue);
+		if (iavf_set_itr_per_queue(adapter, ec, queue))
+			return -EINVAL;
 	} else {
 		netif_info(adapter, drv, netdev, "Invalid queue value, queue range is 0 - %d\n",
 			   adapter->num_active_queues - 1);
@@ -952,14 +1005,13 @@
 
 	if (hfunc)
 		*hfunc = ETH_RSS_HASH_TOP;
-	if (!indir)
-		return 0;
-
-	memcpy(key, adapter->rss_key, adapter->rss_key_size);
+	if (key)
+		memcpy(key, adapter->rss_key, adapter->rss_key_size);
 
-	/* Each 32 bits pointed by 'indir' is stored with a lut entry */
-	for (i = 0; i < adapter->rss_lut_size; i++)
-		indir[i] = (u32)adapter->rss_lut[i];
+	if (indir)
+		/* Each 32 bits pointed by 'indir' is stored with a lut entry */
+		for (i = 0; i < adapter->rss_lut_size; i++)
+			indir[i] = (u32)adapter->rss_lut[i];
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -143,6 +143,30 @@
 }
 
 /**
+ * iavf_lock_timeout - try to set bit but give up after timeout
+ * @adapter: board private structure
+ * @bit: bit to set
+ * @msecs: timeout in msecs
+ *
+ * Returns 0 on success, negative on failure
+ **/
+static int iavf_lock_timeout(struct iavf_adapter *adapter,
+			     enum iavf_critical_section_t bit,
+			     unsigned int msecs)
+{
+	unsigned int wait, delay = 10;
+
+	for (wait = 0; wait < msecs; wait += delay) {
+		if (!test_and_set_bit(bit, &adapter->crit_section))
+			return 0;
+
+		msleep(delay);
+	}
+
+	return -1;
+}
+
+/**
  * iavf_schedule_reset - Set the flags and schedule a reset event
  * @adapter: board private structure
  **/
@@ -220,21 +244,18 @@
 }
 
 /**
- * iavf_irq_enable_queues - Enable interrupt for specified queues
+ * iavf_irq_enable_queues - Enable interrupt for all queues
  * @adapter: board private structure
- * @mask: bitmap of queues to enable
  **/
-void iavf_irq_enable_queues(struct iavf_adapter *adapter, u32 mask)
+void iavf_irq_enable_queues(struct iavf_adapter *adapter)
 {
 	struct iavf_hw *hw = &adapter->hw;
 	int i;
 
 	for (i = 1; i < adapter->num_msix_vectors; i++) {
-		if (mask & BIT(i - 1)) {
-			wr32(hw, IAVF_VFINT_DYN_CTLN1(i - 1),
-			     IAVF_VFINT_DYN_CTLN1_INTENA_MASK |
-			     IAVF_VFINT_DYN_CTLN1_ITR_INDX_MASK);
-		}
+		wr32(hw, IAVF_VFINT_DYN_CTLN1(i - 1),
+		     IAVF_VFINT_DYN_CTLN1_INTENA_MASK |
+		     IAVF_VFINT_DYN_CTLN1_ITR_INDX_MASK);
 	}
 }
 
@@ -248,7 +269,7 @@
 	struct iavf_hw *hw = &adapter->hw;
 
 	iavf_misc_irq_enable(adapter);
-	iavf_irq_enable_queues(adapter, ~0);
+	iavf_irq_enable_queues(adapter);
 
 	if (flush)
 		iavf_flush(hw);
@@ -743,9 +764,8 @@
  *
  * Returns ptr to the filter object or NULL when no memory available.
  **/
-static struct
-iavf_mac_filter *iavf_add_filter(struct iavf_adapter *adapter,
-				 const u8 *macaddr)
+struct iavf_mac_filter *iavf_add_filter(struct iavf_adapter *adapter,
+					const u8 *macaddr)
 {
 	struct iavf_mac_filter *f;
 
@@ -762,6 +782,7 @@
 
 		list_add_tail(&f->list, &adapter->mac_filter_list);
 		f->add = true;
+		f->is_new_mac = true;
 		adapter->aq_required |= IAVF_FLAG_AQ_ADD_MAC_FILTER;
 	} else {
 		f->remove = false;
@@ -1368,19 +1389,16 @@
 static void iavf_free_q_vectors(struct iavf_adapter *adapter)
 {
 	int q_idx, num_q_vectors;
-	int napi_vectors;
 
 	if (!adapter->q_vectors)
 		return;
 
 	num_q_vectors = adapter->num_msix_vectors - NONQ_VECS;
-	napi_vectors = adapter->num_active_queues;
 
 	for (q_idx = 0; q_idx < num_q_vectors; q_idx++) {
 		struct iavf_q_vector *q_vector = &adapter->q_vectors[q_idx];
 
-		if (q_idx < napi_vectors)
-			netif_napi_del(&q_vector->napi);
+		netif_napi_del(&q_vector->napi);
 	}
 	kfree(adapter->q_vectors);
 	adapter->q_vectors = NULL;
@@ -1500,11 +1518,6 @@
 	set_bit(__IAVF_VSI_DOWN, adapter->vsi.state);
 
 	iavf_map_rings_to_vectors(adapter);
-
-	if (RSS_AQ(adapter))
-		adapter->aq_required |= IAVF_FLAG_AQ_CONFIGURE_RSS;
-	else
-		err = iavf_init_rss(adapter);
 err:
 	return err;
 }
@@ -1607,8 +1620,7 @@
 		iavf_set_promiscuous(adapter, FLAG_VF_MULTICAST_PROMISC);
 		return 0;
 	}
-
-	if ((adapter->aq_required & IAVF_FLAG_AQ_RELEASE_PROMISC) &&
+	if ((adapter->aq_required & IAVF_FLAG_AQ_RELEASE_PROMISC) ||
 	    (adapter->aq_required & IAVF_FLAG_AQ_RELEASE_ALLMULTI)) {
 		iavf_set_promiscuous(adapter, 0);
 		return 0;
@@ -1757,17 +1769,17 @@
 	struct net_device *netdev = adapter->netdev;
 	struct pci_dev *pdev = adapter->pdev;
 	struct iavf_hw *hw = &adapter->hw;
-	int err = 0, bufsz;
+	int err;
 
 	WARN_ON(adapter->state != __IAVF_INIT_GET_RESOURCES);
 	/* aq msg sent, awaiting reply */
 	if (!adapter->vf_res) {
-		bufsz = sizeof(struct virtchnl_vf_resource) +
-			(IAVF_MAX_VF_VSI *
-			sizeof(struct virtchnl_vsi_resource));
-		adapter->vf_res = kzalloc(bufsz, GFP_KERNEL);
-		if (!adapter->vf_res)
+		adapter->vf_res = kzalloc(IAVF_VIRTCHNL_VF_RESOURCE_SIZE,
+					  GFP_KERNEL);
+		if (!adapter->vf_res) {
+			err = -ENOMEM;
 			goto err;
+		}
 	}
 	err = iavf_get_vf_config(adapter);
 	if (err == IAVF_ERR_ADMIN_QUEUE_NO_WORK) {
@@ -1787,7 +1799,8 @@
 		goto err_alloc;
 	}
 
-	if (iavf_process_config(adapter))
+	err = iavf_process_config(adapter);
+	if (err)
 		goto err_alloc;
 	adapter->current_op = VIRTCHNL_OP_UNKNOWN;
 
@@ -1845,11 +1858,9 @@
 	netif_tx_stop_all_queues(netdev);
 	if (CLIENT_ALLOWED(adapter)) {
 		err = iavf_lan_add_device(adapter);
-		if (err) {
-			rtnl_unlock();
+		if (err)
 			dev_info(&pdev->dev, "Failed to add VF to client API service list: %d\n",
 				 err);
-		}
 	}
 	dev_info(&pdev->dev, "MAC address: %pM\n", adapter->hw.mac.addr);
 	if (netdev->features & NETIF_F_GRO)
@@ -1864,8 +1875,10 @@
 
 	adapter->rss_key = kzalloc(adapter->rss_key_size, GFP_KERNEL);
 	adapter->rss_lut = kzalloc(adapter->rss_lut_size, GFP_KERNEL);
-	if (!adapter->rss_key || !adapter->rss_lut)
+	if (!adapter->rss_key || !adapter->rss_lut) {
+		err = -ENOMEM;
 		goto err_mem;
+	}
 	if (RSS_AQ(adapter))
 		adapter->aq_required |= IAVF_FLAG_AQ_CONFIGURE_RSS;
 	else
@@ -1947,7 +1960,10 @@
 				iavf_send_api_ver(adapter);
 			}
 		} else {
-			if (!iavf_process_aq_command(adapter) &&
+			/* An error will be returned if no commands were
+			 * processed; use this opportunity to update stats
+			 */
+			if (iavf_process_aq_command(adapter) &&
 			    adapter->state == __IAVF_RUNNING)
 				iavf_request_stats(adapter);
 		}
@@ -1962,7 +1978,6 @@
 		/* check for hw reset */
 	reg_val = rd32(hw, IAVF_VF_ARQLEN1) & IAVF_VF_ARQLEN1_ARQENABLE_MASK;
 	if (!reg_val) {
-		adapter->state = __IAVF_RESETTING;
 		adapter->flags |= IAVF_FLAG_RESET_PENDING;
 		adapter->aq_required = 0;
 		adapter->current_op = VIRTCHNL_OP_UNKNOWN;
@@ -2035,9 +2050,9 @@
 
 	iavf_free_misc_irq(adapter);
 	iavf_reset_interrupt_capability(adapter);
-	iavf_free_queues(adapter);
 	iavf_free_q_vectors(adapter);
-	kfree(adapter->vf_res);
+	iavf_free_queues(adapter);
+	memset(adapter->vf_res, 0, IAVF_VIRTCHNL_VF_RESOURCE_SIZE);
 	iavf_shutdown_adminq(&adapter->hw);
 	adapter->netdev->flags &= ~IFF_UP;
 	clear_bit(__IAVF_IN_CRITICAL_TASK, &adapter->crit_section);
@@ -2065,9 +2080,9 @@
 	struct virtchnl_vf_resource *vfres = adapter->vf_res;
 	struct net_device *netdev = adapter->netdev;
 	struct iavf_hw *hw = &adapter->hw;
+	struct iavf_mac_filter *f, *ftmp;
 	struct iavf_vlan_filter *vlf;
 	struct iavf_cloud_filter *cf;
-	struct iavf_mac_filter *f;
 	u32 reg_val;
 	int i = 0, err;
 	bool running;
@@ -2078,6 +2093,10 @@
 	if (test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section))
 		return;
 
+	if (iavf_lock_timeout(adapter, __IAVF_IN_CRITICAL_TASK, 200)) {
+		schedule_work(&adapter->reset_task);
+		return;
+	}
 	while (test_and_set_bit(__IAVF_IN_CLIENT_TASK,
 				&adapter->crit_section))
 		usleep_range(500, 1000);
@@ -2126,6 +2145,7 @@
 	}
 
 	pci_set_master(adapter->pdev);
+	pci_restore_msi_state(adapter->pdev);
 
 	if (i == IAVF_RESET_WAIT_COUNT) {
 		dev_err(&adapter->pdev->dev, "Reset never finished (%x)\n",
@@ -2176,11 +2196,29 @@
 			goto reset_err;
 	}
 
+	if (RSS_AQ(adapter)) {
+		adapter->aq_required |= IAVF_FLAG_AQ_CONFIGURE_RSS;
+	} else {
+		err = iavf_init_rss(adapter);
+		if (err)
+			goto reset_err;
+	}
+
 	adapter->aq_required |= IAVF_FLAG_AQ_GET_CONFIG;
 	adapter->aq_required |= IAVF_FLAG_AQ_MAP_VECTORS;
 
 	spin_lock_bh(&adapter->mac_vlan_list_lock);
 
+	/* Delete filter for the current MAC address, it could have
+	 * been changed by the PF via administratively set MAC.
+	 * Will be re-added via VIRTCHNL_OP_GET_VF_RESOURCES.
+	 */
+	list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) {
+		if (ether_addr_equal(f->macaddr, adapter->hw.mac.addr)) {
+			list_del(&f->list);
+			kfree(f);
+		}
+	}
 	/* re-add all MAC filters */
 	list_for_each_entry(f, &adapter->mac_filter_list, list) {
 		f->add = true;
@@ -2274,6 +2312,8 @@
 	if (!event.msg_buf)
 		goto out;
 
+	if (iavf_lock_timeout(adapter, __IAVF_IN_CRITICAL_TASK, 200))
+		goto freedom;
 	do {
 		ret = iavf_clean_arq_element(hw, &event, &pending);
 		v_op = (enum virtchnl_ops)le32_to_cpu(event.desc.cookie_high);
@@ -2287,6 +2327,7 @@
 		if (pending != 0)
 			memset(event.msg_buf, 0, IAVF_MAX_AQ_BUF_SIZE);
 	} while (pending);
+	clear_bit(__IAVF_IN_CRITICAL_TASK, &adapter->crit_section);
 
 	if ((adapter->flags &
 	     (IAVF_FLAG_RESET_PENDING | IAVF_FLAG_RESET_NEEDED)) ||
@@ -2295,7 +2336,7 @@
 
 	/* check for error indications */
 	val = rd32(hw, hw->aq.arq.len);
-	if (val == 0xdeadbeef) /* indicates device in reset */
+	if (val == 0xdeadbeef || val == 0xffffffff) /* device in reset */
 		goto freedom;
 	oldval = val;
 	if (val & IAVF_VF_ARQLEN1_ARQVFE_MASK) {
@@ -2478,6 +2519,16 @@
 {
 	int speed = 0, ret = 0;
 
+	if (ADV_LINK_SUPPORT(adapter)) {
+		if (adapter->link_speed_mbps < U32_MAX) {
+			speed = adapter->link_speed_mbps;
+			goto validate_bw;
+		} else {
+			dev_err(&adapter->pdev->dev, "Unknown link speed\n");
+			return -EINVAL;
+		}
+	}
+
 	switch (adapter->link_speed) {
 	case IAVF_LINK_SPEED_40GB:
 		speed = 40000;
@@ -2501,6 +2552,7 @@
 		break;
 	}
 
+validate_bw:
 	if (max_tx_rate > speed) {
 		dev_err(&adapter->pdev->dev,
 			"Invalid tx rate specified\n");
@@ -2523,6 +2575,7 @@
 				   struct tc_mqprio_qopt_offload *mqprio_qopt)
 {
 	u64 total_max_rate = 0;
+	u32 tx_rate_rem = 0;
 	int i, num_qps = 0;
 	u64 tx_rate = 0;
 	int ret = 0;
@@ -2537,17 +2590,40 @@
 			return -EINVAL;
 		if (mqprio_qopt->min_rate[i]) {
 			dev_err(&adapter->pdev->dev,
-				"Invalid min tx rate (greater than 0) specified\n");
+				"Invalid min tx rate (greater than 0) specified for TC%d\n",
+				i);
 			return -EINVAL;
 		}
-		/*convert to Mbps */
+
+		/* convert to Mbps */
 		tx_rate = div_u64(mqprio_qopt->max_rate[i],
 				  IAVF_MBPS_DIVISOR);
+
+		if (mqprio_qopt->max_rate[i] &&
+		    tx_rate < IAVF_MBPS_QUANTA) {
+			dev_err(&adapter->pdev->dev,
+				"Invalid max tx rate for TC%d, minimum %dMbps\n",
+				i, IAVF_MBPS_QUANTA);
+			return -EINVAL;
+		}
+
+		(void)div_u64_rem(tx_rate, IAVF_MBPS_QUANTA, &tx_rate_rem);
+
+		if (tx_rate_rem != 0) {
+			dev_err(&adapter->pdev->dev,
+				"Invalid max tx rate for TC%d, not divisible by %d\n",
+				i, IAVF_MBPS_QUANTA);
+			return -EINVAL;
+		}
+
 		total_max_rate += tx_rate;
 		num_qps += mqprio_qopt->qopt.count[i];
 	}
-	if (num_qps > IAVF_MAX_REQ_QUEUES)
+	if (num_qps > adapter->num_active_queues) {
+		dev_err(&adapter->pdev->dev,
+			"Cannot support requested number of queues\n");
 		return -EINVAL;
+	}
 
 	ret = iavf_validate_tx_bandwidth(adapter, total_max_rate);
 	return ret;
@@ -2572,6 +2648,34 @@
 }
 
 /**
+ * iavf_is_tc_config_same - Compare the mqprio TC config with the
+ * TC config already configured on this adapter.
+ * @adapter: board private structure
+ * @mqprio_qopt: TC config received from kernel.
+ *
+ * This function compares the TC config received from the kernel
+ * with the config already configured on the adapter.
+ *
+ * Return: True if configuration is same, false otherwise.
+ **/
+static bool iavf_is_tc_config_same(struct iavf_adapter *adapter,
+				   struct tc_mqprio_qopt *mqprio_qopt)
+{
+	struct virtchnl_channel_info *ch = &adapter->ch_config.ch_info[0];
+	int i;
+
+	if (adapter->num_tc != mqprio_qopt->num_tc)
+		return false;
+
+	for (i = 0; i < adapter->num_tc; i++) {
+		if (ch[i].count != mqprio_qopt->count[i] ||
+		    ch[i].offset != mqprio_qopt->offset[i])
+			return false;
+	}
+	return true;
+}
+
+/**
  * __iavf_setup_tc - configure multiple traffic classes
  * @netdev: network interface device structure
  * @type_date: tc offload data
@@ -2627,7 +2731,7 @@
 		if (ret)
 			return ret;
 		/* Return if same TC config is requested */
-		if (adapter->num_tc == num_tc)
+		if (iavf_is_tc_config_same(adapter, &mqprio_qopt->qopt))
 			return 0;
 		adapter->num_tc = num_tc;
 
@@ -2976,11 +3080,11 @@
 	/* start out with flow type and eth type IPv4 to begin with */
 	filter->f.flow_type = VIRTCHNL_TCP_V4_FLOW;
 	err = iavf_parse_cls_flower(adapter, cls_flower, filter);
-	if (err < 0)
+	if (err)
 		goto err;
 
 	err = iavf_handle_tclass(adapter, tc, filter);
-	if (err < 0)
+	if (err)
 		goto err;
 
 	/* add filter to the list */
@@ -3052,9 +3156,6 @@
 static int iavf_setup_tc_cls_flower(struct iavf_adapter *adapter,
 				    struct flow_cls_offload *cls_flower)
 {
-	if (cls_flower->common.chain_index)
-		return -EOPNOTSUPP;
-
 	switch (cls_flower->command) {
 	case FLOW_CLS_REPLACE:
 		return iavf_configure_clsflower(adapter, cls_flower);
@@ -3078,6 +3179,11 @@
 static int iavf_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
 				  void *cb_priv)
 {
+	struct iavf_adapter *adapter = cb_priv;
+
+	if (!tc_cls_can_offload_and_chain0(adapter->netdev, type_data))
+		return -EOPNOTSUPP;
+
 	switch (type) {
 	case TC_SETUP_CLSFLOWER:
 		return iavf_setup_tc_cls_flower(cb_priv, type_data);
@@ -3260,8 +3366,11 @@
 		iavf_notify_client_l2_params(&adapter->vsi);
 		adapter->flags |= IAVF_FLAG_SERVICE_CLIENT_REQUESTED;
 	}
-	adapter->flags |= IAVF_FLAG_RESET_NEEDED;
-	queue_work(iavf_wq, &adapter->reset_task);
+
+	if (netif_running(netdev)) {
+		adapter->flags |= IAVF_FLAG_RESET_NEEDED;
+		queue_work(iavf_wq, &adapter->reset_task);
+	}
 
 	return 0;
 }
@@ -3365,7 +3474,8 @@
 {
 	struct iavf_adapter *adapter = netdev_priv(netdev);
 
-	if (!(adapter->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN))
+	if (adapter->vf_res &&
+	    !(adapter->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN))
 		features &= ~(NETIF_F_HW_VLAN_CTAG_TX |
 			      NETIF_F_HW_VLAN_CTAG_RX |
 			      NETIF_F_HW_VLAN_CTAG_FILTER);
@@ -3570,6 +3680,10 @@
 						    init_task.work);
 	struct iavf_hw *hw = &adapter->hw;
 
+	if (iavf_lock_timeout(adapter, __IAVF_IN_CRITICAL_TASK, 5000)) {
+		dev_warn(&adapter->pdev->dev, "failed to set __IAVF_IN_CRITICAL_TASK in %s\n", __FUNCTION__);
+		return;
+	}
 	switch (adapter->state) {
 	case __IAVF_STARTUP:
 		if (iavf_startup(adapter) < 0)
@@ -3582,14 +3696,14 @@
 	case __IAVF_INIT_GET_RESOURCES:
 		if (iavf_init_get_resources(adapter) < 0)
 			goto init_failed;
-		return;
+		goto out;
 	default:
 		goto init_failed;
 	}
 
 	queue_delayed_work(iavf_wq, &adapter->init_task,
 			   msecs_to_jiffies(30));
-	return;
+	goto out;
 init_failed:
 	if (++adapter->aq_wait_count > IAVF_AQ_MAX_ERR) {
 		dev_err(&adapter->pdev->dev,
@@ -3598,9 +3712,11 @@
 		iavf_shutdown_adminq(hw);
 		adapter->state = __IAVF_STARTUP;
 		queue_delayed_work(iavf_wq, &adapter->init_task, HZ * 5);
-		return;
+		goto out;
 	}
 	queue_delayed_work(iavf_wq, &adapter->init_task, HZ);
+out:
+	clear_bit(__IAVF_IN_CRITICAL_TASK, &adapter->crit_section);
 }
 
 /**
@@ -3617,9 +3733,12 @@
 	if (netif_running(netdev))
 		iavf_close(netdev);
 
+	if (iavf_lock_timeout(adapter, __IAVF_IN_CRITICAL_TASK, 5000))
+		dev_warn(&adapter->pdev->dev, "failed to set __IAVF_IN_CRITICAL_TASK in %s\n", __FUNCTION__);
 	/* Prevent the watchdog from running. */
 	adapter->state = __IAVF_REMOVE;
 	adapter->aq_required = 0;
+	clear_bit(__IAVF_IN_CRITICAL_TASK, &adapter->crit_section);
 
 #ifdef CONFIG_PM
 	pci_save_state(pdev);
@@ -3739,6 +3858,7 @@
 err_ioremap:
 	free_netdev(netdev);
 err_alloc_etherdev:
+	pci_disable_pcie_error_reporting(pdev);
 	pci_release_regions(pdev);
 err_pci_reg:
 err_dma:
@@ -3746,7 +3866,6 @@
 	return err;
 }
 
-#ifdef CONFIG_PM
 /**
  * iavf_suspend - Power management suspend routine
  * @pdev: PCI device information struct
@@ -3754,11 +3873,10 @@
  *
  * Called when the system (VM) is entering sleep/suspend.
  **/
-static int iavf_suspend(struct pci_dev *pdev, pm_message_t state)
+static int __maybe_unused iavf_suspend(struct device *dev_d)
 {
-	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct net_device *netdev = dev_get_drvdata(dev_d);
 	struct iavf_adapter *adapter = netdev_priv(netdev);
-	int retval = 0;
 
 	netif_device_detach(netdev);
 
@@ -3776,12 +3894,6 @@
 
 	clear_bit(__IAVF_IN_CRITICAL_TASK, &adapter->crit_section);
 
-	retval = pci_save_state(pdev);
-	if (retval)
-		return retval;
-
-	pci_disable_device(pdev);
-
 	return 0;
 }
 
@@ -3791,24 +3903,13 @@
  *
  * Called when the system (VM) is resumed from sleep/suspend.
  **/
-static int iavf_resume(struct pci_dev *pdev)
+static int __maybe_unused iavf_resume(struct device *dev_d)
 {
-	struct iavf_adapter *adapter = pci_get_drvdata(pdev);
-	struct net_device *netdev = adapter->netdev;
+	struct pci_dev *pdev = to_pci_dev(dev_d);
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct iavf_adapter *adapter = netdev_priv(netdev);
 	u32 err;
 
-	pci_set_power_state(pdev, PCI_D0);
-	pci_restore_state(pdev);
-	/* pci_restore_state clears dev->state_saved so call
-	 * pci_save_state to restore it.
-	 */
-	pci_save_state(pdev);
-
-	err = pci_enable_device_mem(pdev);
-	if (err) {
-		dev_err(&pdev->dev, "Cannot enable PCI device from suspend.\n");
-		return err;
-	}
 	pci_set_master(pdev);
 
 	rtnl_lock();
@@ -3832,7 +3933,6 @@
 	return err;
 }
 
-#endif /* CONFIG_PM */
 /**
  * iavf_remove - Device Removal Routine
  * @pdev: PCI device information struct
@@ -3867,10 +3967,6 @@
 				 err);
 	}
 
-	/* Shut down all the garbage mashers on the detention level */
-	adapter->state = __IAVF_REMOVE;
-	adapter->aq_required = 0;
-	adapter->flags &= ~IAVF_FLAG_REINIT_ITR_NEEDED;
 	iavf_request_reset(adapter);
 	msleep(50);
 	/* If the FW isn't responding, kick it once, but only once. */
@@ -3878,6 +3974,13 @@
 		iavf_request_reset(adapter);
 		msleep(50);
 	}
+	if (iavf_lock_timeout(adapter, __IAVF_IN_CRITICAL_TASK, 5000))
+		dev_warn(&adapter->pdev->dev, "failed to set __IAVF_IN_CRITICAL_TASK in %s\n", __FUNCTION__);
+
+	/* Shut down all the garbage mashers on the detention level */
+	adapter->state = __IAVF_REMOVE;
+	adapter->aq_required = 0;
+	adapter->flags &= ~IAVF_FLAG_REINIT_ITR_NEEDED;
 	iavf_free_all_tx_resources(adapter);
 	iavf_free_all_rx_resources(adapter);
 	iavf_misc_irq_disable(adapter);
@@ -3900,8 +4003,6 @@
 
 	iounmap(hw->hw_addr);
 	pci_release_regions(pdev);
-	iavf_free_all_tx_resources(adapter);
-	iavf_free_all_rx_resources(adapter);
 	iavf_free_queues(adapter);
 	kfree(adapter->vf_res);
 	spin_lock_bh(&adapter->mac_vlan_list_lock);
@@ -3934,16 +4035,15 @@
 	pci_disable_device(pdev);
 }
 
+static SIMPLE_DEV_PM_OPS(iavf_pm_ops, iavf_suspend, iavf_resume);
+
 static struct pci_driver iavf_driver = {
-	.name     = iavf_driver_name,
-	.id_table = iavf_pci_tbl,
-	.probe    = iavf_probe,
-	.remove   = iavf_remove,
-#ifdef CONFIG_PM
-	.suspend  = iavf_suspend,
-	.resume   = iavf_resume,
-#endif
-	.shutdown = iavf_shutdown,
+	.name      = iavf_driver_name,
+	.id_table  = iavf_pci_tbl,
+	.probe     = iavf_probe,
+	.remove    = iavf_remove,
+	.driver.pm = &iavf_pm_ops,
+	.shutdown  = iavf_shutdown,
 };
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/iavf/iavf_register.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/iavf/iavf_register.h
@@ -40,7 +40,7 @@
 #define IAVF_VFINT_DYN_CTL01_INTENA_MASK IAVF_MASK(0x1, IAVF_VFINT_DYN_CTL01_INTENA_SHIFT)
 #define IAVF_VFINT_DYN_CTL01_ITR_INDX_SHIFT 3
 #define IAVF_VFINT_DYN_CTL01_ITR_INDX_MASK IAVF_MASK(0x3, IAVF_VFINT_DYN_CTL01_ITR_INDX_SHIFT)
-#define IAVF_VFINT_DYN_CTLN1(_INTVF) (0x00003800 + ((_INTVF) * 4)) /* _i=0...15 */ /* Reset: VFR */
+#define IAVF_VFINT_DYN_CTLN1(_INTVF) (0x00003800 + ((_INTVF) * 4)) /* _i=0...63 */ /* Reset: VFR */
 #define IAVF_VFINT_DYN_CTLN1_INTENA_SHIFT 0
 #define IAVF_VFINT_DYN_CTLN1_INTENA_MASK IAVF_MASK(0x1, IAVF_VFINT_DYN_CTLN1_INTENA_SHIFT)
 #define IAVF_VFINT_DYN_CTLN1_SWINT_TRIG_SHIFT 2
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/iavf/iavf_txrx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/iavf/iavf_txrx.c
@@ -114,8 +114,11 @@
 {
 	u32 head, tail;
 
+	/* underlying hardware might not allow access and/or always return
+	 * 0 for the head/tail registers so just use the cached values
+	 */
 	head = ring->next_to_clean;
-	tail = readl(ring->tail);
+	tail = ring->next_to_use;
 
 	if (head != tail)
 		return (head < tail) ?
@@ -1058,7 +1061,7 @@
 		cpu_to_le64((u64)IAVF_RX_DESC_FLTSTAT_RSS_HASH <<
 			    IAVF_RX_DESC_STATUS_FLTSTAT_SHIFT);
 
-	if (ring->netdev->features & NETIF_F_RXHASH)
+	if (!(ring->netdev->features & NETIF_F_RXHASH))
 		return;
 
 	if ((rx_desc->wb.qword1.status_error_len & rss_mask) == rss_mask) {
@@ -1263,11 +1266,10 @@
 {
 	struct iavf_rx_buffer *rx_buffer;
 
-	if (!size)
-		return NULL;
-
 	rx_buffer = &rx_ring->rx_bi[rx_ring->next_to_clean];
 	prefetchw(rx_buffer->page);
+	if (!size)
+		return rx_buffer;
 
 	/* we are reusing so sync this buffer for CPU use */
 	dma_sync_single_range_for_cpu(rx_ring->dev,
@@ -1372,7 +1374,7 @@
 #endif
 	struct sk_buff *skb;
 
-	if (!rx_buffer)
+	if (!rx_buffer || !size)
 		return NULL;
 	/* prefetch first cache line of first page */
 	va = page_address(rx_buffer->page) + rx_buffer->page_offset;
@@ -1532,7 +1534,7 @@
 		/* exit if we failed to retrieve a buffer */
 		if (!skb) {
 			rx_ring->rx_stats.alloc_buff_failed++;
-			if (rx_buffer)
+			if (rx_buffer && size)
 				rx_buffer->pagecnt_bias++;
 			break;
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
@@ -139,7 +139,8 @@
 	       VIRTCHNL_VF_OFFLOAD_ENCAP |
 	       VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM |
 	       VIRTCHNL_VF_OFFLOAD_REQ_QUEUES |
-	       VIRTCHNL_VF_OFFLOAD_ADQ;
+	       VIRTCHNL_VF_OFFLOAD_ADQ |
+	       VIRTCHNL_VF_CAP_ADV_LINK_SPEED;
 
 	adapter->current_op = VIRTCHNL_OP_GET_VF_RESOURCES;
 	adapter->aq_required &= ~IAVF_FLAG_AQ_GET_CONFIG;
@@ -240,11 +241,14 @@
 void iavf_configure_queues(struct iavf_adapter *adapter)
 {
 	struct virtchnl_vsi_queue_config_info *vqci;
-	struct virtchnl_queue_pair_info *vqpi;
+	int i, max_frame = adapter->vf_res->max_mtu;
 	int pairs = adapter->num_active_queues;
-	int i, max_frame = IAVF_MAX_RXBUFFER;
+	struct virtchnl_queue_pair_info *vqpi;
 	size_t len;
 
+	if (max_frame > IAVF_MAX_RXBUFFER || !max_frame)
+		max_frame = IAVF_MAX_RXBUFFER;
+
 	if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
 		/* bail because we already have a command pending */
 		dev_err(&adapter->pdev->dev, "Cannot configure queues, command %d pending\n",
@@ -564,6 +568,47 @@
 }
 
 /**
+ * iavf_mac_add_ok
+ * @adapter: adapter structure
+ *
+ * Submit list of filters based on PF response.
+ **/
+static void iavf_mac_add_ok(struct iavf_adapter *adapter)
+{
+	struct iavf_mac_filter *f, *ftmp;
+
+	spin_lock_bh(&adapter->mac_vlan_list_lock);
+	list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) {
+		f->is_new_mac = false;
+	}
+	spin_unlock_bh(&adapter->mac_vlan_list_lock);
+}
+
+/**
+ * iavf_mac_add_reject
+ * @adapter: adapter structure
+ *
+ * Remove filters from list based on PF response.
+ **/
+static void iavf_mac_add_reject(struct iavf_adapter *adapter)
+{
+	struct net_device *netdev = adapter->netdev;
+	struct iavf_mac_filter *f, *ftmp;
+
+	spin_lock_bh(&adapter->mac_vlan_list_lock);
+	list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) {
+		if (f->remove && ether_addr_equal(f->macaddr, netdev->dev_addr))
+			f->remove = false;
+
+		if (f->is_new_mac) {
+			list_del(&f->list);
+			kfree(f);
+		}
+	}
+	spin_unlock_bh(&adapter->mac_vlan_list_lock);
+}
+
+/**
  * iavf_add_vlans
  * @adapter: adapter structure
  *
@@ -918,6 +963,8 @@
 	iavf_send_pf_msg(adapter, VIRTCHNL_OP_DISABLE_VLAN_STRIPPING, NULL, 0);
 }
 
+#define IAVF_MAX_SPEED_STRLEN	13
+
 /**
  * iavf_print_link_message - print link up or down
  * @adapter: adapter structure
@@ -927,37 +974,99 @@
 static void iavf_print_link_message(struct iavf_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
-	char *speed = "Unknown ";
+	int link_speed_mbps;
+	char *speed;
 
 	if (!adapter->link_up) {
 		netdev_info(netdev, "NIC Link is Down\n");
 		return;
 	}
 
+	speed = kcalloc(1, IAVF_MAX_SPEED_STRLEN, GFP_KERNEL);
+	if (!speed)
+		return;
+
+	if (ADV_LINK_SUPPORT(adapter)) {
+		link_speed_mbps = adapter->link_speed_mbps;
+		goto print_link_msg;
+	}
+
 	switch (adapter->link_speed) {
 	case IAVF_LINK_SPEED_40GB:
-		speed = "40 G";
+		link_speed_mbps = SPEED_40000;
 		break;
 	case IAVF_LINK_SPEED_25GB:
-		speed = "25 G";
+		link_speed_mbps = SPEED_25000;
 		break;
 	case IAVF_LINK_SPEED_20GB:
-		speed = "20 G";
+		link_speed_mbps = SPEED_20000;
 		break;
 	case IAVF_LINK_SPEED_10GB:
-		speed = "10 G";
+		link_speed_mbps = SPEED_10000;
 		break;
 	case IAVF_LINK_SPEED_1GB:
-		speed = "1000 M";
+		link_speed_mbps = SPEED_1000;
 		break;
 	case IAVF_LINK_SPEED_100MB:
-		speed = "100 M";
+		link_speed_mbps = SPEED_100;
 		break;
 	default:
+		link_speed_mbps = SPEED_UNKNOWN;
 		break;
 	}
 
-	netdev_info(netdev, "NIC Link is Up %sbps Full Duplex\n", speed);
+print_link_msg:
+	if (link_speed_mbps > SPEED_1000) {
+		if (link_speed_mbps == SPEED_2500)
+			snprintf(speed, IAVF_MAX_SPEED_STRLEN, "2.5 Gbps");
+		else
+			/* convert to Gbps inline */
+			snprintf(speed, IAVF_MAX_SPEED_STRLEN, "%d %s",
+				 link_speed_mbps / 1000, "Gbps");
+	} else if (link_speed_mbps == SPEED_UNKNOWN) {
+		snprintf(speed, IAVF_MAX_SPEED_STRLEN, "%s", "Unknown Mbps");
+	} else {
+		snprintf(speed, IAVF_MAX_SPEED_STRLEN, "%u %s",
+			 link_speed_mbps, "Mbps");
+	}
+
+	netdev_info(netdev, "NIC Link is Up Speed is %s Full Duplex\n", speed);
+	kfree(speed);
+}
+
+/**
+ * iavf_get_vpe_link_status
+ * @adapter: adapter structure
+ * @vpe: virtchnl_pf_event structure
+ *
+ * Helper function for determining the link status
+ **/
+static bool
+iavf_get_vpe_link_status(struct iavf_adapter *adapter,
+			 struct virtchnl_pf_event *vpe)
+{
+	if (ADV_LINK_SUPPORT(adapter))
+		return vpe->event_data.link_event_adv.link_status;
+	else
+		return vpe->event_data.link_event.link_status;
+}
+
+/**
+ * iavf_set_adapter_link_speed_from_vpe
+ * @adapter: adapter structure for which we are setting the link speed
+ * @vpe: virtchnl_pf_event structure that contains the link speed we are setting
+ *
+ * Helper function for setting iavf_adapter link speed
+ **/
+static void
+iavf_set_adapter_link_speed_from_vpe(struct iavf_adapter *adapter,
+				     struct virtchnl_pf_event *vpe)
+{
+	if (ADV_LINK_SUPPORT(adapter))
+		adapter->link_speed_mbps =
+			vpe->event_data.link_event_adv.link_speed;
+	else
+		adapter->link_speed = vpe->event_data.link_event.link_speed;
 }
 
 /**
@@ -1187,12 +1296,11 @@
 	if (v_opcode == VIRTCHNL_OP_EVENT) {
 		struct virtchnl_pf_event *vpe =
 			(struct virtchnl_pf_event *)msg;
-		bool link_up = vpe->event_data.link_event.link_status;
+		bool link_up = iavf_get_vpe_link_status(adapter, vpe);
 
 		switch (vpe->event) {
 		case VIRTCHNL_EVENT_LINK_CHANGE:
-			adapter->link_speed =
-				vpe->event_data.link_event.link_speed;
+			iavf_set_adapter_link_speed_from_vpe(adapter, vpe);
 
 			/* we've already got the right link status, bail */
 			if (adapter->link_up == link_up)
@@ -1252,6 +1360,7 @@
 		case VIRTCHNL_OP_ADD_ETH_ADDR:
 			dev_err(&adapter->pdev->dev, "Failed to add MAC filter, error %s\n",
 				iavf_stat_str(&adapter->hw, v_retval));
+			iavf_mac_add_reject(adapter);
 			/* restore administratively set MAC address */
 			ether_addr_copy(adapter->hw.mac.addr, netdev->dev_addr);
 			break;
@@ -1321,10 +1430,11 @@
 		}
 	}
 	switch (v_opcode) {
-	case VIRTCHNL_OP_ADD_ETH_ADDR: {
+	case VIRTCHNL_OP_ADD_ETH_ADDR:
+		if (!v_retval)
+			iavf_mac_add_ok(adapter);
 		if (!ether_addr_equal(netdev->dev_addr, adapter->hw.mac.addr))
 			ether_addr_copy(netdev->dev_addr, adapter->hw.mac.addr);
-		}
 		break;
 	case VIRTCHNL_OP_GET_STATS: {
 		struct iavf_eth_stats *stats =
@@ -1359,6 +1469,9 @@
 			ether_addr_copy(netdev->perm_addr,
 					adapter->hw.mac.addr);
 		}
+		spin_lock_bh(&adapter->mac_vlan_list_lock);
+		iavf_add_filter(adapter, adapter->hw.mac.addr);
+		spin_unlock_bh(&adapter->mac_vlan_list_lock);
 		iavf_process_config(adapter);
 		}
 		break;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ice/ice_common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ice/ice_common.c
@@ -436,6 +436,7 @@
 static enum ice_status ice_init_fltr_mgmt_struct(struct ice_hw *hw)
 {
 	struct ice_switch_info *sw;
+	enum ice_status status;
 
 	hw->switch_info = devm_kzalloc(ice_hw_to_dev(hw),
 				       sizeof(*hw->switch_info), GFP_KERNEL);
@@ -446,7 +447,12 @@
 
 	INIT_LIST_HEAD(&sw->vsi_list_map_head);
 
-	return ice_init_def_sw_recp(hw);
+	status = ice_init_def_sw_recp(hw);
+	if (status) {
+		devm_kfree(ice_hw_to_dev(hw), hw->switch_info);
+		return status;
+	}
+	return 0;
 }
 
 /**
@@ -934,7 +940,7 @@
  */
 enum ice_status ice_check_reset(struct ice_hw *hw)
 {
-	u32 cnt, reg = 0, grst_delay;
+	u32 cnt, reg = 0, grst_delay, uld_mask;
 
 	/* Poll for Device Active state in case a recent CORER, GLOBR,
 	 * or EMPR has occurred. The grst delay value is in 100ms units.
@@ -956,13 +962,20 @@
 		return ICE_ERR_RESET_FAILED;
 	}
 
-#define ICE_RESET_DONE_MASK	(GLNVM_ULD_CORER_DONE_M | \
-				 GLNVM_ULD_GLOBR_DONE_M)
+#define ICE_RESET_DONE_MASK	(GLNVM_ULD_PCIER_DONE_M |\
+				 GLNVM_ULD_PCIER_DONE_1_M |\
+				 GLNVM_ULD_CORER_DONE_M |\
+				 GLNVM_ULD_GLOBR_DONE_M |\
+				 GLNVM_ULD_POR_DONE_M |\
+				 GLNVM_ULD_POR_DONE_1_M |\
+				 GLNVM_ULD_PCIER_DONE_2_M)
+
+	uld_mask = ICE_RESET_DONE_MASK;
 
 	/* Device is Active; check Global Reset processes are done */
 	for (cnt = 0; cnt < ICE_PF_RESET_WAIT_COUNT; cnt++) {
-		reg = rd32(hw, GLNVM_ULD) & ICE_RESET_DONE_MASK;
-		if (reg == ICE_RESET_DONE_MASK) {
+		reg = rd32(hw, GLNVM_ULD) & uld_mask;
+		if (reg == uld_mask) {
 			ice_debug(hw, ICE_DBG_INIT,
 				  "Global reset processes done. %d\n", cnt);
 			break;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ice/ice_controlq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ice/ice_controlq.c
@@ -199,7 +199,9 @@
 		cq->rq.r.rq_bi[i].pa = 0;
 		cq->rq.r.rq_bi[i].size = 0;
 	}
+	cq->rq.r.rq_bi = NULL;
 	devm_kfree(ice_hw_to_dev(hw), cq->rq.dma_head);
+	cq->rq.dma_head = NULL;
 
 	return ICE_ERR_NO_MEMORY;
 }
@@ -245,7 +247,9 @@
 		cq->sq.r.sq_bi[i].pa = 0;
 		cq->sq.r.sq_bi[i].size = 0;
 	}
+	cq->sq.r.sq_bi = NULL;
 	devm_kfree(ice_hw_to_dev(hw), cq->sq.dma_head);
+	cq->sq.dma_head = NULL;
 
 	return ICE_ERR_NO_MEMORY;
 }
@@ -304,6 +308,28 @@
 	return 0;
 }
 
+#define ICE_FREE_CQ_BUFS(hw, qi, ring)					\
+do {									\
+	int i;								\
+	/* free descriptors */						\
+	if ((qi)->ring.r.ring##_bi)					\
+		for (i = 0; i < (qi)->num_##ring##_entries; i++)	\
+			if ((qi)->ring.r.ring##_bi[i].pa) {		\
+				dmam_free_coherent(ice_hw_to_dev(hw),	\
+					(qi)->ring.r.ring##_bi[i].size,	\
+					(qi)->ring.r.ring##_bi[i].va,	\
+					(qi)->ring.r.ring##_bi[i].pa);	\
+					(qi)->ring.r.ring##_bi[i].va = NULL;\
+					(qi)->ring.r.ring##_bi[i].pa = 0;\
+					(qi)->ring.r.ring##_bi[i].size = 0;\
+		}							\
+	/* free the buffer info list */					\
+	if ((qi)->ring.cmd_buf)						\
+		devm_kfree(ice_hw_to_dev(hw), (qi)->ring.cmd_buf);	\
+	/* free DMA head */						\
+	devm_kfree(ice_hw_to_dev(hw), (qi)->ring.dma_head);		\
+} while (0)
+
 /**
  * ice_init_sq - main initialization routine for Control ATQ
  * @hw: pointer to the hardware structure
@@ -357,6 +383,7 @@
 	goto init_ctrlq_exit;
 
 init_ctrlq_free_rings:
+	ICE_FREE_CQ_BUFS(hw, cq, sq);
 	ice_free_cq_ring(hw, &cq->sq);
 
 init_ctrlq_exit:
@@ -416,33 +443,13 @@
 	goto init_ctrlq_exit;
 
 init_ctrlq_free_rings:
+	ICE_FREE_CQ_BUFS(hw, cq, rq);
 	ice_free_cq_ring(hw, &cq->rq);
 
 init_ctrlq_exit:
 	return ret_code;
 }
 
-#define ICE_FREE_CQ_BUFS(hw, qi, ring)					\
-do {									\
-	int i;								\
-	/* free descriptors */						\
-	for (i = 0; i < (qi)->num_##ring##_entries; i++)		\
-		if ((qi)->ring.r.ring##_bi[i].pa) {			\
-			dmam_free_coherent(ice_hw_to_dev(hw),		\
-					   (qi)->ring.r.ring##_bi[i].size,\
-					   (qi)->ring.r.ring##_bi[i].va,\
-					   (qi)->ring.r.ring##_bi[i].pa);\
-			(qi)->ring.r.ring##_bi[i].va = NULL;		\
-			(qi)->ring.r.ring##_bi[i].pa = 0;		\
-			(qi)->ring.r.ring##_bi[i].size = 0;		\
-		}							\
-	/* free the buffer info list */					\
-	if ((qi)->ring.cmd_buf)						\
-		devm_kfree(ice_hw_to_dev(hw), (qi)->ring.cmd_buf);	\
-	/* free DMA head */						\
-	devm_kfree(ice_hw_to_dev(hw), (qi)->ring.dma_head);		\
-} while (0)
-
 /**
  * ice_shutdown_sq - shutdown the Control ATQ
  * @hw: pointer to the hardware structure
@@ -948,7 +955,7 @@
 		if (ice_sq_done(hw, cq))
 			break;
 
-		mdelay(1);
+		udelay(ICE_CTL_Q_SQ_CMD_USEC);
 		total_delay++;
 	} while (total_delay < cq->sq_cmd_timeout);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ice/ice_controlq.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ice/ice_controlq.h
@@ -31,8 +31,9 @@
 	ICE_CTL_Q_MAILBOX,
 };
 
-/* Control Queue default settings */
-#define ICE_CTL_Q_SQ_CMD_TIMEOUT	250  /* msecs */
+/* Control Queue timeout settings - max delay 1s */
+#define ICE_CTL_Q_SQ_CMD_TIMEOUT	10000 /* Count 10000 times */
+#define ICE_CTL_Q_SQ_CMD_USEC		100   /* Check every 100usec */
 
 struct ice_ctl_q_ring {
 	void *dma_head;			/* Virtual address to DMA head */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ice/ice_devids.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ice/ice_devids.h
@@ -5,11 +5,50 @@
 #define _ICE_DEVIDS_H_
 
 /* Device IDs */
+/* Intel(R) Ethernet Connection E823-L for backplane */
+#define ICE_DEV_ID_E823L_BACKPLANE	0x124C
+/* Intel(R) Ethernet Connection E823-L for SFP */
+#define ICE_DEV_ID_E823L_SFP		0x124D
+/* Intel(R) Ethernet Connection E823-L/X557-AT 10GBASE-T */
+#define ICE_DEV_ID_E823L_10G_BASE_T	0x124E
+/* Intel(R) Ethernet Connection E823-L 1GbE */
+#define ICE_DEV_ID_E823L_1GBE		0x124F
+/* Intel(R) Ethernet Connection E823-L for QSFP */
+#define ICE_DEV_ID_E823L_QSFP		0x151D
 /* Intel(R) Ethernet Controller E810-C for backplane */
 #define ICE_DEV_ID_E810C_BACKPLANE	0x1591
 /* Intel(R) Ethernet Controller E810-C for QSFP */
 #define ICE_DEV_ID_E810C_QSFP		0x1592
 /* Intel(R) Ethernet Controller E810-C for SFP */
 #define ICE_DEV_ID_E810C_SFP		0x1593
-
+/* Intel(R) Ethernet Controller E810-XXV for SFP */
+#define ICE_DEV_ID_E810_XXV_SFP		0x159B
+/* Intel(R) Ethernet Connection E823-C for backplane */
+#define ICE_DEV_ID_E823C_BACKPLANE	0x188A
+/* Intel(R) Ethernet Connection E823-C for QSFP */
+#define ICE_DEV_ID_E823C_QSFP		0x188B
+/* Intel(R) Ethernet Connection E823-C for SFP */
+#define ICE_DEV_ID_E823C_SFP		0x188C
+/* Intel(R) Ethernet Connection E823-C/X557-AT 10GBASE-T */
+#define ICE_DEV_ID_E823C_10G_BASE_T	0x188D
+/* Intel(R) Ethernet Connection E823-C 1GbE */
+#define ICE_DEV_ID_E823C_SGMII		0x188E
+/* Intel(R) Ethernet Connection E822-C for backplane */
+#define ICE_DEV_ID_E822C_BACKPLANE	0x1890
+/* Intel(R) Ethernet Connection E822-C for QSFP */
+#define ICE_DEV_ID_E822C_QSFP		0x1891
+/* Intel(R) Ethernet Connection E822-C for SFP */
+#define ICE_DEV_ID_E822C_SFP		0x1892
+/* Intel(R) Ethernet Connection E822-C/X557-AT 10GBASE-T */
+#define ICE_DEV_ID_E822C_10G_BASE_T	0x1893
+/* Intel(R) Ethernet Connection E822-C 1GbE */
+#define ICE_DEV_ID_E822C_SGMII		0x1894
+/* Intel(R) Ethernet Connection E822-X for backplane */
+#define ICE_DEV_ID_E822X_BACKPLANE	0x1897
+/* Intel(R) Ethernet Connection E822-L for SFP */
+#define ICE_DEV_ID_E822L_SFP		0x1898
+/* Intel(R) Ethernet Connection E822-L/X557-AT 10GBASE-T */
+#define ICE_DEV_ID_E822L_10G_BASE_T	0x1899
+/* Intel(R) Ethernet Connection E822-L 1GbE */
+#define ICE_DEV_ID_E822L_SGMII		0x189A
 #endif /* _ICE_DEVIDS_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ice/ice_ethtool.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ice/ice_ethtool.c
@@ -138,9 +138,6 @@
 	QINT_RQCTL(0),
 	PFINT_OICR_ENA,
 	QRX_ITR(0),
-	PF0INT_ITR_0(0),
-	PF0INT_ITR_1(0),
-	PF0INT_ITR_2(0),
 };
 
 struct ice_priv_flag {
@@ -619,7 +616,8 @@
 		rx_desc = ICE_RX_DESC(rx_ring, i);
 
 		if (!(rx_desc->wb.status_error0 &
-		    cpu_to_le16(ICE_TX_DESC_CMD_EOP | ICE_TX_DESC_CMD_RS)))
+		    (cpu_to_le16(BIT(ICE_RX_FLEX_DESC_STATUS0_DD_S)) |
+		     cpu_to_le16(BIT(ICE_RX_FLEX_DESC_STATUS0_EOF_S)))))
 			continue;
 
 		rx_buf = &rx_ring->rx_buf[i];
@@ -2338,6 +2336,42 @@
 }
 
 /**
+ * ice_set_phy_type_from_speed - set phy_types based on speeds
+ * and advertised modes
+ * @ks: ethtool link ksettings struct
+ * @phy_type_low: pointer to the lower part of phy_type
+ * @phy_type_high: pointer to the higher part of phy_type
+ * @adv_link_speed: targeted link speeds bitmap
+ */
+static void
+ice_set_phy_type_from_speed(const struct ethtool_link_ksettings *ks,
+			    u64 *phy_type_low, u64 *phy_type_high,
+			    u16 adv_link_speed)
+{
+	/* Handle 1000M speed in a special way because ice_update_phy_type
+	 * enables all link modes, but having mixed copper and optical
+	 * standards is not supported.
+	 */
+	adv_link_speed &= ~ICE_AQ_LINK_SPEED_1000MB;
+
+	if (ethtool_link_ksettings_test_link_mode(ks, advertising,
+						  1000baseT_Full))
+		*phy_type_low |= ICE_PHY_TYPE_LOW_1000BASE_T |
+				 ICE_PHY_TYPE_LOW_1G_SGMII;
+
+	if (ethtool_link_ksettings_test_link_mode(ks, advertising,
+						  1000baseKX_Full))
+		*phy_type_low |= ICE_PHY_TYPE_LOW_1000BASE_KX;
+
+	if (ethtool_link_ksettings_test_link_mode(ks, advertising,
+						  1000baseX_Full))
+		*phy_type_low |= ICE_PHY_TYPE_LOW_1000BASE_SX |
+				 ICE_PHY_TYPE_LOW_1000BASE_LX;
+
+	ice_update_phy_type(phy_type_low, phy_type_high, adv_link_speed);
+}
+
+/**
  * ice_set_link_ksettings - Set Speed and Duplex
  * @netdev: network interface device structure
  * @ks: ethtool ksettings
@@ -2472,7 +2506,8 @@
 		adv_link_speed = curr_link_speed;
 
 	/* Convert the advertise link speeds to their corresponded PHY_TYPE */
-	ice_update_phy_type(&phy_type_low, &phy_type_high, adv_link_speed);
+	ice_set_phy_type_from_speed(ks, &phy_type_low, &phy_type_high,
+				    adv_link_speed);
 
 	if (!autoneg_changed && adv_link_speed == curr_link_speed) {
 		netdev_info(netdev, "Nothing changed, exiting without setting anything.\n");
@@ -2635,14 +2670,14 @@
 	netdev_info(netdev, "Changing Tx descriptor count from %d to %d\n",
 		    vsi->tx_rings[0]->count, new_tx_cnt);
 
-	tx_rings = devm_kcalloc(&pf->pdev->dev, vsi->alloc_txq,
+	tx_rings = devm_kcalloc(&pf->pdev->dev, vsi->num_txq,
 				sizeof(*tx_rings), GFP_KERNEL);
 	if (!tx_rings) {
 		err = -ENOMEM;
 		goto done;
 	}
 
-	for (i = 0; i < vsi->alloc_txq; i++) {
+	ice_for_each_txq(vsi, i) {
 		/* clone ring and setup updated count */
 		tx_rings[i] = *vsi->tx_rings[i];
 		tx_rings[i].count = new_tx_cnt;
@@ -2667,14 +2702,14 @@
 	netdev_info(netdev, "Changing Rx descriptor count from %d to %d\n",
 		    vsi->rx_rings[0]->count, new_rx_cnt);
 
-	rx_rings = devm_kcalloc(&pf->pdev->dev, vsi->alloc_rxq,
+	rx_rings = devm_kcalloc(&pf->pdev->dev, vsi->num_rxq,
 				sizeof(*rx_rings), GFP_KERNEL);
 	if (!rx_rings) {
 		err = -ENOMEM;
 		goto done;
 	}
 
-	for (i = 0; i < vsi->alloc_rxq; i++) {
+	ice_for_each_rxq(vsi, i) {
 		/* clone ring and setup updated count */
 		rx_rings[i] = *vsi->rx_rings[i];
 		rx_rings[i].count = new_rx_cnt;
@@ -2712,7 +2747,7 @@
 		ice_down(vsi);
 
 		if (tx_rings) {
-			for (i = 0; i < vsi->alloc_txq; i++) {
+			ice_for_each_txq(vsi, i) {
 				ice_free_tx_ring(vsi->tx_rings[i]);
 				*vsi->tx_rings[i] = tx_rings[i];
 			}
@@ -2720,7 +2755,7 @@
 		}
 
 		if (rx_rings) {
-			for (i = 0; i < vsi->alloc_rxq; i++) {
+			ice_for_each_rxq(vsi, i) {
 				ice_free_rx_ring(vsi->rx_rings[i]);
 				/* copy the real tail offset */
 				rx_rings[i].tail = vsi->rx_rings[i]->tail;
@@ -2744,7 +2779,7 @@
 free_tx:
 	/* error cleanup if the Rx allocations failed after getting Tx */
 	if (tx_rings) {
-		for (i = 0; i < vsi->alloc_txq; i++)
+		ice_for_each_txq(vsi, i)
 			ice_free_tx_ring(&tx_rings[i]);
 		devm_kfree(&pf->pdev->dev, tx_rings);
 	}
@@ -2916,13 +2951,6 @@
 	else
 		return -EINVAL;
 
-	/* Tell the OS link is going down, the link will go back up when fw
-	 * says it is ready asynchronously
-	 */
-	ice_print_link_msg(vsi, false);
-	netif_carrier_off(netdev);
-	netif_tx_stop_all_queues(netdev);
-
 	/* Set the FC mode and only restart AN if link is up */
 	status = ice_set_fc(pi, &aq_failures, link_up);
 
@@ -3368,10 +3396,17 @@
 	struct ice_vsi *vsi = np->vsi;
 
 	if (q_num < 0) {
-		int i;
+		int v_idx;
+
+		ice_for_each_q_vector(vsi, v_idx) {
+			/* In some cases if DCB is configured the num_[rx|tx]q
+			 * can be less than vsi->num_q_vectors. This check
+			 * accounts for that so we don't report a false failure
+			 */
+			if (v_idx >= vsi->num_rxq && v_idx >= vsi->num_txq)
+				goto set_complete;
 
-		ice_for_each_q_vector(vsi, i) {
-			if (ice_set_q_coalesce(vsi, ec, i))
+			if (ice_set_q_coalesce(vsi, ec, v_idx))
 				return -EINVAL;
 		}
 		goto set_complete;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ice/ice_flex_pipe.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ice/ice_flex_pipe.c
@@ -1535,10 +1535,12 @@
 		es->ref_count = devm_kcalloc(ice_hw_to_dev(hw), es->count,
 					     sizeof(*es->ref_count),
 					     GFP_KERNEL);
+		if (!es->ref_count)
+			goto err;
 
 		es->written = devm_kcalloc(ice_hw_to_dev(hw), es->count,
 					   sizeof(*es->written), GFP_KERNEL);
-		if (!es->ref_count)
+		if (!es->written)
 			goto err;
 	}
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ice/ice_hw_autogen.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ice/ice_hw_autogen.h
@@ -6,9 +6,6 @@
 #ifndef _ICE_HW_AUTOGEN_H_
 #define _ICE_HW_AUTOGEN_H_
 
-#define PF0INT_ITR_0(_i)			(0x03000004 + ((_i) * 4096))
-#define PF0INT_ITR_1(_i)			(0x03000008 + ((_i) * 4096))
-#define PF0INT_ITR_2(_i)			(0x0300000C + ((_i) * 4096))
 #define QTX_COMM_DBELL(_DBQM)			(0x002C0000 + ((_DBQM) * 4))
 #define QTX_COMM_HEAD(_DBQM)			(0x000E0000 + ((_DBQM) * 4))
 #define QTX_COMM_HEAD_HEAD_S			0
@@ -34,6 +31,7 @@
 #define PF_FW_ATQLEN_ATQOVFL_M			BIT(29)
 #define PF_FW_ATQLEN_ATQCRIT_M			BIT(30)
 #define VF_MBX_ARQLEN(_VF)			(0x0022BC00 + ((_VF) * 4))
+#define VF_MBX_ATQLEN(_VF)			(0x0022A800 + ((_VF) * 4))
 #define PF_FW_ATQLEN_ATQENABLE_M		BIT(31)
 #define PF_FW_ATQT				0x00080400
 #define PF_MBX_ARQBAH				0x0022E400
@@ -273,8 +271,14 @@
 #define GLNVM_GENS_SR_SIZE_S			5
 #define GLNVM_GENS_SR_SIZE_M			ICE_M(0x7, 5)
 #define GLNVM_ULD				0x000B6008
+#define GLNVM_ULD_PCIER_DONE_M			BIT(0)
+#define GLNVM_ULD_PCIER_DONE_1_M		BIT(1)
 #define GLNVM_ULD_CORER_DONE_M			BIT(3)
 #define GLNVM_ULD_GLOBR_DONE_M			BIT(4)
+#define GLNVM_ULD_POR_DONE_M			BIT(5)
+#define GLNVM_ULD_POR_DONE_1_M			BIT(8)
+#define GLNVM_ULD_PCIER_DONE_2_M		BIT(9)
+#define GLNVM_ULD_PE_DONE_M			BIT(10)
 #define GLPCI_CNF2				0x000BE004
 #define GLPCI_CNF2_CACHELINE_SIZE_M		BIT(1)
 #define PF_FUNC_RID				0x0009E880
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ice/ice_lib.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ice/ice_lib.c
@@ -1015,8 +1015,7 @@
 
 	ctxt->info.q_opt_rss = ((lut_type << ICE_AQ_VSI_Q_OPT_RSS_LUT_S) &
 				ICE_AQ_VSI_Q_OPT_RSS_LUT_M) |
-				((hash_type << ICE_AQ_VSI_Q_OPT_RSS_HASH_S) &
-				 ICE_AQ_VSI_Q_OPT_RSS_HASH_M);
+				(hash_type & ICE_AQ_VSI_Q_OPT_RSS_HASH_M);
 }
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ice/ice_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ice/ice_main.c
@@ -2900,7 +2900,7 @@
 	if (err) {
 		dev_err(dev, "ice_init_interrupt_scheme failed: %d\n", err);
 		err = -EIO;
-		goto err_init_interrupt_unroll;
+		goto err_init_vsi_unroll;
 	}
 
 	/* Driver is mostly up */
@@ -2986,6 +2986,7 @@
 	ice_free_irq_msix_misc(pf);
 err_init_interrupt_unroll:
 	ice_clear_interrupt_scheme(pf);
+err_init_vsi_unroll:
 	devm_kfree(dev, pf->vsi);
 err_init_pf_unroll:
 	ice_deinit_pf(pf);
@@ -3004,9 +3005,6 @@
 	struct ice_pf *pf = pci_get_drvdata(pdev);
 	int i;
 
-	if (!pf)
-		return;
-
 	for (i = 0; i < ICE_MAX_RESET_WAIT; i++) {
 		if (!ice_is_reset_in_progress(pf->state))
 			break;
@@ -3178,6 +3176,26 @@
 	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E810C_BACKPLANE), 0 },
 	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E810C_QSFP), 0 },
 	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E810C_SFP), 0 },
+	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E810_XXV_SFP), 0 },
+	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E823C_BACKPLANE), 0 },
+	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E823C_QSFP), 0 },
+	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E823C_SFP), 0 },
+	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E823C_10G_BASE_T), 0 },
+	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E823C_SGMII), 0 },
+	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E822C_BACKPLANE), 0 },
+	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E822C_QSFP), 0 },
+	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E822C_SFP), 0 },
+	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E822C_10G_BASE_T), 0 },
+	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E822C_SGMII), 0 },
+	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E822X_BACKPLANE), 0 },
+	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E822L_SFP), 0 },
+	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E822L_10G_BASE_T), 0 },
+	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E822L_SGMII), 0 },
+	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E823L_BACKPLANE), 0 },
+	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E823L_SFP), 0 },
+	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E823L_10G_BASE_T), 0 },
+	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E823L_1GBE), 0 },
+	{ PCI_VDEVICE(INTEL, ICE_DEV_ID_E823L_QSFP), 0 },
 	/* required last entry */
 	{ 0, }
 };
@@ -3213,7 +3231,7 @@
 	pr_info("%s - version %s\n", ice_driver_string, ice_drv_ver);
 	pr_info("%s\n", ice_copyright);
 
-	ice_wq = alloc_workqueue("%s", WQ_MEM_RECLAIM, 0, KBUILD_MODNAME);
+	ice_wq = alloc_workqueue("%s", 0, 0, KBUILD_MODNAME);
 	if (!ice_wq) {
 		pr_err("Failed to create workqueue\n");
 		return -ENOMEM;
@@ -3494,11 +3512,10 @@
 {
 	int err;
 
-	if (vsi->netdev) {
+	if (vsi->netdev && vsi->type == ICE_VSI_PF) {
 		ice_set_rx_mode(vsi->netdev);
 
 		err = ice_vsi_vlan_setup(vsi);
-
 		if (err)
 			return err;
 	}
@@ -3557,13 +3574,19 @@
 
 	if (vsi->port_info &&
 	    (vsi->port_info->phy.link_info.link_info & ICE_AQ_LINK_UP) &&
-	    vsi->netdev) {
+	    vsi->netdev && vsi->type == ICE_VSI_PF) {
 		ice_print_link_msg(vsi, true);
 		netif_tx_start_all_queues(vsi->netdev);
 		netif_carrier_on(vsi->netdev);
 	}
 
-	ice_service_task_schedule(pf);
+	/* Perform an initial read of the statistics registers now to
+	 * set the baseline so counters are ready when interface is up
+	 */
+	ice_update_eth_stats(vsi);
+
+	if (vsi->type == ICE_VSI_PF)
+		ice_service_task_schedule(pf);
 
 	return 0;
 }
@@ -3970,8 +3993,13 @@
 	}
 
 	ice_for_each_txq(vsi, i) {
-		vsi->tx_rings[i]->netdev = vsi->netdev;
-		err = ice_setup_tx_ring(vsi->tx_rings[i]);
+		struct ice_ring *ring = vsi->tx_rings[i];
+
+		if (!ring)
+			return -EINVAL;
+
+		ring->netdev = vsi->netdev;
+		err = ice_setup_tx_ring(ring);
 		if (err)
 			break;
 	}
@@ -3996,8 +4024,13 @@
 	}
 
 	ice_for_each_rxq(vsi, i) {
-		vsi->rx_rings[i]->netdev = vsi->netdev;
-		err = ice_setup_rx_ring(vsi->rx_rings[i]);
+		struct ice_ring *ring = vsi->rx_rings[i];
+
+		if (!ring)
+			return -EINVAL;
+
+		ring->netdev = vsi->netdev;
+		err = ice_setup_rx_ring(ring);
 		if (err)
 			break;
 	}
@@ -4581,6 +4614,8 @@
 	pf_sw = pf->first_sw;
 	/* find the attribute in the netlink message */
 	br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
+	if (!br_spec)
+		return -EINVAL;
 
 	nla_for_each_nested(attr, br_spec, rem) {
 		__u16 mode;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ice/ice_nvm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ice/ice_nvm.c
@@ -289,6 +289,32 @@
 
 	hw->nvm.eetrack = (eetrack_hi << 16) | eetrack_lo;
 
+	switch (hw->device_id) {
+	/* the following devices do not have boot_cfg_tlv yet */
+	case ICE_DEV_ID_E823C_BACKPLANE:
+	case ICE_DEV_ID_E823C_QSFP:
+	case ICE_DEV_ID_E823C_SFP:
+	case ICE_DEV_ID_E823C_10G_BASE_T:
+	case ICE_DEV_ID_E823C_SGMII:
+	case ICE_DEV_ID_E822C_BACKPLANE:
+	case ICE_DEV_ID_E822C_QSFP:
+	case ICE_DEV_ID_E822C_10G_BASE_T:
+	case ICE_DEV_ID_E822C_SGMII:
+	case ICE_DEV_ID_E822C_SFP:
+	case ICE_DEV_ID_E822X_BACKPLANE:
+	case ICE_DEV_ID_E822L_SFP:
+	case ICE_DEV_ID_E822L_10G_BASE_T:
+	case ICE_DEV_ID_E822L_SGMII:
+	case ICE_DEV_ID_E823L_BACKPLANE:
+	case ICE_DEV_ID_E823L_SFP:
+	case ICE_DEV_ID_E823L_10G_BASE_T:
+	case ICE_DEV_ID_E823L_1GBE:
+	case ICE_DEV_ID_E823L_QSFP:
+		return status;
+	default:
+		break;
+	}
+
 	return status;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ice/ice_sched.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ice/ice_sched.c
@@ -27,9 +27,8 @@
 	if (!root)
 		return ICE_ERR_NO_MEMORY;
 
-	/* coverity[suspicious_sizeof] */
 	root->children = devm_kcalloc(ice_hw_to_dev(hw), hw->max_children[0],
-				      sizeof(*root), GFP_KERNEL);
+				      sizeof(*root->children), GFP_KERNEL);
 	if (!root->children) {
 		devm_kfree(ice_hw_to_dev(hw), root);
 		return ICE_ERR_NO_MEMORY;
@@ -181,10 +180,9 @@
 	if (!node)
 		return ICE_ERR_NO_MEMORY;
 	if (hw->max_children[layer]) {
-		/* coverity[suspicious_sizeof] */
 		node->children = devm_kcalloc(ice_hw_to_dev(hw),
 					      hw->max_children[layer],
-					      sizeof(*node), GFP_KERNEL);
+					      sizeof(*node->children), GFP_KERNEL);
 		if (!node->children) {
 			devm_kfree(ice_hw_to_dev(hw), node);
 			return ICE_ERR_NO_MEMORY;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ice/ice_switch.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ice/ice_switch.c
@@ -1279,6 +1279,9 @@
 			ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,
 						vsi_list_id);
 
+		if (!m_entry->vsi_list_info)
+			return ICE_ERR_NO_MEMORY;
+
 		/* If this entry was large action then the large action needs
 		 * to be updated to point to FWD to VSI list
 		 */
@@ -1296,7 +1299,7 @@
 
 		/* A rule already exists with the new VSI being added */
 		if (test_bit(vsi_handle, m_entry->vsi_list_info->vsi_map))
-			return 0;
+			return -EEXIST;
 
 		/* Update the previously created VSI list set with
 		 * the new VSI ID passed in
@@ -2266,6 +2269,7 @@
 	return ((fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI &&
 		 fm_entry->fltr_info.vsi_handle == vsi_handle) ||
 		(fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI_LIST &&
+		 fm_entry->vsi_list_info &&
 		 (test_bit(vsi_handle, fm_entry->vsi_list_info->vsi_map))));
 }
 
@@ -2338,14 +2342,12 @@
 		return ICE_ERR_PARAM;
 
 	list_for_each_entry(fm_entry, lkup_list_head, list_entry) {
-		struct ice_fltr_info *fi;
-
-		fi = &fm_entry->fltr_info;
-		if (!fi || !ice_vsi_uses_fltr(fm_entry, vsi_handle))
+		if (!ice_vsi_uses_fltr(fm_entry, vsi_handle))
 			continue;
 
 		status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle,
-							vsi_list_head, fi);
+							vsi_list_head,
+							&fm_entry->fltr_info);
 		if (status)
 			return status;
 	}
@@ -2625,7 +2627,7 @@
 		else
 			status = ice_set_vsi_promisc(hw, vsi_handle,
 						     promisc_mask, vlan_id);
-		if (status)
+		if (status && status != -EEXIST)
 			break;
 	}
 
@@ -2663,7 +2665,7 @@
 					  &remove_list_head);
 	mutex_unlock(rule_lock);
 	if (status)
-		return;
+		goto free_fltr_list;
 
 	switch (lkup) {
 	case ICE_SW_LKUP_MAC:
@@ -2686,6 +2688,7 @@
 		break;
 	}
 
+free_fltr_list:
 	list_for_each_entry_safe(fm_entry, tmp, &remove_list_head, list_entry) {
 		list_del(&fm_entry->list_entry);
 		devm_kfree(ice_hw_to_dev(hw), fm_entry);
@@ -2748,8 +2751,6 @@
 		if (!itr->vsi_list_info ||
 		    !test_bit(vsi_handle, itr->vsi_list_info->vsi_map))
 			continue;
-		/* Clearing it so that the logic can add it back */
-		clear_bit(vsi_handle, itr->vsi_list_info->vsi_map);
 		f_entry.fltr_info.vsi_handle = vsi_handle;
 		f_entry.fltr_info.fltr_act = ICE_FWD_TO_VSI;
 		/* update the src in case it is VSI num */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ice/ice_txrx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ice/ice_txrx.c
@@ -2109,6 +2109,7 @@
 	struct ice_tx_offload_params offload = { 0 };
 	struct ice_vsi *vsi = tx_ring->vsi;
 	struct ice_tx_buf *first;
+	struct ethhdr *eth;
 	unsigned int count;
 	int tso, csum;
 
@@ -2156,7 +2157,9 @@
 		goto out_drop;
 
 	/* allow CONTROL frames egress from main VSI if FW LLDP disabled */
-	if (unlikely(skb->priority == TC_PRIO_CONTROL &&
+	eth = (struct ethhdr *)skb_mac_header(skb);
+	if (unlikely((skb->priority == TC_PRIO_CONTROL ||
+		      eth->h_proto == htons(ETH_P_LLDP)) &&
 		     vsi->type == ICE_VSI_PF &&
 		     vsi->port_info->is_sw_lldp))
 		offload.cd_qw1 |= (u64)(ICE_TX_DESC_DTYPE_CTX |
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ice/ice_type.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ice/ice_type.h
@@ -48,7 +48,7 @@
 /* FW update timeout definitions are in milliseconds */
 #define ICE_NVM_TIMEOUT			180000
 #define ICE_CHANGE_LOCK_TIMEOUT		1000
-#define ICE_GLOBAL_CFG_LOCK_TIMEOUT	3000
+#define ICE_GLOBAL_CFG_LOCK_TIMEOUT	5000
 
 enum ice_aq_res_access_type {
 	ICE_RES_READ = 1,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c
@@ -317,8 +317,9 @@
 	pf->num_alloc_vfs = 0;
 	for (i = 0; i < tmp; i++) {
 		if (test_bit(ICE_VF_STATE_INIT, pf->vf[i].vf_states)) {
-			/* disable VF qp mappings */
+			/* disable VF qp mappings and set VF disable state */
 			ice_dis_vf_mappings(&pf->vf[i]);
+			set_bit(ICE_VF_STATE_DIS, pf->vf[i].vf_states);
 			ice_free_vf_res(&pf->vf[i]);
 		}
 	}
@@ -383,13 +384,15 @@
 	 */
 	clear_bit(ICE_VF_STATE_INIT, vf->vf_states);
 
-	/* VF_MBX_ARQLEN is cleared by PFR, so the driver needs to clear it
-	 * in the case of VFR. If this is done for PFR, it can mess up VF
-	 * resets because the VF driver may already have started cleanup
-	 * by the time we get here.
-	 */
-	if (!is_pfr)
-		wr32(hw, VF_MBX_ARQLEN(vf_abs_id), 0);
+	/* VF_MBX_ARQLEN and VF_MBX_ATQLEN are cleared by PFR, so the driver
+	 * needs to clear them in the case of VFR/VFLR. If this is done for
+	 * PFR, it can mess up VF resets because the VF driver may already
+	 * have started cleanup by the time we get here.
+	 */
+	if (!is_pfr) {
+		wr32(hw, VF_MBX_ARQLEN(vf->vf_id), 0);
+		wr32(hw, VF_MBX_ATQLEN(vf->vf_id), 0);
+	}
 
 	/* In the case of a VFLR, the HW has already reset the VF and we
 	 * just need to clean up, so don't hit the VFRTRIG register.
@@ -1287,9 +1290,12 @@
 	if (!vf || vf->vf_id >= vf->pf->num_alloc_vfs)
 		return;
 
-	/* verify if the VF is in either init or active before proceeding */
-	if (!test_bit(ICE_VF_STATE_INIT, vf->vf_states) &&
-	    !test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states))
+	/* Bail out if VF is in disabled state, neither initialized, nor active
+	 * state - otherwise proceed with notifications
+	 */
+	if ((!test_bit(ICE_VF_STATE_INIT, vf->vf_states) &&
+	     !test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) ||
+	    test_bit(ICE_VF_STATE_DIS, vf->vf_states))
 		return;
 
 	pfe.event = VIRTCHNL_EVENT_RESET_IMPENDING;
@@ -1869,8 +1875,8 @@
 	enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS;
 	struct virtchnl_queue_select *vqs =
 		(struct virtchnl_queue_select *)msg;
+	struct ice_eth_stats stats = { 0 };
 	struct ice_pf *pf = vf->pf;
-	struct ice_eth_stats stats;
 	struct ice_vsi *vsi;
 
 	if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) {
@@ -1889,7 +1895,6 @@
 		goto error_param;
 	}
 
-	memset(&stats, 0, sizeof(struct ice_eth_stats));
 	ice_update_eth_stats(vsi);
 
 	stats = vsi->eth_stats;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/igb/e1000_82575.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/igb/e1000_82575.c
@@ -530,7 +530,7 @@
 		dev_spec->module_plugged = true;
 		if (eth_flags->e1000_base_lx || eth_flags->e1000_base_sx) {
 			hw->phy.media_type = e1000_media_type_internal_serdes;
-		} else if (eth_flags->e100_base_fx) {
+		} else if (eth_flags->e100_base_fx || eth_flags->e100_base_lx) {
 			dev_spec->sgmii_active = true;
 			hw->phy.media_type = e1000_media_type_internal_serdes;
 		} else if (eth_flags->e1000_base_t) {
@@ -657,14 +657,10 @@
 			break;
 		}
 
-		/* do not change link mode for 100BaseFX */
-		if (dev_spec->eth_flags.e100_base_fx)
-			break;
-
 		/* change current link mode setting */
 		ctrl_ext &= ~E1000_CTRL_EXT_LINK_MODE_MASK;
 
-		if (hw->phy.media_type == e1000_media_type_copper)
+		if (dev_spec->sgmii_active)
 			ctrl_ext |= E1000_CTRL_EXT_LINK_MODE_SGMII;
 		else
 			ctrl_ext |= E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/igb/e1000_mac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/igb/e1000_mac.c
@@ -425,7 +425,7 @@
 static u32 igb_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
 {
 	u32 hash_value, hash_mask;
-	u8 bit_shift = 0;
+	u8 bit_shift = 1;
 
 	/* Register count multiplied by bits per register */
 	hash_mask = (hw->mac.mta_reg_count * 32) - 1;
@@ -433,7 +433,7 @@
 	/* For a mc_filter_type of 0, bit_shift is the number of left-shifts
 	 * where 0xFF would still fall within the hash mask.
 	 */
-	while (hash_mask >> bit_shift != 0xFF)
+	while (hash_mask >> bit_shift != 0xFF && bit_shift < 4)
 		bit_shift++;
 
 	/* The portion of the address that is used for the hash table
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/igb/igb.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/igb/igb.h
@@ -32,11 +32,11 @@
 /* TX/RX descriptor defines */
 #define IGB_DEFAULT_TXD		256
 #define IGB_DEFAULT_TX_WORK	128
-#define IGB_MIN_TXD		80
+#define IGB_MIN_TXD		64
 #define IGB_MAX_TXD		4096
 
 #define IGB_DEFAULT_RXD		256
-#define IGB_MIN_RXD		80
+#define IGB_MIN_RXD		64
 #define IGB_MAX_RXD		4096
 
 #define IGB_DEFAULT_ITR		3 /* dynamic */
@@ -594,6 +594,8 @@
 	struct igb_mac_addr *mac_table;
 	struct vf_mac_filter vf_macs;
 	struct vf_mac_filter *vf_mac_list;
+	/* lock for VF resources */
+	spinlock_t vfs_lock;
 };
 
 /* flags controlling PTP/1588 function */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/igb/igb_ethtool.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/igb/igb_ethtool.c
@@ -143,7 +143,8 @@
 	u32 speed;
 	u32 supported, advertising;
 
-	status = rd32(E1000_STATUS);
+	status = pm_runtime_suspended(&adapter->pdev->dev) ?
+		 0 : rd32(E1000_STATUS);
 	if (hw->phy.media_type == e1000_media_type_copper) {
 
 		supported = (SUPPORTED_10baseT_Half |
@@ -181,7 +182,7 @@
 				advertising &= ~ADVERTISED_1000baseKX_Full;
 			}
 		}
-		if (eth_flags->e100_base_fx) {
+		if (eth_flags->e100_base_fx || eth_flags->e100_base_lx) {
 			supported |= SUPPORTED_100baseT_Full;
 			advertising |= ADVERTISED_100baseT_Full;
 		}
@@ -813,6 +814,8 @@
 		 */
 		ret_val = hw->nvm.ops.read(hw, last_word, 1,
 				   &eeprom_buff[last_word - first_word]);
+		if (ret_val)
+			goto out;
 	}
 
 	/* Device's eeprom is always little-endian, word addressable */
@@ -832,6 +835,7 @@
 		hw->nvm.ops.update(hw);
 
 	igb_set_fw_version(adapter);
+out:
 	kfree(eeprom_buff);
 	return ret_val;
 }
@@ -1401,6 +1405,8 @@
 			*data = 1;
 			return -1;
 		}
+		wr32(E1000_IVAR_MISC, E1000_IVAR_VALID << 8);
+		wr32(E1000_EIMS, BIT(0));
 	} else if (adapter->flags & IGB_FLAG_HAS_MSI) {
 		shared_int = false;
 		if (request_irq(irq,
@@ -2991,11 +2997,15 @@
 	if (err)
 		goto err_out_w_lock;
 
-	igb_update_ethtool_nfc_entry(adapter, input, input->sw_idx);
+	err = igb_update_ethtool_nfc_entry(adapter, input, input->sw_idx);
+	if (err)
+		goto err_out_input_filter;
 
 	spin_unlock(&adapter->nfc_lock);
 	return 0;
 
+err_out_input_filter:
+	igb_erase_filter(adapter, input);
 err_out_w_lock:
 	spin_unlock(&adapter->nfc_lock);
 err_out:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/igb/igb_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/igb/igb_main.c
@@ -674,6 +674,10 @@
 	dca_register_notify(&dca_notifier);
 #endif
 	ret = pci_register_driver(&igb_driver);
+#ifdef CONFIG_IGB_DCA
+	if (ret)
+		dca_unregister_notify(&dca_notifier);
+#endif
 	return ret;
 }
 
@@ -940,6 +944,7 @@
  **/
 static int igb_request_msix(struct igb_adapter *adapter)
 {
+	unsigned int num_q_vectors = adapter->num_q_vectors;
 	struct net_device *netdev = adapter->netdev;
 	int i, err = 0, vector = 0, free_vector = 0;
 
@@ -948,7 +953,13 @@
 	if (err)
 		goto err_out;
 
-	for (i = 0; i < adapter->num_q_vectors; i++) {
+	if (num_q_vectors > MAX_Q_VECTORS) {
+		num_q_vectors = MAX_Q_VECTORS;
+		dev_warn(&adapter->pdev->dev,
+			 "The number of queue vectors (%d) is higher than max allowed (%d)\n",
+			 adapter->num_q_vectors, MAX_Q_VECTORS);
+	}
+	for (i = 0; i < num_q_vectors; i++) {
 		struct igb_q_vector *q_vector = adapter->q_vector[i];
 
 		vector++;
@@ -1206,8 +1217,12 @@
 	if (!q_vector) {
 		q_vector = kzalloc(size, GFP_KERNEL);
 	} else if (size > ksize(q_vector)) {
-		kfree_rcu(q_vector, rcu);
-		q_vector = kzalloc(size, GFP_KERNEL);
+		struct igb_q_vector *new_q_vector;
+
+		new_q_vector = kzalloc(size, GFP_KERNEL);
+		if (new_q_vector)
+			kfree_rcu(q_vector, rcu);
+		q_vector = new_q_vector;
 	} else {
 		memset(q_vector, 0, size);
 	}
@@ -1687,14 +1702,15 @@
  **/
 static void igb_config_tx_modes(struct igb_adapter *adapter, int queue)
 {
-	struct igb_ring *ring = adapter->tx_ring[queue];
 	struct net_device *netdev = adapter->netdev;
 	struct e1000_hw *hw = &adapter->hw;
+	struct igb_ring *ring;
 	u32 tqavcc, tqavctrl;
 	u16 value;
 
 	WARN_ON(hw->mac.type != e1000_i210);
 	WARN_ON(queue < 0 || queue > 1);
+	ring = adapter->tx_ring[queue];
 
 	/* If any of the Qav features is enabled, configure queues as SR and
 	 * with HIGH PRIO. If none is, then configure them with LOW PRIO and
@@ -2651,7 +2667,8 @@
 			}
 
 			input->filter.match_flags |= IGB_FILTER_FLAG_VLAN_TCI;
-			input->filter.vlan_tci = match.key->vlan_priority;
+			input->filter.vlan_tci =
+				(__force __be16)match.key->vlan_priority;
 		}
 	}
 
@@ -3468,6 +3485,7 @@
 err_ioremap:
 	free_netdev(netdev);
 err_alloc_etherdev:
+	pci_disable_pcie_error_reporting(pdev);
 	pci_release_mem_regions(pdev);
 err_pci_reg:
 err_dma:
@@ -3481,6 +3499,7 @@
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct igb_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
+	unsigned long flags;
 
 	/* reclaim resources allocated to VFs */
 	if (adapter->vf_data) {
@@ -3493,12 +3512,13 @@
 			pci_disable_sriov(pdev);
 			msleep(500);
 		}
-
+		spin_lock_irqsave(&adapter->vfs_lock, flags);
 		kfree(adapter->vf_mac_list);
 		adapter->vf_mac_list = NULL;
 		kfree(adapter->vf_data);
 		adapter->vf_data = NULL;
 		adapter->vfs_allocated_count = 0;
+		spin_unlock_irqrestore(&adapter->vfs_lock, flags);
 		wr32(E1000_IOVCTL, E1000_IOVCTL_REUSE_VFQ);
 		wrfl();
 		msleep(100);
@@ -3694,8 +3714,9 @@
 	struct pci_dev *pdev = adapter->pdev;
 	struct e1000_hw *hw = &adapter->hw;
 
-	/* Virtualization features not supported on i210 family. */
-	if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211))
+	/* Virtualization features not supported on i210 and 82580 family. */
+	if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211) ||
+	    (hw->mac.type == e1000_82580))
 		return;
 
 	/* Of the below we really only want the effect of getting
@@ -3819,6 +3840,9 @@
 
 	spin_lock_init(&adapter->nfc_lock);
 	spin_lock_init(&adapter->stats64_lock);
+
+	/* init spinlock to avoid concurrency of VF resources */
+	spin_lock_init(&adapter->vfs_lock);
 #ifdef CONFIG_PCI_IOV
 	switch (hw->mac.type) {
 	case e1000_82576:
@@ -4326,8 +4350,7 @@
 		else
 			mrqc |= E1000_MRQC_ENABLE_VMDQ;
 	} else {
-		if (hw->mac.type != e1000_i211)
-			mrqc |= E1000_MRQC_ENABLE_RSS_MQ;
+		mrqc |= E1000_MRQC_ENABLE_RSS_MQ;
 	}
 	igb_vmm_control(adapter);
 
@@ -4534,6 +4557,10 @@
 static void igb_set_rx_buffer_len(struct igb_adapter *adapter,
 				  struct igb_ring *rx_ring)
 {
+#if (PAGE_SIZE < 8192)
+	struct e1000_hw *hw = &adapter->hw;
+#endif
+
 	/* set build_skb and buffer size flags */
 	clear_ring_build_skb_enabled(rx_ring);
 	clear_ring_uses_large_buffer(rx_ring);
@@ -4544,10 +4571,9 @@
 	set_ring_build_skb_enabled(rx_ring);
 
 #if (PAGE_SIZE < 8192)
-	if (adapter->max_frame_size <= IGB_MAX_FRAME_BUILD_SKB)
-		return;
-
-	set_ring_uses_large_buffer(rx_ring);
+	if (adapter->max_frame_size > IGB_MAX_FRAME_BUILD_SKB ||
+	    rd32(E1000_RCTL) & E1000_RCTL_SBP)
+		set_ring_uses_large_buffer(rx_ring);
 #endif
 }
 
@@ -4657,6 +4683,8 @@
 					       DMA_TO_DEVICE);
 		}
 
+		tx_buffer->next_to_watch = NULL;
+
 		/* move us one more past the eop_desc for start of next pkt */
 		tx_buffer++;
 		i++;
@@ -5307,7 +5335,8 @@
 				break;
 			}
 
-			if (adapter->link_speed != SPEED_1000)
+			if (adapter->link_speed != SPEED_1000 ||
+			    !hw->phy.ops.read_reg)
 				goto no_wait;
 
 			/* wait for Remote receiver status OK */
@@ -6194,9 +6223,18 @@
 	struct igb_adapter *adapter;
 	adapter = container_of(work, struct igb_adapter, reset_task);
 
+	rtnl_lock();
+	/* If we're already down or resetting, just bail */
+	if (test_bit(__IGB_DOWN, &adapter->state) ||
+	    test_bit(__IGB_RESETTING, &adapter->state)) {
+		rtnl_unlock();
+		return;
+	}
+
 	igb_dump(adapter);
 	netdev_err(adapter->netdev, "Reset adapter\n");
 	igb_reinit_locked(adapter);
+	rtnl_unlock();
 }
 
 /**
@@ -6445,77 +6483,85 @@
 	}
 }
 
+static void igb_perout(struct igb_adapter *adapter, int tsintr_tt)
+{
+	int pin = ptp_find_pin(adapter->ptp_clock, PTP_PF_PEROUT, tsintr_tt);
+	struct e1000_hw *hw = &adapter->hw;
+	struct timespec64 ts;
+	u32 tsauxc;
+
+	if (pin < 0 || pin >= IGB_N_PEROUT)
+		return;
+
+	spin_lock(&adapter->tmreg_lock);
+	ts = timespec64_add(adapter->perout[pin].start,
+			    adapter->perout[pin].period);
+	/* u32 conversion of tv_sec is safe until y2106 */
+	wr32((tsintr_tt == 1) ? E1000_TRGTTIML1 : E1000_TRGTTIML0, ts.tv_nsec);
+	wr32((tsintr_tt == 1) ? E1000_TRGTTIMH1 : E1000_TRGTTIMH0, (u32)ts.tv_sec);
+	tsauxc = rd32(E1000_TSAUXC);
+	tsauxc |= TSAUXC_EN_TT0;
+	wr32(E1000_TSAUXC, tsauxc);
+	adapter->perout[pin].start = ts;
+	spin_unlock(&adapter->tmreg_lock);
+}
+
+static void igb_extts(struct igb_adapter *adapter, int tsintr_tt)
+{
+	int pin = ptp_find_pin(adapter->ptp_clock, PTP_PF_EXTTS, tsintr_tt);
+	struct e1000_hw *hw = &adapter->hw;
+	struct ptp_clock_event event;
+	u32 sec, nsec;
+
+	if (pin < 0 || pin >= IGB_N_EXTTS)
+		return;
+
+	nsec = rd32((tsintr_tt == 1) ? E1000_AUXSTMPL1 : E1000_AUXSTMPL0);
+	sec  = rd32((tsintr_tt == 1) ? E1000_AUXSTMPH1 : E1000_AUXSTMPH0);
+	event.type = PTP_CLOCK_EXTTS;
+	event.index = tsintr_tt;
+	event.timestamp = sec * 1000000000ULL + nsec;
+	ptp_clock_event(adapter->ptp_clock, &event);
+}
+
 static void igb_tsync_interrupt(struct igb_adapter *adapter)
 {
+	const u32 mask = (TSINTR_SYS_WRAP | E1000_TSICR_TXTS |
+			  TSINTR_TT0 | TSINTR_TT1 |
+			  TSINTR_AUTT0 | TSINTR_AUTT1);
 	struct e1000_hw *hw = &adapter->hw;
+	u32 tsicr = rd32(E1000_TSICR);
 	struct ptp_clock_event event;
-	struct timespec64 ts;
-	u32 ack = 0, tsauxc, sec, nsec, tsicr = rd32(E1000_TSICR);
+
+	if (hw->mac.type == e1000_82580) {
+		/* 82580 has a hardware bug that requires an explicit
+		 * write to clear the TimeSync interrupt cause.
+		 */
+		wr32(E1000_TSICR, tsicr & mask);
+	}
 
 	if (tsicr & TSINTR_SYS_WRAP) {
 		event.type = PTP_CLOCK_PPS;
 		if (adapter->ptp_caps.pps)
 			ptp_clock_event(adapter->ptp_clock, &event);
-		ack |= TSINTR_SYS_WRAP;
 	}
 
 	if (tsicr & E1000_TSICR_TXTS) {
 		/* retrieve hardware timestamp */
 		schedule_work(&adapter->ptp_tx_work);
-		ack |= E1000_TSICR_TXTS;
 	}
 
-	if (tsicr & TSINTR_TT0) {
-		spin_lock(&adapter->tmreg_lock);
-		ts = timespec64_add(adapter->perout[0].start,
-				    adapter->perout[0].period);
-		/* u32 conversion of tv_sec is safe until y2106 */
-		wr32(E1000_TRGTTIML0, ts.tv_nsec);
-		wr32(E1000_TRGTTIMH0, (u32)ts.tv_sec);
-		tsauxc = rd32(E1000_TSAUXC);
-		tsauxc |= TSAUXC_EN_TT0;
-		wr32(E1000_TSAUXC, tsauxc);
-		adapter->perout[0].start = ts;
-		spin_unlock(&adapter->tmreg_lock);
-		ack |= TSINTR_TT0;
-	}
-
-	if (tsicr & TSINTR_TT1) {
-		spin_lock(&adapter->tmreg_lock);
-		ts = timespec64_add(adapter->perout[1].start,
-				    adapter->perout[1].period);
-		wr32(E1000_TRGTTIML1, ts.tv_nsec);
-		wr32(E1000_TRGTTIMH1, (u32)ts.tv_sec);
-		tsauxc = rd32(E1000_TSAUXC);
-		tsauxc |= TSAUXC_EN_TT1;
-		wr32(E1000_TSAUXC, tsauxc);
-		adapter->perout[1].start = ts;
-		spin_unlock(&adapter->tmreg_lock);
-		ack |= TSINTR_TT1;
-	}
-
-	if (tsicr & TSINTR_AUTT0) {
-		nsec = rd32(E1000_AUXSTMPL0);
-		sec  = rd32(E1000_AUXSTMPH0);
-		event.type = PTP_CLOCK_EXTTS;
-		event.index = 0;
-		event.timestamp = sec * 1000000000ULL + nsec;
-		ptp_clock_event(adapter->ptp_clock, &event);
-		ack |= TSINTR_AUTT0;
-	}
-
-	if (tsicr & TSINTR_AUTT1) {
-		nsec = rd32(E1000_AUXSTMPL1);
-		sec  = rd32(E1000_AUXSTMPH1);
-		event.type = PTP_CLOCK_EXTTS;
-		event.index = 1;
-		event.timestamp = sec * 1000000000ULL + nsec;
-		ptp_clock_event(adapter->ptp_clock, &event);
-		ack |= TSINTR_AUTT1;
-	}
+	if (tsicr & TSINTR_TT0)
+		igb_perout(adapter, 0);
 
-	/* acknowledge the interrupts */
-	wr32(E1000_TSICR, ack);
+	if (tsicr & TSINTR_TT1)
+		igb_perout(adapter, 1);
+
+	if (tsicr & TSINTR_AUTT0)
+		igb_extts(adapter, 0);
+
+	if (tsicr & TSINTR_AUTT1)
+		igb_extts(adapter, 1);
 }
 
 static irqreturn_t igb_msix_other(int irq, void *data)
@@ -7105,7 +7151,7 @@
 {
 	struct e1000_hw *hw = &adapter->hw;
 	unsigned char *vf_mac = adapter->vf_data[vf].vf_mac_addresses;
-	u32 reg, msgbuf[3];
+	u32 reg, msgbuf[3] = {};
 	u8 *addr = (u8 *)(&msgbuf[1]);
 
 	/* process all the same items cleared in a function level reset */
@@ -7354,6 +7400,20 @@
 	struct vf_mac_filter *entry = NULL;
 	int ret = 0;
 
+	if ((vf_data->flags & IGB_VF_FLAG_PF_SET_MAC) &&
+	    !vf_data->trusted) {
+		dev_warn(&pdev->dev,
+			 "VF %d requested MAC filter but is administratively denied\n",
+			  vf);
+		return -EINVAL;
+	}
+	if (!is_valid_ether_addr(addr)) {
+		dev_warn(&pdev->dev,
+			 "VF %d attempted to set invalid MAC filter\n",
+			  vf);
+		return -EINVAL;
+	}
+
 	switch (info) {
 	case E1000_VF_MAC_FILTER_CLR:
 		/* remove all unicast MAC filters related to the current VF */
@@ -7367,20 +7427,6 @@
 		}
 		break;
 	case E1000_VF_MAC_FILTER_ADD:
-		if ((vf_data->flags & IGB_VF_FLAG_PF_SET_MAC) &&
-		    !vf_data->trusted) {
-			dev_warn(&pdev->dev,
-				 "VF %d requested MAC filter but is administratively denied\n",
-				 vf);
-			return -EINVAL;
-		}
-		if (!is_valid_ether_addr(addr)) {
-			dev_warn(&pdev->dev,
-				 "VF %d attempted to set invalid MAC filter\n",
-				 vf);
-			return -EINVAL;
-		}
-
 		/* try to find empty slot in the list */
 		list_for_each(pos, &adapter->vf_macs.l) {
 			entry = list_entry(pos, struct vf_mac_filter, l);
@@ -7548,8 +7594,10 @@
 static void igb_msg_task(struct igb_adapter *adapter)
 {
 	struct e1000_hw *hw = &adapter->hw;
+	unsigned long flags;
 	u32 vf;
 
+	spin_lock_irqsave(&adapter->vfs_lock, flags);
 	for (vf = 0; vf < adapter->vfs_allocated_count; vf++) {
 		/* process any reset requests */
 		if (!igb_check_for_rst(hw, vf))
@@ -7563,6 +7611,7 @@
 		if (!igb_check_for_ack(hw, vf))
 			igb_rcv_ack_from_vf(adapter, vf);
 	}
+	spin_unlock_irqrestore(&adapter->vfs_lock, flags);
 }
 
 /**
@@ -7732,7 +7781,7 @@
 	if (likely(napi_complete_done(napi, work_done)))
 		igb_ring_irq_enable(q_vector);
 
-	return min(work_done, budget - 1);
+	return work_done;
 }
 
 /**
@@ -8247,7 +8296,7 @@
 
 		if (igb_test_staterr(rx_desc, E1000_RXDEXT_STATERR_LB) &&
 		    test_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &rx_ring->flags))
-			vid = be16_to_cpu(rx_desc->wb.upper.vlan);
+			vid = be16_to_cpu((__force __be16)rx_desc->wb.upper.vlan);
 		else
 			vid = le16_to_cpu(rx_desc->wb.upper.vlan);
 
@@ -8995,6 +9044,11 @@
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct igb_adapter *adapter = netdev_priv(netdev);
 
+	if (state == pci_channel_io_normal) {
+		dev_warn(&pdev->dev, "Non-correctable non-fatal error reported.\n");
+		return PCI_ERS_RESULT_CAN_RECOVER;
+	}
+
 	netif_device_detach(netdev);
 
 	if (state == pci_channel_io_perm_failure)
@@ -9061,6 +9115,10 @@
 	struct igb_adapter *adapter = netdev_priv(netdev);
 
 	if (netif_running(netdev)) {
+		if (!test_bit(__IGB_DOWN, &adapter->state)) {
+			dev_dbg(&pdev->dev, "Resuming from non-fatal error, do nothing.\n");
+			return;
+		}
 		if (igb_up(adapter)) {
 			dev_err(&pdev->dev, "igb_up failed after reset\n");
 			return;
@@ -9383,11 +9441,10 @@
 	struct e1000_hw *hw = &adapter->hw;
 	u32 dmac_thr;
 	u16 hwm;
+	u32 reg;
 
 	if (hw->mac.type > e1000_82580) {
 		if (adapter->flags & IGB_FLAG_DMAC) {
-			u32 reg;
-
 			/* force threshold to 0. */
 			wr32(E1000_DMCTXTH, 0);
 
@@ -9420,7 +9477,6 @@
 			/* Disable BMC-to-OS Watchdog Enable */
 			if (hw->mac.type != e1000_i354)
 				reg &= ~E1000_DMACR_DC_BMC2OSW_EN;
-
 			wr32(E1000_DMACR, reg);
 
 			/* no lower threshold to disable
@@ -9437,12 +9493,12 @@
 			 */
 			wr32(E1000_DMCTXTH, (IGB_MIN_TXPBSIZE -
 			     (IGB_TX_BUF_4096 + adapter->max_frame_size)) >> 6);
+		}
 
-			/* make low power state decision controlled
-			 * by DMA coal
-			 */
+		if (hw->mac.type >= e1000_i210 ||
+		    (adapter->flags & IGB_FLAG_DMAC)) {
 			reg = rd32(E1000_PCIEMISC);
-			reg &= ~E1000_PCIEMISC_LX_DECISION;
+			reg |= E1000_PCIEMISC_LX_DECISION;
 			wr32(E1000_PCIEMISC, reg);
 		} /* endif adapter->dmac is not disabled */
 	} else if (hw->mac.type == e1000_82580) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/igb/igb_ptp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/igb/igb_ptp.c
@@ -1245,18 +1245,6 @@
 		return;
 	}
 
-	spin_lock_init(&adapter->tmreg_lock);
-	INIT_WORK(&adapter->ptp_tx_work, igb_ptp_tx_work);
-
-	if (adapter->ptp_flags & IGB_PTP_OVERFLOW_CHECK)
-		INIT_DELAYED_WORK(&adapter->ptp_overflow_work,
-				  igb_ptp_overflow_check);
-
-	adapter->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
-	adapter->tstamp_config.tx_type = HWTSTAMP_TX_OFF;
-
-	igb_ptp_reset(adapter);
-
 	adapter->ptp_clock = ptp_clock_register(&adapter->ptp_caps,
 						&adapter->pdev->dev);
 	if (IS_ERR(adapter->ptp_clock)) {
@@ -1266,6 +1254,18 @@
 		dev_info(&adapter->pdev->dev, "added PHC on %s\n",
 			 adapter->netdev->name);
 		adapter->ptp_flags |= IGB_PTP_ENABLED;
+
+		spin_lock_init(&adapter->tmreg_lock);
+		INIT_WORK(&adapter->ptp_tx_work, igb_ptp_tx_work);
+
+		if (adapter->ptp_flags & IGB_PTP_OVERFLOW_CHECK)
+			INIT_DELAYED_WORK(&adapter->ptp_overflow_work,
+					  igb_ptp_overflow_check);
+
+		adapter->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
+		adapter->tstamp_config.tx_type = HWTSTAMP_TX_OFF;
+
+		igb_ptp_reset(adapter);
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/igbvf/igbvf.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/igbvf/igbvf.h
@@ -39,11 +39,11 @@
 /* Tx/Rx descriptor defines */
 #define IGBVF_DEFAULT_TXD	256
 #define IGBVF_MAX_TXD		4096
-#define IGBVF_MIN_TXD		80
+#define IGBVF_MIN_TXD		64
 
 #define IGBVF_DEFAULT_RXD	256
 #define IGBVF_MAX_RXD		4096
-#define IGBVF_MIN_RXD		80
+#define IGBVF_MIN_RXD		64
 
 #define IGBVF_MIN_ITR_USECS	10 /* 100000 irq/sec */
 #define IGBVF_MAX_ITR_USECS	10000 /* 100    irq/sec */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/igbvf/netdev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -83,14 +83,14 @@
 static void igbvf_receive_skb(struct igbvf_adapter *adapter,
 			      struct net_device *netdev,
 			      struct sk_buff *skb,
-			      u32 status, u16 vlan)
+			      u32 status, __le16 vlan)
 {
 	u16 vid;
 
 	if (status & E1000_RXD_STAT_VP) {
 		if ((adapter->flags & IGBVF_FLAG_RX_LB_VLAN_BSWAP) &&
 		    (status & E1000_RXDEXT_STATERR_LB))
-			vid = be16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK;
+			vid = be16_to_cpu((__force __be16)vlan) & E1000_RXD_SPC_VLAN_MASK;
 		else
 			vid = le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK;
 		if (test_bit(vid, adapter->active_vlans))
@@ -1070,7 +1070,7 @@
 			  igbvf_intr_msix_rx, 0, adapter->rx_ring->name,
 			  netdev);
 	if (err)
-		goto out;
+		goto free_irq_tx;
 
 	adapter->rx_ring->itr_register = E1000_EITR(vector);
 	adapter->rx_ring->itr_val = adapter->current_itr;
@@ -1079,10 +1079,14 @@
 	err = request_irq(adapter->msix_entries[vector].vector,
 			  igbvf_msix_other, 0, netdev->name, netdev);
 	if (err)
-		goto out;
+		goto free_irq_rx;
 
 	igbvf_configure_msix(adapter);
 	return 0;
+free_irq_rx:
+	free_irq(adapter->msix_entries[--vector].vector, netdev);
+free_irq_tx:
+	free_irq(adapter->msix_entries[--vector].vector, netdev);
 out:
 	return err;
 }
@@ -2887,6 +2891,7 @@
 	return 0;
 
 err_hw_init:
+	netif_napi_del(&adapter->rx_ring->napi);
 	kfree(adapter->tx_ring);
 	kfree(adapter->rx_ring);
 err_sw_init:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/igbvf/vf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/igbvf/vf.c
@@ -1,6 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0
 /* Copyright(c) 2009 - 2018 Intel Corporation. */
 
+#include <linux/etherdevice.h>
+
 #include "vf.h"
 
 static s32 e1000_check_for_link_vf(struct e1000_hw *hw);
@@ -131,11 +133,16 @@
 		/* set our "perm_addr" based on info provided by PF */
 		ret_val = mbx->ops.read_posted(hw, msgbuf, 3);
 		if (!ret_val) {
-			if (msgbuf[0] == (E1000_VF_RESET |
-					  E1000_VT_MSGTYPE_ACK))
+			switch (msgbuf[0]) {
+			case E1000_VF_RESET | E1000_VT_MSGTYPE_ACK:
 				memcpy(hw->mac.perm_addr, addr, ETH_ALEN);
-			else
+				break;
+			case E1000_VF_RESET | E1000_VT_MSGTYPE_NACK:
+				eth_zero_addr(hw->mac.perm_addr);
+				break;
+			default:
 				ret_val = -E1000_ERR_MAC_INIT;
+			}
 		}
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/igc/igc.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/igc/igc.h
@@ -78,11 +78,11 @@
 /* TX/RX descriptor defines */
 #define IGC_DEFAULT_TXD		256
 #define IGC_DEFAULT_TX_WORK	128
-#define IGC_MIN_TXD		80
+#define IGC_MIN_TXD		64
 #define IGC_MAX_TXD		4096
 
 #define IGC_DEFAULT_RXD		256
-#define IGC_MIN_RXD		80
+#define IGC_MIN_RXD		64
 #define IGC_MAX_RXD		4096
 
 /* Transmit and receive queues */
@@ -504,7 +504,7 @@
 	if (hw->phy.ops.read_reg)
 		return hw->phy.ops.read_reg(hw, offset, data);
 
-	return 0;
+	return -EOPNOTSUPP;
 }
 
 /* forward declaration */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/igc/igc_base.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/igc/igc_base.c
@@ -187,15 +187,7 @@
 
 	igc_check_for_copper_link(hw);
 
-	/* Verify phy id and set remaining function pointers */
-	switch (phy->id) {
-	case I225_I_PHY_ID:
-		phy->type	= igc_phy_i225;
-		break;
-	default:
-		ret_val = -IGC_ERR_PHY;
-		goto out;
-	}
+	phy->type = igc_phy_i225;
 
 out:
 	return ret_val;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/igc/igc_defines.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/igc/igc_defines.h
@@ -360,6 +360,7 @@
 /* PHY Status Register */
 #define MII_SR_LINK_STATUS	0x0004 /* Link Status 1 = link */
 #define MII_SR_AUTONEG_COMPLETE	0x0020 /* Auto Neg Complete */
+#define IGC_PHY_RST_COMP	0x0100 /* Internal PHY reset completion */
 
 /* PHY 1000 MII Register/Bit Definitions */
 /* PHY Registers defined by IEEE */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/igc/igc_ethtool.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/igc/igc_ethtool.c
@@ -1668,14 +1668,22 @@
 	/* twisted pair */
 	cmd->base.port = PORT_TP;
 	cmd->base.phy_address = hw->phy.addr;
+	ethtool_link_ksettings_add_link_mode(cmd, supported, TP);
+	ethtool_link_ksettings_add_link_mode(cmd, advertising, TP);
 
 	/* advertising link modes */
-	ethtool_link_ksettings_add_link_mode(cmd, advertising, 10baseT_Half);
-	ethtool_link_ksettings_add_link_mode(cmd, advertising, 10baseT_Full);
-	ethtool_link_ksettings_add_link_mode(cmd, advertising, 100baseT_Half);
-	ethtool_link_ksettings_add_link_mode(cmd, advertising, 100baseT_Full);
-	ethtool_link_ksettings_add_link_mode(cmd, advertising, 1000baseT_Full);
-	ethtool_link_ksettings_add_link_mode(cmd, advertising, 2500baseT_Full);
+	if (hw->phy.autoneg_advertised & ADVERTISE_10_HALF)
+		ethtool_link_ksettings_add_link_mode(cmd, advertising, 10baseT_Half);
+	if (hw->phy.autoneg_advertised & ADVERTISE_10_FULL)
+		ethtool_link_ksettings_add_link_mode(cmd, advertising, 10baseT_Full);
+	if (hw->phy.autoneg_advertised & ADVERTISE_100_HALF)
+		ethtool_link_ksettings_add_link_mode(cmd, advertising, 100baseT_Half);
+	if (hw->phy.autoneg_advertised & ADVERTISE_100_FULL)
+		ethtool_link_ksettings_add_link_mode(cmd, advertising, 100baseT_Full);
+	if (hw->phy.autoneg_advertised & ADVERTISE_1000_FULL)
+		ethtool_link_ksettings_add_link_mode(cmd, advertising, 1000baseT_Full);
+	if (hw->phy.autoneg_advertised & ADVERTISE_2500_FULL)
+		ethtool_link_ksettings_add_link_mode(cmd, advertising, 2500baseT_Full);
 
 	/* set autoneg settings */
 	if (hw->mac.autoneg == 1) {
@@ -1684,6 +1692,9 @@
 						     Autoneg);
 	}
 
+	/* Set pause flow control settings */
+	ethtool_link_ksettings_add_link_mode(cmd, supported, Pause);
+
 	switch (hw->fc.requested_mode) {
 	case igc_fc_full:
 		ethtool_link_ksettings_add_link_mode(cmd, advertising, Pause);
@@ -1698,12 +1709,11 @@
 						     Asym_Pause);
 		break;
 	default:
-		ethtool_link_ksettings_add_link_mode(cmd, advertising, Pause);
-		ethtool_link_ksettings_add_link_mode(cmd, advertising,
-						     Asym_Pause);
+		break;
 	}
 
-	status = rd32(IGC_STATUS);
+	status = pm_runtime_suspended(&adapter->pdev->dev) ?
+		 0 : rd32(IGC_STATUS);
 
 	if (status & IGC_STATUS_LU) {
 		if (status & IGC_STATUS_SPEED_1000) {
@@ -1758,7 +1768,7 @@
 {
 	struct igc_adapter *adapter = netdev_priv(netdev);
 	struct igc_hw *hw = &adapter->hw;
-	u32 advertising;
+	u16 advertised = 0;
 
 	/* When adapter in resetting mode, autoneg/speed/duplex
 	 * cannot be changed
@@ -1784,12 +1794,33 @@
 	while (test_and_set_bit(__IGC_RESETTING, &adapter->state))
 		usleep_range(1000, 2000);
 
-	ethtool_convert_link_mode_to_legacy_u32(&advertising,
-						cmd->link_modes.advertising);
+	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
+						  2500baseT_Full))
+		advertised |= ADVERTISE_2500_FULL;
+
+	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
+						  1000baseT_Full))
+		advertised |= ADVERTISE_1000_FULL;
+
+	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
+						  100baseT_Full))
+		advertised |= ADVERTISE_100_FULL;
+
+	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
+						  100baseT_Half))
+		advertised |= ADVERTISE_100_HALF;
+
+	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
+						  10baseT_Full))
+		advertised |= ADVERTISE_10_FULL;
+
+	if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
+						  10baseT_Half))
+		advertised |= ADVERTISE_10_HALF;
 
 	if (cmd->base.autoneg == AUTONEG_ENABLE) {
 		hw->mac.autoneg = 1;
-		hw->phy.autoneg_advertised = advertising;
+		hw->phy.autoneg_advertised = advertised;
 		if (adapter->fc_autoneg)
 			hw->fc.requested_mode = igc_fc_default;
 	} else {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/igc/igc_i225.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/igc/igc_i225.c
@@ -156,8 +156,15 @@
 {
 	u32 swfw_sync;
 
-	while (igc_get_hw_semaphore_i225(hw))
-		; /* Empty */
+	/* Releasing the resource requires first getting the HW semaphore.
+	 * If we fail to get the semaphore, there is nothing we can do,
+	 * except log an error and quit. We are not allowed to hang here
+	 * indefinitely, as it may cause denial of service or system crash.
+	 */
+	if (igc_get_hw_semaphore_i225(hw)) {
+		hw_dbg("Failed to release SW_FW_SYNC.\n");
+		return;
+	}
 
 	swfw_sync = rd32(IGC_SW_FW_SYNC);
 	swfw_sync &= ~mask;
@@ -219,9 +226,9 @@
 			      u16 *data)
 {
 	struct igc_nvm_info *nvm = &hw->nvm;
+	s32 ret_val = -IGC_ERR_NVM;
 	u32 attempts = 100000;
 	u32 i, k, eewr = 0;
-	s32 ret_val = 0;
 
 	/* A check for invalid values:  offset too large, too many words,
 	 * too many words for the offset, and not enough words.
@@ -229,7 +236,6 @@
 	if (offset >= nvm->word_size || (words > (nvm->word_size - offset)) ||
 	    words == 0) {
 		hw_dbg("nvm parameter(s) out of bounds\n");
-		ret_val = -IGC_ERR_NVM;
 		goto out;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/igc/igc_mac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/igc/igc_mac.c
@@ -647,7 +647,7 @@
 	}
 
 out:
-	return 0;
+	return ret_val;
 }
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/igc/igc_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/igc/igc_main.c
@@ -256,6 +256,8 @@
 					       DMA_TO_DEVICE);
 		}
 
+		tx_buffer->next_to_watch = NULL;
+
 		/* move us one more past the eop_desc for start of next pkt */
 		tx_buffer++;
 		i++;
@@ -608,7 +610,6 @@
 	/* disable the queue */
 	wr32(IGC_TXDCTL(reg_idx), 0);
 	wrfl();
-	mdelay(10);
 
 	wr32(IGC_TDLEN(reg_idx),
 	     ring->count * sizeof(union igc_adv_tx_desc));
@@ -2222,21 +2223,23 @@
 }
 
 /**
- * igc_get_stats - Get System Network Statistics
+ * igc_get_stats64 - Get System Network Statistics
  * @netdev: network interface device structure
+ * @stats: rtnl_link_stats64 pointer
  *
  * Returns the address of the device statistics structure.
  * The statistics are updated here and also from the timer callback.
  */
-static struct net_device_stats *igc_get_stats(struct net_device *netdev)
+static void igc_get_stats64(struct net_device *netdev,
+			    struct rtnl_link_stats64 *stats)
 {
 	struct igc_adapter *adapter = netdev_priv(netdev);
 
+	spin_lock(&adapter->stats64_lock);
 	if (!test_bit(__IGC_RESETTING, &adapter->state))
 		igc_update_stats(adapter);
-
-	/* only return the current stats */
-	return &netdev->stats;
+	memcpy(stats, &adapter->stats64, sizeof(*stats));
+	spin_unlock(&adapter->stats64_lock);
 }
 
 static netdev_features_t igc_fix_features(struct net_device *netdev,
@@ -2689,6 +2692,7 @@
  */
 static int igc_request_msix(struct igc_adapter *adapter)
 {
+	unsigned int num_q_vectors = adapter->num_q_vectors;
 	int i = 0, err = 0, vector = 0, free_vector = 0;
 	struct net_device *netdev = adapter->netdev;
 
@@ -2697,7 +2701,13 @@
 	if (err)
 		goto err_out;
 
-	for (i = 0; i < adapter->num_q_vectors; i++) {
+	if (num_q_vectors > MAX_Q_VECTORS) {
+		num_q_vectors = MAX_Q_VECTORS;
+		dev_warn(&adapter->pdev->dev,
+			 "The number of queue vectors (%d) is higher than max allowed (%d)\n",
+			 adapter->num_q_vectors, MAX_Q_VECTORS);
+	}
+	for (i = 0; i < num_q_vectors; i++) {
 		struct igc_q_vector *q_vector = adapter->q_vector[i];
 
 		vector++;
@@ -2873,8 +2883,7 @@
 		break;
 	}
 
-	if (hw->mac.type == igc_i225 &&
-	    hw->phy.id == I225_I_PHY_ID) {
+	if (hw->mac.type == igc_i225) {
 		if (!netif_carrier_ok(adapter->netdev)) {
 			adapter->flags &= ~IGC_FLAG_NEED_LINK_UPDATE;
 		} else if (!(adapter->flags & IGC_FLAG_NEED_LINK_UPDATE)) {
@@ -3984,7 +3993,7 @@
 	.ndo_start_xmit		= igc_xmit_frame,
 	.ndo_set_mac_address	= igc_set_mac,
 	.ndo_change_mtu		= igc_change_mtu,
-	.ndo_get_stats		= igc_get_stats,
+	.ndo_get_stats64	= igc_get_stats64,
 	.ndo_fix_features	= igc_fix_features,
 	.ndo_set_features	= igc_set_features,
 	.ndo_features_check	= igc_features_check,
@@ -4308,8 +4317,8 @@
 err_ioremap:
 	free_netdev(netdev);
 err_alloc_etherdev:
-	pci_release_selected_regions(pdev,
-				     pci_select_bars(pdev, IORESOURCE_MEM));
+	pci_disable_pcie_error_reporting(pdev);
+	pci_release_mem_regions(pdev);
 err_pci_reg:
 err_dma:
 	pci_disable_device(pdev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/igc/igc_phy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/igc/igc_phy.c
@@ -173,6 +173,7 @@
 s32 igc_phy_hw_reset(struct igc_hw *hw)
 {
 	struct igc_phy_info *phy = &hw->phy;
+	u32 phpm = 0, timeout = 10000;
 	s32  ret_val;
 	u32 ctrl;
 
@@ -186,6 +187,8 @@
 	if (ret_val)
 		goto out;
 
+	phpm = rd32(IGC_I225_PHPM);
+
 	ctrl = rd32(IGC_CTRL);
 	wr32(IGC_CTRL, ctrl | IGC_CTRL_PHY_RST);
 	wrfl();
@@ -195,7 +198,18 @@
 	wr32(IGC_CTRL, ctrl);
 	wrfl();
 
-	usleep_range(1500, 2000);
+	/* SW should guarantee 100us for the completion of the PHY reset */
+	usleep_range(100, 150);
+	do {
+		phpm = rd32(IGC_I225_PHPM);
+		timeout--;
+		udelay(1);
+	} while (!(phpm & IGC_PHY_RST_COMP) && timeout);
+
+	if (!timeout)
+		hw_dbg("Timeout is expired after a phy reset\n");
+
+	usleep_range(100, 150);
 
 	phy->ops.release(hw);
 
@@ -235,8 +249,7 @@
 			return ret_val;
 	}
 
-	if ((phy->autoneg_mask & ADVERTISE_2500_FULL) &&
-	    hw->phy.id == I225_I_PHY_ID) {
+	if (phy->autoneg_mask & ADVERTISE_2500_FULL) {
 		/* Read the MULTI GBT AN Control Register - reg 7.32 */
 		ret_val = phy->ops.read_reg(hw, (STANDARD_AN_REG_MASK <<
 					    MMD_DEVADDR_SHIFT) |
@@ -376,8 +389,7 @@
 		ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL,
 					     mii_1000t_ctrl_reg);
 
-	if ((phy->autoneg_mask & ADVERTISE_2500_FULL) &&
-	    hw->phy.id == I225_I_PHY_ID)
+	if (phy->autoneg_mask & ADVERTISE_2500_FULL)
 		ret_val = phy->ops.write_reg(hw,
 					     (STANDARD_AN_REG_MASK <<
 					     MMD_DEVADDR_SHIFT) |
@@ -569,7 +581,7 @@
 	 * the lower time out
 	 */
 	for (i = 0; i < IGC_GEN_POLL_TIMEOUT; i++) {
-		usleep_range(500, 1000);
+		udelay(50);
 		mdic = rd32(IGC_MDIC);
 		if (mdic & IGC_MDIC_READY)
 			break;
@@ -626,7 +638,7 @@
 	 * the lower time out
 	 */
 	for (i = 0; i < IGC_GEN_POLL_TIMEOUT; i++) {
-		usleep_range(500, 1000);
+		udelay(50);
 		mdic = rd32(IGC_MDIC);
 		if (mdic & IGC_MDIC_READY)
 			break;
@@ -734,8 +746,6 @@
 		if (ret_val)
 			return ret_val;
 		ret_val = igc_write_phy_reg_mdic(hw, offset, data);
-		if (ret_val)
-			return ret_val;
 		hw->phy.ops.release(hw);
 	} else {
 		ret_val = igc_write_xmdio_reg(hw, (u16)offset, dev_addr,
@@ -767,8 +777,6 @@
 		if (ret_val)
 			return ret_val;
 		ret_val = igc_read_phy_reg_mdic(hw, offset, data);
-		if (ret_val)
-			return ret_val;
 		hw->phy.ops.release(hw);
 	} else {
 		ret_val = igc_read_xmdio_reg(hw, (u16)offset, dev_addr,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/igc/igc_regs.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/igc/igc_regs.h
@@ -12,6 +12,7 @@
 #define IGC_MDIC		0x00020  /* MDI Control - RW */
 #define IGC_MDICNFG		0x00E04  /* MDC/MDIO Configuration - RW */
 #define IGC_CONNSW		0x00034  /* Copper/Fiber switch control - RW */
+#define IGC_I225_PHPM		0x00E14  /* I225 PHY Power Management */
 
 /* Internal Packet Buffer Size Registers */
 #define IGC_RXPBS		0x02404  /* Rx Packet Buffer Size - RW */
@@ -236,4 +237,6 @@
 
 #define array_rd32(reg, offset) (igc_rd32(hw, (reg) + ((offset) << 2)))
 
+#define IGC_REMOVED(h) unlikely(!(h))
+
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -67,6 +67,8 @@
 #define IXGBE_RXBUFFER_4K    4096
 #define IXGBE_MAX_RXBUFFER  16384  /* largest size for a single descriptor */
 
+#define IXGBE_PKT_HDR_PAD   (ETH_HLEN + ETH_FCS_LEN + (VLAN_HLEN * 2))
+
 /* Attempt to maximize the headroom available for incoming frames.  We
  * use a 2K buffer for receives and need 1536/1534 to store the data for
  * the frame.  This leaves us with 512 bytes of room.  From that we need
@@ -177,11 +179,14 @@
 	u16 pf_vlan; /* When set, guest VLAN config not allowed. */
 	u16 pf_qos;
 	u16 tx_rate;
+	int link_enable;
+	int link_state;
 	u8 spoofchk_enabled;
 	bool rss_query_enabled;
 	u8 trusted;
 	int xcast_mode;
 	unsigned int vf_api;
+	u8 primary_abort_count;
 };
 
 enum ixgbevf_xcast_modes {
@@ -553,6 +558,8 @@
 #define IXGBE_TRY_LINK_TIMEOUT (4 * HZ)
 #define IXGBE_SFP_POLL_JIFFIES (2 * HZ)	/* SFP poll every 2 seconds */
 
+#define IXGBE_PRIMARY_ABORT_LIMIT	5
+
 /* board specific private data structure */
 struct ixgbe_adapter {
 	unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
@@ -614,6 +621,7 @@
 #define IXGBE_FLAG2_RX_LEGACY			BIT(16)
 #define IXGBE_FLAG2_IPSEC_ENABLED		BIT(17)
 #define IXGBE_FLAG2_VF_IPSEC_ENABLED		BIT(18)
+#define IXGBE_FLAG2_AUTO_DISABLE_VF		BIT(19)
 
 	/* Tx fast path data */
 	int num_tx_queues;
@@ -773,6 +781,7 @@
 #ifdef CONFIG_IXGBE_IPSEC
 	struct ixgbe_ipsec *ipsec;
 #endif /* CONFIG_IXGBE_IPSEC */
+	spinlock_t vfs_lock;
 };
 
 static inline u8 ixgbe_max_rss_indices(struct ixgbe_adapter *adapter)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
@@ -123,14 +123,14 @@
 		if (ret_val)
 			return ret_val;
 		if (hw->phy.sfp_type == ixgbe_sfp_type_unknown)
-			return IXGBE_ERR_SFP_NOT_SUPPORTED;
+			return -EOPNOTSUPP;
 
 		/* Check to see if SFP+ module is supported */
 		ret_val = ixgbe_get_sfp_init_sequence_offsets(hw,
 							    &list_offset,
 							    &data_offset);
 		if (ret_val)
-			return IXGBE_ERR_SFP_NOT_SUPPORTED;
+			return -EOPNOTSUPP;
 		break;
 	default:
 		break;
@@ -213,7 +213,7 @@
 		break;
 
 	default:
-		return IXGBE_ERR_LINK_SETUP;
+		return -EIO;
 	}
 
 	return 0;
@@ -283,7 +283,7 @@
 
 	/* Validate the water mark configuration */
 	if (!hw->fc.pause_time)
-		return IXGBE_ERR_INVALID_LINK_SETTINGS;
+		return -EINVAL;
 
 	/* Low water mark of zero causes XOFF floods */
 	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
@@ -292,7 +292,7 @@
 			if (!hw->fc.low_water[i] ||
 			    hw->fc.low_water[i] >= hw->fc.high_water[i]) {
 				hw_dbg(hw, "Invalid water mark configuration\n");
-				return IXGBE_ERR_INVALID_LINK_SETTINGS;
+				return -EINVAL;
 			}
 		}
 	}
@@ -369,7 +369,7 @@
 		break;
 	default:
 		hw_dbg(hw, "Flow control param set incorrectly\n");
-		return IXGBE_ERR_CONFIG;
+		return -EIO;
 	}
 
 	/* Set 802.3x based flow control settings. */
@@ -438,7 +438,7 @@
 				msleep(100);
 			}
 			if (!(links_reg & IXGBE_LINKS_KX_AN_COMP)) {
-				status = IXGBE_ERR_AUTONEG_NOT_COMPLETE;
+				status = -EIO;
 				hw_dbg(hw, "Autonegotiation did not complete.\n");
 			}
 		}
@@ -478,7 +478,7 @@
 
 	if (timeout == IXGBE_VALIDATE_LINK_READY_TIMEOUT) {
 		hw_dbg(hw, "Link was indicated but link is down\n");
-		return IXGBE_ERR_LINK_SETUP;
+		return -EIO;
 	}
 
 	return 0;
@@ -594,7 +594,7 @@
 	speed &= link_capabilities;
 
 	if (speed == IXGBE_LINK_SPEED_UNKNOWN)
-		return IXGBE_ERR_LINK_SETUP;
+		return -EINVAL;
 
 	/* Set KX4/KX support according to speed requested */
 	else if (link_mode == IXGBE_AUTOC_LMS_KX4_AN ||
@@ -701,9 +701,9 @@
 
 		/* Init PHY and function pointers, perform SFP setup */
 		phy_status = hw->phy.ops.init(hw);
-		if (phy_status == IXGBE_ERR_SFP_NOT_SUPPORTED)
+		if (phy_status == -EOPNOTSUPP)
 			return phy_status;
-		if (phy_status == IXGBE_ERR_SFP_NOT_PRESENT)
+		if (phy_status == -ENOENT)
 			goto mac_reset_top;
 
 		hw->phy.ops.reset(hw);
@@ -727,7 +727,7 @@
 		udelay(1);
 	}
 	if (ctrl & IXGBE_CTRL_RST) {
-		status = IXGBE_ERR_RESET_FAILED;
+		status = -EIO;
 		hw_dbg(hw, "Reset polling failed to complete.\n");
 	}
 
@@ -789,7 +789,7 @@
 	/* Make sure we are using a valid rar index range */
 	if (rar >= rar_entries) {
 		hw_dbg(hw, "RAR index %d is out of range.\n", rar);
-		return IXGBE_ERR_INVALID_ARGUMENT;
+		return -EINVAL;
 	}
 
 	rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar));
@@ -814,7 +814,7 @@
 	/* Make sure we are using a valid rar index range */
 	if (rar >= rar_entries) {
 		hw_dbg(hw, "RAR index %d is out of range.\n", rar);
-		return IXGBE_ERR_INVALID_ARGUMENT;
+		return -EINVAL;
 	}
 
 	rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar));
@@ -845,7 +845,7 @@
 	u32 vftabyte;
 
 	if (vlan > 4095)
-		return IXGBE_ERR_PARAM;
+		return -EINVAL;
 
 	/* Determine 32-bit word position in array */
 	regindex = (vlan >> 5) & 0x7F;   /* upper seven bits */
@@ -964,7 +964,7 @@
 		gssr = IXGBE_GSSR_PHY0_SM;
 
 	if (hw->mac.ops.acquire_swfw_sync(hw, gssr) != 0)
-		return IXGBE_ERR_SWFW_SYNC;
+		return -EBUSY;
 
 	if (hw->phy.type == ixgbe_phy_nl) {
 		/*
@@ -993,7 +993,7 @@
 
 		if (sfp_stat != IXGBE_I2C_EEPROM_STATUS_PASS) {
 			hw_dbg(hw, "EEPROM read did not pass.\n");
-			status = IXGBE_ERR_SFP_NOT_PRESENT;
+			status = -ENOENT;
 			goto out;
 		}
 
@@ -1003,7 +1003,7 @@
 
 		*eeprom_data = (u8)(sfp_data >> 8);
 	} else {
-		status = IXGBE_ERR_PHY;
+		status = -EIO;
 	}
 
 out:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
@@ -117,7 +117,7 @@
 		ret_val = hw->mac.ops.acquire_swfw_sync(hw,
 							IXGBE_GSSR_MAC_CSR_SM);
 		if (ret_val)
-			return IXGBE_ERR_SWFW_SYNC;
+			return -EBUSY;
 
 		if (hw->eeprom.ops.read(hw, ++data_offset, &data_value))
 			goto setup_sfp_err;
@@ -144,7 +144,7 @@
 
 		if (ret_val) {
 			hw_dbg(hw, " sfp module setup not complete\n");
-			return IXGBE_ERR_SFP_SETUP_NOT_COMPLETE;
+			return -EIO;
 		}
 	}
 
@@ -159,7 +159,7 @@
 	usleep_range(hw->eeprom.semaphore_delay * 1000,
 		     hw->eeprom.semaphore_delay * 2000);
 	hw_err(hw, "eeprom read at offset %d failed\n", data_offset);
-	return IXGBE_ERR_SFP_SETUP_NOT_COMPLETE;
+	return -EIO;
 }
 
 /**
@@ -184,7 +184,7 @@
 		ret_val = hw->mac.ops.acquire_swfw_sync(hw,
 					IXGBE_GSSR_MAC_CSR_SM);
 		if (ret_val)
-			return IXGBE_ERR_SWFW_SYNC;
+			return -EBUSY;
 
 		*locked = true;
 	}
@@ -219,7 +219,7 @@
 		ret_val = hw->mac.ops.acquire_swfw_sync(hw,
 					IXGBE_GSSR_MAC_CSR_SM);
 		if (ret_val)
-			return IXGBE_ERR_SWFW_SYNC;
+			return -EBUSY;
 
 		locked = true;
 	}
@@ -400,7 +400,7 @@
 		break;
 
 	default:
-		return IXGBE_ERR_LINK_SETUP;
+		return -EIO;
 	}
 
 	if (hw->phy.multispeed_fiber) {
@@ -541,7 +541,7 @@
 				msleep(100);
 			}
 			if (!(links_reg & IXGBE_LINKS_KX_AN_COMP)) {
-				status = IXGBE_ERR_AUTONEG_NOT_COMPLETE;
+				status = -EIO;
 				hw_dbg(hw, "Autoneg did not complete.\n");
 			}
 		}
@@ -794,7 +794,7 @@
 	speed &= link_capabilities;
 
 	if (speed == IXGBE_LINK_SPEED_UNKNOWN)
-		return IXGBE_ERR_LINK_SETUP;
+		return -EINVAL;
 
 	/* Use stored value (EEPROM defaults) of AUTOC to find KR/KX4 support*/
 	if (hw->mac.orig_link_settings_stored)
@@ -861,8 +861,7 @@
 					msleep(100);
 				}
 				if (!(links_reg & IXGBE_LINKS_KX_AN_COMP)) {
-					status =
-						IXGBE_ERR_AUTONEG_NOT_COMPLETE;
+					status = -EIO;
 					hw_dbg(hw, "Autoneg did not complete.\n");
 				}
 			}
@@ -927,7 +926,7 @@
 	/* Identify PHY and related function pointers */
 	status = hw->phy.ops.init(hw);
 
-	if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
+	if (status == -EOPNOTSUPP)
 		return status;
 
 	/* Setup SFP module if there is one present. */
@@ -936,7 +935,7 @@
 		hw->phy.sfp_setup_needed = false;
 	}
 
-	if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
+	if (status == -EOPNOTSUPP)
 		return status;
 
 	/* Reset PHY */
@@ -974,7 +973,7 @@
 	}
 
 	if (ctrl & IXGBE_CTRL_RST_MASK) {
-		status = IXGBE_ERR_RESET_FAILED;
+		status = -EIO;
 		hw_dbg(hw, "Reset polling failed to complete.\n");
 	}
 
@@ -1093,7 +1092,7 @@
 		udelay(10);
 	}
 
-	return IXGBE_ERR_FDIR_CMD_INCOMPLETE;
+	return -EIO;
 }
 
 /**
@@ -1155,7 +1154,7 @@
 	}
 	if (i >= IXGBE_FDIR_INIT_DONE_POLL) {
 		hw_dbg(hw, "Flow Director Signature poll time exceeded!\n");
-		return IXGBE_ERR_FDIR_REINIT_FAILED;
+		return -EIO;
 	}
 
 	/* Clear FDIR statistics registers (read to clear) */
@@ -1387,7 +1386,7 @@
 		break;
 	default:
 		hw_dbg(hw, " Error on flow type input\n");
-		return IXGBE_ERR_CONFIG;
+		return -EIO;
 	}
 
 	/* configure FDIRCMD register */
@@ -1546,7 +1545,7 @@
 		break;
 	default:
 		hw_dbg(hw, " Error on vm pool mask\n");
-		return IXGBE_ERR_CONFIG;
+		return -EIO;
 	}
 
 	switch (input_mask->formatted.flow_type & IXGBE_ATR_L4TYPE_MASK) {
@@ -1555,13 +1554,13 @@
 		if (input_mask->formatted.dst_port ||
 		    input_mask->formatted.src_port) {
 			hw_dbg(hw, " Error on src/dst port mask\n");
-			return IXGBE_ERR_CONFIG;
+			return -EIO;
 		}
 	case IXGBE_ATR_L4TYPE_MASK:
 		break;
 	default:
 		hw_dbg(hw, " Error on flow type mask\n");
-		return IXGBE_ERR_CONFIG;
+		return -EIO;
 	}
 
 	switch (ntohs(input_mask->formatted.vlan_id) & 0xEFFF) {
@@ -1582,7 +1581,7 @@
 		break;
 	default:
 		hw_dbg(hw, " Error on VLAN mask\n");
-		return IXGBE_ERR_CONFIG;
+		return -EIO;
 	}
 
 	switch ((__force u16)input_mask->formatted.flex_bytes & 0xFFFF) {
@@ -1594,7 +1593,7 @@
 		break;
 	default:
 		hw_dbg(hw, " Error on flexible byte mask\n");
-		return IXGBE_ERR_CONFIG;
+		return -EIO;
 	}
 
 	/* Now mask VM pool and destination IPv6 - bits 5 and 2 */
@@ -1823,7 +1822,7 @@
 
 	/* Return error if SFP module has been detected but is not supported */
 	if (hw->phy.type == ixgbe_phy_sfp_unsupported)
-		return IXGBE_ERR_SFP_NOT_SUPPORTED;
+		return -EOPNOTSUPP;
 
 	return status;
 }
@@ -1862,13 +1861,13 @@
  *  Verifies that installed the firmware version is 0.6 or higher
  *  for SFI devices. All 82599 SFI devices should have version 0.6 or higher.
  *
- *  Returns IXGBE_ERR_EEPROM_VERSION if the FW is not present or
- *  if the FW version is not supported.
+ *  Return: -EACCES if the FW is not present or if the FW version is
+ *  not supported.
  **/
 static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw)
 {
-	s32 status = IXGBE_ERR_EEPROM_VERSION;
 	u16 fw_offset, fw_ptp_cfg_offset;
+	s32 status = -EACCES;
 	u16 offset;
 	u16 fw_version = 0;
 
@@ -1882,7 +1881,7 @@
 		goto fw_version_err;
 
 	if (fw_offset == 0 || fw_offset == 0xFFFF)
-		return IXGBE_ERR_EEPROM_VERSION;
+		return -EACCES;
 
 	/* get the offset to the Pass Through Patch Configuration block */
 	offset = fw_offset + IXGBE_FW_PASSTHROUGH_PATCH_CONFIG_PTR;
@@ -1890,7 +1889,7 @@
 		goto fw_version_err;
 
 	if (fw_ptp_cfg_offset == 0 || fw_ptp_cfg_offset == 0xFFFF)
-		return IXGBE_ERR_EEPROM_VERSION;
+		return -EACCES;
 
 	/* get the firmware version */
 	offset = fw_ptp_cfg_offset + IXGBE_FW_PATCH_VERSION_4;
@@ -1904,7 +1903,7 @@
 
 fw_version_err:
 	hw_err(hw, "eeprom read at offset %d failed\n", offset);
-	return IXGBE_ERR_EEPROM_VERSION;
+	return -EACCES;
 }
 
 /**
@@ -2037,7 +2036,7 @@
 
 	if (!(anlp1_reg & IXGBE_ANLP1_AN_STATE_MASK)) {
 		hw_dbg(hw, "auto negotiation not completed\n");
-		ret_val = IXGBE_ERR_RESET_FAILED;
+		ret_val = -EIO;
 		goto reset_pipeline_out;
 	}
 
@@ -2086,7 +2085,7 @@
 
 		if (!timeout) {
 			hw_dbg(hw, "Driver can't access resource, acquiring I2C bus timeout.\n");
-			status = IXGBE_ERR_I2C;
+			status = -EIO;
 			goto release_i2c_access;
 		}
 	}
@@ -2140,7 +2139,7 @@
 
 		if (!timeout) {
 			hw_dbg(hw, "Driver can't access resource, acquiring I2C bus timeout.\n");
-			status = IXGBE_ERR_I2C;
+			status = -EIO;
 			goto release_i2c_access;
 		}
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
@@ -30,7 +30,7 @@
 					     u16 words, u16 *data);
 static s32 ixgbe_detect_eeprom_page_size_generic(struct ixgbe_hw *hw,
 						 u16 offset);
-static s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw);
+static s32 ixgbe_disable_pcie_primary(struct ixgbe_hw *hw);
 
 /* Base table for registers values that change by MAC */
 const u32 ixgbe_mvals_8259X[IXGBE_MVALS_IDX_LIMIT] = {
@@ -124,7 +124,7 @@
 	 */
 	if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
 		hw_dbg(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
-		return IXGBE_ERR_INVALID_LINK_SETTINGS;
+		return -EINVAL;
 	}
 
 	/*
@@ -215,7 +215,7 @@
 		break;
 	default:
 		hw_dbg(hw, "Flow control param set incorrectly\n");
-		return IXGBE_ERR_CONFIG;
+		return -EIO;
 	}
 
 	if (hw->mac.type != ixgbe_mac_X540) {
@@ -500,7 +500,7 @@
 
 	if (pba_num == NULL) {
 		hw_dbg(hw, "PBA string buffer was null\n");
-		return IXGBE_ERR_INVALID_ARGUMENT;
+		return -EINVAL;
 	}
 
 	ret_val = hw->eeprom.ops.read(hw, IXGBE_PBANUM0_PTR, &data);
@@ -526,7 +526,7 @@
 		/* we will need 11 characters to store the PBA */
 		if (pba_num_size < 11) {
 			hw_dbg(hw, "PBA string buffer too small\n");
-			return IXGBE_ERR_NO_SPACE;
+			return -ENOSPC;
 		}
 
 		/* extract hex string from data and pba_ptr */
@@ -563,13 +563,13 @@
 
 	if (length == 0xFFFF || length == 0) {
 		hw_dbg(hw, "NVM PBA number section invalid length\n");
-		return IXGBE_ERR_PBA_SECTION;
+		return -EIO;
 	}
 
 	/* check if pba_num buffer is big enough */
 	if (pba_num_size  < (((u32)length * 2) - 1)) {
 		hw_dbg(hw, "PBA string buffer too small\n");
-		return IXGBE_ERR_NO_SPACE;
+		return -ENOSPC;
 	}
 
 	/* trim pba length from start of string */
@@ -746,10 +746,10 @@
 	usleep_range(1000, 2000);
 
 	/*
-	 * Prevent the PCI-E bus from from hanging by disabling PCI-E master
+	 * Prevent the PCI-E bus from hanging by disabling PCI-E primary
 	 * access and verify no pending requests
 	 */
-	return ixgbe_disable_pcie_master(hw);
+	return ixgbe_disable_pcie_primary(hw);
 }
 
 /**
@@ -805,7 +805,7 @@
 	u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
 
 	if (index > 3)
-		return IXGBE_ERR_PARAM;
+		return -EINVAL;
 
 	/* To turn on the LED, set mode to ON. */
 	led_reg &= ~IXGBE_LED_MODE_MASK(index);
@@ -826,7 +826,7 @@
 	u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
 
 	if (index > 3)
-		return IXGBE_ERR_PARAM;
+		return -EINVAL;
 
 	/* To turn off the LED, set mode to OFF. */
 	led_reg &= ~IXGBE_LED_MODE_MASK(index);
@@ -904,11 +904,8 @@
 
 	hw->eeprom.ops.init_params(hw);
 
-	if (words == 0)
-		return IXGBE_ERR_INVALID_ARGUMENT;
-
-	if (offset + words > hw->eeprom.word_size)
-		return IXGBE_ERR_EEPROM;
+	if (words == 0 || (offset + words > hw->eeprom.word_size))
+		return -EINVAL;
 
 	/*
 	 * The EEPROM page size cannot be queried from the chip. We do lazy
@@ -962,7 +959,7 @@
 
 	if (ixgbe_ready_eeprom(hw) != 0) {
 		ixgbe_release_eeprom(hw);
-		return IXGBE_ERR_EEPROM;
+		return -EIO;
 	}
 
 	for (i = 0; i < words; i++) {
@@ -1028,7 +1025,7 @@
 	hw->eeprom.ops.init_params(hw);
 
 	if (offset >= hw->eeprom.word_size)
-		return IXGBE_ERR_EEPROM;
+		return -EINVAL;
 
 	return ixgbe_write_eeprom_buffer_bit_bang(hw, offset, 1, &data);
 }
@@ -1050,11 +1047,8 @@
 
 	hw->eeprom.ops.init_params(hw);
 
-	if (words == 0)
-		return IXGBE_ERR_INVALID_ARGUMENT;
-
-	if (offset + words > hw->eeprom.word_size)
-		return IXGBE_ERR_EEPROM;
+	if (words == 0 || (offset + words > hw->eeprom.word_size))
+		return -EINVAL;
 
 	/*
 	 * We cannot hold synchronization semaphores for too long
@@ -1099,7 +1093,7 @@
 
 	if (ixgbe_ready_eeprom(hw) != 0) {
 		ixgbe_release_eeprom(hw);
-		return IXGBE_ERR_EEPROM;
+		return -EIO;
 	}
 
 	for (i = 0; i < words; i++) {
@@ -1142,7 +1136,7 @@
 	hw->eeprom.ops.init_params(hw);
 
 	if (offset >= hw->eeprom.word_size)
-		return IXGBE_ERR_EEPROM;
+		return -EINVAL;
 
 	return ixgbe_read_eeprom_buffer_bit_bang(hw, offset, 1, data);
 }
@@ -1165,11 +1159,8 @@
 
 	hw->eeprom.ops.init_params(hw);
 
-	if (words == 0)
-		return IXGBE_ERR_INVALID_ARGUMENT;
-
-	if (offset >= hw->eeprom.word_size)
-		return IXGBE_ERR_EEPROM;
+	if (words == 0 || offset >= hw->eeprom.word_size)
+		return -EINVAL;
 
 	for (i = 0; i < words; i++) {
 		eerd = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) |
@@ -1262,11 +1253,8 @@
 
 	hw->eeprom.ops.init_params(hw);
 
-	if (words == 0)
-		return IXGBE_ERR_INVALID_ARGUMENT;
-
-	if (offset >= hw->eeprom.word_size)
-		return IXGBE_ERR_EEPROM;
+	if (words == 0 || offset >= hw->eeprom.word_size)
+		return -EINVAL;
 
 	for (i = 0; i < words; i++) {
 		eewr = ((offset + i) << IXGBE_EEPROM_RW_ADDR_SHIFT) |
@@ -1328,7 +1316,7 @@
 		}
 		udelay(5);
 	}
-	return IXGBE_ERR_EEPROM;
+	return -EIO;
 }
 
 /**
@@ -1344,7 +1332,7 @@
 	u32 i;
 
 	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) != 0)
-		return IXGBE_ERR_SWFW_SYNC;
+		return -EBUSY;
 
 	eec = IXGBE_READ_REG(hw, IXGBE_EEC(hw));
 
@@ -1366,7 +1354,7 @@
 		hw_dbg(hw, "Could not acquire EEPROM grant\n");
 
 		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
-		return IXGBE_ERR_EEPROM;
+		return -EIO;
 	}
 
 	/* Setup EEPROM for Read/Write */
@@ -1419,7 +1407,7 @@
 		swsm = IXGBE_READ_REG(hw, IXGBE_SWSM(hw));
 		if (swsm & IXGBE_SWSM_SMBI) {
 			hw_dbg(hw, "Software semaphore SMBI between device drivers not granted.\n");
-			return IXGBE_ERR_EEPROM;
+			return -EIO;
 		}
 	}
 
@@ -1447,7 +1435,7 @@
 	if (i >= timeout) {
 		hw_dbg(hw, "SWESMBI Software EEPROM semaphore not granted.\n");
 		ixgbe_release_eeprom_semaphore(hw);
-		return IXGBE_ERR_EEPROM;
+		return -EIO;
 	}
 
 	return 0;
@@ -1503,7 +1491,7 @@
 	 */
 	if (i >= IXGBE_EEPROM_MAX_RETRY_SPI) {
 		hw_dbg(hw, "SPI EEPROM Status error\n");
-		return IXGBE_ERR_EEPROM;
+		return -EIO;
 	}
 
 	return 0;
@@ -1715,7 +1703,7 @@
 	for (i = IXGBE_PCIE_ANALOG_PTR; i < IXGBE_FW_PTR; i++) {
 		if (hw->eeprom.ops.read(hw, i, &pointer)) {
 			hw_dbg(hw, "EEPROM read failed\n");
-			return IXGBE_ERR_EEPROM;
+			return -EIO;
 		}
 
 		/* If the pointer seems invalid */
@@ -1724,7 +1712,7 @@
 
 		if (hw->eeprom.ops.read(hw, pointer, &length)) {
 			hw_dbg(hw, "EEPROM read failed\n");
-			return IXGBE_ERR_EEPROM;
+			return -EIO;
 		}
 
 		if (length == 0xFFFF || length == 0)
@@ -1733,7 +1721,7 @@
 		for (j = pointer + 1; j <= pointer + length; j++) {
 			if (hw->eeprom.ops.read(hw, j, &word)) {
 				hw_dbg(hw, "EEPROM read failed\n");
-				return IXGBE_ERR_EEPROM;
+				return -EIO;
 			}
 			checksum += word;
 		}
@@ -1786,7 +1774,7 @@
 	 * calculated checksum
 	 */
 	if (read_checksum != checksum)
-		status = IXGBE_ERR_EEPROM_CHECKSUM;
+		status = -EIO;
 
 	/* If the user cares, return the calculated checksum */
 	if (checksum_val)
@@ -1845,7 +1833,7 @@
 	/* Make sure we are using a valid rar index range */
 	if (index >= rar_entries) {
 		hw_dbg(hw, "RAR index %d is out of range.\n", index);
-		return IXGBE_ERR_INVALID_ARGUMENT;
+		return -EINVAL;
 	}
 
 	/* setup VMDq pool selection before this RAR gets enabled */
@@ -1897,7 +1885,7 @@
 	/* Make sure we are using a valid rar index range */
 	if (index >= rar_entries) {
 		hw_dbg(hw, "RAR index %d is out of range.\n", index);
-		return IXGBE_ERR_INVALID_ARGUMENT;
+		return -EINVAL;
 	}
 
 	/*
@@ -2146,7 +2134,7 @@
 
 	/* Validate the water mark configuration. */
 	if (!hw->fc.pause_time)
-		return IXGBE_ERR_INVALID_LINK_SETTINGS;
+		return -EINVAL;
 
 	/* Low water mark of zero causes XOFF floods */
 	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
@@ -2155,7 +2143,7 @@
 			if (!hw->fc.low_water[i] ||
 			    hw->fc.low_water[i] >= hw->fc.high_water[i]) {
 				hw_dbg(hw, "Invalid water mark configuration\n");
-				return IXGBE_ERR_INVALID_LINK_SETTINGS;
+				return -EINVAL;
 			}
 		}
 	}
@@ -2212,7 +2200,7 @@
 		break;
 	default:
 		hw_dbg(hw, "Flow control param set incorrectly\n");
-		return IXGBE_ERR_CONFIG;
+		return -EIO;
 	}
 
 	/* Set 802.3x based flow control settings. */
@@ -2243,7 +2231,7 @@
 	}
 
 	/* Configure pause time (2 TCs per register) */
-	reg = hw->fc.pause_time * 0x00010001;
+	reg = hw->fc.pause_time * 0x00010001U;
 	for (i = 0; i < (MAX_TRAFFIC_CLASS / 2); i++)
 		IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg);
 
@@ -2269,7 +2257,7 @@
 		       u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm)
 {
 	if ((!(adv_reg)) ||  (!(lp_reg)))
-		return IXGBE_ERR_FC_NOT_NEGOTIATED;
+		return -EINVAL;
 
 	if ((adv_reg & adv_sym) && (lp_reg & lp_sym)) {
 		/*
@@ -2321,7 +2309,7 @@
 	linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA);
 	if ((!!(linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) ||
 	    (!!(linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1))
-		return IXGBE_ERR_FC_NOT_NEGOTIATED;
+		return -EIO;
 
 	pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
 	pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP);
@@ -2353,12 +2341,12 @@
 	 */
 	links = IXGBE_READ_REG(hw, IXGBE_LINKS);
 	if ((links & IXGBE_LINKS_KX_AN_COMP) == 0)
-		return IXGBE_ERR_FC_NOT_NEGOTIATED;
+		return -EIO;
 
 	if (hw->mac.type == ixgbe_mac_82599EB) {
 		links2 = IXGBE_READ_REG(hw, IXGBE_LINKS2);
 		if ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0)
-			return IXGBE_ERR_FC_NOT_NEGOTIATED;
+			return -EIO;
 	}
 	/*
 	 * Read the 10g AN autoc and LP ability registers and resolve
@@ -2407,8 +2395,8 @@
  **/
 void ixgbe_fc_autoneg(struct ixgbe_hw *hw)
 {
-	s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
 	ixgbe_link_speed speed;
+	s32 ret_val = -EIO;
 	bool link_up;
 
 	/*
@@ -2506,15 +2494,15 @@
 }
 
 /**
- *  ixgbe_disable_pcie_master - Disable PCI-express master access
+ *  ixgbe_disable_pcie_primary - Disable PCI-express primary access
  *  @hw: pointer to hardware structure
  *
- *  Disables PCI-Express master access and verifies there are no pending
- *  requests. IXGBE_ERR_MASTER_REQUESTS_PENDING is returned if master disable
- *  bit hasn't caused the master requests to be disabled, else 0
- *  is returned signifying master requests disabled.
+ *  Disables PCI-Express primary access and verifies there are no pending
+ *  requests. -EALREADY is returned if primary disable
+ *  bit hasn't caused the primary requests to be disabled, else 0
+ *  is returned signifying primary requests disabled.
  **/
-static s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
+static s32 ixgbe_disable_pcie_primary(struct ixgbe_hw *hw)
 {
 	u32 i, poll;
 	u16 value;
@@ -2523,23 +2511,23 @@
 	IXGBE_WRITE_REG(hw, IXGBE_CTRL, IXGBE_CTRL_GIO_DIS);
 
 	/* Poll for bit to read as set */
-	for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) {
+	for (i = 0; i < IXGBE_PCI_PRIMARY_DISABLE_TIMEOUT; i++) {
 		if (IXGBE_READ_REG(hw, IXGBE_CTRL) & IXGBE_CTRL_GIO_DIS)
 			break;
 		usleep_range(100, 120);
 	}
-	if (i >= IXGBE_PCI_MASTER_DISABLE_TIMEOUT) {
+	if (i >= IXGBE_PCI_PRIMARY_DISABLE_TIMEOUT) {
 		hw_dbg(hw, "GIO disable did not set - requesting resets\n");
 		goto gio_disable_fail;
 	}
 
-	/* Exit if master requests are blocked */
+	/* Exit if primary requests are blocked */
 	if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO) ||
 	    ixgbe_removed(hw->hw_addr))
 		return 0;
 
-	/* Poll for master request bit to clear */
-	for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) {
+	/* Poll for primary request bit to clear */
+	for (i = 0; i < IXGBE_PCI_PRIMARY_DISABLE_TIMEOUT; i++) {
 		udelay(100);
 		if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO))
 			return 0;
@@ -2547,13 +2535,13 @@
 
 	/*
 	 * Two consecutive resets are required via CTRL.RST per datasheet
-	 * 5.2.5.3.2 Master Disable.  We set a flag to inform the reset routine
-	 * of this need.  The first reset prevents new master requests from
+	 * 5.2.5.3.2 Primary Disable.  We set a flag to inform the reset routine
+	 * of this need.  The first reset prevents new primary requests from
 	 * being issued by our device.  We then must wait 1usec or more for any
 	 * remaining completions from the PCIe bus to trickle in, and then reset
 	 * again to clear out any effects they may have had on our device.
 	 */
-	hw_dbg(hw, "GIO Master Disable bit didn't clear - requesting resets\n");
+	hw_dbg(hw, "GIO Primary Disable bit didn't clear - requesting resets\n");
 gio_disable_fail:
 	hw->mac.flags |= IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
 
@@ -2575,7 +2563,7 @@
 	}
 
 	hw_dbg(hw, "PCIe transaction pending bit also did not clear.\n");
-	return IXGBE_ERR_MASTER_REQUESTS_PENDING;
+	return -EALREADY;
 }
 
 /**
@@ -2600,7 +2588,7 @@
 		 * SW_FW_SYNC bits (not just NVM)
 		 */
 		if (ixgbe_get_eeprom_semaphore(hw))
-			return IXGBE_ERR_SWFW_SYNC;
+			return -EBUSY;
 
 		gssr = IXGBE_READ_REG(hw, IXGBE_GSSR);
 		if (!(gssr & (fwmask | swmask))) {
@@ -2620,7 +2608,7 @@
 		ixgbe_release_swfw_sync(hw, gssr & (fwmask | swmask));
 
 	usleep_range(5000, 10000);
-	return IXGBE_ERR_SWFW_SYNC;
+	return -EBUSY;
 }
 
 /**
@@ -2757,7 +2745,7 @@
 	s32 ret_val;
 
 	if (index > 3)
-		return IXGBE_ERR_PARAM;
+		return -EINVAL;
 
 	/*
 	 * Link must be up to auto-blink the LEDs;
@@ -2803,7 +2791,7 @@
 	s32 ret_val;
 
 	if (index > 3)
-		return IXGBE_ERR_PARAM;
+		return -EINVAL;
 
 	ret_val = hw->mac.ops.prot_autoc_read(hw, &locked, &autoc_reg);
 	if (ret_val)
@@ -2963,7 +2951,7 @@
 	/* Make sure we are using a valid rar index range */
 	if (rar >= rar_entries) {
 		hw_dbg(hw, "RAR index %d is out of range.\n", rar);
-		return IXGBE_ERR_INVALID_ARGUMENT;
+		return -EINVAL;
 	}
 
 	mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar));
@@ -3014,7 +3002,7 @@
 	/* Make sure we are using a valid rar index range */
 	if (rar >= rar_entries) {
 		hw_dbg(hw, "RAR index %d is out of range.\n", rar);
-		return IXGBE_ERR_INVALID_ARGUMENT;
+		return -EINVAL;
 	}
 
 	if (vmdq < 32) {
@@ -3091,7 +3079,7 @@
 	 * will simply bypass the VLVF if there are no entries present in the
 	 * VLVF that contain our VLAN
 	 */
-	first_empty_slot = vlvf_bypass ? IXGBE_ERR_NO_SPACE : 0;
+	first_empty_slot = vlvf_bypass ? -ENOSPC : 0;
 
 	/* add VLAN enable bit for comparison */
 	vlan |= IXGBE_VLVF_VIEN;
@@ -3115,7 +3103,7 @@
 	if (!first_empty_slot)
 		hw_dbg(hw, "No space in VLVF.\n");
 
-	return first_empty_slot ? : IXGBE_ERR_NO_SPACE;
+	return first_empty_slot ? : -ENOSPC;
 }
 
 /**
@@ -3135,7 +3123,7 @@
 	s32 vlvf_index;
 
 	if ((vlan > 4095) || (vind > 63))
-		return IXGBE_ERR_PARAM;
+		return -EINVAL;
 
 	/*
 	 * this is a 2 part operation - first the VFTA, then the
@@ -3596,7 +3584,8 @@
  *
  *  Communicates with the manageability block. On success return 0
  *  else returns semaphore error when encountering an error acquiring
- *  semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
+ *  semaphore, -EINVAL when incorrect parameters passed or -EIO when
+ *  command fails.
  *
  *  This function assumes that the IXGBE_GSSR_SW_MNG_SM semaphore is held
  *  by the caller.
@@ -3609,7 +3598,7 @@
 
 	if (!length || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) {
 		hw_dbg(hw, "Buffer length failure buffersize-%d.\n", length);
-		return IXGBE_ERR_HOST_INTERFACE_COMMAND;
+		return -EINVAL;
 	}
 
 	/* Set bit 9 of FWSTS clearing FW reset indication */
@@ -3620,13 +3609,13 @@
 	hicr = IXGBE_READ_REG(hw, IXGBE_HICR);
 	if (!(hicr & IXGBE_HICR_EN)) {
 		hw_dbg(hw, "IXGBE_HOST_EN bit disabled.\n");
-		return IXGBE_ERR_HOST_INTERFACE_COMMAND;
+		return -EIO;
 	}
 
 	/* Calculate length in DWORDs. We must be DWORD aligned */
 	if (length % sizeof(u32)) {
 		hw_dbg(hw, "Buffer length failure, not aligned to dword");
-		return IXGBE_ERR_INVALID_ARGUMENT;
+		return -EINVAL;
 	}
 
 	dword_len = length >> 2;
@@ -3651,7 +3640,7 @@
 	/* Check command successful completion. */
 	if ((timeout && i == timeout) ||
 	    !(IXGBE_READ_REG(hw, IXGBE_HICR) & IXGBE_HICR_SV))
-		return IXGBE_ERR_HOST_INTERFACE_COMMAND;
+		return -EIO;
 
 	return 0;
 }
@@ -3671,7 +3660,7 @@
  *  in these cases.
  *
  *  Communicates with the manageability block.  On success return 0
- *  else return IXGBE_ERR_HOST_INTERFACE_COMMAND.
+ *  else return -EIO or -EINVAL.
  **/
 s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, void *buffer,
 				 u32 length, u32 timeout,
@@ -3688,7 +3677,7 @@
 
 	if (!length || length > IXGBE_HI_MAX_BLOCK_BYTE_LENGTH) {
 		hw_dbg(hw, "Buffer length failure buffersize-%d.\n", length);
-		return IXGBE_ERR_HOST_INTERFACE_COMMAND;
+		return -EINVAL;
 	}
 	/* Take management host interface semaphore */
 	status = hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_SW_MNG_SM);
@@ -3718,7 +3707,7 @@
 
 	if (length < round_up(buf_len, 4) + hdr_size) {
 		hw_dbg(hw, "Buffer not large enough for reply message.\n");
-		status = IXGBE_ERR_HOST_INTERFACE_COMMAND;
+		status = -EIO;
 		goto rel_out;
 	}
 
@@ -3749,8 +3738,8 @@
  *
  *  Sends driver version number to firmware through the manageability
  *  block.  On success return 0
- *  else returns IXGBE_ERR_SWFW_SYNC when encountering an error acquiring
- *  semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
+ *  else returns -EBUSY when encountering an error acquiring
+ *  semaphore or -EIO when command fails.
  **/
 s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min,
 				 u8 build, u8 sub, __always_unused u16 len,
@@ -3786,7 +3775,7 @@
 		    FW_CEM_RESP_STATUS_SUCCESS)
 			ret_val = 0;
 		else
-			ret_val = IXGBE_ERR_HOST_INTERFACE_COMMAND;
+			ret_val = -EIO;
 
 		break;
 	}
@@ -3884,14 +3873,14 @@
 		return status;
 
 	if ((*ets_offset == 0x0000) || (*ets_offset == 0xFFFF))
-		return IXGBE_NOT_IMPLEMENTED;
+		return -EOPNOTSUPP;
 
 	status = hw->eeprom.ops.read(hw, *ets_offset, ets_cfg);
 	if (status)
 		return status;
 
 	if ((*ets_cfg & IXGBE_ETS_TYPE_MASK) != IXGBE_ETS_TYPE_EMC_SHIFTED)
-		return IXGBE_NOT_IMPLEMENTED;
+		return -EOPNOTSUPP;
 
 	return 0;
 }
@@ -3914,7 +3903,7 @@
 
 	/* Only support thermal sensors attached to physical port 0 */
 	if ((IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1))
-		return IXGBE_NOT_IMPLEMENTED;
+		return -EOPNOTSUPP;
 
 	status = ixgbe_get_ets_data(hw, &ets_cfg, &ets_offset);
 	if (status)
@@ -3974,7 +3963,7 @@
 
 	/* Only support thermal sensors attached to physical port 0 */
 	if ((IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1))
-		return IXGBE_NOT_IMPLEMENTED;
+		return -EOPNOTSUPP;
 
 	status = ixgbe_get_ets_data(hw, &ets_cfg, &ets_offset);
 	if (status)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
@@ -138,6 +138,8 @@
 	"legacy-rx",
 #define IXGBE_PRIV_FLAGS_VF_IPSEC_EN	BIT(1)
 	"vf-ipsec",
+#define IXGBE_PRIV_FLAGS_AUTO_DISABLE_VF	BIT(2)
+	"mdd-disable-vf",
 };
 
 #define IXGBE_PRIV_FLAGS_STR_LEN ARRAY_SIZE(ixgbe_priv_flags_strings)
@@ -2542,6 +2544,14 @@
 	return 0;
 }
 
+static int ixgbe_rss_indir_tbl_max(struct ixgbe_adapter *adapter)
+{
+	if (adapter->hw.mac.type < ixgbe_mac_X550)
+		return 16;
+	else
+		return 64;
+}
+
 static int ixgbe_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
 			   u32 *rule_locs)
 {
@@ -2550,7 +2560,8 @@
 
 	switch (cmd->cmd) {
 	case ETHTOOL_GRXRINGS:
-		cmd->data = adapter->num_rx_queues;
+		cmd->data = min_t(int, adapter->num_rx_queues,
+				  ixgbe_rss_indir_tbl_max(adapter));
 		ret = 0;
 		break;
 	case ETHTOOL_GRXCLSRLCNT:
@@ -2952,14 +2963,6 @@
 	return ret;
 }
 
-static int ixgbe_rss_indir_tbl_max(struct ixgbe_adapter *adapter)
-{
-	if (adapter->hw.mac.type < ixgbe_mac_X550)
-		return 16;
-	else
-		return 64;
-}
-
 static u32 ixgbe_get_rxfh_key_size(struct net_device *netdev)
 {
 	return IXGBE_RSS_KEY_SIZE;
@@ -3008,8 +3011,8 @@
 	int i;
 	u32 reta_entries = ixgbe_rss_indir_tbl_entries(adapter);
 
-	if (hfunc)
-		return -EINVAL;
+	if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
+		return -EOPNOTSUPP;
 
 	/* Fill out the redirection table */
 	if (indir) {
@@ -3246,7 +3249,7 @@
 {
 	struct ixgbe_adapter *adapter = netdev_priv(dev);
 	struct ixgbe_hw *hw = &adapter->hw;
-	s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
+	s32 status = -EFAULT;
 	u8 databyte = 0xFF;
 	int i = 0;
 
@@ -3416,6 +3419,9 @@
 	if (adapter->flags2 & IXGBE_FLAG2_VF_IPSEC_ENABLED)
 		priv_flags |= IXGBE_PRIV_FLAGS_VF_IPSEC_EN;
 
+	if (adapter->flags2 & IXGBE_FLAG2_AUTO_DISABLE_VF)
+		priv_flags |= IXGBE_PRIV_FLAGS_AUTO_DISABLE_VF;
+
 	return priv_flags;
 }
 
@@ -3423,6 +3429,7 @@
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 	unsigned int flags2 = adapter->flags2;
+	unsigned int i;
 
 	flags2 &= ~IXGBE_FLAG2_RX_LEGACY;
 	if (priv_flags & IXGBE_PRIV_FLAGS_LEGACY_RX)
@@ -3432,6 +3439,21 @@
 	if (priv_flags & IXGBE_PRIV_FLAGS_VF_IPSEC_EN)
 		flags2 |= IXGBE_FLAG2_VF_IPSEC_ENABLED;
 
+	flags2 &= ~IXGBE_FLAG2_AUTO_DISABLE_VF;
+	if (priv_flags & IXGBE_PRIV_FLAGS_AUTO_DISABLE_VF) {
+		if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+			/* Reset primary abort counter */
+			for (i = 0; i < adapter->num_vfs; i++)
+				adapter->vfinfo[i].primary_abort_count = 0;
+
+			flags2 |= IXGBE_FLAG2_AUTO_DISABLE_VF;
+		} else {
+			e_info(probe,
+			       "Cannot set private flags: Operation not supported\n");
+			return -EOPNOTSUPP;
+		}
+	}
+
 	if (flags2 != adapter->flags2) {
 		adapter->flags2 = flags2;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
@@ -192,7 +192,7 @@
 	}
 
 	/* alloc the udl from per cpu ddp pool */
-	ddp->udl = dma_pool_alloc(ddp_pool->pool, GFP_KERNEL, &ddp->udp);
+	ddp->udl = dma_pool_alloc(ddp_pool->pool, GFP_ATOMIC, &ddp->udp);
 	if (!ddp->udl) {
 		e_err(drv, "failed allocated ddp context\n");
 		goto out_noddp_unmap;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
@@ -575,6 +575,11 @@
 		return -EINVAL;
 	}
 
+	if (xs->props.mode != XFRM_MODE_TRANSPORT) {
+		netdev_err(dev, "Unsupported mode for ipsec offload\n");
+		return -EINVAL;
+	}
+
 	if (ixgbe_ipsec_check_mgmt_ip(xs)) {
 		netdev_err(dev, "IPsec IP addr clash with mgmt filters\n");
 		return -EINVAL;
@@ -898,12 +903,19 @@
 	/* Tx IPsec offload doesn't seem to work on this
 	 * device, so block these requests for now.
 	 */
-	if (!(sam->flags & XFRM_OFFLOAD_INBOUND)) {
+	sam->flags = sam->flags & ~XFRM_OFFLOAD_IPV6;
+	if (sam->flags != XFRM_OFFLOAD_INBOUND) {
 		err = -EOPNOTSUPP;
 		goto err_out;
 	}
 
-	xs = kzalloc(sizeof(*xs), GFP_KERNEL);
+	algo = xfrm_aead_get_byname(aes_gcm_name, IXGBE_IPSEC_AUTH_BITS, 1);
+	if (unlikely(!algo)) {
+		err = -ENOENT;
+		goto err_out;
+	}
+
+	xs = kzalloc(sizeof(*xs), GFP_ATOMIC);
 	if (unlikely(!xs)) {
 		err = -ENOMEM;
 		goto err_out;
@@ -919,14 +931,8 @@
 		memcpy(&xs->id.daddr.a4, sam->addr, sizeof(xs->id.daddr.a4));
 	xs->xso.dev = adapter->netdev;
 
-	algo = xfrm_aead_get_byname(aes_gcm_name, IXGBE_IPSEC_AUTH_BITS, 1);
-	if (unlikely(!algo)) {
-		err = -ENOENT;
-		goto err_xs;
-	}
-
 	aead_len = sizeof(*xs->aead) + IXGBE_IPSEC_KEY_BITS / 8;
-	xs->aead = kzalloc(aead_len, GFP_KERNEL);
+	xs->aead = kzalloc(aead_len, GFP_ATOMIC);
 	if (unlikely(!xs->aead)) {
 		err = -ENOMEM;
 		goto err_xs;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
@@ -923,7 +923,7 @@
 		ring->queue_index = txr_idx;
 
 		/* assign ring to adapter */
-		adapter->tx_ring[txr_idx] = ring;
+		WRITE_ONCE(adapter->tx_ring[txr_idx], ring);
 
 		/* update count and index */
 		txr_count--;
@@ -950,7 +950,7 @@
 		set_ring_xdp(ring);
 
 		/* assign ring to adapter */
-		adapter->xdp_ring[xdp_idx] = ring;
+		WRITE_ONCE(adapter->xdp_ring[xdp_idx], ring);
 
 		/* update count and index */
 		xdp_count--;
@@ -993,7 +993,7 @@
 		ring->queue_index = rxr_idx;
 
 		/* assign ring to adapter */
-		adapter->rx_ring[rxr_idx] = ring;
+		WRITE_ONCE(adapter->rx_ring[rxr_idx], ring);
 
 		/* update count and index */
 		rxr_count--;
@@ -1022,13 +1022,13 @@
 
 	ixgbe_for_each_ring(ring, q_vector->tx) {
 		if (ring_is_xdp(ring))
-			adapter->xdp_ring[ring->queue_index] = NULL;
+			WRITE_ONCE(adapter->xdp_ring[ring->queue_index], NULL);
 		else
-			adapter->tx_ring[ring->queue_index] = NULL;
+			WRITE_ONCE(adapter->tx_ring[ring->queue_index], NULL);
 	}
 
 	ixgbe_for_each_ring(ring, q_vector->rx)
-		adapter->rx_ring[ring->queue_index] = NULL;
+		WRITE_ONCE(adapter->rx_ring[ring->queue_index], NULL);
 
 	adapter->q_vector[v_idx] = NULL;
 	napi_hash_del(&q_vector->napi);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -1827,7 +1827,8 @@
 				struct sk_buff *skb)
 {
 	if (ring_uses_build_skb(rx_ring)) {
-		unsigned long offset = (unsigned long)(skb->data) & ~PAGE_MASK;
+		unsigned long mask = (unsigned long)ixgbe_rx_pg_size(rx_ring) - 1;
+		unsigned long offset = (unsigned long)(skb->data) & mask;
 
 		dma_sync_single_range_for_cpu(rx_ring->dev,
 					      IXGBE_CB(skb)->dma,
@@ -1947,7 +1948,8 @@
 	return (page_to_nid(page) != numa_mem_id()) || page_is_pfmemalloc(page);
 }
 
-static bool ixgbe_can_reuse_rx_page(struct ixgbe_rx_buffer *rx_buffer)
+static bool ixgbe_can_reuse_rx_page(struct ixgbe_rx_buffer *rx_buffer,
+				    int rx_buffer_pgcnt)
 {
 	unsigned int pagecnt_bias = rx_buffer->pagecnt_bias;
 	struct page *page = rx_buffer->page;
@@ -1958,7 +1960,7 @@
 
 #if (PAGE_SIZE < 8192)
 	/* if we are only owner of page we can reuse it */
-	if (unlikely((page_ref_count(page) - pagecnt_bias) > 1))
+	if (unlikely((rx_buffer_pgcnt - pagecnt_bias) > 1))
 		return false;
 #else
 	/* The last offset is a bit aggressive in that we assume the
@@ -2023,11 +2025,18 @@
 static struct ixgbe_rx_buffer *ixgbe_get_rx_buffer(struct ixgbe_ring *rx_ring,
 						   union ixgbe_adv_rx_desc *rx_desc,
 						   struct sk_buff **skb,
-						   const unsigned int size)
+						   const unsigned int size,
+						   int *rx_buffer_pgcnt)
 {
 	struct ixgbe_rx_buffer *rx_buffer;
 
 	rx_buffer = &rx_ring->rx_buffer_info[rx_ring->next_to_clean];
+	*rx_buffer_pgcnt =
+#if (PAGE_SIZE < 8192)
+		page_count(rx_buffer->page);
+#else
+		0;
+#endif
 	prefetchw(rx_buffer->page);
 	*skb = rx_buffer->skb;
 
@@ -2057,9 +2066,10 @@
 
 static void ixgbe_put_rx_buffer(struct ixgbe_ring *rx_ring,
 				struct ixgbe_rx_buffer *rx_buffer,
-				struct sk_buff *skb)
+				struct sk_buff *skb,
+				int rx_buffer_pgcnt)
 {
-	if (ixgbe_can_reuse_rx_page(rx_buffer)) {
+	if (ixgbe_can_reuse_rx_page(rx_buffer, rx_buffer_pgcnt)) {
 		/* hand second half of page back to the ring */
 		ixgbe_reuse_rx_page(rx_ring, rx_buffer);
 	} else {
@@ -2254,7 +2264,8 @@
 	rx_buffer->page_offset ^= truesize;
 #else
 	unsigned int truesize = ring_uses_build_skb(rx_ring) ?
-				SKB_DATA_ALIGN(IXGBE_SKB_PAD + size) :
+				SKB_DATA_ALIGN(IXGBE_SKB_PAD + size) +
+				SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) :
 				SKB_DATA_ALIGN(size);
 
 	rx_buffer->page_offset += truesize;
@@ -2294,6 +2305,7 @@
 		union ixgbe_adv_rx_desc *rx_desc;
 		struct ixgbe_rx_buffer *rx_buffer;
 		struct sk_buff *skb;
+		int rx_buffer_pgcnt;
 		unsigned int size;
 
 		/* return some buffers to hardware, one at a time is too slow */
@@ -2313,7 +2325,7 @@
 		 */
 		dma_rmb();
 
-		rx_buffer = ixgbe_get_rx_buffer(rx_ring, rx_desc, &skb, size);
+		rx_buffer = ixgbe_get_rx_buffer(rx_ring, rx_desc, &skb, size, &rx_buffer_pgcnt);
 
 		/* retrieve a buffer from the ring */
 		if (!skb) {
@@ -2355,7 +2367,7 @@
 			break;
 		}
 
-		ixgbe_put_rx_buffer(rx_ring, rx_buffer, skb);
+		ixgbe_put_rx_buffer(rx_ring, rx_buffer, skb, rx_buffer_pgcnt);
 		cleaned_count++;
 
 		/* place incomplete frames back on ring for completion */
@@ -2743,7 +2755,6 @@
 {
 	struct ixgbe_hw *hw = &adapter->hw;
 	u32 eicr = adapter->interrupt_event;
-	s32 rc;
 
 	if (test_bit(__IXGBE_DOWN, &adapter->state))
 		return;
@@ -2777,14 +2788,13 @@
 		}
 
 		/* Check if this is not due to overtemp */
-		if (hw->phy.ops.check_overtemp(hw) != IXGBE_ERR_OVERTEMP)
+		if (!hw->phy.ops.check_overtemp(hw))
 			return;
 
 		break;
 	case IXGBE_DEV_ID_X550EM_A_1G_T:
 	case IXGBE_DEV_ID_X550EM_A_1G_T_L:
-		rc = hw->phy.ops.check_overtemp(hw);
-		if (rc != IXGBE_ERR_OVERTEMP)
+		if (!hw->phy.ops.check_overtemp(hw))
 			return;
 		break;
 	default:
@@ -2928,8 +2938,8 @@
 static inline void ixgbe_irq_enable_queues(struct ixgbe_adapter *adapter,
 					   u64 qmask)
 {
-	u32 mask;
 	struct ixgbe_hw *hw = &adapter->hw;
+	u32 mask;
 
 	switch (hw->mac.type) {
 	case ixgbe_mac_82598EB:
@@ -5239,7 +5249,7 @@
 	struct ixgbe_hw *hw = &adapter->hw;
 	struct hlist_node *node2;
 	struct ixgbe_fdir_filter *filter;
-	u64 action;
+	u8 queue;
 
 	spin_lock(&adapter->fdir_perfect_lock);
 
@@ -5248,17 +5258,34 @@
 
 	hlist_for_each_entry_safe(filter, node2,
 				  &adapter->fdir_filter_list, fdir_node) {
-		action = filter->action;
-		if (action != IXGBE_FDIR_DROP_QUEUE && action != 0)
-			action =
-			(action >> ETHTOOL_RX_FLOW_SPEC_RING_VF_OFF) - 1;
+		if (filter->action == IXGBE_FDIR_DROP_QUEUE) {
+			queue = IXGBE_FDIR_DROP_QUEUE;
+		} else {
+			u32 ring = ethtool_get_flow_spec_ring(filter->action);
+			u8 vf = ethtool_get_flow_spec_ring_vf(filter->action);
+
+			if (!vf && (ring >= adapter->num_rx_queues)) {
+				e_err(drv, "FDIR restore failed without VF, ring: %u\n",
+				      ring);
+				continue;
+			} else if (vf &&
+				   ((vf > adapter->num_vfs) ||
+				     ring >= adapter->num_rx_queues_per_pool)) {
+				e_err(drv, "FDIR restore failed with VF, vf: %hhu, ring: %u\n",
+				      vf, ring);
+				continue;
+			}
+
+			/* Map the ring onto the absolute queue index */
+			if (!vf)
+				queue = adapter->rx_ring[ring]->reg_idx;
+			else
+				queue = ((vf - 1) *
+					adapter->num_rx_queues_per_pool) + ring;
+		}
 
 		ixgbe_fdir_write_perfect_filter_82599(hw,
-				&filter->filter,
-				filter->sw_idx,
-				(action == IXGBE_FDIR_DROP_QUEUE) ?
-				IXGBE_FDIR_DROP_QUEUE :
-				adapter->rx_ring[action]->reg_idx);
+				&filter->filter, filter->sw_idx, queue);
 	}
 
 	spin_unlock(&adapter->fdir_perfect_lock);
@@ -5490,7 +5517,7 @@
 {
 	u32 speed;
 	bool autoneg, link_up = false;
-	int ret = IXGBE_ERR_LINK_SETUP;
+	int ret = -EIO;
 
 	if (hw->mac.ops.check_link)
 		ret = hw->mac.ops.check_link(hw, &speed, &link_up, false);
@@ -5650,6 +5677,9 @@
 	ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
 	ctrl_ext |= IXGBE_CTRL_EXT_PFRSTD;
 	IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
+
+	/* update setting rx tx for all active vfs */
+	ixgbe_set_all_vfs(adapter);
 }
 
 void ixgbe_reinit_locked(struct ixgbe_adapter *adapter)
@@ -5909,13 +5939,13 @@
 	err = hw->mac.ops.init_hw(hw);
 	switch (err) {
 	case 0:
-	case IXGBE_ERR_SFP_NOT_PRESENT:
-	case IXGBE_ERR_SFP_NOT_SUPPORTED:
+	case -ENOENT:
+	case -EOPNOTSUPP:
 		break;
-	case IXGBE_ERR_MASTER_REQUESTS_PENDING:
-		e_dev_err("master disable timed out\n");
+	case -EALREADY:
+		e_dev_err("primary disable timed out\n");
 		break;
-	case IXGBE_ERR_EEPROM_VERSION:
+	case -EACCES:
 		/* We are running on a pre-production device, log a warning */
 		e_dev_warn("This device is a pre-production adapter/LOM. "
 			   "Please be aware there may be issues associated with "
@@ -6108,11 +6138,8 @@
 		for (i = 0 ; i < adapter->num_vfs; i++)
 			adapter->vfinfo[i].clear_to_send = false;
 
-		/* ping all the active vfs to let them know we are going down */
-		ixgbe_ping_all_vfs(adapter);
-
-		/* Disable all VFTE/VFRE TX/RX */
-		ixgbe_disable_tx_rx(adapter);
+		/* update setting rx tx for all active vfs */
+		ixgbe_set_all_vfs(adapter);
 	}
 
 	/* disable transmits in the hardware now that interrupts are off */
@@ -6367,6 +6394,9 @@
 	/* n-tuple support exists, always init our spinlock */
 	spin_lock_init(&adapter->fdir_perfect_lock);
 
+	/* init spinlock to avoid concurrency of VF resources */
+	spin_lock_init(&adapter->vfs_lock);
+
 #ifdef CONFIG_IXGBE_DCB
 	ixgbe_init_dcb(adapter);
 #endif
@@ -6690,6 +6720,18 @@
 }
 
 /**
+ * ixgbe_max_xdp_frame_size - returns the maximum allowed frame size for XDP
+ * @adapter: device handle, pointer to adapter
+ */
+static int ixgbe_max_xdp_frame_size(struct ixgbe_adapter *adapter)
+{
+	if (PAGE_SIZE >= 8192 || adapter->flags2 & IXGBE_FLAG2_RX_LEGACY)
+		return IXGBE_RXBUFFER_2K;
+	else
+		return IXGBE_RXBUFFER_3K;
+}
+
+/**
  * ixgbe_change_mtu - Change the Maximum Transfer Unit
  * @netdev: network interface device structure
  * @new_mtu: new value for maximum frame size
@@ -6700,18 +6742,12 @@
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 
-	if (adapter->xdp_prog) {
-		int new_frame_size = new_mtu + ETH_HLEN + ETH_FCS_LEN +
-				     VLAN_HLEN;
-		int i;
-
-		for (i = 0; i < adapter->num_rx_queues; i++) {
-			struct ixgbe_ring *ring = adapter->rx_ring[i];
+	if (ixgbe_enabled_xdp_adapter(adapter)) {
+		int new_frame_size = new_mtu + IXGBE_PKT_HDR_PAD;
 
-			if (new_frame_size > ixgbe_rx_bufsz(ring)) {
-				e_warn(probe, "Requested MTU size is not supported with XDP\n");
-				return -EINVAL;
-			}
+		if (new_frame_size > ixgbe_max_xdp_frame_size(adapter)) {
+			e_warn(probe, "Requested MTU size is not supported with XDP\n");
+			return -EINVAL;
 		}
 	}
 
@@ -7046,7 +7082,10 @@
 	}
 
 	for (i = 0; i < adapter->num_rx_queues; i++) {
-		struct ixgbe_ring *rx_ring = adapter->rx_ring[i];
+		struct ixgbe_ring *rx_ring = READ_ONCE(adapter->rx_ring[i]);
+
+		if (!rx_ring)
+			continue;
 		non_eop_descs += rx_ring->rx_stats.non_eop_descs;
 		alloc_rx_page += rx_ring->rx_stats.alloc_rx_page;
 		alloc_rx_page_failed += rx_ring->rx_stats.alloc_rx_page_failed;
@@ -7067,15 +7106,20 @@
 	packets = 0;
 	/* gather some stats to the adapter struct that are per queue */
 	for (i = 0; i < adapter->num_tx_queues; i++) {
-		struct ixgbe_ring *tx_ring = adapter->tx_ring[i];
+		struct ixgbe_ring *tx_ring = READ_ONCE(adapter->tx_ring[i]);
+
+		if (!tx_ring)
+			continue;
 		restart_queue += tx_ring->tx_stats.restart_queue;
 		tx_busy += tx_ring->tx_stats.tx_busy;
 		bytes += tx_ring->stats.bytes;
 		packets += tx_ring->stats.packets;
 	}
 	for (i = 0; i < adapter->num_xdp_queues; i++) {
-		struct ixgbe_ring *xdp_ring = adapter->xdp_ring[i];
+		struct ixgbe_ring *xdp_ring = READ_ONCE(adapter->xdp_ring[i]);
 
+		if (!xdp_ring)
+			continue;
 		restart_queue += xdp_ring->tx_stats.restart_queue;
 		tx_busy += xdp_ring->tx_stats.tx_busy;
 		bytes += xdp_ring->stats.bytes;
@@ -7588,6 +7632,27 @@
 }
 
 #ifdef CONFIG_PCI_IOV
+static void ixgbe_bad_vf_abort(struct ixgbe_adapter *adapter, u32 vf)
+{
+	struct ixgbe_hw *hw = &adapter->hw;
+
+	if (adapter->hw.mac.type == ixgbe_mac_82599EB &&
+	    adapter->flags2 & IXGBE_FLAG2_AUTO_DISABLE_VF) {
+		adapter->vfinfo[vf].primary_abort_count++;
+		if (adapter->vfinfo[vf].primary_abort_count ==
+		    IXGBE_PRIMARY_ABORT_LIMIT) {
+			ixgbe_set_vf_link_state(adapter, vf,
+						IFLA_VF_LINK_STATE_DISABLE);
+			adapter->vfinfo[vf].primary_abort_count = 0;
+
+			e_info(drv,
+			       "Malicious Driver Detection event detected on PF %d VF %d MAC: %pM mdd-disable-vf=on",
+			       hw->bus.func, vf,
+			       adapter->vfinfo[vf].vf_mac_addresses);
+		}
+	}
+}
+
 static void ixgbe_check_for_bad_vf(struct ixgbe_adapter *adapter)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
@@ -7619,8 +7684,10 @@
 			continue;
 		pci_read_config_word(vfdev, PCI_STATUS, &status_reg);
 		if (status_reg != IXGBE_FAILED_READ_CFG_WORD &&
-		    status_reg & PCI_STATUS_REC_MASTER_ABORT)
+		    status_reg & PCI_STATUS_REC_MASTER_ABORT) {
+			ixgbe_bad_vf_abort(adapter, vf);
 			pcie_flr(vfdev);
+		}
 	}
 }
 
@@ -7707,10 +7774,10 @@
 	adapter->sfp_poll_time = jiffies + IXGBE_SFP_POLL_JIFFIES - 1;
 
 	err = hw->phy.ops.identify_sfp(hw);
-	if (err == IXGBE_ERR_SFP_NOT_SUPPORTED)
+	if (err == -EOPNOTSUPP)
 		goto sfp_out;
 
-	if (err == IXGBE_ERR_SFP_NOT_PRESENT) {
+	if (err == -ENOENT) {
 		/* If no cable is present, then we need to reset
 		 * the next time we find a good cable. */
 		adapter->flags2 |= IXGBE_FLAG2_SFP_NEEDS_RESET;
@@ -7736,7 +7803,7 @@
 	else
 		err = hw->mac.ops.setup_sfp(hw);
 
-	if (err == IXGBE_ERR_SFP_NOT_SUPPORTED)
+	if (err == -EOPNOTSUPP)
 		goto sfp_out;
 
 	adapter->flags |= IXGBE_FLAG_NEED_LINK_CONFIG;
@@ -7745,8 +7812,8 @@
 sfp_out:
 	clear_bit(__IXGBE_IN_SFP_INIT, &adapter->state);
 
-	if ((err == IXGBE_ERR_SFP_NOT_SUPPORTED) &&
-	    (adapter->netdev->reg_state == NETREG_REGISTERED)) {
+	if (err == -EOPNOTSUPP &&
+	    adapter->netdev->reg_state == NETREG_REGISTERED) {
 		e_dev_err("failed to initialize because an unsupported "
 			  "SFP+ module type was detected.\n");
 		e_dev_err("Reload the driver after installing a "
@@ -7816,7 +7883,7 @@
 static void ixgbe_phy_interrupt_subtask(struct ixgbe_adapter *adapter)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
-	u32 status;
+	bool overtemp;
 
 	if (!(adapter->flags2 & IXGBE_FLAG2_PHY_INTERRUPT))
 		return;
@@ -7826,11 +7893,9 @@
 	if (!hw->phy.ops.handle_lasi)
 		return;
 
-	status = hw->phy.ops.handle_lasi(&adapter->hw);
-	if (status != IXGBE_ERR_OVERTEMP)
-		return;
-
-	e_crit(drv, "%s\n", ixgbe_overheat_msg);
+	hw->phy.ops.handle_lasi(&adapter->hw, &overtemp);
+	if (overtemp)
+		e_crit(drv, "%s\n", ixgbe_overheat_msg);
 }
 
 static void ixgbe_reset_subtask(struct ixgbe_adapter *adapter)
@@ -8377,7 +8442,7 @@
 		struct ixgbe_adapter *adapter = q_vector->adapter;
 
 		if (unlikely(skb_tail_pointer(skb) < hdr.network +
-			     VXLAN_HEADROOM))
+			     vxlan_headroom(0)))
 			return;
 
 		/* verify the port is recognized as VXLAN */
@@ -8639,7 +8704,8 @@
 
 	if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
 	    adapter->ptp_clock) {
-		if (!test_and_set_bit_lock(__IXGBE_PTP_TX_IN_PROGRESS,
+		if (adapter->tstamp_config.tx_type == HWTSTAMP_TX_ON &&
+		    !test_and_set_bit_lock(__IXGBE_PTP_TX_IN_PROGRESS,
 					   &adapter->state)) {
 			skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
 			tx_flags |= IXGBE_TX_FLAGS_TSTAMP;
@@ -9558,8 +9624,10 @@
 	ixgbe_atr_compute_perfect_hash_82599(&input->filter, mask);
 	err = ixgbe_fdir_write_perfect_filter_82599(hw, &input->filter,
 						    input->sw_idx, queue);
-	if (!err)
-		ixgbe_update_ethtool_fdir_entry(adapter, input, input->sw_idx);
+	if (err)
+		goto err_out_w_lock;
+
+	ixgbe_update_ethtool_fdir_entry(adapter, input, input->sw_idx);
 	spin_unlock(&adapter->fdir_perfect_lock);
 
 	if ((uhtid != 0x800) && (adapter->jump_tables[uhtid]))
@@ -10247,7 +10315,12 @@
 
 	/* If transitioning XDP modes reconfigure rings */
 	if (need_reset) {
-		int err = ixgbe_setup_tc(dev, adapter->hw_tcs);
+		int err;
+
+		if (!prog)
+			/* Wait until ndo_xsk_wakeup completes. */
+			synchronize_rcu();
+		err = ixgbe_setup_tc(dev, adapter->hw_tcs);
 
 		if (err) {
 			rcu_assign_pointer(adapter->xdp_prog, old_prog);
@@ -10361,6 +10434,7 @@
 	.ndo_set_vf_vlan	= ixgbe_ndo_set_vf_vlan,
 	.ndo_set_vf_rate	= ixgbe_ndo_set_vf_bw,
 	.ndo_set_vf_spoofchk	= ixgbe_ndo_set_vf_spoofchk,
+	.ndo_set_vf_link_state	= ixgbe_ndo_set_vf_link_state,
 	.ndo_set_vf_rss_query_en = ixgbe_ndo_set_vf_rss_query_en,
 	.ndo_set_vf_trust	= ixgbe_ndo_set_vf_trust,
 	.ndo_get_vf_config	= ixgbe_ndo_get_vf_config,
@@ -10479,6 +10553,44 @@
 }
 
 /**
+ * ixgbe_irq_disable_single - Disable single IRQ vector
+ * @adapter: adapter structure
+ * @ring: ring index
+ **/
+static void ixgbe_irq_disable_single(struct ixgbe_adapter *adapter, u32 ring)
+{
+	struct ixgbe_hw *hw = &adapter->hw;
+	u64 qmask = BIT_ULL(ring);
+	u32 mask;
+
+	switch (adapter->hw.mac.type) {
+	case ixgbe_mac_82598EB:
+		mask = qmask & IXGBE_EIMC_RTX_QUEUE;
+		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, mask);
+		break;
+	case ixgbe_mac_82599EB:
+	case ixgbe_mac_X540:
+	case ixgbe_mac_X550:
+	case ixgbe_mac_X550EM_x:
+	case ixgbe_mac_x550em_a:
+		mask = (qmask & 0xFFFFFFFF);
+		if (mask)
+			IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(0), mask);
+		mask = (qmask >> 32);
+		if (mask)
+			IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(1), mask);
+		break;
+	default:
+		break;
+	}
+	IXGBE_WRITE_FLUSH(&adapter->hw);
+	if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED)
+		synchronize_irq(adapter->msix_entries[ring].vector);
+	else
+		synchronize_irq(adapter->pdev->irq);
+}
+
+/**
  * ixgbe_txrx_ring_disable - Disable Rx/Tx/XDP Tx rings
  * @adapter: adapter structure
  * @ring: ring index
@@ -10494,6 +10606,11 @@
 	tx_ring = adapter->tx_ring[ring];
 	xdp_ring = adapter->xdp_ring[ring];
 
+	ixgbe_irq_disable_single(adapter, ring);
+
+	/* Rx/Tx/XDP Tx share the same napi context. */
+	napi_disable(&rx_ring->q_vector->napi);
+
 	ixgbe_disable_txr(adapter, tx_ring);
 	if (xdp_ring)
 		ixgbe_disable_txr(adapter, xdp_ring);
@@ -10502,9 +10619,6 @@
 	if (xdp_ring)
 		synchronize_rcu();
 
-	/* Rx/Tx/XDP Tx share the same napi context. */
-	napi_disable(&rx_ring->q_vector->napi);
-
 	ixgbe_clean_tx_ring(tx_ring);
 	if (xdp_ring)
 		ixgbe_clean_tx_ring(xdp_ring);
@@ -10532,9 +10646,6 @@
 	tx_ring = adapter->tx_ring[ring];
 	xdp_ring = adapter->xdp_ring[ring];
 
-	/* Rx/Tx/XDP Tx share the same napi context. */
-	napi_enable(&rx_ring->q_vector->napi);
-
 	ixgbe_configure_tx_ring(adapter, tx_ring);
 	if (xdp_ring)
 		ixgbe_configure_tx_ring(adapter, xdp_ring);
@@ -10543,6 +10654,11 @@
 	clear_bit(__IXGBE_TX_DISABLED, &tx_ring->state);
 	if (xdp_ring)
 		clear_bit(__IXGBE_TX_DISABLED, &xdp_ring->state);
+
+	/* Rx/Tx/XDP Tx share the same napi context. */
+	napi_enable(&rx_ring->q_vector->napi);
+	ixgbe_irq_enable_queues(adapter, BIT_ULL(ring));
+	IXGBE_WRITE_FLUSH(&adapter->hw);
 }
 
 /**
@@ -10829,6 +10945,9 @@
 	if (err)
 		goto err_sw_init;
 
+	if (adapter->hw.mac.type == ixgbe_mac_82599EB)
+		adapter->flags2 |= IXGBE_FLAG2_AUTO_DISABLE_VF;
+
 	/* Make sure the SWFW semaphore is in a valid state */
 	if (hw->mac.ops.init_swfw_sync)
 		hw->mac.ops.init_swfw_sync(hw);
@@ -10864,9 +10983,9 @@
 	err = hw->mac.ops.reset_hw(hw);
 	hw->phy.reset_if_overtemp = false;
 	ixgbe_set_eee_capable(adapter);
-	if (err == IXGBE_ERR_SFP_NOT_PRESENT) {
+	if (err == -ENOENT) {
 		err = 0;
-	} else if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
+	} else if (err == -EOPNOTSUPP) {
 		e_dev_err("failed to load because an unsupported SFP+ or QSFP module type was detected.\n");
 		e_dev_err("Reload the driver after installing a supported module.\n");
 		goto err_sw_init;
@@ -11083,7 +11202,7 @@
 
 	/* reset the hardware with the new settings */
 	err = hw->mac.ops.start_hw(hw);
-	if (err == IXGBE_ERR_EEPROM_VERSION) {
+	if (err == -EACCES) {
 		/* We are running on a pre-production device, log a warning */
 		e_dev_warn("This device is a pre-production adapter/LOM. "
 			   "Please be aware there may be issues associated "
@@ -11163,6 +11282,7 @@
 	disable_dev = !test_and_set_bit(__IXGBE_DISABLED, &adapter->state);
 	free_netdev(netdev);
 err_alloc_etherdev:
+	pci_disable_pcie_error_reporting(pdev);
 	pci_release_mem_regions(pdev);
 err_pci_reg:
 err_dma:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c
@@ -24,7 +24,7 @@
 		size = mbx->size;
 
 	if (!mbx->ops)
-		return IXGBE_ERR_MBX;
+		return -EIO;
 
 	return mbx->ops->read(hw, msg, size, mbx_id);
 }
@@ -43,10 +43,10 @@
 	struct ixgbe_mbx_info *mbx = &hw->mbx;
 
 	if (size > mbx->size)
-		return IXGBE_ERR_MBX;
+		return -EINVAL;
 
 	if (!mbx->ops)
-		return IXGBE_ERR_MBX;
+		return -EIO;
 
 	return mbx->ops->write(hw, msg, size, mbx_id);
 }
@@ -63,7 +63,7 @@
 	struct ixgbe_mbx_info *mbx = &hw->mbx;
 
 	if (!mbx->ops)
-		return IXGBE_ERR_MBX;
+		return -EIO;
 
 	return mbx->ops->check_for_msg(hw, mbx_id);
 }
@@ -80,7 +80,7 @@
 	struct ixgbe_mbx_info *mbx = &hw->mbx;
 
 	if (!mbx->ops)
-		return IXGBE_ERR_MBX;
+		return -EIO;
 
 	return mbx->ops->check_for_ack(hw, mbx_id);
 }
@@ -97,7 +97,7 @@
 	struct ixgbe_mbx_info *mbx = &hw->mbx;
 
 	if (!mbx->ops)
-		return IXGBE_ERR_MBX;
+		return -EIO;
 
 	return mbx->ops->check_for_rst(hw, mbx_id);
 }
@@ -115,12 +115,12 @@
 	int countdown = mbx->timeout;
 
 	if (!countdown || !mbx->ops)
-		return IXGBE_ERR_MBX;
+		return -EIO;
 
 	while (mbx->ops->check_for_msg(hw, mbx_id)) {
 		countdown--;
 		if (!countdown)
-			return IXGBE_ERR_MBX;
+			return -EIO;
 		udelay(mbx->usec_delay);
 	}
 
@@ -140,12 +140,12 @@
 	int countdown = mbx->timeout;
 
 	if (!countdown || !mbx->ops)
-		return IXGBE_ERR_MBX;
+		return -EIO;
 
 	while (mbx->ops->check_for_ack(hw, mbx_id)) {
 		countdown--;
 		if (!countdown)
-			return IXGBE_ERR_MBX;
+			return -EIO;
 		udelay(mbx->usec_delay);
 	}
 
@@ -169,7 +169,7 @@
 	s32 ret_val;
 
 	if (!mbx->ops)
-		return IXGBE_ERR_MBX;
+		return -EIO;
 
 	ret_val = ixgbe_poll_for_msg(hw, mbx_id);
 	if (ret_val)
@@ -197,7 +197,7 @@
 
 	/* exit if either we can't write or there isn't a defined timeout */
 	if (!mbx->ops || !mbx->timeout)
-		return IXGBE_ERR_MBX;
+		return -EIO;
 
 	/* send msg */
 	ret_val = mbx->ops->write(hw, msg, size, mbx_id);
@@ -217,7 +217,7 @@
 		return 0;
 	}
 
-	return IXGBE_ERR_MBX;
+	return -EIO;
 }
 
 /**
@@ -238,7 +238,7 @@
 		return 0;
 	}
 
-	return IXGBE_ERR_MBX;
+	return -EIO;
 }
 
 /**
@@ -259,7 +259,7 @@
 		return 0;
 	}
 
-	return IXGBE_ERR_MBX;
+	return -EIO;
 }
 
 /**
@@ -295,7 +295,7 @@
 		return 0;
 	}
 
-	return IXGBE_ERR_MBX;
+	return -EIO;
 }
 
 /**
@@ -317,7 +317,7 @@
 	if (p2v_mailbox & IXGBE_PFMAILBOX_PFU)
 		return 0;
 
-	return IXGBE_ERR_MBX;
+	return -EIO;
 }
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h
@@ -7,7 +7,6 @@
 #include "ixgbe_type.h"
 
 #define IXGBE_VFMAILBOX_SIZE        16 /* 16 32 bit words - 64 bytes */
-#define IXGBE_ERR_MBX               -100
 
 #define IXGBE_VFMAILBOX             0x002FC
 #define IXGBE_VFMBMEM               0x00200
@@ -85,6 +84,8 @@
 #define IXGBE_VF_IPSEC_ADD	0x0d
 #define IXGBE_VF_IPSEC_DEL	0x0e
 
+#define IXGBE_VF_GET_LINK_STATE 0x10 /* get vf link state */
+
 /* length of permanent address message returned from PF */
 #define IXGBE_VF_PERMADDR_MSG_LEN 4
 /* word in permanent address message with the current multicast type */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
@@ -102,7 +102,7 @@
 	csum = ~csum;
 	do {
 		if (lock && hw->mac.ops.acquire_swfw_sync(hw, swfw_mask))
-			return IXGBE_ERR_SWFW_SYNC;
+			return -EBUSY;
 		ixgbe_i2c_start(hw);
 		/* Device Address and write indication */
 		if (ixgbe_out_i2c_byte_ack(hw, addr))
@@ -150,7 +150,7 @@
 			hw_dbg(hw, "I2C byte read combined error.\n");
 	} while (retry < max_retry);
 
-	return IXGBE_ERR_I2C;
+	return -EIO;
 }
 
 /**
@@ -179,7 +179,7 @@
 	csum = ~csum;
 	do {
 		if (lock && hw->mac.ops.acquire_swfw_sync(hw, swfw_mask))
-			return IXGBE_ERR_SWFW_SYNC;
+			return -EBUSY;
 		ixgbe_i2c_start(hw);
 		/* Device Address and write indication */
 		if (ixgbe_out_i2c_byte_ack(hw, addr))
@@ -215,7 +215,7 @@
 			hw_dbg(hw, "I2C byte write combined error.\n");
 	} while (retry < max_retry);
 
-	return IXGBE_ERR_I2C;
+	return -EIO;
 }
 
 /**
@@ -262,8 +262,8 @@
  **/
 s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw)
 {
+	u32 status = -EFAULT;
 	u32 phy_addr;
-	u32 status = IXGBE_ERR_PHY_ADDR_INVALID;
 
 	if (!hw->phy.phy_semaphore_mask) {
 		if (hw->bus.lan_id)
@@ -282,7 +282,7 @@
 		if (ixgbe_probe_phy(hw, phy_addr))
 			return 0;
 		else
-			return IXGBE_ERR_PHY_ADDR_INVALID;
+			return -EFAULT;
 	}
 
 	for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) {
@@ -405,8 +405,7 @@
 		return status;
 
 	/* Don't reset PHY if it's shut down due to overtemp. */
-	if (!hw->phy.reset_if_overtemp &&
-	    (IXGBE_ERR_OVERTEMP == hw->phy.ops.check_overtemp(hw)))
+	if (!hw->phy.reset_if_overtemp && hw->phy.ops.check_overtemp(hw))
 		return 0;
 
 	/* Blocked by MNG FW so bail */
@@ -454,7 +453,7 @@
 
 	if (ctrl & MDIO_CTRL1_RESET) {
 		hw_dbg(hw, "PHY reset polling failed to complete.\n");
-		return IXGBE_ERR_RESET_FAILED;
+		return -EIO;
 	}
 
 	return 0;
@@ -496,7 +495,7 @@
 
 	if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) {
 		hw_dbg(hw, "PHY address command did not complete.\n");
-		return IXGBE_ERR_PHY;
+		return -EIO;
 	}
 
 	/* Address cycle complete, setup and write the read
@@ -523,7 +522,7 @@
 
 	if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) {
 		hw_dbg(hw, "PHY read command didn't complete\n");
-		return IXGBE_ERR_PHY;
+		return -EIO;
 	}
 
 	/* Read operation is complete.  Get the data
@@ -555,7 +554,7 @@
 						phy_data);
 		hw->mac.ops.release_swfw_sync(hw, gssr);
 	} else {
-		return IXGBE_ERR_SWFW_SYNC;
+		return -EBUSY;
 	}
 
 	return status;
@@ -600,7 +599,7 @@
 
 	if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) {
 		hw_dbg(hw, "PHY address cmd didn't complete\n");
-		return IXGBE_ERR_PHY;
+		return -EIO;
 	}
 
 	/*
@@ -628,7 +627,7 @@
 
 	if ((command & IXGBE_MSCA_MDI_COMMAND) != 0) {
 		hw_dbg(hw, "PHY write cmd didn't complete\n");
-		return IXGBE_ERR_PHY;
+		return -EIO;
 	}
 
 	return 0;
@@ -653,7 +652,7 @@
 						 phy_data);
 		hw->mac.ops.release_swfw_sync(hw, gssr);
 	} else {
-		return IXGBE_ERR_SWFW_SYNC;
+		return -EBUSY;
 	}
 
 	return status;
@@ -851,9 +850,11 @@
 	rp_pdev = pci_get_domain_bus_and_slot(0, 0, devfn);
 	if (rp_pdev && rp_pdev->subordinate) {
 		bus = rp_pdev->subordinate->number;
+		pci_dev_put(rp_pdev);
 		return pci_get_domain_bus_and_slot(0, bus, 0);
 	}
 
+	pci_dev_put(rp_pdev);
 	return NULL;
 }
 
@@ -870,6 +871,7 @@
 	struct ixgbe_adapter *adapter = hw->back;
 	struct pci_dev *pdev = adapter->pdev;
 	struct pci_dev *func0_pdev;
+	bool has_mii = false;
 
 	/* For the C3000 family of SoCs (x550em_a) the internal ixgbe devices
 	 * are always downstream of root ports @ 0000:00:16.0 & 0000:00:17.0
@@ -880,15 +882,16 @@
 	func0_pdev = ixgbe_get_first_secondary_devfn(PCI_DEVFN(0x16, 0));
 	if (func0_pdev) {
 		if (func0_pdev == pdev)
-			return true;
-		else
-			return false;
+			has_mii = true;
+		goto out;
 	}
 	func0_pdev = ixgbe_get_first_secondary_devfn(PCI_DEVFN(0x17, 0));
 	if (func0_pdev == pdev)
-		return true;
+		has_mii = true;
 
-	return false;
+out:
+	pci_dev_put(func0_pdev);
+	return has_mii;
 }
 
 /**
@@ -1298,7 +1301,7 @@
 
 	if ((phy_data & MDIO_CTRL1_RESET) != 0) {
 		hw_dbg(hw, "PHY reset did not complete.\n");
-		return IXGBE_ERR_PHY;
+		return -EIO;
 	}
 
 	/* Get init offsets */
@@ -1355,12 +1358,12 @@
 				hw_dbg(hw, "SOL\n");
 			} else {
 				hw_dbg(hw, "Bad control value\n");
-				return IXGBE_ERR_PHY;
+				return -EIO;
 			}
 			break;
 		default:
 			hw_dbg(hw, "Bad control type\n");
-			return IXGBE_ERR_PHY;
+			return -EIO;
 		}
 	}
 
@@ -1368,7 +1371,7 @@
 
 err_eeprom:
 	hw_err(hw, "eeprom read at offset %d failed\n", data_offset);
-	return IXGBE_ERR_PHY;
+	return -EIO;
 }
 
 /**
@@ -1386,10 +1389,10 @@
 		return ixgbe_identify_qsfp_module_generic(hw);
 	default:
 		hw->phy.sfp_type = ixgbe_sfp_type_not_present;
-		return IXGBE_ERR_SFP_NOT_PRESENT;
+		return -ENOENT;
 	}
 
-	return IXGBE_ERR_SFP_NOT_PRESENT;
+	return -ENOENT;
 }
 
 /**
@@ -1414,7 +1417,7 @@
 
 	if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_fiber) {
 		hw->phy.sfp_type = ixgbe_sfp_type_not_present;
-		return IXGBE_ERR_SFP_NOT_PRESENT;
+		return -ENOENT;
 	}
 
 	/* LAN ID is needed for sfp_type determination */
@@ -1429,7 +1432,7 @@
 
 	if (identifier != IXGBE_SFF_IDENTIFIER_SFP) {
 		hw->phy.type = ixgbe_phy_sfp_unsupported;
-		return IXGBE_ERR_SFP_NOT_SUPPORTED;
+		return -EOPNOTSUPP;
 	}
 	status = hw->phy.ops.read_i2c_eeprom(hw,
 					     IXGBE_SFF_1GBE_COMP_CODES,
@@ -1620,7 +1623,7 @@
 	      hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
 	      hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1)) {
 		hw->phy.type = ixgbe_phy_sfp_unsupported;
-		return IXGBE_ERR_SFP_NOT_SUPPORTED;
+		return -EOPNOTSUPP;
 	}
 
 	/* Anything else 82598-based is supported */
@@ -1644,7 +1647,7 @@
 		}
 		hw_dbg(hw, "SFP+ module not supported\n");
 		hw->phy.type = ixgbe_phy_sfp_unsupported;
-		return IXGBE_ERR_SFP_NOT_SUPPORTED;
+		return -EOPNOTSUPP;
 	}
 	return 0;
 
@@ -1654,7 +1657,7 @@
 		hw->phy.id = 0;
 		hw->phy.type = ixgbe_phy_unknown;
 	}
-	return IXGBE_ERR_SFP_NOT_PRESENT;
+	return -ENOENT;
 }
 
 /**
@@ -1681,7 +1684,7 @@
 
 	if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_fiber_qsfp) {
 		hw->phy.sfp_type = ixgbe_sfp_type_not_present;
-		return IXGBE_ERR_SFP_NOT_PRESENT;
+		return -ENOENT;
 	}
 
 	/* LAN ID is needed for sfp_type determination */
@@ -1695,7 +1698,7 @@
 
 	if (identifier != IXGBE_SFF_IDENTIFIER_QSFP_PLUS) {
 		hw->phy.type = ixgbe_phy_sfp_unsupported;
-		return IXGBE_ERR_SFP_NOT_SUPPORTED;
+		return -EOPNOTSUPP;
 	}
 
 	hw->phy.id = identifier;
@@ -1763,7 +1766,7 @@
 		} else {
 			/* unsupported module type */
 			hw->phy.type = ixgbe_phy_sfp_unsupported;
-			return IXGBE_ERR_SFP_NOT_SUPPORTED;
+			return -EOPNOTSUPP;
 		}
 	}
 
@@ -1823,7 +1826,7 @@
 			}
 			hw_dbg(hw, "QSFP module not supported\n");
 			hw->phy.type = ixgbe_phy_sfp_unsupported;
-			return IXGBE_ERR_SFP_NOT_SUPPORTED;
+			return -EOPNOTSUPP;
 		}
 		return 0;
 	}
@@ -1834,7 +1837,7 @@
 	hw->phy.id = 0;
 	hw->phy.type = ixgbe_phy_unknown;
 
-	return IXGBE_ERR_SFP_NOT_PRESENT;
+	return -ENOENT;
 }
 
 /**
@@ -1854,14 +1857,14 @@
 	u16 sfp_type = hw->phy.sfp_type;
 
 	if (hw->phy.sfp_type == ixgbe_sfp_type_unknown)
-		return IXGBE_ERR_SFP_NOT_SUPPORTED;
+		return -EOPNOTSUPP;
 
 	if (hw->phy.sfp_type == ixgbe_sfp_type_not_present)
-		return IXGBE_ERR_SFP_NOT_PRESENT;
+		return -ENOENT;
 
 	if ((hw->device_id == IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM) &&
 	    (hw->phy.sfp_type == ixgbe_sfp_type_da_cu))
-		return IXGBE_ERR_SFP_NOT_SUPPORTED;
+		return -EOPNOTSUPP;
 
 	/*
 	 * Limiting active cables and 1G Phys must be initialized as
@@ -1882,11 +1885,11 @@
 	if (hw->eeprom.ops.read(hw, IXGBE_PHY_INIT_OFFSET_NL, list_offset)) {
 		hw_err(hw, "eeprom read at %d failed\n",
 		       IXGBE_PHY_INIT_OFFSET_NL);
-		return IXGBE_ERR_SFP_NO_INIT_SEQ_PRESENT;
+		return -EIO;
 	}
 
 	if ((!*list_offset) || (*list_offset == 0xFFFF))
-		return IXGBE_ERR_SFP_NO_INIT_SEQ_PRESENT;
+		return -EIO;
 
 	/* Shift offset to first ID word */
 	(*list_offset)++;
@@ -1905,7 +1908,7 @@
 				goto err_phy;
 			if ((!*data_offset) || (*data_offset == 0xFFFF)) {
 				hw_dbg(hw, "SFP+ module not supported\n");
-				return IXGBE_ERR_SFP_NOT_SUPPORTED;
+				return -EOPNOTSUPP;
 			} else {
 				break;
 			}
@@ -1918,14 +1921,14 @@
 
 	if (sfp_id == IXGBE_PHY_INIT_END_NL) {
 		hw_dbg(hw, "No matching SFP+ module found\n");
-		return IXGBE_ERR_SFP_NOT_SUPPORTED;
+		return -EOPNOTSUPP;
 	}
 
 	return 0;
 
 err_phy:
 	hw_err(hw, "eeprom read at offset %d failed\n", *list_offset);
-	return IXGBE_ERR_PHY;
+	return -EIO;
 }
 
 /**
@@ -2020,7 +2023,7 @@
 
 	do {
 		if (lock && hw->mac.ops.acquire_swfw_sync(hw, swfw_mask))
-			return IXGBE_ERR_SWFW_SYNC;
+			return -EBUSY;
 
 		ixgbe_i2c_start(hw);
 
@@ -2136,7 +2139,7 @@
 	u32 swfw_mask = hw->phy.phy_semaphore_mask;
 
 	if (lock && hw->mac.ops.acquire_swfw_sync(hw, swfw_mask))
-		return IXGBE_ERR_SWFW_SYNC;
+		return -EBUSY;
 
 	do {
 		ixgbe_i2c_start(hw);
@@ -2378,7 +2381,7 @@
 
 	if (ack == 1) {
 		hw_dbg(hw, "I2C ack was not received.\n");
-		status = IXGBE_ERR_I2C;
+		status = -EIO;
 	}
 
 	ixgbe_lower_i2c_clk(hw, &i2cctl);
@@ -2450,7 +2453,7 @@
 		udelay(IXGBE_I2C_T_LOW);
 	} else {
 		hw_dbg(hw, "I2C data was not set to %X\n", data);
-		return IXGBE_ERR_I2C;
+		return -EIO;
 	}
 
 	return 0;
@@ -2546,7 +2549,7 @@
 	*i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL(hw));
 	if (data != ixgbe_get_i2c_data(hw, i2cctl)) {
 		hw_dbg(hw, "Error - I2C data was not set to %X.\n", data);
-		return IXGBE_ERR_I2C;
+		return -EIO;
 	}
 
 	return 0;
@@ -2616,22 +2619,24 @@
  *  @hw: pointer to hardware structure
  *
  *  Checks if the LASI temp alarm status was triggered due to overtemp
+ *
+ *  Return true when an overtemp event detected, otherwise false.
  **/
-s32 ixgbe_tn_check_overtemp(struct ixgbe_hw *hw)
+bool ixgbe_tn_check_overtemp(struct ixgbe_hw *hw)
 {
 	u16 phy_data = 0;
+	u32 status;
 
 	if (hw->device_id != IXGBE_DEV_ID_82599_T3_LOM)
-		return 0;
+		return false;
 
 	/* Check that the LASI temp alarm status was triggered */
-	hw->phy.ops.read_reg(hw, IXGBE_TN_LASI_STATUS_REG,
-			     MDIO_MMD_PMAPMD, &phy_data);
-
-	if (!(phy_data & IXGBE_TN_LASI_STATUS_TEMP_ALARM))
-		return 0;
+	status = hw->phy.ops.read_reg(hw, IXGBE_TN_LASI_STATUS_REG,
+				      MDIO_MMD_PMAPMD, &phy_data);
+	if (status)
+		return false;
 
-	return IXGBE_ERR_OVERTEMP;
+	return !!(phy_data & IXGBE_TN_LASI_STATUS_TEMP_ALARM);
 }
 
 /** ixgbe_set_copper_phy_power - Control power for copper phy
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
@@ -155,7 +155,7 @@
 s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
 					u16 *list_offset,
 					u16 *data_offset);
-s32 ixgbe_tn_check_overtemp(struct ixgbe_hw *hw);
+bool ixgbe_tn_check_overtemp(struct ixgbe_hw *hw);
 s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
 				u8 dev_addr, u8 *data);
 s32 ixgbe_read_i2c_byte_generic_unlocked(struct ixgbe_hw *hw, u8 byte_offset,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
@@ -989,6 +989,7 @@
 	u32 tsync_tx_ctl = IXGBE_TSYNCTXCTL_ENABLED;
 	u32 tsync_rx_ctl = IXGBE_TSYNCRXCTL_ENABLED;
 	u32 tsync_rx_mtrl = PTP_EV_PORT << 16;
+	u32 aflags = adapter->flags;
 	bool is_l2 = false;
 	u32 regval;
 
@@ -1009,20 +1010,20 @@
 	case HWTSTAMP_FILTER_NONE:
 		tsync_rx_ctl = 0;
 		tsync_rx_mtrl = 0;
-		adapter->flags &= ~(IXGBE_FLAG_RX_HWTSTAMP_ENABLED |
-				    IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER);
+		aflags &= ~(IXGBE_FLAG_RX_HWTSTAMP_ENABLED |
+			    IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER);
 		break;
 	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
 		tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L4_V1;
 		tsync_rx_mtrl |= IXGBE_RXMTRL_V1_SYNC_MSG;
-		adapter->flags |= (IXGBE_FLAG_RX_HWTSTAMP_ENABLED |
-				   IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER);
+		aflags |= (IXGBE_FLAG_RX_HWTSTAMP_ENABLED |
+			   IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER);
 		break;
 	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
 		tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L4_V1;
 		tsync_rx_mtrl |= IXGBE_RXMTRL_V1_DELAY_REQ_MSG;
-		adapter->flags |= (IXGBE_FLAG_RX_HWTSTAMP_ENABLED |
-				   IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER);
+		aflags |= (IXGBE_FLAG_RX_HWTSTAMP_ENABLED |
+			   IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER);
 		break;
 	case HWTSTAMP_FILTER_PTP_V2_EVENT:
 	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
@@ -1036,8 +1037,8 @@
 		tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_EVENT_V2;
 		is_l2 = true;
 		config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
-		adapter->flags |= (IXGBE_FLAG_RX_HWTSTAMP_ENABLED |
-				   IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER);
+		aflags |= (IXGBE_FLAG_RX_HWTSTAMP_ENABLED |
+			   IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER);
 		break;
 	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
 	case HWTSTAMP_FILTER_NTP_ALL:
@@ -1048,7 +1049,7 @@
 		if (hw->mac.type >= ixgbe_mac_X550) {
 			tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_ALL;
 			config->rx_filter = HWTSTAMP_FILTER_ALL;
-			adapter->flags |= IXGBE_FLAG_RX_HWTSTAMP_ENABLED;
+			aflags |= IXGBE_FLAG_RX_HWTSTAMP_ENABLED;
 			break;
 		}
 		/* fall through */
@@ -1059,8 +1060,6 @@
 		 * Delay_Req messages and hardware does not support
 		 * timestamping all packets => return error
 		 */
-		adapter->flags &= ~(IXGBE_FLAG_RX_HWTSTAMP_ENABLED |
-				    IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER);
 		config->rx_filter = HWTSTAMP_FILTER_NONE;
 		return -ERANGE;
 	}
@@ -1092,8 +1091,8 @@
 			       IXGBE_TSYNCRXCTL_TYPE_ALL |
 			       IXGBE_TSYNCRXCTL_TSIP_UT_EN;
 		config->rx_filter = HWTSTAMP_FILTER_ALL;
-		adapter->flags |= IXGBE_FLAG_RX_HWTSTAMP_ENABLED;
-		adapter->flags &= ~IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER;
+		aflags |= IXGBE_FLAG_RX_HWTSTAMP_ENABLED;
+		aflags &= ~IXGBE_FLAG_RX_HWTSTAMP_IN_REGISTER;
 		is_l2 = true;
 		break;
 	default:
@@ -1126,6 +1125,9 @@
 
 	IXGBE_WRITE_FLUSH(hw);
 
+	/* configure adapter flags only when HW is actually configured */
+	adapter->flags = aflags;
+
 	/* clear TX/RX time stamp registers, just to be sure */
 	ixgbe_ptp_clear_tx_timestamp(adapter);
 	IXGBE_READ_REG(hw, IXGBE_RXSTMPH);
@@ -1211,7 +1213,6 @@
 	struct cyclecounter cc;
 	unsigned long flags;
 	u32 incval = 0;
-	u32 tsauxc = 0;
 	u32 fuse0 = 0;
 
 	/* For some of the boards below this mask is technically incorrect.
@@ -1246,18 +1247,6 @@
 	case ixgbe_mac_x550em_a:
 	case ixgbe_mac_X550:
 		cc.read = ixgbe_ptp_read_X550;
-
-		/* enable SYSTIME counter */
-		IXGBE_WRITE_REG(hw, IXGBE_SYSTIMR, 0);
-		IXGBE_WRITE_REG(hw, IXGBE_SYSTIML, 0);
-		IXGBE_WRITE_REG(hw, IXGBE_SYSTIMH, 0);
-		tsauxc = IXGBE_READ_REG(hw, IXGBE_TSAUXC);
-		IXGBE_WRITE_REG(hw, IXGBE_TSAUXC,
-				tsauxc & ~IXGBE_TSAUXC_DISABLE_SYSTIME);
-		IXGBE_WRITE_REG(hw, IXGBE_TSIM, IXGBE_TSIM_TXTS);
-		IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_TIMESYNC);
-
-		IXGBE_WRITE_FLUSH(hw);
 		break;
 	case ixgbe_mac_X540:
 		cc.read = ixgbe_ptp_read_82599;
@@ -1290,6 +1279,50 @@
 }
 
 /**
+ * ixgbe_ptp_init_systime - Initialize SYSTIME registers
+ * @adapter: the ixgbe private board structure
+ *
+ * Initialize and start the SYSTIME registers.
+ */
+static void ixgbe_ptp_init_systime(struct ixgbe_adapter *adapter)
+{
+	struct ixgbe_hw *hw = &adapter->hw;
+	u32 tsauxc;
+
+	switch (hw->mac.type) {
+	case ixgbe_mac_X550EM_x:
+	case ixgbe_mac_x550em_a:
+	case ixgbe_mac_X550:
+		tsauxc = IXGBE_READ_REG(hw, IXGBE_TSAUXC);
+
+		/* Reset SYSTIME registers to 0 */
+		IXGBE_WRITE_REG(hw, IXGBE_SYSTIMR, 0);
+		IXGBE_WRITE_REG(hw, IXGBE_SYSTIML, 0);
+		IXGBE_WRITE_REG(hw, IXGBE_SYSTIMH, 0);
+
+		/* Reset interrupt settings */
+		IXGBE_WRITE_REG(hw, IXGBE_TSIM, IXGBE_TSIM_TXTS);
+		IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_TIMESYNC);
+
+		/* Activate the SYSTIME counter */
+		IXGBE_WRITE_REG(hw, IXGBE_TSAUXC,
+				tsauxc & ~IXGBE_TSAUXC_DISABLE_SYSTIME);
+		break;
+	case ixgbe_mac_X540:
+	case ixgbe_mac_82599EB:
+		/* Reset SYSTIME registers to 0 */
+		IXGBE_WRITE_REG(hw, IXGBE_SYSTIML, 0);
+		IXGBE_WRITE_REG(hw, IXGBE_SYSTIMH, 0);
+		break;
+	default:
+		/* Other devices aren't supported */
+		return;
+	};
+
+	IXGBE_WRITE_FLUSH(hw);
+}
+
+/**
  * ixgbe_ptp_reset
  * @adapter: the ixgbe private board structure
  *
@@ -1315,6 +1348,8 @@
 
 	ixgbe_ptp_start_cyclecounter(adapter);
 
+	ixgbe_ptp_init_systime(adapter);
+
 	spin_lock_irqsave(&adapter->tmreg_lock, flags);
 	timecounter_init(&adapter->hw_tc, &adapter->hw_cc,
 			 ktime_to_ns(ktime_get_real()));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
@@ -28,6 +28,9 @@
 	struct vf_macvlans *mv_list;
 	int num_vf_macvlans, i;
 
+	/* Initialize list of VF macvlans */
+	INIT_LIST_HEAD(&adapter->vf_mvs.l);
+
 	num_vf_macvlans = hw->mac.num_rar_entries -
 			  (IXGBE_MAX_PF_MACVLANS + 1 + num_vfs);
 	if (!num_vf_macvlans)
@@ -36,8 +39,6 @@
 	mv_list = kcalloc(num_vf_macvlans, sizeof(struct vf_macvlans),
 			  GFP_KERNEL);
 	if (mv_list) {
-		/* Initialize list of VF macvlans */
-		INIT_LIST_HEAD(&adapter->vf_mvs.l);
 		for (i = 0; i < num_vf_macvlans; i++) {
 			mv_list[i].vf = -1;
 			mv_list[i].free = true;
@@ -96,6 +97,7 @@
 	for (i = 0; i < num_vfs; i++) {
 		/* enable spoof checking for all VFs */
 		adapter->vfinfo[i].spoofchk_enabled = true;
+		adapter->vfinfo[i].link_enable = true;
 
 		/* We support VF RSS querying only for 82599 and x540
 		 * devices at the moment. These devices share RSS
@@ -204,10 +206,13 @@
 int ixgbe_disable_sriov(struct ixgbe_adapter *adapter)
 {
 	unsigned int num_vfs = adapter->num_vfs, vf;
+	unsigned long flags;
 	int rss;
 
+	spin_lock_irqsave(&adapter->vfs_lock, flags);
 	/* set num VFs to 0 to prevent access to vfinfo */
 	adapter->num_vfs = 0;
+	spin_unlock_irqrestore(&adapter->vfs_lock, flags);
 
 	/* put the reference to all of the vf devices */
 	for (vf = 0; vf < num_vfs; ++vf) {
@@ -467,12 +472,16 @@
 	return err;
 }
 
-static s32 ixgbe_set_vf_lpe(struct ixgbe_adapter *adapter, u32 *msgbuf, u32 vf)
+static int ixgbe_set_vf_lpe(struct ixgbe_adapter *adapter, u32 max_frame, u32 vf)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
-	int max_frame = msgbuf[1];
 	u32 max_frs;
 
+	if (max_frame < ETH_MIN_MTU || max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE) {
+		e_err(drv, "VF max_frame %d out of range\n", max_frame);
+		return -EINVAL;
+	}
+
 	/*
 	 * For 82599EB we have to keep all PFs and VFs operating with
 	 * the same max_frame value in order to avoid sending an oversize
@@ -533,12 +542,6 @@
 		}
 	}
 
-	/* MTU < 68 is an error and causes problems on some kernels */
-	if (max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE) {
-		e_err(drv, "VF max_frame %d out of range\n", max_frame);
-		return -EINVAL;
-	}
-
 	/* pull current max frame size from hardware */
 	max_frs = IXGBE_READ_REG(hw, IXGBE_MAXFRS);
 	max_frs &= IXGBE_MHADD_MFS_MASK;
@@ -822,6 +825,57 @@
 	}
 }
 
+/**
+ * ixgbe_set_vf_rx_tx - Set VF rx tx
+ * @adapter: Pointer to adapter struct
+ * @vf: VF identifier
+ *
+ * Set or reset correct transmit and receive for vf
+ **/
+static void ixgbe_set_vf_rx_tx(struct ixgbe_adapter *adapter, int vf)
+{
+	u32 reg_cur_tx, reg_cur_rx, reg_req_tx, reg_req_rx;
+	struct ixgbe_hw *hw = &adapter->hw;
+	u32 reg_offset, vf_shift;
+
+	vf_shift = vf % 32;
+	reg_offset = vf / 32;
+
+	reg_cur_tx = IXGBE_READ_REG(hw, IXGBE_VFTE(reg_offset));
+	reg_cur_rx = IXGBE_READ_REG(hw, IXGBE_VFRE(reg_offset));
+
+	if (adapter->vfinfo[vf].link_enable) {
+		reg_req_tx = reg_cur_tx | 1 << vf_shift;
+		reg_req_rx = reg_cur_rx | 1 << vf_shift;
+	} else {
+		reg_req_tx = reg_cur_tx & ~(1 << vf_shift);
+		reg_req_rx = reg_cur_rx & ~(1 << vf_shift);
+	}
+
+	/* The 82599 cannot support a mix of jumbo and non-jumbo PF/VFs.
+	 * For more info take a look at ixgbe_set_vf_lpe
+	 */
+	if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+		struct net_device *dev = adapter->netdev;
+		int pf_max_frame = dev->mtu + ETH_HLEN;
+
+#if IS_ENABLED(CONFIG_FCOE)
+		if (dev->features & NETIF_F_FCOE_MTU)
+			pf_max_frame = max_t(int, pf_max_frame,
+					     IXGBE_FCOE_JUMBO_FRAME_SIZE);
+#endif /* CONFIG_FCOE */
+
+		if (pf_max_frame > ETH_FRAME_LEN)
+			reg_req_rx = reg_cur_rx & ~(1 << vf_shift);
+	}
+
+	/* Enable/Disable particular VF */
+	if (reg_cur_tx != reg_req_tx)
+		IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset), reg_req_tx);
+	if (reg_cur_rx != reg_req_rx)
+		IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset), reg_req_rx);
+}
+
 static int ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf)
 {
 	struct ixgbe_ring_feature *vmdq = &adapter->ring_feature[RING_F_VMDQ];
@@ -847,11 +901,6 @@
 	vf_shift = vf % 32;
 	reg_offset = vf / 32;
 
-	/* enable transmit for vf */
-	reg = IXGBE_READ_REG(hw, IXGBE_VFTE(reg_offset));
-	reg |= BIT(vf_shift);
-	IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset), reg);
-
 	/* force drop enable for all VF Rx queues */
 	reg = IXGBE_QDE_ENABLE;
 	if (adapter->vfinfo[vf].pf_vlan)
@@ -859,27 +908,7 @@
 
 	ixgbe_write_qde(adapter, vf, reg);
 
-	/* enable receive for vf */
-	reg = IXGBE_READ_REG(hw, IXGBE_VFRE(reg_offset));
-	reg |= BIT(vf_shift);
-	/*
-	 * The 82599 cannot support a mix of jumbo and non-jumbo PF/VFs.
-	 * For more info take a look at ixgbe_set_vf_lpe
-	 */
-	if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
-		struct net_device *dev = adapter->netdev;
-		int pf_max_frame = dev->mtu + ETH_HLEN;
-
-#ifdef CONFIG_FCOE
-		if (dev->features & NETIF_F_FCOE_MTU)
-			pf_max_frame = max_t(int, pf_max_frame,
-					     IXGBE_FCOE_JUMBO_FRAME_SIZE);
-
-#endif /* CONFIG_FCOE */
-		if (pf_max_frame > ETH_FRAME_LEN)
-			reg &= ~BIT(vf_shift);
-	}
-	IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset), reg);
+	ixgbe_set_vf_rx_tx(adapter, vf);
 
 	/* enable VF mailbox for further messages */
 	adapter->vfinfo[vf].clear_to_send = true;
@@ -1159,9 +1188,9 @@
 
 	switch (xcast_mode) {
 	case IXGBEVF_XCAST_MODE_NONE:
-		disable = IXGBE_VMOLR_BAM | IXGBE_VMOLR_ROMPE |
+		disable = IXGBE_VMOLR_ROMPE |
 			  IXGBE_VMOLR_MPE | IXGBE_VMOLR_UPE | IXGBE_VMOLR_VPE;
-		enable = 0;
+		enable = IXGBE_VMOLR_BAM;
 		break;
 	case IXGBEVF_XCAST_MODE_MULTI:
 		disable = IXGBE_VMOLR_MPE | IXGBE_VMOLR_UPE | IXGBE_VMOLR_VPE;
@@ -1183,9 +1212,9 @@
 			return -EPERM;
 		}
 
-		disable = 0;
+		disable = IXGBE_VMOLR_VPE;
 		enable = IXGBE_VMOLR_BAM | IXGBE_VMOLR_ROMPE |
-			 IXGBE_VMOLR_MPE | IXGBE_VMOLR_UPE | IXGBE_VMOLR_VPE;
+			 IXGBE_VMOLR_MPE | IXGBE_VMOLR_UPE;
 		break;
 	default:
 		return -EOPNOTSUPP;
@@ -1204,6 +1233,26 @@
 	return 0;
 }
 
+static int ixgbe_get_vf_link_state(struct ixgbe_adapter *adapter,
+				   u32 *msgbuf, u32 vf)
+{
+	u32 *link_state = &msgbuf[1];
+
+	/* verify the PF is supporting the correct API */
+	switch (adapter->vfinfo[vf].vf_api) {
+	case ixgbe_mbox_api_12:
+	case ixgbe_mbox_api_13:
+	case ixgbe_mbox_api_14:
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	*link_state = adapter->vfinfo[vf].link_enable;
+
+	return 0;
+}
+
 static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
 {
 	u32 mbx_size = IXGBE_VFMAILBOX_SIZE;
@@ -1249,7 +1298,7 @@
 		retval = ixgbe_set_vf_vlan_msg(adapter, msgbuf, vf);
 		break;
 	case IXGBE_VF_SET_LPE:
-		retval = ixgbe_set_vf_lpe(adapter, msgbuf, vf);
+		retval = ixgbe_set_vf_lpe(adapter, msgbuf[1], vf);
 		break;
 	case IXGBE_VF_SET_MACVLAN:
 		retval = ixgbe_set_vf_macvlan_msg(adapter, msgbuf, vf);
@@ -1269,6 +1318,9 @@
 	case IXGBE_VF_UPDATE_XCAST_MODE:
 		retval = ixgbe_update_vf_xcast_mode(adapter, msgbuf, vf);
 		break;
+	case IXGBE_VF_GET_LINK_STATE:
+		retval = ixgbe_get_vf_link_state(adapter, msgbuf, vf);
+		break;
 	case IXGBE_VF_IPSEC_ADD:
 		retval = ixgbe_ipsec_vf_add_sa(adapter, msgbuf, vf);
 		break;
@@ -1277,7 +1329,7 @@
 		break;
 	default:
 		e_err(drv, "Unhandled Msg %8.8x\n", msgbuf[0]);
-		retval = IXGBE_ERR_MBX;
+		retval = -EIO;
 		break;
 	}
 
@@ -1307,8 +1359,10 @@
 void ixgbe_msg_task(struct ixgbe_adapter *adapter)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
+	unsigned long flags;
 	u32 vf;
 
+	spin_lock_irqsave(&adapter->vfs_lock, flags);
 	for (vf = 0; vf < adapter->num_vfs; vf++) {
 		/* process any reset requests */
 		if (!ixgbe_check_for_rst(hw, vf))
@@ -1322,18 +1376,7 @@
 		if (!ixgbe_check_for_ack(hw, vf))
 			ixgbe_rcv_ack_from_vf(adapter, vf);
 	}
-}
-
-void ixgbe_disable_tx_rx(struct ixgbe_adapter *adapter)
-{
-	struct ixgbe_hw *hw = &adapter->hw;
-
-	/* disable transmit and receive for all vfs */
-	IXGBE_WRITE_REG(hw, IXGBE_VFTE(0), 0);
-	IXGBE_WRITE_REG(hw, IXGBE_VFTE(1), 0);
-
-	IXGBE_WRITE_REG(hw, IXGBE_VFRE(0), 0);
-	IXGBE_WRITE_REG(hw, IXGBE_VFRE(1), 0);
+	spin_unlock_irqrestore(&adapter->vfs_lock, flags);
 }
 
 static inline void ixgbe_ping_vf(struct ixgbe_adapter *adapter, int vf)
@@ -1361,6 +1404,21 @@
 	}
 }
 
+/**
+ * ixgbe_set_all_vfs - update vfs queues
+ * @adapter: Pointer to adapter struct
+ *
+ * Update setting transmit and receive queues for all vfs
+ **/
+void ixgbe_set_all_vfs(struct ixgbe_adapter *adapter)
+{
+	int i;
+
+	for (i = 0 ; i < adapter->num_vfs; i++)
+		ixgbe_set_vf_link_state(adapter, i,
+					adapter->vfinfo[i].link_state);
+}
+
 int ixgbe_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
@@ -1658,6 +1716,84 @@
 	return 0;
 }
 
+/**
+ * ixgbe_set_vf_link_state - Set link state
+ * @adapter: Pointer to adapter struct
+ * @vf: VF identifier
+ * @state: required link state
+ *
+ * Set a link force state on/off a single vf
+ **/
+void ixgbe_set_vf_link_state(struct ixgbe_adapter *adapter, int vf, int state)
+{
+	adapter->vfinfo[vf].link_state = state;
+
+	switch (state) {
+	case IFLA_VF_LINK_STATE_AUTO:
+		if (test_bit(__IXGBE_DOWN, &adapter->state))
+			adapter->vfinfo[vf].link_enable = false;
+		else
+			adapter->vfinfo[vf].link_enable = true;
+		break;
+	case IFLA_VF_LINK_STATE_ENABLE:
+		adapter->vfinfo[vf].link_enable = true;
+		break;
+	case IFLA_VF_LINK_STATE_DISABLE:
+		adapter->vfinfo[vf].link_enable = false;
+		break;
+	}
+
+	ixgbe_set_vf_rx_tx(adapter, vf);
+
+	/* restart the VF */
+	adapter->vfinfo[vf].clear_to_send = false;
+	ixgbe_ping_vf(adapter, vf);
+}
+
+/**
+ * ixgbe_ndo_set_vf_link_state - Set link state
+ * @netdev: network interface device structure
+ * @vf: VF identifier
+ * @state: required link state
+ *
+ * Set the link state of a specified VF, regardless of physical link state
+ **/
+int ixgbe_ndo_set_vf_link_state(struct net_device *netdev, int vf, int state)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	int ret = 0;
+
+	if (vf < 0 || vf >= adapter->num_vfs) {
+		dev_err(&adapter->pdev->dev,
+			"NDO set VF link - invalid VF identifier %d\n", vf);
+		return -EINVAL;
+	}
+
+	switch (state) {
+	case IFLA_VF_LINK_STATE_ENABLE:
+		dev_info(&adapter->pdev->dev,
+			 "NDO set VF %d link state %d - not supported\n",
+			vf, state);
+		break;
+	case IFLA_VF_LINK_STATE_DISABLE:
+		dev_info(&adapter->pdev->dev,
+			 "NDO set VF %d link state disable\n", vf);
+		ixgbe_set_vf_link_state(adapter, vf, state);
+		break;
+	case IFLA_VF_LINK_STATE_AUTO:
+		dev_info(&adapter->pdev->dev,
+			 "NDO set VF %d link state auto\n", vf);
+		ixgbe_set_vf_link_state(adapter, vf, state);
+		break;
+	default:
+		dev_err(&adapter->pdev->dev,
+			"NDO set VF %d - invalid link state %d\n", vf, state);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
 int ixgbe_ndo_set_vf_rss_query_en(struct net_device *netdev, int vf,
 				  bool setting)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.h
@@ -17,8 +17,8 @@
 #endif
 void ixgbe_msg_task(struct ixgbe_adapter *adapter);
 int ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask);
-void ixgbe_disable_tx_rx(struct ixgbe_adapter *adapter);
 void ixgbe_ping_all_vfs(struct ixgbe_adapter *adapter);
+void ixgbe_set_all_vfs(struct ixgbe_adapter *adapter);
 int ixgbe_ndo_set_vf_mac(struct net_device *netdev, int queue, u8 *mac);
 int ixgbe_ndo_set_vf_vlan(struct net_device *netdev, int queue, u16 vlan,
 			   u8 qos, __be16 vlan_proto);
@@ -31,7 +31,9 @@
 int ixgbe_ndo_set_vf_trust(struct net_device *netdev, int vf, bool setting);
 int ixgbe_ndo_get_vf_config(struct net_device *netdev,
 			    int vf, struct ifla_vf_info *ivi);
+int ixgbe_ndo_set_vf_link_state(struct net_device *netdev, int vf, int state);
 void ixgbe_check_vf_rate_limit(struct ixgbe_adapter *adapter);
+void ixgbe_set_vf_link_state(struct ixgbe_adapter *adapter, int vf, int state);
 int ixgbe_disable_sriov(struct ixgbe_adapter *adapter);
 #ifdef CONFIG_PCI_IOV
 void ixgbe_enable_sriov(struct ixgbe_adapter *adapter, unsigned int max_vfs);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
@@ -1247,7 +1247,7 @@
 #define IXGBE_PSRTYPE_RQPL_SHIFT    29
 
 /* CTRL Bit Masks */
-#define IXGBE_CTRL_GIO_DIS      0x00000004 /* Global IO Master Disable bit */
+#define IXGBE_CTRL_GIO_DIS      0x00000004 /* Global IO Primary Disable bit */
 #define IXGBE_CTRL_LNK_RST      0x00000008 /* Link Reset. Resets everything. */
 #define IXGBE_CTRL_RST          0x04000000 /* Reset (SW) */
 #define IXGBE_CTRL_RST_MASK     (IXGBE_CTRL_LNK_RST | IXGBE_CTRL_RST)
@@ -1810,7 +1810,7 @@
 /* STATUS Bit Masks */
 #define IXGBE_STATUS_LAN_ID         0x0000000C /* LAN ID */
 #define IXGBE_STATUS_LAN_ID_SHIFT   2          /* LAN ID Shift*/
-#define IXGBE_STATUS_GIO            0x00080000 /* GIO Master Enable Status */
+#define IXGBE_STATUS_GIO            0x00080000 /* GIO Primary Enable Status */
 
 #define IXGBE_STATUS_LAN_ID_0   0x00000000 /* LAN ID 0 */
 #define IXGBE_STATUS_LAN_ID_1   0x00000004 /* LAN ID 1 */
@@ -2192,8 +2192,8 @@
 #define IXGBE_PCIDEVCTRL2_4_8s		0xd
 #define IXGBE_PCIDEVCTRL2_17_34s	0xe
 
-/* Number of 100 microseconds we wait for PCI Express master disable */
-#define IXGBE_PCI_MASTER_DISABLE_TIMEOUT	800
+/* Number of 100 microseconds we wait for PCI Express primary disable */
+#define IXGBE_PCI_PRIMARY_DISABLE_TIMEOUT	800
 
 /* RAH */
 #define IXGBE_RAH_VIND_MASK     0x003C0000
@@ -3505,10 +3505,10 @@
 	s32 (*read_i2c_sff8472)(struct ixgbe_hw *, u8 , u8 *);
 	s32 (*read_i2c_eeprom)(struct ixgbe_hw *, u8 , u8 *);
 	s32 (*write_i2c_eeprom)(struct ixgbe_hw *, u8, u8);
-	s32 (*check_overtemp)(struct ixgbe_hw *);
+	bool (*check_overtemp)(struct ixgbe_hw *);
 	s32 (*set_phy_power)(struct ixgbe_hw *, bool on);
 	s32 (*enter_lplu)(struct ixgbe_hw *);
-	s32 (*handle_lasi)(struct ixgbe_hw *hw);
+	s32 (*handle_lasi)(struct ixgbe_hw *hw, bool *);
 	s32 (*read_i2c_byte_unlocked)(struct ixgbe_hw *, u8 offset, u8 addr,
 				      u8 *value);
 	s32 (*write_i2c_byte_unlocked)(struct ixgbe_hw *, u8 offset, u8 addr,
@@ -3661,45 +3661,6 @@
 	const u32			*mvals;
 };
 
-
-/* Error Codes */
-#define IXGBE_ERR_EEPROM                        -1
-#define IXGBE_ERR_EEPROM_CHECKSUM               -2
-#define IXGBE_ERR_PHY                           -3
-#define IXGBE_ERR_CONFIG                        -4
-#define IXGBE_ERR_PARAM                         -5
-#define IXGBE_ERR_MAC_TYPE                      -6
-#define IXGBE_ERR_UNKNOWN_PHY                   -7
-#define IXGBE_ERR_LINK_SETUP                    -8
-#define IXGBE_ERR_ADAPTER_STOPPED               -9
-#define IXGBE_ERR_INVALID_MAC_ADDR              -10
-#define IXGBE_ERR_DEVICE_NOT_SUPPORTED          -11
-#define IXGBE_ERR_MASTER_REQUESTS_PENDING       -12
-#define IXGBE_ERR_INVALID_LINK_SETTINGS         -13
-#define IXGBE_ERR_AUTONEG_NOT_COMPLETE          -14
-#define IXGBE_ERR_RESET_FAILED                  -15
-#define IXGBE_ERR_SWFW_SYNC                     -16
-#define IXGBE_ERR_PHY_ADDR_INVALID              -17
-#define IXGBE_ERR_I2C                           -18
-#define IXGBE_ERR_SFP_NOT_SUPPORTED             -19
-#define IXGBE_ERR_SFP_NOT_PRESENT               -20
-#define IXGBE_ERR_SFP_NO_INIT_SEQ_PRESENT       -21
-#define IXGBE_ERR_NO_SAN_ADDR_PTR               -22
-#define IXGBE_ERR_FDIR_REINIT_FAILED            -23
-#define IXGBE_ERR_EEPROM_VERSION                -24
-#define IXGBE_ERR_NO_SPACE                      -25
-#define IXGBE_ERR_OVERTEMP                      -26
-#define IXGBE_ERR_FC_NOT_NEGOTIATED             -27
-#define IXGBE_ERR_FC_NOT_SUPPORTED              -28
-#define IXGBE_ERR_SFP_SETUP_NOT_COMPLETE        -30
-#define IXGBE_ERR_PBA_SECTION                   -31
-#define IXGBE_ERR_INVALID_ARGUMENT              -32
-#define IXGBE_ERR_HOST_INTERFACE_COMMAND        -33
-#define IXGBE_ERR_FDIR_CMD_INCOMPLETE		-38
-#define IXGBE_ERR_FW_RESP_INVALID		-39
-#define IXGBE_ERR_TOKEN_RETRY			-40
-#define IXGBE_NOT_IMPLEMENTED                   0x7FFFFFFF
-
 #define IXGBE_FUSES0_GROUP(_i)		(0x11158 + ((_i) * 4))
 #define IXGBE_FUSES0_300MHZ		BIT(5)
 #define IXGBE_FUSES0_REV_MASK		(3u << 6)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
@@ -84,7 +84,7 @@
 	status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
 	if (status) {
 		hw_dbg(hw, "semaphore failed with %d", status);
-		return IXGBE_ERR_SWFW_SYNC;
+		return -EBUSY;
 	}
 
 	ctrl = IXGBE_CTRL_RST;
@@ -103,7 +103,7 @@
 	}
 
 	if (ctrl & IXGBE_CTRL_RST_MASK) {
-		status = IXGBE_ERR_RESET_FAILED;
+		status = -EIO;
 		hw_dbg(hw, "Reset polling failed to complete.\n");
 	}
 	msleep(100);
@@ -220,7 +220,7 @@
 	s32 status;
 
 	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM))
-		return IXGBE_ERR_SWFW_SYNC;
+		return -EBUSY;
 
 	status = ixgbe_read_eerd_generic(hw, offset, data);
 
@@ -243,7 +243,7 @@
 	s32 status;
 
 	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM))
-		return IXGBE_ERR_SWFW_SYNC;
+		return -EBUSY;
 
 	status = ixgbe_read_eerd_buffer_generic(hw, offset, words, data);
 
@@ -264,7 +264,7 @@
 	s32 status;
 
 	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM))
-		return IXGBE_ERR_SWFW_SYNC;
+		return -EBUSY;
 
 	status = ixgbe_write_eewr_generic(hw, offset, data);
 
@@ -287,7 +287,7 @@
 	s32 status;
 
 	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM))
-		return IXGBE_ERR_SWFW_SYNC;
+		return -EBUSY;
 
 	status = ixgbe_write_eewr_buffer_generic(hw, offset, words, data);
 
@@ -324,7 +324,7 @@
 	for (i = 0; i < checksum_last_word; i++) {
 		if (ixgbe_read_eerd_generic(hw, i, &word)) {
 			hw_dbg(hw, "EEPROM read failed\n");
-			return IXGBE_ERR_EEPROM;
+			return -EIO;
 		}
 		checksum += word;
 	}
@@ -349,8 +349,7 @@
 
 		if (ixgbe_read_eerd_generic(hw, pointer, &length)) {
 			hw_dbg(hw, "EEPROM read failed\n");
-			return IXGBE_ERR_EEPROM;
-			break;
+			return -EIO;
 		}
 
 		/* Skip pointer section if length is invalid. */
@@ -361,7 +360,7 @@
 		for (j = pointer + 1; j <= pointer + length; j++) {
 			if (ixgbe_read_eerd_generic(hw, j, &word)) {
 				hw_dbg(hw, "EEPROM read failed\n");
-				return IXGBE_ERR_EEPROM;
+				return -EIO;
 			}
 			checksum += word;
 		}
@@ -398,7 +397,7 @@
 	}
 
 	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM))
-		return IXGBE_ERR_SWFW_SYNC;
+		return -EBUSY;
 
 	status = hw->eeprom.ops.calc_checksum(hw);
 	if (status < 0)
@@ -419,7 +418,7 @@
 	 */
 	if (read_checksum != checksum) {
 		hw_dbg(hw, "Invalid EEPROM checksum");
-		status = IXGBE_ERR_EEPROM_CHECKSUM;
+		status = -EIO;
 	}
 
 	/* If the user cares, return the calculated checksum */
@@ -456,7 +455,7 @@
 	}
 
 	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM))
-		return  IXGBE_ERR_SWFW_SYNC;
+		return  -EBUSY;
 
 	status = hw->eeprom.ops.calc_checksum(hw);
 	if (status < 0)
@@ -491,7 +490,7 @@
 	s32 status;
 
 	status = ixgbe_poll_flash_update_done_X540(hw);
-	if (status == IXGBE_ERR_EEPROM) {
+	if (status == -EIO) {
 		hw_dbg(hw, "Flash update time out\n");
 		return status;
 	}
@@ -541,7 +540,7 @@
 			return 0;
 		udelay(5);
 	}
-	return IXGBE_ERR_EEPROM;
+	return -EIO;
 }
 
 /**
@@ -576,7 +575,7 @@
 		 * SW_FW_SYNC bits (not just NVM)
 		 */
 		if (ixgbe_get_swfw_sync_semaphore(hw))
-			return IXGBE_ERR_SWFW_SYNC;
+			return -EBUSY;
 
 		swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC(hw));
 		if (!(swfw_sync & (fwmask | swmask | hwmask))) {
@@ -600,7 +599,7 @@
 	 * bits in the SW_FW_SYNC register.
 	 */
 	if (ixgbe_get_swfw_sync_semaphore(hw))
-		return IXGBE_ERR_SWFW_SYNC;
+		return -EBUSY;
 	swfw_sync = IXGBE_READ_REG(hw, IXGBE_SWFW_SYNC(hw));
 	if (swfw_sync & (fwmask | hwmask)) {
 		swfw_sync |= swmask;
@@ -623,11 +622,11 @@
 			rmask |= IXGBE_GSSR_I2C_MASK;
 		ixgbe_release_swfw_sync_X540(hw, rmask);
 		ixgbe_release_swfw_sync_semaphore(hw);
-		return IXGBE_ERR_SWFW_SYNC;
+		return -EBUSY;
 	}
 	ixgbe_release_swfw_sync_semaphore(hw);
 
-	return IXGBE_ERR_SWFW_SYNC;
+	return -EBUSY;
 }
 
 /**
@@ -681,7 +680,7 @@
 	if (i == timeout) {
 		hw_dbg(hw,
 		       "Software semaphore SMBI between device drivers not granted.\n");
-		return IXGBE_ERR_EEPROM;
+		return -EIO;
 	}
 
 	/* Now get the semaphore between SW/FW through the REGSMP bit */
@@ -698,7 +697,7 @@
 	 */
 	hw_dbg(hw, "REGSMP Software NVM semaphore not granted\n");
 	ixgbe_release_swfw_sync_semaphore(hw);
-	return IXGBE_ERR_EEPROM;
+	return -EIO;
 }
 
 /**
@@ -769,7 +768,7 @@
 	bool link_up;
 
 	if (index > 3)
-		return IXGBE_ERR_PARAM;
+		return -EINVAL;
 
 	/* Link should be up in order for the blink bit in the LED control
 	 * register to work. Force link and speed in the MAC if link is down.
@@ -805,7 +804,7 @@
 	u32 ledctl_reg;
 
 	if (index > 3)
-		return IXGBE_ERR_PARAM;
+		return -EINVAL;
 
 	/* Restore the LED to its default value. */
 	ledctl_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c
@@ -206,13 +206,13 @@
 	}
 	if (retry == IXGBE_CS4227_RETRIES) {
 		hw_err(hw, "CS4227 reset did not complete\n");
-		return IXGBE_ERR_PHY;
+		return -EIO;
 	}
 
 	status = ixgbe_read_cs4227(hw, IXGBE_CS4227_EEPROM_STATUS, &value);
 	if (status || !(value & IXGBE_CS4227_EEPROM_LOAD_OK)) {
 		hw_err(hw, "CS4227 EEPROM did not load successfully\n");
-		return IXGBE_ERR_PHY;
+		return -EIO;
 	}
 
 	return 0;
@@ -350,13 +350,13 @@
 static s32 ixgbe_read_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr,
 				     u32 device_type, u16 *phy_data)
 {
-	return IXGBE_NOT_IMPLEMENTED;
+	return -EOPNOTSUPP;
 }
 
 static s32 ixgbe_write_phy_reg_x550em(struct ixgbe_hw *hw, u32 reg_addr,
 				      u32 device_type, u16 phy_data)
 {
-	return IXGBE_NOT_IMPLEMENTED;
+	return -EOPNOTSUPP;
 }
 
 /**
@@ -463,7 +463,7 @@
 		--retries;
 	} while (retries > 0);
 
-	return IXGBE_ERR_HOST_INTERFACE_COMMAND;
+	return -EIO;
 }
 
 static const struct {
@@ -511,7 +511,7 @@
 	hw->phy.id |= phy_id_lo & IXGBE_PHY_REVISION_MASK;
 	hw->phy.revision = phy_id_lo & ~IXGBE_PHY_REVISION_MASK;
 	if (!hw->phy.id || hw->phy.id == IXGBE_PHY_REVISION_MASK)
-		return IXGBE_ERR_PHY_ADDR_INVALID;
+		return -EFAULT;
 
 	hw->phy.autoneg_advertised = hw->phy.speeds_supported;
 	hw->phy.eee_speeds_supported = IXGBE_LINK_SPEED_100_FULL |
@@ -568,7 +568,7 @@
 
 	if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
 		hw_err(hw, "rx_pause not valid in strict IEEE mode\n");
-		return IXGBE_ERR_INVALID_LINK_SETTINGS;
+		return -EINVAL;
 	}
 
 	switch (hw->fc.requested_mode) {
@@ -600,8 +600,10 @@
 	rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_SETUP_LINK, &setup);
 	if (rc)
 		return rc;
+
 	if (setup[0] == FW_PHY_ACT_SETUP_LINK_RSP_DOWN)
-		return IXGBE_ERR_OVERTEMP;
+		return -EIO;
+
 	return 0;
 }
 
@@ -675,7 +677,7 @@
 		*ctrl = command;
 	if (i == IXGBE_MDIO_COMMAND_TIMEOUT) {
 		hw_dbg(hw, "IOSF wait timed out\n");
-		return IXGBE_ERR_PHY;
+		return -EIO;
 	}
 
 	return 0;
@@ -715,7 +717,8 @@
 		error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >>
 			 IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT;
 		hw_dbg(hw, "Failed to read, error %x\n", error);
-		return IXGBE_ERR_PHY;
+		ret = -EIO;
+		goto out;
 	}
 
 	if (!ret)
@@ -750,9 +753,9 @@
 	if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK)
 		return 0;
 	if (token_cmd.hdr.cmd_or_resp.ret_status != FW_PHY_TOKEN_RETRY)
-		return IXGBE_ERR_FW_RESP_INVALID;
+		return -EIO;
 
-	return IXGBE_ERR_TOKEN_RETRY;
+	return -EAGAIN;
 }
 
 /**
@@ -778,7 +781,7 @@
 		return status;
 	if (token_cmd.hdr.cmd_or_resp.ret_status == FW_PHY_TOKEN_OK)
 		return 0;
-	return IXGBE_ERR_FW_RESP_INVALID;
+	return -EIO;
 }
 
 /**
@@ -942,7 +945,7 @@
 		local_buffer = buf;
 	} else {
 		if (buffer_size < ptr)
-			return  IXGBE_ERR_PARAM;
+			return  -EINVAL;
 		local_buffer = &buffer[ptr];
 	}
 
@@ -960,7 +963,7 @@
 	}
 
 	if (buffer && ((u32)start + (u32)length > buffer_size))
-		return IXGBE_ERR_PARAM;
+		return -EINVAL;
 
 	for (i = start; length; i++, length--) {
 		if (i == bufsz && !buffer) {
@@ -1012,7 +1015,7 @@
 		local_buffer = eeprom_ptrs;
 	} else {
 		if (buffer_size < IXGBE_EEPROM_LAST_WORD)
-			return IXGBE_ERR_PARAM;
+			return -EINVAL;
 		local_buffer = buffer;
 	}
 
@@ -1148,7 +1151,7 @@
 	 * calculated checksum
 	 */
 	if (read_checksum != checksum) {
-		status = IXGBE_ERR_EEPROM_CHECKSUM;
+		status = -EIO;
 		hw_dbg(hw, "Invalid EEPROM checksum");
 	}
 
@@ -1203,7 +1206,7 @@
 		hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
 	} else {
 		hw_dbg(hw, "write ee hostif failed to get semaphore");
-		status = IXGBE_ERR_SWFW_SYNC;
+		status = -EBUSY;
 	}
 
 	return status;
@@ -1415,7 +1418,7 @@
 		error = (command & IXGBE_SB_IOSF_CTRL_CMPL_ERR_MASK) >>
 			 IXGBE_SB_IOSF_CTRL_CMPL_ERR_SHIFT;
 		hw_dbg(hw, "Failed to write, error %x\n", error);
-		return IXGBE_ERR_PHY;
+		return -EIO;
 	}
 
 out:
@@ -1558,7 +1561,7 @@
 
 	/* iXFI is only supported with X552 */
 	if (mac->type != ixgbe_mac_X550EM_x)
-		return IXGBE_ERR_LINK_SETUP;
+		return -EIO;
 
 	/* Disable AN and force speed to 10G Serial. */
 	status = ixgbe_read_iosf_sb_reg_x550(hw,
@@ -1580,7 +1583,7 @@
 		break;
 	default:
 		/* Other link speeds are not supported by internal KR PHY. */
-		return IXGBE_ERR_LINK_SETUP;
+		return -EINVAL;
 	}
 
 	status = ixgbe_write_iosf_sb_reg_x550(hw,
@@ -1611,7 +1614,7 @@
 {
 	switch (hw->phy.sfp_type) {
 	case ixgbe_sfp_type_not_present:
-		return IXGBE_ERR_SFP_NOT_PRESENT;
+		return -ENOENT;
 	case ixgbe_sfp_type_da_cu_core0:
 	case ixgbe_sfp_type_da_cu_core1:
 		*linear = true;
@@ -1630,7 +1633,7 @@
 	case ixgbe_sfp_type_1g_cu_core0:
 	case ixgbe_sfp_type_1g_cu_core1:
 	default:
-		return IXGBE_ERR_SFP_NOT_SUPPORTED;
+		return -EOPNOTSUPP;
 	}
 
 	return 0;
@@ -1660,7 +1663,7 @@
 	 * there is no reason to configure CS4227 and SFP not present error is
 	 * not accepted in the setup MAC link flow.
 	 */
-	if (status == IXGBE_ERR_SFP_NOT_PRESENT)
+	if (status == -ENOENT)
 		return 0;
 
 	if (status)
@@ -1718,7 +1721,7 @@
 		break;
 	default:
 		/* Other link speeds are not supported by internal PHY. */
-		return IXGBE_ERR_LINK_SETUP;
+		return -EINVAL;
 	}
 
 	status = mac->ops.write_iosf_sb_reg(hw,
@@ -1753,7 +1756,7 @@
 	/* If no SFP module present, then return success. Return success since
 	 * SFP not present error is not excepted in the setup MAC link flow.
 	 */
-	if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT)
+	if (ret_val == -ENOENT)
 		return 0;
 
 	if (ret_val)
@@ -1803,7 +1806,7 @@
 	/* If no SFP module present, then return success. Return success since
 	 * SFP not present error is not excepted in the setup MAC link flow.
 	 */
-	if (ret_val == IXGBE_ERR_SFP_NOT_PRESENT)
+	if (ret_val == -ENOENT)
 		return 0;
 
 	if (ret_val)
@@ -1813,7 +1816,7 @@
 	ixgbe_setup_kr_speed_x550em(hw, speed);
 
 	if (hw->phy.mdio.prtad == MDIO_PRTAD_NONE)
-		return IXGBE_ERR_PHY_ADDR_INVALID;
+		return -EFAULT;
 
 	/* Get external PHY SKU id */
 	ret_val = hw->phy.ops.read_reg(hw, IXGBE_CS4227_EFUSE_PDF_SKU,
@@ -1912,7 +1915,7 @@
 	u16 i, autoneg_status;
 
 	if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper)
-		return IXGBE_ERR_CONFIG;
+		return -EIO;
 
 	status = ixgbe_check_mac_link_generic(hw, speed, link_up,
 					      link_up_wait_to_complete);
@@ -2095,9 +2098,9 @@
  */
 static void ixgbe_fc_autoneg_sgmii_x550em_a(struct ixgbe_hw *hw)
 {
-	s32 status = IXGBE_ERR_FC_NOT_NEGOTIATED;
 	u32 info[FW_PHY_ACT_DATA_COUNT] = { 0 };
 	ixgbe_link_speed speed;
+	s32 status = -EIO;
 	bool link_up;
 
 	/* AN should have completed when the cable was plugged in.
@@ -2115,7 +2118,7 @@
 	/* Check if auto-negotiation has completed */
 	status = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_LINK_INFO, &info);
 	if (status || !(info[0] & FW_PHY_ACT_GET_LINK_INFO_AN_COMPLETE)) {
-		status = IXGBE_ERR_FC_NOT_NEGOTIATED;
+		status = -EIO;
 		goto out;
 	}
 
@@ -2319,18 +2322,18 @@
  * @hw: pointer to hardware structure
  * @lsc: pointer to boolean flag which indicates whether external Base T
  *	 PHY interrupt is lsc
+ * @is_overtemp: indicate whether an overtemp event encountered
  *
  * Determime if external Base T PHY interrupt cause is high temperature
  * failure alarm or link status change.
- *
- * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature
- * failure alarm, else return PHY access status.
  **/
-static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc)
+static s32 ixgbe_get_lasi_ext_t_x550em(struct ixgbe_hw *hw, bool *lsc,
+				       bool *is_overtemp)
 {
 	u32 status;
 	u16 reg;
 
+	*is_overtemp = false;
 	*lsc = false;
 
 	/* Vendor alarm triggered */
@@ -2362,7 +2365,8 @@
 	if (reg & IXGBE_MDIO_GLOBAL_ALM_1_HI_TMP_FAIL) {
 		/* power down the PHY in case the PHY FW didn't already */
 		ixgbe_set_copper_phy_power(hw, false);
-		return IXGBE_ERR_OVERTEMP;
+		*is_overtemp = true;
+		return -EIO;
 	}
 	if (reg & IXGBE_MDIO_GLOBAL_ALM_1_DEV_FAULT) {
 		/*  device fault alarm triggered */
@@ -2376,7 +2380,8 @@
 		if (reg == IXGBE_MDIO_GLOBAL_FAULT_MSG_HI_TMP) {
 			/* power down the PHY in case the PHY FW didn't */
 			ixgbe_set_copper_phy_power(hw, false);
-			return IXGBE_ERR_OVERTEMP;
+			*is_overtemp = true;
+			return -EIO;
 		}
 	}
 
@@ -2412,12 +2417,12 @@
  **/
 static s32 ixgbe_enable_lasi_ext_t_x550em(struct ixgbe_hw *hw)
 {
+	bool lsc, overtemp;
 	u32 status;
 	u16 reg;
-	bool lsc;
 
 	/* Clear interrupt flags */
-	status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc);
+	status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc, &overtemp);
 
 	/* Enable link status change alarm */
 
@@ -2496,21 +2501,20 @@
 /**
  * ixgbe_handle_lasi_ext_t_x550em - Handle external Base T PHY interrupt
  * @hw: pointer to hardware structure
+ * @is_overtemp: indicate whether an overtemp event encountered
  *
  * Handle external Base T PHY interrupt. If high temperature
  * failure alarm then return error, else if link status change
  * then setup internal/external PHY link
- *
- * Return IXGBE_ERR_OVERTEMP if interrupt is high temperature
- * failure alarm, else return PHY access status.
  **/
-static s32 ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw)
+static s32 ixgbe_handle_lasi_ext_t_x550em(struct ixgbe_hw *hw,
+					  bool *is_overtemp)
 {
 	struct ixgbe_phy_info *phy = &hw->phy;
 	bool lsc;
 	u32 status;
 
-	status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc);
+	status = ixgbe_get_lasi_ext_t_x550em(hw, &lsc, is_overtemp);
 	if (status)
 		return status;
 
@@ -2642,7 +2646,7 @@
 	u16 speed;
 
 	if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_copper)
-		return IXGBE_ERR_CONFIG;
+		return -EIO;
 
 	if (!(hw->mac.type == ixgbe_mac_X550EM_x &&
 	      !(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_INT_PHY_MODE))) {
@@ -2685,7 +2689,7 @@
 		break;
 	default:
 		/* Internal PHY does not support anything else */
-		return IXGBE_ERR_INVALID_LINK_SETTINGS;
+		return -EINVAL;
 	}
 
 	return ixgbe_setup_ixfi_x550em(hw, &force_speed);
@@ -2717,7 +2721,7 @@
 	u16 phy_data;
 
 	if (led_idx >= IXGBE_X557_MAX_LED_INDEX)
-		return IXGBE_ERR_PARAM;
+		return -EINVAL;
 
 	/* To turn on the LED, set mode to ON. */
 	hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
@@ -2739,7 +2743,7 @@
 	u16 phy_data;
 
 	if (led_idx >= IXGBE_X557_MAX_LED_INDEX)
-		return IXGBE_ERR_PARAM;
+		return -EINVAL;
 
 	/* To turn on the LED, set mode to ON. */
 	hw->phy.ops.read_reg(hw, IXGBE_X557_LED_PROVISIONING + led_idx,
@@ -2763,8 +2767,9 @@
  *
  *  Sends driver version number to firmware through the manageability
  *  block.  On success return 0
- *  else returns IXGBE_ERR_SWFW_SYNC when encountering an error acquiring
- *  semaphore or IXGBE_ERR_HOST_INTERFACE_COMMAND when command fails.
+ *  else returns -EBUSY when encountering an error acquiring
+ *  semaphore, -EIO when command fails or -ENIVAL when incorrect
+ *  params passed.
  **/
 static s32 ixgbe_set_fw_drv_ver_x550(struct ixgbe_hw *hw, u8 maj, u8 min,
 				     u8 build, u8 sub, u16 len,
@@ -2775,7 +2780,7 @@
 	int i;
 
 	if (!len || !driver_ver || (len > sizeof(fw_cmd.driver_string)))
-		return IXGBE_ERR_INVALID_ARGUMENT;
+		return -EINVAL;
 
 	fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO;
 	fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN + len;
@@ -2800,7 +2805,7 @@
 
 		if (fw_cmd.hdr.cmd_or_resp.ret_status !=
 		    FW_CEM_RESP_STATUS_SUCCESS)
-			return IXGBE_ERR_HOST_INTERFACE_COMMAND;
+			return -EIO;
 		return 0;
 	}
 
@@ -2857,7 +2862,7 @@
 	/* Validate the requested mode */
 	if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
 		hw_err(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
-		return IXGBE_ERR_INVALID_LINK_SETTINGS;
+		return -EINVAL;
 	}
 
 	/* 10gig parts do not have a word in the EEPROM to determine the
@@ -2892,7 +2897,7 @@
 		break;
 	default:
 		hw_err(hw, "Flow control param set incorrectly\n");
-		return IXGBE_ERR_CONFIG;
+		return -EIO;
 	}
 
 	switch (hw->device_id) {
@@ -2936,8 +2941,8 @@
 static void ixgbe_fc_autoneg_backplane_x550em_a(struct ixgbe_hw *hw)
 {
 	u32 link_s1, lp_an_page_low, an_cntl_1;
-	s32 status = IXGBE_ERR_FC_NOT_NEGOTIATED;
 	ixgbe_link_speed speed;
+	s32 status = -EIO;
 	bool link_up;
 
 	/* AN should have completed when the cable was plugged in.
@@ -2963,7 +2968,7 @@
 
 	if (status || (link_s1 & IXGBE_KRM_LINK_S1_MAC_AN_COMPLETE) == 0) {
 		hw_dbg(hw, "Auto-Negotiation did not complete\n");
-		status = IXGBE_ERR_FC_NOT_NEGOTIATED;
+		status = -EIO;
 		goto out;
 	}
 
@@ -3137,21 +3142,23 @@
 /**
  * ixgbe_check_overtemp_fw - Check firmware-controlled PHYs for overtemp
  * @hw: pointer to hardware structure
+ *
+ * Return true when an overtemp event detected, otherwise false.
  */
-static s32 ixgbe_check_overtemp_fw(struct ixgbe_hw *hw)
+static bool ixgbe_check_overtemp_fw(struct ixgbe_hw *hw)
 {
 	u32 store[FW_PHY_ACT_DATA_COUNT] = { 0 };
 	s32 rc;
 
 	rc = ixgbe_fw_phy_activity(hw, FW_PHY_ACT_GET_LINK_INFO, &store);
 	if (rc)
-		return rc;
+		return false;
 
 	if (store[0] & FW_PHY_ACT_GET_LINK_INFO_TEMP) {
 		ixgbe_shutdown_fw_phy(hw);
-		return IXGBE_ERR_OVERTEMP;
+		return true;
 	}
-	return 0;
+	return false;
 }
 
 /**
@@ -3201,8 +3208,7 @@
 
 	/* Identify the PHY or SFP module */
 	ret_val = phy->ops.identify(hw);
-	if (ret_val == IXGBE_ERR_SFP_NOT_SUPPORTED ||
-	    ret_val == IXGBE_ERR_PHY_ADDR_INVALID)
+	if (ret_val == -EOPNOTSUPP || ret_val == -EFAULT)
 		return ret_val;
 
 	/* Setup function pointers based on detected hardware */
@@ -3405,10 +3411,12 @@
 	/* flush pending Tx transactions */
 	ixgbe_clear_tx_pending(hw);
 
+	/* set MDIO speed before talking to the PHY in case it's the 1st time */
+	ixgbe_set_mdio_speed(hw);
+
 	/* PHY ops must be identified and initialized prior to reset */
 	status = hw->phy.ops.init(hw);
-	if (status == IXGBE_ERR_SFP_NOT_SUPPORTED ||
-	    status == IXGBE_ERR_PHY_ADDR_INVALID)
+	if (status == -EOPNOTSUPP || status == -EFAULT)
 		return status;
 
 	/* start the external PHY */
@@ -3424,7 +3432,7 @@
 		hw->phy.sfp_setup_needed = false;
 	}
 
-	if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
+	if (status == -EOPNOTSUPP)
 		return status;
 
 	/* Reset PHY */
@@ -3448,7 +3456,7 @@
 	status = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
 	if (status) {
 		hw_dbg(hw, "semaphore failed with %d", status);
-		return IXGBE_ERR_SWFW_SYNC;
+		return -EBUSY;
 	}
 
 	ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL);
@@ -3466,7 +3474,7 @@
 	}
 
 	if (ctrl & IXGBE_CTRL_RST_MASK) {
-		status = IXGBE_ERR_RESET_FAILED;
+		status = -EIO;
 		hw_dbg(hw, "Reset polling failed to complete.\n");
 	}
 
@@ -3562,7 +3570,7 @@
 	/* Validate the requested mode */
 	if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
 		hw_err(hw, "ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
-		return IXGBE_ERR_INVALID_LINK_SETTINGS;
+		return -EINVAL;
 	}
 
 	if (hw->fc.requested_mode == ixgbe_fc_default)
@@ -3619,7 +3627,7 @@
 		break;
 	default:
 		hw_err(hw, "Flow control param set incorrectly\n");
-		return IXGBE_ERR_CONFIG;
+		return -EIO;
 	}
 
 	status = hw->mac.ops.write_iosf_sb_reg(hw,
@@ -3715,7 +3723,7 @@
 			return 0;
 		if (hmask)
 			ixgbe_release_swfw_sync_X540(hw, hmask);
-		if (status != IXGBE_ERR_TOKEN_RETRY)
+		if (status != -EAGAIN)
 			return status;
 		msleep(FW_PHY_TOKEN_DELAY);
 	}
@@ -3759,7 +3767,7 @@
 	s32 status;
 
 	if (hw->mac.ops.acquire_swfw_sync(hw, mask))
-		return IXGBE_ERR_SWFW_SYNC;
+		return -EBUSY;
 
 	status = hw->phy.ops.read_reg_mdi(hw, reg_addr, device_type, phy_data);
 
@@ -3785,7 +3793,7 @@
 	s32 status;
 
 	if (hw->mac.ops.acquire_swfw_sync(hw, mask))
-		return IXGBE_ERR_SWFW_SYNC;
+		return -EBUSY;
 
 	status = ixgbe_write_phy_reg_mdi(hw, reg_addr, device_type, phy_data);
 	hw->mac.ops.release_swfw_sync(hw, mask);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c
@@ -583,12 +583,14 @@
 	u32 cmd_type;
 
 	while (budget-- > 0) {
-		if (unlikely(!ixgbe_desc_unused(xdp_ring)) ||
-		    !netif_carrier_ok(xdp_ring->netdev)) {
+		if (unlikely(!ixgbe_desc_unused(xdp_ring))) {
 			work_done = false;
 			break;
 		}
 
+		if (!netif_carrier_ok(xdp_ring->netdev))
+			break;
+
 		if (!xsk_umem_consume_tx(xdp_ring->xsk_umem, &desc))
 			break;
 
@@ -709,10 +711,14 @@
 	if (qid >= adapter->num_xdp_queues)
 		return -ENXIO;
 
-	if (!adapter->xdp_ring[qid]->xsk_umem)
+	ring = adapter->xdp_ring[qid];
+
+	if (test_bit(__IXGBE_TX_DISABLED, &ring->state))
+		return -ENETDOWN;
+
+	if (!ring->xsk_umem)
 		return -ENXIO;
 
-	ring = adapter->xdp_ring[qid];
 	if (!napi_if_scheduled_mark_missed(&ring->q_vector->napi)) {
 		u64 eics = BIT_ULL(ring->q_vector->v_idx);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ixgbevf/ipsec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ixgbevf/ipsec.c
@@ -272,6 +272,11 @@
 		return -EINVAL;
 	}
 
+	if (xs->props.mode != XFRM_MODE_TRANSPORT) {
+		netdev_err(dev, "Unsupported mode for ipsec offload\n");
+		return -EINVAL;
+	}
+
 	if (xs->xso.flags & XFRM_OFFLOAD_INBOUND) {
 		struct rx_sa rsa;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
@@ -387,6 +387,8 @@
 	u32 *rss_key;
 	u8 rss_indir_tbl[IXGBEVF_X550_VFRETA_SIZE];
 	u32 flags;
+	bool link_state;
+
 #define IXGBEVF_FLAGS_LEGACY_RX		BIT(1)
 
 #ifdef CONFIG_XFRM
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -1079,11 +1079,14 @@
 	case XDP_TX:
 		xdp_ring = adapter->xdp_ring[rx_ring->queue_index];
 		result = ixgbevf_xmit_xdp_ring(xdp_ring, xdp);
+		if (result == IXGBEVF_XDP_CONSUMED)
+			goto out_failure;
 		break;
 	default:
 		bpf_warn_invalid_xdp_action(act);
 		/* fallthrough */
 	case XDP_ABORTED:
+out_failure:
 		trace_xdp_exception(rx_ring->netdev, xdp_prog, act);
 		/* fallthrough -- handle aborts by dropping packet */
 	case XDP_DROP:
@@ -1976,14 +1979,15 @@
 	if (adapter->flags & IXGBEVF_FLAGS_LEGACY_RX)
 		return;
 
-	set_ring_build_skb_enabled(rx_ring);
+	if (PAGE_SIZE < 8192)
+		if (max_frame > IXGBEVF_MAX_FRAME_BUILD_SKB)
+			set_ring_uses_large_buffer(rx_ring);
 
-	if (PAGE_SIZE < 8192) {
-		if (max_frame <= IXGBEVF_MAX_FRAME_BUILD_SKB)
-			return;
+	/* 82599 can't rely on RXDCTL.RLPML to restrict the size of the frame */
+	if (adapter->hw.mac.type == ixgbe_mac_82599_vf && !ring_uses_large_buffer(rx_ring))
+		return;
 
-		set_ring_uses_large_buffer(rx_ring);
-	}
+	set_ring_build_skb_enabled(rx_ring);
 }
 
 /**
@@ -2081,11 +2085,6 @@
 	struct ixgbe_hw *hw = &adapter->hw;
 	int count = 0;
 
-	if ((netdev_uc_count(netdev)) > 10) {
-		pr_err("Too many unicast filters - No Space\n");
-		return -ENOSPC;
-	}
-
 	if (!netdev_uc_empty(netdev)) {
 		struct netdev_hw_addr *ha;
 
@@ -2287,7 +2286,9 @@
 static void ixgbevf_up_complete(struct ixgbevf_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
+	struct pci_dev *pdev = adapter->pdev;
 	struct ixgbe_hw *hw = &adapter->hw;
+	bool state;
 
 	ixgbevf_configure_msix(adapter);
 
@@ -2300,6 +2301,11 @@
 
 	spin_unlock_bh(&adapter->mbx_lock);
 
+	state = adapter->link_state;
+	hw->mac.ops.get_link_state(hw, &adapter->link_state);
+	if (state && state != adapter->link_state)
+		dev_info(&pdev->dev, "VF is administratively disabled\n");
+
 	smp_mb__before_atomic();
 	clear_bit(__IXGBEVF_DOWN, &adapter->state);
 	ixgbevf_napi_enable_all(adapter);
@@ -3070,6 +3076,8 @@
 	adapter->tx_ring_count = IXGBEVF_DEFAULT_TXD;
 	adapter->rx_ring_count = IXGBEVF_DEFAULT_RXD;
 
+	adapter->link_state = true;
+
 	set_bit(__IXGBEVF_DOWN, &adapter->state);
 	return 0;
 
@@ -3302,7 +3310,7 @@
 
 	ixgbevf_watchdog_update_link(adapter);
 
-	if (adapter->link_up)
+	if (adapter->link_up && adapter->link_state)
 		ixgbevf_watchdog_link_is_up(adapter);
 	else
 		ixgbevf_watchdog_link_is_down(adapter);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ixgbevf/mbx.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ixgbevf/mbx.h
@@ -51,6 +51,16 @@
 /* bits 23:16 are used for exra info for certain messages */
 #define IXGBE_VT_MSGINFO_MASK	(0xFF << IXGBE_VT_MSGINFO_SHIFT)
 
+/* IXGBE_VT_MSGTYPE_NACK and IXGBE_VT_MSGTYPE_ACK were renamed to
+ * IXGBE_VT_MSGTYPE_FAILURE and IXGBE_VT_MSGTYPE_SUCCESS respectively
+ * with commit 0edbecd57057 upstream.
+ *
+ * One of the backported fixes use them with their new names. These
+ * aliases enable them to work with both older and newer names.
+ */
+#define IXGBE_VT_MSGTYPE_SUCCESS IXGBE_VT_MSGTYPE_ACK
+#define IXGBE_VT_MSGTYPE_FAILURE IXGBE_VT_MSGTYPE_NACK
+
 /* definitions to support mailbox API version negotiation */
 
 /* each element denotes a version of the API; existing numbers may not
@@ -97,6 +107,8 @@
 #define IXGBE_VF_IPSEC_ADD	0x0d
 #define IXGBE_VF_IPSEC_DEL	0x0e
 
+#define IXGBE_VF_GET_LINK_STATE 0x10 /* get vf link state */
+
 /* length of permanent address message returned from PF */
 #define IXGBE_VF_PERMADDR_MSG_LEN	4
 /* word in permanent address message with the current multicast type */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ixgbevf/vf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ixgbevf/vf.c
@@ -574,6 +574,46 @@
 }
 
 /**
+ * ixgbevf_get_link_state_vf - Get VF link state from PF
+ * @hw: pointer to the HW structure
+ * @link_state: link state storage
+ *
+ * Returns state of the operation error or success.
+ */
+static s32 ixgbevf_get_link_state_vf(struct ixgbe_hw *hw, bool *link_state)
+{
+	u32 msgbuf[2];
+	s32 ret_val;
+	s32 err;
+
+	msgbuf[0] = IXGBE_VF_GET_LINK_STATE;
+	msgbuf[1] = 0x0;
+
+	err = ixgbevf_write_msg_read_ack(hw, msgbuf, msgbuf, 2);
+
+	if (err || (msgbuf[0] & IXGBE_VT_MSGTYPE_FAILURE)) {
+		ret_val = IXGBE_ERR_MBX;
+	} else {
+		ret_val = 0;
+		*link_state = msgbuf[1];
+	}
+
+	return ret_val;
+}
+
+/**
+ * ixgbevf_hv_get_link_state_vf - * Hyper-V variant - just a stub.
+ * @hw: unused
+ * @link_state: unused
+ *
+ * Hyper-V variant; there is no mailbox communication.
+ */
+static s32 ixgbevf_hv_get_link_state_vf(struct ixgbe_hw *hw, bool *link_state)
+{
+	return -EOPNOTSUPP;
+}
+
+/**
  *  ixgbevf_set_vfta_vf - Set/Unset VLAN filter table address
  *  @hw: pointer to the HW structure
  *  @vlan: 12 bit VLAN ID
@@ -950,6 +990,7 @@
 	.set_rar		= ixgbevf_set_rar_vf,
 	.update_mc_addr_list	= ixgbevf_update_mc_addr_list_vf,
 	.update_xcast_mode	= ixgbevf_update_xcast_mode,
+	.get_link_state		= ixgbevf_get_link_state_vf,
 	.set_uc_addr		= ixgbevf_set_uc_addr_vf,
 	.set_vfta		= ixgbevf_set_vfta_vf,
 	.set_rlpml		= ixgbevf_set_rlpml_vf,
@@ -967,6 +1008,7 @@
 	.set_rar		= ixgbevf_hv_set_rar_vf,
 	.update_mc_addr_list	= ixgbevf_hv_update_mc_addr_list_vf,
 	.update_xcast_mode	= ixgbevf_hv_update_xcast_mode,
+	.get_link_state		= ixgbevf_hv_get_link_state_vf,
 	.set_uc_addr		= ixgbevf_hv_set_uc_addr_vf,
 	.set_vfta		= ixgbevf_hv_set_vfta_vf,
 	.set_rlpml		= ixgbevf_hv_set_rlpml_vf,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/intel/ixgbevf/vf.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/intel/ixgbevf/vf.h
@@ -42,6 +42,7 @@
 	s32 (*init_rx_addrs)(struct ixgbe_hw *);
 	s32 (*update_mc_addr_list)(struct ixgbe_hw *, struct net_device *);
 	s32 (*update_xcast_mode)(struct ixgbe_hw *, int);
+	s32 (*get_link_state)(struct ixgbe_hw *hw, bool *link_state);
 	s32 (*enable_mc)(struct ixgbe_hw *);
 	s32 (*disable_mc)(struct ixgbe_hw *);
 	s32 (*clear_vfta)(struct ixgbe_hw *);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/jme.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/jme.c
@@ -947,15 +947,13 @@
 	if (skb->protocol != htons(ETH_P_IP))
 		return csum;
 	skb_set_network_header(skb, ETH_HLEN);
-	if ((ip_hdr(skb)->protocol != IPPROTO_UDP) ||
-	    (skb->len < (ETH_HLEN +
-			(ip_hdr(skb)->ihl << 2) +
-			sizeof(struct udphdr)))) {
+
+	if (ip_hdr(skb)->protocol != IPPROTO_UDP ||
+	    skb->len < (ETH_HLEN + ip_hdrlen(skb) + sizeof(struct udphdr))) {
 		skb_reset_network_header(skb);
 		return csum;
 	}
-	skb_set_transport_header(skb,
-			ETH_HLEN + (ip_hdr(skb)->ihl << 2));
+	skb_set_transport_header(skb, ETH_HLEN + ip_hdrlen(skb));
 	csum = udp_hdr(skb)->check;
 	skb_reset_transport_header(skb);
 	skb_reset_network_header(skb);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/korina.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/korina.c
@@ -219,7 +219,7 @@
 			dev_kfree_skb_any(skb);
 			spin_unlock_irqrestore(&lp->lock, flags);
 
-			return NETDEV_TX_BUSY;
+			return NETDEV_TX_OK;
 		}
 	}
 
@@ -1113,7 +1113,7 @@
 	return rc;
 
 probe_err_register:
-	kfree(lp->td_ring);
+	kfree((struct dma_desc *)KSEG0ADDR(lp->td_ring));
 probe_err_td_ring:
 	iounmap(lp->tx_dma_regs);
 probe_err_dma_tx:
@@ -1133,6 +1133,7 @@
 	iounmap(lp->eth_regs);
 	iounmap(lp->rx_dma_regs);
 	iounmap(lp->tx_dma_regs);
+	kfree((struct dma_desc *)KSEG0ADDR(lp->td_ring));
 
 	unregister_netdev(bif->dev);
 	free_netdev(bif->dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/lantiq_etop.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/lantiq_etop.c
@@ -213,8 +213,9 @@
 	if (ch->dma.irq)
 		free_irq(ch->dma.irq, priv);
 	if (IS_RX(ch->idx)) {
-		int desc;
-		for (desc = 0; desc < LTQ_DESC_NUM; desc++)
+		struct ltq_dma_channel *dma = &ch->dma;
+
+		for (dma->desc = 0; dma->desc < LTQ_DESC_NUM; dma->desc++)
 			dev_kfree_skb_any(ch->skb[ch->dma.desc]);
 	}
 }
@@ -463,10 +464,11 @@
 	unsigned long flags;
 	u32 byte_offset;
 
-	len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
+	if (skb_put_padto(skb, ETH_ZLEN))
+		return NETDEV_TX_OK;
+	len = skb->len;
 
 	if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) || ch->skb[ch->dma.desc]) {
-		dev_kfree_skb_any(skb);
 		netdev_err(dev, "tx ring full\n");
 		netif_tx_stop_queue(txq);
 		return NETDEV_TX_BUSY;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/lantiq_xrx200.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/lantiq_xrx200.c
@@ -154,6 +154,8 @@
 
 static int xrx200_alloc_skb(struct xrx200_chan *ch)
 {
+	struct sk_buff *skb = ch->skb[ch->dma.desc];
+	dma_addr_t mapping;
 	int ret = 0;
 
 	ch->skb[ch->dma.desc] = netdev_alloc_skb_ip_align(ch->priv->net_dev,
@@ -163,16 +165,18 @@
 		goto skip;
 	}
 
-	ch->dma.desc_base[ch->dma.desc].addr = dma_map_single(ch->priv->dev,
-			ch->skb[ch->dma.desc]->data, XRX200_DMA_DATA_LEN,
-			DMA_FROM_DEVICE);
-	if (unlikely(dma_mapping_error(ch->priv->dev,
-				       ch->dma.desc_base[ch->dma.desc].addr))) {
+	mapping = dma_map_single(ch->priv->dev, ch->skb[ch->dma.desc]->data,
+				 XRX200_DMA_DATA_LEN, DMA_FROM_DEVICE);
+	if (unlikely(dma_mapping_error(ch->priv->dev, mapping))) {
 		dev_kfree_skb_any(ch->skb[ch->dma.desc]);
+		ch->skb[ch->dma.desc] = skb;
 		ret = -ENOMEM;
 		goto skip;
 	}
 
+	ch->dma.desc_base[ch->dma.desc].addr = mapping;
+	/* Make sure the address is written before we give it to HW */
+	wmb();
 skip:
 	ch->dma.desc_base[ch->dma.desc].ctl =
 		LTQ_DMA_OWN | LTQ_DMA_RX_OFFSET(NET_IP_ALIGN) |
@@ -196,6 +200,7 @@
 	ch->dma.desc %= LTQ_DESC_NUM;
 
 	if (ret) {
+		net_dev->stats.rx_dropped++;
 		netdev_err(net_dev, "failed to allocate new rx buffer\n");
 		return ret;
 	}
@@ -204,7 +209,7 @@
 	skb->protocol = eth_type_trans(skb, net_dev);
 	netif_receive_skb(skb);
 	net_dev->stats.rx_packets++;
-	net_dev->stats.rx_bytes += len - ETH_FCS_LEN;
+	net_dev->stats.rx_bytes += len;
 
 	return 0;
 }
@@ -230,8 +235,8 @@
 	}
 
 	if (rx < budget) {
-		napi_complete(&ch->napi);
-		ltq_dma_enable_irq(&ch->dma);
+		if (napi_complete_done(&ch->napi, rx))
+			ltq_dma_enable_irq(&ch->dma);
 	}
 
 	return rx;
@@ -245,6 +250,7 @@
 	int pkts = 0;
 	int bytes = 0;
 
+	netif_tx_lock(net_dev);
 	while (pkts < budget) {
 		struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->tx_free];
 
@@ -268,9 +274,13 @@
 	net_dev->stats.tx_bytes += bytes;
 	netdev_completed_queue(ch->priv->net_dev, pkts, bytes);
 
+	netif_tx_unlock(net_dev);
+	if (netif_queue_stopped(net_dev))
+		netif_wake_queue(net_dev);
+
 	if (pkts < budget) {
-		napi_complete(&ch->napi);
-		ltq_dma_enable_irq(&ch->dma);
+		if (napi_complete_done(&ch->napi, pkts))
+			ltq_dma_enable_irq(&ch->dma);
 	}
 
 	return pkts;
@@ -341,10 +351,12 @@
 {
 	struct xrx200_chan *ch = ptr;
 
-	ltq_dma_disable_irq(&ch->dma);
-	ltq_dma_ack_irq(&ch->dma);
+	if (napi_schedule_prep(&ch->napi)) {
+		ltq_dma_disable_irq(&ch->dma);
+		__napi_schedule(&ch->napi);
+	}
 
-	napi_schedule(&ch->napi);
+	ltq_dma_ack_irq(&ch->dma);
 
 	return IRQ_HANDLED;
 }
@@ -498,7 +510,7 @@
 
 	/* setup NAPI */
 	netif_napi_add(net_dev, &priv->chan_rx.napi, xrx200_poll_rx, 32);
-	netif_napi_add(net_dev, &priv->chan_tx.napi, xrx200_tx_housekeeping, 32);
+	netif_tx_napi_add(net_dev, &priv->chan_tx.napi, xrx200_tx_housekeeping, 32);
 
 	platform_set_drvdata(pdev, priv);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -2476,6 +2476,7 @@
 	for (i = 0; i < mp->rxq_count; i++)
 		rxq_deinit(mp->rxq + i);
 out:
+	napi_disable(&mp->napi);
 	free_irq(dev->irq, dev);
 
 	return err;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/marvell/mvneta.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/marvell/mvneta.c
@@ -101,12 +101,14 @@
 #define      MVNETA_DESC_SWAP                    BIT(6)
 #define      MVNETA_TX_BRST_SZ_MASK(burst)       ((burst) << 22)
 #define MVNETA_PORT_STATUS                       0x2444
-#define      MVNETA_TX_IN_PRGRS                  BIT(1)
+#define      MVNETA_TX_IN_PRGRS                  BIT(0)
 #define      MVNETA_TX_FIFO_EMPTY                BIT(8)
 #define MVNETA_RX_MIN_FRAME_SIZE                 0x247c
+/* Only exists on Armada XP and Armada 370 */
 #define MVNETA_SERDES_CFG			 0x24A0
 #define      MVNETA_SGMII_SERDES_PROTO		 0x0cc7
 #define      MVNETA_QSGMII_SERDES_PROTO		 0x0667
+#define      MVNETA_HSGMII_SERDES_PROTO		 0x1107
 #define MVNETA_TYPE_PRIO                         0x24bc
 #define      MVNETA_FORCE_UNI                    BIT(21)
 #define MVNETA_TXQ_CMD_1                         0x24e4
@@ -388,6 +390,8 @@
 	struct	u64_stats_sync syncp;
 	u64	rx_packets;
 	u64	rx_bytes;
+	u64	rx_dropped;
+	u64	rx_errors;
 	u64	tx_packets;
 	u64	tx_bytes;
 };
@@ -545,6 +549,20 @@
 };
 #endif
 
+enum mvneta_tx_buf_type {
+	MVNETA_TYPE_SKB,
+	MVNETA_TYPE_XDP_TX,
+	MVNETA_TYPE_XDP_NDO,
+};
+
+struct mvneta_tx_buf {
+	enum mvneta_tx_buf_type type;
+	union {
+		struct xdp_frame *xdpf;
+		struct sk_buff *skb;
+	};
+};
+
 struct mvneta_tx_queue {
 	/* Number of this TX queue, in the range 0-7 */
 	u8 id;
@@ -560,8 +578,8 @@
 	int tx_stop_threshold;
 	int tx_wake_threshold;
 
-	/* Array of transmitted skb */
-	struct sk_buff **tx_skb;
+	/* Array of transmitted buffers */
+	struct mvneta_tx_buf *buf;
 
 	/* Index of last TX DMA descriptor that was inserted */
 	int txq_put_index;
@@ -706,6 +724,8 @@
 		struct mvneta_pcpu_stats *cpu_stats;
 		u64 rx_packets;
 		u64 rx_bytes;
+		u64 rx_dropped;
+		u64 rx_errors;
 		u64 tx_packets;
 		u64 tx_bytes;
 
@@ -714,19 +734,20 @@
 			start = u64_stats_fetch_begin_irq(&cpu_stats->syncp);
 			rx_packets = cpu_stats->rx_packets;
 			rx_bytes   = cpu_stats->rx_bytes;
+			rx_dropped = cpu_stats->rx_dropped;
+			rx_errors  = cpu_stats->rx_errors;
 			tx_packets = cpu_stats->tx_packets;
 			tx_bytes   = cpu_stats->tx_bytes;
 		} while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start));
 
 		stats->rx_packets += rx_packets;
 		stats->rx_bytes   += rx_bytes;
+		stats->rx_dropped += rx_dropped;
+		stats->rx_errors  += rx_errors;
 		stats->tx_packets += tx_packets;
 		stats->tx_bytes   += tx_bytes;
 	}
 
-	stats->rx_errors	= dev->stats.rx_errors;
-	stats->rx_dropped	= dev->stats.rx_dropped;
-
 	stats->tx_dropped	= dev->stats.tx_dropped;
 }
 
@@ -1401,7 +1422,7 @@
 			 */
 			if (txq_number == 1)
 				txq_map = (cpu == pp->rxq_def) ?
-					MVNETA_CPU_TXQ_ACCESS(1) : 0;
+					MVNETA_CPU_TXQ_ACCESS(0) : 0;
 
 		} else {
 			txq_map = MVNETA_CPU_TXQ_ACCESS_ALL_MASK;
@@ -1703,8 +1724,14 @@
 static void mvneta_rx_error(struct mvneta_port *pp,
 			    struct mvneta_rx_desc *rx_desc)
 {
+	struct mvneta_pcpu_stats *stats = this_cpu_ptr(pp->stats);
 	u32 status = rx_desc->status;
 
+	/* update per-cpu counter */
+	u64_stats_update_begin(&stats->syncp);
+	stats->rx_errors++;
+	u64_stats_update_end(&stats->syncp);
+
 	switch (status & MVNETA_RXD_ERR_CODE_MASK) {
 	case MVNETA_RXD_ERR_CRC:
 		netdev_err(pp->dev, "bad rx status %08x (crc error), size=%d\n",
@@ -1761,14 +1788,9 @@
 	int i;
 
 	for (i = 0; i < num; i++) {
+		struct mvneta_tx_buf *buf = &txq->buf[txq->txq_get_index];
 		struct mvneta_tx_desc *tx_desc = txq->descs +
 			txq->txq_get_index;
-		struct sk_buff *skb = txq->tx_skb[txq->txq_get_index];
-
-		if (skb) {
-			bytes_compl += skb->len;
-			pkts_compl++;
-		}
 
 		mvneta_txq_inc_get(txq);
 
@@ -1776,9 +1798,12 @@
 			dma_unmap_single(pp->dev->dev.parent,
 					 tx_desc->buf_phys_addr,
 					 tx_desc->data_size, DMA_TO_DEVICE);
-		if (!skb)
+		if (!buf->skb)
 			continue;
-		dev_kfree_skb_any(skb);
+
+		bytes_compl += buf->skb->len;
+		pkts_compl++;
+		dev_kfree_skb_any(buf->skb);
 	}
 
 	netdev_tx_completed_queue(nq, pkts_compl, bytes_compl);
@@ -1965,7 +1990,6 @@
 			/* Check errors only for FIRST descriptor */
 			if (rx_status & MVNETA_RXD_ERR_SUMMARY) {
 				mvneta_rx_error(pp, rx_desc);
-				dev->stats.rx_errors++;
 				/* leave the descriptor untouched */
 				continue;
 			}
@@ -1976,11 +2000,17 @@
 			skb_size = max(rx_copybreak, rx_header_size);
 			rxq->skb = netdev_alloc_skb_ip_align(dev, skb_size);
 			if (unlikely(!rxq->skb)) {
+				struct mvneta_pcpu_stats *stats = this_cpu_ptr(pp->stats);
+
 				netdev_err(dev,
 					   "Can't allocate skb on queue %d\n",
 					   rxq->id);
-				dev->stats.rx_dropped++;
+
 				rxq->skb_alloc_err++;
+
+				u64_stats_update_begin(&stats->syncp);
+				stats->rx_dropped++;
+				u64_stats_update_end(&stats->syncp);
 				continue;
 			}
 			copy_size = min(skb_size, rx_bytes);
@@ -2137,7 +2167,6 @@
 			mvneta_bm_pool_put_bp(pp->bm_priv, bm_pool,
 					      rx_desc->buf_phys_addr);
 err_drop_frame:
-			dev->stats.rx_errors++;
 			mvneta_rx_error(pp, rx_desc);
 			/* leave the descriptor untouched */
 			continue;
@@ -2225,16 +2254,19 @@
 mvneta_tso_put_hdr(struct sk_buff *skb,
 		   struct mvneta_port *pp, struct mvneta_tx_queue *txq)
 {
-	struct mvneta_tx_desc *tx_desc;
 	int hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
+	struct mvneta_tx_buf *buf = &txq->buf[txq->txq_put_index];
+	struct mvneta_tx_desc *tx_desc;
 
-	txq->tx_skb[txq->txq_put_index] = NULL;
 	tx_desc = mvneta_txq_next_desc_get(txq);
 	tx_desc->data_size = hdr_len;
 	tx_desc->command = mvneta_skb_tx_csum(pp, skb);
 	tx_desc->command |= MVNETA_TXD_F_DESC;
 	tx_desc->buf_phys_addr = txq->tso_hdrs_phys +
 				 txq->txq_put_index * TSO_HEADER_SIZE;
+	buf->type = MVNETA_TYPE_SKB;
+	buf->skb = NULL;
+
 	mvneta_txq_inc_put(txq);
 }
 
@@ -2243,6 +2275,7 @@
 		    struct sk_buff *skb, char *data, int size,
 		    bool last_tcp, bool is_last)
 {
+	struct mvneta_tx_buf *buf = &txq->buf[txq->txq_put_index];
 	struct mvneta_tx_desc *tx_desc;
 
 	tx_desc = mvneta_txq_next_desc_get(txq);
@@ -2256,7 +2289,8 @@
 	}
 
 	tx_desc->command = 0;
-	txq->tx_skb[txq->txq_put_index] = NULL;
+	buf->type = MVNETA_TYPE_SKB;
+	buf->skb = NULL;
 
 	if (last_tcp) {
 		/* last descriptor in the TCP packet */
@@ -2264,7 +2298,7 @@
 
 		/* last descriptor in SKB */
 		if (is_last)
-			txq->tx_skb[txq->txq_put_index] = skb;
+			buf->skb = skb;
 	}
 	mvneta_txq_inc_put(txq);
 	return 0;
@@ -2349,6 +2383,7 @@
 	int i, nr_frags = skb_shinfo(skb)->nr_frags;
 
 	for (i = 0; i < nr_frags; i++) {
+		struct mvneta_tx_buf *buf = &txq->buf[txq->txq_put_index];
 		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
 		void *addr = skb_frag_address(frag);
 
@@ -2368,12 +2403,13 @@
 		if (i == nr_frags - 1) {
 			/* Last descriptor */
 			tx_desc->command = MVNETA_TXD_L_DESC | MVNETA_TXD_Z_PAD;
-			txq->tx_skb[txq->txq_put_index] = skb;
+			buf->skb = skb;
 		} else {
 			/* Descriptor in the middle: Not First, Not Last */
 			tx_desc->command = 0;
-			txq->tx_skb[txq->txq_put_index] = NULL;
+			buf->skb = NULL;
 		}
+		buf->type = MVNETA_TYPE_SKB;
 		mvneta_txq_inc_put(txq);
 	}
 
@@ -2401,6 +2437,7 @@
 	struct mvneta_port *pp = netdev_priv(dev);
 	u16 txq_id = skb_get_queue_mapping(skb);
 	struct mvneta_tx_queue *txq = &pp->txqs[txq_id];
+	struct mvneta_tx_buf *buf = &txq->buf[txq->txq_put_index];
 	struct mvneta_tx_desc *tx_desc;
 	int len = skb->len;
 	int frags = 0;
@@ -2433,16 +2470,17 @@
 		goto out;
 	}
 
+	buf->type = MVNETA_TYPE_SKB;
 	if (frags == 1) {
 		/* First and Last descriptor */
 		tx_cmd |= MVNETA_TXD_FLZ_DESC;
 		tx_desc->command = tx_cmd;
-		txq->tx_skb[txq->txq_put_index] = skb;
+		buf->skb = skb;
 		mvneta_txq_inc_put(txq);
 	} else {
 		/* First but not Last */
 		tx_cmd |= MVNETA_TXD_F_DESC;
-		txq->tx_skb[txq->txq_put_index] = NULL;
+		buf->skb = NULL;
 		mvneta_txq_inc_put(txq);
 		tx_desc->command = tx_cmd;
 		/* Continue with other skb fragments */
@@ -2789,11 +2827,10 @@
 	/* For the case where the last mvneta_poll did not process all
 	 * RX packets
 	 */
-	rx_queue = fls(((cause_rx_tx >> 8) & 0xff));
-
 	cause_rx_tx |= pp->neta_armada3700 ? pp->cause_rx_tx :
 		port->cause_rx_tx;
 
+	rx_queue = fls(((cause_rx_tx >> 8) & 0xff));
 	if (rx_queue) {
 		rx_queue = rx_queue - 1;
 		if (pp->bm_priv)
@@ -2989,9 +3026,8 @@
 
 	txq->last_desc = txq->size - 1;
 
-	txq->tx_skb = kmalloc_array(txq->size, sizeof(*txq->tx_skb),
-				    GFP_KERNEL);
-	if (!txq->tx_skb) {
+	txq->buf = kmalloc_array(txq->size, sizeof(*txq->buf), GFP_KERNEL);
+	if (!txq->buf) {
 		dma_free_coherent(pp->dev->dev.parent,
 				  txq->size * MVNETA_DESC_ALIGNED_SIZE,
 				  txq->descs, txq->descs_phys);
@@ -3003,7 +3039,7 @@
 					   txq->size * TSO_HEADER_SIZE,
 					   &txq->tso_hdrs_phys, GFP_KERNEL);
 	if (!txq->tso_hdrs) {
-		kfree(txq->tx_skb);
+		kfree(txq->buf);
 		dma_free_coherent(pp->dev->dev.parent,
 				  txq->size * MVNETA_DESC_ALIGNED_SIZE,
 				  txq->descs, txq->descs_phys);
@@ -3011,7 +3047,9 @@
 	}
 
 	/* Setup XPS mapping */
-	if (txq_number > 1)
+	if (pp->neta_armada3700)
+		cpu = 0;
+	else if (txq_number > 1)
 		cpu = txq->id % num_present_cpus();
 	else
 		cpu = pp->rxq_def % num_present_cpus();
@@ -3056,7 +3094,7 @@
 {
 	struct netdev_queue *nq = netdev_get_tx_queue(pp->dev, txq->id);
 
-	kfree(txq->tx_skb);
+	kfree(txq->buf);
 
 	if (txq->tso_hdrs)
 		dma_free_coherent(pp->dev->dev.parent,
@@ -3150,26 +3188,60 @@
 	return 0;
 }
 
-static int mvneta_comphy_init(struct mvneta_port *pp)
+static int mvneta_comphy_init(struct mvneta_port *pp, phy_interface_t interface)
 {
 	int ret;
 
-	if (!pp->comphy)
-		return 0;
-
-	ret = phy_set_mode_ext(pp->comphy, PHY_MODE_ETHERNET,
-			       pp->phy_interface);
+	ret = phy_set_mode_ext(pp->comphy, PHY_MODE_ETHERNET, interface);
 	if (ret)
 		return ret;
 
 	return phy_power_on(pp->comphy);
 }
 
+static int mvneta_config_interface(struct mvneta_port *pp,
+				   phy_interface_t interface)
+{
+	int ret = 0;
+
+	if (pp->comphy) {
+		if (interface == PHY_INTERFACE_MODE_SGMII ||
+		    interface == PHY_INTERFACE_MODE_1000BASEX ||
+		    interface == PHY_INTERFACE_MODE_2500BASEX) {
+			ret = mvneta_comphy_init(pp, interface);
+		}
+	} else {
+		switch (interface) {
+		case PHY_INTERFACE_MODE_QSGMII:
+			mvreg_write(pp, MVNETA_SERDES_CFG,
+				    MVNETA_QSGMII_SERDES_PROTO);
+			break;
+
+		case PHY_INTERFACE_MODE_SGMII:
+		case PHY_INTERFACE_MODE_1000BASEX:
+			mvreg_write(pp, MVNETA_SERDES_CFG,
+				    MVNETA_SGMII_SERDES_PROTO);
+			break;
+
+		case PHY_INTERFACE_MODE_2500BASEX:
+			mvreg_write(pp, MVNETA_SERDES_CFG,
+				    MVNETA_HSGMII_SERDES_PROTO);
+			break;
+		default:
+			break;
+		}
+	}
+
+	pp->phy_interface = interface;
+
+	return ret;
+}
+
 static void mvneta_start_dev(struct mvneta_port *pp)
 {
 	int cpu;
 
-	WARN_ON(mvneta_comphy_init(pp));
+	WARN_ON(mvneta_config_interface(pp, pp->phy_interface));
 
 	mvneta_max_rx_size_set(pp, pp->pkt_size);
 	mvneta_txq_max_tx_size_set(pp, pp->pkt_size);
@@ -3544,17 +3616,13 @@
 	/* When at 2.5G, the link partner can send frames with shortened
 	 * preambles.
 	 */
-	if (state->speed == SPEED_2500)
+	if (state->interface == PHY_INTERFACE_MODE_2500BASEX)
 		new_ctrl4 |= MVNETA_GMAC4_SHORT_PREAMBLE_ENABLE;
 
-	if (pp->comphy && pp->phy_interface != state->interface &&
-	    (state->interface == PHY_INTERFACE_MODE_SGMII ||
-	     state->interface == PHY_INTERFACE_MODE_1000BASEX ||
-	     state->interface == PHY_INTERFACE_MODE_2500BASEX)) {
-		pp->phy_interface = state->interface;
-
-		WARN_ON(phy_power_off(pp->comphy));
-		WARN_ON(mvneta_comphy_init(pp));
+	if (pp->phy_interface != state->interface) {
+		if (pp->comphy)
+			WARN_ON(phy_power_off(pp->comphy));
+		WARN_ON(mvneta_config_interface(pp, state->interface));
 	}
 
 	if (new_ctrl0 != gmac_ctrl0)
@@ -3669,7 +3737,7 @@
 	/* Use the cpu associated to the rxq when it is online, in all
 	 * the other cases, use the cpu 0 which can't be offline.
 	 */
-	if (cpu_online(pp->rxq_def))
+	if (pp->rxq_def < nr_cpu_ids && cpu_online(pp->rxq_def))
 		elected_cpu = pp->rxq_def;
 
 	max_cpu = num_present_cpus();
@@ -3694,7 +3762,7 @@
 		 */
 		if (txq_number == 1)
 			txq_map = (cpu == elected_cpu) ?
-				MVNETA_CPU_TXQ_ACCESS(1) : 0;
+				MVNETA_CPU_TXQ_ACCESS(0) : 0;
 		else
 			txq_map = mvreg_read(pp, MVNETA_CPU_MAP(cpu)) &
 				MVNETA_CPU_TXQ_ACCESS_ALL_MASK;
@@ -3718,6 +3786,11 @@
 						  node_online);
 	struct mvneta_pcpu_port *port = per_cpu_ptr(pp->ports, cpu);
 
+	/* Armada 3700's per-cpu interrupt for mvneta is broken, all interrupts
+	 * are routed to CPU 0, so we don't need all the cpu-hotplug support
+	 */
+	if (pp->neta_armada3700)
+		return 0;
 
 	spin_lock(&pp->lock);
 	/*
@@ -4455,12 +4528,10 @@
 	/* MAC Cause register should be cleared */
 	mvreg_write(pp, MVNETA_UNIT_INTR_CAUSE, 0);
 
-	if (phy_mode == PHY_INTERFACE_MODE_QSGMII)
-		mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_QSGMII_SERDES_PROTO);
-	else if (phy_mode == PHY_INTERFACE_MODE_SGMII ||
-		 phy_interface_mode_is_8023z(phy_mode))
-		mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_SGMII_SERDES_PROTO);
-	else if (!phy_interface_mode_is_rgmii(phy_mode))
+	if (phy_mode != PHY_INTERFACE_MODE_QSGMII &&
+	    phy_mode != PHY_INTERFACE_MODE_SGMII &&
+	    !phy_interface_mode_is_8023z(phy_mode) &&
+	    !phy_interface_mode_is_rgmii(phy_mode))
 		return -EINVAL;
 
 	return 0;
@@ -4647,7 +4718,7 @@
 	if (err < 0)
 		goto err_netdev;
 
-	err = mvneta_port_power_up(pp, phy_mode);
+	err = mvneta_port_power_up(pp, pp->phy_interface);
 	if (err < 0) {
 		dev_err(&pdev->dev, "can't power up port\n");
 		goto err_netdev;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/marvell/mvpp2/mvpp2.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/marvell/mvpp2/mvpp2.h
@@ -809,7 +809,7 @@
 	unsigned int max_port_rxqs;
 
 	/* Workqueue to gather hardware statistics */
-	char queue_name[30];
+	char queue_name[31];
 	struct workqueue_struct *stats_queue;
 
 	/* Debugfs root entry */
@@ -1202,5 +1202,6 @@
 void mvpp2_dbgfs_init(struct mvpp2 *priv, const char *name);
 
 void mvpp2_dbgfs_cleanup(struct mvpp2 *priv);
+void mvpp2_dbgfs_exit(void);
 
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c
@@ -318,7 +318,7 @@
 		       MVPP2_PRS_RI_VLAN_MASK),
 	/* Non IP flow, with vlan tag */
 	MVPP2_DEF_FLOW(MVPP22_FLOW_ETHERNET, MVPP2_FL_NON_IP_TAG,
-		       MVPP22_CLS_HEK_OPT_VLAN,
+		       MVPP22_CLS_HEK_TAGGED,
 		       0, 0),
 };
 
@@ -1070,7 +1070,7 @@
 		    (port->first_rxq >> MVPP2_CLS_OVERSIZE_RXQ_LOW_BITS));
 
 	val = mvpp2_read(port->priv, MVPP2_CLS_SWFWD_PCTRL_REG);
-	val |= MVPP2_CLS_SWFWD_PCTRL_MASK(port->id);
+	val &= ~MVPP2_CLS_SWFWD_PCTRL_MASK(port->id);
 	mvpp2_write(port->priv, MVPP2_CLS_SWFWD_PCTRL_REG, val);
 }
 
@@ -1422,6 +1422,9 @@
 	struct mvpp2_ethtool_fs *efs;
 	int ret;
 
+	if (info->fs.location >= MVPP2_N_RFS_ENTRIES_PER_FLOW)
+		return -EINVAL;
+
 	efs = port->rfs_rules[info->fs.location];
 	if (!efs)
 		return -EINVAL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/marvell/mvpp2/mvpp2_debugfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/marvell/mvpp2/mvpp2_debugfs.c
@@ -691,6 +691,13 @@
 	return 0;
 }
 
+static struct dentry *mvpp2_root;
+
+void mvpp2_dbgfs_exit(void)
+{
+	debugfs_remove(mvpp2_root);
+}
+
 void mvpp2_dbgfs_cleanup(struct mvpp2 *priv)
 {
 	debugfs_remove_recursive(priv->dbgfs_dir);
@@ -700,10 +707,9 @@
 
 void mvpp2_dbgfs_init(struct mvpp2 *priv, const char *name)
 {
-	struct dentry *mvpp2_dir, *mvpp2_root;
+	struct dentry *mvpp2_dir;
 	int ret, i;
 
-	mvpp2_root = debugfs_lookup(MVPP2_DRIVER_NAME, NULL);
 	if (!mvpp2_root)
 		mvpp2_root = debugfs_create_dir(MVPP2_DRIVER_NAME, NULL);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -1073,7 +1073,7 @@
 	u32 val;
 
 	/* If the thread isn't used, don't do anything */
-	if (smp_processor_id() > port->priv->nthreads)
+	if (smp_processor_id() >= port->priv->nthreads)
 		return;
 
 	val = MVPP2_CAUSE_MISC_SUM_MASK |
@@ -1129,7 +1129,7 @@
 
 	regmap_read(priv->sysctrl_base, GENCONF_CTRL0, &val);
 	if (port->gop_id == 2)
-		val |= GENCONF_CTRL0_PORT0_RGMII | GENCONF_CTRL0_PORT1_RGMII;
+		val |= GENCONF_CTRL0_PORT0_RGMII;
 	else if (port->gop_id == 3)
 		val |= GENCONF_CTRL0_PORT1_RGMII_MII;
 	regmap_write(priv->sysctrl_base, GENCONF_CTRL0, val);
@@ -1541,7 +1541,7 @@
 	for (q = 0; q < port->ntxqs; q++)
 		for (i = 0; i < ARRAY_SIZE(mvpp2_ethtool_txq_regs); i++)
 			*pstats++ += mvpp2_read_index(port->priv,
-						      MVPP22_CTRS_TX_CTR(port->id, i),
+						      MVPP22_CTRS_TX_CTR(port->id, q),
 						      mvpp2_ethtool_txq_regs[i].offset);
 
 	/* Rxqs are numbered from 0 from the user standpoint, but not from the
@@ -1550,7 +1550,7 @@
 	for (q = 0; q < port->nrxqs; q++)
 		for (i = 0; i < ARRAY_SIZE(mvpp2_ethtool_rxq_regs); i++)
 			*pstats++ += mvpp2_read_index(port->priv,
-						      port->first_rxq + i,
+						      port->first_rxq + q,
 						      mvpp2_ethtool_rxq_regs[i].offset);
 }
 
@@ -2078,7 +2078,7 @@
 	int queue;
 
 	/* If the thread isn't used, don't do anything */
-	if (smp_processor_id() > port->priv->nthreads)
+	if (smp_processor_id() >= port->priv->nthreads)
 		return;
 
 	for (queue = 0; queue < port->ntxqs; queue++) {
@@ -2161,17 +2161,18 @@
 static void mvpp2_tx_pkts_coal_set(struct mvpp2_port *port,
 				   struct mvpp2_tx_queue *txq)
 {
-	unsigned int thread = mvpp2_cpu_to_thread(port->priv, get_cpu());
+	unsigned int thread;
 	u32 val;
 
 	if (txq->done_pkts_coal > MVPP2_TXQ_THRESH_MASK)
 		txq->done_pkts_coal = MVPP2_TXQ_THRESH_MASK;
 
 	val = (txq->done_pkts_coal << MVPP2_TXQ_THRESH_OFFSET);
-	mvpp2_thread_write(port->priv, thread, MVPP2_TXQ_NUM_REG, txq->id);
-	mvpp2_thread_write(port->priv, thread, MVPP2_TXQ_THRESH_REG, val);
-
-	put_cpu();
+	/* PKT-coalescing registers are per-queue + per-thread */
+	for (thread = 0; thread < MVPP2_MAX_THREADS; thread++) {
+		mvpp2_thread_write(port->priv, thread, MVPP2_TXQ_NUM_REG, txq->id);
+		mvpp2_thread_write(port->priv, thread, MVPP2_TXQ_THRESH_REG, val);
+	}
 }
 
 static u32 mvpp2_usec_to_cycles(u32 usec, unsigned long clk_hz)
@@ -3674,7 +3675,7 @@
 		valid = true;
 	}
 
-	if (priv->hw_version == MVPP22 && port->link_irq && !port->phylink) {
+	if (priv->hw_version == MVPP22 && port->link_irq) {
 		err = request_irq(port->link_irq, mvpp2_link_status_isr, 0,
 				  dev->name, port);
 		if (err) {
@@ -3696,6 +3697,7 @@
 	if (!valid) {
 		netdev_err(port->dev,
 			   "invalid configuration: no dt or link IRQ");
+		err = -ENOENT;
 		goto err_free_irq;
 	}
 
@@ -4231,6 +4233,11 @@
 		break;
 	case ETHTOOL_GRXCLSRLALL:
 		for (i = 0; i < MVPP2_N_RFS_ENTRIES_PER_FLOW; i++) {
+			if (loc == info->rule_cnt) {
+				ret = -EMSGSIZE;
+				break;
+			}
+
 			if (port->rfs_rules[i])
 				rules[loc++] = i;
 		}
@@ -4319,6 +4326,8 @@
 
 	if (!mvpp22_rss_is_supported())
 		return -EOPNOTSUPP;
+	if (rss_context >= MVPP22_N_RSS_TABLES)
+		return -EINVAL;
 
 	if (hfunc)
 		*hfunc = ETH_RSS_HASH_CRC32;
@@ -4742,12 +4751,16 @@
 	eth_hw_addr_random(dev);
 }
 
+static struct mvpp2_port *mvpp2_phylink_to_port(struct phylink_config *config)
+{
+	return container_of(config, struct mvpp2_port, phylink_config);
+}
+
 static void mvpp2_phylink_validate(struct phylink_config *config,
 				   unsigned long *supported,
 				   struct phylink_link_state *state)
 {
-	struct mvpp2_port *port = container_of(config, struct mvpp2_port,
-					       phylink_config);
+	struct mvpp2_port *port = mvpp2_phylink_to_port(config);
 	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
 
 	/* Invalid combinations */
@@ -4770,8 +4783,6 @@
 
 	phylink_set(mask, Autoneg);
 	phylink_set_port_modes(mask);
-	phylink_set(mask, Pause);
-	phylink_set(mask, Asym_Pause);
 
 	switch (state->interface) {
 	case PHY_INTERFACE_MODE_10GKR:
@@ -4874,8 +4885,7 @@
 static int mvpp2_phylink_mac_link_state(struct phylink_config *config,
 					struct phylink_link_state *state)
 {
-	struct mvpp2_port *port = container_of(config, struct mvpp2_port,
-					       phylink_config);
+	struct mvpp2_port *port = mvpp2_phylink_to_port(config);
 
 	if (port->priv->hw_version == MVPP22 && port->gop_id == 0) {
 		u32 mode = readl(port->base + MVPP22_XLG_CTRL3_REG);
@@ -4893,8 +4903,7 @@
 
 static void mvpp2_mac_an_restart(struct phylink_config *config)
 {
-	struct mvpp2_port *port = container_of(config, struct mvpp2_port,
-					       phylink_config);
+	struct mvpp2_port *port = mvpp2_phylink_to_port(config);
 	u32 val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG);
 
 	writel(val | MVPP2_GMAC_IN_BAND_RESTART_AN,
@@ -5082,13 +5091,12 @@
 static void mvpp2_mac_config(struct phylink_config *config, unsigned int mode,
 			     const struct phylink_link_state *state)
 {
-	struct net_device *dev = to_net_dev(config->dev);
-	struct mvpp2_port *port = netdev_priv(dev);
+	struct mvpp2_port *port = mvpp2_phylink_to_port(config);
 	bool change_interface = port->phy_interface != state->interface;
 
 	/* Check for invalid configuration */
 	if (mvpp2_is_xlg(state->interface) && port->gop_id != 0) {
-		netdev_err(dev, "Invalid mode on %s\n", dev->name);
+		netdev_err(port->dev, "Invalid mode on %s\n", port->dev->name);
 		return;
 	}
 
@@ -5125,8 +5133,7 @@
 static void mvpp2_mac_link_up(struct phylink_config *config, unsigned int mode,
 			      phy_interface_t interface, struct phy_device *phy)
 {
-	struct net_device *dev = to_net_dev(config->dev);
-	struct mvpp2_port *port = netdev_priv(dev);
+	struct mvpp2_port *port = mvpp2_phylink_to_port(config);
 	u32 val;
 
 	if (!phylink_autoneg_inband(mode)) {
@@ -5147,14 +5154,13 @@
 
 	mvpp2_egress_enable(port);
 	mvpp2_ingress_enable(port);
-	netif_tx_wake_all_queues(dev);
+	netif_tx_wake_all_queues(port->dev);
 }
 
 static void mvpp2_mac_link_down(struct phylink_config *config,
 				unsigned int mode, phy_interface_t interface)
 {
-	struct net_device *dev = to_net_dev(config->dev);
-	struct mvpp2_port *port = netdev_priv(dev);
+	struct mvpp2_port *port = mvpp2_phylink_to_port(config);
 	u32 val;
 
 	if (!phylink_autoneg_inband(mode)) {
@@ -5171,7 +5177,7 @@
 		}
 	}
 
-	netif_tx_stop_all_queues(dev);
+	netif_tx_stop_all_queues(port->dev);
 	mvpp2_egress_disable(port);
 	mvpp2_ingress_disable(port);
 
@@ -5727,6 +5733,10 @@
 			return PTR_ERR(priv->lms_base);
 	} else {
 		res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+		if (!res) {
+			dev_err(&pdev->dev, "Invalid resource\n");
+			return -EINVAL;
+		}
 		if (has_acpi_companion(&pdev->dev)) {
 			/* In case the MDIO memory region is declared in
 			 * the ACPI, it can already appear as 'in-use'
@@ -5768,7 +5778,7 @@
 
 	shared = num_present_cpus() - priv->nthreads;
 	if (shared > 0)
-		bitmap_fill(&priv->lock_map,
+		bitmap_set(&priv->lock_map, 0,
 			    min_t(int, shared, MVPP2_MAX_THREADS));
 
 	for (i = 0; i < MVPP2_MAX_THREADS; i++) {
@@ -5897,6 +5907,8 @@
 	return 0;
 
 err_port_probe:
+	fwnode_handle_put(port_fwnode);
+
 	i = 0;
 	fwnode_for_each_available_child_node(fwnode, port_fwnode) {
 		if (priv->port_list[i])
@@ -5923,8 +5935,8 @@
 {
 	struct mvpp2 *priv = platform_get_drvdata(pdev);
 	struct fwnode_handle *fwnode = pdev->dev.fwnode;
+	int i = 0, poolnum = MVPP2_BM_POOLS_NUM;
 	struct fwnode_handle *port_fwnode;
-	int i = 0;
 
 	mvpp2_dbgfs_cleanup(priv);
 
@@ -5938,7 +5950,10 @@
 
 	destroy_workqueue(priv->stats_queue);
 
-	for (i = 0; i < MVPP2_BM_POOLS_NUM; i++) {
+	if (priv->percpu_pools)
+		poolnum = mvpp2_get_nrxqs(priv) * 2;
+
+	for (i = 0; i < poolnum; i++) {
 		struct mvpp2_bm_pool *bm_pool = &priv->bm_pools[i];
 
 		mvpp2_bm_pool_destroy(&pdev->dev, priv, bm_pool);
@@ -5994,7 +6009,18 @@
 	},
 };
 
-module_platform_driver(mvpp2_driver);
+static int __init mvpp2_driver_init(void)
+{
+	return platform_driver_register(&mvpp2_driver);
+}
+module_init(mvpp2_driver_init);
+
+static void __exit mvpp2_driver_exit(void)
+{
+	platform_driver_unregister(&mvpp2_driver);
+	mvpp2_dbgfs_exit();
+}
+module_exit(mvpp2_driver_exit);
 
 MODULE_DESCRIPTION("Marvell PPv2 Ethernet Driver - www.marvell.com");
 MODULE_AUTHOR("Marcin Wojtas <mw@semihalf.com>");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/marvell/mvpp2/mvpp2_prs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/marvell/mvpp2/mvpp2_prs.c
@@ -29,16 +29,16 @@
 	/* Clear entry invalidation bit */
 	pe->tcam[MVPP2_PRS_TCAM_INV_WORD] &= ~MVPP2_PRS_TCAM_INV_MASK;
 
-	/* Write tcam index - indirect access */
-	mvpp2_write(priv, MVPP2_PRS_TCAM_IDX_REG, pe->index);
-	for (i = 0; i < MVPP2_PRS_TCAM_WORDS; i++)
-		mvpp2_write(priv, MVPP2_PRS_TCAM_DATA_REG(i), pe->tcam[i]);
-
 	/* Write sram index - indirect access */
 	mvpp2_write(priv, MVPP2_PRS_SRAM_IDX_REG, pe->index);
 	for (i = 0; i < MVPP2_PRS_SRAM_WORDS; i++)
 		mvpp2_write(priv, MVPP2_PRS_SRAM_DATA_REG(i), pe->sram[i]);
 
+	/* Write tcam index - indirect access */
+	mvpp2_write(priv, MVPP2_PRS_TCAM_IDX_REG, pe->index);
+	for (i = 0; i < MVPP2_PRS_TCAM_WORDS; i++)
+		mvpp2_write(priv, MVPP2_PRS_TCAM_DATA_REG(i), pe->tcam[i]);
+
 	return 0;
 }
 
@@ -405,6 +405,38 @@
 	return -EINVAL;
 }
 
+/* Drop flow control pause frames */
+static void mvpp2_prs_drop_fc(struct mvpp2 *priv)
+{
+	unsigned char da[ETH_ALEN] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x01 };
+	struct mvpp2_prs_entry pe;
+	unsigned int len;
+
+	memset(&pe, 0, sizeof(pe));
+
+	/* For all ports - drop flow control frames */
+	pe.index = MVPP2_PE_FC_DROP;
+	mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_MAC);
+
+	/* Set match on DA */
+	len = ETH_ALEN;
+	while (len--)
+		mvpp2_prs_tcam_data_byte_set(&pe, len, da[len], 0xff);
+
+	mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_DROP_MASK,
+				 MVPP2_PRS_RI_DROP_MASK);
+
+	mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1);
+	mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
+
+	/* Mask all ports */
+	mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK);
+
+	/* Update shadow table and hw entry */
+	mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_MAC);
+	mvpp2_prs_hw_write(priv, &pe);
+}
+
 /* Enable/disable dropping all mac da's */
 static void mvpp2_prs_mac_drop_all_set(struct mvpp2 *priv, int port, bool add)
 {
@@ -1162,6 +1194,7 @@
 	mvpp2_prs_hw_write(priv, &pe);
 
 	/* Create dummy entries for drop all and promiscuous modes */
+	mvpp2_prs_drop_fc(priv);
 	mvpp2_prs_mac_drop_all_set(priv, 0, false);
 	mvpp2_prs_mac_promisc_set(priv, 0, MVPP2_PRS_L2_UNI_CAST, false);
 	mvpp2_prs_mac_promisc_set(priv, 0, MVPP2_PRS_L2_MULTI_CAST, false);
@@ -1647,8 +1680,9 @@
 	mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_IP6);
 	mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_IP6,
 				 MVPP2_PRS_RI_L3_PROTO_MASK);
-	/* Skip eth_type + 4 bytes of IPv6 header */
-	mvpp2_prs_sram_shift_set(&pe, MVPP2_ETH_TYPE_LEN + 4,
+	/* Jump to DIP of IPV6 header */
+	mvpp2_prs_sram_shift_set(&pe, MVPP2_ETH_TYPE_LEN + 8 +
+				 MVPP2_MAX_L3_ADDR_SIZE,
 				 MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
 	/* Set L3 offset */
 	mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L3,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/marvell/mvpp2/mvpp2_prs.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/marvell/mvpp2/mvpp2_prs.h
@@ -129,7 +129,7 @@
 #define MVPP2_PE_VID_EDSA_FLTR_DEFAULT	(MVPP2_PRS_TCAM_SRAM_SIZE - 7)
 #define MVPP2_PE_VLAN_DBL		(MVPP2_PRS_TCAM_SRAM_SIZE - 6)
 #define MVPP2_PE_VLAN_NONE		(MVPP2_PRS_TCAM_SRAM_SIZE - 5)
-/* reserved */
+#define MVPP2_PE_FC_DROP		(MVPP2_PRS_TCAM_SRAM_SIZE - 4)
 #define MVPP2_PE_MAC_MC_PROMISCUOUS	(MVPP2_PRS_TCAM_SRAM_SIZE - 3)
 #define MVPP2_PE_MAC_UC_PROMISCUOUS	(MVPP2_PRS_TCAM_SRAM_SIZE - 2)
 #define MVPP2_PE_MAC_NON_PROMISCUOUS	(MVPP2_PRS_TCAM_SRAM_SIZE - 1)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
@@ -582,7 +582,7 @@
 
 		/* Release thread waiting for completion  */
 		lmac->cmd_pend = false;
-		wake_up_interruptible(&lmac->wq_cmd_cmplt);
+		wake_up(&lmac->wq_cmd_cmplt);
 		break;
 	case CGX_EVT_ASYNC:
 		if (cgx_event_is_linkevent(event))
@@ -725,8 +725,10 @@
 		if (!lmac)
 			return -ENOMEM;
 		lmac->name = kcalloc(1, sizeof("cgx_fwi_xxx_yyy"), GFP_KERNEL);
-		if (!lmac->name)
-			return -ENOMEM;
+		if (!lmac->name) {
+			err = -ENOMEM;
+			goto err_lmac_free;
+		}
 		sprintf(lmac->name, "cgx_fwi_%d_%d", cgx->cgx_id, i);
 		lmac->lmac_id = i;
 		lmac->cgx = cgx;
@@ -737,7 +739,7 @@
 						 CGX_LMAC_FWI + i * 9),
 				   cgx_fwi_event_handler, 0, lmac->name, lmac);
 		if (err)
-			return err;
+			goto err_irq;
 
 		/* Enable interrupt */
 		cgx_write(cgx, lmac->lmac_id, CGXX_CMRX_INT_ENA_W1S,
@@ -748,6 +750,12 @@
 	}
 
 	return cgx_lmac_verify_fwi_version(cgx);
+
+err_irq:
+	kfree(lmac->name);
+err_lmac_free:
+	kfree(lmac);
+	return err;
 }
 
 static int cgx_lmac_exit(struct cgx *cgx)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/marvell/octeontx2/af/common.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/marvell/octeontx2/af/common.h
@@ -43,7 +43,7 @@
 	void            *base;
 	dma_addr_t	iova;
 	int		alloc_sz;
-	u8		entry_sz;
+	u16		entry_sz;
 	u8		align;
 	u32		qsize;
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/marvell/octeontx2/af/npc.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/marvell/octeontx2/af/npc.h
@@ -38,14 +38,18 @@
 	NPC_LT_LB_ITAG,
 };
 
+/* Don't modify ltypes up to IP6_EXT, otherwise length and checksum of IP
+ * headers may not be checked correctly. IPv4 ltypes and IPv6 ltypes must
+ * differ only at bit 0 so mask 0xE can be used to detect extended headers.
+ */
 enum npc_kpu_lc_ltype {
-	NPC_LT_LC_IP = 1,
+	NPC_LT_LC_PTP = 1,
+	NPC_LT_LC_IP,
 	NPC_LT_LC_IP6,
 	NPC_LT_LC_ARP,
 	NPC_LT_LC_RARP,
 	NPC_LT_LC_MPLS,
 	NPC_LT_LC_NSH,
-	NPC_LT_LC_PTP,
 	NPC_LT_LC_FCOE,
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
@@ -1124,7 +1124,7 @@
 		if (req->ssow > block->lf.max) {
 			dev_err(&rvu->pdev->dev,
 				"Func 0x%x: Invalid SSOW req, %d > max %d\n",
-				 pcifunc, req->sso, block->lf.max);
+				 pcifunc, req->ssow, block->lf.max);
 			return -EINVAL;
 		}
 		mappedlfs = rvu_get_rsrc_mapcount(pfvf, block->type);
@@ -1708,10 +1708,9 @@
 	}
 }
 
-static irqreturn_t rvu_mbox_intr_handler(int irq, void *rvu_irq)
+static irqreturn_t rvu_mbox_pf_intr_handler(int irq, void *rvu_irq)
 {
 	struct rvu *rvu = (struct rvu *)rvu_irq;
-	int vfs = rvu->vfs;
 	u64 intr;
 
 	intr = rvu_read64(rvu, BLKADDR_RVUM, RVU_AF_PFAF_MBOX_INT);
@@ -1723,13 +1722,25 @@
 
 	rvu_queue_work(&rvu->afpf_wq_info, 0, rvu->hw->total_pfs, intr);
 
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t rvu_mbox_intr_handler(int irq, void *rvu_irq)
+{
+	struct rvu *rvu = (struct rvu *)rvu_irq;
+	int vfs = rvu->vfs;
+	u64 intr;
+
+	/* Sync with mbox memory region */
+	rmb();
+
 	/* Handle VF interrupts */
 	if (vfs > 64) {
 		intr = rvupf_read64(rvu, RVU_PF_VFPF_MBOX_INTX(1));
 		rvupf_write64(rvu, RVU_PF_VFPF_MBOX_INTX(1), intr);
 
 		rvu_queue_work(&rvu->afvf_wq_info, 64, vfs, intr);
-		vfs -= 64;
+		vfs = 64;
 	}
 
 	intr = rvupf_read64(rvu, RVU_PF_VFPF_MBOX_INTX(0));
@@ -1980,8 +1991,10 @@
 		    INTR_MASK(rvu->hw->total_pfs) & ~1ULL);
 
 	for (irq = 0; irq < rvu->num_vec; irq++) {
-		if (rvu->irq_allocated[irq])
+		if (rvu->irq_allocated[irq]) {
 			free_irq(pci_irq_vector(rvu->pdev, irq), rvu);
+			rvu->irq_allocated[irq] = false;
+		}
 	}
 
 	pci_free_irq_vectors(rvu->pdev);
@@ -2033,7 +2046,7 @@
 	/* Register mailbox interrupt handler */
 	sprintf(&rvu->irq_name[RVU_AF_INT_VEC_MBOX * NAME_SIZE], "RVUAF Mbox");
 	ret = request_irq(pci_irq_vector(rvu->pdev, RVU_AF_INT_VEC_MBOX),
-			  rvu_mbox_intr_handler, 0,
+			  rvu_mbox_pf_intr_handler, 0,
 			  &rvu->irq_name[RVU_AF_INT_VEC_MBOX * NAME_SIZE], rvu);
 	if (ret) {
 		dev_err(rvu->dev,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
@@ -2430,9 +2430,10 @@
 	if (link < 0)
 		return NIX_AF_ERR_RX_LINK_INVALID;
 
-	nix_find_link_frs(rvu, req, pcifunc);
 
 linkcfg:
+	nix_find_link_frs(rvu, req, pcifunc);
+
 	cfg = rvu_read64(rvu, blkaddr, NIX_AF_RX_LINKX_CFG(link));
 	cfg = (cfg & ~(0xFFFFULL << 16)) | ((u64)req->maxlen << 16);
 	if (req->update_minlen)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
@@ -1967,10 +1967,10 @@
 		index = find_next_bit(mcam->bmap, mcam->bmap_entries, entry);
 		if (index >= mcam->bmap_entries)
 			break;
+		entry = index + 1;
 		if (mcam->entry2cntr_map[index] != req->cntr)
 			continue;
 
-		entry = index + 1;
 		npc_unmap_mcam_entry_and_cntr(rvu, mcam, blkaddr,
 					      index, req->cntr);
 	}
@@ -2013,10 +2013,11 @@
 		index = find_next_bit(mcam->bmap, mcam->bmap_entries, entry);
 		if (index >= mcam->bmap_entries)
 			break;
+		entry = index + 1;
+
 		if (mcam->entry2cntr_map[index] != req->cntr)
 			continue;
 
-		entry = index + 1;
 		npc_unmap_mcam_entry_and_cntr(rvu, mcam, blkaddr,
 					      index, req->cntr);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/marvell/pxa168_eth.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/marvell/pxa168_eth.c
@@ -1407,18 +1407,15 @@
 
 	printk(KERN_NOTICE "PXA168 10/100 Ethernet Driver\n");
 
-	clk = devm_clk_get(&pdev->dev, NULL);
+	clk = devm_clk_get_enabled(&pdev->dev, NULL);
 	if (IS_ERR(clk)) {
-		dev_err(&pdev->dev, "Fast Ethernet failed to get clock\n");
+		dev_err(&pdev->dev, "Fast Ethernet failed to get and enable clock\n");
 		return -ENODEV;
 	}
-	clk_prepare_enable(clk);
 
 	dev = alloc_etherdev(sizeof(struct pxa168_eth_private));
-	if (!dev) {
-		err = -ENOMEM;
-		goto err_clk;
-	}
+	if (!dev)
+		return -ENOMEM;
 
 	platform_set_drvdata(pdev, dev);
 	pep = netdev_priv(dev);
@@ -1531,8 +1528,6 @@
 	mdiobus_free(pep->smi_bus);
 err_netdev:
 	free_netdev(dev);
-err_clk:
-	clk_disable_unprepare(clk);
 	return err;
 }
 
@@ -1554,8 +1549,8 @@
 
 	mdiobus_unregister(pep->smi_bus);
 	mdiobus_free(pep->smi_bus);
-	unregister_netdev(dev);
 	cancel_work_sync(&pep->tx_timeout_task);
+	unregister_netdev(dev);
 	free_netdev(dev);
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/marvell/sky2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/marvell/sky2.c
@@ -130,6 +130,7 @@
 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436C) }, /* 88E8072 */
 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436D) }, /* 88E8055 */
 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4370) }, /* 88E8075 */
+	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4373) }, /* 88E8075 */
 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4380) }, /* 88E8057 */
 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4381) }, /* 88E8059 */
 	{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4382) }, /* 88E8079 */
@@ -203,7 +204,7 @@
 
 static inline u16 gm_phy_read(struct sky2_hw *hw, unsigned port, u16 reg)
 {
-	u16 v;
+	u16 v = 0;
 	__gm_phy_read(hw, port, reg, &v);
 	return v;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/marvell/sky2.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/marvell/sky2.h
@@ -2201,7 +2201,7 @@
 	struct sk_buff	*skb;
 	dma_addr_t	data_addr;
 	DEFINE_DMA_UNMAP_LEN(data_size);
-	dma_addr_t	frag_addr[ETH_JUMBO_MTU >> PAGE_SHIFT];
+	dma_addr_t	frag_addr[ETH_JUMBO_MTU >> PAGE_SHIFT ?: 1];
 };
 
 enum flow_control {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -65,6 +65,17 @@
 	return __raw_readl(eth->base + reg);
 }
 
+u32 mtk_m32(struct mtk_eth *eth, u32 mask, u32 set, unsigned reg)
+{
+	u32 val;
+
+	val = mtk_r32(eth, reg);
+	val &= ~mask;
+	val |= set;
+	mtk_w32(eth, val, reg);
+	return reg;
+}
+
 static int mtk_mdio_busy_wait(struct mtk_eth *eth)
 {
 	unsigned long t_start = jiffies;
@@ -160,11 +171,21 @@
 	return 0;
 }
 
-static void mtk_gmac0_rgmii_adjust(struct mtk_eth *eth, int speed)
+static void mtk_gmac0_rgmii_adjust(struct mtk_eth *eth,
+				   phy_interface_t interface, int speed)
 {
 	u32 val;
 	int ret;
 
+	if (interface == PHY_INTERFACE_MODE_TRGMII) {
+		mtk_w32(eth, TRGMII_MODE, INTF_MODE);
+		val = 500000000;
+		ret = clk_set_rate(eth->clks[MTK_CLK_TRGPLL], val);
+		if (ret)
+			dev_err(eth->dev, "Failed to set trgmii pll: %d\n", ret);
+		return;
+	}
+
 	val = (speed == SPEED_1000) ?
 		INTF_MODE_RGMII_1000 : INTF_MODE_RGMII_10_100;
 	mtk_w32(eth, val, INTF_MODE);
@@ -193,8 +214,8 @@
 	struct mtk_mac *mac = container_of(config, struct mtk_mac,
 					   phylink_config);
 	struct mtk_eth *eth = mac->hw;
-	u32 mcr_cur, mcr_new, sid;
-	int val, ge_mode, err;
+	u32 mcr_cur, mcr_new, sid, i;
+	int val, ge_mode, err = 0;
 
 	/* MT76x8 has no hardware settings between for the MAC */
 	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628) &&
@@ -251,10 +272,20 @@
 							      state->interface))
 					goto err_phy;
 			} else {
-				if (state->interface !=
-				    PHY_INTERFACE_MODE_TRGMII)
-					mtk_gmac0_rgmii_adjust(mac->hw,
-							       state->speed);
+				mtk_gmac0_rgmii_adjust(mac->hw,
+						       state->interface,
+						       state->speed);
+
+				/* mt7623_pad_clk_setup */
+				for (i = 0 ; i < NUM_TRGMII_CTRL; i++)
+					mtk_w32(mac->hw,
+						TD_DM_DRVP(8) | TD_DM_DRVN(8),
+						TRGMII_TD_ODT(i));
+
+				/* Assert/release MT7623 RXC reset */
+				mtk_m32(mac->hw, 0, RXC_RST | RXC_DQSISEL,
+					TRGMII_RCK_CTRL);
+				mtk_m32(mac->hw, RXC_RST, 0, TRGMII_RCK_CTRL);
 			}
 		}
 
@@ -644,32 +675,53 @@
 void mtk_stats_update_mac(struct mtk_mac *mac)
 {
 	struct mtk_hw_stats *hw_stats = mac->hw_stats;
-	unsigned int base = MTK_GDM1_TX_GBCNT;
-	u64 stats;
-
-	base += hw_stats->reg_offset;
+	struct mtk_eth *eth = mac->hw;
 
 	u64_stats_update_begin(&hw_stats->syncp);
 
-	hw_stats->rx_bytes += mtk_r32(mac->hw, base);
-	stats =  mtk_r32(mac->hw, base + 0x04);
-	if (stats)
-		hw_stats->rx_bytes += (stats << 32);
-	hw_stats->rx_packets += mtk_r32(mac->hw, base + 0x08);
-	hw_stats->rx_overflow += mtk_r32(mac->hw, base + 0x10);
-	hw_stats->rx_fcs_errors += mtk_r32(mac->hw, base + 0x14);
-	hw_stats->rx_short_errors += mtk_r32(mac->hw, base + 0x18);
-	hw_stats->rx_long_errors += mtk_r32(mac->hw, base + 0x1c);
-	hw_stats->rx_checksum_errors += mtk_r32(mac->hw, base + 0x20);
-	hw_stats->rx_flow_control_packets +=
-					mtk_r32(mac->hw, base + 0x24);
-	hw_stats->tx_skip += mtk_r32(mac->hw, base + 0x28);
-	hw_stats->tx_collisions += mtk_r32(mac->hw, base + 0x2c);
-	hw_stats->tx_bytes += mtk_r32(mac->hw, base + 0x30);
-	stats =  mtk_r32(mac->hw, base + 0x34);
-	if (stats)
-		hw_stats->tx_bytes += (stats << 32);
-	hw_stats->tx_packets += mtk_r32(mac->hw, base + 0x38);
+	if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) {
+		hw_stats->tx_packets += mtk_r32(mac->hw, MT7628_SDM_TPCNT);
+		hw_stats->tx_bytes += mtk_r32(mac->hw, MT7628_SDM_TBCNT);
+		hw_stats->rx_packets += mtk_r32(mac->hw, MT7628_SDM_RPCNT);
+		hw_stats->rx_bytes += mtk_r32(mac->hw, MT7628_SDM_RBCNT);
+		hw_stats->rx_checksum_errors +=
+			mtk_r32(mac->hw, MT7628_SDM_CS_ERR);
+	} else {
+		unsigned int offs = hw_stats->reg_offset;
+		u64 stats;
+
+		hw_stats->rx_bytes += mtk_r32(mac->hw,
+					      MTK_GDM1_RX_GBCNT_L + offs);
+		stats = mtk_r32(mac->hw, MTK_GDM1_RX_GBCNT_H + offs);
+		if (stats)
+			hw_stats->rx_bytes += (stats << 32);
+		hw_stats->rx_packets +=
+			mtk_r32(mac->hw, MTK_GDM1_RX_GPCNT + offs);
+		hw_stats->rx_overflow +=
+			mtk_r32(mac->hw, MTK_GDM1_RX_OERCNT + offs);
+		hw_stats->rx_fcs_errors +=
+			mtk_r32(mac->hw, MTK_GDM1_RX_FERCNT + offs);
+		hw_stats->rx_short_errors +=
+			mtk_r32(mac->hw, MTK_GDM1_RX_SERCNT + offs);
+		hw_stats->rx_long_errors +=
+			mtk_r32(mac->hw, MTK_GDM1_RX_LENCNT + offs);
+		hw_stats->rx_checksum_errors +=
+			mtk_r32(mac->hw, MTK_GDM1_RX_CERCNT + offs);
+		hw_stats->rx_flow_control_packets +=
+			mtk_r32(mac->hw, MTK_GDM1_RX_FCCNT + offs);
+		hw_stats->tx_skip +=
+			mtk_r32(mac->hw, MTK_GDM1_TX_SKIPCNT + offs);
+		hw_stats->tx_collisions +=
+			mtk_r32(mac->hw, MTK_GDM1_TX_COLCNT + offs);
+		hw_stats->tx_bytes +=
+			mtk_r32(mac->hw, MTK_GDM1_TX_GBCNT_L + offs);
+		stats =  mtk_r32(mac->hw, MTK_GDM1_TX_GBCNT_H + offs);
+		if (stats)
+			hw_stats->tx_bytes += (stats << 32);
+		hw_stats->tx_packets +=
+			mtk_r32(mac->hw, MTK_GDM1_TX_GPCNT + offs);
+	}
+
 	u64_stats_update_end(&hw_stats->syncp);
 }
 
@@ -750,6 +802,17 @@
 	rxd->rxd4 = READ_ONCE(dma_rxd->rxd4);
 }
 
+static void *mtk_max_lro_buf_alloc(gfp_t gfp_mask)
+{
+	unsigned int size = mtk_max_frag_size(MTK_MAX_LRO_RX_LENGTH);
+	unsigned long data;
+
+	data = __get_free_pages(gfp_mask | __GFP_COMP | __GFP_NOWARN,
+				get_order(size));
+
+	return (void *)data;
+}
+
 /* the qdma core needs scratch memory to be setup */
 static int mtk_init_fq_dma(struct mtk_eth *eth)
 {
@@ -1247,7 +1310,10 @@
 			goto release_desc;
 
 		/* alloc new buffer */
-		new_data = napi_alloc_frag(ring->frag_size);
+		if (ring->frag_size <= PAGE_SIZE)
+			new_data = napi_alloc_frag(ring->frag_size);
+		else
+			new_data = mtk_max_lro_buf_alloc(GFP_ATOMIC);
 		if (unlikely(!new_data)) {
 			netdev->stats.rx_dropped++;
 			goto release_desc;
@@ -1284,7 +1350,7 @@
 		skb->protocol = eth_type_trans(skb, netdev);
 
 		if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX &&
-		    RX_DMA_VID(trxd.rxd3))
+		    (trxd.rxd2 & RX_DMA_VTAG))
 			__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
 					       RX_DMA_VID(trxd.rxd3));
 		skb_record_rx_queue(skb, 0);
@@ -1644,7 +1710,10 @@
 		return -ENOMEM;
 
 	for (i = 0; i < rx_dma_size; i++) {
-		ring->data[i] = netdev_alloc_frag(ring->frag_size);
+		if (ring->frag_size <= PAGE_SIZE)
+			ring->data[i] = netdev_alloc_frag(ring->frag_size);
+		else
+			ring->data[i] = mtk_max_lro_buf_alloc(GFP_KERNEL);
 		if (!ring->data[i])
 			return -ENOMEM;
 	}
@@ -1910,6 +1979,9 @@
 	struct ethtool_rx_flow_spec *fsp =
 		(struct ethtool_rx_flow_spec *)&cmd->fs;
 
+	if (fsp->location >= ARRAY_SIZE(mac->hwlro_ip))
+		return -EINVAL;
+
 	/* only tcp dst ipv4 is meaningful, others are meaningless */
 	fsp->flow_type = TCP_V4_FLOW;
 	fsp->h_u.tcp_ip4_spec.ip4dst = ntohl(mac->hwlro_ip[fsp->location]);
@@ -1936,6 +2008,9 @@
 	int i;
 
 	for (i = 0; i < MTK_MAX_LRO_IP_CNT; i++) {
+		if (cnt == cmd->rule_cnt)
+			return -EMSGSIZE;
+
 		if (mac->hwlro_ip[i]) {
 			rule_locs[cnt] = i;
 			cnt++;
@@ -2847,6 +2922,8 @@
 	eth->netdev[id]->irq = eth->irq[0];
 	eth->netdev[id]->dev.of_node = np;
 
+	eth->netdev[id]->max_mtu = MTK_MAX_RX_LENGTH - MTK_RX_ETH_HLEN;
+
 	return 0;
 
 free_netdev:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -264,8 +264,21 @@
 /* QDMA FQ Free Page Buffer Length Register */
 #define MTK_QDMA_FQ_BLEN	0x1B2C
 
-/* GMA1 Received Good Byte Count Register */
-#define MTK_GDM1_TX_GBCNT	0x2400
+/* GMA1 counter / statics register */
+#define MTK_GDM1_RX_GBCNT_L	0x2400
+#define MTK_GDM1_RX_GBCNT_H	0x2404
+#define MTK_GDM1_RX_GPCNT	0x2408
+#define MTK_GDM1_RX_OERCNT	0x2410
+#define MTK_GDM1_RX_FERCNT	0x2414
+#define MTK_GDM1_RX_SERCNT	0x2418
+#define MTK_GDM1_RX_LENCNT	0x241c
+#define MTK_GDM1_RX_CERCNT	0x2420
+#define MTK_GDM1_RX_FCCNT	0x2424
+#define MTK_GDM1_TX_SKIPCNT	0x2428
+#define MTK_GDM1_TX_COLCNT	0x242c
+#define MTK_GDM1_TX_GBCNT_L	0x2430
+#define MTK_GDM1_TX_GBCNT_H	0x2434
+#define MTK_GDM1_TX_GPCNT	0x2438
 #define MTK_STAT_OFFSET		0x40
 
 /* QDMA descriptor txd4 */
@@ -293,6 +306,7 @@
 #define RX_DMA_LSO		BIT(30)
 #define RX_DMA_PLEN0(_x)	(((_x) & 0x3fff) << 16)
 #define RX_DMA_GET_PLEN0(_x)	(((_x) >> 16) & 0x3fff)
+#define RX_DMA_VTAG		BIT(15)
 
 /* QDMA descriptor rxd3 */
 #define RX_DMA_VID(_x)		((_x) & 0xfff)
@@ -350,10 +364,13 @@
 #define DQSI0(x)		((x << 0) & GENMASK(6, 0))
 #define DQSI1(x)		((x << 8) & GENMASK(14, 8))
 #define RXCTL_DMWTLAT(x)	((x << 16) & GENMASK(18, 16))
+#define RXC_RST			BIT(31)
 #define RXC_DQSISEL		BIT(30)
 #define RCK_CTRL_RGMII_1000	(RXC_DQSISEL | RXCTL_DMWTLAT(2) | DQSI1(16))
 #define RCK_CTRL_RGMII_10_100	RXCTL_DMWTLAT(2)
 
+#define NUM_TRGMII_CTRL		5
+
 /* TRGMII RXC control register */
 #define TRGMII_TCK_CTRL		0x10340
 #define TXCTL_DMWTLAT(x)	((x << 16) & GENMASK(18, 16))
@@ -361,6 +378,11 @@
 #define TCK_CTRL_RGMII_1000	TXCTL_DMWTLAT(2)
 #define TCK_CTRL_RGMII_10_100	(TXC_INV | TXCTL_DMWTLAT(2))
 
+/* TRGMII TX Drive Strength */
+#define TRGMII_TD_ODT(i)	(0x10354 + 8 * (i))
+#define  TD_DM_DRVP(x)		((x) & 0xf)
+#define  TD_DM_DRVN(x)		(((x) & 0xf) << 4)
+
 /* TRGMII Interface mode register */
 #define INTF_MODE		0x10390
 #define TRGMII_INTF_DIS		BIT(0)
@@ -467,6 +489,13 @@
 #define MT7628_SDM_MAC_ADRL	(MT7628_SDM_OFFSET + 0x0c)
 #define MT7628_SDM_MAC_ADRH	(MT7628_SDM_OFFSET + 0x10)
 
+/* Counter / stat register */
+#define MT7628_SDM_TPCNT	(MT7628_SDM_OFFSET + 0x100)
+#define MT7628_SDM_TBCNT	(MT7628_SDM_OFFSET + 0x104)
+#define MT7628_SDM_RPCNT	(MT7628_SDM_OFFSET + 0x108)
+#define MT7628_SDM_RBCNT	(MT7628_SDM_OFFSET + 0x10c)
+#define MT7628_SDM_CS_ERR	(MT7628_SDM_OFFSET + 0x110)
+
 struct mtk_rx_dma {
 	unsigned int rxd1;
 	unsigned int rxd2;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mediatek/mtk_sgmii.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mediatek/mtk_sgmii.c
@@ -26,6 +26,7 @@
 			break;
 
 		ss->regmap[i] = syscon_node_to_regmap(np);
+		of_node_put(np);
 		if (IS_ERR(ss->regmap[i]))
 			return PTR_ERR(ss->regmap[i]);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
@@ -47,7 +47,7 @@
 #define EN_ETHTOOL_SHORT_MASK cpu_to_be16(0xffff)
 #define EN_ETHTOOL_WORD_MASK  cpu_to_be32(0xffffffff)
 
-static int mlx4_en_moderation_update(struct mlx4_en_priv *priv)
+int mlx4_en_moderation_update(struct mlx4_en_priv *priv)
 {
 	int i, t;
 	int err = 0;
@@ -663,7 +663,7 @@
 	MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_1000BASE_T, SPEED_1000,
 				       ETHTOOL_LINK_MODE_1000baseT_Full_BIT);
 	MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_1000BASE_CX_SGMII, SPEED_1000,
-				       ETHTOOL_LINK_MODE_1000baseKX_Full_BIT);
+				       ETHTOOL_LINK_MODE_1000baseX_Full_BIT);
 	MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_1000BASE_KX, SPEED_1000,
 				       ETHTOOL_LINK_MODE_1000baseKX_Full_BIT);
 	MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_10GBASE_T, SPEED_10000,
@@ -675,9 +675,9 @@
 	MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_10GBASE_KR, SPEED_10000,
 				       ETHTOOL_LINK_MODE_10000baseKR_Full_BIT);
 	MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_10GBASE_CR, SPEED_10000,
-				       ETHTOOL_LINK_MODE_10000baseKR_Full_BIT);
+				       ETHTOOL_LINK_MODE_10000baseCR_Full_BIT);
 	MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_10GBASE_SR, SPEED_10000,
-				       ETHTOOL_LINK_MODE_10000baseKR_Full_BIT);
+				       ETHTOOL_LINK_MODE_10000baseSR_Full_BIT);
 	MLX4_BUILD_PTYS2ETHTOOL_CONFIG(MLX4_20GBASE_KR2, SPEED_20000,
 				       ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT,
 				       ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT);
@@ -2011,8 +2011,6 @@
 	return ret;
 }
 
-#define MLX4_EEPROM_PAGE_LEN 256
-
 static int mlx4_en_get_module_info(struct net_device *dev,
 				   struct ethtool_modinfo *modinfo)
 {
@@ -2047,7 +2045,7 @@
 		break;
 	case MLX4_MODULE_ID_SFP:
 		modinfo->type = ETH_MODULE_SFF_8472;
-		modinfo->eeprom_len = MLX4_EEPROM_PAGE_LEN;
+		modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
 		break;
 	default:
 		return -EINVAL;
@@ -2085,7 +2083,7 @@
 			en_err(priv,
 			       "mlx4_get_module_info i(%d) offset(%d) bytes_to_read(%d) - FAILED (0x%x)\n",
 			       i, offset, ee->len - i, ret);
-			return 0;
+			return ret;
 		}
 
 		i += ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -371,6 +371,9 @@
 	int nhoff = skb_network_offset(skb);
 	int ret = 0;
 
+	if (skb->encapsulation)
+		return -EPROTONOSUPPORT;
+
 	if (skb->protocol != htons(ETH_P_IP))
 		return -EPROTONOSUPPORT;
 
@@ -1383,8 +1386,10 @@
 	}
 
 	priv->port_stats.tx_timeout++;
-	en_dbg(DRV, priv, "Scheduling watchdog\n");
-	queue_work(mdev->workqueue, &priv->watchdog_task);
+	if (!test_and_set_bit(MLX4_EN_STATE_FLAG_RESTARTING, &priv->state)) {
+		en_dbg(DRV, priv, "Scheduling port restart\n");
+		queue_work(mdev->workqueue, &priv->restart_task);
+	}
 }
 
 
@@ -1738,6 +1743,7 @@
 				mlx4_en_deactivate_cq(priv, cq);
 				goto tx_err;
 			}
+			clear_bit(MLX4_EN_TX_RING_STATE_RECOVERING, &tx_ring->state);
 			if (t != TX_XDP) {
 				tx_ring->tx_queue = netdev_get_tx_queue(dev, i);
 				tx_ring->recycle_ring = NULL;
@@ -1834,6 +1840,7 @@
 		local_bh_enable();
 	}
 
+	clear_bit(MLX4_EN_STATE_FLAG_RESTARTING, &priv->state);
 	netif_tx_start_all_queues(dev);
 	netif_device_attach(dev);
 
@@ -2004,7 +2011,7 @@
 static void mlx4_en_restart(struct work_struct *work)
 {
 	struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv,
-						 watchdog_task);
+						 restart_task);
 	struct mlx4_en_dev *mdev = priv->mdev;
 	struct net_device *dev = priv->dev;
 
@@ -2274,9 +2281,14 @@
 				bool carry_xdp_prog)
 {
 	struct bpf_prog *xdp_prog;
-	int i, t;
+	int i, t, ret;
 
-	mlx4_en_copy_priv(tmp, priv, prof);
+	ret = mlx4_en_copy_priv(tmp, priv, prof);
+	if (ret) {
+		en_warn(priv, "%s: mlx4_en_copy_priv() failed, return\n",
+			__func__);
+		return ret;
+	}
 
 	if (mlx4_en_alloc_resources(tmp)) {
 		en_warn(priv,
@@ -2386,7 +2398,7 @@
 	if (netif_running(dev)) {
 		mutex_lock(&mdev->state_lock);
 		if (!mdev->device_up) {
-			/* NIC is probably restarting - let watchdog task reset
+			/* NIC is probably restarting - let restart task reset
 			 * the port */
 			en_dbg(DRV, priv, "Change MTU called with card down!?\n");
 		} else {
@@ -2395,7 +2407,9 @@
 			if (err) {
 				en_err(priv, "Failed restarting port:%d\n",
 					 priv->port);
-				queue_work(mdev->workqueue, &priv->watchdog_task);
+				if (!test_and_set_bit(MLX4_EN_STATE_FLAG_RESTARTING,
+						      &priv->state))
+					queue_work(mdev->workqueue, &priv->restart_task);
 			}
 		}
 		mutex_unlock(&mdev->state_lock);
@@ -2865,7 +2879,8 @@
 		if (err) {
 			en_err(priv, "Failed starting port %d for XDP change\n",
 			       priv->port);
-			queue_work(mdev->workqueue, &priv->watchdog_task);
+			if (!test_and_set_bit(MLX4_EN_STATE_FLAG_RESTARTING, &priv->state))
+				queue_work(mdev->workqueue, &priv->restart_task);
 		}
 	}
 
@@ -3263,7 +3278,7 @@
 	priv->counter_index = MLX4_SINK_COUNTER_INDEX(mdev->dev);
 	spin_lock_init(&priv->stats_lock);
 	INIT_WORK(&priv->rx_mode_task, mlx4_en_do_set_rx_mode);
-	INIT_WORK(&priv->watchdog_task, mlx4_en_restart);
+	INIT_WORK(&priv->restart_task, mlx4_en_restart);
 	INIT_WORK(&priv->linkstate_task, mlx4_en_linkstate);
 	INIT_DELAYED_WORK(&priv->stats_task, mlx4_en_do_get_stats);
 	INIT_DELAYED_WORK(&priv->service_task, mlx4_en_service_task);
@@ -3650,6 +3665,8 @@
 			en_err(priv, "Failed starting port\n");
 	}
 
+	if (!err)
+		err = mlx4_en_moderation_update(priv);
 out:
 	mutex_unlock(&mdev->state_lock);
 	kfree(tmp);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx4/en_rx.c
@@ -942,6 +942,9 @@
 	bool clean_complete = true;
 	int done;
 
+	if (!budget)
+		return 0;
+
 	if (priv->tx_ring_num[TX_XDP]) {
 		xdp_tx_cq = priv->tx_cq[TX_XDP][cq->ring];
 		if (xdp_tx_cq->xdp_busy) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx4/en_tx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx4/en_tx.c
@@ -43,6 +43,7 @@
 #include <linux/ip.h>
 #include <linux/ipv6.h>
 #include <linux/moduleparam.h>
+#include <linux/indirect_call_wrapper.h>
 
 #include "mlx4_en.h"
 
@@ -261,6 +262,10 @@
 	}
 }
 
+INDIRECT_CALLABLE_DECLARE(u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv,
+						   struct mlx4_en_tx_ring *ring,
+						   int index, u64 timestamp,
+						   int napi_mode));
 
 u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv,
 			 struct mlx4_en_tx_ring *ring,
@@ -329,6 +334,11 @@
 	return tx_info->nr_txbb;
 }
 
+INDIRECT_CALLABLE_DECLARE(u32 mlx4_en_recycle_tx_desc(struct mlx4_en_priv *priv,
+						      struct mlx4_en_tx_ring *ring,
+						      int index, u64 timestamp,
+						      int napi_mode));
+
 u32 mlx4_en_recycle_tx_desc(struct mlx4_en_priv *priv,
 			    struct mlx4_en_tx_ring *ring,
 			    int index, u64 timestamp,
@@ -340,7 +350,7 @@
 		.dma = tx_info->map0_dma,
 	};
 
-	if (!mlx4_en_rx_recycle(ring->recycle_ring, &frame)) {
+	if (!napi_mode || !mlx4_en_rx_recycle(ring->recycle_ring, &frame)) {
 		dma_unmap_page(priv->ddev, tx_info->map0_dma,
 			       PAGE_SIZE, priv->dma_dir);
 		put_page(tx_info->page);
@@ -382,6 +392,35 @@
 	return cnt;
 }
 
+static void mlx4_en_handle_err_cqe(struct mlx4_en_priv *priv, struct mlx4_err_cqe *err_cqe,
+				   u16 cqe_index, struct mlx4_en_tx_ring *ring)
+{
+	struct mlx4_en_dev *mdev = priv->mdev;
+	struct mlx4_en_tx_info *tx_info;
+	struct mlx4_en_tx_desc *tx_desc;
+	u16 wqe_index;
+	int desc_size;
+
+	en_err(priv, "CQE error - cqn 0x%x, ci 0x%x, vendor syndrome: 0x%x syndrome: 0x%x\n",
+	       ring->sp_cqn, cqe_index, err_cqe->vendor_err_syndrome, err_cqe->syndrome);
+	print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 16, 1, err_cqe, sizeof(*err_cqe),
+		       false);
+
+	wqe_index = be16_to_cpu(err_cqe->wqe_index) & ring->size_mask;
+	tx_info = &ring->tx_info[wqe_index];
+	desc_size = tx_info->nr_txbb << LOG_TXBB_SIZE;
+	en_err(priv, "Related WQE - qpn 0x%x, wqe index 0x%x, wqe size 0x%x\n", ring->qpn,
+	       wqe_index, desc_size);
+	tx_desc = ring->buf + (wqe_index << LOG_TXBB_SIZE);
+	print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 16, 1, tx_desc, desc_size, false);
+
+	if (test_and_set_bit(MLX4_EN_STATE_FLAG_RESTARTING, &priv->state))
+		return;
+
+	en_err(priv, "Scheduling port restart\n");
+	queue_work(mdev->workqueue, &priv->restart_task);
+}
+
 bool mlx4_en_process_tx_cq(struct net_device *dev,
 			   struct mlx4_en_cq *cq, int napi_budget)
 {
@@ -428,13 +467,10 @@
 		dma_rmb();
 
 		if (unlikely((cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) ==
-			     MLX4_CQE_OPCODE_ERROR)) {
-			struct mlx4_err_cqe *cqe_err = (struct mlx4_err_cqe *)cqe;
-
-			en_err(priv, "CQE error - vendor syndrome: 0x%x syndrome: 0x%x\n",
-			       cqe_err->vendor_err_syndrome,
-			       cqe_err->syndrome);
-		}
+			     MLX4_CQE_OPCODE_ERROR))
+			if (!test_and_set_bit(MLX4_EN_TX_RING_STATE_RECOVERING, &ring->state))
+				mlx4_en_handle_err_cqe(priv, (struct mlx4_err_cqe *)cqe, index,
+						       ring);
 
 		/* Skip over last polled CQE */
 		new_index = be16_to_cpu(cqe->wqe_index) & size_mask;
@@ -449,7 +485,9 @@
 				timestamp = mlx4_en_get_cqe_ts(cqe);
 
 			/* free next descriptor */
-			last_nr_txbb = ring->free_tx_desc(
+			last_nr_txbb = INDIRECT_CALL_2(ring->free_tx_desc,
+						       mlx4_en_free_tx_desc,
+						       mlx4_en_recycle_tx_desc,
 					priv, ring, ring_index,
 					timestamp, napi_budget);
 
@@ -830,6 +868,7 @@
 	struct mlx4_en_tx_desc *tx_desc;
 	struct mlx4_wqe_data_seg *data;
 	struct mlx4_en_tx_info *tx_info;
+	u32 __maybe_unused ring_cons;
 	int tx_ind;
 	int nr_txbb;
 	int desc_size;
@@ -843,7 +882,6 @@
 	bool stop_queue;
 	bool inline_ok;
 	u8 data_offset;
-	u32 ring_cons;
 	bool bf_ok;
 
 	tx_ind = skb_get_queue_mapping(skb);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx4/fw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx4/fw.c
@@ -823,6 +823,7 @@
 #define QUERY_DEV_CAP_MAD_DEMUX_OFFSET		0xb0
 #define QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_BASE_OFFSET	0xa8
 #define QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_RANGE_OFFSET	0xac
+#define QUERY_DEV_CAP_MAP_CLOCK_TO_USER 0xc1
 #define QUERY_DEV_CAP_QP_RATE_LIMIT_NUM_OFFSET	0xcc
 #define QUERY_DEV_CAP_QP_RATE_LIMIT_MAX_OFFSET	0xd0
 #define QUERY_DEV_CAP_QP_RATE_LIMIT_MIN_OFFSET	0xd2
@@ -841,6 +842,8 @@
 
 	if (mlx4_is_mfunc(dev))
 		disable_unsupported_roce_caps(outbox);
+	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAP_CLOCK_TO_USER);
+	dev_cap->map_clock_to_user = field & 0x80;
 	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_QP_OFFSET);
 	dev_cap->reserved_qps = 1 << (field & 0xf);
 	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_QP_OFFSET);
@@ -1864,8 +1867,8 @@
 #define	 INIT_HCA_LOG_RD_OFFSET		 (INIT_HCA_QPC_OFFSET + 0x77)
 #define INIT_HCA_MCAST_OFFSET		 0x0c0
 #define	 INIT_HCA_MC_BASE_OFFSET	 (INIT_HCA_MCAST_OFFSET + 0x00)
-#define	 INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x12)
-#define	 INIT_HCA_LOG_MC_HASH_SZ_OFFSET	 (INIT_HCA_MCAST_OFFSET + 0x16)
+#define	 INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x13)
+#define	 INIT_HCA_LOG_MC_HASH_SZ_OFFSET	 (INIT_HCA_MCAST_OFFSET + 0x17)
 #define  INIT_HCA_UC_STEERING_OFFSET	 (INIT_HCA_MCAST_OFFSET + 0x18)
 #define	 INIT_HCA_LOG_MC_TABLE_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x1b)
 #define  INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN	0x6
@@ -1873,7 +1876,7 @@
 #define  INIT_HCA_DRIVER_VERSION_SZ       0x40
 #define  INIT_HCA_FS_PARAM_OFFSET         0x1d0
 #define  INIT_HCA_FS_BASE_OFFSET          (INIT_HCA_FS_PARAM_OFFSET + 0x00)
-#define  INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET  (INIT_HCA_FS_PARAM_OFFSET + 0x12)
+#define  INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET  (INIT_HCA_FS_PARAM_OFFSET + 0x13)
 #define  INIT_HCA_FS_A0_OFFSET		  (INIT_HCA_FS_PARAM_OFFSET + 0x18)
 #define  INIT_HCA_FS_LOG_TABLE_SZ_OFFSET  (INIT_HCA_FS_PARAM_OFFSET + 0x1b)
 #define  INIT_HCA_FS_ETH_BITS_OFFSET      (INIT_HCA_FS_PARAM_OFFSET + 0x21)
@@ -2734,7 +2737,7 @@
 		if (err) {
 			mlx4_err(dev, "Failed to retrieve required operation: %d\n",
 				 err);
-			return;
+			goto out;
 		}
 		MLX4_GET(modifier, outbox, GET_OP_REQ_MODIFIER_OFFSET);
 		MLX4_GET(token, outbox, GET_OP_REQ_TOKEN_OFFSET);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx4/fw.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx4/fw.h
@@ -131,6 +131,7 @@
 	u32 health_buffer_addrs;
 	struct mlx4_port_cap port_cap[MLX4_MAX_PORTS + 1];
 	bool wol_port[MLX4_MAX_PORTS + 1];
+	bool map_clock_to_user;
 };
 
 struct mlx4_func_cap {
@@ -182,8 +183,8 @@
 	u64 cmpt_base;
 	u64 mtt_base;
 	u64 global_caps;
-	u16 log_mc_entry_sz;
-	u16 log_mc_hash_sz;
+	u8 log_mc_entry_sz;
+	u8 log_mc_hash_sz;
 	u16 hca_core_clock; /* Internal Clock Frequency (in MHz) */
 	u8  log_num_qps;
 	u8  log_num_srqs;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx4/main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -498,6 +498,7 @@
 		}
 	}
 
+	dev->caps.map_clock_to_user  = dev_cap->map_clock_to_user;
 	dev->caps.uar_page_size	     = PAGE_SIZE;
 	dev->caps.num_uars	     = dev_cap->uar_size / PAGE_SIZE;
 	dev->caps.local_ca_ack_delay = dev_cap->local_ca_ack_delay;
@@ -1948,6 +1949,11 @@
 	if (mlx4_is_slave(dev))
 		return -EOPNOTSUPP;
 
+	if (!dev->caps.map_clock_to_user) {
+		mlx4_dbg(dev, "Map clock to user is not supported.\n");
+		return -EOPNOTSUPP;
+	}
+
 	if (!params)
 		return -EINVAL;
 
@@ -2550,6 +2556,7 @@
 
 		if (!err || err == -ENOSPC) {
 			priv->def_counter[port] = idx;
+			err = 0;
 		} else if (err == -ENOENT) {
 			err = 0;
 			continue;
@@ -2600,7 +2607,8 @@
 				   MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
 		if (!err)
 			*idx = get_param_l(&out_param);
-
+		if (WARN_ON(err == -ENOSPC))
+			err = -EINVAL;
 		return err;
 	}
 	return __mlx4_counter_alloc(dev, idx);
@@ -3518,6 +3526,7 @@
 
 		if (!SRIOV_VALID_STATE(dev->flags)) {
 			mlx4_err(dev, "Invalid SRIOV state\n");
+			err = -EINVAL;
 			goto err_close;
 		}
 	}
@@ -4352,12 +4361,14 @@
 static void mlx4_shutdown(struct pci_dev *pdev)
 {
 	struct mlx4_dev_persistent *persist = pci_get_drvdata(pdev);
+	struct mlx4_dev *dev = persist->dev;
 
 	mlx4_info(persist->dev, "mlx4_shutdown was called\n");
 	mutex_lock(&persist->interface_state_mutex);
 	if (persist->interface_state & MLX4_INTERFACE_STATE_UP)
 		mlx4_unload_one(pdev);
 	mutex_unlock(&persist->interface_state_mutex);
+	mlx4_pci_disable_device(dev);
 }
 
 static const struct pci_error_handlers mlx4_err_handler = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
@@ -271,6 +271,10 @@
 	} buf[MLX4_EN_CACHE_SIZE];
 };
 
+enum {
+	MLX4_EN_TX_RING_STATE_RECOVERING,
+};
+
 struct mlx4_en_priv;
 
 struct mlx4_en_tx_ring {
@@ -317,6 +321,7 @@
 	 * Only queue_stopped might be used if BQL is not properly working.
 	 */
 	unsigned long		queue_stopped;
+	unsigned long		state;
 	struct mlx4_hwq_resources sp_wqres;
 	struct mlx4_qp		sp_qp;
 	struct mlx4_qp_context	sp_context;
@@ -530,6 +535,10 @@
 	struct mutex mutex; /* for mutual access to stats bitmap */
 };
 
+enum {
+	MLX4_EN_STATE_FLAG_RESTARTING,
+};
+
 struct mlx4_en_priv {
 	struct mlx4_en_dev *mdev;
 	struct mlx4_en_port_profile *prof;
@@ -595,7 +604,7 @@
 	struct mlx4_en_cq *rx_cq[MAX_RX_RINGS];
 	struct mlx4_qp drop_qp;
 	struct work_struct rx_mode_task;
-	struct work_struct watchdog_task;
+	struct work_struct restart_task;
 	struct work_struct linkstate_task;
 	struct delayed_work stats_task;
 	struct delayed_work service_task;
@@ -643,6 +652,7 @@
 	u32 pflags;
 	u8 rss_key[MLX4_EN_RSS_KEY_SIZE];
 	u8 rss_hash_fn;
+	unsigned long state;
 };
 
 enum mlx4_en_wol {
@@ -787,6 +797,7 @@
 #define DEV_FEATURE_CHANGED(dev, new_features, feature) \
 	((dev->features & feature) ^ (new_features & feature))
 
+int mlx4_en_moderation_update(struct mlx4_en_priv *priv);
 int mlx4_en_reset_config(struct net_device *dev,
 			 struct hwtstamp_config ts_config,
 			 netdev_features_t new_features);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx4/mr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx4/mr.c
@@ -114,7 +114,7 @@
 		goto err_out;
 
 	for (i = 0; i <= buddy->max_order; ++i) {
-		s = BITS_TO_LONGS(1 << (buddy->max_order - i));
+		s = BITS_TO_LONGS(1UL << (buddy->max_order - i));
 		buddy->bits[i] = kvmalloc_array(s, sizeof(long), GFP_KERNEL | __GFP_ZERO);
 		if (!buddy->bits[i])
 			goto err_out_free;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx4/port.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx4/port.c
@@ -1973,6 +1973,7 @@
 #define I2C_ADDR_LOW  0x50
 #define I2C_ADDR_HIGH 0x51
 #define I2C_PAGE_SIZE 256
+#define I2C_HIGH_PAGE_SIZE 128
 
 /* Module Info Data */
 struct mlx4_cable_info {
@@ -2026,6 +2027,88 @@
 	return "Unknown Error";
 }
 
+static int mlx4_get_module_id(struct mlx4_dev *dev, u8 port, u8 *module_id)
+{
+	struct mlx4_cmd_mailbox *inbox, *outbox;
+	struct mlx4_mad_ifc *inmad, *outmad;
+	struct mlx4_cable_info *cable_info;
+	int ret;
+
+	inbox = mlx4_alloc_cmd_mailbox(dev);
+	if (IS_ERR(inbox))
+		return PTR_ERR(inbox);
+
+	outbox = mlx4_alloc_cmd_mailbox(dev);
+	if (IS_ERR(outbox)) {
+		mlx4_free_cmd_mailbox(dev, inbox);
+		return PTR_ERR(outbox);
+	}
+
+	inmad = (struct mlx4_mad_ifc *)(inbox->buf);
+	outmad = (struct mlx4_mad_ifc *)(outbox->buf);
+
+	inmad->method = 0x1; /* Get */
+	inmad->class_version = 0x1;
+	inmad->mgmt_class = 0x1;
+	inmad->base_version = 0x1;
+	inmad->attr_id = cpu_to_be16(0xFF60); /* Module Info */
+
+	cable_info = (struct mlx4_cable_info *)inmad->data;
+	cable_info->dev_mem_address = 0;
+	cable_info->page_num = 0;
+	cable_info->i2c_addr = I2C_ADDR_LOW;
+	cable_info->size = cpu_to_be16(1);
+
+	ret = mlx4_cmd_box(dev, inbox->dma, outbox->dma, port, 3,
+			   MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C,
+			   MLX4_CMD_NATIVE);
+	if (ret)
+		goto out;
+
+	if (be16_to_cpu(outmad->status)) {
+		/* Mad returned with bad status */
+		ret = be16_to_cpu(outmad->status);
+		mlx4_warn(dev,
+			  "MLX4_CMD_MAD_IFC Get Module ID attr(%x) port(%d) i2c_addr(%x) offset(%d) size(%d): Response Mad Status(%x) - %s\n",
+			  0xFF60, port, I2C_ADDR_LOW, 0, 1, ret,
+			  cable_info_mad_err_str(ret));
+		ret = -ret;
+		goto out;
+	}
+	cable_info = (struct mlx4_cable_info *)outmad->data;
+	*module_id = cable_info->data[0];
+out:
+	mlx4_free_cmd_mailbox(dev, inbox);
+	mlx4_free_cmd_mailbox(dev, outbox);
+	return ret;
+}
+
+static void mlx4_sfp_eeprom_params_set(u8 *i2c_addr, u8 *page_num, u16 *offset)
+{
+	*i2c_addr = I2C_ADDR_LOW;
+	*page_num = 0;
+
+	if (*offset < I2C_PAGE_SIZE)
+		return;
+
+	*i2c_addr = I2C_ADDR_HIGH;
+	*offset -= I2C_PAGE_SIZE;
+}
+
+static void mlx4_qsfp_eeprom_params_set(u8 *i2c_addr, u8 *page_num, u16 *offset)
+{
+	/* Offsets 0-255 belong to page 0.
+	 * Offsets 256-639 belong to pages 01, 02, 03.
+	 * For example, offset 400 is page 02: 1 + (400 - 256) / 128 = 2
+	 */
+	if (*offset < I2C_PAGE_SIZE)
+		*page_num = 0;
+	else
+		*page_num = 1 + (*offset - I2C_PAGE_SIZE) / I2C_HIGH_PAGE_SIZE;
+	*i2c_addr = I2C_ADDR_LOW;
+	*offset -= *page_num * I2C_HIGH_PAGE_SIZE;
+}
+
 /**
  * mlx4_get_module_info - Read cable module eeprom data
  * @dev: mlx4_dev.
@@ -2045,12 +2128,30 @@
 	struct mlx4_cmd_mailbox *inbox, *outbox;
 	struct mlx4_mad_ifc *inmad, *outmad;
 	struct mlx4_cable_info *cable_info;
-	u16 i2c_addr;
+	u8 module_id, i2c_addr, page_num;
 	int ret;
 
 	if (size > MODULE_INFO_MAX_READ)
 		size = MODULE_INFO_MAX_READ;
 
+	ret = mlx4_get_module_id(dev, port, &module_id);
+	if (ret)
+		return ret;
+
+	switch (module_id) {
+	case MLX4_MODULE_ID_SFP:
+		mlx4_sfp_eeprom_params_set(&i2c_addr, &page_num, &offset);
+		break;
+	case MLX4_MODULE_ID_QSFP:
+	case MLX4_MODULE_ID_QSFP_PLUS:
+	case MLX4_MODULE_ID_QSFP28:
+		mlx4_qsfp_eeprom_params_set(&i2c_addr, &page_num, &offset);
+		break;
+	default:
+		mlx4_err(dev, "Module ID not recognized: %#x\n", module_id);
+		return -EINVAL;
+	}
+
 	inbox = mlx4_alloc_cmd_mailbox(dev);
 	if (IS_ERR(inbox))
 		return PTR_ERR(inbox);
@@ -2076,11 +2177,9 @@
 		 */
 		size -= offset + size - I2C_PAGE_SIZE;
 
-	i2c_addr = I2C_ADDR_LOW;
-
 	cable_info = (struct mlx4_cable_info *)inmad->data;
 	cable_info->dev_mem_address = cpu_to_be16(offset);
-	cable_info->page_num = 0;
+	cable_info->page_num = page_num;
 	cable_info->i2c_addr = i2c_addr;
 	cable_info->size = cpu_to_be16(size);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx4/qp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx4/qp.c
@@ -697,7 +697,8 @@
 			err = mlx4_bitmap_init(*bitmap + k, 1,
 					       MLX4_QP_TABLE_RAW_ETH_SIZE - 1, 0,
 					       0);
-			mlx4_bitmap_alloc_range(*bitmap + k, 1, 1, 0);
+			if (!err)
+				mlx4_bitmap_alloc_range(*bitmap + k, 1, 1, 0);
 		}
 
 		if (err)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
@@ -4986,6 +4986,7 @@
 
 	if (!fs_rule->mirr_mbox) {
 		mlx4_err(dev, "rule mirroring mailbox is null\n");
+		mlx4_free_cmd_mailbox(dev, mailbox);
 		return -EINVAL;
 	}
 	memcpy(mailbox->buf, fs_rule->mirr_mbox, fs_rule->mirr_mbox_size);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/accel/tls.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/accel/tls.h
@@ -45,7 +45,7 @@
 
 static inline bool mlx5_accel_is_ktls_device(struct mlx5_core_dev *mdev)
 {
-	if (!MLX5_CAP_GEN(mdev, tls))
+	if (!MLX5_CAP_GEN(mdev, tls_tx))
 		return false;
 
 	if (!MLX5_CAP_GEN(mdev, log_max_dek))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
@@ -69,12 +69,10 @@
 	MLX5_CMD_DELIVERY_STAT_CMD_DESCR_ERR		= 0x10,
 };
 
-static struct mlx5_cmd_work_ent *alloc_cmd(struct mlx5_cmd *cmd,
-					   struct mlx5_cmd_msg *in,
-					   struct mlx5_cmd_msg *out,
-					   void *uout, int uout_size,
-					   mlx5_cmd_cbk_t cbk,
-					   void *context, int page_queue)
+static struct mlx5_cmd_work_ent *
+cmd_alloc_ent(struct mlx5_cmd *cmd, struct mlx5_cmd_msg *in,
+	      struct mlx5_cmd_msg *out, void *uout, int uout_size,
+	      mlx5_cmd_cbk_t cbk, void *context, int page_queue)
 {
 	gfp_t alloc_flags = cbk ? GFP_ATOMIC : GFP_KERNEL;
 	struct mlx5_cmd_work_ent *ent;
@@ -83,6 +81,7 @@
 	if (!ent)
 		return ERR_PTR(-ENOMEM);
 
+	ent->idx	= -EINVAL;
 	ent->in		= in;
 	ent->out	= out;
 	ent->uout	= uout;
@@ -91,10 +90,16 @@
 	ent->context	= context;
 	ent->cmd	= cmd;
 	ent->page_queue = page_queue;
+	refcount_set(&ent->refcnt, 1);
 
 	return ent;
 }
 
+static void cmd_free_ent(struct mlx5_cmd_work_ent *ent)
+{
+	kfree(ent);
+}
+
 static u8 alloc_token(struct mlx5_cmd *cmd)
 {
 	u8 token;
@@ -109,26 +114,50 @@
 	return token;
 }
 
-static int alloc_ent(struct mlx5_cmd *cmd)
+static int cmd_alloc_index(struct mlx5_cmd *cmd, struct mlx5_cmd_work_ent *ent)
 {
 	unsigned long flags;
 	int ret;
 
 	spin_lock_irqsave(&cmd->alloc_lock, flags);
 	ret = find_first_bit(&cmd->bitmask, cmd->max_reg_cmds);
-	if (ret < cmd->max_reg_cmds)
+	if (ret < cmd->max_reg_cmds) {
 		clear_bit(ret, &cmd->bitmask);
+		ent->idx = ret;
+		cmd->ent_arr[ent->idx] = ent;
+	}
 	spin_unlock_irqrestore(&cmd->alloc_lock, flags);
 
 	return ret < cmd->max_reg_cmds ? ret : -ENOMEM;
 }
 
-static void free_ent(struct mlx5_cmd *cmd, int idx)
+static void cmd_free_index(struct mlx5_cmd *cmd, int idx)
+{
+	lockdep_assert_held(&cmd->alloc_lock);
+	set_bit(idx, &cmd->bitmask);
+}
+
+static void cmd_ent_get(struct mlx5_cmd_work_ent *ent)
+{
+	refcount_inc(&ent->refcnt);
+}
+
+static void cmd_ent_put(struct mlx5_cmd_work_ent *ent)
 {
+	struct mlx5_cmd *cmd = ent->cmd;
 	unsigned long flags;
 
 	spin_lock_irqsave(&cmd->alloc_lock, flags);
-	set_bit(idx, &cmd->bitmask);
+	if (!refcount_dec_and_test(&ent->refcnt))
+		goto out;
+
+	if (ent->idx >= 0) {
+		cmd_free_index(cmd, ent->idx);
+		up(ent->page_queue ? &cmd->pages_sem : &cmd->sem);
+	}
+
+	cmd_free_ent(ent);
+out:
 	spin_unlock_irqrestore(&cmd->alloc_lock, flags);
 }
 
@@ -219,11 +248,6 @@
 	ent->ret = -ETIMEDOUT;
 }
 
-static void free_cmd(struct mlx5_cmd_work_ent *ent)
-{
-	kfree(ent);
-}
-
 static int verify_signature(struct mlx5_cmd_work_ent *ent)
 {
 	struct mlx5_cmd_mailbox *next = ent->out->next;
@@ -317,6 +341,8 @@
 	case MLX5_CMD_OP_DEALLOC_MEMIC:
 	case MLX5_CMD_OP_PAGE_FAULT_RESUME:
 	case MLX5_CMD_OP_QUERY_ESW_FUNCTIONS:
+	case MLX5_CMD_OP_DESTROY_UCTX:
+	case MLX5_CMD_OP_DESTROY_UMEM:
 		return MLX5_CMD_STAT_OK;
 
 	case MLX5_CMD_OP_QUERY_HCA_CAP:
@@ -442,9 +468,7 @@
 	case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT:
 	case MLX5_CMD_OP_QUERY_GENERAL_OBJECT:
 	case MLX5_CMD_OP_CREATE_UCTX:
-	case MLX5_CMD_OP_DESTROY_UCTX:
 	case MLX5_CMD_OP_CREATE_UMEM:
-	case MLX5_CMD_OP_DESTROY_UMEM:
 	case MLX5_CMD_OP_ALLOC_MEMIC:
 	case MLX5_CMD_OP_MODIFY_XRQ:
 	case MLX5_CMD_OP_RELEASE_XRQ_ERROR:
@@ -837,17 +861,43 @@
 	struct mlx5_core_dev *dev = container_of(ent->cmd, struct mlx5_core_dev,
 						 cmd);
 
+	mlx5_cmd_eq_recover(dev);
+
+	/* Maybe got handled by eq recover ? */
+	if (!test_bit(MLX5_CMD_ENT_STATE_PENDING_COMP, &ent->state)) {
+		mlx5_core_warn(dev, "cmd[%d]: %s(0x%x) Async, recovered after timeout\n", ent->idx,
+			       mlx5_command_str(msg_to_opcode(ent->in)), msg_to_opcode(ent->in));
+		goto out; /* phew, already handled */
+	}
+
 	ent->ret = -ETIMEDOUT;
-	mlx5_core_warn(dev, "%s(0x%x) timeout. Will cause a leak of a command resource\n",
-		       mlx5_command_str(msg_to_opcode(ent->in)),
-		       msg_to_opcode(ent->in));
-	mlx5_cmd_comp_handler(dev, 1UL << ent->idx, true);
+	mlx5_core_warn(dev, "cmd[%d]: %s(0x%x) Async, timeout. Will cause a leak of a command resource\n",
+		       ent->idx, mlx5_command_str(msg_to_opcode(ent->in)), msg_to_opcode(ent->in));
+	mlx5_cmd_comp_handler(dev, 1ULL << ent->idx, true);
+
+out:
+	cmd_ent_put(ent); /* for the cmd_ent_get() took on schedule delayed work */
 }
 
 static void free_msg(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *msg);
 static void mlx5_free_cmd_msg(struct mlx5_core_dev *dev,
 			      struct mlx5_cmd_msg *msg);
 
+static bool opcode_allowed(struct mlx5_cmd *cmd, u16 opcode)
+{
+	if (cmd->allowed_opcode == CMD_ALLOWED_OPCODE_ALL)
+		return true;
+
+	return cmd->allowed_opcode == opcode;
+}
+
+bool mlx5_cmd_is_down(struct mlx5_core_dev *dev)
+{
+	return pci_channel_offline(dev->pdev) ||
+	       dev->cmd.state != MLX5_CMDIF_STATE_UP ||
+	       dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR;
+}
+
 static void cmd_work_handler(struct work_struct *work)
 {
 	struct mlx5_cmd_work_ent *ent = container_of(work, struct mlx5_cmd_work_ent, work);
@@ -861,17 +911,18 @@
 	int alloc_ret;
 	int cmd_mode;
 
+	complete(&ent->handling);
 	sem = ent->page_queue ? &cmd->pages_sem : &cmd->sem;
 	down(sem);
 	if (!ent->page_queue) {
-		alloc_ret = alloc_ent(cmd);
+		alloc_ret = cmd_alloc_index(cmd, ent);
 		if (alloc_ret < 0) {
 			mlx5_core_err(dev, "failed to allocate command entry\n");
 			if (ent->callback) {
 				ent->callback(-EAGAIN, ent->context);
 				mlx5_free_cmd_msg(dev, ent->out);
 				free_msg(dev, ent->in);
-				free_cmd(ent);
+				cmd_ent_put(ent);
 			} else {
 				ent->ret = -EAGAIN;
 				complete(&ent->done);
@@ -879,16 +930,14 @@
 			up(sem);
 			return;
 		}
-		ent->idx = alloc_ret;
 	} else {
 		ent->idx = cmd->max_reg_cmds;
 		spin_lock_irqsave(&cmd->alloc_lock, flags);
 		clear_bit(ent->idx, &cmd->bitmask);
+		cmd->ent_arr[ent->idx] = ent;
 		spin_unlock_irqrestore(&cmd->alloc_lock, flags);
 	}
 
-	cmd->ent_arr[ent->idx] = ent;
-	set_bit(MLX5_CMD_ENT_STATE_PENDING_COMP, &ent->state);
 	lay = get_inst(cmd, ent->idx);
 	ent->lay = lay;
 	memset(lay, 0, sizeof(*lay));
@@ -908,12 +957,13 @@
 	ent->ts1 = ktime_get_ns();
 	cmd_mode = cmd->mode;
 
-	if (ent->callback)
-		schedule_delayed_work(&ent->cb_timeout_work, cb_timeout);
+	if (ent->callback && schedule_delayed_work(&ent->cb_timeout_work, cb_timeout))
+		cmd_ent_get(ent);
+	set_bit(MLX5_CMD_ENT_STATE_PENDING_COMP, &ent->state);
 
+	cmd_ent_get(ent); /* for the _real_ FW event on completion */
 	/* Skip sending command to fw if internal error */
-	if (pci_channel_offline(dev->pdev) ||
-	    dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) {
+	if (mlx5_cmd_is_down(dev) || !opcode_allowed(&dev->cmd, ent->op)) {
 		u8 status = 0;
 		u32 drv_synd;
 
@@ -921,7 +971,7 @@
 		MLX5_SET(mbox_out, ent->out, status, status);
 		MLX5_SET(mbox_out, ent->out, syndrome, drv_synd);
 
-		mlx5_cmd_comp_handler(dev, 1UL << ent->idx, true);
+		mlx5_cmd_comp_handler(dev, 1ULL << ent->idx, true);
 		return;
 	}
 
@@ -934,7 +984,7 @@
 		poll_timeout(ent);
 		/* make sure we read the descriptor after ownership is SW */
 		rmb();
-		mlx5_cmd_comp_handler(dev, 1UL << ent->idx, (ent->ret == -ETIMEDOUT));
+		mlx5_cmd_comp_handler(dev, 1ULL << ent->idx, (ent->ret == -ETIMEDOUT));
 	}
 }
 
@@ -968,25 +1018,62 @@
 	}
 }
 
+enum {
+	MLX5_CMD_TIMEOUT_RECOVER_MSEC   = 5 * 1000,
+};
+
+static void wait_func_handle_exec_timeout(struct mlx5_core_dev *dev,
+					  struct mlx5_cmd_work_ent *ent)
+{
+	unsigned long timeout = msecs_to_jiffies(MLX5_CMD_TIMEOUT_RECOVER_MSEC);
+
+	mlx5_cmd_eq_recover(dev);
+
+	/* Re-wait on the ent->done after executing the recovery flow. If the
+	 * recovery flow (or any other recovery flow running simultaneously)
+	 * has recovered an EQE, it should cause the entry to be completed by
+	 * the command interface.
+	 */
+	if (wait_for_completion_timeout(&ent->done, timeout)) {
+		mlx5_core_warn(dev, "cmd[%d]: %s(0x%x) recovered after timeout\n", ent->idx,
+			       mlx5_command_str(msg_to_opcode(ent->in)), msg_to_opcode(ent->in));
+		return;
+	}
+
+	mlx5_core_warn(dev, "cmd[%d]: %s(0x%x) No done completion\n", ent->idx,
+		       mlx5_command_str(msg_to_opcode(ent->in)), msg_to_opcode(ent->in));
+
+	ent->ret = -ETIMEDOUT;
+	mlx5_cmd_comp_handler(dev, 1ULL << ent->idx, true);
+}
+
 static int wait_func(struct mlx5_core_dev *dev, struct mlx5_cmd_work_ent *ent)
 {
 	unsigned long timeout = msecs_to_jiffies(MLX5_CMD_TIMEOUT_MSEC);
 	struct mlx5_cmd *cmd = &dev->cmd;
 	int err;
 
-	if (cmd->mode == CMD_MODE_POLLING || ent->polling) {
-		wait_for_completion(&ent->done);
-	} else if (!wait_for_completion_timeout(&ent->done, timeout)) {
-		ent->ret = -ETIMEDOUT;
-		mlx5_cmd_comp_handler(dev, 1UL << ent->idx, true);
+	if (!wait_for_completion_timeout(&ent->handling, timeout) &&
+	    cancel_work_sync(&ent->work)) {
+		ent->ret = -ECANCELED;
+		goto out_err;
 	}
+	if (cmd->mode == CMD_MODE_POLLING || ent->polling)
+		wait_for_completion(&ent->done);
+	else if (!wait_for_completion_timeout(&ent->done, timeout))
+		wait_func_handle_exec_timeout(dev, ent);
 
+out_err:
 	err = ent->ret;
 
 	if (err == -ETIMEDOUT) {
 		mlx5_core_warn(dev, "%s(0x%x) timeout. Will cause a leak of a command resource\n",
 			       mlx5_command_str(msg_to_opcode(ent->in)),
 			       msg_to_opcode(ent->in));
+	} else if (err == -ECANCELED) {
+		mlx5_core_warn(dev, "%s(0x%x) canceled on out of queue timeout.\n",
+			       mlx5_command_str(msg_to_opcode(ent->in)),
+			       msg_to_opcode(ent->in));
 	}
 	mlx5_core_dbg(dev, "err %d, delivery status %s(%d)\n",
 		      err, deliv_status_to_str(ent->status), ent->status);
@@ -1014,14 +1101,20 @@
 	if (callback && page_queue)
 		return -EINVAL;
 
-	ent = alloc_cmd(cmd, in, out, uout, uout_size, callback, context,
-			page_queue);
+	ent = cmd_alloc_ent(cmd, in, out, uout, uout_size,
+			    callback, context, page_queue);
 	if (IS_ERR(ent))
 		return PTR_ERR(ent);
 
+	/* put for this ent is when consumed, depending on the use case
+	 * 1) (!callback) blocking flow: by caller after wait_func completes
+	 * 2) (callback) flow: by mlx5_cmd_comp_handler() when ent is handled
+	 */
+
 	ent->token = token;
 	ent->polling = force_polling;
 
+	init_completion(&ent->handling);
 	if (!callback)
 		init_completion(&ent->done);
 
@@ -1036,11 +1129,11 @@
 	}
 
 	if (callback)
-		goto out;
+		goto out; /* mlx5_cmd_comp_handler() will put(ent) */
 
 	err = wait_func(dev, ent);
-	if (err == -ETIMEDOUT)
-		goto out;
+	if (err == -ETIMEDOUT || err == -ECANCELED)
+		goto out_free;
 
 	ds = ent->ts2 - ent->ts1;
 	op = MLX5_GET(mbox_in, in->first.data, opcode);
@@ -1057,7 +1150,7 @@
 	*status = ent->status;
 
 out_free:
-	free_cmd(ent);
+	cmd_ent_put(ent);
 out:
 	return err;
 }
@@ -1331,8 +1424,8 @@
 		return -EFAULT;
 
 	err = sscanf(outlen_str, "%d", &outlen);
-	if (err < 0)
-		return err;
+	if (err != 1)
+		return -EINVAL;
 
 	ptr = kzalloc(outlen, GFP_KERNEL);
 	if (!ptr)
@@ -1387,6 +1480,22 @@
 	mlx5_cmdif_debugfs_init(dev);
 }
 
+void mlx5_cmd_allowed_opcode(struct mlx5_core_dev *dev, u16 opcode)
+{
+	struct mlx5_cmd *cmd = &dev->cmd;
+	int i;
+
+	for (i = 0; i < cmd->max_reg_cmds; i++)
+		down(&cmd->sem);
+	down(&cmd->pages_sem);
+
+	cmd->allowed_opcode = opcode;
+
+	up(&cmd->pages_sem);
+	for (i = 0; i < cmd->max_reg_cmds; i++)
+		up(&cmd->sem);
+}
+
 static void mlx5_cmd_change_mod(struct mlx5_core_dev *dev, int mode)
 {
 	struct mlx5_cmd *cmd = &dev->cmd;
@@ -1461,8 +1570,6 @@
 	vector = vec & 0xffffffff;
 	for (i = 0; i < (1 << cmd->log_sz); i++) {
 		if (test_bit(i, &vector)) {
-			struct semaphore *sem;
-
 			ent = cmd->ent_arr[i];
 
 			/* if we already completed the command, ignore it */
@@ -1472,18 +1579,19 @@
 				if (!forced) {
 					mlx5_core_err(dev, "Command completion arrived after timeout (entry idx = %d).\n",
 						      ent->idx);
-					free_ent(cmd, ent->idx);
-					free_cmd(ent);
+					cmd_ent_put(ent);
 				}
 				continue;
 			}
 
-			if (ent->callback)
-				cancel_delayed_work(&ent->cb_timeout_work);
-			if (ent->page_queue)
-				sem = &cmd->pages_sem;
-			else
-				sem = &cmd->sem;
+			if (ent->callback && cancel_delayed_work(&ent->cb_timeout_work))
+				cmd_ent_put(ent); /* timeout work was canceled */
+
+			if (!forced || /* Real FW completion */
+			     mlx5_cmd_is_down(dev) || /* No real FW completion is expected */
+			     !opcode_allowed(cmd, ent->op))
+				cmd_ent_put(ent);
+
 			ent->ts2 = ktime_get_ns();
 			memcpy(ent->out->first.data, ent->lay->out, sizeof(ent->lay->out));
 			dump_command(dev, ent, 0);
@@ -1501,10 +1609,6 @@
 					      ent->ret, deliv_status_to_str(ent->status), ent->status);
 			}
 
-			/* only real completion will free the entry slot */
-			if (!forced)
-				free_ent(cmd, ent->idx);
-
 			if (ent->callback) {
 				ds = ent->ts2 - ent->ts1;
 				if (ent->op < ARRAY_SIZE(cmd->stats)) {
@@ -1532,21 +1636,26 @@
 				free_msg(dev, ent->in);
 
 				err = err ? err : ent->status;
-				if (!forced)
-					free_cmd(ent);
+				/* final consumer is done, release ent */
+				cmd_ent_put(ent);
 				callback(err, context);
 			} else {
+				/* release wait_func() so mlx5_cmd_invoke()
+				 * can make the final ent_put()
+				 */
 				complete(&ent->done);
 			}
-			up(sem);
 		}
 	}
 }
 
 void mlx5_cmd_trigger_completions(struct mlx5_core_dev *dev)
 {
+	struct mlx5_cmd *cmd = &dev->cmd;
+	unsigned long bitmask;
 	unsigned long flags;
 	u64 vector;
+	int i;
 
 	/* wait for pending handlers to complete */
 	mlx5_eq_synchronize_cmd_irq(dev);
@@ -1555,11 +1664,20 @@
 	if (!vector)
 		goto no_trig;
 
+	bitmask = vector;
+	/* we must increment the allocated entries refcount before triggering the completions
+	 * to guarantee pending commands will not get freed in the meanwhile.
+	 * For that reason, it also has to be done inside the alloc_lock.
+	 */
+	for_each_set_bit(i, &bitmask, (1 << cmd->log_sz))
+		cmd_ent_get(cmd->ent_arr[i]);
 	vector |= MLX5_TRIGGERED_CMD_COMP;
 	spin_unlock_irqrestore(&dev->cmd.alloc_lock, flags);
 
 	mlx5_core_dbg(dev, "vector 0x%llx\n", vector);
 	mlx5_cmd_comp_handler(dev, vector, true);
+	for_each_set_bit(i, &bitmask, (1 << cmd->log_sz))
+		cmd_ent_put(cmd->ent_arr[i]);
 	return;
 
 no_trig:
@@ -1571,12 +1689,17 @@
 	struct mlx5_cmd *cmd = &dev->cmd;
 	int i;
 
-	for (i = 0; i < cmd->max_reg_cmds; i++)
-		while (down_trylock(&cmd->sem))
+	for (i = 0; i < cmd->max_reg_cmds; i++) {
+		while (down_trylock(&cmd->sem)) {
 			mlx5_cmd_trigger_completions(dev);
+			cond_resched();
+		}
+	}
 
-	while (down_trylock(&cmd->pages_sem))
+	while (down_trylock(&cmd->pages_sem)) {
 		mlx5_cmd_trigger_completions(dev);
+		cond_resched();
+	}
 
 	/* Unlock cmdif */
 	up(&cmd->pages_sem);
@@ -1663,12 +1786,11 @@
 	int err;
 	u8 status = 0;
 	u32 drv_synd;
+	u16 opcode;
 	u8 token;
 
-	if (pci_channel_offline(dev->pdev) ||
-	    dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) {
-		u16 opcode = MLX5_GET(mbox_in, in, opcode);
-
+	opcode = MLX5_GET(mbox_in, in, opcode);
+	if (mlx5_cmd_is_down(dev) || !opcode_allowed(&dev->cmd, opcode)) {
 		err = mlx5_internal_err_ret_value(dev, opcode, &drv_synd, &status);
 		MLX5_SET(mbox_out, out, status, status);
 		MLX5_SET(mbox_out, out, syndrome, drv_synd);
@@ -1738,7 +1860,7 @@
 	ctx->dev = dev;
 	/* Starts at 1 to avoid doing wake_up if we are not cleaning up */
 	atomic_set(&ctx->num_inflight, 1);
-	init_waitqueue_head(&ctx->wait);
+	init_completion(&ctx->inflight_done);
 }
 EXPORT_SYMBOL(mlx5_cmd_init_async_ctx);
 
@@ -1752,8 +1874,8 @@
  */
 void mlx5_cmd_cleanup_async_ctx(struct mlx5_async_ctx *ctx)
 {
-	atomic_dec(&ctx->num_inflight);
-	wait_event(ctx->wait, atomic_read(&ctx->num_inflight) == 0);
+	if (!atomic_dec_and_test(&ctx->num_inflight))
+		wait_for_completion(&ctx->inflight_done);
 }
 EXPORT_SYMBOL(mlx5_cmd_cleanup_async_ctx);
 
@@ -1764,7 +1886,7 @@
 
 	work->user_callback(status, work);
 	if (atomic_dec_and_test(&ctx->num_inflight))
-		wake_up(&ctx->wait);
+		complete(&ctx->inflight_done);
 }
 
 int mlx5_cmd_exec_cb(struct mlx5_async_ctx *ctx, void *in, int in_size,
@@ -1780,7 +1902,7 @@
 	ret = cmd_exec(ctx->dev, in, in_size, out, out_size,
 		       mlx5_cmd_exec_cb_handler, work, false);
 	if (ret && atomic_dec_and_test(&ctx->num_inflight))
-		wake_up(&ctx->wait);
+		complete(&ctx->inflight_done);
 
 	return ret;
 }
@@ -1933,6 +2055,7 @@
 		goto err_free_page;
 	}
 
+	cmd->state = MLX5_CMDIF_STATE_DOWN;
 	cmd->checksum_disabled = 1;
 	cmd->max_reg_cmds = (1 << cmd->log_sz) - 1;
 	cmd->bitmask = (1UL << cmd->max_reg_cmds) - 1;
@@ -1970,6 +2093,7 @@
 	mlx5_core_dbg(dev, "descriptor at dma 0x%llx\n", (unsigned long long)(cmd->dma));
 
 	cmd->mode = CMD_MODE_POLLING;
+	cmd->allowed_opcode = CMD_ALLOWED_OPCODE_ALL;
 
 	create_msg_cache(dev);
 
@@ -2009,3 +2133,10 @@
 	dma_pool_destroy(cmd->pool);
 }
 EXPORT_SYMBOL(mlx5_cmd_cleanup);
+
+void mlx5_cmd_set_state(struct mlx5_core_dev *dev,
+			enum mlx5_cmdif_state cmdif_state)
+{
+	dev->cmd.state = cmdif_state;
+}
+EXPORT_SYMBOL(mlx5_cmd_set_state);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/devlink.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/devlink.c
@@ -23,7 +23,10 @@
 	if (err)
 		return err;
 
-	return mlx5_firmware_flash(dev, fw, extack);
+	err = mlx5_firmware_flash(dev, fw, extack);
+	release_firmware(fw);
+
+	return err;
 }
 
 static u8 mlx5_fw_ver_major(u32 version)
@@ -52,7 +55,7 @@
 	u32 running_fw, stored_fw;
 	int err;
 
-	err = devlink_info_driver_name_put(req, DRIVER_NAME);
+	err = devlink_info_driver_name_put(req, KBUILD_MODNAME);
 	if (err)
 		return err;
 
@@ -85,6 +88,22 @@
 	return 0;
 }
 
+static int mlx5_devlink_reload_down(struct devlink *devlink,
+				    struct netlink_ext_ack *extack)
+{
+	struct mlx5_core_dev *dev = devlink_priv(devlink);
+
+	return mlx5_unload_one(dev, false);
+}
+
+static int mlx5_devlink_reload_up(struct devlink *devlink,
+				  struct netlink_ext_ack *extack)
+{
+	struct mlx5_core_dev *dev = devlink_priv(devlink);
+
+	return mlx5_load_one(dev, false);
+}
+
 static const struct devlink_ops mlx5_devlink_ops = {
 #ifdef CONFIG_MLX5_ESWITCH
 	.eswitch_mode_set = mlx5_devlink_eswitch_mode_set,
@@ -96,6 +115,8 @@
 #endif
 	.flash_update = mlx5_devlink_flash_update,
 	.info_get = mlx5_devlink_info_get,
+	.reload_down = mlx5_devlink_reload_down,
+	.reload_up = mlx5_devlink_reload_up,
 };
 
 struct devlink *mlx5_devlink_alloc(void)
@@ -177,12 +198,29 @@
 	MLX5_DEVLINK_PARAM_FLOW_STEERING_MODE,
 };
 
+static int mlx5_devlink_enable_roce_validate(struct devlink *devlink, u32 id,
+					     union devlink_param_value val,
+					     struct netlink_ext_ack *extack)
+{
+	struct mlx5_core_dev *dev = devlink_priv(devlink);
+	bool new_state = val.vbool;
+
+	if (new_state && !MLX5_CAP_GEN(dev, roce)) {
+		NL_SET_ERR_MSG_MOD(extack, "Device doesn't support RoCE");
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
 static const struct devlink_param mlx5_devlink_params[] = {
 	DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_FLOW_STEERING_MODE,
 			     "flow_steering_mode", DEVLINK_PARAM_TYPE_STRING,
 			     BIT(DEVLINK_PARAM_CMODE_RUNTIME),
 			     mlx5_devlink_fs_mode_get, mlx5_devlink_fs_mode_set,
 			     mlx5_devlink_fs_mode_validate),
+	DEVLINK_PARAM_GENERIC(ENABLE_ROCE, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
+			      NULL, NULL, mlx5_devlink_enable_roce_validate),
 };
 
 static void mlx5_devlink_set_params_init_values(struct devlink *devlink)
@@ -197,6 +235,11 @@
 	devlink_param_driverinit_value_set(devlink,
 					   MLX5_DEVLINK_PARAM_FLOW_STEERING_MODE,
 					   value);
+
+	value.vbool = MLX5_CAP_GEN(dev, roce);
+	devlink_param_driverinit_value_set(devlink,
+					   DEVLINK_PARAM_GENERIC_ID_ENABLE_ROCE,
+					   value);
 }
 
 int mlx5_devlink_register(struct devlink *devlink, struct device *dev)
@@ -213,6 +256,7 @@
 		goto params_reg_err;
 	mlx5_devlink_set_params_init_values(devlink);
 	devlink_params_publish(devlink);
+	devlink_reload_enable(devlink);
 	return 0;
 
 params_reg_err:
@@ -222,6 +266,7 @@
 
 void mlx5_devlink_unregister(struct devlink *devlink)
 {
+	devlink_reload_disable(devlink);
 	devlink_params_unregister(devlink, mlx5_devlink_params,
 				  ARRAY_SIZE(mlx5_devlink_params));
 	devlink_unregister(devlink);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c
@@ -480,7 +480,7 @@
 				(u64)timestamp_low;
 		break;
 	default:
-		if (tracer_event->event_id >= tracer->str_db.first_string_trace ||
+		if (tracer_event->event_id >= tracer->str_db.first_string_trace &&
 		    tracer_event->event_id <= tracer->str_db.first_string_trace +
 					      tracer->str_db.num_string_trace) {
 			tracer_event->type = TRACER_EVENT_TYPE_STRING;
@@ -600,7 +600,7 @@
 	} else {
 		cur_string = mlx5_tracer_message_get(tracer, tracer_event);
 		if (!cur_string) {
-			pr_debug("%s Got string event for unknown string tdsm: %d\n",
+			pr_debug("%s Got string event for unknown string tmsn: %d\n",
 				 __func__, tracer_event->string_event.tmsn);
 			return -1;
 		}
@@ -636,7 +636,7 @@
 			trace_timestamp = (timestamp_event.timestamp & MASK_52_7) |
 					  (str_frmt->timestamp & MASK_6_0);
 		else
-			trace_timestamp = ((timestamp_event.timestamp & MASK_52_7) - 1) |
+			trace_timestamp = ((timestamp_event.timestamp - 1) & MASK_52_7) |
 					  (str_frmt->timestamp & MASK_6_0);
 
 		mlx5_tracer_print_trace(str_frmt, dev, trace_timestamp);
@@ -673,6 +673,9 @@
 	if (!tracer->owner)
 		return;
 
+	if (unlikely(!tracer->str_db.loaded))
+		goto arm;
+
 	block_count = tracer->buff.size / TRACER_BLOCK_SIZE_BYTE;
 	start_offset = tracer->buff.consumer_index * TRACER_BLOCK_SIZE_BYTE;
 
@@ -684,8 +687,8 @@
 		get_block_timestamp(tracer, &tmp_trace_block[TRACES_PER_BLOCK - 1]);
 
 	while (block_timestamp > tracer->last_timestamp) {
-		/* Check block override if its not the first block */
-		if (!tracer->last_timestamp) {
+		/* Check block override if it's not the first block */
+		if (tracer->last_timestamp) {
 			u64 *ts_event;
 			/* To avoid block override be the HW in case of buffer
 			 * wraparound, the time stamp of the previous block
@@ -730,6 +733,7 @@
 						      &tmp_trace_block[TRACES_PER_BLOCK - 1]);
 	}
 
+arm:
 	mlx5_fw_tracer_arm(dev);
 }
 
@@ -935,7 +939,7 @@
 		return NULL;
 	}
 
-	tracer = kzalloc(sizeof(*tracer), GFP_KERNEL);
+	tracer = kvzalloc(sizeof(*tracer), GFP_KERNEL);
 	if (!tracer)
 		return ERR_PTR(-ENOMEM);
 
@@ -982,7 +986,7 @@
 	tracer->dev = NULL;
 	destroy_workqueue(tracer->work_queue);
 free_tracer:
-	kfree(tracer);
+	kvfree(tracer);
 	return ERR_PTR(err);
 }
 
@@ -1005,7 +1009,7 @@
 	err = mlx5_core_alloc_pd(dev, &tracer->buff.pdn);
 	if (err) {
 		mlx5_core_warn(dev, "FWTracer: Failed to allocate PD %d\n", err);
-		return err;
+		goto err_cancel_work;
 	}
 
 	err = mlx5_fw_tracer_create_mkey(tracer);
@@ -1017,12 +1021,20 @@
 	MLX5_NB_INIT(&tracer->nb, fw_tracer_event, DEVICE_TRACER);
 	mlx5_eq_notifier_register(dev, &tracer->nb);
 
-	mlx5_fw_tracer_start(tracer);
-
+	err = mlx5_fw_tracer_start(tracer);
+	if (err) {
+		mlx5_core_warn(dev, "FWTracer: Failed to start tracer %d\n", err);
+		goto err_notifier_unregister;
+	}
 	return 0;
 
+err_notifier_unregister:
+	mlx5_eq_notifier_unregister(dev, &tracer->nb);
+	mlx5_core_destroy_mkey(dev, &tracer->buff.mkey);
 err_dealloc_pd:
 	mlx5_core_dealloc_pd(dev, tracer->buff.pdn);
+err_cancel_work:
+	cancel_work_sync(&tracer->read_fw_strings_work);
 	return err;
 }
 
@@ -1061,7 +1073,7 @@
 	mlx5_fw_tracer_destroy_log_buf(tracer);
 	flush_workqueue(tracer->work_queue);
 	destroy_workqueue(tracer->work_queue);
-	kfree(tracer);
+	kvfree(tracer);
 }
 
 static int fw_tracer_event(struct notifier_block *nb, unsigned long action, void *data)
@@ -1076,8 +1088,7 @@
 			queue_work(tracer->work_queue, &tracer->ownership_change_work);
 		break;
 	case MLX5_TRACER_SUBTYPE_TRACES_AVAILABLE:
-		if (likely(tracer->str_db.loaded))
-			queue_work(tracer->work_queue, &tracer->handle_traces_work);
+		queue_work(tracer->work_queue, &tracer->handle_traces_work);
 		break;
 	default:
 		mlx5_core_dbg(dev, "FWTracer: Event with unrecognized subtype: sub_type %d\n",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -92,11 +92,16 @@
 #define MLX5_MPWRQ_PAGES_PER_WQE		BIT(MLX5_MPWRQ_WQE_PAGE_ORDER)
 
 #define MLX5_MTT_OCTW(npages) (ALIGN(npages, 8) / 2)
-#define MLX5E_REQUIRED_WQE_MTTS		(ALIGN(MLX5_MPWRQ_PAGES_PER_WQE, 8))
+/* Add another page to MLX5E_REQUIRED_WQE_MTTS as a buffer between
+ * WQEs, This page will absorb write overflow by the hardware, when
+ * receiving packets larger than MTU. These oversize packets are
+ * dropped by the driver at a later stage.
+ */
+#define MLX5E_REQUIRED_WQE_MTTS		(ALIGN(MLX5_MPWRQ_PAGES_PER_WQE + 1, 8))
 #define MLX5E_LOG_ALIGNED_MPWQE_PPW	(ilog2(MLX5E_REQUIRED_WQE_MTTS))
 #define MLX5E_REQUIRED_MTTS(wqes)	(wqes * MLX5E_REQUIRED_WQE_MTTS)
 #define MLX5E_MAX_RQ_NUM_MTTS	\
-	((1 << 16) * 2) /* So that MLX5_MTT_OCTW(num_mtts) fits into u16 */
+	(ALIGN_DOWN(U16_MAX, 4) * 2) /* So that MLX5_MTT_OCTW(num_mtts) fits into u16 */
 #define MLX5E_ORDER2_MAX_PACKET_MTU (order_base_2(10 * 1024))
 #define MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE_MPW	\
 		(ilog2(MLX5E_MAX_RQ_NUM_MTTS / MLX5E_REQUIRED_WQE_MTTS))
@@ -367,10 +372,12 @@
 	MLX5E_SQ_STATE_AM,
 	MLX5E_SQ_STATE_TLS,
 	MLX5E_SQ_STATE_VLAN_NEED_L2_INLINE,
+	MLX5E_SQ_STATE_PENDING_XSK_TX,
 };
 
 struct mlx5e_sq_wqe_info {
 	u8  opcode;
+	u8 num_wqebbs;
 
 	/* Auxiliary data for different opcodes. */
 	union {
@@ -692,6 +699,7 @@
 	u32                    rqn;
 	struct mlx5_core_dev  *mdev;
 	struct mlx5_core_mkey  umr_mkey;
+	struct mlx5e_dma_info  wqe_overflow;
 
 	/* XDP read-mostly */
 	struct xdp_rxq_info    xdp_rxq;
@@ -760,7 +768,7 @@
 	MLX5E_STATE_OPENED,
 	MLX5E_STATE_DESTROYING,
 	MLX5E_STATE_XDP_TX_ENABLED,
-	MLX5E_STATE_XDP_OPEN,
+	MLX5E_STATE_XDP_ACTIVE,
 };
 
 struct mlx5e_rqt {
@@ -816,7 +824,7 @@
 struct mlx5e_priv {
 	/* priv data path fields - start */
 	struct mlx5e_txqsq *txq2sq[MLX5E_MAX_NUM_CHANNELS * MLX5E_MAX_NUM_TC];
-	int channel_tc2txq[MLX5E_MAX_NUM_CHANNELS][MLX5E_MAX_NUM_TC];
+	int channel_tc2realtxq[MLX5E_MAX_NUM_CHANNELS][MLX5E_MAX_NUM_TC];
 #ifdef CONFIG_MLX5_CORE_EN_DCB
 	struct mlx5e_dcbx_dp       dcbx_dp;
 #endif
@@ -947,7 +955,7 @@
 void mlx5e_handle_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe);
 void mlx5e_handle_rx_cqe_mpwrq(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe);
 bool mlx5e_post_rx_wqes(struct mlx5e_rq *rq);
-void mlx5e_poll_ico_cq(struct mlx5e_cq *cq);
+int mlx5e_poll_ico_cq(struct mlx5e_cq *cq);
 bool mlx5e_post_rx_mpwqes(struct mlx5e_rq *rq);
 void mlx5e_dealloc_rx_wqe(struct mlx5e_rq *rq, u16 ix);
 void mlx5e_dealloc_rx_mpwqe(struct mlx5e_rq *rq, u16 ix);
@@ -1034,14 +1042,15 @@
 			struct mlx5e_channels *chs);
 void mlx5e_close_channels(struct mlx5e_channels *chs);
 
-/* Function pointer to be used to modify WH settings while
+/* Function pointer to be used to modify HW or kernel settings while
  * switching channels
  */
-typedef int (*mlx5e_fp_hw_modify)(struct mlx5e_priv *priv);
+typedef int (*mlx5e_fp_preactivate)(struct mlx5e_priv *priv);
 int mlx5e_safe_reopen_channels(struct mlx5e_priv *priv);
 int mlx5e_safe_switch_channels(struct mlx5e_priv *priv,
 			       struct mlx5e_channels *new_chs,
-			       mlx5e_fp_hw_modify hw_modify);
+			       mlx5e_fp_preactivate preactivate);
+int mlx5e_num_channels_changed(struct mlx5e_priv *priv);
 void mlx5e_activate_priv_channels(struct mlx5e_priv *priv);
 void mlx5e_deactivate_priv_channels(struct mlx5e_priv *priv);
 
@@ -1058,6 +1067,7 @@
 void mlx5e_activate_rq(struct mlx5e_rq *rq);
 void mlx5e_deactivate_rq(struct mlx5e_rq *rq);
 void mlx5e_free_rx_descs(struct mlx5e_rq *rq);
+void mlx5e_free_rx_in_progress_descs(struct mlx5e_rq *rq);
 void mlx5e_activate_icosq(struct mlx5e_icosq *icosq);
 void mlx5e_deactivate_icosq(struct mlx5e_icosq *icosq);
 
@@ -1099,7 +1109,7 @@
 int mlx5e_create_indirect_rqt(struct mlx5e_priv *priv);
 
 int mlx5e_create_indirect_tirs(struct mlx5e_priv *priv, bool inner_ttc);
-void mlx5e_destroy_indirect_tirs(struct mlx5e_priv *priv, bool inner_ttc);
+void mlx5e_destroy_indirect_tirs(struct mlx5e_priv *priv);
 
 int mlx5e_create_direct_rqts(struct mlx5e_priv *priv, struct mlx5e_tir *tirs);
 void mlx5e_destroy_direct_rqts(struct mlx5e_priv *priv, struct mlx5e_tir *tirs);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en/fs.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/en/fs.h
@@ -122,6 +122,22 @@
 #endif
 };
 
+#define MLX5E_TTC_NUM_GROUPS	3
+#define MLX5E_TTC_GROUP1_SIZE	(BIT(3) + MLX5E_NUM_TUNNEL_TT)
+#define MLX5E_TTC_GROUP2_SIZE	 BIT(1)
+#define MLX5E_TTC_GROUP3_SIZE	 BIT(0)
+#define MLX5E_TTC_TABLE_SIZE	(MLX5E_TTC_GROUP1_SIZE +\
+				 MLX5E_TTC_GROUP2_SIZE +\
+				 MLX5E_TTC_GROUP3_SIZE)
+
+#define MLX5E_INNER_TTC_NUM_GROUPS	3
+#define MLX5E_INNER_TTC_GROUP1_SIZE	BIT(3)
+#define MLX5E_INNER_TTC_GROUP2_SIZE	BIT(1)
+#define MLX5E_INNER_TTC_GROUP3_SIZE	BIT(0)
+#define MLX5E_INNER_TTC_TABLE_SIZE	(MLX5E_INNER_TTC_GROUP1_SIZE +\
+					 MLX5E_INNER_TTC_GROUP2_SIZE +\
+					 MLX5E_INNER_TTC_GROUP3_SIZE)
+
 #ifdef CONFIG_MLX5_EN_RXNFC
 
 struct mlx5e_ethtool_table {
@@ -218,18 +234,12 @@
 
 void mlx5e_set_ttc_basic_params(struct mlx5e_priv *priv, struct ttc_params *ttc_params);
 void mlx5e_set_ttc_ft_params(struct ttc_params *ttc_params);
-void mlx5e_set_inner_ttc_ft_params(struct ttc_params *ttc_params);
 
 int mlx5e_create_ttc_table(struct mlx5e_priv *priv, struct ttc_params *params,
 			   struct mlx5e_ttc_table *ttc);
 void mlx5e_destroy_ttc_table(struct mlx5e_priv *priv,
 			     struct mlx5e_ttc_table *ttc);
 
-int mlx5e_create_inner_ttc_table(struct mlx5e_priv *priv, struct ttc_params *params,
-				 struct mlx5e_ttc_table *ttc);
-void mlx5e_destroy_inner_ttc_table(struct mlx5e_priv *priv,
-				   struct mlx5e_ttc_table *ttc);
-
 void mlx5e_destroy_flow_table(struct mlx5e_flow_table *ft);
 
 void mlx5e_enable_cvlan_filter(struct mlx5e_priv *priv);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en/health.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/en/health.c
@@ -197,9 +197,10 @@
 			struct devlink_health_reporter *reporter, char *err_str,
 			struct mlx5e_err_ctx *err_ctx)
 {
-	if (!reporter) {
-		netdev_err(priv->netdev, err_str);
-		return err_ctx->recover(&err_ctx->ctx);
-	}
+	netdev_err(priv->netdev, err_str);
+
+	if (!reporter)
+		return err_ctx->recover(err_ctx->ctx);
+
 	return devlink_health_report(reporter, err_str, err_ctx);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en/health.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/en/health.h
@@ -10,8 +10,7 @@
 
 static inline bool cqe_syndrome_needs_recover(u8 syndrome)
 {
-	return syndrome == MLX5_CQE_SYNDROME_LOCAL_LENGTH_ERR ||
-	       syndrome == MLX5_CQE_SYNDROME_LOCAL_QP_OP_ERR ||
+	return syndrome == MLX5_CQE_SYNDROME_LOCAL_QP_OP_ERR ||
 	       syndrome == MLX5_CQE_SYNDROME_LOCAL_PROT_ERR ||
 	       syndrome == MLX5_CQE_SYNDROME_WR_FLUSH_ERR;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en/port.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/en/port.c
@@ -73,15 +73,31 @@
 	[MLX5E_50GAUI_2_LAUI_2_50GBASE_CR2_KR2]	= 50000,
 	[MLX5E_50GAUI_1_LAUI_1_50GBASE_CR_KR]	= 50000,
 	[MLX5E_CAUI_4_100GBASE_CR4_KR4]		= 100000,
+	[MLX5E_100GAUI_2_100GBASE_CR2_KR2]	= 100000,
 	[MLX5E_200GAUI_4_200GBASE_CR4_KR4]	= 200000,
 	[MLX5E_400GAUI_8]			= 400000,
 };
 
+bool mlx5e_ptys_ext_supported(struct mlx5_core_dev *mdev)
+{
+	struct mlx5e_port_eth_proto eproto;
+	int err;
+
+	if (MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet))
+		return true;
+
+	err = mlx5_port_query_eth_proto(mdev, 1, true, &eproto);
+	if (err)
+		return false;
+
+	return !!eproto.cap;
+}
+
 static void mlx5e_port_get_speed_arr(struct mlx5_core_dev *mdev,
 				     const u32 **arr, u32 *size,
 				     bool force_legacy)
 {
-	bool ext = force_legacy ? false : MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
+	bool ext = force_legacy ? false : mlx5e_ptys_ext_supported(mdev);
 
 	*size = ext ? ARRAY_SIZE(mlx5e_ext_link_speed) :
 		      ARRAY_SIZE(mlx5e_link_speed);
@@ -176,7 +192,7 @@
 	bool ext;
 	int err;
 
-	ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
+	ext = mlx5e_ptys_ext_supported(mdev);
 	err = mlx5_port_query_eth_proto(mdev, 1, ext, &eproto);
 	if (err)
 		goto out;
@@ -204,7 +220,7 @@
 	int err;
 	int i;
 
-	ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
+	ext = mlx5e_ptys_ext_supported(mdev);
 	err = mlx5_port_query_eth_proto(mdev, 1, ext, &eproto);
 	if (err)
 		return err;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en/port.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/en/port.h
@@ -54,7 +54,7 @@
 int mlx5e_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed);
 u32 mlx5e_port_speed2linkmodes(struct mlx5_core_dev *mdev, u32 speed,
 			       bool force_legacy);
-
+bool mlx5e_ptys_ext_supported(struct mlx5_core_dev *mdev);
 int mlx5e_port_query_pbmc(struct mlx5_core_dev *mdev, void *out);
 int mlx5e_port_set_pbmc(struct mlx5_core_dev *mdev, void *in);
 int mlx5e_port_query_priority2buffer(struct mlx5_core_dev *mdev, u8 *buffer);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c
@@ -155,8 +155,11 @@
 		}
 
 		if (port_buffer->buffer[i].size <
-		    (xoff + max_mtu + (1 << MLX5E_BUFFER_CELL_SHIFT)))
+		    (xoff + max_mtu + (1 << MLX5E_BUFFER_CELL_SHIFT))) {
+			pr_err("buffer_size[%d]=%d is not enough for lossless buffer\n",
+			       i, port_buffer->buffer[i].size);
 			return -ENOMEM;
+		}
 
 		port_buffer->buffer[i].xoff = port_buffer->buffer[i].size - xoff;
 		port_buffer->buffer[i].xon  =
@@ -232,6 +235,26 @@
 	return 0;
 }
 
+static int fill_pfc_en(struct mlx5_core_dev *mdev, u8 *pfc_en)
+{
+	u32 g_rx_pause, g_tx_pause;
+	int err;
+
+	err = mlx5_query_port_pause(mdev, &g_rx_pause, &g_tx_pause);
+	if (err)
+		return err;
+
+	/* If global pause enabled, set all active buffers to lossless.
+	 * Otherwise, check PFC setting.
+	 */
+	if (g_rx_pause || g_tx_pause)
+		*pfc_en = 0xff;
+	else
+		err = mlx5_query_port_pfc(mdev, pfc_en, NULL);
+
+	return err;
+}
+
 #define MINIMUM_MAX_MTU 9216
 int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv,
 				    u32 change, unsigned int mtu,
@@ -277,7 +300,7 @@
 
 	if (change & MLX5E_PORT_BUFFER_PRIO2BUFFER) {
 		update_prio2buffer = true;
-		err = mlx5_query_port_pfc(priv->mdev, &curr_pfc_en, NULL);
+		err = fill_pfc_en(priv->mdev, &curr_pfc_en);
 		if (err)
 			return err;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c
@@ -90,7 +90,7 @@
 		goto out;
 
 	mlx5e_reset_icosq_cc_pc(icosq);
-	mlx5e_free_rx_descs(rq);
+	mlx5e_free_rx_in_progress_descs(rq);
 	clear_bit(MLX5E_SQ_STATE_RECOVERING, &icosq->state);
 	mlx5e_activate_icosq(icosq);
 	mlx5e_activate_rq(rq);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c
@@ -144,10 +144,10 @@
 #if IS_ENABLED(CONFIG_INET) && IS_ENABLED(CONFIG_IPV6)
 	int ret;
 
-	ret = ipv6_stub->ipv6_dst_lookup(dev_net(mirred_dev), NULL, &dst,
-					 fl6);
-	if (ret < 0)
-		return ret;
+	dst = ipv6_stub->ipv6_dst_lookup_flow(dev_net(mirred_dev), NULL, fl6,
+					      NULL);
+	if (IS_ERR(dst))
+		return PTR_ERR(dst);
 
 	if (!(*out_ttl))
 		*out_ttl = ip6_dst_hoplimit(dst);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_geneve.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_geneve.c
@@ -227,6 +227,10 @@
 	option_key = (struct geneve_opt *)&enc_opts.key->data[0];
 	option_mask = (struct geneve_opt *)&enc_opts.mask->data[0];
 
+	if (option_mask->opt_class == 0 && option_mask->type == 0 &&
+	    !memchr_inv(option_mask->opt_data, 0, option_mask->length * 4))
+		return 0;
+
 	if (option_key->length > max_tlv_option_data_len) {
 		NL_SET_ERR_MSG_MOD(extack,
 				   "Matching on GENEVE options: unsupported option len");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h
@@ -27,6 +27,11 @@
 
 #define INL_HDR_START_SZ (sizeof(((struct mlx5_wqe_eth_seg *)NULL)->inline_hdr.start))
 
+static inline bool mlx5e_skb_is_multicast(struct sk_buff *skb)
+{
+	return skb->pkt_type == PACKET_MULTICAST || skb->pkt_type == PACKET_BROADCAST;
+}
+
 static inline bool
 mlx5e_wqc_has_room_for(struct mlx5_wq_cyc *wq, u16 cc, u16 pc, u16 n)
 {
@@ -179,6 +184,16 @@
 	}
 }
 
+static inline void mlx5e_rqwq_reset(struct mlx5e_rq *rq)
+{
+	if (rq->wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ) {
+		mlx5_wq_ll_reset(&rq->mpwqe.wq);
+		rq->mpwqe.actual_wq_head = 0;
+	} else {
+		mlx5_wq_cyc_reset(&rq->wqe.wq);
+	}
+}
+
 /* SW parser related functions */
 
 struct mlx5e_swp_spec {
@@ -189,6 +204,15 @@
 	u8 tun_l4_proto;
 };
 
+static inline void mlx5e_eseg_swp_offsets_add_vlan(struct mlx5_wqe_eth_seg *eseg)
+{
+	/* SWP offsets are in 2-bytes words */
+	eseg->swp_outer_l3_offset += VLAN_HLEN / 2;
+	eseg->swp_outer_l4_offset += VLAN_HLEN / 2;
+	eseg->swp_inner_l3_offset += VLAN_HLEN / 2;
+	eseg->swp_inner_l4_offset += VLAN_HLEN / 2;
+}
+
 static inline void
 mlx5e_set_eseg_swp(struct sk_buff *skb, struct mlx5_wqe_eth_seg *eseg,
 		   struct mlx5e_swp_spec *swp_spec)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h
@@ -75,12 +75,18 @@
 static inline void mlx5e_xdp_tx_enable(struct mlx5e_priv *priv)
 {
 	set_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state);
+
+	if (priv->channels.params.xdp_prog)
+		set_bit(MLX5E_STATE_XDP_ACTIVE, &priv->state);
 }
 
 static inline void mlx5e_xdp_tx_disable(struct mlx5e_priv *priv)
 {
+	if (priv->channels.params.xdp_prog)
+		clear_bit(MLX5E_STATE_XDP_ACTIVE, &priv->state);
+
 	clear_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state);
-	/* let other device's napi(s) see our new state */
+	/* Let other device's napi(s) and XSK wakeups see our new state. */
 	synchronize_rcu();
 }
 
@@ -89,19 +95,9 @@
 	return test_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state);
 }
 
-static inline void mlx5e_xdp_set_open(struct mlx5e_priv *priv)
-{
-	set_bit(MLX5E_STATE_XDP_OPEN, &priv->state);
-}
-
-static inline void mlx5e_xdp_set_closed(struct mlx5e_priv *priv)
-{
-	clear_bit(MLX5E_STATE_XDP_OPEN, &priv->state);
-}
-
-static inline bool mlx5e_xdp_is_open(struct mlx5e_priv *priv)
+static inline bool mlx5e_xdp_is_active(struct mlx5e_priv *priv)
 {
-	return test_bit(MLX5E_STATE_XDP_OPEN, &priv->state);
+	return test_bit(MLX5E_STATE_XDP_ACTIVE, &priv->state);
 }
 
 static inline void mlx5e_xmit_xdp_doorbell(struct mlx5e_xdpsq *sq)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c
@@ -144,6 +144,7 @@
 {
 	clear_bit(MLX5E_CHANNEL_STATE_XSK, c->state);
 	napi_synchronize(&c->napi);
+	synchronize_rcu(); /* Sync with the XSK wakeup. */
 
 	mlx5e_close_rq(&c->xskrq);
 	mlx5e_close_cq(&c->xskrq.cq);
@@ -151,6 +152,10 @@
 	mlx5e_close_cq(&c->xskicosq.cq);
 	mlx5e_close_xdpsq(&c->xsksq);
 	mlx5e_close_cq(&c->xsksq.cq);
+
+	memset(&c->xskrq, 0, sizeof(c->xskrq));
+	memset(&c->xsksq, 0, sizeof(c->xsksq));
+	memset(&c->xskicosq, 0, sizeof(c->xskicosq));
 }
 
 void mlx5e_activate_xsk(struct mlx5e_channel *c)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/tx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/tx.c
@@ -14,7 +14,7 @@
 	struct mlx5e_channel *c;
 	u16 ix;
 
-	if (unlikely(!mlx5e_xdp_is_open(priv)))
+	if (unlikely(!mlx5e_xdp_is_active(priv)))
 		return -ENETDOWN;
 
 	if (unlikely(!mlx5e_qid_get_ch_if_in_group(params, qid, MLX5E_RQ_GROUP_XSK, &ix)))
@@ -33,6 +33,9 @@
 		if (unlikely(!test_bit(MLX5E_SQ_STATE_ENABLED, &c->xskicosq.state)))
 			return 0;
 
+		if (test_and_set_bit(MLX5E_SQ_STATE_PENDING_XSK_TX, &c->xskicosq.state))
+			return 0;
+
 		spin_lock(&c->xskicosq_lock);
 		mlx5e_trigger_irq(&c->xskicosq);
 		spin_unlock(&c->xskicosq_lock);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/en_accel/en_accel.h
@@ -48,7 +48,7 @@
 }
 
 static inline void
-mlx5e_tx_tunnel_accel(struct sk_buff *skb, struct mlx5_wqe_eth_seg *eseg)
+mlx5e_tx_tunnel_accel(struct sk_buff *skb, struct mlx5_wqe_eth_seg *eseg, u16 ihs)
 {
 	struct mlx5e_swp_spec swp_spec = {};
 	unsigned int offset = 0;
@@ -82,6 +82,8 @@
 	}
 
 	mlx5e_set_eseg_swp(skb, eseg, &swp_spec);
+	if (skb_vlan_tag_present(skb) && ihs)
+		mlx5e_eseg_swp_offsets_add_vlan(eseg);
 }
 
 #else
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
@@ -117,7 +117,6 @@
 	struct xfrm_replay_state_esn *replay_esn;
 	u32 seq_bottom;
 	u8 overlap;
-	u32 *esn;
 
 	if (!(sa_entry->x->props.flags & XFRM_STATE_ESN)) {
 		sa_entry->esn_state.trigger = 0;
@@ -130,11 +129,9 @@
 
 	sa_entry->esn_state.esn = xfrm_replay_seqhi(sa_entry->x,
 						    htonl(seq_bottom));
-	esn = &sa_entry->esn_state.esn;
 
 	sa_entry->esn_state.trigger = 1;
 	if (unlikely(overlap && seq_bottom < MLX5E_IPSEC_ESN_SCOPE_MID)) {
-		++(*esn);
 		sa_entry->esn_state.overlap = 0;
 		return true;
 	} else if (unlikely(!overlap &&
@@ -515,9 +512,6 @@
 	struct mlx5_core_dev *mdev = priv->mdev;
 	struct net_device *netdev = priv->netdev;
 
-	if (!priv->ipsec)
-		return;
-
 	if (!(mlx5_accel_ipsec_device_caps(mdev) & MLX5_ACCEL_IPSEC_CAP_ESP) ||
 	    !MLX5_CAP_ETH(mdev, swp)) {
 		mlx5_core_dbg(mdev, "mlx5e: ESP and SWP offload not supported\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c
@@ -121,7 +121,9 @@
 
 	trailer_len = alen + plen + 2;
 
-	pskb_trim(skb, skb->len - trailer_len);
+	ret = pskb_trim(skb, skb->len - trailer_len);
+	if (unlikely(ret))
+		return ret;
 	if (skb->protocol == htons(ETH_P_IP)) {
 		ipv4hdr->tot_len = htons(ntohs(ipv4hdr->tot_len) - trailer_len);
 		ip_send_check(ipv4hdr);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c
@@ -69,8 +69,8 @@
 	struct mlx5e_ktls_offload_context_tx *tx_priv =
 		mlx5e_get_ktls_tx_priv_ctx(tls_ctx);
 
-	mlx5_ktls_destroy_key(priv->mdev, tx_priv->key_id);
 	mlx5e_destroy_tis(priv->mdev, tx_priv->tisn);
+	mlx5_ktls_destroy_key(priv->mdev, tx_priv->key_id);
 	kvfree(tx_priv);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.h
@@ -38,8 +38,8 @@
 
 enum {
 	MLX5E_TLS_PROGRESS_PARAMS_RECORD_TRACKER_STATE_START     = 0,
-	MLX5E_TLS_PROGRESS_PARAMS_RECORD_TRACKER_STATE_SEARCHING = 1,
-	MLX5E_TLS_PROGRESS_PARAMS_RECORD_TRACKER_STATE_TRACKING  = 2,
+	MLX5E_TLS_PROGRESS_PARAMS_RECORD_TRACKER_STATE_TRACKING  = 1,
+	MLX5E_TLS_PROGRESS_PARAMS_RECORD_TRACKER_STATE_SEARCHING = 2,
 };
 
 struct mlx5e_ktls_offload_context_tx {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c
@@ -180,7 +180,7 @@
 
 struct tx_sync_info {
 	u64 rcd_sn;
-	s32 sync_len;
+	u32 sync_len;
 	int nr_frags;
 	skb_frag_t frags[MAX_SKB_FRAGS];
 };
@@ -193,13 +193,14 @@
 
 static enum mlx5e_ktls_sync_retval
 tx_sync_info_get(struct mlx5e_ktls_offload_context_tx *priv_tx,
-		 u32 tcp_seq, struct tx_sync_info *info)
+		 u32 tcp_seq, int datalen, struct tx_sync_info *info)
 {
 	struct tls_offload_context_tx *tx_ctx = priv_tx->tx_ctx;
 	enum mlx5e_ktls_sync_retval ret = MLX5E_KTLS_SYNC_DONE;
 	struct tls_record_info *record;
 	int remaining, i = 0;
 	unsigned long flags;
+	bool ends_before;
 
 	spin_lock_irqsave(&tx_ctx->lock, flags);
 	record = tls_get_record(tx_ctx, tcp_seq, &info->rcd_sn);
@@ -209,9 +210,21 @@
 		goto out;
 	}
 
-	if (unlikely(tcp_seq < tls_record_start_seq(record))) {
-		ret = tls_record_is_start_marker(record) ?
-			MLX5E_KTLS_SYNC_SKIP_NO_DATA : MLX5E_KTLS_SYNC_FAIL;
+	/* There are the following cases:
+	 * 1. packet ends before start marker: bypass offload.
+	 * 2. packet starts before start marker and ends after it: drop,
+	 *    not supported, breaks contract with kernel.
+	 * 3. packet ends before tls record info starts: drop,
+	 *    this packet was already acknowledged and its record info
+	 *    was released.
+	 */
+	ends_before = before(tcp_seq + datalen - 1, tls_record_start_seq(record));
+
+	if (unlikely(tls_record_is_start_marker(record))) {
+		ret = ends_before ? MLX5E_KTLS_SYNC_SKIP_NO_DATA : MLX5E_KTLS_SYNC_FAIL;
+		goto out;
+	} else if (ends_before) {
+		ret = MLX5E_KTLS_SYNC_FAIL;
 		goto out;
 	}
 
@@ -220,7 +233,7 @@
 	while (remaining > 0) {
 		skb_frag_t *frag = &record->frags[i];
 
-		get_page(skb_frag_page(frag));
+		page_ref_inc(skb_frag_page(frag));
 		remaining -= skb_frag_size(frag);
 		info->frags[i++] = *frag;
 	}
@@ -308,7 +321,7 @@
 	stats = sq->stats;
 
 	mlx5e_tx_dma_unmap(sq->pdev, dma);
-	put_page(wi->resync_dump_frag_page);
+	page_ref_dec(wi->resync_dump_frag_page);
 	stats->tls_dump_packets++;
 	stats->tls_dump_bytes += wi->num_bytes;
 }
@@ -337,7 +350,7 @@
 	u8 num_wqebbs;
 	int i = 0;
 
-	ret = tx_sync_info_get(priv_tx, seq, &info);
+	ret = tx_sync_info_get(priv_tx, seq, datalen, &info);
 	if (unlikely(ret != MLX5E_KTLS_SYNC_DONE)) {
 		if (ret == MLX5E_KTLS_SYNC_SKIP_NO_DATA) {
 			stats->tls_skip_no_sync_data++;
@@ -351,14 +364,6 @@
 		goto err_out;
 	}
 
-	if (unlikely(info.sync_len < 0)) {
-		if (likely(datalen <= -info.sync_len))
-			return MLX5E_KTLS_SYNC_DONE;
-
-		stats->tls_drop_bypass_req++;
-		goto err_out;
-	}
-
 	stats->tls_ooo++;
 
 	tx_post_resync_params(sq, priv_tx, info.rcd_sn);
@@ -378,8 +383,6 @@
 	if (unlikely(contig_wqebbs_room < num_wqebbs))
 		mlx5e_fill_sq_frag_edge(sq, wq, pi, contig_wqebbs_room);
 
-	tx_post_resync_params(sq, priv_tx, info.rcd_sn);
-
 	for (; i < info.nr_frags; i++) {
 		unsigned int orig_fsz, frag_offset = 0, n = 0;
 		skb_frag_t *f = &info.frags[i];
@@ -409,12 +412,12 @@
 
 err_out:
 	for (; i < info.nr_frags; i++)
-		/* The put_page() here undoes the page ref obtained in tx_sync_info_get().
+		/* The page_ref_dec() here undoes the page ref obtained in tx_sync_info_get().
 		 * Page refs obtained for the DUMP WQEs above (by page_ref_add) will be
 		 * released only upon their completions (or in mlx5e_free_txqsq_descs,
 		 * if channel closes).
 		 */
-		put_page(skb_frag_page(&info.frags[i]));
+		page_ref_dec(skb_frag_page(&info.frags[i]));
 
 	return MLX5E_KTLS_SYNC_FAIL;
 }
@@ -455,12 +458,18 @@
 		enum mlx5e_ktls_sync_retval ret =
 			mlx5e_ktls_tx_handle_ooo(priv_tx, sq, datalen, seq);
 
-		if (likely(ret == MLX5E_KTLS_SYNC_DONE))
+		switch (ret) {
+		case MLX5E_KTLS_SYNC_DONE:
 			*wqe = mlx5e_sq_fetch_wqe(sq, sizeof(**wqe), pi);
-		else if (ret == MLX5E_KTLS_SYNC_FAIL)
+			break;
+		case MLX5E_KTLS_SYNC_SKIP_NO_DATA:
+			if (likely(!skb->decrypted))
+				goto out;
+			WARN_ON_ONCE(1);
+			/* fall-through */
+		default: /* MLX5E_KTLS_SYNC_FAIL */
 			goto err_out;
-		else /* ret == MLX5E_KTLS_SYNC_SKIP_NO_DATA */
-			goto out;
+		}
 	}
 
 	priv_tx->expected_seq = seq + datalen;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_rxtx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_rxtx.c
@@ -269,7 +269,7 @@
 	int datalen;
 	u32 skb_seq;
 
-	if (MLX5_CAP_GEN(sq->channel->mdev, tls)) {
+	if (MLX5_CAP_GEN(sq->channel->mdev, tls_tx)) {
 		skb = mlx5e_ktls_handle_tx_skb(netdev, sq, skb, wqe, pi);
 		goto out;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_stats.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_stats.c
@@ -35,7 +35,6 @@
 #include <net/sock.h>
 
 #include "en.h"
-#include "accel/tls.h"
 #include "fpga/sdk.h"
 #include "en_accel/tls.h"
 
@@ -51,9 +50,14 @@
 
 #define NUM_TLS_SW_COUNTERS ARRAY_SIZE(mlx5e_tls_sw_stats_desc)
 
+static bool is_tls_atomic_stats(struct mlx5e_priv *priv)
+{
+	return priv->tls && !mlx5_accel_is_ktls_device(priv->mdev);
+}
+
 int mlx5e_tls_get_count(struct mlx5e_priv *priv)
 {
-	if (!priv->tls)
+	if (!is_tls_atomic_stats(priv))
 		return 0;
 
 	return NUM_TLS_SW_COUNTERS;
@@ -63,7 +67,7 @@
 {
 	unsigned int i, idx = 0;
 
-	if (!priv->tls)
+	if (!is_tls_atomic_stats(priv))
 		return 0;
 
 	for (i = 0; i < NUM_TLS_SW_COUNTERS; i++)
@@ -77,7 +81,7 @@
 {
 	int i, idx = 0;
 
-	if (!priv->tls)
+	if (!is_tls_atomic_stats(priv))
 		return 0;
 
 	for (i = 0; i < NUM_TLS_SW_COUNTERS; i++)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
@@ -227,11 +227,13 @@
 
 	ft->g = kcalloc(MLX5E_ARFS_NUM_GROUPS,
 			sizeof(*ft->g), GFP_KERNEL);
-	in = kvzalloc(inlen, GFP_KERNEL);
-	if  (!in || !ft->g) {
-		kvfree(ft->g);
-		kvfree(in);
+	if (!ft->g)
 		return -ENOMEM;
+
+	in = kvzalloc(inlen, GFP_KERNEL);
+	if (!in) {
+		err = -ENOMEM;
+		goto err_free_g;
 	}
 
 	mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
@@ -251,7 +253,7 @@
 		break;
 	default:
 		err = -EINVAL;
-		goto out;
+		goto err_free_in;
 	}
 
 	switch (type) {
@@ -273,7 +275,7 @@
 		break;
 	default:
 		err = -EINVAL;
-		goto out;
+		goto err_free_in;
 	}
 
 	MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
@@ -282,7 +284,7 @@
 	MLX5_SET_CFG(in, end_flow_index, ix - 1);
 	ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
 	if (IS_ERR(ft->g[ft->num_groups]))
-		goto err;
+		goto err_clean_group;
 	ft->num_groups++;
 
 	memset(in, 0, inlen);
@@ -291,18 +293,20 @@
 	MLX5_SET_CFG(in, end_flow_index, ix - 1);
 	ft->g[ft->num_groups] = mlx5_create_flow_group(ft->t, in);
 	if (IS_ERR(ft->g[ft->num_groups]))
-		goto err;
+		goto err_clean_group;
 	ft->num_groups++;
 
 	kvfree(in);
 	return 0;
 
-err:
+err_clean_group:
 	err = PTR_ERR(ft->g[ft->num_groups]);
 	ft->g[ft->num_groups] = NULL;
-out:
+err_free_in:
 	kvfree(in);
-
+err_free_g:
+	kfree(ft->g);
+	ft->g = NULL;
 	return err;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
@@ -109,12 +109,14 @@
 	if (!MLX5_CAP_GEN(priv->mdev, ets))
 		return -EOPNOTSUPP;
 
-	ets->ets_cap = mlx5_max_tc(priv->mdev) + 1;
-	for (i = 0; i < ets->ets_cap; i++) {
+	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
 		err = mlx5_query_port_prio_tc(mdev, i, &ets->prio_tc[i]);
 		if (err)
 			return err;
+	}
 
+	ets->ets_cap = mlx5_max_tc(priv->mdev) + 1;
+	for (i = 0; i < ets->ets_cap; i++) {
 		err = mlx5_query_port_tc_group(mdev, i, &tc_group[i]);
 		if (err)
 			return err;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
@@ -40,9 +40,7 @@
 {
 	struct mlx5_core_dev *mdev = priv->mdev;
 
-	strlcpy(drvinfo->driver, DRIVER_NAME, sizeof(drvinfo->driver));
-	strlcpy(drvinfo->version, DRIVER_VERSION,
-		sizeof(drvinfo->version));
+	strlcpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver));
 	snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
 		 "%d.%d.%04d (%.16s)",
 		 fw_rev_maj(mdev), fw_rev_min(mdev), fw_rev_sub(mdev),
@@ -129,6 +127,10 @@
 				       ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT);
 	MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100GBASE_LR4, legacy,
 				       ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT);
+	MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_100BASE_TX, legacy,
+				       ETHTOOL_LINK_MODE_100baseT_Full_BIT);
+	MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_1000BASE_T, legacy,
+				       ETHTOOL_LINK_MODE_1000baseT_Full_BIT);
 	MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_10GBASE_T, legacy,
 				       ETHTOOL_LINK_MODE_10000baseT_Full_BIT);
 	MLX5_BUILD_PTYS2ETHTOOL_CONFIG(MLX5E_25GBASE_CR, legacy,
@@ -200,7 +202,7 @@
 					struct ptys2ethtool_config **arr,
 					u32 *size)
 {
-	bool ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
+	bool ext = mlx5e_ptys_ext_supported(mdev);
 
 	*arr = ext ? ptys2ext_ethtool_table : ptys2legacy_ethtool_table;
 	*size = ext ? ARRAY_SIZE(ptys2ext_ethtool_table) :
@@ -445,9 +447,7 @@
 
 	if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) {
 		*cur_params = new_channels.params;
-		if (!netif_is_rxfh_configured(priv->netdev))
-			mlx5e_build_default_indir_rqt(priv->rss_params.indirection_rqt,
-						      MLX5E_INDIR_RQT_SIZE, count);
+		mlx5e_num_channels_changed(priv);
 		goto out;
 	}
 
@@ -455,12 +455,8 @@
 	if (arfs_enabled)
 		mlx5e_arfs_disable(priv);
 
-	if (!netif_is_rxfh_configured(priv->netdev))
-		mlx5e_build_default_indir_rqt(priv->rss_params.indirection_rqt,
-					      MLX5E_INDIR_RQT_SIZE, count);
-
 	/* Switch to new channels, set new parameters and close old ones */
-	err = mlx5e_safe_switch_channels(priv, &new_channels, NULL);
+	err = mlx5e_safe_switch_channels(priv, &new_channels, mlx5e_num_channels_changed);
 
 	if (arfs_enabled) {
 		int err2 = mlx5e_arfs_enable(priv);
@@ -706,11 +702,11 @@
 	return 0;
 }
 
-static void ptys2ethtool_supported_advertised_port(struct ethtool_link_ksettings *link_ksettings,
-						   u32 eth_proto_cap,
-						   u8 connector_type, bool ext)
+static void ptys2ethtool_supported_advertised_port(struct mlx5_core_dev *mdev,
+						   struct ethtool_link_ksettings *link_ksettings,
+						   u32 eth_proto_cap, u8 connector_type)
 {
-	if ((!connector_type && !ext) || connector_type >= MLX5E_CONNECTOR_TYPE_NUMBER) {
+	if (!MLX5_CAP_PCAM_FEATURE(mdev, ptys_connector_type)) {
 		if (eth_proto_cap & (MLX5E_PROT_MASK(MLX5E_10GBASE_CR)
 				   | MLX5E_PROT_MASK(MLX5E_10GBASE_SR)
 				   | MLX5E_PROT_MASK(MLX5E_40GBASE_CR4)
@@ -842,9 +838,9 @@
 		[MLX5E_PORT_OTHER]              = PORT_OTHER,
 	};
 
-static u8 get_connector_port(u32 eth_proto, u8 connector_type, bool ext)
+static u8 get_connector_port(struct mlx5_core_dev *mdev, u32 eth_proto, u8 connector_type)
 {
-	if ((connector_type || ext) && connector_type < MLX5E_CONNECTOR_TYPE_NUMBER)
+	if (MLX5_CAP_PCAM_FEATURE(mdev, ptys_connector_type))
 		return ptys2connector_type[connector_type];
 
 	if (eth_proto &
@@ -877,7 +873,7 @@
 			       struct ethtool_link_ksettings *link_ksettings)
 {
 	unsigned long *lp_advertising = link_ksettings->link_modes.lp_advertising;
-	bool ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
+	bool ext = mlx5e_ptys_ext_supported(mdev);
 
 	ptys2ethtool_adver_link(lp_advertising, eth_proto_lp, ext);
 }
@@ -906,7 +902,7 @@
 			   __func__, err);
 		goto err_query_regs;
 	}
-	ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
+	ext = !!MLX5_GET_ETH_PROTO(ptys_reg, out, true, eth_proto_capability);
 	eth_proto_cap    = MLX5_GET_ETH_PROTO(ptys_reg, out, ext,
 					      eth_proto_capability);
 	eth_proto_admin  = MLX5_GET_ETH_PROTO(ptys_reg, out, ext,
@@ -943,11 +939,11 @@
 			 link_ksettings);
 
 	eth_proto_oper = eth_proto_oper ? eth_proto_oper : eth_proto_cap;
-
-	link_ksettings->base.port = get_connector_port(eth_proto_oper,
-						       connector_type, ext);
-	ptys2ethtool_supported_advertised_port(link_ksettings, eth_proto_admin,
-					       connector_type, ext);
+	connector_type = connector_type < MLX5E_CONNECTOR_TYPE_NUMBER ?
+			 connector_type : MLX5E_PORT_UNKNOWN;
+	link_ksettings->base.port = get_connector_port(mdev, eth_proto_oper, connector_type);
+	ptys2ethtool_supported_advertised_port(mdev, link_ksettings, eth_proto_admin,
+					       connector_type);
 	get_lp_advertising(mdev, eth_proto_lp, link_ksettings);
 
 	if (an_status == MLX5_AN_COMPLETE)
@@ -982,6 +978,22 @@
 	return mlx5e_ethtool_get_link_ksettings(priv, link_ksettings);
 }
 
+static int mlx5e_speed_validate(struct net_device *netdev, bool ext,
+				const unsigned long link_modes, u8 autoneg)
+{
+	/* Extended link-mode has no speed limitations. */
+	if (ext)
+		return 0;
+
+	if ((link_modes & MLX5E_PROT_MASK(MLX5E_56GBASE_R4)) &&
+	    autoneg != AUTONEG_ENABLE) {
+		netdev_err(netdev, "%s: 56G link speed requires autoneg enabled\n",
+			   __func__);
+		return -EINVAL;
+	}
+	return 0;
+}
+
 static u32 mlx5e_ethtool2ptys_adver_link(const unsigned long *link_modes)
 {
 	u32 i, ptys_modes = 0;
@@ -1027,18 +1039,11 @@
 	return bitmap_intersects(modes, adver, __ETHTOOL_LINK_MODE_MASK_NBITS);
 }
 
-static bool ext_speed_requested(u32 speed)
-{
-#define MLX5E_MAX_PTYS_LEGACY_SPEED 100000
-	return !!(speed > MLX5E_MAX_PTYS_LEGACY_SPEED);
-}
-
-static bool ext_requested(u8 autoneg, const unsigned long *adver, u32 speed)
+static bool ext_requested(u8 autoneg, const unsigned long *adver, bool ext_supported)
 {
 	bool ext_link_mode = ext_link_mode_requested(adver);
-	bool ext_speed = ext_speed_requested(speed);
 
-	return  autoneg == AUTONEG_ENABLE ? ext_link_mode : ext_speed;
+	return  autoneg == AUTONEG_ENABLE ? ext_link_mode : ext_supported;
 }
 
 int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv,
@@ -1065,8 +1070,8 @@
 	autoneg = link_ksettings->base.autoneg;
 	speed = link_ksettings->base.speed;
 
-	ext = ext_requested(autoneg, adver, speed),
-	ext_supported = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
+	ext_supported = mlx5e_ptys_ext_supported(mdev);
+	ext = ext_requested(autoneg, adver, ext_supported);
 	if (!ext_supported && ext)
 		return -EOPNOTSUPP;
 
@@ -1081,13 +1086,9 @@
 	link_modes = autoneg == AUTONEG_ENABLE ? ethtool2ptys_adver_func(adver) :
 		mlx5e_port_speed2linkmodes(mdev, speed, !ext);
 
-	if ((link_modes & MLX5E_PROT_MASK(MLX5E_56GBASE_R4)) &&
-	    autoneg != AUTONEG_ENABLE) {
-		netdev_err(priv->netdev, "%s: 56G link speed requires autoneg enabled\n",
-			   __func__);
-		err = -EINVAL;
+	err = mlx5e_speed_validate(priv->netdev, ext, link_modes, autoneg);
+	if (err)
 		goto out;
-	}
 
 	link_modes = link_modes & eproto.cap;
 	if (!link_modes) {
@@ -1107,7 +1108,12 @@
 	if (!an_changes && link_modes == eproto.admin)
 		goto out;
 
-	mlx5_port_set_eth_ptys(mdev, an_disable, link_modes, ext);
+	err = mlx5_port_set_eth_ptys(mdev, an_disable, link_modes, ext);
+	if (err) {
+		netdev_err(priv->netdev, "%s: failed to set ptys reg: %d\n", __func__, err);
+		goto out;
+	}
+
 	mlx5_toggle_port_link(mdev);
 
 out:
@@ -1561,6 +1567,10 @@
 	int mode;
 	int err;
 
+	if (bitmap_weight((unsigned long *)&fecparam->fec,
+			  ETHTOOL_FEC_BASER_BIT + 1) > 1)
+		return -EOPNOTSUPP;
+
 	for (mode = 0; mode < ARRAY_SIZE(pplm_fec_2_ethtool); mode++) {
 		if (!(pplm_fec_2_ethtool[mode] & fecparam->fec))
 			continue;
@@ -1643,7 +1653,7 @@
 		break;
 	case MLX5_MODULE_ID_SFP:
 		modinfo->type       = ETH_MODULE_SFF_8472;
-		modinfo->eeprom_len = MLX5_EEPROM_PAGE_LENGTH;
+		modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
 		break;
 	default:
 		netdev_err(priv->netdev, "%s: cable type not recognized:0x%x\n",
@@ -1680,7 +1690,7 @@
 		if (size_read < 0) {
 			netdev_err(priv->netdev, "%s: mlx5_query_eeprom failed:0x%x\n",
 				   __func__, size_read);
-			return 0;
+			return size_read;
 		}
 
 		i += size_read;
@@ -1808,6 +1818,7 @@
 {
 	struct mlx5e_priv *priv = netdev_priv(netdev);
 	struct mlx5_core_dev *mdev = priv->mdev;
+	int err;
 
 	if (!MLX5_CAP_GEN(mdev, cqe_compression))
 		return -EOPNOTSUPP;
@@ -1817,7 +1828,10 @@
 		return -EINVAL;
 	}
 
-	mlx5e_modify_rx_cqe_compression_locked(priv, enable);
+	err = mlx5e_modify_rx_cqe_compression_locked(priv, enable);
+	if (err)
+		return err;
+
 	priv->channels.params.rx_cqe_compress_def = enable;
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
@@ -217,6 +217,9 @@
 		break;
 	}
 
+	if (WARN_ONCE(*rule_p, "VLAN rule already exists type %d", rule_type))
+		return 0;
+
 	*rule_p = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
 
 	if (IS_ERR(*rule_p)) {
@@ -397,8 +400,7 @@
 	for_each_set_bit(i, priv->fs.vlan.active_svlans, VLAN_N_VID)
 		mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_STAG_VID, i);
 
-	if (priv->fs.vlan.cvlan_filter_disabled &&
-	    !(priv->netdev->flags & IFF_PROMISC))
+	if (priv->fs.vlan.cvlan_filter_disabled)
 		mlx5e_add_any_vid_rules(priv);
 }
 
@@ -415,8 +417,12 @@
 	for_each_set_bit(i, priv->fs.vlan.active_svlans, VLAN_N_VID)
 		mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_MATCH_STAG_VID, i);
 
-	if (priv->fs.vlan.cvlan_filter_disabled &&
-	    !(priv->netdev->flags & IFF_PROMISC))
+	WARN_ON_ONCE(!(test_bit(MLX5E_STATE_DESTROYING, &priv->state)));
+
+	/* must be called after DESTROY bit is set and
+	 * set_rx_mode is called and flushed
+	 */
+	if (priv->fs.vlan.cvlan_filter_disabled)
 		mlx5e_del_any_vid_rules(priv);
 }
 
@@ -904,22 +910,6 @@
 	return err;
 }
 
-#define MLX5E_TTC_NUM_GROUPS	3
-#define MLX5E_TTC_GROUP1_SIZE	(BIT(3) + MLX5E_NUM_TUNNEL_TT)
-#define MLX5E_TTC_GROUP2_SIZE	 BIT(1)
-#define MLX5E_TTC_GROUP3_SIZE	 BIT(0)
-#define MLX5E_TTC_TABLE_SIZE	(MLX5E_TTC_GROUP1_SIZE +\
-				 MLX5E_TTC_GROUP2_SIZE +\
-				 MLX5E_TTC_GROUP3_SIZE)
-
-#define MLX5E_INNER_TTC_NUM_GROUPS	3
-#define MLX5E_INNER_TTC_GROUP1_SIZE	BIT(3)
-#define MLX5E_INNER_TTC_GROUP2_SIZE	BIT(1)
-#define MLX5E_INNER_TTC_GROUP3_SIZE	BIT(0)
-#define MLX5E_INNER_TTC_TABLE_SIZE	(MLX5E_INNER_TTC_GROUP1_SIZE +\
-					 MLX5E_INNER_TTC_GROUP2_SIZE +\
-					 MLX5E_INNER_TTC_GROUP3_SIZE)
-
 static int mlx5e_create_ttc_table_groups(struct mlx5e_ttc_table *ttc,
 					 bool use_ipv)
 {
@@ -937,6 +927,7 @@
 	in = kvzalloc(inlen, GFP_KERNEL);
 	if (!in) {
 		kfree(ft->g);
+		ft->g = NULL;
 		return -ENOMEM;
 	}
 
@@ -1077,6 +1068,7 @@
 	in = kvzalloc(inlen, GFP_KERNEL);
 	if (!in) {
 		kfree(ft->g);
+		ft->g = NULL;
 		return -ENOMEM;
 	}
 
@@ -1131,7 +1123,7 @@
 	ttc_params->inner_ttc = &priv->fs.inner_ttc;
 }
 
-void mlx5e_set_inner_ttc_ft_params(struct ttc_params *ttc_params)
+static void mlx5e_set_inner_ttc_ft_params(struct ttc_params *ttc_params)
 {
 	struct mlx5_flow_table_attr *ft_attr = &ttc_params->ft_attr;
 
@@ -1150,8 +1142,8 @@
 	ft_attr->prio = MLX5E_NIC_PRIO;
 }
 
-int mlx5e_create_inner_ttc_table(struct mlx5e_priv *priv, struct ttc_params *params,
-				 struct mlx5e_ttc_table *ttc)
+static int mlx5e_create_inner_ttc_table(struct mlx5e_priv *priv, struct ttc_params *params,
+					struct mlx5e_ttc_table *ttc)
 {
 	struct mlx5e_flow_table *ft = &ttc->ft;
 	int err;
@@ -1181,8 +1173,8 @@
 	return err;
 }
 
-void mlx5e_destroy_inner_ttc_table(struct mlx5e_priv *priv,
-				   struct mlx5e_ttc_table *ttc)
+static void mlx5e_destroy_inner_ttc_table(struct mlx5e_priv *priv,
+					  struct mlx5e_ttc_table *ttc)
 {
 	if (!mlx5e_tunnel_inner_ft_supported(priv->mdev))
 		return;
@@ -1356,6 +1348,7 @@
 	ft->g[ft->num_groups] = NULL;
 	mlx5e_destroy_groups(ft);
 	kvfree(in);
+	kfree(ft->g);
 
 	return err;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c
@@ -676,7 +676,7 @@
 	if (num_tuples <= 0) {
 		netdev_warn(priv->netdev, "%s: flow is not valid %d\n",
 			    __func__, num_tuples);
-		return num_tuples;
+		return num_tuples < 0 ? num_tuples : -EINVAL;
 	}
 
 	eth_ft = get_flow_table(priv, fs, num_tuples);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -266,12 +266,17 @@
 
 static int mlx5e_create_umr_mkey(struct mlx5_core_dev *mdev,
 				 u64 npages, u8 page_shift,
-				 struct mlx5_core_mkey *umr_mkey)
+				 struct mlx5_core_mkey *umr_mkey,
+				 dma_addr_t filler_addr)
 {
-	int inlen = MLX5_ST_SZ_BYTES(create_mkey_in);
+	struct mlx5_mtt *mtt;
+	int inlen;
 	void *mkc;
 	u32 *in;
 	int err;
+	int i;
+
+	inlen = MLX5_ST_SZ_BYTES(create_mkey_in) + sizeof(*mtt) * npages;
 
 	in = kvzalloc(inlen, GFP_KERNEL);
 	if (!in)
@@ -291,6 +296,18 @@
 	MLX5_SET(mkc, mkc, translations_octword_size,
 		 MLX5_MTT_OCTW(npages));
 	MLX5_SET(mkc, mkc, log_page_size, page_shift);
+	MLX5_SET(create_mkey_in, in, translations_octword_actual_size,
+		 MLX5_MTT_OCTW(npages));
+
+	/* Initialize the mkey with all MTTs pointing to a default
+	 * page (filler_addr). When the channels are activated, UMR
+	 * WQEs will redirect the RX WQEs to the actual memory from
+	 * the RQ's pool, while the gaps (wqe_overflow) remain mapped
+	 * to the default page.
+	 */
+	mtt = MLX5_ADDR_OF(create_mkey_in, in, klm_pas_mtt);
+	for (i = 0 ; i < npages ; i++)
+		mtt[i].ptag = cpu_to_be64(filler_addr);
 
 	err = mlx5_core_create_mkey(mdev, umr_mkey, in, inlen);
 
@@ -302,7 +319,8 @@
 {
 	u64 num_mtts = MLX5E_REQUIRED_MTTS(mlx5_wq_ll_get_size(&rq->mpwqe.wq));
 
-	return mlx5e_create_umr_mkey(mdev, num_mtts, PAGE_SHIFT, &rq->umr_mkey);
+	return mlx5e_create_umr_mkey(mdev, num_mtts, PAGE_SHIFT, &rq->umr_mkey,
+				     rq->wqe_overflow.addr);
 }
 
 static inline u64 mlx5e_get_mpwqe_offset(struct mlx5e_rq *rq, u16 wqe_ix)
@@ -370,6 +388,28 @@
 	mlx5e_reporter_rq_cqe_err(rq);
 }
 
+static int mlx5e_alloc_mpwqe_rq_drop_page(struct mlx5e_rq *rq)
+{
+	rq->wqe_overflow.page = alloc_page(GFP_KERNEL);
+	if (!rq->wqe_overflow.page)
+		return -ENOMEM;
+
+	rq->wqe_overflow.addr = dma_map_page(rq->pdev, rq->wqe_overflow.page, 0,
+					     PAGE_SIZE, rq->buff.map_dir);
+	if (dma_mapping_error(rq->pdev, rq->wqe_overflow.addr)) {
+		__free_page(rq->wqe_overflow.page);
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+static void mlx5e_free_mpwqe_rq_drop_page(struct mlx5e_rq *rq)
+{
+	 dma_unmap_page(rq->pdev, rq->wqe_overflow.addr, PAGE_SIZE,
+			rq->buff.map_dir);
+	 __free_page(rq->wqe_overflow.page);
+}
+
 static int mlx5e_alloc_rq(struct mlx5e_channel *c,
 			  struct mlx5e_params *params,
 			  struct mlx5e_xsk_param *xsk,
@@ -432,7 +472,11 @@
 		err = mlx5_wq_ll_create(mdev, &rqp->wq, rqc_wq, &rq->mpwqe.wq,
 					&rq->wq_ctrl);
 		if (err)
-			return err;
+			goto err_rq_wq_destroy;
+
+		err = mlx5e_alloc_mpwqe_rq_drop_page(rq);
+		if (err)
+			goto err_rq_wq_destroy;
 
 		rq->mpwqe.wq.db = &rq->mpwqe.wq.db[MLX5_RCV_DBR];
 
@@ -474,7 +518,7 @@
 
 		err = mlx5e_create_rq_umr_mkey(mdev, rq);
 		if (err)
-			goto err_rq_wq_destroy;
+			goto err_rq_drop_page;
 		rq->mkey_be = cpu_to_be32(rq->umr_mkey.key);
 
 		err = mlx5e_rq_alloc_mpwqe_info(rq, c);
@@ -485,7 +529,7 @@
 		err = mlx5_wq_cyc_create(mdev, &rqp->wq, rqc_wq, &rq->wqe.wq,
 					 &rq->wq_ctrl);
 		if (err)
-			return err;
+			goto err_rq_wq_destroy;
 
 		rq->wqe.wq.db = &rq->wqe.wq.db[MLX5_RCV_DBR];
 
@@ -622,6 +666,8 @@
 	case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ:
 		kvfree(rq->mpwqe.info);
 		mlx5_core_destroy_mkey(mdev, &rq->umr_mkey);
+err_rq_drop_page:
+		mlx5e_free_mpwqe_rq_drop_page(rq);
 		break;
 	default: /* MLX5_WQ_TYPE_CYCLIC */
 		kvfree(rq->wqe.frags);
@@ -649,6 +695,7 @@
 	case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ:
 		kvfree(rq->mpwqe.info);
 		mlx5_core_destroy_mkey(rq->mdev, &rq->umr_mkey);
+		mlx5e_free_mpwqe_rq_drop_page(rq);
 		break;
 	default: /* MLX5_WQ_TYPE_CYCLIC */
 		kvfree(rq->wqe.frags);
@@ -723,6 +770,9 @@
 	if (!in)
 		return -ENOMEM;
 
+	if (curr_state == MLX5_RQC_STATE_RST && next_state == MLX5_RQC_STATE_RDY)
+		mlx5e_rqwq_reset(rq);
+
 	rqc = MLX5_ADDR_OF(modify_rq_in, in, ctx);
 
 	MLX5_SET(modify_rq_in, in, rq_state, curr_state);
@@ -821,6 +871,29 @@
 	return -ETIMEDOUT;
 }
 
+void mlx5e_free_rx_in_progress_descs(struct mlx5e_rq *rq)
+{
+	struct mlx5_wq_ll *wq;
+	u16 head;
+	int i;
+
+	if (rq->wq_type != MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ)
+		return;
+
+	wq = &rq->mpwqe.wq;
+	head = wq->head;
+
+	/* Outstanding UMR WQEs (in progress) start at wq->head */
+	for (i = 0; i < rq->mpwqe.umr_in_progress; i++) {
+		rq->dealloc_wqe(rq, head);
+		head = mlx5_wq_ll_get_wqe_next_ix(wq, head);
+	}
+
+	rq->mpwqe.actual_wq_head = wq->head;
+	rq->mpwqe.umr_in_progress = 0;
+	rq->mpwqe.umr_completed = 0;
+}
+
 void mlx5e_free_rx_descs(struct mlx5e_rq *rq)
 {
 	__be16 wqe_ix_be;
@@ -828,14 +901,8 @@
 
 	if (rq->wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ) {
 		struct mlx5_wq_ll *wq = &rq->mpwqe.wq;
-		u16 head = wq->head;
-		int i;
 
-		/* Outstanding UMR WQEs (in progress) start at wq->head */
-		for (i = 0; i < rq->mpwqe.umr_in_progress; i++) {
-			rq->dealloc_wqe(rq, head);
-			head = mlx5_wq_ll_get_wqe_next_ix(wq, head);
-		}
+		mlx5e_free_rx_in_progress_descs(rq);
 
 		while (!mlx5_wq_ll_is_empty(wq)) {
 			struct mlx5e_rx_wqe_ll *wqe;
@@ -1693,11 +1760,10 @@
 			  struct mlx5e_params *params,
 			  struct mlx5e_channel_param *cparam)
 {
-	struct mlx5e_priv *priv = c->priv;
 	int err, tc;
 
 	for (tc = 0; tc < params->num_tc; tc++) {
-		int txq_ix = c->ix + tc * priv->max_nch;
+		int txq_ix = c->ix + tc * params->num_channels;
 
 		err = mlx5e_open_txqsq(c, c->priv->tisn[c->lag_port][tc], txq_ix,
 				       params, &cparam->sq, &c->sq[tc], tc);
@@ -2299,8 +2365,9 @@
 {
 	switch (params->rq_wq_type) {
 	case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ:
-		return order_base_2(MLX5E_UMR_WQEBBS) +
-			mlx5e_get_rq_log_wq_sz(rqp->rqc);
+		return max_t(u8, MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE,
+			     order_base_2(MLX5E_UMR_WQEBBS) +
+			     mlx5e_get_rq_log_wq_sz(rqp->rqc));
 	default: /* MLX5_WQ_TYPE_CYCLIC */
 		return MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE;
 	}
@@ -2739,7 +2806,8 @@
 		mlx5_core_modify_tir(mdev, priv->indir_tir[tt].tirn, in, inlen);
 	}
 
-	if (!mlx5e_tunnel_inner_ft_supported(priv->mdev))
+	/* Verify inner tirs resources allocated */
+	if (!priv->inner_indir_tir[0].tirn)
 		return;
 
 	for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++) {
@@ -2878,41 +2946,52 @@
 		netdev_set_tc_queue(netdev, tc, nch, 0);
 }
 
-static void mlx5e_build_tc2txq_maps(struct mlx5e_priv *priv)
+static void mlx5e_update_netdev_queues(struct mlx5e_priv *priv)
 {
-	int i, tc;
+	int num_txqs = priv->channels.num * priv->channels.params.num_tc;
+	int num_rxqs = priv->channels.num * priv->profile->rq_groups;
+	struct net_device *netdev = priv->netdev;
 
-	for (i = 0; i < priv->max_nch; i++)
-		for (tc = 0; tc < priv->profile->max_tc; tc++)
-			priv->channel_tc2txq[i][tc] = i + tc * priv->max_nch;
+	mlx5e_netdev_set_tcs(netdev);
+	netif_set_real_num_tx_queues(netdev, num_txqs);
+	netif_set_real_num_rx_queues(netdev, num_rxqs);
 }
 
-static void mlx5e_build_tx2sq_maps(struct mlx5e_priv *priv)
+int mlx5e_num_channels_changed(struct mlx5e_priv *priv)
 {
-	struct mlx5e_channel *c;
-	struct mlx5e_txqsq *sq;
-	int i, tc;
+	u16 count = priv->channels.params.num_channels;
+
+	if (!netif_is_rxfh_configured(priv->netdev))
+		mlx5e_build_default_indir_rqt(priv->rss_params.indirection_rqt,
+					      MLX5E_INDIR_RQT_SIZE, count);
+
+	return 0;
+}
+
+static void mlx5e_build_txq_maps(struct mlx5e_priv *priv)
+{
+	int i, ch;
+
+	ch = priv->channels.num;
+
+	for (i = 0; i < ch; i++) {
+		int tc;
+
+		for (tc = 0; tc < priv->channels.params.num_tc; tc++) {
+			struct mlx5e_channel *c = priv->channels.c[i];
+			struct mlx5e_txqsq *sq = &c->sq[tc];
 
-	for (i = 0; i < priv->channels.num; i++) {
-		c = priv->channels.c[i];
-		for (tc = 0; tc < c->num_tc; tc++) {
-			sq = &c->sq[tc];
 			priv->txq2sq[sq->txq_ix] = sq;
+			priv->channel_tc2realtxq[i][tc] = i + tc * ch;
 		}
 	}
 }
 
 void mlx5e_activate_priv_channels(struct mlx5e_priv *priv)
 {
-	int num_txqs = priv->channels.num * priv->channels.params.num_tc;
-	int num_rxqs = priv->channels.num * priv->profile->rq_groups;
-	struct net_device *netdev = priv->netdev;
-
-	mlx5e_netdev_set_tcs(netdev);
-	netif_set_real_num_tx_queues(netdev, num_txqs);
-	netif_set_real_num_rx_queues(netdev, num_rxqs);
+	mlx5e_update_netdev_queues(priv);
 
-	mlx5e_build_tx2sq_maps(priv);
+	mlx5e_build_txq_maps(priv);
 	mlx5e_activate_channels(&priv->channels);
 	mlx5e_xdp_tx_enable(priv);
 	netif_tx_start_all_queues(priv->netdev);
@@ -2946,7 +3025,7 @@
 
 static void mlx5e_switch_priv_channels(struct mlx5e_priv *priv,
 				       struct mlx5e_channels *new_chs,
-				       mlx5e_fp_hw_modify hw_modify)
+				       mlx5e_fp_preactivate preactivate)
 {
 	struct net_device *netdev = priv->netdev;
 	int new_num_txqs;
@@ -2965,9 +3044,11 @@
 
 	priv->channels = *new_chs;
 
-	/* New channels are ready to roll, modify HW settings if needed */
-	if (hw_modify)
-		hw_modify(priv);
+	/* New channels are ready to roll, call the preactivate hook if needed
+	 * to modify HW settings or update kernel parameters.
+	 */
+	if (preactivate)
+		preactivate(priv);
 
 	priv->profile->update_rx(priv);
 	mlx5e_activate_priv_channels(priv);
@@ -2979,7 +3060,7 @@
 
 int mlx5e_safe_switch_channels(struct mlx5e_priv *priv,
 			       struct mlx5e_channels *new_chs,
-			       mlx5e_fp_hw_modify hw_modify)
+			       mlx5e_fp_preactivate preactivate)
 {
 	int err;
 
@@ -2987,7 +3068,7 @@
 	if (err)
 		return err;
 
-	mlx5e_switch_priv_channels(priv, new_chs, hw_modify);
+	mlx5e_switch_priv_channels(priv, new_chs, preactivate);
 	return 0;
 }
 
@@ -3005,15 +3086,32 @@
 	priv->tstamp.rx_filter = HWTSTAMP_FILTER_NONE;
 }
 
+static void mlx5e_modify_admin_state(struct mlx5_core_dev *mdev,
+				     enum mlx5_port_status state)
+{
+	struct mlx5_eswitch *esw = mdev->priv.eswitch;
+	int vport_admin_state;
+
+	mlx5_set_port_admin_status(mdev, state);
+
+	if (!MLX5_ESWITCH_MANAGER(mdev) || mlx5_eswitch_mode(esw) == MLX5_ESWITCH_OFFLOADS ||
+	    !MLX5_CAP_GEN(mdev, uplink_follow))
+		return;
+
+	if (state == MLX5_PORT_UP)
+		vport_admin_state = MLX5_VPORT_ADMIN_STATE_AUTO;
+	else
+		vport_admin_state = MLX5_VPORT_ADMIN_STATE_DOWN;
+
+	mlx5_eswitch_set_vport_state(esw, MLX5_VPORT_UPLINK, vport_admin_state);
+}
+
 int mlx5e_open_locked(struct net_device *netdev)
 {
 	struct mlx5e_priv *priv = netdev_priv(netdev);
-	bool is_xdp = priv->channels.params.xdp_prog;
 	int err;
 
 	set_bit(MLX5E_STATE_OPENED, &priv->state);
-	if (is_xdp)
-		mlx5e_xdp_set_open(priv);
 
 	err = mlx5e_open_channels(priv, &priv->channels);
 	if (err)
@@ -3028,8 +3126,6 @@
 	return 0;
 
 err_clear_state_opened_flag:
-	if (is_xdp)
-		mlx5e_xdp_set_closed(priv);
 	clear_bit(MLX5E_STATE_OPENED, &priv->state);
 	return err;
 }
@@ -3042,7 +3138,7 @@
 	mutex_lock(&priv->state_lock);
 	err = mlx5e_open_locked(netdev);
 	if (!err)
-		mlx5_set_port_admin_status(priv->mdev, MLX5_PORT_UP);
+		mlx5e_modify_admin_state(priv->mdev, MLX5_PORT_UP);
 	mutex_unlock(&priv->state_lock);
 
 	if (mlx5_vxlan_allowed(priv->mdev->vxlan))
@@ -3061,8 +3157,6 @@
 	if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
 		return 0;
 
-	if (priv->channels.params.xdp_prog)
-		mlx5e_xdp_set_closed(priv);
 	clear_bit(MLX5E_STATE_OPENED, &priv->state);
 
 	netif_carrier_off(priv->netdev);
@@ -3081,7 +3175,7 @@
 		return -ENODEV;
 
 	mutex_lock(&priv->state_lock);
-	mlx5_set_port_admin_status(priv->mdev, MLX5_PORT_DOWN);
+	mlx5e_modify_admin_state(priv->mdev, MLX5_PORT_DOWN);
 	err = mlx5e_close_locked(netdev);
 	mutex_unlock(&priv->state_lock);
 
@@ -3380,14 +3474,15 @@
 	return err;
 }
 
-void mlx5e_destroy_indirect_tirs(struct mlx5e_priv *priv, bool inner_ttc)
+void mlx5e_destroy_indirect_tirs(struct mlx5e_priv *priv)
 {
 	int i;
 
 	for (i = 0; i < MLX5E_NUM_INDIR_TIRS; i++)
 		mlx5e_destroy_tir(priv->mdev, &priv->indir_tir[i]);
 
-	if (!inner_ttc || !mlx5e_tunnel_inner_ft_supported(priv->mdev))
+	/* Verify inner tirs resources allocated */
+	if (!priv->inner_indir_tir[0].tirn)
 		return;
 
 	for (i = 0; i < MLX5E_NUM_INDIR_TIRS; i++)
@@ -3536,6 +3631,7 @@
 
 		s->rx_packets   += rq_stats->packets + xskrq_stats->packets;
 		s->rx_bytes     += rq_stats->bytes + xskrq_stats->bytes;
+		s->multicast    += rq_stats->mcast_packets + xskrq_stats->mcast_packets;
 
 		for (j = 0; j < priv->max_opened_tc; j++) {
 			struct mlx5e_sq_stats *sq_stats = &channel_stats->sq[j];
@@ -3551,10 +3647,14 @@
 mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
 {
 	struct mlx5e_priv *priv = netdev_priv(dev);
-	struct mlx5e_vport_stats *vstats = &priv->stats.vport;
 	struct mlx5e_pport_stats *pstats = &priv->stats.pport;
 
-	if (!mlx5e_monitor_counter_supported(priv)) {
+	/* In switchdev mode, monitor counters doesn't monitor
+	 * rx/tx stats of 802_3. The update stats mechanism
+	 * should keep the 802_3 layout counters updated
+	 */
+	if (!mlx5e_monitor_counter_supported(priv) ||
+	    mlx5e_is_uplink_rep(priv)) {
 		/* update HW stats in background for next time */
 		mlx5e_queue_update_stats(priv);
 	}
@@ -3568,7 +3668,7 @@
 		mlx5e_fold_sw_stats64(priv, stats);
 	}
 
-	stats->rx_dropped = priv->stats.qcnt.rx_out_of_buffer;
+	stats->rx_missed_errors = priv->stats.qcnt.rx_out_of_buffer;
 
 	stats->rx_length_errors =
 		PPORT_802_3_GET(pstats, a_in_range_length_errors) +
@@ -3581,12 +3681,6 @@
 	stats->rx_errors = stats->rx_length_errors + stats->rx_crc_errors +
 			   stats->rx_frame_errors;
 	stats->tx_errors = stats->tx_aborted_errors + stats->tx_carrier_errors;
-
-	/* vport multicast also counts packets that are dropped due to steering
-	 * or rx out of buffer
-	 */
-	stats->multicast =
-		VPORT_COUNTER_GET(vstats, received_eth_multicast.packets);
 }
 
 static void mlx5e_set_rx_mode(struct net_device *dev)
@@ -3706,20 +3800,67 @@
 	return mlx5_set_port_fcs(mdev, !enable);
 }
 
+static int mlx5e_set_rx_port_ts(struct mlx5_core_dev *mdev, bool enable)
+{
+	u32 in[MLX5_ST_SZ_DW(pcmr_reg)] = {};
+	bool supported, curr_state;
+	int err;
+
+	if (!MLX5_CAP_GEN(mdev, ports_check))
+		return 0;
+
+	err = mlx5_query_ports_check(mdev, in, sizeof(in));
+	if (err)
+		return err;
+
+	supported = MLX5_GET(pcmr_reg, in, rx_ts_over_crc_cap);
+	curr_state = MLX5_GET(pcmr_reg, in, rx_ts_over_crc);
+
+	if (!supported || enable == curr_state)
+		return 0;
+
+	MLX5_SET(pcmr_reg, in, local_port, 1);
+	MLX5_SET(pcmr_reg, in, rx_ts_over_crc, enable);
+
+	return mlx5_set_ports_check(mdev, in, sizeof(in));
+}
+
 static int set_feature_rx_fcs(struct net_device *netdev, bool enable)
 {
 	struct mlx5e_priv *priv = netdev_priv(netdev);
+	struct mlx5e_channels *chs = &priv->channels;
+	struct mlx5_core_dev *mdev = priv->mdev;
 	int err;
 
 	mutex_lock(&priv->state_lock);
 
-	priv->channels.params.scatter_fcs_en = enable;
-	err = mlx5e_modify_channels_scatter_fcs(&priv->channels, enable);
-	if (err)
-		priv->channels.params.scatter_fcs_en = !enable;
+	if (enable) {
+		err = mlx5e_set_rx_port_ts(mdev, false);
+		if (err)
+			goto out;
 
-	mutex_unlock(&priv->state_lock);
+		chs->params.scatter_fcs_en = true;
+		err = mlx5e_modify_channels_scatter_fcs(chs, true);
+		if (err) {
+			chs->params.scatter_fcs_en = false;
+			mlx5e_set_rx_port_ts(mdev, true);
+		}
+	} else {
+		chs->params.scatter_fcs_en = false;
+		err = mlx5e_modify_channels_scatter_fcs(chs, false);
+		if (err) {
+			chs->params.scatter_fcs_en = true;
+			goto out;
+		}
+		err = mlx5e_set_rx_port_ts(mdev, true);
+		if (err) {
+			mlx5_core_warn(mdev, "Failed to set RX port timestamp %d\n", err);
+			err = 0;
+		}
+	}
 
+out:
+	mutex_unlock(&priv->state_lock);
 	return err;
 }
 
@@ -3761,12 +3902,11 @@
 
 static int mlx5e_handle_feature(struct net_device *netdev,
 				netdev_features_t *features,
-				netdev_features_t wanted_features,
 				netdev_features_t feature,
 				mlx5e_feature_handler feature_handler)
 {
-	netdev_features_t changes = wanted_features ^ netdev->features;
-	bool enable = !!(wanted_features & feature);
+	netdev_features_t changes = *features ^ netdev->features;
+	bool enable = !!(*features & feature);
 	int err;
 
 	if (!(changes & feature))
@@ -3774,22 +3914,22 @@
 
 	err = feature_handler(netdev, enable);
 	if (err) {
+		MLX5E_SET_FEATURE(features, feature, !enable);
 		netdev_err(netdev, "%s feature %pNF failed, err %d\n",
 			   enable ? "Enable" : "Disable", &feature, err);
 		return err;
 	}
 
-	MLX5E_SET_FEATURE(features, feature, enable);
 	return 0;
 }
 
 int mlx5e_set_features(struct net_device *netdev, netdev_features_t features)
 {
-	netdev_features_t oper_features = netdev->features;
+	netdev_features_t oper_features = features;
 	int err = 0;
 
 #define MLX5E_HANDLE_FEATURE(feature, handler) \
-	mlx5e_handle_feature(netdev, &oper_features, features, feature, handler)
+	mlx5e_handle_feature(netdev, &oper_features, feature, handler)
 
 	err |= MLX5E_HANDLE_FEATURE(NETIF_F_LRO, set_feature_lro);
 	err |= MLX5E_HANDLE_FEATURE(NETIF_F_HW_VLAN_CTAG_FILTER,
@@ -3835,6 +3975,13 @@
 		}
 	}
 
+	if (params->xdp_prog) {
+		if (features & NETIF_F_LRO) {
+			netdev_warn(netdev, "LRO is incompatible with XDP\n");
+			features &= ~NETIF_F_LRO;
+		}
+	}
+
 	if (MLX5E_GET_PFLAG(params, MLX5E_PFLAG_RX_CQE_COMPRESS)) {
 		features &= ~NETIF_F_RXHASH;
 		if (netdev->features & NETIF_F_RXHASH)
@@ -4230,6 +4377,21 @@
 	mlx5e_vxlan_queue_work(priv, be16_to_cpu(ti->port), 0);
 }
 
+static bool mlx5e_gre_tunnel_inner_proto_offload_supported(struct mlx5_core_dev *mdev,
+							   struct sk_buff *skb)
+{
+	switch (skb->inner_protocol) {
+	case htons(ETH_P_IP):
+	case htons(ETH_P_IPV6):
+	case htons(ETH_P_TEB):
+		return true;
+	case htons(ETH_P_MPLS_UC):
+	case htons(ETH_P_MPLS_MC):
+		return MLX5_CAP_ETH(mdev, tunnel_stateless_mpls_over_gre);
+	}
+	return false;
+}
+
 static netdev_features_t mlx5e_tunnel_features_check(struct mlx5e_priv *priv,
 						     struct sk_buff *skb,
 						     netdev_features_t features)
@@ -4252,7 +4414,9 @@
 
 	switch (proto) {
 	case IPPROTO_GRE:
-		return features;
+		if (mlx5e_gre_tunnel_inner_proto_offload_supported(priv->mdev, skb))
+			return features;
+		break;
 	case IPPROTO_IPIP:
 	case IPPROTO_IPV6:
 		if (mlx5e_tunnel_proto_supported(priv->mdev, IPPROTO_IPIP))
@@ -4264,7 +4428,7 @@
 
 		/* Verify if UDP port is being offloaded by HW */
 		if (mlx5_vxlan_lookup_port(priv->mdev->vxlan, port))
-			return features;
+			return vxlan_features_check(skb, features);
 
 #if IS_ENABLED(CONFIG_GENEVE)
 		/* Support Geneve offload for default UDP port */
@@ -4285,7 +4449,6 @@
 	struct mlx5e_priv *priv = netdev_priv(netdev);
 
 	features = vlan_features_check(skb, features);
-	features = vxlan_features_check(skb, features);
 
 #ifdef CONFIG_MLX5_EN_IPSEC
 	if (mlx5e_ipsec_feature_check(skb, netdev, features))
@@ -4379,16 +4542,6 @@
 	return 0;
 }
 
-static int mlx5e_xdp_update_state(struct mlx5e_priv *priv)
-{
-	if (priv->channels.params.xdp_prog)
-		mlx5e_xdp_set_open(priv);
-	else
-		mlx5e_xdp_set_closed(priv);
-
-	return 0;
-}
-
 static int mlx5e_xdp_set(struct net_device *netdev, struct bpf_prog *prog)
 {
 	struct mlx5e_priv *priv = netdev_priv(netdev);
@@ -4428,7 +4581,7 @@
 		mlx5e_set_rq_type(priv->mdev, &new_channels.params);
 		old_prog = priv->channels.params.xdp_prog;
 
-		err = mlx5e_safe_switch_channels(priv, &new_channels, mlx5e_xdp_update_state);
+		err = mlx5e_safe_switch_channels(priv, &new_channels, NULL);
 		if (err)
 			goto unlock;
 	} else {
@@ -4479,6 +4632,11 @@
 
 unlock:
 	mutex_unlock(&priv->state_lock);
+
+	/* Need to fix some features. */
+	if (!err)
+		netdev_update_features(netdev);
+
 	return err;
 }
 
@@ -4521,11 +4679,9 @@
 	struct mlx5e_priv *priv = netdev_priv(dev);
 	struct mlx5_core_dev *mdev = priv->mdev;
 	u8 mode, setting;
-	int err;
 
-	err = mlx5_eswitch_get_vepa(mdev->priv.eswitch, &setting);
-	if (err)
-		return err;
+	if (mlx5_eswitch_get_vepa(mdev->priv.eswitch, &setting))
+		return -EOPNOTSUPP;
 	mode = setting ? BRIDGE_MODE_VEPA : BRIDGE_MODE_VEB;
 	return ndo_dflt_bridge_getlink(skb, pid, seq, dev,
 				       mode,
@@ -4906,6 +5062,8 @@
 		netdev->hw_enc_features |= NETIF_F_GSO_UDP_TUNNEL |
 					   NETIF_F_GSO_UDP_TUNNEL_CSUM;
 		netdev->gso_partial_features = NETIF_F_GSO_UDP_TUNNEL_CSUM;
+		netdev->vlan_features |= NETIF_F_GSO_UDP_TUNNEL |
+					 NETIF_F_GSO_UDP_TUNNEL_CSUM;
 	}
 
 	if (mlx5e_tunnel_proto_supported(mdev, IPPROTO_GRE)) {
@@ -5028,7 +5186,6 @@
 	if (err)
 		mlx5_core_err(mdev, "TLS initialization failed, %d\n", err);
 	mlx5e_build_nic_netdev(netdev);
-	mlx5e_build_tc2txq_maps(priv);
 	mlx5e_health_create_reporters(priv);
 
 	return 0;
@@ -5100,7 +5257,7 @@
 err_destroy_direct_tirs:
 	mlx5e_destroy_direct_tirs(priv, priv->direct_tir);
 err_destroy_indirect_tirs:
-	mlx5e_destroy_indirect_tirs(priv, true);
+	mlx5e_destroy_indirect_tirs(priv);
 err_destroy_direct_rqts:
 	mlx5e_destroy_direct_rqts(priv, priv->direct_tir);
 err_destroy_indirect_rqts:
@@ -5119,7 +5276,7 @@
 	mlx5e_destroy_direct_tirs(priv, priv->xsk_tir);
 	mlx5e_destroy_direct_rqts(priv, priv->xsk_tir);
 	mlx5e_destroy_direct_tirs(priv, priv->direct_tir);
-	mlx5e_destroy_indirect_tirs(priv, true);
+	mlx5e_destroy_indirect_tirs(priv);
 	mlx5e_destroy_direct_rqts(priv, priv->direct_tir);
 	mlx5e_destroy_rqt(priv, &priv->indir_rqt);
 	mlx5e_close_drop_rq(&priv->drop_rq);
@@ -5151,7 +5308,7 @@
 
 	/* Marking the link as currently not needed by the Driver */
 	if (!netif_running(netdev))
-		mlx5_set_port_admin_status(mdev, MLX5_PORT_DOWN);
+		mlx5e_modify_admin_state(mdev, MLX5_PORT_DOWN);
 
 	mlx5e_set_netdev_mtu_boundaries(priv);
 	mlx5e_set_dev_port_mtu(priv);
@@ -5312,9 +5469,10 @@
 	max_nch = mlx5e_get_max_num_channels(priv->mdev);
 	if (priv->channels.params.num_channels > max_nch) {
 		mlx5_core_warn(priv->mdev, "MLX5E: Reducing number of channels to %d\n", max_nch);
+		/* Reducing the number of channels - RXFH has to be reset. */
+		priv->netdev->priv_flags &= ~IFF_RXFH_CONFIGURED;
 		priv->channels.params.num_channels = max_nch;
-		mlx5e_build_default_indir_rqt(priv->rss_params.indirection_rqt,
-					      MLX5E_INDIR_RQT_SIZE, max_nch);
+		mlx5e_num_channels_changed(priv);
 	}
 
 	err = profile->init_tx(priv);
@@ -5334,6 +5492,8 @@
 	profile->cleanup_tx(priv);
 
 out:
+	set_bit(MLX5E_STATE_DESTROYING, &priv->state);
+	cancel_work_sync(&priv->update_stats_work);
 	return err;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -71,14 +71,17 @@
 {
 	struct mlx5e_priv *priv = netdev_priv(dev);
 	struct mlx5_core_dev *mdev = priv->mdev;
+	int count;
 
 	strlcpy(drvinfo->driver, mlx5e_rep_driver_name,
 		sizeof(drvinfo->driver));
-	strlcpy(drvinfo->version, UTS_RELEASE, sizeof(drvinfo->version));
-	snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
-		 "%d.%d.%04d (%.16s)",
-		 fw_rev_maj(mdev), fw_rev_min(mdev),
-		 fw_rev_sub(mdev), mdev->board_id);
+	count = snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
+			 "%d.%d.%04d (%.16s)", fw_rev_maj(mdev),
+			 fw_rev_min(mdev), fw_rev_sub(mdev), mdev->board_id);
+	if (count >= sizeof(drvinfo->fw_version))
+		snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
+			 "%d.%d.%04d", fw_rev_maj(mdev),
+			 fw_rev_min(mdev), fw_rev_sub(mdev));
 }
 
 static void mlx5e_uplink_rep_get_drvinfo(struct net_device *dev,
@@ -1434,6 +1437,8 @@
 
 	params->num_tc                = 1;
 	params->tunneled_offload_en = false;
+	if (rep->vport != MLX5_VPORT_UPLINK)
+		params->vlan_strip_disable = true;
 
 	mlx5_query_min_inline(mdev, &params->tx_min_inline_mode);
 
@@ -1597,7 +1602,7 @@
 err_destroy_direct_tirs:
 	mlx5e_destroy_direct_tirs(priv, priv->direct_tir);
 err_destroy_indirect_tirs:
-	mlx5e_destroy_indirect_tirs(priv, false);
+	mlx5e_destroy_indirect_tirs(priv);
 err_destroy_direct_rqts:
 	mlx5e_destroy_direct_rqts(priv, priv->direct_tir);
 err_destroy_indirect_rqts:
@@ -1614,7 +1619,7 @@
 	mlx5_del_flow_rules(rpriv->vport_rx_rule);
 	mlx5e_destroy_ttc_table(priv, &priv->fs.ttc);
 	mlx5e_destroy_direct_tirs(priv, priv->direct_tir);
-	mlx5e_destroy_indirect_tirs(priv, false);
+	mlx5e_destroy_indirect_tirs(priv);
 	mlx5e_destroy_direct_rqts(priv, priv->direct_tir);
 	mlx5e_destroy_rqt(priv, &priv->indir_rqt);
 	mlx5e_close_drop_rq(&priv->drop_rq);
@@ -1736,6 +1741,9 @@
 	INIT_WORK(&rpriv->uplink_priv.reoffload_flows_work,
 		  mlx5e_tc_reoffload_flows_work);
 
+	if (MLX5_CAP_GEN(mdev, uplink_follow))
+		mlx5_modify_vport_admin_state(mdev, MLX5_VPORT_STATE_OP_MOD_UPLINK,
+					      0, 0, MLX5_VPORT_ADMIN_STATE_AUTO);
 	mlx5_lag_add(mdev, netdev);
 	priv->events_nb.notifier_call = uplink_rep_async_event;
 	mlx5_notifier_register(mdev, &priv->events_nb);
@@ -1814,29 +1822,30 @@
 	struct mlx5_eswitch_rep *rep = rpriv->rep;
 	struct netdev_phys_item_id ppid = {};
 	unsigned int dl_port_index = 0;
+	u16 pfnum;
 
 	if (!is_devlink_port_supported(dev, rpriv))
 		return 0;
 
 	mlx5e_rep_get_port_parent_id(rpriv->netdev, &ppid);
+	pfnum = PCI_FUNC(dev->pdev->devfn);
 
 	if (rep->vport == MLX5_VPORT_UPLINK) {
 		devlink_port_attrs_set(&rpriv->dl_port,
 				       DEVLINK_PORT_FLAVOUR_PHYSICAL,
-				       PCI_FUNC(dev->pdev->devfn), false, 0,
+				       pfnum, false, 0,
 				       &ppid.id[0], ppid.id_len);
 		dl_port_index = vport_to_devlink_port_index(dev, rep->vport);
 	} else if (rep->vport == MLX5_VPORT_PF) {
 		devlink_port_attrs_pci_pf_set(&rpriv->dl_port,
 					      &ppid.id[0], ppid.id_len,
-					      dev->pdev->devfn);
+					      pfnum);
 		dl_port_index = rep->vport;
 	} else if (mlx5_eswitch_is_vf_vport(dev->priv.eswitch,
 					    rpriv->rep->vport)) {
 		devlink_port_attrs_pci_vf_set(&rpriv->dl_port,
 					      &ppid.id[0], ppid.id_len,
-					      dev->pdev->devfn,
-					      rep->vport - 1);
+					      pfnum, rep->vport - 1);
 		dl_port_index = vport_to_devlink_port_index(dev, rep->vport);
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
@@ -49,6 +49,7 @@
 #include "en/xdp.h"
 #include "en/xsk/rx.h"
 #include "en/health.h"
+#include "en/txrx.h"
 
 static inline bool mlx5e_rx_hw_stamp(struct hwtstamp_config *config)
 {
@@ -247,8 +248,8 @@
 	if (unlikely(!dma_info->page))
 		return -ENOMEM;
 
-	dma_info->addr = dma_map_page(rq->pdev, dma_info->page, 0,
-				      PAGE_SIZE, rq->buff.map_dir);
+	dma_info->addr = dma_map_page_attrs(rq->pdev, dma_info->page, 0, PAGE_SIZE,
+					    rq->buff.map_dir, DMA_ATTR_SKIP_CPU_SYNC);
 	if (unlikely(dma_mapping_error(rq->pdev, dma_info->addr))) {
 		page_pool_recycle_direct(rq->page_pool, dma_info->page);
 		dma_info->page = NULL;
@@ -269,7 +270,8 @@
 
 void mlx5e_page_dma_unmap(struct mlx5e_rq *rq, struct mlx5e_dma_info *dma_info)
 {
-	dma_unmap_page(rq->pdev, dma_info->addr, PAGE_SIZE, rq->buff.map_dir);
+	dma_unmap_page_attrs(rq->pdev, dma_info->addr, PAGE_SIZE, rq->buff.map_dir,
+			     DMA_ATTR_SKIP_CPU_SYNC);
 }
 
 void mlx5e_page_release_dynamic(struct mlx5e_rq *rq,
@@ -477,6 +479,7 @@
 	/* fill sq frag edge with nops to avoid wqe wrapping two pages */
 	for (; wi < edge_wi; wi++) {
 		wi->opcode = MLX5_OPCODE_NOP;
+		wi->num_wqebbs = 1;
 		mlx5e_post_nop(wq, sq->sqn, &sq->pc);
 	}
 }
@@ -525,6 +528,7 @@
 	umr_wqe->uctrl.xlt_offset = cpu_to_be16(xlt_offset);
 
 	sq->db.ico_wqe[pi].opcode = MLX5_OPCODE_UMR;
+	sq->db.ico_wqe[pi].num_wqebbs = MLX5E_UMR_WQEBBS;
 	sq->db.ico_wqe[pi].umr.rq = rq;
 	sq->pc += MLX5E_UMR_WQEBBS;
 
@@ -585,7 +589,7 @@
 	return !!err;
 }
 
-void mlx5e_poll_ico_cq(struct mlx5e_cq *cq)
+int mlx5e_poll_ico_cq(struct mlx5e_cq *cq)
 {
 	struct mlx5e_icosq *sq = container_of(cq, struct mlx5e_icosq, cq);
 	struct mlx5_cqe64 *cqe;
@@ -593,11 +597,11 @@
 	int i;
 
 	if (unlikely(!test_bit(MLX5E_SQ_STATE_ENABLED, &sq->state)))
-		return;
+		return 0;
 
 	cqe = mlx5_cqwq_get_cqe(&cq->wq);
 	if (likely(!cqe))
-		return;
+		return 0;
 
 	/* sq->cc must be updated only after mlx5_cqwq_update_db_record(),
 	 * otherwise a cq overrun may occur
@@ -628,17 +632,14 @@
 
 			ci = mlx5_wq_cyc_ctr2ix(&sq->wq, sqcc);
 			wi = &sq->db.ico_wqe[ci];
+			sqcc += wi->num_wqebbs;
 
-			if (likely(wi->opcode == MLX5_OPCODE_UMR)) {
-				sqcc += MLX5E_UMR_WQEBBS;
+			if (likely(wi->opcode == MLX5_OPCODE_UMR))
 				wi->umr.rq->mpwqe.umr_completed++;
-			} else if (likely(wi->opcode == MLX5_OPCODE_NOP)) {
-				sqcc++;
-			} else {
+			else if (unlikely(wi->opcode != MLX5_OPCODE_NOP))
 				netdev_WARN_ONCE(cq->channel->netdev,
 						 "Bad OPCODE in ICOSQ WQE info: 0x%x\n",
 						 wi->opcode);
-			}
 
 		} while (!last_wqe);
 
@@ -647,6 +648,8 @@
 	sq->cc = sqcc;
 
 	mlx5_cqwq_update_db_record(&cq->wq);
+
+	return i;
 }
 
 bool mlx5e_post_rx_mpwqes(struct mlx5e_rq *rq)
@@ -1021,6 +1024,9 @@
 		mlx5e_enable_ecn(rq, skb);
 
 	skb->protocol = eth_type_trans(skb, netdev);
+
+	if (unlikely(mlx5e_skb_is_multicast(skb)))
+		stats->mcast_packets++;
 }
 
 static inline void mlx5e_complete_rx_cqe(struct mlx5e_rq *rq,
@@ -1427,6 +1433,7 @@
 
 #ifdef CONFIG_MLX5_CORE_IPOIB
 
+#define MLX5_IB_GRH_SGID_OFFSET 8
 #define MLX5_IB_GRH_DGID_OFFSET 24
 #define MLX5_GID_SIZE           16
 
@@ -1440,6 +1447,7 @@
 	struct net_device *netdev;
 	struct mlx5e_priv *priv;
 	char *pseudo_header;
+	u32 flags_rqpn;
 	u32 qpn;
 	u8 *dgid;
 	u8 g;
@@ -1461,7 +1469,8 @@
 	tstamp = &priv->tstamp;
 	stats = &priv->channel_stats[rq->ix].rq;
 
-	g = (be32_to_cpu(cqe->flags_rqpn) >> 28) & 3;
+	flags_rqpn = be32_to_cpu(cqe->flags_rqpn);
+	g = (flags_rqpn >> 28) & 3;
 	dgid = skb->data + MLX5_IB_GRH_DGID_OFFSET;
 	if ((!g) || dgid[0] != 0xff)
 		skb->pkt_type = PACKET_HOST;
@@ -1470,9 +1479,15 @@
 	else
 		skb->pkt_type = PACKET_MULTICAST;
 
-	/* TODO: IB/ipoib: Allow mcast packets from other VFs
-	 * 68996a6e760e5c74654723eeb57bf65628ae87f4
+	/* Drop packets that this interface sent, ie multicast packets
+	 * that the HCA has replicated.
 	 */
+	if (g && (qpn == (flags_rqpn & 0xffffff)) &&
+	    (memcmp(netdev->dev_addr + 4, skb->data + MLX5_IB_GRH_SGID_OFFSET,
+		    MLX5_GID_SIZE) == 0)) {
+		skb->dev = NULL;
+		return;
+	}
 
 	skb_pull(skb, MLX5_IB_GRH_BYTES);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
@@ -297,6 +297,9 @@
 			s->tx_tls_drop_bypass_req   += sq_stats->tls_drop_bypass_req;
 #endif
 			s->tx_cqes		+= sq_stats->cqes;
+
+			/* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92657 */
+			barrier();
 		}
 	}
 }
@@ -1601,7 +1604,7 @@
 			for (j = 0; j < NUM_SQ_STATS; j++)
 				sprintf(data + (idx++) * ETH_GSTRING_LEN,
 					sq_stats_desc[j].format,
-					priv->channel_tc2txq[i][tc]);
+					i + tc * max_nch);
 
 	for (i = 0; i < max_nch; i++) {
 		for (j = 0; j < NUM_XSKSQ_STATS * is_xsk; j++)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h
@@ -68,6 +68,7 @@
 	u64 tx_nop;
 	u64 rx_lro_packets;
 	u64 rx_lro_bytes;
+	u64 rx_mcast_packets;
 	u64 rx_ecn_mark;
 	u64 rx_removed_vlan_packets;
 	u64 rx_csum_unnecessary;
@@ -235,6 +236,7 @@
 	u64 csum_none;
 	u64 lro_packets;
 	u64 lro_bytes;
+	u64 mcast_packets;
 	u64 ecn_mark;
 	u64 removed_vlan_packets;
 	u64 xdp_drop;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
@@ -57,6 +57,7 @@
 #include "lib/devcom.h"
 #include "lib/geneve.h"
 #include "diag/en_tc_tracepoint.h"
+#include <asm/div64.h>
 
 struct mlx5_nic_flow_attr {
 	u32 action;
@@ -443,12 +444,32 @@
 static
 struct mlx5_core_dev *mlx5e_hairpin_get_mdev(struct net *net, int ifindex)
 {
+	struct mlx5_core_dev *mdev;
 	struct net_device *netdev;
 	struct mlx5e_priv *priv;
 
-	netdev = __dev_get_by_index(net, ifindex);
+	netdev = dev_get_by_index(net, ifindex);
+	if (!netdev)
+		return ERR_PTR(-ENODEV);
+
 	priv = netdev_priv(netdev);
-	return priv->mdev;
+	mdev = priv->mdev;
+	dev_put(netdev);
+
+	/* Mirred tc action holds a refcount on the ifindex net_device (see
+	 * net/sched/act_mirred.c:tcf_mirred_get_dev). So, it's okay to continue using mdev
+	 * after dev_put(netdev), while we're in the context of adding a tc flow.
+	 *
+	 * The mdev pointer corresponds to the peer/out net_device of a hairpin. It is then
+	 * stored in a hairpin object, which exists until all flows, that refer to it, get
+	 * removed.
+	 *
+	 * On the other hand, after a hairpin object has been created, the peer net_device may
+	 * be removed/unbound while there are still some hairpin flows that are using it. This
+	 * case is handled by mlx5e_tc_hairpin_update_dead_peer, which is hooked to
+	 * NETDEV_UNREGISTER event of the peer net_device.
+	 */
+	return mdev;
 }
 
 static int mlx5e_hairpin_create_transport(struct mlx5e_hairpin *hp)
@@ -586,7 +607,7 @@
 	for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++)
 		ttc_params->indir_tirn[tt] = hp->indir_tirn[tt];
 
-	ft_attr->max_fte = MLX5E_NUM_TT;
+	ft_attr->max_fte = MLX5E_TTC_TABLE_SIZE;
 	ft_attr->level = MLX5E_TC_TTC_FT_LEVEL;
 	ft_attr->prio = MLX5E_TC_PRIO;
 }
@@ -647,6 +668,10 @@
 
 	func_mdev = priv->mdev;
 	peer_mdev = mlx5e_hairpin_get_mdev(dev_net(priv->netdev), peer_ifindex);
+	if (IS_ERR(peer_mdev)) {
+		err = PTR_ERR(peer_mdev);
+		goto create_pair_err;
+	}
 
 	pair = mlx5_core_hairpin_create(func_mdev, peer_mdev, params);
 	if (IS_ERR(pair)) {
@@ -785,6 +810,11 @@
 	int err;
 
 	peer_mdev = mlx5e_hairpin_get_mdev(dev_net(priv->netdev), peer_ifindex);
+	if (IS_ERR(peer_mdev)) {
+		NL_SET_ERR_MSG_MOD(extack, "invalid ifindex of mirred device");
+		return PTR_ERR(peer_mdev);
+	}
+
 	if (!MLX5_CAP_GEN(priv->mdev, hairpin) || !MLX5_CAP_GEN(peer_mdev, hairpin)) {
 		NL_SET_ERR_MSG_MOD(extack, "hairpin is not supported");
 		return -EOPNOTSUPP;
@@ -1615,8 +1645,11 @@
 
 	flow_flag_clear(flow, DUP);
 
-	mlx5e_tc_del_fdb_flow(flow->peer_flow->priv, flow->peer_flow);
-	kvfree(flow->peer_flow);
+	if (refcount_dec_and_test(&flow->peer_flow->refcnt)) {
+		mlx5e_tc_del_fdb_flow(flow->peer_flow->priv, flow->peer_flow);
+		kfree(flow->peer_flow);
+	}
+
 	flow->peer_flow = NULL;
 }
 
@@ -1834,8 +1867,8 @@
 	      BIT(FLOW_DISSECTOR_KEY_ENC_IP) |
 	      BIT(FLOW_DISSECTOR_KEY_ENC_OPTS))) {
 		NL_SET_ERR_MSG_MOD(extack, "Unsupported key");
-		netdev_warn(priv->netdev, "Unsupported key used: 0x%x\n",
-			    dissector->used_keys);
+		netdev_dbg(priv->netdev, "Unsupported key used: 0x%x\n",
+			   dissector->used_keys);
 		return -EOPNOTSUPP;
 	}
 
@@ -2421,10 +2454,11 @@
 		field_bsize = f->size * BITS_PER_BYTE;
 
 		if (field_bsize == 32) {
-			mask_be32 = *(__be32 *)&mask;
+			mask_be32 = (__be32)mask;
 			mask = (__force unsigned long)cpu_to_le32(be32_to_cpu(mask_be32));
 		} else if (field_bsize == 16) {
-			mask_be16 = *(__be16 *)&mask;
+			mask_be32 = (__be32)mask;
+			mask_be16 = *(__be16 *)&mask_be32;
 			mask = (__force unsigned long)cpu_to_le16(be16_to_cpu(mask_be16));
 		}
 
@@ -3166,8 +3200,12 @@
 	if (err)
 		return err;
 
-	*out_dev = dev_get_by_index_rcu(dev_net(vlan_dev),
-					dev_get_iflink(vlan_dev));
+	rcu_read_lock();
+	*out_dev = dev_get_by_index_rcu(dev_net(vlan_dev), dev_get_iflink(vlan_dev));
+	rcu_read_unlock();
+	if (!*out_dev)
+		return -ENODEV;
+
 	if (is_vlan_dev(*out_dev))
 		err = add_vlan_push_action(priv, attr, out_dev, action);
 
@@ -3178,12 +3216,13 @@
 			       struct mlx5_esw_flow_attr *attr,
 			       u32 *action)
 {
-	int nest_level = attr->parse_attr->filter_dev->lower_level;
 	struct flow_action_entry vlan_act = {
 		.id = FLOW_ACTION_VLAN_POP,
 	};
-	int err = 0;
+	int nest_level, err = 0;
 
+	nest_level = attr->parse_attr->filter_dev->lower_level -
+						priv->netdev->lower_level;
 	while (nest_level--) {
 		err = parse_tc_vlan_action(priv, &vlan_act, attr, action);
 		if (err)
@@ -3443,6 +3482,12 @@
 		attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
 	}
 
+	if (!(attr->action &
+	      (MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | MLX5_FLOW_CONTEXT_ACTION_DROP))) {
+		NL_SET_ERR_MSG(extack, "Rule must have at least one forward/drop action");
+		return -EOPNOTSUPP;
+	}
+
 	if (attr->split_count > 0 && !mlx5_esw_has_fwd_fdb(priv->mdev)) {
 		NL_SET_ERR_MSG_MOD(extack,
 				   "current firmware doesn't support split rule for port mirroring");
@@ -3933,15 +3978,22 @@
 	return err;
 }
 
-static int apply_police_params(struct mlx5e_priv *priv, u32 rate,
+static int apply_police_params(struct mlx5e_priv *priv, u64 rate,
 			       struct netlink_ext_ack *extack)
 {
 	struct mlx5e_rep_priv *rpriv = priv->ppriv;
 	struct mlx5_eswitch *esw;
+	u32 rate_mbps = 0;
 	u16 vport_num;
-	u32 rate_mbps;
 	int err;
 
+	vport_num = rpriv->rep->vport;
+	if (vport_num >= MLX5_VPORT_ECPF) {
+		NL_SET_ERR_MSG_MOD(extack,
+				   "Ingress rate limit is supported only for Eswitch ports connected to VFs");
+		return -EOPNOTSUPP;
+	}
+
 	esw = priv->mdev->priv.eswitch;
 	/* rate is given in bytes/sec.
 	 * First convert to bits/sec and then round to the nearest mbit/secs.
@@ -3949,8 +4001,10 @@
 	 * Moreover, if rate is non zero we choose to configure to a minimum of
 	 * 1 mbit/sec.
 	 */
-	rate_mbps = rate ? max_t(u32, (rate * 8 + 500000) / 1000000, 1) : 0;
-	vport_num = rpriv->rep->vport;
+	if (rate) {
+		rate = (rate * BITS_PER_BYTE) + 500000;
+		rate_mbps = max_t(u32, do_div(rate, 1000000), 1);
+	}
 
 	err = mlx5_esw_modify_vport_rate(esw, vport_num, rate_mbps);
 	if (err)
@@ -4055,7 +4109,7 @@
 	list_for_each_entry_safe(hpe, tmp, &init_wait_list, dead_peer_wait_list) {
 		wait_for_completion(&hpe->res_ready);
 		if (!IS_ERR_OR_NULL(hpe->hp) && hpe->peer_vhca_id == peer_vhca_id)
-			hpe->hp->pair->peer_gone = true;
+			mlx5_core_hairpin_clear_dead_peer(hpe->hp->pair);
 
 		mlx5e_hairpin_put(priv, hpe);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
@@ -93,7 +93,7 @@
 	if (txq_ix >= num_channels)
 		txq_ix = priv->txq2sq[txq_ix]->ch_ix;
 
-	return priv->channel_tc2txq[txq_ix][up];
+	return priv->channel_tc2realtxq[txq_ix][up];
 }
 
 static inline int mlx5e_skb_l2_header_offset(struct sk_buff *skb)
@@ -341,8 +341,8 @@
 	dseg =  wqe->data;
 
 #if IS_ENABLED(CONFIG_GENEVE)
-	if (skb->encapsulation)
-		mlx5e_tx_tunnel_accel(skb, eseg);
+	if (skb->encapsulation && skb->ip_summed == CHECKSUM_PARTIAL)
+		mlx5e_tx_tunnel_accel(skb, eseg, ihs);
 #endif
 	mlx5e_txwqe_build_eseg_csum(sq, skb, eseg);
 
@@ -537,10 +537,9 @@
 void mlx5e_free_txqsq_descs(struct mlx5e_txqsq *sq)
 {
 	struct mlx5e_tx_wqe_info *wi;
+	u32 dma_fifo_cc, nbytes = 0;
+	u16 ci, sqcc, npkts = 0;
 	struct sk_buff *skb;
-	u32 dma_fifo_cc;
-	u16 sqcc;
-	u16 ci;
 	int i;
 
 	sqcc = sq->cc;
@@ -565,11 +564,15 @@
 		}
 
 		dev_kfree_skb_any(skb);
+		npkts++;
+		nbytes += wi->num_bytes;
 		sqcc += wi->num_wqebbs;
 	}
 
 	sq->dma_fifo_cc = dma_fifo_cc;
 	sq->cc = sqcc;
+
+	netdev_tx_completed_queue(sq->txq, npkts, nbytes);
 }
 
 #ifdef CONFIG_MLX5_CORE_IPOIB
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c
@@ -78,6 +78,7 @@
 	u16 pi = mlx5_wq_cyc_ctr2ix(wq, sq->pc);
 
 	sq->db.ico_wqe[pi].opcode = MLX5_OPCODE_NOP;
+	sq->db.ico_wqe[pi].num_wqebbs = 1;
 	nopwqe = mlx5e_post_nop(wq, sq->sqn, &sq->pc);
 	mlx5e_notify_hw(wq, sq->pc, sq->uar_map, &nopwqe->ctrl);
 }
@@ -144,7 +145,11 @@
 
 	busy |= rq->post_wqes(rq);
 	if (xsk_open) {
-		mlx5e_poll_ico_cq(&c->xskicosq.cq);
+		if (mlx5e_poll_ico_cq(&c->xskicosq.cq))
+			/* Don't clear the flag if nothing was polled to prevent
+			 * queueing more WQEs and overflowing XSKICOSQ.
+			 */
+			clear_bit(MLX5E_SQ_STATE_PENDING_XSK_TX, &c->xskicosq.state);
 		busy |= mlx5e_poll_xdpsq_cq(&xsksq->cq);
 		busy_xsk |= mlx5e_napi_xsk_post(xsksq, xskrq);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/eq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/eq.c
@@ -190,6 +190,29 @@
 	return count_eqe;
 }
 
+static void mlx5_eq_async_int_lock(struct mlx5_eq_async *eq, unsigned long *flags)
+	__acquires(&eq->lock)
+{
+	if (in_irq())
+		spin_lock(&eq->lock);
+	else
+		spin_lock_irqsave(&eq->lock, *flags);
+}
+
+static void mlx5_eq_async_int_unlock(struct mlx5_eq_async *eq, unsigned long *flags)
+	__releases(&eq->lock)
+{
+	if (in_irq())
+		spin_unlock(&eq->lock);
+	else
+		spin_unlock_irqrestore(&eq->lock, *flags);
+}
+
+enum async_eq_nb_action {
+	ASYNC_EQ_IRQ_HANDLER = 0,
+	ASYNC_EQ_RECOVER = 1,
+};
+
 static int mlx5_eq_async_int(struct notifier_block *nb,
 			     unsigned long action, void *data)
 {
@@ -199,11 +222,14 @@
 	struct mlx5_eq_table *eqt;
 	struct mlx5_core_dev *dev;
 	struct mlx5_eqe *eqe;
+	unsigned long flags;
 	int num_eqes = 0;
 
 	dev = eq->dev;
 	eqt = dev->priv.eq_table;
 
+	mlx5_eq_async_int_lock(eq_async, &flags);
+
 	eqe = next_eqe_sw(eq);
 	if (!eqe)
 		goto out;
@@ -224,8 +250,19 @@
 
 out:
 	eq_update_ci(eq, 1);
+	mlx5_eq_async_int_unlock(eq_async, &flags);
 
-	return 0;
+	return unlikely(action == ASYNC_EQ_RECOVER) ? num_eqes : 0;
+}
+
+void mlx5_cmd_eq_recover(struct mlx5_core_dev *dev)
+{
+	struct mlx5_eq_async *eq = &dev->priv.eq_table->cmd_eq;
+	int eqes;
+
+	eqes = mlx5_eq_async_int(&eq->irq_nb, ASYNC_EQ_RECOVER, NULL);
+	if (eqes)
+		mlx5_core_warn(dev, "Recovered %d EQEs on cmd_eq\n", eqes);
 }
 
 static void init_eq_buf(struct mlx5_eq *eq)
@@ -563,6 +600,40 @@
 		gather_user_async_events(dev, mask);
 }
 
+static int
+setup_async_eq(struct mlx5_core_dev *dev, struct mlx5_eq_async *eq,
+	       struct mlx5_eq_param *param, const char *name)
+{
+	int err;
+
+	eq->irq_nb.notifier_call = mlx5_eq_async_int;
+	spin_lock_init(&eq->lock);
+
+	err = create_async_eq(dev, &eq->core, param);
+	if (err) {
+		mlx5_core_warn(dev, "failed to create %s EQ %d\n", name, err);
+		return err;
+	}
+	err = mlx5_eq_enable(dev, &eq->core, &eq->irq_nb);
+	if (err) {
+		mlx5_core_warn(dev, "failed to enable %s EQ %d\n", name, err);
+		destroy_async_eq(dev, &eq->core);
+	}
+	return err;
+}
+
+static void cleanup_async_eq(struct mlx5_core_dev *dev,
+			     struct mlx5_eq_async *eq, const char *name)
+{
+	int err;
+
+	mlx5_eq_disable(dev, &eq->core, &eq->irq_nb);
+	err = destroy_async_eq(dev, &eq->core);
+	if (err)
+		mlx5_core_err(dev, "failed to destroy %s eq, err(%d)\n",
+			      name, err);
+}
+
 static int create_async_eqs(struct mlx5_core_dev *dev)
 {
 	struct mlx5_eq_table *table = dev->priv.eq_table;
@@ -572,77 +643,48 @@
 	MLX5_NB_INIT(&table->cq_err_nb, cq_err_event_notifier, CQ_ERROR);
 	mlx5_eq_notifier_register(dev, &table->cq_err_nb);
 
-	table->cmd_eq.irq_nb.notifier_call = mlx5_eq_async_int;
 	param = (struct mlx5_eq_param) {
 		.irq_index = 0,
 		.nent = MLX5_NUM_CMD_EQE,
+		.mask[0] = 1ull << MLX5_EVENT_TYPE_CMD,
 	};
-
-	param.mask[0] = 1ull << MLX5_EVENT_TYPE_CMD;
-	err = create_async_eq(dev, &table->cmd_eq.core, &param);
-	if (err) {
-		mlx5_core_warn(dev, "failed to create cmd EQ %d\n", err);
-		goto err0;
-	}
-	err = mlx5_eq_enable(dev, &table->cmd_eq.core, &table->cmd_eq.irq_nb);
-	if (err) {
-		mlx5_core_warn(dev, "failed to enable cmd EQ %d\n", err);
+	mlx5_cmd_allowed_opcode(dev, MLX5_CMD_OP_CREATE_EQ);
+	err = setup_async_eq(dev, &table->cmd_eq, &param, "cmd");
+	if (err)
 		goto err1;
-	}
+
 	mlx5_cmd_use_events(dev);
+	mlx5_cmd_allowed_opcode(dev, CMD_ALLOWED_OPCODE_ALL);
 
-	table->async_eq.irq_nb.notifier_call = mlx5_eq_async_int;
 	param = (struct mlx5_eq_param) {
 		.irq_index = 0,
 		.nent = MLX5_NUM_ASYNC_EQE,
 	};
 
 	gather_async_events_mask(dev, param.mask);
-	err = create_async_eq(dev, &table->async_eq.core, &param);
-	if (err) {
-		mlx5_core_warn(dev, "failed to create async EQ %d\n", err);
+	err = setup_async_eq(dev, &table->async_eq, &param, "async");
+	if (err)
 		goto err2;
-	}
-	err = mlx5_eq_enable(dev, &table->async_eq.core,
-			     &table->async_eq.irq_nb);
-	if (err) {
-		mlx5_core_warn(dev, "failed to enable async EQ %d\n", err);
-		goto err3;
-	}
 
-	table->pages_eq.irq_nb.notifier_call = mlx5_eq_async_int;
 	param = (struct mlx5_eq_param) {
 		.irq_index = 0,
 		.nent = /* TODO: sriov max_vf + */ 1,
+		.mask[0] = 1ull << MLX5_EVENT_TYPE_PAGE_REQUEST,
 	};
 
-	param.mask[0] = 1ull << MLX5_EVENT_TYPE_PAGE_REQUEST;
-	err = create_async_eq(dev, &table->pages_eq.core, &param);
-	if (err) {
-		mlx5_core_warn(dev, "failed to create pages EQ %d\n", err);
-		goto err4;
-	}
-	err = mlx5_eq_enable(dev, &table->pages_eq.core,
-			     &table->pages_eq.irq_nb);
-	if (err) {
-		mlx5_core_warn(dev, "failed to enable pages EQ %d\n", err);
-		goto err5;
-	}
+	err = setup_async_eq(dev, &table->pages_eq, &param, "pages");
+	if (err)
+		goto err3;
 
-	return err;
+	return 0;
 
-err5:
-	destroy_async_eq(dev, &table->pages_eq.core);
-err4:
-	mlx5_eq_disable(dev, &table->async_eq.core, &table->async_eq.irq_nb);
 err3:
-	destroy_async_eq(dev, &table->async_eq.core);
+	cleanup_async_eq(dev, &table->async_eq, "async");
 err2:
 	mlx5_cmd_use_polling(dev);
-	mlx5_eq_disable(dev, &table->cmd_eq.core, &table->cmd_eq.irq_nb);
+	cleanup_async_eq(dev, &table->cmd_eq, "cmd");
 err1:
-	destroy_async_eq(dev, &table->cmd_eq.core);
-err0:
+	mlx5_cmd_allowed_opcode(dev, CMD_ALLOWED_OPCODE_ALL);
 	mlx5_eq_notifier_unregister(dev, &table->cq_err_nb);
 	return err;
 }
@@ -650,28 +692,13 @@
 static void destroy_async_eqs(struct mlx5_core_dev *dev)
 {
 	struct mlx5_eq_table *table = dev->priv.eq_table;
-	int err;
-
-	mlx5_eq_disable(dev, &table->pages_eq.core, &table->pages_eq.irq_nb);
-	err = destroy_async_eq(dev, &table->pages_eq.core);
-	if (err)
-		mlx5_core_err(dev, "failed to destroy pages eq, err(%d)\n",
-			      err);
-
-	mlx5_eq_disable(dev, &table->async_eq.core, &table->async_eq.irq_nb);
-	err = destroy_async_eq(dev, &table->async_eq.core);
-	if (err)
-		mlx5_core_err(dev, "failed to destroy async eq, err(%d)\n",
-			      err);
 
+	cleanup_async_eq(dev, &table->pages_eq, "pages");
+	cleanup_async_eq(dev, &table->async_eq, "async");
+	mlx5_cmd_allowed_opcode(dev, MLX5_CMD_OP_DESTROY_EQ);
 	mlx5_cmd_use_polling(dev);
-
-	mlx5_eq_disable(dev, &table->cmd_eq.core, &table->cmd_eq.irq_nb);
-	err = destroy_async_eq(dev, &table->cmd_eq.core);
-	if (err)
-		mlx5_core_err(dev, "failed to destroy command eq, err(%d)\n",
-			      err);
-
+	cleanup_async_eq(dev, &table->cmd_eq, "cmd");
+	mlx5_cmd_allowed_opcode(dev, CMD_ALLOWED_OPCODE_ALL);
 	mlx5_eq_notifier_unregister(dev, &table->cq_err_nb);
 }
 
@@ -901,13 +928,24 @@
 	mutex_unlock(&table->lock);
 }
 
+#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
+#define MLX5_MAX_ASYNC_EQS 4
+#else
+#define MLX5_MAX_ASYNC_EQS 3
+#endif
+
 int mlx5_eq_table_create(struct mlx5_core_dev *dev)
 {
 	struct mlx5_eq_table *eq_table = dev->priv.eq_table;
+	int num_eqs = MLX5_CAP_GEN(dev, max_num_eqs) ?
+		      MLX5_CAP_GEN(dev, max_num_eqs) :
+		      1 << MLX5_CAP_GEN(dev, log_max_eq);
 	int err;
 
 	eq_table->num_comp_eqs =
-		mlx5_irq_get_num_comp(eq_table->irq_table);
+		min_t(int,
+		      mlx5_irq_get_num_comp(eq_table->irq_table),
+		      num_eqs - MLX5_MAX_ASYNC_EQS);
 
 	err = create_async_eqs(dev);
 	if (err) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
@@ -1592,6 +1592,10 @@
 	struct mlx5_vport *vport;
 
 	vport = mlx5_eswitch_get_vport(esw, vport_num);
+
+	if (!vport->qos.enabled)
+		return -EOPNOTSUPP;
+
 	MLX5_SET(scheduling_context, ctx, max_average_bw, rate_mbps);
 
 	return mlx5_modify_scheduling_element_cmd(esw->dev,
@@ -1919,7 +1923,7 @@
 		mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_IB);
 		mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_ETH);
 	}
-
+	esw_destroy_tsar(esw);
 	return err;
 }
 
@@ -2094,6 +2098,8 @@
 				 u16 vport, int link_state)
 {
 	struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
+	int opmod = MLX5_VPORT_STATE_OP_MOD_ESW_VPORT;
+	int other_vport = 1;
 	int err = 0;
 
 	if (!ESW_ALLOWED(esw))
@@ -2101,15 +2107,17 @@
 	if (IS_ERR(evport))
 		return PTR_ERR(evport);
 
+	if (vport == MLX5_VPORT_UPLINK) {
+		opmod = MLX5_VPORT_STATE_OP_MOD_UPLINK;
+		other_vport = 0;
+		vport = 0;
+	}
 	mutex_lock(&esw->state_lock);
 
-	err = mlx5_modify_vport_admin_state(esw->dev,
-					    MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
-					    vport, 1, link_state);
+	err = mlx5_modify_vport_admin_state(esw->dev, opmod, vport, other_vport, link_state);
 	if (err) {
-		mlx5_core_warn(esw->dev,
-			       "Failed to set vport %d link state, err = %d",
-			       vport, err);
+		mlx5_core_warn(esw->dev, "Failed to set vport %d link state, opmod = %d, err = %d",
+			       vport, opmod, err);
 		goto unlock;
 	}
 
@@ -2151,8 +2159,6 @@
 	struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
 	int err = 0;
 
-	if (!ESW_ALLOWED(esw))
-		return -EPERM;
 	if (IS_ERR(evport))
 		return PTR_ERR(evport);
 	if (vlan > 4095 || qos > 7)
@@ -2180,6 +2186,9 @@
 	u8 set_flags = 0;
 	int err;
 
+	if (!ESW_ALLOWED(esw))
+		return vlan ? -EPERM : 0;
+
 	if (vlan || qos)
 		set_flags = SET_VLAN_STRIP | SET_VLAN_INSERT;
 
@@ -2319,25 +2328,17 @@
 
 int mlx5_eswitch_get_vepa(struct mlx5_eswitch *esw, u8 *setting)
 {
-	int err = 0;
-
 	if (!esw)
 		return -EOPNOTSUPP;
 
 	if (!ESW_ALLOWED(esw))
 		return -EPERM;
 
-	mutex_lock(&esw->state_lock);
-	if (esw->mode != MLX5_ESWITCH_LEGACY) {
-		err = -EOPNOTSUPP;
-		goto out;
-	}
+	if (esw->mode != MLX5_ESWITCH_LEGACY)
+		return -EOPNOTSUPP;
 
 	*setting = esw->fdb_table.legacy.vepa_uplink_rule ? 1 : 0;
-
-out:
-	mutex_unlock(&esw->state_lock);
-	return err;
+	return 0;
 }
 
 int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw,
@@ -2372,12 +2373,15 @@
 		max_guarantee = evport->info.min_rate;
 	}
 
-	return max_t(u32, max_guarantee / fw_max_bw_share, 1);
+	if (max_guarantee)
+		return max_t(u32, max_guarantee / fw_max_bw_share, 1);
+	return 0;
 }
 
-static int normalize_vports_min_rate(struct mlx5_eswitch *esw, u32 divider)
+static int normalize_vports_min_rate(struct mlx5_eswitch *esw)
 {
 	u32 fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share);
+	u32 divider = calculate_vports_min_rate_divider(esw);
 	struct mlx5_vport *evport;
 	u32 vport_max_rate;
 	u32 vport_min_rate;
@@ -2390,9 +2394,9 @@
 			continue;
 		vport_min_rate = evport->info.min_rate;
 		vport_max_rate = evport->info.max_rate;
-		bw_share = MLX5_MIN_BW_SHARE;
+		bw_share = 0;
 
-		if (vport_min_rate)
+		if (divider)
 			bw_share = MLX5_RATE_TO_BW_SHARE(vport_min_rate,
 							 divider,
 							 fw_max_bw_share);
@@ -2417,7 +2421,6 @@
 	struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
 	u32 fw_max_bw_share;
 	u32 previous_min_rate;
-	u32 divider;
 	bool min_rate_supported;
 	bool max_rate_supported;
 	int err = 0;
@@ -2442,8 +2445,7 @@
 
 	previous_min_rate = evport->info.min_rate;
 	evport->info.min_rate = min_rate;
-	divider = calculate_vports_min_rate_divider(esw);
-	err = normalize_vports_min_rate(esw, divider);
+	err = normalize_vports_min_rate(esw);
 	if (err) {
 		evport->info.min_rate = previous_min_rate;
 		goto unlock;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
@@ -606,6 +606,8 @@
 static inline void mlx5_eswitch_disable(struct mlx5_eswitch *esw) {}
 static inline bool mlx5_esw_lag_prereq(struct mlx5_core_dev *dev0, struct mlx5_core_dev *dev1) { return true; }
 static inline bool mlx5_eswitch_is_funcs_handler(struct mlx5_core_dev *dev) { return false; }
+static inline
+int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw, u16 vport, int link_state) { return 0; }
 static inline const u32 *mlx5_esw_query_functions(struct mlx5_core_dev *dev)
 {
 	return ERR_PTR(-EOPNOTSUPP);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
@@ -858,7 +858,7 @@
  */
 #define ESW_SIZE (16 * 1024 * 1024)
 const unsigned int ESW_POOLS[4] = { 4 * 1024 * 1024, 1 * 1024 * 1024,
-				    64 * 1024, 4 * 1024 };
+				    64 * 1024, 128 };
 
 static int
 get_sz_from_pool(struct mlx5_eswitch *esw)
@@ -1143,35 +1143,37 @@
 	}
 	esw->fdb_table.offloads.send_to_vport_grp = g;
 
-	/* create peer esw miss group */
-	memset(flow_group_in, 0, inlen);
-
-	esw_set_flow_group_source_port(esw, flow_group_in);
+	if (MLX5_CAP_ESW(esw->dev, merged_eswitch)) {
+		/* create peer esw miss group */
+		memset(flow_group_in, 0, inlen);
+
+		esw_set_flow_group_source_port(esw, flow_group_in);
+
+		if (!mlx5_eswitch_vport_match_metadata_enabled(esw)) {
+			match_criteria = MLX5_ADDR_OF(create_flow_group_in,
+						      flow_group_in,
+						      match_criteria);
 
-	if (!mlx5_eswitch_vport_match_metadata_enabled(esw)) {
-		match_criteria = MLX5_ADDR_OF(create_flow_group_in,
-					      flow_group_in,
-					      match_criteria);
-
-		MLX5_SET_TO_ONES(fte_match_param, match_criteria,
-				 misc_parameters.source_eswitch_owner_vhca_id);
+			MLX5_SET_TO_ONES(fte_match_param, match_criteria,
+					 misc_parameters.source_eswitch_owner_vhca_id);
 
-		MLX5_SET(create_flow_group_in, flow_group_in,
-			 source_eswitch_owner_vhca_id_valid, 1);
-	}
-
-	MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, ix);
-	MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index,
-		 ix + esw->total_vports - 1);
-	ix += esw->total_vports;
+			MLX5_SET(create_flow_group_in, flow_group_in,
+				 source_eswitch_owner_vhca_id_valid, 1);
+		}
 
-	g = mlx5_create_flow_group(fdb, flow_group_in);
-	if (IS_ERR(g)) {
-		err = PTR_ERR(g);
-		esw_warn(dev, "Failed to create peer miss flow group err(%d)\n", err);
-		goto peer_miss_err;
+		MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, ix);
+		MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index,
+			 ix + esw->total_vports - 1);
+		ix += esw->total_vports;
+
+		g = mlx5_create_flow_group(fdb, flow_group_in);
+		if (IS_ERR(g)) {
+			err = PTR_ERR(g);
+			esw_warn(dev, "Failed to create peer miss flow group err(%d)\n", err);
+			goto peer_miss_err;
+		}
+		esw->fdb_table.offloads.peer_miss_grp = g;
 	}
-	esw->fdb_table.offloads.peer_miss_grp = g;
 
 	/* create miss group */
 	memset(flow_group_in, 0, inlen);
@@ -1206,7 +1208,8 @@
 miss_rule_err:
 	mlx5_destroy_flow_group(esw->fdb_table.offloads.miss_grp);
 miss_err:
-	mlx5_destroy_flow_group(esw->fdb_table.offloads.peer_miss_grp);
+	if (MLX5_CAP_ESW(esw->dev, merged_eswitch))
+		mlx5_destroy_flow_group(esw->fdb_table.offloads.peer_miss_grp);
 peer_miss_err:
 	mlx5_destroy_flow_group(esw->fdb_table.offloads.send_to_vport_grp);
 send_vport_err:
@@ -1229,7 +1232,8 @@
 	mlx5_del_flow_rules(esw->fdb_table.offloads.miss_rule_multi);
 	mlx5_del_flow_rules(esw->fdb_table.offloads.miss_rule_uni);
 	mlx5_destroy_flow_group(esw->fdb_table.offloads.send_to_vport_grp);
-	mlx5_destroy_flow_group(esw->fdb_table.offloads.peer_miss_grp);
+	if (MLX5_CAP_ESW(esw->dev, merged_eswitch))
+		mlx5_destroy_flow_group(esw->fdb_table.offloads.peer_miss_grp);
 	mlx5_destroy_flow_group(esw->fdb_table.offloads.miss_grp);
 
 	mlx5_destroy_flow_table(esw->fdb_table.offloads.slow_fdb);
@@ -1973,10 +1977,6 @@
 	if (!MLX5_CAP_ESW_FLOWTABLE(esw->dev, flow_source))
 		return false;
 
-	if (mlx5_core_is_ecpf_esw_manager(esw->dev) ||
-	    mlx5_ecpf_vport_exists(esw->dev))
-		return false;
-
 	return true;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_termtbl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_termtbl.c
@@ -267,6 +267,8 @@
 	for (curr_dest = 0; curr_dest < num_vport_dests; curr_dest++) {
 		struct mlx5_termtbl_handle *tt = attr->dests[curr_dest].termtbl;
 
+		attr->dests[curr_dest].termtbl = NULL;
+
 		/* search for the destination associated with the
 		 * current term table
 		 */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/events.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/events.c
@@ -346,8 +346,10 @@
 	events->dev = dev;
 	dev->priv.events = events;
 	events->wq = create_singlethread_workqueue("mlx5_events");
-	if (!events->wq)
+	if (!events->wq) {
+		kfree(events);
 		return -ENOMEM;
+	}
 	INIT_WORK(&events->pcie_core_work, mlx5_pcie_event);
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c
@@ -850,6 +850,7 @@
 	mutex_lock(&fpga_xfrm->lock);
 	if (!--fpga_xfrm->num_rules) {
 		mlx5_fpga_ipsec_release_sa_ctx(fpga_xfrm->sa_ctx);
+		kfree(fpga_xfrm->sa_ctx);
 		fpga_xfrm->sa_ctx = NULL;
 	}
 	mutex_unlock(&fpga_xfrm->lock);
@@ -1478,7 +1479,7 @@
 	if (!memcmp(&xfrm->attrs, attrs, sizeof(xfrm->attrs)))
 		return 0;
 
-	if (!mlx5_fpga_esp_validate_xfrm_attrs(mdev, attrs)) {
+	if (mlx5_fpga_esp_validate_xfrm_attrs(mdev, attrs)) {
 		mlx5_core_warn(mdev, "Tried to create an esp with unsupported attrs\n");
 		return -EOPNOTSUPP;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
@@ -496,6 +496,13 @@
 		goto out;
 	}
 
+	if (rule->dest_attr.type == MLX5_FLOW_DESTINATION_TYPE_PORT &&
+	    --fte->dests_size) {
+		fte->modify_mask |= BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_ACTION);
+		fte->action.action &= ~MLX5_FLOW_CONTEXT_ACTION_ALLOW;
+		goto out;
+	}
+
 	if ((fte->action.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) &&
 	    --fte->dests_size) {
 		fte->modify_mask |=
@@ -629,7 +636,7 @@
 	fte->action = *flow_act;
 	fte->flow_context = spec->flow_context;
 
-	tree_init_node(&fte->node, NULL, del_sw_fte);
+	tree_init_node(&fte->node, del_hw_fte, del_sw_fte);
 
 	return fte;
 }
@@ -809,18 +816,15 @@
 {
 	struct mlx5_flow_root_namespace *root = find_root(&prio->node);
 	struct mlx5_flow_table *iter;
-	int i = 0;
 	int err;
 
 	fs_for_each_ft(iter, prio) {
-		i++;
 		err = root->cmds->modify_flow_table(root, iter, ft);
 		if (err) {
-			mlx5_core_warn(dev, "Failed to modify flow table %d\n",
-				       iter->id);
+			mlx5_core_err(dev,
+				      "Failed to modify flow table id %d, type %d, err %d\n",
+				      iter->id, iter->type, err);
 			/* The driver is out of sync with the FW */
-			if (i > 1)
-				WARN_ON(true);
 			return err;
 		}
 	}
@@ -964,17 +968,19 @@
 static int connect_flow_table(struct mlx5_core_dev *dev, struct mlx5_flow_table *ft,
 			      struct fs_prio *prio)
 {
-	struct mlx5_flow_table *next_ft;
+	struct mlx5_flow_table *next_ft, *first_ft;
 	int err = 0;
 
 	/* Connect_prev_fts and update_root_ft_create are mutually exclusive */
 
-	if (list_empty(&prio->node.children)) {
+	first_ft = list_first_entry_or_null(&prio->node.children,
+					    struct mlx5_flow_table, node.list);
+	if (!first_ft || first_ft->level > ft->level) {
 		err = connect_prev_fts(dev, ft, prio);
 		if (err)
 			return err;
 
-		next_ft = find_next_chained_ft(prio);
+		next_ft = first_ft ? first_ft : find_next_chained_ft(prio);
 		err = connect_fwd_rules(dev, ft, next_ft);
 		if (err)
 			return err;
@@ -1064,6 +1070,7 @@
 destroy_ft:
 	root->cmds->destroy_flow_table(root, ft);
 free_ft:
+	rhltable_destroy(&ft->fgs_hash);
 	kfree(ft);
 unlock_root:
 	mutex_unlock(&root->chain_lock);
@@ -1443,9 +1450,22 @@
 	return NULL;
 }
 
-static bool check_conflicting_actions(u32 action1, u32 action2)
+static bool check_conflicting_actions_vlan(const struct mlx5_fs_vlan *vlan0,
+					   const struct mlx5_fs_vlan *vlan1)
 {
-	u32 xored_actions = action1 ^ action2;
+	return vlan0->ethtype != vlan1->ethtype ||
+	       vlan0->vid != vlan1->vid ||
+	       vlan0->prio != vlan1->prio;
+}
+
+static bool check_conflicting_actions(const struct mlx5_flow_act *act1,
+				      const struct mlx5_flow_act *act2)
+{
+	u32 action1 = act1->action;
+	u32 action2 = act2->action;
+	u32 xored_actions;
+
+	xored_actions = action1 ^ action2;
 
 	/* if one rule only wants to count, it's ok */
 	if (action1 == MLX5_FLOW_CONTEXT_ACTION_COUNT ||
@@ -1462,6 +1482,22 @@
 			     MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2))
 		return true;
 
+	if (action1 & MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT &&
+	    act1->pkt_reformat != act2->pkt_reformat)
+		return true;
+
+	if (action1 & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR &&
+	    act1->modify_hdr != act2->modify_hdr)
+		return true;
+
+	if (action1 & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH &&
+	    check_conflicting_actions_vlan(&act1->vlan[0], &act2->vlan[0]))
+		return true;
+
+	if (action1 & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2 &&
+	    check_conflicting_actions_vlan(&act1->vlan[1], &act2->vlan[1]))
+		return true;
+
 	return false;
 }
 
@@ -1469,7 +1505,7 @@
 				  const struct mlx5_flow_context *flow_context,
 				  const struct mlx5_flow_act *flow_act)
 {
-	if (check_conflicting_actions(flow_act->action, fte->action.action)) {
+	if (check_conflicting_actions(flow_act, &fte->action)) {
 		mlx5_core_warn(get_dev(&fte->node),
 			       "Found two FTEs with conflicting actions\n");
 		return -EEXIST;
@@ -1513,8 +1549,9 @@
 	}
 	trace_mlx5_fs_set_fte(fte, false);
 
+	/* Link newly added rules into the tree. */
 	for (i = 0; i < handle->num_rules; i++) {
-		if (refcount_read(&handle->rule[i]->node.refcount) == 1) {
+		if (!handle->rule[i]->node.parent) {
 			tree_add_node(&handle->rule[i]->node, &fte->node);
 			trace_mlx5_fs_add_rule(handle->rule[i]);
 		}
@@ -1555,16 +1592,16 @@
 	struct match_list first;
 };
 
-static void free_match_list(struct match_list_head *head)
+static void free_match_list(struct match_list_head *head, bool ft_locked)
 {
 	if (!list_empty(&head->list)) {
 		struct match_list *iter, *match_tmp;
 
 		list_del(&head->first.list);
-		tree_put_node(&head->first.g->node, false);
+		tree_put_node(&head->first.g->node, ft_locked);
 		list_for_each_entry_safe(iter, match_tmp, &head->list,
 					 list) {
-			tree_put_node(&iter->g->node, false);
+			tree_put_node(&iter->g->node, ft_locked);
 			list_del(&iter->list);
 			kfree(iter);
 		}
@@ -1573,7 +1610,8 @@
 
 static int build_match_list(struct match_list_head *match_head,
 			    struct mlx5_flow_table *ft,
-			    const struct mlx5_flow_spec *spec)
+			    const struct mlx5_flow_spec *spec,
+			    bool ft_locked)
 {
 	struct rhlist_head *tmp, *list;
 	struct mlx5_flow_group *g;
@@ -1598,9 +1636,9 @@
 
 		curr_match = kmalloc(sizeof(*curr_match), GFP_ATOMIC);
 		if (!curr_match) {
-			free_match_list(match_head);
-			err = -ENOMEM;
-			goto out;
+			rcu_read_unlock();
+			free_match_list(match_head, ft_locked);
+			return -ENOMEM;
 		}
 		if (!tree_get_node(&g->node)) {
 			kfree(curr_match);
@@ -1609,7 +1647,6 @@
 		curr_match->g = g;
 		list_add_tail(&curr_match->list, &match_head->list);
 	}
-out:
 	rcu_read_unlock();
 	return err;
 }
@@ -1641,13 +1678,22 @@
 		fte_tmp = NULL;
 		goto out;
 	}
+
+	nested_down_write_ref_node(&fte_tmp->node, FS_LOCK_CHILD);
+
 	if (!fte_tmp->node.active) {
+		up_write_ref_node(&fte_tmp->node, false);
+
+		if (take_write)
+			up_write_ref_node(&g->node, false);
+		else
+			up_read_ref_node(&g->node);
+
 		tree_put_node(&fte_tmp->node, false);
-		fte_tmp = NULL;
-		goto out;
+
+		return NULL;
 	}
 
-	nested_down_write_ref_node(&fte_tmp->node, FS_LOCK_CHILD);
 out:
 	if (take_write)
 		up_write_ref_node(&g->node, false);
@@ -1691,6 +1737,7 @@
 		if (!fte_tmp)
 			continue;
 		rule = add_rule_fg(g, spec, flow_act, dest, dest_num, fte_tmp);
+		/* No error check needed here, because insert_fte() is not called */
 		up_write_ref_node(&fte_tmp->node, false);
 		tree_put_node(&fte_tmp->node, false);
 		kmem_cache_free(steering->ftes_cache, fte);
@@ -1739,7 +1786,8 @@
 		up_write_ref_node(&g->node, false);
 		rule = add_rule_fg(g, spec, flow_act, dest, dest_num, fte);
 		up_write_ref_node(&fte->node, false);
-		tree_put_node(&fte->node, false);
+		if (IS_ERR(rule))
+			tree_put_node(&fte->node, false);
 		return rule;
 	}
 	rule = ERR_PTR(-ENOENT);
@@ -1778,7 +1826,7 @@
 	version = atomic_read(&ft->node.version);
 
 	/* Collect all fgs which has a matching match_criteria */
-	err = build_match_list(&match_head, ft, spec);
+	err = build_match_list(&match_head, ft, spec, take_write);
 	if (err) {
 		if (take_write)
 			up_write_ref_node(&ft->node, false);
@@ -1792,7 +1840,7 @@
 
 	rule = try_add_to_existing_fg(ft, &match_head.list, spec, flow_act, dest,
 				      dest_num, version);
-	free_match_list(&match_head);
+	free_match_list(&match_head, take_write);
 	if (!IS_ERR(rule) ||
 	    (PTR_ERR(rule) != -ENOENT && PTR_ERR(rule) != -EAGAIN)) {
 		if (take_write)
@@ -1839,7 +1887,8 @@
 	up_write_ref_node(&g->node, false);
 	rule = add_rule_fg(g, spec, flow_act, dest, dest_num, fte);
 	up_write_ref_node(&fte->node, false);
-	tree_put_node(&fte->node, false);
+	if (IS_ERR(rule))
+		tree_put_node(&fte->node, false);
 	tree_put_node(&g->node, false);
 	return rule;
 
@@ -1927,13 +1976,18 @@
 	down_write_ref_node(&fte->node, false);
 	for (i = handle->num_rules - 1; i >= 0; i--)
 		tree_remove_node(&handle->rule[i]->node, true);
-	if (fte->modify_mask && fte->dests_size) {
-		modify_fte(fte);
-		up_write_ref_node(&fte->node, false);
-	} else {
+	if (list_empty(&fte->node.children)) {
 		del_hw_fte(&fte->node);
-		up_write(&fte->node.lock);
+		/* Avoid double call to del_hw_fte */
+		fte->node.del_hw_func = NULL;
+		up_write_ref_node(&fte->node, false);
 		tree_put_node(&fte->node, false);
+	} else if (fte->dests_size) {
+		if (fte->modify_mask)
+			modify_fte(fte);
+		up_write_ref_node(&fte->node, false);
+	} else {
+		up_write_ref_node(&fte->node, false);
 	}
 	kfree(handle);
 }
@@ -2014,7 +2068,7 @@
 				node.list) == ft))
 		return 0;
 
-	next_ft = find_next_chained_ft(prio);
+	next_ft = find_next_ft(ft);
 	err = connect_fwd_rules(dev, next_ft, ft);
 	if (err)
 		return err;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/fw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/fw.c
@@ -239,7 +239,7 @@
 			return err;
 	}
 
-	if (MLX5_CAP_GEN(dev, tls)) {
+	if (MLX5_CAP_GEN(dev, tls_tx)) {
 		err = mlx5_core_get_caps(dev, MLX5_CAP_TLS);
 		if (err)
 			return err;
@@ -337,6 +337,10 @@
 	do {
 		if (mlx5_get_nic_state(dev) == MLX5_NIC_IFC_DISABLED)
 			break;
+		if (pci_channel_offline(dev->pdev)) {
+			mlx5_core_err(dev, "PCI channel offline, stop waiting for NIC IFC\n");
+			return -EACCES;
+		}
 
 		cond_resched();
 	} while (!time_after(jiffies, end));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/health.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/health.c
@@ -193,15 +193,23 @@
 
 void mlx5_enter_error_state(struct mlx5_core_dev *dev, bool force)
 {
+	bool err_detected = false;
+
+	/* Mark the device as fatal in order to abort FW commands */
+	if ((check_fatal_sensors(dev) || force) &&
+	    dev->state == MLX5_DEVICE_STATE_UP) {
+		dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR;
+		err_detected = true;
+	}
 	mutex_lock(&dev->intf_state_mutex);
-	if (dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR)
-		goto unlock;
+	if (!err_detected && dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR)
+		goto unlock;/* a previous error is still being handled */
 	if (dev->state == MLX5_DEVICE_STATE_UNINITIALIZED) {
 		dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR;
 		goto unlock;
 	}
 
-	if (check_fatal_sensors(dev) || force) {
+	if (check_fatal_sensors(dev) || force) { /* protected state setting */
 		dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR;
 		mlx5_cmd_flush(dev);
 	}
@@ -242,8 +250,12 @@
 	do {
 		if (mlx5_get_nic_state(dev) == MLX5_NIC_IFC_DISABLED)
 			break;
+		if (pci_channel_offline(dev->pdev)) {
+			mlx5_core_err(dev, "PCI channel offline, stop waiting for NIC IFC\n");
+			goto unlock;
+		}
 
-		cond_resched();
+		msleep(20);
 	} while (!time_after(jiffies, end));
 
 	if (mlx5_get_nic_state(dev) != MLX5_NIC_IFC_DISABLED) {
@@ -314,6 +326,10 @@
 				      "health recovery flow aborted, PCI reads still not working\n");
 			return -EIO;
 		}
+		if (pci_channel_offline(dev->pdev)) {
+			mlx5_core_err(dev, "PCI channel offline, stop waiting for PCI\n");
+			return -EACCES;
+		}
 		msleep(100);
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c
@@ -39,7 +39,7 @@
 	struct mlx5e_priv *priv = mlx5i_epriv(dev);
 
 	mlx5e_ethtool_get_drvinfo(priv, drvinfo);
-	strlcpy(drvinfo->driver, DRIVER_NAME "[ib_ipoib]",
+	strlcpy(drvinfo->driver, KBUILD_MODNAME "[ib_ipoib]",
 		sizeof(drvinfo->driver));
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
@@ -319,17 +319,6 @@
 	}
 
 	mlx5e_set_ttc_basic_params(priv, &ttc_params);
-	mlx5e_set_inner_ttc_ft_params(&ttc_params);
-	for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++)
-		ttc_params.indir_tirn[tt] = priv->inner_indir_tir[tt].tirn;
-
-	err = mlx5e_create_inner_ttc_table(priv, &ttc_params, &priv->fs.inner_ttc);
-	if (err) {
-		netdev_err(priv->netdev, "Failed to create inner ttc table, err=%d\n",
-			   err);
-		goto err_destroy_arfs_tables;
-	}
-
 	mlx5e_set_ttc_ft_params(&ttc_params);
 	for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++)
 		ttc_params.indir_tirn[tt] = priv->indir_tir[tt].tirn;
@@ -338,13 +327,11 @@
 	if (err) {
 		netdev_err(priv->netdev, "Failed to create ttc table, err=%d\n",
 			   err);
-		goto err_destroy_inner_ttc_table;
+		goto err_destroy_arfs_tables;
 	}
 
 	return 0;
 
-err_destroy_inner_ttc_table:
-	mlx5e_destroy_inner_ttc_table(priv, &priv->fs.inner_ttc);
 err_destroy_arfs_tables:
 	mlx5e_arfs_destroy_tables(priv);
 
@@ -354,7 +341,6 @@
 static void mlx5i_destroy_flow_steering(struct mlx5e_priv *priv)
 {
 	mlx5e_destroy_ttc_table(priv, &priv->fs.ttc);
-	mlx5e_destroy_inner_ttc_table(priv, &priv->fs.inner_ttc);
 	mlx5e_arfs_destroy_tables(priv);
 }
 
@@ -379,7 +365,7 @@
 	if (err)
 		goto err_destroy_indirect_rqts;
 
-	err = mlx5e_create_indirect_tirs(priv, true);
+	err = mlx5e_create_indirect_tirs(priv, false);
 	if (err)
 		goto err_destroy_direct_rqts;
 
@@ -396,7 +382,7 @@
 err_destroy_direct_tirs:
 	mlx5e_destroy_direct_tirs(priv, priv->direct_tir);
 err_destroy_indirect_tirs:
-	mlx5e_destroy_indirect_tirs(priv, true);
+	mlx5e_destroy_indirect_tirs(priv);
 err_destroy_direct_rqts:
 	mlx5e_destroy_direct_rqts(priv, priv->direct_tir);
 err_destroy_indirect_rqts:
@@ -412,7 +398,7 @@
 {
 	mlx5i_destroy_flow_steering(priv);
 	mlx5e_destroy_direct_tirs(priv, priv->direct_tir);
-	mlx5e_destroy_indirect_tirs(priv, true);
+	mlx5e_destroy_indirect_tirs(priv);
 	mlx5e_destroy_direct_rqts(priv, priv->direct_tir);
 	mlx5e_destroy_rqt(priv, &priv->indir_rqt);
 	mlx5e_close_drop_rq(&priv->drop_rq);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c
@@ -265,10 +265,8 @@
 		fen_info = container_of(info, struct fib_entry_notifier_info,
 					info);
 		fi = fen_info->fi;
-		if (fi->nh) {
-			NL_SET_ERR_MSG_MOD(info->extack, "IPv4 route with nexthop objects is not supported");
-			return notifier_from_errno(-EINVAL);
-		}
+		if (fi->nh)
+			return NOTIFY_DONE;
 		fib_dev = fib_info_nh(fen_info->fi, 0)->fib_nh_dev;
 		if (fib_dev != ldev->pf[0].netdev &&
 		    fib_dev != ldev->pf[1].netdev) {
@@ -307,6 +305,11 @@
 	struct lag_mp *mp = &ldev->lag_mp;
 	int err;
 
+	/* always clear mfi, as it might become stale when a route delete event
+	 * has been missed
+	 */
+	mp->mfi = NULL;
+
 	if (mp->fib_nb.notifier_call)
 		return 0;
 
@@ -328,4 +331,5 @@
 
 	unregister_fib_notifier(&mp->fib_nb);
 	mp->fib_nb.notifier_call = NULL;
+	mp->mfi = NULL;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
@@ -388,16 +388,37 @@
 	return 0;
 }
 
+enum {
+	MLX5_MTPPS_REG_CAP_PIN_X_MODE_SUPPORT_PPS_IN = BIT(0),
+	MLX5_MTPPS_REG_CAP_PIN_X_MODE_SUPPORT_PPS_OUT = BIT(1),
+};
+
 static int mlx5_ptp_verify(struct ptp_clock_info *ptp, unsigned int pin,
 			   enum ptp_pin_function func, unsigned int chan)
 {
-	return (func == PTP_PF_PHYSYNC) ? -EOPNOTSUPP : 0;
+	struct mlx5_clock *clock = container_of(ptp, struct mlx5_clock,
+						ptp_info);
+
+	switch (func) {
+	case PTP_PF_NONE:
+		return 0;
+	case PTP_PF_EXTTS:
+		return !(clock->pps_info.pin_caps[pin] &
+			 MLX5_MTPPS_REG_CAP_PIN_X_MODE_SUPPORT_PPS_IN);
+	case PTP_PF_PEROUT:
+		return !(clock->pps_info.pin_caps[pin] &
+			 MLX5_MTPPS_REG_CAP_PIN_X_MODE_SUPPORT_PPS_OUT);
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return -EOPNOTSUPP;
 }
 
 static const struct ptp_clock_info mlx5_ptp_clock_info = {
 	.owner		= THIS_MODULE,
-	.name		= "mlx5_p2p",
-	.max_adj	= 100000000,
+	.name		= "mlx5_ptp",
+	.max_adj	= 50000000,
 	.n_alarm	= 0,
 	.n_ext_ts	= 0,
 	.n_per_out	= 0,
@@ -477,8 +498,9 @@
 	switch (clock->ptp_info.pin_config[pin].func) {
 	case PTP_PF_EXTTS:
 		ptp_event.index = pin;
-		ptp_event.timestamp = timecounter_cyc2time(&clock->tc,
-					be64_to_cpu(eqe->data.pps.time_stamp));
+		ptp_event.timestamp =
+			mlx5_timecounter_cyc2time(clock,
+						  be64_to_cpu(eqe->data.pps.time_stamp));
 		if (clock->pps_info.enabled) {
 			ptp_event.type = PTP_CLOCK_PPSUSR;
 			ptp_event.pps_times.ts_real =
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c
@@ -3,6 +3,7 @@
 
 #include <linux/mlx5/vport.h>
 #include "lib/devcom.h"
+#include "mlx5_core.h"
 
 static LIST_HEAD(devcom_list);
 
@@ -14,7 +15,7 @@
 struct mlx5_devcom_component {
 	struct {
 		void *data;
-	} device[MLX5_MAX_PORTS];
+	} device[MLX5_DEVCOM_PORTS_SUPPORTED];
 
 	mlx5_devcom_event_handler_t handler;
 	struct rw_semaphore sem;
@@ -25,7 +26,7 @@
 	struct list_head list;
 
 	struct mlx5_devcom_component components[MLX5_DEVCOM_NUM_COMPONENTS];
-	struct mlx5_core_dev *devs[MLX5_MAX_PORTS];
+	struct mlx5_core_dev *devs[MLX5_DEVCOM_PORTS_SUPPORTED];
 };
 
 struct mlx5_devcom {
@@ -74,13 +75,16 @@
 
 	if (!mlx5_core_is_pf(dev))
 		return NULL;
+	if (MLX5_CAP_GEN(dev, num_lag_ports) != MLX5_DEVCOM_PORTS_SUPPORTED)
+		return NULL;
 
+	mlx5_dev_list_lock();
 	sguid0 = mlx5_query_nic_system_image_guid(dev);
 	list_for_each_entry(iter, &devcom_list, list) {
 		struct mlx5_core_dev *tmp_dev = NULL;
 
 		idx = -1;
-		for (i = 0; i < MLX5_MAX_PORTS; i++) {
+		for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++) {
 			if (iter->devs[i])
 				tmp_dev = iter->devs[i];
 			else
@@ -100,8 +104,10 @@
 
 	if (!priv) {
 		priv = mlx5_devcom_list_alloc();
-		if (!priv)
-			return ERR_PTR(-ENOMEM);
+		if (!priv) {
+			devcom = ERR_PTR(-ENOMEM);
+			goto out;
+		}
 
 		idx = 0;
 		new_priv = true;
@@ -110,13 +116,16 @@
 	priv->devs[idx] = dev;
 	devcom = mlx5_devcom_alloc(priv, idx);
 	if (!devcom) {
-		kfree(priv);
-		return ERR_PTR(-ENOMEM);
+		if (new_priv)
+			kfree(priv);
+		devcom = ERR_PTR(-ENOMEM);
+		goto out;
 	}
 
 	if (new_priv)
 		list_add(&priv->list, &devcom_list);
-
+out:
+	mlx5_dev_list_unlock();
 	return devcom;
 }
 
@@ -129,20 +138,23 @@
 	if (IS_ERR_OR_NULL(devcom))
 		return;
 
+	mlx5_dev_list_lock();
 	priv = devcom->priv;
 	priv->devs[devcom->idx] = NULL;
 
 	kfree(devcom);
 
-	for (i = 0; i < MLX5_MAX_PORTS; i++)
+	for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++)
 		if (priv->devs[i])
 			break;
 
-	if (i != MLX5_MAX_PORTS)
-		return;
+	if (i != MLX5_DEVCOM_PORTS_SUPPORTED)
+		goto out;
 
 	list_del(&priv->list);
 	kfree(priv);
+out:
+	mlx5_dev_list_unlock();
 }
 
 void mlx5_devcom_register_component(struct mlx5_devcom *devcom,
@@ -191,7 +203,7 @@
 
 	comp = &devcom->priv->components[id];
 	down_write(&comp->sem);
-	for (i = 0; i < MLX5_MAX_PORTS; i++)
+	for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++)
 		if (i != devcom->idx && comp->device[i].data) {
 			err = comp->handler(event, comp->device[i].data,
 					    event_data);
@@ -239,7 +251,7 @@
 		return NULL;
 	}
 
-	for (i = 0; i < MLX5_MAX_PORTS; i++)
+	for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++)
 		if (i != devcom->idx)
 			break;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h
@@ -6,6 +6,8 @@
 
 #include <linux/mlx5/driver.h>
 
+#define MLX5_DEVCOM_PORTS_SUPPORTED 2
+
 enum mlx5_devcom_components {
 	MLX5_DEVCOM_ESW_OFFLOADS,
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/lib/eq.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/lib/eq.h
@@ -38,6 +38,7 @@
 struct mlx5_eq_async {
 	struct mlx5_eq          core;
 	struct notifier_block   irq_nb;
+	spinlock_t              lock; /* To avoid irq EQ handle races with resiliency flows */
 };
 
 struct mlx5_eq_comp {
@@ -82,6 +83,7 @@
 struct cpumask *mlx5_eq_comp_cpumask(struct mlx5_core_dev *dev, int ix);
 
 u32 mlx5_eq_poll_irq_disabled(struct mlx5_eq_comp *eq);
+void mlx5_cmd_eq_recover(struct mlx5_core_dev *dev);
 void mlx5_eq_synchronize_async_irq(struct mlx5_core_dev *dev);
 void mlx5_eq_synchronize_cmd_irq(struct mlx5_core_dev *dev);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/lib/geneve.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/lib/geneve.c
@@ -105,6 +105,7 @@
 		geneve->opt_type = opt->type;
 		geneve->obj_id = res;
 		geneve->refcount++;
+		res = 0;
 	}
 
 unlock:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/lib/pci_vsc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/lib/pci_vsc.c
@@ -24,6 +24,11 @@
 	pci_write_config_dword((dev)->pdev, (dev)->vsc_addr + (offset), (val))
 #define VSC_MAX_RETRIES 2048
 
+/* Reading VSC registers can take relatively long time.
+ * Yield the cpu every 128 registers read.
+ */
+#define VSC_GW_READ_BLOCK_COUNT 128
+
 enum {
 	VSC_CTRL_OFFSET = 0x4,
 	VSC_COUNTER_OFFSET = 0x8,
@@ -74,6 +79,10 @@
 			ret = -EBUSY;
 			goto pci_unlock;
 		}
+		if (pci_channel_offline(dev->pdev)) {
+			ret = -EACCES;
+			goto pci_unlock;
+		}
 
 		/* Check if semaphore is already locked */
 		ret = vsc_read(dev, VSC_SEMAPHORE_OFFSET, &lock_val);
@@ -269,6 +278,7 @@
 {
 	unsigned int next_read_addr = 0;
 	unsigned int read_addr = 0;
+	unsigned int count = 0;
 
 	while (read_addr < length) {
 		if (mlx5_vsc_gw_read_fast(dev, read_addr, &next_read_addr,
@@ -276,6 +286,10 @@
 			return read_addr;
 
 		read_addr = next_read_addr;
+		if (++count == VSC_GW_READ_BLOCK_COUNT) {
+			cond_resched();
+			count = 0;
+		}
 	}
 	return length;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/main.c
@@ -50,6 +50,7 @@
 #ifdef CONFIG_RFS_ACCEL
 #include <linux/cpu_rmap.h>
 #endif
+#include <linux/version.h>
 #include <net/devlink.h>
 #include "mlx5_core.h"
 #include "lib/eq.h"
@@ -74,7 +75,6 @@
 MODULE_AUTHOR("Eli Cohen <eli@mellanox.com>");
 MODULE_DESCRIPTION("Mellanox 5th generation network adapters (ConnectX series) core driver");
 MODULE_LICENSE("Dual BSD/GPL");
-MODULE_VERSION(DRIVER_VERSION);
 
 unsigned int mlx5_core_debug_mask;
 module_param_named(debug_mask, mlx5_core_debug_mask, uint, 0644);
@@ -221,13 +221,16 @@
 	strncat(string, ",", remaining_size);
 
 	remaining_size = max_t(int, 0, driver_ver_sz - strlen(string));
-	strncat(string, DRIVER_NAME, remaining_size);
+	strncat(string, KBUILD_MODNAME, remaining_size);
 
 	remaining_size = max_t(int, 0, driver_ver_sz - strlen(string));
 	strncat(string, ",", remaining_size);
 
 	remaining_size = max_t(int, 0, driver_ver_sz - strlen(string));
-	strncat(string, DRIVER_VERSION, remaining_size);
+
+	snprintf(string + strlen(string), remaining_size, "%u.%u.%u",
+		 (u8)((LINUX_VERSION_CODE >> 16) & 0xff), (u8)((LINUX_VERSION_CODE >> 8) & 0xff),
+		 (u16)(LINUX_VERSION_CODE & 0xffff));
 
 	/*Send the command*/
 	MLX5_SET(set_driver_version_in, in, opcode,
@@ -303,7 +306,7 @@
 		return -ENODEV;
 	}
 
-	err = pci_request_regions(pdev, DRIVER_NAME);
+	err = pci_request_regions(pdev, KBUILD_MODNAME);
 	if (err)
 		dev_err(&pdev->dev, "Couldn't get PCI resources, aborting\n");
 
@@ -794,6 +797,11 @@
 
 static void mlx5_pci_close(struct mlx5_core_dev *dev)
 {
+	/* health work might still be active, and it needs pci bar in
+	 * order to know the NIC state. Therefore, drain the health WQ
+	 * before removing the pci bars
+	 */
+	mlx5_drain_health_wq(dev);
 	iounmap(dev->iseg);
 	pci_clear_master(dev->pdev);
 	release_bar(dev->pdev);
@@ -878,7 +886,7 @@
 
 	dev->dm = mlx5_dm_create(dev);
 	if (IS_ERR(dev->dm))
-		mlx5_core_warn(dev, "Failed to init device memory%d\n", err);
+		mlx5_core_warn(dev, "Failed to init device memory %ld\n", PTR_ERR(dev->dm));
 
 	dev->tracer = mlx5_fw_tracer_create(dev);
 	dev->hv_vhca = mlx5_hv_vhca_create(dev);
@@ -966,6 +974,8 @@
 		goto err_cmd_cleanup;
 	}
 
+	mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_UP);
+
 	err = mlx5_core_enable_hca(dev, 0);
 	if (err) {
 		mlx5_core_err(dev, "enable hca failed\n");
@@ -1027,6 +1037,7 @@
 err_disable_hca:
 	mlx5_core_disable_hca(dev, 0);
 err_cmd_cleanup:
+	mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_DOWN);
 	mlx5_cmd_cleanup(dev);
 
 	return err;
@@ -1044,6 +1055,7 @@
 	}
 	mlx5_reclaim_startup_pages(dev);
 	mlx5_core_disable_hca(dev, 0);
+	mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_DOWN);
 	mlx5_cmd_cleanup(dev);
 
 	return 0;
@@ -1168,7 +1180,7 @@
 	mlx5_put_uars_page(dev, dev->priv.uar);
 }
 
-static int mlx5_load_one(struct mlx5_core_dev *dev, bool boot)
+int mlx5_load_one(struct mlx5_core_dev *dev, bool boot)
 {
 	int err = 0;
 
@@ -1183,7 +1195,7 @@
 
 	err = mlx5_function_setup(dev, boot);
 	if (err)
-		goto out;
+		goto err_function;
 
 	if (boot) {
 		err = mlx5_init_once(dev);
@@ -1197,6 +1209,12 @@
 	if (err)
 		goto err_load;
 
+	if (boot) {
+		err = mlx5_devlink_register(priv_to_devlink(dev), dev->device);
+		if (err)
+			goto err_devlink_reg;
+	}
+
 	if (mlx5_device_registered(dev)) {
 		mlx5_attach_device(dev);
 	} else {
@@ -1214,22 +1232,24 @@
 	return err;
 
 err_reg_dev:
+	if (boot)
+		mlx5_devlink_unregister(priv_to_devlink(dev));
+err_devlink_reg:
 	mlx5_unload(dev);
 err_load:
 	if (boot)
 		mlx5_cleanup_once(dev);
 function_teardown:
 	mlx5_function_teardown(dev, boot);
+err_function:
 	dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR;
 	mutex_unlock(&dev->intf_state_mutex);
 
 	return err;
 }
 
-static int mlx5_unload_one(struct mlx5_core_dev *dev, bool cleanup)
+int mlx5_unload_one(struct mlx5_core_dev *dev, bool cleanup)
 {
-	int err = 0;
-
 	if (cleanup) {
 		mlx5_unregister_device(dev);
 		mlx5_drain_health_wq(dev);
@@ -1257,7 +1277,7 @@
 	mlx5_function_teardown(dev, cleanup);
 out:
 	mutex_unlock(&dev->intf_state_mutex);
-	return err;
+	return 0;
 }
 
 static int mlx5_mdev_init(struct mlx5_core_dev *dev, int profile_idx)
@@ -1353,10 +1373,6 @@
 
 	request_module_nowait(MLX5_IB_MOD);
 
-	err = mlx5_devlink_register(devlink, &pdev->dev);
-	if (err)
-		goto clean_load;
-
 	err = mlx5_crdump_enable(dev);
 	if (err)
 		dev_err(&pdev->dev, "mlx5_crdump_enable failed with error code %d\n", err);
@@ -1364,9 +1380,6 @@
 	pci_save_state(pdev);
 	return 0;
 
-clean_load:
-	mlx5_unload_one(dev, true);
-
 err_load_one:
 	mlx5_pci_close(dev);
 pci_init_err:
@@ -1551,6 +1564,22 @@
 	mlx5_pci_disable_device(dev);
 }
 
+static int mlx5_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct mlx5_core_dev *dev = pci_get_drvdata(pdev);
+
+	mlx5_unload_one(dev, false);
+
+	return 0;
+}
+
+static int mlx5_resume(struct pci_dev *pdev)
+{
+	struct mlx5_core_dev *dev = pci_get_drvdata(pdev);
+
+	return mlx5_load_one(dev, false);
+}
+
 static const struct pci_device_id mlx5_core_pci_table[] = {
 	{ PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_CONNECTIB) },
 	{ PCI_VDEVICE(MELLANOX, 0x1012), MLX5_PCI_DEV_IS_VF},	/* Connect-IB VF */
@@ -1567,6 +1596,7 @@
 	{ PCI_VDEVICE(MELLANOX, 0x101d) },			/* ConnectX-6 Dx */
 	{ PCI_VDEVICE(MELLANOX, 0x101e), MLX5_PCI_DEV_IS_VF},	/* ConnectX Family mlx5Gen Virtual Function */
 	{ PCI_VDEVICE(MELLANOX, 0x101f) },			/* ConnectX-6 LX */
+	{ PCI_VDEVICE(MELLANOX, 0x1021) },			/* ConnectX-7 */
 	{ PCI_VDEVICE(MELLANOX, 0xa2d2) },			/* BlueField integrated ConnectX-5 network controller */
 	{ PCI_VDEVICE(MELLANOX, 0xa2d3), MLX5_PCI_DEV_IS_VF},	/* BlueField integrated ConnectX-5 network controller VF */
 	{ PCI_VDEVICE(MELLANOX, 0xa2d6) },			/* BlueField-2 integrated ConnectX-6 Dx network controller */
@@ -1589,10 +1619,12 @@
 }
 
 static struct pci_driver mlx5_core_driver = {
-	.name           = DRIVER_NAME,
+	.name           = KBUILD_MODNAME,
 	.id_table       = mlx5_core_pci_table,
 	.probe          = init_one,
 	.remove         = remove_one,
+	.suspend        = mlx5_suspend,
+	.resume         = mlx5_resume,
 	.shutdown	= shutdown,
 	.err_handler	= &mlx5_err_handler,
 	.sriov_configure   = mlx5_core_sriov_configure,
@@ -1609,10 +1641,13 @@
 	}
 }
 
-static int __init init(void)
+static int __init mlx5_init(void)
 {
 	int err;
 
+	WARN_ONCE(strcmp(MLX5_ADEV_NAME, KBUILD_MODNAME),
+		  "mlx5_core name not in sync with kernel module name");
+
 	get_random_bytes(&sw_owner_id, sizeof(sw_owner_id));
 
 	mlx5_core_verify_params();
@@ -1634,7 +1669,7 @@
 	return err;
 }
 
-static void __exit cleanup(void)
+static void __exit mlx5_cleanup(void)
 {
 #ifdef CONFIG_MLX5_CORE_EN
 	mlx5e_cleanup();
@@ -1643,5 +1678,5 @@
 	mlx5_unregister_debugfs();
 }
 
-module_init(init);
-module_exit(cleanup);
+module_init(mlx5_init);
+module_exit(mlx5_cleanup);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
@@ -43,9 +43,6 @@
 #include <linux/mlx5/fs.h>
 #include <linux/mlx5/driver.h>
 
-#define DRIVER_NAME "mlx5_core"
-#define DRIVER_VERSION "5.0-0"
-
 extern uint mlx5_core_debug_mask;
 
 #define mlx5_core_dbg(__dev, format, ...)				\
@@ -243,4 +240,7 @@
 
 u8 mlx5_get_nic_state(struct mlx5_core_dev *dev);
 void mlx5_set_nic_state(struct mlx5_core_dev *dev, u8 state);
+
+int mlx5_unload_one(struct mlx5_core_dev *dev, bool cleanup);
+int mlx5_load_one(struct mlx5_core_dev *dev, bool boot);
 #endif /* __MLX5_CORE_H__ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
@@ -167,7 +167,8 @@
 	fp = list_entry(dev->priv.free_list.next, struct fw_page, list);
 	n = find_first_bit(&fp->bitmask, 8 * sizeof(fp->bitmask));
 	if (n >= MLX5_NUM_4K_IN_PAGE) {
-		mlx5_core_warn(dev, "alloc 4k bug\n");
+		mlx5_core_warn(dev, "alloc 4k bug: fw page = 0x%llx, n = %u, bitmask: %lu, max num of 4K pages: %d\n",
+			       fp->addr, n, fp->bitmask,  MLX5_NUM_4K_IN_PAGE);
 		return -ENOENT;
 	}
 	clear_bit(n, &fp->bitmask);
@@ -339,6 +340,24 @@
 	return err;
 }
 
+static u32 fwp_fill_manage_pages_out(struct fw_page *fwp, u32 *out, u32 index,
+				     u32 npages)
+{
+	u32 pages_set = 0;
+	unsigned int n;
+
+	for_each_clear_bit(n, &fwp->bitmask, MLX5_NUM_4K_IN_PAGE) {
+		MLX5_ARRAY_SET64(manage_pages_out, out, pas, index + pages_set,
+				 fwp->addr + (n * MLX5_ADAPTER_PAGE_SIZE));
+		pages_set++;
+
+		if (!--npages)
+			break;
+	}
+
+	return pages_set;
+}
+
 static int reclaim_pages_cmd(struct mlx5_core_dev *dev,
 			     u32 *in, int in_size, u32 *out, int out_size)
 {
@@ -348,7 +367,7 @@
 	u32 npages;
 	u32 i = 0;
 
-	if (dev->state != MLX5_DEVICE_STATE_INTERNAL_ERROR)
+	if (!mlx5_cmd_is_down(dev))
 		return mlx5_cmd_exec(dev, in, in_size, out, out_size);
 
 	/* No hard feelings, we want our pages back! */
@@ -362,8 +381,7 @@
 		if (fwp->func_id != func_id)
 			continue;
 
-		MLX5_ARRAY_SET64(manage_pages_out, out, pas, i, fwp->addr);
-		i++;
+		i += fwp_fill_manage_pages_out(fwp, out, i, npages - i);
 	}
 
 	MLX5_SET(manage_pages_out, out, output_num_entries, i);
@@ -486,8 +504,8 @@
 
 int mlx5_satisfy_startup_pages(struct mlx5_core_dev *dev, int boot)
 {
-	u16 uninitialized_var(func_id);
-	s32 uninitialized_var(npages);
+	u16 func_id;
+	s32 npages;
 	int err;
 
 	err = mlx5_cmd_query_pages(dev, &func_id, &npages, boot);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
@@ -115,7 +115,7 @@
 	return 0;
 
 err_request_irq:
-	for (; i >= 0; i--) {
+	while (i--) {
 		struct mlx5_irq *irq = mlx5_irq_get(dev, i);
 		int irqn = pci_irq_vector(dev->pdev, i);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/port.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/port.c
@@ -293,7 +293,40 @@
 	return 0;
 }
 
-static int mlx5_eeprom_page(int offset)
+static int mlx5_query_module_id(struct mlx5_core_dev *dev, int module_num,
+				u8 *module_id)
+{
+	u32 in[MLX5_ST_SZ_DW(mcia_reg)] = {};
+	u32 out[MLX5_ST_SZ_DW(mcia_reg)];
+	int err, status;
+	u8 *ptr;
+
+	MLX5_SET(mcia_reg, in, i2c_device_address, MLX5_I2C_ADDR_LOW);
+	MLX5_SET(mcia_reg, in, module, module_num);
+	MLX5_SET(mcia_reg, in, device_address, 0);
+	MLX5_SET(mcia_reg, in, page_number, 0);
+	MLX5_SET(mcia_reg, in, size, 1);
+	MLX5_SET(mcia_reg, in, l, 0);
+
+	err = mlx5_core_access_reg(dev, in, sizeof(in), out,
+				   sizeof(out), MLX5_REG_MCIA, 0, 0);
+	if (err)
+		return err;
+
+	status = MLX5_GET(mcia_reg, out, status);
+	if (status) {
+		mlx5_core_err(dev, "query_mcia_reg failed: status: 0x%x\n",
+			      status);
+		return -EIO;
+	}
+	ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0);
+
+	*module_id = ptr[0];
+
+	return 0;
+}
+
+static int mlx5_qsfp_eeprom_page(u16 offset)
 {
 	if (offset < MLX5_EEPROM_PAGE_LENGTH)
 		/* Addresses between 0-255 - page 00 */
@@ -307,7 +340,7 @@
 		    MLX5_EEPROM_HIGH_PAGE_LENGTH);
 }
 
-static int mlx5_eeprom_high_page_offset(int page_num)
+static int mlx5_qsfp_eeprom_high_page_offset(int page_num)
 {
 	if (!page_num) /* Page 0 always start from low page */
 		return 0;
@@ -316,35 +349,62 @@
 	return page_num * MLX5_EEPROM_HIGH_PAGE_LENGTH;
 }
 
+static void mlx5_qsfp_eeprom_params_set(u16 *i2c_addr, int *page_num, u16 *offset)
+{
+	*i2c_addr = MLX5_I2C_ADDR_LOW;
+	*page_num = mlx5_qsfp_eeprom_page(*offset);
+	*offset -=  mlx5_qsfp_eeprom_high_page_offset(*page_num);
+}
+
+static void mlx5_sfp_eeprom_params_set(u16 *i2c_addr, int *page_num, u16 *offset)
+{
+	*i2c_addr = MLX5_I2C_ADDR_LOW;
+	*page_num = 0;
+
+	if (*offset < MLX5_EEPROM_PAGE_LENGTH)
+		return;
+
+	*i2c_addr = MLX5_I2C_ADDR_HIGH;
+	*offset -= MLX5_EEPROM_PAGE_LENGTH;
+}
+
 int mlx5_query_module_eeprom(struct mlx5_core_dev *dev,
 			     u16 offset, u16 size, u8 *data)
 {
-	int module_num, page_num, status, err;
+	int module_num, status, err, page_num = 0;
+	u32 in[MLX5_ST_SZ_DW(mcia_reg)] = {};
 	u32 out[MLX5_ST_SZ_DW(mcia_reg)];
-	u32 in[MLX5_ST_SZ_DW(mcia_reg)];
-	u16 i2c_addr;
-	void *ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0);
+	u16 i2c_addr = 0;
+	u8 module_id;
+	void *ptr;
 
 	err = mlx5_query_module_num(dev, &module_num);
 	if (err)
 		return err;
 
-	memset(in, 0, sizeof(in));
-	size = min_t(int, size, MLX5_EEPROM_MAX_BYTES);
-
-	/* Get the page number related to the given offset */
-	page_num = mlx5_eeprom_page(offset);
+	err = mlx5_query_module_id(dev, module_num, &module_id);
+	if (err)
+		return err;
 
-	/* Set the right offset according to the page number,
-	 * For page_num > 0, relative offset is always >= 128 (high page).
-	 */
-	offset -= mlx5_eeprom_high_page_offset(page_num);
+	switch (module_id) {
+	case MLX5_MODULE_ID_SFP:
+		mlx5_sfp_eeprom_params_set(&i2c_addr, &page_num, &offset);
+		break;
+	case MLX5_MODULE_ID_QSFP:
+	case MLX5_MODULE_ID_QSFP_PLUS:
+	case MLX5_MODULE_ID_QSFP28:
+		mlx5_qsfp_eeprom_params_set(&i2c_addr, &page_num, &offset);
+		break;
+	default:
+		mlx5_core_err(dev, "Module ID not recognized: 0x%x\n", module_id);
+		return -EINVAL;
+	}
 
 	if (offset + size > MLX5_EEPROM_PAGE_LENGTH)
 		/* Cross pages read, read until offset 256 in low page */
 		size -= offset + size - MLX5_EEPROM_PAGE_LENGTH;
 
-	i2c_addr = MLX5_I2C_ADDR_LOW;
+	size = min_t(int, size, MLX5_EEPROM_MAX_BYTES);
 
 	MLX5_SET(mcia_reg, in, l, 0);
 	MLX5_SET(mcia_reg, in, module, module_num);
@@ -365,6 +425,7 @@
 		return -EIO;
 	}
 
+	ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0);
 	memcpy(data, ptr, size);
 
 	return size;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/rdma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/rdma.c
@@ -116,7 +116,7 @@
 static void mlx5_rdma_del_roce_addr(struct mlx5_core_dev *dev)
 {
 	mlx5_core_roce_gid_set(dev, 0, 0, 0,
-			       NULL, NULL, false, 0, 0);
+			       NULL, NULL, false, 0, 1);
 }
 
 static void mlx5_rdma_make_default_gid(struct mlx5_core_dev *dev, union ib_gid *gid)
@@ -156,6 +156,9 @@
 {
 	int err;
 
+	if (!MLX5_CAP_GEN(dev, roce))
+		return;
+
 	err = mlx5_nic_vport_enable_roce(dev);
 	if (err) {
 		mlx5_core_err(dev, "Failed to enable RoCE: %d\n", err);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/sriov.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/sriov.c
@@ -211,8 +211,7 @@
 		host_total_vfs = MLX5_GET(query_esw_functions_out, out,
 					  host_params_context.host_total_vfs);
 		kvfree(out);
-		if (host_total_vfs)
-			return host_total_vfs;
+		return host_total_vfs;
 	}
 
 done:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c
@@ -667,6 +667,7 @@
 		switch (action_type) {
 		case DR_ACTION_TYP_DROP:
 			attr.final_icm_addr = nic_dmn->drop_icm_addr;
+			attr.hit_gvmi = nic_dmn->drop_icm_addr >> 48;
 			break;
 		case DR_ACTION_TYP_FT:
 			dest_action = action;
@@ -930,7 +931,6 @@
 
 	action->rewrite.data = (void *)ops;
 	action->rewrite.num_of_actions = i;
-	action->rewrite.chunk->byte_size = i * sizeof(*ops);
 
 	ret = mlx5dr_send_postsend_action(dmn, action);
 	if (ret) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_cmd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_cmd.c
@@ -92,6 +92,7 @@
 	caps->eswitch_manager	= MLX5_CAP_GEN(mdev, eswitch_manager);
 	caps->gvmi		= MLX5_CAP_GEN(mdev, vhca_id);
 	caps->flex_protocols	= MLX5_CAP_GEN(mdev, flex_parser_protocols);
+	caps->sw_format_ver	= MLX5_CAP_GEN(mdev, steering_format_version);
 
 	if (mlx5dr_matcher_supp_flex_parser_icmp_v4(caps)) {
 		caps->flex_parser_id_icmp_dw0 = MLX5_CAP_GEN(mdev, flex_parser_id_icmp_dw0);
@@ -422,11 +423,12 @@
 
 	err = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out));
 	if (err)
-		return err;
+		goto err_free_in;
 
 	*reformat_id = MLX5_GET(alloc_packet_reformat_context_out, out, packet_reformat_id);
-	kvfree(in);
 
+err_free_in:
+	kvfree(in);
 	return err;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c
@@ -2,6 +2,7 @@
 /* Copyright (c) 2019 Mellanox Technologies. */
 
 #include <linux/mlx5/eswitch.h>
+#include <linux/err.h>
 #include "dr_types.h"
 
 static int dr_domain_init_cache(struct mlx5dr_domain *dmn)
@@ -64,9 +65,9 @@
 	}
 
 	dmn->uar = mlx5_get_uars_page(dmn->mdev);
-	if (!dmn->uar) {
+	if (IS_ERR(dmn->uar)) {
 		mlx5dr_err(dmn, "Couldn't allocate UAR\n");
-		ret = -ENOMEM;
+		ret = PTR_ERR(dmn->uar);
 		goto clean_pd;
 	}
 
@@ -223,6 +224,11 @@
 	if (ret)
 		return ret;
 
+	if (dmn->info.caps.sw_format_ver != MLX5_STEERING_FORMAT_CONNECTX_5) {
+		mlx5dr_err(dmn, "SW steering is not supported on this device\n");
+		return -EOPNOTSUPP;
+	}
+
 	ret = dr_domain_query_fdb_caps(mdev, dmn);
 	if (ret)
 		return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_rule.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_rule.c
@@ -209,7 +209,7 @@
 	/* We need to copy the refcount since this ste
 	 * may have been traversed several times
 	 */
-	refcount_set(&new_ste->refcount, refcount_read(&cur_ste->refcount));
+	new_ste->refcount = cur_ste->refcount;
 
 	/* Link old STEs rule_mem list to the new ste */
 	mlx5dr_rule_update_rule_member(cur_ste, new_ste);
@@ -638,6 +638,9 @@
 	if (!rule_mem)
 		return -ENOMEM;
 
+	INIT_LIST_HEAD(&rule_mem->list);
+	INIT_LIST_HEAD(&rule_mem->use_ste_list);
+
 	rule_mem->ste = ste;
 	list_add_tail(&rule_mem->list, &nic_rule->rule_members_list);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
 /* Copyright (c) 2019 Mellanox Technologies. */
 
+#include <linux/smp.h>
 #include "dr_types.h"
 
 #define QUEUE_SIZE 128
@@ -180,7 +181,7 @@
 							 in, pas));
 
 	err = mlx5_core_create_qp(mdev, &dr_qp->mqp, in, inlen);
-	kfree(in);
+	kvfree(in);
 
 	if (err) {
 		mlx5_core_warn(mdev, " Can't create QP\n");
@@ -557,7 +558,8 @@
 	int ret;
 
 	send_info.write.addr = (uintptr_t)action->rewrite.data;
-	send_info.write.length = action->rewrite.chunk->byte_size;
+	send_info.write.length = action->rewrite.num_of_actions *
+				 DR_MODIFY_ACTION_SIZE;
 	send_info.write.lkey = 0;
 	send_info.remote_addr = action->rewrite.chunk->mr_addr;
 	send_info.rkey = action->rewrite.chunk->rkey;
@@ -601,6 +603,7 @@
 	MLX5_SET(qpc, qpc, log_ack_req_freq, 0);
 	MLX5_SET(qpc, qpc, retry_count, attr->retry_cnt);
 	MLX5_SET(qpc, qpc, rnr_retry, attr->rnr_retry);
+	MLX5_SET(qpc, qpc, primary_address_path.ack_timeout, 0x8); /* ~1ms */
 
 	return mlx5_core_qp_modify(mdev, MLX5_CMD_OP_RTR2RTS_QP, 0, qpc,
 				   &dr_qp->mqp);
@@ -687,6 +690,12 @@
 	pr_info("CQ event %u on CQ #%u\n", event, mcq->cqn);
 }
 
+static void dr_cq_complete(struct mlx5_core_cq *mcq,
+			   struct mlx5_eqe *eqe)
+{
+	pr_err("CQ completion CQ: #%u\n", mcq->cqn);
+}
+
 static struct mlx5dr_cq *dr_create_cq(struct mlx5_core_dev *mdev,
 				      struct mlx5_uars_page *uar,
 				      size_t ncqe)
@@ -729,7 +738,7 @@
 	if (!in)
 		goto err_cqwq;
 
-	vector = smp_processor_id() % mlx5_comp_vectors_count(mdev);
+	vector = raw_smp_processor_id() % mlx5_comp_vectors_count(mdev);
 	err = mlx5_vector2eqn(mdev, vector, &eqn, &irqn);
 	if (err) {
 		kvfree(in);
@@ -748,6 +757,7 @@
 	mlx5_fill_page_frag_array(&cq->wq_ctrl.buf, pas);
 
 	cq->mcq.event = dr_cq_event;
+	cq->mcq.comp  = dr_cq_complete;
 
 	err = mlx5_core_create_cq(mdev, &cq->mcq, in, inlen, out, sizeof(out));
 	kvfree(in);
@@ -759,7 +769,12 @@
 	cq->mcq.set_ci_db = cq->wq_ctrl.db.db;
 	cq->mcq.arm_db = cq->wq_ctrl.db.db + 1;
 	*cq->mcq.set_ci_db = 0;
-	*cq->mcq.arm_db = 0;
+
+	/* set no-zero value, in order to avoid the HW to run db-recovery on
+	 * CQ that used in polling mode.
+	 */
+	*cq->mcq.arm_db = cpu_to_be32(2 << 28);
+
 	cq->mcq.vector = 0;
 	cq->mcq.irqn = irqn;
 	cq->mcq.uar = uar;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste.c
@@ -340,7 +340,7 @@
 	if (dst->next_htbl)
 		dst->next_htbl->pointing_ste = dst;
 
-	refcount_set(&dst->refcount, refcount_read(&src->refcount));
+	dst->refcount = src->refcount;
 
 	INIT_LIST_HEAD(&dst->rule_list);
 	list_splice_tail_init(&src->rule_list, &dst->rule_list);
@@ -557,7 +557,7 @@
 
 bool mlx5dr_ste_not_used_ste(struct mlx5dr_ste *ste)
 {
-	return !refcount_read(&ste->refcount);
+	return !ste->refcount;
 }
 
 /* Init one ste as a pattern for ste data array */
@@ -681,14 +681,14 @@
 	htbl->ste_arr = chunk->ste_arr;
 	htbl->hw_ste_arr = chunk->hw_ste_arr;
 	htbl->miss_list = chunk->miss_list;
-	refcount_set(&htbl->refcount, 0);
+	htbl->refcount = 0;
 
 	for (i = 0; i < chunk->num_of_entries; i++) {
 		struct mlx5dr_ste *ste = &htbl->ste_arr[i];
 
 		ste->hw_ste = htbl->hw_ste_arr + i * DR_STE_SIZE_REDUCED;
 		ste->htbl = htbl;
-		refcount_set(&ste->refcount, 0);
+		ste->refcount = 0;
 		INIT_LIST_HEAD(&ste->miss_list_node);
 		INIT_LIST_HEAD(&htbl->miss_list[i]);
 		INIT_LIST_HEAD(&ste->rule_list);
@@ -705,7 +705,7 @@
 
 int mlx5dr_ste_htbl_free(struct mlx5dr_ste_htbl *htbl)
 {
-	if (refcount_read(&htbl->refcount))
+	if (htbl->refcount)
 		return -EBUSY;
 
 	mlx5dr_icm_free_chunk(htbl->chunk);
@@ -2257,7 +2257,9 @@
 	struct mlx5dr_cmd_vport_cap *vport_cap;
 	struct mlx5dr_domain *dmn = sb->dmn;
 	struct mlx5dr_cmd_caps *caps;
+	u8 *bit_mask = sb->bit_mask;
 	u8 *tag = hw_ste->tag;
+	bool source_gvmi_set;
 
 	DR_STE_SET_TAG(src_gvmi_qp, tag, source_qp, misc, source_sqn);
 
@@ -2278,7 +2280,8 @@
 	if (!vport_cap)
 		return -EINVAL;
 
-	if (vport_cap->vport_gvmi)
+	source_gvmi_set = MLX5_GET(ste_src_gvmi_qp, bit_mask, source_gvmi);
+	if (vport_cap->vport_gvmi && source_gvmi_set)
 		MLX5_SET(ste_src_gvmi_qp, tag, source_gvmi, vport_cap->vport_gvmi);
 
 	misc->source_eswitch_owner_vhca_id = 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_table.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_table.c
@@ -9,7 +9,7 @@
 	struct mlx5dr_matcher *last_matcher = NULL;
 	struct mlx5dr_htbl_connect_info info;
 	struct mlx5dr_ste_htbl *last_htbl;
-	int ret;
+	int ret = -EOPNOTSUPP;
 
 	if (action && action->action_type != DR_ACTION_TYP_FT)
 		return -EOPNOTSUPP;
@@ -68,6 +68,9 @@
 		}
 	}
 
+	if (ret)
+		goto out;
+
 	/* Release old action */
 	if (tbl->miss_action)
 		refcount_dec(&tbl->miss_action->refcount);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h
@@ -117,7 +117,7 @@
 struct mlx5dr_ste {
 	u8 *hw_ste;
 	/* refcount: indicates the num of rules that using this ste */
-	refcount_t refcount;
+	u32 refcount;
 
 	/* attached to the miss_list head at each htbl entry */
 	struct list_head miss_list_node;
@@ -149,7 +149,7 @@
 struct mlx5dr_ste_htbl {
 	u8 lu_type;
 	u16 byte_mask;
-	refcount_t refcount;
+	u32 refcount;
 	struct mlx5dr_icm_chunk *chunk;
 	struct mlx5dr_ste *ste_arr;
 	u8 *hw_ste_arr;
@@ -200,13 +200,14 @@
 
 static inline void mlx5dr_htbl_put(struct mlx5dr_ste_htbl *htbl)
 {
-	if (refcount_dec_and_test(&htbl->refcount))
+	htbl->refcount--;
+	if (!htbl->refcount)
 		mlx5dr_ste_htbl_free(htbl);
 }
 
 static inline void mlx5dr_htbl_get(struct mlx5dr_ste_htbl *htbl)
 {
-	refcount_inc(&htbl->refcount);
+	htbl->refcount++;
 }
 
 /* STE utils */
@@ -248,14 +249,15 @@
 				  struct mlx5dr_matcher *matcher,
 				  struct mlx5dr_matcher_rx_tx *nic_matcher)
 {
-	if (refcount_dec_and_test(&ste->refcount))
+	ste->refcount--;
+	if (!ste->refcount)
 		mlx5dr_ste_free(ste, matcher, nic_matcher);
 }
 
 /* initial as 0, increased only when ste appears in a new rule */
 static inline void mlx5dr_ste_get(struct mlx5dr_ste *ste)
 {
-	refcount_inc(&ste->refcount);
+	ste->refcount++;
 }
 
 void mlx5dr_ste_set_hit_addr_by_next_htbl(u8 *hw_ste,
@@ -611,6 +613,7 @@
 	u8 max_ft_level;
 	u16 roce_min_src_udp;
 	u8 num_esw_ports;
+	u8 sw_format_ver;
 	bool eswitch_manager;
 	bool rx_sw_owner;
 	bool tx_sw_owner;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c
@@ -43,11 +43,10 @@
 	err = mlx5dr_table_set_miss_action(ft->fs_dr_table.dr_table, action);
 	if (err && action) {
 		err = mlx5dr_action_destroy(action);
-		if (err) {
-			action = NULL;
-			mlx5_core_err(ns->dev, "Failed to destroy action (%d)\n",
-				      err);
-		}
+		if (err)
+			mlx5_core_err(ns->dev,
+				      "Failed to destroy action (%d)\n", err);
+		action = NULL;
 	}
 	ft->fs_dr_table.miss_action = action;
 	if (old_miss_action) {
@@ -247,29 +246,9 @@
 
 	/* The order of the actions are must to be keep, only the following
 	 * order is supported by SW steering:
-	 * TX: push vlan -> modify header -> encap
+	 * TX: modify header -> push vlan -> encap
 	 * RX: decap -> pop vlan -> modify header
 	 */
-	if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH) {
-		tmp_action = create_action_push_vlan(domain, &fte->action.vlan[0]);
-		if (!tmp_action) {
-			err = -ENOMEM;
-			goto free_actions;
-		}
-		fs_dr_actions[fs_dr_num_actions++] = tmp_action;
-		actions[num_actions++] = tmp_action;
-	}
-
-	if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2) {
-		tmp_action = create_action_push_vlan(domain, &fte->action.vlan[1]);
-		if (!tmp_action) {
-			err = -ENOMEM;
-			goto free_actions;
-		}
-		fs_dr_actions[fs_dr_num_actions++] = tmp_action;
-		actions[num_actions++] = tmp_action;
-	}
-
 	if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_DECAP) {
 		enum mlx5dr_action_reformat_type decap_type =
 			DR_ACTION_REFORMAT_TYP_TNL_L2_TO_L2;
@@ -322,6 +301,26 @@
 		actions[num_actions++] =
 			fte->action.modify_hdr->action.dr_action;
 
+	if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH) {
+		tmp_action = create_action_push_vlan(domain, &fte->action.vlan[0]);
+		if (!tmp_action) {
+			err = -ENOMEM;
+			goto free_actions;
+		}
+		fs_dr_actions[fs_dr_num_actions++] = tmp_action;
+		actions[num_actions++] = tmp_action;
+	}
+
+	if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2) {
+		tmp_action = create_action_push_vlan(domain, &fte->action.vlan[1]);
+		if (!tmp_action) {
+			err = -ENOMEM;
+			goto free_actions;
+		}
+		fs_dr_actions[fs_dr_num_actions++] = tmp_action;
+		actions[num_actions++] = tmp_action;
+	}
+
 	if (delay_encap_set)
 		actions[num_actions++] =
 			fte->action.pkt_reformat->action.dr_action;
@@ -352,26 +351,16 @@
 	if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
 		list_for_each_entry(dst, &fte->node.children, node.list) {
 			enum mlx5_flow_destination_type type = dst->dest_attr.type;
-			u32 id;
 
 			if (num_actions == MLX5_FLOW_CONTEXT_ACTION_MAX) {
 				err = -ENOSPC;
 				goto free_actions;
 			}
 
-			switch (type) {
-			case MLX5_FLOW_DESTINATION_TYPE_COUNTER:
-				id = dst->dest_attr.counter_id;
+			if (type == MLX5_FLOW_DESTINATION_TYPE_COUNTER)
+				continue;
 
-				tmp_action =
-					mlx5dr_action_create_flow_counter(id);
-				if (!tmp_action) {
-					err = -ENOMEM;
-					goto free_actions;
-				}
-				fs_dr_actions[fs_dr_num_actions++] = tmp_action;
-				actions[num_actions++] = tmp_action;
-				break;
+			switch (type) {
 			case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE:
 				tmp_action = create_ft_action(dev, dst);
 				if (!tmp_action) {
@@ -397,6 +386,32 @@
 		}
 	}
 
+	if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
+		list_for_each_entry(dst, &fte->node.children, node.list) {
+			u32 id;
+
+			if (dst->dest_attr.type !=
+			    MLX5_FLOW_DESTINATION_TYPE_COUNTER)
+				continue;
+
+			if (num_actions == MLX5_FLOW_CONTEXT_ACTION_MAX) {
+				err = -ENOSPC;
+				goto free_actions;
+			}
+
+			id = dst->dest_attr.counter_id;
+			tmp_action =
+				mlx5dr_action_create_flow_counter(id);
+			if (!tmp_action) {
+				err = -ENOMEM;
+				goto free_actions;
+			}
+
+			fs_dr_actions[fs_dr_num_actions++] = tmp_action;
+			actions[num_actions++] = tmp_action;
+		}
+	}
+
 	params.match_sz = match_sz;
 	params.match_buf = (u64 *)fte->val;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/transobj.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/transobj.c
@@ -457,6 +457,15 @@
 	return err;
 }
 
+static void mlx5_hairpin_unpair_peer_sq(struct mlx5_hairpin *hp)
+{
+	int i;
+
+	for (i = 0; i < hp->num_channels; i++)
+		mlx5_hairpin_modify_sq(hp->peer_mdev, hp->sqn[i], MLX5_SQC_STATE_RDY,
+				       MLX5_SQC_STATE_RST, 0, 0);
+}
+
 static void mlx5_hairpin_unpair_queues(struct mlx5_hairpin *hp)
 {
 	int i;
@@ -465,13 +474,9 @@
 	for (i = 0; i < hp->num_channels; i++)
 		mlx5_hairpin_modify_rq(hp->func_mdev, hp->rqn[i], MLX5_RQC_STATE_RDY,
 				       MLX5_RQC_STATE_RST, 0, 0);
-
 	/* unset peer SQs */
-	if (hp->peer_gone)
-		return;
-	for (i = 0; i < hp->num_channels; i++)
-		mlx5_hairpin_modify_sq(hp->peer_mdev, hp->sqn[i], MLX5_SQC_STATE_RDY,
-				       MLX5_SQC_STATE_RST, 0, 0);
+	if (!hp->peer_gone)
+		mlx5_hairpin_unpair_peer_sq(hp);
 }
 
 struct mlx5_hairpin *
@@ -518,3 +523,16 @@
 	mlx5_hairpin_destroy_queues(hp);
 	kfree(hp);
 }
+
+void mlx5_core_hairpin_clear_dead_peer(struct mlx5_hairpin *hp)
+{
+	int i;
+
+	mlx5_hairpin_unpair_peer_sq(hp);
+
+	/* destroy peer SQ */
+	for (i = 0; i < hp->num_channels; i++)
+		mlx5_core_destroy_sq(hp->peer_mdev, hp->sqn[i]);
+
+	hp->peer_gone = true;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/wq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/wq.c
@@ -96,6 +96,13 @@
 	return err;
 }
 
+void mlx5_wq_cyc_reset(struct mlx5_wq_cyc *wq)
+{
+	wq->wqe_ctr = 0;
+	wq->cur_sz = 0;
+	mlx5_wq_cyc_update_db_record(wq);
+}
+
 int mlx5_wq_qp_create(struct mlx5_core_dev *mdev, struct mlx5_wq_param *param,
 		      void *qpc, struct mlx5_wq_qp *wq,
 		      struct mlx5_wq_ctrl *wq_ctrl)
@@ -194,6 +201,19 @@
 	return err;
 }
 
+static void mlx5_wq_ll_init_list(struct mlx5_wq_ll *wq)
+{
+	struct mlx5_wqe_srq_next_seg *next_seg;
+	int i;
+
+	for (i = 0; i < wq->fbc.sz_m1; i++) {
+		next_seg = mlx5_wq_ll_get_wqe(wq, i);
+		next_seg->next_wqe_index = cpu_to_be16(i + 1);
+	}
+	next_seg = mlx5_wq_ll_get_wqe(wq, i);
+	wq->tail_next = &next_seg->next_wqe_index;
+}
+
 int mlx5_wq_ll_create(struct mlx5_core_dev *mdev, struct mlx5_wq_param *param,
 		      void *wqc, struct mlx5_wq_ll *wq,
 		      struct mlx5_wq_ctrl *wq_ctrl)
@@ -201,9 +221,7 @@
 	u8 log_wq_stride = MLX5_GET(wq, wqc, log_wq_stride);
 	u8 log_wq_sz     = MLX5_GET(wq, wqc, log_wq_sz);
 	struct mlx5_frag_buf_ctrl *fbc = &wq->fbc;
-	struct mlx5_wqe_srq_next_seg *next_seg;
 	int err;
-	int i;
 
 	err = mlx5_db_alloc_node(mdev, &wq_ctrl->db, param->db_numa_node);
 	if (err) {
@@ -222,13 +240,7 @@
 
 	mlx5_init_fbc(wq_ctrl->buf.frags, log_wq_stride, log_wq_sz, fbc);
 
-	for (i = 0; i < fbc->sz_m1; i++) {
-		next_seg = mlx5_wq_ll_get_wqe(wq, i);
-		next_seg->next_wqe_index = cpu_to_be16(i + 1);
-	}
-	next_seg = mlx5_wq_ll_get_wqe(wq, i);
-	wq->tail_next = &next_seg->next_wqe_index;
-
+	mlx5_wq_ll_init_list(wq);
 	wq_ctrl->mdev = mdev;
 
 	return 0;
@@ -239,6 +251,15 @@
 	return err;
 }
 
+void mlx5_wq_ll_reset(struct mlx5_wq_ll *wq)
+{
+	wq->head = 0;
+	wq->wqe_ctr = 0;
+	wq->cur_sz = 0;
+	mlx5_wq_ll_init_list(wq);
+	mlx5_wq_ll_update_db_record(wq);
+}
+
 void mlx5_wq_destroy(struct mlx5_wq_ctrl *wq_ctrl)
 {
 	mlx5_frag_buf_free(wq_ctrl->mdev, &wq_ctrl->buf);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlx5/core/wq.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlx5/core/wq.h
@@ -80,10 +80,12 @@
 		       void *wqc, struct mlx5_wq_cyc *wq,
 		       struct mlx5_wq_ctrl *wq_ctrl);
 u32 mlx5_wq_cyc_get_size(struct mlx5_wq_cyc *wq);
+void mlx5_wq_cyc_reset(struct mlx5_wq_cyc *wq);
 
 int mlx5_wq_qp_create(struct mlx5_core_dev *mdev, struct mlx5_wq_param *param,
 		      void *qpc, struct mlx5_wq_qp *wq,
 		      struct mlx5_wq_ctrl *wq_ctrl);
+void mlx5_wq_ll_reset(struct mlx5_wq_ll *wq);
 
 int mlx5_cqwq_create(struct mlx5_core_dev *mdev, struct mlx5_wq_param *param,
 		     void *cqc, struct mlx5_cqwq *wq,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlxfw/mlxfw_fsm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlxfw/mlxfw_fsm.c
@@ -14,7 +14,6 @@
 #define MLXFW_FSM_STATE_WAIT_TIMEOUT_MS 30000
 #define MLXFW_FSM_STATE_WAIT_ROUNDS \
 	(MLXFW_FSM_STATE_WAIT_TIMEOUT_MS / MLXFW_FSM_STATE_WAIT_CYCLE_MS)
-#define MLXFW_FSM_MAX_COMPONENT_SIZE (10 * (1 << 20))
 
 static const char * const mlxfw_fsm_state_err_str[] = {
 	[MLXFW_FSM_STATE_ERR_ERROR] =
@@ -111,7 +110,6 @@
 	if (err)
 		return err;
 
-	comp_max_size = min_t(u32, comp_max_size, MLXFW_FSM_MAX_COMPONENT_SIZE);
 	if (comp->data_size > comp_max_size) {
 		pr_err("Component %d is of size %d which is bigger than limit %d\n",
 		       comp->index, comp->data_size, comp_max_size);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2.c
@@ -6,6 +6,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/netlink.h>
+#include <linux/vmalloc.h>
 #include <linux/xz.h>
 #include "mlxfw_mfa2.h"
 #include "mlxfw_mfa2_file.h"
@@ -548,7 +549,7 @@
 	comp_size = be32_to_cpu(comp->size);
 	comp_buf_size = comp_size + mlxfw_mfa2_comp_magic_len;
 
-	comp_data = kmalloc(sizeof(*comp_data) + comp_buf_size, GFP_KERNEL);
+	comp_data = vzalloc(sizeof(*comp_data) + comp_buf_size);
 	if (!comp_data)
 		return ERR_PTR(-ENOMEM);
 	comp_data->comp.data_size = comp_size;
@@ -570,7 +571,7 @@
 	comp_data->comp.data = comp_data->buff + mlxfw_mfa2_comp_magic_len;
 	return &comp_data->comp;
 err_out:
-	kfree(comp_data);
+	vfree(comp_data);
 	return ERR_PTR(err);
 }
 
@@ -579,7 +580,7 @@
 	const struct mlxfw_mfa2_comp_data *comp_data;
 
 	comp_data = container_of(comp, struct mlxfw_mfa2_comp_data, comp);
-	kfree(comp_data);
+	vfree(comp_data);
 }
 
 void mlxfw_mfa2_file_fini(struct mlxfw_mfa2_file *mfa2_file)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv_multi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2_tlv_multi.c
@@ -31,6 +31,8 @@
 
 	if (tlv->type == MLXFW_MFA2_TLV_MULTI_PART) {
 		multi = mlxfw_mfa2_tlv_multi_get(mfa2_file, tlv);
+		if (!multi)
+			return NULL;
 		tlv_len = NLA_ALIGN(tlv_len + be16_to_cpu(multi->total_len));
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlxsw/core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlxsw/core.c
@@ -444,7 +444,8 @@
 	if (trans->core->fw_flash_in_progress)
 		timeout = msecs_to_jiffies(MLXSW_EMAD_TIMEOUT_DURING_FW_FLASH_MS);
 
-	queue_delayed_work(trans->core->emad_wq, &trans->timeout_dw, timeout);
+	queue_delayed_work(trans->core->emad_wq, &trans->timeout_dw,
+			   timeout << trans->retries);
 }
 
 static int mlxsw_emad_transmit(struct mlxsw_core *mlxsw_core,
@@ -493,6 +494,9 @@
 		err = mlxsw_emad_transmit(trans->core, trans);
 		if (err == 0)
 			return;
+
+		if (!atomic_dec_and_test(&trans->active))
+			return;
 	} else {
 		err = -EIO;
 	}
@@ -562,7 +566,7 @@
 
 static const struct mlxsw_listener mlxsw_emad_rx_listener =
 	MLXSW_RXL(mlxsw_emad_rx_listener_func, ETHEMAD, TRAP_TO_CPU, false,
-		  EMAD, DISCARD);
+		  EMAD, FORWARD);
 
 static int mlxsw_emad_init(struct mlxsw_core *mlxsw_core)
 {
@@ -592,7 +596,7 @@
 	err = mlxsw_core_trap_register(mlxsw_core, &mlxsw_emad_rx_listener,
 				       mlxsw_core);
 	if (err)
-		return err;
+		goto err_trap_register;
 
 	err = mlxsw_core->driver->basic_trap_groups_set(mlxsw_core);
 	if (err)
@@ -604,6 +608,7 @@
 err_emad_trap_set:
 	mlxsw_core_trap_unregister(mlxsw_core, &mlxsw_emad_rx_listener,
 				   mlxsw_core);
+err_trap_register:
 	destroy_workqueue(mlxsw_core->emad_wq);
 	return err;
 }
@@ -1280,6 +1285,8 @@
 	if (!reload)
 		devlink_resources_unregister(devlink, NULL);
 	mlxsw_core->bus->fini(mlxsw_core->bus_priv);
+	if (!reload)
+		devlink_free(devlink);
 
 	return;
 
@@ -1576,7 +1583,7 @@
 	err = mlxsw_emad_reg_access(mlxsw_core, reg, payload, type, trans,
 				    bulk_list, cb, cb_priv, tid);
 	if (err) {
-		kfree(trans);
+		kfree_rcu(trans, rcu);
 		return err;
 	}
 	return 0;
@@ -1801,11 +1808,13 @@
 			break;
 		}
 	}
-	rcu_read_unlock();
-	if (!found)
+	if (!found) {
+		rcu_read_unlock();
 		goto drop;
+	}
 
 	rxl->func(skb, local_port, rxl_item->priv);
+	rcu_read_unlock();
 	return;
 
 drop:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c
@@ -316,7 +316,7 @@
 
 	block = kzalloc(sizeof(*block), GFP_KERNEL);
 	if (!block)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 	INIT_LIST_HEAD(&block->resource_list);
 	block->afa = mlxsw_afa;
 
@@ -344,7 +344,7 @@
 	mlxsw_afa_set_destroy(block->first_set);
 err_first_set_create:
 	kfree(block);
-	return NULL;
+	return ERR_PTR(-ENOMEM);
 }
 EXPORT_SYMBOL(mlxsw_afa_block_create);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
@@ -19,22 +19,14 @@
 #define MLXSW_THERMAL_ASIC_TEMP_NORM	75000	/* 75C */
 #define MLXSW_THERMAL_ASIC_TEMP_HIGH	85000	/* 85C */
 #define MLXSW_THERMAL_ASIC_TEMP_HOT	105000	/* 105C */
-#define MLXSW_THERMAL_ASIC_TEMP_CRIT	110000	/* 110C */
+#define MLXSW_THERMAL_ASIC_TEMP_CRIT	140000	/* 140C */
 #define MLXSW_THERMAL_HYSTERESIS_TEMP	5000	/* 5C */
 #define MLXSW_THERMAL_MODULE_TEMP_SHIFT	(MLXSW_THERMAL_HYSTERESIS_TEMP * 2)
 #define MLXSW_THERMAL_ZONE_MAX_NAME	16
 #define MLXSW_THERMAL_TEMP_SCORE_MAX	GENMASK(31, 0)
 #define MLXSW_THERMAL_MAX_STATE	10
+#define MLXSW_THERMAL_MIN_STATE	2
 #define MLXSW_THERMAL_MAX_DUTY	255
-/* Minimum and maximum fan allowed speed in percent: from 20% to 100%. Values
- * MLXSW_THERMAL_MAX_STATE + x, where x is between 2 and 10 are used for
- * setting fan speed dynamic minimum. For example, if value is set to 14 (40%)
- * cooling levels vector will be set to 4, 4, 4, 4, 4, 5, 6, 7, 8, 9, 10 to
- * introduce PWM speed in percent: 40, 40, 40, 40, 40, 50, 60. 70, 80, 90, 100.
- */
-#define MLXSW_THERMAL_SPEED_MIN		(MLXSW_THERMAL_MAX_STATE + 2)
-#define MLXSW_THERMAL_SPEED_MAX		(MLXSW_THERMAL_MAX_STATE * 2)
-#define MLXSW_THERMAL_SPEED_MIN_LEVEL	2		/* 20% */
 
 /* External cooling devices, allowed for binding to mlxsw thermal zones. */
 static char * const mlxsw_thermal_external_allowed_cdev[] = {
@@ -177,6 +169,12 @@
 	if (err)
 		return err;
 
+	if (crit_temp > emerg_temp) {
+		dev_warn(dev, "%s : Critical threshold %d is above emergency threshold %d\n",
+			 tz->tzdev->type, crit_temp, emerg_temp);
+		return 0;
+	}
+
 	/* According to the system thermal requirements, the thermal zones are
 	 * defined with four trip points. The critical and emergency
 	 * temperature thresholds, provided by QSFP module are set as "active"
@@ -191,11 +189,8 @@
 		tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temp = crit_temp;
 	tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temp = crit_temp;
 	tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temp = emerg_temp;
-	if (emerg_temp > crit_temp)
-		tz->trips[MLXSW_THERMAL_TEMP_TRIP_CRIT].temp = emerg_temp +
+	tz->trips[MLXSW_THERMAL_TEMP_TRIP_CRIT].temp = emerg_temp +
 					MLXSW_THERMAL_MODULE_TEMP_SHIFT;
-	else
-		tz->trips[MLXSW_THERMAL_TEMP_TRIP_CRIT].temp = emerg_temp;
 
 	return 0;
 }
@@ -390,8 +385,7 @@
 static int mlxsw_thermal_trend_get(struct thermal_zone_device *tzdev,
 				   int trip, enum thermal_trend *trend)
 {
-	struct mlxsw_thermal_module *tz = tzdev->devdata;
-	struct mlxsw_thermal *thermal = tz->parent;
+	struct mlxsw_thermal *thermal = tzdev->devdata;
 
 	if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
 		return -EINVAL;
@@ -592,6 +586,22 @@
 	return 0;
 }
 
+static int mlxsw_thermal_module_trend_get(struct thermal_zone_device *tzdev,
+					  int trip, enum thermal_trend *trend)
+{
+	struct mlxsw_thermal_module *tz = tzdev->devdata;
+	struct mlxsw_thermal *thermal = tz->parent;
+
+	if (trip < 0 || trip >= MLXSW_THERMAL_NUM_TRIPS)
+		return -EINVAL;
+
+	if (tzdev == thermal->tz_highest_dev)
+		return 1;
+
+	*trend = THERMAL_TREND_STABLE;
+	return 0;
+}
+
 static struct thermal_zone_device_ops mlxsw_thermal_module_ops = {
 	.bind		= mlxsw_thermal_module_bind,
 	.unbind		= mlxsw_thermal_module_unbind,
@@ -603,7 +613,7 @@
 	.set_trip_temp	= mlxsw_thermal_module_trip_temp_set,
 	.get_trip_hyst	= mlxsw_thermal_module_trip_hyst_get,
 	.set_trip_hyst	= mlxsw_thermal_module_trip_hyst_set,
-	.get_trend	= mlxsw_thermal_trend_get,
+	.get_trend	= mlxsw_thermal_module_trend_get,
 };
 
 static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev,
@@ -642,7 +652,7 @@
 	.set_trip_temp	= mlxsw_thermal_module_trip_temp_set,
 	.get_trip_hyst	= mlxsw_thermal_module_trip_hyst_get,
 	.set_trip_hyst	= mlxsw_thermal_module_trip_hyst_set,
-	.get_trend	= mlxsw_thermal_trend_get,
+	.get_trend	= mlxsw_thermal_module_trend_get,
 };
 
 static int mlxsw_thermal_get_max_state(struct thermal_cooling_device *cdev,
@@ -685,49 +695,16 @@
 	struct mlxsw_thermal *thermal = cdev->devdata;
 	struct device *dev = thermal->bus_info->dev;
 	char mfsc_pl[MLXSW_REG_MFSC_LEN];
-	unsigned long cur_state, i;
 	int idx;
-	u8 duty;
 	int err;
 
+	if (state > MLXSW_THERMAL_MAX_STATE)
+		return -EINVAL;
+
 	idx = mlxsw_get_cooling_device_idx(thermal, cdev);
 	if (idx < 0)
 		return idx;
 
-	/* Verify if this request is for changing allowed fan dynamical
-	 * minimum. If it is - update cooling levels accordingly and update
-	 * state, if current state is below the newly requested minimum state.
-	 * For example, if current state is 5, and minimal state is to be
-	 * changed from 4 to 6, thermal->cooling_levels[0 to 5] will be changed
-	 * all from 4 to 6. And state 5 (thermal->cooling_levels[4]) should be
-	 * overwritten.
-	 */
-	if (state >= MLXSW_THERMAL_SPEED_MIN &&
-	    state <= MLXSW_THERMAL_SPEED_MAX) {
-		state -= MLXSW_THERMAL_MAX_STATE;
-		for (i = 0; i <= MLXSW_THERMAL_MAX_STATE; i++)
-			thermal->cooling_levels[i] = max(state, i);
-
-		mlxsw_reg_mfsc_pack(mfsc_pl, idx, 0);
-		err = mlxsw_reg_query(thermal->core, MLXSW_REG(mfsc), mfsc_pl);
-		if (err)
-			return err;
-
-		duty = mlxsw_reg_mfsc_pwm_duty_cycle_get(mfsc_pl);
-		cur_state = mlxsw_duty_to_state(duty);
-
-		/* If current fan state is lower than requested dynamical
-		 * minimum, increase fan speed up to dynamical minimum.
-		 */
-		if (state < cur_state)
-			return 0;
-
-		state = cur_state;
-	}
-
-	if (state > MLXSW_THERMAL_MAX_STATE)
-		return -EINVAL;
-
 	/* Normalize the state to the valid speed range. */
 	state = thermal->cooling_levels[state];
 	mlxsw_reg_mfsc_pack(mfsc_pl, idx, mlxsw_state_to_duty(state));
@@ -1022,8 +999,7 @@
 
 	/* Initialize cooling levels per PWM state. */
 	for (i = 0; i < MLXSW_THERMAL_MAX_STATE; i++)
-		thermal->cooling_levels[i] = max(MLXSW_THERMAL_SPEED_MIN_LEVEL,
-						 i);
+		thermal->cooling_levels[i] = max(MLXSW_THERMAL_MIN_STATE, i);
 
 	thermal->polling_delay = bus_info->low_frequency ?
 				 MLXSW_THERMAL_SLOW_POLL_INT :
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlxsw/i2c.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlxsw/i2c.c
@@ -47,6 +47,7 @@
 #define MLXSW_I2C_MBOX_SIZE_BITS	12
 #define MLXSW_I2C_ADDR_BUF_SIZE		4
 #define MLXSW_I2C_BLK_DEF		32
+#define MLXSW_I2C_BLK_MAX		100
 #define MLXSW_I2C_RETRY			5
 #define MLXSW_I2C_TIMEOUT_MSECS		5000
 #define MLXSW_I2C_MAX_DATA_SIZE		256
@@ -427,7 +428,7 @@
 	} else {
 		/* No input mailbox is case of initialization query command. */
 		reg_size = MLXSW_I2C_MAX_DATA_SIZE;
-		num = reg_size / mlxsw_i2c->block_size;
+		num = DIV_ROUND_UP(reg_size, mlxsw_i2c->block_size);
 
 		if (mutex_lock_interruptible(&mlxsw_i2c->cmd.lock) < 0) {
 			dev_err(&client->dev, "Could not acquire lock");
@@ -575,7 +576,7 @@
 			return -EOPNOTSUPP;
 		}
 
-		mlxsw_i2c->block_size = max_t(u16, MLXSW_I2C_BLK_DEF,
+		mlxsw_i2c->block_size = min_t(u16, MLXSW_I2C_BLK_MAX,
 					      min_t(u16, quirks->max_read_len,
 						    quirks->max_write_len));
 	} else {
@@ -649,6 +650,7 @@
 	return 0;
 
 errout:
+	mutex_destroy(&mlxsw_i2c->cmd.lock);
 	i2c_set_clientdata(client, NULL);
 
 	return err;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlxsw/minimal.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlxsw/minimal.c
@@ -204,8 +204,8 @@
 
 err_register_netdev:
 	mlxsw_m->ports[local_port] = NULL;
-	free_netdev(dev);
 err_dev_addr_get:
+	free_netdev(dev);
 err_alloc_etherdev:
 	mlxsw_core_port_fini(mlxsw_m->core, local_port);
 	return err;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlxsw/pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlxsw/pci.c
@@ -1318,36 +1318,64 @@
 			    mbox->mapaddr);
 }
 
-static int mlxsw_pci_sw_reset(struct mlxsw_pci *mlxsw_pci,
-			      const struct pci_device_id *id)
+static int mlxsw_pci_sys_ready_wait(struct mlxsw_pci *mlxsw_pci,
+				    const struct pci_device_id *id,
+				    u32 *p_sys_status)
 {
 	unsigned long end;
-	char mrsr_pl[MLXSW_REG_MRSR_LEN];
-	int err;
+	u32 val;
 
-	mlxsw_reg_mrsr_pack(mrsr_pl);
-	err = mlxsw_reg_write(mlxsw_pci->core, MLXSW_REG(mrsr), mrsr_pl);
-	if (err)
-		return err;
 	if (id->device == PCI_DEVICE_ID_MELLANOX_SWITCHX2) {
 		msleep(MLXSW_PCI_SW_RESET_TIMEOUT_MSECS);
 		return 0;
 	}
 
-	/* We must wait for the HW to become responsive once again. */
+	/* We must wait for the HW to become responsive. */
 	msleep(MLXSW_PCI_SW_RESET_WAIT_MSECS);
 
 	end = jiffies + msecs_to_jiffies(MLXSW_PCI_SW_RESET_TIMEOUT_MSECS);
 	do {
-		u32 val = mlxsw_pci_read32(mlxsw_pci, FW_READY);
-
+		val = mlxsw_pci_read32(mlxsw_pci, FW_READY);
 		if ((val & MLXSW_PCI_FW_READY_MASK) == MLXSW_PCI_FW_READY_MAGIC)
 			return 0;
 		cond_resched();
 	} while (time_before(jiffies, end));
+
+	*p_sys_status = val & MLXSW_PCI_FW_READY_MASK;
+
 	return -EBUSY;
 }
 
+static int mlxsw_pci_sw_reset(struct mlxsw_pci *mlxsw_pci,
+			      const struct pci_device_id *id)
+{
+	struct pci_dev *pdev = mlxsw_pci->pdev;
+	char mrsr_pl[MLXSW_REG_MRSR_LEN];
+	u32 sys_status;
+	int err;
+
+	err = mlxsw_pci_sys_ready_wait(mlxsw_pci, id, &sys_status);
+	if (err) {
+		dev_err(&pdev->dev, "Failed to reach system ready status before reset. Status is 0x%x\n",
+			sys_status);
+		return err;
+	}
+
+	mlxsw_reg_mrsr_pack(mrsr_pl);
+	err = mlxsw_reg_write(mlxsw_pci->core, MLXSW_REG(mrsr), mrsr_pl);
+	if (err)
+		return err;
+
+	err = mlxsw_pci_sys_ready_wait(mlxsw_pci, id, &sys_status);
+	if (err) {
+		dev_err(&pdev->dev, "Failed to reach system ready status after reset. Status is 0x%x\n",
+			sys_status);
+		return err;
+	}
+
+	return 0;
+}
+
 static int mlxsw_pci_alloc_irq_vectors(struct mlxsw_pci *mlxsw_pci)
 {
 	int err;
@@ -1373,23 +1401,12 @@
 	u16 num_pages;
 	int err;
 
-	mutex_init(&mlxsw_pci->cmd.lock);
-	init_waitqueue_head(&mlxsw_pci->cmd.wait);
-
 	mlxsw_pci->core = mlxsw_core;
 
 	mbox = mlxsw_cmd_mbox_alloc();
 	if (!mbox)
 		return -ENOMEM;
 
-	err = mlxsw_pci_mbox_alloc(mlxsw_pci, &mlxsw_pci->cmd.in_mbox);
-	if (err)
-		goto mbox_put;
-
-	err = mlxsw_pci_mbox_alloc(mlxsw_pci, &mlxsw_pci->cmd.out_mbox);
-	if (err)
-		goto err_out_mbox_alloc;
-
 	err = mlxsw_pci_sw_reset(mlxsw_pci, mlxsw_pci->id);
 	if (err)
 		goto err_sw_reset;
@@ -1496,9 +1513,6 @@
 	mlxsw_pci_free_irq_vectors(mlxsw_pci);
 err_alloc_irq:
 err_sw_reset:
-	mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.out_mbox);
-err_out_mbox_alloc:
-	mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.in_mbox);
 mbox_put:
 	mlxsw_cmd_mbox_free(mbox);
 	return err;
@@ -1512,8 +1526,6 @@
 	mlxsw_pci_aqs_fini(mlxsw_pci);
 	mlxsw_pci_fw_area_fini(mlxsw_pci);
 	mlxsw_pci_free_irq_vectors(mlxsw_pci);
-	mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.out_mbox);
-	mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.in_mbox);
 }
 
 static struct mlxsw_pci_queue *
@@ -1727,6 +1739,37 @@
 	.features		= MLXSW_BUS_F_TXRX | MLXSW_BUS_F_RESET,
 };
 
+static int mlxsw_pci_cmd_init(struct mlxsw_pci *mlxsw_pci)
+{
+	int err;
+
+	mutex_init(&mlxsw_pci->cmd.lock);
+	init_waitqueue_head(&mlxsw_pci->cmd.wait);
+
+	err = mlxsw_pci_mbox_alloc(mlxsw_pci, &mlxsw_pci->cmd.in_mbox);
+	if (err)
+		goto err_in_mbox_alloc;
+
+	err = mlxsw_pci_mbox_alloc(mlxsw_pci, &mlxsw_pci->cmd.out_mbox);
+	if (err)
+		goto err_out_mbox_alloc;
+
+	return 0;
+
+err_out_mbox_alloc:
+	mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.in_mbox);
+err_in_mbox_alloc:
+	mutex_destroy(&mlxsw_pci->cmd.lock);
+	return err;
+}
+
+static void mlxsw_pci_cmd_fini(struct mlxsw_pci *mlxsw_pci)
+{
+	mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.out_mbox);
+	mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.in_mbox);
+	mutex_destroy(&mlxsw_pci->cmd.lock);
+}
+
 static int mlxsw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	const char *driver_name = pdev->driver->name;
@@ -1782,6 +1825,10 @@
 	mlxsw_pci->pdev = pdev;
 	pci_set_drvdata(pdev, mlxsw_pci);
 
+	err = mlxsw_pci_cmd_init(mlxsw_pci);
+	if (err)
+		goto err_pci_cmd_init;
+
 	mlxsw_pci->bus_info.device_kind = driver_name;
 	mlxsw_pci->bus_info.device_name = pci_name(mlxsw_pci->pdev);
 	mlxsw_pci->bus_info.dev = &pdev->dev;
@@ -1799,6 +1846,8 @@
 	return 0;
 
 err_bus_device_register:
+	mlxsw_pci_cmd_fini(mlxsw_pci);
+err_pci_cmd_init:
 	iounmap(mlxsw_pci->hw_addr);
 err_ioremap:
 err_pci_resource_len_check:
@@ -1816,6 +1865,7 @@
 	struct mlxsw_pci *mlxsw_pci = pci_get_drvdata(pdev);
 
 	mlxsw_core_bus_device_unregister(mlxsw_pci->core, false);
+	mlxsw_pci_cmd_fini(mlxsw_pci);
 	iounmap(mlxsw_pci->hw_addr);
 	pci_release_regions(mlxsw_pci->pdev);
 	pci_disable_device(mlxsw_pci->pdev);
@@ -1826,6 +1876,7 @@
 {
 	pci_driver->probe = mlxsw_pci_probe;
 	pci_driver->remove = mlxsw_pci_remove;
+	pci_driver->shutdown = mlxsw_pci_remove;
 	return pci_register_driver(pci_driver);
 }
 EXPORT_SYMBOL(mlxsw_pci_driver_register);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlxsw/reg.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlxsw/reg.h
@@ -5421,6 +5421,7 @@
 	MLXSW_REG_HTGT_TRAP_GROUP_SP_LBERROR,
 	MLXSW_REG_HTGT_TRAP_GROUP_SP_PTP0,
 	MLXSW_REG_HTGT_TRAP_GROUP_SP_PTP1,
+	MLXSW_REG_HTGT_TRAP_GROUP_SP_VRRP,
 
 	__MLXSW_REG_HTGT_TRAP_GROUP_MAX,
 	MLXSW_REG_HTGT_TRAP_GROUP_MAX = __MLXSW_REG_HTGT_TRAP_GROUP_MAX - 1
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -812,23 +812,17 @@
 	u64 len;
 	int err;
 
+	if (skb_cow_head(skb, MLXSW_TXHDR_LEN)) {
+		this_cpu_inc(mlxsw_sp_port->pcpu_stats->tx_dropped);
+		dev_kfree_skb_any(skb);
+		return NETDEV_TX_OK;
+	}
+
 	memset(skb->cb, 0, sizeof(struct mlxsw_skb_cb));
 
 	if (mlxsw_core_skb_transmit_busy(mlxsw_sp->core, &tx_info))
 		return NETDEV_TX_BUSY;
 
-	if (unlikely(skb_headroom(skb) < MLXSW_TXHDR_LEN)) {
-		struct sk_buff *skb_orig = skb;
-
-		skb = skb_realloc_headroom(skb, MLXSW_TXHDR_LEN);
-		if (!skb) {
-			this_cpu_inc(mlxsw_sp_port->pcpu_stats->tx_dropped);
-			dev_kfree_skb_any(skb_orig);
-			return NETDEV_TX_OK;
-		}
-		dev_consume_skb_any(skb_orig);
-	}
-
 	if (eth_skb_pad(skb)) {
 		this_cpu_inc(mlxsw_sp_port->pcpu_stats->tx_dropped);
 		return NETDEV_TX_OK;
@@ -1167,6 +1161,9 @@
 			     periodic_hw_stats.update_dw.work);
 
 	if (!netif_carrier_ok(mlxsw_sp_port->dev))
+		/* Note: mlxsw_sp_port_down_wipe_counters() clears the cache as
+		 * necessary when port goes down.
+		 */
 		goto out;
 
 	mlxsw_sp_port_get_hw_stats(mlxsw_sp_port->dev,
@@ -3935,6 +3932,7 @@
 	mlxsw_sp_cpu_port_remove(mlxsw_sp);
 	kfree(mlxsw_sp->port_to_module);
 	kfree(mlxsw_sp->ports);
+	mlxsw_sp->ports = NULL;
 }
 
 static int mlxsw_sp_ports_create(struct mlxsw_sp *mlxsw_sp)
@@ -3989,6 +3987,7 @@
 	kfree(mlxsw_sp->port_to_module);
 err_port_to_module_alloc:
 	kfree(mlxsw_sp->ports);
+	mlxsw_sp->ports = NULL;
 	return err;
 }
 
@@ -4043,6 +4042,14 @@
 	}
 }
 
+static struct mlxsw_sp_port *
+mlxsw_sp_port_get_by_local_port(struct mlxsw_sp *mlxsw_sp, u8 local_port)
+{
+	if (mlxsw_sp->ports && mlxsw_sp->ports[local_port])
+		return mlxsw_sp->ports[local_port];
+	return NULL;
+}
+
 static int mlxsw_sp_port_split(struct mlxsw_core *mlxsw_core, u8 local_port,
 			       unsigned int count,
 			       struct netlink_ext_ack *extack)
@@ -4061,7 +4068,7 @@
 	local_ports_in_1x = MLXSW_CORE_RES_GET(mlxsw_core, LOCAL_PORTS_IN_1X);
 	local_ports_in_2x = MLXSW_CORE_RES_GET(mlxsw_core, LOCAL_PORTS_IN_2X);
 
-	mlxsw_sp_port = mlxsw_sp->ports[local_port];
+	mlxsw_sp_port = mlxsw_sp_port_get_by_local_port(mlxsw_sp, local_port);
 	if (!mlxsw_sp_port) {
 		dev_err(mlxsw_sp->bus_info->dev, "Port number \"%d\" does not exist\n",
 			local_port);
@@ -4139,7 +4146,7 @@
 	local_ports_in_1x = MLXSW_CORE_RES_GET(mlxsw_core, LOCAL_PORTS_IN_1X);
 	local_ports_in_2x = MLXSW_CORE_RES_GET(mlxsw_core, LOCAL_PORTS_IN_2X);
 
-	mlxsw_sp_port = mlxsw_sp->ports[local_port];
+	mlxsw_sp_port = mlxsw_sp_port_get_by_local_port(mlxsw_sp, local_port);
 	if (!mlxsw_sp_port) {
 		dev_err(mlxsw_sp->bus_info->dev, "Port number \"%d\" does not exist\n",
 			local_port);
@@ -4176,6 +4183,15 @@
 	return 0;
 }
 
+static void
+mlxsw_sp_port_down_wipe_counters(struct mlxsw_sp_port *mlxsw_sp_port)
+{
+	int i;
+
+	for (i = 0; i < TC_MAX_QUEUE; i++)
+		mlxsw_sp_port->periodic_hw_stats.xstats.backlog[i] = 0;
+}
+
 static void mlxsw_sp_pude_event_func(const struct mlxsw_reg_info *reg,
 				     char *pude_pl, void *priv)
 {
@@ -4197,6 +4213,7 @@
 	} else {
 		netdev_info(mlxsw_sp_port->dev, "link down\n");
 		netif_carrier_off(mlxsw_sp_port->dev);
+		mlxsw_sp_port_down_wipe_counters(mlxsw_sp_port);
 	}
 }
 
@@ -4398,8 +4415,8 @@
 	MLXSW_SP_RXL_MARK(ROUTER_ALERT_IPV6, TRAP_TO_CPU, ROUTER_EXP, false),
 	MLXSW_SP_RXL_MARK(IPIP_DECAP_ERROR, TRAP_TO_CPU, ROUTER_EXP, false),
 	MLXSW_SP_RXL_MARK(DECAP_ECN0, TRAP_TO_CPU, ROUTER_EXP, false),
-	MLXSW_SP_RXL_MARK(IPV4_VRRP, TRAP_TO_CPU, ROUTER_EXP, false),
-	MLXSW_SP_RXL_MARK(IPV6_VRRP, TRAP_TO_CPU, ROUTER_EXP, false),
+	MLXSW_SP_RXL_MARK(IPV4_VRRP, TRAP_TO_CPU, VRRP, false),
+	MLXSW_SP_RXL_MARK(IPV6_VRRP, TRAP_TO_CPU, VRRP, false),
 	/* PKT Sample trap */
 	MLXSW_RXL(mlxsw_sp_rx_listener_sample_func, PKT_SAMPLE, MIRROR_TO_CPU,
 		  false, SP_IP2ME, DISCARD),
@@ -4483,6 +4500,10 @@
 			rate = 19 * 1024;
 			burst_size = 12;
 			break;
+		case MLXSW_REG_HTGT_TRAP_GROUP_SP_VRRP:
+			rate = 360;
+			burst_size = 7;
+			break;
 		default:
 			continue;
 		}
@@ -4522,6 +4543,7 @@
 		case MLXSW_REG_HTGT_TRAP_GROUP_SP_OSPF:
 		case MLXSW_REG_HTGT_TRAP_GROUP_SP_PIM:
 		case MLXSW_REG_HTGT_TRAP_GROUP_SP_PTP0:
+		case MLXSW_REG_HTGT_TRAP_GROUP_SP_VRRP:
 			priority = 5;
 			tc = 5;
 			break;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlxsw/spectrum2_acl_tcam.c
@@ -88,8 +88,8 @@
 	 * to be written using PEFA register to all indexes for all regions.
 	 */
 	afa_block = mlxsw_afa_block_create(mlxsw_sp->afa);
-	if (!afa_block) {
-		err = -ENOMEM;
+	if (IS_ERR(afa_block)) {
+		err = PTR_ERR(afa_block);
 		goto err_afa_block;
 	}
 	err = mlxsw_afa_block_continue(afa_block);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
@@ -8,6 +8,7 @@
 #include <linux/string.h>
 #include <linux/rhashtable.h>
 #include <linux/netdevice.h>
+#include <linux/mutex.h>
 #include <net/net_namespace.h>
 #include <net/tc_act/tc_vlan.h>
 
@@ -25,6 +26,7 @@
 	struct mlxsw_sp_fid *dummy_fid;
 	struct rhashtable ruleset_ht;
 	struct list_head rules;
+	struct mutex rules_lock; /* Protects rules list */
 	struct {
 		struct delayed_work dw;
 		unsigned long interval;	/* ms */
@@ -442,7 +444,7 @@
 
 	rulei = kzalloc(sizeof(*rulei), GFP_KERNEL);
 	if (!rulei)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 
 	if (afa_block) {
 		rulei->act_block = afa_block;
@@ -701,7 +703,9 @@
 			goto err_ruleset_block_bind;
 	}
 
+	mutex_lock(&mlxsw_sp->acl->rules_lock);
 	list_add_tail(&rule->list, &mlxsw_sp->acl->rules);
+	mutex_unlock(&mlxsw_sp->acl->rules_lock);
 	block->rule_count++;
 	block->egress_blocker_rule_count += rule->rulei->egress_bind_blocker;
 	return 0;
@@ -723,7 +727,9 @@
 
 	block->egress_blocker_rule_count -= rule->rulei->egress_bind_blocker;
 	ruleset->ht_key.block->rule_count--;
+	mutex_lock(&mlxsw_sp->acl->rules_lock);
 	list_del(&rule->list);
+	mutex_unlock(&mlxsw_sp->acl->rules_lock);
 	if (!ruleset->ht_key.chain_index &&
 	    mlxsw_sp_acl_ruleset_is_singular(ruleset))
 		mlxsw_sp_acl_ruleset_block_unbind(mlxsw_sp, ruleset,
@@ -783,19 +789,18 @@
 	struct mlxsw_sp_acl_rule *rule;
 	int err;
 
-	/* Protect internal structures from changes */
-	rtnl_lock();
+	mutex_lock(&acl->rules_lock);
 	list_for_each_entry(rule, &acl->rules, list) {
 		err = mlxsw_sp_acl_rule_activity_update(acl->mlxsw_sp,
 							rule);
 		if (err)
 			goto err_rule_update;
 	}
-	rtnl_unlock();
+	mutex_unlock(&acl->rules_lock);
 	return 0;
 
 err_rule_update:
-	rtnl_unlock();
+	mutex_unlock(&acl->rules_lock);
 	return err;
 }
 
@@ -880,6 +885,7 @@
 	acl->dummy_fid = fid;
 
 	INIT_LIST_HEAD(&acl->rules);
+	mutex_init(&acl->rules_lock);
 	err = mlxsw_sp_acl_tcam_init(mlxsw_sp, &acl->tcam);
 	if (err)
 		goto err_acl_ops_init;
@@ -892,6 +898,7 @@
 	return 0;
 
 err_acl_ops_init:
+	mutex_destroy(&acl->rules_lock);
 	mlxsw_sp_fid_put(fid);
 err_fid_get:
 	rhashtable_destroy(&acl->ruleset_ht);
@@ -908,6 +915,7 @@
 
 	cancel_delayed_work_sync(&mlxsw_sp->acl->rule_activity_update.dw);
 	mlxsw_sp_acl_tcam_fini(mlxsw_sp, &acl->tcam);
+	mutex_destroy(&acl->rules_lock);
 	WARN_ON(!list_empty(&acl->rules));
 	mlxsw_sp_fid_put(acl->dummy_fid);
 	rhashtable_destroy(&acl->ruleset_ht);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c
@@ -301,6 +301,7 @@
 			     unsigned long *p_index)
 {
 	unsigned int num_rows, entry_size;
+	unsigned long index;
 
 	/* We only allow allocations of entire rows */
 	if (num_erps % erp_core->num_erp_banks != 0)
@@ -309,10 +310,11 @@
 	entry_size = erp_core->erpt_entries_size[region_type];
 	num_rows = num_erps / erp_core->num_erp_banks;
 
-	*p_index = gen_pool_alloc(erp_core->erp_tables, num_rows * entry_size);
-	if (*p_index == 0)
+	index = gen_pool_alloc(erp_core->erp_tables, num_rows * entry_size);
+	if (!index)
 		return -ENOBUFS;
-	*p_index -= MLXSW_SP_ACL_ERP_GENALLOC_OFFSET;
+
+	*p_index = index - MLXSW_SP_ACL_ERP_GENALLOC_OFFSET;
 
 	return 0;
 }
@@ -1215,18 +1217,6 @@
 	return err ? false : true;
 }
 
-static int mlxsw_sp_acl_erp_hints_obj_cmp(const void *obj1, const void *obj2)
-{
-	const struct mlxsw_sp_acl_erp_key *key1 = obj1;
-	const struct mlxsw_sp_acl_erp_key *key2 = obj2;
-
-	/* For hints purposes, two objects are considered equal
-	 * in case the masks are the same. Does not matter what
-	 * the "ctcam" value is.
-	 */
-	return memcmp(key1->mask, key2->mask, sizeof(key1->mask));
-}
-
 static void *mlxsw_sp_acl_erp_delta_create(void *priv, void *parent_obj,
 					   void *obj)
 {
@@ -1306,7 +1296,6 @@
 static const struct objagg_ops mlxsw_sp_acl_erp_objagg_ops = {
 	.obj_size = sizeof(struct mlxsw_sp_acl_erp_key),
 	.delta_check = mlxsw_sp_acl_erp_delta_check,
-	.hints_obj_cmp = mlxsw_sp_acl_erp_hints_obj_cmp,
 	.delta_create = mlxsw_sp_acl_erp_delta_create,
 	.delta_destroy = mlxsw_sp_acl_erp_delta_destroy,
 	.root_create = mlxsw_sp_acl_erp_root_create,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
@@ -68,6 +68,8 @@
 	tcam->max_groups = max_groups;
 	tcam->max_group_size = MLXSW_CORE_RES_GET(mlxsw_sp->core,
 						 ACL_MAX_GROUP_SIZE);
+	tcam->max_group_size = min_t(unsigned int, tcam->max_group_size,
+				     MLXSW_REG_PAGT_ACL_MAX_NUM);
 
 	err = ops->init(mlxsw_sp, tcam->priv, tcam);
 	if (err)
@@ -290,13 +292,14 @@
 	int err;
 
 	group->tcam = tcam;
-	mutex_init(&group->lock);
 	INIT_LIST_HEAD(&group->region_list);
 
 	err = mlxsw_sp_acl_tcam_group_id_get(tcam, &group->id);
 	if (err)
 		return err;
 
+	mutex_init(&group->lock);
+
 	return 0;
 }
 
@@ -755,7 +758,9 @@
 			     rehash.dw.work);
 	int credits = MLXSW_SP_ACL_TCAM_VREGION_REHASH_CREDITS;
 
+	mutex_lock(&vregion->lock);
 	mlxsw_sp_acl_tcam_vregion_rehash(vregion->mlxsw_sp, vregion, &credits);
+	mutex_unlock(&vregion->lock);
 	if (credits < 0)
 		/* Rehash gone out of credits so it was interrupted.
 		 * Schedule the work as soon as possible to continue.
@@ -766,6 +771,17 @@
 }
 
 static void
+mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset(struct mlxsw_sp_acl_tcam_rehash_ctx *ctx)
+{
+	/* The entry markers are relative to the current chunk and therefore
+	 * needs to be reset together with the chunk marker.
+	 */
+	ctx->current_vchunk = NULL;
+	ctx->start_ventry = NULL;
+	ctx->stop_ventry = NULL;
+}
+
+static void
 mlxsw_sp_acl_tcam_rehash_ctx_vchunk_changed(struct mlxsw_sp_acl_tcam_vchunk *vchunk)
 {
 	struct mlxsw_sp_acl_tcam_vregion *vregion = vchunk->vregion;
@@ -787,7 +803,7 @@
 	 * the current chunk pointer to make sure all chunks
 	 * are properly migrated.
 	 */
-	vregion->rehash.ctx.current_vchunk = NULL;
+	mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset(&vregion->rehash.ctx);
 }
 
 static struct mlxsw_sp_acl_tcam_vregion *
@@ -860,10 +876,14 @@
 	struct mlxsw_sp_acl_tcam *tcam = vregion->tcam;
 
 	if (vgroup->vregion_rehash_enabled && ops->region_rehash_hints_get) {
+		struct mlxsw_sp_acl_tcam_rehash_ctx *ctx = &vregion->rehash.ctx;
+
 		mutex_lock(&tcam->lock);
 		list_del(&vregion->tlist);
 		mutex_unlock(&tcam->lock);
-		cancel_delayed_work_sync(&vregion->rehash.dw);
+		if (cancel_delayed_work_sync(&vregion->rehash.dw) &&
+		    ctx->hints_priv)
+			ops->region_rehash_hints_put(ctx->hints_priv);
 	}
 	mlxsw_sp_acl_tcam_vgroup_vregion_detach(mlxsw_sp, vregion);
 	if (vregion->region2)
@@ -986,8 +1006,9 @@
 				unsigned int priority,
 				struct mlxsw_afk_element_usage *elusage)
 {
+	struct mlxsw_sp_acl_tcam_vchunk *vchunk, *vchunk2;
 	struct mlxsw_sp_acl_tcam_vregion *vregion;
-	struct mlxsw_sp_acl_tcam_vchunk *vchunk;
+	struct list_head *pos;
 	int err;
 
 	if (priority == MLXSW_SP_ACL_TCAM_CATCHALL_PRIO)
@@ -1025,7 +1046,14 @@
 	}
 
 	mlxsw_sp_acl_tcam_rehash_ctx_vregion_changed(vregion);
-	list_add_tail(&vchunk->list, &vregion->vchunk_list);
+
+	/* Position the vchunk inside the list according to priority */
+	list_for_each(pos, &vregion->vchunk_list) {
+		vchunk2 = list_entry(pos, typeof(*vchunk2), list);
+		if (vchunk2->priority > priority)
+			break;
+	}
+	list_add_tail(&vchunk->list, pos);
 	mutex_unlock(&vregion->lock);
 
 	return vchunk;
@@ -1219,8 +1247,14 @@
 				      struct mlxsw_sp_acl_tcam_ventry *ventry,
 				      bool *activity)
 {
-	return mlxsw_sp_acl_tcam_entry_activity_get(mlxsw_sp,
-						    ventry->entry, activity);
+	struct mlxsw_sp_acl_tcam_vregion *vregion = ventry->vchunk->vregion;
+	int err;
+
+	mutex_lock(&vregion->lock);
+	err = mlxsw_sp_acl_tcam_entry_activity_get(mlxsw_sp, ventry->entry,
+						   activity);
+	mutex_unlock(&vregion->lock);
+	return err;
 }
 
 static int
@@ -1254,6 +1288,8 @@
 {
 	struct mlxsw_sp_acl_tcam_chunk *new_chunk;
 
+	WARN_ON(vchunk->chunk2);
+
 	new_chunk = mlxsw_sp_acl_tcam_chunk_create(mlxsw_sp, vchunk, region);
 	if (IS_ERR(new_chunk))
 		return PTR_ERR(new_chunk);
@@ -1272,7 +1308,7 @@
 {
 	mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk2);
 	vchunk->chunk2 = NULL;
-	ctx->current_vchunk = NULL;
+	mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset(ctx);
 }
 
 static int
@@ -1295,6 +1331,9 @@
 		return 0;
 	}
 
+	if (list_empty(&vchunk->ventry_list))
+		goto out;
+
 	/* If the migration got interrupted, we have the ventry to start from
 	 * stored in context.
 	 */
@@ -1304,6 +1343,8 @@
 		ventry = list_first_entry(&vchunk->ventry_list,
 					  typeof(*ventry), list);
 
+	WARN_ON(ventry->vchunk != vchunk);
+
 	list_for_each_entry_from(ventry, &vchunk->ventry_list, list) {
 		/* During rollback, once we reach the ventry that failed
 		 * to migrate, we are done.
@@ -1344,6 +1385,7 @@
 		}
 	}
 
+out:
 	mlxsw_sp_acl_tcam_vchunk_migrate_end(mlxsw_sp, vchunk, ctx);
 	return 0;
 }
@@ -1357,6 +1399,9 @@
 	struct mlxsw_sp_acl_tcam_vchunk *vchunk;
 	int err;
 
+	if (list_empty(&vregion->vchunk_list))
+		return 0;
+
 	/* If the migration got interrupted, we have the vchunk
 	 * we are working on stored in context.
 	 */
@@ -1385,16 +1430,17 @@
 	int err, err2;
 
 	trace_mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion);
-	mutex_lock(&vregion->lock);
 	err = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion,
 						   ctx, credits);
 	if (err) {
+		if (ctx->this_is_rollback)
+			return err;
 		/* In case migration was not successful, we need to swap
 		 * so the original region pointer is assigned again
 		 * to vregion->region.
 		 */
 		swap(vregion->region, vregion->region2);
-		ctx->current_vchunk = NULL;
+		mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset(ctx);
 		ctx->this_is_rollback = true;
 		err2 = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion,
 							    ctx, credits);
@@ -1405,7 +1451,6 @@
 			/* Let the rollback to be continued later on. */
 		}
 	}
-	mutex_unlock(&vregion->lock);
 	trace_mlxsw_sp_acl_tcam_vregion_migrate_end(mlxsw_sp, vregion);
 	return err;
 }
@@ -1454,6 +1499,7 @@
 
 	ctx->hints_priv = hints_priv;
 	ctx->this_is_rollback = false;
+	mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset(ctx);
 
 	return 0;
 
@@ -1506,7 +1552,8 @@
 	err = mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion,
 						ctx, credits);
 	if (err) {
-		dev_err(mlxsw_sp->bus_info->dev, "Failed to migrate vregion\n");
+		dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to migrate vregion\n");
+		return;
 	}
 
 	if (*credits >= 0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlxsw/spectrum_cnt.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlxsw/spectrum_cnt.h
@@ -7,8 +7,8 @@
 #include "spectrum.h"
 
 enum mlxsw_sp_counter_sub_pool_id {
-	MLXSW_SP_COUNTER_SUB_POOL_FLOW,
 	MLXSW_SP_COUNTER_SUB_POOL_RIF,
+	MLXSW_SP_COUNTER_SUB_POOL_FLOW,
 };
 
 int mlxsw_sp_counter_alloc(struct mlxsw_sp *mlxsw_sp,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlxsw/spectrum_dcb.c
@@ -227,8 +227,6 @@
 static int mlxsw_sp_dcbnl_app_validate(struct net_device *dev,
 				       struct dcb_app *app)
 {
-	int prio;
-
 	if (app->priority >= IEEE_8021QAZ_MAX_TCS) {
 		netdev_err(dev, "APP entry with priority value %u is invalid\n",
 			   app->priority);
@@ -242,17 +240,6 @@
 				   app->protocol);
 			return -EINVAL;
 		}
-
-		/* Warn about any DSCP APP entries with the same PID. */
-		prio = fls(dcb_ieee_getapp_mask(dev, app));
-		if (prio--) {
-			if (prio < app->priority)
-				netdev_warn(dev, "Choosing priority %d for DSCP %d in favor of previously-active value of %d\n",
-					    app->priority, app->protocol, prio);
-			else if (prio > app->priority)
-				netdev_warn(dev, "Ignoring new priority %d for DSCP %d in favor of current value of %d\n",
-					    app->priority, app->protocol, prio);
-		}
 		break;
 
 	case IEEE_8021QAZ_APP_SEL_ETHERTYPE:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
@@ -215,7 +215,7 @@
 start_again:
 	err = devlink_dpipe_entry_ctx_prepare(dump_ctx);
 	if (err)
-		return err;
+		goto err_ctx_prepare;
 	j = 0;
 	for (; i < rif_count; i++) {
 		struct mlxsw_sp_rif *rif = mlxsw_sp_rif_by_index(mlxsw_sp, i);
@@ -247,6 +247,7 @@
 	return 0;
 err_entry_append:
 err_entry_get:
+err_ctx_prepare:
 	rtnl_unlock();
 	devlink_dpipe_entry_clear(&entry);
 	return err;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c
@@ -123,9 +123,12 @@
 			u8 prio = act->vlan.prio;
 			u16 vid = act->vlan.vid;
 
-			return mlxsw_sp_acl_rulei_act_vlan(mlxsw_sp, rulei,
-							   act->id, vid,
-							   proto, prio, extack);
+			err = mlxsw_sp_acl_rulei_act_vlan(mlxsw_sp, rulei,
+							  act->id, vid,
+							  proto, prio, extack);
+			if (err)
+				return err;
+			break;
 			}
 		default:
 			NL_SET_ERR_MSG_MOD(extack, "Unsupported action");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c
@@ -524,6 +524,16 @@
 	u16 erif_index = 0;
 	int err;
 
+	/* Add the eRIF */
+	if (mlxsw_sp_mr_vif_valid(rve->mr_vif)) {
+		erif_index = mlxsw_sp_rif_index(rve->mr_vif->rif);
+		err = mr->mr_ops->route_erif_add(mlxsw_sp,
+						 rve->mr_route->route_priv,
+						 erif_index);
+		if (err)
+			return err;
+	}
+
 	/* Update the route action, as the new eVIF can be a tunnel or a pimreg
 	 * device which will require updating the action.
 	 */
@@ -533,17 +543,7 @@
 						      rve->mr_route->route_priv,
 						      route_action);
 		if (err)
-			return err;
-	}
-
-	/* Add the eRIF */
-	if (mlxsw_sp_mr_vif_valid(rve->mr_vif)) {
-		erif_index = mlxsw_sp_rif_index(rve->mr_vif->rif);
-		err = mr->mr_ops->route_erif_add(mlxsw_sp,
-						 rve->mr_route->route_priv,
-						 erif_index);
-		if (err)
-			goto err_route_erif_add;
+			goto err_route_action_update;
 	}
 
 	/* Update the minimum MTU */
@@ -561,14 +561,14 @@
 	return 0;
 
 err_route_min_mtu_update:
-	if (mlxsw_sp_mr_vif_valid(rve->mr_vif))
-		mr->mr_ops->route_erif_del(mlxsw_sp, rve->mr_route->route_priv,
-					   erif_index);
-err_route_erif_add:
 	if (route_action != rve->mr_route->route_action)
 		mr->mr_ops->route_action_update(mlxsw_sp,
 						rve->mr_route->route_priv,
 						rve->mr_route->route_action);
+err_route_action_update:
+	if (mlxsw_sp_mr_vif_valid(rve->mr_vif))
+		mr->mr_ops->route_erif_del(mlxsw_sp, rve->mr_route->route_priv,
+					   erif_index);
 	return err;
 }
 
@@ -637,12 +637,12 @@
 	return 0;
 
 err_erif_unresolve:
-	list_for_each_entry_from_reverse(erve, &mr_vif->route_evif_list,
-					 vif_node)
+	list_for_each_entry_continue_reverse(erve, &mr_vif->route_evif_list,
+					     vif_node)
 		mlxsw_sp_mr_route_evif_unresolve(mr_table, erve);
 err_irif_unresolve:
-	list_for_each_entry_from_reverse(irve, &mr_vif->route_ivif_list,
-					 vif_node)
+	list_for_each_entry_continue_reverse(irve, &mr_vif->route_ivif_list,
+					     vif_node)
 		mlxsw_sp_mr_route_ivif_unresolve(mr_table, irve);
 	mr_vif->rif = NULL;
 	return err;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr_tcam.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr_tcam.c
@@ -199,8 +199,8 @@
 	int err;
 
 	afa_block = mlxsw_afa_block_create(mlxsw_sp->afa);
-	if (!afa_block)
-		return ERR_PTR(-ENOMEM);
+	if (IS_ERR(afa_block))
+		return afa_block;
 
 	err = mlxsw_afa_block_append_allocated_counter(afa_block,
 						       counter_index);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c
@@ -294,8 +294,8 @@
 	.fdb_clear_offload = mlxsw_sp_nve_vxlan_clear_offload,
 };
 
-static bool mlxsw_sp2_nve_vxlan_learning_set(struct mlxsw_sp *mlxsw_sp,
-					     bool learning_en)
+static int mlxsw_sp2_nve_vxlan_learning_set(struct mlxsw_sp *mlxsw_sp,
+					    bool learning_en)
 {
 	char tnpc_pl[MLXSW_REG_TNPC_LEN];
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlxsw/spectrum_qdisc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlxsw/spectrum_qdisc.c
@@ -195,6 +195,20 @@
 	return -EOPNOTSUPP;
 }
 
+static u64
+mlxsw_sp_xstats_backlog(struct mlxsw_sp_port_xstats *xstats, int tclass_num)
+{
+	return xstats->backlog[tclass_num] +
+	       xstats->backlog[tclass_num + 8];
+}
+
+static u64
+mlxsw_sp_xstats_tail_drop(struct mlxsw_sp_port_xstats *xstats, int tclass_num)
+{
+	return xstats->tail_drop[tclass_num] +
+	       xstats->tail_drop[tclass_num + 8];
+}
+
 static void
 mlxsw_sp_qdisc_bstats_per_priority_get(struct mlxsw_sp_port_xstats *xstats,
 				       u8 prio_bitmap, u64 *tx_packets,
@@ -269,7 +283,7 @@
 					       &stats_base->tx_bytes);
 	red_base->prob_mark = xstats->ecn;
 	red_base->prob_drop = xstats->wred_drop[tclass_num];
-	red_base->pdrop = xstats->tail_drop[tclass_num];
+	red_base->pdrop = mlxsw_sp_xstats_tail_drop(xstats, tclass_num);
 
 	stats_base->overlimits = red_base->prob_drop + red_base->prob_mark;
 	stats_base->drops = red_base->prob_drop + red_base->pdrop;
@@ -369,7 +383,8 @@
 
 	early_drops = xstats->wred_drop[tclass_num] - xstats_base->prob_drop;
 	marks = xstats->ecn - xstats_base->prob_mark;
-	pdrops = xstats->tail_drop[tclass_num] - xstats_base->pdrop;
+	pdrops = mlxsw_sp_xstats_tail_drop(xstats, tclass_num) -
+		 xstats_base->pdrop;
 
 	res->pdrop += pdrops;
 	res->prob_drop += early_drops;
@@ -402,9 +417,10 @@
 
 	overlimits = xstats->wred_drop[tclass_num] + xstats->ecn -
 		     stats_base->overlimits;
-	drops = xstats->wred_drop[tclass_num] + xstats->tail_drop[tclass_num] -
+	drops = xstats->wred_drop[tclass_num] +
+		mlxsw_sp_xstats_tail_drop(xstats, tclass_num) -
 		stats_base->drops;
-	backlog = xstats->backlog[tclass_num];
+	backlog = mlxsw_sp_xstats_backlog(xstats, tclass_num);
 
 	_bstats_update(stats_ptr->bstats, tx_bytes, tx_packets);
 	stats_ptr->qstats->overlimits += overlimits;
@@ -575,9 +591,9 @@
 	tx_packets = stats->tx_packets - stats_base->tx_packets;
 
 	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
-		drops += xstats->tail_drop[i];
+		drops += mlxsw_sp_xstats_tail_drop(xstats, i);
 		drops += xstats->wred_drop[i];
-		backlog += xstats->backlog[i];
+		backlog += mlxsw_sp_xstats_backlog(xstats, i);
 	}
 	drops = drops - stats_base->drops;
 
@@ -613,7 +629,7 @@
 
 	stats_base->drops = 0;
 	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
-		stats_base->drops += xstats->tail_drop[i];
+		stats_base->drops += mlxsw_sp_xstats_tail_drop(xstats, i);
 		stats_base->drops += xstats->wred_drop[i];
 	}
 
@@ -650,6 +666,13 @@
 	    mlxsw_sp_port->tclass_qdiscs[tclass_num].handle == p->child_handle)
 		return 0;
 
+	if (!p->child_handle) {
+		/* This is an invisible FIFO replacing the original Qdisc.
+		 * Ignore it--the original Qdisc's destroy will follow.
+		 */
+		return 0;
+	}
+
 	/* See if the grafted qdisc is already offloaded on any tclass. If so,
 	 * unoffload it.
 	 */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -3871,7 +3871,7 @@
 {
 	const struct fib_nh *nh = fib_info_nh(fi, 0);
 
-	return nh->fib_nh_scope == RT_SCOPE_LINK ||
+	return nh->fib_nh_gw_family ||
 	       mlxsw_sp_nexthop4_ipip_type(mlxsw_sp, nh, NULL);
 }
 
@@ -5637,8 +5637,13 @@
 	if (mlxsw_sp_fib6_rt_should_ignore(rt))
 		return;
 
+	/* Multipath routes are first added to the FIB trie and only then
+	 * notified. If we vetoed the addition, we will get a delete
+	 * notification for a route we do not have. Therefore, do not warn if
+	 * route was not found.
+	 */
 	fib6_entry = mlxsw_sp_fib6_entry_lookup(mlxsw_sp, rt);
-	if (WARN_ON(!fib6_entry))
+	if (!fib6_entry)
 		return;
 
 	/* If not all the nexthops are deleted, then only reduce the nexthop
@@ -6282,7 +6287,7 @@
 	}
 
 	fib_work = kzalloc(sizeof(*fib_work), GFP_ATOMIC);
-	if (WARN_ON(!fib_work))
+	if (!fib_work)
 		return NOTIFY_BAD;
 
 	fib_work->mlxsw_sp = router->mlxsw_sp;
@@ -6980,6 +6985,9 @@
 
 	for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++) {
 		rif = mlxsw_sp->router->rifs[i];
+		if (rif && rif->ops &&
+		    rif->ops->type == MLXSW_SP_RIF_TYPE_IPIP_LB)
+			continue;
 		if (rif && rif->dev && rif->dev != dev &&
 		    !ether_addr_equal_masked(rif->dev->dev_addr, dev_addr,
 					     mlxsw_sp->mac_mask)) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mellanox/mlxsw/switchx2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mellanox/mlxsw/switchx2.c
@@ -299,22 +299,17 @@
 	u64 len;
 	int err;
 
+	if (skb_cow_head(skb, MLXSW_TXHDR_LEN)) {
+		this_cpu_inc(mlxsw_sx_port->pcpu_stats->tx_dropped);
+		dev_kfree_skb_any(skb);
+		return NETDEV_TX_OK;
+	}
+
 	memset(skb->cb, 0, sizeof(struct mlxsw_skb_cb));
 
 	if (mlxsw_core_skb_transmit_busy(mlxsw_sx->core, &tx_info))
 		return NETDEV_TX_BUSY;
 
-	if (unlikely(skb_headroom(skb) < MLXSW_TXHDR_LEN)) {
-		struct sk_buff *skb_orig = skb;
-
-		skb = skb_realloc_headroom(skb, MLXSW_TXHDR_LEN);
-		if (!skb) {
-			this_cpu_inc(mlxsw_sx_port->pcpu_stats->tx_dropped);
-			dev_kfree_skb_any(skb_orig);
-			return NETDEV_TX_OK;
-		}
-		dev_consume_skb_any(skb_orig);
-	}
 	mlxsw_sx_txhdr_construct(skb, &tx_info);
 	/* TX header is consumed by HW on the way so we shouldn't count its
 	 * bytes as being sent.
@@ -1263,6 +1258,7 @@
 		if (mlxsw_sx_port_created(mlxsw_sx, i))
 			mlxsw_sx_port_remove(mlxsw_sx, i);
 	kfree(mlxsw_sx->ports);
+	mlxsw_sx->ports = NULL;
 }
 
 static int mlxsw_sx_ports_create(struct mlxsw_sx *mlxsw_sx)
@@ -1297,6 +1293,7 @@
 		if (mlxsw_sx_port_created(mlxsw_sx, i))
 			mlxsw_sx_port_remove(mlxsw_sx, i);
 	kfree(mlxsw_sx->ports);
+	mlxsw_sx->ports = NULL;
 	return err;
 }
 
@@ -1380,6 +1377,12 @@
 	u8 module, width;
 	int err;
 
+	if (!mlxsw_sx->ports || !mlxsw_sx->ports[local_port]) {
+		dev_err(mlxsw_sx->bus_info->dev, "Port number \"%d\" does not exist\n",
+			local_port);
+		return -EINVAL;
+	}
+
 	if (new_type == DEVLINK_PORT_TYPE_AUTO)
 		return -EOPNOTSUPP;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/micrel/ks8842.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/micrel/ks8842.c
@@ -1136,6 +1136,10 @@
 	unsigned i;
 
 	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!iomem) {
+		dev_err(&pdev->dev, "Invalid resource\n");
+		return -EINVAL;
+	}
 	if (!request_mem_region(iomem->start, resource_size(iomem), DRV_NAME))
 		goto err_mem_region;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/micrel/ks8851_mll.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/micrel/ks8851_mll.c
@@ -157,21 +157,47 @@
  */
 
 /**
- * ks_rdreg8 - read 8 bit register from device
+ * ks_check_endian - Check whether endianness of the bus is correct
  * @ks	  : The chip information
- * @offset: The register address
  *
- * Read a 8bit register from the chip, returning the result
+ * The KS8851-16MLL EESK pin allows selecting the endianness of the 16bit
+ * bus. To maintain optimum performance, the bus endianness should be set
+ * such that it matches the endianness of the CPU.
  */
-static u8 ks_rdreg8(struct ks_net *ks, int offset)
+
+static int ks_check_endian(struct ks_net *ks)
 {
-	u16 data;
-	u8 shift_bit = offset & 0x03;
-	u8 shift_data = (offset & 1) << 3;
-	ks->cmd_reg_cache = (u16) offset | (u16)(BE0 << shift_bit);
-	iowrite16(ks->cmd_reg_cache, ks->hw_addr_cmd);
-	data  = ioread16(ks->hw_addr);
-	return (u8)(data >> shift_data);
+	u16 cider;
+
+	/*
+	 * Read CIDER register first, however read it the "wrong" way around.
+	 * If the endian strap on the KS8851-16MLL in incorrect and the chip
+	 * is operating in different endianness than the CPU, then the meaning
+	 * of BE[3:0] byte-enable bits is also swapped such that:
+	 *    BE[3,2,1,0] becomes BE[1,0,3,2]
+	 *
+	 * Luckily for us, the byte-enable bits are the top four MSbits of
+	 * the address register and the CIDER register is at offset 0xc0.
+	 * Hence, by reading address 0xc0c0, which is not impacted by endian
+	 * swapping, we assert either BE[3:2] or BE[1:0] while reading the
+	 * CIDER register.
+	 *
+	 * If the bus configuration is correct, reading 0xc0c0 asserts
+	 * BE[3:2] and this read returns 0x0000, because to read register
+	 * with bottom two LSbits of address set to 0, BE[1:0] must be
+	 * asserted.
+	 *
+	 * If the bus configuration is NOT correct, reading 0xc0c0 asserts
+	 * BE[1:0] and this read returns non-zero 0x8872 value.
+	 */
+	iowrite16(BE3 | BE2 | KS_CIDER, ks->hw_addr_cmd);
+	cider = ioread16(ks->hw_addr);
+	if (!cider)
+		return 0;
+
+	netdev_err(ks->netdev, "incorrect EESK endian strap setting\n");
+
+	return -EINVAL;
 }
 
 /**
@@ -190,22 +216,6 @@
 }
 
 /**
- * ks_wrreg8 - write 8bit register value to chip
- * @ks: The chip information
- * @offset: The register address
- * @value: The value to write
- *
- */
-static void ks_wrreg8(struct ks_net *ks, int offset, u8 value)
-{
-	u8  shift_bit = (offset & 0x03);
-	u16 value_write = (u16)(value << ((offset & 1) << 3));
-	ks->cmd_reg_cache = (u16)offset | (BE0 << shift_bit);
-	iowrite16(ks->cmd_reg_cache, ks->hw_addr_cmd);
-	iowrite16(value_write, ks->hw_addr);
-}
-
-/**
  * ks_wrreg16 - write 16bit register value to chip
  * @ks: The chip information
  * @offset: The register address
@@ -324,8 +334,7 @@
 	u16 reg_data = 0;
 
 	/* Regardless of bus width, 8 bit read should always work.*/
-	reg_data = ks_rdreg8(ks, KS_CCR) & 0x00FF;
-	reg_data |= ks_rdreg8(ks, KS_CCR+1) << 8;
+	reg_data = ks_rdreg16(ks, KS_CCR);
 
 	/* addr/data bus are multiplexed */
 	ks->sharedbus = (reg_data & CCR_SHARED) == CCR_SHARED;
@@ -429,7 +438,7 @@
 
 	/* 1. set sudo DMA mode */
 	ks_wrreg16(ks, KS_RXFDPR, RXFDPR_RXFPAI);
-	ks_wrreg8(ks, KS_RXQCR, (ks->rc_rxqcr | RXQCR_SDA) & 0xff);
+	ks_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr | RXQCR_SDA);
 
 	/* 2. read prepend data */
 	/**
@@ -446,7 +455,7 @@
 	ks_inblk(ks, buf, ALIGN(len, 4));
 
 	/* 4. reset sudo DMA Mode */
-	ks_wrreg8(ks, KS_RXQCR, ks->rc_rxqcr);
+	ks_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr);
 }
 
 /**
@@ -548,14 +557,17 @@
 {
 	struct net_device *netdev = pw;
 	struct ks_net *ks = netdev_priv(netdev);
+	unsigned long flags;
 	u16 status;
 
+	spin_lock_irqsave(&ks->statelock, flags);
 	/*this should be the first in IRQ handler */
 	ks_save_cmd_reg(ks);
 
 	status = ks_rdreg16(ks, KS_ISR);
 	if (unlikely(!status)) {
 		ks_restore_cmd_reg(ks);
+		spin_unlock_irqrestore(&ks->statelock, flags);
 		return IRQ_NONE;
 	}
 
@@ -581,6 +593,7 @@
 		ks->netdev->stats.rx_over_errors++;
 	/* this should be the last in IRQ handler*/
 	ks_restore_cmd_reg(ks);
+	spin_unlock_irqrestore(&ks->statelock, flags);
 	return IRQ_HANDLED;
 }
 
@@ -650,6 +663,7 @@
 
 	/* shutdown RX/TX QMU */
 	ks_disable_qmu(ks);
+	ks_disable_int(ks);
 
 	/* set powermode to soft power down to save power */
 	ks_set_powermode(ks, PMECR_PM_SOFTDOWN);
@@ -679,13 +693,13 @@
 	ks->txh.txw[1] = cpu_to_le16(len);
 
 	/* 1. set sudo-DMA mode */
-	ks_wrreg8(ks, KS_RXQCR, (ks->rc_rxqcr | RXQCR_SDA) & 0xff);
+	ks_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr | RXQCR_SDA);
 	/* 2. write status/lenth info */
 	ks_outblk(ks, ks->txh.txw, 4);
 	/* 3. write pkt data */
 	ks_outblk(ks, (u16 *)pdata, ALIGN(len, 4));
 	/* 4. reset sudo-DMA mode */
-	ks_wrreg8(ks, KS_RXQCR, ks->rc_rxqcr);
+	ks_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr);
 	/* 5. Enqueue Tx(move the pkt from TX buffer into TXQ) */
 	ks_wrreg16(ks, KS_TXQCR, TXQCR_METFE);
 	/* 6. wait until TXQCR_METFE is auto-cleared */
@@ -706,10 +720,9 @@
 {
 	netdev_tx_t retv = NETDEV_TX_OK;
 	struct ks_net *ks = netdev_priv(netdev);
+	unsigned long flags;
 
-	disable_irq(netdev->irq);
-	ks_disable_int(ks);
-	spin_lock(&ks->statelock);
+	spin_lock_irqsave(&ks->statelock, flags);
 
 	/* Extra space are required:
 	*  4 byte for alignment, 4 for status/length, 4 for CRC
@@ -723,9 +736,7 @@
 		dev_kfree_skb(skb);
 	} else
 		retv = NETDEV_TX_BUSY;
-	spin_unlock(&ks->statelock);
-	ks_enable_int(ks);
-	enable_irq(netdev->irq);
+	spin_unlock_irqrestore(&ks->statelock, flags);
 	return retv;
 }
 
@@ -1251,6 +1262,10 @@
 		goto err_free;
 	}
 
+	err = ks_check_endian(ks);
+	if (err)
+		goto err_free;
+
 	netdev->irq = platform_get_irq(pdev, 0);
 
 	if ((int)netdev->irq < 0) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/micrel/ksz884x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/micrel/ksz884x.c
@@ -1649,8 +1649,7 @@
 
 #define HW_DELAY(hw, reg)			\
 	do {					\
-		u16 dummy;			\
-		dummy = readw(hw->io + reg);	\
+		readw(hw->io + reg);		\
 	} while (0)
 
 /**
@@ -5694,7 +5693,7 @@
 		 * from the bridge.
 		 */
 		if ((hw->features & STP_SUPPORT) && !promiscuous &&
-		    (dev->priv_flags & IFF_BRIDGE_PORT)) {
+		    netif_is_bridge_port(dev)) {
 			struct ksz_switch *sw = hw->ksz_switch;
 			int port = priv->port.first_port;
 
@@ -6929,7 +6928,7 @@
 	char banner[sizeof(version)];
 	struct ksz_switch *sw = NULL;
 
-	result = pci_enable_device(pdev);
+	result = pcim_enable_device(pdev);
 	if (result)
 		return result;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/microchip/encx24j600-regmap.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/microchip/encx24j600-regmap.c
@@ -364,7 +364,7 @@
 		goto err_out;
 
 	usleep_range(26, 100);
-	while ((ret = regmap_read(ctx->regmap, MISTAT, &mistat) != 0) &&
+	while (((ret = regmap_read(ctx->regmap, MISTAT, &mistat)) == 0) &&
 	       (mistat & BUSY))
 		cpu_relax();
 
@@ -402,7 +402,7 @@
 		goto err_out;
 
 	usleep_range(26, 100);
-	while ((ret = regmap_read(ctx->regmap, MISTAT, &mistat) != 0) &&
+	while (((ret = regmap_read(ctx->regmap, MISTAT, &mistat)) == 0) &&
 	       (mistat & BUSY))
 		cpu_relax();
 
@@ -502,13 +502,19 @@
 	.reg_read = regmap_encx24j600_phy_reg_read,
 };
 
-void devm_regmap_init_encx24j600(struct device *dev,
-				 struct encx24j600_context *ctx)
+int devm_regmap_init_encx24j600(struct device *dev,
+				struct encx24j600_context *ctx)
 {
 	mutex_init(&ctx->mutex);
 	regcfg.lock_arg = ctx;
 	ctx->regmap = devm_regmap_init(dev, &regmap_encx24j600, ctx, &regcfg);
+	if (IS_ERR(ctx->regmap))
+		return PTR_ERR(ctx->regmap);
 	ctx->phymap = devm_regmap_init(dev, &phymap_encx24j600, ctx, &phycfg);
+	if (IS_ERR(ctx->phymap))
+		return PTR_ERR(ctx->phymap);
+
+	return 0;
 }
 EXPORT_SYMBOL_GPL(devm_regmap_init_encx24j600);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/microchip/encx24j600.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/microchip/encx24j600.c
@@ -1027,10 +1027,13 @@
 	priv->speed = SPEED_100;
 
 	priv->ctx.spi = spi;
-	devm_regmap_init_encx24j600(&spi->dev, &priv->ctx);
 	ndev->irq = spi->irq;
 	ndev->netdev_ops = &encx24j600_netdev_ops;
 
+	ret = devm_regmap_init_encx24j600(&spi->dev, &priv->ctx);
+	if (ret)
+		goto out_free;
+
 	mutex_init(&priv->lock);
 
 	/* Reset device and check if it is connected */
@@ -1070,7 +1073,7 @@
 	if (unlikely(ret)) {
 		netif_err(priv, probe, ndev, "Error %d initializing card encx24j600 card\n",
 			  ret);
-		goto out_free;
+		goto out_stop;
 	}
 
 	eidled = encx24j600_read_reg(priv, EIDLED);
@@ -1088,6 +1091,8 @@
 
 out_unregister:
 	unregister_netdev(priv->ndev);
+out_stop:
+	kthread_stop(priv->kworker_task);
 out_free:
 	free_netdev(ndev);
 
@@ -1100,6 +1105,7 @@
 	struct encx24j600_priv *priv = dev_get_drvdata(&spi->dev);
 
 	unregister_netdev(priv->ndev);
+	kthread_stop(priv->kworker_task);
 
 	free_netdev(priv->ndev);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/microchip/encx24j600_hw.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/microchip/encx24j600_hw.h
@@ -15,8 +15,8 @@
 	int bank;
 };
 
-void devm_regmap_init_encx24j600(struct device *dev,
-				 struct encx24j600_context *ctx);
+int devm_regmap_init_encx24j600(struct device *dev,
+				struct encx24j600_context *ctx);
 
 /* Single-byte instructions */
 #define BANK_SELECT(bank) (0xC0 | ((bank & (BANK_MASK >> BANK_SHIFT)) << 1))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/microchip/lan743x_ethtool.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/microchip/lan743x_ethtool.c
@@ -780,7 +780,9 @@
 
 	wol->supported = 0;
 	wol->wolopts = 0;
-	phy_ethtool_get_wol(netdev->phydev, wol);
+
+	if (netdev->phydev)
+		phy_ethtool_get_wol(netdev->phydev, wol);
 
 	wol->supported |= WAKE_BCAST | WAKE_UCAST | WAKE_MCAST |
 		WAKE_MAGIC | WAKE_PHY | WAKE_ARP;
@@ -809,9 +811,8 @@
 
 	device_set_wakeup_enable(&adapter->pdev->dev, (bool)wol->wolopts);
 
-	phy_ethtool_set_wol(netdev->phydev, wol);
-
-	return 0;
+	return netdev->phydev ? phy_ethtool_set_wol(netdev->phydev, wol)
+			: -ENETDOWN;
 }
 #endif /* CONFIG_PM */
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/microchip/lan743x_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/microchip/lan743x_main.c
@@ -80,6 +80,18 @@
 				  !(data & HW_CFG_LRST_), 100000, 10000000);
 }
 
+static int lan743x_csr_wait_for_bit_atomic(struct lan743x_adapter *adapter,
+					   int offset, u32 bit_mask,
+					   int target_value, int udelay_min,
+					   int udelay_max, int count)
+{
+	u32 data;
+
+	return readx_poll_timeout_atomic(LAN743X_CSR_READ_OP, offset, data,
+					 target_value == !!(data & bit_mask),
+					 udelay_max, udelay_min * count);
+}
+
 static int lan743x_csr_wait_for_bit(struct lan743x_adapter *adapter,
 				    int offset, u32 bit_mask,
 				    int target_value, int usleep_min,
@@ -145,7 +157,8 @@
 
 	int_sts = lan743x_csr_read(adapter, INT_STS);
 	if (int_sts & INT_BIT_SW_GP_) {
-		lan743x_csr_write(adapter, INT_STS, INT_BIT_SW_GP_);
+		/* disable the interrupt to prevent repeated re-triggering */
+		lan743x_csr_write(adapter, INT_EN_CLR, INT_BIT_SW_GP_);
 		intr->software_isr_flag = 1;
 	}
 }
@@ -155,9 +168,8 @@
 	struct lan743x_tx *tx = context;
 	struct lan743x_adapter *adapter = tx->adapter;
 	bool enable_flag = true;
-	u32 int_en = 0;
 
-	int_en = lan743x_csr_read(adapter, INT_EN_SET);
+	lan743x_csr_read(adapter, INT_EN_SET);
 	if (flags & LAN743X_VECTOR_FLAG_SOURCE_ENABLE_CLEAR) {
 		lan743x_csr_write(adapter, INT_EN_CLR,
 				  INT_BIT_DMA_TX_(tx->channel_number));
@@ -672,14 +684,12 @@
 static int lan743x_dp_write(struct lan743x_adapter *adapter,
 			    u32 select, u32 addr, u32 length, u32 *buf)
 {
-	int ret = -EIO;
 	u32 dp_sel;
 	int i;
 
-	mutex_lock(&adapter->dp_lock);
-	if (lan743x_csr_wait_for_bit(adapter, DP_SEL, DP_SEL_DPRDY_,
-				     1, 40, 100, 100))
-		goto unlock;
+	if (lan743x_csr_wait_for_bit_atomic(adapter, DP_SEL, DP_SEL_DPRDY_,
+					    1, 40, 100, 100))
+		return -EIO;
 	dp_sel = lan743x_csr_read(adapter, DP_SEL);
 	dp_sel &= ~DP_SEL_MASK_;
 	dp_sel |= select;
@@ -689,15 +699,13 @@
 		lan743x_csr_write(adapter, DP_ADDR, addr + i);
 		lan743x_csr_write(adapter, DP_DATA_0, buf[i]);
 		lan743x_csr_write(adapter, DP_CMD, DP_CMD_WRITE_);
-		if (lan743x_csr_wait_for_bit(adapter, DP_SEL, DP_SEL_DPRDY_,
-					     1, 40, 100, 100))
-			goto unlock;
+		if (lan743x_csr_wait_for_bit_atomic(adapter, DP_SEL,
+						    DP_SEL_DPRDY_,
+						    1, 40, 100, 100))
+			return -EIO;
 	}
-	ret = 0;
 
-unlock:
-	mutex_unlock(&adapter->dp_lock);
-	return ret;
+	return 0;
 }
 
 static u32 lan743x_mac_mii_access(u16 id, u16 index, int read)
@@ -921,8 +929,7 @@
 }
 
 static void lan743x_phy_update_flowcontrol(struct lan743x_adapter *adapter,
-					   u8 duplex, u16 local_adv,
-					   u16 remote_adv)
+					   u16 local_adv, u16 remote_adv)
 {
 	struct lan743x_phy *phy = &adapter->phy;
 	u8 cap;
@@ -949,22 +956,17 @@
 
 	phy_print_status(phydev);
 	if (phydev->state == PHY_RUNNING) {
-		struct ethtool_link_ksettings ksettings;
 		int remote_advertisement = 0;
 		int local_advertisement = 0;
 
-		memset(&ksettings, 0, sizeof(ksettings));
-		phy_ethtool_get_link_ksettings(netdev, &ksettings);
 		local_advertisement =
 			linkmode_adv_to_mii_adv_t(phydev->advertising);
 		remote_advertisement =
 			linkmode_adv_to_mii_adv_t(phydev->lp_advertising);
 
-		lan743x_phy_update_flowcontrol(adapter,
-					       ksettings.base.duplex,
-					       local_advertisement,
+		lan743x_phy_update_flowcontrol(adapter, local_advertisement,
 					       remote_advertisement);
-		lan743x_ptp_update_latency(adapter, ksettings.base.speed);
+		lan743x_ptp_update_latency(adapter, phydev->speed);
 	}
 }
 
@@ -1247,13 +1249,13 @@
 		goto clear_active;
 
 	if (!(buffer_info->flags & TX_BUFFER_INFO_FLAG_TIMESTAMP_REQUESTED)) {
-		dev_kfree_skb(buffer_info->skb);
+		dev_kfree_skb_any(buffer_info->skb);
 		goto clear_skb;
 	}
 
 	if (cleanup) {
 		lan743x_ptp_unrequest_tx_timestamp(tx->adapter);
-		dev_kfree_skb(buffer_info->skb);
+		dev_kfree_skb_any(buffer_info->skb);
 	} else {
 		ignore_sync = (buffer_info->flags &
 			       TX_BUFFER_INFO_FLAG_IGNORE_SYNC) != 0;
@@ -1563,7 +1565,7 @@
 	if (required_number_of_descriptors >
 		lan743x_tx_get_avail_desc(tx)) {
 		if (required_number_of_descriptors > (tx->ring_size - 1)) {
-			dev_kfree_skb(skb);
+			dev_kfree_skb_irq(skb);
 		} else {
 			/* save to overflow buffer */
 			tx->overflow_skb = skb;
@@ -1596,7 +1598,7 @@
 				   start_frame_length,
 				   do_timestamp,
 				   skb->ip_summed == CHECKSUM_PARTIAL)) {
-		dev_kfree_skb(skb);
+		dev_kfree_skb_irq(skb);
 		goto unlock;
 	}
 
@@ -1615,7 +1617,7 @@
 			 * frame assembler clean up was performed inside
 			 *	lan743x_tx_frame_add_fragment
 			 */
-			dev_kfree_skb(skb);
+			dev_kfree_skb_irq(skb);
 			goto unlock;
 		}
 	}
@@ -1635,10 +1637,9 @@
 	bool start_transmitter = false;
 	unsigned long irq_flags = 0;
 	u32 ioc_bit = 0;
-	u32 int_sts = 0;
 
 	ioc_bit = DMAC_INT_BIT_TX_IOC_(tx->channel_number);
-	int_sts = lan743x_csr_read(adapter, DMAC_INT_STS);
+	lan743x_csr_read(adapter, DMAC_INT_STS);
 	if (tx->vector_flags & LAN743X_VECTOR_FLAG_SOURCE_STATUS_W2C)
 		lan743x_csr_write(adapter, DMAC_INT_STS, ioc_bit);
 	spin_lock_irqsave(&tx->ring_lock, irq_flags);
@@ -1712,6 +1713,16 @@
 		ret = -EINVAL;
 		goto cleanup;
 	}
+	if (dma_set_mask_and_coherent(&tx->adapter->pdev->dev,
+				      DMA_BIT_MASK(64))) {
+		if (dma_set_mask_and_coherent(&tx->adapter->pdev->dev,
+					      DMA_BIT_MASK(32))) {
+			dev_warn(&tx->adapter->pdev->dev,
+				 "lan743x_: No suitable DMA available\n");
+			ret = -ENOMEM;
+			goto cleanup;
+		}
+	}
 	ring_allocation_size = ALIGN(tx->ring_size *
 				     sizeof(struct lan743x_tx_descriptor),
 				     PAGE_SIZE);
@@ -1894,13 +1905,21 @@
 	return ((++index) % rx->ring_size);
 }
 
-static struct sk_buff *lan743x_rx_allocate_skb(struct lan743x_rx *rx)
+static struct sk_buff *lan743x_rx_allocate_skb(struct lan743x_rx *rx, gfp_t gfp)
 {
 	int length = 0;
 
 	length = (LAN743X_MAX_FRAME_SIZE + ETH_HLEN + 4 + RX_HEAD_PADDING);
 	return __netdev_alloc_skb(rx->adapter->netdev,
-				  length, GFP_ATOMIC | GFP_DMA);
+				  length, gfp);
+}
+
+static void lan743x_rx_update_tail(struct lan743x_rx *rx, int index)
+{
+	/* update the tail once per 8 descriptors */
+	if ((index & 7) == 7)
+		lan743x_csr_write(rx->adapter, RX_TAIL(rx->channel_number),
+				  index);
 }
 
 static int lan743x_rx_init_ring_element(struct lan743x_rx *rx, int index,
@@ -1933,6 +1952,7 @@
 	descriptor->data0 = (RX_DESC_DATA0_OWN_ |
 			    (length & RX_DESC_DATA0_BUF_LENGTH_MASK_));
 	skb_reserve(buffer_info->skb, RX_HEAD_PADDING);
+	lan743x_rx_update_tail(rx, index);
 
 	return 0;
 }
@@ -1951,6 +1971,7 @@
 	descriptor->data0 = (RX_DESC_DATA0_OWN_ |
 			    ((buffer_info->buffer_length) &
 			    RX_DESC_DATA0_BUF_LENGTH_MASK_));
+	lan743x_rx_update_tail(rx, index);
 }
 
 static void lan743x_rx_release_ring_element(struct lan743x_rx *rx, int index)
@@ -2063,7 +2084,8 @@
 			struct sk_buff *new_skb = NULL;
 			int packet_length;
 
-			new_skb = lan743x_rx_allocate_skb(rx);
+			new_skb = lan743x_rx_allocate_skb(rx,
+							  GFP_ATOMIC | GFP_DMA);
 			if (!new_skb) {
 				/* failed to allocate next skb.
 				 * Memory is very low.
@@ -2162,6 +2184,7 @@
 {
 	struct lan743x_rx *rx = container_of(napi, struct lan743x_rx, napi);
 	struct lan743x_adapter *adapter = rx->adapter;
+	int result = RX_PROCESS_RESULT_NOTHING_TO_DO;
 	u32 rx_tail_flags = 0;
 	int count;
 
@@ -2170,27 +2193,19 @@
 		lan743x_csr_write(adapter, DMAC_INT_STS,
 				  DMAC_INT_BIT_RXFRM_(rx->channel_number));
 	}
-	count = 0;
-	while (count < weight) {
-		int rx_process_result = lan743x_rx_process_packet(rx);
-
-		if (rx_process_result == RX_PROCESS_RESULT_PACKET_RECEIVED) {
-			count++;
-		} else if (rx_process_result ==
-			RX_PROCESS_RESULT_NOTHING_TO_DO) {
+	for (count = 0; count < weight; count++) {
+		result = lan743x_rx_process_packet(rx);
+		if (result == RX_PROCESS_RESULT_NOTHING_TO_DO)
 			break;
-		} else if (rx_process_result ==
-			RX_PROCESS_RESULT_PACKET_DROPPED) {
-			continue;
-		}
 	}
 	rx->frame_count += count;
-	if (count == weight)
-		goto done;
+	if (count == weight || result == RX_PROCESS_RESULT_PACKET_RECEIVED)
+		return weight;
 
 	if (!napi_complete_done(napi, count))
-		goto done;
+		return count;
 
+	/* re-arm interrupts, must write to rx tail on some chip variants */
 	if (rx->vector_flags & LAN743X_VECTOR_FLAG_VECTOR_ENABLE_AUTO_SET)
 		rx_tail_flags |= RX_TAIL_SET_TOP_INT_VEC_EN_;
 	if (rx->vector_flags & LAN743X_VECTOR_FLAG_SOURCE_ENABLE_AUTO_SET) {
@@ -2200,10 +2215,10 @@
 				  INT_BIT_DMA_RX_(rx->channel_number));
 	}
 
-	/* update RX_TAIL */
-	lan743x_csr_write(adapter, RX_TAIL(rx->channel_number),
-			  rx_tail_flags | rx->last_tail);
-done:
+	if (rx_tail_flags)
+		lan743x_csr_write(adapter, RX_TAIL(rx->channel_number),
+				  rx_tail_flags | rx->last_tail);
+
 	return count;
 }
 
@@ -2259,6 +2274,16 @@
 		ret = -EINVAL;
 		goto cleanup;
 	}
+	if (dma_set_mask_and_coherent(&rx->adapter->pdev->dev,
+				      DMA_BIT_MASK(64))) {
+		if (dma_set_mask_and_coherent(&rx->adapter->pdev->dev,
+					      DMA_BIT_MASK(32))) {
+			dev_warn(&rx->adapter->pdev->dev,
+				 "lan743x_: No suitable DMA available\n");
+			ret = -ENOMEM;
+			goto cleanup;
+		}
+	}
 	ring_allocation_size = ALIGN(rx->ring_size *
 				     sizeof(struct lan743x_rx_descriptor),
 				     PAGE_SIZE);
@@ -2297,7 +2322,8 @@
 
 	rx->last_head = 0;
 	for (index = 0; index < rx->ring_size; index++) {
-		struct sk_buff *new_skb = lan743x_rx_allocate_skb(rx);
+		struct sk_buff *new_skb = lan743x_rx_allocate_skb(rx,
+								   GFP_KERNEL);
 
 		ret = lan743x_rx_init_ring_element(rx, index, new_skb);
 		if (ret)
@@ -2348,7 +2374,7 @@
 
 	netif_napi_add(adapter->netdev,
 		       &rx->napi, lan743x_rx_napi_poll,
-		       rx->ring_size - 1);
+		       NAPI_POLL_WEIGHT);
 
 	lan743x_csr_write(adapter, DMAC_CMD,
 			  DMAC_CMD_RX_SWR_(rx->channel_number));
@@ -2674,7 +2700,6 @@
 
 	adapter->intr.irq = adapter->pdev->irq;
 	lan743x_csr_write(adapter, INT_EN_CLR, 0xFFFFFFFF);
-	mutex_init(&adapter->dp_lock);
 
 	ret = lan743x_gpio_init(adapter);
 	if (ret)
@@ -3005,6 +3030,8 @@
 	if (ret) {
 		netif_err(adapter, probe, adapter->netdev,
 			  "lan743x_hardware_init returned %d\n", ret);
+		lan743x_pci_cleanup(adapter);
+		return ret;
 	}
 
 	/* open netdev when netdev is at running state while resume.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/microchip/lan743x_main.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/microchip/lan743x_main.h
@@ -706,9 +706,6 @@
 	struct lan743x_csr      csr;
 	struct lan743x_intr     intr;
 
-	/* lock, used to prevent concurrent access to data port */
-	struct mutex		dp_lock;
-
 	struct lan743x_gpio	gpio;
 	struct lan743x_ptp	ptp;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/moxa/moxart_ether.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/moxa/moxart_ether.c
@@ -74,11 +74,6 @@
 static void moxart_mac_free_memory(struct net_device *ndev)
 {
 	struct moxart_mac_priv_t *priv = netdev_priv(ndev);
-	int i;
-
-	for (i = 0; i < RX_DESC_NUM; i++)
-		dma_unmap_single(&ndev->dev, priv->rx_mapping[i],
-				 priv->rx_buf_size, DMA_FROM_DEVICE);
 
 	if (priv->tx_desc_base)
 		dma_free_coherent(&priv->pdev->dev,
@@ -147,11 +142,11 @@
 		       desc + RX_REG_OFFSET_DESC1);
 
 		priv->rx_buf[i] = priv->rx_buf_base + priv->rx_buf_size * i;
-		priv->rx_mapping[i] = dma_map_single(&ndev->dev,
+		priv->rx_mapping[i] = dma_map_single(&priv->pdev->dev,
 						     priv->rx_buf[i],
 						     priv->rx_buf_size,
 						     DMA_FROM_DEVICE);
-		if (dma_mapping_error(&ndev->dev, priv->rx_mapping[i]))
+		if (dma_mapping_error(&priv->pdev->dev, priv->rx_mapping[i]))
 			netdev_err(ndev, "DMA mapping error\n");
 
 		moxart_desc_write(priv->rx_mapping[i],
@@ -193,6 +188,7 @@
 static int moxart_mac_stop(struct net_device *ndev)
 {
 	struct moxart_mac_priv_t *priv = netdev_priv(ndev);
+	int i;
 
 	napi_disable(&priv->napi);
 
@@ -204,6 +200,11 @@
 	/* disable all functions */
 	writel(0, priv->base + REG_MAC_CTRL);
 
+	/* unmap areas mapped in moxart_mac_setup_desc_ring() */
+	for (i = 0; i < RX_DESC_NUM; i++)
+		dma_unmap_single(&priv->pdev->dev, priv->rx_mapping[i],
+				 priv->rx_buf_size, DMA_FROM_DEVICE);
+
 	return 0;
 }
 
@@ -240,7 +241,7 @@
 		if (len > RX_BUF_SIZE)
 			len = RX_BUF_SIZE;
 
-		dma_sync_single_for_cpu(&ndev->dev,
+		dma_sync_single_for_cpu(&priv->pdev->dev,
 					priv->rx_mapping[rx_head],
 					priv->rx_buf_size, DMA_FROM_DEVICE);
 		skb = netdev_alloc_skb_ip_align(ndev, len);
@@ -294,7 +295,7 @@
 	unsigned int tx_tail = priv->tx_tail;
 
 	while (tx_tail != tx_head) {
-		dma_unmap_single(&ndev->dev, priv->tx_mapping[tx_tail],
+		dma_unmap_single(&priv->pdev->dev, priv->tx_mapping[tx_tail],
 				 priv->tx_len[tx_tail], DMA_TO_DEVICE);
 
 		ndev->stats.tx_packets++;
@@ -357,9 +358,9 @@
 
 	len = skb->len > TX_BUF_SIZE ? TX_BUF_SIZE : skb->len;
 
-	priv->tx_mapping[tx_head] = dma_map_single(&ndev->dev, skb->data,
+	priv->tx_mapping[tx_head] = dma_map_single(&priv->pdev->dev, skb->data,
 						   len, DMA_TO_DEVICE);
-	if (dma_mapping_error(&ndev->dev, priv->tx_mapping[tx_head])) {
+	if (dma_mapping_error(&priv->pdev->dev, priv->tx_mapping[tx_head])) {
 		netdev_err(ndev, "DMA mapping error\n");
 		goto out_unlock;
 	}
@@ -378,7 +379,7 @@
 		len = ETH_ZLEN;
 	}
 
-	dma_sync_single_for_device(&ndev->dev, priv->tx_mapping[tx_head],
+	dma_sync_single_for_device(&priv->pdev->dev, priv->tx_mapping[tx_head],
 				   priv->tx_buf_size, DMA_TO_DEVICE);
 
 	txdes1 = TX_DESC1_LTS | TX_DESC1_FTS | (len & TX_DESC1_BUF_SIZE_MASK);
@@ -481,6 +482,10 @@
 	priv->pdev = pdev;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		ret = -EINVAL;
+		goto init_fail;
+	}
 	ndev->base_addr = res->start;
 	priv->base = devm_ioremap_resource(p_dev, res);
 	if (IS_ERR(priv->base)) {
@@ -494,7 +499,7 @@
 	priv->tx_buf_size = TX_BUF_SIZE;
 	priv->rx_buf_size = RX_BUF_SIZE;
 
-	priv->tx_desc_base = dma_alloc_coherent(&pdev->dev, TX_REG_DESC_SIZE *
+	priv->tx_desc_base = dma_alloc_coherent(p_dev, TX_REG_DESC_SIZE *
 						TX_DESC_NUM, &priv->tx_base,
 						GFP_DMA | GFP_KERNEL);
 	if (!priv->tx_desc_base) {
@@ -502,7 +507,7 @@
 		goto init_fail;
 	}
 
-	priv->rx_desc_base = dma_alloc_coherent(&pdev->dev, RX_REG_DESC_SIZE *
+	priv->rx_desc_base = dma_alloc_coherent(p_dev, RX_REG_DESC_SIZE *
 						RX_DESC_NUM, &priv->rx_base,
 						GFP_DMA | GFP_KERNEL);
 	if (!priv->rx_desc_base) {
@@ -541,10 +546,8 @@
 	SET_NETDEV_DEV(ndev, &pdev->dev);
 
 	ret = register_netdev(ndev);
-	if (ret) {
-		free_netdev(ndev);
+	if (ret)
 		goto init_fail;
-	}
 
 	netdev_dbg(ndev, "%s: IRQ=%d address=%pM\n",
 		   __func__, ndev->irq, ndev->dev_addr);
@@ -564,7 +567,7 @@
 	struct net_device *ndev = platform_get_drvdata(pdev);
 
 	unregister_netdev(ndev);
-	free_irq(ndev->irq, ndev);
+	devm_free_irq(&pdev->dev, ndev->irq, ndev);
 	moxart_mac_free_memory(ndev);
 	free_netdev(ndev);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mscc/ocelot.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mscc/ocelot.c
@@ -1024,12 +1024,6 @@
 	switch (cfg.rx_filter) {
 	case HWTSTAMP_FILTER_NONE:
 		break;
-	case HWTSTAMP_FILTER_ALL:
-	case HWTSTAMP_FILTER_SOME:
-	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
-	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
-	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
-	case HWTSTAMP_FILTER_NTP_ALL:
 	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
 	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
 	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
@@ -1189,7 +1183,10 @@
 				 SOF_TIMESTAMPING_RAW_HARDWARE;
 	info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON) |
 			 BIT(HWTSTAMP_TX_ONESTEP_SYNC);
-	info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | BIT(HWTSTAMP_FILTER_ALL);
+	info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |
+			   BIT(HWTSTAMP_FILTER_PTP_V2_EVENT) |
+			   BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
+			   BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT);
 
 	return 0;
 }
@@ -1716,10 +1713,8 @@
 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 	int ret = 0;
 
-	if (!ocelot_netdevice_dev_check(dev))
-		return 0;
-
 	if (event == NETDEV_PRECHANGEUPPER &&
+	    ocelot_netdevice_dev_check(dev) &&
 	    netif_is_lag_master(info->upper_dev)) {
 		struct netdev_lag_upper_info *lag_upper_info = info->upper_info;
 		struct netlink_ext_ack *extack;
@@ -1979,14 +1974,18 @@
 
 static int ocelot_init_timestamp(struct ocelot *ocelot)
 {
+	struct ptp_clock *ptp_clock;
+
 	ocelot->ptp_info = ocelot_ptp_clock_info;
-	ocelot->ptp_clock = ptp_clock_register(&ocelot->ptp_info, ocelot->dev);
-	if (IS_ERR(ocelot->ptp_clock))
-		return PTR_ERR(ocelot->ptp_clock);
+	ptp_clock = ptp_clock_register(&ocelot->ptp_info, ocelot->dev);
+	if (IS_ERR(ptp_clock))
+		return PTR_ERR(ptp_clock);
 	/* Check if PHC support is missing at the configuration level */
-	if (!ocelot->ptp_clock)
+	if (!ptp_clock)
 		return 0;
 
+	ocelot->ptp_clock = ptp_clock;
+
 	ocelot_write(ocelot, SYS_PTP_CFG_PTP_STAMP_WID(30), SYS_PTP_CFG);
 	ocelot_write(ocelot, 0xffffffff, ANA_TABLES_PTP_ID_LOW);
 	ocelot_write(ocelot, 0xffffffff, ANA_TABLES_PTP_ID_HIGH);
@@ -2154,8 +2153,12 @@
 	ocelot_write_rix(ocelot,
 			 ANA_PGID_PGID_PGID(GENMASK(ocelot->num_phys_ports, 0)),
 			 ANA_PGID_PGID, PGID_MC);
-	ocelot_write_rix(ocelot, 0, ANA_PGID_PGID, PGID_MCIPV4);
-	ocelot_write_rix(ocelot, 0, ANA_PGID_PGID, PGID_MCIPV6);
+	ocelot_write_rix(ocelot,
+			 ANA_PGID_PGID_PGID(GENMASK(ocelot->num_phys_ports, 0)),
+			 ANA_PGID_PGID, PGID_MCIPV4);
+	ocelot_write_rix(ocelot,
+			 ANA_PGID_PGID_PGID(GENMASK(ocelot->num_phys_ports, 0)),
+			 ANA_PGID_PGID, PGID_MCIPV6);
 
 	/* CPU port Injection/Extraction configuration */
 	ocelot_write_rix(ocelot, QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE |
@@ -2213,6 +2216,8 @@
 	destroy_workqueue(ocelot->stats_queue);
 	mutex_destroy(&ocelot->stats_lock);
 	ocelot_ace_deinit();
+	if (ocelot->ptp_clock)
+		ptp_clock_unregister(ocelot->ptp_clock);
 
 	for (i = 0; i < ocelot->num_phys_ports; i++) {
 		port = ocelot->ports[i];
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/mscc/ocelot_board.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/mscc/ocelot_board.c
@@ -112,6 +112,14 @@
 		if (err != 4)
 			break;
 
+		/* At this point the IFH was read correctly, so it is safe to
+		 * presume that there is no error. The err needs to be reset
+		 * otherwise a frame could come in CPU queue between the while
+		 * condition and the check for error later on. And in that case
+		 * the new frame is just removed and not processed.
+		 */
+		err = 0;
+
 		ocelot_parse_ifh(ifh, &info);
 
 		dev = ocelot->ports[info.port]->dev;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
@@ -3849,6 +3849,7 @@
 		dev_err(&pdev->dev,
 			"invalid sram_size %dB or board span %ldB\n",
 			mgp->sram_size, mgp->board_span);
+		status = -EINVAL;
 		goto abort_with_ioremap;
 	}
 	memcpy_fromio(mgp->eeprom_strings,
@@ -3955,6 +3956,7 @@
 	myri10ge_free_slices(mgp);
 
 abort_with_firmware:
+	kfree(mgp->msix_vectors);
 	myri10ge_dummy_rdma(mgp, 0);
 
 abort_with_ioremap:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/natsemi/jazzsonic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/natsemi/jazzsonic.c
@@ -235,11 +235,13 @@
 
 	err = register_netdev(dev);
 	if (err)
-		goto out1;
+		goto undo_probe1;
 
 	return 0;
 
-out1:
+undo_probe1:
+	dma_free_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
+			  lp->descriptors, lp->descriptors_laddr);
 	release_mem_region(dev->base_addr, SONIC_MEM_SIZE);
 out:
 	free_netdev(dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/natsemi/macsonic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/natsemi/macsonic.c
@@ -540,10 +540,14 @@
 
 	err = register_netdev(dev);
 	if (err)
-		goto out;
+		goto undo_probe;
 
 	return 0;
 
+undo_probe:
+	dma_free_coherent(lp->device,
+			  SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
+			  lp->descriptors, lp->descriptors_laddr);
 out:
 	free_netdev(dev);
 
@@ -618,12 +622,16 @@
 
 	err = register_netdev(ndev);
 	if (err)
-		goto out;
+		goto undo_probe;
 
 	nubus_set_drvdata(board, ndev);
 
 	return 0;
 
+undo_probe:
+	dma_free_coherent(lp->device,
+			  SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
+			  lp->descriptors, lp->descriptors_laddr);
 out:
 	free_netdev(ndev);
 	return err;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/natsemi/natsemi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/natsemi/natsemi.c
@@ -819,7 +819,7 @@
 		printk(version);
 #endif
 
-	i = pci_enable_device(pdev);
+	i = pcim_enable_device(pdev);
 	if (i) return i;
 
 	/* natsemi has a non-standard PM control register
@@ -852,7 +852,7 @@
 	ioaddr = ioremap(iostart, iosize);
 	if (!ioaddr) {
 		i = -ENOMEM;
-		goto err_ioremap;
+		goto err_pci_request_regions;
 	}
 
 	/* Work around the dropped serial bit. */
@@ -974,9 +974,6 @@
  err_register_netdev:
 	iounmap(ioaddr);
 
- err_ioremap:
-	pci_release_regions(pdev);
-
  err_pci_request_regions:
 	free_netdev(dev);
 	return i;
@@ -3242,7 +3239,6 @@
 
 	NATSEMI_REMOVE_FILE(pdev, dspcfg_workaround);
 	unregister_netdev (dev);
-	pci_release_regions (pdev);
 	iounmap(ioaddr);
 	free_netdev (dev);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/natsemi/sonic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/natsemi/sonic.c
@@ -64,6 +64,8 @@
 
 	netif_dbg(lp, ifup, dev, "%s: initializing sonic driver\n", __func__);
 
+	spin_lock_init(&lp->lock);
+
 	for (i = 0; i < SONIC_NUM_RRS; i++) {
 		struct sk_buff *skb = netdev_alloc_skb(dev, SONIC_RBSIZE + 2);
 		if (skb == NULL) {
@@ -114,6 +116,24 @@
 	return 0;
 }
 
+/* Wait for the SONIC to become idle. */
+static void sonic_quiesce(struct net_device *dev, u16 mask)
+{
+	struct sonic_local * __maybe_unused lp = netdev_priv(dev);
+	int i;
+	u16 bits;
+
+	for (i = 0; i < 1000; ++i) {
+		bits = SONIC_READ(SONIC_CMD) & mask;
+		if (!bits)
+			return;
+		if (irqs_disabled() || in_interrupt())
+			udelay(20);
+		else
+			usleep_range(100, 200);
+	}
+	WARN_ONCE(1, "command deadline expired! 0x%04x\n", bits);
+}
 
 /*
  * Close the SONIC device
@@ -130,6 +150,9 @@
 	/*
 	 * stop the SONIC, disable interrupts
 	 */
+	SONIC_WRITE(SONIC_CMD, SONIC_CR_RXDIS);
+	sonic_quiesce(dev, SONIC_CR_ALL);
+
 	SONIC_WRITE(SONIC_IMR, 0);
 	SONIC_WRITE(SONIC_ISR, 0x7fff);
 	SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
@@ -169,6 +192,9 @@
 	 * put the Sonic into software-reset mode and
 	 * disable all interrupts before releasing DMA buffers
 	 */
+	SONIC_WRITE(SONIC_CMD, SONIC_CR_RXDIS);
+	sonic_quiesce(dev, SONIC_CR_ALL);
+
 	SONIC_WRITE(SONIC_IMR, 0);
 	SONIC_WRITE(SONIC_ISR, 0x7fff);
 	SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
@@ -206,8 +232,6 @@
  *   wake the tx queue
  * Concurrently with all of this, the SONIC is potentially writing to
  * the status flags of the TDs.
- * Until some mutual exclusion is added, this code will not work with SMP. However,
- * MIPS Jazz machines and m68k Macs were all uni-processor machines.
  */
 
 static int sonic_send_packet(struct sk_buff *skb, struct net_device *dev)
@@ -215,7 +239,8 @@
 	struct sonic_local *lp = netdev_priv(dev);
 	dma_addr_t laddr;
 	int length;
-	int entry = lp->next_tx;
+	int entry;
+	unsigned long flags;
 
 	netif_dbg(lp, tx_queued, dev, "%s: skb=%p\n", __func__, skb);
 
@@ -231,12 +256,16 @@
 	 */
 
 	laddr = dma_map_single(lp->device, skb->data, length, DMA_TO_DEVICE);
-	if (!laddr) {
+	if (dma_mapping_error(lp->device, laddr)) {
 		pr_err_ratelimited("%s: failed to map tx DMA buffer.\n", dev->name);
 		dev_kfree_skb_any(skb);
 		return NETDEV_TX_OK;
 	}
 
+	spin_lock_irqsave(&lp->lock, flags);
+
+	entry = lp->next_tx;
+
 	sonic_tda_put(dev, entry, SONIC_TD_STATUS, 0);       /* clear status */
 	sonic_tda_put(dev, entry, SONIC_TD_FRAG_COUNT, 1);   /* single fragment */
 	sonic_tda_put(dev, entry, SONIC_TD_PKTSIZE, length); /* length of packet */
@@ -246,10 +275,6 @@
 	sonic_tda_put(dev, entry, SONIC_TD_LINK,
 		sonic_tda_get(dev, entry, SONIC_TD_LINK) | SONIC_EOL);
 
-	/*
-	 * Must set tx_skb[entry] only after clearing status, and
-	 * before clearing EOL and before stopping queue
-	 */
 	wmb();
 	lp->tx_len[entry] = length;
 	lp->tx_laddr[entry] = laddr;
@@ -272,6 +297,8 @@
 
 	SONIC_WRITE(SONIC_CMD, SONIC_CR_TXP);
 
+	spin_unlock_irqrestore(&lp->lock, flags);
+
 	return NETDEV_TX_OK;
 }
 
@@ -284,15 +311,28 @@
 	struct net_device *dev = dev_id;
 	struct sonic_local *lp = netdev_priv(dev);
 	int status;
+	unsigned long flags;
+
+	/* The lock has two purposes. Firstly, it synchronizes sonic_interrupt()
+	 * with sonic_send_packet() so that the two functions can share state.
+	 * Secondly, it makes sonic_interrupt() re-entrant, as that is required
+	 * by macsonic which must use two IRQs with different priority levels.
+	 */
+	spin_lock_irqsave(&lp->lock, flags);
+
+	status = SONIC_READ(SONIC_ISR) & SONIC_IMR_DEFAULT;
+	if (!status) {
+		spin_unlock_irqrestore(&lp->lock, flags);
 
-	if (!(status = SONIC_READ(SONIC_ISR) & SONIC_IMR_DEFAULT))
 		return IRQ_NONE;
+	}
 
 	do {
+		SONIC_WRITE(SONIC_ISR, status); /* clear the interrupt(s) */
+
 		if (status & SONIC_INT_PKTRX) {
 			netif_dbg(lp, intr, dev, "%s: packet rx\n", __func__);
 			sonic_rx(dev);	/* got packet(s) */
-			SONIC_WRITE(SONIC_ISR, SONIC_INT_PKTRX); /* clear the interrupt */
 		}
 
 		if (status & SONIC_INT_TXDN) {
@@ -300,11 +340,12 @@
 			int td_status;
 			int freed_some = 0;
 
-			/* At this point, cur_tx is the index of a TD that is one of:
-			 *   unallocated/freed                          (status set   & tx_skb[entry] clear)
-			 *   allocated and sent                         (status set   & tx_skb[entry] set  )
-			 *   allocated and not yet sent                 (status clear & tx_skb[entry] set  )
-			 *   still being allocated by sonic_send_packet (status clear & tx_skb[entry] clear)
+			/* The state of a Transmit Descriptor may be inferred
+			 * from { tx_skb[entry], td_status } as follows.
+			 * { clear, clear } => the TD has never been used
+			 * { set,   clear } => the TD was handed to SONIC
+			 * { set,   set   } => the TD was handed back
+			 * { clear, set   } => the TD is available for re-use
 			 */
 
 			netif_dbg(lp, intr, dev, "%s: tx done\n", __func__);
@@ -313,18 +354,19 @@
 				if ((td_status = sonic_tda_get(dev, entry, SONIC_TD_STATUS)) == 0)
 					break;
 
-				if (td_status & 0x0001) {
+				if (td_status & SONIC_TCR_PTX) {
 					lp->stats.tx_packets++;
 					lp->stats.tx_bytes += sonic_tda_get(dev, entry, SONIC_TD_PKTSIZE);
 				} else {
-					lp->stats.tx_errors++;
-					if (td_status & 0x0642)
+					if (td_status & (SONIC_TCR_EXD |
+					    SONIC_TCR_EXC | SONIC_TCR_BCM))
 						lp->stats.tx_aborted_errors++;
-					if (td_status & 0x0180)
+					if (td_status &
+					    (SONIC_TCR_NCRS | SONIC_TCR_CRLS))
 						lp->stats.tx_carrier_errors++;
-					if (td_status & 0x0020)
+					if (td_status & SONIC_TCR_OWC)
 						lp->stats.tx_window_errors++;
-					if (td_status & 0x0004)
+					if (td_status & SONIC_TCR_FU)
 						lp->stats.tx_fifo_errors++;
 				}
 
@@ -346,7 +388,6 @@
 			if (freed_some || lp->tx_skb[entry] == NULL)
 				netif_wake_queue(dev);  /* The ring is no longer full */
 			lp->cur_tx = entry;
-			SONIC_WRITE(SONIC_ISR, SONIC_INT_TXDN); /* clear the interrupt */
 		}
 
 		/*
@@ -355,42 +396,37 @@
 		if (status & SONIC_INT_RFO) {
 			netif_dbg(lp, rx_err, dev, "%s: rx fifo overrun\n",
 				  __func__);
-			lp->stats.rx_fifo_errors++;
-			SONIC_WRITE(SONIC_ISR, SONIC_INT_RFO); /* clear the interrupt */
 		}
 		if (status & SONIC_INT_RDE) {
 			netif_dbg(lp, rx_err, dev, "%s: rx descriptors exhausted\n",
 				  __func__);
-			lp->stats.rx_dropped++;
-			SONIC_WRITE(SONIC_ISR, SONIC_INT_RDE); /* clear the interrupt */
 		}
 		if (status & SONIC_INT_RBAE) {
 			netif_dbg(lp, rx_err, dev, "%s: rx buffer area exceeded\n",
 				  __func__);
-			lp->stats.rx_dropped++;
-			SONIC_WRITE(SONIC_ISR, SONIC_INT_RBAE); /* clear the interrupt */
 		}
 
 		/* counter overruns; all counters are 16bit wide */
-		if (status & SONIC_INT_FAE) {
+		if (status & SONIC_INT_FAE)
 			lp->stats.rx_frame_errors += 65536;
-			SONIC_WRITE(SONIC_ISR, SONIC_INT_FAE); /* clear the interrupt */
-		}
-		if (status & SONIC_INT_CRC) {
+		if (status & SONIC_INT_CRC)
 			lp->stats.rx_crc_errors += 65536;
-			SONIC_WRITE(SONIC_ISR, SONIC_INT_CRC); /* clear the interrupt */
-		}
-		if (status & SONIC_INT_MP) {
+		if (status & SONIC_INT_MP)
 			lp->stats.rx_missed_errors += 65536;
-			SONIC_WRITE(SONIC_ISR, SONIC_INT_MP); /* clear the interrupt */
-		}
 
 		/* transmit error */
 		if (status & SONIC_INT_TXER) {
-			if (SONIC_READ(SONIC_TCR) & SONIC_TCR_FU)
-				netif_dbg(lp, tx_err, dev, "%s: tx fifo underrun\n",
-					  __func__);
-			SONIC_WRITE(SONIC_ISR, SONIC_INT_TXER); /* clear the interrupt */
+			u16 tcr = SONIC_READ(SONIC_TCR);
+
+			netif_dbg(lp, tx_err, dev, "%s: TXER intr, TCR %04x\n",
+				  __func__, tcr);
+
+			if (tcr & (SONIC_TCR_EXD | SONIC_TCR_EXC |
+				   SONIC_TCR_FU | SONIC_TCR_BCM)) {
+				/* Aborted transmission. Try again. */
+				netif_stop_queue(dev);
+				SONIC_WRITE(SONIC_CMD, SONIC_CR_TXP);
+			}
 		}
 
 		/* bus retry */
@@ -400,107 +436,164 @@
 			/* ... to help debug DMA problems causing endless interrupts. */
 			/* Bounce the eth interface to turn on the interrupt again. */
 			SONIC_WRITE(SONIC_IMR, 0);
-			SONIC_WRITE(SONIC_ISR, SONIC_INT_BR); /* clear the interrupt */
 		}
 
-		/* load CAM done */
-		if (status & SONIC_INT_LCD)
-			SONIC_WRITE(SONIC_ISR, SONIC_INT_LCD); /* clear the interrupt */
-	} while((status = SONIC_READ(SONIC_ISR) & SONIC_IMR_DEFAULT));
+		status = SONIC_READ(SONIC_ISR) & SONIC_IMR_DEFAULT;
+	} while (status);
+
+	spin_unlock_irqrestore(&lp->lock, flags);
+
 	return IRQ_HANDLED;
 }
 
+/* Return the array index corresponding to a given Receive Buffer pointer. */
+static int index_from_addr(struct sonic_local *lp, dma_addr_t addr,
+			   unsigned int last)
+{
+	unsigned int i = last;
+
+	do {
+		i = (i + 1) & SONIC_RRS_MASK;
+		if (addr == lp->rx_laddr[i])
+			return i;
+	} while (i != last);
+
+	return -ENOENT;
+}
+
+/* Allocate and map a new skb to be used as a receive buffer. */
+static bool sonic_alloc_rb(struct net_device *dev, struct sonic_local *lp,
+			   struct sk_buff **new_skb, dma_addr_t *new_addr)
+{
+	*new_skb = netdev_alloc_skb(dev, SONIC_RBSIZE + 2);
+	if (!*new_skb)
+		return false;
+
+	if (SONIC_BUS_SCALE(lp->dma_bitmode) == 2)
+		skb_reserve(*new_skb, 2);
+
+	*new_addr = dma_map_single(lp->device, skb_put(*new_skb, SONIC_RBSIZE),
+				   SONIC_RBSIZE, DMA_FROM_DEVICE);
+	if (dma_mapping_error(lp->device, *new_addr)) {
+		dev_kfree_skb(*new_skb);
+		*new_skb = NULL;
+		return false;
+	}
+
+	return true;
+}
+
+/* Place a new receive resource in the Receive Resource Area and update RWP. */
+static void sonic_update_rra(struct net_device *dev, struct sonic_local *lp,
+			     dma_addr_t old_addr, dma_addr_t new_addr)
+{
+	unsigned int entry = sonic_rr_entry(dev, SONIC_READ(SONIC_RWP));
+	unsigned int end = sonic_rr_entry(dev, SONIC_READ(SONIC_RRP));
+	u32 buf;
+
+	/* The resources in the range [RRP, RWP) belong to the SONIC. This loop
+	 * scans the other resources in the RRA, those in the range [RWP, RRP).
+	 */
+	do {
+		buf = (sonic_rra_get(dev, entry, SONIC_RR_BUFADR_H) << 16) |
+		      sonic_rra_get(dev, entry, SONIC_RR_BUFADR_L);
+
+		if (buf == old_addr)
+			break;
+
+		entry = (entry + 1) & SONIC_RRS_MASK;
+	} while (entry != end);
+
+	WARN_ONCE(buf != old_addr, "failed to find resource!\n");
+
+	sonic_rra_put(dev, entry, SONIC_RR_BUFADR_H, new_addr >> 16);
+	sonic_rra_put(dev, entry, SONIC_RR_BUFADR_L, new_addr & 0xffff);
+
+	entry = (entry + 1) & SONIC_RRS_MASK;
+
+	SONIC_WRITE(SONIC_RWP, sonic_rr_addr(dev, entry));
+}
+
 /*
  * We have a good packet(s), pass it/them up the network stack.
  */
 static void sonic_rx(struct net_device *dev)
 {
 	struct sonic_local *lp = netdev_priv(dev);
-	int status;
 	int entry = lp->cur_rx;
+	int prev_entry = lp->eol_rx;
+	bool rbe = false;
 
 	while (sonic_rda_get(dev, entry, SONIC_RD_IN_USE) == 0) {
-		struct sk_buff *used_skb;
-		struct sk_buff *new_skb;
-		dma_addr_t new_laddr;
-		u16 bufadr_l;
-		u16 bufadr_h;
-		int pkt_len;
-
-		status = sonic_rda_get(dev, entry, SONIC_RD_STATUS);
-		if (status & SONIC_RCR_PRX) {
-			/* Malloc up new buffer. */
-			new_skb = netdev_alloc_skb(dev, SONIC_RBSIZE + 2);
-			if (new_skb == NULL) {
-				lp->stats.rx_dropped++;
+		u16 status = sonic_rda_get(dev, entry, SONIC_RD_STATUS);
+
+		/* If the RD has LPKT set, the chip has finished with the RB */
+		if ((status & SONIC_RCR_PRX) && (status & SONIC_RCR_LPKT)) {
+			struct sk_buff *new_skb;
+			dma_addr_t new_laddr;
+			u32 addr = (sonic_rda_get(dev, entry,
+						  SONIC_RD_PKTPTR_H) << 16) |
+				   sonic_rda_get(dev, entry, SONIC_RD_PKTPTR_L);
+			int i = index_from_addr(lp, addr, entry);
+
+			if (i < 0) {
+				WARN_ONCE(1, "failed to find buffer!\n");
 				break;
 			}
-			/* provide 16 byte IP header alignment unless DMA requires otherwise */
-			if(SONIC_BUS_SCALE(lp->dma_bitmode) == 2)
-				skb_reserve(new_skb, 2);
-
-			new_laddr = dma_map_single(lp->device, skb_put(new_skb, SONIC_RBSIZE),
-		                               SONIC_RBSIZE, DMA_FROM_DEVICE);
-			if (!new_laddr) {
-				dev_kfree_skb(new_skb);
-				printk(KERN_ERR "%s: Failed to map rx buffer, dropping packet.\n", dev->name);
+
+			if (sonic_alloc_rb(dev, lp, &new_skb, &new_laddr)) {
+				struct sk_buff *used_skb = lp->rx_skb[i];
+				int pkt_len;
+
+				/* Pass the used buffer up the stack */
+				dma_unmap_single(lp->device, addr, SONIC_RBSIZE,
+						 DMA_FROM_DEVICE);
+
+				pkt_len = sonic_rda_get(dev, entry,
+							SONIC_RD_PKTLEN);
+				skb_trim(used_skb, pkt_len);
+				used_skb->protocol = eth_type_trans(used_skb,
+								    dev);
+				netif_rx(used_skb);
+				lp->stats.rx_packets++;
+				lp->stats.rx_bytes += pkt_len;
+
+				lp->rx_skb[i] = new_skb;
+				lp->rx_laddr[i] = new_laddr;
+			} else {
+				/* Failed to obtain a new buffer so re-use it */
+				new_laddr = addr;
 				lp->stats.rx_dropped++;
-				break;
 			}
-
-			/* now we have a new skb to replace it, pass the used one up the stack */
-			dma_unmap_single(lp->device, lp->rx_laddr[entry], SONIC_RBSIZE, DMA_FROM_DEVICE);
-			used_skb = lp->rx_skb[entry];
-			pkt_len = sonic_rda_get(dev, entry, SONIC_RD_PKTLEN);
-			skb_trim(used_skb, pkt_len);
-			used_skb->protocol = eth_type_trans(used_skb, dev);
-			netif_rx(used_skb);
-			lp->stats.rx_packets++;
-			lp->stats.rx_bytes += pkt_len;
-
-			/* and insert the new skb */
-			lp->rx_laddr[entry] = new_laddr;
-			lp->rx_skb[entry] = new_skb;
-
-			bufadr_l = (unsigned long)new_laddr & 0xffff;
-			bufadr_h = (unsigned long)new_laddr >> 16;
-			sonic_rra_put(dev, entry, SONIC_RR_BUFADR_L, bufadr_l);
-			sonic_rra_put(dev, entry, SONIC_RR_BUFADR_H, bufadr_h);
-		} else {
-			/* This should only happen, if we enable accepting broken packets. */
-			lp->stats.rx_errors++;
-			if (status & SONIC_RCR_FAER)
-				lp->stats.rx_frame_errors++;
-			if (status & SONIC_RCR_CRCR)
-				lp->stats.rx_crc_errors++;
-		}
-		if (status & SONIC_RCR_LPKT) {
-			/*
-			 * this was the last packet out of the current receive buffer
-			 * give the buffer back to the SONIC
+			/* If RBE is already asserted when RWP advances then
+			 * it's safe to clear RBE after processing this packet.
 			 */
-			lp->cur_rwp += SIZEOF_SONIC_RR * SONIC_BUS_SCALE(lp->dma_bitmode);
-			if (lp->cur_rwp >= lp->rra_end) lp->cur_rwp = lp->rra_laddr & 0xffff;
-			SONIC_WRITE(SONIC_RWP, lp->cur_rwp);
-			if (SONIC_READ(SONIC_ISR) & SONIC_INT_RBE) {
-				netif_dbg(lp, rx_err, dev, "%s: rx buffer exhausted\n",
-					  __func__);
-				SONIC_WRITE(SONIC_ISR, SONIC_INT_RBE); /* clear the flag */
-			}
-		} else
-			printk(KERN_ERR "%s: rx desc without RCR_LPKT. Shouldn't happen !?\n",
-			     dev->name);
+			rbe = rbe || SONIC_READ(SONIC_ISR) & SONIC_INT_RBE;
+			sonic_update_rra(dev, lp, addr, new_laddr);
+		}
 		/*
 		 * give back the descriptor
 		 */
-		sonic_rda_put(dev, entry, SONIC_RD_LINK,
-			sonic_rda_get(dev, entry, SONIC_RD_LINK) | SONIC_EOL);
+		sonic_rda_put(dev, entry, SONIC_RD_STATUS, 0);
 		sonic_rda_put(dev, entry, SONIC_RD_IN_USE, 1);
-		sonic_rda_put(dev, lp->eol_rx, SONIC_RD_LINK,
-			sonic_rda_get(dev, lp->eol_rx, SONIC_RD_LINK) & ~SONIC_EOL);
-		lp->eol_rx = entry;
-		lp->cur_rx = entry = (entry + 1) & SONIC_RDS_MASK;
+
+		prev_entry = entry;
+		entry = (entry + 1) & SONIC_RDS_MASK;
+	}
+
+	lp->cur_rx = entry;
+
+	if (prev_entry != lp->eol_rx) {
+		/* Advance the EOL flag to put descriptors back into service */
+		sonic_rda_put(dev, prev_entry, SONIC_RD_LINK, SONIC_EOL |
+			      sonic_rda_get(dev, prev_entry, SONIC_RD_LINK));
+		sonic_rda_put(dev, lp->eol_rx, SONIC_RD_LINK, ~SONIC_EOL &
+			      sonic_rda_get(dev, lp->eol_rx, SONIC_RD_LINK));
+		lp->eol_rx = prev_entry;
 	}
+
+	if (rbe)
+		SONIC_WRITE(SONIC_ISR, SONIC_INT_RBE);
 	/*
 	 * If any worth-while packets have been received, netif_rx()
 	 * has done a mark_bh(NET_BH) for us and will work on them
@@ -550,6 +643,8 @@
 		    (netdev_mc_count(dev) > 15)) {
 			rcr |= SONIC_RCR_AMC;
 		} else {
+			unsigned long flags;
+
 			netif_dbg(lp, ifup, dev, "%s: mc_count %d\n", __func__,
 				  netdev_mc_count(dev));
 			sonic_set_cam_enable(dev, 1);  /* always enable our own address */
@@ -563,9 +658,14 @@
 				i++;
 			}
 			SONIC_WRITE(SONIC_CDC, 16);
-			/* issue Load CAM command */
 			SONIC_WRITE(SONIC_CDP, lp->cda_laddr & 0xffff);
+
+			/* LCAM and TXP commands can't be used simultaneously */
+			spin_lock_irqsave(&lp->lock, flags);
+			sonic_quiesce(dev, SONIC_CR_TXP);
 			SONIC_WRITE(SONIC_CMD, SONIC_CR_LCAM);
+			sonic_quiesce(dev, SONIC_CR_LCAM);
+			spin_unlock_irqrestore(&lp->lock, flags);
 		}
 	}
 
@@ -580,7 +680,6 @@
  */
 static int sonic_init(struct net_device *dev)
 {
-	unsigned int cmd;
 	struct sonic_local *lp = netdev_priv(dev);
 	int i;
 
@@ -592,12 +691,16 @@
 	SONIC_WRITE(SONIC_ISR, 0x7fff);
 	SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
 
+	/* While in reset mode, clear CAM Enable register */
+	SONIC_WRITE(SONIC_CE, 0);
+
 	/*
 	 * clear software reset flag, disable receiver, clear and
 	 * enable interrupts, then completely initialize the SONIC
 	 */
 	SONIC_WRITE(SONIC_CMD, 0);
-	SONIC_WRITE(SONIC_CMD, SONIC_CR_RXDIS);
+	SONIC_WRITE(SONIC_CMD, SONIC_CR_RXDIS | SONIC_CR_STP);
+	sonic_quiesce(dev, SONIC_CR_ALL);
 
 	/*
 	 * initialize the receive resource area
@@ -615,15 +718,10 @@
 	}
 
 	/* initialize all RRA registers */
-	lp->rra_end = (lp->rra_laddr + SONIC_NUM_RRS * SIZEOF_SONIC_RR *
-					SONIC_BUS_SCALE(lp->dma_bitmode)) & 0xffff;
-	lp->cur_rwp = (lp->rra_laddr + (SONIC_NUM_RRS - 1) * SIZEOF_SONIC_RR *
-					SONIC_BUS_SCALE(lp->dma_bitmode)) & 0xffff;
-
-	SONIC_WRITE(SONIC_RSA, lp->rra_laddr & 0xffff);
-	SONIC_WRITE(SONIC_REA, lp->rra_end);
-	SONIC_WRITE(SONIC_RRP, lp->rra_laddr & 0xffff);
-	SONIC_WRITE(SONIC_RWP, lp->cur_rwp);
+	SONIC_WRITE(SONIC_RSA, sonic_rr_addr(dev, 0));
+	SONIC_WRITE(SONIC_REA, sonic_rr_addr(dev, SONIC_NUM_RRS));
+	SONIC_WRITE(SONIC_RRP, sonic_rr_addr(dev, 0));
+	SONIC_WRITE(SONIC_RWP, sonic_rr_addr(dev, SONIC_NUM_RRS - 1));
 	SONIC_WRITE(SONIC_URRA, lp->rra_laddr >> 16);
 	SONIC_WRITE(SONIC_EOBC, (SONIC_RBSIZE >> 1) - (lp->dma_bitmode ? 2 : 1));
 
@@ -631,14 +729,7 @@
 	netif_dbg(lp, ifup, dev, "%s: issuing RRRA command\n", __func__);
 
 	SONIC_WRITE(SONIC_CMD, SONIC_CR_RRRA);
-	i = 0;
-	while (i++ < 100) {
-		if (SONIC_READ(SONIC_CMD) & SONIC_CR_RRRA)
-			break;
-	}
-
-	netif_dbg(lp, ifup, dev, "%s: status=%x, i=%d\n", __func__,
-		  SONIC_READ(SONIC_CMD), i);
+	sonic_quiesce(dev, SONIC_CR_RRRA);
 
 	/*
 	 * Initialize the receive descriptors so that they
@@ -713,28 +804,17 @@
 	 * load the CAM
 	 */
 	SONIC_WRITE(SONIC_CMD, SONIC_CR_LCAM);
-
-	i = 0;
-	while (i++ < 100) {
-		if (SONIC_READ(SONIC_ISR) & SONIC_INT_LCD)
-			break;
-	}
-	netif_dbg(lp, ifup, dev, "%s: CMD=%x, ISR=%x, i=%d\n", __func__,
-		  SONIC_READ(SONIC_CMD), SONIC_READ(SONIC_ISR), i);
+	sonic_quiesce(dev, SONIC_CR_LCAM);
 
 	/*
 	 * enable receiver, disable loopback
 	 * and enable all interrupts
 	 */
-	SONIC_WRITE(SONIC_CMD, SONIC_CR_RXEN | SONIC_CR_STP);
 	SONIC_WRITE(SONIC_RCR, SONIC_RCR_DEFAULT);
 	SONIC_WRITE(SONIC_TCR, SONIC_TCR_DEFAULT);
 	SONIC_WRITE(SONIC_ISR, 0x7fff);
 	SONIC_WRITE(SONIC_IMR, SONIC_IMR_DEFAULT);
-
-	cmd = SONIC_READ(SONIC_CMD);
-	if ((cmd & SONIC_CR_RXEN) == 0 || (cmd & SONIC_CR_STP) == 0)
-		printk(KERN_ERR "sonic_init: failed, status=%x\n", cmd);
+	SONIC_WRITE(SONIC_CMD, SONIC_CR_RXEN);
 
 	netif_dbg(lp, ifup, dev, "%s: new status=%x\n", __func__,
 		  SONIC_READ(SONIC_CMD));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/natsemi/sonic.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/natsemi/sonic.h
@@ -110,6 +110,9 @@
 #define SONIC_CR_TXP            0x0002
 #define SONIC_CR_HTX            0x0001
 
+#define SONIC_CR_ALL (SONIC_CR_LCAM | SONIC_CR_RRRA | \
+		      SONIC_CR_RXEN | SONIC_CR_TXP)
+
 /*
  * SONIC data configuration bits
  */
@@ -175,6 +178,7 @@
 #define SONIC_TCR_NCRS          0x0100
 #define SONIC_TCR_CRLS          0x0080
 #define SONIC_TCR_EXC           0x0040
+#define SONIC_TCR_OWC           0x0020
 #define SONIC_TCR_PMB           0x0008
 #define SONIC_TCR_FU            0x0004
 #define SONIC_TCR_BCM           0x0002
@@ -274,8 +278,9 @@
 #define SONIC_NUM_RDS   SONIC_NUM_RRS /* number of receive descriptors */
 #define SONIC_NUM_TDS   16            /* number of transmit descriptors */
 
-#define SONIC_RDS_MASK  (SONIC_NUM_RDS-1)
-#define SONIC_TDS_MASK  (SONIC_NUM_TDS-1)
+#define SONIC_RRS_MASK  (SONIC_NUM_RRS - 1)
+#define SONIC_RDS_MASK  (SONIC_NUM_RDS - 1)
+#define SONIC_TDS_MASK  (SONIC_NUM_TDS - 1)
 
 #define SONIC_RBSIZE	1520          /* size of one resource buffer */
 
@@ -312,8 +317,6 @@
 	u32 rda_laddr;              /* logical DMA address of RDA */
 	dma_addr_t rx_laddr[SONIC_NUM_RRS]; /* logical DMA addresses of rx skbuffs */
 	dma_addr_t tx_laddr[SONIC_NUM_TDS]; /* logical DMA addresses of tx skbuffs */
-	unsigned int rra_end;
-	unsigned int cur_rwp;
 	unsigned int cur_rx;
 	unsigned int cur_tx;           /* first unacked transmit packet */
 	unsigned int eol_rx;
@@ -322,6 +325,7 @@
 	int msg_enable;
 	struct device *device;         /* generic device */
 	struct net_device_stats stats;
+	spinlock_t lock;
 };
 
 #define TX_TIMEOUT (3 * HZ)
@@ -344,30 +348,30 @@
    as far as we can tell. */
 /* OpenBSD calls this "SWO".  I'd like to think that sonic_buf_put()
    is a much better name. */
-static inline void sonic_buf_put(void* base, int bitmode,
+static inline void sonic_buf_put(u16 *base, int bitmode,
 				 int offset, __u16 val)
 {
 	if (bitmode)
 #ifdef __BIG_ENDIAN
-		((__u16 *) base + (offset*2))[1] = val;
+		__raw_writew(val, base + (offset * 2) + 1);
 #else
-		((__u16 *) base + (offset*2))[0] = val;
+		__raw_writew(val, base + (offset * 2) + 0);
 #endif
 	else
-	 	((__u16 *) base)[offset] = val;
+		__raw_writew(val, base + (offset * 1) + 0);
 }
 
-static inline __u16 sonic_buf_get(void* base, int bitmode,
+static inline __u16 sonic_buf_get(u16 *base, int bitmode,
 				  int offset)
 {
 	if (bitmode)
 #ifdef __BIG_ENDIAN
-		return ((volatile __u16 *) base + (offset*2))[1];
+		return __raw_readw(base + (offset * 2) + 1);
 #else
-		return ((volatile __u16 *) base + (offset*2))[0];
+		return __raw_readw(base + (offset * 2) + 0);
 #endif
 	else
-		return ((volatile __u16 *) base)[offset];
+		return __raw_readw(base + (offset * 1) + 0);
 }
 
 /* Inlines that you should actually use for reading/writing DMA buffers */
@@ -447,6 +451,22 @@
 			     (entry * SIZEOF_SONIC_RR) + offset);
 }
 
+static inline u16 sonic_rr_addr(struct net_device *dev, int entry)
+{
+	struct sonic_local *lp = netdev_priv(dev);
+
+	return lp->rra_laddr +
+	       entry * SIZEOF_SONIC_RR * SONIC_BUS_SCALE(lp->dma_bitmode);
+}
+
+static inline u16 sonic_rr_entry(struct net_device *dev, u16 addr)
+{
+	struct sonic_local *lp = netdev_priv(dev);
+
+	return (addr - (u16)lp->rra_laddr) / (SIZEOF_SONIC_RR *
+					      SONIC_BUS_SCALE(lp->dma_bitmode));
+}
+
 static const char version[] =
     "sonic.c:v0.92 20.9.98 tsbogend@alpha.franken.de\n";
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/natsemi/xtsonic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/natsemi/xtsonic.c
@@ -120,7 +120,7 @@
 	.ndo_set_mac_address	= eth_mac_addr,
 };
 
-static int __init sonic_probe1(struct net_device *dev)
+static int sonic_probe1(struct net_device *dev)
 {
 	unsigned int silicon_revision;
 	struct sonic_local *lp = netdev_priv(dev);
@@ -265,11 +265,14 @@
 	sonic_msg_init(dev);
 
 	if ((err = register_netdev(dev)))
-		goto out1;
+		goto undo_probe1;
 
 	return 0;
 
-out1:
+undo_probe1:
+	dma_free_coherent(lp->device,
+			  SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
+			  lp->descriptors, lp->descriptors_laddr);
 	release_region(dev->base_addr, SONIC_MEM_SIZE);
 out:
 	free_netdev(dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/neterion/s2io.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/neterion/s2io.c
@@ -2375,7 +2375,7 @@
 			skb = s2io_txdl_getskb(&mac_control->fifos[i], txdp, j);
 			if (skb) {
 				swstats->mem_freed += skb->truesize;
-				dev_kfree_skb(skb);
+				dev_kfree_skb_irq(skb);
 				cnt++;
 			}
 		}
@@ -7122,9 +7122,8 @@
 		if (ret) {
 			DBG_PRINT(ERR_DBG, "%s: Out of memory in Open\n",
 				  dev->name);
-			s2io_reset(sp);
-			free_rx_buffers(sp);
-			return -ENOMEM;
+			ret = -ENOMEM;
+			goto err_fill_buff;
 		}
 		DBG_PRINT(INFO_DBG, "Buf in ring:%d is %d:\n", i,
 			  ring->rx_bufs_left);
@@ -7162,18 +7161,16 @@
 	/* Enable Rx Traffic and interrupts on the NIC */
 	if (start_nic(sp)) {
 		DBG_PRINT(ERR_DBG, "%s: Starting NIC failed\n", dev->name);
-		s2io_reset(sp);
-		free_rx_buffers(sp);
-		return -ENODEV;
+		ret = -ENODEV;
+		goto err_out;
 	}
 
 	/* Add interrupt service routine */
 	if (s2io_add_isr(sp) != 0) {
 		if (sp->config.intr_type == MSI_X)
 			s2io_rem_isr(sp);
-		s2io_reset(sp);
-		free_rx_buffers(sp);
-		return -ENODEV;
+		ret = -ENODEV;
+		goto err_out;
 	}
 
 	timer_setup(&sp->alarm_timer, s2io_alarm_handle, 0);
@@ -7193,6 +7190,20 @@
 	}
 
 	return 0;
+
+err_out:
+	if (config->napi) {
+		if (config->intr_type == MSI_X) {
+			for (i = 0; i < sp->config.rx_ring_num; i++)
+				napi_disable(&sp->mac_control.rings[i].napi);
+		} else {
+			napi_disable(&sp->napi);
+		}
+	}
+err_fill_buff:
+	s2io_reset(sp);
+	free_rx_buffers(sp);
+	return ret;
 }
 
 /**
@@ -7276,7 +7287,7 @@
 	int ring_no = ring_data->ring_no;
 	u16 l3_csum, l4_csum;
 	unsigned long long err = rxdp->Control_1 & RXD_T_CODE;
-	struct lro *uninitialized_var(lro);
+	struct lro *lro;
 	u8 err_mask;
 	struct swStat *swstats = &sp->mac_control.stats_info->sw_stat;
 
@@ -8565,7 +8576,7 @@
 			return;
 		}
 
-		if (s2io_set_mac_addr(netdev, netdev->dev_addr) == FAILURE) {
+		if (do_s2io_prog_unicast(netdev, netdev->dev_addr) == FAILURE) {
 			s2io_card_down(sp);
 			pr_err("Can't restore mac addr after reset.\n");
 			return;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/neterion/vxge/vxge-config.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/neterion/vxge/vxge-config.h
@@ -2045,7 +2045,7 @@
 	if ((level >= VXGE_ERR && VXGE_COMPONENT_LL & VXGE_DEBUG_ERR_MASK) ||  \
 	    (level >= VXGE_TRACE && VXGE_COMPONENT_LL & VXGE_DEBUG_TRACE_MASK))\
 		if ((mask & VXGE_DEBUG_MASK) == mask)			       \
-			printk(fmt "\n", __VA_ARGS__);			       \
+			printk(fmt "\n", ##__VA_ARGS__);		       \
 } while (0)
 #else
 #define vxge_debug_ll(level, mask, fmt, ...)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/neterion/vxge/vxge-main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/neterion/vxge/vxge-main.c
@@ -3524,13 +3524,13 @@
 
 	kfree(vdev->vpaths);
 
-	/* we are safe to free it now */
-	free_netdev(dev);
-
 	vxge_debug_init(vdev->level_trace, "%s: ethernet device unregistered",
 			buf);
 	vxge_debug_entryexit(vdev->level_trace,	"%s: %s:%d  Exiting...", buf,
 			     __func__, __LINE__);
+
+	/* we are safe to free it now */
+	free_netdev(dev);
 }
 
 /*
@@ -4197,6 +4197,9 @@
 	return ret;
 }
 
+#define VXGE_PXE_FIRMWARE "vxge/X3fw-pxe.ncf"
+#define VXGE_FIRMWARE "vxge/X3fw.ncf"
+
 static int vxge_probe_fw_update(struct vxgedev *vdev)
 {
 	u32 maj, min, bld;
@@ -4239,9 +4242,9 @@
 			}
 	}
 	if (gpxe)
-		fw_name = "vxge/X3fw-pxe.ncf";
+		fw_name = VXGE_PXE_FIRMWARE;
 	else
-		fw_name = "vxge/X3fw.ncf";
+		fw_name = VXGE_FIRMWARE;
 
 	ret = vxge_fw_upgrade(vdev, fw_name, 0);
 	/* -EINVAL and -ENOENT are not fatal errors for flashing firmware on
@@ -4846,3 +4849,5 @@
 }
 module_init(vxge_starter);
 module_exit(vxge_closer);
+MODULE_FIRMWARE(VXGE_PXE_FIRMWARE);
+MODULE_FIRMWARE(VXGE_FIRMWARE);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/neterion/vxge/vxge-main.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/neterion/vxge/vxge-main.h
@@ -452,49 +452,49 @@
 
 #if (VXGE_DEBUG_LL_CONFIG & VXGE_DEBUG_MASK)
 #define vxge_debug_ll_config(level, fmt, ...) \
-	vxge_debug_ll(level, VXGE_DEBUG_LL_CONFIG, fmt, __VA_ARGS__)
+	vxge_debug_ll(level, VXGE_DEBUG_LL_CONFIG, fmt, ##__VA_ARGS__)
 #else
 #define vxge_debug_ll_config(level, fmt, ...)
 #endif
 
 #if (VXGE_DEBUG_INIT & VXGE_DEBUG_MASK)
 #define vxge_debug_init(level, fmt, ...) \
-	vxge_debug_ll(level, VXGE_DEBUG_INIT, fmt, __VA_ARGS__)
+	vxge_debug_ll(level, VXGE_DEBUG_INIT, fmt, ##__VA_ARGS__)
 #else
 #define vxge_debug_init(level, fmt, ...)
 #endif
 
 #if (VXGE_DEBUG_TX & VXGE_DEBUG_MASK)
 #define vxge_debug_tx(level, fmt, ...) \
-	vxge_debug_ll(level, VXGE_DEBUG_TX, fmt, __VA_ARGS__)
+	vxge_debug_ll(level, VXGE_DEBUG_TX, fmt, ##__VA_ARGS__)
 #else
 #define vxge_debug_tx(level, fmt, ...)
 #endif
 
 #if (VXGE_DEBUG_RX & VXGE_DEBUG_MASK)
 #define vxge_debug_rx(level, fmt, ...) \
-	vxge_debug_ll(level, VXGE_DEBUG_RX, fmt, __VA_ARGS__)
+	vxge_debug_ll(level, VXGE_DEBUG_RX, fmt, ##__VA_ARGS__)
 #else
 #define vxge_debug_rx(level, fmt, ...)
 #endif
 
 #if (VXGE_DEBUG_MEM & VXGE_DEBUG_MASK)
 #define vxge_debug_mem(level, fmt, ...) \
-	vxge_debug_ll(level, VXGE_DEBUG_MEM, fmt, __VA_ARGS__)
+	vxge_debug_ll(level, VXGE_DEBUG_MEM, fmt, ##__VA_ARGS__)
 #else
 #define vxge_debug_mem(level, fmt, ...)
 #endif
 
 #if (VXGE_DEBUG_ENTRYEXIT & VXGE_DEBUG_MASK)
 #define vxge_debug_entryexit(level, fmt, ...) \
-	vxge_debug_ll(level, VXGE_DEBUG_ENTRYEXIT, fmt, __VA_ARGS__)
+	vxge_debug_ll(level, VXGE_DEBUG_ENTRYEXIT, fmt, ##__VA_ARGS__)
 #else
 #define vxge_debug_entryexit(level, fmt, ...)
 #endif
 
 #if (VXGE_DEBUG_INTR & VXGE_DEBUG_MASK)
 #define vxge_debug_intr(level, fmt, ...) \
-	vxge_debug_ll(level, VXGE_DEBUG_INTR, fmt, __VA_ARGS__)
+	vxge_debug_ll(level, VXGE_DEBUG_INTR, fmt, ##__VA_ARGS__)
 #else
 #define vxge_debug_intr(level, fmt, ...)
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/neterion/vxge/vxge-traffic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/neterion/vxge/vxge-traffic.c
@@ -30,8 +30,6 @@
  */
 enum vxge_hw_status vxge_hw_vpath_intr_enable(struct __vxge_hw_vpath_handle *vp)
 {
-	u64 val64;
-
 	struct __vxge_hw_virtualpath *vpath;
 	struct vxge_hw_vpath_reg __iomem *vp_reg;
 	enum vxge_hw_status status = VXGE_HW_OK;
@@ -84,7 +82,7 @@
 	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
 			&vp_reg->xgmac_vp_int_status);
 
-	val64 = readq(&vp_reg->vpath_general_int_status);
+	readq(&vp_reg->vpath_general_int_status);
 
 	/* Mask unwanted interrupts */
 
@@ -157,8 +155,6 @@
 enum vxge_hw_status vxge_hw_vpath_intr_disable(
 			struct __vxge_hw_vpath_handle *vp)
 {
-	u64 val64;
-
 	struct __vxge_hw_virtualpath *vpath;
 	enum vxge_hw_status status = VXGE_HW_OK;
 	struct vxge_hw_vpath_reg __iomem *vp_reg;
@@ -179,8 +175,6 @@
 		(u32)VXGE_HW_INTR_MASK_ALL,
 		&vp_reg->vpath_general_int_mask);
 
-	val64 = VXGE_HW_TIM_CLR_INT_EN_VP(1 << (16 - vpath->vp_id));
-
 	writeq(VXGE_HW_INTR_MASK_ALL, &vp_reg->kdfcctl_errors_mask);
 
 	__vxge_hw_pio_mem_write32_upper((u32)VXGE_HW_INTR_MASK_ALL,
@@ -487,9 +481,7 @@
  */
 void vxge_hw_device_flush_io(struct __vxge_hw_device *hldev)
 {
-	u32 val32;
-
-	val32 = readl(&hldev->common_reg->titan_general_int_status);
+	readl(&hldev->common_reg->titan_general_int_status);
 }
 
 /**
@@ -1716,8 +1708,8 @@
 enum vxge_hw_status
 vxge_hw_vpath_mac_addr_add(
 	struct __vxge_hw_vpath_handle *vp,
-	u8 (macaddr)[ETH_ALEN],
-	u8 (macaddr_mask)[ETH_ALEN],
+	u8 *macaddr,
+	u8 *macaddr_mask,
 	enum vxge_hw_vpath_mac_addr_add_mode duplicate_mode)
 {
 	u32 i;
@@ -1779,8 +1771,8 @@
 enum vxge_hw_status
 vxge_hw_vpath_mac_addr_get(
 	struct __vxge_hw_vpath_handle *vp,
-	u8 (macaddr)[ETH_ALEN],
-	u8 (macaddr_mask)[ETH_ALEN])
+	u8 *macaddr,
+	u8 *macaddr_mask)
 {
 	u32 i;
 	u64 data1 = 0ULL;
@@ -1831,8 +1823,8 @@
 enum vxge_hw_status
 vxge_hw_vpath_mac_addr_get_next(
 	struct __vxge_hw_vpath_handle *vp,
-	u8 (macaddr)[ETH_ALEN],
-	u8 (macaddr_mask)[ETH_ALEN])
+	u8 *macaddr,
+	u8 *macaddr_mask)
 {
 	u32 i;
 	u64 data1 = 0ULL;
@@ -1884,8 +1876,8 @@
 enum vxge_hw_status
 vxge_hw_vpath_mac_addr_delete(
 	struct __vxge_hw_vpath_handle *vp,
-	u8 (macaddr)[ETH_ALEN],
-	u8 (macaddr_mask)[ETH_ALEN])
+	u8 *macaddr,
+	u8 *macaddr_mask)
 {
 	u32 i;
 	u64 data1 = 0ULL;
@@ -2375,7 +2367,6 @@
 	u8 t_code;
 	enum vxge_hw_status status = VXGE_HW_OK;
 	void *first_rxdh;
-	u64 val64 = 0;
 	int new_count = 0;
 
 	ring->cmpl_cnt = 0;
@@ -2403,8 +2394,7 @@
 			}
 			writeq(VXGE_HW_PRC_RXD_DOORBELL_NEW_QW_CNT(new_count),
 				&ring->vp_reg->prc_rxd_doorbell);
-			val64 =
-			  readl(&ring->common_reg->titan_general_int_status);
+			readl(&ring->common_reg->titan_general_int_status);
 			ring->doorbell_cnt = 0;
 		}
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/netronome/nfp/abm/cls.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/netronome/nfp/abm/cls.c
@@ -176,10 +176,8 @@
 	u8 mask, val;
 	int err;
 
-	if (!nfp_abm_u32_check_knode(alink->abm, knode, proto, extack)) {
-		err = -EOPNOTSUPP;
+	if (!nfp_abm_u32_check_knode(alink->abm, knode, proto, extack))
 		goto err_delete;
-	}
 
 	tos_off = proto == htons(ETH_P_IP) ? 16 : 20;
 
@@ -200,18 +198,14 @@
 		if ((iter->val & cmask) == (val & cmask) &&
 		    iter->band != knode->res->classid) {
 			NL_SET_ERR_MSG_MOD(extack, "conflict with already offloaded filter");
-			err = -EOPNOTSUPP;
 			goto err_delete;
 		}
 	}
 
 	if (!match) {
 		match = kzalloc(sizeof(*match), GFP_KERNEL);
-		if (!match) {
-			err = -ENOMEM;
-			goto err_delete;
-		}
-
+		if (!match)
+			return -ENOMEM;
 		list_add(&match->list, &alink->dscp_map);
 	}
 	match->handle = knode->handle;
@@ -227,7 +221,7 @@
 
 err_delete:
 	nfp_abm_u32_knode_delete(alink, knode);
-	return err;
+	return -EOPNOTSUPP;
 }
 
 static int nfp_abm_setup_tc_block_cb(enum tc_setup_type type,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/netronome/nfp/abm/main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/netronome/nfp/abm/main.c
@@ -283,6 +283,7 @@
 	if (!nfp_nsp_has_hwinfo_lookup(nsp)) {
 		nfp_warn(pf->cpp, "NSP doesn't support PF MAC generation\n");
 		eth_hw_addr_random(nn->dp.netdev);
+		nfp_nsp_close(nsp);
 		return;
 	}
 
@@ -332,8 +333,10 @@
 		goto err_free_alink;
 
 	alink->prio_map = kzalloc(abm->prio_map_len, GFP_KERNEL);
-	if (!alink->prio_map)
+	if (!alink->prio_map) {
+		err = -ENOMEM;
 		goto err_free_alink;
+	}
 
 	/* This is a multi-host app, make sure MAC/PHY is up, but don't
 	 * make the MAC/PHY state follow the state of any of the ports.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/netronome/nfp/bpf/cmsg.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/netronome/nfp/bpf/cmsg.c
@@ -20,6 +20,8 @@
 	struct sk_buff *skb;
 
 	skb = nfp_app_ctrl_msg_alloc(bpf->app, size, GFP_KERNEL);
+	if (!skb)
+		return NULL;
 	skb_put(skb, size);
 
 	return skb;
@@ -454,6 +456,7 @@
 			dev_consume_skb_any(skb);
 		else
 			dev_kfree_skb_any(skb);
+		return;
 	}
 
 	nfp_ccm_rx(&bpf->ccm, skb);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/netronome/nfp/bpf/main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/netronome/nfp/bpf/main.c
@@ -182,15 +182,21 @@
 nfp_bpf_check_mtu(struct nfp_app *app, struct net_device *netdev, int new_mtu)
 {
 	struct nfp_net *nn = netdev_priv(netdev);
-	unsigned int max_mtu;
+	struct nfp_bpf_vnic *bv;
+	struct bpf_prog *prog;
 
 	if (~nn->dp.ctrl & NFP_NET_CFG_CTRL_BPF)
 		return 0;
 
-	max_mtu = nn_readb(nn, NFP_NET_CFG_BPF_INL_MTU) * 64 - 32;
-	if (new_mtu > max_mtu) {
-		nn_info(nn, "BPF offload active, MTU over %u not supported\n",
-			max_mtu);
+	if (nn->xdp_hw.prog) {
+		prog = nn->xdp_hw.prog;
+	} else {
+		bv = nn->app_priv;
+		prog = bv->tc_prog;
+	}
+
+	if (nfp_bpf_offload_check_mtu(nn, prog, new_mtu)) {
+		nn_info(nn, "BPF offload active, potential packet access beyond hardware packet boundary");
 		return -EBUSY;
 	}
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/netronome/nfp/bpf/main.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/netronome/nfp/bpf/main.h
@@ -560,6 +560,8 @@
 void nfp_bpf_jit_prepare(struct nfp_prog *nfp_prog);
 int nfp_bpf_jit(struct nfp_prog *prog);
 bool nfp_bpf_supported_opcode(u8 code);
+bool nfp_bpf_offload_check_mtu(struct nfp_net *nn, struct bpf_prog *prog,
+			       unsigned int mtu);
 
 int nfp_verify_insn(struct bpf_verifier_env *env, int insn_idx,
 		    int prev_insn_idx);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/netronome/nfp/bpf/offload.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/netronome/nfp/bpf/offload.c
@@ -454,7 +454,8 @@
 	map_id_full = be64_to_cpu(cbe->map_ptr);
 	map_id = map_id_full;
 
-	if (len < sizeof(struct cmsg_bpf_event) + pkt_size + data_size)
+	if (size_add(pkt_size, data_size) > INT_MAX ||
+	    len < sizeof(struct cmsg_bpf_event) + pkt_size + data_size)
 		return -EINVAL;
 	if (cbe->hdr.ver != NFP_CCM_ABI_VERSION)
 		return -EINVAL;
@@ -477,19 +478,28 @@
 	return 0;
 }
 
+bool nfp_bpf_offload_check_mtu(struct nfp_net *nn, struct bpf_prog *prog,
+			       unsigned int mtu)
+{
+	unsigned int fw_mtu, pkt_off;
+
+	fw_mtu = nn_readb(nn, NFP_NET_CFG_BPF_INL_MTU) * 64 - 32;
+	pkt_off = min(prog->aux->max_pkt_offset, mtu);
+
+	return fw_mtu < pkt_off;
+}
+
 static int
 nfp_net_bpf_load(struct nfp_net *nn, struct bpf_prog *prog,
 		 struct netlink_ext_ack *extack)
 {
 	struct nfp_prog *nfp_prog = prog->aux->offload->dev_priv;
-	unsigned int fw_mtu, pkt_off, max_stack, max_prog_len;
+	unsigned int max_stack, max_prog_len;
 	dma_addr_t dma_addr;
 	void *img;
 	int err;
 
-	fw_mtu = nn_readb(nn, NFP_NET_CFG_BPF_INL_MTU) * 64 - 32;
-	pkt_off = min(prog->aux->max_pkt_offset, nn->dp.netdev->mtu);
-	if (fw_mtu < pkt_off) {
+	if (nfp_bpf_offload_check_mtu(nn, prog, nn->dp.netdev->mtu)) {
 		NL_SET_ERR_MSG_MOD(extack, "BPF offload not supported with potential packet access beyond HW packet split boundary");
 		return -EOPNOTSUPP;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/netronome/nfp/flower/lag_conf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/netronome/nfp/flower/lag_conf.c
@@ -308,6 +308,11 @@
 
 		acti_netdevs = kmalloc_array(entry->slave_cnt,
 					     sizeof(*acti_netdevs), GFP_KERNEL);
+		if (!acti_netdevs) {
+			schedule_delayed_work(&lag->work,
+					      NFP_FL_LAG_DELAY);
+			continue;
+		}
 
 		/* Include sanity check in the loop. It may be that a bond has
 		 * changed between processing the last notification and the
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/netronome/nfp/flower/main.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/netronome/nfp/flower/main.h
@@ -164,6 +164,7 @@
  * @qos_rate_limiters:	Current active qos rate limiters
  * @qos_stats_lock:	Lock on qos stats updates
  * @pre_tun_rule_cnt:	Number of pre-tunnel rules offloaded
+ * @merge_table:	Hash table to store merged flows
  */
 struct nfp_flower_priv {
 	struct nfp_app *app;
@@ -196,6 +197,7 @@
 	unsigned int qos_rate_limiters;
 	spinlock_t qos_stats_lock; /* Protect the qos stats */
 	int pre_tun_rule_cnt;
+	struct rhashtable merge_table;
 };
 
 /**
@@ -310,6 +312,12 @@
 };
 
 extern const struct rhashtable_params nfp_flower_table_params;
+extern const struct rhashtable_params merge_table_params;
+
+struct nfp_merge_info {
+	u64 parent_ctx;
+	struct rhash_head ht_node;
+};
 
 struct nfp_fl_stats_frame {
 	__be32 stats_con_id;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/netronome/nfp/flower/metadata.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/netronome/nfp/flower/metadata.c
@@ -65,17 +65,17 @@
 	freed_stats_id = priv->stats_ring_size;
 	/* Check for unallocated entries first. */
 	if (priv->stats_ids.init_unalloc > 0) {
-		if (priv->active_mem_unit == priv->total_mem_units) {
-			priv->stats_ids.init_unalloc--;
-			priv->active_mem_unit = 0;
-		}
-
 		*stats_context_id =
 			FIELD_PREP(NFP_FL_STAT_ID_STAT,
 				   priv->stats_ids.init_unalloc - 1) |
 			FIELD_PREP(NFP_FL_STAT_ID_MU_NUM,
 				   priv->active_mem_unit);
-		priv->active_mem_unit++;
+
+		if (++priv->active_mem_unit == priv->total_mem_units) {
+			priv->stats_ids.init_unalloc--;
+			priv->active_mem_unit = 0;
+		}
+
 		return 0;
 	}
 
@@ -327,8 +327,14 @@
 		goto err_free_ctx_entry;
 	}
 
+	/* Do net allocate a mask-id for pre_tun_rules. These flows are used to
+	 * configure the pre_tun table and are never actually send to the
+	 * firmware as an add-flow message. This causes the mask-id allocation
+	 * on the firmware to get out of sync if allocated here.
+	 */
 	new_mask_id = 0;
-	if (!nfp_check_mask_add(app, nfp_flow->mask_data,
+	if (!nfp_flow->pre_tun_rule.dev &&
+	    !nfp_check_mask_add(app, nfp_flow->mask_data,
 				nfp_flow->meta.mask_len,
 				&nfp_flow->meta.flags, &new_mask_id)) {
 		NL_SET_ERR_MSG_MOD(extack, "invalid entry: cannot allocate a new mask id");
@@ -359,7 +365,8 @@
 			goto err_remove_mask;
 		}
 
-		if (!nfp_check_mask_remove(app, nfp_flow->mask_data,
+		if (!nfp_flow->pre_tun_rule.dev &&
+		    !nfp_check_mask_remove(app, nfp_flow->mask_data,
 					   nfp_flow->meta.mask_len,
 					   NULL, &new_mask_id)) {
 			NL_SET_ERR_MSG_MOD(extack, "invalid entry: cannot release mask id");
@@ -374,8 +381,10 @@
 	return 0;
 
 err_remove_mask:
-	nfp_check_mask_remove(app, nfp_flow->mask_data, nfp_flow->meta.mask_len,
-			      NULL, &new_mask_id);
+	if (!nfp_flow->pre_tun_rule.dev)
+		nfp_check_mask_remove(app, nfp_flow->mask_data,
+				      nfp_flow->meta.mask_len,
+				      NULL, &new_mask_id);
 err_remove_rhash:
 	WARN_ON_ONCE(rhashtable_remove_fast(&priv->stats_ctx_table,
 					    &ctx_entry->ht_node,
@@ -406,9 +415,10 @@
 
 	__nfp_modify_flow_metadata(priv, nfp_flow);
 
-	nfp_check_mask_remove(app, nfp_flow->mask_data,
-			      nfp_flow->meta.mask_len, &nfp_flow->meta.flags,
-			      &new_mask_id);
+	if (!nfp_flow->pre_tun_rule.dev)
+		nfp_check_mask_remove(app, nfp_flow->mask_data,
+				      nfp_flow->meta.mask_len, &nfp_flow->meta.flags,
+				      &new_mask_id);
 
 	/* Update flow payload with mask ids. */
 	nfp_flow->unmasked_data[NFP_FL_MASK_ID_LOCATION] = new_mask_id;
@@ -480,6 +490,12 @@
 	.automatic_shrinking	= true,
 };
 
+const struct rhashtable_params merge_table_params = {
+	.key_offset	= offsetof(struct nfp_merge_info, parent_ctx),
+	.head_offset	= offsetof(struct nfp_merge_info, ht_node),
+	.key_len	= sizeof(u64),
+};
+
 int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count,
 			     unsigned int host_num_mems)
 {
@@ -496,6 +512,10 @@
 	if (err)
 		goto err_free_flow_table;
 
+	err = rhashtable_init(&priv->merge_table, &merge_table_params);
+	if (err)
+		goto err_free_stats_ctx_table;
+
 	get_random_bytes(&priv->mask_id_seed, sizeof(priv->mask_id_seed));
 
 	/* Init ring buffer and unallocated mask_ids. */
@@ -503,7 +523,7 @@
 		kmalloc_array(NFP_FLOWER_MASK_ENTRY_RS,
 			      NFP_FLOWER_MASK_ELEMENT_RS, GFP_KERNEL);
 	if (!priv->mask_ids.mask_id_free_list.buf)
-		goto err_free_stats_ctx_table;
+		goto err_free_merge_table;
 
 	priv->mask_ids.init_unallocated = NFP_FLOWER_MASK_ENTRY_RS - 1;
 
@@ -540,6 +560,8 @@
 	kfree(priv->mask_ids.last_used);
 err_free_mask_id:
 	kfree(priv->mask_ids.mask_id_free_list.buf);
+err_free_merge_table:
+	rhashtable_destroy(&priv->merge_table);
 err_free_stats_ctx_table:
 	rhashtable_destroy(&priv->stats_ctx_table);
 err_free_flow_table:
@@ -558,6 +580,8 @@
 				    nfp_check_rhashtable_empty, NULL);
 	rhashtable_free_and_destroy(&priv->stats_ctx_table,
 				    nfp_check_rhashtable_empty, NULL);
+	rhashtable_free_and_destroy(&priv->merge_table,
+				    nfp_check_rhashtable_empty, NULL);
 	kvfree(priv->stats);
 	kfree(priv->mask_ids.mask_id_free_list.buf);
 	kfree(priv->mask_ids.last_used);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/netronome/nfp/flower/offload.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/netronome/nfp/flower/offload.c
@@ -923,6 +923,8 @@
 	struct netlink_ext_ack *extack = NULL;
 	struct nfp_fl_payload *merge_flow;
 	struct nfp_fl_key_ls merge_key_ls;
+	struct nfp_merge_info *merge_info;
+	u64 parent_ctx = 0;
 	int err;
 
 	ASSERT_RTNL();
@@ -933,6 +935,15 @@
 	    nfp_flower_is_merge_flow(sub_flow2))
 		return -EINVAL;
 
+	/* check if the two flows are already merged */
+	parent_ctx = (u64)(be32_to_cpu(sub_flow1->meta.host_ctx_id)) << 32;
+	parent_ctx |= (u64)(be32_to_cpu(sub_flow2->meta.host_ctx_id));
+	if (rhashtable_lookup_fast(&priv->merge_table,
+				   &parent_ctx, merge_table_params)) {
+		nfp_flower_cmsg_warn(app, "The two flows are already merged.\n");
+		return 0;
+	}
+
 	err = nfp_flower_can_merge(sub_flow1, sub_flow2);
 	if (err)
 		return err;
@@ -974,16 +985,33 @@
 	if (err)
 		goto err_release_metadata;
 
+	merge_info = kmalloc(sizeof(*merge_info), GFP_KERNEL);
+	if (!merge_info) {
+		err = -ENOMEM;
+		goto err_remove_rhash;
+	}
+	merge_info->parent_ctx = parent_ctx;
+	err = rhashtable_insert_fast(&priv->merge_table, &merge_info->ht_node,
+				     merge_table_params);
+	if (err)
+		goto err_destroy_merge_info;
+
 	err = nfp_flower_xmit_flow(app, merge_flow,
 				   NFP_FLOWER_CMSG_TYPE_FLOW_MOD);
 	if (err)
-		goto err_remove_rhash;
+		goto err_remove_merge_info;
 
 	merge_flow->in_hw = true;
 	sub_flow1->in_hw = false;
 
 	return 0;
 
+err_remove_merge_info:
+	WARN_ON_ONCE(rhashtable_remove_fast(&priv->merge_table,
+					    &merge_info->ht_node,
+					    merge_table_params));
+err_destroy_merge_info:
+	kfree(merge_info);
 err_remove_rhash:
 	WARN_ON_ONCE(rhashtable_remove_fast(&priv->flow_table,
 					    &merge_flow->fl_node,
@@ -1211,7 +1239,9 @@
 {
 	struct nfp_flower_priv *priv = app->priv;
 	struct nfp_fl_payload_link *link, *temp;
+	struct nfp_merge_info *merge_info;
 	struct nfp_fl_payload *origin;
+	u64 parent_ctx = 0;
 	bool mod = false;
 	int err;
 
@@ -1248,8 +1278,22 @@
 err_free_links:
 	/* Clean any links connected with the merged flow. */
 	list_for_each_entry_safe(link, temp, &merge_flow->linked_flows,
-				 merge_flow.list)
+				 merge_flow.list) {
+		u32 ctx_id = be32_to_cpu(link->sub_flow.flow->meta.host_ctx_id);
+
+		parent_ctx = (parent_ctx << 32) | (u64)(ctx_id);
 		nfp_flower_unlink_flow(link);
+	}
+
+	merge_info = rhashtable_lookup_fast(&priv->merge_table,
+					    &parent_ctx,
+					    merge_table_params);
+	if (merge_info) {
+		WARN_ON_ONCE(rhashtable_remove_fast(&priv->merge_table,
+						    &merge_info->ht_node,
+						    merge_table_params));
+		kfree(merge_info);
+	}
 
 	kfree(merge_flow->action_data);
 	kfree(merge_flow->mask_data);
@@ -1368,7 +1412,8 @@
 		ctx_id = be32_to_cpu(sub_flow->meta.host_ctx_id);
 		priv->stats[ctx_id].pkts += pkts;
 		priv->stats[ctx_id].bytes += bytes;
-		max_t(u64, priv->stats[ctx_id].used, used);
+		priv->stats[ctx_id].used = max_t(u64, used,
+						 priv->stats[ctx_id].used);
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
@@ -588,12 +588,12 @@
 			  int port, bool mod)
 {
 	struct nfp_flower_priv *priv = app->priv;
-	int ida_idx = NFP_MAX_MAC_INDEX, err;
 	struct nfp_tun_offloaded_mac *entry;
+	int ida_idx = -1, err;
 	u16 nfp_mac_idx = 0;
 
 	entry = nfp_tunnel_lookup_offloaded_macs(app, netdev->dev_addr);
-	if (entry && nfp_tunnel_is_mac_idx_global(entry->index)) {
+	if (entry && (nfp_tunnel_is_mac_idx_global(entry->index) || netif_is_lag_port(netdev))) {
 		if (entry->bridge_count ||
 		    !nfp_flower_is_supported_bridge(netdev)) {
 			nfp_tunnel_offloaded_macs_inc_ref_and_link(entry,
@@ -663,7 +663,7 @@
 err_free_entry:
 	kfree(entry);
 err_free_ida:
-	if (ida_idx != NFP_MAX_MAC_INDEX)
+	if (ida_idx != -1)
 		ida_simple_remove(&priv->tun.mac_off_ids, ida_idx);
 
 	return err;
@@ -677,6 +677,7 @@
 	struct nfp_flower_repr_priv *repr_priv;
 	struct nfp_tun_offloaded_mac *entry;
 	struct nfp_repr *repr;
+	u16 nfp_mac_idx;
 	int ida_idx;
 
 	entry = nfp_tunnel_lookup_offloaded_macs(app, mac);
@@ -695,8 +696,6 @@
 		entry->bridge_count--;
 
 		if (!entry->bridge_count && entry->ref_count) {
-			u16 nfp_mac_idx;
-
 			nfp_mac_idx = entry->index & ~NFP_TUN_PRE_TUN_IDX_BIT;
 			if (__nfp_tunnel_offload_mac(app, mac, nfp_mac_idx,
 						     false)) {
@@ -712,7 +711,6 @@
 
 	/* If MAC is now used by 1 repr set the offloaded MAC index to port. */
 	if (entry->ref_count == 1 && list_is_singular(&entry->repr_list)) {
-		u16 nfp_mac_idx;
 		int port, err;
 
 		repr_priv = list_first_entry(&entry->repr_list,
@@ -740,8 +738,14 @@
 	WARN_ON_ONCE(rhashtable_remove_fast(&priv->tun.offloaded_macs,
 					    &entry->ht_node,
 					    offloaded_macs_params));
+
+	if (nfp_flower_is_supported_bridge(netdev))
+		nfp_mac_idx = entry->index & ~NFP_TUN_PRE_TUN_IDX_BIT;
+	else
+		nfp_mac_idx = entry->index;
+
 	/* If MAC has global ID then extract and free the ida entry. */
-	if (nfp_tunnel_is_mac_idx_global(entry->index)) {
+	if (nfp_tunnel_is_mac_idx_global(nfp_mac_idx)) {
 		ida_idx = nfp_tunnel_get_ida_from_global_mac_idx(entry->index);
 		ida_simple_remove(&priv->tun.mac_off_ids, ida_idx);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/netronome/nfp/nfp_asm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/netronome/nfp/nfp_asm.c
@@ -196,7 +196,7 @@
 	}
 
 	reg->dst_lmextn = swreg_lmextn(dst);
-	reg->src_lmextn = swreg_lmextn(lreg) | swreg_lmextn(rreg);
+	reg->src_lmextn = swreg_lmextn(lreg) || swreg_lmextn(rreg);
 
 	return 0;
 }
@@ -277,7 +277,7 @@
 	}
 
 	reg->dst_lmextn = swreg_lmextn(dst);
-	reg->src_lmextn = swreg_lmextn(lreg) | swreg_lmextn(rreg);
+	reg->src_lmextn = swreg_lmextn(lreg) || swreg_lmextn(rreg);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/netronome/nfp/nfp_net.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/netronome/nfp/nfp_net.h
@@ -557,7 +557,6 @@
  * @exn_name:           Name for Exception interrupt
  * @shared_handler:     Handler for shared interrupts
  * @shared_name:        Name for shared interrupt
- * @me_freq_mhz:        ME clock_freq (MHz)
  * @reconfig_lock:	Protects @reconfig_posted, @reconfig_timer_active,
  *			@reconfig_sync_present and HW reconfiguration request
  *			regs/machinery from async requests (sync must take
@@ -639,8 +638,6 @@
 	irq_handler_t shared_handler;
 	char shared_name[IFNAMSIZ + 8];
 
-	u32 me_freq_mhz;
-
 	bool link_up;
 	spinlock_t link_status_lock;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -2626,8 +2626,8 @@
 
 	snprintf(r_vec->name, sizeof(r_vec->name),
 		 "%s-rxtx-%d", nfp_net_name(nn), idx);
-	err = request_irq(r_vec->irq_vector, r_vec->handler, 0, r_vec->name,
-			  r_vec);
+	err = request_irq(r_vec->irq_vector, r_vec->handler, IRQF_NO_AUTOEN,
+			  r_vec->name, r_vec);
 	if (err) {
 		if (nn->dp.netdev)
 			netif_napi_del(&r_vec->napi);
@@ -2637,7 +2637,6 @@
 		nn_err(nn, "Error requesting IRQ %d\n", r_vec->irq_vector);
 		return err;
 	}
-	disable_irq(r_vec->irq_vector);
 
 	irq_set_affinity_hint(r_vec->irq_vector, &r_vec->affinity_mask);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
@@ -273,6 +273,8 @@
 	port = nfp_port_from_netdev(netdev);
 	eth_port = nfp_port_get_eth_port(port);
 	if (eth_port) {
+		ethtool_link_ksettings_add_link_mode(cmd, supported, Pause);
+		ethtool_link_ksettings_add_link_mode(cmd, advertising, Pause);
 		cmd->base.autoneg = eth_port->aneg != NFP_ANEG_DISABLED ?
 			AUTONEG_ENABLE : AUTONEG_DISABLE;
 		nfp_net_set_fec_link_mode(eth_port, cmd);
@@ -731,8 +733,8 @@
 	struct nfp_eth_table_port *eth_port;
 	struct nfp_port *port;
 
-	param->active_fec = ETHTOOL_FEC_NONE_BIT;
-	param->fec = ETHTOOL_FEC_NONE_BIT;
+	param->active_fec = ETHTOOL_FEC_NONE;
+	param->fec = ETHTOOL_FEC_NONE;
 
 	port = nfp_port_from_netdev(netdev);
 	eth_port = nfp_port_get_eth_port(port);
@@ -1125,6 +1127,11 @@
 	u8 data;
 
 	port = nfp_port_from_netdev(netdev);
+	if (!port)
+		return -EOPNOTSUPP;
+
+	/* update port state to get latest interface */
+	set_bit(NFP_PORT_CHANGED, &port->flags);
 	eth_port = nfp_port_get_eth_port(port);
 	if (!eth_port)
 		return -EOPNOTSUPP;
@@ -1267,7 +1274,7 @@
 	 * ME timestamp ticks.  There are 16 ME clock cycles for each timestamp
 	 * count.
 	 */
-	factor = nn->me_freq_mhz / 16;
+	factor = nn->tlv_caps.me_freq_mhz / 16;
 
 	/* Each pair of (usecs, max_frames) fields specifies that interrupts
 	 * should be coalesced until
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c
@@ -542,11 +542,13 @@
 	const u32 barcfg_msix_general =
 		NFP_PCIE_BAR_PCIE2CPP_MapType(
 			NFP_PCIE_BAR_PCIE2CPP_MapType_GENERAL) |
-		NFP_PCIE_BAR_PCIE2CPP_LengthSelect_32BIT;
+		NFP_PCIE_BAR_PCIE2CPP_LengthSelect(
+			NFP_PCIE_BAR_PCIE2CPP_LengthSelect_32BIT);
 	const u32 barcfg_msix_xpb =
 		NFP_PCIE_BAR_PCIE2CPP_MapType(
 			NFP_PCIE_BAR_PCIE2CPP_MapType_BULK) |
-		NFP_PCIE_BAR_PCIE2CPP_LengthSelect_32BIT |
+		NFP_PCIE_BAR_PCIE2CPP_LengthSelect(
+			NFP_PCIE_BAR_PCIE2CPP_LengthSelect_32BIT) |
 		NFP_PCIE_BAR_PCIE2CPP_Target_BaseAddress(
 			NFP_CPP_TARGET_ISLAND_XPB);
 	const u32 barcfg_explicit[4] = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cppcore.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_cppcore.c
@@ -803,8 +803,10 @@
 		return -ENOMEM;
 
 	cache = kzalloc(sizeof(*cache), GFP_KERNEL);
-	if (!cache)
+	if (!cache) {
+		nfp_cpp_area_free(area);
 		return -ENOMEM;
+	}
 
 	cache->id = 0;
 	cache->addr = 0;
@@ -872,7 +874,6 @@
 	}
 
 	/* Adjust the start address to be cache size aligned */
-	cache->id = id;
 	cache->addr = addr & ~(u64)(cache->size - 1);
 
 	/* Re-init to the new ID and address */
@@ -892,6 +893,8 @@
 		return NULL;
 	}
 
+	cache->id = id;
+
 exit:
 	/* Adjust offset */
 	*offset = addr - cache->addr;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/ni/nixge.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/ni/nixge.c
@@ -249,25 +249,26 @@
 	struct sk_buff *skb;
 	int i;
 
-	for (i = 0; i < RX_BD_NUM; i++) {
-		phys_addr = nixge_hw_dma_bd_get_addr(&priv->rx_bd_v[i],
-						     phys);
-
-		dma_unmap_single(ndev->dev.parent, phys_addr,
-				 NIXGE_MAX_JUMBO_FRAME_SIZE,
-				 DMA_FROM_DEVICE);
-
-		skb = (struct sk_buff *)(uintptr_t)
-			nixge_hw_dma_bd_get_addr(&priv->rx_bd_v[i],
-						 sw_id_offset);
-		dev_kfree_skb(skb);
-	}
+	if (priv->rx_bd_v) {
+		for (i = 0; i < RX_BD_NUM; i++) {
+			phys_addr = nixge_hw_dma_bd_get_addr(&priv->rx_bd_v[i],
+							     phys);
+
+			dma_unmap_single(ndev->dev.parent, phys_addr,
+					 NIXGE_MAX_JUMBO_FRAME_SIZE,
+					 DMA_FROM_DEVICE);
+
+			skb = (struct sk_buff *)(uintptr_t)
+				nixge_hw_dma_bd_get_addr(&priv->rx_bd_v[i],
+							 sw_id_offset);
+			dev_kfree_skb(skb);
+		}
 
-	if (priv->rx_bd_v)
 		dma_free_coherent(ndev->dev.parent,
 				  sizeof(*priv->rx_bd_v) * RX_BD_NUM,
 				  priv->rx_bd_v,
 				  priv->rx_bd_p);
+	}
 
 	if (priv->tx_skb)
 		devm_kfree(ndev->dev.parent, priv->tx_skb);
@@ -899,6 +900,7 @@
 err_rx_irq:
 	free_irq(priv->tx_irq, ndev);
 err_tx_irq:
+	napi_disable(&priv->napi);
 	phy_stop(phy);
 	phy_disconnect(phy);
 	tasklet_kill(&priv->dma_err_tasklet);
@@ -1318,19 +1320,21 @@
 	netif_napi_add(ndev, &priv->napi, nixge_poll, NAPI_POLL_WEIGHT);
 	err = nixge_of_get_resources(pdev);
 	if (err)
-		return err;
+		goto free_netdev;
 	__nixge_hw_set_mac_address(ndev);
 
 	priv->tx_irq = platform_get_irq_byname(pdev, "tx");
 	if (priv->tx_irq < 0) {
 		netdev_err(ndev, "could not find 'tx' irq");
-		return priv->tx_irq;
+		err = priv->tx_irq;
+		goto free_netdev;
 	}
 
 	priv->rx_irq = platform_get_irq_byname(pdev, "rx");
 	if (priv->rx_irq < 0) {
 		netdev_err(ndev, "could not find 'rx' irq");
-		return priv->rx_irq;
+		err = priv->rx_irq;
+		goto free_netdev;
 	}
 
 	priv->coalesce_count_rx = XAXIDMA_DFT_RX_THRESHOLD;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/nvidia/forcedeth.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/nvidia/forcedeth.c
@@ -6099,6 +6099,7 @@
 	return 0;
 
 out_error:
+	nv_mgmt_release_sema(dev);
 	if (phystate_orig)
 		writel(phystate|NVREG_ADAPTCTL_RUNNING, base + NvRegAdapterControl);
 out_freering:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/nxp/lpc_eth.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/nxp/lpc_eth.c
@@ -815,7 +815,8 @@
 	if (mdiobus_register(pldat->mii_bus))
 		goto err_out_unregister_bus;
 
-	if (lpc_mii_probe(pldat->ndev) != 0)
+	err = lpc_mii_probe(pldat->ndev);
+	if (err)
 		goto err_out_unregister_bus;
 
 	return 0;
@@ -1006,9 +1007,6 @@
 	napi_disable(&pldat->napi);
 	netif_stop_queue(ndev);
 
-	if (ndev->phydev)
-		phy_stop(ndev->phydev);
-
 	spin_lock_irqsave(&pldat->lock, flags);
 	__lpc_eth_reset(pldat);
 	netif_carrier_off(ndev);
@@ -1016,6 +1014,8 @@
 	writel(0, LPC_ENET_MAC2(pldat->net_base));
 	spin_unlock_irqrestore(&pldat->lock, flags);
 
+	if (ndev->phydev)
+		phy_stop(ndev->phydev);
 	clk_disable_unprepare(pldat->clk);
 
 	return 0;
@@ -1470,6 +1470,7 @@
 {
 	struct net_device *ndev = platform_get_drvdata(pdev);
 	struct netdata_local *pldat;
+	int ret;
 
 	if (device_may_wakeup(&pdev->dev))
 		disable_irq_wake(ndev->irq);
@@ -1479,7 +1480,9 @@
 			pldat = netdev_priv(ndev);
 
 			/* Enable interface clock */
-			clk_enable(pldat->clk);
+			ret = clk_enable(pldat->clk);
+			if (ret)
+				return ret;
 
 			/* Reset and initialize */
 			__lpc_eth_reset(pldat);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
@@ -107,7 +107,7 @@
 {
 	u8 *data = skb->data;
 	unsigned int offset;
-	u16 *hi, *id;
+	u16 hi, id;
 	u32 lo;
 
 	if (ptp_classify_raw(skb) == PTP_CLASS_NONE)
@@ -118,14 +118,11 @@
 	if (skb->len < offset + OFF_PTP_SEQUENCE_ID + sizeof(seqid))
 		return 0;
 
-	hi = (u16 *)(data + offset + OFF_PTP_SOURCE_UUID);
-	id = (u16 *)(data + offset + OFF_PTP_SEQUENCE_ID);
+	hi = get_unaligned_be16(data + offset + OFF_PTP_SOURCE_UUID + 0);
+	lo = get_unaligned_be32(data + offset + OFF_PTP_SOURCE_UUID + 2);
+	id = get_unaligned_be16(data + offset + OFF_PTP_SEQUENCE_ID);
 
-	memcpy(&lo, &hi[1], sizeof(lo));
-
-	return (uid_hi == *hi &&
-		uid_lo == lo &&
-		seqid  == *id);
+	return (uid_hi == hi && uid_lo == lo && seqid == id);
 }
 
 static void
@@ -135,7 +132,6 @@
 	struct pci_dev *pdev;
 	u64 ns;
 	u32 hi, lo, val;
-	u16 uid, seq;
 
 	if (!adapter->hwts_rx_en)
 		return;
@@ -151,10 +147,7 @@
 	lo = pch_src_uuid_lo_read(pdev);
 	hi = pch_src_uuid_hi_read(pdev);
 
-	uid = hi & 0xffff;
-	seq = (hi >> 16) & 0xffff;
-
-	if (!pch_ptp_match(skb, htons(uid), htonl(lo), htons(seq)))
+	if (!pch_ptp_match(skb, hi, lo, hi >> 16))
 		goto out;
 
 	ns = pch_rx_snap_read(pdev);
@@ -1173,6 +1166,7 @@
 		buffer_info->dma = 0;
 		buffer_info->time_stamp = 0;
 		tx_ring->next_to_use = ring_num;
+		dev_kfree_skb_any(skb);
 		return;
 	}
 	buffer_info->mapped = true;
@@ -2487,6 +2481,7 @@
 	unregister_netdev(netdev);
 
 	pch_gbe_phy_hw_reset(&adapter->hw);
+	pci_dev_put(adapter->ptp_pdev);
 
 	free_netdev(netdev);
 }
@@ -2535,9 +2530,13 @@
 	adapter->pdev = pdev;
 	adapter->hw.back = adapter;
 	adapter->hw.reg = pcim_iomap_table(pdev)[PCH_GBE_PCI_BAR];
+
 	adapter->pdata = (struct pch_gbe_privdata *)pci_id->driver_data;
-	if (adapter->pdata && adapter->pdata->platform_init)
-		adapter->pdata->platform_init(pdev);
+	if (adapter->pdata && adapter->pdata->platform_init) {
+		ret = adapter->pdata->platform_init(pdev);
+		if (ret)
+			goto err_free_netdev;
+	}
 
 	adapter->ptp_pdev =
 		pci_get_domain_bus_and_slot(pci_domain_nr(adapter->pdev->bus),
@@ -2564,7 +2563,7 @@
 	/* setup the private structure */
 	ret = pch_gbe_sw_init(adapter);
 	if (ret)
-		goto err_free_netdev;
+		goto err_put_dev;
 
 	/* Initialize PHY */
 	ret = pch_gbe_init_phy(adapter);
@@ -2622,6 +2621,8 @@
 
 err_free_adapter:
 	pch_gbe_phy_hw_reset(&adapter->hw);
+err_put_dev:
+	pci_dev_put(adapter->ptp_pdev);
 err_free_netdev:
 	free_netdev(netdev);
 	return ret;
@@ -2632,7 +2633,7 @@
  */
 static int pch_gbe_minnow_platform_init(struct pci_dev *pdev)
 {
-	unsigned long flags = GPIOF_DIR_OUT | GPIOF_INIT_HIGH | GPIOF_EXPORT;
+	unsigned long flags = GPIOF_OUT_INIT_HIGH;
 	unsigned gpio = MINNOW_PHY_RESET_GPIO;
 	int ret;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/pasemi/pasemi_mac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/pasemi/pasemi_mac.c
@@ -1078,16 +1078,20 @@
 
 	mac->tx = pasemi_mac_setup_tx_resources(dev);
 
-	if (!mac->tx)
+	if (!mac->tx) {
+		ret = -ENOMEM;
 		goto out_tx_ring;
+	}
 
 	/* We might already have allocated rings in case mtu was changed
 	 * before interface was brought up.
 	 */
 	if (dev->mtu > 1500 && !mac->num_cs) {
 		pasemi_mac_setup_csrings(mac);
-		if (!mac->num_cs)
+		if (!mac->num_cs) {
+			ret = -ENOMEM;
 			goto out_tx_ring;
+		}
 	}
 
 	/* Zero out rmon counters */
@@ -1419,7 +1423,7 @@
 	write_dma_reg(PAS_DMA_TXCHAN_INCR(txring->chan.chno), 2);
 }
 
-static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev)
 {
 	struct pasemi_mac * const mac = netdev_priv(dev);
 	struct pasemi_mac_txring * const txring = tx_ring(mac);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c
@@ -102,15 +102,18 @@
 			   void *p)
 {
 	struct ionic_lif *lif = netdev_priv(netdev);
+	unsigned int offset;
 	unsigned int size;
 
 	regs->version = IONIC_DEV_CMD_REG_VERSION;
 
+	offset = 0;
 	size = IONIC_DEV_INFO_REG_COUNT * sizeof(u32);
-	memcpy_fromio(p, lif->ionic->idev.dev_info_regs->words, size);
+	memcpy_fromio(p + offset, lif->ionic->idev.dev_info_regs->words, size);
 
+	offset += size;
 	size = IONIC_DEV_CMD_REG_COUNT * sizeof(u32);
-	memcpy_fromio(p, lif->ionic->idev.dev_cmd_regs->words, size);
+	memcpy_fromio(p + offset, lif->ionic->idev.dev_cmd_regs->words, size);
 }
 
 static int ionic_get_link_ksettings(struct net_device *netdev,
@@ -122,6 +125,11 @@
 
 	ethtool_link_ksettings_zero_link_mode(ks, supported);
 
+	if (!idev->port_info) {
+		netdev_err(netdev, "port_info not initialized\n");
+		return -EOPNOTSUPP;
+	}
+
 	/* The port_info data is found in a DMA space that the NIC keeps
 	 * up-to-date, so there's no need to request the data from the
 	 * NIC, we already have it in our memory space.
@@ -565,7 +573,7 @@
 		info->data = lif->nxqs;
 		break;
 	default:
-		netdev_err(netdev, "Command parameter %d is not supported\n",
+		netdev_dbg(netdev, "Command parameter %d is not supported\n",
 			   info->cmd);
 		err = -EOPNOTSUPP;
 	}
@@ -703,8 +711,8 @@
 	len = min_t(u32, sizeof(xcvr->sprom), ee->len);
 
 	do {
-		memcpy(data, xcvr->sprom, len);
-		memcpy(tbuf, xcvr->sprom, len);
+		memcpy(data, &xcvr->sprom[ee->offset], len);
+		memcpy(tbuf, &xcvr->sprom[ee->offset], len);
 
 		/* Let's make sure we got a consistent copy */
 		if (!memcmp(data, tbuf, len))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/pensando/ionic/ionic_if.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/pensando/ionic/ionic_if.h
@@ -862,7 +862,7 @@
 #define IONIC_RXQ_COMP_CSUM_F_VLAN	0x40
 #define IONIC_RXQ_COMP_CSUM_F_CALC	0x80
 	u8     pkt_type_color;
-#define IONIC_RXQ_COMP_PKT_TYPE_MASK	0x0f
+#define IONIC_RXQ_COMP_PKT_TYPE_MASK	0x7f
 };
 
 enum ionic_pkt_type {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/pensando/ionic/ionic_lif.c
@@ -143,7 +143,7 @@
 		name = dev_name(dev);
 
 	snprintf(intr->name, sizeof(intr->name),
-		 "%s-%s-%s", IONIC_DRV_NAME, name, q->name);
+		 "%.5s-%.16s-%.8s", IONIC_DRV_NAME, name, q->name);
 
 	return devm_request_irq(dev, intr->vector, ionic_isr,
 				0, intr->name, &qcq->napi);
@@ -167,10 +167,10 @@
 	return 0;
 }
 
-static void ionic_intr_free(struct ionic_lif *lif, int index)
+static void ionic_intr_free(struct ionic *ionic, int index)
 {
-	if (index != INTR_INDEX_NOT_ASSIGNED && index < lif->ionic->nintrs)
-		clear_bit(index, lif->ionic->intrs);
+	if (index != INTR_INDEX_NOT_ASSIGNED && index < ionic->nintrs)
+		clear_bit(index, ionic->intrs);
 }
 
 static int ionic_qcq_enable(struct ionic_qcq *qcq)
@@ -190,6 +190,7 @@
 			.oper = IONIC_Q_ENABLE,
 		},
 	};
+	int ret;
 
 	idev = &lif->ionic->idev;
 	dev = lif->ionic->dev;
@@ -197,16 +198,22 @@
 	dev_dbg(dev, "q_enable.index %d q_enable.qtype %d\n",
 		ctx.cmd.q_control.index, ctx.cmd.q_control.type);
 
+	if (qcq->flags & IONIC_QCQ_F_INTR)
+		ionic_intr_clean(idev->intr_ctrl, qcq->intr.index);
+
+	ret = ionic_adminq_post_wait(lif, &ctx);
+	if (ret)
+		return ret;
+
 	if (qcq->flags & IONIC_QCQ_F_INTR) {
+		napi_enable(&qcq->napi);
 		irq_set_affinity_hint(qcq->intr.vector,
 				      &qcq->intr.affinity_mask);
-		napi_enable(&qcq->napi);
-		ionic_intr_clean(idev->intr_ctrl, qcq->intr.index);
 		ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
 				IONIC_INTR_MASK_CLEAR);
 	}
 
-	return ionic_adminq_post_wait(lif, &ctx);
+	return 0;
 }
 
 static int ionic_qcq_disable(struct ionic_qcq *qcq)
@@ -247,7 +254,6 @@
 static void ionic_lif_qcq_deinit(struct ionic_lif *lif, struct ionic_qcq *qcq)
 {
 	struct ionic_dev *idev = &lif->ionic->idev;
-	struct device *dev = lif->ionic->dev;
 
 	if (!qcq)
 		return;
@@ -260,7 +266,6 @@
 	if (qcq->flags & IONIC_QCQ_F_INTR) {
 		ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
 				IONIC_INTR_MASK_SET);
-		devm_free_irq(dev, qcq->intr.vector, &qcq->napi);
 		netif_napi_del(&qcq->napi);
 	}
 
@@ -278,8 +283,12 @@
 	qcq->base = NULL;
 	qcq->base_pa = 0;
 
-	if (qcq->flags & IONIC_QCQ_F_INTR)
-		ionic_intr_free(lif, qcq->intr.index);
+	if (qcq->flags & IONIC_QCQ_F_INTR) {
+		irq_set_affinity_hint(qcq->intr.vector, NULL);
+		devm_free_irq(dev, qcq->intr.vector, &qcq->napi);
+		qcq->intr.vector = 0;
+		ionic_intr_free(lif->ionic, qcq->intr.index);
+	}
 
 	devm_kfree(dev, qcq->cq.info);
 	qcq->cq.info = NULL;
@@ -321,11 +330,6 @@
 static void ionic_link_qcq_interrupts(struct ionic_qcq *src_qcq,
 				      struct ionic_qcq *n_qcq)
 {
-	if (WARN_ON(n_qcq->flags & IONIC_QCQ_F_INTR)) {
-		ionic_intr_free(n_qcq->cq.lif, n_qcq->intr.index);
-		n_qcq->flags &= ~IONIC_QCQ_F_INTR;
-	}
-
 	n_qcq->intr.vector = src_qcq->intr.vector;
 	n_qcq->intr.index = src_qcq->intr.index;
 }
@@ -409,8 +413,15 @@
 		ionic_intr_mask_assert(idev->intr_ctrl, new->intr.index,
 				       IONIC_INTR_MASK_SET);
 
-		new->intr.cpu = new->intr.index % num_online_cpus();
-		if (cpu_online(new->intr.cpu))
+		err = ionic_request_irq(lif, new);
+		if (err) {
+			netdev_warn(lif->netdev, "irq request failed %d\n", err);
+			goto err_out_free_intr;
+		}
+
+		new->intr.cpu = cpumask_local_spread(new->intr.index,
+						     dev_to_node(dev));
+		if (new->intr.cpu != -1)
 			cpumask_set_cpu(new->intr.cpu,
 					&new->intr.affinity_mask);
 	} else {
@@ -422,13 +433,13 @@
 	if (!new->cq.info) {
 		netdev_err(lif->netdev, "Cannot allocate completion queue info\n");
 		err = -ENOMEM;
-		goto err_out_free_intr;
+		goto err_out_free_irq;
 	}
 
 	err = ionic_cq_init(lif, &new->cq, &new->intr, num_descs, cq_desc_size);
 	if (err) {
 		netdev_err(lif->netdev, "Cannot initialize completion queue\n");
-		goto err_out_free_intr;
+		goto err_out_free_irq;
 	}
 
 	new->base = dma_alloc_coherent(dev, total_size, &new->base_pa,
@@ -436,7 +447,7 @@
 	if (!new->base) {
 		netdev_err(lif->netdev, "Cannot allocate queue DMA memory\n");
 		err = -ENOMEM;
-		goto err_out_free_intr;
+		goto err_out_free_irq;
 	}
 
 	new->total_size = total_size;
@@ -462,8 +473,12 @@
 
 	return 0;
 
+err_out_free_irq:
+	if (flags & IONIC_QCQ_F_INTR)
+		devm_free_irq(dev, new->intr.vector, &new->napi);
 err_out_free_intr:
-	ionic_intr_free(lif, new->intr.index);
+	if (flags & IONIC_QCQ_F_INTR)
+		ionic_intr_free(lif->ionic, new->intr.index);
 err_out:
 	dev_err(dev, "qcq alloc of %s%d failed %d\n", name, index, err);
 	return err;
@@ -638,12 +653,6 @@
 	netif_napi_add(lif->netdev, &qcq->napi, ionic_rx_napi,
 		       NAPI_POLL_WEIGHT);
 
-	err = ionic_request_irq(lif, qcq);
-	if (err) {
-		netif_napi_del(&qcq->napi);
-		return err;
-	}
-
 	qcq->flags |= IONIC_QCQ_F_INITED;
 
 	ionic_debugfs_add_qcq(lif, qcq);
@@ -666,7 +675,7 @@
 	eid = le64_to_cpu(comp->event.eid);
 
 	/* Have we run out of new completions to process? */
-	if (eid <= lif->last_eid)
+	if ((s64)(eid - lif->last_eid) <= 0)
 		return false;
 
 	lif->last_eid = eid;
@@ -809,8 +818,7 @@
 	if (f)
 		return 0;
 
-	netdev_dbg(lif->netdev, "rx_filter add ADDR %pM (id %d)\n", addr,
-		   ctx.comp.rx_filter_add.filter_id);
+	netdev_dbg(lif->netdev, "rx_filter add ADDR %pM\n", addr);
 
 	memcpy(ctx.cmd.rx_filter_add.mac.addr, addr, ETH_ALEN);
 	err = ionic_adminq_post_wait(lif, &ctx);
@@ -839,6 +847,9 @@
 		return -ENOENT;
 	}
 
+	netdev_dbg(lif->netdev, "rx_filter del ADDR %pM (id %d)\n",
+		   addr, f->filter_id);
+
 	ctx.cmd.rx_filter_del.filter_id = cpu_to_le32(f->filter_id);
 	ionic_rx_filter_free(lif, f);
 	spin_unlock_bh(&lif->rx_filters.lock);
@@ -847,9 +858,6 @@
 	if (err)
 		return err;
 
-	netdev_dbg(lif->netdev, "rx_filter del ADDR %pM (id %d)\n", addr,
-		   ctx.cmd.rx_filter_del.filter_id);
-
 	return 0;
 }
 
@@ -913,6 +921,10 @@
 
 static int ionic_addr_del(struct net_device *netdev, const u8 *addr)
 {
+	/* Don't delete our own address from the uc list */
+	if (ether_addr_equal(addr, netdev->dev_addr))
+		return 0;
+
 	return ionic_lif_addr(netdev_priv(netdev), addr, false);
 }
 
@@ -1187,6 +1199,7 @@
 
 	netdev->hw_features |= netdev->hw_enc_features;
 	netdev->features |= netdev->hw_features;
+	netdev->vlan_features |= netdev->features & ~NETIF_F_VLAN_FEATURES;
 
 	netdev->priv_flags |= IFF_UNICAST_FLT;
 
@@ -1290,13 +1303,11 @@
 	};
 	int err;
 
+	netdev_dbg(netdev, "rx_filter add VLAN %d\n", vid);
 	err = ionic_adminq_post_wait(lif, &ctx);
 	if (err)
 		return err;
 
-	netdev_dbg(netdev, "rx_filter add VLAN %d (id %d)\n", vid,
-		   ctx.comp.rx_filter_add.filter_id);
-
 	return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, 0, &ctx);
 }
 
@@ -1321,8 +1332,8 @@
 		return -ENOENT;
 	}
 
-	netdev_dbg(netdev, "rx_filter del VLAN %d (id %d)\n", vid,
-		   le32_to_cpu(ctx.cmd.rx_filter_del.filter_id));
+	netdev_dbg(netdev, "rx_filter del VLAN %d (id %d)\n",
+		   vid, f->filter_id);
 
 	ctx.cmd.rx_filter_del.filter_id = cpu_to_le32(f->filter_id);
 	ionic_rx_filter_free(lif, f);
@@ -1364,12 +1375,9 @@
 
 static int ionic_lif_rss_init(struct ionic_lif *lif)
 {
-	u8 rss_key[IONIC_RSS_HASH_KEY_SIZE];
 	unsigned int tbl_sz;
 	unsigned int i;
 
-	netdev_rss_key_fill(rss_key, IONIC_RSS_HASH_KEY_SIZE);
-
 	lif->rss_types = IONIC_RSS_TYPE_IPV4     |
 			 IONIC_RSS_TYPE_IPV4_TCP |
 			 IONIC_RSS_TYPE_IPV4_UDP |
@@ -1382,12 +1390,18 @@
 	for (i = 0; i < tbl_sz; i++)
 		lif->rss_ind_tbl[i] = ethtool_rxfh_indir_default(i, lif->nxqs);
 
-	return ionic_lif_rss_config(lif, lif->rss_types, rss_key, NULL);
+	return ionic_lif_rss_config(lif, lif->rss_types, NULL, NULL);
 }
 
-static int ionic_lif_rss_deinit(struct ionic_lif *lif)
+static void ionic_lif_rss_deinit(struct ionic_lif *lif)
 {
-	return ionic_lif_rss_config(lif, 0x0, NULL, NULL);
+	int tbl_sz;
+
+	tbl_sz = le16_to_cpu(lif->ionic->ident.lif.eth.rss_ind_tbl_sz);
+	memset(lif->rss_ind_tbl, 0, tbl_sz);
+	memset(lif->rss_hash_key, 0, IONIC_RSS_HASH_KEY_SIZE);
+
+	ionic_lif_rss_config(lif, 0x0, NULL, NULL);
 }
 
 static void ionic_txrx_disable(struct ionic_lif *lif)
@@ -1710,6 +1724,7 @@
 		dev_err(dev, "Failed to allocate rss indirection table, aborting\n");
 		goto err_out_free_qcqs;
 	}
+	netdev_rss_key_fill(lif->rss_hash_key, IONIC_RSS_HASH_KEY_SIZE);
 
 	list_add_tail(&lif->list, &ionic->lifs);
 
@@ -1855,18 +1870,14 @@
 	netif_napi_add(lif->netdev, &qcq->napi, ionic_adminq_napi,
 		       NAPI_POLL_WEIGHT);
 
-	err = ionic_request_irq(lif, qcq);
-	if (err) {
-		netdev_warn(lif->netdev, "adminq irq request failed %d\n", err);
-		netif_napi_del(&qcq->napi);
-		return err;
-	}
-
 	napi_enable(&qcq->napi);
 
-	if (qcq->flags & IONIC_QCQ_F_INTR)
+	if (qcq->flags & IONIC_QCQ_F_INTR) {
+		irq_set_affinity_hint(qcq->intr.vector,
+				      &qcq->intr.affinity_mask);
 		ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
 				IONIC_INTR_MASK_CLEAR);
+	}
 
 	qcq->flags |= IONIC_QCQ_F_INITED;
 
@@ -1989,7 +2000,7 @@
 		return -EINVAL;
 	}
 
-	lif->dbid_inuse = bitmap_alloc(lif->dbid_count, GFP_KERNEL);
+	lif->dbid_inuse = bitmap_zalloc(lif->dbid_count, GFP_KERNEL);
 	if (!lif->dbid_inuse) {
 		dev_err(dev, "Failed alloc doorbell id bitmap, aborting\n");
 		return -ENOMEM;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/pensando/ionic/ionic_rx_filter.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/pensando/ionic/ionic_rx_filter.c
@@ -36,10 +36,12 @@
 
 	spin_lock_init(&lif->rx_filters.lock);
 
+	spin_lock_bh(&lif->rx_filters.lock);
 	for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) {
 		INIT_HLIST_HEAD(&lif->rx_filters.by_hash[i]);
 		INIT_HLIST_HEAD(&lif->rx_filters.by_id[i]);
 	}
+	spin_unlock_bh(&lif->rx_filters.lock);
 
 	return 0;
 }
@@ -51,11 +53,13 @@
 	struct hlist_node *tmp;
 	unsigned int i;
 
+	spin_lock_bh(&lif->rx_filters.lock);
 	for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) {
 		head = &lif->rx_filters.by_id[i];
 		hlist_for_each_entry_safe(f, tmp, head, by_id)
 			ionic_rx_filter_free(lif, f);
 	}
+	spin_unlock_bh(&lif->rx_filters.lock);
 }
 
 int ionic_rx_filter_save(struct ionic_lif *lif, u32 flow_id, u16 rxq_index,
@@ -91,6 +95,7 @@
 	f->filter_id = le32_to_cpu(ctx->comp.rx_filter_add.filter_id);
 	f->rxq_index = rxq_index;
 	memcpy(&f->cmd, ac, sizeof(f->cmd));
+	netdev_dbg(lif->netdev, "rx_filter add filter_id %d\n", f->filter_id);
 
 	INIT_HLIST_NODE(&f->by_hash);
 	INIT_HLIST_NODE(&f->by_id);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/pensando/ionic/ionic_txrx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/pensando/ionic/ionic_txrx.c
@@ -257,7 +257,7 @@
 	unsigned int len;
 	unsigned int i;
 
-	len = netdev->mtu + ETH_HLEN;
+	len = netdev->mtu + ETH_HLEN + VLAN_HLEN;
 
 	for (i = ionic_q_space_avail(q); i; i--) {
 		skb = ionic_rx_skb_alloc(q, len, &dma_addr);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/Kconfig
@@ -78,6 +78,7 @@
 	depends on PCI
 	select ZLIB_INFLATE
 	select CRC8
+	select CRC32
 	select NET_DEVLINK
 	---help---
 	  This enables the support for ...
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
@@ -564,11 +564,6 @@
 	.ndo_set_features = netxen_set_features,
 };
 
-static inline bool netxen_function_zero(struct pci_dev *pdev)
-{
-	return (PCI_FUNC(pdev->devfn) == 0) ? true : false;
-}
-
 static inline void netxen_set_interrupt_mode(struct netxen_adapter *adapter,
 					     u32 mode)
 {
@@ -664,7 +659,7 @@
 	netxen_initialize_interrupt_registers(adapter);
 	netxen_set_msix_bit(pdev, 0);
 
-	if (netxen_function_zero(pdev)) {
+	if (adapter->portnum == 0) {
 		if (!netxen_setup_msi_interrupts(adapter, num_msix))
 			netxen_set_interrupt_mode(adapter, NETXEN_MSI_MODE);
 		else
@@ -1607,6 +1602,8 @@
 	free_netdev(netdev);
 
 err_out_free_res:
+	if (NX_IS_REVISION_P3(pdev->revision))
+		pci_disable_pcie_error_reporting(pdev);
 	pci_release_regions(pdev);
 
 err_out_disable_pdev:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qed/qed_cxt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qed/qed_cxt.c
@@ -396,7 +396,7 @@
 		vf_tids += segs[NUM_TASK_PF_SEGMENTS].count;
 	}
 
-	iids->vf_cids += vf_cids * p_mngr->vf_count;
+	iids->vf_cids = vf_cids;
 	iids->tids += vf_tids * p_mngr->vf_count;
 
 	DP_VERBOSE(p_hwfn, QED_MSG_ILT,
@@ -1023,6 +1023,7 @@
 		p_dma->p_virt = NULL;
 	}
 	kfree(p_mngr->ilt_shadow);
+	p_mngr->ilt_shadow = NULL;
 }
 
 static int qed_ilt_blk_alloc(struct qed_hwfn *p_hwfn,
@@ -2073,8 +2074,8 @@
 	num_srqs = min_t(u32, QED_RDMA_MAX_SRQS, p_params->num_srqs);
 
 	if (p_hwfn->mcp_info->func_info.protocol == QED_PCI_ETH_RDMA) {
-		DP_NOTICE(p_hwfn,
-			  "Current day drivers don't support RoCE & iWARP simultaneously on the same PF. Default to RoCE-only\n");
+		DP_VERBOSE(p_hwfn, QED_MSG_SP,
+			   "Current day drivers don't support RoCE & iWARP simultaneously on the same PF. Default to RoCE-only\n");
 		p_hwfn->hw_info.personality = QED_PCI_ETH_ROCE;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qed/qed_dcbx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qed/qed_dcbx.c
@@ -1293,9 +1293,11 @@
 		p_hwfn->p_dcbx_info->set.ver_num |= DCBX_CONFIG_VERSION_STATIC;
 
 	p_hwfn->p_dcbx_info->set.enabled = dcbx_info->operational.enabled;
+	BUILD_BUG_ON(sizeof(dcbx_info->operational.params) !=
+		     sizeof(p_hwfn->p_dcbx_info->set.config.params));
 	memcpy(&p_hwfn->p_dcbx_info->set.config.params,
 	       &dcbx_info->operational.params,
-	       sizeof(struct qed_dcbx_admin_params));
+	       sizeof(p_hwfn->p_dcbx_info->set.config.params));
 	p_hwfn->p_dcbx_info->set.config.valid = true;
 
 	memcpy(params, &p_hwfn->p_dcbx_info->set, sizeof(struct qed_dcbx_set));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qed/qed_debug.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qed/qed_debug.c
@@ -8197,6 +8197,10 @@
 		DP_ERR(cdev, "qed_dbg_mcp_trace failed. rc = %d\n", rc);
 	}
 
+	/* Re-populate nvm attribute info */
+	qed_mcp_nvm_info_free(p_hwfn);
+	qed_mcp_nvm_info_populate(p_hwfn);
+
 	/* nvm cfg1 */
 	rc = qed_dbg_nvm_image(cdev,
 			       (u8 *)buffer + offset + REGDUMP_HEADER_SIZE,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qed/qed_dev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qed/qed_dev.c
@@ -1368,6 +1368,8 @@
 
 void qed_resc_free(struct qed_dev *cdev)
 {
+	struct qed_rdma_info *rdma_info;
+	struct qed_hwfn *p_hwfn;
 	int i;
 
 	if (IS_VF(cdev)) {
@@ -1385,7 +1387,8 @@
 	qed_llh_free(cdev);
 
 	for_each_hwfn(cdev, i) {
-		struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
+		p_hwfn = cdev->hwfns + i;
+		rdma_info = p_hwfn->p_rdma_info;
 
 		qed_cxt_mngr_free(p_hwfn);
 		qed_qm_info_free(p_hwfn);
@@ -1404,8 +1407,10 @@
 			qed_ooo_free(p_hwfn);
 		}
 
-		if (QED_IS_RDMA_PERSONALITY(p_hwfn))
+		if (QED_IS_RDMA_PERSONALITY(p_hwfn) && rdma_info) {
+			qed_spq_unregister_async_cb(p_hwfn, rdma_info->proto);
 			qed_rdma_info_free(p_hwfn);
+		}
 
 		qed_iov_free(p_hwfn);
 		qed_l2_free(p_hwfn);
@@ -3087,7 +3092,7 @@
 		}
 
 		/* Log and clear previous pglue_b errors if such exist */
-		qed_pglueb_rbc_attn_handler(p_hwfn, p_hwfn->p_main_ptt);
+		qed_pglueb_rbc_attn_handler(p_hwfn, p_hwfn->p_main_ptt, true);
 
 		/* Enable the PF's internal FID_enable in the PXP */
 		rc = qed_pglueb_set_pfid_enable(p_hwfn, p_hwfn->p_main_ptt,
@@ -4137,7 +4142,8 @@
 			cdev->mf_bits = BIT(QED_MF_LLH_MAC_CLSS) |
 					BIT(QED_MF_LLH_PROTO_CLSS) |
 					BIT(QED_MF_LL2_NON_UNICAST) |
-					BIT(QED_MF_INTER_PF_SWITCH);
+					BIT(QED_MF_INTER_PF_SWITCH) |
+					BIT(QED_MF_DISABLE_ARFS);
 			break;
 		case NVM_CFG1_GLOB_MF_MODE_DEFAULT:
 			cdev->mf_bits = BIT(QED_MF_LLH_MAC_CLSS) |
@@ -4150,6 +4156,14 @@
 
 		DP_INFO(p_hwfn, "Multi function mode is 0x%lx\n",
 			cdev->mf_bits);
+
+		/* In CMT the PF is unknown when the GFS block processes the
+		 * packet. Therefore cannot use searcher as it has a per PF
+		 * database, and thus ARFS must be disabled.
+		 *
+		 */
+		if (QED_IS_CMT(cdev))
+			cdev->mf_bits |= BIT(QED_MF_DISABLE_ARFS);
 	}
 
 	DP_INFO(p_hwfn, "Multi function mode is 0x%lx\n",
@@ -4418,12 +4432,6 @@
 	return 0;
 }
 
-static void qed_nvm_info_free(struct qed_hwfn *p_hwfn)
-{
-	kfree(p_hwfn->nvm_info.image_att);
-	p_hwfn->nvm_info.image_att = NULL;
-}
-
 static int qed_hw_prepare_single(struct qed_hwfn *p_hwfn,
 				 void __iomem *p_regview,
 				 void __iomem *p_doorbells,
@@ -4508,7 +4516,7 @@
 	return rc;
 err3:
 	if (IS_LEAD_HWFN(p_hwfn))
-		qed_nvm_info_free(p_hwfn);
+		qed_mcp_nvm_info_free(p_hwfn);
 err2:
 	if (IS_LEAD_HWFN(p_hwfn))
 		qed_iov_free_hw_info(p_hwfn->cdev);
@@ -4569,7 +4577,7 @@
 		if (rc) {
 			if (IS_PF(cdev)) {
 				qed_init_free(p_hwfn);
-				qed_nvm_info_free(p_hwfn);
+				qed_mcp_nvm_info_free(p_hwfn);
 				qed_mcp_free(p_hwfn);
 				qed_hw_hwfn_free(p_hwfn);
 			}
@@ -4603,7 +4611,7 @@
 
 	qed_iov_free_hw_info(cdev);
 
-	qed_nvm_info_free(p_hwfn);
+	qed_mcp_nvm_info_free(p_hwfn);
 }
 
 static void qed_chain_free_next_ptr(struct qed_dev *cdev,
@@ -4648,26 +4656,20 @@
 
 static void qed_chain_free_pbl(struct qed_dev *cdev, struct qed_chain *p_chain)
 {
-	void **pp_virt_addr_tbl = p_chain->pbl.pp_virt_addr_tbl;
+	struct addr_tbl_entry *pp_addr_tbl = p_chain->pbl.pp_addr_tbl;
 	u32 page_cnt = p_chain->page_cnt, i, pbl_size;
-	u8 *p_pbl_virt = p_chain->pbl_sp.p_virt_table;
 
-	if (!pp_virt_addr_tbl)
+	if (!pp_addr_tbl)
 		return;
 
-	if (!p_pbl_virt)
-		goto out;
-
 	for (i = 0; i < page_cnt; i++) {
-		if (!pp_virt_addr_tbl[i])
+		if (!pp_addr_tbl[i].virt_addr || !pp_addr_tbl[i].dma_map)
 			break;
 
 		dma_free_coherent(&cdev->pdev->dev,
 				  QED_CHAIN_PAGE_SIZE,
-				  pp_virt_addr_tbl[i],
-				  *(dma_addr_t *)p_pbl_virt);
-
-		p_pbl_virt += QED_CHAIN_PBL_ENTRY_SIZE;
+				  pp_addr_tbl[i].virt_addr,
+				  pp_addr_tbl[i].dma_map);
 	}
 
 	pbl_size = page_cnt * QED_CHAIN_PBL_ENTRY_SIZE;
@@ -4677,9 +4679,9 @@
 				  pbl_size,
 				  p_chain->pbl_sp.p_virt_table,
 				  p_chain->pbl_sp.p_phys_table);
-out:
-	vfree(p_chain->pbl.pp_virt_addr_tbl);
-	p_chain->pbl.pp_virt_addr_tbl = NULL;
+
+	vfree(p_chain->pbl.pp_addr_tbl);
+	p_chain->pbl.pp_addr_tbl = NULL;
 }
 
 void qed_chain_free(struct qed_dev *cdev, struct qed_chain *p_chain)
@@ -4780,19 +4782,19 @@
 {
 	u32 page_cnt = p_chain->page_cnt, size, i;
 	dma_addr_t p_phys = 0, p_pbl_phys = 0;
-	void **pp_virt_addr_tbl = NULL;
+	struct addr_tbl_entry *pp_addr_tbl;
 	u8 *p_pbl_virt = NULL;
 	void *p_virt = NULL;
 
-	size = page_cnt * sizeof(*pp_virt_addr_tbl);
-	pp_virt_addr_tbl = vzalloc(size);
-	if (!pp_virt_addr_tbl)
+	size = page_cnt * sizeof(*pp_addr_tbl);
+	pp_addr_tbl =  vzalloc(size);
+	if (!pp_addr_tbl)
 		return -ENOMEM;
 
 	/* The allocation of the PBL table is done with its full size, since it
 	 * is expected to be successive.
 	 * qed_chain_init_pbl_mem() is called even in a case of an allocation
-	 * failure, since pp_virt_addr_tbl was previously allocated, and it
+	 * failure, since tbl was previously allocated, and it
 	 * should be saved to allow its freeing during the error flow.
 	 */
 	size = page_cnt * QED_CHAIN_PBL_ENTRY_SIZE;
@@ -4806,8 +4808,7 @@
 		p_chain->b_external_pbl = true;
 	}
 
-	qed_chain_init_pbl_mem(p_chain, p_pbl_virt, p_pbl_phys,
-			       pp_virt_addr_tbl);
+	qed_chain_init_pbl_mem(p_chain, p_pbl_virt, p_pbl_phys, pp_addr_tbl);
 	if (!p_pbl_virt)
 		return -ENOMEM;
 
@@ -4826,7 +4827,8 @@
 		/* Fill the PBL table with the physical address of the page */
 		*(dma_addr_t *)p_pbl_virt = p_phys;
 		/* Keep the virtual address of the page */
-		p_chain->pbl.pp_virt_addr_tbl[i] = p_virt;
+		p_chain->pbl.pp_addr_tbl[i].virt_addr = p_virt;
+		p_chain->pbl.pp_addr_tbl[i].dma_map = p_phys;
 
 		p_pbl_virt += QED_CHAIN_PBL_ENTRY_SIZE;
 	}
@@ -5137,6 +5139,11 @@
 
 	num_vports = p_hwfn->qm_info.num_vports;
 
+	if (num_vports < 2) {
+		DP_NOTICE(p_hwfn, "Unexpected num_vports: %d\n", num_vports);
+		return -EINVAL;
+	}
+
 	/* Accounting for the vports which are configured for WFQ explicitly */
 	for (i = 0; i < num_vports; i++) {
 		u32 tmp_speed;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qed/qed_int.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qed/qed_int.c
@@ -256,9 +256,10 @@
 #define PGLUE_ATTENTION_ZLR_VALID		(1 << 25)
 #define PGLUE_ATTENTION_ILT_VALID		(1 << 23)
 
-int qed_pglueb_rbc_attn_handler(struct qed_hwfn *p_hwfn,
-				struct qed_ptt *p_ptt)
+int qed_pglueb_rbc_attn_handler(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
+				bool hw_init)
 {
+	char msg[256];
 	u32 tmp;
 
 	tmp = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_TX_ERR_WR_DETAILS2);
@@ -272,22 +273,23 @@
 		details = qed_rd(p_hwfn, p_ptt,
 				 PGLUE_B_REG_TX_ERR_WR_DETAILS);
 
-		DP_NOTICE(p_hwfn,
-			  "Illegal write by chip to [%08x:%08x] blocked.\n"
-			  "Details: %08x [PFID %02x, VFID %02x, VF_VALID %02x]\n"
-			  "Details2 %08x [Was_error %02x BME deassert %02x FID_enable deassert %02x]\n",
-			  addr_hi, addr_lo, details,
-			  (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_PFID),
-			  (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_VFID),
-			  GET_FIELD(details,
-				    PGLUE_ATTENTION_DETAILS_VF_VALID) ? 1 : 0,
-			  tmp,
-			  GET_FIELD(tmp,
-				    PGLUE_ATTENTION_DETAILS2_WAS_ERR) ? 1 : 0,
-			  GET_FIELD(tmp,
-				    PGLUE_ATTENTION_DETAILS2_BME) ? 1 : 0,
-			  GET_FIELD(tmp,
-				    PGLUE_ATTENTION_DETAILS2_FID_EN) ? 1 : 0);
+		snprintf(msg, sizeof(msg),
+			 "Illegal write by chip to [%08x:%08x] blocked.\n"
+			 "Details: %08x [PFID %02x, VFID %02x, VF_VALID %02x]\n"
+			 "Details2 %08x [Was_error %02x BME deassert %02x FID_enable deassert %02x]",
+			 addr_hi, addr_lo, details,
+			 (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_PFID),
+			 (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_VFID),
+			 !!GET_FIELD(details, PGLUE_ATTENTION_DETAILS_VF_VALID),
+			 tmp,
+			 !!GET_FIELD(tmp, PGLUE_ATTENTION_DETAILS2_WAS_ERR),
+			 !!GET_FIELD(tmp, PGLUE_ATTENTION_DETAILS2_BME),
+			 !!GET_FIELD(tmp, PGLUE_ATTENTION_DETAILS2_FID_EN));
+
+		if (hw_init)
+			DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, "%s\n", msg);
+		else
+			DP_NOTICE(p_hwfn, "%s\n", msg);
 	}
 
 	tmp = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_TX_ERR_RD_DETAILS2);
@@ -320,8 +322,14 @@
 	}
 
 	tmp = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_TX_ERR_WR_DETAILS_ICPL);
-	if (tmp & PGLUE_ATTENTION_ICPL_VALID)
-		DP_NOTICE(p_hwfn, "ICPL error - %08x\n", tmp);
+	if (tmp & PGLUE_ATTENTION_ICPL_VALID) {
+		snprintf(msg, sizeof(msg), "ICPL error - %08x", tmp);
+
+		if (hw_init)
+			DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, "%s\n", msg);
+		else
+			DP_NOTICE(p_hwfn, "%s\n", msg);
+	}
 
 	tmp = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_MASTER_ZLR_ERR_DETAILS);
 	if (tmp & PGLUE_ATTENTION_ZLR_VALID) {
@@ -360,7 +368,7 @@
 
 static int qed_pglueb_rbc_attn_cb(struct qed_hwfn *p_hwfn)
 {
-	return qed_pglueb_rbc_attn_handler(p_hwfn, p_hwfn->p_dpc_ptt);
+	return qed_pglueb_rbc_attn_handler(p_hwfn, p_hwfn->p_dpc_ptt, false);
 }
 
 #define QED_DORQ_ATTENTION_REASON_MASK  (0xfffff)
@@ -1172,7 +1180,8 @@
 			index, attn_bits, attn_acks, asserted_bits,
 			deasserted_bits, p_sb_attn_sw->known_attn);
 	} else if (asserted_bits == 0x100) {
-		DP_INFO(p_hwfn, "MFW indication via attention\n");
+		DP_VERBOSE(p_hwfn, NETIF_MSG_INTR,
+			   "MFW indication via attention\n");
 	} else {
 		DP_VERBOSE(p_hwfn, NETIF_MSG_INTR,
 			   "MFW indication [deassertion]\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qed/qed_int.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qed/qed_int.h
@@ -431,7 +431,7 @@
 
 #define QED_MAPPING_MEMORY_SIZE(dev)	(NUM_OF_SBS(dev))
 
-int qed_pglueb_rbc_attn_handler(struct qed_hwfn *p_hwfn,
-				struct qed_ptt *p_ptt);
+int qed_pglueb_rbc_attn_handler(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
+				bool hw_init);
 
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qed/qed_iwarp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qed/qed_iwarp.c
@@ -1307,6 +1307,14 @@
 	prev_weight = weight;
 
 	while (weight) {
+		/* If the HW device is during recovery, all resources are
+		 * immediately reset without receiving a per-cid indication
+		 * from HW. In this case we don't expect the cid_map to be
+		 * cleared.
+		 */
+		if (p_hwfn->cdev->recov_in_prog)
+			return 0;
+
 		msleep(QED_IWARP_MAX_CID_CLEAN_TIME);
 
 		weight = bitmap_weight(bmap->bitmap, bmap->max_count);
@@ -2742,14 +2750,18 @@
 	iwarp_info->partial_fpdus = kcalloc((u16)p_hwfn->p_rdma_info->num_qps,
 					    sizeof(*iwarp_info->partial_fpdus),
 					    GFP_KERNEL);
-	if (!iwarp_info->partial_fpdus)
+	if (!iwarp_info->partial_fpdus) {
+		rc = -ENOMEM;
 		goto err;
+	}
 
 	iwarp_info->max_num_partial_fpdus = (u16)p_hwfn->p_rdma_info->num_qps;
 
 	iwarp_info->mpa_intermediate_buf = kzalloc(buff_size, GFP_KERNEL);
-	if (!iwarp_info->mpa_intermediate_buf)
+	if (!iwarp_info->mpa_intermediate_buf) {
+		rc = -ENOMEM;
 		goto err;
+	}
 
 	/* The mpa_bufs array serves for pending RX packets received on the
 	 * mpa ll2 that don't have place on the tx ring and require later
@@ -2759,8 +2771,10 @@
 	iwarp_info->mpa_bufs = kcalloc(data.input.rx_num_desc,
 				       sizeof(*iwarp_info->mpa_bufs),
 				       GFP_KERNEL);
-	if (!iwarp_info->mpa_bufs)
+	if (!iwarp_info->mpa_bufs) {
+		rc = -ENOMEM;
 		goto err;
+	}
 
 	INIT_LIST_HEAD(&iwarp_info->mpa_buf_pending_list);
 	INIT_LIST_HEAD(&iwarp_info->mpa_buf_list);
@@ -2832,8 +2846,6 @@
 	if (rc)
 		return rc;
 
-	qed_spq_unregister_async_cb(p_hwfn, PROTOCOLID_IWARP);
-
 	return qed_iwarp_ll2_stop(p_hwfn);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qed/qed_l2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qed/qed_l2.c
@@ -2001,6 +2001,9 @@
 			     struct qed_ptt *p_ptt,
 			     struct qed_arfs_config_params *p_cfg_params)
 {
+	if (test_bit(QED_MF_DISABLE_ARFS, &p_hwfn->cdev->mf_bits))
+		return;
+
 	if (p_cfg_params->mode != QED_FILTER_CONFIG_MODE_DISABLE) {
 		qed_gft_config(p_hwfn, p_ptt, p_hwfn->rel_pf_id,
 			       p_cfg_params->tcp,
@@ -2778,25 +2781,6 @@
 	return qed_filter_mcast_cmd(cdev, &mcast, QED_SPQ_MODE_CB, NULL);
 }
 
-static int qed_configure_filter(struct qed_dev *cdev,
-				struct qed_filter_params *params)
-{
-	enum qed_filter_rx_mode_type accept_flags;
-
-	switch (params->type) {
-	case QED_FILTER_TYPE_UCAST:
-		return qed_configure_filter_ucast(cdev, &params->filter.ucast);
-	case QED_FILTER_TYPE_MCAST:
-		return qed_configure_filter_mcast(cdev, &params->filter.mcast);
-	case QED_FILTER_TYPE_RX_MODE:
-		accept_flags = params->filter.accept_flags;
-		return qed_configure_filter_rx_mode(cdev, accept_flags);
-	default:
-		DP_NOTICE(cdev, "Unknown filter type %d\n", (int)params->type);
-		return -EINVAL;
-	}
-}
-
 static int qed_configure_arfs_searcher(struct qed_dev *cdev,
 				       enum qed_filter_config_mode mode)
 {
@@ -2929,7 +2913,9 @@
 	.q_rx_stop = &qed_stop_rxq,
 	.q_tx_start = &qed_start_txq,
 	.q_tx_stop = &qed_stop_txq,
-	.filter_config = &qed_configure_filter,
+	.filter_config_rx_mode = &qed_configure_filter_rx_mode,
+	.filter_config_ucast = &qed_configure_filter_ucast,
+	.filter_config_mcast = &qed_configure_filter_mcast,
 	.fastpath_stop = &qed_fastpath_stop,
 	.eth_cqe_completion = &qed_fp_cqe_completion,
 	.get_vport_stats = &qed_get_vport_stats,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qed/qed_ll2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qed/qed_ll2.c
@@ -113,7 +113,10 @@
 static int qed_ll2_alloc_buffer(struct qed_dev *cdev,
 				u8 **data, dma_addr_t *phys_addr)
 {
-	*data = kmalloc(cdev->ll2->rx_size, GFP_ATOMIC);
+	size_t size = cdev->ll2->rx_size + NET_SKB_PAD +
+		      SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+
+	*data = kmalloc(size, GFP_ATOMIC);
 	if (!(*data)) {
 		DP_INFO(cdev, "Failed to allocate LL2 buffer data\n");
 		return -ENOMEM;
@@ -353,6 +356,9 @@
 	unsigned long flags;
 	int rc = -EINVAL;
 
+	if (!p_ll2_conn)
+		return rc;
+
 	spin_lock_irqsave(&p_tx->lock, flags);
 	if (p_tx->b_completing_packet) {
 		rc = -EBUSY;
@@ -526,7 +532,16 @@
 	unsigned long flags = 0;
 	int rc = 0;
 
+	if (!p_ll2_conn)
+		return rc;
+
 	spin_lock_irqsave(&p_rx->lock, flags);
+
+	if (!QED_LL2_RX_REGISTERED(p_ll2_conn)) {
+		spin_unlock_irqrestore(&p_rx->lock, flags);
+		return 0;
+	}
+
 	cq_new_idx = le16_to_cpu(*p_rx->p_fw_cons);
 	cq_old_idx = qed_chain_get_cons_idx(&p_rx->rcq_chain);
 
@@ -847,6 +862,9 @@
 	struct qed_ll2_info *p_ll2_conn = (struct qed_ll2_info *)p_cookie;
 	int rc;
 
+	if (!p_ll2_conn)
+		return 0;
+
 	if (!QED_LL2_RX_REGISTERED(p_ll2_conn))
 		return 0;
 
@@ -870,6 +888,9 @@
 	u16 new_idx = 0, num_bds = 0;
 	int rc;
 
+	if (!p_ll2_conn)
+		return 0;
+
 	if (!QED_LL2_TX_REGISTERED(p_ll2_conn))
 		return 0;
 
@@ -1642,6 +1663,8 @@
 	if (!p_ll2_conn)
 		return -EINVAL;
 	p_rx = &p_ll2_conn->rx_queue;
+	if (!p_rx->set_prod_addr)
+		return -EIO;
 
 	spin_lock_irqsave(&p_rx->lock, flags);
 	if (!list_empty(&p_rx->free_descq))
@@ -2429,7 +2452,7 @@
 	INIT_LIST_HEAD(&cdev->ll2->list);
 	spin_lock_init(&cdev->ll2->lock);
 
-	cdev->ll2->rx_size = NET_SKB_PAD + ETH_HLEN +
+	cdev->ll2->rx_size = PRM_DMA_PAD_BYTES_NUM + ETH_HLEN +
 			     L1_CACHE_BYTES + params->mtu;
 
 	/* Allocate memory for LL2.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qed/qed_ll2.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qed/qed_ll2.h
@@ -123,9 +123,9 @@
 	enum core_tx_dest tx_dest;
 	u8 tx_stats_en;
 	bool main_func_queue;
+	struct qed_ll2_cbs cbs;
 	struct qed_ll2_rx_queue rx_queue;
 	struct qed_ll2_tx_queue tx_queue;
-	struct qed_ll2_cbs cbs;
 };
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qed/qed_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qed/qed_main.c
@@ -280,6 +280,8 @@
 		dev_info->fw_eng = FW_ENGINEERING_VERSION;
 		dev_info->b_inter_pf_switch = test_bit(QED_MF_INTER_PF_SWITCH,
 						       &cdev->mf_bits);
+		if (!test_bit(QED_MF_DISABLE_ARFS, &cdev->mf_bits))
+			dev_info->b_arfs_capable = true;
 		dev_info->tx_switching = true;
 
 		if (hw_info->b_wol_support == QED_WOL_SUPPORT_PME)
@@ -557,7 +559,12 @@
 			rc = cnt;
 	}
 
-	if (rc > 0) {
+	/* For VFs, we should return with an error in case we didn't get the
+	 * exact number of msix vectors as we requested.
+	 * Not doing that will lead to a crash when starting queues for
+	 * this VF.
+	 */
+	if ((IS_PF(cdev) && rc > 0) || (IS_VF(cdev) && rc == cnt)) {
 		/* MSI-x configuration was achieved */
 		int_params->out.int_mode = QED_INT_MODE_MSIX;
 		int_params->out.num_vectors = rc;
@@ -1087,9 +1094,6 @@
 #define QED_PERIODIC_DB_REC_INTERVAL_MS		100
 #define QED_PERIODIC_DB_REC_INTERVAL \
 	msecs_to_jiffies(QED_PERIODIC_DB_REC_INTERVAL_MS)
-#define QED_PERIODIC_DB_REC_WAIT_COUNT		10
-#define QED_PERIODIC_DB_REC_WAIT_INTERVAL \
-	(QED_PERIODIC_DB_REC_INTERVAL_MS / QED_PERIODIC_DB_REC_WAIT_COUNT)
 
 static int qed_slowpath_delayed_work(struct qed_hwfn *hwfn,
 				     enum qed_slowpath_wq_flag wq_flag,
@@ -1123,7 +1127,7 @@
 
 static void qed_slowpath_wq_stop(struct qed_dev *cdev)
 {
-	int i, sleep_count = QED_PERIODIC_DB_REC_WAIT_COUNT;
+	int i;
 
 	if (IS_VF(cdev))
 		return;
@@ -1135,13 +1139,7 @@
 		/* Stop queuing new delayed works */
 		cdev->hwfns[i].slowpath_wq_active = false;
 
-		/* Wait until the last periodic doorbell recovery is executed */
-		while (test_bit(QED_SLOWPATH_PERIODIC_DB_REC,
-				&cdev->hwfns[i].slowpath_task_flags) &&
-		       sleep_count--)
-			msleep(QED_PERIODIC_DB_REC_WAIT_INTERVAL);
-
-		flush_workqueue(cdev->hwfns[i].slowpath_wq);
+		cancel_delayed_work(&cdev->hwfns[i].slowpath_task);
 		destroy_workqueue(cdev->hwfns[i].slowpath_wq);
 	}
 }
@@ -1179,7 +1177,6 @@
 static int qed_slowpath_wq_start(struct qed_dev *cdev)
 {
 	struct qed_hwfn *hwfn;
-	char name[NAME_SIZE];
 	int i;
 
 	if (IS_VF(cdev))
@@ -1188,11 +1185,11 @@
 	for_each_hwfn(cdev, i) {
 		hwfn = &cdev->hwfns[i];
 
-		snprintf(name, NAME_SIZE, "slowpath-%02x:%02x.%02x",
-			 cdev->pdev->bus->number,
-			 PCI_SLOT(cdev->pdev->devfn), hwfn->abs_pf_id);
+		hwfn->slowpath_wq = alloc_workqueue("slowpath-%02x:%02x.%02x",
+					 0, 0, cdev->pdev->bus->number,
+					 PCI_SLOT(cdev->pdev->devfn),
+					 hwfn->abs_pf_id);
 
-		hwfn->slowpath_wq = alloc_workqueue(name, 0, 0);
 		if (!hwfn->slowpath_wq) {
 			DP_NOTICE(hwfn, "Cannot create slowpath workqueue\n");
 			return -ENOMEM;
@@ -1240,6 +1237,7 @@
 			} else {
 				DP_NOTICE(cdev,
 					  "Failed to acquire PTT for aRFS\n");
+				rc = -EINVAL;
 				goto err;
 			}
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qed/qed_mcp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qed/qed_mcp.c
@@ -498,14 +498,18 @@
 
 		spin_lock_bh(&p_hwfn->mcp_info->cmd_lock);
 
-		if (!qed_mcp_has_pending_cmd(p_hwfn))
+		if (!qed_mcp_has_pending_cmd(p_hwfn)) {
+			spin_unlock_bh(&p_hwfn->mcp_info->cmd_lock);
 			break;
+		}
 
 		rc = qed_mcp_update_pending_cmd(p_hwfn, p_ptt);
-		if (!rc)
+		if (!rc) {
+			spin_unlock_bh(&p_hwfn->mcp_info->cmd_lock);
 			break;
-		else if (rc != -EAGAIN)
+		} else if (rc != -EAGAIN) {
 			goto err;
+		}
 
 		spin_unlock_bh(&p_hwfn->mcp_info->cmd_lock);
 
@@ -522,6 +526,8 @@
 		return -EAGAIN;
 	}
 
+	spin_lock_bh(&p_hwfn->mcp_info->cmd_lock);
+
 	/* Send the mailbox command */
 	qed_mcp_reread_offsets(p_hwfn, p_ptt);
 	seq_num = ++p_hwfn->mcp_info->drv_mb_seq;
@@ -548,14 +554,18 @@
 
 		spin_lock_bh(&p_hwfn->mcp_info->cmd_lock);
 
-		if (p_cmd_elem->b_is_completed)
+		if (p_cmd_elem->b_is_completed) {
+			spin_unlock_bh(&p_hwfn->mcp_info->cmd_lock);
 			break;
+		}
 
 		rc = qed_mcp_update_pending_cmd(p_hwfn, p_ptt);
-		if (!rc)
+		if (!rc) {
+			spin_unlock_bh(&p_hwfn->mcp_info->cmd_lock);
 			break;
-		else if (rc != -EAGAIN)
+		} else if (rc != -EAGAIN) {
 			goto err;
+		}
 
 		spin_unlock_bh(&p_hwfn->mcp_info->cmd_lock);
 	} while (++cnt < max_retries);
@@ -576,6 +586,7 @@
 		return -EAGAIN;
 	}
 
+	spin_lock_bh(&p_hwfn->mcp_info->cmd_lock);
 	qed_mcp_cmd_del_elem(p_hwfn, p_cmd_elem);
 	spin_unlock_bh(&p_hwfn->mcp_info->cmd_lock);
 
@@ -3048,7 +3059,9 @@
 	if (rc)
 		return rc;
 
-	if (((rsp & FW_MSG_CODE_MASK) != FW_MSG_CODE_OK))
+	if (((rsp & FW_MSG_CODE_MASK) == FW_MSG_CODE_UNSUPPORTED))
+		rc = -EOPNOTSUPP;
+	else if (((rsp & FW_MSG_CODE_MASK) != FW_MSG_CODE_OK))
 		rc = -EINVAL;
 
 	return rc;
@@ -3149,12 +3162,20 @@
 	return rc;
 }
 
+void qed_mcp_nvm_info_free(struct qed_hwfn *p_hwfn)
+{
+	kfree(p_hwfn->nvm_info.image_att);
+	p_hwfn->nvm_info.image_att = NULL;
+	p_hwfn->nvm_info.valid = false;
+}
+
 int
 qed_mcp_get_nvm_image_att(struct qed_hwfn *p_hwfn,
 			  enum qed_nvm_images image_id,
 			  struct qed_nvm_image_att *p_image_att)
 {
 	enum nvm_image_type type;
+	int rc;
 	u32 i;
 
 	/* Translate image_id into MFW definitions */
@@ -3180,7 +3201,10 @@
 		return -EINVAL;
 	}
 
-	qed_mcp_nvm_info_populate(p_hwfn);
+	rc = qed_mcp_nvm_info_populate(p_hwfn);
+	if (rc)
+		return rc;
+
 	for (i = 0; i < p_hwfn->nvm_info.num_images; i++)
 		if (type == p_hwfn->nvm_info.image_att[i].image_type)
 			break;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qed/qed_mcp.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qed/qed_mcp.h
@@ -1193,6 +1193,13 @@
 int qed_mcp_nvm_info_populate(struct qed_hwfn *p_hwfn);
 
 /**
+ * @brief Delete nvm info shadow in the given hardware function
+ *
+ * @param p_hwfn
+ */
+void qed_mcp_nvm_info_free(struct qed_hwfn *p_hwfn);
+
+/**
  * @brief Get the engine affinity configuration.
  *
  * @param p_hwfn
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qed/qed_ptp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qed/qed_ptp.c
@@ -44,8 +44,8 @@
 /* Add/subtract the Adjustment_Value when making a Drift adjustment */
 #define QED_DRIFT_CNTR_DIRECTION_SHIFT		31
 #define QED_TIMESTAMP_MASK			BIT(16)
-/* Param mask for Hardware to detect/timestamp the unicast PTP packets */
-#define QED_PTP_UCAST_PARAM_MASK		0xF
+/* Param mask for Hardware to detect/timestamp the L2/L4 unicast PTP packets */
+#define QED_PTP_UCAST_PARAM_MASK              0x70F
 
 static enum qed_resc_lock qed_ptcdev_to_resc(struct qed_hwfn *p_hwfn)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qed/qed_rdma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qed/qed_rdma.c
@@ -1245,8 +1245,7 @@
 
 	if (!rdma_cxt || !in_params || !out_params ||
 	    !p_hwfn->p_rdma_info->active) {
-		DP_ERR(p_hwfn->cdev,
-		       "qed roce create qp failed due to NULL entry (rdma_cxt=%p, in=%p, out=%p, roce_info=?\n",
+		pr_err("qed roce create qp failed due to NULL entry (rdma_cxt=%p, in=%p, out=%p, roce_info=?\n",
 		       rdma_cxt, in_params, out_params);
 		return NULL;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qed/qed_roce.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qed/qed_roce.c
@@ -107,13 +107,20 @@
 	 * Beyond the added delay we clear the bitmap anyway.
 	 */
 	while (bitmap_weight(rcid_map->bitmap, rcid_map->max_count)) {
+		/* If the HW device is during recovery, all resources are
+		 * immediately reset without receiving a per-cid indication
+		 * from HW. In this case we don't expect the cid bitmap to be
+		 * cleared.
+		 */
+		if (p_hwfn->cdev->recov_in_prog)
+			return;
+
 		msleep(100);
 		if (wait_count++ > 20) {
 			DP_NOTICE(p_hwfn, "cid bitmap wait timed out\n");
 			break;
 		}
 	}
-	qed_spq_unregister_async_cb(p_hwfn, PROTOCOLID_ROCE);
 }
 
 static void qed_rdma_copy_gids(struct qed_rdma_qp *qp, __le32 *src_gid,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qed/qed_sriov.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qed/qed_sriov.c
@@ -96,6 +96,7 @@
 		p_ramrod->personality = PERSONALITY_ETH;
 		break;
 	case QED_PCI_ETH_ROCE:
+	case QED_PCI_ETH_IWARP:
 		p_ramrod->personality = PERSONALITY_RDMA_AND_ETH;
 		break;
 	default:
@@ -3002,12 +3003,16 @@
 	u8 mask = QED_ACCEPT_UCAST_UNMATCHED | QED_ACCEPT_MCAST_UNMATCHED;
 	struct qed_filter_accept_flags *flags = &params->accept_flags;
 	struct qed_public_vf_info *vf_info;
+	u16 tlv_mask;
+
+	tlv_mask = BIT(QED_IOV_VP_UPDATE_ACCEPT_PARAM) |
+		   BIT(QED_IOV_VP_UPDATE_ACCEPT_ANY_VLAN);
 
 	/* Untrusted VFs can't even be trusted to know that fact.
 	 * Simply indicate everything is configured fine, and trace
 	 * configuration 'behind their back'.
 	 */
-	if (!(*tlvs & BIT(QED_IOV_VP_UPDATE_ACCEPT_PARAM)))
+	if (!(*tlvs & tlv_mask))
 		return 0;
 
 	vf_info = qed_iov_get_public_vf_info(hwfn, vfid, true);
@@ -3024,6 +3029,13 @@
 			flags->tx_accept_filter &= ~mask;
 	}
 
+	if (params->update_accept_any_vlan_flg) {
+		vf_info->accept_any_vlan = params->accept_any_vlan;
+
+		if (vf_info->forced_vlan && !vf_info->is_trusted_configured)
+			params->accept_any_vlan = false;
+	}
+
 	return 0;
 }
 
@@ -3800,11 +3812,11 @@
 	return found;
 }
 
-static void qed_iov_get_link(struct qed_hwfn *p_hwfn,
-			     u16 vfid,
-			     struct qed_mcp_link_params *p_params,
-			     struct qed_mcp_link_state *p_link,
-			     struct qed_mcp_link_capabilities *p_caps)
+static int qed_iov_get_link(struct qed_hwfn *p_hwfn,
+			    u16 vfid,
+			    struct qed_mcp_link_params *p_params,
+			    struct qed_mcp_link_state *p_link,
+			    struct qed_mcp_link_capabilities *p_caps)
 {
 	struct qed_vf_info *p_vf = qed_iov_get_vf_info(p_hwfn,
 						       vfid,
@@ -3812,7 +3824,7 @@
 	struct qed_bulletin_content *p_bulletin;
 
 	if (!p_vf)
-		return;
+		return -EINVAL;
 
 	p_bulletin = p_vf->bulletin.p_virt;
 
@@ -3822,6 +3834,7 @@
 		__qed_vf_get_link_state(p_hwfn, p_link, p_bulletin);
 	if (p_caps)
 		__qed_vf_get_link_caps(p_hwfn, p_caps, p_bulletin);
+	return 0;
 }
 
 static int
@@ -4391,6 +4404,9 @@
 	}
 
 	vf = qed_iov_get_vf_info(QED_LEADING_HWFN(cdev), (u16)vfid, true);
+	if (!vf)
+		return -EINVAL;
+
 	vport_id = vf->vport_id;
 
 	return qed_configure_vport_wfq(cdev, vport_id, rate);
@@ -4683,6 +4699,7 @@
 	struct qed_public_vf_info *vf_info;
 	struct qed_mcp_link_state link;
 	u32 tx_rate;
+	int ret;
 
 	/* Sanitize request */
 	if (IS_VF(cdev))
@@ -4696,7 +4713,9 @@
 
 	vf_info = qed_iov_get_public_vf_info(hwfn, vf_id, true);
 
-	qed_iov_get_link(hwfn, vf_id, NULL, &link, NULL);
+	ret = qed_iov_get_link(hwfn, vf_id, NULL, &link, NULL);
+	if (ret)
+		return ret;
 
 	/* Fill information about VF */
 	ivi->vf = vf_id;
@@ -4712,6 +4731,7 @@
 	tx_rate = vf_info->tx_rate;
 	ivi->max_tx_rate = tx_rate ? tx_rate : link.speed;
 	ivi->min_tx_rate = qed_iov_get_vf_min_rate(hwfn, vf_id);
+	ivi->trusted = vf_info->is_trusted_request;
 
 	return 0;
 }
@@ -5133,7 +5153,7 @@
 
 		/* Validate that the VF has a configured vport */
 		vf = qed_iov_get_vf_info(hwfn, i, true);
-		if (!vf->vport_instance)
+		if (!vf || !vf->vport_instance)
 			continue;
 
 		memset(&params, 0, sizeof(params));
@@ -5142,6 +5162,12 @@
 
 		params.update_ctl_frame_check = 1;
 		params.mac_chk_en = !vf_info->is_trusted_configured;
+		params.update_accept_any_vlan_flg = 0;
+
+		if (vf_info->accept_any_vlan && vf_info->forced_vlan) {
+			params.update_accept_any_vlan_flg = 1;
+			params.accept_any_vlan = vf_info->accept_any_vlan;
+		}
 
 		if (vf_info->rx_accept_mode & mask) {
 			flags->update_rx_mode_config = 1;
@@ -5157,13 +5183,20 @@
 		if (!vf_info->is_trusted_configured) {
 			flags->rx_accept_filter &= ~mask;
 			flags->tx_accept_filter &= ~mask;
+			params.accept_any_vlan = false;
 		}
 
 		if (flags->update_rx_mode_config ||
 		    flags->update_tx_mode_config ||
-		    params.update_ctl_frame_check)
+		    params.update_ctl_frame_check ||
+		    params.update_accept_any_vlan_flg) {
+			DP_VERBOSE(hwfn, QED_MSG_IOV,
+				   "vport update config for %s VF[abs 0x%x rel 0x%x]\n",
+				   vf_info->is_trusted_configured ? "trusted" : "untrusted",
+				   vf->abs_vf_id, vf->relative_vf_id);
 			qed_sp_vport_update(hwfn, &params,
 					    QED_SPQ_MODE_EBLOCK, NULL);
+		}
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qed/qed_sriov.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qed/qed_sriov.h
@@ -88,6 +88,7 @@
 	bool is_trusted_request;
 	u8 rx_accept_mode;
 	u8 tx_accept_mode;
+	bool accept_any_vlan;
 };
 
 struct qed_iov_vf_init_params {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qed/qed_vf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qed/qed_vf.c
@@ -81,12 +81,17 @@
 	mutex_unlock(&(p_hwfn->vf_iov_info->mutex));
 }
 
+#define QED_VF_CHANNEL_USLEEP_ITERATIONS	90
+#define QED_VF_CHANNEL_USLEEP_DELAY		100
+#define QED_VF_CHANNEL_MSLEEP_ITERATIONS	10
+#define QED_VF_CHANNEL_MSLEEP_DELAY		25
+
 static int qed_send_msg2pf(struct qed_hwfn *p_hwfn, u8 *done, u32 resp_size)
 {
 	union vfpf_tlvs *p_req = p_hwfn->vf_iov_info->vf2pf_request;
 	struct ustorm_trigger_vf_zone trigger;
 	struct ustorm_vf_zone *zone_data;
-	int rc = 0, time = 100;
+	int iter, rc = 0;
 
 	zone_data = (struct ustorm_vf_zone *)PXP_VF_BAR0_START_USDM_ZONE_B;
 
@@ -126,11 +131,19 @@
 	REG_WR(p_hwfn, (uintptr_t)&zone_data->trigger, *((u32 *)&trigger));
 
 	/* When PF would be done with the response, it would write back to the
-	 * `done' address. Poll until then.
+	 * `done' address from a coherent DMA zone. Poll until then.
 	 */
-	while ((!*done) && time) {
-		msleep(25);
-		time--;
+
+	iter = QED_VF_CHANNEL_USLEEP_ITERATIONS;
+	while (!*done && iter--) {
+		udelay(QED_VF_CHANNEL_USLEEP_DELAY);
+		dma_rmb();
+	}
+
+	iter = QED_VF_CHANNEL_MSLEEP_ITERATIONS;
+	while (!*done && iter--) {
+		msleep(QED_VF_CHANNEL_MSLEEP_DELAY);
+		dma_rmb();
 	}
 
 	if (!*done) {
@@ -526,6 +539,9 @@
 						    p_iov->bulletin.size,
 						    &p_iov->bulletin.phys,
 						    GFP_KERNEL);
+	if (!p_iov->bulletin.p_virt)
+		goto free_pf2vf_reply;
+
 	DP_VERBOSE(p_hwfn, QED_MSG_IOV,
 		   "VF's bulletin Board [%p virt 0x%llx phys 0x%08x bytes]\n",
 		   p_iov->bulletin.p_virt,
@@ -565,6 +581,10 @@
 
 	return rc;
 
+free_pf2vf_reply:
+	dma_free_coherent(&p_hwfn->cdev->pdev->dev,
+			  sizeof(union pfvf_tlvs),
+			  p_iov->pf2vf_reply, p_iov->pf2vf_reply_phys);
 free_vf2pf_request:
 	dma_free_coherent(&p_hwfn->cdev->pdev->dev,
 			  sizeof(union vfpf_tlvs),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qede/qede.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qede/qede.h
@@ -163,6 +163,8 @@
 	struct list_head entry;
 	struct list_head rdma_event_list;
 	struct workqueue_struct *rdma_wq;
+	struct kref refcnt;
+	struct completion event_comp;
 	bool exp_recovery;
 };
 
@@ -572,12 +574,14 @@
 #define RX_RING_SIZE		((u16)BIT(RX_RING_SIZE_POW))
 #define NUM_RX_BDS_MAX		(RX_RING_SIZE - 1)
 #define NUM_RX_BDS_MIN		128
+#define NUM_RX_BDS_KDUMP_MIN	63
 #define NUM_RX_BDS_DEF		((u16)BIT(10) - 1)
 
 #define TX_RING_SIZE_POW	13
 #define TX_RING_SIZE		((u16)BIT(TX_RING_SIZE_POW))
 #define NUM_TX_BDS_MAX		(TX_RING_SIZE - 1)
 #define NUM_TX_BDS_MIN		128
+#define NUM_TX_BDS_KDUMP_MIN	63
 #define NUM_TX_BDS_DEF		NUM_TX_BDS_MAX
 
 #define QEDE_MIN_PKT_LEN		64
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qede/qede_filter.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qede/qede_filter.c
@@ -336,6 +336,9 @@
 {
 	int i;
 
+	if (!edev->dev_info.common.b_arfs_capable)
+		return -EINVAL;
+
 	edev->arfs = vzalloc(sizeof(*edev->arfs));
 	if (!edev->arfs)
 		return -ENOMEM;
@@ -641,30 +644,28 @@
 				 enum qed_filter_xcast_params_type opcode,
 				 unsigned char mac[ETH_ALEN])
 {
-	struct qed_filter_params filter_cmd;
+	struct qed_filter_ucast_params ucast;
 
-	memset(&filter_cmd, 0, sizeof(filter_cmd));
-	filter_cmd.type = QED_FILTER_TYPE_UCAST;
-	filter_cmd.filter.ucast.type = opcode;
-	filter_cmd.filter.ucast.mac_valid = 1;
-	ether_addr_copy(filter_cmd.filter.ucast.mac, mac);
+	memset(&ucast, 0, sizeof(ucast));
+	ucast.type = opcode;
+	ucast.mac_valid = 1;
+	ether_addr_copy(ucast.mac, mac);
 
-	return edev->ops->filter_config(edev->cdev, &filter_cmd);
+	return edev->ops->filter_config_ucast(edev->cdev, &ucast);
 }
 
 static int qede_set_ucast_rx_vlan(struct qede_dev *edev,
 				  enum qed_filter_xcast_params_type opcode,
 				  u16 vid)
 {
-	struct qed_filter_params filter_cmd;
+	struct qed_filter_ucast_params ucast;
 
-	memset(&filter_cmd, 0, sizeof(filter_cmd));
-	filter_cmd.type = QED_FILTER_TYPE_UCAST;
-	filter_cmd.filter.ucast.type = opcode;
-	filter_cmd.filter.ucast.vlan_valid = 1;
-	filter_cmd.filter.ucast.vlan = vid;
+	memset(&ucast, 0, sizeof(ucast));
+	ucast.type = opcode;
+	ucast.vlan_valid = 1;
+	ucast.vlan = vid;
 
-	return edev->ops->filter_config(edev->cdev, &filter_cmd);
+	return edev->ops->filter_config_ucast(edev->cdev, &ucast);
 }
 
 static int qede_config_accept_any_vlan(struct qede_dev *edev, bool action)
@@ -1130,18 +1131,17 @@
 				 enum qed_filter_xcast_params_type opcode,
 				 unsigned char *mac, int num_macs)
 {
-	struct qed_filter_params filter_cmd;
+	struct qed_filter_mcast_params mcast;
 	int i;
 
-	memset(&filter_cmd, 0, sizeof(filter_cmd));
-	filter_cmd.type = QED_FILTER_TYPE_MCAST;
-	filter_cmd.filter.mcast.type = opcode;
-	filter_cmd.filter.mcast.num = num_macs;
+	memset(&mcast, 0, sizeof(mcast));
+	mcast.type = opcode;
+	mcast.num = num_macs;
 
 	for (i = 0; i < num_macs; i++, mac += ETH_ALEN)
-		ether_addr_copy(filter_cmd.filter.mcast.mac[i], mac);
+		ether_addr_copy(mcast.mac[i], mac);
 
-	return edev->ops->filter_config(edev->cdev, &filter_cmd);
+	return edev->ops->filter_config_mcast(edev->cdev, &mcast);
 }
 
 int qede_set_mac_addr(struct net_device *ndev, void *p)
@@ -1230,7 +1230,7 @@
 	netif_addr_lock_bh(ndev);
 
 	mc_count = netdev_mc_count(ndev);
-	if (mc_count < 64) {
+	if (mc_count <= 64) {
 		netdev_for_each_mc_addr(ha, ndev) {
 			ether_addr_copy(temp, ha->addr);
 			temp += ETH_ALEN;
@@ -1267,7 +1267,6 @@
 {
 	enum qed_filter_rx_mode_type accept_flags;
 	struct qede_dev *edev = netdev_priv(ndev);
-	struct qed_filter_params rx_mode;
 	unsigned char *uc_macs, *temp;
 	struct netdev_hw_addr *ha;
 	int rc, uc_count;
@@ -1293,10 +1292,6 @@
 
 	netif_addr_unlock_bh(ndev);
 
-	/* Configure the struct for the Rx mode */
-	memset(&rx_mode, 0, sizeof(struct qed_filter_params));
-	rx_mode.type = QED_FILTER_TYPE_RX_MODE;
-
 	/* Remove all previous unicast secondary macs and multicast macs
 	 * (configrue / leave the primary mac)
 	 */
@@ -1344,8 +1339,7 @@
 		qede_config_accept_any_vlan(edev, false);
 	}
 
-	rx_mode.filter.accept_flags = accept_flags;
-	edev->ops->filter_config(edev->cdev, &rx_mode);
+	edev->ops->filter_config_rx_mode(edev->cdev, accept_flags);
 out:
 	kfree(uc_macs);
 }
@@ -1946,8 +1940,8 @@
 			    struct flow_cls_offload *f)
 {
 	struct qede_arfs_fltr_node *n;
-	int min_hlen, rc = -EINVAL;
 	struct qede_arfs_tuple t;
+	int min_hlen, rc;
 
 	__qede_lock(edev);
 
@@ -1957,7 +1951,8 @@
 	}
 
 	/* parse flower attribute and prepare filter */
-	if (qede_parse_flow_attr(edev, proto, f->rule, &t))
+	rc = qede_parse_flow_attr(edev, proto, f->rule, &t);
+	if (rc)
 		goto unlock;
 
 	/* Validate profile mode and number of filters */
@@ -1966,12 +1961,15 @@
 		DP_NOTICE(edev,
 			  "Filter configuration invalidated, filter mode=0x%x, configured mode=0x%x, filter count=0x%x\n",
 			  t.mode, edev->arfs->mode, edev->arfs->filter_count);
+		rc = -EINVAL;
 		goto unlock;
 	}
 
 	/* parse tc actions and get the vf_id */
-	if (qede_parse_actions(edev, &f->rule->action))
+	if (qede_parse_actions(edev, &f->rule->action)) {
+		rc = -EINVAL;
 		goto unlock;
+	}
 
 	if (qede_flow_find_fltr(edev, &t)) {
 		rc = -EEXIST;
@@ -2076,10 +2074,9 @@
 	if (IS_ERR(flow))
 		return PTR_ERR(flow);
 
-	if (qede_parse_flow_attr(edev, proto, flow->rule, t)) {
-		err = -EINVAL;
+	err = qede_parse_flow_attr(edev, proto, flow->rule, t);
+	if (err)
 		goto err_out;
-	}
 
 	/* Make sure location is valid and filter isn't already set */
 	err = qede_flow_spec_validate(edev, &flow->rule->action, t,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qede/qede_fp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qede/qede_fp.c
@@ -723,6 +723,9 @@
 	buf = page_address(bd->data) + bd->page_offset;
 	skb = build_skb(buf, rxq->rx_buf_seg_size);
 
+	if (unlikely(!skb))
+		return NULL;
+
 	skb_reserve(skb, pad);
 	skb_put(skb, len);
 
@@ -1597,6 +1600,13 @@
 			data_split = true;
 		}
 	} else {
+		if (unlikely(skb->len > ETH_TX_MAX_NON_LSO_PKT_LEN)) {
+			DP_ERR(edev, "Unexpected non LSO skb length = 0x%x\n", skb->len);
+			qede_free_failed_tx_pkt(txq, first_bd, 0, false);
+			qede_update_tx_producer(txq);
+			return NETDEV_TX_OK;
+		}
+
 		val |= ((skb->len & ETH_TX_DATA_1ST_BD_PKT_LEN_MASK) <<
 			 ETH_TX_DATA_1ST_BD_PKT_LEN_SHIFT);
 	}
@@ -1737,6 +1747,11 @@
 			      ntohs(udp_hdr(skb)->dest) != gnv_port))
 				return features & ~(NETIF_F_CSUM_MASK |
 						    NETIF_F_GSO_MASK);
+		} else if (l4_proto == IPPROTO_IPIP) {
+			/* IPIP tunnels are unknown to the device or at least unsupported natively,
+			 * offloads for them can't be done trivially, so disable them for such skb.
+			 */
+			return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
 		}
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -29,6 +29,7 @@
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  */
+#include <linux/crash_dump.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/version.h>
@@ -707,8 +708,14 @@
 	edev->dp_module = dp_module;
 	edev->dp_level = dp_level;
 	edev->ops = qed_ops;
-	edev->q_num_rx_buffers = NUM_RX_BDS_DEF;
-	edev->q_num_tx_buffers = NUM_TX_BDS_DEF;
+
+	if (is_kdump_kernel()) {
+		edev->q_num_rx_buffers = NUM_RX_BDS_KDUMP_MIN;
+		edev->q_num_tx_buffers = NUM_TX_BDS_KDUMP_MIN;
+	} else {
+		edev->q_num_rx_buffers = NUM_RX_BDS_DEF;
+		edev->q_num_tx_buffers = NUM_TX_BDS_DEF;
+	}
 
 	DP_INFO(edev, "Allocated netdev with %d tx queues and %d rx queues\n",
 		info->num_queues, info->num_queues);
@@ -763,7 +770,7 @@
 		      NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
 		      NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_HW_TC;
 
-	if (!IS_VF(edev) && edev->dev_info.common.num_hwfns == 1)
+	if (edev->dev_info.common.b_arfs_capable)
 		hw_features |= NETIF_F_NTUPLE;
 
 	if (edev->dev_info.common.vxlan_enable ||
@@ -1151,7 +1158,7 @@
 
 	/* PTP not supported on VFs */
 	if (!is_vf)
-		qede_ptp_enable(edev, (mode == QEDE_PROBE_NORMAL));
+		qede_ptp_enable(edev);
 
 	edev->ops->register_ops(cdev, &qede_ll_ops, edev);
 
@@ -1240,6 +1247,7 @@
 	if (system_state == SYSTEM_POWER_OFF)
 		return;
 	qed_ops->common->remove(cdev);
+	edev->cdev = NULL;
 
 	/* Since this can happen out-of-sync with other flows,
 	 * don't release the netdevice until after slowpath stop
@@ -1406,6 +1414,7 @@
 		rxq->rx_buf_seg_size = roundup_pow_of_two(size);
 	} else {
 		rxq->rx_buf_seg_size = PAGE_SIZE;
+		edev->ndev->features &= ~NETIF_F_GRO_HW;
 	}
 
 	/* Allocate the parallel driver ring for Rx buffers */
@@ -1450,6 +1459,7 @@
 		}
 	}
 
+	edev->gro_disable = !(edev->ndev->features & NETIF_F_GRO_HW);
 	if (!edev->gro_disable)
 		qede_set_tpa_param(rxq);
 err:
@@ -1702,8 +1712,6 @@
 		snprintf(fp->name, sizeof(fp->name), "%s-fp-%d",
 			 edev->ndev->name, queue_id);
 	}
-
-	edev->gro_disable = !(edev->ndev->features & NETIF_F_GRO_HW);
 }
 
 static int qede_set_real_num_queues(struct qede_dev *edev)
@@ -1765,6 +1773,7 @@
 	}
 
 	edev->int_info.used_cnt = 0;
+	edev->int_info.msix_cnt = 0;
 }
 
 static int qede_req_msix_irqs(struct qede_dev *edev)
@@ -2203,7 +2212,7 @@
 	qede_vlan_mark_nonconfigured(edev);
 	edev->ops->fastpath_stop(edev->cdev);
 
-	if (!IS_VF(edev) && edev->dev_info.common.num_hwfns == 1) {
+	if (edev->dev_info.common.b_arfs_capable) {
 		qede_poll_for_freeing_arfs_filters(edev);
 		qede_free_arfs(edev);
 	}
@@ -2270,10 +2279,9 @@
 	if (rc)
 		goto err2;
 
-	if (!IS_VF(edev) && edev->dev_info.common.num_hwfns == 1) {
-		rc = qede_alloc_arfs(edev);
-		if (rc)
-			DP_NOTICE(edev, "aRFS memory allocation failed\n");
+	if (qede_alloc_arfs(edev)) {
+		edev->ndev->features &= ~NETIF_F_NTUPLE;
+		edev->dev_info.common.b_arfs_capable = false;
 	}
 
 	qede_napi_add_enable(edev);
@@ -2310,7 +2318,6 @@
 	goto out;
 err4:
 	qede_sync_free_irqs(edev);
-	memset(&edev->int_info.msix_cnt, 0, sizeof(struct qed_int_info));
 err3:
 	qede_napi_disable_remove(edev);
 err2:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qede/qede_ptp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qede/qede_ptp.c
@@ -411,6 +411,7 @@
 	if (ptp->tx_skb) {
 		dev_kfree_skb_any(ptp->tx_skb);
 		ptp->tx_skb = NULL;
+		clear_bit_unlock(QEDE_FLAGS_PTP_TX_IN_PRORGESS, &edev->flags);
 	}
 
 	/* Disable PTP in HW */
@@ -422,7 +423,7 @@
 	edev->ptp = NULL;
 }
 
-static int qede_ptp_init(struct qede_dev *edev, bool init_tc)
+static int qede_ptp_init(struct qede_dev *edev)
 {
 	struct qede_ptp *ptp;
 	int rc;
@@ -443,25 +444,19 @@
 	/* Init work queue for Tx timestamping */
 	INIT_WORK(&ptp->work, qede_ptp_task);
 
-	/* Init cyclecounter and timecounter. This is done only in the first
-	 * load. If done in every load, PTP application will fail when doing
-	 * unload / load (e.g. MTU change) while it is running.
-	 */
-	if (init_tc) {
-		memset(&ptp->cc, 0, sizeof(ptp->cc));
-		ptp->cc.read = qede_ptp_read_cc;
-		ptp->cc.mask = CYCLECOUNTER_MASK(64);
-		ptp->cc.shift = 0;
-		ptp->cc.mult = 1;
+	/* Init cyclecounter and timecounter */
+	memset(&ptp->cc, 0, sizeof(ptp->cc));
+	ptp->cc.read = qede_ptp_read_cc;
+	ptp->cc.mask = CYCLECOUNTER_MASK(64);
+	ptp->cc.shift = 0;
+	ptp->cc.mult = 1;
 
-		timecounter_init(&ptp->tc, &ptp->cc,
-				 ktime_to_ns(ktime_get_real()));
-	}
+	timecounter_init(&ptp->tc, &ptp->cc, ktime_to_ns(ktime_get_real()));
 
-	return rc;
+	return 0;
 }
 
-int qede_ptp_enable(struct qede_dev *edev, bool init_tc)
+int qede_ptp_enable(struct qede_dev *edev)
 {
 	struct qede_ptp *ptp;
 	int rc;
@@ -482,7 +477,7 @@
 
 	edev->ptp = ptp;
 
-	rc = qede_ptp_init(edev, init_tc);
+	rc = qede_ptp_init(edev);
 	if (rc)
 		goto err1;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qede/qede_ptp.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qede/qede_ptp.h
@@ -41,7 +41,7 @@
 void qede_ptp_tx_ts(struct qede_dev *edev, struct sk_buff *skb);
 int qede_ptp_hw_ts(struct qede_dev *edev, struct ifreq *req);
 void qede_ptp_disable(struct qede_dev *edev);
-int qede_ptp_enable(struct qede_dev *edev, bool init_tc);
+int qede_ptp_enable(struct qede_dev *edev);
 int qede_ptp_get_ts_info(struct qede_dev *edev, struct ethtool_ts_info *ts);
 
 static inline void qede_ptp_record_rx_ts(struct qede_dev *edev,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qede/qede_rdma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qede/qede_rdma.c
@@ -59,6 +59,9 @@
 static int qede_rdma_create_wq(struct qede_dev *edev)
 {
 	INIT_LIST_HEAD(&edev->rdma_info.rdma_event_list);
+	kref_init(&edev->rdma_info.refcnt);
+	init_completion(&edev->rdma_info.event_comp);
+
 	edev->rdma_info.rdma_wq = create_singlethread_workqueue("rdma_wq");
 	if (!edev->rdma_info.rdma_wq) {
 		DP_NOTICE(edev, "qedr: Could not create workqueue\n");
@@ -83,10 +86,26 @@
 	}
 }
 
+static void qede_rdma_complete_event(struct kref *ref)
+{
+	struct qede_rdma_dev *rdma_dev =
+		container_of(ref, struct qede_rdma_dev, refcnt);
+
+	/* no more events will be added after this */
+	complete(&rdma_dev->event_comp);
+}
+
 static void qede_rdma_destroy_wq(struct qede_dev *edev)
 {
+	/* Avoid race with add_event flow, make sure it finishes before
+	 * we start accessing the list and cleaning up the work
+	 */
+	kref_put(&edev->rdma_info.refcnt, qede_rdma_complete_event);
+	wait_for_completion(&edev->rdma_info.event_comp);
+
 	qede_rdma_cleanup_event(edev);
 	destroy_workqueue(edev->rdma_info.rdma_wq);
+	edev->rdma_info.rdma_wq = NULL;
 }
 
 int qede_rdma_dev_add(struct qede_dev *edev, bool recovery)
@@ -307,18 +326,27 @@
 	if (edev->rdma_info.exp_recovery)
 		return;
 
-	if (!edev->rdma_info.qedr_dev)
+	if (!edev->rdma_info.qedr_dev || !edev->rdma_info.rdma_wq)
 		return;
 
+	/* We don't want the cleanup flow to start while we're allocating and
+	 * scheduling the work
+	 */
+	if (!kref_get_unless_zero(&edev->rdma_info.refcnt))
+		return; /* already being destroyed */
+
 	event_node = qede_rdma_get_free_event_node(edev);
 	if (!event_node)
-		return;
+		goto out;
 
 	event_node->event = event;
 	event_node->ptr = edev;
 
 	INIT_WORK(&event_node->work, qede_rdma_handle_event);
 	queue_work(edev->rdma_info.rdma_wq, &event_node->work);
+
+out:
+	kref_put(&edev->rdma_info.refcnt, qede_rdma_complete_event);
 }
 
 void qede_rdma_dev_event_open(struct qede_dev *edev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qla3xxx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qla3xxx.c
@@ -115,7 +115,7 @@
 		value = readl(&port_regs->CommonRegs.semaphoreReg);
 		if ((value & (sem_mask >> 16)) == sem_bits)
 			return 0;
-		ssleep(1);
+		mdelay(1000);
 	} while (--seconds);
 	return -1;
 }
@@ -155,7 +155,7 @@
 				      "driver lock acquired\n");
 			return 1;
 		}
-		ssleep(1);
+		mdelay(1000);
 	} while (++i < 10);
 
 	netdev_err(qdev->ndev, "Timed out waiting for driver lock...\n");
@@ -316,12 +316,11 @@
 			 * buffer
 			 */
 			skb_reserve(lrg_buf_cb->skb, QL_HEADER_SPACE);
-			map = pci_map_single(qdev->pdev,
+			map = dma_map_single(&qdev->pdev->dev,
 					     lrg_buf_cb->skb->data,
-					     qdev->lrg_buffer_len -
-					     QL_HEADER_SPACE,
-					     PCI_DMA_FROMDEVICE);
-			err = pci_dma_mapping_error(qdev->pdev, map);
+					     qdev->lrg_buffer_len - QL_HEADER_SPACE,
+					     DMA_FROM_DEVICE);
+			err = dma_mapping_error(&qdev->pdev->dev, map);
 			if (err) {
 				netdev_err(qdev->ndev,
 					   "PCI mapping failed with error: %d\n",
@@ -1803,13 +1802,12 @@
 				 * first buffer
 				 */
 				skb_reserve(lrg_buf_cb->skb, QL_HEADER_SPACE);
-				map = pci_map_single(qdev->pdev,
+				map = dma_map_single(&qdev->pdev->dev,
 						     lrg_buf_cb->skb->data,
-						     qdev->lrg_buffer_len -
-						     QL_HEADER_SPACE,
-						     PCI_DMA_FROMDEVICE);
+						     qdev->lrg_buffer_len - QL_HEADER_SPACE,
+						     DMA_FROM_DEVICE);
 
-				err = pci_dma_mapping_error(qdev->pdev, map);
+				err = dma_mapping_error(&qdev->pdev->dev, map);
 				if (err) {
 					netdev_err(qdev->ndev,
 						   "PCI mapping failed with error: %d\n",
@@ -1944,18 +1942,16 @@
 		goto invalid_seg_count;
 	}
 
-	pci_unmap_single(qdev->pdev,
+	dma_unmap_single(&qdev->pdev->dev,
 			 dma_unmap_addr(&tx_cb->map[0], mapaddr),
-			 dma_unmap_len(&tx_cb->map[0], maplen),
-			 PCI_DMA_TODEVICE);
+			 dma_unmap_len(&tx_cb->map[0], maplen), DMA_TO_DEVICE);
 	tx_cb->seg_count--;
 	if (tx_cb->seg_count) {
 		for (i = 1; i < tx_cb->seg_count; i++) {
-			pci_unmap_page(qdev->pdev,
-				       dma_unmap_addr(&tx_cb->map[i],
-						      mapaddr),
+			dma_unmap_page(&qdev->pdev->dev,
+				       dma_unmap_addr(&tx_cb->map[i], mapaddr),
 				       dma_unmap_len(&tx_cb->map[i], maplen),
-				       PCI_DMA_TODEVICE);
+				       DMA_TO_DEVICE);
 		}
 	}
 	qdev->ndev->stats.tx_packets++;
@@ -2022,10 +2018,9 @@
 	qdev->ndev->stats.rx_bytes += length;
 
 	skb_put(skb, length);
-	pci_unmap_single(qdev->pdev,
+	dma_unmap_single(&qdev->pdev->dev,
 			 dma_unmap_addr(lrg_buf_cb2, mapaddr),
-			 dma_unmap_len(lrg_buf_cb2, maplen),
-			 PCI_DMA_FROMDEVICE);
+			 dma_unmap_len(lrg_buf_cb2, maplen), DMA_FROM_DEVICE);
 	prefetch(skb->data);
 	skb_checksum_none_assert(skb);
 	skb->protocol = eth_type_trans(skb, qdev->ndev);
@@ -2068,10 +2063,9 @@
 	skb2 = lrg_buf_cb2->skb;
 
 	skb_put(skb2, length);	/* Just the second buffer length here. */
-	pci_unmap_single(qdev->pdev,
+	dma_unmap_single(&qdev->pdev->dev,
 			 dma_unmap_addr(lrg_buf_cb2, mapaddr),
-			 dma_unmap_len(lrg_buf_cb2, maplen),
-			 PCI_DMA_FROMDEVICE);
+			 dma_unmap_len(lrg_buf_cb2, maplen), DMA_FROM_DEVICE);
 	prefetch(skb2->data);
 
 	skb_checksum_none_assert(skb2);
@@ -2320,9 +2314,9 @@
 	/*
 	 * Map the skb buffer first.
 	 */
-	map = pci_map_single(qdev->pdev, skb->data, len, PCI_DMA_TODEVICE);
+	map = dma_map_single(&qdev->pdev->dev, skb->data, len, DMA_TO_DEVICE);
 
-	err = pci_dma_mapping_error(qdev->pdev, map);
+	err = dma_mapping_error(&qdev->pdev->dev, map);
 	if (err) {
 		netdev_err(qdev->ndev, "PCI mapping failed with error: %d\n",
 			   err);
@@ -2358,11 +2352,11 @@
 		    (seg == 7 && seg_cnt > 8) ||
 		    (seg == 12 && seg_cnt > 13) ||
 		    (seg == 17 && seg_cnt > 18)) {
-			map = pci_map_single(qdev->pdev, oal,
+			map = dma_map_single(&qdev->pdev->dev, oal,
 					     sizeof(struct oal),
-					     PCI_DMA_TODEVICE);
+					     DMA_TO_DEVICE);
 
-			err = pci_dma_mapping_error(qdev->pdev, map);
+			err = dma_mapping_error(&qdev->pdev->dev, map);
 			if (err) {
 				netdev_err(qdev->ndev,
 					   "PCI mapping outbound address list with error: %d\n",
@@ -2424,24 +2418,24 @@
 		    (seg == 7 && seg_cnt > 8) ||
 		    (seg == 12 && seg_cnt > 13) ||
 		    (seg == 17 && seg_cnt > 18)) {
-			pci_unmap_single(qdev->pdev,
-				dma_unmap_addr(&tx_cb->map[seg], mapaddr),
-				dma_unmap_len(&tx_cb->map[seg], maplen),
-				 PCI_DMA_TODEVICE);
+			dma_unmap_single(&qdev->pdev->dev,
+					 dma_unmap_addr(&tx_cb->map[seg], mapaddr),
+					 dma_unmap_len(&tx_cb->map[seg], maplen),
+					 DMA_TO_DEVICE);
 			oal++;
 			seg++;
 		}
 
-		pci_unmap_page(qdev->pdev,
+		dma_unmap_page(&qdev->pdev->dev,
 			       dma_unmap_addr(&tx_cb->map[seg], mapaddr),
 			       dma_unmap_len(&tx_cb->map[seg], maplen),
-			       PCI_DMA_TODEVICE);
+			       DMA_TO_DEVICE);
 	}
 
-	pci_unmap_single(qdev->pdev,
+	dma_unmap_single(&qdev->pdev->dev,
 			 dma_unmap_addr(&tx_cb->map[0], mapaddr),
 			 dma_unmap_addr(&tx_cb->map[0], maplen),
-			 PCI_DMA_TODEVICE);
+			 DMA_TO_DEVICE);
 
 	return NETDEV_TX_BUSY;
 
@@ -2476,6 +2470,7 @@
 					     skb_shinfo(skb)->nr_frags);
 	if (tx_cb->seg_count == -1) {
 		netdev_err(ndev, "%s: invalid segment count!\n", __func__);
+		dev_kfree_skb_any(skb);
 		return NETDEV_TX_OK;
 	}
 
@@ -2526,9 +2521,8 @@
 	wmb();
 
 	qdev->req_q_virt_addr =
-	    pci_alloc_consistent(qdev->pdev,
-				 (size_t) qdev->req_q_size,
-				 &qdev->req_q_phy_addr);
+	    dma_alloc_coherent(&qdev->pdev->dev, (size_t)qdev->req_q_size,
+			       &qdev->req_q_phy_addr, GFP_KERNEL);
 
 	if ((qdev->req_q_virt_addr == NULL) ||
 	    LS_64BITS(qdev->req_q_phy_addr) & (qdev->req_q_size - 1)) {
@@ -2537,16 +2531,14 @@
 	}
 
 	qdev->rsp_q_virt_addr =
-	    pci_alloc_consistent(qdev->pdev,
-				 (size_t) qdev->rsp_q_size,
-				 &qdev->rsp_q_phy_addr);
+	    dma_alloc_coherent(&qdev->pdev->dev, (size_t)qdev->rsp_q_size,
+			       &qdev->rsp_q_phy_addr, GFP_KERNEL);
 
 	if ((qdev->rsp_q_virt_addr == NULL) ||
 	    LS_64BITS(qdev->rsp_q_phy_addr) & (qdev->rsp_q_size - 1)) {
 		netdev_err(qdev->ndev, "rspQ allocation failed\n");
-		pci_free_consistent(qdev->pdev, (size_t) qdev->req_q_size,
-				    qdev->req_q_virt_addr,
-				    qdev->req_q_phy_addr);
+		dma_free_coherent(&qdev->pdev->dev, (size_t)qdev->req_q_size,
+				  qdev->req_q_virt_addr, qdev->req_q_phy_addr);
 		return -ENOMEM;
 	}
 
@@ -2562,15 +2554,13 @@
 		return;
 	}
 
-	pci_free_consistent(qdev->pdev,
-			    qdev->req_q_size,
-			    qdev->req_q_virt_addr, qdev->req_q_phy_addr);
+	dma_free_coherent(&qdev->pdev->dev, qdev->req_q_size,
+			  qdev->req_q_virt_addr, qdev->req_q_phy_addr);
 
 	qdev->req_q_virt_addr = NULL;
 
-	pci_free_consistent(qdev->pdev,
-			    qdev->rsp_q_size,
-			    qdev->rsp_q_virt_addr, qdev->rsp_q_phy_addr);
+	dma_free_coherent(&qdev->pdev->dev, qdev->rsp_q_size,
+			  qdev->rsp_q_virt_addr, qdev->rsp_q_phy_addr);
 
 	qdev->rsp_q_virt_addr = NULL;
 
@@ -2594,12 +2584,13 @@
 		return -ENOMEM;
 
 	qdev->lrg_buf_q_alloc_virt_addr =
-		pci_alloc_consistent(qdev->pdev,
-				     qdev->lrg_buf_q_alloc_size,
-				     &qdev->lrg_buf_q_alloc_phy_addr);
+		dma_alloc_coherent(&qdev->pdev->dev,
+				   qdev->lrg_buf_q_alloc_size,
+				   &qdev->lrg_buf_q_alloc_phy_addr, GFP_KERNEL);
 
 	if (qdev->lrg_buf_q_alloc_virt_addr == NULL) {
 		netdev_err(qdev->ndev, "lBufQ failed\n");
+		kfree(qdev->lrg_buf);
 		return -ENOMEM;
 	}
 	qdev->lrg_buf_q_virt_addr = qdev->lrg_buf_q_alloc_virt_addr;
@@ -2614,15 +2605,17 @@
 		qdev->small_buf_q_alloc_size = qdev->small_buf_q_size * 2;
 
 	qdev->small_buf_q_alloc_virt_addr =
-		pci_alloc_consistent(qdev->pdev,
-				     qdev->small_buf_q_alloc_size,
-				     &qdev->small_buf_q_alloc_phy_addr);
+		dma_alloc_coherent(&qdev->pdev->dev,
+				   qdev->small_buf_q_alloc_size,
+				   &qdev->small_buf_q_alloc_phy_addr, GFP_KERNEL);
 
 	if (qdev->small_buf_q_alloc_virt_addr == NULL) {
 		netdev_err(qdev->ndev, "Small Buffer Queue allocation failed\n");
-		pci_free_consistent(qdev->pdev, qdev->lrg_buf_q_alloc_size,
-				    qdev->lrg_buf_q_alloc_virt_addr,
-				    qdev->lrg_buf_q_alloc_phy_addr);
+		dma_free_coherent(&qdev->pdev->dev,
+				  qdev->lrg_buf_q_alloc_size,
+				  qdev->lrg_buf_q_alloc_virt_addr,
+				  qdev->lrg_buf_q_alloc_phy_addr);
+		kfree(qdev->lrg_buf);
 		return -ENOMEM;
 	}
 
@@ -2639,17 +2632,15 @@
 		return;
 	}
 	kfree(qdev->lrg_buf);
-	pci_free_consistent(qdev->pdev,
-			    qdev->lrg_buf_q_alloc_size,
-			    qdev->lrg_buf_q_alloc_virt_addr,
-			    qdev->lrg_buf_q_alloc_phy_addr);
+	dma_free_coherent(&qdev->pdev->dev, qdev->lrg_buf_q_alloc_size,
+			  qdev->lrg_buf_q_alloc_virt_addr,
+			  qdev->lrg_buf_q_alloc_phy_addr);
 
 	qdev->lrg_buf_q_virt_addr = NULL;
 
-	pci_free_consistent(qdev->pdev,
-			    qdev->small_buf_q_alloc_size,
-			    qdev->small_buf_q_alloc_virt_addr,
-			    qdev->small_buf_q_alloc_phy_addr);
+	dma_free_coherent(&qdev->pdev->dev, qdev->small_buf_q_alloc_size,
+			  qdev->small_buf_q_alloc_virt_addr,
+			  qdev->small_buf_q_alloc_phy_addr);
 
 	qdev->small_buf_q_virt_addr = NULL;
 
@@ -2667,9 +2658,9 @@
 		 QL_SMALL_BUFFER_SIZE);
 
 	qdev->small_buf_virt_addr =
-		pci_alloc_consistent(qdev->pdev,
-				     qdev->small_buf_total_size,
-				     &qdev->small_buf_phy_addr);
+		dma_alloc_coherent(&qdev->pdev->dev,
+				   qdev->small_buf_total_size,
+				   &qdev->small_buf_phy_addr, GFP_KERNEL);
 
 	if (qdev->small_buf_virt_addr == NULL) {
 		netdev_err(qdev->ndev, "Failed to get small buffer memory\n");
@@ -2702,10 +2693,10 @@
 		return;
 	}
 	if (qdev->small_buf_virt_addr != NULL) {
-		pci_free_consistent(qdev->pdev,
-				    qdev->small_buf_total_size,
-				    qdev->small_buf_virt_addr,
-				    qdev->small_buf_phy_addr);
+		dma_free_coherent(&qdev->pdev->dev,
+				  qdev->small_buf_total_size,
+				  qdev->small_buf_virt_addr,
+				  qdev->small_buf_phy_addr);
 
 		qdev->small_buf_virt_addr = NULL;
 	}
@@ -2720,10 +2711,10 @@
 		lrg_buf_cb = &qdev->lrg_buf[i];
 		if (lrg_buf_cb->skb) {
 			dev_kfree_skb(lrg_buf_cb->skb);
-			pci_unmap_single(qdev->pdev,
+			dma_unmap_single(&qdev->pdev->dev,
 					 dma_unmap_addr(lrg_buf_cb, mapaddr),
 					 dma_unmap_len(lrg_buf_cb, maplen),
-					 PCI_DMA_FROMDEVICE);
+					 DMA_FROM_DEVICE);
 			memset(lrg_buf_cb, 0, sizeof(struct ql_rcv_buf_cb));
 		} else {
 			break;
@@ -2756,6 +2747,9 @@
 	int err;
 
 	for (i = 0; i < qdev->num_large_buffers; i++) {
+		lrg_buf_cb = &qdev->lrg_buf[i];
+		memset(lrg_buf_cb, 0, sizeof(struct ql_rcv_buf_cb));
+
 		skb = netdev_alloc_skb(qdev->ndev,
 				       qdev->lrg_buffer_len);
 		if (unlikely(!skb)) {
@@ -2766,23 +2760,17 @@
 			ql_free_large_buffers(qdev);
 			return -ENOMEM;
 		} else {
-
-			lrg_buf_cb = &qdev->lrg_buf[i];
-			memset(lrg_buf_cb, 0, sizeof(struct ql_rcv_buf_cb));
 			lrg_buf_cb->index = i;
-			lrg_buf_cb->skb = skb;
 			/*
 			 * We save some space to copy the ethhdr from first
 			 * buffer
 			 */
 			skb_reserve(skb, QL_HEADER_SPACE);
-			map = pci_map_single(qdev->pdev,
-					     skb->data,
-					     qdev->lrg_buffer_len -
-					     QL_HEADER_SPACE,
-					     PCI_DMA_FROMDEVICE);
+			map = dma_map_single(&qdev->pdev->dev, skb->data,
+					     qdev->lrg_buffer_len - QL_HEADER_SPACE,
+					     DMA_FROM_DEVICE);
 
-			err = pci_dma_mapping_error(qdev->pdev, map);
+			err = dma_mapping_error(&qdev->pdev->dev, map);
 			if (err) {
 				netdev_err(qdev->ndev,
 					   "PCI mapping failed with error: %d\n",
@@ -2792,6 +2780,7 @@
 				return -ENOMEM;
 			}
 
+			lrg_buf_cb->skb = skb;
 			dma_unmap_addr_set(lrg_buf_cb, mapaddr, map);
 			dma_unmap_len_set(lrg_buf_cb, maplen,
 					  qdev->lrg_buffer_len -
@@ -2866,8 +2855,8 @@
 	 * Network Completion Queue Producer Index Register
 	 */
 	qdev->shadow_reg_virt_addr =
-		pci_alloc_consistent(qdev->pdev,
-				     PAGE_SIZE, &qdev->shadow_reg_phy_addr);
+		dma_alloc_coherent(&qdev->pdev->dev, PAGE_SIZE,
+				   &qdev->shadow_reg_phy_addr, GFP_KERNEL);
 
 	if (qdev->shadow_reg_virt_addr != NULL) {
 		qdev->preq_consumer_index = qdev->shadow_reg_virt_addr;
@@ -2922,10 +2911,9 @@
 err_buffer_queues:
 	ql_free_net_req_rsp_queues(qdev);
 err_req_rsp:
-	pci_free_consistent(qdev->pdev,
-			    PAGE_SIZE,
-			    qdev->shadow_reg_virt_addr,
-			    qdev->shadow_reg_phy_addr);
+	dma_free_coherent(&qdev->pdev->dev, PAGE_SIZE,
+			  qdev->shadow_reg_virt_addr,
+			  qdev->shadow_reg_phy_addr);
 
 	return -ENOMEM;
 }
@@ -2938,10 +2926,9 @@
 	ql_free_buffer_queues(qdev);
 	ql_free_net_req_rsp_queues(qdev);
 	if (qdev->shadow_reg_virt_addr != NULL) {
-		pci_free_consistent(qdev->pdev,
-				    PAGE_SIZE,
-				    qdev->shadow_reg_virt_addr,
-				    qdev->shadow_reg_phy_addr);
+		dma_free_coherent(&qdev->pdev->dev, PAGE_SIZE,
+				  qdev->shadow_reg_virt_addr,
+				  qdev->shadow_reg_phy_addr);
 		qdev->shadow_reg_virt_addr = NULL;
 	}
 }
@@ -3291,7 +3278,7 @@
 		if ((value & ISP_CONTROL_SR) == 0)
 			break;
 
-		ssleep(1);
+		mdelay(1000);
 	} while ((--max_wait_time));
 
 	/*
@@ -3327,7 +3314,7 @@
 						   ispControlStatus);
 			if ((value & ISP_CONTROL_FSR) == 0)
 				break;
-			ssleep(1);
+			mdelay(1000);
 		} while ((--max_wait_time));
 	}
 	if (max_wait_time == 0)
@@ -3495,20 +3482,19 @@
 
 	spin_lock_irqsave(&qdev->hw_lock, hw_flags);
 
-	err = ql_wait_for_drvr_lock(qdev);
-	if (err) {
-		err = ql_adapter_initialize(qdev);
-		if (err) {
-			netdev_err(ndev, "Unable to initialize adapter\n");
-			goto err_init;
-		}
-		netdev_err(ndev, "Releasing driver lock\n");
-		ql_sem_unlock(qdev, QL_DRVR_SEM_MASK);
-	} else {
+	if (!ql_wait_for_drvr_lock(qdev)) {
 		netdev_err(ndev, "Could not acquire driver lock\n");
+		err = -ENODEV;
 		goto err_lock;
 	}
 
+	err = ql_adapter_initialize(qdev);
+	if (err) {
+		netdev_err(ndev, "Unable to initialize adapter\n");
+		goto err_init;
+	}
+	ql_sem_unlock(qdev, QL_DRVR_SEM_MASK);
+
 	spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
 
 	set_bit(QL_ADAPTER_UP, &qdev->flags);
@@ -3630,7 +3616,8 @@
 		qdev->mem_map_registers;
 	unsigned long hw_flags;
 
-	if (test_bit((QL_RESET_PER_SCSI | QL_RESET_START), &qdev->flags)) {
+	if (test_bit(QL_RESET_PER_SCSI, &qdev->flags) ||
+	    test_bit(QL_RESET_START, &qdev->flags)) {
 		clear_bit(QL_LINK_MASTER, &qdev->flags);
 
 		/*
@@ -3642,18 +3629,15 @@
 			if (tx_cb->skb) {
 				netdev_printk(KERN_DEBUG, ndev,
 					      "Freeing lost SKB\n");
-				pci_unmap_single(qdev->pdev,
-					 dma_unmap_addr(&tx_cb->map[0],
-							mapaddr),
-					 dma_unmap_len(&tx_cb->map[0], maplen),
-					 PCI_DMA_TODEVICE);
+				dma_unmap_single(&qdev->pdev->dev,
+						 dma_unmap_addr(&tx_cb->map[0], mapaddr),
+						 dma_unmap_len(&tx_cb->map[0], maplen),
+						 DMA_TO_DEVICE);
 				for (j = 1; j < tx_cb->seg_count; j++) {
-					pci_unmap_page(qdev->pdev,
-					       dma_unmap_addr(&tx_cb->map[j],
-							      mapaddr),
-					       dma_unmap_len(&tx_cb->map[j],
-							     maplen),
-					       PCI_DMA_TODEVICE);
+					dma_unmap_page(&qdev->pdev->dev,
+						       dma_unmap_addr(&tx_cb->map[j], mapaddr),
+						       dma_unmap_len(&tx_cb->map[j], maplen),
+						       DMA_TO_DEVICE);
 				}
 				dev_kfree_skb(tx_cb->skb);
 				tx_cb->skb = NULL;
@@ -3769,7 +3753,7 @@
 	struct net_device *ndev = NULL;
 	struct ql3_adapter *qdev = NULL;
 	static int cards_found;
-	int uninitialized_var(pci_using_dac), err;
+	int pci_using_dac, err;
 
 	err = pci_enable_device(pdev);
 	if (err) {
@@ -3785,13 +3769,10 @@
 
 	pci_set_master(pdev);
 
-	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
+	if (!dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)))
 		pci_using_dac = 1;
-		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
-	} else if (!(err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) {
+	else if (!(err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32))))
 		pci_using_dac = 0;
-		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
-	}
 
 	if (err) {
 		pr_err("%s no usable DMA configuration\n", pci_name(pdev));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
@@ -1079,8 +1079,14 @@
 	sds_mbx_size = sizeof(struct qlcnic_sds_mbx);
 	context_id = recv_ctx->context_id;
 	num_sds = adapter->drv_sds_rings - QLCNIC_MAX_SDS_RINGS;
-	ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
-				    QLCNIC_CMD_ADD_RCV_RINGS);
+	err = ahw->hw_ops->alloc_mbx_args(&cmd, adapter,
+					QLCNIC_CMD_ADD_RCV_RINGS);
+	if (err) {
+		dev_err(&adapter->pdev->dev,
+			"Failed to alloc mbx args %d\n", err);
+		return err;
+	}
+
 	cmd.req.arg[1] = 0 | (num_sds << 8) | (context_id << 16);
 
 	/* set up status rings, mbx 2-81 */
@@ -2987,7 +2993,7 @@
 		QLCWRX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK, val);
 		dev_info(&adapter->pdev->dev,
 			 "%s: lock recovery initiated\n", __func__);
-		msleep(QLC_83XX_DRV_LOCK_RECOVERY_DELAY);
+		mdelay(QLC_83XX_DRV_LOCK_RECOVERY_DELAY);
 		val = QLCRDX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK);
 		id = ((val >> 2) & 0xF);
 		if (id == adapter->portnum) {
@@ -3023,7 +3029,7 @@
 		if (status)
 			break;
 
-		msleep(QLC_83XX_DRV_LOCK_WAIT_DELAY);
+		mdelay(QLC_83XX_DRV_LOCK_WAIT_DELAY);
 		i++;
 
 		if (i == 1)
@@ -3158,8 +3164,10 @@
 
 		indirect_addr = QLC_83XX_FLASH_DIRECT_DATA(addr);
 		ret = QLCRD32(adapter, indirect_addr, &err);
-		if (err == -EIO)
+		if (err == -EIO) {
+			qlcnic_83xx_unlock_flash(adapter);
 			return err;
+		}
 
 		word = ret;
 		*(u32 *)p_data  = word;
@@ -3651,7 +3659,7 @@
 	ahw->diag_cnt = 0;
 	ret = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_INTRPT_TEST);
 	if (ret)
-		goto fail_diag_irq;
+		goto fail_mbx_args;
 
 	if (adapter->flags & QLCNIC_MSIX_ENABLED)
 		intrpt_id = ahw->intr_tbl[0].id;
@@ -3681,6 +3689,8 @@
 
 done:
 	qlcnic_free_mbx_args(&cmd);
+
+fail_mbx_args:
 	qlcnic_83xx_diag_free_res(netdev, drv_sds_rings);
 
 fail_diag_irq:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
@@ -1720,7 +1720,7 @@
 
 	ahw->reset.seq_error = 0;
 	ahw->reset.buff = kzalloc(QLC_83XX_RESTART_TEMPLATE_SIZE, GFP_KERNEL);
-	if (p_dev->ahw->reset.buff == NULL)
+	if (ahw->reset.buff == NULL)
 		return -ENOMEM;
 
 	p_buff = p_dev->ahw->reset.buff;
@@ -2043,6 +2043,7 @@
 			break;
 		}
 		entry += p_hdr->size;
+		cond_resched();
 	}
 	p_dev->ahw->reset.seq_index = index;
 }
@@ -2250,7 +2251,8 @@
 
 	/* Boot either flash image or firmware image from host file system */
 	if (qlcnic_load_fw_file == 1) {
-		if (qlcnic_83xx_load_fw_image_from_host(adapter))
+		err = qlcnic_83xx_load_fw_image_from_host(adapter);
+		if (err)
 			return err;
 	} else {
 		QLC_SHARED_REG_WR32(adapter, QLCNIC_FW_IMG_VALID,
@@ -2523,7 +2525,13 @@
 		goto disable_mbx_intr;
 
 	qlcnic_83xx_clear_function_resources(adapter);
-	qlcnic_dcb_enable(adapter->dcb);
+
+	err = qlcnic_dcb_enable(adapter->dcb);
+	if (err) {
+		qlcnic_dcb_free(adapter->dcb);
+		goto disable_mbx_intr;
+	}
+
 	qlcnic_83xx_initialize_nic(adapter, 1);
 	qlcnic_dcb_get_info(adapter->dcb);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
@@ -629,7 +629,13 @@
 	int i, err, ring;
 
 	if (dev->flags & QLCNIC_NEED_FLR) {
-		pci_reset_function(dev->pdev);
+		err = pci_reset_function(dev->pdev);
+		if (err) {
+			dev_err(&dev->pdev->dev,
+				"Adapter reset failed (%d). Please reboot\n",
+				err);
+			return err;
+		}
 		dev->flags &= ~QLCNIC_NEED_FLR;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.h
@@ -42,17 +42,12 @@
 	unsigned long			state;
 };
 
-static inline void qlcnic_clear_dcb_ops(struct qlcnic_dcb *dcb)
-{
-	kfree(dcb);
-}
-
 static inline int qlcnic_dcb_get_hw_capability(struct qlcnic_dcb *dcb)
 {
 	if (dcb && dcb->ops->get_hw_capability)
 		return dcb->ops->get_hw_capability(dcb);
 
-	return 0;
+	return -EOPNOTSUPP;
 }
 
 static inline void qlcnic_dcb_free(struct qlcnic_dcb *dcb)
@@ -66,7 +61,7 @@
 	if (dcb && dcb->ops->attach)
 		return dcb->ops->attach(dcb);
 
-	return 0;
+	return -EOPNOTSUPP;
 }
 
 static inline int
@@ -75,7 +70,7 @@
 	if (dcb && dcb->ops->query_hw_capability)
 		return dcb->ops->query_hw_capability(dcb, buf);
 
-	return 0;
+	return -EOPNOTSUPP;
 }
 
 static inline void qlcnic_dcb_get_info(struct qlcnic_dcb *dcb)
@@ -90,7 +85,7 @@
 	if (dcb && dcb->ops->query_cee_param)
 		return dcb->ops->query_cee_param(dcb, buf, type);
 
-	return 0;
+	return -EOPNOTSUPP;
 }
 
 static inline int qlcnic_dcb_get_cee_cfg(struct qlcnic_dcb *dcb)
@@ -98,7 +93,7 @@
 	if (dcb && dcb->ops->get_cee_cfg)
 		return dcb->ops->get_cee_cfg(dcb);
 
-	return 0;
+	return -EOPNOTSUPP;
 }
 
 static inline void qlcnic_dcb_aen_handler(struct qlcnic_dcb *dcb, void *msg)
@@ -113,9 +108,8 @@
 		dcb->ops->init_dcbnl_ops(dcb);
 }
 
-static inline void qlcnic_dcb_enable(struct qlcnic_dcb *dcb)
+static inline int qlcnic_dcb_enable(struct qlcnic_dcb *dcb)
 {
-	if (dcb && qlcnic_dcb_attach(dcb))
-		qlcnic_clear_dcb_ops(dcb);
+	return dcb ? qlcnic_dcb_attach(dcb) : 0;
 }
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
@@ -1049,7 +1049,7 @@
 	for (i = 0; i < QLCNIC_NUM_ILB_PKT; i++) {
 		skb = netdev_alloc_skb(adapter->netdev, QLCNIC_ILB_PKT_SIZE);
 		if (!skb)
-			break;
+			goto error;
 		qlcnic_create_loopback_buff(skb->data, adapter->mac_addr);
 		skb_put(skb, QLCNIC_ILB_PKT_SIZE);
 		adapter->ahw->diag_cnt = 0;
@@ -1073,6 +1073,7 @@
 			cnt++;
 	}
 	if (cnt != i) {
+error:
 		dev_err(&adapter->pdev->dev,
 			"LB Test: failed, TX[%d], RX[%d]\n", i, cnt);
 		if (mode != QLCNIC_ILB_MODE)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
@@ -440,7 +440,6 @@
 	QLCWR32(adapter, QLCNIC_CRB_PEG_NET_4 + 0x3c, 1);
 	msleep(20);
 
-	qlcnic_rom_unlock(adapter);
 	/* big hammer don't reset CAM block on reset */
 	QLCWR32(adapter, QLCNIC_ROMUSB_GLB_SW_RESET, 0xfeffffff);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -2509,6 +2509,7 @@
 		qlcnic_sriov_vf_register_map(ahw);
 		break;
 	default:
+		err = -EINVAL;
 		goto err_out_free_hw_res;
 	}
 
@@ -2638,7 +2639,13 @@
 			 "Device does not support MSI interrupts\n");
 
 	if (qlcnic_82xx_check(adapter)) {
-		qlcnic_dcb_enable(adapter->dcb);
+		err = qlcnic_dcb_enable(adapter->dcb);
+		if (err) {
+			qlcnic_dcb_free(adapter->dcb);
+			dev_err(&pdev->dev, "Failed to enable DCB\n");
+			goto err_out_free_hw;
+		}
+
 		qlcnic_dcb_get_info(adapter->dcb);
 		err = qlcnic_setup_intr(adapter);
 
@@ -2708,6 +2715,7 @@
 	kfree(ahw);
 
 err_out_free_res:
+	pci_disable_pcie_error_reporting(pdev);
 	pci_release_regions(pdev);
 
 err_out_disable_pdev:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
@@ -703,6 +703,7 @@
 		addr += 16;
 		reg_read -= 16;
 		ret += 16;
+		cond_resched();
 	}
 out:
 	mutex_unlock(&adapter->ahw->mem_lock);
@@ -1383,6 +1384,7 @@
 		buf_offset += entry->hdr.cap_size;
 		entry_offset += entry->hdr.offset;
 		buffer = fw_dump->data + buf_offset;
+		cond_resched();
 	}
 
 	fw_dump->clr = 1;
@@ -1424,6 +1426,7 @@
 
 	if (fw_dump->tmpl_hdr == NULL || current_version > prev_version) {
 		vfree(fw_dump->tmpl_hdr);
+		fw_dump->tmpl_hdr = NULL;
 
 		if (qlcnic_83xx_md_check_extended_dump_capability(adapter))
 			extended = !qlcnic_83xx_extend_md_capab(adapter);
@@ -1442,6 +1445,8 @@
 			struct qlcnic_83xx_dump_template_hdr *hdr;
 
 			hdr = fw_dump->tmpl_hdr;
+			if (!hdr)
+				return;
 			hdr->drv_cap_mask = 0x1f;
 			fw_dump->cap_mask = 0x1f;
 			dev_info(&pdev->dev,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov.h
@@ -202,7 +202,7 @@
 				   struct qlcnic_info *, u16);
 int qlcnic_sriov_cfg_vf_guest_vlan(struct qlcnic_adapter *, u16, u8);
 void qlcnic_sriov_free_vlans(struct qlcnic_adapter *);
-void qlcnic_sriov_alloc_vlans(struct qlcnic_adapter *);
+int qlcnic_sriov_alloc_vlans(struct qlcnic_adapter *);
 bool qlcnic_sriov_check_any_vlan(struct qlcnic_vf_info *);
 void qlcnic_sriov_del_vlan_id(struct qlcnic_sriov *,
 			      struct qlcnic_vf_info *, u16);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
@@ -222,6 +222,8 @@
 	return 0;
 
 qlcnic_destroy_async_wq:
+	while (i--)
+		kfree(sriov->vf_info[i].vp);
 	destroy_workqueue(bc->bc_async_wq);
 
 qlcnic_destroy_trans_wq:
@@ -433,7 +435,7 @@
 					    struct qlcnic_cmd_args *cmd)
 {
 	struct qlcnic_sriov *sriov = adapter->ahw->sriov;
-	int i, num_vlans;
+	int i, num_vlans, ret;
 	u16 *vlans;
 
 	if (sriov->allowed_vlans)
@@ -444,15 +446,19 @@
 	dev_info(&adapter->pdev->dev, "Number of allowed Guest VLANs = %d\n",
 		 sriov->num_allowed_vlans);
 
-	qlcnic_sriov_alloc_vlans(adapter);
+	ret = qlcnic_sriov_alloc_vlans(adapter);
+	if (ret)
+		return ret;
 
 	if (!sriov->any_vlan)
 		return 0;
 
 	num_vlans = sriov->num_allowed_vlans;
 	sriov->allowed_vlans = kcalloc(num_vlans, sizeof(u16), GFP_KERNEL);
-	if (!sriov->allowed_vlans)
+	if (!sriov->allowed_vlans) {
+		qlcnic_sriov_free_vlans(adapter);
 		return -ENOMEM;
+	}
 
 	vlans = (u16 *)&cmd->rsp.arg[3];
 	for (i = 0; i < num_vlans; i++)
@@ -2160,7 +2166,7 @@
 	return err;
 }
 
-void qlcnic_sriov_alloc_vlans(struct qlcnic_adapter *adapter)
+int qlcnic_sriov_alloc_vlans(struct qlcnic_adapter *adapter)
 {
 	struct qlcnic_sriov *sriov = adapter->ahw->sriov;
 	struct qlcnic_vf_info *vf;
@@ -2170,7 +2176,13 @@
 		vf = &sriov->vf_info[i];
 		vf->sriov_vlans = kcalloc(sriov->num_allowed_vlans,
 					  sizeof(*vf->sriov_vlans), GFP_KERNEL);
+		if (!vf->sriov_vlans) {
+			qlcnic_sriov_free_vlans(adapter);
+			return -ENOMEM;
+		}
 	}
+
+	return 0;
 }
 
 void qlcnic_sriov_free_vlans(struct qlcnic_adapter *adapter)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c
@@ -598,7 +598,9 @@
 	if (err)
 		goto del_flr_queue;
 
-	qlcnic_sriov_alloc_vlans(adapter);
+	err = qlcnic_sriov_alloc_vlans(adapter);
+	if (err)
+		goto del_flr_queue;
 
 	return err;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qualcomm/emac/emac-mac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qualcomm/emac/emac-mac.c
@@ -1439,6 +1439,7 @@
 {
 	struct emac_tpd tpd;
 	u32 prod_idx;
+	int len;
 
 	memset(&tpd, 0, sizeof(tpd));
 
@@ -1458,9 +1459,10 @@
 	if (skb_network_offset(skb) != ETH_HLEN)
 		TPD_TYP_SET(&tpd, 1);
 
+	len = skb->len;
 	emac_tx_fill_tpd(adpt, tx_q, skb, &tpd);
 
-	netdev_sent_queue(adpt->netdev, skb->len);
+	netdev_sent_queue(adpt->netdev, len);
 
 	/* Make sure the are enough free descriptors to hold one
 	 * maximum-sized SKB.  We need one desc for each fragment,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qualcomm/emac/emac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qualcomm/emac/emac.c
@@ -485,13 +485,24 @@
 
 	ret = clk_prepare_enable(adpt->clk[EMAC_CLK_CFG_AHB]);
 	if (ret)
-		return ret;
+		goto disable_clk_axi;
 
 	ret = clk_set_rate(adpt->clk[EMAC_CLK_HIGH_SPEED], 19200000);
 	if (ret)
-		return ret;
+		goto disable_clk_cfg_ahb;
+
+	ret = clk_prepare_enable(adpt->clk[EMAC_CLK_HIGH_SPEED]);
+	if (ret)
+		goto disable_clk_cfg_ahb;
+
+	return 0;
+
+disable_clk_cfg_ahb:
+	clk_disable_unprepare(adpt->clk[EMAC_CLK_CFG_AHB]);
+disable_clk_axi:
+	clk_disable_unprepare(adpt->clk[EMAC_CLK_AXI]);
 
-	return clk_prepare_enable(adpt->clk[EMAC_CLK_HIGH_SPEED]);
+	return ret;
 }
 
 /* Enable clocks; needs emac_clks_phase1_init to be called before */
@@ -727,19 +738,26 @@
 	struct net_device *netdev = dev_get_drvdata(&pdev->dev);
 	struct emac_adapter *adpt = netdev_priv(netdev);
 
+	netif_carrier_off(netdev);
+	netif_tx_disable(netdev);
+
 	unregister_netdev(netdev);
 	netif_napi_del(&adpt->rx_q.napi);
 
+	free_irq(adpt->irq.irq, &adpt->irq);
+	cancel_work_sync(&adpt->work_thread);
+
 	emac_clks_teardown(adpt);
 
 	put_device(&adpt->phydev->mdio.dev);
 	mdiobus_unregister(adpt->mii_bus);
-	free_netdev(netdev);
 
 	if (adpt->phy.digital)
 		iounmap(adpt->phy.digital);
 	iounmap(adpt->phy.base);
 
+	free_netdev(netdev);
+
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qualcomm/qca_debug.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qualcomm/qca_debug.c
@@ -30,6 +30,8 @@
 
 #define QCASPI_MAX_REGS 0x20
 
+#define QCASPI_RX_MAX_FRAMES 4
+
 static const u16 qcaspi_spi_regs[] = {
 	SPI_REG_BFR_SIZE,
 	SPI_REG_WRBUF_SPC_AVA,
@@ -249,31 +251,30 @@
 {
 	struct qcaspi *qca = netdev_priv(dev);
 
-	ring->rx_max_pending = 4;
+	ring->rx_max_pending = QCASPI_RX_MAX_FRAMES;
 	ring->tx_max_pending = TX_RING_MAX_LEN;
-	ring->rx_pending = 4;
+	ring->rx_pending = QCASPI_RX_MAX_FRAMES;
 	ring->tx_pending = qca->txr.count;
 }
 
 static int
 qcaspi_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ring)
 {
-	const struct net_device_ops *ops = dev->netdev_ops;
 	struct qcaspi *qca = netdev_priv(dev);
 
-	if ((ring->rx_pending) ||
+	if (ring->rx_pending != QCASPI_RX_MAX_FRAMES ||
 	    (ring->rx_mini_pending) ||
 	    (ring->rx_jumbo_pending))
 		return -EINVAL;
 
-	if (netif_running(dev))
-		ops->ndo_stop(dev);
+	if (qca->spi_thread)
+		kthread_park(qca->spi_thread);
 
 	qca->txr.count = max_t(u32, ring->tx_pending, TX_RING_MIN_LEN);
 	qca->txr.count = min_t(u16, qca->txr.count, TX_RING_MAX_LEN);
 
-	if (netif_running(dev))
-		ops->ndo_open(dev);
+	if (qca->spi_thread)
+		kthread_unpark(qca->spi_thread);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qualcomm/qca_spi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qualcomm/qca_spi.c
@@ -65,7 +65,7 @@
 
 #define QCASPI_PLUGGABLE_MIN 0
 #define QCASPI_PLUGGABLE_MAX 1
-static int qcaspi_pluggable = QCASPI_PLUGGABLE_MIN;
+static int qcaspi_pluggable = QCASPI_PLUGGABLE_MAX;
 module_param(qcaspi_pluggable, int, 0);
 MODULE_PARM_DESC(qcaspi_pluggable, "Pluggable SPI connection (yes/no).");
 
@@ -434,7 +434,7 @@
 				skb_put(qca->rx_skb, retcode);
 				qca->rx_skb->protocol = eth_type_trans(
 					qca->rx_skb, qca->rx_skb->dev);
-				qca->rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
+				skb_checksum_none_assert(qca->rx_skb);
 				netif_rx_ni(qca->rx_skb);
 				qca->rx_skb = netdev_alloc_skb_ip_align(net_dev,
 					net_dev->mtu + VLAN_ETH_HLEN);
@@ -573,9 +573,20 @@
 	netdev_info(qca->net_dev, "SPI thread created\n");
 	while (!kthread_should_stop()) {
 		set_current_state(TASK_INTERRUPTIBLE);
+		if (kthread_should_park()) {
+			netif_tx_disable(qca->net_dev);
+			netif_carrier_off(qca->net_dev);
+			qcaspi_flush_tx_ring(qca);
+			kthread_parkme();
+			if (qca->sync == QCASPI_SYNC_READY) {
+				netif_carrier_on(qca->net_dev);
+				netif_wake_queue(qca->net_dev);
+			}
+			continue;
+		}
+
 		if ((qca->intr_req == qca->intr_svc) &&
-		    (qca->txr.skb[qca->txr.head] == NULL) &&
-		    (qca->sync == QCASPI_SYNC_READY))
+		    !qca->txr.skb[qca->txr.head])
 			schedule();
 
 		set_current_state(TASK_RUNNING);
@@ -602,11 +613,17 @@
 			if (intr_cause & SPI_INT_CPU_ON) {
 				qcaspi_qca7k_sync(qca, QCASPI_EVENT_CPUON);
 
+				/* Frame decoding in progress */
+				if (qca->frm_handle.state != qca->frm_handle.init)
+					qca->net_dev->stats.rx_dropped++;
+
+				qcafrm_fsm_init_spi(&qca->frm_handle);
+				qca->stats.device_reset++;
+
 				/* not synced. */
 				if (qca->sync != QCASPI_SYNC_READY)
 					continue;
 
-				qca->stats.device_reset++;
 				netif_wake_queue(qca->net_dev);
 				netif_carrier_on(qca->net_dev);
 			}
@@ -806,7 +823,6 @@
 
 	dev->mtu = QCAFRM_MAX_MTU;
 	dev->type = ARPHRD_ETHER;
-	qca->clkspeed = qcaspi_clkspeed;
 	qca->burst_len = qcaspi_burst_len;
 	qca->spi_thread = NULL;
 	qca->buffer_size = (dev->mtu + VLAN_ETH_HLEN + QCAFRM_HEADER_LEN +
@@ -895,17 +911,15 @@
 	legacy_mode = of_property_read_bool(spi->dev.of_node,
 					    "qca,legacy-mode");
 
-	if (qcaspi_clkspeed == 0) {
-		if (spi->max_speed_hz)
-			qcaspi_clkspeed = spi->max_speed_hz;
-		else
-			qcaspi_clkspeed = QCASPI_CLK_SPEED;
-	}
-
-	if ((qcaspi_clkspeed < QCASPI_CLK_SPEED_MIN) ||
-	    (qcaspi_clkspeed > QCASPI_CLK_SPEED_MAX)) {
-		dev_err(&spi->dev, "Invalid clkspeed: %d\n",
-			qcaspi_clkspeed);
+	if (qcaspi_clkspeed)
+		spi->max_speed_hz = qcaspi_clkspeed;
+	else if (!spi->max_speed_hz)
+		spi->max_speed_hz = QCASPI_CLK_SPEED;
+
+	if (spi->max_speed_hz < QCASPI_CLK_SPEED_MIN ||
+	    spi->max_speed_hz > QCASPI_CLK_SPEED_MAX) {
+		dev_err(&spi->dev, "Invalid clkspeed: %u\n",
+			spi->max_speed_hz);
 		return -EINVAL;
 	}
 
@@ -930,14 +944,13 @@
 		return -EINVAL;
 	}
 
-	dev_info(&spi->dev, "ver=%s, clkspeed=%d, burst_len=%d, pluggable=%d\n",
+	dev_info(&spi->dev, "ver=%s, clkspeed=%u, burst_len=%d, pluggable=%d\n",
 		 QCASPI_DRV_VERSION,
-		 qcaspi_clkspeed,
+		 spi->max_speed_hz,
 		 qcaspi_burst_len,
 		 qcaspi_pluggable);
 
 	spi->mode = SPI_MODE_3;
-	spi->max_speed_hz = qcaspi_clkspeed;
 	if (spi_setup(spi) < 0) {
 		dev_err(&spi->dev, "Unable to setup SPI device\n");
 		return -EFAULT;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qualcomm/qca_spi.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qualcomm/qca_spi.h
@@ -101,7 +101,6 @@
 #endif
 
 	/* user configurable options */
-	u32 clkspeed;
 	u8 legacy_mode;
 	u16 burst_len;
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qualcomm/qca_uart.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qualcomm/qca_uart.c
@@ -107,7 +107,7 @@
 			skb_put(qca->rx_skb, retcode);
 			qca->rx_skb->protocol = eth_type_trans(
 						qca->rx_skb, qca->rx_skb->dev);
-			qca->rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
+			skb_checksum_none_assert(qca->rx_skb);
 			netif_rx_ni(qca->rx_skb);
 			qca->rx_skb = netdev_alloc_skb_ip_align(netdev,
 								netdev->mtu +
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
@@ -13,25 +13,6 @@
 #include "rmnet_vnd.h"
 #include "rmnet_private.h"
 
-/* Locking scheme -
- * The shared resource which needs to be protected is realdev->rx_handler_data.
- * For the writer path, this is using rtnl_lock(). The writer paths are
- * rmnet_newlink(), rmnet_dellink() and rmnet_force_unassociate_device(). These
- * paths are already called with rtnl_lock() acquired in. There is also an
- * ASSERT_RTNL() to ensure that we are calling with rtnl acquired. For
- * dereference here, we will need to use rtnl_dereference(). Dev list writing
- * needs to happen with rtnl_lock() acquired for netdev_master_upper_dev_link().
- * For the reader path, the real_dev->rx_handler_data is called in the TX / RX
- * path. We only need rcu_read_lock() for these scenarios. In these cases,
- * the rcu_read_lock() is held in __dev_queue_xmit() and
- * netif_receive_skb_internal(), so readers need to use rcu_dereference_rtnl()
- * to get the relevant information. For dev list reading, we again acquire
- * rcu_read_lock() in rmnet_dellink() for netdev_master_upper_dev_get_rcu().
- * We also use unregister_netdevice_many() to free all rmnet devices in
- * rmnet_force_unassociate_device() so we dont lose the rtnl_lock() and free in
- * same context.
- */
-
 /* Local Definitions and Declarations */
 
 static const struct nla_policy rmnet_policy[IFLA_RMNET_MAX + 1] = {
@@ -51,9 +32,10 @@
 	return rtnl_dereference(real_dev->rx_handler_data);
 }
 
-static int rmnet_unregister_real_device(struct net_device *real_dev,
-					struct rmnet_port *port)
+static int rmnet_unregister_real_device(struct net_device *real_dev)
 {
+	struct rmnet_port *port = rmnet_get_port_rtnl(real_dev);
+
 	if (port->nr_rmnet_devs)
 		return -EINVAL;
 
@@ -61,22 +43,27 @@
 
 	kfree(port);
 
-	/* release reference on real_dev */
-	dev_put(real_dev);
-
 	netdev_dbg(real_dev, "Removed from rmnet\n");
 	return 0;
 }
 
-static int rmnet_register_real_device(struct net_device *real_dev)
+static int rmnet_register_real_device(struct net_device *real_dev,
+				      struct netlink_ext_ack *extack)
 {
 	struct rmnet_port *port;
 	int rc, entry;
 
 	ASSERT_RTNL();
 
-	if (rmnet_is_real_dev_registered(real_dev))
+	if (rmnet_is_real_dev_registered(real_dev)) {
+		port = rmnet_get_port_rtnl(real_dev);
+		if (port->rmnet_mode != RMNET_EPMODE_VND) {
+			NL_SET_ERR_MSG_MOD(extack, "bridge device already exists");
+			return -EINVAL;
+		}
+
 		return 0;
+	}
 
 	port = kzalloc(sizeof(*port), GFP_ATOMIC);
 	if (!port)
@@ -89,9 +76,6 @@
 		return -EBUSY;
 	}
 
-	/* hold on to real dev for MAP data */
-	dev_hold(real_dev);
-
 	for (entry = 0; entry < RMNET_MAX_LOGICAL_EP; entry++)
 		INIT_HLIST_HEAD(&port->muxed_ep[entry]);
 
@@ -99,28 +83,33 @@
 	return 0;
 }
 
-static void rmnet_unregister_bridge(struct net_device *dev,
-				    struct rmnet_port *port)
+static void rmnet_unregister_bridge(struct rmnet_port *port)
 {
-	struct rmnet_port *bridge_port;
-	struct net_device *bridge_dev;
+	struct net_device *bridge_dev, *real_dev, *rmnet_dev;
+	struct rmnet_port *real_port;
 
 	if (port->rmnet_mode != RMNET_EPMODE_BRIDGE)
 		return;
 
-	/* bridge slave handling */
+	rmnet_dev = port->rmnet_dev;
 	if (!port->nr_rmnet_devs) {
-		bridge_dev = port->bridge_ep;
-
-		bridge_port = rmnet_get_port_rtnl(bridge_dev);
-		bridge_port->bridge_ep = NULL;
-		bridge_port->rmnet_mode = RMNET_EPMODE_VND;
+		/* bridge device */
+		real_dev = port->bridge_ep;
+		bridge_dev = port->dev;
+
+		real_port = rmnet_get_port_rtnl(real_dev);
+		real_port->bridge_ep = NULL;
+		real_port->rmnet_mode = RMNET_EPMODE_VND;
 	} else {
+		/* real device */
 		bridge_dev = port->bridge_ep;
 
-		bridge_port = rmnet_get_port_rtnl(bridge_dev);
-		rmnet_unregister_real_device(bridge_dev, bridge_port);
+		port->bridge_ep = NULL;
+		port->rmnet_mode = RMNET_EPMODE_VND;
 	}
+
+	netdev_upper_dev_unlink(bridge_dev, rmnet_dev);
+	rmnet_unregister_real_device(bridge_dev);
 }
 
 static int rmnet_newlink(struct net *src_net, struct net_device *dev,
@@ -135,6 +124,11 @@
 	int err = 0;
 	u16 mux_id;
 
+	if (!tb[IFLA_LINK]) {
+		NL_SET_ERR_MSG_MOD(extack, "link not specified");
+		return -EINVAL;
+	}
+
 	real_dev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK]));
 	if (!real_dev || !dev)
 		return -ENODEV;
@@ -148,7 +142,7 @@
 
 	mux_id = nla_get_u16(data[IFLA_RMNET_MUX_ID]);
 
-	err = rmnet_register_real_device(real_dev);
+	err = rmnet_register_real_device(real_dev, extack);
 	if (err)
 		goto err0;
 
@@ -157,7 +151,12 @@
 	if (err)
 		goto err1;
 
+	err = netdev_upper_dev_link(real_dev, dev, extack);
+	if (err < 0)
+		goto err2;
+
 	port->rmnet_mode = mode;
+	port->rmnet_dev = dev;
 
 	hlist_add_head_rcu(&ep->hlnode, &port->muxed_ep[mux_id]);
 
@@ -173,8 +172,11 @@
 
 	return 0;
 
+err2:
+	unregister_netdevice(dev);
+	rmnet_vnd_dellink(mux_id, port, ep);
 err1:
-	rmnet_unregister_real_device(real_dev, port);
+	rmnet_unregister_real_device(real_dev);
 err0:
 	kfree(ep);
 	return err;
@@ -183,77 +185,74 @@
 static void rmnet_dellink(struct net_device *dev, struct list_head *head)
 {
 	struct rmnet_priv *priv = netdev_priv(dev);
-	struct net_device *real_dev;
+	struct net_device *real_dev, *bridge_dev;
+	struct rmnet_port *real_port, *bridge_port;
 	struct rmnet_endpoint *ep;
-	struct rmnet_port *port;
-	u8 mux_id;
+	u8 mux_id = priv->mux_id;
 
 	real_dev = priv->real_dev;
 
-	if (!real_dev || !rmnet_is_real_dev_registered(real_dev))
+	if (!rmnet_is_real_dev_registered(real_dev))
 		return;
 
-	port = rmnet_get_port_rtnl(real_dev);
-
-	mux_id = rmnet_vnd_get_mux(dev);
+	real_port = rmnet_get_port_rtnl(real_dev);
+	bridge_dev = real_port->bridge_ep;
+	if (bridge_dev) {
+		bridge_port = rmnet_get_port_rtnl(bridge_dev);
+		rmnet_unregister_bridge(bridge_port);
+	}
 
-	ep = rmnet_get_endpoint(port, mux_id);
+	ep = rmnet_get_endpoint(real_port, mux_id);
 	if (ep) {
 		hlist_del_init_rcu(&ep->hlnode);
-		rmnet_unregister_bridge(dev, port);
-		rmnet_vnd_dellink(mux_id, port, ep);
+		rmnet_vnd_dellink(mux_id, real_port, ep);
 		kfree(ep);
 	}
-	rmnet_unregister_real_device(real_dev, port);
 
+	netdev_upper_dev_unlink(real_dev, dev);
+	rmnet_unregister_real_device(real_dev);
 	unregister_netdevice_queue(dev, head);
 }
 
-static void rmnet_force_unassociate_device(struct net_device *dev)
+static void rmnet_force_unassociate_device(struct net_device *real_dev)
 {
-	struct net_device *real_dev = dev;
 	struct hlist_node *tmp_ep;
 	struct rmnet_endpoint *ep;
 	struct rmnet_port *port;
 	unsigned long bkt_ep;
 	LIST_HEAD(list);
 
-	if (!rmnet_is_real_dev_registered(real_dev))
-		return;
-
-	ASSERT_RTNL();
-
-	port = rmnet_get_port_rtnl(dev);
-
-	rcu_read_lock();
-	rmnet_unregister_bridge(dev, port);
-
-	hash_for_each_safe(port->muxed_ep, bkt_ep, tmp_ep, ep, hlnode) {
-		unregister_netdevice_queue(ep->egress_dev, &list);
-		rmnet_vnd_dellink(ep->mux_id, port, ep);
+	port = rmnet_get_port_rtnl(real_dev);
 
-		hlist_del_init_rcu(&ep->hlnode);
-		kfree(ep);
+	if (port->nr_rmnet_devs) {
+		/* real device */
+		rmnet_unregister_bridge(port);
+		hash_for_each_safe(port->muxed_ep, bkt_ep, tmp_ep, ep, hlnode) {
+			unregister_netdevice_queue(ep->egress_dev, &list);
+			netdev_upper_dev_unlink(real_dev, ep->egress_dev);
+			rmnet_vnd_dellink(ep->mux_id, port, ep);
+			hlist_del_init_rcu(&ep->hlnode);
+			kfree(ep);
+		}
+		rmnet_unregister_real_device(real_dev);
+		unregister_netdevice_many(&list);
+	} else {
+		rmnet_unregister_bridge(port);
 	}
-
-	rcu_read_unlock();
-	unregister_netdevice_many(&list);
-
-	rmnet_unregister_real_device(real_dev, port);
 }
 
 static int rmnet_config_notify_cb(struct notifier_block *nb,
 				  unsigned long event, void *data)
 {
-	struct net_device *dev = netdev_notifier_info_to_dev(data);
+	struct net_device *real_dev = netdev_notifier_info_to_dev(data);
 
-	if (!dev)
+	if (!rmnet_is_real_dev_registered(real_dev))
 		return NOTIFY_DONE;
 
 	switch (event) {
 	case NETDEV_UNREGISTER:
-		netdev_dbg(dev, "Kernel unregister\n");
-		rmnet_force_unassociate_device(dev);
+		netdev_dbg(real_dev, "Kernel unregister\n");
+		rmnet_force_unassociate_device(real_dev);
 		break;
 
 	default:
@@ -288,32 +287,41 @@
 {
 	struct rmnet_priv *priv = netdev_priv(dev);
 	struct net_device *real_dev;
-	struct rmnet_endpoint *ep;
 	struct rmnet_port *port;
 	u16 mux_id;
 
 	if (!dev)
 		return -ENODEV;
 
-	real_dev = __dev_get_by_index(dev_net(dev),
-				      nla_get_u32(tb[IFLA_LINK]));
-
-	if (!real_dev || !rmnet_is_real_dev_registered(real_dev))
+	real_dev = priv->real_dev;
+	if (!rmnet_is_real_dev_registered(real_dev))
 		return -ENODEV;
 
 	port = rmnet_get_port_rtnl(real_dev);
 
 	if (data[IFLA_RMNET_MUX_ID]) {
 		mux_id = nla_get_u16(data[IFLA_RMNET_MUX_ID]);
-		ep = rmnet_get_endpoint(port, priv->mux_id);
-		if (!ep)
-			return -ENODEV;
 
-		hlist_del_init_rcu(&ep->hlnode);
-		hlist_add_head_rcu(&ep->hlnode, &port->muxed_ep[mux_id]);
+		if (mux_id != priv->mux_id) {
+			struct rmnet_endpoint *ep;
 
-		ep->mux_id = mux_id;
-		priv->mux_id = mux_id;
+			ep = rmnet_get_endpoint(port, priv->mux_id);
+			if (!ep)
+				return -ENODEV;
+
+			if (rmnet_get_endpoint(port, mux_id)) {
+				NL_SET_ERR_MSG_MOD(extack,
+						   "MUX ID already exists");
+				return -EINVAL;
+			}
+
+			hlist_del_init_rcu(&ep->hlnode);
+			hlist_add_head_rcu(&ep->hlnode,
+					   &port->muxed_ep[mux_id]);
+
+			ep->mux_id = mux_id;
+			priv->mux_id = mux_id;
+		}
 	}
 
 	if (data[IFLA_RMNET_FLAGS]) {
@@ -367,7 +375,7 @@
 
 struct rtnl_link_ops rmnet_link_ops __read_mostly = {
 	.kind		= "rmnet",
-	.maxtype	= __IFLA_RMNET_MAX,
+	.maxtype	= IFLA_RMNET_MAX,
 	.priv_size	= sizeof(struct rmnet_priv),
 	.setup		= rmnet_vnd_setup,
 	.validate	= rmnet_rtnl_validate,
@@ -379,11 +387,10 @@
 	.fill_info	= rmnet_fill_info,
 };
 
-/* Needs either rcu_read_lock() or rtnl lock */
-struct rmnet_port *rmnet_get_port(struct net_device *real_dev)
+struct rmnet_port *rmnet_get_port_rcu(struct net_device *real_dev)
 {
 	if (rmnet_is_real_dev_registered(real_dev))
-		return rcu_dereference_rtnl(real_dev->rx_handler_data);
+		return rcu_dereference_bh(real_dev->rx_handler_data);
 	else
 		return NULL;
 }
@@ -409,7 +416,7 @@
 	struct rmnet_port *port, *slave_port;
 	int err;
 
-	port = rmnet_get_port(real_dev);
+	port = rmnet_get_port_rtnl(real_dev);
 
 	/* If there is more than one rmnet dev attached, its probably being
 	 * used for muxing. Skip the briding in that case
@@ -420,13 +427,21 @@
 	if (rmnet_is_real_dev_registered(slave_dev))
 		return -EBUSY;
 
-	err = rmnet_register_real_device(slave_dev);
+	err = rmnet_register_real_device(slave_dev, extack);
 	if (err)
 		return -EBUSY;
 
-	slave_port = rmnet_get_port(slave_dev);
+	err = netdev_master_upper_dev_link(slave_dev, rmnet_dev, NULL, NULL,
+					   extack);
+	if (err) {
+		rmnet_unregister_real_device(slave_dev);
+		return err;
+	}
+
+	slave_port = rmnet_get_port_rtnl(slave_dev);
 	slave_port->rmnet_mode = RMNET_EPMODE_BRIDGE;
 	slave_port->bridge_ep = real_dev;
+	slave_port->rmnet_dev = rmnet_dev;
 
 	port->rmnet_mode = RMNET_EPMODE_BRIDGE;
 	port->bridge_ep = slave_dev;
@@ -438,16 +453,9 @@
 int rmnet_del_bridge(struct net_device *rmnet_dev,
 		     struct net_device *slave_dev)
 {
-	struct rmnet_priv *priv = netdev_priv(rmnet_dev);
-	struct net_device *real_dev = priv->real_dev;
-	struct rmnet_port *port, *slave_port;
+	struct rmnet_port *port = rmnet_get_port_rtnl(slave_dev);
 
-	port = rmnet_get_port(real_dev);
-	port->rmnet_mode = RMNET_EPMODE_VND;
-	port->bridge_ep = NULL;
-
-	slave_port = rmnet_get_port(slave_dev);
-	rmnet_unregister_real_device(slave_dev, slave_port);
+	rmnet_unregister_bridge(port);
 
 	netdev_dbg(slave_dev, "removed from rmnet as slave\n");
 	return 0;
@@ -473,8 +481,8 @@
 
 static void __exit rmnet_exit(void)
 {
-	unregister_netdevice_notifier(&rmnet_dev_notifier);
 	rtnl_link_unregister(&rmnet_link_ops);
+	unregister_netdevice_notifier(&rmnet_dev_notifier);
 }
 
 module_init(rmnet_init)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.h
@@ -28,6 +28,7 @@
 	u8 rmnet_mode;
 	struct hlist_head muxed_ep[RMNET_MAX_LOGICAL_EP];
 	struct net_device *bridge_ep;
+	struct net_device *rmnet_dev;
 };
 
 extern struct rtnl_link_ops rmnet_link_ops;
@@ -65,7 +66,7 @@
 	struct rmnet_priv_stats stats;
 };
 
-struct rmnet_port *rmnet_get_port(struct net_device *real_dev);
+struct rmnet_port *rmnet_get_port_rcu(struct net_device *real_dev);
 struct rmnet_endpoint *rmnet_get_endpoint(struct rmnet_port *port, u8 mux_id);
 int rmnet_add_bridge(struct net_device *rmnet_dev,
 		     struct net_device *slave_dev,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c
@@ -159,6 +159,9 @@
 static void
 rmnet_bridge_handler(struct sk_buff *skb, struct net_device *bridge_dev)
 {
+	if (skb_mac_header_was_set(skb))
+		skb_push(skb, skb->mac_len);
+
 	if (bridge_dev) {
 		skb->dev = bridge_dev;
 		dev_queue_xmit(skb);
@@ -184,7 +187,12 @@
 		return RX_HANDLER_PASS;
 
 	dev = skb->dev;
-	port = rmnet_get_port(dev);
+	port = rmnet_get_port_rcu(dev);
+	if (unlikely(!port)) {
+		atomic_long_inc(&skb->dev->rx_nohandler);
+		kfree_skb(skb);
+		goto done;
+	}
 
 	switch (port->rmnet_mode) {
 	case RMNET_EPMODE_VND:
@@ -217,7 +225,7 @@
 	skb->dev = priv->real_dev;
 	mux_id = priv->mux_id;
 
-	port = rmnet_get_port(skb->dev);
+	port = rmnet_get_port_rcu(skb->dev);
 	if (!port)
 		goto drop;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c
@@ -266,14 +266,6 @@
 	return 0;
 }
 
-u8 rmnet_vnd_get_mux(struct net_device *rmnet_dev)
-{
-	struct rmnet_priv *priv;
-
-	priv = netdev_priv(rmnet_dev);
-	return priv->mux_id;
-}
-
 int rmnet_vnd_do_flow_control(struct net_device *rmnet_dev, int enable)
 {
 	netdev_dbg(rmnet_dev, "Setting VND TX queue state to %d\n", enable);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.h
@@ -16,6 +16,5 @@
 		      struct rmnet_endpoint *ep);
 void rmnet_vnd_rx_fixup(struct sk_buff *skb, struct net_device *dev);
 void rmnet_vnd_tx_fixup(struct sk_buff *skb, struct net_device *dev);
-u8 rmnet_vnd_get_mux(struct net_device *rmnet_dev);
 void rmnet_vnd_setup(struct net_device *dev);
 #endif /* _RMNET_VND_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/rdc/r6040.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/rdc/r6040.c
@@ -119,6 +119,8 @@
 #define PHY_ST		0x8A	/* PHY status register */
 #define MAC_SM		0xAC	/* MAC status machine */
 #define  MAC_SM_RST	0x0002	/* MAC status machine reset */
+#define MD_CSC		0xb6	/* MDC speed control register */
+#define  MD_CSC_DEFAULT	0x0030
 #define MAC_ID		0xBE	/* Identifier register */
 
 #define TX_DCNT		0x80	/* TX descriptor count */
@@ -354,8 +356,9 @@
 {
 	void __iomem *ioaddr = lp->base;
 	int limit = MAC_DEF_TIMEOUT;
-	u16 cmd;
+	u16 cmd, md_csc;
 
+	md_csc = ioread16(ioaddr + MD_CSC);
 	iowrite16(MAC_RST, ioaddr + MCR1);
 	while (limit--) {
 		cmd = ioread16(ioaddr + MCR1);
@@ -367,6 +370,10 @@
 	iowrite16(MAC_SM_RST, ioaddr + MAC_SM);
 	iowrite16(0, ioaddr + MAC_SM);
 	mdelay(5);
+
+	/* Restore MDIO clock frequency */
+	if (md_csc != MD_CSC_DEFAULT)
+		iowrite16(md_csc, ioaddr + MD_CSC);
 }
 
 static void r6040_init_mac_regs(struct net_device *dev)
@@ -1155,10 +1162,12 @@
 	err = register_netdev(dev);
 	if (err) {
 		dev_err(&pdev->dev, "Failed to register net device\n");
-		goto err_out_mdio_unregister;
+		goto err_out_phy_disconnect;
 	}
 	return 0;
 
+err_out_phy_disconnect:
+	phy_disconnect(dev->phydev);
 err_out_mdio_unregister:
 	mdiobus_unregister(lp->mii_bus);
 err_out_mdio:
@@ -1182,6 +1191,7 @@
 	struct r6040_private *lp = netdev_priv(dev);
 
 	unregister_netdev(dev);
+	phy_disconnect(dev->phydev);
 	mdiobus_unregister(lp->mii_bus);
 	mdiobus_free(lp->mii_bus);
 	netif_napi_del(&lp->napi);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/realtek/r8169_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/realtek/r8169_main.c
@@ -52,6 +52,7 @@
 #define FIRMWARE_8168G_3	"rtl_nic/rtl8168g-3.fw"
 #define FIRMWARE_8168H_1	"rtl_nic/rtl8168h-1.fw"
 #define FIRMWARE_8168H_2	"rtl_nic/rtl8168h-2.fw"
+#define FIRMWARE_8168FP_3	"rtl_nic/rtl8168fp-3.fw"
 #define FIRMWARE_8107E_1	"rtl_nic/rtl8107e-1.fw"
 #define FIRMWARE_8107E_2	"rtl_nic/rtl8107e-2.fw"
 #define FIRMWARE_8125A_3	"rtl_nic/rtl8125a-3.fw"
@@ -135,6 +136,7 @@
 	RTL_GIGA_MAC_VER_49,
 	RTL_GIGA_MAC_VER_50,
 	RTL_GIGA_MAC_VER_51,
+	RTL_GIGA_MAC_VER_52,
 	RTL_GIGA_MAC_VER_60,
 	RTL_GIGA_MAC_VER_61,
 	RTL_GIGA_MAC_NONE
@@ -202,6 +204,7 @@
 	[RTL_GIGA_MAC_VER_49] = {"RTL8168ep/8111ep"			},
 	[RTL_GIGA_MAC_VER_50] = {"RTL8168ep/8111ep"			},
 	[RTL_GIGA_MAC_VER_51] = {"RTL8168ep/8111ep"			},
+	[RTL_GIGA_MAC_VER_52] = {"RTL8168fp/RTL8117",  FIRMWARE_8168FP_3},
 	[RTL_GIGA_MAC_VER_60] = {"RTL8125"				},
 	[RTL_GIGA_MAC_VER_61] = {"RTL8125",		FIRMWARE_8125A_3},
 };
@@ -212,6 +215,7 @@
 	{ PCI_VDEVICE(REALTEK,	0x8129) },
 	{ PCI_VDEVICE(REALTEK,	0x8136), RTL_CFG_NO_GBIT },
 	{ PCI_VDEVICE(REALTEK,	0x8161) },
+	{ PCI_VDEVICE(REALTEK,	0x8162) },
 	{ PCI_VDEVICE(REALTEK,	0x8167) },
 	{ PCI_VDEVICE(REALTEK,	0x8168) },
 	{ PCI_VDEVICE(NCUBE,	0x8168) },
@@ -622,7 +626,34 @@
 	__le64	rx_broadcast;
 	__le32	rx_multicast;
 	__le16	tx_aborted;
-	__le16	tx_underun;
+	__le16	tx_underrun;
+	/* new since RTL8125 */
+	__le64 tx_octets;
+	__le64 rx_octets;
+	__le64 rx_multicast64;
+	__le64 tx_unicast64;
+	__le64 tx_broadcast64;
+	__le64 tx_multicast64;
+	__le32 tx_pause_on;
+	__le32 tx_pause_off;
+	__le32 tx_pause_all;
+	__le32 tx_deferred;
+	__le32 tx_late_collision;
+	__le32 tx_all_collision;
+	__le32 tx_aborted32;
+	__le32 align_errors32;
+	__le32 rx_frame_too_long;
+	__le32 rx_runt;
+	__le32 rx_pause_on;
+	__le32 rx_pause_off;
+	__le32 rx_pause_all;
+	__le32 rx_unknown_opcode;
+	__le32 rx_mac_error;
+	__le32 tx_underrun32;
+	__le32 rx_mac_missed;
+	__le32 rx_tcam_dropped;
+	__le32 tdu;
+	__le32 rdu;
 };
 
 struct rtl8169_tc_offsets {
@@ -680,6 +711,7 @@
 	struct rtl8169_counters *counters;
 	struct rtl8169_tc_offsets tc_offset;
 	u32 saved_wolopts;
+	int eee_adv;
 
 	const char *fw_name;
 	struct rtl_fw *rtl_fw;
@@ -712,6 +744,7 @@
 MODULE_FIRMWARE(FIRMWARE_8168G_3);
 MODULE_FIRMWARE(FIRMWARE_8168H_1);
 MODULE_FIRMWARE(FIRMWARE_8168H_2);
+MODULE_FIRMWARE(FIRMWARE_8168FP_3);
 MODULE_FIRMWARE(FIRMWARE_8107E_1);
 MODULE_FIRMWARE(FIRMWARE_8107E_2);
 MODULE_FIRMWARE(FIRMWARE_8125A_3);
@@ -741,12 +774,6 @@
 	RTL_W8(tp, Cfg9346, Cfg9346_Unlock);
 }
 
-static void rtl_tx_performance_tweak(struct rtl8169_private *tp, u16 force)
-{
-	pcie_capability_clear_and_set_word(tp->pci_dev, PCI_EXP_DEVCTL,
-					   PCI_EXP_DEVCTL_READRQ, force);
-}
-
 static bool rtl_is_8125(struct rtl8169_private *tp)
 {
 	return tp->mac_version >= RTL_GIGA_MAC_VER_60;
@@ -756,7 +783,7 @@
 {
 	return tp->mac_version >= RTL_GIGA_MAC_VER_34 &&
 	       tp->mac_version != RTL_GIGA_MAC_VER_39 &&
-	       tp->mac_version <= RTL_GIGA_MAC_VER_51;
+	       tp->mac_version <= RTL_GIGA_MAC_VER_52;
 }
 
 static bool rtl_supports_eee(struct rtl8169_private *tp)
@@ -1092,6 +1119,17 @@
 	rtl_writephy(tp, reg_addr, (val & ~m) | p);
 }
 
+static void r8168g_phy_param(struct phy_device *phydev, u16 parm,
+			     u16 mask, u16 val)
+{
+	int oldpage = phy_select_page(phydev, 0x0a43);
+
+	__phy_write(phydev, 0x13, parm);
+	__phy_modify(phydev, 0x14, mask, val);
+
+	phy_restore_page(phydev, oldpage, 0);
+}
+
 DECLARE_RTL_COND(rtl_ephyar_cond)
 {
 	return RTL_R32(tp, EPHYAR) & EPHYAR_FLAG;
@@ -1115,6 +1153,13 @@
 		RTL_R32(tp, EPHYAR) & EPHYAR_DATA_MASK : ~0;
 }
 
+static void r8168fp_adjust_ocp_cmd(struct rtl8169_private *tp, u32 *cmd, int type)
+{
+	/* based on RTL8168FP_OOBMAC_BASE in vendor driver */
+	if (tp->mac_version == RTL_GIGA_MAC_VER_52 && type == ERIAR_OOB)
+		*cmd |= 0x7f0 << 18;
+}
+
 DECLARE_RTL_COND(rtl_eriar_cond)
 {
 	return RTL_R32(tp, ERIAR) & ERIAR_FLAG;
@@ -1123,9 +1168,12 @@
 static void _rtl_eri_write(struct rtl8169_private *tp, int addr, u32 mask,
 			   u32 val, int type)
 {
+	u32 cmd = ERIAR_WRITE_CMD | type | mask | addr;
+
 	BUG_ON((addr & 3) || (mask == 0));
 	RTL_W32(tp, ERIDR, val);
-	RTL_W32(tp, ERIAR, ERIAR_WRITE_CMD | type | mask | addr);
+	r8168fp_adjust_ocp_cmd(tp, &cmd, type);
+	RTL_W32(tp, ERIAR, cmd);
 
 	rtl_udelay_loop_wait_low(tp, &rtl_eriar_cond, 100, 100);
 }
@@ -1138,7 +1186,10 @@
 
 static u32 _rtl_eri_read(struct rtl8169_private *tp, int addr, int type)
 {
-	RTL_W32(tp, ERIAR, ERIAR_READ_CMD | type | ERIAR_MASK_1111 | addr);
+	u32 cmd = ERIAR_READ_CMD | type | ERIAR_MASK_1111 | addr;
+
+	r8168fp_adjust_ocp_cmd(tp, &cmd, type);
+	RTL_W32(tp, ERIAR, cmd);
 
 	return rtl_udelay_loop_wait_high(tp, &rtl_eriar_cond, 100, 100) ?
 		RTL_R32(tp, ERIDR) : ~0;
@@ -1262,9 +1313,7 @@
 	case RTL_GIGA_MAC_VER_31:
 		rtl8168dp_driver_start(tp);
 		break;
-	case RTL_GIGA_MAC_VER_49:
-	case RTL_GIGA_MAC_VER_50:
-	case RTL_GIGA_MAC_VER_51:
+	case RTL_GIGA_MAC_VER_49 ... RTL_GIGA_MAC_VER_52:
 		rtl8168ep_driver_start(tp);
 		break;
 	default:
@@ -1296,9 +1345,7 @@
 	case RTL_GIGA_MAC_VER_31:
 		rtl8168dp_driver_stop(tp);
 		break;
-	case RTL_GIGA_MAC_VER_49:
-	case RTL_GIGA_MAC_VER_50:
-	case RTL_GIGA_MAC_VER_51:
+	case RTL_GIGA_MAC_VER_49 ... RTL_GIGA_MAC_VER_52:
 		rtl8168ep_driver_stop(tp);
 		break;
 	default:
@@ -1326,9 +1373,7 @@
 	case RTL_GIGA_MAC_VER_28:
 	case RTL_GIGA_MAC_VER_31:
 		return r8168dp_check_dash(tp);
-	case RTL_GIGA_MAC_VER_49:
-	case RTL_GIGA_MAC_VER_50:
-	case RTL_GIGA_MAC_VER_51:
+	case RTL_GIGA_MAC_VER_49 ... RTL_GIGA_MAC_VER_52:
 		return r8168ep_check_dash(tp);
 	default:
 		return false;
@@ -1503,7 +1548,7 @@
 		break;
 	case RTL_GIGA_MAC_VER_34:
 	case RTL_GIGA_MAC_VER_37:
-	case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_51:
+	case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_52:
 		options = RTL_R8(tp, Config2) & ~PME_SIGNAL;
 		if (wolopts)
 			options |= PME_SIGNAL;
@@ -1516,6 +1561,7 @@
 	rtl_lock_config_regs(tp);
 
 	device_set_wakeup_enable(tp_to_dev(tp), wolopts);
+	tp->dev->wol_enabled = wolopts ? 1 : 0;
 }
 
 static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
@@ -1798,14 +1844,14 @@
 	data[9] = le64_to_cpu(counters->rx_broadcast);
 	data[10] = le32_to_cpu(counters->rx_multicast);
 	data[11] = le16_to_cpu(counters->tx_aborted);
-	data[12] = le16_to_cpu(counters->tx_underun);
+	data[12] = le16_to_cpu(counters->tx_underrun);
 }
 
 static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data)
 {
 	switch(stringset) {
 	case ETH_SS_STATS:
-		memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings));
+		memcpy(data, rtl8169_gstrings, sizeof(rtl8169_gstrings));
 		break;
 	}
 }
@@ -2074,6 +2120,10 @@
 	}
 
 	ret = phy_ethtool_set_eee(tp->phydev, data);
+
+	if (!ret)
+		tp->eee_adv = phy_read_mmd(dev->phydev, MDIO_MMD_AN,
+					   MDIO_AN_EEE_ADV);
 out:
 	pm_runtime_put_noidle(d);
 	return ret;
@@ -2104,10 +2154,16 @@
 static void rtl_enable_eee(struct rtl8169_private *tp)
 {
 	struct phy_device *phydev = tp->phydev;
-	int supported = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE);
+	int adv;
+
+	/* respect EEE advertisement the user may have set */
+	if (tp->eee_adv >= 0)
+		adv = tp->eee_adv;
+	else
+		adv = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE);
 
-	if (supported > 0)
-		phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, supported);
+	if (adv >= 0)
+		phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, adv);
 }
 
 static void rtl8169_get_mac_version(struct rtl8169_private *tp)
@@ -2132,6 +2188,9 @@
 		{ 0x7cf, 0x608,	RTL_GIGA_MAC_VER_60 },
 		{ 0x7c8, 0x608,	RTL_GIGA_MAC_VER_61 },
 
+		/* RTL8117 */
+		{ 0x7cf, 0x54a,	RTL_GIGA_MAC_VER_52 },
+
 		/* 8168EP family. */
 		{ 0x7cf, 0x502,	RTL_GIGA_MAC_VER_51 },
 		{ 0x7cf, 0x501,	RTL_GIGA_MAC_VER_50 },
@@ -2190,6 +2249,8 @@
 		{ 0x7cf, 0x348,	RTL_GIGA_MAC_VER_07 },
 		{ 0x7cf, 0x248,	RTL_GIGA_MAC_VER_07 },
 		{ 0x7cf, 0x340,	RTL_GIGA_MAC_VER_13 },
+		/* RTL8401, reportedly works if treated as RTL8101e */
+		{ 0x7cf, 0x240,	RTL_GIGA_MAC_VER_13 },
 		{ 0x7cf, 0x343,	RTL_GIGA_MAC_VER_10 },
 		{ 0x7cf, 0x342,	RTL_GIGA_MAC_VER_16 },
 		{ 0x7c8, 0x348,	RTL_GIGA_MAC_VER_09 },
@@ -2256,8 +2317,11 @@
 static void rtl_apply_firmware(struct rtl8169_private *tp)
 {
 	/* TODO: release firmware if rtl_fw_write_firmware signals failure. */
-	if (tp->rtl_fw)
+	if (tp->rtl_fw) {
 		rtl_fw_write_firmware(tp, tp->rtl_fw);
+		/* At least one firmware doesn't reset tp->ocp_base. */
+		tp->ocp_base = OCP_STD_PHY_BASE;
+	}
 }
 
 static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val)
@@ -3228,12 +3292,8 @@
 
 	phy_modify_paged(phydev, 0x0bcc, 0x14, BIT(8), 0);
 	phy_modify_paged(phydev, 0x0a44, 0x11, 0, BIT(7) | BIT(6));
-	phy_write(phydev, 0x1f, 0x0a43);
-	phy_write(phydev, 0x13, 0x8084);
-	phy_clear_bits(phydev, 0x14, BIT(14) | BIT(13));
-	phy_set_bits(phydev, 0x10, BIT(12) | BIT(1) | BIT(0));
-
-	phy_write(phydev, 0x1f, 0x0000);
+	r8168g_phy_param(phydev, 0x8084, 0x6000, 0x0000);
+	phy_modify_paged(phydev, 0x0a43, 0x10, 0x0000, 0x1003);
 }
 
 static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp)
@@ -3263,9 +3323,7 @@
 	phy_modify_paged(tp->phydev, 0x0a4b, 0x11, 0, BIT(2));
 
 	/* Enable UC LPF tune function */
-	rtl_writephy(tp, 0x1f, 0x0a43);
-	rtl_writephy(tp, 0x13, 0x8012);
-	rtl_w0w1_phy(tp, 0x14, 0x8000, 0x0000);
+	r8168g_phy_param(tp->phydev, 0x8012, 0x0000, 0x8000);
 
 	phy_modify_paged(tp->phydev, 0x0c42, 0x11, BIT(13), BIT(14));
 
@@ -3295,73 +3353,48 @@
 
 static void rtl8168h_1_hw_phy_config(struct rtl8169_private *tp)
 {
+	struct phy_device *phydev = tp->phydev;
 	u16 dout_tapbin;
 	u32 data;
 
 	rtl_apply_firmware(tp);
 
 	/* CHN EST parameters adjust - giga master */
-	rtl_writephy(tp, 0x1f, 0x0a43);
-	rtl_writephy(tp, 0x13, 0x809b);
-	rtl_w0w1_phy(tp, 0x14, 0x8000, 0xf800);
-	rtl_writephy(tp, 0x13, 0x80a2);
-	rtl_w0w1_phy(tp, 0x14, 0x8000, 0xff00);
-	rtl_writephy(tp, 0x13, 0x80a4);
-	rtl_w0w1_phy(tp, 0x14, 0x8500, 0xff00);
-	rtl_writephy(tp, 0x13, 0x809c);
-	rtl_w0w1_phy(tp, 0x14, 0xbd00, 0xff00);
-	rtl_writephy(tp, 0x1f, 0x0000);
+	r8168g_phy_param(phydev, 0x809b, 0xf800, 0x8000);
+	r8168g_phy_param(phydev, 0x80a2, 0xff00, 0x8000);
+	r8168g_phy_param(phydev, 0x80a4, 0xff00, 0x8500);
+	r8168g_phy_param(phydev, 0x809c, 0xff00, 0xbd00);
 
 	/* CHN EST parameters adjust - giga slave */
-	rtl_writephy(tp, 0x1f, 0x0a43);
-	rtl_writephy(tp, 0x13, 0x80ad);
-	rtl_w0w1_phy(tp, 0x14, 0x7000, 0xf800);
-	rtl_writephy(tp, 0x13, 0x80b4);
-	rtl_w0w1_phy(tp, 0x14, 0x5000, 0xff00);
-	rtl_writephy(tp, 0x13, 0x80ac);
-	rtl_w0w1_phy(tp, 0x14, 0x4000, 0xff00);
-	rtl_writephy(tp, 0x1f, 0x0000);
+	r8168g_phy_param(phydev, 0x80ad, 0xf800, 0x7000);
+	r8168g_phy_param(phydev, 0x80b4, 0xff00, 0x5000);
+	r8168g_phy_param(phydev, 0x80ac, 0xff00, 0x4000);
 
 	/* CHN EST parameters adjust - fnet */
-	rtl_writephy(tp, 0x1f, 0x0a43);
-	rtl_writephy(tp, 0x13, 0x808e);
-	rtl_w0w1_phy(tp, 0x14, 0x1200, 0xff00);
-	rtl_writephy(tp, 0x13, 0x8090);
-	rtl_w0w1_phy(tp, 0x14, 0xe500, 0xff00);
-	rtl_writephy(tp, 0x13, 0x8092);
-	rtl_w0w1_phy(tp, 0x14, 0x9f00, 0xff00);
-	rtl_writephy(tp, 0x1f, 0x0000);
+	r8168g_phy_param(phydev, 0x808e, 0xff00, 0x1200);
+	r8168g_phy_param(phydev, 0x8090, 0xff00, 0xe500);
+	r8168g_phy_param(phydev, 0x8092, 0xff00, 0x9f00);
 
 	/* enable R-tune & PGA-retune function */
 	dout_tapbin = 0;
-	rtl_writephy(tp, 0x1f, 0x0a46);
-	data = rtl_readphy(tp, 0x13);
+	data = phy_read_paged(phydev, 0x0a46, 0x13);
 	data &= 3;
 	data <<= 2;
 	dout_tapbin |= data;
-	data = rtl_readphy(tp, 0x12);
+	data = phy_read_paged(phydev, 0x0a46, 0x12);
 	data &= 0xc000;
 	data >>= 14;
 	dout_tapbin |= data;
 	dout_tapbin = ~(dout_tapbin^0x08);
 	dout_tapbin <<= 12;
 	dout_tapbin &= 0xf000;
-	rtl_writephy(tp, 0x1f, 0x0a43);
-	rtl_writephy(tp, 0x13, 0x827a);
-	rtl_w0w1_phy(tp, 0x14, dout_tapbin, 0xf000);
-	rtl_writephy(tp, 0x13, 0x827b);
-	rtl_w0w1_phy(tp, 0x14, dout_tapbin, 0xf000);
-	rtl_writephy(tp, 0x13, 0x827c);
-	rtl_w0w1_phy(tp, 0x14, dout_tapbin, 0xf000);
-	rtl_writephy(tp, 0x13, 0x827d);
-	rtl_w0w1_phy(tp, 0x14, dout_tapbin, 0xf000);
-
-	rtl_writephy(tp, 0x1f, 0x0a43);
-	rtl_writephy(tp, 0x13, 0x0811);
-	rtl_w0w1_phy(tp, 0x14, 0x0800, 0x0000);
-	rtl_writephy(tp, 0x1f, 0x0a42);
-	rtl_w0w1_phy(tp, 0x16, 0x0002, 0x0000);
-	rtl_writephy(tp, 0x1f, 0x0000);
+
+	r8168g_phy_param(phydev, 0x827a, 0xf000, dout_tapbin);
+	r8168g_phy_param(phydev, 0x827b, 0xf000, dout_tapbin);
+	r8168g_phy_param(phydev, 0x827c, 0xf000, dout_tapbin);
+	r8168g_phy_param(phydev, 0x827d, 0xf000, dout_tapbin);
+	r8168g_phy_param(phydev, 0x0811, 0x0000, 0x0800);
+	phy_modify_paged(phydev, 0x0a42, 0x16, 0x0000, 0x0002);
 
 	/* enable GPHY 10M */
 	phy_modify_paged(tp->phydev, 0x0a44, 0x11, 0, BIT(11));
@@ -3369,22 +3402,13 @@
 	/* SAR ADC performance */
 	phy_modify_paged(tp->phydev, 0x0bca, 0x17, BIT(12) | BIT(13), BIT(14));
 
-	rtl_writephy(tp, 0x1f, 0x0a43);
-	rtl_writephy(tp, 0x13, 0x803f);
-	rtl_w0w1_phy(tp, 0x14, 0x0000, 0x3000);
-	rtl_writephy(tp, 0x13, 0x8047);
-	rtl_w0w1_phy(tp, 0x14, 0x0000, 0x3000);
-	rtl_writephy(tp, 0x13, 0x804f);
-	rtl_w0w1_phy(tp, 0x14, 0x0000, 0x3000);
-	rtl_writephy(tp, 0x13, 0x8057);
-	rtl_w0w1_phy(tp, 0x14, 0x0000, 0x3000);
-	rtl_writephy(tp, 0x13, 0x805f);
-	rtl_w0w1_phy(tp, 0x14, 0x0000, 0x3000);
-	rtl_writephy(tp, 0x13, 0x8067);
-	rtl_w0w1_phy(tp, 0x14, 0x0000, 0x3000);
-	rtl_writephy(tp, 0x13, 0x806f);
-	rtl_w0w1_phy(tp, 0x14, 0x0000, 0x3000);
-	rtl_writephy(tp, 0x1f, 0x0000);
+	r8168g_phy_param(phydev, 0x803f, 0x3000, 0x0000);
+	r8168g_phy_param(phydev, 0x8047, 0x3000, 0x0000);
+	r8168g_phy_param(phydev, 0x804f, 0x3000, 0x0000);
+	r8168g_phy_param(phydev, 0x8057, 0x3000, 0x0000);
+	r8168g_phy_param(phydev, 0x805f, 0x3000, 0x0000);
+	r8168g_phy_param(phydev, 0x8067, 0x3000, 0x0000);
+	r8168g_phy_param(phydev, 0x806f, 0x3000, 0x0000);
 
 	/* disable phy pfm mode */
 	phy_modify_paged(tp->phydev, 0x0a44, 0x11, BIT(7), 0);
@@ -3397,24 +3421,18 @@
 static void rtl8168h_2_hw_phy_config(struct rtl8169_private *tp)
 {
 	u16 ioffset_p3, ioffset_p2, ioffset_p1, ioffset_p0;
+	struct phy_device *phydev = tp->phydev;
 	u16 rlen;
 	u32 data;
 
 	rtl_apply_firmware(tp);
 
 	/* CHIN EST parameter update */
-	rtl_writephy(tp, 0x1f, 0x0a43);
-	rtl_writephy(tp, 0x13, 0x808a);
-	rtl_w0w1_phy(tp, 0x14, 0x000a, 0x003f);
-	rtl_writephy(tp, 0x1f, 0x0000);
+	r8168g_phy_param(phydev, 0x808a, 0x003f, 0x000a);
 
 	/* enable R-tune & PGA-retune function */
-	rtl_writephy(tp, 0x1f, 0x0a43);
-	rtl_writephy(tp, 0x13, 0x0811);
-	rtl_w0w1_phy(tp, 0x14, 0x0800, 0x0000);
-	rtl_writephy(tp, 0x1f, 0x0a42);
-	rtl_w0w1_phy(tp, 0x16, 0x0002, 0x0000);
-	rtl_writephy(tp, 0x1f, 0x0000);
+	r8168g_phy_param(phydev, 0x0811, 0x0000, 0x0800);
+	phy_modify_paged(phydev, 0x0a42, 0x16, 0x0000, 0x0002);
 
 	/* enable GPHY 10M */
 	phy_modify_paged(tp->phydev, 0x0a44, 0x11, 0, BIT(11));
@@ -3434,26 +3452,20 @@
 	data = (ioffset_p3<<12)|(ioffset_p2<<8)|(ioffset_p1<<4)|(ioffset_p0);
 
 	if ((ioffset_p3 != 0x0f) || (ioffset_p2 != 0x0f) ||
-	    (ioffset_p1 != 0x0f) || (ioffset_p0 != 0x0f)) {
-		rtl_writephy(tp, 0x1f, 0x0bcf);
-		rtl_writephy(tp, 0x16, data);
-		rtl_writephy(tp, 0x1f, 0x0000);
-	}
+	    (ioffset_p1 != 0x0f) || (ioffset_p0 != 0x0f))
+		phy_write_paged(phydev, 0x0bcf, 0x16, data);
 
 	/* Modify rlen (TX LPF corner frequency) level */
-	rtl_writephy(tp, 0x1f, 0x0bcd);
-	data = rtl_readphy(tp, 0x16);
+	data = phy_read_paged(phydev, 0x0bcd, 0x16);
 	data &= 0x000f;
 	rlen = 0;
 	if (data > 3)
 		rlen = data - 3;
 	data = rlen | (rlen<<4) | (rlen<<8) | (rlen<<12);
-	rtl_writephy(tp, 0x17, data);
-	rtl_writephy(tp, 0x1f, 0x0bcd);
-	rtl_writephy(tp, 0x1f, 0x0000);
+	phy_write_paged(phydev, 0x0bcd, 0x17, data);
 
 	/* disable phy pfm mode */
-	phy_modify_paged(tp->phydev, 0x0a44, 0x11, BIT(7), 0);
+	phy_modify_paged(phydev, 0x0a44, 0x11, BIT(7), 0);
 
 	rtl8168g_disable_aldps(tp);
 	rtl8168g_config_eee_phy(tp);
@@ -3462,22 +3474,21 @@
 
 static void rtl8168ep_1_hw_phy_config(struct rtl8169_private *tp)
 {
+	struct phy_device *phydev = tp->phydev;
+
 	/* Enable PHY auto speed down */
-	phy_modify_paged(tp->phydev, 0x0a44, 0x11, 0, BIT(3) | BIT(2));
+	phy_modify_paged(phydev, 0x0a44, 0x11, 0, BIT(3) | BIT(2));
 
 	rtl8168g_phy_adjust_10m_aldps(tp);
 
 	/* Enable EEE auto-fallback function */
-	phy_modify_paged(tp->phydev, 0x0a4b, 0x11, 0, BIT(2));
+	phy_modify_paged(phydev, 0x0a4b, 0x11, 0, BIT(2));
 
 	/* Enable UC LPF tune function */
-	rtl_writephy(tp, 0x1f, 0x0a43);
-	rtl_writephy(tp, 0x13, 0x8012);
-	rtl_w0w1_phy(tp, 0x14, 0x8000, 0x0000);
-	rtl_writephy(tp, 0x1f, 0x0000);
+	r8168g_phy_param(phydev, 0x8012, 0x0000, 0x8000);
 
 	/* set rg_sel_sdm_rate */
-	phy_modify_paged(tp->phydev, 0x0c42, 0x11, BIT(13), BIT(14));
+	phy_modify_paged(phydev, 0x0c42, 0x11, BIT(13), BIT(14));
 
 	rtl8168g_disable_aldps(tp);
 	rtl8168g_config_eee_phy(tp);
@@ -3486,63 +3497,38 @@
 
 static void rtl8168ep_2_hw_phy_config(struct rtl8169_private *tp)
 {
+	struct phy_device *phydev = tp->phydev;
+
 	rtl8168g_phy_adjust_10m_aldps(tp);
 
 	/* Enable UC LPF tune function */
-	rtl_writephy(tp, 0x1f, 0x0a43);
-	rtl_writephy(tp, 0x13, 0x8012);
-	rtl_w0w1_phy(tp, 0x14, 0x8000, 0x0000);
-	rtl_writephy(tp, 0x1f, 0x0000);
+	r8168g_phy_param(phydev, 0x8012, 0x0000, 0x8000);
 
 	/* Set rg_sel_sdm_rate */
 	phy_modify_paged(tp->phydev, 0x0c42, 0x11, BIT(13), BIT(14));
 
 	/* Channel estimation parameters */
-	rtl_writephy(tp, 0x1f, 0x0a43);
-	rtl_writephy(tp, 0x13, 0x80f3);
-	rtl_w0w1_phy(tp, 0x14, 0x8b00, ~0x8bff);
-	rtl_writephy(tp, 0x13, 0x80f0);
-	rtl_w0w1_phy(tp, 0x14, 0x3a00, ~0x3aff);
-	rtl_writephy(tp, 0x13, 0x80ef);
-	rtl_w0w1_phy(tp, 0x14, 0x0500, ~0x05ff);
-	rtl_writephy(tp, 0x13, 0x80f6);
-	rtl_w0w1_phy(tp, 0x14, 0x6e00, ~0x6eff);
-	rtl_writephy(tp, 0x13, 0x80ec);
-	rtl_w0w1_phy(tp, 0x14, 0x6800, ~0x68ff);
-	rtl_writephy(tp, 0x13, 0x80ed);
-	rtl_w0w1_phy(tp, 0x14, 0x7c00, ~0x7cff);
-	rtl_writephy(tp, 0x13, 0x80f2);
-	rtl_w0w1_phy(tp, 0x14, 0xf400, ~0xf4ff);
-	rtl_writephy(tp, 0x13, 0x80f4);
-	rtl_w0w1_phy(tp, 0x14, 0x8500, ~0x85ff);
-	rtl_writephy(tp, 0x1f, 0x0a43);
-	rtl_writephy(tp, 0x13, 0x8110);
-	rtl_w0w1_phy(tp, 0x14, 0xa800, ~0xa8ff);
-	rtl_writephy(tp, 0x13, 0x810f);
-	rtl_w0w1_phy(tp, 0x14, 0x1d00, ~0x1dff);
-	rtl_writephy(tp, 0x13, 0x8111);
-	rtl_w0w1_phy(tp, 0x14, 0xf500, ~0xf5ff);
-	rtl_writephy(tp, 0x13, 0x8113);
-	rtl_w0w1_phy(tp, 0x14, 0x6100, ~0x61ff);
-	rtl_writephy(tp, 0x13, 0x8115);
-	rtl_w0w1_phy(tp, 0x14, 0x9200, ~0x92ff);
-	rtl_writephy(tp, 0x13, 0x810e);
-	rtl_w0w1_phy(tp, 0x14, 0x0400, ~0x04ff);
-	rtl_writephy(tp, 0x13, 0x810c);
-	rtl_w0w1_phy(tp, 0x14, 0x7c00, ~0x7cff);
-	rtl_writephy(tp, 0x13, 0x810b);
-	rtl_w0w1_phy(tp, 0x14, 0x5a00, ~0x5aff);
-	rtl_writephy(tp, 0x1f, 0x0a43);
-	rtl_writephy(tp, 0x13, 0x80d1);
-	rtl_w0w1_phy(tp, 0x14, 0xff00, ~0xffff);
-	rtl_writephy(tp, 0x13, 0x80cd);
-	rtl_w0w1_phy(tp, 0x14, 0x9e00, ~0x9eff);
-	rtl_writephy(tp, 0x13, 0x80d3);
-	rtl_w0w1_phy(tp, 0x14, 0x0e00, ~0x0eff);
-	rtl_writephy(tp, 0x13, 0x80d5);
-	rtl_w0w1_phy(tp, 0x14, 0xca00, ~0xcaff);
-	rtl_writephy(tp, 0x13, 0x80d7);
-	rtl_w0w1_phy(tp, 0x14, 0x8400, ~0x84ff);
+	r8168g_phy_param(phydev, 0x80f3, 0xff00, 0x8b00);
+	r8168g_phy_param(phydev, 0x80f0, 0xff00, 0x3a00);
+	r8168g_phy_param(phydev, 0x80ef, 0xff00, 0x0500);
+	r8168g_phy_param(phydev, 0x80f6, 0xff00, 0x6e00);
+	r8168g_phy_param(phydev, 0x80ec, 0xff00, 0x6800);
+	r8168g_phy_param(phydev, 0x80ed, 0xff00, 0x7c00);
+	r8168g_phy_param(phydev, 0x80f2, 0xff00, 0xf400);
+	r8168g_phy_param(phydev, 0x80f4, 0xff00, 0x8500);
+	r8168g_phy_param(phydev, 0x8110, 0xff00, 0xa800);
+	r8168g_phy_param(phydev, 0x810f, 0xff00, 0x1d00);
+	r8168g_phy_param(phydev, 0x8111, 0xff00, 0xf500);
+	r8168g_phy_param(phydev, 0x8113, 0xff00, 0x6100);
+	r8168g_phy_param(phydev, 0x8115, 0xff00, 0x9200);
+	r8168g_phy_param(phydev, 0x810e, 0xff00, 0x0400);
+	r8168g_phy_param(phydev, 0x810c, 0xff00, 0x7c00);
+	r8168g_phy_param(phydev, 0x810b, 0xff00, 0x5a00);
+	r8168g_phy_param(phydev, 0x80d1, 0xff00, 0xff00);
+	r8168g_phy_param(phydev, 0x80cd, 0xff00, 0x9e00);
+	r8168g_phy_param(phydev, 0x80d3, 0xff00, 0x0e00);
+	r8168g_phy_param(phydev, 0x80d5, 0xff00, 0xca00);
+	r8168g_phy_param(phydev, 0x80d7, 0xff00, 0x8400);
 
 	/* Force PWM-mode */
 	rtl_writephy(tp, 0x1f, 0x0bcd);
@@ -3561,6 +3547,46 @@
 	rtl_enable_eee(tp);
 }
 
+static void rtl8117_hw_phy_config(struct rtl8169_private *tp)
+{
+	struct phy_device *phydev = tp->phydev;
+
+	/* CHN EST parameters adjust - fnet */
+	r8168g_phy_param(phydev, 0x808e, 0xff00, 0x4800);
+	r8168g_phy_param(phydev, 0x8090, 0xff00, 0xcc00);
+	r8168g_phy_param(phydev, 0x8092, 0xff00, 0xb000);
+
+	r8168g_phy_param(phydev, 0x8088, 0xff00, 0x6000);
+	r8168g_phy_param(phydev, 0x808b, 0x3f00, 0x0b00);
+	r8168g_phy_param(phydev, 0x808d, 0x1f00, 0x0600);
+	r8168g_phy_param(phydev, 0x808c, 0xff00, 0xb000);
+	r8168g_phy_param(phydev, 0x80a0, 0xff00, 0x2800);
+	r8168g_phy_param(phydev, 0x80a2, 0xff00, 0x5000);
+	r8168g_phy_param(phydev, 0x809b, 0xf800, 0xb000);
+	r8168g_phy_param(phydev, 0x809a, 0xff00, 0x4b00);
+	r8168g_phy_param(phydev, 0x809d, 0x3f00, 0x0800);
+	r8168g_phy_param(phydev, 0x80a1, 0xff00, 0x7000);
+	r8168g_phy_param(phydev, 0x809f, 0x1f00, 0x0300);
+	r8168g_phy_param(phydev, 0x809e, 0xff00, 0x8800);
+	r8168g_phy_param(phydev, 0x80b2, 0xff00, 0x2200);
+	r8168g_phy_param(phydev, 0x80ad, 0xf800, 0x9800);
+	r8168g_phy_param(phydev, 0x80af, 0x3f00, 0x0800);
+	r8168g_phy_param(phydev, 0x80b3, 0xff00, 0x6f00);
+	r8168g_phy_param(phydev, 0x80b1, 0x1f00, 0x0300);
+	r8168g_phy_param(phydev, 0x80b0, 0xff00, 0x9300);
+
+	r8168g_phy_param(phydev, 0x8011, 0x0000, 0x0800);
+
+	/* enable GPHY 10M */
+	phy_modify_paged(tp->phydev, 0x0a44, 0x11, 0, BIT(11));
+
+	r8168g_phy_param(phydev, 0x8016, 0x0000, 0x0400);
+
+	rtl8168g_disable_aldps(tp);
+	rtl8168h_config_eee_phy(tp);
+	rtl_enable_eee(tp);
+}
+
 static void rtl8102e_hw_phy_config(struct rtl8169_private *tp)
 {
 	static const struct phy_reg phy_reg_init[] = {
@@ -3657,38 +3683,22 @@
 	phy_modify_paged(phydev, 0xad1, 0x15, 0x0000, 0x03ff);
 	phy_modify_paged(phydev, 0xad1, 0x16, 0x0000, 0x03ff);
 
-	phy_write(phydev, 0x1f, 0x0a43);
-	phy_write(phydev, 0x13, 0x80ea);
-	phy_modify(phydev, 0x14, 0xff00, 0xc400);
-	phy_write(phydev, 0x13, 0x80eb);
-	phy_modify(phydev, 0x14, 0x0700, 0x0300);
-	phy_write(phydev, 0x13, 0x80f8);
-	phy_modify(phydev, 0x14, 0xff00, 0x1c00);
-	phy_write(phydev, 0x13, 0x80f1);
-	phy_modify(phydev, 0x14, 0xff00, 0x3000);
-	phy_write(phydev, 0x13, 0x80fe);
-	phy_modify(phydev, 0x14, 0xff00, 0xa500);
-	phy_write(phydev, 0x13, 0x8102);
-	phy_modify(phydev, 0x14, 0xff00, 0x5000);
-	phy_write(phydev, 0x13, 0x8105);
-	phy_modify(phydev, 0x14, 0xff00, 0x3300);
-	phy_write(phydev, 0x13, 0x8100);
-	phy_modify(phydev, 0x14, 0xff00, 0x7000);
-	phy_write(phydev, 0x13, 0x8104);
-	phy_modify(phydev, 0x14, 0xff00, 0xf000);
-	phy_write(phydev, 0x13, 0x8106);
-	phy_modify(phydev, 0x14, 0xff00, 0x6500);
-	phy_write(phydev, 0x13, 0x80dc);
-	phy_modify(phydev, 0x14, 0xff00, 0xed00);
-	phy_write(phydev, 0x13, 0x80df);
-	phy_set_bits(phydev, 0x14, BIT(8));
-	phy_write(phydev, 0x13, 0x80e1);
-	phy_clear_bits(phydev, 0x14, BIT(8));
-	phy_write(phydev, 0x1f, 0x0000);
+	r8168g_phy_param(phydev, 0x80ea, 0xff00, 0xc400);
+	r8168g_phy_param(phydev, 0x80eb, 0x0700, 0x0300);
+	r8168g_phy_param(phydev, 0x80f8, 0xff00, 0x1c00);
+	r8168g_phy_param(phydev, 0x80f1, 0xff00, 0x3000);
+	r8168g_phy_param(phydev, 0x80fe, 0xff00, 0xa500);
+	r8168g_phy_param(phydev, 0x8102, 0xff00, 0x5000);
+	r8168g_phy_param(phydev, 0x8105, 0xff00, 0x3300);
+	r8168g_phy_param(phydev, 0x8100, 0xff00, 0x7000);
+	r8168g_phy_param(phydev, 0x8104, 0xff00, 0xf000);
+	r8168g_phy_param(phydev, 0x8106, 0xff00, 0x6500);
+	r8168g_phy_param(phydev, 0x80dc, 0xff00, 0xed00);
+	r8168g_phy_param(phydev, 0x80df, 0x0000, 0x0100);
+	r8168g_phy_param(phydev, 0x80e1, 0x0100, 0x0000);
 
 	phy_modify_paged(phydev, 0xbf0, 0x13, 0x003f, 0x0038);
-	phy_write_paged(phydev, 0xa43, 0x13, 0x819f);
-	phy_write_paged(phydev, 0xa43, 0x14, 0xd0b6);
+	r8168g_phy_param(phydev, 0x819f, 0xffff, 0xd0b6);
 
 	phy_write_paged(phydev, 0xbc3, 0x12, 0x5555);
 	phy_modify_paged(phydev, 0xbf0, 0x15, 0x0e00, 0x0a00);
@@ -3743,22 +3753,16 @@
 	phy_write(phydev, 0x14, 0x0002);
 	for (i = 0; i < 25; i++)
 		phy_write(phydev, 0x14, 0x0000);
-
-	phy_write(phydev, 0x13, 0x8257);
-	phy_write(phydev, 0x14, 0x020F);
-
-	phy_write(phydev, 0x13, 0x80EA);
-	phy_write(phydev, 0x14, 0x7843);
 	phy_write(phydev, 0x1f, 0x0000);
 
+	r8168g_phy_param(phydev, 0x8257, 0xffff, 0x020F);
+	r8168g_phy_param(phydev, 0x80ea, 0xffff, 0x7843);
+
 	rtl_apply_firmware(tp);
 
 	phy_modify_paged(phydev, 0xd06, 0x14, 0x0000, 0x2000);
 
-	phy_write(phydev, 0x1f, 0x0a43);
-	phy_write(phydev, 0x13, 0x81a2);
-	phy_set_bits(phydev, 0x14, BIT(8));
-	phy_write(phydev, 0x1f, 0x0000);
+	r8168g_phy_param(phydev, 0x81a2, 0x0000, 0x0100);
 
 	phy_modify_paged(phydev, 0xb54, 0x16, 0xff00, 0xdb00);
 	phy_modify_paged(phydev, 0xa45, 0x12, 0x0001, 0x0000);
@@ -3826,6 +3830,7 @@
 		[RTL_GIGA_MAC_VER_49] = rtl8168ep_1_hw_phy_config,
 		[RTL_GIGA_MAC_VER_50] = rtl8168ep_2_hw_phy_config,
 		[RTL_GIGA_MAC_VER_51] = rtl8168ep_2_hw_phy_config,
+		[RTL_GIGA_MAC_VER_52] = rtl8117_hw_phy_config,
 		[RTL_GIGA_MAC_VER_60] = rtl8125_1_hw_phy_config,
 		[RTL_GIGA_MAC_VER_61] = rtl8125_2_hw_phy_config,
 	};
@@ -3919,7 +3924,7 @@
 	case RTL_GIGA_MAC_VER_32:
 	case RTL_GIGA_MAC_VER_33:
 	case RTL_GIGA_MAC_VER_34:
-	case RTL_GIGA_MAC_VER_37 ... RTL_GIGA_MAC_VER_51:
+	case RTL_GIGA_MAC_VER_37 ... RTL_GIGA_MAC_VER_61:
 		RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) |
 			AcceptBroadcast | AcceptMulticast | AcceptMyPhys);
 		break;
@@ -3944,7 +3949,9 @@
 	}
 
 	switch (tp->mac_version) {
-	case RTL_GIGA_MAC_VER_25 ... RTL_GIGA_MAC_VER_33:
+	case RTL_GIGA_MAC_VER_25 ... RTL_GIGA_MAC_VER_26:
+	case RTL_GIGA_MAC_VER_29 ... RTL_GIGA_MAC_VER_30:
+	case RTL_GIGA_MAC_VER_32 ... RTL_GIGA_MAC_VER_33:
 	case RTL_GIGA_MAC_VER_37:
 	case RTL_GIGA_MAC_VER_39:
 	case RTL_GIGA_MAC_VER_43:
@@ -3955,6 +3962,7 @@
 	case RTL_GIGA_MAC_VER_48:
 	case RTL_GIGA_MAC_VER_50:
 	case RTL_GIGA_MAC_VER_51:
+	case RTL_GIGA_MAC_VER_52:
 	case RTL_GIGA_MAC_VER_60:
 	case RTL_GIGA_MAC_VER_61:
 		RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) & ~0x80);
@@ -3973,7 +3981,9 @@
 static void rtl_pll_power_up(struct rtl8169_private *tp)
 {
 	switch (tp->mac_version) {
-	case RTL_GIGA_MAC_VER_25 ... RTL_GIGA_MAC_VER_33:
+	case RTL_GIGA_MAC_VER_25 ... RTL_GIGA_MAC_VER_26:
+	case RTL_GIGA_MAC_VER_29 ... RTL_GIGA_MAC_VER_30:
+	case RTL_GIGA_MAC_VER_32 ... RTL_GIGA_MAC_VER_33:
 	case RTL_GIGA_MAC_VER_37:
 	case RTL_GIGA_MAC_VER_39:
 	case RTL_GIGA_MAC_VER_43:
@@ -3986,6 +3996,7 @@
 	case RTL_GIGA_MAC_VER_48:
 	case RTL_GIGA_MAC_VER_50:
 	case RTL_GIGA_MAC_VER_51:
+	case RTL_GIGA_MAC_VER_52:
 	case RTL_GIGA_MAC_VER_60:
 	case RTL_GIGA_MAC_VER_61:
 		RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) | 0xc0);
@@ -4017,7 +4028,7 @@
 	case RTL_GIGA_MAC_VER_38:
 		RTL_W32(tp, RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST);
 		break;
-	case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_51:
+	case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_52:
 		RTL_W32(tp, RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST | RX_EARLY_OFF);
 		break;
 	case RTL_GIGA_MAC_VER_60 ... RTL_GIGA_MAC_VER_61:
@@ -4039,14 +4050,12 @@
 {
 	RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0);
 	RTL_W8(tp, Config4, RTL_R8(tp, Config4) | Jumbo_En1);
-	rtl_tx_performance_tweak(tp, PCI_EXP_DEVCTL_READRQ_512B);
 }
 
 static void r8168c_hw_jumbo_disable(struct rtl8169_private *tp)
 {
 	RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0);
 	RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~Jumbo_En1);
-	rtl_tx_performance_tweak(tp, PCI_EXP_DEVCTL_READRQ_4096B);
 }
 
 static void r8168dp_hw_jumbo_enable(struct rtl8169_private *tp)
@@ -4061,104 +4070,80 @@
 
 static void r8168e_hw_jumbo_enable(struct rtl8169_private *tp)
 {
-	RTL_W8(tp, MaxTxPacketSize, 0x3f);
+	RTL_W8(tp, MaxTxPacketSize, 0x24);
 	RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0);
 	RTL_W8(tp, Config4, RTL_R8(tp, Config4) | 0x01);
-	rtl_tx_performance_tweak(tp, PCI_EXP_DEVCTL_READRQ_512B);
 }
 
 static void r8168e_hw_jumbo_disable(struct rtl8169_private *tp)
 {
-	RTL_W8(tp, MaxTxPacketSize, 0x0c);
+	RTL_W8(tp, MaxTxPacketSize, 0x3f);
 	RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0);
 	RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~0x01);
-	rtl_tx_performance_tweak(tp, PCI_EXP_DEVCTL_READRQ_4096B);
-}
-
-static void r8168b_0_hw_jumbo_enable(struct rtl8169_private *tp)
-{
-	rtl_tx_performance_tweak(tp,
-		PCI_EXP_DEVCTL_READRQ_512B | PCI_EXP_DEVCTL_NOSNOOP_EN);
-}
-
-static void r8168b_0_hw_jumbo_disable(struct rtl8169_private *tp)
-{
-	rtl_tx_performance_tweak(tp,
-		PCI_EXP_DEVCTL_READRQ_4096B | PCI_EXP_DEVCTL_NOSNOOP_EN);
 }
 
 static void r8168b_1_hw_jumbo_enable(struct rtl8169_private *tp)
 {
-	r8168b_0_hw_jumbo_enable(tp);
-
 	RTL_W8(tp, Config4, RTL_R8(tp, Config4) | (1 << 0));
 }
 
 static void r8168b_1_hw_jumbo_disable(struct rtl8169_private *tp)
 {
-	r8168b_0_hw_jumbo_disable(tp);
-
 	RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~(1 << 0));
 }
 
-static void rtl_hw_jumbo_enable(struct rtl8169_private *tp)
+static void rtl_jumbo_config(struct rtl8169_private *tp)
 {
-	rtl_unlock_config_regs(tp);
-	switch (tp->mac_version) {
-	case RTL_GIGA_MAC_VER_11:
-		r8168b_0_hw_jumbo_enable(tp);
-		break;
-	case RTL_GIGA_MAC_VER_12:
-	case RTL_GIGA_MAC_VER_17:
-		r8168b_1_hw_jumbo_enable(tp);
-		break;
-	case RTL_GIGA_MAC_VER_18 ... RTL_GIGA_MAC_VER_26:
-		r8168c_hw_jumbo_enable(tp);
-		break;
-	case RTL_GIGA_MAC_VER_27 ... RTL_GIGA_MAC_VER_28:
-		r8168dp_hw_jumbo_enable(tp);
-		break;
-	case RTL_GIGA_MAC_VER_31 ... RTL_GIGA_MAC_VER_34:
-		r8168e_hw_jumbo_enable(tp);
-		break;
-	default:
-		break;
-	}
-	rtl_lock_config_regs(tp);
-}
+	bool jumbo = tp->dev->mtu > ETH_DATA_LEN;
+	int readrq = 4096;
 
-static void rtl_hw_jumbo_disable(struct rtl8169_private *tp)
-{
 	rtl_unlock_config_regs(tp);
 	switch (tp->mac_version) {
-	case RTL_GIGA_MAC_VER_11:
-		r8168b_0_hw_jumbo_disable(tp);
-		break;
 	case RTL_GIGA_MAC_VER_12:
 	case RTL_GIGA_MAC_VER_17:
-		r8168b_1_hw_jumbo_disable(tp);
+		if (jumbo) {
+			readrq = 512;
+			r8168b_1_hw_jumbo_enable(tp);
+		} else {
+			r8168b_1_hw_jumbo_disable(tp);
+		}
 		break;
 	case RTL_GIGA_MAC_VER_18 ... RTL_GIGA_MAC_VER_26:
-		r8168c_hw_jumbo_disable(tp);
+		if (jumbo) {
+			readrq = 512;
+			r8168c_hw_jumbo_enable(tp);
+		} else {
+			r8168c_hw_jumbo_disable(tp);
+		}
 		break;
 	case RTL_GIGA_MAC_VER_27 ... RTL_GIGA_MAC_VER_28:
-		r8168dp_hw_jumbo_disable(tp);
+		if (jumbo)
+			r8168dp_hw_jumbo_enable(tp);
+		else
+			r8168dp_hw_jumbo_disable(tp);
 		break;
-	case RTL_GIGA_MAC_VER_31 ... RTL_GIGA_MAC_VER_34:
-		r8168e_hw_jumbo_disable(tp);
+	case RTL_GIGA_MAC_VER_31 ... RTL_GIGA_MAC_VER_33:
+		if (jumbo) {
+			pcie_set_readrq(tp->pci_dev, 512);
+			r8168e_hw_jumbo_enable(tp);
+		} else {
+			r8168e_hw_jumbo_disable(tp);
+		}
 		break;
 	default:
 		break;
 	}
 	rtl_lock_config_regs(tp);
-}
 
-static void rtl_jumbo_config(struct rtl8169_private *tp, int mtu)
-{
-	if (mtu > ETH_DATA_LEN)
-		rtl_hw_jumbo_enable(tp);
-	else
-		rtl_hw_jumbo_disable(tp);
+	if (pci_is_pcie(tp->pci_dev) && tp->supports_gmii)
+		pcie_set_readrq(tp->pci_dev, readrq);
+
+	/* Chip doesn't support pause in jumbo mode */
+	linkmode_mod_bit(ETHTOOL_LINK_MODE_Pause_BIT,
+			 tp->phydev->advertising, !jumbo);
+	linkmode_mod_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
+			 tp->phydev->advertising, !jumbo);
+	phy_start_aneg(tp->phydev);
 }
 
 DECLARE_RTL_COND(rtl_chipcmd_cond)
@@ -4229,7 +4214,7 @@
 		rtl_udelay_loop_wait_low(tp, &rtl_npq_cond, 20, 42*42);
 		break;
 	case RTL_GIGA_MAC_VER_34 ... RTL_GIGA_MAC_VER_38:
-	case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_51:
+	case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_52:
 		RTL_W8(tp, ChipCmd, RTL_R8(tp, ChipCmd) | StopReq);
 		rtl_udelay_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 666);
 		break;
@@ -4301,6 +4286,8 @@
 		/* Unconditionally log net taps. */
 		netif_notice(tp, link, dev, "Promiscuous mode enabled\n");
 		rx_mode |= AcceptAllPhys;
+	} else if (!(dev->flags & IFF_MULTICAST)) {
+		rx_mode &= ~AcceptMulticast;
 	} else if (netdev_mc_count(dev) > MC_FILTER_LIMIT ||
 		   dev->flags & IFF_ALLMULTI ||
 		   tp->mac_version == RTL_GIGA_MAC_VER_35) {
@@ -4557,18 +4544,12 @@
 	rtl_set_def_aspm_entry_latency(tp);
 
 	rtl_disable_clock_request(tp);
-
-	if (tp->dev->mtu <= ETH_DATA_LEN)
-		rtl_tx_performance_tweak(tp, PCI_EXP_DEVCTL_READRQ_4096B);
 }
 
 static void rtl_hw_start_8168dp(struct rtl8169_private *tp)
 {
 	rtl_set_def_aspm_entry_latency(tp);
 
-	if (tp->dev->mtu <= ETH_DATA_LEN)
-		rtl_tx_performance_tweak(tp, PCI_EXP_DEVCTL_READRQ_4096B);
-
 	rtl_disable_clock_request(tp);
 }
 
@@ -4583,8 +4564,6 @@
 
 	rtl_set_def_aspm_entry_latency(tp);
 
-	rtl_tx_performance_tweak(tp, PCI_EXP_DEVCTL_READRQ_4096B);
-
 	rtl_ephy_init(tp, e_info_8168d_4);
 
 	rtl_enable_clock_request(tp);
@@ -4659,8 +4638,6 @@
 {
 	rtl_set_def_aspm_entry_latency(tp);
 
-	rtl_tx_performance_tweak(tp, PCI_EXP_DEVCTL_READRQ_4096B);
-
 	rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000);
 	rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000);
 	rtl_set_fifo_size(tp, 0x10, 0x10, 0x02, 0x06);
@@ -4687,7 +4664,7 @@
 		{ 0x08, 0x0001,	0x0002 },
 		{ 0x09, 0x0000,	0x0080 },
 		{ 0x19, 0x0000,	0x0224 },
-		{ 0x00, 0x0000,	0x0004 },
+		{ 0x00, 0x0000,	0x0008 },
 		{ 0x0c, 0x3df0,	0x0200 },
 	};
 
@@ -4704,7 +4681,7 @@
 		{ 0x06, 0x00c0,	0x0020 },
 		{ 0x0f, 0xffff,	0x5200 },
 		{ 0x19, 0x0000,	0x0224 },
-		{ 0x00, 0x0000,	0x0004 },
+		{ 0x00, 0x0000,	0x0008 },
 		{ 0x0c, 0x3df0,	0x0200 },
 	};
 
@@ -4723,8 +4700,6 @@
 
 	rtl_set_def_aspm_entry_latency(tp);
 
-	rtl_tx_performance_tweak(tp, PCI_EXP_DEVCTL_READRQ_4096B);
-
 	rtl_reset_packet_filter(tp);
 	rtl_eri_write(tp, 0x2f8, ERIAR_MASK_0011, 0x1d8f);
 
@@ -4739,6 +4714,7 @@
 	rtl_eri_clear_bits(tp, 0x1b0, ERIAR_MASK_0011, BIT(12));
 
 	rtl_pcie_state_l2l3_disable(tp);
+	rtl_hw_aspm_clkreq_enable(tp, true);
 }
 
 static void rtl_hw_start_8168g_1(struct rtl8169_private *tp)
@@ -4961,8 +4937,6 @@
 
 	rtl_set_def_aspm_entry_latency(tp);
 
-	rtl_tx_performance_tweak(tp, PCI_EXP_DEVCTL_READRQ_4096B);
-
 	rtl_reset_packet_filter(tp);
 
 	rtl_eri_set_bits(tp, 0xdc, ERIAR_MASK_1111, BIT(4));
@@ -5020,8 +4994,6 @@
 
 	rtl_set_def_aspm_entry_latency(tp);
 
-	rtl_tx_performance_tweak(tp, PCI_EXP_DEVCTL_READRQ_4096B);
-
 	rtl_reset_packet_filter(tp);
 
 	rtl_eri_set_bits(tp, 0xd4, ERIAR_MASK_1111, 0x1f80);
@@ -5106,6 +5078,71 @@
 	rtl_hw_aspm_clkreq_enable(tp, true);
 }
 
+static void rtl_hw_start_8117(struct rtl8169_private *tp)
+{
+	static const struct ephy_info e_info_8117[] = {
+		{ 0x19, 0x0040,	0x1100 },
+		{ 0x59, 0x0040,	0x1100 },
+	};
+	int rg_saw_cnt;
+
+	rtl8168ep_stop_cmac(tp);
+
+	/* disable aspm and clock request before access ephy */
+	rtl_hw_aspm_clkreq_enable(tp, false);
+	rtl_ephy_init(tp, e_info_8117);
+
+	rtl_set_fifo_size(tp, 0x08, 0x10, 0x02, 0x06);
+	rtl8168g_set_pause_thresholds(tp, 0x2f, 0x5f);
+
+	rtl_set_def_aspm_entry_latency(tp);
+
+	rtl_reset_packet_filter(tp);
+
+	rtl_eri_set_bits(tp, 0xd4, ERIAR_MASK_1111, 0x1f90);
+
+	rtl_eri_write(tp, 0x5f0, ERIAR_MASK_0011, 0x4f87);
+
+	RTL_W32(tp, MISC, RTL_R32(tp, MISC) & ~RXDV_GATED_EN);
+
+	rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000);
+	rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000);
+
+	rtl8168_config_eee_mac(tp);
+
+	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~PFM_EN);
+	RTL_W8(tp, MISC_1, RTL_R8(tp, MISC_1) & ~PFM_D3COLD_EN);
+
+	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~TX_10M_PS_EN);
+
+	rtl_eri_clear_bits(tp, 0x1b0, ERIAR_MASK_0011, BIT(12));
+
+	rtl_pcie_state_l2l3_disable(tp);
+
+	rg_saw_cnt = phy_read_paged(tp->phydev, 0x0c42, 0x13) & 0x3fff;
+	if (rg_saw_cnt > 0) {
+		u16 sw_cnt_1ms_ini;
+
+		sw_cnt_1ms_ini = (16000000 / rg_saw_cnt) & 0x0fff;
+		r8168_mac_ocp_modify(tp, 0xd412, 0x0fff, sw_cnt_1ms_ini);
+	}
+
+	r8168_mac_ocp_modify(tp, 0xe056, 0x00f0, 0x0070);
+	r8168_mac_ocp_write(tp, 0xea80, 0x0003);
+	r8168_mac_ocp_modify(tp, 0xe052, 0x0000, 0x0009);
+	r8168_mac_ocp_modify(tp, 0xd420, 0x0fff, 0x047f);
+
+	r8168_mac_ocp_write(tp, 0xe63e, 0x0001);
+	r8168_mac_ocp_write(tp, 0xe63e, 0x0000);
+	r8168_mac_ocp_write(tp, 0xc094, 0x0000);
+	r8168_mac_ocp_write(tp, 0xc09e, 0x0000);
+
+	/* firmware is for MAC only */
+	rtl_apply_firmware(tp);
+
+	rtl_hw_aspm_clkreq_enable(tp, true);
+}
+
 static void rtl_hw_start_8102e_1(struct rtl8169_private *tp)
 {
 	static const struct ephy_info e_info_8102e_1[] = {
@@ -5124,8 +5161,6 @@
 
 	RTL_W8(tp, DBG_REG, FIX_NAK_1);
 
-	rtl_tx_performance_tweak(tp, PCI_EXP_DEVCTL_READRQ_4096B);
-
 	RTL_W8(tp, Config1,
 	       LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable);
 	RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en);
@@ -5141,8 +5176,6 @@
 {
 	rtl_set_def_aspm_entry_latency(tp);
 
-	rtl_tx_performance_tweak(tp, PCI_EXP_DEVCTL_READRQ_4096B);
-
 	RTL_W8(tp, Config1, MEMMAP | IOMAP | VPD | PMEnable);
 	RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en);
 }
@@ -5203,8 +5236,6 @@
 
 	rtl_ephy_init(tp, e_info_8402);
 
-	rtl_tx_performance_tweak(tp, PCI_EXP_DEVCTL_READRQ_4096B);
-
 	rtl_set_fifo_size(tp, 0x00, 0x00, 0x02, 0x06);
 	rtl_reset_packet_filter(tp);
 	rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000);
@@ -5226,7 +5257,6 @@
 	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~PFM_EN);
 
 	rtl_pcie_state_l2l3_disable(tp);
-	rtl_hw_aspm_clkreq_enable(tp, true);
 }
 
 DECLARE_RTL_COND(rtl_mac_ocp_e00e_cond)
@@ -5399,6 +5429,7 @@
 		[RTL_GIGA_MAC_VER_49] = rtl_hw_start_8168ep_1,
 		[RTL_GIGA_MAC_VER_50] = rtl_hw_start_8168ep_2,
 		[RTL_GIGA_MAC_VER_51] = rtl_hw_start_8168ep_3,
+		[RTL_GIGA_MAC_VER_52] = rtl_hw_start_8117,
 		[RTL_GIGA_MAC_VER_60] = rtl_hw_start_8125_1,
 		[RTL_GIGA_MAC_VER_61] = rtl_hw_start_8125_2,
 	};
@@ -5420,10 +5451,18 @@
 
 static void rtl_hw_start_8168(struct rtl8169_private *tp)
 {
-	if (tp->mac_version == RTL_GIGA_MAC_VER_13 ||
-	    tp->mac_version == RTL_GIGA_MAC_VER_16)
+	switch (tp->mac_version) {
+	case RTL_GIGA_MAC_VER_11:
+	case RTL_GIGA_MAC_VER_12:
+	case RTL_GIGA_MAC_VER_13:
+	case RTL_GIGA_MAC_VER_16:
+	case RTL_GIGA_MAC_VER_17:
 		pcie_capability_set_word(tp->pci_dev, PCI_EXP_DEVCTL,
 					 PCI_EXP_DEVCTL_NOSNOOP_EN);
+		break;
+	default:
+		break;
+	}
 
 	if (rtl_is_8168evl_up(tp))
 		RTL_W8(tp, MaxTxPacketSize, EarlySize);
@@ -5480,7 +5519,7 @@
 	rtl_set_rx_tx_desc_registers(tp);
 	rtl_lock_config_regs(tp);
 
-	rtl_jumbo_config(tp, tp->dev->mtu);
+	rtl_jumbo_config(tp);
 
 	/* Initially a 10 us delay. Turned it into a PCI commit. - FR */
 	RTL_R16(tp, CPlusCmd);
@@ -5495,10 +5534,13 @@
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
 
-	rtl_jumbo_config(tp, new_mtu);
-
 	dev->mtu = new_mtu;
 	netdev_update_features(dev);
+	rtl_jumbo_config(tp);
+
+	/* Reportedly at least Asus X453MA truncates packets otherwise */
+	if (tp->mac_version == RTL_GIGA_MAC_VER_37)
+		rtl_init_rxcfg(tp);
 
 	return 0;
 }
@@ -5828,7 +5870,8 @@
 		opts[1] |= transport_offset << TCPHO_SHIFT;
 	} else {
 		if (unlikely(rtl_test_hw_pad_bug(tp, skb)))
-			return !eth_skb_pad(skb);
+			/* eth_skb_pad would free the skb on error */
+			return !__skb_put_padto(skb, ETH_ZLEN, false);
 	}
 
 	return true;
@@ -6054,7 +6097,7 @@
 		struct ring_info *tx_skb = tp->tx_skb + entry;
 		u32 status;
 
-		status = le32_to_cpu(tp->TxDescArray[entry].opts1);
+		status = le32_to_cpu(READ_ONCE(tp->TxDescArray[entry].opts1));
 		if (status & DescOwn)
 			break;
 
@@ -6137,7 +6180,7 @@
 		struct RxDesc *desc = tp->RxDescArray + entry;
 		u32 status;
 
-		status = le32_to_cpu(desc->opts1);
+		status = le32_to_cpu(READ_ONCE(desc->opts1));
 		if (status & DescOwn)
 			break;
 
@@ -6231,7 +6274,9 @@
 	    !(status & tp->irq_mask))
 		return IRQ_NONE;
 
-	if (unlikely(status & SYSErr)) {
+	/* At least RTL8168fp may unexpectedly set the SYSErr bit */
+	if (unlikely(status & SYSErr &&
+	    tp->mac_version <= RTL_GIGA_MAC_VER_06)) {
 		rtl8169_pcierr_interrupt(tp->dev);
 		goto out;
 	}
@@ -6242,12 +6287,11 @@
 	if (unlikely(status & RxFIFOOver &&
 	    tp->mac_version == RTL_GIGA_MAC_VER_11)) {
 		netif_stop_queue(tp->dev);
-		/* XXX - Hack alert. See rtl_task(). */
-		set_bit(RTL_FLAG_TASK_RESET_PENDING, tp->wk.flags);
+		rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
 	}
 
 	rtl_irq_disable(tp);
-	napi_schedule_irqoff(&tp->napi);
+	napi_schedule(&tp->napi);
 out:
 	rtl_ack_events(tp, status);
 
@@ -6317,12 +6361,17 @@
 static void r8169_phylink_handler(struct net_device *ndev)
 {
 	struct rtl8169_private *tp = netdev_priv(ndev);
+	struct device *d = tp_to_dev(tp);
 
 	if (netif_carrier_ok(ndev)) {
 		rtl_link_chg_patch(tp);
-		pm_request_resume(&tp->pci_dev->dev);
+		pm_request_resume(d);
+		netif_wake_queue(tp->dev);
 	} else {
-		pm_runtime_idle(&tp->pci_dev->dev);
+		/* In few cases rx is broken after link-down otherwise */
+		if (rtl_is_8125(tp))
+			rtl_reset_work(tp);
+		pm_runtime_idle(d);
 	}
 
 	if (net_ratelimit())
@@ -6346,8 +6395,6 @@
 	if (!tp->supports_gmii)
 		phy_set_max_speed(phydev, SPEED_100);
 
-	phy_support_asym_pause(phydev);
-
 	phy_attached_info(phydev);
 
 	return 0;
@@ -6399,9 +6446,9 @@
 
 	cancel_work_sync(&tp->wk.work);
 
-	phy_disconnect(tp->phydev);
+	free_irq(pci_irq_vector(pdev, 0), tp);
 
-	pci_free_irq(pdev, 0, tp);
+	phy_disconnect(tp->phydev);
 
 	dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray,
 			  tp->RxPhyAddr);
@@ -6452,8 +6499,8 @@
 
 	rtl_request_firmware(tp);
 
-	retval = pci_request_irq(pdev, 0, rtl8169_interrupt, NULL, tp,
-				 dev->name);
+	retval = request_irq(pci_irq_vector(pdev, 0), rtl8169_interrupt,
+			     IRQF_SHARED, dev->name, tp);
 	if (retval < 0)
 		goto err_release_fw_2;
 
@@ -6486,7 +6533,7 @@
 	return retval;
 
 err_free_irq:
-	pci_free_irq(pdev, 0, tp);
+	free_irq(pci_irq_vector(pdev, 0), tp);
 err_release_fw_2:
 	rtl_release_firmware(tp);
 	rtl8169_rx_clear(tp);
@@ -6800,7 +6847,7 @@
 		RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~MSIEnable);
 		rtl_lock_config_regs(tp);
 		/* fall through */
-	case RTL_GIGA_MAC_VER_07 ... RTL_GIGA_MAC_VER_24:
+	case RTL_GIGA_MAC_VER_07 ... RTL_GIGA_MAC_VER_17:
 		flags = PCI_IRQ_LEGACY;
 		break;
 	default:
@@ -6870,6 +6917,15 @@
 	struct mii_bus *new_bus;
 	int ret;
 
+	/* On some boards with this chip version the BIOS is buggy and misses
+	 * to reset the PHY page selector. This results in the PHY ID read
+	 * accessing registers on a different page, returning a more or
+	 * less random value. Fix this by resetting the page selector first.
+	 */
+	if (tp->mac_version == RTL_GIGA_MAC_VER_25 ||
+	    tp->mac_version == RTL_GIGA_MAC_VER_26)
+		r8169_mdio_write(tp, 0x1f, 0);
+
 	new_bus = devm_mdiobus_alloc(&pdev->dev);
 	if (!new_bus)
 		return -ENOMEM;
@@ -6878,7 +6934,8 @@
 	new_bus->priv = tp;
 	new_bus->parent = &pdev->dev;
 	new_bus->irq[0] = PHY_IGNORE_INTERRUPT;
-	snprintf(new_bus->id, MII_BUS_ID_SIZE, "r8169-%x", pci_dev_id(pdev));
+	snprintf(new_bus->id, MII_BUS_ID_SIZE, "r8169-%x-%x",
+		 pci_domain_nr(pdev->bus), pci_dev_id(pdev));
 
 	new_bus->read = r8169_mdio_read_reg;
 	new_bus->write = r8169_mdio_write_reg;
@@ -6891,6 +6948,13 @@
 	if (!tp->phydev) {
 		mdiobus_unregister(new_bus);
 		return -ENODEV;
+	} else if (!tp->phydev->drv) {
+		/* Most chip versions fail with the genphy driver.
+		 * Therefore ensure that the dedicated PHY driver is loaded.
+		 */
+		dev_err(&pdev->dev, "realtek.ko not loaded, maybe it needs to be added to initramfs?\n");
+		mdiobus_unregister(new_bus);
+		return -EUNATCH;
 	}
 
 	/* PHY will be woken up in rtl_open() */
@@ -6953,7 +7017,7 @@
 static void rtl_hw_initialize(struct rtl8169_private *tp)
 {
 	switch (tp->mac_version) {
-	case RTL_GIGA_MAC_VER_49 ... RTL_GIGA_MAC_VER_51:
+	case RTL_GIGA_MAC_VER_49 ... RTL_GIGA_MAC_VER_52:
 		rtl8168ep_stop_cmac(tp);
 		/* fall through */
 	case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_48:
@@ -7063,6 +7127,7 @@
 	tp->pci_dev = pdev;
 	tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT);
 	tp->supports_gmii = ent->driver_data == RTL_CFG_NO_GBIT ? 0 : 1;
+	tp->eee_adv = -1;
 
 	/* Get the *optional* external "ether_clk" used on some boards */
 	rc = rtl_get_ether_clk(tp);
@@ -7072,8 +7137,7 @@
 	/* Disable ASPM completely as that cause random device stop working
 	 * problems as well as full system hangs for some PCIe devices users.
 	 */
-	rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S |
-					  PCIE_LINK_STATE_L1);
+	rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1_1);
 	tp->aspm_manageable = !rc;
 
 	/* enable device (incl. PCI PM wakeup and hotplug setup) */
@@ -7147,12 +7211,10 @@
 
 	netif_napi_add(dev, &tp->napi, rtl8169_poll, NAPI_POLL_WEIGHT);
 
-	dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
-		NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_TX |
-		NETIF_F_HW_VLAN_CTAG_RX;
-	dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
-		NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_TX |
-		NETIF_F_HW_VLAN_CTAG_RX;
+	dev->features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
+			 NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
+	dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
+			   NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
 	dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO |
 		NETIF_F_HIGHDMA;
 	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
@@ -7170,25 +7232,25 @@
 		dev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_RX;
 
 	if (rtl_chip_supports_csum_v2(tp)) {
-		dev->hw_features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6;
-		dev->features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6;
+		dev->hw_features |= NETIF_F_IPV6_CSUM;
+		dev->features |= NETIF_F_IPV6_CSUM;
+	}
+
+	/* There has been a number of reports that using SG/TSO results in
+	 * tx timeouts. However for a lot of people SG/TSO works fine.
+	 * Therefore disable both features by default, but allow users to
+	 * enable them. Use at own risk!
+	 */
+	if (rtl_chip_supports_csum_v2(tp)) {
+		dev->hw_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6;
 		dev->gso_max_size = RTL_GSO_MAX_SIZE_V2;
 		dev->gso_max_segs = RTL_GSO_MAX_SEGS_V2;
 	} else {
+		dev->hw_features |= NETIF_F_SG | NETIF_F_TSO;
 		dev->gso_max_size = RTL_GSO_MAX_SIZE_V1;
 		dev->gso_max_segs = RTL_GSO_MAX_SEGS_V1;
 	}
 
-	/* RTL8168e-vl and one RTL8168c variant are known to have a
-	 * HW issue with TSO.
-	 */
-	if (tp->mac_version == RTL_GIGA_MAC_VER_34 ||
-	    tp->mac_version == RTL_GIGA_MAC_VER_22) {
-		dev->vlan_features &= ~(NETIF_F_ALL_TSO | NETIF_F_SG);
-		dev->hw_features &= ~(NETIF_F_ALL_TSO | NETIF_F_SG);
-		dev->features &= ~(NETIF_F_ALL_TSO | NETIF_F_SG);
-	}
-
 	dev->hw_features |= NETIF_F_RXALL;
 	dev->hw_features |= NETIF_F_RXFCS;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/renesas/ravb_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/renesas/ravb_main.c
@@ -736,14 +736,14 @@
 	ravb_write(ndev, ~(EIS_QFS | EIS_RESERVED), EIS);
 	if (eis & EIS_QFS) {
 		ris2 = ravb_read(ndev, RIS2);
-		ravb_write(ndev, ~(RIS2_QFF0 | RIS2_RFFF | RIS2_RESERVED),
+		ravb_write(ndev, ~(RIS2_QFF0 | RIS2_QFF1 | RIS2_RFFF | RIS2_RESERVED),
 			   RIS2);
 
 		/* Receive Descriptor Empty int */
 		if (ris2 & RIS2_QFF0)
 			priv->stats[RAVB_BE].rx_over_errors++;
 
-		    /* Receive Descriptor Empty int */
+		/* Receive Descriptor Empty int */
 		if (ris2 & RIS2_QFF1)
 			priv->stats[RAVB_NC].rx_over_errors++;
 
@@ -911,31 +911,23 @@
 	int q = napi - priv->napi;
 	int mask = BIT(q);
 	int quota = budget;
-	u32 ris0, tis;
+	bool unmask;
 
-	for (;;) {
-		tis = ravb_read(ndev, TIS);
-		ris0 = ravb_read(ndev, RIS0);
-		if (!((ris0 & mask) || (tis & mask)))
-			break;
-
-		/* Processing RX Descriptor Ring */
-		if (ris0 & mask) {
-			/* Clear RX interrupt */
-			ravb_write(ndev, ~(mask | RIS0_RESERVED), RIS0);
-			if (ravb_rx(ndev, &quota, q))
-				goto out;
-		}
-		/* Processing TX Descriptor Ring */
-		if (tis & mask) {
-			spin_lock_irqsave(&priv->lock, flags);
-			/* Clear TX interrupt */
-			ravb_write(ndev, ~(mask | TIS_RESERVED), TIS);
-			ravb_tx_free(ndev, q, true);
-			netif_wake_subqueue(ndev, q);
-			spin_unlock_irqrestore(&priv->lock, flags);
-		}
-	}
+	/* Processing RX Descriptor Ring */
+	/* Clear RX interrupt */
+	ravb_write(ndev, ~(mask | RIS0_RESERVED), RIS0);
+	unmask = !ravb_rx(ndev, &quota, q);
+
+	/* Processing RX Descriptor Ring */
+	spin_lock_irqsave(&priv->lock, flags);
+	/* Clear TX interrupt */
+	ravb_write(ndev, ~(mask | TIS_RESERVED), TIS);
+	ravb_tx_free(ndev, q, true);
+	netif_wake_subqueue(ndev, q);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	if (!unmask)
+		goto out;
 
 	napi_complete(napi);
 
@@ -1391,13 +1383,13 @@
 	if (priv->chip_id == RCAR_GEN2)
 		ravb_ptp_init(ndev, priv->pdev);
 
-	netif_tx_start_all_queues(ndev);
-
 	/* PHY control start */
 	error = ravb_phy_start(ndev);
 	if (error)
 		goto out_ptp_stop;
 
+	netif_tx_start_all_queues(ndev);
+
 	return 0;
 
 out_ptp_stop:
@@ -1444,6 +1436,13 @@
 	struct ravb_private *priv = container_of(work, struct ravb_private,
 						 work);
 	struct net_device *ndev = priv->ndev;
+	int error;
+
+	if (!rtnl_trylock()) {
+		usleep_range(1000, 2000);
+		schedule_work(&priv->work);
+		return;
+	}
 
 	netif_tx_stop_all_queues(ndev);
 
@@ -1452,20 +1451,44 @@
 		ravb_ptp_stop(ndev);
 
 	/* Wait for DMA stopping */
-	ravb_stop_dma(ndev);
+	if (ravb_stop_dma(ndev)) {
+		/* If ravb_stop_dma() fails, the hardware is still operating
+		 * for TX and/or RX. So, this should not call the following
+		 * functions because ravb_dmac_init() is possible to fail too.
+		 * Also, this should not retry ravb_stop_dma() again and again
+		 * here because it's possible to wait forever. So, this just
+		 * re-enables the TX and RX and skip the following
+		 * re-initialization procedure.
+		 */
+		ravb_rcv_snd_enable(ndev);
+		goto out;
+	}
 
 	ravb_ring_free(ndev, RAVB_BE);
 	ravb_ring_free(ndev, RAVB_NC);
 
 	/* Device init */
-	ravb_dmac_init(ndev);
+	error = ravb_dmac_init(ndev);
+	if (error) {
+		/* If ravb_dmac_init() fails, descriptors are freed. So, this
+		 * should return here to avoid re-enabling the TX and RX in
+		 * ravb_emac_init().
+		 */
+		netdev_err(ndev, "%s: ravb_dmac_init() failed, error %d\n",
+			   __func__, error);
+		goto out_unlock;
+	}
 	ravb_emac_init(ndev);
 
+out:
 	/* Initialise PTP Clock driver */
 	if (priv->chip_id == RCAR_GEN2)
 		ravb_ptp_init(ndev, priv->pdev);
 
 	netif_tx_start_all_queues(ndev);
+
+out_unlock:
+	rtnl_unlock();
 }
 
 /* Packet transmit function for Ethernet AVB */
@@ -1477,7 +1500,7 @@
 	struct ravb_tstamp_skb *ts_skb;
 	struct ravb_tx_desc *desc;
 	unsigned long flags;
-	u32 dma_addr;
+	dma_addr_t dma_addr;
 	void *buffer;
 	u32 entry;
 	u32 len;
@@ -1692,6 +1715,8 @@
 			of_phy_deregister_fixed_link(np);
 	}
 
+	cancel_work_sync(&priv->work);
+
 	if (priv->chip_id != RCAR_GEN2) {
 		free_irq(priv->tx_irqs[RAVB_NC], ndev);
 		free_irq(priv->rx_irqs[RAVB_NC], ndev);
@@ -1719,12 +1744,16 @@
 	config.flags = 0;
 	config.tx_type = priv->tstamp_tx_ctrl ? HWTSTAMP_TX_ON :
 						HWTSTAMP_TX_OFF;
-	if (priv->tstamp_rx_ctrl & RAVB_RXTSTAMP_TYPE_V2_L2_EVENT)
+	switch (priv->tstamp_rx_ctrl & RAVB_RXTSTAMP_TYPE) {
+	case RAVB_RXTSTAMP_TYPE_V2_L2_EVENT:
 		config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
-	else if (priv->tstamp_rx_ctrl & RAVB_RXTSTAMP_TYPE_ALL)
+		break;
+	case RAVB_RXTSTAMP_TYPE_ALL:
 		config.rx_filter = HWTSTAMP_FILTER_ALL;
-	else
+		break;
+	default:
 		config.rx_filter = HWTSTAMP_FILTER_NONE;
+	}
 
 	return copy_to_user(req->ifr_data, &config, sizeof(config)) ?
 		-EFAULT : 0;
@@ -2013,7 +2042,9 @@
 	ndev->hw_features = NETIF_F_RXCSUM;
 
 	pm_runtime_enable(&pdev->dev);
-	pm_runtime_get_sync(&pdev->dev);
+	error = pm_runtime_resume_and_get(&pdev->dev);
+	if (error < 0)
+		goto out_rpm_disable;
 
 	/* The Ether-specific entries in the device structure. */
 	ndev->base_addr = res->start;
@@ -2184,6 +2215,7 @@
 	free_netdev(ndev);
 
 	pm_runtime_put(&pdev->dev);
+out_rpm_disable:
 	pm_runtime_disable(&pdev->dev);
 	return error;
 }
@@ -2197,15 +2229,15 @@
 	if (priv->chip_id != RCAR_GEN2)
 		ravb_ptp_stop(ndev);
 
-	dma_free_coherent(ndev->dev.parent, priv->desc_bat_size, priv->desc_bat,
-			  priv->desc_bat_dma);
 	/* Set reset mode */
 	ravb_write(ndev, CCC_OPC_RESET, CCC);
-	pm_runtime_put_sync(&pdev->dev);
 	unregister_netdev(ndev);
 	netif_napi_del(&priv->napi[RAVB_NC]);
 	netif_napi_del(&priv->napi[RAVB_BE]);
 	ravb_mdio_release(priv);
+	dma_free_coherent(ndev->dev.parent, priv->desc_bat_size, priv->desc_bat,
+			  priv->desc_bat_dma);
+	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 	free_netdev(ndev);
 	platform_set_drvdata(pdev, NULL);
@@ -2312,6 +2344,7 @@
 		ret = ravb_open(ndev);
 		if (ret < 0)
 			return ret;
+		ravb_set_rx_mode(ndev);
 		netif_device_attach(ndev);
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/renesas/sh_eth.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/renesas/sh_eth.c
@@ -610,6 +610,8 @@
 			  EESR_TDE,
 	.fdr_value	= 0x0000070f,
 
+	.trscer_err_mask = DESC_I_RINT8 | DESC_I_RINT5,
+
 	.no_psr		= 1,
 	.apr		= 1,
 	.mpr		= 1,
@@ -828,6 +830,8 @@
 
 	.fdr_value	= 0x0000070f,
 
+	.trscer_err_mask = DESC_I_RINT8 | DESC_I_RINT5,
+
 	.apr		= 1,
 	.mpr		= 1,
 	.tpauser	= 1,
@@ -1131,6 +1135,9 @@
 			  EESIPR_CEEFIP | EESIPR_CELFIP |
 			  EESIPR_RRFIP | EESIPR_RTLFIP | EESIPR_RTSFIP |
 			  EESIPR_PREIP | EESIPR_CERFIP,
+
+	.trscer_err_mask = DESC_I_RINT8,
+
 	.tsu		= 1,
 	.dual_port	= 1,
 };
@@ -2204,24 +2211,28 @@
 	if (cd->tsu) {
 		add_tsu_reg(ARSTR);
 		add_tsu_reg(TSU_CTRST);
-		add_tsu_reg(TSU_FWEN0);
-		add_tsu_reg(TSU_FWEN1);
-		add_tsu_reg(TSU_FCM);
-		add_tsu_reg(TSU_BSYSL0);
-		add_tsu_reg(TSU_BSYSL1);
-		add_tsu_reg(TSU_PRISL0);
-		add_tsu_reg(TSU_PRISL1);
-		add_tsu_reg(TSU_FWSL0);
-		add_tsu_reg(TSU_FWSL1);
+		if (cd->dual_port) {
+			add_tsu_reg(TSU_FWEN0);
+			add_tsu_reg(TSU_FWEN1);
+			add_tsu_reg(TSU_FCM);
+			add_tsu_reg(TSU_BSYSL0);
+			add_tsu_reg(TSU_BSYSL1);
+			add_tsu_reg(TSU_PRISL0);
+			add_tsu_reg(TSU_PRISL1);
+			add_tsu_reg(TSU_FWSL0);
+			add_tsu_reg(TSU_FWSL1);
+		}
 		add_tsu_reg(TSU_FWSLC);
-		add_tsu_reg(TSU_QTAGM0);
-		add_tsu_reg(TSU_QTAGM1);
-		add_tsu_reg(TSU_FWSR);
-		add_tsu_reg(TSU_FWINMK);
-		add_tsu_reg(TSU_ADQT0);
-		add_tsu_reg(TSU_ADQT1);
-		add_tsu_reg(TSU_VTAG0);
-		add_tsu_reg(TSU_VTAG1);
+		if (cd->dual_port) {
+			add_tsu_reg(TSU_QTAGM0);
+			add_tsu_reg(TSU_QTAGM1);
+			add_tsu_reg(TSU_FWSR);
+			add_tsu_reg(TSU_FWINMK);
+			add_tsu_reg(TSU_ADQT0);
+			add_tsu_reg(TSU_ADQT1);
+			add_tsu_reg(TSU_VTAG0);
+			add_tsu_reg(TSU_VTAG1);
+		}
 		add_tsu_reg(TSU_ADSBSY);
 		add_tsu_reg(TSU_TEN);
 		add_tsu_reg(TSU_POST1);
@@ -2311,7 +2322,7 @@
 {
 	switch (stringset) {
 	case ETH_SS_STATS:
-		memcpy(data, *sh_eth_gstrings_stats,
+		memcpy(data, sh_eth_gstrings_stats,
 		       sizeof(sh_eth_gstrings_stats));
 		break;
 	}
@@ -2556,6 +2567,7 @@
 	else
 		txdesc->status |= cpu_to_le32(TD_TACT);
 
+	wmb(); /* cur_tx must be incremented after TACT bit was set */
 	mdp->cur_tx++;
 
 	if (!(sh_eth_read(ndev, EDTRR) & mdp->cd->edtrr_trns))
@@ -2636,10 +2648,10 @@
 	/* Free all the skbuffs in the Rx queue and the DMA buffer. */
 	sh_eth_ring_free(ndev);
 
-	pm_runtime_put_sync(&mdp->pdev->dev);
-
 	mdp->is_opened = 0;
 
+	pm_runtime_put(&mdp->pdev->dev);
+
 	return 0;
 }
 
@@ -3484,10 +3496,12 @@
 
 	netif_device_detach(ndev);
 
+	rtnl_lock();
 	if (mdp->wol_enabled)
 		ret = sh_eth_wol_setup(ndev);
 	else
 		ret = sh_eth_close(ndev);
+	rtnl_unlock();
 
 	return ret;
 }
@@ -3501,10 +3515,12 @@
 	if (!netif_running(ndev))
 		return 0;
 
+	rtnl_lock();
 	if (mdp->wol_enabled)
 		ret = sh_eth_wol_restore(ndev);
 	else
 		ret = sh_eth_open(ndev);
+	rtnl_unlock();
 
 	if (ret < 0)
 		return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/rocker/rocker_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/rocker/rocker_main.c
@@ -647,10 +647,10 @@
 err_dma_event_ring_bufs_alloc:
 	rocker_dma_ring_destroy(rocker, &rocker->event_ring);
 err_dma_event_ring_create:
+	rocker_dma_cmd_ring_waits_free(rocker);
+err_dma_cmd_ring_waits_alloc:
 	rocker_dma_ring_bufs_free(rocker, &rocker->cmd_ring,
 				  PCI_DMA_BIDIRECTIONAL);
-err_dma_cmd_ring_waits_alloc:
-	rocker_dma_cmd_ring_waits_free(rocker);
 err_dma_cmd_ring_bufs_alloc:
 	rocker_dma_ring_destroy(rocker, &rocker->cmd_ring);
 	return err;
@@ -2542,7 +2542,7 @@
 	u64 link_status = rocker_read64(rocker, PORT_PHYS_LINK_STATUS);
 	bool link_up;
 
-	link_up = link_status & (1 << rocker_port->pport);
+	link_up = link_status & (1ULL << rocker_port->pport);
 	if (link_up)
 		netif_carrier_on(rocker_port->dev);
 	else
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/rocker/rocker_ofdpa.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/rocker/rocker_ofdpa.c
@@ -1273,7 +1273,7 @@
 	bool removing;
 	int err = 0;
 
-	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+	entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
 	if (!entry)
 		return -ENOMEM;
 
@@ -2795,7 +2795,8 @@
 		if (!ofdpa_port)
 			continue;
 		nh->fib_nh_flags &= ~RTNH_F_OFFLOAD;
-		ofdpa_flow_tbl_del(ofdpa_port, OFDPA_OP_FLAG_REMOVE,
+		ofdpa_flow_tbl_del(ofdpa_port,
+				   OFDPA_OP_FLAG_REMOVE | OFDPA_OP_FLAG_NOWAIT,
 				   flow_entry);
 	}
 	spin_unlock_irqrestore(&ofdpa->flow_tbl_lock, flags);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
@@ -2277,18 +2277,18 @@
 	char *opt;
 
 	if (!str || !*str)
-		return -EINVAL;
+		return 1;
 	while ((opt = strsep(&str, ",")) != NULL) {
-		if (!strncmp(opt, "eee_timer:", 6)) {
+		if (!strncmp(opt, "eee_timer:", 10)) {
 			if (kstrtoint(opt + 10, 0, &eee_timer))
 				goto err;
 		}
 	}
-	return 0;
+	return 1;
 
 err:
 	pr_err("%s: ERROR broken module parameter conversion\n", __func__);
-	return -EINVAL;
+	return 1;
 }
 
 __setup("sxgbeeth=", sxgbe_cmdline_opt);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/seeq/ether3.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/seeq/ether3.c
@@ -848,9 +848,11 @@
 {
 	struct net_device *dev = ecard_get_drvdata(ec);
 
+	ether3_outw(priv(dev)->regs.config2 |= CFG2_CTRLO, REG_CONFIG2);
 	ecard_set_drvdata(ec, NULL);
 
 	unregister_netdev(dev);
+	del_timer_sync(&priv(dev)->timer);
 	free_netdev(dev);
 	ecard_release_resources(ec);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/sfc/ef10.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/sfc/ef10.c
@@ -2056,7 +2056,10 @@
 
 	efx_update_sw_stats(efx, stats);
 out:
+	/* releasing a DMA coherent buffer with BH disabled can panic */
+	spin_unlock_bh(&efx->stats_lock);
 	efx_nic_free_buffer(efx, &stats_buf);
+	spin_lock_bh(&efx->stats_lock);
 	return rc;
 }
 
@@ -6160,6 +6163,11 @@
 		n_parts++;
 	}
 
+	if (!n_parts) {
+		kfree(parts);
+		return 0;
+	}
+
 	rc = efx_mtd_add(efx, &parts[0].common, n_parts, sizeof(*parts));
 fail:
 	if (rc)
@@ -6593,6 +6601,30 @@
 	return rc;
 }
 
+static unsigned int efx_ef10_recycle_ring_size(const struct efx_nic *efx)
+{
+	unsigned int ret = EFX_RECYCLE_RING_SIZE_10G;
+
+	/* There is no difference between PFs and VFs. The side is based on
+	 * the maximum link speed of a given NIC.
+	 */
+	switch (efx->pci_dev->device & 0xfff) {
+	case 0x0903:	/* Farmingdale can do up to 10G */
+		break;
+	case 0x0923:	/* Greenport can do up to 40G */
+	case 0x0a03:	/* Medford can do up to 40G */
+		ret *= 4;
+		break;
+	default:	/* Medford2 can do up to 100G */
+		ret *= 10;
+	}
+
+	if (IS_ENABLED(CONFIG_PPC64))
+		ret *= 4;
+
+	return ret;
+}
+
 #define EF10_OFFLOAD_FEATURES		\
 	(NETIF_F_IP_CSUM |		\
 	 NETIF_F_HW_VLAN_CTAG_FILTER |	\
@@ -6705,6 +6737,7 @@
 	.hwtstamp_filters = 1 << HWTSTAMP_FILTER_NONE |
 			    1 << HWTSTAMP_FILTER_ALL,
 	.rx_hash_key_size = 40,
+	.rx_recycle_ring_size = efx_ef10_recycle_ring_size,
 };
 
 const struct efx_nic_type efx_hunt_a0_nic_type = {
@@ -6840,4 +6873,5 @@
 	.hwtstamp_filters = 1 << HWTSTAMP_FILTER_NONE |
 			    1 << HWTSTAMP_FILTER_ALL,
 	.rx_hash_key_size = 40,
+	.rx_recycle_ring_size = efx_ef10_recycle_ring_size,
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/sfc/ef10_sriov.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/sfc/ef10_sriov.c
@@ -403,12 +403,18 @@
 	return rc;
 }
 
+/* Disable SRIOV and remove VFs
+ * If some VFs are attached to a guest (using Xen, only) nothing is
+ * done if force=false, and vports are freed if force=true (for the non
+ * attachedc ones, only) but SRIOV is not disabled and VFs are not
+ * removed in either case.
+ */
 static int efx_ef10_pci_sriov_disable(struct efx_nic *efx, bool force)
 {
 	struct pci_dev *dev = efx->pci_dev;
-	unsigned int vfs_assigned = 0;
-
-	vfs_assigned = pci_vfs_assigned(dev);
+	struct efx_ef10_nic_data *nic_data = efx->nic_data;
+	unsigned int vfs_assigned = pci_vfs_assigned(dev);
+	int i, rc = 0;
 
 	if (vfs_assigned && !force) {
 		netif_info(efx, drv, efx->net_dev, "VFs are assigned to guests; "
@@ -416,12 +422,17 @@
 		return -EBUSY;
 	}
 
-	if (!vfs_assigned)
+	if (!vfs_assigned) {
+		for (i = 0; i < efx->vf_count; i++)
+			nic_data->vf[i].pci_dev = NULL;
 		pci_disable_sriov(dev);
+	} else {
+		rc = -EBUSY;
+	}
 
 	efx_ef10_sriov_free_vf_vswitching(efx);
 	efx->vf_count = 0;
-	return 0;
+	return rc;
 }
 
 int efx_ef10_sriov_configure(struct efx_nic *efx, int num_vfs)
@@ -440,7 +451,6 @@
 void efx_ef10_sriov_fini(struct efx_nic *efx)
 {
 	struct efx_ef10_nic_data *nic_data = efx->nic_data;
-	unsigned int i;
 	int rc;
 
 	if (!nic_data->vf) {
@@ -450,14 +460,7 @@
 		return;
 	}
 
-	/* Remove any VFs in the host */
-	for (i = 0; i < efx->vf_count; ++i) {
-		struct efx_nic *vf_efx = nic_data->vf[i].efx;
-
-		if (vf_efx)
-			vf_efx->pci_dev->driver->remove(vf_efx->pci_dev);
-	}
-
+	/* Disable SRIOV and remove any VFs in the host */
 	rc = efx_ef10_pci_sriov_disable(efx, true);
 	if (rc)
 		netif_dbg(efx, drv, efx->net_dev,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/sfc/efx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/sfc/efx.c
@@ -519,6 +519,7 @@
 		if (tx_queue->channel)
 			tx_queue->channel = channel;
 		tx_queue->buffer = NULL;
+		tx_queue->cb_page = NULL;
 		memset(&tx_queue->txd, 0, sizeof(tx_queue->txd));
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/sfc/efx.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/sfc/efx.h
@@ -57,6 +57,12 @@
 #define EFX_MAX_EVQ_SIZE 16384UL
 #define EFX_MIN_EVQ_SIZE 512UL
 
+/* Number of RX buffers to recycle pages for.  When creating the RX page recycle
+ * ring, this number is divided by the number of buffers per page to calculate
+ * the number of pages to store in the RX page recycle ring.
+ */
+#define EFX_RECYCLE_RING_SIZE_10G	256
+
 /* Maximum number of TCP segments we support for soft-TSO */
 #define EFX_TSO_MAX_SEGS	100
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/sfc/ethtool.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/sfc/ethtool.c
@@ -128,20 +128,14 @@
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
 	struct efx_link_state *link_state = &efx->link_state;
-	u32 supported;
 
 	mutex_lock(&efx->mac_lock);
 	efx->phy_op->get_link_ksettings(efx, cmd);
 	mutex_unlock(&efx->mac_lock);
 
 	/* Both MACs support pause frames (bidirectional and respond-only) */
-	ethtool_convert_link_mode_to_legacy_u32(&supported,
-						cmd->link_modes.supported);
-
-	supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
-
-	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
-						supported);
+	ethtool_link_ksettings_add_link_mode(cmd, supported, Pause);
+	ethtool_link_ksettings_add_link_mode(cmd, supported, Asym_Pause);
 
 	if (LOOPBACK_INTERNAL(efx)) {
 		cmd->base.speed = link_state->speed;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/sfc/falcon/farch.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/sfc/falcon/farch.c
@@ -870,17 +870,12 @@
 {
 	struct ef4_channel *channel = ef4_rx_queue_channel(rx_queue);
 	struct ef4_nic *efx = rx_queue->efx;
-	bool rx_ev_buf_owner_id_err, rx_ev_ip_hdr_chksum_err;
+	bool __maybe_unused rx_ev_buf_owner_id_err, rx_ev_ip_hdr_chksum_err;
 	bool rx_ev_tcp_udp_chksum_err, rx_ev_eth_crc_err;
 	bool rx_ev_frm_trunc, rx_ev_drib_nib, rx_ev_tobe_disc;
-	bool rx_ev_other_err, rx_ev_pause_frm;
-	bool rx_ev_hdr_type, rx_ev_mcast_pkt;
-	unsigned rx_ev_pkt_type;
+	bool rx_ev_pause_frm;
 
-	rx_ev_hdr_type = EF4_QWORD_FIELD(*event, FSF_AZ_RX_EV_HDR_TYPE);
-	rx_ev_mcast_pkt = EF4_QWORD_FIELD(*event, FSF_AZ_RX_EV_MCAST_PKT);
 	rx_ev_tobe_disc = EF4_QWORD_FIELD(*event, FSF_AZ_RX_EV_TOBE_DISC);
-	rx_ev_pkt_type = EF4_QWORD_FIELD(*event, FSF_AZ_RX_EV_PKT_TYPE);
 	rx_ev_buf_owner_id_err = EF4_QWORD_FIELD(*event,
 						 FSF_AZ_RX_EV_BUF_OWNER_ID_ERR);
 	rx_ev_ip_hdr_chksum_err = EF4_QWORD_FIELD(*event,
@@ -893,10 +888,6 @@
 			  0 : EF4_QWORD_FIELD(*event, FSF_AA_RX_EV_DRIB_NIB));
 	rx_ev_pause_frm = EF4_QWORD_FIELD(*event, FSF_AZ_RX_EV_PAUSE_FRM_ERR);
 
-	/* Every error apart from tobe_disc and pause_frm */
-	rx_ev_other_err = (rx_ev_drib_nib | rx_ev_tcp_udp_chksum_err |
-			   rx_ev_buf_owner_id_err | rx_ev_eth_crc_err |
-			   rx_ev_frm_trunc | rx_ev_ip_hdr_chksum_err);
 
 	/* Count errors that are not in MAC stats.  Ignore expected
 	 * checksum errors during self-test. */
@@ -916,6 +907,13 @@
 	 * to a FIFO overflow.
 	 */
 #ifdef DEBUG
+	{
+	/* Every error apart from tobe_disc and pause_frm */
+
+	bool rx_ev_other_err = (rx_ev_drib_nib | rx_ev_tcp_udp_chksum_err |
+				rx_ev_buf_owner_id_err | rx_ev_eth_crc_err |
+				rx_ev_frm_trunc | rx_ev_ip_hdr_chksum_err);
+
 	if (rx_ev_other_err && net_ratelimit()) {
 		netif_dbg(efx, rx_err, efx->net_dev,
 			  " RX queue %d unexpected RX event "
@@ -932,6 +930,7 @@
 			  rx_ev_tobe_disc ? " [TOBE_DISC]" : "",
 			  rx_ev_pause_frm ? " [PAUSE]" : "");
 	}
+	}
 #endif
 
 	/* The frame must be discarded if any of these are true. */
@@ -1643,15 +1642,11 @@
  */
 void ef4_farch_dimension_resources(struct ef4_nic *efx, unsigned sram_lim_qw)
 {
-	unsigned vi_count, buftbl_min;
+	unsigned vi_count;
 
 	/* Account for the buffer table entries backing the datapath channels
 	 * and the descriptor caches for those channels.
 	 */
-	buftbl_min = ((efx->n_rx_channels * EF4_MAX_DMAQ_SIZE +
-		       efx->n_tx_channels * EF4_TXQ_TYPES * EF4_MAX_DMAQ_SIZE +
-		       efx->n_channels * EF4_MAX_EVQ_SIZE)
-		      * sizeof(ef4_qword_t) / EF4_BUF_SIZE);
 	vi_count = max(efx->n_channels, efx->n_tx_channels * EF4_TXQ_TYPES);
 
 	efx->tx_dc_base = sram_lim_qw - vi_count * TX_DC_ENTRIES;
@@ -2532,7 +2527,6 @@
 	enum ef4_farch_filter_table_id table_id;
 	struct ef4_farch_filter_table *table;
 	unsigned int filter_idx;
-	struct ef4_farch_filter_spec *spec;
 	int rc;
 
 	table_id = ef4_farch_filter_id_table_id(filter_id);
@@ -2543,7 +2537,6 @@
 	filter_idx = ef4_farch_filter_id_index(filter_id);
 	if (filter_idx >= table->size)
 		return -ENOENT;
-	spec = &table->spec[filter_idx];
 
 	spin_lock_bh(&efx->filter_lock);
 	rc = ef4_farch_filter_remove(efx, table, filter_idx, priority);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/sfc/falcon/rx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/sfc/falcon/rx.c
@@ -726,7 +726,10 @@
 					    efx->rx_bufs_per_page);
 	rx_queue->page_ring = kcalloc(page_ring_size,
 				      sizeof(*rx_queue->page_ring), GFP_KERNEL);
-	rx_queue->page_ptr_mask = page_ring_size - 1;
+	if (!rx_queue->page_ring)
+		rx_queue->page_ptr_mask = 0;
+	else
+		rx_queue->page_ptr_mask = page_ring_size - 1;
 }
 
 void ef4_init_rx_queue(struct ef4_rx_queue *rx_queue)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/sfc/mcdi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/sfc/mcdi.c
@@ -163,9 +163,9 @@
 	/* Serialise with efx_mcdi_ev_cpl() and efx_mcdi_ev_death() */
 	spin_lock_bh(&mcdi->iface_lock);
 	++mcdi->seqno;
+	seqno = mcdi->seqno & SEQ_MASK;
 	spin_unlock_bh(&mcdi->iface_lock);
 
-	seqno = mcdi->seqno & SEQ_MASK;
 	xflags = 0;
 	if (mcdi->mode == MCDI_MODE_EVENTS)
 		xflags |= MCDI_HEADER_XFLAGS_EVREQ;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/sfc/net_driver.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/sfc/net_driver.h
@@ -1243,6 +1243,7 @@
  * @udp_tnl_add_port: Add a UDP tunnel port
  * @udp_tnl_has_port: Check if a port has been added as UDP tunnel
  * @udp_tnl_del_port: Remove a UDP tunnel port
+ * @rx_recycle_ring_size: Size of the RX recycle ring
  * @revision: Hardware architecture revision
  * @txd_ptr_tbl_base: TX descriptor ring base address
  * @rxd_ptr_tbl_base: RX descriptor ring base address
@@ -1413,6 +1414,7 @@
 	int (*udp_tnl_add_port)(struct efx_nic *efx, struct efx_udp_tunnel tnl);
 	bool (*udp_tnl_has_port)(struct efx_nic *efx, __be16 port);
 	int (*udp_tnl_del_port)(struct efx_nic *efx, struct efx_udp_tunnel tnl);
+	unsigned int (*rx_recycle_ring_size)(const struct efx_nic *efx);
 
 	int revision;
 	unsigned int txd_ptr_tbl_base;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/sfc/nic.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/sfc/nic.h
@@ -607,6 +607,11 @@
 
 bool efx_nic_event_present(struct efx_channel *channel);
 
+static inline unsigned int efx_rx_recycle_ring_size(const struct efx_nic *efx)
+{
+	return efx->type->rx_recycle_ring_size(efx);
+}
+
 /* Some statistics are computed as A - B where A and B each increase
  * linearly with some hardware counter(s) and the counters are read
  * asynchronously.  If the counters contributing to B are always read
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/sfc/ptp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/sfc/ptp.c
@@ -560,13 +560,45 @@
 				    u32 nic_major, u32 nic_minor,
 				    s32 correction)
 {
+	u32 sync_timestamp;
 	ktime_t kt = { 0 };
+	s16 delta;
 
 	if (!(nic_major & 0x80000000)) {
 		WARN_ON_ONCE(nic_major >> 16);
-		/* Use the top bits from the latest sync event. */
-		nic_major &= 0xffff;
-		nic_major |= (last_sync_timestamp_major(efx) & 0xffff0000);
+
+		/* Medford provides 48 bits of timestamp, so we must get the top
+		 * 16 bits from the timesync event state.
+		 *
+		 * We only have the lower 16 bits of the time now, but we do
+		 * have a full resolution timestamp at some point in past. As
+		 * long as the difference between the (real) now and the sync
+		 * is less than 2^15, then we can reconstruct the difference
+		 * between those two numbers using only the lower 16 bits of
+		 * each.
+		 *
+		 * Put another way
+		 *
+		 * a - b = ((a mod k) - b) mod k
+		 *
+		 * when -k/2 < (a-b) < k/2. In our case k is 2^16. We know
+		 * (a mod k) and b, so can calculate the delta, a - b.
+		 *
+		 */
+		sync_timestamp = last_sync_timestamp_major(efx);
+
+		/* Because delta is s16 this does an implicit mask down to
+		 * 16 bits which is what we need, assuming
+		 * MEDFORD_TX_SECS_EVENT_BITS is 16. delta is signed so that
+		 * we can deal with the (unlikely) case of sync timestamps
+		 * arriving from the future.
+		 */
+		delta = nic_major - sync_timestamp;
+
+		/* Recover the fully specified time now, by applying the offset
+		 * to the (fully specified) sync time.
+		 */
+		nic_major = sync_timestamp + delta;
 
 		kt = ptp->nic_to_kernel_time(nic_major, nic_minor,
 					     correction);
@@ -616,7 +648,7 @@
 	} else if (rc == -EINVAL) {
 		fmt = MC_CMD_PTP_OUT_GET_ATTRIBUTES_SECONDS_NANOSECONDS;
 	} else if (rc == -EPERM) {
-		netif_info(efx, probe, efx->net_dev, "no PTP support\n");
+		pci_info(efx->pci_dev, "no PTP support\n");
 		return rc;
 	} else {
 		efx_mcdi_display_error(efx, MC_CMD_PTP, sizeof(inbuf),
@@ -792,7 +824,7 @@
 	 * should only have been called during probe.
 	 */
 	if (rc == -ENOSYS || rc == -EPERM)
-		netif_info(efx, probe, efx->net_dev, "no PTP support\n");
+		pci_info(efx->pci_dev, "no PTP support\n");
 	else if (rc)
 		efx_mcdi_display_error(efx, MC_CMD_PTP,
 				       MC_CMD_PTP_IN_DISABLE_LEN,
@@ -1061,7 +1093,29 @@
 
 	tx_queue = &ptp_data->channel->tx_queue[type];
 	if (tx_queue && tx_queue->timestamping) {
+		/* This code invokes normal driver TX code which is always
+		 * protected from softirqs when called from generic TX code,
+		 * which in turn disables preemption. Look at __dev_queue_xmit
+		 * which uses rcu_read_lock_bh disabling preemption for RCU
+		 * plus disabling softirqs. We do not need RCU reader
+		 * protection here.
+		 *
+		 * Although it is theoretically safe for current PTP TX/RX code
+		 * running without disabling softirqs, there are three good
+		 * reasond for doing so:
+		 *
+		 *      1) The code invoked is mainly implemented for non-PTP
+		 *         packets and it is always executed with softirqs
+		 *         disabled.
+		 *      2) This being a single PTP packet, better to not
+		 *         interrupt its processing by softirqs which can lead
+		 *         to high latencies.
+		 *      3) netdev_xmit_more checks preemption is disabled and
+		 *         triggers a BUG_ON if not.
+		 */
+		local_bh_disable();
 		efx_enqueue_skb(tx_queue, skb);
+		local_bh_enable();
 	} else {
 		WARN_ONCE(1, "PTP channel has no timestamped tx queue\n");
 		dev_kfree_skb_any(skb);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/sfc/rx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/sfc/rx.c
@@ -27,13 +27,6 @@
 /* Preferred number of descriptors to fill at once */
 #define EFX_RX_PREFERRED_BATCH 8U
 
-/* Number of RX buffers to recycle pages for.  When creating the RX page recycle
- * ring, this number is divided by the number of buffers per page to calculate
- * the number of pages to store in the RX page recycle ring.
- */
-#define EFX_RECYCLE_RING_SIZE_IOMMU 4096
-#define EFX_RECYCLE_RING_SIZE_NOIOMMU (2 * EFX_RX_PREFERRED_BATCH)
-
 /* Size of buffer allocated for skb header area. */
 #define EFX_SKB_HEADERS  128u
 
@@ -710,16 +703,7 @@
 {
 	unsigned int bufs_in_recycle_ring, page_ring_size;
 
-	/* Set the RX recycle ring size */
-#ifdef CONFIG_PPC64
-	bufs_in_recycle_ring = EFX_RECYCLE_RING_SIZE_IOMMU;
-#else
-	if (iommu_present(&pci_bus_type))
-		bufs_in_recycle_ring = EFX_RECYCLE_RING_SIZE_IOMMU;
-	else
-		bufs_in_recycle_ring = EFX_RECYCLE_RING_SIZE_NOIOMMU;
-#endif /* CONFIG_PPC64 */
-
+	bufs_in_recycle_ring = efx_rx_recycle_ring_size(efx);
 	page_ring_size = roundup_pow_of_two(bufs_in_recycle_ring /
 					    efx->rx_bufs_per_page);
 	rx_queue->page_ring = kcalloc(page_ring_size,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/sfc/siena.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/sfc/siena.c
@@ -946,6 +946,12 @@
 
 #endif /* CONFIG_SFC_MTD */
 
+static unsigned int efx_siena_recycle_ring_size(const struct efx_nic *efx)
+{
+	/* Maximum link speed is 10G */
+	return EFX_RECYCLE_RING_SIZE_10G;
+}
+
 /**************************************************************************
  *
  * Revision-dependent attributes used by efx.c and nic.c
@@ -1084,4 +1090,5 @@
 			     1 << HWTSTAMP_FILTER_PTP_V1_L4_EVENT |
 			     1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT),
 	.rx_hash_key_size = 16,
+	.rx_recycle_ring_size = efx_siena_recycle_ring_size,
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/sfc/siena_sriov.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/sfc/siena_sriov.c
@@ -1056,7 +1056,7 @@
 		return;
 
 	if (efx_siena_sriov_cmd(efx, false, &efx->vi_scale, &count)) {
-		netif_info(efx, probe, efx->net_dev, "no SR-IOV VFs probed\n");
+		pci_info(efx->pci_dev, "no SR-IOV VFs probed\n");
 		return;
 	}
 	if (count > 0 && count > max_vfs)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/sis/sis900.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/sis/sis900.c
@@ -443,7 +443,7 @@
 #endif
 
 	/* setup various bits in PCI command register */
-	ret = pci_enable_device(pci_dev);
+	ret = pcim_enable_device(pci_dev);
 	if(ret) return ret;
 
 	i = pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32));
@@ -469,7 +469,7 @@
 	ioaddr = pci_iomap(pci_dev, 0, 0);
 	if (!ioaddr) {
 		ret = -ENOMEM;
-		goto err_out_cleardev;
+		goto err_out;
 	}
 
 	sis_priv = netdev_priv(net_dev);
@@ -579,8 +579,6 @@
 		sis_priv->tx_ring_dma);
 err_out_unmap:
 	pci_iounmap(pci_dev, ioaddr);
-err_out_cleardev:
-	pci_release_regions(pci_dev);
  err_out:
 	free_netdev(net_dev);
 	return ret;
@@ -787,10 +785,9 @@
 static void sis900_set_capability(struct net_device *net_dev, struct mii_phy *phy)
 {
 	u16 cap;
-	u16 status;
 
-	status = mdio_read(net_dev, phy->phy_addr, MII_STATUS);
-	status = mdio_read(net_dev, phy->phy_addr, MII_STATUS);
+	mdio_read(net_dev, phy->phy_addr, MII_STATUS);
+	mdio_read(net_dev, phy->phy_addr, MII_STATUS);
 
 	cap = MII_NWAY_CSMA_CD |
 		((phy->status & MII_STAT_CAN_TX_FDX)? MII_NWAY_TX_FDX:0) |
@@ -2490,7 +2487,6 @@
 		sis_priv->tx_ring_dma);
 	pci_iounmap(pci_dev, sis_priv->ioaddr);
 	free_netdev(net_dev);
-	pci_release_regions(pci_dev);
 }
 
 #ifdef CONFIG_PM
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/smsc/smc911x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/smsc/smc911x.c
@@ -936,7 +936,7 @@
 	if (lp->ctl_rspeed != 100)
 		my_ad_caps &= ~(ADVERTISE_100BASE4|ADVERTISE_100FULL|ADVERTISE_100HALF);
 
-	 if (!lp->ctl_rfduplx)
+	if (!lp->ctl_rfduplx)
 		my_ad_caps &= ~(ADVERTISE_100FULL|ADVERTISE_10FULL);
 
 	/* Update our Auto-Neg Advertisement Register */
@@ -2069,6 +2069,11 @@
 
 	ndev->dma = (unsigned char)-1;
 	ndev->irq = platform_get_irq(pdev, 0);
+	if (ndev->irq < 0) {
+		ret = ndev->irq;
+		goto release_both;
+	}
+
 	lp = netdev_priv(ndev);
 	lp->netdev = ndev;
 #ifdef SMC_DYNAMIC_BUS_CONFIG
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/smsc/smc91x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/smsc/smc91x.c
@@ -2274,7 +2274,7 @@
 		ret = try_toggle_control_gpio(&pdev->dev, &lp->power_gpio,
 					      "power", 0, 0, 100);
 		if (ret)
-			return ret;
+			goto out_free_netdev;
 
 		/*
 		 * Optional reset GPIO configured? Minimum 100 ns reset needed
@@ -2283,7 +2283,7 @@
 		ret = try_toggle_control_gpio(&pdev->dev, &lp->reset_gpio,
 					      "reset", 0, 0, 100);
 		if (ret)
-			return ret;
+			goto out_free_netdev;
 
 		/*
 		 * Need to wait for optional EEPROM to load, max 750 us according
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/smsc/smc91x.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/smsc/smc91x.h
@@ -175,8 +175,8 @@
 		writew(*wp++, a);
 }
 
-#define SMC_inw(a, r)		_swapw(readw((a) + (r)))
-#define SMC_outw(lp, v, a, r)	writew(_swapw(v), (a) + (r))
+#define SMC_inw(a, r)		ioread16be((a) + (r))
+#define SMC_outw(lp, v, a, r)	iowrite16be(v, (a) + (r))
 #define SMC_insw(a, r, p, l)	mcf_insw(a + r, p, l)
 #define SMC_outsw(a, r, p, l)	mcf_outsw(a + r, p, l)
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/smsc/smsc911x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/smsc/smsc911x.c
@@ -2433,7 +2433,7 @@
 	if (irq == -EPROBE_DEFER) {
 		retval = -EPROBE_DEFER;
 		goto out_0;
-	} else if (irq <= 0) {
+	} else if (irq < 0) {
 		pr_warn("Could not allocate irq resource\n");
 		retval = -ENODEV;
 		goto out_0;
@@ -2502,20 +2502,20 @@
 
 	retval = smsc911x_init(dev);
 	if (retval < 0)
-		goto out_disable_resources;
+		goto out_init_fail;
 
 	netif_carrier_off(dev);
 
 	retval = smsc911x_mii_init(pdev, dev);
 	if (retval) {
 		SMSC_WARN(pdata, probe, "Error %i initialising mii", retval);
-		goto out_disable_resources;
+		goto out_init_fail;
 	}
 
 	retval = register_netdev(dev);
 	if (retval) {
 		SMSC_WARN(pdata, probe, "Error %i registering device", retval);
-		goto out_disable_resources;
+		goto out_init_fail;
 	} else {
 		SMSC_TRACE(pdata, probe,
 			   "Network interface: \"%s\"", dev->name);
@@ -2556,9 +2556,10 @@
 
 	return 0;
 
-out_disable_resources:
+out_init_fail:
 	pm_runtime_put(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
+out_disable_resources:
 	(void)smsc911x_disable_resources(pdev);
 out_enable_resources_fail:
 	smsc911x_free_resources(pdev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/socionext/netsec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/socionext/netsec.c
@@ -847,8 +847,8 @@
 		enum dma_data_direction dma_dir =
 			page_pool_get_dma_dir(rx_ring->page_pool);
 
-		dma_handle = page_pool_get_dma_addr(page) +
-			NETSEC_RXBUF_HEADROOM;
+		dma_handle = page_pool_get_dma_addr(page) + xdpf->headroom +
+			sizeof(*xdpf);
 		dma_sync_single_for_device(priv->dev, dma_handle, xdpf->len,
 					   dma_dir);
 		tx_desc.buf_type = TYPE_NETSEC_XDP_TX;
@@ -928,7 +928,6 @@
 	struct netsec_rx_pkt_info rx_info;
 	enum dma_data_direction dma_dir;
 	struct bpf_prog *xdp_prog;
-	struct sk_buff *skb = NULL;
 	u16 xdp_xmit = 0;
 	u32 xdp_act = 0;
 	int done = 0;
@@ -942,7 +941,8 @@
 		struct netsec_de *de = dring->vaddr + (DESC_SZ * idx);
 		struct netsec_desc *desc = &dring->desc[idx];
 		struct page *page = virt_to_page(desc->addr);
-		u32 xdp_result = XDP_PASS;
+		u32 xdp_result = NETSEC_XDP_PASS;
+		struct sk_buff *skb = NULL;
 		u16 pkt_len, desc_len;
 		dma_addr_t dma_handle;
 		struct xdp_buff xdp;
@@ -1693,14 +1693,17 @@
 		goto err1;
 
 	/* set phy power down */
-	data = netsec_phy_read(priv->mii_bus, priv->phy_addr, MII_BMCR) |
-		BMCR_PDOWN;
-	netsec_phy_write(priv->mii_bus, priv->phy_addr, MII_BMCR, data);
+	data = netsec_phy_read(priv->mii_bus, priv->phy_addr, MII_BMCR);
+	netsec_phy_write(priv->mii_bus, priv->phy_addr, MII_BMCR,
+			 data | BMCR_PDOWN);
 
 	ret = netsec_reset_hardware(priv, true);
 	if (ret)
 		goto err2;
 
+	/* Restore phy power state */
+	netsec_phy_write(priv->mii_bus, priv->phy_addr, MII_BMCR, data);
+
 	spin_lock_init(&priv->desc_ring[NETSEC_RING_TX].lock);
 	spin_lock_init(&priv->desc_ring[NETSEC_RING_RX].lock);
 
@@ -1933,11 +1936,13 @@
 			ret = PTR_ERR(priv->phydev);
 			dev_err(priv->dev, "get_phy_device err(%d)\n", ret);
 			priv->phydev = NULL;
+			mdiobus_unregister(bus);
 			return -ENODEV;
 		}
 
 		ret = phy_device_register(priv->phydev);
 		if (ret) {
+			phy_device_free(priv->phydev);
 			mdiobus_unregister(bus);
 			dev_err(priv->dev,
 				"phy_device_register err(%d)\n", ret);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/socionext/sni_ave.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/socionext/sni_ave.c
@@ -424,16 +424,22 @@
 		phy_ethtool_get_wol(ndev->phydev, wol);
 }
 
-static int ave_ethtool_set_wol(struct net_device *ndev,
-			       struct ethtool_wolinfo *wol)
+static int __ave_ethtool_set_wol(struct net_device *ndev,
+				 struct ethtool_wolinfo *wol)
 {
-	int ret;
-
 	if (!ndev->phydev ||
 	    (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE)))
 		return -EOPNOTSUPP;
 
-	ret = phy_ethtool_set_wol(ndev->phydev, wol);
+	return phy_ethtool_set_wol(ndev->phydev, wol);
+}
+
+static int ave_ethtool_set_wol(struct net_device *ndev,
+			       struct ethtool_wolinfo *wol)
+{
+	int ret;
+
+	ret = __ave_ethtool_set_wol(ndev, wol);
 	if (!ret)
 		device_set_wakeup_enable(&ndev->dev, !!wol->wolopts);
 
@@ -1185,7 +1191,7 @@
 	ret = regmap_update_bits(priv->regmap, SG_ETPINMODE,
 				 priv->pinmode_mask, priv->pinmode_val);
 	if (ret)
-		return ret;
+		goto out_reset_assert;
 
 	ave_global_reset(ndev);
 
@@ -1216,7 +1222,7 @@
 
 	/* set wol initial state disabled */
 	wol.wolopts = 0;
-	ave_ethtool_set_wol(ndev, &wol);
+	__ave_ethtool_set_wol(ndev, &wol);
 
 	if (!phy_interface_is_rgmii(phydev))
 		phy_set_max_speed(phydev, SPEED_100);
@@ -1768,7 +1774,7 @@
 
 	ave_ethtool_get_wol(ndev, &wol);
 	wol.wolopts = priv->wolopts;
-	ave_ethtool_set_wol(ndev, &wol);
+	__ave_ethtool_set_wol(ndev, &wol);
 
 	if (ndev->phydev) {
 		ret = phy_resume(ndev->phydev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c
@@ -57,10 +57,6 @@
 #define TSE_PCS_USE_SGMII_ENA				BIT(0)
 #define TSE_PCS_IF_USE_SGMII				0x03
 
-#define SGMII_ADAPTER_CTRL_REG				0x00
-#define SGMII_ADAPTER_DISABLE				0x0001
-#define SGMII_ADAPTER_ENABLE				0x0000
-
 #define AUTONEGO_LINK_TIMER				20
 
 static int tse_pcs_reset(void __iomem *base, struct tse_pcs *pcs)
@@ -202,12 +198,8 @@
 			   unsigned int speed)
 {
 	void __iomem *tse_pcs_base = pcs->tse_pcs_base;
-	void __iomem *sgmii_adapter_base = pcs->sgmii_adapter_base;
 	u32 val;
 
-	writew(SGMII_ADAPTER_ENABLE,
-	       sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG);
-
 	pcs->autoneg = phy_dev->autoneg;
 
 	if (phy_dev->autoneg == AUTONEG_ENABLE) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.h
@@ -10,6 +10,10 @@
 #include <linux/phy.h>
 #include <linux/timer.h>
 
+#define SGMII_ADAPTER_CTRL_REG		0x00
+#define SGMII_ADAPTER_ENABLE		0x0000
+#define SGMII_ADAPTER_DISABLE		0x0001
+
 struct tse_pcs {
 	struct device *dev;
 	void __iomem *tse_pcs_base;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/common.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -176,6 +176,7 @@
 	unsigned long mac_errors[32];
 	unsigned long mtl_errors[32];
 	unsigned long dma_errors[32];
+	unsigned long dma_dpp_errors[32];
 };
 
 /* Number of fields in Safety Stats */
@@ -364,9 +365,8 @@
 	unsigned int arpoffsel;
 };
 
-/* GMAC TX FIFO is 8K, Rx FIFO is 16K */
-#define BUF_SIZE_16KiB 16384
-/* RX Buffer size must be < 8191 and multiple of 4/8/16 bytes */
+/* RX Buffer size must be multiple of 4/8/16 bytes */
+#define BUF_SIZE_16KiB 16368
 #define BUF_SIZE_8KiB 8188
 #define BUF_SIZE_4KiB 4096
 #define BUF_SIZE_2KiB 2048
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
@@ -357,6 +357,7 @@
 	data->fix_mac_speed = tegra_eqos_fix_speed;
 	data->init = tegra_eqos_init;
 	data->bsp_priv = eqos;
+	data->sph_disable = 1;
 
 	err = tegra_eqos_init(pdev, eqos);
 	if (err < 0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c
@@ -71,6 +71,7 @@
 
 static const struct of_device_id dwmac_generic_match[] = {
 	{ .compatible = "st,spear600-gmac"},
+	{ .compatible = "snps,dwmac-3.40a"},
 	{ .compatible = "snps,dwmac-3.50a"},
 	{ .compatible = "snps,dwmac-3.610"},
 	{ .compatible = "snps,dwmac-3.70a"},
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
@@ -288,10 +288,7 @@
 		val &= ~NSS_COMMON_GMAC_CTL_PHY_IFACE_SEL;
 		break;
 	default:
-		dev_err(&pdev->dev, "Unsupported PHY mode: \"%s\"\n",
-			phy_modes(gmac->phy_mode));
-		err = -EINVAL;
-		goto err_remove_config_dt;
+		goto err_unsupported_phy;
 	}
 	regmap_write(gmac->nss_common, NSS_COMMON_GMAC_CTL(gmac->id), val);
 
@@ -308,16 +305,25 @@
 			NSS_COMMON_CLK_SRC_CTRL_OFFSET(gmac->id);
 		break;
 	default:
-		dev_err(&pdev->dev, "Unsupported PHY mode: \"%s\"\n",
-			phy_modes(gmac->phy_mode));
-		err = -EINVAL;
-		goto err_remove_config_dt;
+		goto err_unsupported_phy;
 	}
 	regmap_write(gmac->nss_common, NSS_COMMON_CLK_SRC_CTRL, val);
 
 	/* Enable PTP clock */
 	regmap_read(gmac->nss_common, NSS_COMMON_CLK_GATE, &val);
 	val |= NSS_COMMON_CLK_GATE_PTP_EN(gmac->id);
+	switch (gmac->phy_mode) {
+	case PHY_INTERFACE_MODE_RGMII:
+		val |= NSS_COMMON_CLK_GATE_RGMII_RX_EN(gmac->id) |
+			NSS_COMMON_CLK_GATE_RGMII_TX_EN(gmac->id);
+		break;
+	case PHY_INTERFACE_MODE_SGMII:
+		val |= NSS_COMMON_CLK_GATE_GMII_RX_EN(gmac->id) |
+				NSS_COMMON_CLK_GATE_GMII_TX_EN(gmac->id);
+		break;
+	default:
+		goto err_unsupported_phy;
+	}
 	regmap_write(gmac->nss_common, NSS_COMMON_CLK_GATE, val);
 
 	if (gmac->phy_mode == PHY_INTERFACE_MODE_SGMII) {
@@ -337,6 +343,9 @@
 	plat_dat->has_gmac = true;
 	plat_dat->bsp_priv = gmac;
 	plat_dat->fix_mac_speed = ipq806x_gmac_fix_mac_speed;
+	plat_dat->multicast_filter_bins = 0;
+	plat_dat->tx_fifo_size = 8192;
+	plat_dat->rx_fifo_size = 8192;
 
 	err = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
 	if (err)
@@ -344,6 +353,11 @@
 
 	return 0;
 
+err_unsupported_phy:
+	dev_err(&pdev->dev, "Unsupported PHY mode: \"%s\"\n",
+		phy_modes(gmac->phy_mode));
+	err = -EINVAL;
+
 err_remove_config_dt:
 	stmmac_remove_config_dt(pdev, plat_dat);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
@@ -29,7 +29,6 @@
 #define PRG_ETH0_EXT_RMII_MODE		4
 
 /* mux to choose between fclk_div2 (bit unset) and mpll2 (bit set) */
-#define PRG_ETH0_CLK_M250_SEL_SHIFT	4
 #define PRG_ETH0_CLK_M250_SEL_MASK	GENMASK(4, 4)
 
 #define PRG_ETH0_TXDLY_SHIFT		5
@@ -112,6 +111,15 @@
 	struct device *dev = dwmac->dev;
 	const char *parent_name, *mux_parent_names[MUX_CLK_NUM_PARENTS];
 	struct meson8b_dwmac_clk_configs *clk_configs;
+	static const struct clk_div_table div_table[] = {
+		{ .div = 2, .val = 2, },
+		{ .div = 3, .val = 3, },
+		{ .div = 4, .val = 4, },
+		{ .div = 5, .val = 5, },
+		{ .div = 6, .val = 6, },
+		{ .div = 7, .val = 7, },
+		{ /* end of array */ }
+	};
 
 	clk_configs = devm_kzalloc(dev, sizeof(*clk_configs), GFP_KERNEL);
 	if (!clk_configs)
@@ -134,8 +142,9 @@
 	}
 
 	clk_configs->m250_mux.reg = dwmac->regs + PRG_ETH0;
-	clk_configs->m250_mux.shift = PRG_ETH0_CLK_M250_SEL_SHIFT;
-	clk_configs->m250_mux.mask = PRG_ETH0_CLK_M250_SEL_MASK;
+	clk_configs->m250_mux.shift = __ffs(PRG_ETH0_CLK_M250_SEL_MASK);
+	clk_configs->m250_mux.mask = PRG_ETH0_CLK_M250_SEL_MASK >>
+				     clk_configs->m250_mux.shift;
 	clk = meson8b_dwmac_register_clk(dwmac, "m250_sel", mux_parent_names,
 					 MUX_CLK_NUM_PARENTS, &clk_mux_ops,
 					 &clk_configs->m250_mux.hw);
@@ -146,9 +155,9 @@
 	clk_configs->m250_div.reg = dwmac->regs + PRG_ETH0;
 	clk_configs->m250_div.shift = PRG_ETH0_CLK_M250_DIV_SHIFT;
 	clk_configs->m250_div.width = PRG_ETH0_CLK_M250_DIV_WIDTH;
-	clk_configs->m250_div.flags = CLK_DIVIDER_ONE_BASED |
-				CLK_DIVIDER_ALLOW_ZERO |
-				CLK_DIVIDER_ROUND_CLOSEST;
+	clk_configs->m250_div.table = div_table;
+	clk_configs->m250_div.flags = CLK_DIVIDER_ALLOW_ZERO |
+				      CLK_DIVIDER_ROUND_CLOSEST;
 	clk = meson8b_dwmac_register_clk(dwmac, "m250_div", &parent_name, 1,
 					 &clk_divider_ops,
 					 &clk_configs->m250_div.hw);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
@@ -75,6 +75,11 @@
 	unsigned int value;
 };
 
+struct ethqos_emac_driver_data {
+	const struct ethqos_emac_por *por;
+	unsigned int num_por;
+};
+
 struct qcom_ethqos {
 	struct platform_device *pdev;
 	void __iomem *rgmii_base;
@@ -171,6 +176,11 @@
 	{ .offset = RGMII_IO_MACRO_CONFIG2,	.value = 0x00002060 },
 };
 
+static const struct ethqos_emac_driver_data emac_v2_3_0_data = {
+	.por = emac_v2_3_0_por,
+	.num_por = ARRAY_SIZE(emac_v2_3_0_por),
+};
+
 static int ethqos_dll_configure(struct qcom_ethqos *ethqos)
 {
 	unsigned int val;
@@ -413,6 +423,7 @@
 			dll_lock = rgmii_readl(ethqos, SDC4_STATUS);
 			if (dll_lock & SDC4_STATUS_DLL_LOCK)
 				break;
+			retry--;
 		} while (retry > 0);
 		if (!retry)
 			dev_err(&ethqos->pdev->dev,
@@ -441,6 +452,7 @@
 	struct device_node *np = pdev->dev.of_node;
 	struct plat_stmmacenet_data *plat_dat;
 	struct stmmac_resources stmmac_res;
+	const struct ethqos_emac_driver_data *data;
 	struct qcom_ethqos *ethqos;
 	struct resource *res;
 	int ret;
@@ -470,7 +482,9 @@
 		goto err_mem;
 	}
 
-	ethqos->por = of_device_get_match_data(&pdev->dev);
+	data = of_device_get_match_data(&pdev->dev);
+	ethqos->por = data->por;
+	ethqos->num_por = data->num_por;
 
 	ethqos->rgmii_clk = devm_clk_get(&pdev->dev, "rgmii");
 	if (IS_ERR(ethqos->rgmii_clk)) {
@@ -491,6 +505,8 @@
 	plat_dat->has_gmac4 = 1;
 	plat_dat->pmt = 1;
 	plat_dat->tso_en = of_property_read_bool(np, "snps,tso");
+	if (of_device_is_compatible(np, "qcom,qcs404-ethqos"))
+		plat_dat->rx_clk_runs_in_lpi = 1;
 
 	ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
 	if (ret)
@@ -525,7 +541,7 @@
 }
 
 static const struct of_device_id qcom_ethqos_match[] = {
-	{ .compatible = "qcom,qcs404-ethqos", .data = &emac_v2_3_0_por},
+	{ .compatible = "qcom,qcs404-ethqos", .data = &emac_v2_3_0_data},
 	{ }
 };
 MODULE_DEVICE_TABLE(of, qcom_ethqos_match);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -1411,7 +1411,7 @@
 
 	ret = rk_gmac_clk_init(plat_dat);
 	if (ret)
-		return ret;
+		goto err_remove_config_dt;
 
 	ret = rk_gmac_powerup(plat_dat->bsp_priv);
 	if (ret)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
@@ -18,9 +18,6 @@
 
 #include "altr_tse_pcs.h"
 
-#define SGMII_ADAPTER_CTRL_REG                          0x00
-#define SGMII_ADAPTER_DISABLE                           0x0001
-
 #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII 0x0
 #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII 0x1
 #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII 0x2
@@ -62,14 +59,13 @@
 {
 	struct socfpga_dwmac *dwmac = (struct socfpga_dwmac *)priv;
 	void __iomem *splitter_base = dwmac->splitter_base;
-	void __iomem *tse_pcs_base = dwmac->pcs.tse_pcs_base;
 	void __iomem *sgmii_adapter_base = dwmac->pcs.sgmii_adapter_base;
 	struct device *dev = dwmac->dev;
 	struct net_device *ndev = dev_get_drvdata(dev);
 	struct phy_device *phy_dev = ndev->phydev;
 	u32 val;
 
-	if ((tse_pcs_base) && (sgmii_adapter_base))
+	if (sgmii_adapter_base)
 		writew(SGMII_ADAPTER_DISABLE,
 		       sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG);
 
@@ -93,8 +89,11 @@
 		writel(val, splitter_base + EMAC_SPLITTER_CTRL_REG);
 	}
 
-	if (tse_pcs_base && sgmii_adapter_base)
+	if (phy_dev && sgmii_adapter_base) {
+		writew(SGMII_ADAPTER_ENABLE,
+		       sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG);
 		tse_pcs_fix_mac_speed(&dwmac->pcs, phy_dev, speed);
+	}
 }
 
 static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *dev)
@@ -241,6 +240,8 @@
 	switch (phymode) {
 	case PHY_INTERFACE_MODE_RGMII:
 	case PHY_INTERFACE_MODE_RGMII_ID:
+	case PHY_INTERFACE_MODE_RGMII_RXID:
+	case PHY_INTERFACE_MODE_RGMII_TXID:
 		*val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII;
 		break;
 	case PHY_INTERFACE_MODE_MII:
@@ -289,16 +290,19 @@
 	    phymode == PHY_INTERFACE_MODE_MII ||
 	    phymode == PHY_INTERFACE_MODE_GMII ||
 	    phymode == PHY_INTERFACE_MODE_SGMII) {
-		ctrl |= SYSMGR_EMACGRP_CTRL_PTP_REF_CLK_MASK << (reg_shift / 2);
 		regmap_read(sys_mgr_base_addr, SYSMGR_FPGAGRP_MODULE_REG,
 			    &module);
 		module |= (SYSMGR_FPGAGRP_MODULE_EMAC << (reg_shift / 2));
 		regmap_write(sys_mgr_base_addr, SYSMGR_FPGAGRP_MODULE_REG,
 			     module);
-	} else {
-		ctrl &= ~(SYSMGR_EMACGRP_CTRL_PTP_REF_CLK_MASK << (reg_shift / 2));
 	}
 
+	if (dwmac->f2h_ptp_ref_clk)
+		ctrl |= SYSMGR_EMACGRP_CTRL_PTP_REF_CLK_MASK << (reg_shift / 2);
+	else
+		ctrl &= ~(SYSMGR_EMACGRP_CTRL_PTP_REF_CLK_MASK <<
+			  (reg_shift / 2));
+
 	regmap_write(sys_mgr_base_addr, reg_offset, ctrl);
 
 	/* Deassert reset for the phy configuration to be sampled by
@@ -422,6 +426,8 @@
 	plat_dat->bsp_priv = dwmac;
 	plat_dat->fix_mac_speed = socfpga_dwmac_fix_mac_speed;
 
+	plat_dat->riwt_off = 1;
+
 	ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
 	if (ret)
 		goto err_remove_config_dt;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
@@ -111,6 +111,7 @@
 	int (*parse_data)(struct stm32_dwmac *dwmac,
 			  struct device *dev);
 	u32 syscfg_eth_mask;
+	bool clk_rx_enable_in_suspend;
 };
 
 static int stm32_dwmac_init(struct plat_stmmacenet_data *plat_dat)
@@ -128,7 +129,8 @@
 	if (ret)
 		return ret;
 
-	if (!dwmac->dev->power.is_suspended) {
+	if (!dwmac->ops->clk_rx_enable_in_suspend ||
+	    !dwmac->dev->power.is_suspended) {
 		ret = clk_prepare_enable(dwmac->clk_rx);
 		if (ret) {
 			clk_disable_unprepare(dwmac->clk_tx);
@@ -508,7 +510,8 @@
 	.suspend = stm32mp1_suspend,
 	.resume = stm32mp1_resume,
 	.parse_data = stm32mp1_parse_data,
-	.syscfg_eth_mask = SYSCFG_MP1_ETH_MASK
+	.syscfg_eth_mask = SYSCFG_MP1_ETH_MASK,
+	.clk_rx_enable_in_suspend = true
 };
 
 static const struct of_device_id stm32_dwmac_match[] = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
@@ -64,6 +64,7 @@
  * @variant:	reference to the current board variant
  * @regmap:	regmap for using the syscon
  * @internal_phy_powered: Does the internal PHY is enabled
+ * @use_internal_phy: Is the internal PHY selected for use
  * @mux_handle:	Internal pointer used by mdio-mux lib
  */
 struct sunxi_priv_data {
@@ -74,6 +75,7 @@
 	const struct emac_variant *variant;
 	struct regmap_field *regmap_field;
 	bool internal_phy_powered;
+	bool use_internal_phy;
 	void *mux_handle;
 };
 
@@ -523,8 +525,11 @@
 	.dma_interrupt = sun8i_dwmac_dma_interrupt,
 };
 
+static int sun8i_dwmac_power_internal_phy(struct stmmac_priv *priv);
+
 static int sun8i_dwmac_init(struct platform_device *pdev, void *priv)
 {
+	struct net_device *ndev = platform_get_drvdata(pdev);
 	struct sunxi_priv_data *gmac = priv;
 	int ret;
 
@@ -538,13 +543,25 @@
 
 	ret = clk_prepare_enable(gmac->tx_clk);
 	if (ret) {
-		if (gmac->regulator)
-			regulator_disable(gmac->regulator);
 		dev_err(&pdev->dev, "Could not enable AHB clock\n");
-		return ret;
+		goto err_disable_regulator;
+	}
+
+	if (gmac->use_internal_phy) {
+		ret = sun8i_dwmac_power_internal_phy(netdev_priv(ndev));
+		if (ret)
+			goto err_disable_clk;
 	}
 
 	return 0;
+
+err_disable_clk:
+	clk_disable_unprepare(gmac->tx_clk);
+err_disable_regulator:
+	if (gmac->regulator)
+		regulator_disable(gmac->regulator);
+
+	return ret;
 }
 
 static void sun8i_dwmac_core_init(struct mac_device_info *hw,
@@ -701,7 +718,7 @@
 
 	if (err) {
 		dev_err(priv->device, "EMAC reset timeout\n");
-		return -EFAULT;
+		return err;
 	}
 	return 0;
 }
@@ -815,7 +832,6 @@
 	struct sunxi_priv_data *gmac = priv->plat->bsp_priv;
 	u32 reg, val;
 	int ret = 0;
-	bool need_power_ephy = false;
 
 	if (current_child ^ desired_child) {
 		regmap_field_read(gmac->regmap_field, &reg);
@@ -823,13 +839,12 @@
 		case DWMAC_SUN8I_MDIO_MUX_INTERNAL_ID:
 			dev_info(priv->device, "Switch mux to internal PHY");
 			val = (reg & ~H3_EPHY_MUX_MASK) | H3_EPHY_SELECT;
-
-			need_power_ephy = true;
+			gmac->use_internal_phy = true;
 			break;
 		case DWMAC_SUN8I_MDIO_MUX_EXTERNAL_ID:
 			dev_info(priv->device, "Switch mux to external PHY");
 			val = (reg & ~H3_EPHY_MUX_MASK) | H3_EPHY_SHUTDOWN;
-			need_power_ephy = false;
+			gmac->use_internal_phy = false;
 			break;
 		default:
 			dev_err(priv->device, "Invalid child ID %x\n",
@@ -837,7 +852,7 @@
 			return -EINVAL;
 		}
 		regmap_field_write(gmac->regmap_field, val);
-		if (need_power_ephy) {
+		if (gmac->use_internal_phy) {
 			ret = sun8i_dwmac_power_internal_phy(priv);
 			if (ret)
 				return ret;
@@ -864,6 +879,7 @@
 
 	ret = mdio_mux_init(priv->device, mdio_mux, mdio_mux_syscon_switch_fn,
 			    &gmac->mux_handle, priv, priv->mii);
+	of_node_put(mdio_mux);
 	return ret;
 }
 
@@ -957,6 +973,9 @@
 		/* default */
 		break;
 	case PHY_INTERFACE_MODE_RGMII:
+	case PHY_INTERFACE_MODE_RGMII_ID:
+	case PHY_INTERFACE_MODE_RGMII_RXID:
+	case PHY_INTERFACE_MODE_RGMII_TXID:
 		reg |= SYSCON_EPIT | SYSCON_ETCS_INT_GMII;
 		break;
 	case PHY_INTERFACE_MODE_RMII:
@@ -985,17 +1004,12 @@
 	struct sunxi_priv_data *gmac = priv;
 
 	if (gmac->variant->soc_has_internal_phy) {
-		/* sun8i_dwmac_exit could be called with mdiomux uninit */
-		if (gmac->mux_handle)
-			mdio_mux_uninit(gmac->mux_handle);
 		if (gmac->internal_phy_powered)
 			sun8i_dwmac_unpower_internal_phy(gmac);
 	}
 
 	sun8i_dwmac_unset_syscon(gmac);
 
-	reset_control_put(gmac->rst_ephy);
-
 	clk_disable_unprepare(gmac->tx_clk);
 
 	if (gmac->regulator)
@@ -1193,6 +1207,8 @@
 	plat_dat->init = sun8i_dwmac_init;
 	plat_dat->exit = sun8i_dwmac_exit;
 	plat_dat->setup = sun8i_dwmac_setup;
+	plat_dat->tx_fifo_size = 4096;
+	plat_dat->rx_fifo_size = 16384;
 
 	ret = sun8i_dwmac_init(pdev, plat_dat->bsp_priv);
 	if (ret)
@@ -1224,12 +1240,32 @@
 
 	return ret;
 dwmac_mux:
+	reset_control_put(gmac->rst_ephy);
+	clk_put(gmac->ephy_clk);
 	sun8i_dwmac_unset_syscon(gmac);
 dwmac_exit:
 	stmmac_pltfr_remove(pdev);
 return ret;
 }
 
+static int sun8i_dwmac_remove(struct platform_device *pdev)
+{
+	struct net_device *ndev = platform_get_drvdata(pdev);
+	struct stmmac_priv *priv = netdev_priv(ndev);
+	struct sunxi_priv_data *gmac = priv->plat->bsp_priv;
+
+	if (gmac->variant->soc_has_internal_phy) {
+		mdio_mux_uninit(gmac->mux_handle);
+		sun8i_dwmac_unpower_internal_phy(gmac);
+		reset_control_put(gmac->rst_ephy);
+		clk_put(gmac->ephy_clk);
+	}
+
+	stmmac_pltfr_remove(pdev);
+
+	return 0;
+}
+
 static const struct of_device_id sun8i_dwmac_match[] = {
 	{ .compatible = "allwinner,sun8i-h3-emac",
 		.data = &emac_variant_h3 },
@@ -1249,7 +1285,7 @@
 
 static struct platform_driver sun8i_dwmac_driver = {
 	.probe  = sun8i_dwmac_probe,
-	.remove = stmmac_pltfr_remove,
+	.remove = sun8i_dwmac_remove,
 	.driver = {
 		.name           = "dwmac-sun8i",
 		.pm		= &stmmac_pltfr_pm_ops,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
@@ -30,7 +30,7 @@
 static int sun7i_gmac_init(struct platform_device *pdev, void *priv)
 {
 	struct sunxi_priv_data *gmac = priv;
-	int ret;
+	int ret = 0;
 
 	if (gmac->regulator) {
 		ret = regulator_enable(gmac->regulator);
@@ -44,18 +44,18 @@
 	 * rate, which then uses the auto-reparenting feature of the
 	 * clock driver, and enabling/disabling the clock.
 	 */
-	if (gmac->interface == PHY_INTERFACE_MODE_RGMII) {
+	if (phy_interface_mode_is_rgmii(gmac->interface)) {
 		clk_set_rate(gmac->tx_clk, SUN7I_GMAC_GMII_RGMII_RATE);
 		clk_prepare_enable(gmac->tx_clk);
 		gmac->clk_enabled = 1;
 	} else {
 		clk_set_rate(gmac->tx_clk, SUN7I_GMAC_MII_RATE);
 		ret = clk_prepare(gmac->tx_clk);
-		if (ret)
-			return ret;
+		if (ret && gmac->regulator)
+			regulator_disable(gmac->regulator);
 	}
 
-	return 0;
+	return ret;
 }
 
 static void sun7i_gmac_exit(struct platform_device *pdev, void *priv)
@@ -146,6 +146,8 @@
 	plat_dat->init = sun7i_gmac_init;
 	plat_dat->exit = sun7i_gmac_exit;
 	plat_dat->fix_mac_speed = sun7i_fix_speed;
+	plat_dat->tx_fifo_size = 4096;
+	plat_dat->rx_fifo_size = 16384;
 
 	ret = sun7i_gmac_init(pdev, plat_dat->bsp_priv);
 	if (ret)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
@@ -76,10 +76,10 @@
 #define LPI_CTRL_STATUS_TLPIEN	0x00000001	/* Transmit LPI Entry */
 
 /* GMAC HW ADDR regs */
-#define GMAC_ADDR_HIGH(reg)	(((reg > 15) ? 0x00000800 : 0x00000040) + \
-				(reg * 8))
-#define GMAC_ADDR_LOW(reg)	(((reg > 15) ? 0x00000804 : 0x00000044) + \
-				(reg * 8))
+#define GMAC_ADDR_HIGH(reg)	((reg > 15) ? 0x00000800 + (reg - 16) * 8 : \
+				 0x00000040 + (reg * 8))
+#define GMAC_ADDR_LOW(reg)	((reg > 15) ? 0x00000804 + (reg - 16) * 8 : \
+				 0x00000044 + (reg * 8))
 #define GMAC_MAX_PERFECT_ADDRESSES	1
 
 #define GMAC_PCS_BASE		0x000000c0	/* PCS register base */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
@@ -24,6 +24,7 @@
 static void dwmac1000_core_init(struct mac_device_info *hw,
 				struct net_device *dev)
 {
+	struct stmmac_priv *priv = netdev_priv(dev);
 	void __iomem *ioaddr = hw->pcsr;
 	u32 value = readl(ioaddr + GMAC_CONTROL);
 	int mtu = dev->mtu;
@@ -35,7 +36,7 @@
 	 * Broadcom tags can look like invalid LLC/SNAP packets and cause the
 	 * hardware to truncate packets on reception.
 	 */
-	if (netdev_uses_dsa(dev))
+	if (netdev_uses_dsa(dev) || !priv->plat->enh_desc)
 		value &= ~GMAC_CONTROL_ACS;
 
 	if (mtu > 1500)
@@ -165,6 +166,9 @@
 		value = GMAC_FRAME_FILTER_PR | GMAC_FRAME_FILTER_PCF;
 	} else if (dev->flags & IFF_ALLMULTI) {
 		value = GMAC_FRAME_FILTER_PM;	/* pass all multi */
+	} else if (!netdev_mc_empty(dev) && (mcbitslog2 == 0)) {
+		/* Fall back to all multicast if we've no filter */
+		value = GMAC_FRAME_FILTER_PM;
 	} else if (!netdev_mc_empty(dev)) {
 		struct netdev_hw_addr *ha;
 
@@ -208,7 +212,7 @@
 			reg++;
 		}
 
-		while (reg <= perfect_addr_number) {
+		while (reg < perfect_addr_number) {
 			writel(0, ioaddr + GMAC_ADDR_HIGH(reg));
 			writel(0, ioaddr + GMAC_ADDR_LOW(reg));
 			reg++;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
@@ -218,11 +218,18 @@
 				readl(ioaddr + DMA_BUS_MODE + i * 4);
 }
 
-static void dwmac1000_get_hw_feature(void __iomem *ioaddr,
-				     struct dma_features *dma_cap)
+static int dwmac1000_get_hw_feature(void __iomem *ioaddr,
+				    struct dma_features *dma_cap)
 {
 	u32 hw_cap = readl(ioaddr + DMA_HW_FEATURE);
 
+	if (!hw_cap) {
+		/* 0x00000000 is the value read on old hardware that does not
+		 * implement this register
+		 */
+		return -EOPNOTSUPP;
+	}
+
 	dma_cap->mbps_10_100 = (hw_cap & DMA_HW_FEAT_MIISEL);
 	dma_cap->mbps_1000 = (hw_cap & DMA_HW_FEAT_GMIISEL) >> 1;
 	dma_cap->half_duplex = (hw_cap & DMA_HW_FEAT_HDSEL) >> 2;
@@ -252,6 +259,8 @@
 	dma_cap->number_tx_channel = (hw_cap & DMA_HW_FEAT_TXCHCNT) >> 22;
 	/* Alternate (enhanced) DESC mode */
 	dma_cap->enh_desc = (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24;
+
+	return 0;
 }
 
 static void dwmac1000_rx_watchdog(void __iomem *ioaddr, u32 riwt,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
@@ -75,19 +75,41 @@
 				     u32 prio, u32 queue)
 {
 	void __iomem *ioaddr = hw->pcsr;
-	u32 base_register;
-	u32 value;
+	u32 clear_mask = 0;
+	u32 ctrl2, ctrl3;
+	int i;
+
+	ctrl2 = readl(ioaddr + GMAC_RXQ_CTRL2);
+	ctrl3 = readl(ioaddr + GMAC_RXQ_CTRL3);
+
+	/* The software must ensure that the same priority
+	 * is not mapped to multiple Rx queues
+	 */
+	for (i = 0; i < 4; i++)
+		clear_mask |= ((prio << GMAC_RXQCTRL_PSRQX_SHIFT(i)) &
+						GMAC_RXQCTRL_PSRQX_MASK(i));
+
+	ctrl2 &= ~clear_mask;
+	ctrl3 &= ~clear_mask;
+
+	/* First assign new priorities to a queue, then
+	 * clear them from others queues
+	 */
+	if (queue < 4) {
+		ctrl2 |= (prio << GMAC_RXQCTRL_PSRQX_SHIFT(queue)) &
+						GMAC_RXQCTRL_PSRQX_MASK(queue);
 
-	base_register = (queue < 4) ? GMAC_RXQ_CTRL2 : GMAC_RXQ_CTRL3;
-	if (queue >= 4)
+		writel(ctrl2, ioaddr + GMAC_RXQ_CTRL2);
+		writel(ctrl3, ioaddr + GMAC_RXQ_CTRL3);
+	} else {
 		queue -= 4;
 
-	value = readl(ioaddr + base_register);
-
-	value &= ~GMAC_RXQCTRL_PSRQX_MASK(queue);
-	value |= (prio << GMAC_RXQCTRL_PSRQX_SHIFT(queue)) &
+		ctrl3 |= (prio << GMAC_RXQCTRL_PSRQX_SHIFT(queue)) &
 						GMAC_RXQCTRL_PSRQX_MASK(queue);
-	writel(value, ioaddr + base_register);
+
+		writel(ctrl3, ioaddr + GMAC_RXQ_CTRL3);
+		writel(ctrl2, ioaddr + GMAC_RXQ_CTRL2);
+	}
 }
 
 static void dwmac4_tx_queue_priority(struct mac_device_info *hw,
@@ -215,6 +237,9 @@
 	if (queue == 0 || queue == 4) {
 		value &= ~MTL_RXQ_DMA_Q04MDMACH_MASK;
 		value |= MTL_RXQ_DMA_Q04MDMACH(chan);
+	} else if (queue > 4) {
+		value &= ~MTL_RXQ_DMA_QXMDMACH_MASK(queue - 4);
+		value |= MTL_RXQ_DMA_QXMDMACH(chan, queue - 4);
 	} else {
 		value &= ~MTL_RXQ_DMA_QXMDMACH_MASK(queue);
 		value |= MTL_RXQ_DMA_QXMDMACH(chan, queue);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
@@ -116,6 +116,23 @@
 	       ioaddr + DMA_CHAN_INTR_ENA(chan));
 }
 
+static void dwmac410_dma_init_channel(void __iomem *ioaddr,
+				      struct stmmac_dma_cfg *dma_cfg, u32 chan)
+{
+	u32 value;
+
+	/* common channel control register config */
+	value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
+	if (dma_cfg->pblx8)
+		value = value | DMA_BUS_MODE_PBL;
+
+	writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
+
+	/* Mask interrupts by writing to CSR7 */
+	writel(DMA_CHAN_INTR_DEFAULT_MASK_4_10,
+	       ioaddr + DMA_CHAN_INTR_ENA(chan));
+}
+
 static void dwmac4_dma_init(void __iomem *ioaddr,
 			    struct stmmac_dma_cfg *dma_cfg, int atds)
 {
@@ -194,7 +211,7 @@
 				       u32 channel, int fifosz, u8 qmode)
 {
 	unsigned int rqs = fifosz / 256 - 1;
-	u32 mtl_rx_op, mtl_rx_int;
+	u32 mtl_rx_op;
 
 	mtl_rx_op = readl(ioaddr + MTL_CHAN_RX_OP_MODE(channel));
 
@@ -265,11 +282,6 @@
 	}
 
 	writel(mtl_rx_op, ioaddr + MTL_CHAN_RX_OP_MODE(channel));
-
-	/* Enable MTL RX overflow */
-	mtl_rx_int = readl(ioaddr + MTL_CHAN_INT_CTRL(channel));
-	writel(mtl_rx_int | MTL_RX_OVERFLOW_INT_EN,
-	       ioaddr + MTL_CHAN_INT_CTRL(channel));
 }
 
 static void dwmac4_dma_tx_chan_op_mode(void __iomem *ioaddr, int mode,
@@ -324,8 +336,8 @@
 	writel(mtl_tx_op, ioaddr +  MTL_CHAN_TX_OP_MODE(channel));
 }
 
-static void dwmac4_get_hw_feature(void __iomem *ioaddr,
-				  struct dma_features *dma_cap)
+static int dwmac4_get_hw_feature(void __iomem *ioaddr,
+				 struct dma_features *dma_cap)
 {
 	u32 hw_cap = readl(ioaddr + GMAC_HW_FEATURE0);
 
@@ -388,6 +400,8 @@
 	dma_cap->frpbs = (hw_cap & GMAC_HW_FEAT_FRPBS) >> 11;
 	dma_cap->frpsel = (hw_cap & GMAC_HW_FEAT_FRPSEL) >> 10;
 	dma_cap->dvlan = (hw_cap & GMAC_HW_FEAT_DVLAN) >> 5;
+
+	return 0;
 }
 
 /* Enable/disable TSO feature and set MSS */
@@ -462,7 +476,7 @@
 const struct stmmac_dma_ops dwmac410_dma_ops = {
 	.reset = dwmac4_dma_reset,
 	.init = dwmac4_dma_init,
-	.init_chan = dwmac4_dma_init_channel,
+	.init_chan = dwmac410_dma_init_channel,
 	.init_rx_chan = dwmac4_dma_init_rx_chan,
 	.init_tx_chan = dwmac4_dma_init_tx_chan,
 	.axi = dwmac4_dma_axi,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
@@ -60,10 +60,6 @@
 
 	value &= ~DMA_CONTROL_ST;
 	writel(value, ioaddr + DMA_CHAN_TX_CONTROL(chan));
-
-	value = readl(ioaddr + GMAC_CONFIG);
-	value &= ~GMAC_CONFIG_TE;
-	writel(value, ioaddr + GMAC_CONFIG);
 }
 
 void dwmac4_dma_start_rx(void __iomem *ioaddr, u32 chan)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/dwmac5.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/dwmac5.c
@@ -520,9 +520,9 @@
 		return 0;
 	}
 
-	val |= PPSCMDx(index, 0x2);
 	val |= TRGTMODSELx(index, 0x2);
 	val |= PPSEN0;
+	writel(val, ioaddr + MAC_PPS_CONTROL);
 
 	writel(cfg->start.tv_sec, ioaddr + MAC_PPSx_TARGET_TIME_SEC(index));
 
@@ -547,6 +547,7 @@
 	writel(period - 1, ioaddr + MAC_PPSx_WIDTH(index));
 
 	/* Finally, activate it */
+	val |= PPSCMDx(index, 0x2);
 	writel(val, ioaddr + MAC_PPS_CONTROL);
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
@@ -128,6 +128,7 @@
 
 #define NUM_DWMAC100_DMA_REGS	9
 #define NUM_DWMAC1000_DMA_REGS	23
+#define NUM_DWMAC4_DMA_REGS	27
 
 void dwmac_enable_dma_transmission(void __iomem *ioaddr);
 void dwmac_enable_dma_irq(void __iomem *ioaddr, u32 chan);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
@@ -212,7 +212,7 @@
 	((val) << XGMAC_PPS_MINIDX(x))
 #define XGMAC_PPSCMD_START		0x2
 #define XGMAC_PPSCMD_STOP		0x5
-#define XGMAC_PPSEN0			BIT(4)
+#define XGMAC_PPSENx(x)			BIT(4 + (x) * 8)
 #define XGMAC_PPSx_TARGET_TIME_SEC(x)	(0x00000d80 + (x) * 0x10)
 #define XGMAC_PPSx_TARGET_TIME_NSEC(x)	(0x00000d84 + (x) * 0x10)
 #define XGMAC_TRGTBUSY0			BIT(31)
@@ -256,6 +256,8 @@
 #define XGMAC_RXCEIE			BIT(4)
 #define XGMAC_TXCEIE			BIT(0)
 #define XGMAC_MTL_ECC_INT_STATUS	0x000010cc
+#define XGMAC_MTL_DPP_CONTROL		0x000010e0
+#define XGMAC_DPP_DISABLE		BIT(0)
 #define XGMAC_MTL_TXQ_OPMODE(x)		(0x00001100 + (0x80 * (x)))
 #define XGMAC_TQS			GENMASK(25, 16)
 #define XGMAC_TQS_SHIFT			16
@@ -331,6 +333,7 @@
 #define XGMAC_DCEIE			BIT(1)
 #define XGMAC_TCEIE			BIT(0)
 #define XGMAC_DMA_ECC_INT_STATUS	0x0000306c
+#define XGMAC_DMA_DPP_INT_STATUS	0x00003074
 #define XGMAC_DMA_CH_CONTROL(x)		(0x00003100 + (0x80 * (x)))
 #define XGMAC_SPH			BIT(24)
 #define XGMAC_PBLx8			BIT(16)
@@ -343,6 +346,8 @@
 #define XGMAC_DMA_CH_RX_CONTROL(x)	(0x00003108 + (0x80 * (x)))
 #define XGMAC_RxPBL			GENMASK(21, 16)
 #define XGMAC_RxPBL_SHIFT		16
+#define XGMAC_RBSZ			GENMASK(14, 1)
+#define XGMAC_RBSZ_SHIFT		1
 #define XGMAC_RXST			BIT(0)
 #define XGMAC_DMA_CH_TxDESC_HADDR(x)	(0x00003110 + (0x80 * (x)))
 #define XGMAC_DMA_CH_TxDESC_LADDR(x)	(0x00003114 + (0x80 * (x)))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
@@ -96,17 +96,41 @@
 				   u32 queue)
 {
 	void __iomem *ioaddr = hw->pcsr;
-	u32 value, reg;
+	u32 clear_mask = 0;
+	u32 ctrl2, ctrl3;
+	int i;
 
-	reg = (queue < 4) ? XGMAC_RXQ_CTRL2 : XGMAC_RXQ_CTRL3;
-	if (queue >= 4)
+	ctrl2 = readl(ioaddr + XGMAC_RXQ_CTRL2);
+	ctrl3 = readl(ioaddr + XGMAC_RXQ_CTRL3);
+
+	/* The software must ensure that the same priority
+	 * is not mapped to multiple Rx queues
+	 */
+	for (i = 0; i < 4; i++)
+		clear_mask |= ((prio << XGMAC_PSRQ_SHIFT(i)) &
+						XGMAC_PSRQ(i));
+
+	ctrl2 &= ~clear_mask;
+	ctrl3 &= ~clear_mask;
+
+	/* First assign new priorities to a queue, then
+	 * clear them from others queues
+	 */
+	if (queue < 4) {
+		ctrl2 |= (prio << XGMAC_PSRQ_SHIFT(queue)) &
+						XGMAC_PSRQ(queue);
+
+		writel(ctrl2, ioaddr + XGMAC_RXQ_CTRL2);
+		writel(ctrl3, ioaddr + XGMAC_RXQ_CTRL3);
+	} else {
 		queue -= 4;
 
-	value = readl(ioaddr + reg);
-	value &= ~XGMAC_PSRQ(queue);
-	value |= (prio << XGMAC_PSRQ_SHIFT(queue)) & XGMAC_PSRQ(queue);
+		ctrl3 |= (prio << XGMAC_PSRQ_SHIFT(queue)) &
+						XGMAC_PSRQ(queue);
 
-	writel(value, ioaddr + reg);
+		writel(ctrl3, ioaddr + XGMAC_RXQ_CTRL3);
+		writel(ctrl2, ioaddr + XGMAC_RXQ_CTRL2);
+	}
 }
 
 static void dwxgmac2_tx_queue_prio(struct mac_device_info *hw, u32 prio,
@@ -757,6 +781,44 @@
 	{ false, "UNKNOWN", "Unknown Error" }, /* 31 */
 };
 
+#define DPP_RX_ERR "Read Rx Descriptor Parity checker Error"
+#define DPP_TX_ERR "Read Tx Descriptor Parity checker Error"
+
+static const struct dwxgmac3_error_desc dwxgmac3_dma_dpp_errors[32] = {
+	{ true, "TDPES0", DPP_TX_ERR },
+	{ true, "TDPES1", DPP_TX_ERR },
+	{ true, "TDPES2", DPP_TX_ERR },
+	{ true, "TDPES3", DPP_TX_ERR },
+	{ true, "TDPES4", DPP_TX_ERR },
+	{ true, "TDPES5", DPP_TX_ERR },
+	{ true, "TDPES6", DPP_TX_ERR },
+	{ true, "TDPES7", DPP_TX_ERR },
+	{ true, "TDPES8", DPP_TX_ERR },
+	{ true, "TDPES9", DPP_TX_ERR },
+	{ true, "TDPES10", DPP_TX_ERR },
+	{ true, "TDPES11", DPP_TX_ERR },
+	{ true, "TDPES12", DPP_TX_ERR },
+	{ true, "TDPES13", DPP_TX_ERR },
+	{ true, "TDPES14", DPP_TX_ERR },
+	{ true, "TDPES15", DPP_TX_ERR },
+	{ true, "RDPES0", DPP_RX_ERR },
+	{ true, "RDPES1", DPP_RX_ERR },
+	{ true, "RDPES2", DPP_RX_ERR },
+	{ true, "RDPES3", DPP_RX_ERR },
+	{ true, "RDPES4", DPP_RX_ERR },
+	{ true, "RDPES5", DPP_RX_ERR },
+	{ true, "RDPES6", DPP_RX_ERR },
+	{ true, "RDPES7", DPP_RX_ERR },
+	{ true, "RDPES8", DPP_RX_ERR },
+	{ true, "RDPES9", DPP_RX_ERR },
+	{ true, "RDPES10", DPP_RX_ERR },
+	{ true, "RDPES11", DPP_RX_ERR },
+	{ true, "RDPES12", DPP_RX_ERR },
+	{ true, "RDPES13", DPP_RX_ERR },
+	{ true, "RDPES14", DPP_RX_ERR },
+	{ true, "RDPES15", DPP_RX_ERR },
+};
+
 static void dwxgmac3_handle_dma_err(struct net_device *ndev,
 				    void __iomem *ioaddr, bool correctable,
 				    struct stmmac_safety_stats *stats)
@@ -768,6 +830,13 @@
 
 	dwxgmac3_log_error(ndev, value, correctable, "DMA",
 			   dwxgmac3_dma_errors, STAT_OFF(dma_errors), stats);
+
+	value = readl(ioaddr + XGMAC_DMA_DPP_INT_STATUS);
+	writel(value, ioaddr + XGMAC_DMA_DPP_INT_STATUS);
+
+	dwxgmac3_log_error(ndev, value, false, "DMA_DPP",
+			   dwxgmac3_dma_dpp_errors,
+			   STAT_OFF(dma_dpp_errors), stats);
 }
 
 static int dwxgmac3_safety_feat_config(void __iomem *ioaddr, unsigned int asp)
@@ -804,6 +873,12 @@
 	value |= XGMAC_TMOUTEN; /* FSM Timeout Feature */
 	writel(value, ioaddr + XGMAC_MAC_FSM_CONTROL);
 
+	/* 5. Enable Data Path Parity Protection */
+	value = readl(ioaddr + XGMAC_MTL_DPP_CONTROL);
+	/* already enabled by default, explicit enable it again */
+	value &= ~XGMAC_DPP_DISABLE;
+	writel(value, ioaddr + XGMAC_MTL_DPP_CONTROL);
+
 	return 0;
 }
 
@@ -837,7 +912,11 @@
 		ret |= !corr;
 	}
 
-	err = dma & (XGMAC_DEUIS | XGMAC_DECIS);
+	/* DMA_DPP_Interrupt_Status is indicated by MCSIS bit in
+	 * DMA_Safety_Interrupt_Status, so we handle DMA Data Path
+	 * Parity Errors here
+	 */
+	err = dma & (XGMAC_DEUIS | XGMAC_DECIS | XGMAC_MCSIS);
 	corr = dma & XGMAC_DECIS;
 	if (err) {
 		dwxgmac3_handle_dma_err(ndev, ioaddr, corr, stats);
@@ -853,6 +932,7 @@
 	{ dwxgmac3_mac_errors },
 	{ dwxgmac3_mtl_errors },
 	{ dwxgmac3_dma_errors },
+	{ dwxgmac3_dma_dpp_errors },
 };
 
 static int dwxgmac3_safety_feat_dump(struct stmmac_safety_stats *stats,
@@ -1101,7 +1181,19 @@
 
 	val |= XGMAC_PPSCMDx(index, XGMAC_PPSCMD_START);
 	val |= XGMAC_TRGTMODSELx(index, XGMAC_PPSCMD_START);
-	val |= XGMAC_PPSEN0;
+
+	/* XGMAC Core has 4 PPS outputs at most.
+	 *
+	 * Prior XGMAC Core 3.20, Fixed mode or Flexible mode are selectable for
+	 * PPS0 only via PPSEN0. PPS{1,2,3} are in Flexible mode by default,
+	 * and can not be switched to Fixed mode, since PPSEN{1,2,3} are
+	 * read-only reserved to 0.
+	 * But we always set PPSEN{1,2,3} do not make things worse ;-)
+	 *
+	 * From XGMAC Core 3.20 and later, PPSEN{0,1,2,3} are writable and must
+	 * be set, or the PPS outputs stay in Fixed PPS mode by default.
+	 */
+	val |= XGMAC_PPSENx(index);
 
 	writel(cfg->start.tv_sec, ioaddr + XGMAC_PPSx_TARGET_TIME_SEC(index));
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
@@ -356,8 +356,8 @@
 	return ret;
 }
 
-static void dwxgmac2_get_hw_feature(void __iomem *ioaddr,
-				    struct dma_features *dma_cap)
+static int dwxgmac2_get_hw_feature(void __iomem *ioaddr,
+				   struct dma_features *dma_cap)
 {
 	u32 hw_cap;
 
@@ -425,6 +425,8 @@
 	dma_cap->frpes = (hw_cap & XGMAC_HWFEAT_FRPES) >> 11;
 	dma_cap->frpbs = (hw_cap & XGMAC_HWFEAT_FRPPB) >> 9;
 	dma_cap->frpsel = (hw_cap & XGMAC_HWFEAT_FRPSEL) >> 3;
+
+	return 0;
 }
 
 static void dwxgmac2_rx_watchdog(void __iomem *ioaddr, u32 riwt, u32 nchan)
@@ -489,7 +491,8 @@
 	u32 value;
 
 	value = readl(ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan));
-	value |= bfsize << 1;
+	value &= ~XGMAC_RBSZ;
+	value |= bfsize << XGMAC_RBSZ_SHIFT;
 	writel(value, ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan));
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/hwif.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/hwif.h
@@ -196,8 +196,8 @@
 	int (*dma_interrupt) (void __iomem *ioaddr,
 			      struct stmmac_extra_stats *x, u32 chan);
 	/* If supported then get the optional core features */
-	void (*get_hw_feature)(void __iomem *ioaddr,
-			       struct dma_features *dma_cap);
+	int (*get_hw_feature)(void __iomem *ioaddr,
+			      struct dma_features *dma_cap);
 	/* Program the HW RX Watchdog */
 	void (*rx_watchdog)(void __iomem *ioaddr, u32 riwt, u32 number_chan);
 	void (*set_tx_ring_len)(void __iomem *ioaddr, u32 len, u32 chan);
@@ -247,7 +247,7 @@
 #define stmmac_dma_interrupt_status(__priv, __args...) \
 	stmmac_do_callback(__priv, dma, dma_interrupt, __args)
 #define stmmac_get_hw_feature(__priv, __args...) \
-	stmmac_do_void_callback(__priv, dma, get_hw_feature, __args)
+	stmmac_do_callback(__priv, dma, get_hw_feature, __args)
 #define stmmac_rx_watchdog(__priv, __args...) \
 	stmmac_do_void_callback(__priv, dma, rx_watchdog, __args)
 #define stmmac_set_tx_ring_len(__priv, __args...) \
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/mmc_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/mmc_core.c
@@ -170,8 +170,10 @@
 #define MMC_XGMAC_RX_DISCARD_OCT_GB	0x1b4
 #define MMC_XGMAC_RX_ALIGN_ERR_PKT	0x1bc
 
+#define MMC_XGMAC_TX_FPE_INTR_MASK	0x204
 #define MMC_XGMAC_TX_FPE_FRAG		0x208
 #define MMC_XGMAC_TX_HOLD_REQ		0x20c
+#define MMC_XGMAC_RX_FPE_INTR_MASK	0x224
 #define MMC_XGMAC_RX_PKT_ASSEMBLY_ERR	0x228
 #define MMC_XGMAC_RX_PKT_SMD_ERR	0x22c
 #define MMC_XGMAC_RX_PKT_ASSEMBLY_OK	0x230
@@ -336,6 +338,8 @@
 {
 	writel(0x0, mmcaddr + MMC_RX_INTR_MASK);
 	writel(0x0, mmcaddr + MMC_TX_INTR_MASK);
+	writel(MMC_DEFAULT_MASK, mmcaddr + MMC_XGMAC_TX_FPE_INTR_MASK);
+	writel(MMC_DEFAULT_MASK, mmcaddr + MMC_XGMAC_RX_FPE_INTR_MASK);
 	writel(MMC_DEFAULT_MASK, mmcaddr + MMC_XGMAC_RX_IPC_INTR_MASK);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -191,6 +191,7 @@
 	u32 msg_enable;
 	int wolopts;
 	int wol_irq;
+	bool wol_irq_disabled;
 	int clk_csr;
 	struct timer_list eee_ctrl_timer;
 	int lpi_irq;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -21,10 +21,18 @@
 #include "dwxgmac2.h"
 
 #define REG_SPACE_SIZE	0x1060
+#define GMAC4_REG_SPACE_SIZE	0x116C
 #define MAC100_ETHTOOL_NAME	"st_mac100"
 #define GMAC_ETHTOOL_NAME	"st_gmac"
 #define XGMAC_ETHTOOL_NAME	"st_xgmac"
 
+/* Same as DMA_CHAN_BASE_ADDR defined in dwmac4_dma.h
+ *
+ * It is here because dwmac_dma.h and dwmac4_dam.h can not be included at the
+ * same time due to the conflicting macro names.
+ */
+#define GMAC4_DMA_CHAN_BASE_ADDR  0x00001100
+
 #define ETHTOOL_DMA_OFFSET	55
 
 struct stmmac_stats {
@@ -413,6 +421,8 @@
 
 	if (priv->plat->has_xgmac)
 		return XGMAC_REGSIZE * 4;
+	else if (priv->plat->has_gmac4)
+		return GMAC4_REG_SPACE_SIZE;
 	return REG_SPACE_SIZE;
 }
 
@@ -425,8 +435,13 @@
 	stmmac_dump_mac_regs(priv, priv->hw, reg_space);
 	stmmac_dump_dma_regs(priv, priv->ioaddr, reg_space);
 
-	if (!priv->plat->has_xgmac) {
-		/* Copy DMA registers to where ethtool expects them */
+	/* Copy DMA registers to where ethtool expects them */
+	if (priv->plat->has_gmac4) {
+		/* GMAC4 dumps its DMA registers at its DMA_CHAN_BASE_ADDR */
+		memcpy(&reg_space[ETHTOOL_DMA_OFFSET],
+		       &reg_space[GMAC4_DMA_CHAN_BASE_ADDR / 4],
+		       NUM_DWMAC4_DMA_REGS * 4);
+	} else if (!priv->plat->has_xgmac) {
 		memcpy(&reg_space[ETHTOOL_DMA_OFFSET],
 		       &reg_space[DMA_BUS_MODE / 4],
 		       NUM_DWMAC1000_DMA_REGS * 4);
@@ -628,10 +643,16 @@
 	if (wol->wolopts) {
 		pr_info("stmmac: wakeup enable\n");
 		device_set_wakeup_enable(priv->device, 1);
-		enable_irq_wake(priv->wol_irq);
+		/* Avoid unbalanced enable_irq_wake calls */
+		if (priv->wol_irq_disabled)
+			enable_irq_wake(priv->wol_irq);
+		priv->wol_irq_disabled = false;
 	} else {
 		device_set_wakeup_enable(priv->device, 0);
-		disable_irq_wake(priv->wol_irq);
+		/* Avoid unbalanced disable_irq_wake calls */
+		if (!priv->wol_irq_disabled)
+			disable_irq_wake(priv->wol_irq);
+		priv->wol_irq_disabled = true;
 	}
 
 	mutex_lock(&priv->lock);
@@ -662,23 +683,16 @@
 	struct stmmac_priv *priv = netdev_priv(dev);
 	int ret;
 
-	if (!edata->eee_enabled) {
+	if (!priv->dma_cap.eee)
+		return -EOPNOTSUPP;
+
+	if (!edata->eee_enabled)
 		stmmac_disable_eee_mode(priv);
-	} else {
-		/* We are asking for enabling the EEE but it is safe
-		 * to verify all by invoking the eee_init function.
-		 * In case of failure it will return an error.
-		 */
-		edata->eee_enabled = stmmac_eee_init(priv);
-		if (!edata->eee_enabled)
-			return -EOPNOTSUPP;
-	}
 
 	ret = phylink_ethtool_set_eee(priv->phylink, edata);
 	if (ret)
 		return ret;
 
-	priv->eee_enabled = edata->eee_enabled;
 	priv->tx_lpi_timer = edata->tx_lpi_timer;
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c
@@ -26,12 +26,16 @@
 	unsigned long data;
 	u32 reg_value;
 
-	/* For GMAC3.x, 4.x versions, convert the ptp_clock to nano second
-	 *	formula = (1/ptp_clock) * 1000000000
-	 * where ptp_clock is 50MHz if fine method is used to update system
+	/* For GMAC3.x, 4.x versions, in "fine adjustement mode" set sub-second
+	 * increment to twice the number of nanoseconds of a clock cycle.
+	 * The calculation of the default_addend value by the caller will set it
+	 * to mid-range = 2^31 when the remainder of this division is zero,
+	 * which will make the accumulator overflow once every 2 ptp_clock
+	 * cycles, adding twice the number of nanoseconds of a clock cycle :
+	 * 2000000000ULL / ptp_clock.
 	 */
 	if (value & PTP_TCR_TSCFUPDT)
-		data = (1000000000ULL / 50000000);
+		data = (2000000000ULL / ptp_clock);
 	else
 		data = (1000000000ULL / ptp_clock);
 
@@ -39,7 +43,8 @@
 	if (!(value & PTP_TCR_TSCTRLSSR))
 		data = (data * 1000) / 465;
 
-	data &= PTP_SSIR_SSINC_MASK;
+	if (data > PTP_SSIR_SSINC_MAX)
+		data = PTP_SSIR_SSINC_MAX;
 
 	reg_value = data;
 	if (gmac4)
@@ -145,15 +150,20 @@
 
 static void get_systime(void __iomem *ioaddr, u64 *systime)
 {
-	u64 ns;
+	u64 ns, sec0, sec1;
 
-	/* Get the TSSS value */
-	ns = readl(ioaddr + PTP_STNSR);
-	/* Get the TSS and convert sec time value to nanosecond */
-	ns += readl(ioaddr + PTP_STSR) * 1000000000ULL;
+	/* Get the TSS value */
+	sec1 = readl_relaxed(ioaddr + PTP_STSR);
+	do {
+		sec0 = sec1;
+		/* Get the TSSS value */
+		ns = readl_relaxed(ioaddr + PTP_STNSR);
+		/* Get the TSS value */
+		sec1 = readl_relaxed(ioaddr + PTP_STSR);
+	} while (sec0 != sec1);
 
 	if (systime)
-		*systime = ns;
+		*systime = ns + (sec1 * 1000000000ULL);
 }
 
 const struct stmmac_hwtimestamp stmmac_ptp = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -45,7 +45,7 @@
 #include "dwxgmac2.h"
 #include "hwif.h"
 
-#define	STMMAC_ALIGN(x)		__ALIGN_KERNEL(x, SMP_CACHE_BYTES)
+#define	STMMAC_ALIGN(x)		ALIGN(ALIGN(x, SMP_CACHE_BYTES), 16)
 #define	TSO_MAX_BUFF_SIZE	(SZ_16K - 1)
 
 /* Module parameters */
@@ -105,6 +105,7 @@
 static irqreturn_t stmmac_interrupt(int irq, void *dev_id);
 
 #ifdef CONFIG_DEBUG_FS
+static const struct net_device_ops stmmac_netdev_ops;
 static void stmmac_init_fs(struct net_device *dev);
 static void stmmac_exit_fs(struct net_device *dev);
 #endif
@@ -174,32 +175,6 @@
 	}
 }
 
-/**
- * stmmac_stop_all_queues - Stop all queues
- * @priv: driver private structure
- */
-static void stmmac_stop_all_queues(struct stmmac_priv *priv)
-{
-	u32 tx_queues_cnt = priv->plat->tx_queues_to_use;
-	u32 queue;
-
-	for (queue = 0; queue < tx_queues_cnt; queue++)
-		netif_tx_stop_queue(netdev_get_tx_queue(priv->dev, queue));
-}
-
-/**
- * stmmac_start_all_queues - Start all queues
- * @priv: driver private structure
- */
-static void stmmac_start_all_queues(struct stmmac_priv *priv)
-{
-	u32 tx_queues_cnt = priv->plat->tx_queues_to_use;
-	u32 queue;
-
-	for (queue = 0; queue < tx_queues_cnt; queue++)
-		netif_tx_start_queue(netdev_get_tx_queue(priv->dev, queue));
-}
-
 static void stmmac_service_event_schedule(struct stmmac_priv *priv)
 {
 	if (!test_bit(STMMAC_DOWN, &priv->state) &&
@@ -250,7 +225,7 @@
 			priv->clk_csr = STMMAC_CSR_100_150M;
 		else if ((clk_rate >= CSR_F_150M) && (clk_rate < CSR_F_250M))
 			priv->clk_csr = STMMAC_CSR_150_250M;
-		else if ((clk_rate >= CSR_F_250M) && (clk_rate < CSR_F_300M))
+		else if ((clk_rate >= CSR_F_250M) && (clk_rate <= CSR_F_300M))
 			priv->clk_csr = STMMAC_CSR_250_300M;
 	}
 
@@ -629,7 +604,8 @@
 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
 			ptp_v2 = PTP_TCR_TSVER2ENA;
 			snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
-			ts_event_en = PTP_TCR_TSEVNTENA;
+			if (priv->synopsys_id < DWMAC_CORE_4_10)
+				ts_event_en = PTP_TCR_TSEVNTENA;
 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
 			ptp_over_ethernet = PTP_TCR_TSIPENA;
@@ -956,7 +932,8 @@
 
 	stmmac_mac_set(priv, priv->ioaddr, true);
 	if (phy && priv->dma_cap.eee) {
-		priv->eee_active = phy_init_eee(phy, 1) >= 0;
+		priv->eee_active =
+			phy_init_eee(phy, !priv->plat->rx_clk_runs_in_lpi) >= 0;
 		priv->eee_enabled = stmmac_eee_init(priv);
 		stmmac_set_eee_pls(priv, priv->hw, true);
 	}
@@ -1022,6 +999,11 @@
 		int addr = priv->plat->phy_addr;
 		struct phy_device *phydev;
 
+		if (addr < 0) {
+			netdev_err(priv->dev, "no phy found\n");
+			return -ENODEV;
+		}
+
 		phydev = mdiobus_get_phy(priv->mii, addr);
 		if (!phydev) {
 			netdev_err(priv->dev, "no phy at addr %d\n", addr);
@@ -1108,7 +1090,9 @@
 {
 	int ret = bufsize;
 
-	if (mtu >= BUF_SIZE_4KiB)
+	if (mtu >= BUF_SIZE_8KiB)
+		ret = BUF_SIZE_16KiB;
+	else if (mtu >= BUF_SIZE_4KiB)
 		ret = BUF_SIZE_8KiB;
 	else if (mtu >= BUF_SIZE_2KiB)
 		ret = BUF_SIZE_4KiB;
@@ -1292,19 +1276,9 @@
 	struct stmmac_priv *priv = netdev_priv(dev);
 	u32 rx_count = priv->plat->rx_queues_to_use;
 	int ret = -ENOMEM;
-	int bfsize = 0;
 	int queue;
 	int i;
 
-	bfsize = stmmac_set_16kib_bfsize(priv, dev->mtu);
-	if (bfsize < 0)
-		bfsize = 0;
-
-	if (bfsize < BUF_SIZE_16KiB)
-		bfsize = stmmac_set_bfsize(dev->mtu, priv->dma_buf_sz);
-
-	priv->dma_buf_sz = bfsize;
-
 	/* RX INITIALIZATION */
 	netif_dbg(priv, probe, priv->dev,
 		  "SKB addresses:\nskb\t\tskb data\tdma data\n");
@@ -1346,8 +1320,6 @@
 		}
 	}
 
-	buf_sz = bfsize;
-
 	return 0;
 
 err_init_rx_buffers:
@@ -1476,6 +1448,19 @@
 }
 
 /**
+ * stmmac_free_tx_skbufs - free TX skb buffers
+ * @priv: private structure
+ */
+static void stmmac_free_tx_skbufs(struct stmmac_priv *priv)
+{
+	u32 tx_queue_cnt = priv->plat->tx_queues_to_use;
+	u32 queue;
+
+	for (queue = 0; queue < tx_queue_cnt; queue++)
+		dma_free_tx_skbufs(priv, queue);
+}
+
+/**
  * free_dma_rx_desc_resources - free RX dma desc resources
  * @priv: private structure
  */
@@ -1502,10 +1487,8 @@
 					  rx_q->dma_erx, rx_q->dma_rx_phy);
 
 		kfree(rx_q->buf_pool);
-		if (rx_q->page_pool) {
-			page_pool_request_shutdown(rx_q->page_pool);
+		if (rx_q->page_pool)
 			page_pool_destroy(rx_q->page_pool);
-		}
 	}
 }
 
@@ -2010,6 +1993,8 @@
 	tx_q->cur_tx = 0;
 	tx_q->mss = 0;
 	netdev_tx_reset_queue(netdev_get_tx_queue(priv->dev, chan));
+	stmmac_init_tx_chan(priv, priv->ioaddr, priv->plat->dma_cfg,
+			    tx_q->dma_tx_phy, chan);
 	stmmac_start_tx_dma(priv, chan);
 
 	priv->dev->stats.tx_errors++;
@@ -2656,6 +2641,7 @@
 static int stmmac_open(struct net_device *dev)
 {
 	struct stmmac_priv *priv = netdev_priv(dev);
+	int bfsize = 0;
 	u32 chan;
 	int ret;
 
@@ -2675,7 +2661,16 @@
 	memset(&priv->xstats, 0, sizeof(struct stmmac_extra_stats));
 	priv->xstats.threshold = tc;
 
-	priv->dma_buf_sz = STMMAC_ALIGN(buf_sz);
+	bfsize = stmmac_set_16kib_bfsize(priv, dev->mtu);
+	if (bfsize < 0)
+		bfsize = 0;
+
+	if (bfsize < BUF_SIZE_16KiB)
+		bfsize = stmmac_set_bfsize(dev->mtu, priv->dma_buf_sz);
+
+	priv->dma_buf_sz = bfsize;
+	buf_sz = bfsize;
+
 	priv->rx_copybreak = STMMAC_RX_COPYBREAK;
 
 	ret = alloc_dma_desc_resources(priv);
@@ -2712,6 +2707,7 @@
 		goto irq_error;
 	}
 
+	priv->wol_irq_disabled = true;
 	/* Request the Wake IRQ in case of another line is used for WoL */
 	if (priv->wol_irq != dev->irq) {
 		ret = request_irq(priv->wol_irq, stmmac_interrupt,
@@ -2737,7 +2733,7 @@
 	}
 
 	stmmac_enable_all_queues(priv);
-	stmmac_start_all_queues(priv);
+	netif_tx_start_all_queues(priv->dev);
 
 	return 0;
 
@@ -2771,15 +2767,10 @@
 	struct stmmac_priv *priv = netdev_priv(dev);
 	u32 chan;
 
-	if (priv->eee_enabled)
-		del_timer_sync(&priv->eee_ctrl_timer);
-
 	/* Stop and disconnect the PHY */
 	phylink_stop(priv->phylink);
 	phylink_disconnect_phy(priv->phylink);
 
-	stmmac_stop_all_queues(priv);
-
 	stmmac_disable_all_queues(priv);
 
 	for (chan = 0; chan < priv->plat->tx_queues_to_use; chan++)
@@ -2792,6 +2783,11 @@
 	if (priv->lpi_irq > 0)
 		free_irq(priv->lpi_irq, dev);
 
+	if (priv->eee_enabled) {
+		priv->tx_path_in_lpi_mode = false;
+		del_timer_sync(&priv->eee_ctrl_timer);
+	}
+
 	/* Stop TX/RX DMA and clear the descriptors */
 	stmmac_stop_all_dma(priv);
 
@@ -3105,6 +3101,7 @@
 
 	tx_q->tx_tail_addr = tx_q->dma_tx_phy + (tx_q->cur_tx * sizeof(*desc));
 	stmmac_set_tx_tail_ptr(priv, priv->ioaddr, tx_q->tx_tail_addr, queue);
+	stmmac_tx_timer_arm(priv, queue);
 
 	return NETDEV_TX_OK;
 
@@ -3332,6 +3329,7 @@
 
 	tx_q->tx_tail_addr = tx_q->dma_tx_phy + (tx_q->cur_tx * sizeof(*desc));
 	stmmac_set_tx_tail_ptr(priv, priv->ioaddr, tx_q->tx_tail_addr, queue);
+	stmmac_tx_timer_arm(priv, queue);
 
 	return NETDEV_TX_OK;
 
@@ -3443,6 +3441,55 @@
 	stmmac_set_rx_tail_ptr(priv, priv->ioaddr, rx_q->rx_tail_addr, queue);
 }
 
+static unsigned int stmmac_rx_buf1_len(struct stmmac_priv *priv,
+				       struct dma_desc *p,
+				       int status, unsigned int len)
+{
+	int ret, coe = priv->hw->rx_csum;
+	unsigned int plen = 0, hlen = 0;
+
+	/* Not first descriptor, buffer is always zero */
+	if (priv->sph && len)
+		return 0;
+
+	/* First descriptor, get split header length */
+	ret = stmmac_get_rx_header_len(priv, p, &hlen);
+	if (priv->sph && hlen) {
+		priv->xstats.rx_split_hdr_pkt_n++;
+		return hlen;
+	}
+
+	/* First descriptor, not last descriptor and not split header */
+	if (status & rx_not_ls)
+		return priv->dma_buf_sz;
+
+	plen = stmmac_get_rx_frame_len(priv, p, coe);
+
+	/* First descriptor and last descriptor and not split header */
+	return min_t(unsigned int, priv->dma_buf_sz, plen);
+}
+
+static unsigned int stmmac_rx_buf2_len(struct stmmac_priv *priv,
+				       struct dma_desc *p,
+				       int status, unsigned int len)
+{
+	int coe = priv->hw->rx_csum;
+	unsigned int plen = 0;
+
+	/* Not split header, buffer is not available */
+	if (!priv->sph)
+		return 0;
+
+	/* Not last descriptor */
+	if (status & rx_not_ls)
+		return priv->dma_buf_sz;
+
+	plen = stmmac_get_rx_frame_len(priv, p, coe);
+
+	/* Last descriptor */
+	return plen - len;
+}
+
 /**
  * stmmac_rx - manage the receive process
  * @priv: driver private structure
@@ -3472,11 +3519,10 @@
 		stmmac_display_ring(priv, rx_head, DMA_RX_SIZE, true);
 	}
 	while (count < limit) {
-		unsigned int hlen = 0, prev_len = 0;
+		unsigned int buf1_len = 0, buf2_len = 0;
 		enum pkt_hash_types hash_type;
 		struct stmmac_rx_buffer *buf;
 		struct dma_desc *np, *p;
-		unsigned int sec_len;
 		int entry;
 		u32 hash;
 
@@ -3491,11 +3537,12 @@
 			len = 0;
 		}
 
+read_again:
 		if (count >= limit)
 			break;
 
-read_again:
-		sec_len = 0;
+		buf1_len = 0;
+		buf2_len = 0;
 		entry = next_entry;
 		buf = &rx_q->buf_pool[entry];
 
@@ -3520,7 +3567,6 @@
 			np = rx_q->dma_rx + next_entry;
 
 		prefetch(np);
-		prefetch(page_address(buf->page));
 
 		if (priv->extend_desc)
 			stmmac_rx_extended_status(priv, &priv->dev->stats,
@@ -3537,69 +3583,61 @@
 			goto read_again;
 		if (unlikely(error)) {
 			dev_kfree_skb(skb);
+			skb = NULL;
 			count++;
 			continue;
 		}
 
 		/* Buffer is good. Go on. */
 
-		if (likely(status & rx_not_ls)) {
-			len += priv->dma_buf_sz;
-		} else {
-			prev_len = len;
-			len = stmmac_get_rx_frame_len(priv, p, coe);
+		prefetch(page_address(buf->page));
+		if (buf->sec_page)
+			prefetch(page_address(buf->sec_page));
 
-			/* ACS is set; GMAC core strips PAD/FCS for IEEE 802.3
-			 * Type frames (LLC/LLC-SNAP)
-			 *
-			 * llc_snap is never checked in GMAC >= 4, so this ACS
-			 * feature is always disabled and packets need to be
-			 * stripped manually.
-			 */
-			if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00) ||
-			    unlikely(status != llc_snap))
-				len -= ETH_FCS_LEN;
+		buf1_len = stmmac_rx_buf1_len(priv, p, status, len);
+		len += buf1_len;
+		buf2_len = stmmac_rx_buf2_len(priv, p, status, len);
+		len += buf2_len;
+
+		/* ACS is set; GMAC core strips PAD/FCS for IEEE 802.3
+		 * Type frames (LLC/LLC-SNAP)
+		 *
+		 * llc_snap is never checked in GMAC >= 4, so this ACS
+		 * feature is always disabled and packets need to be
+		 * stripped manually.
+		 */
+		if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00) ||
+		    unlikely(status != llc_snap)) {
+			if (buf2_len)
+				buf2_len -= ETH_FCS_LEN;
+			else
+				buf1_len -= ETH_FCS_LEN;
+
+			len -= ETH_FCS_LEN;
 		}
 
 		if (!skb) {
-			int ret = stmmac_get_rx_header_len(priv, p, &hlen);
-
-			if (priv->sph && !ret && (hlen > 0)) {
-				sec_len = len;
-				if (!(status & rx_not_ls))
-					sec_len = sec_len - hlen;
-				len = hlen;
-
-				prefetch(page_address(buf->sec_page));
-				priv->xstats.rx_split_hdr_pkt_n++;
-			}
-
-			skb = napi_alloc_skb(&ch->rx_napi, len);
+			skb = napi_alloc_skb(&ch->rx_napi, buf1_len);
 			if (!skb) {
 				priv->dev->stats.rx_dropped++;
 				count++;
-				continue;
+				goto drain_data;
 			}
 
-			dma_sync_single_for_cpu(priv->device, buf->addr, len,
-						DMA_FROM_DEVICE);
+			dma_sync_single_for_cpu(priv->device, buf->addr,
+						buf1_len, DMA_FROM_DEVICE);
 			skb_copy_to_linear_data(skb, page_address(buf->page),
-						len);
-			skb_put(skb, len);
+						buf1_len);
+			skb_put(skb, buf1_len);
 
 			/* Data payload copied into SKB, page ready for recycle */
 			page_pool_recycle_direct(rx_q->page_pool, buf->page);
 			buf->page = NULL;
-		} else {
-			unsigned int buf_len = len - prev_len;
-
-			if (likely(status & rx_not_ls))
-				buf_len = priv->dma_buf_sz;
-
+		} else if (buf1_len) {
 			dma_sync_single_for_cpu(priv->device, buf->addr,
-						buf_len, DMA_FROM_DEVICE);
+						buf1_len, DMA_FROM_DEVICE);
 			skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
-					buf->page, 0, buf_len,
+					buf->page, 0, buf1_len,
 					priv->dma_buf_sz);
 
 			/* Data payload appended into SKB */
@@ -3607,22 +3645,23 @@
 			buf->page = NULL;
 		}
 
-		if (sec_len > 0) {
+		if (buf2_len) {
 			dma_sync_single_for_cpu(priv->device, buf->sec_addr,
-						sec_len, DMA_FROM_DEVICE);
+						buf2_len, DMA_FROM_DEVICE);
 			skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
-					buf->sec_page, 0, sec_len,
+					buf->sec_page, 0, buf2_len,
 					priv->dma_buf_sz);
 
-			len += sec_len;
-
 			/* Data payload appended into SKB */
 			page_pool_release_page(rx_q->page_pool, buf->sec_page);
 			buf->sec_page = NULL;
 		}
 
+drain_data:
 		if (likely(status & rx_not_ls))
 			goto read_again;
+		if (!skb)
+			continue;
 
 		/* Got entire packet into SKB. Finish it. */
 
@@ -3640,13 +3679,14 @@
 
 		skb_record_rx_queue(skb, queue);
 		napi_gro_receive(&ch->rx_napi, skb);
+		skb = NULL;
 
 		priv->dev->stats.rx_packets++;
 		priv->dev->stats.rx_bytes += len;
 		count++;
 	}
 
-	if (status & rx_not_ls) {
+	if (status & rx_not_ls || skb) {
 		rx_q->state_saved = true;
 		rx_q->state.skb = skb;
 		rx_q->state.error = error;
@@ -3749,13 +3789,26 @@
 static int stmmac_change_mtu(struct net_device *dev, int new_mtu)
 {
 	struct stmmac_priv *priv = netdev_priv(dev);
+	int txfifosz = priv->plat->tx_fifo_size;
+	const int mtu = new_mtu;
+
+	if (txfifosz == 0)
+		txfifosz = priv->dma_cap.tx_fifo_size;
+
+	txfifosz /= priv->plat->tx_queues_to_use;
 
 	if (netif_running(dev)) {
 		netdev_err(priv->dev, "must be stopped to change its MTU\n");
 		return -EBUSY;
 	}
 
-	dev->mtu = new_mtu;
+	new_mtu = STMMAC_ALIGN(new_mtu);
+
+	/* If condition true, FIFO is too small or MTU too large */
+	if ((txfifosz < new_mtu) || (new_mtu > BUF_SIZE_16KiB))
+		return -EINVAL;
+
+	dev->mtu = mtu;
 
 	netdev_update_features(dev);
 
@@ -3819,7 +3872,7 @@
 /**
  *  stmmac_interrupt - main ISR
  *  @irq: interrupt number.
- *  @dev_id: to pass the net device pointer.
+ *  @dev_id: to pass the net device pointer (must be valid).
  *  Description: this is the main driver interrupt service routine.
  *  It can call:
  *  o DMA service routine (to manage incoming frame reception and transmission
@@ -3843,11 +3896,6 @@
 	if (priv->irq_wake)
 		pm_wakeup_event(priv->device, 0);
 
-	if (unlikely(!dev)) {
-		netdev_err(priv->dev, "%s: invalid dev pointer\n", __func__);
-		return IRQ_NONE;
-	}
-
 	/* Check if adapter is up */
 	if (test_bit(STMMAC_DOWN, &priv->state))
 		return IRQ_HANDLED;
@@ -3858,7 +3906,6 @@
 	/* To handle GMAC own interrupts */
 	if ((priv->plat->has_gmac) || xmac) {
 		int status = stmmac_host_irq_status(priv, priv->hw, &priv->xstats);
-		int mtl_status;
 
 		if (unlikely(status)) {
 			/* For LPI we need to save the tx status */
@@ -3869,17 +3916,8 @@
 		}
 
 		for (queue = 0; queue < queues_count; queue++) {
-			struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
-
-			mtl_status = stmmac_host_mtl_irq_status(priv, priv->hw,
-								queue);
-			if (mtl_status != -EINVAL)
-				status |= mtl_status;
-
-			if (status & CORE_IRQ_MTL_RX_OVERFLOW)
-				stmmac_set_rx_tail_ptr(priv, priv->ioaddr,
-						       rx_q->rx_tail_addr,
-						       queue);
+			status = stmmac_host_mtl_irq_status(priv, priv->hw,
+							    queue);
 		}
 
 		/* PCS link status */
@@ -4163,10 +4201,40 @@
 }
 DEFINE_SHOW_ATTRIBUTE(stmmac_dma_cap);
 
+/* Use network device events to rename debugfs file entries.
+ */
+static int stmmac_device_event(struct notifier_block *unused,
+			       unsigned long event, void *ptr)
+{
+	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+	struct stmmac_priv *priv = netdev_priv(dev);
+
+	if (dev->netdev_ops != &stmmac_netdev_ops)
+		goto done;
+
+	switch (event) {
+	case NETDEV_CHANGENAME:
+		if (priv->dbgfs_dir)
+			priv->dbgfs_dir = debugfs_rename(stmmac_fs_dir,
+							 priv->dbgfs_dir,
+							 stmmac_fs_dir,
+							 dev->name);
+		break;
+	}
+done:
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block stmmac_notifier = {
+	.notifier_call = stmmac_device_event,
+};
+
 static void stmmac_init_fs(struct net_device *dev)
 {
 	struct stmmac_priv *priv = netdev_priv(dev);
 
+	rtnl_lock();
+
 	/* Create per netdev entries */
 	priv->dbgfs_dir = debugfs_create_dir(dev->name, stmmac_fs_dir);
 
@@ -4177,6 +4245,8 @@
 	/* Entry to report the DMA HW features */
 	debugfs_create_file("dma_cap", 0444, priv->dbgfs_dir, dev,
 			    &stmmac_dma_cap_fops);
+
+	rtnl_unlock();
 }
 
 static void stmmac_exit_fs(struct net_device *dev)
@@ -4510,7 +4580,7 @@
 		dev_info(priv->device, "TSO feature enabled\n");
 	}
 
-	if (priv->dma_cap.sphen) {
+	if (priv->dma_cap.sphen && !priv->plat->sph_disable) {
 		ndev->hw_features |= NETIF_F_GRO;
 		priv->sph = true;
 		dev_info(priv->device, "SPH feature enabled\n");
@@ -4622,9 +4692,9 @@
 		/* MDIO bus Registration */
 		ret = stmmac_mdio_register(ndev);
 		if (ret < 0) {
-			dev_err(priv->device,
-				"%s: MDIO bus (id: %d) registration failed",
-				__func__, priv->plat->bus_id);
+			dev_err_probe(priv->device, ret,
+				      "%s: MDIO bus (id: %d) registration failed\n",
+				      __func__, priv->plat->bus_id);
 			goto error_mdio_register;
 		}
 	}
@@ -4684,14 +4754,14 @@
 
 	netdev_info(priv->dev, "%s: removing driver", __func__);
 
-#ifdef CONFIG_DEBUG_FS
-	stmmac_exit_fs(ndev);
-#endif
 	stmmac_stop_all_dma(priv);
 
 	stmmac_mac_set(priv, priv->ioaddr, false);
 	netif_carrier_off(ndev);
 	unregister_netdev(ndev);
+#ifdef CONFIG_DEBUG_FS
+	stmmac_exit_fs(ndev);
+#endif
 	phylink_destroy(priv->phylink);
 	if (priv->plat->stmmac_rst)
 		reset_control_assert(priv->plat->stmmac_rst);
@@ -4719,6 +4789,7 @@
 {
 	struct net_device *ndev = dev_get_drvdata(dev);
 	struct stmmac_priv *priv = netdev_priv(ndev);
+	u32 chan;
 
 	if (!ndev || !netif_running(ndev))
 		return 0;
@@ -4728,10 +4799,17 @@
 	mutex_lock(&priv->lock);
 
 	netif_device_detach(ndev);
-	stmmac_stop_all_queues(priv);
 
 	stmmac_disable_all_queues(priv);
 
+	for (chan = 0; chan < priv->plat->tx_queues_to_use; chan++)
+		del_timer_sync(&priv->tx_queue[chan].txtimer);
+
+	if (priv->eee_enabled) {
+		priv->tx_path_in_lpi_mode = false;
+		del_timer_sync(&priv->eee_ctrl_timer);
+	}
+
 	/* Stop TX/RX DMA */
 	stmmac_stop_all_dma(priv);
 
@@ -4784,6 +4862,8 @@
 		tx_q->cur_tx = 0;
 		tx_q->dirty_tx = 0;
 		tx_q->mss = 0;
+
+		netdev_tx_reset_queue(netdev_get_tx_queue(priv->dev, queue));
 	}
 }
 
@@ -4824,12 +4904,11 @@
 			stmmac_mdio_reset(priv->mii);
 	}
 
-	netif_device_attach(ndev);
-
 	mutex_lock(&priv->lock);
 
 	stmmac_reset_queues_param(priv);
 
+	stmmac_free_tx_skbufs(priv);
 	stmmac_clear_descriptors(priv);
 
 	stmmac_hw_setup(ndev, false);
@@ -4838,8 +4917,6 @@
 
 	stmmac_enable_all_queues(priv);
 
-	stmmac_start_all_queues(priv);
-
 	mutex_unlock(&priv->lock);
 
 	if (!device_may_wakeup(priv->device)) {
@@ -4850,6 +4927,8 @@
 
 	phylink_mac_change(priv->phylink, true);
 
+	netif_device_attach(ndev);
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(stmmac_resume);
@@ -4860,7 +4939,7 @@
 	char *opt;
 
 	if (!str || !*str)
-		return -EINVAL;
+		return 1;
 	while ((opt = strsep(&str, ",")) != NULL) {
 		if (!strncmp(opt, "debug:", 6)) {
 			if (kstrtoint(opt + 6, 0, &debug))
@@ -4891,11 +4970,11 @@
 				goto err;
 		}
 	}
-	return 0;
+	return 1;
 
 err:
 	pr_err("%s: ERROR broken module parameter conversion", __func__);
-	return -EINVAL;
+	return 1;
 }
 
 __setup("stmmaceth=", stmmac_cmdline_opt);
@@ -4907,6 +4986,7 @@
 	/* Create debugfs main directory if it doesn't exist yet */
 	if (!stmmac_fs_dir)
 		stmmac_fs_dir = debugfs_create_dir(STMMAC_RESOURCE_NAME, NULL);
+	register_netdevice_notifier(&stmmac_notifier);
 #endif
 
 	return 0;
@@ -4915,6 +4995,7 @@
 static void __exit stmmac_exit(void)
 {
 #ifdef CONFIG_DEBUG_FS
+	unregister_netdevice_notifier(&stmmac_notifier);
 	debugfs_remove_recursive(stmmac_fs_dir);
 #endif
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
@@ -358,8 +358,12 @@
 	new_bus->parent = priv->device;
 
 	err = of_mdiobus_register(new_bus, mdio_node);
-	if (err != 0) {
-		dev_err(dev, "Cannot register the MDIO bus\n");
+	if (err == -ENODEV) {
+		err = 0;
+		dev_info(dev, "MDIO bus is disabled\n");
+		goto bus_register_fail;
+	} else if (err) {
+		dev_err_probe(dev, err, "Cannot register the MDIO bus\n");
 		goto bus_register_fail;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
@@ -119,6 +119,7 @@
 	plat->has_gmac4 = 1;
 	plat->force_sf_dma_mode = 0;
 	plat->tso_en = 1;
+	plat->sph_disable = 1;
 
 	plat->rx_sched_algorithm = MTL_RX_ALGORITHM_SP;
 
@@ -481,7 +482,7 @@
 		return -ENOMEM;
 
 	/* Enable pci device */
-	ret = pci_enable_device(pdev);
+	ret = pcim_enable_device(pdev);
 	if (ret) {
 		dev_err(&pdev->dev, "%s: ERROR: failed to enable device\n",
 			__func__);
@@ -538,8 +539,6 @@
 		pcim_iounmap_regions(pdev, BIT(i));
 		break;
 	}
-
-	pci_disable_device(pdev);
 }
 
 static int __maybe_unused stmmac_pci_suspend(struct device *dev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -107,10 +107,10 @@
 
 	axi->axi_lpi_en = of_property_read_bool(np, "snps,lpi_en");
 	axi->axi_xit_frm = of_property_read_bool(np, "snps,xit_frm");
-	axi->axi_kbbe = of_property_read_bool(np, "snps,axi_kbbe");
-	axi->axi_fb = of_property_read_bool(np, "snps,axi_fb");
-	axi->axi_mb = of_property_read_bool(np, "snps,axi_mb");
-	axi->axi_rb =  of_property_read_bool(np, "snps,axi_rb");
+	axi->axi_kbbe = of_property_read_bool(np, "snps,kbbe");
+	axi->axi_fb = of_property_read_bool(np, "snps,fb");
+	axi->axi_mb = of_property_read_bool(np, "snps,mb");
+	axi->axi_rb =  of_property_read_bool(np, "snps,rb");
 
 	if (of_property_read_u32(np, "snps,wr_osr_lmt", &axi->axi_wr_osr_lmt))
 		axi->axi_wr_osr_lmt = 1;
@@ -320,7 +320,7 @@
 static int stmmac_dt_phy(struct plat_stmmacenet_data *plat,
 			 struct device_node *np, struct device *dev)
 {
-	bool mdio = true;
+	bool mdio = !of_phy_is_fixed_link(np);
 	static const struct of_device_id need_mdio_ids[] = {
 		{ .compatible = "snps,dwc-qos-ethernet-4.10" },
 		{},
@@ -428,8 +428,7 @@
 	plat->phylink_node = np;
 
 	/* Get max speed of operation from device tree */
-	if (of_property_read_u32(np, "max-speed", &plat->max_speed))
-		plat->max_speed = -1;
+	of_property_read_u32(np, "max-speed", &plat->max_speed);
 
 	plat->bus_id = of_alias_get_id(np, "ethernet");
 	if (plat->bus_id < 0)
@@ -505,6 +504,14 @@
 		plat->pmt = 1;
 	}
 
+	if (of_device_is_compatible(np, "snps,dwmac-3.40a")) {
+		plat->has_gmac = 1;
+		plat->enh_desc = 1;
+		plat->tx_coe = 1;
+		plat->bugged_jumbo = 1;
+		plat->pmt = 1;
+	}
+
 	if (of_device_is_compatible(np, "snps,dwmac-4.00") ||
 	    of_device_is_compatible(np, "snps,dwmac-4.10a") ||
 	    of_device_is_compatible(np, "snps,dwmac-4.20a")) {
@@ -547,7 +554,7 @@
 	dma_cfg->mixed_burst = of_property_read_bool(np, "snps,mixed-burst");
 
 	plat->force_thresh_dma_mode = of_property_read_bool(np, "snps,force_thresh_dma_mode");
-	if (plat->force_thresh_dma_mode) {
+	if (plat->force_thresh_dma_mode && plat->force_sf_dma_mode) {
 		plat->force_sf_dma_mode = 0;
 		dev_warn(&pdev->dev,
 			 "force_sf_dma_mode is ignored if force_thresh_dma_mode is set.\n");
@@ -624,6 +631,8 @@
 void stmmac_remove_config_dt(struct platform_device *pdev,
 			     struct plat_stmmacenet_data *plat)
 {
+	clk_disable_unprepare(plat->stmmac_clk);
+	clk_disable_unprepare(plat->pclk);
 	of_node_put(plat->phy_node);
 	of_node_put(plat->mdio_node);
 }
@@ -663,16 +672,22 @@
 	 * In case the wake up interrupt is not passed from the platform
 	 * so the driver will continue to use the mac irq (ndev->irq)
 	 */
-	stmmac_res->wol_irq = platform_get_irq_byname(pdev, "eth_wake_irq");
+	stmmac_res->wol_irq =
+		platform_get_irq_byname_optional(pdev, "eth_wake_irq");
 	if (stmmac_res->wol_irq < 0) {
 		if (stmmac_res->wol_irq == -EPROBE_DEFER)
 			return -EPROBE_DEFER;
+		dev_info(&pdev->dev, "IRQ eth_wake_irq not found\n");
 		stmmac_res->wol_irq = stmmac_res->irq;
 	}
 
-	stmmac_res->lpi_irq = platform_get_irq_byname(pdev, "eth_lpi");
-	if (stmmac_res->lpi_irq == -EPROBE_DEFER)
-		return -EPROBE_DEFER;
+	stmmac_res->lpi_irq =
+		platform_get_irq_byname_optional(pdev, "eth_lpi");
+	if (stmmac_res->lpi_irq < 0) {
+		if (stmmac_res->lpi_irq == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+		dev_info(&pdev->dev, "IRQ eth_lpi not found\n");
+	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	stmmac_res->addr = devm_ioremap_resource(&pdev->dev, res);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
@@ -61,7 +61,7 @@
 #define	PTP_TCR_TSENMACADDR	BIT(18)
 
 /* SSIR defines */
-#define	PTP_SSIR_SSINC_MASK		0xff
+#define	PTP_SSIR_SSINC_MAX		0xff
 #define	GMAC4_PTP_SSIR_SSINC_SHIFT	16
 
 #endif	/* __STMMAC_PTP_H__ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c
@@ -80,7 +80,7 @@
 	if (attr->max_size && (attr->max_size > size))
 		size = attr->max_size;
 
-	skb = netdev_alloc_skb_ip_align(priv->dev, size);
+	skb = netdev_alloc_skb(priv->dev, size);
 	if (!skb)
 		return NULL;
 
@@ -244,6 +244,8 @@
 					 struct net_device *orig_ndev)
 {
 	struct stmmac_test_priv *tpriv = pt->af_packet_priv;
+	unsigned char *src = tpriv->packet->src;
+	unsigned char *dst = tpriv->packet->dst;
 	struct stmmachdr *shdr;
 	struct ethhdr *ehdr;
 	struct udphdr *uhdr;
@@ -260,15 +262,15 @@
 		goto out;
 
 	ehdr = (struct ethhdr *)skb_mac_header(skb);
-	if (tpriv->packet->dst) {
-		if (!ether_addr_equal(ehdr->h_dest, tpriv->packet->dst))
+	if (dst) {
+		if (!ether_addr_equal_unaligned(ehdr->h_dest, dst))
 			goto out;
 	}
 	if (tpriv->packet->sarc) {
-		if (!ether_addr_equal(ehdr->h_source, ehdr->h_dest))
+		if (!ether_addr_equal_unaligned(ehdr->h_source, ehdr->h_dest))
 			goto out;
-	} else if (tpriv->packet->src) {
-		if (!ether_addr_equal(ehdr->h_source, tpriv->packet->src))
+	} else if (src) {
+		if (!ether_addr_equal_unaligned(ehdr->h_source, src))
 			goto out;
 	}
 
@@ -624,6 +626,8 @@
 		return -EOPNOTSUPP;
 	if (netdev_uc_count(priv->dev) >= priv->hw->unicast_filter_entries)
 		return -EOPNOTSUPP;
+	if (netdev_mc_count(priv->dev) >= priv->hw->multicast_filter_bins)
+		return -EOPNOTSUPP;
 
 	while (--tries) {
 		/* We only need to check the mc_addr for collisions */
@@ -666,6 +670,8 @@
 
 	if (stmmac_filter_check(priv))
 		return -EOPNOTSUPP;
+	if (netdev_uc_count(priv->dev) >= priv->hw->unicast_filter_entries)
+		return -EOPNOTSUPP;
 	if (netdev_mc_count(priv->dev) >= priv->hw->multicast_filter_bins)
 		return -EOPNOTSUPP;
 
@@ -710,7 +716,7 @@
 	struct ethhdr *ehdr;
 
 	ehdr = (struct ethhdr *)skb_mac_header(skb);
-	if (!ether_addr_equal(ehdr->h_source, orig_ndev->dev_addr))
+	if (!ether_addr_equal_unaligned(ehdr->h_source, orig_ndev->dev_addr))
 		goto out;
 	if (ehdr->h_proto != htons(ETH_P_PAUSE))
 		goto out;
@@ -847,12 +853,16 @@
 	if (tpriv->vlan_id) {
 		if (skb->vlan_proto != htons(proto))
 			goto out;
-		if (skb->vlan_tci != tpriv->vlan_id)
+		if (skb->vlan_tci != tpriv->vlan_id) {
+			/* Means filter did not work. */
+			tpriv->ok = false;
+			complete(&tpriv->comp);
 			goto out;
+		}
 	}
 
 	ehdr = (struct ethhdr *)skb_mac_header(skb);
-	if (!ether_addr_equal(ehdr->h_dest, tpriv->packet->dst))
+	if (!ether_addr_equal_unaligned(ehdr->h_dest, tpriv->packet->dst))
 		goto out;
 
 	ihdr = ip_hdr(skb);
@@ -1287,16 +1297,19 @@
 	struct stmmac_packet_attrs attr = { };
 	struct flow_dissector *dissector;
 	struct flow_cls_offload *cls;
+	int ret, old_enable = 0;
 	struct flow_rule *rule;
-	int ret;
 
 	if (!tc_can_offload(priv->dev))
 		return -EOPNOTSUPP;
 	if (!priv->dma_cap.l3l4fnum)
 		return -EOPNOTSUPP;
-	if (priv->rss.enable)
+	if (priv->rss.enable) {
+		old_enable = priv->rss.enable;
+		priv->rss.enable = false;
 		stmmac_rss_configure(priv, priv->hw, NULL,
 				     priv->plat->rx_queues_to_use);
+	}
 
 	dissector = kzalloc(sizeof(*dissector), GFP_KERNEL);
 	if (!dissector) {
@@ -1363,7 +1376,8 @@
 cleanup_dissector:
 	kfree(dissector);
 cleanup_rss:
-	if (priv->rss.enable) {
+	if (old_enable) {
+		priv->rss.enable = old_enable;
 		stmmac_rss_configure(priv, priv->hw, &priv->rss,
 				     priv->plat->rx_queues_to_use);
 	}
@@ -1408,16 +1422,19 @@
 	struct stmmac_packet_attrs attr = { };
 	struct flow_dissector *dissector;
 	struct flow_cls_offload *cls;
+	int ret, old_enable = 0;
 	struct flow_rule *rule;
-	int ret;
 
 	if (!tc_can_offload(priv->dev))
 		return -EOPNOTSUPP;
 	if (!priv->dma_cap.l3l4fnum)
 		return -EOPNOTSUPP;
-	if (priv->rss.enable)
+	if (priv->rss.enable) {
+		old_enable = priv->rss.enable;
+		priv->rss.enable = false;
 		stmmac_rss_configure(priv, priv->hw, NULL,
 				     priv->plat->rx_queues_to_use);
+	}
 
 	dissector = kzalloc(sizeof(*dissector), GFP_KERNEL);
 	if (!dissector) {
@@ -1489,7 +1506,8 @@
 cleanup_dissector:
 	kfree(dissector);
 cleanup_rss:
-	if (priv->rss.enable) {
+	if (old_enable) {
+		priv->rss.enable = old_enable;
 		stmmac_rss_configure(priv, priv->hw, &priv->rss,
 				     priv->plat->rx_queues_to_use);
 	}
@@ -1542,7 +1560,7 @@
 	struct arphdr *ahdr;
 
 	ehdr = (struct ethhdr *)skb_mac_header(skb);
-	if (!ether_addr_equal(ehdr->h_dest, tpriv->packet->src))
+	if (!ether_addr_equal_unaligned(ehdr->h_dest, tpriv->packet->src))
 		goto out;
 
 	ahdr = arp_hdr(skb);
@@ -1596,12 +1614,16 @@
 	}
 
 	ret = stmmac_set_arp_offload(priv, priv->hw, true, ip_addr);
-	if (ret)
+	if (ret) {
+		kfree_skb(skb);
 		goto cleanup;
+	}
 
 	ret = dev_set_promiscuity(priv->dev, 1);
-	if (ret)
+	if (ret) {
+		kfree_skb(skb);
 		goto cleanup;
+	}
 
 	skb_set_queue_mapping(skb, 0);
 	ret = dev_queue_xmit(skb);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
@@ -332,7 +332,12 @@
 
 		priv->plat->tx_queues_cfg[queue].mode_to_use = MTL_QUEUE_AVB;
 	} else if (!qopt->enable) {
-		return stmmac_dma_qmode(priv, priv->ioaddr, queue, MTL_QUEUE_DCB);
+		ret = stmmac_dma_qmode(priv, priv->ioaddr, queue,
+				       MTL_QUEUE_DCB);
+		if (ret)
+			return ret;
+
+		priv->plat->tx_queues_cfg[queue].mode_to_use = MTL_QUEUE_DCB;
 	}
 
 	/* Port Transmit Rate and Speed Divider */
@@ -579,6 +584,10 @@
 {
 	int ret = 0;
 
+	/* When RSS is enabled, the filtering will be bypassed */
+	if (priv->rss.enable)
+		return -EBUSY;
+
 	switch (cls->command) {
 	case FLOW_CLS_REPLACE:
 		ret = tc_add_flow(priv, cls);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/sun/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/sun/Kconfig
@@ -73,6 +73,7 @@
 config SUNVNET_COMMON
 	tristate "Common routines to support Sun Virtual Networking"
 	depends on SUN_LDOMS
+	depends on INET
 	default m
 
 config SUNVNET
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/sun/cassini.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/sun/cassini.c
@@ -1337,7 +1337,7 @@
 	writel(val, cp->regs + REG_RX_PAGE_SIZE);
 
 	/* enable the header parser if desired */
-	if (CAS_HP_FIRMWARE == cas_prog_null)
+	if (&CAS_HP_FIRMWARE[0] == &cas_prog_null[0])
 		return;
 
 	val = CAS_BASE(HP_CFG_NUM_CPU, CAS_NCPUS > 63 ? 0 : CAS_NCPUS);
@@ -2291,7 +2291,7 @@
 	drops = 0;
 	while (1) {
 		struct cas_rx_comp *rxc = rxcs + entry;
-		struct sk_buff *uninitialized_var(skb);
+		struct sk_buff *skb;
 		int type, len;
 		u64 words[4];
 		int i, dring;
@@ -3807,7 +3807,7 @@
 
 	/* program header parser */
 	if ((cp->cas_flags & CAS_FLAG_TARGET_ABORT) ||
-	    (CAS_HP_ALT_FIRMWARE == cas_prog_null)) {
+	    (&CAS_HP_ALT_FIRMWARE[0] == &cas_prog_null[0])) {
 		cas_load_firmware(cp, CAS_HP_FIRMWARE);
 	} else {
 		cas_load_firmware(cp, CAS_HP_ALT_FIRMWARE);
@@ -4971,7 +4971,7 @@
 					  cas_cacheline_size)) {
 			dev_err(&pdev->dev, "Could not set PCI cache "
 			       "line size\n");
-			goto err_write_cacheline;
+			goto err_out_free_res;
 		}
 	}
 #endif
@@ -5138,13 +5138,14 @@
 		cas_shutdown(cp);
 	mutex_unlock(&cp->pm_mutex);
 
+	vfree(cp->fw_data);
+
 	pci_iounmap(pdev, cp->regs);
 
 
 err_out_free_res:
 	pci_release_regions(pdev);
 
-err_write_cacheline:
 	/* Try to restore it in case the error occurred after we
 	 * set it.
 	 */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/sun/ldmvsw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/sun/ldmvsw.c
@@ -290,6 +290,9 @@
 
 	hp = mdesc_grab();
 
+	if (!hp)
+		return -ENODEV;
+
 	rmac = mdesc_get_property(hp, vdev->mp, remote_macaddr_prop, &len);
 	err = -ENODEV;
 	if (!rmac) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/sun/niu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/sun/niu.c
@@ -429,7 +429,7 @@
 	struct niu_link_config *lp = &np->link_config;
 	u16 pll_cfg, pll_sts;
 	int max_retry = 100;
-	u64 uninitialized_var(sig), mask, val;
+	u64 sig, mask, val;
 	u32 tx_cfg, rx_cfg;
 	unsigned long i;
 	int err;
@@ -526,7 +526,7 @@
 	struct niu_link_config *lp = &np->link_config;
 	u32 tx_cfg, rx_cfg, pll_cfg, pll_sts;
 	int max_retry = 100;
-	u64 uninitialized_var(sig), mask, val;
+	u64 sig, mask, val;
 	unsigned long i;
 	int err;
 
@@ -714,7 +714,7 @@
 
 static int esr_reset(struct niu *np)
 {
-	u32 uninitialized_var(reset);
+	u32 reset;
 	int err;
 
 	err = mdio_write(np, np->port, NIU_ESR_DEV_ADDR,
@@ -3931,8 +3931,6 @@
 		mp->rx_mcasts += RXMAC_MC_FRM_CNT_COUNT;
 	if (val & XRXMAC_STATUS_RXBCAST_CNT_EXP)
 		mp->rx_bcasts += RXMAC_BC_FRM_CNT_COUNT;
-	if (val & XRXMAC_STATUS_RXBCAST_CNT_EXP)
-		mp->rx_bcasts += RXMAC_BC_FRM_CNT_COUNT;
 	if (val & XRXMAC_STATUS_RXHIST1_CNT_EXP)
 		mp->rx_hist_cnt1 += RXMAC_HIST_CNT1_COUNT;
 	if (val & XRXMAC_STATUS_RXHIST2_CNT_EXP)
@@ -4505,7 +4503,7 @@
 
 		err = niu_rbr_fill(np, rp, GFP_KERNEL);
 		if (err)
-			return err;
+			goto out_err;
 	}
 
 	tx_rings = kcalloc(num_tx_rings, sizeof(struct tx_ring_info),
@@ -8146,10 +8144,10 @@
 				     "VPD_SCAN: Reading in property [%s] len[%d]\n",
 				     namebuf, prop_len);
 			for (i = 0; i < prop_len; i++) {
-				err = niu_pci_eeprom_read(np, off + i);
-				if (err >= 0)
-					*prop_buf = err;
-				++prop_buf;
+				err =  niu_pci_eeprom_read(np, off + i);
+				if (err < 0)
+					return err;
+				*prop_buf++ = err;
 			}
 		}
 
@@ -8160,14 +8158,14 @@
 }
 
 /* ESPC_PIO_EN_ENABLE must be set */
-static void niu_pci_vpd_fetch(struct niu *np, u32 start)
+static int niu_pci_vpd_fetch(struct niu *np, u32 start)
 {
 	u32 offset;
 	int err;
 
 	err = niu_pci_eeprom_read16_swp(np, start + 1);
 	if (err < 0)
-		return;
+		return err;
 
 	offset = err + 3;
 
@@ -8176,12 +8174,14 @@
 		u32 end;
 
 		err = niu_pci_eeprom_read(np, here);
+		if (err < 0)
+			return err;
 		if (err != 0x90)
-			return;
+			return -EINVAL;
 
 		err = niu_pci_eeprom_read16_swp(np, here + 1);
 		if (err < 0)
-			return;
+			return err;
 
 		here = start + offset + 3;
 		end = start + offset + err;
@@ -8189,9 +8189,13 @@
 		offset += err;
 
 		err = niu_pci_vpd_scan_props(np, here, end);
-		if (err < 0 || err == 1)
-			return;
+		if (err < 0)
+			return err;
+		/* ret == 1 is not an error */
+		if (err == 1)
+			return 0;
 	}
+	return 0;
 }
 
 /* ESPC_PIO_EN_ENABLE must be set */
@@ -9282,8 +9286,11 @@
 		offset = niu_pci_vpd_offset(np);
 		netif_printk(np, probe, KERN_DEBUG, np->dev,
 			     "%s() VPD offset [%08x]\n", __func__, offset);
-		if (offset)
-			niu_pci_vpd_fetch(np, offset);
+		if (offset) {
+			err = niu_pci_vpd_fetch(np, offset);
+			if (err < 0)
+				return err;
+		}
 		nw64(ESPC_PIO_EN, 0);
 
 		if (np->flags & NIU_FLAGS_VPD_VALID) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/sun/sungem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/sun/sungem.c
@@ -959,17 +959,6 @@
 	return IRQ_HANDLED;
 }
 
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void gem_poll_controller(struct net_device *dev)
-{
-	struct gem *gp = netdev_priv(dev);
-
-	disable_irq(gp->pdev->irq);
-	gem_interrupt(gp->pdev->irq, dev);
-	enable_irq(gp->pdev->irq);
-}
-#endif
-
 static void gem_tx_timeout(struct net_device *dev)
 {
 	struct gem *gp = netdev_priv(dev);
@@ -2835,9 +2824,6 @@
 	.ndo_change_mtu		= gem_change_mtu,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_mac_address    = gem_set_mac_address,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller    = gem_poll_controller,
-#endif
 };
 
 static int gem_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/sun/sunhme.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/sun/sunhme.c
@@ -2064,9 +2064,9 @@
 
 			skb_reserve(copy_skb, 2);
 			skb_put(copy_skb, len);
-			dma_sync_single_for_cpu(hp->dma_dev, dma_addr, len, DMA_FROM_DEVICE);
+			dma_sync_single_for_cpu(hp->dma_dev, dma_addr, len + 2, DMA_FROM_DEVICE);
 			skb_copy_from_linear_data(skb, copy_skb->data, len);
-			dma_sync_single_for_device(hp->dma_dev, dma_addr, len, DMA_FROM_DEVICE);
+			dma_sync_single_for_device(hp->dma_dev, dma_addr, len + 2, DMA_FROM_DEVICE);
 			/* Reuse original ring buffer. */
 			hme_write_rxd(hp, this,
 				      (RXFLAG_OWN|((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)),
@@ -3164,7 +3164,7 @@
 	if (err) {
 		printk(KERN_ERR "happymeal(PCI): Cannot register net device, "
 		       "aborting.\n");
-		goto err_out_iounmap;
+		goto err_out_free_coherent;
 	}
 
 	pci_set_drvdata(pdev, hp);
@@ -3197,6 +3197,10 @@
 
 	return 0;
 
+err_out_free_coherent:
+	dma_free_coherent(hp->dma_dev, PAGE_SIZE,
+			  hp->happy_block, hp->hblock_dvma);
+
 err_out_iounmap:
 	iounmap(hp->gregs);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/sun/sunvnet.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/sun/sunvnet.c
@@ -431,6 +431,9 @@
 
 	hp = mdesc_grab();
 
+	if (!hp)
+		return -ENODEV;
+
 	vp = vnet_find_parent(hp, vdev->mp, vdev);
 	if (IS_ERR(vp)) {
 		pr_err("Cannot find port parent vnet\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/sun/sunvnet_common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/sun/sunvnet_common.c
@@ -1353,27 +1353,12 @@
 		if (vio_version_after_eq(&port->vio, 1, 3))
 			localmtu -= VLAN_HLEN;
 
-		if (skb->protocol == htons(ETH_P_IP)) {
-			struct flowi4 fl4;
-			struct rtable *rt = NULL;
-
-			memset(&fl4, 0, sizeof(fl4));
-			fl4.flowi4_oif = dev->ifindex;
-			fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos);
-			fl4.daddr = ip_hdr(skb)->daddr;
-			fl4.saddr = ip_hdr(skb)->saddr;
-
-			rt = ip_route_output_key(dev_net(dev), &fl4);
-			if (!IS_ERR(rt)) {
-				skb_dst_set(skb, &rt->dst);
-				icmp_send(skb, ICMP_DEST_UNREACH,
-					  ICMP_FRAG_NEEDED,
-					  htonl(localmtu));
-			}
-		}
+		if (skb->protocol == htons(ETH_P_IP))
+			icmp_ndo_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
+				      htonl(localmtu));
 #if IS_ENABLED(CONFIG_IPV6)
 		else if (skb->protocol == htons(ETH_P_IPV6))
-			icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, localmtu);
+			icmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, localmtu);
 #endif
 		goto out_dropped;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/synopsys/dwc-xlgmac-common.c
@@ -513,7 +513,7 @@
 
 void xlgmac_print_all_hw_features(struct xlgmac_pdata *pdata)
 {
-	char *str = NULL;
+	char __maybe_unused *str = NULL;
 
 	XLGMAC_PR("\n");
 	XLGMAC_PR("=====================================================\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/tehuti/tehuti.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/tehuti/tehuti.c
@@ -2052,6 +2052,7 @@
 		/*bdx_hw_reset(priv); */
 		if (bdx_read_mac(priv)) {
 			pr_err("load MAC address failed\n");
+			err = -EFAULT;
 			goto err_out_iomap;
 		}
 		SET_NETDEV_DEV(ndev, &pdev->dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/ti/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/ti/Kconfig
@@ -22,6 +22,7 @@
 	depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 ) || COMPILE_TEST
 	select TI_DAVINCI_MDIO
 	select PHYLIB
+	select GENERIC_ALLOCATOR
 	---help---
 	  This driver supports TI's DaVinci Ethernet .
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/ti/cpsw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/ti/cpsw.c
@@ -890,8 +890,8 @@
 {
 	struct cpsw_common *cpsw = dev_id;
 
-	cpdma_ctlr_eoi(cpsw->dma, CPDMA_EOI_RX);
 	writel(0, &cpsw->wr_regs->rx_en);
+	cpdma_ctlr_eoi(cpsw->dma, CPDMA_EOI_RX);
 
 	if (cpsw->quirk_irq) {
 		disable_irq_nosync(cpsw->irqs_table[0]);
@@ -1753,6 +1753,8 @@
 
 err_cleanup:
 	if (!cpsw->usage_count) {
+		napi_disable(&cpsw->napi_rx);
+		napi_disable(&cpsw->napi_tx);
 		cpdma_ctlr_stop(cpsw->dma);
 		cpsw_destroy_xdp_rxqs(cpsw);
 	}
@@ -2209,7 +2211,7 @@
 				  HOST_PORT_NUM, ALE_VLAN, vid);
 	ret |= cpsw_ale_del_mcast(cpsw->ale, priv->ndev->broadcast,
 				  0, ALE_VLAN, vid);
-	ret |= cpsw_ale_flush_multicast(cpsw->ale, 0, vid);
+	ret |= cpsw_ale_flush_multicast(cpsw->ale, ALE_PORT_HOST, vid);
 err:
 	pm_runtime_put(cpsw->dev);
 	return ret;
@@ -2876,6 +2878,7 @@
 				       CPSW_MAX_QUEUES, CPSW_MAX_QUEUES);
 	if (!ndev) {
 		dev_err(dev, "error allocating net_device\n");
+		ret = -ENOMEM;
 		goto clean_cpts;
 	}
 
@@ -2999,11 +3002,15 @@
 	struct cpsw_common *cpsw = dev_get_drvdata(dev);
 	int i;
 
+	rtnl_lock();
+
 	for (i = 0; i < cpsw->data.slaves; i++)
 		if (cpsw->slaves[i].ndev)
 			if (netif_running(cpsw->slaves[i].ndev))
 				cpsw_ndo_stop(cpsw->slaves[i].ndev);
 
+	rtnl_unlock();
+
 	/* Select sleep pin state */
 	pinctrl_pm_select_sleep_state(dev);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/ti/cpsw_ale.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/ti/cpsw_ale.c
@@ -60,23 +60,37 @@
 
 static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits)
 {
-	int idx;
+	int idx, idx2, index;
+	u32 hi_val = 0;
 
 	idx    = start / 32;
+	idx2 = (start + bits - 1) / 32;
+	/* Check if bits to be fetched exceed a word */
+	if (idx != idx2) {
+		index = 2 - idx2; /* flip */
+		hi_val = ale_entry[index] << ((idx2 * 32) - start);
+	}
 	start -= idx * 32;
 	idx    = 2 - idx; /* flip */
-	return (ale_entry[idx] >> start) & BITMASK(bits);
+	return (hi_val + (ale_entry[idx] >> start)) & BITMASK(bits);
 }
 
 static inline void cpsw_ale_set_field(u32 *ale_entry, u32 start, u32 bits,
 				      u32 value)
 {
-	int idx;
+	int idx, idx2, index;
 
 	value &= BITMASK(bits);
-	idx    = start / 32;
+	idx = start / 32;
+	idx2 = (start + bits - 1) / 32;
+	/* Check if bits to be set exceed a word */
+	if (idx != idx2) {
+		index = 2 - idx2; /* flip */
+		ale_entry[index] &= ~(BITMASK(bits + start - (idx2 * 32)));
+		ale_entry[index] |= (value >> ((idx2 * 32) - start));
+	}
 	start -= idx * 32;
-	idx    = 2 - idx; /* flip */
+	idx = 2 - idx; /* flip */
 	ale_entry[idx] &= ~(BITMASK(bits) << start);
 	ale_entry[idx] |=  (value << start);
 }
@@ -779,6 +793,7 @@
 void cpsw_ale_stop(struct cpsw_ale *ale)
 {
 	del_timer_sync(&ale->timer);
+	cpsw_ale_control_set(ale, 0, ALE_CLEAR, 1);
 	cpsw_ale_control_set(ale, 0, ALE_ENABLE, 0);
 }
 
@@ -862,6 +877,7 @@
 					ALE_UNKNOWNVLAN_FORCE_UNTAG_EGRESS;
 	}
 
+	cpsw_ale_control_set(ale, 0, ALE_CLEAR, 1);
 	return ale;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/ti/cpts.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/ti/cpts.c
@@ -454,7 +454,9 @@
 	for (i = 0; i < CPTS_MAX_EVENTS; i++)
 		list_add(&cpts->pool_data[i].list, &cpts->pool);
 
-	clk_enable(cpts->refclk);
+	err = clk_enable(cpts->refclk);
+	if (err)
+		return err;
 
 	cpts_write32(cpts, CPTS_EN, control);
 	cpts_write32(cpts, TS_PEND_EN, int_enable);
@@ -485,6 +487,7 @@
 
 	ptp_clock_unregister(cpts->clock);
 	cpts->clock = NULL;
+	cpts->phc_index = -1;
 
 	cpts_write32(cpts, 0, int_enable);
 	cpts_write32(cpts, 0, control);
@@ -667,6 +670,7 @@
 	cpts->cc.read = cpts_systim_read;
 	cpts->cc.mask = CLOCKSOURCE_MASK(32);
 	cpts->info = cpts_info;
+	cpts->phc_index = -1;
 
 	cpts_calc_mult_shift(cpts);
 	/* save cc.mult original value as it can be modified
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/ti/davinci_cpdma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/ti/davinci_cpdma.c
@@ -1018,7 +1018,6 @@
 	struct cpdma_chan		*chan = si->chan;
 	struct cpdma_ctlr		*ctlr = chan->ctlr;
 	int				len = si->len;
-	int				swlen = len;
 	struct cpdma_desc __iomem	*desc;
 	dma_addr_t			buffer;
 	u32				mode;
@@ -1046,7 +1045,6 @@
 	if (si->data_dma) {
 		buffer = si->data_dma;
 		dma_sync_single_for_device(ctlr->dev, buffer, len, chan->dir);
-		swlen |= CPDMA_DMA_EXT_MAP;
 	} else {
 		buffer = dma_map_single(ctlr->dev, si->data_virt, len, chan->dir);
 		ret = dma_mapping_error(ctlr->dev, buffer);
@@ -1065,7 +1063,8 @@
 	writel_relaxed(mode | len, &desc->hw_mode);
 	writel_relaxed((uintptr_t)si->token, &desc->sw_token);
 	writel_relaxed(buffer, &desc->sw_buffer);
-	writel_relaxed(swlen, &desc->sw_len);
+	writel_relaxed(si->data_dma ? len | CPDMA_DMA_EXT_MAP : len,
+		       &desc->sw_len);
 	desc_read(desc, sw_len);
 
 	__cpdma_chan_submit(chan, desc);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/ti/davinci_emac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/ti/davinci_emac.c
@@ -169,11 +169,11 @@
 /* EMAC mac_status register */
 #define EMAC_MACSTATUS_TXERRCODE_MASK	(0xF00000)
 #define EMAC_MACSTATUS_TXERRCODE_SHIFT	(20)
-#define EMAC_MACSTATUS_TXERRCH_MASK	(0x7)
+#define EMAC_MACSTATUS_TXERRCH_MASK	(0x70000)
 #define EMAC_MACSTATUS_TXERRCH_SHIFT	(16)
 #define EMAC_MACSTATUS_RXERRCODE_MASK	(0xF000)
 #define EMAC_MACSTATUS_RXERRCODE_SHIFT	(12)
-#define EMAC_MACSTATUS_RXERRCH_MASK	(0x7)
+#define EMAC_MACSTATUS_RXERRCH_MASK	(0x700)
 #define EMAC_MACSTATUS_RXERRCH_SHIFT	(8)
 
 /* EMAC RX register masks */
@@ -412,8 +412,20 @@
 	u32 int_ctrl, num_interrupts = 0;
 	u32 prescale = 0, addnl_dvdr = 1, coal_intvl = 0;
 
-	if (!coal->rx_coalesce_usecs)
-		return -EINVAL;
+	if (!coal->rx_coalesce_usecs) {
+		priv->coal_intvl = 0;
+
+		switch (priv->version) {
+		case EMAC_VERSION_2:
+			emac_ctrl_write(EMAC_DM646X_CMINTCTRL, 0);
+			break;
+		default:
+			emac_ctrl_write(EMAC_CTRL_EWINTTCNT, 0);
+			break;
+		}
+
+		return 0;
+	}
 
 	coal_intvl = coal->rx_coalesce_usecs;
 
@@ -1226,7 +1238,7 @@
 	struct net_device *ndev = priv->ndev;
 	struct device *emac_dev = &ndev->dev;
 	u32 status = 0;
-	u32 num_tx_pkts = 0, num_rx_pkts = 0;
+	u32 num_rx_pkts = 0;
 
 	/* Check interrupt vectors and call packet processing */
 	status = emac_read(EMAC_MACINVECTOR);
@@ -1237,8 +1249,7 @@
 		mask = EMAC_DM646X_MAC_IN_VECTOR_TX_INT_VEC;
 
 	if (status & mask) {
-		num_tx_pkts = cpdma_chan_process(priv->txchan,
-					      EMAC_DEF_TX_MAX_SERVICE);
+		cpdma_chan_process(priv->txchan, EMAC_DEF_TX_MAX_SERVICE);
 	} /* TX processing */
 
 	mask = EMAC_DM644X_MAC_IN_VECTOR_RX_INT_VEC;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/ti/davinci_mdio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/ti/davinci_mdio.c
@@ -397,6 +397,8 @@
 	data->dev = dev;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -EINVAL;
 	data->regs = devm_ioremap(dev, res->start, resource_size(res));
 	if (!data->regs)
 		return -ENOMEM;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/ti/netcp_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/ti/netcp_core.c
@@ -1262,7 +1262,7 @@
 }
 
 /* Submit the packet */
-static int netcp_ndo_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+static netdev_tx_t netcp_ndo_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 {
 	struct netcp_intf *netcp = netdev_priv(ndev);
 	struct netcp_stats *tx_stats = &netcp->stats;
@@ -1350,9 +1350,9 @@
 	tx_pipe->dma_queue = knav_queue_open(name, tx_pipe->dma_queue_id,
 					     KNAV_QUEUE_SHARED);
 	if (IS_ERR(tx_pipe->dma_queue)) {
+		ret = PTR_ERR(tx_pipe->dma_queue);
 		dev_err(dev, "Could not open DMA queue for channel \"%s\": %d\n",
 			name, ret);
-		ret = PTR_ERR(tx_pipe->dma_queue);
 		goto err;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/ti/tlan.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/ti/tlan.c
@@ -314,9 +314,8 @@
 	pci_release_regions(pdev);
 #endif
 
-	free_netdev(dev);
-
 	cancel_work_sync(&priv->tlan_tqueue);
+	free_netdev(dev);
 }
 
 static void tlan_start(struct net_device *dev)
@@ -673,7 +672,6 @@
 static void  __init tlan_eisa_probe(void)
 {
 	long	ioaddr;
-	int	rc = -ENODEV;
 	int	irq;
 	u16	device_id;
 
@@ -738,8 +736,7 @@
 
 
 		/* Setup the newly found eisa adapter */
-		rc = tlan_probe1(NULL, ioaddr, irq,
-				 12, NULL);
+		tlan_probe1(NULL, ioaddr, irq, 12, NULL);
 		continue;
 
 out:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/toshiba/ps3_gelic_net.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/toshiba/ps3_gelic_net.c
@@ -317,15 +317,17 @@
 
 	/* set up the hardware pointers in each descriptor */
 	for (i = 0; i < no; i++, descr++) {
+		dma_addr_t cpu_addr;
+
 		gelic_descr_set_status(descr, GELIC_DESCR_DMA_NOT_IN_USE);
-		descr->bus_addr =
-			dma_map_single(ctodev(card), descr,
-				       GELIC_DESCR_SIZE,
-				       DMA_BIDIRECTIONAL);
 
-		if (!descr->bus_addr)
+		cpu_addr = dma_map_single(ctodev(card), descr,
+					  GELIC_DESCR_SIZE, DMA_BIDIRECTIONAL);
+
+		if (dma_mapping_error(ctodev(card), cpu_addr))
 			goto iommu_error;
 
+		descr->bus_addr = cpu_to_be32(cpu_addr);
 		descr->next = descr + 1;
 		descr->prev = descr - 1;
 	}
@@ -365,28 +367,30 @@
  *
  * allocates a new rx skb, iommu-maps it and attaches it to the descriptor.
  * Activate the descriptor state-wise
+ *
+ * Gelic RX sk_buffs must be aligned to GELIC_NET_RXBUF_ALIGN and the length
+ * must be a multiple of GELIC_NET_RXBUF_ALIGN.
  */
 static int gelic_descr_prepare_rx(struct gelic_card *card,
 				  struct gelic_descr *descr)
 {
+	static const unsigned int rx_skb_size =
+		ALIGN(GELIC_NET_MAX_FRAME, GELIC_NET_RXBUF_ALIGN) +
+		GELIC_NET_RXBUF_ALIGN - 1;
+	dma_addr_t cpu_addr;
 	int offset;
-	unsigned int bufsize;
 
 	if (gelic_descr_get_status(descr) !=  GELIC_DESCR_DMA_NOT_IN_USE)
 		dev_info(ctodev(card), "%s: ERROR status\n", __func__);
-	/* we need to round up the buffer size to a multiple of 128 */
-	bufsize = ALIGN(GELIC_NET_MAX_MTU, GELIC_NET_RXBUF_ALIGN);
 
-	/* and we need to have it 128 byte aligned, therefore we allocate a
-	 * bit more */
-	descr->skb = dev_alloc_skb(bufsize + GELIC_NET_RXBUF_ALIGN - 1);
+	descr->skb = netdev_alloc_skb(*card->netdev, rx_skb_size);
 	if (!descr->skb) {
 		descr->buf_addr = 0; /* tell DMAC don't touch memory */
 		dev_info(ctodev(card),
 			 "%s:allocate skb failed !!\n", __func__);
 		return -ENOMEM;
 	}
-	descr->buf_size = cpu_to_be32(bufsize);
+	descr->buf_size = cpu_to_be32(rx_skb_size);
 	descr->dmac_cmd_status = 0;
 	descr->result_size = 0;
 	descr->valid_size = 0;
@@ -397,11 +401,10 @@
 	if (offset)
 		skb_reserve(descr->skb, GELIC_NET_RXBUF_ALIGN - offset);
 	/* io-mmu-map the skb */
-	descr->buf_addr = cpu_to_be32(dma_map_single(ctodev(card),
-						     descr->skb->data,
-						     GELIC_NET_MAX_MTU,
-						     DMA_FROM_DEVICE));
-	if (!descr->buf_addr) {
+	cpu_addr = dma_map_single(ctodev(card), descr->skb->data,
+				  GELIC_NET_MAX_FRAME, DMA_FROM_DEVICE);
+	descr->buf_addr = cpu_to_be32(cpu_addr);
+	if (dma_mapping_error(ctodev(card), cpu_addr)) {
 		dev_kfree_skb_any(descr->skb);
 		descr->skb = NULL;
 		dev_info(ctodev(card),
@@ -781,7 +784,7 @@
 
 	buf = dma_map_single(ctodev(card), skb->data, skb->len, DMA_TO_DEVICE);
 
-	if (!buf) {
+	if (dma_mapping_error(ctodev(card), buf)) {
 		dev_err(ctodev(card),
 			"dma map 2 failed (%p, %i). Dropping packet\n",
 			skb->data, skb->len);
@@ -917,7 +920,7 @@
 	data_error = be32_to_cpu(descr->data_error);
 	/* unmap skb buffer */
 	dma_unmap_single(ctodev(card), be32_to_cpu(descr->buf_addr),
-			 GELIC_NET_MAX_MTU,
+			 GELIC_NET_MAX_FRAME,
 			 DMA_FROM_DEVICE);
 
 	skb_put(skb, be32_to_cpu(descr->valid_size)?
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/toshiba/ps3_gelic_net.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/toshiba/ps3_gelic_net.h
@@ -19,8 +19,9 @@
 #define GELIC_NET_RX_DESCRIPTORS        128 /* num of descriptors */
 #define GELIC_NET_TX_DESCRIPTORS        128 /* num of descriptors */
 
-#define GELIC_NET_MAX_MTU               VLAN_ETH_FRAME_LEN
-#define GELIC_NET_MIN_MTU               VLAN_ETH_ZLEN
+#define GELIC_NET_MAX_FRAME             2312
+#define GELIC_NET_MAX_MTU               2294
+#define GELIC_NET_MIN_MTU               64
 #define GELIC_NET_RXBUF_ALIGN           128
 #define GELIC_CARD_RX_CSUM_DEFAULT      1 /* hw chksum */
 #define GELIC_NET_WATCHDOG_TIMEOUT      5*HZ
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
@@ -1217,7 +1217,7 @@
 		key_index = wl->current_key;
 
 	if (!enc->length && (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)) {
-		/* reques to change default key index */
+		/* request to change default key index */
 		pr_debug("%s: request to change default key to %d\n",
 			 __func__, key_index);
 		wl->current_key = key_index;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/toshiba/spider_net.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/toshiba/spider_net.c
@@ -283,8 +283,8 @@
 		descr = descr->next;
 	} while (descr != chain->ring);
 
-	dma_free_coherent(&card->pdev->dev, chain->num_desc,
-	    chain->hwring, chain->dma_addr);
+	dma_free_coherent(&card->pdev->dev, chain->num_desc * sizeof(struct spider_net_hw_descr),
+			  chain->hwring, chain->dma_addr);
 }
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/toshiba/tc35815.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/toshiba/tc35815.c
@@ -644,7 +644,7 @@
 		linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, mask);
 		linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, mask);
 	}
-	linkmode_and(phydev->supported, phydev->supported, mask);
+	linkmode_andnot(phydev->supported, phydev->supported, mask);
 	linkmode_copy(phydev->advertising, phydev->supported);
 
 	lp->link = 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/tundra/tsi108_eth.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/tundra/tsi108_eth.c
@@ -1302,12 +1302,15 @@
 
 	data->rxring = dma_alloc_coherent(&data->pdev->dev, rxring_size,
 					  &data->rxdma, GFP_KERNEL);
-	if (!data->rxring)
+	if (!data->rxring) {
+		free_irq(data->irq_num, dev);
 		return -ENOMEM;
+	}
 
 	data->txring = dma_alloc_coherent(&data->pdev->dev, txring_size,
 					  &data->txdma, GFP_KERNEL);
 	if (!data->txring) {
+		free_irq(data->irq_num, dev);
 		dma_free_coherent(&data->pdev->dev, rxring_size, data->rxring,
 				    data->rxdma);
 		return -ENOMEM;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/via/via-velocity.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/via/via-velocity.c
@@ -865,26 +865,13 @@
  */
 static int velocity_set_media_mode(struct velocity_info *vptr, u32 mii_status)
 {
-	u32 curr_status;
 	struct mac_regs __iomem *regs = vptr->mac_regs;
 
 	vptr->mii_status = mii_check_media_mode(vptr->mac_regs);
-	curr_status = vptr->mii_status & (~VELOCITY_LINK_FAIL);
 
 	/* Set mii link status */
 	set_mii_flow_control(vptr);
 
-	/*
-	   Check if new status is consistent with current status
-	   if (((mii_status & curr_status) & VELOCITY_AUTONEG_ENABLE) ||
-	       (mii_status==curr_status)) {
-	   vptr->mii_status=mii_check_media_mode(vptr->mac_regs);
-	   vptr->mii_status=check_connection_type(vptr->mac_regs);
-	   VELOCITY_PRT(MSG_LEVEL_INFO, "Velocity link no change\n");
-	   return 0;
-	   }
-	 */
-
 	if (PHYID_GET_PHY_ID(vptr->phy_id) == PHYID_CICADA_CS8201)
 		MII_REG_BITS_ON(AUXCR_MDPPS, MII_NCONFIG, vptr->mac_regs);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/wiznet/w5100.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/wiznet/w5100.c
@@ -1052,6 +1052,8 @@
 		mac_addr = data->mac_addr;
 
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem)
+		return -EINVAL;
 	if (resource_size(mem) < W5100_BUS_DIRECT_SIZE)
 		ops = &w5100_mmio_indirect_ops;
 	else
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/xilinx/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/xilinx/Kconfig
@@ -1,12 +1,11 @@
 # SPDX-License-Identifier: GPL-2.0-only
 #
-# Xilink device configuration
+# Xilinx device configuration
 #
 
 config NET_VENDOR_XILINX
 	bool "Xilinx devices"
 	default y
-	depends on PPC || PPC32 || MICROBLAZE || ARCH_ZYNQ || MIPS || X86 || ARM || COMPILE_TEST
 	---help---
 	  If you have a network (Ethernet) card belonging to this class, say Y.
 
@@ -19,18 +18,30 @@
 
 config XILINX_EMACLITE
 	tristate "Xilinx 10/100 Ethernet Lite support"
-	depends on PPC32 || MICROBLAZE || ARCH_ZYNQ || MIPS
 	select PHYLIB
+	depends on HAS_IOMEM
 	---help---
 	  This driver supports the 10/100 Ethernet Lite from Xilinx.
 
 config XILINX_AXI_EMAC
 	tristate "Xilinx 10/100/1000 AXI Ethernet support"
-	depends on MICROBLAZE || X86 || ARM || COMPILE_TEST
-	select PHYLINK
+	select PHYLIB
 	---help---
 	  This driver supports the 10/100/1000 Ethernet from Xilinx for the
-	  AXI bus interface used in Xilinx Virtex FPGAs.
+	  AXI bus interface used in Xilinx Virtex FPGAs and Soc's.
+config XILINX_AXI_EMAC_HWTSTAMP
+	bool "Generate hardware packet timestamps"
+	depends on XILINX_AXI_EMAC
+	select PTP_1588_CLOCK
+	default n
+	---help---
+	  Generate hardware packet timestamps. This is to facilitate IEE 1588.
+config  AXIENET_HAS_MCDMA
+	bool "AXI Ethernet is configured with MCDMA"
+	depends on XILINX_AXI_EMAC
+	default n
+	---help---
+	  When hardware is generated with AXI Ethernet with MCDMA select this option.
 
 config XILINX_LL_TEMAC
 	tristate "Xilinx LL TEMAC (LocalLink Tri-mode Ethernet MAC) driver"
@@ -40,4 +51,54 @@
 	  This driver supports the Xilinx 10/100/1000 LocalLink TEMAC
 	  core used in Xilinx Spartan and Virtex FPGAs
 
+config XILINX_TSN
+	bool "Enable Xilinx's TSN IP"
+	default n
+	---help---
+	  Enable Xilinx's TSN IP.
+
+config XILINX_TSN_PTP
+	bool "Generate hardware packet timestamps using Xilinx's TSN IP"
+	depends on XILINX_TSN
+	select PTP_1588_CLOCK
+	default y
+	---help---
+	  Generate hardare packet timestamps. This is to facilitate IEE 1588.
+
+config XILINX_TSN_QBV
+	bool "Support Qbv protocol in TSN"
+	depends on XILINX_TSN_PTP
+	select PTP_1588_CLOCK
+	default y
+	---help---
+	  Enables TSN Qbv protocol.
+
+config XILINX_TSN_SWITCH
+	bool "Support TSN switch"
+	depends on XILINX_TSN
+	default y
+	---help---
+	  Enable Xilinx's TSN Switch support.
+
+config XILINX_TSN_QCI
+	bool "Support Qci protocol in TSN"
+	depends on XILINX_TSN_SWITCH
+	default y
+	---help---
+	  Enable TSN QCI protocol.
+
+config XILINX_TSN_CB
+	bool "Support CB protocol in TSN"
+	depends on XILINX_TSN_SWITCH
+	default y
+	---help---
+	  Enable TSN CB protocol support.
+
+config XILINX_TSN_QBR
+       bool "Support QBR protocol in TSN"
+       depends on XILINX_TSN_SWITCH
+       default y
+       ---help---
+         Enable TSN QBR protocol support.
+
 endif # NET_VENDOR_XILINX
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/xilinx/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/xilinx/Makefile
@@ -1,10 +1,18 @@
 # SPDX-License-Identifier: GPL-2.0
 #
-# Makefile for the Xilink network device drivers.
+# Makefile for the Xilinx network device drivers.
 #
 
 ll_temac-objs := ll_temac_main.o ll_temac_mdio.o
 obj-$(CONFIG_XILINX_LL_TEMAC) += ll_temac.o
 obj-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite.o
-xilinx_emac-objs := xilinx_axienet_main.o xilinx_axienet_mdio.o
+obj-$(CONFIG_XILINX_TSN) += xilinx_tsn_ep.o
+obj-$(CONFIG_XILINX_TSN_PTP) += xilinx_tsn_ptp_xmit.o xilinx_tsn_ptp_clock.o
+obj-$(CONFIG_XILINX_TSN_QBV) += xilinx_tsn_shaper.o
+obj-$(CONFIG_XILINX_TSN_QCI) += xilinx_tsn_qci.o
+obj-$(CONFIG_XILINX_TSN_CB) += xilinx_tsn_cb.o
+obj-$(CONFIG_XILINX_TSN_SWITCH) += xilinx_tsn_switch.o
+xilinx_emac-objs := xilinx_axienet_main.o xilinx_axienet_mdio.o xilinx_axienet_dma.o
 obj-$(CONFIG_XILINX_AXI_EMAC) += xilinx_emac.o
+obj-$(CONFIG_XILINX_TSN_QBR) += xilinx_tsn_preemption.o
+obj-$(CONFIG_AXIENET_HAS_MCDMA) += xilinx_axienet_mcdma.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/xilinx/ll_temac.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/xilinx/ll_temac.h
@@ -375,10 +375,14 @@
 	int tx_bd_next;
 	int tx_bd_tail;
 	int rx_bd_ci;
+	int rx_bd_tail;
 
 	/* DMA channel control setup */
 	u32 tx_chnl_ctrl;
 	u32 rx_chnl_ctrl;
+	u8 coalesce_count_rx;
+
+	struct delayed_work restart_work;
 };
 
 /* Wrappers for temac_ior()/temac_iow() function pointers above */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/xilinx/ll_temac_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/xilinx/ll_temac_main.c
@@ -51,6 +51,7 @@
 #include <linux/ip.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
+#include <linux/workqueue.h>
 #include <linux/dma-mapping.h>
 #include <linux/processor.h>
 #include <linux/platform_data/xilinx-ll-temac.h>
@@ -102,7 +103,7 @@
  */
 #define HARD_ACS_RDY_POLL_NS (20 * NSEC_PER_MSEC)
 
-/**
+/*
  * temac_indirect_busywait - Wait for current indirect register access
  * to complete.
  */
@@ -117,7 +118,7 @@
 		return 0;
 }
 
-/**
+/*
  * temac_indirect_in32 - Indirect register read access.  This function
  * must be called without lp->indirect_lock being held.
  */
@@ -132,7 +133,7 @@
 	return val;
 }
 
-/**
+/*
  * temac_indirect_in32_locked - Indirect register read access.  This
  * function must be called with lp->indirect_lock being held.  Use
  * this together with spin_lock_irqsave/spin_lock_irqrestore to avoid
@@ -160,7 +161,7 @@
 	return temac_ior(lp, XTE_LSW0_OFFSET);
 }
 
-/**
+/*
  * temac_indirect_out32 - Indirect register write access.  This function
  * must be called without lp->indirect_lock being held.
  */
@@ -173,7 +174,7 @@
 	spin_unlock_irqrestore(lp->indirect_lock, flags);
 }
 
-/**
+/*
  * temac_indirect_out32_locked - Indirect register write access.  This
  * function must be called with lp->indirect_lock being held.  Use
  * this together with spin_lock_irqsave/spin_lock_irqrestore to avoid
@@ -198,7 +199,7 @@
 	WARN_ON(temac_indirect_busywait(lp));
 }
 
-/**
+/*
  * temac_dma_in32_* - Memory mapped DMA read, these function expects a
  * register input that is based on DCR word addresses which are then
  * converted to memory mapped byte addresses.  To be assigned to
@@ -214,7 +215,7 @@
 	return ioread32(lp->sdma_regs + (reg << 2));
 }
 
-/**
+/*
  * temac_dma_out32_* - Memory mapped DMA read, these function expects
  * a register input that is based on DCR word addresses which are then
  * converted to memory mapped byte addresses.  To be assigned to
@@ -236,7 +237,7 @@
  */
 #ifdef CONFIG_PPC_DCR
 
-/**
+/*
  * temac_dma_dcr_in32 - DCR based DMA read
  */
 static u32 temac_dma_dcr_in(struct temac_local *lp, int reg)
@@ -244,7 +245,7 @@
 	return dcr_read(lp->sdma_dcrs, reg);
 }
 
-/**
+/*
  * temac_dma_dcr_out32 - DCR based DMA write
  */
 static void temac_dma_dcr_out(struct temac_local *lp, int reg, u32 value)
@@ -252,7 +253,7 @@
 	dcr_write(lp->sdma_dcrs, reg, value);
 }
 
-/**
+/*
  * temac_dcr_setup - If the DMA is DCR based, then setup the address and
  * I/O  functions
  */
@@ -289,7 +290,7 @@
 
 #endif
 
-/**
+/*
  * temac_dma_bd_release - Release buffer descriptor rings
  */
 static void temac_dma_bd_release(struct net_device *ndev)
@@ -319,7 +320,7 @@
 				lp->tx_bd_v, lp->tx_bd_p);
 }
 
-/**
+/*
  * temac_dma_bd_init - Setup buffer descriptor rings
  */
 static int temac_dma_bd_init(struct net_device *ndev)
@@ -367,6 +368,8 @@
 		skb_dma_addr = dma_map_single(ndev->dev.parent, skb->data,
 					      XTE_MAX_JUMBO_FRAME_SIZE,
 					      DMA_FROM_DEVICE);
+		if (dma_mapping_error(ndev->dev.parent, skb_dma_addr))
+			goto out;
 		lp->rx_bd_v[i].phys = cpu_to_be32(skb_dma_addr);
 		lp->rx_bd_v[i].len = cpu_to_be32(XTE_MAX_JUMBO_FRAME_SIZE);
 		lp->rx_bd_v[i].app0 = cpu_to_be32(STS_CTRL_APP0_IRQONEND);
@@ -387,12 +390,13 @@
 	lp->tx_bd_next = 0;
 	lp->tx_bd_tail = 0;
 	lp->rx_bd_ci = 0;
+	lp->rx_bd_tail = RX_BD_NUM - 1;
 
 	/* Enable RX DMA transfers */
 	wmb();
 	lp->dma_out(lp, RX_CURDESC_PTR,  lp->rx_bd_p);
 	lp->dma_out(lp, RX_TAILDESC_PTR,
-		       lp->rx_bd_p + (sizeof(*lp->rx_bd_v) * (RX_BD_NUM - 1)));
+		       lp->rx_bd_p + (sizeof(*lp->rx_bd_v) * lp->rx_bd_tail));
 
 	/* Prepare for TX DMA transfer */
 	lp->dma_out(lp, TX_CURDESC_PTR, lp->tx_bd_p);
@@ -585,7 +589,7 @@
 	{}
 };
 
-/**
+/*
  * temac_setoptions
  */
 static u32 temac_setoptions(struct net_device *ndev, u32 options)
@@ -766,12 +770,15 @@
 	stat = be32_to_cpu(cur_p->app0);
 
 	while (stat & STS_CTRL_APP0_CMPLT) {
+		/* Make sure that the other fields are read after bd is
+		 * released by dma
+		 */
+		rmb();
 		dma_unmap_single(ndev->dev.parent, be32_to_cpu(cur_p->phys),
 				 be32_to_cpu(cur_p->len), DMA_TO_DEVICE);
 		skb = (struct sk_buff *)ptr_from_txbd(cur_p);
 		if (skb)
 			dev_consume_skb_irq(skb);
-		cur_p->app0 = 0;
 		cur_p->app1 = 0;
 		cur_p->app2 = 0;
 		cur_p->app3 = 0;
@@ -780,6 +787,12 @@
 		ndev->stats.tx_packets++;
 		ndev->stats.tx_bytes += be32_to_cpu(cur_p->len);
 
+		/* app0 must be visible last, as it is used to flag
+		 * availability of the bd
+		 */
+		smp_mb();
+		cur_p->app0 = 0;
+
 		lp->tx_bd_ci++;
 		if (lp->tx_bd_ci >= TX_BD_NUM)
 			lp->tx_bd_ci = 0;
@@ -788,6 +801,9 @@
 		stat = be32_to_cpu(cur_p->app0);
 	}
 
+	/* Matches barrier in temac_start_xmit */
+	smp_mb();
+
 	netif_wake_queue(ndev);
 }
 
@@ -803,6 +819,9 @@
 		if (cur_p->app0)
 			return NETDEV_TX_BUSY;
 
+		/* Make sure to read next bd app0 after this one */
+		rmb();
+
 		tail++;
 		if (tail >= TX_BD_NUM)
 			tail = 0;
@@ -830,9 +849,19 @@
 	cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
 
 	if (temac_check_tx_bd_space(lp, num_frag + 1)) {
-		if (!netif_queue_stopped(ndev))
-			netif_stop_queue(ndev);
-		return NETDEV_TX_BUSY;
+		if (netif_queue_stopped(ndev))
+			return NETDEV_TX_BUSY;
+
+		netif_stop_queue(ndev);
+
+		/* Matches barrier in temac_start_xmit_done */
+		smp_mb();
+
+		/* Space might have just been freed - check again */
+		if (temac_check_tx_bd_space(lp, num_frag + 1))
+			return NETDEV_TX_BUSY;
+
+		netif_wake_queue(ndev);
 	}
 
 	cur_p->app0 = 0;
@@ -850,12 +879,15 @@
 	skb_dma_addr = dma_map_single(ndev->dev.parent, skb->data,
 				      skb_headlen(skb), DMA_TO_DEVICE);
 	cur_p->len = cpu_to_be32(skb_headlen(skb));
+	if (WARN_ON_ONCE(dma_mapping_error(ndev->dev.parent, skb_dma_addr))) {
+		dev_kfree_skb_any(skb);
+		ndev->stats.tx_dropped++;
+		return NETDEV_TX_OK;
+	}
 	cur_p->phys = cpu_to_be32(skb_dma_addr);
-	ptr_to_txbd((void *)skb, cur_p);
 
 	for (ii = 0; ii < num_frag; ii++) {
-		lp->tx_bd_tail++;
-		if (lp->tx_bd_tail >= TX_BD_NUM)
+		if (++lp->tx_bd_tail >= TX_BD_NUM)
 			lp->tx_bd_tail = 0;
 
 		cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
@@ -863,6 +895,27 @@
 					      skb_frag_address(frag),
 					      skb_frag_size(frag),
 					      DMA_TO_DEVICE);
+		if (dma_mapping_error(ndev->dev.parent, skb_dma_addr)) {
+			if (--lp->tx_bd_tail < 0)
+				lp->tx_bd_tail = TX_BD_NUM - 1;
+			cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
+			while (--ii >= 0) {
+				--frag;
+				dma_unmap_single(ndev->dev.parent,
+						 be32_to_cpu(cur_p->phys),
+						 skb_frag_size(frag),
+						 DMA_TO_DEVICE);
+				if (--lp->tx_bd_tail < 0)
+					lp->tx_bd_tail = TX_BD_NUM - 1;
+				cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
+			}
+			dma_unmap_single(ndev->dev.parent,
+					 be32_to_cpu(cur_p->phys),
+					 skb_headlen(skb), DMA_TO_DEVICE);
+			dev_kfree_skb_any(skb);
+			ndev->stats.tx_dropped++;
+			return NETDEV_TX_OK;
+		}
 		cur_p->phys = cpu_to_be32(skb_dma_addr);
 		cur_p->len = cpu_to_be32(skb_frag_size(frag));
 		cur_p->app0 = 0;
@@ -870,6 +923,11 @@
 	}
 	cur_p->app0 |= cpu_to_be32(STS_CTRL_APP0_EOP);
 
+	/* Mark last fragment with skb address, so it can be consumed
+	 * in temac_start_xmit_done()
+	 */
+	ptr_to_txbd((void *)skb, cur_p);
+
 	tail_p = lp->tx_bd_p + sizeof(*lp->tx_bd_v) * lp->tx_bd_tail;
 	lp->tx_bd_tail++;
 	if (lp->tx_bd_tail >= TX_BD_NUM)
@@ -881,34 +939,62 @@
 	wmb();
 	lp->dma_out(lp, TX_TAILDESC_PTR, tail_p); /* DMA start */
 
+	if (temac_check_tx_bd_space(lp, MAX_SKB_FRAGS + 1))
+		netif_stop_queue(ndev);
+
 	return NETDEV_TX_OK;
 }
 
+static int ll_temac_recv_buffers_available(struct temac_local *lp)
+{
+	int available;
+
+	if (!lp->rx_skb[lp->rx_bd_ci])
+		return 0;
+	available = 1 + lp->rx_bd_tail - lp->rx_bd_ci;
+	if (available <= 0)
+		available += RX_BD_NUM;
+	return available;
+}
 
 static void ll_temac_recv(struct net_device *ndev)
 {
 	struct temac_local *lp = netdev_priv(ndev);
-	struct sk_buff *skb, *new_skb;
-	unsigned int bdstat;
-	struct cdmac_bd *cur_p;
-	dma_addr_t tail_p, skb_dma_addr;
-	int length;
 	unsigned long flags;
+	int rx_bd;
+	bool update_tail = false;
 
 	spin_lock_irqsave(&lp->rx_lock, flags);
 
-	tail_p = lp->rx_bd_p + sizeof(*lp->rx_bd_v) * lp->rx_bd_ci;
-	cur_p = &lp->rx_bd_v[lp->rx_bd_ci];
-
-	bdstat = be32_to_cpu(cur_p->app0);
-	while ((bdstat & STS_CTRL_APP0_CMPLT)) {
+	/* Process all received buffers, passing them on network
+	 * stack.  After this, the buffer descriptors will be in an
+	 * un-allocated stage, where no skb is allocated for it, and
+	 * they are therefore not available for TEMAC/DMA.
+	 */
+	do {
+		struct cdmac_bd *bd = &lp->rx_bd_v[lp->rx_bd_ci];
+		struct sk_buff *skb = lp->rx_skb[lp->rx_bd_ci];
+		unsigned int bdstat = be32_to_cpu(bd->app0);
+		int length;
+
+		/* While this should not normally happen, we can end
+		 * here when GFP_ATOMIC allocations fail, and we
+		 * therefore have un-allocated buffers.
+		 */
+		if (!skb)
+			break;
 
-		skb = lp->rx_skb[lp->rx_bd_ci];
-		length = be32_to_cpu(cur_p->app4) & 0x3FFF;
+		/* Loop over all completed buffer descriptors */
+		if (!(bdstat & STS_CTRL_APP0_CMPLT))
+			break;
 
-		dma_unmap_single(ndev->dev.parent, be32_to_cpu(cur_p->phys),
+		dma_unmap_single(ndev->dev.parent, be32_to_cpu(bd->phys),
 				 XTE_MAX_JUMBO_FRAME_SIZE, DMA_FROM_DEVICE);
+		/* The buffer is not valid for DMA anymore */
+		bd->phys = 0;
+		bd->len = 0;
 
+		length = be32_to_cpu(bd->app4) & 0x3FFF;
 		skb_put(skb, length);
 		skb->protocol = eth_type_trans(skb, ndev);
 		skb_checksum_none_assert(skb);
@@ -923,43 +1009,102 @@
 			 * (back) for proper IP checksum byte order
 			 * (be16).
 			 */
-			skb->csum = htons(be32_to_cpu(cur_p->app3) & 0xFFFF);
+			skb->csum = htons(be32_to_cpu(bd->app3) & 0xFFFF);
 			skb->ip_summed = CHECKSUM_COMPLETE;
 		}
 
 		if (!skb_defer_rx_timestamp(skb))
 			netif_rx(skb);
+		/* The skb buffer is now owned by network stack above */
+		lp->rx_skb[lp->rx_bd_ci] = NULL;
 
 		ndev->stats.rx_packets++;
 		ndev->stats.rx_bytes += length;
 
-		new_skb = netdev_alloc_skb_ip_align(ndev,
-						XTE_MAX_JUMBO_FRAME_SIZE);
-		if (!new_skb) {
-			spin_unlock_irqrestore(&lp->rx_lock, flags);
-			return;
+		rx_bd = lp->rx_bd_ci;
+		if (++lp->rx_bd_ci >= RX_BD_NUM)
+			lp->rx_bd_ci = 0;
+	} while (rx_bd != lp->rx_bd_tail);
+
+	/* DMA operations will halt when the last buffer descriptor is
+	 * processed (ie. the one pointed to by RX_TAILDESC_PTR).
+	 * When that happens, no more interrupt events will be
+	 * generated.  No IRQ_COAL or IRQ_DLY, and not even an
+	 * IRQ_ERR.  To avoid stalling, we schedule a delayed work
+	 * when there is a potential risk of that happening.  The work
+	 * will call this function, and thus re-schedule itself until
+	 * enough buffers are available again.
+	 */
+	if (ll_temac_recv_buffers_available(lp) < lp->coalesce_count_rx)
+		schedule_delayed_work(&lp->restart_work, HZ / 1000);
+
+	/* Allocate new buffers for those buffer descriptors that were
+	 * passed to network stack.  Note that GFP_ATOMIC allocations
+	 * can fail (e.g. when a larger burst of GFP_ATOMIC
+	 * allocations occurs), so while we try to allocate all
+	 * buffers in the same interrupt where they were processed, we
+	 * continue with what we could get in case of allocation
+	 * failure.  Allocation of remaining buffers will be retried
+	 * in following calls.
+	 */
+	while (1) {
+		struct sk_buff *skb;
+		struct cdmac_bd *bd;
+		dma_addr_t skb_dma_addr;
+
+		rx_bd = lp->rx_bd_tail + 1;
+		if (rx_bd >= RX_BD_NUM)
+			rx_bd = 0;
+		bd = &lp->rx_bd_v[rx_bd];
+
+		if (bd->phys)
+			break;	/* All skb's allocated */
+
+		skb = netdev_alloc_skb_ip_align(ndev, XTE_MAX_JUMBO_FRAME_SIZE);
+		if (!skb) {
+			dev_warn(&ndev->dev, "skb alloc failed\n");
+			break;
 		}
 
-		cur_p->app0 = cpu_to_be32(STS_CTRL_APP0_IRQONEND);
-		skb_dma_addr = dma_map_single(ndev->dev.parent, new_skb->data,
+		skb_dma_addr = dma_map_single(ndev->dev.parent, skb->data,
 					      XTE_MAX_JUMBO_FRAME_SIZE,
 					      DMA_FROM_DEVICE);
-		cur_p->phys = cpu_to_be32(skb_dma_addr);
-		cur_p->len = cpu_to_be32(XTE_MAX_JUMBO_FRAME_SIZE);
-		lp->rx_skb[lp->rx_bd_ci] = new_skb;
+		if (WARN_ON_ONCE(dma_mapping_error(ndev->dev.parent,
+						   skb_dma_addr))) {
+			dev_kfree_skb_any(skb);
+			break;
+		}
 
-		lp->rx_bd_ci++;
-		if (lp->rx_bd_ci >= RX_BD_NUM)
-			lp->rx_bd_ci = 0;
+		bd->phys = cpu_to_be32(skb_dma_addr);
+		bd->len = cpu_to_be32(XTE_MAX_JUMBO_FRAME_SIZE);
+		bd->app0 = cpu_to_be32(STS_CTRL_APP0_IRQONEND);
+		lp->rx_skb[rx_bd] = skb;
+
+		lp->rx_bd_tail = rx_bd;
+		update_tail = true;
+	}
 
-		cur_p = &lp->rx_bd_v[lp->rx_bd_ci];
-		bdstat = be32_to_cpu(cur_p->app0);
+	/* Move tail pointer when buffers have been allocated */
+	if (update_tail) {
+		lp->dma_out(lp, RX_TAILDESC_PTR,
+			lp->rx_bd_p + sizeof(*lp->rx_bd_v) * lp->rx_bd_tail);
 	}
-	lp->dma_out(lp, RX_TAILDESC_PTR, tail_p);
 
 	spin_unlock_irqrestore(&lp->rx_lock, flags);
 }
 
+/* Function scheduled to ensure a restart in case of DMA halt
+ * condition caused by running out of buffer descriptors.
+ */
+static void ll_temac_restart_work_func(struct work_struct *work)
+{
+	struct temac_local *lp = container_of(work, struct temac_local,
+					      restart_work.work);
+	struct net_device *ndev = lp->ndev;
+
+	ll_temac_recv(ndev);
+}
+
 static irqreturn_t ll_temac_tx_irq(int irq, void *_ndev)
 {
 	struct net_device *ndev = _ndev;
@@ -1052,6 +1197,8 @@
 
 	dev_dbg(&ndev->dev, "temac_close()\n");
 
+	cancel_delayed_work_sync(&lp->restart_work);
+
 	free_irq(lp->tx_irq, ndev);
 	free_irq(lp->rx_irq, ndev);
 
@@ -1184,6 +1331,7 @@
 	lp->dev = &pdev->dev;
 	lp->options = XTE_OPTION_DEFAULTS;
 	spin_lock_init(&lp->rx_lock);
+	INIT_DELAYED_WORK(&lp->restart_work, ll_temac_restart_work_func);
 
 	/* Setup mutex for synchronization of indirect register access */
 	if (pdata) {
@@ -1197,6 +1345,8 @@
 		lp->indirect_lock = devm_kmalloc(&pdev->dev,
 						 sizeof(*lp->indirect_lock),
 						 GFP_KERNEL);
+		if (!lp->indirect_lock)
+			return -ENOMEM;
 		spin_lock_init(lp->indirect_lock);
 	}
 
@@ -1290,14 +1440,13 @@
 		 */
 		lp->tx_chnl_ctrl = 0x10220000;
 		lp->rx_chnl_ctrl = 0xff070000;
+		lp->coalesce_count_rx = 0x07;
 
 		/* Finished with the DMA node; drop the reference */
 		of_node_put(dma_np);
 	} else if (pdata) {
 		/* 2nd memory resource specifies DMA registers */
-		res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-		lp->sdma_regs = devm_ioremap_nocache(&pdev->dev, res->start,
-						     resource_size(res));
+		lp->sdma_regs = devm_platform_ioremap_resource(pdev, 1);
 		if (IS_ERR(lp->sdma_regs)) {
 			dev_err(&pdev->dev,
 				"could not map DMA registers\n");
@@ -1321,23 +1470,26 @@
 				(pdata->tx_irq_count << 16);
 		else
 			lp->tx_chnl_ctrl = 0x10220000;
-		if (pdata->rx_irq_timeout || pdata->rx_irq_count)
+		if (pdata->rx_irq_timeout || pdata->rx_irq_count) {
 			lp->rx_chnl_ctrl = (pdata->rx_irq_timeout << 24) |
 				(pdata->rx_irq_count << 16);
-		else
+			lp->coalesce_count_rx = pdata->rx_irq_count;
+		} else {
 			lp->rx_chnl_ctrl = 0xff070000;
+			lp->coalesce_count_rx = 0x07;
+		}
 	}
 
 	/* Error handle returned DMA RX and TX interrupts */
-	if (lp->rx_irq < 0) {
-		if (lp->rx_irq != -EPROBE_DEFER)
-			dev_err(&pdev->dev, "could not get DMA RX irq\n");
-		return lp->rx_irq;
-	}
-	if (lp->tx_irq < 0) {
-		if (lp->tx_irq != -EPROBE_DEFER)
-			dev_err(&pdev->dev, "could not get DMA TX irq\n");
-		return lp->tx_irq;
+	if (lp->rx_irq <= 0) {
+		rc = lp->rx_irq ?: -EINVAL;
+		return dev_err_probe(&pdev->dev, rc,
+				     "could not get DMA RX irq\n");
+	}
+	if (lp->tx_irq <= 0) {
+		rc = lp->tx_irq ?: -EINVAL;
+		return dev_err_probe(&pdev->dev, rc,
+				     "could not get DMA TX irq\n");
 	}
 
 	if (temac_np) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/xilinx/xilinx_axienet.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/xilinx/xilinx_axienet.h
@@ -13,7 +13,9 @@
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <linux/if_vlan.h>
-#include <linux/phylink.h>
+#include <linux/net_tstamp.h>
+#include <linux/phy.h>
+#include <linux/of_platform.h>
 
 /* Packet size info */
 #define XAE_HDR_SIZE			14 /* Size of Ethernet header */
@@ -25,29 +27,39 @@
 #define XAE_MAX_VLAN_FRAME_SIZE  (XAE_MTU + VLAN_ETH_HLEN + XAE_TRL_SIZE)
 #define XAE_MAX_JUMBO_FRAME_SIZE (XAE_JUMBO_MTU + XAE_HDR_SIZE + XAE_TRL_SIZE)
 
+/* DMA address width min and max range */
+#define XAE_DMA_MASK_MIN	32
+#define XAE_DMA_MASK_MAX	64
+
+/* In AXI DMA Tx and Rx queue count is same */
+#define for_each_tx_dma_queue(lp, var) \
+	for ((var) = 0; (var) < (lp)->num_tx_queues; (var)++)
+
+#define for_each_rx_dma_queue(lp, var) \
+	for ((var) = 0; (var) < (lp)->num_rx_queues; (var)++)
 /* Configuration options */
 
 /* Accept all incoming packets. Default: disabled (cleared) */
-#define XAE_OPTION_PROMISC			(1 << 0)
+#define XAE_OPTION_PROMISC			BIT(0)
 
 /* Jumbo frame support for Tx & Rx. Default: disabled (cleared) */
-#define XAE_OPTION_JUMBO			(1 << 1)
+#define XAE_OPTION_JUMBO			BIT(1)
 
 /* VLAN Rx & Tx frame support. Default: disabled (cleared) */
-#define XAE_OPTION_VLAN				(1 << 2)
+#define XAE_OPTION_VLAN				BIT(2)
 
 /* Enable recognition of flow control frames on Rx. Default: enabled (set) */
-#define XAE_OPTION_FLOW_CONTROL			(1 << 4)
+#define XAE_OPTION_FLOW_CONTROL			BIT(4)
 
 /* Strip FCS and PAD from incoming frames. Note: PAD from VLAN frames is not
  * stripped. Default: disabled (set)
  */
-#define XAE_OPTION_FCS_STRIP			(1 << 5)
+#define XAE_OPTION_FCS_STRIP			BIT(5)
 
 /* Generate FCS field and add PAD automatically for outgoing frames.
  * Default: enabled (set)
  */
-#define XAE_OPTION_FCS_INSERT			(1 << 6)
+#define XAE_OPTION_FCS_INSERT			BIT(6)
 
 /* Enable Length/Type error checking for incoming frames. When this option is
  * set, the MAC will filter frames that have a mismatched type/length field
@@ -55,13 +67,13 @@
  * types of frames are encountered. When this option is cleared, the MAC will
  * allow these types of frames to be received. Default: enabled (set)
  */
-#define XAE_OPTION_LENTYPE_ERR			(1 << 7)
+#define XAE_OPTION_LENTYPE_ERR			BIT(7)
 
 /* Enable the transmitter. Default: enabled (set) */
-#define XAE_OPTION_TXEN				(1 << 11)
+#define XAE_OPTION_TXEN				BIT(11)
 
 /*  Enable the receiver. Default: enabled (set) */
-#define XAE_OPTION_RXEN				(1 << 12)
+#define XAE_OPTION_RXEN				BIT(12)
 
 /*  Default options set when device is initialized or reset */
 #define XAE_OPTION_DEFAULTS				   \
@@ -122,7 +134,7 @@
 /* Default TX/RX Threshold and waitbound values for SGDMA mode */
 #define XAXIDMA_DFT_TX_THRESHOLD	24
 #define XAXIDMA_DFT_TX_WAITBOUND	254
-#define XAXIDMA_DFT_RX_THRESHOLD	24
+#define XAXIDMA_DFT_RX_THRESHOLD	1
 #define XAXIDMA_DFT_RX_WAITBOUND	254
 
 #define XAXIDMA_BD_CTRL_TXSOF_MASK	0x08000000 /* First tx packet */
@@ -141,6 +153,24 @@
 
 #define XAXIDMA_BD_MINIMUM_ALIGNMENT	0x40
 
+/* AXI Tx Timestamp Stream FIFO Register Definitions */
+#define XAXIFIFO_TXTS_ISR	0x00000000 /* Interrupt Status Register */
+#define XAXIFIFO_TXTS_TDFV	0x0000000C /* Transmit Data FIFO Vacancy */
+#define XAXIFIFO_TXTS_TXFD	0x00000010 /* Tx Data Write Port */
+#define XAXIFIFO_TXTS_TLR	0x00000014 /* Transmit Length Register */
+#define XAXIFIFO_TXTS_RFO	0x0000001C /* Rx Fifo Occupancy */
+#define XAXIFIFO_TXTS_RDFR	0x00000018 /* Rx Fifo reset */
+#define XAXIFIFO_TXTS_RXFD	0x00000020 /* Rx Data Read Port */
+#define XAXIFIFO_TXTS_RLR	0x00000024 /* Receive Length Register */
+#define XAXIFIFO_TXTS_SRR	0x00000028 /* AXI4-Stream Reset */
+
+#define XAXIFIFO_TXTS_INT_RC_MASK	0x04000000
+#define XAXIFIFO_TXTS_RXFD_MASK		0x7FFFFFFF
+#define XAXIFIFO_TXTS_RESET_MASK	0x000000A5
+#define XAXIFIFO_TXTS_TAG_MASK		0xFFFF0000
+#define XAXIFIFO_TXTS_TAG_SHIFT		16
+#define XAXIFIFO_TXTS_TAG_MAX		0xFFFE
+
 /* Axi Ethernet registers definition */
 #define XAE_RAF_OFFSET		0x00000000 /* Reset and Address filter */
 #define XAE_TPF_OFFSET		0x00000004 /* Tx Pause Frame */
@@ -159,22 +189,19 @@
 #define XAE_RCW1_OFFSET		0x00000404 /* Rx Configuration Word 1 */
 #define XAE_TC_OFFSET		0x00000408 /* Tx Configuration */
 #define XAE_FCC_OFFSET		0x0000040C /* Flow Control Configuration */
-#define XAE_EMMC_OFFSET		0x00000410 /* EMAC mode configuration */
-#define XAE_PHYC_OFFSET		0x00000414 /* RGMII/SGMII configuration */
-#define XAE_MDIO_MC_OFFSET	0x00000500 /* MII Management Config */
-#define XAE_MDIO_MCR_OFFSET	0x00000504 /* MII Management Control */
-#define XAE_MDIO_MWD_OFFSET	0x00000508 /* MII Management Write Data */
-#define XAE_MDIO_MRD_OFFSET	0x0000050C /* MII Management Read Data */
-#define XAE_MDIO_MIS_OFFSET	0x00000600 /* MII Management Interrupt Status */
-/* MII Mgmt Interrupt Pending register offset */
-#define XAE_MDIO_MIP_OFFSET	0x00000620
-/* MII Management Interrupt Enable register offset */
-#define XAE_MDIO_MIE_OFFSET	0x00000640
-/* MII Management Interrupt Clear register offset. */
-#define XAE_MDIO_MIC_OFFSET	0x00000660
+#define XAE_EMMC_OFFSET		0x00000410 /* MAC speed configuration */
+#define XAE_RMFC_OFFSET		0x00000414 /* RX Max Frame Configuration */
+#define XAE_MDIO_MC_OFFSET	0x00000500 /* MDIO Setup */
+#define XAE_MDIO_MCR_OFFSET	0x00000504 /* MDIO Control */
+#define XAE_MDIO_MWD_OFFSET	0x00000508 /* MDIO Write Data */
+#define XAE_MDIO_MRD_OFFSET	0x0000050C /* MDIO Read Data */
+#define XAE_TEMAC_IS_OFFSET	0x00000600 /* TEMAC Interrupt Status */
+#define XAE_TEMAC_IP_OFFSET	0x00000610 /* TEMAC Interrupt Pending Status */
+#define XAE_TEMAC_IE_OFFSET	0x00000620 /* TEMAC Interrupt Enable Status */
+#define XAE_TEMAC_IC_OFFSET	0x00000630 /* TEMAC Interrupt Clear Status */
 #define XAE_UAW0_OFFSET		0x00000700 /* Unicast address word 0 */
 #define XAE_UAW1_OFFSET		0x00000704 /* Unicast address word 1 */
-#define XAE_FMI_OFFSET		0x00000708 /* Filter Mask Index */
+#define XAE_FMC_OFFSET		0x00000708 /* Frame Filter Control */
 #define XAE_AF0_OFFSET		0x00000710 /* Address Filter 0 */
 #define XAE_AF1_OFFSET		0x00000714 /* Address Filter 1 */
 
@@ -235,6 +262,7 @@
 #define XAE_TPID_3_MASK		0xFFFF0000 /* TPID 1 */
 
 /* Bit masks for Axi Ethernet RCW1 register */
+#define XAE_RCW1_INBAND1588_MASK 0x00400000 /* Inband 1588 Enable */
 #define XAE_RCW1_RST_MASK	0x80000000 /* Reset */
 #define XAE_RCW1_JUM_MASK	0x40000000 /* Jumbo frame enable */
 /* In-Band FCS enable (FCS not stripped) */
@@ -251,6 +279,7 @@
 #define XAE_RCW1_PAUSEADDR_MASK 0x0000FFFF
 
 /* Bit masks for Axi Ethernet TC register */
+#define XAE_TC_INBAND1588_MASK 0x00400000 /* Inband 1588 Enable */
 #define XAE_TC_RST_MASK		0x80000000 /* Reset */
 #define XAE_TC_JUM_MASK		0x40000000 /* Jumbo frame enable */
 /* In-Band FCS enable (FCS not generated) */
@@ -275,18 +304,7 @@
 #define XAE_EMMC_LINKSPD_10	0x00000000 /* Link Speed mask for 10 Mbit */
 #define XAE_EMMC_LINKSPD_100	0x40000000 /* Link Speed mask for 100 Mbit */
 #define XAE_EMMC_LINKSPD_1000	0x80000000 /* Link Speed mask for 1000 Mbit */
-
-/* Bit masks for Axi Ethernet PHYC register */
-#define XAE_PHYC_SGMIILINKSPEED_MASK	0xC0000000 /* SGMII link speed mask*/
-#define XAE_PHYC_RGMIILINKSPEED_MASK	0x0000000C /* RGMII link speed */
-#define XAE_PHYC_RGMIIHD_MASK		0x00000002 /* RGMII Half-duplex */
-#define XAE_PHYC_RGMIILINK_MASK		0x00000001 /* RGMII link status */
-#define XAE_PHYC_RGLINKSPD_10		0x00000000 /* RGMII link 10 Mbit */
-#define XAE_PHYC_RGLINKSPD_100		0x00000004 /* RGMII link 100 Mbit */
-#define XAE_PHYC_RGLINKSPD_1000		0x00000008 /* RGMII link 1000 Mbit */
-#define XAE_PHYC_SGLINKSPD_10		0x00000000 /* SGMII link 10 Mbit */
-#define XAE_PHYC_SGLINKSPD_100		0x40000000 /* SGMII link 100 Mbit */
-#define XAE_PHYC_SGLINKSPD_1000		0x80000000 /* SGMII link 1000 Mbit */
+#define XAE_EMMC_LINKSPD_2500	0x80000000 /* Link Speed mask for 2500 Mbit */
 
 /* Bit masks for Axi Ethernet MDIO interface MC register */
 #define XAE_MDIO_MC_MDIOEN_MASK		0x00000040 /* MII management enable */
@@ -304,37 +322,26 @@
 #define XAE_MDIO_MCR_INITIATE_MASK	0x00000800 /* Ready Mask */
 #define XAE_MDIO_MCR_READY_MASK		0x00000080 /* Ready Mask */
 
-/* Bit masks for Axi Ethernet MDIO interface MIS, MIP, MIE, MIC registers */
-#define XAE_MDIO_INT_MIIM_RDY_MASK	0x00000001 /* MIIM Interrupt */
-
 /* Bit masks for Axi Ethernet UAW1 register */
 /* Station address bits [47:32]; Station address
  * bits [31:0] are stored in register UAW0
  */
 #define XAE_UAW1_UNICASTADDR_MASK	0x0000FFFF
 
-/* Bit masks for Axi Ethernet FMI register */
-#define XAE_FMI_PM_MASK			0x80000000 /* Promis. mode enable */
-#define XAE_FMI_IND_MASK		0x00000003 /* Index Mask */
+/* Bit masks for Axi Ethernet FMC register */
+#define XAE_FMC_PM_MASK			0x80000000 /* Promis. mode enable */
+#define XAE_FMC_IND_MASK		0x00000003 /* Index Mask */
 
 #define XAE_MDIO_DIV_DFT		29 /* Default MDIO clock divisor */
 
-/* Defines for different options for C_PHY_TYPE parameter in Axi Ethernet IP */
-#define XAE_PHY_TYPE_MII		0
-#define XAE_PHY_TYPE_GMII		1
-#define XAE_PHY_TYPE_RGMII_1_3		2
-#define XAE_PHY_TYPE_RGMII_2_0		3
-#define XAE_PHY_TYPE_SGMII		4
-#define XAE_PHY_TYPE_1000BASE_X		5
-
- /* Total number of entries in the hardware multicast table. */
+/* Total number of entries in the hardware multicast table. */
 #define XAE_MULTICAST_CAM_TABLE_NUM	4
 
 /* Axi Ethernet Synthesis features */
-#define XAE_FEATURE_PARTIAL_RX_CSUM	(1 << 0)
-#define XAE_FEATURE_PARTIAL_TX_CSUM	(1 << 1)
-#define XAE_FEATURE_FULL_RX_CSUM	(1 << 2)
-#define XAE_FEATURE_FULL_TX_CSUM	(1 << 3)
+#define XAE_FEATURE_PARTIAL_RX_CSUM	BIT(0)
+#define XAE_FEATURE_PARTIAL_TX_CSUM	BIT(1)
+#define XAE_FEATURE_FULL_RX_CSUM	BIT(2)
+#define XAE_FEATURE_FULL_TX_CSUM	BIT(3)
 
 #define XAE_NO_CSUM_OFFLOAD		0
 
@@ -344,12 +351,215 @@
 
 #define DELAY_OF_ONE_MILLISEC		1000
 
+#define XAXIENET_NAPI_WEIGHT		64
+
+/* Definition of 1588 PTP in Axi Ethernet IP */
+#define TX_TS_OP_NOOP           0x0
+#define TX_TS_OP_ONESTEP        0x1
+#define TX_TS_OP_TWOSTEP        0x2
+#define TX_TS_CSUM_UPDATE       0x1
+#define TX_PTP_CSUM_OFFSET      0x28
+#define TX_PTP_TS_OFFSET        0x4C
+
+/* XXV MAC Register Definitions */
+#define XXV_GT_RESET_OFFSET		0x00000000
+#define XXV_TC_OFFSET			0x0000000C
+#define XXV_RCW1_OFFSET			0x00000014
+#define XXV_JUM_OFFSET			0x00000018
+#define XXV_TICKREG_OFFSET		0x00000020
+#define XXV_STATRX_BLKLCK_OFFSET	0x0000040C
+#define XXV_USXGMII_AN_OFFSET		0x000000C8
+#define XXV_USXGMII_AN_STS_OFFSET	0x00000458
+
+/* XXV MAC Register Mask Definitions */
+#define XXV_GT_RESET_MASK	BIT(0)
+#define XXV_TC_TX_MASK		BIT(0)
+#define XXV_RCW1_RX_MASK	BIT(0)
+#define XXV_RCW1_FCS_MASK	BIT(1)
+#define XXV_TC_FCS_MASK		BIT(1)
+#define XXV_MIN_JUM_MASK	GENMASK(7, 0)
+#define XXV_MAX_JUM_MASK	GENMASK(10, 8)
+#define XXV_RX_BLKLCK_MASK	BIT(0)
+#define XXV_TICKREG_STATEN_MASK BIT(0)
+#define XXV_MAC_MIN_PKT_LEN	64
+
+/* USXGMII Register Mask Definitions  */
+#define USXGMII_AN_EN		BIT(5)
+#define USXGMII_AN_RESET	BIT(6)
+#define USXGMII_AN_RESTART	BIT(7)
+#define USXGMII_EN		BIT(16)
+#define USXGMII_RATE_MASK	0x0E000700
+#define USXGMII_RATE_1G		0x04000200
+#define USXGMII_RATE_2G5	0x08000400
+#define USXGMII_RATE_10M	0x0
+#define USXGMII_RATE_100M	0x02000100
+#define USXGMII_RATE_5G		0x0A000500
+#define USXGMII_RATE_10G	0x06000300
+#define USXGMII_FD		BIT(28)
+#define USXGMII_LINK_STS	BIT(31)
+
+/* USXGMII AN STS register mask definitions */
+#define USXGMII_AN_STS_COMP_MASK	BIT(16)
+
+/* MCDMA Register Definitions */
+#define XMCDMA_CR_OFFSET	0x00
+#define XMCDMA_SR_OFFSET	0x04
+#define XMCDMA_CHEN_OFFSET	0x08
+#define XMCDMA_CHSER_OFFSET	0x0C
+#define XMCDMA_ERR_OFFSET	0x10
+#define XMCDMA_PKTDROP_OFFSET	0x14
+#define XMCDMA_TXWEIGHT0_OFFSET 0x18
+#define XMCDMA_TXWEIGHT1_OFFSET 0x1C
+#define XMCDMA_RXINT_SER_OFFSET 0x20
+#define XMCDMA_TXINT_SER_OFFSET 0x28
+
+#define XMCDMA_CHOBS1_OFFSET	0x440
+#define XMCDMA_CHOBS2_OFFSET	0x444
+#define XMCDMA_CHOBS3_OFFSET	0x448
+#define XMCDMA_CHOBS4_OFFSET	0x44C
+#define XMCDMA_CHOBS5_OFFSET	0x450
+#define XMCDMA_CHOBS6_OFFSET	0x454
+
+#define XMCDMA_CHAN_RX_OFFSET  0x500
+
+/* Per Channel Registers */
+#define XMCDMA_CHAN_CR_OFFSET(chan_id)		(0x40 + ((chan_id) - 1) * 0x40)
+#define XMCDMA_CHAN_SR_OFFSET(chan_id)		(0x44 + ((chan_id) - 1) * 0x40)
+#define XMCDMA_CHAN_CURDESC_OFFSET(chan_id)	(0x48 + ((chan_id) - 1) * 0x40)
+#define XMCDMA_CHAN_TAILDESC_OFFSET(chan_id)	(0x50 + ((chan_id) - 1) * 0x40)
+#define XMCDMA_CHAN_PKTDROP_OFFSET(chan_id)	(0x58 + ((chan_id) - 1) * 0x40)
+
+#define XMCDMA_RX_OFFSET	0x500
+
+/* MCDMA Mask registers */
+#define XMCDMA_CR_RUNSTOP_MASK		BIT(0) /* Start/stop DMA channel */
+#define XMCDMA_CR_RESET_MASK		BIT(2) /* Reset DMA engine */
+
+#define XMCDMA_SR_HALTED_MASK		BIT(0)
+#define XMCDMA_SR_IDLE_MASK		BIT(1)
+
+#define XMCDMA_IRQ_ERRON_OTHERQ_MASK	BIT(3)
+#define XMCDMA_IRQ_PKTDROP_MASK		BIT(4)
+#define XMCDMA_IRQ_IOC_MASK		BIT(5)
+#define XMCDMA_IRQ_DELAY_MASK		BIT(6)
+#define XMCDMA_IRQ_ERR_MASK		BIT(7)
+#define XMCDMA_IRQ_ALL_MASK		GENMASK(7, 5)
+#define XMCDMA_PKTDROP_COALESCE_MASK	GENMASK(15, 8)
+#define XMCDMA_COALESCE_MASK		GENMASK(23, 16)
+#define XMCDMA_DELAY_MASK		GENMASK(31, 24)
+
+#define XMCDMA_CHEN_MASK		GENMASK(7, 0)
+#define XMCDMA_CHID_MASK		GENMASK(7, 0)
+
+#define XMCDMA_ERR_INTERNAL_MASK	BIT(0)
+#define XMCDMA_ERR_SLAVE_MASK		BIT(1)
+#define XMCDMA_ERR_DECODE_MASK		BIT(2)
+#define XMCDMA_ERR_SG_INT_MASK		BIT(4)
+#define XMCDMA_ERR_SG_SLV_MASK		BIT(5)
+#define XMCDMA_ERR_SG_DEC_MASK		BIT(6)
+
+#define XMCDMA_PKTDROP_CNT_MASK		GENMASK(31, 0)
+
+#define XMCDMA_BD_CTRL_TXSOF_MASK	0x80000000 /* First tx packet */
+#define XMCDMA_BD_CTRL_TXEOF_MASK	0x40000000 /* Last tx packet */
+#define XMCDMA_BD_CTRL_ALL_MASK		0xC0000000 /* All control bits */
+#define XMCDMA_BD_STS_ALL_MASK		0xF0000000 /* All status bits */
+
+#define XMCDMA_COALESCE_SHIFT		16
+#define XMCDMA_DELAY_SHIFT		24
+#define XMCDMA_DFT_TX_THRESHOLD		1
+
+#define XMCDMA_TXWEIGHT_CH_MASK(chan_id)	GENMASK(((chan_id) * 4 + 3), \
+							(chan_id) * 4)
+#define XMCDMA_TXWEIGHT_CH_SHIFT(chan_id)	((chan_id) * 4)
+
+/* PTP Packet length */
+#define XAE_TX_PTP_LEN		16
+#define XXV_TX_PTP_LEN		12
+
+/* Macros used when AXI DMA h/w is configured without DRE */
+#define XAE_TX_BUFFERS		64
+#define XAE_MAX_PKT_LEN		8192
+
+/* MRMAC Register Definitions */
+/* Configuration Registers */
+#define MRMAC_REV_OFFSET		0x00000000
+#define MRMAC_RESET_OFFSET		0x00000004
+#define MRMAC_MODE_OFFSET		0x00000008
+#define MRMAC_CONFIG_TX_OFFSET		0x0000000C
+#define MRMAC_CONFIG_RX_OFFSET		0x00000010
+#define MRMAC_TICK_OFFSET		0x0000002C
+
+/* Status Registers */
+#define MRMAC_TX_STS_OFFSET		0x00000740
+#define MRMAC_RX_STS_OFFSET		0x00000744
+#define MRMAC_TX_RT_STS_OFFSET		0x00000748
+#define MRMAC_RX_RT_STS_OFFSET		0x0000074C
+#define MRMAC_STATRX_BLKLCK_OFFSET	0x00000754
+
+/* Register bit masks */
+#define MRMAC_RX_SERDES_RST_MASK	(BIT(3) | BIT(2) | BIT(1) | BIT(0))
+#define MRMAC_TX_SERDES_RST_MASK	BIT(4)
+#define MRMAC_RX_RST_MASK		BIT(5)
+#define MRMAC_TX_RST_MASK		BIT(6)
+#define MRMAC_RX_AXI_RST_MASK		BIT(8)
+#define MRMAC_TX_AXI_RST_MASK		BIT(9)
+#define MRMAC_STS_ALL_MASK		0xFFFFFFFF
+
+#define MRMAC_RX_EN_MASK		BIT(0)
+#define MRMAC_RX_DEL_FCS_MASK		BIT(1)
+
+#define MRMAC_TX_EN_MASK		BIT(0)
+#define MRMAC_TX_INS_FCS_MASK		BIT(1)
+
+#define MRMAC_RX_BLKLCK_MASK		BIT(0)
+
+#define MRMAC_CTL_DATA_RATE_MASK	GENMASK(2, 0)
+#define MRMAC_CTL_DATA_RATE_10G		0
+#define MRMAC_CTL_DATA_RATE_25G		1
+#define MRMAC_CTL_DATA_RATE_40G		2
+#define MRMAC_CTL_DATA_RATE_50G		3
+#define MRMAC_CTL_DATA_RATE_100G	4
+
+#define MRMAC_CTL_AXIS_CFG_MASK		GENMASK(11, 9)
+#define MRMAC_CTL_AXIS_CFG_SHIFT	9
+#define MRMAC_CTL_AXIS_CFG_10G_IND	1
+#define MRMAC_CTL_AXIS_CFG_25G_IND	1
+
+#define MRMAC_CTL_SERDES_WIDTH_MASK	GENMASK(6, 4)
+#define MRMAC_CTL_SERDES_WIDTH_SHIFT	4
+#define MRMAC_CTL_SERDES_WIDTH_10G	4
+#define MRMAC_CTL_SERDES_WIDTH_25G	6
+
+#define MRMAC_CTL_RATE_CFG_MASK		(MRMAC_CTL_DATA_RATE_MASK |	\
+					 MRMAC_CTL_AXIS_CFG_MASK |	\
+					 MRMAC_CTL_SERDES_WIDTH_MASK)
+
+#define MRMAC_CTL_PM_TICK_MASK		BIT(30)
+#define MRMAC_TICK_TRIGGER		BIT(0)
+
+/* MRMAC GT wrapper registers */
+#define MRMAC_GT_PLL_OFFSET		0x0
+#define MRMAC_GT_PLL_STS_OFFSET		0x8
+#define MRMAC_GT_RATE_OFFSET		0x0
+#define MRMAC_GT_CTRL_OFFSET		0x8
+
+#define MRMAC_GT_PLL_RST_MASK		0x00030003
+#define MRMAC_GT_PLL_DONE_MASK		0xFF
+#define MRMAC_GT_RST_ALL_MASK		BIT(0)
+#define MRMAC_GT_RST_RX_MASK		BIT(1)
+#define MRMAC_GT_RST_TX_MASK		BIT(2)
+#define MRMAC_GT_10G_MASK		0x01010101
+#define MRMAC_GT_25G_MASK		0x02020202
+
+#define MRMAC_GT_LANE_OFFSET		0x10000
+#define MRMAC_MAX_GT_LANES		4
 /**
  * struct axidma_bd - Axi Dma buffer descriptor layout
  * @next:         MM2S/S2MM Next Descriptor Pointer
- * @reserved1:    Reserved and not used
+ * @reserved1:    Reserved and not used for 32-bit
  * @phys:         MM2S/S2MM Buffer Address
- * @reserved2:    Reserved and not used
+ * @reserved2:    Reserved and not used for 32-bit
  * @reserved3:    Reserved and not used
  * @reserved4:    Reserved and not used
  * @cntrl:        MM2S/S2MM Control value
@@ -359,12 +569,23 @@
  * @app2:         MM2S/S2MM User Application Field 2.
  * @app3:         MM2S/S2MM User Application Field 3.
  * @app4:         MM2S/S2MM User Application Field 4.
+ * @sw_id_offset: MM2S/S2MM Sw ID
+ * @ptp_tx_skb:   If timestamping is enabled used for timestamping skb
+ *		  Otherwise reserved.
+ * @ptp_tx_ts_tag: Tag value of 2 step timestamping if timestamping is enabled
+ *		   Otherwise reserved.
+ * @tx_skb:	  Transmit skb address
+ * @tx_desc_mapping: Tx Descriptor DMA mapping type.
  */
 struct axidma_bd {
-	u32 next;	/* Physical address of next buffer descriptor */
+	phys_addr_t next;	/* Physical address of next buffer descriptor */
+#ifndef CONFIG_PHYS_ADDR_T_64BIT
 	u32 reserved1;
-	u32 phys;
+#endif
+	phys_addr_t phys;
+#ifndef CONFIG_PHYS_ADDR_T_64BIT
 	u32 reserved2;
+#endif
 	u32 reserved3;
 	u32 reserved4;
 	u32 cntrl;
@@ -373,37 +594,128 @@
 	u32 app1;	/* TX start << 16 | insert */
 	u32 app2;	/* TX csum seed */
 	u32 app3;
-	u32 app4;   /* Last field used by HW */
-	struct sk_buff *skb;
+	u32 app4;
+	phys_addr_t sw_id_offset; /* first unused field by h/w */
+	phys_addr_t ptp_tx_skb;
+	u32 ptp_tx_ts_tag;
+	phys_addr_t tx_skb;
+	u32 tx_desc_mapping;
+} __aligned(XAXIDMA_BD_MINIMUM_ALIGNMENT);
+/**
+ * struct aximcdma_bd - Axi MCDMA buffer descriptor layout
+ * @next:         MM2S/S2MM Next Descriptor Pointer
+ * @reserved1:    Reserved and not used for 32-bit
+ * @phys:         MM2S/S2MM Buffer Address
+ * @reserved2:    Reserved and not used for 32-bit
+ * @reserved3:    Reserved and not used
+ * @cntrl:        MM2S/S2MM Control value
+ * @status:       S2MM Status value
+ * @sband_stats:  S2MM Sideband Status value
+ *		  MM2S Status value
+ * @app0:         MM2S/S2MM User Application Field 0.
+ * @app1:         MM2S/S2MM User Application Field 1.
+ * @app2:         MM2S/S2MM User Application Field 2.
+ * @app3:         MM2S/S2MM User Application Field 3.
+ * @app4:         MM2S/S2MM User Application Field 4.
+ * @sw_id_offset: MM2S/S2MM Sw ID
+ * @ptp_tx_skb:   If timestamping is enabled used for timestamping skb
+ *		  Otherwise reserved.
+ * @ptp_tx_ts_tag: Tag value of 2 step timestamping if timestamping is enabled
+ *		   Otherwise reserved.
+ * @tx_skb:	  Transmit skb address
+ * @tx_desc_mapping: Tx Descriptor DMA mapping type.
+ */
+struct aximcdma_bd {
+	phys_addr_t next;	/* Physical address of next buffer descriptor */
+#ifndef CONFIG_PHYS_ADDR_T_64BIT
+	u32 reserved1;
+#endif
+	phys_addr_t phys;
+#ifndef CONFIG_PHYS_ADDR_T_64BIT
+	u32 reserved2;
+#endif
+	u32 reserved3;
+	u32 cntrl;
+	u32 status;
+	u32 sband_stats;
+	u32 app0;
+	u32 app1;	/* TX start << 16 | insert */
+	u32 app2;	/* TX csum seed */
+	u32 app3;
+	u32 app4;
+	phys_addr_t sw_id_offset; /* first unused field by h/w */
+	phys_addr_t ptp_tx_skb;
+	u32 ptp_tx_ts_tag;
+	phys_addr_t tx_skb;
+	u32 tx_desc_mapping;
 } __aligned(XAXIDMA_BD_MINIMUM_ALIGNMENT);
 
+#define DESC_DMA_MAP_SINGLE 0
+#define DESC_DMA_MAP_PAGE 1
+
+#if defined(CONFIG_XILINX_TSN)
+#define XAE_MAX_QUEUES		5
+#elif defined(CONFIG_AXIENET_HAS_MCDMA)
+#define XAE_MAX_QUEUES		16
+#else
+#define XAE_MAX_QUEUES		1
+#endif
+
+#ifdef CONFIG_XILINX_TSN
+/* TSN queues range is 2 to 5. For eg: for num_tc = 2 minimum queues = 2;
+ * for num_tc = 3 with sideband signalling maximum queues = 5
+ */
+#define XAE_MAX_TSN_TC		3
+#define XAE_TSN_MIN_QUEUES	2
+#endif
+
+enum axienet_tsn_ioctl {
+	SIOCCHIOCTL = SIOCDEVPRIVATE,
+	SIOC_GET_SCHED,
+	SIOC_PREEMPTION_CFG,
+	SIOC_PREEMPTION_CTRL,
+	SIOC_PREEMPTION_STS,
+	SIOC_PREEMPTION_COUNTER,
+	SIOC_QBU_USER_OVERRIDE,
+	SIOC_QBU_STS,
+};
+
 /**
  * struct axienet_local - axienet private per device data
  * @ndev:	Pointer for net_device to which it will be attached.
  * @dev:	Pointer to device structure
  * @phy_node:	Pointer to device node structure
+ * @clk:	AXI bus clock
  * @mii_bus:	Pointer to MII bus structure
  * @regs_start: Resource start for axienet device addresses
  * @regs:	Base address for the axienet_local device address space
- * @dma_regs:	Base address for the axidma device address space
- * @dma_err_tasklet: Tasklet structure to process Axi DMA errors
- * @tx_irq:	Axidma TX IRQ number
- * @rx_irq:	Axidma RX IRQ number
+ * @mcdma_regs:	Base address for the aximcdma device address space
+ * @napi:	Napi Structure array for all dma queues
+ * @num_tx_queues: Total number of Tx DMA queues
+ * @num_rx_queues: Total number of Rx DMA queues
+ * @dq:		DMA queues data
  * @phy_mode:	Phy type to identify between MII/GMII/RGMII/SGMII/1000 Base-X
+ * @is_tsn:	Denotes a tsn port
+ * @temac_no:	Denotes the port number in TSN IP
+ * @num_tc:	Total number of TSN Traffic classes
+ * @timer_priv: PTP timer private data pointer
+ * @ptp_tx_irq: PTP tx irq
+ * @ptp_rx_irq: PTP rx irq
+ * @rtc_irq:	PTP RTC irq
+ * @qbv_irq:	QBV shed irq
+ * @ptp_ts_type: ptp time stamp type - 1 or 2 step mode
+ * @ptp_rx_hw_pointer: ptp rx hw pointer
+ * @ptp_rx_sw_pointer: ptp rx sw pointer
+ * @ptp_txq:	PTP tx queue header
+ * @tx_tstamp_work: PTP timestamping work queue
+ * @ptp_tx_lock: PTP tx lock
+ * @dma_err_tasklet: Tasklet structure to process Axi DMA errors
+ * @eth_irq:	Axi Ethernet IRQ number
  * @options:	AxiEthernet option word
  * @last_link:	Phy link state in which the PHY was negotiated earlier
  * @features:	Stores the extended features supported by the axienet hw
- * @tx_bd_v:	Virtual address of the TX buffer descriptor ring
- * @tx_bd_p:	Physical address(start address) of the TX buffer descr. ring
- * @rx_bd_v:	Virtual address of the RX buffer descriptor ring
- * @rx_bd_p:	Physical address(start address) of the RX buffer descr. ring
- * @tx_bd_ci:	Stores the index of the Tx buffer descriptor in the ring being
- *		accessed currently. Used while alloc. BDs before a TX starts
- * @tx_bd_tail:	Stores the index of the Tx buffer descriptor in the ring being
- *		accessed currently. Used while processing BDs after the TX
- *		completed.
- * @rx_bd_ci:	Stores the index of the Rx buffer descriptor in the ring being
- *		accessed currently.
+ * @tx_bd_num:	Number of TX buffer descriptors.
+ * @rx_bd_num:	Number of RX buffer descriptors.
  * @max_frm_size: Stores the maximum size of the frame that can be that
  *		  Txed/Rxed in the existing hardware. If jumbo option is
  *		  supported, the maximum frame size would be 9k. Else it is
@@ -413,6 +725,33 @@
  * @csum_offload_on_rx_path:	Stores the checksum selection on RX side.
  * @coalesce_count_rx:	Store the irq coalesce on RX side.
  * @coalesce_count_tx:	Store the irq coalesce on TX side.
+ * @phy_interface: Phy interface type.
+ * @phy_flags:	Phy interface flags.
+ * @eth_hasnobuf: Ethernet is configured in Non buf mode.
+ * @eth_hasptp: Ethernet is configured for ptp.
+ * @axienet_config: Ethernet config structure
+ * @tx_ts_regs:	  Base address for the axififo device address space.
+ * @rx_ts_regs:	  Base address for the rx axififo device address space.
+ * @tstamp_config: Hardware timestamp config structure.
+ * @tx_ptpheader: Stores the tx ptp header.
+ * @aclk: AXI4-Lite clock for ethernet and dma.
+ * @eth_sclk: AXI4-Stream interface clock.
+ * @eth_refclk: Stable clock used by signal delay primitives and transceivers.
+ * @eth_dclk: Dynamic Reconfiguration Port(DRP) clock.
+ * @dma_sg_clk: DMA Scatter Gather Clock.
+ * @dma_rx_clk: DMA S2MM Primary Clock.
+ * @dma_tx_clk: DMA MM2S Primary Clock.
+ * @qnum:     Axi Ethernet queue number to be operate on.
+ * @chan_num: MCDMA Channel number to be operate on.
+ * @chan_id:  MCMDA Channel id used in conjunction with weight parameter.
+ * @weight:   MCDMA Channel weight value to be configured for.
+ * @dma_mask: Specify the width of the DMA address space.
+ * @usxgmii_rate: USXGMII PHY speed.
+ * @mrmac_rate: MRMAC speed.
+ * @gt_pll: Common GT PLL mask control register space.
+ * @gt_ctrl: GT speed and reset control register space.
+ * @phc_index: Index to corresponding PTP clock used.
+ * @gt_lane: MRMAC GT lane index used.
  */
 struct axienet_local {
 	struct net_device *ndev;
@@ -421,9 +760,6 @@
 	/* Connection to PHY device */
 	struct device_node *phy_node;
 
-	struct phylink *phylink;
-	struct phylink_config phylink_config;
-
 	/* Clock for AXI bus */
 	struct clk *clk;
 
@@ -433,28 +769,45 @@
 	/* IO registers, dma functions and IRQs */
 	resource_size_t regs_start;
 	void __iomem *regs;
-	void __iomem *dma_regs;
+	void __iomem *mcdma_regs;
 
-	struct tasklet_struct dma_err_tasklet;
+	struct tasklet_struct dma_err_tasklet[XAE_MAX_QUEUES];
+	struct napi_struct napi[XAE_MAX_QUEUES];	/* NAPI Structure */
+
+	#define XAE_TEMAC1 0
+	#define XAE_TEMAC2 1
+	u8     temac_no;
+	u16    num_tx_queues;	/* Number of TX DMA queues */
+	u16    num_rx_queues;	/* Number of RX DMA queues */
+	struct axienet_dma_q *dq[XAE_MAX_QUEUES];	/* DMA queue data*/
 
-	int tx_irq;
-	int rx_irq;
-	int eth_irq;
 	phy_interface_t phy_mode;
 
+	bool is_tsn;
+#ifdef CONFIG_XILINX_TSN
+	u16    num_tc;
+#ifdef CONFIG_XILINX_TSN_PTP
+	void *timer_priv;
+	int ptp_tx_irq;
+	int ptp_rx_irq;
+	int rtc_irq;
+	int qbv_irq;
+	int ptp_ts_type;
+	u8  ptp_rx_hw_pointer;
+	u8  ptp_rx_sw_pointer;
+	struct sk_buff_head ptp_txq;
+	struct work_struct tx_tstamp_work;
+#endif
+#endif
+	spinlock_t ptp_tx_lock;		/* PTP tx lock*/
+	int eth_irq;
+
 	u32 options;			/* Current options word */
+	u32 last_link;
 	u32 features;
 
-	/* Buffer descriptors */
-	struct axidma_bd *tx_bd_v;
-	dma_addr_t tx_bd_p;
 	u32 tx_bd_num;
-	struct axidma_bd *rx_bd_v;
-	dma_addr_t rx_bd_p;
 	u32 rx_bd_num;
-	u32 tx_bd_ci;
-	u32 tx_bd_tail;
-	u32 rx_bd_ci;
 
 	u32 max_frm_size;
 	u32 rxmem;
@@ -464,6 +817,142 @@
 
 	u32 coalesce_count_rx;
 	u32 coalesce_count_tx;
+	u32 phy_interface;
+	u32 phy_flags;
+	bool eth_hasnobuf;
+	bool eth_hasptp;
+	const struct axienet_config *axienet_config;
+
+#if defined(CONFIG_XILINX_AXI_EMAC_HWTSTAMP) || defined(CONFIG_XILINX_TSN_PTP)
+	void __iomem *tx_ts_regs;
+	void __iomem *rx_ts_regs;
+	struct hwtstamp_config tstamp_config;
+	u8 *tx_ptpheader;
+#endif
+	struct clk *aclk;
+	struct clk *eth_sclk;
+	struct clk *eth_refclk;
+	struct clk *eth_dclk;
+	struct clk *dma_sg_clk;
+	struct clk *dma_rx_clk;
+	struct clk *dma_tx_clk;
+
+	/* MCDMA Fields */
+	int qnum[XAE_MAX_QUEUES];
+	int chan_num[XAE_MAX_QUEUES];
+	/* WRR Fields */
+	u16 chan_id;
+	u16 weight;
+
+	u8 dma_mask;
+	u32 usxgmii_rate;
+
+	u32 mrmac_rate;		/* MRMAC speed */
+	void __iomem *gt_pll;	/* Common GT PLL mask control register space */
+	void __iomem *gt_ctrl;	/* GT speed and reset control register space */
+	u32 phc_index;		/* Index to corresponding PTP clock used  */
+	u32 gt_lane;		/* MRMAC GT lane index used */
+};
+
+/**
+ * struct axienet_dma_q - axienet private per dma queue data
+ * @lp:		Parent pointer
+ * @dma_regs:	Base address for the axidma device address space
+ * @tx_irq:	Axidma TX IRQ number
+ * @rx_irq:	Axidma RX IRQ number
+ * @tx_lock:	Spin lock for tx path
+ * @rx_lock:	Spin lock for tx path
+ * @tx_bd_v:	Virtual address of the TX buffer descriptor ring
+ * @tx_bd_p:	Physical address(start address) of the TX buffer descr. ring
+ * @rx_bd_v:	Virtual address of the RX buffer descriptor ring
+ * @rx_bd_p:	Physical address(start address) of the RX buffer descr. ring
+ * @tx_buf:	Virtual address of the Tx buffer pool used by the driver when
+ *		DMA h/w is configured without DRE.
+ * @tx_bufs:	Virutal address of the Tx buffer address.
+ * @tx_bufs_dma: Physical address of the Tx buffer address used by the driver
+ *		 when DMA h/w is configured without DRE.
+ * @eth_hasdre: Tells whether DMA h/w is configured with dre or not.
+ * @tx_bd_ci:	Stores the index of the Tx buffer descriptor in the ring being
+ *		accessed currently. Used while alloc. BDs before a TX starts
+ * @tx_bd_tail:	Stores the index of the Tx buffer descriptor in the ring being
+ *		accessed currently. Used while processing BDs after the TX
+ *		completed.
+ * @rx_bd_ci:	Stores the index of the Rx buffer descriptor in the ring being
+ *		accessed currently.
+ * @chan_id:    MCDMA channel to operate on.
+ * @rx_offset:	MCDMA S2MM channel starting offset.
+ * @txq_bd_v:	Virtual address of the MCDMA TX buffer descriptor ring
+ * @rxq_bd_v:	Virtual address of the MCDMA RX buffer descriptor ring
+ * @tx_packets: Number of transmit packets processed by the dma queue.
+ * @tx_bytes:   Number of transmit bytes processed by the dma queue.
+ * @rx_packets: Number of receive packets processed by the dma queue.
+ * @rx_bytes:	Number of receive bytes processed by the dma queue.
+ */
+struct axienet_dma_q {
+	struct axienet_local	*lp; /* parent */
+	void __iomem *dma_regs;
+
+	int tx_irq;
+	int rx_irq;
+
+	spinlock_t tx_lock;		/* tx lock */
+	spinlock_t rx_lock;		/* rx lock */
+
+	/* Buffer descriptors */
+	struct axidma_bd *tx_bd_v;
+	struct axidma_bd *rx_bd_v;
+	dma_addr_t rx_bd_p;
+	dma_addr_t tx_bd_p;
+
+	unsigned char *tx_buf[XAE_TX_BUFFERS];
+	unsigned char *tx_bufs;
+	dma_addr_t tx_bufs_dma;
+	bool eth_hasdre;
+
+	u32 tx_bd_ci;
+	u32 rx_bd_ci;
+	u32 tx_bd_tail;
+
+	/* MCDMA fields */
+	u16 chan_id;
+	u32 rx_offset;
+	struct aximcdma_bd *txq_bd_v;
+	struct aximcdma_bd *rxq_bd_v;
+
+	unsigned long tx_packets;
+	unsigned long tx_bytes;
+	unsigned long rx_packets;
+	unsigned long rx_bytes;
+};
+
+#define AXIENET_TX_SSTATS_LEN(lp) ((lp)->num_tx_queues * 2)
+#define AXIENET_RX_SSTATS_LEN(lp) ((lp)->num_rx_queues * 2)
+
+/**
+ * enum axienet_ip_type - AXIENET IP/MAC type.
+ *
+ * @XAXIENET_1G:	 IP is 1G MAC
+ * @XAXIENET_2_5G:	 IP type is 2.5G MAC.
+ * @XAXIENET_LEGACY_10G: IP type is legacy 10G MAC.
+ * @XAXIENET_10G_25G:	 IP type is 10G/25G MAC(XXV MAC).
+ * @XAXIENET_MRMAC:	 IP type is hardened Multi Rate MAC (MRMAC).
+ *
+ */
+enum axienet_ip_type {
+	XAXIENET_1G = 0,
+	XAXIENET_2_5G,
+	XAXIENET_LEGACY_10G,
+	XAXIENET_10G_25G,
+	XAXIENET_MRMAC,
+};
+
+struct axienet_config {
+	enum axienet_ip_type mactype;
+	void (*setoptions)(struct net_device *ndev, u32 options);
+	int (*clk_init)(struct platform_device *pdev, struct clk **axi_aclk,
+			struct clk **axis_clk, struct clk **ref_clk,
+			struct clk **dclk);
+	u32 tx_ptplen;
 };
 
 /**
@@ -478,6 +967,17 @@
 	u32 m_or;
 };
 
+struct xxvenet_option {
+	u32 opt;
+	u32 reg;
+	u32 m_or;
+};
+
+extern void __iomem *mrmac_gt_pll;
+extern void __iomem *mrmac_gt_ctrl;
+extern int mrmac_pll_reg;
+extern int mrmac_pll_rst;
+
 /**
  * axienet_ior - Memory mapped Axi Ethernet register read
  * @lp:         Pointer to axienet local structure
@@ -512,10 +1012,183 @@
 	iowrite32(value, lp->regs + offset);
 }
 
+#ifdef CONFIG_XILINX_AXI_EMAC_HWTSTAMP
+/**
+ * axienet_txts_ior - Memory mapped AXI FIFO MM S register read
+ * @lp:         Pointer to axienet_local structure
+ * @reg:     Address offset from the base address of AXI FIFO MM S
+ *              core
+ *
+ * Return: the contents of the AXI FIFO MM S register
+ */
+
+static inline u32 axienet_txts_ior(struct axienet_local *lp, off_t reg)
+{
+	return ioread32(lp->tx_ts_regs + reg);
+}
+
+/**
+ * axienet_txts_iow - Memory mapper AXI FIFO MM S register write
+ * @lp:         Pointer to axienet_local structure
+ * @reg:     Address offset from the base address of AXI FIFO MM S
+ *              core.
+ * @value:      Value to be written into the AXI FIFO MM S register
+ */
+static inline void axienet_txts_iow(struct  axienet_local *lp, off_t reg,
+				    u32 value)
+{
+	iowrite32(value, (lp->tx_ts_regs + reg));
+}
+
+/**
+ * axienet_rxts_ior - Memory mapped AXI FIFO MM S register read
+ * @lp:         Pointer to axienet_local structure
+ * @reg:     Address offset from the base address of AXI FIFO MM S
+ *              core
+ *
+ * Return: the contents of the AXI FIFO MM S register
+ */
+
+static inline u32 axienet_rxts_ior(struct axienet_local *lp, off_t reg)
+{
+	return ioread32(lp->rx_ts_regs + reg);
+}
+
+/**
+ * axienet_rxts_iow - Memory mapper AXI FIFO MM S register write
+ * @lp:         Pointer to axienet_local structure
+ * @reg:     Address offset from the base address of AXI FIFO MM S
+ *              core.
+ * @value:      Value to be written into the AXI FIFO MM S register
+ */
+static inline void axienet_rxts_iow(struct  axienet_local *lp, off_t reg,
+				    u32 value)
+{
+	iowrite32(value, (lp->rx_ts_regs + reg));
+}
+#endif
+
+/**
+ * axienet_dma_in32 - Memory mapped Axi DMA register read
+ * @q:		Pointer to DMA queue structure
+ * @reg:	Address offset from the base address of the Axi DMA core
+ *
+ * Return: The contents of the Axi DMA register
+ *
+ * This function returns the contents of the corresponding Axi DMA register.
+ */
+static inline u32 axienet_dma_in32(struct axienet_dma_q *q, off_t reg)
+{
+	return ioread32(q->dma_regs + reg);
+}
+
+/**
+ * axienet_dma_out32 - Memory mapped Axi DMA register write.
+ * @q:		Pointer to DMA queue structure
+ * @reg:	Address offset from the base address of the Axi DMA core
+ * @value:	Value to be written into the Axi DMA register
+ *
+ * This function writes the desired value into the corresponding Axi DMA
+ * register.
+ */
+static inline void axienet_dma_out32(struct axienet_dma_q *q,
+				     off_t reg, u32 value)
+{
+	iowrite32(value, q->dma_regs + reg);
+}
+
+/**
+ * axienet_dma_bdout - Memory mapped Axi DMA register Buffer Descriptor write.
+ * @q:		Pointer to DMA queue structure
+ * @reg:	Address offset from the base address of the Axi DMA core
+ * @value:	Value to be written into the Axi DMA register
+ *
+ * This function writes the desired value into the corresponding Axi DMA
+ * register.
+ */
+static inline void axienet_dma_bdout(struct axienet_dma_q *q,
+				     off_t reg, dma_addr_t value)
+{
+#if defined(CONFIG_PHYS_ADDR_T_64BIT)
+	writeq(value, (q->dma_regs + reg));
+#else
+	writel(value, (q->dma_regs + reg));
+#endif
+}
 /* Function prototypes visible in xilinx_axienet_mdio.c for other files */
 int axienet_mdio_enable(struct axienet_local *lp);
 void axienet_mdio_disable(struct axienet_local *lp);
 int axienet_mdio_setup(struct axienet_local *lp);
 void axienet_mdio_teardown(struct axienet_local *lp);
+#ifdef CONFIG_XILINX_TSN_PTP
+void axienet_tx_tstamp(struct work_struct *work);
+#endif
+#ifdef CONFIG_XILINX_TSN_QBV
+int axienet_qbv_init(struct net_device *ndev);
+void axienet_qbv_remove(struct net_device *ndev);
+int axienet_set_schedule(struct net_device *ndev, void __user *useraddr);
+int axienet_get_schedule(struct net_device *ndev, void __user *useraddr);
+#endif
+
+#ifdef CONFIG_XILINX_TSN_QBR
+int axienet_preemption(struct net_device *ndev, void __user *useraddr);
+int axienet_preemption_ctrl(struct net_device *ndev, void __user *useraddr);
+int axienet_preemption_sts(struct net_device *ndev, void __user *useraddr);
+int axienet_preemption_cnt(struct net_device *ndev, void __user *useraddr);
+#ifdef CONFIG_XILINX_TSN_QBV
+int axienet_qbu_user_override(struct net_device *ndev, void __user *useraddr);
+int axienet_qbu_sts(struct net_device *ndev, void __user *useraddr);
+#endif
+#endif
+
+int axienet_mdio_wait_until_ready(struct axienet_local *lp);
+void __maybe_unused axienet_bd_free(struct net_device *ndev,
+				    struct axienet_dma_q *q);
+int __maybe_unused axienet_dma_q_init(struct net_device *ndev,
+				      struct axienet_dma_q *q);
+void axienet_dma_err_handler(unsigned long data);
+irqreturn_t __maybe_unused axienet_tx_irq(int irq, void *_ndev);
+irqreturn_t __maybe_unused axienet_rx_irq(int irq, void *_ndev);
+void axienet_start_xmit_done(struct net_device *ndev, struct axienet_dma_q *q);
+void axienet_dma_bd_release(struct net_device *ndev);
+void __axienet_device_reset(struct axienet_dma_q *q);
+void axienet_set_mac_address(struct net_device *ndev, const void *address);
+void axienet_set_multicast_list(struct net_device *ndev);
+int xaxienet_rx_poll(struct napi_struct *napi, int quota);
+
+#if defined(CONFIG_AXIENET_HAS_MCDMA)
+int __maybe_unused axienet_mcdma_rx_q_init(struct net_device *ndev,
+					   struct axienet_dma_q *q);
+int __maybe_unused axienet_mcdma_tx_q_init(struct net_device *ndev,
+					   struct axienet_dma_q *q);
+void __maybe_unused axienet_mcdma_tx_bd_free(struct net_device *ndev,
+					     struct axienet_dma_q *q);
+void __maybe_unused axienet_mcdma_rx_bd_free(struct net_device *ndev,
+					     struct axienet_dma_q *q);
+irqreturn_t __maybe_unused axienet_mcdma_tx_irq(int irq, void *_ndev);
+irqreturn_t __maybe_unused axienet_mcdma_rx_irq(int irq, void *_ndev);
+void __maybe_unused axienet_mcdma_err_handler(unsigned long data);
+void axienet_strings(struct net_device *ndev, u32 sset, u8 *data);
+int axienet_sset_count(struct net_device *ndev, int sset);
+void axienet_get_stats(struct net_device *ndev,
+		       struct ethtool_stats *stats,
+		       u64 *data);
+int axeinet_mcdma_create_sysfs(struct kobject *kobj);
+void axeinet_mcdma_remove_sysfs(struct kobject *kobj);
+int __maybe_unused axienet_mcdma_tx_probe(struct platform_device *pdev,
+					  struct device_node *np,
+					  struct axienet_local *lp);
+int __maybe_unused axienet_mcdma_rx_probe(struct platform_device *pdev,
+					  struct axienet_local *lp,
+					  struct net_device *ndev);
+#endif
+
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+void axienet_tx_hwtstamp(struct axienet_local *lp,
+			 struct aximcdma_bd *cur_p);
+#else
+void axienet_tx_hwtstamp(struct axienet_local *lp,
+			 struct axidma_bd *cur_p);
+#endif
 
 #endif /* XILINX_AXI_ENET_H */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/xilinx/xilinx_axienet_dma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/xilinx/xilinx_axienet_dma.c
@@ -0,0 +1,504 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/* Xilinx AXI Ethernet (DMA programming)
+ *
+ * Copyright (c) 2008 Nissin Systems Co., Ltd.,  Yoshio Kashiwagi
+ * Copyright (c) 2005-2008 DLA Systems,  David H. Lynch Jr. <dhlii@dlasys.net>
+ * Copyright (c) 2008-2009 Secret Lab Technologies Ltd.
+ * Copyright (c) 2010 - 2011 Michal Simek <monstr@monstr.eu>
+ * Copyright (c) 2010 - 2011 PetaLogix
+ * Copyright (c) 2010 - 2012 Xilinx, Inc.
+ * Copyright (C) 2018 Xilinx, Inc. All rights reserved.
+ *
+ * This file contains helper functions for AXI DMA TX and RX programming.
+ */
+
+#include "xilinx_axienet.h"
+
+/**
+ * axienet_bd_free - Release buffer descriptor rings for individual dma queue
+ * @ndev:	Pointer to the net_device structure
+ * @q:		Pointer to DMA queue structure
+ *
+ * This function is helper function to axienet_dma_bd_release.
+ */
+
+void __maybe_unused axienet_bd_free(struct net_device *ndev,
+				    struct axienet_dma_q *q)
+{
+	int i;
+	struct axienet_local *lp = netdev_priv(ndev);
+
+	for (i = 0; i < lp->rx_bd_num; i++) {
+		dma_unmap_single(ndev->dev.parent, q->rx_bd_v[i].phys,
+				 lp->max_frm_size, DMA_FROM_DEVICE);
+		dev_kfree_skb((struct sk_buff *)
+			      (q->rx_bd_v[i].sw_id_offset));
+	}
+
+	if (q->rx_bd_v) {
+		dma_free_coherent(ndev->dev.parent,
+				  sizeof(*q->rx_bd_v) * lp->rx_bd_num,
+				  q->rx_bd_v,
+				  q->rx_bd_p);
+	}
+	if (q->tx_bd_v) {
+		dma_free_coherent(ndev->dev.parent,
+				  sizeof(*q->tx_bd_v) * lp->tx_bd_num,
+				  q->tx_bd_v,
+				  q->tx_bd_p);
+	}
+	if (q->tx_bufs) {
+		dma_free_coherent(ndev->dev.parent,
+				  XAE_MAX_PKT_LEN * lp->tx_bd_num,
+				  q->tx_bufs,
+				  q->tx_bufs_dma);
+	}
+}
+
+/**
+ * __dma_txq_init - Setup buffer descriptor rings for individual Axi DMA-Tx
+ * @ndev:	Pointer to the net_device structure
+ * @q:		Pointer to DMA queue structure
+ *
+ * Return: 0, on success -ENOMEM, on failure
+ *
+ * This function is helper function to axienet_dma_q_init
+ */
+static int __dma_txq_init(struct net_device *ndev, struct axienet_dma_q *q)
+{
+	int i;
+	u32 cr;
+	struct axienet_local *lp = netdev_priv(ndev);
+
+	q->tx_bd_ci = 0;
+	q->tx_bd_tail = 0;
+
+	q->tx_bd_v = dma_alloc_coherent(ndev->dev.parent,
+					sizeof(*q->tx_bd_v) * lp->tx_bd_num,
+					&q->tx_bd_p, GFP_KERNEL);
+	if (!q->tx_bd_v)
+		goto out;
+
+	for (i = 0; i < lp->tx_bd_num; i++) {
+		q->tx_bd_v[i].next = q->tx_bd_p +
+				     sizeof(*q->tx_bd_v) *
+				     ((i + 1) % lp->tx_bd_num);
+	}
+
+	if (!q->eth_hasdre) {
+		q->tx_bufs = dma_alloc_coherent(ndev->dev.parent,
+						XAE_MAX_PKT_LEN * lp->tx_bd_num,
+						&q->tx_bufs_dma,
+						GFP_KERNEL);
+		if (!q->tx_bufs)
+			goto out;
+
+		for (i = 0; i < lp->tx_bd_num; i++)
+			q->tx_buf[i] = &q->tx_bufs[i * XAE_MAX_PKT_LEN];
+	}
+
+	/* Start updating the Tx channel control register */
+	cr = axienet_dma_in32(q, XAXIDMA_TX_CR_OFFSET);
+	/* Update the interrupt coalesce count */
+	cr = (((cr & ~XAXIDMA_COALESCE_MASK)) |
+	      ((lp->coalesce_count_tx) << XAXIDMA_COALESCE_SHIFT));
+	/* Update the delay timer count */
+	cr = (((cr & ~XAXIDMA_DELAY_MASK)) |
+	      (XAXIDMA_DFT_TX_WAITBOUND << XAXIDMA_DELAY_SHIFT));
+	/* Enable coalesce, delay timer and error interrupts */
+	cr |= XAXIDMA_IRQ_ALL_MASK;
+	/* Write to the Tx channel control register */
+	axienet_dma_out32(q, XAXIDMA_TX_CR_OFFSET, cr);
+
+	/* Write to the RS (Run-stop) bit in the Tx channel control register.
+	 * Tx channel is now ready to run. But only after we write to the
+	 * tail pointer register that the Tx channel will start transmitting.
+	 */
+	axienet_dma_bdout(q, XAXIDMA_TX_CDESC_OFFSET, q->tx_bd_p);
+	cr = axienet_dma_in32(q, XAXIDMA_TX_CR_OFFSET);
+	axienet_dma_out32(q, XAXIDMA_TX_CR_OFFSET,
+			  cr | XAXIDMA_CR_RUNSTOP_MASK);
+	return 0;
+out:
+	return -ENOMEM;
+}
+
+/**
+ * __dma_rxq_init - Setup buffer descriptor rings for individual Axi DMA-Rx
+ * @ndev:	Pointer to the net_device structure
+ * @q:		Pointer to DMA queue structure
+ *
+ * Return: 0, on success -ENOMEM, on failure
+ *
+ * This function is helper function to axienet_dma_q_init
+ */
+static int __dma_rxq_init(struct net_device *ndev,
+			  struct axienet_dma_q *q)
+{
+	int i;
+	u32 cr;
+	struct sk_buff *skb;
+	struct axienet_local *lp = netdev_priv(ndev);
+	/* Reset the indexes which are used for accessing the BDs */
+	q->rx_bd_ci = 0;
+
+	/* Allocate the Rx buffer descriptors. */
+	q->rx_bd_v = dma_alloc_coherent(ndev->dev.parent,
+					sizeof(*q->rx_bd_v) * lp->rx_bd_num,
+					&q->rx_bd_p, GFP_KERNEL);
+	if (!q->rx_bd_v)
+		goto out;
+
+	for (i = 0; i < lp->rx_bd_num; i++) {
+		q->rx_bd_v[i].next = q->rx_bd_p +
+				     sizeof(*q->rx_bd_v) *
+				     ((i + 1) % lp->rx_bd_num);
+
+		skb = netdev_alloc_skb(ndev, lp->max_frm_size);
+		if (!skb)
+			goto out;
+
+		/* Ensure that the skb is completely updated
+		 * prio to mapping the DMA
+		 */
+		wmb();
+
+		q->rx_bd_v[i].sw_id_offset = (phys_addr_t)skb;
+		q->rx_bd_v[i].phys = dma_map_single(ndev->dev.parent,
+						    skb->data,
+						    lp->max_frm_size,
+						    DMA_FROM_DEVICE);
+		q->rx_bd_v[i].cntrl = lp->max_frm_size;
+	}
+
+	/* Start updating the Rx channel control register */
+	cr = axienet_dma_in32(q, XAXIDMA_RX_CR_OFFSET);
+	/* Update the interrupt coalesce count */
+	cr = ((cr & ~XAXIDMA_COALESCE_MASK) |
+	      ((lp->coalesce_count_rx) << XAXIDMA_COALESCE_SHIFT));
+	/* Update the delay timer count */
+	cr = ((cr & ~XAXIDMA_DELAY_MASK) |
+	      (XAXIDMA_DFT_RX_WAITBOUND << XAXIDMA_DELAY_SHIFT));
+	/* Enable coalesce, delay timer and error interrupts */
+	cr |= XAXIDMA_IRQ_ALL_MASK;
+	/* Write to the Rx channel control register */
+	axienet_dma_out32(q, XAXIDMA_RX_CR_OFFSET, cr);
+
+	/* Populate the tail pointer and bring the Rx Axi DMA engine out of
+	 * halted state. This will make the Rx side ready for reception.
+	 */
+	axienet_dma_bdout(q, XAXIDMA_RX_CDESC_OFFSET, q->rx_bd_p);
+	cr = axienet_dma_in32(q, XAXIDMA_RX_CR_OFFSET);
+	axienet_dma_out32(q, XAXIDMA_RX_CR_OFFSET,
+			  cr | XAXIDMA_CR_RUNSTOP_MASK);
+	axienet_dma_bdout(q, XAXIDMA_RX_TDESC_OFFSET, q->rx_bd_p +
+			  (sizeof(*q->rx_bd_v) * (lp->rx_bd_num - 1)));
+
+	return 0;
+out:
+	return -ENOMEM;
+}
+
+/**
+ * axienet_dma_q_init - Setup buffer descriptor rings for individual Axi DMA
+ * @ndev:	Pointer to the net_device structure
+ * @q:		Pointer to DMA queue structure
+ *
+ * Return: 0, on success -ENOMEM, on failure
+ *
+ * This function is helper function to axienet_dma_bd_init
+ */
+int __maybe_unused axienet_dma_q_init(struct net_device *ndev,
+				      struct axienet_dma_q *q)
+{
+	if (__dma_txq_init(ndev, q))
+		goto out;
+
+	if (__dma_rxq_init(ndev, q))
+		goto out;
+
+	return 0;
+out:
+	axienet_dma_bd_release(ndev);
+	return -ENOMEM;
+}
+
+/**
+ * map_dma_q_irq - Map dma q based on interrupt number.
+ * @irq:	irq number
+ * @lp:		axienet local structure
+ *
+ * Return: DMA queue.
+ *
+ * This returns the DMA number on which interrupt has occurred.
+ */
+static int map_dma_q_irq(int irq, struct axienet_local *lp)
+{
+	int i;
+
+	for_each_rx_dma_queue(lp, i) {
+		if (irq == lp->dq[i]->tx_irq || irq == lp->dq[i]->rx_irq)
+			return i;
+	}
+	pr_err("Error mapping DMA irq\n");
+	return -ENODEV;
+}
+
+/**
+ * axienet_tx_irq - Tx Done Isr.
+ * @irq:	irq number
+ * @_ndev:	net_device pointer
+ *
+ * Return: IRQ_HANDLED if device generated a TX interrupt, IRQ_NONE otherwise.
+ *
+ * This is the Axi DMA Tx done Isr. It invokes "axienet_start_xmit_done"
+ * to complete the BD processing.
+ */
+irqreturn_t __maybe_unused axienet_tx_irq(int irq, void *_ndev)
+{
+	u32 cr;
+	unsigned int status;
+	struct net_device *ndev = _ndev;
+	struct axienet_local *lp = netdev_priv(ndev);
+	int i = map_dma_q_irq(irq, lp);
+	struct axienet_dma_q *q;
+
+	if (i < 0)
+		return IRQ_NONE;
+
+	q = lp->dq[i];
+
+	status = axienet_dma_in32(q, XAXIDMA_TX_SR_OFFSET);
+	if (status & (XAXIDMA_IRQ_IOC_MASK | XAXIDMA_IRQ_DELAY_MASK)) {
+		axienet_dma_out32(q, XAXIDMA_TX_SR_OFFSET, status);
+		axienet_start_xmit_done(lp->ndev, q);
+		goto out;
+	}
+
+	if (!(status & XAXIDMA_IRQ_ALL_MASK))
+		return IRQ_NONE;
+
+	if (status & XAXIDMA_IRQ_ERROR_MASK) {
+		dev_err(&ndev->dev, "DMA Tx error 0x%x\n", status);
+		dev_err(&ndev->dev, "Current BD is at: %pa\n",
+			&q->tx_bd_v[q->tx_bd_ci].phys);
+
+		cr = axienet_dma_in32(q, XAXIDMA_TX_CR_OFFSET);
+		/* Disable coalesce, delay timer and error interrupts */
+		cr &= (~XAXIDMA_IRQ_ALL_MASK);
+		/* Write to the Tx channel control register */
+		axienet_dma_out32(q, XAXIDMA_TX_CR_OFFSET, cr);
+
+		cr = axienet_dma_in32(q, XAXIDMA_RX_CR_OFFSET);
+		/* Disable coalesce, delay timer and error interrupts */
+		cr &= (~XAXIDMA_IRQ_ALL_MASK);
+		/* Write to the Rx channel control register */
+		axienet_dma_out32(q, XAXIDMA_RX_CR_OFFSET, cr);
+
+		tasklet_schedule(&lp->dma_err_tasklet[i]);
+		axienet_dma_out32(q, XAXIDMA_TX_SR_OFFSET, status);
+	}
+out:
+	return IRQ_HANDLED;
+}
+
+/**
+ * axienet_rx_irq - Rx Isr.
+ * @irq:	irq number
+ * @_ndev:	net_device pointer
+ *
+ * Return: IRQ_HANDLED if device generated a RX interrupt, IRQ_NONE otherwise.
+ *
+ * This is the Axi DMA Rx Isr. It invokes "axienet_recv" to complete the BD
+ * processing.
+ */
+irqreturn_t __maybe_unused axienet_rx_irq(int irq, void *_ndev)
+{
+	u32 cr;
+	unsigned int status;
+	struct net_device *ndev = _ndev;
+	struct axienet_local *lp = netdev_priv(ndev);
+	int i = map_dma_q_irq(irq, lp);
+	struct axienet_dma_q *q;
+
+	if (i < 0)
+		return IRQ_NONE;
+
+	q = lp->dq[i];
+
+	status = axienet_dma_in32(q, XAXIDMA_RX_SR_OFFSET);
+	if (status & (XAXIDMA_IRQ_IOC_MASK | XAXIDMA_IRQ_DELAY_MASK)) {
+		cr = axienet_dma_in32(q, XAXIDMA_RX_CR_OFFSET);
+		cr &= ~(XAXIDMA_IRQ_IOC_MASK | XAXIDMA_IRQ_DELAY_MASK);
+		axienet_dma_out32(q, XAXIDMA_RX_CR_OFFSET, cr);
+		napi_schedule(&lp->napi[i]);
+	}
+
+	if (!(status & XAXIDMA_IRQ_ALL_MASK))
+		return IRQ_NONE;
+
+	if (status & XAXIDMA_IRQ_ERROR_MASK) {
+		dev_err(&ndev->dev, "DMA Rx error 0x%x\n", status);
+		dev_err(&ndev->dev, "Current BD is at: %pa\n",
+			&q->rx_bd_v[q->rx_bd_ci].phys);
+
+		cr = axienet_dma_in32(q, XAXIDMA_TX_CR_OFFSET);
+		/* Disable coalesce, delay timer and error interrupts */
+		cr &= (~XAXIDMA_IRQ_ALL_MASK);
+		/* Finally write to the Tx channel control register */
+		axienet_dma_out32(q, XAXIDMA_TX_CR_OFFSET, cr);
+
+		cr = axienet_dma_in32(q, XAXIDMA_RX_CR_OFFSET);
+		/* Disable coalesce, delay timer and error interrupts */
+		cr &= (~XAXIDMA_IRQ_ALL_MASK);
+			/* write to the Rx channel control register */
+		axienet_dma_out32(q, XAXIDMA_RX_CR_OFFSET, cr);
+
+		tasklet_schedule(&lp->dma_err_tasklet[i]);
+		axienet_dma_out32(q, XAXIDMA_RX_SR_OFFSET, status);
+	}
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * axienet_dma_err_handler - Tasklet handler for Axi DMA Error
+ * @data:	Data passed
+ *
+ * Resets the Axi DMA and Axi Ethernet devices, and reconfigures the
+ * Tx/Rx BDs.
+ */
+void __maybe_unused axienet_dma_err_handler(unsigned long data)
+{
+	u32 axienet_status;
+	u32 cr, i;
+	struct axienet_dma_q *q = (struct axienet_dma_q *)data;
+	struct axienet_local *lp = q->lp;
+	struct net_device *ndev = lp->ndev;
+	struct axidma_bd *cur_p;
+
+	lp->axienet_config->setoptions(ndev, lp->options &
+				       ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN));
+
+	if (lp->axienet_config->mactype != XAXIENET_10G_25G) {
+		mutex_lock(&lp->mii_bus->mdio_lock);
+		axienet_mdio_disable(lp);
+		axienet_mdio_wait_until_ready(lp);
+		/* Disable the MDIO interface till Axi Ethernet Reset is
+		 * Completed. When we do an Axi Ethernet reset, it resets the
+		 * Complete core including the MDIO. So if MDIO is not disabled
+		 * When the reset process is started,
+		 * MDIO will be broken afterwards.
+		 */
+	}
+
+	__axienet_device_reset(q);
+
+	if (lp->axienet_config->mactype != XAXIENET_10G_25G) {
+		axienet_mdio_enable(lp);
+		axienet_mdio_wait_until_ready(lp);
+		mutex_unlock(&lp->mii_bus->mdio_lock);
+	}
+
+	for (i = 0; i < lp->tx_bd_num; i++) {
+		cur_p = &q->tx_bd_v[i];
+		if (cur_p->phys)
+			dma_unmap_single(ndev->dev.parent, cur_p->phys,
+					 (cur_p->cntrl &
+					  XAXIDMA_BD_CTRL_LENGTH_MASK),
+					 DMA_TO_DEVICE);
+		if (cur_p->tx_skb)
+			dev_kfree_skb_irq((struct sk_buff *)cur_p->tx_skb);
+		cur_p->phys = 0;
+		cur_p->cntrl = 0;
+		cur_p->status = 0;
+		cur_p->app0 = 0;
+		cur_p->app1 = 0;
+		cur_p->app2 = 0;
+		cur_p->app3 = 0;
+		cur_p->app4 = 0;
+		cur_p->sw_id_offset = 0;
+		cur_p->tx_skb = 0;
+	}
+
+	for (i = 0; i < lp->rx_bd_num; i++) {
+		cur_p = &q->rx_bd_v[i];
+		cur_p->status = 0;
+		cur_p->app0 = 0;
+		cur_p->app1 = 0;
+		cur_p->app2 = 0;
+		cur_p->app3 = 0;
+		cur_p->app4 = 0;
+	}
+
+	q->tx_bd_ci = 0;
+	q->tx_bd_tail = 0;
+	q->rx_bd_ci = 0;
+
+	/* Start updating the Rx channel control register */
+	cr = axienet_dma_in32(q, XAXIDMA_RX_CR_OFFSET);
+	/* Update the interrupt coalesce count */
+	cr = ((cr & ~XAXIDMA_COALESCE_MASK) |
+	      (XAXIDMA_DFT_RX_THRESHOLD << XAXIDMA_COALESCE_SHIFT));
+	/* Update the delay timer count */
+	cr = ((cr & ~XAXIDMA_DELAY_MASK) |
+	      (XAXIDMA_DFT_RX_WAITBOUND << XAXIDMA_DELAY_SHIFT));
+	/* Enable coalesce, delay timer and error interrupts */
+	cr |= XAXIDMA_IRQ_ALL_MASK;
+	/* Finally write to the Rx channel control register */
+	axienet_dma_out32(q, XAXIDMA_RX_CR_OFFSET, cr);
+
+	/* Start updating the Tx channel control register */
+	cr = axienet_dma_in32(q, XAXIDMA_TX_CR_OFFSET);
+	/* Update the interrupt coalesce count */
+	cr = (((cr & ~XAXIDMA_COALESCE_MASK)) |
+	      (XAXIDMA_DFT_TX_THRESHOLD << XAXIDMA_COALESCE_SHIFT));
+	/* Update the delay timer count */
+	cr = (((cr & ~XAXIDMA_DELAY_MASK)) |
+	      (XAXIDMA_DFT_TX_WAITBOUND << XAXIDMA_DELAY_SHIFT));
+	/* Enable coalesce, delay timer and error interrupts */
+	cr |= XAXIDMA_IRQ_ALL_MASK;
+	/* Finally write to the Tx channel control register */
+	axienet_dma_out32(q, XAXIDMA_TX_CR_OFFSET, cr);
+
+	/* Populate the tail pointer and bring the Rx Axi DMA engine out of
+	 * halted state. This will make the Rx side ready for reception.
+	 */
+	axienet_dma_bdout(q, XAXIDMA_RX_CDESC_OFFSET, q->rx_bd_p);
+	cr = axienet_dma_in32(q, XAXIDMA_RX_CR_OFFSET);
+	axienet_dma_out32(q, XAXIDMA_RX_CR_OFFSET,
+			  cr | XAXIDMA_CR_RUNSTOP_MASK);
+	axienet_dma_bdout(q, XAXIDMA_RX_TDESC_OFFSET, q->rx_bd_p +
+			  (sizeof(*q->rx_bd_v) * (lp->rx_bd_num - 1)));
+
+	/* Write to the RS (Run-stop) bit in the Tx channel control register.
+	 * Tx channel is now ready to run. But only after we write to the
+	 * tail pointer register that the Tx channel will start transmitting
+	 */
+	axienet_dma_bdout(q, XAXIDMA_TX_CDESC_OFFSET, q->tx_bd_p);
+	cr = axienet_dma_in32(q, XAXIDMA_TX_CR_OFFSET);
+	axienet_dma_out32(q, XAXIDMA_TX_CR_OFFSET,
+			  cr | XAXIDMA_CR_RUNSTOP_MASK);
+
+	if (lp->axienet_config->mactype != XAXIENET_10G_25G) {
+		axienet_status = axienet_ior(lp, XAE_RCW1_OFFSET);
+		axienet_status &= ~XAE_RCW1_RX_MASK;
+		axienet_iow(lp, XAE_RCW1_OFFSET, axienet_status);
+	}
+
+	if (lp->axienet_config->mactype == XAXIENET_1G && !lp->eth_hasnobuf) {
+		axienet_status = axienet_ior(lp, XAE_IP_OFFSET);
+		if (axienet_status & XAE_INT_RXRJECT_MASK)
+			axienet_iow(lp, XAE_IS_OFFSET, XAE_INT_RXRJECT_MASK);
+	}
+
+	if (lp->axienet_config->mactype != XAXIENET_10G_25G)
+		axienet_iow(lp, XAE_FCC_OFFSET, XAE_FCC_FCRX_MASK);
+
+	lp->axienet_config->setoptions(ndev, lp->options &
+			   ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN));
+	axienet_set_mac_address(ndev, NULL);
+	axienet_set_multicast_list(ndev);
+	lp->axienet_config->setoptions(ndev, lp->options);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -23,6 +23,7 @@
  */
 
 #include <linux/clk.h>
+#include <linux/circ_buf.h>
 #include <linux/delay.h>
 #include <linux/etherdevice.h>
 #include <linux/module.h>
@@ -37,12 +38,24 @@
 #include <linux/phy.h>
 #include <linux/mii.h>
 #include <linux/ethtool.h>
+#include <linux/iopoll.h>
+#include <linux/ptp_classify.h>
+#include <linux/net_tstamp.h>
+#include <linux/random.h>
+#include <net/sock.h>
+#include <linux/xilinx_phy.h>
+#include <linux/clk.h>
 
 #include "xilinx_axienet.h"
 
+#ifdef CONFIG_XILINX_TSN_PTP
+#include "xilinx_tsn_ptp.h"
+#include "xilinx_tsn_timer.h"
+#endif
 /* Descriptors defines for Tx and Rx DMA */
-#define TX_BD_NUM_DEFAULT		64
-#define RX_BD_NUM_DEFAULT		1024
+#define TX_BD_NUM_DEFAULT		128
+#define RX_BD_NUM_DEFAULT		128
+#define TX_BD_NUM_MIN			(MAX_SKB_FRAGS + 1)
 #define TX_BD_NUM_MAX			4096
 #define RX_BD_NUM_MAX			4096
 
@@ -52,16 +65,28 @@
 #define DRIVER_VERSION		"1.00a"
 
 #define AXIENET_REGS_N		40
+#define AXIENET_TS_HEADER_LEN	8
+#define XXVENET_TS_HEADER_LEN	4
+#define NS_PER_SEC              1000000000ULL /* Nanoseconds per second */
+
+#define MRMAC_RESET_DELAY	1 /* Delay in msecs*/
+
+#ifdef CONFIG_XILINX_TSN_PTP
+int axienet_phc_index = -1;
+EXPORT_SYMBOL(axienet_phc_index);
+#endif
 
-/* Match table for of_platform binding */
-static const struct of_device_id axienet_of_match[] = {
-	{ .compatible = "xlnx,axi-ethernet-1.00.a", },
-	{ .compatible = "xlnx,axi-ethernet-1.01.a", },
-	{ .compatible = "xlnx,axi-ethernet-2.01.a", },
-	{},
-};
+void __iomem *mrmac_gt_pll;
+EXPORT_SYMBOL(mrmac_gt_pll);
 
-MODULE_DEVICE_TABLE(of, axienet_of_match);
+void __iomem *mrmac_gt_ctrl;
+EXPORT_SYMBOL(mrmac_gt_ctrl);
+
+int mrmac_pll_reg;
+EXPORT_SYMBOL(mrmac_pll_reg);
+
+int mrmac_pll_rst;
+EXPORT_SYMBOL(mrmac_pll_rst);
 
 /* Option table for setting up Axi Ethernet hardware options */
 static struct axienet_option axienet_options[] = {
@@ -104,8 +129,8 @@
 		.m_or = XAE_FCC_FCTX_MASK,
 	}, { /* Turn on promiscuous frame filtering */
 		.opt = XAE_OPTION_PROMISC,
-		.reg = XAE_FMI_OFFSET,
-		.m_or = XAE_FMI_PM_MASK,
+		.reg = XAE_FMC_OFFSET,
+		.m_or = XAE_FMC_PM_MASK,
 	}, { /* Enable transmitter */
 		.opt = XAE_OPTION_TXEN,
 		.reg = XAE_TC_OFFSET,
@@ -118,34 +143,49 @@
 	{}
 };
 
-/**
- * axienet_dma_in32 - Memory mapped Axi DMA register read
- * @lp:		Pointer to axienet local structure
- * @reg:	Address offset from the base address of the Axi DMA core
- *
- * Return: The contents of the Axi DMA register
- *
- * This function returns the contents of the corresponding Axi DMA register.
- */
-static inline u32 axienet_dma_in32(struct axienet_local *lp, off_t reg)
-{
-	return ioread32(lp->dma_regs + reg);
-}
+/* Option table for setting up Axi Ethernet hardware options */
+static struct xxvenet_option xxvenet_options[] = {
+	{ /* Turn on FCS stripping on receive packets */
+		.opt = XAE_OPTION_FCS_STRIP,
+		.reg = XXV_RCW1_OFFSET,
+		.m_or = XXV_RCW1_FCS_MASK,
+	}, { /* Turn on FCS insertion on transmit packets */
+		.opt = XAE_OPTION_FCS_INSERT,
+		.reg = XXV_TC_OFFSET,
+		.m_or = XXV_TC_FCS_MASK,
+	}, { /* Enable transmitter */
+		.opt = XAE_OPTION_TXEN,
+		.reg = XXV_TC_OFFSET,
+		.m_or = XXV_TC_TX_MASK,
+	}, { /* Enable receiver */
+		.opt = XAE_OPTION_RXEN,
+		.reg = XXV_RCW1_OFFSET,
+		.m_or = XXV_RCW1_RX_MASK,
+	},
+	{}
+};
 
-/**
- * axienet_dma_out32 - Memory mapped Axi DMA register write.
- * @lp:		Pointer to axienet local structure
- * @reg:	Address offset from the base address of the Axi DMA core
- * @value:	Value to be written into the Axi DMA register
- *
- * This function writes the desired value into the corresponding Axi DMA
- * register.
- */
-static inline void axienet_dma_out32(struct axienet_local *lp,
-				     off_t reg, u32 value)
-{
-	iowrite32(value, lp->dma_regs + reg);
-}
+/* Option table for setting up MRMAC hardware options */
+static struct xxvenet_option mrmacenet_options[] = {
+	{ /* Turn on FCS stripping on receive packets */
+		.opt = XAE_OPTION_FCS_STRIP,
+		.reg = MRMAC_CONFIG_RX_OFFSET,
+		.m_or = MRMAC_RX_DEL_FCS_MASK,
+	}, { /* Turn on FCS insertion on transmit packets */
+		.opt = XAE_OPTION_FCS_INSERT,
+		.reg = MRMAC_CONFIG_TX_OFFSET,
+		.m_or = MRMAC_TX_INS_FCS_MASK,
+	}, { /* Enable transmitter */
+		.opt = XAE_OPTION_TXEN,
+		.reg = MRMAC_CONFIG_TX_OFFSET,
+		.m_or = MRMAC_TX_EN_MASK,
+	}, { /* Enable receiver */
+		.opt = XAE_OPTION_RXEN,
+		.reg = MRMAC_CONFIG_RX_OFFSET,
+		.m_or = MRMAC_RX_EN_MASK,
+	},
+	{}
+};
 
 /**
  * axienet_dma_bd_release - Release buffer descriptor rings
@@ -155,28 +195,22 @@
  * axienet_dma_bd_init. axienet_dma_bd_release is called when Axi Ethernet
  * driver stop api is called.
  */
-static void axienet_dma_bd_release(struct net_device *ndev)
+void axienet_dma_bd_release(struct net_device *ndev)
 {
 	int i;
 	struct axienet_local *lp = netdev_priv(ndev);
 
-	for (i = 0; i < lp->rx_bd_num; i++) {
-		dma_unmap_single(ndev->dev.parent, lp->rx_bd_v[i].phys,
-				 lp->max_frm_size, DMA_FROM_DEVICE);
-		dev_kfree_skb(lp->rx_bd_v[i].skb);
-	}
-
-	if (lp->rx_bd_v) {
-		dma_free_coherent(ndev->dev.parent,
-				  sizeof(*lp->rx_bd_v) * lp->rx_bd_num,
-				  lp->rx_bd_v,
-				  lp->rx_bd_p);
-	}
-	if (lp->tx_bd_v) {
-		dma_free_coherent(ndev->dev.parent,
-				  sizeof(*lp->tx_bd_v) * lp->tx_bd_num,
-				  lp->tx_bd_v,
-				  lp->tx_bd_p);
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+	for_each_tx_dma_queue(lp, i) {
+		axienet_mcdma_tx_bd_free(ndev, lp->dq[i]);
+	}
+#endif
+	for_each_rx_dma_queue(lp, i) {
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+		axienet_mcdma_rx_bd_free(ndev, lp->dq[i]);
+#else
+		axienet_bd_free(ndev, lp->dq[i]);
+#endif
 	}
 }
 
@@ -192,101 +226,29 @@
  */
 static int axienet_dma_bd_init(struct net_device *ndev)
 {
-	u32 cr;
-	int i;
-	struct sk_buff *skb;
+	int i, ret;
 	struct axienet_local *lp = netdev_priv(ndev);
 
-	/* Reset the indexes which are used for accessing the BDs */
-	lp->tx_bd_ci = 0;
-	lp->tx_bd_tail = 0;
-	lp->rx_bd_ci = 0;
-
-	/* Allocate the Tx and Rx buffer descriptors. */
-	lp->tx_bd_v = dma_alloc_coherent(ndev->dev.parent,
-					 sizeof(*lp->tx_bd_v) * lp->tx_bd_num,
-					 &lp->tx_bd_p, GFP_KERNEL);
-	if (!lp->tx_bd_v)
-		goto out;
-
-	lp->rx_bd_v = dma_alloc_coherent(ndev->dev.parent,
-					 sizeof(*lp->rx_bd_v) * lp->rx_bd_num,
-					 &lp->rx_bd_p, GFP_KERNEL);
-	if (!lp->rx_bd_v)
-		goto out;
-
-	for (i = 0; i < lp->tx_bd_num; i++) {
-		lp->tx_bd_v[i].next = lp->tx_bd_p +
-				      sizeof(*lp->tx_bd_v) *
-				      ((i + 1) % lp->tx_bd_num);
-	}
-
-	for (i = 0; i < lp->rx_bd_num; i++) {
-		lp->rx_bd_v[i].next = lp->rx_bd_p +
-				      sizeof(*lp->rx_bd_v) *
-				      ((i + 1) % lp->rx_bd_num);
-
-		skb = netdev_alloc_skb_ip_align(ndev, lp->max_frm_size);
-		if (!skb)
-			goto out;
-
-		lp->rx_bd_v[i].skb = skb;
-		lp->rx_bd_v[i].phys = dma_map_single(ndev->dev.parent,
-						     skb->data,
-						     lp->max_frm_size,
-						     DMA_FROM_DEVICE);
-		lp->rx_bd_v[i].cntrl = lp->max_frm_size;
-	}
-
-	/* Start updating the Rx channel control register */
-	cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
-	/* Update the interrupt coalesce count */
-	cr = ((cr & ~XAXIDMA_COALESCE_MASK) |
-	      ((lp->coalesce_count_rx) << XAXIDMA_COALESCE_SHIFT));
-	/* Update the delay timer count */
-	cr = ((cr & ~XAXIDMA_DELAY_MASK) |
-	      (XAXIDMA_DFT_RX_WAITBOUND << XAXIDMA_DELAY_SHIFT));
-	/* Enable coalesce, delay timer and error interrupts */
-	cr |= XAXIDMA_IRQ_ALL_MASK;
-	/* Write to the Rx channel control register */
-	axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, cr);
-
-	/* Start updating the Tx channel control register */
-	cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
-	/* Update the interrupt coalesce count */
-	cr = (((cr & ~XAXIDMA_COALESCE_MASK)) |
-	      ((lp->coalesce_count_tx) << XAXIDMA_COALESCE_SHIFT));
-	/* Update the delay timer count */
-	cr = (((cr & ~XAXIDMA_DELAY_MASK)) |
-	      (XAXIDMA_DFT_TX_WAITBOUND << XAXIDMA_DELAY_SHIFT));
-	/* Enable coalesce, delay timer and error interrupts */
-	cr |= XAXIDMA_IRQ_ALL_MASK;
-	/* Write to the Tx channel control register */
-	axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, cr);
-
-	/* Populate the tail pointer and bring the Rx Axi DMA engine out of
-	 * halted state. This will make the Rx side ready for reception.
-	 */
-	axienet_dma_out32(lp, XAXIDMA_RX_CDESC_OFFSET, lp->rx_bd_p);
-	cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
-	axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET,
-			  cr | XAXIDMA_CR_RUNSTOP_MASK);
-	axienet_dma_out32(lp, XAXIDMA_RX_TDESC_OFFSET, lp->rx_bd_p +
-			  (sizeof(*lp->rx_bd_v) * (lp->rx_bd_num - 1)));
-
-	/* Write to the RS (Run-stop) bit in the Tx channel control register.
-	 * Tx channel is now ready to run. But only after we write to the
-	 * tail pointer register that the Tx channel will start transmitting.
-	 */
-	axienet_dma_out32(lp, XAXIDMA_TX_CDESC_OFFSET, lp->tx_bd_p);
-	cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
-	axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET,
-			  cr | XAXIDMA_CR_RUNSTOP_MASK);
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+	for_each_tx_dma_queue(lp, i) {
+		ret = axienet_mcdma_tx_q_init(ndev, lp->dq[i]);
+		if (ret != 0)
+			break;
+	}
+#endif
+	for_each_rx_dma_queue(lp, i) {
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+		ret = axienet_mcdma_rx_q_init(ndev, lp->dq[i]);
+#else
+		ret = axienet_dma_q_init(ndev, lp->dq[i]);
+#endif
+		if (ret != 0) {
+			netdev_err(ndev, "%s: Failed to init DMA buf\n", __func__);
+			break;
+		}
+	}
 
-	return 0;
-out:
-	axienet_dma_bd_release(ndev);
-	return -ENOMEM;
+	return ret;
 }
 
 /**
@@ -297,16 +259,20 @@
  * This function is called to initialize the MAC address of the Axi Ethernet
  * core. It writes to the UAW0 and UAW1 registers of the core.
  */
-static void axienet_set_mac_address(struct net_device *ndev,
-				    const void *address)
+void axienet_set_mac_address(struct net_device *ndev,
+			     const void *address)
 {
 	struct axienet_local *lp = netdev_priv(ndev);
 
 	if (address)
-		memcpy(ndev->dev_addr, address, ETH_ALEN);
+		ether_addr_copy(ndev->dev_addr, address);
 	if (!is_valid_ether_addr(ndev->dev_addr))
 		eth_hw_addr_random(ndev);
 
+	if (lp->axienet_config->mactype != XAXIENET_1G &&
+	    lp->axienet_config->mactype != XAXIENET_2_5G)
+		return;
+
 	/* Set up unicast MAC address filter set its mac address */
 	axienet_iow(lp, XAE_UAW0_OFFSET,
 		    (ndev->dev_addr[0]) |
@@ -334,6 +300,7 @@
 static int netdev_set_mac_address(struct net_device *ndev, void *p)
 {
 	struct sockaddr *addr = p;
+
 	axienet_set_mac_address(ndev, addr->sa_data);
 	return 0;
 }
@@ -349,12 +316,15 @@
  * means whenever the multicast table entries need to be updated this
  * function gets called.
  */
-static void axienet_set_multicast_list(struct net_device *ndev)
+void axienet_set_multicast_list(struct net_device *ndev)
 {
 	int i;
 	u32 reg, af0reg, af1reg;
 	struct axienet_local *lp = netdev_priv(ndev);
 
+	if ((lp->axienet_config->mactype != XAXIENET_1G) || lp->eth_hasnobuf)
+		return;
+
 	if (ndev->flags & (IFF_ALLMULTI | IFF_PROMISC) ||
 	    netdev_mc_count(ndev) > XAE_MULTICAST_CAM_TABLE_NUM) {
 		/* We must make the kernel realize we had to move into
@@ -362,9 +332,9 @@
 		 * the flag is already set. If not we set it.
 		 */
 		ndev->flags |= IFF_PROMISC;
-		reg = axienet_ior(lp, XAE_FMI_OFFSET);
-		reg |= XAE_FMI_PM_MASK;
-		axienet_iow(lp, XAE_FMI_OFFSET, reg);
+		reg = axienet_ior(lp, XAE_FMC_OFFSET);
+		reg |= XAE_FMC_PM_MASK;
+		axienet_iow(lp, XAE_FMC_OFFSET, reg);
 		dev_info(&ndev->dev, "Promiscuous mode enabled.\n");
 	} else if (!netdev_mc_empty(ndev)) {
 		struct netdev_hw_addr *ha;
@@ -382,25 +352,25 @@
 			af1reg = (ha->addr[4]);
 			af1reg |= (ha->addr[5] << 8);
 
-			reg = axienet_ior(lp, XAE_FMI_OFFSET) & 0xFFFFFF00;
+			reg = axienet_ior(lp, XAE_FMC_OFFSET) & 0xFFFFFF00;
 			reg |= i;
 
-			axienet_iow(lp, XAE_FMI_OFFSET, reg);
+			axienet_iow(lp, XAE_FMC_OFFSET, reg);
 			axienet_iow(lp, XAE_AF0_OFFSET, af0reg);
 			axienet_iow(lp, XAE_AF1_OFFSET, af1reg);
 			i++;
 		}
 	} else {
-		reg = axienet_ior(lp, XAE_FMI_OFFSET);
-		reg &= ~XAE_FMI_PM_MASK;
+		reg = axienet_ior(lp, XAE_FMC_OFFSET);
+		reg &= ~XAE_FMC_PM_MASK;
 
-		axienet_iow(lp, XAE_FMI_OFFSET, reg);
+		axienet_iow(lp, XAE_FMC_OFFSET, reg);
 
 		for (i = 0; i < XAE_MULTICAST_CAM_TABLE_NUM; i++) {
-			reg = axienet_ior(lp, XAE_FMI_OFFSET) & 0xFFFFFF00;
+			reg = axienet_ior(lp, XAE_FMC_OFFSET) & 0xFFFFFF00;
 			reg |= i;
 
-			axienet_iow(lp, XAE_FMI_OFFSET, reg);
+			axienet_iow(lp, XAE_FMC_OFFSET, reg);
 			axienet_iow(lp, XAE_AF0_OFFSET, 0);
 			axienet_iow(lp, XAE_AF1_OFFSET, 0);
 		}
@@ -437,7 +407,115 @@
 	lp->options |= options;
 }
 
-static void __axienet_device_reset(struct axienet_local *lp)
+static void xxvenet_setoptions(struct net_device *ndev, u32 options)
+{
+	int reg;
+	struct axienet_local *lp = netdev_priv(ndev);
+	struct xxvenet_option *tp;
+
+	if (lp->axienet_config->mactype == XAXIENET_MRMAC)
+		tp = &mrmacenet_options[0];
+	else
+		tp = &xxvenet_options[0];
+
+	while (tp->opt) {
+		reg = ((axienet_ior(lp, tp->reg)) & ~(tp->m_or));
+		if (options & tp->opt)
+			reg |= tp->m_or;
+		axienet_iow(lp, tp->reg, reg);
+		tp++;
+	}
+
+	lp->options |= options;
+}
+
+static inline void axienet_mrmac_reset(struct axienet_local *lp)
+{
+	u32 val, reg;
+
+	val = axienet_ior(lp, MRMAC_RESET_OFFSET);
+	val |= (MRMAC_RX_SERDES_RST_MASK | MRMAC_TX_SERDES_RST_MASK |
+		MRMAC_RX_RST_MASK | MRMAC_TX_RST_MASK);
+	axienet_iow(lp, MRMAC_RESET_OFFSET, val);
+	mdelay(MRMAC_RESET_DELAY);
+
+	reg = axienet_ior(lp, MRMAC_MODE_OFFSET);
+	if (lp->mrmac_rate == SPEED_25000) {
+		reg &= ~MRMAC_CTL_RATE_CFG_MASK;
+		reg |= MRMAC_CTL_DATA_RATE_25G;
+		reg |= (MRMAC_CTL_AXIS_CFG_25G_IND << MRMAC_CTL_AXIS_CFG_SHIFT);
+		reg |= (MRMAC_CTL_SERDES_WIDTH_25G <<
+			MRMAC_CTL_SERDES_WIDTH_SHIFT);
+	} else {
+		reg &= ~MRMAC_CTL_RATE_CFG_MASK;
+		reg |= MRMAC_CTL_DATA_RATE_10G;
+		reg |= (MRMAC_CTL_AXIS_CFG_10G_IND << MRMAC_CTL_AXIS_CFG_SHIFT);
+		reg |= (MRMAC_CTL_SERDES_WIDTH_10G <<
+			MRMAC_CTL_SERDES_WIDTH_SHIFT);
+	}
+
+	/* For tick reg */
+	reg |= MRMAC_CTL_PM_TICK_MASK;
+	axienet_iow(lp, MRMAC_MODE_OFFSET, reg);
+
+	val = axienet_ior(lp, MRMAC_RESET_OFFSET);
+	val &= ~(MRMAC_RX_SERDES_RST_MASK | MRMAC_TX_SERDES_RST_MASK |
+		MRMAC_RX_RST_MASK | MRMAC_TX_RST_MASK);
+	axienet_iow(lp, MRMAC_RESET_OFFSET, val);
+}
+
+static inline int axienet_mrmac_gt_reset(struct net_device *ndev)
+{
+	struct axienet_local *lp = netdev_priv(ndev);
+	u32 err, val;
+	int i;
+
+	if (mrmac_pll_rst == 0) {
+		/* PLL reset for all lanes */
+		iowrite32(MRMAC_GT_PLL_RST_MASK, lp->gt_pll);
+
+		for (i = 0; i < MRMAC_MAX_GT_LANES; i++) {
+			iowrite32(MRMAC_GT_RST_ALL_MASK, (lp->gt_ctrl +
+				  (MRMAC_GT_LANE_OFFSET * i) +
+				  MRMAC_GT_CTRL_OFFSET));
+			mdelay(MRMAC_RESET_DELAY);
+			iowrite32(0, (lp->gt_ctrl + (MRMAC_GT_LANE_OFFSET * i) +
+				      MRMAC_GT_CTRL_OFFSET));
+		}
+
+		/* Wait for PLL lock with timeout */
+		err = readl_poll_timeout(lp->gt_pll + MRMAC_GT_PLL_STS_OFFSET,
+					 val, (val & MRMAC_GT_PLL_DONE_MASK),
+					 10, DELAY_OF_ONE_MILLISEC);
+		if (err) {
+			netdev_err(ndev, "MRMAC PLL lock not complete! Cross-check the MAC ref clock configuration\n");
+			return -ENODEV;
+		}
+		iowrite32(0, lp->gt_pll);
+		mrmac_pll_rst = 1;
+	}
+
+	if (lp->mrmac_rate == SPEED_25000)
+		iowrite32(MRMAC_GT_25G_MASK, (lp->gt_ctrl +
+			  MRMAC_GT_LANE_OFFSET * lp->gt_lane +
+			  MRMAC_GT_RATE_OFFSET));
+	else
+		iowrite32(MRMAC_GT_10G_MASK, (lp->gt_ctrl +
+			  MRMAC_GT_LANE_OFFSET * lp->gt_lane +
+			  MRMAC_GT_RATE_OFFSET));
+
+	iowrite32(MRMAC_GT_RST_RX_MASK | MRMAC_GT_RST_TX_MASK,
+		  (lp->gt_ctrl + MRMAC_GT_LANE_OFFSET * lp->gt_lane +
+		  MRMAC_GT_CTRL_OFFSET));
+	mdelay(MRMAC_RESET_DELAY);
+	iowrite32(0, (lp->gt_ctrl + MRMAC_GT_LANE_OFFSET * lp->gt_lane +
+		  MRMAC_GT_CTRL_OFFSET));
+	mdelay(MRMAC_RESET_DELAY);
+
+	return 0;
+}
+
+void __axienet_device_reset(struct axienet_dma_q *q)
 {
 	u32 timeout;
 	/* Reset Axi DMA. This would reset Axi Ethernet core as well. The reset
@@ -447,13 +525,13 @@
 	 * Note that even though both TX and RX have their own reset register,
 	 * they both reset the entire DMA core, so only one needs to be used.
 	 */
-	axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, XAXIDMA_CR_RESET_MASK);
+	axienet_dma_out32(q, XAXIDMA_TX_CR_OFFSET, XAXIDMA_CR_RESET_MASK);
 	timeout = DELAY_OF_ONE_MILLISEC;
-	while (axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET) &
+	while (axienet_dma_in32(q, XAXIDMA_TX_CR_OFFSET) &
 				XAXIDMA_CR_RESET_MASK) {
 		udelay(1);
 		if (--timeout == 0) {
-			netdev_err(lp->ndev, "%s: DMA reset timeout!\n",
+			netdev_err(q->lp->ndev, "%s: DMA reset timeout!\n",
 				   __func__);
 			break;
 		}
@@ -475,55 +553,333 @@
 {
 	u32 axienet_status;
 	struct axienet_local *lp = netdev_priv(ndev);
+	u32 err, val;
+	struct axienet_dma_q *q;
+	u32 i;
+
+	if (lp->axienet_config->mactype == XAXIENET_10G_25G) {
+		/* Reset the XXV MAC */
+		val = axienet_ior(lp, XXV_GT_RESET_OFFSET);
+		val |= XXV_GT_RESET_MASK;
+		axienet_iow(lp, XXV_GT_RESET_OFFSET, val);
+		/* Wait for 1ms for GT reset to complete as per spec */
+		mdelay(1);
+		val = axienet_ior(lp, XXV_GT_RESET_OFFSET);
+		val &= ~XXV_GT_RESET_MASK;
+		axienet_iow(lp, XXV_GT_RESET_OFFSET, val);
+	}
+
+	if (lp->axienet_config->mactype == XAXIENET_MRMAC) {
+		/* Reset MRMAC */
+		axienet_mrmac_reset(lp);
 
-	__axienet_device_reset(lp);
+		if (axienet_mrmac_gt_reset(ndev))
+			return;
+	}
+
+	if (!lp->is_tsn || lp->temac_no == XAE_TEMAC1) {
+		for_each_rx_dma_queue(lp, i) {
+			q = lp->dq[i];
+			__axienet_device_reset(q);
+#ifndef CONFIG_AXIENET_HAS_MCDMA
+			__axienet_device_reset(q);
+#endif
+		}
+	}
 
 	lp->max_frm_size = XAE_MAX_VLAN_FRAME_SIZE;
-	lp->options |= XAE_OPTION_VLAN;
-	lp->options &= (~XAE_OPTION_JUMBO);
+	if (lp->axienet_config->mactype != XAXIENET_10G_25G &&
+	    lp->axienet_config->mactype != XAXIENET_MRMAC) {
+		lp->options |= XAE_OPTION_VLAN;
+		lp->options &= (~XAE_OPTION_JUMBO);
+	}
 
-	if ((ndev->mtu > XAE_MTU) &&
-		(ndev->mtu <= XAE_JUMBO_MTU)) {
+	if ((ndev->mtu > XAE_MTU) && (ndev->mtu <= XAE_JUMBO_MTU)) {
 		lp->max_frm_size = ndev->mtu + VLAN_ETH_HLEN +
 					XAE_TRL_SIZE;
-
-		if (lp->max_frm_size <= lp->rxmem)
+		if (lp->max_frm_size <= lp->rxmem &&
+		    (lp->axienet_config->mactype != XAXIENET_10G_25G &&
+		     lp->axienet_config->mactype != XAXIENET_MRMAC))
 			lp->options |= XAE_OPTION_JUMBO;
 	}
 
-	if (axienet_dma_bd_init(ndev)) {
-		netdev_err(ndev, "%s: descriptor allocation failed\n",
-			   __func__);
+	if (!lp->is_tsn || lp->temac_no == XAE_TEMAC1) {
+		if (axienet_dma_bd_init(ndev)) {
+			netdev_err(ndev, "%s: descriptor allocation failed\n",
+				   __func__);
+		}
 	}
 
-	axienet_status = axienet_ior(lp, XAE_RCW1_OFFSET);
-	axienet_status &= ~XAE_RCW1_RX_MASK;
-	axienet_iow(lp, XAE_RCW1_OFFSET, axienet_status);
-
-	axienet_status = axienet_ior(lp, XAE_IP_OFFSET);
-	if (axienet_status & XAE_INT_RXRJECT_MASK)
-		axienet_iow(lp, XAE_IS_OFFSET, XAE_INT_RXRJECT_MASK);
-	axienet_iow(lp, XAE_IE_OFFSET, lp->eth_irq > 0 ?
-		    XAE_INT_RECV_ERROR_MASK : 0);
+	if (lp->axienet_config->mactype != XAXIENET_10G_25G &&
+	    lp->axienet_config->mactype != XAXIENET_MRMAC) {
+		axienet_status = axienet_ior(lp, XAE_RCW1_OFFSET);
+		axienet_status &= ~XAE_RCW1_RX_MASK;
+		axienet_iow(lp, XAE_RCW1_OFFSET, axienet_status);
+	}
 
-	axienet_iow(lp, XAE_FCC_OFFSET, XAE_FCC_FCRX_MASK);
+	if (lp->axienet_config->mactype == XAXIENET_10G_25G) {
+		/* Check for block lock bit got set or not
+		 * This ensures that 10G ethernet IP
+		 * is functioning normally or not.
+		 */
+		err = readl_poll_timeout(lp->regs + XXV_STATRX_BLKLCK_OFFSET,
+					 val, (val & XXV_RX_BLKLCK_MASK),
+					 10, DELAY_OF_ONE_MILLISEC);
+		if (err) {
+			netdev_err(ndev, "XXV MAC block lock not complete! Cross-check the MAC ref clock configuration\n");
+		}
+#ifdef CONFIG_XILINX_AXI_EMAC_HWTSTAMP
+		if (!lp->is_tsn) {
+			axienet_rxts_iow(lp, XAXIFIFO_TXTS_RDFR,
+					 XAXIFIFO_TXTS_RESET_MASK);
+			axienet_rxts_iow(lp, XAXIFIFO_TXTS_SRR,
+					 XAXIFIFO_TXTS_RESET_MASK);
+			axienet_txts_iow(lp, XAXIFIFO_TXTS_RDFR,
+					 XAXIFIFO_TXTS_RESET_MASK);
+			axienet_txts_iow(lp, XAXIFIFO_TXTS_SRR,
+					 XAXIFIFO_TXTS_RESET_MASK);
+		}
+#endif
+	}
+
+#ifdef CONFIG_XILINX_AXI_EMAC_HWTSTAMP
+	if (lp->axienet_config->mactype == XAXIENET_MRMAC) {
+		axienet_rxts_iow(lp, XAXIFIFO_TXTS_RDFR,
+				 XAXIFIFO_TXTS_RESET_MASK);
+		axienet_rxts_iow(lp, XAXIFIFO_TXTS_SRR,
+				 XAXIFIFO_TXTS_RESET_MASK);
+		axienet_txts_iow(lp, XAXIFIFO_TXTS_RDFR,
+				 XAXIFIFO_TXTS_RESET_MASK);
+		axienet_txts_iow(lp, XAXIFIFO_TXTS_SRR,
+				 XAXIFIFO_TXTS_RESET_MASK);
+	}
+#endif
+
+	if ((lp->axienet_config->mactype == XAXIENET_1G) &&
+	    !lp->eth_hasnobuf) {
+		axienet_status = axienet_ior(lp, XAE_IP_OFFSET);
+		if (axienet_status & XAE_INT_RXRJECT_MASK)
+			axienet_iow(lp, XAE_IS_OFFSET, XAE_INT_RXRJECT_MASK);
+		/* Enable receive erros */
+		axienet_iow(lp, XAE_IE_OFFSET, lp->eth_irq > 0 ?
+			    XAE_INT_RECV_ERROR_MASK : 0);
+	}
+
+	if (lp->axienet_config->mactype == XAXIENET_10G_25G ||
+	    lp->axienet_config->mactype == XAXIENET_MRMAC) {
+		lp->options |= XAE_OPTION_FCS_STRIP;
+		lp->options |= XAE_OPTION_FCS_INSERT;
+	} else {
+		axienet_iow(lp, XAE_FCC_OFFSET, XAE_FCC_FCRX_MASK);
+	}
+	lp->axienet_config->setoptions(ndev, lp->options &
+				       ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN));
 
-	/* Sync default options with HW but leave receiver and
-	 * transmitter disabled.
-	 */
-	axienet_setoptions(ndev, lp->options &
-			   ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN));
 	axienet_set_mac_address(ndev, NULL);
 	axienet_set_multicast_list(ndev);
-	axienet_setoptions(ndev, lp->options);
+	lp->axienet_config->setoptions(ndev, lp->options);
 
 	netif_trans_update(ndev);
 }
 
 /**
+ * axienet_adjust_link - Adjust the PHY link speed/duplex.
+ * @ndev:	Pointer to the net_device structure
+ *
+ * This function is called to change the speed and duplex setting after
+ * auto negotiation is done by the PHY. This is the function that gets
+ * registered with the PHY interface through the "of_phy_connect" call.
+ */
+static void axienet_adjust_link(struct net_device *ndev)
+{
+	u32 emmc_reg;
+	u32 link_state;
+	u32 setspeed = 1;
+	struct axienet_local *lp = netdev_priv(ndev);
+	struct phy_device *phy = ndev->phydev;
+
+	link_state = phy->speed | (phy->duplex << 1) | phy->link;
+	if (lp->last_link != link_state) {
+		if ((phy->speed == SPEED_10) || (phy->speed == SPEED_100)) {
+			if (lp->phy_mode == PHY_INTERFACE_MODE_1000BASEX)
+				setspeed = 0;
+		} else {
+			if ((phy->speed == SPEED_1000) &&
+			    (lp->phy_mode == PHY_INTERFACE_MODE_MII))
+				setspeed = 0;
+		}
+
+		if (setspeed == 1) {
+			emmc_reg = axienet_ior(lp, XAE_EMMC_OFFSET);
+			emmc_reg &= ~XAE_EMMC_LINKSPEED_MASK;
+
+			switch (phy->speed) {
+			case SPEED_2500:
+				emmc_reg |= XAE_EMMC_LINKSPD_2500;
+				break;
+			case SPEED_1000:
+				emmc_reg |= XAE_EMMC_LINKSPD_1000;
+				break;
+			case SPEED_100:
+				emmc_reg |= XAE_EMMC_LINKSPD_100;
+				break;
+			case SPEED_10:
+				emmc_reg |= XAE_EMMC_LINKSPD_10;
+				break;
+			default:
+				dev_err(&ndev->dev, "Speed other than 10, 100 ");
+				dev_err(&ndev->dev, "or 1Gbps is not supported\n");
+				break;
+			}
+
+			axienet_iow(lp, XAE_EMMC_OFFSET, emmc_reg);
+			phy_print_status(phy);
+		} else {
+			netdev_err(ndev,
+				   "Error setting Axi Ethernet mac speed\n");
+		}
+
+		lp->last_link = link_state;
+	}
+}
+
+#ifdef CONFIG_XILINX_AXI_EMAC_HWTSTAMP
+/**
+ * axienet_tx_hwtstamp - Read tx timestamp from hw and update it to the skbuff
+ * @lp:		Pointer to axienet local structure
+ * @cur_p:	Pointer to the axi_dma/axi_mcdma current bd
+ *
+ * Return:	None.
+ */
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+void axienet_tx_hwtstamp(struct axienet_local *lp,
+			 struct aximcdma_bd *cur_p)
+#else
+void axienet_tx_hwtstamp(struct axienet_local *lp,
+			 struct axidma_bd *cur_p)
+#endif
+{
+	u32 sec = 0, nsec = 0, val;
+	u64 time64;
+	int err = 0;
+	u32 count, len = lp->axienet_config->tx_ptplen;
+	struct skb_shared_hwtstamps *shhwtstamps =
+		skb_hwtstamps((struct sk_buff *)cur_p->ptp_tx_skb);
+
+	val = axienet_txts_ior(lp, XAXIFIFO_TXTS_ISR);
+	if (unlikely(!(val & XAXIFIFO_TXTS_INT_RC_MASK)))
+		dev_info(lp->dev, "Did't get FIFO tx interrupt %d\n", val);
+
+	/* If FIFO is configured in cut through Mode we will get Rx complete
+	 * interrupt even one byte is there in the fifo wait for the full packet
+	 */
+	err = readl_poll_timeout_atomic(lp->tx_ts_regs + XAXIFIFO_TXTS_RLR, val,
+					((val & XAXIFIFO_TXTS_RXFD_MASK) >=
+					len), 0, 1000000);
+	if (err)
+		netdev_err(lp->ndev, "%s: Didn't get the full timestamp packet",
+			   __func__);
+
+	nsec = axienet_txts_ior(lp, XAXIFIFO_TXTS_RXFD);
+	sec  = axienet_txts_ior(lp, XAXIFIFO_TXTS_RXFD);
+	val = axienet_txts_ior(lp, XAXIFIFO_TXTS_RXFD);
+	val = ((val & XAXIFIFO_TXTS_TAG_MASK) >> XAXIFIFO_TXTS_TAG_SHIFT);
+	dev_dbg(lp->dev, "tx_stamp:[%04x] %04x %u %9u\n",
+		cur_p->ptp_tx_ts_tag, val, sec, nsec);
+
+	if (val != cur_p->ptp_tx_ts_tag) {
+		count = axienet_txts_ior(lp, XAXIFIFO_TXTS_RFO);
+		while (count) {
+			nsec = axienet_txts_ior(lp, XAXIFIFO_TXTS_RXFD);
+			sec  = axienet_txts_ior(lp, XAXIFIFO_TXTS_RXFD);
+			val = axienet_txts_ior(lp, XAXIFIFO_TXTS_RXFD);
+			val = ((val & XAXIFIFO_TXTS_TAG_MASK) >>
+				XAXIFIFO_TXTS_TAG_SHIFT);
+
+			dev_dbg(lp->dev, "tx_stamp:[%04x] %04x %u %9u\n",
+				cur_p->ptp_tx_ts_tag, val, sec, nsec);
+			if (val == cur_p->ptp_tx_ts_tag)
+				break;
+			count = axienet_txts_ior(lp, XAXIFIFO_TXTS_RFO);
+		}
+		if (val != cur_p->ptp_tx_ts_tag) {
+			dev_info(lp->dev, "Mismatching 2-step tag. Got %x",
+				 val);
+			dev_info(lp->dev, "Expected %x\n",
+				 cur_p->ptp_tx_ts_tag);
+		}
+	}
+
+	if (lp->axienet_config->mactype != XAXIENET_10G_25G &&
+	    lp->axienet_config->mactype != XAXIENET_MRMAC)
+		val = axienet_txts_ior(lp, XAXIFIFO_TXTS_RXFD);
+
+	time64 = sec * NS_PER_SEC + nsec;
+	memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps));
+	shhwtstamps->hwtstamp = ns_to_ktime(time64);
+	if (lp->axienet_config->mactype != XAXIENET_10G_25G &&
+	    lp->axienet_config->mactype != XAXIENET_MRMAC)
+		skb_pull((struct sk_buff *)cur_p->ptp_tx_skb,
+			 AXIENET_TS_HEADER_LEN);
+
+	skb_tstamp_tx((struct sk_buff *)cur_p->ptp_tx_skb, shhwtstamps);
+	dev_kfree_skb_any((struct sk_buff *)cur_p->ptp_tx_skb);
+	cur_p->ptp_tx_skb = 0;
+}
+
+/**
+ * axienet_rx_hwtstamp - Read rx timestamp from hw and update it to the skbuff
+ * @lp:		Pointer to axienet local structure
+ * @skb:	Pointer to the sk_buff structure
+ *
+ * Return:	None.
+ */
+static void axienet_rx_hwtstamp(struct axienet_local *lp,
+				struct sk_buff *skb)
+{
+	u32 sec = 0, nsec = 0, val;
+	u64 time64;
+	int err = 0;
+	struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
+
+	val = axienet_rxts_ior(lp, XAXIFIFO_TXTS_ISR);
+	if (unlikely(!(val & XAXIFIFO_TXTS_INT_RC_MASK))) {
+		dev_info(lp->dev, "Did't get FIFO rx interrupt %d\n", val);
+		return;
+	}
+
+	val = axienet_rxts_ior(lp, XAXIFIFO_TXTS_RFO);
+	if (!val)
+		return;
+
+	/* If FIFO is configured in cut through Mode we will get Rx complete
+	 * interrupt even one byte is there in the fifo wait for the full packet
+	 */
+	err = readl_poll_timeout_atomic(lp->rx_ts_regs + XAXIFIFO_TXTS_RLR, val,
+					((val & XAXIFIFO_TXTS_RXFD_MASK) >= 12),
+					0, 1000000);
+	if (err) {
+		netdev_err(lp->ndev, "%s: Didn't get the full timestamp packet",
+			   __func__);
+		return;
+	}
+
+	nsec = axienet_rxts_ior(lp, XAXIFIFO_TXTS_RXFD);
+	sec  = axienet_rxts_ior(lp, XAXIFIFO_TXTS_RXFD);
+	val = axienet_rxts_ior(lp, XAXIFIFO_TXTS_RXFD);
+
+	if (lp->tstamp_config.rx_filter == HWTSTAMP_FILTER_ALL) {
+		time64 = sec * NS_PER_SEC + nsec;
+		shhwtstamps->hwtstamp = ns_to_ktime(time64);
+	}
+}
+#endif
+
+/**
  * axienet_start_xmit_done - Invoked once a transmit is completed by the
  * Axi DMA Tx channel.
  * @ndev:	Pointer to the net_device structure
+ * @q:		Pointer to DMA queue structure
  *
  * This function is invoked from the Axi DMA Tx isr to notify the completion
  * of transmit operation. It clears fields in the corresponding Tx BDs and
@@ -531,51 +887,88 @@
  * buffer. It finally invokes "netif_wake_queue" to restart transmission if
  * required.
  */
-static void axienet_start_xmit_done(struct net_device *ndev)
+void axienet_start_xmit_done(struct net_device *ndev,
+			     struct axienet_dma_q *q)
 {
 	u32 size = 0;
 	u32 packets = 0;
 	struct axienet_local *lp = netdev_priv(ndev);
+
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+	struct aximcdma_bd *cur_p;
+#else
 	struct axidma_bd *cur_p;
+#endif
 	unsigned int status = 0;
 
-	cur_p = &lp->tx_bd_v[lp->tx_bd_ci];
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+	cur_p = &q->txq_bd_v[q->tx_bd_ci];
+	status = cur_p->sband_stats;
+#else
+	cur_p = &q->tx_bd_v[q->tx_bd_ci];
 	status = cur_p->status;
+#endif
 	while (status & XAXIDMA_BD_STS_COMPLETE_MASK) {
-		dma_unmap_single(ndev->dev.parent, cur_p->phys,
-				(cur_p->cntrl & XAXIDMA_BD_CTRL_LENGTH_MASK),
-				DMA_TO_DEVICE);
-		if (cur_p->skb)
-			dev_consume_skb_irq(cur_p->skb);
+#ifdef CONFIG_XILINX_AXI_EMAC_HWTSTAMP
+		if (cur_p->ptp_tx_skb)
+			axienet_tx_hwtstamp(lp, cur_p);
+#endif
+		if (cur_p->tx_desc_mapping == DESC_DMA_MAP_PAGE)
+			dma_unmap_page(ndev->dev.parent, cur_p->phys,
+				       cur_p->cntrl &
+				       XAXIDMA_BD_CTRL_LENGTH_MASK,
+				       DMA_TO_DEVICE);
+		else
+			dma_unmap_single(ndev->dev.parent, cur_p->phys,
+					 cur_p->cntrl &
+					 XAXIDMA_BD_CTRL_LENGTH_MASK,
+					 DMA_TO_DEVICE);
+		if (cur_p->tx_skb)
+			dev_kfree_skb_irq((struct sk_buff *)cur_p->tx_skb);
 		/*cur_p->phys = 0;*/
 		cur_p->app0 = 0;
 		cur_p->app1 = 0;
 		cur_p->app2 = 0;
 		cur_p->app4 = 0;
 		cur_p->status = 0;
-		cur_p->skb = NULL;
+		cur_p->tx_skb = 0;
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+		cur_p->sband_stats = 0;
+#endif
 
 		size += status & XAXIDMA_BD_STS_ACTUAL_LEN_MASK;
 		packets++;
 
-		if (++lp->tx_bd_ci >= lp->tx_bd_num)
-			lp->tx_bd_ci = 0;
-		cur_p = &lp->tx_bd_v[lp->tx_bd_ci];
+		if (++q->tx_bd_ci >= lp->tx_bd_num)
+			q->tx_bd_ci = 0;
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+		cur_p = &q->txq_bd_v[q->tx_bd_ci];
+		status = cur_p->sband_stats;
+#else
+		cur_p = &q->tx_bd_v[q->tx_bd_ci];
 		status = cur_p->status;
+#endif
 	}
 
 	ndev->stats.tx_packets += packets;
 	ndev->stats.tx_bytes += size;
+	q->tx_packets += packets;
+	q->tx_bytes += size;
 
 	/* Matches barrier in axienet_start_xmit */
 	smp_mb();
 
-	netif_wake_queue(ndev);
+	/* Fixme: With the existing multiqueue implementation
+	 * in the driver it is difficult to get the exact queue info.
+	 * We should wake only the particular queue
+	 * instead of waking all ndev queues.
+	 */
+	netif_tx_wake_all_queues(ndev);
 }
 
 /**
  * axienet_check_tx_bd_space - Checks if a BD/group of BDs are currently busy
- * @lp:		Pointer to the axienet_local structure
+ * @q:		Pointer to DMA queue structure
  * @num_frag:	The number of BDs to check for
  *
  * Return: 0, on success
@@ -586,47 +979,307 @@
  * transmission. If the BD or any of the BDs are not free the function
  * returns a busy status. This is invoked from axienet_start_xmit.
  */
-static inline int axienet_check_tx_bd_space(struct axienet_local *lp,
+static inline int axienet_check_tx_bd_space(struct axienet_dma_q *q,
 					    int num_frag)
 {
+	struct axienet_local *lp = q->lp;
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+	struct aximcdma_bd *cur_p;
+
+	if (CIRC_SPACE(q->tx_bd_tail, q->tx_bd_ci, lp->tx_bd_num) < (num_frag + 1))
+		return NETDEV_TX_BUSY;
+
+	cur_p = &q->txq_bd_v[(q->tx_bd_tail + num_frag) % lp->tx_bd_num];
+	if (cur_p->sband_stats & XMCDMA_BD_STS_ALL_MASK)
+		return NETDEV_TX_BUSY;
+#else
 	struct axidma_bd *cur_p;
-	cur_p = &lp->tx_bd_v[(lp->tx_bd_tail + num_frag) % lp->tx_bd_num];
+
+	if (CIRC_SPACE(q->tx_bd_tail, q->tx_bd_ci, lp->tx_bd_num) < (num_frag + 1))
+		return NETDEV_TX_BUSY;
+
+	cur_p = &q->tx_bd_v[(q->tx_bd_tail + num_frag) % lp->tx_bd_num];
 	if (cur_p->status & XAXIDMA_BD_STS_ALL_MASK)
 		return NETDEV_TX_BUSY;
+#endif
 	return 0;
 }
 
+#ifdef CONFIG_XILINX_AXI_EMAC_HWTSTAMP
 /**
- * axienet_start_xmit - Starts the transmission.
- * @skb:	sk_buff pointer that contains data to be Txed.
- * @ndev:	Pointer to net_device structure.
- *
- * Return: NETDEV_TX_OK, on success
- *	    NETDEV_TX_BUSY, if any of the descriptors are not free
+ * axienet_create_tsheader - Create timestamp header for tx
+ * @q:		Pointer to DMA queue structure
+ * @buf:	Pointer to the buf to copy timestamp header
+ * @msg_type:	PTP message type
  *
- * This function is invoked from upper layers to initiate transmission. The
- * function uses the next available free BDs and populates their fields to
- * start the transmission. Additionally if checksum offloading is supported,
- * it populates AXI Stream Control fields with appropriate values.
+ * Return: 0, on success
+ *	    NETDEV_TX_BUSY, if timestamp FIFO has no vacancy
  */
-static netdev_tx_t
-axienet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+static int axienet_create_tsheader(u8 *buf, u8 msg_type,
+				   struct axienet_dma_q *q)
+{
+	struct axienet_local *lp = q->lp;
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+	struct aximcdma_bd *cur_p;
+#else
+	struct axidma_bd *cur_p;
+#endif
+	u64 val;
+	u32 tmp;
+	u32 flags;
+
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+	cur_p = &q->txq_bd_v[q->tx_bd_tail];
+#else
+	cur_p = &q->tx_bd_v[q->tx_bd_tail];
+#endif
+
+	if (msg_type == TX_TS_OP_NOOP) {
+		buf[0] = TX_TS_OP_NOOP;
+	} else if (msg_type == TX_TS_OP_ONESTEP) {
+		buf[0] = TX_TS_OP_ONESTEP;
+		buf[1] = TX_TS_CSUM_UPDATE;
+		buf[4] = TX_PTP_TS_OFFSET;
+		buf[6] = TX_PTP_CSUM_OFFSET;
+	} else {
+		buf[0] = TX_TS_OP_TWOSTEP;
+		buf[2] = cur_p->ptp_tx_ts_tag & 0xFF;
+		buf[3] = (cur_p->ptp_tx_ts_tag >> 8) & 0xFF;
+	}
+
+	if (lp->axienet_config->mactype == XAXIENET_1G ||
+	    lp->axienet_config->mactype == XAXIENET_2_5G) {
+		memcpy(&val, buf, AXIENET_TS_HEADER_LEN);
+		swab64s(&val);
+		memcpy(buf, &val, AXIENET_TS_HEADER_LEN);
+	} else if (lp->axienet_config->mactype == XAXIENET_10G_25G ||
+		   lp->axienet_config->mactype == XAXIENET_MRMAC) {
+		memcpy(&tmp, buf, XXVENET_TS_HEADER_LEN);
+		/* Check for Transmit Data FIFO Vacancy */
+		spin_lock_irqsave(&lp->ptp_tx_lock, flags);
+		if (!axienet_txts_ior(lp, XAXIFIFO_TXTS_TDFV)) {
+			spin_unlock_irqrestore(&lp->ptp_tx_lock, flags);
+			return NETDEV_TX_BUSY;
+		}
+		axienet_txts_iow(lp, XAXIFIFO_TXTS_TXFD, tmp);
+		axienet_txts_iow(lp, XAXIFIFO_TXTS_TLR,
+				 XXVENET_TS_HEADER_LEN);
+		spin_unlock_irqrestore(&lp->ptp_tx_lock, flags);
+	}
+
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_XILINX_TSN
+static inline u16 get_tsn_queue(u8 pcp, u16 num_tc)
+{
+	u16 queue = 0;
+
+	/* For 3 queue system, RE queue is 1 and ST queue is 2
+	 * For 2 queue system, ST queue is 1. BE queue is always 0
+	 */
+	if (pcp == 4) {
+		if (num_tc == 2)
+			queue = 1;
+		else
+			queue = 2;
+	} else if ((num_tc == 3) && (pcp == 2 || pcp == 3)) {
+		queue = 1;
+	}
+
+	return queue;
+}
+
+static inline u16 tsn_queue_mapping(const struct sk_buff *skb, u16 num_tc)
+{
+	int queue = 0;
+	u16 vlan_tci;
+	u8 pcp;
+
+	struct ethhdr *hdr = (struct ethhdr *)skb->data;
+	u16 ether_type = ntohs(hdr->h_proto);
+
+	if (unlikely(ether_type == ETH_P_8021Q)) {
+		struct vlan_ethhdr *vhdr = (struct vlan_ethhdr *)skb->data;
+
+		/* ether_type = ntohs(vhdr->h_vlan_encapsulated_proto); */
+
+		vlan_tci = ntohs(vhdr->h_vlan_TCI);
+
+		pcp = (vlan_tci & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT;
+		pr_debug("vlan_tci: %x\n", vlan_tci);
+		pr_debug("pcp: %d\n", pcp);
+
+		queue = get_tsn_queue(pcp, num_tc);
+	}
+	pr_debug("selected queue: %d\n", queue);
+	return queue;
+}
+#endif
+
+#ifdef CONFIG_XILINX_AXI_EMAC_HWTSTAMP
+static int axienet_skb_tstsmp(struct sk_buff **__skb, struct axienet_dma_q *q,
+			      struct net_device *ndev)
+{
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+	struct aximcdma_bd *cur_p;
+#else
+	struct axidma_bd *cur_p;
+#endif
+	struct axienet_local *lp = netdev_priv(ndev);
+	struct sk_buff *old_skb = *__skb;
+	struct sk_buff *skb = *__skb;
+
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+	cur_p = &q->txq_bd_v[q->tx_bd_tail];
+#else
+	cur_p = &q->tx_bd_v[q->tx_bd_tail];
+#endif
+
+	if ((((lp->tstamp_config.tx_type == HWTSTAMP_TX_ONESTEP_SYNC) ||
+	      (lp->tstamp_config.tx_type == HWTSTAMP_TX_ON)) ||
+	       lp->eth_hasptp) && (lp->axienet_config->mactype !=
+	       XAXIENET_10G_25G) &&
+	       (lp->axienet_config->mactype != XAXIENET_MRMAC)) {
+		u8 *tmp;
+		struct sk_buff *new_skb;
+
+		if (skb_headroom(old_skb) < AXIENET_TS_HEADER_LEN) {
+			new_skb =
+			skb_realloc_headroom(old_skb,
+					     AXIENET_TS_HEADER_LEN);
+			if (!new_skb) {
+				dev_err(&ndev->dev, "failed to allocate new socket buffer\n");
+				dev_kfree_skb_any(old_skb);
+				return NETDEV_TX_BUSY;
+			}
+
+			/*  Transfer the ownership to the
+			 *  new socket buffer if required
+			 */
+			if (old_skb->sk)
+				skb_set_owner_w(new_skb, old_skb->sk);
+			dev_kfree_skb_any(old_skb);
+			*__skb = new_skb;
+			skb = new_skb;
+		}
+
+		tmp = skb_push(skb, AXIENET_TS_HEADER_LEN);
+		memset(tmp, 0, AXIENET_TS_HEADER_LEN);
+		cur_p->ptp_tx_ts_tag++;
+
+		if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
+			if (lp->tstamp_config.tx_type ==
+				HWTSTAMP_TX_ONESTEP_SYNC) {
+				axienet_create_tsheader(tmp,
+							TX_TS_OP_ONESTEP
+							, q);
+			} else {
+				axienet_create_tsheader(tmp,
+							TX_TS_OP_TWOSTEP
+							, q);
+				skb_shinfo(skb)->tx_flags
+						|= SKBTX_IN_PROGRESS;
+				cur_p->ptp_tx_skb =
+					(unsigned long)skb_get(skb);
+			}
+		}
+	} else if ((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
+			  (lp->axienet_config->mactype == XAXIENET_10G_25G ||
+			   lp->axienet_config->mactype == XAXIENET_MRMAC)) {
+			cur_p->ptp_tx_ts_tag = prandom_u32_max(XAXIFIFO_TXTS_TAG_MAX) + 1;
+			dev_dbg(lp->dev, "tx_tag:[%04x]\n",
+				cur_p->ptp_tx_ts_tag);
+			if (lp->tstamp_config.tx_type == HWTSTAMP_TX_ONESTEP_SYNC) {
+				if (axienet_create_tsheader(lp->tx_ptpheader,
+							    TX_TS_OP_ONESTEP,
+							    q))
+					return NETDEV_TX_BUSY;
+			} else {
+				if (axienet_create_tsheader(lp->tx_ptpheader,
+							    TX_TS_OP_TWOSTEP,
+							    q))
+					return NETDEV_TX_BUSY;
+				skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+				cur_p->ptp_tx_skb = (phys_addr_t)skb_get(skb);
+			}
+	} else if (lp->axienet_config->mactype == XAXIENET_10G_25G ||
+		   lp->axienet_config->mactype == XAXIENET_MRMAC) {
+			dev_dbg(lp->dev, "tx_tag:NOOP\n");
+			if (axienet_create_tsheader(lp->tx_ptpheader,
+						    TX_TS_OP_NOOP, q))
+				return NETDEV_TX_BUSY;
+	}
+
+	return NETDEV_TX_OK;
+}
+#endif
+
+static int axienet_queue_xmit(struct sk_buff *skb,
+			      struct net_device *ndev, u16 map)
 {
 	u32 ii;
 	u32 num_frag;
 	u32 csum_start_off;
 	u32 csum_index_off;
-	skb_frag_t *frag;
 	dma_addr_t tail_p;
 	struct axienet_local *lp = netdev_priv(ndev);
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+	struct aximcdma_bd *cur_p;
+#else
 	struct axidma_bd *cur_p;
+#endif
+	unsigned long flags;
+	struct axienet_dma_q *q;
+
+	if (lp->axienet_config->mactype == XAXIENET_10G_25G ||
+	    lp->axienet_config->mactype == XAXIENET_MRMAC) {
+		/* Need to manually pad the small frames in case of XXV MAC
+		 * because the pad field is not added by the IP. We must present
+		 * a packet that meets the minimum length to the IP core.
+		 * When the IP core is configured to calculate and add the FCS
+		 * to the packet the minimum packet length is 60 bytes.
+		 */
+		if (eth_skb_pad(skb)) {
+			ndev->stats.tx_dropped++;
+			return NETDEV_TX_OK;
+		}
+	}
 
+#ifdef CONFIG_XILINX_TSN
+	if (unlikely(lp->is_tsn)) {
+		map = tsn_queue_mapping(skb, lp->num_tc);
+#ifdef CONFIG_XILINX_TSN_PTP
+		const struct ethhdr *eth;
+
+		eth = (struct ethhdr *)skb->data;
+		/* check if skb is a PTP frame ? */
+		if (eth->h_proto == htons(ETH_P_1588))
+			return axienet_ptp_xmit(skb, ndev);
+#endif
+		if (lp->temac_no == XAE_TEMAC2) {
+			dev_kfree_skb_any(skb);
+			return NETDEV_TX_OK;
+		}
+	}
+#endif
 	num_frag = skb_shinfo(skb)->nr_frags;
-	cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
 
-	if (axienet_check_tx_bd_space(lp, num_frag)) {
-		if (netif_queue_stopped(ndev))
+	q = lp->dq[map];
+
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+	cur_p = &q->txq_bd_v[q->tx_bd_tail];
+#else
+	cur_p = &q->tx_bd_v[q->tx_bd_tail];
+#endif
+
+	spin_lock_irqsave(&q->tx_lock, flags);
+	if (axienet_check_tx_bd_space(q, num_frag)) {
+		if (netif_queue_stopped(ndev)) {
+			spin_unlock_irqrestore(&q->tx_lock, flags);
 			return NETDEV_TX_BUSY;
+		}
 
 		netif_stop_queue(ndev);
 
@@ -634,65 +1287,148 @@
 		smp_mb();
 
 		/* Space might have just been freed - check again */
-		if (axienet_check_tx_bd_space(lp, num_frag))
+		if (axienet_check_tx_bd_space(q, num_frag)) {
+			spin_unlock_irqrestore(&q->tx_lock, flags);
 			return NETDEV_TX_BUSY;
+		}
 
 		netif_wake_queue(ndev);
 	}
 
-	if (skb->ip_summed == CHECKSUM_PARTIAL) {
+#ifdef CONFIG_XILINX_AXI_EMAC_HWTSTAMP
+	if (axienet_skb_tstsmp(&skb, q, ndev)) {
+		spin_unlock_irqrestore(&q->tx_lock, flags);
+		return NETDEV_TX_BUSY;
+	}
+#endif
+
+	if (skb->ip_summed == CHECKSUM_PARTIAL && !lp->eth_hasnobuf &&
+	    (lp->axienet_config->mactype == XAXIENET_1G)) {
 		if (lp->features & XAE_FEATURE_FULL_TX_CSUM) {
 			/* Tx Full Checksum Offload Enabled */
 			cur_p->app0 |= 2;
-		} else if (lp->features & XAE_FEATURE_PARTIAL_RX_CSUM) {
+		} else if (lp->features & XAE_FEATURE_PARTIAL_TX_CSUM) {
 			csum_start_off = skb_transport_offset(skb);
 			csum_index_off = csum_start_off + skb->csum_offset;
 			/* Tx Partial Checksum Offload Enabled */
 			cur_p->app0 |= 1;
 			cur_p->app1 = (csum_start_off << 16) | csum_index_off;
 		}
-	} else if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
+	} else if (skb->ip_summed == CHECKSUM_UNNECESSARY &&
+		   !lp->eth_hasnobuf &&
+		   (lp->axienet_config->mactype == XAXIENET_1G)) {
 		cur_p->app0 |= 2; /* Tx Full Checksum Offload Enabled */
 	}
 
-	cur_p->cntrl = skb_headlen(skb) | XAXIDMA_BD_CTRL_TXSOF_MASK;
-	cur_p->phys = dma_map_single(ndev->dev.parent, skb->data,
-				     skb_headlen(skb), DMA_TO_DEVICE);
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+	cur_p->cntrl = (skb_headlen(skb) | XMCDMA_BD_CTRL_TXSOF_MASK);
+#else
+	cur_p->cntrl = (skb_headlen(skb) | XAXIDMA_BD_CTRL_TXSOF_MASK);
+#endif
+
+	if (!q->eth_hasdre &&
+	    (((phys_addr_t)skb->data & 0x3) || num_frag > 0)) {
+		skb_copy_and_csum_dev(skb, q->tx_buf[q->tx_bd_tail]);
+
+		cur_p->phys = q->tx_bufs_dma +
+			      (q->tx_buf[q->tx_bd_tail] - q->tx_bufs);
+
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+		cur_p->cntrl = skb_pagelen(skb) | XMCDMA_BD_CTRL_TXSOF_MASK;
+#else
+		cur_p->cntrl = skb_pagelen(skb) | XAXIDMA_BD_CTRL_TXSOF_MASK;
+#endif
+		goto out;
+	} else {
+		cur_p->phys = dma_map_single(ndev->dev.parent, skb->data,
+					     skb_headlen(skb), DMA_TO_DEVICE);
+	}
+	cur_p->tx_desc_mapping = DESC_DMA_MAP_SINGLE;
 
 	for (ii = 0; ii < num_frag; ii++) {
-		if (++lp->tx_bd_tail >= lp->tx_bd_num)
-			lp->tx_bd_tail = 0;
-		cur_p = &lp->tx_bd_v[lp->tx_bd_tail];
+		u32 len;
+		skb_frag_t *frag;
+
+		if (++q->tx_bd_tail >= lp->tx_bd_num)
+			q->tx_bd_tail = 0;
+
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+		cur_p = &q->txq_bd_v[q->tx_bd_tail];
+#else
+		cur_p = &q->tx_bd_v[q->tx_bd_tail];
+#endif
 		frag = &skb_shinfo(skb)->frags[ii];
-		cur_p->phys = dma_map_single(ndev->dev.parent,
-					     skb_frag_address(frag),
-					     skb_frag_size(frag),
-					     DMA_TO_DEVICE);
-		cur_p->cntrl = skb_frag_size(frag);
+		len = skb_frag_size(frag);
+		cur_p->phys = skb_frag_dma_map(ndev->dev.parent, frag, 0, len,
+					       DMA_TO_DEVICE);
+		cur_p->cntrl = len;
+		cur_p->tx_desc_mapping = DESC_DMA_MAP_PAGE;
 	}
 
+out:
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+	cur_p->cntrl |= XMCDMA_BD_CTRL_TXEOF_MASK;
+	tail_p = q->tx_bd_p + sizeof(*q->txq_bd_v) * q->tx_bd_tail;
+#else
 	cur_p->cntrl |= XAXIDMA_BD_CTRL_TXEOF_MASK;
-	cur_p->skb = skb;
+	tail_p = q->tx_bd_p + sizeof(*q->tx_bd_v) * q->tx_bd_tail;
+#endif
+	cur_p->tx_skb = (phys_addr_t)skb;
+	cur_p->tx_skb = (phys_addr_t)skb;
+
+	tail_p = q->tx_bd_p + sizeof(*q->tx_bd_v) * q->tx_bd_tail;
+	/* Ensure BD write before starting transfer */
+	wmb();
 
-	tail_p = lp->tx_bd_p + sizeof(*lp->tx_bd_v) * lp->tx_bd_tail;
 	/* Start the transfer */
-	axienet_dma_out32(lp, XAXIDMA_TX_TDESC_OFFSET, tail_p);
-	if (++lp->tx_bd_tail >= lp->tx_bd_num)
-		lp->tx_bd_tail = 0;
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+	axienet_dma_bdout(q, XMCDMA_CHAN_TAILDESC_OFFSET(q->chan_id),
+			  tail_p);
+#else
+	axienet_dma_bdout(q, XAXIDMA_TX_TDESC_OFFSET, tail_p);
+#endif
+	if (++q->tx_bd_tail >= lp->tx_bd_num)
+		q->tx_bd_tail = 0;
+
+	spin_unlock_irqrestore(&q->tx_lock, flags);
 
 	return NETDEV_TX_OK;
 }
 
 /**
+ * axienet_start_xmit - Starts the transmission.
+ * @skb:	sk_buff pointer that contains data to be Txed.
+ * @ndev:	Pointer to net_device structure.
+ *
+ * Return: NETDEV_TX_OK, on success
+ *	    NETDEV_TX_BUSY, if any of the descriptors are not free
+ *
+ * This function is invoked from upper layers to initiate transmission. The
+ * function uses the next available free BDs and populates their fields to
+ * start the transmission. Additionally if checksum offloading is supported,
+ * it populates AXI Stream Control fields with appropriate values.
+ */
+static int axienet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+	u16 map = skb_get_queue_mapping(skb); /* Single dma queue default*/
+
+	return axienet_queue_xmit(skb, ndev, map);
+}
+
+/**
  * axienet_recv - Is called from Axi DMA Rx Isr to complete the received
  *		  BD processing.
  * @ndev:	Pointer to net_device structure.
+ * @budget:	NAPI budget
+ * @q:		Pointer to axienet DMA queue structure
  *
- * This function is invoked from the Axi DMA Rx isr to process the Rx BDs. It
- * does minimal processing and invokes "netif_rx" to complete further
- * processing.
+ * This function is invoked from the Axi DMA Rx isr(poll) to process the Rx BDs
+ * It does minimal processing and invokes "netif_receive_skb" to complete
+ * further processing.
+ * Return: Number of BD's processed.
  */
-static void axienet_recv(struct net_device *ndev)
+static int axienet_recv(struct net_device *ndev, int budget,
+			struct axienet_dma_q *q)
 {
 	u32 length;
 	u32 csumstatus;
@@ -701,28 +1437,90 @@
 	dma_addr_t tail_p = 0;
 	struct axienet_local *lp = netdev_priv(ndev);
 	struct sk_buff *skb, *new_skb;
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+	struct aximcdma_bd *cur_p;
+#else
 	struct axidma_bd *cur_p;
+#endif
+	unsigned int numbdfree = 0;
 
-	cur_p = &lp->rx_bd_v[lp->rx_bd_ci];
+	/* Get relevat BD status value */
+	rmb();
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+	cur_p = &q->rxq_bd_v[q->rx_bd_ci];
+#else
+	cur_p = &q->rx_bd_v[q->rx_bd_ci];
+#endif
 
-	while ((cur_p->status & XAXIDMA_BD_STS_COMPLETE_MASK)) {
-		tail_p = lp->rx_bd_p + sizeof(*lp->rx_bd_v) * lp->rx_bd_ci;
+	while ((numbdfree < budget) &&
+	       (cur_p->status & XAXIDMA_BD_STS_COMPLETE_MASK)) {
+		new_skb = netdev_alloc_skb(ndev, lp->max_frm_size);
+		if (!new_skb) {
+			dev_err(lp->dev, "No memory for new_skb\n");
+			break;
+		}
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+		tail_p = q->rx_bd_p + sizeof(*q->rxq_bd_v) * q->rx_bd_ci;
+#else
+		tail_p = q->rx_bd_p + sizeof(*q->rx_bd_v) * q->rx_bd_ci;
+#endif
 
 		dma_unmap_single(ndev->dev.parent, cur_p->phys,
 				 lp->max_frm_size,
 				 DMA_FROM_DEVICE);
 
-		skb = cur_p->skb;
-		cur_p->skb = NULL;
-		length = cur_p->app4 & 0x0000FFFF;
+		skb = (struct sk_buff *)(cur_p->sw_id_offset);
+
+		if (lp->eth_hasnobuf ||
+		    (lp->axienet_config->mactype != XAXIENET_1G))
+			length = cur_p->status & XAXIDMA_BD_STS_ACTUAL_LEN_MASK;
+		else
+			length = cur_p->app4 & 0x0000FFFF;
 
 		skb_put(skb, length);
+#ifdef CONFIG_XILINX_AXI_EMAC_HWTSTAMP
+	if (!lp->is_tsn) {
+		if ((lp->tstamp_config.rx_filter == HWTSTAMP_FILTER_ALL ||
+			lp->eth_hasptp) &&
+			(lp->axienet_config->mactype != XAXIENET_10G_25G) &&
+			(lp->axienet_config->mactype != XAXIENET_MRMAC)) {
+			u32 sec, nsec;
+			u64 time64;
+			struct skb_shared_hwtstamps *shhwtstamps;
+
+			if (lp->axienet_config->mactype == XAXIENET_1G ||
+			    lp->axienet_config->mactype == XAXIENET_2_5G) {
+				/* The first 8 bytes will be the timestamp */
+				memcpy(&sec, &skb->data[0], 4);
+				memcpy(&nsec, &skb->data[4], 4);
+
+				sec = cpu_to_be32(sec);
+				nsec = cpu_to_be32(nsec);
+			} else {
+				/* The first 8 bytes will be the timestamp */
+				memcpy(&nsec, &skb->data[0], 4);
+				memcpy(&sec, &skb->data[4], 4);
+			}
+
+			/* Remove these 8 bytes from the buffer */
+			skb_pull(skb, 8);
+			time64 = sec * NS_PER_SEC + nsec;
+			shhwtstamps = skb_hwtstamps(skb);
+			shhwtstamps->hwtstamp = ns_to_ktime(time64);
+		} else if (lp->axienet_config->mactype == XAXIENET_10G_25G ||
+			   lp->axienet_config->mactype == XAXIENET_MRMAC) {
+			axienet_rx_hwtstamp(lp, skb);
+		}
+	}
+#endif
 		skb->protocol = eth_type_trans(skb, ndev);
 		/*skb_checksum_none_assert(skb);*/
 		skb->ip_summed = CHECKSUM_NONE;
 
 		/* if we're doing Rx csum offload, set it up */
-		if (lp->features & XAE_FEATURE_FULL_RX_CSUM) {
+		if (lp->features & XAE_FEATURE_FULL_RX_CSUM &&
+		    (lp->axienet_config->mactype == XAXIENET_1G) &&
+		    !lp->eth_hasnobuf) {
 			csumstatus = (cur_p->app2 &
 				      XAE_FULL_CSUM_STATUS_MASK) >> 3;
 			if ((csumstatus == XAE_IP_TCP_CSUM_VALIDATED) ||
@@ -731,135 +1529,132 @@
 			}
 		} else if ((lp->features & XAE_FEATURE_PARTIAL_RX_CSUM) != 0 &&
 			   skb->protocol == htons(ETH_P_IP) &&
-			   skb->len > 64) {
+			   skb->len > 64 && !lp->eth_hasnobuf &&
+			   (lp->axienet_config->mactype == XAXIENET_1G)) {
 			skb->csum = be32_to_cpu(cur_p->app3 & 0xFFFF);
 			skb->ip_summed = CHECKSUM_COMPLETE;
 		}
 
-		netif_rx(skb);
+		netif_receive_skb(skb);
 
 		size += length;
 		packets++;
 
-		new_skb = netdev_alloc_skb_ip_align(ndev, lp->max_frm_size);
-		if (!new_skb)
-			return;
+		/* Ensure that the skb is completely updated
+		 * prio to mapping the DMA
+		 */
+		wmb();
 
 		cur_p->phys = dma_map_single(ndev->dev.parent, new_skb->data,
 					     lp->max_frm_size,
 					     DMA_FROM_DEVICE);
 		cur_p->cntrl = lp->max_frm_size;
 		cur_p->status = 0;
-		cur_p->skb = new_skb;
+		cur_p->sw_id_offset = (phys_addr_t)new_skb;
+
+		if (++q->rx_bd_ci >= lp->rx_bd_num)
+			q->rx_bd_ci = 0;
 
-		if (++lp->rx_bd_ci >= lp->rx_bd_num)
-			lp->rx_bd_ci = 0;
-		cur_p = &lp->rx_bd_v[lp->rx_bd_ci];
+		/* Get relevat BD status value */
+		rmb();
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+		cur_p = &q->rxq_bd_v[q->rx_bd_ci];
+#else
+		cur_p = &q->rx_bd_v[q->rx_bd_ci];
+#endif
+		numbdfree++;
 	}
 
 	ndev->stats.rx_packets += packets;
 	ndev->stats.rx_bytes += size;
+	q->rx_packets += packets;
+	q->rx_bytes += size;
 
-	if (tail_p)
-		axienet_dma_out32(lp, XAXIDMA_RX_TDESC_OFFSET, tail_p);
-}
-
-/**
- * axienet_tx_irq - Tx Done Isr.
- * @irq:	irq number
- * @_ndev:	net_device pointer
- *
- * Return: IRQ_HANDLED if device generated a TX interrupt, IRQ_NONE otherwise.
- *
- * This is the Axi DMA Tx done Isr. It invokes "axienet_start_xmit_done"
- * to complete the BD processing.
- */
-static irqreturn_t axienet_tx_irq(int irq, void *_ndev)
-{
-	u32 cr;
-	unsigned int status;
-	struct net_device *ndev = _ndev;
-	struct axienet_local *lp = netdev_priv(ndev);
-
-	status = axienet_dma_in32(lp, XAXIDMA_TX_SR_OFFSET);
-	if (status & (XAXIDMA_IRQ_IOC_MASK | XAXIDMA_IRQ_DELAY_MASK)) {
-		axienet_dma_out32(lp, XAXIDMA_TX_SR_OFFSET, status);
-		axienet_start_xmit_done(lp->ndev);
-		goto out;
+	if (tail_p) {
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+		axienet_dma_bdout(q, XMCDMA_CHAN_TAILDESC_OFFSET(q->chan_id) +
+				  q->rx_offset, tail_p);
+#else
+		axienet_dma_bdout(q, XAXIDMA_RX_TDESC_OFFSET, tail_p);
+#endif
 	}
-	if (!(status & XAXIDMA_IRQ_ALL_MASK))
-		return IRQ_NONE;
-	if (status & XAXIDMA_IRQ_ERROR_MASK) {
-		dev_err(&ndev->dev, "DMA Tx error 0x%x\n", status);
-		dev_err(&ndev->dev, "Current BD is at: 0x%x\n",
-			(lp->tx_bd_v[lp->tx_bd_ci]).phys);
-
-		cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
-		/* Disable coalesce, delay timer and error interrupts */
-		cr &= (~XAXIDMA_IRQ_ALL_MASK);
-		/* Write to the Tx channel control register */
-		axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, cr);
-
-		cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
-		/* Disable coalesce, delay timer and error interrupts */
-		cr &= (~XAXIDMA_IRQ_ALL_MASK);
-		/* Write to the Rx channel control register */
-		axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, cr);
 
-		tasklet_schedule(&lp->dma_err_tasklet);
-		axienet_dma_out32(lp, XAXIDMA_TX_SR_OFFSET, status);
-	}
-out:
-	return IRQ_HANDLED;
+	return numbdfree;
 }
 
 /**
- * axienet_rx_irq - Rx Isr.
- * @irq:	irq number
- * @_ndev:	net_device pointer
+ * xaxienet_rx_poll - Poll routine for rx packets (NAPI)
+ * @napi:	napi structure pointer
+ * @quota:	Max number of rx packets to be processed.
  *
- * Return: IRQ_HANDLED if device generated a RX interrupt, IRQ_NONE otherwise.
+ * This is the poll routine for rx part.
+ * It will process the packets maximux quota value.
  *
- * This is the Axi DMA Rx Isr. It invokes "axienet_recv" to complete the BD
- * processing.
+ * Return: number of packets received
  */
-static irqreturn_t axienet_rx_irq(int irq, void *_ndev)
+int xaxienet_rx_poll(struct napi_struct *napi, int quota)
 {
-	u32 cr;
-	unsigned int status;
-	struct net_device *ndev = _ndev;
+	struct net_device *ndev = napi->dev;
 	struct axienet_local *lp = netdev_priv(ndev);
+	int work_done = 0;
+	unsigned int status, cr;
 
-	status = axienet_dma_in32(lp, XAXIDMA_RX_SR_OFFSET);
-	if (status & (XAXIDMA_IRQ_IOC_MASK | XAXIDMA_IRQ_DELAY_MASK)) {
-		axienet_dma_out32(lp, XAXIDMA_RX_SR_OFFSET, status);
-		axienet_recv(lp->ndev);
-		goto out;
+	int map = napi - lp->napi;
+
+	struct axienet_dma_q *q = lp->dq[map];
+
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+	spin_lock(&q->rx_lock);
+	status = axienet_dma_in32(q, XMCDMA_CHAN_SR_OFFSET(q->chan_id) +
+				  q->rx_offset);
+	while ((status & (XMCDMA_IRQ_IOC_MASK | XMCDMA_IRQ_DELAY_MASK)) &&
+	       (work_done < quota)) {
+		axienet_dma_out32(q, XMCDMA_CHAN_SR_OFFSET(q->chan_id) +
+				  q->rx_offset, status);
+		if (status & XMCDMA_IRQ_ERR_MASK) {
+			dev_err(lp->dev, "Rx error 0x%x\n\r", status);
+			break;
+		}
+		work_done += axienet_recv(lp->ndev, quota - work_done, q);
+		status = axienet_dma_in32(q, XMCDMA_CHAN_SR_OFFSET(q->chan_id) +
+					  q->rx_offset);
+	}
+	spin_unlock(&q->rx_lock);
+#else
+	spin_lock(&q->rx_lock);
+
+	status = axienet_dma_in32(q, XAXIDMA_RX_SR_OFFSET);
+	while ((status & (XAXIDMA_IRQ_IOC_MASK | XAXIDMA_IRQ_DELAY_MASK)) &&
+	       (work_done < quota)) {
+		axienet_dma_out32(q, XAXIDMA_RX_SR_OFFSET, status);
+		if (status & XAXIDMA_IRQ_ERROR_MASK) {
+			dev_err(lp->dev, "Rx error 0x%x\n\r", status);
+			break;
+		}
+		work_done += axienet_recv(lp->ndev, quota - work_done, q);
+		status = axienet_dma_in32(q, XAXIDMA_RX_SR_OFFSET);
 	}
-	if (!(status & XAXIDMA_IRQ_ALL_MASK))
-		return IRQ_NONE;
-	if (status & XAXIDMA_IRQ_ERROR_MASK) {
-		dev_err(&ndev->dev, "DMA Rx error 0x%x\n", status);
-		dev_err(&ndev->dev, "Current BD is at: 0x%x\n",
-			(lp->rx_bd_v[lp->rx_bd_ci]).phys);
-
-		cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
-		/* Disable coalesce, delay timer and error interrupts */
-		cr &= (~XAXIDMA_IRQ_ALL_MASK);
-		/* Finally write to the Tx channel control register */
-		axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, cr);
-
-		cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
-		/* Disable coalesce, delay timer and error interrupts */
-		cr &= (~XAXIDMA_IRQ_ALL_MASK);
-		/* write to the Rx channel control register */
-		axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, cr);
+	spin_unlock(&q->rx_lock);
+#endif
 
-		tasklet_schedule(&lp->dma_err_tasklet);
-		axienet_dma_out32(lp, XAXIDMA_RX_SR_OFFSET, status);
+	if (work_done < quota) {
+		napi_complete(napi);
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+		/* Enable the interrupts again */
+		cr = axienet_dma_in32(q, XMCDMA_CHAN_CR_OFFSET(q->chan_id) +
+				      XMCDMA_RX_OFFSET);
+		cr |= (XMCDMA_IRQ_IOC_MASK | XMCDMA_IRQ_DELAY_MASK);
+		axienet_dma_out32(q, XMCDMA_CHAN_CR_OFFSET(q->chan_id) +
+				  XMCDMA_RX_OFFSET, cr);
+#else
+		/* Enable the interrupts again */
+		cr = axienet_dma_in32(q, XAXIDMA_RX_CR_OFFSET);
+		cr |= (XAXIDMA_IRQ_IOC_MASK | XAXIDMA_IRQ_DELAY_MASK);
+		axienet_dma_out32(q, XAXIDMA_RX_CR_OFFSET, cr);
+#endif
 	}
-out:
-	return IRQ_HANDLED;
+
+	return work_done;
 }
 
 /**
@@ -891,7 +1686,32 @@
 	return IRQ_HANDLED;
 }
 
-static void axienet_dma_err_handler(unsigned long data);
+static int axienet_mii_init(struct net_device *ndev)
+{
+	struct axienet_local *lp = netdev_priv(ndev);
+	int ret;
+
+	/* Disable the MDIO interface till Axi Ethernet Reset is completed.
+	 * When we do an Axi Ethernet reset, it resets the complete core
+	 * including the MDIO. MDIO must be disabled before resetting
+	 * and re-enabled afterwards.
+	 * Hold MDIO bus lock to avoid MDIO accesses during the reset.
+	 */
+
+	mutex_lock(&lp->mii_bus->mdio_lock);
+	ret = axienet_mdio_wait_until_ready(lp);
+	if (ret < 0)
+		return ret;
+	axienet_mdio_disable(lp);
+	axienet_device_reset(ndev);
+	ret = axienet_mdio_enable(lp);
+	ret = axienet_mdio_wait_until_ready(lp);
+	mutex_unlock(&lp->mii_bus->mdio_lock);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
 
 /**
  * axienet_open - Driver open routine.
@@ -900,73 +1720,250 @@
  * Return: 0, on success.
  *	    non-zero error value on failure
  *
- * This is the driver open routine. It calls phylink_start to start the
- * PHY device.
+ * This is the driver open routine. It calls phy_start to start the PHY device.
  * It also allocates interrupt service routines, enables the interrupt lines
  * and ISR handling. Axi Ethernet core is reset through Axi DMA core. Buffer
  * descriptors are initialized.
  */
 static int axienet_open(struct net_device *ndev)
 {
-	int ret;
+	int ret = 0, i = 0;
 	struct axienet_local *lp = netdev_priv(ndev);
+	struct axienet_dma_q *q;
+	u32 reg, err;
+	struct phy_device *phydev = NULL;
 
 	dev_dbg(&ndev->dev, "axienet_open()\n");
 
-	/* Disable the MDIO interface till Axi Ethernet Reset is completed.
-	 * When we do an Axi Ethernet reset, it resets the complete core
-	 * including the MDIO. MDIO must be disabled before resetting
-	 * and re-enabled afterwards.
-	 * Hold MDIO bus lock to avoid MDIO accesses during the reset.
-	 */
-	mutex_lock(&lp->mii_bus->mdio_lock);
-	axienet_mdio_disable(lp);
-	axienet_device_reset(ndev);
-	ret = axienet_mdio_enable(lp);
-	mutex_unlock(&lp->mii_bus->mdio_lock);
+	if (lp->axienet_config->mactype == XAXIENET_10G_25G ||
+	    lp->axienet_config->mactype == XAXIENET_MRMAC)
+		axienet_device_reset(ndev);
+	else
+		ret = axienet_mii_init(ndev);
+
 	if (ret < 0)
 		return ret;
 
-	ret = phylink_of_phy_connect(lp->phylink, lp->dev->of_node, 0);
-	if (ret) {
-		dev_err(lp->dev, "phylink_of_phy_connect() failed: %d\n", ret);
-		return ret;
+	if (lp->phy_node) {
+		phydev = of_phy_connect(lp->ndev, lp->phy_node,
+					axienet_adjust_link,
+					lp->phy_flags,
+					lp->phy_interface);
+
+		if (!phydev)
+			dev_err(lp->dev, "of_phy_connect() failed\n");
+		else
+			phy_start(phydev);
+	}
+	if (!lp->is_tsn || lp->temac_no == XAE_TEMAC1) {
+		/* Enable tasklets for Axi DMA error handling */
+		for_each_rx_dma_queue(lp, i) {
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+			tasklet_init(&lp->dma_err_tasklet[i],
+				     axienet_mcdma_err_handler,
+				     (unsigned long)lp->dq[i]);
+#else
+			tasklet_init(&lp->dma_err_tasklet[i],
+				     axienet_dma_err_handler,
+				     (unsigned long)lp->dq[i]);
+#endif
+
+			/* Enable NAPI scheduling before enabling Axi DMA Rx
+			 * IRQ, or you might run into a race condition; the RX
+			 * ISR disables IRQ processing before scheduling the
+			 * NAPI function to complete the processing. If NAPI
+			 * scheduling is (still) disabled at that time, no more
+			 * RX IRQs will be processed as only the NAPI function
+			 * re-enables them!
+			 */
+			napi_enable(&lp->napi[i]);
+		}
+		for_each_tx_dma_queue(lp, i) {
+			struct axienet_dma_q *q = lp->dq[i];
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+			/* Enable interrupts for Axi MCDMA Tx */
+			ret = request_irq(q->tx_irq, axienet_mcdma_tx_irq,
+					  IRQF_SHARED, ndev->name, ndev);
+			if (ret)
+				goto err_tx_irq;
+#else
+			/* Enable interrupts for Axi DMA Tx */
+			ret = request_irq(q->tx_irq, axienet_tx_irq,
+					  0, ndev->name, ndev);
+			if (ret)
+				goto err_tx_irq;
+#endif
+		}
+
+		for_each_rx_dma_queue(lp, i) {
+			struct axienet_dma_q *q = lp->dq[i];
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+			/* Enable interrupts for Axi MCDMA Rx */
+			ret = request_irq(q->rx_irq, axienet_mcdma_rx_irq,
+					  IRQF_SHARED, ndev->name, ndev);
+			if (ret)
+				goto err_rx_irq;
+#else
+			/* Enable interrupts for Axi DMA Rx */
+			ret = request_irq(q->rx_irq, axienet_rx_irq,
+					  0, ndev->name, ndev);
+			if (ret)
+				goto err_rx_irq;
+#endif
+		}
 	}
+#ifdef CONFIG_XILINX_TSN_PTP
+	if (lp->is_tsn) {
+		INIT_WORK(&lp->tx_tstamp_work, axienet_tx_tstamp);
+		skb_queue_head_init(&lp->ptp_txq);
+
+		lp->ptp_rx_hw_pointer = 0;
+		lp->ptp_rx_sw_pointer = 0xff;
 
-	phylink_start(lp->phylink);
+		axienet_iow(lp, PTP_RX_CONTROL_OFFSET, PTP_RX_PACKET_CLEAR);
+
+		ret = request_irq(lp->ptp_rx_irq, axienet_ptp_rx_irq,
+				  0, "ptp_rx", ndev);
+		if (ret)
+			goto err_ptp_rx_irq;
+
+		ret = request_irq(lp->ptp_tx_irq, axienet_ptp_tx_irq,
+				  0, "ptp_tx", ndev);
+		if (ret)
+			goto err_ptp_rx_irq;
+	}
+#endif
+
+	if (lp->phy_mode == XXE_PHY_TYPE_USXGMII) {
+		netdev_dbg(ndev, "RX reg: 0x%x\n",
+			   axienet_ior(lp, XXV_RCW1_OFFSET));
+		/* USXGMII setup at selected speed */
+		reg = axienet_ior(lp, XXV_USXGMII_AN_OFFSET);
+		reg &= ~USXGMII_RATE_MASK;
+		netdev_dbg(ndev, "usxgmii_rate %d\n", lp->usxgmii_rate);
+		switch (lp->usxgmii_rate) {
+		case SPEED_1000:
+			reg |= USXGMII_RATE_1G;
+			break;
+		case SPEED_2500:
+			reg |= USXGMII_RATE_2G5;
+			break;
+		case SPEED_10:
+			reg |= USXGMII_RATE_10M;
+			break;
+		case SPEED_100:
+			reg |= USXGMII_RATE_100M;
+			break;
+		case SPEED_5000:
+			reg |= USXGMII_RATE_5G;
+			break;
+		case SPEED_10000:
+			reg |= USXGMII_RATE_10G;
+			break;
+		default:
+			reg |= USXGMII_RATE_1G;
+		}
+		reg |= USXGMII_FD;
+		reg |= (USXGMII_EN | USXGMII_LINK_STS);
+		axienet_iow(lp, XXV_USXGMII_AN_OFFSET, reg);
+		reg |= USXGMII_AN_EN;
+		axienet_iow(lp, XXV_USXGMII_AN_OFFSET, reg);
+		/* AN Restart bit should be reset, set and then reset as per
+		 * spec with a 1 ms delay for a raising edge trigger
+		 */
+		axienet_iow(lp, XXV_USXGMII_AN_OFFSET,
+			    reg & ~USXGMII_AN_RESTART);
+		mdelay(1);
+		axienet_iow(lp, XXV_USXGMII_AN_OFFSET,
+			    reg | USXGMII_AN_RESTART);
+		mdelay(1);
+		axienet_iow(lp, XXV_USXGMII_AN_OFFSET,
+			    reg & ~USXGMII_AN_RESTART);
+
+		/* Check block lock bit to make sure RX path is ok with
+		 * USXGMII initialization.
+		 */
+		err = readl_poll_timeout(lp->regs + XXV_STATRX_BLKLCK_OFFSET,
+					 reg, (reg & XXV_RX_BLKLCK_MASK),
+					 100, DELAY_OF_ONE_MILLISEC);
+		if (err) {
+			netdev_err(ndev, "%s: USXGMII Block lock bit not set",
+				   __func__);
+			ret = -ENODEV;
+			goto err_eth_irq;
+		}
+
+		err = readl_poll_timeout(lp->regs + XXV_USXGMII_AN_STS_OFFSET,
+					 reg, (reg & USXGMII_AN_STS_COMP_MASK),
+					 1000000, DELAY_OF_ONE_MILLISEC);
+		if (err) {
+			netdev_err(ndev, "%s: USXGMII AN not complete",
+				   __func__);
+			ret = -ENODEV;
+			goto err_eth_irq;
+		}
+
+		netdev_info(ndev, "USXGMII setup at %d\n", lp->usxgmii_rate);
+	}
+
+	if (lp->axienet_config->mactype == XAXIENET_MRMAC) {
+		u32 val;
+
+		/* Reset MRMAC */
+		axienet_mrmac_reset(lp);
+
+		mdelay(MRMAC_RESET_DELAY);
+		/* Check for block lock bit to be set. This ensures that
+		 * MRMAC ethernet IP is functioning normally.
+		 */
+		axienet_iow(lp, MRMAC_TX_STS_OFFSET, MRMAC_STS_ALL_MASK);
+		axienet_iow(lp, MRMAC_RX_STS_OFFSET, MRMAC_STS_ALL_MASK);
+		axienet_iow(lp, MRMAC_STATRX_BLKLCK_OFFSET, MRMAC_STS_ALL_MASK);
+		err = readl_poll_timeout(lp->regs + MRMAC_STATRX_BLKLCK_OFFSET,
+					 val, (val & MRMAC_RX_BLKLCK_MASK),
+					 10, DELAY_OF_ONE_MILLISEC);
+		if (err) {
+			netdev_err(ndev, "MRMAC block lock not complete! Cross-check the MAC ref clock configuration\n");
+			ret = -ENODEV;
+			goto err_eth_irq;
+		}
+		netdev_info(ndev, "MRMAC setup at %d\n", lp->mrmac_rate);
+		axienet_iow(lp, MRMAC_TICK_OFFSET, MRMAC_TICK_TRIGGER);
+	}
 
-	/* Enable tasklets for Axi DMA error handling */
-	tasklet_init(&lp->dma_err_tasklet, axienet_dma_err_handler,
-		     (unsigned long) lp);
-
-	/* Enable interrupts for Axi DMA Tx */
-	ret = request_irq(lp->tx_irq, axienet_tx_irq, IRQF_SHARED,
-			  ndev->name, ndev);
-	if (ret)
-		goto err_tx_irq;
-	/* Enable interrupts for Axi DMA Rx */
-	ret = request_irq(lp->rx_irq, axienet_rx_irq, IRQF_SHARED,
-			  ndev->name, ndev);
-	if (ret)
-		goto err_rx_irq;
 	/* Enable interrupts for Axi Ethernet core (if defined) */
-	if (lp->eth_irq > 0) {
+	if (!lp->eth_hasnobuf && (lp->axienet_config->mactype == XAXIENET_1G)) {
 		ret = request_irq(lp->eth_irq, axienet_eth_irq, IRQF_SHARED,
 				  ndev->name, ndev);
 		if (ret)
 			goto err_eth_irq;
 	}
 
+	netif_tx_start_all_queues(ndev);
 	return 0;
 
 err_eth_irq:
-	free_irq(lp->rx_irq, ndev);
+	while (i--) {
+		q = lp->dq[i];
+		free_irq(q->rx_irq, ndev);
+	}
+	i = lp->num_tx_queues;
 err_rx_irq:
-	free_irq(lp->tx_irq, ndev);
+	while (i--) {
+		q = lp->dq[i];
+		free_irq(q->tx_irq, ndev);
+	}
 err_tx_irq:
-	phylink_stop(lp->phylink);
-	phylink_disconnect_phy(lp->phylink);
-	tasklet_kill(&lp->dma_err_tasklet);
+	for_each_rx_dma_queue(lp, i)
+		napi_disable(&lp->napi[i]);
+	if (phydev)
+		phy_disconnect(phydev);
+	phydev = NULL;
+#ifdef CONFIG_XILINX_TSN_PTP
+err_ptp_rx_irq:
+#endif
+	for_each_rx_dma_queue(lp, i)
+		tasklet_kill(&lp->dma_err_tasklet[i]);
 	dev_err(lp->dev, "request_irq() failed\n");
 	return ret;
 }
@@ -977,7 +1974,7 @@
  *
  * Return: 0, on success.
  *
- * This is the driver stop routine. It calls phylink_disconnect to stop the PHY
+ * This is the driver stop routine. It calls phy_disconnect to stop the PHY
  * device. It also removes the interrupt handlers and disables the interrupts.
  * The Axi DMA Tx/Rx BDs are released.
  */
@@ -985,54 +1982,80 @@
 {
 	u32 cr, sr;
 	int count;
+	u32 i;
 	struct axienet_local *lp = netdev_priv(ndev);
+	struct axienet_dma_q *q;
 
 	dev_dbg(&ndev->dev, "axienet_close()\n");
 
-	phylink_stop(lp->phylink);
-	phylink_disconnect_phy(lp->phylink);
-
-	axienet_setoptions(ndev, lp->options &
+	lp->axienet_config->setoptions(ndev, lp->options &
 			   ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN));
 
-	cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
-	cr &= ~(XAXIDMA_CR_RUNSTOP_MASK | XAXIDMA_IRQ_ALL_MASK);
-	axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, cr);
-
-	cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
-	cr &= ~(XAXIDMA_CR_RUNSTOP_MASK | XAXIDMA_IRQ_ALL_MASK);
-	axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, cr);
+	if (!lp->is_tsn || lp->temac_no == XAE_TEMAC1) {
+		for_each_tx_dma_queue(lp, i) {
+			q = lp->dq[i];
+			cr = axienet_dma_in32(q, XAXIDMA_RX_CR_OFFSET);
+			cr &= ~(XAXIDMA_CR_RUNSTOP_MASK | XAXIDMA_IRQ_ALL_MASK);
+			axienet_dma_out32(q, XAXIDMA_RX_CR_OFFSET, cr);
+
+			cr = axienet_dma_in32(q, XAXIDMA_TX_CR_OFFSET);
+			cr &= ~(XAXIDMA_CR_RUNSTOP_MASK | XAXIDMA_IRQ_ALL_MASK);
+			axienet_dma_out32(q, XAXIDMA_TX_CR_OFFSET, cr);
+
+			axienet_iow(lp, XAE_IE_OFFSET, 0);
+
+			/* Give DMAs a chance to halt gracefully */
+			sr = axienet_dma_in32(q, XAXIDMA_RX_SR_OFFSET);
+			for (count = 0; !(sr & XAXIDMA_SR_HALT_MASK) && count < 5; ++count) {
+				msleep(20);
+				sr = axienet_dma_in32(q, XAXIDMA_RX_SR_OFFSET);
+			}
 
-	axienet_iow(lp, XAE_IE_OFFSET, 0);
+			sr = axienet_dma_in32(q, XAXIDMA_TX_SR_OFFSET);
+			for (count = 0; !(sr & XAXIDMA_SR_HALT_MASK) && count < 5; ++count) {
+				msleep(20);
+				sr = axienet_dma_in32(q, XAXIDMA_TX_SR_OFFSET);
+			}
 
-	/* Give DMAs a chance to halt gracefully */
-	sr = axienet_dma_in32(lp, XAXIDMA_RX_SR_OFFSET);
-	for (count = 0; !(sr & XAXIDMA_SR_HALT_MASK) && count < 5; ++count) {
-		msleep(20);
-		sr = axienet_dma_in32(lp, XAXIDMA_RX_SR_OFFSET);
-	}
+			/* Do a reset to ensure DMA is really stopped */
+			if (lp->axienet_config->mactype != XAXIENET_10G_25G &&
+			    lp->axienet_config->mactype != XAXIENET_MRMAC) {
+				mutex_lock(&lp->mii_bus->mdio_lock);
+				axienet_mdio_disable(lp);
+			}
 
-	sr = axienet_dma_in32(lp, XAXIDMA_TX_SR_OFFSET);
-	for (count = 0; !(sr & XAXIDMA_SR_HALT_MASK) && count < 5; ++count) {
-		msleep(20);
-		sr = axienet_dma_in32(lp, XAXIDMA_TX_SR_OFFSET);
-	}
+			__axienet_device_reset(q);
 
-	/* Do a reset to ensure DMA is really stopped */
-	mutex_lock(&lp->mii_bus->mdio_lock);
-	axienet_mdio_disable(lp);
-	__axienet_device_reset(lp);
-	axienet_mdio_enable(lp);
-	mutex_unlock(&lp->mii_bus->mdio_lock);
+			if (lp->axienet_config->mactype != XAXIENET_10G_25G &&
+			    lp->axienet_config->mactype != XAXIENET_MRMAC) {
+				axienet_mdio_enable(lp);
+				mutex_unlock(&lp->mii_bus->mdio_lock);
+			}
+			free_irq(q->tx_irq, ndev);
+		}
 
-	tasklet_kill(&lp->dma_err_tasklet);
+		for_each_rx_dma_queue(lp, i) {
+			q = lp->dq[i];
+			netif_stop_queue(ndev);
+			napi_disable(&lp->napi[i]);
+			tasklet_kill(&lp->dma_err_tasklet[i]);
+			free_irq(q->rx_irq, ndev);
+		}
+#ifdef CONFIG_XILINX_TSN_PTP
+		if (lp->is_tsn) {
+			free_irq(lp->ptp_tx_irq, ndev);
+			free_irq(lp->ptp_rx_irq, ndev);
+		}
+#endif
+		if ((lp->axienet_config->mactype == XAXIENET_1G) && !lp->eth_hasnobuf)
+			free_irq(lp->eth_irq, ndev);
 
-	if (lp->eth_irq > 0)
-		free_irq(lp->eth_irq, ndev);
-	free_irq(lp->tx_irq, ndev);
-	free_irq(lp->rx_irq, ndev);
+		if (ndev->phydev)
+			phy_disconnect(ndev->phydev);
 
-	axienet_dma_bd_release(ndev);
+		if (lp->temac_no != XAE_TEMAC2)
+			axienet_dma_bd_release(ndev);
+	}
 	return 0;
 }
 
@@ -1074,15 +2097,216 @@
 static void axienet_poll_controller(struct net_device *ndev)
 {
 	struct axienet_local *lp = netdev_priv(ndev);
-	disable_irq(lp->tx_irq);
-	disable_irq(lp->rx_irq);
-	axienet_rx_irq(lp->tx_irq, ndev);
-	axienet_tx_irq(lp->rx_irq, ndev);
-	enable_irq(lp->tx_irq);
-	enable_irq(lp->rx_irq);
+	int i;
+
+	for_each_tx_dma_queue(lp, i)
+		disable_irq(lp->dq[i]->tx_irq);
+	for_each_rx_dma_queue(lp, i)
+		disable_irq(lp->dq[i]->rx_irq);
+
+	for_each_rx_dma_queue(lp, i)
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+		axienet_mcdma_rx_irq(lp->dq[i]->rx_irq, ndev);
+#else
+		axienet_rx_irq(lp->dq[i]->rx_irq, ndev);
+#endif
+	for_each_tx_dma_queue(lp, i)
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+		axienet_mcdma_tx_irq(lp->dq[i]->tx_irq, ndev);
+#else
+		axienet_tx_irq(lp->dq[i]->tx_irq, ndev);
+#endif
+	for_each_tx_dma_queue(lp, i)
+		enable_irq(lp->dq[i]->tx_irq);
+	for_each_rx_dma_queue(lp, i)
+		enable_irq(lp->dq[i]->rx_irq);
 }
 #endif
 
+#if defined(CONFIG_XILINX_AXI_EMAC_HWTSTAMP) || defined(CONFIG_XILINX_TSN_PTP)
+/**
+ *  axienet_set_timestamp_mode - sets up the hardware for the requested mode
+ *  @lp: Pointer to axienet local structure
+ *  @config: the hwtstamp configuration requested
+ *
+ * Return: 0 on success, Negative value on errors
+ */
+static int axienet_set_timestamp_mode(struct axienet_local *lp,
+				      struct hwtstamp_config *config)
+{
+	u32 regval;
+
+#ifdef CONFIG_XILINX_TSN_PTP
+	if (lp->is_tsn) {
+		/* reserved for future extensions */
+		if (config->flags)
+			return -EINVAL;
+
+		if (config->tx_type < HWTSTAMP_TX_OFF ||
+		    config->tx_type > HWTSTAMP_TX_ONESTEP_SYNC)
+			return -ERANGE;
+
+		lp->ptp_ts_type = config->tx_type;
+
+		/* On RX always timestamp everything */
+		switch (config->rx_filter) {
+		case HWTSTAMP_FILTER_NONE:
+			break;
+		default:
+			config->rx_filter = HWTSTAMP_FILTER_ALL;
+		}
+		return 0;
+	}
+#endif
+
+	/* reserved for future extensions */
+	if (config->flags)
+		return -EINVAL;
+
+	/* Read the current value in the MAC TX CTRL register */
+	if (lp->axienet_config->mactype != XAXIENET_10G_25G &&
+	    lp->axienet_config->mactype != XAXIENET_MRMAC)
+		regval = axienet_ior(lp, XAE_TC_OFFSET);
+
+	switch (config->tx_type) {
+	case HWTSTAMP_TX_OFF:
+		regval &= ~XAE_TC_INBAND1588_MASK;
+		break;
+	case HWTSTAMP_TX_ON:
+		config->tx_type = HWTSTAMP_TX_ON;
+		regval |= XAE_TC_INBAND1588_MASK;
+		break;
+	case HWTSTAMP_TX_ONESTEP_SYNC:
+		config->tx_type = HWTSTAMP_TX_ONESTEP_SYNC;
+		regval |= XAE_TC_INBAND1588_MASK;
+		break;
+	default:
+		return -ERANGE;
+	}
+
+	if (lp->axienet_config->mactype != XAXIENET_10G_25G &&
+	    lp->axienet_config->mactype != XAXIENET_MRMAC)
+		axienet_iow(lp, XAE_TC_OFFSET, regval);
+
+	/* Read the current value in the MAC RX RCW1 register */
+	if (lp->axienet_config->mactype != XAXIENET_10G_25G &&
+	    lp->axienet_config->mactype != XAXIENET_MRMAC)
+		regval = axienet_ior(lp, XAE_RCW1_OFFSET);
+
+	/* On RX always timestamp everything */
+	switch (config->rx_filter) {
+	case HWTSTAMP_FILTER_NONE:
+		regval &= ~XAE_RCW1_INBAND1588_MASK;
+		break;
+	default:
+		config->rx_filter = HWTSTAMP_FILTER_ALL;
+		regval |= XAE_RCW1_INBAND1588_MASK;
+	}
+
+	if (lp->axienet_config->mactype != XAXIENET_10G_25G &&
+	    lp->axienet_config->mactype != XAXIENET_MRMAC)
+		axienet_iow(lp, XAE_RCW1_OFFSET, regval);
+
+	return 0;
+}
+
+/**
+ * axienet_set_ts_config - user entry point for timestamp mode
+ * @lp: Pointer to axienet local structure
+ * @ifr: ioctl data
+ *
+ * Set hardware to the requested more. If unsupported return an error
+ * with no changes. Otherwise, store the mode for future reference
+ *
+ * Return: 0 on success, Negative value on errors
+ */
+static int axienet_set_ts_config(struct axienet_local *lp, struct ifreq *ifr)
+{
+	struct hwtstamp_config config;
+	int err;
+
+	if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
+		return -EFAULT;
+
+	err = axienet_set_timestamp_mode(lp, &config);
+	if (err)
+		return err;
+
+	/* save these settings for future reference */
+	memcpy(&lp->tstamp_config, &config, sizeof(lp->tstamp_config));
+
+	return copy_to_user(ifr->ifr_data, &config,
+			    sizeof(config)) ? -EFAULT : 0;
+}
+
+/**
+ * axienet_get_ts_config - return the current timestamp configuration
+ * to the user
+ * @lp: pointer to axienet local structure
+ * @ifr: ioctl data
+ *
+ * Return: 0 on success, Negative value on errors
+ */
+static int axienet_get_ts_config(struct axienet_local *lp, struct ifreq *ifr)
+{
+	struct hwtstamp_config *config = &lp->tstamp_config;
+
+	return copy_to_user(ifr->ifr_data, config,
+			    sizeof(*config)) ? -EFAULT : 0;
+}
+#endif
+
+/* Ioctl MII Interface */
+static int axienet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+#if defined(CONFIG_XILINX_AXI_EMAC_HWTSTAMP) || defined(CONFIG_XILINX_TSN_PTP)
+	struct axienet_local *lp = netdev_priv(dev);
+#endif
+
+	if (!netif_running(dev))
+		return -EINVAL;
+
+	switch (cmd) {
+	case SIOCGMIIPHY:
+	case SIOCGMIIREG:
+	case SIOCSMIIREG:
+		if (!dev->phydev)
+			return -EOPNOTSUPP;
+		return phy_mii_ioctl(dev->phydev, rq, cmd);
+#if defined(CONFIG_XILINX_AXI_EMAC_HWTSTAMP) || defined(CONFIG_XILINX_TSN_PTP)
+	case SIOCSHWTSTAMP:
+		return axienet_set_ts_config(lp, rq);
+	case SIOCGHWTSTAMP:
+		return axienet_get_ts_config(lp, rq);
+#endif
+#ifdef CONFIG_XILINX_TSN_QBV
+	case SIOCCHIOCTL:
+		return axienet_set_schedule(dev, rq->ifr_data);
+	case SIOC_GET_SCHED:
+		return axienet_get_schedule(dev, rq->ifr_data);
+#endif
+#ifdef CONFIG_XILINX_TSN_QBR
+	case SIOC_PREEMPTION_CFG:
+		return axienet_preemption(dev, rq->ifr_data);
+	case SIOC_PREEMPTION_CTRL:
+		return axienet_preemption_ctrl(dev, rq->ifr_data);
+	case SIOC_PREEMPTION_STS:
+		return axienet_preemption_sts(dev, rq->ifr_data);
+	case SIOC_PREEMPTION_COUNTER:
+		return axienet_preemption_cnt(dev, rq->ifr_data);
+#ifdef CONFIG_XILINX_TSN_QBV
+	case SIOC_QBU_USER_OVERRIDE:
+		return axienet_qbu_user_override(dev, rq->ifr_data);
+	case SIOC_QBU_STS:
+		return axienet_qbu_sts(dev, rq->ifr_data);
+#endif
+#endif
+
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
 static const struct net_device_ops axienet_netdev_ops = {
 	.ndo_open = axienet_open,
 	.ndo_stop = axienet_stop,
@@ -1091,6 +2315,7 @@
 	.ndo_set_mac_address = netdev_set_mac_address,
 	.ndo_validate_addr = eth_validate_addr,
 	.ndo_set_rx_mode = axienet_set_multicast_list,
+	.ndo_do_ioctl = axienet_ioctl,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller = axienet_poll_controller,
 #endif
@@ -1139,7 +2364,7 @@
 static void axienet_ethtools_get_regs(struct net_device *ndev,
 				      struct ethtool_regs *regs, void *ret)
 {
-	u32 *data = (u32 *) ret;
+	u32 *data = (u32 *)ret;
 	size_t len = sizeof(u32) * AXIENET_REGS_N;
 	struct axienet_local *lp = netdev_priv(ndev);
 
@@ -1165,28 +2390,29 @@
 	data[15] = axienet_ior(lp, XAE_TC_OFFSET);
 	data[16] = axienet_ior(lp, XAE_FCC_OFFSET);
 	data[17] = axienet_ior(lp, XAE_EMMC_OFFSET);
-	data[18] = axienet_ior(lp, XAE_PHYC_OFFSET);
+	data[18] = axienet_ior(lp, XAE_RMFC_OFFSET);
 	data[19] = axienet_ior(lp, XAE_MDIO_MC_OFFSET);
 	data[20] = axienet_ior(lp, XAE_MDIO_MCR_OFFSET);
 	data[21] = axienet_ior(lp, XAE_MDIO_MWD_OFFSET);
 	data[22] = axienet_ior(lp, XAE_MDIO_MRD_OFFSET);
-	data[23] = axienet_ior(lp, XAE_MDIO_MIS_OFFSET);
-	data[24] = axienet_ior(lp, XAE_MDIO_MIP_OFFSET);
-	data[25] = axienet_ior(lp, XAE_MDIO_MIE_OFFSET);
-	data[26] = axienet_ior(lp, XAE_MDIO_MIC_OFFSET);
+	data[23] = axienet_ior(lp, XAE_TEMAC_IS_OFFSET);
+	data[24] = axienet_ior(lp, XAE_TEMAC_IP_OFFSET);
+	data[25] = axienet_ior(lp, XAE_TEMAC_IE_OFFSET);
+	data[26] = axienet_ior(lp, XAE_TEMAC_IC_OFFSET);
 	data[27] = axienet_ior(lp, XAE_UAW0_OFFSET);
 	data[28] = axienet_ior(lp, XAE_UAW1_OFFSET);
-	data[29] = axienet_ior(lp, XAE_FMI_OFFSET);
+	data[29] = axienet_ior(lp, XAE_FMC_OFFSET);
 	data[30] = axienet_ior(lp, XAE_AF0_OFFSET);
 	data[31] = axienet_ior(lp, XAE_AF1_OFFSET);
-	data[32] = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
-	data[33] = axienet_dma_in32(lp, XAXIDMA_TX_SR_OFFSET);
-	data[34] = axienet_dma_in32(lp, XAXIDMA_TX_CDESC_OFFSET);
-	data[35] = axienet_dma_in32(lp, XAXIDMA_TX_TDESC_OFFSET);
-	data[36] = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
-	data[37] = axienet_dma_in32(lp, XAXIDMA_RX_SR_OFFSET);
-	data[38] = axienet_dma_in32(lp, XAXIDMA_RX_CDESC_OFFSET);
-	data[39] = axienet_dma_in32(lp, XAXIDMA_RX_TDESC_OFFSET);
+	/* Support only single DMA queue */
+	data[32] = axienet_dma_in32(lp->dq[0], XAXIDMA_TX_CR_OFFSET);
+	data[33] = axienet_dma_in32(lp->dq[0], XAXIDMA_TX_SR_OFFSET);
+	data[34] = axienet_dma_in32(lp->dq[0], XAXIDMA_TX_CDESC_OFFSET);
+	data[35] = axienet_dma_in32(lp->dq[0], XAXIDMA_TX_TDESC_OFFSET);
+	data[36] = axienet_dma_in32(lp->dq[0], XAXIDMA_RX_CR_OFFSET);
+	data[37] = axienet_dma_in32(lp->dq[0], XAXIDMA_RX_SR_OFFSET);
+	data[38] = axienet_dma_in32(lp->dq[0], XAXIDMA_RX_CDESC_OFFSET);
+	data[39] = axienet_dma_in32(lp->dq[0], XAXIDMA_RX_TDESC_OFFSET);
 }
 
 static void axienet_ethtools_get_ringparam(struct net_device *ndev,
@@ -1212,7 +2438,8 @@
 	if (ering->rx_pending > RX_BD_NUM_MAX ||
 	    ering->rx_mini_pending ||
 	    ering->rx_jumbo_pending ||
-	    ering->rx_pending > TX_BD_NUM_MAX)
+	    ering->tx_pending < TX_BD_NUM_MIN ||
+	    ering->tx_pending > TX_BD_NUM_MAX)
 		return -EINVAL;
 
 	if (netif_running(ndev))
@@ -1236,16 +2463,20 @@
 axienet_ethtools_get_pauseparam(struct net_device *ndev,
 				struct ethtool_pauseparam *epauseparm)
 {
+	u32 regval;
 	struct axienet_local *lp = netdev_priv(ndev);
 
-	phylink_ethtool_get_pauseparam(lp->phylink, epauseparm);
+	epauseparm->autoneg  = 0;
+	regval = axienet_ior(lp, XAE_FCC_OFFSET);
+	epauseparm->tx_pause = regval & XAE_FCC_FCTX_MASK;
+	epauseparm->rx_pause = regval & XAE_FCC_FCRX_MASK;
 }
 
 /**
  * axienet_ethtools_set_pauseparam - Set device pause parameter(flow control)
  *				     settings.
  * @ndev:	Pointer to net_device structure
- * @epauseparm:Pointer to ethtool_pauseparam structure
+ * @epauseparm:	Pointer to ethtool_pauseparam structure
  *
  * This implements ethtool command for enabling flow control on Rx and Tx
  * paths. Issue "ethtool -A ethX tx on|off" under linux prompt to execute this
@@ -1257,9 +2488,27 @@
 axienet_ethtools_set_pauseparam(struct net_device *ndev,
 				struct ethtool_pauseparam *epauseparm)
 {
+	u32 regval = 0;
 	struct axienet_local *lp = netdev_priv(ndev);
 
-	return phylink_ethtool_set_pauseparam(lp->phylink, epauseparm);
+	if (netif_running(ndev)) {
+		netdev_err(ndev,
+			   "Please stop netif before applying configuration\n");
+		return -EFAULT;
+	}
+
+	regval = axienet_ior(lp, XAE_FCC_OFFSET);
+	if (epauseparm->tx_pause)
+		regval |= XAE_FCC_FCTX_MASK;
+	else
+		regval &= ~XAE_FCC_FCTX_MASK;
+	if (epauseparm->rx_pause)
+		regval |= XAE_FCC_FCRX_MASK;
+	else
+		regval &= ~XAE_FCC_FCRX_MASK;
+	axienet_iow(lp, XAE_FCC_OFFSET, regval);
+
+	return 0;
 }
 
 /**
@@ -1278,12 +2527,24 @@
 {
 	u32 regval = 0;
 	struct axienet_local *lp = netdev_priv(ndev);
-	regval = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
-	ecoalesce->rx_max_coalesced_frames = (regval & XAXIDMA_COALESCE_MASK)
-					     >> XAXIDMA_COALESCE_SHIFT;
-	regval = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
-	ecoalesce->tx_max_coalesced_frames = (regval & XAXIDMA_COALESCE_MASK)
-					     >> XAXIDMA_COALESCE_SHIFT;
+	struct axienet_dma_q *q;
+	int i;
+
+	for_each_rx_dma_queue(lp, i) {
+		q = lp->dq[i];
+
+		regval = axienet_dma_in32(q, XAXIDMA_RX_CR_OFFSET);
+		ecoalesce->rx_max_coalesced_frames +=
+						(regval & XAXIDMA_COALESCE_MASK)
+						     >> XAXIDMA_COALESCE_SHIFT;
+	}
+	for_each_tx_dma_queue(lp, i) {
+		q = lp->dq[i];
+		regval = axienet_dma_in32(q, XAXIDMA_TX_CR_OFFSET);
+		ecoalesce->tx_max_coalesced_frames +=
+						(regval & XAXIDMA_COALESCE_MASK)
+						     >> XAXIDMA_COALESCE_SHIFT;
+	}
 	return 0;
 }
 
@@ -1338,23 +2599,33 @@
 	return 0;
 }
 
-static int
-axienet_ethtools_get_link_ksettings(struct net_device *ndev,
-				    struct ethtool_link_ksettings *cmd)
+#if defined(CONFIG_XILINX_AXI_EMAC_HWTSTAMP) || defined(CONFIG_XILINX_TSN_PTP)
+/**
+ * axienet_ethtools_get_ts_info - Get h/w timestamping capabilities.
+ * @ndev:	Pointer to net_device structure
+ * @info:	Pointer to ethtool_ts_info structure
+ *
+ * Return: 0, on success, Non-zero error value on failure.
+ */
+static int axienet_ethtools_get_ts_info(struct net_device *ndev,
+					struct ethtool_ts_info *info)
 {
 	struct axienet_local *lp = netdev_priv(ndev);
 
-	return phylink_ethtool_ksettings_get(lp->phylink, cmd);
-}
-
-static int
-axienet_ethtools_set_link_ksettings(struct net_device *ndev,
-				    const struct ethtool_link_ksettings *cmd)
-{
-	struct axienet_local *lp = netdev_priv(ndev);
+	info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE |
+				SOF_TIMESTAMPING_RX_HARDWARE |
+				SOF_TIMESTAMPING_RAW_HARDWARE;
+	info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON);
+	info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
+			   (1 << HWTSTAMP_FILTER_ALL);
+	info->phc_index = lp->phc_index;
 
-	return phylink_ethtool_ksettings_set(lp->phylink, cmd);
+#ifdef CONFIG_XILINX_TSN_PTP
+	info->phc_index = axienet_phc_index;
+#endif
+	return 0;
 }
+#endif
 
 static const struct ethtool_ops axienet_ethtool_ops = {
 	.get_drvinfo    = axienet_ethtools_get_drvinfo,
@@ -1362,277 +2633,488 @@
 	.get_regs       = axienet_ethtools_get_regs,
 	.get_link       = ethtool_op_get_link,
 	.get_ringparam	= axienet_ethtools_get_ringparam,
-	.set_ringparam	= axienet_ethtools_set_ringparam,
+	.set_ringparam  = axienet_ethtools_set_ringparam,
 	.get_pauseparam = axienet_ethtools_get_pauseparam,
 	.set_pauseparam = axienet_ethtools_set_pauseparam,
 	.get_coalesce   = axienet_ethtools_get_coalesce,
 	.set_coalesce   = axienet_ethtools_set_coalesce,
-	.get_link_ksettings = axienet_ethtools_get_link_ksettings,
-	.set_link_ksettings = axienet_ethtools_set_link_ksettings,
+#if defined(CONFIG_XILINX_AXI_EMAC_HWTSTAMP) || defined(CONFIG_XILINX_TSN_PTP)
+	.get_ts_info    = axienet_ethtools_get_ts_info,
+#endif
+	.get_link_ksettings = phy_ethtool_get_link_ksettings,
+	.set_link_ksettings = phy_ethtool_set_link_ksettings,
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+	.get_sset_count	 = axienet_sset_count,
+	.get_ethtool_stats = axienet_get_stats,
+	.get_strings = axienet_strings,
+#endif
 };
 
-static void axienet_validate(struct phylink_config *config,
-			     unsigned long *supported,
-			     struct phylink_link_state *state)
-{
-	struct net_device *ndev = to_net_dev(config->dev);
-	struct axienet_local *lp = netdev_priv(ndev);
-	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
-
-	/* Only support the mode we are configured for */
-	if (state->interface != PHY_INTERFACE_MODE_NA &&
-	    state->interface != lp->phy_mode) {
-		netdev_warn(ndev, "Cannot use PHY mode %s, supported: %s\n",
-			    phy_modes(state->interface),
-			    phy_modes(lp->phy_mode));
-		bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
-		return;
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+static int __maybe_unused axienet_mcdma_probe(struct platform_device *pdev,
+					      struct axienet_local *lp,
+					      struct net_device *ndev)
+{
+	int i, ret = 0;
+	struct axienet_dma_q *q;
+	struct device_node *np;
+	struct resource dmares;
+	const char *str;
+
+	ret = of_property_count_strings(pdev->dev.of_node, "xlnx,channel-ids");
+	if (ret < 0)
+		return -EINVAL;
+
+	for_each_rx_dma_queue(lp, i) {
+		q = kzalloc(sizeof(*q), GFP_KERNEL);
+
+		/* parent */
+		q->lp = lp;
+		lp->dq[i] = q;
+		ret = of_property_read_string_index(pdev->dev.of_node,
+						    "xlnx,channel-ids", i,
+						    &str);
+		ret = kstrtou16(str, 16, &q->chan_id);
+		lp->qnum[i] = i;
+		lp->chan_num[i] = q->chan_id;
+	}
+
+	np = of_parse_phandle(pdev->dev.of_node, "axistream-connected",
+			      0);
+	if (IS_ERR(np)) {
+		dev_err(&pdev->dev, "could not find DMA node\n");
+		return ret;
 	}
 
-	phylink_set(mask, Autoneg);
-	phylink_set_port_modes(mask);
+	ret = of_address_to_resource(np, 0, &dmares);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to get DMA resource\n");
+		return ret;
+	}
+
+	ret = of_property_read_u8(np, "xlnx,addrwidth", (u8 *)&lp->dma_mask);
+	if (ret < 0 || lp->dma_mask < XAE_DMA_MASK_MIN ||
+	    lp->dma_mask > XAE_DMA_MASK_MAX) {
+		dev_info(&pdev->dev, "missing/invalid xlnx,addrwidth property, using default\n");
+		lp->dma_mask = XAE_DMA_MASK_MIN;
+	}
+
+	lp->mcdma_regs = devm_ioremap_resource(&pdev->dev, &dmares);
+	if (IS_ERR(lp->mcdma_regs)) {
+		dev_err(&pdev->dev, "iormeap failed for the dma\n");
+		ret = PTR_ERR(lp->mcdma_regs);
+		return ret;
+	}
 
-	phylink_set(mask, Asym_Pause);
-	phylink_set(mask, Pause);
-	phylink_set(mask, 1000baseX_Full);
-	phylink_set(mask, 10baseT_Full);
-	phylink_set(mask, 100baseT_Full);
-	phylink_set(mask, 1000baseT_Full);
+	axienet_mcdma_tx_probe(pdev, np, lp);
+	axienet_mcdma_rx_probe(pdev, lp, ndev);
 
-	bitmap_and(supported, supported, mask,
-		   __ETHTOOL_LINK_MODE_MASK_NBITS);
-	bitmap_and(state->advertising, state->advertising, mask,
-		   __ETHTOOL_LINK_MODE_MASK_NBITS);
+	return 0;
 }
+#endif
 
-static int axienet_mac_link_state(struct phylink_config *config,
-				  struct phylink_link_state *state)
+static int __maybe_unused axienet_dma_probe(struct platform_device *pdev,
+					    struct net_device *ndev)
 {
-	struct net_device *ndev = to_net_dev(config->dev);
+	int i, ret;
 	struct axienet_local *lp = netdev_priv(ndev);
-	u32 emmc_reg, fcc_reg;
+	struct axienet_dma_q *q;
+	struct device_node *np = NULL;
+	struct resource dmares;
+#ifdef CONFIG_XILINX_TSN
+	char dma_name[10];
+#endif
 
-	state->interface = lp->phy_mode;
+	for_each_rx_dma_queue(lp, i) {
+		q = kzalloc(sizeof(*q), GFP_KERNEL);
 
-	emmc_reg = axienet_ior(lp, XAE_EMMC_OFFSET);
-	if (emmc_reg & XAE_EMMC_LINKSPD_1000)
-		state->speed = SPEED_1000;
-	else if (emmc_reg & XAE_EMMC_LINKSPD_100)
-		state->speed = SPEED_100;
-	else
-		state->speed = SPEED_10;
+		/* parent */
+		q->lp = lp;
+
+		lp->dq[i] = q;
+	}
 
-	state->pause = 0;
-	fcc_reg = axienet_ior(lp, XAE_FCC_OFFSET);
-	if (fcc_reg & XAE_FCC_FCTX_MASK)
-		state->pause |= MLO_PAUSE_TX;
-	if (fcc_reg & XAE_FCC_FCRX_MASK)
-		state->pause |= MLO_PAUSE_RX;
+	/* Find the DMA node, map the DMA registers, and decode the DMA IRQs */
+	/* TODO handle error ret */
+	for_each_rx_dma_queue(lp, i) {
+		q = lp->dq[i];
+
+		np = of_parse_phandle(pdev->dev.of_node, "axistream-connected",
+				      i);
+		if (np) {
+			ret = of_address_to_resource(np, 0, &dmares);
+			if (ret >= 0) {
+				q->dma_regs = devm_ioremap_resource(&pdev->dev,
+								    &dmares);
+			} else {
+				dev_err(&pdev->dev, "unable to get DMA resource for %pOF\n",
+					np);
+				return -ENODEV;
+			}
+			q->eth_hasdre = of_property_read_bool(np,
+							      "xlnx,include-dre");
+			ret = of_property_read_u8(np, "xlnx,addrwidth",
+						  (u8 *)&lp->dma_mask);
+			if (ret <  0 || lp->dma_mask < XAE_DMA_MASK_MIN ||
+			    lp->dma_mask > XAE_DMA_MASK_MAX) {
+				dev_info(&pdev->dev, "missing/invalid xlnx,addrwidth property, using default\n");
+				lp->dma_mask = XAE_DMA_MASK_MIN;
+			}
+
+		} else {
+			dev_err(&pdev->dev, "missing axistream-connected property\n");
+			return -EINVAL;
+		}
+	}
+
+#ifdef CONFIG_XILINX_TSN
+	if (lp->is_tsn) {
+		for_each_rx_dma_queue(lp, i) {
+			sprintf(dma_name, "dma%d_tx", i);
+			lp->dq[i]->tx_irq = platform_get_irq_byname(pdev,
+								    dma_name);
+			sprintf(dma_name, "dma%d_rx", i);
+			lp->dq[i]->rx_irq = platform_get_irq_byname(pdev,
+								    dma_name);
+			pr_info("lp->dq[%d]->tx_irq  %d\n", i,
+				lp->dq[i]->tx_irq);
+			pr_info("lp->dq[%d]->rx_irq  %d\n", i,
+				lp->dq[i]->rx_irq);
+		}
+	} else {
+#endif /* This should remove when axienet device tree irq comply to dma name */
+		for_each_rx_dma_queue(lp, i) {
+			lp->dq[i]->tx_irq = irq_of_parse_and_map(np, 0);
+			lp->dq[i]->rx_irq = irq_of_parse_and_map(np, 1);
+		}
+#ifdef CONFIG_XILINX_TSN
+	}
+#endif
+
+	of_node_put(np);
 
-	state->an_complete = 0;
-	state->duplex = 1;
+	for_each_rx_dma_queue(lp, i) {
+		struct axienet_dma_q *q = lp->dq[i];
 
-	return 1;
+		spin_lock_init(&q->tx_lock);
+		spin_lock_init(&q->rx_lock);
+	}
+
+	for_each_rx_dma_queue(lp, i) {
+		netif_napi_add(ndev, &lp->napi[i], xaxienet_rx_poll,
+			       XAXIENET_NAPI_WEIGHT);
+	}
+
+	return 0;
 }
 
-static void axienet_mac_an_restart(struct phylink_config *config)
+static int axienet_clk_init(struct platform_device *pdev,
+			    struct clk **axi_aclk, struct clk **axis_clk,
+			    struct clk **ref_clk, struct clk **tmpclk)
 {
-	/* Unsupported, do nothing */
+	int err;
+
+	*tmpclk = NULL;
+
+	/* The "ethernet_clk" is deprecated and will be removed sometime in
+	 * the future. For proper clock usage check axiethernet binding
+	 * documentation.
+	 */
+	*axi_aclk = devm_clk_get(&pdev->dev, "ethernet_clk");
+	if (IS_ERR(*axi_aclk)) {
+		if (PTR_ERR(*axi_aclk) != -ENOENT) {
+			err = PTR_ERR(*axi_aclk);
+			return err;
+		}
+
+		*axi_aclk = devm_clk_get(&pdev->dev, "s_axi_lite_clk");
+		if (IS_ERR(*axi_aclk)) {
+			if (PTR_ERR(*axi_aclk) != -ENOENT) {
+				err = PTR_ERR(*axi_aclk);
+				return err;
+			}
+			*axi_aclk = NULL;
+		}
+
+	} else {
+		dev_warn(&pdev->dev, "ethernet_clk is deprecated and will be removed sometime in the future\n");
+	}
+
+	*axis_clk = devm_clk_get(&pdev->dev, "axis_clk");
+	if (IS_ERR(*axis_clk)) {
+		if (PTR_ERR(*axis_clk) != -ENOENT) {
+			err = PTR_ERR(*axis_clk);
+			return err;
+		}
+		*axis_clk = NULL;
+	}
+
+	*ref_clk = devm_clk_get(&pdev->dev, "ref_clk");
+	if (IS_ERR(*ref_clk)) {
+		if (PTR_ERR(*ref_clk) != -ENOENT) {
+			err = PTR_ERR(*ref_clk);
+			return err;
+		}
+		*ref_clk = NULL;
+	}
+
+	err = clk_prepare_enable(*axi_aclk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable axi_aclk/ethernet_clk (%d)\n", err);
+		return err;
+	}
+
+	err = clk_prepare_enable(*axis_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable axis_clk (%d)\n", err);
+		goto err_disable_axi_aclk;
+	}
+
+	err = clk_prepare_enable(*ref_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable ref_clk (%d)\n", err);
+		goto err_disable_axis_clk;
+	}
+
+	return 0;
+
+err_disable_axis_clk:
+	clk_disable_unprepare(*axis_clk);
+err_disable_axi_aclk:
+	clk_disable_unprepare(*axi_aclk);
+
+	return err;
 }
 
-static void axienet_mac_config(struct phylink_config *config, unsigned int mode,
-			       const struct phylink_link_state *state)
+static int axienet_dma_clk_init(struct platform_device *pdev)
 {
-	struct net_device *ndev = to_net_dev(config->dev);
+	int err;
+	struct net_device *ndev = platform_get_drvdata(pdev);
 	struct axienet_local *lp = netdev_priv(ndev);
-	u32 emmc_reg, fcc_reg;
 
-	emmc_reg = axienet_ior(lp, XAE_EMMC_OFFSET);
-	emmc_reg &= ~XAE_EMMC_LINKSPEED_MASK;
+	/* The "dma_clk" is deprecated and will be removed sometime in
+	 * the future. For proper clock usage check axiethernet binding
+	 * documentation.
+	 */
+	lp->dma_tx_clk = devm_clk_get(&pdev->dev, "dma_clk");
+	if (IS_ERR(lp->dma_tx_clk)) {
+		if (PTR_ERR(lp->dma_tx_clk) != -ENOENT) {
+			err = PTR_ERR(lp->dma_tx_clk);
+			return err;
+		}
 
-	switch (state->speed) {
-	case SPEED_1000:
-		emmc_reg |= XAE_EMMC_LINKSPD_1000;
-		break;
-	case SPEED_100:
-		emmc_reg |= XAE_EMMC_LINKSPD_100;
-		break;
-	case SPEED_10:
-		emmc_reg |= XAE_EMMC_LINKSPD_10;
-		break;
-	default:
-		dev_err(&ndev->dev,
-			"Speed other than 10, 100 or 1Gbps is not supported\n");
-		break;
+		lp->dma_tx_clk = devm_clk_get(&pdev->dev, "m_axi_mm2s_aclk");
+		if (IS_ERR(lp->dma_tx_clk)) {
+			if (PTR_ERR(lp->dma_tx_clk) != -ENOENT) {
+				err = PTR_ERR(lp->dma_tx_clk);
+				return err;
+			}
+			lp->dma_tx_clk = NULL;
+		}
+	} else {
+		dev_warn(&pdev->dev, "dma_clk is deprecated and will be removed sometime in the future\n");
 	}
 
-	axienet_iow(lp, XAE_EMMC_OFFSET, emmc_reg);
+	lp->dma_rx_clk = devm_clk_get(&pdev->dev, "m_axi_s2mm_aclk");
+	if (IS_ERR(lp->dma_rx_clk)) {
+		if (PTR_ERR(lp->dma_rx_clk) != -ENOENT) {
+			err = PTR_ERR(lp->dma_rx_clk);
+			return err;
+		}
+		lp->dma_rx_clk = NULL;
+	}
 
-	fcc_reg = axienet_ior(lp, XAE_FCC_OFFSET);
-	if (state->pause & MLO_PAUSE_TX)
-		fcc_reg |= XAE_FCC_FCTX_MASK;
-	else
-		fcc_reg &= ~XAE_FCC_FCTX_MASK;
-	if (state->pause & MLO_PAUSE_RX)
-		fcc_reg |= XAE_FCC_FCRX_MASK;
-	else
-		fcc_reg &= ~XAE_FCC_FCRX_MASK;
-	axienet_iow(lp, XAE_FCC_OFFSET, fcc_reg);
-}
+	lp->dma_sg_clk = devm_clk_get(&pdev->dev, "m_axi_sg_aclk");
+	if (IS_ERR(lp->dma_sg_clk)) {
+		if (PTR_ERR(lp->dma_sg_clk) != -ENOENT) {
+			err = PTR_ERR(lp->dma_sg_clk);
+			return err;
+		}
+		lp->dma_sg_clk = NULL;
+	}
 
-static void axienet_mac_link_down(struct phylink_config *config,
-				  unsigned int mode,
-				  phy_interface_t interface)
-{
-	/* nothing meaningful to do */
-}
+	err = clk_prepare_enable(lp->dma_tx_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable tx_clk/dma_clk (%d)\n", err);
+		return err;
+	}
 
-static void axienet_mac_link_up(struct phylink_config *config,
-				unsigned int mode,
-				phy_interface_t interface,
-				struct phy_device *phy)
-{
-	/* nothing meaningful to do */
-}
+	err = clk_prepare_enable(lp->dma_rx_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable rx_clk (%d)\n", err);
+		goto err_disable_txclk;
+	}
 
-static const struct phylink_mac_ops axienet_phylink_ops = {
-	.validate = axienet_validate,
-	.mac_link_state = axienet_mac_link_state,
-	.mac_an_restart = axienet_mac_an_restart,
-	.mac_config = axienet_mac_config,
-	.mac_link_down = axienet_mac_link_down,
-	.mac_link_up = axienet_mac_link_up,
-};
+	err = clk_prepare_enable(lp->dma_sg_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable sg_clk (%d)\n", err);
+		goto err_disable_rxclk;
+	}
 
-/**
- * axienet_dma_err_handler - Tasklet handler for Axi DMA Error
- * @data:	Data passed
- *
- * Resets the Axi DMA and Axi Ethernet devices, and reconfigures the
- * Tx/Rx BDs.
- */
-static void axienet_dma_err_handler(unsigned long data)
+	return 0;
+
+err_disable_rxclk:
+	clk_disable_unprepare(lp->dma_rx_clk);
+err_disable_txclk:
+	clk_disable_unprepare(lp->dma_tx_clk);
+
+	return err;
+}
+
+static void axienet_clk_disable(struct platform_device *pdev)
 {
-	u32 axienet_status;
-	u32 cr, i;
-	struct axienet_local *lp = (struct axienet_local *) data;
-	struct net_device *ndev = lp->ndev;
-	struct axidma_bd *cur_p;
+	struct net_device *ndev = platform_get_drvdata(pdev);
+	struct axienet_local *lp = netdev_priv(ndev);
 
-	axienet_setoptions(ndev, lp->options &
-			   ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN));
-	/* Disable the MDIO interface till Axi Ethernet Reset is completed.
-	 * When we do an Axi Ethernet reset, it resets the complete core
-	 * including the MDIO. MDIO must be disabled before resetting
-	 * and re-enabled afterwards.
-	 * Hold MDIO bus lock to avoid MDIO accesses during the reset.
+	clk_disable_unprepare(lp->dma_sg_clk);
+	clk_disable_unprepare(lp->dma_tx_clk);
+	clk_disable_unprepare(lp->dma_rx_clk);
+	clk_disable_unprepare(lp->eth_sclk);
+	clk_disable_unprepare(lp->eth_refclk);
+	clk_disable_unprepare(lp->eth_dclk);
+	clk_disable_unprepare(lp->aclk);
+}
+
+static int xxvenet_clk_init(struct platform_device *pdev,
+			    struct clk **axi_aclk, struct clk **axis_clk,
+			    struct clk **tmpclk, struct clk **dclk)
+{
+	int err;
+
+	*tmpclk = NULL;
+
+	/* The "ethernet_clk" is deprecated and will be removed sometime in
+	 * the future. For proper clock usage check axiethernet binding
+	 * documentation.
 	 */
-	mutex_lock(&lp->mii_bus->mdio_lock);
-	axienet_mdio_disable(lp);
-	__axienet_device_reset(lp);
-	axienet_mdio_enable(lp);
-	mutex_unlock(&lp->mii_bus->mdio_lock);
+	*axi_aclk = devm_clk_get(&pdev->dev, "ethernet_clk");
+	if (IS_ERR(*axi_aclk)) {
+		if (PTR_ERR(*axi_aclk) != -ENOENT) {
+			err = PTR_ERR(*axi_aclk);
+			return err;
+		}
 
-	for (i = 0; i < lp->tx_bd_num; i++) {
-		cur_p = &lp->tx_bd_v[i];
-		if (cur_p->phys)
-			dma_unmap_single(ndev->dev.parent, cur_p->phys,
-					 (cur_p->cntrl &
-					  XAXIDMA_BD_CTRL_LENGTH_MASK),
-					 DMA_TO_DEVICE);
-		if (cur_p->skb)
-			dev_kfree_skb_irq(cur_p->skb);
-		cur_p->phys = 0;
-		cur_p->cntrl = 0;
-		cur_p->status = 0;
-		cur_p->app0 = 0;
-		cur_p->app1 = 0;
-		cur_p->app2 = 0;
-		cur_p->app3 = 0;
-		cur_p->app4 = 0;
-		cur_p->skb = NULL;
+		*axi_aclk = devm_clk_get(&pdev->dev, "s_axi_aclk");
+		if (IS_ERR(*axi_aclk)) {
+			if (PTR_ERR(*axi_aclk) != -ENOENT) {
+				err = PTR_ERR(*axi_aclk);
+				return err;
+			}
+			*axi_aclk = NULL;
+		}
+
+	} else {
+		dev_warn(&pdev->dev, "ethernet_clk is deprecated and will be removed sometime in the future\n");
 	}
 
-	for (i = 0; i < lp->rx_bd_num; i++) {
-		cur_p = &lp->rx_bd_v[i];
-		cur_p->status = 0;
-		cur_p->app0 = 0;
-		cur_p->app1 = 0;
-		cur_p->app2 = 0;
-		cur_p->app3 = 0;
-		cur_p->app4 = 0;
+	*axis_clk = devm_clk_get(&pdev->dev, "rx_core_clk");
+	if (IS_ERR(*axis_clk)) {
+		if (PTR_ERR(*axis_clk) != -ENOENT) {
+			err = PTR_ERR(*axis_clk);
+			return err;
+		}
+		*axis_clk = NULL;
 	}
 
-	lp->tx_bd_ci = 0;
-	lp->tx_bd_tail = 0;
-	lp->rx_bd_ci = 0;
-
-	/* Start updating the Rx channel control register */
-	cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
-	/* Update the interrupt coalesce count */
-	cr = ((cr & ~XAXIDMA_COALESCE_MASK) |
-	      (XAXIDMA_DFT_RX_THRESHOLD << XAXIDMA_COALESCE_SHIFT));
-	/* Update the delay timer count */
-	cr = ((cr & ~XAXIDMA_DELAY_MASK) |
-	      (XAXIDMA_DFT_RX_WAITBOUND << XAXIDMA_DELAY_SHIFT));
-	/* Enable coalesce, delay timer and error interrupts */
-	cr |= XAXIDMA_IRQ_ALL_MASK;
-	/* Finally write to the Rx channel control register */
-	axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, cr);
-
-	/* Start updating the Tx channel control register */
-	cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
-	/* Update the interrupt coalesce count */
-	cr = (((cr & ~XAXIDMA_COALESCE_MASK)) |
-	      (XAXIDMA_DFT_TX_THRESHOLD << XAXIDMA_COALESCE_SHIFT));
-	/* Update the delay timer count */
-	cr = (((cr & ~XAXIDMA_DELAY_MASK)) |
-	      (XAXIDMA_DFT_TX_WAITBOUND << XAXIDMA_DELAY_SHIFT));
-	/* Enable coalesce, delay timer and error interrupts */
-	cr |= XAXIDMA_IRQ_ALL_MASK;
-	/* Finally write to the Tx channel control register */
-	axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, cr);
+	*dclk = devm_clk_get(&pdev->dev, "dclk");
+	if (IS_ERR(*dclk)) {
+		if (PTR_ERR(*dclk) != -ENOENT) {
+			err = PTR_ERR(*dclk);
+			return err;
+		}
+		*dclk = NULL;
+	}
 
-	/* Populate the tail pointer and bring the Rx Axi DMA engine out of
-	 * halted state. This will make the Rx side ready for reception.
-	 */
-	axienet_dma_out32(lp, XAXIDMA_RX_CDESC_OFFSET, lp->rx_bd_p);
-	cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET);
-	axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET,
-			  cr | XAXIDMA_CR_RUNSTOP_MASK);
-	axienet_dma_out32(lp, XAXIDMA_RX_TDESC_OFFSET, lp->rx_bd_p +
-			  (sizeof(*lp->rx_bd_v) * (lp->rx_bd_num - 1)));
-
-	/* Write to the RS (Run-stop) bit in the Tx channel control register.
-	 * Tx channel is now ready to run. But only after we write to the
-	 * tail pointer register that the Tx channel will start transmitting
-	 */
-	axienet_dma_out32(lp, XAXIDMA_TX_CDESC_OFFSET, lp->tx_bd_p);
-	cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET);
-	axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET,
-			  cr | XAXIDMA_CR_RUNSTOP_MASK);
-
-	axienet_status = axienet_ior(lp, XAE_RCW1_OFFSET);
-	axienet_status &= ~XAE_RCW1_RX_MASK;
-	axienet_iow(lp, XAE_RCW1_OFFSET, axienet_status);
-
-	axienet_status = axienet_ior(lp, XAE_IP_OFFSET);
-	if (axienet_status & XAE_INT_RXRJECT_MASK)
-		axienet_iow(lp, XAE_IS_OFFSET, XAE_INT_RXRJECT_MASK);
-	axienet_iow(lp, XAE_IE_OFFSET, lp->eth_irq > 0 ?
-		    XAE_INT_RECV_ERROR_MASK : 0);
-	axienet_iow(lp, XAE_FCC_OFFSET, XAE_FCC_FCRX_MASK);
+	err = clk_prepare_enable(*axi_aclk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable axi_clk/ethernet_clk (%d)\n", err);
+		return err;
+	}
 
-	/* Sync default options with HW but leave receiver and
-	 * transmitter disabled.
-	 */
-	axienet_setoptions(ndev, lp->options &
-			   ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN));
-	axienet_set_mac_address(ndev, NULL);
-	axienet_set_multicast_list(ndev);
-	axienet_setoptions(ndev, lp->options);
+	err = clk_prepare_enable(*axis_clk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable axis_clk (%d)\n", err);
+		goto err_disable_axi_aclk;
+	}
+
+	err = clk_prepare_enable(*dclk);
+	if (err) {
+		dev_err(&pdev->dev, "failed to enable dclk (%d)\n", err);
+		goto err_disable_axis_clk;
+	}
+
+	return 0;
+
+err_disable_axis_clk:
+	clk_disable_unprepare(*axis_clk);
+err_disable_axi_aclk:
+	clk_disable_unprepare(*axi_aclk);
+
+	return err;
 }
 
+static const struct axienet_config axienet_1g_config = {
+	.mactype = XAXIENET_1G,
+	.setoptions = axienet_setoptions,
+	.clk_init = axienet_clk_init,
+	.tx_ptplen = XAE_TX_PTP_LEN,
+};
+
+static const struct axienet_config axienet_2_5g_config = {
+	.mactype = XAXIENET_2_5G,
+	.setoptions = axienet_setoptions,
+	.clk_init = axienet_clk_init,
+	.tx_ptplen = XAE_TX_PTP_LEN,
+};
+
+static const struct axienet_config axienet_10g_config = {
+	.mactype = XAXIENET_LEGACY_10G,
+	.setoptions = axienet_setoptions,
+	.clk_init = xxvenet_clk_init,
+	.tx_ptplen = XAE_TX_PTP_LEN,
+};
+
+static const struct axienet_config axienet_10g25g_config = {
+	.mactype = XAXIENET_10G_25G,
+	.setoptions = xxvenet_setoptions,
+	.clk_init = xxvenet_clk_init,
+	.tx_ptplen = XXV_TX_PTP_LEN,
+};
+
+static const struct axienet_config axienet_usxgmii_config = {
+	.mactype = XAXIENET_10G_25G,
+	.setoptions = xxvenet_setoptions,
+	.clk_init = xxvenet_clk_init,
+	.tx_ptplen = 0,
+};
+
+static const struct axienet_config axienet_mrmac_config = {
+	.mactype = XAXIENET_MRMAC,
+	.setoptions = xxvenet_setoptions,
+	.clk_init = xxvenet_clk_init,
+	.tx_ptplen = 0,
+};
+
+/* Match table for of_platform binding */
+static const struct of_device_id axienet_of_match[] = {
+	{ .compatible = "xlnx,axi-ethernet-1.00.a", .data = &axienet_1g_config},
+	{ .compatible = "xlnx,axi-ethernet-1.01.a", .data = &axienet_1g_config},
+	{ .compatible = "xlnx,axi-ethernet-2.01.a", .data = &axienet_1g_config},
+	{ .compatible = "xlnx,axi-2_5-gig-ethernet-1.0",
+						.data = &axienet_2_5g_config},
+	{ .compatible = "xlnx,ten-gig-eth-mac", .data = &axienet_10g_config},
+	{ .compatible = "xlnx,xxv-ethernet-1.0",
+						.data = &axienet_10g25g_config},
+	{ .compatible = "xlnx,tsn-ethernet-1.00.a", .data = &axienet_1g_config},
+	{ .compatible = "xlnx,xxv-usxgmii-ethernet-1.0",
+					.data = &axienet_usxgmii_config},
+	{ .compatible = "xlnx,mrmac-ethernet-1.0",
+					.data = &axienet_mrmac_config},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, axienet_of_match);
+
 /**
  * axienet_probe - Axi Ethernet probe function.
  * @pdev:	Pointer to platform device structure.
@@ -1647,15 +3129,38 @@
  */
 static int axienet_probe(struct platform_device *pdev)
 {
-	int ret;
+	int (*axienet_clk_init)(struct platform_device *pdev,
+				struct clk **axi_aclk, struct clk **axis_clk,
+				struct clk **ref_clk, struct clk **tmpclk) =
+					axienet_clk_init;
+	int ret = 0;
 	struct device_node *np;
 	struct axienet_local *lp;
 	struct net_device *ndev;
 	const void *mac_addr;
 	struct resource *ethres;
 	u32 value;
+	u16 num_queues = XAE_MAX_QUEUES;
+	bool slave = false;
+	bool is_tsn = false;
+
+	is_tsn = of_property_read_bool(pdev->dev.of_node, "xlnx,tsn");
+	ret = of_property_read_u16(pdev->dev.of_node, "xlnx,num-queues",
+				   &num_queues);
+	if (ret) {
+		if (!is_tsn) {
+#ifndef CONFIG_AXIENET_HAS_MCDMA
+			num_queues = 1;
+#endif
+		}
+	}
+#ifdef CONFIG_XILINX_TSN
+	if (is_tsn && (num_queues < XAE_TSN_MIN_QUEUES ||
+		       num_queues > XAE_MAX_QUEUES))
+		num_queues = XAE_MAX_QUEUES;
+#endif
 
-	ndev = alloc_etherdev(sizeof(*lp));
+	ndev = alloc_etherdev_mq(sizeof(*lp), num_queues);
 	if (!ndev)
 		return -ENOMEM;
 
@@ -1675,37 +3180,77 @@
 	lp->ndev = ndev;
 	lp->dev = &pdev->dev;
 	lp->options = XAE_OPTION_DEFAULTS;
+	lp->num_tx_queues = num_queues;
+	lp->num_rx_queues = num_queues;
+	lp->is_tsn = is_tsn;
 	lp->rx_bd_num = RX_BD_NUM_DEFAULT;
 	lp->tx_bd_num = TX_BD_NUM_DEFAULT;
+
+	lp->clk = devm_clk_get_optional(&pdev->dev, NULL);
+	if (IS_ERR(lp->clk)) {
+		ret = PTR_ERR(lp->clk);
+		goto free_netdev;
+	}
+	ret = clk_prepare_enable(lp->clk);
+	if (ret) {
+		dev_err(&pdev->dev, "Unable to enable clock: %d\n", ret);
+		goto free_netdev;
+	}
+#ifdef CONFIG_XILINX_TSN
+	ret = of_property_read_u16(pdev->dev.of_node, "xlnx,num-tc",
+				   &lp->num_tc);
+	if (ret || (lp->num_tc != 2 && lp->num_tc != 3))
+		lp->num_tc = XAE_MAX_TSN_TC;
+#endif
+
 	/* Map device registers */
 	ethres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	lp->regs = devm_ioremap_resource(&pdev->dev, ethres);
 	if (IS_ERR(lp->regs)) {
-		dev_err(&pdev->dev, "could not map Axi Ethernet regs.\n");
 		ret = PTR_ERR(lp->regs);
 		goto free_netdev;
 	}
+#ifdef CONFIG_XILINX_TSN
+	slave = of_property_read_bool(pdev->dev.of_node,
+				      "xlnx,tsn-slave");
+	if (slave)
+		lp->temac_no = XAE_TEMAC2;
+	else
+		lp->temac_no = XAE_TEMAC1;
+#endif
 	lp->regs_start = ethres->start;
 
 	/* Setup checksum offload, but default to off if not specified */
 	lp->features = 0;
 
+	if (pdev->dev.of_node) {
+		const struct of_device_id *match;
+
+		match = of_match_node(axienet_of_match, pdev->dev.of_node);
+		if (match && match->data) {
+			lp->axienet_config = match->data;
+			axienet_clk_init = lp->axienet_config->clk_init;
+		}
+	}
+
 	ret = of_property_read_u32(pdev->dev.of_node, "xlnx,txcsum", &value);
 	if (!ret) {
+		dev_info(&pdev->dev, "TX_CSUM %d\n", value);
+
 		switch (value) {
 		case 1:
 			lp->csum_offload_on_tx_path =
 				XAE_FEATURE_PARTIAL_TX_CSUM;
 			lp->features |= XAE_FEATURE_PARTIAL_TX_CSUM;
 			/* Can checksum TCP/UDP over IPv4. */
-			ndev->features |= NETIF_F_IP_CSUM;
+			ndev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
 			break;
 		case 2:
 			lp->csum_offload_on_tx_path =
 				XAE_FEATURE_FULL_TX_CSUM;
 			lp->features |= XAE_FEATURE_FULL_TX_CSUM;
 			/* Can checksum TCP/UDP over IPv4. */
-			ndev->features |= NETIF_F_IP_CSUM;
+			ndev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
 			break;
 		default:
 			lp->csum_offload_on_tx_path = XAE_NO_CSUM_OFFLOAD;
@@ -1713,6 +3258,8 @@
 	}
 	ret = of_property_read_u32(pdev->dev.of_node, "xlnx,rxcsum", &value);
 	if (!ret) {
+		dev_info(&pdev->dev, "RX_CSUM %d\n", value);
+
 		switch (value) {
 		case 1:
 			lp->csum_offload_on_rx_path =
@@ -1736,80 +3283,205 @@
 	 */
 	of_property_read_u32(pdev->dev.of_node, "xlnx,rxmem", &lp->rxmem);
 
-	/* Start with the proprietary, and broken phy_type */
-	ret = of_property_read_u32(pdev->dev.of_node, "xlnx,phy-type", &value);
-	if (!ret) {
-		netdev_warn(ndev, "Please upgrade your device tree binary blob to use phy-mode");
-		switch (value) {
-		case XAE_PHY_TYPE_MII:
-			lp->phy_mode = PHY_INTERFACE_MODE_MII;
-			break;
-		case XAE_PHY_TYPE_GMII:
-			lp->phy_mode = PHY_INTERFACE_MODE_GMII;
-			break;
-		case XAE_PHY_TYPE_RGMII_2_0:
-			lp->phy_mode = PHY_INTERFACE_MODE_RGMII_ID;
-			break;
-		case XAE_PHY_TYPE_SGMII:
-			lp->phy_mode = PHY_INTERFACE_MODE_SGMII;
-			break;
-		case XAE_PHY_TYPE_1000BASE_X:
-			lp->phy_mode = PHY_INTERFACE_MODE_1000BASEX;
-			break;
-		default:
-			ret = -EINVAL;
-			goto free_netdev;
+	/* The phy_mode is optional but when it is not specified it should not
+	 *  be a value that alters the driver behavior so set it to an invalid
+	 *  value as the default.
+	 */
+	lp->phy_mode = ~0;
+	of_property_read_u32(pdev->dev.of_node, "xlnx,phy-type", &lp->phy_mode);
+
+	/* Set default USXGMII rate */
+	lp->usxgmii_rate = SPEED_1000;
+	of_property_read_u32(pdev->dev.of_node, "xlnx,usxgmii-rate",
+			     &lp->usxgmii_rate);
+
+	/* Set default MRMAC rate */
+	lp->mrmac_rate = SPEED_10000;
+	of_property_read_u32(pdev->dev.of_node, "xlnx,mrmac-rate",
+			     &lp->mrmac_rate);
+
+	lp->eth_hasnobuf = of_property_read_bool(pdev->dev.of_node,
+						 "xlnx,eth-hasnobuf");
+	lp->eth_hasptp = of_property_read_bool(pdev->dev.of_node,
+					       "xlnx,eth-hasptp");
+
+	if ((lp->axienet_config->mactype == XAXIENET_1G) && !lp->eth_hasnobuf)
+		lp->eth_irq = platform_get_irq(pdev, 0);
+
+	if (lp->axienet_config->mactype == XAXIENET_MRMAC) {
+		struct resource gtpll, gtctrl;
+
+		if (mrmac_pll_reg) {
+			lp->gt_pll = mrmac_gt_pll;
+			lp->gt_ctrl = mrmac_gt_ctrl;
+		} else {
+			np = of_parse_phandle(pdev->dev.of_node,
+					      "xlnx,gtpll", 0);
+			if (IS_ERR(np)) {
+				dev_err(&pdev->dev,
+					"couldn't find GT PLL\n");
+				ret = PTR_ERR(np);
+				goto free_netdev;
+			}
+
+			ret = of_address_to_resource(np, 0, &gtpll);
+			if (ret) {
+				dev_err(&pdev->dev,
+					"unable to get GT PLL resource\n");
+				goto free_netdev;
+			}
+
+			lp->gt_pll = devm_ioremap_resource(&pdev->dev,
+							   &gtpll);
+			if (IS_ERR(lp->gt_pll)) {
+				dev_err(&pdev->dev,
+					"couldn't map GT PLL regs\n");
+				ret = PTR_ERR(lp->gt_pll);
+				goto free_netdev;
+			}
+
+			np = of_parse_phandle(pdev->dev.of_node,
+					      "xlnx,gtctrl", 0);
+			if (IS_ERR(np)) {
+				dev_err(&pdev->dev,
+					"couldn't find GT control\n");
+				ret = PTR_ERR(np);
+				goto free_netdev;
+			}
+
+			ret = of_address_to_resource(np, 0, &gtctrl);
+			if (ret) {
+				dev_err(&pdev->dev,
+					"unable to get GT control resource\n");
+				goto free_netdev;
+			}
+
+			lp->gt_ctrl = devm_ioremap_resource(&pdev->dev,
+							    &gtctrl);
+			if (IS_ERR(lp->gt_ctrl)) {
+				dev_err(&pdev->dev,
+					"couldn't map GT control regs\n");
+				ret = PTR_ERR(lp->gt_ctrl);
+				goto free_netdev;
+			}
+
+			mrmac_gt_pll = lp->gt_pll;
+			mrmac_gt_ctrl = lp->gt_ctrl;
+			mrmac_pll_reg = 1;
 		}
-	} else {
-		lp->phy_mode = of_get_phy_mode(pdev->dev.of_node);
-		if ((int)lp->phy_mode < 0) {
-			ret = -EINVAL;
+#ifdef CONFIG_XILINX_AXI_EMAC_HWTSTAMP
+		ret = of_property_read_u32(pdev->dev.of_node, "xlnx,phcindex",
+					   &lp->phc_index);
+		if (ret)
+			dev_warn(&pdev->dev, "No phc index defaulting to 0\n");
+#endif
+		ret = of_property_read_u32(pdev->dev.of_node, "xlnx,gtlane",
+					   &lp->gt_lane);
+		if (ret) {
+			dev_err(&pdev->dev, "MRMAC GT lane information missing\n");
 			goto free_netdev;
 		}
+		dev_info(&pdev->dev, "GT lane: %d\n", lp->gt_lane);
 	}
 
-	/* Find the DMA node, map the DMA registers, and decode the DMA IRQs */
-	np = of_parse_phandle(pdev->dev.of_node, "axistream-connected", 0);
-	if (np) {
-		struct resource dmares;
+#ifdef CONFIG_XILINX_AXI_EMAC_HWTSTAMP
+	if (!lp->is_tsn) {
+		struct resource txtsres, rxtsres;
+
+		/* Find AXI Stream FIFO */
+		np = of_parse_phandle(pdev->dev.of_node, "axififo-connected",
+				      0);
+		if (IS_ERR(np)) {
+			dev_err(&pdev->dev, "could not find TX Timestamp FIFO\n");
+			ret = PTR_ERR(np);
+			goto free_netdev;
+		}
 
-		ret = of_address_to_resource(np, 0, &dmares);
+		ret = of_address_to_resource(np, 0, &txtsres);
 		if (ret) {
 			dev_err(&pdev->dev,
-				"unable to get DMA resource\n");
-			of_node_put(np);
+				"unable to get Tx Timestamp resource\n");
 			goto free_netdev;
 		}
-		lp->dma_regs = devm_ioremap_resource(&pdev->dev,
-						     &dmares);
-		lp->rx_irq = irq_of_parse_and_map(np, 1);
-		lp->tx_irq = irq_of_parse_and_map(np, 0);
+
+		lp->tx_ts_regs = devm_ioremap_resource(&pdev->dev, &txtsres);
+		if (IS_ERR(lp->tx_ts_regs)) {
+			dev_err(&pdev->dev, "could not map Tx Timestamp regs\n");
+			ret = PTR_ERR(lp->tx_ts_regs);
+			goto free_netdev;
+		}
+
+		if (lp->axienet_config->mactype == XAXIENET_10G_25G ||
+		    lp->axienet_config->mactype == XAXIENET_MRMAC) {
+			np = of_parse_phandle(pdev->dev.of_node,
+					      "xlnx,rxtsfifo", 0);
+			if (IS_ERR(np)) {
+				dev_err(&pdev->dev,
+					"couldn't find rx-timestamp FIFO\n");
+				ret = PTR_ERR(np);
+				goto free_netdev;
+			}
+
+			ret = of_address_to_resource(np, 0, &rxtsres);
+			if (ret) {
+				dev_err(&pdev->dev,
+					"unable to get rx-timestamp resource\n");
+				goto free_netdev;
+			}
+
+			lp->rx_ts_regs = devm_ioremap_resource(&pdev->dev,
+								&rxtsres);
+			if (IS_ERR(lp->rx_ts_regs)) {
+				dev_err(&pdev->dev,
+					"couldn't map rx-timestamp regs\n");
+				ret = PTR_ERR(lp->rx_ts_regs);
+				goto free_netdev;
+			}
+			lp->tx_ptpheader = devm_kzalloc(&pdev->dev,
+						XXVENET_TS_HEADER_LEN,
+						GFP_KERNEL);
+			spin_lock_init(&lp->ptp_tx_lock);
+		}
+
 		of_node_put(np);
-		lp->eth_irq = platform_get_irq(pdev, 0);
-	} else {
-		/* Check for these resources directly on the Ethernet node. */
-		struct resource *res = platform_get_resource(pdev,
-							     IORESOURCE_MEM, 1);
-		if (!res) {
-			dev_err(&pdev->dev, "unable to get DMA memory resource\n");
+	}
+#endif
+	if (!slave) {
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+		ret = axienet_mcdma_probe(pdev, lp, ndev);
+#else
+		ret = axienet_dma_probe(pdev, ndev);
+#endif
+		if (ret) {
+			pr_err("Getting DMA resource failed\n");
+			goto free_netdev;
+		}
+
+		if (dma_set_mask_and_coherent(lp->dev, DMA_BIT_MASK(lp->dma_mask)) != 0) {
+			dev_warn(&pdev->dev, "default to %d-bit dma mask\n", XAE_DMA_MASK_MIN);
+			if (dma_set_mask_and_coherent(lp->dev, DMA_BIT_MASK(XAE_DMA_MASK_MIN)) != 0) {
+				dev_err(&pdev->dev, "dma_set_mask_and_coherent failed, aborting\n");
+				goto free_netdev;
+			}
+		}
+
+		ret = axienet_dma_clk_init(pdev);
+		if (ret) {
+			if (ret != -EPROBE_DEFER)
+				dev_err(&pdev->dev, "DMA clock init failed %d\n", ret);
 			goto free_netdev;
 		}
-		lp->dma_regs = devm_ioremap_resource(&pdev->dev, res);
-		lp->rx_irq = platform_get_irq(pdev, 1);
-		lp->tx_irq = platform_get_irq(pdev, 0);
-		lp->eth_irq = platform_get_irq(pdev, 2);
-	}
-	if (IS_ERR(lp->dma_regs)) {
-		dev_err(&pdev->dev, "could not map DMA regs\n");
-		ret = PTR_ERR(lp->dma_regs);
-		goto free_netdev;
 	}
-	if ((lp->rx_irq <= 0) || (lp->tx_irq <= 0)) {
-		dev_err(&pdev->dev, "could not determine irqs\n");
-		ret = -ENOMEM;
-		goto free_netdev;
+
+	ret = axienet_clk_init(pdev, &lp->aclk, &lp->eth_sclk,
+			       &lp->eth_refclk, &lp->eth_dclk);
+	if (ret) {
+		if (ret != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "Ethernet clock init failed %d\n", ret);
+		goto err_disable_clk;
 	}
 
+	lp->eth_irq = platform_get_irq(pdev, 0);
 	/* Check for Ethernet core IRQ (optional) */
 	if (lp->eth_irq <= 0)
 		dev_info(&pdev->dev, "Ethernet core IRQ not defined\n");
@@ -1826,48 +3498,68 @@
 	lp->coalesce_count_rx = XAXIDMA_DFT_RX_THRESHOLD;
 	lp->coalesce_count_tx = XAXIDMA_DFT_TX_THRESHOLD;
 
+	ret = of_get_phy_mode(pdev->dev.of_node);
+	if (ret < 0)
+		dev_warn(&pdev->dev, "couldn't find phy i/f\n");
+	lp->phy_interface = ret;
+	if (lp->phy_mode == XAE_PHY_TYPE_1000BASE_X)
+		lp->phy_flags = XAE_PHY_TYPE_1000BASE_X;
+
 	lp->phy_node = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0);
 	if (lp->phy_node) {
-		lp->clk = devm_clk_get(&pdev->dev, NULL);
-		if (IS_ERR(lp->clk)) {
-			dev_warn(&pdev->dev, "Failed to get clock: %ld\n",
-				 PTR_ERR(lp->clk));
-			lp->clk = NULL;
-		} else {
-			ret = clk_prepare_enable(lp->clk);
-			if (ret) {
-				dev_err(&pdev->dev, "Unable to enable clock: %d\n",
-					ret);
-				goto free_netdev;
-			}
-		}
-
 		ret = axienet_mdio_setup(lp);
 		if (ret)
 			dev_warn(&pdev->dev,
 				 "error registering MDIO bus: %d\n", ret);
 	}
 
-	lp->phylink_config.dev = &ndev->dev;
-	lp->phylink_config.type = PHYLINK_NETDEV;
-
-	lp->phylink = phylink_create(&lp->phylink_config, pdev->dev.fwnode,
-				     lp->phy_mode,
-				     &axienet_phylink_ops);
-	if (IS_ERR(lp->phylink)) {
-		ret = PTR_ERR(lp->phylink);
-		dev_err(&pdev->dev, "phylink_create error (%i)\n", ret);
-		goto free_netdev;
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+	/* Create sysfs file entries for the device */
+	ret = axeinet_mcdma_create_sysfs(&lp->dev->kobj);
+	if (ret < 0) {
+		dev_err(lp->dev, "unable to create sysfs entries\n");
+		return ret;
 	}
+#endif
 
 	ret = register_netdev(lp->ndev);
 	if (ret) {
 		dev_err(lp->dev, "register_netdev() error (%i)\n", ret);
-		goto free_netdev;
+		axienet_mdio_teardown(lp);
+		goto err_disable_clk;
 	}
 
+#ifdef CONFIG_XILINX_TSN_PTP
+	if (lp->is_tsn) {
+		lp->ptp_rx_irq = platform_get_irq_byname(pdev, "ptp_rx");
+
+		lp->ptp_tx_irq = platform_get_irq_byname(pdev, "ptp_tx");
+
+		lp->qbv_irq = platform_get_irq_byname(pdev, "qbv_irq");
+
+		pr_debug("ptp RX irq: %d\n", lp->ptp_rx_irq);
+		pr_debug("ptp TX irq: %d\n", lp->ptp_tx_irq);
+		pr_debug("qbv_irq: %d\n", lp->qbv_irq);
+
+		spin_lock_init(&lp->ptp_tx_lock);
+
+		if (lp->temac_no == XAE_TEMAC1) {
+			axienet_ptp_timer_probe((lp->regs + XAE_RTC_OFFSET),
+						pdev);
+
+		/* enable VLAN */
+		lp->options |= XAE_OPTION_VLAN;
+		axienet_setoptions(lp->ndev, lp->options);
+#ifdef CONFIG_XILINX_TSN_QBV
+			axienet_qbv_init(ndev);
+#endif
+		}
+	}
+#endif
 	return 0;
 
+err_disable_clk:
+	axienet_clk_disable(pdev);
 free_netdev:
 	free_netdev(ndev);
 
@@ -1878,17 +3570,30 @@
 {
 	struct net_device *ndev = platform_get_drvdata(pdev);
 	struct axienet_local *lp = netdev_priv(ndev);
+	int i;
 
-	unregister_netdev(ndev);
-
-	if (lp->phylink)
-		phylink_destroy(lp->phylink);
+	if (!lp->is_tsn || lp->temac_no == XAE_TEMAC1) {
+		for_each_rx_dma_queue(lp, i)
+			netif_napi_del(&lp->napi[i]);
+	}
+#ifdef CONFIG_XILINX_TSN_PTP
+		axienet_ptp_timer_remove(lp->timer_priv);
+#ifdef CONFIG_XILINX_TSN_QBV
+		axienet_qbv_remove(ndev);
+#endif
+#endif
+		unregister_netdev(ndev);
+		axienet_clk_disable(pdev);
 
-	axienet_mdio_teardown(lp);
+	if (lp->mii_bus)
+		axienet_mdio_teardown(lp);
 
 	if (lp->clk)
 		clk_disable_unprepare(lp->clk);
 
+#ifdef CONFIG_AXIENET_HAS_MCDMA
+	axeinet_mcdma_remove_sysfs(&lp->dev->kobj);
+#endif
 	of_node_put(lp->phy_node);
 	lp->phy_node = NULL;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/xilinx/xilinx_axienet_mcdma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/xilinx/xilinx_axienet_mcdma.c
@@ -0,0 +1,1061 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/* Xilinx AXI Ethernet (MCDMA programming)
+ *
+ * Copyright (c) 2008 Nissin Systems Co., Ltd.,  Yoshio Kashiwagi
+ * Copyright (c) 2005-2008 DLA Systems,  David H. Lynch Jr. <dhlii@dlasys.net>
+ * Copyright (c) 2008-2009 Secret Lab Technologies Ltd.
+ * Copyright (c) 2010 - 2011 Michal Simek <monstr@monstr.eu>
+ * Copyright (c) 2010 - 2011 PetaLogix
+ * Copyright (c) 2010 - 2012 Xilinx, Inc.
+ * Copyright (C) 2018 Xilinx, Inc. All rights reserved.
+ *
+ * This file contains helper functions for AXI MCDMA TX and RX programming.
+ */
+
+#include <linux/module.h>
+#include <linux/of_mdio.h>
+#include <linux/of_platform.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/of_net.h>
+
+#include "xilinx_axienet.h"
+
+struct axienet_stat {
+	const char *name;
+};
+
+static struct axienet_stat axienet_get_tx_strings_stats[] = {
+	{ "txq0_packets" },
+	{ "txq0_bytes"   },
+	{ "txq1_packets" },
+	{ "txq1_bytes"   },
+	{ "txq2_packets" },
+	{ "txq2_bytes"   },
+	{ "txq3_packets" },
+	{ "txq3_bytes"   },
+	{ "txq4_packets" },
+	{ "txq4_bytes"   },
+	{ "txq5_packets" },
+	{ "txq5_bytes"   },
+	{ "txq6_packets" },
+	{ "txq6_bytes"   },
+	{ "txq7_packets" },
+	{ "txq7_bytes"   },
+	{ "txq8_packets" },
+	{ "txq8_bytes"   },
+	{ "txq9_packets" },
+	{ "txq9_bytes"   },
+	{ "txq10_packets" },
+	{ "txq10_bytes"   },
+	{ "txq11_packets" },
+	{ "txq11_bytes"   },
+	{ "txq12_packets" },
+	{ "txq12_bytes"   },
+	{ "txq13_packets" },
+	{ "txq13_bytes"   },
+	{ "txq14_packets" },
+	{ "txq14_bytes"   },
+	{ "txq15_packets" },
+	{ "txq15_bytes"   },
+};
+
+static struct axienet_stat axienet_get_rx_strings_stats[] = {
+	{ "rxq0_packets" },
+	{ "rxq0_bytes"   },
+	{ "rxq1_packets" },
+	{ "rxq1_bytes"   },
+	{ "rxq2_packets" },
+	{ "rxq2_bytes"   },
+	{ "rxq3_packets" },
+	{ "rxq3_bytes"   },
+	{ "rxq4_packets" },
+	{ "rxq4_bytes"   },
+	{ "rxq5_packets" },
+	{ "rxq5_bytes"   },
+	{ "rxq6_packets" },
+	{ "rxq6_bytes"   },
+	{ "rxq7_packets" },
+	{ "rxq7_bytes"   },
+	{ "rxq8_packets" },
+	{ "rxq8_bytes"   },
+	{ "rxq9_packets" },
+	{ "rxq9_bytes"   },
+	{ "rxq10_packets" },
+	{ "rxq10_bytes"   },
+	{ "rxq11_packets" },
+	{ "rxq11_bytes"   },
+	{ "rxq12_packets" },
+	{ "rxq12_bytes"   },
+	{ "rxq13_packets" },
+	{ "rxq13_bytes"   },
+	{ "rxq14_packets" },
+	{ "rxq14_bytes"   },
+	{ "rxq15_packets" },
+	{ "rxq15_bytes"   },
+};
+
+/**
+ * axienet_mcdma_tx_bd_free - Release MCDMA Tx buffer descriptor rings
+ * @ndev:	Pointer to the net_device structure
+ * @q:		Pointer to DMA queue structure
+ *
+ * This function is used to release the descriptors allocated in
+ * axienet_mcdma_tx_q_init.
+ */
+void __maybe_unused axienet_mcdma_tx_bd_free(struct net_device *ndev,
+					     struct axienet_dma_q *q)
+{
+	struct axienet_local *lp = netdev_priv(ndev);
+
+	if (q->txq_bd_v) {
+		dma_free_coherent(ndev->dev.parent,
+				  sizeof(*q->txq_bd_v) * lp->tx_bd_num,
+				  q->txq_bd_v,
+				  q->tx_bd_p);
+	}
+	if (q->tx_bufs) {
+		dma_free_coherent(ndev->dev.parent,
+				  XAE_MAX_PKT_LEN * lp->tx_bd_num,
+				  q->tx_bufs,
+				  q->tx_bufs_dma);
+	}
+}
+
+/**
+ * axienet_mcdma_rx_bd_free - Release MCDMA Rx buffer descriptor rings
+ * @ndev:	Pointer to the net_device structure
+ * @q:		Pointer to DMA queue structure
+ *
+ * This function is used to release the descriptors allocated in
+ * axienet_mcdma_rx_q_init.
+ */
+void __maybe_unused axienet_mcdma_rx_bd_free(struct net_device *ndev,
+					     struct axienet_dma_q *q)
+{
+	int i;
+	struct axienet_local *lp = netdev_priv(ndev);
+
+	for (i = 0; i < lp->rx_bd_num; i++) {
+		dma_unmap_single(ndev->dev.parent, q->rxq_bd_v[i].phys,
+				 lp->max_frm_size, DMA_FROM_DEVICE);
+		dev_kfree_skb((struct sk_buff *)
+			      (q->rxq_bd_v[i].sw_id_offset));
+	}
+
+	if (q->rxq_bd_v) {
+		dma_free_coherent(ndev->dev.parent,
+				  sizeof(*q->rxq_bd_v) * lp->rx_bd_num,
+				  q->rxq_bd_v,
+				  q->rx_bd_p);
+	}
+}
+
+/**
+ * axienet_mcdma_tx_q_init - Setup buffer descriptor rings for individual Axi
+ * MCDMA-Tx
+ * @ndev:	Pointer to the net_device structure
+ * @q:		Pointer to DMA queue structure
+ *
+ * Return: 0, on success -ENOMEM, on failure
+ *
+ * This function is helper function to axienet_dma_bd_init
+ */
+int __maybe_unused axienet_mcdma_tx_q_init(struct net_device *ndev,
+					   struct axienet_dma_q *q)
+{
+	u32 cr, chan_en;
+	int i;
+	struct axienet_local *lp = netdev_priv(ndev);
+
+	q->tx_bd_ci = 0;
+	q->tx_bd_tail = 0;
+
+	q->txq_bd_v = dma_alloc_coherent(ndev->dev.parent,
+					 sizeof(*q->txq_bd_v) * lp->tx_bd_num,
+					 &q->tx_bd_p, GFP_KERNEL);
+	if (!q->txq_bd_v)
+		goto out;
+
+	if (!q->eth_hasdre) {
+		q->tx_bufs = dma_alloc_coherent(ndev->dev.parent,
+						XAE_MAX_PKT_LEN * lp->tx_bd_num,
+						&q->tx_bufs_dma,
+						GFP_KERNEL);
+		if (!q->tx_bufs)
+			goto out;
+
+		for (i = 0; i < lp->tx_bd_num; i++)
+			q->tx_buf[i] = &q->tx_bufs[i * XAE_MAX_PKT_LEN];
+	}
+
+	for (i = 0; i < lp->tx_bd_num; i++) {
+		q->txq_bd_v[i].next = q->tx_bd_p +
+				      sizeof(*q->txq_bd_v) *
+				      ((i + 1) % lp->tx_bd_num);
+	}
+
+	/* Start updating the Tx channel control register */
+	cr = axienet_dma_in32(q, XMCDMA_CHAN_CR_OFFSET(q->chan_id));
+	/* Update the interrupt coalesce count */
+	cr = (((cr & ~XMCDMA_COALESCE_MASK)) |
+	      ((lp->coalesce_count_tx) << XMCDMA_COALESCE_SHIFT));
+	/* Update the delay timer count */
+	cr = (((cr & ~XMCDMA_DELAY_MASK)) |
+	      (XAXIDMA_DFT_TX_WAITBOUND << XMCDMA_DELAY_SHIFT));
+	/* Enable coalesce, delay timer and error interrupts */
+	cr |= XMCDMA_IRQ_ALL_MASK;
+	/* Write to the Tx channel control register */
+	axienet_dma_out32(q, XMCDMA_CHAN_CR_OFFSET(q->chan_id), cr);
+
+	/* Write to the RS (Run-stop) bit in the Tx channel control register.
+	 * Tx channel is now ready to run. But only after we write to the
+	 * tail pointer register that the Tx channel will start transmitting.
+	 */
+	axienet_dma_bdout(q, XMCDMA_CHAN_CURDESC_OFFSET(q->chan_id),
+			  q->tx_bd_p);
+	cr = axienet_dma_in32(q, XMCDMA_CR_OFFSET);
+	axienet_dma_out32(q, XMCDMA_CR_OFFSET,
+			  cr | XMCDMA_CR_RUNSTOP_MASK);
+	cr = axienet_dma_in32(q, XMCDMA_CHAN_CR_OFFSET(q->chan_id));
+	axienet_dma_out32(q, XMCDMA_CHAN_CR_OFFSET(q->chan_id),
+			  cr | XMCDMA_CR_RUNSTOP_MASK);
+	chan_en = axienet_dma_in32(q, XMCDMA_CHEN_OFFSET);
+	chan_en |= (1 << (q->chan_id - 1));
+	axienet_dma_out32(q, XMCDMA_CHEN_OFFSET, chan_en);
+
+	return 0;
+out:
+	for_each_tx_dma_queue(lp, i) {
+		axienet_mcdma_tx_bd_free(ndev, lp->dq[i]);
+	}
+	return -ENOMEM;
+}
+
+/**
+ * axienet_mcdma_rx_q_init - Setup buffer descriptor rings for individual Axi
+ * MCDMA-Rx
+ * @ndev:	Pointer to the net_device structure
+ * @q:		Pointer to DMA queue structure
+ *
+ * Return: 0, on success -ENOMEM, on failure
+ *
+ * This function is helper function to axienet_dma_bd_init
+ */
+int __maybe_unused axienet_mcdma_rx_q_init(struct net_device *ndev,
+					   struct axienet_dma_q *q)
+{
+	u32 cr, chan_en;
+	int i;
+	struct sk_buff *skb;
+	struct axienet_local *lp = netdev_priv(ndev);
+
+	q->rx_bd_ci = 0;
+	q->rx_offset = XMCDMA_CHAN_RX_OFFSET;
+
+	q->rxq_bd_v = dma_alloc_coherent(ndev->dev.parent,
+					 sizeof(*q->rxq_bd_v) * lp->rx_bd_num,
+					 &q->rx_bd_p, GFP_KERNEL);
+	if (!q->rxq_bd_v)
+		goto out;
+
+	for (i = 0; i < lp->rx_bd_num; i++) {
+		q->rxq_bd_v[i].next = q->rx_bd_p +
+				      sizeof(*q->rxq_bd_v) *
+				      ((i + 1) % lp->rx_bd_num);
+
+		skb = netdev_alloc_skb(ndev, lp->max_frm_size);
+		if (!skb)
+			goto out;
+
+		/* Ensure that the skb is completely updated
+		 * prio to mapping the DMA
+		 */
+		wmb();
+
+		q->rxq_bd_v[i].sw_id_offset = (phys_addr_t)skb;
+		q->rxq_bd_v[i].phys = dma_map_single(ndev->dev.parent,
+						     skb->data,
+						     lp->max_frm_size,
+						     DMA_FROM_DEVICE);
+		q->rxq_bd_v[i].cntrl = lp->max_frm_size;
+	}
+
+	/* Start updating the Rx channel control register */
+	cr = axienet_dma_in32(q, XMCDMA_CHAN_CR_OFFSET(q->chan_id) +
+			      q->rx_offset);
+	/* Update the interrupt coalesce count */
+	cr = ((cr & ~XMCDMA_COALESCE_MASK) |
+	      ((lp->coalesce_count_rx) << XMCDMA_COALESCE_SHIFT));
+	/* Update the delay timer count */
+	cr = ((cr & ~XMCDMA_DELAY_MASK) |
+	      (XAXIDMA_DFT_RX_WAITBOUND << XMCDMA_DELAY_SHIFT));
+	/* Enable coalesce, delay timer and error interrupts */
+	cr |= XMCDMA_IRQ_ALL_MASK;
+	/* Write to the Rx channel control register */
+	axienet_dma_out32(q, XMCDMA_CHAN_CR_OFFSET(q->chan_id) +
+			  q->rx_offset, cr);
+
+	/* Populate the tail pointer and bring the Rx Axi DMA engine out of
+	 * halted state. This will make the Rx side ready for reception.
+	 */
+	axienet_dma_bdout(q, XMCDMA_CHAN_CURDESC_OFFSET(q->chan_id) +
+			    q->rx_offset, q->rx_bd_p);
+	cr = axienet_dma_in32(q, XMCDMA_CR_OFFSET +  q->rx_offset);
+	axienet_dma_out32(q, XMCDMA_CR_OFFSET +  q->rx_offset,
+			  cr | XMCDMA_CR_RUNSTOP_MASK);
+	cr = axienet_dma_in32(q, XMCDMA_CHAN_CR_OFFSET(q->chan_id) +
+				q->rx_offset);
+	axienet_dma_out32(q, XMCDMA_CHAN_CR_OFFSET(q->chan_id) + q->rx_offset,
+			  cr | XMCDMA_CR_RUNSTOP_MASK);
+	axienet_dma_bdout(q, XMCDMA_CHAN_TAILDESC_OFFSET(q->chan_id) +
+			    q->rx_offset, q->rx_bd_p + (sizeof(*q->rxq_bd_v) *
+			    (lp->rx_bd_num - 1)));
+	chan_en = axienet_dma_in32(q, XMCDMA_CHEN_OFFSET + q->rx_offset);
+	chan_en |= (1 << (q->chan_id - 1));
+	axienet_dma_out32(q, XMCDMA_CHEN_OFFSET + q->rx_offset, chan_en);
+
+	return 0;
+
+out:
+	for_each_rx_dma_queue(lp, i) {
+		axienet_mcdma_rx_bd_free(ndev, lp->dq[i]);
+	}
+	return -ENOMEM;
+}
+
+static inline int get_mcdma_tx_q(struct axienet_local *lp, u32 chan_id)
+{
+	int i;
+
+	for_each_tx_dma_queue(lp, i) {
+		if (chan_id == lp->chan_num[i])
+			return lp->qnum[i];
+	}
+
+	return -ENODEV;
+}
+
+static inline int get_mcdma_rx_q(struct axienet_local *lp, u32 chan_id)
+{
+	int i;
+
+	for_each_rx_dma_queue(lp, i) {
+		if (chan_id == lp->chan_num[i])
+			return lp->qnum[i];
+	}
+
+	return -ENODEV;
+}
+
+static inline int map_dma_q_txirq(int irq, struct axienet_local *lp)
+{
+	int i, chan_sermask;
+	u16 chan_id = 1;
+	struct axienet_dma_q *q = lp->dq[0];
+
+	chan_sermask = axienet_dma_in32(q, XMCDMA_TXINT_SER_OFFSET);
+
+	for (i = 1, chan_id = 1; i != 0 && i <= chan_sermask;
+	     i <<= 1, chan_id++) {
+		if (chan_sermask & i)
+			return chan_id;
+	}
+
+	return -ENODEV;
+}
+
+irqreturn_t __maybe_unused axienet_mcdma_tx_irq(int irq, void *_ndev)
+{
+	u32 cr;
+	unsigned int status;
+	struct net_device *ndev = _ndev;
+	struct axienet_local *lp = netdev_priv(ndev);
+	int i, j = map_dma_q_txirq(irq, lp);
+	struct axienet_dma_q *q;
+
+	if (j < 0)
+		return IRQ_NONE;
+
+	i = get_mcdma_tx_q(lp, j);
+	q = lp->dq[i];
+
+	status = axienet_dma_in32(q, XMCDMA_CHAN_SR_OFFSET(q->chan_id));
+	if (status & (XMCDMA_IRQ_IOC_MASK | XMCDMA_IRQ_DELAY_MASK)) {
+		axienet_dma_out32(q, XMCDMA_CHAN_SR_OFFSET(q->chan_id), status);
+		axienet_start_xmit_done(lp->ndev, q);
+		goto out;
+	}
+	if (!(status & XMCDMA_IRQ_ALL_MASK))
+		return IRQ_NONE;
+	if (status & XMCDMA_IRQ_ERR_MASK) {
+		dev_err(&ndev->dev, "DMA Tx error 0x%x\n", status);
+		dev_err(&ndev->dev, "Current BD is at: %pa\n",
+			&q->txq_bd_v[q->tx_bd_ci].phys);
+
+		cr = axienet_dma_in32(q, XMCDMA_CHAN_CR_OFFSET(q->chan_id));
+		/* Disable coalesce, delay timer and error interrupts */
+		cr &= (~XMCDMA_IRQ_ALL_MASK);
+		/* Finally write to the Tx channel control register */
+		axienet_dma_out32(q, XMCDMA_CHAN_CR_OFFSET(q->chan_id), cr);
+
+		cr = axienet_dma_in32(q, XMCDMA_CHAN_CR_OFFSET(q->chan_id) +
+				      q->rx_offset);
+		/* Disable coalesce, delay timer and error interrupts */
+		cr &= (~XMCDMA_IRQ_ALL_MASK);
+		/* write to the Rx channel control register */
+		axienet_dma_out32(q, XMCDMA_CHAN_CR_OFFSET(q->chan_id) +
+				  q->rx_offset, cr);
+
+		tasklet_schedule(&lp->dma_err_tasklet[i]);
+		axienet_dma_out32(q, XMCDMA_CHAN_SR_OFFSET(q->chan_id) +
+				  q->rx_offset, status);
+	}
+out:
+	return IRQ_HANDLED;
+}
+
+static inline int map_dma_q_rxirq(int irq, struct axienet_local *lp)
+{
+	int i, chan_sermask;
+	u16 chan_id = 1;
+	struct axienet_dma_q *q = lp->dq[0];
+
+	chan_sermask = axienet_dma_in32(q, XMCDMA_RXINT_SER_OFFSET +
+					q->rx_offset);
+
+	for (i = 1, chan_id = 1; i != 0 && i <= chan_sermask;
+		i <<= 1, chan_id++) {
+		if (chan_sermask & i)
+			return chan_id;
+	}
+
+	return -ENODEV;
+}
+
+irqreturn_t __maybe_unused axienet_mcdma_rx_irq(int irq, void *_ndev)
+{
+	u32 cr;
+	unsigned int status;
+	struct net_device *ndev = _ndev;
+	struct axienet_local *lp = netdev_priv(ndev);
+	int i, j = map_dma_q_rxirq(irq, lp);
+	struct axienet_dma_q *q;
+
+	if (j < 0)
+		return IRQ_NONE;
+
+	i = get_mcdma_rx_q(lp, j);
+	q = lp->dq[i];
+
+	status = axienet_dma_in32(q, XMCDMA_CHAN_SR_OFFSET(q->chan_id) +
+				  q->rx_offset);
+	if (status & (XMCDMA_IRQ_IOC_MASK | XMCDMA_IRQ_DELAY_MASK)) {
+		cr = axienet_dma_in32(q, XMCDMA_CHAN_CR_OFFSET(q->chan_id) +
+				      q->rx_offset);
+		cr &= ~(XMCDMA_IRQ_IOC_MASK | XMCDMA_IRQ_DELAY_MASK);
+		axienet_dma_out32(q, XMCDMA_CHAN_CR_OFFSET(q->chan_id) +
+				  q->rx_offset, cr);
+		napi_schedule(&lp->napi[i]);
+	}
+
+	if (!(status & XMCDMA_IRQ_ALL_MASK))
+		return IRQ_NONE;
+
+	if (status & XMCDMA_IRQ_ERR_MASK) {
+		dev_err(&ndev->dev, "DMA Rx error 0x%x\n", status);
+		dev_err(&ndev->dev, "Current BD is at: %pa\n",
+			&q->rxq_bd_v[q->rx_bd_ci].phys);
+
+		cr = axienet_dma_in32(q, XMCDMA_CHAN_CR_OFFSET(q->chan_id));
+		/* Disable coalesce, delay timer and error interrupts */
+		cr &= (~XMCDMA_IRQ_ALL_MASK);
+		/* Finally write to the Tx channel control register */
+		axienet_dma_out32(q, XMCDMA_CHAN_CR_OFFSET(q->chan_id), cr);
+
+		cr = axienet_dma_in32(q, XMCDMA_CHAN_CR_OFFSET(q->chan_id) +
+				      q->rx_offset);
+		/* Disable coalesce, delay timer and error interrupts */
+		cr &= (~XMCDMA_IRQ_ALL_MASK);
+		/* write to the Rx channel control register */
+		axienet_dma_out32(q, XMCDMA_CHAN_CR_OFFSET(q->chan_id) +
+				  q->rx_offset, cr);
+
+		tasklet_schedule(&lp->dma_err_tasklet[i]);
+		axienet_dma_out32(q, XMCDMA_CHAN_SR_OFFSET(q->chan_id) +
+				  q->rx_offset, status);
+	}
+
+	return IRQ_HANDLED;
+}
+
+void axienet_strings(struct net_device *ndev, u32 sset, u8 *data)
+{
+	struct axienet_local *lp = netdev_priv(ndev);
+	struct axienet_dma_q *q;
+	int i, j, k = 0;
+
+	for (i = 0, j = 0; i < AXIENET_TX_SSTATS_LEN(lp);) {
+		if (j >= lp->num_tx_queues)
+			break;
+		q = lp->dq[j];
+		if (i % 2 == 0)
+			k = (q->chan_id - 1) * 2;
+		if (sset == ETH_SS_STATS)
+			memcpy(data + i * ETH_GSTRING_LEN,
+			       axienet_get_tx_strings_stats[k].name,
+			       ETH_GSTRING_LEN);
+		++i;
+		k++;
+		if (i % 2 == 0)
+			++j;
+	}
+	k = 0;
+	for (j = 0; i < AXIENET_TX_SSTATS_LEN(lp) +
+			AXIENET_RX_SSTATS_LEN(lp);) {
+		if (j >= lp->num_rx_queues)
+			break;
+		q = lp->dq[j];
+		if (i % 2 == 0)
+			k = (q->chan_id - 1) * 2;
+		if (sset == ETH_SS_STATS)
+			memcpy(data + i * ETH_GSTRING_LEN,
+			       axienet_get_rx_strings_stats[k].name,
+			       ETH_GSTRING_LEN);
+		++i;
+		k++;
+		if (i % 2 == 0)
+			++j;
+	}
+}
+
+int axienet_sset_count(struct net_device *ndev, int sset)
+{
+	struct axienet_local *lp = netdev_priv(ndev);
+
+	switch (sset) {
+	case ETH_SS_STATS:
+		return (AXIENET_TX_SSTATS_LEN(lp) + AXIENET_RX_SSTATS_LEN(lp));
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+void axienet_get_stats(struct net_device *ndev,
+		       struct ethtool_stats *stats,
+		       u64 *data)
+{
+	struct axienet_local *lp = netdev_priv(ndev);
+	struct axienet_dma_q *q;
+	unsigned int i = 0, j;
+
+	for (i = 0, j = 0; i < AXIENET_TX_SSTATS_LEN(lp);) {
+		if (j >= lp->num_tx_queues)
+			break;
+
+		q = lp->dq[j];
+		data[i++] = q->tx_packets;
+		data[i++] = q->tx_bytes;
+		++j;
+	}
+	for (j = 0; i < AXIENET_TX_SSTATS_LEN(lp) +
+			AXIENET_RX_SSTATS_LEN(lp);) {
+		if (j >= lp->num_rx_queues)
+			break;
+
+		q = lp->dq[j];
+		data[i++] = q->rx_packets;
+		data[i++] = q->rx_bytes;
+		++j;
+	}
+}
+
+/**
+ * axienet_mcdma_err_handler - Tasklet handler for Axi MCDMA Error
+ * @data:	Data passed
+ *
+ * Resets the Axi MCDMA and Axi Ethernet devices, and reconfigures the
+ * Tx/Rx BDs.
+ */
+void __maybe_unused axienet_mcdma_err_handler(unsigned long data)
+{
+	u32 axienet_status;
+	u32 cr, i, chan_en;
+	struct axienet_dma_q *q = (struct axienet_dma_q *)data;
+	struct axienet_local *lp = q->lp;
+	struct net_device *ndev = lp->ndev;
+	struct aximcdma_bd *cur_p;
+
+	lp->axienet_config->setoptions(ndev, lp->options &
+				       ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN));
+
+	if (lp->axienet_config->mactype != XAXIENET_10G_25G &&
+	    lp->axienet_config->mactype != XAXIENET_MRMAC) {
+		mutex_lock(&lp->mii_bus->mdio_lock);
+		/* Disable the MDIO interface till Axi Ethernet Reset is
+		 * Completed. When we do an Axi Ethernet reset, it resets the
+		 * Complete core including the MDIO. So if MDIO is not disabled
+		 * When the reset process is started,
+		 * MDIO will be broken afterwards.
+		 */
+		axienet_mdio_disable(lp);
+		axienet_mdio_wait_until_ready(lp);
+	}
+
+	__axienet_device_reset(q);
+
+	if (lp->axienet_config->mactype != XAXIENET_10G_25G &&
+	    lp->axienet_config->mactype != XAXIENET_MRMAC) {
+		axienet_mdio_enable(lp);
+		axienet_mdio_wait_until_ready(lp);
+		mutex_unlock(&lp->mii_bus->mdio_lock);
+	}
+
+	for (i = 0; i < lp->tx_bd_num; i++) {
+		cur_p = &q->txq_bd_v[i];
+		if (cur_p->phys)
+			dma_unmap_single(ndev->dev.parent, cur_p->phys,
+					 (cur_p->cntrl &
+					  XAXIDMA_BD_CTRL_LENGTH_MASK),
+					 DMA_TO_DEVICE);
+		if (cur_p->tx_skb)
+			dev_kfree_skb_irq((struct sk_buff *)cur_p->tx_skb);
+		cur_p->phys = 0;
+		cur_p->cntrl = 0;
+		cur_p->status = 0;
+		cur_p->app0 = 0;
+		cur_p->app1 = 0;
+		cur_p->app2 = 0;
+		cur_p->app3 = 0;
+		cur_p->app4 = 0;
+		cur_p->sw_id_offset = 0;
+		cur_p->tx_skb = 0;
+	}
+
+	for (i = 0; i < lp->rx_bd_num; i++) {
+		cur_p = &q->rxq_bd_v[i];
+		cur_p->status = 0;
+		cur_p->app0 = 0;
+		cur_p->app1 = 0;
+		cur_p->app2 = 0;
+		cur_p->app3 = 0;
+		cur_p->app4 = 0;
+	}
+
+	q->tx_bd_ci = 0;
+	q->tx_bd_tail = 0;
+	q->rx_bd_ci = 0;
+
+	/* Start updating the Rx channel control register */
+	cr = axienet_dma_in32(q, XMCDMA_CHAN_CR_OFFSET(q->chan_id) +
+			      q->rx_offset);
+	/* Update the interrupt coalesce count */
+	cr = ((cr & ~XMCDMA_COALESCE_MASK) |
+	      ((lp->coalesce_count_rx) << XMCDMA_COALESCE_SHIFT));
+	/* Update the delay timer count */
+	cr = ((cr & ~XMCDMA_DELAY_MASK) |
+	      (XAXIDMA_DFT_RX_WAITBOUND << XMCDMA_DELAY_SHIFT));
+	/* Enable coalesce, delay timer and error interrupts */
+	cr |= XMCDMA_IRQ_ALL_MASK;
+	/* Write to the Rx channel control register */
+	axienet_dma_out32(q, XMCDMA_CHAN_CR_OFFSET(q->chan_id) +
+			  q->rx_offset, cr);
+
+	/* Start updating the Tx channel control register */
+	cr = axienet_dma_in32(q, XMCDMA_CHAN_CR_OFFSET(q->chan_id));
+	/* Update the interrupt coalesce count */
+	cr = (((cr & ~XMCDMA_COALESCE_MASK)) |
+	      ((lp->coalesce_count_tx) << XMCDMA_COALESCE_SHIFT));
+	/* Update the delay timer count */
+	cr = (((cr & ~XMCDMA_DELAY_MASK)) |
+	      (XAXIDMA_DFT_TX_WAITBOUND << XMCDMA_DELAY_SHIFT));
+	/* Enable coalesce, delay timer and error interrupts */
+	cr |= XMCDMA_IRQ_ALL_MASK;
+	/* Write to the Tx channel control register */
+	axienet_dma_out32(q, XMCDMA_CHAN_CR_OFFSET(q->chan_id), cr);
+
+	/* Populate the tail pointer and bring the Rx Axi DMA engine out of
+	 * halted state. This will make the Rx side ready for reception.
+	 */
+	axienet_dma_bdout(q, XMCDMA_CHAN_CURDESC_OFFSET(q->chan_id) +
+			    q->rx_offset, q->rx_bd_p);
+	cr = axienet_dma_in32(q, XMCDMA_CR_OFFSET +  q->rx_offset);
+	axienet_dma_out32(q, XMCDMA_CR_OFFSET +  q->rx_offset,
+			  cr | XMCDMA_CR_RUNSTOP_MASK);
+	cr = axienet_dma_in32(q, XMCDMA_CHAN_CR_OFFSET(q->chan_id) +
+				q->rx_offset);
+	axienet_dma_out32(q, XMCDMA_CHAN_CR_OFFSET(q->chan_id) + q->rx_offset,
+			  cr | XMCDMA_CR_RUNSTOP_MASK);
+	axienet_dma_bdout(q, XMCDMA_CHAN_TAILDESC_OFFSET(q->chan_id) +
+			    q->rx_offset, q->rx_bd_p + (sizeof(*q->rxq_bd_v) *
+			    (lp->rx_bd_num - 1)));
+	chan_en = axienet_dma_in32(q, XMCDMA_CHEN_OFFSET + q->rx_offset);
+	chan_en |= (1 << (q->chan_id - 1));
+	axienet_dma_out32(q, XMCDMA_CHEN_OFFSET + q->rx_offset, chan_en);
+
+	/* Write to the RS (Run-stop) bit in the Tx channel control register.
+	 * Tx channel is now ready to run. But only after we write to the
+	 * tail pointer register that the Tx channel will start transmitting.
+	 */
+	axienet_dma_bdout(q, XMCDMA_CHAN_CURDESC_OFFSET(q->chan_id),
+			  q->tx_bd_p);
+	cr = axienet_dma_in32(q, XMCDMA_CR_OFFSET);
+	axienet_dma_out32(q, XMCDMA_CR_OFFSET,
+			  cr | XMCDMA_CR_RUNSTOP_MASK);
+	cr = axienet_dma_in32(q, XMCDMA_CHAN_CR_OFFSET(q->chan_id));
+	axienet_dma_out32(q, XMCDMA_CHAN_CR_OFFSET(q->chan_id),
+			  cr | XMCDMA_CR_RUNSTOP_MASK);
+	chan_en = axienet_dma_in32(q, XMCDMA_CHEN_OFFSET);
+	chan_en |= (1 << (q->chan_id - 1));
+	axienet_dma_out32(q, XMCDMA_CHEN_OFFSET, chan_en);
+
+	if (lp->axienet_config->mactype != XAXIENET_10G_25G &&
+	    lp->axienet_config->mactype != XAXIENET_MRMAC) {
+		axienet_status = axienet_ior(lp, XAE_RCW1_OFFSET);
+		axienet_status &= ~XAE_RCW1_RX_MASK;
+		axienet_iow(lp, XAE_RCW1_OFFSET, axienet_status);
+	}
+
+	if (lp->axienet_config->mactype == XAXIENET_1G && !lp->eth_hasnobuf) {
+		axienet_status = axienet_ior(lp, XAE_IP_OFFSET);
+		if (axienet_status & XAE_INT_RXRJECT_MASK)
+			axienet_iow(lp, XAE_IS_OFFSET, XAE_INT_RXRJECT_MASK);
+	}
+
+	if (lp->axienet_config->mactype != XAXIENET_10G_25G &&
+	    lp->axienet_config->mactype != XAXIENET_MRMAC)
+		axienet_iow(lp, XAE_FCC_OFFSET, XAE_FCC_FCRX_MASK);
+
+#ifdef CONFIG_XILINX_AXI_EMAC_HWTSTAMP
+	if (lp->axienet_config->mactype == XAXIENET_10G_25G ||
+	    lp->axienet_config->mactype == XAXIENET_MRMAC) {
+		axienet_rxts_iow(lp, XAXIFIFO_TXTS_RDFR,
+				 XAXIFIFO_TXTS_RESET_MASK);
+		axienet_rxts_iow(lp, XAXIFIFO_TXTS_SRR,
+				 XAXIFIFO_TXTS_RESET_MASK);
+		axienet_txts_iow(lp, XAXIFIFO_TXTS_RDFR,
+				 XAXIFIFO_TXTS_RESET_MASK);
+		axienet_txts_iow(lp, XAXIFIFO_TXTS_SRR,
+				 XAXIFIFO_TXTS_RESET_MASK);
+	}
+#endif
+
+	lp->axienet_config->setoptions(ndev, lp->options &
+				       ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN));
+	axienet_set_mac_address(ndev, NULL);
+	axienet_set_multicast_list(ndev);
+	lp->axienet_config->setoptions(ndev, lp->options);
+}
+
+int __maybe_unused axienet_mcdma_tx_probe(struct platform_device *pdev,
+					  struct device_node *np,
+					  struct axienet_local *lp)
+{
+	int i;
+	char dma_name[24];
+
+	for_each_tx_dma_queue(lp, i) {
+		struct axienet_dma_q *q;
+
+		q = lp->dq[i];
+
+		q->dma_regs = lp->mcdma_regs;
+		snprintf(dma_name, sizeof(dma_name), "mm2s_ch%d_introut",
+			 q->chan_id);
+		q->tx_irq = platform_get_irq_byname(pdev, dma_name);
+		q->eth_hasdre = of_property_read_bool(np,
+						      "xlnx,include-dre");
+		spin_lock_init(&q->tx_lock);
+	}
+	of_node_put(np);
+
+	return 0;
+}
+
+int __maybe_unused axienet_mcdma_rx_probe(struct platform_device *pdev,
+					  struct axienet_local *lp,
+					  struct net_device *ndev)
+{
+	int i;
+	char dma_name[24];
+
+	for_each_rx_dma_queue(lp, i) {
+		struct axienet_dma_q *q;
+
+		q = lp->dq[i];
+
+		q->dma_regs = lp->mcdma_regs;
+		snprintf(dma_name, sizeof(dma_name), "s2mm_ch%d_introut",
+			 q->chan_id);
+		q->rx_irq = platform_get_irq_byname(pdev, dma_name);
+
+		spin_lock_init(&q->rx_lock);
+
+		netif_napi_add(ndev, &lp->napi[i], xaxienet_rx_poll,
+			       XAXIENET_NAPI_WEIGHT);
+	}
+
+	return 0;
+}
+
+static ssize_t rxch_obs1_show(struct device *dev,
+			      struct device_attribute *attr, char *buf)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct axienet_local *lp = netdev_priv(ndev);
+	struct axienet_dma_q *q = lp->dq[0];
+	u32 reg;
+
+	reg = axienet_dma_in32(q, XMCDMA_CHOBS1_OFFSET + q->rx_offset);
+
+	return sprintf(buf, "Ingress Channel Observer 1 Contents is 0x%x\n",
+		       reg);
+}
+
+static ssize_t rxch_obs2_show(struct device *dev,
+			      struct device_attribute *attr, char *buf)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct axienet_local *lp = netdev_priv(ndev);
+	struct axienet_dma_q *q = lp->dq[0];
+	u32 reg;
+
+	reg = axienet_dma_in32(q, XMCDMA_CHOBS2_OFFSET + q->rx_offset);
+
+	return sprintf(buf, "Ingress Channel Observer 2 Contents is 0x%x\n",
+		       reg);
+}
+
+static ssize_t rxch_obs3_show(struct device *dev,
+			      struct device_attribute *attr, char *buf)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct axienet_local *lp = netdev_priv(ndev);
+	struct axienet_dma_q *q = lp->dq[0];
+	u32 reg;
+
+	reg = axienet_dma_in32(q, XMCDMA_CHOBS3_OFFSET + q->rx_offset);
+
+	return sprintf(buf, "Ingress Channel Observer 3 Contents is 0x%x\n",
+		       reg);
+}
+
+static ssize_t rxch_obs4_show(struct device *dev,
+			      struct device_attribute *attr, char *buf)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct axienet_local *lp = netdev_priv(ndev);
+	struct axienet_dma_q *q = lp->dq[0];
+	u32 reg;
+
+	reg = axienet_dma_in32(q, XMCDMA_CHOBS4_OFFSET + q->rx_offset);
+
+	return sprintf(buf, "Ingress Channel Observer 4 Contents is 0x%x\n",
+		       reg);
+}
+
+static ssize_t rxch_obs5_show(struct device *dev,
+			      struct device_attribute *attr, char *buf)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct axienet_local *lp = netdev_priv(ndev);
+	struct axienet_dma_q *q = lp->dq[0];
+	u32 reg;
+
+	reg = axienet_dma_in32(q, XMCDMA_CHOBS5_OFFSET + q->rx_offset);
+
+	return sprintf(buf, "Ingress Channel Observer 5 Contents is 0x%x\n",
+		       reg);
+}
+
+static ssize_t rxch_obs6_show(struct device *dev,
+			      struct device_attribute *attr, char *buf)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct axienet_local *lp = netdev_priv(ndev);
+	struct axienet_dma_q *q = lp->dq[0];
+	u32 reg;
+
+	reg = axienet_dma_in32(q, XMCDMA_CHOBS6_OFFSET + q->rx_offset);
+
+	return sprintf(buf, "Ingress Channel Observer 6 Contents is 0x%x\n\r",
+		       reg);
+}
+
+static ssize_t txch_obs1_show(struct device *dev,
+			      struct device_attribute *attr, char *buf)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct axienet_local *lp = netdev_priv(ndev);
+	struct axienet_dma_q *q = lp->dq[0];
+	u32 reg;
+
+	reg = axienet_dma_in32(q, XMCDMA_CHOBS1_OFFSET);
+
+	return sprintf(buf, "Egress Channel Observer 1 Contents is 0x%x\n",
+		       reg);
+}
+
+static ssize_t txch_obs2_show(struct device *dev,
+			      struct device_attribute *attr, char *buf)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct axienet_local *lp = netdev_priv(ndev);
+	struct axienet_dma_q *q = lp->dq[0];
+	u32 reg;
+
+	reg = axienet_dma_in32(q, XMCDMA_CHOBS2_OFFSET);
+
+	return sprintf(buf, "Egress Channel Observer 2 Contents is 0x%x\n\r",
+		       reg);
+}
+
+static ssize_t txch_obs3_show(struct device *dev,
+			      struct device_attribute *attr, char *buf)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct axienet_local *lp = netdev_priv(ndev);
+	struct axienet_dma_q *q = lp->dq[0];
+	u32 reg;
+
+	reg = axienet_dma_in32(q, XMCDMA_CHOBS3_OFFSET);
+
+	return sprintf(buf, "Egress Channel Observer 3 Contents is 0x%x\n\r",
+		       reg);
+}
+
+static ssize_t txch_obs4_show(struct device *dev,
+			      struct device_attribute *attr, char *buf)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct axienet_local *lp = netdev_priv(ndev);
+	struct axienet_dma_q *q = lp->dq[0];
+	u32 reg;
+
+	reg = axienet_dma_in32(q, XMCDMA_CHOBS4_OFFSET);
+
+	return sprintf(buf, "Egress Channel Observer 4 Contents is 0x%x\n\r",
+		       reg);
+}
+
+static ssize_t txch_obs5_show(struct device *dev,
+			      struct device_attribute *attr, char *buf)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct axienet_local *lp = netdev_priv(ndev);
+	struct axienet_dma_q *q = lp->dq[0];
+	u32 reg;
+
+	reg = axienet_dma_in32(q, XMCDMA_CHOBS5_OFFSET);
+
+	return sprintf(buf, "Egress Channel Observer 5 Contents is 0x%x\n\r",
+		       reg);
+}
+
+static ssize_t txch_obs6_show(struct device *dev,
+			      struct device_attribute *attr, char *buf)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct axienet_local *lp = netdev_priv(ndev);
+	struct axienet_dma_q *q = lp->dq[0];
+	u32 reg;
+
+	reg = axienet_dma_in32(q, XMCDMA_CHOBS6_OFFSET);
+
+	return sprintf(buf, "Egress Channel Observer 6 Contents is 0x%x\n\r",
+		       reg);
+}
+
+static ssize_t chan_weight_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct axienet_local *lp = netdev_priv(ndev);
+
+	return sprintf(buf, "chan_id is %d and weight is %d\n",
+		       lp->chan_id, lp->weight);
+}
+
+static ssize_t chan_weight_store(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct axienet_local *lp = netdev_priv(ndev);
+	struct axienet_dma_q *q = lp->dq[0];
+	int ret;
+	u16 flags, chan_id;
+	u32 val;
+
+	ret = kstrtou16(buf, 16, &flags);
+	if (ret)
+		return ret;
+
+	lp->chan_id = (flags & 0xF0) >> 4;
+	lp->weight = flags & 0x0F;
+
+	if (lp->chan_id < 8)
+		val = axienet_dma_in32(q, XMCDMA_TXWEIGHT0_OFFSET);
+	else
+		val = axienet_dma_in32(q, XMCDMA_TXWEIGHT1_OFFSET);
+
+	if (lp->chan_id > 7)
+		chan_id = lp->chan_id - 8;
+	else
+		chan_id = lp->chan_id;
+
+	val &= ~XMCDMA_TXWEIGHT_CH_MASK(chan_id);
+	val |= lp->weight << XMCDMA_TXWEIGHT_CH_SHIFT(chan_id);
+
+	if (lp->chan_id < 8)
+		axienet_dma_out32(q, XMCDMA_TXWEIGHT0_OFFSET, val);
+	else
+		axienet_dma_out32(q, XMCDMA_TXWEIGHT1_OFFSET, val);
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(chan_weight);
+static DEVICE_ATTR_RO(rxch_obs1);
+static DEVICE_ATTR_RO(rxch_obs2);
+static DEVICE_ATTR_RO(rxch_obs3);
+static DEVICE_ATTR_RO(rxch_obs4);
+static DEVICE_ATTR_RO(rxch_obs5);
+static DEVICE_ATTR_RO(rxch_obs6);
+static DEVICE_ATTR_RO(txch_obs1);
+static DEVICE_ATTR_RO(txch_obs2);
+static DEVICE_ATTR_RO(txch_obs3);
+static DEVICE_ATTR_RO(txch_obs4);
+static DEVICE_ATTR_RO(txch_obs5);
+static DEVICE_ATTR_RO(txch_obs6);
+static const struct attribute *mcdma_attrs[] = {
+	&dev_attr_chan_weight.attr,
+	&dev_attr_rxch_obs1.attr,
+	&dev_attr_rxch_obs2.attr,
+	&dev_attr_rxch_obs3.attr,
+	&dev_attr_rxch_obs4.attr,
+	&dev_attr_rxch_obs5.attr,
+	&dev_attr_rxch_obs6.attr,
+	&dev_attr_txch_obs1.attr,
+	&dev_attr_txch_obs2.attr,
+	&dev_attr_txch_obs3.attr,
+	&dev_attr_txch_obs4.attr,
+	&dev_attr_txch_obs5.attr,
+	&dev_attr_txch_obs6.attr,
+	NULL,
+};
+
+static const struct attribute_group mcdma_attributes = {
+	.attrs = (struct attribute **)mcdma_attrs,
+};
+
+int axeinet_mcdma_create_sysfs(struct kobject *kobj)
+{
+	return sysfs_create_group(kobj, &mcdma_attributes);
+}
+
+void axeinet_mcdma_remove_sysfs(struct kobject *kobj)
+{
+	sysfs_remove_group(kobj, &mcdma_attributes);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
@@ -21,7 +21,7 @@
 #define DEFAULT_HOST_CLOCK	150000000 /* 150 MHz */
 
 /* Wait till MDIO interface is ready to accept a new transaction.*/
-static int axienet_mdio_wait_until_ready(struct axienet_local *lp)
+int axienet_mdio_wait_until_ready(struct axienet_local *lp)
 {
 	u32 val;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/xilinx/xilinx_emaclite.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/xilinx/xilinx_emaclite.c
@@ -1,6 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Xilinx EmacLite Linux driver for the Xilinx Ethernet MAC Lite device.
+/* Xilinx EmacLite Linux driver for the Xilinx Ethernet MAC Lite device.
  *
  * This is a new flat driver which is based on the original emac_lite
  * driver from John Williams <john.williams@xilinx.com>.
@@ -91,13 +90,11 @@
 #define XEL_ARP_PACKET_SIZE		28	/* Max ARP packet size */
 #define XEL_HEADER_IP_LENGTH_OFFSET	16	/* IP Length Offset */
 
-
-
 #define TX_TIMEOUT		(60 * HZ)	/* Tx timeout is 60 seconds. */
 #define ALIGNMENT		4
 
 /* BUFFER_ALIGN(adr) calculates the number of bytes to the next alignment. */
-#define BUFFER_ALIGN(adr) ((ALIGNMENT - ((u32)adr)) % ALIGNMENT)
+#define BUFFER_ALIGN(adr) ((ALIGNMENT - ((ulong)adr)) % ALIGNMENT)
 
 #ifdef __BIG_ENDIAN
 #define xemaclite_readl		ioread32be
@@ -115,7 +112,7 @@
  * @next_tx_buf_to_use:	next Tx buffer to write to
  * @next_rx_buf_to_use:	next Rx buffer to read from
  * @base_addr:		base address of the Emaclite device
- * @reset_lock:		lock used for synchronization
+ * @reset_lock:		lock to serialize xmit and tx_timeout execution
  * @deferred_skb:	holds an skb (for transmission at a later time) when the
  *			Tx buffer is not free
  * @phy_dev:		pointer to the PHY device
@@ -124,7 +121,6 @@
  * @last_link:		last link status
  */
 struct net_local {
-
 	struct net_device *ndev;
 
 	bool tx_ping_pong;
@@ -133,7 +129,7 @@
 	u32 next_rx_buf_to_use;
 	void __iomem *base_addr;
 
-	spinlock_t reset_lock;
+	spinlock_t reset_lock; /* serialize xmit and tx_timeout execution */
 	struct sk_buff *deferred_skb;
 
 	struct phy_device *phy_dev;
@@ -144,7 +140,6 @@
 	int last_link;
 };
 
-
 /*************************/
 /* EmacLite driver calls */
 /*************************/
@@ -207,7 +202,7 @@
  * address in the EmacLite device.
  */
 static void xemaclite_aligned_write(void *src_ptr, u32 *dest_ptr,
-				    unsigned length)
+				    unsigned int length)
 {
 	u32 align_buffer;
 	u32 *to_u32_ptr;
@@ -264,7 +259,7 @@
  * to a 16-bit aligned buffer.
  */
 static void xemaclite_aligned_read(u32 *src_ptr, u8 *dest_ptr,
-				   unsigned length)
+				   unsigned int length)
 {
 	u16 *to_u16_ptr, *from_u16_ptr;
 	u32 *from_u32_ptr;
@@ -329,7 +324,6 @@
 	reg_data = xemaclite_readl(addr + XEL_TSR_OFFSET);
 	if ((reg_data & (XEL_TSR_XMIT_BUSY_MASK |
 	     XEL_TSR_XMIT_ACTIVE_MASK)) == 0) {
-
 		/* Switch to next buffer if configured */
 		if (drvdata->tx_ping_pong != 0)
 			drvdata->next_tx_buf_to_use ^= XEL_BUFFER_OFFSET;
@@ -338,15 +332,16 @@
 		 * if it is configured in HW
 		 */
 
-		addr = (void __iomem __force *)((u32 __force)addr ^
+		addr = (void __iomem __force *)((ulong __force)addr ^
 						 XEL_BUFFER_OFFSET);
 		reg_data = xemaclite_readl(addr + XEL_TSR_OFFSET);
 
 		if ((reg_data & (XEL_TSR_XMIT_BUSY_MASK |
 		     XEL_TSR_XMIT_ACTIVE_MASK)) != 0)
 			return -1; /* Buffers were full, return failure */
-	} else
+	} else {
 		return -1; /* Buffer was full, return failure */
+	}
 
 	/* Write the frame to the buffer */
 	xemaclite_aligned_write(data, (u32 __force *)addr, byte_count);
@@ -399,7 +394,7 @@
 		 * will correct on subsequent calls
 		 */
 		if (drvdata->rx_ping_pong != 0)
-			addr = (void __iomem __force *)((u32 __force)addr ^
+			addr = (void __iomem __force *)((ulong __force)addr ^
 							 XEL_BUFFER_OFFSET);
 		else
 			return 0;	/* No data was available */
@@ -421,7 +416,6 @@
 	 * or an IP packet or an ARP packet
 	 */
 	if (proto_type > ETH_DATA_LEN) {
-
 		if (proto_type == ETH_P_IP) {
 			length = ((ntohl(xemaclite_readl(addr +
 					XEL_HEADER_IP_LENGTH_OFFSET +
@@ -431,23 +425,25 @@
 			length = min_t(u16, length, ETH_DATA_LEN);
 			length += ETH_HLEN + ETH_FCS_LEN;
 
-		} else if (proto_type == ETH_P_ARP)
+		} else if (proto_type == ETH_P_ARP) {
 			length = XEL_ARP_PACKET_SIZE + ETH_HLEN + ETH_FCS_LEN;
-		else
+		} else {
 			/* Field contains type other than IP or ARP, use max
 			 * frame size and let user parse it
 			 */
 			length = ETH_FRAME_LEN + ETH_FCS_LEN;
-	} else
+		}
+	} else {
 		/* Use the length in the frame, plus the header and trailer */
 		length = proto_type + ETH_HLEN + ETH_FCS_LEN;
+	}
 
 	if (WARN_ON(length > maxlen))
 		length = maxlen;
 
 	/* Read from the EmacLite device */
 	xemaclite_aligned_read((u32 __force *)(addr + XEL_RXBUFF_OFFSET),
-				data, length);
+			       data, length);
 
 	/* Acknowledge the frame */
 	reg_data = xemaclite_readl(addr + XEL_RSR_OFFSET);
@@ -541,7 +537,7 @@
 	xemaclite_enable_interrupts(lp);
 
 	if (lp->deferred_skb) {
-		dev_kfree_skb(lp->deferred_skb);
+		dev_kfree_skb_irq(lp->deferred_skb);
 		lp->deferred_skb = NULL;
 		dev->stats.tx_errors++;
 	}
@@ -668,8 +664,7 @@
 	/* Check if the Transmission for the first buffer is completed */
 	tx_status = xemaclite_readl(base_addr + XEL_TSR_OFFSET);
 	if (((tx_status & XEL_TSR_XMIT_BUSY_MASK) == 0) &&
-		(tx_status & XEL_TSR_XMIT_ACTIVE_MASK) != 0) {
-
+	    (tx_status & XEL_TSR_XMIT_ACTIVE_MASK) != 0) {
 		tx_status &= ~XEL_TSR_XMIT_ACTIVE_MASK;
 		xemaclite_writel(tx_status, base_addr + XEL_TSR_OFFSET);
 
@@ -679,8 +674,7 @@
 	/* Check if the Transmission for the second buffer is completed */
 	tx_status = xemaclite_readl(base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
 	if (((tx_status & XEL_TSR_XMIT_BUSY_MASK) == 0) &&
-		(tx_status & XEL_TSR_XMIT_ACTIVE_MASK) != 0) {
-
+	    (tx_status & XEL_TSR_XMIT_ACTIVE_MASK) != 0) {
 		tx_status &= ~XEL_TSR_XMIT_ACTIVE_MASK;
 		xemaclite_writel(tx_status, base_addr + XEL_BUFFER_OFFSET +
 				 XEL_TSR_OFFSET);
@@ -820,10 +814,10 @@
 static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev)
 {
 	struct mii_bus *bus;
-	int rc;
 	struct resource res;
 	struct device_node *np = of_get_parent(lp->phy_node);
 	struct device_node *npp;
+	int rc, ret;
 
 	/* Don't register the MDIO bus if the phy_node or its parent node
 	 * can't be found.
@@ -833,16 +827,24 @@
 		return -ENODEV;
 	}
 	npp = of_get_parent(np);
-
-	of_address_to_resource(npp, 0, &res);
+	ret = of_address_to_resource(npp, 0, &res);
+	of_node_put(npp);
+	if (ret) {
+		dev_err(dev, "%s resource error!\n",
+			dev->of_node->full_name);
+		of_node_put(np);
+		return ret;
+	}
 	if (lp->ndev->mem_start != res.start) {
 		struct phy_device *phydev;
+
 		phydev = of_phy_find_device(lp->phy_node);
 		if (!phydev)
 			dev_info(dev,
 				 "MDIO of the phy is not registered yet\n");
 		else
 			put_device(&phydev->mdio.dev);
+		of_node_put(np);
 		return 0;
 	}
 
@@ -855,6 +857,7 @@
 	bus = mdiobus_alloc();
 	if (!bus) {
 		dev_err(dev, "Failed to allocate mdiobus\n");
+		of_node_put(np);
 		return -ENOMEM;
 	}
 
@@ -867,6 +870,7 @@
 	bus->parent = dev;
 
 	rc = of_mdiobus_register(bus, np);
+	of_node_put(np);
 	if (rc) {
 		dev_err(dev, "Failed to register mdio bus.\n");
 		goto err_register;
@@ -923,8 +927,6 @@
 	xemaclite_disable_interrupts(lp);
 
 	if (lp->phy_node) {
-		u32 bmcr;
-
 		lp->phy_dev = of_phy_connect(lp->ndev, lp->phy_node,
 					     xemaclite_adjust_link, 0,
 					     PHY_INTERFACE_MODE_MII);
@@ -935,19 +937,6 @@
 
 		/* EmacLite doesn't support giga-bit speeds */
 		phy_set_max_speed(lp->phy_dev, SPEED_100);
-
-		/* Don't advertise 1000BASE-T Full/Half duplex speeds */
-		phy_write(lp->phy_dev, MII_CTRL1000, 0);
-
-		/* Advertise only 10 and 100mbps full/half duplex speeds */
-		phy_write(lp->phy_dev, MII_ADVERTISE, ADVERTISE_ALL |
-			  ADVERTISE_CSMA);
-
-		/* Restart auto negotiation */
-		bmcr = phy_read(lp->phy_dev, MII_BMCR);
-		bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
-		phy_write(lp->phy_dev, MII_BMCR, bmcr);
-
 		phy_start(lp->phy_dev);
 	}
 
@@ -1187,15 +1176,16 @@
 	if (rc) {
 		dev_err(dev,
 			"Cannot register network device, aborting\n");
-		goto error;
+		goto put_node;
 	}
 
 	dev_info(dev,
-		 "Xilinx EmacLite at 0x%08X mapped to 0x%08X, irq=%d\n",
-		 (unsigned int __force)ndev->mem_start,
-		 (unsigned int __force)lp->base_addr, ndev->irq);
+		 "Xilinx EmacLite at 0x%08X mapped to 0x%p, irq=%d\n",
+		 (unsigned int __force)ndev->mem_start, lp->base_addr, ndev->irq);
 	return 0;
 
+put_node:
+	of_node_put(lp->phy_node);
 error:
 	free_netdev(ndev);
 	return rc;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/xilinx/xilinx_tsn_cb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/xilinx/xilinx_tsn_cb.c
@@ -0,0 +1,177 @@
+/*
+ * Xilinx FPGA Xilinx TSN QCI Controller module.
+ *
+ * Copyright (c) 2017 Xilinx Pvt., Ltd
+ *
+ * Author: Saurabh Sengar <saurabhs@xilinx.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include "xilinx_tsn_switch.h"
+
+#define IN_PORTID_MASK				0x3
+#define IN_PORTID_SHIFT				24
+#define MAX_SEQID_MASK				0x0000FFFF
+
+#define SEQ_REC_HIST_LEN_MASK			0x000000FF
+#define SEQ_REC_HIST_LEN_SHIFT			16
+#define SPLIT_STREAM_INPORTID_SHIFT		12
+#define SPLIT_STREAM_INPORTID_MASK		0x3
+#define SPLIT_STREAM_VLANID_MASK		0x00000FFF
+
+#define GATE_ID_SHIFT				24
+#define MEMBER_ID_SHIFT				8
+#define SEQ_RESET_SHIFT				7
+#define REC_TIMEOUT_SHIFT			6
+#define GATE_STATE_SHIFT			5
+#define FRER_VALID_SHIFT			4
+#define WR_OP_TYPE_SHIFT			2
+#define OP_TYPE_SHIFT				1
+#define WR_OP_TYPE_MASK				0x3
+#define FRER_EN_CONTROL_MASK			0x1
+
+/**
+ * frer_control - Configure thr control for frer
+ * @data:	Value to be programmed
+ */
+void frer_control(struct frer_ctrl data)
+{
+	u32 mask = 0;
+
+	mask = data.gate_id << GATE_ID_SHIFT;
+	mask |= data.memb_id << MEMBER_ID_SHIFT;
+	mask |= data.seq_reset << SEQ_RESET_SHIFT;
+	mask |= data.gate_state << GATE_STATE_SHIFT;
+	mask |= data.rcvry_tmout << REC_TIMEOUT_SHIFT;
+	mask |= data.frer_valid << FRER_VALID_SHIFT;
+	mask |= (data.wr_op_type & WR_OP_TYPE_MASK) << WR_OP_TYPE_SHIFT;
+	mask |= data.op_type << OP_TYPE_SHIFT;
+	mask |= FRER_EN_CONTROL_MASK;
+
+	axienet_iow(&lp, FRER_CONTROL_OFFSET, mask);
+
+	/* wait for write to complete */
+	while ((axienet_ior(&lp, FRER_CONTROL_OFFSET) & FRER_EN_CONTROL_MASK))
+		;
+}
+
+/**
+ * get_ingress_filter_config -  Get Ingress Filter Configuration
+ * @data:	Value returned
+ */
+void get_ingress_filter_config(struct in_fltr *data)
+{
+	u32 reg_val = 0;
+
+	reg_val = axienet_ior(&lp, INGRESS_FILTER_OFFSET);
+
+	data->max_seq_id = reg_val & MAX_SEQID_MASK;
+	data->in_port_id = (reg_val >> IN_PORTID_SHIFT) & IN_PORTID_MASK;
+}
+
+/**
+ * config_stream_filter -  Configure Ingress Filter Configuration
+ * @data:	Value to be programmed
+ */
+void config_ingress_filter(struct in_fltr data)
+{
+	u32 mask = 0;
+
+	mask = ((data.in_port_id & IN_PORTID_MASK) << IN_PORTID_SHIFT) |
+					(data.max_seq_id & MAX_SEQID_MASK);
+	axienet_iow(&lp, INGRESS_FILTER_OFFSET, mask);
+}
+
+/**
+ * get_member_reg -  Read frer member Configuration registers value
+ * @data:	Value returned
+ */
+void get_member_reg(struct frer_memb_config *data)
+{
+	u32 conf_r1 = 0;
+
+	conf_r1 = axienet_ior(&lp, FRER_CONFIG_REG1);
+	data->rem_ticks = axienet_ior(&lp, FRER_CONFIG_REG2);
+
+	data->seq_rec_hist_len = (conf_r1 >> SEQ_REC_HIST_LEN_SHIFT)
+						& SEQ_REC_HIST_LEN_MASK;
+	data->split_strm_egport_id = (conf_r1 >> SPLIT_STREAM_INPORTID_SHIFT)
+						& SPLIT_STREAM_INPORTID_MASK;
+	data->split_strm_vlan_id = conf_r1 & SPLIT_STREAM_VLANID_MASK;
+}
+
+/**
+ * program_member_reg -  configure frer member Configuration registers
+ * @data:	Value to be programmed
+ */
+void program_member_reg(struct frer_memb_config data)
+{
+	u32 conf_r1 = 0;
+
+	conf_r1 = (data.seq_rec_hist_len & SEQ_REC_HIST_LEN_MASK)
+						<< SEQ_REC_HIST_LEN_SHIFT;
+	conf_r1 = conf_r1 | ((data.split_strm_egport_id
+					& SPLIT_STREAM_INPORTID_MASK)
+					<< SPLIT_STREAM_INPORTID_SHIFT);
+	conf_r1 = conf_r1 | (data.split_strm_vlan_id
+					& SPLIT_STREAM_VLANID_MASK);
+
+	axienet_iow(&lp, FRER_CONFIG_REG1, conf_r1);
+	axienet_iow(&lp, FRER_CONFIG_REG2, data.rem_ticks);
+}
+
+/**
+ * get_frer_static_counter -  get frer static counters value
+ * @data:	return value, containing counter value
+ */
+void get_frer_static_counter(struct frer_static_counter *data)
+{
+	int offset = (data->num) * 8;
+
+	data->frer_fr_count.lsb = axienet_ior(&lp, TOTAL_FRER_FRAMES_OFFSET +
+									offset);
+	data->frer_fr_count.msb = axienet_ior(&lp, TOTAL_FRER_FRAMES_OFFSET +
+								offset + 0x4);
+
+	data->disc_frames_in_portid.lsb = axienet_ior(&lp,
+						      FRER_DISCARD_INGS_FLTR_OFFSET + offset);
+	data->disc_frames_in_portid.msb = axienet_ior(&lp,
+						      FRER_DISCARD_INGS_FLTR_OFFSET + offset + 0x4);
+
+	data->pass_frames_ind_recv.lsb = axienet_ior(&lp,
+						     FRER_PASS_FRAMES_INDV_OFFSET + offset);
+	data->pass_frames_ind_recv.msb = axienet_ior(&lp,
+						     FRER_PASS_FRAMES_INDV_OFFSET + offset + 0x4);
+
+	data->disc_frames_ind_recv.lsb = axienet_ior(&lp,
+						     FRER_DISCARD_FRAMES_INDV_OFFSET + offset);
+	data->disc_frames_ind_recv.msb = axienet_ior(&lp,
+						     FRER_DISCARD_FRAMES_INDV_OFFSET + offset + 0x4);
+
+	data->pass_frames_seq_recv.lsb = axienet_ior(&lp,
+						     FRER_PASS_FRAMES_SEQ_OFFSET + offset);
+	data->pass_frames_seq_recv.msb = axienet_ior(&lp,
+						     FRER_PASS_FRAMES_SEQ_OFFSET + offset + 0x4);
+
+	data->disc_frames_seq_recv.lsb = axienet_ior(&lp,
+						     FRER_DISCARD_FRAMES_SEQ_OFFSET + offset);
+	data->disc_frames_seq_recv.msb = axienet_ior(&lp,
+						     FRER_DISCARD_FRAMES_SEQ_OFFSET + offset + 0x4);
+
+	data->rogue_frames_seq_recv.lsb = axienet_ior(&lp,
+						      FRER_ROGUE_FRAMES_SEQ_OFFSET + offset);
+	data->rogue_frames_seq_recv.msb = axienet_ior(&lp,
+						      FRER_ROGUE_FRAMES_SEQ_OFFSET + offset + 0x4);
+
+	data->seq_recv_rst.lsb = axienet_ior(&lp,
+					     SEQ_RECV_RESETS_OFFSET + offset);
+	data->seq_recv_rst.msb = axienet_ior(&lp,
+					     SEQ_RECV_RESETS_OFFSET + offset + 0x4);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/xilinx/xilinx_tsn_ep.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/xilinx/xilinx_tsn_ep.c
@@ -0,0 +1,161 @@
+/*
+ * Xilinx FPGA Xilinx TSN End point driver.
+ *
+ * Copyright (c) 2017 Xilinx Pvt., Ltd
+ *
+ * Author: Saurabh Sengar <saurabhs@xilinx.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/etherdevice.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/skbuff.h>
+
+#include "xilinx_axienet.h"
+
+/**
+ * tsn_ep_ioctl - TSN endpoint ioctl interface.
+ * @dev: Pointer to the net_device structure
+ * @rq: Socket ioctl interface request structure
+ * @cmd: Ioctl case
+ *
+ * Return: 0 on success, Non-zero error value on failure.
+ *
+ * This is the ioctl interface for TSN end point. Currently this
+ * supports only gate programming.
+ */
+static int tsn_ep_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	switch (cmd) {
+#ifdef CONFIG_XILINX_TSN_QBV
+	case SIOCCHIOCTL:
+		return axienet_set_schedule(dev, rq->ifr_data);
+	case SIOC_GET_SCHED:
+		return axienet_get_schedule(dev, rq->ifr_data);
+#endif
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+/**
+ * tsn_ep_xmit - TSN endpoint xmit routine.
+ * @skb: Packet data
+ * @dev: Pointer to the net_device structure
+ *
+ * Return: Always returns NETDEV_TX_OK.
+ *
+ * This is dummy xmit function for endpoint as all the data path is assumed to
+ * be connected by TEMAC1 as per linux view
+ */
+static int tsn_ep_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	kfree_skb(skb);
+	return NETDEV_TX_OK;
+}
+
+static const struct net_device_ops ep_netdev_ops = {
+	.ndo_do_ioctl = tsn_ep_ioctl,
+	.ndo_start_xmit = tsn_ep_xmit,
+};
+
+static const struct of_device_id tsn_ep_of_match[] = {
+	{ .compatible = "xlnx,tsn-ep"},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, tsn_ep_of_match);
+
+/**
+ * tsn_ep_probe - TSN ep pointer probe function.
+ * @pdev:	Pointer to platform device structure.
+ *
+ * Return: 0, on success
+ *	    Non-zero error value on failure.
+ *
+ * This is the probe routine for TSN endpoint driver.
+ */
+static int tsn_ep_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct axienet_local *lp;
+	struct net_device *ndev;
+	struct resource *ethres;
+	u16 num_tc = 0;
+
+	ndev = alloc_netdev(0, "ep", NET_NAME_UNKNOWN, ether_setup);
+	if (!ndev)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, ndev);
+
+	SET_NETDEV_DEV(ndev, &pdev->dev);
+	ndev->netdev_ops = &ep_netdev_ops;
+
+	lp = netdev_priv(ndev);
+	lp->ndev = ndev;
+	lp->dev = &pdev->dev;
+	lp->options = XAE_OPTION_DEFAULTS;
+
+	ret = of_property_read_u16(
+		pdev->dev.of_node, "xlnx,num-tc", &num_tc);
+	if (ret || (num_tc != 2 && num_tc != 3))
+		lp->num_tc = XAE_MAX_TSN_TC;
+	else
+		lp->num_tc = num_tc;
+	/* Map device registers */
+	ethres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	lp->regs = devm_ioremap_resource(&pdev->dev, ethres);
+	if (IS_ERR(lp->regs)) {
+		ret = PTR_ERR(lp->regs);
+		goto free_netdev;
+	}
+
+	ret = register_netdev(lp->ndev);
+	if (ret)
+		dev_err(lp->dev, "register_netdev() error (%i)\n", ret);
+
+	return ret;
+
+free_netdev:
+	free_netdev(ndev);
+
+	return ret;
+}
+
+static int tsn_ep_remove(struct platform_device *pdev)
+{
+	struct net_device *ndev = platform_get_drvdata(pdev);
+
+	unregister_netdev(ndev);
+
+	free_netdev(ndev);
+
+	return 0;
+}
+
+static struct platform_driver tsn_ep_driver = {
+	.probe = tsn_ep_probe,
+	.remove = tsn_ep_remove,
+	.driver = {
+		 .name = "tsn_ep_axienet",
+		 .of_match_table = tsn_ep_of_match,
+	},
+};
+
+module_platform_driver(tsn_ep_driver);
+
+MODULE_DESCRIPTION("Xilinx Axi Ethernet driver");
+MODULE_AUTHOR("Xilinx");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/xilinx/xilinx_tsn_preemption.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/xilinx/xilinx_tsn_preemption.c
@@ -0,0 +1,223 @@
+/*
+ * Xilinx FPGA Xilinx TSN QBU/QBR - Frame Preemption module.
+ *
+ * Copyright (c) 2017 Xilinx Pvt., Ltd
+ *
+ * Author: Priyadarshini Babu <priyadar@xilinx.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "xilinx_axienet.h"
+#include "xilinx_tsn_preemption.h"
+
+/**
+ * axienet_preemption -  Configure Frame Preemption
+ * @ndev: Pointer to the net_device structure
+ * @useraddr: Value to be programmed
+ * Return: 0 on success, Non-zero error value on failure
+ */
+int axienet_preemption(struct net_device *ndev, void __user *useraddr)
+{
+	struct axienet_local *lp = netdev_priv(ndev);
+	u8 preemp;
+
+	if (copy_from_user(&preemp, useraddr, sizeof(preemp)))
+		return -EFAULT;
+
+	axienet_iow(lp, PREEMPTION_ENABLE_REG, preemp & PREEMPTION_ENABLE);
+	return 0;
+}
+
+/**
+ * axienet_preemption_ctrl -  Configure Frame Preemption Control register
+ * @ndev: Pointer to the net_device structure
+ * @useraddr: Value to be programmed
+ * Return: 0 on success, Non-zero error value on failure
+ */
+int axienet_preemption_ctrl(struct net_device *ndev, void __user *useraddr)
+{
+	struct axienet_local *lp = netdev_priv(ndev);
+	struct preempt_ctrl_sts data;
+	u32 value;
+
+	if (copy_from_user(&data, useraddr, sizeof(struct preempt_ctrl_sts)))
+		return -EFAULT;
+	value = axienet_ior(lp, PREEMPTION_CTRL_STS_REG);
+
+	value &= ~(VERIFY_TIMER_VALUE_MASK << VERIFY_TIMER_VALUE_SHIFT);
+	value |= (data.verify_timer_value << VERIFY_TIMER_VALUE_SHIFT);
+	value &= ~(ADDITIONAL_FRAG_SIZE_MASK << ADDITIONAL_FRAG_SIZE_SHIFT);
+	value |= (data.additional_frag_size << ADDITIONAL_FRAG_SIZE_SHIFT);
+	value &= ~(DISABLE_PREEMPTION_VERIFY);
+	value |= (data.disable_preemp_verify);
+
+	axienet_iow(lp, PREEMPTION_CTRL_STS_REG, value);
+	return 0;
+}
+
+/**
+ * axienet_preemption_sts -  Get Frame Preemption Status
+ * @ndev: Pointer to the net_device structure
+ * @useraddr: return value, containing Frame Preemption status
+ * Return: 0 on success, Non-zero error value on failure
+ */
+int axienet_preemption_sts(struct net_device *ndev, void __user *useraddr)
+{
+	struct axienet_local *lp = netdev_priv(ndev);
+	struct preempt_ctrl_sts status;
+	u32 value;
+
+	value = axienet_ior(lp, PREEMPTION_CTRL_STS_REG);
+
+	status.tx_preemp_sts = (value & TX_PREEMPTION_STS) ? 1 : 0;
+	status.mac_tx_verify_sts = (value >> MAC_MERGE_TX_VERIFY_STS_SHIFT) &
+					MAC_MERGE_TX_VERIFY_STS_MASK;
+	status.verify_timer_value = (value >> VERIFY_TIMER_VALUE_SHIFT) &
+					VERIFY_TIMER_VALUE_MASK;
+	status.additional_frag_size = (value >> ADDITIONAL_FRAG_SIZE_SHIFT) &
+					ADDITIONAL_FRAG_SIZE_MASK;
+	status.disable_preemp_verify = value & DISABLE_PREEMPTION_VERIFY;
+
+	if (copy_to_user(useraddr, &status, sizeof(struct preempt_ctrl_sts)))
+		return -EFAULT;
+	return 0;
+}
+
+/**
+ * statistic_cnts -  Read statistics counter registers
+ * @ndev: Pointer to the net_device structure
+ * @ptr: Buffer addr to fill the counter values
+ * @count: read #count number of registers
+ * @addr_off: Register address to be read
+ */
+static void statistic_cnts(struct net_device *ndev, void *ptr,
+			   unsigned int count, unsigned int addr_off)
+{
+	struct axienet_local *lp = netdev_priv(ndev);
+	int *buf = (int *)ptr;
+	int i = 0;
+
+	for (i = 0; i < count; i++) {
+		buf[i] = axienet_ior(lp, addr_off);
+		addr_off += 4;
+	}
+}
+
+/**
+ * axienet_preemption_cnt -  Get Frame Preemption Statistics counter
+ * @ndev: Pointer to the net_device structure
+ * @useraddr: return value, containing counters value
+ * Return: 0 on success, Non-zero error value on failure
+ */
+int axienet_preemption_cnt(struct net_device *ndev, void __user *useraddr)
+{
+	struct axienet_local *lp = netdev_priv(ndev);
+	struct emac_pmac_stats stats;
+
+	statistic_cnts(ndev, &stats.emac,
+		       sizeof(struct statistics_counters) / 4,
+		       RX_BYTES_EMAC_REG);
+
+	stats.preemp_en = axienet_ior(lp, PREEMPTION_ENABLE_REG);
+	if (stats.preemp_en) {
+		statistic_cnts(ndev, &stats.pmac.sts,
+			       sizeof(struct statistics_counters) / 4,
+			       RX_BYTES_PMAC_REG);
+		statistic_cnts(ndev, &stats.pmac.merge,
+			       sizeof(struct mac_merge_counters) / 4,
+			       TX_HOLD_REG);
+	}
+
+	if (copy_to_user(useraddr, &stats, sizeof(struct emac_pmac_stats)))
+		return -EFAULT;
+	return 0;
+}
+
+/**
+ * axienet_qbu_user_override -  Configure QBU user override register
+ * @ndev: Pointer to the net_device structure
+ * @useraddr: Value to be programmed
+ * Return: 0 on success, Non-zero error value on failure
+ */
+int axienet_qbu_user_override(struct net_device *ndev, void __user *useraddr)
+{
+	struct axienet_local *lp = netdev_priv(ndev);
+	struct qbu_user data;
+	u32 value;
+
+	if (copy_from_user(&data, useraddr, sizeof(struct qbu_user)))
+		return -EFAULT;
+
+	value = axienet_ior(lp, QBU_USER_OVERRIDE_REG);
+
+	if (data.set & QBU_WINDOW) {
+		if (data.user.hold_rel_window) {
+			value |= USER_HOLD_REL_ENABLE_VALUE;
+			value |= HOLD_REL_WINDOW_OVERRIDE;
+		} else {
+			value &= ~(USER_HOLD_REL_ENABLE_VALUE);
+			value &= ~(HOLD_REL_WINDOW_OVERRIDE);
+		}
+	}
+	if (data.set & QBU_GUARD_BAND) {
+		if (data.user.guard_band)
+			value |= GUARD_BAND_OVERRUN_CNT_INC_OVERRIDE;
+		else
+			value &= ~(GUARD_BAND_OVERRUN_CNT_INC_OVERRIDE);
+	}
+	if (data.set & QBU_HOLD_TIME) {
+		if (data.user.hold_time_override) {
+			value |= HOLD_TIME_OVERRIDE;
+			value &= ~(USER_HOLD_TIME_MASK << USER_HOLD_TIME_SHIFT);
+			value |= data.user.user_hold_time <<
+					USER_HOLD_TIME_SHIFT;
+		} else {
+			value &= ~(HOLD_TIME_OVERRIDE);
+			value &= ~(USER_HOLD_TIME_MASK << USER_HOLD_TIME_SHIFT);
+		}
+	}
+	if (data.set & QBU_REL_TIME) {
+		if (data.user.rel_time_override) {
+			value |= REL_TIME_OVERRIDE;
+			value &= ~(USER_REL_TIME_MASK << USER_REL_TIME_SHIFT);
+			value |= data.user.user_rel_time << USER_REL_TIME_SHIFT;
+		} else {
+			value &= ~(REL_TIME_OVERRIDE);
+			value &= ~(USER_REL_TIME_MASK << USER_REL_TIME_SHIFT);
+		}
+	}
+
+	axienet_iow(lp, QBU_USER_OVERRIDE_REG, value);
+	return 0;
+}
+
+/**
+ * axienet_qbu_sts -  Get QBU Core status
+ * @ndev: Pointer to the net_device structure
+ * @useraddr: return value, containing QBU core status value
+ * Return: 0 on success, Non-zero error value on failure
+ */
+int axienet_qbu_sts(struct net_device *ndev, void __user *useraddr)
+{
+	struct axienet_local *lp = netdev_priv(ndev);
+	struct qbu_core_status status;
+	u32 value = 0;
+
+	value = axienet_ior(lp, QBU_CORE_STS_REG);
+	status.hold_time = (value >> HOLD_TIME_STS_SHIFT) & HOLD_TIME_STS_MASK;
+	status.rel_time = (value >> REL_TIME_STS_SHIFT) & REL_TIME_STS_MASK;
+	status.hold_rel_en = (value & HOLD_REL_ENABLE_STS) ? 1 : 0;
+	status.pmac_hold_req = value & PMAC_HOLD_REQ_STS;
+
+	if (copy_to_user(useraddr, &status, sizeof(struct qbu_core_status)))
+		return -EFAULT;
+	return 0;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/xilinx/xilinx_tsn_preemption.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/xilinx/xilinx_tsn_preemption.h
@@ -0,0 +1,159 @@
+/**
+ * Xilinx TSN QBU/QBR - Frame Preemption header
+ *
+ * Copyright (C) 2017 Xilinx, Inc.
+ *
+ * Author: Priyadarshini Babu <priyadar@xilinx.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef XILINX_TSN_PREEMPTION_H
+#define XILINX_TSN_PREEMPTION_H
+
+#define PREEMPTION_ENABLE_REG			0x00000440
+#define PREEMPTION_CTRL_STS_REG			0x00000444
+#define QBU_USER_OVERRIDE_REG			0x00000448
+#define QBU_CORE_STS_REG			0x0000044c
+#define TX_HOLD_REG				0x00000910
+#define RX_BYTES_EMAC_REG			0x00000200
+#define RX_BYTES_PMAC_REG			0x00000800
+
+#define PREEMPTION_ENABLE			BIT(0)
+
+#define TX_PREEMPTION_STS			BIT(31)
+#define MAC_MERGE_TX_VERIFY_STS_MASK		0x7
+#define MAC_MERGE_TX_VERIFY_STS_SHIFT		24
+#define VERIFY_TIMER_VALUE_MASK			0x7F
+#define VERIFY_TIMER_VALUE_SHIFT		8
+#define ADDITIONAL_FRAG_SIZE_MASK		0x3
+#define ADDITIONAL_FRAG_SIZE_SHIFT		4
+#define DISABLE_PREEMPTION_VERIFY		BIT(0)
+
+#define USER_HOLD_REL_ENABLE_VALUE		BIT(31)
+#define USER_HOLD_TIME_MASK			0x1FF
+#define USER_HOLD_TIME_SHIFT			16
+#define USER_REL_TIME_MASK			0x3F
+#define USER_REL_TIME_SHIFT			8
+#define GUARD_BAND_OVERRUN_CNT_INC_OVERRIDE	BIT(3)
+#define HOLD_REL_WINDOW_OVERRIDE		BIT(2)
+#define HOLD_TIME_OVERRIDE			BIT(1)
+#define REL_TIME_OVERRIDE			BIT(0)
+
+#define HOLD_REL_ENABLE_STS			BIT(31)
+#define HOLD_TIME_STS_MASK			0x1FF
+#define HOLD_TIME_STS_SHIFT			16
+#define REL_TIME_STS_MASK			0x3F
+#define REL_TIME_STS_SHIFT			8
+#define PMAC_HOLD_REQ_STS			BIT(0)
+
+struct preempt_ctrl_sts {
+	u8 tx_preemp_sts:1;
+	u8 mac_tx_verify_sts:3;
+	u8 verify_timer_value:7;
+	u8 additional_frag_size:2;
+	u8 disable_preemp_verify:1;
+} __packed;
+
+struct qbu_user_override {
+	u8 enable_value:1;
+	u16 user_hold_time:9;
+	u8 user_rel_time:6;
+	u8 guard_band:1;
+	u8 hold_rel_window:1;
+	u8 hold_time_override:1;
+	u8 rel_time_override:1;
+} __packed;
+
+struct qbu_user {
+	struct qbu_user_override user;
+	u8 set;
+};
+
+#define QBU_WINDOW BIT(0)
+#define QBU_GUARD_BAND BIT(1)
+#define QBU_HOLD_TIME BIT(2)
+#define QBU_REL_TIME BIT(3)
+
+struct qbu_core_status {
+	u16 hold_time;
+	u8 rel_time;
+	u8 hold_rel_en:1;
+	u8 pmac_hold_req:1;
+} __packed;
+
+struct cnt_64 {
+	unsigned int msb;
+	unsigned int lsb;
+};
+
+union static_cntr {
+	u64 cnt;
+	struct cnt_64 word;
+};
+
+struct mac_merge_counters {
+	union static_cntr tx_hold_cnt;
+	union static_cntr tx_frag_cnt;
+	union static_cntr rx_assembly_ok_cnt;
+	union static_cntr rx_assembly_err_cnt;
+	union static_cntr rx_smd_err_cnt;
+	union static_cntr rx_frag_cnt;
+};
+
+struct statistics_counters {
+	union static_cntr rx_bytes_cnt;
+	union static_cntr tx_bytes_cnt;
+	union static_cntr undersize_frames_cnt;
+	union static_cntr frag_frames_cnt;
+	union static_cntr rx_64_bytes_frames_cnt;
+	union static_cntr rx_65_127_bytes_frames_cnt;
+	union static_cntr rx_128_255_bytes_frames_cnt;
+	union static_cntr rx_256_511_bytes_frames_cnt;
+	union static_cntr rx_512_1023_bytes_frames_cnt;
+	union static_cntr rx_1024_max_frames_cnt;
+	union static_cntr rx_oversize_frames_cnt;
+	union static_cntr tx_64_bytes_frames_cnt;
+	union static_cntr tx_65_127_bytes_frames_cnt;
+	union static_cntr tx_128_255_bytes_frames_cnt;
+	union static_cntr tx_256_511_bytes_frames_cnt;
+	union static_cntr tx_512_1023_bytes_frames_cnt;
+	union static_cntr tx_1024_max_frames_cnt;
+	union static_cntr tx_oversize_frames_cnt;
+	union static_cntr rx_good_frames_cnt;
+	union static_cntr rx_fcs_err_cnt;
+	union static_cntr rx_good_broadcast_frames_cnt;
+	union static_cntr rx_good_multicast_frames_cnt;
+	union static_cntr rx_good_control_frames_cnt;
+	union static_cntr rx_out_of_range_err_cnt;
+	union static_cntr rx_good_vlan_frames_cnt;
+	union static_cntr rx_good_pause_frames_cnt;
+	union static_cntr rx_bad_opcode_frames_cnt;
+	union static_cntr tx_good_frames_cnt;
+	union static_cntr tx_good_broadcast_frames_cnt;
+	union static_cntr tx_good_multicast_frames_cnt;
+	union static_cntr tx_underrun_err_cnt;
+	union static_cntr tx_good_control_frames_cnt;
+	union static_cntr tx_good_vlan_frames_cnt;
+	union static_cntr tx_good_pause_frames_cnt;
+};
+
+struct pmac_counters {
+	struct statistics_counters sts;
+	struct mac_merge_counters merge;
+};
+
+struct emac_pmac_stats {
+	u8 preemp_en;
+	struct statistics_counters emac;
+	struct pmac_counters pmac;
+};
+
+#endif /* XILINX_TSN_PREEMPTION_H */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/xilinx/xilinx_tsn_ptp.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/xilinx/xilinx_tsn_ptp.h
@@ -0,0 +1,88 @@
+/*
+ * Xilinx TSN PTP header
+ *
+ * Copyright (C) 2017 Xilinx, Inc.
+ *
+ * Author: Syed S <syeds@xilinx.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _TSN_PTP_H_
+#define _TSN_PTP_H_
+
+#define PTP_HW_TSTAMP_SIZE  8   /* 64 bit timestamp */
+#define PTP_RX_HWBUF_SIZE   256
+#define PTP_RX_FRAME_SIZE   252
+#define PTP_HW_TSTAMP_OFFSET (PTP_RX_HWBUF_SIZE - PTP_HW_TSTAMP_SIZE)
+
+#define PTP_MSG_TYPE_MASK				BIT(3)
+#define PTP_TYPE_SYNC                                   0x0
+#define PTP_TYPE_FOLLOW_UP                              0x8
+#define PTP_TYPE_PDELAYREQ                              0x2
+#define PTP_TYPE_PDELAYRESP                             0x3
+#define PTP_TYPE_PDELAYRESP_FOLLOW_UP                   0xA
+#define PTP_TYPE_ANNOUNCE                               0xB
+#define PTP_TYPE_SIGNALING                              0xC
+
+#define PTP_TX_CONTROL_OFFSET		0x00012000 /**< Tx PTP Control Reg */
+#define PTP_RX_CONTROL_OFFSET		0x00012004 /**< Rx PTP Control Reg */
+#define RX_FILTER_CONTROL		0x00012008 /**< Rx Filter Ctrl Reg */
+
+#define PTP_RX_BASE_OFFSET		0x00010000
+#define PTP_RX_CONTROL_OFFSET		0x00012004 /**< Rx PTP Control Reg */
+#define PTP_RX_PACKET_FIELD_MASK	0x00000F00
+#define PTP_RX_PACKET_CLEAR		0x00000001
+
+#define PTP_TX_BUFFER_OFFSET(index)	   (0x00011000 + (index) * 0x100)
+
+#define PTP_TX_CMD_FIELD_LEN			8
+#define PTP_TX_CMD_1STEP_SHIFT			BIT(16)
+#define PTP_TX_BUFFER_CMD2_FIELD		0x4
+
+#define PTP_TX_SYNC_OFFSET                 0x00011000
+#define PTP_TX_FOLLOW_UP_OFFSET            0x00011100
+#define PTP_TX_PDELAYREQ_OFFSET            0x00011200
+#define PTP_TX_PDELAYRESP_OFFSET           0x00011300
+#define PTP_TX_PDELAYRESP_FOLLOW_UP_OFFSET 0x00011400
+#define PTP_TX_ANNOUNCE_OFFSET             0x00011500
+#define PTP_TX_SIGNALING_OFFSET		   0x00011600
+#define PTP_TX_GENERIC_OFFSET		   0x00011700
+#define PTP_TX_SEND_SYNC_FRAME_MASK                     0x00000001
+#define PTP_TX_SEND_FOLLOWUP_FRAME_MASK                 0x00000002
+#define PTP_TX_SEND_PDELAYREQ_FRAME_MASK                0x00000004
+#define PTP_TX_SEND_PDELAYRESP_FRAME_MASK               0x00000008
+#define PTP_TX_SEND_PDELAYRESPFOLLOWUP_FRAME_MASK       0x00000010
+#define PTP_TX_SEND_ANNOUNCE_FRAME_MASK                 0x00000020
+#define PTP_TX_SEND_FRAME6_BIT_MASK                     0x00000040
+#define PTP_TX_SEND_FRAME7_BIT_MASK                     0x00000080
+#define PTP_TX_FRAME_WAITING_MASK			0x0000ff00
+#define PTP_TX_FRAME_WAITING_SHIFT			8
+#define PTP_TX_WAIT_SYNC_FRAME_MASK                     0x00000100
+#define PTP_TX_WAIT_FOLLOWUP_FRAME_MASK                 0x00000200
+#define PTP_TX_WAIT_PDELAYREQ_FRAME_MASK                0x00000400
+#define PTP_TX_WAIT_PDELAYRESP_FRAME_MASK               0x00000800
+#define PTP_TX_WAIT_PDELAYRESPFOLLOWUP_FRAME_MASK       0x00001000
+#define PTP_TX_WAIT_ANNOUNCE_FRAME_MASK                 0x00002000
+#define PTP_TX_WAIT_FRAME6_BIT_MASK                     0x00004000
+#define PTP_TX_WAIT_FRAME7_BIT_MASK                     0x00008000
+#define PTP_TX_WAIT_ALL_FRAMES_MASK                     0x0000FF00
+#define PTP_TX_PACKET_FIELD_MASK                        0x00070000
+#define PTP_TX_PACKET_FIELD_SHIFT                       16
+/* 1-step Correction Field offset 802.1 ASrev */
+#define PTP_CRCT_FIELD_OFFSET				22
+/* 1-step Time Of Day offset 1588-2008 */
+#define PTP_TOD_FIELD_OFFSET				48
+
+int axienet_ptp_xmit(struct sk_buff *skb, struct net_device *ndev);
+irqreturn_t axienet_ptp_rx_irq(int irq, void *_ndev);
+irqreturn_t axienet_ptp_tx_irq(int irq, void *_ndev);
+
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/xilinx/xilinx_tsn_ptp_clock.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/xilinx/xilinx_tsn_ptp_clock.c
@@ -0,0 +1,325 @@
+/*
+ * Xilinx FPGA Xilinx TSN PTP protocol clock Controller module.
+ *
+ * Copyright (c) 2017 Xilinx Pvt., Ltd
+ *
+ * Author: Syed S <syeds@xilinx.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/ptp_clock_kernel.h>
+#include <linux/platform_device.h>
+#include <linux/of_irq.h>
+#include "xilinx_tsn_timer.h"
+
+struct xlnx_ptp_timer {
+	struct                 device *dev;
+	void __iomem          *baseaddr;
+	struct ptp_clock      *ptp_clock;
+	struct ptp_clock_info  ptp_clock_info;
+	spinlock_t             reg_lock; /* ptp timer lock */
+	int                    irq;
+	int                    pps_enable;
+	int                    countpulse;
+};
+
+static void xlnx_tod_read(struct xlnx_ptp_timer *timer, struct timespec64 *ts)
+{
+	u32 sec, nsec;
+
+	nsec = in_be32(timer->baseaddr + XTIMER1588_CURRENT_RTC_NS);
+	sec = in_be32(timer->baseaddr + XTIMER1588_CURRENT_RTC_SEC_L);
+
+	ts->tv_sec = sec;
+	ts->tv_nsec = nsec;
+}
+
+static void xlnx_rtc_offset_write(struct xlnx_ptp_timer *timer,
+				  const struct timespec64 *ts)
+{
+	pr_debug("%s: sec: %ld nsec: %ld\n", __func__, ts->tv_sec, ts->tv_nsec);
+
+	out_be32((timer->baseaddr + XTIMER1588_RTC_OFFSET_SEC_H), 0);
+	out_be32((timer->baseaddr + XTIMER1588_RTC_OFFSET_SEC_L),
+		 (ts->tv_sec));
+	out_be32((timer->baseaddr + XTIMER1588_RTC_OFFSET_NS), ts->tv_nsec);
+}
+
+static void xlnx_rtc_offset_read(struct xlnx_ptp_timer *timer,
+				 struct timespec64 *ts)
+{
+	ts->tv_sec = in_be32(timer->baseaddr + XTIMER1588_RTC_OFFSET_SEC_L);
+	ts->tv_nsec = in_be32(timer->baseaddr + XTIMER1588_RTC_OFFSET_NS);
+}
+
+/* PTP clock operations
+ */
+static int xlnx_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+{
+	struct xlnx_ptp_timer *timer = container_of(ptp, struct xlnx_ptp_timer,
+						    ptp_clock_info);
+
+	int neg_adj = 0;
+	u64 freq;
+	u32 diff, incval;
+
+	/* This number should be replaced by a call to get the frequency
+	 * from the device-tree. Currently assumes 125MHz
+	 */
+	incval = 0x800000;
+	/* for 156.25 MHZ Ref clk the value is  incval = 0x800000; */
+
+	if (ppb < 0) {
+		neg_adj = 1;
+		ppb = -ppb;
+	}
+
+	freq = incval;
+	freq *= ppb;
+	diff = div_u64(freq, 1000000000ULL);
+
+	pr_debug("%s: adj: %d ppb: %d\n", __func__, diff, ppb);
+
+	incval = neg_adj ? (incval - diff) : (incval + diff);
+	out_be32((timer->baseaddr + XTIMER1588_RTC_INCREMENT), incval);
+	return 0;
+}
+
+static int xlnx_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+	unsigned long flags;
+	struct xlnx_ptp_timer *timer = container_of(ptp, struct xlnx_ptp_timer,
+						    ptp_clock_info);
+	struct timespec64 now, then = ns_to_timespec64(delta);
+
+	spin_lock_irqsave(&timer->reg_lock, flags);
+
+	xlnx_rtc_offset_read(timer, &now);
+
+	now = timespec64_add(now, then);
+
+	xlnx_rtc_offset_write(timer, (const struct timespec64 *)&now);
+	spin_unlock_irqrestore(&timer->reg_lock, flags);
+
+	return 0;
+}
+
+static int xlnx_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
+{
+	unsigned long flags;
+	struct xlnx_ptp_timer *timer = container_of(ptp, struct xlnx_ptp_timer,
+						    ptp_clock_info);
+	spin_lock_irqsave(&timer->reg_lock, flags);
+
+	xlnx_tod_read(timer, ts);
+
+	spin_unlock_irqrestore(&timer->reg_lock, flags);
+	return 0;
+}
+
+/**
+ * xlnx_ptp_settime - Set the current time on the hardware clock
+ * @ptp: ptp clock structure
+ * @ts: timespec64 containing the new time for the cycle counter
+ *
+ * Return: 0 in all cases.
+ *
+ * The seconds register is written first, then the nanosecond
+ * The hardware loads the entire new value when a nanosecond register
+ * is written
+ **/
+static int xlnx_ptp_settime(struct ptp_clock_info *ptp,
+			    const struct timespec64 *ts)
+{
+	struct xlnx_ptp_timer *timer = container_of(ptp, struct xlnx_ptp_timer,
+						    ptp_clock_info);
+	struct timespec64 delta, tod;
+	struct timespec64 offset;
+	unsigned long flags;
+
+	spin_lock_irqsave(&timer->reg_lock, flags);
+
+	/* First zero the offset */
+	offset.tv_sec = 0;
+	offset.tv_nsec = 0;
+	xlnx_rtc_offset_write(timer, &offset);
+
+	/* Get the current timer value */
+	xlnx_tod_read(timer, &tod);
+
+	/* Subtract the current reported time from our desired time */
+	delta = timespec64_sub(*ts, tod);
+
+	/* Don't write a negative offset */
+	if (delta.tv_sec <= 0) {
+		delta.tv_sec = 0;
+		if (delta.tv_nsec < 0)
+			delta.tv_nsec = 0;
+	}
+
+	xlnx_rtc_offset_write(timer, &delta);
+	spin_unlock_irqrestore(&timer->reg_lock, flags);
+	return 0;
+}
+
+static int xlnx_ptp_enable(struct ptp_clock_info *ptp,
+			   struct ptp_clock_request *rq, int on)
+{
+	struct xlnx_ptp_timer *timer = container_of(ptp, struct xlnx_ptp_timer,
+						    ptp_clock_info);
+
+	switch (rq->type) {
+	case PTP_CLK_REQ_PPS:
+		timer->pps_enable = 1;
+		return 0;
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+static struct ptp_clock_info xlnx_ptp_clock_info = {
+	.owner    = THIS_MODULE,
+	.name     = "Xilinx Timer",
+	.max_adj  = 999999999,
+	.n_ext_ts	= 0,
+	.pps      = 1,
+	.adjfreq  = xlnx_ptp_adjfreq,
+	.adjtime  = xlnx_ptp_adjtime,
+	.gettime64  = xlnx_ptp_gettime,
+	.settime64 = xlnx_ptp_settime,
+	.enable   = xlnx_ptp_enable,
+};
+
+/* module operations */
+
+/**
+ * xlnx_ptp_timer_isr - Interrupt Service Routine
+ * @irq:               IRQ number
+ * @priv:              pointer to the timer structure
+ *
+ * Returns: IRQ_HANDLED for all cases
+ *
+ * Handles the timer interrupt. The timer interrupt fires 128 times per
+ * secound. When our count reaches 128 emit a PTP_CLOCK_PPS event
+ */
+static irqreturn_t xlnx_ptp_timer_isr(int irq, void *priv)
+{
+	struct xlnx_ptp_timer *timer = (struct xlnx_ptp_timer *)priv;
+	struct ptp_clock_event event;
+
+	event.type = PTP_CLOCK_PPS;
+	++timer->countpulse;
+	if (timer->countpulse >= PULSESIN1PPS) {
+		timer->countpulse = 0;
+		if ((timer->ptp_clock) && (timer->pps_enable))
+			ptp_clock_event(timer->ptp_clock, &event);
+	}
+	out_be32((timer->baseaddr + XTIMER1588_INTERRUPT),
+		 (1 << XTIMER1588_INT_SHIFT));
+
+	return IRQ_HANDLED;
+}
+
+int axienet_ptp_timer_remove(void *priv)
+{
+	struct xlnx_ptp_timer *timer = (struct xlnx_ptp_timer *)priv;
+
+	free_irq(timer->irq, (void *)timer);
+
+	axienet_phc_index = -1;
+	if (timer->ptp_clock) {
+		ptp_clock_unregister(timer->ptp_clock);
+		timer->ptp_clock = NULL;
+	}
+	kfree(timer);
+	return 0;
+}
+
+int axienet_get_phc_index(void *priv)
+{
+	struct xlnx_ptp_timer *timer = (struct xlnx_ptp_timer *)priv;
+
+	if (timer->ptp_clock)
+		return ptp_clock_index(timer->ptp_clock);
+	else
+		return -1;
+}
+
+void *axienet_ptp_timer_probe(void __iomem *base, struct platform_device *pdev)
+{
+	struct xlnx_ptp_timer *timer;
+	struct timespec64 ts;
+	int err = 0;
+
+	timer = kzalloc(sizeof(*timer), GFP_KERNEL);
+	if (!timer)
+		return NULL;
+
+	timer->baseaddr = base;
+
+	timer->irq = platform_get_irq_byname(pdev, "interrupt_ptp_timer");
+
+	if (timer->irq < 0) {
+		timer->irq = platform_get_irq_byname(pdev, "rtc_irq");
+		if (timer->irq > 0) {
+			pr_err("ptp timer interrupt name 'rtc_irq' is"
+				"deprecated\n");
+		} else {
+			pr_err("ptp timer interrupt not found\n");
+			kfree(timer);
+			return NULL;
+		}
+	}
+	spin_lock_init(&timer->reg_lock);
+
+	timer->ptp_clock_info = xlnx_ptp_clock_info;
+
+	timer->ptp_clock = ptp_clock_register(&timer->ptp_clock_info,
+					      &pdev->dev);
+
+	if (IS_ERR(timer->ptp_clock)) {
+		err = PTR_ERR(timer->ptp_clock);
+		pr_debug("Failed to register ptp clock\n");
+		goto out;
+	}
+
+	axienet_phc_index = ptp_clock_index(timer->ptp_clock);
+
+	ts = ktime_to_timespec64(ktime_get_real());
+
+	xlnx_ptp_settime(&timer->ptp_clock_info, &ts);
+
+	/* Enable interrupts */
+	err = request_irq(timer->irq,
+			  xlnx_ptp_timer_isr,
+			  0,
+			  "ptp_rtc",
+			  (void *)timer);
+	if (err)
+		goto err_irq;
+
+	return timer;
+
+err_irq:
+	ptp_clock_unregister(timer->ptp_clock);
+out:
+	timer->ptp_clock = NULL;
+	return NULL;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/xilinx/xilinx_tsn_ptp_xmit.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/xilinx/xilinx_tsn_ptp_xmit.c
@@ -0,0 +1,369 @@
+/*
+ * Xilinx FPGA Xilinx TSN PTP transfer protocol module.
+ *
+ * Copyright (c) 2017 Xilinx Pvt., Ltd
+ *
+ * Author: Syed S <syeds@xilinx.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "xilinx_axienet.h"
+#include "xilinx_tsn_ptp.h"
+#include "xilinx_tsn_timer.h"
+#include <linux/ptp_classify.h>
+
+#define PTP_ONE_SECOND            1000000000    /**< Value in ns */
+
+#define msg_type_string(type) \
+	((type) == PTP_TYPE_SYNC) ? "SYNC" : \
+	((type) == PTP_TYPE_FOLLOW_UP)		  ? "FOLLOW_UP" : \
+	((type) == PTP_TYPE_PDELAYREQ)		  ? "PDELAY_REQ" : \
+	((type) == PTP_TYPE_PDELAYRESP)		  ? "PDELAY_RESP" : \
+	((type) == PTP_TYPE_PDELAYRESP_FOLLOW_UP) ? "PDELAY_RESP_FOLLOW_UP" : \
+	((type) == PTP_TYPE_ANNOUNCE)		  ? "ANNOUNCE" : \
+	"UNKNOWN"
+
+/**
+ * memcpy_fromio_32 - copy ptp buffer from HW
+ * @lp:		Pointer to axienet local structure
+ * @offset:	Offset in the PTP buffer
+ * @data:	Destination buffer
+ * @len:	Len to copy
+ *
+ * This functions copies the data from PTP buffer to destination data buffer
+ */
+static void memcpy_fromio_32(struct axienet_local *lp,
+			     unsigned long offset, u8 *data, size_t len)
+{
+	while (len >= 4) {
+		*(u32 *)data = axienet_ior(lp, offset);
+		len -= 4;
+		offset += 4;
+		data += 4;
+	}
+
+	if (len > 0) {
+		u32 leftover = axienet_ior(lp, offset);
+		u8 *src = (u8 *)&leftover;
+
+		while (len) {
+			*data++ = *src++;
+			len--;
+		}
+	}
+}
+
+/**
+ * memcpy_toio_32 - copy ptp buffer from HW
+ * @lp:		Pointer to axienet local structure
+ * @offset:	Offset in the PTP buffer
+ * @data:	Source data
+ * @len:	Len to copy
+ *
+ * This functions copies the source data to desination ptp buffer
+ */
+static void memcpy_toio_32(struct axienet_local *lp,
+			   unsigned long offset, u8 *data, size_t len)
+{
+	while (len >= 4) {
+		axienet_iow(lp, offset, *(u32 *)data);
+		len -= 4;
+		offset += 4;
+		data += 4;
+	}
+
+	if (len > 0) {
+		u32 leftover = 0;
+		u8 *dest = (u8 *)&leftover;
+
+		while (len) {
+			*dest++ = *data++;
+			len--;
+		}
+		axienet_iow(lp, offset, leftover);
+	}
+}
+
+static int is_sync(struct sk_buff *skb)
+{
+	u8 *msg_type;
+
+	msg_type = (u8 *)skb->data + ETH_HLEN;
+
+	return (*msg_type & 0xf) == PTP_TYPE_SYNC;
+}
+
+/**
+ * axienet_ptp_xmit - xmit skb using PTP HW
+ * @skb:	sk_buff pointer that contains data to be Txed.
+ * @ndev:	Pointer to net_device structure.
+ *
+ * Return: NETDEV_TX_OK, on success
+ *	    NETDEV_TX_BUSY, if any of the descriptors are not free
+ *
+ * This function is called to transmit a PTP skb. The function uses
+ * the free PTP TX buffer entry and sends the frame
+ */
+int axienet_ptp_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+	u8 msg_type;
+	struct axienet_local *lp = netdev_priv(ndev);
+	unsigned long flags;
+	u8 tx_frame_waiting;
+	u8 free_index;
+	u32 cmd1_field = 0;
+	u32 cmd2_field = 0;
+
+	msg_type  = *(u8 *)(skb->data + ETH_HLEN);
+
+	pr_debug("  -->XMIT: protocol: %x message: %s frame_len: %d\n",
+		 skb->protocol,
+		 msg_type_string(msg_type & 0xf), skb->len);
+
+	tx_frame_waiting =  (axienet_ior(lp, PTP_TX_CONTROL_OFFSET) &
+				PTP_TX_FRAME_WAITING_MASK) >>
+				PTP_TX_FRAME_WAITING_SHIFT;
+
+	/* we reached last frame */
+	if (tx_frame_waiting & (1 << 7)) {
+		if (!netif_queue_stopped(ndev))
+			netif_stop_queue(ndev);
+		pr_debug("tx_frame_waiting: %d\n", tx_frame_waiting);
+		return NETDEV_TX_BUSY;
+	}
+
+	/* go to next available slot */
+	free_index  = fls(tx_frame_waiting);
+
+	/* write the len */
+	if (lp->ptp_ts_type == HWTSTAMP_TX_ONESTEP_SYNC &&
+	    is_sync(skb)) {
+		/* enable 1STEP SYNC */
+		cmd1_field |= PTP_TX_CMD_1STEP_SHIFT;
+		cmd2_field |= PTP_TOD_FIELD_OFFSET;
+	}
+
+	cmd1_field |= skb->len;
+
+	axienet_iow(lp, PTP_TX_BUFFER_OFFSET(free_index), cmd1_field);
+	axienet_iow(lp, PTP_TX_BUFFER_OFFSET(free_index) +
+			PTP_TX_BUFFER_CMD2_FIELD, cmd2_field);
+	memcpy_toio_32(lp,
+		       (PTP_TX_BUFFER_OFFSET(free_index) +
+			PTP_TX_CMD_FIELD_LEN),
+		       skb->data, skb->len);
+
+	/* send the frame */
+	axienet_iow(lp, PTP_TX_CONTROL_OFFSET, (1 << free_index));
+
+	if (lp->ptp_ts_type != HWTSTAMP_TX_ONESTEP_SYNC ||
+	    (!is_sync(skb))) {
+		spin_lock_irqsave(&lp->ptp_tx_lock, flags);
+		skb->cb[0] = free_index;
+		skb_queue_tail(&lp->ptp_txq, skb);
+
+		if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)
+			skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+
+		skb_tx_timestamp(skb);
+		spin_unlock_irqrestore(&lp->ptp_tx_lock, flags);
+	}
+	return NETDEV_TX_OK;
+}
+
+/**
+ * axienet_set_timestamp - timestamp skb with HW timestamp
+ * @lp:		Pointer to axienet local structure
+ * @hwtstamps:  Pointer to skb timestamp structure
+ * @offset:	offset of the timestamp in the PTP buffer
+ *
+ * Return:	None.
+ *
+ */
+static void axienet_set_timestamp(struct axienet_local *lp,
+				  struct skb_shared_hwtstamps *hwtstamps,
+				  unsigned int offset)
+{
+	u32 captured_ns;
+	u32 captured_sec;
+
+	captured_ns = axienet_ior(lp, offset + 4);
+	captured_sec = axienet_ior(lp, offset);
+
+	/* Upper 32 bits contain s, lower 32 bits contain ns. */
+	hwtstamps->hwtstamp = ktime_set(captured_sec,
+						captured_ns);
+}
+
+/**
+ * axienet_ptp_recv - receive ptp buffer in skb from HW
+ * @ndev:	Pointer to net_device structure.
+ *
+ * This function is called from the ptp rx isr. It allocates skb, and
+ * copies the ptp rx buffer data to it and calls netif_rx for further
+ * processing.
+ *
+ */
+static void axienet_ptp_recv(struct net_device *ndev)
+{
+	struct axienet_local *lp = netdev_priv(ndev);
+	unsigned long ptp_frame_base_addr = 0;
+	struct sk_buff *skb;
+	u16 msg_len;
+	u8 msg_type;
+	u32 bytes = 0;
+	u32 packets = 0;
+
+	pr_debug("%s:\n ", __func__);
+
+	while (((lp->ptp_rx_hw_pointer & 0xf) !=
+		 (lp->ptp_rx_sw_pointer & 0xf))) {
+		skb = netdev_alloc_skb(ndev, PTP_RX_FRAME_SIZE);
+
+		lp->ptp_rx_sw_pointer += 1;
+
+		ptp_frame_base_addr = PTP_RX_BASE_OFFSET +
+				   ((lp->ptp_rx_sw_pointer & 0xf) *
+							PTP_RX_HWBUF_SIZE);
+
+		memset(skb->data, 0x0, PTP_RX_FRAME_SIZE);
+
+		memcpy_fromio_32(lp, ptp_frame_base_addr, skb->data,
+				 PTP_RX_FRAME_SIZE);
+
+		msg_type  = *(u8 *)(skb->data + ETH_HLEN) & 0xf;
+		msg_len  = *(u16 *)(skb->data + ETH_HLEN + 2);
+
+		skb_put(skb, ntohs(msg_len) + ETH_HLEN);
+
+		bytes += skb->len;
+		packets++;
+
+		skb->protocol = eth_type_trans(skb, ndev);
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+		pr_debug("  -->RECV: protocol: %x message: %s frame_len: %d\n",
+			 skb->protocol, msg_type_string(msg_type & 0xf),
+			 skb->len);
+		/* timestamp only event messages */
+		if (!(msg_type & PTP_MSG_TYPE_MASK)) {
+			axienet_set_timestamp(lp, skb_hwtstamps(skb),
+					      (ptp_frame_base_addr +
+					      PTP_HW_TSTAMP_OFFSET));
+		}
+
+		netif_rx(skb);
+	}
+	ndev->stats.rx_packets += packets;
+	ndev->stats.rx_bytes += bytes;
+}
+
+/**
+ * axienet_ptp_rx_irq - PTP RX ISR handler
+ * @irq:		irq number
+ * @_ndev:	net_device pointer
+ *
+ * Return:	IRQ_HANDLED for all cases.
+ */
+irqreturn_t axienet_ptp_rx_irq(int irq, void *_ndev)
+{
+	struct net_device *ndev = _ndev;
+	struct axienet_local *lp = netdev_priv(ndev);
+
+	pr_debug("%s: received\n ", __func__);
+	lp->ptp_rx_hw_pointer = (axienet_ior(lp, PTP_RX_CONTROL_OFFSET)
+					& PTP_RX_PACKET_FIELD_MASK)  >> 8;
+
+	axienet_ptp_recv(ndev);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * axienet_tx_tstamp - timestamp skb on trasmit path
+ * @work:	Pointer to work_struct structure
+ *
+ * This adds TX timestamp to skb
+ */
+void axienet_tx_tstamp(struct work_struct *work)
+{
+	struct axienet_local *lp = container_of(work, struct axienet_local,
+			tx_tstamp_work);
+	struct net_device *ndev = lp->ndev;
+	struct skb_shared_hwtstamps hwtstamps;
+	struct sk_buff *skb;
+	unsigned long ts_reg_offset;
+	unsigned long flags;
+	u8 tx_packet;
+	u8 index;
+	u32 bytes = 0;
+	u32 packets = 0;
+
+	memset(&hwtstamps, 0, sizeof(struct skb_shared_hwtstamps));
+
+	spin_lock_irqsave(&lp->ptp_tx_lock, flags);
+
+	tx_packet =  (axienet_ior(lp, PTP_TX_CONTROL_OFFSET) &
+				PTP_TX_PACKET_FIELD_MASK) >>
+				PTP_TX_PACKET_FIELD_SHIFT;
+
+	while ((skb = __skb_dequeue(&lp->ptp_txq)) != NULL) {
+		index = skb->cb[0];
+
+		/* dequeued packet yet to be xmited? */
+		if (index > tx_packet) {
+			/* enqueue it back and break */
+			skb_queue_tail(&lp->ptp_txq, skb);
+			break;
+		}
+		/* time stamp reg offset */
+		ts_reg_offset = PTP_TX_BUFFER_OFFSET(index) +
+					PTP_HW_TSTAMP_OFFSET;
+
+		if (skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS) {
+			axienet_set_timestamp(lp, &hwtstamps, ts_reg_offset);
+			skb_tstamp_tx(skb, &hwtstamps);
+		}
+
+		bytes += skb->len;
+		packets++;
+		dev_kfree_skb_any(skb);
+	}
+	ndev->stats.tx_packets += packets;
+	ndev->stats.tx_bytes += bytes;
+
+	spin_unlock_irqrestore(&lp->ptp_tx_lock, flags);
+}
+
+/**
+ * axienet_ptp_tx_irq - PTP TX irq handler
+ * @irq:		irq number
+ * @_ndev:	net_device pointer
+ *
+ * Return:	IRQ_HANDLED for all cases.
+ *
+ */
+irqreturn_t axienet_ptp_tx_irq(int irq, void *_ndev)
+{
+	struct net_device *ndev = _ndev;
+	struct axienet_local *lp = netdev_priv(ndev);
+
+	pr_debug("%s: got tx interrupt\n", __func__);
+
+	/* read ctrl register to clear the interrupt */
+	axienet_ior(lp, PTP_TX_CONTROL_OFFSET);
+
+	schedule_work(&lp->tx_tstamp_work);
+
+	netif_wake_queue(ndev);
+
+	return IRQ_HANDLED;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/xilinx/xilinx_tsn_qci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/xilinx/xilinx_tsn_qci.c
@@ -0,0 +1,151 @@
+/*
+ * Xilinx FPGA Xilinx TSN QCI Controller module.
+ *
+ * Copyright (c) 2017 Xilinx Pvt., Ltd
+ *
+ * Author: Saurabh Sengar <saurabhs@xilinx.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "xilinx_tsn_switch.h"
+
+#define SMC_MODE_SHIFT				28
+#define	SMC_CBR_MASK				0x00FFFFFF
+#define	SMC_EBR_MASK				0x00FFFFFF
+#define IN_PORTID_MASK				0x3
+#define IN_PORT_SHIFT				14
+#define MAX_FR_SIZE_MASK			0x00000FFF
+
+#define GATE_ID_SHIFT				24
+#define METER_ID_SHIFT				8
+#define EN_METER_SHIFT				6
+#define ALLOW_STREM_SHIFT			5
+#define EN_PSFP_SHIFT				4
+#define WR_OP_TYPE_MASK				0x3
+#define WR_OP_TYPE_SHIFT			2
+#define OP_TYPE_SHIFT				1
+#define PSFP_EN_CONTROL_MASK			0x1
+
+/**
+ * psfp_control - Configure thr control for PSFP
+ * @data:	Value to be programmed
+ */
+void psfp_control(struct psfp_config data)
+{
+	u32 mask;
+	u32 timeout = 20000;
+
+	mask = data.gate_id << GATE_ID_SHIFT;
+	mask |= data.meter_id << METER_ID_SHIFT;
+	mask |= data.en_meter << EN_METER_SHIFT;
+	mask |= data.allow_stream << ALLOW_STREM_SHIFT;
+	mask |= data.en_psfp << EN_PSFP_SHIFT;
+	mask |= (data.wr_op_type & WR_OP_TYPE_MASK) << WR_OP_TYPE_SHIFT;
+	mask |= data.op_type << OP_TYPE_SHIFT;
+	mask |= PSFP_EN_CONTROL_MASK;
+
+	axienet_iow(&lp, PSFP_CONTROL_OFFSET, mask);
+
+	/* wait for write to complete */
+	while ((axienet_ior(&lp, PSFP_CONTROL_OFFSET) &
+		PSFP_EN_CONTROL_MASK) && timeout)
+		timeout--;
+
+	if (!timeout)
+		pr_warn("PSFP control write took longer time!!");
+}
+
+/**
+ * get_stream_filter_config -  Get Stream Filter Configuration
+ * @data:	Value returned
+ */
+void get_stream_filter_config(struct stream_filter *data)
+{
+	u32 reg_val;
+
+	reg_val = axienet_ior(&lp, STREAM_FILTER_CONFIG_OFFSET);
+
+	data->max_fr_size = reg_val & MAX_FR_SIZE_MASK;
+	data->in_pid = (reg_val >> IN_PORT_SHIFT) & IN_PORTID_MASK;
+}
+
+/**
+ * config_stream_filter -  Configure Stream Filter Configuration
+ * @data:	Value to be programmed
+ */
+void config_stream_filter(struct stream_filter data)
+{
+	u32 mask;
+
+	mask = ((data.in_pid & IN_PORTID_MASK) << IN_PORT_SHIFT) |
+					(data.max_fr_size & MAX_FR_SIZE_MASK);
+	axienet_iow(&lp, STREAM_FILTER_CONFIG_OFFSET, mask);
+}
+
+/**
+ * get_meter_reg -  Read Stream Meter Configuration registers value
+ * @data:	Value returned
+ */
+void get_meter_reg(struct meter_config *data)
+{
+	u32 conf_r4;
+
+	data->cir = axienet_ior(&lp, STREAM_METER_CIR_OFFSET);
+	data->eir = axienet_ior(&lp, STREAM_METER_EIR_OFFSET);
+	data->cbr = axienet_ior(&lp, STREAM_METER_CBR_OFFSET) & SMC_CBR_MASK;
+	conf_r4 = axienet_ior(&lp, STREAM_METER_EBR_OFFSET);
+
+	data->ebr = conf_r4 & SMC_EBR_MASK;
+	data->mode = (conf_r4 & 0xF0000000) >> SMC_MODE_SHIFT;
+}
+
+/**
+ * program_meter_reg -  configure Stream Meter Configuration registers
+ * @data:	Value to be programmed
+ */
+void program_meter_reg(struct meter_config data)
+{
+	u32 conf_r4;
+
+	axienet_iow(&lp, STREAM_METER_CIR_OFFSET, data.cir);
+	axienet_iow(&lp, STREAM_METER_EIR_OFFSET, data.eir);
+	axienet_iow(&lp, STREAM_METER_CBR_OFFSET, data.cbr & SMC_CBR_MASK);
+
+	conf_r4 = (data.ebr & SMC_EBR_MASK) | (data.mode << SMC_MODE_SHIFT);
+	axienet_iow(&lp, STREAM_METER_EBR_OFFSET, conf_r4);
+}
+
+/**
+ * get_psfp_static_counter -  get memory static counters value
+ * @data  :	return value, containing counter value
+ */
+void get_psfp_static_counter(struct psfp_static_counter *data)
+{
+	int offset = (data->num) * 8;
+
+	data->psfp_fr_count.lsb = axienet_ior(&lp, TOTAL_PSFP_FRAMES_OFFSET +
+									offset);
+	data->psfp_fr_count.msb = axienet_ior(&lp, TOTAL_PSFP_FRAMES_OFFSET  +
+								offset + 0x4);
+
+	data->err_filter_ins_port.lsb = axienet_ior(&lp,
+					FLTR_INGS_PORT_ERR_OFFSET + offset);
+	data->err_filter_ins_port.msb = axienet_ior(&lp,
+				FLTR_INGS_PORT_ERR_OFFSET + offset + 0x4);
+
+	data->err_filtr_sdu.lsb = axienet_ior(&lp, FLTR_STDU_ERR_OFFSET +
+									offset);
+	data->err_filtr_sdu.msb = axienet_ior(&lp, FLTR_STDU_ERR_OFFSET +
+								offset + 0x4);
+
+	data->err_meter.lsb = axienet_ior(&lp, METER_ERR_OFFSET + offset);
+	data->err_meter.msb = axienet_ior(&lp, METER_ERR_OFFSET + offset + 0x4);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/xilinx/xilinx_tsn_shaper.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/xilinx/xilinx_tsn_shaper.c
@@ -0,0 +1,232 @@
+/*
+ * Xilinx FPGA Xilinx TSN QBV sheduler module.
+ *
+ * Copyright (c) 2017 Xilinx Pvt., Ltd
+ *
+ * Author: Syed S <syeds@xilinx.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "xilinx_axienet.h"
+#include "xilinx_tsn_shaper.h"
+
+static inline int axienet_map_gs_to_hw(struct axienet_local *lp, u32 gs)
+{
+	u8 be_queue = 0;
+	u8 re_queue = 1;
+	u8 st_queue = 2;
+	unsigned int acl_bit_map = 0;
+
+	if (lp->num_tc == 2)
+		st_queue = 1;
+
+	if (gs & GS_BE_OPEN)
+		acl_bit_map |= (1 << be_queue);
+	if (gs & GS_ST_OPEN)
+		acl_bit_map |= (1 << st_queue);
+	if (lp->num_tc == 3 && (gs & GS_RE_OPEN))
+		acl_bit_map |= (1 << re_queue);
+
+	return acl_bit_map;
+}
+
+static int __axienet_set_schedule(struct net_device *ndev, struct qbv_info *qbv)
+{
+	struct axienet_local *lp = netdev_priv(ndev);
+	u16 i;
+	unsigned int acl_bit_map = 0;
+	u32 u_config_change = 0;
+	u8 port = qbv->port;
+
+	if (qbv->cycle_time == 0) {
+		/* clear the gate enable bit */
+		u_config_change &= ~CC_ADMIN_GATE_ENABLE_BIT;
+		/* open all the gates */
+		u_config_change |= CC_ADMIN_GATE_STATE_SHIFT;
+
+		axienet_iow(lp, CONFIG_CHANGE(port), u_config_change);
+
+		return 0;
+	}
+
+	if (axienet_ior(lp, PORT_STATUS(port)) & 1) {
+		if (qbv->force) {
+			u_config_change &= ~CC_ADMIN_GATE_ENABLE_BIT;
+			axienet_iow(lp, CONFIG_CHANGE(port), u_config_change);
+		} else {
+			return -EALREADY;
+		}
+	}
+	/* write admin time */
+	axienet_iow(lp, ADMIN_CYCLE_TIME_DENOMINATOR(port),
+		    qbv->cycle_time & CYCLE_TIME_DENOMINATOR_MASK);
+
+	axienet_iow(lp, ADMIN_BASE_TIME_NS(port), qbv->ptp_time_ns);
+
+	axienet_iow(lp, ADMIN_BASE_TIME_SEC(port),
+		    qbv->ptp_time_sec & 0xFFFFFFFF);
+	axienet_iow(lp, ADMIN_BASE_TIME_SECS(port),
+		    (qbv->ptp_time_sec >> 32) & BASE_TIME_SECS_MASK);
+
+	u_config_change = axienet_ior(lp, CONFIG_CHANGE(port));
+
+	u_config_change &= ~(CC_ADMIN_CTRL_LIST_LENGTH_MASK <<
+				CC_ADMIN_CTRL_LIST_LENGTH_SHIFT);
+	u_config_change |= (qbv->list_length & CC_ADMIN_CTRL_LIST_LENGTH_MASK)
+					<< CC_ADMIN_CTRL_LIST_LENGTH_SHIFT;
+
+	/* program each list */
+	for (i = 0; i < qbv->list_length; i++) {
+		acl_bit_map = axienet_map_gs_to_hw(lp, qbv->acl_gate_state[i]);
+		axienet_iow(lp,  ADMIN_CTRL_LIST(port, i),
+			    (acl_bit_map & (ACL_GATE_STATE_MASK)) <<
+			    ACL_GATE_STATE_SHIFT);
+
+	    /* set the time for each entry */
+	    axienet_iow(lp, ADMIN_CTRL_LIST_TIME(port, i),
+			qbv->acl_gate_time[i] & CTRL_LIST_TIME_INTERVAL_MASK);
+	}
+
+	/* clear interrupt status */
+	axienet_iow(lp, INT_STATUS(port), 0);
+
+	/* kick in new config change */
+	u_config_change |= CC_ADMIN_CONFIG_CHANGE_BIT;
+
+	/* enable gate */
+	u_config_change |= CC_ADMIN_GATE_ENABLE_BIT;
+
+	/* start */
+	axienet_iow(lp, CONFIG_CHANGE(port), u_config_change);
+
+	return 0;
+}
+
+int axienet_set_schedule(struct net_device *ndev, void __user *useraddr)
+{
+	struct qbv_info *config;
+	int ret;
+
+	config = kmalloc(sizeof(*config), GFP_KERNEL);
+	if (!config)
+		return -ENOMEM;
+
+	if (copy_from_user(config, useraddr, sizeof(struct qbv_info))) {
+		ret = -EFAULT;
+		goto out;
+	}
+
+	pr_debug("setting new schedule\n");
+
+	ret = __axienet_set_schedule(ndev, config);
+out:
+	kfree(config);
+	return ret;
+}
+
+static int __axienet_get_schedule(struct net_device *ndev, struct qbv_info *qbv)
+{
+	struct axienet_local *lp = netdev_priv(ndev);
+	u16 i = 0;
+	u32 u_value = 0;
+	u8 port = qbv->port;
+
+	if (!(axienet_ior(lp, CONFIG_CHANGE(port)) &
+			CC_ADMIN_GATE_ENABLE_BIT)) {
+		qbv->cycle_time = 0;
+		return 0;
+	}
+
+	u_value = axienet_ior(lp, GATE_STATE(port));
+	qbv->list_length = (u_value >> CC_ADMIN_CTRL_LIST_LENGTH_SHIFT) &
+				CC_ADMIN_CTRL_LIST_LENGTH_MASK;
+
+	u_value = axienet_ior(lp, OPER_CYCLE_TIME_DENOMINATOR(port));
+	qbv->cycle_time = u_value & CYCLE_TIME_DENOMINATOR_MASK;
+
+	u_value = axienet_ior(lp, OPER_BASE_TIME_NS(port));
+	qbv->ptp_time_ns = u_value & OPER_BASE_TIME_NS_MASK;
+
+	qbv->ptp_time_sec = axienet_ior(lp, OPER_BASE_TIME_SEC(port));
+	u_value = axienet_ior(lp, OPER_BASE_TIME_SECS(port));
+	qbv->ptp_time_sec |= (u64)(u_value & BASE_TIME_SECS_MASK) << 32;
+
+	for (i = 0; i < qbv->list_length; i++) {
+		u_value = axienet_ior(lp, OPER_CTRL_LIST(port, i));
+		qbv->acl_gate_state[i] = (u_value >> ACL_GATE_STATE_SHIFT) &
+					ACL_GATE_STATE_MASK;
+		/**
+		 * In 2Q system, the actual ST Gate state value is 2,
+		 * for user the ST Gate state value is always 4.
+		 */
+		if (lp->num_tc == 2 && qbv->acl_gate_state[i] == 2)
+			qbv->acl_gate_state[i] = 4;
+
+		u_value = axienet_ior(lp, OPER_CTRL_LIST_TIME(port, i));
+		qbv->acl_gate_time[i] = u_value & CTRL_LIST_TIME_INTERVAL_MASK;
+	}
+	return 0;
+}
+
+int axienet_get_schedule(struct net_device *ndev, void __user *useraddr)
+{
+	struct qbv_info *qbv;
+	int ret = 0;
+
+	qbv = kmalloc(sizeof(*qbv), GFP_KERNEL);
+	if (!qbv)
+		return -ENOMEM;
+
+	if (copy_from_user(qbv, useraddr, sizeof(struct qbv_info))) {
+		ret = -EFAULT;
+		goto out;
+	}
+
+	__axienet_get_schedule(ndev, qbv);
+
+	if (copy_to_user(useraddr, qbv, sizeof(struct qbv_info)))
+		ret = -EFAULT;
+out:
+	kfree(qbv);
+	return ret;
+}
+
+static irqreturn_t axienet_qbv_irq(int irq, void *_ndev)
+{
+	struct net_device *ndev = _ndev;
+	struct axienet_local *lp = netdev_priv(ndev);
+	u8  port = 0; /* TODO */
+
+	/* clear status */
+	axienet_iow(lp, INT_CLEAR(port), 0);
+
+	return IRQ_HANDLED;
+}
+
+int axienet_qbv_init(struct net_device *ndev)
+{
+	struct axienet_local *lp = netdev_priv(ndev);
+	int rc;
+
+	rc = request_irq(lp->qbv_irq, axienet_qbv_irq, 0, ndev->name, ndev);
+	if (rc)
+		goto err_qbv_irq;
+
+err_qbv_irq:
+	return rc;
+}
+
+void axienet_qbv_remove(struct net_device *ndev)
+{
+	struct axienet_local *lp = netdev_priv(ndev);
+
+	free_irq(lp->qbv_irq, ndev);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/xilinx/xilinx_tsn_shaper.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/xilinx/xilinx_tsn_shaper.h
@@ -0,0 +1,151 @@
+/*
+ * Xilinx TSN QBV scheduler header
+ *
+ * Copyright (C) 2017 Xilinx, Inc.
+ *
+ * Author: Syed S <syeds@xilinx.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef XILINX_TSN_SHAPER_H
+#define XILINX_TSN_SHAPER_H
+
+/* 0x0		CONFIG_CHANGE
+ * 0x8		GATE_STATE
+ * 0x10		ADMIN_CTRL_LIST_LENGTH
+ * 0x18	ADMIN_CYCLE_TIME_DENOMINATOR
+ * 0x20         ADMIN_BASE_TIME_NS
+ * 0x24		ADMIN_BASE_TIME_SEC
+ * 0x28		ADMIN_BASE_TIME_SECS
+ * 0x30	INT_STAT
+ * 0x34	INT_EN
+ * 0x38		INT_CLR
+ * 0x3c		STATUS
+ * 0x40		CONFIG_CHANGE_TIME_NS
+ * 0x44		CONFIG_CHANGE_TIME_SEC
+ * 0x48		CONFIG_CHANGE_TIME_SECS
+ * 0x50		OPER_CTRL_LIST_LENGTH
+ * 0x58	OPER_CYCLE_TIME_DENOMINATOR
+ * 0x60		OPER_BASE_TIME_NS
+ * 0x64		OPER_BASE_TIME_SEC
+ * 0x68		OPER_BASE_TIME_SECS
+ * 0x6c	BE_XMIT_OVRRUN_CNT
+ * 0x74		RES_XMIT_OVRRUN_CNT
+ * 0x7c		ST_XMIT_OVRRUN_CNT
+ */
+
+enum hw_port {
+	PORT_EP = 0,
+	PORT_TEMAC_1,
+	PORT_TEMAC_2,
+};
+
+			     /* EP */ /* TEMAC1 */ /* TEMAC2*/
+static u32 qbv_reg_map[3] = { 0x0,   0x14000,     0x14000 };
+
+/* 0x14000	0x14FFC	Time Schedule Registers (Control & Status)
+ * 0x15000	0x15FFF	Time Schedule Control List Entries
+ */
+
+#define TIME_SCHED_BASE(port)  qbv_reg_map[(port)]
+
+#define CTRL_LIST_BASE(port)  (TIME_SCHED_BASE(port) + 0x1000)
+
+/* control list entries
+ * admin control list 0 : 31
+ * "Time interval between two gate entries" must be greater than
+ * "time required to transmit biggest supported frame" on that queue when
+ * the gate for the queue is going from open to close state.
+ */
+#define ADMIN_CTRL_LIST(port, n)  (CTRL_LIST_BASE(port) + ((n) * 8))
+#define ACL_GATE_STATE_SHIFT	8
+#define ACL_GATE_STATE_MASK	0x7
+#define ADMIN_CTRL_LIST_TIME(port, n)  (ADMIN_CTRL_LIST((port), n) + 4)
+
+#define OPER_CTRL_LIST(port, n)	(CTRL_LIST_BASE(port) + 0x800 + ((n) * 8))
+#define OPER_CTRL_LIST_TIME(port, n)  (OPER_CTRL_LIST(port, n) + 4)
+#define CTRL_LIST_TIME_INTERVAL_MASK	0xFFFFF
+
+#define CONFIG_CHANGE(port)    (TIME_SCHED_BASE(port) + 0x0)
+#define CC_ADMIN_GATE_STATE_SHIFT            0x7
+#define CC_ADMIN_GATE_STATE_MASK             (7)
+#define CC_ADMIN_CTRL_LIST_LENGTH_SHIFT      (8)
+#define CC_ADMIN_CTRL_LIST_LENGTH_MASK		(0x1FF)
+/* This request bit is set when all the related Admin* filelds are populated.
+ * This bit is set by S/W and clear by core when core start with new schedule.
+ * Once set it can only be cleared by core or hard/soft reset.
+ */
+#define CC_ADMIN_CONFIG_CHANGE_BIT           BIT(30)
+#define CC_ADMIN_GATE_ENABLE_BIT             BIT(31)
+
+#define GATE_STATE(port)      (TIME_SCHED_BASE(port) + 0x8)
+#define GS_OPER_GATE_STATE_SHIFT		(0)
+#define GS_OPER_GATE_STATE_MASK		(0x7)
+#define GS_OPER_CTRL_LIST_LENGTH_SHIFT	(8)
+#define GS_OPER_CTRL_LIST_LENGTH_MASK		(0x3F)
+#define GS_SUP_MAX_LIST_LENGTH_SHIFT		(16)
+#define GS_SUP_MAX_LIST_LENGTH_MASK		(0x3F)
+#define GS_TICK_GRANULARITY_SHIFT		(24)
+#define GS_TICK_GRANULARITY_MASK		(0x3F)
+
+#define ADMIN_CYCLE_TIME_DENOMINATOR(port)	(TIME_SCHED_BASE(port) + 0x18)
+#define ADMIN_BASE_TIME_NS(port)		(TIME_SCHED_BASE(port) + 0x20)
+#define ADMIN_BASE_TIME_SEC(port)		(TIME_SCHED_BASE(port) + 0x24)
+#define ADMIN_BASE_TIME_SECS(port)		(TIME_SCHED_BASE(port) + 0x28)
+
+#define INT_STATUS(port)			(TIME_SCHED_BASE(port) + 0x30)
+#define INT_ENABLE(port)			(TIME_SCHED_BASE(port) + 0x34)
+#define INT_CLEAR(port)				(TIME_SCHED_BASE(port) + 0x38)
+#define PORT_STATUS(port)			(TIME_SCHED_BASE(port) + 0x3c)
+
+/* Config Change time is valid after Config Pending bit is set. */
+#define CONFIG_CHANGE_TIME_NS(port)		(TIME_SCHED_BASE((port)) + 0x40)
+#define CONFIG_CHANGE_TIME_SEC(port)		(TIME_SCHED_BASE((port)) + 0x44)
+#define CONFIG_CHANGE_TIME_SECS(port)		(TIME_SCHED_BASE((port)) + 0x48)
+
+#define OPER_CONTROL_LIST_LENGTH(port)		(TIME_SCHED_BASE(port) + 0x50)
+#define OPER_CYCLE_TIME_DENOMINATOR(port)	(TIME_SCHED_BASE(port) + 0x58)
+#define CYCLE_TIME_DENOMINATOR_MASK		(0x3FFFFFFF)
+
+#define OPER_BASE_TIME_NS(port)			(TIME_SCHED_BASE(port) + 0x60)
+#define OPER_BASE_TIME_NS_MASK			(0x3FFFFFFF)
+#define OPER_BASE_TIME_SEC(port)		(TIME_SCHED_BASE(port) + 0x64)
+#define OPER_BASE_TIME_SECS(port)		(TIME_SCHED_BASE(port) + 0x68)
+#define BASE_TIME_SECS_MASK			(0xFFFF)
+
+#define BE_XMIT_OVERRUN_COUNT(port)		(TIME_SCHED_BASE(port) + 0x6c)
+#define RES_XMIT_OVERRUN_COUNT(port)		(TIME_SCHED_BASE(port) + 0x74)
+#define ST_XMIT_OVERRUN_COUNT(port)		(TIME_SCHED_BASE(port) + 0x7c)
+
+/* internally hw deals with queues only,
+ * in 3q system ST acl bitmap would be would 1 << 2
+ * in 2q system ST acl bitmap would be 1 << 1
+ * But this is confusing to users.
+ * so use the following fixed gate state and internally
+ * map them to hw
+ */
+#define GS_BE_OPEN   BIT(0)
+#define GS_RE_OPEN   BIT(1)
+#define GS_ST_OPEN   BIT(2)
+#define QBV_MAX_ENTRIES	256
+
+struct qbv_info {
+	u8 port;
+	u8 force;
+	u32 cycle_time;
+	u64 ptp_time_sec;
+	u32 ptp_time_ns;
+	u32 list_length;
+	u32 acl_gate_state[QBV_MAX_ENTRIES];
+	u32 acl_gate_time[QBV_MAX_ENTRIES];
+};
+
+#endif /* XILINX_TSN_SHAPER_H */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/xilinx/xilinx_tsn_switch.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/xilinx/xilinx_tsn_switch.c
@@ -0,0 +1,807 @@
+/*
+ * Xilinx FPGA Xilinx TSN Switch Controller driver.
+ *
+ * Copyright (c) 2017 Xilinx Pvt., Ltd
+ *
+ * Author: Saurabh Sengar <saurabhs@xilinx.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "xilinx_tsn_switch.h"
+#include <linux/of_platform.h>
+#include <linux/module.h>
+#include <linux/miscdevice.h>
+
+static struct miscdevice switch_dev;
+struct axienet_local lp;
+
+#define ADD					1
+#define DELETE					0
+
+#define PMAP_EGRESS_QUEUE_MASK			0x7
+#define PMAP_EGRESS_QUEUE0_SELECT		0x0
+#define PMAP_EGRESS_QUEUE1_SELECT		0x1
+#define PMAP_EGRESS_QUEUE2_SELECT		0x2
+#define PMAP_PRIORITY0_SHIFT			0
+#define PMAP_PRIORITY1_SHIFT			4
+#define PMAP_PRIORITY2_SHIFT			8
+#define PMAP_PRIORITY3_SHIFT			12
+#define PMAP_PRIORITY4_SHIFT			16
+#define PMAP_PRIORITY5_SHIFT			20
+#define PMAP_PRIORITY6_SHIFT			24
+#define PMAP_PRIORITY7_SHIFT			28
+#define SDL_EN_CAM_IPV_SHIFT			28
+#define SDL_CAM_IPV_SHIFT			29
+
+#define SDL_CAM_WR_ENABLE			BIT(0)
+#define SDL_CAM_ADD_ENTRY			0x1
+#define SDL_CAM_DELETE_ENTRY			0x3
+#define SDL_CAM_VLAN_SHIFT			16
+#define SDL_CAM_VLAN_MASK			0xFFF
+#define SDL_CAM_IPV_MASK			0x7
+#define SDL_CAM_PORT_LIST_SHIFT			8
+#define SDL_GATEID_SHIFT			16
+#define SDL_CAM_FWD_TO_EP			BIT(0)
+#define SDL_CAM_FWD_TO_PORT_1			BIT(1)
+#define SDL_CAM_FWD_TO_PORT_2			BIT(2)
+#define SDL_CAM_EP_ACTION_LIST_SHIFT		0
+#define SDL_CAM_MAC_ACTION_LIST_SHIFT		4
+#define SDL_CAM_DEST_MAC_XLATION		BIT(0)
+#define SDL_CAM_VLAN_ID_XLATION			BIT(1)
+#define SDL_CAM_UNTAG_FRAME			BIT(2)
+
+/* Match table for of_platform binding */
+static const struct of_device_id tsnswitch_of_match[] = {
+	{ .compatible = "xlnx,tsn-switch", },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, tsnswitch_of_match);
+
+static int switch_open(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+static int switch_release(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+/* set_frame_filter_option Frame Filtering Type Field Options */
+static void set_frame_filter_opt(u16 type1, u16 type2)
+{
+	int type = axienet_ior(&lp, XAS_FRM_FLTR_TYPE_FIELD_OPT_OFFSET);
+
+	if (type1)
+		type = (type & 0x0000FFFF) | (type1 << 16);
+	if (type2)
+		type = (type & 0xFFFF0000) | type2;
+	axienet_iow(&lp, XAS_FRM_FLTR_TYPE_FIELD_OPT_OFFSET, type);
+}
+
+/* MAC Port-1 Management Queueing Options */
+static void set_mac1_mngmntq(u32 config)
+{
+	axienet_iow(&lp, XAS_MAC1_MNG_Q_OPTION_OFFSET, config);
+}
+
+/* MAC Port-2 Management Queueing Options */
+static void set_mac2_mngmntq(u32 config)
+{
+	axienet_iow(&lp, XAS_MAC2_MNG_Q_OPTION_OFFSET, config);
+}
+
+/**
+ * set_switch_regs -  read the various status of switch
+ * @data:	Pointer which will be writen to switch
+ */
+static void set_switch_regs(struct switch_data *data)
+{
+	int tmp;
+	u8 mac_addr[6];
+
+	axienet_iow(&lp, XAS_CONTROL_OFFSET, data->switch_ctrl);
+	axienet_iow(&lp, XAS_PMAP_OFFSET, data->switch_prt);
+	mac_addr[0] = data->sw_mac_addr[0];
+	mac_addr[1] = data->sw_mac_addr[1];
+	mac_addr[2] = data->sw_mac_addr[2];
+	mac_addr[3] = data->sw_mac_addr[3];
+	mac_addr[4] = data->sw_mac_addr[4];
+	mac_addr[5] = data->sw_mac_addr[5];
+	axienet_iow(&lp, XAS_MAC_LSB_OFFSET,
+		    (mac_addr[0] << 24) | (mac_addr[1] << 16) |
+		    (mac_addr[2] << 8)  | (mac_addr[3]));
+	axienet_iow(&lp, XAS_MAC_MSB_OFFSET, (mac_addr[4] << 8) | mac_addr[5]);
+
+	/* Threshold */
+	tmp = (data->thld_ep_mac[0].t1 << 16) | data->thld_ep_mac[0].t2;
+	axienet_iow(&lp, XAS_EP2MAC_ST_FIFOT_OFFSET, tmp);
+
+	tmp = (data->thld_ep_mac[1].t1 << 16) | data->thld_ep_mac[1].t2;
+	axienet_iow(&lp, XAS_EP2MAC_RE_FIFOT_OFFSET, tmp);
+
+	tmp = (data->thld_ep_mac[2].t1 << 16) | data->thld_ep_mac[2].t2;
+	axienet_iow(&lp, XAS_EP2MAC_BE_FIFOT_OFFSET, tmp);
+
+	tmp = (data->thld_mac_mac[0].t1 << 16) | data->thld_mac_mac[0].t2;
+	axienet_iow(&lp, XAS_MAC2MAC_ST_FIFOT_OFFSET, tmp);
+
+	tmp = (data->thld_mac_mac[1].t1 << 16) | data->thld_mac_mac[1].t2;
+	axienet_iow(&lp, XAS_MAC2MAC_RE_FIFOT_OFFSET, tmp);
+
+	tmp = (data->thld_mac_mac[2].t1 << 16) | data->thld_mac_mac[2].t2;
+	axienet_iow(&lp, XAS_MAC2MAC_BE_FIFOT_OFFSET, tmp);
+
+	/* Port VLAN ID */
+	axienet_iow(&lp, XAS_EP_PORT_VLAN_OFFSET, data->ep_vlan);
+	axienet_iow(&lp, XAS_MAC_PORT_VLAN_OFFSET, data->mac_vlan);
+
+	/* max frame size */
+	axienet_iow(&lp, XAS_ST_MAX_FRAME_SIZE_OFFSET, data->max_frame_sc_que);
+	axienet_iow(&lp, XAS_RE_MAX_FRAME_SIZE_OFFSET, data->max_frame_res_que);
+	axienet_iow(&lp, XAS_BE_MAX_FRAME_SIZE_OFFSET, data->max_frame_be_que);
+}
+
+/**
+ * get_switch_regs -  read the various status of switch
+ * @data:	Pointer which will return the switch status
+ */
+static void get_switch_regs(struct switch_data *data)
+{
+	int tmp;
+
+	data->switch_status = axienet_ior(&lp, XAS_STATUS_OFFSET);
+	data->switch_ctrl = axienet_ior(&lp, XAS_CONTROL_OFFSET);
+	data->switch_prt = axienet_ior(&lp, XAS_PMAP_OFFSET);
+	tmp = axienet_ior(&lp, XAS_MAC_LSB_OFFSET);
+	data->sw_mac_addr[0] = (tmp & 0xFF000000) >> 24;
+	data->sw_mac_addr[1] = (tmp & 0xFF0000) >> 16;
+	data->sw_mac_addr[2] = (tmp & 0xFF00) >> 8;
+	data->sw_mac_addr[3] = (tmp & 0xFF);
+	tmp = axienet_ior(&lp, XAS_MAC_MSB_OFFSET);
+	data->sw_mac_addr[4] = (tmp & 0xFF00) >> 8;
+	data->sw_mac_addr[5] = (tmp & 0xFF);
+
+	/* Threshold */
+	tmp = axienet_ior(&lp, XAS_EP2MAC_ST_FIFOT_OFFSET);
+	data->thld_ep_mac[0].t1 = ((tmp >> 16) & 0xFFFF);
+	data->thld_ep_mac[0].t2 = tmp & (0xFFFF);
+
+	tmp = axienet_ior(&lp, XAS_EP2MAC_RE_FIFOT_OFFSET);
+	data->thld_ep_mac[1].t1 = ((tmp >> 16) & 0xFFFF);
+	data->thld_ep_mac[1].t2 = tmp & (0xFFFF);
+
+	tmp = axienet_ior(&lp, XAS_EP2MAC_BE_FIFOT_OFFSET);
+	data->thld_ep_mac[2].t1 = ((tmp >> 16) & 0xFFFF);
+	data->thld_ep_mac[2].t2 = tmp & (0xFFFF);
+
+	tmp = axienet_ior(&lp, XAS_MAC2MAC_ST_FIFOT_OFFSET);
+	data->thld_mac_mac[0].t1 = ((tmp >> 16) & 0xFFFF);
+	data->thld_mac_mac[0].t2 = tmp & (0xFFFF);
+
+	tmp = axienet_ior(&lp, XAS_MAC2MAC_RE_FIFOT_OFFSET);
+	data->thld_mac_mac[1].t1 = ((tmp >> 16) & 0xFFFF);
+	data->thld_mac_mac[1].t2 = tmp & (0xFFFF);
+
+	tmp = axienet_ior(&lp, XAS_MAC2MAC_BE_FIFOT_OFFSET);
+	data->thld_mac_mac[2].t1 = ((tmp >> 16) & 0xFFFF);
+	data->thld_mac_mac[2].t2 = tmp & (0xFFFF);
+
+	/* Port VLAN ID */
+	data->ep_vlan = axienet_ior(&lp, XAS_EP_PORT_VLAN_OFFSET);
+	data->mac_vlan = axienet_ior(&lp, XAS_MAC_PORT_VLAN_OFFSET);
+
+	/* max frame size */
+	data->max_frame_sc_que = (axienet_ior(&lp,
+				XAS_ST_MAX_FRAME_SIZE_OFFSET) & 0xFFFF);
+	data->max_frame_res_que = (axienet_ior(&lp,
+				XAS_RE_MAX_FRAME_SIZE_OFFSET) & 0xFFFF);
+	data->max_frame_be_que = (axienet_ior(&lp,
+				XAS_BE_MAX_FRAME_SIZE_OFFSET) & 0xFFFF);
+
+	/* frame filter type options*/
+	tmp = axienet_ior(&lp, XAS_FRM_FLTR_TYPE_FIELD_OPT_OFFSET);
+	data->typefield.type2 = (tmp & 0xFFFF0000) >> 16;
+	data->typefield.type2 = tmp & 0x0000FFFF;
+
+	/* MAC Port 1 Management Q option*/
+	data->mac1_config = axienet_ior(&lp, XAS_MAC1_MNG_Q_OPTION_OFFSET);
+	/* MAC Port 2 Management Q option*/
+	data->mac2_config = axienet_ior(&lp, XAS_MAC2_MNG_Q_OPTION_OFFSET);
+
+	/* Port VLAN Membership control*/
+	data->port_vlan_mem_ctrl = axienet_ior(&lp, XAS_VLAN_MEMB_CTRL_REG);
+	/* Port VLAN Membership read data*/
+	data->port_vlan_mem_data = axienet_ior(&lp, XAS_VLAN_MEMB_DATA_REG);
+}
+
+/**
+ * get_memory_static_counter -  get memory static counters value
+ * @data:	Value to be programmed
+ */
+static void get_memory_static_counter(struct switch_data *data)
+{
+	data->mem_arr_cnt.cam_lookup.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_CAM_LOOKUP);
+	data->mem_arr_cnt.cam_lookup.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_CAM_LOOKUP + 0x4);
+
+	data->mem_arr_cnt.multicast_fr.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_MULTCAST);
+	data->mem_arr_cnt.multicast_fr.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_MULTCAST + 0x4);
+
+	data->mem_arr_cnt.err_mac1.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_MAC1);
+	data->mem_arr_cnt.err_mac1.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_MAC1 + 0x4);
+
+	data->mem_arr_cnt.err_mac2.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_MAC2);
+	data->mem_arr_cnt.err_mac2.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_MAC2 + 0x4);
+
+	data->mem_arr_cnt.sc_mac1_ep.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_SC_MAC1_EP);
+	data->mem_arr_cnt.sc_mac1_ep.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_SC_MAC1_EP + 0x4);
+	data->mem_arr_cnt.res_mac1_ep.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_RES_MAC1_EP);
+	data->mem_arr_cnt.res_mac1_ep.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_RES_MAC1_EP + 0x4);
+	data->mem_arr_cnt.be_mac1_ep.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_BE_MAC1_EP);
+	data->mem_arr_cnt.be_mac1_ep.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_BE_MAC1_EP + 0x4);
+	data->mem_arr_cnt.err_sc_mac1_ep.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_SC_MAC1_EP);
+	data->mem_arr_cnt.err_sc_mac1_ep.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_SC_MAC1_EP + 0x4);
+	data->mem_arr_cnt.err_res_mac1_ep.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_RES_MAC1_EP);
+	data->mem_arr_cnt.err_res_mac1_ep.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_RES_MAC1_EP + 0x4);
+	data->mem_arr_cnt.err_be_mac1_ep.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_BE_MAC1_EP);
+	data->mem_arr_cnt.err_be_mac1_ep.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_BE_MAC1_EP + 0x4);
+
+	data->mem_arr_cnt.sc_mac2_ep.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_SC_MAC2_EP);
+	data->mem_arr_cnt.sc_mac2_ep.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_SC_MAC2_EP + 0x4);
+	data->mem_arr_cnt.res_mac2_ep.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_RES_MAC2_EP);
+	data->mem_arr_cnt.res_mac2_ep.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_RES_MAC2_EP + 0x4);
+	data->mem_arr_cnt.be_mac2_ep.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_BE_MAC2_EP);
+	data->mem_arr_cnt.be_mac2_ep.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_BE_MAC2_EP + 0x4);
+	data->mem_arr_cnt.err_sc_mac2_ep.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_SC_MAC2_EP);
+	data->mem_arr_cnt.err_sc_mac2_ep.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_SC_MAC2_EP + 0x4);
+	data->mem_arr_cnt.err_res_mac2_ep.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_RES_MAC2_EP);
+	data->mem_arr_cnt.err_res_mac2_ep.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_RES_MAC2_EP + 0x4);
+	data->mem_arr_cnt.err_be_mac2_ep.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_BE_MAC2_EP);
+	data->mem_arr_cnt.err_be_mac2_ep.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_BE_MAC2_EP + 0x4);
+
+	data->mem_arr_cnt.sc_ep_mac1.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_SC_EP_MAC1);
+	data->mem_arr_cnt.sc_ep_mac1.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_SC_EP_MAC1 + 0x4);
+	data->mem_arr_cnt.res_ep_mac1.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_RES_EP_MAC1);
+	data->mem_arr_cnt.res_ep_mac1.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_RES_EP_MAC1 + 0x4);
+	data->mem_arr_cnt.be_ep_mac1.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_BE_EP_MAC1);
+	data->mem_arr_cnt.be_ep_mac1.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_BE_EP_MAC1 + 0x4);
+	data->mem_arr_cnt.err_sc_ep_mac1.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_SC_EP_MAC1);
+	data->mem_arr_cnt.err_sc_ep_mac1.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_SC_EP_MAC1 + 0x4);
+	data->mem_arr_cnt.err_res_ep_mac1.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_RES_EP_MAC1);
+	data->mem_arr_cnt.err_res_ep_mac1.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_RES_EP_MAC1 + 0x4);
+	data->mem_arr_cnt.err_be_ep_mac1.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_BE_EP_MAC1);
+	data->mem_arr_cnt.err_be_ep_mac1.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_BE_EP_MAC1 + 0x4);
+
+	data->mem_arr_cnt.sc_mac2_mac1.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_SC_MAC2_MAC1);
+	data->mem_arr_cnt.sc_mac2_mac1.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_SC_MAC2_MAC1 + 0x4);
+	data->mem_arr_cnt.res_mac2_mac1.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_RES_MAC2_MAC1);
+	data->mem_arr_cnt.res_mac2_mac1.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_RES_MAC2_MAC1 + 0x4);
+	data->mem_arr_cnt.be_mac2_mac1.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_BE_MAC2_MAC1);
+	data->mem_arr_cnt.be_mac2_mac1.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_BE_MAC2_MAC1 + 0x4);
+	data->mem_arr_cnt.err_sc_mac2_mac1.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_SC_MAC2_MAC1);
+	data->mem_arr_cnt.err_sc_mac2_mac1.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_SC_MAC2_MAC1 + 0x4);
+	data->mem_arr_cnt.err_res_mac2_mac1.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_RES_MAC2_MAC1);
+	data->mem_arr_cnt.err_res_mac2_mac1.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_RES_MAC2_MAC1 + 0x4);
+	data->mem_arr_cnt.err_be_mac2_mac1.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_BE_MAC2_MAC1);
+	data->mem_arr_cnt.err_be_mac2_mac1.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_BE_MAC2_MAC1 + 0x4);
+
+	data->mem_arr_cnt.sc_ep_mac2.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_SC_EP_MAC2);
+	data->mem_arr_cnt.sc_ep_mac2.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_SC_EP_MAC2 + 0x4);
+	data->mem_arr_cnt.res_ep_mac2.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_RES_EP_MAC2);
+	data->mem_arr_cnt.res_ep_mac2.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_RES_EP_MAC2 + 0x4);
+	data->mem_arr_cnt.be_ep_mac2.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_BE_EP_MAC2);
+	data->mem_arr_cnt.be_ep_mac2.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_BE_EP_MAC2 + 0x4);
+	data->mem_arr_cnt.err_sc_ep_mac2.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_SC_EP_MAC2);
+	data->mem_arr_cnt.err_sc_ep_mac2.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_SC_EP_MAC2 + 0x4);
+	data->mem_arr_cnt.err_res_ep_mac2.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_RES_EP_MAC2);
+	data->mem_arr_cnt.err_res_ep_mac2.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_RES_EP_MAC2 + 0x4);
+	data->mem_arr_cnt.err_be_ep_mac2.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_BE_EP_MAC2);
+	data->mem_arr_cnt.err_be_ep_mac2.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_BE_EP_MAC2 + 0x4);
+
+	data->mem_arr_cnt.sc_mac1_mac2.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_SC_MAC1_MAC2);
+	data->mem_arr_cnt.sc_mac1_mac2.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_SC_MAC1_MAC2 + 0x4);
+	data->mem_arr_cnt.res_mac1_mac2.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_RES_MAC1_MAC2);
+	data->mem_arr_cnt.res_mac1_mac2.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_RES_MAC1_MAC2 + 0x4);
+	data->mem_arr_cnt.be_mac1_mac2.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_BE_MAC1_MAC2);
+	data->mem_arr_cnt.be_mac1_mac2.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_BE_MAC1_MAC2 + 0x4);
+	data->mem_arr_cnt.err_sc_mac1_mac2.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_SC_MAC1_MAC2);
+	data->mem_arr_cnt.err_sc_mac1_mac2.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_SC_MAC1_MAC2 + 0x4);
+	data->mem_arr_cnt.err_res_mac1_mac2.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_RES_MAC1_MAC2);
+	data->mem_arr_cnt.err_res_mac1_mac2.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_RES_MAC1_MAC2 + 0x4);
+	data->mem_arr_cnt.err_be_mac1_mac2.lsb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_BE_MAC1_MAC2);
+	data->mem_arr_cnt.err_be_mac1_mac2.msb = axienet_ior(&lp,
+					XAS_MEM_STCNTR_ERR_BE_MAC1_MAC2 + 0x4);
+}
+
+static void add_delete_cam_entry(struct cam_struct data, u8 add)
+{
+	u32 port_action = 0;
+	u32 tv2 = 0;
+	u32 timeout = 20000;
+
+	/* wait for cam init done */
+	while (!(axienet_ior(&lp, XAS_SDL_CAM_STATUS_OFFSET) &
+		SDL_CAM_WR_ENABLE) && timeout)
+		timeout--;
+
+	if (!timeout)
+		pr_warn("CAM init took longer time!!");
+	/* mac and vlan */
+	axienet_iow(&lp, XAS_SDL_CAM_KEY1_OFFSET,
+		    (data.dest_addr[0] << 24) | (data.dest_addr[1] << 16) |
+		    (data.dest_addr[2] << 8)  | (data.dest_addr[3]));
+	axienet_iow(&lp, XAS_SDL_CAM_KEY2_OFFSET,
+		    ((data.dest_addr[4] << 8) | data.dest_addr[5]) |
+		    ((data.vlanid & SDL_CAM_VLAN_MASK) << SDL_CAM_VLAN_SHIFT));
+
+	/* TV 1 and TV 2 */
+	axienet_iow(&lp, XAS_SDL_CAM_TV1_OFFSET,
+		    (data.src_addr[0] << 24) | (data.src_addr[1] << 16) |
+		    (data.src_addr[2] << 8)  | (data.src_addr[3]));
+
+	tv2 = ((data.src_addr[4] << 8) | data.src_addr[5]) |
+	       ((data.tv_vlanid & SDL_CAM_VLAN_MASK) << SDL_CAM_VLAN_SHIFT);
+
+#if IS_ENABLED(CONFIG_XILINX_TSN_QCI)
+	tv2 = tv2 | ((data.ipv & SDL_CAM_IPV_MASK) << SDL_CAM_IPV_SHIFT)
+				| (data.en_ipv << SDL_EN_CAM_IPV_SHIFT);
+#endif
+	axienet_iow(&lp, XAS_SDL_CAM_TV2_OFFSET, tv2);
+
+	if (data.tv_en)
+		port_action = ((SDL_CAM_DEST_MAC_XLATION |
+		SDL_CAM_VLAN_ID_XLATION) << SDL_CAM_MAC_ACTION_LIST_SHIFT);
+
+	port_action = port_action | (data.fwd_port << SDL_CAM_PORT_LIST_SHIFT);
+
+#if IS_ENABLED(CONFIG_XILINX_TSN_QCI) || IS_ENABLED(CONFIG_XILINX_TSN_CB)
+	port_action = port_action | (data.gate_id << SDL_GATEID_SHIFT);
+#endif
+
+	/* port action */
+	axienet_iow(&lp, XAS_SDL_CAM_PORT_ACT_OFFSET, port_action);
+
+	if (add)
+		axienet_iow(&lp, XAS_SDL_CAM_CTRL_OFFSET, SDL_CAM_ADD_ENTRY);
+	else
+		axienet_iow(&lp, XAS_SDL_CAM_CTRL_OFFSET, SDL_CAM_DELETE_ENTRY);
+
+	timeout = 20000;
+	/* wait for write to complete */
+	while ((axienet_ior(&lp, XAS_SDL_CAM_CTRL_OFFSET) &
+		SDL_CAM_WR_ENABLE) && timeout)
+		timeout--;
+
+	if (!timeout)
+		pr_warn("CAM write took longer time!!");
+}
+
+static void port_vlan_mem_ctrl(u32 port_vlan_mem)
+{
+		axienet_iow(&lp, XAS_VLAN_MEMB_CTRL_REG, port_vlan_mem);
+}
+
+static long switch_ioctl(struct file *file, unsigned int cmd,
+			 unsigned long arg)
+{
+	long retval = 0;
+	struct switch_data data;
+#if IS_ENABLED(CONFIG_XILINX_TSN_QCI)
+	struct qci qci_data;
+#endif
+#if IS_ENABLED(CONFIG_XILINX_TSN_CB)
+	struct cb cb_data;
+#endif
+	switch (cmd) {
+	case GET_STATUS_SWITCH:
+		/* Switch configurations */
+		get_switch_regs(&data);
+
+		/* Memory static counter*/
+		get_memory_static_counter(&data);
+		if (copy_to_user((char __user *)arg, &data, sizeof(data))) {
+			pr_err("Copy to user failed\n");
+			retval = -EINVAL;
+			goto end;
+			}
+		break;
+
+	case SET_STATUS_SWITCH:
+		if (copy_from_user(&data, (char __user *)arg, sizeof(data))) {
+			pr_err("Copy from user failed\n");
+			retval = -EINVAL;
+			goto end;
+		}
+		set_switch_regs(&data);
+		break;
+
+	case ADD_CAM_ENTRY:
+		if (copy_from_user(&data, (char __user *)arg, sizeof(data))) {
+			pr_err("Copy from user failed\n");
+			retval = -EINVAL;
+			goto end;
+		}
+		add_delete_cam_entry(data.cam_data, ADD);
+		break;
+
+	case DELETE_CAM_ENTRY:
+		if (copy_from_user(&data, (char __user *)arg, sizeof(data))) {
+			pr_err("Copy from user failed\n");
+			retval = -EINVAL;
+			goto end;
+		}
+		add_delete_cam_entry(data.cam_data, DELETE);
+		break;
+
+	case PORT_VLAN_MEM_CTRL:
+		if (copy_from_user(&data, (char __user *)arg, sizeof(data))) {
+			pr_err("Copy from user failed\n");
+			retval = -EINVAL;
+			goto end;
+		}
+		port_vlan_mem_ctrl(data.port_vlan_mem_ctrl);
+		break;
+
+	case SET_FRAME_TYPE_FIELD:
+		if (copy_from_user(&data, (char __user *)arg, sizeof(data))) {
+			pr_err("Copy from user failed\n");
+			retval = -EINVAL;
+			goto end;
+		}
+		set_frame_filter_opt(data.typefield.type1,
+				     data.typefield.type2);
+		break;
+
+	case SET_MAC1_MNGMNT_Q_CONFIG:
+		if (copy_from_user(&data, (char __user *)arg, sizeof(data))) {
+			pr_err("Copy from user failed\n");
+			retval = -EINVAL;
+			goto end;
+		}
+		set_mac1_mngmntq(data.mac1_config);
+		break;
+
+	case SET_MAC2_MNGMNT_Q_CONFIG:
+		if (copy_from_user(&data, (char __user *)arg, sizeof(data))) {
+			pr_err("Copy from user failed\n");
+			retval = -EINVAL;
+			goto end;
+		}
+		set_mac2_mngmntq(data.mac2_config);
+		break;
+#if IS_ENABLED(CONFIG_XILINX_TSN_QCI)
+	case CONFIG_METER_MEM:
+		if (copy_from_user(&qci_data, (char __user *)arg,
+				   sizeof(qci_data))) {
+			pr_err("Copy from user failed\n");
+			retval = -EINVAL;
+			goto end;
+		}
+		program_meter_reg(qci_data.meter_config_data);
+		break;
+
+	case CONFIG_GATE_MEM:
+		if (copy_from_user(&qci_data, (char __user *)arg,
+				   sizeof(qci_data))) {
+			pr_err("Copy from user failed\n");
+			retval = -EINVAL;
+			goto end;
+		}
+		config_stream_filter(qci_data.stream_config_data);
+		break;
+
+	case PSFP_CONTROL:
+		if (copy_from_user(&qci_data, (char __user *)arg,
+				   sizeof(qci_data))) {
+			retval = -EINVAL;
+			pr_err("Copy from user failed\n");
+			goto end;
+		}
+		psfp_control(qci_data.psfp_config_data);
+		break;
+
+	case GET_STATIC_PSFP_COUNTER:
+		if (copy_from_user(&qci_data, (char __user *)arg,
+				   sizeof(qci_data))) {
+			pr_err("Copy from user failed\n");
+			retval = -EINVAL;
+			goto end;
+		}
+		get_psfp_static_counter(&qci_data.psfp_counter_data);
+		if (copy_to_user((char __user *)arg, &qci_data,
+				 sizeof(qci_data))) {
+			pr_err("Copy to user failed\n");
+			retval = -EINVAL;
+			goto end;
+		}
+		break;
+	case GET_METER_REG:
+		get_meter_reg(&qci_data.meter_config_data);
+		if (copy_to_user((char __user *)arg, &qci_data,
+				 sizeof(qci_data))) {
+			pr_err("Copy to user failed\n");
+			retval = -EINVAL;
+			goto end;
+		}
+		break;
+	case GET_STREAM_FLTR_CONFIG:
+		get_stream_filter_config(&qci_data.stream_config_data);
+		if (copy_to_user((char __user *)arg, &qci_data,
+				 sizeof(qci_data))) {
+			pr_err("Copy to user failed\n");
+			retval = -EINVAL;
+			goto end;
+		}
+		break;
+#endif
+#if IS_ENABLED(CONFIG_XILINX_TSN_CB)
+	case CONFIG_MEMBER_MEM:
+		if (copy_from_user(&cb_data, (char __user *)arg,
+				   sizeof(cb_data))) {
+			pr_err("Copy from user failed\n");
+			retval = -EINVAL;
+			goto end;
+		}
+		program_member_reg(cb_data.frer_memb_config_data);
+		break;
+
+	case CONFIG_INGRESS_FLTR:
+		if (copy_from_user(&cb_data, (char __user *)arg,
+				   sizeof(cb_data))) {
+			pr_err("Copy from user failed\n");
+			retval = -EINVAL;
+			goto end;
+		}
+		config_ingress_filter(cb_data.in_fltr_data);
+		break;
+
+	case FRER_CONTROL:
+		if (copy_from_user(&cb_data, (char __user *)arg,
+				   sizeof(cb_data))) {
+			pr_err("Copy from user failed\n");
+			retval = -EINVAL;
+			goto end;
+		}
+		frer_control(cb_data.frer_ctrl_data);
+		break;
+
+	case GET_STATIC_FRER_COUNTER:
+		if (copy_from_user(&cb_data, (char __user *)arg,
+				   sizeof(cb_data))) {
+			pr_err("Copy from user failed\n");
+			retval = -EINVAL;
+			goto end;
+		}
+		get_frer_static_counter(&cb_data.frer_counter_data);
+		if (copy_to_user((char __user *)arg, &cb_data,
+				 sizeof(cb_data))) {
+			pr_err("Copy to user failed\n");
+			retval = -EINVAL;
+			goto end;
+		}
+		break;
+
+	case GET_MEMBER_REG:
+		get_member_reg(&cb_data.frer_memb_config_data);
+		if (copy_to_user((char __user *)arg, &cb_data,
+				 sizeof(cb_data))) {
+			pr_err("Copy to user failed\n");
+			retval = -EINVAL;
+			goto end;
+		}
+		break;
+
+	case GET_INGRESS_FLTR:
+		get_ingress_filter_config(&cb_data.in_fltr_data);
+		if (copy_to_user((char __user *)arg, &cb_data,
+				 sizeof(cb_data))) {
+			pr_err("Copy to user failed\n");
+			retval = -EINVAL;
+			goto end;
+		}
+		break;
+#endif
+	}
+end:
+	return retval;
+}
+
+static const struct file_operations switch_fops = {
+	.owner		=	THIS_MODULE,
+	.unlocked_ioctl	=	switch_ioctl,
+	.open		=	switch_open,
+	.release	=       switch_release,
+};
+
+static int tsn_switch_init(void)
+{
+	int ret;
+
+	switch_dev.minor = MISC_DYNAMIC_MINOR;
+	switch_dev.name = "switch";
+	switch_dev.fops = &switch_fops;
+	ret = misc_register(&switch_dev);
+	if (ret < 0) {
+		pr_err("Switch driver registration failed!\n");
+		return ret;
+	}
+
+	pr_debug("Xilinx TSN Switch driver initialized!\n");
+	return 0;
+}
+
+static int tsn_switch_cam_init(u16 num_q)
+{
+	u32 pmap;
+	u32 timeout = 20000;
+
+	/* wait for switch init done */
+	while (!(axienet_ior(&lp, XAS_STATUS_OFFSET) &
+		SDL_CAM_WR_ENABLE) && timeout)
+		timeout--;
+
+	if (!timeout)
+		pr_warn("Switch init took longer time!!");
+
+	if (num_q == 3) {
+	/* map pcp = 2,3 to queue1
+	 *     pcp = 4 to queue2
+	 */
+	pmap = ((PMAP_EGRESS_QUEUE1_SELECT << PMAP_PRIORITY2_SHIFT) |
+		(PMAP_EGRESS_QUEUE1_SELECT << PMAP_PRIORITY3_SHIFT) |
+		(PMAP_EGRESS_QUEUE2_SELECT << PMAP_PRIORITY4_SHIFT));
+	} else if (num_q == 2) {
+		/*     pcp = 4 to queue1 */
+		pmap = (PMAP_EGRESS_QUEUE1_SELECT << PMAP_PRIORITY4_SHIFT);
+	}
+
+	axienet_iow(&lp, XAS_PMAP_OFFSET, pmap);
+
+	timeout = 20000;
+	/* wait for cam init done */
+	while (!(axienet_ior(&lp, XAS_SDL_CAM_STATUS_OFFSET) &
+		SDL_CAM_WR_ENABLE) && timeout)
+		timeout--;
+
+	if (!timeout)
+		pr_warn("CAM init took longer time!!");
+
+	return 0;
+}
+
+static int tsnswitch_probe(struct platform_device *pdev)
+{
+	struct resource *swt;
+	int ret;
+	u16 num_tc;
+
+	pr_info("TSN Switch probe\n");
+	/* Map device registers */
+	swt = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	lp.regs = devm_ioremap_resource(&pdev->dev, swt);
+	if (IS_ERR(lp.regs))
+		return PTR_ERR(lp.regs);
+
+	ret = of_property_read_u16(pdev->dev.of_node, "xlnx,num-tc",
+				   &num_tc);
+	if (ret || (num_tc != 2 && num_tc != 3))
+		num_tc = XAE_MAX_TSN_TC;
+
+	pr_info("TSN Switch Initializing ....\n");
+	ret = tsn_switch_init();
+	if (ret)
+		return ret;
+	pr_info("TSN CAM Initializing ....\n");
+	ret = tsn_switch_cam_init(num_tc);
+
+	return ret;
+}
+
+static int tsnswitch_remove(struct platform_device *pdev)
+{
+	misc_deregister(&switch_dev);
+	return 0;
+}
+
+static struct platform_driver tsnswitch_driver = {
+	.probe = tsnswitch_probe,
+	.remove = tsnswitch_remove,
+	.driver = {
+		 .name = "xilinx_tsnswitch",
+		 .of_match_table = tsnswitch_of_match,
+	},
+};
+
+module_platform_driver(tsnswitch_driver);
+
+MODULE_DESCRIPTION("Xilinx TSN Switch driver");
+MODULE_AUTHOR("Xilinx");
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/xilinx/xilinx_tsn_switch.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/xilinx/xilinx_tsn_switch.h
@@ -0,0 +1,364 @@
+/*
+ * Xilinx TSN core switch header
+ *
+ * Copyright (C) 2017 Xilinx, Inc.
+ *
+ * Author: Saurabh Sengar <saurabhs@xilinx.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef XILINX_TSN_SWITCH_H
+#define XILINX_TSN_SWITCH_H
+
+#include "xilinx_axienet.h"
+
+/* ioctls */
+#define GET_STATUS_SWITCH			0x16
+#define SET_STATUS_SWITCH			0x17
+#define ADD_CAM_ENTRY				0x18
+#define DELETE_CAM_ENTRY			0x19
+#define PORT_VLAN_MEM_CTRL			0x20
+#define SET_FRAME_TYPE_FIELD			0x21
+#define SET_MAC1_MNGMNT_Q_CONFIG		0x22
+#define SET_MAC2_MNGMNT_Q_CONFIG		0x23
+#define CONFIG_METER_MEM			0x24
+#define CONFIG_GATE_MEM				0x25
+#define PSFP_CONTROL				0x26
+#define GET_STATIC_PSFP_COUNTER			0x27
+#define GET_METER_REG				0x28
+#define GET_STREAM_FLTR_CONFIG			0x29
+#define CONFIG_MEMBER_MEM			0x2A
+#define CONFIG_INGRESS_FLTR			0x2B
+#define FRER_CONTROL				0x2C
+#define GET_STATIC_FRER_COUNTER			0x2D
+#define GET_MEMBER_REG				0x2E
+#define GET_INGRESS_FLTR			0x2F
+
+/* Xilinx Axi Switch Offsets*/
+#define XAS_STATUS_OFFSET			0x00000
+#define XAS_CONTROL_OFFSET			0x00004
+#define XAS_PMAP_OFFSET				0x00008
+#define XAS_MAC_LSB_OFFSET			0x0000C
+#define XAS_MAC_MSB_OFFSET			0x00010
+#define XAS_EP2MAC_ST_FIFOT_OFFSET		0x00020
+#define XAS_EP2MAC_RE_FIFOT_OFFSET		0x00024
+#define XAS_EP2MAC_BE_FIFOT_OFFSET		0x00028
+#define XAS_MAC2MAC_ST_FIFOT_OFFSET		0x00030
+#define XAS_MAC2MAC_RE_FIFOT_OFFSET		0x00034
+#define XAS_MAC2MAC_BE_FIFOT_OFFSET		0x00038
+#define XAS_EP_PORT_VLAN_OFFSET			0x00040
+#define XAS_MAC_PORT_VLAN_OFFSET		0x00044
+#define XAS_FRM_FLTR_TYPE_FIELD_OPT_OFFSET	0x00050
+#define XAS_MAC2_MNG_Q_OPTION_OFFSET		0x00054
+#define XAS_MAC1_MNG_Q_OPTION_OFFSET		0x00058
+#define XAS_ST_MAX_FRAME_SIZE_OFFSET		0x00060
+#define XAS_RE_MAX_FRAME_SIZE_OFFSET		0x00064
+#define XAS_BE_MAX_FRAME_SIZE_OFFSET		0x00068
+
+/* Memory static counters */
+#define XAS_MEM_STCNTR_CAM_LOOKUP		0x00400
+#define XAS_MEM_STCNTR_MULTCAST			0x00408
+#define XAS_MEM_STCNTR_ERR_MAC1			0x00410
+#define XAS_MEM_STCNTR_ERR_MAC2			0x00418
+#define XAS_MEM_STCNTR_SC_MAC1_EP		0x00420
+#define XAS_MEM_STCNTR_RES_MAC1_EP		0x00428
+#define XAS_MEM_STCNTR_BE_MAC1_EP		0x00430
+#define XAS_MEM_STCNTR_ERR_SC_MAC1_EP		0x00438
+#define XAS_MEM_STCNTR_ERR_RES_MAC1_EP		0x00440
+#define XAS_MEM_STCNTR_ERR_BE_MAC1_EP		0x00448
+#define XAS_MEM_STCNTR_SC_MAC2_EP		0x00458
+#define XAS_MEM_STCNTR_RES_MAC2_EP		0x00460
+#define XAS_MEM_STCNTR_BE_MAC2_EP		0x00468
+#define XAS_MEM_STCNTR_ERR_SC_MAC2_EP		0x00470
+#define XAS_MEM_STCNTR_ERR_RES_MAC2_EP		0x00478
+#define XAS_MEM_STCNTR_ERR_BE_MAC2_EP		0x00480
+#define XAS_MEM_STCNTR_SC_EP_MAC1		0x00490
+#define XAS_MEM_STCNTR_RES_EP_MAC1		0x00498
+#define XAS_MEM_STCNTR_BE_EP_MAC1		0x004A0
+#define XAS_MEM_STCNTR_ERR_SC_EP_MAC1		0x004A8
+#define XAS_MEM_STCNTR_ERR_RES_EP_MAC1		0x004B0
+#define XAS_MEM_STCNTR_ERR_BE_EP_MAC1		0x004B8
+#define XAS_MEM_STCNTR_SC_MAC2_MAC1		0x004C0
+#define XAS_MEM_STCNTR_RES_MAC2_MAC1		0x004C8
+#define XAS_MEM_STCNTR_BE_MAC2_MAC1		0x004D0
+#define XAS_MEM_STCNTR_ERR_SC_MAC2_MAC1		0x004D8
+#define XAS_MEM_STCNTR_ERR_RES_MAC2_MAC1	0x004E0
+#define XAS_MEM_STCNTR_ERR_BE_MAC2_MAC1		0x004E8
+#define XAS_MEM_STCNTR_SC_EP_MAC2		0x004F0
+#define XAS_MEM_STCNTR_RES_EP_MAC2		0x004F8
+#define XAS_MEM_STCNTR_BE_EP_MAC2		0x00500
+#define XAS_MEM_STCNTR_ERR_SC_EP_MAC2		0x00508
+#define XAS_MEM_STCNTR_ERR_RES_EP_MAC2		0x00510
+#define XAS_MEM_STCNTR_ERR_BE_EP_MAC2		0x00518
+#define XAS_MEM_STCNTR_SC_MAC1_MAC2		0x00520
+#define XAS_MEM_STCNTR_RES_MAC1_MAC2		0x00528
+#define XAS_MEM_STCNTR_BE_MAC1_MAC2		0x00530
+#define XAS_MEM_STCNTR_ERR_SC_MAC1_MAC2		0x00538
+#define XAS_MEM_STCNTR_ERR_RES_MAC1_MAC2	0x00540
+#define XAS_MEM_STCNTR_ERR_BE_MAC1_MAC2		0x00548
+
+/* Stream Destination Lookup CAM */
+#define XAS_SDL_CAM_CTRL_OFFSET			0x1000
+#define XAS_SDL_CAM_STATUS_OFFSET		0x1004
+#define XAS_SDL_CAM_KEY1_OFFSET			0x1008
+#define XAS_SDL_CAM_KEY2_OFFSET			0x100C
+#define XAS_SDL_CAM_TV1_OFFSET			0x1010
+#define XAS_SDL_CAM_TV2_OFFSET			0x1014
+#define XAS_SDL_CAM_PORT_ACT_OFFSET		0x1018
+
+/* Port VLAN Membership Memory */
+#define XAS_VLAN_MEMB_CTRL_REG			0x1100
+#define XAS_VLAN_MEMB_DATA_REG			0x1104
+
+/* QCI */
+#define PSFP_CONTROL_OFFSET			0x1200
+#define STREAM_FILTER_CONFIG_OFFSET		0x1204
+#define	STREAM_METER_CIR_OFFSET			0x1208
+#define	STREAM_METER_EIR_OFFSET			0x120C
+#define	STREAM_METER_CBR_OFFSET			0x1210
+#define	STREAM_METER_EBR_OFFSET			0x1214
+
+/* PSFP Statistics Counters */
+#define TOTAL_PSFP_FRAMES_OFFSET		0x2000
+#define FLTR_INGS_PORT_ERR_OFFSET		0x2800
+#define FLTR_STDU_ERR_OFFSET			0x3000
+#define METER_ERR_OFFSET			0x3800
+
+/* CB */
+#define FRER_CONTROL_OFFSET			0x1300
+#define INGRESS_FILTER_OFFSET			0x1304
+#define FRER_CONFIG_REG1			0x1308
+#define FRER_CONFIG_REG2			0x130C
+
+/* FRER Statistics Counters */
+#define TOTAL_FRER_FRAMES_OFFSET		0x4000
+#define FRER_DISCARD_INGS_FLTR_OFFSET		0x4800
+#define FRER_PASS_FRAMES_INDV_OFFSET		0x5000
+#define FRER_DISCARD_FRAMES_INDV_OFFSET		0x5800
+#define FRER_PASS_FRAMES_SEQ_OFFSET		0x6000
+#define FRER_DISCARD_FRAMES_SEQ_OFFSET		0x6800
+#define FRER_ROGUE_FRAMES_SEQ_OFFSET		0x7000
+#define SEQ_RECV_RESETS_OFFSET			0x7800
+
+/* 64 bit counter*/
+struct static_cntr {
+	u32 msb;
+	u32 lsb;
+};
+
+/*********** QCI Structures **************/
+struct psfp_config {
+	u8 gate_id;
+	u8 meter_id;
+	bool en_meter;
+	bool allow_stream;
+	bool en_psfp;
+	u8 wr_op_type;
+	bool op_type;
+};
+
+struct meter_config {
+	u32 cir;
+	u32 eir;
+	u32 cbr;
+	u32 ebr;
+	u8 mode;
+};
+
+struct stream_filter {
+	u8 in_pid; /* ingress port id*/
+	u16 max_fr_size; /* max frame size*/
+};
+
+/* PSFP Static counter*/
+struct psfp_static_counter {
+	struct static_cntr psfp_fr_count;
+	struct static_cntr err_filter_ins_port;
+	struct static_cntr err_filtr_sdu;
+	struct static_cntr err_meter;
+	unsigned char num;
+};
+
+/* QCI Core stuctures */
+struct qci {
+	struct meter_config meter_config_data;
+	struct stream_filter stream_config_data;
+	struct psfp_config psfp_config_data;
+	struct psfp_static_counter psfp_counter_data;
+};
+
+/************* QCI Structures end *************/
+
+/*********** CB Structures **************/
+struct frer_ctrl {
+	u8 gate_id;
+	u8 memb_id;
+	bool seq_reset;
+	bool gate_state;
+	bool rcvry_tmout;
+	bool frer_valid;
+	u8 wr_op_type;
+	bool op_type;
+};
+
+struct in_fltr {
+	u8 in_port_id;
+	u16 max_seq_id;
+};
+
+struct frer_memb_config {
+	u8 seq_rec_hist_len;
+	u8 split_strm_egport_id;
+	u16 split_strm_vlan_id;
+	u32 rem_ticks;
+};
+
+/* FRER Static counter*/
+struct frer_static_counter {
+	struct static_cntr frer_fr_count;
+	struct static_cntr disc_frames_in_portid;
+	struct static_cntr pass_frames_seq_recv;
+	struct static_cntr disc_frames_seq_recv;
+	struct static_cntr rogue_frames_seq_recv;
+	struct static_cntr pass_frames_ind_recv;
+	struct static_cntr disc_frames_ind_recv;
+	struct static_cntr seq_recv_rst;
+	unsigned char num;
+};
+
+/* CB Core stuctures */
+struct cb {
+	struct frer_ctrl frer_ctrl_data;
+	struct in_fltr in_fltr_data;
+	struct frer_memb_config frer_memb_config_data;
+	struct frer_static_counter frer_counter_data;
+};
+
+/************* CB Structures end *************/
+
+/********* Switch Structures Starts ***********/
+struct thershold {
+	u16 t1;
+	u16 t2;
+};
+
+/* memory static counters */
+struct mem_static_arr_cntr {
+	struct static_cntr cam_lookup;
+	struct static_cntr multicast_fr;
+	struct static_cntr err_mac1;
+	struct static_cntr err_mac2;
+	struct static_cntr sc_mac1_ep;
+	struct static_cntr res_mac1_ep;
+	struct static_cntr be_mac1_ep;
+	struct static_cntr err_sc_mac1_ep;
+	struct static_cntr err_res_mac1_ep;
+	struct static_cntr err_be_mac1_ep;
+	struct static_cntr sc_mac2_ep;
+	struct static_cntr res_mac2_ep;
+	struct static_cntr be_mac2_ep;
+	struct static_cntr err_sc_mac2_ep;
+	struct static_cntr err_res_mac2_ep;
+	struct static_cntr err_be_mac2_ep;
+	struct static_cntr sc_ep_mac1;
+	struct static_cntr res_ep_mac1;
+	struct static_cntr be_ep_mac1;
+	struct static_cntr err_sc_ep_mac1;
+	struct static_cntr err_res_ep_mac1;
+	struct static_cntr err_be_ep_mac1;
+	struct static_cntr sc_mac2_mac1;
+	struct static_cntr res_mac2_mac1;
+	struct static_cntr be_mac2_mac1;
+	struct static_cntr err_sc_mac2_mac1;
+	struct static_cntr err_res_mac2_mac1;
+	struct static_cntr err_be_mac2_mac1;
+	struct static_cntr sc_ep_mac2;
+	struct static_cntr res_ep_mac2;
+	struct static_cntr be_ep_mac2;
+	struct static_cntr err_sc_ep_mac2;
+	struct static_cntr err_res_ep_mac2;
+	struct static_cntr err_be_ep_mac2;
+	struct static_cntr sc_mac1_mac2;
+	struct static_cntr res_mac1_mac2;
+	struct static_cntr be_mac1_mac2;
+	struct static_cntr err_sc_mac1_mac2;
+	struct static_cntr err_res_mac1_mac2;
+	struct static_cntr err_be_mac1_mac2;
+};
+
+/* CAM structure */
+struct cam_struct {
+	u8 src_addr[6];
+	u8 dest_addr[6];
+	u16 vlanid;
+	u16 tv_vlanid;
+	u8 fwd_port;
+	bool tv_en;
+	u8 gate_id;
+	u8 ipv;
+	bool en_ipv;
+};
+
+/*Frame Filtering Type Field Option */
+struct ff_type {
+	u16 type1;
+	u16 type2;
+};
+
+/* Core switch structure*/
+struct switch_data {
+	u32 switch_status;
+	u32 switch_ctrl;
+	u32 switch_prt;
+	u8 sw_mac_addr[6];
+	/*0 - schedule, 1 - reserved, 2 - best effort queue*/
+	struct thershold thld_ep_mac[3];
+	struct thershold thld_mac_mac[3];
+	u32 ep_vlan;
+	u32 mac_vlan;
+	u32 max_frame_sc_que;
+	u32 max_frame_res_que;
+	u32 max_frame_be_que;
+	/* Memory counters */
+	struct mem_static_arr_cntr mem_arr_cnt;
+	/* CAM */
+	struct cam_struct cam_data;
+/* Frame Filtering Type Field Option */
+	struct ff_type typefield;
+/* MAC Port-1 Management Queueing Options */
+	int mac1_config;
+/* MAC Port-2 Management Queueing Options */
+	int mac2_config;
+/* Port VLAN Membership Registers */
+	int port_vlan_mem_ctrl;
+	char port_vlan_mem_data;
+};
+
+/********* Switch Structures ends ***********/
+
+extern struct axienet_local lp;
+
+/********* qci function declararions ********/
+void psfp_control(struct psfp_config data);
+void config_stream_filter(struct stream_filter data);
+void program_meter_reg(struct meter_config data);
+void get_psfp_static_counter(struct psfp_static_counter *data);
+void get_meter_reg(struct meter_config *data);
+void get_stream_filter_config(struct stream_filter *data);
+
+/********* cb function declararions ********/
+void frer_control(struct frer_ctrl data);
+void get_ingress_filter_config(struct in_fltr *data);
+void config_ingress_filter(struct in_fltr data);
+void get_member_reg(struct frer_memb_config *data);
+void program_member_reg(struct frer_memb_config data);
+void get_frer_static_counter(struct frer_static_counter *data);
+#endif /* XILINX_TSN_SWITCH_H */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/xilinx/xilinx_tsn_timer.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/xilinx/xilinx_tsn_timer.h
@@ -0,0 +1,73 @@
+/*
+ * Xilinx FPGA Xilinx TSN timer module header.
+ *
+ * Copyright (c) 2017 Xilinx Pvt., Ltd
+ *
+ * Author: Syed S <syeds@xilinx.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _XILINX_TSN_H_
+#define _XILINX_TSN_H_
+
+#include <linux/platform_device.h>
+
+#define XAE_RTC_OFFSET			0x12800
+/* RTC Nanoseconds Field Offset Register */
+#define XTIMER1588_RTC_OFFSET_NS	0x00000
+/* RTC Seconds Field Offset Register - Low */
+#define XTIMER1588_RTC_OFFSET_SEC_L	0x00008
+/* RTC Seconds Field Offset Register - High */
+#define XTIMER1588_RTC_OFFSET_SEC_H	0x0000C
+/* RTC Increment */
+#define XTIMER1588_RTC_INCREMENT	0x00010
+/* Current TOD Nanoseconds - RO */
+#define XTIMER1588_CURRENT_RTC_NS	0x00014
+/* Current TOD Seconds -Low RO  */
+#define XTIMER1588_CURRENT_RTC_SEC_L	0x00018
+/* Current TOD Seconds -High RO */
+#define XTIMER1588_CURRENT_RTC_SEC_H	0x0001C
+#define XTIMER1588_SYNTONIZED_NS	0x0002C
+#define XTIMER1588_SYNTONIZED_SEC_L	0x00030
+#define XTIMER1588_SYNTONIZED_SEC_H	0x00034
+/* Write to Bit 0 to clear the interrupt */
+#define XTIMER1588_INTERRUPT		0x00020
+/* 8kHz Pulse Offset Register */
+#define XTIMER1588_8KPULSE		0x00024
+/* Correction Field - Low */
+#define XTIMER1588_CF_L			0x0002C
+/* Correction Field - Low */
+#define XTIMER1588_CF_H			0x00030
+
+#define XTIMER1588_RTC_MASK  ((1 << 26) - 1)
+#define XTIMER1588_INT_SHIFT 0
+#define NANOSECOND_BITS 20
+#define NANOSECOND_MASK ((1 << NANOSECOND_BITS) - 1)
+#define SECOND_MASK ((1 << (32 - NANOSECOND_BITS)) - 1)
+#define XTIMER1588_RTC_INCREMENT_SHIFT 20
+#define PULSESIN1PPS 128
+
+/* Read/Write access to the registers */
+#ifndef out_be32
+#if defined(CONFIG_ARCH_ZYNQ) || defined(CONFIG_ARCH_ZYNQMP)
+#define in_be32(offset)		__raw_readl(offset)
+#define out_be32(offset, val)	__raw_writel(val, offset)
+#endif
+#endif
+
+/* The tsn ptp module will set this variable */
+extern int axienet_phc_index;
+
+void *axienet_ptp_timer_probe(void __iomem *base,
+			      struct platform_device *pdev);
+int axienet_ptp_timer_remove(void *priv);
+int axienet_get_phc_index(void *priv);
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/xircom/xirc2ps_cs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/xircom/xirc2ps_cs.c
@@ -503,6 +503,11 @@
 xirc2ps_detach(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
+    struct local_info *local = netdev_priv(dev);
+
+    netif_carrier_off(dev);
+    netif_tx_disable(dev);
+    cancel_work_sync(&local->tx_timeout_task);
 
     dev_dbg(&link->dev, "detach\n");
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ethernet/xscale/ixp4xx_eth.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ethernet/xscale/ixp4xx_eth.c
@@ -517,25 +517,14 @@
 	return ret;
 }
 
-static int ixp4xx_mdio_register(void)
+static int ixp4xx_mdio_register(struct eth_regs __iomem *regs)
 {
 	int err;
 
 	if (!(mdio_bus = mdiobus_alloc()))
 		return -ENOMEM;
 
-	if (cpu_is_ixp43x()) {
-		/* IXP43x lacks NPE-B and uses NPE-C for MII PHY access */
-		if (!(ixp4xx_read_feature_bits() & IXP4XX_FEATURE_NPEC_ETH))
-			return -ENODEV;
-		mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthC_BASE_VIRT;
-	} else {
-		/* All MII PHY accesses use NPE-B Ethernet registers */
-		if (!(ixp4xx_read_feature_bits() & IXP4XX_FEATURE_NPEB_ETH0))
-			return -ENODEV;
-		mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthB_BASE_VIRT;
-	}
-
+	mdio_regs = regs;
 	__raw_writel(DEFAULT_CORE_CNTRL, &mdio_regs->core_control);
 	spin_lock_init(&mdio_lock);
 	mdio_bus->name = "IXP4xx MII Bus";
@@ -1374,7 +1363,7 @@
 	.ndo_validate_addr = eth_validate_addr,
 };
 
-static int eth_init_one(struct platform_device *pdev)
+static int ixp4xx_eth_probe(struct platform_device *pdev)
 {
 	struct port *port;
 	struct net_device *dev;
@@ -1384,7 +1373,7 @@
 	char phy_id[MII_BUS_ID_SIZE + 3];
 	int err;
 
-	if (!(dev = alloc_etherdev(sizeof(struct port))))
+	if (!(dev = devm_alloc_etherdev(&pdev->dev, sizeof(struct port))))
 		return -ENOMEM;
 
 	SET_NETDEV_DEV(dev, &pdev->dev);
@@ -1394,20 +1383,51 @@
 
 	switch (port->id) {
 	case IXP4XX_ETH_NPEA:
+		/* If the MDIO bus is not up yet, defer probe */
+		if (!mdio_bus)
+			return -EPROBE_DEFER;
 		port->regs = (struct eth_regs __iomem *)IXP4XX_EthA_BASE_VIRT;
 		regs_phys  = IXP4XX_EthA_BASE_PHYS;
 		break;
 	case IXP4XX_ETH_NPEB:
+		/*
+		 * On all except IXP43x, NPE-B is used for the MDIO bus.
+		 * If there is no NPE-B in the feature set, bail out, else
+		 * register the MDIO bus.
+		 */
+		if (!cpu_is_ixp43x()) {
+			if (!(ixp4xx_read_feature_bits() &
+			      IXP4XX_FEATURE_NPEB_ETH0))
+				return -ENODEV;
+			/* Else register the MDIO bus on NPE-B */
+			if ((err = ixp4xx_mdio_register(IXP4XX_EthC_BASE_VIRT)))
+				return err;
+		}
+		if (!mdio_bus)
+			return -EPROBE_DEFER;
 		port->regs = (struct eth_regs __iomem *)IXP4XX_EthB_BASE_VIRT;
 		regs_phys  = IXP4XX_EthB_BASE_PHYS;
 		break;
 	case IXP4XX_ETH_NPEC:
+		/*
+		 * IXP43x lacks NPE-B and uses NPE-C for the MDIO bus access,
+		 * of there is no NPE-C, no bus, nothing works, so bail out.
+		 */
+		if (cpu_is_ixp43x()) {
+			if (!(ixp4xx_read_feature_bits() &
+			      IXP4XX_FEATURE_NPEC_ETH))
+				return -ENODEV;
+			/* Else register the MDIO bus on NPE-C */
+			if ((err = ixp4xx_mdio_register(IXP4XX_EthC_BASE_VIRT)))
+				return err;
+		}
+		if (!mdio_bus)
+			return -EPROBE_DEFER;
 		port->regs = (struct eth_regs __iomem *)IXP4XX_EthC_BASE_VIRT;
 		regs_phys  = IXP4XX_EthC_BASE_PHYS;
 		break;
 	default:
-		err = -ENODEV;
-		goto err_free;
+		return -ENODEV;
 	}
 
 	dev->netdev_ops = &ixp4xx_netdev_ops;
@@ -1416,10 +1436,8 @@
 
 	netif_napi_add(dev, &port->napi, eth_poll, NAPI_WEIGHT);
 
-	if (!(port->npe = npe_request(NPE_ID(port->id)))) {
-		err = -EIO;
-		goto err_free;
-	}
+	if (!(port->npe = npe_request(NPE_ID(port->id))))
+		return -EIO;
 
 	port->mem_res = request_mem_region(regs_phys, REGS_SIZE, dev->name);
 	if (!port->mem_res) {
@@ -1465,12 +1483,10 @@
 	release_resource(port->mem_res);
 err_npe_rel:
 	npe_release(port->npe);
-err_free:
-	free_netdev(dev);
 	return err;
 }
 
-static int eth_remove_one(struct platform_device *pdev)
+static int ixp4xx_eth_remove(struct platform_device *pdev)
 {
 	struct net_device *dev = platform_get_drvdata(pdev);
 	struct phy_device *phydev = dev->phydev;
@@ -1478,45 +1494,21 @@
 
 	unregister_netdev(dev);
 	phy_disconnect(phydev);
+	ixp4xx_mdio_remove();
 	npe_port_tab[NPE_ID(port->id)] = NULL;
 	npe_release(port->npe);
 	release_resource(port->mem_res);
-	free_netdev(dev);
 	return 0;
 }
 
 static struct platform_driver ixp4xx_eth_driver = {
 	.driver.name	= DRV_NAME,
-	.probe		= eth_init_one,
-	.remove		= eth_remove_one,
+	.probe		= ixp4xx_eth_probe,
+	.remove		= ixp4xx_eth_remove,
 };
-
-static int __init eth_init_module(void)
-{
-	int err;
-
-	/*
-	 * FIXME: we bail out on device tree boot but this really needs
-	 * to be fixed in a nicer way: this registers the MDIO bus before
-	 * even matching the driver infrastructure, we should only probe
-	 * detected hardware.
-	 */
-	if (of_have_populated_dt())
-		return -ENODEV;
-	if ((err = ixp4xx_mdio_register()))
-		return err;
-	return platform_driver_register(&ixp4xx_eth_driver);
-}
-
-static void __exit eth_cleanup_module(void)
-{
-	platform_driver_unregister(&ixp4xx_eth_driver);
-	ixp4xx_mdio_remove();
-}
+module_platform_driver(ixp4xx_eth_driver);
 
 MODULE_AUTHOR("Krzysztof Halasa");
 MODULE_DESCRIPTION("Intel IXP4xx Ethernet driver");
 MODULE_LICENSE("GPL v2");
 MODULE_ALIAS("platform:ixp4xx_eth");
-module_init(eth_init_module);
-module_exit(eth_cleanup_module);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/fddi/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/fddi/Kconfig
@@ -40,17 +40,20 @@
 
 config DEFXX_MMIO
 	bool
-	prompt "Use MMIO instead of PIO" if PCI || EISA
+	prompt "Use MMIO instead of IOP" if PCI || EISA
 	depends on DEFXX
-	default n if PCI || EISA
+	default n if EISA
 	default y
 	---help---
 	  This instructs the driver to use EISA or PCI memory-mapped I/O
-	  (MMIO) as appropriate instead of programmed I/O ports (PIO).
+	  (MMIO) as appropriate instead of programmed I/O ports (IOP).
 	  Enabling this gives an improvement in processing time in parts
-	  of the driver, but it may cause problems with EISA (DEFEA)
-	  adapters.  TURBOchannel does not have the concept of I/O ports,
-	  so MMIO is always used for these (DEFTA) adapters.
+	  of the driver, but it requires a memory window to be configured
+	  for EISA (DEFEA) adapters that may not always be available.
+	  Conversely some PCIe host bridges do not support IOP, so MMIO
+	  may be required to access PCI (DEFPA) adapters on downstream PCI
+	  buses with some systems.  TURBOchannel does not have the concept
+	  of I/O ports, so MMIO is always used for these (DEFTA) adapters.
 
 	  If unsure, say N.
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/fddi/defxx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/fddi/defxx.c
@@ -495,6 +495,25 @@
 	.ndo_set_mac_address	= dfx_ctl_set_mac_address,
 };
 
+static void dfx_register_res_alloc_err(const char *print_name, bool mmio,
+				       bool eisa)
+{
+	pr_err("%s: Cannot use %s, no address set, aborting\n",
+	       print_name, mmio ? "MMIO" : "I/O");
+	pr_err("%s: Recompile driver with \"CONFIG_DEFXX_MMIO=%c\"\n",
+	       print_name, mmio ? 'n' : 'y');
+	if (eisa && mmio)
+		pr_err("%s: Or run ECU and set adapter's MMIO location\n",
+		       print_name);
+}
+
+static void dfx_register_res_err(const char *print_name, bool mmio,
+				 unsigned long start, unsigned long len)
+{
+	pr_err("%s: Cannot reserve %s resource 0x%lx @ 0x%lx, aborting\n",
+	       print_name, mmio ? "MMIO" : "I/O", len, start);
+}
+
 /*
  * ================
  * = dfx_register =
@@ -568,15 +587,12 @@
 	dev_set_drvdata(bdev, dev);
 
 	dfx_get_bars(bdev, bar_start, bar_len);
-	if (dfx_bus_eisa && dfx_use_mmio && bar_start[0] == 0) {
-		pr_err("%s: Cannot use MMIO, no address set, aborting\n",
-		       print_name);
-		pr_err("%s: Run ECU and set adapter's MMIO location\n",
-		       print_name);
-		pr_err("%s: Or recompile driver with \"CONFIG_DEFXX_MMIO=n\""
-		       "\n", print_name);
+	if (bar_len[0] == 0 ||
+	    (dfx_bus_eisa && dfx_use_mmio && bar_start[0] == 0)) {
+		dfx_register_res_alloc_err(print_name, dfx_use_mmio,
+					   dfx_bus_eisa);
 		err = -ENXIO;
-		goto err_out;
+		goto err_out_disable;
 	}
 
 	if (dfx_use_mmio)
@@ -585,18 +601,16 @@
 	else
 		region = request_region(bar_start[0], bar_len[0], print_name);
 	if (!region) {
-		pr_err("%s: Cannot reserve %s resource 0x%lx @ 0x%lx, "
-		       "aborting\n", dfx_use_mmio ? "MMIO" : "I/O", print_name,
-		       (long)bar_len[0], (long)bar_start[0]);
+		dfx_register_res_err(print_name, dfx_use_mmio,
+				     bar_start[0], bar_len[0]);
 		err = -EBUSY;
 		goto err_out_disable;
 	}
 	if (bar_start[1] != 0) {
 		region = request_region(bar_start[1], bar_len[1], print_name);
 		if (!region) {
-			pr_err("%s: Cannot reserve I/O resource "
-			       "0x%lx @ 0x%lx, aborting\n", print_name,
-			       (long)bar_len[1], (long)bar_start[1]);
+			dfx_register_res_err(print_name, 0,
+					     bar_start[1], bar_len[1]);
 			err = -EBUSY;
 			goto err_out_csr_region;
 		}
@@ -604,9 +618,8 @@
 	if (bar_start[2] != 0) {
 		region = request_region(bar_start[2], bar_len[2], print_name);
 		if (!region) {
-			pr_err("%s: Cannot reserve I/O resource "
-			       "0x%lx @ 0x%lx, aborting\n", print_name,
-			       (long)bar_len[2], (long)bar_start[2]);
+			dfx_register_res_err(print_name, 0,
+					     bar_start[2], bar_len[2]);
 			err = -EBUSY;
 			goto err_out_bh_region;
 		}
@@ -3831,10 +3844,24 @@
 	int status;
 
 	status = pci_register_driver(&dfx_pci_driver);
-	if (!status)
-		status = eisa_driver_register(&dfx_eisa_driver);
-	if (!status)
-		status = tc_register_driver(&dfx_tc_driver);
+	if (status)
+		goto err_pci_register;
+
+	status = eisa_driver_register(&dfx_eisa_driver);
+	if (status)
+		goto err_eisa_register;
+
+	status = tc_register_driver(&dfx_tc_driver);
+	if (status)
+		goto err_tc_register;
+
+	return 0;
+
+err_tc_register:
+	eisa_driver_unregister(&dfx_eisa_driver);
+err_eisa_register:
+	pci_unregister_driver(&dfx_pci_driver);
+err_pci_register:
 	return status;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/fddi/defza.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/fddi/defza.c
@@ -1504,9 +1504,8 @@
 	release_mem_region(start, len);
 
 err_out_kfree:
-	free_netdev(dev);
-
 	pr_err("%s: initialization failure, aborting!\n", fp->name);
+	free_netdev(dev);
 	return ret;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/fjes/fjes_hw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/fjes/fjes_hw.c
@@ -220,21 +220,25 @@
 
 	mem_size = FJES_DEV_REQ_BUF_SIZE(hw->max_epid);
 	hw->hw_info.req_buf = kzalloc(mem_size, GFP_KERNEL);
-	if (!(hw->hw_info.req_buf))
-		return -ENOMEM;
+	if (!(hw->hw_info.req_buf)) {
+		result = -ENOMEM;
+		goto free_ep_info;
+	}
 
 	hw->hw_info.req_buf_size = mem_size;
 
 	mem_size = FJES_DEV_RES_BUF_SIZE(hw->max_epid);
 	hw->hw_info.res_buf = kzalloc(mem_size, GFP_KERNEL);
-	if (!(hw->hw_info.res_buf))
-		return -ENOMEM;
+	if (!(hw->hw_info.res_buf)) {
+		result = -ENOMEM;
+		goto free_req_buf;
+	}
 
 	hw->hw_info.res_buf_size = mem_size;
 
 	result = fjes_hw_alloc_shared_status_region(hw);
 	if (result)
-		return result;
+		goto free_res_buf;
 
 	hw->hw_info.buffer_share_bit = 0;
 	hw->hw_info.buffer_unshare_reserve_bit = 0;
@@ -245,11 +249,11 @@
 
 			result = fjes_hw_alloc_epbuf(&buf_pair->tx);
 			if (result)
-				return result;
+				goto free_epbuf;
 
 			result = fjes_hw_alloc_epbuf(&buf_pair->rx);
 			if (result)
-				return result;
+				goto free_epbuf;
 
 			spin_lock_irqsave(&hw->rx_status_lock, flags);
 			fjes_hw_setup_epbuf(&buf_pair->tx, mac,
@@ -272,6 +276,25 @@
 	fjes_hw_init_command_registers(hw, &param);
 
 	return 0;
+
+free_epbuf:
+	for (epidx = 0; epidx < hw->max_epid ; epidx++) {
+		if (epidx == hw->my_epid)
+			continue;
+		fjes_hw_free_epbuf(&hw->ep_shm_info[epidx].tx);
+		fjes_hw_free_epbuf(&hw->ep_shm_info[epidx].rx);
+	}
+	fjes_hw_free_shared_status_region(hw);
+free_res_buf:
+	kfree(hw->hw_info.res_buf);
+	hw->hw_info.res_buf = NULL;
+free_req_buf:
+	kfree(hw->hw_info.req_buf);
+	hw->hw_info.req_buf = NULL;
+free_ep_info:
+	kfree(hw->ep_shm_info);
+	hw->ep_shm_info = NULL;
+	return result;
 }
 
 static void fjes_hw_cleanup(struct fjes_hw *hw)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/fjes/fjes_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/fjes/fjes_main.c
@@ -166,6 +166,9 @@
 	/* create platform_device */
 	plat_dev = platform_device_register_simple(DRV_NAME, 0, fjes_resource,
 						   ARRAY_SIZE(fjes_resource));
+	if (IS_ERR(plat_dev))
+		return PTR_ERR(plat_dev);
+
 	device->driver_data = plat_dev;
 
 	return 0;
@@ -1259,9 +1262,18 @@
 	adapter->interrupt_watch_enable = false;
 
 	res = platform_get_resource(plat_dev, IORESOURCE_MEM, 0);
+	if (!res) {
+		err = -EINVAL;
+		goto err_free_control_wq;
+	}
 	hw->hw_res.start = res->start;
 	hw->hw_res.size = resource_size(res);
 	hw->hw_res.irq = platform_get_irq(plat_dev, 0);
+	if (hw->hw_res.irq < 0) {
+		err = hw->hw_res.irq;
+		goto err_free_control_wq;
+	}
+
 	err = fjes_hw_init(&adapter->hw);
 	if (err)
 		goto err_free_control_wq;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/geneve.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/geneve.c
@@ -215,14 +215,13 @@
 	struct metadata_dst *tun_dst = NULL;
 	struct pcpu_sw_netstats *stats;
 	unsigned int len;
-	int err = 0;
+	int nh, err = 0;
 	void *oiph;
 
 	if (ip_tunnel_collect_metadata() || gs->collect_md) {
 		__be16 flags;
 
-		flags = TUNNEL_KEY | TUNNEL_GENEVE_OPT |
-			(gnvh->oam ? TUNNEL_OAM : 0) |
+		flags = TUNNEL_KEY | (gnvh->oam ? TUNNEL_OAM : 0) |
 			(gnvh->critical ? TUNNEL_CRIT_OPT : 0);
 
 		tun_dst = udp_tun_rx_dst(skb, geneve_get_sk_family(gs), flags,
@@ -260,9 +259,23 @@
 		goto drop;
 	}
 
-	oiph = skb_network_header(skb);
+	/* Save offset of outer header relative to skb->head,
+	 * because we are going to reset the network header to the inner header
+	 * and might change skb->head.
+	 */
+	nh = skb_network_header(skb) - skb->head;
+
 	skb_reset_network_header(skb);
 
+	if (!pskb_inet_may_pull(skb)) {
+		DEV_STATS_INC(geneve->dev, rx_length_errors);
+		DEV_STATS_INC(geneve->dev, rx_errors);
+		goto drop;
+	}
+
+	/* Get the outer header. */
+	oiph = skb->head + nh;
+
 	if (geneve_get_sk_family(gs) == AF_INET)
 		err = IP_ECN_decapsulate(oiph, skb);
 #if IS_ENABLED(CONFIG_IPV6)
@@ -773,7 +786,8 @@
 				       struct net_device *dev,
 				       struct geneve_sock *gs4,
 				       struct flowi4 *fl4,
-				       const struct ip_tunnel_info *info)
+				       const struct ip_tunnel_info *info,
+				       __be16 dport, __be16 sport)
 {
 	bool use_cache = ip_tunnel_dst_cache_usable(skb, info);
 	struct geneve_dev *geneve = netdev_priv(dev);
@@ -789,6 +803,8 @@
 	fl4->flowi4_proto = IPPROTO_UDP;
 	fl4->daddr = info->key.u.ipv4.dst;
 	fl4->saddr = info->key.u.ipv4.src;
+	fl4->fl4_dport = dport;
+	fl4->fl4_sport = sport;
 
 	tos = info->key.tos;
 	if ((tos == 1) && !geneve->collect_md) {
@@ -823,7 +839,8 @@
 					   struct net_device *dev,
 					   struct geneve_sock *gs6,
 					   struct flowi6 *fl6,
-					   const struct ip_tunnel_info *info)
+					   const struct ip_tunnel_info *info,
+					   __be16 dport, __be16 sport)
 {
 	bool use_cache = ip_tunnel_dst_cache_usable(skb, info);
 	struct geneve_dev *geneve = netdev_priv(dev);
@@ -839,21 +856,25 @@
 	fl6->flowi6_proto = IPPROTO_UDP;
 	fl6->daddr = info->key.u.ipv6.dst;
 	fl6->saddr = info->key.u.ipv6.src;
+	fl6->fl6_dport = dport;
+	fl6->fl6_sport = sport;
+
 	prio = info->key.tos;
 	if ((prio == 1) && !geneve->collect_md) {
 		prio = ip_tunnel_get_dsfield(ip_hdr(skb), skb);
 		use_cache = false;
 	}
 
-	fl6->flowlabel = ip6_make_flowinfo(RT_TOS(prio),
-					   info->key.label);
+	fl6->flowlabel = ip6_make_flowinfo(prio, info->key.label);
 	dst_cache = (struct dst_cache *)&info->dst_cache;
 	if (use_cache) {
 		dst = dst_cache_get_ip6(dst_cache, &fl6->saddr);
 		if (dst)
 			return dst;
 	}
-	if (ipv6_stub->ipv6_dst_lookup(geneve->net, gs6->sock->sk, &dst, fl6)) {
+	dst = ipv6_stub->ipv6_dst_lookup_flow(geneve->net, gs6->sock->sk, fl6,
+					      NULL);
+	if (IS_ERR(dst)) {
 		netdev_dbg(dev, "no route to %pI6\n", &fl6->daddr);
 		return ERR_PTR(-ENETUNREACH);
 	}
@@ -883,14 +904,18 @@
 	__be16 sport;
 	int err;
 
-	rt = geneve_get_v4_rt(skb, dev, gs4, &fl4, info);
+	if (!skb_vlan_inet_prepare(skb))
+		return -EINVAL;
+
+	sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
+	rt = geneve_get_v4_rt(skb, dev, gs4, &fl4, info,
+			      geneve->info.key.tp_dst, sport);
 	if (IS_ERR(rt))
 		return PTR_ERR(rt);
 
 	skb_tunnel_check_pmtu(skb, &rt->dst,
 			      GENEVE_IPV4_HLEN + info->options_len);
 
-	sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
 	if (geneve->collect_md) {
 		tos = ip_tunnel_ecn_encap(key->tos, ip_hdr(skb), skb);
 		ttl = key->ttl;
@@ -945,13 +970,17 @@
 	__be16 sport;
 	int err;
 
-	dst = geneve_get_v6_dst(skb, dev, gs6, &fl6, info);
+	if (!skb_vlan_inet_prepare(skb))
+		return -EINVAL;
+
+	sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
+	dst = geneve_get_v6_dst(skb, dev, gs6, &fl6, info,
+				geneve->info.key.tp_dst, sport);
 	if (IS_ERR(dst))
 		return PTR_ERR(dst);
 
 	skb_tunnel_check_pmtu(skb, dst, GENEVE_IPV6_HLEN + info->options_len);
 
-	sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
 	if (geneve->collect_md) {
 		prio = ip_tunnel_ecn_encap(key->tos, ip_hdr(skb), skb);
 		ttl = key->ttl;
@@ -985,9 +1014,10 @@
 	if (geneve->collect_md) {
 		info = skb_tunnel_info(skb);
 		if (unlikely(!info || !(info->mode & IP_TUNNEL_INFO_TX))) {
-			err = -EINVAL;
 			netdev_dbg(dev, "no tunnel metadata\n");
-			goto tx_error;
+			dev_kfree_skb(skb);
+			dev->stats.tx_dropped++;
+			return NETDEV_TX_OK;
 		}
 	} else {
 		info = &geneve->info;
@@ -1004,7 +1034,7 @@
 
 	if (likely(!err))
 		return NETDEV_TX_OK;
-tx_error:
+
 	dev_kfree_skb(skb);
 
 	if (err == -ELOOP)
@@ -1031,13 +1061,18 @@
 {
 	struct ip_tunnel_info *info = skb_tunnel_info(skb);
 	struct geneve_dev *geneve = netdev_priv(dev);
+	__be16 sport;
 
 	if (ip_tunnel_info_af(info) == AF_INET) {
 		struct rtable *rt;
 		struct flowi4 fl4;
+
 		struct geneve_sock *gs4 = rcu_dereference(geneve->sock4);
+		sport = udp_flow_src_port(geneve->net, skb,
+					  1, USHRT_MAX, true);
 
-		rt = geneve_get_v4_rt(skb, dev, gs4, &fl4, info);
+		rt = geneve_get_v4_rt(skb, dev, gs4, &fl4, info,
+				      geneve->info.key.tp_dst, sport);
 		if (IS_ERR(rt))
 			return PTR_ERR(rt);
 
@@ -1047,9 +1082,13 @@
 	} else if (ip_tunnel_info_af(info) == AF_INET6) {
 		struct dst_entry *dst;
 		struct flowi6 fl6;
+
 		struct geneve_sock *gs6 = rcu_dereference(geneve->sock6);
+		sport = udp_flow_src_port(geneve->net, skb,
+					  1, USHRT_MAX, true);
 
-		dst = geneve_get_v6_dst(skb, dev, gs6, &fl6, info);
+		dst = geneve_get_v6_dst(skb, dev, gs6, &fl6, info,
+					geneve->info.key.tp_dst, sport);
 		if (IS_ERR(dst))
 			return PTR_ERR(dst);
 
@@ -1060,8 +1099,7 @@
 		return -EINVAL;
 	}
 
-	info->key.tp_src = udp_flow_src_port(geneve->net, skb,
-					     1, USHRT_MAX, true);
+	info->key.tp_src = sport;
 	info->key.tp_dst = geneve->info.key.tp_dst;
 	return 0;
 }
@@ -1205,7 +1243,7 @@
 		enum ifla_geneve_df df = nla_get_u8(data[IFLA_GENEVE_DF]);
 
 		if (df < 0 || df > GENEVE_DF_MAX) {
-			NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_GENEVE_DF],
+			NL_SET_ERR_MSG_ATTR(extack, data[IFLA_GENEVE_DF],
 					    "Invalid DF attribute");
 			return -EINVAL;
 		}
@@ -1612,11 +1650,11 @@
 			     struct netlink_ext_ack *extack)
 {
 	struct geneve_dev *geneve = netdev_priv(dev);
+	enum ifla_geneve_df df = geneve->df;
 	struct geneve_sock *gs4, *gs6;
 	struct ip_tunnel_info info;
 	bool metadata;
 	bool use_udp6_rx_checksums;
-	enum ifla_geneve_df df;
 	bool ttl_inherit;
 	int err;
 
@@ -1646,6 +1684,7 @@
 	geneve->collect_md = metadata;
 	geneve->use_udp6_rx_checksums = use_udp6_rx_checksums;
 	geneve->ttl_inherit = ttl_inherit;
+	geneve->df = df;
 	geneve_unquiesce(geneve, gs4, gs6);
 
 	return 0;
@@ -1828,23 +1867,9 @@
 {
 	struct geneve_net *gn = net_generic(net, geneve_net_id);
 	struct geneve_dev *geneve, *next;
-	struct net_device *dev, *aux;
 
-	/* gather any geneve devices that were moved into this ns */
-	for_each_netdev_safe(net, dev, aux)
-		if (dev->rtnl_link_ops == &geneve_link_ops)
-			unregister_netdevice_queue(dev, head);
-
-	/* now gather any other geneve devices that were created in this ns */
-	list_for_each_entry_safe(geneve, next, &gn->geneve_list, next) {
-		/* If geneve->dev is in the same netns, it was already added
-		 * to the list by the previous loop.
-		 */
-		if (!net_eq(dev_net(geneve->dev), net))
-			unregister_netdevice_queue(geneve->dev, head);
-	}
-
-	WARN_ON_ONCE(!list_empty(&gn->sock_list));
+	list_for_each_entry_safe(geneve, next, &gn->geneve_list, next)
+		geneve_dellink(geneve->dev, head);
 }
 
 static void __net_exit geneve_exit_batch_net(struct list_head *net_list)
@@ -1859,6 +1884,12 @@
 	/* unregister the devices gathered above */
 	unregister_netdevice_many(&list);
 	rtnl_unlock();
+
+	list_for_each_entry(net, net_list, exit_list) {
+		const struct geneve_net *gn = net_generic(net, geneve_net_id);
+
+		WARN_ON_ONCE(!list_empty(&gn->sock_list));
+	}
 }
 
 static struct pernet_operations geneve_net_ops = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/gtp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/gtp.c
@@ -38,7 +38,6 @@
 	struct hlist_node	hlist_addr;
 
 	union {
-		u64		tid;
 		struct {
 			u64	tid;
 			u16	flow;
@@ -298,7 +297,9 @@
 			gtp->sk1u = NULL;
 		udp_sk(sk)->encap_type = 0;
 		rcu_assign_sk_user_data(sk, NULL);
+		release_sock(sk);
 		sock_put(sk);
+		return;
 	}
 	release_sock(sk);
 }
@@ -541,14 +542,14 @@
 		mtu = dst_mtu(&rt->dst);
 	}
 
-	rt->dst.ops->update_pmtu(&rt->dst, NULL, skb, mtu);
+	rt->dst.ops->update_pmtu(&rt->dst, NULL, skb, mtu, false);
 
-	if (!skb_is_gso(skb) && (iph->frag_off & htons(IP_DF)) &&
-	    mtu < ntohs(iph->tot_len)) {
+	if (iph->frag_off & htons(IP_DF) &&
+	    ((!skb_is_gso(skb) && skb->len > mtu) ||
+	     (skb_is_gso(skb) && !skb_gso_validate_network_len(skb, mtu)))) {
 		netdev_dbg(dev, "packet too big, fragmentation needed\n");
-		memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
-		icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
-			  htonl(mtu));
+		icmp_ndo_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
+			      htonl(mtu));
 		goto err_rt;
 	}
 
@@ -572,6 +573,9 @@
 	if (skb_cow_head(skb, dev->needed_headroom))
 		goto tx_err;
 
+	if (!pskb_inet_may_pull(skb))
+		goto tx_err;
+
 	skb_reset_inner_headers(skb);
 
 	/* PDP context lookups in gtp_build_skb_*() need rcu read-side lock. */
@@ -641,9 +645,16 @@
 }
 
 static int gtp_hashtable_new(struct gtp_dev *gtp, int hsize);
-static void gtp_hashtable_free(struct gtp_dev *gtp);
 static int gtp_encap_enable(struct gtp_dev *gtp, struct nlattr *data[]);
 
+static void gtp_destructor(struct net_device *dev)
+{
+	struct gtp_dev *gtp = netdev_priv(dev);
+
+	kfree(gtp->addr_hash);
+	kfree(gtp->tid_hash);
+}
+
 static int gtp_newlink(struct net *src_net, struct net_device *dev,
 		       struct nlattr *tb[], struct nlattr *data[],
 		       struct netlink_ext_ack *extack)
@@ -657,45 +668,56 @@
 
 	gtp = netdev_priv(dev);
 
-	err = gtp_encap_enable(gtp, data);
-	if (err < 0)
-		return err;
-
-	if (!data[IFLA_GTP_PDP_HASHSIZE])
+	if (!data[IFLA_GTP_PDP_HASHSIZE]) {
 		hashsize = 1024;
-	else
+	} else {
 		hashsize = nla_get_u32(data[IFLA_GTP_PDP_HASHSIZE]);
+		if (!hashsize)
+			hashsize = 1024;
+	}
 
 	err = gtp_hashtable_new(gtp, hashsize);
 	if (err < 0)
-		goto out_encap;
+		return err;
+
+	err = gtp_encap_enable(gtp, data);
+	if (err < 0)
+		goto out_hashtable;
 
 	err = register_netdevice(dev);
 	if (err < 0) {
 		netdev_dbg(dev, "failed to register new netdev %d\n", err);
-		goto out_hashtable;
+		goto out_encap;
 	}
 
-	gn = net_generic(dev_net(dev), gtp_net_id);
-	list_add_rcu(&gtp->list, &gn->gtp_dev_list);
+	gn = net_generic(src_net, gtp_net_id);
+	list_add(&gtp->list, &gn->gtp_dev_list);
+	dev->priv_destructor = gtp_destructor;
 
 	netdev_dbg(dev, "registered new GTP interface\n");
 
 	return 0;
 
-out_hashtable:
-	gtp_hashtable_free(gtp);
 out_encap:
 	gtp_encap_disable(gtp);
+out_hashtable:
+	kfree(gtp->addr_hash);
+	kfree(gtp->tid_hash);
 	return err;
 }
 
 static void gtp_dellink(struct net_device *dev, struct list_head *head)
 {
 	struct gtp_dev *gtp = netdev_priv(dev);
+	struct hlist_node *next;
+	struct pdp_ctx *pctx;
+	int i;
+
+	for (i = 0; i < gtp->hash_size; i++)
+		hlist_for_each_entry_safe(pctx, next, &gtp->tid_hash[i], hlist_tid)
+			pdp_context_delete(pctx);
 
-	gtp_hashtable_free(gtp);
-	list_del_rcu(&gtp->list);
+	list_del(&gtp->list);
 	unregister_netdevice_queue(dev, head);
 }
 
@@ -751,12 +773,12 @@
 	int i;
 
 	gtp->addr_hash = kmalloc_array(hsize, sizeof(struct hlist_head),
-				       GFP_KERNEL);
+				       GFP_KERNEL | __GFP_NOWARN);
 	if (gtp->addr_hash == NULL)
 		return -ENOMEM;
 
 	gtp->tid_hash = kmalloc_array(hsize, sizeof(struct hlist_head),
-				      GFP_KERNEL);
+				      GFP_KERNEL | __GFP_NOWARN);
 	if (gtp->tid_hash == NULL)
 		goto err1;
 
@@ -772,20 +794,6 @@
 	return -ENOMEM;
 }
 
-static void gtp_hashtable_free(struct gtp_dev *gtp)
-{
-	struct pdp_ctx *pctx;
-	int i;
-
-	for (i = 0; i < gtp->hash_size; i++)
-		hlist_for_each_entry_rcu(pctx, &gtp->tid_hash[i], hlist_tid)
-			pdp_context_delete(pctx);
-
-	synchronize_rcu();
-	kfree(gtp->addr_hash);
-	kfree(gtp->tid_hash);
-}
-
 static struct sock *gtp_encap_enable_socket(int fd, int type,
 					    struct gtp_dev *gtp)
 {
@@ -799,22 +807,24 @@
 	sock = sockfd_lookup(fd, &err);
 	if (!sock) {
 		pr_debug("gtp socket fd=%d not found\n", fd);
-		return NULL;
+		return ERR_PTR(err);
 	}
 
-	if (sock->sk->sk_protocol != IPPROTO_UDP) {
+	sk = sock->sk;
+	if (sk->sk_protocol != IPPROTO_UDP ||
+	    sk->sk_type != SOCK_DGRAM ||
+	    (sk->sk_family != AF_INET && sk->sk_family != AF_INET6)) {
 		pr_debug("socket fd=%d not UDP\n", fd);
 		sk = ERR_PTR(-EINVAL);
 		goto out_sock;
 	}
 
-	lock_sock(sock->sk);
-	if (sock->sk->sk_user_data) {
+	lock_sock(sk);
+	if (sk->sk_user_data) {
 		sk = ERR_PTR(-EBUSY);
-		goto out_sock;
+		goto out_rel_sock;
 	}
 
-	sk = sock->sk;
 	sock_hold(sk);
 
 	tuncfg.sk_user_data = gtp;
@@ -824,8 +834,9 @@
 
 	setup_udp_tunnel_sock(sock_net(sock->sk), sock, &tuncfg);
 
-out_sock:
+out_rel_sock:
 	release_sock(sock->sk);
+out_sock:
 	sockfd_put(sock);
 	return sk;
 }
@@ -837,31 +848,32 @@
 	unsigned int role = GTP_ROLE_GGSN;
 
 	if (data[IFLA_GTP_FD0]) {
-		u32 fd0 = nla_get_u32(data[IFLA_GTP_FD0]);
+		int fd0 = nla_get_u32(data[IFLA_GTP_FD0]);
 
-		sk0 = gtp_encap_enable_socket(fd0, UDP_ENCAP_GTP0, gtp);
-		if (IS_ERR(sk0))
-			return PTR_ERR(sk0);
+		if (fd0 >= 0) {
+			sk0 = gtp_encap_enable_socket(fd0, UDP_ENCAP_GTP0, gtp);
+			if (IS_ERR(sk0))
+				return PTR_ERR(sk0);
+		}
 	}
 
 	if (data[IFLA_GTP_FD1]) {
-		u32 fd1 = nla_get_u32(data[IFLA_GTP_FD1]);
+		int fd1 = nla_get_u32(data[IFLA_GTP_FD1]);
 
-		sk1u = gtp_encap_enable_socket(fd1, UDP_ENCAP_GTP1U, gtp);
-		if (IS_ERR(sk1u)) {
-			if (sk0)
+		if (fd1 >= 0) {
+			sk1u = gtp_encap_enable_socket(fd1, UDP_ENCAP_GTP1U, gtp);
+			if (IS_ERR(sk1u)) {
 				gtp_encap_disable_sock(sk0);
-			return PTR_ERR(sk1u);
+				return PTR_ERR(sk1u);
+			}
 		}
 	}
 
 	if (data[IFLA_GTP_ROLE]) {
 		role = nla_get_u32(data[IFLA_GTP_ROLE]);
 		if (role > GTP_ROLE_SGSN) {
-			if (sk0)
-				gtp_encap_disable_sock(sk0);
-			if (sk1u)
-				gtp_encap_disable_sock(sk1u);
+			gtp_encap_disable_sock(sk0);
+			gtp_encap_disable_sock(sk1u);
 			return -EINVAL;
 		}
 	}
@@ -926,24 +938,31 @@
 	}
 }
 
-static int ipv4_pdp_add(struct gtp_dev *gtp, struct sock *sk,
-			struct genl_info *info)
+static int gtp_pdp_add(struct gtp_dev *gtp, struct sock *sk,
+		       struct genl_info *info)
 {
+	struct pdp_ctx *pctx, *pctx_tid = NULL;
 	struct net_device *dev = gtp->dev;
 	u32 hash_ms, hash_tid = 0;
-	struct pdp_ctx *pctx;
+	unsigned int version;
 	bool found = false;
 	__be32 ms_addr;
 
 	ms_addr = nla_get_be32(info->attrs[GTPA_MS_ADDRESS]);
 	hash_ms = ipv4_hashfn(ms_addr) % gtp->hash_size;
+	version = nla_get_u32(info->attrs[GTPA_VERSION]);
 
-	hlist_for_each_entry_rcu(pctx, &gtp->addr_hash[hash_ms], hlist_addr) {
-		if (pctx->ms_addr_ip4.s_addr == ms_addr) {
-			found = true;
-			break;
-		}
-	}
+	pctx = ipv4_pdp_find(gtp, ms_addr);
+	if (pctx)
+		found = true;
+	if (version == GTP_V0)
+		pctx_tid = gtp0_pdp_find(gtp,
+					 nla_get_u64(info->attrs[GTPA_TID]));
+	else if (version == GTP_V1)
+		pctx_tid = gtp1_pdp_find(gtp,
+					 nla_get_u32(info->attrs[GTPA_I_TEI]));
+	if (pctx_tid)
+		found = true;
 
 	if (found) {
 		if (info->nlhdr->nlmsg_flags & NLM_F_EXCL)
@@ -951,6 +970,11 @@
 		if (info->nlhdr->nlmsg_flags & NLM_F_REPLACE)
 			return -EOPNOTSUPP;
 
+		if (pctx && pctx_tid)
+			return -EEXIST;
+		if (!pctx)
+			pctx = pctx_tid;
+
 		ipv4_pdp_fill(pctx, info);
 
 		if (pctx->gtp_version == GTP_V0)
@@ -1074,7 +1098,7 @@
 		goto out_unlock;
 	}
 
-	err = ipv4_pdp_add(gtp, sk, info);
+	err = gtp_pdp_add(gtp, sk, info);
 
 out_unlock:
 	rcu_read_unlock();
@@ -1155,16 +1179,17 @@
 static struct genl_family gtp_genl_family;
 
 static int gtp_genl_fill_info(struct sk_buff *skb, u32 snd_portid, u32 snd_seq,
-			      u32 type, struct pdp_ctx *pctx)
+			      int flags, u32 type, struct pdp_ctx *pctx)
 {
 	void *genlh;
 
-	genlh = genlmsg_put(skb, snd_portid, snd_seq, &gtp_genl_family, 0,
+	genlh = genlmsg_put(skb, snd_portid, snd_seq, &gtp_genl_family, flags,
 			    type);
 	if (genlh == NULL)
 		goto nlmsg_failure;
 
 	if (nla_put_u32(skb, GTPA_VERSION, pctx->gtp_version) ||
+	    nla_put_u32(skb, GTPA_LINK, pctx->dev->ifindex) ||
 	    nla_put_be32(skb, GTPA_PEER_ADDRESS, pctx->peer_addr_ip4.s_addr) ||
 	    nla_put_be32(skb, GTPA_MS_ADDRESS, pctx->ms_addr_ip4.s_addr))
 		goto nla_put_failure;
@@ -1213,8 +1238,8 @@
 		goto err_unlock;
 	}
 
-	err = gtp_genl_fill_info(skb2, NETLINK_CB(skb).portid,
-				 info->snd_seq, info->nlhdr->nlmsg_type, pctx);
+	err = gtp_genl_fill_info(skb2, NETLINK_CB(skb).portid, info->snd_seq,
+				 0, info->nlhdr->nlmsg_type, pctx);
 	if (err < 0)
 		goto err_unlock_free;
 
@@ -1232,43 +1257,50 @@
 				struct netlink_callback *cb)
 {
 	struct gtp_dev *last_gtp = (struct gtp_dev *)cb->args[2], *gtp;
+	int i, j, bucket = cb->args[0], skip = cb->args[1];
 	struct net *net = sock_net(skb->sk);
-	struct gtp_net *gn = net_generic(net, gtp_net_id);
-	unsigned long tid = cb->args[1];
-	int i, k = cb->args[0], ret;
+	struct net_device *dev;
 	struct pdp_ctx *pctx;
 
 	if (cb->args[4])
 		return 0;
 
-	list_for_each_entry_rcu(gtp, &gn->gtp_dev_list, list) {
+	rcu_read_lock();
+	for_each_netdev_rcu(net, dev) {
+		if (dev->rtnl_link_ops != &gtp_link_ops)
+			continue;
+
+		gtp = netdev_priv(dev);
+
 		if (last_gtp && last_gtp != gtp)
 			continue;
 		else
 			last_gtp = NULL;
 
-		for (i = k; i < gtp->hash_size; i++) {
-			hlist_for_each_entry_rcu(pctx, &gtp->tid_hash[i], hlist_tid) {
-				if (tid && tid != pctx->u.tid)
-					continue;
-				else
-					tid = 0;
-
-				ret = gtp_genl_fill_info(skb,
-							 NETLINK_CB(cb->skb).portid,
-							 cb->nlh->nlmsg_seq,
-							 cb->nlh->nlmsg_type, pctx);
-				if (ret < 0) {
+		for (i = bucket; i < gtp->hash_size; i++) {
+			j = 0;
+			hlist_for_each_entry_rcu(pctx, &gtp->tid_hash[i],
+						 hlist_tid) {
+				if (j >= skip &&
+				    gtp_genl_fill_info(skb,
+					    NETLINK_CB(cb->skb).portid,
+					    cb->nlh->nlmsg_seq,
+					    NLM_F_MULTI,
+					    cb->nlh->nlmsg_type, pctx)) {
 					cb->args[0] = i;
-					cb->args[1] = pctx->u.tid;
+					cb->args[1] = j;
 					cb->args[2] = (unsigned long)gtp;
 					goto out;
 				}
+				j++;
 			}
+			skip = 0;
 		}
+		bucket = 0;
 	}
 	cb->args[4] = 1;
 out:
+	rcu_read_unlock();
 	return skb->len;
 }
 
@@ -1326,23 +1358,23 @@
 	return 0;
 }
 
-static void __net_exit gtp_net_exit(struct net *net)
+static void __net_exit gtp_net_exit_batch_rtnl(struct list_head *net_list,
+					       struct list_head *dev_to_kill)
 {
-	struct gtp_net *gn = net_generic(net, gtp_net_id);
-	struct gtp_dev *gtp;
-	LIST_HEAD(list);
+	struct net *net;
 
-	rtnl_lock();
-	list_for_each_entry(gtp, &gn->gtp_dev_list, list)
-		gtp_dellink(gtp->dev, &list);
+	list_for_each_entry(net, net_list, exit_list) {
+		struct gtp_net *gn = net_generic(net, gtp_net_id);
+		struct gtp_dev *gtp, *gtp_next;
 
-	unregister_netdevice_many(&list);
-	rtnl_unlock();
+		list_for_each_entry_safe(gtp, gtp_next, &gn->gtp_dev_list, list)
+			gtp_dellink(gtp->dev, dev_to_kill);
+	}
 }
 
 static struct pernet_operations gtp_net_ops = {
 	.init	= gtp_net_init,
-	.exit	= gtp_net_exit,
+	.exit_batch_rtnl = gtp_net_exit_batch_rtnl,
 	.id	= &gtp_net_id,
 	.size	= sizeof(struct gtp_net),
 };
@@ -1353,26 +1385,26 @@
 
 	get_random_bytes(&gtp_h_initval, sizeof(gtp_h_initval));
 
-	err = rtnl_link_register(&gtp_link_ops);
+	err = register_pernet_subsys(&gtp_net_ops);
 	if (err < 0)
 		goto error_out;
 
-	err = genl_register_family(&gtp_genl_family);
+	err = rtnl_link_register(&gtp_link_ops);
 	if (err < 0)
-		goto unreg_rtnl_link;
+		goto unreg_pernet_subsys;
 
-	err = register_pernet_subsys(&gtp_net_ops);
+	err = genl_register_family(&gtp_genl_family);
 	if (err < 0)
-		goto unreg_genl_family;
+		goto unreg_rtnl_link;
 
 	pr_info("GTP module loaded (pdp ctx size %zd bytes)\n",
 		sizeof(struct pdp_ctx));
 	return 0;
 
-unreg_genl_family:
-	genl_unregister_family(&gtp_genl_family);
 unreg_rtnl_link:
 	rtnl_link_unregister(&gtp_link_ops);
+unreg_pernet_subsys:
+	unregister_pernet_subsys(&gtp_net_ops);
 error_out:
 	pr_err("error loading GTP module loaded\n");
 	return err;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/hamradio/6pack.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/hamradio/6pack.c
@@ -68,9 +68,9 @@
 #define SIXP_DAMA_OFF		0
 
 /* default level 2 parameters */
-#define SIXP_TXDELAY			(HZ/4)	/* in 1 s */
+#define SIXP_TXDELAY			25	/* 250 ms */
 #define SIXP_PERSIST			50	/* in 256ths */
-#define SIXP_SLOTTIME			(HZ/10)	/* in 1 s */
+#define SIXP_SLOTTIME			10	/* 100 ms */
 #define SIXP_INIT_RESYNC_TIMEOUT	(3*HZ/2) /* in 1 s */
 #define SIXP_RESYNC_TIMEOUT		5*HZ	/* in 1 s */
 
@@ -311,7 +311,6 @@
 {
 	/* Finish setting up the DEVICE info. */
 	dev->netdev_ops		= &sp_netdev_ops;
-	dev->needs_free_netdev	= true;
 	dev->mtu		= SIXP_MTU;
 	dev->hard_header_len	= AX25_MAX_HEADER_LEN;
 	dev->header_ops 	= &ax25_header_ops;
@@ -654,10 +653,10 @@
 {
 	struct sixpack *sp;
 
-	write_lock_bh(&disc_data_lock);
+	write_lock_irq(&disc_data_lock);
 	sp = tty->disc_data;
 	tty->disc_data = NULL;
-	write_unlock_bh(&disc_data_lock);
+	write_unlock_irq(&disc_data_lock);
 	if (!sp)
 		return;
 
@@ -674,14 +673,16 @@
 	 */
 	netif_stop_queue(sp->dev);
 
+	unregister_netdev(sp->dev);
+
 	del_timer_sync(&sp->tx_t);
 	del_timer_sync(&sp->resync_t);
 
-	/* Free all 6pack frame buffers. */
+	/* Free all 6pack frame buffers after unreg. */
 	kfree(sp->rbuff);
 	kfree(sp->xbuff);
 
-	unregister_netdev(sp->dev);
+	free_netdev(sp->dev);
 }
 
 /* Perform I/O control on an active 6pack channel. */
@@ -839,6 +840,12 @@
 		return;
 	}
 
+	if (sp->rx_count_cooked + 2 >= sizeof(sp->cooked_buf)) {
+		pr_err("6pack: cooked buffer overrun, data loss\n");
+		sp->rx_count = 0;
+		return;
+	}
+
 	buf = sp->raw_buf;
 	sp->cooked_buf[sp->rx_count_cooked++] =
 		buf[0] | ((buf[1] << 2) & 0xc0);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/hamradio/baycom_epp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/hamradio/baycom_epp.c
@@ -758,7 +758,7 @@
  * ===================== network driver interface =========================
  */
 
-static int baycom_send_packet(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t baycom_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
 	struct baycom_state *bc = netdev_priv(dev);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/hamradio/bpqether.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/hamradio/bpqether.c
@@ -127,7 +127,8 @@
 {
 	struct bpqdev *bpq;
 
-	list_for_each_entry_rcu(bpq, &bpq_devices, bpq_list) {
+	list_for_each_entry_rcu(bpq, &bpq_devices, bpq_list,
+				lockdep_rtnl_is_held()) {
 		if (bpq->ethdev == dev)
 			return bpq->axdev;
 	}
@@ -510,7 +511,7 @@
 	if (!net_eq(dev_net(dev), &init_net))
 		return NOTIFY_DONE;
 
-	if (!dev_is_ethdev(dev))
+	if (!dev_is_ethdev(dev) && !bpq_get_ax25_dev(dev))
 		return NOTIFY_DONE;
 
 	switch (event) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/hamradio/mkiss.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/hamradio/mkiss.c
@@ -31,6 +31,8 @@
 
 #define AX_MTU		236
 
+/* some arch define END as assembly function ending, just undef it */
+#undef	END
 /* SLIP/KISS protocol characters. */
 #define END             0300		/* indicates end of frame	*/
 #define ESC             0333		/* indicates byte stuffing	*/
@@ -773,10 +775,10 @@
 {
 	struct mkiss *ax;
 
-	write_lock_bh(&disc_data_lock);
+	write_lock_irq(&disc_data_lock);
 	ax = tty->disc_data;
 	tty->disc_data = NULL;
-	write_unlock_bh(&disc_data_lock);
+	write_unlock_irq(&disc_data_lock);
 
 	if (!ax)
 		return;
@@ -793,13 +795,15 @@
 	 */
 	netif_stop_queue(ax->dev);
 
-	/* Free all AX25 frame buffers. */
+	unregister_netdev(ax->dev);
+
+	/* Free all AX25 frame buffers after unreg. */
 	kfree(ax->rbuff);
 	kfree(ax->xbuff);
 
 	ax->tty = NULL;
 
-	unregister_netdev(ax->dev);
+	free_netdev(ax->dev);
 }
 
 /* Perform I/O control on an active ax25 channel. */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/hamradio/scc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/hamradio/scc.c
@@ -300,12 +300,12 @@
 	spin_lock_irqsave(&scc->lock, flags);	
 	if (scc->tx_buff != NULL)
 	{
-		dev_kfree_skb(scc->tx_buff);
+		dev_kfree_skb_irq(scc->tx_buff);
 		scc->tx_buff = NULL;
 	}
 	
 	while (!skb_queue_empty(&scc->tx_queue))
-		dev_kfree_skb(skb_dequeue(&scc->tx_queue));
+		dev_kfree_skb_irq(skb_dequeue(&scc->tx_queue));
 
 	spin_unlock_irqrestore(&scc->lock, flags);
 }
@@ -1667,7 +1667,7 @@
 	if (skb_queue_len(&scc->tx_queue) > scc->dev->tx_queue_len) {
 		struct sk_buff *skb_del;
 		skb_del = skb_dequeue(&scc->tx_queue);
-		dev_kfree_skb(skb_del);
+		dev_kfree_skb_irq(skb_del);
 	}
 	skb_queue_tail(&scc->tx_queue, skb);
 	netif_trans_update(dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/hamradio/yam.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/hamradio/yam.c
@@ -951,9 +951,7 @@
 				 sizeof(struct yamdrv_ioctl_mcs));
 		if (IS_ERR(ym))
 			return PTR_ERR(ym);
-		if (ym->cmd != SIOCYAMSMCS)
-			return -EINVAL;
-		if (ym->bitrate > YAM_MAXBITRATE) {
+		if (ym->cmd != SIOCYAMSMCS || ym->bitrate > YAM_MAXBITRATE) {
 			kfree(ym);
 			return -EINVAL;
 		}
@@ -1133,6 +1131,7 @@
 		err = register_netdev(dev);
 		if (err) {
 			printk(KERN_WARNING "yam: cannot register net device %s\n", dev->name);
+			free_netdev(dev);
 			goto error;
 		}
 		yam_devs[i] = dev;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/hippi/rrunner.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/hippi/rrunner.c
@@ -1242,7 +1242,7 @@
 		rrpriv->info = NULL;
 	}
 	if (rrpriv->rx_ctrl) {
-		pci_free_consistent(pdev, sizeof(struct ring_ctrl),
+		pci_free_consistent(pdev, 256 * sizeof(struct ring_ctrl),
 				    rrpriv->rx_ctrl, rrpriv->rx_ctrl_dma);
 		rrpriv->rx_ctrl = NULL;
 	}
@@ -1346,7 +1346,9 @@
 
 	rrpriv->fw_running = 0;
 
+	spin_unlock_irqrestore(&rrpriv->lock, flags);
 	del_timer_sync(&rrpriv->timer);
+	spin_lock_irqsave(&rrpriv->lock, flags);
 
 	writel(0, &regs->TxPi);
 	writel(0, &regs->IpRxPi);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/hyperv/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/hyperv/Kconfig
@@ -3,5 +3,6 @@
 	tristate "Microsoft Hyper-V virtual network driver"
 	depends on HYPERV
 	select UCS2_STRING
+	select NLS
 	help
 	  Select this option to enable the Hyper-V virtual network driver.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/hyperv/hyperv_net.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/hyperv/hyperv_net.h
@@ -169,7 +169,6 @@
 
 	u8 hw_mac_adr[ETH_ALEN];
 	u8 rss_key[NETVSC_HASH_KEYLEN];
-	u16 rx_table[ITAB_NUM];
 };
 
 
@@ -880,6 +879,7 @@
 	unsigned long rx_no_memory;
 	unsigned long stop_queue;
 	unsigned long wake_queue;
+	unsigned long vlan_error;
 };
 
 struct netvsc_ethtool_pcpu_stats {
@@ -938,6 +938,8 @@
 
 	u32 tx_table[VRSS_SEND_TAB_SIZE];
 
+	u16 rx_table[ITAB_NUM];
+
 	/* Ethtool settings */
 	u8 duplex;
 	u32 speed;
@@ -953,6 +955,9 @@
 	u32 vf_alloc;
 	/* Serial number of the VF to team with */
 	u32 vf_serial;
+
+	/* completion variable to confirm vf association */
+	struct completion vf_add;
 };
 
 /* Per channel data */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/hyperv/netvsc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/hyperv/netvsc.c
@@ -99,7 +99,7 @@
 
 	init_waitqueue_head(&net_device->wait_drain);
 	net_device->destroy = false;
-	net_device->tx_disable = false;
+	net_device->tx_disable = true;
 
 	net_device->max_pkt = RNDIS_MAX_PKT_DEFAULT;
 	net_device->pkt_align = RNDIS_PKT_ALIGN_DEFAULT;
@@ -1223,6 +1223,10 @@
 
 	net_device_ctx->vf_alloc = nvmsg->msg.v4_msg.vf_assoc.allocated;
 	net_device_ctx->vf_serial = nvmsg->msg.v4_msg.vf_assoc.serial;
+
+	if (net_device_ctx->vf_alloc)
+		complete(&net_device_ctx->vf_add);
+
 	netdev_info(ndev, "VF slot %u %s\n",
 		    net_device_ctx->vf_serial,
 		    net_device_ctx->vf_alloc ? "added" : "removed");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/hyperv/netvsc_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/hyperv/netvsc_drv.c
@@ -43,6 +43,10 @@
 #define LINKCHANGE_INT (2 * HZ)
 #define VF_TAKEOVER_INT (HZ / 10)
 
+/* Macros to define the context of vf registration */
+#define VF_REG_IN_PROBE		1
+#define VF_REG_IN_NOTIFIER	2
+
 static unsigned int ring_size __ro_after_init = 128;
 module_param(ring_size, uint, 0444);
 MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)");
@@ -285,9 +289,9 @@
 		else if (flow.basic.n_proto == htons(ETH_P_IPV6))
 			hash = jhash2((u32 *)&flow.addrs.v6addrs, 8, hashrnd);
 		else
-			hash = 0;
+			return 0;
 
-		skb_set_hash(skb, hash, PKT_HASH_TYPE_L3);
+		__skb_set_sw_hash(skb, hash, false);
 	}
 
 	return hash;
@@ -366,7 +370,7 @@
 	}
 	rcu_read_unlock();
 
-	while (unlikely(txq >= ndev->real_num_tx_queues))
+	while (txq >= ndev->real_num_tx_queues)
 		txq -= ndev->real_num_tx_queues;
 
 	return txq;
@@ -501,7 +505,7 @@
 	int rc;
 
 	skb->dev = vf_netdev;
-	skb->queue_mapping = qdisc_skb_cb(skb)->slave_dev_queue_mapping;
+	skb_record_rx_queue(skb, qdisc_skb_cb(skb)->slave_dev_queue_mapping);
 
 	rc = dev_queue_xmit(skb);
 	if (likely(rc == NET_XMIT_SUCCESS || rc == NET_XMIT_CN)) {
@@ -531,12 +535,13 @@
 	u32 hash;
 	struct hv_page_buffer pb[MAX_PAGE_BUFFER_COUNT];
 
-	/* if VF is present and up then redirect packets
-	 * already called with rcu_read_lock_bh
+	/* If VF is present and up then redirect packets to it.
+	 * Skip the VF if it is marked down or has no carrier.
+	 * If netpoll is in uses, then VF can not be used either.
 	 */
 	vf_netdev = rcu_dereference_bh(net_device_ctx->vf_netdev);
 	if (vf_netdev && netif_running(vf_netdev) &&
-	    !netpoll_tx_running(net))
+	    netif_carrier_ok(vf_netdev) && !netpoll_tx_running(net))
 		return netvsc_vf_xmit(net, vf_netdev, skb);
 
 	/* We will atmost need two pages to describe the rndis
@@ -604,6 +609,29 @@
 		*hash_info = hash;
 	}
 
+	/* When using AF_PACKET we need to drop VLAN header from
+	 * the frame and update the SKB to allow the HOST OS
+	 * to transmit the 802.1Q packet
+	 */
+	if (skb->protocol == htons(ETH_P_8021Q)) {
+		u16 vlan_tci;
+
+		skb_reset_mac_header(skb);
+		if (eth_type_vlan(eth_hdr(skb)->h_proto)) {
+			if (unlikely(__skb_vlan_pop(skb, &vlan_tci) != 0)) {
+				++net_device_ctx->eth_stats.vlan_error;
+				goto drop;
+			}
+
+			__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tci);
+			/* Update the NDIS header pkt lengths */
+			packet->total_data_buflen -= VLAN_HLEN;
+			packet->total_bytes -= VLAN_HLEN;
+			rndis_msg->msg_len = packet->total_data_buflen;
+			rndis_msg->msg.pkt.data_len = packet->total_data_buflen;
+		}
+	}
+
 	if (skb_vlan_tag_present(skb)) {
 		struct ndis_pkt_8021q_info *vlan;
 
@@ -795,8 +823,7 @@
 	    skb->protocol == htons(ETH_P_IP))
 		netvsc_comp_ipcsum(skb);
 
-	/* Do L4 checksum offload if enabled and present.
-	 */
+	/* Do L4 checksum offload if enabled and present. */
 	if (csum_info && (net->features & NETIF_F_RXCSUM)) {
 		if (csum_info->receive.tcp_checksum_succeeded ||
 		    csum_info->receive.udp_checksum_succeeded)
@@ -974,6 +1001,7 @@
 	}
 
 	/* In any case device is now ready */
+	nvdev->tx_disable = false;
 	netif_device_attach(ndev);
 
 	/* Note: enable and attach happen when sub-channels setup */
@@ -1344,6 +1372,7 @@
 	{ "rx_no_memory", offsetof(struct netvsc_ethtool_stats, rx_no_memory) },
 	{ "stop_queue", offsetof(struct netvsc_ethtool_stats, stop_queue) },
 	{ "wake_queue", offsetof(struct netvsc_ethtool_stats, wake_queue) },
+	{ "vlan_error", offsetof(struct netvsc_ethtool_stats, vlan_error) },
 }, pcpu_stats[] = {
 	{ "cpu%u_rx_packets",
 		offsetof(struct netvsc_ethtool_pcpu_stats, rx_packets) },
@@ -1444,6 +1473,9 @@
 	pcpu_sum = kvmalloc_array(num_possible_cpus(),
 				  sizeof(struct netvsc_ethtool_pcpu_stats),
 				  GFP_KERNEL);
+	if (!pcpu_sum)
+		return;
+
 	netvsc_get_pcpu_stats(dev, pcpu_sum);
 	for_each_present_cpu(cpu) {
 		struct netvsc_ethtool_pcpu_stats *this_sum = &pcpu_sum[cpu];
@@ -1659,7 +1691,7 @@
 	rndis_dev = ndev->extension;
 	if (indir) {
 		for (i = 0; i < ITAB_NUM; i++)
-			indir[i] = rndis_dev->rx_table[i];
+			indir[i] = ndc->rx_table[i];
 	}
 
 	if (key)
@@ -1689,7 +1721,7 @@
 				return -EINVAL;
 
 		for (i = 0; i < ITAB_NUM; i++)
-			rndis_dev->rx_table[i] = indir[i];
+			ndc->rx_table[i] = indir[i];
 	}
 
 	if (!key) {
@@ -2033,7 +2065,7 @@
 }
 
 static int netvsc_vf_join(struct net_device *vf_netdev,
-			  struct net_device *ndev)
+			  struct net_device *ndev, int context)
 {
 	struct net_device_context *ndev_ctx = netdev_priv(ndev);
 	int ret;
@@ -2056,10 +2088,11 @@
 		goto upper_link_failed;
 	}
 
-	/* set slave flag before open to prevent IPv6 addrconf */
-	vf_netdev->flags |= IFF_SLAVE;
-
-	schedule_delayed_work(&ndev_ctx->vf_takeover, VF_TAKEOVER_INT);
+	/* If this registration is called from probe context vf_takeover
+	 * is taken care of later in probe itself.
+	 */
+	if (context == VF_REG_IN_NOTIFIER)
+		schedule_delayed_work(&ndev_ctx->vf_takeover, VF_TAKEOVER_INT);
 
 	call_netdevice_notifiers(NETDEV_JOIN, vf_netdev);
 
@@ -2129,6 +2162,7 @@
 {
 	struct device *parent = vf_netdev->dev.parent;
 	struct net_device_context *ndev_ctx;
+	struct net_device *ndev;
 	struct pci_dev *pdev;
 	u32 serial;
 
@@ -2151,8 +2185,31 @@
 		if (!ndev_ctx->vf_alloc)
 			continue;
 
-		if (ndev_ctx->vf_serial == serial)
-			return hv_get_drvdata(ndev_ctx->device_ctx);
+		if (ndev_ctx->vf_serial != serial)
+			continue;
+
+		ndev = hv_get_drvdata(ndev_ctx->device_ctx);
+		if (ndev->addr_len != vf_netdev->addr_len ||
+		    memcmp(ndev->perm_addr, vf_netdev->perm_addr,
+			   ndev->addr_len) != 0)
+			continue;
+
+		return ndev;
+
+	}
+
+	/* Fallback path to check synthetic vf with help of mac addr.
+	 * Because this function can be called before vf_netdev is
+	 * initialized (NETDEV_POST_INIT) when its perm_addr has not been copied
+	 * from dev_addr, also try to match to its dev_addr.
+	 * Note: On Hyper-V and Azure, it's not possible to set a MAC address
+	 * on a VF that matches to the MAC of a unrelated NETVSC device.
+	 */
+	list_for_each_entry(ndev_ctx, &netvsc_dev_list, list) {
+		ndev = hv_get_drvdata(ndev_ctx->device_ctx);
+		if (ether_addr_equal(vf_netdev->perm_addr, ndev->perm_addr) ||
+		    ether_addr_equal(vf_netdev->dev_addr, ndev->perm_addr))
+			return ndev;
 	}
 
 	netdev_notice(vf_netdev,
@@ -2160,7 +2217,20 @@
 	return NULL;
 }
 
-static int netvsc_register_vf(struct net_device *vf_netdev)
+static int netvsc_prepare_bonding(struct net_device *vf_netdev)
+{
+	struct net_device *ndev;
+
+	ndev = get_netvsc_byslot(vf_netdev);
+	if (!ndev)
+		return NOTIFY_DONE;
+
+	/* set slave flag before open to prevent IPv6 addrconf */
+	vf_netdev->flags |= IFF_SLAVE;
+	return NOTIFY_DONE;
+}
+
+static int netvsc_register_vf(struct net_device *vf_netdev, int context)
 {
 	struct net_device_context *net_device_ctx;
 	struct netvsc_device *netvsc_dev;
@@ -2199,7 +2269,7 @@
 
 	netdev_info(ndev, "VF registering: %s\n", vf_netdev->name);
 
-	if (netvsc_vf_join(vf_netdev, ndev) != 0)
+	if (netvsc_vf_join(vf_netdev, ndev, context) != 0)
 		return NOTIFY_DONE;
 
 	dev_hold(vf_netdev);
@@ -2228,6 +2298,11 @@
 	if (!netvsc_dev)
 		return NOTIFY_DONE;
 
+	if (vf_is_up && !net_device_ctx->vf_alloc) {
+		netdev_info(ndev, "Waiting for the VF association from host\n");
+		wait_for_completion(&net_device_ctx->vf_add);
+	}
+
 	netvsc_switch_datapath(ndev, vf_is_up);
 	netdev_info(ndev, "Data path switched %s VF: %s\n",
 		    vf_is_up ? "to" : "from", vf_netdev->name);
@@ -2249,6 +2324,7 @@
 
 	netdev_info(ndev, "VF unregistering: %s\n", vf_netdev->name);
 
+	reinit_completion(&net_device_ctx->vf_add);
 	netdev_rx_handler_unregister(vf_netdev);
 	netdev_upper_dev_unlink(vf_netdev, ndev);
 	RCU_INIT_POINTER(net_device_ctx->vf_netdev, NULL);
@@ -2257,10 +2333,31 @@
 	return NOTIFY_OK;
 }
 
+static int check_dev_is_matching_vf(struct net_device *event_ndev)
+{
+	/* Skip NetVSC interfaces */
+	if (event_ndev->netdev_ops == &device_ops)
+		return -ENODEV;
+
+	/* Avoid non-Ethernet type devices */
+	if (event_ndev->type != ARPHRD_ETHER)
+		return -ENODEV;
+
+	/* Avoid Vlan dev with same MAC registering as VF */
+	if (is_vlan_dev(event_ndev))
+		return -ENODEV;
+
+	/* Avoid Bonding master dev with same MAC registering as VF */
+	if (netif_is_bond_master(event_ndev))
+		return -ENODEV;
+
+	return 0;
+}
+
 static int netvsc_probe(struct hv_device *dev,
 			const struct hv_vmbus_device_id *dev_id)
 {
-	struct net_device *net = NULL;
+	struct net_device *net = NULL, *vf_netdev;
 	struct net_device_context *net_device_ctx;
 	struct netvsc_device_info *device_info = NULL;
 	struct netvsc_device *nvdev;
@@ -2286,6 +2383,7 @@
 
 	INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_link_change);
 
+	init_completion(&net_device_ctx->vf_add);
 	spin_lock_init(&net_device_ctx->lock);
 	INIT_LIST_HEAD(&net_device_ctx->reconfig_events);
 	INIT_DELAYED_WORK(&net_device_ctx->vf_takeover, netvsc_vf_setup);
@@ -2351,6 +2449,8 @@
 	else
 		net->max_mtu = ETH_DATA_LEN;
 
+	nvdev->tx_disable = false;
+
 	ret = register_netdevice(net);
 	if (ret != 0) {
 		pr_err("Unable to register netdev.\n");
@@ -2358,6 +2458,30 @@
 	}
 
 	list_add(&net_device_ctx->list, &netvsc_dev_list);
+
+	/* When the hv_netvsc driver is unloaded and reloaded, the
+	 * NET_DEVICE_REGISTER for the vf device is replayed before probe
+	 * is complete. This is because register_netdevice_notifier() gets
+	 * registered before vmbus_driver_register() so that callback func
+	 * is set before probe and we don't miss events like NETDEV_POST_INIT
+	 * So, in this section we try to register the matching vf device that
+	 * is present as a netdevice, knowing that its register call is not
+	 * processed in the netvsc_netdev_notifier(as probing is progress and
+	 * get_netvsc_byslot fails).
+	 */
+	for_each_netdev(dev_net(net), vf_netdev) {
+		ret = check_dev_is_matching_vf(vf_netdev);
+		if (ret != 0)
+			continue;
+
+		if (net != get_netvsc_byslot(vf_netdev))
+			continue;
+
+		netvsc_prepare_bonding(vf_netdev);
+		netvsc_register_vf(vf_netdev, VF_REG_IN_PROBE);
+		__netvsc_vf_setup(net, vf_netdev);
+		break;
+	}
 	rtnl_unlock();
 
 	kfree(device_info);
@@ -2440,6 +2564,31 @@
 	},
 };
 
+/* Set VF's namespace same as the synthetic NIC */
+static void netvsc_event_set_vf_ns(struct net_device *ndev)
+{
+	struct net_device_context *ndev_ctx = netdev_priv(ndev);
+	struct net_device *vf_netdev;
+	int ret;
+
+	vf_netdev = rtnl_dereference(ndev_ctx->vf_netdev);
+	if (!vf_netdev)
+		return;
+
+	if (!net_eq(dev_net(ndev), dev_net(vf_netdev))) {
+		ret = dev_change_net_namespace(vf_netdev, dev_net(ndev),
+					       "eth%d");
+		if (ret)
+			netdev_err(vf_netdev,
+				   "Cannot move to same namespace as %s: %d\n",
+				   ndev->name, ret);
+		else
+			netdev_info(vf_netdev,
+				    "Moved VF to namespace with: %s\n",
+				    ndev->name);
+	}
+}
+
 /*
  * On Hyper-V, every VF interface is matched with a corresponding
  * synthetic interface. The synthetic interface is presented first
@@ -2450,27 +2599,22 @@
 			       unsigned long event, void *ptr)
 {
 	struct net_device *event_dev = netdev_notifier_info_to_dev(ptr);
+	int ret = 0;
 
-	/* Skip our own events */
-	if (event_dev->netdev_ops == &device_ops)
-		return NOTIFY_DONE;
-
-	/* Avoid non-Ethernet type devices */
-	if (event_dev->type != ARPHRD_ETHER)
-		return NOTIFY_DONE;
-
-	/* Avoid Vlan dev with same MAC registering as VF */
-	if (is_vlan_dev(event_dev))
+	if (event_dev->netdev_ops == &device_ops && event == NETDEV_REGISTER) {
+		netvsc_event_set_vf_ns(event_dev);
 		return NOTIFY_DONE;
+	}
 
-	/* Avoid Bonding master dev with same MAC registering as VF */
-	if ((event_dev->priv_flags & IFF_BONDING) &&
-	    (event_dev->flags & IFF_MASTER))
+	ret = check_dev_is_matching_vf(event_dev);
+	if (ret != 0)
 		return NOTIFY_DONE;
 
 	switch (event) {
+	case NETDEV_POST_INIT:
+		return netvsc_prepare_bonding(event_dev);
 	case NETDEV_REGISTER:
-		return netvsc_register_vf(event_dev);
+		return netvsc_register_vf(event_dev, VF_REG_IN_NOTIFIER);
 	case NETDEV_UNREGISTER:
 		return netvsc_unregister_vf(event_dev);
 	case NETDEV_UP:
@@ -2502,12 +2646,17 @@
 	}
 	netvsc_ring_bytes = ring_size * PAGE_SIZE;
 
+	register_netdevice_notifier(&netvsc_netdev_notifier);
+
 	ret = vmbus_driver_register(&netvsc_drv);
 	if (ret)
-		return ret;
+		goto err_vmbus_reg;
 
-	register_netdevice_notifier(&netvsc_netdev_notifier);
 	return 0;
+
+err_vmbus_reg:
+	unregister_netdevice_notifier(&netvsc_netdev_notifier);
+	return ret;
 }
 
 MODULE_LICENSE("GPL");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/hyperv/rndis_filter.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/hyperv/rndis_filter.c
@@ -767,6 +767,7 @@
 				   const u8 *rss_key, u16 flag)
 {
 	struct net_device *ndev = rdev->ndev;
+	struct net_device_context *ndc = netdev_priv(ndev);
 	struct rndis_request *request;
 	struct rndis_set_request *set;
 	struct rndis_set_complete *set_complete;
@@ -806,7 +807,7 @@
 	/* Set indirection table entries */
 	itab = (u32 *)(rssp + 1);
 	for (i = 0; i < ITAB_NUM; i++)
-		itab[i] = rdev->rx_table[i];
+		itab[i] = ndc->rx_table[i];
 
 	/* Set hask key values */
 	keyp = (u8 *)((unsigned long)rssp + rssp->hashkey_offset);
@@ -1165,6 +1166,9 @@
 	wait_event(nvdev->subchan_open,
 		   atomic_read(&nvdev->open_chn) == nvdev->num_chn);
 
+	for (i = 0; i < VRSS_SEND_TAB_SIZE; i++)
+		ndev_ctx->tx_table[i] = i % nvdev->num_chn;
+
 	/* ignore failures from setting rss parameters, still have channels */
 	if (dev_info)
 		rndis_filter_set_rss_param(rdev, dev_info->rss_key);
@@ -1174,9 +1178,6 @@
 	netif_set_real_num_tx_queues(ndev, nvdev->num_chn);
 	netif_set_real_num_rx_queues(ndev, nvdev->num_chn);
 
-	for (i = 0; i < VRSS_SEND_TAB_SIZE; i++)
-		ndev_ctx->tx_table[i] = i % nvdev->num_chn;
-
 	return 0;
 }
 
@@ -1305,6 +1306,7 @@
 				      struct netvsc_device_info *device_info)
 {
 	struct net_device *net = hv_get_drvdata(dev);
+	struct net_device_context *ndc = netdev_priv(net);
 	struct netvsc_device *net_device;
 	struct rndis_device *rndis_device;
 	struct ndis_recv_scale_cap rsscap;
@@ -1391,9 +1393,11 @@
 	/* We will use the given number of channels if available. */
 	net_device->num_chn = min(net_device->max_chn, device_info->num_chn);
 
-	for (i = 0; i < ITAB_NUM; i++)
-		rndis_device->rx_table[i] = ethtool_rxfh_indir_default(
+	if (!netif_is_rxfh_configured(net)) {
+		for (i = 0; i < ITAB_NUM; i++)
+			ndc->rx_table[i] = ethtool_rxfh_indir_default(
 						i, net_device->num_chn);
+	}
 
 	atomic_set(&net_device->open_chn, 1);
 	vmbus_set_sc_create_callback(dev->channel, netvsc_sc_open);
@@ -1432,8 +1436,6 @@
 	/* Halt and release the rndis device */
 	rndis_filter_halt_device(net_dev, rndis_dev);
 
-	net_dev->extension = NULL;
-
 	netvsc_device_remove(dev);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ieee802154/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ieee802154/Kconfig
@@ -74,9 +74,9 @@
 	  The module will be called 'atusb'.
 
 config IEEE802154_ADF7242
-       tristate "ADF7242 transceiver driver"
-       depends on IEEE802154_DRIVERS && MAC802154
-       depends on SPI
+	tristate "ADF7242 transceiver driver"
+	depends on IEEE802154_DRIVERS && MAC802154
+	depends on SPI
 	---help---
 	  Say Y here to enable the ADF7242 SPI 802.15.4 wireless
 	  controller.
@@ -107,9 +107,10 @@
 	  management entities.
 
 config IEEE802154_MCR20A
-       tristate "MCR20A transceiver driver"
-       depends on IEEE802154_DRIVERS && MAC802154
-       depends on SPI
+	tristate "MCR20A transceiver driver"
+	select REGMAP_SPI
+	depends on IEEE802154_DRIVERS && MAC802154
+	depends on SPI
 	---help---
 	  Say Y here to enable the MCR20A SPI 802.15.4 wireless
 	  controller.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ieee802154/adf7242.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ieee802154/adf7242.c
@@ -882,7 +882,9 @@
 	int ret;
 	u8 lqi, len_u8, *data;
 
-	adf7242_read_reg(lp, 0, &len_u8);
+	ret = adf7242_read_reg(lp, 0, &len_u8);
+	if (ret)
+		return ret;
 
 	len = len_u8;
 
@@ -1160,9 +1162,10 @@
 
 static void adf7242_debugfs_init(struct adf7242_local *lp)
 {
-	char debugfs_dir_name[DNAME_INLINE_LEN + 1] = "adf7242-";
+	char debugfs_dir_name[DNAME_INLINE_LEN + 1];
 
-	strncat(debugfs_dir_name, dev_name(&lp->spi->dev), DNAME_INLINE_LEN);
+	snprintf(debugfs_dir_name, sizeof(debugfs_dir_name),
+		 "adf7242-%s", dev_name(&lp->spi->dev));
 
 	lp->debugfs_root = debugfs_create_dir(debugfs_dir_name, NULL);
 
@@ -1262,7 +1265,7 @@
 					     WQ_MEM_RECLAIM);
 	if (unlikely(!lp->wqueue)) {
 		ret = -ENOMEM;
-		goto err_hw_init;
+		goto err_alloc_wq;
 	}
 
 	ret = adf7242_hw_init(lp);
@@ -1294,6 +1297,8 @@
 	return ret;
 
 err_hw_init:
+	destroy_workqueue(lp->wqueue);
+err_alloc_wq:
 	mutex_destroy(&lp->bmux);
 	ieee802154_free_hw(lp->hw);
 
@@ -1306,10 +1311,11 @@
 
 	debugfs_remove_recursive(lp->debugfs_root);
 
+	ieee802154_unregister_hw(lp->hw);
+
 	cancel_delayed_work_sync(&lp->work);
 	destroy_workqueue(lp->wqueue);
 
-	ieee802154_unregister_hw(lp->hw);
 	mutex_destroy(&lp->bmux);
 	ieee802154_free_hw(lp->hw);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ieee802154/at86rf230.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ieee802154/at86rf230.c
@@ -100,6 +100,7 @@
 	unsigned long cal_timeout;
 	bool is_tx;
 	bool is_tx_from_off;
+	bool was_tx;
 	u8 tx_retry;
 	struct sk_buff *tx_skb;
 	struct at86rf230_state_change tx;
@@ -343,7 +344,11 @@
 	if (ctx->free)
 		kfree(ctx);
 
-	ieee802154_wake_queue(lp->hw);
+	if (lp->was_tx) {
+		lp->was_tx = 0;
+		dev_kfree_skb_any(lp->tx_skb);
+		ieee802154_wake_queue(lp->hw);
+	}
 }
 
 static void
@@ -352,7 +357,11 @@
 	struct at86rf230_state_change *ctx = context;
 	struct at86rf230_local *lp = ctx->lp;
 
-	lp->is_tx = 0;
+	if (lp->is_tx) {
+		lp->was_tx = 1;
+		lp->is_tx = 0;
+	}
+
 	at86rf230_async_state_change(lp, ctx, STATE_RX_AACK_ON,
 				     at86rf230_async_error_recover_complete);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ieee802154/atusb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ieee802154/atusb.c
@@ -93,7 +93,9 @@
 
 	ret = usb_control_msg(usb_dev, pipe, request, requesttype,
 			      value, index, data, size, timeout);
-	if (ret < 0) {
+	if (ret < size) {
+		ret = ret < 0 ? ret : -ENODATA;
+
 		atusb->err = ret;
 		dev_err(&usb_dev->dev,
 			"%s: req 0x%02x val 0x%x idx 0x%x, error %d\n",
@@ -365,6 +367,7 @@
 			return -ENOMEM;
 		}
 		usb_anchor_urb(urb, &atusb->idle_urbs);
+		usb_free_urb(urb);
 		n--;
 	}
 	return 0;
@@ -860,9 +863,9 @@
 	if (!build)
 		return -ENOMEM;
 
-	ret = atusb_control_msg(atusb, usb_rcvctrlpipe(usb_dev, 0),
-				ATUSB_BUILD, ATUSB_REQ_FROM_DEV, 0, 0,
-				build, ATUSB_BUILD_SIZE, 1000);
+	/* We cannot call atusb_control_msg() here, since this request may read various length data */
+	ret = usb_control_msg(atusb->usb_dev, usb_rcvctrlpipe(usb_dev, 0), ATUSB_BUILD,
+			      ATUSB_REQ_FROM_DEV, 0, 0, build, ATUSB_BUILD_SIZE, 1000);
 	if (ret >= 0) {
 		build[ret] = 0;
 		dev_info(&usb_dev->dev, "Firmware: build %s\n", build);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ieee802154/ca8210.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ieee802154/ca8210.c
@@ -926,7 +926,7 @@
 
 	dev_dbg(&spi->dev, "%s called\n", __func__);
 
-	cas_ctl = kmalloc(sizeof(*cas_ctl), GFP_ATOMIC);
+	cas_ctl = kzalloc(sizeof(*cas_ctl), GFP_ATOMIC);
 	if (!cas_ctl)
 		return -ENOMEM;
 
@@ -1770,6 +1770,7 @@
 			status
 		);
 		if (status != MAC_TRANSACTION_OVERFLOW) {
+			dev_kfree_skb_any(priv->tx_skb);
 			ieee802154_wake_queue(priv->hw);
 			return 0;
 		}
@@ -1943,10 +1944,9 @@
 	struct ca8210_priv  *priv
 )
 {
-	int status;
 	struct ieee802154_hdr header = { };
 	struct secspec secspec;
-	unsigned int mac_len;
+	int mac_len, status;
 
 	dev_dbg(&priv->spi->dev, "%s called\n", __func__);
 
@@ -1954,6 +1954,8 @@
 	 * packet
 	 */
 	mac_len = ieee802154_hdr_peek_addrs(skb, &header);
+	if (mac_len < 0)
+		return mac_len;
 
 	secspec.security_level = header.sec.level;
 	secspec.key_id_mode = header.sec.key_id_mode;
@@ -2780,7 +2782,6 @@
 	struct device_node *np = spi->dev.of_node;
 	struct ca8210_priv *priv = spi_get_drvdata(spi);
 	struct ca8210_platform_data *pdata = spi->dev.platform_data;
-	int ret = 0;
 
 	if (!np)
 		return -EFAULT;
@@ -2797,18 +2798,8 @@
 		dev_crit(&spi->dev, "Failed to register external clk\n");
 		return PTR_ERR(priv->clk);
 	}
-	ret = of_clk_add_provider(np, of_clk_src_simple_get, priv->clk);
-	if (ret) {
-		clk_unregister(priv->clk);
-		dev_crit(
-			&spi->dev,
-			"Failed to register external clock as clock provider\n"
-		);
-	} else {
-		dev_info(&spi->dev, "External clock set as clock provider\n");
-	}
 
-	return ret;
+	return of_clk_add_provider(np, of_clk_src_simple_get, priv->clk);
 }
 
 /**
@@ -2820,8 +2811,8 @@
 {
 	struct ca8210_priv *priv = spi_get_drvdata(spi);
 
-	if (!priv->clk)
-		return
+	if (IS_ERR_OR_NULL(priv->clk))
+		return;
 
 	of_clk_del_provider(spi->dev.of_node);
 	clk_unregister(priv->clk);
@@ -2924,6 +2915,7 @@
 	);
 	if (!priv->irq_workqueue) {
 		dev_crit(&priv->spi->dev, "alloc of irq_workqueue failed!\n");
+		destroy_workqueue(priv->mlme_workqueue);
 		return -ENOMEM;
 	}
 
@@ -2974,8 +2966,8 @@
 	ca8210_hw->phy->cca.opt = NL802154_CCA_OPT_ENERGY_CARRIER_AND;
 	ca8210_hw->phy->cca_ed_level = -9800;
 	ca8210_hw->phy->symbol_duration = 16;
-	ca8210_hw->phy->lifs_period = 40;
-	ca8210_hw->phy->sifs_period = 12;
+	ca8210_hw->phy->lifs_period = 40 * ca8210_hw->phy->symbol_duration;
+	ca8210_hw->phy->sifs_period = 12 * ca8210_hw->phy->symbol_duration;
 	ca8210_hw->flags =
 		IEEE802154_HW_AFILT |
 		IEEE802154_HW_OMIT_CKSUM |
@@ -3132,7 +3124,11 @@
 	spi_set_drvdata(priv->spi, priv);
 	if (IS_ENABLED(CONFIG_IEEE802154_CA8210_DEBUGFS)) {
 		cascoda_api_upstream = ca8210_test_int_driver_write;
-		ca8210_test_interface_init(priv);
+		ret = ca8210_test_interface_init(priv);
+		if (ret) {
+			dev_crit(&spi_device->dev, "ca8210_test_interface_init failed\n");
+			goto error;
+		}
 	} else {
 		cascoda_api_upstream = NULL;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ieee802154/cc2520.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ieee802154/cc2520.c
@@ -507,6 +507,7 @@
 		goto err_tx;
 
 	if (status & CC2520_STATUS_TX_UNDERFLOW) {
+		rc = -EINVAL;
 		dev_err(&priv->spi->dev, "cc2520 tx underflow exception\n");
 		goto err_tx;
 	}
@@ -972,7 +973,7 @@
 
 		if (timeout-- <= 0) {
 			dev_err(&priv->spi->dev, "oscillator start failed!\n");
-			return ret;
+			return -ETIMEDOUT;
 		}
 		udelay(1);
 	} while (!(status & CC2520_STATUS_XOSC32M_STABLE));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ieee802154/mac802154_hwsim.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ieee802154/mac802154_hwsim.c
@@ -418,7 +418,7 @@
 	struct hwsim_edge *e;
 	u32 v0, v1;
 
-	if (!info->attrs[MAC802154_HWSIM_ATTR_RADIO_ID] &&
+	if (!info->attrs[MAC802154_HWSIM_ATTR_RADIO_ID] ||
 	    !info->attrs[MAC802154_HWSIM_ATTR_RADIO_EDGE])
 		return -EINVAL;
 
@@ -480,7 +480,7 @@
 	struct hwsim_edge *e;
 	u32 v0, v1;
 
-	if (!info->attrs[MAC802154_HWSIM_ATTR_RADIO_ID] &&
+	if (!info->attrs[MAC802154_HWSIM_ATTR_RADIO_ID] ||
 	    !info->attrs[MAC802154_HWSIM_ATTR_RADIO_EDGE])
 		return -EINVAL;
 
@@ -522,20 +522,20 @@
 static int hwsim_set_edge_lqi(struct sk_buff *msg, struct genl_info *info)
 {
 	struct nlattr *edge_attrs[MAC802154_HWSIM_EDGE_ATTR_MAX + 1];
-	struct hwsim_edge_info *einfo;
+	struct hwsim_edge_info *einfo, *einfo_old;
 	struct hwsim_phy *phy_v0;
 	struct hwsim_edge *e;
 	u32 v0, v1;
 	u8 lqi;
 
-	if (!info->attrs[MAC802154_HWSIM_ATTR_RADIO_ID] &&
+	if (!info->attrs[MAC802154_HWSIM_ATTR_RADIO_ID] ||
 	    !info->attrs[MAC802154_HWSIM_ATTR_RADIO_EDGE])
 		return -EINVAL;
 
 	if (nla_parse_nested_deprecated(edge_attrs, MAC802154_HWSIM_EDGE_ATTR_MAX, info->attrs[MAC802154_HWSIM_ATTR_RADIO_EDGE], hwsim_edge_policy, NULL))
 		return -EINVAL;
 
-	if (!edge_attrs[MAC802154_HWSIM_EDGE_ATTR_ENDPOINT_ID] &&
+	if (!edge_attrs[MAC802154_HWSIM_EDGE_ATTR_ENDPOINT_ID] ||
 	    !edge_attrs[MAC802154_HWSIM_EDGE_ATTR_LQI])
 		return -EINVAL;
 
@@ -560,8 +560,10 @@
 	list_for_each_entry_rcu(e, &phy_v0->edges, list) {
 		if (e->endpoint->idx == v1) {
 			einfo->lqi = lqi;
-			rcu_assign_pointer(e->info, einfo);
+			einfo_old = rcu_replace_pointer(e->info, einfo,
+							lockdep_is_held(&hwsim_phys_lock));
 			rcu_read_unlock();
+			kfree_rcu(einfo_old, rcu);
 			mutex_unlock(&hwsim_phys_lock);
 			return 0;
 		}
@@ -715,6 +717,8 @@
 
 	return 0;
 
+sub_fail:
+	hwsim_edge_unsubscribe_me(phy);
 me_fail:
 	rcu_read_lock();
 	list_for_each_entry_rcu(e, &phy->edges, list) {
@@ -722,8 +726,6 @@
 		hwsim_free_edge(e);
 	}
 	rcu_read_unlock();
-sub_fail:
-	hwsim_edge_unsubscribe_me(phy);
 	return -ENOMEM;
 }
 
@@ -786,6 +788,7 @@
 		goto err_pib;
 	}
 
+	pib->channel = 13;
 	rcu_assign_pointer(phy->pib, pib);
 	phy->idx = idx;
 	INIT_LIST_HEAD(&phy->edges);
@@ -824,12 +827,17 @@
 static void hwsim_del(struct hwsim_phy *phy)
 {
 	struct hwsim_pib *pib;
+	struct hwsim_edge *e;
 
 	hwsim_edge_unsubscribe_me(phy);
 
 	list_del(&phy->list);
 
 	rcu_read_lock();
+	list_for_each_entry_rcu(e, &phy->edges, list) {
+		list_del_rcu(&e->list);
+		hwsim_free_edge(e);
+	}
 	pib = rcu_dereference(phy->pib);
 	rcu_read_unlock();
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ieee802154/mcr20a.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ieee802154/mcr20a.c
@@ -976,8 +976,8 @@
 	dev_dbg(printdev(lp), "%s\n", __func__);
 
 	phy->symbol_duration = 16;
-	phy->lifs_period = 40;
-	phy->sifs_period = 12;
+	phy->lifs_period = 40 * phy->symbol_duration;
+	phy->sifs_period = 12 * phy->symbol_duration;
 
 	hw->flags = IEEE802154_HW_TX_OMIT_CKSUM |
 			IEEE802154_HW_AFILT |
@@ -1311,16 +1311,13 @@
 		irq_type = IRQF_TRIGGER_FALLING;
 
 	ret = devm_request_irq(&spi->dev, spi->irq, mcr20a_irq_isr,
-			       irq_type, dev_name(&spi->dev), lp);
+			       irq_type | IRQF_NO_AUTOEN, dev_name(&spi->dev), lp);
 	if (ret) {
 		dev_err(&spi->dev, "could not request_irq for mcr20a\n");
 		ret = -ENODEV;
 		goto free_dev;
 	}
 
-	/* disable_irq by default and wait for starting hardware */
-	disable_irq(spi->irq);
-
 	ret = ieee802154_register_hw(hw);
 	if (ret) {
 		dev_crit(&spi->dev, "ieee802154_register_hw failed\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ifb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ifb.c
@@ -75,7 +75,7 @@
 	}
 
 	while ((skb = __skb_dequeue(&txp->tq)) != NULL) {
-		skb->tc_redirected = 0;
+		skb->redirected = 0;
 		skb->tc_skip_classify = 1;
 
 		u64_stats_update_begin(&txp->tsync);
@@ -96,7 +96,7 @@
 		rcu_read_unlock();
 		skb->skb_iif = txp->dev->ifindex;
 
-		if (!skb->tc_from_ingress) {
+		if (!skb->from_ingress) {
 			dev_queue_xmit(skb);
 		} else {
 			skb_pull_rcsum(skb, skb->mac_len);
@@ -243,7 +243,7 @@
 	txp->rx_bytes += skb->len;
 	u64_stats_update_end(&txp->rsync);
 
-	if (!skb->tc_redirected || !skb->skb_iif) {
+	if (!skb->redirected || !skb->skb_iif) {
 		dev_kfree_skb(skb);
 		dev->stats.rx_dropped++;
 		return NETDEV_TX_OK;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ipvlan/ipvlan_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ipvlan/ipvlan_core.c
@@ -293,6 +293,7 @@
 		}
 		if (dev)
 			dev_put(dev);
+		cond_resched();
 	}
 }
 
@@ -411,7 +412,7 @@
 	return addr;
 }
 
-static int ipvlan_process_v4_outbound(struct sk_buff *skb)
+static noinline_for_stack int ipvlan_process_v4_outbound(struct sk_buff *skb)
 {
 	const struct iphdr *ip4h = ip_hdr(skb);
 	struct net_device *dev = skb->dev;
@@ -436,27 +437,28 @@
 		goto err;
 	}
 	skb_dst_set(skb, &rt->dst);
-	err = ip_local_out(net, skb->sk, skb);
+
+	memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
+
+	err = ip_local_out(net, NULL, skb);
 	if (unlikely(net_xmit_eval(err)))
-		dev->stats.tx_errors++;
+		DEV_STATS_INC(dev, tx_errors);
 	else
 		ret = NET_XMIT_SUCCESS;
 	goto out;
 err:
-	dev->stats.tx_errors++;
+	DEV_STATS_INC(dev, tx_errors);
 	kfree_skb(skb);
 out:
 	return ret;
 }
 
 #if IS_ENABLED(CONFIG_IPV6)
-static int ipvlan_process_v6_outbound(struct sk_buff *skb)
+
+static noinline_for_stack int
+ipvlan_route_v6_outbound(struct net_device *dev, struct sk_buff *skb)
 {
 	const struct ipv6hdr *ip6h = ipv6_hdr(skb);
-	struct net_device *dev = skb->dev;
-	struct net *net = dev_net(dev);
-	struct dst_entry *dst;
-	int err, ret = NET_XMIT_DROP;
 	struct flowi6 fl6 = {
 		.flowi6_oif = dev->ifindex,
 		.daddr = ip6h->daddr,
@@ -466,24 +468,38 @@
 		.flowi6_mark = skb->mark,
 		.flowi6_proto = ip6h->nexthdr,
 	};
+	struct dst_entry *dst;
+	int err;
 
-	dst = ip6_route_output(net, NULL, &fl6);
-	if (dst->error) {
-		ret = dst->error;
+	dst = ip6_route_output(dev_net(dev), NULL, &fl6);
+	err = dst->error;
+	if (err) {
 		dst_release(dst);
-		goto err;
+		return err;
 	}
 	skb_dst_set(skb, dst);
-	err = ip6_local_out(net, skb->sk, skb);
+	return 0;
+}
+
+static int ipvlan_process_v6_outbound(struct sk_buff *skb)
+{
+	struct net_device *dev = skb->dev;
+	int err, ret = NET_XMIT_DROP;
+
+	err = ipvlan_route_v6_outbound(dev, skb);
+	if (unlikely(err)) {
+		DEV_STATS_INC(dev, tx_errors);
+		kfree_skb(skb);
+		return err;
+	}
+
+	memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
+
+	err = ip6_local_out(dev_net(dev), NULL, skb);
 	if (unlikely(net_xmit_eval(err)))
-		dev->stats.tx_errors++;
+		DEV_STATS_INC(dev, tx_errors);
 	else
 		ret = NET_XMIT_SUCCESS;
-	goto out;
-err:
-	dev->stats.tx_errors++;
-	kfree_skb(skb);
-out:
 	return ret;
 }
 #else
@@ -495,22 +511,25 @@
 
 static int ipvlan_process_outbound(struct sk_buff *skb)
 {
-	struct ethhdr *ethh = eth_hdr(skb);
 	int ret = NET_XMIT_DROP;
 
-	/* In this mode we dont care about multicast and broadcast traffic */
-	if (is_multicast_ether_addr(ethh->h_dest)) {
-		pr_debug_ratelimited("Dropped {multi|broad}cast of type=[%x]\n",
-				     ntohs(skb->protocol));
-		kfree_skb(skb);
-		goto out;
-	}
-
 	/* The ipvlan is a pseudo-L2 device, so the packets that we receive
 	 * will have L2; which need to discarded and processed further
 	 * in the net-ns of the main-device.
 	 */
 	if (skb_mac_header_was_set(skb)) {
+		/* In this mode we dont care about
+		 * multicast and broadcast traffic */
+		struct ethhdr *ethh = eth_hdr(skb);
+
+		if (is_multicast_ether_addr(ethh->h_dest)) {
+			pr_debug_ratelimited(
+				"Dropped {multi|broad}cast of type=[%x]\n",
+				ntohs(skb->protocol));
+			kfree_skb(skb);
+			goto out;
+		}
+
 		skb_pull(skb, sizeof(*ethh));
 		skb->mac_header = (typeof(skb->mac_header))~0U;
 		skb_reset_network_header(skb);
@@ -576,7 +595,8 @@
 				consume_skb(skb);
 				return NET_XMIT_DROP;
 			}
-			return ipvlan_rcv_frame(addr, &skb, true);
+			ipvlan_rcv_frame(addr, &skb, true);
+			return NET_XMIT_SUCCESS;
 		}
 	}
 out:
@@ -587,7 +607,7 @@
 static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev)
 {
 	const struct ipvl_dev *ipvlan = netdev_priv(dev);
-	struct ethhdr *eth = eth_hdr(skb);
+	struct ethhdr *eth = skb_eth_hdr(skb);
 	struct ipvl_addr *addr;
 	void *lyr3h;
 	int addr_type;
@@ -602,7 +622,8 @@
 					consume_skb(skb);
 					return NET_XMIT_DROP;
 				}
-				return ipvlan_rcv_frame(addr, &skb, true);
+				ipvlan_rcv_frame(addr, &skb, true);
+				return NET_XMIT_SUCCESS;
 			}
 		}
 		skb = skb_share_check(skb, GFP_ATOMIC);
@@ -614,9 +635,11 @@
 		 * the skb for the main-dev. At the RX side we just return
 		 * RX_PASS for it to be processed further on the stack.
 		 */
-		return dev_forward_skb(ipvlan->phy_dev, skb);
+		dev_forward_skb(ipvlan->phy_dev, skb);
+		return NET_XMIT_SUCCESS;
 
 	} else if (is_multicast_ether_addr(eth->h_dest)) {
+		skb_reset_mac_header(skb);
 		ipvlan_skb_crossing_ns(skb, NULL);
 		ipvlan_multicast_enqueue(ipvlan->port, skb, true);
 		return NET_XMIT_SUCCESS;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ipvlan/ipvlan_l3s.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ipvlan/ipvlan_l3s.c
@@ -101,6 +101,11 @@
 		goto out;
 
 	skb->dev = addr->master->dev;
+	skb->skb_iif = skb->dev->ifindex;
+#if IS_ENABLED(CONFIG_IPV6)
+	if (addr->atype == IPVL_IPV6)
+		IP6CB(skb)->iif = skb->dev->ifindex;
+#endif
 	len = skb->len + ETH_HLEN;
 	ipvlan_count_rx(addr->master, len, true, false);
 out:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ipvlan/ipvlan_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ipvlan/ipvlan_main.c
@@ -106,12 +106,21 @@
 	kfree(port);
 }
 
+#define IPVLAN_ALWAYS_ON_OFLOADS \
+	(NETIF_F_SG | NETIF_F_HW_CSUM | \
+	 NETIF_F_GSO_ROBUST | NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ENCAP_ALL)
+
+#define IPVLAN_ALWAYS_ON \
+	(IPVLAN_ALWAYS_ON_OFLOADS | NETIF_F_LLTX | NETIF_F_VLAN_CHALLENGED)
+
 #define IPVLAN_FEATURES \
-	(NETIF_F_SG | NETIF_F_CSUM_MASK | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \
+	(NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \
 	 NETIF_F_GSO | NETIF_F_TSO | NETIF_F_GSO_ROBUST | \
 	 NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_GRO | NETIF_F_RXCSUM | \
 	 NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_STAG_FILTER)
 
+	/* NETIF_F_GSO_ENCAP_ALL NETIF_F_GSO_SOFTWARE Newly added */
+
 #define IPVLAN_STATE_MASK \
 	((1<<__LINK_STATE_NOCARRIER) | (1<<__LINK_STATE_DORMANT))
 
@@ -125,7 +134,9 @@
 	dev->state = (dev->state & ~IPVLAN_STATE_MASK) |
 		     (phy_dev->state & IPVLAN_STATE_MASK);
 	dev->features = phy_dev->features & IPVLAN_FEATURES;
-	dev->features |= NETIF_F_LLTX | NETIF_F_VLAN_CHALLENGED;
+	dev->features |= IPVLAN_ALWAYS_ON;
+	dev->vlan_features = phy_dev->vlan_features & IPVLAN_FEATURES;
+	dev->vlan_features |= IPVLAN_ALWAYS_ON_OFLOADS;
 	dev->hw_enc_features |= dev->features;
 	dev->gso_max_size = phy_dev->gso_max_size;
 	dev->gso_max_segs = phy_dev->gso_max_segs;
@@ -164,7 +175,6 @@
 static int ipvlan_open(struct net_device *dev)
 {
 	struct ipvl_dev *ipvlan = netdev_priv(dev);
-	struct net_device *phy_dev = ipvlan->phy_dev;
 	struct ipvl_addr *addr;
 
 	if (ipvlan->port->mode == IPVLAN_MODE_L3 ||
@@ -178,7 +188,7 @@
 		ipvlan_ht_addr_add(ipvlan, addr);
 	rcu_read_unlock();
 
-	return dev_uc_add(phy_dev, phy_dev->dev_addr);
+	return 0;
 }
 
 static int ipvlan_stop(struct net_device *dev)
@@ -190,8 +200,6 @@
 	dev_uc_unsync(phy_dev, dev);
 	dev_mc_unsync(phy_dev, dev);
 
-	dev_uc_del(phy_dev, phy_dev->dev_addr);
-
 	rcu_read_lock();
 	list_for_each_entry_rcu(addr, &ipvlan->addrs, anode)
 		ipvlan_ht_addr_del(addr);
@@ -228,7 +236,14 @@
 {
 	struct ipvl_dev *ipvlan = netdev_priv(dev);
 
-	return features & (ipvlan->sfeatures | ~IPVLAN_FEATURES);
+	features |= NETIF_F_ALL_FOR_ALL;
+	features &= (ipvlan->sfeatures | ~IPVLAN_FEATURES);
+	features = netdev_increment_features(ipvlan->phy_dev->features,
+					     features, features);
+	features |= IPVLAN_ALWAYS_ON;
+	features &= (IPVLAN_FEATURES | IPVLAN_ALWAYS_ON);
+
+	return features;
 }
 
 static void ipvlan_change_rx_flags(struct net_device *dev, int change)
@@ -305,6 +320,7 @@
 		s->rx_dropped = rx_errs;
 		s->tx_dropped = tx_drps;
 	}
+	s->tx_errors = DEV_STATS_READ(dev, tx_errors);
 }
 
 static int ipvlan_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid)
@@ -720,7 +736,8 @@
 
 		write_pnet(&port->pnet, newnet);
 
-		ipvlan_migrate_l3s_hook(oldnet, newnet);
+		if (port->mode == IPVLAN_MODE_L3S)
+			ipvlan_migrate_l3s_hook(oldnet, newnet);
 		break;
 	}
 	case NETDEV_UNREGISTER:
@@ -735,10 +752,9 @@
 
 	case NETDEV_FEAT_CHANGE:
 		list_for_each_entry(ipvlan, &port->ipvlans, pnode) {
-			ipvlan->dev->features = dev->features & IPVLAN_FEATURES;
 			ipvlan->dev->gso_max_size = dev->gso_max_size;
 			ipvlan->dev->gso_max_segs = dev->gso_max_segs;
-			netdev_features_change(ipvlan->dev);
+			netdev_update_features(ipvlan->dev);
 		}
 		break;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ipvlan/ipvtap.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ipvlan/ipvtap.c
@@ -194,7 +194,7 @@
 	.notifier_call	= ipvtap_device_event,
 };
 
-static int ipvtap_init(void)
+static int __init ipvtap_init(void)
 {
 	int err;
 
@@ -228,7 +228,7 @@
 }
 module_init(ipvtap_init);
 
-static void ipvtap_exit(void)
+static void __exit ipvtap_exit(void)
 {
 	rtnl_link_unregister(&ipvtap_link_ops);
 	unregister_netdevice_notifier(&ipvtap_notifier_block);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/loopback.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/loopback.c
@@ -206,7 +206,7 @@
 	int err;
 
 	err = -ENOMEM;
-	dev = alloc_netdev(0, "lo", NET_NAME_UNKNOWN, loopback_setup);
+	dev = alloc_netdev(0, "lo", NET_NAME_PREDICTABLE, loopback_setup);
 	if (!dev)
 		goto out;
 
@@ -241,8 +241,22 @@
 	return NETDEV_TX_OK;
 }
 
+static int blackhole_neigh_output(struct neighbour *n, struct sk_buff *skb)
+{
+	kfree_skb(skb);
+	return 0;
+}
+
+static int blackhole_neigh_construct(struct net_device *dev,
+				     struct neighbour *n)
+{
+	n->output = blackhole_neigh_output;
+	return 0;
+}
+
 static const struct net_device_ops blackhole_netdev_ops = {
 	.ndo_start_xmit = blackhole_netdev_xmit,
+	.ndo_neigh_construct = blackhole_neigh_construct,
 };
 
 /* This is a dst-dummy device used specifically for invalidated
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/macsec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/macsec.c
@@ -16,6 +16,7 @@
 #include <net/genetlink.h>
 #include <net/sock.h>
 #include <net/gro_cells.h>
+#include <linux/if_arp.h>
 
 #include <uapi/linux/if_macsec.h>
 
@@ -560,18 +561,28 @@
 	skb->protocol = eth_hdr(skb)->h_proto;
 }
 
+static unsigned int macsec_msdu_len(struct sk_buff *skb)
+{
+	struct macsec_dev *macsec = macsec_priv(skb->dev);
+	struct macsec_secy *secy = &macsec->secy;
+	bool sci_present = macsec_skb_cb(skb)->has_sci;
+
+	return skb->len - macsec_hdr_len(sci_present) - secy->icv_len;
+}
+
 static void macsec_count_tx(struct sk_buff *skb, struct macsec_tx_sc *tx_sc,
 			    struct macsec_tx_sa *tx_sa)
 {
+	unsigned int msdu_len = macsec_msdu_len(skb);
 	struct pcpu_tx_sc_stats *txsc_stats = this_cpu_ptr(tx_sc->stats);
 
 	u64_stats_update_begin(&txsc_stats->syncp);
 	if (tx_sc->encrypt) {
-		txsc_stats->stats.OutOctetsEncrypted += skb->len;
+		txsc_stats->stats.OutOctetsEncrypted += msdu_len;
 		txsc_stats->stats.OutPktsEncrypted++;
 		this_cpu_inc(tx_sa->stats->OutPktsEncrypted);
 	} else {
-		txsc_stats->stats.OutOctetsProtected += skb->len;
+		txsc_stats->stats.OutOctetsProtected += msdu_len;
 		txsc_stats->stats.OutPktsProtected++;
 		this_cpu_inc(tx_sa->stats->OutPktsProtected);
 	}
@@ -601,9 +612,10 @@
 	aead_request_free(macsec_skb_cb(skb)->req);
 
 	rcu_read_lock_bh();
-	macsec_encrypt_finish(skb, dev);
 	macsec_count_tx(skb, &macsec->secy.tx_sc, macsec_skb_cb(skb)->tx_sa);
-	len = skb->len;
+	/* packet is encrypted/protected so tx_bytes must be calculated */
+	len = macsec_msdu_len(skb) + 2 * ETH_ALEN;
+	macsec_encrypt_finish(skb, dev);
 	ret = dev_queue_xmit(skb);
 	count_tx(dev, ret, len);
 	rcu_read_unlock_bh();
@@ -759,6 +771,7 @@
 
 	macsec_skb_cb(skb)->req = req;
 	macsec_skb_cb(skb)->tx_sa = tx_sa;
+	macsec_skb_cb(skb)->has_sci = sci_present;
 	aead_request_set_callback(req, 0, macsec_encrypt_done, skb);
 
 	dev_hold(skb->dev);
@@ -799,15 +812,17 @@
 		u64_stats_update_begin(&rxsc_stats->syncp);
 		rxsc_stats->stats.InPktsLate++;
 		u64_stats_update_end(&rxsc_stats->syncp);
+		DEV_STATS_INC(secy->netdev, rx_dropped);
 		return false;
 	}
 
 	if (secy->validate_frames != MACSEC_VALIDATE_DISABLED) {
+		unsigned int msdu_len = macsec_msdu_len(skb);
 		u64_stats_update_begin(&rxsc_stats->syncp);
 		if (hdr->tci_an & MACSEC_TCI_E)
-			rxsc_stats->stats.InOctetsDecrypted += skb->len;
+			rxsc_stats->stats.InOctetsDecrypted += msdu_len;
 		else
-			rxsc_stats->stats.InOctetsValidated += skb->len;
+			rxsc_stats->stats.InOctetsValidated += msdu_len;
 		u64_stats_update_end(&rxsc_stats->syncp);
 	}
 
@@ -820,6 +835,8 @@
 			u64_stats_update_begin(&rxsc_stats->syncp);
 			rxsc_stats->stats.InPktsNotValid++;
 			u64_stats_update_end(&rxsc_stats->syncp);
+			this_cpu_inc(rx_sa->stats->InPktsNotValid);
+			DEV_STATS_INC(secy->netdev, rx_errors);
 			return false;
 		}
 
@@ -905,9 +922,9 @@
 
 	macsec_finalize_skb(skb, macsec->secy.icv_len,
 			    macsec_extra_len(macsec_skb_cb(skb)->has_sci));
+	len = skb->len;
 	macsec_reset_skb(skb, macsec->secy.netdev);
 
-	len = skb->len;
 	if (gro_cells_receive(&macsec->gro_cells, skb) == NET_RX_SUCCESS)
 		count_rx(dev, len);
 
@@ -1049,6 +1066,7 @@
 			u64_stats_update_begin(&secy_stats->syncp);
 			secy_stats->stats.InPktsNoTag++;
 			u64_stats_update_end(&secy_stats->syncp);
+			DEV_STATS_INC(macsec->secy.netdev, rx_dropped);
 			continue;
 		}
 
@@ -1079,6 +1097,7 @@
 	struct macsec_rx_sa *rx_sa;
 	struct macsec_rxh_data *rxd;
 	struct macsec_dev *macsec;
+	unsigned int len;
 	sci_t sci;
 	u32 pn;
 	bool cbit;
@@ -1159,6 +1178,7 @@
 		u64_stats_update_begin(&secy_stats->syncp);
 		secy_stats->stats.InPktsBadTag++;
 		u64_stats_update_end(&secy_stats->syncp);
+		DEV_STATS_INC(secy->netdev, rx_errors);
 		goto drop_nosa;
 	}
 
@@ -1174,6 +1194,7 @@
 			u64_stats_update_begin(&rxsc_stats->syncp);
 			rxsc_stats->stats.InPktsNotUsingSA++;
 			u64_stats_update_end(&rxsc_stats->syncp);
+			DEV_STATS_INC(secy->netdev, rx_errors);
 			goto drop_nosa;
 		}
 
@@ -1200,6 +1221,7 @@
 			u64_stats_update_begin(&rxsc_stats->syncp);
 			rxsc_stats->stats.InPktsLate++;
 			u64_stats_update_end(&rxsc_stats->syncp);
+			DEV_STATS_INC(macsec->secy.netdev, rx_dropped);
 			goto drop;
 		}
 	}
@@ -1228,6 +1250,7 @@
 deliver:
 	macsec_finalize_skb(skb, secy->icv_len,
 			    macsec_extra_len(macsec_skb_cb(skb)->has_sci));
+	len = skb->len;
 	macsec_reset_skb(skb, secy->netdev);
 
 	if (rx_sa)
@@ -1237,9 +1260,9 @@
 	skb_orphan(skb);
 	ret = gro_cells_receive(&macsec->gro_cells, skb);
 	if (ret == NET_RX_SUCCESS)
-		count_rx(dev, skb->len);
+		count_rx(dev, len);
 	else
-		macsec->secy.netdev->stats.rx_dropped++;
+		DEV_STATS_INC(macsec->secy.netdev, rx_dropped);
 
 	rcu_read_unlock();
 
@@ -1276,6 +1299,7 @@
 			u64_stats_update_begin(&secy_stats->syncp);
 			secy_stats->stats.InPktsNoSCI++;
 			u64_stats_update_end(&secy_stats->syncp);
+			DEV_STATS_INC(macsec->secy.netdev, rx_errors);
 			continue;
 		}
 
@@ -1294,7 +1318,7 @@
 			secy_stats->stats.InPktsUnknownSCI++;
 			u64_stats_update_end(&secy_stats->syncp);
 		} else {
-			macsec->secy.netdev->stats.rx_dropped++;
+			DEV_STATS_INC(macsec->secy.netdev, rx_dropped);
 		}
 	}
 
@@ -2727,21 +2751,21 @@
 
 	if (!secy->operational) {
 		kfree_skb(skb);
-		dev->stats.tx_dropped++;
+		DEV_STATS_INC(dev, tx_dropped);
 		return NETDEV_TX_OK;
 	}
 
+	len = skb->len;
 	skb = macsec_encrypt(skb, dev);
 	if (IS_ERR(skb)) {
 		if (PTR_ERR(skb) != -EINPROGRESS)
-			dev->stats.tx_dropped++;
+			DEV_STATS_INC(dev, tx_dropped);
 		return NETDEV_TX_OK;
 	}
 
 	macsec_count_tx(skb, &macsec->secy.tx_sc, macsec_skb_cb(skb)->tx_sa);
 
 	macsec_encrypt_finish(skb, dev);
-	len = skb->len;
 	ret = dev_queue_xmit(skb);
 	count_tx(dev, ret, len);
 	return ret;
@@ -2779,6 +2803,9 @@
 	if (is_zero_ether_addr(dev->broadcast))
 		memcpy(dev->broadcast, real_dev->broadcast, dev->addr_len);
 
+	/* Get macsec's reference to real_dev */
+	dev_hold(real_dev);
+
 	return 0;
 }
 
@@ -2882,6 +2909,11 @@
 	dev_uc_sync(real_dev, dev);
 }
 
+static sci_t dev_to_sci(struct net_device *dev, __be16 port)
+{
+	return make_sci(dev->dev_addr, port);
+}
+
 static int macsec_set_mac_address(struct net_device *dev, void *p)
 {
 	struct macsec_dev *macsec = macsec_priv(dev);
@@ -2903,6 +2935,7 @@
 
 out:
 	ether_addr_copy(dev->dev_addr, addr->sa_data);
+	macsec->secy.sci = dev_to_sci(dev, MACSEC_PORT_ES);
 	return 0;
 }
 
@@ -2947,8 +2980,9 @@
 		s->tx_bytes   += tmp.tx_bytes;
 	}
 
-	s->rx_dropped = dev->stats.rx_dropped;
-	s->tx_dropped = dev->stats.tx_dropped;
+	s->rx_dropped = DEV_STATS_READ(dev, rx_dropped);
+	s->tx_dropped = DEV_STATS_READ(dev, tx_dropped);
+	s->rx_errors = DEV_STATS_READ(dev, rx_errors);
 }
 
 static int macsec_get_iflink(const struct net_device *dev)
@@ -2977,6 +3011,7 @@
 
 static const struct nla_policy macsec_rtnl_policy[IFLA_MACSEC_MAX + 1] = {
 	[IFLA_MACSEC_SCI] = { .type = NLA_U64 },
+	[IFLA_MACSEC_PORT] = { .type = NLA_U16 },
 	[IFLA_MACSEC_ICV_LEN] = { .type = NLA_U8 },
 	[IFLA_MACSEC_CIPHER_SUITE] = { .type = NLA_U64 },
 	[IFLA_MACSEC_WINDOW] = { .type = NLA_U32 },
@@ -2997,6 +3032,8 @@
 	free_percpu(macsec->stats);
 	free_percpu(macsec->secy.tx_sc.stats);
 
+	/* Get rid of the macsec's reference to real_dev */
+	dev_put(macsec->real_dev);
 }
 
 static void macsec_setup(struct net_device *dev)
@@ -3176,11 +3213,6 @@
 	return false;
 }
 
-static sci_t dev_to_sci(struct net_device *dev, __be16 port)
-{
-	return make_sci(dev->dev_addr, port);
-}
-
 static int macsec_add_dev(struct net_device *dev, sci_t sci, u8 icv_len)
 {
 	struct macsec_dev *macsec = macsec_priv(dev);
@@ -3223,25 +3255,40 @@
 			  struct netlink_ext_ack *extack)
 {
 	struct macsec_dev *macsec = macsec_priv(dev);
+	rx_handler_func_t *rx_handler;
+	u8 icv_len = DEFAULT_ICV_LEN;
 	struct net_device *real_dev;
-	int err;
+	int err, mtu;
 	sci_t sci;
-	u8 icv_len = DEFAULT_ICV_LEN;
-	rx_handler_func_t *rx_handler;
 
 	if (!tb[IFLA_LINK])
 		return -EINVAL;
 	real_dev = __dev_get_by_index(net, nla_get_u32(tb[IFLA_LINK]));
 	if (!real_dev)
 		return -ENODEV;
+	if (real_dev->type != ARPHRD_ETHER)
+		return -EINVAL;
 
 	dev->priv_flags |= IFF_MACSEC;
 
 	macsec->real_dev = real_dev;
 
+	/* send_sci must be set to true when transmit sci explicitly is set */
+	if ((data && data[IFLA_MACSEC_SCI]) &&
+	    (data && data[IFLA_MACSEC_INC_SCI])) {
+		u8 send_sci = !!nla_get_u8(data[IFLA_MACSEC_INC_SCI]);
+
+		if (!send_sci)
+			return -EINVAL;
+	}
+
 	if (data && data[IFLA_MACSEC_ICV_LEN])
 		icv_len = nla_get_u8(data[IFLA_MACSEC_ICV_LEN]);
-	dev->mtu = real_dev->mtu - icv_len - macsec_extra_len(true);
+	mtu = real_dev->mtu - icv_len - macsec_extra_len(true);
+	if (mtu < 0)
+		dev->mtu = 0;
+	else
+		dev->mtu = mtu;
 
 	rx_handler = rtnl_dereference(real_dev->rx_handler);
 	if (rx_handler && rx_handler != macsec_handle_frame)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/macvlan.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/macvlan.c
@@ -138,7 +138,7 @@
 	u32 idx = macvlan_eth_hash(addr);
 	struct hlist_head *h = &vlan->port->vlan_source_hash[idx];
 
-	hlist_for_each_entry_rcu(entry, h, hlist) {
+	hlist_for_each_entry_rcu(entry, h, hlist, lockdep_rtnl_is_held()) {
 		if (ether_addr_equal_64bits(entry->addr, addr) &&
 		    entry->vlan == vlan)
 			return entry;
@@ -334,6 +334,8 @@
 		if (src)
 			dev_put(src->dev);
 		consume_skb(skb);
+
+		cond_resched();
 	}
 }
 
@@ -359,10 +361,11 @@
 	}
 	spin_unlock(&port->bc_queue.lock);
 
+	schedule_work(&port->bc_work);
+
 	if (err)
 		goto free_nskb;
 
-	schedule_work(&port->bc_work);
 	return;
 
 free_nskb:
@@ -444,6 +447,10 @@
 	int ret;
 	rx_handler_result_t handle_res;
 
+	/* Packets from dev_loopback_xmit() do not have L2 header, bail out */
+	if (unlikely(skb->pkt_type == PACKET_LOOPBACK))
+		return RX_HANDLER_PASS;
+
 	port = macvlan_port_get_rcu(skb->dev);
 	if (is_multicast_ether_addr(eth->h_dest)) {
 		unsigned int hash;
@@ -512,10 +519,11 @@
 	const struct macvlan_dev *dest;
 
 	if (vlan->mode == MACVLAN_MODE_BRIDGE) {
-		const struct ethhdr *eth = (void *)skb->data;
+		const struct ethhdr *eth = skb_eth_hdr(skb);
 
 		/* send to other bridge ports directly */
 		if (is_multicast_ether_addr(eth->h_dest)) {
+			skb_reset_mac_header(skb);
 			macvlan_broadcast(skb, port, dev, MACVLAN_MODE_BRIDGE);
 			goto xmit_world;
 		}
@@ -757,7 +765,7 @@
 	if (dev->flags & IFF_UP) {
 		if (change & IFF_ALLMULTI)
 			dev_set_allmulti(lowerdev, dev->flags & IFF_ALLMULTI ? 1 : -1);
-		if (change & IFF_PROMISC)
+		if (!macvlan_passthru(vlan->port) && change & IFF_PROMISC)
 			dev_set_promiscuity(lowerdev,
 					    dev->flags & IFF_PROMISC ? 1 : -1);
 
@@ -1158,7 +1166,7 @@
 {
 	ether_setup(dev);
 
-	dev->min_mtu		= 0;
+	/* ether_setup() has set dev->min_mtu to ETH_MIN_MTU. */
 	dev->max_mtu		= ETH_MAX_MTU;
 	dev->priv_flags	       &= ~IFF_TX_SKB_SHARING;
 	netif_keep_dst(dev);
@@ -1251,6 +1259,9 @@
 static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[],
 			    struct netlink_ext_ack *extack)
 {
+	struct nlattr *nla, *head;
+	int rem, len;
+
 	if (tb[IFLA_ADDRESS]) {
 		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
 			return -EINVAL;
@@ -1298,6 +1309,20 @@
 			return -EADDRNOTAVAIL;
 	}
 
+	if (data[IFLA_MACVLAN_MACADDR_DATA]) {
+		head = nla_data(data[IFLA_MACVLAN_MACADDR_DATA]);
+		len = nla_len(data[IFLA_MACVLAN_MACADDR_DATA]);
+
+		nla_for_each_attr(nla, head, len, rem) {
+			if (nla_type(nla) != IFLA_MACVLAN_MACADDR ||
+			    nla_len(nla) != ETH_ALEN)
+				return -EINVAL;
+
+			if (!is_valid_ether_addr(nla_data(nla)))
+				return -EADDRNOTAVAIL;
+		}
+	}
+
 	if (data[IFLA_MACVLAN_MACADDR_COUNT])
 		return -EINVAL;
 
@@ -1354,10 +1379,6 @@
 		len = nla_len(data[IFLA_MACVLAN_MACADDR_DATA]);
 
 		nla_for_each_attr(nla, head, len, rem) {
-			if (nla_type(nla) != IFLA_MACVLAN_MACADDR ||
-			    nla_len(nla) != ETH_ALEN)
-				continue;
-
 			addr = nla_data(nla);
 			ret = macvlan_hash_add_source(vlan, addr);
 			if (ret)
@@ -1478,8 +1499,10 @@
 	/* the macvlan port may be freed by macvlan_uninit when fail to register.
 	 * so we destroy the macvlan port only when it's valid.
 	 */
-	if (create && macvlan_port_get_rtnl(lowerdev))
+	if (create && macvlan_port_get_rtnl(lowerdev)) {
+		macvlan_flush_sources(port, vlan);
 		macvlan_port_destroy(port->dev);
+	}
 	return err;
 }
 EXPORT_SYMBOL_GPL(macvlan_common_newlink);
@@ -1581,7 +1604,7 @@
 	struct hlist_head *h = &vlan->port->vlan_source_hash[i];
 	struct macvlan_source_entry *entry;
 
-	hlist_for_each_entry_rcu(entry, h, hlist) {
+	hlist_for_each_entry_rcu(entry, h, hlist, lockdep_rtnl_is_held()) {
 		if (entry->vlan != vlan)
 			continue;
 		if (nla_put(skb, IFLA_MACVLAN_MACADDR, ETH_ALEN, entry->addr))
@@ -1700,7 +1723,7 @@
 						struct macvlan_dev,
 						list);
 
-		if (macvlan_sync_address(vlan->dev, dev->dev_addr))
+		if (vlan && macvlan_sync_address(vlan->dev, dev->dev_addr))
 			return NOTIFY_BAD;
 
 		break;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/macvtap.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/macvtap.c
@@ -133,11 +133,17 @@
 	dev->tx_queue_len = TUN_READQ_SIZE;
 }
 
+static struct net *macvtap_link_net(const struct net_device *dev)
+{
+	return dev_net(macvlan_dev_real_dev(dev));
+}
+
 static struct rtnl_link_ops macvtap_link_ops __read_mostly = {
 	.kind		= "macvtap",
 	.setup		= macvtap_setup,
 	.newlink	= macvtap_newlink,
 	.dellink	= macvtap_dellink,
+	.get_link_net	= macvtap_link_net,
 	.priv_size      = sizeof(struct macvtap_dev),
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/net_failover.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/net_failover.c
@@ -61,7 +61,8 @@
 	return 0;
 
 err_standby_open:
-	dev_close(primary_dev);
+	if (primary_dev)
+		dev_close(primary_dev);
 err_primary_open:
 	netif_tx_disable(dev);
 	return err;
@@ -129,14 +130,10 @@
 			txq = ops->ndo_select_queue(primary_dev, skb, sb_dev);
 		else
 			txq = netdev_pick_tx(primary_dev, skb, NULL);
-
-		qdisc_skb_cb(skb)->slave_dev_queue_mapping = skb->queue_mapping;
-
-		return txq;
+	} else {
+		txq = skb_rx_queue_recorded(skb) ? skb_get_rx_queue(skb) : 0;
 	}
 
-	txq = skb_rx_queue_recorded(skb) ? skb_get_rx_queue(skb) : 0;
-
 	/* Save the original txq to restore before passing to the driver */
 	qdisc_skb_cb(skb)->slave_dev_queue_mapping = skb->queue_mapping;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/netconsole.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/netconsole.c
@@ -715,6 +715,7 @@
 				/* rtnl_lock already held
 				 * we might sleep in __netpoll_cleanup()
 				 */
+				nt->enabled = false;
 				spin_unlock_irqrestore(&target_list_lock, flags);
 
 				__netpoll_cleanup(&nt->np);
@@ -722,7 +723,6 @@
 				spin_lock_irqsave(&target_list_lock, flags);
 				dev_put(nt->np.dev);
 				nt->np.dev = NULL;
-				nt->enabled = false;
 				stopped = true;
 				netconsole_target_put(nt);
 				goto restart;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/netdevsim/bpf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/netdevsim/bpf.c
@@ -347,10 +347,12 @@
 {
 	struct nsim_bpf_bound_map *nmap = offmap->dev_priv;
 
-	nmap->entry[idx].key = kmalloc(offmap->map.key_size, GFP_USER);
+	nmap->entry[idx].key = kmalloc(offmap->map.key_size,
+				       GFP_KERNEL_ACCOUNT | __GFP_NOWARN);
 	if (!nmap->entry[idx].key)
 		return -ENOMEM;
-	nmap->entry[idx].value = kmalloc(offmap->map.value_size, GFP_USER);
+	nmap->entry[idx].value = kmalloc(offmap->map.value_size,
+					 GFP_KERNEL_ACCOUNT | __GFP_NOWARN);
 	if (!nmap->entry[idx].value) {
 		kfree(nmap->entry[idx].key);
 		nmap->entry[idx].key = NULL;
@@ -492,7 +494,7 @@
 	if (offmap->map.map_flags)
 		return -EINVAL;
 
-	nmap = kzalloc(sizeof(*nmap), GFP_USER);
+	nmap = kzalloc(sizeof(*nmap), GFP_KERNEL_ACCOUNT);
 	if (!nmap)
 		return -ENOMEM;
 
@@ -510,6 +512,7 @@
 				goto err_free;
 			key = nmap->entry[i].key;
 			*key = i;
+			memset(nmap->entry[i].value, 0, offmap->map.value_size);
 		}
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/netdevsim/dev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/netdevsim/dev.c
@@ -73,7 +73,7 @@
 
 static int nsim_dev_debugfs_init(struct nsim_dev *nsim_dev)
 {
-	char dev_ddir_name[16];
+	char dev_ddir_name[sizeof(DRV_NAME) + 10];
 
 	sprintf(dev_ddir_name, DRV_NAME "%u", nsim_dev->nsim_bus_dev->dev.id);
 	nsim_dev->ddir = debugfs_create_dir(dev_ddir_name, nsim_dev_ddir);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/netdevsim/netdev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/netdevsim/netdev.c
@@ -292,6 +292,7 @@
 
 	ns = netdev_priv(dev);
 	ns->netdev = dev;
+	u64_stats_init(&ns->syncp);
 	ns->nsim_dev = nsim_dev;
 	ns->nsim_dev_port = nsim_dev_port;
 	ns->nsim_bus_dev = nsim_dev->nsim_bus_dev;
@@ -301,7 +302,7 @@
 	rtnl_lock();
 	err = nsim_bpf_init(ns);
 	if (err)
-		goto err_free_netdev;
+		goto err_rtnl_unlock;
 
 	nsim_ipsec_init(ns);
 
@@ -315,8 +316,8 @@
 err_ipsec_teardown:
 	nsim_ipsec_teardown(ns);
 	nsim_bpf_uninit(ns);
+err_rtnl_unlock:
 	rtnl_unlock();
-err_free_netdev:
 	free_netdev(dev);
 	return ERR_PTR(err);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ntb_netdev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ntb_netdev.c
@@ -137,7 +137,7 @@
 enqueue_again:
 	rc = ntb_transport_rx_enqueue(qp, skb, skb->data, ndev->mtu + ETH_HLEN);
 	if (rc) {
-		dev_kfree_skb(skb);
+		dev_kfree_skb_any(skb);
 		ndev->stats.rx_errors++;
 		ndev->stats.rx_fifo_errors++;
 	}
@@ -192,7 +192,7 @@
 		ndev->stats.tx_aborted_errors++;
 	}
 
-	dev_kfree_skb(skb);
+	dev_kfree_skb_any(skb);
 
 	if (ntb_transport_tx_free_entry(dev->qp) >= tx_start) {
 		/* Make sure anybody stopping the queue after this sees the new
@@ -484,7 +484,14 @@
 	rc = ntb_transport_register_client_dev(KBUILD_MODNAME);
 	if (rc)
 		return rc;
-	return ntb_transport_register_client(&ntb_netdev_client);
+
+	rc = ntb_transport_register_client(&ntb_netdev_client);
+	if (rc) {
+		ntb_transport_unregister_client_dev(KBUILD_MODNAME);
+		return rc;
+	}
+
+	return 0;
 }
 module_init(ntb_netdev_init_module);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/Kconfig
@@ -193,6 +193,7 @@
 	depends on 64BIT
 	depends on PCI
 	select MDIO_CAVIUM
+	select MDIO_DEVRES
 	help
 	  This driver supports the MDIO interfaces found on Cavium
 	  ThunderX SoCs when the MDIO bus device appears as a PCI
@@ -431,7 +432,8 @@
 config MICROSEMI_PHY
 	tristate "Microsemi PHYs"
 	---help---
-	  Currently supports VSC8514, VSC8530, VSC8531, VSC8540 and VSC8541 PHYs
+	  Currently supports VSC8514, VSC8530, VSC8531, VSC8531_02, VSC8540 and
+	  VSC8541 PHYs
 
 config NATIONAL_PHY
 	tristate "National Semiconductor PHYs"
@@ -484,6 +486,11 @@
 	---help---
 	  Currently supports the vsc8244
 
+config XILINX_PHY
+	tristate "Drivers for xilinx PHYs"
+	---help---
+	  This module provides a driver for the Xilinx PCS/PMA Core.
+
 config XILINX_GMII2RGMII
 	tristate "Xilinx GMII2RGMII converter driver"
 	---help---
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/Makefile
@@ -93,4 +93,5 @@
 obj-$(CONFIG_STE10XP)		+= ste10Xp.o
 obj-$(CONFIG_TERANETICS_PHY)	+= teranetics.o
 obj-$(CONFIG_VITESSE_PHY)	+= vitesse.o
+obj-$(CONFIG_XILINX_PHY)	+= xilinx_phy.o
 obj-$(CONFIG_XILINX_GMII2RGMII) += xilinx_gmii2rgmii.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/aquantia_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/aquantia_main.c
@@ -34,6 +34,8 @@
 #define MDIO_AN_VEND_PROV			0xc400
 #define MDIO_AN_VEND_PROV_1000BASET_FULL	BIT(15)
 #define MDIO_AN_VEND_PROV_1000BASET_HALF	BIT(14)
+#define MDIO_AN_VEND_PROV_5000BASET_FULL	BIT(11)
+#define MDIO_AN_VEND_PROV_2500BASET_FULL	BIT(10)
 #define MDIO_AN_VEND_PROV_DOWNSHIFT_EN		BIT(4)
 #define MDIO_AN_VEND_PROV_DOWNSHIFT_MASK	GENMASK(3, 0)
 #define MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT	4
@@ -230,9 +232,20 @@
 			      phydev->advertising))
 		reg |= MDIO_AN_VEND_PROV_1000BASET_HALF;
 
+	/* Handle the case when the 2.5G and 5G speeds are not advertised */
+	if (linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
+			      phydev->advertising))
+		reg |= MDIO_AN_VEND_PROV_2500BASET_FULL;
+
+	if (linkmode_test_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
+			      phydev->advertising))
+		reg |= MDIO_AN_VEND_PROV_5000BASET_FULL;
+
 	ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MDIO_AN_VEND_PROV,
 				     MDIO_AN_VEND_PROV_1000BASET_HALF |
-				     MDIO_AN_VEND_PROV_1000BASET_FULL, reg);
+				     MDIO_AN_VEND_PROV_1000BASET_FULL |
+				     MDIO_AN_VEND_PROV_2500BASET_FULL |
+				     MDIO_AN_VEND_PROV_5000BASET_FULL, reg);
 	if (ret < 0)
 		return ret;
 	if (ret > 0)
@@ -627,6 +640,8 @@
 	.config_intr	= aqr_config_intr,
 	.ack_interrupt	= aqr_ack_interrupt,
 	.read_status	= aqr_read_status,
+	.suspend	= aqr107_suspend,
+	.resume		= aqr107_resume,
 },
 {
 	PHY_ID_MATCH_MODEL(PHY_ID_AQR106),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/bcm-phy-lib.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/bcm-phy-lib.c
@@ -190,7 +190,7 @@
 
 int bcm_phy_set_eee(struct phy_device *phydev, bool enable)
 {
-	int val;
+	int val, mask = 0;
 
 	/* Enable EEE at PHY level */
 	val = phy_read_mmd(phydev, MDIO_MMD_AN, BRCM_CL45VEN_EEE_CONTROL);
@@ -209,10 +209,17 @@
 	if (val < 0)
 		return val;
 
+	if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
+			      phydev->supported))
+		mask |= MDIO_EEE_1000T;
+	if (linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
+			      phydev->supported))
+		mask |= MDIO_EEE_100TX;
+
 	if (enable)
-		val |= (MDIO_EEE_100TX | MDIO_EEE_1000T);
+		val |= mask;
 	else
-		val &= ~(MDIO_EEE_100TX | MDIO_EEE_1000T);
+		val &= ~mask;
 
 	phy_write_mmd(phydev, MDIO_MMD_AN, BCM_CL45VEN_EEE_ADV, (u32)val);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/bcm63xx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/bcm63xx.c
@@ -73,6 +73,7 @@
 	/* same phy as above, with just a different OUI */
 	.phy_id		= 0x002bdc00,
 	.phy_id_mask	= 0xfffffc00,
+	.name		= "Broadcom BCM63XX (2)",
 	/* PHY_BASIC_FEATURES */
 	.flags		= PHY_IS_INTERNAL,
 	.config_init	= bcm63xx_config_init,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/bcm7xxx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/bcm7xxx.c
@@ -26,7 +26,12 @@
 #define MII_BCM7XXX_SHD_2_ADDR_CTRL	0xe
 #define MII_BCM7XXX_SHD_2_CTRL_STAT	0xf
 #define MII_BCM7XXX_SHD_2_BIAS_TRIM	0x1a
+#define MII_BCM7XXX_SHD_3_PCS_CTRL	0x0
+#define MII_BCM7XXX_SHD_3_PCS_STATUS	0x1
+#define MII_BCM7XXX_SHD_3_EEE_CAP	0x2
 #define MII_BCM7XXX_SHD_3_AN_EEE_ADV	0x3
+#define MII_BCM7XXX_SHD_3_EEE_LP	0x4
+#define MII_BCM7XXX_SHD_3_EEE_WK_ERR	0x5
 #define MII_BCM7XXX_SHD_3_PCS_CTRL_2	0x6
 #define  MII_BCM7XXX_PCS_CTRL_2_DEF	0x4400
 #define MII_BCM7XXX_SHD_3_AN_STAT	0xb
@@ -210,25 +215,37 @@
 	return genphy_config_aneg(phydev);
 }
 
-static int phy_set_clr_bits(struct phy_device *dev, int location,
-					int set_mask, int clr_mask)
+static int __phy_set_clr_bits(struct phy_device *dev, int location,
+			      int set_mask, int clr_mask)
 {
 	int v, ret;
 
-	v = phy_read(dev, location);
+	v = __phy_read(dev, location);
 	if (v < 0)
 		return v;
 
 	v &= ~clr_mask;
 	v |= set_mask;
 
-	ret = phy_write(dev, location, v);
+	ret = __phy_write(dev, location, v);
 	if (ret < 0)
 		return ret;
 
 	return v;
 }
 
+static int phy_set_clr_bits(struct phy_device *dev, int location,
+			    int set_mask, int clr_mask)
+{
+	int ret;
+
+	mutex_lock(&dev->mdio.bus->mdio_lock);
+	ret = __phy_set_clr_bits(dev, location, set_mask, clr_mask);
+	mutex_unlock(&dev->mdio.bus->mdio_lock);
+
+	return ret;
+}
+
 static int bcm7xxx_28nm_ephy_01_afe_config_init(struct phy_device *phydev)
 {
 	int ret;
@@ -392,6 +409,93 @@
 	return bcm7xxx_28nm_ephy_apd_enable(phydev);
 }
 
+#define MII_BCM7XXX_REG_INVALID	0xff
+
+static u8 bcm7xxx_28nm_ephy_regnum_to_shd(u16 regnum)
+{
+	switch (regnum) {
+	case MDIO_CTRL1:
+		return MII_BCM7XXX_SHD_3_PCS_CTRL;
+	case MDIO_STAT1:
+		return MII_BCM7XXX_SHD_3_PCS_STATUS;
+	case MDIO_PCS_EEE_ABLE:
+		return MII_BCM7XXX_SHD_3_EEE_CAP;
+	case MDIO_AN_EEE_ADV:
+		return MII_BCM7XXX_SHD_3_AN_EEE_ADV;
+	case MDIO_AN_EEE_LPABLE:
+		return MII_BCM7XXX_SHD_3_EEE_LP;
+	case MDIO_PCS_EEE_WK_ERR:
+		return MII_BCM7XXX_SHD_3_EEE_WK_ERR;
+	default:
+		return MII_BCM7XXX_REG_INVALID;
+	}
+}
+
+static bool bcm7xxx_28nm_ephy_dev_valid(int devnum)
+{
+	return devnum == MDIO_MMD_AN || devnum == MDIO_MMD_PCS;
+}
+
+static int bcm7xxx_28nm_ephy_read_mmd(struct phy_device *phydev,
+				      int devnum, u16 regnum)
+{
+	u8 shd = bcm7xxx_28nm_ephy_regnum_to_shd(regnum);
+	int ret;
+
+	if (!bcm7xxx_28nm_ephy_dev_valid(devnum) ||
+	    shd == MII_BCM7XXX_REG_INVALID)
+		return -EOPNOTSUPP;
+
+	/* set shadow mode 2 */
+	ret = __phy_set_clr_bits(phydev, MII_BCM7XXX_TEST,
+				 MII_BCM7XXX_SHD_MODE_2, 0);
+	if (ret < 0)
+		return ret;
+
+	/* Access the desired shadow register address */
+	ret = __phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL, shd);
+	if (ret < 0)
+		goto reset_shadow_mode;
+
+	ret = __phy_read(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT);
+
+reset_shadow_mode:
+	/* reset shadow mode 2 */
+	__phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0,
+			   MII_BCM7XXX_SHD_MODE_2);
+	return ret;
+}
+
+static int bcm7xxx_28nm_ephy_write_mmd(struct phy_device *phydev,
+				       int devnum, u16 regnum, u16 val)
+{
+	u8 shd = bcm7xxx_28nm_ephy_regnum_to_shd(regnum);
+	int ret;
+
+	if (!bcm7xxx_28nm_ephy_dev_valid(devnum) ||
+	    shd == MII_BCM7XXX_REG_INVALID)
+		return -EOPNOTSUPP;
+
+	/* set shadow mode 2 */
+	ret = __phy_set_clr_bits(phydev, MII_BCM7XXX_TEST,
+				 MII_BCM7XXX_SHD_MODE_2, 0);
+	if (ret < 0)
+		return ret;
+
+	/* Access the desired shadow register address */
+	ret = __phy_write(phydev, MII_BCM7XXX_SHD_2_ADDR_CTRL, shd);
+	if (ret < 0)
+		goto reset_shadow_mode;
+
+	/* Write the desired value in the shadow register */
+	__phy_write(phydev, MII_BCM7XXX_SHD_2_CTRL_STAT, val);
+
+reset_shadow_mode:
+	/* reset shadow mode 2 */
+	return __phy_set_clr_bits(phydev, MII_BCM7XXX_TEST, 0,
+				  MII_BCM7XXX_SHD_MODE_2);
+}
+
 static int bcm7xxx_28nm_ephy_resume(struct phy_device *phydev)
 {
 	int ret;
@@ -563,6 +667,8 @@
 	.get_strings	= bcm_phy_get_strings,				\
 	.get_stats	= bcm7xxx_28nm_get_phy_stats,			\
 	.probe		= bcm7xxx_28nm_probe,				\
+	.read_mmd	= bcm7xxx_28nm_ephy_read_mmd,			\
+	.write_mmd	= bcm7xxx_28nm_ephy_write_mmd,			\
 }
 
 #define BCM7XXX_40NM_EPHY(_oui, _name)					\
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/broadcom.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/broadcom.c
@@ -11,6 +11,7 @@
  */
 
 #include "bcm-phy-lib.h"
+#include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/phy.h>
 #include <linux/brcmphy.h>
@@ -26,18 +27,13 @@
 MODULE_AUTHOR("Maciej W. Rozycki");
 MODULE_LICENSE("GPL");
 
+static int bcm54xx_config_clock_delay(struct phy_device *phydev);
+
 static int bcm54210e_config_init(struct phy_device *phydev)
 {
 	int val;
 
-	val = bcm54xx_auxctl_read(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
-	val &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN;
-	val |= MII_BCM54XX_AUXCTL_MISC_WREN;
-	bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC, val);
-
-	val = bcm_phy_read_shadow(phydev, BCM54810_SHD_CLK_CTL);
-	val &= ~BCM54810_SHD_CLK_CTL_GTXCLK_EN;
-	bcm_phy_write_shadow(phydev, BCM54810_SHD_CLK_CTL, val);
+	bcm54xx_config_clock_delay(phydev);
 
 	if (phydev->dev_flags & PHY_BRCM_EN_MASTER_MODE) {
 		val = phy_read(phydev, MII_CTRL1000);
@@ -429,6 +425,17 @@
 	return err;
 }
 
+static int bcm54810_read_mmd(struct phy_device *phydev, int devnum, u16 regnum)
+{
+	return -EOPNOTSUPP;
+}
+
+static int bcm54810_write_mmd(struct phy_device *phydev, int devnum, u16 regnum,
+			      u16 val)
+{
+	return -EOPNOTSUPP;
+}
+
 static int bcm5481_config_aneg(struct phy_device *phydev)
 {
 	struct device_node *np = phydev->mdio.dev.of_node;
@@ -484,6 +491,26 @@
 	if (err < 0)
 		return err;
 
+	/* The datasheet indicates the PHY needs up to 1us to complete a reset,
+	 * build some slack here.
+	 */
+	usleep_range(1000, 2000);
+
+	/* The PHY requires 65 MDC clock cycles to complete a write operation
+	 * and turnaround the line properly.
+	 *
+	 * We ignore -EIO here as the MDIO controller (e.g.: mdio-bcm-unimac)
+	 * may flag the lack of turn-around as a read failure. This is
+	 * particularly true with this combination since the MDIO controller
+	 * only used 64 MDC cycles. This is not a critical failure in this
+	 * specific case and it has no functional impact otherwise, so we let
+	 * that one go through. If there is a genuine bus error, the next read
+	 * of MII_BRCM_FET_INTREG will error out.
+	 */
+	err = phy_read(phydev, MII_BMCR);
+	if (err < 0 && err != -EIO)
+		return err;
+
 	reg = phy_read(phydev, MII_BRCM_FET_INTREG);
 	if (reg < 0)
 		return reg;
@@ -651,6 +678,7 @@
 	.phy_id_mask	= 0xfffffff0,
 	.name		= "Broadcom BCM54616S",
 	/* PHY_GBIT_FEATURES */
+	.soft_reset     = genphy_soft_reset,
 	.config_init	= bcm54xx_config_init,
 	.config_aneg	= bcm54616s_config_aneg,
 	.ack_interrupt	= bcm_phy_ack_intr,
@@ -679,6 +707,8 @@
 	.phy_id_mask    = 0xfffffff0,
 	.name           = "Broadcom BCM54810",
 	/* PHY_GBIT_FEATURES */
+	.read_mmd	= bcm54810_read_mmd,
+	.write_mmd	= bcm54810_write_mmd,
 	.config_init    = bcm54xx_config_init,
 	.config_aneg    = bcm5481_config_aneg,
 	.ack_interrupt  = bcm_phy_ack_intr,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/dp83640.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/dp83640.c
@@ -1119,7 +1119,7 @@
 		goto out;
 	}
 	dp83640_clock_init(clock, bus);
-	list_add_tail(&phyter_clocks, &clock->list);
+	list_add_tail(&clock->list, &phyter_clocks);
 out:
 	mutex_unlock(&phyter_clocks_lock);
 
@@ -1348,6 +1348,7 @@
 		dp83640->hwts_rx_en = 1;
 		dp83640->layer = PTP_CLASS_L4;
 		dp83640->version = PTP_CLASS_V1;
+		cfg.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
 		break;
 	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
 	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
@@ -1355,6 +1356,7 @@
 		dp83640->hwts_rx_en = 1;
 		dp83640->layer = PTP_CLASS_L4;
 		dp83640->version = PTP_CLASS_V2;
+		cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
 		break;
 	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
 	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
@@ -1362,6 +1364,7 @@
 		dp83640->hwts_rx_en = 1;
 		dp83640->layer = PTP_CLASS_L2;
 		dp83640->version = PTP_CLASS_V2;
+		cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
 		break;
 	case HWTSTAMP_FILTER_PTP_V2_EVENT:
 	case HWTSTAMP_FILTER_PTP_V2_SYNC:
@@ -1369,6 +1372,7 @@
 		dp83640->hwts_rx_en = 1;
 		dp83640->layer = PTP_CLASS_L4 | PTP_CLASS_L2;
 		dp83640->version = PTP_CLASS_V2;
+		cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
 		break;
 	default:
 		return -ERANGE;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/dp83640_reg.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/dp83640_reg.h
@@ -5,7 +5,7 @@
 #ifndef HAVE_DP83640_REGISTERS
 #define HAVE_DP83640_REGISTERS
 
-#define PAGE0                     0x0000
+/* #define PAGE0                  0x0000 */
 #define PHYCR2                    0x001c /* PHY Control Register 2 */
 
 #define PAGE4                     0x0004
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/dp83822.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/dp83822.c
@@ -197,9 +197,7 @@
 		if (misr_status < 0)
 			return misr_status;
 
-		misr_status |= (DP83822_RX_ERR_HF_INT_EN |
-				DP83822_FALSE_CARRIER_HF_INT_EN |
-				DP83822_ANEG_COMPLETE_INT_EN |
+		misr_status |= (DP83822_ANEG_COMPLETE_INT_EN |
 				DP83822_DUP_MODE_CHANGE_INT_EN |
 				DP83822_SPEED_CHANGED_INT_EN |
 				DP83822_LINK_STAT_INT_EN |
@@ -238,7 +236,7 @@
 		if (err < 0)
 			return err;
 
-		err = phy_write(phydev, MII_DP83822_MISR1, 0);
+		err = phy_write(phydev, MII_DP83822_MISR2, 0);
 		if (err < 0)
 			return err;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/dp83867.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/dp83867.c
@@ -21,11 +21,14 @@
 #define MII_DP83867_PHYCTRL	0x10
 #define MII_DP83867_MICR	0x12
 #define MII_DP83867_ISR		0x13
+#define MII_DP83867_CFG2	0x14
+#define MII_DP83867_BISCR	0x16
 #define DP83867_CTRL		0x1f
 #define DP83867_CFG3		0x1e
 
 /* Extended Registers */
-#define DP83867_CFG4            0x0031
+#define DP83867_FLD_THR_CFG	0x002e
+#define DP83867_CFG4		0x0031
 #define DP83867_CFG4_SGMII_ANEG_MASK (BIT(5) | BIT(6))
 #define DP83867_CFG4_SGMII_ANEG_TIMER_11MS   (3 << 5)
 #define DP83867_CFG4_SGMII_ANEG_TIMER_800US  (2 << 5)
@@ -74,12 +77,19 @@
 #define DP83867_STRAP_STS2_CLK_SKEW_RX_MASK	GENMASK(2, 0)
 #define DP83867_STRAP_STS2_CLK_SKEW_RX_SHIFT	0
 #define DP83867_STRAP_STS2_CLK_SKEW_NONE	BIT(2)
+#define DP83867_STRAP_STS2_STRAP_FLD		BIT(10)
 
 /* PHY CTRL bits */
 #define DP83867_PHYCR_FIFO_DEPTH_SHIFT		14
 #define DP83867_PHYCR_FIFO_DEPTH_MAX		0x03
 #define DP83867_PHYCR_FIFO_DEPTH_MASK		GENMASK(15, 14)
 #define DP83867_PHYCR_RESERVED_MASK		BIT(11)
+#define DP83867_PHYCR_FORCE_LINK_GOOD		BIT(10)
+#define DP83867_MDI_CROSSOVER		5
+#define DP83867_MDI_CROSSOVER_AUTO		0b10
+#define DP83867_PHYCTRL_SGMIIEN			0x0800
+#define DP83867_PHYCTRL_RXFIFO_SHIFT		12
+#define DP83867_PHYCTRL_TXFIFO_SHIFT		14
 
 /* RGMIIDCTL bits */
 #define DP83867_RGMII_TX_CLK_DELAY_MAX		0xf
@@ -95,9 +105,24 @@
 #define DP83867_IO_MUX_CFG_CLK_O_SEL_MASK	(0x1f << 8)
 #define DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT	8
 
+/* CFG2 bits */
+#define MII_DP83867_CFG2_SPEEDOPT_10EN		0x0040
+#define MII_DP83867_CFG2_SGMII_AUTONEGEN	0x0080
+#define MII_DP83867_CFG2_SPEEDOPT_ENH		0x0100
+#define MII_DP83867_CFG2_SPEEDOPT_CNT		0x0800
+#define MII_DP83867_CFG2_SPEEDOPT_INTLOW	0x2000
+#define MII_DP83867_CFG2_MASK			0x003F
+
+/* CFG3 bits */
+#define DP83867_CFG3_INT_OE			BIT(7)
+#define DP83867_CFG3_ROBUST_AUTO_MDIX		BIT(9)
+
 /* CFG4 bits */
 #define DP83867_CFG4_PORT_MIRROR_EN              BIT(0)
 
+/* FLD_THR_CFG */
+#define DP83867_FLD_THR_CFG_ENERGY_LOST_THR_MASK	0x7
+
 enum {
 	DP83867_PORT_MIRROING_KEEP,
 	DP83867_PORT_MIRROING_EN,
@@ -302,7 +327,7 @@
 {
 	struct dp83867_private *dp83867 = phydev->priv;
 	int ret, val, bs;
-	u16 delay;
+	u16 delay, cfg2;
 
 	ret = dp83867_of_init(phydev);
 	if (ret)
@@ -313,6 +338,20 @@
 		phy_clear_bits_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4,
 				   BIT(7));
 
+	bs = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_STRAP_STS2);
+	if (bs & DP83867_STRAP_STS2_STRAP_FLD) {
+		/* When using strap to enable FLD, the ENERGY_LOST_FLD_THR will
+		 * be set to 0x2. This may causes the PHY link to be unstable -
+		 * the default value 0x1 need to be restored.
+		 */
+		ret = phy_modify_mmd(phydev, DP83867_DEVADDR,
+				     DP83867_FLD_THR_CFG,
+				     DP83867_FLD_THR_CFG_ENERGY_LOST_THR_MASK,
+				     0x1);
+		if (ret)
+			return ret;
+	}
+
 	if (phy_interface_is_rgmii(phydev)) {
 		val = phy_read(phydev, MII_DP83867_PHYCTRL);
 		if (val < 0)
@@ -408,14 +447,44 @@
 		else
 			val &= ~DP83867_SGMII_TYPE;
 		phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_SGMIICTL, val);
+
+		phy_write(phydev, MII_BMCR,
+			  (BMCR_ANENABLE | BMCR_FULLDPLX | BMCR_SPEED1000));
+
+		cfg2 = phy_read(phydev, MII_DP83867_CFG2);
+		cfg2 &= MII_DP83867_CFG2_MASK;
+		cfg2 |= (MII_DP83867_CFG2_SPEEDOPT_10EN |
+			 MII_DP83867_CFG2_SGMII_AUTONEGEN |
+			 MII_DP83867_CFG2_SPEEDOPT_ENH |
+			 MII_DP83867_CFG2_SPEEDOPT_CNT |
+			 MII_DP83867_CFG2_SPEEDOPT_INTLOW);
+		phy_write(phydev, MII_DP83867_CFG2, cfg2);
+
+		phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RGMIICTL, 0x0);
+
+		phy_write(phydev, MII_DP83867_PHYCTRL,
+			  DP83867_PHYCTRL_SGMIIEN |
+			  (DP83867_MDI_CROSSOVER_AUTO << DP83867_MDI_CROSSOVER) |
+			  (dp83867->fifo_depth << DP83867_PHYCTRL_RXFIFO_SHIFT) |
+			  (dp83867->fifo_depth  << DP83867_PHYCTRL_TXFIFO_SHIFT));
+		phy_write(phydev, MII_DP83867_BISCR, 0x0);
+
+		/* This is a SW workaround for link instability if RX_CTRL is
+		 * not strapped to mode 3 or 4 in HW. This is required for SGMII
+		 * in addition to clearing bit 7, handled above.
+		 */
+		if (dp83867->rxctrl_strap_quirk)
+			phy_set_bits_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4,
+					 BIT(8));
 	}
 
+	val = phy_read(phydev, DP83867_CFG3);
 	/* Enable Interrupt output INT_OE in CFG3 register */
-	if (phy_interrupt_is_valid(phydev)) {
-		val = phy_read(phydev, DP83867_CFG3);
-		val |= BIT(7);
-		phy_write(phydev, DP83867_CFG3, val);
-	}
+	if (phy_interrupt_is_valid(phydev))
+		val |= DP83867_CFG3_INT_OE;
+
+	val |= DP83867_CFG3_ROBUST_AUTO_MDIX;
+	phy_write(phydev, DP83867_CFG3, val);
 
 	if (dp83867->port_mirroring != DP83867_PORT_MIRROING_KEEP)
 		dp83867_config_port_mirroring(phydev);
@@ -449,7 +518,8 @@
 
 	usleep_range(10, 20);
 
-	return 0;
+	return phy_modify(phydev, MII_DP83867_PHYCTRL,
+			 DP83867_PHYCR_FORCE_LINK_GOOD, 0);
 }
 
 static struct phy_driver dp83867_driver[] = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/fixed_phy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/fixed_phy.c
@@ -212,16 +212,13 @@
 	 */
 	gpiod = gpiod_get_from_of_node(fixed_link_node, "link-gpios", 0,
 				       GPIOD_IN, "mdio");
-	of_node_put(fixed_link_node);
-	if (IS_ERR(gpiod)) {
-		if (PTR_ERR(gpiod) == -EPROBE_DEFER)
-			return gpiod;
-
+	if (IS_ERR(gpiod) && PTR_ERR(gpiod) != -EPROBE_DEFER) {
 		if (PTR_ERR(gpiod) != -ENOENT)
 			pr_err("error getting GPIO for fixed link %pOF, proceed without\n",
 			       fixed_link_node);
 		gpiod = NULL;
 	}
+	of_node_put(fixed_link_node);
 
 	return gpiod;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/intel-xway.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/intel-xway.c
@@ -11,6 +11,18 @@
 
 #define XWAY_MDIO_IMASK			0x19	/* interrupt mask */
 #define XWAY_MDIO_ISTAT			0x1A	/* interrupt status */
+#define XWAY_MDIO_LED			0x1B	/* led control */
+
+/* bit 15:12 are reserved */
+#define XWAY_MDIO_LED_LED3_EN		BIT(11)	/* Enable the integrated function of LED3 */
+#define XWAY_MDIO_LED_LED2_EN		BIT(10)	/* Enable the integrated function of LED2 */
+#define XWAY_MDIO_LED_LED1_EN		BIT(9)	/* Enable the integrated function of LED1 */
+#define XWAY_MDIO_LED_LED0_EN		BIT(8)	/* Enable the integrated function of LED0 */
+/* bit 7:4 are reserved */
+#define XWAY_MDIO_LED_LED3_DA		BIT(3)	/* Direct Access to LED3 */
+#define XWAY_MDIO_LED_LED2_DA		BIT(2)	/* Direct Access to LED2 */
+#define XWAY_MDIO_LED_LED1_DA		BIT(1)	/* Direct Access to LED1 */
+#define XWAY_MDIO_LED_LED0_DA		BIT(0)	/* Direct Access to LED0 */
 
 #define XWAY_MDIO_INIT_WOL		BIT(15)	/* Wake-On-LAN */
 #define XWAY_MDIO_INIT_MSRE		BIT(14)
@@ -159,6 +171,15 @@
 	/* Clear all pending interrupts */
 	phy_read(phydev, XWAY_MDIO_ISTAT);
 
+	/* Ensure that integrated led function is enabled for all leds */
+	err = phy_write(phydev, XWAY_MDIO_LED,
+			XWAY_MDIO_LED_LED0_EN |
+			XWAY_MDIO_LED_LED1_EN |
+			XWAY_MDIO_LED_LED2_EN |
+			XWAY_MDIO_LED_LED3_EN);
+	if (err)
+		return err;
+
 	phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LEDCH,
 		      XWAY_MMD_LEDCH_NACS_NONE |
 		      XWAY_MMD_LEDCH_SBF_F02HZ |
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/marvell.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/marvell.c
@@ -358,7 +358,7 @@
 	return marvell_config_aneg(phydev);
 }
 
-#ifdef CONFIG_OF_MDIO
+#if IS_ENABLED(CONFIG_OF_MDIO)
 /* Set and/or override some configuration registers based on the
  * marvell,reg-init property stored in the of_node for the phydev.
  *
@@ -444,9 +444,9 @@
 	else
 		mscr = 0;
 
-	return phy_modify_paged(phydev, MII_MARVELL_MSCR_PAGE,
-				MII_88E1121_PHY_MSCR_REG,
-				MII_88E1121_PHY_MSCR_DELAY_MASK, mscr);
+	return phy_modify_paged_changed(phydev, MII_MARVELL_MSCR_PAGE,
+					MII_88E1121_PHY_MSCR_REG,
+					MII_88E1121_PHY_MSCR_DELAY_MASK, mscr);
 }
 
 static int m88e1121_config_aneg(struct phy_device *phydev)
@@ -460,11 +460,13 @@
 			return err;
 	}
 
+	changed = err;
+
 	err = marvell_set_polarity(phydev, phydev->mdix_ctrl);
 	if (err < 0)
 		return err;
 
-	changed = err;
+	changed |= err;
 
 	err = genphy_config_aneg(phydev);
 	if (err < 0)
@@ -886,16 +888,15 @@
 {
 	int err;
 
-	err = genphy_soft_reset(phydev);
+	err = marvell_set_polarity(phydev, phydev->mdix_ctrl);
 	if (err < 0)
 		return err;
 
-	err = marvell_set_polarity(phydev, phydev->mdix_ctrl);
+	err = genphy_config_aneg(phydev);
 	if (err < 0)
 		return err;
 
-	err = genphy_config_aneg(phydev);
-	return 0;
+	return genphy_soft_reset(phydev);
 }
 
 static int m88e1118_config_init(struct phy_device *phydev)
@@ -917,6 +918,12 @@
 	if (err < 0)
 		return err;
 
+	if (phy_interface_is_rgmii(phydev)) {
+		err = m88e1121_config_aneg_rgmii_delays(phydev);
+		if (err < 0)
+			return err;
+	}
+
 	/* Adjust LED Control */
 	if (phydev->dev_flags & MARVELL_PHY_M1118_DNS323_LEDS)
 		err = phy_write(phydev, 0x10, 0x1100);
@@ -1401,8 +1408,8 @@
 	int err;
 
 	/* Suspend the fiber mode first */
-	if (!linkmode_test_bit(ETHTOOL_LINK_MODE_FIBRE_BIT,
-			       phydev->supported)) {
+	if (linkmode_test_bit(ETHTOOL_LINK_MODE_FIBRE_BIT,
+			      phydev->supported)) {
 		err = marvell_set_page(phydev, MII_MARVELL_FIBER_PAGE);
 		if (err < 0)
 			goto error;
@@ -1436,8 +1443,8 @@
 	int err;
 
 	/* Resume the fiber mode first */
-	if (!linkmode_test_bit(ETHTOOL_LINK_MODE_FIBRE_BIT,
-			       phydev->supported)) {
+	if (linkmode_test_bit(ETHTOOL_LINK_MODE_FIBRE_BIT,
+			      phydev->supported)) {
 		err = marvell_set_page(phydev, MII_MARVELL_FIBER_PAGE);
 		if (err < 0)
 			goto error;
@@ -2401,9 +2408,31 @@
 		.get_stats = marvell_get_stats,
 	},
 	{
-		.phy_id = MARVELL_PHY_ID_88E6390,
+		.phy_id = MARVELL_PHY_ID_88E6341_FAMILY,
+		.phy_id_mask = MARVELL_PHY_ID_MASK,
+		.name = "Marvell 88E6341 Family",
+		/* PHY_GBIT_FEATURES */
+		.probe = m88e1510_probe,
+		.config_init = &marvell_config_init,
+		.config_aneg = &m88e6390_config_aneg,
+		.read_status = &marvell_read_status,
+		.ack_interrupt = &marvell_ack_interrupt,
+		.config_intr = &marvell_config_intr,
+		.did_interrupt = &m88e1121_did_interrupt,
+		.resume = &genphy_resume,
+		.suspend = &genphy_suspend,
+		.read_page = marvell_read_page,
+		.write_page = marvell_write_page,
+		.get_sset_count = marvell_get_sset_count,
+		.get_strings = marvell_get_strings,
+		.get_stats = marvell_get_stats,
+		.get_tunable = m88e1540_get_tunable,
+		.set_tunable = m88e1540_set_tunable,
+	},
+	{
+		.phy_id = MARVELL_PHY_ID_88E6390_FAMILY,
 		.phy_id_mask = MARVELL_PHY_ID_MASK,
-		.name = "Marvell 88E6390",
+		.name = "Marvell 88E6390 Family",
 		/* PHY_GBIT_FEATURES */
 		.probe = m88e6390_probe,
 		.config_init = &marvell_config_init,
@@ -2441,7 +2470,8 @@
 	{ MARVELL_PHY_ID_88E1540, MARVELL_PHY_ID_MASK },
 	{ MARVELL_PHY_ID_88E1545, MARVELL_PHY_ID_MASK },
 	{ MARVELL_PHY_ID_88E3016, MARVELL_PHY_ID_MASK },
-	{ MARVELL_PHY_ID_88E6390, MARVELL_PHY_ID_MASK },
+	{ MARVELL_PHY_ID_88E6341_FAMILY, MARVELL_PHY_ID_MASK },
+	{ MARVELL_PHY_ID_88E6390_FAMILY, MARVELL_PHY_ID_MASK },
 	{ }
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/mdio-aspeed.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/mdio-aspeed.c
@@ -61,6 +61,13 @@
 
 	iowrite32(ctrl, ctx->base + ASPEED_MDIO_CTRL);
 
+	rc = readl_poll_timeout(ctx->base + ASPEED_MDIO_CTRL, ctrl,
+				!(ctrl & ASPEED_MDIO_CTRL_FIRE),
+				ASPEED_MDIO_INTERVAL_US,
+				ASPEED_MDIO_TIMEOUT_US);
+	if (rc < 0)
+		return rc;
+
 	rc = readl_poll_timeout(ctx->base + ASPEED_MDIO_DATA, data,
 				data & ASPEED_MDIO_DATA_IDLE,
 				ASPEED_MDIO_INTERVAL_US,
@@ -141,6 +148,7 @@
 	{ .compatible = "aspeed,ast2600-mdio", },
 	{ },
 };
+MODULE_DEVICE_TABLE(of, aspeed_mdio_of_match);
 
 static struct platform_driver aspeed_mdio_driver = {
 	.driver = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/mdio-bcm-iproc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/mdio-bcm-iproc.c
@@ -178,6 +178,23 @@
 	return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+int iproc_mdio_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct iproc_mdio_priv *priv = platform_get_drvdata(pdev);
+
+	/* restore the mii clock configuration */
+	iproc_mdio_config_clk(priv->base);
+
+	return 0;
+}
+
+static const struct dev_pm_ops iproc_mdio_pm_ops = {
+	.resume = iproc_mdio_resume
+};
+#endif /* CONFIG_PM_SLEEP */
+
 static const struct of_device_id iproc_mdio_of_match[] = {
 	{ .compatible = "brcm,iproc-mdio", },
 	{ /* sentinel */ },
@@ -188,6 +205,9 @@
 	.driver = {
 		.name = "iproc-mdio",
 		.of_match_table = iproc_mdio_of_match,
+#ifdef CONFIG_PM_SLEEP
+		.pm = &iproc_mdio_pm_ops,
+#endif
 	},
 	.probe = iproc_mdio_probe,
 	.remove = iproc_mdio_remove,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/mdio-bcm-unimac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/mdio-bcm-unimac.c
@@ -242,11 +242,9 @@
 		return -ENOMEM;
 	}
 
-	priv->clk = devm_clk_get(&pdev->dev, NULL);
-	if (PTR_ERR(priv->clk) == -EPROBE_DEFER)
+	priv->clk = devm_clk_get_optional(&pdev->dev, NULL);
+	if (IS_ERR(priv->clk))
 		return PTR_ERR(priv->clk);
-	else
-		priv->clk = NULL;
 
 	ret = clk_prepare_enable(priv->clk);
 	if (ret)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/mdio-i2c.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/mdio-i2c.c
@@ -10,10 +10,9 @@
  * of their settings.
  */
 #include <linux/i2c.h>
+#include <linux/mdio/mdio-i2c.h>
 #include <linux/phy.h>
 
-#include "mdio-i2c.h"
-
 /*
  * I2C bus addresses 0x50 and 0x51 are normally an EEPROM, which is
  * specified to be present in SFP modules.  These correspond with PHY
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/mdio-mux-bcm-iproc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/mdio-mux-bcm-iproc.c
@@ -288,8 +288,13 @@
 static int mdio_mux_iproc_resume(struct device *dev)
 {
 	struct iproc_mdiomux_desc *md = dev_get_drvdata(dev);
+	int rc;
 
-	clk_prepare_enable(md->core_clk);
+	rc = clk_prepare_enable(md->core_clk);
+	if (rc) {
+		dev_err(md->dev, "failed to enable core clk\n");
+		return rc;
+	}
 	mdio_mux_iproc_config(md);
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/mdio-mux-meson-g12a.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/mdio-mux-meson-g12a.c
@@ -4,6 +4,7 @@
  */
 
 #include <linux/bitfield.h>
+#include <linux/delay.h>
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/device.h>
@@ -148,6 +149,7 @@
 
 static int g12a_enable_internal_mdio(struct g12a_mdio_mux *priv)
 {
+	u32 value;
 	int ret;
 
 	/* Enable the phy clock */
@@ -161,18 +163,25 @@
 
 	/* Initialize ephy control */
 	writel(EPHY_G12A_ID, priv->regs + ETH_PHY_CNTL0);
-	writel(FIELD_PREP(PHY_CNTL1_ST_MODE, 3) |
-	       FIELD_PREP(PHY_CNTL1_ST_PHYADD, EPHY_DFLT_ADD) |
-	       FIELD_PREP(PHY_CNTL1_MII_MODE, EPHY_MODE_RMII) |
-	       PHY_CNTL1_CLK_EN |
-	       PHY_CNTL1_CLKFREQ |
-	       PHY_CNTL1_PHY_ENB,
-	       priv->regs + ETH_PHY_CNTL1);
+
+	/* Make sure we get a 0 -> 1 transition on the enable bit */
+	value = FIELD_PREP(PHY_CNTL1_ST_MODE, 3) |
+		FIELD_PREP(PHY_CNTL1_ST_PHYADD, EPHY_DFLT_ADD) |
+		FIELD_PREP(PHY_CNTL1_MII_MODE, EPHY_MODE_RMII) |
+		PHY_CNTL1_CLK_EN |
+		PHY_CNTL1_CLKFREQ;
+	writel(value, priv->regs + ETH_PHY_CNTL1);
 	writel(PHY_CNTL2_USE_INTERNAL |
 	       PHY_CNTL2_SMI_SRC_MAC |
 	       PHY_CNTL2_RX_CLK_EPHY,
 	       priv->regs + ETH_PHY_CNTL2);
 
+	value |= PHY_CNTL1_PHY_ENB;
+	writel(value, priv->regs + ETH_PHY_CNTL1);
+
+	/* The phy needs a bit of time to power up */
+	mdelay(10);
+
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/mdio-mux.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/mdio-mux.c
@@ -82,6 +82,17 @@
 
 static int parent_count;
 
+static void mdio_mux_uninit_children(struct mdio_mux_parent_bus *pb)
+{
+	struct mdio_mux_child_bus *cb = pb->children;
+
+	while (cb) {
+		mdiobus_unregister(cb->mii_bus);
+		mdiobus_free(cb->mii_bus);
+		cb = cb->next;
+	}
+}
+
 int mdio_mux_init(struct device *dev,
 		  struct device_node *mux_node,
 		  int (*switch_fn)(int cur, int desired, void *data),
@@ -144,7 +155,7 @@
 		cb = devm_kzalloc(dev, sizeof(*cb), GFP_KERNEL);
 		if (!cb) {
 			ret_val = -ENOMEM;
-			continue;
+			goto err_loop;
 		}
 		cb->bus_number = v;
 		cb->parent = pb;
@@ -152,8 +163,7 @@
 		cb->mii_bus = mdiobus_alloc();
 		if (!cb->mii_bus) {
 			ret_val = -ENOMEM;
-			devm_kfree(dev, cb);
-			continue;
+			goto err_loop;
 		}
 		cb->mii_bus->priv = cb;
 
@@ -165,11 +175,15 @@
 		cb->mii_bus->write = mdio_mux_write;
 		r = of_mdiobus_register(cb->mii_bus, child_bus_node);
 		if (r) {
+			mdiobus_free(cb->mii_bus);
+			if (r == -EPROBE_DEFER) {
+				ret_val = r;
+				goto err_loop;
+			}
+			devm_kfree(dev, cb);
 			dev_err(dev,
 				"Error: Failed to register MDIO bus for child %pOF\n",
 				child_bus_node);
-			mdiobus_free(cb->mii_bus);
-			devm_kfree(dev, cb);
 		} else {
 			cb->next = pb->children;
 			pb->children = cb;
@@ -182,6 +196,10 @@
 
 	dev_err(dev, "Error: No acceptable child buses found\n");
 	devm_kfree(dev, pb);
+
+err_loop:
+	mdio_mux_uninit_children(pb);
+	of_node_put(child_bus_node);
 err_pb_kz:
 	put_device(&parent_bus->dev);
 err_parent_bus:
@@ -193,14 +211,8 @@
 void mdio_mux_uninit(void *mux_handle)
 {
 	struct mdio_mux_parent_bus *pb = mux_handle;
-	struct mdio_mux_child_bus *cb = pb->children;
-
-	while (cb) {
-		mdiobus_unregister(cb->mii_bus);
-		mdiobus_free(cb->mii_bus);
-		cb = cb->next;
-	}
 
+	mdio_mux_uninit_children(pb);
 	put_device(&pb->mii_bus->dev);
 }
 EXPORT_SYMBOL_GPL(mdio_mux_uninit);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/mdio-octeon.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/mdio-octeon.c
@@ -72,7 +72,6 @@
 
 	return 0;
 fail_register:
-	mdiobus_free(bus->mii_bus);
 	smi_en.u64 = 0;
 	oct_mdio_writeq(smi_en.u64, bus->register_base + SMI_EN);
 	return err;
@@ -86,7 +85,6 @@
 	bus = platform_get_drvdata(pdev);
 
 	mdiobus_unregister(bus->mii_bus);
-	mdiobus_free(bus->mii_bus);
 	smi_en.u64 = 0;
 	oct_mdio_writeq(smi_en.u64, bus->register_base + SMI_EN);
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/mdio-thunder.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/mdio-thunder.c
@@ -104,6 +104,7 @@
 		if (i >= ARRAY_SIZE(nexus->buses))
 			break;
 	}
+	fwnode_handle_put(fwn);
 	return 0;
 
 err_release_regions:
@@ -126,7 +127,6 @@
 			continue;
 
 		mdiobus_unregister(bus->mii_bus);
-		mdiobus_free(bus->mii_bus);
 		oct_mdio_writeq(0, bus->register_base + SMI_EN);
 	}
 	pci_set_drvdata(pdev, NULL);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/mdio-xgene.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/mdio-xgene.c
@@ -11,6 +11,7 @@
 #include <linux/efi.h>
 #include <linux/if_vlan.h>
 #include <linux/io.h>
+#include <linux/mdio/mdio-xgene.h>
 #include <linux/module.h>
 #include <linux/of_platform.h>
 #include <linux/of_net.h>
@@ -18,7 +19,6 @@
 #include <linux/prefetch.h>
 #include <linux/phy.h>
 #include <net/ip.h>
-#include "mdio-xgene.h"
 
 static bool xgene_mdio_status;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/mdio_bus.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/mdio_bus.c
@@ -62,8 +62,8 @@
 	struct reset_control *reset = NULL;
 
 	if (mdiodev->dev.of_node)
-		reset = devm_reset_control_get_exclusive(&mdiodev->dev,
-							 "phy");
+		reset = of_reset_control_get_exclusive(mdiodev->dev.of_node,
+						       "phy");
 	if (IS_ERR(reset)) {
 		if (PTR_ERR(reset) == -ENOENT || PTR_ERR(reset) == -ENOTSUPP)
 			reset = NULL;
@@ -107,6 +107,8 @@
 	if (mdiodev->bus->mdio_map[mdiodev->addr] != mdiodev)
 		return -EINVAL;
 
+	reset_control_put(mdiodev->reset_ctrl);
+
 	mdiodev->bus->mdio_map[mdiodev->addr] = NULL;
 
 	return 0;
@@ -115,7 +117,12 @@
 
 struct phy_device *mdiobus_get_phy(struct mii_bus *bus, int addr)
 {
-	struct mdio_device *mdiodev = bus->mdio_map[addr];
+	struct mdio_device *mdiodev;
+
+	if (addr < 0 || addr >= ARRAY_SIZE(bus->mdio_map))
+		return NULL;
+
+	mdiodev = bus->mdio_map[addr];
 
 	if (!mdiodev)
 		return NULL;
@@ -383,6 +390,13 @@
 	bus->dev.groups = NULL;
 	dev_set_name(&bus->dev, "%s", bus->id);
 
+	/* We need to set state to MDIOBUS_UNREGISTERED to correctly release
+	 * the device in mdiobus_free()
+	 *
+	 * State will be updated later in this function in case of success
+	 */
+	bus->state = MDIOBUS_UNREGISTERED;
+
 	err = device_register(&bus->dev);
 	if (err) {
 		pr_err("mii_bus %s failed to register\n", bus->id);
@@ -410,7 +424,7 @@
 		bus->reset(bus);
 
 	for (i = 0; i < PHY_MAX_ADDR; i++) {
-		if ((bus->phy_mask & (1 << i)) == 0) {
+		if ((bus->phy_mask & BIT(i)) == 0) {
 			struct phy_device *phydev;
 
 			phydev = mdiobus_scan(bus, i);
@@ -424,7 +438,7 @@
 	mdiobus_setup_mdiodev_from_board_info(bus, mdiobus_create_device);
 
 	bus->state = MDIOBUS_REGISTERED;
-	pr_info("%s: probed\n", bus->name);
+	dev_dbg(&bus->dev, "probed\n");
 	return 0;
 
 error:
@@ -451,7 +465,8 @@
 	struct mdio_device *mdiodev;
 	int i;
 
-	BUG_ON(bus->state != MDIOBUS_REGISTERED);
+	if (WARN_ON_ONCE(bus->state != MDIOBUS_REGISTERED))
+		return;
 	bus->state = MDIOBUS_UNREGISTERED;
 
 	for (i = 0; i < PHY_MAX_ADDR; i++) {
@@ -743,7 +758,6 @@
 
 	return ret;
 }
-EXPORT_SYMBOL_GPL(mdio_bus_init);
 
 #if IS_ENABLED(CONFIG_PHYLIB)
 void mdio_bus_exit(void)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/mdio_device.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/mdio_device.c
@@ -180,6 +180,16 @@
 	return 0;
 }
 
+static void mdio_shutdown(struct device *dev)
+{
+	struct mdio_device *mdiodev = to_mdio_device(dev);
+	struct device_driver *drv = mdiodev->dev.driver;
+	struct mdio_driver *mdiodrv = to_mdio_driver(drv);
+
+	if (mdiodrv->shutdown)
+		mdiodrv->shutdown(mdiodev);
+}
+
 /**
  * mdio_driver_register - register an mdio_driver with the MDIO layer
  * @new_driver: new mdio_driver to register
@@ -194,6 +204,7 @@
 	mdiodrv->driver.bus = &mdio_bus_type;
 	mdiodrv->driver.probe = mdio_probe;
 	mdiodrv->driver.remove = mdio_remove;
+	mdiodrv->driver.shutdown = mdio_shutdown;
 
 	retval = driver_register(&mdiodrv->driver);
 	if (retval) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/meson-gxl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/meson-gxl.c
@@ -235,6 +235,8 @@
 		.config_intr	= meson_gxl_config_intr,
 		.suspend        = genphy_suspend,
 		.resume         = genphy_resume,
+		.read_mmd	= genphy_read_mmd_unsupported,
+		.write_mmd	= genphy_write_mmd_unsupported,
 	}, {
 		PHY_ID_MATCH_EXACT(0x01803301),
 		.name		= "Meson G12A Internal PHY",
@@ -245,6 +247,8 @@
 		.config_intr	= meson_gxl_config_intr,
 		.suspend        = genphy_suspend,
 		.resume         = genphy_resume,
+		.read_mmd	= genphy_read_mmd_unsupported,
+		.write_mmd	= genphy_write_mmd_unsupported,
 	},
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/micrel.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/micrel.c
@@ -25,6 +25,7 @@
 #include <linux/micrel_phy.h>
 #include <linux/of.h>
 #include <linux/clk.h>
+#include <linux/delay.h>
 
 /* Operation Mode Strap Override */
 #define MII_KSZPHY_OMSO				0x16
@@ -281,7 +282,7 @@
 		}
 	}
 
-	if (priv->led_mode >= 0)
+	if (priv->type && priv->led_mode >= 0)
 		kszphy_setup_led(phydev, priv->type->led_mode_reg, priv->led_mode);
 
 	return 0;
@@ -297,10 +298,10 @@
 
 	type = priv->type;
 
-	if (type->has_broadcast_disable)
+	if (type && type->has_broadcast_disable)
 		kszphy_broadcast_disable(phydev);
 
-	if (type->has_nand_tree_disable)
+	if (type && type->has_nand_tree_disable)
 		kszphy_nand_tree_disable(phydev);
 
 	return kszphy_config_reset(phydev);
@@ -342,11 +343,11 @@
 }
 
 static int ksz8051_ksz8795_match_phy_device(struct phy_device *phydev,
-					    const u32 ksz_phy_id)
+					    const bool ksz_8051)
 {
 	int ret;
 
-	if ((phydev->phy_id & MICREL_PHY_ID_MASK) != ksz_phy_id)
+	if ((phydev->phy_id & MICREL_PHY_ID_MASK) != PHY_ID_KSZ8051)
 		return 0;
 
 	ret = phy_read(phydev, MII_BMSR);
@@ -359,7 +360,7 @@
 	 * the switch does not.
 	 */
 	ret &= BMSR_ERCAP;
-	if (ksz_phy_id == PHY_ID_KSZ8051)
+	if (ksz_8051)
 		return ret;
 	else
 		return !ret;
@@ -367,7 +368,7 @@
 
 static int ksz8051_match_phy_device(struct phy_device *phydev)
 {
-	return ksz8051_ksz8795_match_phy_device(phydev, PHY_ID_KSZ8051);
+	return ksz8051_ksz8795_match_phy_device(phydev, true);
 }
 
 static int ksz8081_config_init(struct phy_device *phydev)
@@ -395,7 +396,7 @@
 
 static int ksz8795_match_phy_device(struct phy_device *phydev)
 {
-	return ksz8051_ksz8795_match_phy_device(phydev, PHY_ID_KSZ87XX);
+	return ksz8051_ksz8795_match_phy_device(phydev, false);
 }
 
 static int ksz9021_load_values_from_of(struct phy_device *phydev,
@@ -902,6 +903,12 @@
 
 	genphy_resume(phydev);
 
+	/* After switching from power-down to normal mode, an internal global
+	 * reset is automatically generated. Wait a minimum of 1 ms before
+	 * read/write access to the PHY registers.
+	 */
+	usleep_range(1000, 2000);
+
 	ret = kszphy_config_reset(phydev);
 	if (ret)
 		return ret;
@@ -932,7 +939,7 @@
 
 	priv->type = type;
 
-	if (type->led_mode_reg) {
+	if (type && type->led_mode_reg) {
 		ret = of_property_read_u32(np, "micrel,led-mode",
 				&priv->led_mode);
 		if (ret)
@@ -953,7 +960,8 @@
 		unsigned long rate = clk_get_rate(clk);
 		bool rmii_ref_clk_sel_25_mhz;
 
-		priv->rmii_ref_clk_sel = type->has_rmii_ref_clk_sel;
+		if (type)
+			priv->rmii_ref_clk_sel = type->has_rmii_ref_clk_sel;
 		rmii_ref_clk_sel_25_mhz = of_property_read_bool(np,
 				"micrel,rmii-reference-clock-select-25-mhz");
 
@@ -1033,8 +1041,9 @@
 	.get_sset_count = kszphy_get_sset_count,
 	.get_strings	= kszphy_get_strings,
 	.get_stats	= kszphy_get_stats,
-	.suspend	= genphy_suspend,
-	.resume		= genphy_resume,
+	/* No suspend/resume callbacks because of errata DS80000700A,
+	 * receiver error following software power down.
+	 */
 }, {
 	.phy_id		= PHY_ID_KSZ8041RNLI,
 	.phy_id_mask	= MICREL_PHY_ID_MASK,
@@ -1088,6 +1097,7 @@
 	.probe		= kszphy_probe,
 	.config_init	= ksz8081_config_init,
 	.ack_interrupt	= kszphy_ack_interrupt,
+	.soft_reset	= genphy_soft_reset,
 	.config_intr	= kszphy_config_intr,
 	.get_sset_count = kszphy_get_sset_count,
 	.get_strings	= kszphy_get_strings,
@@ -1140,14 +1150,28 @@
 	.suspend	= genphy_suspend,
 	.resume		= kszphy_resume,
 }, {
+	.phy_id		= PHY_ID_LAN8814,
+	.phy_id_mask	= MICREL_PHY_ID_MASK,
+	.name		= "Microchip INDY Gigabit Quad PHY",
+	.driver_data	= &ksz9021_type,
+	.probe		= kszphy_probe,
+	.soft_reset	= genphy_soft_reset,
+	.read_status	= ksz9031_read_status,
+	.get_sset_count	= kszphy_get_sset_count,
+	.get_strings	= kszphy_get_strings,
+	.get_stats	= kszphy_get_stats,
+	.suspend	= genphy_suspend,
+	.resume		= kszphy_resume,
+}, {
 	.phy_id		= PHY_ID_KSZ9131,
 	.phy_id_mask	= MICREL_PHY_ID_MASK,
 	.name		= "Microchip KSZ9131 Gigabit PHY",
 	/* PHY_GBIT_FEATURES */
 	.driver_data	= &ksz9021_type,
 	.probe		= kszphy_probe,
+	.soft_reset	= genphy_soft_reset,
 	.config_init	= ksz9131_config_init,
-	.read_status	= ksz9031_read_status,
+	.read_status	= genphy_read_status,
 	.ack_interrupt	= kszphy_ack_interrupt,
 	.config_intr	= kszphy_config_intr,
 	.get_sset_count = kszphy_get_sset_count,
@@ -1177,8 +1201,6 @@
 	.name		= "Micrel KSZ87XX Switch",
 	/* PHY_BASIC_FEATURES */
 	.config_init	= kszphy_config_init,
-	.config_aneg	= ksz8873mll_config_aneg,
-	.read_status	= ksz8873mll_read_status,
 	.match_phy_device = ksz8795_match_phy_device,
 	.suspend	= genphy_suspend,
 	.resume		= genphy_resume,
@@ -1212,6 +1234,8 @@
 	{ PHY_ID_KSZ8081, MICREL_PHY_ID_MASK },
 	{ PHY_ID_KSZ8873MLL, MICREL_PHY_ID_MASK },
 	{ PHY_ID_KSZ886X, MICREL_PHY_ID_MASK },
+	{ PHY_ID_KSZ9477, MICREL_PHY_ID_MASK },
+	{ PHY_ID_LAN8814, MICREL_PHY_ID_MASK },
 	{ }
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/microchip.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/microchip.c
@@ -326,6 +326,37 @@
 	return genphy_config_aneg(phydev);
 }
 
+static void lan88xx_link_change_notify(struct phy_device *phydev)
+{
+	int temp;
+
+	/* At forced 100 F/H mode, chip may fail to set mode correctly
+	 * when cable is switched between long(~50+m) and short one.
+	 * As workaround, set to 10 before setting to 100
+	 * at forced 100 F/H mode.
+	 */
+	if (!phydev->autoneg && phydev->speed == 100) {
+		/* disable phy interrupt */
+		temp = phy_read(phydev, LAN88XX_INT_MASK);
+		temp &= ~LAN88XX_INT_MASK_MDINTPIN_EN_;
+		phy_write(phydev, LAN88XX_INT_MASK, temp);
+
+		temp = phy_read(phydev, MII_BMCR);
+		temp &= ~(BMCR_SPEED100 | BMCR_SPEED1000);
+		phy_write(phydev, MII_BMCR, temp); /* set to 10 first */
+		temp |= BMCR_SPEED100;
+		phy_write(phydev, MII_BMCR, temp); /* set to 100 later */
+
+		/* clear pending interrupt generated while workaround */
+		temp = phy_read(phydev, LAN88XX_INT_STS);
+
+		/* enable phy interrupt back */
+		temp = phy_read(phydev, LAN88XX_INT_MASK);
+		temp |= LAN88XX_INT_MASK_MDINTPIN_EN_;
+		phy_write(phydev, LAN88XX_INT_MASK, temp);
+	}
+}
+
 static struct phy_driver microchip_phy_driver[] = {
 {
 	.phy_id		= 0x0007c130,
@@ -339,6 +370,7 @@
 
 	.config_init	= lan88xx_config_init,
 	.config_aneg	= lan88xx_config_aneg,
+	.link_change_notify = lan88xx_link_change_notify,
 
 	.ack_interrupt	= lan88xx_phy_ack_interrupt,
 	.config_intr	= lan88xx_phy_config_intr,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/microchip_t1.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/microchip_t1.c
@@ -3,9 +3,21 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/delay.h>
 #include <linux/mii.h>
 #include <linux/phy.h>
 
+/* External Register Control Register */
+#define LAN87XX_EXT_REG_CTL                     (0x14)
+#define LAN87XX_EXT_REG_CTL_RD_CTL              (0x1000)
+#define LAN87XX_EXT_REG_CTL_WR_CTL              (0x0800)
+
+/* External Register Read Data Register */
+#define LAN87XX_EXT_REG_RD_DATA                 (0x15)
+
+/* External Register Write Data Register */
+#define LAN87XX_EXT_REG_WR_DATA                 (0x16)
+
 /* Interrupt Source Register */
 #define LAN87XX_INTERRUPT_SOURCE                (0x18)
 
@@ -14,9 +26,160 @@
 #define LAN87XX_MASK_LINK_UP                    (0x0004)
 #define LAN87XX_MASK_LINK_DOWN                  (0x0002)
 
+/* phyaccess nested types */
+#define	PHYACC_ATTR_MODE_READ		0
+#define	PHYACC_ATTR_MODE_WRITE		1
+#define	PHYACC_ATTR_MODE_MODIFY		2
+
+#define	PHYACC_ATTR_BANK_SMI		0
+#define	PHYACC_ATTR_BANK_MISC		1
+#define	PHYACC_ATTR_BANK_PCS		2
+#define	PHYACC_ATTR_BANK_AFE		3
+#define	PHYACC_ATTR_BANK_MAX		7
+
 #define DRIVER_AUTHOR	"Nisar Sayed <nisar.sayed@microchip.com>"
 #define DRIVER_DESC	"Microchip LAN87XX T1 PHY driver"
 
+struct access_ereg_val {
+	u8  mode;
+	u8  bank;
+	u8  offset;
+	u16 val;
+	u16 mask;
+};
+
+static int access_ereg(struct phy_device *phydev, u8 mode, u8 bank,
+		       u8 offset, u16 val)
+{
+	u16 ereg = 0;
+	int rc = 0;
+
+	if (mode > PHYACC_ATTR_MODE_WRITE || bank > PHYACC_ATTR_BANK_MAX)
+		return -EINVAL;
+
+	if (bank == PHYACC_ATTR_BANK_SMI) {
+		if (mode == PHYACC_ATTR_MODE_WRITE)
+			rc = phy_write(phydev, offset, val);
+		else
+			rc = phy_read(phydev, offset);
+		return rc;
+	}
+
+	if (mode == PHYACC_ATTR_MODE_WRITE) {
+		ereg = LAN87XX_EXT_REG_CTL_WR_CTL;
+		rc = phy_write(phydev, LAN87XX_EXT_REG_WR_DATA, val);
+		if (rc < 0)
+			return rc;
+	} else {
+		ereg = LAN87XX_EXT_REG_CTL_RD_CTL;
+	}
+
+	ereg |= (bank << 8) | offset;
+
+	rc = phy_write(phydev, LAN87XX_EXT_REG_CTL, ereg);
+	if (rc < 0)
+		return rc;
+
+	if (mode == PHYACC_ATTR_MODE_READ)
+		rc = phy_read(phydev, LAN87XX_EXT_REG_RD_DATA);
+
+	return rc;
+}
+
+static int access_ereg_modify_changed(struct phy_device *phydev,
+				      u8 bank, u8 offset, u16 val, u16 mask)
+{
+	int new = 0, rc = 0;
+
+	if (bank > PHYACC_ATTR_BANK_MAX)
+		return -EINVAL;
+
+	rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ, bank, offset, val);
+	if (rc < 0)
+		return rc;
+
+	new = val | (rc & (mask ^ 0xFFFF));
+	rc = access_ereg(phydev, PHYACC_ATTR_MODE_WRITE, bank, offset, new);
+
+	return rc;
+}
+
+static int lan87xx_phy_init(struct phy_device *phydev)
+{
+	static const struct access_ereg_val init[] = {
+		/* TX Amplitude = 5 */
+		{PHYACC_ATTR_MODE_MODIFY, PHYACC_ATTR_BANK_AFE, 0x0B,
+		 0x000A, 0x001E},
+		/* Clear SMI interrupts */
+		{PHYACC_ATTR_MODE_READ, PHYACC_ATTR_BANK_SMI, 0x18,
+		 0, 0},
+		/* Clear MISC interrupts */
+		{PHYACC_ATTR_MODE_READ, PHYACC_ATTR_BANK_MISC, 0x08,
+		 0, 0},
+		/* Turn on TC10 Ring Oscillator (ROSC) */
+		{PHYACC_ATTR_MODE_MODIFY, PHYACC_ATTR_BANK_MISC, 0x20,
+		 0x0020, 0x0020},
+		/* WUR Detect Length to 1.2uS, LPC Detect Length to 1.09uS */
+		{PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_PCS, 0x20,
+		 0x283C, 0},
+		/* Wake_In Debounce Length to 39uS, Wake_Out Length to 79uS */
+		{PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_MISC, 0x21,
+		 0x274F, 0},
+		/* Enable Auto Wake Forward to Wake_Out, ROSC on, Sleep,
+		 * and Wake_In to wake PHY
+		 */
+		{PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_MISC, 0x20,
+		 0x80A7, 0},
+		/* Enable WUP Auto Fwd, Enable Wake on MDI, Wakeup Debouncer
+		 * to 128 uS
+		 */
+		{PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_MISC, 0x24,
+		 0xF110, 0},
+		/* Enable HW Init */
+		{PHYACC_ATTR_MODE_MODIFY, PHYACC_ATTR_BANK_SMI, 0x1A,
+		 0x0100, 0x0100},
+	};
+	int rc, i;
+
+	/* Start manual initialization procedures in Managed Mode */
+	rc = access_ereg_modify_changed(phydev, PHYACC_ATTR_BANK_SMI,
+					0x1a, 0x0000, 0x0100);
+	if (rc < 0)
+		return rc;
+
+	/* Soft Reset the SMI block */
+	rc = access_ereg_modify_changed(phydev, PHYACC_ATTR_BANK_SMI,
+					0x00, 0x8000, 0x8000);
+	if (rc < 0)
+		return rc;
+
+	/* Check to see if the self-clearing bit is cleared */
+	usleep_range(1000, 2000);
+	rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ,
+			 PHYACC_ATTR_BANK_SMI, 0x00, 0);
+	if (rc < 0)
+		return rc;
+	if ((rc & 0x8000) != 0)
+		return -ETIMEDOUT;
+
+	/* PHY Initialization */
+	for (i = 0; i < ARRAY_SIZE(init); i++) {
+		if (init[i].mode == PHYACC_ATTR_MODE_MODIFY) {
+			rc = access_ereg_modify_changed(phydev, init[i].bank,
+							init[i].offset,
+							init[i].val,
+							init[i].mask);
+		} else {
+			rc = access_ereg(phydev, init[i].mode, init[i].bank,
+					 init[i].offset, init[i].val);
+		}
+		if (rc < 0)
+			return rc;
+	}
+
+	return 0;
+}
+
 static int lan87xx_phy_config_intr(struct phy_device *phydev)
 {
 	int rc, val = 0;
@@ -40,6 +203,13 @@
 	return rc < 0 ? rc : 0;
 }
 
+static int lan87xx_config_init(struct phy_device *phydev)
+{
+	int rc = lan87xx_phy_init(phydev);
+
+	return rc < 0 ? rc : 0;
+}
+
 static struct phy_driver microchip_t1_phy_driver[] = {
 	{
 		.phy_id         = 0x0007c150,
@@ -48,6 +218,7 @@
 
 		.features       = PHY_BASIC_T1_FEATURES,
 
+		.config_init	= lan87xx_config_init,
 		.config_aneg    = genphy_config_aneg,
 
 		.ack_interrupt  = lan87xx_phy_ack_interrupt,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/mscc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/mscc.c
@@ -18,17 +18,6 @@
 #include <linux/netdevice.h>
 #include <dt-bindings/net/mscc-phy-vsc8531.h>
 
-enum rgmii_rx_clock_delay {
-	RGMII_RX_CLK_DELAY_0_2_NS = 0,
-	RGMII_RX_CLK_DELAY_0_8_NS = 1,
-	RGMII_RX_CLK_DELAY_1_1_NS = 2,
-	RGMII_RX_CLK_DELAY_1_7_NS = 3,
-	RGMII_RX_CLK_DELAY_2_0_NS = 4,
-	RGMII_RX_CLK_DELAY_2_3_NS = 5,
-	RGMII_RX_CLK_DELAY_2_6_NS = 6,
-	RGMII_RX_CLK_DELAY_3_4_NS = 7
-};
-
 /* Microsemi VSC85xx PHY registers */
 /* IEEE 802. Std Registers */
 #define MSCC_PHY_BYPASS_CONTROL		  18
@@ -163,6 +152,7 @@
 #define MSCC_PHY_RGMII_CNTL		  20
 #define RGMII_RX_CLK_DELAY_MASK		  0x0070
 #define RGMII_RX_CLK_DELAY_POS		  4
+#define RGMII_TX_CLK_DELAY_MASK		  0x0007
 
 #define MSCC_PHY_WOL_LOWER_MAC_ADDR	  21
 #define MSCC_PHY_WOL_MID_MAC_ADDR	  22
@@ -256,6 +246,7 @@
 #define PHY_ID_VSC8514			  0x00070670
 #define PHY_ID_VSC8530			  0x00070560
 #define PHY_ID_VSC8531			  0x00070570
+#define PHY_ID_VSC8531_02		  0x00070572
 #define PHY_ID_VSC8540			  0x00070760
 #define PHY_ID_VSC8541			  0x00070770
 #define PHY_ID_VSC8574			  0x000704a0
@@ -302,11 +293,11 @@
 				BIT(VSC8531_FORCE_LED_OFF) | \
 				BIT(VSC8531_FORCE_LED_ON))
 
-#define MSCC_VSC8584_REVB_INT8051_FW		"mscc_vsc8584_revb_int8051_fb48.bin"
+#define MSCC_VSC8584_REVB_INT8051_FW		"microchip/mscc_vsc8584_revb_int8051_fb48.bin"
 #define MSCC_VSC8584_REVB_INT8051_FW_START_ADDR	0xe800
 #define MSCC_VSC8584_REVB_INT8051_FW_CRC	0xfb48
 
-#define MSCC_VSC8574_REVB_INT8051_FW		"mscc_vsc8574_revb_int8051_29e8.bin"
+#define MSCC_VSC8574_REVB_INT8051_FW		"microchip/mscc_vsc8574_revb_int8051_29e8.bin"
 #define MSCC_VSC8574_REVB_INT8051_FW_START_ADDR	0x4000
 #define MSCC_VSC8574_REVB_INT8051_FW_CRC	0x29e8
 
@@ -416,6 +407,8 @@
 	 * package.
 	 */
 	unsigned int base_addr;
+	u32 rx_delay;
+	u32 tx_delay;
 };
 
 #ifdef CONFIG_OF_MDIO
@@ -846,15 +839,17 @@
 {
 	int rc;
 	u16 reg_val;
+	struct vsc8531_private *vsc8531 = phydev->priv;
 
 	phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
 	mutex_lock(&phydev->lock);
 
-	reg_val = RGMII_RX_CLK_DELAY_1_1_NS << RGMII_RX_CLK_DELAY_POS;
+	reg_val = (vsc8531->rx_delay << RGMII_RX_CLK_DELAY_POS) |
+		  vsc8531->tx_delay;
 
 	rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED_2,
-			      MSCC_PHY_RGMII_CNTL, RGMII_RX_CLK_DELAY_MASK,
-			      reg_val);
+			      MSCC_PHY_RGMII_CNTL, (RGMII_RX_CLK_DELAY_MASK |
+			      RGMII_TX_CLK_DELAY_MASK), reg_val);
 
 	mutex_unlock(&phydev->lock);
 
@@ -1736,6 +1731,17 @@
 {
 	int rc, i, phy_id;
 	struct vsc8531_private *vsc8531 = phydev->priv;
+	struct device_node *of_node = phydev->mdio.dev.of_node;
+
+	rc = of_property_read_u32(of_node, "vsc8531,rx-delay",
+				  &vsc8531->rx_delay);
+	if (rc < 0)
+		vsc8531->rx_delay = VSC8531_RGMII_CLK_DELAY_1_1_NS;
+
+	rc = of_property_read_u32(of_node, "vsc8531,tx-delay",
+				  &vsc8531->tx_delay);
+	if (rc < 0)
+		vsc8531->tx_delay = VSC8531_RGMII_CLK_DELAY_0_2_NS;
 
 	rc = vsc85xx_default_config(phydev);
 	if (rc)
@@ -2395,6 +2401,31 @@
 	.get_stats      = &vsc85xx_get_stats,
 },
 {
+	.phy_id		= PHY_ID_VSC8531_02,
+	.name		= "Microsemi VSC8531-02",
+	.phy_id_mask	= 0xfffffff0,
+	/* PHY_GBIT_FEATURES */
+	.soft_reset	= &genphy_soft_reset,
+	.config_init	= &vsc85xx_config_init,
+	.config_aneg	= &vsc85xx_config_aneg,
+	.aneg_done	= &genphy_aneg_done,
+	.read_status	= &vsc85xx_read_status,
+	.ack_interrupt	= &vsc85xx_ack_interrupt,
+	.config_intr	= &vsc85xx_config_intr,
+	.suspend	= &genphy_suspend,
+	.resume		= &genphy_resume,
+	.probe		= &vsc85xx_probe,
+	.set_wol	= &vsc85xx_wol_set,
+	.get_wol	= &vsc85xx_wol_get,
+	.get_tunable	= &vsc85xx_get_tunable,
+	.set_tunable	= &vsc85xx_set_tunable,
+	.read_page	= &vsc85xx_phy_read_page,
+	.write_page	= &vsc85xx_phy_write_page,
+	.get_sset_count = &vsc85xx_get_sset_count,
+	.get_strings	= &vsc85xx_get_strings,
+	.get_stats	= &vsc85xx_get_stats,
+},
+{
 	.phy_id		= PHY_ID_VSC8540,
 	.name		= "Microsemi FE VSC8540 SyncE",
 	.phy_id_mask	= 0xfffffff0,
@@ -2503,6 +2534,7 @@
 	{ PHY_ID_VSC8514, 0xfffffff0, },
 	{ PHY_ID_VSC8530, 0xfffffff0, },
 	{ PHY_ID_VSC8531, 0xfffffff0, },
+	{ PHY_ID_VSC8531_02, 0xfffffff0, },
 	{ PHY_ID_VSC8540, 0xfffffff0, },
 	{ PHY_ID_VSC8541, 0xfffffff0, },
 	{ PHY_ID_VSC8574, 0xfffffff0, },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/phy-c45.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/phy-c45.c
@@ -239,9 +239,10 @@
 
 		/* The link state is latched low so that momentary link
 		 * drops can be detected. Do not double-read the status
-		 * in polling mode to detect such short link drops.
+		 * in polling mode to detect such short link drops except
+		 * the link was already down.
 		 */
-		if (!phy_polling_mode(phydev)) {
+		if (!phy_polling_mode(phydev) || !phydev->link) {
 			val = phy_read_mmd(phydev, devad, MDIO_STAT1);
 			if (val < 0)
 				return val;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/phy-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/phy-core.c
@@ -128,11 +128,11 @@
 	PHY_SETTING(   2500, FULL,   2500baseT_Full		),
 	PHY_SETTING(   2500, FULL,   2500baseX_Full		),
 	/* 1G */
-	PHY_SETTING(   1000, FULL,   1000baseKX_Full		),
 	PHY_SETTING(   1000, FULL,   1000baseT_Full		),
 	PHY_SETTING(   1000, HALF,   1000baseT_Half		),
 	PHY_SETTING(   1000, FULL,   1000baseT1_Full		),
 	PHY_SETTING(   1000, FULL,   1000baseX_Full		),
+	PHY_SETTING(   1000, FULL,   1000baseKX_Full		),
 	/* 100M */
 	PHY_SETTING(    100, FULL,    100baseT_Full		),
 	PHY_SETTING(    100, FULL,    100baseT1_Full		),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/phy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/phy.c
@@ -116,10 +116,15 @@
  */
 static int phy_clear_interrupt(struct phy_device *phydev)
 {
-	if (phydev->drv->ack_interrupt)
-		return phydev->drv->ack_interrupt(phydev);
+	int ret = 0;
 
-	return 0;
+	if (phydev->drv->ack_interrupt) {
+		mutex_lock(&phydev->lock);
+		ret = phydev->drv->ack_interrupt(phydev);
+		mutex_unlock(&phydev->lock);
+	}
+
+	return ret;
 }
 
 /**
@@ -345,15 +350,16 @@
 
 	phydev->autoneg = autoneg;
 
-	phydev->speed = speed;
+	if (autoneg == AUTONEG_DISABLE) {
+		phydev->speed = speed;
+		phydev->duplex = duplex;
+	}
 
 	linkmode_copy(phydev->advertising, advertising);
 
 	linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
 			 phydev->advertising, autoneg == AUTONEG_ENABLE);
 
-	phydev->duplex = duplex;
-
 	phydev->mdix_ctrl = cmd->base.eth_tp_mdix_ctrl;
 
 	/* Restart the PHY */
@@ -366,6 +372,7 @@
 void phy_ethtool_ksettings_get(struct phy_device *phydev,
 			       struct ethtool_link_ksettings *cmd)
 {
+	mutex_lock(&phydev->lock);
 	linkmode_copy(cmd->link_modes.supported, phydev->supported);
 	linkmode_copy(cmd->link_modes.advertising, phydev->advertising);
 	linkmode_copy(cmd->link_modes.lp_advertising, phydev->lp_advertising);
@@ -382,6 +389,7 @@
 	cmd->base.autoneg = phydev->autoneg;
 	cmd->base.eth_tp_mdix_ctrl = phydev->mdix_ctrl;
 	cmd->base.eth_tp_mdix = phydev->mdix;
+	mutex_unlock(&phydev->lock);
 }
 EXPORT_SYMBOL(phy_ethtool_ksettings_get);
 
@@ -552,7 +560,7 @@
 }
 
 /**
- * phy_start_aneg - start auto-negotiation for this PHY device
+ * _phy_start_aneg - start auto-negotiation for this PHY device
  * @phydev: the phy_device struct
  *
  * Description: Sanitizes the settings (if we're not autonegotiating
@@ -560,25 +568,43 @@
  *   If the PHYCONTROL Layer is operating, we change the state to
  *   reflect the beginning of Auto-negotiation or forcing.
  */
-int phy_start_aneg(struct phy_device *phydev)
+static int _phy_start_aneg(struct phy_device *phydev)
 {
 	int err;
 
+	lockdep_assert_held(&phydev->lock);
+
 	if (!phydev->drv)
 		return -EIO;
 
-	mutex_lock(&phydev->lock);
-
 	if (AUTONEG_DISABLE == phydev->autoneg)
 		phy_sanitize_settings(phydev);
 
 	err = phy_config_aneg(phydev);
 	if (err < 0)
-		goto out_unlock;
+		return err;
 
 	if (phy_is_started(phydev))
 		err = phy_check_link_status(phydev);
-out_unlock:
+
+	return err;
+}
+
+/**
+ * phy_start_aneg - start auto-negotiation for this PHY device
+ * @phydev: the phy_device struct
+ *
+ * Description: Sanitizes the settings (if we're not autonegotiating
+ *   them), and then calls the driver's config_aneg function.
+ *   If the PHYCONTROL Layer is operating, we change the state to
+ *   reflect the beginning of Auto-negotiation or forcing.
+ */
+int phy_start_aneg(struct phy_device *phydev)
+{
+	int err;
+
+	mutex_lock(&phydev->lock);
+	err = _phy_start_aneg(phydev);
 	mutex_unlock(&phydev->lock);
 
 	return err;
@@ -740,6 +766,36 @@
 }
 
 /**
+ * phy_did_interrupt - Checks if the PHY generated an interrupt
+ * @phydev: target phy_device struct
+ */
+static int phy_did_interrupt(struct phy_device *phydev)
+{
+	int ret;
+
+	mutex_lock(&phydev->lock);
+	ret = phydev->drv->did_interrupt(phydev);
+	mutex_unlock(&phydev->lock);
+
+	return ret;
+}
+
+/**
+ * phy_handle_interrupt - PHY specific interrupt handler
+ * @phydev: target phy_device struct
+ */
+static int phy_handle_interrupt(struct phy_device *phydev)
+{
+	int ret;
+
+	mutex_lock(&phydev->lock);
+	ret = phydev->drv->handle_interrupt(phydev);
+	mutex_unlock(&phydev->lock);
+
+	return ret;
+}
+
+/**
  * phy_interrupt - PHY interrupt handler
  * @irq: interrupt line
  * @phy_dat: phy_device pointer
@@ -750,18 +806,19 @@
 {
 	struct phy_device *phydev = phy_dat;
 
-	if (phydev->drv->did_interrupt && !phydev->drv->did_interrupt(phydev))
+	if (phydev->drv->did_interrupt && !phy_did_interrupt(phydev))
 		return IRQ_NONE;
 
 	if (phydev->drv->handle_interrupt) {
-		if (phydev->drv->handle_interrupt(phydev))
+		if (phy_handle_interrupt(phydev))
 			goto phy_err;
 	} else {
 		/* reschedule state queue work to run as soon as possible */
 		phy_trigger_machine(phydev);
 	}
 
-	if (phy_clear_interrupt(phydev))
+	/* did_interrupt() may have cleared the interrupt already */
+	if (!phydev->drv->did_interrupt && phy_clear_interrupt(phydev))
 		goto phy_err;
 	return IRQ_HANDLED;
 
@@ -833,7 +890,7 @@
  */
 void phy_stop(struct phy_device *phydev)
 {
-	if (!phy_is_started(phydev)) {
+	if (!phy_is_started(phydev) && phydev->state != PHY_DOWN) {
 		WARN(1, "called from state %s\n",
 		     phy_state_to_str(phydev->state));
 		return;
@@ -845,9 +902,6 @@
 
 	mutex_unlock(&phydev->lock);
 
-	phy_state_machine(&phydev->state_queue.work);
-	phy_stop_machine(phydev);
-
 	/* Cannot call flush_scheduled_work() here as desired because
 	 * of rtnl_lock(), but PHY_HALTED shall guarantee irq handler
 	 * will not reenable interrupts.
@@ -1159,9 +1213,11 @@
 		/* Restart autonegotiation so the new modes get sent to the
 		 * link partner.
 		 */
-		ret = phy_restart_aneg(phydev);
-		if (ret < 0)
-			return ret;
+		if (phydev->autoneg == AUTONEG_ENABLE) {
+			ret = phy_restart_aneg(phydev);
+			if (ret < 0)
+				return ret;
+		}
 	}
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/phy_device.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/phy_device.c
@@ -246,7 +246,7 @@
 	 * MDIO bus driver and clock gated at this point.
 	 */
 	if (!netdev)
-		return !phydev->suspended;
+		goto out;
 
 	if (netdev->wol_enabled)
 		return false;
@@ -266,7 +266,8 @@
 	if (device_may_wakeup(&netdev->dev))
 		return false;
 
-	return true;
+out:
+	return !phydev->suspended;
 }
 
 static int mdio_bus_phy_suspend(struct device *dev)
@@ -284,6 +285,8 @@
 	if (!mdio_bus_phy_may_suspend(phydev))
 		return 0;
 
+	phydev->suspended_by_mdio_bus = 1;
+
 	return phy_suspend(phydev);
 }
 
@@ -292,9 +295,11 @@
 	struct phy_device *phydev = to_phy_device(dev);
 	int ret;
 
-	if (!mdio_bus_phy_may_suspend(phydev))
+	if (!phydev->suspended_by_mdio_bus)
 		goto no_resume;
 
+	phydev->suspended_by_mdio_bus = 0;
+
 	ret = phy_resume(phydev);
 	if (ret < 0)
 		return ret;
@@ -488,7 +493,7 @@
 
 	if (phydev->is_c45) {
 		for (i = 1; i < num_ids; i++) {
-			if (!(phydev->c45_ids.devices_in_package & (1 << i)))
+			if (phydev->c45_ids.device_ids[i] == 0xffffffff)
 				continue;
 
 			if ((phydrv->phy_id & phydrv->phy_id_mask) ==
@@ -552,7 +557,7 @@
 	.pm = MDIO_BUS_PHY_PM_OPS,
 };
 
-static int phy_request_driver_module(struct phy_device *dev, int phy_id)
+static int phy_request_driver_module(struct phy_device *dev, u32 phy_id)
 {
 	int ret;
 
@@ -564,15 +569,15 @@
 	 * then modprobe isn't available.
 	 */
 	if (IS_ENABLED(CONFIG_MODULES) && ret < 0 && ret != -ENOENT) {
-		phydev_err(dev, "error %d loading PHY driver module for ID 0x%08x\n",
-			   ret, phy_id);
+		phydev_err(dev, "error %d loading PHY driver module for ID 0x%08lx\n",
+			   ret, (unsigned long)phy_id);
 		return ret;
 	}
 
 	return 0;
 }
 
-struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id,
+struct phy_device *phy_device_create(struct mii_bus *bus, int addr, u32 phy_id,
 				     bool is_c45,
 				     struct phy_c45_device_ids *c45_ids)
 {
@@ -596,8 +601,8 @@
 	mdiodev->device_free = phy_mdio_device_free;
 	mdiodev->device_remove = phy_mdio_device_remove;
 
-	dev->speed = 0;
-	dev->duplex = -1;
+	dev->speed = SPEED_UNKNOWN;
+	dev->duplex = DUPLEX_UNKNOWN;
 	dev->pause = 0;
 	dev->asym_pause = 0;
 	dev->link = 0;
@@ -610,7 +615,9 @@
 	if (c45_ids)
 		dev->c45_ids = *c45_ids;
 	dev->irq = bus->irq[addr];
+
 	dev_set_name(&mdiodev->dev, PHY_ID_FMT, bus->id, addr);
+	device_initialize(&mdiodev->dev);
 
 	dev->state = PHY_DOWN;
 
@@ -632,7 +639,7 @@
 		int i;
 
 		for (i = 1; i < num_ids; i++) {
-			if (!(c45_ids->devices_in_package & (1 << i)))
+			if (c45_ids->device_ids[i] == 0xffffffff)
 				continue;
 
 			ret = phy_request_driver_module(dev,
@@ -644,10 +651,8 @@
 		ret = phy_request_driver_module(dev, phy_id);
 	}
 
-	if (!ret) {
-		device_initialize(&mdiodev->dev);
-	} else {
-		kfree(dev);
+	if (ret) {
+		put_device(&mdiodev->dev);
 		dev = ERR_PTR(ret);
 	}
 
@@ -792,8 +797,10 @@
 
 	/* Grab the bits from PHYIR2, and put them in the lower half */
 	phy_reg = mdiobus_read(bus, addr, MII_PHYSID2);
-	if (phy_reg < 0)
-		return -EIO;
+	if (phy_reg < 0) {
+		/* returning -ENODEV doesn't stop bus scanning */
+		return (phy_reg == -EIO || phy_reg == -ENODEV) ? -ENODEV : -EIO;
+	}
 
 	*phy_id |= phy_reg;
 
@@ -812,10 +819,13 @@
  */
 struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45)
 {
-	struct phy_c45_device_ids c45_ids = {0};
+	struct phy_c45_device_ids c45_ids;
 	u32 phy_id = 0;
 	int r;
 
+	c45_ids.devices_in_package = 0;
+	memset(c45_ids.device_ids, 0xff, sizeof(c45_ids.device_ids));
+
 	r = get_phy_id(bus, addr, &phy_id, is_c45, &c45_ids);
 	if (r)
 		return ERR_PTR(r);
@@ -1018,6 +1028,8 @@
 	if (phy_interrupt_is_valid(phydev))
 		phy_free_interrupt(phydev);
 
+	phy_stop_machine(phydev);
+
 	phydev->adjust_link = NULL;
 
 	phy_detach(phydev);
@@ -1302,6 +1314,7 @@
 
 error_module_put:
 	module_put(d->driver->owner);
+	d->driver = NULL;
 error_put_device:
 	put_device(d);
 	if (ndev_owner != bus->owner)
@@ -1411,7 +1424,8 @@
 
 	phy_led_triggers_unregister(phydev);
 
-	module_put(phydev->mdio.dev.driver->owner);
+	if (phydev->mdio.dev.driver)
+		module_put(phydev->mdio.dev.driver->owner);
 
 	/* If the device had no specific driver before (i.e. - it
 	 * was using the generic driver), we unbind the device
@@ -1422,6 +1436,9 @@
 	    phy_driver_is_genphy_10g(phydev))
 		device_release_driver(&phydev->mdio.dev);
 
+	/* Assert the reset signal */
+	phy_device_reset(phydev, 1);
+
 	/*
 	 * The phydev might go away on the put_device() below, so avoid
 	 * a use-after-free bug by reading the underlying bus first.
@@ -1433,9 +1450,6 @@
 		ndev_owner = dev->dev.parent->driver->owner;
 	if (ndev_owner != bus->owner)
 		module_put(bus->owner);
-
-	/* Assert the reset signal */
-	phy_device_reset(phydev, 1);
 }
 EXPORT_SYMBOL(phy_detach);
 
@@ -1755,9 +1769,10 @@
 
 	/* The link state is latched low so that momentary link
 	 * drops can be detected. Do not double-read the status
-	 * in polling mode to detect such short link drops.
+	 * in polling mode to detect such short link drops except
+	 * the link was already down.
 	 */
-	if (!phy_polling_mode(phydev)) {
+	if (!phy_polling_mode(phydev) || !phydev->link) {
 		status = phy_read(phydev, MII_BMSR);
 		if (status < 0)
 			return status;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/phylink.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/phylink.c
@@ -444,8 +444,7 @@
 
 	pl->cur_interface = link_state.interface;
 	pl->ops->mac_link_up(pl->config, pl->link_an_mode,
-			     pl->phy_state.interface,
-			     pl->phydev);
+			     pl->cur_interface, pl->phydev);
 
 	if (ndev)
 		netif_carrier_on(ndev);
@@ -583,6 +582,11 @@
 		return ret;
 	}
 
+	if (!fwnode_device_is_available(ref.fwnode)) {
+		fwnode_handle_put(ref.fwnode);
+		return 0;
+	}
+
 	pl->sfp_bus = sfp_register_upstream(ref.fwnode, pl, &sfp_phylink_ops);
 	if (!pl->sfp_bus)
 		return -ENOMEM;
@@ -1332,7 +1336,7 @@
 		return -EOPNOTSUPP;
 
 	if (!phylink_test(pl->supported, Asym_Pause) &&
-	    !pause->autoneg && pause->rx_pause != pause->tx_pause)
+	    pause->rx_pause != pause->tx_pause)
 		return -EINVAL;
 
 	config->pause &= ~(MLO_PAUSE_AN | MLO_PAUSE_TXRX_MASK);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/realtek.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/realtek.c
@@ -171,7 +171,9 @@
 
 static int rtl8211f_config_init(struct phy_device *phydev)
 {
+	struct device *dev = &phydev->mdio.dev;
 	u16 val;
+	int ret;
 
 	/* enable TX-delay for rgmii-{id,txid}, and disable it for rgmii and
 	 * rgmii-rxid. The RX-delay can be enabled by the external RXDLY pin.
@@ -189,7 +191,22 @@
 		return 0;
 	}
 
-	return phy_modify_paged(phydev, 0xd08, 0x11, RTL8211F_TX_DELAY, val);
+	ret = phy_modify_paged_changed(phydev, 0xd08, 0x11, RTL8211F_TX_DELAY,
+				       val);
+	if (ret < 0) {
+		dev_err(dev, "Failed to update the TX delay register\n");
+		return ret;
+	} else if (ret) {
+		dev_dbg(dev,
+			"%s 2ns TX delay (and changing the value from pin-strapping RXD1 or the bootloader)\n",
+			val ? "Enabling" : "Disabling");
+	} else {
+		dev_dbg(dev,
+			"2ns TX delay was already %s (by pin-strapping RXD1 or bootloader configuration)\n",
+			val ? "enabled" : "disabled");
+	}
+
+	return 0;
 }
 
 static int rtl8211e_config_init(struct phy_device *phydev)
@@ -438,6 +455,15 @@
 		.suspend	= genphy_suspend,
 		.resume		= genphy_resume,
 		.read_page	= rtl821x_read_page,
+		.write_page	= rtl821x_write_page,
+	}, {
+		PHY_ID_MATCH_MODEL(0x001cc880),
+		.name		= "RTL8208 Fast Ethernet",
+		.read_mmd	= genphy_read_mmd_unsupported,
+		.write_mmd	= genphy_write_mmd_unsupported,
+		.suspend	= genphy_suspend,
+		.resume		= genphy_resume,
+		.read_page	= rtl821x_read_page,
 		.write_page	= rtl821x_write_page,
 	}, {
 		PHY_ID_MATCH_EXACT(0x001cc910),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/sfp-bus.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/sfp-bus.c
@@ -9,6 +9,12 @@
 
 #include "sfp.h"
 
+struct sfp_quirk {
+	const char *vendor;
+	const char *part;
+	void (*modes)(const struct sfp_eeprom_id *id, unsigned long *modes);
+};
+
 /**
  * struct sfp_bus - internal representation of a sfp bus
  */
@@ -21,6 +27,7 @@
 	const struct sfp_socket_ops *socket_ops;
 	struct device *sfp_dev;
 	struct sfp *sfp;
+	const struct sfp_quirk *sfp_quirk;
 
 	const struct sfp_upstream_ops *upstream_ops;
 	void *upstream;
@@ -30,6 +37,71 @@
 	bool started;
 };
 
+static void sfp_quirk_2500basex(const struct sfp_eeprom_id *id,
+				unsigned long *modes)
+{
+	phylink_set(modes, 2500baseX_Full);
+}
+
+static const struct sfp_quirk sfp_quirks[] = {
+	{
+		// Alcatel Lucent G-010S-P can operate at 2500base-X, but
+		// incorrectly report 2500MBd NRZ in their EEPROM
+		.vendor = "ALCATELLUCENT",
+		.part = "G010SP",
+		.modes = sfp_quirk_2500basex,
+	}, {
+		// Alcatel Lucent G-010S-A can operate at 2500base-X, but
+		// report 3.2GBd NRZ in their EEPROM
+		.vendor = "ALCATELLUCENT",
+		.part = "3FE46541AA",
+		.modes = sfp_quirk_2500basex,
+	}, {
+		// Huawei MA5671A can operate at 2500base-X, but report 1.2GBd
+		// NRZ in their EEPROM
+		.vendor = "HUAWEI",
+		.part = "MA5671A",
+		.modes = sfp_quirk_2500basex,
+	},
+};
+
+static size_t sfp_strlen(const char *str, size_t maxlen)
+{
+	size_t size, i;
+
+	/* Trailing characters should be filled with space chars */
+	for (i = 0, size = 0; i < maxlen; i++)
+		if (str[i] != ' ')
+			size = i + 1;
+
+	return size;
+}
+
+static bool sfp_match(const char *qs, const char *str, size_t len)
+{
+	if (!qs)
+		return true;
+	if (strlen(qs) != len)
+		return false;
+	return !strncmp(qs, str, len);
+}
+
+static const struct sfp_quirk *sfp_lookup_quirk(const struct sfp_eeprom_id *id)
+{
+	const struct sfp_quirk *q;
+	unsigned int i;
+	size_t vs, ps;
+
+	vs = sfp_strlen(id->base.vendor_name, ARRAY_SIZE(id->base.vendor_name));
+	ps = sfp_strlen(id->base.vendor_pn, ARRAY_SIZE(id->base.vendor_pn));
+
+	for (i = 0, q = sfp_quirks; i < ARRAY_SIZE(sfp_quirks); i++, q++)
+		if (sfp_match(q->vendor, id->base.vendor_name, vs) &&
+		    sfp_match(q->part, id->base.vendor_pn, ps))
+			return q;
+
+	return NULL;
+}
 /**
  * sfp_parse_port() - Parse the EEPROM base ID, setting the port type
  * @bus: a pointer to the &struct sfp_bus structure for the sfp module
@@ -233,6 +305,9 @@
 			phylink_set(modes, 1000baseX_Full);
 	}
 
+	if (bus->sfp_quirk)
+		bus->sfp_quirk->modes(id, modes);
+
 	bitmap_or(support, support, modes, __ETHTOOL_LINK_MODE_MASK_NBITS);
 
 	phylink_set(support, Autoneg);
@@ -553,6 +628,8 @@
 	const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus);
 	int ret = 0;
 
+	bus->sfp_quirk = sfp_lookup_quirk(id);
+
 	if (ops && ops->module_insert)
 		ret = ops->module_insert(bus->upstream, id);
 
@@ -566,6 +643,8 @@
 
 	if (ops && ops->module_remove)
 		ops->module_remove(bus->upstream);
+
+	bus->sfp_quirk = NULL;
 }
 EXPORT_SYMBOL_GPL(sfp_module_remove);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/sfp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/sfp.c
@@ -7,6 +7,7 @@
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
 #include <linux/jiffies.h>
+#include <linux/mdio/mdio-i2c.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/of.h>
@@ -16,7 +17,6 @@
 #include <linux/slab.h>
 #include <linux/workqueue.h>
 
-#include "mdio-i2c.h"
 #include "sfp.h"
 #include "swphy.h"
 
@@ -115,7 +115,7 @@
 	[SFP_S_LINK_UP] = "link_up",
 	[SFP_S_TX_FAULT] = "tx_fault",
 	[SFP_S_REINIT] = "reinit",
-	[SFP_S_TX_DISABLE] = "rx_disable",
+	[SFP_S_TX_DISABLE] = "tx_disable",
 };
 
 static const char *sm_state_to_str(unsigned short sm_state)
@@ -1878,7 +1878,7 @@
 
 	platform_set_drvdata(pdev, sfp);
 
-	err = devm_add_action(sfp->dev, sfp_cleanup, sfp);
+	err = devm_add_action_or_reset(sfp->dev, sfp_cleanup, sfp);
 	if (err < 0)
 		return err;
 
@@ -1970,7 +1970,8 @@
 			continue;
 
 		sfp->gpio_irq[i] = gpiod_to_irq(sfp->gpio[i]);
-		if (!sfp->gpio_irq[i]) {
+		if (sfp->gpio_irq[i] < 0) {
+			sfp->gpio_irq[i] = 0;
 			poll = true;
 			continue;
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/smsc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/smsc.c
@@ -108,8 +108,11 @@
 static int lan87xx_read_status(struct phy_device *phydev)
 {
 	struct smsc_phy_priv *priv = phydev->priv;
+	int err;
 
-	int err = genphy_read_status(phydev);
+	err = genphy_read_status(phydev);
+	if (err)
+		return err;
 
 	if (!phydev->link && priv->energy_enable) {
 		int i;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/vitesse.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/vitesse.c
@@ -232,16 +232,6 @@
 	return 0;
 }
 
-static int vsc73xx_config_aneg(struct phy_device *phydev)
-{
-	/* The VSC73xx switches does not like to be instructed to
-	 * do autonegotiation in any way, it prefers that you just go
-	 * with the power-on/reset defaults. Writing some registers will
-	 * just make autonegotiation permanently fail.
-	 */
-	return 0;
-}
-
 /* This adds a skew for both TX and RX clocks, so the skew should only be
  * applied to "rgmii-id" interfaces. It may not work as expected
  * on "rgmii-txid", "rgmii-rxid" or "rgmii" interfaces. */
@@ -424,7 +414,6 @@
 	.phy_id_mask    = 0x000ffff0,
 	/* PHY_GBIT_FEATURES */
 	.config_init    = vsc738x_config_init,
-	.config_aneg    = vsc73xx_config_aneg,
 	.read_page      = vsc73xx_read_page,
 	.write_page     = vsc73xx_write_page,
 }, {
@@ -433,7 +422,6 @@
 	.phy_id_mask    = 0x000ffff0,
 	/* PHY_GBIT_FEATURES */
 	.config_init    = vsc738x_config_init,
-	.config_aneg    = vsc73xx_config_aneg,
 	.read_page      = vsc73xx_read_page,
 	.write_page     = vsc73xx_write_page,
 }, {
@@ -442,7 +430,6 @@
 	.phy_id_mask    = 0x000ffff0,
 	/* PHY_GBIT_FEATURES */
 	.config_init    = vsc739x_config_init,
-	.config_aneg    = vsc73xx_config_aneg,
 	.read_page      = vsc73xx_read_page,
 	.write_page     = vsc73xx_write_page,
 }, {
@@ -451,7 +438,6 @@
 	.phy_id_mask    = 0x000ffff0,
 	/* PHY_GBIT_FEATURES */
 	.config_init    = vsc739x_config_init,
-	.config_aneg    = vsc73xx_config_aneg,
 	.read_page      = vsc73xx_read_page,
 	.write_page     = vsc73xx_write_page,
 }, {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/xilinx_gmii2rgmii.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/xilinx_gmii2rgmii.c
@@ -52,9 +52,7 @@
 	else
 		val |= BMCR_SPEED10;
 
-	mdiobus_write(bus, addr, XILINX_GMII2RGMII_REG, val);
-
-	return 0;
+	return mdiobus_write(bus, addr, XILINX_GMII2RGMII_REG, val);
 }
 
 static int xgmiitorgmii_probe(struct mdio_device *mdiodev)
@@ -82,6 +80,7 @@
 
 	if (!priv->phy_dev->drv) {
 		dev_info(dev, "Attached phy not ready\n");
+		put_device(&priv->phy_dev->mdio.dev);
 		return -EPROBE_DEFER;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/phy/xilinx_phy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/phy/xilinx_phy.c
@@ -0,0 +1,160 @@
+/* Xilinx PCS/PMA Core phy driver
+ *
+ * Copyright (C) 2015 Xilinx, Inc.
+ *
+ * Description:
+ * This driver is developed for PCS/PMA Core.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
+#include <linux/of.h>
+#include <linux/xilinx_phy.h>
+
+#define MII_PHY_STATUS_SPD_MASK		0x0C00
+#define MII_PHY_STATUS_FULLDUPLEX	0x1000
+#define MII_PHY_STATUS_1000		0x0800
+#define MII_PHY_STATUS_100		0x0400
+#define XPCSPMA_PHY_CTRL_ISOLATE_DISABLE 0xFBFF
+
+static int xilinxphy_read_status(struct phy_device *phydev)
+{
+	int err;
+	int status = 0;
+
+	/* Update the link, but return if there
+	 * was an error
+	 */
+	err = genphy_update_link(phydev);
+	if (err)
+		return err;
+
+	if (phydev->autoneg == AUTONEG_ENABLE) {
+		status = phy_read(phydev, MII_LPA);
+
+		if (status & MII_PHY_STATUS_FULLDUPLEX)
+			phydev->duplex = DUPLEX_FULL;
+		else
+			phydev->duplex = DUPLEX_HALF;
+
+		switch (status & MII_PHY_STATUS_SPD_MASK) {
+		case MII_PHY_STATUS_1000:
+			phydev->speed = SPEED_1000;
+			break;
+
+		case MII_PHY_STATUS_100:
+			phydev->speed = SPEED_100;
+			break;
+
+		default:
+			phydev->speed = SPEED_10;
+			break;
+		}
+	} else {
+		int bmcr = phy_read(phydev, MII_BMCR);
+
+		if (bmcr < 0)
+			return bmcr;
+
+		if (bmcr & BMCR_FULLDPLX)
+			phydev->duplex = DUPLEX_FULL;
+		else
+			phydev->duplex = DUPLEX_HALF;
+
+		if (bmcr & BMCR_SPEED1000)
+			phydev->speed = SPEED_1000;
+		else if (bmcr & BMCR_SPEED100)
+			phydev->speed = SPEED_100;
+		else
+			phydev->speed = SPEED_10;
+	}
+
+	/* For 1000BASE-X Phy Mode the speed/duplex will always be
+	 * 1000Mbps/fullduplex
+	 */
+	if (phydev->dev_flags == XAE_PHY_TYPE_1000BASE_X) {
+		phydev->duplex = DUPLEX_FULL;
+		phydev->speed = SPEED_1000;
+	}
+
+	/* For 2500BASE-X Phy Mode the speed/duplex will always be
+	 * 2500Mbps/fullduplex
+	 */
+	if (phydev->dev_flags == XAE_PHY_TYPE_2500) {
+		phydev->duplex = DUPLEX_FULL;
+		phydev->speed = SPEED_2500;
+	}
+
+	return 0;
+}
+
+static int xilinxphy_of_init(struct phy_device *phydev)
+{
+	struct device *dev = &phydev->mdio.dev;
+	struct device_node *of_node = dev->of_node;
+	u32 phytype;
+
+	if (!IS_ENABLED(CONFIG_OF_MDIO))
+		return 0;
+
+	if (!of_node)
+		return -ENODEV;
+
+	if (!of_property_read_u32(of_node, "xlnx,phy-type", &phytype)) {
+		if (phytype == XAE_PHY_TYPE_1000BASE_X)
+			phydev->dev_flags |= XAE_PHY_TYPE_1000BASE_X;
+		if (phytype == XAE_PHY_TYPE_2500)
+			phydev->dev_flags |= XAE_PHY_TYPE_2500;
+	}
+
+	return 0;
+}
+
+static int xilinxphy_config_init(struct phy_device *phydev)
+{
+	int temp;
+
+	xilinxphy_of_init(phydev);
+	temp = phy_read(phydev, MII_BMCR);
+	temp &= XPCSPMA_PHY_CTRL_ISOLATE_DISABLE;
+	phy_write(phydev, MII_BMCR, temp);
+
+	return 0;
+}
+
+static struct phy_driver xilinx_drivers[] = {
+	{
+		.phy_id = XILINX_PHY_ID,
+		.phy_id_mask = XILINX_PHY_ID_MASK,
+		.name = "Xilinx PCS/PMA PHY",
+		.features = PHY_GBIT_FEATURES,
+		.config_init = &xilinxphy_config_init,
+		.config_aneg = &genphy_config_aneg,
+		.read_status = &xilinxphy_read_status,
+		.resume = &genphy_resume,
+		.suspend = &genphy_suspend,
+	},
+};
+
+module_phy_driver(xilinx_drivers);
+
+static struct mdio_device_id __maybe_unused xilinx_tbl[] = {
+	{ XILINX_PHY_ID, XILINX_PHY_ID_MASK },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(mdio, xilinx_tbl);
+MODULE_DESCRIPTION("Xilinx PCS/PMA PHY driver");
+MODULE_LICENSE("GPL");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/plip/plip.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/plip/plip.c
@@ -444,12 +444,12 @@
 	}
 	rcv->state = PLIP_PK_DONE;
 	if (rcv->skb) {
-		kfree_skb(rcv->skb);
+		dev_kfree_skb_irq(rcv->skb);
 		rcv->skb = NULL;
 	}
 	snd->state = PLIP_PK_DONE;
 	if (snd->skb) {
-		dev_kfree_skb(snd->skb);
+		dev_consume_skb_irq(snd->skb);
 		snd->skb = NULL;
 	}
 	spin_unlock_irq(&nl->lock);
@@ -1103,7 +1103,7 @@
 		/* Any address will do - we take the first. We already
 		   have the first two bytes filled with 0xfc, from
 		   plip_init_dev(). */
-		const struct in_ifaddr *ifa = rcu_dereference(in_dev->ifa_list);
+		const struct in_ifaddr *ifa = rtnl_dereference(in_dev->ifa_list);
 		if (ifa != NULL) {
 			memcpy(dev->dev_addr+2, &ifa->ifa_local, 4);
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ppp/ppp_async.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ppp/ppp_async.c
@@ -470,6 +470,10 @@
 	case PPPIOCSMRU:
 		if (get_user(val, p))
 			break;
+		if (val > U16_MAX) {
+			err = -EINVAL;
+			break;
+		}
 		if (val < PPP_MRU)
 			val = PPP_MRU;
 		ap->mru = val;
@@ -547,7 +551,7 @@
 	 * and 7 (code-reject) must be sent as though no options
 	 * had been negotiated.
 	 */
-	islcp = proto == PPP_LCP && 1 <= data[2] && data[2] <= 7;
+	islcp = proto == PPP_LCP && count >= 3 && 1 <= data[2] && data[2] <= 7;
 
 	if (i == 0) {
 		if (islcp)
@@ -874,15 +878,15 @@
 				skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2);
 				if (!skb)
 					goto nomem;
- 				ap->rpkt = skb;
- 			}
- 			if (skb->len == 0) {
- 				/* Try to get the payload 4-byte aligned.
- 				 * This should match the
- 				 * PPP_ALLSTATIONS/PPP_UI/compressed tests in
- 				 * process_input_packet, but we do not have
- 				 * enough chars here to test buf[1] and buf[2].
- 				 */
+				ap->rpkt = skb;
+			}
+			if (skb->len == 0) {
+				/* Try to get the payload 4-byte aligned.
+				 * This should match the
+				 * PPP_ALLSTATIONS/PPP_UI/compressed tests in
+				 * process_input_packet, but we do not have
+				 * enough chars here to test buf[1] and buf[2].
+				 */
 				if (buf[0] != PPP_ALLSTATIONS)
 					skb_reserve(skb, 2 + (buf[0] & 1));
 			}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ppp/ppp_generic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ppp/ppp_generic.c
@@ -69,6 +69,20 @@
 #define MPHDRLEN	6	/* multilink protocol header length */
 #define MPHDRLEN_SSN	4	/* ditto with short sequence numbers */
 
+#define PPP_PROTO_LEN	2
+#define PPP_LCP_HDRLEN	4
+
+/* The filter instructions generated by libpcap are constructed
+ * assuming a four-byte PPP header on each packet, where the last
+ * 2 bytes are the protocol field defined in the RFC and the first
+ * byte of the first 2 bytes indicates the direction.
+ * The second byte is currently unused, but we still need to initialize
+ * it to prevent crafted BPF programs from reading them which would
+ * cause reading of uninitialized data.
+ */
+#define PPP_FILTER_OUTBOUND_TAG 0x0100
+#define PPP_FILTER_INBOUND_TAG  0x0000
+
 /*
  * An instance of /dev/ppp can be associated with either a ppp
  * interface unit or a ppp channel.  In both cases, file->private_data
@@ -283,7 +297,7 @@
 static int ppp_connect_channel(struct channel *pch, int unit);
 static int ppp_disconnect_channel(struct channel *pch);
 static void ppp_destroy_channel(struct channel *pch);
-static int unit_get(struct idr *p, void *ptr);
+static int unit_get(struct idr *p, void *ptr, int min);
 static int unit_set(struct idr *p, void *ptr, int n);
 static void unit_put(struct idr *p, int n);
 static void *unit_find(struct idr *p, int n);
@@ -489,6 +503,15 @@
 	return ret;
 }
 
+static bool ppp_check_packet(struct sk_buff *skb, size_t count)
+{
+	/* LCP packets must include LCP header which 4 bytes long:
+	 * 1-byte code, 1-byte identifier, and 2-byte length.
+	 */
+	return get_unaligned_be16(skb->data) != PPP_LCP ||
+		count >= PPP_PROTO_LEN + PPP_LCP_HDRLEN;
+}
+
 static ssize_t ppp_write(struct file *file, const char __user *buf,
 			 size_t count, loff_t *ppos)
 {
@@ -498,6 +521,9 @@
 
 	if (!pf)
 		return -ENXIO;
+	/* All PPP packets should start with the 2-byte protocol */
+	if (count < PPP_PROTO_LEN)
+		return -EINVAL;
 	ret = -ENOMEM;
 	skb = alloc_skb(count + pf->hdrlen, GFP_KERNEL);
 	if (!skb)
@@ -508,6 +534,11 @@
 		kfree_skb(skb);
 		goto out;
 	}
+	ret = -EINVAL;
+	if (unlikely(!ppp_check_packet(skb, count))) {
+		kfree_skb(skb);
+		goto out;
+	}
 
 	switch (pf->kind) {
 	case INTERFACE:
@@ -959,9 +990,20 @@
 	mutex_lock(&pn->all_ppp_mutex);
 
 	if (unit < 0) {
-		ret = unit_get(&pn->units_idr, ppp);
+		ret = unit_get(&pn->units_idr, ppp, 0);
 		if (ret < 0)
 			goto err;
+		if (!ifname_is_set) {
+			while (1) {
+				snprintf(ppp->dev->name, IFNAMSIZ, "ppp%i", ret);
+				if (!__dev_get_by_name(ppp->ppp_net, ppp->dev->name))
+					break;
+				unit_put(&pn->units_idr, ret);
+				ret = unit_get(&pn->units_idr, ppp, ret + 1);
+				if (ret < 0)
+					goto err;
+			}
+		}
 	} else {
 		/* Caller asked for a specific unit number. Fail with -EEXIST
 		 * if unavailable. For backward compatibility, return -EEXIST
@@ -1110,7 +1152,7 @@
 	 * the PPP unit identifer as suffix (i.e. ppp<unit_id>). This allows
 	 * userspace to infer the device name using to the PPPIOCGUNIT ioctl.
 	 */
-	if (!tb[IFLA_IFNAME])
+	if (!tb[IFLA_IFNAME] || !nla_len(tb[IFLA_IFNAME]) || !*(char *)nla_data(tb[IFLA_IFNAME]))
 		conf.ifname_is_set = false;
 
 	err = ppp_dev_configure(src_net, dev, &conf);
@@ -1506,12 +1548,14 @@
 	int len;
 	unsigned char *cp;
 
+	skb->dev = ppp->dev;
+
 	if (proto < 0x8000) {
 #ifdef CONFIG_PPP_FILTER
-		/* check if we should pass this packet */
-		/* the filter instructions are constructed assuming
-		   a four-byte PPP header on each packet */
-		*(u8 *)skb_push(skb, 2) = 1;
+		/* check if the packet passes the pass and active filters.
+		 * See comment for PPP_FILTER_OUTBOUND_TAG above.
+		 */
+		*(__be16 *)skb_push(skb, 2) = htons(PPP_FILTER_OUTBOUND_TAG);
 		if (ppp->pass_filter &&
 		    BPF_PROG_RUN(ppp->pass_filter, skb) == 0) {
 			if (ppp->debug & 1)
@@ -1533,7 +1577,7 @@
 	}
 
 	++ppp->stats64.tx_packets;
-	ppp->stats64.tx_bytes += skb->len - 2;
+	ppp->stats64.tx_bytes += skb->len - PPP_PROTO_LEN;
 
 	switch (proto) {
 	case PPP_IP:
@@ -2190,14 +2234,13 @@
 		/* network protocol frame - give it to the kernel */
 
 #ifdef CONFIG_PPP_FILTER
-		/* check if the packet passes the pass and active filters */
-		/* the filter instructions are constructed assuming
-		   a four-byte PPP header on each packet */
 		if (ppp->pass_filter || ppp->active_filter) {
 			if (skb_unclone(skb, GFP_ATOMIC))
 				goto err;
-
-			*(u8 *)skb_push(skb, 2) = 0;
+			/* Check if the packet passes the pass and active filters.
+			 * See comment for PPP_FILTER_INBOUND_TAG above.
+			 */
+			*(__be16 *)skb_push(skb, 2) = htons(PPP_FILTER_INBOUND_TAG);
 			if (ppp->pass_filter &&
 			    BPF_PROG_RUN(ppp->pass_filter, skb) == 0) {
 				if (ppp->debug & 1)
@@ -3294,9 +3337,9 @@
 }
 
 /* get new free unit number and associate pointer with it */
-static int unit_get(struct idr *p, void *ptr)
+static int unit_get(struct idr *p, void *ptr, int min)
 {
-	return idr_alloc(p, ptr, 0, 0, GFP_KERNEL);
+	return idr_alloc(p, ptr, min, 0, GFP_KERNEL);
 }
 
 /* put unit number back to a pool */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ppp/ppp_synctty.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ppp/ppp_synctty.c
@@ -463,6 +463,10 @@
 	case PPPIOCSMRU:
 		if (get_user(val, (int __user *) argp))
 			break;
+		if (val > U16_MAX) {
+			err = -EINVAL;
+			break;
+		}
 		if (val < PPP_MRU)
 			val = PPP_MRU;
 		ap->mru = val;
@@ -698,7 +702,7 @@
 
 	/* strip address/control field if present */
 	p = skb->data;
-	if (p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) {
+	if (skb->len >= 2 && p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) {
 		/* chop off address/control */
 		if (skb->len < 3)
 			goto err;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/ppp/pppoe.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/ppp/pppoe.c
@@ -492,6 +492,9 @@
 	if (!skb)
 		goto out;
 
+	if (skb->pkt_type != PACKET_HOST)
+		goto abort;
+
 	if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr)))
 		goto abort;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/slip/slhc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/slip/slhc.c
@@ -232,7 +232,7 @@
 	struct cstate *cs = lcs->next;
 	unsigned long deltaS, deltaA;
 	short changes = 0;
-	int hlen;
+	int nlen, hlen;
 	unsigned char new_seq[16];
 	unsigned char *cp = new_seq;
 	struct iphdr *ip;
@@ -248,6 +248,8 @@
 		return isize;
 
 	ip = (struct iphdr *) icp;
+	if (ip->version != 4 || ip->ihl < 5)
+		return isize;
 
 	/* Bail if this packet isn't TCP, or is an IP fragment */
 	if (ip->protocol != IPPROTO_TCP || (ntohs(ip->frag_off) & 0x3fff)) {
@@ -258,10 +260,14 @@
 			comp->sls_o_tcp++;
 		return isize;
 	}
-	/* Extract TCP header */
+	nlen = ip->ihl * 4;
+	if (isize < nlen + sizeof(*th))
+		return isize;
 
-	th = (struct tcphdr *)(((unsigned char *)ip) + ip->ihl*4);
-	hlen = ip->ihl*4 + th->doff*4;
+	th = (struct tcphdr *)(icp + nlen);
+	if (th->doff < sizeof(struct tcphdr) / 4)
+		return isize;
+	hlen = nlen + th->doff * 4;
 
 	/*  Bail if the TCP packet isn't `compressible' (i.e., ACK isn't set or
 	 *  some other control bit is set). Also uncompressible if
@@ -637,46 +643,57 @@
 int
 slhc_remember(struct slcompress *comp, unsigned char *icp, int isize)
 {
-	struct cstate *cs;
-	unsigned ihl;
-
+	const struct tcphdr *th;
 	unsigned char index;
+	struct iphdr *iph;
+	struct cstate *cs;
+	unsigned int ihl;
 
-	if(isize < 20) {
-		/* The packet is shorter than a legal IP header */
+	/* The packet is shorter than a legal IP header.
+	 * Also make sure isize is positive.
+	 */
+	if (isize < (int)sizeof(struct iphdr)) {
+runt:
 		comp->sls_i_runt++;
-		return slhc_toss( comp );
+		return slhc_toss(comp);
 	}
+	iph = (struct iphdr *)icp;
 	/* Peek at the IP header's IHL field to find its length */
-	ihl = icp[0] & 0xf;
-	if(ihl < 20 / 4){
-		/* The IP header length field is too small */
-		comp->sls_i_runt++;
-		return slhc_toss( comp );
-	}
-	index = icp[9];
-	icp[9] = IPPROTO_TCP;
+	ihl = iph->ihl;
+	/* The IP header length field is too small,
+	 * or packet is shorter than the IP header followed
+	 * by minimal tcp header.
+	 */
+	if (ihl < 5 || isize < ihl * 4 + sizeof(struct tcphdr))
+		goto runt;
+
+	index = iph->protocol;
+	iph->protocol = IPPROTO_TCP;
 
 	if (ip_fast_csum(icp, ihl)) {
 		/* Bad IP header checksum; discard */
 		comp->sls_i_badcheck++;
-		return slhc_toss( comp );
+		return slhc_toss(comp);
 	}
-	if(index > comp->rslot_limit) {
+	if (index > comp->rslot_limit) {
 		comp->sls_i_error++;
 		return slhc_toss(comp);
 	}
-
+	th = (struct tcphdr *)(icp + ihl * 4);
+	if (th->doff < sizeof(struct tcphdr) / 4)
+		goto runt;
+	if (isize < ihl * 4 + th->doff * 4)
+		goto runt;
 	/* Update local state */
 	cs = &comp->rstate[comp->recv_current = index];
 	comp->flags &=~ SLF_TOSS;
-	memcpy(&cs->cs_ip,icp,20);
-	memcpy(&cs->cs_tcp,icp + ihl*4,20);
+	memcpy(&cs->cs_ip, iph, sizeof(*iph));
+	memcpy(&cs->cs_tcp, th, sizeof(*th));
 	if (ihl > 5)
-	  memcpy(cs->cs_ipopt, icp + sizeof(struct iphdr), (ihl - 5) * 4);
-	if (cs->cs_tcp.doff > 5)
-	  memcpy(cs->cs_tcpopt, icp + ihl*4 + sizeof(struct tcphdr), (cs->cs_tcp.doff - 5) * 4);
-	cs->cs_hsize = ihl*2 + cs->cs_tcp.doff*2;
+	  memcpy(cs->cs_ipopt, &iph[1], (ihl - 5) * 4);
+	if (th->doff > 5)
+	  memcpy(cs->cs_tcpopt, &th[1], (th->doff - 5) * 4);
+	cs->cs_hsize = ihl*2 + th->doff*2;
 	cs->initialized = true;
 	/* Put headers back on packet
 	 * Neither header checksum is recalculated
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/slip/slip.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/slip/slip.c
@@ -452,9 +452,16 @@
  */
 static void slip_write_wakeup(struct tty_struct *tty)
 {
-	struct slip *sl = tty->disc_data;
+	struct slip *sl;
+
+	rcu_read_lock();
+	sl = rcu_dereference(tty->disc_data);
+	if (!sl)
+		goto out;
 
 	schedule_work(&sl->tx_work);
+out:
+	rcu_read_unlock();
 }
 
 static void sl_tx_timeout(struct net_device *dev)
@@ -464,7 +471,7 @@
 	spin_lock(&sl->lock);
 
 	if (netif_queue_stopped(dev)) {
-		if (!netif_running(dev))
+		if (!netif_running(dev) || !sl->tty)
 			goto out;
 
 		/* May be we must check transmitter timeout here ?
@@ -855,7 +862,11 @@
 	sl->tty = NULL;
 	tty->disc_data = NULL;
 	clear_bit(SLF_INUSE, &sl->flags);
+	sl_free_netdev(sl->dev);
+	/* do not call free_netdev before rtnl_unlock */
+	rtnl_unlock();
 	free_netdev(sl->dev);
+	return err;
 
 err_exit:
 	rtnl_unlock();
@@ -881,10 +892,11 @@
 		return;
 
 	spin_lock_bh(&sl->lock);
-	tty->disc_data = NULL;
+	rcu_assign_pointer(tty->disc_data, NULL);
 	sl->tty = NULL;
 	spin_unlock_bh(&sl->lock);
 
+	synchronize_rcu();
 	flush_work(&sl->tx_work);
 
 	/* VSV = very important to remove timers */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/sungem_phy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/sungem_phy.c
@@ -454,6 +454,7 @@
 		int can_low_power = 1;
 		if (np == NULL || of_get_property(np, "no-autolowpower", NULL))
 			can_low_power = 0;
+		of_node_put(np);
 		if (can_low_power) {
 			/* Enable automatic low-power */
 			sungem_phy_write(phy, 0x1c, 0x9002);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/tap.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/tap.c
@@ -525,7 +525,7 @@
 	q->sock.state = SS_CONNECTED;
 	q->sock.file = file;
 	q->sock.ops = &tap_socket_ops;
-	sock_init_data(&q->sock, &q->sk);
+	sock_init_data_uid(&q->sock, &q->sk, current_fsuid());
 	q->sk.sk_write_space = tap_sock_write_space;
 	q->sk.sk_destruct = tap_sock_destruct;
 	q->flags = IFF_VNET_HDR | IFF_NO_PI | IFF_TAP;
@@ -715,9 +715,8 @@
 	skb_probe_transport_header(skb);
 
 	/* Move network header to the right position for VLAN tagged packets */
-	if ((skb->protocol == htons(ETH_P_8021Q) ||
-	     skb->protocol == htons(ETH_P_8021AD)) &&
-	    __vlan_get_protocol(skb, skb->protocol, &depth) != 0)
+	if (eth_type_vlan(skb->protocol) &&
+	    vlan_get_protocol_and_depth(skb, skb->protocol, &depth) != 0)
 		skb_set_network_header(skb, depth);
 
 	rcu_read_lock();
@@ -1095,10 +1094,9 @@
 			return -ENOLINK;
 		}
 		ret = 0;
-		u = tap->dev->type;
+		dev_get_mac_address(&sa, dev_net(tap->dev), tap->dev->name);
 		if (copy_to_user(&ifr->ifr_name, tap->dev->name, IFNAMSIZ) ||
-		    copy_to_user(&ifr->ifr_hwaddr.sa_data, tap->dev->dev_addr, ETH_ALEN) ||
-		    put_user(u, &ifr->ifr_hwaddr.sa_family))
+		    copy_to_user(&ifr->ifr_hwaddr, &sa, sizeof(sa)))
 			ret = -EFAULT;
 		tap_put_tap_dev(tap);
 		rtnl_unlock();
@@ -1113,7 +1111,7 @@
 			rtnl_unlock();
 			return -ENOLINK;
 		}
-		ret = dev_set_mac_address(tap->dev, &sa, NULL);
+		ret = dev_set_mac_address_user(tap->dev, &sa, NULL);
 		tap_put_tap_dev(tap);
 		rtnl_unlock();
 		return ret;
@@ -1155,6 +1153,11 @@
 	struct sk_buff *skb;
 	int err, depth;
 
+	if (unlikely(xdp->data_end - xdp->data < ETH_HLEN)) {
+		err = -EINVAL;
+		goto err;
+	}
+
 	if (q->flags & IFF_VNET_HDR)
 		vnet_hdr_len = READ_ONCE(q->vnet_hdr_sz);
 
@@ -1178,9 +1181,8 @@
 	}
 
 	/* Move network header to the right position for VLAN tagged packets */
-	if ((skb->protocol == htons(ETH_P_8021Q) ||
-	     skb->protocol == htons(ETH_P_8021AD)) &&
-	    __vlan_get_protocol(skb, skb->protocol, &depth) != 0)
+	if (eth_type_vlan(skb->protocol) &&
+	    vlan_get_protocol_and_depth(skb, skb->protocol, &depth) != 0)
 		skb_set_network_header(skb, depth);
 
 	rcu_read_lock();
@@ -1215,7 +1217,8 @@
 	struct xdp_buff *xdp;
 	int i;
 
-	if (ctl && (ctl->type == TUN_MSG_PTR)) {
+	if (m->msg_controllen == sizeof(struct tun_msg_ctl) &&
+	    ctl && ctl->type == TUN_MSG_PTR) {
 		for (i = 0; i < ctl->num; i++) {
 			xdp = &((struct xdp_buff *)ctl->ptr)[i];
 			tap_get_user_xdp(q, xdp);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/team/team.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/team/team.c
@@ -284,10 +284,12 @@
 	return 0;
 
 inst_rollback:
-	for (i--; i >= 0; i--)
+	for (i--; i >= 0; i--) {
 		__team_option_inst_del_option(team, dst_opts[i]);
+		list_del(&dst_opts[i]->list);
+	}
 
-	i = option_count - 1;
+	i = option_count;
 alloc_rollback:
 	for (i--; i >= 0; i--)
 		kfree(dst_opts[i]);
@@ -468,6 +470,9 @@
 	struct team_mode_item *mitem;
 	const struct team_mode *mode = NULL;
 
+	if (!try_module_get(THIS_MODULE))
+		return NULL;
+
 	spin_lock(&mode_list_lock);
 	mitem = __find_mode(kind);
 	if (!mitem) {
@@ -483,6 +488,7 @@
 	}
 
 	spin_unlock(&mode_list_lock);
+	module_put(THIS_MODULE);
 	return mode;
 }
 
@@ -987,7 +993,8 @@
 	unsigned int dst_release_flag = IFF_XMIT_DST_RELEASE |
 					IFF_XMIT_DST_RELEASE_PERM;
 
-	list_for_each_entry(port, &team->port_list, list) {
+	rcu_read_lock();
+	list_for_each_entry_rcu(port, &team->port_list, list) {
 		vlan_features = netdev_increment_features(vlan_features,
 					port->dev->vlan_features,
 					TEAM_VLAN_FEATURES);
@@ -1001,6 +1008,7 @@
 		if (port->dev->hard_header_len > max_hard_header_len)
 			max_hard_header_len = port->dev->hard_header_len;
 	}
+	rcu_read_unlock();
 
 	team->dev->vlan_features = vlan_features;
 	team->dev->hw_enc_features = enc_features | NETIF_F_GSO_ENCAP_ALL |
@@ -1016,9 +1024,7 @@
 
 static void team_compute_features(struct team *team)
 {
-	mutex_lock(&team->lock);
 	__team_compute_features(team);
-	mutex_unlock(&team->lock);
 	netdev_change_features(team->dev);
 }
 
@@ -1159,6 +1165,13 @@
 		return -EBUSY;
 	}
 
+	if (netdev_has_upper_dev(port_dev, dev)) {
+		NL_SET_ERR_MSG(extack, "Device is already a lower device of the team interface");
+		netdev_err(dev, "Device %s is already a lower device of the team interface\n",
+			   portname);
+		return -EBUSY;
+	}
+
 	if (port_dev->features & NETIF_F_VLAN_CHALLENGED &&
 	    vlan_uses_dev(dev)) {
 		NL_SET_ERR_MSG(extack, "Device is VLAN challenged and team device has VLAN set up");
@@ -1266,10 +1279,12 @@
 		}
 	}
 
-	netif_addr_lock_bh(dev);
-	dev_uc_sync_multiple(port_dev, dev);
-	dev_mc_sync_multiple(port_dev, dev);
-	netif_addr_unlock_bh(dev);
+	if (dev->flags & IFF_UP) {
+		netif_addr_lock_bh(dev);
+		dev_uc_sync_multiple(port_dev, dev);
+		dev_mc_sync_multiple(port_dev, dev);
+		netif_addr_unlock_bh(dev);
+	}
 
 	port->index = -1;
 	list_add_tail_rcu(&port->list, &team->port_list);
@@ -1340,8 +1355,10 @@
 	netdev_rx_handler_unregister(port_dev);
 	team_port_disable_netpoll(port);
 	vlan_vids_del_by_dev(port_dev, dev);
-	dev_uc_unsync(port_dev, dev);
-	dev_mc_unsync(port_dev, dev);
+	if (dev->flags & IFF_UP) {
+		dev_uc_unsync(port_dev, dev);
+		dev_mc_unsync(port_dev, dev);
+	}
 	dev_close(port_dev);
 	team_port_leave(team, port);
 
@@ -1616,6 +1633,7 @@
 
 	team->dev = dev;
 	team_set_no_mode(team);
+	team->notifier_ctx = false;
 
 	team->pcpu_stats = netdev_alloc_pcpu_stats(struct team_pcpu_stats);
 	if (!team->pcpu_stats)
@@ -1690,6 +1708,14 @@
 
 static int team_close(struct net_device *dev)
 {
+	struct team *team = netdev_priv(dev);
+	struct team_port *port;
+
+	list_for_each_entry(port, &team->port_list, list) {
+		dev_uc_unsync(port->dev, dev);
+		dev_mc_unsync(port->dev, dev);
+	}
+
 	return 0;
 }
 
@@ -2074,7 +2100,8 @@
 	cmd->base.duplex = DUPLEX_UNKNOWN;
 	cmd->base.port = PORT_OTHER;
 
-	list_for_each_entry(port, &team->port_list, list) {
+	rcu_read_lock();
+	list_for_each_entry_rcu(port, &team->port_list, list) {
 		if (team_port_txable(port)) {
 			if (port->state.speed != SPEED_UNKNOWN)
 				speed += port->state.speed;
@@ -2083,6 +2110,8 @@
 				cmd->base.duplex = port->state.duplex;
 		}
 	}
+	rcu_read_unlock();
+
 	cmd->base.speed = speed ? : SPEED_UNKNOWN;
 
 	return 0;
@@ -2101,13 +2130,28 @@
 static void team_setup_by_port(struct net_device *dev,
 			       struct net_device *port_dev)
 {
-	dev->header_ops	= port_dev->header_ops;
+	struct team *team = netdev_priv(dev);
+
+	if (port_dev->type == ARPHRD_ETHER)
+		dev->header_ops	= team->header_ops_cache;
+	else
+		dev->header_ops	= port_dev->header_ops;
 	dev->type = port_dev->type;
 	dev->hard_header_len = port_dev->hard_header_len;
+	dev->needed_headroom = port_dev->needed_headroom;
 	dev->addr_len = port_dev->addr_len;
 	dev->mtu = port_dev->mtu;
 	memcpy(dev->broadcast, port_dev->broadcast, port_dev->addr_len);
 	eth_hw_addr_inherit(dev, port_dev);
+
+	if (port_dev->flags & IFF_POINTOPOINT) {
+		dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST);
+		dev->flags |= (IFF_POINTOPOINT | IFF_NOARP);
+	} else if ((port_dev->flags & (IFF_BROADCAST | IFF_MULTICAST)) ==
+		    (IFF_BROADCAST | IFF_MULTICAST)) {
+		dev->flags |= (IFF_BROADCAST | IFF_MULTICAST);
+		dev->flags &= ~(IFF_POINTOPOINT | IFF_NOARP);
+	}
 }
 
 static int team_dev_type_check_change(struct net_device *dev,
@@ -2138,8 +2182,11 @@
 
 static void team_setup(struct net_device *dev)
 {
+	struct team *team = netdev_priv(dev);
+
 	ether_setup(dev);
 	dev->max_mtu = ETH_MAX_MTU;
+	team->header_ops_cache = dev->header_ops;
 
 	dev->netdev_ops = &team_netdev_ops;
 	dev->ethtool_ops = &team_ethtool_ops;
@@ -2164,7 +2211,9 @@
 
 	dev->hw_features = TEAM_VLAN_FEATURES |
 			   NETIF_F_HW_VLAN_CTAG_RX |
-			   NETIF_F_HW_VLAN_CTAG_FILTER;
+			   NETIF_F_HW_VLAN_CTAG_FILTER |
+			   NETIF_F_HW_VLAN_STAG_RX |
+			   NETIF_F_HW_VLAN_STAG_FILTER;
 
 	dev->hw_features |= NETIF_F_GSO_ENCAP_ALL | NETIF_F_GSO_UDP_L4;
 	dev->features |= dev->hw_features;
@@ -2237,6 +2286,8 @@
 	[TEAM_ATTR_OPTION_CHANGED]		= { .type = NLA_FLAG },
 	[TEAM_ATTR_OPTION_TYPE]			= { .type = NLA_U8 },
 	[TEAM_ATTR_OPTION_DATA]			= { .type = NLA_BINARY },
+	[TEAM_ATTR_OPTION_PORT_IFINDEX]		= { .type = NLA_U32 },
+	[TEAM_ATTR_OPTION_ARRAY_INDEX]		= { .type = NLA_U32 },
 };
 
 static int team_nl_cmd_noop(struct sk_buff *skb, struct genl_info *info)
@@ -2612,7 +2663,9 @@
 				ctx.data.u32_val = nla_get_u32(attr_data);
 				break;
 			case TEAM_OPTION_TYPE_STRING:
-				if (nla_len(attr_data) > TEAM_STRING_MAX_LEN) {
+				if (nla_len(attr_data) > TEAM_STRING_MAX_LEN ||
+				    !memchr(nla_data(attr_data), '\0',
+					    nla_len(attr_data))) {
 					err = -EINVAL;
 					goto team_put;
 				}
@@ -2993,7 +3046,11 @@
 		team_del_slave(port->team->dev, dev);
 		break;
 	case NETDEV_FEAT_CHANGE:
-		team_compute_features(port->team);
+		if (!port->team->notifier_ctx) {
+			port->team->notifier_ctx = true;
+			team_compute_features(port->team);
+			port->team->notifier_ctx = false;
+		}
 		break;
 	case NETDEV_PRECHANGEMTU:
 		/* Forbid to change mtu of underlaying device */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/thunderbolt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/thunderbolt.c
@@ -958,12 +958,11 @@
 		*tucso = ~csum_tcpudp_magic(ip_hdr(skb)->saddr,
 					    ip_hdr(skb)->daddr, 0,
 					    ip_hdr(skb)->protocol, 0);
-	} else if (skb_is_gso_v6(skb)) {
+	} else if (skb_is_gso(skb) && skb_is_gso_v6(skb)) {
 		tucso = dest + ((void *)&(tcp_hdr(skb)->check) - data);
 		*tucso = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
 					  &ipv6_hdr(skb)->daddr, 0,
 					  IPPROTO_TCP, 0);
-		return false;
 	} else if (protocol == htons(ETH_P_IPV6)) {
 		tucso = dest + skb_checksum_start_offset(skb) + skb->csum_offset;
 		*tucso = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
@@ -1339,12 +1338,21 @@
 				  TBNET_MATCH_FRAGS_ID);
 
 	ret = tb_register_property_dir("network", tbnet_dir);
-	if (ret) {
-		tb_property_free_dir(tbnet_dir);
-		return ret;
-	}
+	if (ret)
+		goto err_free_dir;
+
+	ret = tb_register_service_driver(&tbnet_driver);
+	if (ret)
+		goto err_unregister;
+
+	return 0;
+
+err_unregister:
+	tb_unregister_property_dir("network", tbnet_dir);
+err_free_dir:
+	tb_property_free_dir(tbnet_dir);
 
-	return tb_register_service_driver(&tbnet_driver);
+	return ret;
 }
 module_init(tbnet_init);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/tun.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/tun.c
@@ -68,6 +68,14 @@
 #include <linux/bpf.h>
 #include <linux/bpf_trace.h>
 #include <linux/mutex.h>
+#include <linux/ieee802154.h>
+#include <linux/if_ltalk.h>
+#include <uapi/linux/if_fddi.h>
+#include <uapi/linux/if_hippi.h>
+#include <uapi/linux/if_fc.h>
+#include <net/ax25.h>
+#include <net/rose.h>
+#include <net/6lowpan.h>
 
 #include <linux/uaccess.h>
 #include <linux/proc_fs.h>
@@ -242,6 +250,9 @@
 	struct tun_prog __rcu *steering_prog;
 	struct tun_prog __rcu *filter_prog;
 	struct ethtool_link_ksettings link_ksettings;
+	/* init args */
+	struct file *file;
+	struct ifreq *ifr;
 };
 
 struct veth {
@@ -267,6 +278,9 @@
 }
 EXPORT_SYMBOL(tun_ptr_to_xdp);
 
+static void tun_flow_init(struct tun_struct *tun);
+static void tun_flow_uninit(struct tun_struct *tun);
+
 static int tun_napi_receive(struct napi_struct *napi, int budget)
 {
 	struct tun_file *tfile = container_of(napi, struct tun_file, napi);
@@ -313,12 +327,18 @@
 	tfile->napi_enabled = napi_en;
 	tfile->napi_frags_enabled = napi_en && napi_frags;
 	if (napi_en) {
-		netif_napi_add(tun->dev, &tfile->napi, tun_napi_poll,
-			       NAPI_POLL_WEIGHT);
+		netif_tx_napi_add(tun->dev, &tfile->napi, tun_napi_poll,
+				  NAPI_POLL_WEIGHT);
 		napi_enable(&tfile->napi);
 	}
 }
 
+static void tun_napi_enable(struct tun_file *tfile)
+{
+	if (tfile->napi_enabled)
+		napi_enable(&tfile->napi);
+}
+
 static void tun_napi_disable(struct tun_file *tfile)
 {
 	if (tfile->napi_enabled)
@@ -622,7 +642,7 @@
 	struct net *net = dev_net(tun->dev);
 
 	return ((uid_valid(tun->owner) && !uid_eq(cred->euid, tun->owner)) ||
-		  (gid_valid(tun->group) && !in_egroup_p(tun->group))) &&
+		(gid_valid(tun->group) && !in_egroup_p(tun->group))) &&
 		!ns_capable(net->user_ns, CAP_NET_ADMIN);
 }
 
@@ -682,7 +702,8 @@
 	tun = rtnl_dereference(tfile->tun);
 
 	if (tun && clean) {
-		tun_napi_disable(tfile);
+		if (!tfile->detached)
+			tun_napi_disable(tfile);
 		tun_napi_del(tfile);
 	}
 
@@ -694,6 +715,7 @@
 				   tun->tfiles[tun->numqueues - 1]);
 		ntfile = rtnl_dereference(tun->tfiles[index]);
 		ntfile->queue_index = index;
+		ntfile->xdp_rxq.queue_index = index;
 		rcu_assign_pointer(tun->tfiles[tun->numqueues - 1],
 				   NULL);
 
@@ -701,8 +723,10 @@
 		if (clean) {
 			RCU_INIT_POINTER(tfile->tun, NULL);
 			sock_put(&tfile->sk);
-		} else
+		} else {
 			tun_disable_queue(tun, tfile);
+			tun_napi_disable(tfile);
+		}
 
 		synchronize_net();
 		tun_flow_delete_by_queue(tun, tun->numqueues + 1);
@@ -725,7 +749,6 @@
 		if (tun)
 			xdp_rxq_info_unreg(&tfile->xdp_rxq);
 		ptr_ring_cleanup(&tfile->tx_ring, tun_ptr_free);
-		sock_put(&tfile->sk);
 	}
 }
 
@@ -741,6 +764,9 @@
 	if (dev)
 		netdev_state_change(dev);
 	rtnl_unlock();
+
+	if (clean)
+		sock_put(&tfile->sk);
 }
 
 static void tun_detach_all(struct net_device *dev)
@@ -775,6 +801,7 @@
 		sock_put(&tfile->sk);
 	}
 	list_for_each_entry_safe(tfile, tmp, &tun->disabled, next) {
+		tun_napi_del(tfile);
 		tun_enable_queue(tfile);
 		tun_queue_purge(tfile);
 		xdp_rxq_info_unreg(&tfile->xdp_rxq);
@@ -855,6 +882,7 @@
 
 	if (tfile->detached) {
 		tun_enable_queue(tfile);
+		tun_napi_enable(tfile);
 	} else {
 		sock_hold(&tfile->sk);
 		tun_napi_init(tun, tfile, napi, napi_frags);
@@ -1006,6 +1034,49 @@
 
 static const struct ethtool_ops tun_ethtool_ops;
 
+static int tun_net_init(struct net_device *dev)
+{
+	struct tun_struct *tun = netdev_priv(dev);
+	struct ifreq *ifr = tun->ifr;
+	int err;
+
+	tun->pcpu_stats = netdev_alloc_pcpu_stats(struct tun_pcpu_stats);
+	if (!tun->pcpu_stats)
+		return -ENOMEM;
+
+	spin_lock_init(&tun->lock);
+
+	err = security_tun_dev_alloc_security(&tun->security);
+	if (err < 0) {
+		free_percpu(tun->pcpu_stats);
+		return err;
+	}
+
+	tun_flow_init(tun);
+
+	dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST |
+			   TUN_USER_FEATURES | NETIF_F_HW_VLAN_CTAG_TX |
+			   NETIF_F_HW_VLAN_STAG_TX;
+	dev->features = dev->hw_features | NETIF_F_LLTX;
+	dev->vlan_features = dev->features &
+			     ~(NETIF_F_HW_VLAN_CTAG_TX |
+			       NETIF_F_HW_VLAN_STAG_TX);
+
+	tun->flags = (tun->flags & ~TUN_FEATURES) |
+		      (ifr->ifr_flags & TUN_FEATURES);
+
+	INIT_LIST_HEAD(&tun->disabled);
+	err = tun_attach(tun, tun->file, false, ifr->ifr_flags & IFF_NAPI,
+			 ifr->ifr_flags & IFF_NAPI_FRAGS, false);
+	if (err < 0) {
+		tun_flow_uninit(tun);
+		security_tun_dev_free_security(tun->security);
+		free_percpu(tun->pcpu_stats);
+		return err;
+	}
+	return 0;
+}
+
 /* Net device detach from fd. */
 static void tun_net_uninit(struct net_device *dev)
 {
@@ -1063,6 +1134,7 @@
 {
 	struct tun_struct *tun = netdev_priv(dev);
 	int txq = skb->queue_mapping;
+	struct netdev_queue *queue;
 	struct tun_file *tfile;
 	int len = skb->len;
 
@@ -1109,6 +1181,10 @@
 	if (ptr_ring_produce(&tfile->tx_ring, skb))
 		goto drop;
 
+	/* NETIF_F_LLTX requires to do our own update of trans_start */
+	queue = netdev_get_tx_queue(dev, txq);
+	queue->trans_start = jiffies;
+
 	/* Notify and wake up reader process */
 	if (tfile->flags & TUN_FASYNC)
 		kill_fasync(&tfile->fasync, SIGIO, POLL_IN);
@@ -1259,6 +1335,7 @@
 }
 
 static const struct net_device_ops tun_netdev_ops = {
+	.ndo_init		= tun_net_init,
 	.ndo_uninit		= tun_net_uninit,
 	.ndo_open		= tun_net_open,
 	.ndo_stop		= tun_net_close,
@@ -1339,6 +1416,7 @@
 }
 
 static const struct net_device_ops tap_netdev_ops = {
+	.ndo_init		= tun_net_init,
 	.ndo_uninit		= tun_net_uninit,
 	.ndo_open		= tun_net_open,
 	.ndo_stop		= tun_net_close,
@@ -1379,7 +1457,7 @@
 #define MAX_MTU 65535
 
 /* Initialize net device. */
-static void tun_net_init(struct net_device *dev)
+static void tun_net_initialize(struct net_device *dev)
 {
 	struct tun_struct *tun = netdev_priv(dev);
 
@@ -1468,8 +1546,9 @@
 	int err;
 	int i;
 
-	if (it->nr_segs > MAX_SKB_FRAGS + 1)
-		return ERR_PTR(-ENOMEM);
+	if (it->nr_segs > MAX_SKB_FRAGS + 1 ||
+	    len > (ETH_MAX_MTU - NET_SKB_PAD - NET_IP_ALIGN))
+		return ERR_PTR(-EMSGSIZE);
 
 	local_bh_disable();
 	skb = napi_get_frags(&tfile->napi);
@@ -1594,7 +1673,7 @@
 	if (zerocopy)
 		return false;
 
-	if (SKB_DATA_ALIGN(len + TUN_RX_PAD) +
+	if (SKB_DATA_ALIGN(len + TUN_RX_PAD + XDP_PACKET_HEADROOM) +
 	    SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) > PAGE_SIZE)
 		return false;
 
@@ -1715,8 +1794,12 @@
 			alloc_frag->offset += buflen;
 		}
 		err = tun_xdp_act(tun, xdp_prog, &xdp, act);
-		if (err < 0)
-			goto err_xdp;
+		if (err < 0) {
+			if (act == XDP_REDIRECT || act == XDP_TX)
+				put_page(alloc_frag->page);
+			goto out;
+		}
+
 		if (err == XDP_REDIRECT)
 			xdp_do_flush_map();
 		if (err != XDP_PASS)
@@ -1730,8 +1813,6 @@
 
 	return __tun_build_skb(tfile, alloc_frag, buf, buflen, len, pad);
 
-err_xdp:
-	put_page(alloc_frag->page);
 out:
 	rcu_read_unlock();
 	local_bh_enable();
@@ -1906,8 +1987,11 @@
 		skb->dev = tun->dev;
 		break;
 	case IFF_TAP:
-		if (!frags)
-			skb->protocol = eth_type_trans(skb, tun->dev);
+		if (frags && !pskb_may_pull(skb, ETH_HLEN)) {
+			err = -ENOMEM;
+			goto drop;
+		}
+		skb->protocol = eth_type_trans(skb, tun->dev);
 		break;
 	}
 
@@ -1923,6 +2007,7 @@
 
 	skb_reset_network_header(skb);
 	skb_probe_transport_header(skb);
+	skb_record_rx_queue(skb, tfile->queue_index);
 
 	if (skb_xdp) {
 		struct bpf_prog *xdp_prog;
@@ -1936,6 +2021,10 @@
 			if (ret != XDP_PASS) {
 				rcu_read_unlock();
 				local_bh_enable();
+				if (frags) {
+					tfile->napi.skb = NULL;
+					mutex_unlock(&tfile->napi_mutex);
+				}
 				return total_len;
 			}
 		}
@@ -1959,22 +2048,33 @@
 	}
 
 	if (frags) {
+		u32 headlen;
+
 		/* Exercise flow dissector code path. */
-		u32 headlen = eth_get_headlen(tun->dev, skb->data,
-					      skb_headlen(skb));
+		skb_push(skb, ETH_HLEN);
+		headlen = eth_get_headlen(tun->dev, skb->data,
+					  skb_headlen(skb));
 
 		if (unlikely(headlen > skb_headlen(skb))) {
+			WARN_ON_ONCE(1);
+			err = -ENOMEM;
 			this_cpu_inc(tun->pcpu_stats->rx_dropped);
+napi_busy:
 			napi_free_frags(&tfile->napi);
 			rcu_read_unlock();
 			mutex_unlock(&tfile->napi_mutex);
-			WARN_ON(1);
-			return -ENOMEM;
+			return err;
 		}
 
-		local_bh_disable();
-		napi_gro_frags(&tfile->napi);
-		local_bh_enable();
+		if (likely(napi_schedule_prep(&tfile->napi))) {
+			local_bh_disable();
+			napi_gro_frags(&tfile->napi);
+			napi_complete(&tfile->napi);
+			local_bh_enable();
+		} else {
+			err = -EBUSY;
+			goto napi_busy;
+		}
 		mutex_unlock(&tfile->napi_mutex);
 	} else if (tfile->napi_enabled) {
 		struct sk_buff_head *queue = &tfile->sk.sk_write_queue;
@@ -2015,12 +2115,15 @@
 	struct tun_file *tfile = file->private_data;
 	struct tun_struct *tun = tun_get(tfile);
 	ssize_t result;
+	int noblock = 0;
 
 	if (!tun)
 		return -EBADFD;
 
-	result = tun_get_user(tun, tfile, NULL, from,
-			      file->f_flags & O_NONBLOCK, false);
+	if ((file->f_flags & O_NONBLOCK) || (iocb->ki_flags & IOCB_NOWAIT))
+		noblock = 1;
+
+	result = tun_get_user(tun, tfile, NULL, from, noblock, false);
 
 	tun_put(tun);
 	return result;
@@ -2105,14 +2208,16 @@
 					    tun_is_little_endian(tun), true,
 					    vlan_hlen)) {
 			struct skb_shared_info *sinfo = skb_shinfo(skb);
-			pr_err("unexpected GSO type: "
-			       "0x%x, gso_size %d, hdr_len %d\n",
-			       sinfo->gso_type, tun16_to_cpu(tun, gso.gso_size),
-			       tun16_to_cpu(tun, gso.hdr_len));
-			print_hex_dump(KERN_ERR, "tun: ",
-				       DUMP_PREFIX_NONE,
-				       16, 1, skb->head,
-				       min((int)tun16_to_cpu(tun, gso.hdr_len), 64), true);
+
+			if (net_ratelimit()) {
+				netdev_err(tun->dev, "unexpected GSO type: 0x%x, gso_size %d, hdr_len %d\n",
+					   sinfo->gso_type, tun16_to_cpu(tun, gso.gso_size),
+					   tun16_to_cpu(tun, gso.hdr_len));
+				print_hex_dump(KERN_ERR, "tun: ",
+					       DUMP_PREFIX_NONE,
+					       16, 1, skb->head,
+					       min((int)tun16_to_cpu(tun, gso.hdr_len), 64), true);
+			}
 			WARN_ON_ONCE(1);
 			return -EINVAL;
 		}
@@ -2241,10 +2346,15 @@
 	struct tun_file *tfile = file->private_data;
 	struct tun_struct *tun = tun_get(tfile);
 	ssize_t len = iov_iter_count(to), ret;
+	int noblock = 0;
 
 	if (!tun)
 		return -EBADFD;
-	ret = tun_do_read(tun, tfile, to, file->f_flags & O_NONBLOCK, NULL);
+
+	if ((file->f_flags & O_NONBLOCK) || (iocb->ki_flags & IOCB_NOWAIT))
+		noblock = 1;
+
+	ret = tun_do_read(tun, tfile, to, noblock, NULL);
 	ret = min_t(ssize_t, ret, len);
 	if (ret > 0)
 		iocb->ki_pos = ret;
@@ -2429,6 +2539,9 @@
 	bool skb_xdp = false;
 	struct page *page;
 
+	if (unlikely(datasize < ETH_HLEN))
+		return -EINVAL;
+
 	xdp_prog = rcu_dereference(tun->xdp_prog);
 	if (xdp_prog) {
 		if (gso->gso_type) {
@@ -2486,6 +2599,7 @@
 	skb->protocol = eth_type_trans(skb, tun->dev);
 	skb_reset_network_header(skb);
 	skb_probe_transport_header(skb);
+	skb_record_rx_queue(skb, tfile->queue_index);
 
 	if (skb_xdp) {
 		err = do_xdp_generic(xdp_prog, skb);
@@ -2497,7 +2611,6 @@
 	    !tfile->detached)
 		rxhash = __skb_get_hash_symmetric(skb);
 
-	skb_record_rx_queue(skb, tfile->queue_index);
 	netif_receive_skb(skb);
 
 	/* No need for get_cpu_ptr() here since this function is
@@ -2527,7 +2640,8 @@
 	if (!tun)
 		return -EBADFD;
 
-	if (ctl && (ctl->type == TUN_MSG_PTR)) {
+	if (m->msg_controllen == sizeof(struct tun_msg_ctl) &&
+	    ctl && ctl->type == TUN_MSG_PTR) {
 		struct tun_page tpage;
 		int n = ctl->num;
 		int flush = 0;
@@ -2782,9 +2896,6 @@
 
 		if (!dev)
 			return -ENOMEM;
-		err = dev_get_valid_name(net, dev, name);
-		if (err < 0)
-			goto err_free_dev;
 
 		dev_net_set(dev, net);
 		dev->rtnl_link_ops = &tun_link_ops;
@@ -2803,41 +2914,16 @@
 		tun->rx_batched = 0;
 		RCU_INIT_POINTER(tun->steering_prog, NULL);
 
-		tun->pcpu_stats = netdev_alloc_pcpu_stats(struct tun_pcpu_stats);
-		if (!tun->pcpu_stats) {
-			err = -ENOMEM;
-			goto err_free_dev;
-		}
-
-		spin_lock_init(&tun->lock);
-
-		err = security_tun_dev_alloc_security(&tun->security);
-		if (err < 0)
-			goto err_free_stat;
-
-		tun_net_init(dev);
-		tun_flow_init(tun);
+		tun->ifr = ifr;
+		tun->file = file;
 
-		dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST |
-				   TUN_USER_FEATURES | NETIF_F_HW_VLAN_CTAG_TX |
-				   NETIF_F_HW_VLAN_STAG_TX;
-		dev->features = dev->hw_features | NETIF_F_LLTX;
-		dev->vlan_features = dev->features &
-				     ~(NETIF_F_HW_VLAN_CTAG_TX |
-				       NETIF_F_HW_VLAN_STAG_TX);
-
-		tun->flags = (tun->flags & ~TUN_FEATURES) |
-			      (ifr->ifr_flags & TUN_FEATURES);
-
-		INIT_LIST_HEAD(&tun->disabled);
-		err = tun_attach(tun, file, false, ifr->ifr_flags & IFF_NAPI,
-				 ifr->ifr_flags & IFF_NAPI_FRAGS, false);
-		if (err < 0)
-			goto err_free_flow;
+		tun_net_initialize(dev);
 
 		err = register_netdevice(tun->dev);
-		if (err < 0)
-			goto err_detach;
+		if (err < 0) {
+			free_netdev(dev);
+			return err;
+		}
 		/* free_netdev() won't check refcnt, to aovid race
 		 * with dev_put() we need publish tun after registration.
 		 */
@@ -2856,20 +2942,6 @@
 
 	strcpy(ifr->ifr_name, tun->dev->name);
 	return 0;
-
-err_detach:
-	tun_detach_all(dev);
-	/* register_netdevice() already called tun_free_netdev() */
-	goto err_free_dev;
-
-err_free_flow:
-	tun_flow_uninit(tun);
-	security_tun_dev_free_security(tun->security);
-err_free_stat:
-	free_percpu(tun->pcpu_stats);
-err_free_dev:
-	free_netdev(dev);
-	return err;
 }
 
 static void tun_get_iff(struct tun_struct *tun, struct ifreq *ifr)
@@ -3022,6 +3094,45 @@
 	return __tun_set_ebpf(tun, prog_p, prog);
 }
 
+/* Return correct value for tun->dev->addr_len based on tun->dev->type. */
+static unsigned char tun_get_addr_len(unsigned short type)
+{
+	switch (type) {
+	case ARPHRD_IP6GRE:
+	case ARPHRD_TUNNEL6:
+		return sizeof(struct in6_addr);
+	case ARPHRD_IPGRE:
+	case ARPHRD_TUNNEL:
+	case ARPHRD_SIT:
+		return 4;
+	case ARPHRD_ETHER:
+		return ETH_ALEN;
+	case ARPHRD_IEEE802154:
+	case ARPHRD_IEEE802154_MONITOR:
+		return IEEE802154_EXTENDED_ADDR_LEN;
+	case ARPHRD_PHONET_PIPE:
+	case ARPHRD_PPP:
+	case ARPHRD_NONE:
+		return 0;
+	case ARPHRD_6LOWPAN:
+		return EUI64_ADDR_LEN;
+	case ARPHRD_FDDI:
+		return FDDI_K_ALEN;
+	case ARPHRD_HIPPI:
+		return HIPPI_ALEN;
+	case ARPHRD_IEEE802:
+		return FC_ALEN;
+	case ARPHRD_ROSE:
+		return ROSE_ADDR_LEN;
+	case ARPHRD_NETROM:
+		return AX25_ADDR_LEN;
+	case ARPHRD_LOCALTLK:
+		return LTALK_ALEN;
+	default:
+		return 0;
+	}
+}
+
 static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
 			    unsigned long arg, int ifreq_len)
 {
@@ -3029,10 +3140,11 @@
 	struct net *net = sock_net(&tfile->sk);
 	struct tun_struct *tun;
 	void __user* argp = (void __user*)arg;
-	unsigned int ifindex, carrier;
+	unsigned int carrier;
 	struct ifreq ifr;
 	kuid_t owner;
 	kgid_t group;
+	int ifindex;
 	int sndbuf;
 	int vnet_hdr_sz;
 	int le;
@@ -3089,7 +3201,9 @@
 		ret = -EFAULT;
 		if (copy_from_user(&ifindex, argp, sizeof(ifindex)))
 			goto unlock;
-
+		ret = -EINVAL;
+		if (ifindex < 0)
+			goto unlock;
 		ret = 0;
 		tfile->ifindex = ifindex;
 		goto unlock;
@@ -3177,6 +3291,7 @@
 			ret = -EBUSY;
 		} else {
 			tun->dev->type = (int) arg;
+			tun->dev->addr_len = tun_get_addr_len(tun->dev->type);
 			tun_debug(KERN_INFO, tun, "linktype set to %d\n",
 				  tun->dev->type);
 			ret = 0;
@@ -3203,7 +3318,7 @@
 	case SIOCGIFHWADDR:
 		/* Get hw address */
 		memcpy(ifr.ifr_hwaddr.sa_data, tun->dev->dev_addr, ETH_ALEN);
-		ifr.ifr_hwaddr.sa_family = tun->dev->type;
+		dev_get_mac_address(&ifr.ifr_hwaddr, net, tun->dev->name);
 		if (copy_to_user(argp, &ifr, ifreq_len))
 			ret = -EFAULT;
 		break;
@@ -3213,7 +3328,7 @@
 		tun_debug(KERN_DEBUG, tun, "set hw address: %pM\n",
 			  ifr.ifr_hwaddr.sa_data);
 
-		ret = dev_set_mac_address(tun->dev, &ifr.ifr_hwaddr, NULL);
+		ret = dev_set_mac_address_user(tun->dev, &ifr.ifr_hwaddr, NULL);
 		break;
 
 	case TUNGETSNDBUF:
@@ -3428,7 +3543,7 @@
 	tfile->socket.file = file;
 	tfile->socket.ops = &tun_socket_ops;
 
-	sock_init_data(&tfile->socket, &tfile->sk);
+	sock_init_data_uid(&tfile->socket, &tfile->sk, current_fsuid());
 
 	tfile->sk.sk_write_space = tun_sock_write_space;
 	tfile->sk.sk_sndbuf = INT_MAX;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/usb/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/usb/Kconfig
@@ -99,6 +99,10 @@
 config USB_RTL8152
 	tristate "Realtek RTL8152/RTL8153 Based USB Ethernet Adapters"
 	select MII
+	select CRC32
+	select CRYPTO
+	select CRYPTO_HASH
+	select CRYPTO_SHA256
 	help
 	  This option adds support for Realtek RTL8152 based USB 2.0
 	  10/100 Ethernet adapters and RTL8153 based USB 3.0 10/100/1000
@@ -113,6 +117,7 @@
 	select PHYLIB
 	select MICROCHIP_PHY
 	select FIXED_PHY
+	select CRC32
 	help
 	  This option adds support for Microchip LAN78XX based USB 2
 	  & USB 3 10/100/1000 Ethernet adapters.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/usb/aqc111.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/usb/aqc111.c
@@ -1079,17 +1079,17 @@
 	u16 pkt_count = 0;
 	u64 desc_hdr = 0;
 	u16 vlan_tag = 0;
-	u32 skb_len = 0;
+	u32 skb_len;
 
 	if (!skb)
 		goto err;
 
-	if (skb->len == 0)
+	skb_len = skb->len;
+	if (skb_len < sizeof(desc_hdr))
 		goto err;
 
-	skb_len = skb->len;
 	/* RX Descriptor Header */
-	skb_trim(skb, skb->len - sizeof(desc_hdr));
+	skb_trim(skb, skb_len - sizeof(desc_hdr));
 	desc_hdr = le64_to_cpup((u64 *)skb_tail_pointer(skb));
 
 	/* Check these packets */
@@ -1102,10 +1102,15 @@
 	if (start_of_descs != desc_offset)
 		goto err;
 
-	/* self check desc_offset from header*/
-	if (desc_offset >= skb_len)
+	/* self check desc_offset from header and make sure that the
+	 * bounds of the metadata array are inside the SKB
+	 */
+	if (pkt_count * 2 + desc_offset >= skb_len)
 		goto err;
 
+	/* Packets must not overlap the metadata array */
+	skb_trim(skb, desc_offset);
+
 	if (pkt_count == 0)
 		goto err;
 
@@ -1136,17 +1141,15 @@
 			continue;
 		}
 
-		/* Clone SKB */
-		new_skb = skb_clone(skb, GFP_ATOMIC);
+		new_skb = netdev_alloc_skb_ip_align(dev->net, pkt_len);
 
 		if (!new_skb)
 			goto err;
 
-		new_skb->len = pkt_len;
+		skb_put(new_skb, pkt_len);
+		memcpy(new_skb->data, skb->data, pkt_len);
 		skb_pull(new_skb, AQ_RX_HW_PAD);
-		skb_set_tail_pointer(new_skb, new_skb->len);
 
-		new_skb->truesize = SKB_TRUESIZE(new_skb->len);
 		if (aqc111_data->rx_checksum)
 			aqc111_rx_checksum(new_skb, pkt_desc);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/usb/asix_common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/usb/asix_common.c
@@ -9,6 +9,8 @@
 
 #include "asix.h"
 
+#define AX_HOST_EN_RETRIES	30
+
 int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
 		  u16 size, void *data, int in_pm)
 {
@@ -63,6 +65,29 @@
 			       value, index, data, size);
 }
 
+static int asix_check_host_enable(struct usbnet *dev, int in_pm)
+{
+	int i, ret;
+	u8 smsr;
+
+	for (i = 0; i < AX_HOST_EN_RETRIES; ++i) {
+		ret = asix_set_sw_mii(dev, in_pm);
+		if (ret == -ENODEV || ret == -ETIMEDOUT)
+			break;
+		usleep_range(1000, 1100);
+		ret = asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG,
+				    0, 0, 1, &smsr, in_pm);
+		if (ret == -ENODEV)
+			break;
+		else if (ret < sizeof(smsr))
+			continue;
+		else if (smsr & AX_HOST_EN)
+			break;
+	}
+
+	return i >= AX_HOST_EN_RETRIES ? -ETIMEDOUT : ret;
+}
+
 static void reset_asix_rx_fixup_info(struct asix_rx_fixup_info *rx)
 {
 	/* Reset the variables that have a lifetime outside of
@@ -296,7 +321,7 @@
 
 	netdev_dbg(dev->net, "asix_get_phy_addr()\n");
 
-	if (ret < 0) {
+	if (ret < 2) {
 		netdev_err(dev->net, "Error reading PHYID register: %02x\n", ret);
 		goto out;
 	}
@@ -445,19 +470,11 @@
 {
 	struct usbnet *dev = netdev_priv(netdev);
 	__le16 res;
-	u8 smsr;
-	int i = 0;
 	int ret;
 
 	mutex_lock(&dev->phy_mutex);
-	do {
-		ret = asix_set_sw_mii(dev, 0);
-		if (ret == -ENODEV || ret == -ETIMEDOUT)
-			break;
-		usleep_range(1000, 1100);
-		ret = asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG,
-				    0, 0, 1, &smsr, 0);
-	} while (!(smsr & AX_HOST_EN) && (i++ < 30) && (ret != -ENODEV));
+
+	ret = asix_check_host_enable(dev, 0);
 	if (ret == -ENODEV || ret == -ETIMEDOUT) {
 		mutex_unlock(&dev->phy_mutex);
 		return ret;
@@ -478,22 +495,14 @@
 {
 	struct usbnet *dev = netdev_priv(netdev);
 	__le16 res = cpu_to_le16(val);
-	u8 smsr;
-	int i = 0;
 	int ret;
 
 	netdev_dbg(dev->net, "asix_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x\n",
 			phy_id, loc, val);
 
 	mutex_lock(&dev->phy_mutex);
-	do {
-		ret = asix_set_sw_mii(dev, 0);
-		if (ret == -ENODEV)
-			break;
-		usleep_range(1000, 1100);
-		ret = asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG,
-				    0, 0, 1, &smsr, 0);
-	} while (!(smsr & AX_HOST_EN) && (i++ < 30) && (ret != -ENODEV));
+
+	ret = asix_check_host_enable(dev, 0);
 	if (ret == -ENODEV) {
 		mutex_unlock(&dev->phy_mutex);
 		return;
@@ -509,19 +518,11 @@
 {
 	struct usbnet *dev = netdev_priv(netdev);
 	__le16 res;
-	u8 smsr;
-	int i = 0;
 	int ret;
 
 	mutex_lock(&dev->phy_mutex);
-	do {
-		ret = asix_set_sw_mii(dev, 1);
-		if (ret == -ENODEV || ret == -ETIMEDOUT)
-			break;
-		usleep_range(1000, 1100);
-		ret = asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG,
-				    0, 0, 1, &smsr, 1);
-	} while (!(smsr & AX_HOST_EN) && (i++ < 30) && (ret != -ENODEV));
+
+	ret = asix_check_host_enable(dev, 1);
 	if (ret == -ENODEV || ret == -ETIMEDOUT) {
 		mutex_unlock(&dev->phy_mutex);
 		return ret;
@@ -543,22 +544,14 @@
 {
 	struct usbnet *dev = netdev_priv(netdev);
 	__le16 res = cpu_to_le16(val);
-	u8 smsr;
-	int i = 0;
 	int ret;
 
 	netdev_dbg(dev->net, "asix_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x\n",
 			phy_id, loc, val);
 
 	mutex_lock(&dev->phy_mutex);
-	do {
-		ret = asix_set_sw_mii(dev, 1);
-		if (ret == -ENODEV)
-			break;
-		usleep_range(1000, 1100);
-		ret = asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG,
-				    0, 0, 1, &smsr, 1);
-	} while (!(smsr & AX_HOST_EN) && (i++ < 30) && (ret != -ENODEV));
+
+	ret = asix_check_host_enable(dev, 1);
 	if (ret == -ENODEV) {
 		mutex_unlock(&dev->phy_mutex);
 		return;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/usb/ax88172a.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/usb/ax88172a.c
@@ -186,7 +186,9 @@
 	u8 buf[ETH_ALEN];
 	struct ax88172a_private *priv;
 
-	usbnet_get_endpoints(dev, intf);
+	ret = usbnet_get_endpoints(dev, intf);
+	if (ret)
+		return ret;
 
 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 	if (!priv)
@@ -198,6 +200,7 @@
 	ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, buf, 0);
 	if (ret < ETH_ALEN) {
 		netdev_err(dev->net, "Failed to read MAC address: %d\n", ret);
+		ret = -EIO;
 		goto free;
 	}
 	memcpy(dev->net->dev_addr, buf, ETH_ALEN);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/usb/ax88179_178a.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/usb/ax88179_178a.c
@@ -295,12 +295,12 @@
 	int ret;
 
 	if (2 == size) {
-		u16 buf;
+		u16 buf = 0;
 		ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 0);
 		le16_to_cpus(&buf);
 		*((u16 *)data) = buf;
 	} else if (4 == size) {
-		u32 buf;
+		u32 buf = 0;
 		ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 0);
 		le32_to_cpus(&buf);
 		*((u32 *)data) = buf;
@@ -345,7 +345,8 @@
 
 	if (netif_carrier_ok(dev->net) != link) {
 		usbnet_link_change(dev, link, 1);
-		netdev_info(dev->net, "ax88179 - Link status is: %d\n", link);
+		if (!link)
+			netdev_info(dev->net, "ax88179 - Link status is: 0\n");
 	}
 }
 
@@ -1361,57 +1362,114 @@
 	u16 hdr_off;
 	u32 *pkt_hdr;
 
-	/* This check is no longer done by usbnet */
-	if (skb->len < dev->net->hard_header_len)
-		return 0;
+	/* At the end of the SKB, there's a header telling us how many packets
+	 * are bundled into this buffer and where we can find an array of
+	 * per-packet metadata (which contains elements encoded into u16).
+	 */
+
+	/* SKB contents for current firmware:
+	 *   <packet 1> <padding>
+	 *   ...
+	 *   <packet N> <padding>
+	 *   <per-packet metadata entry 1> <dummy header>
+	 *   ...
+	 *   <per-packet metadata entry N> <dummy header>
+	 *   <padding2> <rx_hdr>
+	 *
+	 * where:
+	 *   <packet N> contains pkt_len bytes:
+	 *		2 bytes of IP alignment pseudo header
+	 *		packet received
+	 *   <per-packet metadata entry N> contains 4 bytes:
+	 *		pkt_len and fields AX_RXHDR_*
+	 *   <padding>	0-7 bytes to terminate at
+	 *		8 bytes boundary (64-bit).
+	 *   <padding2> 4 bytes to make rx_hdr terminate at
+	 *		8 bytes boundary (64-bit)
+	 *   <dummy-header> contains 4 bytes:
+	 *		pkt_len=0 and AX_RXHDR_DROP_ERR
+	 *   <rx-hdr>	contains 4 bytes:
+	 *		pkt_cnt and hdr_off (offset of
+	 *		  <per-packet metadata entry 1>)
+	 *
+	 * pkt_cnt is number of entrys in the per-packet metadata.
+	 * In current firmware there is 2 entrys per packet.
+	 * The first points to the packet and the
+	 *  second is a dummy header.
+	 * This was done probably to align fields in 64-bit and
+	 *  maintain compatibility with old firmware.
+	 * This code assumes that <dummy header> and <padding2> are
+	 *  optional.
+	 */
 
+	if (skb->len < 4)
+		return 0;
 	skb_trim(skb, skb->len - 4);
 	rx_hdr = get_unaligned_le32(skb_tail_pointer(skb));
-
 	pkt_cnt = (u16)rx_hdr;
 	hdr_off = (u16)(rx_hdr >> 16);
+
+	if (pkt_cnt == 0)
+		return 0;
+
+	/* Make sure that the bounds of the metadata array are inside the SKB
+	 * (and in front of the counter at the end).
+	 */
+	if (pkt_cnt * 4 + hdr_off > skb->len)
+		return 0;
 	pkt_hdr = (u32 *)(skb->data + hdr_off);
 
-	while (pkt_cnt--) {
+	/* Packets must not overlap the metadata array */
+	skb_trim(skb, hdr_off);
+
+	for (; pkt_cnt > 0; pkt_cnt--, pkt_hdr++) {
+		u16 pkt_len_plus_padd;
 		u16 pkt_len;
 
 		le32_to_cpus(pkt_hdr);
 		pkt_len = (*pkt_hdr >> 16) & 0x1fff;
+		pkt_len_plus_padd = (pkt_len + 7) & 0xfff8;
+
+		/* Skip dummy header used for alignment
+		 */
+		if (pkt_len == 0)
+			continue;
+
+		if (pkt_len_plus_padd > skb->len)
+			return 0;
 
 		/* Check CRC or runt packet */
-		if ((*pkt_hdr & AX_RXHDR_CRC_ERR) ||
-		    (*pkt_hdr & AX_RXHDR_DROP_ERR)) {
-			skb_pull(skb, (pkt_len + 7) & 0xFFF8);
-			pkt_hdr++;
+		if ((*pkt_hdr & (AX_RXHDR_CRC_ERR | AX_RXHDR_DROP_ERR)) ||
+		    pkt_len < 2 + ETH_HLEN) {
+			dev->net->stats.rx_errors++;
+			skb_pull(skb, pkt_len_plus_padd);
 			continue;
 		}
 
-		if (pkt_cnt == 0) {
-			/* Skip IP alignment psudo header */
+		/* last packet */
+		if (pkt_len_plus_padd == skb->len) {
+			skb_trim(skb, pkt_len);
+
+			/* Skip IP alignment pseudo header */
 			skb_pull(skb, 2);
-			skb->len = pkt_len;
-			skb_set_tail_pointer(skb, pkt_len);
-			skb->truesize = pkt_len + sizeof(struct sk_buff);
+
 			ax88179_rx_checksum(skb, pkt_hdr);
 			return 1;
 		}
 
-		ax_skb = skb_clone(skb, GFP_ATOMIC);
-		if (ax_skb) {
-			ax_skb->len = pkt_len;
-			ax_skb->data = skb->data + 2;
-			skb_set_tail_pointer(ax_skb, pkt_len);
-			ax_skb->truesize = pkt_len + sizeof(struct sk_buff);
-			ax88179_rx_checksum(ax_skb, pkt_hdr);
-			usbnet_skb_return(dev, ax_skb);
-		} else {
+		ax_skb = netdev_alloc_skb_ip_align(dev->net, pkt_len);
+		if (!ax_skb)
 			return 0;
-		}
+		skb_put(ax_skb, pkt_len);
+		memcpy(ax_skb->data, skb->data + 2, pkt_len);
+
+		ax88179_rx_checksum(ax_skb, pkt_hdr);
+		usbnet_skb_return(dev, ax_skb);
 
-		skb_pull(skb, (pkt_len + 7) & 0xFFF8);
-		pkt_hdr++;
+		skb_pull(skb, pkt_len_plus_padd);
 	}
-	return 1;
+
+	return 0;
 }
 
 static struct sk_buff *
@@ -1475,6 +1533,7 @@
 			 GMII_PHY_PHYSR, 2, &tmp16);
 
 	if (!(tmp16 & GMII_PHY_PHYSR_LINK)) {
+		netdev_info(dev->net, "ax88179 - Link status is: 0\n");
 		return 0;
 	} else if (GMII_PHY_PHYSR_GIGA == (tmp16 & GMII_PHY_PHYSR_SMASK)) {
 		mode |= AX_MEDIUM_GIGAMODE | AX_MEDIUM_EN_125MHZ;
@@ -1512,6 +1571,8 @@
 
 	netif_carrier_on(dev->net);
 
+	netdev_info(dev->net, "ax88179 - Link status is: 1\n");
+
 	return 0;
 }
 
@@ -1532,11 +1593,11 @@
 
 	*tmp16 = AX_PHYPWR_RSTCTL_IPRL;
 	ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, tmp16);
-	msleep(200);
+	msleep(500);
 
 	*tmp = AX_CLK_SELECT_ACS | AX_CLK_SELECT_BCS;
 	ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, tmp);
-	msleep(100);
+	msleep(200);
 
 	/* Ethernet PHY Auto Detach*/
 	ax88179_auto_detach(dev, 0);
@@ -1718,6 +1779,7 @@
 	.status = ax88179_status,
 	.link_reset = ax88179_link_reset,
 	.reset	= ax88179_reset,
+	.stop	= ax88179_stop,
 	.flags	= FLAG_ETHER | FLAG_FRAMING_AX,
 	.rx_fixup = ax88179_rx_fixup,
 	.tx_fixup = ax88179_tx_fixup,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/usb/cdc-phonet.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/usb/cdc-phonet.c
@@ -387,6 +387,8 @@
 
 	err = register_netdev(dev);
 	if (err) {
+		/* Set disconnected flag so that disconnect() returns early. */
+		pnd->disconnected = 1;
 		usb_driver_release_interface(&usbpn_driver, data_intf);
 		goto out;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/usb/cdc_eem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/usb/cdc_eem.c
@@ -123,10 +123,10 @@
 	}
 
 	skb2 = skb_copy_expand(skb, EEM_HEAD, ETH_FCS_LEN + padlen, flags);
+	dev_kfree_skb_any(skb);
 	if (!skb2)
 		return NULL;
 
-	dev_kfree_skb_any(skb);
 	skb = skb2;
 
 done:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/usb/cdc_ether.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/usb/cdc_ether.c
@@ -571,6 +571,11 @@
 	.bInterfaceSubClass	= USB_CDC_SUBCLASS_ETHERNET, \
 	.bInterfaceProtocol	= USB_CDC_PROTO_NONE
 
+#define ZAURUS_FAKE_INTERFACE \
+	.bInterfaceClass	= USB_CLASS_COMM, \
+	.bInterfaceSubClass	= USB_CDC_SUBCLASS_MDLM, \
+	.bInterfaceProtocol	= USB_CDC_PROTO_NONE
+
 /* SA-1100 based Sharp Zaurus ("collie"), or compatible;
  * wire-incompatible with true CDC Ethernet implementations.
  * (And, it seems, needlessly so...)
@@ -600,6 +605,13 @@
 	.match_flags	=   USB_DEVICE_ID_MATCH_INT_INFO
 			  | USB_DEVICE_ID_MATCH_DEVICE,
 	.idVendor		= 0x04DD,
+	.idProduct		= 0x8005,   /* A-300 */
+	ZAURUS_FAKE_INTERFACE,
+	.driver_info        = 0,
+}, {
+	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
+			  | USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor		= 0x04DD,
 	.idProduct		= 0x8006,	/* B-500/SL-5600 */
 	ZAURUS_MASTER_INTERFACE,
 	.driver_info		= 0,
@@ -607,11 +619,25 @@
 	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
 			  | USB_DEVICE_ID_MATCH_DEVICE,
 	.idVendor		= 0x04DD,
+	.idProduct		= 0x8006,   /* B-500/SL-5600 */
+	ZAURUS_FAKE_INTERFACE,
+	.driver_info        = 0,
+}, {
+	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
+			  | USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor		= 0x04DD,
 	.idProduct		= 0x8007,	/* C-700 */
 	ZAURUS_MASTER_INTERFACE,
 	.driver_info		= 0,
 }, {
 	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
+			  | USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor		= 0x04DD,
+	.idProduct		= 0x8007,   /* C-700 */
+	ZAURUS_FAKE_INTERFACE,
+	.driver_info        = 0,
+}, {
+	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
 		 | USB_DEVICE_ID_MATCH_DEVICE,
 	.idVendor               = 0x04DD,
 	.idProduct              = 0x9031,	/* C-750 C-760 */
@@ -628,6 +654,13 @@
 	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
 		 | USB_DEVICE_ID_MATCH_DEVICE,
 	.idVendor               = 0x04DD,
+	.idProduct              = 0x9032,	/* SL-6000 */
+	ZAURUS_FAKE_INTERFACE,
+	.driver_info		= 0,
+}, {
+	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
+		 | USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor               = 0x04DD,
 	/* reported with some C860 units */
 	.idProduct              = 0x9050,	/* C-860 */
 	ZAURUS_MASTER_INTERFACE,
@@ -752,6 +785,13 @@
 },
 #endif
 
+/* Lenovo ThinkPad OneLink+ Dock (based on Realtek RTL8153) */
+{
+	USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3054, USB_CLASS_COMM,
+			USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
+	.driver_info = 0,
+},
+
 /* ThinkPad USB-C Dock (based on Realtek RTL8153) */
 {
 	USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3062, USB_CLASS_COMM,
@@ -766,6 +806,13 @@
 	.driver_info = 0,
 },
 
+/* ThinkPad Thunderbolt 3 Dock Gen 2 (based on Realtek RTL8153) */
+{
+	USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3082, USB_CLASS_COMM,
+			USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
+	.driver_info = 0,
+},
+
 /* Lenovo Thinkpad USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */
 {
 	USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x7205, USB_CLASS_COMM,
@@ -787,6 +834,13 @@
 	.driver_info = 0,
 },
 
+/* Lenovo Powered USB-C Travel Hub (4X90S92381, based on Realtek RTL8153) */
+{
+	USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x721e, USB_CLASS_COMM,
+			USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
+	.driver_info = 0,
+},
+
 /* ThinkPad USB-C Dock Gen 2 (based on Realtek RTL8153) */
 {
 	USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0xa387, USB_CLASS_COMM,
@@ -808,14 +862,21 @@
 	.driver_info = 0,
 },
 
-/* Microsoft Surface 3 dock (based on Realtek RTL8153) */
+/* Microsoft Surface Ethernet Adapter (based on Realtek RTL8153) */
 {
 	USB_DEVICE_AND_INTERFACE_INFO(MICROSOFT_VENDOR_ID, 0x07c6, USB_CLASS_COMM,
 			USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
 	.driver_info = 0,
 },
 
-	/* TP-LINK UE300 USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */
+/* Microsoft Surface Ethernet Adapter (based on Realtek RTL8153B) */
+{
+	USB_DEVICE_AND_INTERFACE_INFO(MICROSOFT_VENDOR_ID, 0x0927, USB_CLASS_COMM,
+			USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
+	.driver_info = 0,
+},
+
+/* TP-LINK UE300 USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */
 {
 	USB_DEVICE_AND_INTERFACE_INFO(TPLINK_VENDOR_ID, 0x0601, USB_CLASS_COMM,
 			USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/usb/cdc_mbim.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/usb/cdc_mbim.c
@@ -653,6 +653,21 @@
 	  .driver_info = (unsigned long)&cdc_mbim_info_avoid_altsetting_toggle,
 	},
 
+	/* Telit LN920 */
+	{ USB_DEVICE_AND_INTERFACE_INFO(0x1bc7, 0x1061, USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
+	  .driver_info = (unsigned long)&cdc_mbim_info_avoid_altsetting_toggle,
+	},
+
+	/* Telit FN990 */
+	{ USB_DEVICE_AND_INTERFACE_INFO(0x1bc7, 0x1071, USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
+	  .driver_info = (unsigned long)&cdc_mbim_info_avoid_altsetting_toggle,
+	},
+
+	/* Telit FE990 */
+	{ USB_DEVICE_AND_INTERFACE_INFO(0x1bc7, 0x1081, USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
+	  .driver_info = (unsigned long)&cdc_mbim_info_avoid_altsetting_toggle,
+	},
+
 	/* default entry */
 	{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
 	  .driver_info = (unsigned long)&cdc_mbim_info_zlp,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/usb/cdc_ncm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/usb/cdc_ncm.c
@@ -175,8 +175,17 @@
 	u32 val, max, min;
 
 	/* clamp new_tx to sane values */
-	min = ctx->max_datagram_size + ctx->max_ndp_size + sizeof(struct usb_cdc_ncm_nth16);
-	max = min_t(u32, CDC_NCM_NTB_MAX_SIZE_TX, le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize));
+	if (ctx->is_ndp16)
+		min = ctx->max_datagram_size + ctx->max_ndp_size + sizeof(struct usb_cdc_ncm_nth16);
+	else
+		min = ctx->max_datagram_size + ctx->max_ndp_size + sizeof(struct usb_cdc_ncm_nth32);
+
+	if (le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize) == 0)
+		max = CDC_NCM_NTB_MAX_SIZE_TX; /* dwNtbOutMaxSize not set */
+	else
+		max = clamp_t(u32, le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize),
+			      USB_CDC_NCM_NTB_MIN_OUT_SIZE,
+			      CDC_NCM_NTB_MAX_SIZE_TX);
 
 	/* some devices set dwNtbOutMaxSize too low for the above default */
 	min = min(min, max);
@@ -307,10 +316,17 @@
 	if (enable == (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END))
 		return len;
 
-	if (enable && !ctx->delayed_ndp16) {
-		ctx->delayed_ndp16 = kzalloc(ctx->max_ndp_size, GFP_KERNEL);
-		if (!ctx->delayed_ndp16)
-			return -ENOMEM;
+	if (enable) {
+		if (ctx->is_ndp16 && !ctx->delayed_ndp16) {
+			ctx->delayed_ndp16 = kzalloc(ctx->max_ndp_size, GFP_KERNEL);
+			if (!ctx->delayed_ndp16)
+				return -ENOMEM;
+		}
+		if (!ctx->is_ndp16 && !ctx->delayed_ndp32) {
+			ctx->delayed_ndp32 = kzalloc(ctx->max_ndp_size, GFP_KERNEL);
+			if (!ctx->delayed_ndp32)
+				return -ENOMEM;
+		}
 	}
 
 	/* flush pending data before changing flag */
@@ -512,6 +528,9 @@
 			dev_err(&dev->intf->dev, "SET_CRC_MODE failed\n");
 	}
 
+	/* use ndp16 by default */
+	ctx->is_ndp16 = 1;
+
 	/* set NTB format, if both formats are supported.
 	 *
 	 * "The host shall only send this command while the NCM Data
@@ -519,14 +538,27 @@
 	 */
 	if (le16_to_cpu(ctx->ncm_parm.bmNtbFormatsSupported) &
 						USB_CDC_NCM_NTB32_SUPPORTED) {
-		dev_dbg(&dev->intf->dev, "Setting NTB format to 16-bit\n");
-		err = usbnet_write_cmd(dev, USB_CDC_SET_NTB_FORMAT,
-				       USB_TYPE_CLASS | USB_DIR_OUT
-				       | USB_RECIP_INTERFACE,
-				       USB_CDC_NCM_NTB16_FORMAT,
-				       iface_no, NULL, 0);
-		if (err < 0)
+		if (ctx->drvflags & CDC_NCM_FLAG_PREFER_NTB32) {
+			ctx->is_ndp16 = 0;
+			dev_dbg(&dev->intf->dev, "Setting NTB format to 32-bit\n");
+			err = usbnet_write_cmd(dev, USB_CDC_SET_NTB_FORMAT,
+					       USB_TYPE_CLASS | USB_DIR_OUT
+					       | USB_RECIP_INTERFACE,
+					       USB_CDC_NCM_NTB32_FORMAT,
+					       iface_no, NULL, 0);
+		} else {
+			ctx->is_ndp16 = 1;
+			dev_dbg(&dev->intf->dev, "Setting NTB format to 16-bit\n");
+			err = usbnet_write_cmd(dev, USB_CDC_SET_NTB_FORMAT,
+					       USB_TYPE_CLASS | USB_DIR_OUT
+					       | USB_RECIP_INTERFACE,
+					       USB_CDC_NCM_NTB16_FORMAT,
+					       iface_no, NULL, 0);
+		}
+		if (err < 0) {
+			ctx->is_ndp16 = 1;
 			dev_err(&dev->intf->dev, "SET_NTB_FORMAT failed\n");
+		}
 	}
 
 	/* set initial device values */
@@ -549,7 +581,10 @@
 		ctx->tx_max_datagrams = CDC_NCM_DPT_DATAGRAMS_MAX;
 
 	/* set up maximum NDP size */
-	ctx->max_ndp_size = sizeof(struct usb_cdc_ncm_ndp16) + (ctx->tx_max_datagrams + 1) * sizeof(struct usb_cdc_ncm_dpe16);
+	if (ctx->is_ndp16)
+		ctx->max_ndp_size = sizeof(struct usb_cdc_ncm_ndp16) + (ctx->tx_max_datagrams + 1) * sizeof(struct usb_cdc_ncm_dpe16);
+	else
+		ctx->max_ndp_size = sizeof(struct usb_cdc_ncm_ndp32) + (ctx->tx_max_datagrams + 1) * sizeof(struct usb_cdc_ncm_dpe32);
 
 	/* initial coalescing timer interval */
 	ctx->timer_interval = CDC_NCM_TIMER_INTERVAL_USEC * NSEC_PER_USEC;
@@ -734,7 +769,10 @@
 		ctx->tx_curr_skb = NULL;
 	}
 
-	kfree(ctx->delayed_ndp16);
+	if (ctx->is_ndp16)
+		kfree(ctx->delayed_ndp16);
+	else
+		kfree(ctx->delayed_ndp32);
 
 	kfree(ctx);
 }
@@ -772,10 +810,8 @@
 	u8 *buf;
 	int len;
 	int temp;
-	int err;
 	u8 iface_no;
 	struct usb_cdc_parsed_header hdr;
-	__le16 curr_ntb_format;
 
 	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
 	if (!ctx)
@@ -879,32 +915,6 @@
 		goto error2;
 	}
 
-	/*
-	 * Some Huawei devices have been observed to come out of reset in NDP32 mode.
-	 * Let's check if this is the case, and set the device to NDP16 mode again if
-	 * needed.
-	*/
-	if (ctx->drvflags & CDC_NCM_FLAG_RESET_NTB16) {
-		err = usbnet_read_cmd(dev, USB_CDC_GET_NTB_FORMAT,
-				      USB_TYPE_CLASS | USB_DIR_IN | USB_RECIP_INTERFACE,
-				      0, iface_no, &curr_ntb_format, 2);
-		if (err < 0) {
-			goto error2;
-		}
-
-		if (curr_ntb_format == cpu_to_le16(USB_CDC_NCM_NTB32_FORMAT)) {
-			dev_info(&intf->dev, "resetting NTB format to 16-bit");
-			err = usbnet_write_cmd(dev, USB_CDC_SET_NTB_FORMAT,
-					       USB_TYPE_CLASS | USB_DIR_OUT
-					       | USB_RECIP_INTERFACE,
-					       USB_CDC_NCM_NTB16_FORMAT,
-					       iface_no, NULL, 0);
-
-			if (err < 0)
-				goto error2;
-		}
-	}
-
 	cdc_ncm_find_endpoints(dev, ctx->data);
 	cdc_ncm_find_endpoints(dev, ctx->control);
 	if (!dev->in || !dev->out || !dev->status) {
@@ -929,9 +939,15 @@
 
 	/* Allocate the delayed NDP if needed. */
 	if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) {
-		ctx->delayed_ndp16 = kzalloc(ctx->max_ndp_size, GFP_KERNEL);
-		if (!ctx->delayed_ndp16)
-			goto error2;
+		if (ctx->is_ndp16) {
+			ctx->delayed_ndp16 = kzalloc(ctx->max_ndp_size, GFP_KERNEL);
+			if (!ctx->delayed_ndp16)
+				goto error2;
+		} else {
+			ctx->delayed_ndp32 = kzalloc(ctx->max_ndp_size, GFP_KERNEL);
+			if (!ctx->delayed_ndp32)
+				goto error2;
+		}
 		dev_info(&intf->dev, "NDP will be placed at end of frame for this device.");
 	}
 
@@ -1055,7 +1071,7 @@
 /* return a pointer to a valid struct usb_cdc_ncm_ndp16 of type sign, possibly
  * allocating a new one within skb
  */
-static struct usb_cdc_ncm_ndp16 *cdc_ncm_ndp(struct cdc_ncm_ctx *ctx, struct sk_buff *skb, __le32 sign, size_t reserve)
+static struct usb_cdc_ncm_ndp16 *cdc_ncm_ndp16(struct cdc_ncm_ctx *ctx, struct sk_buff *skb, __le32 sign, size_t reserve)
 {
 	struct usb_cdc_ncm_ndp16 *ndp16 = NULL;
 	struct usb_cdc_ncm_nth16 *nth16 = (void *)skb->data;
@@ -1110,12 +1126,73 @@
 	return ndp16;
 }
 
+static struct usb_cdc_ncm_ndp32 *cdc_ncm_ndp32(struct cdc_ncm_ctx *ctx, struct sk_buff *skb, __le32 sign, size_t reserve)
+{
+	struct usb_cdc_ncm_ndp32 *ndp32 = NULL;
+	struct usb_cdc_ncm_nth32 *nth32 = (void *)skb->data;
+	size_t ndpoffset = le32_to_cpu(nth32->dwNdpIndex);
+
+	/* If NDP should be moved to the end of the NCM package, we can't follow the
+	 * NTH32 header as we would normally do. NDP isn't written to the SKB yet, and
+	 * the wNdpIndex field in the header is actually not consistent with reality. It will be later.
+	 */
+	if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) {
+		if (ctx->delayed_ndp32->dwSignature == sign)
+			return ctx->delayed_ndp32;
+
+		/* We can only push a single NDP to the end. Return
+		 * NULL to send what we've already got and queue this
+		 * skb for later.
+		 */
+		else if (ctx->delayed_ndp32->dwSignature)
+			return NULL;
+	}
+
+	/* follow the chain of NDPs, looking for a match */
+	while (ndpoffset) {
+		ndp32 = (struct usb_cdc_ncm_ndp32 *)(skb->data + ndpoffset);
+		if  (ndp32->dwSignature == sign)
+			return ndp32;
+		ndpoffset = le32_to_cpu(ndp32->dwNextNdpIndex);
+	}
+
+	/* align new NDP */
+	if (!(ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END))
+		cdc_ncm_align_tail(skb, ctx->tx_ndp_modulus, 0, ctx->tx_curr_size);
+
+	/* verify that there is room for the NDP and the datagram (reserve) */
+	if ((ctx->tx_curr_size - skb->len - reserve) < ctx->max_ndp_size)
+		return NULL;
+
+	/* link to it */
+	if (ndp32)
+		ndp32->dwNextNdpIndex = cpu_to_le32(skb->len);
+	else
+		nth32->dwNdpIndex = cpu_to_le32(skb->len);
+
+	/* push a new empty NDP */
+	if (!(ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END))
+		ndp32 = skb_put_zero(skb, ctx->max_ndp_size);
+	else
+		ndp32 = ctx->delayed_ndp32;
+
+	ndp32->dwSignature = sign;
+	ndp32->wLength = cpu_to_le16(sizeof(struct usb_cdc_ncm_ndp32) + sizeof(struct usb_cdc_ncm_dpe32));
+	return ndp32;
+}
+
 struct sk_buff *
 cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign)
 {
 	struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
-	struct usb_cdc_ncm_nth16 *nth16;
-	struct usb_cdc_ncm_ndp16 *ndp16;
+	union {
+		struct usb_cdc_ncm_nth16 *nth16;
+		struct usb_cdc_ncm_nth32 *nth32;
+	} nth;
+	union {
+		struct usb_cdc_ncm_ndp16 *ndp16;
+		struct usb_cdc_ncm_ndp32 *ndp32;
+	} ndp;
 	struct sk_buff *skb_out;
 	u16 n = 0, index, ndplen;
 	u8 ready2send = 0;
@@ -1126,7 +1203,10 @@
 	 * accordingly. Otherwise, we should check here.
 	 */
 	if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END)
-		delayed_ndp_size = ALIGN(ctx->max_ndp_size, ctx->tx_ndp_modulus);
+		delayed_ndp_size = ctx->max_ndp_size +
+			max_t(u32,
+			      ctx->tx_ndp_modulus,
+			      ctx->tx_modulus + ctx->tx_remainder) - 1;
 	else
 		delayed_ndp_size = 0;
 
@@ -1152,6 +1232,9 @@
 			 * further.
 			 */
 			if (skb_out == NULL) {
+				/* If even the smallest allocation fails, abort. */
+				if (ctx->tx_curr_size == USB_CDC_NCM_NTB_MIN_OUT_SIZE)
+					goto alloc_failed;
 				ctx->tx_low_mem_max_cnt = min(ctx->tx_low_mem_max_cnt + 1,
 							      (unsigned)CDC_NCM_LOW_MEM_MAX_CNT);
 				ctx->tx_low_mem_val = ctx->tx_low_mem_max_cnt;
@@ -1170,20 +1253,23 @@
 			skb_out = alloc_skb(ctx->tx_curr_size, GFP_ATOMIC);
 
 			/* No allocation possible so we will abort */
-			if (skb_out == NULL) {
-				if (skb != NULL) {
-					dev_kfree_skb_any(skb);
-					dev->net->stats.tx_dropped++;
-				}
-				goto exit_no_skb;
-			}
+			if (!skb_out)
+				goto alloc_failed;
 			ctx->tx_low_mem_val--;
 		}
-		/* fill out the initial 16-bit NTB header */
-		nth16 = skb_put_zero(skb_out, sizeof(struct usb_cdc_ncm_nth16));
-		nth16->dwSignature = cpu_to_le32(USB_CDC_NCM_NTH16_SIGN);
-		nth16->wHeaderLength = cpu_to_le16(sizeof(struct usb_cdc_ncm_nth16));
-		nth16->wSequence = cpu_to_le16(ctx->tx_seq++);
+		if (ctx->is_ndp16) {
+			/* fill out the initial 16-bit NTB header */
+			nth.nth16 = skb_put_zero(skb_out, sizeof(struct usb_cdc_ncm_nth16));
+			nth.nth16->dwSignature = cpu_to_le32(USB_CDC_NCM_NTH16_SIGN);
+			nth.nth16->wHeaderLength = cpu_to_le16(sizeof(struct usb_cdc_ncm_nth16));
+			nth.nth16->wSequence = cpu_to_le16(ctx->tx_seq++);
+		} else {
+			/* fill out the initial 32-bit NTB header */
+			nth.nth32 = skb_put_zero(skb_out, sizeof(struct usb_cdc_ncm_nth32));
+			nth.nth32->dwSignature = cpu_to_le32(USB_CDC_NCM_NTH32_SIGN);
+			nth.nth32->wHeaderLength = cpu_to_le16(sizeof(struct usb_cdc_ncm_nth32));
+			nth.nth32->wSequence = cpu_to_le16(ctx->tx_seq++);
+		}
 
 		/* count total number of frames in this NTB */
 		ctx->tx_curr_frame_num = 0;
@@ -1205,13 +1291,17 @@
 		}
 
 		/* get the appropriate NDP for this skb */
-		ndp16 = cdc_ncm_ndp(ctx, skb_out, sign, skb->len + ctx->tx_modulus + ctx->tx_remainder);
+		if (ctx->is_ndp16)
+			ndp.ndp16 = cdc_ncm_ndp16(ctx, skb_out, sign, skb->len + ctx->tx_modulus + ctx->tx_remainder);
+		else
+			ndp.ndp32 = cdc_ncm_ndp32(ctx, skb_out, sign, skb->len + ctx->tx_modulus + ctx->tx_remainder);
 
 		/* align beginning of next frame */
 		cdc_ncm_align_tail(skb_out,  ctx->tx_modulus, ctx->tx_remainder, ctx->tx_curr_size);
 
 		/* check if we had enough room left for both NDP and frame */
-		if (!ndp16 || skb_out->len + skb->len + delayed_ndp_size > ctx->tx_curr_size) {
+		if ((ctx->is_ndp16 && !ndp.ndp16) || (!ctx->is_ndp16 && !ndp.ndp32) ||
+		    skb_out->len + skb->len + delayed_ndp_size > ctx->tx_curr_size) {
 			if (n == 0) {
 				/* won't fit, MTU problem? */
 				dev_kfree_skb_any(skb);
@@ -1233,13 +1323,22 @@
 		}
 
 		/* calculate frame number withing this NDP */
-		ndplen = le16_to_cpu(ndp16->wLength);
-		index = (ndplen - sizeof(struct usb_cdc_ncm_ndp16)) / sizeof(struct usb_cdc_ncm_dpe16) - 1;
+		if (ctx->is_ndp16) {
+			ndplen = le16_to_cpu(ndp.ndp16->wLength);
+			index = (ndplen - sizeof(struct usb_cdc_ncm_ndp16)) / sizeof(struct usb_cdc_ncm_dpe16) - 1;
+
+			/* OK, add this skb */
+			ndp.ndp16->dpe16[index].wDatagramLength = cpu_to_le16(skb->len);
+			ndp.ndp16->dpe16[index].wDatagramIndex = cpu_to_le16(skb_out->len);
+			ndp.ndp16->wLength = cpu_to_le16(ndplen + sizeof(struct usb_cdc_ncm_dpe16));
+		} else {
+			ndplen = le16_to_cpu(ndp.ndp32->wLength);
+			index = (ndplen - sizeof(struct usb_cdc_ncm_ndp32)) / sizeof(struct usb_cdc_ncm_dpe32) - 1;
 
-		/* OK, add this skb */
-		ndp16->dpe16[index].wDatagramLength = cpu_to_le16(skb->len);
-		ndp16->dpe16[index].wDatagramIndex = cpu_to_le16(skb_out->len);
-		ndp16->wLength = cpu_to_le16(ndplen + sizeof(struct usb_cdc_ncm_dpe16));
+			ndp.ndp32->dpe32[index].dwDatagramLength = cpu_to_le32(skb->len);
+			ndp.ndp32->dpe32[index].dwDatagramIndex = cpu_to_le32(skb_out->len);
+			ndp.ndp32->wLength = cpu_to_le16(ndplen + sizeof(struct usb_cdc_ncm_dpe32));
+		}
 		skb_put_data(skb_out, skb->data, skb->len);
 		ctx->tx_curr_frame_payload += skb->len;	/* count real tx payload data */
 		dev_kfree_skb_any(skb);
@@ -1286,13 +1385,22 @@
 
 	/* If requested, put NDP at end of frame. */
 	if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) {
-		nth16 = (struct usb_cdc_ncm_nth16 *)skb_out->data;
-		cdc_ncm_align_tail(skb_out, ctx->tx_ndp_modulus, 0, ctx->tx_curr_size - ctx->max_ndp_size);
-		nth16->wNdpIndex = cpu_to_le16(skb_out->len);
-		skb_put_data(skb_out, ctx->delayed_ndp16, ctx->max_ndp_size);
+		if (ctx->is_ndp16) {
+			nth.nth16 = (struct usb_cdc_ncm_nth16 *)skb_out->data;
+			cdc_ncm_align_tail(skb_out, ctx->tx_ndp_modulus, 0, ctx->tx_curr_size - ctx->max_ndp_size);
+			nth.nth16->wNdpIndex = cpu_to_le16(skb_out->len);
+			skb_put_data(skb_out, ctx->delayed_ndp16, ctx->max_ndp_size);
+
+			/* Zero out delayed NDP - signature checking will naturally fail. */
+			ndp.ndp16 = memset(ctx->delayed_ndp16, 0, ctx->max_ndp_size);
+		} else {
+			nth.nth32 = (struct usb_cdc_ncm_nth32 *)skb_out->data;
+			cdc_ncm_align_tail(skb_out, ctx->tx_ndp_modulus, 0, ctx->tx_curr_size - ctx->max_ndp_size);
+			nth.nth32->dwNdpIndex = cpu_to_le32(skb_out->len);
+			skb_put_data(skb_out, ctx->delayed_ndp32, ctx->max_ndp_size);
 
-		/* Zero out delayed NDP - signature checking will naturally fail. */
-		ndp16 = memset(ctx->delayed_ndp16, 0, ctx->max_ndp_size);
+			ndp.ndp32 = memset(ctx->delayed_ndp32, 0, ctx->max_ndp_size);
+		}
 	}
 
 	/* If collected data size is less or equal ctx->min_tx_pkt
@@ -1307,15 +1415,21 @@
 	if (!(dev->driver_info->flags & FLAG_SEND_ZLP) &&
 	    skb_out->len > ctx->min_tx_pkt) {
 		padding_count = ctx->tx_curr_size - skb_out->len;
-		skb_put_zero(skb_out, padding_count);
+		if (!WARN_ON(padding_count > ctx->tx_curr_size))
+			skb_put_zero(skb_out, padding_count);
 	} else if (skb_out->len < ctx->tx_curr_size &&
 		   (skb_out->len % dev->maxpacket) == 0) {
 		skb_put_u8(skb_out, 0);	/* force short packet */
 	}
 
 	/* set final frame length */
-	nth16 = (struct usb_cdc_ncm_nth16 *)skb_out->data;
-	nth16->wBlockLength = cpu_to_le16(skb_out->len);
+	if (ctx->is_ndp16) {
+		nth.nth16 = (struct usb_cdc_ncm_nth16 *)skb_out->data;
+		nth.nth16->wBlockLength = cpu_to_le16(skb_out->len);
+	} else {
+		nth.nth32 = (struct usb_cdc_ncm_nth32 *)skb_out->data;
+		nth.nth32->dwBlockLength = cpu_to_le32(skb_out->len);
+	}
 
 	/* return skb */
 	ctx->tx_curr_skb = NULL;
@@ -1333,6 +1447,11 @@
 
 	return skb_out;
 
+alloc_failed:
+	if (skb) {
+		dev_kfree_skb_any(skb);
+		dev->net->stats.tx_dropped++;
+	}
 exit_no_skb:
 	/* Start timer, if there is a remaining non-empty skb */
 	if (ctx->tx_curr_skb != NULL && n > 0)
@@ -1398,7 +1517,12 @@
 		goto error;
 
 	spin_lock_bh(&ctx->mtx);
-	skb_out = cdc_ncm_fill_tx_frame(dev, skb, cpu_to_le32(USB_CDC_NCM_NDP16_NOCRC_SIGN));
+
+	if (ctx->is_ndp16)
+		skb_out = cdc_ncm_fill_tx_frame(dev, skb, cpu_to_le32(USB_CDC_NCM_NDP16_NOCRC_SIGN));
+	else
+		skb_out = cdc_ncm_fill_tx_frame(dev, skb, cpu_to_le32(USB_CDC_NCM_NDP32_NOCRC_SIGN));
+
 	spin_unlock_bh(&ctx->mtx);
 	return skb_out;
 
@@ -1459,6 +1583,54 @@
 }
 EXPORT_SYMBOL_GPL(cdc_ncm_rx_verify_nth16);
 
+int cdc_ncm_rx_verify_nth32(struct cdc_ncm_ctx *ctx, struct sk_buff *skb_in)
+{
+	struct usbnet *dev = netdev_priv(skb_in->dev);
+	struct usb_cdc_ncm_nth32 *nth32;
+	int len;
+	int ret = -EINVAL;
+
+	if (ctx == NULL)
+		goto error;
+
+	if (skb_in->len < (sizeof(struct usb_cdc_ncm_nth32) +
+					sizeof(struct usb_cdc_ncm_ndp32))) {
+		netif_dbg(dev, rx_err, dev->net, "frame too short\n");
+		goto error;
+	}
+
+	nth32 = (struct usb_cdc_ncm_nth32 *)skb_in->data;
+
+	if (nth32->dwSignature != cpu_to_le32(USB_CDC_NCM_NTH32_SIGN)) {
+		netif_dbg(dev, rx_err, dev->net,
+			  "invalid NTH32 signature <%#010x>\n",
+			  le32_to_cpu(nth32->dwSignature));
+		goto error;
+	}
+
+	len = le32_to_cpu(nth32->dwBlockLength);
+	if (len > ctx->rx_max) {
+		netif_dbg(dev, rx_err, dev->net,
+			  "unsupported NTB block length %u/%u\n", len,
+			  ctx->rx_max);
+		goto error;
+	}
+
+	if ((ctx->rx_seq + 1) != le16_to_cpu(nth32->wSequence) &&
+	    (ctx->rx_seq || le16_to_cpu(nth32->wSequence)) &&
+	    !((ctx->rx_seq == 0xffff) && !le16_to_cpu(nth32->wSequence))) {
+		netif_dbg(dev, rx_err, dev->net,
+			  "sequence number glitch prev=%d curr=%d\n",
+			  ctx->rx_seq, le16_to_cpu(nth32->wSequence));
+	}
+	ctx->rx_seq = le16_to_cpu(nth32->wSequence);
+
+	ret = le32_to_cpu(nth32->dwNdpIndex);
+error:
+	return ret;
+}
+EXPORT_SYMBOL_GPL(cdc_ncm_rx_verify_nth32);
+
 /* verify NDP header and return number of datagrams, or negative error */
 int cdc_ncm_rx_verify_ndp16(struct sk_buff *skb_in, int ndpoffset)
 {
@@ -1495,42 +1667,110 @@
 }
 EXPORT_SYMBOL_GPL(cdc_ncm_rx_verify_ndp16);
 
+/* verify NDP header and return number of datagrams, or negative error */
+int cdc_ncm_rx_verify_ndp32(struct sk_buff *skb_in, int ndpoffset)
+{
+	struct usbnet *dev = netdev_priv(skb_in->dev);
+	struct usb_cdc_ncm_ndp32 *ndp32;
+	int ret = -EINVAL;
+
+	if ((ndpoffset + sizeof(struct usb_cdc_ncm_ndp32)) > skb_in->len) {
+		netif_dbg(dev, rx_err, dev->net, "invalid NDP offset  <%u>\n",
+			  ndpoffset);
+		goto error;
+	}
+	ndp32 = (struct usb_cdc_ncm_ndp32 *)(skb_in->data + ndpoffset);
+
+	if (le16_to_cpu(ndp32->wLength) < USB_CDC_NCM_NDP32_LENGTH_MIN) {
+		netif_dbg(dev, rx_err, dev->net, "invalid DPT32 length <%u>\n",
+			  le16_to_cpu(ndp32->wLength));
+		goto error;
+	}
+
+	ret = ((le16_to_cpu(ndp32->wLength) -
+					sizeof(struct usb_cdc_ncm_ndp32)) /
+					sizeof(struct usb_cdc_ncm_dpe32));
+	ret--; /* we process NDP entries except for the last one */
+
+	if ((sizeof(struct usb_cdc_ncm_ndp32) +
+	     ret * (sizeof(struct usb_cdc_ncm_dpe32))) > skb_in->len) {
+		netif_dbg(dev, rx_err, dev->net, "Invalid nframes = %d\n", ret);
+		ret = -EINVAL;
+	}
+
+error:
+	return ret;
+}
+EXPORT_SYMBOL_GPL(cdc_ncm_rx_verify_ndp32);
+
 int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
 {
 	struct sk_buff *skb;
 	struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
-	int len;
+	unsigned int len;
 	int nframes;
 	int x;
-	int offset;
-	struct usb_cdc_ncm_ndp16 *ndp16;
-	struct usb_cdc_ncm_dpe16 *dpe16;
+	unsigned int offset;
+	union {
+		struct usb_cdc_ncm_ndp16 *ndp16;
+		struct usb_cdc_ncm_ndp32 *ndp32;
+	} ndp;
+	union {
+		struct usb_cdc_ncm_dpe16 *dpe16;
+		struct usb_cdc_ncm_dpe32 *dpe32;
+	} dpe;
+
 	int ndpoffset;
 	int loopcount = 50; /* arbitrary max preventing infinite loop */
 	u32 payload = 0;
 
-	ndpoffset = cdc_ncm_rx_verify_nth16(ctx, skb_in);
+	if (ctx->is_ndp16)
+		ndpoffset = cdc_ncm_rx_verify_nth16(ctx, skb_in);
+	else
+		ndpoffset = cdc_ncm_rx_verify_nth32(ctx, skb_in);
+
 	if (ndpoffset < 0)
 		goto error;
 
 next_ndp:
-	nframes = cdc_ncm_rx_verify_ndp16(skb_in, ndpoffset);
-	if (nframes < 0)
-		goto error;
+	if (ctx->is_ndp16) {
+		nframes = cdc_ncm_rx_verify_ndp16(skb_in, ndpoffset);
+		if (nframes < 0)
+			goto error;
 
-	ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb_in->data + ndpoffset);
+		ndp.ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb_in->data + ndpoffset);
 
-	if (ndp16->dwSignature != cpu_to_le32(USB_CDC_NCM_NDP16_NOCRC_SIGN)) {
-		netif_dbg(dev, rx_err, dev->net,
-			  "invalid DPT16 signature <%#010x>\n",
-			  le32_to_cpu(ndp16->dwSignature));
-		goto err_ndp;
-	}
-	dpe16 = ndp16->dpe16;
-
-	for (x = 0; x < nframes; x++, dpe16++) {
-		offset = le16_to_cpu(dpe16->wDatagramIndex);
-		len = le16_to_cpu(dpe16->wDatagramLength);
+		if (ndp.ndp16->dwSignature != cpu_to_le32(USB_CDC_NCM_NDP16_NOCRC_SIGN)) {
+			netif_dbg(dev, rx_err, dev->net,
+				  "invalid DPT16 signature <%#010x>\n",
+				  le32_to_cpu(ndp.ndp16->dwSignature));
+			goto err_ndp;
+		}
+		dpe.dpe16 = ndp.ndp16->dpe16;
+	} else {
+		nframes = cdc_ncm_rx_verify_ndp32(skb_in, ndpoffset);
+		if (nframes < 0)
+			goto error;
+
+		ndp.ndp32 = (struct usb_cdc_ncm_ndp32 *)(skb_in->data + ndpoffset);
+
+		if (ndp.ndp32->dwSignature != cpu_to_le32(USB_CDC_NCM_NDP32_NOCRC_SIGN)) {
+			netif_dbg(dev, rx_err, dev->net,
+				  "invalid DPT32 signature <%#010x>\n",
+				  le32_to_cpu(ndp.ndp32->dwSignature));
+			goto err_ndp;
+		}
+		dpe.dpe32 = ndp.ndp32->dpe32;
+	}
+
+	for (x = 0; x < nframes; x++) {
+		if (ctx->is_ndp16) {
+			offset = le16_to_cpu(dpe.dpe16->wDatagramIndex);
+			len = le16_to_cpu(dpe.dpe16->wDatagramLength);
+		} else {
+			offset = le32_to_cpu(dpe.dpe32->dwDatagramIndex);
+			len = le32_to_cpu(dpe.dpe32->dwDatagramLength);
+		}
 
 		/*
 		 * CDC NCM ch. 3.7
@@ -1542,8 +1782,8 @@
 			break;
 		}
 
-		/* sanity checking */
-		if (((offset + len) > skb_in->len) ||
+		/* sanity checking - watch out for integer wrap*/
+		if ((offset > skb_in->len) || (len > skb_in->len - offset) ||
 				(len > ctx->rx_max) || (len < ETH_HLEN)) {
 			netif_dbg(dev, rx_err, dev->net,
 				  "invalid frame detected (ignored) offset[%u]=%u, length=%u, skb=%p\n",
@@ -1561,10 +1801,19 @@
 			usbnet_skb_return(dev, skb);
 			payload += len;	/* count payload bytes in this NTB */
 		}
+
+		if (ctx->is_ndp16)
+			dpe.dpe16++;
+		else
+			dpe.dpe32++;
 	}
 err_ndp:
 	/* are there more NDPs to process? */
-	ndpoffset = le16_to_cpu(ndp16->wNextNdpIndex);
+	if (ctx->is_ndp16)
+		ndpoffset = le16_to_cpu(ndp.ndp16->wNextNdpIndex);
+	else
+		ndpoffset = le32_to_cpu(ndp.ndp32->dwNextNdpIndex);
+
 	if (ndpoffset && loopcount--)
 		goto next_ndp;
 
@@ -1585,6 +1834,15 @@
 	uint32_t rx_speed = le32_to_cpu(data->DLBitRRate);
 	uint32_t tx_speed = le32_to_cpu(data->ULBitRate);
 
+	/* if the speed hasn't changed, don't report it.
+	 * RTL8156 shipped before 2021 sends notification about every 32ms.
+	 */
+	if (dev->rx_speed == rx_speed && dev->tx_speed == tx_speed)
+		return;
+
+	dev->rx_speed = rx_speed;
+	dev->tx_speed = tx_speed;
+
 	/*
 	 * Currently the USB-NET API does not support reporting the actual
 	 * device speed. Do print it instead.
@@ -1625,10 +1883,8 @@
 		 * USB_CDC_NOTIFY_NETWORK_CONNECTION notification shall be
 		 * sent by device after USB_CDC_NOTIFY_SPEED_CHANGE.
 		 */
-		netif_info(dev, link, dev->net,
-			   "network connection: %sconnected\n",
-			   !!event->wValue ? "" : "dis");
-		usbnet_link_change(dev, !!event->wValue, 0);
+		if (netif_carrier_ok(dev->net) != !!event->wValue)
+			usbnet_link_change(dev, !!event->wValue, 0);
 		break;
 
 	case USB_CDC_NOTIFY_SPEED_CHANGE:
@@ -1651,7 +1907,7 @@
 static const struct driver_info cdc_ncm_info = {
 	.description = "CDC NCM",
 	.flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT | FLAG_MULTI_PACKET
-			| FLAG_LINK_INTR,
+			| FLAG_LINK_INTR | FLAG_ETHER,
 	.bind = cdc_ncm_bind,
 	.unbind = cdc_ncm_unbind,
 	.manage_power = usbnet_manage_power,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/usb/ch9200.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/usb/ch9200.c
@@ -338,6 +338,7 @@
 {
 	int retval = 0;
 	unsigned char data[2];
+	u8 addr[ETH_ALEN];
 
 	retval = usbnet_get_endpoints(dev, intf);
 	if (retval)
@@ -385,7 +386,8 @@
 	retval = control_write(dev, REQUEST_WRITE, 0, MAC_REG_CTRL, data, 0x02,
 			       CONTROL_TIMEOUT_MS);
 
-	retval = get_mac_address(dev, dev->net->dev_addr);
+	retval = get_mac_address(dev, addr);
+	eth_hw_addr_set(dev->net, addr);
 
 	return retval;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/usb/cx82310_eth.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/usb/cx82310_eth.c
@@ -40,6 +40,11 @@
 #define CX82310_MTU	1514
 #define CMD_EP		0x01
 
+struct cx82310_priv {
+	struct work_struct reenable_work;
+	struct usbnet *dev;
+};
+
 /*
  * execute control command
  *  - optionally send some data (command parameters)
@@ -115,6 +120,23 @@
 	return ret;
 }
 
+static int cx82310_enable_ethernet(struct usbnet *dev)
+{
+	int ret = cx82310_cmd(dev, CMD_ETHERNET_MODE, true, "\x01", 1, NULL, 0);
+
+	if (ret)
+		netdev_err(dev->net, "unable to enable ethernet mode: %d\n",
+			   ret);
+	return ret;
+}
+
+static void cx82310_reenable_work(struct work_struct *work)
+{
+	struct cx82310_priv *priv = container_of(work, struct cx82310_priv,
+						 reenable_work);
+	cx82310_enable_ethernet(priv->dev);
+}
+
 #define partial_len	data[0]		/* length of partial packet data */
 #define partial_rem	data[1]		/* remaining (missing) data length */
 #define partial_data	data[2]		/* partial packet data */
@@ -126,6 +148,8 @@
 	struct usb_device *udev = dev->udev;
 	u8 link[3];
 	int timeout = 50;
+	struct cx82310_priv *priv;
+	u8 addr[ETH_ALEN];
 
 	/* avoid ADSL modems - continue only if iProduct is "USB NET CARD" */
 	if (usb_string(udev, udev->descriptor.iProduct, buf, sizeof(buf)) > 0
@@ -152,6 +176,15 @@
 	if (!dev->partial_data)
 		return -ENOMEM;
 
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		ret = -ENOMEM;
+		goto err_partial;
+	}
+	dev->driver_priv = priv;
+	INIT_WORK(&priv->reenable_work, cx82310_reenable_work);
+	priv->dev = dev;
+
 	/* wait for firmware to become ready (indicated by the link being up) */
 	while (--timeout) {
 		ret = cx82310_cmd(dev, CMD_GET_LINK_STATUS, true, NULL, 0,
@@ -168,20 +201,17 @@
 	}
 
 	/* enable ethernet mode (?) */
-	ret = cx82310_cmd(dev, CMD_ETHERNET_MODE, true, "\x01", 1, NULL, 0);
-	if (ret) {
-		dev_err(&udev->dev, "unable to enable ethernet mode: %d\n",
-			ret);
+	ret = cx82310_enable_ethernet(dev);
+	if (ret)
 		goto err;
-	}
 
 	/* get the MAC address */
-	ret = cx82310_cmd(dev, CMD_GET_MAC_ADDR, true, NULL, 0,
-			  dev->net->dev_addr, ETH_ALEN);
+	ret = cx82310_cmd(dev, CMD_GET_MAC_ADDR, true, NULL, 0, addr, ETH_ALEN);
 	if (ret) {
 		dev_err(&udev->dev, "unable to read MAC address: %d\n", ret);
 		goto err;
 	}
+	eth_hw_addr_set(dev->net, addr);
 
 	/* start (does not seem to have any effect?) */
 	ret = cx82310_cmd(dev, CMD_START, false, NULL, 0, NULL, 0);
@@ -190,13 +220,19 @@
 
 	return 0;
 err:
+	kfree(dev->driver_priv);
+err_partial:
 	kfree((void *)dev->partial_data);
 	return ret;
 }
 
 static void cx82310_unbind(struct usbnet *dev, struct usb_interface *intf)
 {
+	struct cx82310_priv *priv = dev->driver_priv;
+
 	kfree((void *)dev->partial_data);
+	cancel_work_sync(&priv->reenable_work);
+	kfree(dev->driver_priv);
 }
 
 /*
@@ -211,6 +247,7 @@
 {
 	int len;
 	struct sk_buff *skb2;
+	struct cx82310_priv *priv = dev->driver_priv;
 
 	/*
 	 * If the last skb ended with an incomplete packet, this skb contains
@@ -245,7 +282,10 @@
 			break;
 		}
 
-		if (len > CX82310_MTU) {
+		if (len == 0xffff) {
+			netdev_info(dev->net, "router was rebooted, re-enabling ethernet mode");
+			schedule_work(&priv->reenable_work);
+		} else if (len > CX82310_MTU) {
 			dev_err(&dev->udev->dev, "RX packet too long: %d B\n",
 				len);
 			return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/usb/dm9601.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/usb/dm9601.c
@@ -221,13 +221,18 @@
 	struct usbnet *dev = netdev_priv(netdev);
 
 	__le16 res;
+	int err;
 
 	if (phy_id) {
 		netdev_dbg(dev->net, "Only internal phy supported\n");
 		return 0;
 	}
 
-	dm_read_shared_word(dev, 1, loc, &res);
+	err = dm_read_shared_word(dev, 1, loc, &res);
+	if (err < 0) {
+		netdev_err(dev->net, "MDIO read error: %d\n", err);
+		return 0;
+	}
 
 	netdev_dbg(dev->net,
 		   "dm9601_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n",
@@ -625,6 +630,10 @@
 	 USB_DEVICE(0x0a46, 0x1269),	/* DM9621A USB to Fast Ethernet Adapter */
 	 .driver_info = (unsigned long)&dm9601_info,
 	},
+	{
+	 USB_DEVICE(0x0586, 0x3427),	/* ZyXEL Keenetic Plus DSL xDSL modem */
+	 .driver_info = (unsigned long)&dm9601_info,
+	},
 	{},			// END
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/usb/gl620a.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/usb/gl620a.c
@@ -179,9 +179,7 @@
 {
 	dev->hard_mtu = GL_RCV_BUF_SIZE;
 	dev->net->hard_header_len += 4;
-	dev->in = usb_rcvbulkpipe(dev->udev, dev->driver_info->in);
-	dev->out = usb_sndbulkpipe(dev->udev, dev->driver_info->out);
-	return 0;
+	return usbnet_get_endpoints(dev, intf);
 }
 
 static const struct driver_info	genelink_info = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/usb/hso.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/usb/hso.c
@@ -611,7 +611,7 @@
 	return serial;
 }
 
-static int get_free_serial_index(void)
+static int obtain_minor(struct hso_serial *serial)
 {
 	int index;
 	unsigned long flags;
@@ -619,8 +619,10 @@
 	spin_lock_irqsave(&serial_table_lock, flags);
 	for (index = 0; index < HSO_SERIAL_TTY_MINORS; index++) {
 		if (serial_table[index] == NULL) {
+			serial_table[index] = serial->parent;
+			serial->minor = index;
 			spin_unlock_irqrestore(&serial_table_lock, flags);
-			return index;
+			return 0;
 		}
 	}
 	spin_unlock_irqrestore(&serial_table_lock, flags);
@@ -629,15 +631,12 @@
 	return -1;
 }
 
-static void set_serial_by_index(unsigned index, struct hso_serial *serial)
+static void release_minor(struct hso_serial *serial)
 {
 	unsigned long flags;
 
 	spin_lock_irqsave(&serial_table_lock, flags);
-	if (serial)
-		serial_table[index] = serial->parent;
-	else
-		serial_table[index] = NULL;
+	serial_table[serial->minor] = NULL;
 	spin_unlock_irqrestore(&serial_table_lock, flags);
 }
 
@@ -1389,8 +1388,9 @@
 	unsigned long flags;
 
 	if (old)
-		hso_dbg(0x16, "Termios called with: cflags new[%d] - old[%d]\n",
-			tty->termios.c_cflag, old->c_cflag);
+		hso_dbg(0x16, "Termios called with: cflags new[%u] - old[%u]\n",
+			(unsigned int)tty->termios.c_cflag,
+			(unsigned int)old->c_cflag);
 
 	/* the actual setup */
 	spin_lock_irqsave(&serial->serial_lock, flags);
@@ -1689,7 +1689,7 @@
 	spin_unlock_irqrestore(&serial->serial_lock, flags);
 
 	return usb_control_msg(serial->parent->usb,
-			       usb_rcvctrlpipe(serial->parent->usb, 0), 0x22,
+			       usb_sndctrlpipe(serial->parent->usb, 0), 0x22,
 			       0x21, val, if_num, NULL, 0,
 			       USB_CTRL_SET_TIMEOUT);
 }
@@ -2229,6 +2229,7 @@
 static void hso_serial_tty_unregister(struct hso_serial *serial)
 {
 	tty_unregister_device(tty_drv, serial->minor);
+	release_minor(serial);
 }
 
 static void hso_serial_common_free(struct hso_serial *serial)
@@ -2252,22 +2253,22 @@
 static int hso_serial_common_create(struct hso_serial *serial, int num_urbs,
 				    int rx_size, int tx_size)
 {
-	int minor;
 	int i;
 
 	tty_port_init(&serial->port);
 
-	minor = get_free_serial_index();
-	if (minor < 0)
-		goto exit;
+	if (obtain_minor(serial))
+		goto exit2;
 
 	/* register our minor number */
 	serial->parent->dev = tty_port_register_device_attr(&serial->port,
-			tty_drv, minor, &serial->parent->interface->dev,
+			tty_drv, serial->minor, &serial->parent->interface->dev,
 			serial->parent, hso_serial_dev_groups);
+	if (IS_ERR(serial->parent->dev)) {
+		release_minor(serial);
+		goto exit2;
+	}
 
-	/* fill in specific data for later use */
-	serial->minor = minor;
 	serial->magic = HSO_SERIAL_MAGIC;
 	spin_lock_init(&serial->serial_lock);
 	serial->num_rx_urbs = num_urbs;
@@ -2309,6 +2310,7 @@
 	return 0;
 exit:
 	hso_serial_tty_unregister(serial);
+exit2:
 	hso_serial_common_free(serial);
 	return -1;
 }
@@ -2434,7 +2436,7 @@
 	if (hso_dev->usb_gone)
 		rv = 0;
 	else
-		rv = usb_control_msg(hso_dev->usb, usb_rcvctrlpipe(hso_dev->usb, 0),
+		rv = usb_control_msg(hso_dev->usb, usb_sndctrlpipe(hso_dev->usb, 0),
 				       enabled ? 0x82 : 0x81, 0x40, 0, 0, NULL, 0,
 				       USB_CTRL_SET_TIMEOUT);
 	mutex_unlock(&hso_dev->mutex);
@@ -2495,7 +2497,7 @@
 			   hso_net_init);
 	if (!net) {
 		dev_err(&interface->dev, "Unable to create ethernet device\n");
-		goto exit;
+		goto err_hso_dev;
 	}
 
 	hso_net = netdev_priv(net);
@@ -2508,13 +2510,13 @@
 				      USB_DIR_IN);
 	if (!hso_net->in_endp) {
 		dev_err(&interface->dev, "Can't find BULK IN endpoint\n");
-		goto exit;
+		goto err_net;
 	}
 	hso_net->out_endp = hso_get_ep(interface, USB_ENDPOINT_XFER_BULK,
 				       USB_DIR_OUT);
 	if (!hso_net->out_endp) {
 		dev_err(&interface->dev, "Can't find BULK OUT endpoint\n");
-		goto exit;
+		goto err_net;
 	}
 	SET_NETDEV_DEV(net, &interface->dev);
 	SET_NETDEV_DEVTYPE(net, &hso_type);
@@ -2523,18 +2525,18 @@
 	for (i = 0; i < MUX_BULK_RX_BUF_COUNT; i++) {
 		hso_net->mux_bulk_rx_urb_pool[i] = usb_alloc_urb(0, GFP_KERNEL);
 		if (!hso_net->mux_bulk_rx_urb_pool[i])
-			goto exit;
+			goto err_mux_bulk_rx;
 		hso_net->mux_bulk_rx_buf_pool[i] = kzalloc(MUX_BULK_RX_BUF_SIZE,
 							   GFP_KERNEL);
 		if (!hso_net->mux_bulk_rx_buf_pool[i])
-			goto exit;
+			goto err_mux_bulk_rx;
 	}
 	hso_net->mux_bulk_tx_urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!hso_net->mux_bulk_tx_urb)
-		goto exit;
+		goto err_mux_bulk_rx;
 	hso_net->mux_bulk_tx_buf = kzalloc(MUX_BULK_TX_BUF_SIZE, GFP_KERNEL);
 	if (!hso_net->mux_bulk_tx_buf)
-		goto exit;
+		goto err_free_tx_urb;
 
 	add_net_device(hso_dev);
 
@@ -2542,7 +2544,7 @@
 	result = register_netdev(net);
 	if (result) {
 		dev_err(&interface->dev, "Failed to register device\n");
-		goto exit;
+		goto err_free_tx_buf;
 	}
 
 	hso_log_port(hso_dev);
@@ -2550,8 +2552,21 @@
 	hso_create_rfkill(hso_dev, interface);
 
 	return hso_dev;
-exit:
-	hso_free_net_device(hso_dev);
+
+err_free_tx_buf:
+	remove_net_device(hso_dev);
+	kfree(hso_net->mux_bulk_tx_buf);
+err_free_tx_urb:
+	usb_free_urb(hso_net->mux_bulk_tx_urb);
+err_mux_bulk_rx:
+	for (i = 0; i < MUX_BULK_RX_BUF_COUNT; i++) {
+		usb_free_urb(hso_net->mux_bulk_rx_urb_pool[i]);
+		kfree(hso_net->mux_bulk_rx_buf_pool[i]);
+	}
+err_net:
+	free_netdev(net);
+err_hso_dev:
+	kfree(hso_dev);
 	return NULL;
 }
 
@@ -2617,32 +2632,31 @@
 		num_urbs = 2;
 		serial->tiocmget = kzalloc(sizeof(struct hso_tiocmget),
 					   GFP_KERNEL);
+		if (!serial->tiocmget)
+			goto exit;
 		serial->tiocmget->serial_state_notification
 			= kzalloc(sizeof(struct hso_serial_state_notification),
 					   GFP_KERNEL);
-		/* it isn't going to break our heart if serial->tiocmget
-		 *  allocation fails don't bother checking this.
-		 */
-		if (serial->tiocmget && serial->tiocmget->serial_state_notification) {
-			tiocmget = serial->tiocmget;
-			tiocmget->endp = hso_get_ep(interface,
-						    USB_ENDPOINT_XFER_INT,
-						    USB_DIR_IN);
-			if (!tiocmget->endp) {
-				dev_err(&interface->dev, "Failed to find INT IN ep\n");
-				goto exit;
-			}
-
-			tiocmget->urb = usb_alloc_urb(0, GFP_KERNEL);
-			if (tiocmget->urb) {
-				mutex_init(&tiocmget->mutex);
-				init_waitqueue_head(&tiocmget->waitq);
-			} else
-				hso_free_tiomget(serial);
+		if (!serial->tiocmget->serial_state_notification)
+			goto exit;
+		tiocmget = serial->tiocmget;
+		tiocmget->endp = hso_get_ep(interface,
+					    USB_ENDPOINT_XFER_INT,
+					    USB_DIR_IN);
+		if (!tiocmget->endp) {
+			dev_err(&interface->dev, "Failed to find INT IN ep\n");
+			goto exit;
 		}
-	}
-	else
+
+		tiocmget->urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!tiocmget->urb)
+			goto exit;
+
+		mutex_init(&tiocmget->mutex);
+		init_waitqueue_head(&tiocmget->waitq);
+	} else {
 		num_urbs = 1;
+	}
 
 	if (hso_serial_common_create(serial, num_urbs, BULK_URB_RX_SIZE,
 				     BULK_URB_TX_SIZE))
@@ -2664,9 +2678,6 @@
 
 	serial->write_data = hso_std_serial_write_data;
 
-	/* and record this serial */
-	set_serial_by_index(serial->minor, serial);
-
 	/* setup the proc dirs and files if needed */
 	hso_log_port(hso_dev);
 
@@ -2706,14 +2717,14 @@
 
 	serial = kzalloc(sizeof(*serial), GFP_KERNEL);
 	if (!serial)
-		goto exit;
+		goto err_free_dev;
 
 	hso_dev->port_data.dev_serial = serial;
 	serial->parent = hso_dev;
 
 	if (hso_serial_common_create
 	    (serial, 1, CTRL_URB_RX_SIZE, CTRL_URB_TX_SIZE))
-		goto exit;
+		goto err_free_serial;
 
 	serial->tx_data_length--;
 	serial->write_data = hso_mux_serial_write_data;
@@ -2723,20 +2734,15 @@
 	serial->shared_int->ref_count++;
 	mutex_unlock(&serial->shared_int->shared_int_lock);
 
-	/* and record this serial */
-	set_serial_by_index(serial->minor, serial);
-
 	/* setup the proc dirs and files if needed */
 	hso_log_port(hso_dev);
 
 	/* done, return it */
 	return hso_dev;
 
-exit:
-	if (serial) {
-		tty_unregister_device(tty_drv, serial->minor);
-		kfree(serial);
-	}
+err_free_serial:
+	kfree(serial);
+err_free_dev:
 	kfree(hso_dev);
 	return NULL;
 
@@ -3109,8 +3115,7 @@
 			cancel_work_sync(&serial_table[i]->async_put_intf);
 			cancel_work_sync(&serial_table[i]->async_get_intf);
 			hso_serial_tty_unregister(serial);
-			kref_put(&serial_table[i]->ref, hso_serial_ref_free);
-			set_serial_by_index(i, NULL);
+			kref_put(&serial->parent->ref, hso_serial_ref_free);
 		}
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/usb/huawei_cdc_ncm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/usb/huawei_cdc_ncm.c
@@ -77,11 +77,11 @@
 	 */
 	drvflags |= CDC_NCM_FLAG_NDP_TO_END;
 
-	/* Additionally, it has been reported that some Huawei E3372H devices, with
-	 * firmware version 21.318.01.00.541, come out of reset in NTB32 format mode, hence
-	 * needing to be set to the NTB16 one again.
+	/* For many Huawei devices the NTB32 mode is the default and the best mode
+	 * they work with. Huawei E5785 and E5885 devices refuse to work in NTB16 mode at all.
 	 */
-	drvflags |= CDC_NCM_FLAG_RESET_NTB16;
+	drvflags |= CDC_NCM_FLAG_PREFER_NTB32;
+
 	ret = cdc_ncm_bind_common(usbnet_dev, intf, 1, drvflags);
 	if (ret)
 		goto err;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/usb/ipheth.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/usb/ipheth.c
@@ -59,7 +59,7 @@
 #define IPHETH_USBINTF_SUBCLASS 253
 #define IPHETH_USBINTF_PROTO    1
 
-#define IPHETH_BUF_SIZE         1516
+#define IPHETH_BUF_SIZE         1514
 #define IPHETH_IP_ALIGN		2	/* padding at front of URB */
 #define IPHETH_TX_TIMEOUT       (5 * HZ)
 
@@ -121,7 +121,7 @@
 	if (tx_buf == NULL)
 		goto free_rx_urb;
 
-	rx_buf = usb_alloc_coherent(iphone->udev, IPHETH_BUF_SIZE,
+	rx_buf = usb_alloc_coherent(iphone->udev, IPHETH_BUF_SIZE + IPHETH_IP_ALIGN,
 				    GFP_KERNEL, &rx_urb->transfer_dma);
 	if (rx_buf == NULL)
 		goto free_tx_buf;
@@ -146,7 +146,7 @@
 
 static void ipheth_free_urbs(struct ipheth_device *iphone)
 {
-	usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE, iphone->rx_buf,
+	usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE + IPHETH_IP_ALIGN, iphone->rx_buf,
 			  iphone->rx_urb->transfer_dma);
 	usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE, iphone->tx_buf,
 			  iphone->tx_urb->transfer_dma);
@@ -253,13 +253,14 @@
 			0x02, /* index */
 			dev->ctrl_buf, IPHETH_CTRL_BUF_SIZE,
 			IPHETH_CTRL_TIMEOUT);
-	if (retval < 0) {
+	if (retval <= 0) {
 		dev_err(&dev->intf->dev, "%s: usb_control_msg: %d\n",
 			__func__, retval);
 		return retval;
 	}
 
-	if (dev->ctrl_buf[0] == IPHETH_CARRIER_ON) {
+	if ((retval == 1 && dev->ctrl_buf[0] == IPHETH_CARRIER_ON) ||
+	    (retval >= 2 && dev->ctrl_buf[1] == IPHETH_CARRIER_ON)) {
 		netif_carrier_on(dev->net);
 		if (dev->tx_urb->status != -EINPROGRESS)
 			netif_wake_queue(dev->net);
@@ -317,7 +318,7 @@
 
 	usb_fill_bulk_urb(dev->rx_urb, udev,
 			  usb_rcvbulkpipe(udev, dev->bulk_in),
-			  dev->rx_buf, IPHETH_BUF_SIZE,
+			  dev->rx_buf, IPHETH_BUF_SIZE + IPHETH_IP_ALIGN,
 			  ipheth_rcvbulk_callback,
 			  dev);
 	dev->rx_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
@@ -353,8 +354,8 @@
 {
 	struct ipheth_device *dev = netdev_priv(net);
 
-	cancel_delayed_work_sync(&dev->carrier_work);
 	netif_stop_queue(net);
+	cancel_delayed_work_sync(&dev->carrier_work);
 	return 0;
 }
 
@@ -443,7 +444,7 @@
 
 	netdev->netdev_ops = &ipheth_netdev_ops;
 	netdev->watchdog_timeo = IPHETH_TX_TIMEOUT;
-	strcpy(netdev->name, "eth%d");
+	strscpy(netdev->name, "eth%d", sizeof(netdev->name));
 
 	dev = netdev_priv(netdev);
 	dev->udev = udev;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/usb/kalmia.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/usb/kalmia.c
@@ -65,8 +65,8 @@
 		init_msg, init_msg_len, &act_len, KALMIA_USB_TIMEOUT);
 	if (status != 0) {
 		netdev_err(dev->net,
-			"Error sending init packet. Status %i, length %i\n",
-			status, act_len);
+			"Error sending init packet. Status %i\n",
+			status);
 		return status;
 	}
 	else if (act_len != init_msg_len) {
@@ -83,8 +83,8 @@
 
 	if (status != 0)
 		netdev_err(dev->net,
-			"Error receiving init result. Status %i, length %i\n",
-			status, act_len);
+			"Error receiving init result. Status %i\n",
+			status);
 	else if (act_len != expected_len)
 		netdev_err(dev->net, "Unexpected init result length: %i\n",
 			act_len);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/usb/kaweth.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/usb/kaweth.c
@@ -1127,8 +1127,7 @@
 		goto err_all_but_rxbuf;
 
 	memcpy(netdev->broadcast, &bcast_addr, sizeof(bcast_addr));
-	memcpy(netdev->dev_addr, &kaweth->configuration.hw_addr,
-               sizeof(kaweth->configuration.hw_addr));
+	eth_hw_addr_set(netdev, (u8 *)&kaweth->configuration.hw_addr);
 
 	netdev->netdev_ops = &kaweth_netdev_ops;
 	netdev->watchdog_timeo = KAWETH_TX_TIMEOUT;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/usb/lan78xx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/usb/lan78xx.c
@@ -20,6 +20,7 @@
 #include <linux/mdio.h>
 #include <linux/phy.h>
 #include <net/ip6_checksum.h>
+#include <net/vxlan.h>
 #include <linux/interrupt.h>
 #include <linux/irqdomain.h>
 #include <linux/irq.h>
@@ -63,6 +64,8 @@
 #define LAN7801_USB_PRODUCT_ID		(0x7801)
 #define LAN78XX_EEPROM_MAGIC		(0x78A5)
 #define LAN78XX_OTP_MAGIC		(0x78F3)
+#define AT29M2AF_USB_VENDOR_ID		(0x07C9)
+#define AT29M2AF_USB_PRODUCT_ID	(0x0012)
 
 #define	MII_READ			1
 #define	MII_WRITE			0
@@ -87,6 +90,12 @@
 /* statistic update interval (mSec) */
 #define STAT_UPDATE_TIMER		(1 * 1000)
 
+/* time to wait for MAC or FCT to stop (jiffies) */
+#define HW_DISABLE_TIMEOUT		(HZ / 10)
+
+/* time to wait between polling MAC or FCT state (ms) */
+#define HW_DISABLE_DELAY_MS		1
+
 /* defines interrupts from interrupt EP */
 #define MAX_INT_EP			(32)
 #define INT_EP_INTEP			(31)
@@ -376,17 +385,14 @@
 	struct tasklet_struct	bh;
 	struct delayed_work	wq;
 
-	struct usb_host_endpoint *ep_blkin;
-	struct usb_host_endpoint *ep_blkout;
-	struct usb_host_endpoint *ep_intr;
-
 	int			msg_enable;
 
 	struct urb		*urb_intr;
 	struct usb_anchor	deferred;
 
+	struct mutex		dev_mutex; /* serialise open/stop wrt suspend/resume */
 	struct mutex		phy_mutex; /* for phy access */
-	unsigned		pipe_in, pipe_out, pipe_intr;
+	unsigned int		pipe_in, pipe_out, pipe_intr;
 
 	u32			hard_mtu;	/* count any extra framing */
 	size_t			rx_urb_size;	/* size for rx urbs */
@@ -396,7 +402,7 @@
 	wait_queue_head_t	*wait;
 	unsigned char		suspend_count;
 
-	unsigned		maxpacket;
+	unsigned int		maxpacket;
 	struct timer_list	delay;
 	struct timer_list	stat_monitor;
 
@@ -480,6 +486,26 @@
 	return ret;
 }
 
+static int lan78xx_update_reg(struct lan78xx_net *dev, u32 reg, u32 mask,
+			      u32 data)
+{
+	int ret;
+	u32 buf;
+
+	ret = lan78xx_read_reg(dev, reg, &buf);
+	if (ret < 0)
+		return ret;
+
+	buf &= ~mask;
+	buf |= (mask & data);
+
+	ret = lan78xx_write_reg(dev, reg, buf);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
 static int lan78xx_read_stats(struct lan78xx_net *dev,
 			      struct lan78xx_statstage *data)
 {
@@ -505,13 +531,13 @@
 	if (likely(ret >= 0)) {
 		src = (u32 *)stats;
 		dst = (u32 *)data;
-		for (i = 0; i < sizeof(*stats)/sizeof(u32); i++) {
+		for (i = 0; i < sizeof(*stats) / sizeof(u32); i++) {
 			le32_to_cpus(&src[i]);
 			dst[i] = src[i];
 		}
 	} else {
 		netdev_warn(dev->net,
-			    "Failed to read stat ret = 0x%x", ret);
+			    "Failed to read stat ret = %d", ret);
 	}
 
 	kfree(stats);
@@ -519,10 +545,11 @@
 	return ret;
 }
 
-#define check_counter_rollover(struct1, dev_stats, member) {	\
-	if (struct1->member < dev_stats.saved.member)		\
-		dev_stats.rollover_count.member++;		\
-	}
+#define check_counter_rollover(struct1, dev_stats, member)		\
+	do {								\
+		if ((struct1)->member < (dev_stats).saved.member)	\
+			(dev_stats).rollover_count.member++;		\
+	} while (0)
 
 static void lan78xx_check_stat_rollover(struct lan78xx_net *dev,
 					struct lan78xx_statstage *stats)
@@ -825,20 +852,19 @@
 				u32 length, u8 *data)
 {
 	int i;
-	int ret;
 	u32 buf;
 	unsigned long timeout;
 
-	ret = lan78xx_read_reg(dev, OTP_PWR_DN, &buf);
+	lan78xx_read_reg(dev, OTP_PWR_DN, &buf);
 
 	if (buf & OTP_PWR_DN_PWRDN_N_) {
 		/* clear it and wait to be cleared */
-		ret = lan78xx_write_reg(dev, OTP_PWR_DN, 0);
+		lan78xx_write_reg(dev, OTP_PWR_DN, 0);
 
 		timeout = jiffies + HZ;
 		do {
 			usleep_range(1, 10);
-			ret = lan78xx_read_reg(dev, OTP_PWR_DN, &buf);
+			lan78xx_read_reg(dev, OTP_PWR_DN, &buf);
 			if (time_after(jiffies, timeout)) {
 				netdev_warn(dev->net,
 					    "timeout on OTP_PWR_DN");
@@ -848,18 +874,18 @@
 	}
 
 	for (i = 0; i < length; i++) {
-		ret = lan78xx_write_reg(dev, OTP_ADDR1,
-					((offset + i) >> 8) & OTP_ADDR1_15_11);
-		ret = lan78xx_write_reg(dev, OTP_ADDR2,
-					((offset + i) & OTP_ADDR2_10_3));
+		lan78xx_write_reg(dev, OTP_ADDR1,
+				  ((offset + i) >> 8) & OTP_ADDR1_15_11);
+		lan78xx_write_reg(dev, OTP_ADDR2,
+				  ((offset + i) & OTP_ADDR2_10_3));
 
-		ret = lan78xx_write_reg(dev, OTP_FUNC_CMD, OTP_FUNC_CMD_READ_);
-		ret = lan78xx_write_reg(dev, OTP_CMD_GO, OTP_CMD_GO_GO_);
+		lan78xx_write_reg(dev, OTP_FUNC_CMD, OTP_FUNC_CMD_READ_);
+		lan78xx_write_reg(dev, OTP_CMD_GO, OTP_CMD_GO_GO_);
 
 		timeout = jiffies + HZ;
 		do {
 			udelay(1);
-			ret = lan78xx_read_reg(dev, OTP_STATUS, &buf);
+			lan78xx_read_reg(dev, OTP_STATUS, &buf);
 			if (time_after(jiffies, timeout)) {
 				netdev_warn(dev->net,
 					    "timeout on OTP_STATUS");
@@ -867,7 +893,7 @@
 			}
 		} while (buf & OTP_STATUS_BUSY_);
 
-		ret = lan78xx_read_reg(dev, OTP_RD_DATA, &buf);
+		lan78xx_read_reg(dev, OTP_RD_DATA, &buf);
 
 		data[i] = (u8)(buf & 0xFF);
 	}
@@ -879,20 +905,19 @@
 				 u32 length, u8 *data)
 {
 	int i;
-	int ret;
 	u32 buf;
 	unsigned long timeout;
 
-	ret = lan78xx_read_reg(dev, OTP_PWR_DN, &buf);
+	lan78xx_read_reg(dev, OTP_PWR_DN, &buf);
 
 	if (buf & OTP_PWR_DN_PWRDN_N_) {
 		/* clear it and wait to be cleared */
-		ret = lan78xx_write_reg(dev, OTP_PWR_DN, 0);
+		lan78xx_write_reg(dev, OTP_PWR_DN, 0);
 
 		timeout = jiffies + HZ;
 		do {
 			udelay(1);
-			ret = lan78xx_read_reg(dev, OTP_PWR_DN, &buf);
+			lan78xx_read_reg(dev, OTP_PWR_DN, &buf);
 			if (time_after(jiffies, timeout)) {
 				netdev_warn(dev->net,
 					    "timeout on OTP_PWR_DN completion");
@@ -902,21 +927,21 @@
 	}
 
 	/* set to BYTE program mode */
-	ret = lan78xx_write_reg(dev, OTP_PRGM_MODE, OTP_PRGM_MODE_BYTE_);
+	lan78xx_write_reg(dev, OTP_PRGM_MODE, OTP_PRGM_MODE_BYTE_);
 
 	for (i = 0; i < length; i++) {
-		ret = lan78xx_write_reg(dev, OTP_ADDR1,
-					((offset + i) >> 8) & OTP_ADDR1_15_11);
-		ret = lan78xx_write_reg(dev, OTP_ADDR2,
-					((offset + i) & OTP_ADDR2_10_3));
-		ret = lan78xx_write_reg(dev, OTP_PRGM_DATA, data[i]);
-		ret = lan78xx_write_reg(dev, OTP_TST_CMD, OTP_TST_CMD_PRGVRFY_);
-		ret = lan78xx_write_reg(dev, OTP_CMD_GO, OTP_CMD_GO_GO_);
+		lan78xx_write_reg(dev, OTP_ADDR1,
+				  ((offset + i) >> 8) & OTP_ADDR1_15_11);
+		lan78xx_write_reg(dev, OTP_ADDR2,
+				  ((offset + i) & OTP_ADDR2_10_3));
+		lan78xx_write_reg(dev, OTP_PRGM_DATA, data[i]);
+		lan78xx_write_reg(dev, OTP_TST_CMD, OTP_TST_CMD_PRGVRFY_);
+		lan78xx_write_reg(dev, OTP_CMD_GO, OTP_CMD_GO_GO_);
 
 		timeout = jiffies + HZ;
 		do {
 			udelay(1);
-			ret = lan78xx_read_reg(dev, OTP_STATUS, &buf);
+			lan78xx_read_reg(dev, OTP_STATUS, &buf);
 			if (time_after(jiffies, timeout)) {
 				netdev_warn(dev->net,
 					    "Timeout on OTP_STATUS completion");
@@ -965,7 +990,7 @@
 		usleep_range(40, 100);
 	}
 
-	netdev_warn(dev->net, "lan78xx_dataport_wait_not_busy timed out");
+	netdev_warn(dev->net, "%s timed out", __func__);
 
 	return -EIO;
 }
@@ -978,7 +1003,7 @@
 	int i, ret;
 
 	if (usb_autopm_get_interface(dev->intf) < 0)
-			return 0;
+		return 0;
 
 	mutex_lock(&pdata->dataport_mutex);
 
@@ -1041,7 +1066,6 @@
 			container_of(param, struct lan78xx_priv, set_multicast);
 	struct lan78xx_net *dev = pdata->dev;
 	int i;
-	int ret;
 
 	netif_dbg(dev, drv, dev->net, "deferred multicast write 0x%08x\n",
 		  pdata->rfe_ctl);
@@ -1050,14 +1074,14 @@
 			       DP_SEL_VHF_HASH_LEN, pdata->mchash_table);
 
 	for (i = 1; i < NUM_OF_MAF; i++) {
-		ret = lan78xx_write_reg(dev, MAF_HI(i), 0);
-		ret = lan78xx_write_reg(dev, MAF_LO(i),
-					pdata->pfilter_table[i][1]);
-		ret = lan78xx_write_reg(dev, MAF_HI(i),
-					pdata->pfilter_table[i][0]);
+		lan78xx_write_reg(dev, MAF_HI(i), 0);
+		lan78xx_write_reg(dev, MAF_LO(i),
+				  pdata->pfilter_table[i][1]);
+		lan78xx_write_reg(dev, MAF_HI(i),
+				  pdata->pfilter_table[i][0]);
 	}
 
-	ret = lan78xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl);
+	lan78xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl);
 }
 
 static void lan78xx_set_multicast(struct net_device *netdev)
@@ -1073,11 +1097,12 @@
 			    RFE_CTL_DA_PERFECT_ | RFE_CTL_MCAST_HASH_);
 
 	for (i = 0; i < DP_SEL_VHF_HASH_LEN; i++)
-			pdata->mchash_table[i] = 0;
+		pdata->mchash_table[i] = 0;
+
 	/* pfilter_table[0] has own HW address */
 	for (i = 1; i < NUM_OF_MAF; i++) {
-			pdata->pfilter_table[i][0] =
-			pdata->pfilter_table[i][1] = 0;
+		pdata->pfilter_table[i][0] = 0;
+		pdata->pfilter_table[i][1] = 0;
 	}
 
 	pdata->rfe_ctl |= RFE_CTL_BCAST_EN_;
@@ -1127,7 +1152,6 @@
 				      u16 lcladv, u16 rmtadv)
 {
 	u32 flow = 0, fct_flow = 0;
-	int ret;
 	u8 cap;
 
 	if (dev->fc_autoneg)
@@ -1150,10 +1174,10 @@
 		  (cap & FLOW_CTRL_RX ? "enabled" : "disabled"),
 		  (cap & FLOW_CTRL_TX ? "enabled" : "disabled"));
 
-	ret = lan78xx_write_reg(dev, FCT_FLOW, fct_flow);
+	lan78xx_write_reg(dev, FCT_FLOW, fct_flow);
 
 	/* threshold value should be set before enabling flow */
-	ret = lan78xx_write_reg(dev, FLOW, flow);
+	lan78xx_write_reg(dev, FLOW, flow);
 
 	return 0;
 }
@@ -1162,30 +1186,33 @@
 {
 	struct phy_device *phydev = dev->net->phydev;
 	struct ethtool_link_ksettings ecmd;
-	int ladv, radv, ret;
+	int ladv, radv, ret, link;
 	u32 buf;
 
 	/* clear LAN78xx interrupt status */
 	ret = lan78xx_write_reg(dev, INT_STS, INT_STS_PHY_INT_);
 	if (unlikely(ret < 0))
-		return -EIO;
+		return ret;
 
+	mutex_lock(&phydev->lock);
 	phy_read_status(phydev);
+	link = phydev->link;
+	mutex_unlock(&phydev->lock);
 
-	if (!phydev->link && dev->link_on) {
+	if (!link && dev->link_on) {
 		dev->link_on = false;
 
 		/* reset MAC */
 		ret = lan78xx_read_reg(dev, MAC_CR, &buf);
 		if (unlikely(ret < 0))
-			return -EIO;
+			return ret;
 		buf |= MAC_CR_RST_;
 		ret = lan78xx_write_reg(dev, MAC_CR, buf);
 		if (unlikely(ret < 0))
-			return -EIO;
+			return ret;
 
 		del_timer(&dev->stat_monitor);
-	} else if (phydev->link && !dev->link_on) {
+	} else if (link && !dev->link_on) {
 		dev->link_on = true;
 
 		phy_ethtool_ksettings_get(phydev, &ecmd);
@@ -1194,18 +1221,30 @@
 			if (ecmd.base.speed == 1000) {
 				/* disable U2 */
 				ret = lan78xx_read_reg(dev, USB_CFG1, &buf);
+				if (ret < 0)
+					return ret;
 				buf &= ~USB_CFG1_DEV_U2_INIT_EN_;
 				ret = lan78xx_write_reg(dev, USB_CFG1, buf);
+				if (ret < 0)
+					return ret;
 				/* enable U1 */
 				ret = lan78xx_read_reg(dev, USB_CFG1, &buf);
+				if (ret < 0)
+					return ret;
 				buf |= USB_CFG1_DEV_U1_INIT_EN_;
 				ret = lan78xx_write_reg(dev, USB_CFG1, buf);
+				if (ret < 0)
+					return ret;
 			} else {
 				/* enable U1 & U2 */
 				ret = lan78xx_read_reg(dev, USB_CFG1, &buf);
+				if (ret < 0)
+					return ret;
 				buf |= USB_CFG1_DEV_U2_INIT_EN_;
 				buf |= USB_CFG1_DEV_U1_INIT_EN_;
 				ret = lan78xx_write_reg(dev, USB_CFG1, buf);
+				if (ret < 0)
+					return ret;
 			}
 		}
 
@@ -1223,6 +1262,8 @@
 
 		ret = lan78xx_update_flowcontrol(dev, ecmd.base.duplex, ladv,
 						 radv);
+		if (ret < 0)
+			return ret;
 
 		if (!timer_pending(&dev->stat_monitor)) {
 			dev->delta = 1;
@@ -1233,7 +1274,7 @@
 		tasklet_schedule(&dev->bh);
 	}
 
-	return ret;
+	return 0;
 }
 
 /* some work can't be done in tasklets, so we use keventd
@@ -1269,9 +1310,10 @@
 			generic_handle_irq(dev->domain_data.phyirq);
 			local_irq_enable();
 		}
-	} else
+	} else {
 		netdev_warn(dev->net,
 			    "unexpected interrupt: 0x%08x\n", intdata);
+	}
 }
 
 static int lan78xx_ethtool_get_eeprom_len(struct net_device *netdev)
@@ -1360,7 +1402,7 @@
 	struct lan78xx_priv *pdata = (struct lan78xx_priv *)(dev->data[0]);
 
 	if (usb_autopm_get_interface(dev->intf) < 0)
-			return;
+		return;
 
 	ret = lan78xx_read_reg(dev, USB_CFG0, &buf);
 	if (unlikely(ret < 0)) {
@@ -1386,13 +1428,13 @@
 	struct lan78xx_priv *pdata = (struct lan78xx_priv *)(dev->data[0]);
 	int ret;
 
+	if (wol->wolopts & ~WAKE_ALL)
+		return -EINVAL;
+
 	ret = usb_autopm_get_interface(dev->intf);
 	if (ret < 0)
 		return ret;
 
-	if (wol->wolopts & ~WAKE_ALL)
-		return -EINVAL;
-
 	pdata->wol = wol->wolopts;
 
 	device_set_wakeup_enable(&dev->udev->dev, (bool)wol->wolopts);
@@ -1474,9 +1516,14 @@
 
 static u32 lan78xx_get_link(struct net_device *net)
 {
+	u32 link;
+
+	mutex_lock(&net->phydev->lock);
 	phy_read_status(net->phydev);
+	link = net->phydev->link;
+	mutex_unlock(&net->phydev->lock);
 
-	return net->phydev->link;
+	return link;
 }
 
 static void lan78xx_get_drvinfo(struct net_device *net,
@@ -1674,11 +1721,10 @@
 static void lan78xx_init_mac_address(struct lan78xx_net *dev)
 {
 	u32 addr_lo, addr_hi;
-	int ret;
 	u8 addr[6];
 
-	ret = lan78xx_read_reg(dev, RX_ADDRL, &addr_lo);
-	ret = lan78xx_read_reg(dev, RX_ADDRH, &addr_hi);
+	lan78xx_read_reg(dev, RX_ADDRL, &addr_lo);
+	lan78xx_read_reg(dev, RX_ADDRH, &addr_hi);
 
 	addr[0] = addr_lo & 0xFF;
 	addr[1] = (addr_lo >> 8) & 0xFF;
@@ -1711,12 +1757,12 @@
 			  (addr[2] << 16) | (addr[3] << 24);
 		addr_hi = addr[4] | (addr[5] << 8);
 
-		ret = lan78xx_write_reg(dev, RX_ADDRL, addr_lo);
-		ret = lan78xx_write_reg(dev, RX_ADDRH, addr_hi);
+		lan78xx_write_reg(dev, RX_ADDRL, addr_lo);
+		lan78xx_write_reg(dev, RX_ADDRH, addr_hi);
 	}
 
-	ret = lan78xx_write_reg(dev, MAF_LO(0), addr_lo);
-	ret = lan78xx_write_reg(dev, MAF_HI(0), addr_hi | MAF_HI_VALID_);
+	lan78xx_write_reg(dev, MAF_LO(0), addr_lo);
+	lan78xx_write_reg(dev, MAF_HI(0), addr_hi | MAF_HI_VALID_);
 
 	ether_addr_copy(dev->net->dev_addr, addr);
 }
@@ -1808,6 +1854,7 @@
 	dev->mdiobus->read = lan78xx_mdiobus_read;
 	dev->mdiobus->write = lan78xx_mdiobus_write;
 	dev->mdiobus->name = "lan78xx-mdiobus";
+	dev->mdiobus->parent = &dev->udev->dev;
 
 	snprintf(dev->mdiobus->id, MII_BUS_ID_SIZE, "usb-%03d:%03d",
 		 dev->udev->bus->busnum, dev->udev->devnum);
@@ -1848,33 +1895,8 @@
 static void lan78xx_link_status_change(struct net_device *net)
 {
 	struct phy_device *phydev = net->phydev;
-	int ret, temp;
-
-	/* At forced 100 F/H mode, chip may fail to set mode correctly
-	 * when cable is switched between long(~50+m) and short one.
-	 * As workaround, set to 10 before setting to 100
-	 * at forced 100 F/H mode.
-	 */
-	if (!phydev->autoneg && (phydev->speed == 100)) {
-		/* disable phy interrupt */
-		temp = phy_read(phydev, LAN88XX_INT_MASK);
-		temp &= ~LAN88XX_INT_MASK_MDINTPIN_EN_;
-		ret = phy_write(phydev, LAN88XX_INT_MASK, temp);
 
-		temp = phy_read(phydev, MII_BMCR);
-		temp &= ~(BMCR_SPEED100 | BMCR_SPEED1000);
-		phy_write(phydev, MII_BMCR, temp); /* set to 10 first */
-		temp |= BMCR_SPEED100;
-		phy_write(phydev, MII_BMCR, temp); /* set to 100 later */
-
-		/* clear pending interrupt generated while workaround */
-		temp = phy_read(phydev, LAN88XX_INT_STS);
-
-		/* enable phy interrupt back */
-		temp = phy_read(phydev, LAN88XX_INT_MASK);
-		temp |= LAN88XX_INT_MASK_MDINTPIN_EN_;
-		ret = phy_write(phydev, LAN88XX_INT_MASK, temp);
-	}
+	phy_print_status(phydev);
 }
 
 static int irq_map(struct irq_domain *d, unsigned int irq,
@@ -1927,14 +1949,13 @@
 	struct lan78xx_net *dev =
 			container_of(data, struct lan78xx_net, domain_data);
 	u32 buf;
-	int ret;
 
 	/* call register access here because irq_bus_lock & irq_bus_sync_unlock
 	 * are only two callbacks executed in non-atomic contex.
 	 */
-	ret = lan78xx_read_reg(dev, INT_EP_CTL, &buf);
+	lan78xx_read_reg(dev, INT_EP_CTL, &buf);
 	if (buf != data->irqenable)
-		ret = lan78xx_write_reg(dev, INT_EP_CTL, data->irqenable);
+		lan78xx_write_reg(dev, INT_EP_CTL, data->irqenable);
 
 	mutex_unlock(&data->irq_lock);
 }
@@ -2001,7 +2022,6 @@
 static int lan8835_fixup(struct phy_device *phydev)
 {
 	int buf;
-	int ret;
 	struct lan78xx_net *dev = netdev_priv(phydev->attached_dev);
 
 	/* LED2/PME_N/IRQ_N/RGMII_ID pin to IRQ_N mode */
@@ -2011,11 +2031,11 @@
 	phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8010, buf);
 
 	/* RGMII MAC TXC Delay Enable */
-	ret = lan78xx_write_reg(dev, MAC_RGMII_ID,
-				MAC_RGMII_ID_TXC_DELAY_EN_);
+	lan78xx_write_reg(dev, MAC_RGMII_ID,
+			  MAC_RGMII_ID_TXC_DELAY_EN_);
 
 	/* RGMII TX DLL Tune Adjust */
-	ret = lan78xx_write_reg(dev, RGMII_TX_BYP_DLL, 0x3D00);
+	lan78xx_write_reg(dev, RGMII_TX_BYP_DLL, 0x3D00);
 
 	dev->interface = PHY_INTERFACE_MODE_RGMII_TXID;
 
@@ -2130,7 +2150,7 @@
 	if (dev->domain_data.phyirq > 0)
 		phydev->irq = dev->domain_data.phyirq;
 	else
-		phydev->irq = 0;
+		phydev->irq = PHY_POLL;
 	netdev_dbg(dev->net, "phydev->irq = %d\n", phydev->irq);
 
 	/* set to AUTOMDIX */
@@ -2145,6 +2165,7 @@
 		if (dev->chipid == ID_REV_CHIP_ID_7801_) {
 			if (phy_is_pseudo_fixed_link(phydev)) {
 				fixed_phy_unregister(phydev);
+				phy_device_free(phydev);
 			} else {
 				phy_unregister_fixup_for_uid(PHY_KSZ9031RNX,
 							     0xfffffff0);
@@ -2199,28 +2220,27 @@
 
 static int lan78xx_set_rx_max_frame_length(struct lan78xx_net *dev, int size)
 {
-	int ret = 0;
 	u32 buf;
 	bool rxenabled;
 
-	ret = lan78xx_read_reg(dev, MAC_RX, &buf);
+	lan78xx_read_reg(dev, MAC_RX, &buf);
 
 	rxenabled = ((buf & MAC_RX_RXEN_) != 0);
 
 	if (rxenabled) {
 		buf &= ~MAC_RX_RXEN_;
-		ret = lan78xx_write_reg(dev, MAC_RX, buf);
+		lan78xx_write_reg(dev, MAC_RX, buf);
 	}
 
 	/* add 4 to size for FCS */
 	buf &= ~MAC_RX_MAX_SIZE_MASK_;
 	buf |= (((size + 4) << MAC_RX_MAX_SIZE_SHIFT_) & MAC_RX_MAX_SIZE_MASK_);
 
-	ret = lan78xx_write_reg(dev, MAC_RX, buf);
+	lan78xx_write_reg(dev, MAC_RX, buf);
 
 	if (rxenabled) {
 		buf |= MAC_RX_RXEN_;
-		ret = lan78xx_write_reg(dev, MAC_RX, buf);
+		lan78xx_write_reg(dev, MAC_RX, buf);
 	}
 
 	return 0;
@@ -2283,7 +2303,11 @@
 	if ((ll_mtu % dev->maxpacket) == 0)
 		return -EDOM;
 
-	ret = lan78xx_set_rx_max_frame_length(dev, new_mtu + VLAN_ETH_HLEN);
+	ret = usb_autopm_get_interface(dev->intf);
+	if (ret < 0)
+		return ret;
+
+	lan78xx_set_rx_max_frame_length(dev, new_mtu + VLAN_ETH_HLEN);
 
 	netdev->mtu = new_mtu;
 
@@ -2298,6 +2322,8 @@
 		}
 	}
 
+	usb_autopm_put_interface(dev->intf);
+
 	return 0;
 }
 
@@ -2306,7 +2332,6 @@
 	struct lan78xx_net *dev = netdev_priv(netdev);
 	struct sockaddr *addr = p;
 	u32 addr_lo, addr_hi;
-	int ret;
 
 	if (netif_running(netdev))
 		return -EBUSY;
@@ -2323,12 +2348,12 @@
 	addr_hi = netdev->dev_addr[4] |
 		  netdev->dev_addr[5] << 8;
 
-	ret = lan78xx_write_reg(dev, RX_ADDRL, addr_lo);
-	ret = lan78xx_write_reg(dev, RX_ADDRH, addr_hi);
+	lan78xx_write_reg(dev, RX_ADDRL, addr_lo);
+	lan78xx_write_reg(dev, RX_ADDRH, addr_hi);
 
 	/* Added to support MAC address changes */
-	ret = lan78xx_write_reg(dev, MAF_LO(0), addr_lo);
-	ret = lan78xx_write_reg(dev, MAF_HI(0), addr_hi | MAF_HI_VALID_);
+	lan78xx_write_reg(dev, MAF_LO(0), addr_lo);
+	lan78xx_write_reg(dev, MAF_HI(0), addr_hi | MAF_HI_VALID_);
 
 	return 0;
 }
@@ -2340,7 +2365,6 @@
 	struct lan78xx_net *dev = netdev_priv(netdev);
 	struct lan78xx_priv *pdata = (struct lan78xx_priv *)(dev->data[0]);
 	unsigned long flags;
-	int ret;
 
 	spin_lock_irqsave(&pdata->rfe_ctl_lock, flags);
 
@@ -2364,7 +2388,7 @@
 
 	spin_unlock_irqrestore(&pdata->rfe_ctl_lock, flags);
 
-	ret = lan78xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl);
+	lan78xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl);
 
 	return 0;
 }
@@ -2456,26 +2480,186 @@
 	lan78xx_write_reg(dev, LTM_INACTIVE1, regs[5]);
 }
 
+static int lan78xx_start_hw(struct lan78xx_net *dev, u32 reg, u32 hw_enable)
+{
+	return lan78xx_update_reg(dev, reg, hw_enable, hw_enable);
+}
+
+static int lan78xx_stop_hw(struct lan78xx_net *dev, u32 reg, u32 hw_enabled,
+			   u32 hw_disabled)
+{
+	unsigned long timeout;
+	bool stopped = true;
+	int ret;
+	u32 buf;
+
+	/* Stop the h/w block (if not already stopped) */
+
+	ret = lan78xx_read_reg(dev, reg, &buf);
+	if (ret < 0)
+		return ret;
+
+	if (buf & hw_enabled) {
+		buf &= ~hw_enabled;
+
+		ret = lan78xx_write_reg(dev, reg, buf);
+		if (ret < 0)
+			return ret;
+
+		stopped = false;
+		timeout = jiffies + HW_DISABLE_TIMEOUT;
+		do  {
+			ret = lan78xx_read_reg(dev, reg, &buf);
+			if (ret < 0)
+				return ret;
+
+			if (buf & hw_disabled)
+				stopped = true;
+			else
+				msleep(HW_DISABLE_DELAY_MS);
+		} while (!stopped && !time_after(jiffies, timeout));
+	}
+
+	ret = stopped ? 0 : -ETIME;
+
+	return ret;
+}
+
+static int lan78xx_flush_fifo(struct lan78xx_net *dev, u32 reg, u32 fifo_flush)
+{
+	return lan78xx_update_reg(dev, reg, fifo_flush, fifo_flush);
+}
+
+static int lan78xx_start_tx_path(struct lan78xx_net *dev)
+{
+	int ret;
+
+	netif_dbg(dev, drv, dev->net, "start tx path");
+
+	/* Start the MAC transmitter */
+
+	ret = lan78xx_start_hw(dev, MAC_TX, MAC_TX_TXEN_);
+	if (ret < 0)
+		return ret;
+
+	/* Start the Tx FIFO */
+
+	ret = lan78xx_start_hw(dev, FCT_TX_CTL, FCT_TX_CTL_EN_);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int lan78xx_stop_tx_path(struct lan78xx_net *dev)
+{
+	int ret;
+
+	netif_dbg(dev, drv, dev->net, "stop tx path");
+
+	/* Stop the Tx FIFO */
+
+	ret = lan78xx_stop_hw(dev, FCT_TX_CTL, FCT_TX_CTL_EN_, FCT_TX_CTL_DIS_);
+	if (ret < 0)
+		return ret;
+
+	/* Stop the MAC transmitter */
+
+	ret = lan78xx_stop_hw(dev, MAC_TX, MAC_TX_TXEN_, MAC_TX_TXD_);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+/* The caller must ensure the Tx path is stopped before calling
+ * lan78xx_flush_tx_fifo().
+ */
+static int lan78xx_flush_tx_fifo(struct lan78xx_net *dev)
+{
+	return lan78xx_flush_fifo(dev, FCT_TX_CTL, FCT_TX_CTL_RST_);
+}
+
+static int lan78xx_start_rx_path(struct lan78xx_net *dev)
+{
+	int ret;
+
+	netif_dbg(dev, drv, dev->net, "start rx path");
+
+	/* Start the Rx FIFO */
+
+	ret = lan78xx_start_hw(dev, FCT_RX_CTL, FCT_RX_CTL_EN_);
+	if (ret < 0)
+		return ret;
+
+	/* Start the MAC receiver*/
+
+	ret = lan78xx_start_hw(dev, MAC_RX, MAC_RX_RXEN_);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int lan78xx_stop_rx_path(struct lan78xx_net *dev)
+{
+	int ret;
+
+	netif_dbg(dev, drv, dev->net, "stop rx path");
+
+	/* Stop the MAC receiver */
+
+	ret = lan78xx_stop_hw(dev, MAC_RX, MAC_RX_RXEN_, MAC_RX_RXD_);
+	if (ret < 0)
+		return ret;
+
+	/* Stop the Rx FIFO */
+
+	ret = lan78xx_stop_hw(dev, FCT_RX_CTL, FCT_RX_CTL_EN_, FCT_RX_CTL_DIS_);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+/* The caller must ensure the Rx path is stopped before calling
+ * lan78xx_flush_rx_fifo().
+ */
+static int lan78xx_flush_rx_fifo(struct lan78xx_net *dev)
+{
+	return lan78xx_flush_fifo(dev, FCT_RX_CTL, FCT_RX_CTL_RST_);
+}
+
 static int lan78xx_reset(struct lan78xx_net *dev)
 {
 	struct lan78xx_priv *pdata = (struct lan78xx_priv *)(dev->data[0]);
-	u32 buf;
-	int ret = 0;
 	unsigned long timeout;
+	int ret;
+	u32 buf;
 	u8 sig;
 
 	ret = lan78xx_read_reg(dev, HW_CFG, &buf);
+	if (ret < 0)
+		return ret;
+
 	buf |= HW_CFG_LRST_;
+
 	ret = lan78xx_write_reg(dev, HW_CFG, buf);
+	if (ret < 0)
+		return ret;
 
 	timeout = jiffies + HZ;
 	do {
 		mdelay(1);
 		ret = lan78xx_read_reg(dev, HW_CFG, &buf);
+		if (ret < 0)
+			return ret;
+
 		if (time_after(jiffies, timeout)) {
 			netdev_warn(dev->net,
 				    "timeout on completion of LiteReset");
-			return -EIO;
+			ret = -ETIMEDOUT;
+			return ret;
 		}
 	} while (buf & HW_CFG_LRST_);
 
@@ -2483,13 +2667,22 @@
 
 	/* save DEVID for later usage */
 	ret = lan78xx_read_reg(dev, ID_REV, &buf);
+	if (ret < 0)
+		return ret;
+
 	dev->chipid = (buf & ID_REV_CHIP_ID_MASK_) >> 16;
 	dev->chiprev = buf & ID_REV_CHIP_REV_MASK_;
 
 	/* Respond to the IN token with a NAK */
 	ret = lan78xx_read_reg(dev, USB_CFG0, &buf);
+	if (ret < 0)
+		return ret;
+
 	buf |= USB_CFG_BIR_;
+
 	ret = lan78xx_write_reg(dev, USB_CFG0, buf);
+	if (ret < 0)
+		return ret;
 
 	/* Init LTM */
 	lan78xx_init_ltm(dev);
@@ -2512,58 +2705,111 @@
 	}
 
 	ret = lan78xx_write_reg(dev, BURST_CAP, buf);
+	if (ret < 0)
+		return ret;
+
 	ret = lan78xx_write_reg(dev, BULK_IN_DLY, DEFAULT_BULK_IN_DELAY);
+	if (ret < 0)
+		return ret;
 
 	ret = lan78xx_read_reg(dev, HW_CFG, &buf);
+	if (ret < 0)
+		return ret;
+
 	buf |= HW_CFG_MEF_;
+
 	ret = lan78xx_write_reg(dev, HW_CFG, buf);
+	if (ret < 0)
+		return ret;
 
 	ret = lan78xx_read_reg(dev, USB_CFG0, &buf);
+	if (ret < 0)
+		return ret;
+
 	buf |= USB_CFG_BCE_;
+
 	ret = lan78xx_write_reg(dev, USB_CFG0, buf);
+	if (ret < 0)
+		return ret;
 
 	/* set FIFO sizes */
 	buf = (MAX_RX_FIFO_SIZE - 512) / 512;
+
 	ret = lan78xx_write_reg(dev, FCT_RX_FIFO_END, buf);
+	if (ret < 0)
+		return ret;
 
 	buf = (MAX_TX_FIFO_SIZE - 512) / 512;
+
 	ret = lan78xx_write_reg(dev, FCT_TX_FIFO_END, buf);
+	if (ret < 0)
+		return ret;
 
 	ret = lan78xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL_);
+	if (ret < 0)
+		return ret;
+
 	ret = lan78xx_write_reg(dev, FLOW, 0);
+	if (ret < 0)
+		return ret;
+
 	ret = lan78xx_write_reg(dev, FCT_FLOW, 0);
+	if (ret < 0)
+		return ret;
 
 	/* Don't need rfe_ctl_lock during initialisation */
 	ret = lan78xx_read_reg(dev, RFE_CTL, &pdata->rfe_ctl);
+	if (ret < 0)
+		return ret;
+
 	pdata->rfe_ctl |= RFE_CTL_BCAST_EN_ | RFE_CTL_DA_PERFECT_;
+
 	ret = lan78xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl);
+	if (ret < 0)
+		return ret;
 
 	/* Enable or disable checksum offload engines */
-	lan78xx_set_features(dev->net, dev->net->features);
+	ret = lan78xx_set_features(dev->net, dev->net->features);
+	if (ret < 0)
+		return ret;
 
 	lan78xx_set_multicast(dev->net);
 
 	/* reset PHY */
 	ret = lan78xx_read_reg(dev, PMT_CTL, &buf);
+	if (ret < 0)
+		return ret;
+
 	buf |= PMT_CTL_PHY_RST_;
+
 	ret = lan78xx_write_reg(dev, PMT_CTL, buf);
+	if (ret < 0)
+		return ret;
 
 	timeout = jiffies + HZ;
 	do {
 		mdelay(1);
 		ret = lan78xx_read_reg(dev, PMT_CTL, &buf);
+		if (ret < 0)
+			return ret;
+
 		if (time_after(jiffies, timeout)) {
 			netdev_warn(dev->net, "timeout waiting for PHY Reset");
-			return -EIO;
+			ret = -ETIMEDOUT;
+			return ret;
 		}
 	} while ((buf & PMT_CTL_PHY_RST_) || !(buf & PMT_CTL_READY_));
 
 	ret = lan78xx_read_reg(dev, MAC_CR, &buf);
+	if (ret < 0)
+		return ret;
+
 	/* LAN7801 only has RGMII mode */
 	if (dev->chipid == ID_REV_CHIP_ID_7801_)
 		buf &= ~MAC_CR_GMII_EN_;
 
-	if (dev->chipid == ID_REV_CHIP_ID_7800_) {
+	if (dev->chipid == ID_REV_CHIP_ID_7800_ ||
+	    dev->chipid == ID_REV_CHIP_ID_7850_) {
 		ret = lan78xx_read_raw_eeprom(dev, 0, 1, &sig);
 		if (!ret && sig != EEPROM_INDICATOR) {
 			/* Implies there is no external eeprom. Set mac speed */
@@ -2572,27 +2818,13 @@
 		}
 	}
 	ret = lan78xx_write_reg(dev, MAC_CR, buf);
-
-	ret = lan78xx_read_reg(dev, MAC_TX, &buf);
-	buf |= MAC_TX_TXEN_;
-	ret = lan78xx_write_reg(dev, MAC_TX, buf);
-
-	ret = lan78xx_read_reg(dev, FCT_TX_CTL, &buf);
-	buf |= FCT_TX_CTL_EN_;
-	ret = lan78xx_write_reg(dev, FCT_TX_CTL, buf);
+	if (ret < 0)
+		return ret;
 
 	ret = lan78xx_set_rx_max_frame_length(dev,
 					      dev->net->mtu + VLAN_ETH_HLEN);
 
-	ret = lan78xx_read_reg(dev, MAC_RX, &buf);
-	buf |= MAC_RX_RXEN_;
-	ret = lan78xx_write_reg(dev, MAC_RX, buf);
-
-	ret = lan78xx_read_reg(dev, FCT_RX_CTL, &buf);
-	buf |= FCT_RX_CTL_EN_;
-	ret = lan78xx_write_reg(dev, FCT_RX_CTL, buf);
-
-	return 0;
+	return ret;
 }
 
 static void lan78xx_init_stats(struct lan78xx_net *dev)
@@ -2626,9 +2858,13 @@
 	struct lan78xx_net *dev = netdev_priv(net);
 	int ret;
 
+	netif_dbg(dev, ifup, dev->net, "open device");
+
 	ret = usb_autopm_get_interface(dev->intf);
 	if (ret < 0)
-		goto out;
+		return ret;
+
+	mutex_lock(&dev->dev_mutex);
 
 	phy_start(net->phydev);
 
@@ -2644,6 +2880,20 @@
 		}
 	}
 
+	ret = lan78xx_flush_rx_fifo(dev);
+	if (ret < 0)
+		goto done;
+	ret = lan78xx_flush_tx_fifo(dev);
+	if (ret < 0)
+		goto done;
+
+	ret = lan78xx_start_tx_path(dev);
+	if (ret < 0)
+		goto done;
+	ret = lan78xx_start_rx_path(dev);
+	if (ret < 0)
+		goto done;
+
 	lan78xx_init_stats(dev);
 
 	set_bit(EVENT_DEV_OPEN, &dev->flags);
@@ -2654,9 +2904,11 @@
 
 	lan78xx_defer_kevent(dev, EVENT_LINK_RESET);
 done:
-	usb_autopm_put_interface(dev->intf);
+	mutex_unlock(&dev->dev_mutex);
+
+	if (ret < 0)
+		usb_autopm_put_interface(dev->intf);
 
-out:
 	return ret;
 }
 
@@ -2673,38 +2925,56 @@
 	temp = unlink_urbs(dev, &dev->txq) + unlink_urbs(dev, &dev->rxq);
 
 	/* maybe wait for deletions to finish. */
-	while (!skb_queue_empty(&dev->rxq) &&
-	       !skb_queue_empty(&dev->txq) &&
-	       !skb_queue_empty(&dev->done)) {
+	while (!skb_queue_empty(&dev->rxq) ||
+	       !skb_queue_empty(&dev->txq)) {
 		schedule_timeout(msecs_to_jiffies(UNLINK_TIMEOUT_MS));
 		set_current_state(TASK_UNINTERRUPTIBLE);
 		netif_dbg(dev, ifdown, dev->net,
-			  "waited for %d urb completions\n", temp);
+			  "waited for %d urb completions", temp);
 	}
 	set_current_state(TASK_RUNNING);
 	dev->wait = NULL;
 	remove_wait_queue(&unlink_wakeup, &wait);
+
+	while (!skb_queue_empty(&dev->done)) {
+		struct skb_data *entry;
+		struct sk_buff *skb;
+
+		skb = skb_dequeue(&dev->done);
+		entry = (struct skb_data *)(skb->cb);
+		usb_free_urb(entry->urb);
+		dev_kfree_skb(skb);
+	}
 }
 
 static int lan78xx_stop(struct net_device *net)
 {
 	struct lan78xx_net *dev = netdev_priv(net);
 
+	netif_dbg(dev, ifup, dev->net, "stop device");
+
+	mutex_lock(&dev->dev_mutex);
+
 	if (timer_pending(&dev->stat_monitor))
 		del_timer_sync(&dev->stat_monitor);
 
-	if (net->phydev)
-		phy_stop(net->phydev);
-
 	clear_bit(EVENT_DEV_OPEN, &dev->flags);
 	netif_stop_queue(net);
+	tasklet_kill(&dev->bh);
+
+	lan78xx_terminate_urbs(dev);
 
 	netif_info(dev, ifdown, dev->net,
 		   "stop stats: rx/tx %lu/%lu, errs %lu/%lu\n",
 		   net->stats.rx_packets, net->stats.tx_packets,
 		   net->stats.rx_errors, net->stats.tx_errors);
 
-	lan78xx_terminate_urbs(dev);
+	/* ignore errors that occur stopping the Tx and Rx data paths */
+	lan78xx_stop_tx_path(dev);
+	lan78xx_stop_rx_path(dev);
+
+	if (net->phydev)
+		phy_stop(net->phydev);
 
 	usb_kill_urb(dev->urb_intr);
 
@@ -2714,18 +2984,18 @@
 	 * can't flush_scheduled_work() until we drop rtnl (later),
 	 * else workers could deadlock; so make workers a NOP.
 	 */
-	dev->flags = 0;
+	clear_bit(EVENT_TX_HALT, &dev->flags);
+	clear_bit(EVENT_RX_HALT, &dev->flags);
+	clear_bit(EVENT_LINK_RESET, &dev->flags);
+	clear_bit(EVENT_STAT_UPDATE, &dev->flags);
+
 	cancel_delayed_work_sync(&dev->wq);
-	tasklet_kill(&dev->bh);
 
 	usb_autopm_put_interface(dev->intf);
 
-	return 0;
-}
+	mutex_unlock(&dev->dev_mutex);
 
-static int lan78xx_linearize(struct sk_buff *skb)
-{
-	return skb_linearize(skb);
+	return 0;
 }
 
 static struct sk_buff *lan78xx_tx_prep(struct lan78xx_net *dev,
@@ -2739,8 +3009,10 @@
 		return NULL;
 	}
 
-	if (lan78xx_linearize(skb) < 0)
+	if (skb_linearize(skb)) {
+		dev_kfree_skb_any(skb);
 		return NULL;
+	}
 
 	tx_cmd_a = (u32)(skb->len & TX_CMD_A_LEN_MASK_) | TX_CMD_A_FCS_;
 
@@ -2845,6 +3117,9 @@
 	struct lan78xx_net *dev = netdev_priv(net);
 	struct sk_buff *skb2 = NULL;
 
+	if (test_bit(EVENT_DEV_ASLEEP, &dev->flags))
+		schedule_delayed_work(&dev->wq, 0);
+
 	if (skb) {
 		skb_tx_timestamp(skb);
 		skb2 = lan78xx_tx_prep(dev, skb, GFP_ATOMIC);
@@ -2869,78 +3144,12 @@
 	return NETDEV_TX_OK;
 }
 
-static int
-lan78xx_get_endpoints(struct lan78xx_net *dev, struct usb_interface *intf)
-{
-	int tmp;
-	struct usb_host_interface *alt = NULL;
-	struct usb_host_endpoint *in = NULL, *out = NULL;
-	struct usb_host_endpoint *status = NULL;
-
-	for (tmp = 0; tmp < intf->num_altsetting; tmp++) {
-		unsigned ep;
-
-		in = NULL;
-		out = NULL;
-		status = NULL;
-		alt = intf->altsetting + tmp;
-
-		for (ep = 0; ep < alt->desc.bNumEndpoints; ep++) {
-			struct usb_host_endpoint *e;
-			int intr = 0;
-
-			e = alt->endpoint + ep;
-			switch (e->desc.bmAttributes) {
-			case USB_ENDPOINT_XFER_INT:
-				if (!usb_endpoint_dir_in(&e->desc))
-					continue;
-				intr = 1;
-				/* FALLTHROUGH */
-			case USB_ENDPOINT_XFER_BULK:
-				break;
-			default:
-				continue;
-			}
-			if (usb_endpoint_dir_in(&e->desc)) {
-				if (!intr && !in)
-					in = e;
-				else if (intr && !status)
-					status = e;
-			} else {
-				if (!out)
-					out = e;
-			}
-		}
-		if (in && out)
-			break;
-	}
-	if (!alt || !in || !out)
-		return -EINVAL;
-
-	dev->pipe_in = usb_rcvbulkpipe(dev->udev,
-				       in->desc.bEndpointAddress &
-				       USB_ENDPOINT_NUMBER_MASK);
-	dev->pipe_out = usb_sndbulkpipe(dev->udev,
-					out->desc.bEndpointAddress &
-					USB_ENDPOINT_NUMBER_MASK);
-	dev->ep_intr = status;
-
-	return 0;
-}
-
 static int lan78xx_bind(struct lan78xx_net *dev, struct usb_interface *intf)
 {
 	struct lan78xx_priv *pdata = NULL;
 	int ret;
 	int i;
 
-	ret = lan78xx_get_endpoints(dev, intf);
-	if (ret) {
-		netdev_warn(dev->net, "lan78xx_get_endpoints failed: %d\n",
-			    ret);
-		return ret;
-	}
-
 	dev->data[0] = (unsigned long)kzalloc(sizeof(*pdata), GFP_KERNEL);
 
 	pdata = (struct lan78xx_priv *)(dev->data[0]);
@@ -3438,9 +3647,10 @@
 		if (skb)
 			dev_kfree_skb_any(skb);
 		usb_free_urb(urb);
-	} else
+	} else {
 		netif_dbg(dev, tx_queued, dev->net,
 			  "> tx, len %d, type 0x%x\n", length, skb->protocol);
+	}
 }
 
 static void lan78xx_rx_bh(struct lan78xx_net *dev)
@@ -3516,18 +3726,17 @@
 
 	dev = container_of(work, struct lan78xx_net, wq.work);
 
+	if (usb_autopm_get_interface(dev->intf) < 0)
+		return;
+
 	if (test_bit(EVENT_TX_HALT, &dev->flags)) {
 		unlink_urbs(dev, &dev->txq);
-		status = usb_autopm_get_interface(dev->intf);
-		if (status < 0)
-			goto fail_pipe;
+
 		status = usb_clear_halt(dev->udev, dev->pipe_out);
-		usb_autopm_put_interface(dev->intf);
 		if (status < 0 &&
 		    status != -EPIPE &&
 		    status != -ESHUTDOWN) {
 			if (netif_msg_tx_err(dev))
-fail_pipe:
 				netdev_err(dev->net,
 					   "can't clear tx halt, status %d\n",
 					   status);
@@ -3537,18 +3746,14 @@
 				netif_wake_queue(dev->net);
 		}
 	}
+
 	if (test_bit(EVENT_RX_HALT, &dev->flags)) {
 		unlink_urbs(dev, &dev->rxq);
-		status = usb_autopm_get_interface(dev->intf);
-		if (status < 0)
-				goto fail_halt;
 		status = usb_clear_halt(dev->udev, dev->pipe_in);
-		usb_autopm_put_interface(dev->intf);
 		if (status < 0 &&
 		    status != -EPIPE &&
 		    status != -ESHUTDOWN) {
 			if (netif_msg_rx_err(dev))
-fail_halt:
 				netdev_err(dev->net,
 					   "can't clear rx halt, status %d\n",
 					   status);
@@ -3562,16 +3767,9 @@
 		int ret = 0;
 
 		clear_bit(EVENT_LINK_RESET, &dev->flags);
-		status = usb_autopm_get_interface(dev->intf);
-		if (status < 0)
-			goto skip_reset;
 		if (lan78xx_link_reset(dev) < 0) {
-			usb_autopm_put_interface(dev->intf);
-skip_reset:
 			netdev_info(dev->net, "link reset failed (%d)\n",
 				    ret);
-		} else {
-			usb_autopm_put_interface(dev->intf);
 		}
 	}
 
@@ -3585,6 +3783,8 @@
 
 		dev->delta = min((dev->delta * 2), 50);
 	}
+
+	usb_autopm_put_interface(dev->intf);
 }
 
 static void intr_complete(struct urb *urb)
@@ -3644,8 +3844,10 @@
 
 	phy_disconnect(net->phydev);
 
-	if (phy_is_pseudo_fixed_link(phydev))
+	if (phy_is_pseudo_fixed_link(phydev)) {
 		fixed_phy_unregister(phydev);
+		phy_device_free(phydev);
+	}
 
 	unregister_netdev(net);
 
@@ -3670,6 +3872,19 @@
 	tasklet_schedule(&dev->bh);
 }
 
+static netdev_features_t lan78xx_features_check(struct sk_buff *skb,
+						struct net_device *netdev,
+						netdev_features_t features)
+{
+	if (skb->len + TX_OVERHEAD > MAX_SINGLE_PACKET_SIZE)
+		features &= ~NETIF_F_GSO_MASK;
+
+	features = vlan_features_check(skb, features);
+	features = vxlan_features_check(skb, features);
+
+	return features;
+}
+
 static const struct net_device_ops lan78xx_netdev_ops = {
 	.ndo_open		= lan78xx_open,
 	.ndo_stop		= lan78xx_stop,
@@ -3683,6 +3898,7 @@
 	.ndo_set_features	= lan78xx_set_features,
 	.ndo_vlan_rx_add_vid	= lan78xx_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid	= lan78xx_vlan_rx_kill_vid,
+	.ndo_features_check	= lan78xx_features_check,
 };
 
 static void lan78xx_stat_monitor(struct timer_list *t)
@@ -3695,12 +3911,13 @@
 static int lan78xx_probe(struct usb_interface *intf,
 			 const struct usb_device_id *id)
 {
+	struct usb_host_endpoint *ep_blkin, *ep_blkout, *ep_intr;
 	struct lan78xx_net *dev;
 	struct net_device *netdev;
 	struct usb_device *udev;
 	int ret;
-	unsigned maxp;
-	unsigned period;
+	unsigned int maxp;
+	unsigned int period;
 	u8 *buf = NULL;
 
 	udev = interface_to_usbdev(intf);
@@ -3729,6 +3946,7 @@
 	skb_queue_head_init(&dev->rxq_pause);
 	skb_queue_head_init(&dev->txq_pend);
 	mutex_init(&dev->phy_mutex);
+	mutex_init(&dev->dev_mutex);
 
 	tasklet_init(&dev->bh, lan78xx_bh, (unsigned long)dev);
 	INIT_DELAYED_WORK(&dev->wq, lan78xx_delayedwork);
@@ -3743,6 +3961,34 @@
 
 	mutex_init(&dev->stats.access_lock);
 
+	if (intf->cur_altsetting->desc.bNumEndpoints < 3) {
+		ret = -ENODEV;
+		goto out2;
+	}
+
+	dev->pipe_in = usb_rcvbulkpipe(udev, BULK_IN_PIPE);
+	ep_blkin = usb_pipe_endpoint(udev, dev->pipe_in);
+	if (!ep_blkin || !usb_endpoint_is_bulk_in(&ep_blkin->desc)) {
+		ret = -ENODEV;
+		goto out2;
+	}
+
+	dev->pipe_out = usb_sndbulkpipe(udev, BULK_OUT_PIPE);
+	ep_blkout = usb_pipe_endpoint(udev, dev->pipe_out);
+	if (!ep_blkout || !usb_endpoint_is_bulk_out(&ep_blkout->desc)) {
+		ret = -ENODEV;
+		goto out2;
+	}
+
+	ep_intr = &intf->cur_altsetting->endpoint[2];
+	if (!usb_endpoint_is_int_in(&ep_intr->desc)) {
+		ret = -ENODEV;
+		goto out2;
+	}
+
+	dev->pipe_intr = usb_rcvintpipe(dev->udev,
+					usb_endpoint_num(&ep_intr->desc));
+
 	ret = lan78xx_bind(dev, intf);
 	if (ret < 0)
 		goto out2;
@@ -3752,19 +3998,9 @@
 
 	/* MTU range: 68 - 9000 */
 	netdev->max_mtu = MAX_SINGLE_PACKET_SIZE;
+	netif_set_gso_max_size(netdev, MAX_SINGLE_PACKET_SIZE - MAX_HEADER);
 
-	dev->ep_blkin = (intf->cur_altsetting)->endpoint + 0;
-	dev->ep_blkout = (intf->cur_altsetting)->endpoint + 1;
-	dev->ep_intr = (intf->cur_altsetting)->endpoint + 2;
-
-	dev->pipe_in = usb_rcvbulkpipe(udev, BULK_IN_PIPE);
-	dev->pipe_out = usb_sndbulkpipe(udev, BULK_OUT_PIPE);
-
-	dev->pipe_intr = usb_rcvintpipe(dev->udev,
-					dev->ep_intr->desc.bEndpointAddress &
-					USB_ENDPOINT_NUMBER_MASK);
-	period = dev->ep_intr->desc.bInterval;
-
+	period = ep_intr->desc.bInterval;
 	maxp = usb_maxpacket(dev->udev, dev->pipe_intr, 0);
 	buf = kmalloc(maxp, GFP_KERNEL);
 	if (buf) {
@@ -3777,11 +4013,18 @@
 			usb_fill_int_urb(dev->urb_intr, dev->udev,
 					 dev->pipe_intr, buf, maxp,
 					 intr_complete, dev, period);
+			dev->urb_intr->transfer_flags |= URB_FREE_BUFFER;
 		}
 	}
 
 	dev->maxpacket = usb_maxpacket(dev->udev, dev->pipe_out, 1);
 
+	/* Reject broken descriptors. */
+	if (dev->maxpacket == 0) {
+		ret = -ENODEV;
+		goto out4;
+	}
+
 	/* driver requires remote-wakeup capability during autosuspend. */
 	intf->needs_remote_wakeup = 1;
 
@@ -3846,38 +4089,119 @@
 	return crc;
 }
 
-static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol)
+static int lan78xx_set_auto_suspend(struct lan78xx_net *dev)
 {
 	u32 buf;
 	int ret;
-	int mask_index;
-	u16 crc;
-	u32 temp_wucsr;
-	u32 temp_pmt_ctl;
+
+	ret = lan78xx_stop_tx_path(dev);
+	if (ret < 0)
+		return ret;
+
+	ret = lan78xx_stop_rx_path(dev);
+	if (ret < 0)
+		return ret;
+
+	/* auto suspend (selective suspend) */
+
+	ret = lan78xx_write_reg(dev, WUCSR, 0);
+	if (ret < 0)
+		return ret;
+	ret = lan78xx_write_reg(dev, WUCSR2, 0);
+	if (ret < 0)
+		return ret;
+	ret = lan78xx_write_reg(dev, WK_SRC, 0xFFF1FF1FUL);
+	if (ret < 0)
+		return ret;
+
+	/* set goodframe wakeup */
+
+	ret = lan78xx_read_reg(dev, WUCSR, &buf);
+	if (ret < 0)
+		return ret;
+
+	buf |= WUCSR_RFE_WAKE_EN_;
+	buf |= WUCSR_STORE_WAKE_;
+
+	ret = lan78xx_write_reg(dev, WUCSR, buf);
+	if (ret < 0)
+		return ret;
+
+	ret = lan78xx_read_reg(dev, PMT_CTL, &buf);
+	if (ret < 0)
+		return ret;
+
+	buf &= ~PMT_CTL_RES_CLR_WKP_EN_;
+	buf |= PMT_CTL_RES_CLR_WKP_STS_;
+	buf |= PMT_CTL_PHY_WAKE_EN_;
+	buf |= PMT_CTL_WOL_EN_;
+	buf &= ~PMT_CTL_SUS_MODE_MASK_;
+	buf |= PMT_CTL_SUS_MODE_3_;
+
+	ret = lan78xx_write_reg(dev, PMT_CTL, buf);
+	if (ret < 0)
+		return ret;
+
+	ret = lan78xx_read_reg(dev, PMT_CTL, &buf);
+	if (ret < 0)
+		return ret;
+
+	buf |= PMT_CTL_WUPS_MASK_;
+
+	ret = lan78xx_write_reg(dev, PMT_CTL, buf);
+	if (ret < 0)
+		return ret;
+
+	ret = lan78xx_start_rx_path(dev);
+
+	return ret;
+}
+
+static int lan78xx_set_suspend(struct lan78xx_net *dev, u32 wol)
+{
 	const u8 ipv4_multicast[3] = { 0x01, 0x00, 0x5E };
 	const u8 ipv6_multicast[3] = { 0x33, 0x33 };
 	const u8 arp_type[2] = { 0x08, 0x06 };
+	u32 temp_pmt_ctl;
+	int mask_index;
+	u32 temp_wucsr;
+	u32 buf;
+	u16 crc;
+	int ret;
 
-	ret = lan78xx_read_reg(dev, MAC_TX, &buf);
-	buf &= ~MAC_TX_TXEN_;
-	ret = lan78xx_write_reg(dev, MAC_TX, buf);
-	ret = lan78xx_read_reg(dev, MAC_RX, &buf);
-	buf &= ~MAC_RX_RXEN_;
-	ret = lan78xx_write_reg(dev, MAC_RX, buf);
+	ret = lan78xx_stop_tx_path(dev);
+	if (ret < 0)
+		return ret;
+	ret = lan78xx_stop_rx_path(dev);
+	if (ret < 0)
+		return ret;
 
 	ret = lan78xx_write_reg(dev, WUCSR, 0);
+	if (ret < 0)
+		return ret;
 	ret = lan78xx_write_reg(dev, WUCSR2, 0);
+	if (ret < 0)
+		return ret;
 	ret = lan78xx_write_reg(dev, WK_SRC, 0xFFF1FF1FUL);
+	if (ret < 0)
+		return ret;
 
 	temp_wucsr = 0;
 
 	temp_pmt_ctl = 0;
+
 	ret = lan78xx_read_reg(dev, PMT_CTL, &temp_pmt_ctl);
+	if (ret < 0)
+		return ret;
+
 	temp_pmt_ctl &= ~PMT_CTL_RES_CLR_WKP_EN_;
 	temp_pmt_ctl |= PMT_CTL_RES_CLR_WKP_STS_;
 
-	for (mask_index = 0; mask_index < NUM_OF_WUF_CFG; mask_index++)
+	for (mask_index = 0; mask_index < NUM_OF_WUF_CFG; mask_index++) {
 		ret = lan78xx_write_reg(dev, WUF_CFG(mask_index), 0);
+		if (ret < 0)
+			return ret;
+	}
 
 	mask_index = 0;
 	if (wol & WAKE_PHY) {
@@ -3911,11 +4235,22 @@
 					WUF_CFGX_TYPE_MCAST_ |
 					(0 << WUF_CFGX_OFFSET_SHIFT_) |
 					(crc & WUF_CFGX_CRC16_MASK_));
+		if (ret < 0)
+			return ret;
 
 		ret = lan78xx_write_reg(dev, WUF_MASK0(mask_index), 7);
+		if (ret < 0)
+			return ret;
 		ret = lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0);
+		if (ret < 0)
+			return ret;
 		ret = lan78xx_write_reg(dev, WUF_MASK2(mask_index), 0);
+		if (ret < 0)
+			return ret;
 		ret = lan78xx_write_reg(dev, WUF_MASK3(mask_index), 0);
+		if (ret < 0)
+			return ret;
+
 		mask_index++;
 
 		/* for IPv6 Multicast */
@@ -3925,11 +4260,22 @@
 					WUF_CFGX_TYPE_MCAST_ |
 					(0 << WUF_CFGX_OFFSET_SHIFT_) |
 					(crc & WUF_CFGX_CRC16_MASK_));
+		if (ret < 0)
+			return ret;
 
 		ret = lan78xx_write_reg(dev, WUF_MASK0(mask_index), 3);
+		if (ret < 0)
+			return ret;
 		ret = lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0);
+		if (ret < 0)
+			return ret;
 		ret = lan78xx_write_reg(dev, WUF_MASK2(mask_index), 0);
+		if (ret < 0)
+			return ret;
 		ret = lan78xx_write_reg(dev, WUF_MASK3(mask_index), 0);
+		if (ret < 0)
+			return ret;
+
 		mask_index++;
 
 		temp_pmt_ctl |= PMT_CTL_WOL_EN_;
@@ -3955,11 +4301,22 @@
 					WUF_CFGX_TYPE_ALL_ |
 					(0 << WUF_CFGX_OFFSET_SHIFT_) |
 					(crc & WUF_CFGX_CRC16_MASK_));
+		if (ret < 0)
+			return ret;
 
 		ret = lan78xx_write_reg(dev, WUF_MASK0(mask_index), 0x3000);
+		if (ret < 0)
+			return ret;
 		ret = lan78xx_write_reg(dev, WUF_MASK1(mask_index), 0);
+		if (ret < 0)
+			return ret;
 		ret = lan78xx_write_reg(dev, WUF_MASK2(mask_index), 0);
+		if (ret < 0)
+			return ret;
 		ret = lan78xx_write_reg(dev, WUF_MASK3(mask_index), 0);
+		if (ret < 0)
+			return ret;
+
 		mask_index++;
 
 		temp_pmt_ctl |= PMT_CTL_WOL_EN_;
@@ -3968,6 +4325,8 @@
 	}
 
 	ret = lan78xx_write_reg(dev, WUCSR, temp_wucsr);
+	if (ret < 0)
+		return ret;
 
 	/* when multiple WOL bits are set */
 	if (hweight_long((unsigned long)wol) > 1) {
@@ -3976,35 +4335,47 @@
 		temp_pmt_ctl |= PMT_CTL_SUS_MODE_0_;
 	}
 	ret = lan78xx_write_reg(dev, PMT_CTL, temp_pmt_ctl);
+	if (ret < 0)
+		return ret;
 
 	/* clear WUPS */
 	ret = lan78xx_read_reg(dev, PMT_CTL, &buf);
+	if (ret < 0)
+		return ret;
+
 	buf |= PMT_CTL_WUPS_MASK_;
+
 	ret = lan78xx_write_reg(dev, PMT_CTL, buf);
+	if (ret < 0)
+		return ret;
 
-	ret = lan78xx_read_reg(dev, MAC_RX, &buf);
-	buf |= MAC_RX_RXEN_;
-	ret = lan78xx_write_reg(dev, MAC_RX, buf);
+	ret = lan78xx_start_rx_path(dev);
 
-	return 0;
+	return ret;
 }
 
 static int lan78xx_suspend(struct usb_interface *intf, pm_message_t message)
 {
 	struct lan78xx_net *dev = usb_get_intfdata(intf);
-	struct lan78xx_priv *pdata = (struct lan78xx_priv *)(dev->data[0]);
-	u32 buf;
+	bool dev_open;
 	int ret;
 	int event;
 
 	event = message.event;
 
-	if (!dev->suspend_count++) {
+	mutex_lock(&dev->dev_mutex);
+
+	netif_dbg(dev, ifdown, dev->net,
+		  "suspending: pm event %#x", message.event);
+
+	dev_open = test_bit(EVENT_DEV_OPEN, &dev->flags);
+
+	if (dev_open) {
 		spin_lock_irq(&dev->txq.lock);
 		/* don't autosuspend while transmitting */
 		if ((skb_queue_len(&dev->txq) ||
 		     skb_queue_len(&dev->txq_pend)) &&
-			PMSG_IS_AUTO(message)) {
+		    PMSG_IS_AUTO(message)) {
 			spin_unlock_irq(&dev->txq.lock);
 			ret = -EBUSY;
 			goto out;
@@ -4013,129 +4384,207 @@
 			spin_unlock_irq(&dev->txq.lock);
 		}
 
-		/* stop TX & RX */
-		ret = lan78xx_read_reg(dev, MAC_TX, &buf);
-		buf &= ~MAC_TX_TXEN_;
-		ret = lan78xx_write_reg(dev, MAC_TX, buf);
-		ret = lan78xx_read_reg(dev, MAC_RX, &buf);
-		buf &= ~MAC_RX_RXEN_;
-		ret = lan78xx_write_reg(dev, MAC_RX, buf);
+		/* stop RX */
+		ret = lan78xx_stop_rx_path(dev);
+		if (ret < 0)
+			goto out;
 
-		/* empty out the rx and queues */
+		ret = lan78xx_flush_rx_fifo(dev);
+		if (ret < 0)
+			goto out;
+
+		/* stop Tx */
+		ret = lan78xx_stop_tx_path(dev);
+		if (ret < 0)
+			goto out;
+
+		/* empty out the Rx and Tx queues */
 		netif_device_detach(dev->net);
 		lan78xx_terminate_urbs(dev);
 		usb_kill_urb(dev->urb_intr);
 
 		/* reattach */
 		netif_device_attach(dev->net);
-	}
 
-	if (test_bit(EVENT_DEV_ASLEEP, &dev->flags)) {
 		del_timer(&dev->stat_monitor);
 
 		if (PMSG_IS_AUTO(message)) {
-			/* auto suspend (selective suspend) */
-			ret = lan78xx_read_reg(dev, MAC_TX, &buf);
-			buf &= ~MAC_TX_TXEN_;
-			ret = lan78xx_write_reg(dev, MAC_TX, buf);
-			ret = lan78xx_read_reg(dev, MAC_RX, &buf);
-			buf &= ~MAC_RX_RXEN_;
-			ret = lan78xx_write_reg(dev, MAC_RX, buf);
+			ret = lan78xx_set_auto_suspend(dev);
+			if (ret < 0)
+				goto out;
+		} else {
+			struct lan78xx_priv *pdata;
 
-			ret = lan78xx_write_reg(dev, WUCSR, 0);
-			ret = lan78xx_write_reg(dev, WUCSR2, 0);
-			ret = lan78xx_write_reg(dev, WK_SRC, 0xFFF1FF1FUL);
+			pdata = (struct lan78xx_priv *)(dev->data[0]);
+			netif_carrier_off(dev->net);
+			ret = lan78xx_set_suspend(dev, pdata->wol);
+			if (ret < 0)
+				goto out;
+		}
+	} else {
+		/* Interface is down; don't allow WOL and PHY
+		 * events to wake up the host
+		 */
+		u32 buf;
 
-			/* set goodframe wakeup */
-			ret = lan78xx_read_reg(dev, WUCSR, &buf);
+		set_bit(EVENT_DEV_ASLEEP, &dev->flags);
 
-			buf |= WUCSR_RFE_WAKE_EN_;
-			buf |= WUCSR_STORE_WAKE_;
+		ret = lan78xx_write_reg(dev, WUCSR, 0);
+		if (ret < 0)
+			goto out;
+		ret = lan78xx_write_reg(dev, WUCSR2, 0);
+		if (ret < 0)
+			goto out;
 
-			ret = lan78xx_write_reg(dev, WUCSR, buf);
+		ret = lan78xx_read_reg(dev, PMT_CTL, &buf);
+		if (ret < 0)
+			goto out;
 
-			ret = lan78xx_read_reg(dev, PMT_CTL, &buf);
+		buf &= ~PMT_CTL_RES_CLR_WKP_EN_;
+		buf |= PMT_CTL_RES_CLR_WKP_STS_;
+		buf &= ~PMT_CTL_SUS_MODE_MASK_;
+		buf |= PMT_CTL_SUS_MODE_3_;
 
-			buf &= ~PMT_CTL_RES_CLR_WKP_EN_;
-			buf |= PMT_CTL_RES_CLR_WKP_STS_;
+		ret = lan78xx_write_reg(dev, PMT_CTL, buf);
+		if (ret < 0)
+			goto out;
 
-			buf |= PMT_CTL_PHY_WAKE_EN_;
-			buf |= PMT_CTL_WOL_EN_;
-			buf &= ~PMT_CTL_SUS_MODE_MASK_;
-			buf |= PMT_CTL_SUS_MODE_3_;
+		ret = lan78xx_read_reg(dev, PMT_CTL, &buf);
+		if (ret < 0)
+			goto out;
 
-			ret = lan78xx_write_reg(dev, PMT_CTL, buf);
+		buf |= PMT_CTL_WUPS_MASK_;
 
-			ret = lan78xx_read_reg(dev, PMT_CTL, &buf);
+		ret = lan78xx_write_reg(dev, PMT_CTL, buf);
+		if (ret < 0)
+			goto out;
+	}
+
+	ret = 0;
+out:
+	mutex_unlock(&dev->dev_mutex);
 
-			buf |= PMT_CTL_WUPS_MASK_;
+	return ret;
+}
 
-			ret = lan78xx_write_reg(dev, PMT_CTL, buf);
+static bool lan78xx_submit_deferred_urbs(struct lan78xx_net *dev)
+{
+	bool pipe_halted = false;
+	struct urb *urb;
 
-			ret = lan78xx_read_reg(dev, MAC_RX, &buf);
-			buf |= MAC_RX_RXEN_;
-			ret = lan78xx_write_reg(dev, MAC_RX, buf);
+	while ((urb = usb_get_from_anchor(&dev->deferred))) {
+		struct sk_buff *skb = urb->context;
+		int ret;
+
+		if (!netif_device_present(dev->net) ||
+		    !netif_carrier_ok(dev->net) ||
+		    pipe_halted) {
+			usb_free_urb(urb);
+			dev_kfree_skb(skb);
+			continue;
+		}
+
+		ret = usb_submit_urb(urb, GFP_ATOMIC);
+
+		if (ret == 0) {
+			netif_trans_update(dev->net);
+			lan78xx_queue_skb(&dev->txq, skb, tx_start);
 		} else {
-			lan78xx_set_suspend(dev, pdata->wol);
+			usb_free_urb(urb);
+			dev_kfree_skb(skb);
+
+			if (ret == -EPIPE) {
+				netif_stop_queue(dev->net);
+				pipe_halted = true;
+			} else if (ret == -ENODEV) {
+				netif_device_detach(dev->net);
+			}
 		}
 	}
 
-	ret = 0;
-out:
-	return ret;
+	return pipe_halted;
 }
 
 static int lan78xx_resume(struct usb_interface *intf)
 {
 	struct lan78xx_net *dev = usb_get_intfdata(intf);
-	struct sk_buff *skb;
-	struct urb *res;
+	bool dev_open;
 	int ret;
-	u32 buf;
 
-	if (!timer_pending(&dev->stat_monitor)) {
-		dev->delta = 1;
-		mod_timer(&dev->stat_monitor,
-			  jiffies + STAT_UPDATE_TIMER);
-	}
+	mutex_lock(&dev->dev_mutex);
 
-	if (!--dev->suspend_count) {
-		/* resume interrupt URBs */
-		if (dev->urb_intr && test_bit(EVENT_DEV_OPEN, &dev->flags))
-				usb_submit_urb(dev->urb_intr, GFP_NOIO);
+	netif_dbg(dev, ifup, dev->net, "resuming device");
+
+	dev_open = test_bit(EVENT_DEV_OPEN, &dev->flags);
+
+	if (dev_open) {
+		bool pipe_halted = false;
+
+		ret = lan78xx_flush_tx_fifo(dev);
+		if (ret < 0)
+			goto out;
+
+		if (dev->urb_intr) {
+			int ret = usb_submit_urb(dev->urb_intr, GFP_KERNEL);
 
-		spin_lock_irq(&dev->txq.lock);
-		while ((res = usb_get_from_anchor(&dev->deferred))) {
-			skb = (struct sk_buff *)res->context;
-			ret = usb_submit_urb(res, GFP_ATOMIC);
 			if (ret < 0) {
-				dev_kfree_skb_any(skb);
-				usb_free_urb(res);
-				usb_autopm_put_interface_async(dev->intf);
-			} else {
-				netif_trans_update(dev->net);
-				lan78xx_queue_skb(&dev->txq, skb, tx_start);
+				if (ret == -ENODEV)
+					netif_device_detach(dev->net);
+
+			netdev_warn(dev->net, "Failed to submit intr URB");
 			}
 		}
 
+		spin_lock_irq(&dev->txq.lock);
+
+		if (netif_device_present(dev->net)) {
+			pipe_halted = lan78xx_submit_deferred_urbs(dev);
+
+			if (pipe_halted)
+				lan78xx_defer_kevent(dev, EVENT_TX_HALT);
+		}
+
 		clear_bit(EVENT_DEV_ASLEEP, &dev->flags);
+
 		spin_unlock_irq(&dev->txq.lock);
 
-		if (test_bit(EVENT_DEV_OPEN, &dev->flags)) {
-			if (!(skb_queue_len(&dev->txq) >= dev->tx_qlen))
-				netif_start_queue(dev->net);
-			tasklet_schedule(&dev->bh);
+		if (!pipe_halted &&
+		    netif_device_present(dev->net) &&
+		    (skb_queue_len(&dev->txq) < dev->tx_qlen))
+			netif_start_queue(dev->net);
+
+		ret = lan78xx_start_tx_path(dev);
+		if (ret < 0)
+			goto out;
+
+		tasklet_schedule(&dev->bh);
+
+		if (!timer_pending(&dev->stat_monitor)) {
+			dev->delta = 1;
+			mod_timer(&dev->stat_monitor,
+				  jiffies + STAT_UPDATE_TIMER);
 		}
+
+	} else {
+		clear_bit(EVENT_DEV_ASLEEP, &dev->flags);
 	}
 
 	ret = lan78xx_write_reg(dev, WUCSR2, 0);
+	if (ret < 0)
+		goto out;
 	ret = lan78xx_write_reg(dev, WUCSR, 0);
+	if (ret < 0)
+		goto out;
 	ret = lan78xx_write_reg(dev, WK_SRC, 0xFFF1FF1FUL);
+	if (ret < 0)
+		goto out;
 
 	ret = lan78xx_write_reg(dev, WUCSR2, WUCSR2_NS_RCD_ |
 					     WUCSR2_ARP_RCD_ |
 					     WUCSR2_IPV6_TCPSYN_RCD_ |
 					     WUCSR2_IPV4_TCPSYN_RCD_);
+	if (ret < 0)
+		goto out;
 
 	ret = lan78xx_write_reg(dev, WUCSR, WUCSR_EEE_TX_WAKE_ |
 					    WUCSR_EEE_RX_WAKE_ |
@@ -4144,23 +4593,32 @@
 					    WUCSR_WUFR_ |
 					    WUCSR_MPR_ |
 					    WUCSR_BCST_FR_);
+	if (ret < 0)
+		goto out;
 
-	ret = lan78xx_read_reg(dev, MAC_TX, &buf);
-	buf |= MAC_TX_TXEN_;
-	ret = lan78xx_write_reg(dev, MAC_TX, buf);
+	ret = 0;
+out:
+	mutex_unlock(&dev->dev_mutex);
 
-	return 0;
+	return ret;
 }
 
 static int lan78xx_reset_resume(struct usb_interface *intf)
 {
 	struct lan78xx_net *dev = usb_get_intfdata(intf);
+	int ret;
 
-	lan78xx_reset(dev);
+	netif_dbg(dev, ifup, dev->net, "(reset) resuming device");
+
+	ret = lan78xx_reset(dev);
+	if (ret < 0)
+		return ret;
 
 	phy_start(dev->net->phydev);
 
-	return lan78xx_resume(intf);
+	ret = lan78xx_resume(intf);
+
+	return ret;
 }
 
 static const struct usb_device_id products[] = {
@@ -4176,6 +4634,10 @@
 	/* LAN7801 USB Gigabit Ethernet Device */
 	USB_DEVICE(LAN78XX_USB_VENDOR_ID, LAN7801_USB_PRODUCT_ID),
 	},
+	{
+	/* ATM2-AF USB Gigabit Ethernet Device */
+	USB_DEVICE(AT29M2AF_USB_VENDOR_ID, AT29M2AF_USB_PRODUCT_ID),
+	},
 	{},
 };
 MODULE_DEVICE_TABLE(usb, products);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/usb/mcs7830.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/usb/mcs7830.c
@@ -108,8 +108,16 @@
 
 static int mcs7830_get_reg(struct usbnet *dev, u16 index, u16 size, void *data)
 {
-	return usbnet_read_cmd(dev, MCS7830_RD_BREQ, MCS7830_RD_BMREQ,
-				0x0000, index, data, size);
+	int ret;
+
+	ret = usbnet_read_cmd(dev, MCS7830_RD_BREQ, MCS7830_RD_BMREQ,
+			      0x0000, index, data, size);
+	if (ret < 0)
+		return ret;
+	else if (ret < size)
+		return -ENODATA;
+
+	return ret;
 }
 
 static int mcs7830_set_reg(struct usbnet *dev, u16 index, u16 size, const void *data)
@@ -472,17 +480,19 @@
 static int mcs7830_bind(struct usbnet *dev, struct usb_interface *udev)
 {
 	struct net_device *net = dev->net;
+	u8 addr[ETH_ALEN];
 	int ret;
 	int retry;
 
 	/* Initial startup: Gather MAC address setting from EEPROM */
 	ret = -EINVAL;
 	for (retry = 0; retry < 5 && ret; retry++)
-		ret = mcs7830_hif_get_mac_address(dev, net->dev_addr);
+		ret = mcs7830_hif_get_mac_address(dev, addr);
 	if (ret) {
 		dev_warn(&dev->udev->dev, "Cannot read MAC address\n");
 		goto out;
 	}
+	eth_hw_addr_set(net, addr);
 
 	mcs7830_data_set_multicast(net);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/usb/pegasus.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/usb/pegasus.c
@@ -495,11 +495,11 @@
 		goto goon;
 
 	rx_status = buf[count - 2];
-	if (rx_status & 0x1e) {
+	if (rx_status & 0x1c) {
 		netif_dbg(pegasus, rx_err, net,
 			  "RX packet error %x\n", rx_status);
 		net->stats.rx_errors++;
-		if (rx_status & 0x06)	/* long or runt	*/
+		if (rx_status & 0x04)	/* runt	*/
 			net->stats.rx_length_errors++;
 		if (rx_status & 0x08)
 			net->stats.rx_crc_errors++;
@@ -747,12 +747,16 @@
 	set_registers(pegasus, EthCtrl0, sizeof(tmp), &tmp);
 }
 
-static inline void get_interrupt_interval(pegasus_t *pegasus)
+static inline int get_interrupt_interval(pegasus_t *pegasus)
 {
 	u16 data;
 	u8 interval;
+	int ret;
+
+	ret = read_eprom_word(pegasus, 4, &data);
+	if (ret < 0)
+		return ret;
 
-	read_eprom_word(pegasus, 4, &data);
 	interval = data >> 8;
 	if (pegasus->usb->speed != USB_SPEED_HIGH) {
 		if (interval < 0x80) {
@@ -767,6 +771,8 @@
 		}
 	}
 	pegasus->intr_interval = interval;
+
+	return 0;
 }
 
 static void set_carrier(struct net_device *net)
@@ -1186,7 +1192,9 @@
 				| NETIF_MSG_PROBE | NETIF_MSG_LINK);
 
 	pegasus->features = usb_dev_id[dev_index].private;
-	get_interrupt_interval(pegasus);
+	res = get_interrupt_interval(pegasus);
+	if (res)
+		goto out2;
 	if (reset_mac(pegasus)) {
 		dev_err(&intf->dev, "can't reset MAC\n");
 		res = -EIO;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/usb/plusb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/usb/plusb.c
@@ -57,9 +57,7 @@
 static inline int
 pl_vendor_req(struct usbnet *dev, u8 req, u8 val, u8 index)
 {
-	return usbnet_read_cmd(dev, req,
-				USB_DIR_IN | USB_TYPE_VENDOR |
-				USB_RECIP_DEVICE,
+	return usbnet_write_cmd(dev, req, USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 				val, index, NULL, 0);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/usb/qmi_wwan.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/usb/qmi_wwan.c
@@ -61,7 +61,6 @@
 
 enum qmi_wwan_quirks {
 	QMI_WWAN_QUIRK_DTR = 1 << 0,	/* needs "set DTR" request */
-	QMI_WWAN_QUIRK_QUECTEL_DYNCFG = 1 << 1,	/* check num. endpoints */
 };
 
 struct qmimux_hdr {
@@ -239,6 +238,7 @@
 			break;
 		default:
 			/* not ip - do not know what to do */
+			kfree_skb(skbn);
 			goto skip;
 		}
 
@@ -338,6 +338,9 @@
 		netdev_dbg(net, "mode: raw IP\n");
 	} else if (!net->header_ops) { /* don't bother if already set */
 		ether_setup(net);
+		/* Restoring min/max mtu values set originally by usbnet */
+		net->min_mtu = 0;
+		net->max_mtu = ETH_MAX_MTU;
 		clear_bit(EVENT_NO_IP_ALIGN, &dev->flags);
 		netdev_dbg(net, "mode: Ethernet\n");
 	}
@@ -439,13 +442,6 @@
 		goto err;
 	}
 
-	/* we don't want to modify a running netdev */
-	if (netif_running(dev->net)) {
-		netdev_err(dev->net, "Cannot change a running device\n");
-		ret = -EBUSY;
-		goto err;
-	}
-
 	ret = qmimux_register_device(dev->net, mux_id);
 	if (!ret) {
 		info->flags |= QMI_WWAN_FLAG_MUX;
@@ -475,13 +471,6 @@
 	if (!rtnl_trylock())
 		return restart_syscall();
 
-	/* we don't want to modify a running netdev */
-	if (netif_running(dev->net)) {
-		netdev_err(dev->net, "Cannot change a running device\n");
-		ret = -EBUSY;
-		goto err;
-	}
-
 	del_dev = qmimux_find_dev(dev, mux_id);
 	if (!del_dev) {
 		netdev_err(dev->net, "mux_id not present\n");
@@ -916,16 +905,6 @@
 	.data           = QMI_WWAN_QUIRK_DTR,
 };
 
-static const struct driver_info	qmi_wwan_info_quirk_quectel_dyncfg = {
-	.description	= "WWAN/QMI device",
-	.flags		= FLAG_WWAN | FLAG_SEND_ZLP,
-	.bind		= qmi_wwan_bind,
-	.unbind		= qmi_wwan_unbind,
-	.manage_power	= qmi_wwan_manage_power,
-	.rx_fixup       = qmi_wwan_rx_fixup,
-	.data           = QMI_WWAN_QUIRK_DTR | QMI_WWAN_QUIRK_QUECTEL_DYNCFG,
-};
-
 #define HUAWEI_VENDOR_ID	0x12D1
 
 /* map QMI/wwan function by a fixed interface number */
@@ -946,14 +925,18 @@
 #define QMI_GOBI_DEVICE(vend, prod) \
 	QMI_FIXED_INTF(vend, prod, 0)
 
-/* Quectel does not use fixed interface numbers on at least some of their
- * devices. We need to check the number of endpoints to ensure that we bind to
- * the correct interface.
+/* Many devices have QMI and DIAG functions which are distinguishable
+ * from other vendor specific functions by class, subclass and
+ * protocol all being 0xff. The DIAG function has exactly 2 endpoints
+ * and is silently rejected when probed.
+ *
+ * This makes it possible to match dynamically numbered QMI functions
+ * as seen on e.g. many Quectel modems.
  */
-#define QMI_QUIRK_QUECTEL_DYNCFG(vend, prod) \
+#define QMI_MATCH_FF_FF_FF(vend, prod) \
 	USB_DEVICE_AND_INTERFACE_INFO(vend, prod, USB_CLASS_VENDOR_SPEC, \
 				      USB_SUBCLASS_VENDOR_SPEC, 0xff), \
-	.driver_info = (unsigned long)&qmi_wwan_info_quirk_quectel_dyncfg
+	.driver_info = (unsigned long)&qmi_wwan_info_quirk_dtr
 
 static const struct usb_device_id products[] = {
 	/* 1. CDC ECM like devices match on the control interface */
@@ -1059,9 +1042,13 @@
 		USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0x581d, USB_CLASS_VENDOR_SPEC, 1, 7),
 		.driver_info = (unsigned long)&qmi_wwan_info,
 	},
-	{QMI_QUIRK_QUECTEL_DYNCFG(0x2c7c, 0x0125)},	/* Quectel EC25, EC20 R2.0  Mini PCIe */
-	{QMI_QUIRK_QUECTEL_DYNCFG(0x2c7c, 0x0306)},	/* Quectel EP06/EG06/EM06 */
-	{QMI_QUIRK_QUECTEL_DYNCFG(0x2c7c, 0x0512)},	/* Quectel EG12/EM12 */
+	{QMI_MATCH_FF_FF_FF(0x2c7c, 0x0122)},	/* Quectel RG650V */
+	{QMI_MATCH_FF_FF_FF(0x2c7c, 0x0125)},	/* Quectel EC25, EC20 R2.0  Mini PCIe */
+	{QMI_MATCH_FF_FF_FF(0x2c7c, 0x0306)},	/* Quectel EP06/EG06/EM06 */
+	{QMI_MATCH_FF_FF_FF(0x2c7c, 0x0512)},	/* Quectel EG12/EM12 */
+	{QMI_MATCH_FF_FF_FF(0x2c7c, 0x0620)},	/* Quectel EM160R-GL */
+	{QMI_MATCH_FF_FF_FF(0x2c7c, 0x0800)},	/* Quectel RM500Q-GL */
+	{QMI_MATCH_FF_FF_FF(0x2c7c, 0x0801)},	/* Quectel RM520N */
 
 	/* 3. Combined interface devices matching on interface number */
 	{QMI_FIXED_INTF(0x0408, 0xea42, 4)},	/* Yota / Megafon M100-1 */
@@ -1095,7 +1082,7 @@
 	{QMI_FIXED_INTF(0x05c6, 0x9011, 4)},
 	{QMI_FIXED_INTF(0x05c6, 0x9021, 1)},
 	{QMI_FIXED_INTF(0x05c6, 0x9022, 2)},
-	{QMI_FIXED_INTF(0x05c6, 0x9025, 4)},	/* Alcatel-sbell ASB TL131 TDD LTE  (China Mobile) */
+	{QMI_QUIRK_SET_DTR(0x05c6, 0x9025, 4)},	/* Alcatel-sbell ASB TL131 TDD LTE (China Mobile) */
 	{QMI_FIXED_INTF(0x05c6, 0x9026, 3)},
 	{QMI_FIXED_INTF(0x05c6, 0x902e, 5)},
 	{QMI_FIXED_INTF(0x05c6, 0x9031, 5)},
@@ -1193,7 +1180,9 @@
 	{QMI_FIXED_INTF(0x05c6, 0x9080, 8)},
 	{QMI_FIXED_INTF(0x05c6, 0x9083, 3)},
 	{QMI_FIXED_INTF(0x05c6, 0x9084, 4)},
+	{QMI_QUIRK_SET_DTR(0x05c6, 0x9091, 2)},	/* Compal RXM-G1 */
 	{QMI_FIXED_INTF(0x05c6, 0x90b2, 3)},    /* ublox R410M */
+	{QMI_QUIRK_SET_DTR(0x05c6, 0x90db, 2)},	/* Compal RXM-G1 */
 	{QMI_FIXED_INTF(0x05c6, 0x920d, 0)},
 	{QMI_FIXED_INTF(0x05c6, 0x920d, 5)},
 	{QMI_QUIRK_SET_DTR(0x05c6, 0x9625, 4)},	/* YUGA CLM920-NC5 */
@@ -1213,6 +1202,7 @@
 	{QMI_FIXED_INTF(0x1435, 0xd182, 5)},	/* Wistron NeWeb D18 */
 	{QMI_FIXED_INTF(0x1435, 0xd191, 4)},	/* Wistron NeWeb D19Q1 */
 	{QMI_QUIRK_SET_DTR(0x1508, 0x1001, 4)},	/* Fibocom NL668 series */
+	{QMI_FIXED_INTF(0x1690, 0x7588, 4)},    /* ASKEY WWHC050 */
 	{QMI_FIXED_INTF(0x16d8, 0x6003, 0)},	/* CMOTech 6003 */
 	{QMI_FIXED_INTF(0x16d8, 0x6007, 0)},	/* CMOTech CHE-628S */
 	{QMI_FIXED_INTF(0x16d8, 0x6008, 0)},	/* CMOTech CMU-301 */
@@ -1259,6 +1249,7 @@
 	{QMI_FIXED_INTF(0x19d2, 0x0168, 4)},
 	{QMI_FIXED_INTF(0x19d2, 0x0176, 3)},
 	{QMI_FIXED_INTF(0x19d2, 0x0178, 3)},
+	{QMI_FIXED_INTF(0x19d2, 0x0189, 4)},    /* ZTE MF290 */
 	{QMI_FIXED_INTF(0x19d2, 0x0191, 4)},	/* ZTE EuFi890 */
 	{QMI_FIXED_INTF(0x19d2, 0x0199, 1)},	/* ZTE MF820S */
 	{QMI_FIXED_INTF(0x19d2, 0x0200, 1)},
@@ -1281,6 +1272,7 @@
 	{QMI_FIXED_INTF(0x19d2, 0x1255, 4)},
 	{QMI_FIXED_INTF(0x19d2, 0x1256, 4)},
 	{QMI_FIXED_INTF(0x19d2, 0x1270, 5)},	/* ZTE MF667 */
+	{QMI_FIXED_INTF(0x19d2, 0x1275, 3)},	/* ZTE P685M */
 	{QMI_FIXED_INTF(0x19d2, 0x1401, 2)},
 	{QMI_FIXED_INTF(0x19d2, 0x1402, 2)},	/* ZTE MF60 */
 	{QMI_FIXED_INTF(0x19d2, 0x1424, 2)},
@@ -1295,7 +1287,7 @@
 	{QMI_FIXED_INTF(0x2001, 0x7e3d, 4)},	/* D-Link DWM-222 A2 */
 	{QMI_FIXED_INTF(0x2020, 0x2031, 4)},	/* Olicard 600 */
 	{QMI_FIXED_INTF(0x2020, 0x2033, 4)},	/* BroadMobi BM806U */
-	{QMI_FIXED_INTF(0x2020, 0x2060, 4)},	/* BroadMobi BM818 */
+	{QMI_QUIRK_SET_DTR(0x2020, 0x2060, 4)},	/* BroadMobi BM818 */
 	{QMI_FIXED_INTF(0x0f3d, 0x68a2, 8)},    /* Sierra Wireless MC7700 */
 	{QMI_FIXED_INTF(0x114f, 0x68a2, 8)},    /* Sierra Wireless MC7750 */
 	{QMI_FIXED_INTF(0x1199, 0x68a2, 8)},	/* Sierra Wireless MC7710 in QMI mode */
@@ -1326,15 +1318,31 @@
 	{QMI_FIXED_INTF(0x1bbb, 0x0203, 2)},	/* Alcatel L800MA */
 	{QMI_FIXED_INTF(0x2357, 0x0201, 4)},	/* TP-LINK HSUPA Modem MA180 */
 	{QMI_FIXED_INTF(0x2357, 0x9000, 4)},	/* TP-LINK MA260 */
+	{QMI_QUIRK_SET_DTR(0x1bc7, 0x1031, 3)}, /* Telit LE910C1-EUX */
+	{QMI_QUIRK_SET_DTR(0x1bc7, 0x103a, 0)}, /* Telit LE910C4-WWX */
 	{QMI_QUIRK_SET_DTR(0x1bc7, 0x1040, 2)},	/* Telit LE922A */
 	{QMI_QUIRK_SET_DTR(0x1bc7, 0x1050, 2)},	/* Telit FN980 */
+	{QMI_QUIRK_SET_DTR(0x1bc7, 0x1060, 2)},	/* Telit LN920 */
+	{QMI_QUIRK_SET_DTR(0x1bc7, 0x1070, 2)},	/* Telit FN990 */
+	{QMI_QUIRK_SET_DTR(0x1bc7, 0x1080, 2)}, /* Telit FE990 */
+	{QMI_QUIRK_SET_DTR(0x1bc7, 0x10a0, 0)}, /* Telit FN920C04 */
+	{QMI_QUIRK_SET_DTR(0x1bc7, 0x10a4, 0)}, /* Telit FN920C04 */
+	{QMI_QUIRK_SET_DTR(0x1bc7, 0x10a9, 0)}, /* Telit FN920C04 */
+	{QMI_QUIRK_SET_DTR(0x1bc7, 0x10b0, 0)}, /* Telit FE990B */
+	{QMI_QUIRK_SET_DTR(0x1bc7, 0x10c0, 0)}, /* Telit FE910C04 */
+	{QMI_QUIRK_SET_DTR(0x1bc7, 0x10c4, 0)}, /* Telit FE910C04 */
+	{QMI_QUIRK_SET_DTR(0x1bc7, 0x10c8, 0)}, /* Telit FE910C04 */
+	{QMI_QUIRK_SET_DTR(0x1bc7, 0x10d0, 0)}, /* Telit FN990B */
 	{QMI_FIXED_INTF(0x1bc7, 0x1100, 3)},	/* Telit ME910 */
 	{QMI_FIXED_INTF(0x1bc7, 0x1101, 3)},	/* Telit ME910 dual modem */
 	{QMI_FIXED_INTF(0x1bc7, 0x1200, 5)},	/* Telit LE920 */
 	{QMI_QUIRK_SET_DTR(0x1bc7, 0x1201, 2)},	/* Telit LE920, LE920A4 */
+	{QMI_QUIRK_SET_DTR(0x1bc7, 0x1230, 2)},	/* Telit LE910Cx */
 	{QMI_QUIRK_SET_DTR(0x1bc7, 0x1260, 2)},	/* Telit LE910Cx */
 	{QMI_QUIRK_SET_DTR(0x1bc7, 0x1261, 2)},	/* Telit LE910Cx */
 	{QMI_QUIRK_SET_DTR(0x1bc7, 0x1900, 1)},	/* Telit LN940 series */
+	{QMI_QUIRK_SET_DTR(0x1bc7, 0x3000, 0)},	/* Telit FN912 series */
+	{QMI_QUIRK_SET_DTR(0x1bc7, 0x3001, 0)},	/* Telit FN912 series */
 	{QMI_FIXED_INTF(0x1c9e, 0x9801, 3)},	/* Telewell TW-3G HSPA+ */
 	{QMI_FIXED_INTF(0x1c9e, 0x9803, 4)},	/* Telewell TW-3G HSPA+ */
 	{QMI_FIXED_INTF(0x1c9e, 0x9b01, 3)},	/* XS Stick W100-2 from 4G Systems */
@@ -1346,12 +1354,14 @@
 	{QMI_FIXED_INTF(0x0b3c, 0xc00a, 6)},	/* Olivetti Olicard 160 */
 	{QMI_FIXED_INTF(0x0b3c, 0xc00b, 4)},	/* Olivetti Olicard 500 */
 	{QMI_FIXED_INTF(0x1e2d, 0x0060, 4)},	/* Cinterion PLxx */
+	{QMI_QUIRK_SET_DTR(0x1e2d, 0x006f, 8)}, /* Cinterion PLS83/PLS63 */
 	{QMI_FIXED_INTF(0x1e2d, 0x0053, 4)},	/* Cinterion PHxx,PXxx */
 	{QMI_FIXED_INTF(0x1e2d, 0x0063, 10)},	/* Cinterion ALASxx (1 RmNet) */
 	{QMI_FIXED_INTF(0x1e2d, 0x0082, 4)},	/* Cinterion PHxx,PXxx (2 RmNet) */
 	{QMI_FIXED_INTF(0x1e2d, 0x0082, 5)},	/* Cinterion PHxx,PXxx (2 RmNet) */
 	{QMI_FIXED_INTF(0x1e2d, 0x0083, 4)},	/* Cinterion PHxx,PXxx (1 RmNet + USB Audio)*/
 	{QMI_QUIRK_SET_DTR(0x1e2d, 0x00b0, 4)},	/* Cinterion CLS8 */
+	{QMI_FIXED_INTF(0x1e2d, 0x00b7, 0)},	/* Cinterion MV31 RmNet */
 	{QMI_FIXED_INTF(0x413c, 0x81a2, 8)},	/* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card */
 	{QMI_FIXED_INTF(0x413c, 0x81a3, 8)},	/* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card */
 	{QMI_FIXED_INTF(0x413c, 0x81a4, 8)},	/* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */
@@ -1361,18 +1371,30 @@
 	{QMI_FIXED_INTF(0x413c, 0x81b3, 8)},	/* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card (rev3) */
 	{QMI_FIXED_INTF(0x413c, 0x81b6, 8)},	/* Dell Wireless 5811e */
 	{QMI_FIXED_INTF(0x413c, 0x81b6, 10)},	/* Dell Wireless 5811e */
+	{QMI_FIXED_INTF(0x413c, 0x81c2, 8)},	/* Dell Wireless 5811e */
+	{QMI_FIXED_INTF(0x413c, 0x81cc, 8)},	/* Dell Wireless 5816e */
 	{QMI_FIXED_INTF(0x413c, 0x81d7, 0)},	/* Dell Wireless 5821e */
+	{QMI_FIXED_INTF(0x413c, 0x81d7, 1)},	/* Dell Wireless 5821e preproduction config */
 	{QMI_FIXED_INTF(0x413c, 0x81e0, 0)},	/* Dell Wireless 5821e with eSIM support*/
+	{QMI_FIXED_INTF(0x413c, 0x81e4, 0)},	/* Dell Wireless 5829e with eSIM support*/
+	{QMI_FIXED_INTF(0x413c, 0x81e6, 0)},	/* Dell Wireless 5829e */
 	{QMI_FIXED_INTF(0x03f0, 0x4e1d, 8)},	/* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */
 	{QMI_FIXED_INTF(0x03f0, 0x9d1d, 1)},	/* HP lt4120 Snapdragon X5 LTE */
 	{QMI_FIXED_INTF(0x22de, 0x9061, 3)},	/* WeTelecom WPD-600N */
 	{QMI_QUIRK_SET_DTR(0x1e0e, 0x9001, 5)},	/* SIMCom 7100E, 7230E, 7600E ++ */
 	{QMI_QUIRK_SET_DTR(0x2c7c, 0x0121, 4)},	/* Quectel EC21 Mini PCIe */
 	{QMI_QUIRK_SET_DTR(0x2c7c, 0x0191, 4)},	/* Quectel EG91 */
+	{QMI_QUIRK_SET_DTR(0x2c7c, 0x0195, 4)},	/* Quectel EG95 */
 	{QMI_FIXED_INTF(0x2c7c, 0x0296, 4)},	/* Quectel BG96 */
+	{QMI_QUIRK_SET_DTR(0x2c7c, 0x030e, 4)},	/* Quectel EM05GV2 */
 	{QMI_QUIRK_SET_DTR(0x2cb7, 0x0104, 4)},	/* Fibocom NL678 series */
+	{QMI_QUIRK_SET_DTR(0x2cb7, 0x0112, 0)},	/* Fibocom FG132 */
 	{QMI_FIXED_INTF(0x0489, 0xe0b4, 0)},	/* Foxconn T77W968 LTE */
 	{QMI_FIXED_INTF(0x0489, 0xe0b5, 0)},	/* Foxconn T77W968 LTE with eSIM support*/
+	{QMI_FIXED_INTF(0x2692, 0x9025, 4)},    /* Cellient MPL200 (rebranded Qualcomm 05c6:9025) */
+	{QMI_QUIRK_SET_DTR(0x1546, 0x1342, 4)},	/* u-blox LARA-L6 */
+	{QMI_QUIRK_SET_DTR(0x33f8, 0x0104, 4)}, /* Rolling RW101 RMNET */
+	{QMI_FIXED_INTF(0x2dee, 0x4d22, 5)},    /* MeiG Smart SRM825L */
 
 	/* 4. Gobi 1000 devices */
 	{QMI_GOBI1K_DEVICE(0x05c6, 0x9212)},	/* Acer Gobi Modem Device */
@@ -1453,7 +1475,6 @@
 {
 	struct usb_device_id *id = (struct usb_device_id *)prod;
 	struct usb_interface_descriptor *desc = &intf->cur_altsetting->desc;
-	const struct driver_info *info;
 
 	/* Workaround to enable dynamic IDs.  This disables usbnet
 	 * blacklisting functionality.  Which, if required, can be
@@ -1489,12 +1510,8 @@
 	 * different. Ignore the current interface if the number of endpoints
 	 * equals the number for the diag interface (two).
 	 */
-	info = (void *)id->driver_info;
-
-	if (info->data & QMI_WWAN_QUIRK_QUECTEL_DYNCFG) {
-		if (desc->bNumEndpoints == 2)
-			return -ENODEV;
-	}
+	if (desc->bNumEndpoints == 2)
+		return -ENODEV;
 
 	return usbnet_probe(intf, id);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/usb/r8152.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/usb/r8152.c
@@ -29,7 +29,7 @@
 #define NETNEXT_VERSION		"10"
 
 /* Information for net */
-#define NET_VERSION		"10"
+#define NET_VERSION		"11"
 
 #define DRIVER_VERSION		"v1." NETNEXT_VERSION "." NET_VERSION
 #define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd@realtek.com>"
@@ -63,6 +63,7 @@
 #define PLA_LED_FEATURE		0xdd92
 #define PLA_PHYAR		0xde00
 #define PLA_BOOT_CTRL		0xe004
+#define PLA_LWAKE_CTRL_REG	0xe007
 #define PLA_GPHY_INTR_IMR	0xe022
 #define PLA_EEE_CR		0xe040
 #define PLA_EEEP_CR		0xe080
@@ -90,6 +91,7 @@
 #define PLA_TALLYCNT		0xe890
 #define PLA_SFF_STS_7		0xe8de
 #define PLA_PHYSTATUS		0xe908
+#define PLA_CONFIG6		0xe90a /* CONFIG6 */
 #define PLA_BP_BA		0xfc26
 #define PLA_BP_0		0xfc28
 #define PLA_BP_1		0xfc2a
@@ -102,6 +104,7 @@
 #define PLA_BP_EN		0xfc38
 
 #define USB_USB2PHY		0xb41e
+#define USB_SSPHYLINK1		0xb426
 #define USB_SSPHYLINK2		0xb428
 #define USB_U2P3_CTRL		0xb460
 #define USB_CSR_DUMMY1		0xb464
@@ -286,6 +289,9 @@
 #define LINK_ON_WAKE_EN		0x0010
 #define LINK_OFF_WAKE_EN	0x0008
 
+/* PLA_CONFIG6 */
+#define LANWAKE_CLR_EN		BIT(0)
+
 /* PLA_CONFIG5 */
 #define BWF_EN			0x0040
 #define MWF_EN			0x0020
@@ -298,6 +304,7 @@
 /* PLA_PHY_PWR */
 #define TX_10M_IDLE_EN		0x0080
 #define PFM_PWM_SWITCH		0x0040
+#define TEST_IO_OFF		BIT(4)
 
 /* PLA_MAC_PWR_CTRL */
 #define D3_CLK_GATED_EN		0x00004000
@@ -310,6 +317,7 @@
 #define MAC_CLK_SPDWN_EN	BIT(15)
 
 /* PLA_MAC_PWR_CTRL3 */
+#define PLA_MCU_SPDWN_EN	BIT(14)
 #define PKT_AVAIL_SPDWN_EN	0x0100
 #define SUSPEND_SPDWN_EN	0x0004
 #define U1U2_SPDWN_EN		0x0002
@@ -340,6 +348,9 @@
 /* PLA_BOOT_CTRL */
 #define AUTOLOAD_DONE		0x0002
 
+/* PLA_LWAKE_CTRL_REG */
+#define LANWAKE_PIN		BIT(7)
+
 /* PLA_SUSPEND_FLAG */
 #define LINK_CHG_EVENT		BIT(0)
 
@@ -353,6 +364,9 @@
 #define USB2PHY_SUSPEND		0x0001
 #define USB2PHY_L1		0x0002
 
+/* USB_SSPHYLINK1 */
+#define DELAY_PHY_PWR_CHG	BIT(1)
+
 /* USB_SSPHYLINK2 */
 #define pwd_dn_scale_mask	0x3ffe
 #define pwd_dn_scale(x)		((x) << 1)
@@ -622,6 +636,7 @@
 	SCHEDULE_TASKLET,
 	GREEN_ETHERNET,
 	DELL_TB_RX_AGG_BUG,
+	LENOVO_MACPASSTHRU,
 };
 
 /* Define these values to match your device */
@@ -836,7 +851,7 @@
 
 	ret = usb_control_msg(tp->udev, usb_rcvctrlpipe(tp->udev, 0),
 			      RTL8152_REQ_GET_REGS, RTL8152_REQT_READ,
-			      value, index, tmp, size, 500);
+			      value, index, tmp, size, USB_CTRL_GET_TIMEOUT);
 	if (ret < 0)
 		memset(data, 0xff, size);
 	else
@@ -859,7 +874,7 @@
 
 	ret = usb_control_msg(tp->udev, usb_sndctrlpipe(tp->udev, 0),
 			      RTL8152_REQ_SET_REGS, RTL8152_REQT_WRITE,
-			      value, index, tmp, size, 500);
+			      value, index, tmp, size, USB_CTRL_SET_TIMEOUT);
 
 	kfree(tmp);
 
@@ -1222,38 +1237,52 @@
 	int ret = -EINVAL;
 	u32 ocp_data;
 	unsigned char buf[6];
-
-	/* test for -AD variant of RTL8153 */
-	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0);
-	if ((ocp_data & AD_MASK) == 0x1000) {
-		/* test for MAC address pass-through bit */
-		ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, EFUSE);
-		if ((ocp_data & PASS_THRU_MASK) != 1) {
-			netif_dbg(tp, probe, tp->netdev,
-				  "No efuse for RTL8153-AD MAC pass through\n");
-			return -ENODEV;
-		}
+	char *mac_obj_name;
+	acpi_object_type mac_obj_type;
+	int mac_strlen;
+
+	if (test_bit(LENOVO_MACPASSTHRU, &tp->flags)) {
+		mac_obj_name = "\\MACA";
+		mac_obj_type = ACPI_TYPE_STRING;
+		mac_strlen = 0x16;
 	} else {
-		/* test for RTL8153-BND and RTL8153-BD */
-		ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_MISC_1);
-		if ((ocp_data & BND_MASK) == 0 && (ocp_data & BD_MASK) == 0) {
-			netif_dbg(tp, probe, tp->netdev,
-				  "Invalid variant for MAC pass through\n");
-			return -ENODEV;
+		/* test for -AD variant of RTL8153 */
+		ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0);
+		if ((ocp_data & AD_MASK) == 0x1000) {
+			/* test for MAC address pass-through bit */
+			ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, EFUSE);
+			if ((ocp_data & PASS_THRU_MASK) != 1) {
+				netif_dbg(tp, probe, tp->netdev,
+						"No efuse for RTL8153-AD MAC pass through\n");
+				return -ENODEV;
+			}
+		} else {
+			/* test for RTL8153-BND and RTL8153-BD */
+			ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_MISC_1);
+			if ((ocp_data & BND_MASK) == 0 && (ocp_data & BD_MASK) == 0) {
+				netif_dbg(tp, probe, tp->netdev,
+						"Invalid variant for MAC pass through\n");
+				return -ENODEV;
+			}
 		}
+
+		mac_obj_name = "\\_SB.AMAC";
+		mac_obj_type = ACPI_TYPE_BUFFER;
+		mac_strlen = 0x17;
 	}
 
 	/* returns _AUXMAC_#AABBCCDDEEFF# */
-	status = acpi_evaluate_object(NULL, "\\_SB.AMAC", NULL, &buffer);
+	status = acpi_evaluate_object(NULL, mac_obj_name, NULL, &buffer);
 	obj = (union acpi_object *)buffer.pointer;
 	if (!ACPI_SUCCESS(status))
 		return -ENODEV;
-	if (obj->type != ACPI_TYPE_BUFFER || obj->string.length != 0x17) {
+	if (obj->type != mac_obj_type || obj->string.length != mac_strlen) {
 		netif_warn(tp, probe, tp->netdev,
 			   "Invalid buffer for pass-thru MAC addr: (%d, %d)\n",
 			   obj->type, obj->string.length);
 		goto amacout;
 	}
+
 	if (strncmp(obj->string.pointer, "_AUXMAC_#", 9) != 0 ||
 	    strncmp(obj->string.pointer + 0x15, "#", 1) != 0) {
 		netif_warn(tp, probe, tp->netdev,
@@ -1465,7 +1494,9 @@
 			   "Stop submitting intr, status %d\n", status);
 		return;
 	case -EOVERFLOW:
-		netif_info(tp, intr, tp->netdev, "intr status -EOVERFLOW\n");
+		if (net_ratelimit())
+			netif_info(tp, intr, tp->netdev,
+				   "intr status -EOVERFLOW\n");
 		goto resubmit;
 	/* -EPIPE:  should clear the halt */
 	default:
@@ -2237,6 +2268,9 @@
 	struct r8152 *tp = container_of(napi, struct r8152, napi);
 	int work_done;
 
+	if (!budget)
+		return 0;
+
 	work_done = rx_bottom(tp, budget);
 
 	if (work_done < budget) {
@@ -2822,29 +2856,6 @@
 		device_set_wakeup_enable(&tp->udev->dev, false);
 }
 
-static void r8153_mac_clk_spd(struct r8152 *tp, bool enable)
-{
-	/* MAC clock speed down */
-	if (enable) {
-		ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL,
-			       ALDPS_SPDWN_RATIO);
-		ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2,
-			       EEE_SPDWN_RATIO);
-		ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3,
-			       PKT_AVAIL_SPDWN_EN | SUSPEND_SPDWN_EN |
-			       U1U2_SPDWN_EN | L1_SPDWN_EN);
-		ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4,
-			       PWRSAVE_SPDWN_EN | RXDV_SPDWN_EN | TX10MIDLE_EN |
-			       TP100_SPDWN_EN | TP500_SPDWN_EN | EEE_SPDWN_EN |
-			       TP1000_SPDWN_EN);
-	} else {
-		ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL, 0);
-		ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, 0);
-		ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, 0);
-		ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, 0);
-	}
-}
-
 static void r8153_u1u2en(struct r8152 *tp, bool enable)
 {
 	u8 u1u2[8];
@@ -2992,6 +3003,8 @@
 		}
 
 		msleep(20);
+		if (test_bit(RTL8152_UNPLUG, &tp->flags))
+			break;
 	}
 
 	return data;
@@ -3142,11 +3155,9 @@
 	if (enable) {
 		r8153_u1u2en(tp, false);
 		r8153_u2p3en(tp, false);
-		r8153_mac_clk_spd(tp, true);
 		rtl_runtime_suspend_enable(tp, true);
 	} else {
 		rtl_runtime_suspend_enable(tp, false);
-		r8153_mac_clk_spd(tp, false);
 
 		switch (tp->version) {
 		case RTL_VER_03:
@@ -3175,7 +3186,6 @@
 		r8153b_ups_en(tp, false);
 		r8153_queue_wake(tp, false);
 		rtl_runtime_suspend_enable(tp, false);
-		r8153_u2p3en(tp, true);
 		r8153b_u1u2en(tp, true);
 	}
 }
@@ -3377,11 +3387,23 @@
 	set_bit(PHY_RESET, &tp->flags);
 }
 
-static void r8152b_exit_oob(struct r8152 *tp)
+static void wait_oob_link_list_ready(struct r8152 *tp)
 {
 	u32 ocp_data;
 	int i;
 
+	for (i = 0; i < 1000; i++) {
+		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
+		if (ocp_data & LINK_LIST_READY)
+			break;
+		usleep_range(1000, 2000);
+	}
+}
+
+static void r8152b_exit_oob(struct r8152 *tp)
+{
+	u32 ocp_data;
+
 	ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
 	ocp_data &= ~RCR_ACPT_ALL;
 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
@@ -3399,23 +3421,13 @@
 	ocp_data &= ~MCU_BORW_EN;
 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
 
-	for (i = 0; i < 1000; i++) {
-		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
-		if (ocp_data & LINK_LIST_READY)
-			break;
-		usleep_range(1000, 2000);
-	}
+	wait_oob_link_list_ready(tp);
 
 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7);
 	ocp_data |= RE_INIT_LL;
 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
 
-	for (i = 0; i < 1000; i++) {
-		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
-		if (ocp_data & LINK_LIST_READY)
-			break;
-		usleep_range(1000, 2000);
-	}
+	wait_oob_link_list_ready(tp);
 
 	rtl8152_nic_reset(tp);
 
@@ -3457,7 +3469,6 @@
 static void r8152b_enter_oob(struct r8152 *tp)
 {
 	u32 ocp_data;
-	int i;
 
 	ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
 	ocp_data &= ~NOW_IS_OOB;
@@ -3469,23 +3480,13 @@
 
 	rtl_disable(tp);
 
-	for (i = 0; i < 1000; i++) {
-		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
-		if (ocp_data & LINK_LIST_READY)
-			break;
-		usleep_range(1000, 2000);
-	}
+	wait_oob_link_list_ready(tp);
 
 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7);
 	ocp_data |= RE_INIT_LL;
 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
 
-	for (i = 0; i < 1000; i++) {
-		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
-		if (ocp_data & LINK_LIST_READY)
-			break;
-		usleep_range(1000, 2000);
-	}
+	wait_oob_link_list_ready(tp);
 
 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS);
 
@@ -3703,7 +3704,6 @@
 
 	r8153_aldps_en(tp, true);
 	r8152b_enable_fc(tp);
-	r8153_u2p3en(tp, true);
 
 	set_bit(PHY_RESET, &tp->flags);
 }
@@ -3711,9 +3711,7 @@
 static void r8153_first_init(struct r8152 *tp)
 {
 	u32 ocp_data;
-	int i;
 
-	r8153_mac_clk_spd(tp, false);
 	rxdy_gated_en(tp, true);
 	r8153_teredo_off(tp);
 
@@ -3732,23 +3730,13 @@
 	ocp_data &= ~MCU_BORW_EN;
 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
 
-	for (i = 0; i < 1000; i++) {
-		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
-		if (ocp_data & LINK_LIST_READY)
-			break;
-		usleep_range(1000, 2000);
-	}
+	wait_oob_link_list_ready(tp);
 
 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7);
 	ocp_data |= RE_INIT_LL;
 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
 
-	for (i = 0; i < 1000; i++) {
-		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
-		if (ocp_data & LINK_LIST_READY)
-			break;
-		usleep_range(1000, 2000);
-	}
+	wait_oob_link_list_ready(tp);
 
 	rtl_rx_vlan_en(tp, tp->netdev->features & NETIF_F_HW_VLAN_CTAG_RX);
 
@@ -3773,9 +3761,6 @@
 static void r8153_enter_oob(struct r8152 *tp)
 {
 	u32 ocp_data;
-	int i;
-
-	r8153_mac_clk_spd(tp, true);
 
 	ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
 	ocp_data &= ~NOW_IS_OOB;
@@ -3784,23 +3769,13 @@
 	rtl_disable(tp);
 	rtl_reset_bmu(tp);
 
-	for (i = 0; i < 1000; i++) {
-		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
-		if (ocp_data & LINK_LIST_READY)
-			break;
-		usleep_range(1000, 2000);
-	}
+	wait_oob_link_list_ready(tp);
 
 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7);
 	ocp_data |= RE_INIT_LL;
 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
 
-	for (i = 0; i < 1000; i++) {
-		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
-		if (ocp_data & LINK_LIST_READY)
-			break;
-		usleep_range(1000, 2000);
-	}
+	wait_oob_link_list_ready(tp);
 
 	ocp_data = tp->netdev->mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;
 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, ocp_data);
@@ -4004,6 +3979,8 @@
 
 static void rtl8153_up(struct r8152 *tp)
 {
+	u32 ocp_data;
+
 	if (test_bit(RTL8152_UNPLUG, &tp->flags))
 		return;
 
@@ -4011,6 +3988,19 @@
 	r8153_u2p3en(tp, false);
 	r8153_aldps_en(tp, false);
 	r8153_first_init(tp);
+
+	ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CONFIG6);
+	ocp_data |= LANWAKE_CLR_EN;
+	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CONFIG6, ocp_data);
+
+	ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_LWAKE_CTRL_REG);
+	ocp_data &= ~LANWAKE_PIN;
+	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_LWAKE_CTRL_REG, ocp_data);
+
+	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_SSPHYLINK1);
+	ocp_data &= ~DELAY_PHY_PWR_CHG;
+	ocp_write_word(tp, MCU_TYPE_USB, USB_SSPHYLINK1, ocp_data);
+
 	r8153_aldps_en(tp, true);
 
 	switch (tp->version) {
@@ -4029,11 +4019,17 @@
 
 static void rtl8153_down(struct r8152 *tp)
 {
+	u32 ocp_data;
+
 	if (test_bit(RTL8152_UNPLUG, &tp->flags)) {
 		rtl_drop_queued_tx(tp);
 		return;
 	}
 
+	ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CONFIG6);
+	ocp_data &= ~LANWAKE_CLR_EN;
+	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CONFIG6, ocp_data);
+
 	r8153_u1u2en(tp, false);
 	r8153_u2p3en(tp, false);
 	r8153_power_cut_en(tp, false);
@@ -4044,6 +4040,8 @@
 
 static void rtl8153b_up(struct r8152 *tp)
 {
+	u32 ocp_data;
+
 	if (test_bit(RTL8152_UNPLUG, &tp->flags))
 		return;
 
@@ -4054,18 +4052,27 @@
 	r8153_first_init(tp);
 	ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_BUF_TH, RX_THR_B);
 
+	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3);
+	ocp_data &= ~PLA_MCU_SPDWN_EN;
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, ocp_data);
+
 	r8153_aldps_en(tp, true);
-	r8153_u2p3en(tp, true);
 	r8153b_u1u2en(tp, true);
 }
 
 static void rtl8153b_down(struct r8152 *tp)
 {
+	u32 ocp_data;
+
 	if (test_bit(RTL8152_UNPLUG, &tp->flags)) {
 		rtl_drop_queued_tx(tp);
 		return;
 	}
 
+	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3);
+	ocp_data |= PLA_MCU_SPDWN_EN;
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, ocp_data);
+
 	r8153b_u1u2en(tp, false);
 	r8153_u2p3en(tp, false);
 	r8153b_power_cut_en(tp, false);
@@ -4299,9 +4306,10 @@
 		tp->rtl_ops.down(tp);
 
 		mutex_unlock(&tp->control);
+	}
 
+	if (!res)
 		usb_autopm_put_interface(tp->intf);
-	}
 
 	free_all_mem(tp);
 
@@ -4375,7 +4383,10 @@
 		if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) &
 		    AUTOLOAD_DONE)
 			break;
+
 		msleep(20);
+		if (test_bit(RTL8152_UNPLUG, &tp->flags))
+			break;
 	}
 
 	data = r8153_phy_status(tp, 0);
@@ -4449,11 +4460,24 @@
 
 	ocp_write_word(tp, MCU_TYPE_USB, USB_CONNECT_TIMER, 0x0001);
 
+	/* MAC clock speed down */
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL, 0);
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, 0);
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, 0);
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, 0);
+
 	r8153_power_cut_en(tp, false);
 	r8153_u1u2en(tp, true);
-	r8153_mac_clk_spd(tp, false);
 	usb_enable_lpm(tp->udev);
 
+	ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CONFIG6);
+	ocp_data |= LANWAKE_CLR_EN;
+	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CONFIG6, ocp_data);
+
+	ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_LWAKE_CTRL_REG);
+	ocp_data &= ~LANWAKE_PIN;
+	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_LWAKE_CTRL_REG, ocp_data);
+
 	/* rx aggregation */
 	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL);
 	ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN);
@@ -4493,7 +4517,10 @@
 		if (ocp_read_word(tp, MCU_TYPE_PLA, PLA_BOOT_CTRL) &
 		    AUTOLOAD_DONE)
 			break;
+
 		msleep(20);
+		if (test_bit(RTL8152_UNPLUG, &tp->flags))
+			break;
 	}
 
 	data = r8153_phy_status(tp, 0);
@@ -4526,6 +4553,19 @@
 	ocp_data |= MAC_CLK_SPDWN_EN;
 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, ocp_data);
 
+	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3);
+	ocp_data &= ~PLA_MCU_SPDWN_EN;
+	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, ocp_data);
+
+	if (tp->version == RTL_VER_09) {
+		/* Disable Test IO for 32QFN */
+		if (ocp_read_byte(tp, MCU_TYPE_PLA, 0xdc00) & BIT(5)) {
+			ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR);
+			ocp_data |= TEST_IO_OFF;
+			ocp_write_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR, ocp_data);
+		}
+	}
+
 	set_bit(GREEN_ETHERNET, &tp->flags);
 
 	/* rx aggregation */
@@ -5015,7 +5055,7 @@
 {
 	switch (stringset) {
 	case ETH_SS_STATS:
-		memcpy(data, *rtl8152_gstrings, sizeof(rtl8152_gstrings));
+		memcpy(data, rtl8152_gstrings, sizeof(rtl8152_gstrings));
 		break;
 	}
 }
@@ -5479,7 +5519,10 @@
 		ops->in_nway		= rtl8153_in_nway;
 		ops->hw_phy_cfg		= r8153_hw_phy_cfg;
 		ops->autosuspend_en	= rtl8153_runtime_enable;
-		tp->rx_buf_sz		= 32 * 1024;
+		if (tp->udev->speed < USB_SPEED_SUPER)
+			tp->rx_buf_sz	= 16 * 1024;
+		else
+			tp->rx_buf_sz	= 32 * 1024;
 		tp->eee_en		= true;
 		tp->eee_adv		= MDIO_EEE_1000T | MDIO_EEE_100TX;
 		break;
@@ -5525,7 +5568,8 @@
 
 	ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
 			      RTL8152_REQ_GET_REGS, RTL8152_REQT_READ,
-			      PLA_TCR0, MCU_TYPE_PLA, tmp, sizeof(*tmp), 500);
+			      PLA_TCR0, MCU_TYPE_PLA, tmp, sizeof(*tmp),
+			      USB_CTRL_GET_TIMEOUT);
 	if (ret > 0)
 		ocp_data = (__le32_to_cpu(*tmp) >> 16) & VERSION_MASK;
 
@@ -5587,6 +5631,9 @@
 		return -ENODEV;
 	}
 
+	if (intf->cur_altsetting->desc.bNumEndpoints < 3)
+		return -ENODEV;
+
 	usb_reset_device(udev);
 	netdev = alloc_etherdev(sizeof(struct r8152));
 	if (!netdev) {
@@ -5644,6 +5691,10 @@
 		netdev->hw_features &= ~NETIF_F_RXCSUM;
 	}
 
+	if (le16_to_cpu(udev->descriptor.idVendor) == VENDOR_ID_LENOVO &&
+	    le16_to_cpu(udev->descriptor.idProduct) == 0x3082)
+		set_bit(LENOVO_MACPASSTHRU, &tp->flags);
+
 	if (le16_to_cpu(udev->descriptor.bcdDevice) == 0x3011 && udev->serial &&
 	    (!strcmp(udev->serial, "000001000000") || !strcmp(udev->serial, "000002000000"))) {
 		dev_info(&udev->dev, "Dell TB16 Dock, disable RX aggregation");
@@ -5687,6 +5738,11 @@
 
 	intf->needs_remote_wakeup = 1;
 
+	if (!rtl_can_wakeup(tp))
+		__rtl_set_wol(tp, 0);
+	else
+		tp->saved_wolopts = __rtl_get_wol(tp);
+
 	tp->rtl_ops.init(tp);
 	queue_delayed_work(system_long_wq, &tp->hw_phy_work, 0);
 	set_ethernet_addr(tp);
@@ -5700,10 +5756,6 @@
 		goto out1;
 	}
 
-	if (!rtl_can_wakeup(tp))
-		__rtl_set_wol(tp, 0);
-
-	tp->saved_wolopts = __rtl_get_wol(tp);
 	if (tp->saved_wolopts)
 		device_set_wakeup_enable(&udev->dev, true);
 	else
@@ -5715,6 +5767,9 @@
 
 out1:
 	tasklet_kill(&tp->tx_tl);
+	cancel_delayed_work_sync(&tp->hw_phy_work);
+	if (tp->rtl_ops.unload)
+		tp->rtl_ops.unload(tp);
 	usb_set_intfdata(intf, NULL);
 out:
 	free_netdev(netdev);
@@ -5760,13 +5815,17 @@
 	{REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8153)},
 	{REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07ab)},
 	{REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07c6)},
+	{REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x0927)},
 	{REALTEK_USB_DEVICE(VENDOR_ID_SAMSUNG, 0xa101)},
 	{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x304f)},
+	{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x3054)},
 	{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x3062)},
 	{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x3069)},
+	{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x3082)},
 	{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x7205)},
 	{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x720c)},
 	{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x7214)},
+	{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x721e)},
 	{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0xa387)},
 	{REALTEK_USB_DEVICE(VENDOR_ID_LINKSYS, 0x0041)},
 	{REALTEK_USB_DEVICE(VENDOR_ID_NVIDIA,  0x09ff)},
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/usb/rndis_host.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/usb/rndis_host.c
@@ -201,7 +201,7 @@
 			dev_dbg(&info->control->dev,
 				"rndis response error, code %d\n", retval);
 		}
-		msleep(20);
+		msleep(40);
 	}
 	dev_dbg(&info->control->dev, "rndis response timeout\n");
 	return -ETIMEDOUT;
@@ -255,7 +255,8 @@
 
 	off = le32_to_cpu(u.get_c->offset);
 	len = le32_to_cpu(u.get_c->len);
-	if (unlikely((8 + off + len) > CONTROL_BUFFER_SIZE))
+	if (unlikely((off > CONTROL_BUFFER_SIZE - 8) ||
+		     (len > CONTROL_BUFFER_SIZE - 8 - off)))
 		goto response_error;
 
 	if (*reply_len != -1 && len != *reply_len)
@@ -387,7 +388,7 @@
 	reply_len = sizeof *phym;
 	retval = rndis_query(dev, intf, u.buf,
 			     RNDIS_OID_GEN_PHYSICAL_MEDIUM,
-			     0, (void **) &phym, &reply_len);
+			     reply_len, (void **)&phym, &reply_len);
 	if (retval != 0 || !phym) {
 		/* OID is optional so don't fail here. */
 		phym_unspec = cpu_to_le32(RNDIS_PHYSICAL_MEDIUM_UNSPECIFIED);
@@ -609,6 +610,11 @@
 				      USB_CLASS_COMM, 2 /* ACM */, 0x0ff),
 	.driver_info = (unsigned long) &rndis_poll_status_info,
 }, {
+	/* Hytera Communications DMR radios' "Radio to PC Network" */
+	USB_VENDOR_AND_INTERFACE_INFO(0x238b,
+				      USB_CLASS_COMM, 2 /* ACM */, 0x0ff),
+	.driver_info = (unsigned long)&rndis_info,
+}, {
 	/* RNDIS is MSFT's un-official variant of CDC ACM */
 	USB_INTERFACE_INFO(USB_CLASS_COMM, 2 /* ACM */, 0x0ff),
 	.driver_info = (unsigned long) &rndis_info,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/usb/rtl8150.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/usb/rtl8150.c
@@ -71,6 +71,14 @@
 #define MSR_SPEED		(1<<3)
 #define MSR_LINK		(1<<2)
 
+/* USB endpoints */
+enum rtl8150_usb_ep {
+	RTL8150_USB_EP_CONTROL = 0,
+	RTL8150_USB_EP_BULK_IN = 1,
+	RTL8150_USB_EP_BULK_OUT = 2,
+	RTL8150_USB_EP_INT_IN = 3,
+};
+
 /* Interrupt pipe data */
 #define INT_TSR			0x00
 #define INT_RSR			0x01
@@ -274,12 +282,20 @@
 		return 1;
 }
 
-static inline void set_ethernet_addr(rtl8150_t * dev)
+static void set_ethernet_addr(rtl8150_t *dev)
 {
-	u8 node_id[6];
+	u8 node_id[ETH_ALEN];
+	int ret;
+
+	ret = get_registers(dev, IDR, sizeof(node_id), node_id);
 
-	get_registers(dev, IDR, sizeof(node_id), node_id);
-	memcpy(dev->netdev->dev_addr, node_id, sizeof(node_id));
+	if (ret == sizeof(node_id)) {
+		ether_addr_copy(dev->netdev->dev_addr, node_id);
+	} else {
+		eth_hw_addr_random(dev->netdev);
+		netdev_notice(dev->netdev, "Assigned a random MAC address: %pM\n",
+			      dev->netdev->dev_addr);
+	}
 }
 
 static int rtl8150_set_mac_address(struct net_device *netdev, void *p)
@@ -589,9 +605,9 @@
 		dev_kfree_skb(dev->rx_skb_pool[i]);
 }
 
-static void rx_fixup(unsigned long data)
+static void rx_fixup(struct tasklet_struct *t)
 {
-	struct rtl8150 *dev = (struct rtl8150 *)data;
+	struct rtl8150 *dev = from_tasklet(dev, t, tl);
 	struct sk_buff *skb;
 	int status;
 
@@ -790,7 +806,8 @@
 				      struct ethtool_link_ksettings *ecmd)
 {
 	rtl8150_t *dev = netdev_priv(netdev);
-	short lpa, bmcr;
+	short lpa = 0;
+	short bmcr = 0;
 	u32 supported;
 
 	supported = (SUPPORTED_10baseT_Half |
@@ -877,6 +894,13 @@
 	struct usb_device *udev = interface_to_usbdev(intf);
 	rtl8150_t *dev;
 	struct net_device *netdev;
+	static const u8 bulk_ep_addr[] = {
+		RTL8150_USB_EP_BULK_IN | USB_DIR_IN,
+		RTL8150_USB_EP_BULK_OUT | USB_DIR_OUT,
+		0};
+	static const u8 int_ep_addr[] = {
+		RTL8150_USB_EP_INT_IN | USB_DIR_IN,
+		0};
 
 	netdev = alloc_etherdev(sizeof(rtl8150_t));
 	if (!netdev)
@@ -890,7 +914,14 @@
 		return -ENOMEM;
 	}
 
-	tasklet_init(&dev->tl, rx_fixup, (unsigned long)dev);
+	/* Verify that all required endpoints are present */
+	if (!usb_check_bulk_endpoints(intf, bulk_ep_addr) ||
+	    !usb_check_int_endpoints(intf, int_ep_addr)) {
+		dev_err(&intf->dev, "couldn't find required endpoints\n");
+		goto out;
+	}
+
+	tasklet_setup(&dev->tl, rx_fixup);
 	spin_lock_init(&dev->rx_pool_lock);
 
 	dev->udev = udev;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/usb/sierra_net.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/usb/sierra_net.c
@@ -674,6 +674,7 @@
 		0x00, 0x00, SIERRA_NET_HIP_MSYNC_ID, 0x00};
 	static const u8 shdwn_tmplate[sizeof(priv->shdwn_msg)] = {
 		0x00, 0x00, SIERRA_NET_HIP_SHUTD_ID, 0x00};
+	u8 mod[2];
 
 	dev_dbg(&dev->udev->dev, "%s", __func__);
 
@@ -703,8 +704,9 @@
 	dev->net->netdev_ops = &sierra_net_device_ops;
 
 	/* change MAC addr to include, ifacenum, and to be unique */
-	dev->net->dev_addr[ETH_ALEN-2] = atomic_inc_return(&iface_counter);
-	dev->net->dev_addr[ETH_ALEN-1] = ifacenum;
+	mod[0] = atomic_inc_return(&iface_counter);
+	mod[1] = ifacenum;
+	dev_addr_mod(dev->net, ETH_ALEN - 2, mod, 2);
 
 	/* prepare shutdown message template */
 	memcpy(priv->shdwn_msg, shdwn_tmplate, sizeof(priv->shdwn_msg));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/usb/smsc75xx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/usb/smsc75xx.c
@@ -90,7 +90,9 @@
 	ret = fn(dev, USB_VENDOR_REQUEST_READ_REGISTER, USB_DIR_IN
 		 | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 		 0, index, &buf, 4);
-	if (unlikely(ret < 0)) {
+	if (unlikely(ret < 4)) {
+		ret = ret < 0 ? ret : -ENODATA;
+
 		netdev_warn(dev->net, "Failed to read reg index 0x%08x: %d\n",
 			    index, ret);
 		return ret;
@@ -1482,7 +1484,7 @@
 	ret = smsc75xx_wait_ready(dev, 0);
 	if (ret < 0) {
 		netdev_warn(dev->net, "device not ready in smsc75xx_bind\n");
-		return ret;
+		goto free_pdata;
 	}
 
 	smsc75xx_init_mac_address(dev);
@@ -1491,7 +1493,7 @@
 	ret = smsc75xx_reset(dev);
 	if (ret < 0) {
 		netdev_warn(dev->net, "smsc75xx_reset error %d\n", ret);
-		return ret;
+		goto cancel_work;
 	}
 
 	dev->net->netdev_ops = &smsc75xx_netdev_ops;
@@ -1501,6 +1503,13 @@
 	dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
 	dev->net->max_mtu = MAX_SINGLE_PACKET_SIZE;
 	return 0;
+
+cancel_work:
+	cancel_work_sync(&pdata->set_multicast);
+free_pdata:
+	kfree(pdata);
+	dev->data[0] = 0;
+	return ret;
 }
 
 static void smsc75xx_unbind(struct usbnet *dev, struct usb_interface *intf)
@@ -1510,7 +1519,6 @@
 		cancel_work_sync(&pdata->set_multicast);
 		netif_dbg(dev, ifdown, dev->net, "free pdata\n");
 		kfree(pdata);
-		pdata = NULL;
 		dev->data[0] = 0;
 	}
 }
@@ -2192,6 +2200,13 @@
 		size = (rx_cmd_a & RX_CMD_A_LEN) - RXW_PADDING;
 		align_count = (4 - ((size + RXW_PADDING) % 4)) % 4;
 
+		if (unlikely(size > skb->len)) {
+			netif_dbg(dev, rx_err, dev->net,
+				  "size err rx_cmd_a=0x%08x\n",
+				  rx_cmd_a);
+			return 0;
+		}
+
 		if (unlikely(rx_cmd_a & RX_CMD_A_RED)) {
 			netif_dbg(dev, rx_err, dev->net,
 				  "Error rx_cmd_a=0x%08x\n", rx_cmd_a);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/usb/smsc95xx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/usb/smsc95xx.c
@@ -261,16 +261,18 @@
 	mutex_unlock(&dev->phy_mutex);
 }
 
-static int smsc95xx_mdio_read_nopm(struct net_device *netdev, int phy_id,
-				   int idx)
+static int smsc95xx_mdio_read_nopm(struct usbnet *dev, int idx)
 {
-	return __smsc95xx_mdio_read(netdev, phy_id, idx, 1);
+	struct mii_if_info *mii = &dev->mii;
+
+	return __smsc95xx_mdio_read(dev->net, mii->phy_id, idx, 1);
 }
 
-static void smsc95xx_mdio_write_nopm(struct net_device *netdev, int phy_id,
-				     int idx, int regval)
+static void smsc95xx_mdio_write_nopm(struct usbnet *dev, int idx, int regval)
 {
-	__smsc95xx_mdio_write(netdev, phy_id, idx, regval, 1);
+	struct mii_if_info *mii = &dev->mii;
+
+	__smsc95xx_mdio_write(dev->net, mii->phy_id, idx, regval, 1);
 }
 
 static int smsc95xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
@@ -455,7 +457,7 @@
 static void smsc95xx_set_multicast(struct net_device *netdev)
 {
 	struct usbnet *dev = netdev_priv(netdev);
-	struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+	struct smsc95xx_priv *pdata = dev->driver_priv;
 	unsigned long flags;
 	int ret;
 
@@ -550,7 +552,7 @@
 
 static int smsc95xx_link_reset(struct usbnet *dev)
 {
-	struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+	struct smsc95xx_priv *pdata = dev->driver_priv;
 	struct mii_if_info *mii = &dev->mii;
 	struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET };
 	unsigned long flags;
@@ -618,7 +620,7 @@
 
 static void set_carrier(struct usbnet *dev, bool link)
 {
-	struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+	struct smsc95xx_priv *pdata = dev->driver_priv;
 
 	if (pdata->link_ok == link)
 		return;
@@ -747,7 +749,7 @@
 				     struct ethtool_wolinfo *wolinfo)
 {
 	struct usbnet *dev = netdev_priv(net);
-	struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+	struct smsc95xx_priv *pdata = dev->driver_priv;
 
 	wolinfo->supported = SUPPORTED_WAKE;
 	wolinfo->wolopts = pdata->wolopts;
@@ -757,7 +759,7 @@
 				    struct ethtool_wolinfo *wolinfo)
 {
 	struct usbnet *dev = netdev_priv(net);
-	struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+	struct smsc95xx_priv *pdata = dev->driver_priv;
 	int ret;
 
 	if (wolinfo->wolopts & ~SUPPORTED_WAKE)
@@ -796,7 +798,7 @@
 static void set_mdix_status(struct net_device *net, __u8 mdix_ctrl)
 {
 	struct usbnet *dev = netdev_priv(net);
-	struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+	struct smsc95xx_priv *pdata = dev->driver_priv;
 	int buf;
 
 	if ((pdata->chip_id == ID_REV_CHIP_ID_9500A_) ||
@@ -845,7 +847,7 @@
 				       struct ethtool_link_ksettings *cmd)
 {
 	struct usbnet *dev = netdev_priv(net);
-	struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+	struct smsc95xx_priv *pdata = dev->driver_priv;
 	int retval;
 
 	retval = usbnet_get_link_ksettings(net, cmd);
@@ -860,7 +862,7 @@
 				       const struct ethtool_link_ksettings *cmd)
 {
 	struct usbnet *dev = netdev_priv(net);
-	struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+	struct smsc95xx_priv *pdata = dev->driver_priv;
 	int retval;
 
 	if (pdata->mdix_ctrl != cmd->base.eth_tp_mdix_ctrl)
@@ -942,7 +944,7 @@
 /* starts the TX path */
 static int smsc95xx_start_tx_path(struct usbnet *dev)
 {
-	struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+	struct smsc95xx_priv *pdata = dev->driver_priv;
 	unsigned long flags;
 	int ret;
 
@@ -962,7 +964,7 @@
 /* Starts the Receive path */
 static int smsc95xx_start_rx_path(struct usbnet *dev, int in_pm)
 {
-	struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+	struct smsc95xx_priv *pdata = dev->driver_priv;
 	unsigned long flags;
 
 	spin_lock_irqsave(&pdata->mac_cr_lock, flags);
@@ -1019,8 +1021,8 @@
 
 static int smsc95xx_reset(struct usbnet *dev)
 {
-	struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
-	u32 read_buf, write_buf, burst_cap;
+	struct smsc95xx_priv *pdata = dev->driver_priv;
+	u32 read_buf, burst_cap;
 	int ret = 0, timeout;
 
 	netif_dbg(dev, ifup, dev->net, "entering smsc95xx_reset\n");
@@ -1040,7 +1042,7 @@
 
 	if (timeout >= 100) {
 		netdev_warn(dev->net, "timeout waiting for completion of Lite Reset\n");
-		return ret;
+		return -ETIMEDOUT;
 	}
 
 	ret = smsc95xx_write_reg(dev, PM_CTRL, PM_CTL_PHY_RST_);
@@ -1162,10 +1164,13 @@
 		return ret;
 	netif_dbg(dev, ifup, dev->net, "ID_REV = 0x%08x\n", read_buf);
 
+	ret = smsc95xx_read_reg(dev, LED_GPIO_CFG, &read_buf);
+	if (ret < 0)
+		return ret;
 	/* Configure GPIO pins as LED outputs */
-	write_buf = LED_GPIO_CFG_SPD_LED | LED_GPIO_CFG_LNK_LED |
-		LED_GPIO_CFG_FDX_LED;
-	ret = smsc95xx_write_reg(dev, LED_GPIO_CFG, write_buf);
+	read_buf |= LED_GPIO_CFG_SPD_LED | LED_GPIO_CFG_LNK_LED |
+		    LED_GPIO_CFG_FDX_LED;
+	ret = smsc95xx_write_reg(dev, LED_GPIO_CFG, read_buf);
 	if (ret < 0)
 		return ret;
 
@@ -1247,7 +1252,7 @@
 
 static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
 {
-	struct smsc95xx_priv *pdata = NULL;
+	struct smsc95xx_priv *pdata;
 	u32 val;
 	int ret;
 
@@ -1259,13 +1264,12 @@
 		return ret;
 	}
 
-	dev->data[0] = (unsigned long)kzalloc(sizeof(struct smsc95xx_priv),
-					      GFP_KERNEL);
-
-	pdata = (struct smsc95xx_priv *)(dev->data[0]);
+	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
 	if (!pdata)
 		return -ENOMEM;
 
+	dev->driver_priv = pdata;
+
 	spin_lock_init(&pdata->mac_cr_lock);
 
 	/* LAN95xx devices do not alter the computed checksum of 0 to 0xffff.
@@ -1287,11 +1291,14 @@
 
 	/* Init all registers */
 	ret = smsc95xx_reset(dev);
+	if (ret)
+		goto free_pdata;
 
 	/* detect device revision as different features may be available */
 	ret = smsc95xx_read_reg(dev, ID_REV, &val);
 	if (ret < 0)
-		return ret;
+		goto free_pdata;
+
 	val >>= 16;
 	pdata->chip_id = val;
 	pdata->mdix_ctrl = get_mdix_status(dev->net);
@@ -1317,19 +1324,19 @@
 	schedule_delayed_work(&pdata->carrier_check, CARRIER_CHECK_DELAY);
 
 	return 0;
+
+free_pdata:
+	kfree(pdata);
+	return ret;
 }
 
 static void smsc95xx_unbind(struct usbnet *dev, struct usb_interface *intf)
 {
-	struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+	struct smsc95xx_priv *pdata = dev->driver_priv;
 
-	if (pdata) {
-		cancel_delayed_work(&pdata->carrier_check);
-		netif_dbg(dev, ifdown, dev->net, "free pdata\n");
-		kfree(pdata);
-		pdata = NULL;
-		dev->data[0] = 0;
-	}
+	cancel_delayed_work_sync(&pdata->carrier_check);
+	netif_dbg(dev, ifdown, dev->net, "free pdata\n");
+	kfree(pdata);
 }
 
 static u32 smsc_crc(const u8 *buffer, size_t len, int filter)
@@ -1340,39 +1347,37 @@
 
 static int smsc95xx_enable_phy_wakeup_interrupts(struct usbnet *dev, u16 mask)
 {
-	struct mii_if_info *mii = &dev->mii;
 	int ret;
 
 	netdev_dbg(dev->net, "enabling PHY wakeup interrupts\n");
 
 	/* read to clear */
-	ret = smsc95xx_mdio_read_nopm(dev->net, mii->phy_id, PHY_INT_SRC);
+	ret = smsc95xx_mdio_read_nopm(dev, PHY_INT_SRC);
 	if (ret < 0)
 		return ret;
 
 	/* enable interrupt source */
-	ret = smsc95xx_mdio_read_nopm(dev->net, mii->phy_id, PHY_INT_MASK);
+	ret = smsc95xx_mdio_read_nopm(dev, PHY_INT_MASK);
 	if (ret < 0)
 		return ret;
 
 	ret |= mask;
 
-	smsc95xx_mdio_write_nopm(dev->net, mii->phy_id, PHY_INT_MASK, ret);
+	smsc95xx_mdio_write_nopm(dev, PHY_INT_MASK, ret);
 
 	return 0;
 }
 
 static int smsc95xx_link_ok_nopm(struct usbnet *dev)
 {
-	struct mii_if_info *mii = &dev->mii;
 	int ret;
 
 	/* first, a dummy read, needed to latch some MII phys */
-	ret = smsc95xx_mdio_read_nopm(dev->net, mii->phy_id, MII_BMSR);
+	ret = smsc95xx_mdio_read_nopm(dev, MII_BMSR);
 	if (ret < 0)
 		return ret;
 
-	ret = smsc95xx_mdio_read_nopm(dev->net, mii->phy_id, MII_BMSR);
+	ret = smsc95xx_mdio_read_nopm(dev, MII_BMSR);
 	if (ret < 0)
 		return ret;
 
@@ -1381,7 +1386,7 @@
 
 static int smsc95xx_enter_suspend0(struct usbnet *dev)
 {
-	struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+	struct smsc95xx_priv *pdata = dev->driver_priv;
 	u32 val;
 	int ret;
 
@@ -1420,8 +1425,7 @@
 
 static int smsc95xx_enter_suspend1(struct usbnet *dev)
 {
-	struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
-	struct mii_if_info *mii = &dev->mii;
+	struct smsc95xx_priv *pdata = dev->driver_priv;
 	u32 val;
 	int ret;
 
@@ -1429,17 +1433,17 @@
 	 * compatibility with non-standard link partners
 	 */
 	if (pdata->features & FEATURE_PHY_NLP_CROSSOVER)
-		smsc95xx_mdio_write_nopm(dev->net, mii->phy_id,	PHY_EDPD_CONFIG,
-			PHY_EDPD_CONFIG_DEFAULT);
+		smsc95xx_mdio_write_nopm(dev, PHY_EDPD_CONFIG,
+					 PHY_EDPD_CONFIG_DEFAULT);
 
 	/* enable energy detect power-down mode */
-	ret = smsc95xx_mdio_read_nopm(dev->net, mii->phy_id, PHY_MODE_CTRL_STS);
+	ret = smsc95xx_mdio_read_nopm(dev, PHY_MODE_CTRL_STS);
 	if (ret < 0)
 		return ret;
 
 	ret |= MODE_CTRL_STS_EDPWRDOWN_;
 
-	smsc95xx_mdio_write_nopm(dev->net, mii->phy_id, PHY_MODE_CTRL_STS, ret);
+	smsc95xx_mdio_write_nopm(dev, PHY_MODE_CTRL_STS, ret);
 
 	/* enter SUSPEND1 mode */
 	ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
@@ -1468,7 +1472,7 @@
 
 static int smsc95xx_enter_suspend2(struct usbnet *dev)
 {
-	struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+	struct smsc95xx_priv *pdata = dev->driver_priv;
 	u32 val;
 	int ret;
 
@@ -1490,7 +1494,7 @@
 
 static int smsc95xx_enter_suspend3(struct usbnet *dev)
 {
-	struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+	struct smsc95xx_priv *pdata = dev->driver_priv;
 	u32 val;
 	int ret;
 
@@ -1529,7 +1533,7 @@
 
 static int smsc95xx_autosuspend(struct usbnet *dev, u32 link_up)
 {
-	struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+	struct smsc95xx_priv *pdata = dev->driver_priv;
 	int ret;
 
 	if (!netif_running(dev->net)) {
@@ -1577,7 +1581,7 @@
 static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message)
 {
 	struct usbnet *dev = usb_get_intfdata(intf);
-	struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+	struct smsc95xx_priv *pdata = dev->driver_priv;
 	u32 val, link_up;
 	int ret;
 
@@ -1848,7 +1852,7 @@
 	u32 val;
 
 	BUG_ON(!dev);
-	pdata = (struct smsc95xx_priv *)(dev->data[0]);
+	pdata = dev->driver_priv;
 	suspend_flags = pdata->suspend_flags;
 
 	netdev_dbg(dev->net, "resume suspend_flags=0x%02x\n", suspend_flags);
@@ -1903,9 +1907,11 @@
 
 static void smsc95xx_rx_csum_offload(struct sk_buff *skb)
 {
-	skb->csum = *(u16 *)(skb_tail_pointer(skb) - 2);
+	u16 *csum_ptr = (u16 *)(skb_tail_pointer(skb) - 2);
+
+	skb->csum = (__force __wsum)get_unaligned(csum_ptr);
 	skb->ip_summed = CHECKSUM_COMPLETE;
-	skb_trim(skb, skb->len - 2);
+	skb_trim(skb, skb->len - 2); /* remove csum */
 }
 
 static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
@@ -1928,6 +1934,12 @@
 		size = (u16)((header & RX_STS_FL_) >> 16);
 		align_count = (4 - ((size + NET_IP_ALIGN) % 4)) % 4;
 
+		if (unlikely(size > skb->len)) {
+			netif_dbg(dev, rx_err, dev->net,
+				  "size err header=0x%08x\n", header);
+			return 0;
+		}
+
 		if (unlikely(header & RX_STS_ES_)) {
 			netif_dbg(dev, rx_err, dev->net,
 				  "Error header=0x%08x\n", header);
@@ -1957,25 +1969,22 @@
 				if (dev->net->features & NETIF_F_RXCSUM)
 					smsc95xx_rx_csum_offload(skb);
 				skb_trim(skb, skb->len - 4); /* remove fcs */
-				skb->truesize = size + sizeof(struct sk_buff);
 
 				return 1;
 			}
 
-			ax_skb = skb_clone(skb, GFP_ATOMIC);
+			ax_skb = netdev_alloc_skb_ip_align(dev->net, size);
 			if (unlikely(!ax_skb)) {
 				netdev_warn(dev->net, "Error allocating skb\n");
 				return 0;
 			}
 
-			ax_skb->len = size;
-			ax_skb->data = packet;
-			skb_set_tail_pointer(ax_skb, size);
+			skb_put(ax_skb, size);
+			memcpy(ax_skb->data, packet, size);
 
 			if (dev->net->features & NETIF_F_RXCSUM)
 				smsc95xx_rx_csum_offload(ax_skb);
 			skb_trim(ax_skb, ax_skb->len - 4); /* remove fcs */
-			ax_skb->truesize = size + sizeof(struct sk_buff);
 
 			usbnet_skb_return(dev, ax_skb);
 		}
@@ -2068,7 +2077,7 @@
 
 static int smsc95xx_manage_power(struct usbnet *dev, int on)
 {
-	struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+	struct smsc95xx_priv *pdata = dev->driver_priv;
 
 	dev->intf->needs_remote_wakeup = on;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/usb/sr9700.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/usb/sr9700.c
@@ -178,6 +178,7 @@
 	struct usbnet *dev = netdev_priv(netdev);
 	__le16 res;
 	int rc = 0;
+	int err;
 
 	if (phy_id) {
 		netdev_dbg(netdev, "Only internal phy supported\n");
@@ -188,11 +189,17 @@
 	if (loc == MII_BMSR) {
 		u8 value;
 
-		sr_read_reg(dev, SR_NSR, &value);
+		err = sr_read_reg(dev, SR_NSR, &value);
+		if (err < 0)
+			return err;
+
 		if (value & NSR_LINKST)
 			rc = 1;
 	}
-	sr_share_read_word(dev, 1, loc, &res);
+	err = sr_share_read_word(dev, 1, loc, &res);
+	if (err < 0)
+		return err;
+
 	if (rc == 1)
 		res = le16_to_cpu(res) | BMSR_LSTATUS;
 	else
@@ -319,6 +326,7 @@
 {
 	struct net_device *netdev;
 	struct mii_if_info *mii;
+	u8 addr[ETH_ALEN];
 	int ret;
 
 	ret = usbnet_get_endpoints(dev, intf);
@@ -349,11 +357,12 @@
 	 * EEPROM automatically to PAR. In case there is no EEPROM externally,
 	 * a default MAC address is stored in PAR for making chip work properly.
 	 */
-	if (sr_read(dev, SR_PAR, ETH_ALEN, netdev->dev_addr) < 0) {
+	if (sr_read(dev, SR_PAR, ETH_ALEN, addr) < 0) {
 		netdev_err(netdev, "Error reading MAC address\n");
 		ret = -ENODEV;
 		goto out;
 	}
+	eth_hw_addr_set(netdev, addr);
 
 	/* power up and reset phy */
 	sr_write_reg(dev, SR_PRR, PRR_PHY_RST);
@@ -410,7 +419,7 @@
 		/* ignore the CRC length */
 		len = (skb->data[1] | (skb->data[2] << 8)) - 4;
 
-		if (len > ETH_FRAME_LEN)
+		if (len > ETH_FRAME_LEN || len > skb->len || len < 0)
 			return 0;
 
 		/* the last packet of current skb */
@@ -418,19 +427,15 @@
 			skb_pull(skb, 3);
 			skb->len = len;
 			skb_set_tail_pointer(skb, len);
-			skb->truesize = len + sizeof(struct sk_buff);
 			return 2;
 		}
 
-		/* skb_clone is used for address align */
-		sr_skb = skb_clone(skb, GFP_ATOMIC);
+		sr_skb = netdev_alloc_skb_ip_align(dev->net, len);
 		if (!sr_skb)
 			return 0;
 
-		sr_skb->len = len;
-		sr_skb->data = skb->data + 3;
-		skb_set_tail_pointer(sr_skb, len);
-		sr_skb->truesize = len + sizeof(struct sk_buff);
+		skb_put(sr_skb, len);
+		memcpy(sr_skb->data, skb->data + 3, len);
 		usbnet_skb_return(dev, sr_skb);
 
 		skb_pull(skb, len + SR_RX_OVERHEAD);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/usb/sr9800.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/usb/sr9800.c
@@ -731,12 +731,15 @@
 	struct sr_data *data = (struct sr_data *)&dev->data;
 	u16 led01_mux, led23_mux;
 	int ret, embd_phy;
+	u8 addr[ETH_ALEN];
 	u32 phyid;
 	u16 rx_ctl;
 
 	data->eeprom_len = SR9800_EEPROM_LEN;
 
-	usbnet_get_endpoints(dev, intf);
+	ret = usbnet_get_endpoints(dev, intf);
+	if (ret)
+		goto out;
 
 	/* LED Setting Rule :
 	 * AABB:CCDD
@@ -754,12 +757,12 @@
 	}
 
 	/* Get the MAC address */
-	ret = sr_read_cmd(dev, SR_CMD_READ_NODE_ID, 0, 0, ETH_ALEN,
-			  dev->net->dev_addr);
+	ret = sr_read_cmd(dev, SR_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, addr);
 	if (ret < 0) {
 		netdev_dbg(dev->net, "Failed to read MAC address: %d\n", ret);
 		return ret;
 	}
+	eth_hw_addr_set(dev->net, addr);
 	netdev_dbg(dev->net, "mac addr : %pM\n", dev->net->dev_addr);
 
 	/* Initialize MII structure */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/usb/usbnet.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/usb/usbnet.c
@@ -67,9 +67,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-// randomly generated ethernet address
-static u8	node_id [ETH_ALEN];
-
 /* use ethtool to change the level for any given device */
 static int msg_level = -1;
 module_param (msg_level, int, 0);
@@ -151,12 +148,13 @@
 
 int usbnet_get_ethernet_addr(struct usbnet *dev, int iMACAddress)
 {
+	u8		addr[ETH_ALEN];
 	int 		tmp = -1, ret;
 	unsigned char	buf [13];
 
 	ret = usb_string(dev->udev, iMACAddress, buf, sizeof buf);
 	if (ret == 12)
-		tmp = hex2bin(dev->net->dev_addr, buf, 6);
+		tmp = hex2bin(addr, buf, 6);
 	if (tmp < 0) {
 		dev_dbg(&dev->udev->dev,
 			"bad MAC string %d fetch, %d\n", iMACAddress, tmp);
@@ -164,10 +162,22 @@
 			ret = -EINVAL;
 		return ret;
 	}
+	eth_hw_addr_set(dev->net, addr);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(usbnet_get_ethernet_addr);
 
+static bool usbnet_needs_usb_name_format(struct usbnet *dev, struct net_device *net)
+{
+	/* Point to point devices which don't have a real MAC address
+	 * (or report a fake local one) have historically used the usb%d
+	 * naming. Preserve this..
+	 */
+	return (dev->driver_info->flags & FLAG_POINTTOPOINT) != 0 &&
+		(is_zero_ether_addr(net->dev_addr) ||
+		 is_local_ether_addr(net->dev_addr));
+}
+
 static void intr_complete (struct urb *urb)
 {
 	struct usbnet	*dev = urb->context;
@@ -833,13 +843,11 @@
 
 	mpn = !test_and_clear_bit(EVENT_NO_RUNTIME_PM, &dev->flags);
 
-	/* deferred work (task, timer, softirq) must also stop.
-	 * can't flush_scheduled_work() until we drop rtnl (later),
-	 * else workers could deadlock; so make workers a NOP.
-	 */
+	/* deferred work (timer, softirq, task) must also stop */
 	dev->flags = 0;
 	del_timer_sync (&dev->delay);
 	tasklet_kill (&dev->bh);
+	cancel_work_sync(&dev->kevent);
 	if (!pm)
 		usb_autopm_put_interface(dev->intf);
 
@@ -1587,6 +1595,7 @@
 	struct usbnet		*dev;
 	struct usb_device	*xdev;
 	struct net_device	*net;
+	struct urb		*urb;
 
 	dev = usb_get_intfdata(intf);
 	usb_set_intfdata(intf, NULL);
@@ -1603,9 +1612,11 @@
 	net = dev->net;
 	unregister_netdev (net);
 
-	cancel_work_sync(&dev->kevent);
-
-	usb_scuttle_anchored_urbs(&dev->deferred);
+	while ((urb = usb_get_from_anchor(&dev->deferred))) {
+		dev_kfree_skb(urb->context);
+		kfree(urb->sg);
+		usb_free_urb(urb);
+	}
 
 	if (dev->driver_info->unbind)
 		dev->driver_info->unbind (dev, intf);
@@ -1710,8 +1721,7 @@
 	dev->interrupt_count = 0;
 
 	dev->net = net;
-	strcpy (net->name, "usb%d");
-	memcpy (net->dev_addr, node_id, sizeof node_id);
+	strscpy(net->name, "usb%d", sizeof(net->name));
 
 	/* rx and tx sides can use different message sizes;
 	 * bind() should set rx_urb_size in that case.
@@ -1731,19 +1741,18 @@
 		if (status < 0)
 			goto out1;
 
-		// heuristic:  "usb%d" for links we know are two-host,
-		// else "eth%d" when there's reasonable doubt.  userspace
-		// can rename the link if it knows better.
+		/* heuristic: rename to "eth%d" if we are not sure this link
+		 * is two-host (these links keep "usb%d")
+		 */
 		if ((dev->driver_info->flags & FLAG_ETHER) != 0 &&
-		    ((dev->driver_info->flags & FLAG_POINTTOPOINT) == 0 ||
-		     (net->dev_addr [0] & 0x02) == 0))
-			strcpy (net->name, "eth%d");
+		    !usbnet_needs_usb_name_format(dev, net))
+			strscpy(net->name, "eth%d", sizeof(net->name));
 		/* WLAN devices should always be named "wlan%d" */
 		if ((dev->driver_info->flags & FLAG_WLAN) != 0)
-			strcpy(net->name, "wlan%d");
+			strscpy(net->name, "wlan%d", sizeof(net->name));
 		/* WWAN devices should always be named "wwan%d" */
 		if ((dev->driver_info->flags & FLAG_WWAN) != 0)
-			strcpy(net->name, "wwan%d");
+			strscpy(net->name, "wwan%d", sizeof(net->name));
 
 		/* devices that cannot do ARP */
 		if ((dev->driver_info->flags & FLAG_NOARP) != 0)
@@ -1755,6 +1764,10 @@
 	} else if (!info->in || !info->out)
 		status = usbnet_get_endpoints (dev, udev);
 	else {
+		u8 ep_addrs[3] = {
+			info->in + USB_DIR_IN, info->out + USB_DIR_OUT, 0
+		};
+
 		dev->in = usb_rcvbulkpipe (xdev, info->in);
 		dev->out = usb_sndbulkpipe (xdev, info->out);
 		if (!(info->flags & FLAG_NO_SETINT))
@@ -1764,6 +1777,8 @@
 		else
 			status = 0;
 
+		if (status == 0 && !usb_check_bulk_endpoints(udev, ep_addrs))
+			status = -EINVAL;
 	}
 	if (status >= 0 && dev->status)
 		status = init_status (dev, udev);
@@ -1773,10 +1788,15 @@
 	if (!dev->rx_urb_size)
 		dev->rx_urb_size = dev->hard_mtu;
 	dev->maxpacket = usb_maxpacket (dev->udev, dev->out, 1);
+	if (dev->maxpacket == 0) {
+		/* that is a broken device */
+		status = -ENODEV;
+		goto out4;
+	}
 
-	/* let userspace know we have a random address */
-	if (ether_addr_equal(net->dev_addr, node_id))
-		net->addr_assign_type = NET_ADDR_RANDOM;
+	/* this flags the device for user space */
+	if (!is_valid_ether_addr(net->dev_addr))
+		eth_hw_addr_random(net);
 
 	if ((dev->driver_info->flags & FLAG_WLAN) != 0)
 		SET_NETDEV_DEVTYPE(net, &wlan_type);
@@ -1982,7 +2002,7 @@
 		   cmd, reqtype, value, index, size);
 
 	if (size) {
-		buf = kmalloc(size, GFP_KERNEL);
+		buf = kmalloc(size, GFP_NOIO);
 		if (!buf)
 			goto out;
 	}
@@ -2014,7 +2034,7 @@
 		   cmd, reqtype, value, index, size);
 
 	if (data) {
-		buf = kmemdup(data, size, GFP_KERNEL);
+		buf = kmemdup(data, size, GFP_NOIO);
 		if (!buf)
 			goto out;
 	} else {
@@ -2115,7 +2135,7 @@
 int usbnet_write_cmd_async(struct usbnet *dev, u8 cmd, u8 reqtype,
 			   u16 value, u16 index, const void *data, u16 size)
 {
-	struct usb_ctrlrequest *req = NULL;
+	struct usb_ctrlrequest *req;
 	struct urb *urb;
 	int err = -ENOMEM;
 	void *buf = NULL;
@@ -2133,7 +2153,7 @@
 		if (!buf) {
 			netdev_err(dev->net, "Error allocating buffer"
 				   " in %s!\n", __func__);
-			goto fail_free;
+			goto fail_free_urb;
 		}
 	}
 
@@ -2157,14 +2177,21 @@
 	if (err < 0) {
 		netdev_err(dev->net, "Error submitting the control"
 			   " message: status=%d\n", err);
-		goto fail_free;
+		goto fail_free_all;
 	}
 	return 0;
 
+fail_free_all:
+	kfree(req);
 fail_free_buf:
 	kfree(buf);
-fail_free:
-	kfree(req);
+	/*
+	 * avoid a double free
+	 * needed because the flag can be set only
+	 * after filling the URB
+	 */
+	urb->transfer_flags = 0;
+fail_free_urb:
 	usb_free_urb(urb);
 fail:
 	return err;
@@ -2179,7 +2206,6 @@
 	BUILD_BUG_ON(
 		FIELD_SIZEOF(struct sk_buff, cb) < sizeof(struct skb_data));
 
-	eth_random_addr(node_id);
 	return 0;
 }
 module_init(usbnet_init);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/usb/zaurus.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/usb/zaurus.c
@@ -256,6 +256,11 @@
 	.bInterfaceSubClass	= USB_CDC_SUBCLASS_ETHERNET, \
 	.bInterfaceProtocol	= USB_CDC_PROTO_NONE
 
+#define ZAURUS_FAKE_INTERFACE \
+	.bInterfaceClass	= USB_CLASS_COMM, \
+	.bInterfaceSubClass	= USB_CDC_SUBCLASS_MDLM, \
+	.bInterfaceProtocol	= USB_CDC_PROTO_NONE
+
 /* SA-1100 based Sharp Zaurus ("collie"), or compatible. */
 {
 	.match_flags	=   USB_DEVICE_ID_MATCH_INT_INFO
@@ -284,11 +289,25 @@
 	.match_flags	=   USB_DEVICE_ID_MATCH_INT_INFO
 			  | USB_DEVICE_ID_MATCH_DEVICE,
 	.idVendor		= 0x04DD,
+	.idProduct		= 0x8005,	/* A-300 */
+	ZAURUS_FAKE_INTERFACE,
+	.driver_info = (unsigned long)&bogus_mdlm_info,
+}, {
+	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
+			  | USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor		= 0x04DD,
 	.idProduct		= 0x8006,	/* B-500/SL-5600 */
 	ZAURUS_MASTER_INTERFACE,
 	.driver_info = ZAURUS_PXA_INFO,
 }, {
 	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
+			  | USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor		= 0x04DD,
+	.idProduct		= 0x8006,	/* B-500/SL-5600 */
+	ZAURUS_FAKE_INTERFACE,
+	.driver_info = (unsigned long)&bogus_mdlm_info,
+}, {
+	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
 	          | USB_DEVICE_ID_MATCH_DEVICE,
 	.idVendor		= 0x04DD,
 	.idProduct		= 0x8007,	/* C-700 */
@@ -296,6 +315,13 @@
 	.driver_info = ZAURUS_PXA_INFO,
 }, {
 	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
+			  | USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor		= 0x04DD,
+	.idProduct		= 0x8007,	/* C-700 */
+	ZAURUS_FAKE_INTERFACE,
+	.driver_info = (unsigned long)&bogus_mdlm_info,
+}, {
+	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
 		 | USB_DEVICE_ID_MATCH_DEVICE,
 	.idVendor               = 0x04DD,
 	.idProduct              = 0x9031,	/* C-750 C-760 */
@@ -315,6 +341,13 @@
 	.driver_info = ZAURUS_PXA_INFO,
 }, {
 	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
+			    | USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor		= 0x04DD,
+	.idProduct		= 0x9032,	/* SL-6000 */
+	ZAURUS_FAKE_INTERFACE,
+	.driver_info = (unsigned long)&bogus_mdlm_info,
+}, {
+	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
 		 | USB_DEVICE_ID_MATCH_DEVICE,
 	.idVendor               = 0x04DD,
 	/* reported with some C860 units */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/veth.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/veth.c
@@ -209,9 +209,10 @@
 {
 	/* Write ptr_ring before reading rx_notify_masked */
 	smp_mb();
-	if (!rq->rx_notify_masked) {
-		rq->rx_notify_masked = true;
-		napi_schedule(&rq->xdp_napi);
+	if (!READ_ONCE(rq->rx_notify_masked) &&
+	    napi_schedule_prep(&rq->xdp_napi)) {
+		WRITE_ONCE(rq->rx_notify_masked, true);
+		__napi_schedule(&rq->xdp_napi);
 	}
 }
 
@@ -237,6 +238,7 @@
 {
 	struct veth_priv *rcv_priv, *priv = netdev_priv(dev);
 	struct veth_rq *rq = NULL;
+	int ret = NETDEV_TX_OK;
 	struct net_device *rcv;
 	int length = skb->len;
 	bool rcv_xdp = false;
@@ -244,7 +246,7 @@
 
 	rcu_read_lock();
 	rcv = rcu_dereference(priv->peer);
-	if (unlikely(!rcv)) {
+	if (unlikely(!rcv) || !pskb_may_pull(skb, ETH_HLEN)) {
 		kfree_skb(skb);
 		goto drop;
 	}
@@ -254,8 +256,6 @@
 	if (rxq < rcv->real_num_rx_queues) {
 		rq = &rcv_priv->rq[rxq];
 		rcv_xdp = rcu_access_pointer(rq->xdp_prog);
-		if (rcv_xdp)
-			skb_record_rx_queue(skb, rxq);
 	}
 
 	skb_tx_timestamp(skb);
@@ -271,6 +271,7 @@
 	} else {
 drop:
 		atomic64_inc(&priv->dropped);
+		ret = NET_XMIT_DROP;
 	}
 
 	if (rcv_xdp)
@@ -278,7 +279,7 @@
 
 	rcu_read_unlock();
 
-	return NETDEV_TX_OK;
+	return ret;
 }
 
 static u64 veth_stats_tx(struct pcpu_lstats *result, struct net_device *dev)
@@ -510,13 +511,15 @@
 					struct veth_xdp_tx_bq *bq)
 {
 	void *hard_start = frame->data - frame->headroom;
-	void *head = hard_start - sizeof(struct xdp_frame);
 	int len = frame->len, delta = 0;
 	struct xdp_frame orig_frame;
 	struct bpf_prog *xdp_prog;
 	unsigned int headroom;
 	struct sk_buff *skb;
 
+	/* bpf_xdp_adjust_head() assures BPF cannot access xdp_frame area */
+	hard_start -= sizeof(struct xdp_frame);
+
 	rcu_read_lock();
 	xdp_prog = rcu_dereference(rq->xdp_prog);
 	if (likely(xdp_prog)) {
@@ -538,7 +541,6 @@
 			break;
 		case XDP_TX:
 			orig_frame = *frame;
-			xdp.data_hard_start = head;
 			xdp.rxq->mem = frame->mem;
 			if (unlikely(veth_xdp_tx(rq->dev, &xdp, bq) < 0)) {
 				trace_xdp_exception(rq->dev, xdp_prog, act);
@@ -550,7 +552,6 @@
 			goto xdp_xmit;
 		case XDP_REDIRECT:
 			orig_frame = *frame;
-			xdp.data_hard_start = head;
 			xdp.rxq->mem = frame->mem;
 			if (xdp_do_redirect(rq->dev, &xdp, xdp_prog)) {
 				frame = &orig_frame;
@@ -572,7 +573,7 @@
 	rcu_read_unlock();
 
 	headroom = sizeof(struct xdp_frame) + frame->headroom - delta;
-	skb = veth_build_skb(head, headroom, len, 0);
+	skb = veth_build_skb(hard_start, headroom, len, 0);
 	if (!skb) {
 		xdp_return_frame(frame);
 		goto err;
@@ -782,8 +783,10 @@
 		/* Write rx_notify_masked before reading ptr_ring */
 		smp_store_mb(rq->rx_notify_masked, false);
 		if (unlikely(!__ptr_ring_empty(&rq->xdp_ring))) {
-			rq->rx_notify_masked = true;
-			napi_schedule(&rq->xdp_napi);
+			if (napi_schedule_prep(&rq->xdp_napi)) {
+				WRITE_ONCE(rq->rx_notify_masked, true);
+				__napi_schedule(&rq->xdp_napi);
+			}
 		}
 	}
 
@@ -1254,10 +1257,7 @@
 
 		nla_peer = data[VETH_INFO_PEER];
 		ifmp = nla_data(nla_peer);
-		err = rtnl_nla_parse_ifla(peer_tb,
-					  nla_data(nla_peer) + sizeof(struct ifinfomsg),
-					  nla_len(nla_peer) - sizeof(struct ifinfomsg),
-					  NULL);
+		err = rtnl_nla_parse_ifinfomsg(peer_tb, nla_peer, extack);
 		if (err < 0)
 			return err;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/virtio_net.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/virtio_net.c
@@ -63,6 +63,11 @@
 	VIRTIO_NET_F_GUEST_CSUM
 };
 
+#define GUEST_OFFLOAD_GRO_HW_MASK ((1ULL << VIRTIO_NET_F_GUEST_TSO4) | \
+				(1ULL << VIRTIO_NET_F_GUEST_TSO6) | \
+				(1ULL << VIRTIO_NET_F_GUEST_ECN)  | \
+				(1ULL << VIRTIO_NET_F_GUEST_UFO))
+
 struct virtnet_stat_desc {
 	char desc[ETH_GSTRING_LEN];
 	size_t offset;
@@ -190,6 +195,9 @@
 	/* # of XDP queue pairs currently used by the driver */
 	u16 xdp_queue_pairs;
 
+	/* xdp_queue_pairs may be 0, when xdp is already loaded. So add this. */
+	bool xdp_enabled;
+
 	/* I like... big packets and I cannot lie! */
 	bool big_packets;
 
@@ -205,9 +213,15 @@
 	/* Packet virtio header size */
 	u8 hdr_len;
 
-	/* Work struct for refilling if we run low on memory. */
+	/* Work struct for delayed refilling if we run low on memory. */
 	struct delayed_work refill;
 
+	/* Is delayed refill enabled? */
+	bool refill_enabled;
+
+	/* The lock to synchronize the access to refill_enabled */
+	spinlock_t refill_lock;
+
 	/* Work struct for config space updates */
 	struct work_struct config_work;
 
@@ -311,6 +325,20 @@
 	return p;
 }
 
+static void enable_delayed_refill(struct virtnet_info *vi)
+{
+	spin_lock_bh(&vi->refill_lock);
+	vi->refill_enabled = true;
+	spin_unlock_bh(&vi->refill_lock);
+}
+
+static void disable_delayed_refill(struct virtnet_info *vi)
+{
+	spin_lock_bh(&vi->refill_lock);
+	vi->refill_enabled = false;
+	spin_unlock_bh(&vi->refill_lock);
+}
+
 static void virtqueue_napi_schedule(struct napi_struct *napi,
 				    struct virtqueue *vq)
 {
@@ -371,7 +399,7 @@
 				   struct receive_queue *rq,
 				   struct page *page, unsigned int offset,
 				   unsigned int len, unsigned int truesize,
-				   bool hdr_valid)
+				   bool hdr_valid, unsigned int metasize)
 {
 	struct sk_buff *skb;
 	struct virtio_net_hdr_mrg_rxbuf *hdr;
@@ -393,6 +421,7 @@
 	else
 		hdr_padded_len = sizeof(struct padded_vnet_hdr);
 
+	/* hdr_valid means no XDP, so we can copy the vnet header */
 	if (hdr_valid)
 		memcpy(hdr, p, hdr_len);
 
@@ -400,11 +429,20 @@
 	offset += hdr_padded_len;
 	p += hdr_padded_len;
 
-	copy = len;
-	if (copy > skb_tailroom(skb))
-		copy = skb_tailroom(skb);
+	/* Copy all frame if it fits skb->head, otherwise
+	 * we let virtio_net_hdr_to_skb() and GRO pull headers as needed.
+	 */
+	if (len <= skb_tailroom(skb))
+		copy = len;
+	else
+		copy = ETH_HLEN + metasize;
 	skb_put_data(skb, p, copy);
 
+	if (metasize) {
+		__skb_pull(skb, metasize);
+		skb_metadata_set(skb, metasize);
+	}
+
 	len -= copy;
 	offset += copy;
 
@@ -450,10 +488,6 @@
 	struct virtio_net_hdr_mrg_rxbuf *hdr;
 	int err;
 
-	/* virtqueue want to use data area in-front of packet */
-	if (unlikely(xdpf->metasize > 0))
-		return -EOPNOTSUPP;
-
 	if (unlikely(xdpf->headroom < vi->hdr_len))
 		return -EOVERFLOW;
 
@@ -474,12 +508,41 @@
 	return 0;
 }
 
-static struct send_queue *virtnet_xdp_sq(struct virtnet_info *vi)
-{
-	unsigned int qp;
-
-	qp = vi->curr_queue_pairs - vi->xdp_queue_pairs + smp_processor_id();
-	return &vi->sq[qp];
+/* when vi->curr_queue_pairs > nr_cpu_ids, the txq/sq is only used for xdp tx on
+ * the current cpu, so it does not need to be locked.
+ *
+ * Here we use marco instead of inline functions because we have to deal with
+ * three issues at the same time: 1. the choice of sq. 2. judge and execute the
+ * lock/unlock of txq 3. make sparse happy. It is difficult for two inline
+ * functions to perfectly solve these three problems at the same time.
+ */
+#define virtnet_xdp_get_sq(vi) ({                                       \
+	struct netdev_queue *txq;                                       \
+	typeof(vi) v = (vi);                                            \
+	unsigned int qp;                                                \
+									\
+	if (v->curr_queue_pairs > nr_cpu_ids) {                         \
+		qp = v->curr_queue_pairs - v->xdp_queue_pairs;          \
+		qp += smp_processor_id();                               \
+		txq = netdev_get_tx_queue(v->dev, qp);                  \
+		__netif_tx_acquire(txq);                                \
+	} else {                                                        \
+		qp = smp_processor_id() % v->curr_queue_pairs;          \
+		txq = netdev_get_tx_queue(v->dev, qp);                  \
+		__netif_tx_lock(txq, raw_smp_processor_id());           \
+	}                                                               \
+	v->sq + qp;                                                     \
+})
+
+#define virtnet_xdp_put_sq(vi, q) {                                     \
+	struct netdev_queue *txq;                                       \
+	typeof(vi) v = (vi);                                            \
+									\
+	txq = netdev_get_tx_queue(v->dev, (q) - v->sq);                 \
+	if (v->curr_queue_pairs > nr_cpu_ids)                           \
+		__netif_tx_release(txq);                                \
+	else                                                            \
+		__netif_tx_unlock(txq);                                 \
 }
 
 static int virtnet_xdp_xmit(struct net_device *dev,
@@ -505,7 +568,7 @@
 	if (!xdp_prog)
 		return -ENXIO;
 
-	sq = virtnet_xdp_sq(vi);
+	sq = virtnet_xdp_get_sq(vi);
 
 	if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK)) {
 		ret = -EINVAL;
@@ -553,12 +616,13 @@
 	sq->stats.kicks += kicks;
 	u64_stats_update_end(&sq->stats.syncp);
 
+	virtnet_xdp_put_sq(vi, sq);
 	return ret;
 }
 
 static unsigned int virtnet_get_headroom(struct virtnet_info *vi)
 {
-	return vi->xdp_queue_pairs ? VIRTIO_XDP_HEADROOM : 0;
+	return vi->xdp_enabled ? VIRTIO_XDP_HEADROOM : 0;
 }
 
 /* We copy the packet for XDP in the following cases:
@@ -582,8 +646,13 @@
 				       int page_off,
 				       unsigned int *len)
 {
-	struct page *page = alloc_page(GFP_ATOMIC);
+	int tailroom = SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+	struct page *page;
 
+	if (page_off + *len + tailroom > PAGE_SIZE)
+		return NULL;
+
+	page = alloc_page(GFP_ATOMIC);
 	if (!page)
 		return NULL;
 
@@ -591,7 +660,6 @@
 	page_off += *len;
 
 	while (--*num_buf) {
-		int tailroom = SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
 		unsigned int buflen;
 		void *buf;
 		int off;
@@ -644,6 +712,7 @@
 	unsigned int delta = 0;
 	struct page *xdp_page;
 	int err;
+	unsigned int metasize = 0;
 
 	len -= vi->hdr_len;
 	stats->bytes += len;
@@ -683,8 +752,8 @@
 
 		xdp.data_hard_start = buf + VIRTNET_RX_PAD + vi->hdr_len;
 		xdp.data = xdp.data_hard_start + xdp_headroom;
-		xdp_set_data_meta_invalid(&xdp);
 		xdp.data_end = xdp.data + len;
+		xdp.data_meta = xdp.data;
 		xdp.rxq = &rq->xdp_rxq;
 		orig_data = xdp.data;
 		act = bpf_prog_run_xdp(xdp_prog, &xdp);
@@ -695,6 +764,7 @@
 			/* Recalculate length in case bpf program changed it */
 			delta = orig_data - xdp.data;
 			len = xdp.data_end - xdp.data;
+			metasize = xdp.data - xdp.data_meta;
 			break;
 		case XDP_TX:
 			stats->xdp_tx++;
@@ -740,6 +810,9 @@
 		memcpy(skb_vnet_hdr(skb), buf, vi->hdr_len);
 	} /* keep zeroed vnet hdr since packet was changed by bpf */
 
+	if (metasize)
+		skb_metadata_set(skb, metasize);
+
 err:
 	return skb;
 
@@ -760,8 +833,8 @@
 				   struct virtnet_rq_stats *stats)
 {
 	struct page *page = buf;
-	struct sk_buff *skb = page_to_skb(vi, rq, page, 0, len,
-					  PAGE_SIZE, true);
+	struct sk_buff *skb =
+		page_to_skb(vi, rq, page, 0, len, PAGE_SIZE, true, 0);
 
 	stats->bytes += len - vi->hdr_len;
 	if (unlikely(!skb))
@@ -793,6 +866,7 @@
 	unsigned int truesize;
 	unsigned int headroom = mergeable_ctx_to_headroom(ctx);
 	int err;
+	unsigned int metasize = 0;
 
 	head_skb = NULL;
 	stats->bytes += len - vi->hdr_len;
@@ -839,8 +913,8 @@
 		data = page_address(xdp_page) + offset;
 		xdp.data_hard_start = data - VIRTIO_XDP_HEADROOM + vi->hdr_len;
 		xdp.data = data + vi->hdr_len;
-		xdp_set_data_meta_invalid(&xdp);
 		xdp.data_end = xdp.data + (len - vi->hdr_len);
+		xdp.data_meta = xdp.data;
 		xdp.rxq = &rq->xdp_rxq;
 
 		act = bpf_prog_run_xdp(xdp_prog, &xdp);
@@ -848,24 +922,27 @@
 
 		switch (act) {
 		case XDP_PASS:
+			metasize = xdp.data - xdp.data_meta;
+
 			/* recalculate offset to account for any header
-			 * adjustments. Note other cases do not build an
-			 * skb and avoid using offset
+			 * adjustments and minus the metasize to copy the
+			 * metadata in page_to_skb(). Note other cases do not
+			 * build an skb and avoid using offset
 			 */
-			offset = xdp.data -
-					page_address(xdp_page) - vi->hdr_len;
+			offset = xdp.data - page_address(xdp_page) -
+				 vi->hdr_len - metasize;
 
-			/* recalculate len if xdp.data or xdp.data_end were
-			 * adjusted
+			/* recalculate len if xdp.data, xdp.data_end or
+			 * xdp.data_meta were adjusted
 			 */
-			len = xdp.data_end - xdp.data + vi->hdr_len;
+			len = xdp.data_end - xdp.data + vi->hdr_len + metasize;
 			/* We can only create skb based on xdp_page. */
 			if (unlikely(xdp_page != page)) {
 				rcu_read_unlock();
 				put_page(page);
-				head_skb = page_to_skb(vi, rq, xdp_page,
-						       offset, len,
-						       PAGE_SIZE, false);
+				head_skb = page_to_skb(vi, rq, xdp_page, offset,
+						       len, PAGE_SIZE, false,
+						       metasize);
 				return head_skb;
 			}
 			break;
@@ -921,7 +998,8 @@
 		goto err_skb;
 	}
 
-	head_skb = page_to_skb(vi, rq, page, offset, len, truesize, !xdp_prog);
+	head_skb = page_to_skb(vi, rq, page, offset, len, truesize, !xdp_prog,
+			       metasize);
 	curr_skb = head_skb;
 
 	if (unlikely(!curr_skb))
@@ -1231,9 +1309,11 @@
 			break;
 	} while (rq->vq->num_free);
 	if (virtqueue_kick_prepare(rq->vq) && virtqueue_notify(rq->vq)) {
-		u64_stats_update_begin(&rq->stats.syncp);
+		unsigned long flags;
+
+		flags = u64_stats_update_begin_irqsave(&rq->stats.syncp);
 		rq->stats.kicks++;
-		u64_stats_update_end(&rq->stats.syncp);
+		u64_stats_update_end_irqrestore(&rq->stats.syncp, flags);
 	}
 
 	return !oom;
@@ -1332,8 +1412,12 @@
 	}
 
 	if (rq->vq->num_free > min((unsigned int)budget, virtqueue_get_vring_size(rq->vq)) / 2) {
-		if (!try_fill_recv(vi, rq, GFP_ATOMIC))
-			schedule_delayed_work(&vi->refill, 0);
+		if (!try_fill_recv(vi, rq, GFP_ATOMIC)) {
+			spin_lock(&vi->refill_lock);
+			if (vi->refill_enabled)
+				schedule_delayed_work(&vi->refill, 0);
+			spin_unlock(&vi->refill_lock);
+		}
 	}
 
 	u64_stats_update_begin(&rq->stats.syncp);
@@ -1395,7 +1479,7 @@
 		return false;
 }
 
-static void virtnet_poll_cleantx(struct receive_queue *rq)
+static void virtnet_poll_cleantx(struct receive_queue *rq, int budget)
 {
 	struct virtnet_info *vi = rq->vq->vdev->priv;
 	unsigned int index = vq2rxq(rq->vq);
@@ -1406,7 +1490,7 @@
 		return;
 
 	if (__netif_tx_trylock(txq)) {
-		free_old_xmit_skbs(sq, true);
+		free_old_xmit_skbs(sq, !!budget);
 		__netif_tx_unlock(txq);
 	}
 
@@ -1423,7 +1507,7 @@
 	unsigned int received;
 	unsigned int xdp_xmit = 0;
 
-	virtnet_poll_cleantx(rq);
+	virtnet_poll_cleantx(rq, budget);
 
 	received = virtnet_receive(rq, budget, &xdp_xmit);
 
@@ -1435,12 +1519,13 @@
 		xdp_do_flush_map();
 
 	if (xdp_xmit & VIRTIO_XDP_TX) {
-		sq = virtnet_xdp_sq(vi);
+		sq = virtnet_xdp_get_sq(vi);
 		if (virtqueue_kick_prepare(sq->vq) && virtqueue_notify(sq->vq)) {
 			u64_stats_update_begin(&sq->stats.syncp);
 			sq->stats.kicks++;
 			u64_stats_update_end(&sq->stats.syncp);
 		}
+		virtnet_xdp_put_sq(vi, sq);
 	}
 
 	return received;
@@ -1451,6 +1536,8 @@
 	struct virtnet_info *vi = netdev_priv(dev);
 	int i, err;
 
+	enable_delayed_refill(vi);
+
 	for (i = 0; i < vi->max_queue_pairs; i++) {
 		if (i < vi->curr_queue_pairs)
 			/* Make sure we have some buffers: if oom use wq. */
@@ -1481,6 +1568,8 @@
 	struct virtnet_info *vi = sq->vq->vdev->priv;
 	unsigned int index = vq2txq(sq->vq);
 	struct netdev_queue *txq;
+	int opaque;
+	bool done;
 
 	if (unlikely(is_xdp_raw_buffer_queue(vi, index))) {
 		/* We don't need to enable cb for XDP */
@@ -1490,10 +1579,28 @@
 
 	txq = netdev_get_tx_queue(vi->dev, index);
 	__netif_tx_lock(txq, raw_smp_processor_id());
-	free_old_xmit_skbs(sq, true);
+	virtqueue_disable_cb(sq->vq);
+	free_old_xmit_skbs(sq, !!budget);
+
+	opaque = virtqueue_enable_cb_prepare(sq->vq);
+
+	done = napi_complete_done(napi, 0);
+
+	if (!done)
+		virtqueue_disable_cb(sq->vq);
+
 	__netif_tx_unlock(txq);
 
-	virtqueue_napi_complete(napi, sq->vq, 0);
+	if (done) {
+		if (unlikely(virtqueue_poll(sq->vq, opaque))) {
+			if (napi_schedule_prep(napi)) {
+				__netif_tx_lock(txq, raw_smp_processor_id());
+				virtqueue_disable_cb(sq->vq);
+				__netif_tx_unlock(txq);
+				__napi_schedule(napi);
+			}
+		}
+	}
 
 	if (sq->vq->num_free >= 2 + MAX_SKB_FRAGS)
 		netif_tx_wake_queue(txq);
@@ -1525,7 +1632,7 @@
 	if (virtio_net_hdr_from_skb(skb, &hdr->hdr,
 				    virtio_is_little_endian(vi->vdev), false,
 				    0))
-		BUG();
+		return -EPROTO;
 
 	if (vi->mergeable_rx_bufs)
 		hdr->num_buffers = 0;
@@ -1801,12 +1908,14 @@
 	struct virtnet_info *vi = netdev_priv(dev);
 	int i;
 
+	/* Make sure NAPI doesn't schedule refill work */
+	disable_delayed_refill(vi);
 	/* Make sure refill_work doesn't re-enable napi! */
 	cancel_delayed_work_sync(&vi->refill);
 
 	for (i = 0; i < vi->max_queue_pairs; i++) {
-		xdp_rxq_info_unreg(&vi->rq[i].xdp_rxq);
 		napi_disable(&vi->rq[i].napi);
+		xdp_rxq_info_unreg(&vi->rq[i].xdp_rxq);
 		virtnet_napi_tx_disable(&vi->sq[i].napi);
 	}
 
@@ -2065,14 +2174,16 @@
 
 	get_online_cpus();
 	err = _virtnet_set_queues(vi, queue_pairs);
-	if (!err) {
-		netif_set_real_num_tx_queues(dev, queue_pairs);
-		netif_set_real_num_rx_queues(dev, queue_pairs);
-
-		virtnet_set_affinity(vi);
+	if (err) {
+		put_online_cpus();
+		goto err;
 	}
+	virtnet_set_affinity(vi);
 	put_online_cpus();
 
+	netif_set_real_num_tx_queues(dev, queue_pairs);
+	netif_set_real_num_rx_queues(dev, queue_pairs);
+ err:
 	return err;
 }
 
@@ -2314,7 +2425,6 @@
 static void virtnet_freeze_down(struct virtio_device *vdev)
 {
 	struct virtnet_info *vi = vdev->priv;
-	int i;
 
 	/* Make sure no work handler is accessing the device */
 	flush_work(&vi->config_work);
@@ -2322,14 +2432,8 @@
 	netif_tx_lock_bh(vi->dev);
 	netif_device_detach(vi->dev);
 	netif_tx_unlock_bh(vi->dev);
-	cancel_delayed_work_sync(&vi->refill);
-
-	if (netif_running(vi->dev)) {
-		for (i = 0; i < vi->max_queue_pairs; i++) {
-			napi_disable(&vi->rq[i].napi);
-			virtnet_napi_tx_disable(&vi->sq[i].napi);
-		}
-	}
+	if (netif_running(vi->dev))
+		virtnet_close(vi->dev);
 }
 
 static int init_vqs(struct virtnet_info *vi);
@@ -2337,7 +2441,7 @@
 static int virtnet_restore_up(struct virtio_device *vdev)
 {
 	struct virtnet_info *vi = vdev->priv;
-	int err, i;
+	int err;
 
 	err = init_vqs(vi);
 	if (err)
@@ -2345,16 +2449,12 @@
 
 	virtio_device_ready(vdev);
 
-	if (netif_running(vi->dev)) {
-		for (i = 0; i < vi->curr_queue_pairs; i++)
-			if (!try_fill_recv(vi, &vi->rq[i], GFP_KERNEL))
-				schedule_delayed_work(&vi->refill, 0);
+	enable_delayed_refill(vi);
 
-		for (i = 0; i < vi->max_queue_pairs; i++) {
-			virtnet_napi_enable(vi->rq[i].vq, &vi->rq[i].napi);
-			virtnet_napi_tx_enable(vi, vi->sq[i].vq,
-					       &vi->sq[i].napi);
-		}
+	if (netif_running(vi->dev)) {
+		err = virtnet_open(vi->dev);
+		if (err)
+			return err;
 	}
 
 	netif_tx_lock_bh(vi->dev);
@@ -2414,7 +2514,7 @@
 	        virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_ECN) ||
 		virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_UFO) ||
 		virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_CSUM))) {
-		NL_SET_ERR_MSG_MOD(extack, "Can't set XDP while host is implementing LRO/CSUM, disable LRO/CSUM first");
+		NL_SET_ERR_MSG_MOD(extack, "Can't set XDP while host is implementing GRO_HW/CSUM, disable GRO_HW/CSUM first");
 		return -EOPNOTSUPP;
 	}
 
@@ -2435,10 +2535,9 @@
 
 	/* XDP requires extra queues for XDP_TX */
 	if (curr_qp + xdp_qp > vi->max_queue_pairs) {
-		NL_SET_ERR_MSG_MOD(extack, "Too few free TX rings available");
-		netdev_warn(dev, "request %i queues but max is %i\n",
+		netdev_warn(dev, "XDP request %i queues but max is %i. XDP_TX and XDP_REDIRECT will operate in a slower locked tx mode.\n",
 			    curr_qp + xdp_qp, vi->max_queue_pairs);
-		return -ENOMEM;
+		xdp_qp = 0;
 	}
 
 	old_prog = rtnl_dereference(vi->rq[0].xdp_prog);
@@ -2475,11 +2574,14 @@
 	vi->xdp_queue_pairs = xdp_qp;
 
 	if (prog) {
+		vi->xdp_enabled = true;
 		for (i = 0; i < vi->max_queue_pairs; i++) {
 			rcu_assign_pointer(vi->rq[i].xdp_prog, prog);
 			if (i == 0 && !old_prog)
 				virtnet_clear_guest_offloads(vi);
 		}
+	} else {
+		vi->xdp_enabled = false;
 	}
 
 	for (i = 0; i < vi->max_queue_pairs; i++) {
@@ -2563,14 +2665,15 @@
 	u64 offloads;
 	int err;
 
-	if ((dev->features ^ features) & NETIF_F_LRO) {
-		if (vi->xdp_queue_pairs)
+	if ((dev->features ^ features) & NETIF_F_GRO_HW) {
+		if (vi->xdp_enabled)
 			return -EBUSY;
 
-		if (features & NETIF_F_LRO)
+		if (features & NETIF_F_GRO_HW)
 			offloads = vi->guest_offloads_capable;
 		else
-			offloads = 0;
+			offloads = vi->guest_offloads_capable &
+				   ~GUEST_OFFLOAD_GRO_HW_MASK;
 
 		err = virtnet_set_guest_offloads(vi, offloads);
 		if (err)
@@ -2689,6 +2792,27 @@
 			put_page(vi->rq[i].alloc_frag.page);
 }
 
+static void virtnet_sq_free_unused_buf(struct virtqueue *vq, void *buf)
+{
+	if (!is_xdp_frame(buf))
+		dev_kfree_skb(buf);
+	else
+		xdp_return_frame(ptr_to_xdp(buf));
+}
+
+static void virtnet_rq_free_unused_buf(struct virtqueue *vq, void *buf)
+{
+	struct virtnet_info *vi = vq->vdev->priv;
+	int i = vq2rxq(vq);
+
+	if (vi->mergeable_rx_bufs)
+		put_page(virt_to_head_page(buf));
+	else if (vi->big_packets)
+		give_pages(&vi->rq[i], buf);
+	else
+		put_page(virt_to_head_page(buf));
+}
+
 static void free_unused_bufs(struct virtnet_info *vi)
 {
 	void *buf;
@@ -2696,26 +2820,16 @@
 
 	for (i = 0; i < vi->max_queue_pairs; i++) {
 		struct virtqueue *vq = vi->sq[i].vq;
-		while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) {
-			if (!is_xdp_frame(buf))
-				dev_kfree_skb(buf);
-			else
-				xdp_return_frame(ptr_to_xdp(buf));
-		}
+		while ((buf = virtqueue_detach_unused_buf(vq)) != NULL)
+			virtnet_sq_free_unused_buf(vq, buf);
+		cond_resched();
 	}
 
 	for (i = 0; i < vi->max_queue_pairs; i++) {
 		struct virtqueue *vq = vi->rq[i].vq;
-
-		while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) {
-			if (vi->mergeable_rx_bufs) {
-				put_page(virt_to_head_page(buf));
-			} else if (vi->big_packets) {
-				give_pages(&vi->rq[i], buf);
-			} else {
-				put_page(virt_to_head_page(buf));
-			}
-		}
+		while ((buf = virtqueue_detach_unused_buf(vq)) != NULL)
+			virtnet_rq_free_unused_buf(vq, buf);
+		cond_resched();
 	}
 }
 
@@ -2750,10 +2864,11 @@
 {
 	vq_callback_t **callbacks;
 	struct virtqueue **vqs;
-	int ret = -ENOMEM;
-	int i, total_vqs;
 	const char **names;
+	int ret = -ENOMEM;
+	int total_vqs;
 	bool *ctx;
+	u16 i;
 
 	/* We expect 1 RX virtqueue followed by 1 TX virtqueue, followed by
 	 * possible N-1 RX/TX queue pairs used in multiqueue mode, followed by
@@ -2790,8 +2905,8 @@
 	for (i = 0; i < vi->max_queue_pairs; i++) {
 		callbacks[rxq2vq(i)] = skb_recv_done;
 		callbacks[txq2vq(i)] = skb_xmit_done;
-		sprintf(vi->rq[i].name, "input.%d", i);
-		sprintf(vi->sq[i].name, "output.%d", i);
+		sprintf(vi->rq[i].name, "input.%u", i);
+		sprintf(vi->sq[i].name, "output.%u", i);
 		names[rxq2vq(i)] = vi->rq[i].name;
 		names[txq2vq(i)] = vi->sq[i].name;
 		if (ctx)
@@ -3042,13 +3157,21 @@
 			dev->features |= dev->hw_features & NETIF_F_ALL_TSO;
 		/* (!csum && gso) case will be fixed by register_netdev() */
 	}
-	if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_CSUM))
-		dev->features |= NETIF_F_RXCSUM;
+
+	/* 1. With VIRTIO_NET_F_GUEST_CSUM negotiation, the driver doesn't
+	 * need to calculate checksums for partially checksummed packets,
+	 * as they're considered valid by the upper layer.
+	 * 2. Without VIRTIO_NET_F_GUEST_CSUM negotiation, the driver only
+	 * receives fully checksummed packets. The device may assist in
+	 * validating these packets' checksums, so the driver won't have to.
+	 */
+	dev->features |= NETIF_F_RXCSUM;
+
 	if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) ||
 	    virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO6))
-		dev->features |= NETIF_F_LRO;
+		dev->features |= NETIF_F_GRO_HW;
 	if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS))
-		dev->hw_features |= NETIF_F_LRO;
+		dev->hw_features |= NETIF_F_GRO_HW;
 
 	dev->vlan_features = dev->features;
 
@@ -3071,6 +3194,7 @@
 	vdev->priv = vi;
 
 	INIT_WORK(&vi->config_work, virtnet_config_changed_work);
+	spin_lock_init(&vi->refill_lock);
 
 	/* If we can receive ANY GSO packets, we must allocate large ones. */
 	if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) ||
@@ -3106,6 +3230,7 @@
 			dev_err(&vdev->dev,
 				"device MTU appears to have changed it is now %d < %d",
 				mtu, dev->min_mtu);
+			err = -EINVAL;
 			goto free;
 		}
 
@@ -3149,22 +3274,28 @@
 		}
 	}
 
-	err = register_netdev(dev);
+	/* serialize netdev register + virtio_device_ready() with ndo_open() */
+	rtnl_lock();
+
+	err = register_netdevice(dev);
 	if (err) {
 		pr_debug("virtio_net: registering device failed\n");
+		rtnl_unlock();
 		goto free_failover;
 	}
 
 	virtio_device_ready(vdev);
 
+	_virtnet_set_queues(vi, vi->curr_queue_pairs);
+
+	rtnl_unlock();
+
 	err = virtnet_cpu_notif_add(vi);
 	if (err) {
 		pr_debug("virtio_net: registering cpu notifier failed\n");
 		goto free_unregister_netdev;
 	}
 
-	virtnet_set_queues(vi, vi->curr_queue_pairs);
-
 	/* Assume link up if device can't report link status,
 	   otherwise get link status from config. */
 	netif_carrier_off(dev);
@@ -3255,8 +3386,11 @@
 	virtnet_set_queues(vi, vi->curr_queue_pairs);
 
 	err = virtnet_cpu_notif_add(vi);
-	if (err)
+	if (err) {
+		virtnet_freeze_down(vdev);
+		remove_vq_common(vi);
 		return err;
+	}
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/vmxnet3/vmxnet3_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -595,6 +595,7 @@
 				if (dma_mapping_error(&adapter->pdev->dev,
 						      rbi->dma_addr)) {
 					dev_kfree_skb_any(rbi->skb);
+					rbi->skb = NULL;
 					rq->stats.rx_buf_alloc_failure++;
 					break;
 				}
@@ -619,6 +620,7 @@
 				if (dma_mapping_error(&adapter->pdev->dev,
 						      rbi->dma_addr)) {
 					put_page(rbi->page);
+					rbi->page = NULL;
 					rq->stats.rx_buf_alloc_failure++;
 					break;
 				}
@@ -861,7 +863,8 @@
 
 			switch (protocol) {
 			case IPPROTO_TCP:
-				ctx->l4_hdr_size = tcp_hdrlen(skb);
+				ctx->l4_hdr_size = skb->encapsulation ? inner_tcp_hdrlen(skb) :
+						   tcp_hdrlen(skb);
 				break;
 			case IPPROTO_UDP:
 				ctx->l4_hdr_size = sizeof(struct udphdr);
@@ -1583,6 +1586,10 @@
 	u32 i, ring_idx;
 	struct Vmxnet3_RxDesc *rxd;
 
+	/* ring has already been cleaned up */
+	if (!rq->rx_ring[0].base)
+		return;
+
 	for (ring_idx = 0; ring_idx < 2; ring_idx++) {
 		for (i = 0; i < rq->rx_ring[ring_idx].size; i++) {
 #ifdef __BIG_ENDIAN_BITFIELD
@@ -3633,7 +3640,6 @@
 	vmxnet3_free_intr_resources(adapter);
 
 	netif_device_detach(netdev);
-	netif_tx_stop_all_queues(netdev);
 
 	/* Create wake-up filters. */
 	pmConf = adapter->pm_conf;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/vmxnet3/vmxnet3_ethtool.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/vmxnet3/vmxnet3_ethtool.c
@@ -702,6 +702,8 @@
 		*hfunc = ETH_RSS_HASH_TOP;
 	if (!p)
 		return 0;
+	if (n > UPT1_RSS_MAX_IND_TABLE_SIZE)
+		return 0;
 	while (n--)
 		p[n] = rssConf->indTable[n];
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/vrf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/vrf.c
@@ -33,6 +33,7 @@
 #include <net/l3mdev.h>
 #include <net/fib_rules.h>
 #include <net/netns/generic.h>
+#include <net/netfilter/nf_conntrack.h>
 
 #define DRV_NAME	"vrf"
 #define DRV_VERSION	"1.0"
@@ -147,12 +148,26 @@
 	return NETDEV_TX_OK;
 }
 
+static void vrf_nf_set_untracked(struct sk_buff *skb)
+{
+	if (skb_get_nfct(skb) == 0)
+		nf_ct_set(skb, NULL, IP_CT_UNTRACKED);
+}
+
+static void vrf_nf_reset_ct(struct sk_buff *skb)
+{
+	if (skb_get_nfct(skb) == IP_CT_UNTRACKED)
+		nf_reset_ct(skb);
+}
+
 #if IS_ENABLED(CONFIG_IPV6)
 static int vrf_ip6_local_out(struct net *net, struct sock *sk,
 			     struct sk_buff *skb)
 {
 	int err;
 
+	vrf_nf_reset_ct(skb);
+
 	err = nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT, net,
 		      sk, skb, NULL, skb_dst(skb)->dev, dst_output);
 
@@ -188,8 +203,8 @@
 	fl6.flowi6_proto = iph->nexthdr;
 	fl6.flowi6_flags = FLOWI_FLAG_SKIP_NH_OIF;
 
-	dst = ip6_route_output(net, NULL, &fl6);
-	if (dst == dst_null)
+	dst = ip6_dst_lookup_flow(net, NULL, &fl6, NULL);
+	if (IS_ERR(dst) || dst == dst_null)
 		goto err;
 
 	skb_dst_drop(skb);
@@ -206,6 +221,7 @@
 	/* strip the ethernet header added for pass through VRF device */
 	__skb_pull(skb, skb_network_offset(skb));
 
+	memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
 	ret = vrf_ip6_local_out(net, skb->sk, skb);
 	if (unlikely(net_xmit_eval(ret)))
 		dev->stats.tx_errors++;
@@ -232,6 +248,8 @@
 {
 	int err;
 
+	vrf_nf_reset_ct(skb);
+
 	err = nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT, net, sk,
 		      skb, NULL, skb_dst(skb)->dev, dst_output);
 	if (likely(err == 1))
@@ -287,6 +305,7 @@
 					       RT_SCOPE_LINK);
 	}
 
+	memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
 	ret = vrf_ip_local_out(dev_net(skb_dst(skb)->dev), skb->sk, skb);
 	if (unlikely(net_xmit_eval(ret)))
 		vrf_dev->stats.tx_errors++;
@@ -332,8 +351,7 @@
 	return ret;
 }
 
-static int vrf_finish_direct(struct net *net, struct sock *sk,
-			     struct sk_buff *skb)
+static void vrf_finish_direct(struct sk_buff *skb)
 {
 	struct net_device *vrf_dev = skb->dev;
 
@@ -352,7 +370,7 @@
 		skb_pull(skb, ETH_HLEN);
 	}
 
-	return 1;
+	vrf_nf_reset_ct(skb);
 }
 
 #if IS_ENABLED(CONFIG_IPV6)
@@ -366,7 +384,7 @@
 	struct neighbour *neigh;
 	int ret;
 
-	nf_reset_ct(skb);
+	vrf_nf_reset_ct(skb);
 
 	skb->protocol = htons(ETH_P_IPV6);
 	skb->dev = dev;
@@ -431,15 +449,41 @@
 	return skb;
 }
 
+static int vrf_output6_direct_finish(struct net *net, struct sock *sk,
+				     struct sk_buff *skb)
+{
+	vrf_finish_direct(skb);
+
+	return vrf_ip6_local_out(net, sk, skb);
+}
+
 static int vrf_output6_direct(struct net *net, struct sock *sk,
 			      struct sk_buff *skb)
 {
+	int err = 1;
+
 	skb->protocol = htons(ETH_P_IPV6);
 
-	return NF_HOOK_COND(NFPROTO_IPV6, NF_INET_POST_ROUTING,
-			    net, sk, skb, NULL, skb->dev,
-			    vrf_finish_direct,
-			    !(IPCB(skb)->flags & IPSKB_REROUTED));
+	if (!(IPCB(skb)->flags & IPSKB_REROUTED))
+		err = nf_hook(NFPROTO_IPV6, NF_INET_POST_ROUTING, net, sk, skb,
+			      NULL, skb->dev, vrf_output6_direct_finish);
+
+	if (likely(err == 1))
+		vrf_finish_direct(skb);
+
+	return err;
+}
+
+static int vrf_ip6_out_direct_finish(struct net *net, struct sock *sk,
+				     struct sk_buff *skb)
+{
+	int err;
+
+	err = vrf_output6_direct(net, sk, skb);
+	if (likely(err == 1))
+		err = vrf_ip6_local_out(net, sk, skb);
+
+	return err;
 }
 
 static struct sk_buff *vrf_ip6_out_direct(struct net_device *vrf_dev,
@@ -452,18 +496,15 @@
 	skb->dev = vrf_dev;
 
 	err = nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT, net, sk,
-		      skb, NULL, vrf_dev, vrf_output6_direct);
+		      skb, NULL, vrf_dev, vrf_ip6_out_direct_finish);
 
 	if (likely(err == 1))
 		err = vrf_output6_direct(net, sk, skb);
 
-	/* reset skb device */
 	if (likely(err == 1))
-		nf_reset_ct(skb);
-	else
-		skb = NULL;
+		return skb;
 
-	return skb;
+	return NULL;
 }
 
 static struct sk_buff *vrf_ip6_out(struct net_device *vrf_dev,
@@ -474,7 +515,10 @@
 	if (rt6_need_strict(&ipv6_hdr(skb)->daddr))
 		return skb;
 
-	if (qdisc_tx_is_default(vrf_dev))
+	vrf_nf_set_untracked(skb);
+
+	if (qdisc_tx_is_default(vrf_dev) ||
+	    IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
 		return vrf_ip6_out_direct(vrf_dev, sk, skb);
 
 	return vrf_ip6_out_redirect(vrf_dev, skb);
@@ -560,7 +604,7 @@
 	bool is_v6gw = false;
 	int ret = -EINVAL;
 
-	nf_reset_ct(skb);
+	vrf_nf_reset_ct(skb);
 
 	/* Be paranoid, rather than too clever. */
 	if (unlikely(skb_headroom(skb) < hh_len && dev->header_ops)) {
@@ -642,15 +686,41 @@
 	return skb;
 }
 
+static int vrf_output_direct_finish(struct net *net, struct sock *sk,
+				    struct sk_buff *skb)
+{
+	vrf_finish_direct(skb);
+
+	return vrf_ip_local_out(net, sk, skb);
+}
+
 static int vrf_output_direct(struct net *net, struct sock *sk,
 			     struct sk_buff *skb)
 {
+	int err = 1;
+
 	skb->protocol = htons(ETH_P_IP);
 
-	return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING,
-			    net, sk, skb, NULL, skb->dev,
-			    vrf_finish_direct,
-			    !(IPCB(skb)->flags & IPSKB_REROUTED));
+	if (!(IPCB(skb)->flags & IPSKB_REROUTED))
+		err = nf_hook(NFPROTO_IPV4, NF_INET_POST_ROUTING, net, sk, skb,
+			      NULL, skb->dev, vrf_output_direct_finish);
+
+	if (likely(err == 1))
+		vrf_finish_direct(skb);
+
+	return err;
+}
+
+static int vrf_ip_out_direct_finish(struct net *net, struct sock *sk,
+				    struct sk_buff *skb)
+{
+	int err;
+
+	err = vrf_output_direct(net, sk, skb);
+	if (likely(err == 1))
+		err = vrf_ip_local_out(net, sk, skb);
+
+	return err;
 }
 
 static struct sk_buff *vrf_ip_out_direct(struct net_device *vrf_dev,
@@ -663,18 +733,15 @@
 	skb->dev = vrf_dev;
 
 	err = nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT, net, sk,
-		      skb, NULL, vrf_dev, vrf_output_direct);
+		      skb, NULL, vrf_dev, vrf_ip_out_direct_finish);
 
 	if (likely(err == 1))
 		err = vrf_output_direct(net, sk, skb);
 
-	/* reset skb device */
 	if (likely(err == 1))
-		nf_reset_ct(skb);
-	else
-		skb = NULL;
+		return skb;
 
-	return skb;
+	return NULL;
 }
 
 static struct sk_buff *vrf_ip_out(struct net_device *vrf_dev,
@@ -686,7 +753,10 @@
 	    ipv4_is_lbcast(ip_hdr(skb)->daddr))
 		return skb;
 
-	if (qdisc_tx_is_default(vrf_dev))
+	vrf_nf_set_untracked(skb);
+
+	if (qdisc_tx_is_default(vrf_dev) ||
+	    IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
 		return vrf_ip_out_direct(vrf_dev, sk, skb);
 
 	return vrf_ip_out_redirect(vrf_dev, skb);
@@ -860,9 +930,6 @@
 
 	dev->flags = IFF_MASTER | IFF_NOARP;
 
-	/* MTU is irrelevant for VRF device; set to 64k similar to lo */
-	dev->mtu = 64 * 1024;
-
 	/* similarly, oper state is irrelevant; set to up to avoid confusion */
 	dev->operstate = IF_OPER_UP;
 	return 0;
@@ -992,14 +1059,20 @@
 	bool is_ndisc = ipv6_ndisc_frame(skb);
 
 	/* loopback, multicast & non-ND link-local traffic; do not push through
-	 * packet taps again. Reset pkt_type for upper layers to process skb
+	 * packet taps again. Reset pkt_type for upper layers to process skb.
+	 * For strict packets with a source LLA, determine the dst using the
+	 * original ifindex.
 	 */
 	if (skb->pkt_type == PACKET_LOOPBACK || (need_strict && !is_ndisc)) {
 		skb->dev = vrf_dev;
 		skb->skb_iif = vrf_dev->ifindex;
 		IP6CB(skb)->flags |= IP6SKB_L3SLAVE;
+
 		if (skb->pkt_type == PACKET_LOOPBACK)
 			skb->pkt_type = PACKET_HOST;
+		else if (ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)
+			vrf_ip6_input_dst(skb, vrf_dev, orig_iif);
+
 		goto out;
 	}
 
@@ -1289,7 +1362,8 @@
 	 * which breaks networking.
 	 */
 	dev->min_mtu = IPV6_MIN_MTU;
-	dev->max_mtu = ETH_MAX_MTU;
+	dev->max_mtu = IP6_MAX_MTU;
+	dev->mtu = dev->max_mtu;
 }
 
 static int vrf_validate(struct nlattr *tb[], struct nlattr *data[],
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/vxlan.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/vxlan.c
@@ -13,6 +13,7 @@
 #include <linux/slab.h>
 #include <linux/udp.h>
 #include <linux/igmp.h>
+#include <linux/inetdevice.h>
 #include <linux/if_ether.h>
 #include <linux/ethtool.h>
 #include <net/arp.h>
@@ -91,6 +92,167 @@
 	       ip_tunnel_collect_metadata();
 }
 
+static struct ip_fan_map *vxlan_fan_find_map(struct vxlan_dev *vxlan, __be32 daddr)
+{
+	struct ip_fan_map *fan_map;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(fan_map, &vxlan->fan.fan_maps, list) {
+		if (fan_map->overlay ==
+		    (daddr & inet_make_mask(fan_map->overlay_prefix))) {
+			rcu_read_unlock();
+			return fan_map;
+		}
+	}
+	rcu_read_unlock();
+
+	return NULL;
+}
+
+static void vxlan_fan_flush_map(struct vxlan_dev *vxlan)
+{
+	struct ip_fan_map *fan_map;
+
+	list_for_each_entry_rcu(fan_map, &vxlan->fan.fan_maps, list) {
+		list_del_rcu(&fan_map->list);
+		kfree_rcu(fan_map, rcu);
+	}
+}
+
+static int vxlan_fan_del_map(struct vxlan_dev *vxlan, __be32 overlay)
+{
+	struct ip_fan_map *fan_map;
+
+	fan_map = vxlan_fan_find_map(vxlan, overlay);
+	if (!fan_map)
+		return -ENOENT;
+
+	list_del_rcu(&fan_map->list);
+	kfree_rcu(fan_map, rcu);
+
+	return 0;
+}
+
+static int vxlan_fan_add_map(struct vxlan_dev *vxlan, struct ifla_fan_map *map)
+{
+	__be32 overlay_mask, underlay_mask;
+	struct ip_fan_map *fan_map;
+
+	overlay_mask = inet_make_mask(map->overlay_prefix);
+	underlay_mask = inet_make_mask(map->underlay_prefix);
+
+	netdev_dbg(vxlan->dev, "vfam: map: o %x/%d u %x/%d om %x um %x\n",
+		   map->overlay, map->overlay_prefix,
+		   map->underlay, map->underlay_prefix,
+		   overlay_mask, underlay_mask);
+
+	if ((map->overlay & ~overlay_mask) || (map->underlay & ~underlay_mask))
+		return -EINVAL;
+
+	if (!(map->overlay & overlay_mask) && (map->underlay & underlay_mask))
+		return -EINVAL;
+
+	/* Special case: overlay 0 and underlay 0: flush all mappings */
+	if (!map->overlay && !map->underlay) {
+		vxlan_fan_flush_map(vxlan);
+		return 0;
+	}
+	
+	/* Special case: overlay set and underlay 0: clear map for overlay */
+	if (!map->underlay)
+		return vxlan_fan_del_map(vxlan, map->overlay);
+
+	if (vxlan_fan_find_map(vxlan, map->overlay))
+		return -EEXIST;
+
+	fan_map = kmalloc(sizeof(*fan_map), GFP_KERNEL);
+	fan_map->underlay = map->underlay;
+	fan_map->overlay = map->overlay;
+	fan_map->underlay_prefix = map->underlay_prefix;
+	fan_map->overlay_mask = ntohl(overlay_mask);
+	fan_map->overlay_prefix = map->overlay_prefix;
+
+	list_add_tail_rcu(&fan_map->list, &vxlan->fan.fan_maps);
+
+	return 0;
+}
+	
+static int vxlan_parse_fan_map(struct nlattr *data[], struct vxlan_dev *vxlan)
+{
+	struct ifla_fan_map *map;
+	struct nlattr *attr;
+	int rem, rv;
+
+	nla_for_each_nested(attr, data[IFLA_IPTUN_FAN_MAP], rem) {
+		map = nla_data(attr);
+		rv = vxlan_fan_add_map(vxlan, map);
+		if (rv)
+			return rv;
+	}
+
+	return 0;
+}
+
+static int vxlan_fan_build_rdst(struct vxlan_dev *vxlan, struct sk_buff *skb,
+				      struct vxlan_rdst *fan_rdst)
+{
+	struct ip_fan_map *f_map;
+	union vxlan_addr *va;
+	u32 daddr, underlay;
+	struct arphdr *arp;
+	void *arp_ptr;
+	struct ethhdr *eth;
+	struct iphdr *iph;
+
+	eth = eth_hdr(skb);
+	switch (eth->h_proto) {
+	case htons(ETH_P_IP):
+		iph = ip_hdr(skb);
+		if (!iph)
+			return -EINVAL;
+		daddr = iph->daddr;
+		break;
+	case htons(ETH_P_ARP):
+		arp = arp_hdr(skb);
+		if (!arp)
+			return -EINVAL;
+		arp_ptr = arp + 1;
+		netdev_dbg(vxlan->dev,
+			   "vfbr: arp sha %pM sip %pI4 tha %pM tip %pI4\n",
+			   arp_ptr, arp_ptr + skb->dev->addr_len,
+			   arp_ptr + skb->dev->addr_len + 4,
+			   arp_ptr + (skb->dev->addr_len * 2) + 4);
+		arp_ptr += (skb->dev->addr_len * 2) + 4;
+		memcpy(&daddr, arp_ptr, 4);
+		break;
+	default:
+		netdev_dbg(vxlan->dev, "vfbr: unknown eth p %x\n", eth->h_proto);
+		return -EINVAL;
+	}
+
+	f_map = vxlan_fan_find_map(vxlan, daddr);
+	if (!f_map)
+		return -EINVAL;
+
+	daddr = ntohl(daddr);
+	underlay = ntohl(f_map->underlay);
+	if (!underlay)
+		return -EINVAL;
+
+	memset(fan_rdst, 0, sizeof(*fan_rdst));
+	va = &fan_rdst->remote_ip;
+	va->sa.sa_family = AF_INET;
+	fan_rdst->remote_vni = vxlan->default_dst.remote_vni;
+	va->sin.sin_addr.s_addr = htonl(underlay |
+					((daddr & ~f_map->overlay_mask) >>
+					 (32 - f_map->overlay_prefix -
+					  (32 - f_map->underlay_prefix))));
+	netdev_dbg(vxlan->dev, "vfbr: daddr %x ul %x dst %x\n",
+		   daddr, underlay, va->sin.sin_addr.s_addr);
+
+	return 0;
+}
+
 #if IS_ENABLED(CONFIG_IPV6)
 static inline
 bool vxlan_addr_equal(const union vxlan_addr *a, const union vxlan_addr *b)
@@ -679,11 +841,11 @@
 
 	rd = kmalloc(sizeof(*rd), GFP_ATOMIC);
 	if (rd == NULL)
-		return -ENOBUFS;
+		return -ENOMEM;
 
 	if (dst_cache_init(&rd->dst_cache, GFP_ATOMIC)) {
 		kfree(rd);
-		return -ENOBUFS;
+		return -ENOMEM;
 	}
 
 	rd->remote_ip = *ip;
@@ -698,6 +860,32 @@
 	return 1;
 }
 
+static bool vxlan_parse_gpe_proto(struct vxlanhdr *hdr, __be16 *protocol)
+{
+	struct vxlanhdr_gpe *gpe = (struct vxlanhdr_gpe *)hdr;
+
+	/* Need to have Next Protocol set for interfaces in GPE mode. */
+	if (!gpe->np_applied)
+		return false;
+	/* "The initial version is 0. If a receiver does not support the
+	 * version indicated it MUST drop the packet.
+	 */
+	if (gpe->version != 0)
+		return false;
+	/* "When the O bit is set to 1, the packet is an OAM packet and OAM
+	 * processing MUST occur." However, we don't implement OAM
+	 * processing, thus drop the packet.
+	 */
+	if (gpe->oam_flag)
+		return false;
+
+	*protocol = tun_p_to_eth_p(gpe->next_protocol);
+	if (!*protocol)
+		return false;
+
+	return true;
+}
+
 static struct vxlanhdr *vxlan_gro_remcsum(struct sk_buff *skb,
 					  unsigned int off,
 					  struct vxlanhdr *vh, size_t hdrlen,
@@ -1225,6 +1413,7 @@
 	for (h = 0; h < FDB_HASH_SIZE; ++h) {
 		struct vxlan_fdb *f;
 
+		rcu_read_lock();
 		hlist_for_each_entry_rcu(f, &vxlan->fdb_head[h], hlist) {
 			struct vxlan_rdst *rd;
 
@@ -1237,12 +1426,15 @@
 						     cb->nlh->nlmsg_seq,
 						     RTM_NEWNEIGH,
 						     NLM_F_MULTI, rd);
-				if (err < 0)
+				if (err < 0) {
+					rcu_read_unlock();
 					goto out;
+				}
 skip:
 				*idx += 1;
 			}
 		}
+		rcu_read_unlock();
 	}
 out:
 	return err;
@@ -1293,6 +1485,10 @@
 	struct vxlan_fdb *f;
 	u32 ifindex = 0;
 
+	/* Ignore packets from invalid src-address */
+	if (!is_valid_ether_addr(src_mac))
+		return true;
+
 #if IS_ENABLED(CONFIG_IPV6)
 	if (src_ip->sa.sa_family == AF_INET6 &&
 	    (ipv6_addr_type(&src_ip->sin6.sin6_addr) & IPV6_ADDR_LINKLOCAL))
@@ -1560,35 +1756,6 @@
 	unparsed->vx_flags &= ~VXLAN_GBP_USED_BITS;
 }
 
-static bool vxlan_parse_gpe_hdr(struct vxlanhdr *unparsed,
-				__be16 *protocol,
-				struct sk_buff *skb, u32 vxflags)
-{
-	struct vxlanhdr_gpe *gpe = (struct vxlanhdr_gpe *)unparsed;
-
-	/* Need to have Next Protocol set for interfaces in GPE mode. */
-	if (!gpe->np_applied)
-		return false;
-	/* "The initial version is 0. If a receiver does not support the
-	 * version indicated it MUST drop the packet.
-	 */
-	if (gpe->version != 0)
-		return false;
-	/* "When the O bit is set to 1, the packet is an OAM packet and OAM
-	 * processing MUST occur." However, we don't implement OAM
-	 * processing, thus drop the packet.
-	 */
-	if (gpe->oam_flag)
-		return false;
-
-	*protocol = tun_p_to_eth_p(gpe->next_protocol);
-	if (!*protocol)
-		return false;
-
-	unparsed->vx_flags &= ~VXLAN_GPE_USED_BITS;
-	return true;
-}
-
 static bool vxlan_set_mac(struct vxlan_dev *vxlan,
 			  struct vxlan_sock *vs,
 			  struct sk_buff *skb, __be32 vni)
@@ -1690,8 +1857,9 @@
 	 * used by VXLAN extensions if explicitly requested.
 	 */
 	if (vs->flags & VXLAN_F_GPE) {
-		if (!vxlan_parse_gpe_hdr(&unparsed, &protocol, skb, vs->flags))
+		if (!vxlan_parse_gpe_proto(&unparsed, &protocol))
 			goto drop;
+		unparsed.vx_flags &= ~VXLAN_GPE_USED_BITS;
 		raw_proto = true;
 	}
 
@@ -1924,6 +2092,10 @@
 	ns_olen = request->len - skb_network_offset(request) -
 		sizeof(struct ipv6hdr) - sizeof(*ns);
 	for (i = 0; i < ns_olen-1; i += (ns->opt[i+1]<<3)) {
+		if (!ns->opt[i + 1]) {
+			kfree_skb(reply);
+			return NULL;
+		}
 		if (ns->opt[i] == ND_OPT_SOURCE_LL_ADDR) {
 			daddr = ns->opt + i + sizeof(struct nd_opt_hdr);
 			break;
@@ -1987,6 +2159,7 @@
 	struct neighbour *n;
 	struct nd_msg *msg;
 
+	rcu_read_lock();
 	in6_dev = __in6_dev_get(dev);
 	if (!in6_dev)
 		goto out;
@@ -2038,6 +2211,7 @@
 	}
 
 out:
+	rcu_read_unlock();
 	consume_skb(skb);
 	return NETDEV_TX_OK;
 }
@@ -2276,7 +2450,6 @@
 	bool use_cache = ip_tunnel_dst_cache_usable(skb, info);
 	struct dst_entry *ndst;
 	struct flowi6 fl6;
-	int err;
 
 	if (!sock6)
 		return ERR_PTR(-EIO);
@@ -2299,10 +2472,9 @@
 	fl6.fl6_dport = dport;
 	fl6.fl6_sport = sport;
 
-	err = ipv6_stub->ipv6_dst_lookup(vxlan->net,
-					 sock6->sock->sk,
-					 &ndst, &fl6);
-	if (unlikely(err < 0)) {
+	ndst = ipv6_stub->ipv6_dst_lookup_flow(vxlan->net, sock6->sock->sk,
+					       &fl6, NULL);
+	if (unlikely(IS_ERR(ndst))) {
 		netdev_dbg(dev, "no route to %pI6\n", daddr);
 		return ERR_PTR(-ENETUNREACH);
 	}
@@ -2519,6 +2691,13 @@
 			goto tx_error;
 		}
 
+		if (fan_has_map(&vxlan->fan) && rt->rt_flags & RTCF_LOCAL) {
+			netdev_dbg(dev, "discard fan to localhost %pI4\n",
+				   &dst->sin.sin_addr.s_addr);
+			ip_rt_put(rt);
+			goto tx_free;
+		}
+
 		if (!info) {
 			/* Bypass encapsulation if the destination is local */
 			err = encap_bypass_if_local(skb, dev, vxlan, dst,
@@ -2542,7 +2721,7 @@
 		}
 
 		ndst = &rt->dst;
-		skb_tunnel_check_pmtu(skb, ndst, VXLAN_HEADROOM);
+		skb_tunnel_check_pmtu(skb, ndst, vxlan_headroom(flags & VXLAN_F_GPE));
 
 		tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
 		ttl = ttl ? : ip4_dst_hoplimit(&rt->dst);
@@ -2582,7 +2761,7 @@
 				goto out_unlock;
 		}
 
-		skb_tunnel_check_pmtu(skb, ndst, VXLAN6_HEADROOM);
+		skb_tunnel_check_pmtu(skb, ndst, vxlan_headroom((flags & VXLAN_F_GPE) | VXLAN_F_IPV6));
 
 		tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
 		ttl = ttl ? : ip6_dst_hoplimit(ndst);
@@ -2615,6 +2794,7 @@
 		dev->stats.tx_carrier_errors++;
 	dst_release(ndst);
 	dev->stats.tx_errors++;
+tx_free:
 	kfree_skb(skb);
 }
 
@@ -2669,6 +2849,20 @@
 #endif
 	}
 
+	if (fan_has_map(&vxlan->fan)) {
+		struct vxlan_rdst fan_rdst;
+
+		netdev_dbg(vxlan->dev, "vxlan_xmit p %x d %pM\n",
+			   eth->h_proto, eth->h_dest);
+		if (vxlan_fan_build_rdst(vxlan, skb, &fan_rdst)) {
+			dev->stats.tx_dropped++;
+			kfree_skb(skb);
+			return NETDEV_TX_OK;
+		}
+		vxlan_xmit_one(skb, dev, vni, &fan_rdst, 0);
+		return NETDEV_TX_OK;
+	}
+
 	eth = eth_hdr(skb);
 	f = vxlan_find_mac(vxlan, eth->h_dest, vni);
 	did_rsc = false;
@@ -2781,10 +2975,19 @@
 /* Setup stats when device is created */
 static int vxlan_init(struct net_device *dev)
 {
+	struct vxlan_dev *vxlan = netdev_priv(dev);
+	int err;
+
 	dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
 	if (!dev->tstats)
 		return -ENOMEM;
 
+	err = gro_cells_init(&vxlan->gro_cells, dev);
+	if (err) {
+		free_percpu(dev->tstats);
+		return err;
+	}
+
 	return 0;
 }
 
@@ -2852,8 +3055,10 @@
 			if (!do_all && (f->state & (NUD_PERMANENT | NUD_NOARP)))
 				continue;
 			/* the all_zeros_mac entry is deleted at vxlan_uninit */
-			if (!is_zero_ether_addr(f->eth_addr))
-				vxlan_fdb_destroy(vxlan, f, true, true);
+			if (is_zero_ether_addr(f->eth_addr) &&
+			    f->vni == vxlan->cfg.vni)
+				continue;
+			vxlan_fdb_destroy(vxlan, f, true, true);
 		}
 		spin_unlock_bh(&vxlan->hash_lock[h]);
 	}
@@ -2889,14 +3094,12 @@
 	struct vxlan_rdst *dst = &vxlan->default_dst;
 	struct net_device *lowerdev = __dev_get_by_index(vxlan->net,
 							 dst->remote_ifindex);
-	bool use_ipv6 = !!(vxlan->cfg.flags & VXLAN_F_IPV6);
 
 	/* This check is different than dev->max_mtu, because it looks at
 	 * the lowerdev->mtu, rather than the static dev->max_mtu
 	 */
 	if (lowerdev) {
-		int max_mtu = lowerdev->mtu -
-			      (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM);
+		int max_mtu = lowerdev->mtu - vxlan_headroom(vxlan->cfg.flags);
 		if (new_mtu > max_mtu)
 			return -EINVAL;
 	}
@@ -3045,12 +3248,12 @@
 
 	vxlan->dev = dev;
 
-	gro_cells_init(&vxlan->gro_cells, dev);
-
 	for (h = 0; h < FDB_HASH_SIZE; ++h) {
 		spin_lock_init(&vxlan->hash_lock[h]);
 		INIT_HLIST_HEAD(&vxlan->fdb_head[h]);
 	}
+
+	INIT_LIST_HEAD(&vxlan->fan.fan_maps);
 }
 
 static void vxlan_ether_setup(struct net_device *dev)
@@ -3139,7 +3342,7 @@
 		u32 id = nla_get_u32(data[IFLA_VXLAN_ID]);
 
 		if (id >= VXLAN_N_VID) {
-			NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_ID],
+			NL_SET_ERR_MSG_ATTR(extack, data[IFLA_VXLAN_ID],
 					    "VXLAN ID must be lower than 16777216");
 			return -ERANGE;
 		}
@@ -3150,7 +3353,7 @@
 			= nla_data(data[IFLA_VXLAN_PORT_RANGE]);
 
 		if (ntohs(p->high) < ntohs(p->low)) {
-			NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_PORT_RANGE],
+			NL_SET_ERR_MSG_ATTR(extack, data[IFLA_VXLAN_PORT_RANGE],
 					    "Invalid source port range");
 			return -EINVAL;
 		}
@@ -3160,7 +3363,7 @@
 		enum ifla_vxlan_df df = nla_get_u8(data[IFLA_VXLAN_DF]);
 
 		if (df < 0 || df > VXLAN_DF_MAX) {
-			NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_DF],
+			NL_SET_ERR_MSG_ATTR(extack, data[IFLA_VXLAN_DF],
 					    "Invalid DF attribute");
 			return -EINVAL;
 		}
@@ -3497,11 +3700,11 @@
 	struct vxlan_dev *vxlan = netdev_priv(dev);
 	struct vxlan_rdst *dst = &vxlan->default_dst;
 	unsigned short needed_headroom = ETH_HLEN;
-	bool use_ipv6 = !!(conf->flags & VXLAN_F_IPV6);
 	int max_mtu = ETH_MAX_MTU;
+	u32 flags = conf->flags;
 
 	if (!changelink) {
-		if (conf->flags & VXLAN_F_GPE)
+		if (flags & VXLAN_F_GPE)
 			vxlan_raw_setup(dev);
 		else
 			vxlan_ether_setup(dev);
@@ -3523,9 +3726,11 @@
 		dev->gso_max_segs = lowerdev->gso_max_segs;
 
 		needed_headroom = lowerdev->hard_header_len;
+		needed_headroom += lowerdev->needed_headroom;
+
+		dev->needed_tailroom = lowerdev->needed_tailroom;
 
-		max_mtu = lowerdev->mtu - (use_ipv6 ? VXLAN6_HEADROOM :
-					   VXLAN_HEADROOM);
+		max_mtu = lowerdev->mtu - vxlan_headroom(flags);
 		if (max_mtu < ETH_MIN_MTU)
 			max_mtu = ETH_MIN_MTU;
 
@@ -3536,10 +3741,9 @@
 	if (dev->mtu > max_mtu)
 		dev->mtu = max_mtu;
 
-	if (use_ipv6 || conf->flags & VXLAN_F_COLLECT_METADATA)
-		needed_headroom += VXLAN6_HEADROOM;
-	else
-		needed_headroom += VXLAN_HEADROOM;
+	if (flags & VXLAN_F_COLLECT_METADATA)
+		flags |= VXLAN_F_IPV6;
+	needed_headroom += vxlan_headroom(flags);
 	dev->needed_headroom = needed_headroom;
 
 	memcpy(&vxlan->cfg, conf, sizeof(*conf));
@@ -3602,8 +3806,10 @@
 
 	if (dst->remote_ifindex) {
 		remote_dev = __dev_get_by_index(net, dst->remote_ifindex);
-		if (!remote_dev)
+		if (!remote_dev) {
+			err = -ENODEV;
 			goto errout;
+		}
 
 		err = netdev_upper_dev_link(remote_dev, dev, extack);
 		if (err)
@@ -3722,6 +3928,12 @@
 		conf->remote_ip.sa.sa_family = AF_INET6;
 	}
 
+	if (data[IFLA_VXLAN_FAN_MAP]) {
+		err = vxlan_parse_fan_map(data, vxlan);
+		if (err)
+			return err;
+	}
+
 	if (data[IFLA_VXLAN_LOCAL]) {
 		if (changelink && (conf->saddr.sa.sa_family != AF_INET)) {
 			NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_LOCAL], "New local address family does not match old");
@@ -4058,6 +4270,7 @@
 		nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_UDP_ZERO_CSUM6_RX */
 		nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_REMCSUM_TX */
 		nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_REMCSUM_RX */
+		nla_total_size(sizeof(struct ip_fan_map) * 256) +
 		0;
 }
 
@@ -4104,6 +4317,26 @@
 		}
 	}
 
+	if (fan_has_map(&vxlan->fan)) {
+		struct nlattr *fan_nest;
+		struct ip_fan_map *fan_map;
+
+		fan_nest = nla_nest_start(skb, IFLA_VXLAN_FAN_MAP);
+		if (!fan_nest)
+			goto nla_put_failure;
+		list_for_each_entry_rcu(fan_map, &vxlan->fan.fan_maps, list) {
+			struct ifla_fan_map map;
+
+			map.underlay = fan_map->underlay;
+			map.underlay_prefix = fan_map->underlay_prefix;
+			map.overlay = fan_map->overlay;
+			map.overlay_prefix = fan_map->overlay_prefix;
+			if (nla_put(skb, IFLA_FAN_MAPPING, sizeof(map), &map))
+				goto nla_put_failure;
+		}
+		nla_nest_end(skb, fan_nest);
+	}
+
 	if (nla_put_u8(skb, IFLA_VXLAN_TTL, vxlan->cfg.ttl) ||
 	    nla_put_u8(skb, IFLA_VXLAN_TTL_INHERIT,
 		       !!(vxlan->cfg.flags & VXLAN_F_TTL_INHERIT)) ||
@@ -4399,12 +4632,27 @@
 	return 0;
 }
 
+#ifdef CONFIG_SYSCTL
+static struct ctl_table_header *vxlan_fan_header;
+static unsigned int vxlan_fan_version = 4;
+
+static struct ctl_table vxlan_fan_sysctls[] = {
+	{
+		.procname	= "vxlan",
+		.data		= &vxlan_fan_version,
+		.maxlen		= sizeof(vxlan_fan_version),
+		.mode		= 0444,
+		.proc_handler	= proc_dointvec,
+	},
+	{},
+};
+#endif /* CONFIG_SYSCTL */
+
 static void vxlan_destroy_tunnels(struct net *net, struct list_head *head)
 {
 	struct vxlan_net *vn = net_generic(net, vxlan_net_id);
 	struct vxlan_dev *vxlan, *next;
 	struct net_device *dev, *aux;
-	unsigned int h;
 
 	for_each_netdev_safe(net, dev, aux)
 		if (dev->rtnl_link_ops == &vxlan_link_ops)
@@ -4418,14 +4666,13 @@
 			unregister_netdevice_queue(vxlan->dev, head);
 	}
 
-	for (h = 0; h < PORT_HASH_SIZE; ++h)
-		WARN_ON_ONCE(!hlist_empty(&vn->sock_list[h]));
 }
 
 static void __net_exit vxlan_exit_batch_net(struct list_head *net_list)
 {
 	struct net *net;
 	LIST_HEAD(list);
+	unsigned int h;
 
 	rtnl_lock();
 	list_for_each_entry(net, net_list, exit_list)
@@ -4433,6 +4680,13 @@
 
 	unregister_netdevice_many(&list);
 	rtnl_unlock();
+
+	list_for_each_entry(net, net_list, exit_list) {
+		struct vxlan_net *vn = net_generic(net, vxlan_net_id);
+
+		for (h = 0; h < PORT_HASH_SIZE; ++h)
+			WARN_ON_ONCE(!hlist_empty(&vn->sock_list[h]));
+	}
 }
 
 static struct pernet_operations vxlan_net_ops = {
@@ -4464,7 +4718,20 @@
 	if (rc)
 		goto out4;
 
+#ifdef CONFIG_SYSCTL
+	vxlan_fan_header = register_net_sysctl(&init_net, "net/fan",
+					      vxlan_fan_sysctls);
+	if (!vxlan_fan_header) {
+		rc = -ENOMEM;
+		goto sysctl_failed;
+	}
+#endif /* CONFIG_SYSCTL */
+
 	return 0;
+#ifdef CONFIG_SYSCTL
+sysctl_failed:
+	rtnl_link_unregister(&vxlan_link_ops);
+#endif /* CONFIG_SYSCTL */
 out4:
 	unregister_switchdev_notifier(&vxlan_switchdev_notifier_block);
 out3:
@@ -4478,6 +4745,9 @@
 
 static void __exit vxlan_cleanup_module(void)
 {
+#ifdef CONFIG_SYSCTL
+	unregister_net_sysctl_table(vxlan_fan_header);
+#endif /* CONFIG_SYSCTL */
 	rtnl_link_unregister(&vxlan_link_ops);
 	unregister_switchdev_notifier(&vxlan_switchdev_notifier_block);
 	unregister_netdevice_notifier(&vxlan_notifier_block);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wan/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wan/Kconfig
@@ -200,7 +200,7 @@
 	depends on WANXL && !PREVENT_FIRMWARE_BUILD
 	help
 	  Allows you to rebuild firmware run by the QUICC processor.
-	  It requires as68k, ld68k and hexdump programs.
+	  It requires m68k toolchains and hexdump programs.
 
 	  You should never need this option, say N.
 
@@ -282,6 +282,7 @@
 	tristate "Slic Maxim ds26522 card support"
 	depends on SPI
 	depends on FSL_SOC || ARCH_MXC || ARCH_LAYERSCAPE || COMPILE_TEST
+	select BITREVERSE
 	help
 	  This module initializes and configures the slic maxim card
 	  in T1 or E1 mode.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wan/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wan/Makefile
@@ -40,17 +40,17 @@
 
 ifeq ($(CONFIG_WANXL_BUILD_FIRMWARE),y)
 ifeq ($(ARCH),m68k)
-  AS68K = $(AS)
-  LD68K = $(LD)
+  M68KCC = $(CC)
+  M68KLD = $(LD)
 else
-  AS68K = as68k
-  LD68K = ld68k
+  M68KCC = $(CROSS_COMPILE_M68K)gcc
+  M68KLD = $(CROSS_COMPILE_M68K)ld
 endif
 
 quiet_cmd_build_wanxlfw = BLD FW  $@
       cmd_build_wanxlfw = \
-	$(CPP) -D__ASSEMBLY__ -Wp,-MD,$(depfile) -I$(srctree)/include/uapi $< | $(AS68K) -m68360 -o $(obj)/wanxlfw.o; \
-	$(LD68K) --oformat binary -Ttext 0x1000 $(obj)/wanxlfw.o -o $(obj)/wanxlfw.bin; \
+	$(M68KCC) -D__ASSEMBLY__ -Wp,-MD,$(depfile) -I$(srctree)/include/uapi -c -o $(obj)/wanxlfw.o $<; \
+	$(M68KLD) --oformat binary -Ttext 0x1000 $(obj)/wanxlfw.o -o $(obj)/wanxlfw.bin; \
 	hexdump -ve '"\n" 16/1 "0x%02X,"' $(obj)/wanxlfw.bin | sed 's/0x  ,//g;1s/^/static const u8 firmware[]={/;$$s/,$$/\n};\n/' >$(obj)/wanxlfw.inc; \
 	rm -f $(obj)/wanxlfw.bin $(obj)/wanxlfw.o
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wan/cosa.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wan/cosa.c
@@ -889,6 +889,7 @@
 			chan->tx_status = 1;
 			spin_unlock_irqrestore(&cosa->lock, flags);
 			up(&chan->wsem);
+			kfree(kbuf);
 			return -ERESTARTSYS;
 		}
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wan/farsync.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wan/farsync.c
@@ -569,8 +569,8 @@
 static void fst_process_tx_work_q(unsigned long work_q);
 static void fst_process_int_work_q(unsigned long work_q);
 
-static DECLARE_TASKLET(fst_tx_task, fst_process_tx_work_q, 0);
-static DECLARE_TASKLET(fst_int_task, fst_process_int_work_q, 0);
+static DECLARE_TASKLET_OLD(fst_tx_task, fst_process_tx_work_q);
+static DECLARE_TASKLET_OLD(fst_int_task, fst_process_int_work_q);
 
 static struct fst_card_info *fst_card_array[FST_MAX_CARDS];
 static spinlock_t fst_work_q_lock;
@@ -2613,6 +2613,7 @@
 	for (i = 0; i < card->nports; i++) {
 		struct net_device *dev = port_to_dev(&card->ports[i]);
 		unregister_hdlc_device(dev);
+		free_netdev(dev);
 	}
 
 	fst_disable_intr(card);
@@ -2633,6 +2634,7 @@
 				    card->tx_dma_handle_card);
 	}
 	fst_card_array[card->card_no] = NULL;
+	kfree(card);
 }
 
 static struct pci_driver fst_driver = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wan/fsl_ucc_hdlc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wan/fsl_ucc_hdlc.c
@@ -34,6 +34,8 @@
 #define TDM_PPPOHT_SLIC_MAXIN
 #define RX_BD_ERRORS (R_CD_S | R_OV_S | R_CR_S | R_AB_S | R_NO_S | R_LG_S)
 
+static int uhdlc_close(struct net_device *dev);
+
 static struct ucc_tdm_info utdm_primary_info = {
 	.uf_info = {
 		.tsa = 0,
@@ -73,7 +75,7 @@
 	},
 };
 
-static struct ucc_tdm_info utdm_info[MAX_HDLC_NUM];
+static struct ucc_tdm_info utdm_info[UCC_MAX_NUM];
 
 static int uhdlc_init(struct ucc_hdlc_private *priv)
 {
@@ -204,14 +206,18 @@
 	priv->rx_skbuff = kcalloc(priv->rx_ring_size,
 				  sizeof(*priv->rx_skbuff),
 				  GFP_KERNEL);
-	if (!priv->rx_skbuff)
+	if (!priv->rx_skbuff) {
+		ret = -ENOMEM;
 		goto free_ucc_pram;
+	}
 
 	priv->tx_skbuff = kcalloc(priv->tx_ring_size,
 				  sizeof(*priv->tx_skbuff),
 				  GFP_KERNEL);
-	if (!priv->tx_skbuff)
+	if (!priv->tx_skbuff) {
+		ret = -ENOMEM;
 		goto free_rx_skbuff;
+	}
 
 	priv->skb_curtx = 0;
 	priv->skb_dirtytx = 0;
@@ -245,6 +251,11 @@
 		ret = -ENOMEM;
 		goto free_riptr;
 	}
+	if (riptr != (u16)riptr || tiptr != (u16)tiptr) {
+		dev_err(priv->dev, "MURAM allocation out of addressable range\n");
+		ret = -ENOMEM;
+		goto free_tiptr;
+	}
 
 	/* Set RIPTR, TIPTR */
 	iowrite16be(riptr, &priv->ucc_pram->riptr);
@@ -701,6 +712,7 @@
 	hdlc_device *hdlc = dev_to_hdlc(dev);
 	struct ucc_hdlc_private *priv = hdlc->priv;
 	struct ucc_tdm *utdm = priv->utdm;
+	int rc = 0;
 
 	if (priv->hdlc_busy != 1) {
 		if (request_irq(priv->ut_info->uf_info.irq,
@@ -724,10 +736,13 @@
 		napi_enable(&priv->napi);
 		netdev_reset_queue(dev);
 		netif_start_queue(dev);
-		hdlc_open(dev);
+
+		rc = hdlc_open(dev);
+		if (rc)
+			uhdlc_close(dev);
 	}
 
-	return 0;
+	return rc;
 }
 
 static void uhdlc_memclean(struct ucc_hdlc_private *priv)
@@ -817,6 +832,8 @@
 	netdev_reset_queue(dev);
 	priv->hdlc_busy = 0;
 
+	hdlc_close(dev);
+
 	return 0;
 }
 
@@ -1240,9 +1257,11 @@
 free_dev:
 	free_netdev(dev);
 undo_uhdlc_init:
-	iounmap(utdm->siram);
+	if (utdm)
+		iounmap(utdm->siram);
 unmap_si_regs:
-	iounmap(utdm->si_regs);
+	if (utdm)
+		iounmap(utdm->si_regs);
 free_utdm:
 	if (uhdlc_priv->tsa)
 		kfree(utdm);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wan/hdlc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wan/hdlc.c
@@ -46,7 +46,15 @@
 static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev,
 		    struct packet_type *p, struct net_device *orig_dev)
 {
-	struct hdlc_device *hdlc = dev_to_hdlc(dev);
+	struct hdlc_device *hdlc;
+
+	/* First make sure "dev" is an HDLC device */
+	if (!(dev->priv_flags & IFF_WAN_HDLC)) {
+		kfree_skb(skb);
+		return NET_RX_SUCCESS;
+	}
+
+	hdlc = dev_to_hdlc(dev);
 
 	if (!net_eq(dev_net(dev), &init_net)) {
 		kfree_skb(skb);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wan/hdlc_cisco.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wan/hdlc_cisco.c
@@ -118,6 +118,7 @@
 	skb_put(skb, sizeof(struct cisco_packet));
 	skb->priority = TC_PRIO_CONTROL;
 	skb->dev = dev;
+	skb->protocol = htons(ETH_P_HDLC);
 	skb_reset_network_header(skb);
 
 	dev_queue_xmit(skb);
@@ -370,6 +371,7 @@
 		memcpy(&state(hdlc)->settings, &new_settings, size);
 		spin_lock_init(&state(hdlc)->lock);
 		dev->header_ops = &cisco_header_ops;
+		dev->hard_header_len = sizeof(struct hdlc_header);
 		dev->type = ARPHRD_CISCO;
 		call_netdevice_notifiers(NETDEV_POST_TYPE_CHANGE, dev);
 		netif_dormant_on(dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wan/hdlc_fr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wan/hdlc_fr.c
@@ -273,63 +273,69 @@
 
 static int fr_hard_header(struct sk_buff **skb_p, u16 dlci)
 {
-	u16 head_len;
 	struct sk_buff *skb = *skb_p;
 
-	switch (skb->protocol) {
-	case cpu_to_be16(NLPID_CCITT_ANSI_LMI):
-		head_len = 4;
-		skb_push(skb, head_len);
-		skb->data[3] = NLPID_CCITT_ANSI_LMI;
-		break;
-
-	case cpu_to_be16(NLPID_CISCO_LMI):
-		head_len = 4;
-		skb_push(skb, head_len);
-		skb->data[3] = NLPID_CISCO_LMI;
-		break;
-
-	case cpu_to_be16(ETH_P_IP):
-		head_len = 4;
-		skb_push(skb, head_len);
-		skb->data[3] = NLPID_IP;
-		break;
-
-	case cpu_to_be16(ETH_P_IPV6):
-		head_len = 4;
-		skb_push(skb, head_len);
-		skb->data[3] = NLPID_IPV6;
-		break;
-
-	case cpu_to_be16(ETH_P_802_3):
-		head_len = 10;
-		if (skb_headroom(skb) < head_len) {
-			struct sk_buff *skb2 = skb_realloc_headroom(skb,
-								    head_len);
+	if (!skb->dev) { /* Control packets */
+		switch (dlci) {
+		case LMI_CCITT_ANSI_DLCI:
+			skb_push(skb, 4);
+			skb->data[3] = NLPID_CCITT_ANSI_LMI;
+			break;
+
+		case LMI_CISCO_DLCI:
+			skb_push(skb, 4);
+			skb->data[3] = NLPID_CISCO_LMI;
+			break;
+
+		default:
+			return -EINVAL;
+		}
+
+	} else if (skb->dev->type == ARPHRD_DLCI) {
+		switch (skb->protocol) {
+		case htons(ETH_P_IP):
+			skb_push(skb, 4);
+			skb->data[3] = NLPID_IP;
+			break;
+
+		case htons(ETH_P_IPV6):
+			skb_push(skb, 4);
+			skb->data[3] = NLPID_IPV6;
+			break;
+
+		default:
+			skb_push(skb, 10);
+			skb->data[3] = FR_PAD;
+			skb->data[4] = NLPID_SNAP;
+			/* OUI 00-00-00 indicates an Ethertype follows */
+			skb->data[5] = 0x00;
+			skb->data[6] = 0x00;
+			skb->data[7] = 0x00;
+			/* This should be an Ethertype: */
+			*(__be16 *)(skb->data + 8) = skb->protocol;
+		}
+
+	} else if (skb->dev->type == ARPHRD_ETHER) {
+		if (skb_headroom(skb) < 10) {
+			struct sk_buff *skb2 = skb_realloc_headroom(skb, 10);
 			if (!skb2)
 				return -ENOBUFS;
 			dev_kfree_skb(skb);
 			skb = *skb_p = skb2;
 		}
-		skb_push(skb, head_len);
+		skb_push(skb, 10);
 		skb->data[3] = FR_PAD;
 		skb->data[4] = NLPID_SNAP;
-		skb->data[5] = FR_PAD;
+		/* OUI 00-80-C2 stands for the 802.1 organization */
+		skb->data[5] = 0x00;
 		skb->data[6] = 0x80;
 		skb->data[7] = 0xC2;
+		/* PID 00-07 stands for Ethernet frames without FCS */
 		skb->data[8] = 0x00;
-		skb->data[9] = 0x07; /* bridged Ethernet frame w/out FCS */
-		break;
+		skb->data[9] = 0x07;
 
-	default:
-		head_len = 10;
-		skb_push(skb, head_len);
-		skb->data[3] = FR_PAD;
-		skb->data[4] = NLPID_SNAP;
-		skb->data[5] = FR_PAD;
-		skb->data[6] = FR_PAD;
-		skb->data[7] = FR_PAD;
-		*(__be16*)(skb->data + 8) = skb->protocol;
+	} else {
+		return -EINVAL;
 	}
 
 	dlci_to_q922(skb->data, dlci);
@@ -425,14 +431,16 @@
 				skb_put(skb, pad);
 				memset(skb->data + len, 0, pad);
 			}
-			skb->protocol = cpu_to_be16(ETH_P_802_3);
 		}
+		skb->dev = dev;
 		if (!fr_hard_header(&skb, pvc->dlci)) {
 			dev->stats.tx_bytes += skb->len;
 			dev->stats.tx_packets++;
 			if (pvc->state.fecn) /* TX Congestion counter */
 				dev->stats.tx_compressed++;
 			skb->dev = pvc->frad;
+			skb->protocol = htons(ETH_P_HDLC);
+			skb_reset_network_header(skb);
 			dev_queue_xmit(skb);
 			return NETDEV_TX_OK;
 		}
@@ -492,10 +500,8 @@
 	memset(skb->data, 0, len);
 	skb_reserve(skb, 4);
 	if (lmi == LMI_CISCO) {
-		skb->protocol = cpu_to_be16(NLPID_CISCO_LMI);
 		fr_hard_header(&skb, LMI_CISCO_DLCI);
 	} else {
-		skb->protocol = cpu_to_be16(NLPID_CCITT_ANSI_LMI);
 		fr_hard_header(&skb, LMI_CCITT_ANSI_DLCI);
 	}
 	data = skb_tail_pointer(skb);
@@ -555,6 +561,7 @@
 	skb_put(skb, i);
 	skb->priority = TC_PRIO_CONTROL;
 	skb->dev = dev;
+	skb->protocol = htons(ETH_P_HDLC);
 	skb_reset_network_header(skb);
 
 	dev_queue_xmit(skb);
@@ -1041,7 +1048,7 @@
 {
 	dev->type = ARPHRD_DLCI;
 	dev->flags = IFF_POINTOPOINT;
-	dev->hard_header_len = 10;
+	dev->hard_header_len = 0;
 	dev->addr_len = 2;
 	netif_keep_dst(dev);
 }
@@ -1093,6 +1100,7 @@
 	dev->mtu = HDLC_MAX_MTU;
 	dev->min_mtu = 68;
 	dev->max_mtu = HDLC_MAX_MTU;
+	dev->needed_headroom = 10;
 	dev->priv_flags |= IFF_NO_QUEUE;
 	dev->ml_priv = pvc;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wan/hdlc_ppp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wan/hdlc_ppp.c
@@ -251,6 +251,7 @@
 
 	skb->priority = TC_PRIO_CONTROL;
 	skb->dev = dev;
+	skb->protocol = htons(ETH_P_HDLC);
 	skb_reset_network_header(skb);
 	skb_queue_tail(&tx_queue, skb);
 }
@@ -383,11 +384,8 @@
 	}
 
 	for (opt = data; len; len -= opt[1], opt += opt[1]) {
-		if (len < 2 || len < opt[1]) {
-			dev->stats.rx_errors++;
-			kfree(out);
-			return; /* bad packet, drop silently */
-		}
+		if (len < 2 || opt[1] < 2 || len < opt[1])
+			goto err_out;
 
 		if (pid == PID_LCP)
 			switch (opt[0]) {
@@ -395,6 +393,8 @@
 				continue; /* MRU always OK and > 1500 bytes? */
 
 			case LCP_OPTION_ACCM: /* async control character map */
+				if (opt[1] < sizeof(valid_accm))
+					goto err_out;
 				if (!memcmp(opt, valid_accm,
 					    sizeof(valid_accm)))
 					continue;
@@ -406,6 +406,8 @@
 				}
 				break;
 			case LCP_OPTION_MAGIC:
+				if (len < 6)
+					goto err_out;
 				if (opt[1] != 6 || (!opt[2] && !opt[3] &&
 						    !opt[4] && !opt[5]))
 					break; /* reject invalid magic number */
@@ -424,6 +426,11 @@
 		ppp_cp_event(dev, pid, RCR_GOOD, CP_CONF_ACK, id, req_len, data);
 
 	kfree(out);
+	return;
+
+err_out:
+	dev->stats.rx_errors++;
+	kfree(out);
 }
 
 static int ppp_rx(struct sk_buff *skb)
@@ -562,6 +569,13 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&ppp->lock, flags);
+	/* mod_timer could be called after we entered this function but
+	 * before we got the lock.
+	 */
+	if (timer_pending(&proto->timer)) {
+		spin_unlock_irqrestore(&ppp->lock, flags);
+		return;
+	}
 	switch (proto->state) {
 	case STOPPING:
 	case REQ_SENT:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wan/hdlc_raw_eth.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wan/hdlc_raw_eth.c
@@ -99,6 +99,7 @@
 		old_qlen = dev->tx_queue_len;
 		ether_setup(dev);
 		dev->tx_queue_len = old_qlen;
+		dev->priv_flags &= ~IFF_TX_SKB_SHARING;
 		eth_hw_addr_random(dev);
 		call_netdevice_notifiers(NETDEV_POST_TYPE_CHANGE, dev);
 		netif_dormant_off(dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wan/hdlc_x25.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wan/hdlc_x25.c
@@ -62,10 +62,13 @@
 {
 	unsigned char *ptr;
 
-	skb_push(skb, 1);
-
-	if (skb_cow(skb, 1))
+	if (skb_cow(skb, 1)) {
+		kfree_skb(skb);
 		return NET_RX_DROP;
+	}
+
+	skb_push(skb, 1);
+	skb_reset_network_header(skb);
 
 	ptr  = skb->data;
 	*ptr = X25_IFACE_DATA;
@@ -79,6 +82,13 @@
 static void x25_data_transmit(struct net_device *dev, struct sk_buff *skb)
 {
 	hdlc_device *hdlc = dev_to_hdlc(dev);
+
+	skb_reset_network_header(skb);
+	skb->protocol = hdlc_type_trans(skb, dev);
+
+	if (dev_nit_active(dev))
+		dev_queue_xmit_nit(skb, dev);
+
 	hdlc->xmit(skb, dev); /* Ignore return value :-( */
 }
 
@@ -93,6 +103,7 @@
 	switch (skb->data[0]) {
 	case X25_IFACE_DATA:	/* Data to be transmitted */
 		skb_pull(skb, 1);
+		skb_reset_network_header(skb);
 		if ((result = lapb_data_request(dev, skb)) != LAPB_OK)
 			dev_kfree_skb(skb);
 		return NETDEV_TX_OK;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wan/ixp4xx_hss.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wan/ixp4xx_hss.c
@@ -258,7 +258,7 @@
 	struct hss_plat_info *plat;
 	buffer_t *rx_buff_tab[RX_DESCS], *tx_buff_tab[TX_DESCS];
 	struct desc *desc_tab;	/* coherent */
-	u32 desc_tab_phys;
+	dma_addr_t desc_tab_phys;
 	unsigned int id;
 	unsigned int clock_type, clock_rate, loopback;
 	unsigned int initialized, carrier;
@@ -858,7 +858,7 @@
 		dev->stats.tx_dropped++;
 		return NETDEV_TX_OK;
 	}
-	memcpy_swab32(mem, (u32 *)((int)skb->data & ~3), bytes / 4);
+	memcpy_swab32(mem, (u32 *)((uintptr_t)skb->data & ~3), bytes / 4);
 	dev_kfree_skb(skb);
 #endif
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wan/lapbether.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wan/lapbether.c
@@ -51,6 +51,8 @@
 	struct list_head	node;
 	struct net_device	*ethdev;	/* link to ethernet device */
 	struct net_device	*axdev;		/* lapbeth device (lapb#) */
+	bool			up;
+	spinlock_t		up_lock;	/* Protects "up" */
 };
 
 static LIST_HEAD(lapbeth_devices);
@@ -98,8 +100,9 @@
 	rcu_read_lock();
 	lapbeth = lapbeth_get_x25_dev(dev);
 	if (!lapbeth)
-		goto drop_unlock;
-	if (!netif_running(lapbeth->axdev))
+		goto drop_unlock_rcu;
+	spin_lock_bh(&lapbeth->up_lock);
+	if (!lapbeth->up)
 		goto drop_unlock;
 
 	len = skb->data[0] + skb->data[1] * 256;
@@ -114,11 +117,14 @@
 		goto drop_unlock;
 	}
 out:
+	spin_unlock_bh(&lapbeth->up_lock);
 	rcu_read_unlock();
 	return 0;
 drop_unlock:
 	kfree_skb(skb);
 	goto out;
+drop_unlock_rcu:
+	rcu_read_unlock();
 drop:
 	kfree_skb(skb);
 	return 0;
@@ -128,10 +134,12 @@
 {
 	unsigned char *ptr;
 
-	skb_push(skb, 1);
-
-	if (skb_cow(skb, 1))
+	if (skb_cow(skb, 1)) {
+		kfree_skb(skb);
 		return NET_RX_DROP;
+	}
+
+	skb_push(skb, 1);
 
 	ptr  = skb->data;
 	*ptr = X25_IFACE_DATA;
@@ -146,13 +154,17 @@
 static netdev_tx_t lapbeth_xmit(struct sk_buff *skb,
 				      struct net_device *dev)
 {
+	struct lapbethdev *lapbeth = netdev_priv(dev);
 	int err;
 
-	/*
-	 * Just to be *really* sure not to send anything if the interface
-	 * is down, the ethernet device may have gone.
+	spin_lock_bh(&lapbeth->up_lock);
+	if (!lapbeth->up)
+		goto drop;
+
+	/* There should be a pseudo header of 1 byte added by upper layers.
+	 * Check to make sure it is there before reading it.
 	 */
-	if (!netif_running(dev))
+	if (skb->len < 1)
 		goto drop;
 
 	switch (skb->data[0]) {
@@ -177,6 +189,7 @@
 		goto drop;
 	}
 out:
+	spin_unlock_bh(&lapbeth->up_lock);
 	return NETDEV_TX_OK;
 drop:
 	kfree_skb(skb);
@@ -190,8 +203,6 @@
 	struct net_device *dev;
 	int size = skb->len;
 
-	skb->protocol = htons(ETH_P_X25);
-
 	ptr = skb_push(skb, 2);
 
 	*ptr++ = size % 256;
@@ -202,6 +213,10 @@
 
 	skb->dev = dev = lapbeth->ethdev;
 
+	skb->protocol = htons(ETH_P_DEC);
+
+	skb_reset_network_header(skb);
+
 	dev_hard_header(skb, dev, ETH_P_DEC, bcast_addr, NULL, 0);
 
 	dev_queue_xmit(skb);
@@ -266,6 +281,7 @@
  */
 static int lapbeth_open(struct net_device *dev)
 {
+	struct lapbethdev *lapbeth = netdev_priv(dev);
 	int err;
 
 	if ((err = lapb_register(dev, &lapbeth_callbacks)) != LAPB_OK) {
@@ -273,15 +289,21 @@
 		return -ENODEV;
 	}
 
-	netif_start_queue(dev);
+	spin_lock_bh(&lapbeth->up_lock);
+	lapbeth->up = true;
+	spin_unlock_bh(&lapbeth->up_lock);
+
 	return 0;
 }
 
 static int lapbeth_close(struct net_device *dev)
 {
+	struct lapbethdev *lapbeth = netdev_priv(dev);
 	int err;
 
-	netif_stop_queue(dev);
+	spin_lock_bh(&lapbeth->up_lock);
+	lapbeth->up = false;
+	spin_unlock_bh(&lapbeth->up_lock);
 
 	if ((err = lapb_unregister(dev)) != LAPB_OK)
 		pr_err("lapb_unregister error: %d\n", err);
@@ -303,7 +325,7 @@
 	dev->netdev_ops	     = &lapbeth_netdev_ops;
 	dev->needs_free_netdev = true;
 	dev->type            = ARPHRD_X25;
-	dev->hard_header_len = 3;
+	dev->hard_header_len = 0;
 	dev->mtu             = 1000;
 	dev->addr_len        = 0;
 }
@@ -319,17 +341,33 @@
 
 	ASSERT_RTNL();
 
+	if (dev->type != ARPHRD_ETHER)
+		return -EINVAL;
+
 	ndev = alloc_netdev(sizeof(*lapbeth), "lapb%d", NET_NAME_UNKNOWN,
 			    lapbeth_setup);
 	if (!ndev)
 		goto out;
 
+	/* When transmitting data:
+	 * first this driver removes a pseudo header of 1 byte,
+	 * then the lapb module prepends an LAPB header of at most 3 bytes,
+	 * then this driver prepends a length field of 2 bytes,
+	 * then the underlying Ethernet device prepends its own header.
+	 */
+	ndev->needed_headroom = -1 + 3 + 2 + dev->hard_header_len
+					   + dev->needed_headroom;
+	ndev->needed_tailroom = dev->needed_tailroom;
+
 	lapbeth = netdev_priv(ndev);
 	lapbeth->axdev = ndev;
 
 	dev_hold(dev);
 	lapbeth->ethdev = dev;
 
+	lapbeth->up = false;
+	spin_lock_init(&lapbeth->up_lock);
+
 	rc = -EIO;
 	if (register_netdevice(ndev))
 		goto fail;
@@ -368,7 +406,7 @@
 	if (dev_net(dev) != &init_net)
 		return NOTIFY_DONE;
 
-	if (!dev_is_ethdev(dev))
+	if (!dev_is_ethdev(dev) && !lapbeth_get_x25_dev(dev))
 		return NOTIFY_DONE;
 
 	switch (event) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wan/lmc/lmc_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wan/lmc/lmc_main.c
@@ -912,6 +912,8 @@
         break;
     default:
 	printk(KERN_WARNING "%s: LMC UNKNOWN CARD!\n", dev->name);
+	unregister_hdlc_device(dev);
+	return -EIO;
         break;
     }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wan/lmc/lmc_proto.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wan/lmc/lmc_proto.c
@@ -101,17 +101,13 @@
     switch(sc->if_type){
     case LMC_PPP:
 	    return hdlc_type_trans(skb, sc->lmc_device);
-	    break;
     case LMC_NET:
         return htons(ETH_P_802_2);
-        break;
     case LMC_RAW: /* Packet type for skbuff kind of useless */
         return htons(ETH_P_802_2);
-        break;
     default:
         printk(KERN_WARNING "%s: No protocol set for this interface, assuming 802.2 (which is wrong!!)\n", sc->name);
         return htons(ETH_P_802_2);
-        break;
     }
     lmc_trace(sc->lmc_device, "lmc_proto_tye out");
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wan/sdla.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wan/sdla.c
@@ -708,7 +708,7 @@
 
 					spin_lock_irqsave(&sdla_lock, flags);
 					SDLA_WINDOW(dev, addr);
-					pbuf = (void *)(((int) dev->mem_start) + (addr & SDLA_ADDR_MASK));
+					pbuf = (void *)(dev->mem_start + (addr & SDLA_ADDR_MASK));
 					__sdla_write(dev, pbuf->buf_addr, skb->data, skb->len);
 					SDLA_WINDOW(dev, addr);
 					pbuf->opp_flag = 1;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wan/x25_asy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wan/x25_asy.c
@@ -183,7 +183,7 @@
 	netif_wake_queue(sl->dev);
 }
 
-/* Send one completely decapsulated IP datagram to the IP layer. */
+/* Send an LAPB frame to the LAPB module to process. */
 
 static void x25_asy_bump(struct x25_asy *sl)
 {
@@ -195,13 +195,12 @@
 	count = sl->rcount;
 	dev->stats.rx_bytes += count;
 
-	skb = dev_alloc_skb(count+1);
+	skb = dev_alloc_skb(count);
 	if (skb == NULL) {
 		netdev_warn(sl->dev, "memory squeeze, dropping packet\n");
 		dev->stats.rx_dropped++;
 		return;
 	}
-	skb_push(skb, 1);	/* LAPB internal control */
 	skb_put_data(skb, sl->rbuff, count);
 	skb->protocol = x25_type_trans(skb, sl->dev);
 	err = lapb_data_received(skb->dev, skb);
@@ -209,7 +208,6 @@
 		kfree_skb(skb);
 		printk(KERN_DEBUG "x25_asy: data received err - %d\n", err);
 	} else {
-		netif_rx(skb);
 		dev->stats.rx_packets++;
 	}
 }
@@ -356,12 +354,21 @@
  */
 
 /*
- *	Called when I frame data arrives. We did the work above - throw it
- *	at the net layer.
+ *	Called when I frame data arrive. We add a pseudo header for upper
+ *	layers and pass it to upper layers.
  */
 
 static int x25_asy_data_indication(struct net_device *dev, struct sk_buff *skb)
 {
+	if (skb_cow(skb, 1)) {
+		kfree_skb(skb);
+		return NET_RX_DROP;
+	}
+	skb_push(skb, 1);
+	skb->data[0] = X25_IFACE_DATA;
+
+	skb->protocol = x25_type_trans(skb, dev);
+
 	return netif_rx(skb);
 }
 
@@ -657,7 +664,7 @@
 	switch (s) {
 	case X25_END:
 		if (!test_and_clear_bit(SLF_ERROR, &sl->flags) &&
-		    sl->rcount > 2)
+		    sl->rcount >= 2)
 			x25_asy_bump(sl);
 		clear_bit(SLF_ESCAPE, &sl->flags);
 		sl->rcount = 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wan/z85230.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wan/z85230.c
@@ -702,7 +702,7 @@
 irqreturn_t z8530_interrupt(int irq, void *dev_id)
 {
 	struct z8530_dev *dev=dev_id;
-	u8 uninitialized_var(intr);
+	u8 intr;
 	static volatile int locker=0;
 	int work=0;
 	struct z8530_irqhandler *irqs;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wimax/i2400m/op-rfkill.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wimax/i2400m/op-rfkill.c
@@ -86,7 +86,7 @@
 	if (cmd == NULL)
 		goto error_alloc;
 	cmd->hdr.type = cpu_to_le16(I2400M_MT_CMD_RF_CONTROL);
-	cmd->hdr.length = sizeof(cmd->sw_rf);
+	cmd->hdr.length = cpu_to_le16(sizeof(cmd->sw_rf));
 	cmd->hdr.version = cpu_to_le16(I2400M_L3L4_VERSION);
 	cmd->sw_rf.hdr.type = cpu_to_le16(I2400M_TLV_RF_OPERATION);
 	cmd->sw_rf.hdr.length = cpu_to_le16(sizeof(cmd->sw_rf.status));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wimax/i2400m/usb-fw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wimax/i2400m/usb-fw.c
@@ -354,6 +354,7 @@
 		usb_autopm_put_interface(i2400mu->usb_iface);
 	d_fnend(8, dev, "(i2400m %p ack %p size %zu) = %ld\n",
 		i2400m, ack, ack_size, (long) result);
+	usb_put_urb(&notif_urb);
 	return result;
 
 error_exceeded:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/Kconfig
@@ -30,12 +30,12 @@
 	  Right now only ath9k makes use of this.
 
 config ATH_TRACEPOINTS
-       bool "Atheros wireless tracing"
-       depends on ATH_DEBUG
-       depends on EVENT_TRACING
-       ---help---
-	 This option enables tracepoints for atheros wireless drivers.
-	 Currently, ath9k makes use of this facility.
+	bool "Atheros wireless tracing"
+	depends on ATH_DEBUG
+	depends on EVENT_TRACING
+	---help---
+	  This option enables tracepoints for atheros wireless drivers.
+	  Currently, ath9k makes use of this facility.
 
 config ATH_REG_DYNAMIC_USER_REG_HINTS
 	bool "Atheros dynamic user regulatory hints"
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ar5523/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ar5523/Kconfig
@@ -1,9 +1,9 @@
 # SPDX-License-Identifier: ISC
 config AR5523
-       tristate "Atheros AR5523 wireless driver support"
-       depends on MAC80211 && USB
-       select ATH_COMMON
-       select FW_LOADER
-       ---help---
-	 This module add support for AR5523 based USB dongles such as D-Link
-	 DWL-G132, Netgear WPN111 and many more.
+	tristate "Atheros AR5523 wireless driver support"
+	depends on MAC80211 && USB
+	select ATH_COMMON
+	select FW_LOADER
+	---help---
+	  This module add support for AR5523 based USB dongles such as D-Link
+	  DWL-G132, Netgear WPN111 and many more.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ar5523/ar5523.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ar5523/ar5523.c
@@ -153,6 +153,10 @@
 			ar5523_err(ar, "Invalid reply to WDCMSG_TARGET_START");
 			return;
 		}
+		if (!cmd->odata) {
+			ar5523_err(ar, "Unexpected WDCMSG_TARGET_START reply");
+			return;
+		}
 		memcpy(cmd->odata, hdr + 1, sizeof(u32));
 		cmd->olen = sizeof(u32);
 		cmd->res = 0;
@@ -237,6 +241,11 @@
 	}
 }
 
+static void ar5523_cancel_tx_cmd(struct ar5523 *ar)
+{
+	usb_kill_urb(ar->tx_cmd.urb_tx);
+}
+
 static int ar5523_cmd(struct ar5523 *ar, u32 code, const void *idata,
 		      int ilen, void *odata, int olen, int flags)
 {
@@ -255,7 +264,8 @@
 
 	if (flags & AR5523_CMD_FLAG_MAGIC)
 		hdr->magic = cpu_to_be32(1 << 24);
-	memcpy(hdr + 1, idata, ilen);
+	if (ilen)
+		memcpy(hdr + 1, idata, ilen);
 
 	cmd->odata = odata;
 	cmd->olen = olen;
@@ -275,6 +285,7 @@
 	}
 
 	if (!wait_for_completion_timeout(&cmd->done, 2 * HZ)) {
+		ar5523_cancel_tx_cmd(ar);
 		cmd->odata = NULL;
 		ar5523_err(ar, "timeout waiting for command %02x reply\n",
 			   code);
@@ -1579,6 +1590,20 @@
 	struct ar5523 *ar;
 	int error = -ENOMEM;
 
+	static const u8 bulk_ep_addr[] = {
+		AR5523_CMD_TX_PIPE | USB_DIR_OUT,
+		AR5523_DATA_TX_PIPE | USB_DIR_OUT,
+		AR5523_CMD_RX_PIPE | USB_DIR_IN,
+		AR5523_DATA_RX_PIPE | USB_DIR_IN,
+		0};
+
+	if (!usb_check_bulk_endpoints(intf, bulk_ep_addr)) {
+		dev_err(&dev->dev,
+			"Could not find all expected endpoints\n");
+		error = -ENODEV;
+		goto out;
+	}
+
 	/*
 	 * Load firmware if the device requires it.  This will return
 	 * -ENXIO on success and we'll get called back afer the usb
@@ -1769,6 +1794,8 @@
 	AR5523_DEVICE_UX(0x0846, 0x4300),	/* Netgear / WG111U */
 	AR5523_DEVICE_UG(0x0846, 0x4250),	/* Netgear / WG111T */
 	AR5523_DEVICE_UG(0x0846, 0x5f00),	/* Netgear / WPN111 */
+	AR5523_DEVICE_UG(0x083a, 0x4506),	/* SMC / EZ Connect
+						   SMCWUSBT-G2 */
 	AR5523_DEVICE_UG(0x157e, 0x3006),	/* Umedia / AR5523_1 */
 	AR5523_DEVICE_UX(0x157e, 0x3205),	/* Umedia / AR5523_2 */
 	AR5523_DEVICE_UG(0x157e, 0x3006),	/* Umedia / TEW444UBEU */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath.h
@@ -197,12 +197,13 @@
 bool ath_is_mybeacon(struct ath_common *common, struct ieee80211_hdr *hdr);
 
 void ath_hw_setbssidmask(struct ath_common *common);
-void ath_key_delete(struct ath_common *common, struct ieee80211_key_conf *key);
+void ath_key_delete(struct ath_common *common, u8 hw_key_idx);
 int ath_key_config(struct ath_common *common,
 			  struct ieee80211_vif *vif,
 			  struct ieee80211_sta *sta,
 			  struct ieee80211_key_conf *key);
 bool ath_hw_keyreset(struct ath_common *common, u16 entry);
+bool ath_hw_keysetmac(struct ath_common *common, u16 entry, const u8 *mac);
 void ath_hw_cycle_counters_update(struct ath_common *common);
 int32_t ath_hw_get_listen_time(struct ath_common *common);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath10k/ce.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath10k/ce.c
@@ -1299,29 +1299,24 @@
 	struct ath10k_hw_ce_host_wm_regs *wm_regs = ar->hw_ce_regs->wm_regs;
 	u32 ctrl_addr = ce_state->ctrl_addr;
 
-	spin_lock_bh(&ce->ce_lock);
-
-	/* Clear the copy-complete interrupts that will be handled here. */
+	/*
+	 * Clear before handling
+	 *
+	 * Misc CE interrupts are not being handled, but still need
+	 * to be cleared.
+	 *
+	 * NOTE: When the last copy engine interrupt is cleared the
+	 * hardware will go to sleep.  Once this happens any access to
+	 * the CE registers can cause a hardware fault.
+	 */
 	ath10k_ce_engine_int_status_clear(ar, ctrl_addr,
-					  wm_regs->cc_mask);
-
-	spin_unlock_bh(&ce->ce_lock);
+					  wm_regs->cc_mask | wm_regs->wm_mask);
 
 	if (ce_state->recv_cb)
 		ce_state->recv_cb(ce_state);
 
 	if (ce_state->send_cb)
 		ce_state->send_cb(ce_state);
-
-	spin_lock_bh(&ce->ce_lock);
-
-	/*
-	 * Misc CE interrupts are not being handled, but still need
-	 * to be cleared.
-	 */
-	ath10k_ce_engine_int_status_clear(ar, ctrl_addr, wm_regs->wm_mask);
-
-	spin_unlock_bh(&ce->ce_lock);
 }
 EXPORT_SYMBOL(ath10k_ce_per_engine_service);
 
@@ -1372,45 +1367,55 @@
 	ath10k_ce_watermark_intr_disable(ar, ctrl_addr);
 }
 
-int ath10k_ce_disable_interrupts(struct ath10k *ar)
+void ath10k_ce_disable_interrupt(struct ath10k *ar, int ce_id)
 {
 	struct ath10k_ce *ce = ath10k_ce_priv(ar);
 	struct ath10k_ce_pipe *ce_state;
 	u32 ctrl_addr;
-	int ce_id;
 
-	for (ce_id = 0; ce_id < CE_COUNT; ce_id++) {
-		ce_state  = &ce->ce_states[ce_id];
-		if (ce_state->attr_flags & CE_ATTR_POLL)
-			continue;
+	ce_state  = &ce->ce_states[ce_id];
+	if (ce_state->attr_flags & CE_ATTR_POLL)
+		return;
 
-		ctrl_addr = ath10k_ce_base_address(ar, ce_id);
+	ctrl_addr = ath10k_ce_base_address(ar, ce_id);
 
-		ath10k_ce_copy_complete_intr_disable(ar, ctrl_addr);
-		ath10k_ce_error_intr_disable(ar, ctrl_addr);
-		ath10k_ce_watermark_intr_disable(ar, ctrl_addr);
-	}
+	ath10k_ce_copy_complete_intr_disable(ar, ctrl_addr);
+	ath10k_ce_error_intr_disable(ar, ctrl_addr);
+	ath10k_ce_watermark_intr_disable(ar, ctrl_addr);
+}
+EXPORT_SYMBOL(ath10k_ce_disable_interrupt);
 
-	return 0;
+void ath10k_ce_disable_interrupts(struct ath10k *ar)
+{
+	int ce_id;
+
+	for (ce_id = 0; ce_id < CE_COUNT; ce_id++)
+		ath10k_ce_disable_interrupt(ar, ce_id);
 }
 EXPORT_SYMBOL(ath10k_ce_disable_interrupts);
 
-void ath10k_ce_enable_interrupts(struct ath10k *ar)
+void ath10k_ce_enable_interrupt(struct ath10k *ar, int ce_id)
 {
 	struct ath10k_ce *ce = ath10k_ce_priv(ar);
-	int ce_id;
 	struct ath10k_ce_pipe *ce_state;
 
+	ce_state  = &ce->ce_states[ce_id];
+	if (ce_state->attr_flags & CE_ATTR_POLL)
+		return;
+
+	ath10k_ce_per_engine_handler_adjust(ce_state);
+}
+EXPORT_SYMBOL(ath10k_ce_enable_interrupt);
+
+void ath10k_ce_enable_interrupts(struct ath10k *ar)
+{
+	int ce_id;
+
 	/* Enable interrupts for copy engine that
 	 * are not using polling mode.
 	 */
-	for (ce_id = 0; ce_id < CE_COUNT; ce_id++) {
-		ce_state  = &ce->ce_states[ce_id];
-		if (ce_state->attr_flags & CE_ATTR_POLL)
-			continue;
-
-		ath10k_ce_per_engine_handler_adjust(ce_state);
-	}
+	for (ce_id = 0; ce_id < CE_COUNT; ce_id++)
+		ath10k_ce_enable_interrupt(ar, ce_id);
 }
 EXPORT_SYMBOL(ath10k_ce_enable_interrupts);
 
@@ -1555,7 +1560,7 @@
 		ret = ath10k_ce_alloc_shadow_base(ar, src_ring, nentries);
 		if (ret) {
 			dma_free_coherent(ar->dev,
-					  (nentries * sizeof(struct ce_desc_64) +
+					  (nentries * sizeof(struct ce_desc) +
 					   CE_DESC_RING_ALIGN),
 					  src_ring->base_addr_owner_space_unaligned,
 					  base_addr);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath10k/ce.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath10k/ce.h
@@ -255,10 +255,13 @@
 /*==================CE Interrupt Handlers====================*/
 void ath10k_ce_per_engine_service_any(struct ath10k *ar);
 void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id);
-int ath10k_ce_disable_interrupts(struct ath10k *ar);
+void ath10k_ce_disable_interrupt(struct ath10k *ar, int ce_id);
+void ath10k_ce_disable_interrupts(struct ath10k *ar);
+void ath10k_ce_enable_interrupt(struct ath10k *ar, int ce_id);
 void ath10k_ce_enable_interrupts(struct ath10k *ar);
 void ath10k_ce_dump_registers(struct ath10k *ar,
 			      struct ath10k_fw_crash_data *crash_data);
+
 void ath10k_ce_alloc_rri(struct ath10k *ar);
 void ath10k_ce_free_rri(struct ath10k *ar);
 
@@ -369,18 +372,14 @@
 	(((x) & CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK) >> \
 		CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB)
 #define CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS			0x0000
-#define CE_INTERRUPT_SUMMARY		(GENMASK(CE_COUNT_MAX - 1, 0))
 
 static inline u32 ath10k_ce_interrupt_summary(struct ath10k *ar)
 {
 	struct ath10k_ce *ce = ath10k_ce_priv(ar);
 
-	if (!ar->hw_params.per_ce_irq)
-		return CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_GET(
-			ce->bus_ops->read32((ar), CE_WRAPPER_BASE_ADDRESS +
-			CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS));
-	else
-		return CE_INTERRUPT_SUMMARY;
+	return CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_GET(
+		ce->bus_ops->read32((ar), CE_WRAPPER_BASE_ADDRESS +
+		CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS));
 }
 
 /* Host software's Copy Engine configuration. */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath10k/core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath10k/core.c
@@ -118,7 +118,6 @@
 		.num_wds_entries = 0x20,
 		.target_64bit = false,
 		.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
-		.per_ce_irq = false,
 		.shadow_reg_support = false,
 		.rri_on_ddr = false,
 		.hw_filter_reset_required = true,
@@ -154,7 +153,6 @@
 		.num_wds_entries = 0x20,
 		.target_64bit = false,
 		.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
-		.per_ce_irq = false,
 		.shadow_reg_support = false,
 		.rri_on_ddr = false,
 		.hw_filter_reset_required = true,
@@ -217,7 +215,6 @@
 		.num_wds_entries = 0x20,
 		.target_64bit = false,
 		.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
-		.per_ce_irq = false,
 		.shadow_reg_support = false,
 		.rri_on_ddr = false,
 		.hw_filter_reset_required = true,
@@ -252,7 +249,6 @@
 		.num_wds_entries = 0x20,
 		.target_64bit = false,
 		.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
-		.per_ce_irq = false,
 		.shadow_reg_support = false,
 		.rri_on_ddr = false,
 		.hw_filter_reset_required = true,
@@ -287,7 +283,6 @@
 		.num_wds_entries = 0x20,
 		.target_64bit = false,
 		.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
-		.per_ce_irq = false,
 		.shadow_reg_support = false,
 		.rri_on_ddr = false,
 		.hw_filter_reset_required = true,
@@ -325,7 +320,6 @@
 		.num_wds_entries = 0x20,
 		.target_64bit = false,
 		.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
-		.per_ce_irq = false,
 		.shadow_reg_support = false,
 		.rri_on_ddr = false,
 		.hw_filter_reset_required = true,
@@ -366,7 +360,6 @@
 		.num_wds_entries = 0x20,
 		.target_64bit = false,
 		.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
-		.per_ce_irq = false,
 		.shadow_reg_support = false,
 		.rri_on_ddr = false,
 		.hw_filter_reset_required = true,
@@ -414,7 +407,6 @@
 		.num_wds_entries = 0x20,
 		.target_64bit = false,
 		.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
-		.per_ce_irq = false,
 		.shadow_reg_support = false,
 		.rri_on_ddr = false,
 		.hw_filter_reset_required = true,
@@ -459,7 +451,6 @@
 		.num_wds_entries = 0x20,
 		.target_64bit = false,
 		.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
-		.per_ce_irq = false,
 		.shadow_reg_support = false,
 		.rri_on_ddr = false,
 		.hw_filter_reset_required = true,
@@ -494,7 +485,6 @@
 		.num_wds_entries = 0x20,
 		.target_64bit = false,
 		.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
-		.per_ce_irq = false,
 		.shadow_reg_support = false,
 		.rri_on_ddr = false,
 		.hw_filter_reset_required = true,
@@ -531,7 +521,6 @@
 		.num_wds_entries = 0x20,
 		.target_64bit = false,
 		.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
-		.per_ce_irq = false,
 		.shadow_reg_support = false,
 		.rri_on_ddr = false,
 		.hw_filter_reset_required = true,
@@ -573,7 +562,6 @@
 		.num_wds_entries = 0x20,
 		.target_64bit = false,
 		.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
-		.per_ce_irq = false,
 		.shadow_reg_support = false,
 		.rri_on_ddr = false,
 		.hw_filter_reset_required = true,
@@ -591,6 +579,9 @@
 		.max_spatial_stream = 4,
 		.fw = {
 			.dir = WCN3990_HW_1_0_FW_DIR,
+			.board = WCN3990_HW_1_0_BOARD_DATA_FILE,
+			.board_size = WCN3990_BOARD_DATA_SZ,
+			.board_ext_size = WCN3990_BOARD_EXT_DATA_SZ,
 		},
 		.sw_decrypt_mcast_mgmt = true,
 		.hw_ops = &wcn3990_ops,
@@ -601,7 +592,6 @@
 		.num_wds_entries = TARGET_HL_TLV_NUM_WDS_ENTRIES,
 		.target_64bit = true,
 		.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL_DUAL_MAC,
-		.per_ce_irq = true,
 		.shadow_reg_support = true,
 		.rri_on_ddr = true,
 		.hw_filter_reset_required = false,
@@ -2157,7 +2147,7 @@
 
 static int ath10k_init_hw_params(struct ath10k *ar)
 {
-	const struct ath10k_hw_params *uninitialized_var(hw_params);
+	const struct ath10k_hw_params *hw_params;
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(ath10k_hw_params_list); i++) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath10k/core.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath10k/core.h
@@ -969,6 +969,11 @@
 	u32 low_5ghz_chan;
 	u32 high_5ghz_chan;
 	bool ani_enabled;
+	u32 sys_cap_info;
+
+	/* protected by data_lock */
+	bool hw_rfkill_on;
+
 	/* protected by conf_mutex */
 	u8 ps_state_enable;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath10k/coredump.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath10k/coredump.c
@@ -1208,9 +1208,11 @@
 		dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar);
 		dump_tlv->type = cpu_to_le32(ATH10K_FW_CRASH_DUMP_RAM_DATA);
 		dump_tlv->tlv_len = cpu_to_le32(crash_data->ramdump_buf_len);
-		memcpy(dump_tlv->tlv_data, crash_data->ramdump_buf,
-		       crash_data->ramdump_buf_len);
-		sofar += sizeof(*dump_tlv) + crash_data->ramdump_buf_len;
+		if (crash_data->ramdump_buf_len) {
+			memcpy(dump_tlv->tlv_data, crash_data->ramdump_buf,
+			       crash_data->ramdump_buf_len);
+			sofar += sizeof(*dump_tlv) + crash_data->ramdump_buf_len;
+		}
 	}
 
 	mutex_unlock(&ar->dump_mutex);
@@ -1257,6 +1259,9 @@
 	if (test_bit(ATH10K_FW_CRASH_DUMP_RAM_DATA, &ath10k_coredump_mask)) {
 		crash_data->ramdump_buf_len = ath10k_coredump_get_ramdump_size(ar);
 
+		if (!crash_data->ramdump_buf_len)
+			return 0;
+
 		crash_data->ramdump_buf = vzalloc(crash_data->ramdump_buf_len);
 		if (!crash_data->ramdump_buf)
 			return -ENOMEM;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath10k/debug.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath10k/debug.c
@@ -1138,7 +1138,7 @@
 				 u32 sset, u8 *data)
 {
 	if (sset == ETH_SS_STATS)
-		memcpy(data, *ath10k_gstrings_stats,
+		memcpy(data, ath10k_gstrings_stats,
 		       sizeof(ath10k_gstrings_stats));
 }
 
@@ -1516,7 +1516,7 @@
 	*len += scnprintf(buf + *len, buf_len - *len,
 			  "No.  Preamble Rate_code ");
 
-	for (i = 0; i < WMI_TPC_TX_N_CHAIN; i++)
+	for (i = 0; i < tpc_stats->num_tx_chain; i++)
 		*len += scnprintf(buf + *len, buf_len - *len,
 				  "tpc_value%d ", i);
 
@@ -2532,6 +2532,7 @@
 	ath10k_debug_fw_stats_reset(ar);
 
 	kfree(ar->debug.tpc_stats);
+	kfree(ar->debug.tpc_stats_final);
 }
 
 int ath10k_debug_register(struct ath10k *ar)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath10k/debugfs_sta.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath10k/debugfs_sta.c
@@ -438,7 +438,7 @@
 	}
 out:
 	mutex_unlock(&ar->conf_mutex);
-	return count;
+	return ret ?: count;
 }
 
 static const struct file_operations fops_peer_debug_trigger = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath10k/htt.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath10k/htt.h
@@ -835,6 +835,7 @@
 
 #define ATH10K_HTT_TXRX_PEER_SECURITY_MAX 2
 #define ATH10K_TXRX_NUM_EXT_TIDS 19
+#define ATH10K_TXRX_NON_QOS_TID 16
 
 enum htt_security_flags {
 #define HTT_SECURITY_TYPE_MASK 0x7F
@@ -2033,6 +2034,7 @@
 	int (*htt_h2t_aggr_cfg_msg)(struct ath10k_htt *htt,
 				    u8 max_subfrms_ampdu,
 				    u8 max_subfrms_amsdu);
+	void (*htt_flush_tx)(struct ath10k_htt *htt);
 };
 
 static inline int ath10k_htt_send_rx_ring_cfg(struct ath10k_htt *htt)
@@ -2072,6 +2074,12 @@
 	return htt->tx_ops->htt_tx(htt, txmode, msdu);
 }
 
+static inline void ath10k_htt_flush_tx(struct ath10k_htt *htt)
+{
+	if (htt->tx_ops->htt_flush_tx)
+		htt->tx_ops->htt_flush_tx(htt);
+}
+
 static inline int ath10k_htt_alloc_txbuff(struct ath10k_htt *htt)
 {
 	if (!htt->tx_ops->htt_alloc_txbuff)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -142,6 +142,14 @@
 	BUILD_BUG_ON(HTT_RX_RING_FILL_LEVEL >= HTT_RX_RING_SIZE / 2);
 
 	idx = __le32_to_cpu(*htt->rx_ring.alloc_idx.vaddr);
+
+	if (idx < 0 || idx >= htt->rx_ring.size) {
+		ath10k_err(htt->ar, "rx ring index is not valid, firmware malfunctioning?\n");
+		idx &= htt->rx_ring.size_mask;
+		ret = -ENOMEM;
+		goto fail;
+	}
+
 	while (num > 0) {
 		skb = dev_alloc_skb(HTT_RX_BUF_SIZE + HTT_RX_DESC_ALIGN);
 		if (!skb) {
@@ -941,6 +949,7 @@
 	u8 preamble = 0;
 	u8 group_id;
 	u32 info1, info2, info3;
+	u32 stbc, nsts_su;
 
 	info1 = __le32_to_cpu(rxd->ppdu_start.info1);
 	info2 = __le32_to_cpu(rxd->ppdu_start.info2);
@@ -985,11 +994,16 @@
 		 */
 		bw = info2 & 3;
 		sgi = info3 & 1;
+		stbc = (info2 >> 3) & 1;
 		group_id = (info2 >> 4) & 0x3F;
 
 		if (GROUP_ID_IS_SU_MIMO(group_id)) {
 			mcs = (info3 >> 4) & 0x0F;
-			nss = ((info2 >> 10) & 0x07) + 1;
+			nsts_su = ((info2 >> 10) & 0x07);
+			if (stbc)
+				nss = (nsts_su >> 2) + 1;
+			else
+				nss = (nsts_su + 1);
 		} else {
 			/* Hardware doesn't decode VHT-SIG-B into Rx descriptor
 			 * so it's impossible to decode MCS. Also since
@@ -1725,16 +1739,97 @@
 	msdu->ip_summed = ath10k_htt_rx_get_csum_state(msdu);
 }
 
+static u64 ath10k_htt_rx_h_get_pn(struct ath10k *ar, struct sk_buff *skb,
+				  u16 offset,
+				  enum htt_rx_mpdu_encrypt_type enctype)
+{
+	struct ieee80211_hdr *hdr;
+	u64 pn = 0;
+	u8 *ehdr;
+
+	hdr = (struct ieee80211_hdr *)(skb->data + offset);
+	ehdr = skb->data + offset + ieee80211_hdrlen(hdr->frame_control);
+
+	if (enctype == HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2) {
+		pn = ehdr[0];
+		pn |= (u64)ehdr[1] << 8;
+		pn |= (u64)ehdr[4] << 16;
+		pn |= (u64)ehdr[5] << 24;
+		pn |= (u64)ehdr[6] << 32;
+		pn |= (u64)ehdr[7] << 40;
+	}
+	return pn;
+}
+
+static bool ath10k_htt_rx_h_frag_multicast_check(struct ath10k *ar,
+						 struct sk_buff *skb,
+						 u16 offset)
+{
+	struct ieee80211_hdr *hdr;
+
+	hdr = (struct ieee80211_hdr *)(skb->data + offset);
+	return !is_multicast_ether_addr(hdr->addr1);
+}
+
+static bool ath10k_htt_rx_h_frag_pn_check(struct ath10k *ar,
+					  struct sk_buff *skb,
+					  u16 peer_id,
+					  u16 offset,
+					  enum htt_rx_mpdu_encrypt_type enctype)
+{
+	struct ath10k_peer *peer;
+	union htt_rx_pn_t *last_pn, new_pn = {0};
+	struct ieee80211_hdr *hdr;
+	bool more_frags;
+	u8 tid, frag_number;
+	u32 seq;
+
+	peer = ath10k_peer_find_by_id(ar, peer_id);
+	if (!peer) {
+		ath10k_dbg(ar, ATH10K_DBG_HTT, "invalid peer for frag pn check\n");
+		return false;
+	}
+
+	hdr = (struct ieee80211_hdr *)(skb->data + offset);
+	if (ieee80211_is_data_qos(hdr->frame_control))
+		tid = ieee80211_get_tid(hdr);
+	else
+		tid = ATH10K_TXRX_NON_QOS_TID;
+
+	last_pn = &peer->frag_tids_last_pn[tid];
+	new_pn.pn48 = ath10k_htt_rx_h_get_pn(ar, skb, offset, enctype);
+	more_frags = ieee80211_has_morefrags(hdr->frame_control);
+	frag_number = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG;
+	seq = (__le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
+
+	if (frag_number == 0) {
+		last_pn->pn48 = new_pn.pn48;
+		peer->frag_tids_seq[tid] = seq;
+	} else {
+		if (seq != peer->frag_tids_seq[tid])
+			return false;
+
+		if (new_pn.pn48 != last_pn->pn48 + 1)
+			return false;
+
+		last_pn->pn48 = new_pn.pn48;
+	}
+
+	return true;
+}
+
 static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
 				 struct sk_buff_head *amsdu,
 				 struct ieee80211_rx_status *status,
 				 bool fill_crypt_header,
 				 u8 *rx_hdr,
-				 enum ath10k_pkt_rx_err *err)
+				 enum ath10k_pkt_rx_err *err,
+				 u16 peer_id,
+				 bool frag)
 {
 	struct sk_buff *first;
 	struct sk_buff *last;
-	struct sk_buff *msdu;
+	struct sk_buff *msdu, *temp;
 	struct htt_rx_desc *rxd;
 	struct ieee80211_hdr *hdr;
 	enum htt_rx_mpdu_encrypt_type enctype;
@@ -1747,6 +1842,7 @@
 	bool is_decrypted;
 	bool is_mgmt;
 	u32 attention;
+	bool frag_pn_check = true, multicast_check = true;
 
 	if (skb_queue_empty(amsdu))
 		return;
@@ -1845,7 +1941,37 @@
 	}
 
 	skb_queue_walk(amsdu, msdu) {
+		if (frag && !fill_crypt_header && is_decrypted &&
+		    enctype == HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2)
+			frag_pn_check = ath10k_htt_rx_h_frag_pn_check(ar,
+								      msdu,
+								      peer_id,
+								      0,
+								      enctype);
+
+		if (frag)
+			multicast_check = ath10k_htt_rx_h_frag_multicast_check(ar,
+									       msdu,
+									       0);
+
+		if (!frag_pn_check || !multicast_check) {
+			/* Discard the fragment with invalid PN or multicast DA
+			 */
+			temp = msdu->prev;
+			__skb_unlink(msdu, amsdu);
+			dev_kfree_skb_any(msdu);
+			msdu = temp;
+			frag_pn_check = true;
+			multicast_check = true;
+			continue;
+		}
+
 		ath10k_htt_rx_h_csum_offload(msdu);
+
+		if (frag && !fill_crypt_header &&
+		    enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA)
+			status->flag &= ~RX_FLAG_MMIC_STRIPPED;
+
 		ath10k_htt_rx_h_undecap(ar, msdu, status, first_hdr, enctype,
 					is_decrypted);
 
@@ -1863,6 +1989,11 @@
 
 		hdr = (void *)msdu->data;
 		hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+
+		if (frag && !fill_crypt_header &&
+		    enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA)
+			status->flag &= ~RX_FLAG_IV_STRIPPED &
+					~RX_FLAG_MMIC_STRIPPED;
 	}
 }
 
@@ -1970,14 +2101,62 @@
 	ath10k_unchain_msdu(amsdu, unchain_cnt);
 }
 
+static bool ath10k_htt_rx_validate_amsdu(struct ath10k *ar,
+					 struct sk_buff_head *amsdu)
+{
+	u8 *subframe_hdr;
+	struct sk_buff *first;
+	bool is_first, is_last;
+	struct htt_rx_desc *rxd;
+	struct ieee80211_hdr *hdr;
+	size_t hdr_len, crypto_len;
+	enum htt_rx_mpdu_encrypt_type enctype;
+	int bytes_aligned = ar->hw_params.decap_align_bytes;
+
+	first = skb_peek(amsdu);
+
+	rxd = (void *)first->data - sizeof(*rxd);
+	hdr = (void *)rxd->rx_hdr_status;
+
+	is_first = !!(rxd->msdu_end.common.info0 &
+		      __cpu_to_le32(RX_MSDU_END_INFO0_FIRST_MSDU));
+	is_last = !!(rxd->msdu_end.common.info0 &
+		     __cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU));
+
+	/* Return in case of non-aggregated msdu */
+	if (is_first && is_last)
+		return true;
+
+	/* First msdu flag is not set for the first msdu of the list */
+	if (!is_first)
+		return false;
+
+	enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0),
+		     RX_MPDU_START_INFO0_ENCRYPT_TYPE);
+
+	hdr_len = ieee80211_hdrlen(hdr->frame_control);
+	crypto_len = ath10k_htt_rx_crypto_param_len(ar, enctype);
+
+	subframe_hdr = (u8 *)hdr + round_up(hdr_len, bytes_aligned) +
+		       crypto_len;
+
+	/* Validate if the amsdu has a proper first subframe.
+	 * There are chances a single msdu can be received as amsdu when
+	 * the unauthenticated amsdu flag of a QoS header
+	 * gets flipped in non-SPP AMSDU's, in such cases the first
+	 * subframe has llc/snap header in place of a valid da.
+	 * return false if the da matches rfc1042 pattern
+	 */
+	if (ether_addr_equal(subframe_hdr, rfc1042_header))
+		return false;
+
+	return true;
+}
+
 static bool ath10k_htt_rx_amsdu_allowed(struct ath10k *ar,
 					struct sk_buff_head *amsdu,
 					struct ieee80211_rx_status *rx_status)
 {
-	/* FIXME: It might be a good idea to do some fuzzy-testing to drop
-	 * invalid/dangerous frames.
-	 */
-
 	if (!rx_status->freq) {
 		ath10k_dbg(ar, ATH10K_DBG_HTT, "no channel configured; ignoring frame(s)!\n");
 		return false;
@@ -1988,6 +2167,11 @@
 		return false;
 	}
 
+	if (!ath10k_htt_rx_validate_amsdu(ar, amsdu)) {
+		ath10k_dbg(ar, ATH10K_DBG_HTT, "invalid amsdu received\n");
+		return false;
+	}
+
 	return true;
 }
 
@@ -2050,7 +2234,8 @@
 		ath10k_htt_rx_h_unchain(ar, &amsdu, &drop_cnt, &unchain_cnt);
 
 	ath10k_htt_rx_h_filter(ar, &amsdu, rx_status, &drop_cnt_filter);
-	ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status, true, first_hdr, &err);
+	ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status, true, first_hdr, &err, 0,
+			     false);
 	msdus_to_queue = skb_queue_len(&amsdu);
 	ath10k_htt_rx_h_enqueue(ar, &amsdu, rx_status);
 
@@ -2183,6 +2368,11 @@
 	fw_desc = &rx->fw_desc;
 	rx_desc_len = fw_desc->len;
 
+	if (fw_desc->u.bits.discard) {
+		ath10k_dbg(ar, ATH10K_DBG_HTT, "htt discard mpdu\n");
+		goto err;
+	}
+
 	/* I have not yet seen any case where num_mpdu_ranges > 1.
 	 * qcacld does not seem handle that case either, so we introduce the
 	 * same limitiation here as well.
@@ -2483,6 +2673,13 @@
 	rx_desc = (struct htt_hl_rx_desc *)(skb->data + tot_hdr_len);
 	rx_desc_info = __le32_to_cpu(rx_desc->info);
 
+	hdr = (struct ieee80211_hdr *)((u8 *)rx_desc + rx_hl->fw_desc.len);
+
+	if (is_multicast_ether_addr(hdr->addr1)) {
+		/* Discard the fragment with multicast DA */
+		goto err;
+	}
+
 	if (!MS(rx_desc_info, HTT_RX_DESC_HL_INFO_ENCRYPTED)) {
 		spin_unlock_bh(&ar->data_lock);
 		return ath10k_htt_rx_proc_rx_ind_hl(htt, &resp->rx_ind_hl, skb,
@@ -2490,8 +2687,6 @@
 						    HTT_RX_NON_TKIP_MIC);
 	}
 
-	hdr = (struct ieee80211_hdr *)((u8 *)rx_desc + rx_hl->fw_desc.len);
-
 	if (ieee80211_has_retry(hdr->frame_control))
 		goto err;
 
@@ -2726,7 +2921,7 @@
 		spin_lock_bh(&ar->data_lock);
 
 		peer = ath10k_peer_find_by_id(ar, peer_id);
-		if (!peer) {
+		if (!peer || !peer->sta) {
 			spin_unlock_bh(&ar->data_lock);
 			rcu_read_unlock();
 			continue;
@@ -3000,7 +3195,7 @@
 			ath10k_htt_rx_h_ppdu(ar, &amsdu, status, vdev_id);
 			ath10k_htt_rx_h_filter(ar, &amsdu, status, NULL);
 			ath10k_htt_rx_h_mpdu(ar, &amsdu, status, false, NULL,
-					     NULL);
+					     NULL, peer_id, frag);
 			ath10k_htt_rx_h_enqueue(ar, &amsdu, status);
 			break;
 		case -EAGAIN:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -147,6 +147,9 @@
 	htt->num_pending_tx--;
 	if (htt->num_pending_tx == htt->max_num_pending_tx - 1)
 		ath10k_mac_tx_unlock(htt->ar, ATH10K_TX_PAUSE_Q_FULL);
+
+	if (htt->num_pending_tx == 0)
+		wake_up(&htt->empty_tx_wq);
 }
 
 int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt)
@@ -529,9 +532,14 @@
 	htt->tx_mem_allocated = false;
 }
 
-void ath10k_htt_tx_stop(struct ath10k_htt *htt)
+static void ath10k_htt_flush_tx_queue(struct ath10k_htt *htt)
 {
 	idr_for_each(&htt->pending_tx, ath10k_htt_tx_clean_up_pending, htt->ar);
+}
+
+void ath10k_htt_tx_stop(struct ath10k_htt *htt)
+{
+	ath10k_htt_flush_tx_queue(htt);
 	idr_destroy(&htt->pending_tx);
 }
 
@@ -1535,7 +1543,9 @@
 err_unmap_msdu:
 	dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
 err_free_msdu_id:
+	spin_lock_bh(&htt->tx_lock);
 	ath10k_htt_tx_free_msdu_id(htt, msdu_id);
+	spin_unlock_bh(&htt->tx_lock);
 err:
 	return res;
 }
@@ -1742,7 +1752,9 @@
 err_unmap_msdu:
 	dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
 err_free_msdu_id:
+	spin_lock_bh(&htt->tx_lock);
 	ath10k_htt_tx_free_msdu_id(htt, msdu_id);
+	spin_unlock_bh(&htt->tx_lock);
 err:
 	return res;
 }
@@ -1774,6 +1786,7 @@
 	.htt_send_frag_desc_bank_cfg = ath10k_htt_send_frag_desc_bank_cfg_32,
 	.htt_tx = ath10k_htt_tx_hl,
 	.htt_h2t_aggr_cfg_msg = ath10k_htt_h2t_aggr_cfg_msg_32,
+	.htt_flush_tx = ath10k_htt_flush_tx_queue,
 };
 
 void ath10k_htt_set_tx_ops(struct ath10k_htt *htt)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath10k/hw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath10k/hw.c
@@ -155,6 +155,9 @@
 	.num_target_ce_config_wlan	= 7,
 	.ce_desc_meta_data_mask		= 0xFFFC,
 	.ce_desc_meta_data_lsb		= 2,
+	.rfkill_pin			= 16,
+	.rfkill_cfg			= 0,
+	.rfkill_on_level		= 1,
 };
 
 const struct ath10k_hw_values qca99x0_values = {
@@ -1145,6 +1148,7 @@
 const struct ath10k_hw_ops qca99x0_ops = {
 	.rx_desc_get_l3_pad_bytes = ath10k_qca99x0_rx_desc_get_l3_pad_bytes,
 	.rx_desc_get_msdu_limit_error = ath10k_qca99x0_rx_desc_msdu_limit_error,
+	.is_rssi_enable = ath10k_htt_tx_rssi_enable,
 };
 
 const struct ath10k_hw_ops qca6174_ops = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath10k/hw.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath10k/hw.h
@@ -132,6 +132,7 @@
 /* WCN3990 1.0 definitions */
 #define WCN3990_HW_1_0_DEV_VERSION	ATH10K_HW_WCN3990
 #define WCN3990_HW_1_0_FW_DIR		ATH10K_FW_DIR "/WCN3990/hw1.0"
+#define WCN3990_HW_1_0_BOARD_DATA_FILE "board.bin"
 
 #define ATH10K_FW_FILE_BASE		"firmware"
 #define ATH10K_FW_API_MAX		6
@@ -379,6 +380,9 @@
 	u8 num_target_ce_config_wlan;
 	u16 ce_desc_meta_data_mask;
 	u8 ce_desc_meta_data_lsb;
+	u32 rfkill_pin;
+	u32 rfkill_cfg;
+	bool rfkill_on_level;
 };
 
 extern const struct ath10k_hw_values qca988x_values;
@@ -590,9 +594,6 @@
 	/* Target rx ring fill level */
 	u32 rx_ring_fill_level;
 
-	/* target supporting per ce IRQ */
-	bool per_ce_irq;
-
 	/* target supporting shadow register for ce write */
 	bool shadow_reg_support;
 
@@ -810,7 +811,7 @@
 
 #define TARGET_10_4_TX_DBG_LOG_SIZE		1024
 #define TARGET_10_4_NUM_WDS_ENTRIES		32
-#define TARGET_10_4_DMA_BURST_SIZE		0
+#define TARGET_10_4_DMA_BURST_SIZE		1
 #define TARGET_10_4_MAC_AGGR_DELIM		0
 #define TARGET_10_4_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK 1
 #define TARGET_10_4_VOW_CONFIG			0
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath10k/mac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath10k/mac.c
@@ -12,6 +12,7 @@
 #include <linux/etherdevice.h>
 #include <linux/acpi.h>
 #include <linux/of.h>
+#include <linux/bitfield.h>
 
 #include "hif.h"
 #include "core.h"
@@ -856,11 +857,36 @@
 	return 0;
 }
 
+static void ath10k_peer_map_cleanup(struct ath10k *ar, struct ath10k_peer *peer)
+{
+	int peer_id, i;
+
+	lockdep_assert_held(&ar->conf_mutex);
+
+	for_each_set_bit(peer_id, peer->peer_ids,
+			 ATH10K_MAX_NUM_PEER_IDS) {
+		ar->peer_map[peer_id] = NULL;
+	}
+
+	/* Double check that peer is properly un-referenced from
+	 * the peer_map
+	 */
+	for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++) {
+		if (ar->peer_map[i] == peer) {
+			ath10k_warn(ar, "removing stale peer_map entry for %pM (ptr %pK idx %d)\n",
+				    peer->addr, peer, i);
+			ar->peer_map[i] = NULL;
+		}
+	}
+
+	list_del(&peer->list);
+	kfree(peer);
+	ar->num_peers--;
+}
+
 static void ath10k_peer_cleanup(struct ath10k *ar, u32 vdev_id)
 {
 	struct ath10k_peer *peer, *tmp;
-	int peer_id;
-	int i;
 
 	lockdep_assert_held(&ar->conf_mutex);
 
@@ -872,25 +898,7 @@
 		ath10k_warn(ar, "removing stale peer %pM from vdev_id %d\n",
 			    peer->addr, vdev_id);
 
-		for_each_set_bit(peer_id, peer->peer_ids,
-				 ATH10K_MAX_NUM_PEER_IDS) {
-			ar->peer_map[peer_id] = NULL;
-		}
-
-		/* Double check that peer is properly un-referenced from
-		 * the peer_map
-		 */
-		for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++) {
-			if (ar->peer_map[i] == peer) {
-				ath10k_warn(ar, "removing stale peer_map entry for %pM (ptr %pK idx %d)\n",
-					    peer->addr, peer, i);
-				ar->peer_map[i] = NULL;
-			}
-		}
-
-		list_del(&peer->list);
-		kfree(peer);
-		ar->num_peers--;
+		ath10k_peer_map_cleanup(ar, peer);
 	}
 	spin_unlock_bh(&ar->data_lock);
 }
@@ -985,8 +993,12 @@
 	ath10k_mac_vif_beacon_free(arvif);
 
 	if (arvif->beacon_buf) {
-		dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN,
-				  arvif->beacon_buf, arvif->beacon_paddr);
+		if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL)
+			kfree(arvif->beacon_buf);
+		else
+			dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN,
+					  arvif->beacon_buf,
+					  arvif->beacon_paddr);
 		arvif->beacon_buf = NULL;
 	}
 }
@@ -1040,7 +1052,7 @@
 	arg.channel.min_power = 0;
 	arg.channel.max_power = channel->max_power * 2;
 	arg.channel.max_reg_power = channel->max_reg_power * 2;
-	arg.channel.max_antenna_gain = channel->max_antenna_gain * 2;
+	arg.channel.max_antenna_gain = channel->max_antenna_gain;
 
 	reinit_completion(&ar->vdev_setup_done);
 	reinit_completion(&ar->vdev_delete_done);
@@ -1486,7 +1498,7 @@
 	arg.channel.min_power = 0;
 	arg.channel.max_power = chandef->chan->max_power * 2;
 	arg.channel.max_reg_power = chandef->chan->max_reg_power * 2;
-	arg.channel.max_antenna_gain = chandef->chan->max_antenna_gain * 2;
+	arg.channel.max_antenna_gain = chandef->chan->max_antenna_gain;
 
 	if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
 		arg.ssid = arvif->u.ap.ssid;
@@ -3145,7 +3157,7 @@
 			ch->min_power = 0;
 			ch->max_power = channel->max_power * 2;
 			ch->max_reg_power = channel->max_reg_power * 2;
-			ch->max_antenna_gain = channel->max_antenna_gain * 2;
+			ch->max_antenna_gain = channel->max_antenna_gain;
 			ch->reg_class_id = 0; /* FIXME */
 
 			/* FIXME: why use only legacy modes, why not any
@@ -3624,23 +3636,16 @@
 static int ath10k_mac_tx_wmi_mgmt(struct ath10k *ar, struct sk_buff *skb)
 {
 	struct sk_buff_head *q = &ar->wmi_mgmt_tx_queue;
-	int ret = 0;
 
-	spin_lock_bh(&ar->data_lock);
-
-	if (skb_queue_len(q) == ATH10K_MAX_NUM_MGMT_PENDING) {
+	if (skb_queue_len_lockless(q) >= ATH10K_MAX_NUM_MGMT_PENDING) {
 		ath10k_warn(ar, "wmi mgmt tx queue is full\n");
-		ret = -ENOSPC;
-		goto unlock;
+		return -ENOSPC;
 	}
 
-	__skb_queue_tail(q, skb);
+	skb_queue_tail(q, skb);
 	ieee80211_queue_work(ar->hw, &ar->wmi_mgmt_tx_work);
 
-unlock:
-	spin_unlock_bh(&ar->data_lock);
-
-	return ret;
+	return 0;
 }
 
 static enum ath10k_mac_tx_path
@@ -3708,7 +3713,7 @@
 			 struct ieee80211_vif *vif,
 			 enum ath10k_hw_txrx_mode txmode,
 			 enum ath10k_mac_tx_path txpath,
-			 struct sk_buff *skb)
+			 struct sk_buff *skb, bool noque_offchan)
 {
 	struct ieee80211_hw *hw = ar->hw;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
@@ -3738,10 +3743,10 @@
 		}
 	}
 
-	if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) {
+	if (!noque_offchan && info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) {
 		if (!ath10k_mac_tx_frm_has_freq(ar)) {
-			ath10k_dbg(ar, ATH10K_DBG_MAC, "queued offchannel skb %pK\n",
-				   skb);
+			ath10k_dbg(ar, ATH10K_DBG_MAC, "mac queued offchannel skb %pK len %d\n",
+				   skb, skb->len);
 
 			skb_queue_tail(&ar->offchan_tx_queue, skb);
 			ieee80211_queue_work(hw, &ar->offchan_tx_work);
@@ -3803,8 +3808,8 @@
 
 		mutex_lock(&ar->conf_mutex);
 
-		ath10k_dbg(ar, ATH10K_DBG_MAC, "mac offchannel skb %pK\n",
-			   skb);
+		ath10k_dbg(ar, ATH10K_DBG_MAC, "mac offchannel skb %pK len %d\n",
+			   skb, skb->len);
 
 		hdr = (struct ieee80211_hdr *)skb->data;
 		peer_addr = ieee80211_get_DA(hdr);
@@ -3850,7 +3855,7 @@
 		txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb);
 		txpath = ath10k_mac_tx_h_get_txpath(ar, skb, txmode);
 
-		ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb);
+		ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb, true);
 		if (ret) {
 			ath10k_warn(ar, "failed to transmit offchannel frame: %d\n",
 				    ret);
@@ -3860,8 +3865,8 @@
 		time_left =
 		wait_for_completion_timeout(&ar->offchan_tx_completed, 3 * HZ);
 		if (time_left == 0)
-			ath10k_warn(ar, "timed out waiting for offchannel skb %pK\n",
-				    skb);
+			ath10k_warn(ar, "timed out waiting for offchannel skb %pK, len: %d\n",
+				    skb, skb->len);
 
 		if (!peer && tmp_peer_created) {
 			ret = ath10k_peer_delete(ar, vdev_id, peer_addr);
@@ -3903,12 +3908,17 @@
 			     ar->running_fw->fw_file.fw_features)) {
 			paddr = dma_map_single(ar->dev, skb->data,
 					       skb->len, DMA_TO_DEVICE);
-			if (!paddr)
+			if (dma_mapping_error(ar->dev, paddr)) {
+				ieee80211_free_txskb(ar->hw, skb);
 				continue;
+			}
 			ret = ath10k_wmi_mgmt_tx_send(ar, skb, paddr);
 			if (ret) {
 				ath10k_warn(ar, "failed to transmit management frame by ref via WMI: %d\n",
 					    ret);
+				/* remove this msdu from idr tracking */
+				ath10k_wmi_cleanup_mgmt_tx_send(ar, skb);
+
 				dma_unmap_single(ar->dev, paddr, skb->len,
 						 DMA_TO_DEVICE);
 				ieee80211_free_txskb(ar->hw, skb);
@@ -4097,7 +4107,7 @@
 		spin_unlock_bh(&ar->htt.tx_lock);
 	}
 
-	ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb);
+	ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb, false);
 	if (unlikely(ret)) {
 		ath10k_warn(ar, "failed to push frame: %d\n", ret);
 
@@ -4378,7 +4388,7 @@
 		spin_unlock_bh(&ar->htt.tx_lock);
 	}
 
-	ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb);
+	ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb, false);
 	if (ret) {
 		ath10k_warn(ar, "failed to transmit frame: %d\n", ret);
 		if (is_htt) {
@@ -4754,6 +4764,63 @@
 	return 0;
 }
 
+static int ath10k_mac_rfkill_config(struct ath10k *ar)
+{
+	u32 param;
+	int ret;
+
+	if (ar->hw_values->rfkill_pin == 0) {
+		ath10k_warn(ar, "ath10k does not support hardware rfkill with this device\n");
+		return -EOPNOTSUPP;
+	}
+
+	ath10k_dbg(ar, ATH10K_DBG_MAC,
+		   "mac rfkill_pin %d rfkill_cfg %d rfkill_on_level %d",
+		   ar->hw_values->rfkill_pin, ar->hw_values->rfkill_cfg,
+		   ar->hw_values->rfkill_on_level);
+
+	param = FIELD_PREP(WMI_TLV_RFKILL_CFG_RADIO_LEVEL,
+			   ar->hw_values->rfkill_on_level) |
+		FIELD_PREP(WMI_TLV_RFKILL_CFG_GPIO_PIN_NUM,
+			   ar->hw_values->rfkill_pin) |
+		FIELD_PREP(WMI_TLV_RFKILL_CFG_PIN_AS_GPIO,
+			   ar->hw_values->rfkill_cfg);
+
+	ret = ath10k_wmi_pdev_set_param(ar,
+					ar->wmi.pdev_param->rfkill_config,
+					param);
+	if (ret) {
+		ath10k_warn(ar,
+			    "failed to set rfkill config 0x%x: %d\n",
+			    param, ret);
+		return ret;
+	}
+	return 0;
+}
+
+int ath10k_mac_rfkill_enable_radio(struct ath10k *ar, bool enable)
+{
+	enum wmi_tlv_rfkill_enable_radio param;
+	int ret;
+
+	if (enable)
+		param = WMI_TLV_RFKILL_ENABLE_RADIO_ON;
+	else
+		param = WMI_TLV_RFKILL_ENABLE_RADIO_OFF;
+
+	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac rfkill enable %d", param);
+
+	ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->rfkill_enable,
+					param);
+	if (ret) {
+		ath10k_warn(ar, "failed to set rfkill enable param %d: %d\n",
+			    param, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
 static int ath10k_start(struct ieee80211_hw *hw)
 {
 	struct ath10k *ar = hw->priv;
@@ -4788,6 +4855,16 @@
 		goto err;
 	}
 
+	spin_lock_bh(&ar->data_lock);
+
+	if (ar->hw_rfkill_on) {
+		ar->hw_rfkill_on = false;
+		spin_unlock_bh(&ar->data_lock);
+		goto err;
+	}
+
+	spin_unlock_bh(&ar->data_lock);
+
 	ret = ath10k_hif_power_up(ar, ATH10K_FIRMWARE_MODE_NORMAL);
 	if (ret) {
 		ath10k_err(ar, "Could not init hif: %d\n", ret);
@@ -4801,6 +4878,14 @@
 		goto err_power_down;
 	}
 
+	if (ar->sys_cap_info & WMI_TLV_SYS_CAP_INFO_RFKILL) {
+		ret = ath10k_mac_rfkill_config(ar);
+		if (ret && ret != -EOPNOTSUPP) {
+			ath10k_warn(ar, "failed to configure rfkill: %d", ret);
+			goto err_core_stop;
+		}
+	}
+
 	param = ar->wmi.pdev_param->pmf_qos;
 	ret = ath10k_wmi_pdev_set_param(ar, param, 1);
 	if (ret) {
@@ -4960,7 +5045,8 @@
 
 	mutex_lock(&ar->conf_mutex);
 	if (ar->state != ATH10K_STATE_OFF) {
-		ath10k_halt(ar);
+		if (!ar->hw_rfkill_on)
+			ath10k_halt(ar);
 		ar->state = ATH10K_STATE_OFF;
 	}
 	mutex_unlock(&ar->conf_mutex);
@@ -5253,10 +5339,25 @@
 	if (vif->type == NL80211_IFTYPE_ADHOC ||
 	    vif->type == NL80211_IFTYPE_MESH_POINT ||
 	    vif->type == NL80211_IFTYPE_AP) {
-		arvif->beacon_buf = dma_alloc_coherent(ar->dev,
-						       IEEE80211_MAX_FRAME_LEN,
-						       &arvif->beacon_paddr,
-						       GFP_ATOMIC);
+		if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL) {
+			arvif->beacon_buf = kmalloc(IEEE80211_MAX_FRAME_LEN,
+						    GFP_KERNEL);
+
+			/* Using a kernel pointer in place of a dma_addr_t
+			 * token can lead to undefined behavior if that
+			 * makes it into cache management functions. Use a
+			 * known-invalid address token instead, which
+			 * avoids the warning and makes it easier to catch
+			 * bugs if it does end up getting used.
+			 */
+			arvif->beacon_paddr = DMA_MAPPING_ERROR;
+		} else {
+			arvif->beacon_buf =
+				dma_alloc_coherent(ar->dev,
+						   IEEE80211_MAX_FRAME_LEN,
+						   &arvif->beacon_paddr,
+						   GFP_ATOMIC);
+		}
 		if (!arvif->beacon_buf) {
 			ret = -ENOMEM;
 			ath10k_warn(ar, "failed to allocate beacon buffer: %d\n",
@@ -5269,6 +5370,7 @@
 
 	if (arvif->nohwcrypt &&
 	    !test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
+		ret = -EINVAL;
 		ath10k_warn(ar, "cryptmode module param needed for sw crypto\n");
 		goto err;
 	}
@@ -5470,8 +5572,12 @@
 
 err:
 	if (arvif->beacon_buf) {
-		dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN,
-				  arvif->beacon_buf, arvif->beacon_paddr);
+		if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL)
+			kfree(arvif->beacon_buf);
+		else
+			dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN,
+					  arvif->beacon_buf,
+					  arvif->beacon_paddr);
 		arvif->beacon_buf = NULL;
 	}
 
@@ -6619,10 +6725,7 @@
 				/* Clean up the peer object as well since we
 				 * must have failed to do this above.
 				 */
-				list_del(&peer->list);
-				ar->peer_map[i] = NULL;
-				kfree(peer);
-				ar->num_peers--;
+				ath10k_peer_map_cleanup(ar, peer);
 			}
 		}
 		spin_unlock_bh(&ar->data_lock);
@@ -7080,6 +7183,7 @@
 					ath10k_wmi_peer_flush(ar, arvif->vdev_id,
 							      arvif->bssid, bitmap);
 			}
+			ath10k_htt_flush_tx(&ar->htt);
 		}
 		return;
 	}
@@ -7125,7 +7229,7 @@
 				  struct ieee80211_channel *channel)
 {
 	int ret;
-	enum wmi_bss_survey_req_type type = WMI_BSS_SURVEY_REQ_TYPE_READ_CLEAR;
+	enum wmi_bss_survey_req_type type = WMI_BSS_SURVEY_REQ_TYPE_READ;
 
 	lockdep_assert_held(&ar->conf_mutex);
 
@@ -8809,7 +8913,6 @@
 	ar->hw->wiphy->max_scan_ie_len = WLAN_SCAN_PARAMS_MAX_IE_LEN;
 
 	if (test_bit(WMI_SERVICE_NLO, ar->wmi.svc_map)) {
-		ar->hw->wiphy->max_sched_scan_reqs = 1;
 		ar->hw->wiphy->max_sched_scan_ssids = WMI_PNO_MAX_SUPP_NETWORKS;
 		ar->hw->wiphy->max_match_sets = WMI_PNO_MAX_SUPP_NETWORKS;
 		ar->hw->wiphy->max_sched_scan_ie_len = WMI_PNO_MAX_IE_LENGTH;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath10k/mac.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath10k/mac.h
@@ -72,6 +72,7 @@
 					    u8 tid);
 int ath10k_mac_ext_resource_config(struct ath10k *ar, u32 val);
 void ath10k_mac_wait_tx_complete(struct ath10k *ar);
+int ath10k_mac_rfkill_enable_radio(struct ath10k *ar, bool enable);
 
 static inline void ath10k_tx_h_seq_no(struct ieee80211_vif *vif,
 				      struct sk_buff *skb)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath10k/pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath10k/pci.c
@@ -1604,11 +1604,22 @@
 {
 	struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
 	u32 i;
+	int ret;
+
+	mutex_lock(&ar->conf_mutex);
+	if (ar->state != ATH10K_STATE_ON) {
+		ath10k_warn(ar, "Skipping pci_dump_memory_reg invalid state\n");
+		ret = -EIO;
+		goto done;
+	}
 
 	for (i = 0; i < region->len; i += 4)
 		*(u32 *)(buf + i) = ioread32(ar_pci->mem + region->start + i);
 
-	return region->len;
+	ret = region->len;
+done:
+	mutex_unlock(&ar->conf_mutex);
+	return ret;
 }
 
 /* if an error happened returns < 0, otherwise the length */
@@ -1704,7 +1715,11 @@
 			count = ath10k_pci_dump_memory_sram(ar, current_region, buf);
 			break;
 		case ATH10K_MEM_REGION_TYPE_IOREG:
-			count = ath10k_pci_dump_memory_reg(ar, current_region, buf);
+			ret = ath10k_pci_dump_memory_reg(ar, current_region, buf);
+			if (ret < 0)
+				break;
+
+			count = ret;
 			break;
 		default:
 			ret = ath10k_pci_dump_memory_generic(ar, current_region, buf);
@@ -1945,8 +1960,9 @@
 	ath10k_pci_irq_enable(ar);
 	ath10k_pci_rx_post(ar);
 
-	pcie_capability_write_word(ar_pci->pdev, PCI_EXP_LNKCTL,
-				   ar_pci->link_ctl);
+	pcie_capability_clear_and_set_word(ar_pci->pdev, PCI_EXP_LNKCTL,
+					   PCI_EXP_LNKCTL_ASPMC,
+					   ar_pci->link_ctl & PCI_EXP_LNKCTL_ASPMC);
 
 	return 0;
 }
@@ -2059,6 +2075,7 @@
 	ath10k_pci_irq_sync(ar);
 	napi_synchronize(&ar->napi);
 	napi_disable(&ar->napi);
+	cancel_work_sync(&ar_pci->dump_work);
 
 	/* Most likely the device has HTT Rx ring configured. The only way to
 	 * prevent the device from accessing (and possible corrupting) host
@@ -2802,8 +2819,8 @@
 
 	pcie_capability_read_word(ar_pci->pdev, PCI_EXP_LNKCTL,
 				  &ar_pci->link_ctl);
-	pcie_capability_write_word(ar_pci->pdev, PCI_EXP_LNKCTL,
-				   ar_pci->link_ctl & ~PCI_EXP_LNKCTL_ASPMC);
+	pcie_capability_clear_word(ar_pci->pdev, PCI_EXP_LNKCTL,
+				   PCI_EXP_LNKCTL_ASPMC);
 
 	/*
 	 * Bring the target up cleanly.
@@ -3490,7 +3507,7 @@
 	struct ath10k_pci *ar_pci;
 	enum ath10k_hw_rev hw_rev;
 	struct ath10k_bus_params bus_params = {};
-	bool pci_ps;
+	bool pci_ps, is_qca988x = false;
 	int (*pci_soft_reset)(struct ath10k *ar);
 	int (*pci_hard_reset)(struct ath10k *ar);
 	u32 (*targ_cpu_to_ce_addr)(struct ath10k *ar, u32 addr);
@@ -3500,6 +3517,7 @@
 	case QCA988X_2_0_DEVICE_ID:
 		hw_rev = ATH10K_HW_QCA988X;
 		pci_ps = false;
+		is_qca988x = true;
 		pci_soft_reset = ath10k_pci_warm_reset;
 		pci_hard_reset = ath10k_pci_qca988x_chip_reset;
 		targ_cpu_to_ce_addr = ath10k_pci_qca988x_targ_cpu_to_ce_addr;
@@ -3619,24 +3637,39 @@
 		goto err_deinit_irq;
 	}
 
+	bus_params.dev_type = ATH10K_DEV_TYPE_LL;
+	bus_params.link_can_suspend = true;
+	/* Read CHIP_ID before reset to catch QCA9880-AR1A v1 devices that
+	 * fall off the bus during chip_reset. These chips have the same pci
+	 * device id as the QCA9880 BR4A or 2R4E. So that's why the check.
+	 */
+	if (is_qca988x) {
+		bus_params.chip_id =
+			ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS);
+		if (bus_params.chip_id != 0xffffffff) {
+			if (!ath10k_pci_chip_is_supported(pdev->device,
+							  bus_params.chip_id)) {
+				ret = -ENODEV;
+				goto err_unsupported;
+			}
+		}
+	}
+
 	ret = ath10k_pci_chip_reset(ar);
 	if (ret) {
 		ath10k_err(ar, "failed to reset chip: %d\n", ret);
 		goto err_free_irq;
 	}
 
-	bus_params.dev_type = ATH10K_DEV_TYPE_LL;
-	bus_params.link_can_suspend = true;
 	bus_params.chip_id = ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS);
 	if (bus_params.chip_id == 0xffffffff) {
-		ath10k_err(ar, "failed to get chip id\n");
-		goto err_free_irq;
+		ret = -ENODEV;
+		goto err_unsupported;
 	}
 
 	if (!ath10k_pci_chip_is_supported(pdev->device, bus_params.chip_id)) {
-		ath10k_err(ar, "device %04x with chip_id %08x isn't supported\n",
-			   pdev->device, bus_params.chip_id);
-		goto err_free_irq;
+		ret = -ENODEV;
+		goto err_unsupported;
 	}
 
 	ret = ath10k_core_register(ar, &bus_params);
@@ -3647,6 +3680,10 @@
 
 	return 0;
 
+err_unsupported:
+	ath10k_err(ar, "device %04x with chip_id %08x isn't supported\n",
+		   pdev->device, bus_params.chip_id);
+
 err_free_irq:
 	ath10k_pci_free_irq(ar);
 	ath10k_pci_rx_retry_sync(ar);
@@ -3733,18 +3770,22 @@
 
 static int __init ath10k_pci_init(void)
 {
-	int ret;
+	int ret1, ret2;
 
-	ret = pci_register_driver(&ath10k_pci_driver);
-	if (ret)
+	ret1 = pci_register_driver(&ath10k_pci_driver);
+	if (ret1)
 		printk(KERN_ERR "failed to register ath10k pci driver: %d\n",
-		       ret);
+		       ret1);
 
-	ret = ath10k_ahb_init();
-	if (ret)
-		printk(KERN_ERR "ahb init failed: %d\n", ret);
+	ret2 = ath10k_ahb_init();
+	if (ret2)
+		printk(KERN_ERR "ahb init failed: %d\n", ret2);
 
-	return ret;
+	if (ret1 && ret2)
+		return ret1;
+
+	/* registered to at least one bus */
+	return 0;
 }
 module_init(ath10k_pci_init);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath10k/qmi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath10k/qmi.c
@@ -581,22 +581,29 @@
 {
 	struct wlfw_host_cap_resp_msg_v01 resp = {};
 	struct wlfw_host_cap_req_msg_v01 req = {};
+	struct qmi_elem_info *req_ei;
 	struct ath10k *ar = qmi->ar;
+	struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
 	struct qmi_txn txn;
 	int ret;
 
 	req.daemon_support_valid = 1;
 	req.daemon_support = 0;
 
-	ret = qmi_txn_init(&qmi->qmi_hdl, &txn,
-			   wlfw_host_cap_resp_msg_v01_ei, &resp);
+	ret = qmi_txn_init(&qmi->qmi_hdl, &txn, wlfw_host_cap_resp_msg_v01_ei,
+			   &resp);
 	if (ret < 0)
 		goto out;
 
+	if (test_bit(ATH10K_SNOC_FLAG_8BIT_HOST_CAP_QUIRK, &ar_snoc->flags))
+		req_ei = wlfw_host_cap_8bit_req_msg_v01_ei;
+	else
+		req_ei = wlfw_host_cap_req_msg_v01_ei;
+
 	ret = qmi_send_request(&qmi->qmi_hdl, NULL, &txn,
 			       QMI_WLFW_HOST_CAP_REQ_V01,
 			       WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN,
-			       wlfw_host_cap_req_msg_v01_ei, &req);
+			       req_ei, &req);
 	if (ret < 0) {
 		qmi_txn_cancel(&txn);
 		ath10k_err(ar, "failed to send host capability request: %d\n", ret);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.c
@@ -1988,6 +1988,28 @@
 	{}
 };
 
+struct qmi_elem_info wlfw_host_cap_8bit_req_msg_v01_ei[] = {
+	{
+		.data_type      = QMI_OPT_FLAG,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0x10,
+		.offset         = offsetof(struct wlfw_host_cap_req_msg_v01,
+					   daemon_support_valid),
+	},
+	{
+		.data_type      = QMI_UNSIGNED_1_BYTE,
+		.elem_len       = 1,
+		.elem_size      = sizeof(u8),
+		.array_type     = NO_ARRAY,
+		.tlv_type       = 0x10,
+		.offset         = offsetof(struct wlfw_host_cap_req_msg_v01,
+					   daemon_support),
+	},
+	{}
+};
+
 struct qmi_elem_info wlfw_host_cap_resp_msg_v01_ei[] = {
 	{
 		.data_type      = QMI_STRUCT,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.h
@@ -575,6 +575,7 @@
 
 #define WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN 189
 extern struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[];
+extern struct qmi_elem_info wlfw_host_cap_8bit_req_msg_v01_ei[];
 
 struct wlfw_host_cap_resp_msg_v01 {
 	struct qmi_response_type_v01 resp;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath10k/rx_desc.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath10k/rx_desc.h
@@ -1282,7 +1282,19 @@
 #define FW_RX_DESC_UDP              (1 << 6)
 
 struct fw_rx_desc_hl {
-	u8 info0;
+	union {
+		struct {
+		u8 discard:1,
+		   forward:1,
+		   any_err:1,
+		   dup_err:1,
+		   reserved:1,
+		   inspect:1,
+		   extension:2;
+		} bits;
+		u8 info0;
+	} u;
+
 	u8 version;
 	u8 len;
 	u8 flags;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath10k/sdio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath10k/sdio.c
@@ -3,6 +3,7 @@
  * Copyright (c) 2004-2011 Atheros Communications Inc.
  * Copyright (c) 2011-2012,2017 Qualcomm Atheros, Inc.
  * Copyright (c) 2016-2017 Erik Stromdahl <erik.stromdahl@gmail.com>
+ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/module.h>
@@ -550,6 +551,10 @@
 				    le16_to_cpu(htc_hdr->len),
 				    ATH10K_HTC_MBOX_MAX_PAYLOAD_LENGTH);
 			ret = -ENOMEM;
+
+			queue_work(ar->workqueue, &ar->restart_work);
+			ath10k_warn(ar, "exceeds length, start recovery\n");
+
 			goto err;
 		}
 
@@ -1582,23 +1587,33 @@
 				     size_t buf_len)
 {
 	int ret;
+	void *mem;
+
+	mem = kzalloc(buf_len, GFP_KERNEL);
+	if (!mem)
+		return -ENOMEM;
 
 	/* set window register to start read cycle */
 	ret = ath10k_sdio_write32(ar, MBOX_WINDOW_READ_ADDR_ADDRESS, address);
 	if (ret) {
 		ath10k_warn(ar, "failed to set mbox window read address: %d", ret);
-		return ret;
+		goto out;
 	}
 
 	/* read the data */
-	ret = ath10k_sdio_read(ar, MBOX_WINDOW_DATA_ADDRESS, buf, buf_len);
+	ret = ath10k_sdio_read(ar, MBOX_WINDOW_DATA_ADDRESS, mem, buf_len);
 	if (ret) {
 		ath10k_warn(ar, "failed to read from mbox window data address: %d\n",
 			    ret);
-		return ret;
+		goto out;
 	}
 
-	return 0;
+	memcpy(buf, mem, buf_len);
+
+out:
+	kfree(mem);
+
+	return ret;
 }
 
 static int ath10k_sdio_hif_diag_read32(struct ath10k *ar, u32 address,
@@ -2109,10 +2124,11 @@
 		   func->num, func->vendor, func->device);
 
 	ath10k_core_unregister(ar);
-	ath10k_core_destroy(ar);
 
 	flush_workqueue(ar_sdio->workqueue);
 	destroy_workqueue(ar_sdio->workqueue);
+
+	ath10k_core_destroy(ar);
 }
 
 static const struct sdio_device_id ath10k_sdio_devices[] = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath10k/snoc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath10k/snoc.c
@@ -3,6 +3,7 @@
  * Copyright (c) 2018 The Linux Foundation. All rights reserved.
  */
 
+#include <linux/bits.h>
 #include <linux/clk.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -821,12 +822,20 @@
 
 static inline void ath10k_snoc_irq_disable(struct ath10k *ar)
 {
-	ath10k_ce_disable_interrupts(ar);
+	struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
+	int id;
+
+	for (id = 0; id < CE_COUNT_MAX; id++)
+		disable_irq(ar_snoc->ce_irqs[id].irq_line);
 }
 
 static inline void ath10k_snoc_irq_enable(struct ath10k *ar)
 {
-	ath10k_ce_enable_interrupts(ar);
+	struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
+	int id;
+
+	for (id = 0; id < CE_COUNT_MAX; id++)
+		enable_irq(ar_snoc->ce_irqs[id].irq_line);
 }
 
 static void ath10k_snoc_rx_pipe_cleanup(struct ath10k_snoc_pipe *snoc_pipe)
@@ -919,6 +928,7 @@
 {
 	struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
 
+	bitmap_clear(ar_snoc->pending_ce_irqs, 0, CE_COUNT_MAX);
 	napi_enable(&ar->napi);
 	ath10k_snoc_irq_enable(ar);
 	ath10k_snoc_rx_post(ar);
@@ -1039,12 +1049,15 @@
 	ret = ath10k_snoc_init_pipes(ar);
 	if (ret) {
 		ath10k_err(ar, "failed to initialize CE: %d\n", ret);
-		goto err_wlan_enable;
+		goto err_free_rri;
 	}
 
+	ath10k_ce_enable_interrupts(ar);
+
 	return 0;
 
-err_wlan_enable:
+err_free_rri:
+	ath10k_ce_free_rri(ar);
 	ath10k_snoc_wlan_disable(ar);
 
 	return ret;
@@ -1155,7 +1168,9 @@
 		return IRQ_HANDLED;
 	}
 
-	ath10k_snoc_irq_disable(ar);
+	ath10k_ce_disable_interrupt(ar, ce_id);
+	set_bit(ce_id, ar_snoc->pending_ce_irqs);
+
 	napi_schedule(&ar->napi);
 
 	return IRQ_HANDLED;
@@ -1164,20 +1179,25 @@
 static int ath10k_snoc_napi_poll(struct napi_struct *ctx, int budget)
 {
 	struct ath10k *ar = container_of(ctx, struct ath10k, napi);
+	struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
 	int done = 0;
+	int ce_id;
 
 	if (test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags)) {
 		napi_complete(ctx);
 		return done;
 	}
 
-	ath10k_ce_per_engine_service_any(ar);
+	for (ce_id = 0; ce_id < CE_COUNT; ce_id++)
+		if (test_and_clear_bit(ce_id, ar_snoc->pending_ce_irqs)) {
+			ath10k_ce_per_engine_service(ar, ce_id);
+			ath10k_ce_enable_interrupt(ar, ce_id);
+		}
+
 	done = ath10k_htt_txrx_compl_task(ar, budget);
 
-	if (done < budget) {
+	if (done < budget)
 		napi_complete(ctx);
-		ath10k_snoc_irq_enable(ar);
-	}
 
 	return done;
 }
@@ -1191,13 +1211,12 @@
 static int ath10k_snoc_request_irq(struct ath10k *ar)
 {
 	struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
-	int irqflags = IRQF_TRIGGER_RISING;
 	int ret, id;
 
 	for (id = 0; id < CE_COUNT_MAX; id++) {
 		ret = request_irq(ar_snoc->ce_irqs[id].irq_line,
 				  ath10k_snoc_per_engine_handler,
-				  irqflags, ce_name[id], ar);
+				  IRQF_NO_AUTOEN, ce_name[id], ar);
 		if (ret) {
 			ath10k_err(ar,
 				   "failed to register IRQ handler for CE %d: %d",
@@ -1261,6 +1280,15 @@
 	return ret;
 }
 
+static void ath10k_snoc_quirks_init(struct ath10k *ar)
+{
+	struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
+	struct device *dev = &ar_snoc->dev->dev;
+
+	if (of_property_read_bool(dev->of_node, "qcom,snoc-host-cap-8bit-quirk"))
+		set_bit(ATH10K_SNOC_FLAG_8BIT_HOST_CAP_QUIRK, &ar_snoc->flags);
+}
+
 int ath10k_snoc_fw_indication(struct ath10k *ar, u64 type)
 {
 	struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
@@ -1678,6 +1706,8 @@
 	ar->ce_priv = &ar_snoc->ce;
 	msa_size = drv_data->msa_size;
 
+	ath10k_snoc_quirks_init(ar);
+
 	ret = ath10k_snoc_resource_init(ar);
 	if (ret) {
 		ath10k_warn(ar, "failed to initialize resource: %d\n", ret);
@@ -1718,13 +1748,16 @@
 	ret = ath10k_qmi_init(ar, msa_size);
 	if (ret) {
 		ath10k_warn(ar, "failed to register wlfw qmi client: %d\n", ret);
-		goto err_core_destroy;
+		goto err_power_off;
 	}
 
 	ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc probe\n");
 
 	return 0;
 
+err_power_off:
+	ath10k_hw_power_off(ar);
+
 err_free_irq:
 	ath10k_snoc_free_irq(ar);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath10k/snoc.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath10k/snoc.h
@@ -63,6 +63,7 @@
 	ATH10K_SNOC_FLAG_REGISTERED,
 	ATH10K_SNOC_FLAG_UNREGISTERING,
 	ATH10K_SNOC_FLAG_RECOVERY,
+	ATH10K_SNOC_FLAG_8BIT_HOST_CAP_QUIRK,
 };
 
 struct ath10k_snoc {
@@ -80,6 +81,7 @@
 	struct ath10k_clk_info *clk;
 	struct ath10k_qmi *qmi;
 	unsigned long flags;
+	DECLARE_BITMAP(pending_ce_irqs, CE_COUNT_MAX);
 };
 
 static inline struct ath10k_snoc *ath10k_snoc_priv(struct ath10k *ar)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath10k/targaddrs.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath10k/targaddrs.h
@@ -480,4 +480,7 @@
 #define QCA4019_BOARD_DATA_SZ	  12064
 #define QCA4019_BOARD_EXT_DATA_SZ 0
 
+#define WCN3990_BOARD_DATA_SZ	  26328
+#define WCN3990_BOARD_EXT_DATA_SZ 0
+
 #endif /* __TARGADDRS_H__ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath10k/txrx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath10k/txrx.c
@@ -80,13 +80,13 @@
 
 	ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id);
 	ath10k_htt_tx_dec_pending(htt);
-	if (htt->num_pending_tx == 0)
-		wake_up(&htt->empty_tx_wq);
 	spin_unlock_bh(&htt->tx_lock);
 
+	rcu_read_lock();
 	if (txq && txq->sta && skb_cb->airtime_est)
 		ieee80211_sta_register_airtime(txq->sta, txq->tid,
 					       skb_cb->airtime_est, 0);
+	rcu_read_unlock();
 
 	if (ar->bus_param.dev_type != ATH10K_DEV_TYPE_HL)
 		dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
@@ -95,6 +95,8 @@
 
 	info = IEEE80211_SKB_CB(msdu);
 	memset(&info->status, 0, sizeof(info->status));
+	info->status.rates[0].idx = -1;
+
 	trace_ath10k_txrx_tx_unref(ar, tx_done->msdu_id);
 
 	if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath10k/usb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath10k/usb.c
@@ -38,6 +38,10 @@
 	struct ath10k_urb_context *urb_context = NULL;
 	unsigned long flags;
 
+	/* bail if this pipe is not initialized */
+	if (!pipe->ar_usb)
+		return NULL;
+
 	spin_lock_irqsave(&pipe->ar_usb->cs_lock, flags);
 	if (!list_empty(&pipe->urb_list_head)) {
 		urb_context = list_first_entry(&pipe->urb_list_head,
@@ -55,6 +59,10 @@
 {
 	unsigned long flags;
 
+	/* bail if this pipe is not initialized */
+	if (!pipe->ar_usb)
+		return;
+
 	spin_lock_irqsave(&pipe->ar_usb->cs_lock, flags);
 
 	pipe->urb_cnt++;
@@ -435,6 +443,7 @@
 			ath10k_dbg(ar, ATH10K_DBG_USB_BULK,
 				   "usb bulk transmit failed: %d\n", ret);
 			usb_unanchor_urb(urb);
+			usb_free_urb(urb);
 			ret = -EINVAL;
 			goto err_free_urb_to_pipe;
 		}
@@ -516,7 +525,7 @@
 			      req,
 			      USB_DIR_IN | USB_TYPE_VENDOR |
 			      USB_RECIP_DEVICE, value, index, buf,
-			      size, 2 * HZ);
+			      size, 2000);
 
 	if (ret < 0) {
 		ath10k_warn(ar, "Failed to read usb control message: %d\n",
@@ -856,6 +865,11 @@
 				   le16_to_cpu(endpoint->wMaxPacketSize),
 				   endpoint->bInterval);
 		}
+
+		/* Ignore broken descriptors. */
+		if (usb_endpoint_maxp(endpoint) == 0)
+			continue;
+
 		urbcount = 0;
 
 		pipe_num =
@@ -1000,6 +1014,8 @@
 
 	ar_usb = ath10k_usb_priv(ar);
 	ret = ath10k_usb_create(ar, interface);
+	if (ret)
+		goto err;
 	ar_usb->ar = ar;
 
 	ar->dev_id = product_id;
@@ -1012,7 +1028,7 @@
 	ret = ath10k_core_register(ar, &bus_params);
 	if (ret) {
 		ath10k_warn(ar, "failed to register driver core: %d\n", ret);
-		goto err;
+		goto err_usb_destroy;
 	}
 
 	/* TODO: remove this once USB support is fully implemented */
@@ -1020,6 +1036,9 @@
 
 	return 0;
 
+err_usb_destroy:
+	ath10k_usb_destroy(ar);
+
 err:
 	ath10k_core_destroy(ar);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath10k/wmi-ops.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath10k/wmi-ops.h
@@ -133,6 +133,7 @@
 	struct sk_buff *(*gen_mgmt_tx_send)(struct ath10k *ar,
 					    struct sk_buff *skb,
 					    dma_addr_t paddr);
+	int (*cleanup_mgmt_tx_send)(struct ath10k *ar, struct sk_buff *msdu);
 	struct sk_buff *(*gen_dbglog_cfg)(struct ath10k *ar, u64 module_enable,
 					  u32 log_level);
 	struct sk_buff *(*gen_pktlog_enable)(struct ath10k *ar, u32 filter);
@@ -442,6 +443,15 @@
 }
 
 static inline int
+ath10k_wmi_cleanup_mgmt_tx_send(struct ath10k *ar, struct sk_buff *msdu)
+{
+	if (!ar->wmi.ops->cleanup_mgmt_tx_send)
+		return -EOPNOTSUPP;
+
+	return ar->wmi.ops->cleanup_mgmt_tx_send(ar, msdu);
+}
+
+static inline int
 ath10k_wmi_mgmt_tx_send(struct ath10k *ar, struct sk_buff *msdu,
 			dma_addr_t paddr)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath10k/wmi-tlv.c
@@ -409,6 +409,49 @@
 	return 0;
 }
 
+static void ath10k_wmi_tlv_event_rfkill_state_change(struct ath10k *ar,
+						     struct sk_buff *skb)
+{
+	const struct wmi_tlv_rfkill_state_change_ev *ev;
+	const void **tb;
+	bool radio;
+	int ret;
+
+	tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
+	if (IS_ERR(tb)) {
+		ret = PTR_ERR(tb);
+		ath10k_warn(ar,
+			    "failed to parse rfkill state change event: %d\n",
+			    ret);
+		return;
+	}
+
+	ev = tb[WMI_TLV_TAG_STRUCT_RFKILL_EVENT];
+	if (!ev) {
+		kfree(tb);
+		return;
+	}
+
+	ath10k_dbg(ar, ATH10K_DBG_MAC,
+		   "wmi tlv rfkill state change gpio %d type %d radio_state %d\n",
+		   __le32_to_cpu(ev->gpio_pin_num),
+		   __le32_to_cpu(ev->int_type),
+		   __le32_to_cpu(ev->radio_state));
+
+	radio = (__le32_to_cpu(ev->radio_state) == WMI_TLV_RFKILL_RADIO_STATE_ON);
+
+	spin_lock_bh(&ar->data_lock);
+
+	if (!radio)
+		ar->hw_rfkill_on = true;
+
+	spin_unlock_bh(&ar->data_lock);
+
+	/* notify cfg80211 radio state change */
+	ath10k_mac_rfkill_enable_radio(ar, radio);
+	wiphy_rfkill_set_hw_state(ar->hw->wiphy, !radio);
+}
+
 static int ath10k_wmi_tlv_event_temperature(struct ath10k *ar,
 					    struct sk_buff *skb)
 {
@@ -445,13 +488,13 @@
 	case WMI_TDLS_TEARDOWN_REASON_TX:
 	case WMI_TDLS_TEARDOWN_REASON_RSSI:
 	case WMI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT:
+		rcu_read_lock();
 		station = ieee80211_find_sta_by_ifaddr(ar->hw,
 						       ev->peer_macaddr.addr,
 						       NULL);
 		if (!station) {
 			ath10k_warn(ar, "did not find station from tdls peer event");
-			kfree(tb);
-			return;
+			goto exit;
 		}
 		arvif = ath10k_get_arvif(ar, __le32_to_cpu(ev->vdev_id));
 		ieee80211_tdls_oper_request(
@@ -461,7 +504,13 @@
 					GFP_ATOMIC
 					);
 		break;
+	default:
+		kfree(tb);
+		return;
 	}
+
+exit:
+	rcu_read_unlock();
 	kfree(tb);
 }
 
@@ -629,6 +678,9 @@
 	case WMI_TLV_TX_PAUSE_EVENTID:
 		ath10k_wmi_tlv_event_tx_pause(ar, skb);
 		break;
+	case WMI_TLV_RFKILL_STATE_CHANGE_EVENTID:
+		ath10k_wmi_tlv_event_rfkill_state_change(ar, skb);
+		break;
 	case WMI_TLV_PDEV_TEMPERATURE_EVENTID:
 		ath10k_wmi_tlv_event_temperature(ar, skb);
 		break;
@@ -701,6 +753,10 @@
 	}
 
 	ev = tb[WMI_TLV_TAG_STRUCT_MGMT_TX_COMPL_EVENT];
+	if (!ev) {
+		kfree(tb);
+		return -EPROTO;
+	}
 
 	arg->desc_id = ev->desc_id;
 	arg->status = ev->status;
@@ -1212,6 +1268,7 @@
 	arg->num_mem_reqs = ev->num_mem_reqs;
 	arg->service_map = svc_bmap;
 	arg->service_map_len = ath10k_wmi_tlv_len(svc_bmap);
+	arg->sys_cap_info = ev->sys_cap_info;
 
 	ret = ath10k_wmi_tlv_iter(ar, mem_reqs, ath10k_wmi_tlv_len(mem_reqs),
 				  ath10k_wmi_tlv_parse_mem_reqs, arg);
@@ -1260,13 +1317,15 @@
 
 	switch (tag) {
 	case WMI_TLV_TAG_STRUCT_SERVICE_AVAILABLE_EVENT:
+		arg->service_map_ext_valid = true;
 		arg->service_map_ext_len = *(__le32 *)ptr;
 		arg->service_map_ext = ptr + sizeof(__le32);
 		return 0;
 	default:
 		break;
 	}
-	return -EPROTO;
+
+	return 0;
 }
 
 static int ath10k_wmi_tlv_op_pull_svc_avail(struct ath10k *ar,
@@ -2838,6 +2897,23 @@
 }
 
 static int
+ath10k_wmi_tlv_op_cleanup_mgmt_tx_send(struct ath10k *ar,
+				       struct sk_buff *msdu)
+{
+	struct ath10k_skb_cb *cb = ATH10K_SKB_CB(msdu);
+	struct ath10k_mgmt_tx_pkt_addr *pkt_addr;
+	struct ath10k_wmi *wmi = &ar->wmi;
+
+	spin_lock_bh(&ar->data_lock);
+	pkt_addr = idr_remove(&wmi->mgmt_pending_tx, cb->msdu_id);
+	spin_unlock_bh(&ar->data_lock);
+
+	kfree(pkt_addr);
+
+	return 0;
+}
+
+static int
 ath10k_wmi_mgmt_tx_alloc_msdu_id(struct ath10k *ar, struct sk_buff *skb,
 				 dma_addr_t paddr)
 {
@@ -2911,6 +2987,8 @@
 	if (desc_id < 0)
 		goto err_free_skb;
 
+	cb->msdu_id = desc_id;
+
 	ptr = (void *)skb->data;
 	tlv = ptr;
 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_MGMT_TX_CMD);
@@ -3650,6 +3728,7 @@
 	struct wmi_tlv *tlv;
 	struct sk_buff *skb;
 	__le32 *channel_list;
+	u16 tlv_len;
 	size_t len;
 	void *ptr;
 	u32 i;
@@ -3707,10 +3786,12 @@
 	/* nlo_configured_parameters(nlo_list) */
 	cmd->no_of_ssids = __cpu_to_le32(min_t(u8, pno->uc_networks_count,
 					       WMI_NLO_MAX_SSIDS));
+	tlv_len = __le32_to_cpu(cmd->no_of_ssids) *
+		sizeof(struct nlo_configured_parameters);
 
 	tlv = ptr;
 	tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
-	tlv->len = __cpu_to_le16(len);
+	tlv->len = __cpu_to_le16(tlv_len);
 
 	ptr += sizeof(*tlv);
 	nlo_list = ptr;
@@ -4204,6 +4285,8 @@
 	.wapi_mbssid_offset = WMI_PDEV_PARAM_UNSUPPORTED,
 	.arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
 	.arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+	.rfkill_config = WMI_TLV_PDEV_PARAM_HW_RFKILL_CONFIG,
+	.rfkill_enable = WMI_TLV_PDEV_PARAM_RFKILL_ENABLE,
 };
 
 static struct wmi_vdev_param_map wmi_tlv_vdev_param_map = {
@@ -4336,6 +4419,7 @@
 	.gen_force_fw_hang = ath10k_wmi_tlv_op_gen_force_fw_hang,
 	/* .gen_mgmt_tx = not implemented; HTT is used */
 	.gen_mgmt_tx_send = ath10k_wmi_tlv_op_gen_mgmt_tx_send,
+	.cleanup_mgmt_tx_send = ath10k_wmi_tlv_op_cleanup_mgmt_tx_send,
 	.gen_dbglog_cfg = ath10k_wmi_tlv_op_gen_dbglog_cfg,
 	.gen_pktlog_enable = ath10k_wmi_tlv_op_gen_pktlog_enable,
 	.gen_pktlog_disable = ath10k_wmi_tlv_op_gen_pktlog_disable,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath10k/wmi-tlv.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath10k/wmi-tlv.h
@@ -7,6 +7,8 @@
 #ifndef _WMI_TLV_H
 #define _WMI_TLV_H
 
+#include <linux/bitops.h>
+
 #define WMI_TLV_CMD(grp_id) (((grp_id) << 12) | 0x1)
 #define WMI_TLV_EV(grp_id) (((grp_id) << 12) | 0x1)
 #define WMI_TLV_CMD_UNSUPPORTED 0
@@ -2235,6 +2237,31 @@
 	__le32 vdev_id;
 } __packed;
 
+enum wmi_tlv_sys_cap_info_flags {
+	WMI_TLV_SYS_CAP_INFO_RXTX_LED	= BIT(0),
+	WMI_TLV_SYS_CAP_INFO_RFKILL	= BIT(1),
+};
+
+#define WMI_TLV_RFKILL_CFG_GPIO_PIN_NUM		GENMASK(5, 0)
+#define WMI_TLV_RFKILL_CFG_RADIO_LEVEL		BIT(6)
+#define WMI_TLV_RFKILL_CFG_PIN_AS_GPIO		GENMASK(10, 7)
+
+enum wmi_tlv_rfkill_enable_radio {
+	WMI_TLV_RFKILL_ENABLE_RADIO_ON	= 0,
+	WMI_TLV_RFKILL_ENABLE_RADIO_OFF	= 1,
+};
+
+enum wmi_tlv_rfkill_radio_state {
+	WMI_TLV_RFKILL_RADIO_STATE_OFF	= 1,
+	WMI_TLV_RFKILL_RADIO_STATE_ON	= 2,
+};
+
+struct wmi_tlv_rfkill_state_change_ev {
+	__le32 gpio_pin_num;
+	__le32 int_type;
+	__le32 radio_state;
+};
+
 void ath10k_wmi_tlv_attach(struct ath10k *ar);
 
 enum wmi_nlo_auth_algorithm {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath10k/wmi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath10k/wmi.c
@@ -1720,12 +1720,32 @@
 
 int ath10k_wmi_wait_for_service_ready(struct ath10k *ar)
 {
-	unsigned long time_left;
+	unsigned long time_left, i;
 
 	time_left = wait_for_completion_timeout(&ar->wmi.service_ready,
 						WMI_SERVICE_READY_TIMEOUT_HZ);
-	if (!time_left)
-		return -ETIMEDOUT;
+	if (!time_left) {
+		/* Sometimes the PCI HIF doesn't receive interrupt
+		 * for the service ready message even if the buffer
+		 * was completed. PCIe sniffer shows that it's
+		 * because the corresponding CE ring doesn't fires
+		 * it. Workaround here by polling CE rings once.
+		 */
+		ath10k_warn(ar, "failed to receive service ready completion, polling..\n");
+
+		for (i = 0; i < CE_COUNT; i++)
+			ath10k_hif_send_complete_check(ar, i, 1);
+
+		time_left = wait_for_completion_timeout(&ar->wmi.service_ready,
+							WMI_SERVICE_READY_TIMEOUT_HZ);
+		if (!time_left) {
+			ath10k_warn(ar, "polling timed out\n");
+			return -ETIMEDOUT;
+		}
+
+		ath10k_warn(ar, "service ready completion received, continuing normally\n");
+	}
+
 	return 0;
 }
 
@@ -2365,6 +2385,7 @@
 	dma_unmap_single(ar->dev, pkt_addr->paddr,
 			 msdu->len, DMA_TO_DEVICE);
 	info = IEEE80211_SKB_CB(msdu);
+	kfree(pkt_addr);
 
 	if (param->status) {
 		info->flags &= ~IEEE80211_TX_STAT_ACK;
@@ -2541,6 +2562,10 @@
 	if (ieee80211_is_beacon(hdr->frame_control))
 		ath10k_mac_handle_beacon(ar, skb);
 
+	if (ieee80211_is_beacon(hdr->frame_control) ||
+	    ieee80211_is_probe_resp(hdr->frame_control))
+		status->boottime_ns = ktime_get_boottime_ns();
+
 	ath10k_dbg(ar, ATH10K_DBG_MGMT,
 		   "event mgmt rx skb %pK len %d ftype %02x stype %02x\n",
 		   skb, skb->len,
@@ -4668,16 +4693,13 @@
 	}
 
 	pream_idx = 0;
-	for (i = 0; i < __le32_to_cpu(ev->rate_max); i++) {
+	for (i = 0; i < tpc_stats->rate_max; i++) {
 		memset(tpc_value, 0, sizeof(tpc_value));
 		memset(buff, 0, sizeof(buff));
 		if (i == pream_table[pream_idx])
 			pream_idx++;
 
-		for (j = 0; j < WMI_TPC_TX_N_CHAIN; j++) {
-			if (j >= __le32_to_cpu(ev->num_tx_chain))
-				break;
-
+		for (j = 0; j < tpc_stats->num_tx_chain; j++) {
 			tpc[j] = ath10k_tpc_config_get_rate(ar, ev, i, j + 1,
 							    rate_code[i],
 							    type);
@@ -4790,7 +4812,7 @@
 
 void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, struct sk_buff *skb)
 {
-	u32 num_tx_chain;
+	u32 num_tx_chain, rate_max;
 	u8 rate_code[WMI_TPC_RATE_MAX];
 	u16 pream_table[WMI_TPC_PREAM_TABLE_MAX];
 	struct wmi_pdev_tpc_config_event *ev;
@@ -4806,6 +4828,13 @@
 		return;
 	}
 
+	rate_max = __le32_to_cpu(ev->rate_max);
+	if (rate_max > WMI_TPC_RATE_MAX) {
+		ath10k_warn(ar, "number of rate is %d greater than TPC configured rate %d\n",
+			    rate_max, WMI_TPC_RATE_MAX);
+		rate_max = WMI_TPC_RATE_MAX;
+	}
+
 	tpc_stats = kzalloc(sizeof(*tpc_stats), GFP_ATOMIC);
 	if (!tpc_stats)
 		return;
@@ -4822,8 +4851,8 @@
 		__le32_to_cpu(ev->twice_antenna_reduction);
 	tpc_stats->power_limit = __le32_to_cpu(ev->power_limit);
 	tpc_stats->twice_max_rd_power = __le32_to_cpu(ev->twice_max_rd_power);
-	tpc_stats->num_tx_chain = __le32_to_cpu(ev->num_tx_chain);
-	tpc_stats->rate_max = __le32_to_cpu(ev->rate_max);
+	tpc_stats->num_tx_chain = num_tx_chain;
+	tpc_stats->rate_max = rate_max;
 
 	ath10k_tpc_config_disp_tables(ar, ev, tpc_stats,
 				      rate_code, pream_table,
@@ -5018,16 +5047,13 @@
 	}
 
 	pream_idx = 0;
-	for (i = 0; i < __le32_to_cpu(ev->rate_max); i++) {
+	for (i = 0; i < tpc_stats->rate_max; i++) {
 		memset(tpc_value, 0, sizeof(tpc_value));
 		memset(buff, 0, sizeof(buff));
 		if (i == pream_table[pream_idx])
 			pream_idx++;
 
-		for (j = 0; j < WMI_TPC_TX_N_CHAIN; j++) {
-			if (j >= __le32_to_cpu(ev->num_tx_chain))
-				break;
-
+		for (j = 0; j < tpc_stats->num_tx_chain; j++) {
 			tpc[j] = ath10k_wmi_tpc_final_get_rate(ar, ev, i, j + 1,
 							       rate_code[i],
 							       type, pream_idx);
@@ -5043,7 +5069,7 @@
 
 void ath10k_wmi_event_tpc_final_table(struct ath10k *ar, struct sk_buff *skb)
 {
-	u32 num_tx_chain;
+	u32 num_tx_chain, rate_max;
 	u8 rate_code[WMI_TPC_FINAL_RATE_MAX];
 	u16 pream_table[WMI_TPC_PREAM_TABLE_MAX];
 	struct wmi_pdev_tpc_final_table_event *ev;
@@ -5051,12 +5077,24 @@
 
 	ev = (struct wmi_pdev_tpc_final_table_event *)skb->data;
 
+	num_tx_chain = __le32_to_cpu(ev->num_tx_chain);
+	if (num_tx_chain > WMI_TPC_TX_N_CHAIN) {
+		ath10k_warn(ar, "number of tx chain is %d greater than TPC final configured tx chain %d\n",
+			    num_tx_chain, WMI_TPC_TX_N_CHAIN);
+		return;
+	}
+
+	rate_max = __le32_to_cpu(ev->rate_max);
+	if (rate_max > WMI_TPC_FINAL_RATE_MAX) {
+		ath10k_warn(ar, "number of rate is %d greater than TPC final configured rate %d\n",
+			    rate_max, WMI_TPC_FINAL_RATE_MAX);
+		rate_max = WMI_TPC_FINAL_RATE_MAX;
+	}
+
 	tpc_stats = kzalloc(sizeof(*tpc_stats), GFP_ATOMIC);
 	if (!tpc_stats)
 		return;
 
-	num_tx_chain = __le32_to_cpu(ev->num_tx_chain);
-
 	ath10k_wmi_tpc_config_get_rate_code(rate_code, pream_table,
 					    num_tx_chain);
 
@@ -5069,8 +5107,8 @@
 		__le32_to_cpu(ev->twice_antenna_reduction);
 	tpc_stats->power_limit = __le32_to_cpu(ev->power_limit);
 	tpc_stats->twice_max_rd_power = __le32_to_cpu(ev->twice_max_rd_power);
-	tpc_stats->num_tx_chain = __le32_to_cpu(ev->num_tx_chain);
-	tpc_stats->rate_max = __le32_to_cpu(ev->rate_max);
+	tpc_stats->num_tx_chain = num_tx_chain;
+	tpc_stats->rate_max = rate_max;
 
 	ath10k_wmi_tpc_stats_final_disp_tables(ar, ev, tpc_stats,
 					       rate_code, pream_table,
@@ -5393,6 +5431,12 @@
 	arg->service_map = ev->wmi_service_bitmap;
 	arg->service_map_len = sizeof(ev->wmi_service_bitmap);
 
+	/* Deliberately skipping ev->sys_cap_info as WMI and WMI-TLV have
+	 * different values. We would need a translation to handle that,
+	 * but as we don't currently need anything from sys_cap_info from
+	 * WMI interface (only from WMI-TLV) safest it to skip it.
+	 */
+
 	n = min_t(size_t, __le32_to_cpu(arg->num_mem_reqs),
 		  ARRAY_SIZE(arg->mem_reqs));
 	for (i = 0; i < n; i++)
@@ -5443,9 +5487,12 @@
 	ar->hw_eeprom_rd = __le32_to_cpu(arg.eeprom_rd);
 	ar->low_5ghz_chan = __le32_to_cpu(arg.low_5ghz_chan);
 	ar->high_5ghz_chan = __le32_to_cpu(arg.high_5ghz_chan);
+	ar->sys_cap_info = __le32_to_cpu(arg.sys_cap_info);
 
 	ath10k_dbg_dump(ar, ATH10K_DBG_WMI, NULL, "wmi svc: ",
 			arg.service_map, arg.service_map_len);
+	ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi sys_cap_info 0x%x\n",
+		   ar->sys_cap_info);
 
 	if (ar->num_rf_chains > ar->max_spatial_stream) {
 		ath10k_warn(ar, "hardware advertises support for more spatial streams than it should (%d > %d)\n",
@@ -5646,8 +5693,13 @@
 			    ret);
 	}
 
-	ath10k_wmi_map_svc_ext(ar, arg.service_map_ext, ar->wmi.svc_map,
-			       __le32_to_cpu(arg.service_map_ext_len));
+	/*
+	 * Initialization of "arg.service_map_ext_valid" to ZERO is necessary
+	 * for the below logic to work.
+	 */
+	if (arg.service_map_ext_valid)
+		ath10k_wmi_map_svc_ext(ar, arg.service_map_ext, ar->wmi.svc_map,
+				       __le32_to_cpu(arg.service_map_ext_len));
 }
 
 static int ath10k_wmi_event_temperature(struct ath10k *ar, struct sk_buff *skb)
@@ -9422,8 +9474,9 @@
 
 	msdu = pkt_addr->vaddr;
 	dma_unmap_single(ar->dev, pkt_addr->paddr,
-			 msdu->len, DMA_FROM_DEVICE);
+			 msdu->len, DMA_TO_DEVICE);
 	ieee80211_free_txskb(ar->hw, msdu);
+	kfree(pkt_addr);
 
 	return 0;
 }
@@ -9440,7 +9493,5 @@
 	}
 
 	cancel_work_sync(&ar->svc_rdy_work);
-
-	if (ar->svc_rdy_skb)
-		dev_kfree_skb(ar->svc_rdy_skb);
+	dev_kfree_skb(ar->svc_rdy_skb);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath10k/wmi.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath10k/wmi.h
@@ -2045,7 +2045,9 @@
 	union {
 		__le32 reginfo1;
 		struct {
+			/* note: power unit is 1 dBm */
 			u8 antenna_max;
+			/* note: power unit is 0.5 dBm */
 			u8 max_tx_power;
 		} __packed;
 	} __packed;
@@ -2065,6 +2067,7 @@
 	u32 min_power;
 	u32 max_power;
 	u32 max_reg_power;
+	/* note: power unit is 1 dBm */
 	u32 max_antenna_gain;
 	u32 reg_class_id;
 	enum wmi_phy_mode mode;
@@ -3786,6 +3789,8 @@
 	u32 arp_srcaddr;
 	u32 arp_dstaddr;
 	u32 enable_btcoex;
+	u32 rfkill_config;
+	u32 rfkill_enable;
 };
 
 #define WMI_PDEV_PARAM_UNSUPPORTED 0
@@ -6851,12 +6856,14 @@
 	__le32 num_mem_reqs;
 	__le32 low_5ghz_chan;
 	__le32 high_5ghz_chan;
+	__le32 sys_cap_info;
 	const __le32 *service_map;
 	size_t service_map_len;
 	const struct wlan_host_mem_req *mem_reqs[WMI_MAX_MEM_REQS];
 };
 
 struct wmi_svc_avail_ev_arg {
+	bool service_map_ext_valid;
 	__le32 service_map_ext_len;
 	const __le32 *service_map_ext;
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath10k/wow.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath10k/wow.c
@@ -337,14 +337,15 @@
 			if (patterns[i].mask[j / 8] & BIT(j % 8))
 				bitmask[j] = 0xff;
 		old_pattern.mask = bitmask;
-		new_pattern = old_pattern;
 
 		if (ar->wmi.rx_decap_mode == ATH10K_HW_TXRX_NATIVE_WIFI) {
-			if (patterns[i].pkt_offset < ETH_HLEN)
+			if (patterns[i].pkt_offset < ETH_HLEN) {
 				ath10k_wow_convert_8023_to_80211(&new_pattern,
 								 &old_pattern);
-			else
+			} else {
+				new_pattern = old_pattern;
 				new_pattern.pkt_offset += WOW_HDR_LEN - ETH_HLEN;
+			}
 		}
 
 		if (WARN_ON(new_pattern.pattern_len > WOW_MAX_PATTERN_SIZE))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath5k/eeprom.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath5k/eeprom.c
@@ -529,7 +529,7 @@
 		ee->ee_n_piers[mode]++;
 
 		freq2 = (val >> 8) & 0xff;
-		if (!freq2)
+		if (!freq2 || i >= max)
 			break;
 
 		pc[i++].freq = ath5k_eeprom_bin2freq(ee,
@@ -746,6 +746,9 @@
 			}
 		}
 
+		if (idx == AR5K_EEPROM_N_PD_CURVES)
+			goto err_out;
+
 		ee->ee_pd_gains[mode] = 1;
 
 		pd = &chinfo[pier].pd_curves[idx];
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath5k/mac80211-ops.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath5k/mac80211-ops.c
@@ -521,7 +521,7 @@
 		}
 		break;
 	case DISABLE_KEY:
-		ath_key_delete(common, key);
+		ath_key_delete(common, key->hw_key_idx);
 		break;
 	default:
 		ret = -EINVAL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath5k/pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath5k/pci.c
@@ -46,6 +46,8 @@
 	{ PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */
 	{ PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */
 	{ PCI_VDEVICE(ATHEROS, 0x001d) }, /* 2417 Nala */
+	{ PCI_VDEVICE(ATHEROS, 0xff16) }, /* Gigaset SX76[23] AR241[34]A */
+	{ PCI_VDEVICE(ATHEROS, 0xff1a) }, /* Arcadyan ARV45XX AR2417 */
 	{ PCI_VDEVICE(ATHEROS, 0xff1b) }, /* AR5BXB63 */
 	{ 0 }
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath6kl/bmi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath6kl/bmi.c
@@ -246,7 +246,7 @@
 		return -EACCES;
 	}
 
-	size = sizeof(cid) + sizeof(addr) + sizeof(param);
+	size = sizeof(cid) + sizeof(addr) + sizeof(*param);
 	if (size > ar->bmi.max_cmd_size) {
 		WARN_ON(1);
 		return -EINVAL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath6kl/debug.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath6kl/debug.c
@@ -1027,14 +1027,17 @@
 {
 	struct ath6kl *ar = file->private_data;
 	unsigned long lrssi_roam_threshold;
+	int ret;
 
 	if (kstrtoul_from_user(user_buf, count, 0, &lrssi_roam_threshold))
 		return -EINVAL;
 
 	ar->lrssi_roam_threshold = lrssi_roam_threshold;
 
-	ath6kl_wmi_set_roam_lrssi_cmd(ar->wmi, ar->lrssi_roam_threshold);
+	ret = ath6kl_wmi_set_roam_lrssi_cmd(ar->wmi, ar->lrssi_roam_threshold);
 
+	if (ret)
+		return ret;
 	return count;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath6kl/htc_pipe.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath6kl/htc_pipe.c
@@ -960,8 +960,8 @@
 	 * Thus the possibility of ar->htc_target being NULL
 	 * via ath6kl_recv_complete -> ath6kl_usb_io_comp_work.
 	 */
-	if (WARN_ON_ONCE(!target)) {
-		ath6kl_err("Target not yet initialized\n");
+	if (!target) {
+		ath6kl_dbg(ATH6KL_DBG_HTC, "Target not yet initialized\n");
 		status = -EINVAL;
 		goto free_skb;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath6kl/init.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath6kl/init.c
@@ -1575,7 +1575,7 @@
 
 int ath6kl_init_hw_params(struct ath6kl *ar)
 {
-	const struct ath6kl_hw *uninitialized_var(hw);
+	const struct ath6kl_hw *hw;
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(hw_list); i++) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath6kl/main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath6kl/main.c
@@ -430,6 +430,9 @@
 
 	ath6kl_dbg(ATH6KL_DBG_TRC, "new station %pM aid=%d\n", mac_addr, aid);
 
+	if (aid < 1 || aid > AP_MAX_NUM_STA)
+		return;
+
 	if (assoc_req_len > sizeof(struct ieee80211_hdr_3addr)) {
 		struct ieee80211_mgmt *mgmt =
 			(struct ieee80211_mgmt *) assoc_info;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath6kl/usb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath6kl/usb.c
@@ -340,6 +340,11 @@
 				   le16_to_cpu(endpoint->wMaxPacketSize),
 				   endpoint->bInterval);
 		}
+
+		/* Ignore broken descriptors. */
+		if (usb_endpoint_maxp(endpoint) == 0)
+			continue;
+
 		urbcount = 0;
 
 		pipe_num =
@@ -907,7 +912,7 @@
 				 req,
 				 USB_DIR_IN | USB_TYPE_VENDOR |
 				 USB_RECIP_DEVICE, value, index, buf,
-				 size, 2 * HZ);
+				 size, 2000);
 
 	if (ret < 0) {
 		ath6kl_warn("Failed to read usb control message: %d\n", ret);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath6kl/wmi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -2510,8 +2510,10 @@
 		goto free_data_skb;
 
 	for (index = 0; index < num_pri_streams; index++) {
-		if (WARN_ON(!data_sync_bufs[index].skb))
+		if (WARN_ON(!data_sync_bufs[index].skb)) {
+			ret = -ENOMEM;
 			goto free_data_skb;
+		}
 
 		ep_id = ath6kl_ac2_endpoint_id(wmi->parent_dev,
 					       data_sync_bufs[index].
@@ -2645,6 +2647,11 @@
 		return -EINVAL;
 	}
 
+	if (tsid >= 16) {
+		ath6kl_err("invalid tsid: %d\n", tsid);
+		return -EINVAL;
+	}
+
 	skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
 	if (!skb)
 		return -ENOMEM;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath9k/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath9k/Kconfig
@@ -144,13 +144,13 @@
 	  a platform that can toggle the RF-Kill GPIO.
 
 config ATH9K_CHANNEL_CONTEXT
-       bool "Channel Context support"
-       depends on ATH9K
-       default n
-       ---help---
-	 This option enables channel context support in ath9k, which is needed
-	 for multi-channel concurrency. Enable this if P2P PowerSave support
-	 is required.
+	bool "Channel Context support"
+	depends on ATH9K
+	default n
+	---help---
+	  This option enables channel context support in ath9k, which is needed
+	  for multi-channel concurrency. Enable this if P2P PowerSave support
+	  is required.
 
 config ATH9K_PCOEM
 	bool "Atheros ath9k support for PC OEM cards" if EXPERT
@@ -162,32 +162,32 @@
 	depends on ATH9K_PCI
 	default n
 	help
-	 This separate driver provides a loader in order to support the
-	 AR500X to AR92XX-generation of ath9k PCI(e) WiFi chips, which have
-	 their initialization data (which contains the real PCI Device ID
-	 that ath9k will need) stored together with the calibration data out
-	 of reach for the ath9k chip.
+	  This separate driver provides a loader in order to support the
+	  AR500X to AR92XX-generation of ath9k PCI(e) WiFi chips, which have
+	  their initialization data (which contains the real PCI Device ID
+	  that ath9k will need) stored together with the calibration data out
+	  of reach for the ath9k chip.
 
-	 These devices are usually various network appliances, routers or
-	 access Points and such.
+	  These devices are usually various network appliances, routers or
+	  access Points and such.
 
-	 If unsure say N.
+	  If unsure say N.
 
 config ATH9K_HTC
-       tristate "Atheros HTC based wireless cards support"
-       depends on USB && MAC80211
-       select ATH9K_HW
-       select MAC80211_LEDS
-       select LEDS_CLASS
-       select NEW_LEDS
-       select ATH9K_COMMON
-       ---help---
-	 Support for Atheros HTC based cards.
-	 Chipsets supported: AR9271
+	tristate "Atheros HTC based wireless cards support"
+	depends on USB && MAC80211
+	select ATH9K_HW
+	select MAC80211_LEDS
+	select LEDS_CLASS
+	select NEW_LEDS
+	select ATH9K_COMMON
+	---help---
+	  Support for Atheros HTC based cards.
+	  Chipsets supported: AR9271
 
-	 For more information: http://wireless.kernel.org/en/users/Drivers/ath9k_htc
+	  For more information: http://wireless.kernel.org/en/users/Drivers/ath9k_htc
 
-	 The built module will be ath9k_htc.
+	  The built module will be ath9k_htc.
 
 config ATH9K_HTC_DEBUGFS
 	bool "Atheros ath9k_htc debugging"
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath9k/ahb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath9k/ahb.c
@@ -136,8 +136,8 @@
 
 	ah = sc->sc_ah;
 	ath9k_hw_name(ah, hw_name, sizeof(hw_name));
-	wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n",
-		   hw_name, (unsigned long)mem, irq);
+	wiphy_info(hw->wiphy, "%s mem=0x%p, irq=%d\n",
+		   hw_name, mem, irq);
 
 	return 0;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath9k/antenna.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath9k/antenna.c
@@ -643,7 +643,7 @@
 				conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1;
 				conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
 			} else if (antcomb->rssi_sub >
-				   antcomb->rssi_lna1) {
+				   antcomb->rssi_lna2) {
 				/* set to A-B */
 				conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1;
 				conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
@@ -3351,7 +3351,8 @@
 			"Found block at %x: code=%d ref=%d length=%d major=%d minor=%d\n",
 			cptr, code, reference, length, major, minor);
 		if ((!AR_SREV_9485(ah) && length >= 1024) ||
-		    (AR_SREV_9485(ah) && length > EEPROM_DATA_LEN_9485)) {
+		    (AR_SREV_9485(ah) && length > EEPROM_DATA_LEN_9485) ||
+		    (length > cptr)) {
 			ath_dbg(common, EEPROM, "Skipping bad header\n");
 			cptr -= COMP_HDR_LEN;
 			continue;
@@ -4183,7 +4184,7 @@
 
 static void ar9003_hw_thermo_cal_apply(struct ath_hw *ah)
 {
-	u32 data, ko, kg;
+	u32 data = 0, ko, kg;
 
 	if (!AR_SREV_9462_20_OR_LATER(ah))
 		return;
@@ -5614,7 +5615,7 @@
 
 static u8 ar9003_get_eepmisc(struct ath_hw *ah)
 {
-	return ah->eeprom.map4k.baseEepHeader.eepMisc;
+	return ah->eeprom.ar9300_eep.baseEepHeader.opCapFlags.eepMisc;
 }
 
 const struct eeprom_ops eep_ar9300_ops = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath9k/ar9003_hw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath9k/ar9003_hw.c
@@ -1099,17 +1099,22 @@
 {
 	u32 dma_dbg_chain, dma_dbg_complete;
 	u8 dcu_chain_state, dcu_complete_state;
+	unsigned int dbg_reg, reg_offset;
 	int i;
 
-	for (i = 0; i < NUM_STATUS_READS; i++) {
-		if (queue < 6)
-			dma_dbg_chain = REG_READ(ah, AR_DMADBG_4);
-		else
-			dma_dbg_chain = REG_READ(ah, AR_DMADBG_5);
+	if (queue < 6) {
+		dbg_reg = AR_DMADBG_4;
+		reg_offset = queue * 5;
+	} else {
+		dbg_reg = AR_DMADBG_5;
+		reg_offset = (queue - 6) * 5;
+	}
 
+	for (i = 0; i < NUM_STATUS_READS; i++) {
+		dma_dbg_chain = REG_READ(ah, dbg_reg);
 		dma_dbg_complete = REG_READ(ah, AR_DMADBG_6);
 
-		dcu_chain_state = (dma_dbg_chain >> (5 * queue)) & 0x1f;
+		dcu_chain_state = (dma_dbg_chain >> reg_offset) & 0x1f;
 		dcu_complete_state = dma_dbg_complete & 0x3;
 
 		if ((dcu_chain_state != 0x6) || (dcu_complete_state != 0x1))
@@ -1128,6 +1133,7 @@
 	u8 dcu_chain_state, dcu_complete_state;
 	bool dcu_wait_frdone = false;
 	unsigned long chk_dcu = 0;
+	unsigned int reg_offset;
 	unsigned int i = 0;
 
 	dma_dbg_4 = REG_READ(ah, AR_DMADBG_4);
@@ -1139,12 +1145,15 @@
 		goto exit;
 
 	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
-		if (i < 6)
+		if (i < 6) {
 			chk_dbg = dma_dbg_4;
-		else
+			reg_offset = i * 5;
+		} else {
 			chk_dbg = dma_dbg_5;
+			reg_offset = (i - 6) * 5;
+		}
 
-		dcu_chain_state = (chk_dbg >> (5 * i)) & 0x1f;
+		dcu_chain_state = (chk_dbg >> reg_offset) & 0x1f;
 		if (dcu_chain_state == 0x6) {
 			dcu_wait_frdone = true;
 			chk_dcu |= BIT(i);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath9k/ar9003_phy.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath9k/ar9003_phy.h
@@ -720,7 +720,7 @@
 #define AR_CH0_TOP2		(AR_SREV_9300(ah) ? 0x1628c : \
 					(AR_SREV_9462(ah) ? 0x16290 : 0x16284))
 #define AR_CH0_TOP2_XPABIASLVL		(AR_SREV_9561(ah) ? 0x1e00 : 0xf000)
-#define AR_CH0_TOP2_XPABIASLVL_S	12
+#define AR_CH0_TOP2_XPABIASLVL_S	(AR_SREV_9561(ah) ? 9 : 12)
 
 #define AR_CH0_XTAL		(AR_SREV_9300(ah) ? 0x16294 : \
 				 ((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x16298 : \
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath9k/ath9k.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -177,7 +177,8 @@
 	s8 txq;
 	u8 keyix;
 	u8 rtscts_rate;
-	u8 retries : 7;
+	u8 retries : 6;
+	u8 dyn_smps : 1;
 	u8 baw_tracked : 1;
 	u8 tx_power;
 	enum ath9k_key_type keytype:2;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath9k/ath9k_pci_owl_loader.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath9k/ath9k_pci_owl_loader.c
@@ -84,7 +84,7 @@
 			val = swahb32(val);
 		}
 
-		__raw_writel(val, mem + reg);
+		iowrite32(val, mem + reg);
 		usleep_range(100, 120);
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath9k/debug.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath9k/debug.c
@@ -1223,8 +1223,11 @@
 
 	ah->nf_override = val;
 
-	if (ah->curchan)
+	if (ah->curchan) {
+		ath9k_ps_wakeup(sc);
 		ath9k_hw_loadnf(ah, ah->curchan);
+		ath9k_ps_restore(sc);
+	}
 
 	return count;
 }
@@ -1281,7 +1284,7 @@
 			  u32 sset, u8 *data)
 {
 	if (sset == ETH_SS_STATS)
-		memcpy(data, *ath9k_gstrings_stats,
+		memcpy(data, ath9k_gstrings_stats,
 		       sizeof(ath9k_gstrings_stats));
 }
 
@@ -1313,11 +1316,11 @@
 	struct ath_softc *sc = hw->priv;
 	int i = 0;
 
-	data[i++] = (sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].tx_pkts_all +
+	data[i++] = ((u64)sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].tx_pkts_all +
 		     sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BK)].tx_pkts_all +
 		     sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VI)].tx_pkts_all +
 		     sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VO)].tx_pkts_all);
-	data[i++] = (sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].tx_bytes_all +
+	data[i++] = ((u64)sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BE)].tx_bytes_all +
 		     sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_BK)].tx_bytes_all +
 		     sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VI)].tx_bytes_all +
 		     sc->debug.stats.txstats[PR_QNUM(IEEE80211_AC_VO)].tx_bytes_all);
@@ -1368,8 +1371,6 @@
 
 	sc->debug.debugfs_phy = debugfs_create_dir("ath9k",
 						   sc->hw->wiphy->debugfsdir);
-	if (!sc->debug.debugfs_phy)
-		return -ENOMEM;
 
 #ifdef CONFIG_ATH_DEBUG
 	debugfs_create_file("debug", 0600, sc->debug.debugfs_phy,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -244,11 +244,11 @@
 		ath9k_htc_txcompletion_cb(hif_dev->htc_handle,
 					  skb, txok);
 		if (txok) {
-			TX_STAT_INC(skb_success);
-			TX_STAT_ADD(skb_success_bytes, ln);
+			TX_STAT_INC(hif_dev, skb_success);
+			TX_STAT_ADD(hif_dev, skb_success_bytes, ln);
 		}
 		else
-			TX_STAT_INC(skb_failed);
+			TX_STAT_INC(hif_dev, skb_failed);
 	}
 }
 
@@ -302,7 +302,7 @@
 	hif_dev->tx.tx_buf_cnt++;
 	if (!(hif_dev->tx.flags & HIF_USB_TX_STOP))
 		__hif_usb_tx(hif_dev); /* Check for pending SKBs */
-	TX_STAT_INC(buf_completed);
+	TX_STAT_INC(hif_dev, buf_completed);
 	spin_unlock(&hif_dev->tx.tx_lock);
 }
 
@@ -353,7 +353,7 @@
 			tx_buf->len += tx_buf->offset;
 
 		__skb_queue_tail(&tx_buf->skb_queue, nskb);
-		TX_STAT_INC(skb_queued);
+		TX_STAT_INC(hif_dev, skb_queued);
 	}
 
 	usb_fill_bulk_urb(tx_buf->urb, hif_dev->udev,
@@ -368,11 +368,10 @@
 		__skb_queue_head_init(&tx_buf->skb_queue);
 		list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf);
 		hif_dev->tx.tx_buf_cnt++;
+	} else {
+		TX_STAT_INC(hif_dev, buf_queued);
 	}
 
-	if (!ret)
-		TX_STAT_INC(buf_queued);
-
 	return ret;
 }
 
@@ -449,10 +448,19 @@
 	spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
 
 	/* The pending URBs have to be canceled. */
+	spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
 	list_for_each_entry_safe(tx_buf, tx_buf_tmp,
 				 &hif_dev->tx.tx_pending, list) {
+		usb_get_urb(tx_buf->urb);
+		spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
 		usb_kill_urb(tx_buf->urb);
+		list_del(&tx_buf->list);
+		usb_free_urb(tx_buf->urb);
+		kfree(tx_buf->buf);
+		kfree(tx_buf);
+		spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
 	}
+	spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
 
 	usb_kill_anchored_urbs(&hif_dev->mgmt_submitted);
 }
@@ -506,7 +514,7 @@
 			ath9k_htc_txcompletion_cb(hif_dev->htc_handle,
 						  skb, false);
 			hif_dev->tx.tx_skb_cnt--;
-			TX_STAT_INC(skb_failed);
+			TX_STAT_INC(hif_dev, skb_failed);
 		}
 	}
 
@@ -526,6 +534,24 @@
 	.send = hif_usb_send,
 };
 
+/* Need to free remain_skb allocated in ath9k_hif_usb_rx_stream
+ * in case ath9k_hif_usb_rx_stream wasn't called next time to
+ * process the buffer and subsequently free it.
+ */
+static void ath9k_hif_usb_free_rx_remain_skb(struct hif_device_usb *hif_dev)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hif_dev->rx_lock, flags);
+	if (hif_dev->remain_skb) {
+		dev_kfree_skb_any(hif_dev->remain_skb);
+		hif_dev->remain_skb = NULL;
+		hif_dev->rx_remain_len = 0;
+		RX_STAT_INC(hif_dev, skb_dropped);
+	}
+	spin_unlock_irqrestore(&hif_dev->rx_lock, flags);
+}
+
 static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
 				    struct sk_buff *skb)
 {
@@ -553,11 +579,11 @@
 			memcpy(ptr, skb->data, rx_remain_len);
 
 			rx_pkt_len += rx_remain_len;
-			hif_dev->rx_remain_len = 0;
 			skb_put(remain_skb, rx_pkt_len);
 
 			skb_pool[pool_index++] = remain_skb;
-
+			hif_dev->remain_skb = NULL;
+			hif_dev->rx_remain_len = 0;
 		} else {
 			index = rx_remain_len;
 		}
@@ -576,9 +602,21 @@
 		pkt_len = get_unaligned_le16(ptr + index);
 		pkt_tag = get_unaligned_le16(ptr + index + 2);
 
+		/* It is supposed that if we have an invalid pkt_tag or
+		 * pkt_len then the whole input SKB is considered invalid
+		 * and dropped; the associated packets already in skb_pool
+		 * are dropped, too.
+		 */
 		if (pkt_tag != ATH_USB_RX_STREAM_MODE_TAG) {
-			RX_STAT_INC(skb_dropped);
-			return;
+			RX_STAT_INC(hif_dev, skb_dropped);
+			goto invalid_pkt;
+		}
+
+		if (pkt_len > 2 * MAX_RX_BUF_SIZE) {
+			dev_err(&hif_dev->udev->dev,
+				"ath9k_htc: invalid pkt_len (%x)\n", pkt_len);
+			RX_STAT_INC(hif_dev, skb_dropped);
+			goto invalid_pkt;
 		}
 
 		pad_len = 4 - (pkt_len & 0x3);
@@ -590,11 +628,6 @@
 
 		if (index > MAX_RX_BUF_SIZE) {
 			spin_lock(&hif_dev->rx_lock);
-			hif_dev->rx_remain_len = index - MAX_RX_BUF_SIZE;
-			hif_dev->rx_transfer_len =
-				MAX_RX_BUF_SIZE - chk_idx - 4;
-			hif_dev->rx_pad_len = pad_len;
-
 			nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC);
 			if (!nskb) {
 				dev_err(&hif_dev->udev->dev,
@@ -602,8 +635,14 @@
 				spin_unlock(&hif_dev->rx_lock);
 				goto err;
 			}
+
+			hif_dev->rx_remain_len = index - MAX_RX_BUF_SIZE;
+			hif_dev->rx_transfer_len =
+				MAX_RX_BUF_SIZE - chk_idx - 4;
+			hif_dev->rx_pad_len = pad_len;
+
 			skb_reserve(nskb, 32);
-			RX_STAT_INC(skb_allocated);
+			RX_STAT_INC(hif_dev, skb_allocated);
 
 			memcpy(nskb->data, &(skb->data[chk_idx+4]),
 			       hif_dev->rx_transfer_len);
@@ -612,6 +651,11 @@
 			hif_dev->remain_skb = nskb;
 			spin_unlock(&hif_dev->rx_lock);
 		} else {
+			if (pool_index == MAX_PKT_NUM_IN_TRANSFER) {
+				dev_err(&hif_dev->udev->dev,
+					"ath9k_htc: over RX MAX_PKT_NUM\n");
+				goto err;
+			}
 			nskb = __dev_alloc_skb(pkt_len + 32, GFP_ATOMIC);
 			if (!nskb) {
 				dev_err(&hif_dev->udev->dev,
@@ -619,7 +663,7 @@
 				goto err;
 			}
 			skb_reserve(nskb, 32);
-			RX_STAT_INC(skb_allocated);
+			RX_STAT_INC(hif_dev, skb_allocated);
 
 			memcpy(nskb->data, &(skb->data[chk_idx+4]), pkt_len);
 			skb_put(nskb, pkt_len);
@@ -629,18 +673,25 @@
 
 err:
 	for (i = 0; i < pool_index; i++) {
-		RX_STAT_ADD(skb_completed_bytes, skb_pool[i]->len);
+		RX_STAT_ADD(hif_dev, skb_completed_bytes, skb_pool[i]->len);
 		ath9k_htc_rx_msg(hif_dev->htc_handle, skb_pool[i],
 				 skb_pool[i]->len, USB_WLAN_RX_PIPE);
-		RX_STAT_INC(skb_completed);
+		RX_STAT_INC(hif_dev, skb_completed);
 	}
+	return;
+invalid_pkt:
+	for (i = 0; i < pool_index; i++) {
+		dev_kfree_skb_any(skb_pool[i]);
+		RX_STAT_INC(hif_dev, skb_dropped);
+	}
+	return;
 }
 
 static void ath9k_hif_usb_rx_cb(struct urb *urb)
 {
-	struct sk_buff *skb = (struct sk_buff *) urb->context;
-	struct hif_device_usb *hif_dev =
-		usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
+	struct rx_buf *rx_buf = (struct rx_buf *)urb->context;
+	struct hif_device_usb *hif_dev = rx_buf->hif_dev;
+	struct sk_buff *skb = rx_buf->skb;
 	int ret;
 
 	if (!skb)
@@ -667,8 +718,7 @@
 	}
 
 resubmit:
-	skb_reset_tail_pointer(skb);
-	skb_trim(skb, 0);
+	__skb_set_length(skb, 0);
 
 	usb_anchor_urb(urb, &hif_dev->rx_submitted);
 	ret = usb_submit_urb(urb, GFP_ATOMIC);
@@ -680,21 +730,21 @@
 	return;
 free:
 	kfree_skb(skb);
+	kfree(rx_buf);
 }
 
 static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
 {
-	struct sk_buff *skb = (struct sk_buff *) urb->context;
-	struct sk_buff *nskb;
-	struct hif_device_usb *hif_dev =
-		usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
+	struct rx_buf *rx_buf = (struct rx_buf *)urb->context;
+	struct hif_device_usb *hif_dev = rx_buf->hif_dev;
+	struct sk_buff *skb = rx_buf->skb;
 	int ret;
 
 	if (!skb)
 		return;
 
 	if (!hif_dev)
-		goto free;
+		goto free_skb;
 
 	switch (urb->status) {
 	case 0:
@@ -703,10 +753,9 @@
 	case -ECONNRESET:
 	case -ENODEV:
 	case -ESHUTDOWN:
-		goto free;
+		goto free_skb;
 	default:
-		skb_reset_tail_pointer(skb);
-		skb_trim(skb, 0);
+		__skb_set_length(skb, 0);
 
 		goto resubmit;
 	}
@@ -714,24 +763,28 @@
 	if (likely(urb->actual_length != 0)) {
 		skb_put(skb, urb->actual_length);
 
-		/* Process the command first */
+		/*
+		 * Process the command first.
+		 * skb is either freed here or passed to be
+		 * managed to another callback function.
+		 */
 		ath9k_htc_rx_msg(hif_dev->htc_handle, skb,
 				 skb->len, USB_REG_IN_PIPE);
 
-
-		nskb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_ATOMIC);
-		if (!nskb) {
+		skb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_ATOMIC);
+		if (!skb) {
 			dev_err(&hif_dev->udev->dev,
 				"ath9k_htc: REG_IN memory allocation failure\n");
-			urb->context = NULL;
-			return;
+			goto free_rx_buf;
 		}
 
+		rx_buf->skb = skb;
+
 		usb_fill_int_urb(urb, hif_dev->udev,
 				 usb_rcvintpipe(hif_dev->udev,
 						 USB_REG_IN_PIPE),
-				 nskb->data, MAX_REG_IN_BUF_SIZE,
-				 ath9k_hif_usb_reg_in_cb, nskb, 1);
+				 skb->data, MAX_REG_IN_BUF_SIZE,
+				 ath9k_hif_usb_reg_in_cb, rx_buf, 1);
 	}
 
 resubmit:
@@ -739,12 +792,14 @@
 	ret = usb_submit_urb(urb, GFP_ATOMIC);
 	if (ret) {
 		usb_unanchor_urb(urb);
-		goto free;
+		goto free_skb;
 	}
 
 	return;
-free:
+free_skb:
 	kfree_skb(skb);
+free_rx_buf:
+	kfree(rx_buf);
 	urb->context = NULL;
 }
 
@@ -753,27 +808,33 @@
 	struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL;
 	unsigned long flags;
 
+	spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
 	list_for_each_entry_safe(tx_buf, tx_buf_tmp,
 				 &hif_dev->tx.tx_buf, list) {
-		usb_kill_urb(tx_buf->urb);
 		list_del(&tx_buf->list);
 		usb_free_urb(tx_buf->urb);
 		kfree(tx_buf->buf);
 		kfree(tx_buf);
 	}
+	spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
 
 	spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
 	hif_dev->tx.flags |= HIF_USB_TX_FLUSH;
 	spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
 
+	spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
 	list_for_each_entry_safe(tx_buf, tx_buf_tmp,
 				 &hif_dev->tx.tx_pending, list) {
+		usb_get_urb(tx_buf->urb);
+		spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
 		usb_kill_urb(tx_buf->urb);
 		list_del(&tx_buf->list);
 		usb_free_urb(tx_buf->urb);
 		kfree(tx_buf->buf);
 		kfree(tx_buf);
+		spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
 	}
+	spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
 
 	usb_kill_anchored_urbs(&hif_dev->mgmt_submitted);
 }
@@ -790,7 +851,7 @@
 	init_usb_anchor(&hif_dev->mgmt_submitted);
 
 	for (i = 0; i < MAX_TX_URB_NUM; i++) {
-		tx_buf = kzalloc(sizeof(struct tx_buf), GFP_KERNEL);
+		tx_buf = kzalloc(sizeof(*tx_buf), GFP_KERNEL);
 		if (!tx_buf)
 			goto err;
 
@@ -823,12 +884,14 @@
 static void ath9k_hif_usb_dealloc_rx_urbs(struct hif_device_usb *hif_dev)
 {
 	usb_kill_anchored_urbs(&hif_dev->rx_submitted);
+	ath9k_hif_usb_free_rx_remain_skb(hif_dev);
 }
 
 static int ath9k_hif_usb_alloc_rx_urbs(struct hif_device_usb *hif_dev)
 {
-	struct urb *urb = NULL;
+	struct rx_buf *rx_buf = NULL;
 	struct sk_buff *skb = NULL;
+	struct urb *urb = NULL;
 	int i, ret;
 
 	init_usb_anchor(&hif_dev->rx_submitted);
@@ -836,6 +899,12 @@
 
 	for (i = 0; i < MAX_RX_URB_NUM; i++) {
 
+		rx_buf = kzalloc(sizeof(*rx_buf), GFP_KERNEL);
+		if (!rx_buf) {
+			ret = -ENOMEM;
+			goto err_rxb;
+		}
+
 		/* Allocate URB */
 		urb = usb_alloc_urb(0, GFP_KERNEL);
 		if (urb == NULL) {
@@ -850,11 +919,14 @@
 			goto err_skb;
 		}
 
+		rx_buf->hif_dev = hif_dev;
+		rx_buf->skb = skb;
+
 		usb_fill_bulk_urb(urb, hif_dev->udev,
 				  usb_rcvbulkpipe(hif_dev->udev,
 						  USB_WLAN_RX_PIPE),
 				  skb->data, MAX_RX_BUF_SIZE,
-				  ath9k_hif_usb_rx_cb, skb);
+				  ath9k_hif_usb_rx_cb, rx_buf);
 
 		/* Anchor URB */
 		usb_anchor_urb(urb, &hif_dev->rx_submitted);
@@ -880,6 +952,8 @@
 err_skb:
 	usb_free_urb(urb);
 err_urb:
+	kfree(rx_buf);
+err_rxb:
 	ath9k_hif_usb_dealloc_rx_urbs(hif_dev);
 	return ret;
 }
@@ -891,14 +965,21 @@
 
 static int ath9k_hif_usb_alloc_reg_in_urbs(struct hif_device_usb *hif_dev)
 {
-	struct urb *urb = NULL;
+	struct rx_buf *rx_buf = NULL;
 	struct sk_buff *skb = NULL;
+	struct urb *urb = NULL;
 	int i, ret;
 
 	init_usb_anchor(&hif_dev->reg_in_submitted);
 
 	for (i = 0; i < MAX_REG_IN_URB_NUM; i++) {
 
+		rx_buf = kzalloc(sizeof(*rx_buf), GFP_KERNEL);
+		if (!rx_buf) {
+			ret = -ENOMEM;
+			goto err_rxb;
+		}
+
 		/* Allocate URB */
 		urb = usb_alloc_urb(0, GFP_KERNEL);
 		if (urb == NULL) {
@@ -913,11 +994,14 @@
 			goto err_skb;
 		}
 
+		rx_buf->hif_dev = hif_dev;
+		rx_buf->skb = skb;
+
 		usb_fill_int_urb(urb, hif_dev->udev,
 				  usb_rcvintpipe(hif_dev->udev,
 						  USB_REG_IN_PIPE),
 				  skb->data, MAX_REG_IN_BUF_SIZE,
-				  ath9k_hif_usb_reg_in_cb, skb, 1);
+				  ath9k_hif_usb_reg_in_cb, rx_buf, 1);
 
 		/* Anchor URB */
 		usb_anchor_urb(urb, &hif_dev->reg_in_submitted);
@@ -943,6 +1027,8 @@
 err_skb:
 	usb_free_urb(urb);
 err_urb:
+	kfree(rx_buf);
+err_rxb:
 	ath9k_hif_usb_dealloc_reg_in_urbs(hif_dev);
 	return ret;
 }
@@ -973,7 +1059,7 @@
 	return -ENOMEM;
 }
 
-static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev)
+void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev)
 {
 	usb_kill_anchored_urbs(&hif_dev->regout_submitted);
 	ath9k_hif_usb_dealloc_reg_in_urbs(hif_dev);
@@ -1216,7 +1302,7 @@
 static int send_eject_command(struct usb_interface *interface)
 {
 	struct usb_device *udev = interface_to_usbdev(interface);
-	struct usb_host_interface *iface_desc = &interface->altsetting[0];
+	struct usb_host_interface *iface_desc = interface->cur_altsetting;
 	struct usb_endpoint_descriptor *endpoint;
 	unsigned char *cmd;
 	u8 bulk_out_ep;
@@ -1271,10 +1357,24 @@
 static int ath9k_hif_usb_probe(struct usb_interface *interface,
 			       const struct usb_device_id *id)
 {
+	struct usb_endpoint_descriptor *bulk_in, *bulk_out, *int_in, *int_out;
 	struct usb_device *udev = interface_to_usbdev(interface);
+	struct usb_host_interface *alt;
 	struct hif_device_usb *hif_dev;
 	int ret = 0;
 
+	/* Verify the expected endpoints are present */
+	alt = interface->cur_altsetting;
+	if (usb_find_common_endpoints(alt, &bulk_in, &bulk_out, &int_in, &int_out) < 0 ||
+	    usb_endpoint_num(bulk_in) != USB_WLAN_RX_PIPE ||
+	    usb_endpoint_num(bulk_out) != USB_WLAN_TX_PIPE ||
+	    usb_endpoint_num(int_in) != USB_REG_IN_PIPE ||
+	    usb_endpoint_num(int_out) != USB_REG_OUT_PIPE) {
+		dev_err(&udev->dev,
+			"ath9k_htc: Device endpoint numbers are not the expected ones\n");
+		return -ENODEV;
+	}
+
 	if (id->driver_info == STORAGE_DEVICE)
 		return send_eject_command(interface);
 
@@ -1341,8 +1441,9 @@
 
 	if (hif_dev->flags & HIF_USB_READY) {
 		ath9k_htc_hw_deinit(hif_dev->htc_handle, unplugged);
-		ath9k_htc_hw_free(hif_dev->htc_handle);
 		ath9k_hif_usb_dev_deinit(hif_dev);
+		ath9k_destoy_wmi(hif_dev->htc_handle->drv_priv);
+		ath9k_htc_hw_free(hif_dev->htc_handle);
 	}
 
 	usb_set_intfdata(interface, NULL);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath9k/hif_usb.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath9k/hif_usb.h
@@ -86,6 +86,11 @@
 	struct list_head list;
 };
 
+struct rx_buf {
+	struct sk_buff *skb;
+	struct hif_device_usb *hif_dev;
+};
+
 #define HIF_USB_TX_STOP  BIT(0)
 #define HIF_USB_TX_FLUSH BIT(1)
 
@@ -133,5 +138,6 @@
 
 int ath9k_hif_usb_init(void);
 void ath9k_hif_usb_exit(void);
+void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev);
 
 #endif /* HTC_USB_H */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath9k/htc.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath9k/htc.h
@@ -325,14 +325,18 @@
 }
 
 #ifdef CONFIG_ATH9K_HTC_DEBUGFS
-
-#define TX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c++)
-#define TX_STAT_ADD(c, a) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c += a)
-#define RX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.skbrx_stats.c++)
-#define RX_STAT_ADD(c, a) (hif_dev->htc_handle->drv_priv->debug.skbrx_stats.c += a)
-#define CAB_STAT_INC   priv->debug.tx_stats.cab_queued++
-
-#define TX_QSTAT_INC(q) (priv->debug.tx_stats.queue_stats[q]++)
+#define __STAT_SAFE(hif_dev, expr)	do { ((hif_dev)->htc_handle->drv_priv ? (expr) : 0); } while (0)
+#define CAB_STAT_INC(priv)		do { ((priv)->debug.tx_stats.cab_queued++); } while (0)
+#define TX_QSTAT_INC(priv, q)		do { ((priv)->debug.tx_stats.queue_stats[q]++); } while (0)
+
+#define TX_STAT_INC(hif_dev, c) \
+		__STAT_SAFE((hif_dev), (hif_dev)->htc_handle->drv_priv->debug.tx_stats.c++)
+#define TX_STAT_ADD(hif_dev, c, a) \
+		__STAT_SAFE((hif_dev), (hif_dev)->htc_handle->drv_priv->debug.tx_stats.c += a)
+#define RX_STAT_INC(hif_dev, c) \
+		__STAT_SAFE((hif_dev), (hif_dev)->htc_handle->drv_priv->debug.skbrx_stats.c++)
+#define RX_STAT_ADD(hif_dev, c, a) \
+		__STAT_SAFE((hif_dev), (hif_dev)->htc_handle->drv_priv->debug.skbrx_stats.c += a)
 
 void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv,
 			   struct ath_rx_status *rs);
@@ -372,13 +376,13 @@
 			    struct ethtool_stats *stats, u64 *data);
 #else
 
-#define TX_STAT_INC(c) do { } while (0)
-#define TX_STAT_ADD(c, a) do { } while (0)
-#define RX_STAT_INC(c) do { } while (0)
-#define RX_STAT_ADD(c, a) do { } while (0)
-#define CAB_STAT_INC   do { } while (0)
+#define TX_STAT_INC(hif_dev, c)		do { } while (0)
+#define TX_STAT_ADD(hif_dev, c, a)	do { } while (0)
+#define RX_STAT_INC(hif_dev, c)		do { } while (0)
+#define RX_STAT_ADD(hif_dev, c, a)	do { } while (0)
 
-#define TX_QSTAT_INC(c) do { } while (0)
+#define CAB_STAT_INC(priv)
+#define TX_QSTAT_INC(priv, c)
 
 static inline void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv,
 					 struct ath_rx_status *rs)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
@@ -428,7 +428,7 @@
 			      u32 sset, u8 *data)
 {
 	if (sset == ETH_SS_STATS)
-		memcpy(data, *ath9k_htc_gstrings_stats,
+		memcpy(data, ath9k_htc_gstrings_stats,
 		       sizeof(ath9k_htc_gstrings_stats));
 }
 
@@ -491,8 +491,6 @@
 
 	priv->debug.debugfs_phy = debugfs_create_dir(KBUILD_MODNAME,
 					     priv->hw->wiphy->debugfsdir);
-	if (!priv->debug.debugfs_phy)
-		return -ENOMEM;
 
 	ath9k_cmn_spectral_init_debug(&priv->spec_priv, priv->debug.debugfs_phy);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -246,7 +246,7 @@
 	if (unlikely(r)) {
 		ath_dbg(common, WMI, "REGISTER READ FAILED: (0x%04x, %d)\n",
 			reg_offset, r);
-		return -EIO;
+		return -1;
 	}
 
 	return be32_to_cpu(val);
@@ -931,8 +931,9 @@
 int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
 			   u16 devid, char *product, u32 drv_info)
 {
-	struct ieee80211_hw *hw;
+	struct hif_device_usb *hif_dev;
 	struct ath9k_htc_priv *priv;
+	struct ieee80211_hw *hw;
 	int ret;
 
 	hw = ieee80211_alloc_hw(sizeof(struct ath9k_htc_priv), &ath9k_htc_ops);
@@ -943,7 +944,6 @@
 	priv->hw = hw;
 	priv->htc = htc_handle;
 	priv->dev = dev;
-	htc_handle->drv_priv = priv;
 	SET_IEEE80211_DEV(hw, priv->dev);
 
 	ret = ath9k_htc_wait_for_target(priv);
@@ -964,10 +964,15 @@
 	if (ret)
 		goto err_init;
 
+	htc_handle->drv_priv = priv;
+
 	return 0;
 
 err_init:
-	ath9k_deinit_wmi(priv);
+	ath9k_stop_wmi(priv);
+	hif_dev = (struct hif_device_usb *)htc_handle->hif_dev;
+	ath9k_hif_usb_dealloc_urbs(hif_dev);
+	ath9k_destoy_wmi(priv);
 err_free:
 	ieee80211_free_hw(hw);
 	return ret;
@@ -982,7 +987,7 @@
 			htc_handle->drv_priv->ah->ah_flags |= AH_UNPLUGGED;
 
 		ath9k_deinit_device(htc_handle->drv_priv);
-		ath9k_deinit_wmi(htc_handle->drv_priv);
+		ath9k_stop_wmi(htc_handle->drv_priv);
 		ieee80211_free_hw(htc_handle->drv_priv->hw);
 	}
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -1460,7 +1460,7 @@
 		}
 		break;
 	case DISABLE_KEY:
-		ath_key_delete(common, key);
+		ath_key_delete(common, key->hw_key_idx);
 		break;
 	default:
 		ret = -EINVAL;
@@ -1674,7 +1674,7 @@
 	case IEEE80211_AMPDU_TX_START:
 		ret = ath9k_htc_tx_aggr_oper(priv, vif, sta, action, tid);
 		if (!ret)
-			ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+			ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
 		break;
 	case IEEE80211_AMPDU_TX_STOP_CONT:
 	case IEEE80211_AMPDU_TX_STOP_FLUSH:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -106,20 +106,20 @@
 
 	switch (qnum) {
 	case 0:
-		TX_QSTAT_INC(IEEE80211_AC_VO);
+		TX_QSTAT_INC(priv, IEEE80211_AC_VO);
 		epid = priv->data_vo_ep;
 		break;
 	case 1:
-		TX_QSTAT_INC(IEEE80211_AC_VI);
+		TX_QSTAT_INC(priv, IEEE80211_AC_VI);
 		epid = priv->data_vi_ep;
 		break;
 	case 2:
-		TX_QSTAT_INC(IEEE80211_AC_BE);
+		TX_QSTAT_INC(priv, IEEE80211_AC_BE);
 		epid = priv->data_be_ep;
 		break;
 	case 3:
 	default:
-		TX_QSTAT_INC(IEEE80211_AC_BK);
+		TX_QSTAT_INC(priv, IEEE80211_AC_BK);
 		epid = priv->data_bk_ep;
 		break;
 	}
@@ -323,7 +323,7 @@
 	memcpy(tx_fhdr, (u8 *) &tx_hdr, sizeof(tx_hdr));
 
 	if (is_cab) {
-		CAB_STAT_INC;
+		CAB_STAT_INC(priv);
 		tx_ctl->epid = priv->cab_ep;
 		return;
 	}
@@ -647,9 +647,10 @@
 	struct ath9k_htc_tx_event *tx_pend;
 	int i;
 
-	for (i = 0; i < txs->cnt; i++) {
-		WARN_ON(txs->cnt > HTC_MAX_TX_STATUS);
+	if (WARN_ON_ONCE(txs->cnt > HTC_MAX_TX_STATUS))
+		return;
 
+	for (i = 0; i < txs->cnt; i++) {
 		__txs = &txs->txstatus[i];
 
 		skb = ath9k_htc_tx_get_packet(priv, __txs);
@@ -973,6 +974,8 @@
 	struct ath_htc_rx_status *rxstatus;
 	struct ath_rx_status rx_stats;
 	bool decrypt_error = false;
+	u16 rs_datalen;
+	bool is_phyerr;
 
 	if (skb->len < HTC_RX_FRAME_HEADER_SIZE) {
 		ath_err(common, "Corrupted RX frame, dropping (len: %d)\n",
@@ -982,11 +985,32 @@
 
 	rxstatus = (struct ath_htc_rx_status *)skb->data;
 
-	if (be16_to_cpu(rxstatus->rs_datalen) -
-	    (skb->len - HTC_RX_FRAME_HEADER_SIZE) != 0) {
+	rs_datalen = be16_to_cpu(rxstatus->rs_datalen);
+	if (unlikely(rs_datalen -
+	    (skb->len - HTC_RX_FRAME_HEADER_SIZE) != 0)) {
 		ath_err(common,
 			"Corrupted RX data len, dropping (dlen: %d, skblen: %d)\n",
-			rxstatus->rs_datalen, skb->len);
+			rs_datalen, skb->len);
+		goto rx_next;
+	}
+
+	is_phyerr = rxstatus->rs_status & ATH9K_RXERR_PHY;
+	/*
+	 * Discard zero-length packets and packets smaller than an ACK
+	 * which are not PHY_ERROR (short radar pulses have a length of 3)
+	 */
+	if (unlikely(!rs_datalen || (rs_datalen < 10 && !is_phyerr))) {
+		ath_dbg(common, ANY,
+			"Short RX data len, dropping (dlen: %d)\n",
+			rs_datalen);
+		goto rx_next;
+	}
+
+	if (rxstatus->rs_keyix >= ATH_KEYMAX &&
+	    rxstatus->rs_keyix != ATH9K_RXKEYIX_INVALID) {
+		ath_dbg(common, ANY,
+			"Invalid keyix, dropping (keyix: %d)\n",
+			rxstatus->rs_keyix);
 		goto rx_next;
 	}
 
@@ -1011,7 +1035,7 @@
 	 * Process PHY errors and return so that the packet
 	 * can be dropped.
 	 */
-	if (rx_stats.rs_status & ATH9K_RXERR_PHY) {
+	if (unlikely(is_phyerr)) {
 		/* TODO: Not using DFS processing now. */
 		if (ath_cmn_process_fft(&priv->spec_priv, hdr,
 				    &rx_stats, rx_status->mactime)) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath9k/htc_hst.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath9k/htc_hst.c
@@ -30,6 +30,7 @@
 	hdr->endpoint_id = epid;
 	hdr->flags = flags;
 	hdr->payload_len = cpu_to_be16(len);
+	memset(hdr->control, 0, sizeof(hdr->control));
 
 	status = target->hif->send(target->hif_dev, endpoint->ul_pipeid, skb);
 
@@ -113,6 +114,15 @@
 
 	if (svc_rspmsg->status == HTC_SERVICE_SUCCESS) {
 		epid = svc_rspmsg->endpoint_id;
+
+		/* Check that the received epid for the endpoint to attach
+		 * a new service is valid. ENDPOINT0 can't be used here as it
+		 * is already reserved for HTC_CTRL_RSVD_SVC service and thus
+		 * should not be modified.
+		 */
+		if (epid <= ENDPOINT0 || epid >= ENDPOINT_MAX)
+			return;
+
 		service_id = be16_to_cpu(svc_rspmsg->service_id);
 		max_msglen = be16_to_cpu(svc_rspmsg->max_msg_len);
 		endpoint = &target->endpoint[epid];
@@ -170,7 +180,6 @@
 	time_left = wait_for_completion_timeout(&target->cmd_wait, HZ);
 	if (!time_left) {
 		dev_err(target->dev, "HTC credit config timeout\n");
-		kfree_skb(skb);
 		return -ETIMEDOUT;
 	}
 
@@ -206,7 +215,6 @@
 	time_left = wait_for_completion_timeout(&target->cmd_wait, HZ);
 	if (!time_left) {
 		dev_err(target->dev, "HTC start timeout\n");
-		kfree_skb(skb);
 		return -ETIMEDOUT;
 	}
 
@@ -271,6 +279,10 @@
 	conn_msg->dl_pipeid = endpoint->dl_pipeid;
 	conn_msg->ul_pipeid = endpoint->ul_pipeid;
 
+	/* To prevent infoleak */
+	conn_msg->svc_meta_len = 0;
+	conn_msg->pad = 0;
+
 	ret = htc_issue_send(target, skb, skb->len, 0, ENDPOINT0);
 	if (ret)
 		goto err;
@@ -279,10 +291,12 @@
 	if (!time_left) {
 		dev_err(target->dev, "Service connection timeout for: %d\n",
 			service_connreq->service_id);
-		kfree_skb(skb);
 		return -ETIMEDOUT;
 	}
 
+	if (target->conn_rsp_epid < 0 || target->conn_rsp_epid >= ENDPOINT_MAX)
+		return -EINVAL;
+
 	*conn_rsp_epid = target->conn_rsp_epid;
 	return 0;
 err:
@@ -339,6 +353,8 @@
 
 	if (skb) {
 		htc_hdr = (struct htc_frame_hdr *) skb->data;
+		if (htc_hdr->endpoint_id >= ARRAY_SIZE(htc_handle->endpoint))
+			goto ret;
 		endpoint = &htc_handle->endpoint[htc_hdr->endpoint_id];
 		skb_pull(skb, sizeof(struct htc_frame_hdr));
 
@@ -357,40 +373,34 @@
 }
 
 static void ath9k_htc_fw_panic_report(struct htc_target *htc_handle,
-				      struct sk_buff *skb)
+				      struct sk_buff *skb, u32 len)
 {
 	uint32_t *pattern = (uint32_t *)skb->data;
 
-	switch (*pattern) {
-	case 0x33221199:
-		{
+	if (*pattern == 0x33221199 && len >= sizeof(struct htc_panic_bad_vaddr)) {
 		struct htc_panic_bad_vaddr *htc_panic;
 		htc_panic = (struct htc_panic_bad_vaddr *) skb->data;
 		dev_err(htc_handle->dev, "ath: firmware panic! "
 			"exccause: 0x%08x; pc: 0x%08x; badvaddr: 0x%08x.\n",
 			htc_panic->exccause, htc_panic->pc,
 			htc_panic->badvaddr);
-		break;
-		}
-	case 0x33221299:
-		{
+		return;
+	}
+	if (*pattern == 0x33221299) {
 		struct htc_panic_bad_epid *htc_panic;
 		htc_panic = (struct htc_panic_bad_epid *) skb->data;
 		dev_err(htc_handle->dev, "ath: firmware panic! "
 			"bad epid: 0x%08x\n", htc_panic->epid);
-		break;
-		}
-	default:
-		dev_err(htc_handle->dev, "ath: unknown panic pattern!\n");
-		break;
+		return;
 	}
+	dev_err(htc_handle->dev, "ath: unknown panic pattern!\n");
 }
 
 /*
  * HTC Messages are handled directly here and the obtained SKB
  * is freed.
  *
- * Service messages (Data, WMI) passed to the corresponding
+ * Service messages (Data, WMI) are passed to the corresponding
  * endpoint RX handlers, which have to free the SKB.
  */
 void ath9k_htc_rx_msg(struct htc_target *htc_handle,
@@ -404,16 +414,26 @@
 	if (!htc_handle || !skb)
 		return;
 
+	/* A valid message requires len >= 8.
+	 *
+	 *   sizeof(struct htc_frame_hdr) == 8
+	 *   sizeof(struct htc_ready_msg) == 8
+	 *   sizeof(struct htc_panic_bad_vaddr) == 16
+	 *   sizeof(struct htc_panic_bad_epid) == 8
+	 */
+	if (unlikely(len < sizeof(struct htc_frame_hdr)))
+		goto invalid;
 	htc_hdr = (struct htc_frame_hdr *) skb->data;
 	epid = htc_hdr->endpoint_id;
 
 	if (epid == 0x99) {
-		ath9k_htc_fw_panic_report(htc_handle, skb);
+		ath9k_htc_fw_panic_report(htc_handle, skb, len);
 		kfree_skb(skb);
 		return;
 	}
 
 	if (epid < 0 || epid >= ENDPOINT_MAX) {
+invalid:
 		if (pipe_id != USB_REG_IN_PIPE)
 			dev_kfree_skb_any(skb);
 		else
@@ -425,21 +445,30 @@
 
 		/* Handle trailer */
 		if (htc_hdr->flags & HTC_FLAGS_RECV_TRAILER) {
-			if (be32_to_cpu(*(__be32 *) skb->data) == 0x00C60000)
+			if (be32_to_cpu(*(__be32 *) skb->data) == 0x00C60000) {
 				/* Move past the Watchdog pattern */
 				htc_hdr = (struct htc_frame_hdr *)(skb->data + 4);
+				len -= 4;
+			}
 		}
 
 		/* Get the message ID */
+		if (unlikely(len < sizeof(struct htc_frame_hdr) + sizeof(__be16)))
+			goto invalid;
 		msg_id = (__be16 *) ((void *) htc_hdr +
 				     sizeof(struct htc_frame_hdr));
 
 		/* Now process HTC messages */
 		switch (be16_to_cpu(*msg_id)) {
 		case HTC_MSG_READY_ID:
+			if (unlikely(len < sizeof(struct htc_ready_msg)))
+				goto invalid;
 			htc_process_target_rdy(htc_handle, htc_hdr);
 			break;
 		case HTC_MSG_CONNECT_SERVICE_RESPONSE_ID:
+			if (unlikely(len < sizeof(struct htc_frame_hdr) +
+				     sizeof(struct htc_conn_svc_rspmsg)))
+				goto invalid;
 			htc_process_conn_rsp(htc_handle, htc_hdr);
 			break;
 		default:
@@ -458,6 +487,8 @@
 		if (endpoint->ep_callbacks.rx)
 			endpoint->ep_callbacks.rx(endpoint->ep_callbacks.priv,
 						  skb, epid);
+		else
+			goto invalid;
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath9k/hw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath9k/hw.c
@@ -287,7 +287,7 @@
 
 	srev = REG_READ(ah, AR_SREV);
 
-	if (srev == -EIO) {
+	if (srev == -1) {
 		ath_err(ath9k_hw_common(ah),
 			"Failed to read SREV register");
 		return false;
@@ -1622,7 +1622,6 @@
 		ath9k_hw_gpio_request_out(ah, i, NULL,
 					  AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
 		ath9k_hw_set_gpio(ah, i, !!(ah->gpio_val & BIT(i)));
-		ath9k_hw_gpio_free(ah, i);
 	}
 }
 
@@ -2730,14 +2729,17 @@
 static void ath9k_hw_gpio_cfg_soc(struct ath_hw *ah, u32 gpio, bool out,
 				  const char *label)
 {
+	int err;
+
 	if (ah->caps.gpio_requested & BIT(gpio))
 		return;
 
-	/* may be requested by BSP, free anyway */
-	gpio_free(gpio);
-
-	if (gpio_request_one(gpio, out ? GPIOF_OUT_INIT_LOW : GPIOF_IN, label))
+	err = gpio_request_one(gpio, out ? GPIOF_OUT_INIT_LOW : GPIOF_IN, label);
+	if (err) {
+		ath_err(ath9k_hw_common(ah), "request GPIO%d failed:%d\n",
+			gpio, err);
 		return;
+	}
 
 	ah->caps.gpio_requested |= BIT(gpio);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath9k/hw.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath9k/hw.h
@@ -819,6 +819,7 @@
 	struct ath9k_pacal_info pacal_info;
 	struct ar5416Stats stats;
 	struct ath9k_tx_queue_info txq[ATH9K_NUM_TX_QUEUES];
+	DECLARE_BITMAP(pending_del_keymap, ATH_KEYMAX);
 
 	enum ath9k_int imask;
 	u32 imrs2_reg;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath9k/init.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath9k/init.c
@@ -230,7 +230,7 @@
 	struct ath_hw *ah = hw_priv;
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath_softc *sc = (struct ath_softc *) common->priv;
-	unsigned long uninitialized_var(flags);
+	unsigned long flags;
 	u32 val;
 
 	if (NR_CPUS > 1 && ah->config.serialize_regmode == SER_REG_MODE_ON) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath9k/main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath9k/main.c
@@ -200,7 +200,7 @@
 void ath_restart_work(struct ath_softc *sc)
 {
 	ieee80211_queue_delayed_work(sc->hw, &sc->hw_check_work,
-				     ATH_HW_CHECK_POLL_INT);
+				     msecs_to_jiffies(ATH_HW_CHECK_POLL_INT));
 
 	if (AR_SREV_9340(sc->sc_ah) || AR_SREV_9330(sc->sc_ah))
 		ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work,
@@ -304,6 +304,11 @@
 		hchan = ah->curchan;
 	}
 
+	if (!hchan) {
+		fastcc = false;
+		hchan = ath9k_cmn_get_channel(sc->hw, ah, &sc->cur_chan->chandef);
+	}
+
 	if (!ath_prepare_reset(sc))
 		fastcc = false;
 
@@ -525,8 +530,10 @@
 	ath9k_debug_sync_cause(sc, sync_cause);
 	status &= ah->imask;	/* discard unasked-for bits */
 
-	if (test_bit(ATH_OP_HW_RESET, &common->op_flags))
+	if (test_bit(ATH_OP_HW_RESET, &common->op_flags)) {
+		ath9k_hw_kill_interrupts(sc->sc_ah);
 		return IRQ_HANDLED;
+	}
 
 	/*
 	 * If there are no status bits set, then this interrupt was not
@@ -818,12 +825,81 @@
 	ieee80211_free_txskb(hw, skb);
 }
 
+static bool ath9k_txq_list_has_key(struct list_head *txq_list, u32 keyix)
+{
+	struct ath_buf *bf;
+	struct ieee80211_tx_info *txinfo;
+	struct ath_frame_info *fi;
+
+	list_for_each_entry(bf, txq_list, list) {
+		if (bf->bf_state.stale || !bf->bf_mpdu)
+			continue;
+
+		txinfo = IEEE80211_SKB_CB(bf->bf_mpdu);
+		fi = (struct ath_frame_info *)&txinfo->status.status_driver_data[0];
+		if (fi->keyix == keyix)
+			return true;
+	}
+
+	return false;
+}
+
+static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix)
+{
+	struct ath_hw *ah = sc->sc_ah;
+	int i, j;
+	struct ath_txq *txq;
+	bool key_in_use = false;
+
+	for (i = 0; !key_in_use && i < ATH9K_NUM_TX_QUEUES; i++) {
+		if (!ATH_TXQ_SETUP(sc, i))
+			continue;
+		txq = &sc->tx.txq[i];
+		if (!txq->axq_depth)
+			continue;
+		if (!ath9k_hw_numtxpending(ah, txq->axq_qnum))
+			continue;
+
+		ath_txq_lock(sc, txq);
+		key_in_use = ath9k_txq_list_has_key(&txq->axq_q, keyix);
+		if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+			int idx = txq->txq_tailidx;
+
+			for (j = 0; !key_in_use &&
+			     !list_empty(&txq->txq_fifo[idx]) &&
+			     j < ATH_TXFIFO_DEPTH; j++) {
+				key_in_use = ath9k_txq_list_has_key(
+					&txq->txq_fifo[idx], keyix);
+				INCR(idx, ATH_TXFIFO_DEPTH);
+			}
+		}
+		ath_txq_unlock(sc, txq);
+	}
+
+	return key_in_use;
+}
+
+static void ath9k_pending_key_del(struct ath_softc *sc, u8 keyix)
+{
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_common *common = ath9k_hw_common(ah);
+
+	if (!test_bit(keyix, ah->pending_del_keymap) ||
+	    ath9k_txq_has_key(sc, keyix))
+		return;
+
+	/* No more TXQ frames point to this key cache entry, so delete it. */
+	clear_bit(keyix, ah->pending_del_keymap);
+	ath_key_delete(common, keyix);
+}
+
 static void ath9k_stop(struct ieee80211_hw *hw)
 {
 	struct ath_softc *sc = hw->priv;
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
 	bool prev_idle;
+	int i;
 
 	ath9k_deinit_channel_context(sc);
 
@@ -891,6 +967,14 @@
 
 	spin_unlock_bh(&sc->sc_pcu_lock);
 
+	for (i = 0; i < ATH_KEYMAX; i++)
+		ath9k_pending_key_del(sc, i);
+
+	/* Clear key cache entries explicitly to get rid of any potentially
+	 * remaining keys.
+	 */
+	ath9k_cmn_init_crypto(sc->sc_ah);
+
 	ath9k_ps_restore(sc);
 
 	sc->ps_idle = prev_idle;
@@ -1457,6 +1541,9 @@
 		ath_chanctx_set_channel(sc, ctx, &hw->conf.chandef);
 	}
 
+	if (changed & IEEE80211_CONF_CHANGE_POWER)
+		ath9k_set_txpower(sc, NULL);
+
 	mutex_unlock(&sc->mutex);
 	ath9k_ps_restore(sc);
 
@@ -1533,12 +1620,11 @@
 {
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	struct ath_node *an = (struct ath_node *) sta->drv_priv;
-	struct ieee80211_key_conf ps_key = { .hw_key_idx = an->ps_key };
 
 	if (!an->ps_key)
 	    return;
 
-	ath_key_delete(common, &ps_key);
+	ath_key_delete(common, an->ps_key);
 	an->ps_key = 0;
 	an->key_idx[0] = 0;
 }
@@ -1700,6 +1786,12 @@
 	if (sta)
 		an = (struct ath_node *)sta->drv_priv;
 
+	/* Delete pending key cache entries if no more frames are pointing to
+	 * them in TXQs.
+	 */
+	for (i = 0; i < ATH_KEYMAX; i++)
+		ath9k_pending_key_del(sc, i);
+
 	switch (cmd) {
 	case SET_KEY:
 		if (sta)
@@ -1729,7 +1821,15 @@
 		}
 		break;
 	case DISABLE_KEY:
-		ath_key_delete(common, key);
+		if (ath9k_txq_has_key(sc, key->hw_key_idx)) {
+			/* Delay key cache entry deletion until there are no
+			 * remaining TXQ frames pointing to this entry.
+			 */
+			set_bit(key->hw_key_idx, sc->sc_ah->pending_del_keymap);
+			ath_hw_keysetmac(common, key->hw_key_idx, NULL);
+		} else {
+			ath_key_delete(common, key->hw_key_idx);
+		}
 		if (an) {
 			for (i = 0; i < ARRAY_SIZE(an->key_idx); i++) {
 				if (an->key_idx[i] != key->hw_key_idx)
@@ -1921,7 +2021,7 @@
 		ath9k_ps_wakeup(sc);
 		ret = ath_tx_aggr_start(sc, sta, tid, ssn);
 		if (!ret)
-			ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+			ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
 		ath9k_ps_restore(sc);
 		break;
 	case IEEE80211_AMPDU_TX_STOP_FLUSH:
@@ -2128,7 +2228,7 @@
 	}
 
 	ieee80211_queue_delayed_work(hw, &sc->hw_check_work,
-				     ATH_HW_CHECK_POLL_INT);
+				     msecs_to_jiffies(ATH_HW_CHECK_POLL_INT));
 }
 
 static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath9k/pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath9k/pci.c
@@ -993,8 +993,8 @@
 	sc->sc_ah->msi_reg = 0;
 
 	ath9k_hw_name(sc->sc_ah, hw_name, sizeof(hw_name));
-	wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n",
-		   hw_name, (unsigned long)sc->mem, pdev->irq);
+	wiphy_info(hw->wiphy, "%s mem=0x%p, irq=%d\n",
+		   hw_name, sc->mem, pdev->irq);
 
 	return 0;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath9k/wmi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath9k/wmi.c
@@ -112,14 +112,17 @@
 	return wmi;
 }
 
-void ath9k_deinit_wmi(struct ath9k_htc_priv *priv)
+void ath9k_stop_wmi(struct ath9k_htc_priv *priv)
 {
 	struct wmi *wmi = priv->wmi;
 
 	mutex_lock(&wmi->op_mutex);
 	wmi->stopped = true;
 	mutex_unlock(&wmi->op_mutex);
+}
 
+void ath9k_destoy_wmi(struct ath9k_htc_priv *priv)
+{
 	kfree(priv->wmi);
 }
 
@@ -215,6 +218,10 @@
 	if (unlikely(wmi->stopped))
 		goto free_skb;
 
+	/* Validate the obtained SKB. */
+	if (unlikely(skb->len < sizeof(struct wmi_cmd_hdr)))
+		goto free_skb;
+
 	hdr = (struct wmi_cmd_hdr *) skb->data;
 	cmd_id = be16_to_cpu(hdr->command_id);
 
@@ -232,10 +239,10 @@
 		spin_unlock_irqrestore(&wmi->wmi_lock, flags);
 		goto free_skb;
 	}
-	spin_unlock_irqrestore(&wmi->wmi_lock, flags);
 
 	/* WMI command response */
 	ath9k_wmi_rsp_callback(wmi, skb);
+	spin_unlock_irqrestore(&wmi->wmi_lock, flags);
 
 free_skb:
 	kfree_skb(skb);
@@ -273,7 +280,8 @@
 
 static int ath9k_wmi_cmd_issue(struct wmi *wmi,
 			       struct sk_buff *skb,
-			       enum wmi_cmd_id cmd, u16 len)
+			       enum wmi_cmd_id cmd, u16 len,
+			       u8 *rsp_buf, u32 rsp_len)
 {
 	struct wmi_cmd_hdr *hdr;
 	unsigned long flags;
@@ -283,6 +291,11 @@
 	hdr->seq_no = cpu_to_be16(++wmi->tx_seq_id);
 
 	spin_lock_irqsave(&wmi->wmi_lock, flags);
+
+	/* record the rsp buffer and length */
+	wmi->cmd_rsp_buf = rsp_buf;
+	wmi->cmd_rsp_len = rsp_len;
+
 	wmi->last_seq_id = wmi->tx_seq_id;
 	spin_unlock_irqrestore(&wmi->wmi_lock, flags);
 
@@ -298,8 +311,8 @@
 	struct ath_common *common = ath9k_hw_common(ah);
 	u16 headroom = sizeof(struct htc_frame_hdr) +
 		       sizeof(struct wmi_cmd_hdr);
+	unsigned long time_left, flags;
 	struct sk_buff *skb;
-	unsigned long time_left;
 	int ret = 0;
 
 	if (ah->ah_flags & AH_UNPLUGGED)
@@ -323,11 +336,7 @@
 		goto out;
 	}
 
-	/* record the rsp buffer and length */
-	wmi->cmd_rsp_buf = rsp_buf;
-	wmi->cmd_rsp_len = rsp_len;
-
-	ret = ath9k_wmi_cmd_issue(wmi, skb, cmd_id, cmd_len);
+	ret = ath9k_wmi_cmd_issue(wmi, skb, cmd_id, cmd_len, rsp_buf, rsp_len);
 	if (ret)
 		goto out;
 
@@ -335,8 +344,10 @@
 	if (!time_left) {
 		ath_dbg(common, WMI, "Timeout waiting for WMI command: %s\n",
 			wmi_cmd_to_name(cmd_id));
+		spin_lock_irqsave(&wmi->wmi_lock, flags);
+		wmi->last_seq_id = 0;
+		spin_unlock_irqrestore(&wmi->wmi_lock, flags);
 		mutex_unlock(&wmi->op_mutex);
-		kfree_skb(skb);
 		return -ETIMEDOUT;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath9k/wmi.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath9k/wmi.h
@@ -179,7 +179,6 @@
 };
 
 struct wmi *ath9k_init_wmi(struct ath9k_htc_priv *priv);
-void ath9k_deinit_wmi(struct ath9k_htc_priv *priv);
 int ath9k_wmi_connect(struct htc_target *htc, struct wmi *wmi,
 		      enum htc_endpoint_id *wmi_ctrl_epid);
 int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
@@ -189,6 +188,8 @@
 void ath9k_wmi_event_tasklet(unsigned long data);
 void ath9k_fatal_work(struct work_struct *work);
 void ath9k_wmi_event_drain(struct ath9k_htc_priv *priv);
+void ath9k_stop_wmi(struct ath9k_htc_priv *priv);
+void ath9k_destoy_wmi(struct ath9k_htc_priv *priv);
 
 #define WMI_CMD(_wmi_cmd)						\
 	do {								\
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/ath9k/xmit.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/ath9k/xmit.c
@@ -141,8 +141,8 @@
 {
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
 	BUILD_BUG_ON(sizeof(struct ath_frame_info) >
-		     sizeof(tx_info->rate_driver_data));
-	return (struct ath_frame_info *) &tx_info->rate_driver_data[0];
+		     sizeof(tx_info->status.status_driver_data));
+	return (struct ath_frame_info *) &tx_info->status.status_driver_data[0];
 }
 
 static void ath_send_bar(struct ath_atx_tid *tid, u16 seqno)
@@ -1271,6 +1271,11 @@
 				 is_40, is_sgi, is_sp);
 			if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC))
 				info->rates[i].RateFlags |= ATH9K_RATESERIES_STBC;
+			if (rix >= 8 && fi->dyn_smps) {
+				info->rates[i].RateFlags |=
+					ATH9K_RATESERIES_RTS_CTS;
+				info->flags |= ATH9K_TXDESC_CTSENA;
+			}
 
 			info->txpower[i] = ath_get_rate_txpower(sc, bf, rix,
 								is_40, false);
@@ -2111,6 +2116,7 @@
 		fi->keyix = an->ps_key;
 	else
 		fi->keyix = ATH9K_TXKEYIX_INVALID;
+	fi->dyn_smps = sta && sta->smps_mode == IEEE80211_SMPS_DYNAMIC;
 	fi->keytype = keytype;
 	fi->framelen = framelen;
 	fi->tx_power = txpower;
@@ -2492,6 +2498,16 @@
 	spin_unlock_irqrestore(&sc->tx.txbuflock, flags);
 }
 
+static void ath_clear_tx_status(struct ieee80211_tx_info *tx_info)
+{
+	void *ptr = &tx_info->status;
+
+	memset(ptr + sizeof(tx_info->status.rates), 0,
+	       sizeof(tx_info->status) -
+	       sizeof(tx_info->status.rates) -
+	       sizeof(tx_info->status.status_driver_data));
+}
+
 static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
 			     struct ath_tx_status *ts, int nframes, int nbad,
 			     int txok)
@@ -2503,6 +2519,8 @@
 	struct ath_hw *ah = sc->sc_ah;
 	u8 i, tx_rateindex;
 
+	ath_clear_tx_status(tx_info);
+
 	if (txok)
 		tx_info->status.ack_signal = ts->ts_rssi;
 
@@ -2517,6 +2535,13 @@
 	tx_info->status.ampdu_len = nframes;
 	tx_info->status.ampdu_ack_len = nframes - nbad;
 
+	tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1;
+
+	for (i = tx_rateindex + 1; i < hw->max_rates; i++) {
+		tx_info->status.rates[i].count = 0;
+		tx_info->status.rates[i].idx = -1;
+	}
+
 	if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 &&
 	    (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) == 0) {
 		/*
@@ -2538,16 +2563,6 @@
 			tx_info->status.rates[tx_rateindex].count =
 				hw->max_rate_tries;
 	}
-
-	for (i = tx_rateindex + 1; i < hw->max_rates; i++) {
-		tx_info->status.rates[i].count = 0;
-		tx_info->status.rates[i].idx = -1;
-	}
-
-	tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1;
-
-	/* we report airtime in ath_tx_count_airtime(), don't report twice */
-	tx_info->status.tx_time = 0;
 }
 
 static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/carl9170/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/carl9170/Kconfig
@@ -16,13 +16,11 @@
 
 config CARL9170_LEDS
 	bool "SoftLED Support"
-	depends on CARL9170
-	select MAC80211_LEDS
-	select LEDS_CLASS
-	select NEW_LEDS
 	default y
+	depends on CARL9170
+	depends on MAC80211_LEDS
 	help
-	  This option is necessary, if you want your device' LEDs to blink
+	  This option is necessary, if you want your device's LEDs to blink.
 
 	  Say Y, unless you need the LEDs for firmware debugging.
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/carl9170/fw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/carl9170/fw.c
@@ -338,9 +338,7 @@
 		ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);
 
 		if (SUPP(CARL9170FW_WLANTX_CAB)) {
-			if_comb_types |=
-				BIT(NL80211_IFTYPE_AP) |
-				BIT(NL80211_IFTYPE_P2P_GO);
+			if_comb_types |= BIT(NL80211_IFTYPE_AP);
 
 #ifdef CONFIG_MAC80211_MESH
 			if_comb_types |=
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/carl9170/main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/carl9170/main.c
@@ -582,11 +582,10 @@
 	ar->disable_offload |= ((vif->type != NL80211_IFTYPE_STATION) &&
 	    (vif->type != NL80211_IFTYPE_AP));
 
-	/* While the driver supports HW offload in a single
-	 * P2P client configuration, it doesn't support HW
-	 * offload in the favourit, concurrent P2P GO+CLIENT
-	 * configuration. Hence, HW offload will always be
-	 * disabled for P2P.
+	/* The driver used to have P2P GO+CLIENT support,
+	 * but since this was dropped and we don't know if
+	 * there are any gremlins lurking in the shadows,
+	 * so best we keep HW offload disabled for P2P.
 	 */
 	ar->disable_offload |= vif->p2p;
 
@@ -639,18 +638,6 @@
 			if (vif->type == NL80211_IFTYPE_STATION)
 				break;
 
-			/* P2P GO [master] use-case
-			 * Because the P2P GO station is selected dynamically
-			 * by all participating peers of a WIFI Direct network,
-			 * the driver has be able to change the main interface
-			 * operating mode on the fly.
-			 */
-			if (main_vif->p2p && vif->p2p &&
-			    vif->type == NL80211_IFTYPE_AP) {
-				old_main = main_vif;
-				break;
-			}
-
 			err = -EBUSY;
 			rcu_read_unlock();
 
@@ -1449,8 +1436,7 @@
 		rcu_assign_pointer(sta_info->agg[tid], tid_info);
 		spin_unlock_bh(&ar->tx_ampdu_list_lock);
 
-		ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
-		break;
+		return IEEE80211_AMPDU_TX_START_IMMEDIATE;
 
 	case IEEE80211_AMPDU_TX_STOP_CONT:
 	case IEEE80211_AMPDU_TX_STOP_FLUSH:
@@ -1930,7 +1916,7 @@
 		WARN_ON(!(tx_streams >= 1 && tx_streams <=
 			IEEE80211_HT_MCS_TX_MAX_STREAMS));
 
-		tx_params = (tx_streams - 1) <<
+		tx_params |= (tx_streams - 1) <<
 			    IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
 
 		carl9170_band_2GHz.ht_cap.mcs.tx_params |= tx_params;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/carl9170/tx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/carl9170/tx.c
@@ -1557,6 +1557,9 @@
 					goto out;
 			}
 		} while (ar->beacon_enabled && i--);
+
+		/* no entry found in list */
+		return NULL;
 	}
 
 out:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/carl9170/usb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/carl9170/usb.c
@@ -1069,6 +1069,38 @@
 			ar->usb_ep_cmd_is_bulk = true;
 	}
 
+	/* Verify that all expected endpoints are present */
+	if (ar->usb_ep_cmd_is_bulk) {
+		u8 bulk_ep_addr[] = {
+			AR9170_USB_EP_RX | USB_DIR_IN,
+			AR9170_USB_EP_TX | USB_DIR_OUT,
+			AR9170_USB_EP_CMD | USB_DIR_OUT,
+			0};
+		u8 int_ep_addr[] = {
+			AR9170_USB_EP_IRQ | USB_DIR_IN,
+			0};
+		if (!usb_check_bulk_endpoints(intf, bulk_ep_addr) ||
+		    !usb_check_int_endpoints(intf, int_ep_addr))
+			err = -ENODEV;
+	} else {
+		u8 bulk_ep_addr[] = {
+			AR9170_USB_EP_RX | USB_DIR_IN,
+			AR9170_USB_EP_TX | USB_DIR_OUT,
+			0};
+		u8 int_ep_addr[] = {
+			AR9170_USB_EP_IRQ | USB_DIR_IN,
+			AR9170_USB_EP_CMD | USB_DIR_OUT,
+			0};
+		if (!usb_check_bulk_endpoints(intf, bulk_ep_addr) ||
+		    !usb_check_int_endpoints(intf, int_ep_addr))
+			err = -ENODEV;
+	}
+
+	if (err) {
+		carl9170_free(ar);
+		return err;
+	}
+
 	usb_set_intfdata(intf, ar);
 	SET_IEEE80211_DEV(ar->hw, &intf->dev);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/dfs_pattern_detector.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/dfs_pattern_detector.c
@@ -182,10 +182,12 @@
 	if (cd == NULL)
 		return;
 	list_del(&cd->head);
-	for (i = 0; i < dpd->num_radar_types; i++) {
-		struct pri_detector *de = cd->detectors[i];
-		if (de != NULL)
-			de->exit(de);
+	if (cd->detectors) {
+		for (i = 0; i < dpd->num_radar_types; i++) {
+			struct pri_detector *de = cd->detectors[i];
+			if (de != NULL)
+				de->exit(de);
+		}
 	}
 	kfree(cd->detectors);
 	kfree(cd);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/key.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/key.c
@@ -84,8 +84,7 @@
 }
 EXPORT_SYMBOL(ath_hw_keyreset);
 
-static bool ath_hw_keysetmac(struct ath_common *common,
-			     u16 entry, const u8 *mac)
+bool ath_hw_keysetmac(struct ath_common *common, u16 entry, const u8 *mac)
 {
 	u32 macHi, macLo;
 	u32 unicast_flag = AR_KEYTABLE_VALID;
@@ -125,6 +124,7 @@
 
 	return true;
 }
+EXPORT_SYMBOL(ath_hw_keysetmac);
 
 static bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry,
 				      const struct ath_keyval *k,
@@ -581,29 +581,38 @@
 /*
  * Delete Key.
  */
-void ath_key_delete(struct ath_common *common, struct ieee80211_key_conf *key)
+void ath_key_delete(struct ath_common *common, u8 hw_key_idx)
 {
-	ath_hw_keyreset(common, key->hw_key_idx);
-	if (key->hw_key_idx < IEEE80211_WEP_NKID)
+	/* Leave CCMP and TKIP (main key) configured to avoid disabling
+	 * encryption for potentially pending frames already in a TXQ with the
+	 * keyix pointing to this key entry. Instead, only clear the MAC address
+	 * to prevent RX processing from using this key cache entry.
+	 */
+	if (test_bit(hw_key_idx, common->ccmp_keymap) ||
+	    test_bit(hw_key_idx, common->tkip_keymap))
+		ath_hw_keysetmac(common, hw_key_idx, NULL);
+	else
+		ath_hw_keyreset(common, hw_key_idx);
+	if (hw_key_idx < IEEE80211_WEP_NKID)
 		return;
 
-	clear_bit(key->hw_key_idx, common->keymap);
-	clear_bit(key->hw_key_idx, common->ccmp_keymap);
-	if (key->cipher != WLAN_CIPHER_SUITE_TKIP)
+	clear_bit(hw_key_idx, common->keymap);
+	clear_bit(hw_key_idx, common->ccmp_keymap);
+	if (!test_bit(hw_key_idx, common->tkip_keymap))
 		return;
 
-	clear_bit(key->hw_key_idx + 64, common->keymap);
+	clear_bit(hw_key_idx + 64, common->keymap);
 
-	clear_bit(key->hw_key_idx, common->tkip_keymap);
-	clear_bit(key->hw_key_idx + 64, common->tkip_keymap);
+	clear_bit(hw_key_idx, common->tkip_keymap);
+	clear_bit(hw_key_idx + 64, common->tkip_keymap);
 
 	if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) {
-		ath_hw_keyreset(common, key->hw_key_idx + 32);
-		clear_bit(key->hw_key_idx + 32, common->keymap);
-		clear_bit(key->hw_key_idx + 64 + 32, common->keymap);
+		ath_hw_keyreset(common, hw_key_idx + 32);
+		clear_bit(hw_key_idx + 32, common->keymap);
+		clear_bit(hw_key_idx + 64 + 32, common->keymap);
 
-		clear_bit(key->hw_key_idx + 32, common->tkip_keymap);
-		clear_bit(key->hw_key_idx + 64 + 32, common->tkip_keymap);
+		clear_bit(hw_key_idx + 32, common->tkip_keymap);
+		clear_bit(hw_key_idx + 64 + 32, common->tkip_keymap);
 	}
 }
 EXPORT_SYMBOL(ath_key_delete);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/wcn36xx/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/wcn36xx/Kconfig
@@ -17,3 +17,12 @@
 	  Enabled debugfs support
 
 	  If unsure, say Y to make it easier to debug problems.
+
+config WCN36XX_SNAPDRAGON_HACKS
+	bool "Dragonboard 410c WCN36XX MAC address generation hacks"
+	default n
+	depends on WCN36XX
+	---help---
+	  Upon probe, WCN36XX will try to read its MAC address from
+	  a file located at /lib/firmware/wlan/macaddr0. If the file
+	  is not present, it will randomly generate a new MAC address.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/wcn36xx/dxe.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/wcn36xx/dxe.c
@@ -563,6 +563,10 @@
 	dxe = ctl->desc;
 
 	while (!(READ_ONCE(dxe->ctrl) & WCN36xx_DXE_CTRL_VLD)) {
+		/* do not read until we own DMA descriptor */
+		dma_rmb();
+
+		/* read/modify DMA descriptor */
 		skb = ctl->skb;
 		dma_addr = dxe->dst_addr_l;
 		ret = wcn36xx_dxe_fill_skb(wcn->dev, ctl, GFP_ATOMIC);
@@ -573,9 +577,15 @@
 			dma_unmap_single(wcn->dev, dma_addr, WCN36XX_PKT_SIZE,
 					DMA_FROM_DEVICE);
 			wcn36xx_rx_skb(wcn, skb);
-		} /* else keep old skb not submitted and use it for rx DMA */
+		}
+		/* else keep old skb not submitted and reuse it for rx DMA
+		 * (dropping the packet that it contained)
+		 */
 
+		/* flush descriptor changes before re-marking as valid */
+		dma_wmb();
 		dxe->ctrl = ctrl;
+
 		ctl = ctl->next;
 		dxe = ctl->desc;
 	}
@@ -942,4 +952,9 @@
 
 	wcn36xx_dxe_ch_free_skbs(wcn, &wcn->dxe_rx_l_ch);
 	wcn36xx_dxe_ch_free_skbs(wcn, &wcn->dxe_rx_h_ch);
+
+	wcn36xx_dxe_deinit_descs(wcn->dev, &wcn->dxe_tx_l_ch);
+	wcn36xx_dxe_deinit_descs(wcn->dev, &wcn->dxe_tx_h_ch);
+	wcn36xx_dxe_deinit_descs(wcn->dev, &wcn->dxe_rx_l_ch);
+	wcn36xx_dxe_deinit_descs(wcn->dev, &wcn->dxe_rx_h_ch);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/wcn36xx/main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/wcn36xx/main.c
@@ -134,7 +134,9 @@
 		.cap =	IEEE80211_HT_CAP_GRN_FLD |
 			IEEE80211_HT_CAP_SGI_20 |
 			IEEE80211_HT_CAP_DSSSCCK40 |
-			IEEE80211_HT_CAP_LSIG_TXOP_PROT,
+			IEEE80211_HT_CAP_LSIG_TXOP_PROT |
+			IEEE80211_HT_CAP_SGI_40 |
+			IEEE80211_HT_CAP_SUP_WIDTH_20_40,
 		.ht_supported = true,
 		.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
 		.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
@@ -163,7 +165,7 @@
 		.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
 		.mcs = {
 			.rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
-			.rx_highest = cpu_to_le16(72),
+			.rx_highest = cpu_to_le16(150),
 			.tx_params = IEEE80211_HT_MCS_TX_DEFINED,
 		}
 	}
@@ -293,23 +295,16 @@
 		goto out_free_dxe_pool;
 	}
 
-	wcn->hal_buf = kmalloc(WCN36XX_HAL_BUF_SIZE, GFP_KERNEL);
-	if (!wcn->hal_buf) {
-		wcn36xx_err("Failed to allocate smd buf\n");
-		ret = -ENOMEM;
-		goto out_free_dxe_ctl;
-	}
-
 	ret = wcn36xx_smd_load_nv(wcn);
 	if (ret) {
 		wcn36xx_err("Failed to push NV to chip\n");
-		goto out_free_smd_buf;
+		goto out_free_dxe_ctl;
 	}
 
 	ret = wcn36xx_smd_start(wcn);
 	if (ret) {
 		wcn36xx_err("Failed to start chip\n");
-		goto out_free_smd_buf;
+		goto out_free_dxe_ctl;
 	}
 
 	if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) {
@@ -336,8 +331,6 @@
 
 out_smd_stop:
 	wcn36xx_smd_stop(wcn);
-out_free_smd_buf:
-	kfree(wcn->hal_buf);
 out_free_dxe_ctl:
 	wcn36xx_dxe_free_ctl_blks(wcn);
 out_free_dxe_pool:
@@ -374,8 +367,6 @@
 
 	wcn36xx_dxe_free_mem_pools(wcn);
 	wcn36xx_dxe_free_ctl_blks(wcn);
-
-	kfree(wcn->hal_buf);
 }
 
 static int wcn36xx_config(struct ieee80211_hw *hw, u32 changed)
@@ -1084,6 +1075,7 @@
 	enum ieee80211_ampdu_mlme_action action = params->action;
 	u16 tid = params->tid;
 	u16 *ssn = &params->ssn;
+	int ret = 0;
 
 	wcn36xx_dbg(WCN36XX_DBG_MAC, "mac ampdu action action %d tid %d\n",
 		    action, tid);
@@ -1106,7 +1098,7 @@
 		sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_START;
 		spin_unlock_bh(&sta_priv->ampdu_lock);
 
-		ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+		ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
 		break;
 	case IEEE80211_AMPDU_TX_OPERATIONAL:
 		spin_lock_bh(&sta_priv->ampdu_lock);
@@ -1131,7 +1123,7 @@
 
 	mutex_unlock(&wcn->conf_mutex);
 
-	return 0;
+	return ret;
 }
 
 static const struct ieee80211_ops wcn36xx_ops = {
@@ -1302,6 +1294,14 @@
 	void *wcnss;
 	int ret;
 	const u8 *addr;
+#ifdef	CONFIG_WCN36XX_SNAPDRAGON_HACKS
+	int status;
+	const struct firmware *addr_file = NULL;
+	u8 tmp[18], _addr[ETH_ALEN];
+	static const u8 qcom_oui[3] = {0x00, 0x0A, 0xF5};
+	static const char *files = {"wlan/macaddr0"};
+#endif
+
 
 	wcn36xx_dbg(WCN36XX_DBG_MAC, "platform probe\n");
 
@@ -1322,6 +1322,12 @@
 	mutex_init(&wcn->hal_mutex);
 	mutex_init(&wcn->scan_lock);
 
+	wcn->hal_buf = devm_kmalloc(wcn->dev, WCN36XX_HAL_BUF_SIZE, GFP_KERNEL);
+	if (!wcn->hal_buf) {
+		ret = -ENOMEM;
+		goto out_wq;
+	}
+
 	ret = dma_set_mask_and_coherent(wcn->dev, DMA_BIT_MASK(32));
 	if (ret < 0) {
 		wcn36xx_err("failed to set DMA mask: %d\n", ret);
@@ -1341,15 +1347,43 @@
 	if (addr && ret != ETH_ALEN) {
 		wcn36xx_err("invalid local-mac-address\n");
 		ret = -EINVAL;
-		goto out_wq;
-	} else if (addr) {
+		goto out_destroy_ept;
+	}
+#ifdef	CONFIG_WCN36XX_SNAPDRAGON_HACKS
+	else if (addr == NULL) {
+		addr = _addr;
+		status = request_firmware(&addr_file, files, &pdev->dev);
+
+		if (status < 0) {
+			/* Assign a random mac with Qualcomm oui */
+			dev_err(&pdev->dev, "Failed (%d) to read macaddress"
+			"file %s, using a random address instead", status, files);
+			memcpy(addr, qcom_oui, 3);
+			get_random_bytes(addr + 3, 3);
+		} else {
+			memset(tmp, 0, sizeof(tmp));
+			memcpy(tmp, addr_file->data, sizeof(tmp) - 1);
+			sscanf(tmp, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
+			&addr[0],
+			&addr[1],
+			&addr[2],
+			&addr[3],
+			&addr[4],
+			&addr[5]);
+
+			release_firmware(addr_file);
+		}
+	}
+#endif
+
+	if (addr) {
 		wcn36xx_info("mac address: %pM\n", addr);
 		SET_IEEE80211_PERM_ADDR(wcn->hw, addr);
 	}
 
 	ret = wcn36xx_platform_get_resources(wcn, pdev);
 	if (ret)
-		goto out_wq;
+		goto out_destroy_ept;
 
 	wcn36xx_init_ieee80211(wcn);
 	ret = ieee80211_register_hw(wcn->hw);
@@ -1361,6 +1395,8 @@
 out_unmap:
 	iounmap(wcn->ccu_base);
 	iounmap(wcn->dxe_base);
+out_destroy_ept:
+	rpmsg_destroy_ept(wcn->smd_channel);
 out_wq:
 	ieee80211_free_hw(hw);
 out_err:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/wcn36xx/smd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -2311,7 +2311,7 @@
 			wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n",
 				    tmp->bss_index);
 			vif = wcn36xx_priv_to_vif(tmp);
-			ieee80211_connection_loss(vif);
+			ieee80211_beacon_loss(vif);
 		}
 		return 0;
 	}
@@ -2326,7 +2326,7 @@
 			wcn36xx_dbg(WCN36XX_DBG_HAL, "beacon missed bss_index %d\n",
 				    rsp->bss_index);
 			vif = wcn36xx_priv_to_vif(tmp);
-			ieee80211_connection_loss(vif);
+			ieee80211_beacon_loss(vif);
 			return 0;
 		}
 	}
@@ -2340,30 +2340,52 @@
 					      size_t len)
 {
 	struct wcn36xx_hal_delete_sta_context_ind_msg *rsp = buf;
-	struct wcn36xx_vif *tmp;
+	struct wcn36xx_vif *vif_priv;
+	struct ieee80211_vif *vif;
+	struct ieee80211_bss_conf *bss_conf;
 	struct ieee80211_sta *sta;
+	bool found = false;
 
 	if (len != sizeof(*rsp)) {
 		wcn36xx_warn("Corrupted delete sta indication\n");
 		return -EIO;
 	}
 
-	wcn36xx_dbg(WCN36XX_DBG_HAL, "delete station indication %pM index %d\n",
-		    rsp->addr2, rsp->sta_id);
+	wcn36xx_dbg(WCN36XX_DBG_HAL,
+		    "delete station indication %pM index %d reason %d\n",
+		    rsp->addr2, rsp->sta_id, rsp->reason_code);
 
-	list_for_each_entry(tmp, &wcn->vif_list, list) {
+	list_for_each_entry(vif_priv, &wcn->vif_list, list) {
 		rcu_read_lock();
-		sta = ieee80211_find_sta(wcn36xx_priv_to_vif(tmp), rsp->addr2);
-		if (sta)
-			ieee80211_report_low_ack(sta, 0);
+		vif = wcn36xx_priv_to_vif(vif_priv);
+
+		if (vif->type == NL80211_IFTYPE_STATION) {
+			/* We could call ieee80211_find_sta too, but checking
+			 * bss_conf is clearer.
+			 */
+			bss_conf = &vif->bss_conf;
+			if (vif_priv->sta_assoc &&
+			    !memcmp(bss_conf->bssid, rsp->addr2, ETH_ALEN)) {
+				found = true;
+				wcn36xx_dbg(WCN36XX_DBG_HAL,
+					    "connection loss bss_index %d\n",
+					    vif_priv->bss_index);
+				ieee80211_connection_loss(vif);
+			}
+		} else {
+			sta = ieee80211_find_sta(vif, rsp->addr2);
+			if (sta) {
+				found = true;
+				ieee80211_report_low_ack(sta, 0);
+			}
+		}
+
 		rcu_read_unlock();
-		if (sta)
+		if (found)
 			return 0;
 	}
 
-	wcn36xx_warn("STA with addr %pM and index %d not found\n",
-		     rsp->addr2,
-		     rsp->sta_id);
+	wcn36xx_warn("BSS or STA with addr %pM not found\n", rsp->addr2);
 	return -ENOENT;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/wil6210/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/wil6210/Kconfig
@@ -2,6 +2,7 @@
 config WIL6210
 	tristate "Wilocity 60g WiFi card wil6210 support"
 	select WANT_DEV_COREDUMP
+	select CRC32
 	depends on CFG80211
 	depends on PCI
 	default n
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/wil6210/debugfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -1021,20 +1021,14 @@
 	void *cmd;
 	int cmdlen = len - sizeof(struct wmi_cmd_hdr);
 	u16 cmdid;
-	int rc, rc1;
+	int rc1;
 
-	if (cmdlen < 0)
+	if (cmdlen < 0 || *ppos != 0)
 		return -EINVAL;
 
-	wmi = kmalloc(len, GFP_KERNEL);
-	if (!wmi)
-		return -ENOMEM;
-
-	rc = simple_write_to_buffer(wmi, len, ppos, buf, len);
-	if (rc < 0) {
-		kfree(wmi);
-		return rc;
-	}
+	wmi = memdup_user(buf, len);
+	if (IS_ERR(wmi))
+		return PTR_ERR(wmi);
 
 	cmd = (cmdlen > 0) ? &wmi[1] : NULL;
 	cmdid = le16_to_cpu(wmi->command_id);
@@ -1044,7 +1038,7 @@
 
 	wil_info(wil, "0x%04x[%d] -> %d\n", cmdid, cmdlen, rc1);
 
-	return rc;
+	return len;
 }
 
 static const struct file_operations fops_wmi = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/wil6210/txrx_edma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/wil6210/txrx_edma.c
@@ -880,6 +880,7 @@
 	u8 data_offset;
 	struct wil_rx_status_extended *s;
 	u16 sring_idx = sring - wil->srings;
+	int invalid_buff_id_retry;
 
 	BUILD_BUG_ON(sizeof(struct wil_rx_status_extended) > sizeof(skb->cb));
 
@@ -893,9 +894,9 @@
 	/* Extract the buffer ID from the status message */
 	buff_id = le16_to_cpu(wil_rx_status_get_buff_id(msg));
 
+	invalid_buff_id_retry = 0;
 	while (!buff_id) {
 		struct wil_rx_status_extended *s;
-		int invalid_buff_id_retry = 0;
 
 		wil_dbg_txrx(wil,
 			     "buff_id is not updated yet by HW, (swhead 0x%x)\n",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ath/wil6210/wmi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ath/wil6210/wmi.c
@@ -2505,7 +2505,8 @@
 	cmd->mgmt_frm_type = type;
 	/* BUG: FW API define ieLen as u8. Will fix FW */
 	cmd->ie_len = cpu_to_le16(ie_len);
-	memcpy(cmd->ie_info, ie, ie_len);
+	if (ie_len)
+		memcpy(cmd->ie_info, ie, ie_len);
 	rc = wmi_send(wil, WMI_SET_APPIE_CMDID, vif->mid, cmd, len);
 	kfree(cmd);
 out:
@@ -2541,7 +2542,8 @@
 	}
 
 	cmd->ie_len = cpu_to_le16(ie_len);
-	memcpy(cmd->ie_info, ie, ie_len);
+	if (ie_len)
+		memcpy(cmd->ie_info, ie, ie_len);
 	rc = wmi_send(wil, WMI_UPDATE_FT_IES_CMDID, vif->mid, cmd, len);
 	kfree(cmd);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/atmel/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/atmel/Kconfig
@@ -13,29 +13,29 @@
 if WLAN_VENDOR_ATMEL
 
 config ATMEL
-      tristate "Atmel at76c50x chipset  802.11b support"
-      depends on CFG80211 && (PCI || PCMCIA)
-      select WIRELESS_EXT
-      select WEXT_PRIV
-      select FW_LOADER
-      select CRC32
-       ---help---
-	A driver 802.11b wireless cards based on the Atmel fast-vnet
-	chips. This driver supports standard Linux wireless extensions.
+	tristate "Atmel at76c50x chipset  802.11b support"
+	depends on CFG80211 && (PCI || PCMCIA)
+	select WIRELESS_EXT
+	select WEXT_PRIV
+	select FW_LOADER
+	select CRC32
+	---help---
+	  A driver 802.11b wireless cards based on the Atmel fast-vnet
+	  chips. This driver supports standard Linux wireless extensions.
 
-	Many  cards based on this chipset do not have flash memory
-	and need their firmware loaded at start-up. If yours is
-	one of these, you will need to provide a firmware image
-	to be loaded into the card by the driver. The Atmel
-	firmware package can be downloaded from
-	<http://www.thekelleys.org.uk/atmel>
+	  Many  cards based on this chipset do not have flash memory
+	  and need their firmware loaded at start-up. If yours is
+	  one of these, you will need to provide a firmware image
+	  to be loaded into the card by the driver. The Atmel
+	  firmware package can be downloaded from
+	  <http://www.thekelleys.org.uk/atmel>
 
 config PCI_ATMEL
-      tristate "Atmel at76c506 PCI cards"
-      depends on ATMEL && PCI
-       ---help---
-	Enable support for PCI and mini-PCI cards containing the
-	Atmel at76c506 chip.
+	tristate "Atmel at76c506 PCI cards"
+	depends on ATMEL && PCI
+	---help---
+	  Enable support for PCI and mini-PCI cards containing the
+	  Atmel at76c506 chip.
 
 config PCMCIA_ATMEL
 	tristate "Atmel at76c502/at76c504 PCMCIA cards"
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/atmel/atmel_cs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/atmel/atmel_cs.c
@@ -73,6 +73,7 @@
 static int atmel_probe(struct pcmcia_device *p_dev)
 {
 	struct local_info *local;
+	int ret;
 
 	dev_dbg(&p_dev->dev, "atmel_attach()\n");
 
@@ -83,8 +84,16 @@
 
 	p_dev->priv = local;
 
-	return atmel_config(p_dev);
-} /* atmel_attach */
+	ret = atmel_config(p_dev);
+	if (ret)
+		goto err_free_priv;
+
+	return 0;
+
+err_free_priv:
+	kfree(p_dev->priv);
+	return ret;
+}
 
 static void atmel_detach(struct pcmcia_device *link)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/b43/b43.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/b43/b43.h
@@ -651,7 +651,7 @@
 	union {
 		__be16 d16;
 		__be32 d32;
-	} data __packed;
+	} __packed data;
 } __packed;
 
 
@@ -1082,6 +1082,22 @@
 	return dev->__using_pio_transfers;
 }
 
+static inline void b43_wake_queue(struct b43_wldev *dev, int queue_prio)
+{
+	if (dev->qos_enabled)
+		ieee80211_wake_queue(dev->wl->hw, queue_prio);
+	else
+		ieee80211_wake_queue(dev->wl->hw, 0);
+}
+
+static inline void b43_stop_queue(struct b43_wldev *dev, int queue_prio)
+{
+	if (dev->qos_enabled)
+		ieee80211_stop_queue(dev->wl->hw, queue_prio);
+	else
+		ieee80211_stop_queue(dev->wl->hw, 0);
+}
+
 /* Message printing */
 __printf(2, 3) void b43info(struct b43_wl *wl, const char *fmt, ...);
 __printf(2, 3) void b43err(struct b43_wl *wl, const char *fmt, ...);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/b43/debugfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/b43/debugfs.c
@@ -493,7 +493,7 @@
 	struct b43_wldev *dev;
 	struct b43_debugfs_fops *dfops;
 	struct b43_dfs_file *dfile;
-	ssize_t uninitialized_var(ret);
+	ssize_t ret;
 	char *buf;
 	const size_t bufsize = 1024 * 16; /* 16 kiB buffer */
 	const size_t buforder = get_order(bufsize);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/b43/dma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/b43/dma.c
@@ -37,7 +37,7 @@
 static u32 b43_dma_address(struct b43_dma *dma, dma_addr_t dmaaddr,
 			   enum b43_addrtype addrtype)
 {
-	u32 uninitialized_var(addr);
+	u32 addr;
 
 	switch (addrtype) {
 	case B43_DMA_ADDR_LOW:
@@ -1399,8 +1399,8 @@
 	    should_inject_overflow(ring)) {
 		/* This TX ring is full. */
 		unsigned int skb_mapping = skb_get_queue_mapping(skb);
-		ieee80211_stop_queue(dev->wl->hw, skb_mapping);
-		dev->wl->tx_queue_stopped[skb_mapping] = 1;
+		b43_stop_queue(dev, skb_mapping);
+		dev->wl->tx_queue_stopped[skb_mapping] = true;
 		ring->stopped = true;
 		if (b43_debug(dev, B43_DBG_DMAVERBOSE)) {
 			b43dbg(dev->wl, "Stopped TX ring %d\n", ring->index);
@@ -1566,11 +1566,11 @@
 	}
 
 	if (dev->wl->tx_queue_stopped[ring->queue_prio]) {
-		dev->wl->tx_queue_stopped[ring->queue_prio] = 0;
+		dev->wl->tx_queue_stopped[ring->queue_prio] = false;
 	} else {
 		/* If the driver queue is running wake the corresponding
 		 * mac80211 queue. */
-		ieee80211_wake_queue(dev->wl->hw, ring->queue_prio);
+		b43_wake_queue(dev, ring->queue_prio);
 		if (b43_debug(dev, B43_DBG_DMAVERBOSE)) {
 			b43dbg(dev->wl, "Woke up TX ring %d\n", ring->index);
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/b43/lo.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/b43/lo.c
@@ -729,7 +729,7 @@
 	};
 	int max_rx_gain;
 	struct b43_lo_calib *cal;
-	struct lo_g_saved_values uninitialized_var(saved_regs);
+	struct lo_g_saved_values saved_regs;
 	/* Values from the "TXCTL Register and Value Table" */
 	u16 txctl_reg;
 	u16 txctl_value;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/b43/main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/b43/main.c
@@ -2585,7 +2585,8 @@
 
 start_ieee80211:
 	wl->hw->queues = B43_QOS_QUEUE_NUM;
-	if (!modparam_qos || dev->fw.opensource)
+	if (!modparam_qos || dev->fw.opensource ||
+	    dev->dev->chip_id == BCMA_CHIP_ID_BCM4331)
 		wl->hw->queues = 1;
 
 	err = ieee80211_register_hw(wl->hw);
@@ -3600,8 +3601,8 @@
 			else
 				err = b43_dma_tx(dev, skb);
 			if (err == -ENOSPC) {
-				wl->tx_queue_stopped[queue_num] = 1;
-				ieee80211_stop_queue(wl->hw, queue_num);
+				wl->tx_queue_stopped[queue_num] = true;
+				b43_stop_queue(dev, queue_num);
 				skb_queue_head(&wl->tx_queue[queue_num], skb);
 				break;
 			}
@@ -3611,7 +3612,7 @@
 		}
 
 		if (!err)
-			wl->tx_queue_stopped[queue_num] = 0;
+			wl->tx_queue_stopped[queue_num] = false;
 	}
 
 #if B43_DEBUG
@@ -3625,6 +3626,7 @@
 		      struct sk_buff *skb)
 {
 	struct b43_wl *wl = hw_to_b43_wl(hw);
+	u16 skb_queue_mapping;
 
 	if (unlikely(skb->len < 2 + 2 + 6)) {
 		/* Too short, this can't be a valid frame. */
@@ -3633,12 +3635,12 @@
 	}
 	B43_WARN_ON(skb_shinfo(skb)->nr_frags);
 
-	skb_queue_tail(&wl->tx_queue[skb->queue_mapping], skb);
-	if (!wl->tx_queue_stopped[skb->queue_mapping]) {
+	skb_queue_mapping = skb_get_queue_mapping(skb);
+	skb_queue_tail(&wl->tx_queue[skb_queue_mapping], skb);
+	if (!wl->tx_queue_stopped[skb_queue_mapping])
 		ieee80211_queue_work(wl->hw, &wl->tx_work);
-	} else {
-		ieee80211_stop_queue(wl->hw, skb->queue_mapping);
-	}
+	else
+		b43_stop_queue(wl->current_dev, skb_queue_mapping);
 }
 
 static void b43_qos_params_upload(struct b43_wldev *dev,
@@ -5569,7 +5571,7 @@
 	/* fill hw info */
 	ieee80211_hw_set(hw, RX_INCLUDES_FCS);
 	ieee80211_hw_set(hw, SIGNAL_DBM);
-
+	ieee80211_hw_set(hw, MFP_CAPABLE);
 	hw->wiphy->interface_modes =
 		BIT(NL80211_IFTYPE_AP) |
 		BIT(NL80211_IFTYPE_MESH_POINT) |
@@ -5603,7 +5605,7 @@
 	/* Initialize queues and flags. */
 	for (queue_num = 0; queue_num < B43_QOS_QUEUE_NUM; queue_num++) {
 		skb_queue_head_init(&wl->tx_queue[queue_num]);
-		wl->tx_queue_stopped[queue_num] = 0;
+		wl->tx_queue_stopped[queue_num] = false;
 	}
 
 	snprintf(chip_name, ARRAY_SIZE(chip_name),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/b43/phy_g.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/b43/phy_g.c
@@ -2297,7 +2297,7 @@
 	b43_phy_mask(dev, B43_PHY_G_CRS, 0x7FFF);
 	b43_set_all_gains(dev, 3, 8, 1);
 
-	start = (channel - 5 > 0) ? channel - 5 : 1;
+	start = (channel > 5) ? channel - 5 : 1;
 	end = (channel + 5 < 14) ? channel + 5 : 13;
 
 	for (i = start; i <= end; i++) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/b43/phy_n.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/b43/phy_n.c
@@ -582,7 +582,7 @@
 	u16 data[4];
 	s16 gain[2];
 	u16 minmax[2];
-	static const u16 lna_gain[4] = { -2, 10, 19, 25 };
+	static const s16 lna_gain[4] = { -2, 10, 19, 25 };
 
 	if (nphy->hang_avoid)
 		b43_nphy_stay_in_carrier_search(dev, 1);
@@ -5308,7 +5308,7 @@
 
 	for (i = 0; i < 4; i++) {
 		if (dev->phy.rev >= 3)
-			table[i] = coef[i];
+			coef[i] = table[i];
 		else
 			coef[i] = 0;
 	}
@@ -5643,7 +5643,7 @@
 	u8 rfctl[2];
 	u8 afectl_core;
 	u16 tmp[6];
-	u16 uninitialized_var(cur_hpf1), uninitialized_var(cur_hpf2), cur_lna;
+	u16 cur_hpf1, cur_hpf2, cur_lna;
 	u32 real, imag;
 	enum nl80211_band band;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/b43/pio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/b43/pio.c
@@ -525,7 +525,7 @@
 	if (total_len > (q->buffer_size - q->buffer_used)) {
 		/* Not enough memory on the queue. */
 		err = -EBUSY;
-		ieee80211_stop_queue(dev->wl->hw, skb_get_queue_mapping(skb));
+		b43_stop_queue(dev, skb_get_queue_mapping(skb));
 		q->stopped = true;
 		goto out;
 	}
@@ -552,7 +552,7 @@
 	if (((q->buffer_size - q->buffer_used) < roundup(2 + 2 + 6, 4)) ||
 	    (q->free_packet_slots == 0)) {
 		/* The queue is full. */
-		ieee80211_stop_queue(dev->wl->hw, skb_get_queue_mapping(skb));
+		b43_stop_queue(dev, skb_get_queue_mapping(skb));
 		q->stopped = true;
 	}
 
@@ -587,7 +587,7 @@
 	list_add(&pack->list, &q->packets_list);
 
 	if (q->stopped) {
-		ieee80211_wake_queue(dev->wl->hw, q->queue_prio);
+		b43_wake_queue(dev, q->queue_prio);
 		q->stopped = false;
 	}
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/b43/xmit.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/b43/xmit.c
@@ -422,10 +422,10 @@
 	if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
 	    (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) {
 		unsigned int len;
-		struct ieee80211_hdr *uninitialized_var(hdr);
+		struct ieee80211_hdr *hdr;
 		int rts_rate, rts_rate_fb;
 		int rts_rate_ofdm, rts_rate_fb_ofdm;
-		struct b43_plcp_hdr6 *uninitialized_var(plcp);
+		struct b43_plcp_hdr6 *plcp;
 		struct ieee80211_rate *rts_cts_rate;
 
 		rts_cts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, info);
@@ -436,7 +436,7 @@
 		rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb);
 
 		if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
-			struct ieee80211_cts *uninitialized_var(cts);
+			struct ieee80211_cts *cts;
 
 			switch (dev->fw.hdr_format) {
 			case B43_FW_HDR_598:
@@ -458,7 +458,7 @@
 			mac_ctl |= B43_TXH_MAC_SENDCTS;
 			len = sizeof(struct ieee80211_cts);
 		} else {
-			struct ieee80211_rts *uninitialized_var(rts);
+			struct ieee80211_rts *rts;
 
 			switch (dev->fw.hdr_format) {
 			case B43_FW_HDR_598:
@@ -650,8 +650,8 @@
 	const struct b43_rxhdr_fw4 *rxhdr = _rxhdr;
 	__le16 fctl;
 	u16 phystat0, phystat3;
-	u16 uninitialized_var(chanstat), uninitialized_var(mactime);
-	u32 uninitialized_var(macstat);
+	u16 chanstat, mactime;
+	u32 macstat;
 	u16 chanid;
 	int padding, rate_idx;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/b43legacy/b43legacy.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/b43legacy/b43legacy.h
@@ -379,7 +379,7 @@
 	union {
 		__be16 d16;
 		__be32 d32;
-	} data __packed;
+	} __packed data;
 } __packed;
 
 #define B43legacy_PHYMODE(phytype)	(1 << (phytype))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/b43legacy/debugfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/b43legacy/debugfs.c
@@ -190,7 +190,7 @@
 	struct b43legacy_wldev *dev;
 	struct b43legacy_debugfs_fops *dfops;
 	struct b43legacy_dfs_file *dfile;
-	ssize_t uninitialized_var(ret);
+	ssize_t ret;
 	char *buf;
 	const size_t bufsize = 1024 * 16; /* 16 KiB buffer */
 	const size_t buforder = get_order(bufsize);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/b43legacy/main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/b43legacy/main.c
@@ -1275,8 +1275,9 @@
 }
 
 /* Interrupt handler bottom-half */
-static void b43legacy_interrupt_tasklet(struct b43legacy_wldev *dev)
+static void b43legacy_interrupt_tasklet(unsigned long data)
 {
+	struct b43legacy_wldev *dev = (struct b43legacy_wldev *)data;
 	u32 reason;
 	u32 dma_reason[ARRAY_SIZE(dev->dma_reason)];
 	u32 merged_dma_reason = 0;
@@ -2579,7 +2580,7 @@
 static int b43legacy_switch_phymode(struct b43legacy_wl *wl,
 				      unsigned int new_mode)
 {
-	struct b43legacy_wldev *uninitialized_var(up_dev);
+	struct b43legacy_wldev *up_dev;
 	struct b43legacy_wldev *down_dev;
 	int err;
 	bool gmode = false;
@@ -3741,7 +3742,7 @@
 	b43legacy_set_status(wldev, B43legacy_STAT_UNINIT);
 	wldev->bad_frames_preempt = modparam_bad_frames_preempt;
 	tasklet_init(&wldev->isr_tasklet,
-		     (void (*)(unsigned long))b43legacy_interrupt_tasklet,
+		     b43legacy_interrupt_tasklet,
 		     (unsigned long)wldev);
 	if (modparam_pio)
 		wldev->__using_pio = true;
@@ -3800,6 +3801,7 @@
 	/* fill hw info */
 	ieee80211_hw_set(hw, RX_INCLUDES_FCS);
 	ieee80211_hw_set(hw, SIGNAL_DBM);
+	ieee80211_hw_set(hw, MFP_CAPABLE); /* Allow WPA3 in software */
 
 	hw->wiphy->interface_modes =
 		BIT(NL80211_IFTYPE_AP) |
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/b43legacy/phy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/b43legacy/phy.c
@@ -1123,7 +1123,7 @@
 	struct b43legacy_phy *phy = &dev->phy;
 	u16 regstack[12] = { 0 };
 	u16 mls;
-	u16 fval;
+	s16 fval;
 	int i;
 	int j;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/b43legacy/radio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/b43legacy/radio.c
@@ -283,7 +283,7 @@
 			    & 0x7FFF);
 	b43legacy_set_all_gains(dev, 3, 8, 1);
 
-	start = (channel - 5 > 0) ? channel - 5 : 1;
+	start = (channel > 5) ? channel - 5 : 1;
 	end = (channel + 5 < 14) ? channel + 5 : 13;
 
 	for (i = start; i <= end; i++) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/b43legacy/xmit.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/b43legacy/xmit.c
@@ -558,6 +558,7 @@
 	default:
 		b43legacywarn(dev->wl, "Unexpected value for chanstat (0x%X)\n",
 		       chanstat);
+		goto drop;
 	}
 
 	memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -770,7 +770,7 @@
 
 	nents = max_t(uint, BRCMF_DEFAULT_RXGLOM_SIZE,
 		      sdiodev->settings->bus.sdio.txglomsz);
-	nents += (nents >> 4) + 1;
+	nents *= 2;
 
 	WARN_ON(nents > sdiodev->max_segment_count);
 
@@ -1168,13 +1168,9 @@
 	},
 };
 
-void brcmf_sdio_register(void)
+int brcmf_sdio_register(void)
 {
-	int ret;
-
-	ret = sdio_register_driver(&brcmf_sdmmc_driver);
-	if (ret)
-		brcmf_err("sdio_register_driver failed: %d\n", ret);
+	return sdio_register_driver(&brcmf_sdmmc_driver);
 }
 
 void brcmf_sdio_exit(void)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
@@ -274,11 +274,26 @@
 
 #ifdef CONFIG_BRCMFMAC_SDIO
 void brcmf_sdio_exit(void);
-void brcmf_sdio_register(void);
+int brcmf_sdio_register(void);
+#else
+static inline void brcmf_sdio_exit(void) { }
+static inline int brcmf_sdio_register(void) { return 0; }
 #endif
+
 #ifdef CONFIG_BRCMFMAC_USB
 void brcmf_usb_exit(void);
-void brcmf_usb_register(void);
+int brcmf_usb_register(void);
+#else
+static inline void brcmf_usb_exit(void) { }
+static inline int brcmf_usb_register(void) { return 0; }
+#endif
+
+#ifdef CONFIG_BRCMFMAC_PCIE
+void brcmf_pcie_exit(void);
+int brcmf_pcie_register(void);
+#else
+static inline void brcmf_pcie_exit(void) { }
+static inline int brcmf_pcie_register(void) { return 0; }
 #endif
 
 #endif /* BRCMFMAC_BUS_H */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -82,9 +82,14 @@
 
 #define BRCMF_ND_INFO_TIMEOUT		msecs_to_jiffies(2000)
 
+#define BRCMF_PS_MAX_TIMEOUT_MS		2000
+
 #define BRCMF_ASSOC_PARAMS_FIXED_SIZE \
 	(sizeof(struct brcmf_assoc_params_le) - sizeof(u16))
 
+#define BRCMF_MAX_CHANSPEC_LIST \
+	(BRCMF_DCMD_MEDLEN / sizeof(__le32) - 1)
+
 static bool check_vif_up(struct brcmf_cfg80211_vif *vif)
 {
 	if (!test_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state)) {
@@ -705,8 +710,7 @@
 	scan_request = cfg->scan_request;
 	cfg->scan_request = NULL;
 
-	if (timer_pending(&cfg->escan_timeout))
-		del_timer_sync(&cfg->escan_timeout);
+	del_timer_sync(&cfg->escan_timeout);
 
 	if (fw_abort) {
 		/* Do a scan abort to stop the driver's scan engine */
@@ -1264,13 +1268,14 @@
 {
 	struct brcmf_pub *drvr = ifp->drvr;
 	struct brcmf_wsec_pmk_le pmk;
-	int i, err;
+	int err;
+
+	memset(&pmk, 0, sizeof(pmk));
 
-	/* convert to firmware key format */
-	pmk.key_len = cpu_to_le16(pmk_len << 1);
-	pmk.flags = cpu_to_le16(BRCMF_WSEC_PASSPHRASE);
-	for (i = 0; i < pmk_len; i++)
-		snprintf(&pmk.key[2 * i], 3, "%02x", pmk_data[i]);
+	/* pass pmk directly */
+	pmk.key_len = cpu_to_le16(pmk_len);
+	pmk.flags = cpu_to_le16(0);
+	memcpy(pmk.key, pmk_data, pmk_len);
 
 	/* store psk in firmware */
 	err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_WSEC_PMK,
@@ -2610,8 +2615,9 @@
 	struct brcmf_sta_info_le sta_info_le;
 	u32 sta_flags;
 	u32 is_tdls_peer;
-	s32 total_rssi;
-	s32 count_rssi;
+	s32 total_rssi_avg = 0;
+	s32 total_rssi = 0;
+	s32 count_rssi = 0;
 	int rssi;
 	u32 i;
 
@@ -2677,25 +2683,27 @@
 			sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES);
 			sinfo->rx_bytes = le64_to_cpu(sta_info_le.rx_tot_bytes);
 		}
-		total_rssi = 0;
-		count_rssi = 0;
 		for (i = 0; i < BRCMF_ANT_MAX; i++) {
-			if (sta_info_le.rssi[i]) {
-				sinfo->chain_signal_avg[count_rssi] =
-					sta_info_le.rssi[i];
-				sinfo->chain_signal[count_rssi] =
-					sta_info_le.rssi[i];
-				total_rssi += sta_info_le.rssi[i];
-				count_rssi++;
-			}
+			if (sta_info_le.rssi[i] == 0 ||
+			    sta_info_le.rx_lastpkt_rssi[i] == 0)
+				continue;
+			sinfo->chains |= BIT(count_rssi);
+			sinfo->chain_signal[count_rssi] =
+				sta_info_le.rx_lastpkt_rssi[i];
+			sinfo->chain_signal_avg[count_rssi] =
+				sta_info_le.rssi[i];
+			total_rssi += sta_info_le.rx_lastpkt_rssi[i];
+			total_rssi_avg += sta_info_le.rssi[i];
+			count_rssi++;
 		}
 		if (count_rssi) {
-			sinfo->filled |= BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL);
-			sinfo->chains = count_rssi;
-
 			sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);
-			total_rssi /= count_rssi;
-			sinfo->signal = total_rssi;
+			sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG);
+			sinfo->filled |= BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL);
+			sinfo->filled |=
+				BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL_AVG);
+			sinfo->signal = total_rssi / count_rssi;
+			sinfo->signal_avg = total_rssi_avg / count_rssi;
 		} else if (test_bit(BRCMF_VIF_STATUS_CONNECTED,
 			&ifp->vif->sme_state)) {
 			memset(&scb_val, 0, sizeof(scb_val));
@@ -2789,6 +2797,12 @@
 		else
 			bphy_err(drvr, "error (%d)\n", err);
 	}
+
+	err = brcmf_fil_iovar_int_set(ifp, "pm2_sleep_ret",
+				min_t(u32, timeout, BRCMF_PS_MAX_TIMEOUT_MS));
+	if (err)
+		bphy_err(drvr, "Unable to set pm timeout, (%d)\n", err);
+
 done:
 	brcmf_dbg(TRACE, "Exit\n");
 	return err;
@@ -5374,7 +5388,8 @@
 	return false;
 }
 
-static bool brcmf_is_linkdown(const struct brcmf_event_msg *e)
+static bool brcmf_is_linkdown(struct brcmf_cfg80211_vif *vif,
+			    const struct brcmf_event_msg *e)
 {
 	u32 event = e->event_code;
 	u16 flags = e->flags;
@@ -5383,6 +5398,8 @@
 	    (event == BRCMF_E_DISASSOC_IND) ||
 	    ((event == BRCMF_E_LINK) && (!(flags & BRCMF_EVENT_MSG_LINK)))) {
 		brcmf_dbg(CONN, "Processing link down\n");
+		clear_bit(BRCMF_VIF_STATUS_EAP_SUCCESS, &vif->sme_state);
+		clear_bit(BRCMF_VIF_STATUS_ASSOC_SUCCESS, &vif->sme_state);
 		return true;
 	}
 	return false;
@@ -5449,6 +5466,11 @@
 		(struct brcmf_cfg80211_assoc_ielen_le *)cfg->extra_buf;
 	req_len = le32_to_cpu(assoc_info->req_len);
 	resp_len = le32_to_cpu(assoc_info->resp_len);
+	if (req_len > WL_EXTRA_BUF_MAX || resp_len > WL_EXTRA_BUF_MAX) {
+		bphy_err(drvr, "invalid lengths in assoc info: req %u resp %u\n",
+			 req_len, resp_len);
+		return -EINVAL;
+	}
 	if (req_len) {
 		err = brcmf_fil_iovar_data_get(ifp, "assoc_req_ies",
 					       cfg->extra_buf,
@@ -5675,7 +5697,7 @@
 		} else
 			brcmf_bss_connect_done(cfg, ndev, e, true);
 		brcmf_net_setcarrier(ifp, true);
-	} else if (brcmf_is_linkdown(e)) {
+	} else if (brcmf_is_linkdown(ifp->vif, e)) {
 		brcmf_dbg(CONN, "Linkdown\n");
 		if (!brcmf_is_ibssmode(ifp->vif)) {
 			brcmf_bss_connect_done(cfg, ndev, e, false);
@@ -6053,6 +6075,13 @@
 			band->channels[i].flags = IEEE80211_CHAN_DISABLED;
 
 	total = le32_to_cpu(list->count);
+	if (total > BRCMF_MAX_CHANSPEC_LIST) {
+		bphy_err(drvr, "Invalid count of channel Spec. (%u)\n",
+			 total);
+		err = -EINVAL;
+		goto fail_pbuf;
+	}
+
 	for (i = 0; i < total; i++) {
 		ch.chspec = (u16)le32_to_cpu(list->element[i]);
 		cfg->d11inf.decchspec(&ch);
@@ -6198,6 +6227,13 @@
 		band = cfg_to_wiphy(cfg)->bands[NL80211_BAND_2GHZ];
 		list = (struct brcmf_chanspec_list *)pbuf;
 		num_chan = le32_to_cpu(list->count);
+		if (num_chan > BRCMF_MAX_CHANSPEC_LIST) {
+			bphy_err(drvr, "Invalid count of channel Spec. (%u)\n",
+				 num_chan);
+			kfree(pbuf);
+			return -EINVAL;
+		}
+
 		for (i = 0; i < num_chan; i++) {
 			ch.chspec = (u16)le32_to_cpu(list->element[i]);
 			cfg->d11inf.decchspec(&ch);
@@ -7203,6 +7239,7 @@
 	brcmf_btcoex_detach(cfg);
 	wiphy_unregister(cfg->wiphy);
 	wl_deinit_priv(cfg);
+	cancel_work_sync(&cfg->escan_timeout_work);
 	brcmf_free_wiphy(cfg->wiphy);
 	kfree(cfg);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
@@ -264,6 +264,7 @@
 			 err);
 		goto done;
 	}
+	buf[sizeof(buf) - 1] = '\0';
 	ptr = (char *)buf;
 	strsep(&ptr, "\n");
 
@@ -280,15 +281,17 @@
 	if (err) {
 		brcmf_dbg(TRACE, "retrieving clmver failed, %d\n", err);
 	} else {
+		buf[sizeof(buf) - 1] = '\0';
 		clmver = (char *)buf;
-		/* store CLM version for adding it to revinfo debugfs file */
-		memcpy(ifp->drvr->clmver, clmver, sizeof(ifp->drvr->clmver));
 
 		/* Replace all newline/linefeed characters with space
 		 * character
 		 */
 		strreplace(clmver, '\n', ' ');
 
+		/* store CLM version for adding it to revinfo debugfs file */
+		memcpy(ifp->drvr->clmver, clmver, sizeof(ifp->drvr->clmver));
+
 		brcmf_dbg(INFO, "CLM version = %s\n", clmver);
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -290,6 +290,7 @@
 	struct brcmf_pub *drvr = ifp->drvr;
 	struct ethhdr *eh;
 	int head_delta;
+	unsigned int tx_bytes = skb->len;
 
 	brcmf_dbg(DATA, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx);
 
@@ -332,6 +333,7 @@
 			bphy_err(drvr, "%s: failed to expand headroom\n",
 				 brcmf_ifname(ifp));
 			atomic_inc(&drvr->bus_if->stats.pktcow_failed);
+			dev_kfree_skb(skb);
 			goto done;
 		}
 	}
@@ -361,7 +363,7 @@
 		ndev->stats.tx_dropped++;
 	} else {
 		ndev->stats.tx_packets++;
-		ndev->stats.tx_bytes += skb->len;
+		ndev->stats.tx_bytes += tx_bytes;
 	}
 
 	/* Return ok: we always eat the packet */
@@ -483,7 +485,7 @@
 	ret = brcmf_proto_hdrpull(drvr, true, skb, ifp);
 
 	if (ret || !(*ifp) || !(*ifp)->ndev) {
-		if (ret != -ENODATA && *ifp)
+		if (ret != -ENODATA && *ifp && (*ifp)->ndev)
 			(*ifp)->ndev->stats.rx_errors++;
 		brcmu_pkt_buf_free_skb(skb);
 		return -ENODATA;
@@ -536,6 +538,11 @@
 	struct ethhdr *eh;
 	u16 type;
 
+	if (!ifp) {
+		brcmu_pkt_buf_free_skb(txp);
+		return;
+	}
+
 	eh = (struct ethhdr *)(txp->data);
 	type = ntohs(eh->h_proto);
 
@@ -1350,6 +1357,11 @@
 	brcmf_fweh_detach(drvr);
 	brcmf_proto_detach(drvr);
 
+	if (drvr->mon_if) {
+		brcmf_net_detach(drvr->mon_if->ndev, false);
+		drvr->mon_if = NULL;
+	}
+
 	/* make sure primary interface removed last */
 	for (i = BRCMF_MAX_IFS - 1; i > -1; i--) {
 		if (drvr->iflist[i])
@@ -1433,40 +1445,34 @@
 	}
 }
 
-static void brcmf_driver_register(struct work_struct *work)
-{
-#ifdef CONFIG_BRCMFMAC_SDIO
-	brcmf_sdio_register();
-#endif
-#ifdef CONFIG_BRCMFMAC_USB
-	brcmf_usb_register();
-#endif
-#ifdef CONFIG_BRCMFMAC_PCIE
-	brcmf_pcie_register();
-#endif
-}
-static DECLARE_WORK(brcmf_driver_work, brcmf_driver_register);
-
 int __init brcmf_core_init(void)
 {
-	if (!schedule_work(&brcmf_driver_work))
-		return -EBUSY;
+	int err;
 
+	err = brcmf_sdio_register();
+	if (err)
+		return err;
+
+	err = brcmf_usb_register();
+	if (err)
+		goto error_usb_register;
+
+	err = brcmf_pcie_register();
+	if (err)
+		goto error_pcie_register;
 	return 0;
+
+error_pcie_register:
+	brcmf_usb_exit();
+error_usb_register:
+	brcmf_sdio_exit();
+	return err;
 }
 
 void __exit brcmf_core_exit(void)
 {
-	cancel_work_sync(&brcmf_driver_work);
-
-#ifdef CONFIG_BRCMFMAC_SDIO
 	brcmf_sdio_exit();
-#endif
-#ifdef CONFIG_BRCMFMAC_USB
 	brcmf_usb_exit();
-#endif
-#ifdef CONFIG_BRCMFMAC_PCIE
 	brcmf_pcie_exit();
-#endif
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c
@@ -40,6 +40,18 @@
 	BRCM_CC_43340_CHIP_ID, 2, "pov-tab-p1006w-data"
 };
 
+static const struct brcmf_dmi_data predia_basic_data = {
+	BRCM_CC_43341_CHIP_ID, 2, "predia-basic"
+};
+
+/* Note the Voyo winpad A15 tablet uses the same Ampak AP6330 module, with the
+ * exact same nvram file as the Prowise-PT301 tablet. Since the nvram for the
+ * Prowise-PT301 is already in linux-firmware we just point to that here.
+ */
+static const struct brcmf_dmi_data voyo_winpad_a15_data = {
+	BRCM_CC_4330_CHIP_ID, 4, "Prowise-PT301"
+};
+
 static const struct dmi_system_id dmi_platform_data[] = {
 	{
 		/* ACEPC T8 Cherry Trail Z8350 mini PC */
@@ -64,6 +76,16 @@
 		.driver_data = (void *)&acepc_t8_data,
 	},
 	{
+		/* Cyberbook T116 rugged tablet */
+		.matches = {
+			DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Default string"),
+			DMI_EXACT_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
+			DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "20170531"),
+		},
+		/* The factory image nvram file is identical to the ACEPC T8 one */
+		.driver_data = (void *)&acepc_t8_data,
+	},
+	{
 		/* Match for the GPDwin which unfortunately uses somewhat
 		 * generic dmi strings, which is why we test for 4 strings.
 		 * Comparing against 23 other byt/cht boards, board_vendor
@@ -111,6 +133,26 @@
 		},
 		.driver_data = (void *)&pov_tab_p1006w_data,
 	},
+	{
+		/* Predia Basic tablet (+ with keyboard dock) */
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "CherryTrail"),
+			/* Mx.WT107.KUBNGEA02 with the version-nr dropped */
+			DMI_MATCH(DMI_BIOS_VERSION, "Mx.WT107.KUBNGEA"),
+		},
+		.driver_data = (void *)&predia_basic_data,
+	},
+	{
+		/* Voyo winpad A15 tablet */
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
+			DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
+			/* Above strings are too generic, also match on BIOS date */
+			DMI_MATCH(DMI_BIOS_DATE, "11/20/2014"),
+		},
+		.driver_data = (void *)&voyo_winpad_a15_data,
+	},
 	{}
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
@@ -283,13 +283,14 @@
 	if (!err)
 		ifp->drvr->feat_flags |= BIT(BRCMF_FEAT_SCAN_RANDOM_MAC);
 
+	brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_FWSUP, "sup_wpa");
+
 	if (drvr->settings->feature_disable) {
 		brcmf_dbg(INFO, "Features: 0x%02x, disable: 0x%02x\n",
 			  ifp->drvr->feat_flags,
 			  drvr->settings->feature_disable);
 		ifp->drvr->feat_flags &= ~drvr->settings->feature_disable;
 	}
-	brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_FWSUP, "sup_wpa");
 
 	brcmf_feat_firmware_overrides(drvr);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
@@ -207,6 +207,8 @@
 		size = BRCMF_FW_MAX_NVRAM_SIZE;
 	else
 		size = data_len;
+	/* Add space for properties we may add */
+	size += strlen(BRCMF_FW_DEFAULT_BOARDREV) + 1;
 	/* Alloc for extra 0 byte + roundup by 4 + length field */
 	size += 1 + 3 + sizeof(u32);
 	nvp->nvram = kzalloc(size, GFP_KERNEL);
@@ -701,6 +703,11 @@
 	u32 i, j;
 	char end = '\0';
 
+	if (chiprev >= BITS_PER_TYPE(u32)) {
+		brcmf_err("Invalid chip revision %u\n", chiprev);
+		return NULL;
+	}
+
 	for (i = 0; i < table_size; i++) {
 		if (mapping_table[i].chipid == chip &&
 		    mapping_table[i].revmask & BIT(chiprev))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
@@ -228,6 +228,10 @@
 			  brcmf_fweh_event_name(event->code), event->code,
 			  event->emsg.ifidx, event->emsg.bsscfgidx,
 			  event->emsg.addr);
+		if (event->emsg.bsscfgidx >= BRCMF_MAX_IFS) {
+			bphy_err(drvr, "invalid bsscfg index: %u\n", event->emsg.bsscfgidx);
+			goto event_free;
+		}
 
 		/* convert event message */
 		emsg_be = &event->emsg;
@@ -304,10 +308,12 @@
 {
 	struct brcmf_fweh_info *fweh = &drvr->fweh;
 
-	/* cancel the worker */
-	cancel_work_sync(&fweh->event_work);
-	WARN_ON(!list_empty(&fweh->event_q));
-	memset(fweh->evt_handler, 0, sizeof(fweh->evt_handler));
+	/* cancel the worker if initialized */
+	if (fweh->event_work.func) {
+		cancel_work_sync(&fweh->event_work);
+		WARN_ON(!list_empty(&fweh->event_q));
+		memset(fweh->evt_handler, 0, sizeof(fweh->evt_handler));
+	}
 }
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
@@ -19,7 +19,7 @@
 #define BRCMF_ARP_OL_PEER_AUTO_REPLY	0x00000008
 
 #define	BRCMF_BSS_INFO_VERSION	109 /* curr ver of brcmf_bss_info_le struct */
-#define BRCMF_BSS_RSSI_ON_CHANNEL	0x0002
+#define BRCMF_BSS_RSSI_ON_CHANNEL	0x0004
 
 #define BRCMF_STA_BRCM			0x00000001	/* Running a Broadcom driver */
 #define BRCMF_STA_WME			0x00000002	/* WMM association */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
@@ -643,6 +643,7 @@
 static void brcmf_fws_psq_flush(struct brcmf_fws_info *fws, struct pktq *q,
 				int ifidx)
 {
+	struct brcmf_fws_hanger_item *hi;
 	bool (*matchfn)(struct sk_buff *, void *) = NULL;
 	struct sk_buff *skb;
 	int prec;
@@ -654,6 +655,9 @@
 		skb = brcmu_pktq_pdeq_match(q, prec, matchfn, &ifidx);
 		while (skb) {
 			hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
+			hi = &fws->hanger.items[hslot];
+			WARN_ON(skb != hi->pkt);
+			hi->state = BRCMF_FWS_HANGER_ITEM_STATE_FREE;
 			brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb,
 						true);
 			brcmu_pkt_buf_free_skb(skb);
@@ -2145,8 +2149,7 @@
 		brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_DELAYED, fifo, skb);
 		brcmf_fws_schedule_deq(fws);
 	} else {
-		bphy_err(drvr, "drop skb: no hanger slot\n");
-		brcmf_txfinalize(ifp, skb, false);
+		bphy_err(drvr, "no hanger slot available\n");
 		rc = -ENOMEM;
 	}
 	brcmf_fws_unlock(fws);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
@@ -345,8 +345,11 @@
 		count++;
 	} while (count < pktids->array_size);
 
-	if (count == pktids->array_size)
+	if (count == pktids->array_size) {
+		dma_unmap_single(dev, *physaddr, skb->len - data_offset,
+				 pktids->direction);
 		return -ENOMEM;
+	}
 
 	array[*idx].data_offset = data_offset;
 	array[*idx].physaddr = *physaddr;
@@ -1619,6 +1622,8 @@
 					  BRCMF_TX_IOCTL_MAX_MSG_SIZE,
 					  msgbuf->ioctbuf,
 					  msgbuf->ioctbuf_handle);
+		if (msgbuf->txflow_wq)
+			destroy_workqueue(msgbuf->txflow_wq);
 		kfree(msgbuf);
 	}
 	return -ENOMEM;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
@@ -2092,7 +2092,8 @@
 	/* firmware requires unique mac address for p2pdev interface */
 	if (addr && ether_addr_equal(addr, pri_ifp->mac_addr)) {
 		bphy_err(drvr, "discovery vif must be different from primary interface\n");
-		return ERR_PTR(-EINVAL);
+		err = -EINVAL;
+		goto fail;
 	}
 
 	brcmf_p2p_generate_bss_mac(p2p, addr);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
@@ -12,6 +12,7 @@
 #include <linux/interrupt.h>
 #include <linux/bcma/bcma.h>
 #include <linux/sched.h>
+#include <linux/io.h>
 #include <asm/unaligned.h>
 
 #include <soc.h>
@@ -445,47 +446,6 @@
 
 
 static void
-brcmf_pcie_copy_mem_todev(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
-			  void *srcaddr, u32 len)
-{
-	void __iomem *address = devinfo->tcm + mem_offset;
-	__le32 *src32;
-	__le16 *src16;
-	u8 *src8;
-
-	if (((ulong)address & 4) || ((ulong)srcaddr & 4) || (len & 4)) {
-		if (((ulong)address & 2) || ((ulong)srcaddr & 2) || (len & 2)) {
-			src8 = (u8 *)srcaddr;
-			while (len) {
-				iowrite8(*src8, address);
-				address++;
-				src8++;
-				len--;
-			}
-		} else {
-			len = len / 2;
-			src16 = (__le16 *)srcaddr;
-			while (len) {
-				iowrite16(le16_to_cpu(*src16), address);
-				address += 2;
-				src16++;
-				len--;
-			}
-		}
-	} else {
-		len = len / 4;
-		src32 = (__le32 *)srcaddr;
-		while (len) {
-			iowrite32(le32_to_cpu(*src32), address);
-			address += 4;
-			src32++;
-			len--;
-		}
-	}
-}
-
-
-static void
 brcmf_pcie_copy_dev_tomem(struct brcmf_pciedev_info *devinfo, u32 mem_offset,
 			  void *dstaddr, u32 len)
 {
@@ -656,7 +616,7 @@
 	}
 
 	if (!brcmf_chip_set_active(devinfo->ci, resetintr))
-		return -EINVAL;
+		return -EIO;
 	return 0;
 }
 
@@ -1149,6 +1109,10 @@
 				BRCMF_NROF_H2D_COMMON_MSGRINGS;
 		max_completionrings = BRCMF_NROF_D2H_COMMON_MSGRINGS;
 	}
+	if (max_flowrings > 512) {
+		brcmf_err(bus, "invalid max_flowrings(%d)\n", max_flowrings);
+		return -EIO;
+	}
 
 	if (devinfo->dma_idx_sz != 0) {
 		bufsz = (max_submissionrings + max_completionrings) *
@@ -1346,6 +1310,18 @@
 {
 }
 
+static int brcmf_pcie_preinit(struct device *dev)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+	struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie;
+
+	brcmf_dbg(PCIE, "Enter\n");
+
+	brcmf_pcie_intr_enable(buspub->devinfo);
+	brcmf_pcie_hostready(buspub->devinfo);
+
+	return 0;
+}
 
 static int brcmf_pcie_tx(struct device *dev, struct sk_buff *skb)
 {
@@ -1427,6 +1403,8 @@
 	struct brcmf_fw_request *fwreq;
 	int err;
 
+	brcmf_pcie_intr_disable(devinfo);
+
 	brcmf_pcie_bus_console_read(devinfo, true);
 
 	brcmf_detach(dev);
@@ -1452,6 +1430,7 @@
 }
 
 static const struct brcmf_bus_ops brcmf_pcie_bus_ops = {
+	.preinit = brcmf_pcie_preinit,
 	.txdata = brcmf_pcie_tx,
 	.stop = brcmf_pcie_down,
 	.txctl = brcmf_pcie_tx_ctlpkt,
@@ -1559,8 +1538,8 @@
 		return err;
 
 	brcmf_dbg(PCIE, "Download FW %s\n", devinfo->fw_name);
-	brcmf_pcie_copy_mem_todev(devinfo, devinfo->ci->rambase,
-				  (void *)fw->data, fw->size);
+	memcpy_toio(devinfo->tcm + devinfo->ci->rambase,
+		    (void *)fw->data, fw->size);
 
 	resetintr = get_unaligned_le32(fw->data);
 	release_firmware(fw);
@@ -1574,7 +1553,7 @@
 		brcmf_dbg(PCIE, "Download NVRAM %s\n", devinfo->nvram_name);
 		address = devinfo->ci->rambase + devinfo->ci->ramsize -
 			  nvram_len;
-		brcmf_pcie_copy_mem_todev(devinfo, address, nvram, nvram_len);
+		memcpy_toio(devinfo->tcm + address, nvram, nvram_len);
 		brcmf_fw_nvram_free(nvram);
 	} else {
 		brcmf_dbg(PCIE, "No matching NVRAM file found %s\n",
@@ -1773,6 +1752,8 @@
 	ret = brcmf_chip_get_raminfo(devinfo->ci);
 	if (ret) {
 		brcmf_err(bus, "Failed to get RAM info\n");
+		release_firmware(fw);
+		brcmf_fw_nvram_free(nvram);
 		goto fail;
 	}
 
@@ -1822,9 +1803,6 @@
 
 	init_waitqueue_head(&devinfo->mbdata_resp_wait);
 
-	brcmf_pcie_intr_enable(devinfo);
-	brcmf_pcie_hostready(devinfo);
-
 	ret = brcmf_attach(&devinfo->pdev->dev);
 	if (ret)
 		goto fail;
@@ -1934,16 +1912,18 @@
 	fwreq = brcmf_pcie_prepare_fw_request(devinfo);
 	if (!fwreq) {
 		ret = -ENOMEM;
-		goto fail_bus;
+		goto fail_brcmf;
 	}
 
 	ret = brcmf_fw_get_firmwares(bus->dev, fwreq, brcmf_pcie_setup);
 	if (ret < 0) {
 		kfree(fwreq);
-		goto fail_bus;
+		goto fail_brcmf;
 	}
 	return 0;
 
+fail_brcmf:
+	brcmf_free(&devinfo->pdev->dev);
 fail_bus:
 	kfree(bus->msgbuf);
 	kfree(bus);
@@ -2069,7 +2049,7 @@
 
 	err = brcmf_pcie_probe(pdev, NULL);
 	if (err)
-		brcmf_err(bus, "probe after resume failed, err=%d\n", err);
+		__brcmf_err(NULL, __func__, "probe after resume failed, err=%d\n", err);
 
 	return err;
 }
@@ -2133,15 +2113,10 @@
 };
 
 
-void brcmf_pcie_register(void)
+int brcmf_pcie_register(void)
 {
-	int err;
-
 	brcmf_dbg(PCIE, "Enter\n");
-	err = pci_register_driver(&brcmf_pciedrvr);
-	if (err)
-		brcmf_err(NULL, "PCIE driver registration failed, err=%d\n",
-			  err);
+	return pci_register_driver(&brcmf_pciedrvr);
 }
 
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.h
@@ -11,9 +11,4 @@
 	struct brcmf_pciedev_info *devinfo;
 };
 
-
-void brcmf_pcie_exit(void);
-void brcmf_pcie_register(void);
-
-
 #endif /* BRCMFMAC_PCIE_H */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
@@ -154,12 +154,12 @@
 	struct brcmf_pno_macaddr_le pfn_mac;
 	u8 *mac_addr = NULL;
 	u8 *mac_mask = NULL;
-	int err, i;
+	int err, i, ri;
 
-	for (i = 0; i < pi->n_reqs; i++)
-		if (pi->reqs[i]->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
-			mac_addr = pi->reqs[i]->mac_addr;
-			mac_mask = pi->reqs[i]->mac_addr_mask;
+	for (ri = 0; ri < pi->n_reqs; ri++)
+		if (pi->reqs[ri]->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
+			mac_addr = pi->reqs[ri]->mac_addr;
+			mac_mask = pi->reqs[ri]->mac_addr_mask;
 			break;
 		}
 
@@ -181,7 +181,7 @@
 	pfn_mac.mac[0] |= 0x02;
 
 	brcmf_dbg(SCAN, "enabling random mac: reqid=%llu mac=%pM\n",
-		  pi->reqs[i]->reqid, pfn_mac.mac);
+		  pi->reqs[ri]->reqid, pfn_mac.mac);
 	err = brcmf_fil_iovar_data_set(ifp, "pfn_macaddr", &pfn_mac,
 				       sizeof(pfn_mac));
 	if (err)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -550,7 +550,7 @@
 	BRCMF_SDIO_FT_SUB,
 };
 
-#define SDIOD_DRVSTR_KEY(chip, pmu)     (((chip) << 16) | (pmu))
+#define SDIOD_DRVSTR_KEY(chip, pmu)     (((unsigned int)(chip) << 16) | (pmu))
 
 /* SDIO Pad drive strength to select value mappings */
 struct sdiod_drive_str {
@@ -1934,7 +1934,10 @@
 			if (brcmf_sdio_hdparse(bus, bus->rxhdr, &rd_new,
 					       BRCMF_SDIO_FT_NORMAL)) {
 				rd->len = 0;
+				brcmf_sdio_rxfail(bus, true, true);
+				sdio_release_host(bus->sdiodev->func1);
 				brcmu_pkt_buf_free_skb(pkt);
+				continue;
 			}
 			bus->sdcnt.rx_readahead_cnt++;
 			if (rd->len != roundup(rd_new.len, 16)) {
@@ -3364,6 +3367,7 @@
 	/* Take arm out of reset */
 	if (!brcmf_chip_set_active(bus->ci, rstvec)) {
 		brcmf_err("error getting out of ARM core reset\n");
+		bcmerror = -EIO;
 		goto err;
 	}
 
@@ -3682,7 +3686,11 @@
 			if (bus->idlecount > bus->idletime) {
 				brcmf_dbg(SDIO, "idle\n");
 				sdio_claim_host(bus->sdiodev->func1);
-				brcmf_sdio_wd_timer(bus, false);
+#ifdef DEBUG
+				if (!BRCMF_FWCON_ON() ||
+				    bus->console_interval == 0)
+#endif
+					brcmf_sdio_wd_timer(bus, false);
 				bus->idlecount = 0;
 				brcmf_sdio_bus_sleep(bus, true, false);
 				sdio_release_host(bus->sdiodev->func1);
@@ -4225,6 +4233,12 @@
 	}
 
 	if (err == 0) {
+		/* Assign bus interface call back */
+		sdiod->bus_if->dev = sdiod->dev;
+		sdiod->bus_if->ops = &brcmf_sdio_bus_ops;
+		sdiod->bus_if->chip = bus->ci->chip;
+		sdiod->bus_if->chiprev = bus->ci->chiprev;
+
 		/* Allow full data communication using DPC from now on. */
 		brcmf_sdiod_change_state(bus->sdiodev, BRCMF_SDIOD_DATA);
 
@@ -4241,12 +4255,6 @@
 
 	sdio_release_host(sdiod->func1);
 
-	/* Assign bus interface call back */
-	sdiod->bus_if->dev = sdiod->dev;
-	sdiod->bus_if->ops = &brcmf_sdio_bus_ops;
-	sdiod->bus_if->chip = bus->ci->chip;
-	sdiod->bus_if->chiprev = bus->ci->chiprev;
-
 	err = brcmf_alloc(sdiod->dev, sdiod->settings);
 	if (err) {
 		brcmf_err("brcmf_alloc failed\n");
@@ -4426,6 +4434,7 @@
 		brcmf_sdiod_intr_unregister(bus->sdiodev);
 
 		brcmf_detach(bus->sdiodev->dev);
+		brcmf_free(bus->sdiodev->dev);
 
 		cancel_work_sync(&bus->datawork);
 		if (bus->brcmf_wq)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
@@ -430,6 +430,7 @@
 			usb_free_urb(req->urb);
 		list_del(q->next);
 	}
+	kfree(reqs);
 	return NULL;
 
 }
@@ -1348,7 +1349,7 @@
 		goto fail;
 	}
 
-	desc = &intf->altsetting[0].desc;
+	desc = &intf->cur_altsetting->desc;
 	if ((desc->bInterfaceClass != USB_CLASS_VENDOR_SPEC) ||
 	    (desc->bInterfaceSubClass != 2) ||
 	    (desc->bInterfaceProtocol != 0xff)) {
@@ -1361,7 +1362,7 @@
 
 	num_of_eps = desc->bNumEndpoints;
 	for (ep = 0; ep < num_of_eps; ep++) {
-		endpoint = &intf->altsetting[0].endpoint[ep].desc;
+		endpoint = &intf->cur_altsetting->endpoint[ep].desc;
 		endpoint_num = usb_endpoint_num(endpoint);
 		if (!usb_endpoint_xfer_bulk(endpoint))
 			continue;
@@ -1557,12 +1558,8 @@
 	usb_deregister(&brcmf_usbdrvr);
 }
 
-void brcmf_usb_register(void)
+int brcmf_usb_register(void)
 {
-	int ret;
-
 	brcmf_dbg(USB, "Enter\n");
-	ret = usb_register(&brcmf_usbdrvr);
-	if (ret)
-		brcmf_err("usb_register failed %d\n", ret);
+	return usb_register(&brcmf_usbdrvr);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c
@@ -850,8 +850,7 @@
 				     "START: tid %d is not agg\'able\n", tid);
 			return -EINVAL;
 		}
-		ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
-		break;
+		return IEEE80211_AMPDU_TX_START_IMMEDIATE;
 
 	case IEEE80211_AMPDU_TX_STOP_CONT:
 	case IEEE80211_AMPDU_TX_STOP_FLUSH:
@@ -1091,6 +1090,7 @@
 	ieee80211_hw_set(hw, AMPDU_AGGREGATION);
 	ieee80211_hw_set(hw, SIGNAL_DBM);
 	ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS);
+	ieee80211_hw_set(hw, MFP_CAPABLE);
 
 	hw->extra_tx_headroom = brcms_c_get_header_len();
 	hw->queues = N_TX_QUEUES;
@@ -1223,6 +1223,7 @@
 {
 	struct brcms_info *wl;
 	struct ieee80211_hw *hw;
+	int ret;
 
 	dev_info(&pdev->dev, "mfg %x core %x rev %d class %d irq %d\n",
 		 pdev->id.manuf, pdev->id.id, pdev->id.rev, pdev->id.class,
@@ -1247,11 +1248,16 @@
 	wl = brcms_attach(pdev);
 	if (!wl) {
 		pr_err("%s: brcms_attach failed!\n", __func__);
-		return -ENODEV;
+		ret = -ENODEV;
+		goto err_free_ieee80211;
 	}
 	brcms_led_register(wl);
 
 	return 0;
+
+err_free_ieee80211:
+	ieee80211_free_hw(hw);
+	return ret;
 }
 
 static int brcms_suspend(struct bcma_device *pdev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_cmn.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_cmn.c
@@ -383,8 +383,9 @@
 	return sh;
 }
 
-static void wlc_phy_timercb_phycal(struct brcms_phy *pi)
+static void wlc_phy_timercb_phycal(void *ptr)
 {
+	struct brcms_phy *pi = ptr;
 	uint delay = 5;
 
 	if (PHY_PERICAL_MPHASE_PENDING(pi)) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c
@@ -2625,7 +2625,6 @@
 
 	struct lcnphy_txgains cal_gains, temp_gains;
 	u16 hash;
-	u8 band_idx;
 	int j;
 	u16 ncorr_override[5];
 	u16 syst_coeffs[] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
@@ -2657,6 +2656,9 @@
 	u16 *values_to_save;
 	struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
 
+	if (WARN_ON(CHSPEC_IS5G(pi->radio_chanspec)))
+		return;
+
 	values_to_save = kmalloc_array(20, sizeof(u16), GFP_ATOMIC);
 	if (NULL == values_to_save)
 		return;
@@ -2720,20 +2722,18 @@
 	hash = (target_gains->gm_gain << 8) |
 	       (target_gains->pga_gain << 4) | (target_gains->pad_gain);
 
-	band_idx = (CHSPEC_IS5G(pi->radio_chanspec) ? 1 : 0);
-
 	cal_gains = *target_gains;
 	memset(ncorr_override, 0, sizeof(ncorr_override));
-	for (j = 0; j < iqcal_gainparams_numgains_lcnphy[band_idx]; j++) {
-		if (hash == tbl_iqcal_gainparams_lcnphy[band_idx][j][0]) {
+	for (j = 0; j < iqcal_gainparams_numgains_lcnphy[0]; j++) {
+		if (hash == tbl_iqcal_gainparams_lcnphy[0][j][0]) {
 			cal_gains.gm_gain =
-				tbl_iqcal_gainparams_lcnphy[band_idx][j][1];
+				tbl_iqcal_gainparams_lcnphy[0][j][1];
 			cal_gains.pga_gain =
-				tbl_iqcal_gainparams_lcnphy[band_idx][j][2];
+				tbl_iqcal_gainparams_lcnphy[0][j][2];
 			cal_gains.pad_gain =
-				tbl_iqcal_gainparams_lcnphy[band_idx][j][3];
+				tbl_iqcal_gainparams_lcnphy[0][j][3];
 			memcpy(ncorr_override,
-			       &tbl_iqcal_gainparams_lcnphy[band_idx][j][3],
+			       &tbl_iqcal_gainparams_lcnphy[0][j][3],
 			       sizeof(ncorr_override));
 			break;
 		}
@@ -5065,8 +5065,10 @@
 	pi->pi_fptr.radioloftget = wlc_lcnphy_get_radio_loft;
 	pi->pi_fptr.detach = wlc_phy_detach_lcnphy;
 
-	if (!wlc_phy_txpwr_srom_read_lcnphy(pi))
+	if (!wlc_phy_txpwr_srom_read_lcnphy(pi)) {
+		kfree(pi->u.pi_lcnphy);
 		return false;
+	}
 
 	if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
 		if (pi_lcn->lcnphy_tempsense_option == 3) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c
@@ -23445,6 +23445,9 @@
 			}
 		}
 
+		if (WARN_ON(k == NPHY_IQCAL_NUMGAINS))
+			return;
+
 		params->txgm = tbl_iqcal_gainparams_nphy[band_idx][k][1];
 		params->pga = tbl_iqcal_gainparams_nphy[band_idx][k][2];
 		params->pad = tbl_iqcal_gainparams_nphy[band_idx][k][3];
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy_shim.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy_shim.c
@@ -57,12 +57,11 @@
 }
 
 struct wlapi_timer *wlapi_init_timer(struct phy_shim_info *physhim,
-				     void (*fn)(struct brcms_phy *pi),
+				     void (*fn)(void *pi),
 				     void *arg, const char *name)
 {
 	return (struct wlapi_timer *)
-			brcms_init_timer(physhim->wl, (void (*)(void *))fn,
-					 arg, name);
+			brcms_init_timer(physhim->wl, fn, arg, name);
 }
 
 void wlapi_free_timer(struct wlapi_timer *t)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy_shim.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy_shim.h
@@ -131,7 +131,7 @@
 
 /* PHY to WL utility functions */
 struct wlapi_timer *wlapi_init_timer(struct phy_shim_info *physhim,
-				     void (*fn)(struct brcms_phy *pi),
+				     void (*fn)(void *pi),
 				     void *arg, const char *name);
 void wlapi_free_timer(struct wlapi_timer *t);
 void wlapi_add_timer(struct wlapi_timer *t, uint ms, int periodic);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/cisco/airo.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/cisco/airo.c
@@ -1925,6 +1925,10 @@
 		airo_print_err(dev->name, "%s: skb == NULL!",__func__);
 		return NETDEV_TX_OK;
 	}
+	if (skb_padto(skb, ETH_ZLEN)) {
+		dev->stats.tx_dropped++;
+		return NETDEV_TX_OK;
+	}
 	npacks = skb_queue_len (&ai->txq);
 
 	if (npacks >= MAXTXQ - 1) {
@@ -2127,6 +2131,10 @@
 		airo_print_err(dev->name, "%s: skb == NULL!", __func__);
 		return NETDEV_TX_OK;
 	}
+	if (skb_padto(skb, ETH_ZLEN)) {
+		dev->stats.tx_dropped++;
+		return NETDEV_TX_OK;
+	}
 
 	/* Find a vacant FID */
 	for( i = 0; i < MAX_FIDS / 2 && (fids[i] & 0xffff0000); i++ );
@@ -2201,6 +2209,10 @@
 		airo_print_err(dev->name, "%s: skb == NULL!", __func__);
 		return NETDEV_TX_OK;
 	}
+	if (skb_padto(skb, ETH_ZLEN)) {
+		dev->stats.tx_dropped++;
+		return NETDEV_TX_OK;
+	}
 
 	/* Find a vacant FID */
 	for( i = MAX_FIDS / 2; i < MAX_FIDS && (fids[i] & 0xffff0000); i++ );
@@ -6092,8 +6104,11 @@
 {
 	struct airo_info *local = dev->ml_priv;
 	StatusRid status_rid;		/* Card status info */
+	int ret;
 
-	readStatusRid(local, &status_rid, 1);
+	ret = readStatusRid(local, &status_rid, 1);
+	if (ret)
+		return -EBUSY;
 
 	vwrq->value = le16_to_cpu(status_rid.currentXmitRate) * 500000;
 	/* If more than one rate, set auto */
@@ -7790,16 +7805,8 @@
 	case AIROGVLIST:    ridcode = RID_APLIST;       break;
 	case AIROGDRVNAM:   ridcode = RID_DRVNAME;      break;
 	case AIROGEHTENC:   ridcode = RID_ETHERENCAP;   break;
-	case AIROGWEPKTMP:  ridcode = RID_WEP_TEMP;
-		/* Only super-user can read WEP keys */
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		break;
-	case AIROGWEPKNV:   ridcode = RID_WEP_PERM;
-		/* Only super-user can read WEP keys */
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		break;
+	case AIROGWEPKTMP:  ridcode = RID_WEP_TEMP;	break;
+	case AIROGWEPKNV:   ridcode = RID_WEP_PERM;	break;
 	case AIROGSTAT:     ridcode = RID_STATUS;       break;
 	case AIROGSTATSD32: ridcode = RID_STATSDELTA;   break;
 	case AIROGSTATSC32: ridcode = RID_STATS;        break;
@@ -7813,7 +7820,13 @@
 		return -EINVAL;
 	}
 
-	if ((iobuf = kmalloc(RIDSIZE, GFP_KERNEL)) == NULL)
+	if (ridcode == RID_WEP_TEMP || ridcode == RID_WEP_PERM) {
+		/* Only super-user can read WEP keys */
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+	}
+
+	if ((iobuf = kzalloc(RIDSIZE, GFP_KERNEL)) == NULL)
 		return -ENOMEM;
 
 	PC4500_readrid(ai,ridcode,iobuf,RIDSIZE, 1);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/ipw2x00/ipw2100.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/ipw2x00/ipw2100.c
@@ -2294,10 +2294,11 @@
 		return -ENOMEM;
 
 	packet->rxp = (struct ipw2100_rx *)packet->skb->data;
-	packet->dma_addr = pci_map_single(priv->pci_dev, packet->skb->data,
+	packet->dma_addr = dma_map_single(&priv->pci_dev->dev,
+					  packet->skb->data,
 					  sizeof(struct ipw2100_rx),
-					  PCI_DMA_FROMDEVICE);
-	if (pci_dma_mapping_error(priv->pci_dev, packet->dma_addr)) {
+					  DMA_FROM_DEVICE);
+	if (dma_mapping_error(&priv->pci_dev->dev, packet->dma_addr)) {
 		dev_kfree_skb(packet->skb);
 		return -ENOMEM;
 	}
@@ -2478,9 +2479,8 @@
 		return;
 	}
 
-	pci_unmap_single(priv->pci_dev,
-			 packet->dma_addr,
-			 sizeof(struct ipw2100_rx), PCI_DMA_FROMDEVICE);
+	dma_unmap_single(&priv->pci_dev->dev, packet->dma_addr,
+			 sizeof(struct ipw2100_rx), DMA_FROM_DEVICE);
 
 	skb_put(packet->skb, status->frame_size);
 
@@ -2562,8 +2562,8 @@
 		return;
 	}
 
-	pci_unmap_single(priv->pci_dev, packet->dma_addr,
-			 sizeof(struct ipw2100_rx), PCI_DMA_FROMDEVICE);
+	dma_unmap_single(&priv->pci_dev->dev, packet->dma_addr,
+			 sizeof(struct ipw2100_rx), DMA_FROM_DEVICE);
 	memmove(packet->skb->data + sizeof(struct ipw_rt_hdr),
 		packet->skb->data, status->frame_size);
 
@@ -2688,9 +2688,9 @@
 
 		/* Sync the DMA for the RX buffer so CPU is sure to get
 		 * the correct values */
-		pci_dma_sync_single_for_cpu(priv->pci_dev, packet->dma_addr,
-					    sizeof(struct ipw2100_rx),
-					    PCI_DMA_FROMDEVICE);
+		dma_sync_single_for_cpu(&priv->pci_dev->dev, packet->dma_addr,
+					sizeof(struct ipw2100_rx),
+					DMA_FROM_DEVICE);
 
 		if (unlikely(ipw2100_corruption_check(priv, i))) {
 			ipw2100_corruption_detected(priv, i);
@@ -2922,9 +2922,8 @@
 				     (packet->index + 1 + i) % txq->entries,
 				     tbd->host_addr, tbd->buf_length);
 
-			pci_unmap_single(priv->pci_dev,
-					 tbd->host_addr,
-					 tbd->buf_length, PCI_DMA_TODEVICE);
+			dma_unmap_single(&priv->pci_dev->dev, tbd->host_addr,
+					 tbd->buf_length, DMA_TO_DEVICE);
 		}
 
 		libipw_txb_free(packet->info.d_struct.txb);
@@ -3164,15 +3163,13 @@
 			tbd->buf_length = packet->info.d_struct.txb->
 			    fragments[i]->len - LIBIPW_3ADDR_LEN;
 
-			tbd->host_addr = pci_map_single(priv->pci_dev,
+			tbd->host_addr = dma_map_single(&priv->pci_dev->dev,
 							packet->info.d_struct.
-							txb->fragments[i]->
-							data +
+							txb->fragments[i]->data +
 							LIBIPW_3ADDR_LEN,
 							tbd->buf_length,
-							PCI_DMA_TODEVICE);
-			if (pci_dma_mapping_error(priv->pci_dev,
-						  tbd->host_addr)) {
+							DMA_TO_DEVICE);
+			if (dma_mapping_error(&priv->pci_dev->dev, tbd->host_addr)) {
 				IPW_DEBUG_TX("dma mapping error\n");
 				break;
 			}
@@ -3181,10 +3178,10 @@
 				     txq->next, tbd->host_addr,
 				     tbd->buf_length);
 
-			pci_dma_sync_single_for_device(priv->pci_dev,
-						       tbd->host_addr,
-						       tbd->buf_length,
-						       PCI_DMA_TODEVICE);
+			dma_sync_single_for_device(&priv->pci_dev->dev,
+						   tbd->host_addr,
+						   tbd->buf_length,
+						   DMA_TO_DEVICE);
 
 			txq->next++;
 			txq->next %= txq->entries;
@@ -3206,8 +3203,9 @@
 	}
 }
 
-static void ipw2100_irq_tasklet(struct ipw2100_priv *priv)
+static void ipw2100_irq_tasklet(unsigned long data)
 {
+	struct ipw2100_priv *priv = (struct ipw2100_priv *)data;
 	struct net_device *dev = priv->net_dev;
 	unsigned long flags;
 	u32 inta, tmp;
@@ -3438,9 +3436,9 @@
 		return -ENOMEM;
 
 	for (i = 0; i < IPW_COMMAND_POOL_SIZE; i++) {
-		v = pci_zalloc_consistent(priv->pci_dev,
-					  sizeof(struct ipw2100_cmd_header),
-					  &p);
+		v = dma_alloc_coherent(&priv->pci_dev->dev,
+				       sizeof(struct ipw2100_cmd_header), &p,
+				       GFP_KERNEL);
 		if (!v) {
 			printk(KERN_ERR DRV_NAME ": "
 			       "%s: PCI alloc failed for msg "
@@ -3459,11 +3457,10 @@
 		return 0;
 
 	for (j = 0; j < i; j++) {
-		pci_free_consistent(priv->pci_dev,
-				    sizeof(struct ipw2100_cmd_header),
-				    priv->msg_buffers[j].info.c_struct.cmd,
-				    priv->msg_buffers[j].info.c_struct.
-				    cmd_phys);
+		dma_free_coherent(&priv->pci_dev->dev,
+				  sizeof(struct ipw2100_cmd_header),
+				  priv->msg_buffers[j].info.c_struct.cmd,
+				  priv->msg_buffers[j].info.c_struct.cmd_phys);
 	}
 
 	kfree(priv->msg_buffers);
@@ -3494,11 +3491,10 @@
 		return;
 
 	for (i = 0; i < IPW_COMMAND_POOL_SIZE; i++) {
-		pci_free_consistent(priv->pci_dev,
-				    sizeof(struct ipw2100_cmd_header),
-				    priv->msg_buffers[i].info.c_struct.cmd,
-				    priv->msg_buffers[i].info.c_struct.
-				    cmd_phys);
+		dma_free_coherent(&priv->pci_dev->dev,
+				  sizeof(struct ipw2100_cmd_header),
+				  priv->msg_buffers[i].info.c_struct.cmd,
+				  priv->msg_buffers[i].info.c_struct.cmd_phys);
 	}
 
 	kfree(priv->msg_buffers);
@@ -4321,7 +4317,8 @@
 	IPW_DEBUG_INFO("enter\n");
 
 	q->size = entries * sizeof(struct ipw2100_status);
-	q->drv = pci_zalloc_consistent(priv->pci_dev, q->size, &q->nic);
+	q->drv = dma_alloc_coherent(&priv->pci_dev->dev, q->size, &q->nic,
+				    GFP_KERNEL);
 	if (!q->drv) {
 		IPW_DEBUG_WARNING("Can not allocate status queue.\n");
 		return -ENOMEM;
@@ -4337,9 +4334,10 @@
 	IPW_DEBUG_INFO("enter\n");
 
 	if (priv->status_queue.drv) {
-		pci_free_consistent(priv->pci_dev, priv->status_queue.size,
-				    priv->status_queue.drv,
-				    priv->status_queue.nic);
+		dma_free_coherent(&priv->pci_dev->dev,
+				  priv->status_queue.size,
+				  priv->status_queue.drv,
+				  priv->status_queue.nic);
 		priv->status_queue.drv = NULL;
 	}
 
@@ -4355,7 +4353,8 @@
 
 	q->entries = entries;
 	q->size = entries * sizeof(struct ipw2100_bd);
-	q->drv = pci_zalloc_consistent(priv->pci_dev, q->size, &q->nic);
+	q->drv = dma_alloc_coherent(&priv->pci_dev->dev, q->size, &q->nic,
+				    GFP_KERNEL);
 	if (!q->drv) {
 		IPW_DEBUG_INFO
 		    ("can't allocate shared memory for buffer descriptors\n");
@@ -4375,7 +4374,8 @@
 		return;
 
 	if (q->drv) {
-		pci_free_consistent(priv->pci_dev, q->size, q->drv, q->nic);
+		dma_free_coherent(&priv->pci_dev->dev, q->size, q->drv,
+				  q->nic);
 		q->drv = NULL;
 	}
 
@@ -4435,9 +4435,9 @@
 	}
 
 	for (i = 0; i < TX_PENDED_QUEUE_LENGTH; i++) {
-		v = pci_alloc_consistent(priv->pci_dev,
-					 sizeof(struct ipw2100_data_header),
-					 &p);
+		v = dma_alloc_coherent(&priv->pci_dev->dev,
+				       sizeof(struct ipw2100_data_header), &p,
+				       GFP_KERNEL);
 		if (!v) {
 			printk(KERN_ERR DRV_NAME
 			       ": %s: PCI alloc failed for tx " "buffers.\n",
@@ -4457,11 +4457,10 @@
 		return 0;
 
 	for (j = 0; j < i; j++) {
-		pci_free_consistent(priv->pci_dev,
-				    sizeof(struct ipw2100_data_header),
-				    priv->tx_buffers[j].info.d_struct.data,
-				    priv->tx_buffers[j].info.d_struct.
-				    data_phys);
+		dma_free_coherent(&priv->pci_dev->dev,
+				  sizeof(struct ipw2100_data_header),
+				  priv->tx_buffers[j].info.d_struct.data,
+				  priv->tx_buffers[j].info.d_struct.data_phys);
 	}
 
 	kfree(priv->tx_buffers);
@@ -4538,12 +4537,10 @@
 			priv->tx_buffers[i].info.d_struct.txb = NULL;
 		}
 		if (priv->tx_buffers[i].info.d_struct.data)
-			pci_free_consistent(priv->pci_dev,
-					    sizeof(struct ipw2100_data_header),
-					    priv->tx_buffers[i].info.d_struct.
-					    data,
-					    priv->tx_buffers[i].info.d_struct.
-					    data_phys);
+			dma_free_coherent(&priv->pci_dev->dev,
+					  sizeof(struct ipw2100_data_header),
+					  priv->tx_buffers[i].info.d_struct.data,
+					  priv->tx_buffers[i].info.d_struct.data_phys);
 	}
 
 	kfree(priv->tx_buffers);
@@ -4606,9 +4603,10 @@
 		return 0;
 
 	for (j = 0; j < i; j++) {
-		pci_unmap_single(priv->pci_dev, priv->rx_buffers[j].dma_addr,
+		dma_unmap_single(&priv->pci_dev->dev,
+				 priv->rx_buffers[j].dma_addr,
 				 sizeof(struct ipw2100_rx_packet),
-				 PCI_DMA_FROMDEVICE);
+				 DMA_FROM_DEVICE);
 		dev_kfree_skb(priv->rx_buffers[j].skb);
 	}
 
@@ -4660,10 +4658,10 @@
 
 	for (i = 0; i < RX_QUEUE_LENGTH; i++) {
 		if (priv->rx_buffers[i].rxp) {
-			pci_unmap_single(priv->pci_dev,
+			dma_unmap_single(&priv->pci_dev->dev,
 					 priv->rx_buffers[i].dma_addr,
 					 sizeof(struct ipw2100_rx),
-					 PCI_DMA_FROMDEVICE);
+					 DMA_FROM_DEVICE);
 			dev_kfree_skb(priv->rx_buffers[i].skb);
 		}
 	}
@@ -6007,7 +6005,7 @@
 	spin_unlock_irqrestore(&priv->low_lock, flags);
 }
 
-static void ipw2100_irq_tasklet(struct ipw2100_priv *priv);
+static void ipw2100_irq_tasklet(unsigned long data);
 
 static const struct net_device_ops ipw2100_netdev_ops = {
 	.ndo_open		= ipw2100_open,
@@ -6137,7 +6135,7 @@
 	INIT_DELAYED_WORK(&priv->rf_kill, ipw2100_rf_kill);
 	INIT_DELAYED_WORK(&priv->scan_event, ipw2100_scan_event);
 
-	tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
+	tasklet_init(&priv->irq_tasklet,
 		     ipw2100_irq_tasklet, (unsigned long)priv);
 
 	/* NOTE:  We do not start the deferred work for status checks yet */
@@ -6195,7 +6193,7 @@
 	pci_set_master(pci_dev);
 	pci_set_drvdata(pci_dev, priv);
 
-	err = pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32));
+	err = dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(32));
 	if (err) {
 		printk(KERN_WARNING DRV_NAME
 		       "Error calling pci_set_dma_mask.\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/ipw2x00/ipw2200.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/ipw2x00/ipw2200.c
@@ -1945,8 +1945,9 @@
 	wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL);
 }
 
-static void ipw_irq_tasklet(struct ipw_priv *priv)
+static void ipw_irq_tasklet(unsigned long data)
 {
+	struct ipw_priv *priv = (struct ipw_priv *)data;
 	u32 inta, inta_mask, handled = 0;
 	unsigned long flags;
 	int rc = 0;
@@ -3441,9 +3442,10 @@
 		/* In the reset function, these buffers may have been allocated
 		 * to an SKB, so we need to unmap and free potential storage */
 		if (rxq->pool[i].skb != NULL) {
-			pci_unmap_single(priv->pci_dev, rxq->pool[i].dma_addr,
-					 IPW_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
-			dev_kfree_skb(rxq->pool[i].skb);
+			dma_unmap_single(&priv->pci_dev->dev,
+					 rxq->pool[i].dma_addr,
+					 IPW_RX_BUF_SIZE, DMA_FROM_DEVICE);
+			dev_kfree_skb_irq(rxq->pool[i].skb);
 			rxq->pool[i].skb = NULL;
 		}
 		list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
@@ -3775,7 +3777,8 @@
 	}
 
 	q->bd =
-	    pci_alloc_consistent(dev, sizeof(q->bd[0]) * count, &q->q.dma_addr);
+	    dma_alloc_coherent(&dev->dev, sizeof(q->bd[0]) * count,
+			       &q->q.dma_addr, GFP_KERNEL);
 	if (!q->bd) {
 		IPW_ERROR("pci_alloc_consistent(%zd) failed\n",
 			  sizeof(q->bd[0]) * count);
@@ -3817,9 +3820,10 @@
 
 	/* unmap chunks if any */
 	for (i = 0; i < le32_to_cpu(bd->u.data.num_chunks); i++) {
-		pci_unmap_single(dev, le32_to_cpu(bd->u.data.chunk_ptr[i]),
+		dma_unmap_single(&dev->dev,
+				 le32_to_cpu(bd->u.data.chunk_ptr[i]),
 				 le16_to_cpu(bd->u.data.chunk_len[i]),
-				 PCI_DMA_TODEVICE);
+				 DMA_TO_DEVICE);
 		if (txq->txb[txq->q.last_used]) {
 			libipw_txb_free(txq->txb[txq->q.last_used]);
 			txq->txb[txq->q.last_used] = NULL;
@@ -3851,8 +3855,8 @@
 	}
 
 	/* free buffers belonging to queue itself */
-	pci_free_consistent(dev, sizeof(txq->bd[0]) * q->n_bd, txq->bd,
-			    q->dma_addr);
+	dma_free_coherent(&dev->dev, sizeof(txq->bd[0]) * q->n_bd, txq->bd,
+			  q->dma_addr);
 	kfree(txq->txb);
 
 	/* 0 fill whole structure */
@@ -5197,8 +5201,8 @@
 		list_del(element);
 
 		rxb->dma_addr =
-		    pci_map_single(priv->pci_dev, rxb->skb->data,
-				   IPW_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+		    dma_map_single(&priv->pci_dev->dev, rxb->skb->data,
+				   IPW_RX_BUF_SIZE, DMA_FROM_DEVICE);
 
 		list_add_tail(&rxb->list, &rxq->rx_free);
 		rxq->free_count++;
@@ -5231,8 +5235,9 @@
 
 	for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
 		if (rxq->pool[i].skb != NULL) {
-			pci_unmap_single(priv->pci_dev, rxq->pool[i].dma_addr,
-					 IPW_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+			dma_unmap_single(&priv->pci_dev->dev,
+					 rxq->pool[i].dma_addr,
+					 IPW_RX_BUF_SIZE, DMA_FROM_DEVICE);
 			dev_kfree_skb(rxq->pool[i].skb);
 		}
 	}
@@ -8270,9 +8275,8 @@
 		}
 		priv->rxq->queue[i] = NULL;
 
-		pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->dma_addr,
-					    IPW_RX_BUF_SIZE,
-					    PCI_DMA_FROMDEVICE);
+		dma_sync_single_for_cpu(&priv->pci_dev->dev, rxb->dma_addr,
+					IPW_RX_BUF_SIZE, DMA_FROM_DEVICE);
 
 		pkt = (struct ipw_rx_packet *)rxb->skb->data;
 		IPW_DEBUG_RX("Packet: type=%02X seq=%02X bits=%02X\n",
@@ -8424,8 +8428,8 @@
 			rxb->skb = NULL;
 		}
 
-		pci_unmap_single(priv->pci_dev, rxb->dma_addr,
-				 IPW_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+		dma_unmap_single(&priv->pci_dev->dev, rxb->dma_addr,
+				 IPW_RX_BUF_SIZE, DMA_FROM_DEVICE);
 		list_add_tail(&rxb->list, &priv->rxq->rx_used);
 
 		i = (i + 1) % RX_QUEUE_SIZE;
@@ -10224,11 +10228,10 @@
 			   txb->fragments[i]->len - hdr_len);
 
 		tfd->u.data.chunk_ptr[i] =
-		    cpu_to_le32(pci_map_single
-				(priv->pci_dev,
-				 txb->fragments[i]->data + hdr_len,
-				 txb->fragments[i]->len - hdr_len,
-				 PCI_DMA_TODEVICE));
+		    cpu_to_le32(dma_map_single(&priv->pci_dev->dev,
+					       txb->fragments[i]->data + hdr_len,
+					       txb->fragments[i]->len - hdr_len,
+					       DMA_TO_DEVICE));
 		tfd->u.data.chunk_len[i] =
 		    cpu_to_le16(txb->fragments[i]->len - hdr_len);
 	}
@@ -10258,10 +10261,10 @@
 			dev_kfree_skb_any(txb->fragments[i]);
 			txb->fragments[i] = skb;
 			tfd->u.data.chunk_ptr[i] =
-			    cpu_to_le32(pci_map_single
-					(priv->pci_dev, skb->data,
-					 remaining_bytes,
-					 PCI_DMA_TODEVICE));
+			    cpu_to_le32(dma_map_single(&priv->pci_dev->dev,
+						       skb->data,
+						       remaining_bytes,
+						       DMA_TO_DEVICE));
 
 			le32_add_cpu(&tfd->u.data.num_chunks, 1);
 		}
@@ -10680,7 +10683,7 @@
 	INIT_WORK(&priv->qos_activate, ipw_bg_qos_activate);
 #endif				/* CONFIG_IPW2200_QOS */
 
-	tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
+	tasklet_init(&priv->irq_tasklet,
 		     ipw_irq_tasklet, (unsigned long)priv);
 
 	return ret;
@@ -11411,9 +11414,14 @@
 	set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev);
 
 	/* With that information in place, we can now register the wiphy... */
-	if (wiphy_register(wdev->wiphy))
-		rc = -EIO;
+	rc = wiphy_register(wdev->wiphy);
+	if (rc)
+		goto out;
+
+	return 0;
 out:
+	kfree(priv->ieee->a_band.channels);
+	kfree(priv->ieee->bg_band.channels);
 	return rc;
 }
 
@@ -11631,9 +11639,9 @@
 
 	pci_set_master(pdev);
 
-	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+	err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
 	if (!err)
-		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+		err = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
 	if (err) {
 		printk(KERN_WARNING DRV_NAME ": No suitable DMA available.\n");
 		goto out_pci_disable_device;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/ipw2x00/libipw_rx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/ipw2x00/libipw_rx.c
@@ -870,8 +870,8 @@
 	switch (ieee->iw_mode) {
 	case IW_MODE_ADHOC:
 		/* our BSS and not from/to DS */
-		if (ether_addr_equal(hdr->addr3, ieee->bssid))
-		if ((fc & (IEEE80211_FCTL_TODS+IEEE80211_FCTL_FROMDS)) == 0) {
+		if (ether_addr_equal(hdr->addr3, ieee->bssid) &&
+		    ((fc & (IEEE80211_FCTL_TODS + IEEE80211_FCTL_FROMDS)) == 0)) {
 			/* promisc: get all */
 			if (ieee->dev->flags & IFF_PROMISC)
 				is_packet_for_us = 1;
@@ -885,8 +885,8 @@
 		break;
 	case IW_MODE_INFRA:
 		/* our BSS (== from our AP) and from DS */
-		if (ether_addr_equal(hdr->addr2, ieee->bssid))
-		if ((fc & (IEEE80211_FCTL_TODS+IEEE80211_FCTL_FROMDS)) == IEEE80211_FCTL_FROMDS) {
+		if (ether_addr_equal(hdr->addr2, ieee->bssid) &&
+		    ((fc & (IEEE80211_FCTL_TODS + IEEE80211_FCTL_FROMDS)) == IEEE80211_FCTL_FROMDS)) {
 			/* promisc: get all */
 			if (ieee->dev->flags & IFF_PROMISC)
 				is_packet_for_us = 1;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/ipw2x00/libipw_tx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/ipw2x00/libipw_tx.c
@@ -383,7 +383,7 @@
 
 		/* Each fragment may need to have room for encryption
 		 * pre/postfix */
-		if (host_encrypt)
+		if (host_encrypt && crypt && crypt->ops)
 			bytes_per_frag -= crypt->ops->extra_mpdu_prefix_len +
 			    crypt->ops->extra_mpdu_postfix_len;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/ipw2x00/libipw_wx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/ipw2x00/libipw_wx.c
@@ -633,8 +633,10 @@
 	}
 
 	if (ext->alg != IW_ENCODE_ALG_NONE) {
-		memcpy(sec.keys[idx], ext->key, ext->key_len);
-		sec.key_sizes[idx] = ext->key_len;
+		int key_len = clamp_val(ext->key_len, 0, SCM_KEY_LEN);
+
+		memcpy(sec.keys[idx], ext->key, key_len);
+		sec.key_sizes[idx] = key_len;
 		sec.flags |= (1 << idx);
 		if (ext->alg == IW_ENCODE_ALG_WEP) {
 			sec.encode_alg[idx] = SEC_ALG_WEP;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlegacy/3945-mac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlegacy/3945-mac.c
@@ -1376,8 +1376,9 @@
 }
 
 static void
-il3945_irq_tasklet(struct il_priv *il)
+il3945_irq_tasklet(unsigned long data)
 {
+	struct il_priv *il = (struct il_priv *)data;
 	u32 inta, handled = 0;
 	u32 inta_fh;
 	unsigned long flags;
@@ -2301,9 +2302,7 @@
 	il3945_hw_txq_ctx_free(il);
 exit:
 	memset(&il->card_alive, 0, sizeof(struct il_alive_resp));
-
-	if (il->beacon_skb)
-		dev_kfree_skb(il->beacon_skb);
+	dev_kfree_skb(il->beacon_skb);
 	il->beacon_skb = NULL;
 
 	/* clear out any free frames */
@@ -3383,10 +3382,12 @@
  *
  *****************************************************************************/
 
-static void
+static int
 il3945_setup_deferred_work(struct il_priv *il)
 {
 	il->workqueue = create_singlethread_workqueue(DRV_NAME);
+	if (!il->workqueue)
+		return -ENOMEM;
 
 	init_waitqueue_head(&il->wait_command_queue);
 
@@ -3403,8 +3404,10 @@
 	timer_setup(&il->watchdog, il_bg_watchdog, 0);
 
 	tasklet_init(&il->irq_tasklet,
-		     (void (*)(unsigned long))il3945_irq_tasklet,
+		     il3945_irq_tasklet,
 		     (unsigned long)il);
+
+	return 0;
 }
 
 static void
@@ -3726,7 +3729,10 @@
 	}
 
 	il_set_rxon_channel(il, &il->bands[NL80211_BAND_2GHZ].channels[5]);
-	il3945_setup_deferred_work(il);
+	err = il3945_setup_deferred_work(il);
+	if (err)
+		goto out_remove_sysfs;
+
 	il3945_setup_handlers(il);
 	il_power_initialize(il);
 
@@ -3738,7 +3744,7 @@
 
 	err = il3945_setup_mac(il);
 	if (err)
-		goto out_remove_sysfs;
+		goto out_destroy_workqueue;
 
 	il_dbgfs_register(il, DRV_NAME);
 
@@ -3747,9 +3753,10 @@
 
 	return 0;
 
-out_remove_sysfs:
+out_destroy_workqueue:
 	destroy_workqueue(il->workqueue);
 	il->workqueue = NULL;
+out_remove_sysfs:
 	sysfs_remove_group(&pdev->dev.kobj, &il3945_attribute_group);
 out_release_irq:
 	free_irq(il->pci_dev->irq, il);
@@ -3846,9 +3853,7 @@
 	il_free_channel_map(il);
 	il_free_geos(il);
 	kfree(il->scan_cmd);
-	if (il->beacon_skb)
-		dev_kfree_skb(il->beacon_skb);
-
+	dev_kfree_skb(il->beacon_skb);
 	ieee80211_free_hw(il->hw);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlegacy/3945-rs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlegacy/3945-rs.c
@@ -374,7 +374,7 @@
 }
 
 static void *
-il3945_rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
+il3945_rs_alloc(struct ieee80211_hw *hw)
 {
 	return hw->priv;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlegacy/3945.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlegacy/3945.c
@@ -2100,7 +2100,7 @@
 
 		/* set tx power value for all OFDM rates */
 		for (rate_idx = 0; rate_idx < IL_OFDM_RATES; rate_idx++) {
-			s32 uninitialized_var(power_idx);
+			s32 power_idx;
 			int rc;
 
 			/* use channel group's clip-power table,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlegacy/4965-mac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlegacy/4965-mac.c
@@ -2265,7 +2265,7 @@
 	if (tid_data->tfds_in_queue == 0) {
 		D_HT("HW queue is empty\n");
 		tid_data->agg.state = IL_AGG_ON;
-		ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+		ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
 	} else {
 		D_HT("HW queue is NOT empty: %d packets in HW queue\n",
 		     tid_data->tfds_in_queue);
@@ -2768,7 +2768,7 @@
 	struct ieee80211_tx_info *info;
 	struct il4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
 	u32 status = le32_to_cpu(tx_resp->u.status);
-	int uninitialized_var(tid);
+	int tid;
 	int sta_id;
 	int freed;
 	u8 *qc = NULL;
@@ -4344,8 +4344,9 @@
 }
 
 static void
-il4965_irq_tasklet(struct il_priv *il)
+il4965_irq_tasklet(unsigned long data)
 {
+	struct il_priv *il = (struct il_priv *)data;
 	u32 inta, handled = 0;
 	u32 inta_fh;
 	unsigned long flags;
@@ -6216,10 +6217,12 @@
 	mutex_unlock(&il->mutex);
 }
 
-static void
+static int
 il4965_setup_deferred_work(struct il_priv *il)
 {
 	il->workqueue = create_singlethread_workqueue(DRV_NAME);
+	if (!il->workqueue)
+		return -ENOMEM;
 
 	init_waitqueue_head(&il->wait_command_queue);
 
@@ -6238,8 +6241,10 @@
 	timer_setup(&il->watchdog, il_bg_watchdog, 0);
 
 	tasklet_init(&il->irq_tasklet,
-		     (void (*)(unsigned long))il4965_irq_tasklet,
+		     il4965_irq_tasklet,
 		     (unsigned long)il);
+
+	return 0;
 }
 
 static void
@@ -6629,7 +6634,10 @@
 		goto out_disable_msi;
 	}
 
-	il4965_setup_deferred_work(il);
+	err = il4965_setup_deferred_work(il);
+	if (err)
+		goto out_free_irq;
+
 	il4965_setup_handlers(il);
 
 	/*********************************************
@@ -6667,6 +6675,7 @@
 out_destroy_workqueue:
 	destroy_workqueue(il->workqueue);
 	il->workqueue = NULL;
+out_free_irq:
 	free_irq(il->pci_dev->irq, il);
 out_disable_msi:
 	pci_disable_msi(il->pci_dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlegacy/4965-rs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlegacy/4965-rs.c
@@ -2403,7 +2403,7 @@
 		/* Repeat initial/next rate.
 		 * For legacy IL_NUMBER_TRY == 1, this loop will not execute.
 		 * For HT IL_HT_NUMBER_TRY == 3, this executes twice. */
-		while (repeat_rate > 0 && idx < LINK_QUAL_MAX_RETRY_NUM) {
+		while (repeat_rate > 0 && idx < (LINK_QUAL_MAX_RETRY_NUM - 1)) {
 			if (is_legacy(tbl_type.lq_type)) {
 				if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE)
 					ant_toggle_cnt++;
@@ -2474,7 +2474,7 @@
 }
 
 static void *
-il4965_rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
+il4965_rs_alloc(struct ieee80211_hw *hw)
 {
 	return hw->priv;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlegacy/common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlegacy/common.c
@@ -699,7 +699,7 @@
 	u32 gp = _il_rd(il, CSR_EEPROM_GP);
 	int sz;
 	int ret;
-	u16 addr;
+	int addr;
 
 	/* allocate eeprom */
 	sz = il->cfg->eeprom_size;
@@ -4286,8 +4286,8 @@
 	 *    power savings, even without L1.
 	 */
 	if (il->cfg->set_l0s) {
-		pcie_capability_read_word(il->pci_dev, PCI_EXP_LNKCTL, &lctl);
-		if (lctl & PCI_EXP_LNKCTL_ASPM_L1) {
+		ret = pcie_capability_read_word(il->pci_dev, PCI_EXP_LNKCTL, &lctl);
+		if (!ret && (lctl & PCI_EXP_LNKCTL_ASPM_L1)) {
 			/* L1-ASPM enabled; disable(!) L0S  */
 			il_set_bit(il, CSR_GIO_REG,
 				   CSR_GIO_REG_VAL_L0S_ENABLED);
@@ -4969,6 +4969,8 @@
 	 */
 	pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
 
+	_il_wr(il, CSR_INT, 0xffffffff);
+	_il_wr(il, CSR_FH_INT_STATUS, 0xffffffff);
 	il_enable_interrupts(il);
 
 	if (!(_il_rd(il, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
@@ -5182,8 +5184,7 @@
 	memset(&il->current_ht_config, 0, sizeof(struct il_ht_config));
 
 	/* new association get rid of ibss beacon skb */
-	if (il->beacon_skb)
-		dev_kfree_skb(il->beacon_skb);
+	dev_consume_skb_irq(il->beacon_skb);
 	il->beacon_skb = NULL;
 	il->timestamp = 0;
 
@@ -5302,10 +5303,7 @@
 	}
 
 	spin_lock_irqsave(&il->lock, flags);
-
-	if (il->beacon_skb)
-		dev_kfree_skb(il->beacon_skb);
-
+	dev_consume_skb_irq(il->beacon_skb);
 	il->beacon_skb = skb;
 
 	timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/cfg/22000.c
@@ -137,7 +137,7 @@
 	.pcie_l1_allowed = true,
 };
 
-static const struct iwl_base_params iwl_22560_base_params = {
+static const struct iwl_base_params iwl_ax210_base_params = {
 	.eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
 	.num_of_queues = 512,
 	.max_tfd_queue_size = 65536,
@@ -195,40 +195,26 @@
 	.trans.csr = &iwl_csr_v1,					\
 	.gp2_reg_addr = 0xa02c68
 
-#define IWL_DEVICE_22560						\
-	IWL_DEVICE_22000_COMMON,					\
-	.trans.device_family = IWL_DEVICE_FAMILY_22560,			\
-	.trans.base_params = &iwl_22560_base_params,			\
-	.trans.csr = &iwl_csr_v2
-
 #define IWL_DEVICE_AX210						\
 	IWL_DEVICE_22000_COMMON,					\
 	.trans.umac_prph_offset = 0x300000,				\
 	.trans.device_family = IWL_DEVICE_FAMILY_AX210,			\
-	.trans.base_params = &iwl_22560_base_params,			\
+	.trans.base_params = &iwl_ax210_base_params,			\
 	.trans.csr = &iwl_csr_v1,					\
 	.min_txq_size = 128,						\
 	.gp2_reg_addr = 0xd02c68,					\
 	.min_256_ba_txq_size = 512
 
-const struct iwl_cfg iwl22000_2ac_cfg_hr = {
-	.name = "Intel(R) Dual Band Wireless AC 22000",
-	.fw_name_pre = IWL_22000_HR_FW_PRE,
-	IWL_DEVICE_22500,
-};
-
-const struct iwl_cfg iwl22000_2ac_cfg_hr_cdb = {
-	.name = "Intel(R) Dual Band Wireless AC 22000",
-	.fw_name_pre = IWL_22000_HR_CDB_FW_PRE,
-	IWL_DEVICE_22500,
-	.cdb = true,
-};
-
-const struct iwl_cfg iwl22000_2ac_cfg_jf = {
-	.name = "Intel(R) Dual Band Wireless AC 22000",
-	.fw_name_pre = IWL_22000_JF_FW_PRE,
-	IWL_DEVICE_22500,
-};
+/*
+ * If the device doesn't support HE, no need to have that many buffers.
+ * 22000 devices can split multiple frames into a single RB, so fewer are
+ * needed; AX210 cannot (but use smaller RBs by default) - these sizes
+ * were picked according to 8 MSDUs inside 256 A-MSDUs in an A-MPDU, with
+ * additional overhead to account for processing time.
+ */
+#define IWL_NUM_RBDS_NON_HE		512
+#define IWL_NUM_RBDS_22000_HE		2048
+#define IWL_NUM_RBDS_AX210_HE		4096
 
 const struct iwl_cfg iwl_ax101_cfg_qu_hr = {
 	.name = "Intel(R) Wi-Fi 6 AX101",
@@ -241,6 +227,7 @@
 	 */
 	.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
 	.tx_with_siso_diversity = true,
+	.num_rbds = IWL_NUM_RBDS_22000_HE,
 };
 
 const struct iwl_cfg iwl_ax201_cfg_qu_hr = {
@@ -253,6 +240,7 @@
 	 * HT size; mac80211 would otherwise pick the HE max (256) by default.
 	 */
 	.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
+	.num_rbds = IWL_NUM_RBDS_22000_HE,
 };
 
 const struct iwl_cfg iwl_ax101_cfg_qu_c0_hr_b0 = {
@@ -265,6 +253,7 @@
 	 * HT size; mac80211 would otherwise pick the HE max (256) by default.
 	 */
 	.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
+	.num_rbds = IWL_NUM_RBDS_22000_HE,
 };
 
 const struct iwl_cfg iwl_ax201_cfg_qu_c0_hr_b0 = {
@@ -277,6 +266,7 @@
 	 * HT size; mac80211 would otherwise pick the HE max (256) by default.
 	 */
 	.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
+	.num_rbds = IWL_NUM_RBDS_22000_HE,
 };
 
 const struct iwl_cfg iwl_ax101_cfg_quz_hr = {
@@ -289,42 +279,46 @@
 	 * HT size; mac80211 would otherwise pick the HE max (256) by default.
 	 */
 	.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
+	.num_rbds = IWL_NUM_RBDS_22000_HE,
 };
 
 const struct iwl_cfg iwl_ax201_cfg_quz_hr = {
-		.name = "Intel(R) Wi-Fi 6 AX201 160MHz",
-		.fw_name_pre = IWL_QUZ_A_HR_B_FW_PRE,
-		IWL_DEVICE_22500,
-		/*
+	.name = "Intel(R) Wi-Fi 6 AX201 160MHz",
+	.fw_name_pre = IWL_QUZ_A_HR_B_FW_PRE,
+	IWL_DEVICE_22500,
+	/*
          * This device doesn't support receiving BlockAck with a large bitmap
          * so we need to restrict the size of transmitted aggregation to the
          * HT size; mac80211 would otherwise pick the HE max (256) by default.
          */
-		.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
+	.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
+	.num_rbds = IWL_NUM_RBDS_22000_HE,
 };
 
 const struct iwl_cfg iwl_ax1650s_cfg_quz_hr = {
-		.name = "Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201D2W)",
-		.fw_name_pre = IWL_QUZ_A_HR_B_FW_PRE,
-		IWL_DEVICE_22500,
-		/*
+	.name = "Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201D2W)",
+	.fw_name_pre = IWL_QUZ_A_HR_B_FW_PRE,
+	IWL_DEVICE_22500,
+	/*
          * This device doesn't support receiving BlockAck with a large bitmap
          * so we need to restrict the size of transmitted aggregation to the
          * HT size; mac80211 would otherwise pick the HE max (256) by default.
          */
-		.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
+	.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
+	.num_rbds = IWL_NUM_RBDS_22000_HE,
 };
 
 const struct iwl_cfg iwl_ax1650i_cfg_quz_hr = {
-		.name = "Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201NGW)",
-		.fw_name_pre = IWL_QUZ_A_HR_B_FW_PRE,
-		IWL_DEVICE_22500,
-		/*
+	.name = "Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201NGW)",
+	.fw_name_pre = IWL_QUZ_A_HR_B_FW_PRE,
+	IWL_DEVICE_22500,
+	/*
          * This device doesn't support receiving BlockAck with a large bitmap
          * so we need to restrict the size of transmitted aggregation to the
          * HT size; mac80211 would otherwise pick the HE max (256) by default.
          */
-		.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
+	.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
+	.num_rbds = IWL_NUM_RBDS_22000_HE,
 };
 
 const struct iwl_cfg iwl_ax200_cfg_cc = {
@@ -338,6 +332,7 @@
 	 */
 	.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
 	.trans.bisr_workaround = 1,
+	.num_rbds = IWL_NUM_RBDS_22000_HE,
 };
 
 const struct iwl_cfg killer1650x_2ax_cfg = {
@@ -351,6 +346,7 @@
 	 */
 	.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
 	.trans.bisr_workaround = 1,
+	.num_rbds = IWL_NUM_RBDS_22000_HE,
 };
 
 const struct iwl_cfg killer1650w_2ax_cfg = {
@@ -364,6 +360,7 @@
 	 */
 	.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
 	.trans.bisr_workaround = 1,
+	.num_rbds = IWL_NUM_RBDS_22000_HE,
 };
 
 /*
@@ -375,48 +372,56 @@
 	.name = "Intel(R) Wireless-AC 9461",
 	.fw_name_pre = IWL_QU_B_JF_B_FW_PRE,
 	IWL_DEVICE_22500,
+	.num_rbds = IWL_NUM_RBDS_NON_HE,
 };
 
 const struct iwl_cfg iwl9462_2ac_cfg_qu_b0_jf_b0 = {
 	.name = "Intel(R) Wireless-AC 9462",
 	.fw_name_pre = IWL_QU_B_JF_B_FW_PRE,
 	IWL_DEVICE_22500,
+	.num_rbds = IWL_NUM_RBDS_NON_HE,
 };
 
 const struct iwl_cfg iwl9560_2ac_cfg_qu_b0_jf_b0 = {
 	.name = "Intel(R) Wireless-AC 9560",
 	.fw_name_pre = IWL_QU_B_JF_B_FW_PRE,
 	IWL_DEVICE_22500,
+	.num_rbds = IWL_NUM_RBDS_NON_HE,
 };
 
 const struct iwl_cfg iwl9560_2ac_160_cfg_qu_b0_jf_b0 = {
 	.name = "Intel(R) Wireless-AC 9560 160MHz",
 	.fw_name_pre = IWL_QU_B_JF_B_FW_PRE,
 	IWL_DEVICE_22500,
+	.num_rbds = IWL_NUM_RBDS_NON_HE,
 };
 
 const struct iwl_cfg iwl9461_2ac_cfg_qu_c0_jf_b0 = {
 	.name = "Intel(R) Wireless-AC 9461",
 	.fw_name_pre = IWL_QU_C_JF_B_FW_PRE,
 	IWL_DEVICE_22500,
+	.num_rbds = IWL_NUM_RBDS_NON_HE,
 };
 
 const struct iwl_cfg iwl9462_2ac_cfg_qu_c0_jf_b0 = {
 	.name = "Intel(R) Wireless-AC 9462",
 	.fw_name_pre = IWL_QU_C_JF_B_FW_PRE,
 	IWL_DEVICE_22500,
+	.num_rbds = IWL_NUM_RBDS_NON_HE,
 };
 
 const struct iwl_cfg iwl9560_2ac_cfg_qu_c0_jf_b0 = {
 	.name = "Intel(R) Wireless-AC 9560",
 	.fw_name_pre = IWL_QU_C_JF_B_FW_PRE,
 	IWL_DEVICE_22500,
+	.num_rbds = IWL_NUM_RBDS_NON_HE,
 };
 
 const struct iwl_cfg iwl9560_2ac_160_cfg_qu_c0_jf_b0 = {
 	.name = "Intel(R) Wireless-AC 9560 160MHz",
 	.fw_name_pre = IWL_QU_C_JF_B_FW_PRE,
 	IWL_DEVICE_22500,
+	.num_rbds = IWL_NUM_RBDS_NON_HE,
 };
 
 const struct iwl_cfg iwl9560_2ac_cfg_qnj_jf_b0 = {
@@ -429,6 +434,7 @@
 	 * HT size; mac80211 would otherwise pick the HE max (256) by default.
 	 */
 	.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
+	.num_rbds = IWL_NUM_RBDS_NON_HE,
 };
 
 const struct iwl_cfg iwl9560_2ac_cfg_quz_a0_jf_b0_soc = {
@@ -443,6 +449,7 @@
 	.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
 	.integrated = true,
 	.soc_latency = 5000,
+	.num_rbds = IWL_NUM_RBDS_NON_HE,
 };
 
 const struct iwl_cfg iwl9560_2ac_160_cfg_quz_a0_jf_b0_soc = {
@@ -457,6 +464,7 @@
 	.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
 	.integrated = true,
 	.soc_latency = 5000,
+	.num_rbds = IWL_NUM_RBDS_NON_HE,
 };
 
 const struct iwl_cfg iwl9461_2ac_cfg_quz_a0_jf_b0_soc = {
@@ -471,6 +479,7 @@
 	.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
 	.integrated = true,
 	.soc_latency = 5000,
+	.num_rbds = IWL_NUM_RBDS_NON_HE,
 };
 
 const struct iwl_cfg iwl9462_2ac_cfg_quz_a0_jf_b0_soc = {
@@ -485,6 +494,7 @@
 	.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
 	.integrated = true,
 	.soc_latency = 5000,
+	.num_rbds = IWL_NUM_RBDS_NON_HE,
 };
 
 const struct iwl_cfg iwl9560_killer_s_2ac_cfg_quz_a0_jf_b0_soc = {
@@ -499,6 +509,7 @@
 	.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
 	.integrated = true,
 	.soc_latency = 5000,
+	.num_rbds = IWL_NUM_RBDS_NON_HE,
 };
 
 const struct iwl_cfg iwl9560_killer_i_2ac_cfg_quz_a0_jf_b0_soc = {
@@ -513,18 +524,21 @@
 	.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
 	.integrated = true,
 	.soc_latency = 5000,
+	.num_rbds = IWL_NUM_RBDS_NON_HE,
 };
 
 const struct iwl_cfg killer1550i_2ac_cfg_qu_b0_jf_b0 = {
 	.name = "Killer (R) Wireless-AC 1550i Wireless Network Adapter (9560NGW)",
 	.fw_name_pre = IWL_QU_B_JF_B_FW_PRE,
 	IWL_DEVICE_22500,
+	.num_rbds = IWL_NUM_RBDS_NON_HE,
 };
 
 const struct iwl_cfg killer1550s_2ac_cfg_qu_b0_jf_b0 = {
 	.name = "Killer (R) Wireless-AC 1550s Wireless Network Adapter (9560NGW)",
 	.fw_name_pre = IWL_QU_B_JF_B_FW_PRE,
 	IWL_DEVICE_22500,
+	.num_rbds = IWL_NUM_RBDS_NON_HE,
 };
 
 const struct iwl_cfg killer1650s_2ax_cfg_qu_b0_hr_b0 = {
@@ -537,6 +551,7 @@
 	 * HT size; mac80211 would otherwise pick the HE max (256) by default.
 	 */
 	.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
+	.num_rbds = IWL_NUM_RBDS_22000_HE,
 };
 
 const struct iwl_cfg killer1650i_2ax_cfg_qu_b0_hr_b0 = {
@@ -549,6 +564,7 @@
 	 * HT size; mac80211 would otherwise pick the HE max (256) by default.
 	 */
 	.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
+	.num_rbds = IWL_NUM_RBDS_22000_HE,
 };
 
 const struct iwl_cfg killer1650s_2ax_cfg_qu_c0_hr_b0 = {
@@ -561,6 +577,7 @@
 	 * HT size; mac80211 would otherwise pick the HE max (256) by default.
 	 */
 	.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
+	.num_rbds = IWL_NUM_RBDS_22000_HE,
 };
 
 const struct iwl_cfg killer1650i_2ax_cfg_qu_c0_hr_b0 = {
@@ -573,6 +590,7 @@
 	 * HT size; mac80211 would otherwise pick the HE max (256) by default.
 	 */
 	.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
+	.num_rbds = IWL_NUM_RBDS_22000_HE,
 };
 
 const struct iwl_cfg iwl22000_2ax_cfg_jf = {
@@ -585,6 +603,7 @@
 	 * HT size; mac80211 would otherwise pick the HE max (256) by default.
 	 */
 	.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
+	.num_rbds = IWL_NUM_RBDS_22000_HE,
 };
 
 const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0_f0 = {
@@ -597,6 +616,7 @@
 	 * HT size; mac80211 would otherwise pick the HE max (256) by default.
 	 */
 	.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
+	.num_rbds = IWL_NUM_RBDS_22000_HE,
 };
 
 const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_b0 = {
@@ -609,6 +629,7 @@
 	 * HT size; mac80211 would otherwise pick the HE max (256) by default.
 	 */
 	.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
+	.num_rbds = IWL_NUM_RBDS_22000_HE,
 };
 
 const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_a0 = {
@@ -621,18 +642,21 @@
 	 * HT size; mac80211 would otherwise pick the HE max (256) by default.
 	 */
 	.max_tx_agg_size = IEEE80211_MAX_AMPDU_BUF_HT,
+	.num_rbds = IWL_NUM_RBDS_22000_HE,
 };
 
 const struct iwl_cfg iwlax210_2ax_cfg_so_jf_a0 = {
 	.name = "Intel(R) Wireless-AC 9560 160MHz",
 	.fw_name_pre = IWL_22000_SO_A_JF_B_FW_PRE,
 	IWL_DEVICE_AX210,
+	.num_rbds = IWL_NUM_RBDS_NON_HE,
 };
 
 const struct iwl_cfg iwlax210_2ax_cfg_so_hr_a0 = {
 	.name = "Intel(R) Wi-Fi 7 AX210 160MHz",
 	.fw_name_pre = IWL_22000_SO_A_HR_B_FW_PRE,
 	IWL_DEVICE_AX210,
+	.num_rbds = IWL_NUM_RBDS_AX210_HE,
 };
 
 const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0 = {
@@ -640,6 +664,7 @@
 	.fw_name_pre = IWL_22000_SO_A_GF_A_FW_PRE,
 	.uhb_supported = true,
 	IWL_DEVICE_AX210,
+	.num_rbds = IWL_NUM_RBDS_AX210_HE,
 };
 
 const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0 = {
@@ -647,12 +672,14 @@
 	.fw_name_pre = IWL_22000_TY_A_GF_A_FW_PRE,
 	.uhb_supported = true,
 	IWL_DEVICE_AX210,
+	.num_rbds = IWL_NUM_RBDS_AX210_HE,
 };
 
 const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0 = {
 	.name = "Intel(R) Wi-Fi 7 AX411 160MHz",
 	.fw_name_pre = IWL_22000_SO_A_GF4_A_FW_PRE,
 	IWL_DEVICE_AX210,
+	.num_rbds = IWL_NUM_RBDS_AX210_HE,
 };
 
 MODULE_FIRMWARE(IWL_22000_HR_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/cfg/9000.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/cfg/9000.c
@@ -137,6 +137,7 @@
 	.thermal_params = &iwl9000_tt_params,				\
 	.apmg_not_supported = true,					\
 	.trans.mq_rx_supported = true,					\
+	.num_rbds = 512,						\
 	.vht_mu_mimo_supported = true,					\
 	.mac_addr_from_csr = true,					\
 	.trans.rf_id = true,						\
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/dvm/led.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/dvm/led.c
@@ -171,6 +171,9 @@
 
 	priv->led.name = kasprintf(GFP_KERNEL, "%s-led",
 				   wiphy_name(priv->hw->wiphy));
+	if (!priv->led.name)
+		return;
+
 	priv->led.brightness_set = iwl_led_brightness_set;
 	priv->led.blink_set = iwl_led_blink_set;
 	priv->led.max_brightness = 1;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
@@ -303,7 +303,7 @@
 
 	priv->is_open = 1;
 	IWL_DEBUG_MAC80211(priv, "leave\n");
-	return 0;
+	return ret;
 }
 
 static void iwlagn_mac_stop(struct ieee80211_hw *hw)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/dvm/rs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/dvm/rs.c
@@ -3019,7 +3019,7 @@
 			cpu_to_le16(priv->lib->bt_params->agg_time_limit);
 }
 
-static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
+static void *rs_alloc(struct ieee80211_hw *hw)
 {
 	return hw->priv;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/dvm/sta.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/dvm/sta.c
@@ -1086,6 +1086,7 @@
 {
 	__le16 key_flags;
 	struct iwl_addsta_cmd sta_cmd;
+	size_t to_copy;
 	int i;
 
 	spin_lock_bh(&priv->sta_lock);
@@ -1105,7 +1106,9 @@
 		sta_cmd.key.tkip_rx_tsc_byte2 = tkip_iv32;
 		for (i = 0; i < 5; i++)
 			sta_cmd.key.tkip_rx_ttak[i] = cpu_to_le16(tkip_p1k[i]);
-		memcpy(sta_cmd.key.key, keyconf->key, keyconf->keylen);
+		/* keyconf may contain MIC rx/tx keys which iwl does not use */
+		to_copy = min_t(size_t, sizeof(sta_cmd.key.key), keyconf->keylen);
+		memcpy(sta_cmd.key.key, keyconf->key, to_copy);
 		break;
 	case WLAN_CIPHER_SUITE_WEP104:
 		key_flags |= STA_KEY_FLG_KEY_SIZE_MSK;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/dvm/tx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/dvm/tx.c
@@ -267,7 +267,7 @@
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	struct iwl_station_priv *sta_priv = NULL;
 	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-	struct iwl_device_cmd *dev_cmd;
+	struct iwl_device_tx_cmd *dev_cmd;
 	struct iwl_tx_cmd *tx_cmd;
 	__le16 fc;
 	u8 hdr_len;
@@ -348,7 +348,6 @@
 	if (unlikely(!dev_cmd))
 		goto drop_unlock_priv;
 
-	memset(dev_cmd, 0, sizeof(*dev_cmd));
 	dev_cmd->hdr.cmd = REPLY_TX;
 	tx_cmd = (struct iwl_tx_cmd *) dev_cmd->payload;
 
@@ -621,7 +620,7 @@
 		IWL_DEBUG_TX_QUEUES(priv, "Can proceed: ssn = next_recl = %d\n",
 				    tid_data->agg.ssn);
 		tid_data->agg.state = IWL_AGG_STARTING;
-		ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+		ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
 	} else {
 		IWL_DEBUG_TX_QUEUES(priv, "Can't proceed: ssn %d, "
 				    "next_reclaimed = %d\n",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/fw/api/tx.h
@@ -7,7 +7,7 @@
  *
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
@@ -29,7 +29,7 @@
  *
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -323,7 +323,7 @@
 } __packed; /* TX_CMD_API_S_VER_7 */
 
 /**
- * struct iwl_tx_cmd_gen3 - TX command struct to FW for 22560 devices
+ * struct iwl_tx_cmd_gen3 - TX command struct to FW for AX210+ devices
  * ( TX_CMD = 0x1c )
  * @len: in bytes of the payload, see below for details
  * @flags: combination of &enum iwl_tx_cmd_flags
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/fw/api/txq.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/fw/api/txq.h
@@ -8,7 +8,7 @@
  * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2019 Intel Corporation
+ * Copyright(c) 2019 - 2020 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
@@ -31,7 +31,7 @@
  * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2019 Intel Corporation
+ * Copyright(c) 2019 - 2020 Intel Corporation
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -99,7 +99,7 @@
 	IWL_MVM_DQA_MAX_MGMT_QUEUE = 8,
 	IWL_MVM_DQA_AP_PROBE_RESP_QUEUE = 9,
 	IWL_MVM_DQA_MIN_DATA_QUEUE = 10,
-	IWL_MVM_DQA_MAX_DATA_QUEUE = 31,
+	IWL_MVM_DQA_MAX_DATA_QUEUE = 30,
 };
 
 enum iwl_mvm_tx_fifo {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
@@ -8,7 +8,7 @@
  * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 - 2019 Intel Corporation
+ * Copyright(c) 2018 - 2020 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
@@ -31,7 +31,7 @@
  * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 - 2019 Intel Corporation
+ * Copyright(c) 2018 - 2020 Intel Corporation
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -619,41 +619,71 @@
 }
 
 /*
- * alloc_sgtable - allocates scallerlist table in the given size,
- * fills it with pages and returns it
+ * alloc_sgtable - allocates (chained) scatterlist in the given size,
+ *	fills it with pages and returns it
  * @size: the size (in bytes) of the table
-*/
-static struct scatterlist *alloc_sgtable(int size)
+ */
+static struct scatterlist *alloc_sgtable(ssize_t size)
 {
-	int alloc_size, nents, i;
-	struct page *new_page;
-	struct scatterlist *iter;
-	struct scatterlist *table;
+	struct scatterlist *result = NULL, *prev;
+	int nents, i, n_prev;
 
 	nents = DIV_ROUND_UP(size, PAGE_SIZE);
-	table = kcalloc(nents, sizeof(*table), GFP_KERNEL);
-	if (!table)
-		return NULL;
-	sg_init_table(table, nents);
-	iter = table;
-	for_each_sg(table, iter, sg_nents(table), i) {
-		new_page = alloc_page(GFP_KERNEL);
-		if (!new_page) {
-			/* release all previous allocated pages in the table */
-			iter = table;
-			for_each_sg(table, iter, sg_nents(table), i) {
-				new_page = sg_page(iter);
-				if (new_page)
-					__free_page(new_page);
-			}
-			kfree(table);
+
+#define N_ENTRIES_PER_PAGE (PAGE_SIZE / sizeof(*result))
+	/*
+	 * We need an additional entry for table chaining,
+	 * this ensures the loop can finish i.e. we can
+	 * fit at least two entries per page (obviously,
+	 * many more really fit.)
+	 */
+	BUILD_BUG_ON(N_ENTRIES_PER_PAGE < 2);
+
+	while (nents > 0) {
+		struct scatterlist *new, *iter;
+		int n_fill, n_alloc;
+
+		if (nents <= N_ENTRIES_PER_PAGE) {
+			/* last needed table */
+			n_fill = nents;
+			n_alloc = nents;
+			nents = 0;
+		} else {
+			/* fill a page with entries */
+			n_alloc = N_ENTRIES_PER_PAGE;
+			/* reserve one for chaining */
+			n_fill = n_alloc - 1;
+			nents -= n_fill;
+		}
+
+		new = kcalloc(n_alloc, sizeof(*new), GFP_KERNEL);
+		if (!new) {
+			if (result)
+				_devcd_free_sgtable(result);
 			return NULL;
 		}
-		alloc_size = min_t(int, size, PAGE_SIZE);
-		size -= PAGE_SIZE;
-		sg_set_page(iter, new_page, alloc_size, 0);
+		sg_init_table(new, n_alloc);
+
+		if (!result)
+			result = new;
+		else
+			sg_chain(prev, n_prev, new);
+		prev = new;
+		n_prev = n_alloc;
+
+		for_each_sg(new, iter, n_fill, i) {
+			struct page *new_page = alloc_page(GFP_KERNEL);
+
+			if (!new_page) {
+				_devcd_free_sgtable(result);
+				return NULL;
+			}
+
+			sg_set_page(iter, new_page, PAGE_SIZE, 0);
+		}
 	}
-	return table;
+
+	return result;
 }
 
 static void iwl_fw_get_prph_len(struct iwl_fw_runtime *fwrt,
@@ -1373,11 +1403,7 @@
 		goto out;
 	}
 
-	/*
-	 * region register have absolute value so apply rxf offset after
-	 * reading the registers
-	 */
-	offs += rxf_data.offset;
+	offs = rxf_data.offset;
 
 	/* Lock fence */
 	iwl_write_prph_no_grab(fwrt->trans, RXF_SET_FENCE_MODE + offs, 0x1);
@@ -2315,10 +2341,7 @@
 		goto out;
 	}
 
-	if (iwl_fw_dbg_stop_restart_recording(fwrt, &params, true)) {
-		IWL_ERR(fwrt, "Failed to stop DBGC recording, aborting dump\n");
-		goto out;
-	}
+	iwl_fw_dbg_stop_restart_recording(fwrt, &params, true);
 
 	IWL_DEBUG_FW_INFO(fwrt, "WRT: Data collection start\n");
 	if (iwl_trans_dbg_ini_valid(fwrt->trans))
@@ -2484,19 +2507,14 @@
 	return 0;
 }
 
-int iwl_fw_dbg_stop_restart_recording(struct iwl_fw_runtime *fwrt,
-				      struct iwl_fw_dbg_params *params,
-				      bool stop)
+void iwl_fw_dbg_stop_restart_recording(struct iwl_fw_runtime *fwrt,
+				       struct iwl_fw_dbg_params *params,
+				       bool stop)
 {
 	int ret = 0;
 
-	/* if the FW crashed or not debug monitor cfg was given, there is
-	 * no point in changing the recording state
-	 */
-	if (test_bit(STATUS_FW_ERROR, &fwrt->trans->status) ||
-	    (!fwrt->trans->dbg.dest_tlv &&
-	     fwrt->trans->dbg.ini_dest == IWL_FW_INI_LOCATION_INVALID))
-		return 0;
+	if (test_bit(STATUS_FW_ERROR, &fwrt->trans->status))
+		return;
 
 	if (fw_has_capa(&fwrt->fw->ucode_capa,
 			IWL_UCODE_TLV_CAPA_DBG_SUSPEND_RESUME_CMD_SUPP))
@@ -2513,7 +2531,5 @@
 			iwl_fw_set_dbg_rec_on(fwrt);
 	}
 #endif
-
-	return ret;
 }
 IWL_EXPORT_SYMBOL(iwl_fw_dbg_stop_restart_recording);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/fw/dbg.h
@@ -263,9 +263,9 @@
 	_iwl_fw_dbg_trigger_simple_stop((fwrt), (wdev),		\
 					iwl_fw_dbg_get_trigger((fwrt)->fw,\
 							       (trig)))
-int iwl_fw_dbg_stop_restart_recording(struct iwl_fw_runtime *fwrt,
-				      struct iwl_fw_dbg_params *params,
-				      bool stop);
+void iwl_fw_dbg_stop_restart_recording(struct iwl_fw_runtime *fwrt,
+				       struct iwl_fw_dbg_params *params,
+				       bool stop);
 
 #ifdef CONFIG_IWLWIFI_DEBUGFS
 static inline void iwl_fw_set_dbg_rec_on(struct iwl_fw_runtime *fwrt)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h
@@ -332,9 +332,9 @@
 struct iwl_fw_ini_error_dump_range {
 	__le32 range_data_size;
 	union {
-		__le32 internal_base_addr;
-		__le64 dram_base_addr;
-		__le32 page_num;
+		__le32 internal_base_addr __packed;
+		__le64 dram_base_addr __packed;
+		__le32 page_num __packed;
 		struct iwl_fw_ini_fifo_hdr fifo_hdr;
 	};
 	__le32 data[];
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/iwl-config.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/iwl-config.h
@@ -88,7 +88,6 @@
 	IWL_DEVICE_FAMILY_8000,
 	IWL_DEVICE_FAMILY_9000,
 	IWL_DEVICE_FAMILY_22000,
-	IWL_DEVICE_FAMILY_22560,
 	IWL_DEVICE_FAMILY_AX210,
 };
 
@@ -411,6 +410,8 @@
  * @uhb_supported: ultra high band channels supported
  * @min_256_ba_txq_size: minimum number of slots required in a TX queue which
  *	supports 256 BA aggregation
+ * @num_rbds: number of receive buffer descriptors to use
+ *	(only used for multi-queue capable devices)
  *
  * We enable the driver to be backward compatible wrt. hardware features.
  * API differences in uCode shouldn't be handled here but through TLVs
@@ -466,6 +467,7 @@
 	u8 max_vht_ampdu_exponent;
 	u8 ucode_api_max;
 	u8 ucode_api_min;
+	u16 num_rbds;
 	u32 min_umac_error_event_table;
 	u32 extra_phy_cfg_flags;
 	u32 d3_debug_data_base_addr;
@@ -578,9 +580,6 @@
 extern const struct iwl_cfg iwl9560_2ac_160_cfg_shared_clk;
 extern const struct iwl_cfg iwl9560_killer_2ac_cfg_shared_clk;
 extern const struct iwl_cfg iwl9560_killer_s_2ac_cfg_shared_clk;
-extern const struct iwl_cfg iwl22000_2ac_cfg_hr;
-extern const struct iwl_cfg iwl22000_2ac_cfg_hr_cdb;
-extern const struct iwl_cfg iwl22000_2ac_cfg_jf;
 extern const struct iwl_cfg iwl_ax101_cfg_qu_hr;
 extern const struct iwl_cfg iwl_ax101_cfg_qu_c0_hr_b0;
 extern const struct iwl_cfg iwl_ax101_cfg_quz_hr;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/iwl-context-info.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/iwl-context-info.h
@@ -6,7 +6,7 @@
  * GPL LICENSE SUMMARY
  *
  * Copyright(c) 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
@@ -20,7 +20,7 @@
  * BSD LICENSE
  *
  * Copyright(c) 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -64,12 +64,12 @@
  *	the init done for driver command that configures several system modes
  * @IWL_CTXT_INFO_EARLY_DEBUG: enable early debug
  * @IWL_CTXT_INFO_ENABLE_CDMP: enable core dump
- * @IWL_CTXT_INFO_RB_CB_SIZE_POS: position of the RBD Cyclic Buffer Size
+ * @IWL_CTXT_INFO_RB_CB_SIZE: mask of the RBD Cyclic Buffer Size
  *	exponent, the actual size is 2**value, valid sizes are 8-2048.
  *	The value is four bits long. Maximum valid exponent is 12
  * @IWL_CTXT_INFO_TFD_FORMAT_LONG: use long TFD Format (the
  *	default is short format - not supported by the driver)
- * @IWL_CTXT_INFO_RB_SIZE_POS: RB size position
+ * @IWL_CTXT_INFO_RB_SIZE: RB size mask
  *	(values are IWL_CTXT_INFO_RB_SIZE_*K)
  * @IWL_CTXT_INFO_RB_SIZE_1K: Value for 1K RB size
  * @IWL_CTXT_INFO_RB_SIZE_2K: Value for 2K RB size
@@ -83,12 +83,12 @@
  * @IWL_CTXT_INFO_RB_SIZE_32K: Value for 32K RB size
  */
 enum iwl_context_info_flags {
-	IWL_CTXT_INFO_AUTO_FUNC_INIT	= BIT(0),
-	IWL_CTXT_INFO_EARLY_DEBUG	= BIT(1),
-	IWL_CTXT_INFO_ENABLE_CDMP	= BIT(2),
-	IWL_CTXT_INFO_RB_CB_SIZE_POS	= 4,
-	IWL_CTXT_INFO_TFD_FORMAT_LONG	= BIT(8),
-	IWL_CTXT_INFO_RB_SIZE_POS	= 9,
+	IWL_CTXT_INFO_AUTO_FUNC_INIT	= 0x0001,
+	IWL_CTXT_INFO_EARLY_DEBUG	= 0x0002,
+	IWL_CTXT_INFO_ENABLE_CDMP	= 0x0004,
+	IWL_CTXT_INFO_RB_CB_SIZE	= 0x00f0,
+	IWL_CTXT_INFO_TFD_FORMAT_LONG	= 0x0100,
+	IWL_CTXT_INFO_RB_SIZE		= 0x1e00,
 	IWL_CTXT_INFO_RB_SIZE_1K	= 0x1,
 	IWL_CTXT_INFO_RB_SIZE_2K	= 0x2,
 	IWL_CTXT_INFO_RB_SIZE_4K	= 0x4,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/iwl-csr.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/iwl-csr.h
@@ -147,6 +147,16 @@
 #define CSR_MAC_SHADOW_REG_CTL2		(CSR_BASE + 0x0AC)
 #define CSR_MAC_SHADOW_REG_CTL2_RX_WAKE	0xFFFF
 
+/* LTR control (since IWL_DEVICE_FAMILY_22000) */
+#define CSR_LTR_LONG_VAL_AD			(CSR_BASE + 0x0D4)
+#define CSR_LTR_LONG_VAL_AD_NO_SNOOP_REQ	0x80000000
+#define CSR_LTR_LONG_VAL_AD_NO_SNOOP_SCALE	0x1c000000
+#define CSR_LTR_LONG_VAL_AD_NO_SNOOP_VAL	0x03ff0000
+#define CSR_LTR_LONG_VAL_AD_SNOOP_REQ		0x00008000
+#define CSR_LTR_LONG_VAL_AD_SNOOP_SCALE		0x00001c00
+#define CSR_LTR_LONG_VAL_AD_SNOOP_VAL		0x000003ff
+#define CSR_LTR_LONG_VAL_AD_SCALE_USEC		2
+
 /* GIO Chicken Bits (PCI Express bus link power management) */
 #define CSR_GIO_CHICKEN_BITS    (CSR_BASE+0x100)
 
@@ -603,9 +613,7 @@
 enum msix_hw_int_causes {
 	MSIX_HW_INT_CAUSES_REG_ALIVE		= BIT(0),
 	MSIX_HW_INT_CAUSES_REG_WAKEUP		= BIT(1),
-	MSIX_HW_INT_CAUSES_REG_IPC		= BIT(1),
 	MSIX_HW_INT_CAUSES_REG_IML              = BIT(2),
-	MSIX_HW_INT_CAUSES_REG_SW_ERR_V2	= BIT(5),
 	MSIX_HW_INT_CAUSES_REG_CT_KILL		= BIT(6),
 	MSIX_HW_INT_CAUSES_REG_RF_KILL		= BIT(7),
 	MSIX_HW_INT_CAUSES_REG_PERIODIC		= BIT(8),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/iwl-drv.c
@@ -183,6 +183,9 @@
 
 	for (i = 0; i < IWL_UCODE_TYPE_MAX; i++)
 		iwl_free_fw_img(drv, drv->fw.img + i);
+
+	/* clear the data for the aborted load case */
+	memset(&drv->fw, 0, sizeof(drv->fw));
 }
 
 static int iwl_alloc_fw_desc(struct iwl_drv *drv, struct fw_desc *desc,
@@ -1110,7 +1113,7 @@
 
 			if (tlv_len != sizeof(*fseq_ver))
 				goto invalid_tlv_len;
-			IWL_INFO(drv, "TLV_FW_FSEQ_VERSION: %s\n",
+			IWL_INFO(drv, "TLV_FW_FSEQ_VERSION: %.32s\n",
 				 fseq_ver->version);
 			}
 			break;
@@ -1276,23 +1279,31 @@
 	const struct iwl_op_mode_ops *ops = op->ops;
 	struct dentry *dbgfs_dir = NULL;
 	struct iwl_op_mode *op_mode = NULL;
+	int retry, max_retry = !!iwlwifi_mod_params.fw_restart * IWL_MAX_INIT_RETRY;
+
+	for (retry = 0; retry <= max_retry; retry++) {
 
 #ifdef CONFIG_IWLWIFI_DEBUGFS
-	drv->dbgfs_op_mode = debugfs_create_dir(op->name,
-						drv->dbgfs_drv);
-	dbgfs_dir = drv->dbgfs_op_mode;
+		drv->dbgfs_op_mode = debugfs_create_dir(op->name,
+							drv->dbgfs_drv);
+		dbgfs_dir = drv->dbgfs_op_mode;
 #endif
 
-	op_mode = ops->start(drv->trans, drv->trans->cfg, &drv->fw, dbgfs_dir);
+		op_mode = ops->start(drv->trans, drv->trans->cfg,
+				     &drv->fw, dbgfs_dir);
+
+		if (op_mode)
+			return op_mode;
+
+		IWL_ERR(drv, "retry init count %d\n", retry);
 
 #ifdef CONFIG_IWLWIFI_DEBUGFS
-	if (!op_mode) {
 		debugfs_remove_recursive(drv->dbgfs_op_mode);
 		drv->dbgfs_op_mode = NULL;
-	}
 #endif
+	}
 
-	return op_mode;
+	return NULL;
 }
 
 static void _iwl_op_mode_stop(struct iwl_drv *drv)
@@ -1330,6 +1341,7 @@
 	int i;
 	bool load_module = false;
 	bool usniffer_images = false;
+	bool failure = true;
 
 	fw->ucode_capa.max_probe_length = IWL_DEFAULT_MAX_PROBE_LENGTH;
 	fw->ucode_capa.standard_phy_calibration_size =
@@ -1587,15 +1599,9 @@
 	 * else from proceeding if the module fails to load
 	 * or hangs loading.
 	 */
-	if (load_module) {
+	if (load_module)
 		request_module("%s", op->name);
-#ifdef CONFIG_IWLWIFI_OPMODE_MODULAR
-		if (err)
-			IWL_ERR(drv,
-				"failed to load module %s (error %d), is dynamic loading enabled?\n",
-				op->name, err);
-#endif
-	}
+	failure = false;
 	goto free;
 
  try_again:
@@ -1610,7 +1616,12 @@
  out_unbind:
 	complete(&drv->request_firmware_complete);
 	device_release_driver(drv->trans->dev);
+	/* drv has just been freed by the release */
+	failure = false;
  free:
+	if (failure)
+		iwl_dealloc_ucode(drv);
+
 	if (pieces) {
 		for (i = 0; i < ARRAY_SIZE(pieces->img); i++)
 			kfree(pieces->img[i].sec);
@@ -1658,8 +1669,8 @@
 err_fw:
 #ifdef CONFIG_IWLWIFI_DEBUGFS
 	debugfs_remove_recursive(drv->dbgfs_drv);
-	iwl_dbg_tlv_free(drv->trans);
 #endif
+	iwl_dbg_tlv_free(drv->trans);
 	kfree(drv);
 err:
 	return ERR_PTR(ret);
@@ -1804,7 +1815,7 @@
 	"disable 11n functionality, bitmap: 1: full, 2: disable agg TX, 4: disable agg RX, 8 enable agg TX");
 module_param_named(amsdu_size, iwlwifi_mod_params.amsdu_size, int, 0444);
 MODULE_PARM_DESC(amsdu_size,
-		 "amsdu size 0: 12K for multi Rx queue devices, 2K for 22560 devices, "
+		 "amsdu size 0: 12K for multi Rx queue devices, 2K for AX210 devices, "
 		 "4K for other devices 1:4K 2:8K 3:12K 4: 2K (default 0)");
 module_param_named(fw_restart, iwlwifi_mod_params.fw_restart, bool, 0444);
 MODULE_PARM_DESC(fw_restart, "restart firmware in case of error (default true)");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/iwl-drv.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/iwl-drv.h
@@ -145,4 +145,7 @@
 #define IWL_EXPORT_SYMBOL(sym)
 #endif
 
+/* max retry for init flow */
+#define IWL_MAX_INIT_RETRY 2
+
 #endif /* __iwl_drv_h__ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/iwl-fh.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/iwl-fh.h
@@ -611,10 +611,7 @@
  */
 #define FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN	(0x00000002)
 
-#define MQ_RX_TABLE_SIZE	512
-#define MQ_RX_TABLE_MASK	(MQ_RX_TABLE_SIZE - 1)
-#define MQ_RX_NUM_RBDS		(MQ_RX_TABLE_SIZE - 1)
-#define RX_POOL_SIZE		(MQ_RX_NUM_RBDS +	\
+#define RX_POOL_SIZE(rbds)	((rbds) - 1 +	\
 				 IWL_MAX_RX_HW_QUEUES *	\
 				 (RX_CLAIM_REQ_ALLOC - RX_POST_REQ_ALLOC))
 /* cb size is the exponent */
@@ -768,7 +765,7 @@
 
 /**
  * struct iwl_gen3_bc_tbl scheduler byte count table gen3
- * For 22560 and on:
+ * For AX210 and on:
  * @tfd_offset: 0-12 - tx command byte count
  *		12-13 - number of 64 byte chunks
  *		14-16 - reserved
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
@@ -225,6 +225,34 @@
 	NVM_CHANNEL_DC_HIGH		= BIT(12),
 };
 
+/**
+ * enum iwl_reg_capa_flags - global flags applied for the whole regulatory
+ * domain.
+ * @REG_CAPA_BF_CCD_LOW_BAND: Beam-forming or Cyclic Delay Diversity in the
+ *	2.4Ghz band is allowed.
+ * @REG_CAPA_BF_CCD_HIGH_BAND: Beam-forming or Cyclic Delay Diversity in the
+ *	5Ghz band is allowed.
+ * @REG_CAPA_160MHZ_ALLOWED: 11ac channel with a width of 160Mhz is allowed
+ *	for this regulatory domain (valid only in 5Ghz).
+ * @REG_CAPA_80MHZ_ALLOWED: 11ac channel with a width of 80Mhz is allowed
+ *	for this regulatory domain (valid only in 5Ghz).
+ * @REG_CAPA_MCS_8_ALLOWED: 11ac with MCS 8 is allowed.
+ * @REG_CAPA_MCS_9_ALLOWED: 11ac with MCS 9 is allowed.
+ * @REG_CAPA_40MHZ_FORBIDDEN: 11n channel with a width of 40Mhz is forbidden
+ *	for this regulatory domain (valid only in 5Ghz).
+ * @REG_CAPA_DC_HIGH_ENABLED: DC HIGH allowed.
+ */
+enum iwl_reg_capa_flags {
+	REG_CAPA_BF_CCD_LOW_BAND	= BIT(0),
+	REG_CAPA_BF_CCD_HIGH_BAND	= BIT(1),
+	REG_CAPA_160MHZ_ALLOWED		= BIT(2),
+	REG_CAPA_80MHZ_ALLOWED		= BIT(3),
+	REG_CAPA_MCS_8_ALLOWED		= BIT(4),
+	REG_CAPA_MCS_9_ALLOWED		= BIT(5),
+	REG_CAPA_40MHZ_FORBIDDEN	= BIT(7),
+	REG_CAPA_DC_HIGH_ENABLED	= BIT(9),
+};
+
 static inline void iwl_nvm_print_channel_flags(struct device *dev, u32 level,
 					       int chan, u32 flags)
 {
@@ -491,14 +519,12 @@
 			.has_he = true,
 			.he_cap_elem = {
 				.mac_cap_info[0] =
-					IEEE80211_HE_MAC_CAP0_HTC_HE |
-					IEEE80211_HE_MAC_CAP0_TWT_REQ,
+					IEEE80211_HE_MAC_CAP0_HTC_HE,
 				.mac_cap_info[1] =
 					IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US |
 					IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_8,
 				.mac_cap_info[2] =
-					IEEE80211_HE_MAC_CAP2_32BIT_BA_BITMAP |
-					IEEE80211_HE_MAC_CAP2_ACK_EN,
+					IEEE80211_HE_MAC_CAP2_32BIT_BA_BITMAP,
 				.mac_cap_info[3] =
 					IEEE80211_HE_MAC_CAP3_OMI_CONTROL |
 					IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_VHT_2,
@@ -582,8 +608,7 @@
 					IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US |
 					IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_8,
 				.mac_cap_info[2] =
-					IEEE80211_HE_MAC_CAP2_BSR |
-					IEEE80211_HE_MAC_CAP2_ACK_EN,
+					IEEE80211_HE_MAC_CAP2_BSR,
 				.mac_cap_info[3] =
 					IEEE80211_HE_MAC_CAP3_OMI_CONTROL |
 					IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_VHT_2,
@@ -1031,6 +1056,7 @@
 
 static u32 iwl_nvm_get_regdom_bw_flags(const u16 *nvm_chan,
 				       int ch_idx, u16 nvm_flags,
+				       u16 cap_flags,
 				       const struct iwl_cfg *cfg)
 {
 	u32 flags = NL80211_RRF_NO_HT40;
@@ -1069,13 +1095,27 @@
 	    (flags & NL80211_RRF_NO_IR))
 		flags |= NL80211_RRF_GO_CONCURRENT;
 
+	/*
+	 * cap_flags is per regulatory domain so apply it for every channel
+	 */
+	if (ch_idx >= NUM_2GHZ_CHANNELS) {
+		if (cap_flags & REG_CAPA_40MHZ_FORBIDDEN)
+			flags |= NL80211_RRF_NO_HT40;
+
+		if (!(cap_flags & REG_CAPA_80MHZ_ALLOWED))
+			flags |= NL80211_RRF_NO_80MHZ;
+
+		if (!(cap_flags & REG_CAPA_160MHZ_ALLOWED))
+			flags |= NL80211_RRF_NO_160MHZ;
+	}
+
 	return flags;
 }
 
 struct ieee80211_regdomain *
 iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
 		       int num_of_ch, __le32 *channels, u16 fw_mcc,
-		       u16 geo_info)
+		       u16 geo_info, u16 cap)
 {
 	int ch_idx;
 	u16 ch_flags;
@@ -1133,7 +1173,8 @@
 		}
 
 		reg_rule_flags = iwl_nvm_get_regdom_bw_flags(nvm_chan, ch_idx,
-							     ch_flags, cfg);
+							     ch_flags, cap,
+							     cfg);
 
 		/* we can't continue the same rule */
 		if (ch_idx == 0 || prev_reg_rule_flags != reg_rule_flags ||
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.h
@@ -7,7 +7,7 @@
  *
  * Copyright(c) 2008 - 2015 Intel Corporation. All rights reserved.
  * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018        Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
@@ -29,7 +29,7 @@
  *
  * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018        Intel Corporation
+ * Copyright(c) 2018 - 2019 Intel Corporation
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -103,7 +103,7 @@
 struct ieee80211_regdomain *
 iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg,
 		       int num_of_ch, __le32 *channels, u16 fw_mcc,
-		       u16 geo_info);
+		       u16 geo_info, u16 cap);
 
 /**
  * struct iwl_nvm_section - describes an NVM section in memory.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/iwl-trans.c
@@ -66,7 +66,9 @@
 
 struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
 				  struct device *dev,
-				  const struct iwl_trans_ops *ops)
+				  const struct iwl_trans_ops *ops,
+				  unsigned int cmd_pool_size,
+				  unsigned int cmd_pool_align)
 {
 	struct iwl_trans *trans;
 #ifdef CONFIG_LOCKDEP
@@ -90,10 +92,8 @@
 		 "iwl_cmd_pool:%s", dev_name(trans->dev));
 	trans->dev_cmd_pool =
 		kmem_cache_create(trans->dev_cmd_pool_name,
-				  sizeof(struct iwl_device_cmd),
-				  sizeof(void *),
-				  SLAB_HWCACHE_ALIGN,
-				  NULL);
+				  cmd_pool_size, cmd_pool_align,
+				  SLAB_HWCACHE_ALIGN, NULL);
 	if (!trans->dev_cmd_pool)
 		return NULL;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
@@ -193,6 +193,18 @@
 	};
 } __packed;
 
+/**
+ * struct iwl_device_tx_cmd - buffer for TX command
+ * @hdr: the header
+ * @payload: the payload placeholder
+ *
+ * The actual structure is sized dynamically according to need.
+ */
+struct iwl_device_tx_cmd {
+	struct iwl_cmd_header hdr;
+	u8 payload[];
+} __packed;
+
 #define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd))
 
 /*
@@ -302,6 +314,7 @@
 #define IWL_MGMT_TID		15
 #define IWL_FRAME_LIMIT	64
 #define IWL_MAX_RX_HW_QUEUES	16
+#define IWL_9000_MAX_RX_HW_QUEUES	6
 
 /**
  * enum iwl_wowlan_status - WoWLAN image/device status
@@ -544,7 +557,7 @@
 	int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
 
 	int (*tx)(struct iwl_trans *trans, struct sk_buff *skb,
-		  struct iwl_device_cmd *dev_cmd, int queue);
+		  struct iwl_device_tx_cmd *dev_cmd, int queue);
 	void (*reclaim)(struct iwl_trans *trans, int queue, int ssn,
 			struct sk_buff_head *skbs);
 
@@ -921,22 +934,22 @@
 	return trans->ops->dump_data(trans, dump_mask);
 }
 
-static inline struct iwl_device_cmd *
+static inline struct iwl_device_tx_cmd *
 iwl_trans_alloc_tx_cmd(struct iwl_trans *trans)
 {
-	return kmem_cache_alloc(trans->dev_cmd_pool, GFP_ATOMIC);
+	return kmem_cache_zalloc(trans->dev_cmd_pool, GFP_ATOMIC);
 }
 
 int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
 
 static inline void iwl_trans_free_tx_cmd(struct iwl_trans *trans,
-					 struct iwl_device_cmd *dev_cmd)
+					 struct iwl_device_tx_cmd *dev_cmd)
 {
 	kmem_cache_free(trans->dev_cmd_pool, dev_cmd);
 }
 
 static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
-			       struct iwl_device_cmd *dev_cmd, int queue)
+			       struct iwl_device_tx_cmd *dev_cmd, int queue)
 {
 	if (unlikely(test_bit(STATUS_FW_ERROR, &trans->status)))
 		return -EIO;
@@ -1239,7 +1252,9 @@
  *****************************************************/
 struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
 				  struct device *dev,
-				  const struct iwl_trans_ops *ops);
+				  const struct iwl_trans_ops *ops,
+				  unsigned int cmd_pool_size,
+				  unsigned int cmd_pool_align);
 void iwl_trans_free(struct iwl_trans *trans);
 
 /*****************************************************
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/mvm/constants.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/mvm/constants.h
@@ -154,5 +154,6 @@
 #define IWL_MVM_D3_DEBUG			false
 #define IWL_MVM_USE_TWT				false
 #define IWL_MVM_AMPDU_CONSEC_DROPS_DELBA	10
+#define IWL_MVM_USE_NSSN_SYNC			0
 
 #endif /* __MVM_CONSTANTS_H */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
@@ -514,7 +514,10 @@
 	const size_t bufsz = sizeof(buf);
 	int pos = 0;
 
+	mutex_lock(&mvm->mutex);
 	iwl_mvm_get_sync_time(mvm, &curr_gp2, &curr_os);
+	mutex_unlock(&mvm->mutex);
+
 	do_div(curr_os, NSEC_PER_USEC);
 	diff = curr_os - curr_gp2;
 	pos += scnprintf(buf + pos, bufsz - pos, "diff=%lld\n", diff);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
@@ -5,10 +5,9 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 - 2019 Intel Corporation
+ * Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
@@ -28,10 +27,9 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 - 2019 Intel Corporation
+ * Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -478,6 +476,11 @@
 	if (kstrtou16(buf, 0, &amsdu_len))
 		return -EINVAL;
 
+	/* only change from debug set <-> debug unset */
+	if ((amsdu_len && mvmsta->orig_amsdu_len) ||
+	    (!!amsdu_len && mvmsta->orig_amsdu_len))
+		return -EBUSY;
+
 	if (amsdu_len) {
 		mvmsta->orig_amsdu_len = sta->max_amsdu_len;
 		sta->max_amsdu_len = amsdu_len;
@@ -1174,7 +1177,7 @@
 	int bin_len = count / 2;
 	int ret = -EINVAL;
 	size_t mpdu_cmd_hdr_size = (mvm->trans->trans_cfg->device_family >=
-				    IWL_DEVICE_FAMILY_22560) ?
+				    IWL_DEVICE_FAMILY_AX210) ?
 		sizeof(struct iwl_rx_mpdu_desc) :
 		IWL_RX_DESC_SIZE_V1;
 
@@ -1874,6 +1877,11 @@
 	if (ret < 0)
 		return ret;
 
+	if (iwl_rx_packet_payload_len(hcmd.resp_pkt) < sizeof(*rsp)) {
+		ret = -EIO;
+		goto out;
+	}
+
 	rsp = (void *)hcmd.resp_pkt->data;
 	if (le32_to_cpu(rsp->status) != DEBUG_MEM_STATUS_SUCCESS) {
 		ret = -ENXIO;
@@ -1951,6 +1959,11 @@
 	if (ret < 0)
 		return ret;
 
+	if (iwl_rx_packet_payload_len(hcmd.resp_pkt) < sizeof(*rsp)) {
+		ret = -EIO;
+		goto out;
+	}
+
 	rsp = (void *)hcmd.resp_pkt->data;
 	if (rsp->status != DEBUG_MEM_STATUS_SUCCESS) {
 		ret = -ENXIO;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
@@ -8,6 +8,7 @@
  * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
  * Copyright (C) 2018 Intel Corporation
  * Copyright (C) 2019 Intel Corporation
+ * Copyright (C) 2020 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
@@ -30,6 +31,7 @@
  * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
  * Copyright (C) 2018 Intel Corporation
  * Copyright (C) 2019 Intel Corporation
+ * Copyright (C) 2020 Intel Corporation
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -389,6 +391,8 @@
 	if (req != mvm->ftm_initiator.req)
 		return;
 
+	iwl_mvm_ftm_reset(mvm);
+
 	if (iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(TOF_RANGE_ABORT_CMD,
 						 LOCATION_GROUP, 0),
 				 0, sizeof(cmd), &cmd))
@@ -502,7 +506,6 @@
 	lockdep_assert_held(&mvm->mutex);
 
 	if (!mvm->ftm_initiator.req) {
-		IWL_ERR(mvm, "Got FTM response but have no request?\n");
 		return;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
@@ -134,7 +134,14 @@
 		.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
 	};
 
-	/* Do not configure default queue, it is configured via context info */
+	/*
+	 * The default queue is configured via context info, so if we
+	 * have a single queue, there's nothing to do here.
+	 */
+	if (mvm->trans->num_rx_queues == 1)
+		return 0;
+
+	/* skip the default queue */
 	num_queues = mvm->trans->num_rx_queues - 1;
 
 	size = struct_size(cmd, data, num_queues);
@@ -190,20 +197,10 @@
 {
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
 	struct iwl_mfu_assert_dump_notif *mfu_dump_notif = (void *)pkt->data;
-	__le32 *dump_data = mfu_dump_notif->data;
-	int n_words = le32_to_cpu(mfu_dump_notif->data_size) / sizeof(__le32);
-	int i;
 
 	if (mfu_dump_notif->index_num == 0)
 		IWL_INFO(mvm, "MFUART assert id 0x%x occurred\n",
 			 le32_to_cpu(mfu_dump_notif->assert_id));
-
-	for (i = 0; i < n_words; i++)
-		IWL_DEBUG_INFO(mvm,
-			       "MFUART assert dump, dword %u: 0x%08x\n",
-			       le16_to_cpu(mfu_dump_notif->index_num) *
-			       n_words + i,
-			       le32_to_cpu(dump_data[i]));
 }
 
 static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
@@ -514,6 +511,18 @@
 	struct iwl_phy_cfg_cmd phy_cfg_cmd;
 	enum iwl_ucode_type ucode_type = mvm->fwrt.cur_fw_img;
 
+	if (iwl_mvm_has_unified_ucode(mvm) &&
+	    !mvm->trans->cfg->tx_with_siso_diversity) {
+		return 0;
+	} else if (mvm->trans->cfg->tx_with_siso_diversity) {
+		/*
+		 * TODO: currently we don't set the antenna but letting the NIC
+		 * to decide which antenna to use. This should come from BIOS.
+		 */
+		phy_cfg_cmd.phy_cfg =
+			cpu_to_le32(FW_PHY_CFG_CHAIN_SAD_ENABLED);
+	}
+
 	/* Set parameters */
 	phy_cfg_cmd.phy_cfg = cpu_to_le32(iwl_mvm_get_phy_config(mvm));
 
@@ -644,7 +653,7 @@
 		mvm->nvm_data->bands[0].n_channels = 1;
 		mvm->nvm_data->bands[0].n_bitrates = 1;
 		mvm->nvm_data->bands[0].bitrates =
-			(void *)mvm->nvm_data->channels + 1;
+			(void *)(mvm->nvm_data->channels + 1);
 		mvm->nvm_data->bands[0].bitrates->hw_value = 10;
 	}
 
@@ -1169,15 +1178,22 @@
 
 static int iwl_mvm_ppag_init(struct iwl_mvm *mvm)
 {
-	return -ENOENT;
+	return 0;
 }
 #endif /* CONFIG_ACPI */
 
+static void iwl_mvm_disconnect_iterator(void *data, u8 *mac,
+					struct ieee80211_vif *vif)
+{
+	if (vif->type == NL80211_IFTYPE_STATION)
+		ieee80211_hw_restart_disconnect(vif);
+}
+
 void iwl_mvm_send_recovery_cmd(struct iwl_mvm *mvm, u32 flags)
 {
 	u32 error_log_size = mvm->fw->ucode_capa.error_log_size;
+	u32 status = 0;
 	int ret;
-	u32 resp;
 
 	struct iwl_fw_error_recovery_cmd recovery_cmd = {
 		.flags = cpu_to_le32(flags),
@@ -1185,7 +1201,6 @@
 	};
 	struct iwl_host_cmd host_cmd = {
 		.id = WIDE_ID(SYSTEM_GROUP, FW_ERROR_RECOVERY_CMD),
-		.flags = CMD_WANT_SKB,
 		.data = {&recovery_cmd, },
 		.len = {sizeof(recovery_cmd), },
 	};
@@ -1205,7 +1220,7 @@
 		recovery_cmd.buf_size = cpu_to_le32(error_log_size);
 	}
 
-	ret = iwl_mvm_send_cmd(mvm, &host_cmd);
+	ret = iwl_mvm_send_cmd_status(mvm, &host_cmd, &status);
 	kfree(mvm->error_recovery_buf);
 	mvm->error_recovery_buf = NULL;
 
@@ -1216,11 +1231,15 @@
 
 	/* skb respond is only relevant in ERROR_RECOVERY_UPDATE_DB */
 	if (flags & ERROR_RECOVERY_UPDATE_DB) {
-		resp = le32_to_cpu(*(__le32 *)host_cmd.resp_pkt->data);
-		if (resp)
+		if (status) {
 			IWL_ERR(mvm,
 				"Failed to send recovery cmd blob was invalid %d\n",
-				resp);
+				status);
+
+			ieee80211_iterate_interfaces(mvm->hw, 0,
+						     iwl_mvm_disconnect_iterator,
+						     mvm);
+		}
 	}
 }
 
@@ -1344,12 +1363,12 @@
 		ret = iwl_send_phy_db_data(mvm->phy_db);
 		if (ret)
 			goto error;
-
-		ret = iwl_send_phy_cfg_cmd(mvm);
-		if (ret)
-			goto error;
 	}
 
+	ret = iwl_send_phy_cfg_cmd(mvm);
+	if (ret)
+		goto error;
+
 	ret = iwl_mvm_send_bt_init_conf(mvm);
 	if (ret)
 		goto error;
@@ -1398,8 +1417,10 @@
 	while (!sband && i < NUM_NL80211_BANDS)
 		sband = mvm->hw->wiphy->bands[i++];
 
-	if (WARN_ON_ONCE(!sband))
+	if (WARN_ON_ONCE(!sband)) {
+		ret = -ENODEV;
 		goto error;
+	}
 
 	chan = &sband->channels[0];
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/mvm/led.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/mvm/led.c
@@ -129,6 +129,9 @@
 
 	mvm->led.name = kasprintf(GFP_KERNEL, "%s-led",
 				   wiphy_name(mvm->hw->wiphy));
+	if (!mvm->led.name)
+		return -ENOMEM;
+
 	mvm->led.brightness_set = iwl_led_brightness_set;
 	mvm->led.max_brightness = 1;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
@@ -1043,8 +1043,10 @@
 		return -ENOMEM;
 
 #ifdef CONFIG_IWLWIFI_DEBUGFS
-	if (mvm->beacon_inject_active)
+	if (mvm->beacon_inject_active) {
+		dev_kfree_skb(beacon);
 		return -EBUSY;
+	}
 #endif
 
 	ret = iwl_mvm_mac_ctxt_send_beacon(mvm, vif, beacon);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
@@ -5,10 +5,9 @@
  *
  * GPL LICENSE SUMMARY
  *
- * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 - 2019 Intel Corporation
+ * Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
@@ -28,10 +27,9 @@
  *
  * BSD LICENSE
  *
- * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 - 2019 Intel Corporation
+ * Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -73,6 +71,7 @@
 #include <net/ieee80211_radiotap.h>
 #include <net/tcp.h>
 
+#include "iwl-drv.h"
 #include "iwl-op-mode.h"
 #include "iwl-io.h"
 #include "mvm.h"
@@ -256,7 +255,8 @@
 				      __le32_to_cpu(resp->n_channels),
 				      resp->channels,
 				      __le16_to_cpu(resp->mcc),
-				      __le16_to_cpu(resp->geo_info));
+				      __le16_to_cpu(resp->geo_info),
+				      __le16_to_cpu(resp->cap));
 	/* Store the return source id */
 	src_id = resp->source_id;
 	kfree(resp);
@@ -343,7 +343,6 @@
 	 [0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
 	 [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
 	 [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
-	 [9] = WLAN_EXT_CAPA10_TWT_REQUESTER_SUPPORT,
 };
 
 const static struct wiphy_iftype_ext_capab he_iftypes_ext_capa[] = {
@@ -742,6 +741,20 @@
 	return ret;
 }
 
+static void iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
+			   struct ieee80211_sta *sta)
+{
+	if (likely(sta)) {
+		if (likely(iwl_mvm_tx_skb_sta(mvm, skb, sta) == 0))
+			return;
+	} else {
+		if (likely(iwl_mvm_tx_skb_non_sta(mvm, skb) == 0))
+			return;
+	}
+
+	ieee80211_free_txskb(mvm->hw, skb);
+}
+
 static void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
 			   struct ieee80211_tx_control *control,
 			   struct sk_buff *skb)
@@ -785,14 +798,7 @@
 		}
 	}
 
-	if (sta) {
-		if (iwl_mvm_tx_skb(mvm, skb, sta))
-			goto drop;
-		return;
-	}
-
-	if (iwl_mvm_tx_skb_non_sta(mvm, skb))
-		goto drop;
+	iwl_mvm_tx_skb(mvm, skb, sta);
 	return;
  drop:
 	ieee80211_free_txskb(hw, skb);
@@ -842,10 +848,7 @@
 				break;
 			}
 
-			if (!txq->sta)
-				iwl_mvm_tx_skb_non_sta(mvm, skb);
-			else
-				iwl_mvm_tx_skb(mvm, skb, txq->sta);
+			iwl_mvm_tx_skb(mvm, skb, txq->sta);
 		}
 	} while (atomic_dec_return(&mvmtxq->tx_request));
 	rcu_read_unlock();
@@ -1126,9 +1129,30 @@
 {
 	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
 	int ret;
+	int retry, max_retry = 0;
 
 	mutex_lock(&mvm->mutex);
-	ret = __iwl_mvm_mac_start(mvm);
+
+	/* we are starting the mac not in error flow, and restart is enabled */
+	if (!test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status) &&
+	    iwlwifi_mod_params.fw_restart) {
+		max_retry = IWL_MAX_INIT_RETRY;
+		/*
+		 * This will prevent mac80211 recovery flows to trigger during
+		 * init failures
+		 */
+		set_bit(IWL_MVM_STATUS_STARTING, &mvm->status);
+	}
+
+	for (retry = 0; retry <= max_retry; retry++) {
+		ret = __iwl_mvm_mac_start(mvm);
+		if (!ret)
+			break;
+
+		IWL_ERR(mvm, "mac start retry %d\n", retry);
+	}
+	clear_bit(IWL_MVM_STATUS_STARTING, &mvm->status);
+
 	mutex_unlock(&mvm->mutex);
 
 	return ret;
@@ -1190,14 +1214,13 @@
 	 */
 	flush_work(&mvm->roc_done_wk);
 
+	iwl_mvm_rm_aux_sta(mvm);
+
 	iwl_mvm_stop_device(mvm);
 
 	iwl_mvm_async_handlers_purge(mvm);
 	/* async_handlers_list is empty and will stay empty: HW is stopped */
 
-	/* the fw is stopped, the aux sta is dead: clean up driver state */
-	iwl_mvm_del_aux_sta(mvm);
-
 	/*
 	 * Clear IN_HW_RESTART and HW_RESTART_REQUESTED flag when stopping the
 	 * hw (as restart_complete() won't be called in this case) and mac80211
@@ -1672,6 +1695,7 @@
 	struct iwl_mvm_mc_iter_data iter_data = {
 		.mvm = mvm,
 	};
+	int ret;
 
 	lockdep_assert_held(&mvm->mutex);
 
@@ -1681,6 +1705,22 @@
 	ieee80211_iterate_active_interfaces_atomic(
 		mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
 		iwl_mvm_mc_iface_iterator, &iter_data);
+
+	/*
+	 * Send a (synchronous) ech command so that we wait for the
+	 * multiple asynchronous MCAST_FILTER_CMD commands sent by
+	 * the interface iterator. Otherwise, we might get here over
+	 * and over again (by userspace just sending a lot of these)
+	 * and the CPU can send them faster than the firmware can
+	 * process them.
+	 * Note that the CPU is still faster - but with this we'll
+	 * actually send fewer commands overall because the CPU will
+	 * not schedule the work in mac80211 as frequently if it's
+	 * still running when rescheduled (possibly multiple times).
+	 */
+	ret = iwl_mvm_send_cmd_pdu(mvm, ECHO_CMD, 0, 0, NULL);
+	if (ret)
+		IWL_ERR(mvm, "Failed to synchronize multicast groups update\n");
 }
 
 static u64 iwl_mvm_prepare_multicast(struct ieee80211_hw *hw,
@@ -2020,7 +2060,7 @@
 	rcu_read_lock();
 
 	sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_ctxt_cmd.sta_id]);
-	if (IS_ERR(sta)) {
+	if (IS_ERR_OR_NULL(sta)) {
 		rcu_read_unlock();
 		WARN(1, "Can't find STA to configure HE\n");
 		return;
@@ -2968,16 +3008,20 @@
 						    void *_data)
 {
 	struct iwl_mvm_he_obss_narrow_bw_ru_data *data = _data;
+	const struct cfg80211_bss_ies *ies;
 	const struct element *elem;
 
-	elem = cfg80211_find_elem(WLAN_EID_EXT_CAPABILITY, bss->ies->data,
-				  bss->ies->len);
+	rcu_read_lock();
+	ies = rcu_dereference(bss->ies);
+	elem = cfg80211_find_elem(WLAN_EID_EXT_CAPABILITY, ies->data,
+				  ies->len);
 
 	if (!elem || elem->datalen < 10 ||
 	    !(elem->data[10] &
 	      WLAN_EXT_CAPA10_OBSS_NARROW_BW_RU_TOLERANCE_SUPPORT)) {
 		data->tolerated = false;
 	}
+	rcu_read_unlock();
 }
 
 static void iwl_mvm_check_he_obss_narrow_bw_ru(struct ieee80211_hw *hw,
@@ -3020,7 +3064,7 @@
 
 	/* this would be a mac80211 bug ... but don't crash */
 	if (WARN_ON_ONCE(!mvmvif->phy_ctxt))
-		return -EINVAL;
+		return test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status) ? 0 : -EINVAL;
 
 	/*
 	 * If we are in a STA removal flow and in DQA mode:
@@ -3067,6 +3111,9 @@
 			goto out_unlock;
 		}
 
+		if (vif->type == NL80211_IFTYPE_STATION)
+			vif->bss_conf.he_support = sta->he_cap.has_he;
+
 		if (sta->tdls &&
 		    (vif->p2p ||
 		     iwl_mvm_tdls_sta_count(mvm, NULL) ==
@@ -3648,9 +3695,12 @@
 	tail->apply_time_max_delay = cpu_to_le32(delay);
 
 	IWL_DEBUG_TE(mvm,
-		     "ROC: Requesting to remain on channel %u for %ums (requested = %ums, max_delay = %ums, dtim_interval = %ums)\n",
-		     channel->hw_value, req_dur, duration, delay,
-		     dtim_interval);
+		     "ROC: Requesting to remain on channel %u for %ums\n",
+		     channel->hw_value, req_dur);
+	IWL_DEBUG_TE(mvm,
+		     "\t(requested = %ums, max_delay = %ums, dtim_interval = %ums)\n",
+		     duration, delay, dtim_interval);
+
 	/* Set the node address */
 	memcpy(tail->node_addr, vif->addr, ETH_ALEN);
 
@@ -3717,6 +3767,7 @@
 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 	struct cfg80211_chan_def chandef;
 	struct iwl_mvm_phy_ctxt *phy_ctxt;
+	bool band_change_removal;
 	int ret, i;
 
 	IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value,
@@ -3786,19 +3837,30 @@
 	cfg80211_chandef_create(&chandef, channel, NL80211_CHAN_NO_HT);
 
 	/*
-	 * Change the PHY context configuration as it is currently referenced
-	 * only by the P2P Device MAC
+	 * Check if the remain-on-channel is on a different band and that
+	 * requires context removal, see iwl_mvm_phy_ctxt_changed(). If
+	 * so, we'll need to release and then re-configure here, since we
+	 * must not remove a PHY context that's part of a binding.
 	 */
-	if (mvmvif->phy_ctxt->ref == 1) {
+	band_change_removal =
+		fw_has_capa(&mvm->fw->ucode_capa,
+			    IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT) &&
+		mvmvif->phy_ctxt->channel->band != chandef.chan->band;
+
+	if (mvmvif->phy_ctxt->ref == 1 && !band_change_removal) {
+		/*
+		 * Change the PHY context configuration as it is currently
+		 * referenced only by the P2P Device MAC (and we can modify it)
+		 */
 		ret = iwl_mvm_phy_ctxt_changed(mvm, mvmvif->phy_ctxt,
 					       &chandef, 1, 1);
 		if (ret)
 			goto out_unlock;
 	} else {
 		/*
-		 * The PHY context is shared with other MACs. Need to remove the
-		 * P2P Device from the binding, allocate an new PHY context and
-		 * create a new binding
+		 * The PHY context is shared with other MACs (or we're trying to
+		 * switch bands), so remove the P2P Device from the binding,
+		 * allocate an new PHY context and create a new binding.
 		 */
 		phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm);
 		if (!phy_ctxt) {
@@ -4161,6 +4223,9 @@
 	iwl_mvm_binding_remove_vif(mvm, vif);
 
 out:
+	if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_CHANNEL_SWITCH_CMD) &&
+	    switching_chanctx)
+		return;
 	mvmvif->phy_ctxt = NULL;
 	iwl_mvm_power_update_mac(mvm);
 }
@@ -4601,6 +4666,10 @@
 	int i;
 
 	if (!iwl_mvm_has_new_tx_api(mvm)) {
+		/* we can't ask the firmware anything if it is dead */
+		if (test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
+			     &mvm->status))
+			return;
 		if (drop) {
 			mutex_lock(&mvm->mutex);
 			iwl_mvm_flush_tx_path(mvm,
@@ -4682,8 +4751,11 @@
 
 	/* this can take a while, and we may need/want other operations
 	 * to succeed while doing this, so do it without the mutex held
+	 * If the firmware is dead, this can't work...
 	 */
-	if (!drop && !iwl_mvm_has_new_tx_api(mvm))
+	if (!drop && !iwl_mvm_has_new_tx_api(mvm) &&
+	    !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
+		      &mvm->status))
 		iwl_trans_wait_tx_queues_empty(mvm->trans, msk);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -1167,6 +1167,8 @@
  * @IWL_MVM_STATUS_ROC_AUX_RUNNING: AUX remain-on-channel is running
  * @IWL_MVM_STATUS_FIRMWARE_RUNNING: firmware is running
  * @IWL_MVM_STATUS_NEED_FLUSH_P2P: need to flush P2P bcast STA
+ * @IWL_MVM_STATUS_STARTING: starting mac,
+ *	used to disable restart flow while in STARTING state
  */
 enum iwl_mvm_status {
 	IWL_MVM_STATUS_HW_RFKILL,
@@ -1177,6 +1179,7 @@
 	IWL_MVM_STATUS_ROC_AUX_RUNNING,
 	IWL_MVM_STATUS_FIRMWARE_RUNNING,
 	IWL_MVM_STATUS_NEED_FLUSH_P2P,
+	IWL_MVM_STATUS_STARTING,
 };
 
 /* Keep track of completed init configuration */
@@ -1508,8 +1511,8 @@
 int __must_check iwl_mvm_send_cmd_pdu_status(struct iwl_mvm *mvm, u32 id,
 					     u16 len, const void *data,
 					     u32 *status);
-int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
-		   struct ieee80211_sta *sta);
+int iwl_mvm_tx_skb_sta(struct iwl_mvm *mvm, struct sk_buff *skb,
+		       struct ieee80211_sta *sta);
 int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb);
 void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
 			struct iwl_tx_cmd *tx_cmd,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
@@ -281,7 +281,7 @@
 	int regulatory_type;
 
 	/* Checking for required sections */
-	if (mvm->trans->cfg->nvm_type != IWL_NVM_EXT) {
+	if (mvm->trans->cfg->nvm_type == IWL_NVM) {
 		if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data ||
 		    !mvm->nvm_sections[mvm->cfg->nvm_hw_section_num].data) {
 			IWL_ERR(mvm, "Can't parse empty OTP/NVM sections\n");
@@ -309,7 +309,8 @@
 		}
 
 		/* PHY_SKU section is mandatory in B0 */
-		if (!mvm->nvm_sections[NVM_SECTION_TYPE_PHY_SKU].data) {
+		if (mvm->trans->cfg->nvm_type == IWL_NVM_EXT &&
+		    !mvm->nvm_sections[NVM_SECTION_TYPE_PHY_SKU].data) {
 			IWL_ERR(mvm,
 				"Can't parse phy_sku in B0, empty sections\n");
 			return NULL;
@@ -507,6 +508,11 @@
 		struct iwl_mcc_update_resp *mcc_resp = (void *)pkt->data;
 
 		n_channels =  __le32_to_cpu(mcc_resp->n_channels);
+		if (iwl_rx_packet_payload_len(pkt) !=
+		    struct_size(mcc_resp, channels, n_channels)) {
+			resp_cp = ERR_PTR(-EINVAL);
+			goto exit;
+		}
 		resp_len = sizeof(struct iwl_mcc_update_resp) +
 			   n_channels * sizeof(__le32);
 		resp_cp = kmemdup(mcc_resp, resp_len, GFP_KERNEL);
@@ -518,6 +524,11 @@
 		struct iwl_mcc_update_resp_v3 *mcc_resp_v3 = (void *)pkt->data;
 
 		n_channels =  __le32_to_cpu(mcc_resp_v3->n_channels);
+		if (iwl_rx_packet_payload_len(pkt) !=
+		    struct_size(mcc_resp_v3, channels, n_channels)) {
+			resp_cp = ERR_PTR(-EINVAL);
+			goto exit;
+		}
 		resp_len = sizeof(struct iwl_mcc_update_resp) +
 			   n_channels * sizeof(__le32);
 		resp_cp = kzalloc(resp_len, GFP_KERNEL);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
@@ -316,6 +316,12 @@
 		       iwl_mvm_mu_mimo_grp_notif, RX_HANDLER_SYNC),
 	RX_HANDLER_GRP(DATA_PATH_GROUP, STA_PM_NOTIF,
 		       iwl_mvm_sta_pm_notif, RX_HANDLER_SYNC),
+	RX_HANDLER_GRP(MAC_CONF_GROUP, PROBE_RESPONSE_DATA_NOTIF,
+		       iwl_mvm_probe_resp_data_notif,
+		       RX_HANDLER_ASYNC_LOCKED),
+	RX_HANDLER_GRP(MAC_CONF_GROUP, CHANNEL_SWITCH_NOA_NOTIF,
+		       iwl_mvm_channel_switch_noa_notif,
+		       RX_HANDLER_SYNC),
 };
 #undef RX_HANDLER
 #undef RX_HANDLER_GRP
@@ -667,7 +673,7 @@
 		op_mode->ops = &iwl_mvm_ops_mq;
 		trans->rx_mpdu_cmd_hdr_size =
 			(trans->trans_cfg->device_family >=
-			 IWL_DEVICE_FAMILY_22560) ?
+			 IWL_DEVICE_FAMILY_AX210) ?
 			sizeof(struct iwl_rx_mpdu_desc) :
 			IWL_RX_DESC_SIZE_V1;
 	} else {
@@ -681,10 +687,26 @@
 
 	mvm->fw_restart = iwlwifi_mod_params.fw_restart ? -1 : 0;
 
-	mvm->aux_queue = IWL_MVM_DQA_AUX_QUEUE;
-	mvm->snif_queue = IWL_MVM_DQA_INJECT_MONITOR_QUEUE;
-	mvm->probe_queue = IWL_MVM_DQA_AP_PROBE_RESP_QUEUE;
-	mvm->p2p_dev_queue = IWL_MVM_DQA_P2P_DEVICE_QUEUE;
+	if (iwl_mvm_has_new_tx_api(mvm)) {
+		/*
+		 * If we have the new TX/queue allocation API initialize them
+		 * all to invalid numbers. We'll rewrite the ones that we need
+		 * later, but that doesn't happen for all of them all of the
+		 * time (e.g. P2P Device is optional), and if a dynamic queue
+		 * ends up getting number 2 (IWL_MVM_DQA_P2P_DEVICE_QUEUE) then
+		 * iwl_mvm_is_static_queue() erroneously returns true, and we
+		 * might have things getting stuck.
+		 */
+		mvm->aux_queue = IWL_MVM_INVALID_QUEUE;
+		mvm->snif_queue = IWL_MVM_INVALID_QUEUE;
+		mvm->probe_queue = IWL_MVM_INVALID_QUEUE;
+		mvm->p2p_dev_queue = IWL_MVM_INVALID_QUEUE;
+	} else {
+		mvm->aux_queue = IWL_MVM_DQA_AUX_QUEUE;
+		mvm->snif_queue = IWL_MVM_DQA_INJECT_MONITOR_QUEUE;
+		mvm->probe_queue = IWL_MVM_DQA_AP_PROBE_RESP_QUEUE;
+		mvm->p2p_dev_queue = IWL_MVM_DQA_P2P_DEVICE_QUEUE;
+	}
 
 	mvm->sf_state = SF_UNINIT;
 	if (iwl_mvm_has_unified_ucode(mvm))
@@ -730,7 +752,7 @@
 	trans_cfg.no_reclaim_cmds = no_reclaim_cmds;
 	trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds);
 
-	if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22560)
+	if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
 		rb_size_default = IWL_AMSDU_2K;
 	else
 		rb_size_default = IWL_AMSDU_4K;
@@ -756,7 +778,7 @@
 
 	trans->wide_cmd_header = true;
 	trans_cfg.bc_table_dword =
-		mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_22560;
+		mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210;
 
 	trans_cfg.command_groups = iwl_mvm_groups;
 	trans_cfg.command_groups_size = ARRAY_SIZE(iwl_mvm_groups);
@@ -832,6 +854,10 @@
 	if (!mvm->scan_cmd)
 		goto out_free;
 
+	/* invalidate ids to prevent accidental removal of sta_id 0 */
+	mvm->aux_sta.sta_id = IWL_MVM_INVALID_STA;
+	mvm->snif_sta.sta_id = IWL_MVM_INVALID_STA;
+
 	/* Set EBS as successful as long as not stated otherwise by the FW. */
 	mvm->last_ebs_successful = true;
 
@@ -1141,8 +1167,11 @@
 		mvmtxq = iwl_mvm_txq_from_mac80211(txq);
 		mvmtxq->stopped = !start;
 
-		if (start && mvmsta->sta_state != IEEE80211_STA_NOTEXIST)
+		if (start && mvmsta->sta_state != IEEE80211_STA_NOTEXIST) {
+			local_bh_disable();
 			iwl_mvm_mac_itxq_xmit(mvm->hw, txq);
+			local_bh_enable();
+		}
 	}
 
 out:
@@ -1232,6 +1261,7 @@
 	reprobe = container_of(wk, struct iwl_mvm_reprobe, work);
 	if (device_reprobe(reprobe->dev))
 		dev_err(reprobe->dev, "reprobe failed!\n");
+	put_device(reprobe->dev);
 	kfree(reprobe);
 	module_put(THIS_MODULE);
 }
@@ -1261,6 +1291,9 @@
 	 */
 	if (!mvm->fw_restart && fw_error) {
 		iwl_fw_error_collect(&mvm->fwrt);
+	} else if (test_bit(IWL_MVM_STATUS_STARTING,
+			    &mvm->status)) {
+		IWL_ERR(mvm, "Starting mac, retry will be triggered anyway\n");
 	} else if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
 		struct iwl_mvm_reprobe *reprobe;
 
@@ -1282,7 +1315,7 @@
 			module_put(THIS_MODULE);
 			return;
 		}
-		reprobe->dev = mvm->trans->dev;
+		reprobe->dev = get_device(mvm->trans->dev);
 		INIT_WORK(&reprobe->work, iwl_mvm_reprobe_wk);
 		schedule_work(&reprobe->work);
 	} else if (test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/mvm/power.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/mvm/power.c
@@ -626,6 +626,9 @@
 	struct iwl_power_vifs *power_iterator = _data;
 	bool active = mvmvif->phy_ctxt && mvmvif->phy_ctxt->id < NUM_PHY_CTX;
 
+	if (!mvmvif->uploaded)
+		return;
+
 	switch (ieee80211_vif_type_p2p(vif)) {
 	case NL80211_IFTYPE_P2P_DEVICE:
 		break;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
@@ -6,7 +6,7 @@
  * GPL LICENSE SUMMARY
  *
  * Copyright(c) 2017        Intel Deutschland GmbH
- * Copyright(c) 2018 - 2019 Intel Corporation
+ * Copyright(c) 2018 - 2020 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
@@ -27,7 +27,7 @@
  * BSD LICENSE
  *
  * Copyright(c) 2017        Intel Deutschland GmbH
- * Copyright(c) 2018 - 2019 Intel Corporation
+ * Copyright(c) 2018 - 2020 Intel Corporation
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -147,7 +147,11 @@
 	     (vht_ena && (vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC))))
 		flags |= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK;
 
-	/* consider our LDPC support in case of HE */
+	/* consider LDPC support in case of HE */
+	if (he_cap->has_he && (he_cap->he_cap_elem.phy_cap_info[1] &
+	    IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD))
+		flags |= IWL_TLC_MNG_CFG_FLAGS_LDPC_MSK;
+
 	if (sband->iftype_data && sband->iftype_data->he_cap.has_he &&
 	    !(sband->iftype_data->he_cap.he_cap_elem.phy_cap_info[1] &
 	     IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD))
@@ -191,11 +195,13 @@
 {
 	u16 supp;
 	int i, highest_mcs;
+	u8 nss = sta->rx_nss;
 
-	for (i = 0; i < sta->rx_nss; i++) {
-		if (i == IWL_TLC_NSS_MAX)
-			break;
+	/* the station support only a single receive chain */
+	if (sta->smps_mode == IEEE80211_SMPS_STATIC)
+		nss = 1;
 
+	for (i = 0; i < nss && i < IWL_TLC_NSS_MAX; i++) {
 		highest_mcs = rs_fw_vht_highest_rx_mcs_index(vht_cap, i + 1);
 		if (!highest_mcs)
 			continue;
@@ -241,8 +247,13 @@
 	u16 tx_mcs_160 =
 		le16_to_cpu(sband->iftype_data->he_cap.he_mcs_nss_supp.tx_mcs_160);
 	int i;
+	u8 nss = sta->rx_nss;
+
+	/* the station support only a single receive chain */
+	if (sta->smps_mode == IEEE80211_SMPS_STATIC)
+		nss = 1;
 
-	for (i = 0; i < sta->rx_nss && i < IWL_TLC_NSS_MAX; i++) {
+	for (i = 0; i < nss && i < IWL_TLC_NSS_MAX; i++) {
 		u16 _mcs_160 = (mcs_160 >> (2 * i)) & 0x3;
 		u16 _mcs_80 = (mcs_80 >> (2 * i)) & 0x3;
 		u16 _tx_mcs_160 = (tx_mcs_160 >> (2 * i)) & 0x3;
@@ -303,8 +314,14 @@
 		cmd->mode = IWL_TLC_MNG_MODE_HT;
 		cmd->ht_rates[IWL_TLC_NSS_1][IWL_TLC_HT_BW_NONE_160] =
 			cpu_to_le16(ht_cap->mcs.rx_mask[0]);
-		cmd->ht_rates[IWL_TLC_NSS_2][IWL_TLC_HT_BW_NONE_160] =
-			cpu_to_le16(ht_cap->mcs.rx_mask[1]);
+
+		/* the station support only a single receive chain */
+		if (sta->smps_mode == IEEE80211_SMPS_STATIC)
+			cmd->ht_rates[IWL_TLC_NSS_2][IWL_TLC_HT_BW_NONE_160] =
+				0;
+		else
+			cmd->ht_rates[IWL_TLC_NSS_2][IWL_TLC_HT_BW_NONE_160] =
+				cpu_to_le16(ht_cap->mcs.rx_mask[1]);
 	}
 }
 
@@ -350,8 +367,15 @@
 		u16 size = le32_to_cpu(notif->amsdu_size);
 		int i;
 
-		if (WARN_ON(sta->max_amsdu_len < size))
+		if (sta->max_amsdu_len < size) {
+			/*
+			 * In debug sta->max_amsdu_len < size
+			 * so also check with orig_amsdu_len which holds the
+			 * original data before debugfs changed the value
+			 */
+			WARN_ON(mvmsta->orig_amsdu_len < size);
 			goto out;
+		}
 
 		mvmsta->amsdu_enabled = le32_to_cpu(notif->amsdu_enabled);
 		mvmsta->max_amsdu_len = size;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
@@ -3663,7 +3663,7 @@
 			cpu_to_le16(iwl_mvm_coex_agg_time_limit(mvm, sta));
 }
 
-static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
+static void *rs_alloc(struct ieee80211_hw *hw)
 {
 	return hw->priv;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/mvm/rs.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/mvm/rs.h
@@ -133,13 +133,8 @@
 
 #define LINK_QUAL_AGG_FRAME_LIMIT_DEF	(63)
 #define LINK_QUAL_AGG_FRAME_LIMIT_MAX	(63)
-/*
- * FIXME - various places in firmware API still use u8,
- * e.g. LQ command and SCD config command.
- * This should be 256 instead.
- */
-#define LINK_QUAL_AGG_FRAME_LIMIT_GEN2_DEF	(255)
-#define LINK_QUAL_AGG_FRAME_LIMIT_GEN2_MAX	(255)
+#define LINK_QUAL_AGG_FRAME_LIMIT_GEN2_DEF	(64)
+#define LINK_QUAL_AGG_FRAME_LIMIT_GEN2_MAX	(64)
 #define LINK_QUAL_AGG_FRAME_LIMIT_MIN	(0)
 
 #define LQ_SIZE		2	/* 2 mode tables:  "Active" and "Search" */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/mvm/rx.c
@@ -8,7 +8,7 @@
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 - 2019 Intel Corporation
+ * Copyright(c) 2018 - 2020 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
@@ -31,7 +31,7 @@
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright(c) 2018 - 2019 Intel Corporation
+ * Copyright(c) 2018 - 2020 Intel Corporation
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -60,6 +60,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *****************************************************************************/
+#include <asm/unaligned.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include "iwl-trans.h"
@@ -357,7 +358,7 @@
 	rx_res = (struct iwl_rx_mpdu_res_start *)pkt->data;
 	hdr = (struct ieee80211_hdr *)(pkt->data + sizeof(*rx_res));
 	len = le16_to_cpu(rx_res->byte_count);
-	rx_pkt_status = le32_to_cpup((__le32 *)
+	rx_pkt_status = get_unaligned_le32((__le32 *)
 		(pkt->data + sizeof(*rx_res) + len));
 
 	/* Dont use dev_alloc_skb(), we'll have enough headroom once
@@ -565,6 +566,7 @@
 
 struct iwl_mvm_stat_data {
 	struct iwl_mvm *mvm;
+	__le32 flags;
 	__le32 mac_id;
 	u8 beacon_filter_average_energy;
 	void *general;
@@ -605,6 +607,13 @@
 			-general->beacon_average_energy[vif_id];
 	}
 
+	/* make sure that beacon statistics don't go backwards with TCM
+	 * request to clear statistics
+	 */
+	if (le32_to_cpu(data->flags) & IWL_STATISTICS_REPLY_FLG_CLEAR)
+		mvmvif->beacon_stats.accu_num_beacons +=
+			mvmvif->beacon_stats.num_beacons;
+
 	if (mvmvif->id != id)
 		return;
 
@@ -762,6 +771,7 @@
 
 		flags = stats->flag;
 	}
+	data.flags = flags;
 
 	iwl_mvm_rx_stats_check_trigger(mvm, pkt);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
@@ -177,12 +177,39 @@
 	struct iwl_rx_mpdu_desc *desc = (void *)pkt->data;
 	unsigned int headlen, fraglen, pad_len = 0;
 	unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control);
+	u8 mic_crc_len = u8_get_bits(desc->mac_flags1,
+				     IWL_RX_MPDU_MFLG1_MIC_CRC_LEN_MASK) << 1;
 
 	if (desc->mac_flags2 & IWL_RX_MPDU_MFLG2_PAD) {
 		len -= 2;
 		pad_len = 2;
 	}
 
+	/*
+	 * For non monitor interface strip the bytes the RADA might not have
+	 * removed. As monitor interface cannot exist with other interfaces
+	 * this removal is safe.
+	 */
+	if (mic_crc_len && !ieee80211_hw_check(mvm->hw, RX_INCLUDES_FCS)) {
+		u32 pkt_flags = le32_to_cpu(pkt->len_n_flags);
+
+		/*
+		 * If RADA was not enabled then decryption was not performed so
+		 * the MIC cannot be removed.
+		 */
+		if (!(pkt_flags & FH_RSCSR_RADA_EN)) {
+			if (WARN_ON(crypt_len > mic_crc_len))
+				return -EINVAL;
+
+			mic_crc_len -= crypt_len;
+		}
+
+		if (WARN_ON(mic_crc_len > len))
+			return -EINVAL;
+
+		len -= mic_crc_len;
+	}
+
 	/* If frame is small enough to fit in skb->head, pull it completely.
 	 * If not, only pull ieee80211_hdr (including crypto if present, and
 	 * an additional 8 bytes for SNAP/ethertype, see below) so that
@@ -514,14 +541,17 @@
 
 static void iwl_mvm_sync_nssn(struct iwl_mvm *mvm, u8 baid, u16 nssn)
 {
-	struct iwl_mvm_rss_sync_notif notif = {
-		.metadata.type = IWL_MVM_RXQ_NSSN_SYNC,
-		.metadata.sync = 0,
-		.nssn_sync.baid = baid,
-		.nssn_sync.nssn = nssn,
-	};
+	if (IWL_MVM_USE_NSSN_SYNC) {
+		struct iwl_mvm_rss_sync_notif notif = {
+			.metadata.type = IWL_MVM_RXQ_NSSN_SYNC,
+			.metadata.sync = 0,
+			.nssn_sync.baid = baid,
+			.nssn_sync.nssn = nssn,
+		};
 
-	iwl_mvm_sync_rx_queues_internal(mvm, (void *)&notif, sizeof(notif));
+		iwl_mvm_sync_rx_queues_internal(mvm, (void *)&notif,
+						sizeof(notif));
+	}
 }
 
 #define RX_REORDER_BUF_TIMEOUT_MQ (HZ / 10)
@@ -1565,7 +1595,7 @@
 	if (unlikely(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)))
 		return;
 
-	if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
+	if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
 		rate_n_flags = le32_to_cpu(desc->v3.rate_n_flags);
 		channel = desc->v3.channel;
 		gp2_on_air_rise = le32_to_cpu(desc->v3.gp2_on_air_rise);
@@ -1667,7 +1697,7 @@
 		u64 tsf_on_air_rise;
 
 		if (mvm->trans->trans_cfg->device_family >=
-		    IWL_DEVICE_FAMILY_22560)
+		    IWL_DEVICE_FAMILY_AX210)
 			tsf_on_air_rise = le64_to_cpu(desc->v3.tsf_on_air_rise);
 		else
 			tsf_on_air_rise = le64_to_cpu(desc->v1.tsf_on_air_rise);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
@@ -93,6 +93,8 @@
 /* adaptive dwell default APs number in social channels (1, 6, 11) */
 #define IWL_SCAN_ADWELL_DEFAULT_N_APS_SOCIAL 10
 
+#define WFA_TPC_IE_LEN	9
+
 struct iwl_mvm_scan_timing_params {
 	u32 suspend_time;
 	u32 max_out_time;
@@ -378,8 +380,8 @@
 
 	max_probe_len = SCAN_OFFLOAD_PROBE_REQ_SIZE;
 
-	/* we create the 802.11 header and SSID element */
-	max_probe_len -= 24 + 2;
+	/* we create the 802.11 header SSID element and WFA TPC element */
+	max_probe_len -= 24 + 2 + WFA_TPC_IE_LEN;
 
 	/* DS parameter set element is added on 2.4GHZ band if required */
 	if (iwl_mvm_rrm_scan_needed(mvm))
@@ -776,8 +778,6 @@
 	return newpos;
 }
 
-#define WFA_TPC_IE_LEN	9
-
 static void iwl_mvm_add_tpc_report_ie(u8 *pos)
 {
 	pos[0] = WLAN_EID_VENDOR_SPECIFIC;
@@ -1220,7 +1220,7 @@
 		cmd_size = sizeof(struct iwl_scan_config_v2);
 	else
 		cmd_size = sizeof(struct iwl_scan_config_v1);
-	cmd_size += num_channels;
+	cmd_size += mvm->fw->ucode_capa.n_scan_channels;
 
 	cfg = kzalloc(cmd_size, GFP_KERNEL);
 	if (!cfg)
@@ -1339,7 +1339,7 @@
 		if (IWL_MVM_ADWELL_MAX_BUDGET)
 			cmd->v7.adwell_max_budget =
 				cpu_to_le16(IWL_MVM_ADWELL_MAX_BUDGET);
-		else if (params->ssids && params->ssids[0].ssid_len)
+		else if (params->n_ssids && params->ssids[0].ssid_len)
 			cmd->v7.adwell_max_budget =
 				cpu_to_le16(IWL_SCAN_ADWELL_MAX_BUDGET_DIRECTED_SCAN);
 		else
@@ -1700,7 +1700,7 @@
 	return -EIO;
 }
 
-#define SCAN_TIMEOUT 20000
+#define SCAN_TIMEOUT 30000
 
 void iwl_mvm_scan_timeout_wk(struct work_struct *work)
 {
@@ -2140,7 +2140,7 @@
 	if (!(mvm->scan_status & type))
 		return 0;
 
-	if (iwl_mvm_is_radio_killed(mvm)) {
+	if (!test_bit(STATUS_DEVICE_ENABLED, &mvm->trans->status)) {
 		ret = 0;
 		goto out;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -346,8 +346,9 @@
 }
 
 static int iwl_mvm_disable_txq(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
-			       int queue, u8 tid, u8 flags)
+			       u16 *queueptr, u8 tid, u8 flags)
 {
+	int queue = *queueptr;
 	struct iwl_scd_txq_cfg_cmd cmd = {
 		.scd_queue = queue,
 		.action = SCD_CFG_DISABLE_QUEUE,
@@ -356,6 +357,7 @@
 
 	if (iwl_mvm_has_new_tx_api(mvm)) {
 		iwl_trans_txq_free(mvm->trans, queue);
+		*queueptr = IWL_MVM_INVALID_QUEUE;
 
 		return 0;
 	}
@@ -517,6 +519,7 @@
 	u8 sta_id, tid;
 	unsigned long disable_agg_tids = 0;
 	bool same_sta;
+	u16 queue_tmp = queue;
 	int ret;
 
 	lockdep_assert_held(&mvm->mutex);
@@ -539,7 +542,7 @@
 		iwl_mvm_invalidate_sta_queue(mvm, queue,
 					     disable_agg_tids, false);
 
-	ret = iwl_mvm_disable_txq(mvm, old_sta, queue, tid, 0);
+	ret = iwl_mvm_disable_txq(mvm, old_sta, &queue_tmp, tid, 0);
 	if (ret) {
 		IWL_ERR(mvm,
 			"Failed to free inactive queue %d (ret=%d)\n",
@@ -722,6 +725,11 @@
 
 	lockdep_assert_held(&mvm->mutex);
 
+	if (WARN(maxq >= mvm->trans->trans_cfg->base_params->num_of_queues,
+		 "max queue %d >= num_of_queues (%d)", maxq,
+		 mvm->trans->trans_cfg->base_params->num_of_queues))
+		maxq = mvm->trans->trans_cfg->base_params->num_of_queues - 1;
+
 	/* This should not be hit with new TX path */
 	if (WARN_ON(iwl_mvm_has_new_tx_api(mvm)))
 		return -ENOSPC;
@@ -1164,9 +1172,9 @@
 						   inactive_tid_bitmap,
 						   &unshare_queues,
 						   &changetid_queues);
-		if (ret >= 0 && free_queue < 0) {
+		if (ret && free_queue < 0) {
 			queue_owner = sta;
-			free_queue = ret;
+			free_queue = i;
 		}
 		/* only unlock sta lock - we still need the queue info lock */
 		spin_unlock_bh(&mvmsta->lock);
@@ -1179,17 +1187,15 @@
 	for_each_set_bit(i, &changetid_queues, IWL_MAX_HW_QUEUES)
 		iwl_mvm_change_queue_tid(mvm, i);
 
+	rcu_read_unlock();
+
 	if (free_queue >= 0 && alloc_for_sta != IWL_MVM_INVALID_STA) {
 		ret = iwl_mvm_free_inactive_queue(mvm, free_queue, queue_owner,
 						  alloc_for_sta);
-		if (ret) {
-			rcu_read_unlock();
+		if (ret)
 			return ret;
-		}
 	}
 
-	rcu_read_unlock();
-
 	return free_queue;
 }
 
@@ -1206,6 +1212,7 @@
 	unsigned int wdg_timeout =
 		iwl_mvm_get_wd_timeout(mvm, mvmsta->vif, false, false);
 	int queue = -1;
+	u16 queue_tmp;
 	unsigned long disable_agg_tids = 0;
 	enum iwl_mvm_agg_state queue_state;
 	bool shared_queue = false, inc_ssn;
@@ -1354,7 +1361,8 @@
 	return 0;
 
 out_err:
-	iwl_mvm_disable_txq(mvm, sta, queue, tid, 0);
+	queue_tmp = queue;
+	iwl_mvm_disable_txq(mvm, sta, &queue_tmp, tid, 0);
 
 	return ret;
 }
@@ -1792,7 +1800,7 @@
 		if (mvm_sta->tid_data[i].txq_id == IWL_MVM_INVALID_QUEUE)
 			continue;
 
-		iwl_mvm_disable_txq(mvm, sta, mvm_sta->tid_data[i].txq_id, i,
+		iwl_mvm_disable_txq(mvm, sta, &mvm_sta->tid_data[i].txq_id, i,
 				    0);
 		mvm_sta->tid_data[i].txq_id = IWL_MVM_INVALID_QUEUE;
 	}
@@ -1802,6 +1810,7 @@
 			iwl_mvm_txq_from_mac80211(sta->txq[i]);
 
 		mvmtxq->txq_id = IWL_MVM_INVALID_QUEUE;
+		list_del_init(&mvmtxq->list);
 	}
 }
 
@@ -2002,7 +2011,7 @@
 	ret = iwl_mvm_add_int_sta_common(mvm, sta, NULL, macidx, maccolor);
 	if (ret) {
 		if (!iwl_mvm_has_new_tx_api(mvm))
-			iwl_mvm_disable_txq(mvm, NULL, *queue,
+			iwl_mvm_disable_txq(mvm, NULL, queue,
 					    IWL_MAX_TID_COUNT, 0);
 		return ret;
 	}
@@ -2067,7 +2076,10 @@
 
 	lockdep_assert_held(&mvm->mutex);
 
-	iwl_mvm_disable_txq(mvm, NULL, mvm->snif_queue, IWL_MAX_TID_COUNT, 0);
+	if (WARN_ON_ONCE(mvm->snif_sta.sta_id == IWL_MVM_INVALID_STA))
+		return -EINVAL;
+
+	iwl_mvm_disable_txq(mvm, NULL, &mvm->snif_queue, IWL_MAX_TID_COUNT, 0);
 	ret = iwl_mvm_rm_sta_common(mvm, mvm->snif_sta.sta_id);
 	if (ret)
 		IWL_WARN(mvm, "Failed sending remove station\n");
@@ -2075,16 +2087,27 @@
 	return ret;
 }
 
-void iwl_mvm_dealloc_snif_sta(struct iwl_mvm *mvm)
+int iwl_mvm_rm_aux_sta(struct iwl_mvm *mvm)
 {
-	iwl_mvm_dealloc_int_sta(mvm, &mvm->snif_sta);
-}
+	int ret;
 
-void iwl_mvm_del_aux_sta(struct iwl_mvm *mvm)
-{
 	lockdep_assert_held(&mvm->mutex);
 
+	if (WARN_ON_ONCE(mvm->aux_sta.sta_id == IWL_MVM_INVALID_STA))
+		return -EINVAL;
+
+	iwl_mvm_disable_txq(mvm, NULL, &mvm->aux_queue, IWL_MAX_TID_COUNT, 0);
+	ret = iwl_mvm_rm_sta_common(mvm, mvm->aux_sta.sta_id);
+	if (ret)
+		IWL_WARN(mvm, "Failed sending remove station\n");
 	iwl_mvm_dealloc_int_sta(mvm, &mvm->aux_sta);
+
+	return ret;
+}
+
+void iwl_mvm_dealloc_snif_sta(struct iwl_mvm *mvm)
+{
+	iwl_mvm_dealloc_int_sta(mvm, &mvm->snif_sta);
 }
 
 /*
@@ -2169,7 +2192,7 @@
 					  struct ieee80211_vif *vif)
 {
 	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-	int queue;
+	u16 *queueptr, queue;
 
 	lockdep_assert_held(&mvm->mutex);
 
@@ -2178,10 +2201,10 @@
 	switch (vif->type) {
 	case NL80211_IFTYPE_AP:
 	case NL80211_IFTYPE_ADHOC:
-		queue = mvm->probe_queue;
+		queueptr = &mvm->probe_queue;
 		break;
 	case NL80211_IFTYPE_P2P_DEVICE:
-		queue = mvm->p2p_dev_queue;
+		queueptr = &mvm->p2p_dev_queue;
 		break;
 	default:
 		WARN(1, "Can't free bcast queue on vif type %d\n",
@@ -2189,7 +2212,8 @@
 		return;
 	}
 
-	iwl_mvm_disable_txq(mvm, NULL, queue, IWL_MAX_TID_COUNT, 0);
+	queue = *queueptr;
+	iwl_mvm_disable_txq(mvm, NULL, queueptr, IWL_MAX_TID_COUNT, 0);
 	if (iwl_mvm_has_new_tx_api(mvm))
 		return;
 
@@ -2424,7 +2448,7 @@
 
 	iwl_mvm_flush_sta(mvm, &mvmvif->mcast_sta, true, 0);
 
-	iwl_mvm_disable_txq(mvm, NULL, mvmvif->cab_queue, 0, 0);
+	iwl_mvm_disable_txq(mvm, NULL, &mvmvif->cab_queue, 0, 0);
 
 	ret = iwl_mvm_rm_sta_common(mvm, mvmvif->mcast_sta.sta_id);
 	if (ret)
@@ -2533,7 +2557,7 @@
 	}
 
 	if (iwl_mvm_has_new_rx_api(mvm) && start) {
-		u16 reorder_buf_size = buf_size * sizeof(baid_data->entries[0]);
+		u32 reorder_buf_size = buf_size * sizeof(baid_data->entries[0]);
 
 		/* sparse doesn't like the __align() so don't check */
 #ifndef __CHECKER__
@@ -2844,13 +2868,12 @@
 
 	if (normalized_ssn == tid_data->next_reclaimed) {
 		tid_data->state = IWL_AGG_STARTING;
-		ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+		ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
 	} else {
 		tid_data->state = IWL_EMPTYING_HW_QUEUE_ADDBA;
+		ret = 0;
 	}
 
-	ret = 0;
-
 out:
 	spin_unlock_bh(&mvmsta->lock);
 
@@ -3321,6 +3344,10 @@
 	igtk_cmd.sta_id = cpu_to_le32(sta_id);
 
 	if (remove_key) {
+		/* This is a valid situation for IGTK */
+		if (sta_id == IWL_MVM_INVALID_STA)
+			return 0;
+
 		igtk_cmd.ctrl_flags |= cpu_to_le32(STA_KEY_NOT_VALID);
 	} else {
 		struct ieee80211_key_seq seq;
@@ -3575,9 +3602,9 @@
 	IWL_DEBUG_WEP(mvm, "mvm remove dynamic key: idx=%d sta=%d\n",
 		      keyconf->keyidx, sta_id);
 
-	if (mvm_sta && (keyconf->cipher == WLAN_CIPHER_SUITE_AES_CMAC ||
-			keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 ||
-			keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256))
+	if (keyconf->cipher == WLAN_CIPHER_SUITE_AES_CMAC ||
+	    keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 ||
+	    keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256)
 		return iwl_mvm_send_sta_igtk(mvm, keyconf, sta_id, true);
 
 	if (!__test_and_clear_bit(keyconf->hw_key_idx, mvm->fw_key_table)) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
@@ -8,7 +8,7 @@
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
  * Copyright(c) 2015 - 2016 Intel Deutschland GmbH
- * Copyright(c) 2018 - 2019 Intel Corporation
+ * Copyright(c) 2018 - 2020 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
@@ -31,7 +31,7 @@
  * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
  * Copyright(c) 2015 - 2016 Intel Deutschland GmbH
- * Copyright(c) 2018 - 2019 Intel Corporation
+ * Copyright(c) 2018 - 2020 Intel Corporation
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -541,7 +541,7 @@
 		       int tid, u8 queue, bool start);
 
 int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm);
-void iwl_mvm_del_aux_sta(struct iwl_mvm *mvm);
+int iwl_mvm_rm_aux_sta(struct iwl_mvm *mvm);
 
 int iwl_mvm_alloc_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
 int iwl_mvm_send_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
@@ -731,7 +731,8 @@
 static void iwl_mvm_thermal_zone_register(struct iwl_mvm *mvm)
 {
 	int i;
-	char name[] = "iwlwifi";
+	char name[16];
+	static atomic_t counter = ATOMIC_INIT(0);
 
 	if (!iwl_mvm_is_tt_in_fw(mvm)) {
 		mvm->tz_device.tzone = NULL;
@@ -741,6 +742,7 @@
 
 	BUILD_BUG_ON(ARRAY_SIZE(name) >= THERMAL_NAME_LENGTH);
 
+	sprintf(name, "iwlwifi_%u", atomic_inc_return(&counter) & 0xFF);
 	mvm->tz_device.tzone = thermal_zone_device_register(name,
 							IWL_MAX_DTS_TRIPS,
 							IWL_WRITABLE_TRIPS_MSK,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -487,13 +487,13 @@
 /*
  * Allocates and sets the Tx cmd the driver data pointers in the skb
  */
-static struct iwl_device_cmd *
+static struct iwl_device_tx_cmd *
 iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
 		      struct ieee80211_tx_info *info, int hdrlen,
 		      struct ieee80211_sta *sta, u8 sta_id)
 {
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-	struct iwl_device_cmd *dev_cmd;
+	struct iwl_device_tx_cmd *dev_cmd;
 	struct iwl_tx_cmd *tx_cmd;
 
 	dev_cmd = iwl_trans_alloc_tx_cmd(mvm->trans);
@@ -501,11 +501,6 @@
 	if (unlikely(!dev_cmd))
 		return NULL;
 
-	/* Make sure we zero enough of dev_cmd */
-	BUILD_BUG_ON(sizeof(struct iwl_tx_cmd_gen2) > sizeof(*tx_cmd));
-	BUILD_BUG_ON(sizeof(struct iwl_tx_cmd_gen3) > sizeof(*tx_cmd));
-
-	memset(dev_cmd, 0, sizeof(dev_cmd->hdr) + sizeof(*tx_cmd));
 	dev_cmd->hdr.cmd = TX_CMD;
 
 	if (iwl_mvm_has_new_tx_api(mvm)) {
@@ -534,20 +529,24 @@
 			flags |= IWL_TX_FLAGS_ENCRYPT_DIS;
 
 		/*
-		 * For data packets rate info comes from the fw. Only
-		 * set rate/antenna during connection establishment or in case
-		 * no station is given.
+		 * For data and mgmt packets rate info comes from the fw. Only
+		 * set rate/antenna for injected frames with fixed rate, or
+		 * when no sta is given.
 		 */
-		if (!sta || !ieee80211_is_data(hdr->frame_control) ||
-		    mvmsta->sta_state < IEEE80211_STA_AUTHORIZED) {
+		if (unlikely(!sta ||
+			     info->control.flags & IEEE80211_TX_CTRL_RATE_INJECT)) {
 			flags |= IWL_TX_FLAGS_CMD_RATE;
 			rate_n_flags =
 				iwl_mvm_get_tx_rate_n_flags(mvm, info, sta,
 							    hdr->frame_control);
+		} else if (!ieee80211_is_data(hdr->frame_control) ||
+			   mvmsta->sta_state < IEEE80211_STA_AUTHORIZED) {
+			/* These are important frames */
+			flags |= IWL_TX_FLAGS_HIGH_PRI;
 		}
 
 		if (mvm->trans->trans_cfg->device_family >=
-		    IWL_DEVICE_FAMILY_22560) {
+		    IWL_DEVICE_FAMILY_AX210) {
 			struct iwl_tx_cmd_gen3 *cmd = (void *)dev_cmd->payload;
 
 			cmd->offload_assist |= cpu_to_le32(offload_assist);
@@ -594,7 +593,7 @@
 }
 
 static void iwl_mvm_skb_prepare_status(struct sk_buff *skb,
-				       struct iwl_device_cmd *cmd)
+				       struct iwl_device_tx_cmd *cmd)
 {
 	struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb);
 
@@ -713,7 +712,7 @@
 {
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 	struct ieee80211_tx_info info;
-	struct iwl_device_cmd *dev_cmd;
+	struct iwl_device_tx_cmd *dev_cmd;
 	u8 sta_id;
 	int hdrlen = ieee80211_hdrlen(hdr->frame_control);
 	__le16 fc = hdr->frame_control;
@@ -935,7 +934,12 @@
 	    !(mvmsta->amsdu_enabled & BIT(tid)))
 		return iwl_mvm_tx_tso_segment(skb, 1, netdev_flags, mpdus_skb);
 
-	max_amsdu_len = iwl_mvm_max_amsdu_size(mvm, sta, tid);
+	/*
+	 * Take the min of ieee80211 station and mvm station
+	 */
+	max_amsdu_len =
+		min_t(unsigned int, sta->max_amsdu_len,
+		      iwl_mvm_max_amsdu_size(mvm, sta, tid));
 
 	/*
 	 * Limit A-MSDU in A-MPDU to 4095 bytes when VHT is not
@@ -1070,7 +1074,7 @@
 {
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 	struct iwl_mvm_sta *mvmsta;
-	struct iwl_device_cmd *dev_cmd;
+	struct iwl_device_tx_cmd *dev_cmd;
 	__le16 fc;
 	u16 seq_number = 0;
 	u8 tid = IWL_MAX_TID_COUNT;
@@ -1091,6 +1095,9 @@
 	if (WARN_ON_ONCE(mvmsta->sta_id == IWL_MVM_INVALID_STA))
 		return -1;
 
+	if (unlikely(ieee80211_is_any_nullfunc(fc)) && sta->he_cap.has_he)
+		return -1;
+
 	if (unlikely(ieee80211_is_probe_resp(fc)))
 		iwl_mvm_probe_resp_set_noa(mvm, skb);
 
@@ -1146,7 +1153,7 @@
 	if (WARN_ONCE(txq_id == IWL_MVM_INVALID_QUEUE, "Invalid TXQ id")) {
 		iwl_trans_free_tx_cmd(mvm->trans, dev_cmd);
 		spin_unlock(&mvmsta->lock);
-		return 0;
+		return -1;
 	}
 
 	if (!iwl_mvm_has_new_tx_api(mvm)) {
@@ -1198,14 +1205,15 @@
 	return -1;
 }
 
-int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
-		   struct ieee80211_sta *sta)
+int iwl_mvm_tx_skb_sta(struct iwl_mvm *mvm, struct sk_buff *skb,
+		       struct ieee80211_sta *sta)
 {
 	struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
 	struct ieee80211_tx_info info;
 	struct sk_buff_head mpdus_skbs;
 	unsigned int payload_len;
 	int ret;
+	struct sk_buff *orig_skb = skb;
 
 	if (WARN_ON_ONCE(!mvmsta))
 		return -1;
@@ -1238,8 +1246,17 @@
 
 		ret = iwl_mvm_tx_mpdu(mvm, skb, &info, sta);
 		if (ret) {
+			/* Free skbs created as part of TSO logic that have not yet been dequeued */
 			__skb_queue_purge(&mpdus_skbs);
-			return ret;
+			/* skb here is not necessarily same as skb that entered this method,
+			 * so free it explicitly.
+			 */
+			if (skb == orig_skb)
+				ieee80211_free_txskb(mvm->hw, skb);
+			else
+				kfree_skb(skb);
+			/* there was error, but we consumed skb one way or another, so return 0 */
+			return 0;
 		}
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/mvm/utils.c
@@ -758,6 +758,9 @@
 
 	lockdep_assert_held(&mvm->mutex);
 
+	if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM)
+		return false;
+
 	if (num_of_ant(iwl_mvm_get_valid_rx_ant(mvm)) == 1)
 		return false;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c
@@ -63,7 +63,6 @@
 	struct iwl_prph_scratch *prph_scratch;
 	struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl;
 	struct iwl_prph_info *prph_info;
-	void *iml_img;
 	u32 control_flags = 0;
 	int ret;
 	int cmdq_size = max_t(u32, IWL_CMD_QUEUE_SIZE,
@@ -155,19 +154,22 @@
 	ctxt_info_gen3->mtr_size =
 		cpu_to_le16(TFD_QUEUE_CB_SIZE(cmdq_size));
 	ctxt_info_gen3->mcr_size =
-		cpu_to_le16(RX_QUEUE_CB_SIZE(MQ_RX_TABLE_SIZE));
+		cpu_to_le16(RX_QUEUE_CB_SIZE(trans->cfg->num_rbds));
 
 	trans_pcie->ctxt_info_gen3 = ctxt_info_gen3;
 	trans_pcie->prph_info = prph_info;
 	trans_pcie->prph_scratch = prph_scratch;
 
 	/* Allocate IML */
-	iml_img = dma_alloc_coherent(trans->dev, trans->iml_len,
-				     &trans_pcie->iml_dma_addr, GFP_KERNEL);
-	if (!iml_img)
-		return -ENOMEM;
+	trans_pcie->iml = dma_alloc_coherent(trans->dev, trans->iml_len,
+					     &trans_pcie->iml_dma_addr,
+					     GFP_KERNEL);
+	if (!trans_pcie->iml) {
+		ret = -ENOMEM;
+		goto err_free_ctxt_info;
+	}
 
-	memcpy(iml_img, trans->iml, trans->iml_len);
+	memcpy(trans_pcie->iml, trans->iml, trans->iml_len);
 
 	iwl_enable_fw_load_int_ctx_info(trans);
 
@@ -180,6 +182,26 @@
 
 	iwl_set_bit(trans, CSR_CTXT_INFO_BOOT_CTRL,
 		    CSR_AUTO_FUNC_BOOT_ENA);
+
+	if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_AX210) {
+		/*
+		 * The firmware initializes this again later (to a smaller
+		 * value), but for the boot process initialize the LTR to
+		 * ~250 usec.
+		 */
+		u32 val = CSR_LTR_LONG_VAL_AD_NO_SNOOP_REQ |
+			  u32_encode_bits(CSR_LTR_LONG_VAL_AD_SCALE_USEC,
+					  CSR_LTR_LONG_VAL_AD_NO_SNOOP_SCALE) |
+			  u32_encode_bits(250,
+					  CSR_LTR_LONG_VAL_AD_NO_SNOOP_VAL) |
+			  CSR_LTR_LONG_VAL_AD_SNOOP_REQ |
+			  u32_encode_bits(CSR_LTR_LONG_VAL_AD_SCALE_USEC,
+					  CSR_LTR_LONG_VAL_AD_SNOOP_SCALE) |
+			  u32_encode_bits(250, CSR_LTR_LONG_VAL_AD_SNOOP_VAL);
+
+		iwl_write32(trans, CSR_LTR_LONG_VAL_AD, val);
+	}
+
 	if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
 		iwl_write_umac_prph(trans, UREG_CPU_INIT_RUN, 1);
 	else
@@ -187,6 +209,11 @@
 
 	return 0;
 
+err_free_ctxt_info:
+	dma_free_coherent(trans->dev, sizeof(*trans_pcie->ctxt_info_gen3),
+			  trans_pcie->ctxt_info_gen3,
+			  trans_pcie->ctxt_info_dma_addr);
+	trans_pcie->ctxt_info_gen3 = NULL;
 err_free_prph_info:
 	dma_free_coherent(trans->dev,
 			  sizeof(*prph_info),
@@ -215,6 +242,11 @@
 	trans_pcie->ctxt_info_dma_addr = 0;
 	trans_pcie->ctxt_info_gen3 = NULL;
 
+	dma_free_coherent(trans->dev, trans->iml_len, trans_pcie->iml,
+			  trans_pcie->iml_dma_addr);
+	trans_pcie->iml_dma_addr = 0;
+	trans_pcie->iml = NULL;
+
 	iwl_pcie_ctxt_info_free_fw_img(trans);
 
 	dma_free_coherent(trans->dev, sizeof(*trans_pcie->prph_scratch),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c
@@ -193,11 +193,12 @@
 		rb_size = IWL_CTXT_INFO_RB_SIZE_4K;
 	}
 
-	BUILD_BUG_ON(RX_QUEUE_CB_SIZE(MQ_RX_TABLE_SIZE) > 0xF);
-	control_flags = IWL_CTXT_INFO_TFD_FORMAT_LONG |
-			(RX_QUEUE_CB_SIZE(MQ_RX_TABLE_SIZE) <<
-			 IWL_CTXT_INFO_RB_CB_SIZE_POS) |
-			(rb_size << IWL_CTXT_INFO_RB_SIZE_POS);
+	WARN_ON(RX_QUEUE_CB_SIZE(trans->cfg->num_rbds) > 12);
+	control_flags = IWL_CTXT_INFO_TFD_FORMAT_LONG;
+	control_flags |=
+		u32_encode_bits(RX_QUEUE_CB_SIZE(trans->cfg->num_rbds),
+				IWL_CTXT_INFO_RB_CB_SIZE);
+	control_flags |= u32_encode_bits(rb_size, IWL_CTXT_INFO_RB_SIZE);
 	ctxt_info->control.control_flags = cpu_to_le32(control_flags);
 
 	/* initialize RX default queue */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
@@ -258,6 +258,7 @@
 	{IWL_PCI_DEVICE(0x088E, 0x446A, iwl6035_2agn_sff_cfg)},
 	{IWL_PCI_DEVICE(0x088E, 0x4860, iwl6035_2agn_cfg)},
 	{IWL_PCI_DEVICE(0x088F, 0x5260, iwl6035_2agn_cfg)},
+	{IWL_PCI_DEVICE(0x088F, 0x526A, iwl6035_2agn_cfg)},
 
 /* 105 Series */
 	{IWL_PCI_DEVICE(0x0894, 0x0022, iwl105_bgn_cfg)},
@@ -910,7 +911,6 @@
 	{IWL_PCI_DEVICE(0x2720, 0x0074, iwl_ax201_cfg_qu_hr)},
 	{IWL_PCI_DEVICE(0x2720, 0x0078, iwl_ax201_cfg_qu_hr)},
 	{IWL_PCI_DEVICE(0x2720, 0x007C, iwl_ax201_cfg_qu_hr)},
-	{IWL_PCI_DEVICE(0x2720, 0x0090, iwl22000_2ac_cfg_hr_cdb)},
 	{IWL_PCI_DEVICE(0x2720, 0x0244, iwl_ax101_cfg_qu_hr)},
 	{IWL_PCI_DEVICE(0x2720, 0x0310, iwl_ax201_cfg_qu_hr)},
 	{IWL_PCI_DEVICE(0x2720, 0x0A10, iwl_ax201_cfg_qu_hr)},
@@ -968,6 +968,7 @@
 
 	{IWL_PCI_DEVICE(0x2725, 0x0090, iwlax211_2ax_cfg_so_gf_a0)},
 	{IWL_PCI_DEVICE(0x2725, 0x0020, iwlax210_2ax_cfg_ty_gf_a0)},
+	{IWL_PCI_DEVICE(0x2725, 0x0024, iwlax210_2ax_cfg_ty_gf_a0)},
 	{IWL_PCI_DEVICE(0x2725, 0x0310, iwlax210_2ax_cfg_ty_gf_a0)},
 	{IWL_PCI_DEVICE(0x2725, 0x0510, iwlax210_2ax_cfg_ty_gf_a0)},
 	{IWL_PCI_DEVICE(0x2725, 0x0A10, iwlax210_2ax_cfg_ty_gf_a0)},
@@ -992,18 +993,32 @@
 
 static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	const struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
+	const struct iwl_cfg_trans_params *trans =
+		(struct iwl_cfg_trans_params *)(ent->driver_data);
 	const struct iwl_cfg *cfg_7265d __maybe_unused = NULL;
 	struct iwl_trans *iwl_trans;
+	struct iwl_trans_pcie *trans_pcie;
 	unsigned long flags;
 	int ret;
+	/*
+	 * This is needed for backwards compatibility with the old
+	 * tables, so we don't need to change all the config structs
+	 * at the same time.  The cfg is used to compare with the old
+	 * full cfg structs.
+	 */
+	const struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
+
+	/* make sure trans is the first element in iwl_cfg */
+	BUILD_BUG_ON(offsetof(struct iwl_cfg, trans));
 
-	iwl_trans = iwl_trans_pcie_alloc(pdev, ent, &cfg->trans);
+	iwl_trans = iwl_trans_pcie_alloc(pdev, ent, trans);
 	if (IS_ERR(iwl_trans))
 		return PTR_ERR(iwl_trans);
 
+	trans_pcie = IWL_TRANS_GET_PCIE_TRANS(iwl_trans);
+
 	/* the trans_cfg should never change, so set it now */
-	iwl_trans->trans_cfg = &cfg->trans;
+	iwl_trans->trans_cfg = trans;
 
 	if (WARN_ONCE(!iwl_trans->trans_cfg->csr,
 		      "CSR addresses aren't configured\n")) {
@@ -1027,22 +1042,22 @@
 		cfg_7265d = &iwl7265d_n_cfg;
 	if (cfg_7265d &&
 	    (iwl_trans->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_7265D)
-		cfg = cfg_7265d;
+		iwl_trans->cfg = cfg_7265d;
 
 	iwl_trans->hw_rf_id = iwl_read32(iwl_trans, CSR_HW_RF_ID);
 
 	if (cfg == &iwlax210_2ax_cfg_so_hr_a0) {
 		if (iwl_trans->hw_rev == CSR_HW_REV_TYPE_TY) {
-			cfg = &iwlax210_2ax_cfg_ty_gf_a0;
+			iwl_trans->cfg = &iwlax210_2ax_cfg_ty_gf_a0;
 		} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) ==
 			   CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_JF)) {
-			cfg = &iwlax210_2ax_cfg_so_jf_a0;
+			iwl_trans->cfg = &iwlax210_2ax_cfg_so_jf_a0;
 		} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) ==
 			   CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_GF)) {
-			cfg = &iwlax211_2ax_cfg_so_gf_a0;
+			iwl_trans->cfg = &iwlax211_2ax_cfg_so_gf_a0;
 		} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) ==
 			   CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_GF4)) {
-			cfg = &iwlax411_2ax_cfg_so_gf4_a0;
+			iwl_trans->cfg = &iwlax411_2ax_cfg_so_gf4_a0;
 		}
 	} else if (cfg == &iwl_ax101_cfg_qu_hr) {
 		if ((CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) ==
@@ -1050,13 +1065,17 @@
 		     iwl_trans->hw_rev == CSR_HW_REV_TYPE_QNJ_B0) ||
 		    (CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) ==
 		     CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR1))) {
-			cfg = &iwl22000_2ax_cfg_qnj_hr_b0;
+			iwl_trans->cfg = &iwl22000_2ax_cfg_qnj_hr_b0;
+		} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) ==
+		    CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR) &&
+		    iwl_trans->hw_rev == CSR_HW_REV_TYPE_QUZ) {
+			iwl_trans->cfg = &iwl_ax101_cfg_quz_hr;
 		} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) ==
 			   CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR)) {
-			cfg = &iwl_ax101_cfg_qu_hr;
+			iwl_trans->cfg = &iwl_ax101_cfg_qu_hr;
 		} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) ==
 			   CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_JF)) {
-			cfg = &iwl22000_2ax_cfg_jf;
+			iwl_trans->cfg = &iwl22000_2ax_cfg_jf;
 		} else if (CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) ==
 			   CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HRCDB)) {
 			IWL_ERR(iwl_trans, "RF ID HRCDB is not supported\n");
@@ -1073,19 +1092,11 @@
 
 		hw_status = iwl_read_prph(iwl_trans, UMAG_GEN_HW_STATUS);
 		if (CSR_HW_RF_STEP(iwl_trans->hw_rf_id) == SILICON_B_STEP)
-			/*
-			 * b step fw is the same for physical card and fpga
-			 */
-			cfg = &iwl22000_2ax_cfg_qnj_hr_b0;
+			iwl_trans->cfg = &iwl22000_2ax_cfg_qnj_hr_b0;
 		else if ((hw_status & UMAG_GEN_HW_IS_FPGA) &&
-			 CSR_HW_RF_STEP(iwl_trans->hw_rf_id) == SILICON_A_STEP) {
-			cfg = &iwl22000_2ax_cfg_qnj_hr_a0_f0;
-		} else {
-			/*
-			 * a step no FPGA
-			 */
-			cfg = &iwl22000_2ac_cfg_hr;
-		}
+			 CSR_HW_RF_STEP(iwl_trans->hw_rf_id) ==
+			 SILICON_A_STEP)
+			iwl_trans->cfg = &iwl22000_2ax_cfg_qnj_hr_a0_f0;
 	}
 
 	/*
@@ -1096,38 +1107,60 @@
 	 */
 	if (iwl_trans->hw_rev == CSR_HW_REV_TYPE_QU_C0) {
 		if (cfg == &iwl_ax101_cfg_qu_hr)
-			cfg = &iwl_ax101_cfg_qu_c0_hr_b0;
+			iwl_trans->cfg = &iwl_ax101_cfg_qu_c0_hr_b0;
 		else if (cfg == &iwl_ax201_cfg_qu_hr)
-			cfg = &iwl_ax201_cfg_qu_c0_hr_b0;
+			iwl_trans->cfg = &iwl_ax201_cfg_qu_c0_hr_b0;
 		else if (cfg == &iwl9461_2ac_cfg_qu_b0_jf_b0)
-			cfg = &iwl9461_2ac_cfg_qu_c0_jf_b0;
+			iwl_trans->cfg = &iwl9461_2ac_cfg_qu_c0_jf_b0;
 		else if (cfg == &iwl9462_2ac_cfg_qu_b0_jf_b0)
-			cfg = &iwl9462_2ac_cfg_qu_c0_jf_b0;
+			iwl_trans->cfg = &iwl9462_2ac_cfg_qu_c0_jf_b0;
 		else if (cfg == &iwl9560_2ac_cfg_qu_b0_jf_b0)
-			cfg = &iwl9560_2ac_cfg_qu_c0_jf_b0;
+			iwl_trans->cfg = &iwl9560_2ac_cfg_qu_c0_jf_b0;
 		else if (cfg == &iwl9560_2ac_160_cfg_qu_b0_jf_b0)
-			cfg = &iwl9560_2ac_160_cfg_qu_c0_jf_b0;
+			iwl_trans->cfg = &iwl9560_2ac_160_cfg_qu_c0_jf_b0;
+		else if (cfg == &killer1650s_2ax_cfg_qu_b0_hr_b0)
+			iwl_trans->cfg = &killer1650s_2ax_cfg_qu_c0_hr_b0;
+		else if (cfg == &killer1650i_2ax_cfg_qu_b0_hr_b0)
+			iwl_trans->cfg = &killer1650i_2ax_cfg_qu_c0_hr_b0;
 	}
 
 	/* same thing for QuZ... */
 	if (iwl_trans->hw_rev == CSR_HW_REV_TYPE_QUZ) {
-		if (iwl_trans->cfg == &iwl_ax101_cfg_qu_hr)
+		if (cfg == &iwl_ax101_cfg_qu_hr)
 			iwl_trans->cfg = &iwl_ax101_cfg_quz_hr;
-		else if (iwl_trans->cfg == &iwl_ax201_cfg_qu_hr)
+		else if (cfg == &iwl_ax201_cfg_qu_hr)
 			iwl_trans->cfg = &iwl_ax201_cfg_quz_hr;
-		else if (iwl_trans->cfg == &iwl9461_2ac_cfg_qu_b0_jf_b0)
+		else if (cfg == &iwl9461_2ac_cfg_qu_b0_jf_b0)
 			iwl_trans->cfg = &iwl9461_2ac_cfg_quz_a0_jf_b0_soc;
-		else if (iwl_trans->cfg == &iwl9462_2ac_cfg_qu_b0_jf_b0)
+		else if (cfg == &iwl9462_2ac_cfg_qu_b0_jf_b0)
 			iwl_trans->cfg = &iwl9462_2ac_cfg_quz_a0_jf_b0_soc;
-		else if (iwl_trans->cfg == &iwl9560_2ac_cfg_qu_b0_jf_b0)
+		else if (cfg == &iwl9560_2ac_cfg_qu_b0_jf_b0)
 			iwl_trans->cfg = &iwl9560_2ac_cfg_quz_a0_jf_b0_soc;
-		else if (iwl_trans->cfg == &iwl9560_2ac_160_cfg_qu_b0_jf_b0)
+		else if (cfg == &iwl9560_2ac_160_cfg_qu_b0_jf_b0)
 			iwl_trans->cfg = &iwl9560_2ac_160_cfg_quz_a0_jf_b0_soc;
+		else if (cfg == &killer1650s_2ax_cfg_qu_b0_hr_b0)
+			iwl_trans->cfg = &iwl_ax1650s_cfg_quz_hr;
+		else if (cfg == &killer1650i_2ax_cfg_qu_b0_hr_b0)
+			iwl_trans->cfg = &iwl_ax1650i_cfg_quz_hr;
 	}
 
 #endif
-	/* now set the real cfg we decided to use */
-	iwl_trans->cfg = cfg;
+	/*
+	 * If we didn't set the cfg yet, assume the trans is actually
+	 * a full cfg from the old tables.
+	 */
+	if (!iwl_trans->cfg)
+		iwl_trans->cfg = cfg;
+
+	if (iwl_trans->trans_cfg->mq_rx_supported) {
+		if (WARN_ON(!iwl_trans->cfg->num_rbds)) {
+			ret = -EINVAL;
+			goto out_free_trans;
+		}
+		trans_pcie->num_rx_bufs = iwl_trans->cfg->num_rbds;
+	} else {
+		trans_pcie->num_rx_bufs = RX_QUEUE_SIZE;
+	}
 
 	if (iwl_trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_8000 &&
 	    iwl_trans_grab_nic_access(iwl_trans, &flags)) {
@@ -1172,6 +1205,9 @@
 {
 	struct iwl_trans *trans = pci_get_drvdata(pdev);
 
+	if (!trans)
+		return;
+
 	iwl_drv_stop(trans->drv);
 
 	iwl_trans_pcie_free(trans);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/pcie/internal.h
@@ -166,7 +166,7 @@
  * @id: queue index
  * @bd: driver's pointer to buffer of receive buffer descriptors (rbd).
  *	Address size is 32 bit in pre-9000 devices and 64 bit in 9000 devices.
- *	In 22560 devices it is a pointer to a list of iwl_rx_transfer_desc's
+ *	In AX210 devices it is a pointer to a list of iwl_rx_transfer_desc's
  * @bd_dma: bus address of buffer of receive buffer descriptors (rbd)
  * @ubd: driver's pointer to buffer of used receive buffer descriptors (rbd)
  * @ubd_dma: physical address of buffer of used receive buffer descriptors (rbd)
@@ -264,7 +264,7 @@
 static inline __le16 iwl_get_closed_rb_stts(struct iwl_trans *trans,
 					    struct iwl_rxq *rxq)
 {
-	if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
+	if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
 		__le16 *rb_stts = rxq->rb_stts;
 
 		return READ_ONCE(*rb_stts);
@@ -305,7 +305,7 @@
 #define IWL_FIRST_TB_SIZE_ALIGN ALIGN(IWL_FIRST_TB_SIZE, 64)
 
 struct iwl_pcie_txq_entry {
-	struct iwl_device_cmd *cmd;
+	void *cmd;
 	struct sk_buff *skb;
 	/* buffer to free after command completes */
 	const void *free_buf;
@@ -475,6 +475,8 @@
  *	Context information addresses will be taken from here.
  *	This is driver's local copy for keeping track of size and
  *	count for allocating and freeing the memory.
+ * @iml: image loader image virtual address
+ * @iml_dma_addr: image loader image DMA address
  * @trans: pointer to the generic transport area
  * @scd_base_addr: scheduler sram base address in SRAM
  * @scd_bc_tbls: pointer to the byte count table of the scheduler
@@ -513,8 +515,8 @@
  */
 struct iwl_trans_pcie {
 	struct iwl_rxq *rxq;
-	struct iwl_rx_mem_buffer rx_pool[RX_POOL_SIZE];
-	struct iwl_rx_mem_buffer *global_table[RX_POOL_SIZE];
+	struct iwl_rx_mem_buffer *rx_pool;
+	struct iwl_rx_mem_buffer **global_table;
 	struct iwl_rb_allocator rba;
 	union {
 		struct iwl_context_info *ctxt_info;
@@ -522,6 +524,7 @@
 	};
 	struct iwl_prph_info *prph_info;
 	struct iwl_prph_scratch *prph_scratch;
+	void *iml;
 	dma_addr_t ctxt_info_dma_addr;
 	dma_addr_t prph_info_dma_addr;
 	dma_addr_t prph_scratch_dma_addr;
@@ -573,6 +576,7 @@
 	u8 no_reclaim_cmds[MAX_NO_RECLAIM_CMDS];
 	u8 max_tbs;
 	u16 tfd_size;
+	u16 num_rx_bufs;
 
 	enum iwl_amsdu_size rx_buf_size;
 	bool bc_table_dword;
@@ -690,7 +694,7 @@
 void iwl_trans_pcie_log_scd_error(struct iwl_trans *trans,
 				  struct iwl_txq *txq);
 int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
-		      struct iwl_device_cmd *dev_cmd, int txq_id);
+		      struct iwl_device_tx_cmd *dev_cmd, int txq_id);
 void iwl_pcie_txq_check_wrptrs(struct iwl_trans *trans);
 int iwl_trans_pcie_send_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
 void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx);
@@ -1111,7 +1115,7 @@
 				 unsigned int timeout);
 void iwl_trans_pcie_dyn_txq_free(struct iwl_trans *trans, int queue);
 int iwl_trans_pcie_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb,
-			   struct iwl_device_cmd *dev_cmd, int txq_id);
+			   struct iwl_device_tx_cmd *dev_cmd, int txq_id);
 int iwl_trans_pcie_gen2_send_hcmd(struct iwl_trans *trans,
 				  struct iwl_host_cmd *cmd);
 void iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
@@ -200,8 +200,8 @@
  */
 int iwl_pcie_rx_stop(struct iwl_trans *trans)
 {
-	if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
-		/* TODO: remove this for 22560 once fw does it */
+	if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
+		/* TODO: remove this once fw does it */
 		iwl_write_umac_prph(trans, RFH_RXF_DMA_CFG_GEN3, 0);
 		return iwl_poll_umac_prph_bit(trans, RFH_GEN_STATUS_GEN3,
 					      RXF_DMA_IDLE, RXF_DMA_IDLE, 1000);
@@ -247,11 +247,7 @@
 	}
 
 	rxq->write_actual = round_down(rxq->write, 8);
-	if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22560)
-		iwl_write32(trans, HBUS_TARG_WRPTR,
-			    (rxq->write_actual |
-			     ((FIRST_RX_QUEUE + rxq->id) << 16)));
-	else if (trans->trans_cfg->mq_rx_supported)
+	if (trans->trans_cfg->mq_rx_supported)
 		iwl_write32(trans, RFH_Q_FRBDCB_WIDX_TRG(rxq->id),
 			    rxq->write_actual);
 	else
@@ -279,7 +275,7 @@
 				struct iwl_rxq *rxq,
 				struct iwl_rx_mem_buffer *rxb)
 {
-	if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
+	if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
 		struct iwl_rx_transfer_desc *bd = rxq->bd;
 
 		BUILD_BUG_ON(sizeof(*bd) != 2 * sizeof(u64));
@@ -326,7 +322,7 @@
 		WARN_ON(rxb->page_dma & DMA_BIT_MASK(12));
 		/* Point to Rx buffer via next RBD in circular buffer */
 		iwl_pcie_restock_bd(trans, rxq, rxb);
-		rxq->write = (rxq->write + 1) & MQ_RX_TABLE_MASK;
+		rxq->write = (rxq->write + 1) & (rxq->queue_size - 1);
 		rxq->free_count--;
 	}
 	spin_unlock(&rxq->lock);
@@ -514,7 +510,7 @@
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	int i;
 
-	for (i = 0; i < RX_POOL_SIZE; i++) {
+	for (i = 0; i < RX_POOL_SIZE(trans_pcie->num_rx_bufs); i++) {
 		if (!trans_pcie->rx_pool[i].page)
 			continue;
 		dma_unmap_page(trans->dev, trans_pcie->rx_pool[i].page_dma,
@@ -691,7 +687,7 @@
 {
 	struct device *dev = trans->dev;
 	bool use_rx_td = (trans->trans_cfg->device_family >=
-			  IWL_DEVICE_FAMILY_22560);
+			  IWL_DEVICE_FAMILY_AX210);
 	int free_size = iwl_pcie_free_bd_size(trans, use_rx_td);
 
 	if (rxq->bd)
@@ -712,7 +708,7 @@
 	rxq->used_bd_dma = 0;
 	rxq->used_bd = NULL;
 
-	if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_22560)
+	if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
 		return;
 
 	if (rxq->tr_tail)
@@ -736,13 +732,13 @@
 	int i;
 	int free_size;
 	bool use_rx_td = (trans->trans_cfg->device_family >=
-			  IWL_DEVICE_FAMILY_22560);
+			  IWL_DEVICE_FAMILY_AX210);
 	size_t rb_stts_size = use_rx_td ? sizeof(__le16) :
 			      sizeof(struct iwl_rb_status);
 
 	spin_lock_init(&rxq->lock);
 	if (trans->trans_cfg->mq_rx_supported)
-		rxq->queue_size = MQ_RX_TABLE_SIZE;
+		rxq->queue_size = trans->cfg->num_rbds;
 	else
 		rxq->queue_size = RX_QUEUE_SIZE;
 
@@ -784,11 +780,6 @@
 					  &rxq->cr_tail_dma, GFP_KERNEL);
 	if (!rxq->cr_tail)
 		goto err;
-	/*
-	 * W/A 22560 device step Z0 must be non zero bug
-	 * TODO: remove this when stop supporting Z0
-	 */
-	*rxq->cr_tail = cpu_to_le16(500);
 
 	return 0;
 
@@ -808,7 +799,7 @@
 	struct iwl_rb_allocator *rba = &trans_pcie->rba;
 	int i, ret;
 	size_t rb_stts_size = trans->trans_cfg->device_family >=
-			      IWL_DEVICE_FAMILY_22560 ?
+				IWL_DEVICE_FAMILY_AX210 ?
 			      sizeof(__le16) : sizeof(struct iwl_rb_status);
 
 	if (WARN_ON(trans_pcie->rxq))
@@ -816,8 +807,18 @@
 
 	trans_pcie->rxq = kcalloc(trans->num_rx_queues, sizeof(struct iwl_rxq),
 				  GFP_KERNEL);
-	if (!trans_pcie->rxq)
-		return -ENOMEM;
+	trans_pcie->rx_pool = kcalloc(RX_POOL_SIZE(trans_pcie->num_rx_bufs),
+				      sizeof(trans_pcie->rx_pool[0]),
+				      GFP_KERNEL);
+	trans_pcie->global_table =
+		kcalloc(RX_POOL_SIZE(trans_pcie->num_rx_bufs),
+			sizeof(trans_pcie->global_table[0]),
+			GFP_KERNEL);
+	if (!trans_pcie->rxq || !trans_pcie->rx_pool ||
+	    !trans_pcie->global_table) {
+		ret = -ENOMEM;
+		goto err;
+	}
 
 	spin_lock_init(&rba->lock);
 
@@ -854,6 +855,8 @@
 		trans_pcie->base_rb_stts = NULL;
 		trans_pcie->base_rb_stts_dma = 0;
 	}
+	kfree(trans_pcie->rx_pool);
+	kfree(trans_pcie->global_table);
 	kfree(trans_pcie->rxq);
 
 	return ret;
@@ -1074,8 +1077,9 @@
 		rxq->read = 0;
 		rxq->write = 0;
 		rxq->write_actual = 0;
-		memset(rxq->rb_stts, 0, (trans->trans_cfg->device_family >=
-					 IWL_DEVICE_FAMILY_22560) ?
+		memset(rxq->rb_stts, 0,
+		       (trans->trans_cfg->device_family >=
+			IWL_DEVICE_FAMILY_AX210) ?
 		       sizeof(__le16) : sizeof(struct iwl_rb_status));
 
 		iwl_pcie_rx_init_rxb_lists(rxq);
@@ -1089,12 +1093,11 @@
 
 	/* move the pool to the default queue and allocator ownerships */
 	queue_size = trans->trans_cfg->mq_rx_supported ?
-		     MQ_RX_NUM_RBDS : RX_QUEUE_SIZE;
+			trans_pcie->num_rx_bufs - 1 : RX_QUEUE_SIZE;
 	allocator_pool_size = trans->num_rx_queues *
 		(RX_CLAIM_REQ_ALLOC - RX_POST_REQ_ALLOC);
 	num_alloc = queue_size + allocator_pool_size;
-	BUILD_BUG_ON(ARRAY_SIZE(trans_pcie->global_table) !=
-		     ARRAY_SIZE(trans_pcie->rx_pool));
+
 	for (i = 0; i < num_alloc; i++) {
 		struct iwl_rx_mem_buffer *rxb = &trans_pcie->rx_pool[i];
 
@@ -1152,7 +1155,7 @@
 	struct iwl_rb_allocator *rba = &trans_pcie->rba;
 	int i;
 	size_t rb_stts_size = trans->trans_cfg->device_family >=
-			      IWL_DEVICE_FAMILY_22560 ?
+				IWL_DEVICE_FAMILY_AX210 ?
 			      sizeof(__le16) : sizeof(struct iwl_rb_status);
 
 	/*
@@ -1185,6 +1188,8 @@
 		if (rxq->napi.poll)
 			netif_napi_del(&rxq->napi);
 	}
+	kfree(trans_pcie->rx_pool);
+	kfree(trans_pcie->global_table);
 	kfree(trans_pcie->rxq);
 }
 
@@ -1347,7 +1352,7 @@
 		}
 
 		page_stolen |= rxcb._page_stolen;
-		if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22560)
+		if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
 			break;
 		offset += ALIGN(len, FH_RSCSR_FRAME_ALIGN);
 	}
@@ -1398,13 +1403,12 @@
 		return rxb;
 	}
 
-	/* used_bd is a 32/16 bit but only 12 are used to retrieve the vid */
-	if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22560)
-		vid = le16_to_cpu(rxq->cd[i].rbid) & 0x0FFF;
+	if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
+		vid = le16_to_cpu(rxq->cd[i].rbid);
 	else
-		vid = le32_to_cpu(rxq->bd_32[i]) & 0x0FFF;
+		vid = le32_to_cpu(rxq->bd_32[i]) & 0x0FFF; /* 12-bit VID */
 
-	if (!vid || vid > ARRAY_SIZE(trans_pcie->global_table))
+	if (!vid || vid > RX_POOL_SIZE(trans_pcie->num_rx_bufs))
 		goto out_err;
 
 	rxb = trans_pcie->global_table[vid - 1];
@@ -1429,6 +1433,7 @@
 static void iwl_pcie_rx_handle(struct iwl_trans *trans, int queue)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+	struct napi_struct *napi;
 	struct iwl_rxq *rxq;
 	u32 r, i, count = 0;
 	bool emergency = false;
@@ -1515,7 +1520,7 @@
 	/* Backtrack one entry */
 	rxq->read = i;
 	/* update cr tail with the rxq read pointer */
-	if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22560)
+	if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
 		*rxq->cr_tail = cpu_to_le16(r);
 	spin_unlock(&rxq->lock);
 
@@ -1534,8 +1539,16 @@
 	if (unlikely(emergency && count))
 		iwl_pcie_rxq_alloc_rbs(trans, GFP_ATOMIC, rxq);
 
-	if (rxq->napi.poll)
-		napi_gro_flush(&rxq->napi, false);
+	napi = &rxq->napi;
+	if (napi->poll) {
+		napi_gro_flush(napi, false);
+
+		if (napi->rx_count) {
+			netif_receive_skb_list(&napi->rx_list);
+			INIT_LIST_HEAD(&napi->rx_list);
+			napi->rx_count = 0;
+		}
+	}
 
 	iwl_pcie_rxq_restock(trans, rxq);
 }
@@ -2152,8 +2165,7 @@
 
 	/* Error detected by uCode */
 	if ((inta_fh & MSIX_FH_INT_CAUSES_FH_ERR) ||
-	    (inta_hw & MSIX_HW_INT_CAUSES_REG_SW_ERR) ||
-	    (inta_hw & MSIX_HW_INT_CAUSES_REG_SW_ERR_V2)) {
+	    (inta_hw & MSIX_HW_INT_CAUSES_REG_SW_ERR)) {
 		IWL_ERR(trans,
 			"Microcode SW error detected. Restarting 0x%X.\n",
 			inta_fh);
@@ -2185,17 +2197,7 @@
 		}
 	}
 
-	if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22560 &&
-	    inta_hw & MSIX_HW_INT_CAUSES_REG_IPC) {
-		/* Reflect IML transfer status */
-		int res = iwl_read32(trans, CSR_IML_RESP_ADDR);
-
-		IWL_DEBUG_ISR(trans, "IML transfer status: %d\n", res);
-		if (res == IWL_IMAGE_RESP_FAIL) {
-			isr_stats->sw++;
-			iwl_pcie_irq_handle_error(trans);
-		}
-	} else if (inta_hw & MSIX_HW_INT_CAUSES_REG_WAKEUP) {
+	if (inta_hw & MSIX_HW_INT_CAUSES_REG_WAKEUP) {
 		u32 sleep_notif =
 			le32_to_cpu(trans_pcie->prph_info->sleep_notif);
 		if (sleep_notif == IWL_D3_SLEEP_STATUS_SUSPEND ||
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
@@ -57,24 +57,6 @@
 #include "internal.h"
 #include "fw/dbg.h"
 
-static int iwl_pcie_gen2_force_power_gating(struct iwl_trans *trans)
-{
-	iwl_set_bits_prph(trans, HPM_HIPM_GEN_CFG,
-			  HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE);
-	udelay(20);
-	iwl_set_bits_prph(trans, HPM_HIPM_GEN_CFG,
-			  HPM_HIPM_GEN_CFG_CR_PG_EN |
-			  HPM_HIPM_GEN_CFG_CR_SLP_EN);
-	udelay(20);
-	iwl_clear_bits_prph(trans, HPM_HIPM_GEN_CFG,
-			    HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE);
-
-	iwl_trans_sw_reset(trans);
-	iwl_clear_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
-
-	return 0;
-}
-
 /*
  * Start up NIC's basic functionality after it has been reset
  * (e.g. after platform boot, or shutdown via iwl_pcie_apm_stop())
@@ -110,13 +92,6 @@
 
 	iwl_pcie_apm_config(trans);
 
-	if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000 &&
-	    trans->cfg->integrated) {
-		ret = iwl_pcie_gen2_force_power_gating(trans);
-		if (ret)
-			return ret;
-	}
-
 	ret = iwl_finish_nic_init(trans, trans->trans_cfg);
 	if (ret)
 		return ret;
@@ -193,7 +168,7 @@
 	}
 
 	iwl_pcie_ctxt_info_free_paging(trans);
-	if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22560)
+	if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
 		iwl_pcie_ctxt_info_gen3_free(trans);
 	else
 		iwl_pcie_ctxt_info_free(trans);
@@ -294,7 +269,8 @@
 	/* now that we got alive we can free the fw image & the context info.
 	 * paging memory cannot be freed included since FW will still use it
 	 */
-	iwl_pcie_ctxt_info_free(trans);
+	if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
+		iwl_pcie_ctxt_info_free(trans);
 
 	/*
 	 * Re-enable all the interrupts, including the RF-Kill one, now that
@@ -316,8 +292,7 @@
 	/* This may fail if AMT took ownership of the device */
 	if (iwl_pcie_prepare_card_hw(trans)) {
 		IWL_WARN(trans, "Exit HW not ready\n");
-		ret = -EIO;
-		goto out;
+		return -EIO;
 	}
 
 	iwl_enable_rfkill_int(trans);
@@ -365,7 +340,7 @@
 		goto out;
 	}
 
-	if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22560)
+	if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
 		ret = iwl_pcie_ctxt_info_gen3_init(trans, fw);
 	else
 		ret = iwl_pcie_ctxt_info_init(trans, fw);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
@@ -79,6 +79,7 @@
 #include "iwl-agn-hw.h"
 #include "fw/error-dump.h"
 #include "fw/dbg.h"
+#include "fw/api/tx.h"
 #include "internal.h"
 #include "iwl-fh.h"
 
@@ -629,7 +630,6 @@
 int iwl_pcie_prepare_card_hw(struct iwl_trans *trans)
 {
 	int ret;
-	int t = 0;
 	int iter;
 
 	IWL_DEBUG_INFO(trans, "iwl_trans_prepare_card_hw enter\n");
@@ -644,6 +644,8 @@
 	usleep_range(1000, 2000);
 
 	for (iter = 0; iter < 10; iter++) {
+		int t = 0;
+
 		/* If HW is not ready, prepare the conditions to check again */
 		iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,
 			    CSR_HW_IF_CONFIG_REG_PREPARE);
@@ -1112,30 +1114,12 @@
 	{MSIX_HW_INT_CAUSES_REG_HAP,		CSR_MSIX_HW_INT_MASK_AD, 0x2E},
 };
 
-static struct iwl_causes_list causes_list_v2[] = {
-	{MSIX_FH_INT_CAUSES_D2S_CH0_NUM,	CSR_MSIX_FH_INT_MASK_AD, 0},
-	{MSIX_FH_INT_CAUSES_D2S_CH1_NUM,	CSR_MSIX_FH_INT_MASK_AD, 0x1},
-	{MSIX_FH_INT_CAUSES_S2D,		CSR_MSIX_FH_INT_MASK_AD, 0x3},
-	{MSIX_FH_INT_CAUSES_FH_ERR,		CSR_MSIX_FH_INT_MASK_AD, 0x5},
-	{MSIX_HW_INT_CAUSES_REG_ALIVE,		CSR_MSIX_HW_INT_MASK_AD, 0x10},
-	{MSIX_HW_INT_CAUSES_REG_IPC,		CSR_MSIX_HW_INT_MASK_AD, 0x11},
-	{MSIX_HW_INT_CAUSES_REG_SW_ERR_V2,	CSR_MSIX_HW_INT_MASK_AD, 0x15},
-	{MSIX_HW_INT_CAUSES_REG_CT_KILL,	CSR_MSIX_HW_INT_MASK_AD, 0x16},
-	{MSIX_HW_INT_CAUSES_REG_RF_KILL,	CSR_MSIX_HW_INT_MASK_AD, 0x17},
-	{MSIX_HW_INT_CAUSES_REG_PERIODIC,	CSR_MSIX_HW_INT_MASK_AD, 0x18},
-	{MSIX_HW_INT_CAUSES_REG_SCD,		CSR_MSIX_HW_INT_MASK_AD, 0x2A},
-	{MSIX_HW_INT_CAUSES_REG_FH_TX,		CSR_MSIX_HW_INT_MASK_AD, 0x2B},
-	{MSIX_HW_INT_CAUSES_REG_HW_ERR,		CSR_MSIX_HW_INT_MASK_AD, 0x2D},
-	{MSIX_HW_INT_CAUSES_REG_HAP,		CSR_MSIX_HW_INT_MASK_AD, 0x2E},
-};
-
 static void iwl_pcie_map_non_rx_causes(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie =  IWL_TRANS_GET_PCIE_TRANS(trans);
 	int val = trans_pcie->def_irq | MSIX_NON_AUTO_CLEAR_CAUSE;
-	int i, arr_size =
-		(trans->trans_cfg->device_family != IWL_DEVICE_FAMILY_22560) ?
-		ARRAY_SIZE(causes_list) : ARRAY_SIZE(causes_list_v2);
+	int i, arr_size = ARRAY_SIZE(causes_list);
+	struct iwl_causes_list *causes = causes_list;
 
 	/*
 	 * Access all non RX causes and map them to the default irq.
@@ -1143,11 +1127,6 @@
 	 * the first interrupt vector will serve non-RX and FBQ causes.
 	 */
 	for (i = 0; i < arr_size; i++) {
-		struct iwl_causes_list *causes =
-			(trans->trans_cfg->device_family !=
-			 IWL_DEVICE_FAMILY_22560) ?
-			causes_list : causes_list_v2;
-
 		iwl_write8(trans, CSR_MSIX_IVAR(causes[i].addr), val);
 		iwl_clear_bit(trans, causes[i].mask_reg,
 			      causes[i].cause_num);
@@ -1334,8 +1313,7 @@
 	/* This may fail if AMT took ownership of the device */
 	if (iwl_pcie_prepare_card_hw(trans)) {
 		IWL_WARN(trans, "Exit HW not ready\n");
-		ret = -EIO;
-		goto out;
+		return -EIO;
 	}
 
 	iwl_enable_rfkill_int(trans);
@@ -1634,11 +1612,15 @@
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	int max_irqs, num_irqs, i, ret;
 	u16 pci_cmd;
+	u32 max_rx_queues = IWL_MAX_RX_HW_QUEUES;
 
 	if (!cfg_trans->mq_rx_supported)
 		goto enable_msi;
 
-	max_irqs = min_t(u32, num_online_cpus() + 2, IWL_MAX_RX_HW_QUEUES);
+	if (cfg_trans->device_family <= IWL_DEVICE_FAMILY_9000)
+		max_rx_queues = IWL_9000_MAX_RX_HW_QUEUES;
+
+	max_irqs = min_t(u32, num_online_cpus() + 2, max_rx_queues);
 	for (i = 0; i < max_irqs; i++)
 		trans_pcie->msix_entries[i].entry = i;
 
@@ -1783,6 +1765,29 @@
 	return 0;
 }
 
+static int iwl_pcie_gen2_force_power_gating(struct iwl_trans *trans)
+{
+	int ret;
+
+	ret = iwl_finish_nic_init(trans, trans->trans_cfg);
+	if (ret < 0)
+		return ret;
+
+	iwl_set_bits_prph(trans, HPM_HIPM_GEN_CFG,
+			  HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE);
+	udelay(20);
+	iwl_set_bits_prph(trans, HPM_HIPM_GEN_CFG,
+			  HPM_HIPM_GEN_CFG_CR_PG_EN |
+			  HPM_HIPM_GEN_CFG_CR_SLP_EN);
+	udelay(20);
+	iwl_clear_bits_prph(trans, HPM_HIPM_GEN_CFG,
+			    HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE);
+
+	iwl_trans_pcie_sw_reset(trans);
+
+	return 0;
+}
+
 static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -1802,6 +1807,13 @@
 
 	iwl_trans_pcie_sw_reset(trans);
 
+	if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000 &&
+	    trans->cfg->integrated) {
+		err = iwl_pcie_gen2_force_power_gating(trans);
+		if (err)
+			return err;
+	}
+
 	err = iwl_pcie_apm_init(trans);
 	if (err)
 		return err;
@@ -1871,7 +1883,7 @@
 
 static u32 iwl_trans_pcie_prph_msk(struct iwl_trans *trans)
 {
-	if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22560)
+	if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
 		return 0x00FFFFFF;
 	else
 		return 0x000FFFFF;
@@ -2147,18 +2159,38 @@
 				   void *buf, int dwords)
 {
 	unsigned long flags;
-	int offs, ret = 0;
+	int offs = 0;
 	u32 *vals = buf;
 
-	if (iwl_trans_grab_nic_access(trans, &flags)) {
-		iwl_write32(trans, HBUS_TARG_MEM_RADDR, addr);
-		for (offs = 0; offs < dwords; offs++)
-			vals[offs] = iwl_read32(trans, HBUS_TARG_MEM_RDAT);
-		iwl_trans_release_nic_access(trans, &flags);
-	} else {
-		ret = -EBUSY;
+	while (offs < dwords) {
+		/* limit the time we spin here under lock to 1/2s */
+		unsigned long end = jiffies + HZ / 2;
+		bool resched = false;
+
+		if (iwl_trans_grab_nic_access(trans, &flags)) {
+			iwl_write32(trans, HBUS_TARG_MEM_RADDR,
+				    addr + 4 * offs);
+
+			while (offs < dwords) {
+				vals[offs] = iwl_read32(trans,
+							HBUS_TARG_MEM_RDAT);
+				offs++;
+
+				if (time_after(jiffies, end)) {
+					resched = true;
+					break;
+				}
+			}
+			iwl_trans_release_nic_access(trans, &flags);
+
+			if (resched)
+				cond_resched();
+		} else {
+			return -EBUSY;
+		}
 	}
-	return ret;
+
+	return 0;
 }
 
 static int iwl_trans_pcie_write_mem(struct iwl_trans *trans, u32 addr,
@@ -2781,7 +2813,7 @@
 				  void *buf, ssize_t *size,
 				  ssize_t *bytes_copied)
 {
-	int buf_size_left = count - *bytes_copied;
+	ssize_t buf_size_left = count - *bytes_copied;
 
 	buf_size_left = buf_size_left - (buf_size_left % sizeof(u32));
 	if (*size > buf_size_left)
@@ -3432,19 +3464,34 @@
 {
 	struct iwl_trans_pcie *trans_pcie;
 	struct iwl_trans *trans;
-	int ret, addr_size;
+	int ret, addr_size, txcmd_size, txcmd_align;
+	const struct iwl_trans_ops *ops = &trans_ops_pcie_gen2;
+
+	if (!cfg_trans->gen2) {
+		ops = &trans_ops_pcie;
+		txcmd_size = sizeof(struct iwl_tx_cmd);
+		txcmd_align = sizeof(void *);
+	} else if (cfg_trans->device_family < IWL_DEVICE_FAMILY_AX210) {
+		txcmd_size = sizeof(struct iwl_tx_cmd_gen2);
+		txcmd_align = 64;
+	} else {
+		txcmd_size = sizeof(struct iwl_tx_cmd_gen3);
+		txcmd_align = 128;
+	}
+
+	txcmd_size += sizeof(struct iwl_cmd_header);
+	txcmd_size += 36; /* biggest possible 802.11 header */
+
+	/* Ensure device TX cmd cannot reach/cross a page boundary in gen2 */
+	if (WARN_ON(cfg_trans->gen2 && txcmd_size >= txcmd_align))
+		return ERR_PTR(-EINVAL);
 
 	ret = pcim_enable_device(pdev);
 	if (ret)
 		return ERR_PTR(ret);
 
-	if (cfg_trans->gen2)
-		trans = iwl_trans_alloc(sizeof(struct iwl_trans_pcie),
-					&pdev->dev, &trans_ops_pcie_gen2);
-	else
-		trans = iwl_trans_alloc(sizeof(struct iwl_trans_pcie),
-					&pdev->dev, &trans_ops_pcie);
-
+	trans = iwl_trans_alloc(sizeof(struct iwl_trans_pcie), &pdev->dev, ops,
+				txcmd_size, txcmd_align);
 	if (!trans)
 		return ERR_PTR(-ENOMEM);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c
@@ -113,14 +113,14 @@
 	 */
 	num_fetch_chunks = DIV_ROUND_UP(filled_tfd_size, 64) - 1;
 
-	if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
-		/* Starting from 22560, the HW expects bytes */
+	if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
+		/* Starting from AX210, the HW expects bytes */
 		WARN_ON(trans_pcie->bc_table_dword);
 		WARN_ON(len > 0x3FFF);
 		bc_ent = cpu_to_le16(len | (num_fetch_chunks << 14));
 		scd_bc_tbl_gen3->tfd_offset[idx] = bc_ent;
 	} else {
-		/* Until 22560, the HW expects DW */
+		/* Before AX210, the HW expects DW */
 		WARN_ON(!trans_pcie->bc_table_dword);
 		len = DIV_ROUND_UP(len, 4);
 		WARN_ON(len > 0xFFF);
@@ -243,7 +243,8 @@
 static int iwl_pcie_gen2_build_amsdu(struct iwl_trans *trans,
 				     struct sk_buff *skb,
 				     struct iwl_tfh_tfd *tfd, int start_len,
-				     u8 hdr_len, struct iwl_device_cmd *dev_cmd)
+				     u8 hdr_len,
+				     struct iwl_device_tx_cmd *dev_cmd)
 {
 #ifdef CONFIG_INET
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -371,7 +372,7 @@
 static struct
 iwl_tfh_tfd *iwl_pcie_gen2_build_tx_amsdu(struct iwl_trans *trans,
 					  struct iwl_txq *txq,
-					  struct iwl_device_cmd *dev_cmd,
+					  struct iwl_device_tx_cmd *dev_cmd,
 					  struct sk_buff *skb,
 					  struct iwl_cmd_meta *out_meta,
 					  int hdr_len,
@@ -403,6 +404,10 @@
 	tb_phys = dma_map_single(trans->dev, tb1_addr, len, DMA_TO_DEVICE);
 	if (unlikely(dma_mapping_error(trans->dev, tb_phys)))
 		goto out_err;
+	/*
+	 * No need for _with_wa(), we ensure (via alignment) that the data
+	 * here can never cross or end at a page boundary.
+	 */
 	iwl_pcie_gen2_set_tb(trans, tfd, tb_phys, len);
 
 	if (iwl_pcie_gen2_build_amsdu(trans, skb, tfd,
@@ -456,7 +461,7 @@
 static struct
 iwl_tfh_tfd *iwl_pcie_gen2_build_tx(struct iwl_trans *trans,
 				    struct iwl_txq *txq,
-				    struct iwl_device_cmd *dev_cmd,
+				    struct iwl_device_tx_cmd *dev_cmd,
 				    struct sk_buff *skb,
 				    struct iwl_cmd_meta *out_meta,
 				    int hdr_len,
@@ -468,6 +473,7 @@
 	dma_addr_t tb_phys;
 	int len, tb1_len, tb2_len;
 	void *tb1_addr;
+	struct sk_buff *frag;
 
 	tb_phys = iwl_pcie_get_first_tb_dma(txq, idx);
 
@@ -495,6 +501,10 @@
 	tb_phys = dma_map_single(trans->dev, tb1_addr, tb1_len, DMA_TO_DEVICE);
 	if (unlikely(dma_mapping_error(trans->dev, tb_phys)))
 		goto out_err;
+	/*
+	 * No need for _with_wa(), we ensure (via alignment) that the data
+	 * here can never cross or end at a page boundary.
+	 */
 	iwl_pcie_gen2_set_tb(trans, tfd, tb_phys, tb1_len);
 	trace_iwlwifi_dev_tx(trans->dev, skb, tfd, sizeof(*tfd), &dev_cmd->hdr,
 			     IWL_FIRST_TB_SIZE + tb1_len, hdr_len);
@@ -516,6 +526,19 @@
 	if (iwl_pcie_gen2_tx_add_frags(trans, skb, tfd, out_meta))
 		goto out_err;
 
+	skb_walk_frags(skb, frag) {
+		tb_phys = dma_map_single(trans->dev, frag->data,
+					 skb_headlen(frag), DMA_TO_DEVICE);
+		if (unlikely(dma_mapping_error(trans->dev, tb_phys)))
+			goto out_err;
+		iwl_pcie_gen2_set_tb(trans, tfd, tb_phys, skb_headlen(frag));
+		trace_iwlwifi_dev_tx_tb(trans->dev, skb,
+					frag->data,
+					skb_headlen(frag));
+		if (iwl_pcie_gen2_tx_add_frags(trans, frag, tfd, out_meta))
+			goto out_err;
+	}
+
 	return tfd;
 
 out_err:
@@ -526,7 +549,7 @@
 static
 struct iwl_tfh_tfd *iwl_pcie_gen2_build_tfd(struct iwl_trans *trans,
 					    struct iwl_txq *txq,
-					    struct iwl_device_cmd *dev_cmd,
+					    struct iwl_device_tx_cmd *dev_cmd,
 					    struct sk_buff *skb,
 					    struct iwl_cmd_meta *out_meta)
 {
@@ -541,7 +564,7 @@
 
 	memset(tfd, 0, sizeof(*tfd));
 
-	if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_22560)
+	if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210)
 		len = sizeof(struct iwl_tx_cmd_gen2);
 	else
 		len = sizeof(struct iwl_tx_cmd_gen3);
@@ -566,7 +589,7 @@
 }
 
 int iwl_trans_pcie_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb,
-			   struct iwl_device_cmd *dev_cmd, int txq_id)
+			   struct iwl_device_tx_cmd *dev_cmd, int txq_id)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	struct iwl_cmd_meta *out_meta;
@@ -591,7 +614,7 @@
 
 		/* don't put the packet on the ring, if there is no room */
 		if (unlikely(iwl_queue_space(trans, txq) < 3)) {
-			struct iwl_device_cmd **dev_cmd_ptr;
+			struct iwl_device_tx_cmd **dev_cmd_ptr;
 
 			dev_cmd_ptr = (void *)((u8 *)skb->cb +
 					       trans_pcie->dev_cmd_offs);
@@ -623,7 +646,7 @@
 		return -1;
 	}
 
-	if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22560) {
+	if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
 		struct iwl_tx_cmd_gen3 *tx_cmd_gen3 =
 			(void *)dev_cmd->payload;
 
@@ -682,6 +705,7 @@
 	const u8 *cmddata[IWL_MAX_CMD_TBS_PER_TFD];
 	u16 cmdlen[IWL_MAX_CMD_TBS_PER_TFD];
 	struct iwl_tfh_tfd *tfd;
+	unsigned long flags2;
 
 	copy_size = sizeof(struct iwl_cmd_header_wide);
 	cmd_size = sizeof(struct iwl_cmd_header_wide);
@@ -750,14 +774,14 @@
 		goto free_dup_buf;
 	}
 
-	spin_lock_bh(&txq->lock);
+	spin_lock_irqsave(&txq->lock, flags2);
 
 	idx = iwl_pcie_get_cmd_index(txq, txq->write_ptr);
 	tfd = iwl_pcie_get_tfd(trans, txq, txq->write_ptr);
 	memset(tfd, 0, sizeof(*tfd));
 
 	if (iwl_queue_space(trans, txq) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) {
-		spin_unlock_bh(&txq->lock);
+		spin_unlock_irqrestore(&txq->lock, flags2);
 
 		IWL_ERR(trans, "No space in command queue\n");
 		iwl_op_mode_cmd_queue_full(trans->op_mode);
@@ -892,7 +916,7 @@
 	spin_unlock_irqrestore(&trans_pcie->reg_lock, flags);
 
 out:
-	spin_unlock_bh(&txq->lock);
+	spin_unlock_irqrestore(&txq->lock, flags2);
 free_dup_buf:
 	if (idx < 0)
 		kfree(dup_buf);
@@ -1124,7 +1148,7 @@
 		return -ENOMEM;
 	ret = iwl_pcie_alloc_dma_ptr(trans, &txq->bc_tbl,
 				     (trans->trans_cfg->device_family >=
-				      IWL_DEVICE_FAMILY_22560) ?
+				      IWL_DEVICE_FAMILY_AX210) ?
 				     sizeof(struct iwl_gen3_bc_tbl) :
 				     sizeof(struct iwlagn_scd_bc_tbl));
 	if (ret) {
@@ -1260,6 +1284,9 @@
 
 	iwl_pcie_gen2_txq_unmap(trans, queue);
 
+	iwl_pcie_gen2_txq_free_memory(trans, trans_pcie->txq[queue]);
+	trans_pcie->txq[queue] = NULL;
+
 	IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", queue);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
@@ -213,8 +213,8 @@
 	u8 sec_ctl = 0;
 	u16 len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE;
 	__le16 bc_ent;
-	struct iwl_tx_cmd *tx_cmd =
-		(void *)txq->entries[txq->write_ptr].cmd->payload;
+	struct iwl_device_tx_cmd *dev_cmd = txq->entries[txq->write_ptr].cmd;
+	struct iwl_tx_cmd *tx_cmd = (void *)dev_cmd->payload;
 	u8 sta_id = tx_cmd->sta_id;
 
 	scd_bc_tbl = trans_pcie->scd_bc_tbls.addr;
@@ -257,8 +257,8 @@
 	int read_ptr = txq->read_ptr;
 	u8 sta_id = 0;
 	__le16 bc_ent;
-	struct iwl_tx_cmd *tx_cmd =
-		(void *)txq->entries[read_ptr].cmd->payload;
+	struct iwl_device_tx_cmd *dev_cmd = txq->entries[read_ptr].cmd;
+	struct iwl_tx_cmd *tx_cmd = (void *)dev_cmd->payload;
 
 	WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX);
 
@@ -657,6 +657,11 @@
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	struct iwl_txq *txq = trans_pcie->txq[txq_id];
 
+	if (!txq) {
+		IWL_ERR(trans, "Trying to free a queue that wasn't allocated?\n");
+		return;
+	}
+
 	spin_lock_bh(&txq->lock);
 	while (txq->write_ptr != txq->read_ptr) {
 		IWL_DEBUG_TX_REPLY(trans, "Q %d Free %d\n",
@@ -949,7 +954,7 @@
 	u16 bc_tbls_size = trans->trans_cfg->base_params->num_of_queues;
 
 	bc_tbls_size *= (trans->trans_cfg->device_family >=
-			 IWL_DEVICE_FAMILY_22560) ?
+			 IWL_DEVICE_FAMILY_AX210) ?
 		sizeof(struct iwl_gen3_bc_tbl) :
 		sizeof(struct iwlagn_scd_bc_tbl);
 
@@ -1196,7 +1201,7 @@
 
 		while (!skb_queue_empty(&overflow_skbs)) {
 			struct sk_buff *skb = __skb_dequeue(&overflow_skbs);
-			struct iwl_device_cmd *dev_cmd_ptr;
+			struct iwl_device_tx_cmd *dev_cmd_ptr;
 
 			dev_cmd_ptr = *(void **)((u8 *)skb->cb +
 						 trans_pcie->dev_cmd_offs);
@@ -1539,6 +1544,7 @@
 	u32 cmd_pos;
 	const u8 *cmddata[IWL_MAX_CMD_TBS_PER_TFD];
 	u16 cmdlen[IWL_MAX_CMD_TBS_PER_TFD];
+	unsigned long flags2;
 
 	if (WARN(!trans->wide_cmd_header &&
 		 group_id > IWL_ALWAYS_LONG_GROUP,
@@ -1622,10 +1628,10 @@
 		goto free_dup_buf;
 	}
 
-	spin_lock_bh(&txq->lock);
+	spin_lock_irqsave(&txq->lock, flags2);
 
 	if (iwl_queue_space(trans, txq) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) {
-		spin_unlock_bh(&txq->lock);
+		spin_unlock_irqrestore(&txq->lock, flags2);
 
 		IWL_ERR(trans, "No space in command queue\n");
 		iwl_op_mode_cmd_queue_full(trans->op_mode);
@@ -1786,7 +1792,7 @@
 	spin_unlock_irqrestore(&trans_pcie->reg_lock, flags);
 
  out:
-	spin_unlock_bh(&txq->lock);
+	spin_unlock_irqrestore(&txq->lock, flags2);
  free_dup_buf:
 	if (idx < 0)
 		kfree(dup_buf);
@@ -2099,7 +2105,8 @@
 static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb,
 				   struct iwl_txq *txq, u8 hdr_len,
 				   struct iwl_cmd_meta *out_meta,
-				   struct iwl_device_cmd *dev_cmd, u16 tb1_len)
+				   struct iwl_device_tx_cmd *dev_cmd,
+				   u16 tb1_len)
 {
 	struct iwl_tx_cmd *tx_cmd = (void *)dev_cmd->payload;
 	struct iwl_trans_pcie *trans_pcie = txq->trans_pcie;
@@ -2281,7 +2288,8 @@
 static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb,
 				   struct iwl_txq *txq, u8 hdr_len,
 				   struct iwl_cmd_meta *out_meta,
-				   struct iwl_device_cmd *dev_cmd, u16 tb1_len)
+				   struct iwl_device_tx_cmd *dev_cmd,
+				   u16 tb1_len)
 {
 	/* No A-MSDU without CONFIG_INET */
 	WARN_ON(1);
@@ -2291,7 +2299,7 @@
 #endif /* CONFIG_INET */
 
 int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
-		      struct iwl_device_cmd *dev_cmd, int txq_id)
+		      struct iwl_device_tx_cmd *dev_cmd, int txq_id)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 	struct ieee80211_hdr *hdr;
@@ -2348,7 +2356,7 @@
 
 		/* don't put the packet on the ring, if there is no room */
 		if (unlikely(iwl_queue_space(trans, txq) < 3)) {
-			struct iwl_device_cmd **dev_cmd_ptr;
+			struct iwl_device_tx_cmd **dev_cmd_ptr;
 
 			dev_cmd_ptr = (void *)((u8 *)skb->cb +
 					       trans_pcie->dev_cmd_offs);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intersil/hostap/hostap_ap.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intersil/hostap/hostap_ap.c
@@ -2508,7 +2508,7 @@
 		sta->supported_rates[0] = 2;
 	if (sta->tx_supp_rates & WLAN_RATE_2M)
 		sta->supported_rates[1] = 4;
- 	if (sta->tx_supp_rates & WLAN_RATE_5M5)
+	if (sta->tx_supp_rates & WLAN_RATE_5M5)
 		sta->supported_rates[2] = 11;
 	if (sta->tx_supp_rates & WLAN_RATE_11M)
 		sta->supported_rates[3] = 22;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intersil/orinoco/hw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intersil/orinoco/hw.c
@@ -931,6 +931,8 @@
 			err = hermes_write_wordrec(hw, USER_BAP,
 					HERMES_RID_CNFAUTHENTICATION_AGERE,
 					auth_flag);
+			if (err)
+				return err;
 		}
 		err = hermes_write_wordrec(hw, USER_BAP,
 					   HERMES_RID_CNFWEPENABLED_AGERE,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intersil/orinoco/orinoco_cs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intersil/orinoco/orinoco_cs.c
@@ -96,6 +96,7 @@
 {
 	struct orinoco_private *priv;
 	struct orinoco_pccard *card;
+	int ret;
 
 	priv = alloc_orinocodev(sizeof(*card), &link->dev,
 				orinoco_cs_hard_reset, NULL);
@@ -107,8 +108,16 @@
 	card->p_dev = link;
 	link->priv = priv;
 
-	return orinoco_cs_config(link);
-}				/* orinoco_cs_attach */
+	ret = orinoco_cs_config(link);
+	if (ret)
+		goto err_free_orinocodev;
+
+	return 0;
+
+err_free_orinocodev:
+	free_orinocodev(priv);
+	return ret;
+}
 
 static void orinoco_cs_detach(struct pcmcia_device *link)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intersil/orinoco/orinoco_usb.c
@@ -1234,13 +1234,6 @@
 	if (skb->len < ETH_HLEN)
 		goto drop;
 
-	ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_TX, 0);
-	if (!ctx)
-		goto busy;
-
-	memset(ctx->buf, 0, BULK_BUF_SIZE);
-	buf = ctx->buf->data;
-
 	tx_control = 0;
 
 	err = orinoco_process_xmit_skb(skb, dev, priv, &tx_control,
@@ -1248,6 +1241,13 @@
 	if (err)
 		goto drop;
 
+	ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_TX, 0);
+	if (!ctx)
+		goto drop;
+
+	memset(ctx->buf, 0, BULK_BUF_SIZE);
+	buf = ctx->buf->data;
+
 	{
 		__le16 *tx_cntl = (__le16 *)buf;
 		*tx_cntl = cpu_to_le16(tx_control);
@@ -1361,7 +1361,8 @@
 	int retval;
 
 	BUG_ON(in_interrupt());
-	BUG_ON(!upriv);
+	if (!upriv)
+		return -EINVAL;
 
 	upriv->reply_count = 0;
 	/* Write the MAGIC number on the simulated registers to keep
@@ -1608,9 +1609,9 @@
 	/* set up the endpoint information */
 	/* check out the endpoints */
 
-	iface_desc = &interface->altsetting[0].desc;
+	iface_desc = &interface->cur_altsetting->desc;
 	for (i = 0; i < iface_desc->bNumEndpoints; ++i) {
-		ep = &interface->altsetting[0].endpoint[i].desc;
+		ep = &interface->cur_altsetting->endpoint[i].desc;
 
 		if (usb_endpoint_is_bulk_in(ep)) {
 			/* we found a bulk in endpoint */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intersil/orinoco/spectrum_cs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intersil/orinoco/spectrum_cs.c
@@ -157,6 +157,7 @@
 {
 	struct orinoco_private *priv;
 	struct orinoco_pccard *card;
+	int ret;
 
 	priv = alloc_orinocodev(sizeof(*card), &link->dev,
 				spectrum_cs_hard_reset,
@@ -169,8 +170,16 @@
 	card->p_dev = link;
 	link->priv = priv;
 
-	return spectrum_cs_config(link);
-}				/* spectrum_cs_attach */
+	ret = spectrum_cs_config(link);
+	if (ret)
+		goto err_free_orinocodev;
+
+	return 0;
+
+err_free_orinocodev:
+	free_orinocodev(priv);
+	return ret;
+}
 
 static void spectrum_cs_detach(struct pcmcia_device *link)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intersil/p54/main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intersil/p54/main.c
@@ -682,7 +682,7 @@
 	 * queues have already been stopped and no new frames can sneak
 	 * up from behind.
 	 */
-	while ((total = p54_flush_count(priv) && i--)) {
+	while ((total = p54_flush_count(priv)) && i--) {
 		/* waste time */
 		msleep(20);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intersil/p54/p54pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intersil/p54/p54pci.c
@@ -329,10 +329,12 @@
 	struct p54p_desc *desc;
 	dma_addr_t mapping;
 	u32 idx, i;
+	__le32 device_addr;
 
 	spin_lock_irqsave(&priv->lock, flags);
 	idx = le32_to_cpu(ring_control->host_idx[1]);
 	i = idx % ARRAY_SIZE(ring_control->tx_data);
+	device_addr = ((struct p54_hdr *)skb->data)->req_id;
 
 	mapping = pci_map_single(priv->pdev, skb->data, skb->len,
 				 PCI_DMA_TODEVICE);
@@ -346,7 +348,7 @@
 
 	desc = &ring_control->tx_data[i];
 	desc->host_addr = cpu_to_le32(mapping);
-	desc->device_addr = ((struct p54_hdr *)skb->data)->req_id;
+	desc->device_addr = device_addr;
 	desc->len = cpu_to_le16(skb->len);
 	desc->flags = 0;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intersil/p54/p54spi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intersil/p54/p54spi.c
@@ -164,7 +164,7 @@
 
 	ret = p54_parse_firmware(dev, priv->firmware);
 	if (ret) {
-		release_firmware(priv->firmware);
+		/* the firmware is released by the caller */
 		return ret;
 	}
 
@@ -623,7 +623,7 @@
 	gpio_direction_input(p54spi_gpio_irq);
 
 	ret = request_irq(gpio_to_irq(p54spi_gpio_irq),
-			  p54spi_interrupt, 0, "p54spi",
+			  p54spi_interrupt, IRQF_NO_AUTOEN, "p54spi",
 			  priv->spi);
 	if (ret < 0) {
 		dev_err(&priv->spi->dev, "request_irq() failed");
@@ -632,8 +632,6 @@
 
 	irq_set_irq_type(gpio_to_irq(p54spi_gpio_irq), IRQ_TYPE_EDGE_RISING);
 
-	disable_irq(gpio_to_irq(p54spi_gpio_irq));
-
 	INIT_WORK(&priv->work, p54spi_work);
 	init_completion(&priv->fw_comp);
 	INIT_LIST_HEAD(&priv->tx_pending);
@@ -659,6 +657,7 @@
 	return 0;
 
 err_free_common:
+	release_firmware(priv->firmware);
 	free_irq(gpio_to_irq(p54spi_gpio_irq), spi);
 err_free_gpio_irq:
 	gpio_free(p54spi_gpio_irq);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/intersil/p54/p54usb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/intersil/p54/p54usb.c
@@ -61,6 +61,7 @@
 	{USB_DEVICE(0x0db0, 0x6826)},	/* MSI UB54G (MS-6826) */
 	{USB_DEVICE(0x107b, 0x55f2)},	/* Gateway WGU-210 (Gemtek) */
 	{USB_DEVICE(0x124a, 0x4023)},	/* Shuttle PN15, Airvast WM168g, IOGear GWU513 */
+	{USB_DEVICE(0x124a, 0x4026)},	/* AirVasT USB wireless device */
 	{USB_DEVICE(0x1435, 0x0210)},	/* Inventel UR054G */
 	{USB_DEVICE(0x15a9, 0x0002)},	/* Gemtek WUBI-100GW 802.11g */
 	{USB_DEVICE(0x1630, 0x0005)},	/* 2Wire 802.11g USB (v1) / Z-Com */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/mac80211_hwsim.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/mac80211_hwsim.c
@@ -527,7 +527,7 @@
 	bool ps_poll_pending;
 	struct dentry *debugfs;
 
-	uintptr_t pending_cookie;
+	atomic_t pending_cookie;
 	struct sk_buff_head pending;	/* packets pending */
 	/*
 	 * Only radios in the same group can communicate together (the
@@ -663,6 +663,7 @@
 	struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
 	struct sk_buff *skb;
 	struct ieee80211_hdr *hdr;
+	struct ieee80211_tx_info *cb;
 
 	if (!vp->assoc)
 		return;
@@ -684,6 +685,10 @@
 	memcpy(hdr->addr2, mac, ETH_ALEN);
 	memcpy(hdr->addr3, vp->bssid, ETH_ALEN);
 
+	cb = IEEE80211_SKB_CB(skb);
+	cb->control.rates[0].count = 1;
+	cb->control.rates[1].idx = -1;
+
 	rcu_read_lock();
 	mac80211_hwsim_tx_frame(data->hw, skb,
 				rcu_dereference(vif->chanctx_conf)->def.chan);
@@ -1113,8 +1118,7 @@
 		goto nla_put_failure;
 
 	/* We create a cookie to identify this skb */
-	data->pending_cookie++;
-	cookie = data->pending_cookie;
+	cookie = atomic_inc_return(&data->pending_cookie);
 	info->rate_driver_data[0] = (void *)cookie;
 	if (nla_put_u64_64bit(skb, HWSIM_ATTR_COOKIE, cookie, HWSIM_ATTR_PAD))
 		goto nla_put_failure;
@@ -1458,8 +1462,13 @@
 static void mac80211_hwsim_stop(struct ieee80211_hw *hw)
 {
 	struct mac80211_hwsim_data *data = hw->priv;
+
 	data->started = false;
 	hrtimer_cancel(&data->beacon_timer);
+
+	while (!skb_queue_empty(&data->pending))
+		ieee80211_free_txskb(hw, skb_dequeue(&data->pending));
+
 	wiphy_dbg(hw->wiphy, "%s\n", __func__);
 }
 
@@ -1598,8 +1607,8 @@
 		bcn_int -= data->bcn_delta;
 		data->bcn_delta = 0;
 	}
-	hrtimer_forward(&data->beacon_timer, hrtimer_get_expires(timer),
-			ns_to_ktime(bcn_int * NSEC_PER_USEC));
+	hrtimer_forward_now(&data->beacon_timer,
+			    ns_to_ktime(bcn_int * NSEC_PER_USEC));
 	return HRTIMER_RESTART;
 }
 
@@ -1979,8 +1988,7 @@
 
 	switch (action) {
 	case IEEE80211_AMPDU_TX_START:
-		ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
-		break;
+		return IEEE80211_AMPDU_TX_START_IMMEDIATE;
 	case IEEE80211_AMPDU_TX_STOP_CONT:
 	case IEEE80211_AMPDU_TX_STOP_FLUSH:
 	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
@@ -2057,9 +2065,21 @@
 			if (req->ie_len)
 				skb_put_data(probe, req->ie, req->ie_len);
 
+			rcu_read_lock();
+			if (!ieee80211_tx_prepare_skb(hwsim->hw,
+						      hwsim->hw_scan_vif,
+						      probe,
+						      hwsim->tmp_chan->band,
+						      NULL)) {
+				rcu_read_unlock();
+				kfree_skb(probe);
+				continue;
+			}
+
 			local_bh_disable();
 			mac80211_hwsim_tx_frame(hwsim->hw, probe,
 						hwsim->tmp_chan);
+			rcu_read_unlock();
 			local_bh_enable();
 		}
 	}
@@ -2302,7 +2322,7 @@
 					  u32 sset, u8 *data)
 {
 	if (sset == ETH_SS_STATS)
-		memcpy(data, *mac80211_hwsim_gstrings_stats,
+		memcpy(data, mac80211_hwsim_gstrings_stats,
 		       sizeof(mac80211_hwsim_gstrings_stats));
 }
 
@@ -3243,6 +3263,7 @@
 	const u8 *src;
 	unsigned int hwsim_flags;
 	int i;
+	unsigned long flags;
 	bool found = false;
 
 	if (!info->attrs[HWSIM_ATTR_ADDR_TRANSMITTER] ||
@@ -3267,18 +3288,20 @@
 		goto out;
 
 	/* look for the skb matching the cookie passed back from user */
+	spin_lock_irqsave(&data2->pending.lock, flags);
 	skb_queue_walk_safe(&data2->pending, skb, tmp) {
-		u64 skb_cookie;
+		uintptr_t skb_cookie;
 
 		txi = IEEE80211_SKB_CB(skb);
-		skb_cookie = (u64)(uintptr_t)txi->rate_driver_data[0];
+		skb_cookie = (uintptr_t)txi->rate_driver_data[0];
 
 		if (skb_cookie == ret_skb_cookie) {
-			skb_unlink(skb, &data2->pending);
+			__skb_unlink(skb, &data2->pending);
 			found = true;
 			break;
 		}
 	}
+	spin_unlock_irqrestore(&data2->pending.lock, flags);
 
 	/* not found */
 	if (!found)
@@ -3311,6 +3334,10 @@
 		}
 		txi->flags |= IEEE80211_TX_STAT_ACK;
 	}
+
+	if (hwsim_flags & HWSIM_TX_CTL_NO_ACK)
+		txi->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED;
+
 	ieee80211_tx_status_irqsafe(data2->hw, skb);
 	return 0;
 out:
@@ -3339,14 +3366,15 @@
 	frame_data_len = nla_len(info->attrs[HWSIM_ATTR_FRAME]);
 	frame_data = (void *)nla_data(info->attrs[HWSIM_ATTR_FRAME]);
 
+	if (frame_data_len < sizeof(struct ieee80211_hdr_3addr) ||
+	    frame_data_len > IEEE80211_MAX_DATA_LEN)
+		goto err;
+
 	/* Allocate new skb here */
 	skb = alloc_skb(frame_data_len, GFP_KERNEL);
 	if (skb == NULL)
 		goto err;
 
-	if (frame_data_len > IEEE80211_MAX_DATA_LEN)
-		goto err;
-
 	/* Copy the data */
 	skb_put_data(skb, frame_data, frame_data_len);
 
@@ -3388,6 +3416,8 @@
 
 	rx_status.band = data2->channel->band;
 	rx_status.rate_idx = nla_get_u32(info->attrs[HWSIM_ATTR_RX_RATE]);
+	if (rx_status.rate_idx >= data2->hw->wiphy->bands[rx_status.band]->n_bitrates)
+		goto out;
 	rx_status.signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]);
 
 	hdr = (void *)skb->data;
@@ -3575,9 +3605,9 @@
 	}
 
 	if (info->attrs[HWSIM_ATTR_RADIO_NAME]) {
-		hwname = kasprintf(GFP_KERNEL, "%.*s",
-				   nla_len(info->attrs[HWSIM_ATTR_RADIO_NAME]),
-				   (char *)nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]));
+		hwname = kstrndup((char *)nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]),
+				  nla_len(info->attrs[HWSIM_ATTR_RADIO_NAME]),
+				  GFP_KERNEL);
 		if (!hwname)
 			return -ENOMEM;
 		param.hwname = hwname;
@@ -3597,9 +3627,9 @@
 	if (info->attrs[HWSIM_ATTR_RADIO_ID]) {
 		idx = nla_get_u32(info->attrs[HWSIM_ATTR_RADIO_ID]);
 	} else if (info->attrs[HWSIM_ATTR_RADIO_NAME]) {
-		hwname = kasprintf(GFP_KERNEL, "%.*s",
-				   nla_len(info->attrs[HWSIM_ATTR_RADIO_NAME]),
-				   (char *)nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]));
+		hwname = kstrndup((char *)nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]),
+				  nla_len(info->attrs[HWSIM_ATTR_RADIO_NAME]),
+				  GFP_KERNEL);
 		if (!hwname)
 			return -ENOMEM;
 	} else
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/libertas/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/libertas/Kconfig
@@ -2,8 +2,6 @@
 config LIBERTAS
 	tristate "Marvell 8xxx Libertas WLAN driver support"
 	depends on CFG80211
-	select WIRELESS_EXT
-	select WEXT_SPY
 	select LIB80211
 	select FW_LOADER
 	---help---
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/libertas/cfg.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/libertas/cfg.c
@@ -273,6 +273,10 @@
 	int hw, ap, ap_max = ie[1];
 	u8 hw_rate;
 
+	if (ap_max > MAX_RATES) {
+		lbs_deb_assoc("invalid rates\n");
+		return tlv;
+	}
 	/* Advance past IE header */
 	ie += 2;
 
@@ -1777,6 +1781,12 @@
 	} else {
 		int hw, i;
 		u8 rates_max = rates_eid[1];
+		if (rates_max > MAX_RATES) {
+			lbs_deb_join("invalid rates");
+			rcu_read_unlock();
+			ret = -EINVAL;
+			goto out;
+		}
 		u8 *rates = cmd.bss.rates;
 		for (hw = 0; hw < ARRAY_SIZE(lbs_rates); hw++) {
 			u8 hw_rate = lbs_rates[hw].bitrate / 5;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/libertas/cmd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/libertas/cmd.c
@@ -1133,7 +1133,7 @@
 		if (!cmdarray[i].cmdbuf) {
 			lbs_deb_host("ALLOC_CMD_BUF: ptempvirtualaddr is NULL\n");
 			ret = -1;
-			goto done;
+			goto free_cmd_array;
 		}
 	}
 
@@ -1141,8 +1141,17 @@
 		init_waitqueue_head(&cmdarray[i].cmdwait_q);
 		lbs_cleanup_and_insert_cmd(priv, &cmdarray[i]);
 	}
-	ret = 0;
+	return 0;
 
+free_cmd_array:
+	for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
+		if (cmdarray[i].cmdbuf) {
+			kfree(cmdarray[i].cmdbuf);
+			cmdarray[i].cmdbuf = NULL;
+		}
+	}
+	kfree(priv->cmd_array);
+	priv->cmd_array = NULL;
 done:
 	return ret;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/libertas/cmdresp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/libertas/cmdresp.c
@@ -48,7 +48,7 @@
 
 	/* Free Tx and Rx packets */
 	spin_lock_irqsave(&priv->driver_lock, flags);
-	kfree_skb(priv->currenttxskb);
+	dev_kfree_skb_irq(priv->currenttxskb);
 	priv->currenttxskb = NULL;
 	priv->tx_pending_len = 0;
 	spin_unlock_irqrestore(&priv->driver_lock, flags);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/libertas/if_sdio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/libertas/if_sdio.c
@@ -1179,6 +1179,10 @@
 
 	spin_lock_init(&card->lock);
 	card->workqueue = alloc_workqueue("libertas_sdio", WQ_MEM_RECLAIM, 0);
+	if (unlikely(!card->workqueue)) {
+		ret = -ENOMEM;
+		goto err_queue;
+	}
 	INIT_WORK(&card->packet_worker, if_sdio_host_to_card_worker);
 	init_waitqueue_head(&card->pwron_waitq);
 
@@ -1230,6 +1234,7 @@
 	lbs_remove_card(priv);
 free:
 	destroy_workqueue(card->workqueue);
+err_queue:
 	while (card->packets) {
 		packet = card->packets;
 		card->packets = card->packets->next;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/libertas/if_usb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/libertas/if_usb.c
@@ -287,11 +287,13 @@
 	return 0;
 
 err_get_fw:
+	usb_put_dev(udev);
 	lbs_remove_card(priv);
 err_add_card:
 	if_usb_reset_device(cardp);
 dealloc:
 	if_usb_free(cardp);
+	kfree(cardp);
 
 error:
 	return r;
@@ -316,6 +318,7 @@
 
 	/* Unlink and free urb */
 	if_usb_free(cardp);
+	kfree(cardp);
 
 	usb_set_intfdata(intf, NULL);
 	usb_put_dev(interface_to_usbdev(intf));
@@ -634,7 +637,7 @@
 	priv->resp_len[i] = (recvlength - MESSAGE_HEADER_LEN);
 	memcpy(priv->resp_buf[i], recvbuff + MESSAGE_HEADER_LEN,
 		priv->resp_len[i]);
-	kfree_skb(skb);
+	dev_kfree_skb_irq(skb);
 	lbs_notify_command_response(priv, i);
 
 	spin_unlock_irqrestore(&priv->driver_lock, flags);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/libertas/main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/libertas/main.c
@@ -217,7 +217,7 @@
 
 	spin_lock_irqsave(&priv->driver_lock, flags);
 	priv->iface_running = false;
-	kfree_skb(priv->currenttxskb);
+	dev_kfree_skb_irq(priv->currenttxskb);
 	priv->currenttxskb = NULL;
 	priv->tx_pending_len = 0;
 	spin_unlock_irqrestore(&priv->driver_lock, flags);
@@ -870,6 +870,7 @@
 	ret = kfifo_alloc(&priv->event_fifo, sizeof(u32) * 16, GFP_KERNEL);
 	if (ret) {
 		pr_err("Out of memory allocating event FIFO buffer\n");
+		lbs_free_cmd_buffer(priv);
 		goto out;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/libertas/mesh.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/libertas/mesh.c
@@ -801,24 +801,6 @@
 	.attrs = mesh_ie_attrs,
 };
 
-static void lbs_persist_config_init(struct net_device *dev)
-{
-	int ret;
-	ret = sysfs_create_group(&(dev->dev.kobj), &boot_opts_group);
-	if (ret)
-		pr_err("failed to create boot_opts_group.\n");
-
-	ret = sysfs_create_group(&(dev->dev.kobj), &mesh_ie_group);
-	if (ret)
-		pr_err("failed to create mesh_ie_group.\n");
-}
-
-static void lbs_persist_config_remove(struct net_device *dev)
-{
-	sysfs_remove_group(&(dev->dev.kobj), &boot_opts_group);
-	sysfs_remove_group(&(dev->dev.kobj), &mesh_ie_group);
-}
-
 
 /***************************************************************************
  * Initializing and starting, stopping mesh
@@ -1019,6 +1001,10 @@
 	SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent);
 
 	mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
+	mesh_dev->sysfs_groups[0] = &lbs_mesh_attr_group;
+	mesh_dev->sysfs_groups[1] = &boot_opts_group;
+	mesh_dev->sysfs_groups[2] = &mesh_ie_group;
+
 	/* Register virtual mesh interface */
 	ret = register_netdev(mesh_dev);
 	if (ret) {
@@ -1026,19 +1012,10 @@
 		goto err_free_netdev;
 	}
 
-	ret = sysfs_create_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
-	if (ret)
-		goto err_unregister;
-
-	lbs_persist_config_init(mesh_dev);
-
 	/* Everything successful */
 	ret = 0;
 	goto done;
 
-err_unregister:
-	unregister_netdev(mesh_dev);
-
 err_free_netdev:
 	free_netdev(mesh_dev);
 
@@ -1059,8 +1036,6 @@
 
 	netif_stop_queue(mesh_dev);
 	netif_carrier_off(mesh_dev);
-	sysfs_remove_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
-	lbs_persist_config_remove(mesh_dev);
 	unregister_netdev(mesh_dev);
 	priv->mesh_dev = NULL;
 	kfree(mesh_dev->ieee80211_ptr);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/libertas_tf/if_usb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/libertas_tf/if_usb.c
@@ -230,6 +230,7 @@
 
 dealloc:
 	if_usb_free(cardp);
+	kfree(cardp);
 error:
 lbtf_deb_leave(LBTF_DEB_MAIN);
 	return -ENOMEM;
@@ -247,13 +248,14 @@
 
 	lbtf_deb_enter(LBTF_DEB_MAIN);
 
-	if_usb_reset_device(priv);
-
-	if (priv)
+	if (priv) {
+		if_usb_reset_device(priv);
 		lbtf_remove_card(priv);
+	}
 
 	/* Unlink and free urb */
 	if_usb_free(cardp);
+	kfree(cardp);
 
 	usb_set_intfdata(intf, NULL);
 	usb_put_dev(interface_to_usbdev(intf));
@@ -611,7 +613,7 @@
 	spin_lock_irqsave(&priv->driver_lock, flags);
 	memcpy(priv->cmd_resp_buff, recvbuff + MESSAGE_HEADER_LEN,
 	       recvlength - MESSAGE_HEADER_LEN);
-	kfree_skb(skb);
+	dev_kfree_skb_irq(skb);
 	lbtf_cmd_response_rx(priv);
 	spin_unlock_irqrestore(&priv->driver_lock, flags);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/mwifiex/11h.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/mwifiex/11h.c
@@ -303,5 +303,7 @@
 
 	mwifiex_dbg(priv->adapter, MSG,
 		    "indicating channel switch completion to kernel\n");
+	mutex_lock(&priv->wdev.mtx);
 	cfg80211_ch_switch_notify(priv->netdev, &priv->dfs_chandef);
+	mutex_unlock(&priv->wdev.mtx);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/mwifiex/11n.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/mwifiex/11n.c
@@ -657,14 +657,15 @@
 	uint16_t del_ba_param_set;
 
 	memset(&delba, 0, sizeof(delba));
-	delba.del_ba_param_set = cpu_to_le16(tid << DELBA_TID_POS);
 
-	del_ba_param_set = le16_to_cpu(delba.del_ba_param_set);
+	del_ba_param_set = tid << DELBA_TID_POS;
+
 	if (initiator)
 		del_ba_param_set |= IEEE80211_DELBA_PARAM_INITIATOR_MASK;
 	else
 		del_ba_param_set &= ~IEEE80211_DELBA_PARAM_INITIATOR_MASK;
 
+	delba.del_ba_param_set = cpu_to_le16(del_ba_param_set);
 	memcpy(&delba.peer_mac_addr, peer_mac, ETH_ALEN);
 
 	/* We don't wait for the response of this command */
@@ -889,7 +890,7 @@
  */
 void mwifiex_update_ampdu_txwinsize(struct mwifiex_adapter *adapter)
 {
-	u8 i;
+	u8 i, j;
 	u32 tx_win_size;
 	struct mwifiex_private *priv;
 
@@ -920,8 +921,8 @@
 		if (tx_win_size != priv->add_ba_param.tx_win_size) {
 			if (!priv->media_connected)
 				continue;
-			for (i = 0; i < MAX_NUM_TID; i++)
-				mwifiex_send_delba_txbastream_tbl(priv, i);
+			for (j = 0; j < MAX_NUM_TID; j++)
+				mwifiex_send_delba_txbastream_tbl(priv, j);
 		}
 	}
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
@@ -977,8 +977,8 @@
 			}
 		}
 
-		tlv_buf_left -= (sizeof(*tlv_rxba) + tlv_len);
-		tmp = (u8 *)tlv_rxba + tlv_len + sizeof(*tlv_rxba);
+		tlv_buf_left -= (sizeof(tlv_rxba->header) + tlv_len);
+		tmp = (u8 *)tlv_rxba  + sizeof(tlv_rxba->header) + tlv_len;
 		tlv_rxba = (struct mwifiex_ie_types_rxba_sync *)tmp;
 	}
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -912,16 +912,20 @@
 	switch (type) {
 	case NL80211_IFTYPE_STATION:
 	case NL80211_IFTYPE_ADHOC:
-		priv->bss_role =  MWIFIEX_BSS_ROLE_STA;
+		priv->bss_role = MWIFIEX_BSS_ROLE_STA;
+		priv->bss_type = MWIFIEX_BSS_TYPE_STA;
 		break;
 	case NL80211_IFTYPE_P2P_CLIENT:
-		priv->bss_role =  MWIFIEX_BSS_ROLE_STA;
+		priv->bss_role = MWIFIEX_BSS_ROLE_STA;
+		priv->bss_type = MWIFIEX_BSS_TYPE_P2P;
 		break;
 	case NL80211_IFTYPE_P2P_GO:
-		priv->bss_role =  MWIFIEX_BSS_ROLE_UAP;
+		priv->bss_role = MWIFIEX_BSS_ROLE_UAP;
+		priv->bss_type = MWIFIEX_BSS_TYPE_P2P;
 		break;
 	case NL80211_IFTYPE_AP:
 		priv->bss_role = MWIFIEX_BSS_ROLE_UAP;
+		priv->bss_type = MWIFIEX_BSS_TYPE_UAP;
 		break;
 	default:
 		mwifiex_dbg(adapter, ERROR,
@@ -930,6 +934,8 @@
 		return -EOPNOTSUPP;
 	}
 
+	priv->bss_num = mwifiex_get_unused_bss_num(adapter, priv->bss_type);
+
 	spin_lock_irqsave(&adapter->main_proc_lock, flags);
 	adapter->main_locked = false;
 	spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
@@ -1233,29 +1239,15 @@
 		break;
 	case NL80211_IFTYPE_P2P_CLIENT:
 	case NL80211_IFTYPE_P2P_GO:
+		if (mwifiex_cfg80211_deinit_p2p(priv))
+			return -EFAULT;
+
 		switch (type) {
-		case NL80211_IFTYPE_STATION:
-			if (mwifiex_cfg80211_deinit_p2p(priv))
-				return -EFAULT;
-			priv->adapter->curr_iface_comb.p2p_intf--;
-			priv->adapter->curr_iface_comb.sta_intf++;
-			dev->ieee80211_ptr->iftype = type;
-			if (mwifiex_deinit_priv_params(priv))
-				return -1;
-			if (mwifiex_init_new_priv_params(priv, dev, type))
-				return -1;
-			if (mwifiex_sta_init_cmd(priv, false, false))
-				return -1;
-			break;
 		case NL80211_IFTYPE_ADHOC:
-			if (mwifiex_cfg80211_deinit_p2p(priv))
-				return -EFAULT;
+		case NL80211_IFTYPE_STATION:
 			return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype,
 							       type, params);
-			break;
 		case NL80211_IFTYPE_AP:
-			if (mwifiex_cfg80211_deinit_p2p(priv))
-				return -EFAULT;
 			return mwifiex_change_vif_to_ap(dev, curr_iftype, type,
 							params);
 		case NL80211_IFTYPE_UNSPECIFIED:
@@ -1496,7 +1488,8 @@
 			      int idx, u8 *mac, struct station_info *sinfo)
 {
 	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-	static struct mwifiex_sta_node *node;
+	struct mwifiex_sta_node *node;
+	int i;
 
 	if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
 	    priv->media_connected && idx == 0) {
@@ -1506,13 +1499,10 @@
 		mwifiex_send_cmd(priv, HOST_CMD_APCMD_STA_LIST,
 				 HostCmd_ACT_GEN_GET, 0, NULL, true);
 
-		if (node && (&node->list == &priv->sta_list)) {
-			node = NULL;
-			return -ENOENT;
-		}
-
-		node = list_prepare_entry(node, &priv->sta_list, list);
-		list_for_each_entry_continue(node, &priv->sta_list, list) {
+		i = 0;
+		list_for_each_entry(node, &priv->sta_list, list) {
+			if (i++ != idx)
+				continue;
 			ether_addr_copy(mac, node->mac_addr);
 			return mwifiex_dump_station_info(priv, node, sinfo);
 		}
@@ -1996,6 +1986,8 @@
 
 	mwifiex_set_sys_config_invalid_data(bss_cfg);
 
+	memcpy(bss_cfg->mac_addr, priv->curr_addr, ETH_ALEN);
+
 	if (params->beacon_interval)
 		bss_cfg->beacon_period = params->beacon_interval;
 	if (params->dtim_period)
@@ -4327,11 +4319,27 @@
 	if (ISSUPP_ADHOC_ENABLED(adapter->fw_cap_info))
 		wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);
 
-	wiphy->bands[NL80211_BAND_2GHZ] = &mwifiex_band_2ghz;
-	if (adapter->config_bands & BAND_A)
-		wiphy->bands[NL80211_BAND_5GHZ] = &mwifiex_band_5ghz;
-	else
+	wiphy->bands[NL80211_BAND_2GHZ] = devm_kmemdup(adapter->dev,
+						       &mwifiex_band_2ghz,
+						       sizeof(mwifiex_band_2ghz),
+						       GFP_KERNEL);
+	if (!wiphy->bands[NL80211_BAND_2GHZ]) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	if (adapter->config_bands & BAND_A) {
+		wiphy->bands[NL80211_BAND_5GHZ] = devm_kmemdup(adapter->dev,
+							       &mwifiex_band_5ghz,
+							       sizeof(mwifiex_band_5ghz),
+							       GFP_KERNEL);
+		if (!wiphy->bands[NL80211_BAND_5GHZ]) {
+			ret = -ENOMEM;
+			goto err;
+		}
+	} else {
 		wiphy->bands[NL80211_BAND_5GHZ] = NULL;
+	}
 
 	if (adapter->drcs_enabled && ISSUPP_DRCS_ENABLED(adapter->fw_cap_info))
 		wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta_drcs;
@@ -4419,8 +4427,7 @@
 	if (ret < 0) {
 		mwifiex_dbg(adapter, ERROR,
 			    "%s: wiphy_register failed: %d\n", __func__, ret);
-		wiphy_free(wiphy);
-		return ret;
+		goto err;
 	}
 
 	if (!adapter->regd) {
@@ -4462,4 +4469,9 @@
 
 	adapter->wiphy = wiphy;
 	return ret;
+
+err:
+	wiphy_free(wiphy);
+
+	return ret;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/mwifiex/cmdevt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/mwifiex/cmdevt.c
@@ -322,9 +322,9 @@
 
 	adapter->seq_num++;
 	sleep_cfm_buf->seq_num =
-		cpu_to_le16((HostCmd_SET_SEQ_NO_BSS_INFO
+		cpu_to_le16(HostCmd_SET_SEQ_NO_BSS_INFO
 					(adapter->seq_num, priv->bss_num,
-					 priv->bss_type)));
+					 priv->bss_type));
 
 	mwifiex_dbg(adapter, CMD,
 		    "cmd: DNLD_CMD: %#x, act %#x, len %d, seqno %#x\n",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/mwifiex/debugfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/mwifiex/debugfs.c
@@ -265,8 +265,11 @@
 	if (!p)
 		return -ENOMEM;
 
-	if (!priv || !priv->hist_data)
-		return -EFAULT;
+	if (!priv || !priv->hist_data) {
+		ret = -EFAULT;
+		goto free_and_exit;
+	}
+
 	phist_data = priv->hist_data;
 
 	p += sprintf(p, "\n"
@@ -321,6 +324,8 @@
 	ret = simple_read_from_buffer(ubuf, count, ppos, (char *)page,
 				      (unsigned long)p - page);
 
+free_and_exit:
+	free_page(page);
 	return ret;
 }
 
@@ -971,9 +976,6 @@
 	priv->dfs_dev_dir = debugfs_create_dir(priv->netdev->name,
 					       mwifiex_dfs_dir);
 
-	if (!priv->dfs_dev_dir)
-		return;
-
 	MWIFIEX_DFS_ADD_FILE(info);
 	MWIFIEX_DFS_ADD_FILE(debug);
 	MWIFIEX_DFS_ADD_FILE(getlog);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/mwifiex/fw.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/mwifiex/fw.h
@@ -177,6 +177,7 @@
 #define TLV_TYPE_STA_MAC_ADDR       (PROPRIETARY_TLV_BASE_ID + 32)
 #define TLV_TYPE_BSSID              (PROPRIETARY_TLV_BASE_ID + 35)
 #define TLV_TYPE_CHANNELBANDLIST    (PROPRIETARY_TLV_BASE_ID + 42)
+#define TLV_TYPE_UAP_MAC_ADDRESS    (PROPRIETARY_TLV_BASE_ID + 43)
 #define TLV_TYPE_UAP_BEACON_PERIOD  (PROPRIETARY_TLV_BASE_ID + 44)
 #define TLV_TYPE_UAP_DTIM_PERIOD    (PROPRIETARY_TLV_BASE_ID + 45)
 #define TLV_TYPE_UAP_BCAST_SSID     (PROPRIETARY_TLV_BASE_ID + 48)
@@ -217,6 +218,7 @@
 #define TLV_TYPE_CHANNEL_STATS      (PROPRIETARY_TLV_BASE_ID + 198)
 #define TLV_BTCOEX_WL_AGGR_WINSIZE  (PROPRIETARY_TLV_BASE_ID + 202)
 #define TLV_BTCOEX_WL_SCANTIME      (PROPRIETARY_TLV_BASE_ID + 203)
+#define TLV_TYPE_LED_CONTROL        (PROPRIETARY_TLV_BASE_ID + 205)
 #define TLV_TYPE_BSS_MODE           (PROPRIETARY_TLV_BASE_ID + 206)
 #define TLV_TYPE_RANDOM_MAC         (PROPRIETARY_TLV_BASE_ID + 236)
 #define TLV_TYPE_CHAN_ATTR_CFG      (PROPRIETARY_TLV_BASE_ID + 237)
@@ -363,6 +365,7 @@
 #define HostCmd_CMD_802_11_AD_HOC_JOIN                0x002c
 #define HostCmd_CMD_802_11_AD_HOC_STOP                0x0040
 #define HostCmd_CMD_802_11_MAC_ADDRESS                0x004D
+#define HostCmd_CMD_802_11_LED_CONTROL                0X004E
 #define HostCmd_CMD_802_11D_DOMAIN_INFO               0x005b
 #define HostCmd_CMD_802_11_KEY_MATERIAL               0x005e
 #define HostCmd_CMD_802_11_BG_SCAN_CONFIG             0x006b
@@ -512,10 +515,10 @@
 
 #define RF_ANTENNA_AUTO                 0xFFFF
 
-#define HostCmd_SET_SEQ_NO_BSS_INFO(seq, num, type) {   \
-	(((seq) & 0x00ff) |                             \
-	 (((num) & 0x000f) << 8)) |                     \
-	(((type) & 0x000f) << 12);                  }
+#define HostCmd_SET_SEQ_NO_BSS_INFO(seq, num, type) \
+	((((seq) & 0x00ff) |                        \
+	 (((num) & 0x000f) << 8)) |                 \
+	(((type) & 0x000f) << 12))
 
 #define HostCmd_GET_SEQ_NO(seq)       \
 	((seq) & HostCmd_SEQ_NUM_MASK)
@@ -852,7 +855,7 @@
 struct mwifiex_ie_types_wildcard_ssid_params {
 	struct mwifiex_ie_types_header header;
 	u8 max_ssid_length;
-	u8 ssid[1];
+	u8 ssid[];
 } __packed;
 
 #define TSF_DATA_SIZE            8
@@ -953,7 +956,7 @@
 struct mwifiex_aes_param {
 	u8 pn[WPA_PN_SIZE];
 	__le16 key_len;
-	u8 key[WLAN_KEY_LEN_CCMP];
+	u8 key[WLAN_KEY_LEN_CCMP_256];
 } __packed;
 
 struct mwifiex_wapi_param {
@@ -1193,6 +1196,16 @@
 	u8 oper_mode;
 } __packed;
 
+struct mwifiex_led_param {
+	__le16 mode;
+	__le16 on;
+} __packed;
+
+struct mwifiex_ie_types_led_param {
+	struct mwifiex_ie_types_header header;
+	struct mwifiex_led_param led_cfg;
+} __packed;
+
 struct host_cmd_ds_802_11_ad_hoc_start {
 	u8 ssid[IEEE80211_MAX_SSID_LEN];
 	u8 bss_mode;
@@ -1316,6 +1329,11 @@
 	} params;
 } __packed;
 
+struct host_cmd_ds_802_11_led_control {
+	__le16 action;
+	__le16 num_led;
+} __packed;
+
 enum SNMP_MIB_INDEX {
 	OP_RATE_SET_I = 1,
 	DTIM_PERIOD_I = 3,
@@ -1589,7 +1607,7 @@
 
 struct host_cmd_ds_802_11_scan_ext {
 	u32   reserved;
-	u8    tlv_buffer[1];
+	u8    tlv_buffer[];
 } __packed;
 
 struct mwifiex_ie_types_bss_mode {
@@ -2370,6 +2388,7 @@
 		struct host_cmd_sdio_sp_rx_aggr_cfg sdio_rx_aggr_cfg;
 		struct host_cmd_ds_multi_chan_policy mc_policy;
 		struct host_cmd_ds_robust_coex coex;
+		struct host_cmd_ds_802_11_led_control led_cfg;
 		struct host_cmd_ds_wakeup_reason hs_wakeup_reason;
 		struct host_cmd_ds_gtk_rekey_params rekey;
 		struct host_cmd_ds_chan_region_cfg reg_cfg;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/mwifiex/ioctl.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/mwifiex/ioctl.h
@@ -119,6 +119,7 @@
 	u8 qos_info;
 	u8 power_constraint;
 	struct mwifiex_types_wmm_info wmm_info;
+	u8 mac_addr[ETH_ALEN];
 };
 
 enum {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/mwifiex/join.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/mwifiex/join.c
@@ -877,6 +877,8 @@
 
 	memset(adhoc_start->ssid, 0, IEEE80211_MAX_SSID_LEN);
 
+	if (req_ssid->ssid_len > IEEE80211_MAX_SSID_LEN)
+		req_ssid->ssid_len = IEEE80211_MAX_SSID_LEN;
 	memcpy(adhoc_start->ssid, req_ssid->ssid, req_ssid->ssid_len);
 
 	mwifiex_dbg(adapter, INFO, "info: ADHOC_S_CMD: SSID = %s\n",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/mwifiex/main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/mwifiex/main.c
@@ -631,6 +631,7 @@
 
 	mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1);
 	mwifiex_dbg(adapter, MSG, "driver_version = %s\n", fmt);
+	adapter->is_up = true;
 	goto done;
 
 err_add_intf:
@@ -727,8 +728,10 @@
 static int
 mwifiex_open(struct net_device *dev)
 {
-	netif_carrier_off(dev);
+	struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
 
+	netif_carrier_off(dev);
+	mwifiex_set_led(priv->adapter, MWIFIEX_LED_ON);
 	return 0;
 }
 
@@ -759,6 +762,7 @@
 		cfg80211_sched_scan_stopped(priv->wdev.wiphy, 0);
 	}
 
+	mwifiex_set_led(priv->adapter, MWIFIEX_LED_OFF);
 	return 0;
 }
 
@@ -1468,7 +1472,10 @@
 	priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
 	mwifiex_deauthenticate(priv, NULL);
 
+	mwifiex_init_shutdown_fw(priv, MWIFIEX_FUNC_SHUTDOWN);
+
 	mwifiex_uninit_sw(adapter);
+	adapter->is_up = false;
 
 	if (adapter->if_ops.down_dev)
 		adapter->if_ops.down_dev(adapter);
@@ -1596,7 +1603,8 @@
 	}
 
 	ret = devm_request_irq(dev, adapter->irq_wakeup,
-			       mwifiex_irq_wakeup_handler, IRQF_TRIGGER_LOW,
+			       mwifiex_irq_wakeup_handler,
+			       IRQF_TRIGGER_LOW | IRQF_NO_AUTOEN,
 			       "wifi_wake", adapter);
 	if (ret) {
 		dev_err(dev, "Failed to request irq_wakeup %d (%d)\n",
@@ -1604,7 +1612,6 @@
 		goto err_exit;
 	}
 
-	disable_irq(adapter->irq_wakeup);
 	if (device_init_wakeup(dev, true)) {
 		dev_err(dev, "fail to init wakeup for mwifiex\n");
 		goto err_exit;
@@ -1730,7 +1737,8 @@
 	if (!adapter)
 		return 0;
 
-	mwifiex_uninit_sw(adapter);
+	if (adapter->is_up)
+		mwifiex_uninit_sw(adapter);
 
 	if (adapter->irq_wakeup >= 0)
 		device_init_wakeup(adapter->dev, false);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/mwifiex/main.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/mwifiex/main.h
@@ -132,6 +132,10 @@
 
 #define PKT_TYPE_MGMT	0xE5
 
+#define MWIFIEX_LED_ON		1
+#define MWIFIEX_LED_OFF		0
+#define MWIFIEX_LED_MAX		3
+
 /*
  * Do not check for data_received for USB, as data_received
  * is handled in mwifiex_usb_recv for USB
@@ -700,6 +704,7 @@
 	struct mwifiex_user_scan_chan hidden_chan[MWIFIEX_USER_SCAN_CHAN_MAX];
 	u8 assoc_resp_ht_param;
 	bool ht_param_present;
+	bool is_edge_gateway;
 };
 
 
@@ -1017,6 +1022,7 @@
 
 	/* For synchronizing FW initialization with device lifecycle. */
 	struct completion *fw_done;
+	bool is_up;
 
 	bool ext_scan;
 	u8 fw_api_ver;
@@ -1294,19 +1300,6 @@
 	return pos;
 }
 
-/* This function return interface number with the same bss_type.
- */
-static inline u8
-mwifiex_get_intf_num(struct mwifiex_adapter *adapter, u8 bss_type)
-{
-	u8 i, num = 0;
-
-	for (i = 0; i < adapter->priv_num; i++)
-		if (adapter->priv[i] && adapter->priv[i]->bss_type == bss_type)
-			num++;
-	return num;
-}
-
 /*
  * This function returns the correct private structure pointer based
  * upon the BSS type and BSS number.
@@ -1319,6 +1312,9 @@
 
 	for (i = 0; i < adapter->priv_num; i++) {
 		if (adapter->priv[i]) {
+			if (adapter->priv[i]->bss_mode == NL80211_IFTYPE_UNSPECIFIED)
+				continue;
+
 			if ((adapter->priv[i]->bss_num == bss_num) &&
 			    (adapter->priv[i]->bss_type == bss_type))
 				break;
@@ -1506,6 +1502,7 @@
 				struct cmd_ctrl_node *cmd_queued);
 int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
 		      struct cfg80211_ssid *req_ssid);
+int mwifiex_set_led(struct mwifiex_adapter *adapter, int on);
 int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type);
 int mwifiex_enable_hs(struct mwifiex_adapter *adapter);
 int mwifiex_disable_auto_ds(struct mwifiex_private *priv);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -50,6 +50,8 @@
 }
 
 static void mwifiex_pcie_work(struct work_struct *work);
+static int mwifiex_pcie_delete_rxbd_ring(struct mwifiex_adapter *adapter);
+static int mwifiex_pcie_delete_evtbd_ring(struct mwifiex_adapter *adapter);
 
 static int
 mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb,
@@ -58,8 +60,8 @@
 	struct pcie_service_card *card = adapter->card;
 	struct mwifiex_dma_mapping mapping;
 
-	mapping.addr = pci_map_single(card->dev, skb->data, size, flags);
-	if (pci_dma_mapping_error(card->dev, mapping.addr)) {
+	mapping.addr = dma_map_single(&card->dev->dev, skb->data, size, flags);
+	if (dma_mapping_error(&card->dev->dev, mapping.addr)) {
 		mwifiex_dbg(adapter, ERROR, "failed to map pci memory!\n");
 		return -1;
 	}
@@ -75,7 +77,7 @@
 	struct mwifiex_dma_mapping mapping;
 
 	mwifiex_get_mapping(skb, &mapping);
-	pci_unmap_single(card->dev, mapping.addr, mapping.len, flags);
+	dma_unmap_single(&card->dev->dev, mapping.addr, mapping.len, flags);
 }
 
 /*
@@ -229,6 +231,8 @@
 					const struct pci_device_id *ent)
 {
 	struct pcie_service_card *card;
+	struct mwifiex_private *priv;
+	struct pci_dev *pdev_host;
 	int ret;
 
 	pr_debug("info: vendor=0x%4.04X device=0x%4.04X rev=%d\n",
@@ -267,6 +271,14 @@
 		return -1;
 	}
 
+	priv = mwifiex_get_priv(card->adapter, MWIFIEX_BSS_ROLE_STA);
+	pdev_host = pci_get_subsys(PCI_ANY_ID, PCI_ANY_ID, 0x1028, 0x0720, NULL);
+	if (!pdev_host)
+		pdev_host = pci_get_subsys(PCI_ANY_ID, PCI_ANY_ID, 0x1028, 0x0733, NULL);
+	if (pdev_host) {
+		priv->is_edge_gateway = true;
+		pci_dev_put(pdev_host);
+	}
 	return 0;
 }
 
@@ -377,6 +389,8 @@
 	clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags);
 	clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &card->work_flags);
 	mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__);
+
+	card->pci_reset_ongoing = true;
 }
 
 /*
@@ -405,6 +419,8 @@
 		dev_err(&pdev->dev, "reinit failed: %d\n", ret);
 	else
 		mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__);
+
+	card->pci_reset_ongoing = false;
 }
 
 static const struct pci_error_handlers mwifiex_pcie_err_handler = {
@@ -461,10 +477,9 @@
 	struct sk_buff *cmdrsp = card->cmdrsp_buf;
 
 	for (count = 0; count < max_delay_loop_cnt; count++) {
-		pci_dma_sync_single_for_cpu(card->dev,
-					    MWIFIEX_SKB_DMA_ADDR(cmdrsp),
-					    sizeof(sleep_cookie),
-					    PCI_DMA_FROMDEVICE);
+		dma_sync_single_for_cpu(&card->dev->dev,
+					MWIFIEX_SKB_DMA_ADDR(cmdrsp),
+					sizeof(sleep_cookie), DMA_FROM_DEVICE);
 		buffer = cmdrsp->data;
 		sleep_cookie = get_unaligned_le32(buffer);
 
@@ -473,10 +488,10 @@
 				    "sleep cookie found at count %d\n", count);
 			break;
 		}
-		pci_dma_sync_single_for_device(card->dev,
-					       MWIFIEX_SKB_DMA_ADDR(cmdrsp),
-					       sizeof(sleep_cookie),
-					       PCI_DMA_FROMDEVICE);
+		dma_sync_single_for_device(&card->dev->dev,
+					   MWIFIEX_SKB_DMA_ADDR(cmdrsp),
+					   sizeof(sleep_cookie),
+					   DMA_FROM_DEVICE);
 		usleep_range(20, 30);
 	}
 
@@ -624,14 +639,15 @@
 		if (!skb) {
 			mwifiex_dbg(adapter, ERROR,
 				    "Unable to allocate skb for RX ring.\n");
-			kfree(card->rxbd_ring_vbase);
 			return -ENOMEM;
 		}
 
 		if (mwifiex_map_pci_memory(adapter, skb,
 					   MWIFIEX_RX_DATA_BUF_SIZE,
-					   PCI_DMA_FROMDEVICE))
-			return -1;
+					   DMA_FROM_DEVICE)) {
+			kfree_skb(skb);
+			return -ENOMEM;
+		}
 
 		buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
 
@@ -681,14 +697,15 @@
 		if (!skb) {
 			mwifiex_dbg(adapter, ERROR,
 				    "Unable to allocate skb for EVENT buf.\n");
-			kfree(card->evtbd_ring_vbase);
 			return -ENOMEM;
 		}
 		skb_put(skb, MAX_EVENT_SIZE);
 
 		if (mwifiex_map_pci_memory(adapter, skb, MAX_EVENT_SIZE,
-					   PCI_DMA_FROMDEVICE))
-			return -1;
+					   DMA_FROM_DEVICE)) {
+			kfree_skb(skb);
+			return -ENOMEM;
+		}
 
 		buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
 
@@ -727,7 +744,7 @@
 			if (card->tx_buf_list[i]) {
 				skb = card->tx_buf_list[i];
 				mwifiex_unmap_pci_memory(adapter, skb,
-							 PCI_DMA_TODEVICE);
+							 DMA_TO_DEVICE);
 				dev_kfree_skb_any(skb);
 			}
 			memset(desc2, 0, sizeof(*desc2));
@@ -736,7 +753,7 @@
 			if (card->tx_buf_list[i]) {
 				skb = card->tx_buf_list[i];
 				mwifiex_unmap_pci_memory(adapter, skb,
-							 PCI_DMA_TODEVICE);
+							 DMA_TO_DEVICE);
 				dev_kfree_skb_any(skb);
 			}
 			memset(desc, 0, sizeof(*desc));
@@ -766,7 +783,7 @@
 			if (card->rx_buf_list[i]) {
 				skb = card->rx_buf_list[i];
 				mwifiex_unmap_pci_memory(adapter, skb,
-							 PCI_DMA_FROMDEVICE);
+							 DMA_FROM_DEVICE);
 				dev_kfree_skb_any(skb);
 			}
 			memset(desc2, 0, sizeof(*desc2));
@@ -775,7 +792,7 @@
 			if (card->rx_buf_list[i]) {
 				skb = card->rx_buf_list[i];
 				mwifiex_unmap_pci_memory(adapter, skb,
-							 PCI_DMA_FROMDEVICE);
+							 DMA_FROM_DEVICE);
 				dev_kfree_skb_any(skb);
 			}
 			memset(desc, 0, sizeof(*desc));
@@ -801,7 +818,7 @@
 		if (card->evt_buf_list[i]) {
 			skb = card->evt_buf_list[i];
 			mwifiex_unmap_pci_memory(adapter, skb,
-						 PCI_DMA_FROMDEVICE);
+						 DMA_FROM_DEVICE);
 			dev_kfree_skb_any(skb);
 		}
 		card->evt_buf_list[i] = NULL;
@@ -842,9 +859,10 @@
 	mwifiex_dbg(adapter, INFO,
 		    "info: txbd_ring: Allocating %d bytes\n",
 		    card->txbd_ring_size);
-	card->txbd_ring_vbase = pci_alloc_consistent(card->dev,
-						     card->txbd_ring_size,
-						     &card->txbd_ring_pbase);
+	card->txbd_ring_vbase = dma_alloc_coherent(&card->dev->dev,
+						   card->txbd_ring_size,
+						   &card->txbd_ring_pbase,
+						   GFP_KERNEL);
 	if (!card->txbd_ring_vbase) {
 		mwifiex_dbg(adapter, ERROR,
 			    "allocate consistent memory (%d bytes) failed!\n",
@@ -868,9 +886,9 @@
 	mwifiex_cleanup_txq_ring(adapter);
 
 	if (card->txbd_ring_vbase)
-		pci_free_consistent(card->dev, card->txbd_ring_size,
-				    card->txbd_ring_vbase,
-				    card->txbd_ring_pbase);
+		dma_free_coherent(&card->dev->dev, card->txbd_ring_size,
+				  card->txbd_ring_vbase,
+				  card->txbd_ring_pbase);
 	card->txbd_ring_size = 0;
 	card->txbd_wrptr = 0;
 	card->txbd_rdptr = 0 | reg->tx_rollover_ind;
@@ -885,6 +903,7 @@
  */
 static int mwifiex_pcie_create_rxbd_ring(struct mwifiex_adapter *adapter)
 {
+	int ret;
 	struct pcie_service_card *card = adapter->card;
 	const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
 
@@ -906,9 +925,10 @@
 	mwifiex_dbg(adapter, INFO,
 		    "info: rxbd_ring: Allocating %d bytes\n",
 		    card->rxbd_ring_size);
-	card->rxbd_ring_vbase = pci_alloc_consistent(card->dev,
-						     card->rxbd_ring_size,
-						     &card->rxbd_ring_pbase);
+	card->rxbd_ring_vbase = dma_alloc_coherent(&card->dev->dev,
+						   card->rxbd_ring_size,
+						   &card->rxbd_ring_pbase,
+						   GFP_KERNEL);
 	if (!card->rxbd_ring_vbase) {
 		mwifiex_dbg(adapter, ERROR,
 			    "allocate consistent memory (%d bytes) failed!\n",
@@ -922,7 +942,10 @@
 		    (u32)((u64)card->rxbd_ring_pbase >> 32),
 		    card->rxbd_ring_size);
 
-	return mwifiex_init_rxq_ring(adapter);
+	ret = mwifiex_init_rxq_ring(adapter);
+	if (ret)
+		mwifiex_pcie_delete_rxbd_ring(adapter);
+	return ret;
 }
 
 /*
@@ -936,9 +959,9 @@
 	mwifiex_cleanup_rxq_ring(adapter);
 
 	if (card->rxbd_ring_vbase)
-		pci_free_consistent(card->dev, card->rxbd_ring_size,
-				    card->rxbd_ring_vbase,
-				    card->rxbd_ring_pbase);
+		dma_free_coherent(&card->dev->dev, card->rxbd_ring_size,
+				  card->rxbd_ring_vbase,
+				  card->rxbd_ring_pbase);
 	card->rxbd_ring_size = 0;
 	card->rxbd_wrptr = 0;
 	card->rxbd_rdptr = 0 | reg->rx_rollover_ind;
@@ -953,6 +976,7 @@
  */
 static int mwifiex_pcie_create_evtbd_ring(struct mwifiex_adapter *adapter)
 {
+	int ret;
 	struct pcie_service_card *card = adapter->card;
 	const struct mwifiex_pcie_card_reg *reg = card->pcie.reg;
 
@@ -970,9 +994,10 @@
 	mwifiex_dbg(adapter, INFO,
 		    "info: evtbd_ring: Allocating %d bytes\n",
 		card->evtbd_ring_size);
-	card->evtbd_ring_vbase = pci_alloc_consistent(card->dev,
-						      card->evtbd_ring_size,
-						      &card->evtbd_ring_pbase);
+	card->evtbd_ring_vbase = dma_alloc_coherent(&card->dev->dev,
+						    card->evtbd_ring_size,
+						    &card->evtbd_ring_pbase,
+						    GFP_KERNEL);
 	if (!card->evtbd_ring_vbase) {
 		mwifiex_dbg(adapter, ERROR,
 			    "allocate consistent memory (%d bytes) failed!\n",
@@ -986,7 +1011,10 @@
 		    (u32)((u64)card->evtbd_ring_pbase >> 32),
 		    card->evtbd_ring_size);
 
-	return mwifiex_pcie_init_evt_ring(adapter);
+	ret = mwifiex_pcie_init_evt_ring(adapter);
+	if (ret)
+		mwifiex_pcie_delete_evtbd_ring(adapter);
+	return ret;
 }
 
 /*
@@ -1000,9 +1028,9 @@
 	mwifiex_cleanup_evt_ring(adapter);
 
 	if (card->evtbd_ring_vbase)
-		pci_free_consistent(card->dev, card->evtbd_ring_size,
-				    card->evtbd_ring_vbase,
-				    card->evtbd_ring_pbase);
+		dma_free_coherent(&card->dev->dev, card->evtbd_ring_size,
+				  card->evtbd_ring_vbase,
+				  card->evtbd_ring_pbase);
 	card->evtbd_wrptr = 0;
 	card->evtbd_rdptr = 0 | reg->evt_rollover_ind;
 	card->evtbd_ring_size = 0;
@@ -1029,8 +1057,10 @@
 	}
 	skb_put(skb, MWIFIEX_UPLD_SIZE);
 	if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
-				   PCI_DMA_FROMDEVICE))
+				   DMA_FROM_DEVICE)) {
+		kfree_skb(skb);
 		return -1;
+	}
 
 	card->cmdrsp_buf = skb;
 
@@ -1051,14 +1081,14 @@
 
 	if (card && card->cmdrsp_buf) {
 		mwifiex_unmap_pci_memory(adapter, card->cmdrsp_buf,
-					 PCI_DMA_FROMDEVICE);
+					 DMA_FROM_DEVICE);
 		dev_kfree_skb_any(card->cmdrsp_buf);
 		card->cmdrsp_buf = NULL;
 	}
 
 	if (card && card->cmd_buf) {
 		mwifiex_unmap_pci_memory(adapter, card->cmd_buf,
-					 PCI_DMA_TODEVICE);
+					 DMA_TO_DEVICE);
 		dev_kfree_skb_any(card->cmd_buf);
 		card->cmd_buf = NULL;
 	}
@@ -1071,22 +1101,22 @@
 static int mwifiex_pcie_alloc_sleep_cookie_buf(struct mwifiex_adapter *adapter)
 {
 	struct pcie_service_card *card = adapter->card;
-	u32 tmp;
+	u32 *cookie;
 
-	card->sleep_cookie_vbase = pci_alloc_consistent(card->dev, sizeof(u32),
-						     &card->sleep_cookie_pbase);
+	card->sleep_cookie_vbase = dma_alloc_coherent(&card->dev->dev,
+						      sizeof(u32),
+						      &card->sleep_cookie_pbase,
+						      GFP_KERNEL);
 	if (!card->sleep_cookie_vbase) {
 		mwifiex_dbg(adapter, ERROR,
 			    "pci_alloc_consistent failed!\n");
 		return -ENOMEM;
 	}
+	cookie = (u32 *)card->sleep_cookie_vbase;
 	/* Init val of Sleep Cookie */
-	tmp = FW_AWAKE_COOKIE;
-	put_unaligned(tmp, card->sleep_cookie_vbase);
+	*cookie = FW_AWAKE_COOKIE;
 
-	mwifiex_dbg(adapter, INFO,
-		    "alloc_scook: sleep cookie=0x%x\n",
-		    get_unaligned(card->sleep_cookie_vbase));
+	mwifiex_dbg(adapter, INFO, "alloc_scook: sleep cookie=0x%x\n", *cookie);
 
 	return 0;
 }
@@ -1104,9 +1134,9 @@
 	card = adapter->card;
 
 	if (card && card->sleep_cookie_vbase) {
-		pci_free_consistent(card->dev, sizeof(u32),
-				    card->sleep_cookie_vbase,
-				    card->sleep_cookie_pbase);
+		dma_free_coherent(&card->dev->dev, sizeof(u32),
+				  card->sleep_cookie_vbase,
+				  card->sleep_cookie_pbase);
 		card->sleep_cookie_vbase = NULL;
 	}
 
@@ -1178,7 +1208,7 @@
 				    "SEND COMP: Detach skb %p at txbd_rdidx=%d\n",
 				    skb, wrdoneidx);
 			mwifiex_unmap_pci_memory(adapter, skb,
-						 PCI_DMA_TODEVICE);
+						 DMA_TO_DEVICE);
 
 			unmap_count++;
 
@@ -1271,7 +1301,7 @@
 		put_unaligned_le16(MWIFIEX_TYPE_DATA, payload + 2);
 
 		if (mwifiex_map_pci_memory(adapter, skb, skb->len,
-					   PCI_DMA_TODEVICE))
+					   DMA_TO_DEVICE))
 			return -1;
 
 		wrindx = (card->txbd_wrptr & reg->tx_mask) >> reg->tx_start_ptr;
@@ -1319,6 +1349,14 @@
 			ret = -1;
 			goto done_unmap;
 		}
+
+		/* The firmware (latest version 15.68.19.p21) of the 88W8897 PCIe+USB card
+		 * seems to crash randomly after setting the TX ring write pointer when
+		 * ASPM powersaving is enabled. A workaround seems to be keeping the bus
+		 * busy by reading a random register afterwards.
+		 */
+		mwifiex_read_reg(adapter, PCI_VENDOR_ID, &rx_val);
+
 		if ((mwifiex_pcie_txbd_not_full(card)) &&
 		    tx_param->next_pkt_len) {
 			/* have more packets and TxBD still can hold more */
@@ -1353,7 +1391,7 @@
 
 	return -EINPROGRESS;
 done_unmap:
-	mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
+	mwifiex_unmap_pci_memory(adapter, skb, DMA_TO_DEVICE);
 	card->tx_buf_list[wrindx] = NULL;
 	atomic_dec(&adapter->tx_hw_pending);
 	if (reg->pfu_enabled)
@@ -1407,7 +1445,7 @@
 		if (!skb_data)
 			return -ENOMEM;
 
-		mwifiex_unmap_pci_memory(adapter, skb_data, PCI_DMA_FROMDEVICE);
+		mwifiex_unmap_pci_memory(adapter, skb_data, DMA_FROM_DEVICE);
 		card->rx_buf_list[rd_index] = NULL;
 
 		/* Get data length from interface header -
@@ -1445,7 +1483,7 @@
 
 		if (mwifiex_map_pci_memory(adapter, skb_tmp,
 					   MWIFIEX_RX_DATA_BUF_SIZE,
-					   PCI_DMA_FROMDEVICE))
+					   DMA_FROM_DEVICE))
 			return -1;
 
 		buf_pa = MWIFIEX_SKB_DMA_ADDR(skb_tmp);
@@ -1522,7 +1560,7 @@
 		return -1;
 	}
 
-	if (mwifiex_map_pci_memory(adapter, skb, skb->len, PCI_DMA_TODEVICE))
+	if (mwifiex_map_pci_memory(adapter, skb, skb->len, DMA_TO_DEVICE))
 		return -1;
 
 	buf_pa = MWIFIEX_SKB_DMA_ADDR(skb);
@@ -1534,7 +1572,7 @@
 		mwifiex_dbg(adapter, ERROR,
 			    "%s: failed to write download command to boot code.\n",
 			    __func__);
-		mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
+		mwifiex_unmap_pci_memory(adapter, skb, DMA_TO_DEVICE);
 		return -1;
 	}
 
@@ -1546,7 +1584,7 @@
 		mwifiex_dbg(adapter, ERROR,
 			    "%s: failed to write download command to boot code.\n",
 			    __func__);
-		mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
+		mwifiex_unmap_pci_memory(adapter, skb, DMA_TO_DEVICE);
 		return -1;
 	}
 
@@ -1555,7 +1593,7 @@
 		mwifiex_dbg(adapter, ERROR,
 			    "%s: failed to write command len to cmd_size scratch reg\n",
 			    __func__);
-		mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
+		mwifiex_unmap_pci_memory(adapter, skb, DMA_TO_DEVICE);
 		return -1;
 	}
 
@@ -1564,7 +1602,7 @@
 			      CPU_INTR_DOOR_BELL)) {
 		mwifiex_dbg(adapter, ERROR,
 			    "%s: failed to assert door-bell intr\n", __func__);
-		mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
+		mwifiex_unmap_pci_memory(adapter, skb, DMA_TO_DEVICE);
 		return -1;
 	}
 
@@ -1623,7 +1661,7 @@
 	put_unaligned_le16((u16)skb->len, &payload[0]);
 	put_unaligned_le16(MWIFIEX_TYPE_CMD, &payload[2]);
 
-	if (mwifiex_map_pci_memory(adapter, skb, skb->len, PCI_DMA_TODEVICE))
+	if (mwifiex_map_pci_memory(adapter, skb, skb->len, DMA_TO_DEVICE))
 		return -1;
 
 	card->cmd_buf = skb;
@@ -1723,17 +1761,16 @@
 		    "info: Rx CMD Response\n");
 
 	if (adapter->curr_cmd)
-		mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_FROMDEVICE);
+		mwifiex_unmap_pci_memory(adapter, skb, DMA_FROM_DEVICE);
 	else
-		pci_dma_sync_single_for_cpu(card->dev,
-					    MWIFIEX_SKB_DMA_ADDR(skb),
-					    MWIFIEX_UPLD_SIZE,
-					    PCI_DMA_FROMDEVICE);
+		dma_sync_single_for_cpu(&card->dev->dev,
+					MWIFIEX_SKB_DMA_ADDR(skb),
+					MWIFIEX_UPLD_SIZE, DMA_FROM_DEVICE);
 
 	/* Unmap the command as a response has been received. */
 	if (card->cmd_buf) {
 		mwifiex_unmap_pci_memory(adapter, card->cmd_buf,
-					 PCI_DMA_TODEVICE);
+					 DMA_TO_DEVICE);
 		dev_kfree_skb_any(card->cmd_buf);
 		card->cmd_buf = NULL;
 	}
@@ -1744,10 +1781,10 @@
 
 	if (!adapter->curr_cmd) {
 		if (adapter->ps_state == PS_STATE_SLEEP_CFM) {
-			pci_dma_sync_single_for_device(card->dev,
-						MWIFIEX_SKB_DMA_ADDR(skb),
-						MWIFIEX_SLEEP_COOKIE_SIZE,
-						PCI_DMA_FROMDEVICE);
+			dma_sync_single_for_device(&card->dev->dev,
+						   MWIFIEX_SKB_DMA_ADDR(skb),
+						   MWIFIEX_SLEEP_COOKIE_SIZE,
+						   DMA_FROM_DEVICE);
 			if (mwifiex_write_reg(adapter,
 					      PCIE_CPU_INT_EVENT,
 					      CPU_INTR_SLEEP_CFM_DONE)) {
@@ -1758,7 +1795,7 @@
 			mwifiex_delay_for_sleep_cookie(adapter,
 						       MWIFIEX_MAX_DELAY_COUNT);
 			mwifiex_unmap_pci_memory(adapter, skb,
-						 PCI_DMA_FROMDEVICE);
+						 DMA_FROM_DEVICE);
 			skb_pull(skb, adapter->intf_hdr_len);
 			while (reg->sleep_cookie && (count++ < 10) &&
 			       mwifiex_pcie_ok_to_access_hw(adapter))
@@ -1774,7 +1811,7 @@
 		       min_t(u32, MWIFIEX_SIZE_OF_CMD_BUFFER, skb->len));
 		skb_push(skb, adapter->intf_hdr_len);
 		if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
-					   PCI_DMA_FROMDEVICE))
+					   DMA_FROM_DEVICE))
 			return -1;
 	} else if (mwifiex_pcie_ok_to_access_hw(adapter)) {
 		skb_pull(skb, adapter->intf_hdr_len);
@@ -1816,7 +1853,7 @@
 		card->cmdrsp_buf = skb;
 		skb_push(card->cmdrsp_buf, adapter->intf_hdr_len);
 		if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
-					   PCI_DMA_FROMDEVICE))
+					   DMA_FROM_DEVICE))
 			return -1;
 	}
 
@@ -1871,7 +1908,7 @@
 		mwifiex_dbg(adapter, INFO,
 			    "info: Read Index: %d\n", rdptr);
 		skb_cmd = card->evt_buf_list[rdptr];
-		mwifiex_unmap_pci_memory(adapter, skb_cmd, PCI_DMA_FROMDEVICE);
+		mwifiex_unmap_pci_memory(adapter, skb_cmd, DMA_FROM_DEVICE);
 
 		/* Take the pointer and set it to event pointer in adapter
 		   and will return back after event handling callback */
@@ -1951,7 +1988,7 @@
 		skb_put(skb, MAX_EVENT_SIZE - skb->len);
 		if (mwifiex_map_pci_memory(adapter, skb,
 					   MAX_EVENT_SIZE,
-					   PCI_DMA_FROMDEVICE))
+					   DMA_FROM_DEVICE))
 			return -1;
 		card->evt_buf_list[rdptr] = skb;
 		desc = card->evtbd_ring[rdptr];
@@ -2233,7 +2270,7 @@
 					    "interrupt status during fw dnld.\n",
 					    __func__);
 				mwifiex_unmap_pci_memory(adapter, skb,
-							 PCI_DMA_TODEVICE);
+							 DMA_TO_DEVICE);
 				ret = -1;
 				goto done;
 			}
@@ -2245,12 +2282,12 @@
 			mwifiex_dbg(adapter, ERROR, "%s: Card failed to ACK download\n",
 				    __func__);
 			mwifiex_unmap_pci_memory(adapter, skb,
-						 PCI_DMA_TODEVICE);
+						 DMA_TO_DEVICE);
 			ret = -1;
 			goto done;
 		}
 
-		mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE);
+		mwifiex_unmap_pci_memory(adapter, skb, DMA_TO_DEVICE);
 
 		offset += txlen;
 	} while (true);
@@ -2920,13 +2957,13 @@
 
 	pci_set_master(pdev);
 
-	ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+	ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
 	if (ret) {
 		pr_err("set_dma_mask(32) failed: %d\n", ret);
 		goto err_set_dma_mask;
 	}
 
-	ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+	ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
 	if (ret) {
 		pr_err("set_consistent_dma_mask(64) failed\n");
 		goto err_set_dma_mask;
@@ -2990,7 +3027,19 @@
 	int ret;
 	u32 fw_status;
 
-	cancel_work_sync(&card->work);
+	/* Perform the cancel_work_sync() only when we're not resetting
+	 * the card. It's because that function never returns if we're
+	 * in reset path. If we're here when resetting the card, it means
+	 * that we failed to reset the card (reset failure path).
+	 */
+	if (!card->pci_reset_ongoing) {
+		mwifiex_dbg(adapter, MSG, "performing cancel_work_sync()...\n");
+		cancel_work_sync(&card->work);
+		mwifiex_dbg(adapter, MSG, "cancel_work_sync() done\n");
+	} else {
+		mwifiex_dbg(adapter, MSG,
+			    "skipped cancel_work_sync() because we're in card reset failure path\n");
+	}
 
 	ret = mwifiex_read_reg(adapter, reg->fw_status, &fw_status);
 	if (fw_status == FIRMWARE_READY_PCIE) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/mwifiex/pcie.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/mwifiex/pcie.h
@@ -391,6 +391,8 @@
 	struct mwifiex_msix_context share_irq_ctx;
 	struct work_struct work;
 	unsigned long work_flags;
+
+	bool pci_reset_ongoing;
 };
 
 static inline int
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/mwifiex/scan.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/mwifiex/scan.c
@@ -1891,7 +1891,7 @@
 					    chan, CFG80211_BSS_FTYPE_UNKNOWN,
 					    bssid, timestamp,
 					    cap_info_bitmap, beacon_period,
-					    ie_buf, ie_len, rssi, GFP_KERNEL);
+					    ie_buf, ie_len, rssi, GFP_ATOMIC);
 			if (bss) {
 				bss_priv = (struct mwifiex_bss_priv *)bss->priv;
 				bss_priv->band = band;
@@ -2202,9 +2202,9 @@
 
 	if (nd_config) {
 		adapter->nd_info =
-			kzalloc(sizeof(struct cfg80211_wowlan_nd_match) +
-				sizeof(struct cfg80211_wowlan_nd_match *) *
-				scan_rsp->number_of_sets, GFP_ATOMIC);
+			kzalloc(struct_size(adapter->nd_info, matches,
+					    scan_rsp->number_of_sets),
+				GFP_ATOMIC);
 
 		if (adapter->nd_info)
 			adapter->nd_info->n_matches = scan_rsp->number_of_sets;
@@ -2563,8 +2563,7 @@
 	ext_scan_resp = &resp->params.ext_scan;
 
 	tlv = (void *)ext_scan_resp->tlv_buffer;
-	buf_left = le16_to_cpu(resp->size) - (sizeof(*ext_scan_resp) + S_DS_GEN
-					      - 1);
+	buf_left = le16_to_cpu(resp->size) - (sizeof(*ext_scan_resp) + S_DS_GEN);
 
 	while (buf_left >= sizeof(struct mwifiex_ie_types_header)) {
 		type = le16_to_cpu(tlv->type);
@@ -2886,6 +2885,13 @@
 			vs_param_set->header.len =
 				cpu_to_le16((((u16) priv->vs_ie[id].ie[1])
 				& 0x00FF) + 2);
+			if (le16_to_cpu(vs_param_set->header.len) >
+				MWIFIEX_MAX_VSIE_LEN) {
+				mwifiex_dbg(priv->adapter, ERROR,
+					    "Invalid param length!\n");
+				break;
+			}
+
 			memcpy(vs_param_set->ie, priv->vs_ie[id].ie,
 			       le16_to_cpu(vs_param_set->header.len));
 			*buffer += le16_to_cpu(vs_param_set->header.len) +
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/mwifiex/sdio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/mwifiex/sdio.c
@@ -58,6 +58,7 @@
 };
 
 static const struct of_device_id mwifiex_sdio_of_match_table[] = {
+	{ .compatible = "marvell,sd8787" },
 	{ .compatible = "marvell,sd8897" },
 	{ .compatible = "marvell,sd8997" },
 	{ }
@@ -444,6 +445,9 @@
 		return 0;
 	}
 
+	if (!adapter->is_up)
+		return -EBUSY;
+
 	mwifiex_enable_wake(adapter);
 
 	/* Enable the Host Sleep */
@@ -1993,6 +1997,8 @@
 		kfree(card->mpa_rx.buf);
 		card->mpa_tx.buf_size = 0;
 		card->mpa_rx.buf_size = 0;
+		card->mpa_tx.buf = NULL;
+		card->mpa_rx.buf = NULL;
 	}
 
 	return ret;
@@ -2220,22 +2226,30 @@
 	struct sdio_func *func = card->func;
 	int ret;
 
+	/* Prepare the adapter for the reset. */
 	mwifiex_shutdown_sw(adapter);
+	clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags);
+	clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &card->work_flags);
 
-	/* power cycle the adapter */
+	/* Run a HW reset of the SDIO interface. */
 	sdio_claim_host(func);
-	mmc_hw_reset(func->card->host);
+	ret = mmc_hw_reset(func->card->host);
 	sdio_release_host(func);
 
-	/* Previous save_adapter won't be valid after this. We will cancel
-	 * pending work requests.
-	 */
-	clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags);
-	clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &card->work_flags);
-
-	ret = mwifiex_reinit_sw(adapter);
-	if (ret)
-		dev_err(&func->dev, "reinit failed: %d\n", ret);
+	switch (ret) {
+	case 1:
+		dev_dbg(&func->dev, "SDIO HW reset asynchronous\n");
+		complete_all(adapter->fw_done);
+		break;
+	case 0:
+		ret = mwifiex_reinit_sw(adapter);
+		if (ret)
+			dev_err(&func->dev, "reinit failed: %d\n", ret);
+		break;
+	default:
+		dev_err(&func->dev, "SDIO HW reset failed: %d\n", ret);
+		break;
+	}
 }
 
 /* This function read/write firmware */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/mwifiex/sdio.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/mwifiex/sdio.h
@@ -36,9 +36,9 @@
 #define SD8897_DEFAULT_FW_NAME "mrvl/sd8897_uapsta.bin"
 #define SD8887_DEFAULT_FW_NAME "mrvl/sd8887_uapsta.bin"
 #define SD8801_DEFAULT_FW_NAME "mrvl/sd8801_uapsta.bin"
-#define SD8977_DEFAULT_FW_NAME "mrvl/sd8977_uapsta.bin"
+#define SD8977_DEFAULT_FW_NAME "mrvl/sdsd8977_combo_v2.bin"
 #define SD8987_DEFAULT_FW_NAME "mrvl/sd8987_uapsta.bin"
-#define SD8997_DEFAULT_FW_NAME "mrvl/sd8997_uapsta.bin"
+#define SD8997_DEFAULT_FW_NAME "mrvl/sdsd8997_combo_v4.bin"
 
 #define BLOCK_MODE	1
 #define BYTE_MODE	0
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
@@ -424,6 +424,31 @@
 	return 0;
 }
 
+static int mwifiex_cmd_802_11_led_cfg(struct mwifiex_private *priv,
+				      struct host_cmd_ds_command *cmd,
+				      u16 cmd_action,
+				      struct mwifiex_led_param *ledcfg_param)
+{
+	struct host_cmd_ds_802_11_led_control *led_cfg = &cmd->params.led_cfg;
+	struct mwifiex_ie_types_led_param *led_tlv;
+	u8 *pos;
+
+	cmd->command = cpu_to_le16(HostCmd_CMD_802_11_LED_CONTROL);
+	cmd->size = cpu_to_le16(S_DS_GEN);
+	le16_add_cpu(&cmd->size, sizeof(struct host_cmd_ds_802_11_led_control));
+
+	led_cfg->action = cpu_to_le16(cmd_action);
+	led_cfg->num_led = cpu_to_le16(MWIFIEX_LED_MAX);
+
+	pos = (u8 *)led_cfg + sizeof(struct host_cmd_ds_802_11_led_control);
+	led_tlv = (void *)pos;
+	led_tlv->header.type = cpu_to_le16(TLV_TYPE_LED_CONTROL);
+	led_tlv->header.len = cpu_to_le16(sizeof(struct mwifiex_led_param));
+	memcpy(&led_tlv->led_cfg, ledcfg_param, sizeof(struct mwifiex_led_param));
+	le16_add_cpu(&cmd->size, sizeof(struct mwifiex_ie_types_led_param));
+	return 0;
+}
+
 /*
  * This function prepares command to set/get MAC address.
  *
@@ -1999,6 +2024,10 @@
 		ret = mwifiex_cmd_802_11_hs_cfg(priv, cmd_ptr, cmd_action,
 				(struct mwifiex_hs_config_param *) data_buf);
 		break;
+	case HostCmd_CMD_802_11_LED_CONTROL:
+		ret = mwifiex_cmd_802_11_led_cfg(priv, cmd_ptr, cmd_action,
+						 data_buf);
+		break;
 	case HostCmd_CMD_802_11_SCAN:
 		ret = mwifiex_cmd_802_11_scan(cmd_ptr, data_buf);
 		break;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
@@ -580,6 +580,11 @@
 {
 	struct host_cmd_ds_802_11_key_material *key =
 						&resp->params.key_material;
+	int len;
+
+	len = le16_to_cpu(key->key_param_set.key_len);
+	if (len > sizeof(key->key_param_set.key))
+		return -EINVAL;
 
 	if (le16_to_cpu(key->action) == HostCmd_ACT_GEN_SET) {
 		if ((le16_to_cpu(key->key_param_set.key_info) & KEY_MCAST)) {
@@ -593,9 +598,8 @@
 
 	memset(priv->aes_key.key_param_set.key, 0,
 	       sizeof(key->key_param_set.key));
-	priv->aes_key.key_param_set.key_len = key->key_param_set.key_len;
-	memcpy(priv->aes_key.key_param_set.key, key->key_param_set.key,
-	       le16_to_cpu(priv->aes_key.key_param_set.key_len));
+	priv->aes_key.key_param_set.key_len = cpu_to_le16(len);
+	memcpy(priv->aes_key.key_param_set.key, key->key_param_set.key, len);
 
 	return 0;
 }
@@ -610,9 +614,14 @@
 					      struct host_cmd_ds_command *resp)
 {
 	struct host_cmd_ds_802_11_key_material_v2 *key_v2;
-	__le16 len;
+	int len;
 
 	key_v2 = &resp->params.key_material_v2;
+
+	len = le16_to_cpu(key_v2->key_param_set.key_params.aes.key_len);
+	if (len > sizeof(key_v2->key_param_set.key_params.aes.key))
+		return -EINVAL;
+
 	if (le16_to_cpu(key_v2->action) == HostCmd_ACT_GEN_SET) {
 		if ((le16_to_cpu(key_v2->key_param_set.key_info) & KEY_MCAST)) {
 			mwifiex_dbg(priv->adapter, INFO, "info: key: GTK is set\n");
@@ -626,12 +635,11 @@
 		return 0;
 
 	memset(priv->aes_key_v2.key_param_set.key_params.aes.key, 0,
-	       WLAN_KEY_LEN_CCMP);
+	       sizeof(key_v2->key_param_set.key_params.aes.key));
 	priv->aes_key_v2.key_param_set.key_params.aes.key_len =
-				key_v2->key_param_set.key_params.aes.key_len;
-	len = priv->aes_key_v2.key_param_set.key_params.aes.key_len;
+				cpu_to_le16(len);
 	memcpy(priv->aes_key_v2.key_param_set.key_params.aes.key,
-	       key_v2->key_param_set.key_params.aes.key, le16_to_cpu(len));
+	       key_v2->key_param_set.key_params.aes.key, len);
 
 	return 0;
 }
@@ -1400,6 +1408,8 @@
 	case HostCmd_CMD_ROBUST_COEX:
 		ret = mwifiex_ret_robust_coex(priv, resp, data_buf);
 		break;
+	case HostCmd_CMD_802_11_LED_CONTROL:
+		break;
 	case HostCmd_CMD_GTK_REKEY_OFFLOAD_CFG:
 		break;
 	case HostCmd_CMD_CHAN_REGION_CFG:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/mwifiex/sta_event.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/mwifiex/sta_event.c
@@ -364,10 +364,12 @@
 		sta_ptr = mwifiex_get_sta_entry(priv, tp->peermac);
 		if (sta_ptr && sta_ptr->tx_pause != tp->tx_pause) {
 			sta_ptr->tx_pause = tp->tx_pause;
+			spin_unlock_bh(&priv->sta_list_spinlock);
 			mwifiex_update_ralist_tx_pause(priv, tp->peermac,
 						       tp->tx_pause);
+		} else {
+			spin_unlock_bh(&priv->sta_list_spinlock);
 		}
-		spin_unlock_bh(&priv->sta_list_spinlock);
 	}
 }
 
@@ -399,11 +401,13 @@
 			sta_ptr = mwifiex_get_sta_entry(priv, tp->peermac);
 			if (sta_ptr && sta_ptr->tx_pause != tp->tx_pause) {
 				sta_ptr->tx_pause = tp->tx_pause;
+				spin_unlock_bh(&priv->sta_list_spinlock);
 				mwifiex_update_ralist_tx_pause(priv,
 							       tp->peermac,
 							       tp->tx_pause);
+			} else {
+				spin_unlock_bh(&priv->sta_list_spinlock);
 			}
-			spin_unlock_bh(&priv->sta_list_spinlock);
 		}
 	}
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c
@@ -229,6 +229,14 @@
 			    "11D: skip setting domain info in FW\n");
 		return 0;
 	}
+
+	if (country_ie_len >
+	    (IEEE80211_COUNTRY_STRING_LEN + MWIFIEX_MAX_TRIPLET_802_11D)) {
+		rcu_read_unlock();
+		mwifiex_dbg(priv->adapter, ERROR,
+			    "11D: country_ie_len overflow!, deauth AP\n");
+		return -EINVAL;
+	}
 	memcpy(priv->adapter->country_code, &country_ie[2], 2);
 
 	domain_info->country_code[0] = country_ie[2];
@@ -272,8 +280,9 @@
 	priv->scan_block = false;
 
 	if (bss) {
-		if (adapter->region_code == 0x00)
-			mwifiex_process_country_ie(priv, bss);
+		if (adapter->region_code == 0x00 &&
+		    mwifiex_process_country_ie(priv, bss))
+			return -EINVAL;
 
 		/* Allocate and fill new bss descriptor */
 		bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor),
@@ -560,6 +569,24 @@
 }
 EXPORT_SYMBOL_GPL(mwifiex_enable_hs);
 
+int mwifiex_set_led(struct mwifiex_adapter *adapter, int on)
+{
+	struct mwifiex_private *priv;
+	struct mwifiex_led_param ledcfg;
+
+	priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA);
+	if (!priv->is_edge_gateway)
+		return -ENODEV;
+
+	memset(&ledcfg, 0, sizeof(struct mwifiex_led_param));
+	ledcfg.on = cpu_to_le16(on);
+
+	return mwifiex_send_cmd(priv,
+				HostCmd_CMD_802_11_LED_CONTROL,
+				HostCmd_ACT_GEN_SET, 0,
+				&ledcfg, true);
+}
+
 /*
  * IOCTL request handler to get BSS information.
  *
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/mwifiex/sta_rx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/mwifiex/sta_rx.c
@@ -98,12 +98,23 @@
 	rx_pkt_len = le16_to_cpu(local_rx_pd->rx_pkt_length);
 	rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_off;
 
-	if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header,
-		     sizeof(bridge_tunnel_header))) ||
-	    (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header,
-		     sizeof(rfc1042_header)) &&
-	     ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_AARP &&
-	     ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_IPX)) {
+	if (sizeof(rx_pkt_hdr->eth803_hdr) + sizeof(rfc1042_header) +
+	    rx_pkt_off > skb->len) {
+		mwifiex_dbg(priv->adapter, ERROR,
+			    "wrong rx packet offset: len=%d, rx_pkt_off=%d\n",
+			    skb->len, rx_pkt_off);
+		priv->stats.rx_dropped++;
+		dev_kfree_skb_any(skb);
+		return -1;
+	}
+
+	if (sizeof(*rx_pkt_hdr) + rx_pkt_off <= skb->len &&
+	    ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header,
+		      sizeof(bridge_tunnel_header))) ||
+	     (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header,
+		      sizeof(rfc1042_header)) &&
+	      ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_AARP &&
+	      ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_IPX))) {
 		/*
 		 *  Replace the 803 header and rfc1042 header (llc/snap) with an
 		 *    EthernetII header, keep the src/dst and snap_type
@@ -206,7 +217,8 @@
 
 	rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_offset;
 
-	if ((rx_pkt_offset + rx_pkt_length) > (u16) skb->len) {
+	if ((rx_pkt_offset + rx_pkt_length) > skb->len ||
+	    sizeof(rx_pkt_hdr->eth803_hdr) + rx_pkt_offset > skb->len) {
 		mwifiex_dbg(adapter, ERROR,
 			    "wrong rx packet: len=%d, rx_pkt_offset=%d, rx_pkt_length=%d\n",
 			    skb->len, rx_pkt_offset, rx_pkt_length);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/mwifiex/tdls.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/mwifiex/tdls.c
@@ -734,6 +734,7 @@
 	int ret;
 	u16 capab;
 	struct ieee80211_ht_cap *ht_cap;
+	unsigned int extra;
 	u8 radio, *pos;
 
 	capab = priv->curr_bss_params.bss_descriptor.cap_info_bitmap;
@@ -752,7 +753,10 @@
 
 	switch (action_code) {
 	case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
-		skb_put(skb, sizeof(mgmt->u.action.u.tdls_discover_resp) + 1);
+		/* See the layout of 'struct ieee80211_mgmt'. */
+		extra = sizeof(mgmt->u.action.u.tdls_discover_resp) +
+			sizeof(mgmt->u.action.category);
+		skb_put(skb, extra);
 		mgmt->u.action.category = WLAN_CATEGORY_PUBLIC;
 		mgmt->u.action.u.tdls_discover_resp.action_code =
 					      WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
@@ -761,8 +765,7 @@
 		mgmt->u.action.u.tdls_discover_resp.capability =
 							     cpu_to_le16(capab);
 		/* move back for addr4 */
-		memmove(pos + ETH_ALEN, &mgmt->u.action.category,
-			sizeof(mgmt->u.action.u.tdls_discover_resp));
+		memmove(pos + ETH_ALEN, &mgmt->u.action, extra);
 		/* init address 4 */
 		eth_broadcast_addr(pos);
 
@@ -894,7 +897,7 @@
 	u8 *peer, *pos, *end;
 	u8 i, action, basic;
 	u16 cap = 0;
-	int ie_len = 0;
+	int ies_len = 0;
 
 	if (len < (sizeof(struct ethhdr) + 3))
 		return;
@@ -916,7 +919,7 @@
 		pos = buf + sizeof(struct ethhdr) + 4;
 		/* payload 1+ category 1 + action 1 + dialog 1 */
 		cap = get_unaligned_le16(pos);
-		ie_len = len - sizeof(struct ethhdr) - TDLS_REQ_FIX_LEN;
+		ies_len = len - sizeof(struct ethhdr) - TDLS_REQ_FIX_LEN;
 		pos += 2;
 		break;
 
@@ -926,7 +929,7 @@
 		/* payload 1+ category 1 + action 1 + dialog 1 + status code 2*/
 		pos = buf + sizeof(struct ethhdr) + 6;
 		cap = get_unaligned_le16(pos);
-		ie_len = len - sizeof(struct ethhdr) - TDLS_RESP_FIX_LEN;
+		ies_len = len - sizeof(struct ethhdr) - TDLS_RESP_FIX_LEN;
 		pos += 2;
 		break;
 
@@ -934,7 +937,7 @@
 		if (len < (sizeof(struct ethhdr) + TDLS_CONFIRM_FIX_LEN))
 			return;
 		pos = buf + sizeof(struct ethhdr) + TDLS_CONFIRM_FIX_LEN;
-		ie_len = len - sizeof(struct ethhdr) - TDLS_CONFIRM_FIX_LEN;
+		ies_len = len - sizeof(struct ethhdr) - TDLS_CONFIRM_FIX_LEN;
 		break;
 	default:
 		mwifiex_dbg(priv->adapter, ERROR, "Unknown TDLS frame type.\n");
@@ -947,65 +950,104 @@
 
 	sta_ptr->tdls_cap.capab = cpu_to_le16(cap);
 
-	for (end = pos + ie_len; pos + 1 < end; pos += 2 + pos[1]) {
-		if (pos + 2 + pos[1] > end)
+	for (end = pos + ies_len; pos + 1 < end; pos += 2 + pos[1]) {
+		u8 ie_len = pos[1];
+
+		if (pos + 2 + ie_len > end)
 			break;
 
 		switch (*pos) {
 		case WLAN_EID_SUPP_RATES:
-			sta_ptr->tdls_cap.rates_len = pos[1];
-			for (i = 0; i < pos[1]; i++)
+			if (ie_len > sizeof(sta_ptr->tdls_cap.rates))
+				return;
+			sta_ptr->tdls_cap.rates_len = ie_len;
+			for (i = 0; i < ie_len; i++)
 				sta_ptr->tdls_cap.rates[i] = pos[i + 2];
 			break;
 
 		case WLAN_EID_EXT_SUPP_RATES:
+			if (ie_len > sizeof(sta_ptr->tdls_cap.rates))
+				return;
 			basic = sta_ptr->tdls_cap.rates_len;
-			for (i = 0; i < pos[1]; i++)
+			if (ie_len > sizeof(sta_ptr->tdls_cap.rates) - basic)
+				return;
+			for (i = 0; i < ie_len; i++)
 				sta_ptr->tdls_cap.rates[basic + i] = pos[i + 2];
-			sta_ptr->tdls_cap.rates_len += pos[1];
+			sta_ptr->tdls_cap.rates_len += ie_len;
 			break;
 		case WLAN_EID_HT_CAPABILITY:
-			memcpy((u8 *)&sta_ptr->tdls_cap.ht_capb, pos,
+			if (ie_len != sizeof(struct ieee80211_ht_cap))
+				return;
+			/* copy the ie's value into ht_capb*/
+			memcpy((u8 *)&sta_ptr->tdls_cap.ht_capb, pos + 2,
 			       sizeof(struct ieee80211_ht_cap));
 			sta_ptr->is_11n_enabled = 1;
 			break;
 		case WLAN_EID_HT_OPERATION:
-			memcpy(&sta_ptr->tdls_cap.ht_oper, pos,
+			if (ie_len != sizeof(struct ieee80211_ht_operation))
+				return;
+			/* copy the ie's value into ht_oper*/
+			memcpy(&sta_ptr->tdls_cap.ht_oper, pos + 2,
 			       sizeof(struct ieee80211_ht_operation));
 			break;
 		case WLAN_EID_BSS_COEX_2040:
+			if (ie_len != sizeof(pos[2]))
+				return;
 			sta_ptr->tdls_cap.coex_2040 = pos[2];
 			break;
 		case WLAN_EID_EXT_CAPABILITY:
+			if (ie_len < sizeof(struct ieee_types_header))
+				return;
+			if (ie_len > 8)
+				return;
 			memcpy((u8 *)&sta_ptr->tdls_cap.extcap, pos,
 			       sizeof(struct ieee_types_header) +
-			       min_t(u8, pos[1], 8));
+			       min_t(u8, ie_len, 8));
 			break;
 		case WLAN_EID_RSN:
+			if (ie_len < sizeof(struct ieee_types_header))
+				return;
+			if (ie_len > IEEE_MAX_IE_SIZE -
+			    sizeof(struct ieee_types_header))
+				return;
 			memcpy((u8 *)&sta_ptr->tdls_cap.rsn_ie, pos,
 			       sizeof(struct ieee_types_header) +
-			       min_t(u8, pos[1], IEEE_MAX_IE_SIZE -
+			       min_t(u8, ie_len, IEEE_MAX_IE_SIZE -
 				     sizeof(struct ieee_types_header)));
 			break;
 		case WLAN_EID_QOS_CAPA:
+			if (ie_len != sizeof(pos[2]))
+				return;
 			sta_ptr->tdls_cap.qos_info = pos[2];
 			break;
 		case WLAN_EID_VHT_OPERATION:
-			if (priv->adapter->is_hw_11ac_capable)
-				memcpy(&sta_ptr->tdls_cap.vhtoper, pos,
+			if (priv->adapter->is_hw_11ac_capable) {
+				if (ie_len !=
+				    sizeof(struct ieee80211_vht_operation))
+					return;
+				/* copy the ie's value into vhtoper*/
+				memcpy(&sta_ptr->tdls_cap.vhtoper, pos + 2,
 				       sizeof(struct ieee80211_vht_operation));
+			}
 			break;
 		case WLAN_EID_VHT_CAPABILITY:
 			if (priv->adapter->is_hw_11ac_capable) {
-				memcpy((u8 *)&sta_ptr->tdls_cap.vhtcap, pos,
+				if (ie_len != sizeof(struct ieee80211_vht_cap))
+					return;
+				/* copy the ie's value into vhtcap*/
+				memcpy((u8 *)&sta_ptr->tdls_cap.vhtcap, pos + 2,
 				       sizeof(struct ieee80211_vht_cap));
 				sta_ptr->is_11ac_enabled = 1;
 			}
 			break;
 		case WLAN_EID_AID:
-			if (priv->adapter->is_hw_11ac_capable)
+			if (priv->adapter->is_hw_11ac_capable) {
+				if (ie_len != sizeof(u16))
+					return;
 				sta_ptr->tdls_cap.aid =
 					get_unaligned_le16((pos + 2));
+			}
+			break;
 		default:
 			break;
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/mwifiex/uap_cmd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/mwifiex/uap_cmd.c
@@ -479,6 +479,7 @@
 static int
 mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size)
 {
+	struct host_cmd_tlv_mac_addr *mac_tlv;
 	struct host_cmd_tlv_dtim_period *dtim_period;
 	struct host_cmd_tlv_beacon_period *beacon_period;
 	struct host_cmd_tlv_ssid *ssid;
@@ -498,6 +499,13 @@
 	int i;
 	u16 cmd_size = *param_size;
 
+	mac_tlv = (struct host_cmd_tlv_mac_addr *)tlv;
+	mac_tlv->header.type = cpu_to_le16(TLV_TYPE_UAP_MAC_ADDRESS);
+	mac_tlv->header.len = cpu_to_le16(ETH_ALEN);
+	memcpy(mac_tlv->mac_addr, bss_cfg->mac_addr, ETH_ALEN);
+	cmd_size += sizeof(struct host_cmd_tlv_mac_addr);
+	tlv += sizeof(struct host_cmd_tlv_mac_addr);
+
 	if (bss_cfg->ssid.ssid_len) {
 		ssid = (struct host_cmd_tlv_ssid *)tlv;
 		ssid->header.type = cpu_to_le16(TLV_TYPE_UAP_SSID);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/mwifiex/uap_txrx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/mwifiex/uap_txrx.c
@@ -115,6 +115,16 @@
 		return;
 	}
 
+	if (sizeof(*rx_pkt_hdr) +
+	    le16_to_cpu(uap_rx_pd->rx_pkt_offset) > skb->len) {
+		mwifiex_dbg(adapter, ERROR,
+			    "wrong rx packet offset: len=%d,rx_pkt_offset=%d\n",
+			    skb->len, le16_to_cpu(uap_rx_pd->rx_pkt_offset));
+		priv->stats.rx_dropped++;
+		dev_kfree_skb_any(skb);
+		return;
+	}
+
 	if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header,
 		     sizeof(bridge_tunnel_header))) ||
 	    (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header,
@@ -255,7 +265,15 @@
 
 	if (is_multicast_ether_addr(ra)) {
 		skb_uap = skb_copy(skb, GFP_ATOMIC);
-		mwifiex_uap_queue_bridged_pkt(priv, skb_uap);
+		if (likely(skb_uap)) {
+			mwifiex_uap_queue_bridged_pkt(priv, skb_uap);
+		} else {
+			mwifiex_dbg(adapter, ERROR,
+				    "failed to copy skb for uAP\n");
+			priv->stats.rx_dropped++;
+			dev_kfree_skb_any(skb);
+			return -1;
+		}
 	} else {
 		if (mwifiex_get_sta_entry(priv, ra)) {
 			/* Requeue Intra-BSS packet */
@@ -383,6 +401,16 @@
 	rx_pkt_type = le16_to_cpu(uap_rx_pd->rx_pkt_type);
 	rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset);
 
+	if (le16_to_cpu(uap_rx_pd->rx_pkt_offset) +
+	    sizeof(rx_pkt_hdr->eth803_hdr) > skb->len) {
+		mwifiex_dbg(adapter, ERROR,
+			    "wrong rx packet for struct ethhdr: len=%d, offset=%d\n",
+			    skb->len, le16_to_cpu(uap_rx_pd->rx_pkt_offset));
+		priv->stats.rx_dropped++;
+		dev_kfree_skb_any(skb);
+		return 0;
+	}
+
 	ether_addr_copy(ta, rx_pkt_hdr->eth803_hdr.h_source);
 
 	if ((le16_to_cpu(uap_rx_pd->rx_pkt_offset) +
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/mwifiex/usb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/mwifiex/usb.c
@@ -130,7 +130,8 @@
 		default:
 			mwifiex_dbg(adapter, ERROR,
 				    "unknown recv_type %#x\n", recv_type);
-			return -1;
+			ret = -1;
+			goto exit_restore_skb;
 		}
 		break;
 	case MWIFIEX_USB_EP_DATA:
@@ -505,6 +506,22 @@
 		}
 	}
 
+	switch (card->usb_boot_state) {
+	case USB8XXX_FW_DNLD:
+		/* Reject broken descriptors. */
+		if (!card->rx_cmd_ep || !card->tx_cmd_ep)
+			return -ENODEV;
+		if (card->bulk_out_maxpktsize == 0)
+			return -ENODEV;
+		break;
+	case USB8XXX_FW_READY:
+		/* Assume the driver can handle missing endpoints for now. */
+		break;
+	default:
+		WARN_ON(1);
+		return -ENODEV;
+	}
+
 	usb_set_intfdata(intf, card);
 
 	ret = mwifiex_add_card(card, &card->fw_done, &usb_ops,
@@ -1353,7 +1370,8 @@
 				skb_dequeue(&port->tx_aggr.aggr_list)))
 				mwifiex_write_data_complete(adapter, skb_tmp,
 							    0, -1);
-		del_timer_sync(&port->tx_aggr.timer_cnxt.hold_timer);
+		if (port->tx_aggr.timer_cnxt.hold_timer.function)
+			del_timer_sync(&port->tx_aggr.timer_cnxt.hold_timer);
 		port->tx_aggr.timer_cnxt.is_hold_timer_set = false;
 		port->tx_aggr.timer_cnxt.hold_tmo_msecs = 0;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/mwifiex/util.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/mwifiex/util.c
@@ -405,11 +405,15 @@
 	}
 
 	rx_pd = (struct rxpd *)skb->data;
+	pkt_len = le16_to_cpu(rx_pd->rx_pkt_length);
+	if (pkt_len < sizeof(struct ieee80211_hdr) + sizeof(pkt_len)) {
+		mwifiex_dbg(priv->adapter, ERROR, "invalid rx_pkt_length");
+		return -1;
+	}
 
 	skb_pull(skb, le16_to_cpu(rx_pd->rx_pkt_offset));
 	skb_pull(skb, sizeof(pkt_len));
-
-	pkt_len = le16_to_cpu(rx_pd->rx_pkt_length);
+	pkt_len -= sizeof(pkt_len);
 
 	ieee_hdr = (void *)skb->data;
 	if (ieee80211_is_mgmt(ieee_hdr->frame_control)) {
@@ -422,7 +426,7 @@
 		skb->data + sizeof(struct ieee80211_hdr),
 		pkt_len - sizeof(struct ieee80211_hdr));
 
-	pkt_len -= ETH_ALEN + sizeof(pkt_len);
+	pkt_len -= ETH_ALEN;
 	rx_pd->rx_pkt_length = cpu_to_le16(pkt_len);
 
 	cfg80211_rx_mgmt(&priv->wdev, priv->roc_cfg.chan.center_freq,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/mwifiex/wmm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/mwifiex/wmm.c
@@ -970,6 +970,10 @@
 				    "WMM Parameter Set Count: %d\n",
 				    wmm_param_ie->qos_info_bitmap & mask);
 
+			if (wmm_param_ie->vend_hdr.len + 2 >
+				sizeof(struct ieee_types_wmm_parameter))
+				break;
+
 			memcpy((u8 *) &priv->curr_bss_params.bss_descriptor.
 			       wmm_ie, wmm_param_ie,
 			       wmm_param_ie->vend_hdr.len + 2);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/marvell/mwl8k.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/marvell/mwl8k.c
@@ -1469,6 +1469,7 @@
 	txq->skb = kcalloc(MWL8K_TX_DESCS, sizeof(*txq->skb), GFP_KERNEL);
 	if (txq->skb == NULL) {
 		pci_free_consistent(priv->pdev, size, txq->txd, txq->txd_dma);
+		txq->txd = NULL;
 		return -ENOMEM;
 	}
 
@@ -2713,7 +2714,7 @@
 		cmd->action |= cpu_to_le16(MWL8K_ENABLE_RX_MULTICAST);
 		cmd->numaddr = cpu_to_le16(mc_count);
 		netdev_hw_addr_list_for_each(ha, mc_list) {
-			memcpy(cmd->addr[i], ha->addr, ETH_ALEN);
+			memcpy(cmd->addr[i++], ha->addr, ETH_ALEN);
 		}
 	}
 
@@ -5520,7 +5521,7 @@
 			rc = -EBUSY;
 			break;
 		}
-		ieee80211_start_tx_ba_cb_irqsafe(vif, addr, tid);
+		rc = IEEE80211_AMPDU_TX_START_IMMEDIATE;
 		break;
 	case IEEE80211_AMPDU_TX_STOP_CONT:
 	case IEEE80211_AMPDU_TX_STOP_FLUSH:
@@ -5795,8 +5796,8 @@
 fail:
 	priv->fw_state = FW_STATE_ERROR;
 	complete(&priv->firmware_loading_complete);
-	device_release_driver(&priv->pdev->dev);
 	mwl8k_release_firmware(priv);
+	device_release_driver(&priv->pdev->dev);
 }
 
 #define MAX_RESTART_ATTEMPTS 1
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/mediatek/mt76/agg-rx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/mediatek/mt76/agg-rx.c
@@ -143,8 +143,8 @@
 	struct ieee80211_sta *sta;
 	struct mt76_rx_tid *tid;
 	bool sn_less;
-	u16 seqno, head, size;
-	u8 ackp, idx;
+	u16 seqno, head, size, idx;
+	u8 ackp;
 
 	__skb_queue_tail(frames, skb);
 
@@ -230,7 +230,7 @@
 }
 
 int mt76_rx_aggr_start(struct mt76_dev *dev, struct mt76_wcid *wcid, u8 tidno,
-		       u16 ssn, u8 size)
+		       u16 ssn, u16 size)
 {
 	struct mt76_rx_tid *tid;
 
@@ -254,7 +254,7 @@
 
 static void mt76_rx_aggr_shutdown(struct mt76_dev *dev, struct mt76_rx_tid *tid)
 {
-	u8 size = tid->size;
+	u16 size = tid->size;
 	int i;
 
 	cancel_delayed_work(&tid->reorder_work);
@@ -268,6 +268,7 @@
 		if (!skb)
 			continue;
 
+		tid->reorder_buf[i] = NULL;
 		tid->nframes--;
 		dev_kfree_skb(skb);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/mediatek/mt76/dma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/mediatek/mt76/dma.c
@@ -261,10 +261,13 @@
 	struct mt76_queue_buf buf;
 	dma_addr_t addr;
 
+	if (q->queued + 1 >= q->ndesc - 1)
+		goto error;
+
 	addr = dma_map_single(dev->dev, skb->data, skb->len,
 			      DMA_TO_DEVICE);
 	if (unlikely(dma_mapping_error(dev->dev, addr)))
-		return -ENOMEM;
+		goto error;
 
 	buf.addr = addr;
 	buf.len = skb->len;
@@ -275,6 +278,10 @@
 	spin_unlock_bh(&q->lock);
 
 	return 0;
+
+error:
+	dev_kfree_skb(skb);
+	return -ENOMEM;
 }
 
 static int
@@ -404,6 +411,7 @@
 	bool more;
 
 	spin_lock_bh(&q->lock);
+
 	do {
 		buf = mt76_dma_dequeue(dev, q, true, NULL, NULL, &more);
 		if (!buf)
@@ -411,6 +419,12 @@
 
 		skb_free_frag(buf);
 	} while (1);
+
+	if (q->rx_head) {
+		dev_kfree_skb(q->rx_head);
+		q->rx_head = NULL;
+	}
+
 	spin_unlock_bh(&q->lock);
 
 	if (!q->rx_page.va)
@@ -433,31 +447,33 @@
 	mt76_dma_rx_cleanup(dev, q);
 	mt76_dma_sync_idx(dev, q);
 	mt76_dma_rx_fill(dev, q);
-
-	if (!q->rx_head)
-		return;
-
-	dev_kfree_skb(q->rx_head);
-	q->rx_head = NULL;
 }
 
 static void
 mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data,
 		  int len, bool more)
 {
-	struct page *page = virt_to_head_page(data);
-	int offset = data - page_address(page);
 	struct sk_buff *skb = q->rx_head;
+	struct skb_shared_info *shinfo = skb_shinfo(skb);
+	int nr_frags = shinfo->nr_frags;
 
-	offset += q->buf_offset;
-	skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, offset, len,
-			q->buf_size);
+	if (nr_frags < ARRAY_SIZE(shinfo->frags)) {
+		struct page *page = virt_to_head_page(data);
+		int offset = data - page_address(page) + q->buf_offset;
+
+		skb_add_rx_frag(skb, nr_frags, page, offset, len, q->buf_size);
+	} else {
+		skb_free_frag(data);
+	}
 
 	if (more)
 		return;
 
 	q->rx_head = NULL;
-	dev->drv->rx_skb(dev, q - dev->q_rx, skb);
+	if (nr_frags < ARRAY_SIZE(shinfo->frags))
+		dev->drv->rx_skb(dev, q - dev->q_rx, skb);
+	else
+		dev_kfree_skb(skb);
 }
 
 static int
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/mediatek/mt76/mac80211.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/mediatek/mt76/mac80211.c
@@ -103,9 +103,18 @@
 		if (!of_property_read_u32(np, "led-sources", &led_pin))
 			dev->led_pin = led_pin;
 		dev->led_al = of_property_read_bool(np, "led-active-low");
+		of_node_put(np);
 	}
 
-	return devm_led_classdev_register(dev->dev, &dev->led_cdev);
+	return led_classdev_register(dev->dev, &dev->led_cdev);
+}
+
+static void mt76_led_cleanup(struct mt76_dev *dev)
+{
+	if (!dev->led_cdev.brightness_set && !dev->led_cdev.blink_set)
+		return;
+
+	led_classdev_unregister(&dev->led_cdev);
 }
 
 static void mt76_init_stream_cap(struct mt76_dev *dev,
@@ -360,6 +369,8 @@
 {
 	struct ieee80211_hw *hw = dev->hw;
 
+	if (IS_ENABLED(CONFIG_MT76_LEDS))
+		mt76_led_cleanup(dev);
 	mt76_tx_status_check(dev, NULL, true);
 	ieee80211_unregister_hw(hw);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/mediatek/mt76/mt76.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -240,8 +240,8 @@
 	struct delayed_work reorder_work;
 
 	u16 head;
-	u8 size;
-	u8 nframes;
+	u16 size;
+	u16 nframes;
 
 	u8 started:1, stopped:1, timer_pending:1;
 
@@ -367,8 +367,8 @@
 
 enum mt76u_out_ep {
 	MT_EP_OUT_INBAND_CMD,
-	MT_EP_OUT_AC_BK,
 	MT_EP_OUT_AC_BE,
+	MT_EP_OUT_AC_BK,
 	MT_EP_OUT_AC_VI,
 	MT_EP_OUT_AC_VO,
 	MT_EP_OUT_HCCA,
@@ -723,7 +723,7 @@
 void mt76_set_stream_caps(struct mt76_dev *dev, bool vht);
 
 int mt76_rx_aggr_start(struct mt76_dev *dev, struct mt76_wcid *wcid, u8 tid,
-		       u16 ssn, u8 size);
+		       u16 ssn, u16 size);
 void mt76_rx_aggr_stop(struct mt76_dev *dev, struct mt76_wcid *wcid, u8 tid);
 
 void mt76_wcid_key_setup(struct mt76_dev *dev, struct mt76_wcid *wcid,
@@ -799,7 +799,8 @@
 mt76u_bulk_msg(struct mt76_dev *dev, void *data, int len, int *actual_len,
 	       int timeout)
 {
-	struct usb_device *udev = to_usb_device(dev->dev);
+	struct usb_interface *uintf = to_usb_interface(dev->dev);
+	struct usb_device *udev = interface_to_usbdev(uintf);
 	struct mt76_usb *usb = &dev->usb;
 	unsigned int pipe;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/mediatek/mt76/mt7603/core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/mediatek/mt76/mt7603/core.c
@@ -39,11 +39,13 @@
 	}
 
 	if (intr & MT_INT_RX_DONE(0)) {
+		dev->rx_pse_check = 0;
 		mt7603_irq_disable(dev, MT_INT_RX_DONE(0));
 		napi_schedule(&dev->mt76.napi[0]);
 	}
 
 	if (intr & MT_INT_RX_DONE(1)) {
+		dev->rx_pse_check = 0;
 		mt7603_irq_disable(dev, MT_INT_RX_DONE(1));
 		napi_schedule(&dev->mt76.napi[1]);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
@@ -1032,8 +1032,10 @@
 		if (idx && (cur_rate->idx != info->status.rates[i].idx ||
 			    cur_rate->flags != info->status.rates[i].flags)) {
 			i++;
-			if (i == ARRAY_SIZE(info->status.rates))
+			if (i == ARRAY_SIZE(info->status.rates)) {
+				i--;
 				break;
+			}
 
 			info->status.rates[i] = *cur_rate;
 			info->status.rates[i].count = 0;
@@ -1414,20 +1416,29 @@
 {
 	u32 addr, val;
 
-	if (mt76_rr(dev, MT_MCU_DEBUG_RESET) & MT_MCU_DEBUG_RESET_QUEUES)
-		return true;
-
 	if (mt7603_rx_fifo_busy(dev))
-		return false;
+		goto out;
 
 	addr = mt7603_reg_map(dev, MT_CLIENT_BASE_PHYS_ADDR + MT_CLIENT_STATUS);
 	mt76_wr(dev, addr, 3);
 	val = mt76_rr(dev, addr) >> 16;
 
-	if (is_mt7628(dev) && (val & 0x4001) == 0x4001)
-		return true;
+	if (!(val & BIT(0)))
+		return false;
 
-	return (val & 0x8001) == 0x8001 || (val & 0xe001) == 0xe001;
+	if (is_mt7628(dev))
+		val &= 0xa000;
+	else
+		val &= 0x8000;
+	if (!val)
+		return false;
+
+out:
+	if (mt76_rr(dev, MT_INT_SOURCE_CSR) &
+	    (MT_INT_RX_DONE(0) | MT_INT_RX_DONE(1)))
+		return false;
+
+	return true;
 }
 
 static bool
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/mediatek/mt76/mt7603/main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/mediatek/mt76/mt7603/main.c
@@ -555,12 +555,14 @@
 	u16 ssn = params->ssn;
 	u8 ba_size = params->buf_size;
 	struct mt76_txq *mtxq;
+	int ret = 0;
 
 	if (!txq)
 		return -EINVAL;
 
 	mtxq = (struct mt76_txq *)txq->drv_priv;
 
+	mutex_lock(&dev->mt76.mutex);
 	switch (action) {
 	case IEEE80211_AMPDU_RX_START:
 		mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, ssn,
@@ -582,7 +584,7 @@
 		break;
 	case IEEE80211_AMPDU_TX_START:
 		mtxq->agg_ssn = IEEE80211_SN_TO_SEQ(ssn);
-		ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+		ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
 		break;
 	case IEEE80211_AMPDU_TX_STOP_CONT:
 		mtxq->aggr = false;
@@ -590,8 +592,9 @@
 		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
 		break;
 	}
+	mutex_unlock(&dev->mt76.mutex);
 
-	return 0;
+	return ret;
 }
 
 static void
@@ -603,6 +606,9 @@
 	struct ieee80211_sta_rates *sta_rates = rcu_dereference(sta->rates);
 	int i;
 
+	if (!sta_rates)
+		return;
+
 	spin_lock_bh(&dev->mt76.lock);
 	for (i = 0; i < ARRAY_SIZE(msta->rates); i++) {
 		msta->rates[i].idx = sta_rates->rate[i].idx;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
@@ -13,10 +13,7 @@
 #include "../dma.h"
 #include "mac.h"
 
-static inline s8 to_rssi(u32 field, u32 rxv)
-{
-	return (FIELD_GET(field, rxv) - 220) / 2;
-}
+#define to_rssi(field, rxv)		((FIELD_GET(field, rxv) - 220) / 2)
 
 static struct mt76_wcid *mt7615_rx_get_wcid(struct mt7615_dev *dev,
 					    u8 idx, bool unicast)
@@ -840,22 +837,20 @@
 	int first_idx = 0, last_idx;
 	int i, idx, count;
 	bool fixed_rate, ack_timeout;
-	bool probe, ampdu, cck = false;
+	bool ampdu, cck = false;
 	bool rs_idx;
 	u32 rate_set_tsf;
 	u32 final_rate, final_rate_flags, final_nss, txs;
 
-	fixed_rate = info->status.rates[0].count;
-	probe = !!(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE);
-
 	txs = le32_to_cpu(txs_data[1]);
-	ampdu = !fixed_rate && (txs & MT_TXS1_AMPDU);
+	ampdu = txs & MT_TXS1_AMPDU;
 
 	txs = le32_to_cpu(txs_data[3]);
 	count = FIELD_GET(MT_TXS3_TX_COUNT, txs);
 	last_idx = FIELD_GET(MT_TXS3_LAST_TX_RATE, txs);
 
 	txs = le32_to_cpu(txs_data[0]);
+	fixed_rate = txs & MT_TXS0_FIXED_RATE;
 	final_rate = FIELD_GET(MT_TXS0_TX_RATE, txs);
 	ack_timeout = txs & MT_TXS0_ACK_TIMEOUT;
 
@@ -877,7 +872,7 @@
 
 	first_idx = max_t(int, 0, last_idx - (count + 1) / MT7615_RATE_RETRY);
 
-	if (fixed_rate && !probe) {
+	if (fixed_rate) {
 		info->status.rates[0].count = count;
 		i = 0;
 		goto out;
@@ -914,8 +909,10 @@
 		if (idx && (cur_rate->idx != info->status.rates[i].idx ||
 			    cur_rate->flags != info->status.rates[i].flags)) {
 			i++;
-			if (i == ARRAY_SIZE(info->status.rates))
+			if (i == ARRAY_SIZE(info->status.rates)) {
+				i--;
 				break;
+			}
 
 			info->status.rates[i] = *cur_rate;
 			info->status.rates[i].count = 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/mediatek/mt76/mt7615/main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/mediatek/mt76/mt7615/main.c
@@ -385,6 +385,9 @@
 	struct ieee80211_sta_rates *sta_rates = rcu_dereference(sta->rates);
 	int i;
 
+	if (!sta_rates)
+		return;
+
 	spin_lock_bh(&dev->mt76.lock);
 	for (i = 0; i < ARRAY_SIZE(msta->rates); i++) {
 		msta->rates[i].idx = sta_rates->rate[i].idx;
@@ -449,12 +452,14 @@
 	u16 tid = params->tid;
 	u16 ssn = params->ssn;
 	struct mt76_txq *mtxq;
+	int ret = 0;
 
 	if (!txq)
 		return -EINVAL;
 
 	mtxq = (struct mt76_txq *)txq->drv_priv;
 
+	mutex_lock(&dev->mt76.mutex);
 	switch (action) {
 	case IEEE80211_AMPDU_RX_START:
 		mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, ssn,
@@ -477,7 +482,7 @@
 		break;
 	case IEEE80211_AMPDU_TX_START:
 		mtxq->agg_ssn = IEEE80211_SN_TO_SEQ(ssn);
-		ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+		ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
 		break;
 	case IEEE80211_AMPDU_TX_STOP_CONT:
 		mtxq->aggr = false;
@@ -485,8 +490,9 @@
 		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
 		break;
 	}
+	mutex_unlock(&dev->mt76.mutex);
 
-	return 0;
+	return ret;
 }
 
 const struct ieee80211_ops mt7615_ops = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
@@ -119,8 +119,10 @@
 	struct mt7615_mcu_rxd *rxd = (struct mt7615_mcu_rxd *)skb->data;
 	int ret = 0;
 
-	if (seq != rxd->seq)
-		return -EAGAIN;
+	if (seq != rxd->seq) {
+		ret = -EAGAIN;
+		goto out;
+	}
 
 	switch (cmd) {
 	case -MCU_CMD_PATCH_SEM_CONTROL:
@@ -134,6 +136,7 @@
 	default:
 		break;
 	}
+out:
 	dev_kfree_skb(skb);
 
 	return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/mediatek/mt76/mt76x0/usb.c
@@ -226,7 +226,7 @@
 	u32 mac_rev;
 	int ret;
 
-	mdev = mt76_alloc_device(&usb_dev->dev, sizeof(*dev), &mt76x0u_ops,
+	mdev = mt76_alloc_device(&usb_intf->dev, sizeof(*dev), &mt76x0u_ops,
 				 &drv_ops);
 	if (!mdev)
 		return -ENOMEM;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/mediatek/mt76/mt76x02.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/mediatek/mt76/mt76x02.h
@@ -212,6 +212,7 @@
 static inline bool is_mt76x2(struct mt76x02_dev *dev)
 {
 	return mt76_chip(&dev->mt76) == 0x7612 ||
+	       mt76_chip(&dev->mt76) == 0x7632 ||
 	       mt76_chip(&dev->mt76) == 0x7662 ||
 	       mt76_chip(&dev->mt76) == 0x7602;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/mediatek/mt76/mt76x02_beacon.c
@@ -77,10 +77,7 @@
 	for (i = 0; i < ARRAY_SIZE(dev->beacons); i++) {
 		if (vif_idx == i) {
 			force_update = !!dev->beacons[i] ^ !!skb;
-
-			if (dev->beacons[i])
-				dev_kfree_skb(dev->beacons[i]);
-
+			dev_kfree_skb(dev->beacons[i]);
 			dev->beacons[i] = skb;
 			__mt76x02_mac_set_beacon(dev, bcn_idx, skb);
 		} else if (force_update && dev->beacons[i]) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c
@@ -131,15 +131,8 @@
 			s8 *lna_2g, s8 *lna_5g,
 			struct ieee80211_channel *chan)
 {
-	u16 val;
 	u8 lna;
 
-	val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1);
-	if (val & MT_EE_NIC_CONF_1_LNA_EXT_2G)
-		*lna_2g = 0;
-	if (val & MT_EE_NIC_CONF_1_LNA_EXT_5G)
-		memset(lna_5g, 0, sizeof(s8) * 3);
-
 	if (chan->band == NL80211_BAND_2GHZ)
 		lna = *lna_2g;
 	else if (chan->hw_value <= 64)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/mediatek/mt76/mt76x02_mac.c
@@ -154,7 +154,7 @@
 		mt76_wr(dev, MT_WCID_DROP(idx), (val & ~bit) | (bit * drop));
 }
 
-static __le16
+static u16
 mt76x02_mac_tx_rate_val(struct mt76x02_dev *dev,
 			const struct ieee80211_tx_rate *rate, u8 *nss_val)
 {
@@ -200,14 +200,14 @@
 		rateval |= MT_RXWI_RATE_SGI;
 
 	*nss_val = nss;
-	return cpu_to_le16(rateval);
+	return rateval;
 }
 
 void mt76x02_mac_wcid_set_rate(struct mt76x02_dev *dev, struct mt76_wcid *wcid,
 			       const struct ieee80211_tx_rate *rate)
 {
 	s8 max_txpwr_adj = mt76x02_tx_get_max_txpwr_adj(dev, rate);
-	__le16 rateval;
+	u16 rateval;
 	u32 tx_info;
 	s8 nss;
 
@@ -320,7 +320,7 @@
 	struct ieee80211_key_conf *key = info->control.hw_key;
 	u32 wcid_tx_info;
 	u16 rate_ht_mask = FIELD_PREP(MT_RXWI_RATE_PHY, BIT(1) | BIT(2));
-	u16 txwi_flags = 0;
+	u16 txwi_flags = 0, rateval;
 	u8 nss;
 	s8 txpwr_adj, max_txpwr_adj;
 	u8 ccmp_pn[8], nstreams = dev->mt76.chainmask & 0xf;
@@ -356,14 +356,15 @@
 
 	if (wcid && (rate->idx < 0 || !rate->count)) {
 		wcid_tx_info = wcid->tx_info;
-		txwi->rate = FIELD_GET(MT_WCID_TX_INFO_RATE, wcid_tx_info);
+		rateval = FIELD_GET(MT_WCID_TX_INFO_RATE, wcid_tx_info);
 		max_txpwr_adj = FIELD_GET(MT_WCID_TX_INFO_TXPWR_ADJ,
 					  wcid_tx_info);
 		nss = FIELD_GET(MT_WCID_TX_INFO_NSS, wcid_tx_info);
 	} else {
-		txwi->rate = mt76x02_mac_tx_rate_val(dev, rate, &nss);
+		rateval = mt76x02_mac_tx_rate_val(dev, rate, &nss);
 		max_txpwr_adj = mt76x02_tx_get_max_txpwr_adj(dev, rate);
 	}
+	txwi->rate = cpu_to_le16(rateval);
 
 	txpwr_adj = mt76x02_tx_get_txpwr_adj(dev, dev->mt76.txpower_conf,
 					     max_txpwr_adj);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/mediatek/mt76/mt76x02_util.c
@@ -365,12 +365,14 @@
 	u16 tid = params->tid;
 	u16 ssn = params->ssn;
 	struct mt76_txq *mtxq;
+	int ret = 0;
 
 	if (!txq)
 		return -EINVAL;
 
 	mtxq = (struct mt76_txq *)txq->drv_priv;
 
+	mutex_lock(&dev->mt76.mutex);
 	switch (action) {
 	case IEEE80211_AMPDU_RX_START:
 		mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid,
@@ -393,15 +395,16 @@
 		break;
 	case IEEE80211_AMPDU_TX_START:
 		mtxq->agg_ssn = IEEE80211_SN_TO_SEQ(ssn);
-		ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+		ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
 		break;
 	case IEEE80211_AMPDU_TX_STOP_CONT:
 		mtxq->aggr = false;
 		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
 		break;
 	}
+	mutex_unlock(&dev->mt76.mutex);
 
-	return 0;
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mt76x02_ampdu_action);
 
@@ -448,6 +451,10 @@
 	    !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
 		return -EOPNOTSUPP;
 
+	/* MT76x0 GTK offloading does not work with more than one VIF */
+	if (is_mt76x0(dev) && !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
+		return -EOPNOTSUPP;
+
 	msta = sta ? (struct mt76x02_sta *)sta->drv_priv : NULL;
 	wcid = msta ? &msta->wcid : &mvif->group_wcid;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c
@@ -251,7 +251,8 @@
 	struct ieee80211_channel *chan = dev->mt76.chandef.chan;
 	int channel = chan->hw_value;
 	s8 lna_5g[3], lna_2g;
-	u8 lna;
+	bool use_lna;
+	u8 lna = 0;
 	u16 val;
 
 	if (chan->band == NL80211_BAND_2GHZ)
@@ -270,7 +271,15 @@
 	dev->cal.rx.mcu_gain |= (lna_5g[1] & 0xff) << 16;
 	dev->cal.rx.mcu_gain |= (lna_5g[2] & 0xff) << 24;
 
-	lna = mt76x02_get_lna_gain(dev, &lna_2g, lna_5g, chan);
+	val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1);
+	if (chan->band == NL80211_BAND_2GHZ)
+		use_lna = !(val & MT_EE_NIC_CONF_1_LNA_EXT_2G);
+	else
+		use_lna = !(val & MT_EE_NIC_CONF_1_LNA_EXT_5G);
+
+	if (use_lna)
+		lna = mt76x02_get_lna_gain(dev, &lna_2g, lna_5g, chan);
+
 	dev->cal.rx.lna_gain = mt76x02_sign_extend(lna, 8);
 }
 EXPORT_SYMBOL_GPL(mt76x2_read_rx_gain);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/mediatek/mt76/mt76x2/pci.c
@@ -76,7 +76,7 @@
 	mt76_rmw_field(dev, 0x15a10, 0x1f << 16, 0x9);
 
 	/* RG_SSUSB_G1_CDR_BIC_LTR = 0xf */
-	mt76_rmw_field(dev, 0x15a0c, 0xf << 28, 0xf);
+	mt76_rmw_field(dev, 0x15a0c, 0xfU << 28, 0xf);
 
 	/* RG_SSUSB_CDR_BR_PE1D = 0x3 */
 	mt76_rmw_field(dev, 0x15c58, 0x3 << 6, 0x3);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/mediatek/mt76/mt76x2/usb.c
@@ -18,6 +18,7 @@
 	{ USB_DEVICE(0x7392, 0xb711) },	/* Edimax EW 7722 UAC */
 	{ USB_DEVICE(0x0846, 0x9053) },	/* Netgear A6210 */
 	{ USB_DEVICE(0x045e, 0x02e6) },	/* XBox One Wireless Adapter */
+	{ USB_DEVICE(0x045e, 0x02fe) },	/* XBox One Wireless Adapter */
 	{ },
 };
 
@@ -39,7 +40,7 @@
 	struct mt76_dev *mdev;
 	int err;
 
-	mdev = mt76_alloc_device(&udev->dev, sizeof(*dev), &mt76x2u_ops,
+	mdev = mt76_alloc_device(&intf->dev, sizeof(*dev), &mt76x2u_ops,
 				 &drv_ops);
 	if (!mdev)
 		return -ENOMEM;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/mediatek/mt76/usb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/mediatek/mt76/usb.c
@@ -20,7 +20,8 @@
 				  u8 req_type, u16 val, u16 offset,
 				  void *buf, size_t len)
 {
-	struct usb_device *udev = to_usb_device(dev->dev);
+	struct usb_interface *uintf = to_usb_interface(dev->dev);
+	struct usb_device *udev = interface_to_usbdev(uintf);
 	unsigned int pipe;
 	int i, ret;
 
@@ -235,7 +236,8 @@
 
 static bool mt76u_check_sg(struct mt76_dev *dev)
 {
-	struct usb_device *udev = to_usb_device(dev->dev);
+	struct usb_interface *uintf = to_usb_interface(dev->dev);
+	struct usb_device *udev = interface_to_usbdev(uintf);
 
 	return (!disable_usb_sg && udev->bus->sg_tablesize > 0 &&
 		(udev->bus->no_sg_constraint ||
@@ -370,7 +372,8 @@
 		    struct urb *urb, usb_complete_t complete_fn,
 		    void *context)
 {
-	struct usb_device *udev = to_usb_device(dev->dev);
+	struct usb_interface *uintf = to_usb_interface(dev->dev);
+	struct usb_device *udev = interface_to_usbdev(uintf);
 	unsigned int pipe;
 
 	if (dir == USB_DIR_IN)
@@ -952,6 +955,7 @@
 		.rd_rp = mt76u_rd_rp,
 		.type = MT76_BUS_USB,
 	};
+	struct usb_device *udev = interface_to_usbdev(intf);
 	struct mt76_usb *usb = &dev->usb;
 
 	tasklet_init(&usb->rx_tasklet, mt76u_rx_tasklet, (unsigned long)dev);
@@ -965,6 +969,8 @@
 	dev->bus = &mt76u_ops;
 	dev->queue_ops = &usb_queue_ops;
 
+	dev_set_drvdata(&udev->dev, dev);
+
 	usb->sg_en = mt76u_check_sg(dev);
 
 	return mt76u_set_endpoints(intf, usb);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/mediatek/mt7601u/dma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/mediatek/mt7601u/dma.c
@@ -118,7 +118,8 @@
 	if (data_len < min_seg_len ||
 	    WARN_ON_ONCE(!dma_len) ||
 	    WARN_ON_ONCE(dma_len + MT_DMA_HDRS > data_len) ||
-	    WARN_ON_ONCE(dma_len & 0x3))
+	    WARN_ON_ONCE(dma_len & 0x3) ||
+	    WARN_ON_ONCE(dma_len < min_seg_len))
 		return 0;
 
 	return MT_DMA_HDRS + dma_len;
@@ -152,8 +153,7 @@
 
 	if (new_p) {
 		/* we have one extra ref from the allocator */
-		__free_pages(e->p, MT_RX_ORDER);
-
+		put_page(e->p);
 		e->p = new_p;
 	}
 }
@@ -310,7 +310,6 @@
 	}
 
 	e = &q->e[q->end];
-	e->skb = skb;
 	usb_fill_bulk_urb(e->urb, usb_dev, snd_pipe, skb->data, skb->len,
 			  mt7601u_complete_tx, q);
 	ret = usb_submit_urb(e->urb, GFP_ATOMIC);
@@ -328,6 +327,7 @@
 
 	q->end = (q->end + 1) % q->entries;
 	q->used++;
+	e->skb = skb;
 
 	if (q->used >= q->entries)
 		ieee80211_stop_queue(dev->hw, skb_get_queue_mapping(skb));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/mediatek/mt7601u/eeprom.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/mediatek/mt7601u/eeprom.c
@@ -99,7 +99,7 @@
 {
 	u16 nic_conf1 = get_unaligned_le16(eeprom + MT_EE_NIC_CONF_1);
 
-	return ~nic_conf1 && (nic_conf1 & MT_EE_NIC_CONF_1_TX_ALC_EN);
+	return (u16)~nic_conf1 && (nic_conf1 & MT_EE_NIC_CONF_1_TX_ALC_EN);
 }
 
 static void
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/mediatek/mt7601u/main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/mediatek/mt7601u/main.c
@@ -372,8 +372,7 @@
 		break;
 	case IEEE80211_AMPDU_TX_START:
 		msta->agg_ssn[tid] = ssn << 4;
-		ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
-		break;
+		return IEEE80211_AMPDU_TX_START_IMMEDIATE;
 	case IEEE80211_AMPDU_TX_STOP_CONT:
 		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
 		break;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/mediatek/mt7601u/phy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/mediatek/mt7601u/phy.c
@@ -213,7 +213,7 @@
 
 	do {
 		val = mt7601u_bbp_rr(dev, MT_BBP_REG_VERSION);
-		if (val && ~val)
+		if (val && val != 0xff)
 			break;
 	} while (--i);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/mediatek/mt7601u/usb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/mediatek/mt7601u/usb.c
@@ -26,6 +26,7 @@
 	{ USB_DEVICE(0x2717, 0x4106) },
 	{ USB_DEVICE(0x2955, 0x0001) },
 	{ USB_DEVICE(0x2955, 0x1001) },
+	{ USB_DEVICE(0x2955, 0x1003) },
 	{ USB_DEVICE(0x2a5f, 0x1000) },
 	{ USB_DEVICE(0x7392, 0x7710) },
 	{ 0, }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -83,6 +83,7 @@
 	struct qlink_cmd *cmd;
 	struct qlink_resp *resp = NULL;
 	struct sk_buff *resp_skb = NULL;
+	int resp_res = 0;
 	u16 cmd_id;
 	u8 mac_id;
 	u8 vif_id;
@@ -113,6 +114,7 @@
 	}
 
 	resp = (struct qlink_resp *)resp_skb->data;
+	resp_res = le16_to_cpu(resp->result);
 	ret = qtnf_cmd_check_reply_header(resp, cmd_id, mac_id, vif_id,
 					  const_resp_size);
 	if (ret)
@@ -128,8 +130,8 @@
 	else
 		consume_skb(resp_skb);
 
-	if (!ret && resp)
-		return qtnf_cmd_resp_result_decode(le16_to_cpu(resp->result));
+	if (!ret)
+		return qtnf_cmd_resp_result_decode(resp_res);
 
 	pr_warn("VIF%u.%u: cmd 0x%.4X failed: %d\n",
 		mac_id, vif_id, cmd_id, ret);
@@ -832,6 +834,7 @@
 	default:
 		pr_warn("VIF%u.%u: unsupported iftype %d\n", vif->mac->macid,
 			vif->vifid, vif->wdev.iftype);
+		dev_kfree_skb(cmd_skb);
 		ret = -EINVAL;
 		goto out;
 	}
@@ -1994,6 +1997,7 @@
 		break;
 	default:
 		pr_err("unsupported iftype %d\n", vif->wdev.iftype);
+		dev_kfree_skb(cmd_skb);
 		ret = -EINVAL;
 		goto out;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/quantenna/qtnfmac/event.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/quantenna/qtnfmac/event.c
@@ -171,8 +171,9 @@
 		return -EPROTO;
 	}
 
-	pr_debug("VIF%u.%u: BSSID:%pM status:%u\n",
-		 vif->mac->macid, vif->vifid, join_info->bssid, status);
+	pr_debug("VIF%u.%u: BSSID:%pM chan:%u status:%u\n",
+		 vif->mac->macid, vif->vifid, join_info->bssid,
+		 le16_to_cpu(join_info->chan.chan.center_freq), status);
 
 	if (status != WLAN_STATUS_SUCCESS)
 		goto done;
@@ -181,7 +182,7 @@
 	if (!cfg80211_chandef_valid(&chandef)) {
 		pr_warn("MAC%u.%u: bad channel freq=%u cf1=%u cf2=%u bw=%u\n",
 			vif->mac->macid, vif->vifid,
-			chandef.chan->center_freq,
+			chandef.chan ? chandef.chan->center_freq : 0,
 			chandef.center_freq1,
 			chandef.center_freq2,
 			chandef.width);
@@ -598,8 +599,10 @@
 		return 0;
 
 	if (ev->ssid_len) {
-		memcpy(auth.ssid.ssid, ev->ssid, ev->ssid_len);
-		auth.ssid.ssid_len = ev->ssid_len;
+		int len = clamp_val(ev->ssid_len, 0, IEEE80211_MAX_SSID_LEN);
+
+		memcpy(auth.ssid.ssid, ev->ssid, len);
+		auth.ssid.ssid_len = len;
 	}
 
 	auth.key_mgmt_suite = le32_to_cpu(ev->akm_suite);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/quantenna/qtnfmac/pcie/pcie.c
@@ -130,6 +130,8 @@
 
 int qtnf_pcie_fw_boot_done(struct qtnf_bus *bus)
 {
+	struct qtnf_pcie_bus_priv *priv = get_bus_priv(bus);
+	char card_id[64];
 	int ret;
 
 	bus->fw_state = QTNF_FW_STATE_BOOT_DONE;
@@ -137,7 +139,9 @@
 	if (ret) {
 		pr_err("failed to attach core\n");
 	} else {
-		qtnf_debugfs_init(bus, DRV_NAME);
+		snprintf(card_id, sizeof(card_id), "%s:%s",
+			 DRV_NAME, pci_name(priv->pdev));
+		qtnf_debugfs_init(bus, card_id);
 		qtnf_debugfs_add_entry(bus, "mps", qtnf_dbg_mps_show);
 		qtnf_debugfs_add_entry(bus, "msi_enabled", qtnf_dbg_msi_show);
 		qtnf_debugfs_add_entry(bus, "shm_stats", qtnf_dbg_shm_stats);
@@ -295,19 +299,19 @@
 	sysctl_bar = qtnf_map_bar(pdev, QTN_SYSCTL_BAR);
 	if (IS_ERR(sysctl_bar)) {
 		pr_err("failed to map BAR%u\n", QTN_SYSCTL_BAR);
-		return ret;
+		return PTR_ERR(sysctl_bar);
 	}
 
 	dmareg_bar = qtnf_map_bar(pdev, QTN_DMA_BAR);
 	if (IS_ERR(dmareg_bar)) {
 		pr_err("failed to map BAR%u\n", QTN_DMA_BAR);
-		return ret;
+		return PTR_ERR(dmareg_bar);
 	}
 
 	epmem_bar = qtnf_map_bar(pdev, QTN_SHMEM_BAR);
 	if (IS_ERR(epmem_bar)) {
 		pr_err("failed to map BAR%u\n", QTN_SHMEM_BAR);
-		return ret;
+		return PTR_ERR(epmem_bar);
 	}
 
 	chipid = qtnf_chip_id_get(sysctl_bar);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ralink/rt2x00/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ralink/rt2x00/Kconfig
@@ -95,20 +95,20 @@
 
 
 config RT2800PCI_RT53XX
-       bool "rt2800pci - Include support for rt53xx devices (EXPERIMENTAL)"
-       default y
-       ---help---
-	 This adds support for rt53xx wireless chipset family to the
-	 rt2800pci driver.
-	 Supported chips: RT5390
+	bool "rt2800pci - Include support for rt53xx devices (EXPERIMENTAL)"
+	default y
+	---help---
+	  This adds support for rt53xx wireless chipset family to the
+	  rt2800pci driver.
+	  Supported chips: RT5390
 
 config RT2800PCI_RT3290
-       bool "rt2800pci - Include support for rt3290 devices (EXPERIMENTAL)"
-       default y
-       ---help---
-	 This adds support for rt3290 wireless chipset family to the
-	 rt2800pci driver.
-	 Supported chips: RT3290
+	bool "rt2800pci - Include support for rt3290 devices (EXPERIMENTAL)"
+	default y
+	---help---
+	  This adds support for rt3290 wireless chipset family to the
+	  rt2800pci driver.
+	  Supported chips: RT3290
 endif
 
 config RT2500USB
@@ -174,18 +174,18 @@
 	  in the rt2800usb driver.
 
 config RT2800USB_RT53XX
-       bool "rt2800usb - Include support for rt53xx devices (EXPERIMENTAL)"
-       ---help---
-	 This adds support for rt53xx wireless chipset family to the
-	 rt2800usb driver.
-	 Supported chips: RT5370
+	bool "rt2800usb - Include support for rt53xx devices (EXPERIMENTAL)"
+	---help---
+	  This adds support for rt53xx wireless chipset family to the
+	  rt2800usb driver.
+	  Supported chips: RT5370
 
 config RT2800USB_RT55XX
-       bool "rt2800usb - Include support for rt55xx devices (EXPERIMENTAL)"
-       ---help---
-	 This adds support for rt55xx wireless chipset family to the
-	 rt2800usb driver.
-	 Supported chips: RT5572
+	bool "rt2800usb - Include support for rt55xx devices (EXPERIMENTAL)"
+	---help---
+	  This adds support for rt55xx wireless chipset family to the
+	  rt2800usb driver.
+	  Supported chips: RT5572
 
 config RT2800USB_UNKNOWN
 	bool "rt2800usb - Include support for unknown (USB) devices"
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
@@ -4154,7 +4154,10 @@
 		rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);
 		rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
 		rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain);
-		rt2800_bbp_write(rt2x00dev, 86, 0);
+		if (rt2x00_rt(rt2x00dev, RT6352))
+			rt2800_bbp_write(rt2x00dev, 86, 0x38);
+		else
+			rt2800_bbp_write(rt2x00dev, 86, 0);
 	}
 
 	if (rf->channel <= 14) {
@@ -4355,7 +4358,8 @@
 		reg = (rf->channel <= 14 ? 0x1c : 0x24) + 2*rt2x00dev->lna_gain;
 		rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg);
 
-		rt2800_iq_calibrate(rt2x00dev, rf->channel);
+		if (rt2x00_rt(rt2x00dev, RT5592))
+			rt2800_iq_calibrate(rt2x00dev, rf->channel);
 	}
 
 	bbp = rt2800_bbp_read(rt2x00dev, 4);
@@ -5628,7 +5632,8 @@
 	if (qual->vgc_level != vgc_level) {
 		if (rt2x00_rt(rt2x00dev, RT3572) ||
 		    rt2x00_rt(rt2x00dev, RT3593) ||
-		    rt2x00_rt(rt2x00dev, RT3883)) {
+		    rt2x00_rt(rt2x00dev, RT3883) ||
+		    rt2x00_rt(rt2x00dev, RT6352)) {
 			rt2800_bbp_write_with_rx_chain(rt2x00dev, 66,
 						       vgc_level);
 		} else if (rt2x00_rt(rt2x00dev, RT5592)) {
@@ -5839,8 +5844,7 @@
 		rt2800_register_write(rt2x00dev, TX_TXBF_CFG_0, 0x8000fc21);
 		rt2800_register_write(rt2x00dev, TX_TXBF_CFG_3, 0x00009c40);
 	} else if (rt2x00_rt(rt2x00dev, RT5390) ||
-		   rt2x00_rt(rt2x00dev, RT5392) ||
-		   rt2x00_rt(rt2x00dev, RT6352)) {
+		   rt2x00_rt(rt2x00dev, RT5392)) {
 		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
 		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
 		rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
@@ -5852,10 +5856,8 @@
 		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
 	} else if (rt2x00_rt(rt2x00dev, RT6352)) {
 		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000401);
-		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x000C0000);
+		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x000C0001);
 		rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
-		rt2800_register_write(rt2x00dev, MIMO_PS_CFG, 0x00000002);
-		rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0x00150F0F);
 		rt2800_register_write(rt2x00dev, TX_ALC_VGA3, 0x00000000);
 		rt2800_register_write(rt2x00dev, TX0_BB_GAIN_ATTEN, 0x0);
 		rt2800_register_write(rt2x00dev, TX1_BB_GAIN_ATTEN, 0x0);
@@ -6116,6 +6118,27 @@
 		reg = rt2800_register_read(rt2x00dev, US_CYC_CNT);
 		rt2x00_set_field32(&reg, US_CYC_CNT_CLOCK_CYCLE, 125);
 		rt2800_register_write(rt2x00dev, US_CYC_CNT, reg);
+	} else if (rt2x00_is_soc(rt2x00dev)) {
+		struct clk *clk = clk_get_sys("bus", NULL);
+		int rate;
+
+		if (IS_ERR(clk)) {
+			clk = clk_get_sys("cpu", NULL);
+
+			if (IS_ERR(clk)) {
+				rate = 125;
+			} else {
+				rate = clk_get_rate(clk) / 3000000;
+				clk_put(clk);
+			}
+		} else {
+			rate = clk_get_rate(clk) / 1000000;
+			clk_put(clk);
+		}
+
+		reg = rt2800_register_read(rt2x00dev, US_CYC_CNT);
+		rt2x00_set_field32(&reg, US_CYC_CNT_CLOCK_CYCLE, rate);
+		rt2800_register_write(rt2x00dev, US_CYC_CNT, reg);
 	}
 
 	reg = rt2800_register_read(rt2x00dev, HT_FBK_CFG0);
@@ -10476,7 +10499,7 @@
 	 * when the hw reorders frames due to aggregation.
 	 */
 	if (sta_priv->wcid > WCID_END)
-		return 1;
+		return -ENOSPC;
 
 	switch (action) {
 	case IEEE80211_AMPDU_RX_START:
@@ -10489,7 +10512,7 @@
 		 */
 		break;
 	case IEEE80211_AMPDU_TX_START:
-		ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+		ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
 		break;
 	case IEEE80211_AMPDU_TX_STOP_CONT:
 	case IEEE80211_AMPDU_TX_STOP_FLUSH:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c
@@ -101,6 +101,7 @@
 	rt2x00link_stop_tuner(rt2x00dev);
 	rt2x00queue_stop_queues(rt2x00dev);
 	rt2x00queue_flush_queues(rt2x00dev, true);
+	rt2x00queue_stop_queue(rt2x00dev->bcn);
 
 	/*
 	 * Disable radio.
@@ -1283,6 +1284,7 @@
 	rt2x00dev->intf_ap_count = 0;
 	rt2x00dev->intf_sta_count = 0;
 	rt2x00dev->intf_associated = 0;
+	rt2x00dev->intf_beaconing = 0;
 
 	/* Enable the radio */
 	retval = rt2x00lib_enable_radio(rt2x00dev);
@@ -1310,6 +1312,7 @@
 	rt2x00dev->intf_ap_count = 0;
 	rt2x00dev->intf_sta_count = 0;
 	rt2x00dev->intf_associated = 0;
+	rt2x00dev->intf_beaconing = 0;
 }
 
 static inline void rt2x00lib_set_if_combinations(struct rt2x00_dev *rt2x00dev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ralink/rt2x00/rt2x00mac.c
@@ -578,6 +578,17 @@
 	 */
 	if (changes & BSS_CHANGED_BEACON_ENABLED) {
 		mutex_lock(&intf->beacon_skb_mutex);
+
+		/*
+		 * Clear the 'enable_beacon' flag and clear beacon because
+		 * the beacon queue has been stopped after hardware reset.
+		 */
+		if (test_bit(DEVICE_STATE_RESET, &rt2x00dev->flags) &&
+		    intf->enable_beacon) {
+			intf->enable_beacon = false;
+			rt2x00queue_clear_beacon(rt2x00dev, vif);
+		}
+
 		if (!bss_conf->enable_beacon && intf->enable_beacon) {
 			rt2x00dev->intf_beaconing--;
 			intf->enable_beacon = false;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
@@ -25,6 +25,9 @@
 	if (status == -ENODEV || status == -ENOENT)
 		return true;
 
+	if (!test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags))
+		return false;
+
 	if (status == -EPROTO || status == -ETIMEDOUT)
 		rt2x00dev->num_proto_errs++;
 	else
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ray_cs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ray_cs.c
@@ -270,13 +270,14 @@
 {
 	ray_dev_t *local;
 	struct net_device *dev;
+	int ret;
 
 	dev_dbg(&p_dev->dev, "ray_attach()\n");
 
 	/* Allocate space for private device-specific data */
 	dev = alloc_etherdev(sizeof(ray_dev_t));
 	if (!dev)
-		goto fail_alloc_dev;
+		return -ENOMEM;
 
 	local = netdev_priv(dev);
 	local->finder = p_dev;
@@ -313,11 +314,16 @@
 	timer_setup(&local->timer, NULL, 0);
 
 	this_device = p_dev;
-	return ray_config(p_dev);
+	ret = ray_config(p_dev);
+	if (ret)
+		goto err_free_dev;
+
+	return 0;
 
-fail_alloc_dev:
-	return -ENOMEM;
-} /* ray_attach */
+err_free_dev:
+	free_netdev(dev);
+	return ret;
+}
 
 static void ray_detach(struct pcmcia_device *link)
 {
@@ -382,6 +388,8 @@
 		goto failed;
 	local->sram = ioremap(link->resource[2]->start,
 			resource_size(link->resource[2]));
+	if (!local->sram)
+		goto failed;
 
 /*** Set up 16k window for shared memory (receive buffer) ***************/
 	link->resource[3]->flags |=
@@ -396,6 +404,8 @@
 		goto failed;
 	local->rmem = ioremap(link->resource[3]->start,
 			resource_size(link->resource[3]));
+	if (!local->rmem)
+		goto failed;
 
 /*** Set up window for attribute memory ***********************************/
 	link->resource[4]->flags |=
@@ -410,6 +420,8 @@
 		goto failed;
 	local->amem = ioremap(link->resource[4]->start,
 			resource_size(link->resource[4]));
+	if (!local->amem)
+		goto failed;
 
 	dev_dbg(&link->dev, "ray_config sram=%p\n", local->sram);
 	dev_dbg(&link->dev, "ray_config rmem=%p\n", local->rmem);
@@ -1635,38 +1647,34 @@
 /*===========================================================================*/
 static int parse_addr(char *in_str, UCHAR *out)
 {
+	int i, k;
 	int len;
-	int i, j, k;
-	int status;
 
 	if (in_str == NULL)
 		return 0;
-	if ((len = strlen(in_str)) < 2)
+	len = strnlen(in_str, ADDRLEN * 2 + 1) - 1;
+	if (len < 1)
 		return 0;
 	memset(out, 0, ADDRLEN);
 
-	status = 1;
-	j = len - 1;
-	if (j > 12)
-		j = 12;
 	i = 5;
 
-	while (j > 0) {
-		if ((k = hex_to_bin(in_str[j--])) != -1)
+	while (len > 0) {
+		if ((k = hex_to_bin(in_str[len--])) != -1)
 			out[i] = k;
 		else
 			return 0;
 
-		if (j == 0)
+		if (len == 0)
 			break;
-		if ((k = hex_to_bin(in_str[j--])) != -1)
+		if ((k = hex_to_bin(in_str[len--])) != -1)
 			out[i] += k << 4;
 		else
 			return 0;
 		if (!i--)
 			break;
 	}
-	return status;
+	return 1;
 }
 
 /*===========================================================================*/
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c
@@ -460,8 +460,10 @@
 	struct rtl8180_priv *priv = dev->priv;
 	struct rtl8180_tx_ring *ring;
 	struct rtl8180_tx_desc *entry;
+	unsigned int prio = 0;
 	unsigned long flags;
-	unsigned int idx, prio, hw_prio;
+	unsigned int idx, hw_prio;
+
 	dma_addr_t mapping;
 	u32 tx_flags;
 	u8 rc_flags;
@@ -470,7 +472,9 @@
 	/* do arithmetic and then convert to le16 */
 	u16 frame_duration = 0;
 
-	prio = skb_get_queue_mapping(skb);
+	/* rtl8180/rtl8185 only has one useable tx queue */
+	if (dev->queues > IEEE80211_AC_BK)
+		prio = skb_get_queue_mapping(skb);
 	ring = &priv->tx_ring[prio];
 
 	mapping = pci_map_single(priv->pdev, skb->data,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.c
@@ -28,7 +28,7 @@
 	usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
 			RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
 			(unsigned long)addr, idx & 0x03,
-			&priv->io_dmabuf->bits8, sizeof(val), HZ / 2);
+			&priv->io_dmabuf->bits8, sizeof(val), 500);
 
 	val = priv->io_dmabuf->bits8;
 	mutex_unlock(&priv->io_mutex);
@@ -45,7 +45,7 @@
 	usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
 			RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
 			(unsigned long)addr, idx & 0x03,
-			&priv->io_dmabuf->bits16, sizeof(val), HZ / 2);
+			&priv->io_dmabuf->bits16, sizeof(val), 500);
 
 	val = priv->io_dmabuf->bits16;
 	mutex_unlock(&priv->io_mutex);
@@ -62,7 +62,7 @@
 	usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
 			RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
 			(unsigned long)addr, idx & 0x03,
-			&priv->io_dmabuf->bits32, sizeof(val), HZ / 2);
+			&priv->io_dmabuf->bits32, sizeof(val), 500);
 
 	val = priv->io_dmabuf->bits32;
 	mutex_unlock(&priv->io_mutex);
@@ -79,7 +79,7 @@
 	usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
 			RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
 			(unsigned long)addr, idx & 0x03,
-			&priv->io_dmabuf->bits8, sizeof(val), HZ / 2);
+			&priv->io_dmabuf->bits8, sizeof(val), 500);
 
 	mutex_unlock(&priv->io_mutex);
 }
@@ -93,7 +93,7 @@
 	usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
 			RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
 			(unsigned long)addr, idx & 0x03,
-			&priv->io_dmabuf->bits16, sizeof(val), HZ / 2);
+			&priv->io_dmabuf->bits16, sizeof(val), 500);
 
 	mutex_unlock(&priv->io_mutex);
 }
@@ -107,7 +107,7 @@
 	usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
 			RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
 			(unsigned long)addr, idx & 0x03,
-			&priv->io_dmabuf->bits32, sizeof(val), HZ / 2);
+			&priv->io_dmabuf->bits32, sizeof(val), 500);
 
 	mutex_unlock(&priv->io_mutex);
 }
@@ -183,7 +183,7 @@
 	usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
 			RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
 			addr, 0x8225, &priv->io_dmabuf->bits16, sizeof(data),
-			HZ / 2);
+			500);
 
 	mutex_unlock(&priv->io_mutex);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h
@@ -853,15 +853,10 @@
 	u8 usb_optional_function;
 	u8 res9[2];
 	u8 mac_addr[ETH_ALEN];		/* 0xd7 */
-	u8 res10[2];
-	u8 vendor_name[7];
-	u8 res11[2];
-	u8 device_name[0x0b];		/* 0xe8 */
-	u8 res12[2];
-	u8 serial[0x0b];		/* 0xf5 */
-	u8 res13[0x30];
+	u8 device_info[80];
+	u8 res11[3];
 	u8 unknown[0x0d];		/* 0x130 */
-	u8 res14[0xc3];
+	u8 res12[0xc3];
 };
 
 struct rtl8xxxu_reg8val {
@@ -1183,10 +1178,83 @@
 			u8 dummy3_0;
 		} __packed ra_report;
 	};
-};
+} __packed;
 
 struct rtl8xxxu_fileops;
 
+/*mlme related.*/
+enum wireless_mode {
+	WIRELESS_MODE_UNKNOWN = 0,
+	/* Sub-Element */
+	WIRELESS_MODE_B = BIT(0),
+	WIRELESS_MODE_G = BIT(1),
+	WIRELESS_MODE_A = BIT(2),
+	WIRELESS_MODE_N_24G = BIT(3),
+	WIRELESS_MODE_N_5G = BIT(4),
+	WIRELESS_AUTO = BIT(5),
+	WIRELESS_MODE_AC = BIT(6),
+	WIRELESS_MODE_MAX = 0x7F,
+};
+
+/* from rtlwifi/wifi.h */
+enum ratr_table_mode_new {
+	RATEID_IDX_BGN_40M_2SS = 0,
+	RATEID_IDX_BGN_40M_1SS = 1,
+	RATEID_IDX_BGN_20M_2SS_BN = 2,
+	RATEID_IDX_BGN_20M_1SS_BN = 3,
+	RATEID_IDX_GN_N2SS = 4,
+	RATEID_IDX_GN_N1SS = 5,
+	RATEID_IDX_BG = 6,
+	RATEID_IDX_G = 7,
+	RATEID_IDX_B = 8,
+	RATEID_IDX_VHT_2SS = 9,
+	RATEID_IDX_VHT_1SS = 10,
+	RATEID_IDX_MIX1 = 11,
+	RATEID_IDX_MIX2 = 12,
+	RATEID_IDX_VHT_3SS = 13,
+	RATEID_IDX_BGN_3SS = 14,
+};
+
+#define BT_INFO_8723B_1ANT_B_FTP		BIT(7)
+#define BT_INFO_8723B_1ANT_B_A2DP		BIT(6)
+#define BT_INFO_8723B_1ANT_B_HID		BIT(5)
+#define BT_INFO_8723B_1ANT_B_SCO_BUSY		BIT(4)
+#define BT_INFO_8723B_1ANT_B_ACL_BUSY		BIT(3)
+#define BT_INFO_8723B_1ANT_B_INQ_PAGE		BIT(2)
+#define BT_INFO_8723B_1ANT_B_SCO_ESCO		BIT(1)
+#define BT_INFO_8723B_1ANT_B_CONNECTION	BIT(0)
+
+enum _BT_8723B_1ANT_STATUS {
+	BT_8723B_1ANT_STATUS_NON_CONNECTED_IDLE      = 0x0,
+	BT_8723B_1ANT_STATUS_CONNECTED_IDLE          = 0x1,
+	BT_8723B_1ANT_STATUS_INQ_PAGE                = 0x2,
+	BT_8723B_1ANT_STATUS_ACL_BUSY                = 0x3,
+	BT_8723B_1ANT_STATUS_SCO_BUSY                = 0x4,
+	BT_8723B_1ANT_STATUS_ACL_SCO_BUSY            = 0x5,
+	BT_8723B_1ANT_STATUS_MAX
+};
+
+struct rtl8xxxu_btcoex {
+	u8      bt_status;
+	bool	bt_busy;
+	bool	has_sco;
+	bool	has_a2dp;
+	bool    has_hid;
+	bool    has_pan;
+	bool	hid_only;
+	bool	a2dp_only;
+	bool    c2h_bt_inquiry;
+};
+
+#define RTL8XXXU_RATR_STA_INIT 0
+#define RTL8XXXU_RATR_STA_HIGH 1
+#define RTL8XXXU_RATR_STA_MID  2
+#define RTL8XXXU_RATR_STA_LOW  3
+
+#define RTL8XXXU_NOISE_FLOOR_MIN	-100
+#define RTL8XXXU_SNR_THRESH_HIGH	50
+#define RTL8XXXU_SNR_THRESH_LOW	20
+
 struct rtl8xxxu_priv {
 	struct ieee80211_hw *hw;
 	struct usb_device *udev;
@@ -1260,6 +1328,7 @@
 	u32 rege9c;
 	u32 regeb4;
 	u32 regebc;
+	u32 regrcr;
 	int next_mbox;
 	int nr_out_eps;
 
@@ -1291,6 +1360,17 @@
 	u8 pi_enabled:1;
 	u8 no_pape:1;
 	u8 int_buf[USB_INTR_CONTENT_LENGTH];
+	u8 rssi_level;
+	/*
+	 * Only one virtual interface permitted because only STA mode
+	 * is supported and no iface_combinations are provided.
+	 */
+	struct ieee80211_vif *vif;
+	struct delayed_work ra_watchdog;
+	struct work_struct c2hcmd_work;
+	struct sk_buff_head c2hcmd_queue;
+	spinlock_t c2hcmd_lock;
+	struct rtl8xxxu_btcoex bt_coex;
 };
 
 struct rtl8xxxu_rx_urb {
@@ -1326,7 +1406,7 @@
 	void (*set_tx_power) (struct rtl8xxxu_priv *priv, int channel,
 			      bool ht40);
 	void (*update_rate_mask) (struct rtl8xxxu_priv *priv,
-				  u32 ramask, int sgi);
+				  u32 ramask, u8 rateid, int sgi);
 	void (*report_connect) (struct rtl8xxxu_priv *priv,
 				u8 macid, bool connect);
 	void (*fill_txdesc) (struct ieee80211_hw *hw, struct ieee80211_hdr *hdr,
@@ -1341,6 +1421,7 @@
 	u8 has_s0s1:1;
 	u8 has_tx_report:1;
 	u8 gen2_thermal_meter:1;
+	u8 needs_full_init:1;
 	u32 adda_1t_init;
 	u32 adda_1t_path_on;
 	u32 adda_2t_path_on_a;
@@ -1411,9 +1492,9 @@
 void rtl8xxxu_gen1_usb_quirks(struct rtl8xxxu_priv *priv);
 void rtl8xxxu_gen2_usb_quirks(struct rtl8xxxu_priv *priv);
 void rtl8xxxu_update_rate_mask(struct rtl8xxxu_priv *priv,
-			       u32 ramask, int sgi);
+			       u32 ramask, u8 rateid, int sgi);
 void rtl8xxxu_gen2_update_rate_mask(struct rtl8xxxu_priv *priv,
-				    u32 ramask, int sgi);
+				    u32 ramask, u8 rateid, int sgi);
 void rtl8xxxu_gen1_report_connect(struct rtl8xxxu_priv *priv,
 				  u8 macid, bool connect);
 void rtl8xxxu_gen2_report_connect(struct rtl8xxxu_priv *priv,
@@ -1437,6 +1518,8 @@
 			     struct rtl8xxxu_txdesc32 *tx_desc32, bool sgi,
 			     bool short_preamble, bool ampdu_enable,
 			     u32 rts_rate);
+void rtl8723bu_set_ps_tdma(struct rtl8xxxu_priv *priv,
+			   u8 arg1, u8 arg2, u8 arg3, u8 arg4, u8 arg5);
 
 extern struct rtl8xxxu_fileops rtl8192cu_fops;
 extern struct rtl8xxxu_fileops rtl8192eu_fops;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c
@@ -554,9 +554,43 @@
 	}
 }
 
+static void rtl8192eu_log_next_device_info(struct rtl8xxxu_priv *priv,
+					   char *record_name,
+					   char *device_info,
+					   unsigned int *record_offset)
+{
+	char *record = device_info + *record_offset;
+
+	/* A record is [ total length | 0x03 | value ] */
+	unsigned char l = record[0];
+
+	/*
+	 * The whole device info section seems to be 80 characters, make sure
+	 * we don't read further.
+	 */
+	if (*record_offset + l > 80) {
+		dev_warn(&priv->udev->dev,
+			 "invalid record length %d while parsing \"%s\" at offset %u.\n",
+			 l, record_name, *record_offset);
+		return;
+	}
+
+	if (l >= 2) {
+		char value[80];
+
+		memcpy(value, &record[2], l - 2);
+		value[l - 2] = '\0';
+		dev_info(&priv->udev->dev, "%s: %s\n", record_name, value);
+		*record_offset = *record_offset + l;
+	} else {
+		dev_info(&priv->udev->dev, "%s not available.\n", record_name);
+	}
+}
+
 static int rtl8192eu_parse_efuse(struct rtl8xxxu_priv *priv)
 {
 	struct rtl8192eu_efuse *efuse = &priv->efuse_wifi.efuse8192eu;
+	unsigned int record_offset;
 	int i;
 
 	if (efuse->rtl_id != cpu_to_le16(0x8129))
@@ -604,12 +638,25 @@
 	priv->has_xtalk = 1;
 	priv->xtalk = priv->efuse_wifi.efuse8192eu.xtal_k & 0x3f;
 
-	dev_info(&priv->udev->dev, "Vendor: %.7s\n", efuse->vendor_name);
-	dev_info(&priv->udev->dev, "Product: %.11s\n", efuse->device_name);
-	if (memchr_inv(efuse->serial, 0xff, 11))
-		dev_info(&priv->udev->dev, "Serial: %.11s\n", efuse->serial);
-	else
-		dev_info(&priv->udev->dev, "Serial not available.\n");
+	/*
+	 * device_info section seems to be laid out as records
+	 * [ total length | 0x03 | value ] so:
+	 * - vendor length + 2
+	 * - 0x03
+	 * - vendor string (not null terminated)
+	 * - product length + 2
+	 * - 0x03
+	 * - product string (not null terminated)
+	 * Then there is one or 2 0x00 on all the 4 devices I own or found
+	 * dumped online.
+	 * As previous version of the code handled an optional serial
+	 * string, I now assume there may be a third record if the
+	 * length is not 0.
+	 */
+	record_offset = 0;
+	rtl8192eu_log_next_device_info(priv, "Vendor", efuse->device_info, &record_offset);
+	rtl8192eu_log_next_device_info(priv, "Product", efuse->device_info, &record_offset);
+	rtl8192eu_log_next_device_info(priv, "Serial", efuse->device_info, &record_offset);
 
 	if (rtl8xxxu_debug & RTL8XXXU_DEBUG_EFUSE) {
 		unsigned char *raw = priv->efuse_wifi.raw;
@@ -1624,6 +1671,11 @@
 	val8 = rtl8xxxu_read8(priv, REG_PAD_CTRL1);
 	val8 &= ~BIT(0);
 	rtl8xxxu_write8(priv, REG_PAD_CTRL1, val8);
+
+	/*
+	 * Fix transmission failure of rtl8192e.
+	 */
+	rtl8xxxu_write8(priv, REG_TXPAUSE, 0x00);
 }
 
 struct rtl8xxxu_fileops rtl8192eu_fops = {
@@ -1650,6 +1702,7 @@
 	.rx_desc_size = sizeof(struct rtl8xxxu_rxdesc24),
 	.has_s0s1 = 0,
 	.gen2_thermal_meter = 1,
+	.needs_full_init = 1,
 	.adda_1t_init = 0x0fc01616,
 	.adda_1t_path_on = 0x0fc01616,
 	.adda_2t_path_on_a = 0x0fc01616,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c
@@ -1580,9 +1580,7 @@
 	/*
 	 * Software control, antenna at WiFi side
 	 */
-#ifdef NEED_PS_TDMA
 	rtl8723bu_set_ps_tdma(priv, 0x08, 0x00, 0x00, 0x00, 0x00);
-#endif
 
 	rtl8xxxu_write32(priv, REG_BT_COEX_TABLE1, 0x55555555);
 	rtl8xxxu_write32(priv, REG_BT_COEX_TABLE2, 0x55555555);
@@ -1670,6 +1668,7 @@
 	.has_s0s1 = 1,
 	.has_tx_report = 1,
 	.gen2_thermal_meter = 1,
+	.needs_full_init = 1,
 	.adda_1t_init = 0x01c00014,
 	.adda_1t_path_on = 0x01c00014,
 	.adda_2t_path_on_a = 0x01c00014,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
@@ -28,6 +28,7 @@
 #include <linux/wireless.h>
 #include <linux/firmware.h>
 #include <linux/moduleparam.h>
+#include <linux/bitfield.h>
 #include <net/mac80211.h>
 #include "rtl8xxxu.h"
 #include "rtl8xxxu_regs.h"
@@ -1390,13 +1391,13 @@
 	u8 cck[RTL8723A_MAX_RF_PATHS], ofdm[RTL8723A_MAX_RF_PATHS];
 	u8 ofdmbase[RTL8723A_MAX_RF_PATHS], mcsbase[RTL8723A_MAX_RF_PATHS];
 	u32 val32, ofdm_a, ofdm_b, mcs_a, mcs_b;
-	u8 val8;
+	u8 val8, base;
 	int group, i;
 
 	group = rtl8xxxu_gen1_channel_to_group(channel);
 
-	cck[0] = priv->cck_tx_power_index_A[group] - 1;
-	cck[1] = priv->cck_tx_power_index_B[group] - 1;
+	cck[0] = priv->cck_tx_power_index_A[group];
+	cck[1] = priv->cck_tx_power_index_B[group];
 
 	if (priv->hi_pa) {
 		if (cck[0] > 0x20)
@@ -1407,10 +1408,6 @@
 
 	ofdm[0] = priv->ht40_1s_tx_power_index_A[group];
 	ofdm[1] = priv->ht40_1s_tx_power_index_B[group];
-	if (ofdm[0])
-		ofdm[0] -= 1;
-	if (ofdm[1])
-		ofdm[1] -= 1;
 
 	ofdmbase[0] = ofdm[0] +	priv->ofdm_tx_power_index_diff[group].a;
 	ofdmbase[1] = ofdm[1] +	priv->ofdm_tx_power_index_diff[group].b;
@@ -1499,20 +1496,19 @@
 
 	rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS15_MCS12,
 			 mcs_a + power_base->reg_0e1c);
+	val8 = u32_get_bits(mcs_a + power_base->reg_0e1c, 0xff000000);
 	for (i = 0; i < 3; i++) {
-		if (i != 2)
-			val8 = (mcsbase[0] > 8) ? (mcsbase[0] - 8) : 0;
-		else
-			val8 = (mcsbase[0] > 6) ? (mcsbase[0] - 6) : 0;
+		base = i != 2 ? 8 : 6;
+		val8 = max_t(int, val8 - base, 0);
 		rtl8xxxu_write8(priv, REG_OFDM0_XC_TX_IQ_IMBALANCE + i, val8);
 	}
+
 	rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS15_MCS12,
 			 mcs_b + power_base->reg_0868);
+	val8 = u32_get_bits(mcs_b + power_base->reg_0868, 0xff000000);
 	for (i = 0; i < 3; i++) {
-		if (i != 2)
-			val8 = (mcsbase[1] > 8) ? (mcsbase[1] - 8) : 0;
-		else
-			val8 = (mcsbase[1] > 6) ? (mcsbase[1] - 6) : 0;
+		base = i != 2 ? 8 : 6;
+		val8 = max_t(int, val8 - base, 0);
 		rtl8xxxu_write8(priv, REG_OFDM0_XD_TX_IQ_IMBALANCE + i, val8);
 	}
 }
@@ -1608,18 +1604,18 @@
 static int rtl8xxxu_identify_chip(struct rtl8xxxu_priv *priv)
 {
 	struct device *dev = &priv->udev->dev;
-	u32 val32, bonding;
+	u32 val32, bonding, sys_cfg;
 	u16 val16;
 
-	val32 = rtl8xxxu_read32(priv, REG_SYS_CFG);
-	priv->chip_cut = (val32 & SYS_CFG_CHIP_VERSION_MASK) >>
+	sys_cfg = rtl8xxxu_read32(priv, REG_SYS_CFG);
+	priv->chip_cut = (sys_cfg & SYS_CFG_CHIP_VERSION_MASK) >>
 		SYS_CFG_CHIP_VERSION_SHIFT;
-	if (val32 & SYS_CFG_TRP_VAUX_EN) {
+	if (sys_cfg & SYS_CFG_TRP_VAUX_EN) {
 		dev_info(dev, "Unsupported test chip\n");
 		return -ENOTSUPP;
 	}
 
-	if (val32 & SYS_CFG_BT_FUNC) {
+	if (sys_cfg & SYS_CFG_BT_FUNC) {
 		if (priv->chip_cut >= 3) {
 			sprintf(priv->chip_name, "8723BU");
 			priv->rtl_chip = RTL8723B;
@@ -1641,7 +1637,7 @@
 		if (val32 & MULTI_GPS_FUNC_EN)
 			priv->has_gps = 1;
 		priv->is_multi_func = 1;
-	} else if (val32 & SYS_CFG_TYPE_ID) {
+	} else if (sys_cfg & SYS_CFG_TYPE_ID) {
 		bonding = rtl8xxxu_read32(priv, REG_HPON_FSM);
 		bonding &= HPON_FSM_BONDING_MASK;
 		if (priv->fops->tx_desc_size ==
@@ -1689,7 +1685,7 @@
 	case RTL8188E:
 	case RTL8192E:
 	case RTL8723B:
-		switch (val32 & SYS_CFG_VENDOR_EXT_MASK) {
+		switch (sys_cfg & SYS_CFG_VENDOR_EXT_MASK) {
 		case SYS_CFG_VENDOR_ID_TSMC:
 			sprintf(priv->chip_vendor, "TSMC");
 			break;
@@ -1706,7 +1702,7 @@
 		}
 		break;
 	default:
-		if (val32 & SYS_CFG_VENDOR_ID) {
+		if (sys_cfg & SYS_CFG_VENDOR_ID) {
 			sprintf(priv->chip_vendor, "UMC");
 			priv->vendor_umc = 1;
 		} else {
@@ -1875,13 +1871,6 @@
 
 		/* We have 8 bits to indicate validity */
 		map_addr = offset * 8;
-		if (map_addr >= EFUSE_MAP_LEN) {
-			dev_warn(dev, "%s: Illegal map_addr (%04x), "
-				 "efuse corrupt!\n",
-				 __func__, map_addr);
-			ret = -EINVAL;
-			goto exit;
-		}
 		for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
 			/* Check word enable condition in the section */
 			if (word_mask & BIT(i)) {
@@ -1892,6 +1881,13 @@
 			ret = rtl8xxxu_read_efuse8(priv, efuse_addr++, &val8);
 			if (ret)
 				goto exit;
+			if (map_addr >= EFUSE_MAP_LEN - 1) {
+				dev_warn(dev, "%s: Illegal map_addr (%04x), "
+					 "efuse corrupt!\n",
+					 __func__, map_addr);
+				ret = -EINVAL;
+				goto exit;
+			}
 			priv->efuse_wifi.raw[map_addr++] = val8;
 
 			ret = rtl8xxxu_read_efuse8(priv, efuse_addr++, &val8);
@@ -2926,12 +2922,12 @@
 		}
 
 		if (!(simubitmap & 0x30) && priv->tx_paths > 1) {
-			/* path B RX OK */
+			/* path B TX OK */
 			for (i = 4; i < 6; i++)
 				result[3][i] = result[c1][i];
 		}
 
-		if (!(simubitmap & 0x30) && priv->tx_paths > 1) {
+		if (!(simubitmap & 0xc0) && priv->tx_paths > 1) {
 			/* path B RX OK */
 			for (i = 6; i < 8; i++)
 				result[3][i] = result[c1][i];
@@ -3820,9 +3816,8 @@
 	rtl8xxxu_write8(priv, REG_RSV_CTRL, 0x0e);
 }
 
-#ifdef NEED_PS_TDMA
-static void rtl8723bu_set_ps_tdma(struct rtl8xxxu_priv *priv,
-				  u8 arg1, u8 arg2, u8 arg3, u8 arg4, u8 arg5)
+void rtl8723bu_set_ps_tdma(struct rtl8xxxu_priv *priv,
+			   u8 arg1, u8 arg2, u8 arg3, u8 arg4, u8 arg5)
 {
 	struct h2c_cmd h2c;
 
@@ -3835,7 +3830,6 @@
 	h2c.b_type_dma.data5 = arg5;
 	rtl8xxxu_gen2_h2c_cmd(priv, &h2c, sizeof(h2c.b_type_dma));
 }
-#endif
 
 void rtl8xxxu_gen2_disable_rf(struct rtl8xxxu_priv *priv)
 {
@@ -3902,6 +3896,9 @@
 	else
 		macpower = true;
 
+	if (fops->needs_full_init)
+		macpower = false;
+
 	ret = fops->power_on(priv);
 	if (ret < 0) {
 		dev_warn(dev, "%s: Failed power on\n", __func__);
@@ -4045,6 +4042,7 @@
 		RCR_ACCEPT_MGMT_FRAME | RCR_HTC_LOC_CTRL |
 		RCR_APPEND_PHYSTAT | RCR_APPEND_ICV | RCR_APPEND_MIC;
 	rtl8xxxu_write32(priv, REG_RCR, val32);
+	priv->regrcr = val32;
 
 	/*
 	 * Accept all multicast
@@ -4304,7 +4302,8 @@
 	rtl8xxxu_write8(priv, REG_BEACON_CTRL, val8);
 }
 
-void rtl8xxxu_update_rate_mask(struct rtl8xxxu_priv *priv, u32 ramask, int sgi)
+void rtl8xxxu_update_rate_mask(struct rtl8xxxu_priv *priv,
+			       u32 ramask, u8 rateid, int sgi)
 {
 	struct h2c_cmd h2c;
 
@@ -4324,7 +4323,7 @@
 }
 
 void rtl8xxxu_gen2_update_rate_mask(struct rtl8xxxu_priv *priv,
-				    u32 ramask, int sgi)
+				    u32 ramask, u8 rateid, int sgi)
 {
 	struct h2c_cmd h2c;
 	u8 bw = 0;
@@ -4338,7 +4337,7 @@
 	h2c.b_macid_cfg.ramask3 = (ramask >> 24) & 0xff;
 
 	h2c.ramask.arg = 0x80;
-	h2c.b_macid_cfg.data1 = 0;
+	h2c.b_macid_cfg.data1 = rateid;
 	if (sgi)
 		h2c.b_macid_cfg.data1 |= BIT(7);
 
@@ -4369,12 +4368,9 @@
 void rtl8xxxu_gen2_report_connect(struct rtl8xxxu_priv *priv,
 				  u8 macid, bool connect)
 {
-#ifdef RTL8XXXU_GEN2_REPORT_CONNECT
 	/*
-	 * Barry Day reports this causes issues with 8192eu and 8723bu
-	 * devices reconnecting. The reason for this is unclear, but
-	 * until it is better understood, leave the code in place but
-	 * disabled, so it is not lost.
+	 * The firmware turns on the rate control when it knows it's
+	 * connected to a network.
 	 */
 	struct h2c_cmd h2c;
 
@@ -4387,7 +4383,6 @@
 		h2c.media_status_rpt.parm &= ~BIT(0);
 
 	rtl8xxxu_gen2_h2c_cmd(priv, &h2c, sizeof(h2c.media_status_rpt));
-#endif
 }
 
 void rtl8xxxu_gen1_init_aggregation(struct rtl8xxxu_priv *priv)
@@ -4478,6 +4473,35 @@
 	rtl8xxxu_write8(priv, REG_INIRTS_RATE_SEL, rate_idx);
 }
 
+static u16
+rtl8xxxu_wireless_mode(struct ieee80211_hw *hw, struct ieee80211_sta *sta)
+{
+	u16 network_type = WIRELESS_MODE_UNKNOWN;
+
+	if (hw->conf.chandef.chan->band == NL80211_BAND_5GHZ) {
+		if (sta->vht_cap.vht_supported)
+			network_type = WIRELESS_MODE_AC;
+		else if (sta->ht_cap.ht_supported)
+			network_type = WIRELESS_MODE_N_5G;
+
+		network_type |= WIRELESS_MODE_A;
+	} else {
+		if (sta->vht_cap.vht_supported)
+			network_type = WIRELESS_MODE_AC;
+		else if (sta->ht_cap.ht_supported)
+			network_type = WIRELESS_MODE_N_24G;
+
+		if (sta->supp_rates[0] <= 0xf)
+			network_type |= WIRELESS_MODE_B;
+		else if (sta->supp_rates[0] & 0xf)
+			network_type |= (WIRELESS_MODE_B | WIRELESS_MODE_G);
+		else
+			network_type |= WIRELESS_MODE_G;
+	}
+
+	return network_type;
+}
+
 static void
 rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 			  struct ieee80211_bss_conf *bss_conf, u32 changed)
@@ -4520,7 +4544,10 @@
 				sgi = 1;
 			rcu_read_unlock();
 
-			priv->fops->update_rate_mask(priv, ramask, sgi);
+			priv->vif = vif;
+			priv->rssi_level = RTL8XXXU_RATR_STA_INIT;
+
+			priv->fops->update_rate_mask(priv, ramask, 0, sgi);
 
 			rtl8xxxu_write8(priv, REG_BCN_MAX_ERR, 0xff);
 
@@ -4947,6 +4974,8 @@
 	if (control && control->sta)
 		sta = control->sta;
 
+	queue = rtl8xxxu_queue_select(hw, skb);
+
 	tx_desc = skb_push(skb, tx_desc_size);
 
 	memset(tx_desc, 0, tx_desc_size);
@@ -4959,7 +4988,6 @@
 	    is_broadcast_ether_addr(ieee80211_get_DA(hdr)))
 		tx_desc->txdw0 |= TXDESC_BROADMULTICAST;
 
-	queue = rtl8xxxu_queue_select(hw, skb);
 	tx_desc->txdw1 = cpu_to_le32(queue << TXDESC_QUEUE_SHIFT);
 
 	if (tx_info->control.hw_key) {
@@ -5095,7 +5123,7 @@
 		pending = priv->rx_urb_pending_count;
 	} else {
 		skb = (struct sk_buff *)rx_urb->urb.context;
-		dev_kfree_skb(skb);
+		dev_kfree_skb_irq(skb);
 		usb_free_urb(&rx_urb->urb);
 	}
 
@@ -5148,12 +5176,259 @@
 	}
 }
 
+/*
+ * The RTL8723BU/RTL8192EU vendor driver use coexistence table type
+ * 0-7 to represent writing different combinations of register values
+ * to REG_BT_COEX_TABLEs. It's for different kinds of coexistence use
+ * cases which Realtek doesn't provide detail for these settings. Keep
+ * this aligned with vendor driver for easier maintenance.
+ */
+void rtl8723bu_set_coex_with_type(struct rtl8xxxu_priv *priv, u8 type)
+{
+	switch (type) {
+	case 0:
+		rtl8xxxu_write32(priv, REG_BT_COEX_TABLE1, 0x55555555);
+		rtl8xxxu_write32(priv, REG_BT_COEX_TABLE2, 0x55555555);
+		rtl8xxxu_write32(priv, REG_BT_COEX_TABLE3, 0x00ffffff);
+		rtl8xxxu_write8(priv, REG_BT_COEX_TABLE4, 0x03);
+		break;
+	case 1:
+	case 3:
+		rtl8xxxu_write32(priv, REG_BT_COEX_TABLE1, 0x55555555);
+		rtl8xxxu_write32(priv, REG_BT_COEX_TABLE2, 0x5a5a5a5a);
+		rtl8xxxu_write32(priv, REG_BT_COEX_TABLE3, 0x00ffffff);
+		rtl8xxxu_write8(priv, REG_BT_COEX_TABLE4, 0x03);
+		break;
+	case 2:
+		rtl8xxxu_write32(priv, REG_BT_COEX_TABLE1, 0x5a5a5a5a);
+		rtl8xxxu_write32(priv, REG_BT_COEX_TABLE2, 0x5a5a5a5a);
+		rtl8xxxu_write32(priv, REG_BT_COEX_TABLE3, 0x00ffffff);
+		rtl8xxxu_write8(priv, REG_BT_COEX_TABLE4, 0x03);
+		break;
+	case 4:
+		rtl8xxxu_write32(priv, REG_BT_COEX_TABLE1, 0x5a5a5a5a);
+		rtl8xxxu_write32(priv, REG_BT_COEX_TABLE2, 0xaaaa5a5a);
+		rtl8xxxu_write32(priv, REG_BT_COEX_TABLE3, 0x00ffffff);
+		rtl8xxxu_write8(priv, REG_BT_COEX_TABLE4, 0x03);
+		break;
+	case 5:
+		rtl8xxxu_write32(priv, REG_BT_COEX_TABLE1, 0x5a5a5a5a);
+		rtl8xxxu_write32(priv, REG_BT_COEX_TABLE2, 0xaa5a5a5a);
+		rtl8xxxu_write32(priv, REG_BT_COEX_TABLE3, 0x00ffffff);
+		rtl8xxxu_write8(priv, REG_BT_COEX_TABLE4, 0x03);
+		break;
+	case 6:
+		rtl8xxxu_write32(priv, REG_BT_COEX_TABLE1, 0x55555555);
+		rtl8xxxu_write32(priv, REG_BT_COEX_TABLE2, 0xaaaaaaaa);
+		rtl8xxxu_write32(priv, REG_BT_COEX_TABLE3, 0x00ffffff);
+		rtl8xxxu_write8(priv, REG_BT_COEX_TABLE4, 0x03);
+		break;
+	case 7:
+		rtl8xxxu_write32(priv, REG_BT_COEX_TABLE1, 0xaaaaaaaa);
+		rtl8xxxu_write32(priv, REG_BT_COEX_TABLE2, 0xaaaaaaaa);
+		rtl8xxxu_write32(priv, REG_BT_COEX_TABLE3, 0x00ffffff);
+		rtl8xxxu_write8(priv, REG_BT_COEX_TABLE4, 0x03);
+		break;
+	default:
+		break;
+	}
+}
+
+void rtl8723bu_update_bt_link_info(struct rtl8xxxu_priv *priv, u8 bt_info)
+{
+	struct rtl8xxxu_btcoex *btcoex = &priv->bt_coex;
+
+	if (bt_info & BT_INFO_8723B_1ANT_B_INQ_PAGE)
+		btcoex->c2h_bt_inquiry = true;
+	else
+		btcoex->c2h_bt_inquiry = false;
+
+	if (!(bt_info & BT_INFO_8723B_1ANT_B_CONNECTION)) {
+		btcoex->bt_status = BT_8723B_1ANT_STATUS_NON_CONNECTED_IDLE;
+		btcoex->has_sco = false;
+		btcoex->has_hid = false;
+		btcoex->has_pan = false;
+		btcoex->has_a2dp = false;
+	} else {
+		if ((bt_info & 0x1f) == BT_INFO_8723B_1ANT_B_CONNECTION)
+			btcoex->bt_status = BT_8723B_1ANT_STATUS_CONNECTED_IDLE;
+		else if ((bt_info & BT_INFO_8723B_1ANT_B_SCO_ESCO) ||
+			 (bt_info & BT_INFO_8723B_1ANT_B_SCO_BUSY))
+			btcoex->bt_status = BT_8723B_1ANT_STATUS_SCO_BUSY;
+		else if (bt_info & BT_INFO_8723B_1ANT_B_ACL_BUSY)
+			btcoex->bt_status = BT_8723B_1ANT_STATUS_ACL_BUSY;
+		else
+			btcoex->bt_status = BT_8723B_1ANT_STATUS_MAX;
+
+		if (bt_info & BT_INFO_8723B_1ANT_B_FTP)
+			btcoex->has_pan = true;
+		else
+			btcoex->has_pan = false;
+
+		if (bt_info & BT_INFO_8723B_1ANT_B_A2DP)
+			btcoex->has_a2dp = true;
+		else
+			btcoex->has_a2dp = false;
+
+		if (bt_info & BT_INFO_8723B_1ANT_B_HID)
+			btcoex->has_hid = true;
+		else
+			btcoex->has_hid = false;
+
+		if (bt_info & BT_INFO_8723B_1ANT_B_SCO_ESCO)
+			btcoex->has_sco = true;
+		else
+			btcoex->has_sco = false;
+	}
+
+	if (!btcoex->has_a2dp && !btcoex->has_sco &&
+	    !btcoex->has_pan && btcoex->has_hid)
+		btcoex->hid_only = true;
+	else
+		btcoex->hid_only = false;
+
+	if (!btcoex->has_sco && !btcoex->has_pan &&
+	    !btcoex->has_hid && btcoex->has_a2dp)
+		btcoex->has_a2dp = true;
+	else
+		btcoex->has_a2dp = false;
+
+	if (btcoex->bt_status == BT_8723B_1ANT_STATUS_SCO_BUSY ||
+	    btcoex->bt_status == BT_8723B_1ANT_STATUS_ACL_BUSY)
+		btcoex->bt_busy = true;
+	else
+		btcoex->bt_busy = false;
+}
+
+void rtl8723bu_handle_bt_inquiry(struct rtl8xxxu_priv *priv)
+{
+	struct ieee80211_vif *vif;
+	struct rtl8xxxu_btcoex *btcoex;
+	bool wifi_connected;
+
+	vif = priv->vif;
+	btcoex = &priv->bt_coex;
+	wifi_connected = (vif && vif->bss_conf.assoc);
+
+	if (!wifi_connected) {
+		rtl8723bu_set_ps_tdma(priv, 0x8, 0x0, 0x0, 0x0, 0x0);
+		rtl8723bu_set_coex_with_type(priv, 0);
+	} else if (btcoex->has_sco || btcoex->has_hid || btcoex->has_a2dp) {
+		rtl8723bu_set_ps_tdma(priv, 0x61, 0x35, 0x3, 0x11, 0x11);
+		rtl8723bu_set_coex_with_type(priv, 4);
+	} else if (btcoex->has_pan) {
+		rtl8723bu_set_ps_tdma(priv, 0x61, 0x3f, 0x3, 0x11, 0x11);
+		rtl8723bu_set_coex_with_type(priv, 4);
+	} else {
+		rtl8723bu_set_ps_tdma(priv, 0x8, 0x0, 0x0, 0x0, 0x0);
+		rtl8723bu_set_coex_with_type(priv, 7);
+	}
+}
+
+void rtl8723bu_handle_bt_info(struct rtl8xxxu_priv *priv)
+{
+	struct ieee80211_vif *vif;
+	struct rtl8xxxu_btcoex *btcoex;
+	bool wifi_connected;
+
+	vif = priv->vif;
+	btcoex = &priv->bt_coex;
+	wifi_connected = (vif && vif->bss_conf.assoc);
+
+	if (wifi_connected) {
+		u32 val32 = 0;
+		u32 high_prio_tx = 0, high_prio_rx = 0;
+
+		val32 = rtl8xxxu_read32(priv, 0x770);
+		high_prio_tx = val32 & 0x0000ffff;
+		high_prio_rx = (val32  & 0xffff0000) >> 16;
+
+		if (btcoex->bt_busy) {
+			if (btcoex->hid_only) {
+				rtl8723bu_set_ps_tdma(priv, 0x61, 0x20,
+						      0x3, 0x11, 0x11);
+				rtl8723bu_set_coex_with_type(priv, 5);
+			} else if (btcoex->a2dp_only) {
+				rtl8723bu_set_ps_tdma(priv, 0x61, 0x35,
+						      0x3, 0x11, 0x11);
+				rtl8723bu_set_coex_with_type(priv, 4);
+			} else if ((btcoex->has_a2dp && btcoex->has_pan) ||
+				   (btcoex->has_hid && btcoex->has_a2dp &&
+				    btcoex->has_pan)) {
+				rtl8723bu_set_ps_tdma(priv, 0x51, 0x21,
+						      0x3, 0x10, 0x10);
+				rtl8723bu_set_coex_with_type(priv, 4);
+			} else if (btcoex->has_hid && btcoex->has_a2dp) {
+				rtl8723bu_set_ps_tdma(priv, 0x51, 0x21,
+						      0x3, 0x10, 0x10);
+				rtl8723bu_set_coex_with_type(priv, 3);
+			} else {
+				rtl8723bu_set_ps_tdma(priv, 0x61, 0x35,
+						      0x3, 0x11, 0x11);
+				rtl8723bu_set_coex_with_type(priv, 4);
+			}
+		} else {
+			rtl8723bu_set_ps_tdma(priv, 0x8, 0x0, 0x0, 0x0, 0x0);
+			if (high_prio_tx + high_prio_rx <= 60)
+				rtl8723bu_set_coex_with_type(priv, 2);
+			else
+				rtl8723bu_set_coex_with_type(priv, 7);
+		}
+	} else {
+		rtl8723bu_set_ps_tdma(priv, 0x8, 0x0, 0x0, 0x0, 0x0);
+		rtl8723bu_set_coex_with_type(priv, 0);
+	}
+}
+
+static void rtl8xxxu_c2hcmd_callback(struct work_struct *work)
+{
+	struct rtl8xxxu_priv *priv;
+	struct rtl8723bu_c2h *c2h;
+	struct sk_buff *skb = NULL;
+	unsigned long flags;
+	u8 bt_info = 0;
+	struct rtl8xxxu_btcoex *btcoex;
+
+	priv = container_of(work, struct rtl8xxxu_priv, c2hcmd_work);
+	btcoex = &priv->bt_coex;
+
+	if (priv->rf_paths > 1)
+		goto out;
+
+	while (!skb_queue_empty(&priv->c2hcmd_queue)) {
+		spin_lock_irqsave(&priv->c2hcmd_lock, flags);
+		skb = __skb_dequeue(&priv->c2hcmd_queue);
+		spin_unlock_irqrestore(&priv->c2hcmd_lock, flags);
+
+		c2h = (struct rtl8723bu_c2h *)skb->data;
+
+		switch (c2h->id) {
+		case C2H_8723B_BT_INFO:
+			bt_info = c2h->bt_info.bt_info;
+
+			rtl8723bu_update_bt_link_info(priv, bt_info);
+			if (btcoex->c2h_bt_inquiry) {
+				rtl8723bu_handle_bt_inquiry(priv);
+				break;
+			}
+			rtl8723bu_handle_bt_info(priv);
+			break;
+		default:
+			break;
+		}
+	}
+
+out:
+	dev_kfree_skb(skb);
+}
+
 static void rtl8723bu_handle_c2h(struct rtl8xxxu_priv *priv,
 				 struct sk_buff *skb)
 {
 	struct rtl8723bu_c2h *c2h = (struct rtl8723bu_c2h *)skb->data;
 	struct device *dev = &priv->udev->dev;
 	int len;
+	unsigned long flags;
 
 	len = skb->len - 2;
 
@@ -5191,6 +5466,12 @@
 			       16, 1, c2h->raw.payload, len, false);
 		break;
 	}
+
+	spin_lock_irqsave(&priv->c2hcmd_lock, flags);
+	__skb_queue_tail(&priv->c2hcmd_queue, skb);
+	spin_unlock_irqrestore(&priv->c2hcmd_lock, flags);
+
+	schedule_work(&priv->c2hcmd_work);
 }
 
 int rtl8xxxu_parse_rxdesc16(struct rtl8xxxu_priv *priv, struct sk_buff *skb)
@@ -5315,7 +5596,6 @@
 		struct device *dev = &priv->udev->dev;
 		dev_dbg(dev, "%s: C2H packet\n", __func__);
 		rtl8723bu_handle_c2h(priv, skb);
-		dev_kfree_skb(skb);
 		return RX_TYPE_C2H;
 	}
 
@@ -5452,6 +5732,7 @@
 	rtl8xxxu_write32(priv, REG_USB_HIMR, val32);
 
 error:
+	usb_free_urb(urb);
 	return ret;
 }
 
@@ -5464,6 +5745,10 @@
 
 	switch (vif->type) {
 	case NL80211_IFTYPE_STATION:
+		if (!priv->vif)
+			priv->vif = vif;
+		else
+			return -EOPNOTSUPP;
 		rtl8xxxu_stop_tx_beacon(priv);
 
 		val8 = rtl8xxxu_read8(priv, REG_BEACON_CTRL);
@@ -5487,13 +5772,15 @@
 	struct rtl8xxxu_priv *priv = hw->priv;
 
 	dev_dbg(&priv->udev->dev, "%s\n", __func__);
+
+	if (priv->vif)
+		priv->vif = NULL;
 }
 
 static int rtl8xxxu_config(struct ieee80211_hw *hw, u32 changed)
 {
 	struct rtl8xxxu_priv *priv = hw->priv;
 	struct device *dev = &priv->udev->dev;
-	u16 val16;
 	int ret = 0, channel;
 	bool ht40;
 
@@ -5503,14 +5790,6 @@
 			 __func__, hw->conf.chandef.chan->hw_value,
 			 changed, hw->conf.chandef.width);
 
-	if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) {
-		val16 = ((hw->conf.long_frame_max_tx_count <<
-			  RETRY_LIMIT_LONG_SHIFT) & RETRY_LIMIT_LONG_MASK) |
-			((hw->conf.short_frame_max_tx_count <<
-			  RETRY_LIMIT_SHORT_SHIFT) & RETRY_LIMIT_SHORT_MASK);
-		rtl8xxxu_write16(priv, REG_RETRY_LIMIT, val16);
-	}
-
 	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
 		switch (hw->conf.chandef.width) {
 		case NL80211_CHAN_WIDTH_20_NOHT:
@@ -5593,7 +5872,7 @@
 				      unsigned int *total_flags, u64 multicast)
 {
 	struct rtl8xxxu_priv *priv = hw->priv;
-	u32 rcr = rtl8xxxu_read32(priv, REG_RCR);
+	u32 rcr = priv->regrcr;
 
 	dev_dbg(&priv->udev->dev, "%s: changed_flags %08x, total_flags %08x\n",
 		__func__, changed_flags, *total_flags);
@@ -5639,6 +5918,7 @@
 	 */
 
 	rtl8xxxu_write32(priv, REG_RCR, rcr);
+	priv->regrcr = rcr;
 
 	*total_flags &= (FIF_ALLMULTI | FIF_FCSFAIL | FIF_BCN_PRBRESP_PROMISC |
 			 FIF_CONTROL | FIF_OTHER_BSS | FIF_PSPOLL |
@@ -5772,11 +6052,184 @@
 	return 0;
 }
 
+static u8 rtl8xxxu_signal_to_snr(int signal)
+{
+	if (signal < RTL8XXXU_NOISE_FLOOR_MIN)
+		signal = RTL8XXXU_NOISE_FLOOR_MIN;
+	else if (signal > 0)
+		signal = 0;
+	return (u8)(signal - RTL8XXXU_NOISE_FLOOR_MIN);
+}
+
+static void rtl8xxxu_refresh_rate_mask(struct rtl8xxxu_priv *priv,
+				       int signal, struct ieee80211_sta *sta)
+{
+	struct ieee80211_hw *hw = priv->hw;
+	u16 wireless_mode;
+	u8 rssi_level, ratr_idx;
+	u8 txbw_40mhz;
+	u8 snr, snr_thresh_high, snr_thresh_low;
+	u8 go_up_gap = 5;
+
+	rssi_level = priv->rssi_level;
+	snr = rtl8xxxu_signal_to_snr(signal);
+	snr_thresh_high = RTL8XXXU_SNR_THRESH_HIGH;
+	snr_thresh_low = RTL8XXXU_SNR_THRESH_LOW;
+	txbw_40mhz = (hw->conf.chandef.width == NL80211_CHAN_WIDTH_40) ? 1 : 0;
+
+	switch (rssi_level) {
+	case RTL8XXXU_RATR_STA_MID:
+		snr_thresh_high += go_up_gap;
+		break;
+	case RTL8XXXU_RATR_STA_LOW:
+		snr_thresh_high += go_up_gap;
+		snr_thresh_low += go_up_gap;
+		break;
+	default:
+		break;
+	}
+
+	if (snr > snr_thresh_high)
+		rssi_level = RTL8XXXU_RATR_STA_HIGH;
+	else if (snr > snr_thresh_low)
+		rssi_level = RTL8XXXU_RATR_STA_MID;
+	else
+		rssi_level = RTL8XXXU_RATR_STA_LOW;
+
+	if (rssi_level != priv->rssi_level) {
+		int sgi = 0;
+		u32 rate_bitmap = 0;
+
+		rcu_read_lock();
+		rate_bitmap = (sta->supp_rates[0] & 0xfff) |
+				(sta->ht_cap.mcs.rx_mask[0] << 12) |
+				(sta->ht_cap.mcs.rx_mask[1] << 20);
+		if (sta->ht_cap.cap &
+		    (IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20))
+			sgi = 1;
+		rcu_read_unlock();
+
+		wireless_mode = rtl8xxxu_wireless_mode(hw, sta);
+		switch (wireless_mode) {
+		case WIRELESS_MODE_B:
+			ratr_idx = RATEID_IDX_B;
+			if (rate_bitmap & 0x0000000c)
+				rate_bitmap &= 0x0000000d;
+			else
+				rate_bitmap &= 0x0000000f;
+			break;
+		case WIRELESS_MODE_A:
+		case WIRELESS_MODE_G:
+			ratr_idx = RATEID_IDX_G;
+			if (rssi_level == RTL8XXXU_RATR_STA_HIGH)
+				rate_bitmap &= 0x00000f00;
+			else
+				rate_bitmap &= 0x00000ff0;
+			break;
+		case (WIRELESS_MODE_B | WIRELESS_MODE_G):
+			ratr_idx = RATEID_IDX_BG;
+			if (rssi_level == RTL8XXXU_RATR_STA_HIGH)
+				rate_bitmap &= 0x00000f00;
+			else if (rssi_level == RTL8XXXU_RATR_STA_MID)
+				rate_bitmap &= 0x00000ff0;
+			else
+				rate_bitmap &= 0x00000ff5;
+			break;
+		case WIRELESS_MODE_N_24G:
+		case WIRELESS_MODE_N_5G:
+		case (WIRELESS_MODE_G | WIRELESS_MODE_N_24G):
+		case (WIRELESS_MODE_A | WIRELESS_MODE_N_5G):
+			if (priv->tx_paths == 2 && priv->rx_paths == 2)
+				ratr_idx = RATEID_IDX_GN_N2SS;
+			else
+				ratr_idx = RATEID_IDX_GN_N1SS;
+			break;
+		case (WIRELESS_MODE_B | WIRELESS_MODE_G | WIRELESS_MODE_N_24G):
+		case (WIRELESS_MODE_B | WIRELESS_MODE_N_24G):
+			if (txbw_40mhz) {
+				if (priv->tx_paths == 2 && priv->rx_paths == 2)
+					ratr_idx = RATEID_IDX_BGN_40M_2SS;
+				else
+					ratr_idx = RATEID_IDX_BGN_40M_1SS;
+			} else {
+				if (priv->tx_paths == 2 && priv->rx_paths == 2)
+					ratr_idx = RATEID_IDX_BGN_20M_2SS_BN;
+				else
+					ratr_idx = RATEID_IDX_BGN_20M_1SS_BN;
+			}
+
+			if (priv->tx_paths == 2 && priv->rx_paths == 2) {
+				if (rssi_level == RTL8XXXU_RATR_STA_HIGH) {
+					rate_bitmap &= 0x0f8f0000;
+				} else if (rssi_level == RTL8XXXU_RATR_STA_MID) {
+					rate_bitmap &= 0x0f8ff000;
+				} else {
+					if (txbw_40mhz)
+						rate_bitmap &= 0x0f8ff015;
+					else
+						rate_bitmap &= 0x0f8ff005;
+				}
+			} else {
+				if (rssi_level == RTL8XXXU_RATR_STA_HIGH) {
+					rate_bitmap &= 0x000f0000;
+				} else if (rssi_level == RTL8XXXU_RATR_STA_MID) {
+					rate_bitmap &= 0x000ff000;
+				} else {
+					if (txbw_40mhz)
+						rate_bitmap &= 0x000ff015;
+					else
+						rate_bitmap &= 0x000ff005;
+				}
+			}
+			break;
+		default:
+			ratr_idx = RATEID_IDX_BGN_40M_2SS;
+			rate_bitmap &= 0x0fffffff;
+			break;
+		}
+
+		priv->rssi_level = rssi_level;
+		priv->fops->update_rate_mask(priv, rate_bitmap, ratr_idx, sgi);
+	}
+}
+
+static void rtl8xxxu_watchdog_callback(struct work_struct *work)
+{
+	struct ieee80211_vif *vif;
+	struct rtl8xxxu_priv *priv;
+
+	priv = container_of(work, struct rtl8xxxu_priv, ra_watchdog.work);
+	vif = priv->vif;
+
+	if (vif && vif->type == NL80211_IFTYPE_STATION) {
+		int signal;
+		struct ieee80211_sta *sta;
+
+		rcu_read_lock();
+		sta = ieee80211_find_sta(vif, vif->bss_conf.bssid);
+		if (!sta) {
+			struct device *dev = &priv->udev->dev;
+
+			dev_dbg(dev, "%s: no sta found\n", __func__);
+			rcu_read_unlock();
+			goto out;
+		}
+		rcu_read_unlock();
+
+		signal = ieee80211_ave_rssi(vif);
+		rtl8xxxu_refresh_rate_mask(priv, signal, sta);
+	}
+
+out:
+	schedule_delayed_work(&priv->ra_watchdog, 2 * HZ);
+}
+
 static int rtl8xxxu_start(struct ieee80211_hw *hw)
 {
 	struct rtl8xxxu_priv *priv = hw->priv;
 	struct rtl8xxxu_rx_urb *rx_urb;
 	struct rtl8xxxu_tx_urb *tx_urb;
+	struct sk_buff *skb;
 	unsigned long flags;
 	int ret, i;
 
@@ -5827,7 +6280,16 @@
 		rx_urb->hw = hw;
 
 		ret = rtl8xxxu_submit_rx_urb(priv, rx_urb);
+		if (ret) {
+			if (ret != -ENOMEM) {
+				skb = (struct sk_buff *)rx_urb->urb.context;
+				dev_kfree_skb(skb);
+			}
+			rtl8xxxu_queue_rx_urb(priv, rx_urb);
+		}
 	}
+
+	schedule_delayed_work(&priv->ra_watchdog, 2 * HZ);
 exit:
 	/*
 	 * Accept all data and mgmt frames
@@ -5879,6 +6341,8 @@
 	if (priv->usb_interrupts)
 		rtl8xxxu_write32(priv, REG_USB_HIMR, 0);
 
+	cancel_delayed_work_sync(&priv->ra_watchdog);
+
 	rtl8xxxu_free_rx_resources(priv);
 	rtl8xxxu_free_tx_resources(priv);
 }
@@ -5911,7 +6375,7 @@
 	u8 dir, xtype, num;
 	int ret = 0;
 
-	host_interface = &interface->altsetting[0];
+	host_interface = interface->cur_altsetting;
 	interface_desc = &host_interface->desc;
 	endpoints = interface_desc->bNumEndpoints;
 
@@ -6051,6 +6515,10 @@
 	INIT_LIST_HEAD(&priv->rx_urb_pending_list);
 	spin_lock_init(&priv->rx_urb_lock);
 	INIT_WORK(&priv->rx_urb_wq, rtl8xxxu_rx_urb_work);
+	INIT_DELAYED_WORK(&priv->ra_watchdog, rtl8xxxu_watchdog_callback);
+	spin_lock_init(&priv->c2hcmd_lock);
+	INIT_WORK(&priv->c2hcmd_work, rtl8xxxu_c2hcmd_callback);
+	skb_queue_head_init(&priv->c2hcmd_queue);
 
 	usb_set_intfdata(interface, hw);
 
@@ -6360,6 +6828,18 @@
 	.driver_info = (unsigned long)&rtl8192eu_fops},
 {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x818c, 0xff, 0xff, 0xff),
 	.driver_info = (unsigned long)&rtl8192eu_fops},
+/* D-Link DWA-131 rev C1 */
+{USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3312, 0xff, 0xff, 0xff),
+	.driver_info = (unsigned long)&rtl8192eu_fops},
+/* TP-Link TL-WN8200ND V2 */
+{USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0126, 0xff, 0xff, 0xff),
+	.driver_info = (unsigned long)&rtl8192eu_fops},
+/* Mercusys MW300UM */
+{USB_DEVICE_AND_INTERFACE_INFO(0x2c4e, 0x0100, 0xff, 0xff, 0xff),
+	.driver_info = (unsigned long)&rtl8192eu_fops},
+/* Mercusys MW300UH */
+{USB_DEVICE_AND_INTERFACE_INFO(0x2c4e, 0x0104, 0xff, 0xff, 0xff),
+	.driver_info = (unsigned long)&rtl8192eu_fops},
 #endif
 { }
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/base.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/base.c
@@ -195,8 +195,8 @@
 	} else {
 		if (get_rf_type(rtlphy) == RF_1T2R ||
 		    get_rf_type(rtlphy) == RF_2T2R) {
-			RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
-				 "1T2R or 2T2R\n");
+			rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG,
+				"1T2R or 2T2R\n");
 			ht_cap->mcs.rx_mask[0] = 0xFF;
 			ht_cap->mcs.rx_mask[1] = 0xFF;
 			ht_cap->mcs.rx_mask[4] = 0x01;
@@ -204,7 +204,7 @@
 			ht_cap->mcs.rx_highest =
 				 cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS15);
 		} else if (get_rf_type(rtlphy) == RF_1T1R) {
-			RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "1T1R\n");
+			rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, "1T1R\n");
 
 			ht_cap->mcs.rx_mask[0] = 0xFF;
 			ht_cap->mcs.rx_mask[1] = 0x00;
@@ -436,22 +436,22 @@
 	}
 }
 
-static void _rtl_init_deferred_work(struct ieee80211_hw *hw)
+static int _rtl_init_deferred_work(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct workqueue_struct *wq;
+
+	wq = alloc_workqueue("%s", 0, 0, rtlpriv->cfg->name);
+	if (!wq)
+		return -ENOMEM;
 
 	/* <1> timer */
 	timer_setup(&rtlpriv->works.watchdog_timer,
 		    rtl_watch_dog_timer_callback, 0);
-	timer_setup(&rtlpriv->works.dualmac_easyconcurrent_retrytimer,
-		    rtl_easy_concurrent_retrytimer_callback, 0);
+
 	/* <2> work queue */
 	rtlpriv->works.hw = hw;
-	rtlpriv->works.rtl_wq = alloc_workqueue("%s", 0, 0, rtlpriv->cfg->name);
-	if (unlikely(!rtlpriv->works.rtl_wq)) {
-		pr_err("Failed to allocate work queue\n");
-		return;
-	}
+	rtlpriv->works.rtl_wq = wq;
 
 	INIT_DELAYED_WORK(&rtlpriv->works.watchdog_wq,
 			  (void *)rtl_watchdog_wq_callback);
@@ -465,6 +465,7 @@
 			  (void *)rtl_fwevt_wq_callback);
 	INIT_DELAYED_WORK(&rtlpriv->works.c2hcmd_wq,
 			  (void *)rtl_c2hcmd_wq_callback);
+	return 0;
 }
 
 void rtl_deinit_deferred_work(struct ieee80211_hw *hw, bool ips_wq)
@@ -564,9 +565,7 @@
 	rtlmac->link_state = MAC80211_NOLINK;
 
 	/* <6> init deferred work */
-	_rtl_init_deferred_work(hw);
-
-	return 0;
+	return _rtl_init_deferred_work(hw);
 }
 EXPORT_SYMBOL_GPL(rtl_init_core);
 
@@ -1324,7 +1323,7 @@
 			rtlpriv->cfg->ops->chk_switch_dmdp(hw);
 	}
 	if (ieee80211_is_auth(fc)) {
-		RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, "MAC80211_LINKING\n");
+		rtl_dbg(rtlpriv, COMP_SEND, DBG_DMESG, "MAC80211_LINKING\n");
 
 		mac->link_state = MAC80211_LINKING;
 		/* Dul mac */
@@ -1385,7 +1384,7 @@
 			if (mac->act_scanning)
 				return false;
 
-			RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
+			rtl_dbg(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
 				"%s ACT_ADDBAREQ From :%pM\n",
 				is_tx ? "Tx" : "Rx", hdr->addr2);
 			RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, "req\n",
@@ -1400,8 +1399,8 @@
 				rcu_read_lock();
 				sta = rtl_find_sta(hw, hdr->addr3);
 				if (sta == NULL) {
-					RT_TRACE(rtlpriv, COMP_SEND | COMP_RECV,
-						 DBG_DMESG, "sta is NULL\n");
+					rtl_dbg(rtlpriv, COMP_SEND | COMP_RECV,
+						DBG_DMESG, "sta is NULL\n");
 					rcu_read_unlock();
 					return true;
 				}
@@ -1428,13 +1427,13 @@
 			}
 			break;
 		case ACT_ADDBARSP:
-			RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
-				 "%s ACT_ADDBARSP From :%pM\n",
-				  is_tx ? "Tx" : "Rx", hdr->addr2);
+			rtl_dbg(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
+				"%s ACT_ADDBARSP From :%pM\n",
+				is_tx ? "Tx" : "Rx", hdr->addr2);
 			break;
 		case ACT_DELBA:
-			RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
-				 "ACT_ADDBADEL From :%pM\n", hdr->addr2);
+			rtl_dbg(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
+				"ACT_ADDBADEL From :%pM\n", hdr->addr2);
 			break;
 		}
 		break;
@@ -1519,9 +1518,9 @@
 				/* 68 : UDP BOOTP client
 				 * 67 : UDP BOOTP server
 				 */
-				RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV),
-					 DBG_DMESG, "dhcp %s !!\n",
-					 (is_tx) ? "Tx" : "Rx");
+				rtl_dbg(rtlpriv, (COMP_SEND | COMP_RECV),
+					DBG_DMESG, "dhcp %s !!\n",
+					(is_tx) ? "Tx" : "Rx");
 
 				if (is_tx)
 					setup_special_tx(rtlpriv, ppsc,
@@ -1540,8 +1539,8 @@
 		rtlpriv->btcoexist.btc_info.in_4way = true;
 		rtlpriv->btcoexist.btc_info.in_4way_ts = jiffies;
 
-		RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
-			 "802.1X %s EAPOL pkt!!\n", (is_tx) ? "Tx" : "Rx");
+		rtl_dbg(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
+			"802.1X %s EAPOL pkt!!\n", (is_tx) ? "Tx" : "Rx");
 
 		if (is_tx) {
 			rtlpriv->ra.is_special_data = true;
@@ -1583,12 +1582,12 @@
 	info = IEEE80211_SKB_CB(skb);
 	ieee80211_tx_info_clear_status(info);
 	if (ack) {
-		RT_TRACE(rtlpriv, COMP_TX_REPORT, DBG_LOUD,
-			 "tx report: ack\n");
+		rtl_dbg(rtlpriv, COMP_TX_REPORT, DBG_LOUD,
+			"tx report: ack\n");
 		info->flags |= IEEE80211_TX_STAT_ACK;
 	} else {
-		RT_TRACE(rtlpriv, COMP_TX_REPORT, DBG_LOUD,
-			 "tx report: not ack\n");
+		rtl_dbg(rtlpriv, COMP_TX_REPORT, DBG_LOUD,
+			"tx report: not ack\n");
 		info->flags &= ~IEEE80211_TX_STAT_ACK;
 	}
 	ieee80211_tx_status_irqsafe(hw, skb);
@@ -1626,8 +1625,8 @@
 	tx_report->last_sent_time = jiffies;
 	tx_info->sn = sn;
 	tx_info->send_time = tx_report->last_sent_time;
-	RT_TRACE(rtlpriv, COMP_TX_REPORT, DBG_DMESG,
-		 "Send TX-Report sn=0x%X\n", sn);
+	rtl_dbg(rtlpriv, COMP_TX_REPORT, DBG_DMESG,
+		"Send TX-Report sn=0x%X\n", sn);
 
 	return sn;
 }
@@ -1674,9 +1673,9 @@
 			break;
 		}
 	}
-	RT_TRACE(rtlpriv, COMP_TX_REPORT, DBG_DMESG,
-		 "Recv TX-Report st=0x%02X sn=0x%X retry=0x%X\n",
-		 st, sn, retry);
+	rtl_dbg(rtlpriv, COMP_TX_REPORT, DBG_DMESG,
+		"Recv TX-Report st=0x%02X sn=0x%X retry=0x%X\n",
+		st, sn, retry);
 }
 EXPORT_SYMBOL_GPL(rtl_tx_report_handler);
 
@@ -1689,9 +1688,9 @@
 		return true;
 
 	if (time_before(tx_report->last_sent_time + 3 * HZ, jiffies)) {
-		RT_TRACE(rtlpriv, COMP_TX_REPORT, DBG_WARNING,
-			 "Check TX-Report timeout!! s_sn=0x%X r_sn=0x%X\n",
-			 tx_report->last_sent_sn, tx_report->last_recv_sn);
+		rtl_dbg(rtlpriv, COMP_TX_REPORT, DBG_WARNING,
+			"Check TX-Report timeout!! s_sn=0x%X r_sn=0x%X\n",
+			tx_report->last_sent_sn, tx_report->last_recv_sn);
 		return true;	/* 3 sec. (timeout) seen as acked */
 	}
 
@@ -1707,8 +1706,8 @@
 		if (rtl_check_tx_report_acked(hw))
 			break;
 		usleep_range(1000, 2000);
-		RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
-			 "Wait 1ms (%d/%d) to disable key.\n", i, wait_ms);
+		rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG,
+			"Wait 1ms (%d/%d) to disable key.\n", i, wait_ms);
 	}
 }
 
@@ -1770,14 +1769,13 @@
 		return -ENXIO;
 	tid_data = &sta_entry->tids[tid];
 
-	RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG,
-		 "on ra = %pM tid = %d seq:%d\n", sta->addr, tid,
-		 *ssn);
+	rtl_dbg(rtlpriv, COMP_SEND, DBG_DMESG,
+		"on ra = %pM tid = %d seq:%d\n", sta->addr, tid,
+		*ssn);
 
 	tid_data->agg.agg_state = RTL_AGG_START;
 
-	ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
-	return 0;
+	return IEEE80211_AMPDU_TX_START_IMMEDIATE;
 }
 
 int rtl_tx_agg_stop(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
@@ -1789,8 +1787,8 @@
 	if (sta == NULL)
 		return -EINVAL;
 
-	RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG,
-		 "on ra = %pM tid = %d\n", sta->addr, tid);
+	rtl_dbg(rtlpriv, COMP_SEND, DBG_DMESG,
+		"on ra = %pM tid = %d\n", sta->addr, tid);
 
 	if (unlikely(tid >= MAX_TID_COUNT))
 		return -EINVAL;
@@ -1829,8 +1827,8 @@
 		return -ENXIO;
 	tid_data = &sta_entry->tids[tid];
 
-	RT_TRACE(rtlpriv, COMP_RECV, DBG_DMESG,
-		 "on ra = %pM tid = %d\n", sta->addr, tid);
+	rtl_dbg(rtlpriv, COMP_RECV, DBG_DMESG,
+		"on ra = %pM tid = %d\n", sta->addr, tid);
 
 	tid_data->agg.rx_agg_state = RTL_RX_AGG_START;
 	return 0;
@@ -1845,8 +1843,8 @@
 	if (sta == NULL)
 		return -EINVAL;
 
-	RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG,
-		 "on ra = %pM tid = %d\n", sta->addr, tid);
+	rtl_dbg(rtlpriv, COMP_SEND, DBG_DMESG,
+		"on ra = %pM tid = %d\n", sta->addr, tid);
 
 	if (unlikely(tid >= MAX_TID_COUNT))
 		return -EINVAL;
@@ -1866,8 +1864,8 @@
 	if (sta == NULL)
 		return -EINVAL;
 
-	RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG,
-		 "on ra = %pM tid = %d\n", sta->addr, tid);
+	rtl_dbg(rtlpriv, COMP_SEND, DBG_DMESG,
+		"on ra = %pM tid = %d\n", sta->addr, tid);
 
 	if (unlikely(tid >= MAX_TID_COUNT))
 		return -EINVAL;
@@ -1887,9 +1885,9 @@
 		btc_ops->btc_get_ampdu_cfg(rtlpriv, &reject_agg,
 					   &ctrl_agg_size, &agg_size);
 
-	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
-		 "Set RX AMPDU: coex - reject=%d, ctrl_agg_size=%d, size=%d",
-		 reject_agg, ctrl_agg_size, agg_size);
+	rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
+		"Set RX AMPDU: coex - reject=%d, ctrl_agg_size=%d, size=%d",
+		reject_agg, ctrl_agg_size, agg_size);
 
 	rtlpriv->hw->max_rx_aggregation_subframes =
 		(ctrl_agg_size ? agg_size : IEEE80211_MAX_AMPDU_BUF_HT);
@@ -1977,9 +1975,9 @@
 		list_del(&entry->list);
 		rtlpriv->scan_list.num--;
 
-		RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD,
-			 "BSSID=%pM is expire in scan list (total=%d)\n",
-			 entry->bssid, rtlpriv->scan_list.num);
+		rtl_dbg(rtlpriv, COMP_SCAN, DBG_LOUD,
+			"BSSID=%pM is expire in scan list (total=%d)\n",
+			entry->bssid, rtlpriv->scan_list.num);
 		kfree(entry);
 	}
 
@@ -1995,8 +1993,7 @@
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 	unsigned long flags;
 
-	struct rtl_bssid_entry *entry;
-	bool entry_found = false;
+	struct rtl_bssid_entry *entry = NULL, *iter;
 
 	/* check if it is scanning */
 	if (!mac->act_scanning)
@@ -2009,18 +2006,18 @@
 
 	spin_lock_irqsave(&rtlpriv->locks.scan_list_lock, flags);
 
-	list_for_each_entry(entry, &rtlpriv->scan_list.list, list) {
-		if (memcmp(entry->bssid, hdr->addr3, ETH_ALEN) == 0) {
-			list_del_init(&entry->list);
-			entry_found = true;
-			RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD,
-				 "Update BSSID=%pM to scan list (total=%d)\n",
-				 hdr->addr3, rtlpriv->scan_list.num);
+	list_for_each_entry(iter, &rtlpriv->scan_list.list, list) {
+		if (memcmp(iter->bssid, hdr->addr3, ETH_ALEN) == 0) {
+			list_del_init(&iter->list);
+			entry = iter;
+			rtl_dbg(rtlpriv, COMP_SCAN, DBG_LOUD,
+				"Update BSSID=%pM to scan list (total=%d)\n",
+				hdr->addr3, rtlpriv->scan_list.num);
 			break;
 		}
 	}
 
-	if (!entry_found) {
+	if (!entry) {
 		entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
 
 		if (!entry)
@@ -2029,9 +2026,9 @@
 		memcpy(entry->bssid, hdr->addr3, ETH_ALEN);
 		rtlpriv->scan_list.num++;
 
-		RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD,
-			 "Add BSSID=%pM to scan list (total=%d)\n",
-			 hdr->addr3, rtlpriv->scan_list.num);
+		rtl_dbg(rtlpriv, COMP_SCAN, DBG_LOUD,
+			"Add BSSID=%pM to scan list (total=%d)\n",
+			hdr->addr3, rtlpriv->scan_list.num);
 	}
 
 	entry->age = jiffies;
@@ -2191,8 +2188,8 @@
 		if ((rtlpriv->link_info.bcn_rx_inperiod +
 		    rtlpriv->link_info.num_rx_inperiod) == 0) {
 			rtlpriv->link_info.roam_times++;
-			RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG,
-				 "AP off for %d s\n",
+			rtl_dbg(rtlpriv, COMP_ERR, DBG_DMESG,
+				"AP off for %d s\n",
 				(rtlpriv->link_info.roam_times * 2));
 
 			/* if we can't recv beacon for 10s,
@@ -2305,11 +2302,11 @@
 
 	switch (cmd_id) {
 	case C2H_DBG:
-		RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "[C2H], C2H_DBG!!\n");
+		rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "[C2H], C2H_DBG!!\n");
 		break;
 	case C2H_TXBF:
-		RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
-			 "[C2H], C2H_TXBF!!\n");
+		rtl_dbg(rtlpriv, COMP_FW, DBG_TRACE,
+			"[C2H], C2H_TXBF!!\n");
 		break;
 	case C2H_TX_REPORT:
 		rtl_tx_report_handler(hw, cmd_buf, cmd_len);
@@ -2319,20 +2316,20 @@
 			hal_ops->c2h_ra_report_handler(hw, cmd_buf, cmd_len);
 		break;
 	case C2H_BT_INFO:
-		RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
-			 "[C2H], C2H_BT_INFO!!\n");
+		rtl_dbg(rtlpriv, COMP_FW, DBG_TRACE,
+			"[C2H], C2H_BT_INFO!!\n");
 		if (rtlpriv->cfg->ops->get_btc_status())
 			btc_ops->btc_btinfo_notify(rtlpriv, cmd_buf, cmd_len);
 		break;
 	case C2H_BT_MP:
-		RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
-			 "[C2H], C2H_BT_MP!!\n");
+		rtl_dbg(rtlpriv, COMP_FW, DBG_TRACE,
+			"[C2H], C2H_BT_MP!!\n");
 		if (rtlpriv->cfg->ops->get_btc_status())
 			btc_ops->btc_btmpinfo_notify(rtlpriv, cmd_buf, cmd_len);
 		break;
 	default:
-		RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
-			 "[C2H], Unknown packet!! cmd_id(%#X)!\n", cmd_id);
+		rtl_dbg(rtlpriv, COMP_FW, DBG_TRACE,
+			"[C2H], Unknown packet!! cmd_id(%#X)!\n", cmd_id);
 		break;
 	}
 }
@@ -2356,8 +2353,8 @@
 		if (!skb)
 			break;
 
-		RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG, "C2H rx_desc_shift=%d\n",
-			 *((u8 *)skb->cb));
+		rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG, "C2H rx_desc_shift=%d\n",
+			*((u8 *)skb->cb));
 		RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_DMESG,
 			      "C2H data: ", skb->data, skb->len);
 
@@ -2379,19 +2376,6 @@
 	rtl_c2hcmd_launcher(hw, 1);
 }
 
-void rtl_easy_concurrent_retrytimer_callback(struct timer_list *t)
-{
-	struct rtl_priv *rtlpriv =
-		from_timer(rtlpriv, t, works.dualmac_easyconcurrent_retrytimer);
-	struct ieee80211_hw *hw = rtlpriv->hw;
-	struct rtl_priv *buddy_priv = rtlpriv->buddy_priv;
-
-	if (buddy_priv == NULL)
-		return;
-
-	rtlpriv->cfg->ops->dualmac_easy_concurrent(hw);
-}
-
 /*********************************************************
  *
  * frame process functions
@@ -2702,29 +2686,29 @@
 		(memcmp(mac->bssid, ap5_6, 3) == 0) ||
 		vendor == PEER_ATH) {
 		vendor = PEER_ATH;
-		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "=>ath find\n");
+		rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD, "=>ath find\n");
 	} else if ((memcmp(mac->bssid, ap4_4, 3) == 0) ||
 		(memcmp(mac->bssid, ap4_5, 3) == 0) ||
 		(memcmp(mac->bssid, ap4_1, 3) == 0) ||
 		(memcmp(mac->bssid, ap4_2, 3) == 0) ||
 		(memcmp(mac->bssid, ap4_3, 3) == 0) ||
 		vendor == PEER_RAL) {
-		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "=>ral find\n");
+		rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD, "=>ral find\n");
 		vendor = PEER_RAL;
 	} else if (memcmp(mac->bssid, ap6_1, 3) == 0 ||
 		vendor == PEER_CISCO) {
 		vendor = PEER_CISCO;
-		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "=>cisco find\n");
+		rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD, "=>cisco find\n");
 	} else if ((memcmp(mac->bssid, ap3_1, 3) == 0) ||
 		(memcmp(mac->bssid, ap3_2, 3) == 0) ||
 		(memcmp(mac->bssid, ap3_3, 3) == 0) ||
 		vendor == PEER_BROAD) {
-		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "=>broad find\n");
+		rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD, "=>broad find\n");
 		vendor = PEER_BROAD;
 	} else if (memcmp(mac->bssid, ap7_1, 3) == 0 ||
 		vendor == PEER_MARV) {
 		vendor = PEER_MARV;
-		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "=>marv find\n");
+		rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD, "=>marv find\n");
 	}
 
 	mac->vendor = vendor;
@@ -2737,9 +2721,6 @@
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core");
 
-struct rtl_global_var rtl_global_var = {};
-EXPORT_SYMBOL_GPL(rtl_global_var);
-
 static int __init rtl_core_module_init(void)
 {
 	BUILD_BUG_ON(TX_PWR_BY_RATE_NUM_RATE < TX_PWR_BY_RATE_NUM_SECTION);
@@ -2753,10 +2734,6 @@
 	/* add debugfs */
 	rtl_debugfs_add_topdir();
 
-	/* init some global vars */
-	INIT_LIST_HEAD(&rtl_global_var.glb_priv_list);
-	spin_lock_init(&rtl_global_var.glb_list_lock);
-
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/base.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/base.h
@@ -127,8 +127,6 @@
 u8 *rtl_find_ie(u8 *data, unsigned int len, u8 ie);
 void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len);
 u8 rtl_tid_to_ac(u8 tid);
-void rtl_easy_concurrent_retrytimer_callback(struct timer_list *t);
-extern struct rtl_global_var rtl_global_var;
 void rtl_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation);
 
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/cam.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/cam.c
@@ -43,14 +43,14 @@
 			rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM],
 					target_command);
 
-			RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
-				 "WRITE %x: %x\n",
-				 rtlpriv->cfg->maps[WCAMI], target_content);
-			RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
-				 "The Key ID is %d\n", entry_no);
-			RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
-				 "WRITE %x: %x\n",
-				 rtlpriv->cfg->maps[RWCAM], target_command);
+			rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD,
+				"WRITE %x: %x\n",
+				rtlpriv->cfg->maps[WCAMI], target_content);
+			rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD,
+				"The Key ID is %d\n", entry_no);
+			rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD,
+				"WRITE %x: %x\n",
+				rtlpriv->cfg->maps[RWCAM], target_command);
 
 		} else if (entry_i == 1) {
 
@@ -64,10 +64,10 @@
 			rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM],
 					target_command);
 
-			RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
-				 "WRITE A4: %x\n", target_content);
-			RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
-				 "WRITE A0: %x\n", target_command);
+			rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD,
+				"WRITE A4: %x\n", target_content);
+			rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD,
+				"WRITE A0: %x\n", target_command);
 
 		} else {
 
@@ -83,15 +83,15 @@
 			rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM],
 					target_command);
 
-			RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
-				 "WRITE A4: %x\n", target_content);
-			RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
-				 "WRITE A0: %x\n", target_command);
+			rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD,
+				"WRITE A4: %x\n", target_content);
+			rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD,
+				"WRITE A0: %x\n", target_command);
 		}
 	}
 
-	RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
-		 "after set key, usconfig:%x\n", us_config);
+	rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD,
+		"after set key, usconfig:%x\n", us_config);
 }
 
 u8 rtl_cam_add_one_entry(struct ieee80211_hw *hw, u8 *mac_addr,
@@ -101,14 +101,14 @@
 	u32 us_config;
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 
-	RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
-		 "EntryNo:%x, ulKeyId=%x, ulEncAlg=%x, ulUseDK=%x MacAddr %pM\n",
-		 ul_entry_idx, ul_key_id, ul_enc_alg,
-		 ul_default_key, mac_addr);
+	rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG,
+		"EntryNo:%x, ulKeyId=%x, ulEncAlg=%x, ulUseDK=%x MacAddr %pM\n",
+		ul_entry_idx, ul_key_id, ul_enc_alg,
+		ul_default_key, mac_addr);
 
 	if (ul_key_id == TOTAL_CAM_ENTRY) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
-			 "ulKeyId exceed!\n");
+		rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
+			"ulKeyId exceed!\n");
 		return 0;
 	}
 
@@ -120,7 +120,7 @@
 	rtl_cam_program_entry(hw, ul_entry_idx, mac_addr,
 			      (u8 *)key_content, us_config);
 
-	RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "end\n");
+	rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, "end\n");
 
 	return 1;
 
@@ -133,7 +133,7 @@
 	u32 ul_command;
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 
-	RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "key_idx:%d\n", ul_key_id);
+	rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, "key_idx:%d\n", ul_key_id);
 
 	ul_command = ul_key_id * CAM_CONTENT_COUNT;
 	ul_command = ul_command | BIT(31) | BIT(16);
@@ -141,10 +141,10 @@
 	rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], 0);
 	rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command);
 
-	RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
-		 "rtl_cam_delete_one_entry(): WRITE A4: %x\n", 0);
-	RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
-		 "rtl_cam_delete_one_entry(): WRITE A0: %x\n", ul_command);
+	rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG,
+		"%s: WRITE A4: %x\n", __func__, 0);
+	rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG,
+		"%s: WRITE A0: %x\n", __func__, ul_command);
 
 	return 0;
 
@@ -195,10 +195,10 @@
 	rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], ul_content);
 	rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command);
 
-	RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
-		 "rtl_cam_mark_invalid(): WRITE A4: %x\n", ul_content);
-	RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
-		 "rtl_cam_mark_invalid(): WRITE A0: %x\n", ul_command);
+	rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG,
+		"%s: WRITE A4: %x\n", __func__, ul_content);
+	rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG,
+		"%s: WRITE A0: %x\n", __func__, ul_command);
 }
 EXPORT_SYMBOL(rtl_cam_mark_invalid);
 
@@ -245,12 +245,10 @@
 		rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], ul_content);
 		rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command);
 
-		RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
-			 "rtl_cam_empty_entry(): WRITE A4: %x\n",
-			 ul_content);
-		RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
-			 "rtl_cam_empty_entry(): WRITE A0: %x\n",
-			 ul_command);
+		rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD,
+			"%s: WRITE A4: %x\n", __func__, ul_content);
+		rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD,
+			"%s: WRITE A0: %x\n", __func__, ul_command);
 	}
 
 }
@@ -313,8 +311,8 @@
 			/* Remove from HW Security CAM */
 			eth_zero_addr(rtlpriv->sec.hwsec_cam_sta_addr[i]);
 			rtlpriv->sec.hwsec_cam_bitmap &= ~(BIT(0) << i);
-			RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
-				 "&&&&&&&&&del entry %d\n", i);
+			rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG,
+				"&&&&&&&&&del entry %d\n", i);
 		}
 	}
 	return;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/core.c
@@ -76,8 +76,8 @@
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	int err;
 
-	RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
-		 "Firmware callback routine entered!\n");
+	rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
+		"Firmware callback routine entered!\n");
 	complete(&rtlpriv->firmware_loading_complete);
 	if (!firmware) {
 		if (rtlpriv->cfg->alt_fw_name) {
@@ -214,8 +214,8 @@
 	u8 retry_limit = 0x30;
 
 	if (mac->vif) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
-			 "vif has been set!! mac->vif = 0x%p\n", mac->vif);
+		rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
+			"vif has been set!! mac->vif = 0x%p\n", mac->vif);
 		return -EOPNOTSUPP;
 	}
 
@@ -230,16 +230,16 @@
 		/*fall through*/
 	case NL80211_IFTYPE_STATION:
 		if (mac->beacon_enabled == 1) {
-			RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
-				 "NL80211_IFTYPE_STATION\n");
+			rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD,
+				"NL80211_IFTYPE_STATION\n");
 			mac->beacon_enabled = 0;
 			rtlpriv->cfg->ops->update_interrupt_mask(hw, 0,
 					rtlpriv->cfg->maps[RTL_IBSS_INT_MASKS]);
 		}
 		break;
 	case NL80211_IFTYPE_ADHOC:
-		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
-			 "NL80211_IFTYPE_ADHOC\n");
+		rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD,
+			"NL80211_IFTYPE_ADHOC\n");
 
 		mac->link_state = MAC80211_LINKED;
 		rtlpriv->cfg->ops->set_bcn_reg(hw);
@@ -256,8 +256,8 @@
 		mac->p2p = P2P_ROLE_GO;
 		/*fall through*/
 	case NL80211_IFTYPE_AP:
-		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
-			 "NL80211_IFTYPE_AP\n");
+		rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD,
+			"NL80211_IFTYPE_AP\n");
 
 		mac->link_state = MAC80211_LINKED;
 		rtlpriv->cfg->ops->set_bcn_reg(hw);
@@ -271,8 +271,8 @@
 		retry_limit = 0x07;
 		break;
 	case NL80211_IFTYPE_MESH_POINT:
-		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
-			 "NL80211_IFTYPE_MESH_POINT\n");
+		rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD,
+			"NL80211_IFTYPE_MESH_POINT\n");
 
 		mac->link_state = MAC80211_LINKED;
 		rtlpriv->cfg->ops->set_bcn_reg(hw);
@@ -293,8 +293,8 @@
 	}
 
 	if (mac->p2p) {
-		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
-			 "p2p role %x\n", vif->type);
+		rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD,
+			"p2p role %x\n", vif->type);
 		mac->basic_rates = 0xff0;/*disable cck rate for p2p*/
 		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE,
 				(u8 *)(&mac->basic_rates));
@@ -360,8 +360,8 @@
 	vif->type = new_type;
 	vif->p2p = p2p;
 	ret = rtl_op_add_interface(hw, vif);
-	RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
-		 "p2p  %x\n", p2p);
+	rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD,
+		"p2p  %x\n", p2p);
 	return ret;
 }
 
@@ -435,8 +435,8 @@
 		memset(mask, 0, MAX_WOL_BIT_MASK_SIZE);
 		if (patterns[i].pattern_len < 0 ||
 		    patterns[i].pattern_len > MAX_WOL_PATTERN_SIZE) {
-			RT_TRACE(rtlpriv, COMP_POWER, DBG_WARNING,
-				 "Pattern[%d] is too long\n", i);
+			rtl_dbg(rtlpriv, COMP_POWER, DBG_WARNING,
+				"Pattern[%d] is too long\n", i);
 			continue;
 		}
 		pattern_os = patterns[i].pattern;
@@ -515,8 +515,8 @@
 			      "pattern to hw\n", content, len);
 		/* 3. calculate crc */
 		rtl_pattern.crc = _calculate_wol_pattern_crc(content, len);
-		RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
-			 "CRC_Remainder = 0x%x\n", rtl_pattern.crc);
+		rtl_dbg(rtlpriv, COMP_POWER, DBG_TRACE,
+			"CRC_Remainder = 0x%x\n", rtl_pattern.crc);
 
 		/* 4. write crc & mask_for_hw to hw */
 		rtlpriv->cfg->ops->add_wowlan_pattern(hw, &rtl_pattern, i);
@@ -531,7 +531,7 @@
 	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 
-	RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "\n");
+	rtl_dbg(rtlpriv, COMP_POWER, DBG_DMESG, "\n");
 	if (WARN_ON(!wow))
 		return -EINVAL;
 
@@ -557,7 +557,7 @@
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 	time64_t now;
 
-	RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, "\n");
+	rtl_dbg(rtlpriv, COMP_POWER, DBG_DMESG, "\n");
 	rtlhal->driver_is_goingto_unload = false;
 	rtlhal->enter_pnp_sleep = false;
 	rtlhal->wake_from_pnp_sleep = true;
@@ -588,8 +588,8 @@
 
 	mutex_lock(&rtlpriv->locks.conf_mutex);
 	if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) {	/* BIT(2)*/
-		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
-			 "IEEE80211_CONF_CHANGE_LISTEN_INTERVAL\n");
+		rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD,
+			"IEEE80211_CONF_CHANGE_LISTEN_INTERVAL\n");
 	}
 
 	/*For IPS */
@@ -632,9 +632,9 @@
 	}
 
 	if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) {
-		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
-			 "IEEE80211_CONF_CHANGE_RETRY_LIMITS %x\n",
-			 hw->conf.long_frame_max_tx_count);
+		rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD,
+			"IEEE80211_CONF_CHANGE_RETRY_LIMITS %x\n",
+			hw->conf.long_frame_max_tx_count);
 		/* brought up everything changes (changed == ~0) indicates first
 		 * open, so use our default value instead of that of wiphy.
 		 */
@@ -809,13 +809,13 @@
 		if (*new_flags & FIF_ALLMULTI) {
 			mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_AM] |
 			    rtlpriv->cfg->maps[MAC_RCR_AB];
-			RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
-				 "Enable receive multicast frame\n");
+			rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD,
+				"Enable receive multicast frame\n");
 		} else {
 			mac->rx_conf &= ~(rtlpriv->cfg->maps[MAC_RCR_AM] |
 					  rtlpriv->cfg->maps[MAC_RCR_AB]);
-			RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
-				 "Disable receive multicast frame\n");
+			rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD,
+				"Disable receive multicast frame\n");
 		}
 		update_rcr = true;
 	}
@@ -823,12 +823,12 @@
 	if (changed_flags & FIF_FCSFAIL) {
 		if (*new_flags & FIF_FCSFAIL) {
 			mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_ACRC32];
-			RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
-				 "Enable receive FCS error frame\n");
+			rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD,
+				"Enable receive FCS error frame\n");
 		} else {
 			mac->rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_ACRC32];
-			RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
-				 "Disable receive FCS error frame\n");
+			rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD,
+				"Disable receive FCS error frame\n");
 		}
 		if (!update_rcr)
 			update_rcr = true;
@@ -855,12 +855,12 @@
 		if (*new_flags & FIF_CONTROL) {
 			mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_ACF];
 
-			RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
-				 "Enable receive control frame.\n");
+			rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD,
+				"Enable receive control frame.\n");
 		} else {
 			mac->rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_ACF];
-			RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
-				 "Disable receive control frame.\n");
+			rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD,
+				"Disable receive control frame.\n");
 		}
 		if (!update_rcr)
 			update_rcr = true;
@@ -869,12 +869,12 @@
 	if (changed_flags & FIF_OTHER_BSS) {
 		if (*new_flags & FIF_OTHER_BSS) {
 			mac->rx_conf |= rtlpriv->cfg->maps[MAC_RCR_AAP];
-			RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
-				 "Enable receive other BSS's frame.\n");
+			rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD,
+				"Enable receive other BSS's frame.\n");
 		} else {
 			mac->rx_conf &= ~rtlpriv->cfg->maps[MAC_RCR_AAP];
-			RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
-				 "Disable receive other BSS's frame.\n");
+			rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD,
+				"Disable receive other BSS's frame.\n");
 		}
 		if (!update_rcr)
 			update_rcr = true;
@@ -923,7 +923,7 @@
 			sta->supp_rates[0] &= 0xfffffff0;
 
 		memcpy(sta_entry->mac_addr, sta->addr, ETH_ALEN);
-		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
+		rtl_dbg(rtlpriv, COMP_MAC80211, DBG_DMESG,
 			"Add sta addr is %pM\n", sta->addr);
 		rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 0, true);
 	}
@@ -939,8 +939,8 @@
 	struct rtl_sta_info *sta_entry;
 
 	if (sta) {
-		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
-			 "Remove sta addr is %pM\n", sta->addr);
+		rtl_dbg(rtlpriv, COMP_MAC80211, DBG_DMESG,
+			"Remove sta addr is %pM\n", sta->addr);
 		sta_entry = (struct rtl_sta_info *)sta->drv_priv;
 		sta_entry->wireless_mode = 0;
 		sta_entry->ratr_index = 0;
@@ -988,8 +988,8 @@
 	int aci;
 
 	if (queue >= AC_MAX) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
-			 "queue number %d is incorrect!\n", queue);
+		rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
+			"queue number %d is incorrect!\n", queue);
 		return -EINVAL;
 	}
 
@@ -1034,8 +1034,8 @@
 		    (changed & BSS_CHANGED_BEACON_ENABLED &&
 		     bss_conf->enable_beacon)) {
 			if (mac->beacon_enabled == 0) {
-				RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
-					 "BSS_CHANGED_BEACON_ENABLED\n");
+				rtl_dbg(rtlpriv, COMP_MAC80211, DBG_DMESG,
+					"BSS_CHANGED_BEACON_ENABLED\n");
 
 				/*start hw beacon interrupt. */
 				/*rtlpriv->cfg->ops->set_bcn_reg(hw); */
@@ -1052,8 +1052,8 @@
 		if ((changed & BSS_CHANGED_BEACON_ENABLED &&
 		    !bss_conf->enable_beacon)) {
 			if (mac->beacon_enabled == 1) {
-				RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
-					 "ADHOC DISABLE BEACON\n");
+				rtl_dbg(rtlpriv, COMP_MAC80211, DBG_DMESG,
+					"ADHOC DISABLE BEACON\n");
 
 				mac->beacon_enabled = 0;
 				rtlpriv->cfg->ops->update_interrupt_mask(hw, 0,
@@ -1062,8 +1062,8 @@
 			}
 		}
 		if (changed & BSS_CHANGED_BEACON_INT) {
-			RT_TRACE(rtlpriv, COMP_BEACON, DBG_TRACE,
-				 "BSS_CHANGED_BEACON_INT\n");
+			rtl_dbg(rtlpriv, COMP_BEACON, DBG_TRACE,
+				"BSS_CHANGED_BEACON_INT\n");
 			mac->beacon_interval = bss_conf->beacon_int;
 			rtlpriv->cfg->ops->set_bcn_intv(hw);
 		}
@@ -1102,8 +1102,8 @@
 				rcu_read_unlock();
 				goto out;
 			}
-			RT_TRACE(rtlpriv, COMP_EASY_CONCURRENT, DBG_LOUD,
-				 "send PS STATIC frame\n");
+			rtl_dbg(rtlpriv, COMP_EASY_CONCURRENT, DBG_LOUD,
+				"send PS STATIC frame\n");
 			if (rtlpriv->dm.supp_phymode_switch) {
 				if (sta->ht_cap.ht_supported)
 					rtl_send_smps_action(hw, sta,
@@ -1143,8 +1143,8 @@
 						      HW_VAR_KEEP_ALIVE,
 						      (u8 *)(&keep_alive));
 
-			RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
-				 "BSS_CHANGED_ASSOC\n");
+			rtl_dbg(rtlpriv, COMP_MAC80211, DBG_DMESG,
+				"BSS_CHANGED_ASSOC\n");
 		} else {
 			struct cfg80211_bss *bss = NULL;
 
@@ -1161,14 +1161,14 @@
 					       IEEE80211_BSS_TYPE_ESS,
 					       IEEE80211_PRIVACY_OFF);
 
-			RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
-				 "bssid = %pMF\n", mac->bssid);
+			rtl_dbg(rtlpriv, COMP_MAC80211, DBG_DMESG,
+				"bssid = %pMF\n", mac->bssid);
 
 			if (bss) {
 				cfg80211_unlink_bss(hw->wiphy, bss);
 				cfg80211_put_bss(hw->wiphy, bss);
-				RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
-					 "cfg80211_unlink !!\n");
+				rtl_dbg(rtlpriv, COMP_MAC80211, DBG_DMESG,
+					"cfg80211_unlink !!\n");
 			}
 
 			eth_zero_addr(mac->bssid);
@@ -1179,8 +1179,8 @@
 				if (rtlpriv->cfg->ops->chk_switch_dmdp)
 					rtlpriv->cfg->ops->chk_switch_dmdp(hw);
 			}
-			RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
-				 "BSS_CHANGED_UN_ASSOC\n");
+			rtl_dbg(rtlpriv, COMP_MAC80211, DBG_DMESG,
+				"BSS_CHANGED_UN_ASSOC\n");
 		}
 		rtlpriv->cfg->ops->set_network_type(hw, vif->type);
 		/* For FW LPS:
@@ -1198,14 +1198,14 @@
 	}
 
 	if (changed & BSS_CHANGED_ERP_CTS_PROT) {
-		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
-			 "BSS_CHANGED_ERP_CTS_PROT\n");
+		rtl_dbg(rtlpriv, COMP_MAC80211, DBG_TRACE,
+			"BSS_CHANGED_ERP_CTS_PROT\n");
 		mac->use_cts_protect = bss_conf->use_cts_prot;
 	}
 
 	if (changed & BSS_CHANGED_ERP_PREAMBLE) {
-		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
-			 "BSS_CHANGED_ERP_PREAMBLE use short preamble:%x\n",
+		rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD,
+			"BSS_CHANGED_ERP_PREAMBLE use short preamble:%x\n",
 			  bss_conf->use_short_preamble);
 
 		mac->short_preamble = bss_conf->use_short_preamble;
@@ -1214,8 +1214,8 @@
 	}
 
 	if (changed & BSS_CHANGED_ERP_SLOT) {
-		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
-			 "BSS_CHANGED_ERP_SLOT\n");
+		rtl_dbg(rtlpriv, COMP_MAC80211, DBG_TRACE,
+			"BSS_CHANGED_ERP_SLOT\n");
 
 		if (bss_conf->use_short_slot)
 			mac->slot_time = RTL_SLOT_TIME_9;
@@ -1229,8 +1229,8 @@
 	if (changed & BSS_CHANGED_HT) {
 		struct ieee80211_sta *sta = NULL;
 
-		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
-			 "BSS_CHANGED_HT\n");
+		rtl_dbg(rtlpriv, COMP_MAC80211, DBG_TRACE,
+			"BSS_CHANGED_HT\n");
 
 		rcu_read_lock();
 		sta = ieee80211_find_sta(vif, (u8 *)bss_conf->bssid);
@@ -1261,8 +1261,8 @@
 		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BSSID,
 					      (u8 *)bss_conf->bssid);
 
-		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_DMESG,
-			 "bssid: %pM\n", bss_conf->bssid);
+		rtl_dbg(rtlpriv, COMP_MAC80211, DBG_DMESG,
+			"bssid: %pM\n", bss_conf->bssid);
 
 		mac->vendor = PEER_UNKNOWN;
 		memcpy(mac->bssid, bss_conf->bssid, ETH_ALEN);
@@ -1393,27 +1393,27 @@
 
 	switch (action) {
 	case IEEE80211_AMPDU_TX_START:
-		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
-			 "IEEE80211_AMPDU_TX_START: TID:%d\n", tid);
+		rtl_dbg(rtlpriv, COMP_MAC80211, DBG_TRACE,
+			"IEEE80211_AMPDU_TX_START: TID:%d\n", tid);
 		return rtl_tx_agg_start(hw, vif, sta, tid, ssn);
 	case IEEE80211_AMPDU_TX_STOP_CONT:
 	case IEEE80211_AMPDU_TX_STOP_FLUSH:
 	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
-		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
-			 "IEEE80211_AMPDU_TX_STOP: TID:%d\n", tid);
+		rtl_dbg(rtlpriv, COMP_MAC80211, DBG_TRACE,
+			"IEEE80211_AMPDU_TX_STOP: TID:%d\n", tid);
 		return rtl_tx_agg_stop(hw, vif, sta, tid);
 	case IEEE80211_AMPDU_TX_OPERATIONAL:
-		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
-			 "IEEE80211_AMPDU_TX_OPERATIONAL:TID:%d\n", tid);
+		rtl_dbg(rtlpriv, COMP_MAC80211, DBG_TRACE,
+			"IEEE80211_AMPDU_TX_OPERATIONAL:TID:%d\n", tid);
 		rtl_tx_agg_oper(hw, sta, tid);
 		break;
 	case IEEE80211_AMPDU_RX_START:
-		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
-			 "IEEE80211_AMPDU_RX_START:TID:%d\n", tid);
+		rtl_dbg(rtlpriv, COMP_MAC80211, DBG_TRACE,
+			"IEEE80211_AMPDU_RX_START:TID:%d\n", tid);
 		return rtl_rx_agg_start(hw, sta, tid);
 	case IEEE80211_AMPDU_RX_STOP:
-		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
-			 "IEEE80211_AMPDU_RX_STOP:TID:%d\n", tid);
+		rtl_dbg(rtlpriv, COMP_MAC80211, DBG_TRACE,
+			"IEEE80211_AMPDU_RX_STOP:TID:%d\n", tid);
 		return rtl_rx_agg_stop(hw, sta, tid);
 	default:
 		pr_err("IEEE80211_AMPDU_ERR!!!!:\n");
@@ -1429,7 +1429,7 @@
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 
-	RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "\n");
+	rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD, "\n");
 	mac->act_scanning = true;
 	if (rtlpriv->link_info.higher_busytraffic) {
 		mac->skip_scan = true;
@@ -1467,7 +1467,7 @@
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 
-	RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD, "\n");
+	rtl_dbg(rtlpriv, COMP_MAC80211, DBG_LOUD, "\n");
 	mac->act_scanning = false;
 	mac->skip_scan = false;
 
@@ -1517,8 +1517,8 @@
 	rtlpriv->btcoexist.btc_info.in_4way = false;
 
 	if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
-			 "not open hw encryption\n");
+		rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
+			"not open hw encryption\n");
 		return -ENOSPC;	/*User disabled HW-crypto */
 	}
 	/* To support IBSS, use sw-crypto for GTK */
@@ -1526,10 +1526,10 @@
 	     vif->type == NL80211_IFTYPE_MESH_POINT) &&
 	    !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
 		return -ENOSPC;
-	RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
-		 "%s hardware based encryption for keyidx: %d, mac: %pM\n",
-		  cmd == SET_KEY ? "Using" : "Disabling", key->keyidx,
-		  sta ? sta->addr : bcast_addr);
+	rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG,
+		"%s hardware based encryption for keyidx: %d, mac: %pM\n",
+		cmd == SET_KEY ? "Using" : "Disabling", key->keyidx,
+		sta ? sta->addr : bcast_addr);
 	rtlpriv->sec.being_setkey = true;
 	rtl_ips_nic_on(hw);
 	mutex_lock(&rtlpriv->locks.conf_mutex);
@@ -1538,28 +1538,28 @@
 	switch (key->cipher) {
 	case WLAN_CIPHER_SUITE_WEP40:
 		key_type = WEP40_ENCRYPTION;
-		RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:WEP40\n");
+		rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, "alg:WEP40\n");
 		break;
 	case WLAN_CIPHER_SUITE_WEP104:
-		RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:WEP104\n");
+		rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, "alg:WEP104\n");
 		key_type = WEP104_ENCRYPTION;
 		break;
 	case WLAN_CIPHER_SUITE_TKIP:
 		key_type = TKIP_ENCRYPTION;
-		RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:TKIP\n");
+		rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, "alg:TKIP\n");
 		break;
 	case WLAN_CIPHER_SUITE_CCMP:
 		key_type = AESCCMP_ENCRYPTION;
-		RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:CCMP\n");
+		rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, "alg:CCMP\n");
 		break;
 	case WLAN_CIPHER_SUITE_AES_CMAC:
 		/* HW don't support CMAC encryption,
 		 * use software CMAC encryption
 		 */
 		key_type = AESCMAC_ENCRYPTION;
-		RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "alg:CMAC\n");
-		RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
-			 "HW don't support CMAC encryption, use software CMAC encryption\n");
+		rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, "alg:CMAC\n");
+		rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG,
+			"HW don't support CMAC encryption, use software CMAC encryption\n");
 		err = -EOPNOTSUPP;
 		goto out_unlock;
 	default:
@@ -1605,9 +1605,9 @@
 			    key_type == WEP104_ENCRYPTION))
 				wep_only = true;
 			rtlpriv->sec.pairwise_enc_algorithm = key_type;
-			RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
-				 "set enable_hw_sec, key_type:%x(OPEN:0 WEP40:1 TKIP:2 AES:4 WEP104:5)\n",
-				 key_type);
+			rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG,
+				"set enable_hw_sec, key_type:%x(OPEN:0 WEP40:1 TKIP:2 AES:4 WEP104:5)\n",
+				key_type);
 			rtlpriv->cfg->ops->enable_hw_sec(hw);
 		}
 	}
@@ -1615,8 +1615,8 @@
 	switch (cmd) {
 	case SET_KEY:
 		if (wep_only) {
-			RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
-				 "set WEP(group/pairwise) key\n");
+			rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG,
+				"set WEP(group/pairwise) key\n");
 			/* Pairwise key with an assigned MAC address. */
 			rtlpriv->sec.pairwise_enc_algorithm = key_type;
 			rtlpriv->sec.group_enc_algorithm = key_type;
@@ -1626,8 +1626,8 @@
 			rtlpriv->sec.key_len[key_idx] = key->keylen;
 			eth_zero_addr(mac_addr);
 		} else if (group_key) {	/* group key */
-			RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
-				 "set group key\n");
+			rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG,
+				"set group key\n");
 			/* group key */
 			rtlpriv->sec.group_enc_algorithm = key_type;
 			/*set local buf about group key. */
@@ -1636,8 +1636,8 @@
 			rtlpriv->sec.key_len[key_idx] = key->keylen;
 			memcpy(mac_addr, bcast_addr, ETH_ALEN);
 		} else {	/* pairwise key */
-			RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
-				 "set pairwise key\n");
+			rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG,
+				"set pairwise key\n");
 			if (!sta) {
 				WARN_ONCE(true,
 					  "rtlwifi: pairwise key without mac_addr\n");
@@ -1669,8 +1669,8 @@
 			key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
 		break;
 	case DISABLE_KEY:
-		RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
-			 "disable key delete one entry\n");
+		rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG,
+			"disable key delete one entry\n");
 		/*set local buf about wep key. */
 		if (vif->type == NL80211_IFTYPE_AP ||
 			vif->type == NL80211_IFTYPE_MESH_POINT) {
@@ -1718,9 +1718,9 @@
 		if (unlikely(radio_state != rtlpriv->rfkill.rfkill_state)) {
 			rtlpriv->rfkill.rfkill_state = radio_state;
 
-			RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
-				 "wireless radio switch turned %s\n",
-				  radio_state ? "on" : "off");
+			rtl_dbg(rtlpriv, COMP_RF, DBG_DMESG,
+				"wireless radio switch turned %s\n",
+				radio_state ? "on" : "off");
 
 			blocked = (rtlpriv->rfkill.rfkill_state == 1) ? 0 : 1;
 			wiphy_rfkill_set_hw_state(hw->wiphy, blocked);
@@ -1765,26 +1765,27 @@
 
 	do {
 		cfg_cmd = pwrcfgcmd[ary_idx];
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 "rtl_hal_pwrseqcmdparsing(): offset(%#x),cut_msk(%#x), famsk(%#x), interface_msk(%#x), base(%#x), cmd(%#x), msk(%#x), value(%#x)\n",
-			 GET_PWR_CFG_OFFSET(cfg_cmd),
-					    GET_PWR_CFG_CUT_MASK(cfg_cmd),
-			 GET_PWR_CFG_FAB_MASK(cfg_cmd),
-					      GET_PWR_CFG_INTF_MASK(cfg_cmd),
-			 GET_PWR_CFG_BASE(cfg_cmd), GET_PWR_CFG_CMD(cfg_cmd),
-			 GET_PWR_CFG_MASK(cfg_cmd), GET_PWR_CFG_VALUE(cfg_cmd));
+		rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE,
+			"%s: offset(%#x),cut_msk(%#x), famsk(%#x), interface_msk(%#x), base(%#x), cmd(%#x), msk(%#x), value(%#x)\n",
+			__func__,
+			GET_PWR_CFG_OFFSET(cfg_cmd),
+					   GET_PWR_CFG_CUT_MASK(cfg_cmd),
+			GET_PWR_CFG_FAB_MASK(cfg_cmd),
+					     GET_PWR_CFG_INTF_MASK(cfg_cmd),
+			GET_PWR_CFG_BASE(cfg_cmd), GET_PWR_CFG_CMD(cfg_cmd),
+			GET_PWR_CFG_MASK(cfg_cmd), GET_PWR_CFG_VALUE(cfg_cmd));
 
 		if ((GET_PWR_CFG_FAB_MASK(cfg_cmd)&faversion) &&
 		    (GET_PWR_CFG_CUT_MASK(cfg_cmd)&cut_version) &&
 		    (GET_PWR_CFG_INTF_MASK(cfg_cmd)&interface_type)) {
 			switch (GET_PWR_CFG_CMD(cfg_cmd)) {
 			case PWR_CMD_READ:
-				RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+				rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE,
 					"rtl_hal_pwrseqcmdparsing(): PWR_CMD_READ\n");
 				break;
 			case PWR_CMD_WRITE:
-				RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-					 "%s(): PWR_CMD_WRITE\n", __func__);
+				rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE,
+					"%s(): PWR_CMD_WRITE\n", __func__);
 				offset = GET_PWR_CFG_OFFSET(cfg_cmd);
 
 				/*Read the value from system register*/
@@ -1797,7 +1798,7 @@
 				rtl_write_byte(rtlpriv, offset, value);
 				break;
 			case PWR_CMD_POLLING:
-				RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+				rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE,
 					"rtl_hal_pwrseqcmdparsing(): PWR_CMD_POLLING\n");
 				polling_bit = false;
 				offset = GET_PWR_CFG_OFFSET(cfg_cmd);
@@ -1818,8 +1819,8 @@
 				} while (!polling_bit);
 				break;
 			case PWR_CMD_DELAY:
-				RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-					 "rtl_hal_pwrseqcmdparsing(): PWR_CMD_DELAY\n");
+				rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE,
+					"%s: PWR_CMD_DELAY\n", __func__);
 				if (GET_PWR_CFG_VALUE(cfg_cmd) ==
 				    PWRSEQ_DELAY_US)
 					udelay(GET_PWR_CFG_OFFSET(cfg_cmd));
@@ -1827,8 +1828,8 @@
 					mdelay(GET_PWR_CFG_OFFSET(cfg_cmd));
 				break;
 			case PWR_CMD_END:
-				RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-					 "rtl_hal_pwrseqcmdparsing(): PWR_CMD_END\n");
+				rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE,
+					"%s: PWR_CMD_END\n", __func__);
 				return true;
 			default:
 				WARN_ONCE(true,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/debug.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/debug.c
@@ -298,8 +298,8 @@
 
 	tmp_len = (count > sizeof(tmp) - 1 ? sizeof(tmp) - 1 : count);
 
-	if (!buffer || copy_from_user(tmp, buffer, tmp_len))
-		return count;
+	if (copy_from_user(tmp, buffer, tmp_len))
+		return -EFAULT;
 
 	tmp[tmp_len] = '\0';
 
@@ -307,7 +307,7 @@
 	num = sscanf(tmp, "%x %x %x", &addr, &val, &len);
 
 	if (num !=  3)
-		return count;
+		return -EINVAL;
 
 	switch (len) {
 	case 1:
@@ -349,8 +349,8 @@
 
 	tmp_len = (count > sizeof(tmp) - 1 ? sizeof(tmp) - 1 : count);
 
-	if (!buffer || copy_from_user(tmp, buffer, tmp_len))
-		return count;
+	if (copy_from_user(tmp, buffer, tmp_len))
+		return -EFAULT;
 
 	tmp[tmp_len] = '\0';
 
@@ -360,8 +360,8 @@
 			 &h2c_data[4], &h2c_data[5],
 			 &h2c_data[6], &h2c_data[7]);
 
-	if (h2c_len <= 0)
-		return count;
+	if (h2c_len == 0)
+		return -EINVAL;
 
 	for (i = 0; i < h2c_len; i++)
 		h2c_data_packed[i] = (u8)h2c_data[i];
@@ -395,8 +395,8 @@
 
 	tmp_len = (count > sizeof(tmp) - 1 ? sizeof(tmp) - 1 : count);
 
-	if (!buffer || copy_from_user(tmp, buffer, tmp_len))
-		return count;
+	if (copy_from_user(tmp, buffer, tmp_len))
+		return -EFAULT;
 
 	tmp[tmp_len] = '\0';
 
@@ -404,9 +404,9 @@
 		     &path, &addr, &bitmask, &data);
 
 	if (num != 4) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG,
-			 "Format is <path> <addr> <mask> <data>\n");
-		return count;
+		rtl_dbg(rtlpriv, COMP_ERR, DBG_DMESG,
+			"Format is <path> <addr> <mask> <data>\n");
+		return -EINVAL;
 	}
 
 	rtl_set_rfreg(hw, path, addr, bitmask, data);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/debug.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/debug.h
@@ -160,6 +160,10 @@
 			 const char *titlestring,
 			 const void *hexdata, int hexdatalen);
 
+#define rtl_dbg(rtlpriv, comp, level, fmt, ...)			\
+	_rtl_dbg_trace(rtlpriv, comp, level,				\
+		       fmt, ##__VA_ARGS__)
+
 #define RT_TRACE(rtlpriv, comp, level, fmt, ...)			\
 	_rtl_dbg_trace(rtlpriv, comp, level,				\
 		       fmt, ##__VA_ARGS__)
@@ -177,6 +181,13 @@
 struct rtl_priv;
 
 __printf(4, 5)
+static inline void rtl_dbg(struct rtl_priv *rtlpriv,
+			   u64 comp, int level,
+			   const char *fmt, ...)
+{
+}
+
+__printf(4, 5)
 static inline void RT_TRACE(struct rtl_priv *rtlpriv,
 			    u64 comp, int level,
 			    const char *fmt, ...)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/efuse.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/efuse.c
@@ -120,8 +120,8 @@
 	const u32 efuse_len =
 		rtlpriv->cfg->maps[EFUSE_REAL_CONTENT_SIZE];
 
-	RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, "Addr=%x Data =%x\n",
-		 address, value);
+	rtl_dbg(rtlpriv, COMP_EFUSE, DBG_LOUD, "Addr=%x Data =%x\n",
+		address, value);
 
 	if (address < efuse_len) {
 		rtl_write_byte(rtlpriv, rtlpriv->cfg->maps[EFUSE_CTRL], value);
@@ -211,9 +211,9 @@
 	u8 efuse_usage;
 
 	if ((_offset + _size_byte) > rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]) {
-		RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD,
-			 "read_efuse(): Invalid offset(%#x) with read bytes(%#x)!!\n",
-			 _offset, _size_byte);
+		rtl_dbg(rtlpriv, COMP_EFUSE, DBG_LOUD,
+			"%s: Invalid offset(%#x) with read bytes(%#x)!!\n",
+			__func__, _offset, _size_byte);
 		return;
 	}
 
@@ -376,9 +376,9 @@
 	    (EFUSE_MAX_SIZE - rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN]))
 		result = false;
 
-	RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD,
-		 "efuse_shadow_update_chk(): totalbytes(%#x), hdr_num(%#x), words_need(%#x), efuse_used(%d)\n",
-		 totalbytes, hdr_num, words_need, efuse_used);
+	rtl_dbg(rtlpriv, COMP_EFUSE, DBG_LOUD,
+		"%s: totalbytes(%#x), hdr_num(%#x), words_need(%#x), efuse_used(%d)\n",
+		__func__, totalbytes, hdr_num, words_need, efuse_used);
 
 	return result;
 }
@@ -416,7 +416,7 @@
 	u8 word_en = 0x0F;
 	u8 first_pg = false;
 
-	RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, "\n");
+	rtl_dbg(rtlpriv, COMP_EFUSE, DBG_LOUD, "\n");
 
 	if (!efuse_shadow_update_chk(hw)) {
 		efuse_read_all_map(hw, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0]);
@@ -424,8 +424,8 @@
 		       &rtlefuse->efuse_map[EFUSE_INIT_MAP][0],
 		       rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]);
 
-		RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD,
-			 "efuse out of capacity!!\n");
+		rtl_dbg(rtlpriv, COMP_EFUSE, DBG_LOUD,
+			"efuse out of capacity!!\n");
 		return false;
 	}
 	efuse_power_switch(hw, true, true);
@@ -464,8 +464,8 @@
 
 			if (!efuse_pg_packet_write(hw, (u8) offset, word_en,
 						   tmpdata)) {
-				RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
-					 "PG section(%#x) fail!!\n", offset);
+				rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
+					"PG section(%#x) fail!!\n", offset);
 				break;
 			}
 		}
@@ -478,7 +478,7 @@
 	       &rtlefuse->efuse_map[EFUSE_INIT_MAP][0],
 	       rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]);
 
-	RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, "\n");
+	rtl_dbg(rtlpriv, COMP_EFUSE, DBG_LOUD, "\n");
 	return true;
 }
 
@@ -616,8 +616,8 @@
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	u8 tmpidx = 0;
 
-	RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD,
-		 "Addr = %x Data=%x\n", addr, data);
+	rtl_dbg(rtlpriv, COMP_EFUSE, DBG_LOUD,
+		"Addr = %x Data=%x\n", addr, data);
 
 	rtl_write_byte(rtlpriv,
 		       rtlpriv->cfg->maps[EFUSE_CTRL] + 1, (u8) (addr & 0xff));
@@ -997,8 +997,8 @@
 
 	if (efuse_addr >= (EFUSE_MAX_SIZE -
 		rtlpriv->cfg->maps[EFUSE_OOB_PROTECT_BYTES_LEN])) {
-		RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD,
-			 "efuse_addr(%#x) Out of size!!\n", efuse_addr);
+		rtl_dbg(rtlpriv, COMP_EFUSE, DBG_LOUD,
+			"efuse_addr(%#x) Out of size!!\n", efuse_addr);
 	}
 
 	return true;
@@ -1038,8 +1038,8 @@
 	u8 tmpdata[8];
 
 	memset(tmpdata, 0xff, PGPKT_DATA_SIZE);
-	RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD,
-		 "word_en = %x efuse_addr=%x\n", word_en, efuse_addr);
+	rtl_dbg(rtlpriv, COMP_EFUSE, DBG_LOUD,
+		"word_en = %x efuse_addr=%x\n", word_en, efuse_addr);
 
 	if (!(word_en & BIT(0))) {
 		tmpaddr = start_addr;
@@ -1242,11 +1242,11 @@
 
 	eeprom_id = *((u16 *)&hwinfo[0]);
 	if (eeprom_id != params[0]) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
-			 "EEPROM ID(%#x) is invalid!!\n", eeprom_id);
+		rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
+			"EEPROM ID(%#x) is invalid!!\n", eeprom_id);
 		rtlefuse->autoload_failflag = true;
 	} else {
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n");
+		rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n");
 		rtlefuse->autoload_failflag = false;
 	}
 
@@ -1257,30 +1257,30 @@
 	rtlefuse->eeprom_did = *(u16 *)&hwinfo[params[2]];
 	rtlefuse->eeprom_svid = *(u16 *)&hwinfo[params[3]];
 	rtlefuse->eeprom_smid = *(u16 *)&hwinfo[params[4]];
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-		 "EEPROMId = 0x%4x\n", eeprom_id);
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-		 "EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid);
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-		 "EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did);
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-		 "EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid);
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-		 "EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid);
+	rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
+		"EEPROMId = 0x%4x\n", eeprom_id);
+	rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
+		"EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid);
+	rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
+		"EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did);
+	rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
+		"EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid);
+	rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
+		"EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid);
 
 	for (i = 0; i < 6; i += 2) {
 		usvalue = *(u16 *)&hwinfo[params[5] + i];
 		*((u16 *)(&rtlefuse->dev_addr[i])) = usvalue;
 	}
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%pM\n", rtlefuse->dev_addr);
+	rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, "%pM\n", rtlefuse->dev_addr);
 
 	rtlefuse->eeprom_channelplan = *&hwinfo[params[6]];
 	rtlefuse->eeprom_version = *(u16 *)&hwinfo[params[7]];
 	rtlefuse->txpwr_fromeprom = true;
 	rtlefuse->eeprom_oemid = *&hwinfo[params[8]];
 
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-		 "EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid);
+	rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
+		"EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid);
 
 	/* set channel plan to world wide 13 */
 	rtlefuse->channel_plan = params[9];
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/pci.c
@@ -164,21 +164,29 @@
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 
+	value &= PCI_EXP_LNKCTL_ASPMC;
+
 	if (rtlhal->hw_type != HARDWARE_TYPE_RTL8192SE)
-		value |= 0x40;
+		value |= PCI_EXP_LNKCTL_CCC;
 
-	pci_write_config_byte(rtlpci->pdev, 0x80, value);
+	pcie_capability_clear_and_set_word(rtlpci->pdev, PCI_EXP_LNKCTL,
+					   PCI_EXP_LNKCTL_ASPMC | value,
+					   value);
 
 	return false;
 }
 
-/*When we set 0x01 to enable clk request. Set 0x0 to disable clk req.*/
-static void _rtl_pci_switch_clk_req(struct ieee80211_hw *hw, u8 value)
+/* @value is PCI_EXP_LNKCTL_CLKREQ_EN or 0 to enable/disable clk request. */
+static void _rtl_pci_switch_clk_req(struct ieee80211_hw *hw, u16 value)
 {
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 
-	pci_write_config_byte(rtlpci->pdev, 0x81, value);
+	value &= PCI_EXP_LNKCTL_CLKREQ_EN;
+
+	pcie_capability_clear_and_set_word(rtlpci->pdev, PCI_EXP_LNKCTL,
+					   PCI_EXP_LNKCTL_CLKREQ_EN,
+					   value);
 
 	if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE)
 		udelay(100);
@@ -192,11 +200,8 @@
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 	u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor;
-	u8 num4bytes = pcipriv->ndis_adapter.num4bytes;
 	/*Retrieve original configuration settings. */
 	u8 linkctrl_reg = pcipriv->ndis_adapter.linkctrl_reg;
-	u16 pcibridge_linkctrlreg = pcipriv->ndis_adapter.
-				pcibridge_linkctrlreg;
 	u16 aspmlevel = 0;
 	u8 tmp_u1b = 0;
 
@@ -204,8 +209,8 @@
 		return;
 
 	if (pcibridge_vendor == PCI_BRIDGE_VENDOR_UNKNOWN) {
-		RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
-			 "PCI(Bridge) UNKNOWN\n");
+		rtl_dbg(rtlpriv, COMP_POWER, DBG_TRACE,
+			"PCI(Bridge) UNKNOWN\n");
 
 		return;
 	}
@@ -221,16 +226,8 @@
 	/*Set corresponding value. */
 	aspmlevel |= BIT(0) | BIT(1);
 	linkctrl_reg &= ~aspmlevel;
-	pcibridge_linkctrlreg &= ~(BIT(0) | BIT(1));
 
 	_rtl_pci_platform_switch_device_pci_aspm(hw, linkctrl_reg);
-	udelay(50);
-
-	/*4 Disable Pci Bridge ASPM */
-	pci_write_config_byte(rtlpci->pdev, (num4bytes << 2),
-			      pcibridge_linkctrlreg);
-
-	udelay(50);
 }
 
 /*Enable RTL8192SE ASPM & Enable Pci Bridge ASPM for
@@ -245,39 +242,18 @@
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 	u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor;
-	u8 num4bytes = pcipriv->ndis_adapter.num4bytes;
 	u16 aspmlevel;
-	u8 u_pcibridge_aspmsetting;
 	u8 u_device_aspmsetting;
 
 	if (!ppsc->support_aspm)
 		return;
 
 	if (pcibridge_vendor == PCI_BRIDGE_VENDOR_UNKNOWN) {
-		RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
-			 "PCI(Bridge) UNKNOWN\n");
+		rtl_dbg(rtlpriv, COMP_POWER, DBG_TRACE,
+			"PCI(Bridge) UNKNOWN\n");
 		return;
 	}
 
-	/*4 Enable Pci Bridge ASPM */
-
-	u_pcibridge_aspmsetting =
-	    pcipriv->ndis_adapter.pcibridge_linkctrlreg |
-	    rtlpci->const_hostpci_aspm_setting;
-
-	if (pcibridge_vendor == PCI_BRIDGE_VENDOR_INTEL)
-		u_pcibridge_aspmsetting &= ~BIT(0);
-
-	pci_write_config_byte(rtlpci->pdev, (num4bytes << 2),
-			      u_pcibridge_aspmsetting);
-
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-		 "PlatformEnableASPM(): Write reg[%x] = %x\n",
-		 (pcipriv->ndis_adapter.pcibridge_pciehdr_offset + 0x10),
-		 u_pcibridge_aspmsetting);
-
-	udelay(50);
-
 	/*Get ASPM level (with/without Clock Req) */
 	aspmlevel = rtlpci->const_devicepci_aspm_setting;
 	u_device_aspmsetting = pcipriv->ndis_adapter.linkctrl_reg;
@@ -291,7 +267,8 @@
 
 	if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_CLK_REQ) {
 		_rtl_pci_switch_clk_req(hw, (ppsc->reg_rfps_level &
-					     RT_RF_OFF_LEVL_CLK_REQ) ? 1 : 0);
+					     RT_RF_OFF_LEVL_CLK_REQ) ?
+					     PCI_EXP_LNKCTL_CLKREQ_EN : 0);
 		RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_CLK_REQ);
 	}
 	udelay(100);
@@ -318,63 +295,6 @@
 	return status;
 }
 
-static bool rtl_pci_check_buddy_priv(struct ieee80211_hw *hw,
-				     struct rtl_priv **buddy_priv)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
-	bool find_buddy_priv = false;
-	struct rtl_priv *tpriv;
-	struct rtl_pci_priv *tpcipriv = NULL;
-
-	if (!list_empty(&rtlpriv->glb_var->glb_priv_list)) {
-		list_for_each_entry(tpriv, &rtlpriv->glb_var->glb_priv_list,
-				    list) {
-			tpcipriv = (struct rtl_pci_priv *)tpriv->priv;
-			RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-				 "pcipriv->ndis_adapter.funcnumber %x\n",
-				pcipriv->ndis_adapter.funcnumber);
-			RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-				 "tpcipriv->ndis_adapter.funcnumber %x\n",
-				tpcipriv->ndis_adapter.funcnumber);
-
-			if (pcipriv->ndis_adapter.busnumber ==
-			    tpcipriv->ndis_adapter.busnumber &&
-			    pcipriv->ndis_adapter.devnumber ==
-			    tpcipriv->ndis_adapter.devnumber &&
-			    pcipriv->ndis_adapter.funcnumber !=
-			    tpcipriv->ndis_adapter.funcnumber) {
-				find_buddy_priv = true;
-				break;
-			}
-		}
-	}
-
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-		 "find_buddy_priv %d\n", find_buddy_priv);
-
-	if (find_buddy_priv)
-		*buddy_priv = tpriv;
-
-	return find_buddy_priv;
-}
-
-static void rtl_pci_get_linkcontrol_field(struct ieee80211_hw *hw)
-{
-	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
-	struct rtl_pci *rtlpci = rtl_pcidev(pcipriv);
-	u8 capabilityoffset = pcipriv->ndis_adapter.pcibridge_pciehdr_offset;
-	u8 linkctrl_reg;
-	u8 num4bbytes;
-
-	num4bbytes = (capabilityoffset + 0x10) / 4;
-
-	/*Read  Link Control Register */
-	pci_read_config_byte(rtlpci->pdev, (num4bbytes << 2), &linkctrl_reg);
-
-	pcipriv->ndis_adapter.pcibridge_linkctrlreg = linkctrl_reg;
-}
-
 static void rtl_pci_parse_configuration(struct pci_dev *pdev,
 					struct ieee80211_hw *hw)
 {
@@ -388,8 +308,8 @@
 	pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &linkctrl_reg);
 	pcipriv->ndis_adapter.linkctrl_reg = (u8)linkctrl_reg;
 
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Link Control Register =%x\n",
-		 pcipriv->ndis_adapter.linkctrl_reg);
+	rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE, "Link Control Register =%x\n",
+		pcipriv->ndis_adapter.linkctrl_reg);
 
 	pci_read_config_byte(pdev, 0x98, &tmp);
 	tmp |= BIT(4);
@@ -483,11 +403,6 @@
 	if (!rtlpriv->rtlhal.earlymode_enable)
 		return;
 
-	if (rtlpriv->dm.supp_phymode_switch &&
-	    (rtlpriv->easy_concurrent_ctl.switch_in_process ||
-	    (rtlpriv->buddy_priv &&
-	    rtlpriv->buddy_priv->easy_concurrent_ctl.switch_in_process)))
-		return;
 	/* we just use em for BE/BK/VI/VO */
 	for (tid = 7; tid >= 0; tid--) {
 		u8 hw_queue = ac_to_hwq[rtl_tid_to_ac(tid)];
@@ -557,11 +472,11 @@
 		if (rtlpriv->rtlhal.earlymode_enable)
 			skb_pull(skb, EM_HDR_LEN);
 
-		RT_TRACE(rtlpriv, (COMP_INTR | COMP_SEND), DBG_TRACE,
-			 "new ring->idx:%d, free: skb_queue_len:%d, free: seq:%x\n",
-			 ring->idx,
-			 skb_queue_len(&ring->queue),
-			 *(u16 *)(skb->data + 22));
+		rtl_dbg(rtlpriv, (COMP_INTR | COMP_SEND), DBG_TRACE,
+			"new ring->idx:%d, free: skb_queue_len:%d, free: seq:%x\n",
+			ring->idx,
+			skb_queue_len(&ring->queue),
+			*(u16 *)(skb->data + 22));
 
 		if (prio == TXCMD_QUEUE) {
 			dev_kfree_skb(skb);
@@ -608,10 +523,10 @@
 		}
 
 		if ((ring->entries - skb_queue_len(&ring->queue)) <= 4) {
-			RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG,
-				 "more desc left, wake skb_queue@%d, ring->idx = %d, skb_queue_len = 0x%x\n",
-				 prio, ring->idx,
-				 skb_queue_len(&ring->queue));
+			rtl_dbg(rtlpriv, COMP_ERR, DBG_DMESG,
+				"more desc left, wake skb_queue@%d, ring->idx = %d, skb_queue_len = 0x%x\n",
+				prio, ring->idx,
+				skb_queue_len(&ring->queue));
 
 			ieee80211_wake_queue(hw, skb_get_queue_mapping(skb));
 		}
@@ -801,9 +716,9 @@
 				skb_reserve(skb, stats.rx_drvinfo_size +
 					    stats.rx_bufshift);
 		} else {
-			RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
-				 "skb->end - skb->tail = %d, len is %d\n",
-				 skb->end - skb->tail, len);
+			rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
+				"skb->end - skb->tail = %d, len is %d\n",
+				skb->end - skb->tail, len);
 			dev_kfree_skb_any(skb);
 			goto new_trx_end;
 		}
@@ -925,67 +840,67 @@
 
 	/*<1> beacon related */
 	if (intvec.inta & rtlpriv->cfg->maps[RTL_IMR_TBDOK])
-		RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE,
-			 "beacon ok interrupt!\n");
+		rtl_dbg(rtlpriv, COMP_INTR, DBG_TRACE,
+			"beacon ok interrupt!\n");
 
 	if (unlikely(intvec.inta & rtlpriv->cfg->maps[RTL_IMR_TBDER]))
-		RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE,
-			 "beacon err interrupt!\n");
+		rtl_dbg(rtlpriv, COMP_INTR, DBG_TRACE,
+			"beacon err interrupt!\n");
 
 	if (intvec.inta & rtlpriv->cfg->maps[RTL_IMR_BDOK])
-		RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, "beacon interrupt!\n");
+		rtl_dbg(rtlpriv, COMP_INTR, DBG_TRACE, "beacon interrupt!\n");
 
 	if (intvec.inta & rtlpriv->cfg->maps[RTL_IMR_BCNINT]) {
-		RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE,
-			 "prepare beacon for interrupt!\n");
+		rtl_dbg(rtlpriv, COMP_INTR, DBG_TRACE,
+			"prepare beacon for interrupt!\n");
 		tasklet_schedule(&rtlpriv->works.irq_prepare_bcn_tasklet);
 	}
 
 	/*<2> Tx related */
 	if (unlikely(intvec.intb & rtlpriv->cfg->maps[RTL_IMR_TXFOVW]))
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, "IMR_TXFOVW!\n");
+		rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING, "IMR_TXFOVW!\n");
 
 	if (intvec.inta & rtlpriv->cfg->maps[RTL_IMR_MGNTDOK]) {
-		RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE,
-			 "Manage ok interrupt!\n");
+		rtl_dbg(rtlpriv, COMP_INTR, DBG_TRACE,
+			"Manage ok interrupt!\n");
 		_rtl_pci_tx_isr(hw, MGNT_QUEUE);
 	}
 
 	if (intvec.inta & rtlpriv->cfg->maps[RTL_IMR_HIGHDOK]) {
-		RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE,
-			 "HIGH_QUEUE ok interrupt!\n");
+		rtl_dbg(rtlpriv, COMP_INTR, DBG_TRACE,
+			"HIGH_QUEUE ok interrupt!\n");
 		_rtl_pci_tx_isr(hw, HIGH_QUEUE);
 	}
 
 	if (intvec.inta & rtlpriv->cfg->maps[RTL_IMR_BKDOK]) {
 		rtlpriv->link_info.num_tx_inperiod++;
 
-		RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE,
-			 "BK Tx OK interrupt!\n");
+		rtl_dbg(rtlpriv, COMP_INTR, DBG_TRACE,
+			"BK Tx OK interrupt!\n");
 		_rtl_pci_tx_isr(hw, BK_QUEUE);
 	}
 
 	if (intvec.inta & rtlpriv->cfg->maps[RTL_IMR_BEDOK]) {
 		rtlpriv->link_info.num_tx_inperiod++;
 
-		RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE,
-			 "BE TX OK interrupt!\n");
+		rtl_dbg(rtlpriv, COMP_INTR, DBG_TRACE,
+			"BE TX OK interrupt!\n");
 		_rtl_pci_tx_isr(hw, BE_QUEUE);
 	}
 
 	if (intvec.inta & rtlpriv->cfg->maps[RTL_IMR_VIDOK]) {
 		rtlpriv->link_info.num_tx_inperiod++;
 
-		RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE,
-			 "VI TX OK interrupt!\n");
+		rtl_dbg(rtlpriv, COMP_INTR, DBG_TRACE,
+			"VI TX OK interrupt!\n");
 		_rtl_pci_tx_isr(hw, VI_QUEUE);
 	}
 
 	if (intvec.inta & rtlpriv->cfg->maps[RTL_IMR_VODOK]) {
 		rtlpriv->link_info.num_tx_inperiod++;
 
-		RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE,
-			 "Vo TX OK interrupt!\n");
+		rtl_dbg(rtlpriv, COMP_INTR, DBG_TRACE,
+			"Vo TX OK interrupt!\n");
 		_rtl_pci_tx_isr(hw, VO_QUEUE);
 	}
 
@@ -993,8 +908,8 @@
 		if (intvec.intd & rtlpriv->cfg->maps[RTL_IMR_H2CDOK]) {
 			rtlpriv->link_info.num_tx_inperiod++;
 
-			RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE,
-				 "H2C TX OK interrupt!\n");
+			rtl_dbg(rtlpriv, COMP_INTR, DBG_TRACE,
+				"H2C TX OK interrupt!\n");
 			_rtl_pci_tx_isr(hw, H2C_QUEUE);
 		}
 	}
@@ -1003,34 +918,34 @@
 		if (intvec.inta & rtlpriv->cfg->maps[RTL_IMR_COMDOK]) {
 			rtlpriv->link_info.num_tx_inperiod++;
 
-			RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE,
-				 "CMD TX OK interrupt!\n");
+			rtl_dbg(rtlpriv, COMP_INTR, DBG_TRACE,
+				"CMD TX OK interrupt!\n");
 			_rtl_pci_tx_isr(hw, TXCMD_QUEUE);
 		}
 	}
 
 	/*<3> Rx related */
 	if (intvec.inta & rtlpriv->cfg->maps[RTL_IMR_ROK]) {
-		RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE, "Rx ok interrupt!\n");
+		rtl_dbg(rtlpriv, COMP_INTR, DBG_TRACE, "Rx ok interrupt!\n");
 		_rtl_pci_rx_interrupt(hw);
 	}
 
 	if (unlikely(intvec.inta & rtlpriv->cfg->maps[RTL_IMR_RDU])) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
-			 "rx descriptor unavailable!\n");
+		rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
+			"rx descriptor unavailable!\n");
 		_rtl_pci_rx_interrupt(hw);
 	}
 
 	if (unlikely(intvec.intb & rtlpriv->cfg->maps[RTL_IMR_RXFOVW])) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, "rx overflow !\n");
+		rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING, "rx overflow !\n");
 		_rtl_pci_rx_interrupt(hw);
 	}
 
 	/*<4> fw related*/
 	if (rtlhal->hw_type == HARDWARE_TYPE_RTL8723AE) {
 		if (intvec.inta & rtlpriv->cfg->maps[RTL_IMR_C2HCMD]) {
-			RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE,
-				 "firmware interrupt!\n");
+			rtl_dbg(rtlpriv, COMP_INTR, DBG_TRACE,
+				"firmware interrupt!\n");
 			queue_delayed_work(rtlpriv->works.rtl_wq,
 					   &rtlpriv->works.fwevt_wq, 0);
 		}
@@ -1046,8 +961,8 @@
 	    rtlhal->hw_type == HARDWARE_TYPE_RTL8723BE) {
 		if (unlikely(intvec.inta &
 		    rtlpriv->cfg->maps[RTL_IMR_HSISR_IND])) {
-			RT_TRACE(rtlpriv, COMP_INTR, DBG_TRACE,
-				 "hsisr interrupt!\n");
+			rtl_dbg(rtlpriv, COMP_INTR, DBG_TRACE,
+				"hsisr interrupt!\n");
 			_rtl_pci_hs_interrupt(hw);
 		}
 	}
@@ -1061,13 +976,15 @@
 	return ret;
 }
 
-static void _rtl_pci_irq_tasklet(struct ieee80211_hw *hw)
+static void _rtl_pci_irq_tasklet(unsigned long data)
 {
+	struct ieee80211_hw *hw = (struct ieee80211_hw *)data;
 	_rtl_pci_tx_chk_waitq(hw);
 }
 
-static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw)
+static void _rtl_pci_prepare_bcn_tasklet(unsigned long data)
 {
+	struct ieee80211_hw *hw = (struct ieee80211_hw *)data;
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
@@ -1193,10 +1110,10 @@
 
 	/*task */
 	tasklet_init(&rtlpriv->works.irq_tasklet,
-		     (void (*)(unsigned long))_rtl_pci_irq_tasklet,
+		     _rtl_pci_irq_tasklet,
 		     (unsigned long)hw);
 	tasklet_init(&rtlpriv->works.irq_prepare_bcn_tasklet,
-		     (void (*)(unsigned long))_rtl_pci_prepare_bcn_tasklet,
+		     _rtl_pci_prepare_bcn_tasklet,
 		     (unsigned long)hw);
 	INIT_WORK(&rtlpriv->works.lps_change_work,
 		  rtl_lps_change_work_callback);
@@ -1249,8 +1166,8 @@
 	rtlpci->tx_ring[prio].entries = entries;
 	skb_queue_head_init(&rtlpci->tx_ring[prio].queue);
 
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "queue:%d, ring_addr:%p\n",
-		 prio, desc);
+	rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, "queue:%d, ring_addr:%p\n",
+		prio, desc);
 
 	/* init every desc in this ring */
 	if (!rtlpriv->use_new_trx_flow) {
@@ -1647,10 +1564,10 @@
 				true, HW_DESC_OWN);
 
 		if (own == 1 && hw_queue != BEACON_QUEUE) {
-			RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
-				 "No more TX desc@%d, ring->idx = %d, idx = %d, skb_queue_len = 0x%x\n",
-				 hw_queue, ring->idx, idx,
-				 skb_queue_len(&ring->queue));
+			rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
+				"No more TX desc@%d, ring->idx = %d, idx = %d, skb_queue_len = 0x%x\n",
+				hw_queue, ring->idx, idx,
+				skb_queue_len(&ring->queue));
 
 			spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock,
 					       flags);
@@ -1660,8 +1577,8 @@
 
 	if (rtlpriv->cfg->ops->get_available_desc &&
 	    rtlpriv->cfg->ops->get_available_desc(hw, hw_queue) == 0) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
-			 "get_available_desc fail\n");
+		rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
+			"get_available_desc fail\n");
 		spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
 		return skb->len;
 	}
@@ -1684,8 +1601,8 @@
 
 	if ((ring->entries - skb_queue_len(&ring->queue)) < 2 &&
 	    hw_queue != BEACON_QUEUE) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
-			 "less desc left, stop skb_queue@%d, ring->idx = %d, idx = %d, skb_queue_len = 0x%x\n",
+		rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
+			"less desc left, stop skb_queue@%d, ring->idx = %d, idx = %d, skb_queue_len = 0x%x\n",
 			 hw_queue, ring->idx, idx,
 			 skb_queue_len(&ring->queue));
 
@@ -1792,8 +1709,8 @@
 
 	err = rtlpriv->cfg->ops->hw_init(hw);
 	if (err) {
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
-			 "Failed to config hardware!\n");
+		rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG,
+			"Failed to config hardware!\n");
 		kfree(rtlpriv->btcoexist.btc_context);
 		kfree(rtlpriv->btcoexist.wifi_only_context);
 		return err;
@@ -1802,7 +1719,7 @@
 			&rtlmac->retry_long);
 
 	rtlpriv->cfg->ops->enable_interrupt(hw);
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "enable_interrupt OK\n");
+	rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, "enable_interrupt OK\n");
 
 	rtl_init_rx_config(hw);
 
@@ -1813,7 +1730,7 @@
 
 	rtlpci->up_first_time = false;
 
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%s OK\n", __func__);
+	rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, "%s OK\n", __func__);
 	return 0;
 }
 
@@ -1907,71 +1824,71 @@
 	    deviceid == RTL_PCI_8171_DID) {
 		switch (revisionid) {
 		case RTL_PCI_REVISION_ID_8192PCIE:
-			RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
-				 "8192 PCI-E is found - vid/did=%x/%x\n",
-				 venderid, deviceid);
+			rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG,
+				"8192 PCI-E is found - vid/did=%x/%x\n",
+				venderid, deviceid);
 			rtlhal->hw_type = HARDWARE_TYPE_RTL8192E;
 			return false;
 		case RTL_PCI_REVISION_ID_8192SE:
-			RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
-				 "8192SE is found - vid/did=%x/%x\n",
-				 venderid, deviceid);
+			rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG,
+				"8192SE is found - vid/did=%x/%x\n",
+				venderid, deviceid);
 			rtlhal->hw_type = HARDWARE_TYPE_RTL8192SE;
 			break;
 		default:
-			RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
-				 "Err: Unknown device - vid/did=%x/%x\n",
-				 venderid, deviceid);
+			rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
+				"Err: Unknown device - vid/did=%x/%x\n",
+				venderid, deviceid);
 			rtlhal->hw_type = HARDWARE_TYPE_RTL8192SE;
 			break;
 		}
 	} else if (deviceid == RTL_PCI_8723AE_DID) {
 		rtlhal->hw_type = HARDWARE_TYPE_RTL8723AE;
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
-			 "8723AE PCI-E is found - vid/did=%x/%x\n",
-			 venderid, deviceid);
+		rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG,
+			"8723AE PCI-E is found - vid/did=%x/%x\n",
+			venderid, deviceid);
 	} else if (deviceid == RTL_PCI_8192CET_DID ||
 		   deviceid == RTL_PCI_8192CE_DID ||
 		   deviceid == RTL_PCI_8191CE_DID ||
 		   deviceid == RTL_PCI_8188CE_DID) {
 		rtlhal->hw_type = HARDWARE_TYPE_RTL8192CE;
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
-			 "8192C PCI-E is found - vid/did=%x/%x\n",
-			 venderid, deviceid);
+		rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG,
+			"8192C PCI-E is found - vid/did=%x/%x\n",
+			venderid, deviceid);
 	} else if (deviceid == RTL_PCI_8192DE_DID ||
 		   deviceid == RTL_PCI_8192DE_DID2) {
 		rtlhal->hw_type = HARDWARE_TYPE_RTL8192DE;
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
-			 "8192D PCI-E is found - vid/did=%x/%x\n",
-			 venderid, deviceid);
+		rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG,
+			"8192D PCI-E is found - vid/did=%x/%x\n",
+			venderid, deviceid);
 	} else if (deviceid == RTL_PCI_8188EE_DID) {
 		rtlhal->hw_type = HARDWARE_TYPE_RTL8188EE;
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-			 "Find adapter, Hardware type is 8188EE\n");
+		rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
+			"Find adapter, Hardware type is 8188EE\n");
 	} else if (deviceid == RTL_PCI_8723BE_DID) {
 		rtlhal->hw_type = HARDWARE_TYPE_RTL8723BE;
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-			 "Find adapter, Hardware type is 8723BE\n");
+		rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
+			"Find adapter, Hardware type is 8723BE\n");
 	} else if (deviceid == RTL_PCI_8192EE_DID) {
 		rtlhal->hw_type = HARDWARE_TYPE_RTL8192EE;
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-			 "Find adapter, Hardware type is 8192EE\n");
+		rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
+			"Find adapter, Hardware type is 8192EE\n");
 	} else if (deviceid == RTL_PCI_8821AE_DID) {
 		rtlhal->hw_type = HARDWARE_TYPE_RTL8821AE;
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-			 "Find adapter, Hardware type is 8821AE\n");
+		rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
+			"Find adapter, Hardware type is 8821AE\n");
 	} else if (deviceid == RTL_PCI_8812AE_DID) {
 		rtlhal->hw_type = HARDWARE_TYPE_RTL8812AE;
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-			 "Find adapter, Hardware type is 8812AE\n");
+		rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
+			"Find adapter, Hardware type is 8812AE\n");
 	} else if (deviceid == RTL_PCI_8822BE_DID) {
 		rtlhal->hw_type = HARDWARE_TYPE_RTL8822BE;
 		rtlhal->bandset = BAND_ON_BOTH;
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-			 "Find adapter, Hardware type is 8822BE\n");
+		rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
+			"Find adapter, Hardware type is 8822BE\n");
 	} else {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
-			 "Err: Unknown device - vid/did=%x/%x\n",
+		rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
+			"Err: Unknown device - vid/did=%x/%x\n",
 			 venderid, deviceid);
 
 		rtlhal->hw_type = RTL_DEFAULT_HARDWARE_TYPE;
@@ -1980,17 +1897,17 @@
 	if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192DE) {
 		if (revisionid == 0 || revisionid == 1) {
 			if (revisionid == 0) {
-				RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-					 "Find 92DE MAC0\n");
+				rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
+					"Find 92DE MAC0\n");
 				rtlhal->interfaceindex = 0;
 			} else if (revisionid == 1) {
-				RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-					 "Find 92DE MAC1\n");
+				rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
+					"Find 92DE MAC1\n");
 				rtlhal->interfaceindex = 1;
 			}
 		} else {
-			RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-				 "Unknown device - VendorID/DeviceID=%x/%x, Revision=%x\n",
+			rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
+				"Unknown device - VendorID/DeviceID=%x/%x, Revision=%x\n",
 				 venderid, deviceid, revisionid);
 			rtlhal->interfaceindex = 0;
 		}
@@ -2024,9 +1941,9 @@
 		for (tmp = 0; tmp < PCI_BRIDGE_VENDOR_MAX; tmp++) {
 			if (bridge_pdev->vendor == pcibridge_vendors[tmp]) {
 				pcipriv->ndis_adapter.pcibridge_vendor = tmp;
-				RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
-					 "Pci Bridge Vendor is found index: %d\n",
-					 tmp);
+				rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG,
+					"Pci Bridge Vendor is found index: %d\n",
+					tmp);
 				break;
 			}
 		}
@@ -2040,12 +1957,6 @@
 		    PCI_SLOT(bridge_pdev->devfn);
 		pcipriv->ndis_adapter.pcibridge_funcnum =
 		    PCI_FUNC(bridge_pdev->devfn);
-		pcipriv->ndis_adapter.pcibridge_pciehdr_offset =
-		    pci_pcie_cap(bridge_pdev);
-		pcipriv->ndis_adapter.num4bytes =
-		    (pcipriv->ndis_adapter.pcibridge_pciehdr_offset + 0x10) / 4;
-
-		rtl_pci_get_linkcontrol_field(hw);
 
 		if (pcipriv->ndis_adapter.pcibridge_vendor ==
 		    PCI_BRIDGE_VENDOR_AMD) {
@@ -2054,25 +1965,22 @@
 		}
 	}
 
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
-		 "pcidev busnumber:devnumber:funcnumber:vendor:link_ctl %d:%d:%d:%x:%x\n",
-		 pcipriv->ndis_adapter.busnumber,
-		 pcipriv->ndis_adapter.devnumber,
-		 pcipriv->ndis_adapter.funcnumber,
-		 pdev->vendor, pcipriv->ndis_adapter.linkctrl_reg);
-
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
-		 "pci_bridge busnumber:devnumber:funcnumber:vendor:pcie_cap:link_ctl_reg:amd %d:%d:%d:%x:%x:%x:%x\n",
-		 pcipriv->ndis_adapter.pcibridge_busnum,
-		 pcipriv->ndis_adapter.pcibridge_devnum,
-		 pcipriv->ndis_adapter.pcibridge_funcnum,
-		 pcibridge_vendors[pcipriv->ndis_adapter.pcibridge_vendor],
-		 pcipriv->ndis_adapter.pcibridge_pciehdr_offset,
-		 pcipriv->ndis_adapter.pcibridge_linkctrlreg,
-		 pcipriv->ndis_adapter.amd_l1_patch);
+	rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG,
+		"pcidev busnumber:devnumber:funcnumber:vendor:link_ctl %d:%d:%d:%x:%x\n",
+		pcipriv->ndis_adapter.busnumber,
+		pcipriv->ndis_adapter.devnumber,
+		pcipriv->ndis_adapter.funcnumber,
+		pdev->vendor, pcipriv->ndis_adapter.linkctrl_reg);
+
+	rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG,
+		"pci_bridge busnumber:devnumber:funcnumber:vendor:amd %d:%d:%d:%x:%x\n",
+		pcipriv->ndis_adapter.pcibridge_busnum,
+		pcipriv->ndis_adapter.pcibridge_devnum,
+		pcipriv->ndis_adapter.pcibridge_funcnum,
+		pcibridge_vendors[pcipriv->ndis_adapter.pcibridge_vendor],
+		pcipriv->ndis_adapter.amd_l1_patch);
 
 	rtl_pci_parse_configuration(pdev, hw);
-	list_add_tail(&rtlpriv->list, &rtlpriv->glb_var->glb_priv_list);
 
 	return true;
 }
@@ -2097,8 +2005,8 @@
 
 	rtlpci->using_msi = true;
 
-	RT_TRACE(rtlpriv, COMP_INIT | COMP_INTR, DBG_DMESG,
-		 "MSI Interrupt Mode!\n");
+	rtl_dbg(rtlpriv, COMP_INIT | COMP_INTR, DBG_DMESG,
+		"MSI Interrupt Mode!\n");
 	return 0;
 }
 
@@ -2115,8 +2023,8 @@
 		return ret;
 
 	rtlpci->using_msi = false;
-	RT_TRACE(rtlpriv, COMP_INIT | COMP_INTR, DBG_DMESG,
-		 "Pin-based Interrupt Mode!\n");
+	rtl_dbg(rtlpriv, COMP_INIT | COMP_INTR, DBG_DMESG,
+		"Pin-based Interrupt Mode!\n");
 	return 0;
 }
 
@@ -2219,7 +2127,6 @@
 	rtlpriv->rtlhal.interface = INTF_PCI;
 	rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_data);
 	rtlpriv->intf_ops = &rtl_pci_ops;
-	rtlpriv->glb_var = &rtl_global_var;
 	rtl_efuse_ops_init(hw);
 
 	/* MEM map */
@@ -2243,10 +2150,10 @@
 		goto fail2;
 	}
 
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
-		 "mem mapped space: start: 0x%08lx len:%08lx flags:%08lx, after map:0x%08lx\n",
-		 pmem_start, pmem_len, pmem_flags,
-		 rtlpriv->io.pci_mem_start);
+	rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG,
+		"mem mapped space: start: 0x%08lx len:%08lx flags:%08lx, after map:0x%08lx\n",
+		pmem_start, pmem_len, pmem_flags,
+		rtlpriv->io.pci_mem_start);
 
 	/* Disable Clk Request */
 	pci_write_config_byte(pdev, 0x81, 0);
@@ -2270,7 +2177,7 @@
 	if (rtlpriv->cfg->ops->init_sw_vars(hw)) {
 		pr_err("Can't init_sw_vars\n");
 		err = -ENODEV;
-		goto fail3;
+		goto fail2;
 	}
 	rtlpriv->cfg->ops->init_sw_leds(hw);
 
@@ -2288,14 +2195,14 @@
 	err = rtl_pci_init(hw, pdev);
 	if (err) {
 		pr_err("Failed to init PCI\n");
-		goto fail3;
+		goto fail4;
 	}
 
 	err = ieee80211_register_hw(hw);
 	if (err) {
 		pr_err("Can't register mac80211 hw.\n");
 		err = -ENODEV;
-		goto fail3;
+		goto fail5;
 	}
 	rtlpriv->mac80211.mac80211_registered = 1;
 
@@ -2308,9 +2215,9 @@
 	rtlpci = rtl_pcidev(pcipriv);
 	err = rtl_pci_intr_mode_decide(hw);
 	if (err) {
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
-			 "%s: failed to register IRQ handler\n",
-			 wiphy_name(hw->wiphy));
+		rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG,
+			"%s: failed to register IRQ handler\n",
+			wiphy_name(hw->wiphy));
 		goto fail3;
 	}
 	rtlpci->irq_alloc = 1;
@@ -2318,16 +2225,19 @@
 	set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status);
 	return 0;
 
-fail3:
-	pci_set_drvdata(pdev, NULL);
+fail5:
+	rtl_pci_deinit(hw);
+fail4:
 	rtl_deinit_core(hw);
+fail3:
+	wait_for_completion(&rtlpriv->firmware_loading_complete);
+	rtlpriv->cfg->ops->deinit_sw_vars(hw);
 
 fail2:
 	if (rtlpriv->io.pci_mem_start != 0)
 		pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start);
 
 	pci_release_regions(pdev);
-	complete(&rtlpriv->firmware_loading_complete);
 
 fail1:
 	if (hw)
@@ -2378,7 +2288,6 @@
 	if (rtlpci->using_msi)
 		pci_disable_msi(rtlpci->pdev);
 
-	list_del(&rtlpriv->list);
 	if (rtlpriv->io.pci_mem_start != 0) {
 		pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start);
 		pci_release_regions(pdev);
@@ -2438,7 +2347,6 @@
 	.read_efuse_byte = read_efuse_byte,
 	.adapter_start = rtl_pci_start,
 	.adapter_stop = rtl_pci_stop,
-	.check_buddy_priv = rtl_pci_check_buddy_priv,
 	.adapter_tx = rtl_pci_tx,
 	.flush = rtl_pci_flush,
 	.reset_trx_ring = rtl_pci_reset_trx_ring,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/pci.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/pci.h
@@ -236,11 +236,6 @@
 	u16 pcibridge_vendorid;
 	u16 pcibridge_deviceid;
 
-	u8 num4bytes;
-
-	u8 pcibridge_pciehdr_offset;
-	u8 pcibridge_linkctrlreg;
-
 	bool amd_l1_patch;
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/ps.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/ps.c
@@ -19,8 +19,8 @@
 		rtlpriv->intf_ops->reset_trx_ring(hw);
 
 	if (is_hal_stop(rtlhal))
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
-			 "Driver is already down!\n");
+		rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
+			"Driver is already down!\n");
 
 	/*<2> Enable Adapter */
 	if (rtlpriv->cfg->ops->hw_init(hw))
@@ -81,9 +81,9 @@
 		if (ppsc->rfchange_inprogress) {
 			spin_unlock(&rtlpriv->locks.rf_ps_lock);
 
-			RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
-				 "RF Change in progress! Wait to set..state_toset(%d).\n",
-				  state_toset);
+			rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
+				"RF Change in progress! Wait to set..state_toset(%d).\n",
+				state_toset);
 
 			/* Set RF after the previous action is done.  */
 			while (ppsc->rfchange_inprogress) {
@@ -195,8 +195,8 @@
 	enum rf_pwrstate rtstate;
 
 	if (mac->opmode != NL80211_IFTYPE_STATION) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
-			 "not station return\n");
+		rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
+			"not station return\n");
 		return;
 	}
 
@@ -232,8 +232,8 @@
 		    !ppsc->swrf_processing &&
 		    (mac->link_state == MAC80211_NOLINK) &&
 		    !mac->act_scanning) {
-			RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
-				 "IPSEnter(): Turn off RF\n");
+			rtl_dbg(rtlpriv, COMP_RF, DBG_TRACE,
+				"IPSEnter(): Turn off RF\n");
 
 			ppsc->inactive_pwrstate = ERFOFF;
 			ppsc->in_powersavemode = true;
@@ -311,8 +311,8 @@
 				       ppsc->last_delaylps_stamp_jiffies);
 
 	if (ps_timediff < 2000) {
-		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
-			 "Delay enter Fw LPS for DHCP, ARP, or EAPOL exchanging state\n");
+		rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
+			"Delay enter Fw LPS for DHCP, ARP, or EAPOL exchanging state\n");
 		return false;
 	}
 
@@ -357,9 +357,9 @@
 
 	if ((ppsc->fwctrl_lps) && ppsc->report_linked) {
 		if (ppsc->dot11_psmode == EACTIVE) {
-			RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
-				 "FW LPS leave ps_mode:%x\n",
-				  FW_PS_ACTIVE_MODE);
+			rtl_dbg(rtlpriv, COMP_RF, DBG_DMESG,
+				"FW LPS leave ps_mode:%x\n",
+				FW_PS_ACTIVE_MODE);
 			enter_fwlps = false;
 			ppsc->pwr_mode = FW_PS_ACTIVE_MODE;
 			ppsc->smart_ps = 0;
@@ -372,9 +372,9 @@
 				rtlpriv->btcoexist.btc_ops->btc_lps_notify(rtlpriv, rt_psmode);
 		} else {
 			if (rtl_get_fwlps_doze(hw)) {
-				RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
-					 "FW LPS enter ps_mode:%x\n",
-					 ppsc->fwctrl_psmode);
+				rtl_dbg(rtlpriv, COMP_RF, DBG_DMESG,
+					"FW LPS enter ps_mode:%x\n",
+					ppsc->fwctrl_psmode);
 				if (rtlpriv->cfg->ops->get_btc_status())
 					rtlpriv->btcoexist.btc_ops->btc_lps_notify(rtlpriv, rt_psmode);
 				enter_fwlps = true;
@@ -424,8 +424,8 @@
 	 * bt_ccoexist may ask to enter lps.
 	 * In normal case, this constraint move to rtl_lps_set_psmode().
 	 */
-	RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
-		 "Enter 802.11 power save mode...\n");
+	rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
+		"Enter 802.11 power save mode...\n");
 	rtl_lps_set_psmode(hw, EAUTOPS);
 
 	mutex_unlock(&rtlpriv->locks.lps_mutex);
@@ -453,8 +453,8 @@
 				RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM);
 			}
 
-			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
-				 "Busy Traffic,Leave 802.11 power save..\n");
+			rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
+				"Busy Traffic,Leave 802.11 power save..\n");
 
 			rtl_lps_set_psmode(hw, EACTIVE);
 		}
@@ -538,8 +538,8 @@
 		queue_delayed_work(rtlpriv->works.rtl_wq,
 				   &rtlpriv->works.ps_work, MSECS(5));
 	} else {
-		RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG,
-			 "u_bufferd: %x, m_buffered: %x\n", u_buffed, m_buffed);
+		rtl_dbg(rtlpriv, COMP_POWER, DBG_DMESG,
+			"u_bufferd: %x, m_buffered: %x\n", u_buffed, m_buffed);
 	}
 }
 EXPORT_SYMBOL_GPL(rtl_swlps_beacon);
@@ -634,9 +634,9 @@
 	/* this print should always be dtim_conter = 0 &
 	 * sleep  = dtim_period, that meaons, we should
 	 * awake before every dtim */
-	RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG,
-		 "dtim_counter:%x will sleep :%d beacon_intv\n",
-		  rtlpriv->psc.dtim_counter, sleep_intv);
+	rtl_dbg(rtlpriv, COMP_POWER, DBG_DMESG,
+		"dtim_counter:%x will sleep :%d beacon_intv\n",
+		rtlpriv->psc.dtim_counter, sleep_intv);
 
 	/* we tested that 40ms is enough for sw & hw sw delay */
 	queue_delayed_work(rtlpriv->works.rtl_wq, &rtlpriv->works.ps_rfon_wq,
@@ -748,9 +748,9 @@
 		if (ie[0] == 12) {
 			find_p2p_ps_ie = true;
 			if ((noa_len - 2) % 13 != 0) {
-				RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-					 "P2P notice of absence: invalid length.%d\n",
-					 noa_len);
+				rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
+					"P2P notice of absence: invalid length.%d\n",
+					noa_len);
 				return;
 			} else {
 				noa_num = (noa_len - 2) / 13;
@@ -761,8 +761,8 @@
 			noa_index = ie[3];
 			if (rtlpriv->psc.p2p_ps_info.p2p_ps_mode ==
 			    P2P_PS_NONE || noa_index != p2pinfo->noa_index) {
-				RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD,
-					 "update NOA ie.\n");
+				rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD,
+					"update NOA ie.\n");
 				p2pinfo->noa_index = noa_index;
 				p2pinfo->opp_ps = (ie[4] >> 7);
 				p2pinfo->ctwindow = ie[4] & 0x7F;
@@ -833,7 +833,7 @@
 	if (ie == NULL)
 		return;
 
-	RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "action frame find P2P IE.\n");
+	rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "action frame find P2P IE.\n");
 	/*to find noa ie*/
 	while (ie + 1 < end) {
 		noa_len = READEF2BYTE((__le16 *)&ie[1]);
@@ -841,13 +841,13 @@
 			return;
 
 		if (ie[0] == 12) {
-			RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "find NOA IE.\n");
+			rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "find NOA IE.\n");
 			RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_LOUD, "noa ie ",
 				      ie, noa_len);
 			if ((noa_len - 2) % 13 != 0) {
-				RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD,
-					 "P2P notice of absence: invalid length.%d\n",
-					 noa_len);
+				rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD,
+					"P2P notice of absence: invalid length.%d\n",
+					noa_len);
 				return;
 			} else {
 				noa_num = (noa_len - 2) / 13;
@@ -905,7 +905,7 @@
 	struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
 	struct rtl_p2p_ps_info  *p2pinfo = &(rtlpriv->psc.p2p_ps_info);
 
-	RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, " p2p state %x\n" , p2p_ps_state);
+	rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, " p2p state %x\n", p2p_ps_state);
 	switch (p2p_ps_state) {
 	case P2P_PS_DISABLE:
 		p2pinfo->p2p_ps_state = p2p_ps_state;
@@ -957,18 +957,18 @@
 	default:
 		break;
 	}
-	RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD,
-		 "ctwindow %x oppps %x\n",
-		 p2pinfo->ctwindow , p2pinfo->opp_ps);
-	RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD,
-		 "count %x duration %x index %x interval %x start time %x noa num %x\n",
-		 p2pinfo->noa_count_type[0],
-		 p2pinfo->noa_duration[0],
-		 p2pinfo->noa_index,
-		 p2pinfo->noa_interval[0],
-		 p2pinfo->noa_start_time[0],
-		 p2pinfo->noa_num);
-	RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "end\n");
+	rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD,
+		"ctwindow %x oppps %x\n",
+		p2pinfo->ctwindow, p2pinfo->opp_ps);
+	rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD,
+		"count %x duration %x index %x interval %x start time %x noa num %x\n",
+		p2pinfo->noa_count_type[0],
+		p2pinfo->noa_duration[0],
+		p2pinfo->noa_index,
+		p2pinfo->noa_interval[0],
+		p2pinfo->noa_start_time[0],
+		p2pinfo->noa_num);
+	rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, "end\n");
 }
 
 void rtl_p2p_info(struct ieee80211_hw *hw, void *data, unsigned int len)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/rc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/rc.c
@@ -261,7 +261,7 @@
 {
 }
 
-static void *rtl_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
+static void *rtl_rate_alloc(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	return rtlpriv;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/regd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/regd.c
@@ -386,20 +386,20 @@
 	struct wiphy *wiphy = hw->wiphy;
 	struct country_code_to_enum_rd *country = NULL;
 
-	if (wiphy == NULL || &rtlpriv->regd == NULL)
+	if (!wiphy)
 		return -EINVAL;
 
 	/* init country_code from efuse channel plan */
 	rtlpriv->regd.country_code =
 		channel_plan_to_country_code(rtlpriv->efuse.channel_plan);
 
-	RT_TRACE(rtlpriv, COMP_REGD, DBG_DMESG,
-		 "rtl: EEPROM regdomain: 0x%0x country code: %d\n",
-		 rtlpriv->efuse.channel_plan, rtlpriv->regd.country_code);
+	rtl_dbg(rtlpriv, COMP_REGD, DBG_DMESG,
+		"rtl: EEPROM regdomain: 0x%0x country code: %d\n",
+		rtlpriv->efuse.channel_plan, rtlpriv->regd.country_code);
 
 	if (rtlpriv->regd.country_code >= COUNTRY_CODE_MAX) {
-		RT_TRACE(rtlpriv, COMP_REGD, DBG_DMESG,
-			 "rtl: EEPROM indicates invalid country code, world wide 13 should be used\n");
+		rtl_dbg(rtlpriv, COMP_REGD, DBG_DMESG,
+			"rtl: EEPROM indicates invalid country code, world wide 13 should be used\n");
 
 		rtlpriv->regd.country_code = COUNTRY_CODE_WORLD_WIDE_13;
 	}
@@ -414,9 +414,9 @@
 		rtlpriv->regd.alpha2[1] = '0';
 	}
 
-	RT_TRACE(rtlpriv, COMP_REGD, DBG_TRACE,
-		 "rtl: Country alpha2 being used: %c%c\n",
-		  rtlpriv->regd.alpha2[0], rtlpriv->regd.alpha2[1]);
+	rtl_dbg(rtlpriv, COMP_REGD, DBG_TRACE,
+		"rtl: Country alpha2 being used: %c%c\n",
+		rtlpriv->regd.alpha2[0], rtlpriv->regd.alpha2[1]);
 
 	_rtl_regd_init_wiphy(&rtlpriv->regd, wiphy, reg_notifier);
 
@@ -428,7 +428,7 @@
 	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 
-	RT_TRACE(rtlpriv, COMP_REGD, DBG_LOUD, "\n");
+	rtl_dbg(rtlpriv, COMP_REGD, DBG_LOUD, "\n");
 
 	_rtl_reg_notifier_apply(wiphy, request, &rtlpriv->regd);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/dm.c
@@ -805,7 +805,7 @@
 	}
 
 	if (rtlpriv->btcoexist.bt_edca_dl != 0) {
-		edca_be_ul = rtlpriv->btcoexist.bt_edca_dl;
+		edca_be_dl = rtlpriv->btcoexist.bt_edca_dl;
 		bt_change_edca = true;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/phy.c
@@ -16,7 +16,6 @@
 static void _rtl88e_phy_rf_serial_write(struct ieee80211_hw *hw,
 					enum radio_path rfpath, u32 offset,
 					u32 data);
-static u32 _rtl88e_phy_calculate_bit_shift(u32 bitmask);
 static bool _rtl88e_phy_bb8188e_config_parafile(struct ieee80211_hw *hw);
 static bool _rtl88e_phy_config_mac_with_headerfile(struct ieee80211_hw *hw);
 static bool phy_config_bb_with_headerfile(struct ieee80211_hw *hw,
@@ -46,7 +45,7 @@
 	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
 		 "regaddr(%#x), bitmask(%#x)\n", regaddr, bitmask);
 	originalvalue = rtl_read_dword(rtlpriv, regaddr);
-	bitshift = _rtl88e_phy_calculate_bit_shift(bitmask);
+	bitshift = calculate_bit_shift(bitmask);
 	returnvalue = (originalvalue & bitmask) >> bitshift;
 
 	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
@@ -69,7 +68,7 @@
 
 	if (bitmask != MASKDWORD) {
 		originalvalue = rtl_read_dword(rtlpriv, regaddr);
-		bitshift = _rtl88e_phy_calculate_bit_shift(bitmask);
+		bitshift = calculate_bit_shift(bitmask);
 		data = ((originalvalue & (~bitmask)) | (data << bitshift));
 	}
 
@@ -95,7 +94,7 @@
 
 
 	original_value = _rtl88e_phy_rf_serial_read(hw, rfpath, regaddr);
-	bitshift = _rtl88e_phy_calculate_bit_shift(bitmask);
+	bitshift = calculate_bit_shift(bitmask);
 	readback_value = (original_value & bitmask) >> bitshift;
 
 	spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
@@ -124,7 +123,7 @@
 			original_value = _rtl88e_phy_rf_serial_read(hw,
 								    rfpath,
 								    regaddr);
-			bitshift = _rtl88e_phy_calculate_bit_shift(bitmask);
+			bitshift = calculate_bit_shift(bitmask);
 			data =
 			    ((original_value & (~bitmask)) |
 			     (data << bitshift));
@@ -210,17 +209,6 @@
 		 rfpath, pphyreg->rf3wire_offset, data_and_addr);
 }
 
-static u32 _rtl88e_phy_calculate_bit_shift(u32 bitmask)
-{
-	u32 i;
-
-	for (i = 0; i <= 31; i++) {
-		if (((bitmask >> i) & 0x1) == 1)
-			break;
-	}
-	return i;
-}
-
 bool rtl88e_phy_mac_config(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.h
@@ -561,6 +561,7 @@
 	 rxmcs == DESC92C_RATE11M)
 
 struct phy_status_rpt {
+	u8	padding[2];
 	u8	ch_corr[2];
 	u8	cck_sig_qual_ofdm_pwdb_all;
 	u8	cck_agc_rpt_ofdm_cfosho_a;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/rtl8192c/dm_common.c
@@ -640,7 +640,7 @@
 	}
 
 	if (rtlpriv->btcoexist.bt_edca_dl != 0) {
-		edca_be_ul = rtlpriv->btcoexist.bt_edca_dl;
+		edca_be_dl = rtlpriv->btcoexist.bt_edca_dl;
 		bt_change_edca = true;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.c
@@ -17,7 +17,7 @@
 	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "regaddr(%#x), bitmask(%#x)\n",
 		 regaddr, bitmask);
 	originalvalue = rtl_read_dword(rtlpriv, regaddr);
-	bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
+	bitshift = calculate_bit_shift(bitmask);
 	returnvalue = (originalvalue & bitmask) >> bitshift;
 
 	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
@@ -40,7 +40,7 @@
 
 	if (bitmask != MASKDWORD) {
 		originalvalue = rtl_read_dword(rtlpriv, regaddr);
-		bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
+		bitshift = calculate_bit_shift(bitmask);
 		data = ((originalvalue & (~bitmask)) | (data << bitshift));
 	}
 
@@ -143,18 +143,6 @@
 }
 EXPORT_SYMBOL(_rtl92c_phy_rf_serial_write);
 
-u32 _rtl92c_phy_calculate_bit_shift(u32 bitmask)
-{
-	u32 i;
-
-	for (i = 0; i <= 31; i++) {
-		if (((bitmask >> i) & 0x1) == 1)
-			break;
-	}
-	return i;
-}
-EXPORT_SYMBOL(_rtl92c_phy_calculate_bit_shift);
-
 static void _rtl92c_phy_bb_config_1t(struct ieee80211_hw *hw)
 {
 	rtl_set_bbreg(hw, RFPGA0_TXINFO, 0x3, 0x2);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/rtl8192c/phy_common.h
@@ -196,7 +196,6 @@
 void rtl92ce_phy_set_rf_on(struct ieee80211_hw *hw);
 void rtl92c_phy_set_io(struct ieee80211_hw *hw);
 void rtl92c_bb_block_on(struct ieee80211_hw *hw);
-u32 _rtl92c_phy_calculate_bit_shift(u32 bitmask);
 long _rtl92c_phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw,
 				  enum wireless_mode wirelessmode,
 				  u8 txpwridx);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.c
@@ -39,7 +39,7 @@
 							       rfpath, regaddr);
 	}
 
-	bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
+	bitshift = calculate_bit_shift(bitmask);
 	readback_value = (original_value & bitmask) >> bitshift;
 
 	spin_unlock(&rtlpriv->locks.rf_lock);
@@ -110,7 +110,7 @@
 			original_value = _rtl92c_phy_rf_serial_read(hw,
 								    rfpath,
 								    regaddr);
-			bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
+			bitshift = calculate_bit_shift(bitmask);
 			data =
 			    ((original_value & (~bitmask)) |
 			     (data << bitshift));
@@ -122,7 +122,7 @@
 			original_value = _rtl92c_phy_fw_rf_serial_read(hw,
 								       rfpath,
 								       regaddr);
-			bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
+			bitshift = calculate_bit_shift(bitmask);
 			data =
 			    ((original_value & (~bitmask)) |
 			     (data << bitshift));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/phy.h
@@ -94,7 +94,6 @@
 			       u32 offset);
 u32 _rtl92c_phy_fw_rf_serial_read(struct ieee80211_hw *hw,
 				  enum radio_path rfpath, u32 offset);
-u32 _rtl92c_phy_calculate_bit_shift(u32 bitmask);
 void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw,
 				 enum radio_path rfpath, u32 offset, u32 data);
 void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/hw.c
@@ -618,8 +618,8 @@
 						     u8 queue_sel)
 {
 	u16 beq, bkq, viq, voq, mgtq, hiq;
-	u16 uninitialized_var(valuehi);
-	u16 uninitialized_var(valuelow);
+	u16 valuehi;
+	u16 valuelow;
 
 	switch (queue_sel) {
 	case (TX_SELE_HQ | TX_SELE_LQ):
@@ -1000,6 +1000,7 @@
 	_initpabias(hw);
 	rtl92c_dm_init(hw);
 exit:
+	local_irq_disable();
 	local_irq_restore(flags);
 	return err;
 }
@@ -1540,6 +1541,8 @@
    * This is maybe necessary:
    * rtlpriv->cfg->ops->fill_tx_cmddesc(hw, buffer, 1, 1, skb);
    */
+	dev_kfree_skb(skb);
+
 	return true;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/phy.c
@@ -32,7 +32,7 @@
 		original_value = _rtl92c_phy_fw_rf_serial_read(hw,
 							       rfpath, regaddr);
 	}
-	bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
+	bitshift = calculate_bit_shift(bitmask);
 	readback_value = (original_value & bitmask) >> bitshift;
 	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
 		 "regaddr(%#x), rfpath(%#x), bitmask(%#x), original_value(%#x)\n",
@@ -56,7 +56,7 @@
 			original_value = _rtl92c_phy_rf_serial_read(hw,
 								    rfpath,
 								    regaddr);
-			bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
+			bitshift = calculate_bit_shift(bitmask);
 			data =
 			    ((original_value & (~bitmask)) |
 			     (data << bitshift));
@@ -67,7 +67,7 @@
 			original_value = _rtl92c_phy_fw_rf_serial_read(hw,
 								       rfpath,
 								       regaddr);
-			bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
+			bitshift = calculate_bit_shift(bitmask);
 			data =
 			    ((original_value & (~bitmask)) |
 			     (data << bitshift));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/rtl8192de/hw.c
@@ -1176,6 +1176,7 @@
 
 	rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF);
 	rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF);
+	rtlpci->irq_enabled = true;
 }
 
 void rtl92de_disable_interrupt(struct ieee80211_hw *hw)
@@ -1185,7 +1186,7 @@
 
 	rtl_write_dword(rtlpriv, REG_HIMR, IMR8190_DISABLED);
 	rtl_write_dword(rtlpriv, REG_HIMRE, IMR8190_DISABLED);
-	synchronize_irq(rtlpci->pdev->irq);
+	rtlpci->irq_enabled = false;
 }
 
 static void _rtl92de_poweroff_adapter(struct ieee80211_hw *hw)
@@ -1351,7 +1352,7 @@
 
 	bcn_interval = mac->beacon_interval;
 	atim_window = 2;
-	/*rtl92de_disable_interrupt(hw);  */
+	rtl92de_disable_interrupt(hw);
 	rtl_write_word(rtlpriv, REG_ATIMWND, atim_window);
 	rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval);
 	rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660f);
@@ -1371,9 +1372,9 @@
 
 	RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG,
 		 "beacon_interval:%d\n", bcn_interval);
-	/* rtl92de_disable_interrupt(hw); */
+	rtl92de_disable_interrupt(hw);
 	rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval);
-	/* rtl92de_enable_interrupt(hw); */
+	rtl92de_enable_interrupt(hw);
 }
 
 void rtl92de_update_interrupt_mask(struct ieee80211_hw *hw,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c
@@ -160,17 +160,14 @@
 	25711, 25658, 25606, 25554, 25502, 25451, 25328
 };
 
-static u32 _rtl92d_phy_calculate_bit_shift(u32 bitmask)
-{
-	u32 i;
-
-	for (i = 0; i <= 31; i++) {
-		if (((bitmask >> i) & 0x1) == 1)
-			break;
-	}
-
-	return i;
-}
+static const u8 channel_all[59] = {
+	1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+	36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58,
+	60, 62, 64, 100, 102, 104, 106, 108, 110, 112,
+	114, 116, 118, 120, 122, 124, 126, 128,	130,
+	132, 134, 136, 138, 140, 149, 151, 153, 155,
+	157, 159, 161, 163, 165
+};
 
 u32 rtl92d_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask)
 {
@@ -194,7 +191,7 @@
 	} else {
 		originalvalue = rtl_read_dword(rtlpriv, regaddr);
 	}
-	bitshift = _rtl92d_phy_calculate_bit_shift(bitmask);
+	bitshift = calculate_bit_shift(bitmask);
 	returnvalue = (originalvalue & bitmask) >> bitshift;
 	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
 		 "BBR MASK=0x%x Addr[0x%x]=0x%x\n",
@@ -226,7 +223,7 @@
 					dbi_direct);
 		else
 			originalvalue = rtl_read_dword(rtlpriv, regaddr);
-		bitshift = _rtl92d_phy_calculate_bit_shift(bitmask);
+		bitshift = calculate_bit_shift(bitmask);
 		data = ((originalvalue & (~bitmask)) | (data << bitshift));
 	}
 	if (rtlhal->during_mac1init_radioa || rtlhal->during_mac0init_radiob)
@@ -314,7 +311,7 @@
 		 regaddr, rfpath, bitmask);
 	spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
 	original_value = _rtl92d_phy_rf_serial_read(hw, rfpath, regaddr);
-	bitshift = _rtl92d_phy_calculate_bit_shift(bitmask);
+	bitshift = calculate_bit_shift(bitmask);
 	readback_value = (original_value & bitmask) >> bitshift;
 	spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
 	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
@@ -341,7 +338,7 @@
 		if (bitmask != RFREG_OFFSET_MASK) {
 			original_value = _rtl92d_phy_rf_serial_read(hw,
 				rfpath, regaddr);
-			bitshift = _rtl92d_phy_calculate_bit_shift(bitmask);
+			bitshift = calculate_bit_shift(bitmask);
 			data = ((original_value & (~bitmask)) |
 				(data << bitshift));
 		}
@@ -1361,14 +1358,6 @@
 
 u8 rtl92d_get_rightchnlplace_for_iqk(u8 chnl)
 {
-	u8 channel_all[59] = {
-		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
-		36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58,
-		60, 62, 64, 100, 102, 104, 106, 108, 110, 112,
-		114, 116, 118, 120, 122, 124, 126, 128,	130,
-		132, 134, 136, 138, 140, 149, 151, 153, 155,
-		157, 159, 161, 163, 165
-	};
 	u8 place = chnl;
 
 	if (chnl > 14) {
@@ -2392,14 +2381,10 @@
 			RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD,
 				 "Just Read IQK Matrix reg for channel:%d....\n",
 				 channel);
-			if ((rtlphy->iqk_matrix[indexforchannel].
-			     value[0] != NULL)
-				/*&&(regea4 != 0) */)
+			if (rtlphy->iqk_matrix[indexforchannel].value[0][0] != 0)
 				_rtl92d_phy_patha_fill_iqk_matrix(hw, true,
-					rtlphy->iqk_matrix[
-					indexforchannel].value,	0,
-					(rtlphy->iqk_matrix[
-					indexforchannel].value[0][2] == 0));
+					rtlphy->iqk_matrix[indexforchannel].value, 0,
+					rtlphy->iqk_matrix[indexforchannel].value[0][2] == 0);
 			if (IS_92D_SINGLEPHY(rtlhal->version)) {
 				if ((rtlphy->iqk_matrix[
 					indexforchannel].value[0][4] != 0)
@@ -3227,37 +3212,28 @@
 u8 rtl92d_get_chnlgroup_fromarray(u8 chnl)
 {
 	u8 group;
-	u8 channel_info[59] = {
-		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
-		36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56,
-		58, 60, 62, 64, 100, 102, 104, 106, 108,
-		110, 112, 114, 116, 118, 120, 122, 124,
-		126, 128, 130, 132, 134, 136, 138, 140,
-		149, 151, 153, 155, 157, 159, 161, 163,
-		165
-	};
 
-	if (channel_info[chnl] <= 3)
+	if (channel_all[chnl] <= 3)
 		group = 0;
-	else if (channel_info[chnl] <= 9)
+	else if (channel_all[chnl] <= 9)
 		group = 1;
-	else if (channel_info[chnl] <= 14)
+	else if (channel_all[chnl] <= 14)
 		group = 2;
-	else if (channel_info[chnl] <= 44)
+	else if (channel_all[chnl] <= 44)
 		group = 3;
-	else if (channel_info[chnl] <= 54)
+	else if (channel_all[chnl] <= 54)
 		group = 4;
-	else if (channel_info[chnl] <= 64)
+	else if (channel_all[chnl] <= 64)
 		group = 5;
-	else if (channel_info[chnl] <= 112)
+	else if (channel_all[chnl] <= 112)
 		group = 6;
-	else if (channel_info[chnl] <= 126)
+	else if (channel_all[chnl] <= 126)
 		group = 7;
-	else if (channel_info[chnl] <= 140)
+	else if (channel_all[chnl] <= 140)
 		group = 8;
-	else if (channel_info[chnl] <= 153)
+	else if (channel_all[chnl] <= 153)
 		group = 9;
-	else if (channel_info[chnl] <= 159)
+	else if (channel_all[chnl] <= 159)
 		group = 10;
 	else
 		group = 11;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c
@@ -216,6 +216,7 @@
 	.led_control = rtl92de_led_control,
 	.set_desc = rtl92de_set_desc,
 	.get_desc = rtl92de_get_desc,
+	.is_tx_desc_closed = rtl92de_is_tx_desc_closed,
 	.tx_polling = rtl92de_tx_polling,
 	.enable_hw_sec = rtl92de_enable_hw_security_config,
 	.set_key = rtl92de_set_key,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c
@@ -804,13 +804,15 @@
 			break;
 		}
 	} else {
-		struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc;
 		switch (desc_name) {
 		case HW_DESC_OWN:
-			ret = GET_RX_DESC_OWN(pdesc);
+			ret = GET_RX_DESC_OWN(p_desc);
 			break;
 		case HW_DESC_RXPKT_LEN:
-			ret = GET_RX_DESC_PKT_LEN(pdesc);
+			ret = GET_RX_DESC_PKT_LEN(p_desc);
+			break;
+		case HW_DESC_RXBUFF_ADDR:
+			ret = GET_RX_DESC_BUFF_ADDR(p_desc);
 			break;
 		default:
 			WARN_ONCE(true, "rtl8192de: ERR rxdesc :%d not processed\n",
@@ -821,6 +823,23 @@
 	return ret;
 }
 
+bool rtl92de_is_tx_desc_closed(struct ieee80211_hw *hw,
+			       u8 hw_queue, u16 index)
+{
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue];
+	u8 *entry = (u8 *)(&ring->desc[ring->idx]);
+	u8 own = (u8)rtl92de_get_desc(hw, entry, true, HW_DESC_OWN);
+
+	/* a beacon packet will only use the first
+	 * descriptor by defaut, and the own bit may not
+	 * be cleared by the hardware
+	 */
+	if (own)
+		return false;
+	return true;
+}
+
 void rtl92de_tx_polling(struct ieee80211_hw *hw, u8 hw_queue)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.h
@@ -715,6 +715,8 @@
 		      u8 desc_name, u8 *val);
 u64 rtl92de_get_desc(struct ieee80211_hw *hw,
 		     u8 *p_desc, bool istx, u8 desc_name);
+bool rtl92de_is_tx_desc_closed(struct ieee80211_hw *hw,
+			       u8 hw_queue, u16 index);
 void rtl92de_tx_polling(struct ieee80211_hw *hw, u8 hw_queue);
 void rtl92de_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc,
 			     bool b_firstseg, bool b_lastseg,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/phy.c
@@ -16,7 +16,6 @@
 static void _rtl92ee_phy_rf_serial_write(struct ieee80211_hw *hw,
 					 enum radio_path rfpath, u32 offset,
 					 u32 data);
-static u32 _rtl92ee_phy_calculate_bit_shift(u32 bitmask);
 static bool _rtl92ee_phy_bb8192ee_config_parafile(struct ieee80211_hw *hw);
 static bool _rtl92ee_phy_config_mac_with_headerfile(struct ieee80211_hw *hw);
 static bool phy_config_bb_with_hdr_file(struct ieee80211_hw *hw,
@@ -46,7 +45,7 @@
 	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
 		 "regaddr(%#x), bitmask(%#x)\n", regaddr, bitmask);
 	originalvalue = rtl_read_dword(rtlpriv, regaddr);
-	bitshift = _rtl92ee_phy_calculate_bit_shift(bitmask);
+	bitshift = calculate_bit_shift(bitmask);
 	returnvalue = (originalvalue & bitmask) >> bitshift;
 
 	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
@@ -68,7 +67,7 @@
 
 	if (bitmask != MASKDWORD) {
 		originalvalue = rtl_read_dword(rtlpriv, regaddr);
-		bitshift = _rtl92ee_phy_calculate_bit_shift(bitmask);
+		bitshift = calculate_bit_shift(bitmask);
 		data = ((originalvalue & (~bitmask)) | (data << bitshift));
 	}
 
@@ -93,7 +92,7 @@
 	spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
 
 	original_value = _rtl92ee_phy_rf_serial_read(hw , rfpath, regaddr);
-	bitshift = _rtl92ee_phy_calculate_bit_shift(bitmask);
+	bitshift = calculate_bit_shift(bitmask);
 	readback_value = (original_value & bitmask) >> bitshift;
 
 	spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
@@ -121,7 +120,7 @@
 
 	if (bitmask != RFREG_OFFSET_MASK) {
 		original_value = _rtl92ee_phy_rf_serial_read(hw, rfpath, addr);
-		bitshift = _rtl92ee_phy_calculate_bit_shift(bitmask);
+		bitshift = calculate_bit_shift(bitmask);
 		data = (original_value & (~bitmask)) | (data << bitshift);
 	}
 
@@ -204,17 +203,6 @@
 		 pphyreg->rf3wire_offset, data_and_addr);
 }
 
-static u32 _rtl92ee_phy_calculate_bit_shift(u32 bitmask)
-{
-	u32 i;
-
-	for (i = 0; i <= 31; i++) {
-		if (((bitmask >> i) & 0x1) == 1)
-			break;
-	}
-	return i;
-}
-
 bool rtl92ee_phy_mac_config(struct ieee80211_hw *hw)
 {
 	return _rtl92ee_phy_config_mac_with_headerfile(hw);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.c
@@ -144,10 +144,10 @@
 
 	thermalvalue = (u8)rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0x1f);
 
-	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
-		 "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermal meter 0x%x\n",
-		 thermalvalue,
-		 rtlpriv->dm.thermalvalue, rtlefuse->eeprom_thermalmeter);
+	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+		"Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermal meter 0x%x\n",
+		thermalvalue,
+		rtlpriv->dm.thermalvalue, rtlefuse->eeprom_thermalmeter);
 
 	if (thermalvalue) {
 		rtlpriv->dm.thermalvalue = thermalvalue;
@@ -158,8 +158,8 @@
 				 (rtlpriv->efuse.thermalmeter[0] << 8) |
 				 (thermalvalue << 16));
 
-			RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
-				 "Write to FW Thermal Val = 0x%x\n", fw_cmd);
+			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+				"Write to FW Thermal Val = 0x%x\n", fw_cmd);
 
 			rtl_write_dword(rtlpriv, WFM5, fw_cmd);
 			rtl92s_phy_chk_fwcmd_iodone(hw);
@@ -264,10 +264,10 @@
 		}
 
 		if (ra->pre_ratr_state != ra->ratr_state) {
-			RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
-				 "RSSI = %ld RSSI_LEVEL = %d PreState = %d, CurState = %d\n",
-				 rtlpriv->dm.undec_sm_pwdb, ra->ratr_state,
-				 ra->pre_ratr_state, ra->ratr_state);
+			rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
+				"RSSI = %ld RSSI_LEVEL = %d PreState = %d, CurState = %d\n",
+				rtlpriv->dm.undec_sm_pwdb, ra->ratr_state,
+				ra->pre_ratr_state, ra->ratr_state);
 
 			rcu_read_lock();
 			sta = rtl_find_sta(hw, mac->bssid);
@@ -576,8 +576,8 @@
 
 	if ((mac->link_state < MAC80211_LINKED) &&
 	    (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
-		RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
-			 "Not connected to any\n");
+		rtl_dbg(rtlpriv, COMP_POWER, DBG_TRACE,
+			"Not connected to any\n");
 
 		rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL;
 
@@ -588,21 +588,21 @@
 	if (mac->link_state >= MAC80211_LINKED) {
 		if (mac->opmode == NL80211_IFTYPE_ADHOC) {
 			undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
-			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
-				 "AP Client PWDB = 0x%lx\n",
-				 undec_sm_pwdb);
+			rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
+				"AP Client PWDB = 0x%lx\n",
+				undec_sm_pwdb);
 		} else {
 			undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
-			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
-				 "STA Default Port PWDB = 0x%lx\n",
-				 undec_sm_pwdb);
+			rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
+				"STA Default Port PWDB = 0x%lx\n",
+				undec_sm_pwdb);
 		}
 	} else {
 		undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
 
-		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
-			 "AP Ext Port PWDB = 0x%lx\n",
-			 undec_sm_pwdb);
+		rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
+			"AP Ext Port PWDB = 0x%lx\n",
+			undec_sm_pwdb);
 	}
 
 	txpwr_threshold_lv2 = TX_POWER_NEAR_FIELD_THRESH_LVL2;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/rtl8192se/fw.c
@@ -39,8 +39,8 @@
 	do {
 		cpustatus = rtl_read_byte(rtlpriv, TCR);
 		if (cpustatus & IMEM_RDY) {
-			RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-				 "IMEM Ready after CPU has refilled\n");
+			rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
+				"IMEM Ready after CPU has refilled\n");
 			break;
 		}
 
@@ -195,8 +195,8 @@
 	short pollingcnt = 1000;
 	bool rtstatus = true;
 
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-		 "LoadStaus(%d)\n", loadfw_status);
+	rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
+		"LoadStaus(%d)\n", loadfw_status);
 
 	firmware->fwstatus = (enum fw_status)loadfw_status;
 
@@ -256,9 +256,9 @@
 			goto status_check_fail;
 		}
 
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-			 "DMEM code download success, cpustatus(%#x)\n",
-			 cpustatus);
+		rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
+			"DMEM code download success, cpustatus(%#x)\n",
+			cpustatus);
 
 		/* Prevent Delay too much and being scheduled out */
 		/* Polling Load Firmware ready */
@@ -270,9 +270,9 @@
 			udelay(40);
 		} while (pollingcnt--);
 
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-			 "Polling Load Firmware ready, cpustatus(%x)\n",
-			 cpustatus);
+		rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
+			"Polling Load Firmware ready, cpustatus(%x)\n",
+			cpustatus);
 
 		if (((cpustatus & LOAD_FW_READY) != LOAD_FW_READY) ||
 		    (pollingcnt <= 0)) {
@@ -290,8 +290,8 @@
 		rtl_write_dword(rtlpriv, RCR, (tmpu4b | RCR_APPFCS |
 				RCR_APP_ICV | RCR_APP_MIC));
 
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-			 "Current RCR settings(%#x)\n", tmpu4b);
+		rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
+			"Current RCR settings(%#x)\n", tmpu4b);
 
 		/* Set to normal mode. */
 		rtl_write_byte(rtlpriv, LBKMD_SEL, LBK_NORMAL);
@@ -304,9 +304,9 @@
 	}
 
 status_check_fail:
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-		 "loadfw_status(%d), rtstatus(%x)\n",
-		 loadfw_status, rtstatus);
+	rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
+		"loadfw_status(%d), rtstatus(%x)\n",
+		loadfw_status, rtstatus);
 	return rtstatus;
 }
 
@@ -337,11 +337,11 @@
 	firmware->firmwareversion =  byte(pfwheader->version, 0);
 	firmware->pfwheader->fwpriv.hci_sel = 1;/* pcie */
 
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-		 "signature:%x, version:%x, size:%x, imemsize:%x, sram size:%x\n",
-		 pfwheader->signature,
-		 pfwheader->version, pfwheader->dmem_size,
-		 pfwheader->img_imem_size, pfwheader->img_sram_size);
+	rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
+		"signature:%x, version:%x, size:%x, imemsize:%x, sram size:%x\n",
+		pfwheader->signature,
+		pfwheader->version, pfwheader->dmem_size,
+		pfwheader->img_imem_size, pfwheader->img_sram_size);
 
 	/* 2. Retrieve IMEM image. */
 	if ((pfwheader->img_imem_size == 0) || (pfwheader->img_imem_size >
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c
@@ -111,8 +111,8 @@
 	case HW_VAR_SLOT_TIME:{
 			u8 e_aci;
 
-			RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
-				 "HW_VAR_SLOT_TIME %x\n", val[0]);
+			rtl_dbg(rtlpriv, COMP_MLME, DBG_LOUD,
+				"HW_VAR_SLOT_TIME %x\n", val[0]);
 
 			rtl_write_byte(rtlpriv, SLOT_TIME, val[0]);
 
@@ -156,9 +156,9 @@
 
 				*val = min_spacing_to_set;
 
-				RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
-					 "Set HW_VAR_AMPDU_MIN_SPACE: %#x\n",
-					 mac->min_space_cfg);
+				rtl_dbg(rtlpriv, COMP_MLME, DBG_LOUD,
+					"Set HW_VAR_AMPDU_MIN_SPACE: %#x\n",
+					mac->min_space_cfg);
 
 				rtl_write_byte(rtlpriv, AMPDU_MIN_SPACE,
 					       mac->min_space_cfg);
@@ -172,9 +172,9 @@
 			mac->min_space_cfg = rtlpriv->rtlhal.minspace_cfg;
 			mac->min_space_cfg |= (density_to_set << 3);
 
-			RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
-				 "Set HW_VAR_SHORTGI_DENSITY: %#x\n",
-				 mac->min_space_cfg);
+			rtl_dbg(rtlpriv, COMP_MLME, DBG_LOUD,
+				"Set HW_VAR_SHORTGI_DENSITY: %#x\n",
+				mac->min_space_cfg);
 
 			rtl_write_byte(rtlpriv, AMPDU_MIN_SPACE,
 				       mac->min_space_cfg);
@@ -215,9 +215,9 @@
 					    (factorlevel[17] << 4));
 				rtl_write_byte(rtlpriv, AGGLEN_LMT_H, regtoset);
 
-				RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
-					 "Set HW_VAR_AMPDU_FACTOR: %#x\n",
-					 factor_toset);
+				rtl_dbg(rtlpriv, COMP_MLME, DBG_LOUD,
+					"Set HW_VAR_AMPDU_FACTOR: %#x\n",
+					factor_toset);
 			}
 			break;
 		}
@@ -253,9 +253,9 @@
 					acm_ctrl |= ACMHW_VOQEN;
 					break;
 				default:
-					RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
-						 "HW_VAR_ACM_CTRL acm set failed: eACI is %d\n",
-						 acm);
+					rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
+						"HW_VAR_ACM_CTRL acm set failed: eACI is %d\n",
+						acm);
 					break;
 				}
 			} else {
@@ -276,8 +276,8 @@
 				}
 			}
 
-			RT_TRACE(rtlpriv, COMP_QOS, DBG_TRACE,
-				 "HW_VAR_ACM_CTRL Write 0x%X\n", acm_ctrl);
+			rtl_dbg(rtlpriv, COMP_QOS, DBG_TRACE,
+				"HW_VAR_ACM_CTRL Write 0x%X\n", acm_ctrl);
 			rtl_write_byte(rtlpriv, ACMHWCTRL, acm_ctrl);
 			break;
 		}
@@ -417,14 +417,14 @@
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	u8 sec_reg_value = 0x0;
 
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-		 "PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n",
-		 rtlpriv->sec.pairwise_enc_algorithm,
-		 rtlpriv->sec.group_enc_algorithm);
+	rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
+		"PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n",
+		rtlpriv->sec.pairwise_enc_algorithm,
+		rtlpriv->sec.group_enc_algorithm);
 
 	if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) {
-		RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
-			 "not open hw encryption\n");
+		rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG,
+			"not open hw encryption\n");
 		return;
 	}
 
@@ -435,8 +435,8 @@
 		sec_reg_value |= SCR_RXUSEDK;
 	}
 
-	RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, "The SECR-value %x\n",
-		 sec_reg_value);
+	rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD, "The SECR-value %x\n",
+		sec_reg_value);
 
 	rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value);
 
@@ -870,10 +870,10 @@
 
 		/* Change Program timing */
 		rtl_write_byte(rtlpriv, REG_EFUSE_CTRL + 3, 0x72);
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "EFUSE CONFIG OK\n");
+		rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, "EFUSE CONFIG OK\n");
 	}
 
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "OK\n");
+	rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, "OK\n");
 
 }
 
@@ -960,9 +960,8 @@
 	/* 2. download firmware */
 	rtstatus = rtl92s_download_fw(hw);
 	if (!rtstatus) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
-			 "Failed to download FW. Init HW without FW now... "
-			 "Please copy FW into /lib/firmware/rtlwifi\n");
+		rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
+			"Failed to download FW. Init HW without FW now... Please copy FW into /lib/firmware/rtlwifi\n");
 		err = 1;
 		goto exit;
 	}
@@ -1014,7 +1013,7 @@
 		rtl_write_byte(rtlpriv, RF_CTRL, 0x07);
 
 	if (!rtl92s_phy_rf_config(hw)) {
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "RF Config failed\n");
+		rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, "RF Config failed\n");
 		err = rtstatus;
 		goto exit;
 	}
@@ -1147,23 +1146,23 @@
 	switch (type) {
 	case NL80211_IFTYPE_UNSPECIFIED:
 		bt_msr |= (MSR_LINK_NONE << MSR_LINK_SHIFT);
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 "Set Network type to NO LINK!\n");
+		rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE,
+			"Set Network type to NO LINK!\n");
 		break;
 	case NL80211_IFTYPE_ADHOC:
 		bt_msr |= (MSR_LINK_ADHOC << MSR_LINK_SHIFT);
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 "Set Network type to Ad Hoc!\n");
+		rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE,
+			"Set Network type to Ad Hoc!\n");
 		break;
 	case NL80211_IFTYPE_STATION:
 		bt_msr |= (MSR_LINK_MANAGED << MSR_LINK_SHIFT);
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 "Set Network type to STA!\n");
+		rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE,
+			"Set Network type to STA!\n");
 		break;
 	case NL80211_IFTYPE_AP:
 		bt_msr |= (MSR_LINK_MASTER << MSR_LINK_SHIFT);
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 "Set Network type to AP!\n");
+		rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE,
+			"Set Network type to AP!\n");
 		break;
 	default:
 		pr_err("Network type %d not supported!\n", type);
@@ -1606,8 +1605,8 @@
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 
-	RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, "add_msr:%x, rm_msr:%x\n",
-		 add_msr, rm_msr);
+	rtl_dbg(rtlpriv, COMP_INTR, DBG_LOUD, "add_msr:%x, rm_msr:%x\n",
+		add_msr, rm_msr);
 
 	if (add_msr)
 		rtlpci->irq_mask[0] |= add_msr;
@@ -1671,11 +1670,11 @@
 
 	eeprom_id = *((u16 *)&hwinfo[0]);
 	if (eeprom_id != RTL8190_EEPROM_ID) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
-			 "EEPROM ID(%#x) is invalid!!\n", eeprom_id);
+		rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
+			"EEPROM ID(%#x) is invalid!!\n", eeprom_id);
 		rtlefuse->autoload_failflag = true;
 	} else {
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n");
+		rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n");
 		rtlefuse->autoload_failflag = false;
 	}
 
@@ -1692,16 +1691,16 @@
 	rtlefuse->eeprom_smid = *(u16 *)&hwinfo[EEPROM_SMID];
 	rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION];
 
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-		 "EEPROMId = 0x%4x\n", eeprom_id);
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-		 "EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid);
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-		 "EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did);
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-		 "EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid);
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-		 "EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid);
+	rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
+		"EEPROMId = 0x%4x\n", eeprom_id);
+	rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
+		"EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid);
+	rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
+		"EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did);
+	rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
+		"EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid);
+	rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
+		"EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid);
 
 	for (i = 0; i < 6; i += 2) {
 		usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i];
@@ -1711,7 +1710,7 @@
 	for (i = 0; i < 6; i++)
 		rtl_write_byte(rtlpriv, MACIDR0 + i, rtlefuse->dev_addr[i]);
 
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "%pM\n", rtlefuse->dev_addr);
+	rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, "%pM\n", rtlefuse->dev_addr);
 
 	/* Get Tx Power Level by Channel */
 	/* Read Tx power of Channel 1 ~ 14 from EEPROM. */
@@ -1964,15 +1963,15 @@
 		tempval = rtl_read_byte(rtlpriv, 0x07);
 		if (!(tempval & BIT(0))) {
 			rtlefuse->b1x1_recvcombine = true;
-			RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-				 "RF_TYPE=1T2R but only 1SS\n");
+			rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
+				"RF_TYPE=1T2R but only 1SS\n");
 		}
 	}
 	rtlefuse->b1ss_support = rtlefuse->b1x1_recvcombine;
 	rtlefuse->eeprom_oemid = *&hwinfo[EEPROM_CUSTOMID];
 
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "EEPROM Customer ID: 0x%2x\n",
-		 rtlefuse->eeprom_oemid);
+	rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, "EEPROM Customer ID: 0x%2x\n",
+		rtlefuse->eeprom_oemid);
 
 	/* set channel paln to world wide 13 */
 	rtlefuse->channel_plan = COUNTRY_CODE_WORLD_WIDE_13;
@@ -1987,15 +1986,15 @@
 	tmp_u1b = rtl_read_byte(rtlpriv, EPROM_CMD);
 
 	if (tmp_u1b & BIT(4)) {
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EEPROM\n");
+		rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EEPROM\n");
 		rtlefuse->epromtype = EEPROM_93C46;
 	} else {
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EFUSE\n");
+		rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from EFUSE\n");
 		rtlefuse->epromtype = EEPROM_BOOT_EFUSE;
 	}
 
 	if (tmp_u1b & BIT(5)) {
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n");
+		rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload OK\n");
 		rtlefuse->autoload_failflag = false;
 		_rtl92se_read_adapter_info(hw);
 	} else {
@@ -2101,8 +2100,8 @@
 	else
 		rtl92s_phy_set_fw_cmd(hw, FW_CMD_RA_REFRESH_BG);
 
-	RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, "%x\n",
-		 rtl_read_dword(rtlpriv, ARFR0));
+	rtl_dbg(rtlpriv, COMP_RATR, DBG_DMESG, "%x\n",
+		rtl_read_dword(rtlpriv, ARFR0));
 }
 
 static void rtl92se_update_hal_rate_mask(struct ieee80211_hw *hw,
@@ -2256,8 +2255,8 @@
 
 	mask |= (bmulticast ? 1 : 0) << 9 | (macid & 0x1f) << 4 | (band & 0xf);
 
-	RT_TRACE(rtlpriv, COMP_RATR, DBG_TRACE, "mask = %x, bitmap = %x\n",
-		 mask, ratr_bitmap);
+	rtl_dbg(rtlpriv, COMP_RATR, DBG_TRACE, "mask = %x, bitmap = %x\n",
+		mask, ratr_bitmap);
 	rtl_write_dword(rtlpriv, 0x2c4, ratr_bitmap);
 	rtl_write_dword(rtlpriv, WFM5, (FW_RA_UPDATE_MASK | (mask << 8)));
 
@@ -2332,15 +2331,15 @@
 	rfpwr_toset = _rtl92se_rf_onoff_detect(hw);
 
 	if ((ppsc->hwradiooff) && (rfpwr_toset == ERFON)) {
-		RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
-			 "RFKILL-HW Radio ON, RF ON\n");
+		rtl_dbg(rtlpriv, COMP_RF, DBG_DMESG,
+			"RFKILL-HW Radio ON, RF ON\n");
 
 		rfpwr_toset = ERFON;
 		ppsc->hwradiooff = false;
 		actuallyset = true;
 	} else if ((!ppsc->hwradiooff) && (rfpwr_toset == ERFOFF)) {
-		RT_TRACE(rtlpriv, COMP_RF,
-			 DBG_DMESG, "RFKILL-HW Radio OFF, RF OFF\n");
+		rtl_dbg(rtlpriv, COMP_RF,
+			DBG_DMESG, "RFKILL-HW Radio OFF, RF OFF\n");
 
 		rfpwr_toset = ERFOFF;
 		ppsc->hwradiooff = true;
@@ -2404,7 +2403,7 @@
 		u8 cam_offset = 0;
 		u8 clear_number = 5;
 
-		RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, "clear_all\n");
+		rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, "clear_all\n");
 
 		for (idx = 0; idx < clear_number; idx++) {
 			rtl_cam_mark_invalid(hw, cam_offset + idx);
@@ -2463,26 +2462,26 @@
 		}
 
 		if (rtlpriv->sec.key_len[key_index] == 0) {
-			RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
-				 "delete one entry, entry_id is %d\n",
-				 entry_id);
+			rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG,
+				"delete one entry, entry_id is %d\n",
+				entry_id);
 			if (mac->opmode == NL80211_IFTYPE_AP)
 				rtl_cam_del_entry(hw, p_macaddr);
 			rtl_cam_delete_one_entry(hw, p_macaddr, entry_id);
 		} else {
-			RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
-				 "add one entry\n");
+			rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG,
+				"add one entry\n");
 			if (is_pairwise) {
-				RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
-					 "set Pairwise key\n");
+				rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG,
+					"set Pairwise key\n");
 
 				rtl_cam_add_one_entry(hw, macaddr, key_index,
 					entry_id, enc_algo,
 					CAM_CONFIG_NO_USEDK,
 					rtlpriv->sec.key_buf[key_index]);
 			} else {
-				RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
-					 "set group key\n");
+				rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG,
+					"set group key\n");
 
 				if (mac->opmode == NL80211_IFTYPE_ADHOC) {
 					rtl_cam_add_one_entry(hw,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/rtl8192se/led.c
@@ -27,8 +27,8 @@
 	u8 ledcfg;
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 
-	RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n",
-		 LEDCFG, pled->ledpin);
+	rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n",
+		LEDCFG, pled->ledpin);
 
 	ledcfg = rtl_read_byte(rtlpriv, LEDCFG);
 
@@ -57,8 +57,8 @@
 	rtlpriv = rtl_priv(hw);
 	if (!rtlpriv || rtlpriv->max_fw_size)
 		return;
-	RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n",
-		 LEDCFG, pled->ledpin);
+	rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n",
+		LEDCFG, pled->ledpin);
 
 	ledcfg = rtl_read_byte(rtlpriv, LEDCFG);
 
@@ -119,7 +119,7 @@
 	    ledaction == LED_CTL_POWER_ON)) {
 		return;
 	}
-	RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "ledaction %d\n", ledaction);
+	rtl_dbg(rtlpriv, COMP_LED, DBG_LOUD, "ledaction %d\n", ledaction);
 
 	_rtl92se_sw_led_control(hw, ledaction);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/rtl8192se/phy.c
@@ -14,32 +14,20 @@
 #include "hw.h"
 #include "table.h"
 
-static u32 _rtl92s_phy_calculate_bit_shift(u32 bitmask)
-{
-	u32 i;
-
-	for (i = 0; i <= 31; i++) {
-		if (((bitmask >> i) & 0x1) == 1)
-			break;
-	}
-
-	return i;
-}
-
 u32 rtl92s_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	u32 returnvalue = 0, originalvalue, bitshift;
 
-	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "regaddr(%#x), bitmask(%#x)\n",
-		 regaddr, bitmask);
+	rtl_dbg(rtlpriv, COMP_RF, DBG_TRACE, "regaddr(%#x), bitmask(%#x)\n",
+		regaddr, bitmask);
 
 	originalvalue = rtl_read_dword(rtlpriv, regaddr);
-	bitshift = _rtl92s_phy_calculate_bit_shift(bitmask);
+	bitshift = calculate_bit_shift(bitmask);
 	returnvalue = (originalvalue & bitmask) >> bitshift;
 
-	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "BBR MASK=0x%x Addr[0x%x]=0x%x\n",
-		 bitmask, regaddr, originalvalue);
+	rtl_dbg(rtlpriv, COMP_RF, DBG_TRACE, "BBR MASK=0x%x Addr[0x%x]=0x%x\n",
+		bitmask, regaddr, originalvalue);
 
 	return returnvalue;
 
@@ -51,21 +39,21 @@
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	u32 originalvalue, bitshift;
 
-	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
-		 "regaddr(%#x), bitmask(%#x), data(%#x)\n",
-		 regaddr, bitmask, data);
+	rtl_dbg(rtlpriv, COMP_RF, DBG_TRACE,
+		"regaddr(%#x), bitmask(%#x), data(%#x)\n",
+		regaddr, bitmask, data);
 
 	if (bitmask != MASKDWORD) {
 		originalvalue = rtl_read_dword(rtlpriv, regaddr);
-		bitshift = _rtl92s_phy_calculate_bit_shift(bitmask);
+		bitshift = calculate_bit_shift(bitmask);
 		data = ((originalvalue & (~bitmask)) | (data << bitshift));
 	}
 
 	rtl_write_dword(rtlpriv, regaddr, data);
 
-	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
-		 "regaddr(%#x), bitmask(%#x), data(%#x)\n",
-		 regaddr, bitmask, data);
+	rtl_dbg(rtlpriv, COMP_RF, DBG_TRACE,
+		"regaddr(%#x), bitmask(%#x), data(%#x)\n",
+		regaddr, bitmask, data);
 
 }
 
@@ -123,8 +111,8 @@
 	retvalue = rtl_get_bbreg(hw, pphyreg->rf_rb,
 				 BLSSI_READBACK_DATA);
 
-	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "RFR-%d Addr[0x%x]=0x%x\n",
-		 rfpath, pphyreg->rf_rb, retvalue);
+	rtl_dbg(rtlpriv, COMP_RF, DBG_TRACE, "RFR-%d Addr[0x%x]=0x%x\n",
+		rfpath, pphyreg->rf_rb, retvalue);
 
 	return retvalue;
 
@@ -146,8 +134,8 @@
 	data_and_addr = ((newoffset << 20) | (data & 0x000fffff)) & 0x0fffffff;
 	rtl_set_bbreg(hw, pphyreg->rf3wire_offset, MASKDWORD, data_and_addr);
 
-	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "RFW-%d Addr[0x%x]=0x%x\n",
-		 rfpath, pphyreg->rf3wire_offset, data_and_addr);
+	rtl_dbg(rtlpriv, COMP_RF, DBG_TRACE, "RFW-%d Addr[0x%x]=0x%x\n",
+		rfpath, pphyreg->rf3wire_offset, data_and_addr);
 }
 
 
@@ -157,22 +145,22 @@
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	u32 original_value, readback_value, bitshift;
 
-	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
-		 "regaddr(%#x), rfpath(%#x), bitmask(%#x)\n",
+	rtl_dbg(rtlpriv, COMP_RF, DBG_TRACE,
+		"regaddr(%#x), rfpath(%#x), bitmask(%#x)\n",
 		 regaddr, rfpath, bitmask);
 
 	spin_lock(&rtlpriv->locks.rf_lock);
 
 	original_value = _rtl92s_phy_rf_serial_read(hw, rfpath, regaddr);
 
-	bitshift = _rtl92s_phy_calculate_bit_shift(bitmask);
+	bitshift = calculate_bit_shift(bitmask);
 	readback_value = (original_value & bitmask) >> bitshift;
 
 	spin_unlock(&rtlpriv->locks.rf_lock);
 
-	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
-		 "regaddr(%#x), rfpath(%#x), bitmask(%#x), original_value(%#x)\n",
-		 regaddr, rfpath, bitmask, original_value);
+	rtl_dbg(rtlpriv, COMP_RF, DBG_TRACE,
+		"regaddr(%#x), rfpath(%#x), bitmask(%#x), original_value(%#x)\n",
+		regaddr, rfpath, bitmask, original_value);
 
 	return readback_value;
 }
@@ -187,16 +175,16 @@
 	if (!((rtlphy->rf_pathmap >> rfpath) & 0x1))
 		return;
 
-	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
-		 "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",
-		 regaddr, bitmask, data, rfpath);
+	rtl_dbg(rtlpriv, COMP_RF, DBG_TRACE,
+		"regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",
+		regaddr, bitmask, data, rfpath);
 
 	spin_lock(&rtlpriv->locks.rf_lock);
 
 	if (bitmask != RFREG_OFFSET_MASK) {
 		original_value = _rtl92s_phy_rf_serial_read(hw, rfpath,
 							    regaddr);
-		bitshift = _rtl92s_phy_calculate_bit_shift(bitmask);
+		bitshift = calculate_bit_shift(bitmask);
 		data = ((original_value & (~bitmask)) | (data << bitshift));
 	}
 
@@ -204,9 +192,9 @@
 
 	spin_unlock(&rtlpriv->locks.rf_lock);
 
-	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
-		 "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",
-		 regaddr, bitmask, data, rfpath);
+	rtl_dbg(rtlpriv, COMP_RF, DBG_TRACE,
+		"regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",
+		regaddr, bitmask, data, rfpath);
 
 }
 
@@ -239,9 +227,9 @@
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 	u8 reg_bw_opmode;
 
-	RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "Switch to %s bandwidth\n",
-		 rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ?
-		 "20MHz" : "40MHz");
+	rtl_dbg(rtlpriv, COMP_SCAN, DBG_TRACE, "Switch to %s bandwidth\n",
+		rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ?
+		"20MHz" : "40MHz");
 
 	if (rtlphy->set_bwmode_inprogress)
 		return;
@@ -296,7 +284,7 @@
 
 	rtl92s_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw);
 	rtlphy->set_bwmode_inprogress = false;
-	RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "<==\n");
+	rtl_dbg(rtlpriv, COMP_SCAN, DBG_TRACE, "<==\n");
 }
 
 static bool _rtl92s_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable,
@@ -434,8 +422,8 @@
 	u32 delay;
 	bool ret;
 
-	RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "switch to channel%d\n",
-		 rtlphy->current_channel);
+	rtl_dbg(rtlpriv, COMP_SCAN, DBG_TRACE, "switch to channel%d\n",
+		rtlphy->current_channel);
 
 	if (rtlphy->sw_chnl_inprogress)
 		return 0;
@@ -471,7 +459,7 @@
 
 	rtlphy->sw_chnl_inprogress = false;
 
-	RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "<==\n");
+	rtl_dbg(rtlpriv, COMP_SCAN, DBG_TRACE, "<==\n");
 
 	return 1;
 }
@@ -530,20 +518,19 @@
 				u32 initializecount = 0;
 				do {
 					initializecount++;
-					RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
-						 "IPS Set eRf nic enable\n");
+					rtl_dbg(rtlpriv, COMP_RF, DBG_DMESG,
+						"IPS Set eRf nic enable\n");
 					rtstatus = rtl_ps_enable_nic(hw);
 				} while (!rtstatus && (initializecount < 10));
 
 				RT_CLEAR_PS_LEVEL(ppsc,
 						  RT_RF_OFF_LEVL_HALT_NIC);
 			} else {
-				RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG,
-					 "awake, sleeped:%d ms state_inap:%x\n",
-					 jiffies_to_msecs(jiffies -
-							  ppsc->
-							  last_sleep_jiffies),
-					 rtlpriv->psc.state_inap);
+				rtl_dbg(rtlpriv, COMP_POWER, DBG_DMESG,
+					"awake, slept:%d ms state_inap:%x\n",
+					jiffies_to_msecs(jiffies -
+					ppsc->last_sleep_jiffies),
+					rtlpriv->psc.state_inap);
 				ppsc->last_awake_jiffies = jiffies;
 				rtl_write_word(rtlpriv, CMDR, 0x37FC);
 				rtl_write_byte(rtlpriv, TXPAUSE, 0x00);
@@ -560,8 +547,8 @@
 		}
 	case ERFOFF:{
 			if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) {
-				RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
-					 "IPS Set eRf nic disable\n");
+				rtl_dbg(rtlpriv, COMP_RF, DBG_DMESG,
+					"IPS Set eRf nic disable\n");
 				rtl_ps_disable_nic(hw);
 				RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
 			} else {
@@ -586,34 +573,34 @@
 					queue_id++;
 					continue;
 				} else {
-					RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
-						 "eRf Off/Sleep: %d times TcbBusyQueue[%d] = %d before doze!\n",
-						 i + 1, queue_id,
-						 skb_queue_len(&ring->queue));
+					rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
+						"eRf Off/Sleep: %d times TcbBusyQueue[%d] = %d before doze!\n",
+						i + 1, queue_id,
+						skb_queue_len(&ring->queue));
 
 					udelay(10);
 					i++;
 				}
 
 				if (i >= MAX_DOZE_WAITING_TIMES_9x) {
-					RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
-						 "ERFOFF: %d times TcbBusyQueue[%d] = %d !\n",
-						 MAX_DOZE_WAITING_TIMES_9x,
-						 queue_id,
-						 skb_queue_len(&ring->queue));
+					rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
+						"ERFOFF: %d times TcbBusyQueue[%d] = %d !\n",
+						MAX_DOZE_WAITING_TIMES_9x,
+						queue_id,
+						skb_queue_len(&ring->queue));
 					break;
 				}
 			}
 
-			RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG,
-				 "Set ERFSLEEP awaked:%d ms\n",
-				 jiffies_to_msecs(jiffies -
-						  ppsc->last_awake_jiffies));
-
-			RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG,
-				 "sleep awaked:%d ms state_inap:%x\n",
-				 jiffies_to_msecs(jiffies -
-						  ppsc->last_awake_jiffies),
+			rtl_dbg(rtlpriv, COMP_POWER, DBG_DMESG,
+				"Set ERFSLEEP awaked:%d ms\n",
+				jiffies_to_msecs(jiffies -
+						 ppsc->last_awake_jiffies));
+
+			rtl_dbg(rtlpriv, COMP_POWER, DBG_DMESG,
+				"sleep awaked:%d ms state_inap:%x\n",
+				jiffies_to_msecs(jiffies -
+						 ppsc->last_awake_jiffies),
 				 rtlpriv->psc.state_inap);
 			ppsc->last_sleep_jiffies = jiffies;
 			_rtl92se_phy_set_rf_sleep(hw);
@@ -968,7 +955,7 @@
 		radio_b_tblen = RADIOB_ARRAYLENGTH;
 	}
 
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Radio No %x\n", rfpath);
+	rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, "Radio No %x\n", rfpath);
 	rtstatus = true;
 
 	switch (rfpath) {
@@ -1088,20 +1075,20 @@
 			ROFDM0_XCAGCCORE1, MASKBYTE0);
 	rtlphy->default_initialgain[3] = rtl_get_bbreg(hw,
 			ROFDM0_XDAGCCORE1, MASKBYTE0);
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-		 "Default initial gain (c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x)\n",
-		 rtlphy->default_initialgain[0],
-		 rtlphy->default_initialgain[1],
-		 rtlphy->default_initialgain[2],
-		 rtlphy->default_initialgain[3]);
+	rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
+		"Default initial gain (c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x)\n",
+		rtlphy->default_initialgain[0],
+		rtlphy->default_initialgain[1],
+		rtlphy->default_initialgain[2],
+		rtlphy->default_initialgain[3]);
 
 	/* read framesync */
 	rtlphy->framesync = rtl_get_bbreg(hw, ROFDM0_RXDETECTOR3, MASKBYTE0);
 	rtlphy->framesync_c34 = rtl_get_bbreg(hw, ROFDM0_RXDETECTOR2,
 					      MASKDWORD);
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
-		 "Default framesync (0x%x) = 0x%x\n",
-		 ROFDM0_RXDETECTOR3, rtlphy->framesync);
+	rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
+		"Default framesync (0x%x) = 0x%x\n",
+		ROFDM0_RXDETECTOR3, rtlphy->framesync);
 
 }
 
@@ -1163,10 +1150,10 @@
 	_rtl92s_phy_get_txpower_index(hw, channel, &cckpowerlevel[0],
 			&ofdmpowerlevel[0]);
 
-	RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
-		 "Channel-%d, cckPowerLevel (A / B) = 0x%x / 0x%x, ofdmPowerLevel (A / B) = 0x%x / 0x%x\n",
-		 channel, cckpowerlevel[0], cckpowerlevel[1],
-		 ofdmpowerlevel[0], ofdmpowerlevel[1]);
+	rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
+		"Channel-%d, cckPowerLevel (A / B) = 0x%x / 0x%x, ofdmPowerLevel (A / B) = 0x%x / 0x%x\n",
+		channel, cckpowerlevel[0], cckpowerlevel[1],
+		ofdmpowerlevel[0], ofdmpowerlevel[1]);
 
 	_rtl92s_phy_ccxpower_indexcheck(hw, channel, &cckpowerlevel[0],
 			&ofdmpowerlevel[0]);
@@ -1224,17 +1211,17 @@
 skip:
 	switch (rtlhal->current_fwcmd_io) {
 	case FW_CMD_RA_RESET:
-		RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, "FW_CMD_RA_RESET\n");
+		rtl_dbg(rtlpriv, COMP_CMD, DBG_DMESG, "FW_CMD_RA_RESET\n");
 		rtl_write_dword(rtlpriv, WFM5, FW_RA_RESET);
 		rtl92s_phy_chk_fwcmd_iodone(hw);
 		break;
 	case FW_CMD_RA_ACTIVE:
-		RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, "FW_CMD_RA_ACTIVE\n");
+		rtl_dbg(rtlpriv, COMP_CMD, DBG_DMESG, "FW_CMD_RA_ACTIVE\n");
 		rtl_write_dword(rtlpriv, WFM5, FW_RA_ACTIVE);
 		rtl92s_phy_chk_fwcmd_iodone(hw);
 		break;
 	case FW_CMD_RA_REFRESH_N:
-		RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, "FW_CMD_RA_REFRESH_N\n");
+		rtl_dbg(rtlpriv, COMP_CMD, DBG_DMESG, "FW_CMD_RA_REFRESH_N\n");
 		input = FW_RA_REFRESH;
 		rtl_write_dword(rtlpriv, WFM5, input);
 		rtl92s_phy_chk_fwcmd_iodone(hw);
@@ -1242,29 +1229,29 @@
 		rtl92s_phy_chk_fwcmd_iodone(hw);
 		break;
 	case FW_CMD_RA_REFRESH_BG:
-		RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG,
-			 "FW_CMD_RA_REFRESH_BG\n");
+		rtl_dbg(rtlpriv, COMP_CMD, DBG_DMESG,
+			"FW_CMD_RA_REFRESH_BG\n");
 		rtl_write_dword(rtlpriv, WFM5, FW_RA_REFRESH);
 		rtl92s_phy_chk_fwcmd_iodone(hw);
 		rtl_write_dword(rtlpriv, WFM5, FW_RA_DISABLE_RSSI_MASK);
 		rtl92s_phy_chk_fwcmd_iodone(hw);
 		break;
 	case FW_CMD_RA_REFRESH_N_COMB:
-		RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG,
-			 "FW_CMD_RA_REFRESH_N_COMB\n");
+		rtl_dbg(rtlpriv, COMP_CMD, DBG_DMESG,
+			"FW_CMD_RA_REFRESH_N_COMB\n");
 		input = FW_RA_IOT_N_COMB;
 		rtl_write_dword(rtlpriv, WFM5, input);
 		rtl92s_phy_chk_fwcmd_iodone(hw);
 		break;
 	case FW_CMD_RA_REFRESH_BG_COMB:
-		RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG,
-			 "FW_CMD_RA_REFRESH_BG_COMB\n");
+		rtl_dbg(rtlpriv, COMP_CMD, DBG_DMESG,
+			"FW_CMD_RA_REFRESH_BG_COMB\n");
 		input = FW_RA_IOT_BG_COMB;
 		rtl_write_dword(rtlpriv, WFM5, input);
 		rtl92s_phy_chk_fwcmd_iodone(hw);
 		break;
 	case FW_CMD_IQK_ENABLE:
-		RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, "FW_CMD_IQK_ENABLE\n");
+		rtl_dbg(rtlpriv, COMP_CMD, DBG_DMESG, "FW_CMD_IQK_ENABLE\n");
 		rtl_write_dword(rtlpriv, WFM5, FW_IQK_ENABLE);
 		rtl92s_phy_chk_fwcmd_iodone(hw);
 		break;
@@ -1299,7 +1286,7 @@
 		rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd);
 		break;
 	case FW_CMD_LPS_ENTER:
-		RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, "FW_CMD_LPS_ENTER\n");
+		rtl_dbg(rtlpriv, COMP_CMD, DBG_DMESG, "FW_CMD_LPS_ENTER\n");
 		current_aid = rtlpriv->mac80211.assoc_id;
 		rtl_write_dword(rtlpriv, WFM5, (FW_LPS_ENTER |
 				((current_aid | 0xc000) << 8)));
@@ -1308,18 +1295,18 @@
 		 * turbo mode until driver leave LPS */
 		break;
 	case FW_CMD_LPS_LEAVE:
-		RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, "FW_CMD_LPS_LEAVE\n");
+		rtl_dbg(rtlpriv, COMP_CMD, DBG_DMESG, "FW_CMD_LPS_LEAVE\n");
 		rtl_write_dword(rtlpriv, WFM5, FW_LPS_LEAVE);
 		rtl92s_phy_chk_fwcmd_iodone(hw);
 		break;
 	case FW_CMD_ADD_A2_ENTRY:
-		RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, "FW_CMD_ADD_A2_ENTRY\n");
+		rtl_dbg(rtlpriv, COMP_CMD, DBG_DMESG, "FW_CMD_ADD_A2_ENTRY\n");
 		rtl_write_dword(rtlpriv, WFM5, FW_ADD_A2_ENTRY);
 		rtl92s_phy_chk_fwcmd_iodone(hw);
 		break;
 	case FW_CMD_CTRL_DM_BY_DRIVER:
-		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
-			 "FW_CMD_CTRL_DM_BY_DRIVER\n");
+		rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
+			"FW_CMD_CTRL_DM_BY_DRIVER\n");
 		rtl_write_dword(rtlpriv, WFM5, FW_CTRL_DM_BY_DRIVER);
 		rtl92s_phy_chk_fwcmd_iodone(hw);
 		break;
@@ -1344,9 +1331,9 @@
 	u16	fw_cmdmap = FW_CMD_IO_QUERY(rtlpriv);
 	bool postprocessing = false;
 
-	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
-		 "Set FW Cmd(%#x), set_fwcmd_inprogress(%d)\n",
-		 fw_cmdio, rtlhal->set_fwcmd_inprogress);
+	rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
+		"Set FW Cmd(%#x), set_fwcmd_inprogress(%d)\n",
+		fw_cmdio, rtlhal->set_fwcmd_inprogress);
 
 	do {
 		/* We re-map to combined FW CMD ones if firmware version */
@@ -1383,30 +1370,30 @@
 		 * DM map table in the future. */
 		switch (fw_cmdio) {
 		case FW_CMD_RA_INIT:
-			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "RA init!!\n");
+			rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD, "RA init!!\n");
 			fw_cmdmap |= FW_RA_INIT_CTL;
 			FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
 			/* Clear control flag to sync with FW. */
 			FW_CMD_IO_CLR(rtlpriv, FW_RA_INIT_CTL);
 			break;
 		case FW_CMD_DIG_DISABLE:
-			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
-				 "Set DIG disable!!\n");
+			rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
+				"Set DIG disable!!\n");
 			fw_cmdmap &= ~FW_DIG_ENABLE_CTL;
 			FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
 			break;
 		case FW_CMD_DIG_ENABLE:
 		case FW_CMD_DIG_RESUME:
 			if (!(rtlpriv->dm.dm_flag & HAL_DM_DIG_DISABLE)) {
-				RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
-					 "Set DIG enable or resume!!\n");
+				rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
+					"Set DIG enable or resume!!\n");
 				fw_cmdmap |= (FW_DIG_ENABLE_CTL | FW_SS_CTL);
 				FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
 			}
 			break;
 		case FW_CMD_DIG_HALT:
-			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
-				 "Set DIG halt!!\n");
+			rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
+				"Set DIG halt!!\n");
 			fw_cmdmap &= ~(FW_DIG_ENABLE_CTL | FW_SS_CTL);
 			FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
 			break;
@@ -1421,9 +1408,9 @@
 			fw_param |= ((thermalval << 24) |
 				     (rtlefuse->thermalmeter[0] << 16));
 
-			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
-				 "Set TxPwr tracking!! FwCmdMap(%#x), FwParam(%#x)\n",
-				 fw_cmdmap, fw_param);
+			rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
+				"Set TxPwr tracking!! FwCmdMap(%#x), FwParam(%#x)\n",
+				fw_cmdmap, fw_param);
 
 			FW_CMD_PARA_SET(rtlpriv, fw_param);
 			FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
@@ -1443,9 +1430,9 @@
 			/* Clear FW parameter in terms of RA parts. */
 			fw_param &= FW_RA_PARAM_CLR;
 
-			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
-				 "[FW CMD] [New Version] Set RA/IOT Comb in n mode!! FwCmdMap(%#x), FwParam(%#x)\n",
-				 fw_cmdmap, fw_param);
+			rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
+				"[FW CMD] [New Version] Set RA/IOT Comb in n mode!! FwCmdMap(%#x), FwParam(%#x)\n",
+				fw_cmdmap, fw_param);
 
 			FW_CMD_PARA_SET(rtlpriv, fw_param);
 			FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
@@ -1531,8 +1518,8 @@
 			FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
 			break;
 		case FW_CMD_PAPE_CONTROL:
-			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
-				 "[FW CMD] Set PAPE Control\n");
+			rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
+				"[FW CMD] Set PAPE Control\n");
 			fw_cmdmap &= ~FW_PAPE_CTL_BY_SW_HW;
 
 			FW_CMD_IO_SET(rtlpriv, fw_cmdmap);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.c
@@ -95,13 +95,13 @@
 	}
 
 	if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
-		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
-			 "40MHz finalpwr_idx (A / B) = 0x%x / 0x%x\n",
-			 p_final_pwridx[0], p_final_pwridx[1]);
+		rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
+			"40MHz finalpwr_idx (A / B) = 0x%x / 0x%x\n",
+			p_final_pwridx[0], p_final_pwridx[1]);
 	} else {
-		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
-			 "20MHz finalpwr_idx (A / B) = 0x%x / 0x%x\n",
-			 p_final_pwridx[0], p_final_pwridx[1]);
+		rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
+			"20MHz finalpwr_idx (A / B) = 0x%x / 0x%x\n",
+			p_final_pwridx[0], p_final_pwridx[1]);
 	}
 }
 
@@ -124,9 +124,9 @@
 		if (ant_pwr_diff < -8)
 			ant_pwr_diff = -8;
 
-		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
-			 "Antenna Diff from RF-B to RF-A = %d (0x%x)\n",
-			 ant_pwr_diff, ant_pwr_diff & 0xf);
+		rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
+			"Antenna Diff from RF-B to RF-A = %d (0x%x)\n",
+			ant_pwr_diff, ant_pwr_diff & 0xf);
 
 		ant_pwr_diff &= 0xf;
 	}
@@ -143,8 +143,8 @@
 	rtl_set_bbreg(hw, RFPGA0_TXGAINSTAGE, (BXBTXAGC | BXCTXAGC | BXDTXAGC),
 		      u4reg_val);
 
-	RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "Write BCD-Diff(0x%x) = 0x%x\n",
-		 RFPGA0_TXGAINSTAGE, u4reg_val);
+	rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD, "Write BCD-Diff(0x%x) = 0x%x\n",
+		RFPGA0_TXGAINSTAGE, u4reg_val);
 }
 
 static void _rtl92s_get_txpower_writeval_byregulatory(struct ieee80211_hw *hw,
@@ -169,8 +169,8 @@
 		writeval = rtlphy->mcs_offset[chnlgroup][index] +
 				((index < 2) ? pwrbase0 : pwrbase1);
 
-		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
-			 "RTK better performance, writeval = 0x%x\n", writeval);
+		rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
+			"RTK better performance, writeval = 0x%x\n", writeval);
 		break;
 	case 1:
 		/* Realtek regulatory increase power diff defined
@@ -178,9 +178,9 @@
 		if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
 			writeval = ((index < 2) ? pwrbase0 : pwrbase1);
 
-			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
-				 "Realtek regulatory, 40MHz, writeval = 0x%x\n",
-				 writeval);
+			rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
+				"Realtek regulatory, 40MHz, writeval = 0x%x\n",
+				writeval);
 		} else {
 			chnlgroup = 0;
 
@@ -199,16 +199,16 @@
 					+ ((index < 2) ?
 					pwrbase0 : pwrbase1);
 
-			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
-				 "Realtek regulatory, 20MHz, writeval = 0x%x\n",
-				 writeval);
+			rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
+				"Realtek regulatory, 20MHz, writeval = 0x%x\n",
+				writeval);
 		}
 		break;
 	case 2:
 		/* Better regulatory don't increase any power diff */
 		writeval = ((index < 2) ? pwrbase0 : pwrbase1);
-		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
-			 "Better regulatory, writeval = 0x%x\n", writeval);
+		rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
+			"Better regulatory, writeval = 0x%x\n", writeval);
 		break;
 	case 3:
 		/* Customer defined power diff. increase power diff
@@ -216,15 +216,15 @@
 		chnlgroup = 0;
 
 		if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
-			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
-				 "customer's limit, 40MHz = 0x%x\n",
-				 rtlefuse->pwrgroup_ht40
-				 [RF90_PATH_A][chnl - 1]);
+			rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
+				"customer's limit, 40MHz = 0x%x\n",
+				rtlefuse->pwrgroup_ht40
+				[RF90_PATH_A][chnl - 1]);
 		} else {
-			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
-				 "customer's limit, 20MHz = 0x%x\n",
-				 rtlefuse->pwrgroup_ht20
-				 [RF90_PATH_A][chnl - 1]);
+			rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
+				"customer's limit, 20MHz = 0x%x\n",
+				rtlefuse->pwrgroup_ht20
+				[RF90_PATH_A][chnl - 1]);
 		}
 
 		for (i = 0; i < 4; i++) {
@@ -256,20 +256,20 @@
 				(pwrdiff_limit[2] << 16) |
 				(pwrdiff_limit[1] << 8) |
 				(pwrdiff_limit[0]);
-		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
-			 "Customer's limit = 0x%x\n", customer_limit);
+		rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
+			"Customer's limit = 0x%x\n", customer_limit);
 
 		writeval = customer_limit + ((index < 2) ?
 					     pwrbase0 : pwrbase1);
-		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
-			 "Customer, writeval = 0x%x\n", writeval);
+		rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
+			"Customer, writeval = 0x%x\n", writeval);
 		break;
 	default:
 		chnlgroup = 0;
 		writeval = rtlphy->mcs_offset[chnlgroup][index] +
 				((index < 2) ? pwrbase0 : pwrbase1);
-		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
-			 "RTK better performance, writeval = 0x%x\n", writeval);
+		rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
+			"RTK better performance, writeval = 0x%x\n", writeval);
 		break;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c
@@ -66,24 +66,25 @@
 	struct rt_firmware *pfirmware = NULL;
 	char *fw_name = "rtlwifi/rtl8192sefw.bin";
 
-	RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
-			 "Firmware callback routine entered!\n");
-	complete(&rtlpriv->firmware_loading_complete);
+	rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
+		"Firmware callback routine entered!\n");
 	if (!firmware) {
 		pr_err("Firmware %s not available\n", fw_name);
 		rtlpriv->max_fw_size = 0;
-		return;
+		goto exit;
 	}
 	if (firmware->size > rtlpriv->max_fw_size) {
 		pr_err("Firmware is too big!\n");
 		rtlpriv->max_fw_size = 0;
 		release_firmware(firmware);
-		return;
+		goto exit;
 	}
 	pfirmware = (struct rt_firmware *)rtlpriv->rtlhal.pfirmware;
 	memcpy(pfirmware->sz_fw_tmpbuffer, firmware->data, firmware->size);
 	pfirmware->sz_fw_tmpbufferlen = firmware->size;
 	release_firmware(firmware);
+exit:
+	complete(&rtlpriv->firmware_loading_complete);
 }
 
 static int rtl92s_init_sw_vars(struct ieee80211_hw *hw)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/rtl8192se/trx.c
@@ -333,8 +333,8 @@
 	u8 bw_40 = 0;
 
 	if (pci_dma_mapping_error(rtlpci->pdev, mapping)) {
-		RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
-			 "DMA mapping error\n");
+		rtl_dbg(rtlpriv, COMP_SEND, DBG_TRACE,
+			"DMA mapping error\n");
 		return;
 	}
 	if (mac->opmode == NL80211_IFTYPE_STATION) {
@@ -487,7 +487,7 @@
 	/* DOWRD 8 */
 	SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping);
 
-	RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "\n");
+	rtl_dbg(rtlpriv, COMP_SEND, DBG_TRACE, "\n");
 }
 
 void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc,
@@ -502,8 +502,8 @@
 			PCI_DMA_TODEVICE);
 
 	if (pci_dma_mapping_error(rtlpci->pdev, mapping)) {
-		RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
-			 "DMA mapping error\n");
+		rtl_dbg(rtlpriv, COMP_SEND, DBG_TRACE,
+			"DMA mapping error\n");
 		return;
 	}
 	/* Clear all status	*/
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/dm.c
@@ -578,7 +578,7 @@
 	}
 
 	if (rtlpriv->btcoexist.bt_edca_dl != 0) {
-		edca_be_ul = rtlpriv->btcoexist.bt_edca_dl;
+		edca_be_dl = rtlpriv->btcoexist.bt_edca_dl;
 		bt_change_edca = true;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c
@@ -50,7 +50,7 @@
 							    rfpath, regaddr);
 	}
 
-	bitshift = rtl8723_phy_calculate_bit_shift(bitmask);
+	bitshift = calculate_bit_shift(bitmask);
 	readback_value = (original_value & bitmask) >> bitshift;
 
 	spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
@@ -82,7 +82,7 @@
 			original_value = rtl8723_phy_rf_serial_read(hw,
 								    rfpath,
 								    regaddr);
-			bitshift = rtl8723_phy_calculate_bit_shift(bitmask);
+			bitshift = calculate_bit_shift(bitmask);
 			data =
 			    ((original_value & (~bitmask)) |
 			     (data << bitshift));
@@ -91,7 +91,7 @@
 		rtl8723_phy_rf_serial_write(hw, rfpath, regaddr, data);
 	} else {
 		if (bitmask != RFREG_OFFSET_MASK) {
-			bitshift = rtl8723_phy_calculate_bit_shift(bitmask);
+			bitshift = calculate_bit_shift(bitmask);
 			data =
 			    ((original_value & (~bitmask)) |
 			     (data << bitshift));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/rtl8723be/phy.c
@@ -42,7 +42,7 @@
 	spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
 
 	original_value = rtl8723_phy_rf_serial_read(hw, rfpath, regaddr);
-	bitshift = rtl8723_phy_calculate_bit_shift(bitmask);
+	bitshift = calculate_bit_shift(bitmask);
 	readback_value = (original_value & bitmask) >> bitshift;
 
 	spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
@@ -70,7 +70,7 @@
 	if (bitmask != RFREG_OFFSET_MASK) {
 			original_value = rtl8723_phy_rf_serial_read(hw, path,
 								    regaddr);
-			bitshift = rtl8723_phy_calculate_bit_shift(bitmask);
+			bitshift = calculate_bit_shift(bitmask);
 			data = ((original_value & (~bitmask)) |
 				(data << bitshift));
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/rtl8723com/phy_common.c
@@ -53,13 +53,9 @@
 
 u32 rtl8723_phy_calculate_bit_shift(u32 bitmask)
 {
-	u32 i;
+	u32 i = ffs(bitmask);
 
-	for (i = 0; i <= 31; i++) {
-		if (((bitmask >> i) & 0x1) == 1)
-			break;
-	}
-	return i;
+	return i ? i - 1 : 32;
 }
 EXPORT_SYMBOL_GPL(rtl8723_phy_calculate_bit_shift);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c
@@ -27,7 +27,13 @@
 static void _rtl8821ae_phy_rf_serial_write(struct ieee80211_hw *hw,
 					   enum radio_path rfpath, u32 offset,
 					   u32 data);
-static u32 _rtl8821ae_phy_calculate_bit_shift(u32 bitmask);
+static u32 _rtl8821ae_phy_calculate_bit_shift(u32 bitmask)
+{
+	if (WARN_ON_ONCE(!bitmask))
+		return 0;
+
+	return __ffs(bitmask);
+}
 static bool _rtl8821ae_phy_bb8821a_config_parafile(struct ieee80211_hw *hw);
 /*static bool _rtl8812ae_phy_config_mac_with_headerfile(struct ieee80211_hw *hw);*/
 static bool _rtl8821ae_phy_config_mac_with_headerfile(struct ieee80211_hw *hw);
@@ -274,17 +280,6 @@
 		 rfpath, pphyreg->rf3wire_offset, data_and_addr);
 }
 
-static u32 _rtl8821ae_phy_calculate_bit_shift(u32 bitmask)
-{
-	u32 i;
-
-	for (i = 0; i <= 31; i++) {
-		if (((bitmask >> i) & 0x1) == 1)
-			break;
-	}
-	return i;
-}
-
 bool rtl8821ae_phy_mac_config(struct ieee80211_hw *hw)
 {
 	bool rtstatus = 0;
@@ -1587,7 +1582,7 @@
 }
 
 /* string is in decimal */
-static bool _rtl8812ae_get_integer_from_string(char *str, u8 *pint)
+static bool _rtl8812ae_get_integer_from_string(const char *str, u8 *pint)
 {
 	u16 i = 0;
 	*pint = 0;
@@ -1605,18 +1600,6 @@
 	return true;
 }
 
-static bool _rtl8812ae_eq_n_byte(u8 *str1, u8 *str2, u32 num)
-{
-	if (num == 0)
-		return false;
-	while (num > 0) {
-		num--;
-		if (str1[num] != str2[num])
-			return false;
-	}
-	return true;
-}
-
 static s8 _rtl8812ae_phy_get_chnl_idx_of_txpwr_lmt(struct ieee80211_hw *hw,
 					      u8 band, u8 channel)
 {
@@ -1643,10 +1626,11 @@
 	return channel_index;
 }
 
-static void _rtl8812ae_phy_set_txpower_limit(struct ieee80211_hw *hw, u8 *pregulation,
-				      u8 *pband, u8 *pbandwidth,
-				      u8 *prate_section, u8 *prf_path,
-				      u8 *pchannel, u8 *ppower_limit)
+static void _rtl8812ae_phy_set_txpower_limit(struct ieee80211_hw *hw,
+				      const char *pregulation,
+				      const char *pband, const char *pbandwidth,
+				      const char *prate_section, const char *prf_path,
+				      const char *pchannel, const char *ppower_limit)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_phy *rtlphy = &rtlpriv->phy;
@@ -1654,8 +1638,8 @@
 	u8 channel_index;
 	s8 power_limit = 0, prev_power_limit, ret;
 
-	if (!_rtl8812ae_get_integer_from_string((char *)pchannel, &channel) ||
-	    !_rtl8812ae_get_integer_from_string((char *)ppower_limit,
+	if (!_rtl8812ae_get_integer_from_string(pchannel, &channel) ||
+	    !_rtl8812ae_get_integer_from_string(ppower_limit,
 						&power_limit)) {
 		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 			 "Illegal index of pwr_lmt table [chnl %d][val %d]\n",
@@ -1665,42 +1649,42 @@
 	power_limit = power_limit > MAX_POWER_INDEX ?
 		      MAX_POWER_INDEX : power_limit;
 
-	if (_rtl8812ae_eq_n_byte(pregulation, (u8 *)("FCC"), 3))
+	if (strcmp(pregulation, "FCC") == 0)
 		regulation = 0;
-	else if (_rtl8812ae_eq_n_byte(pregulation, (u8 *)("MKK"), 3))
+	else if (strcmp(pregulation, "MKK") == 0)
 		regulation = 1;
-	else if (_rtl8812ae_eq_n_byte(pregulation, (u8 *)("ETSI"), 4))
+	else if (strcmp(pregulation, "ETSI") == 0)
 		regulation = 2;
-	else if (_rtl8812ae_eq_n_byte(pregulation, (u8 *)("WW13"), 4))
+	else if (strcmp(pregulation, "WW13") == 0)
 		regulation = 3;
 
-	if (_rtl8812ae_eq_n_byte(prate_section, (u8 *)("CCK"), 3))
+	if (strcmp(prate_section, "CCK") == 0)
 		rate_section = 0;
-	else if (_rtl8812ae_eq_n_byte(prate_section, (u8 *)("OFDM"), 4))
+	else if (strcmp(prate_section, "OFDM") == 0)
 		rate_section = 1;
-	else if (_rtl8812ae_eq_n_byte(prate_section, (u8 *)("HT"), 2) &&
-		 _rtl8812ae_eq_n_byte(prf_path, (u8 *)("1T"), 2))
+	else if (strcmp(prate_section, "HT") == 0 &&
+		 strcmp(prf_path, "1T") == 0)
 		rate_section = 2;
-	else if (_rtl8812ae_eq_n_byte(prate_section, (u8 *)("HT"), 2) &&
-		 _rtl8812ae_eq_n_byte(prf_path, (u8 *)("2T"), 2))
+	else if (strcmp(prate_section, "HT") == 0 &&
+		 strcmp(prf_path, "2T") == 0)
 		rate_section = 3;
-	else if (_rtl8812ae_eq_n_byte(prate_section, (u8 *)("VHT"), 3) &&
-		 _rtl8812ae_eq_n_byte(prf_path, (u8 *)("1T"), 2))
+	else if (strcmp(prate_section, "VHT") == 0 &&
+		 strcmp(prf_path, "1T") == 0)
 		rate_section = 4;
-	else if (_rtl8812ae_eq_n_byte(prate_section, (u8 *)("VHT"), 3) &&
-		 _rtl8812ae_eq_n_byte(prf_path, (u8 *)("2T"), 2))
+	else if (strcmp(prate_section, "VHT") == 0 &&
+		 strcmp(prf_path, "2T") == 0)
 		rate_section = 5;
 
-	if (_rtl8812ae_eq_n_byte(pbandwidth, (u8 *)("20M"), 3))
+	if (strcmp(pbandwidth, "20M") == 0)
 		bandwidth = 0;
-	else if (_rtl8812ae_eq_n_byte(pbandwidth, (u8 *)("40M"), 3))
+	else if (strcmp(pbandwidth, "40M") == 0)
 		bandwidth = 1;
-	else if (_rtl8812ae_eq_n_byte(pbandwidth, (u8 *)("80M"), 3))
+	else if (strcmp(pbandwidth, "80M") == 0)
 		bandwidth = 2;
-	else if (_rtl8812ae_eq_n_byte(pbandwidth, (u8 *)("160M"), 4))
+	else if (strcmp(pbandwidth, "160M") == 0)
 		bandwidth = 3;
 
-	if (_rtl8812ae_eq_n_byte(pband, (u8 *)("2.4G"), 4)) {
+	if (strcmp(pband, "2.4G") == 0) {
 		ret = _rtl8812ae_phy_get_chnl_idx_of_txpwr_lmt(hw,
 							       BAND_ON_2_4G,
 							       channel);
@@ -1724,7 +1708,7 @@
 			  regulation, bandwidth, rate_section, channel_index,
 			  rtlphy->txpwr_limit_2_4g[regulation][bandwidth]
 				[rate_section][channel_index][RF90_PATH_A]);
-	} else if (_rtl8812ae_eq_n_byte(pband, (u8 *)("5G"), 2)) {
+	} else if (strcmp(pband, "5G") == 0) {
 		ret = _rtl8812ae_phy_get_chnl_idx_of_txpwr_lmt(hw,
 							       BAND_ON_5G,
 							       channel);
@@ -1755,10 +1739,10 @@
 }
 
 static void _rtl8812ae_phy_config_bb_txpwr_lmt(struct ieee80211_hw *hw,
-					  u8 *regulation, u8 *band,
-					  u8 *bandwidth, u8 *rate_section,
-					  u8 *rf_path, u8 *channel,
-					  u8 *power_limit)
+					  const char *regulation, const char *band,
+					  const char *bandwidth, const char *rate_section,
+					  const char *rf_path, const char *channel,
+					  const char *power_limit)
 {
 	_rtl8812ae_phy_set_txpower_limit(hw, regulation, band, bandwidth,
 					 rate_section, rf_path, channel,
@@ -1771,7 +1755,7 @@
 	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
 	u32 i = 0;
 	u32 array_len;
-	u8 **array;
+	const char **array;
 
 	if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) {
 		array_len = RTL8812AE_TXPWR_LMT_ARRAY_LEN;
@@ -1785,13 +1769,13 @@
 		 "\n");
 
 	for (i = 0; i < array_len; i += 7) {
-		u8 *regulation = array[i];
-		u8 *band = array[i+1];
-		u8 *bandwidth = array[i+2];
-		u8 *rate = array[i+3];
-		u8 *rf_path = array[i+4];
-		u8 *chnl = array[i+5];
-		u8 *val = array[i+6];
+		const char *regulation = array[i];
+		const char *band = array[i+1];
+		const char *bandwidth = array[i+2];
+		const char *rate = array[i+3];
+		const char *rf_path = array[i+4];
+		const char *chnl = array[i+5];
+		const char *val = array[i+6];
 
 		_rtl8812ae_phy_config_bb_txpwr_lmt(hw, regulation, band,
 						   bandwidth, rate, rf_path,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.c
@@ -249,7 +249,7 @@
 	0x824, 0x00030FE0,
 	0x828, 0x00000000,
 	0x82C, 0x002081DD,
-	0x830, 0x2AAA8E24,
+	0x830, 0x2AAAEEC8,
 	0x834, 0x0037A706,
 	0x838, 0x06489B44,
 	0x83C, 0x0000095B,
@@ -324,10 +324,10 @@
 	0x9D8, 0x00000000,
 	0x9DC, 0x00000000,
 	0x9E0, 0x00005D00,
-	0x9E4, 0x00000002,
+	0x9E4, 0x00000003,
 	0x9E8, 0x00000001,
 	0xA00, 0x00D047C8,
-	0xA04, 0x01FF000C,
+	0xA04, 0x01FF800C,
 	0xA08, 0x8C8A8300,
 	0xA0C, 0x2E68000F,
 	0xA10, 0x9500BB78,
@@ -1320,7 +1320,11 @@
 		0x083, 0x00021800,
 		0x084, 0x00028000,
 		0x085, 0x00048000,
+	0x80000111,	0x00000000,	0x40000000,	0x00000000,
+		0x086, 0x0009483A,
+	0xA0000000,	0x00000000,
 		0x086, 0x00094838,
+	0xB0000000,	0x00000000,
 		0x087, 0x00044980,
 		0x088, 0x00048000,
 		0x089, 0x0000D480,
@@ -1409,36 +1413,32 @@
 		0x03C, 0x000CA000,
 		0x0EF, 0x00000000,
 		0x0EF, 0x00001100,
-	0xFF0F0104, 0xABCD,
+	0x80000111,	0x00000000,	0x40000000,	0x00000000,
 		0x034, 0x0004ADF3,
 		0x034, 0x00049DF0,
-	0xFF0F0204, 0xCDEF,
+	0x90000110,	0x00000000,	0x40000000,	0x00000000,
 		0x034, 0x0004ADF3,
 		0x034, 0x00049DF0,
-	0xFF0F0404, 0xCDEF,
-		0x034, 0x0004ADF3,
-		0x034, 0x00049DF0,
-	0xFF0F0200, 0xCDEF,
+	0x90000210,	0x00000000,	0x40000000,	0x00000000,
 		0x034, 0x0004ADF5,
 		0x034, 0x00049DF2,
-	0xFF0F02C0, 0xCDEF,
+	0x9000020c,	0x00000000,	0x40000000,	0x00000000,
+		0x034, 0x0004A0F3,
+		0x034, 0x000490B1,
+		0x9000040c,	0x00000000,	0x40000000,	0x00000000,
 		0x034, 0x0004A0F3,
 		0x034, 0x000490B1,
-	0xCDCDCDCD, 0xCDCD,
+	0x90000200,	0x00000000,	0x40000000,	0x00000000,
+		0x034, 0x0004ADF5,
+		0x034, 0x00049DF2,
+	0x90000410,	0x00000000,	0x40000000,	0x00000000,
+		0x034, 0x0004ADF3,
+		0x034, 0x00049DF0,
+	0xA0000000,	0x00000000,
 		0x034, 0x0004ADF7,
 		0x034, 0x00049DF3,
-	0xFF0F0104, 0xDEAD,
-	0xFF0F0104, 0xABCD,
-		0x034, 0x00048DED,
-		0x034, 0x00047DEA,
-		0x034, 0x00046DE7,
-		0x034, 0x00045CE9,
-		0x034, 0x00044CE6,
-		0x034, 0x000438C6,
-		0x034, 0x00042886,
-		0x034, 0x00041486,
-		0x034, 0x00040447,
-	0xFF0F0204, 0xCDEF,
+	0xB0000000,	0x00000000,
+	0x80000111,	0x00000000,	0x40000000,	0x00000000,
 		0x034, 0x00048DED,
 		0x034, 0x00047DEA,
 		0x034, 0x00046DE7,
@@ -1448,7 +1448,7 @@
 		0x034, 0x00042886,
 		0x034, 0x00041486,
 		0x034, 0x00040447,
-	0xFF0F0404, 0xCDEF,
+	0x90000110,	0x00000000,	0x40000000,	0x00000000,
 		0x034, 0x00048DED,
 		0x034, 0x00047DEA,
 		0x034, 0x00046DE7,
@@ -1458,7 +1458,17 @@
 		0x034, 0x00042886,
 		0x034, 0x00041486,
 		0x034, 0x00040447,
-	0xFF0F02C0, 0xCDEF,
+	0x9000020c,	0x00000000,	0x40000000,	0x00000000,
+		0x034, 0x000480AE,
+		0x034, 0x000470AB,
+		0x034, 0x0004608B,
+		0x034, 0x00045069,
+		0x034, 0x00044048,
+		0x034, 0x00043045,
+		0x034, 0x00042026,
+		0x034, 0x00041023,
+		0x034, 0x00040002,
+	0x9000040c,	0x00000000,	0x40000000,	0x00000000,
 		0x034, 0x000480AE,
 		0x034, 0x000470AB,
 		0x034, 0x0004608B,
@@ -1468,7 +1478,17 @@
 		0x034, 0x00042026,
 		0x034, 0x00041023,
 		0x034, 0x00040002,
-	0xCDCDCDCD, 0xCDCD,
+	0x90000410,	0x00000000,	0x40000000,	0x00000000,
+		0x034, 0x00048DED,
+		0x034, 0x00047DEA,
+		0x034, 0x00046DE7,
+		0x034, 0x00045CE9,
+		0x034, 0x00044CE6,
+		0x034, 0x000438C6,
+		0x034, 0x00042886,
+		0x034, 0x00041486,
+		0x034, 0x00040447,
+	0xA0000000,	0x00000000,
 		0x034, 0x00048DEF,
 		0x034, 0x00047DEC,
 		0x034, 0x00046DE9,
@@ -1478,38 +1498,36 @@
 		0x034, 0x0004248A,
 		0x034, 0x0004108D,
 		0x034, 0x0004008A,
-	0xFF0F0104, 0xDEAD,
-	0xFF0F0200, 0xABCD,
+	0xB0000000,	0x00000000,
+	0x80000210,	0x00000000,	0x40000000,	0x00000000,
 		0x034, 0x0002ADF4,
-	0xFF0F02C0, 0xCDEF,
+	0x9000020c,	0x00000000,	0x40000000,	0x00000000,
+		0x034, 0x0002A0F3,
+	0x9000040c,	0x00000000,	0x40000000,	0x00000000,
 		0x034, 0x0002A0F3,
-	0xCDCDCDCD, 0xCDCD,
+	0x90000200,	0x00000000,	0x40000000,	0x00000000,
+		0x034, 0x0002ADF4,
+	0xA0000000,	0x00000000,
 		0x034, 0x0002ADF7,
-	0xFF0F0200, 0xDEAD,
-	0xFF0F0104, 0xABCD,
-		0x034, 0x00029DF4,
-	0xFF0F0204, 0xCDEF,
+	0xB0000000,	0x00000000,
+	0x80000111,	0x00000000,	0x40000000,	0x00000000,
 		0x034, 0x00029DF4,
-	0xFF0F0404, 0xCDEF,
+	0x90000110,	0x00000000,	0x40000000,	0x00000000,
 		0x034, 0x00029DF4,
-	0xFF0F0200, 0xCDEF,
+	0x90000210,	0x00000000,	0x40000000,	0x00000000,
 		0x034, 0x00029DF1,
-	0xFF0F02C0, 0xCDEF,
+	0x9000020c,	0x00000000,	0x40000000,	0x00000000,
+		0x034, 0x000290F0,
+	0x9000040c,	0x00000000,	0x40000000,	0x00000000,
 		0x034, 0x000290F0,
-	0xCDCDCDCD, 0xCDCD,
+	0x90000200,	0x00000000,	0x40000000,	0x00000000,
+		0x034, 0x00029DF1,
+	0x90000410,	0x00000000,	0x40000000,	0x00000000,
+		0x034, 0x00029DF4,
+	0xA0000000,	0x00000000,
 		0x034, 0x00029DF2,
-	0xFF0F0104, 0xDEAD,
-	0xFF0F0104, 0xABCD,
-		0x034, 0x00028DF1,
-		0x034, 0x00027DEE,
-		0x034, 0x00026DEB,
-		0x034, 0x00025CEC,
-		0x034, 0x00024CE9,
-		0x034, 0x000238CA,
-		0x034, 0x00022889,
-		0x034, 0x00021489,
-		0x034, 0x0002044A,
-	0xFF0F0204, 0xCDEF,
+	0xB0000000,	0x00000000,
+	0x80000111,	0x00000000,	0x40000000,	0x00000000,
 		0x034, 0x00028DF1,
 		0x034, 0x00027DEE,
 		0x034, 0x00026DEB,
@@ -1519,7 +1537,7 @@
 		0x034, 0x00022889,
 		0x034, 0x00021489,
 		0x034, 0x0002044A,
-	0xFF0F0404, 0xCDEF,
+	0x90000110,	0x00000000,	0x40000000,	0x00000000,
 		0x034, 0x00028DF1,
 		0x034, 0x00027DEE,
 		0x034, 0x00026DEB,
@@ -1529,7 +1547,7 @@
 		0x034, 0x00022889,
 		0x034, 0x00021489,
 		0x034, 0x0002044A,
-	0xFF0F02C0, 0xCDEF,
+	0x9000020c,	0x00000000,	0x40000000,	0x00000000,
 		0x034, 0x000280AF,
 		0x034, 0x000270AC,
 		0x034, 0x0002608B,
@@ -1539,7 +1557,27 @@
 		0x034, 0x00022026,
 		0x034, 0x00021023,
 		0x034, 0x00020002,
-	0xCDCDCDCD, 0xCDCD,
+	0x9000040c,	0x00000000,	0x40000000,	0x00000000,
+		0x034, 0x000280AF,
+		0x034, 0x000270AC,
+		0x034, 0x0002608B,
+		0x034, 0x00025069,
+		0x034, 0x00024048,
+		0x034, 0x00023045,
+		0x034, 0x00022026,
+		0x034, 0x00021023,
+		0x034, 0x00020002,
+	0x90000410,	0x00000000,	0x40000000,	0x00000000,
+		0x034, 0x00028DF1,
+		0x034, 0x00027DEE,
+		0x034, 0x00026DEB,
+		0x034, 0x00025CEC,
+		0x034, 0x00024CE9,
+		0x034, 0x000238CA,
+		0x034, 0x00022889,
+		0x034, 0x00021489,
+		0x034, 0x0002044A,
+	0xA0000000,	0x00000000,
 		0x034, 0x00028DEE,
 		0x034, 0x00027DEB,
 		0x034, 0x00026CCD,
@@ -1549,27 +1587,24 @@
 		0x034, 0x00022849,
 		0x034, 0x00021449,
 		0x034, 0x0002004D,
-	0xFF0F0104, 0xDEAD,
-	0xFF0F02C0, 0xABCD,
+	0xB0000000,	0x00000000,
+	0x8000020c,	0x00000000,	0x40000000,	0x00000000,
+		0x034, 0x0000A0D7,
+		0x034, 0x000090D3,
+		0x034, 0x000080B1,
+		0x034, 0x000070AE,
+	0x9000040c,	0x00000000,	0x40000000,	0x00000000,
 		0x034, 0x0000A0D7,
 		0x034, 0x000090D3,
 		0x034, 0x000080B1,
 		0x034, 0x000070AE,
-	0xCDCDCDCD, 0xCDCD,
+	0xA0000000,	0x00000000,
 		0x034, 0x0000ADF7,
 		0x034, 0x00009DF4,
 		0x034, 0x00008DF1,
 		0x034, 0x00007DEE,
-	0xFF0F02C0, 0xDEAD,
-	0xFF0F0104, 0xABCD,
-		0x034, 0x00006DEB,
-		0x034, 0x00005CEC,
-		0x034, 0x00004CE9,
-		0x034, 0x000038CA,
-		0x034, 0x00002889,
-		0x034, 0x00001489,
-		0x034, 0x0000044A,
-	0xFF0F0204, 0xCDEF,
+	0xB0000000,	0x00000000,
+	0x80000111,	0x00000000,	0x40000000,	0x00000000,
 		0x034, 0x00006DEB,
 		0x034, 0x00005CEC,
 		0x034, 0x00004CE9,
@@ -1577,7 +1612,7 @@
 		0x034, 0x00002889,
 		0x034, 0x00001489,
 		0x034, 0x0000044A,
-	0xFF0F0404, 0xCDEF,
+	0x90000110,	0x00000000,	0x40000000,	0x00000000,
 		0x034, 0x00006DEB,
 		0x034, 0x00005CEC,
 		0x034, 0x00004CE9,
@@ -1585,7 +1620,7 @@
 		0x034, 0x00002889,
 		0x034, 0x00001489,
 		0x034, 0x0000044A,
-	0xFF0F02C0, 0xCDEF,
+	0x9000020c,	0x00000000,	0x40000000,	0x00000000,
 		0x034, 0x0000608D,
 		0x034, 0x0000506B,
 		0x034, 0x0000404A,
@@ -1593,7 +1628,23 @@
 		0x034, 0x00002044,
 		0x034, 0x00001025,
 		0x034, 0x00000004,
-	0xCDCDCDCD, 0xCDCD,
+	0x9000040c,	0x00000000,	0x40000000,	0x00000000,
+		0x034, 0x0000608D,
+		0x034, 0x0000506B,
+		0x034, 0x0000404A,
+		0x034, 0x00003047,
+		0x034, 0x00002044,
+		0x034, 0x00001025,
+		0x034, 0x00000004,
+	0x90000410,	0x00000000,	0x40000000,	0x00000000,
+		0x034, 0x00006DEB,
+		0x034, 0x00005CEC,
+		0x034, 0x00004CE9,
+		0x034, 0x000038CA,
+		0x034, 0x00002889,
+		0x034, 0x00001489,
+		0x034, 0x0000044A,
+	0xA0000000,	0x00000000,
 		0x034, 0x00006DCD,
 		0x034, 0x00005CCD,
 		0x034, 0x00004CCA,
@@ -1601,11 +1652,11 @@
 		0x034, 0x00002888,
 		0x034, 0x00001488,
 		0x034, 0x00000486,
-	0xFF0F0104, 0xDEAD,
+	0xB0000000,	0x00000000,
 		0x0EF, 0x00000000,
 		0x018, 0x0001712A,
 		0x0EF, 0x00000040,
-	0xFF0F0104, 0xABCD,
+	0x80000111,	0x00000000,	0x40000000,	0x00000000,
 		0x035, 0x00000187,
 		0x035, 0x00008187,
 		0x035, 0x00010187,
@@ -1615,7 +1666,7 @@
 		0x035, 0x00040188,
 		0x035, 0x00048188,
 		0x035, 0x00050188,
-	0xFF0F0204, 0xCDEF,
+	0x90000110,	0x00000000,	0x40000000,	0x00000000,
 		0x035, 0x00000187,
 		0x035, 0x00008187,
 		0x035, 0x00010187,
@@ -1625,7 +1676,37 @@
 		0x035, 0x00040188,
 		0x035, 0x00048188,
 		0x035, 0x00050188,
-	0xFF0F0404, 0xCDEF,
+	0x90000210,	0x00000000,	0x40000000,	0x00000000,
+		0x035, 0x00000128,
+		0x035, 0x00008128,
+		0x035, 0x00010128,
+		0x035, 0x000201C8,
+		0x035, 0x000281C8,
+		0x035, 0x000301C8,
+		0x035, 0x000401C8,
+		0x035, 0x000481C8,
+		0x035, 0x000501C8,
+	0x9000040c,	0x00000000,	0x40000000,	0x00000000,
+		0x035, 0x00000145,
+		0x035, 0x00008145,
+		0x035, 0x00010145,
+		0x035, 0x00020196,
+		0x035, 0x00028196,
+		0x035, 0x00030196,
+		0x035, 0x000401C7,
+		0x035, 0x000481C7,
+		0x035, 0x000501C7,
+	0x90000200,	0x00000000,	0x40000000,	0x00000000,
+		0x035, 0x00000128,
+		0x035, 0x00008128,
+		0x035, 0x00010128,
+		0x035, 0x000201C8,
+		0x035, 0x000281C8,
+		0x035, 0x000301C8,
+		0x035, 0x000401C8,
+		0x035, 0x000481C8,
+		0x035, 0x000501C8,
+	0x90000410,	0x00000000,	0x40000000,	0x00000000,
 		0x035, 0x00000187,
 		0x035, 0x00008187,
 		0x035, 0x00010187,
@@ -1635,7 +1716,7 @@
 		0x035, 0x00040188,
 		0x035, 0x00048188,
 		0x035, 0x00050188,
-	0xCDCDCDCD, 0xCDCD,
+	0xA0000000,	0x00000000,
 		0x035, 0x00000145,
 		0x035, 0x00008145,
 		0x035, 0x00010145,
@@ -1645,11 +1726,11 @@
 		0x035, 0x000401C7,
 		0x035, 0x000481C7,
 		0x035, 0x000501C7,
-	0xFF0F0104, 0xDEAD,
+	0xB0000000,	0x00000000,
 		0x0EF, 0x00000000,
 		0x018, 0x0001712A,
 		0x0EF, 0x00000010,
-	0xFF0F0104, 0xABCD,
+	0x80000111,	0x00000000,	0x40000000,	0x00000000,
 		0x036, 0x00085733,
 		0x036, 0x0008D733,
 		0x036, 0x00095733,
@@ -1662,7 +1743,7 @@
 		0x036, 0x000CE4B4,
 		0x036, 0x000D64B4,
 		0x036, 0x000DE4B4,
-	0xFF0F0204, 0xCDEF,
+	0x90000110,	0x00000000,	0x40000000,	0x00000000,
 		0x036, 0x00085733,
 		0x036, 0x0008D733,
 		0x036, 0x00095733,
@@ -1675,7 +1756,46 @@
 		0x036, 0x000CE4B4,
 		0x036, 0x000D64B4,
 		0x036, 0x000DE4B4,
-	0xFF0F0404, 0xCDEF,
+	0x90000210,	0x00000000,	0x40000000,	0x00000000,
+		0x036, 0x000063B5,
+		0x036, 0x0000E3B5,
+		0x036, 0x000163B5,
+		0x036, 0x0001E3B5,
+		0x036, 0x000263B5,
+		0x036, 0x0002E3B5,
+		0x036, 0x000363B5,
+		0x036, 0x0003E3B5,
+		0x036, 0x000463B5,
+		0x036, 0x0004E3B5,
+		0x036, 0x000563B5,
+		0x036, 0x0005E3B5,
+	0x9000040c,	0x00000000,	0x40000000,	0x00000000,
+		0x036, 0x000056B3,
+		0x036, 0x0000D6B3,
+		0x036, 0x000156B3,
+		0x036, 0x0001D6B3,
+		0x036, 0x00026634,
+		0x036, 0x0002E634,
+		0x036, 0x00036634,
+		0x036, 0x0003E634,
+		0x036, 0x000467B4,
+		0x036, 0x0004E7B4,
+		0x036, 0x000567B4,
+		0x036, 0x0005E7B4,
+	0x90000200,	0x00000000,	0x40000000,	0x00000000,
+		0x036, 0x000063B5,
+		0x036, 0x0000E3B5,
+		0x036, 0x000163B5,
+		0x036, 0x0001E3B5,
+		0x036, 0x000263B5,
+		0x036, 0x0002E3B5,
+		0x036, 0x000363B5,
+		0x036, 0x0003E3B5,
+		0x036, 0x000463B5,
+		0x036, 0x0004E3B5,
+		0x036, 0x000563B5,
+		0x036, 0x0005E3B5,
+	0x90000410,	0x00000000,	0x40000000,	0x00000000,
 		0x036, 0x00085733,
 		0x036, 0x0008D733,
 		0x036, 0x00095733,
@@ -1688,7 +1808,7 @@
 		0x036, 0x000CE4B4,
 		0x036, 0x000D64B4,
 		0x036, 0x000DE4B4,
-	0xCDCDCDCD, 0xCDCD,
+	0xA0000000,	0x00000000,
 		0x036, 0x000056B3,
 		0x036, 0x0000D6B3,
 		0x036, 0x000156B3,
@@ -1701,103 +1821,162 @@
 		0x036, 0x0004E7B4,
 		0x036, 0x000567B4,
 		0x036, 0x0005E7B4,
-	0xFF0F0104, 0xDEAD,
+	0xB0000000,	0x00000000,
 		0x0EF, 0x00000000,
 		0x0EF, 0x00000008,
-	0xFF0F0104, 0xABCD,
+	0x80000111,	0x00000000,	0x40000000,	0x00000000,
 		0x03C, 0x000001C8,
 		0x03C, 0x00000492,
-	0xFF0F0204, 0xCDEF,
+	0x90000110,	0x00000000,	0x40000000,	0x00000000,
 		0x03C, 0x000001C8,
 		0x03C, 0x00000492,
-	0xFF0F0404, 0xCDEF,
+	0x90000210,	0x00000000,	0x40000000,	0x00000000,
+		0x03C, 0x000001B6,
+		0x03C, 0x00000492,
+	0x9000040c,	0x00000000,	0x40000000,	0x00000000,
+		0x03C, 0x0000022A,
+		0x03C, 0x00000594,
+	0x90000200,	0x00000000,	0x40000000,	0x00000000,
+		0x03C, 0x000001B6,
+		0x03C, 0x00000492,
+	0x90000410,	0x00000000,	0x40000000,	0x00000000,
 		0x03C, 0x000001C8,
 		0x03C, 0x00000492,
-	0xCDCDCDCD, 0xCDCD,
+	0xA0000000,	0x00000000,
 		0x03C, 0x0000022A,
 		0x03C, 0x00000594,
-	0xFF0F0104, 0xDEAD,
-	0xFF0F0104, 0xABCD,
+	0xB0000000,	0x00000000,
+	0x80000111,	0x00000000,	0x40000000,	0x00000000,
 		0x03C, 0x00000800,
-	0xFF0F0204, 0xCDEF,
+	0x90000110,	0x00000000,	0x40000000,	0x00000000,
 		0x03C, 0x00000800,
-	0xFF0F0404, 0xCDEF,
+	0x90000210,	0x00000000,	0x40000000,	0x00000000,
 		0x03C, 0x00000800,
-	0xFF0F02C0, 0xCDEF,
+	0x9000020c,	0x00000000,	0x40000000,	0x00000000,
 		0x03C, 0x00000820,
-	0xCDCDCDCD, 0xCDCD,
+	0x9000040c,	0x00000000,	0x40000000,	0x00000000,
+		0x03C, 0x00000820,
+	0x90000200,	0x00000000,	0x40000000,	0x00000000,
+		0x03C, 0x00000800,
+	0x90000410,	0x00000000,	0x40000000,	0x00000000,
+		0x03C, 0x00000800,
+	0xA0000000,	0x00000000,
 		0x03C, 0x00000900,
-	0xFF0F0104, 0xDEAD,
+	0xB0000000,	0x00000000,
 		0x0EF, 0x00000000,
 		0x018, 0x0001712A,
 		0x0EF, 0x00000002,
-	0xFF0F0104, 0xABCD,
+	0x80000111,	0x00000000,	0x40000000,	0x00000000,
 		0x008, 0x0004E400,
-	0xFF0F0204, 0xCDEF,
+	0x90000110,	0x00000000,	0x40000000,	0x00000000,
 		0x008, 0x0004E400,
-	0xFF0F0404, 0xCDEF,
+	0x90000210,	0x00000000,	0x40000000,	0x00000000,
+		0x008, 0x00002000,
+	0x9000020c,	0x00000000,	0x40000000,	0x00000000,
+		0x008, 0x00002000,
+	0x9000040c,	0x00000000,	0x40000000,	0x00000000,
+		0x008, 0x00002000,
+	0x90000200,	0x00000000,	0x40000000,	0x00000000,
+		0x008, 0x00002000,
+	0x90000410,	0x00000000,	0x40000000,	0x00000000,
 		0x008, 0x0004E400,
-	0xCDCDCDCD, 0xCDCD,
+	0xA0000000,	0x00000000,
 		0x008, 0x00002000,
-	0xFF0F0104, 0xDEAD,
+	0xB0000000,	0x00000000,
 		0x0EF, 0x00000000,
 		0x0DF, 0x000000C0,
-		0x01F, 0x00040064,
-	0xFF0F0104, 0xABCD,
+		0x01F, 0x00000064,
+	0x80000111,	0x00000000,	0x40000000,	0x00000000,
 		0x058, 0x000A7284,
 		0x059, 0x000600EC,
-	0xFF0F0204, 0xCDEF,
+	0x90000110,	0x00000000,	0x40000000,	0x00000000,
 		0x058, 0x000A7284,
 		0x059, 0x000600EC,
-	0xFF0F0404, 0xCDEF,
+	0x9000020c,	0x00000000,	0x40000000,	0x00000000,
+		0x058, 0x00081184,
+		0x059, 0x0006016C,
+	0x9000040c,	0x00000000,	0x40000000,	0x00000000,
+		0x058, 0x00081184,
+		0x059, 0x0006016C,
+	0x90000200,	0x00000000,	0x40000000,	0x00000000,
+		0x058, 0x00081184,
+		0x059, 0x0006016C,
+	0x90000410,	0x00000000,	0x40000000,	0x00000000,
 		0x058, 0x000A7284,
 		0x059, 0x000600EC,
-	0xCDCDCDCD, 0xCDCD,
+	0xA0000000,	0x00000000,
 		0x058, 0x00081184,
 		0x059, 0x0006016C,
-	0xFF0F0104, 0xDEAD,
-	0xFF0F0104, 0xABCD,
+	0xB0000000,	0x00000000,
+	0x80000111,	0x00000000,	0x40000000,	0x00000000,
 		0x061, 0x000E8D73,
 		0x062, 0x00093FC5,
-	0xFF0F0204, 0xCDEF,
+	0x90000110,	0x00000000,	0x40000000,	0x00000000,
 		0x061, 0x000E8D73,
 		0x062, 0x00093FC5,
-	0xFF0F0404, 0xCDEF,
+	0x90000210,	0x00000000,	0x40000000,	0x00000000,
+		0x061, 0x000EFD83,
+		0x062, 0x00093FCC,
+	0x9000040c,	0x00000000,	0x40000000,	0x00000000,
+		0x061, 0x000EAD53,
+		0x062, 0x00093BC4,
+	0x90000200,	0x00000000,	0x40000000,	0x00000000,
+		0x061, 0x000EFD83,
+		0x062, 0x00093FCC,
+	0x90000410,	0x00000000,	0x40000000,	0x00000000,
 		0x061, 0x000E8D73,
 		0x062, 0x00093FC5,
-	0xCDCDCDCD, 0xCDCD,
+	0xA0000000,	0x00000000,
 		0x061, 0x000EAD53,
 		0x062, 0x00093BC4,
-	0xFF0F0104, 0xDEAD,
-	0xFF0F0104, 0xABCD,
+	0xB0000000,	0x00000000,
+	0x80000111,	0x00000000,	0x40000000,	0x00000000,
 		0x063, 0x000110E9,
-	0xFF0F0204, 0xCDEF,
+	0x90000110,	0x00000000,	0x40000000,	0x00000000,
 		0x063, 0x000110E9,
-	0xFF0F0404, 0xCDEF,
+	0x90000210,	0x00000000,	0x40000000,	0x00000000,
+		0x063, 0x000110EB,
+	0x9000020c,	0x00000000,	0x40000000,	0x00000000,
 		0x063, 0x000110E9,
-	0xFF0F0200, 0xCDEF,
-		0x063, 0x000710E9,
-	0xFF0F02C0, 0xCDEF,
+	0x9000040c,	0x00000000,	0x40000000,	0x00000000,
 		0x063, 0x000110E9,
-	0xCDCDCDCD, 0xCDCD,
+	0x90000200,	0x00000000,	0x40000000,	0x00000000,
+		0x063, 0x000110EB,
+	0x90000410,	0x00000000,	0x40000000,	0x00000000,
+		0x063, 0x000110E9,
+	0xA0000000,	0x00000000,
 		0x063, 0x000714E9,
-	0xFF0F0104, 0xDEAD,
-	0xFF0F0104, 0xABCD,
+	0xB0000000,	0x00000000,
+	0x80000111,	0x00000000,	0x40000000,	0x00000000,
+		0x064, 0x0001C27C,
+	0x90000110,	0x00000000,	0x40000000,	0x00000000,
+		0x064, 0x0001C27C,
+	0x90000210,	0x00000000,	0x40000000,	0x00000000,
 		0x064, 0x0001C27C,
-	0xFF0F0204, 0xCDEF,
+	0x9000040c,	0x00000000,	0x40000000,	0x00000000,
+		0x064, 0x0001C67C,
+	0x90000200,	0x00000000,	0x40000000,	0x00000000,
 		0x064, 0x0001C27C,
-	0xFF0F0404, 0xCDEF,
+	0x90000410,	0x00000000,	0x40000000,	0x00000000,
 		0x064, 0x0001C27C,
-	0xCDCDCDCD, 0xCDCD,
+	0xA0000000,	0x00000000,
 		0x064, 0x0001C67C,
-	0xFF0F0104, 0xDEAD,
-	0xFF0F0200, 0xABCD,
+	0xB0000000,	0x00000000,
+	0x80000111,	0x00000000,	0x40000000,	0x00000000,
+		0x065, 0x00091016,
+	0x90000110,	0x00000000,	0x40000000,	0x00000000,
+		0x065, 0x00091016,
+	0x90000210,	0x00000000,	0x40000000,	0x00000000,
 		0x065, 0x00093016,
-	0xFF0F02C0, 0xCDEF,
+		0x9000020c,	0x00000000,	0x40000000,	0x00000000,
 		0x065, 0x00093015,
-	0xCDCDCDCD, 0xCDCD,
+		0x9000040c,	0x00000000,	0x40000000,	0x00000000,
+		0x065, 0x00093015,
+		0x90000200,	0x00000000,	0x40000000,	0x00000000,
+		0x065, 0x00093016,
+		0xA0000000,	0x00000000,
 		0x065, 0x00091016,
-	0xFF0F0200, 0xDEAD,
+		0xB0000000,	0x00000000,
 		0x018, 0x00000006,
 		0x0EF, 0x00002000,
 		0x03B, 0x0003824B,
@@ -1895,9 +2074,10 @@
 		0x0B4, 0x0001214C,
 		0x0B7, 0x0003000C,
 		0x01C, 0x000539D2,
+		0x0C4, 0x000AFE00,
 		0x018, 0x0001F12A,
-		0x0FE, 0x00000000,
-		0x0FE, 0x00000000,
+		0xFFE, 0x00000000,
+		0xFFE, 0x00000000,
 		0x018, 0x0001712A,
 
 };
@@ -2017,6 +2197,7 @@
 u32 RTL8812AE_MAC_1T_ARRAYLEN = ARRAY_SIZE(RTL8812AE_MAC_REG_ARRAY);
 
 u32 RTL8821AE_MAC_REG_ARRAY[] = {
+		0x421, 0x0000000F,
 		0x428, 0x0000000A,
 		0x429, 0x00000010,
 		0x430, 0x00000000,
@@ -2485,7 +2666,7 @@
 		0x81C, 0xA6360001,
 		0x81C, 0xA5380001,
 		0x81C, 0xA43A0001,
-		0x81C, 0xA33C0001,
+		0x81C, 0x683C0001,
 		0x81C, 0x673E0001,
 		0x81C, 0x66400001,
 		0x81C, 0x65420001,
@@ -2519,7 +2700,66 @@
 		0x81C, 0x017A0001,
 		0x81C, 0x017C0001,
 		0x81C, 0x017E0001,
-	0xFF0F02C0, 0xABCD,
+	0x8000020c,	0x00000000,	0x40000000,	0x00000000,
+		0x81C, 0xFB000101,
+		0x81C, 0xFA020101,
+		0x81C, 0xF9040101,
+		0x81C, 0xF8060101,
+		0x81C, 0xF7080101,
+		0x81C, 0xF60A0101,
+		0x81C, 0xF50C0101,
+		0x81C, 0xF40E0101,
+		0x81C, 0xF3100101,
+		0x81C, 0xF2120101,
+		0x81C, 0xF1140101,
+		0x81C, 0xF0160101,
+		0x81C, 0xEF180101,
+		0x81C, 0xEE1A0101,
+		0x81C, 0xED1C0101,
+		0x81C, 0xEC1E0101,
+		0x81C, 0xEB200101,
+		0x81C, 0xEA220101,
+		0x81C, 0xE9240101,
+		0x81C, 0xE8260101,
+		0x81C, 0xE7280101,
+		0x81C, 0xE62A0101,
+		0x81C, 0xE52C0101,
+		0x81C, 0xE42E0101,
+		0x81C, 0xE3300101,
+		0x81C, 0xA5320101,
+		0x81C, 0xA4340101,
+		0x81C, 0xA3360101,
+		0x81C, 0x87380101,
+		0x81C, 0x863A0101,
+		0x81C, 0x853C0101,
+		0x81C, 0x843E0101,
+		0x81C, 0x69400101,
+		0x81C, 0x68420101,
+		0x81C, 0x67440101,
+		0x81C, 0x66460101,
+		0x81C, 0x49480101,
+		0x81C, 0x484A0101,
+		0x81C, 0x474C0101,
+		0x81C, 0x2A4E0101,
+		0x81C, 0x29500101,
+		0x81C, 0x28520101,
+		0x81C, 0x27540101,
+		0x81C, 0x26560101,
+		0x81C, 0x25580101,
+		0x81C, 0x245A0101,
+		0x81C, 0x235C0101,
+		0x81C, 0x055E0101,
+		0x81C, 0x04600101,
+		0x81C, 0x03620101,
+		0x81C, 0x02640101,
+		0x81C, 0x01660101,
+		0x81C, 0x01680101,
+		0x81C, 0x016A0101,
+		0x81C, 0x016C0101,
+		0x81C, 0x016E0101,
+		0x81C, 0x01700101,
+		0x81C, 0x01720101,
+	0x9000040c,	0x00000000,	0x40000000,	0x00000000,
 		0x81C, 0xFB000101,
 		0x81C, 0xFA020101,
 		0x81C, 0xF9040101,
@@ -2578,7 +2818,7 @@
 		0x81C, 0x016E0101,
 		0x81C, 0x01700101,
 		0x81C, 0x01720101,
-	0xCDCDCDCD, 0xCDCD,
+	0xA0000000,	0x00000000,
 		0x81C, 0xFF000101,
 		0x81C, 0xFF020101,
 		0x81C, 0xFE040101,
@@ -2637,7 +2877,7 @@
 		0x81C, 0x046E0101,
 		0x81C, 0x03700101,
 		0x81C, 0x02720101,
-	0xFF0F02C0, 0xDEAD,
+	0xB0000000,	0x00000000,
 		0x81C, 0x01740101,
 		0x81C, 0x01760101,
 		0x81C, 0x01780101,
@@ -2654,7 +2894,7 @@
 *                           TXPWR_LMT.TXT
 ******************************************************************************/
 
-u8 *RTL8812AE_TXPWR_LMT[] = {
+const char *RTL8812AE_TXPWR_LMT[] = {
 	"FCC", "2.4G", "20M", "CCK", "1T", "01", "36",
 	"ETSI", "2.4G", "20M", "CCK", "1T", "01", "32",
 	"MKK", "2.4G", "20M", "CCK", "1T", "01", "32",
@@ -3223,7 +3463,7 @@
 
 u32 RTL8812AE_TXPWR_LMT_ARRAY_LEN = ARRAY_SIZE(RTL8812AE_TXPWR_LMT);
 
-u8 *RTL8821AE_TXPWR_LMT[] = {
+const char *RTL8821AE_TXPWR_LMT[] = {
 	"FCC", "2.4G", "20M", "CCK", "1T", "01", "32",
 	"ETSI", "2.4G", "20M", "CCK", "1T", "01", "32",
 	"MKK", "2.4G", "20M", "CCK", "1T", "01", "32",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/table.h
@@ -28,7 +28,7 @@
 extern u32 RTL8812AE_AGC_TAB_1TARRAYLEN;
 extern u32 RTL8812AE_AGC_TAB_ARRAY[];
 extern u32 RTL8812AE_TXPWR_LMT_ARRAY_LEN;
-extern u8 *RTL8812AE_TXPWR_LMT[];
+extern const char *RTL8812AE_TXPWR_LMT[];
 extern u32 RTL8821AE_TXPWR_LMT_ARRAY_LEN;
-extern u8 *RTL8821AE_TXPWR_LMT[];
+extern const char *RTL8821AE_TXPWR_LMT[];
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/usb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/usb.c
@@ -259,15 +259,15 @@
 						    ? USB_HIGH_SPEED_BULK_SIZE
 						    : USB_FULL_SPEED_BULK_SIZE;
 
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "USB Max Bulk-out Size=%d\n",
-		 rtlusb->max_bulk_out_size);
+	rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, "USB Max Bulk-out Size=%d\n",
+		rtlusb->max_bulk_out_size);
 
 	for (i = 0; i < __RTL_TXQ_NUM; i++) {
 		u32 ep_num = rtlusb->ep_map.ep_mapping[i];
 
 		if (!ep_num) {
-			RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
-				 "Invalid endpoint map setting!\n");
+			rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG,
+				"Invalid endpoint map setting!\n");
 			return -EINVAL;
 		}
 	}
@@ -337,10 +337,10 @@
 		else if (usb_endpoint_dir_out(pep_desc))
 			rtlusb->out_ep_nums++;
 
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
-			 "USB EP(0x%02x), MaxPacketSize=%d, Interval=%d\n",
-			 pep_desc->bEndpointAddress, pep_desc->wMaxPacketSize,
-			 pep_desc->bInterval);
+		rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG,
+			"USB EP(0x%02x), MaxPacketSize=%d, Interval=%d\n",
+			pep_desc->bEndpointAddress, pep_desc->wMaxPacketSize,
+			pep_desc->bInterval);
 	}
 	if (rtlusb->in_ep_nums <  rtlpriv->cfg->usb_interface_cfg->in_ep_num) {
 		pr_err("Too few input end points found\n");
@@ -718,8 +718,11 @@
 
 		usb_anchor_urb(urb, &rtlusb->rx_submitted);
 		err = usb_submit_urb(urb, GFP_KERNEL);
-		if (err)
+		if (err) {
+			usb_unanchor_urb(urb);
+			usb_free_urb(urb);
 			goto err_out;
+		}
 		usb_free_urb(urb);
 	}
 	return 0;
@@ -881,10 +884,8 @@
 
 	WARN_ON(NULL == skb);
 	_urb = usb_alloc_urb(0, GFP_ATOMIC);
-	if (!_urb) {
-		kfree_skb(skb);
+	if (!_urb)
 		return NULL;
-	}
 	_rtl_install_trx_info(rtlusb, skb, ep_num);
 	usb_fill_bulk_urb(_urb, rtlusb->udev, usb_sndbulkpipe(rtlusb->udev,
 			  ep_num), skb->data, skb->len, _rtl_tx_complete, skb);
@@ -898,7 +899,6 @@
 	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
 	u32 ep_num;
 	struct urb *_urb = NULL;
-	struct sk_buff *_skb = NULL;
 
 	WARN_ON(NULL == rtlusb->usb_tx_aggregate_hdl);
 	if (unlikely(IS_USB_STOP(rtlusb))) {
@@ -907,8 +907,7 @@
 		return;
 	}
 	ep_num = rtlusb->ep_map.ep_mapping[qnum];
-	_skb = skb;
-	_urb = _rtl_usb_tx_urb_setup(hw, _skb, ep_num);
+	_urb = _rtl_usb_tx_urb_setup(hw, skb, ep_num);
 	if (unlikely(!_urb)) {
 		pr_err("Can't allocate urb. Drop skb!\n");
 		kfree_skb(skb);
@@ -932,7 +931,7 @@
 
 	memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc));
 	if (ieee80211_is_auth(fc)) {
-		RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, "MAC80211_LINKING\n");
+		rtl_dbg(rtlpriv, COMP_SEND, DBG_DMESG, "MAC80211_LINKING\n");
 	}
 
 	if (rtlpriv->psc.sw_ps_enabled) {
@@ -1014,15 +1013,17 @@
 	hw = ieee80211_alloc_hw(sizeof(struct rtl_priv) +
 				sizeof(struct rtl_usb_priv), &rtl_ops);
 	if (!hw) {
-		WARN_ONCE(true, "rtl_usb: ieee80211 alloc failed\n");
+		pr_warn("rtl_usb: ieee80211 alloc failed\n");
 		return -ENOMEM;
 	}
 	rtlpriv = hw->priv;
 	rtlpriv->hw = hw;
 	rtlpriv->usb_data = kcalloc(RTL_USB_MAX_RX_COUNT, sizeof(u32),
 				    GFP_KERNEL);
-	if (!rtlpriv->usb_data)
+	if (!rtlpriv->usb_data) {
+		ieee80211_free_hw(hw);
 		return -ENOMEM;
+	}
 
 	/* this spin lock must be initialized early */
 	spin_lock_init(&rtlpriv->locks.usb_lock);
@@ -1078,11 +1079,12 @@
 	return 0;
 
 error_out:
+	rtl_usb_deinit(hw);
 	rtl_deinit_core(hw);
 error_out2:
 	_rtl_usb_io_handler_release(hw);
 	usb_put_dev(udev);
-	complete(&rtlpriv->firmware_loading_complete);
+	kfree(rtlpriv->usb_data);
 	return -ENODEV;
 }
 EXPORT_SYMBOL(rtl_usb_probe);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtlwifi/wifi.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtlwifi/wifi.h
@@ -2302,7 +2302,6 @@
 			  u32 regaddr, u32 bitmask, u32 data);
 	void (*linked_set_reg)(struct ieee80211_hw *hw);
 	void (*chk_switch_dmdp)(struct ieee80211_hw *hw);
-	void (*dualmac_easy_concurrent)(struct ieee80211_hw *hw);
 	void (*dualmac_switch_to_dmdp)(struct ieee80211_hw *hw);
 	bool (*phy_rf6052_config)(struct ieee80211_hw *hw);
 	void (*phy_rf6052_set_cck_txpower)(struct ieee80211_hw *hw,
@@ -2338,8 +2337,6 @@
 	void (*read_efuse_byte)(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf);
 	int (*adapter_start)(struct ieee80211_hw *hw);
 	void (*adapter_stop)(struct ieee80211_hw *hw);
-	bool (*check_buddy_priv)(struct ieee80211_hw *hw,
-				 struct rtl_priv **buddy_priv);
 
 	int (*adapter_tx)(struct ieee80211_hw *hw,
 			  struct ieee80211_sta *sta,
@@ -2468,7 +2465,6 @@
 
 	/*timer */
 	struct timer_list watchdog_timer;
-	struct timer_list dualmac_easyconcurrent_retrytimer;
 	struct timer_list fw_clockoff_timer;
 	struct timer_list fast_antenna_training_timer;
 	/*task */
@@ -2500,14 +2496,6 @@
 #define MIMO_PS_DYNAMIC			1
 #define MIMO_PS_NOLIMIT			3
 
-struct rtl_dualmac_easy_concurrent_ctl {
-	enum band_type currentbandtype_backfordmdp;
-	bool close_bbandrf_for_dmsp;
-	bool change_to_dmdp;
-	bool change_to_dmsp;
-	bool switch_in_process;
-};
-
 struct rtl_dmsp_ctl {
 	bool activescan_for_slaveofdmsp;
 	bool scan_for_anothermac_fordmsp;
@@ -2592,14 +2580,6 @@
 	u32 rssi_max;
 };
 
-struct rtl_global_var {
-	/* from this list we can get
-	 * other adapter's rtl_priv
-	 */
-	struct list_head glb_priv_list;
-	spinlock_t glb_list_lock;
-};
-
 #define IN_4WAY_TIMEOUT_TIME	(30 * MSEC_PER_SEC)	/* 30 seconds */
 
 struct rtl_btc_info {
@@ -2745,10 +2725,7 @@
 struct rtl_priv {
 	struct ieee80211_hw *hw;
 	struct completion firmware_loading_complete;
-	struct list_head list;
 	struct rtl_priv *buddy_priv;
-	struct rtl_global_var *glb_var;
-	struct rtl_dualmac_easy_concurrent_ctl easy_concurrent_ctl;
 	struct rtl_dmsp_ctl dmsp_ctl;
 	struct rtl_locks locks;
 	struct rtl_works works;
@@ -3230,4 +3207,11 @@
 	return ieee80211_find_sta(mac->vif, mac_addr);
 }
 
+static inline u32 calculate_bit_shift(u32 bitmask)
+{
+	if (WARN_ON_ONCE(!bitmask))
+		return 0;
+
+	return __ffs(bitmask);
+}
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/Kconfig
@@ -12,6 +12,7 @@
 
 config RTW88_CORE
 	tristate
+	select WANT_DEV_COREDUMP
 
 config RTW88_PCI
 	tristate
@@ -36,6 +37,16 @@
 
 	  802.11ac PCIe wireless network adapter
 
+config RTW88_8723DE
+	bool "Realtek 8723DE PCI wireless network adapter"
+	depends on PCI
+	select RTW88_CORE
+	select RTW88_PCI
+	help
+	  Select this option will enable support for 8723DE chipset
+
+	  802.11n PCIe wireless network adapter
+
 config RTW88_DEBUG
 	bool "Realtek rtw88 debug support"
 	depends on RTW88_CORE
@@ -52,4 +63,14 @@
 
 	  If unsure, say Y to simplify debug problems
 
+config RTW88_REGD_USER_REG_HINTS
+	bool "Realtek rtw88 user regulatory hints"
+	depends on RTW88_CORE
+	default n
+	help
+	  Enable regulatoy user hints
+
+	  If unsure, say N. This should only be allowed on distributions
+	  that need this to correct the regulatory.
+
 endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/Makefile
@@ -14,10 +14,14 @@
 	   fw.o \
 	   ps.o \
 	   sec.o \
+	   bf.o \
+	   wow.o \
+	   sar.o \
 	   regd.o
 
 rtw88-$(CONFIG_RTW88_8822BE)	+= rtw8822b.o rtw8822b_table.o
 rtw88-$(CONFIG_RTW88_8822CE)	+= rtw8822c.o rtw8822c_table.o
+rtw88-$(CONFIG_RTW88_8723DE)	+= rtw8723d.o rtw8723d_table.o
 
 obj-$(CONFIG_RTW88_PCI)		+= rtwpci.o
 rtwpci-objs			:= pci.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/bf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/bf.c
@@ -0,0 +1,397 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2018-2019  Realtek Corporation.
+ */
+
+#include "main.h"
+#include "reg.h"
+#include "bf.h"
+#include "debug.h"
+
+void rtw_bf_disassoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
+		     struct ieee80211_bss_conf *bss_conf)
+{
+	struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
+	struct rtw_bfee *bfee = &rtwvif->bfee;
+	struct rtw_bf_info *bfinfo = &rtwdev->bf_info;
+
+	if (bfee->role == RTW_BFEE_NONE)
+		return;
+
+	if (bfee->role == RTW_BFEE_MU)
+		bfinfo->bfer_mu_cnt--;
+	else if (bfee->role == RTW_BFEE_SU)
+		bfinfo->bfer_su_cnt--;
+
+	rtw_chip_config_bfee(rtwdev, rtwvif, bfee, false);
+
+	bfee->role = RTW_BFEE_NONE;
+}
+
+void rtw_bf_assoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
+		  struct ieee80211_bss_conf *bss_conf)
+{
+	struct ieee80211_hw *hw = rtwdev->hw;
+	struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
+	struct rtw_bfee *bfee = &rtwvif->bfee;
+	struct rtw_bf_info *bfinfo = &rtwdev->bf_info;
+	struct rtw_chip_info *chip = rtwdev->chip;
+	struct ieee80211_sta *sta;
+	struct ieee80211_sta_vht_cap *vht_cap;
+	struct ieee80211_sta_vht_cap *ic_vht_cap;
+	const u8 *bssid = bss_conf->bssid;
+	u32 sound_dim;
+	u8 i;
+
+	if (!(chip->band & RTW_BAND_5G))
+		return;
+
+	rcu_read_lock();
+
+	sta = ieee80211_find_sta(vif, bssid);
+	if (!sta) {
+		rtw_warn(rtwdev, "failed to find station entry for bss %pM\n",
+			 bssid);
+		goto out_unlock;
+	}
+
+	ic_vht_cap = &hw->wiphy->bands[NL80211_BAND_5GHZ]->vht_cap;
+	vht_cap = &sta->vht_cap;
+
+	if ((ic_vht_cap->cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE) &&
+	    (vht_cap->cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)) {
+		if (bfinfo->bfer_mu_cnt >= chip->bfer_mu_max_num) {
+			rtw_dbg(rtwdev, RTW_DBG_BF, "mu bfer number over limit\n");
+			goto out_unlock;
+		}
+
+		ether_addr_copy(bfee->mac_addr, bssid);
+		bfee->role = RTW_BFEE_MU;
+		bfee->p_aid = (bssid[5] << 1) | (bssid[4] >> 7);
+		bfee->aid = bss_conf->aid;
+		bfinfo->bfer_mu_cnt++;
+
+		rtw_chip_config_bfee(rtwdev, rtwvif, bfee, true);
+	} else if ((ic_vht_cap->cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE) &&
+		   (vht_cap->cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)) {
+		if (bfinfo->bfer_su_cnt >= chip->bfer_su_max_num) {
+			rtw_dbg(rtwdev, RTW_DBG_BF, "su bfer number over limit\n");
+			goto out_unlock;
+		}
+
+		sound_dim = vht_cap->cap &
+			    IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK;
+		sound_dim >>= IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT;
+
+		ether_addr_copy(bfee->mac_addr, bssid);
+		bfee->role = RTW_BFEE_SU;
+		bfee->sound_dim = (u8)sound_dim;
+		bfee->g_id = 0;
+		bfee->p_aid = (bssid[5] << 1) | (bssid[4] >> 7);
+		bfinfo->bfer_su_cnt++;
+		for (i = 0; i < chip->bfer_su_max_num; i++) {
+			if (!test_bit(i, bfinfo->bfer_su_reg_maping)) {
+				set_bit(i, bfinfo->bfer_su_reg_maping);
+				bfee->su_reg_index = i;
+				break;
+			}
+		}
+
+		rtw_chip_config_bfee(rtwdev, rtwvif, bfee, true);
+	}
+
+out_unlock:
+	rcu_read_unlock();
+}
+
+void rtw_bf_init_bfer_entry_mu(struct rtw_dev *rtwdev,
+			       struct mu_bfer_init_para *param)
+{
+	u16 mu_bf_ctl = 0;
+	u8 *addr = param->bfer_address;
+	int i;
+
+	for (i = 0; i < ETH_ALEN; i++)
+		rtw_write8(rtwdev, REG_ASSOCIATED_BFMER0_INFO + i, addr[i]);
+	rtw_write16(rtwdev, REG_ASSOCIATED_BFMER0_INFO + 6, param->paid);
+	rtw_write16(rtwdev, REG_TX_CSI_RPT_PARAM_BW20, param->csi_para);
+
+	mu_bf_ctl = rtw_read16(rtwdev, REG_WMAC_MU_BF_CTL) & 0xC000;
+	mu_bf_ctl |= param->my_aid | (param->csi_length_sel << 12);
+	rtw_write16(rtwdev, REG_WMAC_MU_BF_CTL, mu_bf_ctl);
+}
+
+void rtw_bf_cfg_sounding(struct rtw_dev *rtwdev, struct rtw_vif *vif,
+			 enum rtw_trx_desc_rate rate)
+{
+	u32 psf_ctl = 0;
+	u8 csi_rsc = 0x1;
+
+	psf_ctl = rtw_read32(rtwdev, REG_BBPSF_CTRL) |
+		  BIT_WMAC_USE_NDPARATE |
+		  (csi_rsc << 13);
+
+	rtw_write8(rtwdev, REG_SND_PTCL_CTRL, RTW_SND_CTRL_SOUNDING);
+	rtw_write8(rtwdev, REG_SND_PTCL_CTRL + 3, 0x26);
+	rtw_write8_clr(rtwdev, REG_RXFLTMAP1, BIT_RXFLTMAP1_BF_REPORT_POLL);
+	rtw_write8_clr(rtwdev, REG_RXFLTMAP4, BIT_RXFLTMAP4_BF_REPORT_POLL);
+
+	if (vif->net_type == RTW_NET_AP_MODE)
+		rtw_write32(rtwdev, REG_BBPSF_CTRL, psf_ctl | BIT(12));
+	else
+		rtw_write32(rtwdev, REG_BBPSF_CTRL, psf_ctl & ~BIT(12));
+}
+
+void rtw_bf_cfg_mu_bfee(struct rtw_dev *rtwdev, struct cfg_mumimo_para *param)
+{
+	u8 mu_tbl_sel;
+	u8 mu_valid;
+
+	mu_valid = rtw_read8(rtwdev, REG_MU_TX_CTL) &
+		   ~BIT_MASK_R_MU_TABLE_VALID;
+
+	rtw_write8(rtwdev, REG_MU_TX_CTL,
+		   (mu_valid | BIT(0) | BIT(1)) & ~(BIT(7)));
+
+	mu_tbl_sel = rtw_read8(rtwdev, REG_MU_TX_CTL + 1) & 0xF8;
+
+	rtw_write8(rtwdev, REG_MU_TX_CTL + 1, mu_tbl_sel);
+	rtw_write32(rtwdev, REG_MU_STA_GID_VLD, param->given_gid_tab[0]);
+	rtw_write32(rtwdev, REG_MU_STA_USER_POS_INFO, param->given_user_pos[0]);
+	rtw_write32(rtwdev, REG_MU_STA_USER_POS_INFO + 4,
+		    param->given_user_pos[1]);
+
+	rtw_write8(rtwdev, REG_MU_TX_CTL + 1, mu_tbl_sel | 1);
+	rtw_write32(rtwdev, REG_MU_STA_GID_VLD, param->given_gid_tab[1]);
+	rtw_write32(rtwdev, REG_MU_STA_USER_POS_INFO, param->given_user_pos[2]);
+	rtw_write32(rtwdev, REG_MU_STA_USER_POS_INFO + 4,
+		    param->given_user_pos[3]);
+}
+
+void rtw_bf_del_bfer_entry_mu(struct rtw_dev *rtwdev)
+{
+	rtw_write32(rtwdev, REG_ASSOCIATED_BFMER0_INFO, 0);
+	rtw_write32(rtwdev, REG_ASSOCIATED_BFMER0_INFO + 4, 0);
+	rtw_write16(rtwdev, REG_WMAC_MU_BF_CTL, 0);
+	rtw_write8(rtwdev, REG_MU_TX_CTL, 0);
+}
+
+void rtw_bf_del_sounding(struct rtw_dev *rtwdev)
+{
+	rtw_write8(rtwdev, REG_SND_PTCL_CTRL, 0);
+}
+
+void rtw_bf_enable_bfee_su(struct rtw_dev *rtwdev, struct rtw_vif *vif,
+			   struct rtw_bfee *bfee)
+{
+	u8 nc_index = 1;
+	u8 nr_index = bfee->sound_dim;
+	u8 grouping = 0, codebookinfo = 1, coefficientsize = 3;
+	u32 addr_bfer_info, addr_csi_rpt, csi_param;
+	u8 i;
+
+	rtw_dbg(rtwdev, RTW_DBG_BF, "config as an su bfee\n");
+
+	switch (bfee->su_reg_index) {
+	case 1:
+		addr_bfer_info = REG_ASSOCIATED_BFMER1_INFO;
+		addr_csi_rpt = REG_TX_CSI_RPT_PARAM_BW20 + 2;
+		break;
+	case 0:
+	default:
+		addr_bfer_info = REG_ASSOCIATED_BFMER0_INFO;
+		addr_csi_rpt = REG_TX_CSI_RPT_PARAM_BW20;
+		break;
+	}
+
+	/* Sounding protocol control */
+	rtw_write8(rtwdev, REG_SND_PTCL_CTRL, RTW_SND_CTRL_SOUNDING);
+
+	/* MAC address/Partial AID of Beamformer */
+	for (i = 0; i < ETH_ALEN; i++)
+		rtw_write8(rtwdev, addr_bfer_info + i, bfee->mac_addr[i]);
+
+	csi_param = (u16)((coefficientsize << 10) |
+			  (codebookinfo << 8) |
+			  (grouping << 6) |
+			  (nr_index << 3) |
+			  nc_index);
+	rtw_write16(rtwdev, addr_csi_rpt, csi_param);
+
+	/* ndp rx standby timer */
+	rtw_write8(rtwdev, REG_SND_PTCL_CTRL + 3, RTW_NDP_RX_STANDBY_TIME);
+}
+
+/* nc index: 1 2T2R 0 1T1R
+ * nr index: 1 use Nsts 0 use reg setting
+ * codebookinfo: 1 802.11ac 3 802.11n
+ */
+void rtw_bf_enable_bfee_mu(struct rtw_dev *rtwdev, struct rtw_vif *vif,
+			   struct rtw_bfee *bfee)
+{
+	struct rtw_bf_info *bf_info = &rtwdev->bf_info;
+	struct mu_bfer_init_para param;
+	u8 nc_index = 1, nr_index = 1;
+	u8 grouping = 0, codebookinfo = 1, coefficientsize = 0;
+	u32 csi_param;
+
+	rtw_dbg(rtwdev, RTW_DBG_BF, "config as an mu bfee\n");
+
+	csi_param = (u16)((coefficientsize << 10) |
+			  (codebookinfo << 8) |
+			  (grouping << 6) |
+			  (nr_index << 3) |
+			  nc_index);
+
+	rtw_dbg(rtwdev, RTW_DBG_BF, "nc=%d nr=%d group=%d codebookinfo=%d coefficientsize=%d\n",
+		nc_index, nr_index, grouping, codebookinfo,
+		coefficientsize);
+
+	param.paid = bfee->p_aid;
+	param.csi_para = csi_param;
+	param.my_aid = bfee->aid & 0xfff;
+	param.csi_length_sel = HAL_CSI_SEG_4K;
+	ether_addr_copy(param.bfer_address, bfee->mac_addr);
+
+	rtw_bf_init_bfer_entry_mu(rtwdev, &param);
+
+	bf_info->cur_csi_rpt_rate = DESC_RATE6M;
+	rtw_bf_cfg_sounding(rtwdev, vif, DESC_RATE6M);
+
+	/* accept action_no_ack */
+	rtw_write16_set(rtwdev, REG_RXFLTMAP0, BIT_RXFLTMAP0_ACTIONNOACK);
+
+	/* accept NDPA and BF report poll */
+	rtw_write16_set(rtwdev, REG_RXFLTMAP1, BIT_RXFLTMAP1_BF);
+}
+
+void rtw_bf_remove_bfee_su(struct rtw_dev *rtwdev,
+			   struct rtw_bfee *bfee)
+{
+	struct rtw_bf_info *bfinfo = &rtwdev->bf_info;
+
+	rtw_dbg(rtwdev, RTW_DBG_BF, "remove as a su bfee\n");
+	rtw_write8(rtwdev, REG_SND_PTCL_CTRL, RTW_SND_CTRL_REMOVE);
+
+	switch (bfee->su_reg_index) {
+	case 0:
+		rtw_write32(rtwdev, REG_ASSOCIATED_BFMER0_INFO, 0);
+		rtw_write16(rtwdev, REG_ASSOCIATED_BFMER0_INFO + 4, 0);
+		rtw_write16(rtwdev, REG_TX_CSI_RPT_PARAM_BW20, 0);
+		break;
+	case 1:
+		rtw_write32(rtwdev, REG_ASSOCIATED_BFMER1_INFO, 0);
+		rtw_write16(rtwdev, REG_ASSOCIATED_BFMER1_INFO + 4, 0);
+		rtw_write16(rtwdev, REG_TX_CSI_RPT_PARAM_BW20 + 2, 0);
+		break;
+	}
+
+	clear_bit(bfee->su_reg_index, bfinfo->bfer_su_reg_maping);
+	bfee->su_reg_index = 0xFF;
+}
+
+void rtw_bf_remove_bfee_mu(struct rtw_dev *rtwdev,
+			   struct rtw_bfee *bfee)
+{
+	struct rtw_bf_info *bfinfo = &rtwdev->bf_info;
+
+	rtw_write8(rtwdev, REG_SND_PTCL_CTRL, RTW_SND_CTRL_REMOVE);
+
+	rtw_bf_del_bfer_entry_mu(rtwdev);
+
+	if (bfinfo->bfer_su_cnt == 0 && bfinfo->bfer_mu_cnt == 0)
+		rtw_bf_del_sounding(rtwdev);
+}
+
+void rtw_bf_set_gid_table(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
+			  struct ieee80211_bss_conf *conf)
+{
+	struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
+	struct rtw_bfee *bfee = &rtwvif->bfee;
+	struct cfg_mumimo_para param;
+
+	if (bfee->role != RTW_BFEE_MU) {
+		rtw_dbg(rtwdev, RTW_DBG_BF, "this vif is not mu bfee\n");
+		return;
+	}
+
+	param.grouping_bitmap = 0;
+	param.mu_tx_en = 0;
+	memset(param.sounding_sts, 0, 6);
+	memcpy(param.given_gid_tab, conf->mu_group.membership, 8);
+	memcpy(param.given_user_pos, conf->mu_group.position, 16);
+	rtw_dbg(rtwdev, RTW_DBG_BF, "STA0: gid_valid=0x%x, user_position_l=0x%x, user_position_h=0x%x\n",
+		param.given_gid_tab[0], param.given_user_pos[0],
+		param.given_user_pos[1]);
+
+	rtw_dbg(rtwdev, RTW_DBG_BF, "STA1: gid_valid=0x%x, user_position_l=0x%x, user_position_h=0x%x\n",
+		param.given_gid_tab[1], param.given_user_pos[2],
+		param.given_user_pos[3]);
+
+	rtw_bf_cfg_mu_bfee(rtwdev, &param);
+}
+
+void rtw_bf_phy_init(struct rtw_dev *rtwdev)
+{
+	u8 tmp8;
+	u32 tmp32;
+	u8 retry_limit = 0xA;
+	u8 ndpa_rate = 0x10;
+	u8 ack_policy = 3;
+
+	tmp32 = rtw_read32(rtwdev, REG_MU_TX_CTL);
+	/* Enable P1 aggr new packet according to P0 transfer time */
+	tmp32 |= BIT_MU_P1_WAIT_STATE_EN;
+	/* MU Retry Limit */
+	tmp32 &= ~BIT_MASK_R_MU_RL;
+	tmp32 |= (retry_limit << BIT_SHIFT_R_MU_RL) & BIT_MASK_R_MU_RL;
+	/* Disable Tx MU-MIMO until sounding done */
+	tmp32 &= ~BIT_EN_MU_MIMO;
+	/* Clear validity of MU STAs */
+	tmp32 &= ~BIT_MASK_R_MU_TABLE_VALID;
+	rtw_write32(rtwdev, REG_MU_TX_CTL, tmp32);
+
+	/* MU-MIMO Option as default value */
+	tmp8 = ack_policy << BIT_SHIFT_WMAC_TXMU_ACKPOLICY;
+	tmp8 |= BIT_WMAC_TXMU_ACKPOLICY_EN;
+	rtw_write8(rtwdev, REG_WMAC_MU_BF_OPTION, tmp8);
+
+	/* MU-MIMO Control as default value */
+	rtw_write16(rtwdev, REG_WMAC_MU_BF_CTL, 0);
+	/* Set MU NDPA rate & BW source */
+	rtw_write32_set(rtwdev, REG_TXBF_CTRL, BIT_USE_NDPA_PARAMETER);
+	/* Set NDPA Rate */
+	rtw_write8(rtwdev, REG_NDPA_OPT_CTRL, ndpa_rate);
+
+	rtw_write32_mask(rtwdev, REG_BBPSF_CTRL, BIT_MASK_CSI_RATE,
+			 DESC_RATE6M);
+}
+
+void rtw_bf_cfg_csi_rate(struct rtw_dev *rtwdev, u8 rssi, u8 cur_rate,
+			 u8 fixrate_en, u8 *new_rate)
+{
+	u32 csi_cfg;
+	u16 cur_rrsr;
+
+	csi_cfg = rtw_read32(rtwdev, REG_BBPSF_CTRL) & ~BIT_MASK_CSI_RATE;
+	cur_rrsr = rtw_read16(rtwdev, REG_RRSR);
+
+	if (rssi >= 40) {
+		if (cur_rate != DESC_RATE54M) {
+			cur_rrsr |= BIT(DESC_RATE54M);
+			csi_cfg |= (DESC_RATE54M & BIT_MASK_CSI_RATE_VAL) <<
+				   BIT_SHIFT_CSI_RATE;
+			rtw_write16(rtwdev, REG_RRSR, cur_rrsr);
+			rtw_write32(rtwdev, REG_BBPSF_CTRL, csi_cfg);
+		}
+		*new_rate = DESC_RATE54M;
+	} else {
+		if (cur_rate != DESC_RATE24M) {
+			cur_rrsr &= ~BIT(DESC_RATE54M);
+			csi_cfg |= (DESC_RATE54M & BIT_MASK_CSI_RATE_VAL) <<
+				   BIT_SHIFT_CSI_RATE;
+			rtw_write16(rtwdev, REG_RRSR, cur_rrsr);
+			rtw_write32(rtwdev, REG_BBPSF_CTRL, csi_cfg);
+		}
+		*new_rate = DESC_RATE24M;
+	}
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/bf.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/bf.h
@@ -0,0 +1,114 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2018-2019  Realtek Corporation.
+ */
+
+#ifndef __RTW_BF_H_
+#define __RTW_BF_H_
+
+#define REG_TXBF_CTRL		0x042C
+#define REG_RRSR		0x0440
+#define REG_NDPA_OPT_CTRL	0x045F
+
+#define REG_ASSOCIATED_BFMER0_INFO	0x06E4
+#define REG_ASSOCIATED_BFMER1_INFO	0x06EC
+#define REG_TX_CSI_RPT_PARAM_BW20	0x06F4
+#define REG_SND_PTCL_CTRL		0x0718
+#define REG_MU_TX_CTL			0x14C0
+#define REG_MU_STA_GID_VLD		0x14C4
+#define REG_MU_STA_USER_POS_INFO	0x14C8
+#define REG_CSI_RRSR			0x1678
+#define REG_WMAC_MU_BF_OPTION		0x167C
+#define REG_WMAC_MU_BF_CTL		0x1680
+
+#define BIT_WMAC_USE_NDPARATE			BIT(30)
+#define BIT_WMAC_TXMU_ACKPOLICY_EN		BIT(6)
+#define BIT_USE_NDPA_PARAMETER			BIT(30)
+#define BIT_MU_P1_WAIT_STATE_EN			BIT(16)
+#define BIT_EN_MU_MIMO				BIT(7)
+
+#define R_MU_RL				0xf
+#define BIT_SHIFT_R_MU_RL		12
+#define BIT_SHIFT_WMAC_TXMU_ACKPOLICY	4
+#define BIT_SHIFT_CSI_RATE		24
+
+#define BIT_MASK_R_MU_RL (R_MU_RL << BIT_SHIFT_R_MU_RL)
+#define BIT_MASK_R_MU_TABLE_VALID	0x3f
+#define BIT_MASK_CSI_RATE_VAL		0x3F
+#define BIT_MASK_CSI_RATE (BIT_MASK_CSI_RATE_VAL << BIT_SHIFT_CSI_RATE)
+
+#define BIT_RXFLTMAP0_ACTIONNOACK	BIT(14)
+#define BIT_RXFLTMAP1_BF		(BIT(4) | BIT(5))
+#define BIT_RXFLTMAP1_BF_REPORT_POLL	BIT(4)
+#define BIT_RXFLTMAP4_BF_REPORT_POLL	BIT(4)
+
+#define RTW_NDP_RX_STANDBY_TIME	0x70
+#define RTW_SND_CTRL_REMOVE	0xD8
+#define RTW_SND_CTRL_SOUNDING	0xDB
+
+enum csi_seg_len {
+	HAL_CSI_SEG_4K = 0,
+	HAL_CSI_SEG_8K = 1,
+	HAL_CSI_SEG_11K = 2,
+};
+
+struct cfg_mumimo_para {
+	u8 sounding_sts[6];
+	u16 grouping_bitmap;
+	u8 mu_tx_en;
+	u32 given_gid_tab[2];
+	u32 given_user_pos[4];
+};
+
+struct mu_bfer_init_para {
+	u16 paid;
+	u16 csi_para;
+	u16 my_aid;
+	enum csi_seg_len csi_length_sel;
+	u8 bfer_address[ETH_ALEN];
+};
+
+void rtw_bf_disassoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
+		     struct ieee80211_bss_conf *bss_conf);
+void rtw_bf_assoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
+		  struct ieee80211_bss_conf *bss_conf);
+void rtw_bf_init_bfer_entry_mu(struct rtw_dev *rtwdev,
+			       struct mu_bfer_init_para *param);
+void rtw_bf_cfg_sounding(struct rtw_dev *rtwdev, struct rtw_vif *vif,
+			 enum rtw_trx_desc_rate rate);
+void rtw_bf_cfg_mu_bfee(struct rtw_dev *rtwdev, struct cfg_mumimo_para *param);
+void rtw_bf_del_bfer_entry_mu(struct rtw_dev *rtwdev);
+void rtw_bf_del_sounding(struct rtw_dev *rtwdev);
+void rtw_bf_enable_bfee_su(struct rtw_dev *rtwdev, struct rtw_vif *vif,
+			   struct rtw_bfee *bfee);
+void rtw_bf_enable_bfee_mu(struct rtw_dev *rtwdev, struct rtw_vif *vif,
+			   struct rtw_bfee *bfee);
+void rtw_bf_remove_bfee_su(struct rtw_dev *rtwdev, struct rtw_bfee *bfee);
+void rtw_bf_remove_bfee_mu(struct rtw_dev *rtwdev, struct rtw_bfee *bfee);
+void rtw_bf_set_gid_table(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
+			  struct ieee80211_bss_conf *conf);
+void rtw_bf_phy_init(struct rtw_dev *rtwdev);
+void rtw_bf_cfg_csi_rate(struct rtw_dev *rtwdev, u8 rssi, u8 cur_rate,
+			 u8 fixrate_en, u8 *new_rate);
+static inline void rtw_chip_config_bfee(struct rtw_dev *rtwdev, struct rtw_vif *vif,
+					struct rtw_bfee *bfee, bool enable)
+{
+	if (rtwdev->chip->ops->config_bfee)
+		rtwdev->chip->ops->config_bfee(rtwdev, vif, bfee, enable);
+}
+
+static inline void rtw_chip_set_gid_table(struct rtw_dev *rtwdev,
+					  struct ieee80211_vif *vif,
+					  struct ieee80211_bss_conf *conf)
+{
+	if (rtwdev->chip->ops->set_gid_table)
+		rtwdev->chip->ops->set_gid_table(rtwdev, vif, conf);
+}
+
+static inline void rtw_chip_cfg_csi_rate(struct rtw_dev *rtwdev, u8 rssi, u8 cur_rate,
+					 u8 fixrate_en, u8 *new_rate)
+{
+	if (rtwdev->chip->ops->cfg_csi_rate)
+		rtwdev->chip->ops->cfg_csi_rate(rtwdev, rssi, cur_rate,
+						fixrate_en, new_rate);
+}
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/coex.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/coex.c
@@ -383,9 +383,9 @@
 	u8 rssi_step;
 	u8 rssi;
 
-	scan = rtw_flag_check(rtwdev, RTW_FLAG_SCANNING);
+	scan = test_bit(RTW_FLAG_SCANNING, rtwdev->flags);
 	coex_stat->wl_connected = !!rtwdev->sta_cnt;
-	coex_stat->wl_gl_busy = rtw_flag_check(rtwdev, RTW_FLAG_BUSY_TRAFFIC);
+	coex_stat->wl_gl_busy = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
 
 	if (stats->tx_throughput > stats->rx_throughput)
 		coex_stat->wl_tput_dir = COEX_WL_TPUT_TX;
@@ -748,10 +748,18 @@
 
 static void rtw_coex_coex_ctrl_owner(struct rtw_dev *rtwdev, bool wifi_control)
 {
-	if (wifi_control)
+	struct rtw_chip_info *chip = rtwdev->chip;
+	const struct rtw_hw_reg *btg_reg = chip->btg_reg;
+
+	if (wifi_control) {
 		rtw_write32_set(rtwdev, REG_SYS_SDIO_CTRL, BIT_LTE_MUX_CTRL_PATH);
-	else
+		if (btg_reg)
+			rtw_write8_set(rtwdev, btg_reg->addr, btg_reg->mask);
+	} else {
 		rtw_write32_clr(rtwdev, REG_SYS_SDIO_CTRL, BIT_LTE_MUX_CTRL_PATH);
+		if (btg_reg)
+			rtw_write8_clr(rtwdev, btg_reg->addr, btg_reg->mask);
+	}
 }
 
 static void rtw_coex_set_gnt_bt(struct rtw_dev *rtwdev, u8 state)
@@ -810,8 +818,6 @@
 static void rtw_coex_power_save_state(struct rtw_dev *rtwdev, u8 ps_type,
 				      u8 lps_val, u8 rpwm_val)
 {
-	struct rtw_lps_conf *lps_conf = &rtwdev->lps_conf;
-	struct rtw_vif *rtwvif;
 	struct rtw_coex *coex = &rtwdev->coex;
 	struct rtw_coex_stat *coex_stat = &coex->stat;
 	u8 lps_mode = 0x0;
@@ -823,18 +829,14 @@
 		/* recover to original 32k low power setting */
 		coex_stat->wl_force_lps_ctrl = false;
 
-		rtwvif = lps_conf->rtwvif;
-		if (rtwvif && rtw_in_lps(rtwdev))
-			rtw_leave_lps(rtwdev, rtwvif);
+		rtw_leave_lps(rtwdev);
 		break;
 	case COEX_PS_LPS_OFF:
 		coex_stat->wl_force_lps_ctrl = true;
 		if (lps_mode)
 			rtw_fw_coex_tdma_type(rtwdev, 0x8, 0, 0, 0, 0);
 
-		rtwvif = lps_conf->rtwvif;
-		if (rtwvif && rtw_in_lps(rtwdev))
-			rtw_leave_lps(rtwdev, rtwvif);
+		rtw_leave_lps(rtwdev);
 		break;
 	default:
 		break;
@@ -1308,6 +1310,7 @@
 	struct rtw_chip_info *chip = rtwdev->chip;
 	bool wl_hi_pri = false;
 	u8 table_case, tdma_case;
+	u32 slot_type = 0;
 
 	if (coex_stat->wl_linkscan_proc || coex_stat->wl_hi_pri_task1 ||
 	    coex_stat->wl_hi_pri_task2)
@@ -1318,14 +1321,16 @@
 		if (wl_hi_pri) {
 			table_case = 15;
 			if (coex_stat->bt_a2dp_exist &&
-			    !coex_stat->bt_pan_exist)
+			    !coex_stat->bt_pan_exist) {
+				slot_type = TDMA_4SLOT;
 				tdma_case = 11;
-			else if (coex_stat->wl_hi_pri_task1)
+			} else if (coex_stat->wl_hi_pri_task1) {
 				tdma_case = 6;
-			else if (!coex_stat->bt_page)
+			} else if (!coex_stat->bt_page) {
 				tdma_case = 8;
-			else
+			} else {
 				tdma_case = 9;
+			}
 		} else if (coex_stat->wl_connected) {
 			table_case = 10;
 			tdma_case = 10;
@@ -1346,12 +1351,15 @@
 				tdma_case = 108;
 			else
 				tdma_case = 109;
+		} else if (coex_stat->wl_gl_busy) {
+			table_case = 114;
+			tdma_case = 121;
 		} else if (coex_stat->wl_connected) {
-			table_case = 101;
-			tdma_case = 110;
-		} else {
 			table_case = 100;
 			tdma_case = 100;
+		} else {
+			table_case = 101;
+			tdma_case = 100;
 		}
 	}
 
@@ -1361,7 +1369,7 @@
 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
 	rtw_coex_table(rtwdev, table_case);
-	rtw_coex_tdma(rtwdev, false, tdma_case);
+	rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
 }
 
 static void rtw_coex_action_bt_hfp(struct rtw_dev *rtwdev)
@@ -1475,13 +1483,13 @@
 
 	if (efuse->share_ant) {
 		/* Shared-Ant */
+		slot_type = TDMA_4SLOT;
+
 		if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0)
 			table_case = 10;
 		else
 			table_case = 9;
 
-		slot_type = TDMA_4SLOT;
-
 		if (coex_stat->wl_gl_busy)
 			tdma_case = 13;
 		else
@@ -1585,13 +1593,14 @@
 
 	if (efuse->share_ant) {
 		/* Shared-Ant */
+		slot_type = TDMA_4SLOT;
+
 		if (coex_stat->bt_ble_exist)
 			table_case = 26;
 		else
 			table_case = 9;
 
 		if (coex_stat->wl_gl_busy) {
-			slot_type = TDMA_4SLOT;
 			tdma_case = 13;
 		} else {
 			tdma_case = 14;
@@ -1794,10 +1803,12 @@
 	struct rtw_efuse *efuse = &rtwdev->efuse;
 	struct rtw_chip_info *chip = rtwdev->chip;
 	u8 table_case, tdma_case;
+	u32 slot_type = 0;
 
 	if (efuse->share_ant) {
 		/* Shared-Ant */
 		if (coex_stat->bt_a2dp_exist) {
+			slot_type = TDMA_4SLOT;
 			table_case = 9;
 			tdma_case = 11;
 		} else {
@@ -1818,7 +1829,7 @@
 	rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
 	rtw_coex_table(rtwdev, table_case);
-	rtw_coex_tdma(rtwdev, false, tdma_case);
+	rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
 }
 
 static void rtw_coex_action_wl_not_connected(struct rtw_dev *rtwdev)
@@ -1904,6 +1915,9 @@
 
 	lockdep_assert_held(&rtwdev->mutex);
 
+	if (!test_bit(RTW_FLAG_RUNNING, rtwdev->flags))
+		return;
+
 	coex_dm->reason = reason;
 
 	/* update wifi_link_info_ext variable */
@@ -1917,7 +1931,8 @@
 	if (coex_stat->wl_under_ips)
 		return;
 
-	if (coex->freeze && !coex_stat->bt_setup_link)
+	if (coex->freeze && coex_dm->reason == COEX_RSN_BTINFO &&
+	    !coex_stat->bt_setup_link)
 		return;
 
 	coex_stat->cnt_wl[COEX_CNT_WL_COEXRUN]++;
@@ -2500,3 +2515,495 @@
 	rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
 	mutex_unlock(&rtwdev->mutex);
 }
+
+#ifdef CONFIG_RTW88_DEBUGFS
+#define INFO_SIZE	80
+
+#define case_BTINFO(src) \
+	case COEX_BTINFO_SRC_##src: return #src
+
+static const char *rtw_coex_get_bt_info_src_string(u8 bt_info_src)
+{
+	switch (bt_info_src) {
+	case_BTINFO(WL_FW);
+	case_BTINFO(BT_RSP);
+	case_BTINFO(BT_ACT);
+	default:
+		return "Unknown";
+	}
+}
+
+#define case_RSN(src) \
+	case COEX_RSN_##src: return #src
+
+static const char *rtw_coex_get_reason_string(u8 reason)
+{
+	switch (reason) {
+	case_RSN(2GSCANSTART);
+	case_RSN(5GSCANSTART);
+	case_RSN(SCANFINISH);
+	case_RSN(2GSWITCHBAND);
+	case_RSN(5GSWITCHBAND);
+	case_RSN(2GCONSTART);
+	case_RSN(5GCONSTART);
+	case_RSN(2GCONFINISH);
+	case_RSN(5GCONFINISH);
+	case_RSN(2GMEDIA);
+	case_RSN(5GMEDIA);
+	case_RSN(MEDIADISCON);
+	case_RSN(BTINFO);
+	case_RSN(LPS);
+	case_RSN(WLSTATUS);
+	default:
+		return "Unknown";
+	}
+}
+
+static int rtw_coex_addr_info(struct rtw_dev *rtwdev,
+			      const struct rtw_reg_domain *reg,
+			      char addr_info[], int n)
+{
+	const char *rf_prefix = "";
+	const char *sep = n == 0 ? "" : "/ ";
+	int ffs, fls;
+	int max_fls;
+
+	if (INFO_SIZE - n <= 0)
+		return 0;
+
+	switch (reg->domain) {
+	case RTW_REG_DOMAIN_MAC32:
+		max_fls = 31;
+		break;
+	case RTW_REG_DOMAIN_MAC16:
+		max_fls = 15;
+		break;
+	case RTW_REG_DOMAIN_MAC8:
+		max_fls = 7;
+		break;
+	case RTW_REG_DOMAIN_RF_A:
+	case RTW_REG_DOMAIN_RF_B:
+		rf_prefix = "RF_";
+		max_fls = 19;
+		break;
+	default:
+		return 0;
+	}
+
+	ffs = __ffs(reg->mask);
+	fls = __fls(reg->mask);
+
+	if (ffs == 0 && fls == max_fls)
+		return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x",
+				 sep, rf_prefix, reg->addr);
+	else if (ffs == fls)
+		return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x[%d]",
+				 sep, rf_prefix, reg->addr, ffs);
+	else
+		return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x[%d:%d]",
+				 sep, rf_prefix, reg->addr, fls, ffs);
+}
+
+static int rtw_coex_val_info(struct rtw_dev *rtwdev,
+			     const struct rtw_reg_domain *reg,
+			     char val_info[], int n)
+{
+	const char *sep = n == 0 ? "" : "/ ";
+	u8 rf_path;
+
+	if (INFO_SIZE - n <= 0)
+		return 0;
+
+	switch (reg->domain) {
+	case RTW_REG_DOMAIN_MAC32:
+		return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,
+				 rtw_read32_mask(rtwdev, reg->addr, reg->mask));
+	case RTW_REG_DOMAIN_MAC16:
+		return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,
+				 rtw_read16_mask(rtwdev, reg->addr, reg->mask));
+	case RTW_REG_DOMAIN_MAC8:
+		return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,
+				 rtw_read8_mask(rtwdev, reg->addr, reg->mask));
+	case RTW_REG_DOMAIN_RF_A:
+		rf_path = RF_PATH_A;
+		break;
+	case RTW_REG_DOMAIN_RF_B:
+		rf_path = RF_PATH_B;
+		break;
+	default:
+		return 0;
+	}
+
+	/* only RF go through here */
+	return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,
+			 rtw_read_rf(rtwdev, rf_path, reg->addr, reg->mask));
+}
+
+static void rtw_coex_set_coexinfo_hw(struct rtw_dev *rtwdev, struct seq_file *m)
+{
+	struct rtw_chip_info *chip = rtwdev->chip;
+	const struct rtw_reg_domain *reg;
+	char addr_info[INFO_SIZE];
+	int n_addr = 0;
+	char val_info[INFO_SIZE];
+	int n_val = 0;
+	int i;
+
+	for (i = 0; i < chip->coex_info_hw_regs_num; i++) {
+		reg = &chip->coex_info_hw_regs[i];
+
+		n_addr += rtw_coex_addr_info(rtwdev, reg, addr_info, n_addr);
+		n_val += rtw_coex_val_info(rtwdev, reg, val_info, n_val);
+
+		if (reg->domain == RTW_REG_DOMAIN_NL) {
+			seq_printf(m, "%-40s = %s\n", addr_info, val_info);
+			n_addr = 0;
+			n_val = 0;
+		}
+	}
+
+	if (n_addr != 0 && n_val != 0)
+		seq_printf(m, "%-40s = %s\n", addr_info, val_info);
+}
+
+static bool rtw_coex_get_bt_reg(struct rtw_dev *rtwdev,
+				u8 type, u16 addr, u16 *val)
+{
+	struct rtw_coex_info_req req = {0};
+	struct sk_buff *skb;
+	__le16 le_addr;
+	u8 *payload;
+
+	le_addr = cpu_to_le16(addr);
+	req.op_code = BT_MP_INFO_OP_READ_REG;
+	req.para1 = type;
+	req.para2 = le16_get_bits(le_addr, GENMASK(7, 0));
+	req.para3 = le16_get_bits(le_addr, GENMASK(15, 8));
+	skb = rtw_coex_info_request(rtwdev, &req);
+	if (!skb) {
+		*val = 0xeaea;
+		return false;
+	}
+
+	payload = get_payload_from_coex_resp(skb);
+	*val = GET_COEX_RESP_BT_REG_VAL(payload);
+
+	return true;
+}
+
+static bool rtw_coex_get_bt_patch_version(struct rtw_dev *rtwdev,
+					  u32 *patch_version)
+{
+	struct rtw_coex_info_req req = {0};
+	struct sk_buff *skb;
+	u8 *payload;
+	bool ret = false;
+
+	req.op_code = BT_MP_INFO_OP_PATCH_VER;
+	skb = rtw_coex_info_request(rtwdev, &req);
+	if (!skb)
+		goto out;
+
+	payload = get_payload_from_coex_resp(skb);
+	*patch_version = GET_COEX_RESP_BT_PATCH_VER(payload);
+	ret = true;
+
+out:
+	return ret;
+}
+
+static bool rtw_coex_get_bt_supported_version(struct rtw_dev *rtwdev,
+					      u32 *supported_version)
+{
+	struct rtw_coex_info_req req = {0};
+	struct sk_buff *skb;
+	u8 *payload;
+	bool ret = false;
+
+	req.op_code = BT_MP_INFO_OP_SUPP_VER;
+	skb = rtw_coex_info_request(rtwdev, &req);
+	if (!skb)
+		goto out;
+
+	payload = get_payload_from_coex_resp(skb);
+	*supported_version = GET_COEX_RESP_BT_SUPP_VER(payload);
+	ret = true;
+
+out:
+	return ret;
+}
+
+static bool rtw_coex_get_bt_supported_feature(struct rtw_dev *rtwdev,
+					      u32 *supported_feature)
+{
+	struct rtw_coex_info_req req = {0};
+	struct sk_buff *skb;
+	u8 *payload;
+	bool ret = false;
+
+	req.op_code = BT_MP_INFO_OP_SUPP_FEAT;
+	skb = rtw_coex_info_request(rtwdev, &req);
+	if (!skb)
+		goto out;
+
+	payload = get_payload_from_coex_resp(skb);
+	*supported_feature = GET_COEX_RESP_BT_SUPP_FEAT(payload);
+	ret = true;
+
+out:
+	return ret;
+}
+
+struct rtw_coex_sta_stat_iter_data {
+	struct rtw_vif *rtwvif;
+	struct seq_file *file;
+};
+
+static void rtw_coex_sta_stat_iter(void *data, struct ieee80211_sta *sta)
+{
+	struct rtw_coex_sta_stat_iter_data *sta_iter_data = data;
+	struct rtw_vif *rtwvif = sta_iter_data->rtwvif;
+	struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
+	struct seq_file *m = sta_iter_data->file;
+	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
+	u8 rssi;
+
+	if (si->vif != vif)
+		return;
+
+	rssi = ewma_rssi_read(&si->avg_rssi);
+	seq_printf(m, "\tPeer %3d\n", si->mac_id);
+	seq_printf(m, "\t\t%-24s = %d\n", "RSSI", rssi);
+	seq_printf(m, "\t\t%-24s = %d\n", "BW mode", si->bw_mode);
+}
+
+struct rtw_coex_vif_stat_iter_data {
+	struct rtw_dev *rtwdev;
+	struct seq_file *file;
+};
+
+static void rtw_coex_vif_stat_iter(void *data, u8 *mac,
+				   struct ieee80211_vif *vif)
+{
+	struct rtw_coex_vif_stat_iter_data *vif_iter_data = data;
+	struct rtw_coex_sta_stat_iter_data sta_iter_data;
+	struct rtw_dev *rtwdev = vif_iter_data->rtwdev;
+	struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
+	struct seq_file *m = vif_iter_data->file;
+	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+
+	seq_printf(m, "Iface on Port (%d)\n", rtwvif->port);
+	seq_printf(m, "\t%-32s = %d\n",
+		   "Beacon interval", bss_conf->beacon_int);
+	seq_printf(m, "\t%-32s = %d\n",
+		   "Network Type", rtwvif->net_type);
+
+	sta_iter_data.rtwvif = rtwvif;
+	sta_iter_data.file = m;
+	rtw_iterate_stas_atomic(rtwdev, rtw_coex_sta_stat_iter,
+				&sta_iter_data);
+}
+
+void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m)
+{
+	struct rtw_chip_info *chip = rtwdev->chip;
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+	struct rtw_coex *coex = &rtwdev->coex;
+	struct rtw_coex_stat *coex_stat = &coex->stat;
+	struct rtw_coex_dm *coex_dm = &coex->dm;
+	struct rtw_hal *hal = &rtwdev->hal;
+	struct rtw_efuse *efuse = &rtwdev->efuse;
+	struct rtw_fw_state *fw = &rtwdev->fw;
+	struct rtw_coex_vif_stat_iter_data vif_iter_data;
+	u8 reason = coex_dm->reason;
+	u8 sys_lte;
+	u16 score_board_WB, score_board_BW;
+	u32 wl_reg_6c0, wl_reg_6c4, wl_reg_6c8, wl_reg_778, wl_reg_6cc;
+	u32 lte_coex, bt_coex;
+	u32 bt_hi_pri, bt_lo_pri;
+	int i;
+
+	score_board_BW = rtw_coex_read_scbd(rtwdev);
+	score_board_WB = coex_stat->score_board;
+	wl_reg_6c0 = rtw_read32(rtwdev, 0x6c0);
+	wl_reg_6c4 = rtw_read32(rtwdev, 0x6c4);
+	wl_reg_6c8 = rtw_read32(rtwdev, 0x6c8);
+	wl_reg_6cc = rtw_read32(rtwdev, 0x6cc);
+	wl_reg_778 = rtw_read32(rtwdev, 0x778);
+	bt_hi_pri = rtw_read32(rtwdev, 0x770);
+	bt_lo_pri = rtw_read32(rtwdev, 0x774);
+	rtw_write8(rtwdev, 0x76e, 0xc);
+	sys_lte = rtw_read8(rtwdev, 0x73);
+	lte_coex = rtw_coex_read_indirect_reg(rtwdev, 0x38);
+	bt_coex = rtw_coex_read_indirect_reg(rtwdev, 0x54);
+
+	if (!coex_stat->bt_disabled && !coex_stat->bt_mailbox_reply) {
+		rtw_coex_get_bt_supported_version(rtwdev,
+				&coex_stat->bt_supported_version);
+		rtw_coex_get_bt_patch_version(rtwdev, &coex_stat->patch_ver);
+		rtw_coex_get_bt_supported_feature(rtwdev,
+				&coex_stat->bt_supported_feature);
+		rtw_coex_get_bt_reg(rtwdev, 3, 0xae, &coex_stat->bt_reg_vendor_ae);
+		rtw_coex_get_bt_reg(rtwdev, 3, 0xac, &coex_stat->bt_reg_vendor_ac);
+
+		if (coex_stat->patch_ver != 0)
+			coex_stat->bt_mailbox_reply = true;
+	}
+
+	seq_printf(m, "**********************************************\n");
+	seq_printf(m, "\t\tBT Coexist info %x\n", chip->id);
+	seq_printf(m, "**********************************************\n");
+	seq_printf(m, "%-40s = %s/ %d\n",
+		   "Mech/ RFE",
+		   efuse->share_ant ? "Shared" : "Non-Shared",
+		   efuse->rfe_option);
+	seq_printf(m, "%-40s = %08x/ 0x%02x/ 0x%08x %s\n",
+		   "Coex Ver/ BT Dez/ BT Rpt",
+		   chip->coex_para_ver, chip->bt_desired_ver,
+		   coex_stat->bt_supported_version,
+		   coex_stat->bt_disabled ? "(BT disabled)" :
+		   coex_stat->bt_supported_version >= chip->bt_desired_ver ?
+		   "(Match)" : "(Mismatch)");
+	seq_printf(m, "%-40s = %s/ %u/ %d\n",
+		   "Role/ RoleSwCnt/ IgnWL/ Feature",
+		   coex_stat->bt_slave ? "Slave" : "Master",
+		   coex_stat->cnt_bt[COEX_CNT_BT_ROLESWITCH],
+		   coex_dm->ignore_wl_act);
+	seq_printf(m, "%-40s = %u.%u/ 0x%x/ %c\n",
+		   "WL FW/ BT FW/ KT",
+		   fw->version, fw->sub_version,
+		   coex_stat->patch_ver, coex_stat->kt_ver + 65);
+	seq_printf(m, "%-40s = %u/ %u/ %u/ ch-(%u)\n",
+		   "AFH Map",
+		   coex_dm->wl_ch_info[0], coex_dm->wl_ch_info[1],
+		   coex_dm->wl_ch_info[2], hal->current_channel);
+
+	seq_printf(m, "**********************************************\n");
+	seq_printf(m, "\t\tBT Status\n");
+	seq_printf(m, "**********************************************\n");
+	seq_printf(m, "%-40s = %s/ %ddBm/ %u/ %u\n",
+		   "BT status/ rssi/ retry/ pop",
+		   coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE ? "non-conn" :
+		   coex_dm->bt_status == COEX_BTSTATUS_CON_IDLE ? "conn-idle" : "busy",
+		   coex_stat->bt_rssi - 100,
+		   coex_stat->cnt_bt[COEX_CNT_BT_RETRY],
+		   coex_stat->cnt_bt[COEX_CNT_BT_POPEVENT]);
+	seq_printf(m, "%-40s = %s%s%s%s%s (multi-link %d)\n",
+		   "Profiles",
+		   coex_stat->bt_a2dp_exist ? (coex_stat->bt_a2dp_sink ?
+					       "A2DP sink," : "A2DP,") : "",
+		   coex_stat->bt_hfp_exist ? "HFP," : "",
+		   coex_stat->bt_hid_exist ?
+		   (coex_stat->bt_ble_exist ? "HID(RCU)," :
+		    coex_stat->bt_hid_slot >= 2 ? "HID(4/18)" :
+		    "HID(2/18),") : "",
+		   coex_stat->bt_pan_exist ? coex_stat->bt_opp_exist ?
+		   "OPP," : "PAN," : "",
+		   coex_stat->bt_ble_voice ? "Voice," : "",
+		   coex_stat->bt_multi_link);
+	seq_printf(m, "%-40s = %u/ %u/ %u/ 0x%08x\n",
+		   "Reinit/ Relink/ IgnWl/ Feature",
+		   coex_stat->cnt_bt[COEX_CNT_BT_REINIT],
+		   coex_stat->cnt_bt[COEX_CNT_BT_SETUPLINK],
+		   coex_stat->cnt_bt[COEX_CNT_BT_IGNWLANACT],
+		   coex_stat->bt_supported_feature);
+	seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n",
+		   "Page/ Inq/ iqk/ iqk fail",
+		   coex_stat->cnt_bt[COEX_CNT_BT_PAGE],
+		   coex_stat->cnt_bt[COEX_CNT_BT_INQ],
+		   coex_stat->cnt_bt[COEX_CNT_BT_IQK],
+		   coex_stat->cnt_bt[COEX_CNT_BT_IQKFAIL]);
+	seq_printf(m, "%-40s = 0x%04x/ 0x%04x/ 0x%04x/ 0x%04x\n",
+		   "0xae/ 0xac/ score board (W->B)/ (B->W)",
+		   coex_stat->bt_reg_vendor_ae,
+		   coex_stat->bt_reg_vendor_ac,
+		   score_board_WB, score_board_BW);
+	seq_printf(m, "%-40s = %u/%u, %u/%u\n",
+		   "Hi-Pri TX/RX, Lo-Pri TX/RX",
+		   bt_hi_pri & 0xffff, bt_hi_pri >> 16,
+		   bt_lo_pri & 0xffff, bt_lo_pri >> 16);
+	for (i = 0; i < COEX_BTINFO_SRC_BT_IQK; i++)
+		seq_printf(m, "%-40s = %7ph\n",
+			   rtw_coex_get_bt_info_src_string(i),
+			   coex_stat->bt_info_c2h[i]);
+
+	seq_printf(m, "**********************************************\n");
+	seq_printf(m, "\t\tWiFi Status\n");
+	seq_printf(m, "**********************************************\n");
+	seq_printf(m, "%-40s = %d\n",
+		   "Scanning", test_bit(RTW_FLAG_SCANNING, rtwdev->flags));
+	seq_printf(m, "%-40s = %u/ TX %d Mbps/ RX %d Mbps\n",
+		   "G_busy/ TX/ RX",
+		   coex_stat->wl_gl_busy,
+		   rtwdev->stats.tx_throughput, rtwdev->stats.rx_throughput);
+	seq_printf(m, "%-40s = %u/ %u/ %u\n",
+		   "IPS/ Low Power/ PS mode",
+		   test_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags),
+		   test_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags),
+		   rtwdev->lps_conf.mode);
+
+	vif_iter_data.rtwdev = rtwdev;
+	vif_iter_data.file = m;
+	rtw_iterate_vifs_atomic(rtwdev, rtw_coex_vif_stat_iter, &vif_iter_data);
+
+	seq_printf(m, "**********************************************\n");
+	seq_printf(m, "\t\tMechanism\n");
+	seq_printf(m, "**********************************************\n");
+	seq_printf(m, "%-40s = %5ph (case-%d)\n",
+		   "TDMA",
+		   coex_dm->ps_tdma_para, coex_dm->cur_ps_tdma);
+	seq_printf(m, "%-40s = %d\n",
+		   "Timer base", coex_stat->tdma_timer_base);
+	seq_printf(m, "%-40s = %d/ 0x%08x/ 0x%08x/ 0x%08x\n",
+		   "Table/ 0x6c0/ 0x6c4/ 0x6c8",
+		   coex_dm->cur_table, wl_reg_6c0, wl_reg_6c4, wl_reg_6c8);
+	seq_printf(m, "%-40s = 0x%08x/ 0x%08x/ reason (%s)\n",
+		   "0x778/ 0x6cc/ Reason",
+		   wl_reg_778, wl_reg_6cc, rtw_coex_get_reason_string(reason));
+	seq_printf(m, "%-40s = %u/ %u/ %u/ %u/ %u\n",
+		   "Null All/ Retry/ Ack/ BT Empty/ BT Late",
+		   coex_stat->wl_fw_dbg_info[1], coex_stat->wl_fw_dbg_info[2],
+		   coex_stat->wl_fw_dbg_info[3], coex_stat->wl_fw_dbg_info[4],
+		   coex_stat->wl_fw_dbg_info[5]);
+	seq_printf(m, "%-40s = %u/ %u/ %s/ %u\n",
+		   "Cnt TDMA Toggle/ Lk 5ms/ Lk 5ms on/ FW",
+		   coex_stat->wl_fw_dbg_info[6],
+		   coex_stat->wl_fw_dbg_info[7],
+		   coex_stat->wl_slot_extend ? "Yes" : "No",
+		   coex_stat->cnt_wl[COEX_CNT_WL_FW_NOTIFY]);
+
+	seq_printf(m, "**********************************************\n");
+	seq_printf(m, "\t\tHW setting\n");
+	seq_printf(m, "**********************************************\n");
+	seq_printf(m, "%-40s = %s/ %s\n",
+		   "LTE Coex/ Path Owner",
+		   lte_coex & BIT(7) ? "ON" : "OFF",
+		   sys_lte & BIT(2) ? "WL" : "BT");
+	seq_printf(m, "%-40s = RF:%s_BB:%s/ RF:%s_BB:%s/ %s\n",
+		   "GNT_WL_CTRL/ GNT_BT_CTRL/ Dbg",
+		   lte_coex & BIT(12) ? "SW" : "HW",
+		   lte_coex & BIT(8) ? "SW" : "HW",
+		   lte_coex & BIT(14) ? "SW" : "HW",
+		   lte_coex & BIT(10) ? "SW" : "HW",
+		   sys_lte & BIT(3) ? "On" : "Off");
+	seq_printf(m, "%-40s = %lu/ %lu\n",
+		   "GNT_WL/ GNT_BT",
+		   (bt_coex & BIT(2)) >> 2, (bt_coex & BIT(3)) >> 3);
+	seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n",
+		   "CRC OK CCK/ OFDM/ HT/ VHT",
+		   dm_info->cck_ok_cnt, dm_info->ofdm_ok_cnt,
+		   dm_info->ht_ok_cnt, dm_info->vht_ok_cnt);
+	seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n",
+		   "CRC ERR CCK/ OFDM/ HT/ VHT",
+		   dm_info->cck_err_cnt, dm_info->ofdm_err_cnt,
+		   dm_info->ht_err_cnt, dm_info->vht_err_cnt);
+	seq_printf(m, "%-40s = %s/ %s/ %s/ %u\n",
+		   "HiPr/ Locking/ Locked/ Noisy",
+		   coex_stat->wl_hi_pri_task1 ? "Y" : "N",
+		   coex_stat->wl_cck_lock ? "Y" : "N",
+		   coex_stat->wl_cck_lock_ever ? "Y" : "N",
+		   coex_stat->wl_noisy_level);
+
+	rtw_coex_set_coexinfo_hw(rtwdev, m);
+}
+#endif /* CONFIG_RTW88_DEBUGFS */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/coex.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/coex.h
@@ -46,6 +46,14 @@
 	   (__rssi__ == COEX_RSSI_STATE_LOW || \
 	    __rssi__ == COEX_RSSI_STATE_STAY_LOW ? true : false); })
 
+#define GET_COEX_RESP_BT_SUPP_VER(payload)				\
+	le64_get_bits(*((__le64 *)(payload)), GENMASK_ULL(39, 32))
+#define GET_COEX_RESP_BT_SUPP_FEAT(payload)				\
+	le64_get_bits(*((__le64 *)(payload)), GENMASK_ULL(39, 24))
+#define GET_COEX_RESP_BT_PATCH_VER(payload)				\
+	le64_get_bits(*((__le64 *)(payload)), GENMASK_ULL(55, 24))
+#define GET_COEX_RESP_BT_REG_VAL(payload)				\
+	le64_get_bits(*((__le64 *)(payload)), GENMASK_ULL(39, 24))
 #define GET_COEX_RESP_BT_SCAN_TYPE(payload)				\
 	le64_get_bits(*((__le64 *)(payload)), GENMASK(31, 24))
 
@@ -367,4 +375,6 @@
 void rtw_coex_switchband_notify(struct rtw_dev *rtwdev, u8 type);
 void rtw_coex_wl_status_change_notify(struct rtw_dev *rtwdev);
 
+void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m);
+
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/debug.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/debug.c
@@ -5,10 +5,12 @@
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #include "main.h"
+#include "coex.h"
 #include "sec.h"
 #include "fw.h"
 #include "debug.h"
 #include "phy.h"
+#include "sar.h"
 
 #ifdef CONFIG_RTW88_DEBUGFS
 
@@ -146,6 +148,8 @@
 {
 	int tmp_len;
 
+	memset(tmp, 0, size);
+
 	if (count < num)
 		return -EFAULT;
 
@@ -498,20 +502,40 @@
 	seq_printf(m, " VHT%uSMCS%u", n_ss, mcs_n);
 }
 
+static void rtw_print_rate(struct seq_file *m, u8 rate)
+{
+	switch (rate) {
+	case DESC_RATE1M...DESC_RATE11M:
+		rtw_print_cck_rate_txt(m, rate);
+		break;
+	case DESC_RATE6M...DESC_RATE54M:
+		rtw_print_ofdm_rate_txt(m, rate);
+		break;
+	case DESC_RATEMCS0...DESC_RATEMCS15:
+		rtw_print_ht_rate_txt(m, rate);
+		break;
+	case DESC_RATEVHT1SS_MCS0...DESC_RATEVHT2SS_MCS9:
+		rtw_print_vht_rate_txt(m, rate);
+		break;
+	default:
+		seq_printf(m, " Unknown rate=0x%x\n", rate);
+		break;
+	}
+}
+
 static int rtw_debugfs_get_tx_pwr_tbl(struct seq_file *m, void *v)
 {
 	struct rtw_debugfs_priv *debugfs_priv = m->private;
 	struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
 	struct rtw_hal *hal = &rtwdev->hal;
-	void (*print_rate)(struct seq_file *, u8) = NULL;
 	u8 path, rate;
 	struct rtw_power_params pwr_param = {0};
 	u8 bw = hal->current_band_width;
 	u8 ch = hal->current_channel;
 	u8 regd = rtwdev->regd.txpwr_regd;
 
-	seq_printf(m, "%-4s %-10s %-3s%6s %-4s %4s (%-4s %-4s)\n",
-		   "path", "rate", "pwr", "", "base", "", "byr", "lmt");
+	seq_printf(m, "%-4s %-10s %-3s%6s %-4s %4s (%-4s %-4s %-4s %-4s)\n",
+		   "path", "rate", "pwr", "", "base", "", "byr", "lmt", "sar", "rem");
 
 	mutex_lock(&hal->tx_power_mutex);
 	for (path = RF_PATH_A; path <= RF_PATH_B; path++) {
@@ -528,37 +552,20 @@
 			    rate < DESC_RATEVHT1SS_MCS0)
 				continue;
 
-			switch (rate) {
-			case DESC_RATE1M...DESC_RATE11M:
-				print_rate = rtw_print_cck_rate_txt;
-				break;
-			case DESC_RATE6M...DESC_RATE54M:
-				print_rate = rtw_print_ofdm_rate_txt;
-				break;
-			case DESC_RATEMCS0...DESC_RATEMCS15:
-				print_rate = rtw_print_ht_rate_txt;
-				break;
-			case DESC_RATEVHT1SS_MCS0...DESC_RATEVHT2SS_MCS9:
-				print_rate = rtw_print_vht_rate_txt;
-				break;
-			default:
-				print_rate = NULL;
-				break;
-			}
-
 			rtw_get_tx_power_params(rtwdev, path, rate, bw,
 						ch, regd, &pwr_param);
 
 			seq_printf(m, "%4c ", path + 'A');
-			if (print_rate)
-				print_rate(m, rate);
-			seq_printf(m, " %3u(0x%02x) %4u %4d (%4d %4d)\n",
+			rtw_print_rate(m, rate);
+			seq_printf(m, " %3u(0x%02x) %4u %4d (%4d %4d %4d %4d)\n",
 				   hal->tx_pwr_tbl[path][rate],
 				   hal->tx_pwr_tbl[path][rate],
 				   pwr_param.pwr_base,
-				   min_t(s8, pwr_param.pwr_offset,
-					 pwr_param.pwr_limit),
-				   pwr_param.pwr_offset, pwr_param.pwr_limit);
+				   min3(pwr_param.pwr_offset,
+					pwr_param.pwr_limit,
+					pwr_param.pwr_sar),
+				   pwr_param.pwr_offset, pwr_param.pwr_limit,
+				   pwr_param.pwr_sar, pwr_param.pwr_remnant);
 		}
 	}
 
@@ -567,6 +574,208 @@
 	return 0;
 }
 
+static int rtw_debugfs_get_phy_info(struct seq_file *m, void *v)
+{
+	struct rtw_debugfs_priv *debugfs_priv = m->private;
+	struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+	struct rtw_traffic_stats *stats = &rtwdev->stats;
+	struct rtw_pkt_count *last_cnt = &dm_info->last_pkt_count;
+	struct rtw_efuse *efuse = &rtwdev->efuse;
+	struct ewma_evm *ewma_evm = dm_info->ewma_evm;
+	struct ewma_snr *ewma_snr = dm_info->ewma_snr;
+	u8 ss, rate_id;
+
+	seq_puts(m, "==========[Common Info]========\n");
+	seq_printf(m, "Is link = %c\n", rtw_is_assoc(rtwdev) ? 'Y' : 'N');
+	seq_printf(m, "Current CH(fc) = %u\n", rtwdev->hal.current_channel);
+	seq_printf(m, "Current BW = %u\n", rtwdev->hal.current_band_width);
+	seq_printf(m, "Current IGI = 0x%x\n", dm_info->igi_history[0]);
+	seq_printf(m, "TP {Tx, Rx} = {%u, %u}Mbps\n\n",
+		   stats->tx_throughput, stats->rx_throughput);
+
+	seq_puts(m, "==========[Tx Phy Info]========\n");
+	seq_puts(m, "[Tx Rate] = ");
+	rtw_print_rate(m, dm_info->tx_rate);
+	seq_printf(m, "(0x%x)\n\n", dm_info->tx_rate);
+
+	seq_puts(m, "==========[Rx Phy Info]========\n");
+	seq_printf(m, "[Rx Beacon Count] = %u\n", last_cnt->num_bcn_pkt);
+	seq_puts(m, "[Rx Rate] = ");
+	rtw_print_rate(m, dm_info->curr_rx_rate);
+	seq_printf(m, "(0x%x)\n", dm_info->curr_rx_rate);
+
+	seq_puts(m, "[Rx Rate Count]:\n");
+	seq_printf(m, " * CCK = {%u, %u, %u, %u}\n",
+		   last_cnt->num_qry_pkt[DESC_RATE1M],
+		   last_cnt->num_qry_pkt[DESC_RATE2M],
+		   last_cnt->num_qry_pkt[DESC_RATE5_5M],
+		   last_cnt->num_qry_pkt[DESC_RATE11M]);
+
+	seq_printf(m, " * OFDM = {%u, %u, %u, %u, %u, %u, %u, %u}\n",
+		   last_cnt->num_qry_pkt[DESC_RATE6M],
+		   last_cnt->num_qry_pkt[DESC_RATE9M],
+		   last_cnt->num_qry_pkt[DESC_RATE12M],
+		   last_cnt->num_qry_pkt[DESC_RATE18M],
+		   last_cnt->num_qry_pkt[DESC_RATE24M],
+		   last_cnt->num_qry_pkt[DESC_RATE36M],
+		   last_cnt->num_qry_pkt[DESC_RATE48M],
+		   last_cnt->num_qry_pkt[DESC_RATE54M]);
+
+	for (ss = 0; ss < efuse->hw_cap.nss; ss++) {
+		rate_id = DESC_RATEMCS0 + ss * 8;
+		seq_printf(m, " * HT_MCS[%u:%u] = {%u, %u, %u, %u, %u, %u, %u, %u}\n",
+			   ss * 8, ss * 8 + 7,
+			   last_cnt->num_qry_pkt[rate_id],
+			   last_cnt->num_qry_pkt[rate_id + 1],
+			   last_cnt->num_qry_pkt[rate_id + 2],
+			   last_cnt->num_qry_pkt[rate_id + 3],
+			   last_cnt->num_qry_pkt[rate_id + 4],
+			   last_cnt->num_qry_pkt[rate_id + 5],
+			   last_cnt->num_qry_pkt[rate_id + 6],
+			   last_cnt->num_qry_pkt[rate_id + 7]);
+	}
+
+	for (ss = 0; ss < efuse->hw_cap.nss; ss++) {
+		rate_id = DESC_RATEVHT1SS_MCS0 + ss * 10;
+		seq_printf(m, " * VHT_MCS-%uss MCS[0:9] = {%u, %u, %u, %u, %u, %u, %u, %u, %u, %u}\n",
+			   ss + 1,
+			   last_cnt->num_qry_pkt[rate_id],
+			   last_cnt->num_qry_pkt[rate_id + 1],
+			   last_cnt->num_qry_pkt[rate_id + 2],
+			   last_cnt->num_qry_pkt[rate_id + 3],
+			   last_cnt->num_qry_pkt[rate_id + 4],
+			   last_cnt->num_qry_pkt[rate_id + 5],
+			   last_cnt->num_qry_pkt[rate_id + 6],
+			   last_cnt->num_qry_pkt[rate_id + 7],
+			   last_cnt->num_qry_pkt[rate_id + 8],
+			   last_cnt->num_qry_pkt[rate_id + 9]);
+	}
+
+	seq_printf(m, "[RSSI(dBm)] = {%d, %d}\n",
+		   dm_info->rssi[RF_PATH_A] - 100,
+		   dm_info->rssi[RF_PATH_B] - 100);
+	seq_printf(m, "[Rx EVM(dB)] = {-%d, -%d}\n",
+		   dm_info->rx_evm_dbm[RF_PATH_A],
+		   dm_info->rx_evm_dbm[RF_PATH_B]);
+	seq_printf(m, "[Rx SNR] = {%d, %d}\n",
+		   dm_info->rx_snr[RF_PATH_A],
+		   dm_info->rx_snr[RF_PATH_B]);
+	seq_printf(m, "[CFO_tail(KHz)] = {%d, %d}\n",
+		   dm_info->cfo_tail[RF_PATH_A],
+		   dm_info->cfo_tail[RF_PATH_B]);
+
+	if (dm_info->curr_rx_rate >= DESC_RATE11M) {
+		seq_puts(m, "[Rx Average Status]:\n");
+		seq_printf(m, " * OFDM, EVM: {-%d}, SNR: {%d}\n",
+			   (u8)ewma_evm_read(&ewma_evm[RTW_EVM_OFDM]),
+			   (u8)ewma_snr_read(&ewma_snr[RTW_SNR_OFDM_A]));
+		seq_printf(m, " * 1SS, EVM: {-%d}, SNR: {%d}\n",
+			   (u8)ewma_evm_read(&ewma_evm[RTW_EVM_1SS]),
+			   (u8)ewma_snr_read(&ewma_snr[RTW_SNR_1SS_A]));
+		seq_printf(m, " * 2SS, EVM: {-%d, -%d}, SNR: {%d, %d}\n",
+			   (u8)ewma_evm_read(&ewma_evm[RTW_EVM_2SS_A]),
+			   (u8)ewma_evm_read(&ewma_evm[RTW_EVM_2SS_B]),
+			   (u8)ewma_snr_read(&ewma_snr[RTW_SNR_2SS_A]),
+			   (u8)ewma_snr_read(&ewma_snr[RTW_SNR_2SS_B]));
+	}
+
+	seq_puts(m, "[Rx Counter]:\n");
+	seq_printf(m, " * CCA (CCK, OFDM, Total) = (%u, %u, %u)\n",
+		   dm_info->cck_cca_cnt,
+		   dm_info->ofdm_cca_cnt,
+		   dm_info->total_cca_cnt);
+	seq_printf(m, " * False Alarm (CCK, OFDM, Total) = (%u, %u, %u)\n",
+		   dm_info->cck_fa_cnt,
+		   dm_info->ofdm_fa_cnt,
+		   dm_info->total_fa_cnt);
+	seq_printf(m, " * CCK cnt (ok, err) = (%u, %u)\n",
+		   dm_info->cck_ok_cnt, dm_info->cck_err_cnt);
+	seq_printf(m, " * OFDM cnt (ok, err) = (%u, %u)\n",
+		   dm_info->ofdm_ok_cnt, dm_info->ofdm_err_cnt);
+	seq_printf(m, " * HT cnt (ok, err) = (%u, %u)\n",
+		   dm_info->ht_ok_cnt, dm_info->ht_err_cnt);
+	seq_printf(m, " * VHT cnt (ok, err) = (%u, %u)\n",
+		   dm_info->vht_ok_cnt, dm_info->vht_err_cnt);
+
+	return 0;
+}
+
+static int rtw_debugfs_get_coex_info(struct seq_file *m, void *v)
+{
+	struct rtw_debugfs_priv *debugfs_priv = m->private;
+	struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
+
+	rtw_coex_display_coex_info(rtwdev, m);
+
+	return 0;
+}
+
+static ssize_t rtw_debugfs_set_coex_enable(struct file *filp,
+					   const char __user *buffer,
+					   size_t count, loff_t *loff)
+{
+	struct seq_file *seqpriv = (struct seq_file *)filp->private_data;
+	struct rtw_debugfs_priv *debugfs_priv = seqpriv->private;
+	struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
+	struct rtw_coex *coex = &rtwdev->coex;
+	char tmp[32 + 1];
+	bool enable;
+	int ret;
+
+	rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1);
+
+	ret = kstrtobool(tmp, &enable);
+	if (ret) {
+		rtw_warn(rtwdev, "invalid arguments\n");
+		return ret;
+	}
+
+	mutex_lock(&rtwdev->mutex);
+	coex->stop_dm = enable == 0;
+	mutex_unlock(&rtwdev->mutex);
+
+	return count;
+}
+
+static int rtw_debugfs_get_coex_enable(struct seq_file *m, void *v)
+{
+	struct rtw_debugfs_priv *debugfs_priv = m->private;
+	struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
+	struct rtw_coex *coex = &rtwdev->coex;
+
+	seq_printf(m, "coex mechanism %s\n",
+		   coex->stop_dm ? "disabled" : "enabled");
+
+	return 0;
+}
+
+static ssize_t rtw_debugfs_set_edcca_enable(struct file *filp,
+					    const char __user *buffer,
+					    size_t count, loff_t *loff)
+{
+	struct rtw_debugfs_priv *debugfs_priv = filp->private_data;
+	struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
+	char tmp[32 + 1];
+
+	rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1);
+
+	kstrtobool(tmp, &rtw_edcca_enabled);
+	rtw_phy_adaptivity_set_mode(rtwdev);
+
+	return count;
+}
+
+static int rtw_debugfs_get_sar(struct seq_file *m, void *v)
+{
+	struct rtw_debugfs_priv *debugfs_priv = m->private;
+	struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
+
+	rtw_sar_dump_via_debugfs(rtwdev, m);
+
+	return 0;
+}
+
 #define rtw_debug_impl_mac(page, addr)				\
 static struct rtw_debugfs_priv rtw_debug_priv_mac_ ##page = {	\
 	.cb_read = rtw_debug_get_mac_page,			\
@@ -653,12 +862,33 @@
 	.cb_read = rtw_debugfs_get_rsvd_page,
 };
 
+static struct rtw_debugfs_priv rtw_debug_priv_phy_info = {
+	.cb_read = rtw_debugfs_get_phy_info,
+};
+
+static struct rtw_debugfs_priv rtw_debug_priv_coex_enable = {
+	.cb_write = rtw_debugfs_set_coex_enable,
+	.cb_read = rtw_debugfs_get_coex_enable,
+};
+
+static struct rtw_debugfs_priv rtw_debug_priv_coex_info = {
+	.cb_read = rtw_debugfs_get_coex_info,
+};
+
+static struct rtw_debugfs_priv rtw_debug_priv_edcca_enable = {
+	.cb_write = rtw_debugfs_set_edcca_enable,
+};
+
+static struct rtw_debugfs_priv rtw_debug_priv_sar = {
+	.cb_read = rtw_debugfs_get_sar,
+};
+
 #define rtw_debugfs_add_core(name, mode, fopname, parent)		\
 	do {								\
 		rtw_debug_priv_ ##name.rtwdev = rtwdev;			\
-		if (!debugfs_create_file(#name, mode,			\
+		if (IS_ERR(debugfs_create_file(#name, mode,		\
 					 parent, &rtw_debug_priv_ ##name,\
-					 &file_ops_ ##fopname))		\
+					 &file_ops_ ##fopname)))	\
 			pr_debug("Unable to initialize debugfs:%s\n",	\
 			       #name);					\
 	} while (0)
@@ -682,6 +912,10 @@
 	rtw_debugfs_add_rw(rf_read);
 	rtw_debugfs_add_rw(dump_cam);
 	rtw_debugfs_add_rw(rsvd_page);
+	rtw_debugfs_add_r(phy_info);
+	rtw_debugfs_add_r(coex_info);
+	rtw_debugfs_add_rw(coex_enable);
+	rtw_debugfs_add_r(sar);
 	rtw_debugfs_add_r(mac_0);
 	rtw_debugfs_add_r(mac_1);
 	rtw_debugfs_add_r(mac_2);
@@ -722,6 +956,7 @@
 	}
 	rtw_debugfs_add_r(rf_dump);
 	rtw_debugfs_add_r(tx_pwr_tbl);
+	rtw_debugfs_add_w(edcca_enable);
 }
 
 #endif /* CONFIG_RTW88_DEBUGFS */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/debug.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/debug.h
@@ -16,6 +16,9 @@
 	RTW_DBG_RFK		= 0x00000080,
 	RTW_DBG_REGD		= 0x00000100,
 	RTW_DBG_DEBUGFS		= 0x00000200,
+	RTW_DBG_PS		= 0x00000400,
+	RTW_DBG_BF		= 0x00000800,
+	RTW_DBG_WOW		= 0x00001000,
 
 	RTW_DBG_ALL		= 0xffffffff
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/efuse.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/efuse.c
@@ -90,6 +90,8 @@
 	u32 addr;
 	u32 cnt;
 
+	rtw_chip_efuse_grant_on(rtwdev);
+
 	switch_efuse_bank(rtwdev);
 
 	/* disable 2.5V LDO */
@@ -113,6 +115,8 @@
 		*(map + addr) = (u8)(efuse_ctl & BIT_MASK_EF_DATA);
 	}
 
+	rtw_chip_efuse_grant_off(rtwdev);
+
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/fw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/fw.c
@@ -7,7 +7,10 @@
 #include "fw.h"
 #include "tx.h"
 #include "reg.h"
+#include "sec.h"
 #include "debug.h"
+#include "util.h"
+#include "wow.h"
 
 static void rtw_fw_c2h_cmd_handle_ext(struct rtw_dev *rtwdev,
 				      struct sk_buff *skb)
@@ -20,13 +23,107 @@
 
 	switch (sub_cmd_id) {
 	case C2H_CCX_RPT:
-		rtw_tx_report_handle(rtwdev, skb);
+		rtw_tx_report_handle(rtwdev, skb, C2H_CCX_RPT);
 		break;
 	default:
 		break;
 	}
 }
 
+static u16 get_max_amsdu_len(u32 bit_rate)
+{
+	/* lower than ofdm, do not aggregate */
+	if (bit_rate < 550)
+		return 1;
+
+	/* lower than 20M 2ss mcs8, make it small */
+	if (bit_rate < 1800)
+		return 1200;
+
+	/* lower than 40M 2ss mcs9, make it medium */
+	if (bit_rate < 4000)
+		return 2600;
+
+	/* not yet 80M 2ss mcs8/9, make it twice regular packet size */
+	if (bit_rate < 7000)
+		return 3500;
+
+	/* unlimited */
+	return 0;
+}
+
+struct rtw_fw_iter_ra_data {
+	struct rtw_dev *rtwdev;
+	u8 *payload;
+};
+
+static void rtw_fw_ra_report_iter(void *data, struct ieee80211_sta *sta)
+{
+	struct rtw_fw_iter_ra_data *ra_data = data;
+	struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
+	u8 mac_id, rate, sgi, bw;
+	u8 mcs, nss;
+	u32 bit_rate;
+
+	mac_id = GET_RA_REPORT_MACID(ra_data->payload);
+	if (si->mac_id != mac_id)
+		return;
+
+	si->ra_report.txrate.flags = 0;
+
+	rate = GET_RA_REPORT_RATE(ra_data->payload);
+	sgi = GET_RA_REPORT_SGI(ra_data->payload);
+	bw = GET_RA_REPORT_BW(ra_data->payload);
+
+	if (rate < DESC_RATEMCS0) {
+		si->ra_report.txrate.legacy = rtw_desc_to_bitrate(rate);
+		goto legacy;
+	}
+
+	rtw_desc_to_mcsrate(rate, &mcs, &nss);
+	if (rate >= DESC_RATEVHT1SS_MCS0)
+		si->ra_report.txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
+	else if (rate >= DESC_RATEMCS0)
+		si->ra_report.txrate.flags |= RATE_INFO_FLAGS_MCS;
+
+	if (rate >= DESC_RATEMCS0) {
+		si->ra_report.txrate.mcs = mcs;
+		si->ra_report.txrate.nss = nss;
+	}
+
+	if (sgi)
+		si->ra_report.txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+
+	if (bw == RTW_CHANNEL_WIDTH_80)
+		si->ra_report.txrate.bw = RATE_INFO_BW_80;
+	else if (bw == RTW_CHANNEL_WIDTH_40)
+		si->ra_report.txrate.bw = RATE_INFO_BW_40;
+	else
+		si->ra_report.txrate.bw = RATE_INFO_BW_20;
+
+legacy:
+	bit_rate = cfg80211_calculate_bitrate(&si->ra_report.txrate);
+
+	si->ra_report.desc_rate = rate;
+	si->ra_report.bit_rate = bit_rate;
+
+	sta->max_rc_amsdu_len = get_max_amsdu_len(bit_rate);
+}
+
+static void rtw_fw_ra_report_handle(struct rtw_dev *rtwdev, u8 *payload,
+				    u8 length)
+{
+	struct rtw_fw_iter_ra_data ra_data;
+
+	if (WARN(length < 7, "invalid ra report c2h length\n"))
+		return;
+
+	rtwdev->dm_info.tx_rate = GET_RA_REPORT_RATE(payload);
+	ra_data.rtwdev = rtwdev;
+	ra_data.payload = payload;
+	rtw_iterate_stas_atomic(rtwdev, rtw_fw_ra_report_iter, &ra_data);
+}
+
 void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb)
 {
 	struct rtw_c2h_cmd *c2h;
@@ -39,7 +136,13 @@
 
 	mutex_lock(&rtwdev->mutex);
 
+	if (!test_bit(RTW_FLAG_RUNNING, rtwdev->flags))
+		goto unlock;
+
 	switch (c2h->id) {
+	case C2H_CCX_TX_RPT:
+		rtw_tx_report_handle(rtwdev, skb, C2H_CCX_TX_RPT);
+		break;
 	case C2H_BT_INFO:
 		rtw_coex_bt_info_notify(rtwdev, c2h->payload, len);
 		break;
@@ -49,10 +152,15 @@
 	case C2H_HALMAC:
 		rtw_fw_c2h_cmd_handle_ext(rtwdev, skb);
 		break;
+	case C2H_RA_RPT:
+		rtw_fw_ra_report_handle(rtwdev, c2h->payload, len);
+		break;
 	default:
+		rtw_dbg(rtwdev, RTW_DBG_FW, "C2H 0x%x isn't handled\n", c2h->id);
 		break;
 	}
 
+unlock:
 	mutex_unlock(&rtwdev->mutex);
 }
 
@@ -166,6 +274,9 @@
 	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 	u16 total_size = H2C_PKT_HDR_SIZE + 4;
 
+	if (rtw_chip_wcpu_11n(rtwdev))
+		return;
+
 	rtw_h2c_pkt_set_header(h2c_pkt, H2C_PKT_GENERAL_INFO);
 
 	SET_PKT_H2C_TOTAL_LEN(h2c_pkt, total_size);
@@ -186,6 +297,9 @@
 	u16 total_size = H2C_PKT_HDR_SIZE + 8;
 	u8 fw_rf_type = 0;
 
+	if (rtw_chip_wcpu_11n(rtwdev))
+		return;
+
 	if (hal->rf_type == RF_1T1R)
 		fw_rf_type = FW_RF_1T1R;
 	else if (hal->rf_type == RF_2T2R)
@@ -216,6 +330,17 @@
 	rtw_fw_send_h2c_packet(rtwdev, h2c_pkt);
 }
 
+void rtw_fw_set_default_port(struct rtw_dev *rtwdev, u8 port)
+{
+	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
+
+	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_DEFAULT_PORT);
+
+	SET_DEFAULT_PORT_PORTID(h2c_pkt, port);
+
+	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
+}
+
 void rtw_fw_query_bt_info(struct rtw_dev *rtwdev)
 {
 	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
@@ -340,7 +465,7 @@
 	SET_RA_INFO_INIT_RA_LVL(h2c_pkt, si->init_ra_lv);
 	SET_RA_INFO_SGI_EN(h2c_pkt, si->sgi_enable);
 	SET_RA_INFO_BW_MODE(h2c_pkt, si->bw_mode);
-	SET_RA_INFO_LDPC(h2c_pkt, si->ldpc_en);
+	SET_RA_INFO_LDPC(h2c_pkt, !!si->ldpc_en);
 	SET_RA_INFO_NO_UPDATE(h2c_pkt, no_update);
 	SET_RA_INFO_VHT_EN(h2c_pkt, si->vht_enable);
 	SET_RA_INFO_DIS_PT(h2c_pkt, disable_pt);
@@ -371,6 +496,8 @@
 	struct rtw_lps_conf *conf = &rtwdev->lps_conf;
 	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 
+	rtw_fw_set_default_port(rtwdev, conf->port_id);
+
 	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_SET_PWR_MODE);
 
 	SET_PWR_MODE_SET_MODE(h2c_pkt, conf->mode);
@@ -383,13 +510,103 @@
 	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 }
 
+void rtw_fw_set_keep_alive_cmd(struct rtw_dev *rtwdev, bool enable)
+{
+	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
+	struct rtw_fw_wow_keep_alive_para mode = {
+		.adopt = true,
+		.pkt_type = KEEP_ALIVE_NULL_PKT,
+		.period = 5,
+	};
+
+	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_KEEP_ALIVE);
+	SET_KEEP_ALIVE_ENABLE(h2c_pkt, enable);
+	SET_KEEP_ALIVE_ADOPT(h2c_pkt, mode.adopt);
+	SET_KEEP_ALIVE_PKT_TYPE(h2c_pkt, mode.pkt_type);
+	SET_KEEP_ALIVE_CHECK_PERIOD(h2c_pkt, mode.period);
+
+	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
+}
+
+void rtw_fw_set_disconnect_decision_cmd(struct rtw_dev *rtwdev, bool enable)
+{
+	struct rtw_wow_param *rtw_wow = &rtwdev->wow;
+	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
+	struct rtw_fw_wow_disconnect_para mode = {
+		.adopt = true,
+		.period = 30,
+		.retry_count = 5,
+	};
+
+	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_DISCONNECT_DECISION);
+
+	if (test_bit(RTW_WOW_FLAG_EN_DISCONNECT, rtw_wow->flags)) {
+		SET_DISCONNECT_DECISION_ENABLE(h2c_pkt, enable);
+		SET_DISCONNECT_DECISION_ADOPT(h2c_pkt, mode.adopt);
+		SET_DISCONNECT_DECISION_CHECK_PERIOD(h2c_pkt, mode.period);
+		SET_DISCONNECT_DECISION_TRY_PKT_NUM(h2c_pkt, mode.retry_count);
+	}
+
+	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
+}
+
+void rtw_fw_set_wowlan_ctrl_cmd(struct rtw_dev *rtwdev, bool enable)
+{
+	struct rtw_wow_param *rtw_wow = &rtwdev->wow;
+	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
+
+	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_WOWLAN);
+
+	SET_WOWLAN_FUNC_ENABLE(h2c_pkt, enable);
+	if (rtw_wow_mgd_linked(rtwdev)) {
+		if (test_bit(RTW_WOW_FLAG_EN_MAGIC_PKT, rtw_wow->flags))
+			SET_WOWLAN_MAGIC_PKT_ENABLE(h2c_pkt, enable);
+		if (test_bit(RTW_WOW_FLAG_EN_DISCONNECT, rtw_wow->flags))
+			SET_WOWLAN_DEAUTH_WAKEUP_ENABLE(h2c_pkt, enable);
+		if (test_bit(RTW_WOW_FLAG_EN_REKEY_PKT, rtw_wow->flags))
+			SET_WOWLAN_REKEY_WAKEUP_ENABLE(h2c_pkt, enable);
+		if (rtw_wow->pattern_cnt)
+			SET_WOWLAN_PATTERN_MATCH_ENABLE(h2c_pkt, enable);
+	}
+
+	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
+}
+
+void rtw_fw_set_aoac_global_info_cmd(struct rtw_dev *rtwdev,
+				     u8 pairwise_key_enc,
+				     u8 group_key_enc)
+{
+	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
+
+	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_AOAC_GLOBAL_INFO);
+
+	SET_AOAC_GLOBAL_INFO_PAIRWISE_ENC_ALG(h2c_pkt, pairwise_key_enc);
+	SET_AOAC_GLOBAL_INFO_GROUP_ENC_ALG(h2c_pkt, group_key_enc);
+
+	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
+}
+
+void rtw_fw_set_remote_wake_ctrl_cmd(struct rtw_dev *rtwdev, bool enable)
+{
+	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
+
+	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_REMOTE_WAKE_CTRL);
+
+	SET_REMOTE_WAKECTRL_ENABLE(h2c_pkt, enable);
+
+	if (rtw_wow_no_link(rtwdev))
+		SET_REMOTE_WAKE_CTRL_NLO_OFFLOAD_EN(h2c_pkt, enable);
+
+	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
+}
+
 static u8 rtw_get_rsvd_page_location(struct rtw_dev *rtwdev,
 				     enum rtw_rsvd_packet_type type)
 {
 	struct rtw_rsvd_page *rsvd_pkt;
 	u8 location = 0;
 
-	list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list) {
+	list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, build_list) {
 		if (type == rsvd_pkt->type)
 			location = rsvd_pkt->page;
 	}
@@ -397,6 +614,79 @@
 	return location;
 }
 
+void rtw_fw_set_nlo_info(struct rtw_dev *rtwdev, bool enable)
+{
+	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
+	u8 loc_nlo;
+
+	loc_nlo = rtw_get_rsvd_page_location(rtwdev, RSVD_NLO_INFO);
+
+	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_NLO_INFO);
+
+	SET_NLO_FUN_EN(h2c_pkt, enable);
+	if (enable) {
+		if (rtw_fw_lps_deep_mode)
+			SET_NLO_PS_32K(h2c_pkt, enable);
+		SET_NLO_IGNORE_SECURITY(h2c_pkt, enable);
+		SET_NLO_LOC_NLO_INFO(h2c_pkt, loc_nlo);
+	}
+
+	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
+}
+
+void rtw_fw_set_pg_info(struct rtw_dev *rtwdev)
+{
+	struct rtw_lps_conf *conf = &rtwdev->lps_conf;
+	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
+	u8 loc_pg, loc_dpk;
+
+	loc_pg = rtw_get_rsvd_page_location(rtwdev, RSVD_LPS_PG_INFO);
+	loc_dpk = rtw_get_rsvd_page_location(rtwdev, RSVD_LPS_PG_DPK);
+
+	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_LPS_PG_INFO);
+
+	LPS_PG_INFO_LOC(h2c_pkt, loc_pg);
+	LPS_PG_DPK_LOC(h2c_pkt, loc_dpk);
+	LPS_PG_SEC_CAM_EN(h2c_pkt, conf->sec_cam_backup);
+	LPS_PG_PATTERN_CAM_EN(h2c_pkt, conf->pattern_cam_backup);
+
+	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
+}
+
+u8 rtw_get_rsvd_page_probe_req_location(struct rtw_dev *rtwdev,
+					struct cfg80211_ssid *ssid)
+{
+	struct rtw_rsvd_page *rsvd_pkt;
+	u8 location = 0;
+
+	list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, build_list) {
+		if (rsvd_pkt->type != RSVD_PROBE_REQ)
+			continue;
+		if ((!ssid && !rsvd_pkt->ssid) ||
+		    rtw_ssid_equal(rsvd_pkt->ssid, ssid))
+			location = rsvd_pkt->page;
+	}
+
+	return location;
+}
+
+u16 rtw_get_rsvd_page_probe_req_size(struct rtw_dev *rtwdev,
+				     struct cfg80211_ssid *ssid)
+{
+	struct rtw_rsvd_page *rsvd_pkt;
+	u16 size = 0;
+
+	list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, build_list) {
+		if (rsvd_pkt->type != RSVD_PROBE_REQ)
+			continue;
+		if ((!ssid && !rsvd_pkt->ssid) ||
+		    rtw_ssid_equal(rsvd_pkt->ssid, ssid))
+			size = rsvd_pkt->skb->len;
+	}
+
+	return size;
+}
+
 void rtw_send_rsvd_page_h2c(struct rtw_dev *rtwdev)
 {
 	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
@@ -423,34 +713,175 @@
 	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 }
 
-static struct sk_buff *
-rtw_beacon_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+static struct sk_buff *rtw_nlo_info_get(struct ieee80211_hw *hw)
 {
-	struct sk_buff *skb_new;
+	struct rtw_dev *rtwdev = hw->priv;
+	struct rtw_chip_info *chip = rtwdev->chip;
+	struct rtw_pno_request *pno_req = &rtwdev->wow.pno_req;
+	struct rtw_nlo_info_hdr *nlo_hdr;
+	struct cfg80211_ssid *ssid;
+	struct sk_buff *skb;
+	u8 *pos, loc;
+	u32 size;
+	int i;
 
-	if (vif->type != NL80211_IFTYPE_AP &&
-	    vif->type != NL80211_IFTYPE_ADHOC &&
-	    !ieee80211_vif_is_mesh(vif)) {
-		skb_new = alloc_skb(1, GFP_KERNEL);
-		if (!skb_new)
+	if (!pno_req->inited || !pno_req->match_set_cnt)
+		return NULL;
+
+	size = sizeof(struct rtw_nlo_info_hdr) + pno_req->match_set_cnt *
+		      IEEE80211_MAX_SSID_LEN + chip->tx_pkt_desc_sz;
+
+	skb = alloc_skb(size, GFP_KERNEL);
+	if (!skb)
+		return NULL;
+
+	skb_reserve(skb, chip->tx_pkt_desc_sz);
+
+	nlo_hdr = skb_put_zero(skb, sizeof(struct rtw_nlo_info_hdr));
+
+	nlo_hdr->nlo_count = pno_req->match_set_cnt;
+	nlo_hdr->hidden_ap_count = pno_req->match_set_cnt;
+
+	/* pattern check for firmware */
+	memset(nlo_hdr->pattern_check, 0xA5, FW_NLO_INFO_CHECK_SIZE);
+
+	for (i = 0; i < pno_req->match_set_cnt; i++)
+		nlo_hdr->ssid_len[i] = pno_req->match_sets[i].ssid.ssid_len;
+
+	for (i = 0; i < pno_req->match_set_cnt; i++) {
+		ssid = &pno_req->match_sets[i].ssid;
+		loc  = rtw_get_rsvd_page_probe_req_location(rtwdev, ssid);
+		if (!loc) {
+			rtw_err(rtwdev, "failed to get probe req rsvd loc\n");
+			kfree(skb);
 			return NULL;
-		skb_put(skb_new, 1);
-	} else {
-		skb_new = ieee80211_beacon_get(hw, vif);
+		}
+		nlo_hdr->location[i] = loc;
 	}
 
-	return skb_new;
+	for (i = 0; i < pno_req->match_set_cnt; i++) {
+		pos = skb_put_zero(skb, IEEE80211_MAX_SSID_LEN);
+		memcpy(pos, pno_req->match_sets[i].ssid.ssid,
+		       pno_req->match_sets[i].ssid.ssid_len);
+	}
+
+	return skb;
+}
+
+static struct sk_buff *rtw_cs_channel_info_get(struct ieee80211_hw *hw)
+{
+	struct rtw_dev *rtwdev = hw->priv;
+	struct rtw_chip_info *chip = rtwdev->chip;
+	struct rtw_pno_request *pno_req = &rtwdev->wow.pno_req;
+	struct ieee80211_channel *channels = pno_req->channels;
+	struct sk_buff *skb;
+	int count =  pno_req->channel_cnt;
+	u8 *pos;
+	int i = 0;
+
+	skb = alloc_skb(4 * count + chip->tx_pkt_desc_sz, GFP_KERNEL);
+	if (!skb)
+		return NULL;
+
+	skb_reserve(skb, chip->tx_pkt_desc_sz);
+
+	for (i = 0; i < count; i++) {
+		pos = skb_put_zero(skb, 4);
+
+		CHSW_INFO_SET_CH(pos, channels[i].hw_value);
+
+		if (channels[i].flags & IEEE80211_CHAN_RADAR)
+			CHSW_INFO_SET_ACTION_ID(pos, 0);
+		else
+			CHSW_INFO_SET_ACTION_ID(pos, 1);
+		CHSW_INFO_SET_TIMEOUT(pos, 1);
+		CHSW_INFO_SET_PRI_CH_IDX(pos, 1);
+		CHSW_INFO_SET_BW(pos, 0);
+	}
+
+	return skb;
+}
+
+static struct sk_buff *rtw_lps_pg_dpk_get(struct ieee80211_hw *hw)
+{
+	struct rtw_dev *rtwdev = hw->priv;
+	struct rtw_chip_info *chip = rtwdev->chip;
+	struct rtw_dpk_info *dpk_info = &rtwdev->dm_info.dpk_info;
+	struct rtw_lps_pg_dpk_hdr *dpk_hdr;
+	struct sk_buff *skb;
+	u32 size;
+
+	size = chip->tx_pkt_desc_sz + sizeof(*dpk_hdr);
+	skb = alloc_skb(size, GFP_KERNEL);
+	if (!skb)
+		return NULL;
+
+	skb_reserve(skb, chip->tx_pkt_desc_sz);
+	dpk_hdr = skb_put_zero(skb, sizeof(*dpk_hdr));
+	dpk_hdr->dpk_ch = dpk_info->dpk_ch;
+	dpk_hdr->dpk_path_ok = dpk_info->dpk_path_ok[0];
+	memcpy(dpk_hdr->dpk_txagc, dpk_info->dpk_txagc, 2);
+	memcpy(dpk_hdr->dpk_gs, dpk_info->dpk_gs, 4);
+	memcpy(dpk_hdr->coef, dpk_info->coef, 160);
+
+	return skb;
+}
+
+static struct sk_buff *rtw_lps_pg_info_get(struct ieee80211_hw *hw)
+{
+	struct rtw_dev *rtwdev = hw->priv;
+	struct rtw_chip_info *chip = rtwdev->chip;
+	struct rtw_lps_conf *conf = &rtwdev->lps_conf;
+	struct rtw_lps_pg_info_hdr *pg_info_hdr;
+	struct rtw_wow_param *rtw_wow = &rtwdev->wow;
+	struct sk_buff *skb;
+	u32 size;
+
+	size = chip->tx_pkt_desc_sz + sizeof(*pg_info_hdr);
+	skb = alloc_skb(size, GFP_KERNEL);
+	if (!skb)
+		return NULL;
+
+	skb_reserve(skb, chip->tx_pkt_desc_sz);
+	pg_info_hdr = skb_put_zero(skb, sizeof(*pg_info_hdr));
+	pg_info_hdr->tx_bu_page_count = rtwdev->fifo.rsvd_drv_pg_num;
+	pg_info_hdr->macid = find_first_bit(rtwdev->mac_id_map, RTW_MAX_MAC_ID_NUM);
+	pg_info_hdr->sec_cam_count =
+		rtw_sec_cam_pg_backup(rtwdev, pg_info_hdr->sec_cam);
+	pg_info_hdr->pattern_count = rtw_wow->pattern_cnt;
+
+	conf->sec_cam_backup = pg_info_hdr->sec_cam_count != 0;
+	conf->pattern_cam_backup = rtw_wow->pattern_cnt != 0;
+
+	return skb;
 }
 
 static struct sk_buff *rtw_get_rsvd_page_skb(struct ieee80211_hw *hw,
-					     struct ieee80211_vif *vif,
-					     enum rtw_rsvd_packet_type type)
+					     struct rtw_rsvd_page *rsvd_pkt)
 {
+	struct ieee80211_vif *vif;
+	struct rtw_vif *rtwvif;
 	struct sk_buff *skb_new;
+	struct cfg80211_ssid *ssid;
+
+	if (rsvd_pkt->type == RSVD_DUMMY) {
+		skb_new = alloc_skb(1, GFP_KERNEL);
+		if (!skb_new)
+			return NULL;
+
+		skb_put(skb_new, 1);
+		return skb_new;
+	}
 
-	switch (type) {
+	rtwvif = rsvd_pkt->rtwvif;
+	if (!rtwvif)
+		return NULL;
+
+	vif = rtwvif_to_vif(rtwvif);
+
+	switch (rsvd_pkt->type) {
 	case RSVD_BEACON:
-		skb_new = rtw_beacon_get(hw, vif);
+		skb_new = ieee80211_beacon_get(hw, vif);
 		break;
 	case RSVD_PS_POLL:
 		skb_new = ieee80211_pspoll_get(hw, vif);
@@ -464,6 +895,27 @@
 	case RSVD_QOS_NULL:
 		skb_new = ieee80211_nullfunc_get(hw, vif, true);
 		break;
+	case RSVD_LPS_PG_DPK:
+		skb_new = rtw_lps_pg_dpk_get(hw);
+		break;
+	case RSVD_LPS_PG_INFO:
+		skb_new = rtw_lps_pg_info_get(hw);
+		break;
+	case RSVD_PROBE_REQ:
+		ssid = (struct cfg80211_ssid *)rsvd_pkt->ssid;
+		if (ssid)
+			skb_new = ieee80211_probereq_get(hw, vif->addr,
+							 ssid->ssid,
+							 ssid->ssid_len, 0);
+		else
+			skb_new = ieee80211_probereq_get(hw, vif->addr, NULL, 0, 0);
+		break;
+	case RSVD_NLO_INFO:
+		skb_new = rtw_nlo_info_get(hw);
+		break;
+	case RSVD_CH_INFO:
+		skb_new = rtw_cs_channel_info_get(hw);
+		break;
 	default:
 		return NULL;
 	}
@@ -474,14 +926,14 @@
 	return skb_new;
 }
 
-static void rtw_fill_rsvd_page_desc(struct rtw_dev *rtwdev, struct sk_buff *skb)
+static void rtw_fill_rsvd_page_desc(struct rtw_dev *rtwdev, struct sk_buff *skb,
+				    enum rtw_rsvd_packet_type type)
 {
-	struct rtw_tx_pkt_info pkt_info;
+	struct rtw_tx_pkt_info pkt_info = {0};
 	struct rtw_chip_info *chip = rtwdev->chip;
 	u8 *pkt_desc;
 
-	memset(&pkt_info, 0, sizeof(pkt_info));
-	rtw_rsvd_page_pkt_info_update(rtwdev, &pkt_info, skb);
+	rtw_tx_rsvd_page_pkt_info_update(rtwdev, &pkt_info, skb, type);
 	pkt_desc = skb_push(skb, chip->tx_pkt_desc_sz);
 	memset(pkt_desc, 0, chip->tx_pkt_desc_sz);
 	rtw_tx_fill_tx_desc(&pkt_info, skb);
@@ -498,9 +950,6 @@
 {
 	struct sk_buff *skb = rsvd_pkt->skb;
 
-	if (rsvd_pkt->add_txdesc)
-		rtw_fill_rsvd_page_desc(rtwdev, skb);
-
 	if (page >= 1)
 		memcpy(buf + page_margin + page_size * (page - 1),
 		       skb->data, skb->len);
@@ -508,47 +957,152 @@
 		memcpy(buf, skb->data, skb->len);
 }
 
-void rtw_add_rsvd_page(struct rtw_dev *rtwdev, enum rtw_rsvd_packet_type type,
-		       bool txdesc)
+static struct rtw_rsvd_page *rtw_alloc_rsvd_page(struct rtw_dev *rtwdev,
+						 enum rtw_rsvd_packet_type type,
+						 bool txdesc)
 {
-	struct rtw_rsvd_page *rsvd_pkt;
+	struct rtw_rsvd_page *rsvd_pkt = NULL;
+
+	rsvd_pkt = kzalloc(sizeof(*rsvd_pkt), GFP_KERNEL);
+
+	if (!rsvd_pkt)
+		return NULL;
 
+	INIT_LIST_HEAD(&rsvd_pkt->vif_list);
+	INIT_LIST_HEAD(&rsvd_pkt->build_list);
+	rsvd_pkt->type = type;
+	rsvd_pkt->add_txdesc = txdesc;
+
+	return rsvd_pkt;
+}
+
+static void rtw_insert_rsvd_page(struct rtw_dev *rtwdev,
+				 struct rtw_vif *rtwvif,
+				 struct rtw_rsvd_page *rsvd_pkt)
+{
 	lockdep_assert_held(&rtwdev->mutex);
 
-	list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list) {
-		if (rsvd_pkt->type == type)
-			return;
+	list_add_tail(&rsvd_pkt->vif_list, &rtwvif->rsvd_page_list);
+}
+
+static void rtw_add_rsvd_page(struct rtw_dev *rtwdev,
+			      struct rtw_vif *rtwvif,
+			      enum rtw_rsvd_packet_type type,
+			      bool txdesc)
+{
+	struct rtw_rsvd_page *rsvd_pkt;
+
+	rsvd_pkt = rtw_alloc_rsvd_page(rtwdev, type, txdesc);
+	if (!rsvd_pkt) {
+		rtw_err(rtwdev, "failed to alloc rsvd page %d\n", type);
+		return;
 	}
 
-	rsvd_pkt = kmalloc(sizeof(*rsvd_pkt), GFP_KERNEL);
-	if (!rsvd_pkt)
+	rsvd_pkt->rtwvif = rtwvif;
+	rtw_insert_rsvd_page(rtwdev, rtwvif, rsvd_pkt);
+}
+
+static void rtw_add_rsvd_page_probe_req(struct rtw_dev *rtwdev,
+					struct rtw_vif *rtwvif,
+					struct cfg80211_ssid *ssid)
+{
+	struct rtw_rsvd_page *rsvd_pkt;
+
+	rsvd_pkt = rtw_alloc_rsvd_page(rtwdev, RSVD_PROBE_REQ, true);
+	if (!rsvd_pkt) {
+		rtw_err(rtwdev, "failed to alloc probe req rsvd page\n");
 		return;
+	}
 
-	rsvd_pkt->type = type;
-	rsvd_pkt->add_txdesc = txdesc;
-	list_add_tail(&rsvd_pkt->list, &rtwdev->rsvd_page_list);
+	rsvd_pkt->rtwvif = rtwvif;
+	rsvd_pkt->ssid = ssid;
+	rtw_insert_rsvd_page(rtwdev, rtwvif, rsvd_pkt);
 }
 
-void rtw_reset_rsvd_page(struct rtw_dev *rtwdev)
+void rtw_remove_rsvd_page(struct rtw_dev *rtwdev,
+			  struct rtw_vif *rtwvif)
 {
 	struct rtw_rsvd_page *rsvd_pkt, *tmp;
 
 	lockdep_assert_held(&rtwdev->mutex);
 
-	list_for_each_entry_safe(rsvd_pkt, tmp, &rtwdev->rsvd_page_list, list) {
-		if (rsvd_pkt->type == RSVD_BEACON)
-			continue;
-		list_del(&rsvd_pkt->list);
+	/* remove all of the rsvd pages for vif */
+	list_for_each_entry_safe(rsvd_pkt, tmp, &rtwvif->rsvd_page_list,
+				 vif_list) {
+		list_del(&rsvd_pkt->vif_list);
+		if (!list_empty(&rsvd_pkt->build_list))
+			list_del(&rsvd_pkt->build_list);
 		kfree(rsvd_pkt);
 	}
 }
 
+void rtw_add_rsvd_page_bcn(struct rtw_dev *rtwdev,
+			   struct rtw_vif *rtwvif)
+{
+	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
+
+	if (vif->type != NL80211_IFTYPE_AP &&
+	    vif->type != NL80211_IFTYPE_ADHOC &&
+	    vif->type != NL80211_IFTYPE_MESH_POINT) {
+		rtw_warn(rtwdev, "Cannot add beacon rsvd page for %d\n",
+			 vif->type);
+		return;
+	}
+
+	rtw_add_rsvd_page(rtwdev, rtwvif, RSVD_BEACON, false);
+}
+
+void rtw_add_rsvd_page_pno(struct rtw_dev *rtwdev,
+			   struct rtw_vif *rtwvif)
+{
+	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
+	struct rtw_wow_param *rtw_wow = &rtwdev->wow;
+	struct rtw_pno_request *rtw_pno_req = &rtw_wow->pno_req;
+	struct cfg80211_ssid *ssid;
+	int i;
+
+	if (vif->type != NL80211_IFTYPE_STATION) {
+		rtw_warn(rtwdev, "Cannot add PNO rsvd page for %d\n",
+			 vif->type);
+		return;
+	}
+
+	for (i = 0 ; i < rtw_pno_req->match_set_cnt; i++) {
+		ssid = &rtw_pno_req->match_sets[i].ssid;
+		rtw_add_rsvd_page_probe_req(rtwdev, rtwvif, ssid);
+	}
+
+	rtw_add_rsvd_page_probe_req(rtwdev, rtwvif, NULL);
+	rtw_add_rsvd_page(rtwdev, rtwvif, RSVD_NLO_INFO, false);
+	rtw_add_rsvd_page(rtwdev, rtwvif, RSVD_CH_INFO, true);
+}
+
+void rtw_add_rsvd_page_sta(struct rtw_dev *rtwdev,
+			   struct rtw_vif *rtwvif)
+{
+	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
+
+	if (vif->type != NL80211_IFTYPE_STATION) {
+		rtw_warn(rtwdev, "Cannot add sta rsvd page for %d\n",
+			 vif->type);
+		return;
+	}
+
+	rtw_add_rsvd_page(rtwdev, rtwvif, RSVD_PS_POLL, true);
+	rtw_add_rsvd_page(rtwdev, rtwvif, RSVD_QOS_NULL, true);
+	rtw_add_rsvd_page(rtwdev, rtwvif, RSVD_NULL, true);
+	rtw_add_rsvd_page(rtwdev, rtwvif, RSVD_LPS_PG_DPK, true);
+	rtw_add_rsvd_page(rtwdev, rtwvif, RSVD_LPS_PG_INFO, true);
+}
+
 int rtw_fw_write_data_rsvd_page(struct rtw_dev *rtwdev, u16 pg_addr,
 				u8 *buf, u32 size)
 {
 	u8 bckp[2];
 	u8 val;
 	u16 rsvd_pg_head;
+	u32 bcn_valid_addr;
+	u32 bcn_valid_mask;
 	int ret;
 
 	lockdep_assert_held(&rtwdev->mutex);
@@ -556,8 +1110,13 @@
 	if (!size)
 		return -EINVAL;
 
-	pg_addr &= BIT_MASK_BCN_HEAD_1_V1;
-	rtw_write16(rtwdev, REG_FIFOPAGE_CTRL_2, pg_addr | BIT_BCN_VALID_V1);
+	if (rtw_chip_wcpu_11n(rtwdev)) {
+		rtw_write32_set(rtwdev, REG_DWBCN0_CTRL, BIT_BCN_VALID);
+	} else {
+		pg_addr &= BIT_MASK_BCN_HEAD_1_V1;
+		pg_addr |= BIT_BCN_VALID_V1;
+		rtw_write16(rtwdev, REG_FIFOPAGE_CTRL_2, pg_addr);
+	}
 
 	val = rtw_read8(rtwdev, REG_CR + 1);
 	bckp[0] = val;
@@ -575,7 +1134,15 @@
 		goto restore;
 	}
 
-	if (!check_hw_ready(rtwdev, REG_FIFOPAGE_CTRL_2, BIT_BCN_VALID_V1, 1)) {
+	if (rtw_chip_wcpu_11n(rtwdev)) {
+		bcn_valid_addr = REG_DWBCN0_CTRL;
+		bcn_valid_mask = BIT_BCN_VALID;
+	} else {
+		bcn_valid_addr = REG_FIFOPAGE_CTRL_2;
+		bcn_valid_mask = BIT_BCN_VALID_V1;
+	}
+
+	if (!check_hw_ready(rtwdev, bcn_valid_addr, bcn_valid_mask, 1)) {
 		rtw_err(rtwdev, "error beacon valid\n");
 		ret = -EBUSY;
 	}
@@ -606,8 +1173,72 @@
 	return rtw_fw_write_data_rsvd_page(rtwdev, pg_addr, buf, size);
 }
 
-static u8 *rtw_build_rsvd_page(struct rtw_dev *rtwdev,
-			       struct ieee80211_vif *vif, u32 *size)
+static void __rtw_build_rsvd_page_reset(struct rtw_dev *rtwdev)
+{
+	struct rtw_rsvd_page *rsvd_pkt, *tmp;
+
+	list_for_each_entry_safe(rsvd_pkt, tmp, &rtwdev->rsvd_page_list,
+				 build_list) {
+		list_del_init(&rsvd_pkt->build_list);
+
+		/* Don't free except for the dummy rsvd page,
+		 * others will be freed when removing vif
+		 */
+		if (rsvd_pkt->type == RSVD_DUMMY)
+			kfree(rsvd_pkt);
+	}
+}
+
+static void rtw_build_rsvd_page_iter(void *data, u8 *mac,
+				     struct ieee80211_vif *vif)
+{
+	struct rtw_dev *rtwdev = data;
+	struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
+	struct rtw_rsvd_page *rsvd_pkt;
+
+	list_for_each_entry(rsvd_pkt, &rtwvif->rsvd_page_list, vif_list) {
+		if (rsvd_pkt->type == RSVD_BEACON)
+			list_add(&rsvd_pkt->build_list,
+				 &rtwdev->rsvd_page_list);
+		else
+			list_add_tail(&rsvd_pkt->build_list,
+				      &rtwdev->rsvd_page_list);
+	}
+}
+
+static int  __rtw_build_rsvd_page_from_vifs(struct rtw_dev *rtwdev)
+{
+	struct rtw_rsvd_page *rsvd_pkt;
+
+	__rtw_build_rsvd_page_reset(rtwdev);
+
+	/* gather rsvd page from vifs */
+	rtw_iterate_vifs_atomic(rtwdev, rtw_build_rsvd_page_iter, rtwdev);
+
+	rsvd_pkt = list_first_entry_or_null(&rtwdev->rsvd_page_list,
+					    struct rtw_rsvd_page, build_list);
+	if (!rsvd_pkt) {
+		WARN(1, "Should not have an empty reserved page\n");
+		return -EINVAL;
+	}
+
+	/* the first rsvd should be beacon, otherwise add a dummy one */
+	if (rsvd_pkt->type != RSVD_BEACON) {
+		struct rtw_rsvd_page *dummy_pkt;
+
+		dummy_pkt = rtw_alloc_rsvd_page(rtwdev, RSVD_DUMMY, false);
+		if (!dummy_pkt) {
+			rtw_err(rtwdev, "failed to alloc dummy rsvd page\n");
+			return -ENOMEM;
+		}
+
+		list_add(&dummy_pkt->build_list, &rtwdev->rsvd_page_list);
+	}
+
+	return 0;
+}
+
+static u8 *rtw_build_rsvd_page(struct rtw_dev *rtwdev, u32 *size)
 {
 	struct ieee80211_hw *hw = rtwdev->hw;
 	struct rtw_chip_info *chip = rtwdev->chip;
@@ -617,24 +1248,54 @@
 	u8 total_page = 0;
 	u8 page_size, page_margin, tx_desc_sz;
 	u8 *buf;
+	int ret;
 
 	page_size = chip->page_size;
 	tx_desc_sz = chip->tx_pkt_desc_sz;
 	page_margin = page_size - tx_desc_sz;
 
-	list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list) {
-		iter = rtw_get_rsvd_page_skb(hw, vif, rsvd_pkt->type);
+	ret = __rtw_build_rsvd_page_from_vifs(rtwdev);
+	if (ret) {
+		rtw_err(rtwdev,
+			"failed to build rsvd page from vifs, ret %d\n", ret);
+		return NULL;
+	}
+
+	list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, build_list) {
+		iter = rtw_get_rsvd_page_skb(hw, rsvd_pkt);
 		if (!iter) {
-			rtw_err(rtwdev, "fail to build rsvd packet\n");
+			rtw_err(rtwdev, "failed to build rsvd packet\n");
 			goto release_skb;
 		}
+
+		/* Fill the tx_desc for the rsvd pkt that requires one.
+		 * And iter->len will be added with size of tx_desc_sz.
+		 */
+		if (rsvd_pkt->add_txdesc)
+			rtw_fill_rsvd_page_desc(rtwdev, iter, rsvd_pkt->type);
+
 		rsvd_pkt->skb = iter;
 		rsvd_pkt->page = total_page;
-		if (rsvd_pkt->add_txdesc)
+
+		/* Reserved page is downloaded via TX path, and TX path will
+		 * generate a tx_desc at the header to describe length of
+		 * the buffer. If we are not counting page numbers with the
+		 * size of tx_desc added at the first rsvd_pkt (usually a
+		 * beacon, firmware default refer to the first page as the
+		 * content of beacon), we could generate a buffer which size
+		 * is smaller than the actual size of the whole rsvd_page
+		 */
+		if (total_page == 0) {
+			if (rsvd_pkt->type != RSVD_BEACON &&
+			    rsvd_pkt->type != RSVD_DUMMY) {
+				rtw_err(rtwdev, "first page should be a beacon\n");
+				goto release_skb;
+			}
 			total_page += rtw_len_to_page(iter->len + tx_desc_sz,
 						      page_size);
-		else
+		} else {
 			total_page += rtw_len_to_page(iter->len, page_size);
+		}
 	}
 
 	if (total_page > rtwdev->fifo.rsvd_drv_pg_num) {
@@ -647,35 +1308,62 @@
 	if (!buf)
 		goto release_skb;
 
-	list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list) {
+	/* Copy the content of each rsvd_pkt to the buf, and they should
+	 * be aligned to the pages.
+	 *
+	 * Note that the first rsvd_pkt is a beacon no matter what vif->type.
+	 * And that rsvd_pkt does not require tx_desc because when it goes
+	 * through TX path, the TX path will generate one for it.
+	 */
+	list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, build_list) {
 		rtw_rsvd_page_list_to_buf(rtwdev, page_size, page_margin,
 					  page, buf, rsvd_pkt);
-		page += rtw_len_to_page(rsvd_pkt->skb->len, page_size);
-	}
-	list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list)
+		if (page == 0)
+			page += rtw_len_to_page(rsvd_pkt->skb->len +
+						tx_desc_sz, page_size);
+		else
+			page += rtw_len_to_page(rsvd_pkt->skb->len, page_size);
+
 		kfree_skb(rsvd_pkt->skb);
+		rsvd_pkt->skb = NULL;
+	}
 
 	return buf;
 
 release_skb:
-	list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, list)
+	list_for_each_entry(rsvd_pkt, &rtwdev->rsvd_page_list, build_list) {
 		kfree_skb(rsvd_pkt->skb);
+		rsvd_pkt->skb = NULL;
+	}
 
 	return NULL;
 }
 
-static int
-rtw_download_beacon(struct rtw_dev *rtwdev, struct ieee80211_vif *vif)
+static int rtw_download_beacon(struct rtw_dev *rtwdev)
 {
 	struct ieee80211_hw *hw = rtwdev->hw;
+	struct rtw_rsvd_page *rsvd_pkt;
 	struct sk_buff *skb;
 	int ret = 0;
 
-	skb = rtw_beacon_get(hw, vif);
+	rsvd_pkt = list_first_entry_or_null(&rtwdev->rsvd_page_list,
+					    struct rtw_rsvd_page, build_list);
+	if (!rsvd_pkt) {
+		rtw_err(rtwdev, "failed to get rsvd page from build list\n");
+		return -ENOENT;
+	}
+
+	if (rsvd_pkt->type != RSVD_BEACON &&
+	    rsvd_pkt->type != RSVD_DUMMY) {
+		rtw_err(rtwdev, "invalid rsvd page type %d, should be beacon or dummy\n",
+			rsvd_pkt->type);
+		return -EINVAL;
+	}
+
+	skb = rtw_get_rsvd_page_skb(hw, rsvd_pkt);
 	if (!skb) {
 		rtw_err(rtwdev, "failed to get beacon skb\n");
-		ret = -ENOMEM;
-		goto out;
+		return -ENOMEM;
 	}
 
 	ret = rtw_download_drv_rsvd_page(rtwdev, skb->data, skb->len);
@@ -684,17 +1372,16 @@
 
 	dev_kfree_skb(skb);
 
-out:
 	return ret;
 }
 
-int rtw_fw_download_rsvd_page(struct rtw_dev *rtwdev, struct ieee80211_vif *vif)
+int rtw_fw_download_rsvd_page(struct rtw_dev *rtwdev)
 {
 	u8 *buf;
 	u32 size;
 	int ret;
 
-	buf = rtw_build_rsvd_page(rtwdev, vif, &size);
+	buf = rtw_build_rsvd_page(rtwdev, &size);
 	if (!buf) {
 		rtw_err(rtwdev, "failed to build rsvd page pkt\n");
 		return -ENOMEM;
@@ -706,7 +1393,12 @@
 		goto free;
 	}
 
-	ret = rtw_download_beacon(rtwdev, vif);
+	/* The last thing is to download the *ONLY* beacon again, because
+	 * the previous tx_desc is to describe the total rsvd page. Download
+	 * the beacon again to replace the TX desc header, and we will get
+	 * a correct tx_desc for the beacon in the rsvd page.
+	 */
+	ret = rtw_download_beacon(rtwdev);
 	if (ret) {
 		rtw_err(rtwdev, "failed to download beacon\n");
 		goto free;
@@ -764,3 +1456,81 @@
 	rtw_write8(rtwdev, REG_RCR + 2, rcr);
 	return 0;
 }
+
+static void __rtw_fw_update_pkt(struct rtw_dev *rtwdev, u8 pkt_id, u16 size,
+				u8 location)
+{
+	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
+	u16 total_size = H2C_PKT_HDR_SIZE + H2C_PKT_UPDATE_PKT_LEN;
+
+	rtw_h2c_pkt_set_header(h2c_pkt, H2C_PKT_UPDATE_PKT);
+
+	SET_PKT_H2C_TOTAL_LEN(h2c_pkt, total_size);
+	UPDATE_PKT_SET_PKT_ID(h2c_pkt, pkt_id);
+	UPDATE_PKT_SET_LOCATION(h2c_pkt, location);
+
+	/* include txdesc size */
+	UPDATE_PKT_SET_SIZE(h2c_pkt, size);
+
+	rtw_fw_send_h2c_packet(rtwdev, h2c_pkt);
+}
+
+void rtw_fw_update_pkt_probe_req(struct rtw_dev *rtwdev,
+				 struct cfg80211_ssid *ssid)
+{
+	u8 loc;
+	u32 size;
+
+	loc = rtw_get_rsvd_page_probe_req_location(rtwdev, ssid);
+	if (!loc) {
+		rtw_err(rtwdev, "failed to get probe_req rsvd loc\n");
+		return;
+	}
+
+	size = rtw_get_rsvd_page_probe_req_size(rtwdev, ssid);
+	if (!size) {
+		rtw_err(rtwdev, "failed to get probe_req rsvd size\n");
+		return;
+	}
+
+	__rtw_fw_update_pkt(rtwdev, RTW_PACKET_PROBE_REQ, size, loc);
+}
+
+void rtw_fw_channel_switch(struct rtw_dev *rtwdev, bool enable)
+{
+	struct rtw_pno_request *rtw_pno_req = &rtwdev->wow.pno_req;
+	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
+	u16 total_size = H2C_PKT_HDR_SIZE + H2C_PKT_CH_SWITCH_LEN;
+	u8 loc_ch_info;
+	const struct rtw_ch_switch_option cs_option = {
+		.dest_ch_en = 1,
+		.dest_ch = 1,
+		.periodic_option = 2,
+		.normal_period = 5,
+		.normal_period_sel = 0,
+		.normal_cycle = 10,
+		.slow_period = 1,
+		.slow_period_sel = 1,
+	};
+
+	rtw_h2c_pkt_set_header(h2c_pkt, H2C_PKT_CH_SWITCH);
+	SET_PKT_H2C_TOTAL_LEN(h2c_pkt, total_size);
+
+	CH_SWITCH_SET_START(h2c_pkt, enable);
+	CH_SWITCH_SET_DEST_CH_EN(h2c_pkt, cs_option.dest_ch_en);
+	CH_SWITCH_SET_DEST_CH(h2c_pkt, cs_option.dest_ch);
+	CH_SWITCH_SET_NORMAL_PERIOD(h2c_pkt, cs_option.normal_period);
+	CH_SWITCH_SET_NORMAL_PERIOD_SEL(h2c_pkt, cs_option.normal_period_sel);
+	CH_SWITCH_SET_SLOW_PERIOD(h2c_pkt, cs_option.slow_period);
+	CH_SWITCH_SET_SLOW_PERIOD_SEL(h2c_pkt, cs_option.slow_period_sel);
+	CH_SWITCH_SET_NORMAL_CYCLE(h2c_pkt, cs_option.normal_cycle);
+	CH_SWITCH_SET_PERIODIC_OPT(h2c_pkt, cs_option.periodic_option);
+
+	CH_SWITCH_SET_CH_NUM(h2c_pkt, rtw_pno_req->channel_cnt);
+	CH_SWITCH_SET_INFO_SIZE(h2c_pkt, rtw_pno_req->channel_cnt * 4);
+
+	loc_ch_info = rtw_get_rsvd_page_location(rtwdev, RSVD_CH_INFO);
+	CH_SWITCH_SET_INFO_LOC(h2c_pkt, loc_ch_info);
+
+	rtw_fw_send_h2c_packet(rtwdev, h2c_pkt);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/fw.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/fw.h
@@ -11,31 +11,25 @@
 /* FW bin information */
 #define FW_HDR_SIZE			64
 #define FW_HDR_CHKSUM_SIZE		8
-#define FW_HDR_VERSION			4
-#define FW_HDR_SUBVERSION		6
-#define FW_HDR_SUBINDEX			7
-#define FW_HDR_MONTH			16
-#define FW_HDR_DATE			17
-#define FW_HDR_HOUR			18
-#define FW_HDR_MIN			19
-#define FW_HDR_YEAR			20
-#define FW_HDR_MEM_USAGE		24
-#define FW_HDR_H2C_FMT_VER		28
-#define FW_HDR_DMEM_ADDR		32
-#define FW_HDR_DMEM_SIZE		36
-#define FW_HDR_IMEM_SIZE		48
-#define FW_HDR_EMEM_SIZE		52
-#define FW_HDR_EMEM_ADDR		56
-#define FW_HDR_IMEM_ADDR		60
+
+#define FW_NLO_INFO_CHECK_SIZE		4
 
 #define FIFO_PAGE_SIZE_SHIFT		12
 #define FIFO_PAGE_SIZE			4096
 #define RSVD_PAGE_START_ADDR		0x780
 #define FIFO_DUMP_ADDR			0x8000
 
+#define DLFW_PAGE_SIZE_SHIFT_LEGACY	12
+#define DLFW_PAGE_SIZE_LEGACY		0x1000
+#define DLFW_BLK_SIZE_SHIFT_LEGACY	2
+#define DLFW_BLK_SIZE_LEGACY		4
+#define FW_START_ADDR_LEGACY		0x1000
+
 enum rtw_c2h_cmd_id {
+	C2H_CCX_TX_RPT = 0x03,
 	C2H_BT_INFO = 0x09,
 	C2H_BT_MP_INFO = 0x0b,
+	C2H_RA_RPT = 0x0c,
 	C2H_HW_FEATURE_REPORT = 0x19,
 	C2H_WLAN_INFO = 0x27,
 	C2H_HW_FEATURE_DUMP = 0xfd,
@@ -54,10 +48,16 @@
 
 enum rtw_rsvd_packet_type {
 	RSVD_BEACON,
+	RSVD_DUMMY,
 	RSVD_PS_POLL,
 	RSVD_PROBE_RESP,
 	RSVD_NULL,
 	RSVD_QOS_NULL,
+	RSVD_LPS_PG_DPK,
+	RSVD_LPS_PG_INFO,
+	RSVD_PROBE_REQ,
+	RSVD_NLO_INFO,
+	RSVD_CH_INFO,
 };
 
 enum rtw_fw_rf_type {
@@ -86,17 +86,148 @@
 	u8 segment_iqk;
 };
 
+struct rtw_lps_pg_dpk_hdr {
+	u16 dpk_path_ok;
+	u8 dpk_txagc[2];
+	u16 dpk_gs[2];
+	u32 coef[2][20];
+	u8 dpk_ch;
+} __packed;
+
+struct rtw_lps_pg_info_hdr {
+	u8 macid;
+	u8 mbssid;
+	u8 pattern_count;
+	u8 mu_tab_group_id;
+	u8 sec_cam_count;
+	u8 tx_bu_page_count;
+	u16 rsvd;
+	u8 sec_cam[MAX_PG_CAM_BACKUP_NUM];
+} __packed;
+
 struct rtw_rsvd_page {
-	struct list_head list;
+	/* associated with each vif */
+	struct list_head vif_list;
+	struct rtw_vif *rtwvif;
+
+	/* associated when build rsvd page */
+	struct list_head build_list;
+
 	struct sk_buff *skb;
 	enum rtw_rsvd_packet_type type;
 	u8 page;
 	bool add_txdesc;
+	struct cfg80211_ssid *ssid;
+};
+
+enum rtw_keep_alive_pkt_type {
+	KEEP_ALIVE_NULL_PKT = 0,
+	KEEP_ALIVE_ARP_RSP = 1,
+};
+
+struct rtw_nlo_info_hdr {
+	u8 nlo_count;
+	u8 hidden_ap_count;
+	u8 rsvd1[2];
+	u8 pattern_check[FW_NLO_INFO_CHECK_SIZE];
+	u8 rsvd2[8];
+	u8 ssid_len[16];
+	u8 chiper[16];
+	u8 rsvd3[16];
+	u8 location[8];
+} __packed;
+
+enum rtw_packet_type {
+	RTW_PACKET_PROBE_REQ = 0x00,
+
+	RTW_PACKET_UNDEFINE = 0x7FFFFFFF,
 };
 
+struct rtw_fw_wow_keep_alive_para {
+	bool adopt;
+	u8 pkt_type;
+	u8 period;		/* unit: sec */
+};
+
+struct rtw_fw_wow_disconnect_para {
+	bool adopt;
+	u8 period;		/* unit: sec */
+	u8 retry_count;
+};
+
+struct rtw_ch_switch_option {
+	u8 periodic_option;
+	u32 tsf_high;
+	u32 tsf_low;
+	u8 dest_ch_en;
+	u8 absolute_time_en;
+	u8 dest_ch;
+	u8 normal_period;
+	u8 normal_period_sel;
+	u8 normal_cycle;
+	u8 slow_period;
+	u8 slow_period_sel;
+	u8 nlo_en;
+};
+
+struct rtw_fw_hdr {
+	__le16 signature;
+	u8 category;
+	u8 function;
+	__le16 version;		/* 0x04 */
+	u8 subversion;
+	u8 subindex;
+	__le32 rsvd;		/* 0x08 */
+	__le32 rsvd2;		/* 0x0C */
+	u8 month;		/* 0x10 */
+	u8 day;
+	u8 hour;
+	u8 min;
+	__le16 year;		/* 0x14 */
+	__le16 rsvd3;
+	u8 mem_usage;		/* 0x18 */
+	u8 rsvd4[3];
+	__le16 h2c_fmt_ver;	/* 0x1C */
+	__le16 rsvd5;
+	__le32 dmem_addr;	/* 0x20 */
+	__le32 dmem_size;
+	__le32 rsvd6;
+	__le32 rsvd7;
+	__le32 imem_size;	/* 0x30 */
+	__le32 emem_size;
+	__le32 emem_addr;
+	__le32 imem_addr;
+} __packed;
+
+struct rtw_fw_hdr_legacy {
+	__le16 signature;
+	u8 category;
+	u8 function;
+	__le16 version;	/* 0x04 */
+	u8 subversion1;
+	u8 subversion2;
+	u8 month;	/* 0x08 */
+	u8 day;
+	u8 hour;
+	u8 minute;
+	__le16 size;
+	__le16 rsvd2;
+	__le32 idx;	/* 0x10 */
+	__le32 rsvd3;
+	__le32 rsvd4;	/* 0x18 */
+	__le32 rsvd5;
+} __packed;
+
 /* C2H */
-#define GET_CCX_REPORT_SEQNUM(c2h_payload)	(c2h_payload[8] & 0xfc)
-#define GET_CCX_REPORT_STATUS(c2h_payload)	(c2h_payload[9] & 0xc0)
+#define GET_CCX_REPORT_SEQNUM_V0(c2h_payload)	(c2h_payload[6] & 0xfc)
+#define GET_CCX_REPORT_STATUS_V0(c2h_payload)	(c2h_payload[0] & 0xc0)
+#define GET_CCX_REPORT_SEQNUM_V1(c2h_payload)	(c2h_payload[8] & 0xfc)
+#define GET_CCX_REPORT_STATUS_V1(c2h_payload)	(c2h_payload[9] & 0xc0)
+
+#define GET_RA_REPORT_RATE(c2h_payload)		(c2h_payload[0] & 0x7f)
+#define GET_RA_REPORT_SGI(c2h_payload)		((c2h_payload[0] & 0x80) >> 7)
+#define GET_RA_REPORT_BW(c2h_payload)		(c2h_payload[6])
+#define GET_RA_REPORT_MACID(c2h_payload)	(c2h_payload[1])
 
 /* PKT H2C */
 #define H2C_PKT_CMD_ID 0xFF
@@ -106,6 +237,12 @@
 #define H2C_PKT_PHYDM_INFO 0x11
 #define H2C_PKT_IQK 0x0E
 
+#define H2C_PKT_CH_SWITCH 0x02
+#define H2C_PKT_UPDATE_PKT 0x0C
+
+#define H2C_PKT_CH_SWITCH_LEN 0x20
+#define H2C_PKT_UPDATE_PKT_LEN 0x4
+
 #define SET_PKT_H2C_CATEGORY(h2c_pkt, value)                                   \
 	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(6, 0))
 #define SET_PKT_H2C_CMD_ID(h2c_pkt, value)                                     \
@@ -142,10 +279,63 @@
 #define IQK_SET_SEGMENT_IQK(h2c_pkt, value)                                    \
 	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(1))
 
+#define CHSW_INFO_SET_CH(pkt, value)					       \
+	le32p_replace_bits((__le32 *)(pkt) + 0x00, value, GENMASK(7, 0))
+#define CHSW_INFO_SET_PRI_CH_IDX(pkt, value)				       \
+	le32p_replace_bits((__le32 *)(pkt) + 0x00, value, GENMASK(11, 8))
+#define CHSW_INFO_SET_BW(pkt, value)					       \
+	le32p_replace_bits((__le32 *)(pkt) + 0x00, value, GENMASK(15, 12))
+#define CHSW_INFO_SET_TIMEOUT(pkt, value)				       \
+	le32p_replace_bits((__le32 *)(pkt) + 0x00, value, GENMASK(23, 16))
+#define CHSW_INFO_SET_ACTION_ID(pkt, value)				       \
+	le32p_replace_bits((__le32 *)(pkt) + 0x00, value, GENMASK(30, 24))
+
+#define UPDATE_PKT_SET_SIZE(h2c_pkt, value)				       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(15, 0))
+#define UPDATE_PKT_SET_PKT_ID(h2c_pkt, value)				       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(23, 16))
+#define UPDATE_PKT_SET_LOCATION(h2c_pkt, value)				       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(31, 24))
+
+#define CH_SWITCH_SET_START(h2c_pkt, value)				       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(0))
+#define CH_SWITCH_SET_DEST_CH_EN(h2c_pkt, value)			       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(1))
+#define CH_SWITCH_SET_ABSOLUTE_TIME(h2c_pkt, value)			       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, BIT(2))
+#define CH_SWITCH_SET_PERIODIC_OPT(h2c_pkt, value)			       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(4, 3))
+#define CH_SWITCH_SET_INFO_LOC(h2c_pkt, value)				       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(15, 8))
+#define CH_SWITCH_SET_CH_NUM(h2c_pkt, value)				       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(23, 16))
+#define CH_SWITCH_SET_PRI_CH_IDX(h2c_pkt, value)			       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x02, value, GENMASK(27, 24))
+#define CH_SWITCH_SET_DEST_CH(h2c_pkt, value)				       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(7, 0))
+#define CH_SWITCH_SET_NORMAL_PERIOD(h2c_pkt, value)			       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(13, 8))
+#define CH_SWITCH_SET_NORMAL_PERIOD_SEL(h2c_pkt, value)			       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(15, 14))
+#define CH_SWITCH_SET_SLOW_PERIOD(h2c_pkt, value)			       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(21, 16))
+#define CH_SWITCH_SET_SLOW_PERIOD_SEL(h2c_pkt, value)			       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(23, 22))
+#define CH_SWITCH_SET_NORMAL_CYCLE(h2c_pkt, value)			       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x03, value, GENMASK(31, 24))
+#define CH_SWITCH_SET_TSF_HIGH(h2c_pkt, value)				       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x04, value, GENMASK(31, 0))
+#define CH_SWITCH_SET_TSF_LOW(h2c_pkt, value)				       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x05, value, GENMASK(31, 0))
+#define CH_SWITCH_SET_INFO_SIZE(h2c_pkt, value)				       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x06, value, GENMASK(15, 0))
+
 /* Command H2C */
 #define H2C_CMD_RSVD_PAGE		0x0
 #define H2C_CMD_MEDIA_STATUS_RPT	0x01
 #define H2C_CMD_SET_PWR_MODE		0x20
+#define H2C_CMD_LPS_PG_INFO		0x2b
+#define H2C_CMD_DEFAULT_PORT		0x2c
 #define H2C_CMD_RA_INFO			0x40
 #define H2C_CMD_RSSI_MONITOR		0x42
 
@@ -157,6 +347,13 @@
 #define H2C_CMD_QUERY_BT_MP_INFO	0x67
 #define H2C_CMD_BT_WIFI_CONTROL		0x69
 
+#define H2C_CMD_KEEP_ALIVE		0x03
+#define H2C_CMD_DISCONNECT_DECISION	0x04
+#define H2C_CMD_WOWLAN			0x80
+#define H2C_CMD_REMOTE_WAKE_CTRL	0x81
+#define H2C_CMD_AOAC_GLOBAL_INFO	0x82
+#define H2C_CMD_NLO_INFO		0x8C
+
 #define SET_H2C_CMD_ID_CLASS(h2c_pkt, value)				       \
 	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(7, 0))
 
@@ -177,6 +374,14 @@
 	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(7, 5))
 #define SET_PWR_MODE_SET_PWR_STATE(h2c_pkt, value)                             \
 	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(15, 8))
+#define LPS_PG_INFO_LOC(h2c_pkt, value)                                        \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16))
+#define LPS_PG_DPK_LOC(h2c_pkt, value)                                         \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(31, 24))
+#define LPS_PG_SEC_CAM_EN(h2c_pkt, value)                                      \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8))
+#define LPS_PG_PATTERN_CAM_EN(h2c_pkt, value)				       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(10))
 #define SET_RSSI_INFO_MACID(h2c_pkt, value)                                    \
 	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 8))
 #define SET_RSSI_INFO_RSSI(h2c_pkt, value)                                     \
@@ -253,6 +458,58 @@
 	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(15, 8))
 #define SET_BT_WIFI_CONTROL_DATA5(h2c_pkt, value)                              \
 	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x01, value, GENMASK(23, 16))
+#define SET_DEFAULT_PORT_PORTID(h2c_pkt, value)                                \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 8))
+
+#define SET_KEEP_ALIVE_ENABLE(h2c_pkt, value)				       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8))
+#define SET_KEEP_ALIVE_ADOPT(h2c_pkt, value)				       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(9))
+#define SET_KEEP_ALIVE_PKT_TYPE(h2c_pkt, value)				       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(10))
+#define SET_KEEP_ALIVE_CHECK_PERIOD(h2c_pkt, value)			       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16))
+
+#define SET_DISCONNECT_DECISION_ENABLE(h2c_pkt, value)			       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8))
+#define SET_DISCONNECT_DECISION_ADOPT(h2c_pkt, value)			       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(9))
+#define SET_DISCONNECT_DECISION_CHECK_PERIOD(h2c_pkt, value)		       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16))
+#define SET_DISCONNECT_DECISION_TRY_PKT_NUM(h2c_pkt, value)		       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(31, 24))
+
+#define SET_WOWLAN_FUNC_ENABLE(h2c_pkt, value)				       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8))
+#define SET_WOWLAN_PATTERN_MATCH_ENABLE(h2c_pkt, value)			       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(9))
+#define SET_WOWLAN_MAGIC_PKT_ENABLE(h2c_pkt, value)			       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(10))
+#define SET_WOWLAN_UNICAST_PKT_ENABLE(h2c_pkt, value)			       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(11))
+#define SET_WOWLAN_REKEY_WAKEUP_ENABLE(h2c_pkt, value)			       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(14))
+#define SET_WOWLAN_DEAUTH_WAKEUP_ENABLE(h2c_pkt, value)			       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(15))
+
+#define SET_REMOTE_WAKECTRL_ENABLE(h2c_pkt, value)			       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8))
+#define SET_REMOTE_WAKE_CTRL_NLO_OFFLOAD_EN(h2c_pkt, value)		       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(12))
+
+#define SET_AOAC_GLOBAL_INFO_PAIRWISE_ENC_ALG(h2c_pkt, value)		       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(15, 8))
+#define SET_AOAC_GLOBAL_INFO_GROUP_ENC_ALG(h2c_pkt, value)		       \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16))
+
+#define SET_NLO_FUN_EN(h2c_pkt, value)                                         \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(8))
+#define SET_NLO_PS_32K(h2c_pkt, value)                                         \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(9))
+#define SET_NLO_IGNORE_SECURITY(h2c_pkt, value)                                \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, BIT(10))
+#define SET_NLO_LOC_NLO_INFO(h2c_pkt, value)                                   \
+	le32p_replace_bits((__le32 *)(h2c_pkt) + 0x00, value, GENMASK(23, 16))
 
 static inline struct rtw_c2h_cmd *get_c2h_from_skb(struct sk_buff *skb)
 {
@@ -269,7 +526,9 @@
 void rtw_fw_send_phydm_info(struct rtw_dev *rtwdev);
 
 void rtw_fw_do_iqk(struct rtw_dev *rtwdev, struct rtw_iqk_para *para);
+void rtw_fw_set_default_port(struct rtw_dev *rtwdev, u8 port);
 void rtw_fw_set_pwr_mode(struct rtw_dev *rtwdev);
+void rtw_fw_set_pg_info(struct rtw_dev *rtwdev);
 void rtw_fw_query_bt_info(struct rtw_dev *rtwdev);
 void rtw_fw_wl_ch_info(struct rtw_dev *rtwdev, u8 link, u8 ch, u8 bw);
 void rtw_fw_query_bt_mp_info(struct rtw_dev *rtwdev,
@@ -282,14 +541,30 @@
 void rtw_fw_send_rssi_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si);
 void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si);
 void rtw_fw_media_status_report(struct rtw_dev *rtwdev, u8 mac_id, bool conn);
-void rtw_add_rsvd_page(struct rtw_dev *rtwdev, enum rtw_rsvd_packet_type type,
-		       bool txdesc);
 int rtw_fw_write_data_rsvd_page(struct rtw_dev *rtwdev, u16 pg_addr,
 				u8 *buf, u32 size);
-void rtw_reset_rsvd_page(struct rtw_dev *rtwdev);
-int rtw_fw_download_rsvd_page(struct rtw_dev *rtwdev,
-			      struct ieee80211_vif *vif);
+void rtw_remove_rsvd_page(struct rtw_dev *rtwdev,
+			  struct rtw_vif *rtwvif);
+void rtw_add_rsvd_page_bcn(struct rtw_dev *rtwdev,
+			   struct rtw_vif *rtwvif);
+void rtw_add_rsvd_page_pno(struct rtw_dev *rtwdev,
+			   struct rtw_vif *rtwvif);
+void rtw_add_rsvd_page_sta(struct rtw_dev *rtwdev,
+			   struct rtw_vif *rtwvif);
+int rtw_fw_download_rsvd_page(struct rtw_dev *rtwdev);
 void rtw_send_rsvd_page_h2c(struct rtw_dev *rtwdev);
 int rtw_dump_drv_rsvd_page(struct rtw_dev *rtwdev,
 			   u32 offset, u32 size, u32 *buf);
+void rtw_fw_set_remote_wake_ctrl_cmd(struct rtw_dev *rtwdev, bool enable);
+void rtw_fw_set_wowlan_ctrl_cmd(struct rtw_dev *rtwdev, bool enable);
+void rtw_fw_set_keep_alive_cmd(struct rtw_dev *rtwdev, bool enable);
+void rtw_fw_set_disconnect_decision_cmd(struct rtw_dev *rtwdev, bool enable);
+void rtw_fw_set_aoac_global_info_cmd(struct rtw_dev *rtwdev,
+				     u8 pairwise_key_enc,
+				     u8 group_key_enc);
+
+void rtw_fw_set_nlo_info(struct rtw_dev *rtwdev, bool enable);
+void rtw_fw_update_pkt_probe_req(struct rtw_dev *rtwdev,
+				 struct cfg80211_ssid *ssid);
+void rtw_fw_channel_switch(struct rtw_dev *rtwdev, bool enable);
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/hci.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/hci.h
@@ -13,6 +13,9 @@
 	int (*setup)(struct rtw_dev *rtwdev);
 	int (*start)(struct rtw_dev *rtwdev);
 	void (*stop)(struct rtw_dev *rtwdev);
+	void (*deep_ps)(struct rtw_dev *rtwdev, bool enter);
+	void (*link_ps)(struct rtw_dev *rtwdev, bool enter);
+	void (*interface_cfg)(struct rtw_dev *rtwdev);
 
 	int (*write_data_rsvd_page)(struct rtw_dev *rtwdev, u8 *buf, u32 size);
 	int (*write_data_h2c)(struct rtw_dev *rtwdev, u8 *buf, u32 size);
@@ -47,6 +50,21 @@
 	rtwdev->hci.ops->stop(rtwdev);
 }
 
+static inline void rtw_hci_deep_ps(struct rtw_dev *rtwdev, bool enter)
+{
+	rtwdev->hci.ops->deep_ps(rtwdev, enter);
+}
+
+static inline void rtw_hci_link_ps(struct rtw_dev *rtwdev, bool enter)
+{
+	rtwdev->hci.ops->link_ps(rtwdev, enter);
+}
+
+static inline void rtw_hci_interface_cfg(struct rtw_dev *rtwdev)
+{
+	rtwdev->hci.ops->interface_cfg(rtwdev);
+}
+
 static inline int
 rtw_hci_write_data_rsvd_page(struct rtw_dev *rtwdev, u8 *buf, u32 size)
 {
@@ -173,6 +191,32 @@
 	ret = (orig & mask) >> shift;
 
 	return ret;
+}
+
+static inline u16
+rtw_read16_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask)
+{
+	u32 shift = __ffs(mask);
+	u32 orig;
+	u32 ret;
+
+	orig = rtw_read16(rtwdev, addr);
+	ret = (orig & mask) >> shift;
+
+	return ret;
+}
+
+static inline u8
+rtw_read8_mask(struct rtw_dev *rtwdev, u32 addr, u32 mask)
+{
+	u32 shift = __ffs(mask);
+	u32 orig;
+	u32 ret;
+
+	orig = rtw_read8(rtwdev, addr);
+	ret = (orig & mask) >> shift;
+
+	return ret;
 }
 
 static inline void
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/mac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/mac.c
@@ -16,10 +16,12 @@
 	u8 value8;
 
 	txsc20 = primary_ch_idx;
-	if (txsc20 == 1 || txsc20 == 3)
-		txsc40 = 9;
-	else
-		txsc40 = 10;
+	if (bw == RTW_CHANNEL_WIDTH_80) {
+		if (txsc20 == RTW_SC_20_UPPER || txsc20 == RTW_SC_20_UPMOST)
+			txsc40 = RTW_SC_40_UPPER;
+		else
+			txsc40 = RTW_SC_40_LOWER;
+	}
 	rtw_write8(rtwdev, REG_DATA_SC,
 		   BIT_TXSC_20M(txsc20) | BIT_TXSC_40M(txsc40));
 
@@ -38,6 +40,9 @@
 	}
 	rtw_write32(rtwdev, REG_WMAC_TRXPTCL_CTL, value32);
 
+	if (rtw_chip_wcpu_11n(rtwdev))
+		return;
+
 	value32 = rtw_read32(rtwdev, REG_AFE_CTRL1) & ~(BIT_MAC_CLK_SEL);
 	value32 |= (MAC_CLK_HW_DEF_80M << BIT_SHIFT_MAC_CLK_SEL);
 	rtw_write32(rtwdev, REG_AFE_CTRL1, value32);
@@ -47,7 +52,7 @@
 
 	value8 = rtw_read8(rtwdev, REG_CCK_CHECK);
 	value8 = value8 & ~BIT_CHECK_CCK_EN;
-	if (channel > 35)
+	if (IS_CH_5G_BAND(channel))
 		value8 |= BIT_CHECK_CCK_EN;
 	rtw_write8(rtwdev, REG_CCK_CHECK, value8);
 }
@@ -59,6 +64,14 @@
 
 	rtw_write8(rtwdev, REG_RSV_CTRL, 0);
 
+	if (rtw_chip_wcpu_11n(rtwdev)) {
+		if (rtw_read32(rtwdev, REG_SYS_CFG1) & BIT_LDO)
+			rtw_write8(rtwdev, REG_LDO_SWR_CTRL, LDO_SEL);
+		else
+			rtw_write8(rtwdev, REG_LDO_SWR_CTRL, SPS_SEL);
+		return 0;
+	}
+
 	switch (rtw_hci_type(rtwdev)) {
 	case RTW_HCI_TYPE_PCIE:
 		rtw_write32_set(rtwdev, REG_HCI_OPT_CTRL, BIT_BT_DIG_CLK_EN);
@@ -98,42 +111,55 @@
 	return 0;
 }
 
+static bool do_pwr_poll_cmd(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 target)
+{
+	u32 cnt;
+
+	target &= mask;
+
+	for (cnt = 0; cnt < RTW_PWR_POLLING_CNT; cnt++) {
+		if ((rtw_read8(rtwdev, addr) & mask) == target)
+			return true;
+
+		udelay(50);
+	}
+
+	return false;
+}
+
 static int rtw_pwr_cmd_polling(struct rtw_dev *rtwdev,
 			       struct rtw_pwr_seq_cmd *cmd)
 {
 	u8 value;
-	u8 flag = 0;
 	u32 offset;
-	u32 cnt = RTW_PWR_POLLING_CNT;
 
 	if (cmd->base == RTW_PWR_ADDR_SDIO)
 		offset = cmd->offset | SDIO_LOCAL_OFFSET;
 	else
 		offset = cmd->offset;
 
-	do {
-		cnt--;
-		value = rtw_read8(rtwdev, offset);
-		value &= cmd->mask;
-		if (value == (cmd->value & cmd->mask))
-			return 0;
-		if (cnt == 0) {
-			if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_PCIE &&
-			    flag == 0) {
-				value = rtw_read8(rtwdev, REG_SYS_PW_CTRL);
-				value |= BIT(3);
-				rtw_write8(rtwdev, REG_SYS_PW_CTRL, value);
-				value &= ~BIT(3);
-				rtw_write8(rtwdev, REG_SYS_PW_CTRL, value);
-				cnt = RTW_PWR_POLLING_CNT;
-				flag = 1;
-			} else {
-				return -EBUSY;
-			}
-		} else {
-			udelay(50);
-		}
-	} while (1);
+	if (do_pwr_poll_cmd(rtwdev, offset, cmd->mask, cmd->value))
+		return 0;
+
+	if (rtw_hci_type(rtwdev) != RTW_HCI_TYPE_PCIE)
+		goto err;
+
+	/* if PCIE, toggle BIT_PFM_WOWL and try again */
+	value = rtw_read8(rtwdev, REG_SYS_PW_CTRL);
+	if (rtwdev->chip->id == RTW_CHIP_TYPE_8723D)
+		rtw_write8(rtwdev, REG_SYS_PW_CTRL, value & ~BIT_PFM_WOWL);
+	rtw_write8(rtwdev, REG_SYS_PW_CTRL, value | BIT_PFM_WOWL);
+	rtw_write8(rtwdev, REG_SYS_PW_CTRL, value & ~BIT_PFM_WOWL);
+	if (rtwdev->chip->id == RTW_CHIP_TYPE_8723D)
+		rtw_write8(rtwdev, REG_SYS_PW_CTRL, value | BIT_PFM_WOWL);
+
+	if (do_pwr_poll_cmd(rtwdev, offset, cmd->mask, cmd->value))
+		return 0;
+
+err:
+	rtw_err(rtwdev, "failed to poll offset=0x%x mask=0x%x value=0x%x\n",
+		offset, cmd->mask, cmd->value);
+	return -EBUSY;
 }
 
 static int rtw_sub_pwr_seq_parser(struct rtw_dev *rtwdev, u8 intf_mask,
@@ -210,7 +236,7 @@
 
 		ret = rtw_sub_pwr_seq_parser(rtwdev, intf_mask, cut_mask, cmd);
 		if (ret)
-			return -EBUSY;
+			return ret;
 
 		idx++;
 	} while (1);
@@ -224,13 +250,16 @@
 	struct rtw_pwr_seq_cmd **pwr_seq;
 	u8 rpwm;
 	bool cur_pwr;
+	int ret;
 
-	rpwm = rtw_read8(rtwdev, rtwdev->hci.rpwm_addr);
+	if (rtw_chip_wcpu_11ac(rtwdev)) {
+		rpwm = rtw_read8(rtwdev, rtwdev->hci.rpwm_addr);
 
-	/* Check FW still exist or not */
-	if (rtw_read16(rtwdev, REG_MCUFW_CTRL) == 0xC078) {
-		rpwm = (rpwm ^ BIT_RPWM_TOGGLE) & BIT_RPWM_TOGGLE;
-		rtw_write8(rtwdev, rtwdev->hci.rpwm_addr, rpwm);
+		/* Check FW still exist or not */
+		if (rtw_read16(rtwdev, REG_MCUFW_CTRL) == 0xC078) {
+			rpwm = (rpwm ^ BIT_RPWM_TOGGLE) & BIT_RPWM_TOGGLE;
+			rtw_write8(rtwdev, rtwdev->hci.rpwm_addr, rpwm);
+		}
 	}
 
 	if (rtw_read8(rtwdev, REG_CR) == 0xea)
@@ -241,17 +270,18 @@
 	else
 		cur_pwr = true;
 
-	if (pwr_on && cur_pwr)
+	if (pwr_on == cur_pwr)
 		return -EALREADY;
 
 	pwr_seq = pwr_on ? chip->pwr_on_seq : chip->pwr_off_seq;
-	if (rtw_pwr_seq_parser(rtwdev, pwr_seq))
-		return -EINVAL;
+	ret = rtw_pwr_seq_parser(rtwdev, pwr_seq);
+	if (ret)
+		return ret;
 
 	return 0;
 }
 
-static int rtw_mac_init_system_cfg(struct rtw_dev *rtwdev)
+static int __rtw_mac_init_system_cfg(struct rtw_dev *rtwdev)
 {
 	u8 sys_func_en = rtwdev->chip->sys_func_en;
 	u8 value8;
@@ -261,7 +291,7 @@
 	value |= BIT_WL_PLATFORM_RST | BIT_DDMA_EN;
 	rtw_write32(rtwdev, REG_CPU_DMEM_CON, value);
 
-	rtw_write8(rtwdev, REG_SYS_FUNC_EN + 1, sys_func_en);
+	rtw_write8_set(rtwdev, REG_SYS_FUNC_EN + 1, sys_func_en);
 	value8 = (rtw_read8(rtwdev, REG_CR_EXT + 3) & 0xF0) | 0x0C;
 	rtw_write8(rtwdev, REG_CR_EXT + 3, value8);
 
@@ -276,6 +306,29 @@
 	return 0;
 }
 
+static int __rtw_mac_init_system_cfg_legacy(struct rtw_dev *rtwdev)
+{
+	rtw_write8(rtwdev, REG_CR, 0xff);
+	mdelay(2);
+	rtw_write8(rtwdev, REG_HWSEQ_CTRL, 0x7f);
+	mdelay(2);
+
+	rtw_write8_set(rtwdev, REG_SYS_CLKR, BIT_WAKEPAD_EN);
+	rtw_write16_clr(rtwdev, REG_GPIO_MUXCFG, BIT_EN_SIC);
+
+	rtw_write16(rtwdev, REG_CR, 0x2ff);
+
+	return 0;
+}
+
+static int rtw_mac_init_system_cfg(struct rtw_dev *rtwdev)
+{
+	if (rtw_chip_wcpu_11n(rtwdev))
+		return __rtw_mac_init_system_cfg_legacy(rtwdev);
+
+	return __rtw_mac_init_system_cfg(rtwdev);
+}
+
 int rtw_mac_power_on(struct rtw_dev *rtwdev)
 {
 	int ret = 0;
@@ -312,15 +365,16 @@
 
 static bool check_firmware_size(const u8 *data, u32 size)
 {
+	const struct rtw_fw_hdr *fw_hdr = (const struct rtw_fw_hdr *)data;
 	u32 dmem_size;
 	u32 imem_size;
 	u32 emem_size;
 	u32 real_size;
 
-	dmem_size = le32_to_cpu(*((__le32 *)(data + FW_HDR_DMEM_SIZE)));
-	imem_size = le32_to_cpu(*((__le32 *)(data + FW_HDR_IMEM_SIZE)));
-	emem_size = ((*(data + FW_HDR_MEM_USAGE)) & BIT(4)) ?
-		    le32_to_cpu(*((__le32 *)(data + FW_HDR_EMEM_SIZE))) : 0;
+	dmem_size = le32_to_cpu(fw_hdr->dmem_size);
+	imem_size = le32_to_cpu(fw_hdr->imem_size);
+	emem_size = (fw_hdr->mem_usage & BIT(4)) ?
+		    le32_to_cpu(fw_hdr->emem_size) : 0;
 
 	dmem_size += FW_HDR_CHKSUM_SIZE;
 	imem_size += FW_HDR_CHKSUM_SIZE;
@@ -566,27 +620,10 @@
 	return 0;
 }
 
-static void update_firmware_info(struct rtw_dev *rtwdev,
-				 struct rtw_fw_state *fw)
-{
-	const u8 *data = fw->firmware->data;
-
-	fw->h2c_version =
-		le16_to_cpu(*((__le16 *)(data + FW_HDR_H2C_FMT_VER)));
-	fw->version =
-		le16_to_cpu(*((__le16 *)(data + FW_HDR_VERSION)));
-	fw->sub_version = *(data + FW_HDR_SUBVERSION);
-	fw->sub_index = *(data + FW_HDR_SUBINDEX);
-
-	rtw_dbg(rtwdev, RTW_DBG_FW, "fw h2c version: %x\n", fw->h2c_version);
-	rtw_dbg(rtwdev, RTW_DBG_FW, "fw version:     %x\n", fw->version);
-	rtw_dbg(rtwdev, RTW_DBG_FW, "fw sub version: %x\n", fw->sub_version);
-	rtw_dbg(rtwdev, RTW_DBG_FW, "fw sub index:   %x\n", fw->sub_index);
-}
-
 static int
 start_download_firmware(struct rtw_dev *rtwdev, const u8 *data, u32 size)
 {
+	const struct rtw_fw_hdr *fw_hdr = (const struct rtw_fw_hdr *)data;
 	const u8 *cur_fw;
 	u16 val;
 	u32 imem_size;
@@ -595,10 +632,10 @@
 	u32 addr;
 	int ret;
 
-	dmem_size = le32_to_cpu(*((__le32 *)(data + FW_HDR_DMEM_SIZE)));
-	imem_size = le32_to_cpu(*((__le32 *)(data + FW_HDR_IMEM_SIZE)));
-	emem_size = ((*(data + FW_HDR_MEM_USAGE)) & BIT(4)) ?
-		    le32_to_cpu(*((__le32 *)(data + FW_HDR_EMEM_SIZE))) : 0;
+	dmem_size = le32_to_cpu(fw_hdr->dmem_size);
+	imem_size = le32_to_cpu(fw_hdr->imem_size);
+	emem_size = (fw_hdr->mem_usage & BIT(4)) ?
+		    le32_to_cpu(fw_hdr->emem_size) : 0;
 	dmem_size += FW_HDR_CHKSUM_SIZE;
 	imem_size += FW_HDR_CHKSUM_SIZE;
 	emem_size += emem_size ? FW_HDR_CHKSUM_SIZE : 0;
@@ -608,14 +645,14 @@
 	rtw_write16(rtwdev, REG_MCUFW_CTRL, val);
 
 	cur_fw = data + FW_HDR_SIZE;
-	addr = le32_to_cpu(*((__le32 *)(data + FW_HDR_DMEM_ADDR)));
+	addr = le32_to_cpu(fw_hdr->dmem_addr);
 	addr &= ~BIT(31);
 	ret = download_firmware_to_mem(rtwdev, cur_fw, 0, addr, dmem_size);
 	if (ret)
 		return ret;
 
 	cur_fw = data + FW_HDR_SIZE + dmem_size;
-	addr = le32_to_cpu(*((__le32 *)(data + FW_HDR_IMEM_ADDR)));
+	addr = le32_to_cpu(fw_hdr->imem_addr);
 	addr &= ~BIT(31);
 	ret = download_firmware_to_mem(rtwdev, cur_fw, 0, addr, imem_size);
 	if (ret)
@@ -623,7 +660,7 @@
 
 	if (emem_size) {
 		cur_fw = data + FW_HDR_SIZE + dmem_size + imem_size;
-		addr = le32_to_cpu(*((__le32 *)(data + FW_HDR_EMEM_ADDR)));
+		addr = le32_to_cpu(fw_hdr->emem_addr);
 		addr &= ~BIT(31);
 		ret = download_firmware_to_mem(rtwdev, cur_fw, 0, addr,
 					       emem_size);
@@ -663,7 +700,7 @@
 	rtw_write16(rtwdev, REG_MCUFW_CTRL, fw_ctrl);
 }
 
-int rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw)
+int __rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw)
 {
 	struct rtw_backup_info bckp[DLFW_RESTORE_REG_NUM];
 	const u8 *data = fw->firmware->data;
@@ -699,15 +736,13 @@
 	if (ret)
 		goto dlfw_fail;
 
-	update_firmware_info(rtwdev, fw);
-
 	/* reset desc and index */
 	rtw_hci_setup(rtwdev);
 
 	rtwdev->h2c.last_box_num = 0;
 	rtwdev->h2c.seq = 0;
 
-	rtw_flag_set(rtwdev, RTW_FLAG_FW_RUNNING);
+	set_bit(RTW_FLAG_FW_RUNNING, rtwdev->flags);
 
 	return 0;
 
@@ -719,6 +754,230 @@
 	return ret;
 }
 
+static void en_download_firmware_legacy(struct rtw_dev *rtwdev, bool en)
+{
+	int try;
+
+	if (en) {
+		wlan_cpu_enable(rtwdev, false);
+		wlan_cpu_enable(rtwdev, true);
+
+		rtw_write8_set(rtwdev, REG_MCUFW_CTRL, BIT_MCUFWDL_EN);
+
+		for (try = 0; try < 10; try++) {
+			if (rtw_read8(rtwdev, REG_MCUFW_CTRL) & BIT_MCUFWDL_EN)
+				goto fwdl_ready;
+			rtw_write8_set(rtwdev, REG_MCUFW_CTRL, BIT_MCUFWDL_EN);
+			msleep(20);
+		}
+		rtw_err(rtwdev, "failed to check fw download ready\n");
+fwdl_ready:
+		rtw_write32_clr(rtwdev, REG_MCUFW_CTRL, BIT_ROM_DLEN);
+	} else {
+		rtw_write8_clr(rtwdev, REG_MCUFW_CTRL, BIT_MCUFWDL_EN);
+	}
+}
+
+static void
+write_firmware_page(struct rtw_dev *rtwdev, u32 page, const u8 *data, u32 size)
+{
+	u32 val32;
+	u32 block_nr;
+	u32 remain_size;
+	u32 write_addr = FW_START_ADDR_LEGACY;
+	const __le32 *ptr = (const __le32 *)data;
+	u32 block;
+	__le32 remain_data = 0;
+
+	block_nr = size >> DLFW_BLK_SIZE_SHIFT_LEGACY;
+	remain_size = size & (DLFW_BLK_SIZE_LEGACY - 1);
+
+	val32 = rtw_read32(rtwdev, REG_MCUFW_CTRL);
+	val32 &= ~BIT_ROM_PGE;
+	val32 |= (page << BIT_SHIFT_ROM_PGE) & BIT_ROM_PGE;
+	rtw_write32(rtwdev, REG_MCUFW_CTRL, val32);
+
+	for (block = 0; block < block_nr; block++) {
+		rtw_write32(rtwdev, write_addr, le32_to_cpu(*ptr));
+
+		write_addr += DLFW_BLK_SIZE_LEGACY;
+		ptr++;
+	}
+
+	if (remain_size) {
+		memcpy(&remain_data, ptr, remain_size);
+		rtw_write32(rtwdev, write_addr, le32_to_cpu(remain_data));
+	}
+}
+
+static int
+download_firmware_legacy(struct rtw_dev *rtwdev, const u8 *data, u32 size)
+{
+	u32 page;
+	u32 total_page;
+	u32 last_page_size;
+
+	data += sizeof(struct rtw_fw_hdr_legacy);
+	size -= sizeof(struct rtw_fw_hdr_legacy);
+
+	total_page = size >> DLFW_PAGE_SIZE_SHIFT_LEGACY;
+	last_page_size = size & (DLFW_PAGE_SIZE_LEGACY - 1);
+
+	rtw_write8_set(rtwdev, REG_MCUFW_CTRL, BIT_FWDL_CHK_RPT);
+
+	for (page = 0; page < total_page; page++) {
+		write_firmware_page(rtwdev, page, data, DLFW_PAGE_SIZE_LEGACY);
+		data += DLFW_PAGE_SIZE_LEGACY;
+	}
+	if (last_page_size)
+		write_firmware_page(rtwdev, page, data, last_page_size);
+
+	if (!check_hw_ready(rtwdev, REG_MCUFW_CTRL, BIT_FWDL_CHK_RPT, 1)) {
+		rtw_err(rtwdev, "failed to check download fimrware report\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int download_firmware_validate_legacy(struct rtw_dev *rtwdev)
+{
+	u32 val32;
+	int try;
+
+	val32 = rtw_read32(rtwdev, REG_MCUFW_CTRL);
+	val32 |= BIT_MCUFWDL_RDY;
+	val32 &= ~BIT_WINTINI_RDY;
+	rtw_write32(rtwdev, REG_MCUFW_CTRL, val32);
+
+	wlan_cpu_enable(rtwdev, false);
+	wlan_cpu_enable(rtwdev, true);
+
+	for (try = 0; try < 10; try++) {
+		val32 = rtw_read32(rtwdev, REG_MCUFW_CTRL);
+		if ((val32 & FW_READY_LEGACY) == FW_READY_LEGACY)
+			return 0;
+		msleep(20);
+	}
+
+	rtw_err(rtwdev, "failed to validate fimrware\n");
+	return -EINVAL;
+}
+
+int __rtw_download_firmware_legacy(struct rtw_dev *rtwdev, struct rtw_fw_state *fw)
+{
+	int ret = 0;
+
+	en_download_firmware_legacy(rtwdev, true);
+	ret = download_firmware_legacy(rtwdev, fw->firmware->data, fw->firmware->size);
+	en_download_firmware_legacy(rtwdev, false);
+	if (ret)
+		goto out;
+
+	ret = download_firmware_validate_legacy(rtwdev);
+	if (ret)
+		goto out;
+
+	/* reset desc and index */
+	rtw_hci_setup(rtwdev);
+
+	rtwdev->h2c.last_box_num = 0;
+	rtwdev->h2c.seq = 0;
+
+	set_bit(RTW_FLAG_FW_RUNNING, rtwdev->flags);
+
+out:
+	return ret;
+}
+
+int rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw)
+{
+	if (rtw_chip_wcpu_11n(rtwdev))
+		return __rtw_download_firmware_legacy(rtwdev, fw);
+
+	return __rtw_download_firmware(rtwdev, fw);
+}
+
+static u32 get_priority_queues(struct rtw_dev *rtwdev, u32 queues)
+{
+	struct rtw_rqpn *rqpn = rtwdev->fifo.rqpn;
+	u32 prio_queues = 0;
+
+	if (queues & BIT(IEEE80211_AC_VO))
+		prio_queues |= BIT(rqpn->dma_map_vo);
+	if (queues & BIT(IEEE80211_AC_VI))
+		prio_queues |= BIT(rqpn->dma_map_vi);
+	if (queues & BIT(IEEE80211_AC_BE))
+		prio_queues |= BIT(rqpn->dma_map_be);
+	if (queues & BIT(IEEE80211_AC_BK))
+		prio_queues |= BIT(rqpn->dma_map_bk);
+
+	return prio_queues;
+}
+
+static void __rtw_mac_flush_prio_queue(struct rtw_dev *rtwdev,
+				       u32 prio_queue, bool drop)
+{
+	struct rtw_chip_info *chip = rtwdev->chip;
+	struct rtw_prioq_addr *addr;
+	bool wsize;
+	u16 avail_page, rsvd_page;
+	int i;
+
+	if (prio_queue >= RTW_DMA_MAPPING_MAX)
+		return;
+
+	addr = &chip->prioq_addrs->prio[prio_queue];
+	wsize = chip->prioq_addrs->wsize;
+
+	/* check if all of the reserved pages are available for 100 msecs */
+	for (i = 0; i < 5; i++) {
+		rsvd_page = wsize ? rtw_read16(rtwdev, addr->rsvd) :
+				     rtw_read8(rtwdev, addr->rsvd);
+		avail_page = wsize ? rtw_read16(rtwdev, addr->avail) :
+				      rtw_read8(rtwdev, addr->avail);
+		if (rsvd_page == avail_page)
+			return;
+
+		msleep(20);
+	}
+
+	/* priority queue is still not empty, throw a warning,
+	 *
+	 * Note that if we want to flush the tx queue when having a lot of
+	 * traffic (ex, 100Mbps up), some of the packets could be dropped.
+	 * And it requires like ~2secs to flush the full priority queue.
+	 */
+	if (!drop)
+		rtw_warn(rtwdev, "timed out to flush queue %d\n", prio_queue);
+}
+
+static void rtw_mac_flush_prio_queues(struct rtw_dev *rtwdev,
+				      u32 prio_queues, bool drop)
+{
+	u32 q;
+
+	for (q = 0; q < RTW_DMA_MAPPING_MAX; q++)
+		if (prio_queues & BIT(q))
+			__rtw_mac_flush_prio_queue(rtwdev, q, drop);
+}
+
+void rtw_mac_flush_queues(struct rtw_dev *rtwdev, u32 queues, bool drop)
+{
+	u32 prio_queues = 0;
+
+	/* If all of the hardware queues are requested to flush,
+	 * or the priority queues are not mapped yet,
+	 * flush all of the priority queues
+	 */
+	if (queues == BIT(rtwdev->hw->queues) - 1 || !rtwdev->fifo.rqpn)
+		prio_queues = BIT(RTW_DMA_MAPPING_MAX) - 1;
+	else
+		prio_queues = get_priority_queues(rtwdev, queues);
+
+	rtw_mac_flush_prio_queues(rtwdev, prio_queues, drop);
+}
+
 static int txdma_queue_mapping(struct rtw_dev *rtwdev)
 {
 	struct rtw_chip_info *chip = rtwdev->chip;
@@ -743,6 +1002,7 @@
 		return -EINVAL;
 	}
 
+	rtwdev->fifo.rqpn = rqpn;
 	txdma_pq_map |= BIT_TXDMA_HIQ_MAP(rqpn->dma_map_hi);
 	txdma_pq_map |= BIT_TXDMA_MGQ_MAP(rqpn->dma_map_mg);
 	txdma_pq_map |= BIT_TXDMA_BKQ_MAP(rqpn->dma_map_bk);
@@ -753,7 +1013,8 @@
 
 	rtw_write8(rtwdev, REG_CR, 0);
 	rtw_write8(rtwdev, REG_CR, MAC_TRX_ENABLE);
-	rtw_write32(rtwdev, REG_H2CQ_CSR, BIT_H2CQ_FULL);
+	if (rtw_chip_wcpu_11ac(rtwdev))
+		rtw_write32(rtwdev, REG_H2CQ_CSR, BIT_H2CQ_FULL);
 
 	return 0;
 }
@@ -768,13 +1029,16 @@
 	/* config rsvd page num */
 	fifo->rsvd_drv_pg_num = 8;
 	fifo->txff_pg_num = chip->txff_size >> 7;
-	fifo->rsvd_pg_num = fifo->rsvd_drv_pg_num +
-			   RSVD_PG_H2C_EXTRAINFO_NUM +
-			   RSVD_PG_H2C_STATICINFO_NUM +
-			   RSVD_PG_H2CQ_NUM +
-			   RSVD_PG_CPU_INSTRUCTION_NUM +
-			   RSVD_PG_FW_TXBUF_NUM +
-			   csi_buf_pg_num;
+	if (rtw_chip_wcpu_11n(rtwdev))
+		fifo->rsvd_pg_num = fifo->rsvd_drv_pg_num;
+	else
+		fifo->rsvd_pg_num = fifo->rsvd_drv_pg_num +
+				   RSVD_PG_H2C_EXTRAINFO_NUM +
+				   RSVD_PG_H2C_STATICINFO_NUM +
+				   RSVD_PG_H2CQ_NUM +
+				   RSVD_PG_CPU_INSTRUCTION_NUM +
+				   RSVD_PG_FW_TXBUF_NUM +
+				   csi_buf_pg_num;
 
 	if (fifo->rsvd_pg_num > fifo->txff_pg_num)
 		return -ENOMEM;
@@ -783,18 +1047,20 @@
 	fifo->rsvd_boundary = fifo->txff_pg_num - fifo->rsvd_pg_num;
 
 	cur_pg_addr = fifo->txff_pg_num;
-	cur_pg_addr -= csi_buf_pg_num;
-	fifo->rsvd_csibuf_addr = cur_pg_addr;
-	cur_pg_addr -= RSVD_PG_FW_TXBUF_NUM;
-	fifo->rsvd_fw_txbuf_addr = cur_pg_addr;
-	cur_pg_addr -= RSVD_PG_CPU_INSTRUCTION_NUM;
-	fifo->rsvd_cpu_instr_addr = cur_pg_addr;
-	cur_pg_addr -= RSVD_PG_H2CQ_NUM;
-	fifo->rsvd_h2cq_addr = cur_pg_addr;
-	cur_pg_addr -= RSVD_PG_H2C_STATICINFO_NUM;
-	fifo->rsvd_h2c_sta_info_addr = cur_pg_addr;
-	cur_pg_addr -= RSVD_PG_H2C_EXTRAINFO_NUM;
-	fifo->rsvd_h2c_info_addr = cur_pg_addr;
+	if (rtw_chip_wcpu_11ac(rtwdev)) {
+		cur_pg_addr -= csi_buf_pg_num;
+		fifo->rsvd_csibuf_addr = cur_pg_addr;
+		cur_pg_addr -= RSVD_PG_FW_TXBUF_NUM;
+		fifo->rsvd_fw_txbuf_addr = cur_pg_addr;
+		cur_pg_addr -= RSVD_PG_CPU_INSTRUCTION_NUM;
+		fifo->rsvd_cpu_instr_addr = cur_pg_addr;
+		cur_pg_addr -= RSVD_PG_H2CQ_NUM;
+		fifo->rsvd_h2cq_addr = cur_pg_addr;
+		cur_pg_addr -= RSVD_PG_H2C_STATICINFO_NUM;
+		fifo->rsvd_h2c_sta_info_addr = cur_pg_addr;
+		cur_pg_addr -= RSVD_PG_H2C_EXTRAINFO_NUM;
+		fifo->rsvd_h2c_info_addr = cur_pg_addr;
+	}
 	cur_pg_addr -= fifo->rsvd_drv_pg_num;
 	fifo->rsvd_drv_addr = cur_pg_addr;
 
@@ -806,6 +1072,63 @@
 	return 0;
 }
 
+static int __priority_queue_cfg(struct rtw_dev *rtwdev,
+				struct rtw_page_table *pg_tbl, u16 pubq_num)
+{
+	struct rtw_fifo_conf *fifo = &rtwdev->fifo;
+	struct rtw_chip_info *chip = rtwdev->chip;
+
+	rtw_write16(rtwdev, REG_FIFOPAGE_INFO_1, pg_tbl->hq_num);
+	rtw_write16(rtwdev, REG_FIFOPAGE_INFO_2, pg_tbl->lq_num);
+	rtw_write16(rtwdev, REG_FIFOPAGE_INFO_3, pg_tbl->nq_num);
+	rtw_write16(rtwdev, REG_FIFOPAGE_INFO_4, pg_tbl->exq_num);
+	rtw_write16(rtwdev, REG_FIFOPAGE_INFO_5, pubq_num);
+	rtw_write32_set(rtwdev, REG_RQPN_CTRL_2, BIT_LD_RQPN);
+
+	rtw_write16(rtwdev, REG_FIFOPAGE_CTRL_2, fifo->rsvd_boundary);
+	rtw_write8_set(rtwdev, REG_FWHW_TXQ_CTRL + 2, BIT_EN_WR_FREE_TAIL >> 16);
+
+	rtw_write16(rtwdev, REG_BCNQ_BDNY_V1, fifo->rsvd_boundary);
+	rtw_write16(rtwdev, REG_FIFOPAGE_CTRL_2 + 2, fifo->rsvd_boundary);
+	rtw_write16(rtwdev, REG_BCNQ1_BDNY_V1, fifo->rsvd_boundary);
+	rtw_write32(rtwdev, REG_RXFF_BNDY, chip->rxff_size - C2H_PKT_BUF - 1);
+	rtw_write8_set(rtwdev, REG_AUTO_LLT_V1, BIT_AUTO_INIT_LLT_V1);
+
+	if (!check_hw_ready(rtwdev, REG_AUTO_LLT_V1, BIT_AUTO_INIT_LLT_V1, 0))
+		return -EBUSY;
+
+	rtw_write8(rtwdev, REG_CR + 3, 0);
+
+	return 0;
+}
+
+static int __priority_queue_cfg_legacy(struct rtw_dev *rtwdev,
+				       struct rtw_page_table *pg_tbl, u16 pubq_num)
+{
+	struct rtw_fifo_conf *fifo = &rtwdev->fifo;
+	struct rtw_chip_info *chip = rtwdev->chip;
+	u32 val32;
+
+	val32 = BIT_RQPN_NE(pg_tbl->nq_num, pg_tbl->exq_num);
+	rtw_write32(rtwdev, REG_RQPN_NPQ, val32);
+	val32 = BIT_RQPN_HLP(pg_tbl->hq_num, pg_tbl->lq_num, pubq_num);
+	rtw_write32(rtwdev, REG_RQPN, val32);
+
+	rtw_write8(rtwdev, REG_TRXFF_BNDY, fifo->rsvd_boundary);
+	rtw_write16(rtwdev, REG_TRXFF_BNDY + 2, chip->rxff_size - REPORT_BUF - 1);
+	rtw_write8(rtwdev, REG_DWBCN0_CTRL + 1, fifo->rsvd_boundary);
+	rtw_write8(rtwdev, REG_BCNQ_BDNY, fifo->rsvd_boundary);
+	rtw_write8(rtwdev, REG_MGQ_BDNY, fifo->rsvd_boundary);
+	rtw_write8(rtwdev, REG_WMAC_LBK_BF_HD, fifo->rsvd_boundary);
+
+	rtw_write32_set(rtwdev, REG_AUTO_LLT, BIT_AUTO_INIT_LLT);
+
+	if (!check_hw_ready(rtwdev, REG_AUTO_LLT, BIT_AUTO_INIT_LLT, 0))
+		return -EBUSY;
+
+	return 0;
+}
+
 static int priority_queue_cfg(struct rtw_dev *rtwdev)
 {
 	struct rtw_fifo_conf *fifo = &rtwdev->fifo;
@@ -838,28 +1161,10 @@
 
 	pubq_num = fifo->acq_pg_num - pg_tbl->hq_num - pg_tbl->lq_num -
 		   pg_tbl->nq_num - pg_tbl->exq_num - pg_tbl->gapq_num;
-	rtw_write16(rtwdev, REG_FIFOPAGE_INFO_1, pg_tbl->hq_num);
-	rtw_write16(rtwdev, REG_FIFOPAGE_INFO_2, pg_tbl->lq_num);
-	rtw_write16(rtwdev, REG_FIFOPAGE_INFO_3, pg_tbl->nq_num);
-	rtw_write16(rtwdev, REG_FIFOPAGE_INFO_4, pg_tbl->exq_num);
-	rtw_write16(rtwdev, REG_FIFOPAGE_INFO_5, pubq_num);
-	rtw_write32_set(rtwdev, REG_RQPN_CTRL_2, BIT_LD_RQPN);
-
-	rtw_write16(rtwdev, REG_FIFOPAGE_CTRL_2, fifo->rsvd_boundary);
-	rtw_write8_set(rtwdev, REG_FWHW_TXQ_CTRL + 2, BIT_EN_WR_FREE_TAIL >> 16);
-
-	rtw_write16(rtwdev, REG_BCNQ_BDNY_V1, fifo->rsvd_boundary);
-	rtw_write16(rtwdev, REG_FIFOPAGE_CTRL_2 + 2, fifo->rsvd_boundary);
-	rtw_write16(rtwdev, REG_BCNQ1_BDNY_V1, fifo->rsvd_boundary);
-	rtw_write32(rtwdev, REG_RXFF_BNDY, chip->rxff_size - C2H_PKT_BUF - 1);
-	rtw_write8_set(rtwdev, REG_AUTO_LLT_V1, BIT_AUTO_INIT_LLT_V1);
-
-	if (!check_hw_ready(rtwdev, REG_AUTO_LLT_V1, BIT_AUTO_INIT_LLT_V1, 0))
-		return -EBUSY;
-
-	rtw_write8(rtwdev, REG_CR + 3, 0);
-
-	return 0;
+	if (rtw_chip_wcpu_11n(rtwdev))
+		return __priority_queue_cfg_legacy(rtwdev, pg_tbl, pubq_num);
+	else
+		return __priority_queue_cfg(rtwdev, pg_tbl, pubq_num);
 }
 
 static int init_h2c(struct rtw_dev *rtwdev)
@@ -872,6 +1177,9 @@
 	u32 h2cq_free;
 	u32 wp, rp;
 
+	if (rtw_chip_wcpu_11n(rtwdev))
+		return 0;
+
 	h2cq_addr = fifo->rsvd_h2cq_addr << TX_PAGE_SIZE_SHIFT;
 	h2cq_size = RSVD_PG_H2CQ_NUM << TX_PAGE_SIZE_SHIFT;
 
@@ -936,11 +1244,13 @@
 	u8 value8;
 
 	rtw_write8(rtwdev, REG_RX_DRVINFO_SZ, PHY_STATUS_SIZE);
-	value8 = rtw_read8(rtwdev, REG_TRXFF_BNDY + 1);
-	value8 &= 0xF0;
-	/* For rxdesc len = 0 issue */
-	value8 |= 0xF;
-	rtw_write8(rtwdev, REG_TRXFF_BNDY + 1, value8);
+	if (rtw_chip_wcpu_11ac(rtwdev)) {
+		value8 = rtw_read8(rtwdev, REG_TRXFF_BNDY + 1);
+		value8 &= 0xF0;
+		/* For rxdesc len = 0 issue */
+		value8 |= 0xF;
+		rtw_write8(rtwdev, REG_TRXFF_BNDY + 1, value8);
+	}
 	rtw_write32_set(rtwdev, REG_RCR, BIT_APP_PHYSTS);
 	rtw_write32_clr(rtwdev, REG_WMAC_OPTION_FUNCTION + 4, BIT(8) | BIT(9));
 
@@ -964,5 +1274,7 @@
 	if (ret)
 		return ret;
 
+	rtw_hci_interface_cfg(rtwdev);
+
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/mac.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/mac.h
@@ -10,6 +10,7 @@
 #define SDIO_LOCAL_OFFSET	0x10250000
 #define DDMA_POLLING_COUNT	1000
 #define C2H_PKT_BUF		256
+#define REPORT_BUF		128
 #define PHY_STATUS_SIZE		4
 #define ILLEGAL_KEY_GROUP	0xFAAAAA00
 
@@ -31,5 +32,11 @@
 void rtw_mac_power_off(struct rtw_dev *rtwdev);
 int rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw);
 int rtw_mac_init(struct rtw_dev *rtwdev);
+void rtw_mac_flush_queues(struct rtw_dev *rtwdev, u32 queues, bool drop);
+
+static inline void rtw_mac_flush_all_queues(struct rtw_dev *rtwdev, bool drop)
+{
+	rtw_mac_flush_queues(rtwdev, BIT(rtwdev->hw->queues) - 1, drop);
+}
 
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/mac80211.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/mac80211.c
@@ -10,26 +10,39 @@
 #include "coex.h"
 #include "ps.h"
 #include "reg.h"
+#include "bf.h"
 #include "debug.h"
+#include "wow.h"
 
 static void rtw_ops_tx(struct ieee80211_hw *hw,
 		       struct ieee80211_tx_control *control,
 		       struct sk_buff *skb)
 {
 	struct rtw_dev *rtwdev = hw->priv;
-	struct rtw_tx_pkt_info pkt_info = {0};
 
-	if (!rtw_flag_check(rtwdev, RTW_FLAG_RUNNING))
-		goto out;
+	if (!test_bit(RTW_FLAG_RUNNING, rtwdev->flags)) {
+		ieee80211_free_txskb(hw, skb);
+		return;
+	}
 
-	rtw_tx_pkt_info_update(rtwdev, &pkt_info, control, skb);
-	if (rtw_hci_tx(rtwdev, &pkt_info, skb))
-		goto out;
+	rtw_tx(rtwdev, control, skb);
+}
 
-	return;
+static void rtw_ops_wake_tx_queue(struct ieee80211_hw *hw,
+				  struct ieee80211_txq *txq)
+{
+	struct rtw_dev *rtwdev = hw->priv;
+	struct rtw_txq *rtwtxq = (struct rtw_txq *)txq->drv_priv;
 
-out:
-	ieee80211_free_txskb(hw, skb);
+	if (!test_bit(RTW_FLAG_RUNNING, rtwdev->flags))
+		return;
+
+	spin_lock_bh(&rtwdev->txq_lock);
+	if (list_empty(&rtwtxq->list))
+		list_add_tail(&rtwtxq->list, &rtwdev->txqs);
+	spin_unlock_bh(&rtwdev->txq_lock);
+
+	tasklet_schedule(&rtwdev->tx_tasklet);
 }
 
 static int rtw_ops_start(struct ieee80211_hw *hw)
@@ -60,21 +73,33 @@
 
 	mutex_lock(&rtwdev->mutex);
 
-	if (changed & IEEE80211_CONF_CHANGE_IDLE) {
-		if (hw->conf.flags & IEEE80211_CONF_IDLE) {
-			rtw_enter_ips(rtwdev);
+	rtw_leave_lps_deep(rtwdev);
+
+	if ((changed & IEEE80211_CONF_CHANGE_IDLE) &&
+	    !(hw->conf.flags & IEEE80211_CONF_IDLE)) {
+		ret = rtw_leave_ips(rtwdev);
+		if (ret) {
+			rtw_err(rtwdev, "failed to leave idle state\n");
+			goto out;
+		}
+	}
+
+	if (changed & IEEE80211_CONF_CHANGE_PS) {
+		if (hw->conf.flags & IEEE80211_CONF_PS) {
+			rtwdev->ps_enabled = true;
 		} else {
-			ret = rtw_leave_ips(rtwdev);
-			if (ret) {
-				rtw_err(rtwdev, "failed to leave idle state\n");
-				goto out;
-			}
+			rtwdev->ps_enabled = false;
+			rtw_leave_lps(rtwdev);
 		}
 	}
 
 	if (changed & IEEE80211_CONF_CHANGE_CHANNEL)
 		rtw_set_channel(rtwdev);
 
+	if ((changed & IEEE80211_CONF_CHANGE_IDLE) &&
+	    (hw->conf.flags & IEEE80211_CONF_IDLE))
+		rtw_enter_ips(rtwdev);
+
 out:
 	mutex_unlock(&rtwdev->mutex);
 	return ret;
@@ -129,31 +154,40 @@
 	u8 bcn_ctrl = 0;
 
 	rtwvif->port = port;
-	rtwvif->vif = vif;
 	rtwvif->stats.tx_unicast = 0;
 	rtwvif->stats.rx_unicast = 0;
 	rtwvif->stats.tx_cnt = 0;
 	rtwvif->stats.rx_cnt = 0;
-	rtwvif->in_lps = false;
+	memset(&rtwvif->bfee, 0, sizeof(struct rtw_bfee));
 	rtwvif->conf = &rtw_vif_port[port];
+	rtw_txq_init(rtwdev, vif->txq);
+	INIT_LIST_HEAD(&rtwvif->rsvd_page_list);
 
 	mutex_lock(&rtwdev->mutex);
 
+	rtw_leave_lps_deep(rtwdev);
+
 	switch (vif->type) {
 	case NL80211_IFTYPE_AP:
 	case NL80211_IFTYPE_MESH_POINT:
+		rtw_add_rsvd_page_bcn(rtwdev, rtwvif);
 		net_type = RTW_NET_AP_MODE;
 		bcn_ctrl = BIT_EN_BCN_FUNCTION | BIT_DIS_TSF_UDT;
 		break;
 	case NL80211_IFTYPE_ADHOC:
+		rtw_add_rsvd_page_bcn(rtwdev, rtwvif);
 		net_type = RTW_NET_AD_HOC;
 		bcn_ctrl = BIT_EN_BCN_FUNCTION | BIT_DIS_TSF_UDT;
 		break;
 	case NL80211_IFTYPE_STATION:
-	default:
+		rtw_add_rsvd_page_sta(rtwdev, rtwvif);
 		net_type = RTW_NET_NO_LINK;
 		bcn_ctrl = BIT_EN_BCN_FUNCTION;
 		break;
+	default:
+		WARN_ON(1);
+		mutex_unlock(&rtwdev->mutex);
+		return -EINVAL;
 	}
 
 	ether_addr_copy(rtwvif->mac_addr, vif->addr);
@@ -181,6 +215,11 @@
 
 	mutex_lock(&rtwdev->mutex);
 
+	rtw_leave_lps_deep(rtwdev);
+
+	rtw_txq_cleanup(rtwdev, vif->txq);
+	rtw_remove_rsvd_page(rtwdev, rtwvif);
+
 	eth_zero_addr(rtwvif->mac_addr);
 	config |= PORT_SET_MAC_ADDR;
 	rtwvif->net_type = RTW_NET_NO_LINK;
@@ -204,11 +243,13 @@
 
 	mutex_lock(&rtwdev->mutex);
 
+	rtw_leave_lps_deep(rtwdev);
+
 	if (changed_flags & FIF_ALLMULTI) {
 		if (*new_flags & FIF_ALLMULTI)
-			rtwdev->hal.rcr |= BIT_AM | BIT_AB;
+			rtwdev->hal.rcr |= BIT_AM;
 		else
-			rtwdev->hal.rcr &= ~(BIT_AM | BIT_AB);
+			rtwdev->hal.rcr &= ~(BIT_AM);
 	}
 	if (changed_flags & FIF_FCSFAIL) {
 		if (*new_flags & FIF_FCSFAIL)
@@ -238,6 +279,54 @@
 	mutex_unlock(&rtwdev->mutex);
 }
 
+/* Only have one group of EDCA parameters now */
+static const u32 ac_to_edca_param[IEEE80211_NUM_ACS] = {
+	[IEEE80211_AC_VO] = REG_EDCA_VO_PARAM,
+	[IEEE80211_AC_VI] = REG_EDCA_VI_PARAM,
+	[IEEE80211_AC_BE] = REG_EDCA_BE_PARAM,
+	[IEEE80211_AC_BK] = REG_EDCA_BK_PARAM,
+};
+
+static u8 rtw_aifsn_to_aifs(struct rtw_dev *rtwdev,
+			    struct rtw_vif *rtwvif, u8 aifsn)
+{
+	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
+	u8 slot_time;
+	u8 sifs;
+
+	slot_time = vif->bss_conf.use_short_slot ? 9 : 20;
+	sifs = rtwdev->hal.current_band_type == RTW_BAND_5G ? 16 : 10;
+
+	return aifsn * slot_time + sifs;
+}
+
+static void __rtw_conf_tx(struct rtw_dev *rtwdev,
+			  struct rtw_vif *rtwvif, u16 ac)
+{
+	struct ieee80211_tx_queue_params *params = &rtwvif->tx_params[ac];
+	u32 edca_param = ac_to_edca_param[ac];
+	u8 ecw_max, ecw_min;
+	u8 aifs;
+
+	/* 2^ecw - 1 = cw; ecw = log2(cw + 1) */
+	ecw_max = ilog2(params->cw_max + 1);
+	ecw_min = ilog2(params->cw_min + 1);
+	aifs = rtw_aifsn_to_aifs(rtwdev, rtwvif, params->aifs);
+	rtw_write32_mask(rtwdev, edca_param, BIT_MASK_TXOP_LMT, params->txop);
+	rtw_write32_mask(rtwdev, edca_param, BIT_MASK_CWMAX, ecw_max);
+	rtw_write32_mask(rtwdev, edca_param, BIT_MASK_CWMIN, ecw_min);
+	rtw_write32_mask(rtwdev, edca_param, BIT_MASK_AIFS, aifs);
+}
+
+static void rtw_conf_tx(struct rtw_dev *rtwdev,
+			struct rtw_vif *rtwvif)
+{
+	u16 ac;
+
+	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
+		__rtw_conf_tx(rtwdev, rtwvif, ac);
+}
+
 static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,
 				     struct ieee80211_vif *vif,
 				     struct ieee80211_bss_conf *conf,
@@ -249,26 +338,26 @@
 
 	mutex_lock(&rtwdev->mutex);
 
+	rtw_leave_lps_deep(rtwdev);
+
 	if (changed & BSS_CHANGED_ASSOC) {
-		struct rtw_chip_info *chip = rtwdev->chip;
 		enum rtw_net_type net_type;
 
 		if (conf->assoc) {
 			rtw_coex_connect_notify(rtwdev, COEX_ASSOCIATE_FINISH);
 			net_type = RTW_NET_MGD_LINKED;
-			chip->ops->phy_calibration(rtwdev);
 
 			rtwvif->aid = conf->aid;
-			rtw_add_rsvd_page(rtwdev, RSVD_PS_POLL, true);
-			rtw_add_rsvd_page(rtwdev, RSVD_QOS_NULL, true);
-			rtw_add_rsvd_page(rtwdev, RSVD_NULL, true);
-			rtw_fw_download_rsvd_page(rtwdev, vif);
+			rtw_fw_download_rsvd_page(rtwdev);
 			rtw_send_rsvd_page_h2c(rtwdev);
 			rtw_coex_media_status_notify(rtwdev, conf->assoc);
+			if (rtw_bf_support)
+				rtw_bf_assoc(rtwdev, vif, conf);
 		} else {
+			rtw_leave_lps(rtwdev);
 			net_type = RTW_NET_NO_LINK;
 			rtwvif->aid = 0;
-			rtw_reset_rsvd_page(rtwdev);
+			rtw_bf_disassoc(rtwdev, vif, conf);
 		}
 
 		rtwvif->net_type = net_type;
@@ -282,13 +371,38 @@
 	}
 
 	if (changed & BSS_CHANGED_BEACON)
-		rtw_fw_download_rsvd_page(rtwdev, vif);
+		rtw_fw_download_rsvd_page(rtwdev);
+
+	if (changed & BSS_CHANGED_MU_GROUPS)
+		rtw_chip_set_gid_table(rtwdev, vif, conf);
+
+	if (changed & BSS_CHANGED_ERP_SLOT)
+		rtw_conf_tx(rtwdev, rtwvif);
 
 	rtw_vif_port_config(rtwdev, rtwvif, config);
 
 	mutex_unlock(&rtwdev->mutex);
 }
 
+static int rtw_ops_conf_tx(struct ieee80211_hw *hw,
+			   struct ieee80211_vif *vif, u16 ac,
+			   const struct ieee80211_tx_queue_params *params)
+{
+	struct rtw_dev *rtwdev = hw->priv;
+	struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
+
+	mutex_lock(&rtwdev->mutex);
+
+	rtw_leave_lps_deep(rtwdev);
+
+	rtwvif->tx_params[ac] = *params;
+	__rtw_conf_tx(rtwdev, rtwvif, ac);
+
+	mutex_unlock(&rtwdev->mutex);
+
+	return 0;
+}
+
 static u8 rtw_acquire_macid(struct rtw_dev *rtwdev)
 {
 	unsigned long mac_id;
@@ -311,6 +425,7 @@
 {
 	struct rtw_dev *rtwdev = hw->priv;
 	struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
+	int i;
 	int ret = 0;
 
 	mutex_lock(&rtwdev->mutex);
@@ -325,6 +440,8 @@
 	si->vif = vif;
 	si->init_ra_lv = 1;
 	ewma_rssi_init(&si->avg_rssi);
+	for (i = 0; i < ARRAY_SIZE(sta->txq); i++)
+		rtw_txq_init(rtwdev, sta->txq[i]);
 
 	rtw_update_sta_info(rtwdev, si);
 	rtw_fw_media_status_report(rtwdev, si->mac_id, true);
@@ -345,12 +462,18 @@
 {
 	struct rtw_dev *rtwdev = hw->priv;
 	struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
+	int i;
 
 	mutex_lock(&rtwdev->mutex);
 
 	rtw_release_macid(rtwdev, si->mac_id);
 	rtw_fw_media_status_report(rtwdev, si->mac_id, false);
 
+	for (i = 0; i < ARRAY_SIZE(sta->txq); i++)
+		rtw_txq_cleanup(rtwdev, sta->txq[i]);
+
+	kfree(si->mask);
+
 	rtwdev->sta_cnt--;
 
 	rtw_info(rtwdev, "sta %pM with macid %d left\n",
@@ -389,6 +512,9 @@
 	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
 	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
 	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+	case WLAN_CIPHER_SUITE_CCMP_256:
+	case WLAN_CIPHER_SUITE_GCMP:
+	case WLAN_CIPHER_SUITE_GCMP_256:
 		/* suppress error messages */
 		return -EOPNOTSUPP;
 	default:
@@ -397,6 +523,8 @@
 
 	mutex_lock(&rtwdev->mutex);
 
+	rtw_leave_lps_deep(rtwdev);
+
 	if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
 		hw_key_idx = rtw_sec_get_free_cam(sec);
 	} else {
@@ -418,10 +546,15 @@
 				  hw_key_type, hw_key_idx);
 		break;
 	case DISABLE_KEY:
+		rtw_mac_flush_all_queues(rtwdev, false);
 		rtw_sec_clear_cam(rtwdev, sec, key->hw_key_idx);
 		break;
 	}
 
+	/* download new cam settings for PG to backup */
+	if (rtw_fw_lps_deep_mode == LPS_DEEP_MODE_PG)
+		rtw_fw_download_rsvd_page(rtwdev);
+
 out:
 	mutex_unlock(&rtwdev->mutex);
 
@@ -434,17 +567,21 @@
 {
 	struct ieee80211_sta *sta = params->sta;
 	u16 tid = params->tid;
+	struct ieee80211_txq *txq = sta->txq[tid];
+	struct rtw_txq *rtwtxq = (struct rtw_txq *)txq->drv_priv;
 
 	switch (params->action) {
 	case IEEE80211_AMPDU_TX_START:
-		ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
-		break;
+		return IEEE80211_AMPDU_TX_START_IMMEDIATE;
 	case IEEE80211_AMPDU_TX_STOP_CONT:
 	case IEEE80211_AMPDU_TX_STOP_FLUSH:
 	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
+		clear_bit(RTW_TXQ_AMPDU, &rtwtxq->flags);
 		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
 		break;
 	case IEEE80211_AMPDU_TX_OPERATIONAL:
+		set_bit(RTW_TXQ_AMPDU, &rtwtxq->flags);
+		break;
 	case IEEE80211_AMPDU_RX_START:
 	case IEEE80211_AMPDU_RX_STOP:
 		break;
@@ -456,6 +593,20 @@
 	return 0;
 }
 
+static bool rtw_ops_can_aggregate_in_amsdu(struct ieee80211_hw *hw,
+					   struct sk_buff *head,
+					   struct sk_buff *skb)
+{
+	struct rtw_dev *rtwdev = hw->priv;
+	struct rtw_hal *hal = &rtwdev->hal;
+
+	/* we don't want to enable TX AMSDU on 2.4G */
+	if (hal->current_band_type == RTW_BAND_2G)
+		return false;
+
+	return true;
+}
+
 static void rtw_ops_sw_scan_start(struct ieee80211_hw *hw,
 				  struct ieee80211_vif *vif,
 				  const u8 *mac_addr)
@@ -464,18 +615,18 @@
 	struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
 	u32 config = 0;
 
-	rtw_leave_lps(rtwdev, rtwvif);
-
 	mutex_lock(&rtwdev->mutex);
 
+	rtw_leave_lps(rtwdev);
+
 	ether_addr_copy(rtwvif->mac_addr, mac_addr);
 	config |= PORT_SET_MAC_ADDR;
 	rtw_vif_port_config(rtwdev, rtwvif, config);
 
 	rtw_coex_scan_notify(rtwdev, COEX_SCAN_START);
 
-	rtw_flag_set(rtwdev, RTW_FLAG_DIG_DISABLE);
-	rtw_flag_set(rtwdev, RTW_FLAG_SCANNING);
+	set_bit(RTW_FLAG_DIG_DISABLE, rtwdev->flags);
+	set_bit(RTW_FLAG_SCANNING, rtwdev->flags);
 
 	mutex_unlock(&rtwdev->mutex);
 }
@@ -489,8 +640,8 @@
 
 	mutex_lock(&rtwdev->mutex);
 
-	rtw_flag_clear(rtwdev, RTW_FLAG_SCANNING);
-	rtw_flag_clear(rtwdev, RTW_FLAG_DIG_DISABLE);
+	clear_bit(RTW_FLAG_SCANNING, rtwdev->flags);
+	clear_bit(RTW_FLAG_DIG_DISABLE, rtwdev->flags);
 
 	ether_addr_copy(rtwvif->mac_addr, vif->addr);
 	config |= PORT_SET_MAC_ADDR;
@@ -508,12 +659,138 @@
 	struct rtw_dev *rtwdev = hw->priv;
 
 	mutex_lock(&rtwdev->mutex);
+	rtw_leave_lps_deep(rtwdev);
 	rtw_coex_connect_notify(rtwdev, COEX_ASSOCIATE_START);
+	rtw_chip_prepare_tx(rtwdev);
 	mutex_unlock(&rtwdev->mutex);
 }
 
+static int rtw_ops_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
+{
+	struct rtw_dev *rtwdev = hw->priv;
+
+	mutex_lock(&rtwdev->mutex);
+	rtwdev->rts_threshold = value;
+	mutex_unlock(&rtwdev->mutex);
+
+	return 0;
+}
+
+static void rtw_ops_sta_statistics(struct ieee80211_hw *hw,
+				   struct ieee80211_vif *vif,
+				   struct ieee80211_sta *sta,
+				   struct station_info *sinfo)
+{
+	struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
+
+	sinfo->txrate = si->ra_report.txrate;
+	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
+}
+
+static void rtw_ops_flush(struct ieee80211_hw *hw,
+			  struct ieee80211_vif *vif,
+			  u32 queues, bool drop)
+{
+	struct rtw_dev *rtwdev = hw->priv;
+
+	mutex_lock(&rtwdev->mutex);
+	rtw_leave_lps_deep(rtwdev);
+
+	rtw_mac_flush_queues(rtwdev, queues, drop);
+	mutex_unlock(&rtwdev->mutex);
+}
+
+struct rtw_iter_bitrate_mask_data {
+	struct rtw_dev *rtwdev;
+	struct ieee80211_vif *vif;
+	const struct cfg80211_bitrate_mask *mask;
+};
+
+static void rtw_ra_mask_info_update_iter(void *data, struct ieee80211_sta *sta)
+{
+	struct rtw_iter_bitrate_mask_data *br_data = data;
+	struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
+
+	if (si->vif != br_data->vif)
+		return;
+
+	/* free previous mask setting */
+	kfree(si->mask);
+	si->mask = kmemdup(br_data->mask, sizeof(struct cfg80211_bitrate_mask),
+			   GFP_ATOMIC);
+	if (!si->mask) {
+		si->use_cfg_mask = false;
+		return;
+	}
+
+	si->use_cfg_mask = true;
+	rtw_update_sta_info(br_data->rtwdev, si);
+}
+
+static void rtw_ra_mask_info_update(struct rtw_dev *rtwdev,
+				    struct ieee80211_vif *vif,
+				    const struct cfg80211_bitrate_mask *mask)
+{
+	struct rtw_iter_bitrate_mask_data br_data;
+
+	br_data.rtwdev = rtwdev;
+	br_data.vif = vif;
+	br_data.mask = mask;
+	rtw_iterate_stas_atomic(rtwdev, rtw_ra_mask_info_update_iter, &br_data);
+}
+
+static int rtw_ops_set_bitrate_mask(struct ieee80211_hw *hw,
+				    struct ieee80211_vif *vif,
+				    const struct cfg80211_bitrate_mask *mask)
+{
+	struct rtw_dev *rtwdev = hw->priv;
+
+	rtw_ra_mask_info_update(rtwdev, vif, mask);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int rtw_ops_suspend(struct ieee80211_hw *hw,
+			   struct cfg80211_wowlan *wowlan)
+{
+	struct rtw_dev *rtwdev = hw->priv;
+	int ret;
+
+	mutex_lock(&rtwdev->mutex);
+	ret = rtw_wow_suspend(rtwdev, wowlan);
+	if (ret)
+		rtw_err(rtwdev, "failed to suspend for wow %d\n", ret);
+	mutex_unlock(&rtwdev->mutex);
+
+	return ret ? 1 : 0;
+}
+
+static int rtw_ops_resume(struct ieee80211_hw *hw)
+{
+	struct rtw_dev *rtwdev = hw->priv;
+	int ret;
+
+	mutex_lock(&rtwdev->mutex);
+	ret = rtw_wow_resume(rtwdev);
+	if (ret)
+		rtw_err(rtwdev, "failed to resume for wow %d\n", ret);
+	mutex_unlock(&rtwdev->mutex);
+
+	return ret ? 1 : 0;
+}
+
+static void rtw_ops_set_wakeup(struct ieee80211_hw *hw, bool enabled)
+{
+	struct rtw_dev *rtwdev = hw->priv;
+
+	device_set_wakeup_enable(rtwdev->dev, enabled);
+}
+#endif
+
 const struct ieee80211_ops rtw_ops = {
 	.tx			= rtw_ops_tx,
+	.wake_tx_queue		= rtw_ops_wake_tx_queue,
 	.start			= rtw_ops_start,
 	.stop			= rtw_ops_stop,
 	.config			= rtw_ops_config,
@@ -521,12 +798,23 @@
 	.remove_interface	= rtw_ops_remove_interface,
 	.configure_filter	= rtw_ops_configure_filter,
 	.bss_info_changed	= rtw_ops_bss_info_changed,
+	.conf_tx		= rtw_ops_conf_tx,
 	.sta_add		= rtw_ops_sta_add,
 	.sta_remove		= rtw_ops_sta_remove,
 	.set_key		= rtw_ops_set_key,
 	.ampdu_action		= rtw_ops_ampdu_action,
+	.can_aggregate_in_amsdu	= rtw_ops_can_aggregate_in_amsdu,
 	.sw_scan_start		= rtw_ops_sw_scan_start,
 	.sw_scan_complete	= rtw_ops_sw_scan_complete,
 	.mgd_prepare_tx		= rtw_ops_mgd_prepare_tx,
+	.set_rts_threshold	= rtw_ops_set_rts_threshold,
+	.sta_statistics		= rtw_ops_sta_statistics,
+	.flush			= rtw_ops_flush,
+	.set_bitrate_mask	= rtw_ops_set_bitrate_mask,
+#ifdef CONFIG_PM
+	.suspend		= rtw_ops_suspend,
+	.resume			= rtw_ops_resume,
+	.set_wakeup		= rtw_ops_set_wakeup,
+#endif
 };
 EXPORT_SYMBOL(rtw_ops);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/main.c
@@ -12,16 +12,24 @@
 #include "phy.h"
 #include "reg.h"
 #include "efuse.h"
+#include "tx.h"
 #include "debug.h"
+#include "bf.h"
+#include "sar.h"
 
-static bool rtw_fw_support_lps;
+unsigned int rtw_fw_lps_deep_mode;
+EXPORT_SYMBOL(rtw_fw_lps_deep_mode);
+bool rtw_bf_support = true;
 unsigned int rtw_debug_mask;
 EXPORT_SYMBOL(rtw_debug_mask);
+bool rtw_edcca_enabled = true;
 
-module_param_named(support_lps, rtw_fw_support_lps, bool, 0644);
+module_param_named(lps_deep_mode, rtw_fw_lps_deep_mode, uint, 0644);
+module_param_named(support_bf, rtw_bf_support, bool, 0644);
 module_param_named(debug_mask, rtw_debug_mask, uint, 0644);
 
-MODULE_PARM_DESC(support_lps, "Set Y to enable Leisure Power Save support, to turn radio off between beacons");
+MODULE_PARM_DESC(lps_deep_mode, "Deeper PS mode. If 0, deep PS is disabled");
+MODULE_PARM_DESC(support_bf, "Set Y to enable beamformee support");
 MODULE_PARM_DESC(debug_mask, "Debugging mask");
 
 static struct ieee80211_channel rtw_channeltable_2g[] = {
@@ -84,6 +92,18 @@
 	{.bitrate = 540, .hw_value = 0x0b,},
 };
 
+u16 rtw_desc_to_bitrate(u8 desc_rate)
+{
+	struct ieee80211_rate rate;
+
+	if (WARN(desc_rate >= ARRAY_SIZE(rtw_ratetable), "invalid desc rate\n"))
+		return 0;
+
+	rate = rtw_ratetable[desc_rate];
+
+	return rate.bitrate;
+}
+
 static struct ieee80211_supported_band rtw_band_2ghz = {
 	.band = NL80211_BAND_2GHZ,
 
@@ -112,29 +132,39 @@
 };
 
 struct rtw_watch_dog_iter_data {
+	struct rtw_dev *rtwdev;
 	struct rtw_vif *rtwvif;
-	bool active;
-	u8 assoc_cnt;
 };
 
+static void rtw_dynamic_csi_rate(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif)
+{
+	struct rtw_bf_info *bf_info = &rtwdev->bf_info;
+	u8 fix_rate_enable = 0;
+	u8 new_csi_rate_idx;
+
+	if (rtwvif->bfee.role != RTW_BFEE_SU &&
+	    rtwvif->bfee.role != RTW_BFEE_MU)
+		return;
+
+	rtw_chip_cfg_csi_rate(rtwdev, rtwdev->dm_info.min_rssi,
+			      bf_info->cur_csi_rpt_rate,
+			      fix_rate_enable, &new_csi_rate_idx);
+
+	if (new_csi_rate_idx != bf_info->cur_csi_rpt_rate)
+		bf_info->cur_csi_rpt_rate = new_csi_rate_idx;
+}
+
 static void rtw_vif_watch_dog_iter(void *data, u8 *mac,
 				   struct ieee80211_vif *vif)
 {
 	struct rtw_watch_dog_iter_data *iter_data = data;
 	struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
 
-	if (vif->type == NL80211_IFTYPE_STATION) {
-		if (vif->bss_conf.assoc) {
-			iter_data->assoc_cnt++;
+	if (vif->type == NL80211_IFTYPE_STATION)
+		if (vif->bss_conf.assoc)
 			iter_data->rtwvif = rtwvif;
-		}
-		if (rtwvif->stats.tx_cnt > RTW_LPS_THRESHOLD ||
-		    rtwvif->stats.rx_cnt > RTW_LPS_THRESHOLD)
-			iter_data->active = true;
-	} else {
-		/* only STATION mode can enter lps */
-		iter_data->active = true;
-	}
+
+	rtw_dynamic_csi_rate(iter_data->rtwdev, rtwvif);
 
 	rtwvif->stats.tx_unicast = 0;
 	rtwvif->stats.rx_unicast = 0;
@@ -149,46 +179,74 @@
 {
 	struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
 					      watch_dog_work.work);
+	struct rtw_traffic_stats *stats = &rtwdev->stats;
 	struct rtw_watch_dog_iter_data data = {};
-	bool busy_traffic = rtw_flag_check(rtwdev, RTW_FLAG_BUSY_TRAFFIC);
+	bool busy_traffic = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
+	bool ps_active;
 
-	if (!rtw_flag_check(rtwdev, RTW_FLAG_RUNNING))
-		return;
+	mutex_lock(&rtwdev->mutex);
+
+	if (!test_bit(RTW_FLAG_RUNNING, rtwdev->flags))
+		goto unlock;
 
 	ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->watch_dog_work,
 				     RTW_WATCH_DOG_DELAY_TIME);
 
 	if (rtwdev->stats.tx_cnt > 100 || rtwdev->stats.rx_cnt > 100)
-		rtw_flag_set(rtwdev, RTW_FLAG_BUSY_TRAFFIC);
+		set_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
 	else
-		rtw_flag_clear(rtwdev, RTW_FLAG_BUSY_TRAFFIC);
+		clear_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
 
-	if (busy_traffic != rtw_flag_check(rtwdev, RTW_FLAG_BUSY_TRAFFIC))
+	if (busy_traffic != test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags))
 		rtw_coex_wl_status_change_notify(rtwdev);
 
+	if (stats->tx_cnt > RTW_LPS_THRESHOLD ||
+	    stats->rx_cnt > RTW_LPS_THRESHOLD)
+		ps_active = true;
+	else
+		ps_active = false;
+
+	ewma_tp_add(&stats->tx_ewma_tp,
+		    (u32)(stats->tx_unicast >> RTW_TP_SHIFT));
+	ewma_tp_add(&stats->rx_ewma_tp,
+		    (u32)(stats->rx_unicast >> RTW_TP_SHIFT));
+	stats->tx_throughput = ewma_tp_read(&stats->tx_ewma_tp);
+	stats->rx_throughput = ewma_tp_read(&stats->rx_ewma_tp);
+
 	/* reset tx/rx statictics */
-	rtwdev->stats.tx_unicast = 0;
-	rtwdev->stats.rx_unicast = 0;
-	rtwdev->stats.tx_cnt = 0;
-	rtwdev->stats.rx_cnt = 0;
+	stats->tx_unicast = 0;
+	stats->rx_unicast = 0;
+	stats->tx_cnt = 0;
+	stats->rx_cnt = 0;
+
+	if (test_bit(RTW_FLAG_SCANNING, rtwdev->flags))
+		goto unlock;
+
+	/* make sure BB/RF is working for dynamic mech */
+	rtw_leave_lps(rtwdev);
+
+	rtw_phy_dynamic_mechanism(rtwdev);
 
+	data.rtwdev = rtwdev;
 	/* use atomic version to avoid taking local->iflist_mtx mutex */
 	rtw_iterate_vifs_atomic(rtwdev, rtw_vif_watch_dog_iter, &data);
 
 	/* fw supports only one station associated to enter lps, if there are
 	 * more than two stations associated to the AP, then we can not enter
 	 * lps, because fw does not handle the overlapped beacon interval
+	 *
+	 * mac80211 should iterate vifs and determine if driver can enter
+	 * ps by passing IEEE80211_CONF_PS to us, all we need to do is to
+	 * get that vif and check if device is having traffic more than the
+	 * threshold.
 	 */
-	if (rtw_fw_support_lps &&
-	    data.rtwvif && !data.active && data.assoc_cnt == 1)
-		rtw_enter_lps(rtwdev, data.rtwvif);
-
-	if (rtw_flag_check(rtwdev, RTW_FLAG_SCANNING))
-		return;
-
-	rtw_phy_dynamic_mechanism(rtwdev);
+	if (rtwdev->ps_enabled && data.rtwvif && !ps_active)
+		rtw_enter_lps(rtwdev, data.rtwvif->port);
 
 	rtwdev->watch_dog_cnt++;
+
+unlock:
+	mutex_unlock(&rtwdev->mutex);
 }
 
 static void rtw_c2h_work(struct work_struct *work)
@@ -203,6 +261,40 @@
 	}
 }
 
+struct rtw_txq_ba_iter_data {
+};
+
+static void rtw_txq_ba_iter(void *data, struct ieee80211_sta *sta)
+{
+	struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
+	int ret;
+	u8 tid;
+
+	tid = find_first_bit(si->tid_ba, IEEE80211_NUM_TIDS);
+	while (tid != IEEE80211_NUM_TIDS) {
+		clear_bit(tid, si->tid_ba);
+		ret = ieee80211_start_tx_ba_session(sta, tid, 0);
+		if (ret == -EINVAL) {
+			struct ieee80211_txq *txq;
+			struct rtw_txq *rtwtxq;
+
+			txq = sta->txq[tid];
+			rtwtxq = (struct rtw_txq *)txq->drv_priv;
+			set_bit(RTW_TXQ_BLOCK_BA, &rtwtxq->flags);
+		}
+
+		tid = find_first_bit(si->tid_ba, IEEE80211_NUM_TIDS);
+	}
+}
+
+static void rtw_txq_ba_work(struct work_struct *work)
+{
+	struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, ba_work);
+	struct rtw_txq_ba_iter_data data;
+
+	rtw_iterate_stas_atomic(rtwdev, rtw_txq_ba_iter, &data);
+}
+
 void rtw_get_channel_params(struct cfg80211_chan_def *chandef,
 			    struct rtw_channel_params *chan_params)
 {
@@ -226,15 +318,15 @@
 	case NL80211_CHAN_WIDTH_20_NOHT:
 	case NL80211_CHAN_WIDTH_20:
 		bandwidth = RTW_CHANNEL_WIDTH_20;
-		primary_chan_idx = 0;
+		primary_chan_idx = RTW_SC_DONT_CARE;
 		break;
 	case NL80211_CHAN_WIDTH_40:
 		bandwidth = RTW_CHANNEL_WIDTH_40;
 		if (primary_freq > center_freq) {
-			primary_chan_idx = 1;
+			primary_chan_idx = RTW_SC_20_UPPER;
 			center_chan -= 2;
 		} else {
-			primary_chan_idx = 2;
+			primary_chan_idx = RTW_SC_20_LOWER;
 			center_chan += 2;
 		}
 		break;
@@ -242,10 +334,10 @@
 		bandwidth = RTW_CHANNEL_WIDTH_80;
 		if (primary_freq > center_freq) {
 			if (primary_freq - center_freq == 10) {
-				primary_chan_idx = 1;
+				primary_chan_idx = RTW_SC_20_UPPER;
 				center_chan -= 2;
 			} else {
-				primary_chan_idx = 3;
+				primary_chan_idx = RTW_SC_20_UPMOST;
 				center_chan -= 6;
 			}
 			/* assign the center channel used
@@ -254,10 +346,10 @@
 			cch_by_bw[RTW_CHANNEL_WIDTH_40] = center_chan + 4;
 		} else {
 			if (center_freq - primary_freq == 10) {
-				primary_chan_idx = 2;
+				primary_chan_idx = RTW_SC_20_LOWER;
 				center_chan += 2;
 			} else {
-				primary_chan_idx = 4;
+				primary_chan_idx = RTW_SC_20_LOWEST;
 				center_chan += 6;
 			}
 			/* assign the center channel used
@@ -311,13 +403,29 @@
 	if (hal->current_band_type == RTW_BAND_5G) {
 		rtw_coex_switchband_notify(rtwdev, COEX_SWITCH_TO_5G);
 	} else {
-		if (rtw_flag_check(rtwdev, RTW_FLAG_SCANNING))
+		if (test_bit(RTW_FLAG_SCANNING, rtwdev->flags))
 			rtw_coex_switchband_notify(rtwdev, COEX_SWITCH_TO_24G);
 		else
 			rtw_coex_switchband_notify(rtwdev, COEX_SWITCH_TO_24G_NOFORSCAN);
 	}
 
 	rtw_phy_set_tx_power_level(rtwdev, center_chan);
+
+	/* If set channel isn't for scanning, we'll do RF calibration once in
+	 * this channel while mgd_prepare_tx.
+	 */
+	if (!test_bit(RTW_FLAG_SCANNING, rtwdev->flags))
+		rtwdev->need_rfk = true;
+}
+
+void rtw_chip_prepare_tx(struct rtw_dev *rtwdev)
+{
+	struct rtw_chip_info *chip = rtwdev->chip;
+
+	if (rtwdev->need_rfk) {
+		rtwdev->need_rfk = false;
+		chip->ops->phy_calibration(rtwdev);
+	}
 }
 
 static void rtw_vif_write_addr(struct rtw_dev *rtwdev, u32 start, u8 *addr)
@@ -382,6 +490,7 @@
 static void rtw_hw_config_rf_ant_num(struct rtw_dev *rtwdev, u8 hw_ant_num)
 {
 	struct rtw_hal *hal = &rtwdev->hal;
+	struct rtw_chip_info *chip = rtwdev->chip;
 
 	if (hw_ant_num == EFUSE_HW_CAP_IGNORE ||
 	    hw_ant_num >= hal->rf_path_num)
@@ -391,6 +500,8 @@
 	case 1:
 		hal->rf_type = RF_1T1R;
 		hal->rf_path_num = 1;
+		if (!chip->fix_rf_phy_num)
+			hal->rf_phy_num = hal->rf_path_num;
 		hal->antenna_tx = BB_PATH_A;
 		hal->antenna_rx = BB_PATH_A;
 		break;
@@ -529,12 +640,71 @@
 #define RA_MASK_OFDM_IN_HT_2G	0x00010
 #define RA_MASK_OFDM_IN_HT_5G	0x00030
 
+static u64 rtw_update_rate_mask(struct rtw_dev *rtwdev,
+				struct rtw_sta_info *si,
+				u64 ra_mask, bool is_vht_enable,
+				u8 wireless_set)
+{
+	struct rtw_hal *hal = &rtwdev->hal;
+	const struct cfg80211_bitrate_mask *mask = si->mask;
+	u64 cfg_mask = GENMASK_ULL(63, 0);
+	u8 rssi_level, band;
+
+	if (wireless_set != WIRELESS_CCK) {
+		rssi_level = si->rssi_level;
+		if (rssi_level == 0)
+			ra_mask &= 0xffffffffffffffffULL;
+		else if (rssi_level == 1)
+			ra_mask &= 0xfffffffffffffff0ULL;
+		else if (rssi_level == 2)
+			ra_mask &= 0xffffffffffffefe0ULL;
+		else if (rssi_level == 3)
+			ra_mask &= 0xffffffffffffcfc0ULL;
+		else if (rssi_level == 4)
+			ra_mask &= 0xffffffffffff8f80ULL;
+		else if (rssi_level >= 5)
+			ra_mask &= 0xffffffffffff0f00ULL;
+	}
+
+	if (!si->use_cfg_mask)
+		return ra_mask;
+
+	band = hal->current_band_type;
+	if (band == RTW_BAND_2G) {
+		band = NL80211_BAND_2GHZ;
+		cfg_mask = mask->control[band].legacy;
+	} else if (band == RTW_BAND_5G) {
+		band = NL80211_BAND_5GHZ;
+		cfg_mask = u64_encode_bits(mask->control[band].legacy,
+					   RA_MASK_OFDM_RATES);
+	}
+
+	if (!is_vht_enable) {
+		if (ra_mask & RA_MASK_HT_RATES_1SS)
+			cfg_mask |= u64_encode_bits(mask->control[band].ht_mcs[0],
+						    RA_MASK_HT_RATES_1SS);
+		if (ra_mask & RA_MASK_HT_RATES_2SS)
+			cfg_mask |= u64_encode_bits(mask->control[band].ht_mcs[1],
+						    RA_MASK_HT_RATES_2SS);
+	} else {
+		if (ra_mask & RA_MASK_VHT_RATES_1SS)
+			cfg_mask |= u64_encode_bits(mask->control[band].vht_mcs[0],
+						    RA_MASK_VHT_RATES_1SS);
+		if (ra_mask & RA_MASK_VHT_RATES_2SS)
+			cfg_mask |= u64_encode_bits(mask->control[band].vht_mcs[1],
+						    RA_MASK_VHT_RATES_2SS);
+	}
+
+	ra_mask &= cfg_mask;
+
+	return ra_mask;
+}
+
 void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si)
 {
 	struct ieee80211_sta *sta = si->sta;
 	struct rtw_efuse *efuse = &rtwdev->efuse;
 	struct rtw_hal *hal = &rtwdev->hal;
-	u8 rssi_level;
 	u8 wireless_set;
 	u8 bw_mode;
 	u8 rate_id;
@@ -553,20 +723,18 @@
 			stbc_en = VHT_STBC_EN;
 		if (sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC)
 			ldpc_en = VHT_LDPC_EN;
-		if (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80)
-			is_support_sgi = true;
 	} else if (sta->ht_cap.ht_supported) {
-		ra_mask |= (sta->ht_cap.mcs.rx_mask[NL80211_BAND_5GHZ] << 20) |
-			   (sta->ht_cap.mcs.rx_mask[NL80211_BAND_2GHZ] << 12);
+		ra_mask |= (sta->ht_cap.mcs.rx_mask[1] << 20) |
+			   (sta->ht_cap.mcs.rx_mask[0] << 12);
 		if (sta->ht_cap.cap & IEEE80211_HT_CAP_RX_STBC)
 			stbc_en = HT_STBC_EN;
 		if (sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING)
 			ldpc_en = HT_LDPC_EN;
-		if (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20 ||
-		    sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40)
-			is_support_sgi = true;
 	}
 
+	if (efuse->hw_cap.nss == 1)
+		ra_mask &= RA_MASK_VHT_RATES_1SS | RA_MASK_HT_RATES_1SS;
+
 	if (hal->current_band_type == RTW_BAND_5G) {
 		ra_mask |= (u64)sta->supp_rates[NL80211_BAND_5GHZ] << 4;
 		if (sta->vht_cap.vht_supported) {
@@ -600,20 +768,21 @@
 		wireless_set = 0;
 	}
 
-	if (efuse->hw_cap.nss == 1) {
-		ra_mask &= RA_MASK_VHT_RATES_1SS;
-		ra_mask &= RA_MASK_HT_RATES_1SS;
-	}
-
 	switch (sta->bandwidth) {
 	case IEEE80211_STA_RX_BW_80:
 		bw_mode = RTW_CHANNEL_WIDTH_80;
+		is_support_sgi = sta->vht_cap.vht_supported &&
+				 (sta->vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80);
 		break;
 	case IEEE80211_STA_RX_BW_40:
 		bw_mode = RTW_CHANNEL_WIDTH_40;
+		is_support_sgi = sta->ht_cap.ht_supported &&
+				 (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40);
 		break;
 	default:
 		bw_mode = RTW_CHANNEL_WIDTH_20;
+		is_support_sgi = sta->ht_cap.ht_supported &&
+				 (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20);
 		break;
 	}
 
@@ -627,21 +796,8 @@
 
 	rate_id = get_rate_id(wireless_set, bw_mode, tx_num);
 
-	if (wireless_set != WIRELESS_CCK) {
-		rssi_level = si->rssi_level;
-		if (rssi_level == 0)
-			ra_mask &= 0xffffffffffffffffULL;
-		else if (rssi_level == 1)
-			ra_mask &= 0xfffffffffffffff0ULL;
-		else if (rssi_level == 2)
-			ra_mask &= 0xffffffffffffefe0ULL;
-		else if (rssi_level == 3)
-			ra_mask &= 0xffffffffffffcfc0ULL;
-		else if (rssi_level == 4)
-			ra_mask &= 0xffffffffffff8f80ULL;
-		else if (rssi_level >= 5)
-			ra_mask &= 0xffffffffffff0f00ULL;
-	}
+	ra_mask = rtw_update_rate_mask(rtwdev, si, ra_mask, is_vht_enable,
+				       wireless_set);
 
 	si->bw_mode = bw_mode;
 	si->stbc_en = stbc_en;
@@ -656,6 +812,26 @@
 	rtw_fw_send_ra_info(rtwdev, si);
 }
 
+static int rtw_wait_firmware_completion(struct rtw_dev *rtwdev)
+{
+	struct rtw_chip_info *chip = rtwdev->chip;
+	struct rtw_fw_state *fw;
+
+	fw = &rtwdev->fw;
+	wait_for_completion(&fw->completion);
+	if (!fw->firmware)
+		return -EINVAL;
+
+	if (chip->wow_fw_name) {
+		fw = &rtwdev->wow_fw;
+		wait_for_completion(&fw->completion);
+		if (!fw->firmware)
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
 static int rtw_power_on(struct rtw_dev *rtwdev)
 {
 	struct rtw_chip_info *chip = rtwdev->chip;
@@ -676,11 +852,10 @@
 		goto err;
 	}
 
-	wait_for_completion(&fw->completion);
-	if (!fw->firmware) {
-		ret = -EINVAL;
-		rtw_err(rtwdev, "failed to load firmware\n");
-		goto err;
+	ret = rtw_wait_firmware_completion(rtwdev);
+	if (ret) {
+		rtw_err(rtwdev, "failed to wait firmware completion\n");
+		goto err_off;
 	}
 
 	ret = rtw_download_firmware(rtwdev, fw);
@@ -736,15 +911,17 @@
 
 	ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->watch_dog_work,
 				     RTW_WATCH_DOG_DELAY_TIME);
+	ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->sar.work,
+				     RTW_SAR_DELAY_TIME);
 
-	rtw_flag_set(rtwdev, RTW_FLAG_RUNNING);
+	set_bit(RTW_FLAG_RUNNING, rtwdev->flags);
 
 	return 0;
 }
 
 static void rtw_power_off(struct rtw_dev *rtwdev)
 {
-	rtwdev->hci.ops->stop(rtwdev);
+	rtw_hci_stop(rtwdev);
 	rtw_mac_power_off(rtwdev);
 }
 
@@ -752,14 +929,20 @@
 {
 	struct rtw_coex *coex = &rtwdev->coex;
 
-	rtw_flag_clear(rtwdev, RTW_FLAG_RUNNING);
-	rtw_flag_clear(rtwdev, RTW_FLAG_FW_RUNNING);
+	clear_bit(RTW_FLAG_RUNNING, rtwdev->flags);
+	clear_bit(RTW_FLAG_FW_RUNNING, rtwdev->flags);
+
+	mutex_unlock(&rtwdev->mutex);
 
+	cancel_work_sync(&rtwdev->c2h_work);
 	cancel_delayed_work_sync(&rtwdev->watch_dog_work);
+	cancel_delayed_work_sync(&rtwdev->sar.work);
 	cancel_delayed_work_sync(&coex->bt_relink_work);
 	cancel_delayed_work_sync(&coex->bt_reenable_work);
 	cancel_delayed_work_sync(&coex->defreeze_work);
 
+	mutex_lock(&rtwdev->mutex);
+
 	rtw_power_off(rtwdev);
 }
 
@@ -772,7 +955,7 @@
 	ht_cap->cap = 0;
 	ht_cap->cap |= IEEE80211_HT_CAP_SGI_20 |
 			IEEE80211_HT_CAP_MAX_AMSDU |
-			IEEE80211_HT_CAP_LDPC_CODING |
+			(rtw_chip_wcpu_11ac(rtwdev) ? IEEE80211_HT_CAP_LDPC_CODING : 0) |
 			(1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
 	if (efuse->hw_cap.bw & BIT(RTW_CHANNEL_WIDTH_40))
 		ht_cap->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
@@ -814,6 +997,12 @@
 		       IEEE80211_VHT_CAP_HTC_VHT |
 		       IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK |
 		       0;
+
+	vht_cap->cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE |
+			IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
+	vht_cap->cap |= (rtwdev->hal.bfee_sts_cap <<
+			IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT);
+
 	mcs_map = IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 |
 		  IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 |
 		  IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 |
@@ -875,29 +1064,87 @@
 	kfree(hw->wiphy->bands[NL80211_BAND_5GHZ]);
 }
 
+static void __update_firmware_info(struct rtw_dev *rtwdev,
+				   struct rtw_fw_state *fw)
+{
+	const struct rtw_fw_hdr *fw_hdr =
+				(const struct rtw_fw_hdr *)fw->firmware->data;
+
+	fw->h2c_version = le16_to_cpu(fw_hdr->h2c_fmt_ver);
+	fw->version = le16_to_cpu(fw_hdr->version);
+	fw->sub_version = fw_hdr->subversion;
+	fw->sub_index = fw_hdr->subindex;
+}
+
+static void __update_firmware_info_legacy(struct rtw_dev *rtwdev,
+					  struct rtw_fw_state *fw)
+{
+	struct rtw_fw_hdr_legacy *legacy =
+				(struct rtw_fw_hdr_legacy *)fw->firmware->data;
+
+	fw->h2c_version = 0;
+	fw->version = le16_to_cpu(legacy->version);
+	fw->sub_version = legacy->subversion1;
+	fw->sub_index = legacy->subversion2;
+}
+
+static void update_firmware_info(struct rtw_dev *rtwdev,
+				 struct rtw_fw_state *fw)
+{
+	if (rtw_chip_wcpu_11n(rtwdev))
+		__update_firmware_info_legacy(rtwdev, fw);
+	else
+		__update_firmware_info(rtwdev, fw);
+}
+
 static void rtw_load_firmware_cb(const struct firmware *firmware, void *context)
 {
-	struct rtw_dev *rtwdev = context;
-	struct rtw_fw_state *fw = &rtwdev->fw;
+	struct rtw_fw_state *fw = context;
+	struct rtw_dev *rtwdev = fw->rtwdev;
 
-	if (!firmware)
+	if (!firmware || !firmware->data) {
 		rtw_err(rtwdev, "failed to request firmware\n");
+		complete_all(&fw->completion);
+		return;
+	}
 
 	fw->firmware = firmware;
+	update_firmware_info(rtwdev, fw);
 	complete_all(&fw->completion);
+
+	rtw_info(rtwdev, "Firmware version %u.%u.%u, H2C version %u\n",
+		 fw->version, fw->sub_version, fw->sub_index, fw->h2c_version);
 }
 
-static int rtw_load_firmware(struct rtw_dev *rtwdev, const char *fw_name)
+static int rtw_load_firmware(struct rtw_dev *rtwdev, enum rtw_fw_type type)
 {
-	struct rtw_fw_state *fw = &rtwdev->fw;
+	const char *fw_name;
+	struct rtw_fw_state *fw;
 	int ret;
 
+	switch (type) {
+	case RTW_WOWLAN_FW:
+		fw = &rtwdev->wow_fw;
+		fw_name = rtwdev->chip->wow_fw_name;
+		break;
+
+	case RTW_NORMAL_FW:
+		fw = &rtwdev->fw;
+		fw_name = rtwdev->chip->fw_name;
+		break;
+
+	default:
+		rtw_warn(rtwdev, "unsupported firmware type\n");
+		return -ENOENT;
+	}
+
+	fw->rtwdev = rtwdev;
 	init_completion(&fw->completion);
 
 	ret = request_firmware_nowait(THIS_MODULE, true, fw_name, rtwdev->dev,
-				      GFP_KERNEL, rtwdev, rtw_load_firmware_cb);
+				      GFP_KERNEL, fw, rtw_load_firmware_cb);
 	if (ret) {
-		rtw_err(rtwdev, "async firmware request failed\n");
+		rtw_err(rtwdev, "failed to async firmware request\n");
 		return ret;
 	}
 
@@ -914,6 +1161,7 @@
 	switch (rtw_hci_type(rtwdev)) {
 	case RTW_HCI_TYPE_PCIE:
 		rtwdev->hci.rpwm_addr = 0x03d9;
+		rtwdev->hci.cpwm_addr = 0x03da;
 		break;
 	default:
 		rtw_err(rtwdev, "unsupported hci type\n");
@@ -935,6 +1183,8 @@
 		hal->antenna_tx = BB_PATH_A;
 		hal->antenna_rx = BB_PATH_A;
 	}
+	hal->rf_phy_num = chip->fix_rf_phy_num ? chip->fix_rf_phy_num :
+			  hal->rf_path_num;
 
 	if (hal->fab_version == 2)
 		hal->fab_version = 1;
@@ -948,6 +1198,8 @@
 	/* default use ack */
 	rtwdev->hal.rcr |= BIT_VHT_DACK;
 
+	hal->bfee_sts_cap = 3;
+
 	return ret;
 }
 
@@ -1020,7 +1272,8 @@
 
 	rtw_hw_config_rf_ant_num(rtwdev, efuse->hw_cap.ant_num);
 
-	if (efuse->hw_cap.nss == EFUSE_HW_CAP_IGNORE)
+	if (efuse->hw_cap.nss == EFUSE_HW_CAP_IGNORE ||
+	    efuse->hw_cap.nss > rtwdev->hal.rf_path_num)
 		efuse->hw_cap.nss = rtwdev->hal.rf_path_num;
 
 	rtw_dbg(rtwdev, RTW_DBG_EFUSE,
@@ -1047,19 +1300,19 @@
 	/* power on mac to read efuse */
 	ret = rtw_chip_efuse_enable(rtwdev);
 	if (ret)
-		goto out;
+		goto out_unlock;
 
 	ret = rtw_parse_efuse_map(rtwdev);
 	if (ret)
-		goto out;
+		goto out_disable;
 
 	ret = rtw_dump_hw_feature(rtwdev);
 	if (ret)
-		goto out;
+		goto out_disable;
 
 	ret = rtw_check_supported_rfe(rtwdev);
 	if (ret)
-		goto out;
+		goto out_disable;
 
 	if (efuse->crystal_cap == 0xff)
 		efuse->crystal_cap = 0;
@@ -1086,9 +1339,10 @@
 	efuse->ext_pa_5g = efuse->pa_type_5g & BIT(0) ? 1 : 0;
 	efuse->ext_lna_2g = efuse->lna_type_5g & BIT(3) ? 1 : 0;
 
+out_disable:
 	rtw_chip_efuse_disable(rtwdev);
 
-out:
+out_unlock:
 	mutex_unlock(&rtwdev->mutex);
 	return ret;
 }
@@ -1108,6 +1362,7 @@
 	rtw_load_table(rtwdev, rfe_def->txpwr_lmt_tbl);
 	rtw_phy_tx_power_by_rate_config(hal);
 	rtw_phy_tx_power_limit_config(hal);
+	rtw_sar_load_table(rtwdev);
 
 	return 0;
 }
@@ -1141,29 +1396,49 @@
 }
 EXPORT_SYMBOL(rtw_chip_info_setup);
 
+static void rtw_stats_init(struct rtw_dev *rtwdev)
+{
+	struct rtw_traffic_stats *stats = &rtwdev->stats;
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+	int i;
+
+	ewma_tp_init(&stats->tx_ewma_tp);
+	ewma_tp_init(&stats->rx_ewma_tp);
+
+	for (i = 0; i < RTW_EVM_NUM; i++)
+		ewma_evm_init(&dm_info->ewma_evm[i]);
+	for (i = 0; i < RTW_SNR_NUM; i++)
+		ewma_snr_init(&dm_info->ewma_snr[i]);
+}
+
 int rtw_core_init(struct rtw_dev *rtwdev)
 {
+	struct rtw_chip_info *chip = rtwdev->chip;
 	struct rtw_coex *coex = &rtwdev->coex;
 	int ret;
 
 	INIT_LIST_HEAD(&rtwdev->rsvd_page_list);
+	INIT_LIST_HEAD(&rtwdev->txqs);
 
 	timer_setup(&rtwdev->tx_report.purge_timer,
 		    rtw_tx_report_purge_timer, 0);
+	tasklet_init(&rtwdev->tx_tasklet, rtw_tx_tasklet,
+		     (unsigned long)rtwdev);
 
 	INIT_DELAYED_WORK(&rtwdev->watch_dog_work, rtw_watch_dog_work);
-	INIT_DELAYED_WORK(&rtwdev->lps_work, rtw_lps_work);
+	INIT_DELAYED_WORK(&rtwdev->sar.work, rtw_sar_work);
 	INIT_DELAYED_WORK(&coex->bt_relink_work, rtw_coex_bt_relink_work);
 	INIT_DELAYED_WORK(&coex->bt_reenable_work, rtw_coex_bt_reenable_work);
 	INIT_DELAYED_WORK(&coex->defreeze_work, rtw_coex_defreeze_work);
 	INIT_WORK(&rtwdev->c2h_work, rtw_c2h_work);
+	INIT_WORK(&rtwdev->ba_work, rtw_txq_ba_work);
 	skb_queue_head_init(&rtwdev->c2h_queue);
 	skb_queue_head_init(&rtwdev->coex.queue);
 	skb_queue_head_init(&rtwdev->tx_report.queue);
 
-	spin_lock_init(&rtwdev->dm_lock);
 	spin_lock_init(&rtwdev->rf_lock);
 	spin_lock_init(&rtwdev->h2c.lock);
+	spin_lock_init(&rtwdev->txq_lock);
 	spin_lock_init(&rtwdev->tx_report.q_lock);
 
 	mutex_init(&rtwdev->mutex);
@@ -1175,22 +1450,31 @@
 	rtwdev->sec.total_cam_num = 32;
 	rtwdev->hal.current_channel = 1;
 	set_bit(RTW_BC_MC_MACID, rtwdev->mac_id_map);
+	if (!(BIT(rtw_fw_lps_deep_mode) & chip->lps_deep_mode_supported))
+		rtwdev->lps_conf.deep_mode = LPS_DEEP_MODE_NONE;
+	else
+		rtwdev->lps_conf.deep_mode = rtw_fw_lps_deep_mode;
 
-	mutex_lock(&rtwdev->mutex);
-	rtw_add_rsvd_page(rtwdev, RSVD_BEACON, false);
-	mutex_unlock(&rtwdev->mutex);
+	rtw_stats_init(rtwdev);
 
 	/* default rx filter setting */
 	rtwdev->hal.rcr = BIT_APP_FCS | BIT_APP_MIC | BIT_APP_ICV |
 			  BIT_HTC_LOC_CTRL | BIT_APP_PHYSTS |
 			  BIT_AB | BIT_AM | BIT_APM;
 
-	ret = rtw_load_firmware(rtwdev, rtwdev->chip->fw_name);
+	ret = rtw_load_firmware(rtwdev, RTW_NORMAL_FW);
 	if (ret) {
 		rtw_warn(rtwdev, "no firmware loaded\n");
 		return ret;
 	}
 
+	if (chip->wow_fw_name) {
+		ret = rtw_load_firmware(rtwdev, RTW_WOWLAN_FW);
+		if (ret) {
+			rtw_warn(rtwdev, "no wow firmware loaded\n");
+			return ret;
+		}
+	}
 	return 0;
 }
 EXPORT_SYMBOL(rtw_core_init);
@@ -1198,21 +1482,29 @@
 void rtw_core_deinit(struct rtw_dev *rtwdev)
 {
 	struct rtw_fw_state *fw = &rtwdev->fw;
+	struct rtw_fw_state *wow_fw = &rtwdev->wow_fw;
 	struct rtw_rsvd_page *rsvd_pkt, *tmp;
 	unsigned long flags;
 
 	if (fw->firmware)
 		release_firmware(fw->firmware);
 
+	if (wow_fw->firmware)
+		release_firmware(wow_fw->firmware);
+
+	tasklet_kill(&rtwdev->tx_tasklet);
 	spin_lock_irqsave(&rtwdev->tx_report.q_lock, flags);
 	skb_queue_purge(&rtwdev->tx_report.queue);
 	spin_unlock_irqrestore(&rtwdev->tx_report.q_lock, flags);
 
-	list_for_each_entry_safe(rsvd_pkt, tmp, &rtwdev->rsvd_page_list, list) {
-		list_del(&rsvd_pkt->list);
+	list_for_each_entry_safe(rsvd_pkt, tmp, &rtwdev->rsvd_page_list,
+				 build_list) {
+		list_del(&rsvd_pkt->build_list);
 		kfree(rsvd_pkt);
 	}
 
+	rtw_sar_release_table(rtwdev);
+
 	mutex_destroy(&rtwdev->mutex);
 	mutex_destroy(&rtwdev->coex.mutex);
 	mutex_destroy(&rtwdev->hal.tx_power_mutex);
@@ -1229,6 +1521,7 @@
 
 	hw->extra_tx_headroom = max_tx_headroom;
 	hw->queues = IEEE80211_NUM_ACS;
+	hw->txq_data_size = sizeof(struct rtw_txq);
 	hw->sta_data_size = sizeof(struct rtw_sta_info);
 	hw->vif_data_size = sizeof(struct rtw_vif);
 
@@ -1241,6 +1534,8 @@
 	ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
 	ieee80211_hw_set(hw, SUPPORT_FAST_XMIT);
 	ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU);
+	ieee80211_hw_set(hw, HAS_RATE_CONTROL);
+	ieee80211_hw_set(hw, TX_AMSDU);
 
 	hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
 				     BIT(NL80211_IFTYPE_AP) |
@@ -1252,6 +1547,12 @@
 
 	hw->wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
 
+	wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);
+
+#ifdef CONFIG_PM
+	hw->wiphy->wowlan = rtwdev->chip->wowlan_stub;
+	hw->wiphy->max_sched_scan_ssids = rtwdev->chip->max_sched_scan_ssids;
+#endif
 	rtw_set_supported_band(hw, rtwdev->chip);
 	SET_IEEE80211_PERM_ADDR(hw, rtwdev->efuse.addr);
 
@@ -1263,11 +1564,16 @@
 		return ret;
 	}
 
-	if (regulatory_hint(hw->wiphy, rtwdev->regd.alpha2))
-		rtw_err(rtwdev, "regulatory_hint fail\n");
+	if (!rtwdev->efuse.country_worldwide) {
+		if (regulatory_hint(hw->wiphy, rtwdev->efuse.country_code))
+			rtw_err(rtwdev, "regulatory_hint fail\n");
+	}
 
 	rtw_debugfs_init(rtwdev);
 
+	rtwdev->bf_info.bfer_mu_cnt = 0;
+	rtwdev->bf_info.bfer_su_cnt = 0;
+
 	return 0;
 }
 EXPORT_SYMBOL(rtw_register_hw);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/main.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/main.h
@@ -11,11 +11,17 @@
 #include <linux/average.h>
 #include <linux/bitops.h>
 #include <linux/bitfield.h>
+#include <linux/interrupt.h>
 
 #include "util.h"
 
 #define RTW_MAX_MAC_ID_NUM		32
 #define RTW_MAX_SEC_CAM_NUM		32
+#define MAX_PG_CAM_BACKUP_NUM		8
+
+#define RTW_MAX_PATTERN_NUM		12
+#define RTW_MAX_PATTERN_MASK_SIZE	16
+#define RTW_MAX_PATTERN_SIZE		128
 
 #define RTW_WATCH_DOG_DELAY_TIME	round_jiffies_relative(HZ * 2)
 
@@ -27,15 +33,25 @@
 #define RTW_RF_PATH_MAX			4
 #define HW_FEATURE_LEN			13
 
+#define RTW_TP_SHIFT			18 /* bytes/2s --> Mbps */
+
+extern bool rtw_bf_support;
+extern unsigned int rtw_fw_lps_deep_mode;
 extern unsigned int rtw_debug_mask;
+extern bool rtw_edcca_enabled;
 extern const struct ieee80211_ops rtw_ops;
 extern struct rtw_chip_info rtw8822b_hw_spec;
 extern struct rtw_chip_info rtw8822c_hw_spec;
+extern struct rtw_chip_info rtw8723d_hw_spec;
 
 #define RTW_MAX_CHANNEL_NUM_2G 14
 #define RTW_MAX_CHANNEL_NUM_5G 49
 
 struct rtw_dev;
+struct rtw_sar_rwrd;
+union rtw_sar_rwsi;
+union rtw_sar_rwgs;
+struct rtw_sar_read;
 
 enum rtw_hci_type {
 	RTW_HCI_TYPE_PCIE,
@@ -50,10 +66,24 @@
 	enum rtw_hci_type type;
 
 	u32 rpwm_addr;
+	u32 cpwm_addr;
 
 	u8 bulkout_num;
 };
 
+#define IS_CH_5G_BAND_1(channel) ((channel) >= 36 && (channel <= 48))
+#define IS_CH_5G_BAND_2(channel) ((channel) >= 52 && (channel <= 64))
+#define IS_CH_5G_BAND_3(channel) ((channel) >= 100 && (channel <= 144))
+#define IS_CH_5G_BAND_4(channel) ((channel) >= 149 && (channel <= 177))
+
+#define IS_CH_5G_BAND_MID(channel) \
+	(IS_CH_5G_BAND_2(channel) || IS_CH_5G_BAND_3(channel))
+
+#define IS_CH_2G_BAND(channel) ((channel) <= 14)
+#define IS_CH_5G_BAND(channel) \
+	(IS_CH_5G_BAND_1(channel) || IS_CH_5G_BAND_2(channel) || \
+	 IS_CH_5G_BAND_3(channel) || IS_CH_5G_BAND_4(channel))
+
 enum rtw_supported_band {
 	RTW_BAND_2G = 1 << 0,
 	RTW_BAND_5G = 1 << 1,
@@ -75,6 +105,16 @@
 	RTW_CHANNEL_WIDTH_10	= 6,
 };
 
+enum rtw_sc_offset {
+	RTW_SC_DONT_CARE	= 0,
+	RTW_SC_20_UPPER		= 1,
+	RTW_SC_20_LOWER		= 2,
+	RTW_SC_20_UPMOST	= 3,
+	RTW_SC_20_LOWEST	= 4,
+	RTW_SC_40_UPPER		= 9,
+	RTW_SC_40_LOWER		= 10,
+};
+
 enum rtw_net_type {
 	RTW_NET_NO_LINK		= 0,
 	RTW_NET_AD_HOC		= 1,
@@ -149,6 +189,7 @@
 enum rtw_chip_type {
 	RTW_CHIP_TYPE_8822B,
 	RTW_CHIP_TYPE_8822C,
+	RTW_CHIP_TYPE_8723D,
 };
 
 enum rtw_tx_queue_type {
@@ -173,6 +214,11 @@
 	RTK_MAX_RX_QUEUE_NUM
 };
 
+enum rtw_fw_type {
+	RTW_NORMAL_FW = 0x0,
+	RTW_WOWLAN_FW = 0x1,
+};
+
 enum rtw_rate_index {
 	RTW_RATEID_BGN_40M_2SS	= 0,
 	RTW_RATEID_BGN_40M_1SS	= 1,
@@ -303,18 +349,67 @@
 	RTW_REGD_MAX
 };
 
+enum rtw_txq_flags {
+	RTW_TXQ_AMPDU,
+	RTW_TXQ_BLOCK_BA,
+};
+
 enum rtw_flags {
 	RTW_FLAG_RUNNING,
 	RTW_FLAG_FW_RUNNING,
 	RTW_FLAG_SCANNING,
 	RTW_FLAG_INACTIVE_PS,
 	RTW_FLAG_LEISURE_PS,
+	RTW_FLAG_LEISURE_PS_DEEP,
 	RTW_FLAG_DIG_DISABLE,
 	RTW_FLAG_BUSY_TRAFFIC,
+	RTW_FLAG_WOWLAN,
 
 	NUM_OF_RTW_FLAGS,
 };
 
+enum rtw_evm {
+	RTW_EVM_OFDM = 0,
+	RTW_EVM_1SS,
+	RTW_EVM_2SS_A,
+	RTW_EVM_2SS_B,
+	/* keep it last */
+	RTW_EVM_NUM
+};
+
+enum rtw_snr {
+	RTW_SNR_OFDM_A = 0,
+	RTW_SNR_OFDM_B,
+	RTW_SNR_OFDM_C,
+	RTW_SNR_OFDM_D,
+	RTW_SNR_1SS_A,
+	RTW_SNR_1SS_B,
+	RTW_SNR_1SS_C,
+	RTW_SNR_1SS_D,
+	RTW_SNR_2SS_A,
+	RTW_SNR_2SS_B,
+	RTW_SNR_2SS_C,
+	RTW_SNR_2SS_D,
+	/* keep it last */
+	RTW_SNR_NUM
+};
+
+enum rtw_wow_flags {
+	RTW_WOW_FLAG_EN_MAGIC_PKT,
+	RTW_WOW_FLAG_EN_REKEY_PKT,
+	RTW_WOW_FLAG_EN_DISCONNECT,
+
+	/* keep it last */
+	RTW_WOW_FLAG_MAX,
+};
+
+enum rtw_sar_sources {
+	RTW_SAR_SOURCE_NONE,
+	RTW_SAR_SOURCE_VNDCMD,
+	RTW_SAR_SOURCE_ACPI_STATIC,
+	RTW_SAR_SOURCE_ACPI_DYNAMIC,
+};
+
 /* the power index is represented by differences, which cck-1s & ht40-1s are
  * the base values, so for 1s's differences, there are only ht20 & ofdm
  */
@@ -434,6 +529,36 @@
 	u32 mask;
 };
 
+struct rtw_reg_domain {
+	u32 addr;
+	u32 mask;
+#define RTW_REG_DOMAIN_MAC32	0
+#define RTW_REG_DOMAIN_MAC16	1
+#define RTW_REG_DOMAIN_MAC8	2
+#define RTW_REG_DOMAIN_RF_A	3
+#define RTW_REG_DOMAIN_RF_B	4
+#define RTW_REG_DOMAIN_NL	0xFF
+	u8 domain;
+};
+
+struct rtw_hw_reg_offset {
+	struct rtw_hw_reg hw_reg;
+	u8 offset;
+};
+
+struct rtw_rf_sipi_addr {
+	u32 hssi_1;
+	u32 hssi_2;
+	u32 lssi_read;
+	u32 lssi_read_pi;
+};
+
+struct rtw_ltecoex_addr {
+	u32 ctrl;
+	u32 wdata;
+	u32 rdata;
+};
+
 struct rtw_backup_info {
 	u8 len;
 	u32 reg;
@@ -480,6 +605,13 @@
 	bool fs;
 	bool short_gi;
 	bool report;
+	bool rts;
+	bool nav_use_hdr;
+	bool dis_qselseq;
+	bool en_hwseq;
+	u8 hw_ssn_sel;
+	bool en_hw_exseq;
+	bool bt_null;
 };
 
 struct rtw_rx_pkt_stat {
@@ -502,10 +634,16 @@
 	s8 rx_power[RTW_RF_PATH_MAX];
 	u8 rssi;
 	u8 rxsc;
+	s8 rx_snr[RTW_RF_PATH_MAX];
+	u8 rx_evm[RTW_RF_PATH_MAX];
+	s8 cfo_tail[RTW_RF_PATH_MAX];
+
 	struct rtw_sta_info *si;
 	struct ieee80211_vif *vif;
 };
 
+DECLARE_EWMA(tp, 10, 2);
+
 struct rtw_traffic_stats {
 	/* units in bytes */
 	u64 tx_unicast;
@@ -518,6 +656,8 @@
 	/* units in Mbps */
 	u32 tx_throughput;
 	u32 rx_throughput;
+	struct ewma_tp tx_ewma_tp;
+	struct ewma_tp rx_ewma_tp;
 };
 
 enum rtw_lps_mode {
@@ -526,6 +666,12 @@
 	RTW_MODE_WMM_PS	= 2,
 };
 
+enum rtw_lps_deep_mode {
+	LPS_DEEP_MODE_NONE	= 0,
+	LPS_DEEP_MODE_LCLK	= 1,
+	LPS_DEEP_MODE_PG	= 2,
+};
+
 enum rtw_pwr_state {
 	RTW_RF_OFF	= 0x0,
 	RTW_RF_ON	= 0x4,
@@ -533,14 +679,15 @@
 };
 
 struct rtw_lps_conf {
-	/* the interface to enter lps */
-	struct rtw_vif *rtwvif;
 	enum rtw_lps_mode mode;
+	enum rtw_lps_deep_mode deep_mode;
 	enum rtw_pwr_state state;
 	u8 awake_interval;
 	u8 rlbm;
 	u8 smart_ps;
 	u8 port_id;
+	bool sec_cam_backup;
+	bool pattern_cam_backup;
 };
 
 enum rtw_hw_key_type {
@@ -576,6 +723,19 @@
 	struct timer_list purge_timer;
 };
 
+struct rtw_ra_report {
+	struct rate_info txrate;
+	u32 bit_rate;
+	u8 desc_rate;
+};
+
+struct rtw_txq {
+	struct list_head list;
+
+	unsigned long flags;
+	unsigned long last_push;
+};
+
 #define RTW_BC_MC_MACID 1
 DECLARE_EWMA(rssi, 10, 16);
 
@@ -598,20 +758,57 @@
 	bool updated;
 	u8 init_ra_lv;
 	u64 ra_mask;
+
+	DECLARE_BITMAP(tid_ba, IEEE80211_NUM_TIDS);
+
+	struct rtw_ra_report ra_report;
+
+	bool use_cfg_mask;
+	struct cfg80211_bitrate_mask *mask;
+};
+
+enum rtw_bfee_role {
+	RTW_BFEE_NONE,
+	RTW_BFEE_SU,
+	RTW_BFEE_MU
+};
+
+struct rtw_bfee {
+	enum rtw_bfee_role role;
+
+	u16 p_aid;
+	u8 g_id;
+	u8 mac_addr[ETH_ALEN];
+	u8 sound_dim;
+
+	/* SU-MIMO */
+	u8 su_reg_index;
+
+	/* MU-MIMO */
+	u16 aid;
+};
+
+struct rtw_bf_info {
+	u8 bfer_mu_cnt;
+	u8 bfer_su_cnt;
+	DECLARE_BITMAP(bfer_su_reg_maping, 2);
+	u8 cur_csi_rpt_rate;
 };
 
 struct rtw_vif {
-	struct ieee80211_vif *vif;
 	enum rtw_net_type net_type;
 	u16 aid;
 	u8 mac_addr[ETH_ALEN];
 	u8 bssid[ETH_ALEN];
 	u8 port;
 	u8 bcn_ctrl;
+	struct list_head rsvd_page_list;
+	struct ieee80211_tx_queue_params tx_params[IEEE80211_NUM_ACS];
 	const struct rtw_vif_port *conf;
 
 	struct rtw_traffic_stats stats;
-	bool in_lps;
+
+	struct rtw_bfee bfee;
 };
 
 struct rtw_regulatory {
@@ -622,6 +819,7 @@
 
 struct rtw_chip_ops {
 	int (*mac_init)(struct rtw_dev *rtwdev);
+	void (*shutdown)(struct rtw_dev *rtwdev);
 	int (*read_efuse)(struct rtw_dev *rtwdev, u8 *map);
 	void (*phy_set_param)(struct rtw_dev *rtwdev);
 	void (*set_channel)(struct rtw_dev *rtwdev, u8 channel,
@@ -639,10 +837,21 @@
 	void (*set_antenna)(struct rtw_dev *rtwdev, u8 antenna_tx,
 			    u8 antenna_rx);
 	void (*cfg_ldo25)(struct rtw_dev *rtwdev, bool enable);
+	void (*efuse_grant)(struct rtw_dev *rtwdev, bool enable);
 	void (*false_alarm_statistics)(struct rtw_dev *rtwdev);
 	void (*phy_calibration)(struct rtw_dev *rtwdev);
 	void (*dpk_track)(struct rtw_dev *rtwdev);
 	void (*cck_pd_set)(struct rtw_dev *rtwdev, u8 level);
+	void (*pwr_track)(struct rtw_dev *rtwdev);
+	void (*config_bfee)(struct rtw_dev *rtwdev, struct rtw_vif *vif,
+			    struct rtw_bfee *bfee, bool enable);
+	void (*set_gid_table)(struct rtw_dev *rtwdev,
+			      struct ieee80211_vif *vif,
+			      struct ieee80211_bss_conf *conf);
+	void (*cfg_csi_rate)(struct rtw_dev *rtwdev, u8 rssi, u8 cur_rate,
+			     u8 fixrate_en, u8 *new_rate);
+	void (*adaptivity_init)(struct rtw_dev *rtwdev);
+	void (*adaptivity)(struct rtw_dev *rtwdev);
 
 	/* for coex */
 	void (*coex_set_init)(struct rtw_dev *rtwdev);
@@ -674,6 +883,7 @@
 #define RTW_PWR_INTF_PCI_MSK	BIT(2)
 #define RTW_PWR_INTF_ALL_MSK	(BIT(0) | BIT(1) | BIT(2) | BIT(3))
 
+#define RTW_PWR_CUT_TEST_MSK	BIT(0)
 #define RTW_PWR_CUT_A_MSK	BIT(1)
 #define RTW_PWR_CUT_B_MSK	BIT(2)
 #define RTW_PWR_CUT_C_MSK	BIT(3)
@@ -747,6 +957,7 @@
 	RTW_DMA_MAPPING_NORMAL	= 2,
 	RTW_DMA_MAPPING_HIGH	= 3,
 
+	RTW_DMA_MAPPING_MAX,
 	RTW_DMA_MAPPING_UNDEF,
 };
 
@@ -759,6 +970,16 @@
 	enum rtw_dma_mapping dma_map_hi;
 };
 
+struct rtw_prioq_addr {
+	u32 rsvd;
+	u32 avail;
+};
+
+struct rtw_prioq_addrs {
+	struct rtw_prioq_addr prio[RTW_DMA_MAPPING_MAX];
+	bool wsize;
+};
+
 struct rtw_page_table {
 	u16 hq_num;
 	u16 nq_num;
@@ -775,6 +996,33 @@
 	u16 platform;
 };
 
+struct rtw_wow_pattern {
+	u16 crc;
+	u8 type;
+	u8 valid;
+	u8 mask[RTW_MAX_PATTERN_MASK_SIZE];
+};
+
+struct rtw_pno_request {
+	bool inited;
+	u32 match_set_cnt;
+	struct cfg80211_match_set *match_sets;
+	u8 channel_cnt;
+	struct ieee80211_channel *channels;
+	struct cfg80211_sched_scan_plan scan_plan;
+};
+
+struct rtw_wow_param {
+	struct ieee80211_vif *wow_vif;
+	DECLARE_BITMAP(flags, RTW_WOW_FLAG_MAX);
+	u8 txpause;
+	u8 pattern_cnt;
+	struct rtw_wow_pattern patterns[RTW_MAX_PATTERN_NUM];
+
+	bool ips_enabled;
+	struct rtw_pno_request pno_req;
+};
+
 struct rtw_intf_phy_para_table {
 	struct rtw_intf_phy_para *usb2_para;
 	struct rtw_intf_phy_para *usb3_para;
@@ -818,12 +1066,48 @@
 	.txpwr_lmt_tbl = &rtw ## chip ## _txpwr_lmt_type ## pwrlmt ## _tbl, \
 	}
 
+#define RTW_PWR_TRK_5G_1		0
+#define RTW_PWR_TRK_5G_2		1
+#define RTW_PWR_TRK_5G_3		2
+#define RTW_PWR_TRK_5G_NUM		3
+
+#define RTW_PWR_TRK_TBL_SZ		30
+
+/* This table stores the values of TX power that will be adjusted by power
+ * tracking.
+ *
+ * For 5G bands, there are 3 different settings.
+ * For 2G there are cck rate and ofdm rate with different settings.
+ */
+struct rtw_pwr_track_tbl {
+	const u8 *pwrtrk_5gb_n[RTW_PWR_TRK_5G_NUM];
+	const u8 *pwrtrk_5gb_p[RTW_PWR_TRK_5G_NUM];
+	const u8 *pwrtrk_5ga_n[RTW_PWR_TRK_5G_NUM];
+	const u8 *pwrtrk_5ga_p[RTW_PWR_TRK_5G_NUM];
+	const u8 *pwrtrk_2gb_n;
+	const u8 *pwrtrk_2gb_p;
+	const u8 *pwrtrk_2ga_n;
+	const u8 *pwrtrk_2ga_p;
+	const u8 *pwrtrk_2g_cckb_n;
+	const u8 *pwrtrk_2g_cckb_p;
+	const u8 *pwrtrk_2g_ccka_n;
+	const u8 *pwrtrk_2g_ccka_p;
+	const s8 *pwrtrk_xtal_n;
+	const s8 *pwrtrk_xtal_p;
+};
+
+enum rtw_wlan_cpu {
+	RTW_WCPU_11AC,
+	RTW_WCPU_11N,
+};
+
 /* hardware configuration for each IC */
 struct rtw_chip_info {
 	struct rtw_chip_ops *ops;
 	u8 id;
 
 	const char *fw_name;
+	enum rtw_wlan_cpu wlan_cpu;
 	u8 tx_pkt_desc_sz;
 	u8 tx_buf_desc_sz;
 	u8 rx_pkt_desc_sz;
@@ -844,18 +1128,24 @@
 
 	bool ht_supported;
 	bool vht_supported;
+	u8 lps_deep_mode_supported;
 
 	/* init values */
 	u8 sys_func_en;
 	struct rtw_pwr_seq_cmd **pwr_on_seq;
 	struct rtw_pwr_seq_cmd **pwr_off_seq;
 	struct rtw_rqpn *rqpn_table;
+	struct rtw_prioq_addrs *prioq_addrs;
 	struct rtw_page_table *page_table;
 	struct rtw_intf_phy_para_table *intf_table;
 
 	struct rtw_hw_reg *dig;
+	struct rtw_hw_reg *dig_cck;
 	u32 rf_base_addr[2];
 	u32 rf_sipi_addr[2];
+	struct rtw_rf_sipi_addr *rf_sipi_read_addr;
+	u8 fix_rf_phy_num;
+	struct rtw_ltecoex_addr *ltecoex_addr;
 
 	const struct rtw_table *mac_tbl;
 	const struct rtw_table *agc_tbl;
@@ -868,6 +1158,19 @@
 
 	bool en_dis_dpd;
 	u16 dpd_ratemask;
+	u8 iqk_threshold;
+	const struct rtw_pwr_track_tbl *pwr_track_tbl;
+
+	u8 bfer_su_max_num;
+	u8 bfer_mu_max_num;
+
+	struct rtw_hw_reg_offset *edcca_th;
+	s8 l2h_th_ini_cs;
+	s8 l2h_th_ini_ad;
+
+	const char *wow_fw_name;
+	const struct wiphy_wowlan_support *wowlan_stub;
+	const u8 max_sched_scan_ssids;
 
 	/* coex paras */
 	u32 coex_para_ver;
@@ -886,6 +1189,7 @@
 	u8 bt_afh_span_bw40;
 	u8 afh_5g_num;
 	u8 wl_rf_para_num;
+	u8 coex_info_hw_regs_num;
 	const u8 *bt_rssi_step;
 	const u8 *wl_rssi_step;
 	const struct coex_table_para *table_nsant;
@@ -895,6 +1199,8 @@
 	const struct coex_rf_para *wl_rf_para_tx;
 	const struct coex_rf_para *wl_rf_para_rx;
 	const struct coex_5g_afh_map *afh_5g;
+	const struct rtw_hw_reg *btg_reg;
+	const struct rtw_reg_domain *coex_info_hw_regs;
 };
 
 enum rtw_coex_bt_state_cnt {
@@ -941,6 +1247,7 @@
 struct rtw_coex_dm {
 	bool cur_ps_tdma_on;
 	bool cur_wl_rx_low_gain_en;
+	bool ignore_wl_act;
 
 	u8 reason;
 	u8 bt_rssi_state[4];
@@ -1021,6 +1328,9 @@
 
 	u32 bt_supported_version;
 	u32 bt_supported_feature;
+	u32 patch_ver;
+	u16 bt_reg_vendor_ae;
+	u16 bt_reg_vendor_ac;
 	s8 bt_rssi;
 	u8 kt_ver;
 	u8 gnt_workaround_state;
@@ -1121,10 +1431,50 @@
 #define DACK_MSBK_BACKUP_NUM	0xf
 #define DACK_DCK_BACKUP_NUM	0x2
 
+struct rtw_swing_table {
+	const u8 *p[RTW_RF_PATH_MAX];
+	const u8 *n[RTW_RF_PATH_MAX];
+};
+
+struct rtw_pkt_count {
+	u16 num_bcn_pkt;
+	u16 num_qry_pkt[DESC_RATE_MAX];
+};
+
+DECLARE_EWMA(evm, 10, 4);
+DECLARE_EWMA(snr, 10, 4);
+
+#define EDCCA_TH_L2H_IDX 0
+#define EDCCA_TH_H2L_IDX 1
+#define EDCCA_TH_L2H_LB 48
+#define EDCCA_ADC_BACKOFF 12
+#define EDCCA_IGI_BASE 50
+#define EDCCA_IGI_L2H_DIFF 8
+#define EDCCA_L2H_H2L_DIFF 7
+#define EDCCA_L2H_H2L_DIFF_NORMAL 8
+
+enum rtw_edcca_mode {
+	RTW_EDCCA_NORMAL	= 0,
+	RTW_EDCCA_ADAPTIVITY	= 1,
+};
+
+struct rtw_iqk_info {
+	bool done;
+	struct {
+		u32 s1_x;
+		u32 s1_y;
+		u32 s0_x;
+		u32 s0_y;
+	} result;
+};
+
 struct rtw_dm_info {
 	u32 cck_fa_cnt;
 	u32 ofdm_fa_cnt;
 	u32 total_fa_cnt;
+	u32 cck_cca_cnt;
+	u32 ofdm_cca_cnt;
+	u32 total_cca_cnt;
 
 	u32 cck_ok_cnt;
 	u32 cck_err_cnt;
@@ -1147,6 +1497,17 @@
 	u8 cck_gi_u_bnd;
 	u8 cck_gi_l_bnd;
 
+	u8 tx_rate;
+	u8 thermal_avg[RTW_RF_PATH_MAX];
+	u8 thermal_meter_k;
+	s8 delta_power_index[RTW_RF_PATH_MAX];
+	u8 default_ofdm_index;
+	bool pwr_trk_triggered;
+	bool pwr_trk_init_trigger;
+	struct ewma_thermal avg_thermal[RTW_RF_PATH_MAX];
+	s8 txagc_remnant_cck;
+	s8 txagc_remnant_ofdm;
+
 	/* backup dack results for each path and I/Q */
 	u32 dack_adck[RTW_RF_PATH_MAX];
 	u16 dack_msbk[RTW_RF_PATH_MAX][2][DACK_MSBK_BACKUP_NUM];
@@ -1157,6 +1518,22 @@
 	/* [bandwidth 0:20M/1:40M][number of path] */
 	u8 cck_pd_lv[2][RTW_RF_PATH_MAX];
 	u32 cck_fa_avg;
+
+	/* save the last rx phy status for debug */
+	s8 rx_snr[RTW_RF_PATH_MAX];
+	u8 rx_evm_dbm[RTW_RF_PATH_MAX];
+	s16 cfo_tail[RTW_RF_PATH_MAX];
+	u8 rssi[RTW_RF_PATH_MAX];
+	u8 curr_rx_rate;
+	struct rtw_pkt_count cur_pkt_count;
+	struct rtw_pkt_count last_pkt_count;
+	struct ewma_evm ewma_evm[RTW_EVM_NUM];
+	struct ewma_snr ewma_snr[RTW_SNR_NUM];
+
+	s8 l2h_th_ini;
+	enum rtw_edcca_mode edcca_mode;
+
+	struct rtw_iqk_info iqk;
 };
 
 struct rtw_efuse {
@@ -1168,13 +1545,17 @@
 	u8 addr[ETH_ALEN];
 	u8 channel_plan;
 	u8 country_code[2];
+	bool country_worldwide;
 	u8 rf_board_option;
 	u8 rfe_option;
-	u8 thermal_meter;
+	u8 power_track_type;
+	u8 thermal_meter[RTW_RF_PATH_MAX];
+	u8 thermal_meter_k;
 	u8 crystal_cap;
 	u8 ant_div_cfg;
 	u8 ant_div_type;
 	u8 regd;
+	u8 afe;
 
 	u8 lna_type_2g;
 	u8 lna_type_5g;
@@ -1252,11 +1633,12 @@
 	u16 rsvd_cpu_instr_addr;
 	u16 rsvd_fw_txbuf_addr;
 	u16 rsvd_csibuf_addr;
-	enum rtw_dma_mapping pq_map[RTW_PQ_MAP_NUM];
+	struct rtw_rqpn *rqpn;
 };
 
 struct rtw_fw_state {
 	const struct firmware *firmware;
+	struct rtw_dev *rtwdev;
 	struct completion completion;
 	u16 version;
 	u8 sub_version;
@@ -1264,6 +1646,15 @@
 	u16 h2c_version;
 };
 
+struct rtw_sar {
+	enum rtw_sar_sources source;
+	struct rtw_sar_rwrd *rwrd;
+	union rtw_sar_rwsi *rwsi;
+	union rtw_sar_rwgs *rwgs;
+	const struct rtw_sar_read *read;
+	struct delayed_work work;
+};
+
 struct rtw_hal {
 	u32 rcr;
 
@@ -1287,8 +1678,10 @@
 	u8 sec_ch_offset;
 	u8 rf_type;
 	u8 rf_path_num;
+	u8 rf_phy_num;
 	u8 antenna_tx;
 	u8 antenna_rx;
+	u8 bfee_sts_cap;
 
 	/* protect tx power section */
 	struct mutex tx_power_mutex;
@@ -1308,6 +1701,10 @@
 			  [RTW_CHANNEL_WIDTH_MAX]
 			  [RTW_RATE_SECTION_MAX]
 			  [RTW_MAX_CHANNEL_NUM_5G];
+	s8 tx_pwr_sar_2g[RTW_REGD_MAX][RTW_RF_PATH_MAX][RTW_RATE_SECTION_MAX]
+			[RTW_MAX_CHANNEL_NUM_2G];
+	s8 tx_pwr_sar_5g[RTW_REGD_MAX][RTW_RF_PATH_MAX][RTW_RATE_SECTION_MAX]
+			[RTW_MAX_CHANNEL_NUM_5G];
 	s8 tx_pwr_tbl[RTW_RF_PATH_MAX]
 		     [DESC_RATE_MAX];
 };
@@ -1326,6 +1723,7 @@
 	struct rtw_sec_desc sec;
 	struct rtw_traffic_stats stats;
 	struct rtw_regulatory regd;
+	struct rtw_bf_info bf_info;
 
 	struct rtw_dm_info dm_info;
 	struct rtw_coex coex;
@@ -1333,9 +1731,6 @@
 	/* ensures exclusive access from mac80211 callbacks */
 	struct mutex mutex;
 
-	/* lock for dm to use */
-	spinlock_t dm_lock;
-
 	/* read/write rf register */
 	spinlock_t rf_lock;
 
@@ -1349,6 +1744,12 @@
 	struct sk_buff_head c2h_queue;
 	struct work_struct c2h_work;
 
+	/* used to protect txqs list */
+	spinlock_t txq_lock;
+	struct list_head txqs;
+	struct tasklet_struct tx_tasklet;
+	struct work_struct ba_work;
+
 	struct rtw_tx_report tx_report;
 
 	struct {
@@ -1361,41 +1762,82 @@
 
 	/* lps power state & handler work */
 	struct rtw_lps_conf lps_conf;
-	struct delayed_work lps_work;
+	bool ps_enabled;
 
 	struct dentry *debugfs;
 
 	u8 sta_cnt;
+	u32 rts_threshold;
 
 	DECLARE_BITMAP(mac_id_map, RTW_MAX_MAC_ID_NUM);
 	DECLARE_BITMAP(flags, NUM_OF_RTW_FLAGS);
 
 	u8 mp_mode;
 
+	struct rtw_fw_state wow_fw;
+	struct rtw_wow_param wow;
+
+	struct rtw_sar sar;
+
+	bool need_rfk;
+
 	/* hci related data, must be last */
 	u8 priv[0] __aligned(sizeof(void *));
 };
 
 #include "hci.h"
 
-static inline bool rtw_flag_check(struct rtw_dev *rtwdev, enum rtw_flags flag)
+static inline bool rtw_is_assoc(struct rtw_dev *rtwdev)
 {
-	return test_bit(flag, rtwdev->flags);
+	return !!rtwdev->sta_cnt;
 }
 
-static inline void rtw_flag_clear(struct rtw_dev *rtwdev, enum rtw_flags flag)
+static inline struct ieee80211_txq *rtwtxq_to_txq(struct rtw_txq *rtwtxq)
 {
-	clear_bit(flag, rtwdev->flags);
+	void *p = rtwtxq;
+
+	return container_of(p, struct ieee80211_txq, drv_priv);
 }
 
-static inline void rtw_flag_set(struct rtw_dev *rtwdev, enum rtw_flags flag)
+static inline struct ieee80211_vif *rtwvif_to_vif(struct rtw_vif *rtwvif)
 {
-	set_bit(flag, rtwdev->flags);
+	void *p = rtwvif;
+
+	return container_of(p, struct ieee80211_vif, drv_priv);
 }
 
-static inline bool rtw_is_assoc(struct rtw_dev *rtwdev)
+static inline bool rtw_ssid_equal(struct cfg80211_ssid *a,
+				  struct cfg80211_ssid *b)
 {
-	return !!rtwdev->sta_cnt;
+	if (!a || !b || a->ssid_len != b->ssid_len)
+		return false;
+
+	if (memcmp(a->ssid, b->ssid, a->ssid_len))
+		return false;
+
+	return true;
+}
+
+static inline void rtw_chip_efuse_grant_on(struct rtw_dev *rtwdev)
+{
+	if (rtwdev->chip->ops->efuse_grant)
+		rtwdev->chip->ops->efuse_grant(rtwdev, true);
+}
+
+static inline void rtw_chip_efuse_grant_off(struct rtw_dev *rtwdev)
+{
+	if (rtwdev->chip->ops->efuse_grant)
+		rtwdev->chip->ops->efuse_grant(rtwdev, false);
+}
+
+static inline bool rtw_chip_wcpu_11n(struct rtw_dev *rtwdev)
+{
+	return rtwdev->chip->wlan_cpu == RTW_WCPU_11N;
+}
+
+static inline bool rtw_chip_wcpu_11ac(struct rtw_dev *rtwdev)
+{
+	return rtwdev->chip->wlan_cpu == RTW_WCPU_11AC;
 }
 
 void rtw_get_channel_params(struct cfg80211_chan_def *chandef,
@@ -1405,7 +1847,9 @@
 bool ltecoex_reg_write(struct rtw_dev *rtwdev, u16 offset, u32 value);
 void rtw_restore_reg(struct rtw_dev *rtwdev,
 		     struct rtw_backup_info *bckp, u32 num);
+void rtw_desc_to_mcsrate(u16 rate, u8 *mcs, u8 *nss);
 void rtw_set_channel(struct rtw_dev *rtwdev);
+void rtw_chip_prepare_tx(struct rtw_dev *rtwdev);
 void rtw_vif_port_config(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif,
 			 u32 config);
 void rtw_tx_report_purge_timer(struct timer_list *t);
@@ -1417,5 +1861,6 @@
 void rtw_core_deinit(struct rtw_dev *rtwdev);
 int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw);
 void rtw_unregister_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw);
+u16 rtw_desc_to_bitrate(u8 desc_rate);
 
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/pci.c
@@ -6,9 +6,11 @@
 #include <linux/pci.h>
 #include "main.h"
 #include "pci.h"
+#include "reg.h"
 #include "tx.h"
 #include "rx.h"
 #include "fw.h"
+#include "ps.h"
 #include "debug.h"
 
 static bool rtw_disable_msi;
@@ -380,6 +382,7 @@
 	rtwpci->irq_mask[3] = IMR_H2CDOK |
 			      0;
 	spin_lock_init(&rtwpci->irq_lock);
+	spin_lock_init(&rtwpci->hwirq_lock);
 	ret = rtw_pci_init_trx_ring(rtwdev);
 
 	return ret;
@@ -398,12 +401,14 @@
 	dma = rtwpci->tx_rings[RTW_TX_QUEUE_BCN].r.dma;
 	rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_BCNQ, dma);
 
-	len = rtwpci->tx_rings[RTW_TX_QUEUE_H2C].r.len;
-	dma = rtwpci->tx_rings[RTW_TX_QUEUE_H2C].r.dma;
-	rtwpci->tx_rings[RTW_TX_QUEUE_H2C].r.rp = 0;
-	rtwpci->tx_rings[RTW_TX_QUEUE_H2C].r.wp = 0;
-	rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_H2CQ, len);
-	rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_H2CQ, dma);
+	if (!rtw_chip_wcpu_11n(rtwdev)) {
+		len = rtwpci->tx_rings[RTW_TX_QUEUE_H2C].r.len;
+		dma = rtwpci->tx_rings[RTW_TX_QUEUE_H2C].r.dma;
+		rtwpci->tx_rings[RTW_TX_QUEUE_H2C].r.rp = 0;
+		rtwpci->tx_rings[RTW_TX_QUEUE_H2C].r.wp = 0;
+		rtw_write16(rtwdev, RTK_PCI_TXBD_NUM_H2CQ, len);
+		rtw_write32(rtwdev, RTK_PCI_TXBD_DESA_H2CQ, dma);
+	}
 
 	len = rtwpci->tx_rings[RTW_TX_QUEUE_BK].r.len;
 	dma = rtwpci->tx_rings[RTW_TX_QUEUE_BK].r.dma;
@@ -457,9 +462,10 @@
 	/* reset read/write point */
 	rtw_write32(rtwdev, RTK_PCI_TXBD_RWPTR_CLR, 0xffffffff);
 
-	/* rest H2C Queue index */
-	rtw_write32_set(rtwdev, RTK_PCI_TXBD_H2CQ_CSR, BIT_CLR_H2CQ_HOST_IDX);
-	rtw_write32_set(rtwdev, RTK_PCI_TXBD_H2CQ_CSR, BIT_CLR_H2CQ_HW_IDX);
+	/* reset H2C Queue index in a single write */
+	if (rtw_chip_wcpu_11ac(rtwdev))
+		rtw_write32_set(rtwdev, RTK_PCI_TXBD_H2CQ_CSR,
+				BIT_CLR_H2CQ_HOST_IDX | BIT_CLR_H2CQ_HW_IDX);
 }
 
 static void rtw_pci_reset_trx_ring(struct rtw_dev *rtwdev)
@@ -470,26 +476,39 @@
 static void rtw_pci_enable_interrupt(struct rtw_dev *rtwdev,
 				     struct rtw_pci *rtwpci)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&rtwpci->hwirq_lock, flags);
+
 	rtw_write32(rtwdev, RTK_PCI_HIMR0, rtwpci->irq_mask[0]);
 	rtw_write32(rtwdev, RTK_PCI_HIMR1, rtwpci->irq_mask[1]);
-	rtw_write32(rtwdev, RTK_PCI_HIMR3, rtwpci->irq_mask[3]);
+	if (rtw_chip_wcpu_11ac(rtwdev))
+		rtw_write32(rtwdev, RTK_PCI_HIMR3, rtwpci->irq_mask[3]);
+
 	rtwpci->irq_enabled = true;
+
+	spin_unlock_irqrestore(&rtwpci->hwirq_lock, flags);
 }
 
 static void rtw_pci_disable_interrupt(struct rtw_dev *rtwdev,
 				      struct rtw_pci *rtwpci)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&rtwpci->hwirq_lock, flags);
+
+	if (!rtwpci->irq_enabled)
+		goto out;
+
 	rtw_write32(rtwdev, RTK_PCI_HIMR0, 0);
 	rtw_write32(rtwdev, RTK_PCI_HIMR1, 0);
-	rtw_write32(rtwdev, RTK_PCI_HIMR3, 0);
-	rtwpci->irq_enabled = false;
-}
+	if (rtw_chip_wcpu_11ac(rtwdev))
+		rtw_write32(rtwdev, RTK_PCI_HIMR3, 0);
 
-static int rtw_pci_setup(struct rtw_dev *rtwdev)
-{
-	rtw_pci_reset_trx_ring(rtwdev);
+	rtwpci->irq_enabled = false;
 
-	return 0;
+out:
+	spin_unlock_irqrestore(&rtwpci->hwirq_lock, flags);
 }
 
 static void rtw_pci_dma_reset(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci)
@@ -500,11 +519,22 @@
 	rtwpci->rx_tag = 0;
 }
 
+static int rtw_pci_setup(struct rtw_dev *rtwdev)
+{
+	struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
+
+	rtw_pci_reset_trx_ring(rtwdev);
+	rtw_pci_dma_reset(rtwdev, rtwpci);
+
+	return 0;
+}
+
 static void rtw_pci_dma_release(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci)
 {
 	struct rtw_pci_tx_ring *tx_ring;
 	u8 queue;
 
+	rtw_pci_reset_trx_ring(rtwdev);
 	for (queue = 0; queue < RTK_MAX_TX_QUEUE_NUM; queue++) {
 		tx_ring = &rtwpci->tx_rings[queue];
 		rtw_pci_free_tx_ring_skbs(rtwdev, tx_ring);
@@ -514,13 +544,10 @@
 static int rtw_pci_start(struct rtw_dev *rtwdev)
 {
 	struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
-	unsigned long flags;
-
-	rtw_pci_dma_reset(rtwdev, rtwpci);
 
-	spin_lock_irqsave(&rtwpci->irq_lock, flags);
+	spin_lock_bh(&rtwpci->irq_lock);
 	rtw_pci_enable_interrupt(rtwdev, rtwpci);
-	spin_unlock_irqrestore(&rtwpci->irq_lock, flags);
+	spin_unlock_bh(&rtwpci->irq_lock);
 
 	return 0;
 }
@@ -528,12 +555,73 @@
 static void rtw_pci_stop(struct rtw_dev *rtwdev)
 {
 	struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
-	unsigned long flags;
 
-	spin_lock_irqsave(&rtwpci->irq_lock, flags);
+	spin_lock_bh(&rtwpci->irq_lock);
 	rtw_pci_disable_interrupt(rtwdev, rtwpci);
 	rtw_pci_dma_release(rtwdev, rtwpci);
-	spin_unlock_irqrestore(&rtwpci->irq_lock, flags);
+	spin_unlock_bh(&rtwpci->irq_lock);
+}
+
+static void rtw_pci_deep_ps_enter(struct rtw_dev *rtwdev)
+{
+	struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
+	struct rtw_pci_tx_ring *tx_ring;
+	bool tx_empty = true;
+	u8 queue;
+
+	lockdep_assert_held(&rtwpci->irq_lock);
+
+	/* Deep PS state is not allowed to TX-DMA */
+	for (queue = 0; queue < RTK_MAX_TX_QUEUE_NUM; queue++) {
+		/* BCN queue is rsvd page, does not have DMA interrupt
+		 * H2C queue is managed by firmware
+		 */
+		if (queue == RTW_TX_QUEUE_BCN ||
+		    queue == RTW_TX_QUEUE_H2C)
+			continue;
+
+		tx_ring = &rtwpci->tx_rings[queue];
+
+		/* check if there is any skb DMAing */
+		if (skb_queue_len(&tx_ring->queue)) {
+			tx_empty = false;
+			break;
+		}
+	}
+
+	if (!tx_empty) {
+		rtw_dbg(rtwdev, RTW_DBG_PS,
+			"TX path not empty, cannot enter deep power save state\n");
+		return;
+	}
+
+	set_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags);
+	rtw_power_mode_change(rtwdev, true);
+}
+
+static void rtw_pci_deep_ps_leave(struct rtw_dev *rtwdev)
+{
+	struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
+
+	lockdep_assert_held(&rtwpci->irq_lock);
+
+	if (test_and_clear_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags))
+		rtw_power_mode_change(rtwdev, false);
+}
+
+static void rtw_pci_deep_ps(struct rtw_dev *rtwdev, bool enter)
+{
+	struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
+
+	spin_lock_bh(&rtwpci->irq_lock);
+
+	if (enter && !test_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags))
+		rtw_pci_deep_ps_enter(rtwdev);
+
+	if (!enter && test_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags))
+		rtw_pci_deep_ps_leave(rtwdev);
+
+	spin_unlock_bh(&rtwpci->irq_lock);
 }
 
 static u8 ac_to_hwq[] = {
@@ -651,6 +739,10 @@
 	tx_data = rtw_pci_get_tx_data(skb);
 	tx_data->dma = dma;
 	tx_data->sn = pkt_info->sn;
+
+	spin_lock_bh(&rtwpci->irq_lock);
+
+	rtw_pci_deep_ps_leave(rtwdev);
 	skb_queue_tail(&ring->queue, skb);
 
 	/* kick off tx queue */
@@ -666,6 +758,7 @@
 		reg_bcn_work |= BIT_PCI_BCNQ_FLAG;
 		rtw_write8(rtwdev, RTK_PCI_TXBD_BCN_WORK, reg_bcn_work);
 	}
+	spin_unlock_bh(&rtwpci->irq_lock);
 
 	return 0;
 }
@@ -674,43 +767,24 @@
 					u32 size)
 {
 	struct sk_buff *skb;
-	struct rtw_tx_pkt_info pkt_info;
-	u32 tx_pkt_desc_sz;
-	u32 length;
-
-	tx_pkt_desc_sz = rtwdev->chip->tx_pkt_desc_sz;
-	length = size + tx_pkt_desc_sz;
-	skb = dev_alloc_skb(length);
+	struct rtw_tx_pkt_info pkt_info = {0};
+
+	skb = rtw_tx_write_data_rsvd_page_get(rtwdev, &pkt_info, buf, size);
 	if (!skb)
 		return -ENOMEM;
 
-	skb_reserve(skb, tx_pkt_desc_sz);
-	memcpy((u8 *)skb_put(skb, size), buf, size);
-	memset(&pkt_info, 0, sizeof(pkt_info));
-	pkt_info.tx_pkt_size = size;
-	pkt_info.offset = tx_pkt_desc_sz;
-
 	return rtw_pci_xmit(rtwdev, &pkt_info, skb, RTW_TX_QUEUE_BCN);
 }
 
 static int rtw_pci_write_data_h2c(struct rtw_dev *rtwdev, u8 *buf, u32 size)
 {
 	struct sk_buff *skb;
-	struct rtw_tx_pkt_info pkt_info;
-	u32 tx_pkt_desc_sz;
-	u32 length;
-
-	tx_pkt_desc_sz = rtwdev->chip->tx_pkt_desc_sz;
-	length = size + tx_pkt_desc_sz;
-	skb = dev_alloc_skb(length);
+	struct rtw_tx_pkt_info pkt_info = {0};
+
+	skb = rtw_tx_write_data_h2c_get(rtwdev, &pkt_info, buf, size);
 	if (!skb)
 		return -ENOMEM;
 
-	skb_reserve(skb, tx_pkt_desc_sz);
-	memcpy((u8 *)skb_put(skb, size), buf, size);
-	memset(&pkt_info, 0, sizeof(pkt_info));
-	pkt_info.tx_pkt_size = size;
-
 	return rtw_pci_xmit(rtwdev, &pkt_info, skb, RTW_TX_QUEUE_H2C);
 }
 
@@ -762,6 +836,11 @@
 
 	while (count--) {
 		skb = skb_dequeue(&ring->queue);
+		if (!skb) {
+			rtw_err(rtwdev, "failed to dequeue %d skb TX queue %d, BD=0x%08x, rp %d -> %d\n",
+				count, hw_queue, bd_idx, ring->r.rp, cur_rp);
+			break;
+		}
 		tx_data = rtw_pci_get_tx_data(skb);
 		pci_unmap_single(rtwpci->pdev, tx_data->dma, skb->len,
 				 PCI_DMA_TODEVICE);
@@ -883,15 +962,25 @@
 static void rtw_pci_irq_recognized(struct rtw_dev *rtwdev,
 				   struct rtw_pci *rtwpci, u32 *irq_status)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&rtwpci->hwirq_lock, flags);
+
 	irq_status[0] = rtw_read32(rtwdev, RTK_PCI_HISR0);
 	irq_status[1] = rtw_read32(rtwdev, RTK_PCI_HISR1);
-	irq_status[3] = rtw_read32(rtwdev, RTK_PCI_HISR3);
+	if (rtw_chip_wcpu_11ac(rtwdev))
+		irq_status[3] = rtw_read32(rtwdev, RTK_PCI_HISR3);
+	else
+		irq_status[3] = 0;
 	irq_status[0] &= rtwpci->irq_mask[0];
 	irq_status[1] &= rtwpci->irq_mask[1];
 	irq_status[3] &= rtwpci->irq_mask[3];
 	rtw_write32(rtwdev, RTK_PCI_HISR0, irq_status[0]);
 	rtw_write32(rtwdev, RTK_PCI_HISR1, irq_status[1]);
-	rtw_write32(rtwdev, RTK_PCI_HISR3, irq_status[3]);
+	if (rtw_chip_wcpu_11ac(rtwdev))
+		rtw_write32(rtwdev, RTK_PCI_HISR3, irq_status[3]);
+
+	spin_unlock_irqrestore(&rtwpci->hwirq_lock, flags);
 }
 
 static irqreturn_t rtw_pci_interrupt_handler(int irq, void *dev)
@@ -899,10 +988,6 @@
 	struct rtw_dev *rtwdev = dev;
 	struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
 
-	spin_lock(&rtwpci->irq_lock);
-	if (!rtwpci->irq_enabled)
-		goto out;
-
 	/* disable RTW PCI interrupt to avoid more interrupts before the end of
 	 * thread function
 	 *
@@ -912,8 +997,6 @@
 	 * a new HISR flag is set.
 	 */
 	rtw_pci_disable_interrupt(rtwdev, rtwpci);
-out:
-	spin_unlock(&rtwpci->irq_lock);
 
 	return IRQ_WAKE_THREAD;
 }
@@ -922,10 +1005,9 @@
 {
 	struct rtw_dev *rtwdev = dev;
 	struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
-	unsigned long flags;
 	u32 irq_status[4];
 
-	spin_lock_irqsave(&rtwpci->irq_lock, flags);
+	spin_lock_bh(&rtwpci->irq_lock);
 	rtw_pci_irq_recognized(rtwdev, rtwpci, irq_status);
 
 	if (irq_status[0] & IMR_MGNTDOK)
@@ -947,7 +1029,7 @@
 
 	/* all of the jobs for this interrupt have been done */
 	rtw_pci_enable_interrupt(rtwdev, rtwpci);
-	spin_unlock_irqrestore(&rtwpci->irq_lock, flags);
+	spin_unlock_bh(&rtwpci->irq_lock);
 
 	return IRQ_HANDLED;
 }
@@ -969,6 +1051,7 @@
 	len = pci_resource_len(pdev, bar_id);
 	rtwpci->mmap = pci_iomap(pdev, bar_id, len);
 	if (!rtwpci->mmap) {
+		pci_release_regions(pdev);
 		rtw_err(rtwdev, "failed to map pci memory\n");
 		return -ENOMEM;
 	}
@@ -990,23 +1073,49 @@
 static void rtw_dbi_write8(struct rtw_dev *rtwdev, u16 addr, u8 data)
 {
 	u16 write_addr;
-	u16 remainder = addr & 0x3;
+	u16 remainder = addr & ~(BITS_DBI_WREN | BITS_DBI_ADDR_MASK);
 	u8 flag;
-	u8 cnt = 20;
+	u8 cnt;
 
-	write_addr = ((addr & 0x0ffc) | (BIT(0) << (remainder + 12)));
+	write_addr = addr & BITS_DBI_ADDR_MASK;
+	write_addr |= u16_encode_bits(BIT(remainder), BITS_DBI_WREN);
 	rtw_write8(rtwdev, REG_DBI_WDATA_V1 + remainder, data);
 	rtw_write16(rtwdev, REG_DBI_FLAG_V1, write_addr);
-	rtw_write8(rtwdev, REG_DBI_FLAG_V1 + 2, 0x01);
+	rtw_write8(rtwdev, REG_DBI_FLAG_V1 + 2, BIT_DBI_WFLAG >> 16);
+
+	for (cnt = 0; cnt < RTW_PCI_WR_RETRY_CNT; cnt++) {
+		flag = rtw_read8(rtwdev, REG_DBI_FLAG_V1 + 2);
+		if (flag == 0)
+			return;
 
-	flag = rtw_read8(rtwdev, REG_DBI_FLAG_V1 + 2);
-	while (flag && (cnt != 0)) {
 		udelay(10);
+	}
+
+	WARN(flag, "failed to write to DBI register, addr=0x%04x\n", addr);
+}
+
+static int rtw_dbi_read8(struct rtw_dev *rtwdev, u16 addr, u8 *value)
+{
+	u16 read_addr = addr & BITS_DBI_ADDR_MASK;
+	u8 flag;
+	u8 cnt;
+
+	rtw_write16(rtwdev, REG_DBI_FLAG_V1, read_addr);
+	rtw_write8(rtwdev, REG_DBI_FLAG_V1 + 2, BIT_DBI_RFLAG >> 16);
+
+	for (cnt = 0; cnt < RTW_PCI_WR_RETRY_CNT; cnt++) {
 		flag = rtw_read8(rtwdev, REG_DBI_FLAG_V1 + 2);
-		cnt--;
+		if (flag == 0) {
+			read_addr = REG_DBI_RDATA_V1 + (addr & 3);
+			*value = rtw_read8(rtwdev, read_addr);
+			return 0;
+		}
+
+		udelay(10);
 	}
 
-	WARN(flag, "DBI write fail\n");
+	WARN(1, "failed to read DBI register, addr=0x%04x\n", addr);
+	return -EIO;
 }
 
 static void rtw_mdio_write(struct rtw_dev *rtwdev, u8 addr, u16 data, bool g1)
@@ -1017,23 +1126,135 @@
 
 	rtw_write16(rtwdev, REG_MDIO_V1, data);
 
-	page = addr < 0x20 ? 0 : 1;
-	page += g1 ? 0 : 2;
-	rtw_write8(rtwdev, REG_PCIE_MIX_CFG, addr & 0x1f);
+	page = addr < RTW_PCI_MDIO_PG_SZ ? 0 : 1;
+	page += g1 ? RTW_PCI_MDIO_PG_OFFS_G1 : RTW_PCI_MDIO_PG_OFFS_G2;
+	rtw_write8(rtwdev, REG_PCIE_MIX_CFG, addr & BITS_MDIO_ADDR_MASK);
 	rtw_write8(rtwdev, REG_PCIE_MIX_CFG + 3, page);
-
 	rtw_write32_mask(rtwdev, REG_PCIE_MIX_CFG, BIT_MDIO_WFLAG_V1, 1);
-	wflag = rtw_read32_mask(rtwdev, REG_PCIE_MIX_CFG, BIT_MDIO_WFLAG_V1);
 
-	cnt = 20;
-	while (wflag && (cnt != 0)) {
-		udelay(10);
+	for (cnt = 0; cnt < RTW_PCI_WR_RETRY_CNT; cnt++) {
 		wflag = rtw_read32_mask(rtwdev, REG_PCIE_MIX_CFG,
 					BIT_MDIO_WFLAG_V1);
-		cnt--;
+		if (wflag == 0)
+			return;
+
+		udelay(10);
+	}
+
+	WARN(wflag, "failed to write to MDIO register, addr=0x%02x\n", addr);
+}
+
+static void rtw_pci_clkreq_set(struct rtw_dev *rtwdev, bool enable)
+{
+	u8 value;
+	int ret;
+
+	ret = rtw_dbi_read8(rtwdev, RTK_PCIE_LINK_CFG, &value);
+	if (ret) {
+		rtw_err(rtwdev, "failed to read CLKREQ_L1, ret=%d", ret);
+		return;
+	}
+
+	if (enable)
+		value |= BIT_CLKREQ_SW_EN;
+	else
+		value &= ~BIT_CLKREQ_SW_EN;
+
+	rtw_dbi_write8(rtwdev, RTK_PCIE_LINK_CFG, value);
+}
+
+static void rtw_pci_aspm_set(struct rtw_dev *rtwdev, bool enable)
+{
+	u8 value;
+	int ret;
+
+	ret = rtw_dbi_read8(rtwdev, RTK_PCIE_LINK_CFG, &value);
+	if (ret) {
+		rtw_err(rtwdev, "failed to read ASPM, ret=%d", ret);
+		return;
+	}
+
+	if (enable)
+		value |= BIT_L1_SW_EN;
+	else
+		value &= ~BIT_L1_SW_EN;
+
+	rtw_dbi_write8(rtwdev, RTK_PCIE_LINK_CFG, value);
+}
+
+static void rtw_pci_link_ps(struct rtw_dev *rtwdev, bool enter)
+{
+	struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
+
+	/* Like CLKREQ, ASPM is also implemented by two HW modules, and can
+	 * only be enabled when host supports it.
+	 *
+	 * And ASPM mechanism should be enabled when driver/firmware enters
+	 * power save mode, without having heavy traffic. Because we've
+	 * experienced some inter-operability issues that the link tends
+	 * to enter L1 state on the fly even when driver is having high
+	 * throughput. This is probably because the ASPM behavior slightly
+	 * varies from different SOC.
+	 */
+	if (rtwpci->link_ctrl & PCI_EXP_LNKCTL_ASPM_L1)
+		rtw_pci_aspm_set(rtwdev, enter);
+}
+
+static void rtw_pci_link_cfg(struct rtw_dev *rtwdev)
+{
+	struct rtw_chip_info *chip = rtwdev->chip;
+	struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
+	struct pci_dev *pdev = rtwpci->pdev;
+	u16 link_ctrl;
+	int ret;
+
+	/* RTL8822CE has enabled REFCLK auto calibration, it does not need
+	 * to add clock delay to cover the REFCLK timing gap.
+	 */
+	if (chip->id == RTW_CHIP_TYPE_8822C)
+		rtw_dbi_write8(rtwdev, RTK_PCIE_CLKDLY_CTRL, 0);
+
+	/* Though there is standard PCIE configuration space to set the
+	 * link control register, but by Realtek's design, driver should
+	 * check if host supports CLKREQ/ASPM to enable the HW module.
+	 *
+	 * These functions are implemented by two HW modules associated,
+	 * one is responsible to access PCIE configuration space to
+	 * follow the host settings, and another is in charge of doing
+	 * CLKREQ/ASPM mechanisms, it is default disabled. Because sometimes
+	 * the host does not support it, and due to some reasons or wrong
+	 * settings (ex. CLKREQ# not Bi-Direction), it could lead to device
+	 * loss if HW misbehaves on the link.
+	 *
+	 * Hence it's designed that driver should first check the PCIE
+	 * configuration space is sync'ed and enabled, then driver can turn
+	 * on the other module that is actually working on the mechanism.
+	 */
+	ret = pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &link_ctrl);
+	if (ret) {
+		rtw_err(rtwdev, "failed to read PCI cap, ret=%d\n", ret);
+		return;
 	}
 
-	WARN(wflag, "MDIO write fail\n");
+	if (link_ctrl & PCI_EXP_LNKCTL_CLKREQ_EN)
+		rtw_pci_clkreq_set(rtwdev, true);
+
+	rtwpci->link_ctrl = link_ctrl;
+}
+
+static void rtw_pci_interface_cfg(struct rtw_dev *rtwdev)
+{
+	struct rtw_chip_info *chip = rtwdev->chip;
+
+	switch (chip->id) {
+	case RTW_CHIP_TYPE_8822C:
+		if (rtwdev->hal.cut_version >= RTW_CHIP_VER_CUT_D)
+			rtw_write32_mask(rtwdev, REG_HCI_MIX_CFG,
+					 BIT_PCIE_EMAC_PDN_AUX_TO_FAST_CLK, 1);
+		break;
+	default:
+		break;
+	}
 }
 
 static void rtw_pci_phy_cfg(struct rtw_dev *rtwdev)
@@ -1074,8 +1295,27 @@
 		else
 			rtw_dbi_write8(rtwdev, offset, value);
 	}
+
+	rtw_pci_link_cfg(rtwdev);
 }
 
+#ifdef CONFIG_PM
+static int rtw_pci_suspend(struct device *dev)
+{
+	return 0;
+}
+
+static int rtw_pci_resume(struct device *dev)
+{
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(rtw_pm_ops, rtw_pci_suspend, rtw_pci_resume);
+#define RTW_PM_OPS (&rtw_pm_ops)
+#else
+#define RTW_PM_OPS NULL
+#endif
+
 static int rtw_pci_claim(struct rtw_dev *rtwdev, struct pci_dev *pdev)
 {
 	int ret;
@@ -1120,8 +1360,6 @@
 		goto err_io_unmap;
 	}
 
-	rtw_pci_phy_cfg(rtwdev);
-
 	return 0;
 
 err_io_unmap:
@@ -1142,6 +1380,9 @@
 	.setup = rtw_pci_setup,
 	.start = rtw_pci_start,
 	.stop = rtw_pci_stop,
+	.deep_ps = rtw_pci_deep_ps,
+	.link_ps = rtw_pci_link_ps,
+	.interface_cfg = rtw_pci_interface_cfg,
 
 	.read8 = rtw_pci_read8,
 	.read16 = rtw_pci_read16,
@@ -1233,6 +1474,8 @@
 		goto err_destroy_pci;
 	}
 
+	rtw_pci_phy_cfg(rtwdev);
+
 	ret = rtw_register_hw(rtwdev, hw);
 	if (ret) {
 		rtw_err(rtwdev, "failed to register hw\n");
@@ -1283,12 +1526,32 @@
 	ieee80211_free_hw(hw);
 }
 
+static void rtw_pci_shutdown(struct pci_dev *pdev)
+{
+	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
+	struct rtw_dev *rtwdev;
+	struct rtw_chip_info *chip;
+
+	if (!hw)
+		return;
+
+	rtwdev = hw->priv;
+	chip = rtwdev->chip;
+
+	if (chip->ops->shutdown)
+		chip->ops->shutdown(rtwdev);
+}
+
 static const struct pci_device_id rtw_pci_id_table[] = {
 #ifdef CONFIG_RTW88_8822BE
 	{ RTK_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0xB822, rtw8822b_hw_spec) },
 #endif
 #ifdef CONFIG_RTW88_8822CE
 	{ RTK_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0xC822, rtw8822c_hw_spec) },
+	{ RTK_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0xC82F, rtw8822c_hw_spec) },
+#endif
+#ifdef CONFIG_RTW88_8723DE
+	{ RTK_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0xD723, rtw8723d_hw_spec) },
 #endif
 	{},
 };
@@ -1299,6 +1562,8 @@
 	.id_table = rtw_pci_id_table,
 	.probe = rtw_pci_probe,
 	.remove = rtw_pci_remove,
+	.driver.pm = RTW_PM_OPS,
+	.shutdown = rtw_pci_shutdown,
 };
 module_pci_driver(rtw_pci_driver);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/pci.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/pci.h
@@ -13,17 +13,33 @@
 #define RTK_BEQ_TX_DESC_NUM	256
 
 #define RTK_MAX_RX_DESC_NUM	512
-/* 8K + rx desc size */
-#define RTK_PCI_RX_BUF_SIZE	(8192 + 24)
+/* 11K + rx desc size */
+#define RTK_PCI_RX_BUF_SIZE	(11454 + 24)
 
 #define RTK_PCI_CTRL		0x300
 #define BIT_RST_TRXDMA_INTF	BIT(20)
 #define BIT_RX_TAG_EN		BIT(15)
 #define REG_DBI_WDATA_V1	0x03E8
+#define REG_DBI_RDATA_V1	0x03EC
 #define REG_DBI_FLAG_V1		0x03F0
+#define BIT_DBI_RFLAG		BIT(17)
+#define BIT_DBI_WFLAG		BIT(16)
+#define BITS_DBI_WREN		GENMASK(15, 12)
+#define BITS_DBI_ADDR_MASK	GENMASK(11, 2)
+
 #define REG_MDIO_V1		0x03F4
 #define REG_PCIE_MIX_CFG	0x03F8
+#define BITS_MDIO_ADDR_MASK	GENMASK(4, 0)
 #define BIT_MDIO_WFLAG_V1	BIT(5)
+#define RTW_PCI_MDIO_PG_SZ	BIT(5)
+#define RTW_PCI_MDIO_PG_OFFS_G1	0
+#define RTW_PCI_MDIO_PG_OFFS_G2	2
+#define RTW_PCI_WR_RETRY_CNT	20
+
+#define RTK_PCIE_LINK_CFG	0x0719
+#define BIT_CLKREQ_SW_EN	BIT(4)
+#define BIT_L1_SW_EN		BIT(3)
+#define RTK_PCIE_CLKDLY_CTRL	0x0725
 
 #define BIT_PCI_BCNQ_FLAG	BIT(4)
 #define RTK_PCI_TXBD_DESA_BCNQ	0x308
@@ -182,7 +198,9 @@
 struct rtw_pci {
 	struct pci_dev *pdev;
 
-	/* used for pci interrupt */
+	/* Used for PCI interrupt. */
+	spinlock_t hwirq_lock;
+	/* Used for PCI TX queueing. */
 	spinlock_t irq_lock;
 	u32 irq_mask[4];
 	bool irq_enabled;
@@ -190,11 +208,12 @@
 	u16 rx_tag;
 	struct rtw_pci_tx_ring tx_rings[RTK_MAX_TX_QUEUE_NUM];
 	struct rtw_pci_rx_ring rx_rings[RTK_MAX_RX_QUEUE_NUM];
+	u16 link_ctrl;
 
 	void __iomem *mmap;
 };
 
-static u32 max_num_of_tx_queue(u8 queue)
+static inline u32 max_num_of_tx_queue(u8 queue)
 {
 	u32 max_num;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/phy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/phy.c
@@ -20,15 +20,6 @@
 	struct phy_cfg_pair cfg;
 };
 
-struct phy_pg_cfg_pair {
-	u32 band;
-	u32 rf_path;
-	u32 tx_num;
-	u32 addr;
-	u32 bitmask;
-	u32 data;
-};
-
 static const u32 db_invert_table[12][8] = {
 	{10,		13,		16,		20,
 	 25,		32,		40,		50},
@@ -118,12 +109,63 @@
 
 	for (i = 0; i <= RTW_CHANNEL_WIDTH_40; i++) {
 		for (j = 0; j < RTW_RF_PATH_MAX; j++)
-			dm_info->cck_pd_lv[i][j] = 0;
+			dm_info->cck_pd_lv[i][j] = CCK_PD_LV0;
 	}
 
 	dm_info->cck_fa_avg = CCK_FA_AVG_RESET;
 }
 
+void rtw_phy_set_edcca_th(struct rtw_dev *rtwdev, u8 l2h, u8 h2l)
+{
+	struct rtw_hw_reg_offset *edcca_th = rtwdev->chip->edcca_th;
+
+	rtw_write32_mask(rtwdev,
+			 edcca_th[EDCCA_TH_L2H_IDX].hw_reg.addr,
+			 edcca_th[EDCCA_TH_L2H_IDX].hw_reg.mask,
+			 l2h + edcca_th[EDCCA_TH_L2H_IDX].offset);
+	rtw_write32_mask(rtwdev,
+			 edcca_th[EDCCA_TH_H2L_IDX].hw_reg.addr,
+			 edcca_th[EDCCA_TH_H2L_IDX].hw_reg.mask,
+			 h2l + edcca_th[EDCCA_TH_H2L_IDX].offset);
+}
+
+void rtw_phy_adaptivity_set_mode(struct rtw_dev *rtwdev)
+{
+	struct rtw_chip_info *chip = rtwdev->chip;
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+
+	/* turn off in debugfs for debug usage */
+	if (!rtw_edcca_enabled) {
+		dm_info->edcca_mode = RTW_EDCCA_NORMAL;
+		rtw_dbg(rtwdev, RTW_DBG_PHY, "disable edcca\n");
+		return;
+	}
+
+	switch (rtwdev->regd.txpwr_regd) {
+	case RTW_REGD_WW:
+	case RTW_REGD_ETSI:
+		dm_info->edcca_mode = RTW_EDCCA_ADAPTIVITY;
+		dm_info->l2h_th_ini = chip->l2h_th_ini_ad;
+		break;
+	case RTW_REGD_MKK:
+		dm_info->edcca_mode = RTW_EDCCA_ADAPTIVITY;
+		dm_info->l2h_th_ini = chip->l2h_th_ini_cs;
+		break;
+	default:
+		dm_info->edcca_mode = RTW_EDCCA_NORMAL;
+		break;
+	}
+}
+
+static void rtw_phy_adaptivity_init(struct rtw_dev *rtwdev)
+{
+	struct rtw_chip_info *chip = rtwdev->chip;
+
+	rtw_phy_adaptivity_set_mode(rtwdev);
+	if (chip->ops->adaptivity_init)
+		chip->ops->adaptivity_init(rtwdev);
+}
+
 void rtw_phy_init(struct rtw_dev *rtwdev)
 {
 	struct rtw_chip_info *chip = rtwdev->chip;
@@ -143,15 +185,21 @@
 	mask = chip->dig[0].mask;
 	dm_info->igi_history[0] = rtw_read32_mask(rtwdev, addr, mask);
 	rtw_phy_cck_pd_init(rtwdev);
+	rtw_phy_adaptivity_init(rtwdev);
+	dm_info->iqk.done = false;
 }
 
 void rtw_phy_dig_write(struct rtw_dev *rtwdev, u8 igi)
 {
 	struct rtw_chip_info *chip = rtwdev->chip;
 	struct rtw_hal *hal = &rtwdev->hal;
+	struct rtw_hw_reg *dig_cck = &chip->dig_cck[0];
 	u32 addr, mask;
 	u8 path;
 
+	if (dig_cck)
+		rtw_write32_mask(rtwdev, dig_cck->addr, dig_cck->mask, igi >> 1);
+
 	for (path = 0; path < hal->rf_path_num; path++) {
 		addr = chip->dig[path].addr;
 		mask = chip->dig[path].mask;
@@ -222,10 +270,19 @@
 	dm_info->min_rssi = data.min_rssi;
 }
 
+static void rtw_phy_stat_rate_cnt(struct rtw_dev *rtwdev)
+{
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+
+	dm_info->last_pkt_count = dm_info->cur_pkt_count;
+	memset(&dm_info->cur_pkt_count, 0, sizeof(dm_info->cur_pkt_count));
+}
+
 static void rtw_phy_statistics(struct rtw_dev *rtwdev)
 {
 	rtw_phy_stat_rssi(rtwdev);
 	rtw_phy_stat_false_alarm(rtwdev);
+	rtw_phy_stat_rate_cnt(rtwdev);
 }
 
 #define DIG_PERF_FA_TH_LOW			250
@@ -394,7 +451,7 @@
 	u8 step[3];
 	bool linked;
 
-	if (rtw_flag_check(rtwdev, RTW_FLAG_DIG_DISABLE))
+	if (test_bit(RTW_FLAG_DIG_DISABLE, rtwdev->flags))
 		return;
 
 	if (rtw_phy_dig_check_damping(dm_info))
@@ -461,7 +518,6 @@
 		chip->ops->dpk_track(rtwdev);
 }
 
-#define CCK_PD_LV_MAX		5
 #define CCK_PD_FA_LV1_MIN	1000
 #define CCK_PD_FA_LV0_MAX	500
 
@@ -471,10 +527,10 @@
 	u32 cck_fa_avg = dm_info->cck_fa_avg;
 
 	if (cck_fa_avg > CCK_PD_FA_LV1_MIN)
-		return 1;
+		return CCK_PD_LV1;
 
 	if (cck_fa_avg < CCK_PD_FA_LV0_MAX)
-		return 0;
+		return CCK_PD_LV0;
 
 	return CCK_PD_LV_MAX;
 }
@@ -494,15 +550,15 @@
 	u32 cck_fa_avg = dm_info->cck_fa_avg;
 
 	if (igi > CCK_PD_IGI_LV4_VAL && rssi > CCK_PD_RSSI_LV4_VAL)
-		return 4;
+		return CCK_PD_LV4;
 	if (igi > CCK_PD_IGI_LV3_VAL && rssi > CCK_PD_RSSI_LV3_VAL)
-		return 3;
+		return CCK_PD_LV3;
 	if (igi > CCK_PD_IGI_LV2_VAL || rssi > CCK_PD_RSSI_LV2_VAL)
-		return 2;
+		return CCK_PD_LV2;
 	if (cck_fa_avg > CCK_PD_FA_LV1_MIN)
-		return 1;
+		return CCK_PD_LV1;
 	if (cck_fa_avg < CCK_PD_FA_LV0_MAX)
-		return 0;
+		return CCK_PD_LV0;
 
 	return CCK_PD_LV_MAX;
 }
@@ -539,6 +595,17 @@
 		chip->ops->cck_pd_set(rtwdev, level);
 }
 
+static void rtw_phy_pwr_track(struct rtw_dev *rtwdev)
+{
+	rtwdev->chip->ops->pwr_track(rtwdev);
+}
+
+static void rtw_phy_adaptivity(struct rtw_dev *rtwdev)
+{
+	if (rtwdev->chip->ops->adaptivity)
+		rtwdev->chip->ops->adaptivity(rtwdev);
+}
+
 void rtw_phy_dynamic_mechanism(struct rtw_dev *rtwdev)
 {
 	/* for further calculation */
@@ -547,6 +614,8 @@
 	rtw_phy_cck_pd(rtwdev);
 	rtw_phy_ra_info_update(rtwdev);
 	rtw_phy_dpk_track(rtwdev);
+	rtw_phy_pwr_track(rtwdev);
+	rtw_phy_adaptivity(rtwdev);
 }
 
 #define FRAC_BITS 3
@@ -674,7 +743,7 @@
 	const u32 *base_addr = chip->rf_base_addr;
 	u32 val, direct_addr;
 
-	if (rf_path >= hal->rf_path_num) {
+	if (rf_path >= hal->rf_phy_num) {
 		rtw_err(rtwdev, "unsupported rf path (%d)\n", rf_path);
 		return INV_RF_DATA;
 	}
@@ -688,6 +757,54 @@
 	return val;
 }
 
+u32 rtw_phy_read_rf_sipi(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
+			 u32 addr, u32 mask)
+{
+	struct rtw_hal *hal = &rtwdev->hal;
+	struct rtw_chip_info *chip = rtwdev->chip;
+	struct rtw_rf_sipi_addr *rf_sipi_addr;
+	struct rtw_rf_sipi_addr *rf_sipi_addr_a;
+	u32 val32;
+	u32 en_pi;
+	u32 r_addr;
+	u32 shift;
+
+	if (rf_path >= hal->rf_phy_num) {
+		rtw_err(rtwdev, "unsupported rf path (%d)\n", rf_path);
+		return INV_RF_DATA;
+	}
+
+	if (!chip->rf_sipi_read_addr) {
+		rtw_err(rtwdev, "rf_sipi_read_addr isn't defined\n");
+		return INV_RF_DATA;
+	}
+
+	rf_sipi_addr = &chip->rf_sipi_read_addr[rf_path];
+	rf_sipi_addr_a = &chip->rf_sipi_read_addr[RF_PATH_A];
+
+	addr &= 0xff;
+
+	val32 = rtw_read32(rtwdev, rf_sipi_addr->hssi_2);
+	val32 = (val32 & ~LSSI_READ_ADDR_MASK) | (addr << 23);
+	rtw_write32(rtwdev, rf_sipi_addr->hssi_2, val32);
+
+	/* toggle read edge of path A */
+	val32 = rtw_read32(rtwdev, rf_sipi_addr_a->hssi_2);
+	rtw_write32(rtwdev, rf_sipi_addr_a->hssi_2, val32 & ~LSSI_READ_EDGE_MASK);
+	rtw_write32(rtwdev, rf_sipi_addr_a->hssi_2, val32 | LSSI_READ_EDGE_MASK);
+
+	udelay(120);
+
+	en_pi = rtw_read32_mask(rtwdev, rf_sipi_addr->hssi_1, BIT(8));
+	r_addr = en_pi ? rf_sipi_addr->lssi_read_pi : rf_sipi_addr->lssi_read;
+
+	val32 = rtw_read32_mask(rtwdev, r_addr, LSSI_READ_DATA_MASK);
+
+	shift = __ffs(mask);
+
+	return (val32 & mask) >> shift;
+}
+
 bool rtw_phy_write_rf_reg_sipi(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
 			       u32 addr, u32 mask, u32 data)
 {
@@ -698,7 +815,7 @@
 	u32 old_data = 0;
 	u32 shift;
 
-	if (rf_path >= hal->rf_path_num) {
+	if (rf_path >= hal->rf_phy_num) {
 		rtw_err(rtwdev, "unsupported rf path (%d)\n", rf_path);
 		return false;
 	}
@@ -707,7 +824,7 @@
 	mask &= RFREG_MASK;
 
 	if (mask != RFREG_MASK) {
-		old_data = rtw_phy_read_rf(rtwdev, rf_path, addr, RFREG_MASK);
+		old_data = chip->ops->read_rf(rtwdev, rf_path, addr, RFREG_MASK);
 
 		if (old_data == INV_RF_DATA) {
 			rtw_err(rtwdev, "Write fail, rf is disabled\n");
@@ -735,7 +852,7 @@
 	const u32 *base_addr = chip->rf_base_addr;
 	u32 direct_addr;
 
-	if (rf_path >= hal->rf_path_num) {
+	if (rf_path >= hal->rf_phy_num) {
 		rtw_err(rtwdev, "unsupported rf path (%d)\n", rf_path);
 		return false;
 	}
@@ -744,20 +861,10 @@
 	direct_addr = base_addr[rf_path] + (addr << 2);
 	mask &= RFREG_MASK;
 
-	if (addr == RF_CFGCH) {
-		rtw_write32_mask(rtwdev, REG_RSV_CTRL, BITS_RFC_DIRECT, DISABLE_PI);
-		rtw_write32_mask(rtwdev, REG_WLRF1, BITS_RFC_DIRECT, DISABLE_PI);
-	}
-
 	rtw_write32_mask(rtwdev, direct_addr, mask, data);
 
 	udelay(1);
 
-	if (addr == RF_CFGCH) {
-		rtw_write32_mask(rtwdev, REG_RSV_CTRL, BITS_RFC_DIRECT, ENABLE_PI);
-		rtw_write32_mask(rtwdev, REG_WLRF1, BITS_RFC_DIRECT, ENABLE_PI);
-	}
-
 	return true;
 }
 
@@ -1211,10 +1318,8 @@
 
 void rtw_parse_tbl_bb_pg(struct rtw_dev *rtwdev, const struct rtw_table *tbl)
 {
-	const struct phy_pg_cfg_pair *p = tbl->data;
-	const struct phy_pg_cfg_pair *end = p + tbl->size / 6;
-
-	BUILD_BUG_ON(sizeof(struct phy_pg_cfg_pair) != sizeof(u32) * 6);
+	const struct rtw_phy_pg_cfg_pair *p = tbl->data;
+	const struct rtw_phy_pg_cfg_pair *end = p + tbl->size;
 
 	for (; p < end; p++) {
 		if (p->addr == 0xfe || p->addr == 0xffe) {
@@ -1292,6 +1397,94 @@
 	}
 }
 
+static void
+rtw_phy_set_tx_power_sar_by_chidx(struct rtw_dev *rtwdev, u8 regd, u8 rfpath,
+				  u8 band, u8 rs, u8 ch_idx, s8 sar)
+{
+	struct rtw_hal *hal = &rtwdev->hal;
+	s8 base;
+	s8 ww_sar;
+	s8 s;
+
+	if (band == PHY_BAND_2G) {
+		base = hal->tx_pwr_by_rate_base_2g[rfpath][rs];
+		s = sar - base;
+		hal->tx_pwr_sar_2g[regd][rfpath][rs][ch_idx] = s;
+		if (regd == RTW_REGD_WW)
+			return;
+		ww_sar = hal->tx_pwr_sar_2g[RTW_REGD_WW][rfpath][rs][ch_idx];
+		ww_sar = min(ww_sar, s);
+		hal->tx_pwr_sar_2g[RTW_REGD_WW][rfpath][rs][ch_idx] = ww_sar;
+	} else {
+		base = hal->tx_pwr_by_rate_base_5g[rfpath][rs];
+		s = sar - base;
+		hal->tx_pwr_sar_5g[regd][rfpath][rs][ch_idx] = s;
+		if (regd == RTW_REGD_WW)
+			return;
+		ww_sar = hal->tx_pwr_sar_5g[RTW_REGD_WW][rfpath][rs][ch_idx];
+		ww_sar = min(ww_sar, s);
+		hal->tx_pwr_sar_5g[RTW_REGD_WW][rfpath][rs][ch_idx] = ww_sar;
+	}
+}
+
+static void
+rtw_phy_set_tx_power_sar_by_range(struct rtw_dev *rtwdev, u8 regd, u8 rfpath,
+				  u8 band, u8 chidx_start, u8 chidx_end, u8 sar_q3)
+{
+	u8 rs;
+	u8 ch_idx;
+	s8 sar;
+
+	if (regd >= RTW_REGD_MAX || rfpath >= RTW_RF_PATH_MAX)
+		return;
+
+	sar = sar_q3 >> (3 - (int)rtwdev->chip->txgi_factor);
+
+	for (ch_idx = chidx_start; ch_idx <= chidx_end; ch_idx++)
+		for (rs = 0; rs < RTW_RATE_SECTION_MAX; rs++)
+			rtw_phy_set_tx_power_sar_by_chidx(rtwdev, regd, rfpath,
+							  band, rs, ch_idx, sar);
+}
+
+void rtw_phy_set_tx_power_sar(struct rtw_dev *rtwdev, u8 regd, u8 rfpath,
+			      u8 ch_start, u8 ch_end, u8 sar_q3)
+{
+	u8 band_start, band_end;
+	int chidx_start, chidx_end;
+
+	band_start = ch_start <= 14 ? PHY_BAND_2G : PHY_BAND_5G;
+	band_end = ch_end <= 14 ? PHY_BAND_2G : PHY_BAND_5G;
+
+	if (band_start == band_end) {
+		chidx_start = rtw_channel_to_idx(band_start, ch_start);
+		chidx_end = rtw_channel_to_idx(band_start, ch_end);
+		if (chidx_start < 0 || chidx_end < 0)
+			goto err;
+		rtw_phy_set_tx_power_sar_by_range(rtwdev, regd, rfpath, band_start,
+						  chidx_start, chidx_end, sar_q3);
+		return;
+	}
+
+	chidx_start = rtw_channel_to_idx(PHY_BAND_2G, ch_start);
+	if (chidx_start < 0)
+		goto err;
+	rtw_phy_set_tx_power_sar_by_range(rtwdev, regd, rfpath, PHY_BAND_2G,
+					  chidx_start, RTW_MAX_CHANNEL_NUM_2G - 1,
+					  sar_q3);
+
+	chidx_end = rtw_channel_to_idx(PHY_BAND_5G, ch_end);
+	if (chidx_end < 0)
+		goto err;
+	rtw_phy_set_tx_power_sar_by_range(rtwdev, regd, rfpath, PHY_BAND_5G,
+					  0, chidx_end, sar_q3);
+
+	return;
+
+err:
+	rtw_warn(rtwdev, "SAR: invalid channel (start/end)=(%d/%d)\n",
+		 ch_start, ch_end);
+}
+
 /* cross-reference 5G power limits if values are not assigned */
 static void
 rtw_xref_5g_txpwr_lmt(struct rtw_dev *rtwdev, u8 regd,
@@ -1431,7 +1624,7 @@
 
 	rtw_load_table(rtwdev, chip->rfk_init_tbl);
 
-	dpk_info->is_dpk_pwr_on = 1;
+	dpk_info->is_dpk_pwr_on = true;
 }
 
 void rtw_phy_load_tables(struct rtw_dev *rtwdev)
@@ -1452,7 +1645,7 @@
 	}
 }
 
-static u8 rtw_get_channel_group(u8 channel)
+static u8 rtw_get_channel_group(u8 channel, u8 rate)
 {
 	switch (channel) {
 	default:
@@ -1496,6 +1689,7 @@
 	case 106:
 		return 4;
 	case 14:
+		return rate <= DESC_RATE11M ? 5 : 4;
 	case 108:
 	case 110:
 	case 112:
@@ -1673,9 +1867,10 @@
 	return tx_power;
 }
 
-static s8 rtw_phy_get_tx_power_limit(struct rtw_dev *rtwdev, u8 band,
-				     enum rtw_bandwidth bw, u8 rf_path,
-				     u8 rate, u8 channel, u8 regd)
+static void rtw_phy_get_tx_power_limit(struct rtw_dev *rtwdev, u8 band,
+				       enum rtw_bandwidth bw, u8 rf_path,
+				       u8 rate, u8 channel, u8 regd,
+				       struct rtw_power_params *pwr_param)
 {
 	struct rtw_hal *hal = &rtwdev->hal;
 	u8 *cch_by_bw = hal->cch_by_bw;
@@ -1684,9 +1879,10 @@
 	int ch_idx;
 	u8 cur_bw, cur_ch;
 	s8 cur_lmt;
+	s8 sar, sar_ww;
 
 	if (regd > RTW_REGD_WW)
-		return power_limit;
+		goto err;
 
 	if (rate >= DESC_RATE1M && rate <= DESC_RATE11M)
 		rs = RTW_RATE_SECTION_CCK;
@@ -1726,44 +1922,71 @@
 		power_limit = min_t(s8, cur_lmt, power_limit);
 	}
 
-	return power_limit;
+	ch_idx = rtw_channel_to_idx(band, channel);
+	if (ch_idx < 0)
+		goto err;
+
+	if (band == PHY_BAND_2G) {
+		sar = hal->tx_pwr_sar_2g[regd][rf_path][rs][ch_idx];
+		sar_ww = hal->tx_pwr_sar_2g[RTW_REGD_WW][rf_path][rs][ch_idx];
+	} else {
+		sar = hal->tx_pwr_sar_5g[regd][rf_path][rs][ch_idx];
+		sar_ww = hal->tx_pwr_sar_5g[RTW_REGD_WW][rf_path][rs][ch_idx];
+	}
+	if (sar >= rtwdev->chip->max_power_index)
+		sar = sar_ww;
+
+	pwr_param->pwr_sar = sar;
+	pwr_param->pwr_limit = power_limit;
+	return;
 
 err:
 	WARN(1, "invalid arguments, band=%d, bw=%d, path=%d, rate=%d, ch=%d\n",
 	     band, bw, rf_path, rate, channel);
-	return (s8)rtwdev->chip->max_power_index;
+	pwr_param->pwr_sar = (s8)rtwdev->chip->max_power_index;
+	pwr_param->pwr_limit = (s8)rtwdev->chip->max_power_index;
 }
 
-void rtw_get_tx_power_params(struct rtw_dev *rtwdev, u8 path, u8 rate, u8 bw,
-			     u8 ch, u8 regd, struct rtw_power_params *pwr_param)
+static void rtw_phy_get_tx_power_base(struct rtw_dev *rtwdev, u8 band,
+				      enum rtw_bandwidth bw, u8 path, u8 rate,
+				      u8 ch, struct rtw_power_params *pwr_param)
 {
 	struct rtw_hal *hal = &rtwdev->hal;
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
 	struct rtw_txpwr_idx *pwr_idx;
-	u8 group, band;
-	u8 *base = &pwr_param->pwr_base;
-	s8 *offset = &pwr_param->pwr_offset;
-	s8 *limit = &pwr_param->pwr_limit;
+	u8 group;
+	u8 base;
+	s8 offset;
 
 	pwr_idx = &rtwdev->efuse.txpwr_idx_table[path];
-	group = rtw_get_channel_group(ch);
+	group = rtw_get_channel_group(ch, rate);
 
 	/* base power index for 2.4G/5G */
-	if (ch <= 14) {
-		band = PHY_BAND_2G;
-		*base = rtw_phy_get_2g_tx_power_index(rtwdev,
-						      &pwr_idx->pwr_idx_2g,
-						      bw, rate, group);
-		*offset = hal->tx_pwr_by_rate_offset_2g[path][rate];
+	if (band == PHY_BAND_2G) {
+		base = rtw_phy_get_2g_tx_power_index(rtwdev,
+						     &pwr_idx->pwr_idx_2g,
+						     bw, rate, group);
+		offset = hal->tx_pwr_by_rate_offset_2g[path][rate];
 	} else {
-		band = PHY_BAND_5G;
-		*base = rtw_phy_get_5g_tx_power_index(rtwdev,
-						      &pwr_idx->pwr_idx_5g,
-						      bw, rate, group);
-		*offset = hal->tx_pwr_by_rate_offset_5g[path][rate];
+		base = rtw_phy_get_5g_tx_power_index(rtwdev,
+						     &pwr_idx->pwr_idx_5g,
+						     bw, rate, group);
+		offset = hal->tx_pwr_by_rate_offset_5g[path][rate];
 	}
 
-	*limit = rtw_phy_get_tx_power_limit(rtwdev, band, bw, path,
-					    rate, ch, regd);
+	pwr_param->pwr_base = base;
+	pwr_param->pwr_offset = offset;
+	pwr_param->pwr_remnant = (rate <= DESC_RATE11M ? dm_info->txagc_remnant_cck :
+				  dm_info->txagc_remnant_ofdm);
+}
+
+void rtw_get_tx_power_params(struct rtw_dev *rtwdev, u8 path, u8 rate, u8 bw,
+			     u8 ch, u8 regd, struct rtw_power_params *pwr_param)
+{
+	u8 band = IS_CH_2G_BAND(ch) ? PHY_BAND_2G : PHY_BAND_5G;
+
+	rtw_phy_get_tx_power_base(rtwdev, band, bw, path, rate, ch, pwr_param);
+	rtw_phy_get_tx_power_limit(rtwdev, band, bw, path, rate, ch, regd, pwr_param);
 }
 
 u8
@@ -1778,12 +2001,13 @@
 				channel, regd, &pwr_param);
 
 	tx_power = pwr_param.pwr_base;
-	offset = min_t(s8, pwr_param.pwr_offset, pwr_param.pwr_limit);
+	offset = min3(pwr_param.pwr_offset, pwr_param.pwr_limit,
+		      pwr_param.pwr_sar);
 
 	if (rtwdev->chip->en_dis_dpd)
 		offset += rtw_phy_get_dis_dpd_by_rate_diff(rtwdev, rate);
 
-	tx_power += offset;
+	tx_power += offset + pwr_param.pwr_remnant;
 
 	if (tx_power > rtwdev->chip->max_power_index)
 		tx_power = rtwdev->chip->max_power_index;
@@ -1967,4 +2191,130 @@
 			for (rs = 0; rs < RTW_RATE_SECTION_MAX; rs++)
 				rtw_phy_init_tx_power_limit(rtwdev, regd, bw,
 							    rs);
+
+	/* init tx power sar */
+	memset(hal->tx_pwr_sar_2g, rtwdev->chip->max_power_index,
+	       sizeof(hal->tx_pwr_sar_2g));
+	memset(hal->tx_pwr_sar_5g, rtwdev->chip->max_power_index,
+	       sizeof(hal->tx_pwr_sar_5g));
+}
+
+void rtw_phy_config_swing_table(struct rtw_dev *rtwdev,
+				struct rtw_swing_table *swing_table)
+{
+	const struct rtw_pwr_track_tbl *tbl = rtwdev->chip->pwr_track_tbl;
+	u8 channel = rtwdev->hal.current_channel;
+
+	if (IS_CH_2G_BAND(channel)) {
+		if (rtwdev->dm_info.tx_rate <= DESC_RATE11M) {
+			swing_table->p[RF_PATH_A] = tbl->pwrtrk_2g_ccka_p;
+			swing_table->n[RF_PATH_A] = tbl->pwrtrk_2g_ccka_n;
+			swing_table->p[RF_PATH_B] = tbl->pwrtrk_2g_cckb_p;
+			swing_table->n[RF_PATH_B] = tbl->pwrtrk_2g_cckb_n;
+		} else {
+			swing_table->p[RF_PATH_A] = tbl->pwrtrk_2ga_p;
+			swing_table->n[RF_PATH_A] = tbl->pwrtrk_2ga_n;
+			swing_table->p[RF_PATH_B] = tbl->pwrtrk_2gb_p;
+			swing_table->n[RF_PATH_B] = tbl->pwrtrk_2gb_n;
+		}
+	} else if (IS_CH_5G_BAND_1(channel) || IS_CH_5G_BAND_2(channel)) {
+		swing_table->p[RF_PATH_A] = tbl->pwrtrk_5ga_p[RTW_PWR_TRK_5G_1];
+		swing_table->n[RF_PATH_A] = tbl->pwrtrk_5ga_n[RTW_PWR_TRK_5G_1];
+		swing_table->p[RF_PATH_B] = tbl->pwrtrk_5gb_p[RTW_PWR_TRK_5G_1];
+		swing_table->n[RF_PATH_B] = tbl->pwrtrk_5gb_n[RTW_PWR_TRK_5G_1];
+	} else if (IS_CH_5G_BAND_3(channel)) {
+		swing_table->p[RF_PATH_A] = tbl->pwrtrk_5ga_p[RTW_PWR_TRK_5G_2];
+		swing_table->n[RF_PATH_A] = tbl->pwrtrk_5ga_n[RTW_PWR_TRK_5G_2];
+		swing_table->p[RF_PATH_B] = tbl->pwrtrk_5gb_p[RTW_PWR_TRK_5G_2];
+		swing_table->n[RF_PATH_B] = tbl->pwrtrk_5gb_n[RTW_PWR_TRK_5G_2];
+	} else if (IS_CH_5G_BAND_4(channel)) {
+		swing_table->p[RF_PATH_A] = tbl->pwrtrk_5ga_p[RTW_PWR_TRK_5G_3];
+		swing_table->n[RF_PATH_A] = tbl->pwrtrk_5ga_n[RTW_PWR_TRK_5G_3];
+		swing_table->p[RF_PATH_B] = tbl->pwrtrk_5gb_p[RTW_PWR_TRK_5G_3];
+		swing_table->n[RF_PATH_B] = tbl->pwrtrk_5gb_n[RTW_PWR_TRK_5G_3];
+	} else {
+		swing_table->p[RF_PATH_A] = tbl->pwrtrk_2ga_p;
+		swing_table->n[RF_PATH_A] = tbl->pwrtrk_2ga_n;
+		swing_table->p[RF_PATH_B] = tbl->pwrtrk_2gb_p;
+		swing_table->n[RF_PATH_B] = tbl->pwrtrk_2gb_n;
+	}
+}
+
+void rtw_phy_pwrtrack_avg(struct rtw_dev *rtwdev, u8 thermal, u8 path)
+{
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+
+	ewma_thermal_add(&dm_info->avg_thermal[path], thermal);
+	dm_info->thermal_avg[path] =
+		ewma_thermal_read(&dm_info->avg_thermal[path]);
+}
+
+bool rtw_phy_pwrtrack_thermal_changed(struct rtw_dev *rtwdev, u8 thermal,
+				      u8 path)
+{
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+	u8 avg = ewma_thermal_read(&dm_info->avg_thermal[path]);
+
+	if (avg == thermal)
+		return false;
+
+	return true;
+}
+
+u8 rtw_phy_pwrtrack_get_delta(struct rtw_dev *rtwdev, u8 path)
+{
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+	u8 therm_avg, therm_efuse, therm_delta;
+
+	therm_avg = dm_info->thermal_avg[path];
+	therm_efuse = rtwdev->efuse.thermal_meter[path];
+	therm_delta = abs(therm_avg - therm_efuse);
+
+	return min_t(u8, therm_delta, RTW_PWR_TRK_TBL_SZ - 1);
+}
+
+s8 rtw_phy_pwrtrack_get_pwridx(struct rtw_dev *rtwdev,
+			       struct rtw_swing_table *swing_table,
+			       u8 tbl_path, u8 therm_path, u8 delta)
+{
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+	const u8 *delta_swing_table_idx_pos;
+	const u8 *delta_swing_table_idx_neg;
+
+	if (delta >= RTW_PWR_TRK_TBL_SZ) {
+		rtw_warn(rtwdev, "power track table overflow\n");
+		return 0;
+	}
+
+	if (!swing_table) {
+		rtw_warn(rtwdev, "swing table not configured\n");
+		return 0;
+	}
+
+	delta_swing_table_idx_pos = swing_table->p[tbl_path];
+	delta_swing_table_idx_neg = swing_table->n[tbl_path];
+
+	if (!delta_swing_table_idx_pos || !delta_swing_table_idx_neg) {
+		rtw_warn(rtwdev, "invalid swing table index\n");
+		return 0;
+	}
+
+	if (dm_info->thermal_avg[therm_path] >
+	    rtwdev->efuse.thermal_meter[therm_path])
+		return delta_swing_table_idx_pos[delta];
+	else
+		return -delta_swing_table_idx_neg[delta];
+}
+
+bool rtw_phy_pwrtrack_need_iqk(struct rtw_dev *rtwdev)
+{
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+	u8 delta_iqk;
+
+	delta_iqk = abs(dm_info->thermal_avg[0] - dm_info->thermal_meter_k);
+	if (delta_iqk >= rtwdev->chip->iqk_threshold) {
+		dm_info->thermal_meter_k = dm_info->thermal_avg[0];
+		return true;
+	}
+	return false;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/phy.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/phy.h
@@ -21,6 +21,8 @@
 u8 rtw_phy_rf_power_2_rssi(s8 *rf_power, u8 path_num);
 u32 rtw_phy_read_rf(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
 		    u32 addr, u32 mask);
+u32 rtw_phy_read_rf_sipi(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
+			 u32 addr, u32 mask);
 bool rtw_phy_write_rf_reg_sipi(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
 			       u32 addr, u32 mask, u32 data);
 bool rtw_phy_write_rf_reg(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
@@ -41,9 +43,23 @@
 		    u32 addr, u32 data);
 void rtw_phy_init_tx_power(struct rtw_dev *rtwdev);
 void rtw_phy_load_tables(struct rtw_dev *rtwdev);
+u8 rtw_phy_get_tx_power_index(struct rtw_dev *rtwdev, u8 rf_path, u8 rate,
+			      enum rtw_bandwidth bw, u8 channel, u8 regd);
 void rtw_phy_set_tx_power_level(struct rtw_dev *rtwdev, u8 channel);
 void rtw_phy_tx_power_by_rate_config(struct rtw_hal *hal);
 void rtw_phy_tx_power_limit_config(struct rtw_hal *hal);
+void rtw_phy_pwrtrack_avg(struct rtw_dev *rtwdev, u8 thermal, u8 path);
+bool rtw_phy_pwrtrack_thermal_changed(struct rtw_dev *rtwdev, u8 thermal,
+				      u8 path);
+u8 rtw_phy_pwrtrack_get_delta(struct rtw_dev *rtwdev, u8 path);
+s8 rtw_phy_pwrtrack_get_pwridx(struct rtw_dev *rtwdev,
+			       struct rtw_swing_table *swing_table,
+			       u8 tbl_path, u8 therm_path, u8 delta);
+bool rtw_phy_pwrtrack_need_iqk(struct rtw_dev *rtwdev);
+void rtw_phy_config_swing_table(struct rtw_dev *rtwdev,
+				struct rtw_swing_table *swing_table);
+void rtw_phy_set_edcca_th(struct rtw_dev *rtwdev, u8 l2h, u8 h2l);
+void rtw_phy_adaptivity_set_mode(struct rtw_dev *rtwdev);
 
 struct rtw_txpwr_lmt_cfg_pair {
 	u8 regd;
@@ -54,6 +70,15 @@
 	s8 txpwr_lmt;
 };
 
+struct rtw_phy_pg_cfg_pair {
+	u32 band;
+	u32 rf_path;
+	u32 tx_num;
+	u32 addr;
+	u32 bitmask;
+	u32 data;
+};
+
 #define RTW_DECL_TABLE_PHY_COND_CORE(name, cfg, path)	\
 const struct rtw_table name ## _tbl = {			\
 	.data = name,					\
@@ -118,12 +143,25 @@
 	u8 pwr_base;
 	s8 pwr_offset;
 	s8 pwr_limit;
+	s8 pwr_sar;
+	s8 pwr_remnant;
 };
 
 void
 rtw_get_tx_power_params(struct rtw_dev *rtwdev, u8 path,
 			u8 rate, u8 bw, u8 ch, u8 regd,
 			struct rtw_power_params *pwr_param);
+void rtw_phy_set_tx_power_sar(struct rtw_dev *rtwdev, u8 regd, u8 rfpath,
+			      u8 ch_start, u8 ch_end, u8 sar_q3);
+
+enum rtw_phy_cck_pd_lv {
+	CCK_PD_LV0,
+	CCK_PD_LV1,
+	CCK_PD_LV2,
+	CCK_PD_LV3,
+	CCK_PD_LV4,
+	CCK_PD_LV_MAX,
+};
 
 #define	MASKBYTE0		0xff
 #define	MASKBYTE1		0xff00
@@ -148,4 +186,8 @@
 
 #define CCK_FA_AVG_RESET 0xffffffff
 
+#define LSSI_READ_ADDR_MASK	0x7f800000
+#define LSSI_READ_EDGE_MASK	0x80000000
+#define LSSI_READ_DATA_MASK	0xfffff
+
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/ps.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/ps.c
@@ -3,6 +3,7 @@
  */
 
 #include "main.h"
+#include "reg.h"
 #include "fw.h"
 #include "ps.h"
 #include "mac.h"
@@ -18,18 +19,19 @@
 		rtw_err(rtwdev, "leave idle state failed\n");
 
 	rtw_set_channel(rtwdev);
-	rtw_flag_clear(rtwdev, RTW_FLAG_INACTIVE_PS);
+	clear_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags);
 
 	return ret;
 }
 
 int rtw_enter_ips(struct rtw_dev *rtwdev)
 {
-	rtw_flag_set(rtwdev, RTW_FLAG_INACTIVE_PS);
+	set_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags);
 
 	rtw_coex_ips_notify(rtwdev, COEX_IPS_ENTER);
 
 	rtw_core_stop(rtwdev);
+	rtw_hci_link_ps(rtwdev, true);
 
 	return 0;
 }
@@ -48,6 +50,8 @@
 {
 	int ret;
 
+	rtw_hci_link_ps(rtwdev, false);
+
 	ret = rtw_ips_pwr_up(rtwdev);
 	if (ret) {
 		rtw_err(rtwdev, "failed to leave ips state\n");
@@ -61,6 +65,85 @@
 	return 0;
 }
 
+void rtw_power_mode_change(struct rtw_dev *rtwdev, bool enter)
+{
+	u8 request, confirm, polling;
+	u8 polling_cnt;
+	u8 retry_cnt = 0;
+
+	for (retry_cnt = 0; retry_cnt < 3; retry_cnt++) {
+		request = rtw_read8(rtwdev, rtwdev->hci.rpwm_addr);
+		confirm = rtw_read8(rtwdev, rtwdev->hci.cpwm_addr);
+
+		/* toggle to request power mode, others remain 0 */
+		request ^= request | BIT_RPWM_TOGGLE;
+		if (!enter) {
+			request |= POWER_MODE_ACK;
+		} else {
+			request |= POWER_MODE_LCLK;
+			if (rtw_fw_lps_deep_mode == LPS_DEEP_MODE_PG)
+				request |= POWER_MODE_PG;
+		}
+
+		rtw_write8(rtwdev, rtwdev->hci.rpwm_addr, request);
+
+		if (enter)
+			return;
+
+		/* check confirm power mode has left power save state */
+		for (polling_cnt = 0; polling_cnt < 50; polling_cnt++) {
+			polling = rtw_read8(rtwdev, rtwdev->hci.cpwm_addr);
+			if ((polling ^ confirm) & BIT_RPWM_TOGGLE)
+				return;
+			udelay(100);
+		}
+
+		/* in case of fw/hw missed the request, retry */
+		rtw_warn(rtwdev, "failed to leave deep PS, retry=%d\n",
+			 retry_cnt);
+	}
+
+	/* Hit here means that driver failed to change hardware power mode to
+	 * active state after retry 3 times. If the power state is locked at
+	 * Deep sleep, most of the hardware circuits is not working, even
+	 * register read/write. It should be treated as fatal error and
+	 * requires an entire analysis about the firmware/hardware
+	 */
+	WARN(1, "Hardware power state locked\n");
+}
+EXPORT_SYMBOL(rtw_power_mode_change);
+
+static void __rtw_leave_lps_deep(struct rtw_dev *rtwdev)
+{
+	rtw_hci_deep_ps(rtwdev, false);
+}
+
+static void rtw_fw_leave_lps_state_check(struct rtw_dev *rtwdev)
+{
+	int i;
+
+	/* Driver needs to wait for firmware to leave LPS state
+	 * successfully. Firmware will send null packet to inform AP,
+	 * and see if AP sends an ACK back, then firmware will restore
+	 * the REG_TCR register.
+	 *
+	 * If driver does not wait for firmware, null packet with
+	 * PS bit could be sent due to incorrect REG_TCR setting.
+	 *
+	 * In our test, 100ms should be enough for firmware to finish
+	 * the flow. If REG_TCR Register is still incorrect after 100ms,
+	 * just modify it directly, and throw a warn message.
+	 */
+	for (i = 0 ; i < LEAVE_LPS_TRY_CNT; i++) {
+		if (rtw_read32_mask(rtwdev, REG_TCR, BIT_PWRMGT_HWDATA_EN) == 0)
+			return;
+		msleep(20);
+	}
+
+	rtw_write32_mask(rtwdev, REG_TCR, BIT_PWRMGT_HWDATA_EN, 0);
+	rtw_warn(rtwdev, "firmware failed to restore hardware setting\n");
+}
+
 static void rtw_leave_lps_core(struct rtw_dev *rtwdev)
 {
 	struct rtw_lps_conf *conf = &rtwdev->lps_conf;
@@ -70,12 +153,32 @@
 	conf->rlbm = 0;
 	conf->smart_ps = 0;
 
+	rtw_hci_link_ps(rtwdev, false);
 	rtw_fw_set_pwr_mode(rtwdev);
-	rtw_flag_clear(rtwdev, RTW_FLAG_LEISURE_PS);
+	rtw_fw_leave_lps_state_check(rtwdev);
+
+	clear_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags);
 
 	rtw_coex_lps_notify(rtwdev, COEX_LPS_DISABLE);
 }
 
+static void __rtw_enter_lps_deep(struct rtw_dev *rtwdev)
+{
+	if (rtwdev->lps_conf.deep_mode == LPS_DEEP_MODE_NONE)
+		return;
+
+	if (!test_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags)) {
+		rtw_dbg(rtwdev, RTW_DBG_PS,
+			"Should enter LPS before entering deep PS\n");
+		return;
+	}
+
+	if (rtw_fw_lps_deep_mode == LPS_DEEP_MODE_PG)
+		rtw_fw_set_pg_info(rtwdev);
+
+	rtw_hci_deep_ps(rtwdev, true);
+}
+
 static void rtw_enter_lps_core(struct rtw_dev *rtwdev)
 {
 	struct rtw_lps_conf *conf = &rtwdev->lps_conf;
@@ -88,88 +191,64 @@
 	rtw_coex_lps_notify(rtwdev, COEX_LPS_ENABLE);
 
 	rtw_fw_set_pwr_mode(rtwdev);
-	rtw_flag_set(rtwdev, RTW_FLAG_LEISURE_PS);
-}
+	rtw_hci_link_ps(rtwdev, true);
 
-void rtw_lps_work(struct work_struct *work)
-{
-	struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
-					      lps_work.work);
-	struct rtw_lps_conf *conf = &rtwdev->lps_conf;
-	struct rtw_vif *rtwvif = conf->rtwvif;
-
-	if (WARN_ON(!rtwvif))
-		return;
-
-	if (conf->mode == RTW_MODE_LPS)
-		rtw_enter_lps_core(rtwdev);
-	else
-		rtw_leave_lps_core(rtwdev);
+	set_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags);
 }
 
-void rtw_enter_lps_irqsafe(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif)
+static void __rtw_enter_lps(struct rtw_dev *rtwdev, u8 port_id)
 {
 	struct rtw_lps_conf *conf = &rtwdev->lps_conf;
 
-	if (rtwvif->in_lps)
+	if (test_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags))
 		return;
 
 	conf->mode = RTW_MODE_LPS;
-	conf->rtwvif = rtwvif;
-	rtwvif->in_lps = true;
+	conf->port_id = port_id;
 
-	ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->lps_work, 0);
+	rtw_enter_lps_core(rtwdev);
 }
 
-void rtw_leave_lps_irqsafe(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif)
+static void __rtw_leave_lps(struct rtw_dev *rtwdev)
 {
 	struct rtw_lps_conf *conf = &rtwdev->lps_conf;
 
-	if (!rtwvif->in_lps)
+	if (test_and_clear_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags)) {
+		rtw_dbg(rtwdev, RTW_DBG_PS,
+			"Should leave deep PS before leaving LPS\n");
+		__rtw_leave_lps_deep(rtwdev);
+	}
+
+	if (!test_bit(RTW_FLAG_LEISURE_PS, rtwdev->flags))
 		return;
 
 	conf->mode = RTW_MODE_ACTIVE;
-	conf->rtwvif = rtwvif;
-	rtwvif->in_lps = false;
-
-	ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->lps_work, 0);
-}
 
-bool rtw_in_lps(struct rtw_dev *rtwdev)
-{
-	return rtw_flag_check(rtwdev, RTW_FLAG_LEISURE_PS);
+	rtw_leave_lps_core(rtwdev);
 }
 
-void rtw_enter_lps(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif)
+void rtw_enter_lps(struct rtw_dev *rtwdev, u8 port_id)
 {
-	struct rtw_lps_conf *conf = &rtwdev->lps_conf;
-
-	if (WARN_ON(!rtwvif))
-		return;
+	lockdep_assert_held(&rtwdev->mutex);
 
-	if (rtwvif->in_lps)
+	if (rtwdev->coex.stat.wl_force_lps_ctrl)
 		return;
 
-	conf->mode = RTW_MODE_LPS;
-	conf->rtwvif = rtwvif;
-	rtwvif->in_lps = true;
-
-	rtw_enter_lps_core(rtwdev);
+	__rtw_enter_lps(rtwdev, port_id);
+	__rtw_enter_lps_deep(rtwdev);
 }
 
-void rtw_leave_lps(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif)
+void rtw_leave_lps(struct rtw_dev *rtwdev)
 {
-	struct rtw_lps_conf *conf = &rtwdev->lps_conf;
-
-	if (WARN_ON(!rtwvif))
-		return;
+	lockdep_assert_held(&rtwdev->mutex);
 
-	if (!rtwvif->in_lps)
-		return;
+	__rtw_leave_lps_deep(rtwdev);
+	__rtw_leave_lps(rtwdev);
+}
 
-	conf->mode = RTW_MODE_ACTIVE;
-	conf->rtwvif = rtwvif;
-	rtwvif->in_lps = false;
+void rtw_leave_lps_deep(struct rtw_dev *rtwdev)
+{
+	lockdep_assert_held(&rtwdev->mutex);
 
-	rtw_leave_lps_core(rtwdev);
+	__rtw_leave_lps_deep(rtwdev);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/ps.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/ps.h
@@ -5,16 +5,20 @@
 #ifndef __RTW_PS_H_
 #define __RTW_PS_H_
 
-#define RTW_LPS_THRESHOLD	2
+#define RTW_LPS_THRESHOLD	50
+
+#define POWER_MODE_ACK		BIT(6)
+#define POWER_MODE_PG		BIT(4)
+#define POWER_MODE_LCLK		BIT(0)
+
+#define LEAVE_LPS_TRY_CNT	5
 
 int rtw_enter_ips(struct rtw_dev *rtwdev);
 int rtw_leave_ips(struct rtw_dev *rtwdev);
 
-void rtw_lps_work(struct work_struct *work);
-void rtw_enter_lps_irqsafe(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif);
-void rtw_leave_lps_irqsafe(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif);
-void rtw_enter_lps(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif);
-void rtw_leave_lps(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif);
-bool rtw_in_lps(struct rtw_dev *rtwdev);
+void rtw_power_mode_change(struct rtw_dev *rtwdev, bool enter);
+void rtw_enter_lps(struct rtw_dev *rtwdev, u8 port_id);
+void rtw_leave_lps(struct rtw_dev *rtwdev);
+void rtw_leave_lps_deep(struct rtw_dev *rtwdev);
 
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/reg.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/reg.h
@@ -6,13 +6,23 @@
 #define __RTW_REG_DEF_H__
 
 #define REG_SYS_FUNC_EN		0x0002
+#define BIT_FEN_EN_25_1		BIT(13)
+#define BIT_FEN_ELDR		BIT(12)
 #define BIT_FEN_CPUEN		BIT(2)
 #define BIT_FEN_BB_GLB_RST	BIT(1)
 #define BIT_FEN_BB_RSTB		BIT(0)
+#define BIT_R_DIS_PRST		BIT(6)
+#define BIT_WLOCK_1C_B6		BIT(5)
 #define REG_SYS_PW_CTRL		0x0004
+#define BIT_PFM_WOWL		BIT(3)
 #define REG_SYS_CLK_CTRL	0x0008
 #define BIT_CPU_CLK_EN		BIT(14)
 
+#define REG_SYS_CLKR		0x0008
+#define BIT_ANA8M		BIT(1)
+#define BIT_WAKEPAD_EN		BIT(3)
+#define BIT_LOADER_CLK_EN	BIT(5)
+
 #define REG_RSV_CTRL		0x001C
 #define DISABLE_PI		0x3
 #define ENABLE_PI		0x2
@@ -31,12 +41,23 @@
 #define BIT_MASK_EF_ADDR	0x3ff
 #define BIT_MASK_EF_DATA	0xff
 #define BITS_EF_ADDR		(BIT_MASK_EF_ADDR << BIT_SHIFT_EF_ADDR)
+#define BITS_PLL		0xf0
+
+#define REG_AFE_CTRL3		0x2c
+#define BIT_MASK_XTAL		0x00FFF000
+#define BIT_XTAL_GMP_BIT4	BIT(28)
 
 #define REG_LDO_EFUSE_CTRL	0x0034
 #define BIT_MASK_EFUSE_BANK_SEL	(BIT(8) | BIT(9))
 
+#define BIT_LDO25_VOLTAGE_V25	0x03
+#define BIT_MASK_LDO25_VOLTAGE	GENMASK(6, 4)
+#define BIT_SHIFT_LDO25_VOLTAGE	4
+#define BIT_LDO25_EN		BIT(7)
+
 #define REG_GPIO_MUXCFG		0x0040
 #define BIT_FSPI_EN		BIT(19)
+#define BIT_EN_SIC		BIT(12)
 #define BIT_BT_AOD_GPIO3	BIT(9)
 #define BIT_BT_PTA_EN		BIT(5)
 #define BIT_WLRFE_4_5_EN	BIT(2)
@@ -46,7 +67,9 @@
 #define BIT_PAPE_SEL_EN		BIT(25)
 #define BIT_DPDT_WL_SEL		BIT(24)
 #define BIT_DPDT_SEL_EN		BIT(23)
+#define REG_LEDCFG2		0x004E
 #define REG_PAD_CTRL1		0x0064
+#define BIT_BT_BTG_SEL		BIT(31)
 #define BIT_PAPE_WLBT_SEL	BIT(29)
 #define BIT_LNAON_WLBT_SEL	BIT(28)
 #define BIT_BTGP_JTAG_EN	BIT(24)
@@ -60,31 +83,56 @@
 #define BIT_DBG_GNT_WL_BT	BIT(27)
 #define BIT_LTE_MUX_CTRL_PATH	BIT(26)
 #define REG_HCI_OPT_CTRL	0x0074
+#define BIT_USB_SUS_DIS		BIT(8)
+
+#define REG_AFE_CTRL_4		0x0078
+#define BIT_CK320M_AFE_EN	BIT(4)
+#define BIT_EN_SYN		BIT(15)
+
+#define REG_LDO_SWR_CTRL	0x007C
+#define LDO_SEL			0xC3
+#define SPS_SEL			0x83
+#define BIT_XTA1		BIT(29)
+#define BIT_XTA0		BIT(28)
 
 #define REG_MCUFW_CTRL		0x0080
 #define BIT_ANA_PORT_EN		BIT(22)
 #define BIT_MAC_PORT_EN		BIT(21)
 #define BIT_BOOT_FSPI_EN	BIT(20)
+#define BIT_ROM_DLEN		BIT(19)
+#define BIT_ROM_PGE		GENMASK(18, 16)	/* legacy only */
+#define BIT_SHIFT_ROM_PGE	16
 #define BIT_FW_INIT_RDY		BIT(15)
 #define BIT_FW_DW_RDY		BIT(14)
 #define BIT_RPWM_TOGGLE		BIT(7)
+#define BIT_RAM_DL_SEL		BIT(7)	/* legacy only */
 #define BIT_DMEM_CHKSUM_OK	BIT(6)
+#define BIT_WINTINI_RDY		BIT(6)	/* legacy only */
 #define BIT_DMEM_DW_OK		BIT(5)
 #define BIT_IMEM_CHKSUM_OK	BIT(4)
 #define BIT_IMEM_DW_OK		BIT(3)
 #define BIT_IMEM_BOOT_LOAD_CHECKSUM_OK BIT(2)
+#define BIT_FWDL_CHK_RPT	BIT(2)	/* legacy only */
+#define BIT_MCUFWDL_RDY		BIT(1)	/* legacy only */
 #define BIT_MCUFWDL_EN		BIT(0)
 #define BIT_CHECK_SUM_OK	(BIT(4) | BIT(6))
 #define FW_READY		(BIT_FW_INIT_RDY | BIT_FW_DW_RDY |             \
 				 BIT_IMEM_DW_OK | BIT_DMEM_DW_OK |             \
 				 BIT_CHECK_SUM_OK)
+#define FW_READY_LEGACY		(BIT_MCUFWDL_RDY | BIT_FWDL_CHK_RPT |	       \
+				 BIT_WINTINI_RDY | BIT_RAM_DL_SEL)
 #define FW_READY_MASK		0xffff
 
+#define REG_EFUSE_ACCESS	0x00CF
+#define EFUSE_ACCESS_ON		0x69
+#define EFUSE_ACCESS_OFF	0x00
+
 #define REG_WLRF1		0x00EC
 #define REG_WIFI_BT_INFO	0x00AA
 #define BIT_BT_INT_EN		BIT(15)
 #define REG_SYS_CFG1		0x00F0
 #define	BIT_RTL_ID		BIT(23)
+#define BIT_LDO			BIT(24)
 #define BIT_RF_TYPE_ID		BIT(27)
 #define BIT_SHIFT_VENDOR_ID	16
 #define BIT_MASK_VENDOR_ID	0xf
@@ -160,8 +208,13 @@
 #define REG_CR			0x0100
 #define REG_TRXFF_BNDY		0x0114
 #define REG_RXFF_BNDY		0x011C
+#define REG_FE1IMR		0x0120
+#define BIT_FS_RXDONE		BIT(16)
 #define REG_PKTBUF_DBG_CTRL	0x0140
 #define REG_C2HEVT		0x01A0
+#define REG_MCUTST_1		0x01C0
+#define REG_MCUTST_II		0x01C4
+#define REG_WOWLAN_WAKE_REASON	0x01C7
 #define REG_HMETFR		0x01CC
 #define REG_HMEBOX0		0x01D0
 #define REG_HMEBOX1		0x01D4
@@ -172,14 +225,42 @@
 #define REG_HMEBOX2_EX		0x01F8
 #define REG_HMEBOX3_EX		0x01FC
 
+#define REG_RQPN		0x0200
+#define BIT_MASK_HPQ		0xff
+#define BIT_SHIFT_HPQ		0
+#define BIT_RQPN_HPQ(x)		(((x) & BIT_MASK_HPQ) << BIT_SHIFT_HPQ)
+#define BIT_MASK_LPQ		0xff
+#define BIT_SHIFT_LPQ		8
+#define BIT_RQPN_LPQ(x)		(((x) & BIT_MASK_LPQ) << BIT_SHIFT_LPQ)
+#define BIT_MASK_PUBQ		0xff
+#define BIT_SHIFT_PUBQ		16
+#define BIT_RQPN_PUBQ(x)	(((x) & BIT_MASK_PUBQ) << BIT_SHIFT_PUBQ)
+#define BIT_RQPN_HLP(h, l, p)	(BIT_LD_RQPN | BIT_RQPN_HPQ(h) |	       \
+				 BIT_RQPN_LPQ(l) | BIT_RQPN_PUBQ(p))
+
 #define REG_FIFOPAGE_CTRL_2	0x0204
 #define BIT_BCN_VALID_V1	BIT(15)
 #define BIT_MASK_BCN_HEAD_1_V1	0xfff
 #define REG_AUTO_LLT_V1		0x0208
 #define BIT_AUTO_INIT_LLT_V1	BIT(0)
+#define REG_DWBCN0_CTRL		0x0208
+#define BIT_BCN_VALID		BIT(16)
 #define REG_TXDMA_OFFSET_CHK	0x020C
+#define BIT_DROP_DATA_EN	BIT(9)
 #define REG_TXDMA_STATUS	0x0210
 #define BTI_PAGE_OVF		BIT(2)
+
+#define REG_RQPN_NPQ		0x0214
+#define BIT_MASK_NPQ		0xff
+#define BIT_SHIFT_NPQ		0
+#define BIT_MASK_EPQ		0xff
+#define BIT_SHIFT_EPQ		16
+#define BIT_RQPN_NPQ(x)		(((x) & BIT_MASK_NPQ) << BIT_SHIFT_NPQ)
+#define BIT_RQPN_EPQ(x)		(((x) & BIT_MASK_EPQ) << BIT_SHIFT_EPQ)
+#define BIT_RQPN_NE(n, e)	(BIT_RQPN_NPQ(n) | BIT_RQPN_EPQ(e))
+
+#define REG_AUTO_LLT		0x0224
+#define BIT_AUTO_INIT_LLT	BIT(16)
 #define REG_RQPN_CTRL_1		0x0228
 #define REG_RQPN_CTRL_2		0x022C
 #define BIT_LD_RQPN		BIT(31)
@@ -192,13 +273,26 @@
 #define REG_H2C_TAIL		0x0248
 #define REG_H2C_READ_ADDR	0x024C
 #define REG_H2C_INFO		0x0254
+#define REG_RXPKT_NUM		0x0284
+#define BIT_RXDMA_REQ		BIT(19)
+#define BIT_RW_RELEASE		BIT(18)
+#define BIT_RXDMA_IDLE		BIT(17)
+#define REG_RXPKTNUM		0x02B0
 
 #define REG_INT_MIG		0x0304
+#define REG_HCI_MIX_CFG		0x03FC
+#define BIT_PCIE_EMAC_PDN_AUX_TO_FAST_CLK BIT(26)
 
+#define REG_BCNQ_INFO		0x0418
+#define BIT_MGQ_CPU_EMPTY	BIT(24)
 #define REG_FWHW_TXQ_CTRL	0x0420
 #define BIT_EN_BCNQ_DL		BIT(22)
 #define BIT_EN_WR_FREE_TAIL	BIT(20)
+#define REG_HWSEQ_CTRL		0x0423
+
 #define REG_BCNQ_BDNY_V1	0x0424
+#define REG_BCNQ_BDNY		0x0424
+#define REG_MGQ_BDNY		0x0425
 #define REG_LIFETIME_EN		0x0426
 #define BIT_BA_PARSER_EN	BIT(5)
 #define REG_SPEC_SIFS		0x0428
@@ -214,6 +308,8 @@
 #define BIT_CHECK_CCK_EN	BIT(7)
 #define REG_AMPDU_MAX_TIME_V1	0x0455
 #define REG_BCNQ1_BDNY_V1	0x0456
+#define REG_AMPDU_MAX_TIME	0x0456
+#define REG_WMAC_LBK_BF_HD	0x045D
 #define REG_TX_HANG_CTRL	0x045E
 #define BIT_EN_GNT_BT_AWAKE	BIT(3)
 #define BIT_EN_EOF_V1		BIT(2)
@@ -228,7 +324,10 @@
 #define REG_QUEUE_CTRL		0x04C6
 #define BIT_PTA_WL_TX_EN	BIT(4)
 #define BIT_PTA_EDCCA_EN	BIT(5)
+#define REG_SINGLE_AMPDU_CTRL	0x04C7
+#define BIT_EN_SINGLE_APMDU	BIT(7)
 #define REG_PROT_MODE_CTRL	0x04C8
+#define REG_MAX_AGGR_NUM	0x04CA
 #define REG_BAR_MODE_CTRL	0x04CC
 #define REG_PRECNT_CTRL		0x04E5
 #define BIT_BTCCA_CTRL		(BIT(0) | BIT(1))
@@ -239,38 +338,51 @@
 #define REG_EDCA_VI_PARAM	0x0504
 #define REG_EDCA_BE_PARAM	0x0508
 #define REG_EDCA_BK_PARAM	0x050C
+#define BIT_MASK_TXOP_LMT	GENMASK(26, 16)
+#define BIT_MASK_CWMAX		GENMASK(15, 12)
+#define BIT_MASK_CWMIN		GENMASK(11, 8)
+#define BIT_MASK_AIFS		GENMASK(7, 0)
 #define REG_PIFS		0x0512
 #define REG_SIFS		0x0514
 #define BIT_SHIFT_SIFS_OFDM_CTX	8
 #define BIT_SHIFT_SIFS_CCK_TRX	16
 #define BIT_SHIFT_SIFS_OFDM_TRX	24
+#define REG_AGGR_BREAK_TIME	0x051A
 #define REG_SLOT		0x051B
 #define REG_TX_PTCL_CTRL	0x0520
+#define BIT_DIS_EDCCA		BIT(15)
 #define BIT_SIFS_BK_EN		BIT(12)
 #define REG_TXPAUSE		0x0522
 #define REG_RD_CTRL		0x0524
+#define BIT_EDCCA_MSK_CNTDOWN_EN BIT(11)
 #define BIT_DIS_TXOP_CFE	BIT(10)
 #define BIT_DIS_LSIG_CFE	BIT(9)
 #define BIT_DIS_STBC_CFE	BIT(8)
 #define REG_TBTT_PROHIBIT	0x0540
 #define BIT_SHIFT_TBTT_HOLD_TIME_AP 8
 #define REG_RD_NAV_NXT		0x0544
+#define REG_NAV_PROT_LEN	0x0546
 #define REG_BCN_CTRL		0x0550
 #define BIT_DIS_TSF_UDT		BIT(4)
 #define BIT_EN_BCN_FUNCTION	BIT(3)
+#define BIT_EN_TXBCN_RPT	BIT(2)
 #define REG_BCN_CTRL_CLINT0	0x0551
 #define REG_DRVERLYINT		0x0558
 #define REG_BCNDMATIM		0x0559
+#define REG_ATIMWND		0x055A
 #define REG_USTIME_TSF		0x055C
 #define REG_BCN_MAX_ERR		0x055D
 #define REG_RXTSF_OFFSET_CCK	0x055E
 #define REG_MISC_CTRL		0x0577
 #define BIT_EN_FREE_CNT		BIT(3)
 #define BIT_DIS_SECOND_CCA	(BIT(0) | BIT(1))
+#define REG_HIQ_NO_LMT_EN	0x5A7
+#define BIT_HIQ_NO_LMT_EN_ROOT	BIT(0)
 #define REG_TIMER0_SRC_SEL	0x05B4
 #define BIT_TSFT_SEL_TIMER0	(BIT(4) | BIT(5) | BIT(6))
 
 #define REG_TCR			0x0604
+#define BIT_PWRMGT_HWDATA_EN	BIT(7)
 #define REG_RCR			0x0608
 #define BIT_APP_FCS		BIT(31)
 #define BIT_APP_MIC		BIT(30)
@@ -291,6 +403,7 @@
 #define BIT_HTC_LOC_CTRL	BIT(14)
 #define BIT_RPFM_CAM_ENABLE	BIT(12)
 #define BIT_TA_BCN		BIT(11)
+#define BIT_RCR_ADF		BIT(11)
 #define BIT_DISDECMYPKT		BIT(10)
 #define BIT_AICV		BIT(9)
 #define BIT_ACRC32		BIT(8)
@@ -305,8 +418,10 @@
 #define REG_RX_PKT_LIMIT	0x060C
 #define REG_RX_DRVINFO_SZ	0x060F
 #define BIT_APP_PHYSTS		BIT(28)
+#define REG_MAR			0x0620
 #define REG_USTIME_EDCA		0x0638
 #define REG_ACKTO_CCK		0x0639
+#define REG_MAC_SPEC_SIFS	0x063A
 #define REG_RESP_SIFS_CCK	0x063C
 #define REG_RESP_SIFS_OFDM	0x063E
 #define REG_ACKTO		0x0640
@@ -317,9 +432,24 @@
 #define BIT_RFMOD_80M		BIT(8)
 #define BIT_RFMOD_40M		BIT(7)
 #define REG_WMAC_TRXPTCL_CTL_H	0x066C
+#define REG_WKFMCAM_CMD		0x0698
+#define BIT_WKFCAM_POLLING_V1	BIT(31)
+#define BIT_WKFCAM_CLR_V1	BIT(30)
+#define BIT_WKFCAM_WE		BIT(16)
+#define BIT_SHIFT_WKFCAM_ADDR_V2	8
+#define BIT_MASK_WKFCAM_ADDR_V2		0xff
+#define BIT_WKFCAM_ADDR_V2(x)						       \
+	(((x) & BIT_MASK_WKFCAM_ADDR_V2) << BIT_SHIFT_WKFCAM_ADDR_V2)
+#define REG_WKFMCAM_RWD         0x069C
+#define BIT_WKFMCAM_VALID	BIT(31)
+#define BIT_WKFMCAM_BC		BIT(26)
+#define BIT_WKFMCAM_MC		BIT(25)
+#define BIT_WKFMCAM_UC		BIT(24)
+
 #define REG_RXFLTMAP0		0x06A0
 #define REG_RXFLTMAP1		0x06A2
 #define REG_RXFLTMAP2		0x06A4
+#define REG_RXFLTMAP4		0x068A
 #define REG_BT_COEX_TABLE0	0x06C0
 #define REG_BT_COEX_TABLE1	0x06C4
 #define REG_BT_COEX_BRK_TABLE	0x06C8
@@ -334,12 +464,19 @@
 #define BIT_LTE_COEX_EN		BIT(7)
 #define REG_BT_STAT_CTRL	0x0778
 #define REG_BT_TDMA_TIME	0x0790
+#define REG_LTR_IDLE_LATENCY	0x0798
+#define REG_LTR_ACTIVE_LATENCY	0x079C
+#define REG_LTR_CTRL_BASIC	0x07A4
 #define REG_WMAC_OPTION_FUNCTION 0x07D0
 #define REG_WMAC_OPTION_FUNCTION_1 0x07D4
 
+#define REG_FPGA0_RFMOD		0x0800
+#define BIT_CCKEN		BIT(24)
+#define BIT_OFDMEN		BIT(25)
 #define REG_RX_GAIN_EN		0x081c
 
 #define REG_RFE_CTRL_E		0x0974
+#define REG_2ND_CCA_CTRL	0x0976
 
 #define REG_DIS_DPD		0x0a70
 #define DIS_DPD_MASK		GENMASK(9, 0)
@@ -478,7 +615,10 @@
 
 #define REG_IGN_GNTBT4	0x4160
 
+#define RF_MODE		0x00
 #define RF_MODOPT	0x01
+#define RF_WLINT	0x01
+#define RF_WLSEL	0x02
 #define RF_DTXLOK	0x08
 #define RF_CFGCH	0x18
 #define RF_RCK		0x1d
@@ -486,9 +626,15 @@
 #define RF_LUTWD1	0x3e
 #define RF_LUTWD0	0x3f
 #define RF_T_METER	0x42
+#define RF_BSPAD	0x54
+#define RF_GAINTX	0x56
+#define RF_TXATANK	0x64
+#define RF_TRXIQ	0x66
+#define RF_RXIQGEN	0x8d
 #define RF_XTALX2	0xb8
 #define RF_MALSEL	0xbe
 #define RF_RCKD		0xde
+#define RF_TXADBG	0xde
 #define RF_LUTDBG	0xdf
 #define RF_LUTWE2	0xee
 #define RF_LUTWE	0xef
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/regd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/regd.c
@@ -7,6 +7,18 @@
 #include "debug.h"
 #include "phy.h"
 
+static const struct ieee80211_regdomain rtw88_world_regdom = {
+	.n_reg_rules = 5,
+	.alpha2 =  "99",
+	.reg_rules = {
+		REG_RULE(2412 - 10, 2462 + 10, 40, 0, 20, 0),
+		REG_RULE(2467 - 10, 2484 + 10, 40, 0, 20, NL80211_RRF_NO_IR),
+		REG_RULE(5180 - 10, 5240 + 10, 80, 0, 20, NL80211_RRF_NO_IR),
+		REG_RULE(5260 - 10, 5700 + 10, 80, 0, 20,
+			 NL80211_RRF_NO_IR | NL80211_RRF_DFS),
+		REG_RULE(5745 - 10, 5825 + 10, 80, 0, 20, NL80211_RRF_NO_IR),
+	}
+};
 #define COUNTRY_CHPLAN_ENT(_alpha2, _chplan, _txpwr_regd) \
 	{.alpha2 = (_alpha2), \
 	 .chplan = (_chplan), \
@@ -339,12 +351,31 @@
 	return rtw_defined_chplan;
 }
 
+static bool rtw_regd_is_ww(struct rtw_regulatory *reg)
+{
+	if (reg->txpwr_regd == RTW_REGD_WW)
+		return true;
+	return false;
+}
+
 static int rtw_regd_notifier_apply(struct rtw_dev *rtwdev,
 				   struct wiphy *wiphy,
 				   struct regulatory_request *request)
 {
-	if (request->initiator == NL80211_REGDOM_SET_BY_USER)
+	if (request->initiator == NL80211_REGDOM_SET_BY_DRIVER)
+		return -EINVAL;
+	if (request->initiator == NL80211_REGDOM_SET_BY_USER &&
+	    !IS_ENABLED(CONFIG_RTW88_REGD_USER_REG_HINTS))
+		return -EINVAL;
+	if (request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE &&
+	    !rtw_regd_is_ww(&rtwdev->regd))
+		return -EINVAL;
+	if (request->initiator == NL80211_REGDOM_SET_BY_CORE &&
+	    !rtwdev->efuse.country_worldwide) {
+		rtwdev->regd =
+			rtw_regd_find_reg_by_name(rtwdev->efuse.country_code);
 		return 0;
+	}
 	rtwdev->regd = rtw_regd_find_reg_by_name(request->alpha2);
 	rtw_regd_apply_world_flags(wiphy, request->initiator);
 
@@ -352,15 +383,22 @@
 }
 
 static int
-rtw_regd_init_wiphy(struct rtw_regulatory *reg, struct wiphy *wiphy,
+rtw_regd_init_wiphy(struct rtw_dev *rtwdev, struct wiphy *wiphy,
 		    void (*reg_notifier)(struct wiphy *wiphy,
 					 struct regulatory_request *request))
 {
+	struct rtw_regulatory *reg = &rtwdev->regd;
+
 	wiphy->reg_notifier = reg_notifier;
 
-	wiphy->regulatory_flags &= ~REGULATORY_CUSTOM_REG;
-	wiphy->regulatory_flags &= ~REGULATORY_STRICT_REG;
-	wiphy->regulatory_flags &= ~REGULATORY_DISABLE_BEACON_HINTS;
+	if (rtw_regd_is_ww(reg)) {
+		rtwdev->efuse.country_worldwide = true;
+		wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
+		wiphy_apply_custom_regulatory(wiphy, &rtw88_world_regdom);
+	} else {
+		rtwdev->efuse.country_worldwide = false;
+	}
+	wiphy->regulatory_flags |= REGULATORY_STRICT_REG;
 
 	rtw_regd_apply_hw_cap_flags(wiphy);
 
@@ -377,7 +415,7 @@
 		return -EINVAL;
 
 	rtwdev->regd = rtw_regd_find_reg_by_name(rtwdev->efuse.country_code);
-	rtw_regd_init_wiphy(&rtwdev->regd, wiphy, reg_notifier);
+	rtw_regd_init_wiphy(rtwdev, wiphy, reg_notifier);
 
 	return 0;
 }
@@ -388,11 +426,14 @@
 	struct rtw_dev *rtwdev = hw->priv;
 	struct rtw_hal *hal = &rtwdev->hal;
 
-	rtw_regd_notifier_apply(rtwdev, wiphy, request);
-	rtw_dbg(rtwdev, RTW_DBG_REGD,
-		"get alpha2 %c%c from initiator %d, mapping to chplan 0x%x, txregd %d\n",
-		request->alpha2[0], request->alpha2[1], request->initiator,
-		rtwdev->regd.chplan, rtwdev->regd.txpwr_regd);
+	if (!rtw_regd_notifier_apply(rtwdev, wiphy, request)) {
+		rtw_dbg(rtwdev, RTW_DBG_REGD,
+			"get alpha2 %c%c from initiator %d, mapping to chplan 0x%x, txregd %d\n",
+			request->alpha2[0], request->alpha2[1],
+			request->initiator, rtwdev->regd.chplan,
+			rtwdev->regd.txpwr_regd);
+		rtw_phy_adaptivity_set_mode(rtwdev);
+	}
 
 	rtw_phy_set_tx_power_level(rtwdev, hal->current_channel);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/rtw8723d.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/rtw8723d.c
@@ -0,0 +1,2793 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2018-2019  Realtek Corporation
+ */
+
+#include "main.h"
+#include "coex.h"
+#include "fw.h"
+#include "tx.h"
+#include "rx.h"
+#include "phy.h"
+#include "rtw8723d.h"
+#include "rtw8723d_table.h"
+#include "mac.h"
+#include "reg.h"
+#include "debug.h"
+
+static const struct rtw_hw_reg rtw8723d_txagc[] = {
+	[DESC_RATE1M]	= { .addr = 0xe08, .mask = 0x0000ff00 },
+	[DESC_RATE2M]	= { .addr = 0x86c, .mask = 0x0000ff00 },
+	[DESC_RATE5_5M]	= { .addr = 0x86c, .mask = 0x00ff0000 },
+	[DESC_RATE11M]	= { .addr = 0x86c, .mask = 0xff000000 },
+	[DESC_RATE6M]	= { .addr = 0xe00, .mask = 0x000000ff },
+	[DESC_RATE9M]	= { .addr = 0xe00, .mask = 0x0000ff00 },
+	[DESC_RATE12M]	= { .addr = 0xe00, .mask = 0x00ff0000 },
+	[DESC_RATE18M]	= { .addr = 0xe00, .mask = 0xff000000 },
+	[DESC_RATE24M]	= { .addr = 0xe04, .mask = 0x000000ff },
+	[DESC_RATE36M]	= { .addr = 0xe04, .mask = 0x0000ff00 },
+	[DESC_RATE48M]	= { .addr = 0xe04, .mask = 0x00ff0000 },
+	[DESC_RATE54M]	= { .addr = 0xe04, .mask = 0xff000000 },
+	[DESC_RATEMCS0]	= { .addr = 0xe10, .mask = 0x000000ff },
+	[DESC_RATEMCS1]	= { .addr = 0xe10, .mask = 0x0000ff00 },
+	[DESC_RATEMCS2]	= { .addr = 0xe10, .mask = 0x00ff0000 },
+	[DESC_RATEMCS3]	= { .addr = 0xe10, .mask = 0xff000000 },
+	[DESC_RATEMCS4]	= { .addr = 0xe14, .mask = 0x000000ff },
+	[DESC_RATEMCS5]	= { .addr = 0xe14, .mask = 0x0000ff00 },
+	[DESC_RATEMCS6]	= { .addr = 0xe14, .mask = 0x00ff0000 },
+	[DESC_RATEMCS7]	= { .addr = 0xe14, .mask = 0xff000000 },
+};
+
+#define WLAN_TXQ_RPT_EN		0x1F
+#define WLAN_SLOT_TIME		0x09
+#define WLAN_RL_VAL		0x3030
+#define WLAN_BAR_VAL		0x0201ffff
+#define BIT_MASK_TBTT_HOLD	0x00000fff
+#define BIT_SHIFT_TBTT_HOLD	8
+#define BIT_MASK_TBTT_SETUP	0x000000ff
+#define BIT_SHIFT_TBTT_SETUP	0
+#define BIT_MASK_TBTT_MASK	((BIT_MASK_TBTT_HOLD << BIT_SHIFT_TBTT_HOLD) | \
+				 (BIT_MASK_TBTT_SETUP << BIT_SHIFT_TBTT_SETUP))
+#define TBTT_TIME(s, h)((((s) & BIT_MASK_TBTT_SETUP) << BIT_SHIFT_TBTT_SETUP) |\
+			(((h) & BIT_MASK_TBTT_HOLD) << BIT_SHIFT_TBTT_HOLD))
+#define WLAN_TBTT_TIME_NORMAL	TBTT_TIME(0x04, 0x80)
+#define WLAN_TBTT_TIME_STOP_BCN	TBTT_TIME(0x04, 0x64)
+#define WLAN_PIFS_VAL		0
+#define WLAN_AGG_BRK_TIME	0x16
+#define WLAN_NAV_PROT_LEN	0x0040
+#define WLAN_SPEC_SIFS		0x100a
+#define WLAN_RX_PKT_LIMIT	0x17
+#define WLAN_MAX_AGG_NR		0x0A
+#define WLAN_AMPDU_MAX_TIME	0x1C
+#define WLAN_ANT_SEL		0x82
+#define WLAN_LTR_IDLE_LAT	0x90039003
+#define WLAN_LTR_ACT_LAT	0x883c883c
+#define WLAN_LTR_CTRL1		0xCB004010
+#define WLAN_LTR_CTRL2		0x01233425
+
+static void rtw8723d_lck(struct rtw_dev *rtwdev)
+{
+#define BIT_LCK		BIT(15)
+	u8 val_ctx;
+	u32 lc_cal, cnt;
+
+	val_ctx = rtw_read8(rtwdev, REG_CTX);
+	if ((val_ctx & BIT_MASK_CTX_TYPE) != 0)
+		rtw_write8(rtwdev, REG_CTX, val_ctx & ~BIT_MASK_CTX_TYPE);
+	else
+		rtw_write8(rtwdev, REG_TXPAUSE, 0xFF);
+	lc_cal = rtw_read_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK);
+
+	rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK, lc_cal | BIT_LCK);
+	for (cnt = 0; cnt < 100; cnt++) {
+		if (rtw_read_rf(rtwdev, RF_PATH_A, RF_CFGCH, BIT_LCK) != 0x1)
+			break;
+		mdelay(10);
+	}
+
+	rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK, lc_cal);
+	if ((val_ctx & BIT_MASK_CTX_TYPE) != 0)
+		rtw_write8(rtwdev, REG_CTX, val_ctx);
+	else
+		rtw_write8(rtwdev, REG_TXPAUSE, 0x00);
+}
+
+#define RTW_DEF_OFDM_SWING_INDEX	28
+#define RTW_OFDM_SWING_TABLE_SIZE	43
+#define OFDM_SWING_A(swing)	((swing) & 0x000003FF)
+#define OFDM_SWING_B(swing)	(((swing) & 0x0000FC00) >> 10)
+#define OFDM_SWING_C(swing)	(((swing) & 0x003F0000) >> 16)
+#define OFDM_SWING_D(swing)	(((swing) & 0xFFC00000) >> 22)
+static const u32 rtw8723d_ofdm_swing_table[] = {
+	0x0b40002d, 0x0c000030, 0x0cc00033, 0x0d800036, 0x0e400039, 0x0f00003c,
+	0x10000040, 0x11000044, 0x12000048, 0x1300004c, 0x14400051, 0x15800056,
+	0x16c0005b, 0x18000060, 0x19800066, 0x1b00006c, 0x1c800072, 0x1e400079,
+	0x20000080, 0x22000088, 0x24000090, 0x26000098, 0x288000a2, 0x2ac000ab,
+	0x2d4000b5, 0x300000c0, 0x32c000cb, 0x35c000d7, 0x390000e4, 0x3c8000f2,
+	0x40000100, 0x43c0010f, 0x47c0011f, 0x4c000130, 0x50800142, 0x55400155,
+	0x5a400169, 0x5fc0017f, 0x65400195, 0x6b8001ae, 0x71c001c7, 0x788001e2,
+	0x7f8001fe,
+};
+
+#define RTW_DEF_CCK_SWING_INDEX	28
+#define RTW_CCK_TABLE_SIZE	41
+static const u32 rtw8723d_cck_swing_table[] = {
+	0x0CD, 0x0D9, 0x0E6, 0x0F3, 0x102, 0x111, 0x121, 0x132, 0x144, 0x158,
+	0x16C, 0x182, 0x198, 0x1B1, 0x1CA, 0x1E5, 0x202, 0x221, 0x241, 0x263,
+	0x287, 0x2AE, 0x2D6, 0x301, 0x32F, 0x35F, 0x392, 0x3C9, 0x402, 0x43F,
+	0x47F, 0x4C3, 0x50C, 0x558, 0x5A9, 0x5FF, 0x65A, 0x6BA, 0x720, 0x78C,
+	0x7FF,
+};
+
+static_assert(ARRAY_SIZE(rtw8723d_ofdm_swing_table) == RTW_OFDM_SWING_TABLE_SIZE);
+static_assert(ARRAY_SIZE(rtw8723d_cck_swing_table) == RTW_CCK_TABLE_SIZE);
+
+static void rtw8723d_pwrtrack_init(struct rtw_dev *rtwdev)
+{
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+	u8 path;
+
+	dm_info->default_ofdm_index = RTW_DEF_OFDM_SWING_INDEX;
+
+	for (path = RF_PATH_A; path < rtwdev->hal.rf_path_num; path++) {
+		ewma_thermal_init(&dm_info->avg_thermal[path]);
+		dm_info->delta_power_index[path] = 0;
+	}
+	dm_info->pwr_trk_triggered = false;
+	dm_info->pwr_trk_init_trigger = true;
+	dm_info->thermal_meter_k = rtwdev->efuse.thermal_meter_k;
+	dm_info->txagc_remnant_cck = 0;
+	dm_info->txagc_remnant_ofdm = 0;
+}
+
+static void rtw8723d_phy_set_param(struct rtw_dev *rtwdev)
+{
+	u8 xtal_cap;
+	u32 val32;
+
+	/* power on BB/RF domain */
+	rtw_write16_set(rtwdev, REG_SYS_FUNC_EN,
+			BIT_FEN_EN_25_1 | BIT_FEN_BB_GLB_RST | BIT_FEN_BB_RSTB);
+	rtw_write8_set(rtwdev, REG_RF_CTRL,
+		       BIT_RF_EN | BIT_RF_RSTB | BIT_RF_SDM_RSTB);
+	rtw_write8(rtwdev, REG_AFE_CTRL1 + 1, 0x80);
+
+	rtw_phy_load_tables(rtwdev);
+
+	/* post init after header files config */
+	rtw_write32_clr(rtwdev, REG_RCR, BIT_RCR_ADF);
+	rtw_write8_set(rtwdev, REG_HIQ_NO_LMT_EN, BIT_HIQ_NO_LMT_EN_ROOT);
+	rtw_write16_set(rtwdev, REG_AFE_CTRL_4, BIT_CK320M_AFE_EN | BIT_EN_SYN);
+
+	xtal_cap = rtwdev->efuse.crystal_cap & 0x3F;
+	rtw_write32_mask(rtwdev, REG_AFE_CTRL3, BIT_MASK_XTAL,
+			 xtal_cap | (xtal_cap << 6));
+	rtw_write32_set(rtwdev, REG_FPGA0_RFMOD, BIT_CCKEN | BIT_OFDMEN);
+	if ((rtwdev->efuse.afe >> 4) == 14) {
+		rtw_write32_set(rtwdev, REG_AFE_CTRL3, BIT_XTAL_GMP_BIT4);
+		rtw_write32_clr(rtwdev, REG_AFE_CTRL1, BITS_PLL);
+		rtw_write32_set(rtwdev, REG_LDO_SWR_CTRL, BIT_XTA1);
+		rtw_write32_clr(rtwdev, REG_LDO_SWR_CTRL, BIT_XTA0);
+	}
+
+	rtw_write8(rtwdev, REG_SLOT, WLAN_SLOT_TIME);
+	rtw_write8(rtwdev, REG_FWHW_TXQ_CTRL + 1, WLAN_TXQ_RPT_EN);
+	rtw_write16(rtwdev, REG_RETRY_LIMIT, WLAN_RL_VAL);
+	rtw_write32(rtwdev, REG_BAR_MODE_CTRL, WLAN_BAR_VAL);
+	rtw_write8(rtwdev, REG_ATIMWND, 0x2);
+	rtw_write8(rtwdev, REG_BCN_CTRL,
+		   BIT_DIS_TSF_UDT | BIT_EN_BCN_FUNCTION | BIT_EN_TXBCN_RPT);
+	val32 = rtw_read32(rtwdev, REG_TBTT_PROHIBIT);
+	val32 &= ~BIT_MASK_TBTT_MASK;
+	val32 |= WLAN_TBTT_TIME_STOP_BCN;
+	rtw_write8(rtwdev, REG_TBTT_PROHIBIT, val32);
+	rtw_write8(rtwdev, REG_PIFS, WLAN_PIFS_VAL);
+	rtw_write8(rtwdev, REG_AGGR_BREAK_TIME, WLAN_AGG_BRK_TIME);
+	rtw_write16(rtwdev, REG_NAV_PROT_LEN, WLAN_NAV_PROT_LEN);
+	rtw_write16(rtwdev, REG_MAC_SPEC_SIFS, WLAN_SPEC_SIFS);
+	rtw_write16(rtwdev, REG_SIFS, WLAN_SPEC_SIFS);
+	rtw_write16(rtwdev, REG_SIFS + 2, WLAN_SPEC_SIFS);
+	rtw_write8(rtwdev, REG_SINGLE_AMPDU_CTRL, BIT_EN_SINGLE_APMDU);
+	rtw_write8(rtwdev, REG_RX_PKT_LIMIT, WLAN_RX_PKT_LIMIT);
+	rtw_write8(rtwdev, REG_MAX_AGGR_NUM, WLAN_MAX_AGG_NR);
+	rtw_write8(rtwdev, REG_AMPDU_MAX_TIME, WLAN_AMPDU_MAX_TIME);
+	rtw_write8(rtwdev, REG_LEDCFG2, WLAN_ANT_SEL);
+
+	rtw_write32(rtwdev, REG_LTR_IDLE_LATENCY, WLAN_LTR_IDLE_LAT);
+	rtw_write32(rtwdev, REG_LTR_ACTIVE_LATENCY, WLAN_LTR_ACT_LAT);
+	rtw_write32(rtwdev, REG_LTR_CTRL_BASIC, WLAN_LTR_CTRL1);
+	rtw_write32(rtwdev, REG_LTR_CTRL_BASIC + 4, WLAN_LTR_CTRL2);
+
+	rtw_phy_init(rtwdev);
+
+	rtw_write16_set(rtwdev, REG_TXDMA_OFFSET_CHK, BIT_DROP_DATA_EN);
+
+	rtw8723d_lck(rtwdev);
+
+	rtw_write32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0, 0x50);
+	rtw_write32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0, 0x20);
+
+	rtw8723d_pwrtrack_init(rtwdev);
+}
+
+static void rtw8723de_efuse_parsing(struct rtw_efuse *efuse,
+				    struct rtw8723d_efuse *map)
+{
+	ether_addr_copy(efuse->addr, map->e.mac_addr);
+}
+
+static int rtw8723d_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
+{
+	struct rtw_efuse *efuse = &rtwdev->efuse;
+	struct rtw8723d_efuse *map;
+	int i;
+
+	map = (struct rtw8723d_efuse *)log_map;
+
+	efuse->rfe_option = 0;
+	efuse->rf_board_option = map->rf_board_option;
+	efuse->crystal_cap = map->xtal_k;
+	efuse->pa_type_2g = map->pa_type;
+	efuse->lna_type_2g = map->lna_type_2g[0];
+	efuse->channel_plan = map->channel_plan;
+	efuse->country_code[0] = map->country_code[0];
+	efuse->country_code[1] = map->country_code[1];
+	efuse->bt_setting = map->rf_bt_setting;
+	efuse->regd = map->rf_board_option & 0x7;
+	efuse->thermal_meter[0] = map->thermal_meter;
+	efuse->thermal_meter_k = map->thermal_meter;
+	efuse->afe = map->afe;
+
+	for (i = 0; i < 4; i++)
+		efuse->txpwr_idx_table[i] = map->txpwr_idx_table[i];
+
+	switch (rtw_hci_type(rtwdev)) {
+	case RTW_HCI_TYPE_PCIE:
+		rtw8723de_efuse_parsing(efuse, map);
+		break;
+	default:
+		/* unsupported now */
+		return -ENOTSUPP;
+	}
+
+	return 0;
+}
+
+static void query_phy_status_page0(struct rtw_dev *rtwdev, u8 *phy_status,
+				   struct rtw_rx_pkt_stat *pkt_stat)
+{
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+	s8 min_rx_power = -120;
+	u8 pwdb = GET_PHY_STAT_P0_PWDB(phy_status);
+
+	pkt_stat->rx_power[RF_PATH_A] = pwdb - 97;
+	pkt_stat->rssi = rtw_phy_rf_power_2_rssi(pkt_stat->rx_power, 1);
+	pkt_stat->bw = RTW_CHANNEL_WIDTH_20;
+	pkt_stat->signal_power = max(pkt_stat->rx_power[RF_PATH_A],
+				     min_rx_power);
+	dm_info->rssi[RF_PATH_A] = pkt_stat->rssi;
+}
+
+static void query_phy_status_page1(struct rtw_dev *rtwdev, u8 *phy_status,
+				   struct rtw_rx_pkt_stat *pkt_stat)
+{
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+	u8 rxsc, bw;
+	s8 min_rx_power = -120;
+	s8 rx_evm;
+
+	if (pkt_stat->rate > DESC_RATE11M && pkt_stat->rate < DESC_RATEMCS0)
+		rxsc = GET_PHY_STAT_P1_L_RXSC(phy_status);
+	else
+		rxsc = GET_PHY_STAT_P1_HT_RXSC(phy_status);
+
+	if (GET_PHY_STAT_P1_RF_MODE(phy_status) == 0)
+		bw = RTW_CHANNEL_WIDTH_20;
+	else if ((rxsc == 1) || (rxsc == 2))
+		bw = RTW_CHANNEL_WIDTH_20;
+	else
+		bw = RTW_CHANNEL_WIDTH_40;
+
+	pkt_stat->rx_power[RF_PATH_A] = GET_PHY_STAT_P1_PWDB_A(phy_status) - 110;
+	pkt_stat->rssi = rtw_phy_rf_power_2_rssi(pkt_stat->rx_power, 1);
+	pkt_stat->bw = bw;
+	pkt_stat->signal_power = max(pkt_stat->rx_power[RF_PATH_A],
+				     min_rx_power);
+	pkt_stat->rx_evm[RF_PATH_A] = GET_PHY_STAT_P1_RXEVM_A(phy_status);
+	pkt_stat->rx_snr[RF_PATH_A] = GET_PHY_STAT_P1_RXSNR_A(phy_status);
+	pkt_stat->cfo_tail[RF_PATH_A] = GET_PHY_STAT_P1_CFO_TAIL_A(phy_status);
+
+	dm_info->curr_rx_rate = pkt_stat->rate;
+	dm_info->rssi[RF_PATH_A] = pkt_stat->rssi;
+	dm_info->rx_snr[RF_PATH_A] = pkt_stat->rx_snr[RF_PATH_A] >> 1;
+	dm_info->cfo_tail[RF_PATH_A] = (pkt_stat->cfo_tail[RF_PATH_A] * 5) >> 1;
+
+	rx_evm = clamp_t(s8, -pkt_stat->rx_evm[RF_PATH_A] >> 1, 0, 64);
+	rx_evm &= 0x3F;	/* 64->0: second path of 1SS rate is 64 */
+	dm_info->rx_evm_dbm[RF_PATH_A] = rx_evm;
+}
+
+static void query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status,
+			     struct rtw_rx_pkt_stat *pkt_stat)
+{
+	u8 page;
+
+	page = *phy_status & 0xf;
+
+	switch (page) {
+	case 0:
+		query_phy_status_page0(rtwdev, phy_status, pkt_stat);
+		break;
+	case 1:
+		query_phy_status_page1(rtwdev, phy_status, pkt_stat);
+		break;
+	default:
+		rtw_warn(rtwdev, "unused phy status page (%d)\n", page);
+		return;
+	}
+}
+
+static void rtw8723d_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc,
+				   struct rtw_rx_pkt_stat *pkt_stat,
+				   struct ieee80211_rx_status *rx_status)
+{
+	struct ieee80211_hdr *hdr;
+	u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz;
+	u8 *phy_status = NULL;
+
+	memset(pkt_stat, 0, sizeof(*pkt_stat));
+
+	pkt_stat->phy_status = GET_RX_DESC_PHYST(rx_desc);
+	pkt_stat->icv_err = GET_RX_DESC_ICV_ERR(rx_desc);
+	pkt_stat->crc_err = GET_RX_DESC_CRC32(rx_desc);
+	pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc) &&
+			      GET_RX_DESC_ENC_TYPE(rx_desc) != RX_DESC_ENC_NONE;
+	pkt_stat->is_c2h = GET_RX_DESC_C2H(rx_desc);
+	pkt_stat->pkt_len = GET_RX_DESC_PKT_LEN(rx_desc);
+	pkt_stat->drv_info_sz = GET_RX_DESC_DRV_INFO_SIZE(rx_desc);
+	pkt_stat->shift = GET_RX_DESC_SHIFT(rx_desc);
+	pkt_stat->rate = GET_RX_DESC_RX_RATE(rx_desc);
+	pkt_stat->cam_id = GET_RX_DESC_MACID(rx_desc);
+	pkt_stat->ppdu_cnt = 0;
+	pkt_stat->tsf_low = GET_RX_DESC_TSFL(rx_desc);
+
+	/* drv_info_sz is in unit of 8-bytes */
+	pkt_stat->drv_info_sz *= 8;
+
+	/* c2h cmd pkt's rx/phy status is not interested */
+	if (pkt_stat->is_c2h)
+		return;
+
+	hdr = (struct ieee80211_hdr *)(rx_desc + desc_sz + pkt_stat->shift +
+				       pkt_stat->drv_info_sz);
+	if (pkt_stat->phy_status) {
+		phy_status = rx_desc + desc_sz + pkt_stat->shift;
+		query_phy_status(rtwdev, phy_status, pkt_stat);
+	}
+
+	rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status, phy_status);
+}
+
+static
+bool rtw8723d_check_spur_ov_thres(struct rtw_dev *rtwdev, u8 channel, u32 thres)
+{
+#define DIS_3WIRE	0xccf000c0
+#define EN_3WIRE	0xccc000c0
+#define START_PSD	0x400000
+#define FREQ_CH13	0xFCCD
+#define FREQ_CH14	0xFF9A
+
+	u32 freq;
+	bool ret = false;
+
+	if (channel == 13)
+		freq = FREQ_CH13;
+	else if (channel == 14)
+		freq = FREQ_CH14;
+	else
+		return false;
+
+	rtw_write32(rtwdev, REG_ANALOG_P4, DIS_3WIRE);
+	rtw_write32(rtwdev, REG_PSDFN, freq);
+	rtw_write32(rtwdev, REG_PSDFN, START_PSD | freq);
+
+	msleep(30);
+	if (rtw_read32(rtwdev, REG_PSDRPT) >= thres)
+		ret = true;
+
+	rtw_write32(rtwdev, REG_PSDFN, freq);
+	rtw_write32(rtwdev, REG_ANALOG_P4, EN_3WIRE);
+
+	return ret;
+}
+
+static void rtw8723d_cfg_notch(struct rtw_dev *rtwdev, u8 channel, bool notch)
+{
+#define BIT_MASK_RXDSP	(BIT(28) | BIT(27) | BIT(26) | BIT(25) | BIT(24))
+#define BIT_EN_RXDSP	BIT(9)
+#define BIT_EN_CFOTRK	BIT(28)
+
+	if (!notch)
+		goto no_notch;
+
+	switch (channel) {
+	case 13:
+		rtw_write32_mask(rtwdev, REG_OFDM0_RXDSP, BIT_MASK_RXDSP, 0xB);
+		rtw_write32_mask(rtwdev, REG_OFDM0_RXDSP, BIT_EN_RXDSP, 0x1);
+		rtw_write32(rtwdev, REG_OFDM1_CSI1, 0x04000000);
+		rtw_write32(rtwdev, REG_OFDM1_CSI2, 0x00000000);
+		rtw_write32(rtwdev, REG_OFDM1_CSI3, 0x00000000);
+		rtw_write32(rtwdev, REG_OFDM1_CSI4, 0x00000000);
+		rtw_write32_mask(rtwdev, REG_OFDM1_CFOTRK, BIT_EN_CFOTRK, 0x1);
+		break;
+	case 14:
+		rtw_write32_mask(rtwdev, REG_OFDM0_RXDSP, BIT_MASK_RXDSP, 0x5);
+		rtw_write32_mask(rtwdev, REG_OFDM0_RXDSP, BIT_EN_RXDSP, 0x1);
+		rtw_write32(rtwdev, REG_OFDM1_CSI1, 0x00000000);
+		rtw_write32(rtwdev, REG_OFDM1_CSI2, 0x00000000);
+		rtw_write32(rtwdev, REG_OFDM1_CSI3, 0x00000000);
+		rtw_write32(rtwdev, REG_OFDM1_CSI4, 0x00080000);
+		rtw_write32_mask(rtwdev, REG_OFDM1_CFOTRK, BIT_EN_CFOTRK, 0x1);
+		break;
+	default:
+		rtw_write32_mask(rtwdev, REG_OFDM0_RXDSP, BIT_EN_RXDSP, 0x0);
+		rtw_write32_mask(rtwdev, REG_OFDM1_CFOTRK, BIT_EN_CFOTRK, 0x0);
+		break;
+	}
+
+	return;
+
+no_notch:
+	rtw_write32_mask(rtwdev, REG_OFDM0_RXDSP, BIT_MASK_RXDSP, 0x1f);
+	rtw_write32_mask(rtwdev, REG_OFDM0_RXDSP, BIT_EN_RXDSP, 0x0);
+	rtw_write32(rtwdev, REG_OFDM1_CSI1, 0x00000000);
+	rtw_write32(rtwdev, REG_OFDM1_CSI2, 0x00000000);
+	rtw_write32(rtwdev, REG_OFDM1_CSI3, 0x00000000);
+	rtw_write32(rtwdev, REG_OFDM1_CSI4, 0x00000000);
+	rtw_write32_mask(rtwdev, REG_OFDM1_CFOTRK, BIT_EN_CFOTRK, 0x0);
+}
+
+static void rtw8723d_spur_cal(struct rtw_dev *rtwdev, u8 channel)
+{
+#define SPUR_THRES	0x16
+	bool notch = false;
+
+	if (channel < 13)
+		goto do_notch;
+
+	notch = rtw8723d_check_spur_ov_thres(rtwdev, channel, SPUR_THRES);
+
+do_notch:
+	rtw8723d_cfg_notch(rtwdev, channel, notch);
+}
+
+static void rtw8723d_set_channel_rf(struct rtw_dev *rtwdev, u8 channel, u8 bw)
+{
+#define RFCFGCH_CHANNEL_MASK	GENMASK(7, 0)
+#define RFCFGCH_BW_MASK		(BIT(11) | BIT(10))
+#define RFCFGCH_BW_20M		(BIT(11) | BIT(10))
+#define RFCFGCH_BW_40M		(BIT(10))
+
+	u32 rf_cfgch[2];
+
+	rf_cfgch[0] = rtw_read_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK);
+	rf_cfgch[1] = rtw_read_rf(rtwdev, RF_PATH_B, RF_CFGCH, RFREG_MASK);
+
+	rf_cfgch[0] &= ~RFCFGCH_CHANNEL_MASK;
+	rf_cfgch[1] &= ~RFCFGCH_CHANNEL_MASK;
+	rf_cfgch[0] |= (channel & RFCFGCH_CHANNEL_MASK);
+	rf_cfgch[1] |= (channel & RFCFGCH_CHANNEL_MASK);
+
+	rf_cfgch[0] &= ~RFCFGCH_BW_MASK;
+	switch (bw) {
+	case RTW_CHANNEL_WIDTH_20:
+		rf_cfgch[0] |= RFCFGCH_BW_20M;
+		break;
+	case RTW_CHANNEL_WIDTH_40:
+		rf_cfgch[0] |= RFCFGCH_BW_40M;
+		break;
+	default:
+		break;
+	}
+
+	rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK, rf_cfgch[0]);
+	rtw_write_rf(rtwdev, RF_PATH_B, RF_CFGCH, RFREG_MASK, rf_cfgch[1]);
+
+	rtw8723d_spur_cal(rtwdev, channel);
+}
+
+#define CCK_DFIR_NR	3
+static const struct rtw_backup_info cck_dfir_cfg[][CCK_DFIR_NR] = {
+	[0] = {
+		{ .len = 4, .reg = 0xA24, .val = 0x64B80C1C },
+		{ .len = 4, .reg = 0xA28, .val = 0x00008810 },
+		{ .len = 4, .reg = 0xAAC, .val = 0x01235667 },
+	},
+	[1] = {
+		{ .len = 4, .reg = 0xA24, .val = 0x0000B81C },
+		{ .len = 4, .reg = 0xA28, .val = 0x00000000 },
+		{ .len = 4, .reg = 0xAAC, .val = 0x00003667 },
+	},
+};
+
+static void rtw8723d_set_channel_bb(struct rtw_dev *rtwdev, u8 channel, u8 bw,
+				    u8 primary_ch_idx)
+{
+#define BIT_CCK_SIDE_BAND	BIT(4)
+#define BIT_MASK_RFMOD		BIT(0)
+#define BIT_RXBB_DFIR_EN	BIT(19)
+#define BIT_MASK_RXBB_DFIR	(BIT(27) | BIT(26) | BIT(25) | BIT(24))
+
+	const struct rtw_backup_info *cck_dfir =
+			channel <= 13 ? cck_dfir_cfg[0] : cck_dfir_cfg[1];
+	int i;
+
+	for (i = 0; i < CCK_DFIR_NR; i++, cck_dfir++)
+		rtw_write32(rtwdev, cck_dfir->reg, cck_dfir->val);
+
+	switch (bw) {
+	case RTW_CHANNEL_WIDTH_20:
+		rtw_write32_mask(rtwdev, REG_FPGA0_RFMOD, BIT_MASK_RFMOD, 0x0);
+		rtw_write32_mask(rtwdev, REG_FPGA1_RFMOD, BIT_MASK_RFMOD, 0x0);
+		rtw_write32_mask(rtwdev, REG_BBRX_DFIR, BIT_RXBB_DFIR_EN, 1);
+		rtw_write32_mask(rtwdev, REG_BBRX_DFIR, BIT_MASK_RXBB_DFIR, 0xa);
+		break;
+	case RTW_CHANNEL_WIDTH_40:
+		rtw_write32_mask(rtwdev, REG_FPGA0_RFMOD, BIT_MASK_RFMOD, 0x1);
+		rtw_write32_mask(rtwdev, REG_FPGA1_RFMOD, BIT_MASK_RFMOD, 0x1);
+		rtw_write32_mask(rtwdev, REG_BBRX_DFIR, BIT_RXBB_DFIR_EN, 0);
+		rtw_write32_mask(rtwdev, REG_CCK0_SYS, BIT_CCK_SIDE_BAND,
+				 (primary_ch_idx == RTW_SC_20_UPPER ? 1 : 0));
+		break;
+	default:
+		break;
+	}
+}
+
+static void rtw8723d_set_channel(struct rtw_dev *rtwdev, u8 channel, u8 bw,
+				 u8 primary_chan_idx)
+{
+	rtw8723d_set_channel_rf(rtwdev, channel, bw);
+	rtw_set_channel_mac(rtwdev, channel, bw, primary_chan_idx);
+	rtw8723d_set_channel_bb(rtwdev, channel, bw, primary_chan_idx);
+}
+
+#define BIT_CFENDFORM		BIT(9)
+#define BIT_WMAC_TCR_ERR0	BIT(12)
+#define BIT_WMAC_TCR_ERR1	BIT(13)
+#define BIT_TCR_CFG		(BIT_CFENDFORM | BIT_WMAC_TCR_ERR0 |	       \
+				 BIT_WMAC_TCR_ERR1)
+#define WLAN_RX_FILTER0		0xFFFF
+#define WLAN_RX_FILTER1		0x400
+#define WLAN_RX_FILTER2		0xFFFF
+#define WLAN_RCR_CFG		0x700060CE
+
+static int rtw8723d_mac_init(struct rtw_dev *rtwdev)
+{
+	rtw_write8(rtwdev, REG_FWHW_TXQ_CTRL + 1, WLAN_TXQ_RPT_EN);
+	rtw_write32(rtwdev, REG_TCR, BIT_TCR_CFG);
+
+	rtw_write16(rtwdev, REG_RXFLTMAP0, WLAN_RX_FILTER0);
+	rtw_write16(rtwdev, REG_RXFLTMAP1, WLAN_RX_FILTER1);
+	rtw_write16(rtwdev, REG_RXFLTMAP2, WLAN_RX_FILTER2);
+	rtw_write32(rtwdev, REG_RCR, WLAN_RCR_CFG);
+
+	rtw_write32(rtwdev, REG_INT_MIG, 0);
+	rtw_write32(rtwdev, REG_MCUTST_1, 0x0);
+
+	rtw_write8(rtwdev, REG_MISC_CTRL, BIT_DIS_SECOND_CCA);
+	rtw_write8(rtwdev, REG_2ND_CCA_CTRL, 0);
+
+	return 0;
+}
+
+static void rtw8723d_shutdown(struct rtw_dev *rtwdev)
+{
+	rtw_write16_set(rtwdev, REG_HCI_OPT_CTRL, BIT_USB_SUS_DIS);
+}
+
+static void rtw8723d_cfg_ldo25(struct rtw_dev *rtwdev, bool enable)
+{
+	u8 ldo_pwr;
+
+	ldo_pwr = rtw_read8(rtwdev, REG_LDO_EFUSE_CTRL + 3);
+	if (enable) {
+		ldo_pwr &= ~BIT_MASK_LDO25_VOLTAGE;
+		ldo_pwr = (BIT_LDO25_VOLTAGE_V25 << 4) | BIT_LDO25_EN;
+	} else {
+		ldo_pwr &= ~BIT_LDO25_EN;
+	}
+	rtw_write8(rtwdev, REG_LDO_EFUSE_CTRL + 3, ldo_pwr);
+}
+
+static void
+rtw8723d_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path, u8 rs)
+{
+	struct rtw_hal *hal = &rtwdev->hal;
+	const struct rtw_hw_reg *txagc;
+	u8 rate, pwr_index;
+	int j;
+
+	for (j = 0; j < rtw_rate_size[rs]; j++) {
+		rate = rtw_rate_section[rs][j];
+		pwr_index = hal->tx_pwr_tbl[path][rate];
+
+		if (rate >= ARRAY_SIZE(rtw8723d_txagc)) {
+			rtw_warn(rtwdev, "rate 0x%x isn't supported\n", rate);
+			continue;
+		}
+		txagc = &rtw8723d_txagc[rate];
+		if (!txagc->addr) {
+			rtw_warn(rtwdev, "rate 0x%x isn't defined\n", rate);
+			continue;
+		}
+
+		rtw_write32_mask(rtwdev, txagc->addr, txagc->mask, pwr_index);
+	}
+}
+
+static void rtw8723d_set_tx_power_index(struct rtw_dev *rtwdev)
+{
+	struct rtw_hal *hal = &rtwdev->hal;
+	int rs, path;
+
+	for (path = 0; path < hal->rf_path_num; path++) {
+		for (rs = 0; rs <= RTW_RATE_SECTION_HT_1S; rs++)
+			rtw8723d_set_tx_power_index_by_rate(rtwdev, path, rs);
+	}
+}
+
+static void rtw8723d_efuse_grant(struct rtw_dev *rtwdev, bool on)
+{
+	if (on) {
+		rtw_write8(rtwdev, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON);
+
+		rtw_write16_set(rtwdev, REG_SYS_FUNC_EN, BIT_FEN_ELDR);
+		rtw_write16_set(rtwdev, REG_SYS_CLKR, BIT_LOADER_CLK_EN | BIT_ANA8M);
+	} else {
+		rtw_write8(rtwdev, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF);
+	}
+}
+
+static void rtw8723d_false_alarm_statistics(struct rtw_dev *rtwdev)
+{
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+	u32 cck_fa_cnt;
+	u32 ofdm_fa_cnt;
+	u32 crc32_cnt;
+	u32 val32;
+
+	/* hold counter */
+	rtw_write32_mask(rtwdev, REG_OFDM_FA_HOLDC_11N, BIT_MASK_OFDM_FA_KEEP, 1);
+	rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTD_11N, BIT_MASK_OFDM_FA_KEEP1, 1);
+	rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_CNT_KEEP, 1);
+	rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_FA_KEEP, 1);
+
+	cck_fa_cnt = rtw_read32_mask(rtwdev, REG_CCK_FA_LSB_11N, MASKBYTE0);
+	cck_fa_cnt += rtw_read32_mask(rtwdev, REG_CCK_FA_MSB_11N, MASKBYTE3) << 8;
+
+	val32 = rtw_read32(rtwdev, REG_OFDM_FA_TYPE1_11N);
+	ofdm_fa_cnt = u32_get_bits(val32, BIT_MASK_OFDM_FF_CNT);
+	ofdm_fa_cnt += u32_get_bits(val32, BIT_MASK_OFDM_SF_CNT);
+	val32 = rtw_read32(rtwdev, REG_OFDM_FA_TYPE2_11N);
+	dm_info->ofdm_cca_cnt = u32_get_bits(val32, BIT_MASK_OFDM_CCA_CNT);
+	ofdm_fa_cnt += u32_get_bits(val32, BIT_MASK_OFDM_PF_CNT);
+	val32 = rtw_read32(rtwdev, REG_OFDM_FA_TYPE3_11N);
+	ofdm_fa_cnt += u32_get_bits(val32, BIT_MASK_OFDM_RI_CNT);
+	ofdm_fa_cnt += u32_get_bits(val32, BIT_MASK_OFDM_CRC_CNT);
+	val32 = rtw_read32(rtwdev, REG_OFDM_FA_TYPE4_11N);
+	ofdm_fa_cnt += u32_get_bits(val32, BIT_MASK_OFDM_MNS_CNT);
+
+	dm_info->cck_fa_cnt = cck_fa_cnt;
+	dm_info->ofdm_fa_cnt = ofdm_fa_cnt;
+	dm_info->total_fa_cnt = cck_fa_cnt + ofdm_fa_cnt;
+
+	dm_info->cck_err_cnt = rtw_read32(rtwdev, REG_IGI_C_11N);
+	dm_info->cck_ok_cnt = rtw_read32(rtwdev, REG_IGI_D_11N);
+	crc32_cnt = rtw_read32(rtwdev, REG_OFDM_CRC32_CNT_11N);
+	dm_info->ofdm_err_cnt = u32_get_bits(crc32_cnt, BIT_MASK_OFDM_LCRC_ERR);
+	dm_info->ofdm_ok_cnt = u32_get_bits(crc32_cnt, BIT_MASK_OFDM_LCRC_OK);
+	crc32_cnt = rtw_read32(rtwdev, REG_HT_CRC32_CNT_11N);
+	dm_info->ht_err_cnt = u32_get_bits(crc32_cnt, BIT_MASK_HT_CRC_ERR);
+	dm_info->ht_ok_cnt = u32_get_bits(crc32_cnt, BIT_MASK_HT_CRC_OK);
+	dm_info->vht_err_cnt = 0;
+	dm_info->vht_ok_cnt = 0;
+
+	val32 = rtw_read32(rtwdev, REG_CCK_CCA_CNT_11N);
+	dm_info->cck_cca_cnt = (u32_get_bits(val32, BIT_MASK_CCK_FA_MSB) << 8) |
+			       u32_get_bits(val32, BIT_MASK_CCK_FA_LSB);
+	dm_info->total_cca_cnt = dm_info->cck_cca_cnt + dm_info->ofdm_cca_cnt;
+
+	/* reset counter */
+	rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTC_11N, BIT_MASK_OFDM_FA_RST, 1);
+	rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTC_11N, BIT_MASK_OFDM_FA_RST, 0);
+	rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTD_11N, BIT_MASK_OFDM_FA_RST1, 1);
+	rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTD_11N, BIT_MASK_OFDM_FA_RST1, 0);
+	rtw_write32_mask(rtwdev, REG_OFDM_FA_HOLDC_11N, BIT_MASK_OFDM_FA_KEEP, 0);
+	rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTD_11N, BIT_MASK_OFDM_FA_KEEP1, 0);
+	rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_CNT_KPEN, 0);
+	rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_CNT_KPEN, 2);
+	rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_FA_KPEN, 0);
+	rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_FA_KPEN, 2);
+	rtw_write32_mask(rtwdev, REG_PAGE_F_RST_11N, BIT_MASK_F_RST_ALL, 1);
+	rtw_write32_mask(rtwdev, REG_PAGE_F_RST_11N, BIT_MASK_F_RST_ALL, 0);
+}
+
+#define MAX_TOLERANCE	5
+#define IQK_TX_X_ERR	0x142
+#define IQK_TX_Y_ERR	0x42
+#define IQK_RX_X_UPPER	0x11a
+#define IQK_RX_X_LOWER	0xe6
+#define IQK_RX_Y_LMT	0x1a
+
+static const u32 iqk_adda_regs[] = {
+	0x85c, 0xe6c, 0xe70, 0xe74, 0xe78, 0xe7c, 0xe80, 0xe84, 0xe88, 0xe8c,
+	0xed0, 0xed4, 0xed8, 0xedc, 0xee0, 0xeec
+};
+
+static const u32 iqk_mac8_regs[] = {0x522, 0x550, 0x551};
+static const u32 iqk_mac32_regs[] = {0x40};
+
+static const u32 iqk_bb_regs[] = {
+	0xc04, 0xc08, 0x874, 0xb68, 0xb6c, 0x870, 0x860, 0x864, 0xa04
+};
+
+#define IQK_ADDA_REG_NUM	ARRAY_SIZE(iqk_adda_regs)
+#define IQK_MAC8_REG_NUM	ARRAY_SIZE(iqk_mac8_regs)
+#define IQK_MAC32_REG_NUM	ARRAY_SIZE(iqk_mac32_regs)
+#define IQK_BB_REG_NUM		ARRAY_SIZE(iqk_bb_regs)
+
+struct iqk_backup_regs {
+	u32 adda[IQK_ADDA_REG_NUM];
+	u8 mac8[IQK_MAC8_REG_NUM];
+	u32 mac32[IQK_MAC32_REG_NUM];
+	u32 bb[IQK_BB_REG_NUM];
+
+	u32 lte_path;
+	u32 lte_gnt;
+
+	u8 btg_sel;
+	u32 bb_sel_btg;
+
+	u8 igia;
+	u8 igib;
+};
+
+static void rtw8723d_iqk_backup_regs(struct rtw_dev *rtwdev,
+				     struct iqk_backup_regs *backup)
+{
+	int i;
+
+	for (i = 0; i < IQK_ADDA_REG_NUM; i++)
+		backup->adda[i] = rtw_read32(rtwdev, iqk_adda_regs[i]);
+
+	for (i = 0; i < IQK_MAC8_REG_NUM; i++)
+		backup->mac8[i] = rtw_read8(rtwdev, iqk_mac8_regs[i]);
+	for (i = 0; i < IQK_MAC32_REG_NUM; i++)
+		backup->mac32[i] = rtw_read32(rtwdev, iqk_mac32_regs[i]);
+
+	for (i = 0; i < IQK_BB_REG_NUM; i++)
+		backup->bb[i] = rtw_read32(rtwdev, iqk_bb_regs[i]);
+
+	backup->igia = (u8)rtw_read32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0);
+	backup->igib = (u8)rtw_read32_mask(rtwdev, REG_OFDM0_XBAGC1, MASKBYTE0);
+
+	backup->bb_sel_btg = rtw_read32(rtwdev, REG_BB_SEL_BTG);
+}
+
+static void rtw8723d_iqk_restore_regs(struct rtw_dev *rtwdev,
+				      const struct iqk_backup_regs *backup)
+{
+	int i;
+
+	for (i = 0; i < IQK_ADDA_REG_NUM; i++)
+		rtw_write32(rtwdev, iqk_adda_regs[i], backup->adda[i]);
+
+	for (i = 0; i < IQK_MAC8_REG_NUM; i++)
+		rtw_write8(rtwdev, iqk_mac8_regs[i], backup->mac8[i]);
+	for (i = 0; i < IQK_MAC32_REG_NUM; i++)
+		rtw_write32(rtwdev, iqk_mac32_regs[i], backup->mac32[i]);
+
+	for (i = 0; i < IQK_BB_REG_NUM; i++)
+		rtw_write32(rtwdev, iqk_bb_regs[i], backup->bb[i]);
+
+	rtw_write32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0, 0x50);
+	rtw_write32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0, backup->igia);
+
+	rtw_write32_mask(rtwdev, REG_OFDM0_XBAGC1, MASKBYTE0, 0x50);
+	rtw_write32_mask(rtwdev, REG_OFDM0_XBAGC1, MASKBYTE0, backup->igib);
+
+	rtw_write32(rtwdev, REG_TXIQK_TONE_A_11N, 0x01008c00);
+	rtw_write32(rtwdev, REG_RXIQK_TONE_A_11N, 0x01008c00);
+}
+
+static void rtw8723d_iqk_backup_path_ctrl(struct rtw_dev *rtwdev,
+					  struct iqk_backup_regs *backup)
+{
+	backup->btg_sel = rtw_read8(rtwdev, REG_BTG_SEL);
+	rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] original 0x67 = 0x%x\n",
+		backup->btg_sel);
+}
+
+static void rtw8723d_iqk_config_path_ctrl(struct rtw_dev *rtwdev)
+{
+	rtw_write32_mask(rtwdev, REG_PAD_CTRL1, BIT_BT_BTG_SEL, 0x1);
+	rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] set 0x67 = 0x%x\n",
+		rtw_read32_mask(rtwdev, REG_PAD_CTRL1, MASKBYTE3));
+}
+
+static void rtw8723d_iqk_restore_path_ctrl(struct rtw_dev *rtwdev,
+					   const struct iqk_backup_regs *backup)
+{
+	rtw_write8(rtwdev, REG_BTG_SEL, backup->btg_sel);
+	rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] restore 0x67 = 0x%x\n",
+		rtw_read32_mask(rtwdev, REG_PAD_CTRL1, MASKBYTE3));
+}
+
+static void rtw8723d_iqk_backup_lte_path_gnt(struct rtw_dev *rtwdev,
+					     struct iqk_backup_regs *backup)
+{
+	backup->lte_path = rtw_read32(rtwdev, REG_LTECOEX_PATH_CONTROL);
+	rtw_write32(rtwdev, REG_LTECOEX_CTRL, 0x800f0038);
+	mdelay(1);
+	backup->lte_gnt = rtw_read32(rtwdev, REG_LTECOEX_READ_DATA);
+	rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] OriginalGNT = 0x%x\n",
+		backup->lte_gnt);
+}
+
+static void rtw8723d_iqk_config_lte_path_gnt(struct rtw_dev *rtwdev)
+{
+	rtw_write32(rtwdev, REG_LTECOEX_WRITE_DATA, 0x0000ff00);
+	rtw_write32(rtwdev, REG_LTECOEX_CTRL, 0xc0020038);
+	rtw_write32_mask(rtwdev, REG_LTECOEX_PATH_CONTROL, BIT_LTE_MUX_CTRL_PATH, 0x1);
+}
+
+static void rtw8723d_iqk_restore_lte_path_gnt(struct rtw_dev *rtwdev,
+					      const struct iqk_backup_regs *bak)
+{
+	rtw_write32(rtwdev, REG_LTECOEX_WRITE_DATA, bak->lte_gnt);
+	rtw_write32(rtwdev, REG_LTECOEX_CTRL, 0xc00f0038);
+	rtw_write32(rtwdev, REG_LTECOEX_PATH_CONTROL, bak->lte_path);
+}
+
+struct rtw_8723d_iqk_cfg {
+	const char *name;
+	u32 val_bb_sel_btg;
+	u32 reg_lutwe;
+	u32 val_txiqk_pi;
+	u32 reg_padlut;
+	u32 reg_gaintx;
+	u32 reg_bspad;
+	u32 val_wlint;
+	u32 val_wlsel;
+	u32 val_iqkpts;
+};
+
+static const struct rtw_8723d_iqk_cfg iqk_tx_cfg[PATH_NR] = {
+	[PATH_S1] = {
+		.name = "S1",
+		.val_bb_sel_btg = 0x99000000,
+		.reg_lutwe = RF_LUTWE,
+		.val_txiqk_pi = 0x8214019f,
+		.reg_padlut = RF_LUTDBG,
+		.reg_gaintx = RF_GAINTX,
+		.reg_bspad = RF_BSPAD,
+		.val_wlint = 0xe0d,
+		.val_wlsel = 0x60d,
+		.val_iqkpts = 0xfa000000,
+	},
+	[PATH_S0] = {
+		.name = "S0",
+		.val_bb_sel_btg = 0x99000280,
+		.reg_lutwe = RF_LUTWE2,
+		.val_txiqk_pi = 0x8214018a,
+		.reg_padlut = RF_TXADBG,
+		.reg_gaintx = RF_TRXIQ,
+		.reg_bspad = RF_TXATANK,
+		.val_wlint = 0xe6d,
+		.val_wlsel = 0x66d,
+		.val_iqkpts = 0xf9000000,
+	},
+};
+
+enum {
+	IQK_TX_OK = BIT(0),
+	IQK_RX_OK = BIT(1),
+};
+
+static u8 rtw8723d_iqk_check_tx_failed(struct rtw_dev *rtwdev,
+				       const struct rtw_8723d_iqk_cfg *iqk_cfg)
+{
+	s32 tx_x, tx_y;
+	u32 tx_fail;
+
+	rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] 0xeac = 0x%x\n",
+		rtw_read32(rtwdev, REG_IQK_RES_RY));
+	rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] 0xe94 = 0x%x, 0xe9c = 0x%x\n",
+		rtw_read32(rtwdev, REG_IQK_RES_TX),
+		rtw_read32(rtwdev, REG_IQK_RES_TY));
+	rtw_dbg(rtwdev, RTW_DBG_RFK,
+		"[IQK] 0xe90(before IQK)= 0x%x, 0xe98(afer IQK) = 0x%x\n",
+		rtw_read32(rtwdev, 0xe90),
+		rtw_read32(rtwdev, 0xe98));
+
+	tx_fail = rtw_read32_mask(rtwdev, REG_IQK_RES_RY, BIT_IQK_TX_FAIL);
+	tx_x = rtw_read32_mask(rtwdev, REG_IQK_RES_TX, BIT_MASK_RES_TX);
+	tx_y = rtw_read32_mask(rtwdev, REG_IQK_RES_TY, BIT_MASK_RES_TY);
+
+	if (!tx_fail && tx_x != IQK_TX_X_ERR && tx_y != IQK_TX_Y_ERR)
+		return IQK_TX_OK;
+
+	rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] %s TXIQK is failed\n",
+		iqk_cfg->name);
+
+	return 0;
+}
+
+static u8 rtw8723d_iqk_check_rx_failed(struct rtw_dev *rtwdev,
+				       const struct rtw_8723d_iqk_cfg *iqk_cfg)
+{
+	s32 rx_x, rx_y;
+	u32 rx_fail;
+
+	rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] 0xea4 = 0x%x, 0xeac = 0x%x\n",
+		rtw_read32(rtwdev, REG_IQK_RES_RX),
+		rtw_read32(rtwdev, REG_IQK_RES_RY));
+
+	rtw_dbg(rtwdev, RTW_DBG_RFK,
+		"[IQK] 0xea0(before IQK)= 0x%x, 0xea8(afer IQK) = 0x%x\n",
+		rtw_read32(rtwdev, 0xea0),
+		rtw_read32(rtwdev, 0xea8));
+
+	rx_fail = rtw_read32_mask(rtwdev, REG_IQK_RES_RY, BIT_IQK_RX_FAIL);
+	rx_x = rtw_read32_mask(rtwdev, REG_IQK_RES_RX, BIT_MASK_RES_RX);
+	rx_y = rtw_read32_mask(rtwdev, REG_IQK_RES_RY, BIT_MASK_RES_RY);
+	rx_y = abs(iqkxy_to_s32(rx_y));
+
+	if (!rx_fail && rx_x < IQK_RX_X_UPPER && rx_x > IQK_RX_X_LOWER &&
+	    rx_y < IQK_RX_Y_LMT)
+		return IQK_RX_OK;
+
+	rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] %s RXIQK STEP2 is failed\n",
+		iqk_cfg->name);
+
+	return 0;
+}
+
+static void rtw8723d_iqk_one_shot(struct rtw_dev *rtwdev, bool tx,
+				  const struct rtw_8723d_iqk_cfg *iqk_cfg)
+{
+	u32 pts = (tx ? iqk_cfg->val_iqkpts : 0xf9000000);
+
+	/* enter IQK mode */
+	rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, EN_IQK);
+	rtw8723d_iqk_config_lte_path_gnt(rtwdev);
+
+	rtw_write32(rtwdev, REG_LTECOEX_CTRL, 0x800f0054);
+	mdelay(1);
+	rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] GNT_BT @%s %sIQK1 = 0x%x\n",
+		iqk_cfg->name, tx ? "TX" : "RX",
+		rtw_read32(rtwdev, REG_LTECOEX_READ_DATA));
+	rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] 0x948 @%s %sIQK1 = 0x%x\n",
+		iqk_cfg->name, tx ? "TX" : "RX",
+		rtw_read32(rtwdev, REG_BB_SEL_BTG));
+
+	/* One shot, LOK & IQK */
+	rtw_write32(rtwdev, REG_IQK_AGC_PTS_11N, pts);
+	rtw_write32(rtwdev, REG_IQK_AGC_PTS_11N, 0xf8000000);
+
+	if (!check_hw_ready(rtwdev, REG_IQK_RES_RY, BIT_IQK_DONE, 1))
+		rtw_warn(rtwdev, "%s %s IQK isn't done\n", iqk_cfg->name,
+			 tx ? "TX" : "RX");
+}
+
+static void rtw8723d_iqk_txrx_path_post(struct rtw_dev *rtwdev,
+					const struct rtw_8723d_iqk_cfg *iqk_cfg,
+					const struct iqk_backup_regs *backup)
+{
+	rtw8723d_iqk_restore_lte_path_gnt(rtwdev, backup);
+	rtw_write32(rtwdev, REG_BB_SEL_BTG, backup->bb_sel_btg);
+
+	/* leave IQK mode */
+	rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, RST_IQK);
+	mdelay(1);
+	rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_padlut, 0x800, 0x0);
+	rtw_write_rf(rtwdev, RF_PATH_A, RF_WLINT, BIT(0), 0x0);
+	rtw_write_rf(rtwdev, RF_PATH_A, RF_WLSEL, BIT(0), 0x0);
+}
+
+static u8 rtw8723d_iqk_tx_path(struct rtw_dev *rtwdev,
+			       const struct rtw_8723d_iqk_cfg *iqk_cfg,
+			       const struct iqk_backup_regs *backup)
+{
+	u8 result = 0x00;
+
+	rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path %s TXIQK!!\n", iqk_cfg->name);
+	rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] 0x67 @%s TXIQK = 0x%x\n",
+		iqk_cfg->name,
+		rtw_read32_mask(rtwdev, REG_PAD_CTRL1, MASKBYTE3));
+
+	rtw_write32(rtwdev, REG_BB_SEL_BTG, iqk_cfg->val_bb_sel_btg);
+	rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, RST_IQK);
+	mdelay(1);
+	rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_lutwe, RFREG_MASK, 0x80000);
+	rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x00004);
+	rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD1, RFREG_MASK, 0x0005d);
+	rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0xBFFE0);
+	rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_lutwe, RFREG_MASK, 0x00000);
+
+	/* IQK setting */
+	rtw_write32(rtwdev, REG_TXIQK_TONE_A_11N, 0x08008c0c);
+	rtw_write32(rtwdev, REG_RXIQK_TONE_A_11N, 0x38008c1c);
+	rtw_write32(rtwdev, REG_TXIQK_PI_A_11N, iqk_cfg->val_txiqk_pi);
+	rtw_write32(rtwdev, REG_RXIQK_PI_A_11N, 0x28160200);
+	rtw_write32(rtwdev, REG_TXIQK_11N, 0x01007c00);
+	rtw_write32(rtwdev, REG_RXIQK_11N, 0x01004800);
+
+	/* LOK setting */
+	rtw_write32(rtwdev, REG_IQK_AGC_RSP_11N, 0x00462911);
+
+	/* PA, PAD setting */
+	rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_padlut, 0x800, 0x1);
+	rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_gaintx, 0x600, 0x0);
+	rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_gaintx, 0x1E0, 0x3);
+	rtw_write_rf(rtwdev, RF_PATH_A, RF_RXIQGEN, 0x1F, 0xf);
+
+	/* LOK setting for 8723D */
+	rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_lutwe, 0x10, 0x1);
+	rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_bspad, 0x1, 0x1);
+
+	rtw_write_rf(rtwdev, RF_PATH_A, RF_WLINT, RFREG_MASK, iqk_cfg->val_wlint);
+	rtw_write_rf(rtwdev, RF_PATH_A, RF_WLSEL, RFREG_MASK, iqk_cfg->val_wlsel);
+
+	rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] RF0x1 @%s TXIQK = 0x%x\n",
+		iqk_cfg->name,
+		rtw_read_rf(rtwdev, RF_PATH_A, RF_WLINT, RFREG_MASK));
+	rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] RF0x2 @%s TXIQK = 0x%x\n",
+		iqk_cfg->name,
+		rtw_read_rf(rtwdev, RF_PATH_A, RF_WLSEL, RFREG_MASK));
+
+	rtw8723d_iqk_one_shot(rtwdev, true, iqk_cfg);
+	result |= rtw8723d_iqk_check_tx_failed(rtwdev, iqk_cfg);
+
+	rtw8723d_iqk_txrx_path_post(rtwdev, iqk_cfg, backup);
+
+	return result;
+}
+
+static u8 rtw8723d_iqk_rx_path(struct rtw_dev *rtwdev,
+			       const struct rtw_8723d_iqk_cfg *iqk_cfg,
+			       const struct iqk_backup_regs *backup)
+{
+	u32 tx_x, tx_y;
+	u8 result = 0x00;
+
+	rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path %s RXIQK Step1!!\n",
+		iqk_cfg->name);
+	rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] 0x67 @%s RXIQK1 = 0x%x\n",
+		iqk_cfg->name,
+		rtw_read32_mask(rtwdev, REG_PAD_CTRL1, MASKBYTE3));
+	rtw_write32(rtwdev, REG_BB_SEL_BTG, iqk_cfg->val_bb_sel_btg);
+
+	rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, RST_IQK);
+
+	/* IQK setting */
+	rtw_write32(rtwdev, REG_TXIQK_11N, 0x01007c00);
+	rtw_write32(rtwdev, REG_RXIQK_11N, 0x01004800);
+
+	/* path IQK setting */
+	rtw_write32(rtwdev, REG_TXIQK_TONE_A_11N, 0x18008c1c);
+	rtw_write32(rtwdev, REG_RXIQK_TONE_A_11N, 0x38008c1c);
+	rtw_write32(rtwdev, REG_TX_IQK_TONE_B, 0x38008c1c);
+	rtw_write32(rtwdev, REG_RX_IQK_TONE_B, 0x38008c1c);
+	rtw_write32(rtwdev, REG_TXIQK_PI_A_11N, 0x82160000);
+	rtw_write32(rtwdev, REG_RXIQK_PI_A_11N, 0x28160000);
+
+	/* LOK setting */
+	rtw_write32(rtwdev, REG_IQK_AGC_RSP_11N, 0x0046a911);
+
+	/* RXIQK mode */
+	rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_lutwe, RFREG_MASK, 0x80000);
+	rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x00006);
+	rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD1, RFREG_MASK, 0x0005f);
+	rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0xa7ffb);
+	rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_lutwe, RFREG_MASK, 0x00000);
+
+	/* PA/PAD=0 */
+	rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_padlut, 0x800, 0x1);
+	rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_gaintx, 0x600, 0x0);
+	rtw_write_rf(rtwdev, RF_PATH_A, RF_WLINT, RFREG_MASK, iqk_cfg->val_wlint);
+	rtw_write_rf(rtwdev, RF_PATH_A, RF_WLSEL, RFREG_MASK, iqk_cfg->val_wlsel);
+
+	rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] RF0x1@ path %s RXIQK1 = 0x%x\n",
+		iqk_cfg->name,
+		rtw_read_rf(rtwdev, RF_PATH_A, RF_WLINT, RFREG_MASK));
+	rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] RF0x2@ path %s RXIQK1 = 0x%x\n",
+		iqk_cfg->name,
+		rtw_read_rf(rtwdev, RF_PATH_A, RF_WLSEL, RFREG_MASK));
+
+	rtw8723d_iqk_one_shot(rtwdev, false, iqk_cfg);
+	result |= rtw8723d_iqk_check_tx_failed(rtwdev, iqk_cfg);
+
+	if (!result)
+		goto restore;
+
+	tx_x = rtw_read32_mask(rtwdev, REG_IQK_RES_TX, BIT_MASK_RES_TX);
+	tx_y = rtw_read32_mask(rtwdev, REG_IQK_RES_TY, BIT_MASK_RES_TY);
+
+	rtw_write32(rtwdev, REG_TXIQK_11N, BIT_SET_TXIQK_11N(tx_x, tx_y));
+	rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] 0xe40 = 0x%x u4tmp = 0x%x\n",
+		rtw_read32(rtwdev, REG_TXIQK_11N),
+		BIT_SET_TXIQK_11N(tx_x, tx_y));
+
+	rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path %s RXIQK STEP2!!\n",
+		iqk_cfg->name);
+	rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] 0x67 @%s RXIQK2 = 0x%x\n",
+		iqk_cfg->name,
+		rtw_read32_mask(rtwdev, REG_PAD_CTRL1, MASKBYTE3));
+
+	rtw_write32(rtwdev, REG_RXIQK_11N, 0x01004800);
+	rtw_write32(rtwdev, REG_TXIQK_TONE_A_11N, 0x38008c1c);
+	rtw_write32(rtwdev, REG_RXIQK_TONE_A_11N, 0x18008c1c);
+	rtw_write32(rtwdev, REG_TX_IQK_TONE_B, 0x38008c1c);
+	rtw_write32(rtwdev, REG_RX_IQK_TONE_B, 0x38008c1c);
+	rtw_write32(rtwdev, REG_TXIQK_PI_A_11N, 0x82170000);
+	rtw_write32(rtwdev, REG_RXIQK_PI_A_11N, 0x28171400);
+
+	/* LOK setting */
+	rtw_write32(rtwdev, REG_IQK_AGC_RSP_11N, 0x0046a8d1);
+
+	/* RXIQK mode */
+	rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, RST_IQK);
+	mdelay(1);
+	rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_lutwe, 0x80000, 0x1);
+	rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x00007);
+	rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD1, RFREG_MASK, 0x0005f);
+	rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0xb3fdb);
+	rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_lutwe, RFREG_MASK, 0x00000);
+
+	rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] RF0x1 @%s RXIQK2 = 0x%x\n",
+		iqk_cfg->name,
+		rtw_read_rf(rtwdev, RF_PATH_A, RF_WLINT, RFREG_MASK));
+	rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] RF0x2 @%s RXIQK2 = 0x%x\n",
+		iqk_cfg->name,
+		rtw_read_rf(rtwdev, RF_PATH_A, RF_WLSEL, RFREG_MASK));
+
+	rtw8723d_iqk_one_shot(rtwdev, false, iqk_cfg);
+	result |= rtw8723d_iqk_check_rx_failed(rtwdev, iqk_cfg);
+
+restore:
+	rtw8723d_iqk_txrx_path_post(rtwdev, iqk_cfg, backup);
+
+	return result;
+}
+
+static
+void rtw8723d_iqk_fill_s1_matrix(struct rtw_dev *rtwdev, const s32 result[])
+{
+	s32 oldval_1;
+	s32 x, y;
+	s32 tx1_a, tx1_a_ext;
+	s32 tx1_c, tx1_c_ext;
+
+	if (result[IQK_S1_TX_X] == 0)
+		return;
+
+	oldval_1 = rtw_read32_mask(rtwdev, REG_OFDM_0_XA_TX_IQ_IMBALANCE,
+				   BIT_MASK_TXIQ_ELM_D);
+
+	x = iqkxy_to_s32(result[IQK_S1_TX_X]);
+	tx1_a = iqk_mult(x, oldval_1, &tx1_a_ext);
+	rtw_write32_mask(rtwdev, REG_OFDM_0_XA_TX_IQ_IMBALANCE,
+			 BIT_MASK_TXIQ_ELM_A, tx1_a);
+	rtw_write32_mask(rtwdev, REG_OFDM_0_ECCA_THRESHOLD,
+			 BIT_MASK_OFDM0_EXT_A, tx1_a_ext);
+
+	y = iqkxy_to_s32(result[IQK_S1_TX_Y]);
+	tx1_c = iqk_mult(y, oldval_1, &tx1_c_ext);
+	rtw_write32_mask(rtwdev, REG_TXIQK_MATRIXA_LSB2_11N, MASKH4BITS,
+			 BIT_SET_TXIQ_ELM_C1(tx1_c));
+	rtw_write32_mask(rtwdev, REG_OFDM_0_XA_TX_IQ_IMBALANCE,
+			 BIT_MASK_TXIQ_ELM_C, BIT_SET_TXIQ_ELM_C2(tx1_c));
+	rtw_write32_mask(rtwdev, REG_OFDM_0_ECCA_THRESHOLD,
+			 BIT_MASK_OFDM0_EXT_C, tx1_c_ext);
+
+	rtw_dbg(rtwdev, RTW_DBG_RFK,
+		"[IQK] X = 0x%x, TX1_A = 0x%x, oldval_1 0x%x\n",
+		x, tx1_a, oldval_1);
+	rtw_dbg(rtwdev, RTW_DBG_RFK,
+		"[IQK] Y = 0x%x, TX1_C = 0x%x\n", y, tx1_c);
+
+	if (result[IQK_S1_RX_X] == 0)
+		return;
+
+	rtw_write32_mask(rtwdev, REG_A_RXIQI, BIT_MASK_RXIQ_S1_X,
+			 result[IQK_S1_RX_X]);
+	rtw_write32_mask(rtwdev, REG_A_RXIQI, BIT_MASK_RXIQ_S1_Y1,
+			 BIT_SET_RXIQ_S1_Y1(result[IQK_S1_RX_Y]));
+	rtw_write32_mask(rtwdev, REG_RXIQK_MATRIX_LSB_11N, BIT_MASK_RXIQ_S1_Y2,
+			 BIT_SET_RXIQ_S1_Y2(result[IQK_S1_RX_Y]));
+}
+
+static
+void rtw8723d_iqk_fill_s0_matrix(struct rtw_dev *rtwdev, const s32 result[])
+{
+	s32 oldval_0;
+	s32 x, y;
+	s32 tx0_a, tx0_a_ext;
+	s32 tx0_c, tx0_c_ext;
+
+	if (result[IQK_S0_TX_X] == 0)
+		return;
+
+	oldval_0 = rtw_read32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_D_S0);
+
+	x = iqkxy_to_s32(result[IQK_S0_TX_X]);
+	tx0_a = iqk_mult(x, oldval_0, &tx0_a_ext);
+
+	rtw_write32_mask(rtwdev, REG_TXIQ_AB_S0, BIT_MASK_TXIQ_A_S0, tx0_a);
+	rtw_write32_mask(rtwdev, REG_TXIQ_AB_S0, BIT_MASK_TXIQ_A_EXT_S0, tx0_a_ext);
+
+	y = iqkxy_to_s32(result[IQK_S0_TX_Y]);
+	tx0_c = iqk_mult(y, oldval_0, &tx0_c_ext);
+
+	rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_C_S0, tx0_c);
+	rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_C_EXT_S0, tx0_c_ext);
+
+	if (result[IQK_S0_RX_X] == 0)
+		return;
+
+	rtw_write32_mask(rtwdev, REG_RXIQ_AB_S0, BIT_MASK_RXIQ_X_S0,
+			 result[IQK_S0_RX_X]);
+	rtw_write32_mask(rtwdev, REG_RXIQ_AB_S0, BIT_MASK_RXIQ_Y_S0,
+			 result[IQK_S0_RX_Y]);
+}
+
+static void rtw8723d_iqk_path_adda_on(struct rtw_dev *rtwdev)
+{
+	int i;
+
+	for (i = 0; i < IQK_ADDA_REG_NUM; i++)
+		rtw_write32(rtwdev, iqk_adda_regs[i], 0x03c00016);
+}
+
+static void rtw8723d_iqk_config_mac(struct rtw_dev *rtwdev)
+{
+	rtw_write8(rtwdev, REG_TXPAUSE, 0xff);
+}
+
+static
+void rtw8723d_iqk_rf_standby(struct rtw_dev *rtwdev, enum rtw_rf_path path)
+{
+	rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path-%s standby mode!\n",
+		path == RF_PATH_A ? "S1" : "S0");
+
+	rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, RST_IQK);
+	mdelay(1);
+	rtw_write_rf(rtwdev, path, RF_MODE, RFREG_MASK, 0x10000);
+	rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, EN_IQK);
+}
+
+static
+bool rtw8723d_iqk_similarity_cmp(struct rtw_dev *rtwdev, s32 result[][IQK_NR],
+				 u8 c1, u8 c2)
+{
+	u32 i, j, diff;
+	u32 bitmap = 0;
+	u8 candidate[PATH_NR] = {IQK_ROUND_INVALID, IQK_ROUND_INVALID};
+	bool ret = true;
+
+	s32 tmp1, tmp2;
+
+	for (i = 0; i < IQK_NR; i++) {
+		tmp1 = iqkxy_to_s32(result[c1][i]);
+		tmp2 = iqkxy_to_s32(result[c2][i]);
+
+		diff = abs(tmp1 - tmp2);
+
+		if (diff <= MAX_TOLERANCE)
+			continue;
+
+		if ((i == IQK_S1_RX_X || i == IQK_S0_RX_X) && !bitmap) {
+			if (result[c1][i] + result[c1][i + 1] == 0)
+				candidate[i / IQK_SX_NR] = c2;
+			else if (result[c2][i] + result[c2][i + 1] == 0)
+				candidate[i / IQK_SX_NR] = c1;
+			else
+				bitmap |= BIT(i);
+		} else {
+			bitmap |= BIT(i);
+		}
+	}
+
+	if (bitmap != 0)
+		goto check_sim;
+
+	for (i = 0; i < PATH_NR; i++) {
+		if (candidate[i] == IQK_ROUND_INVALID)
+			continue;
+
+		for (j = i * IQK_SX_NR; j < i * IQK_SX_NR + 2; j++)
+			result[IQK_ROUND_HYBRID][j] = result[candidate[i]][j];
+		ret = false;
+	}
+
+	return ret;
+
+check_sim:
+	for (i = 0; i < IQK_NR; i++) {
+		j = i & ~1;	/* 2 bits are a pair for IQ[X, Y] */
+		if (bitmap & GENMASK(j + 1, j))
+			continue;
+
+		result[IQK_ROUND_HYBRID][i] = result[c1][i];
+	}
+
+	return false;
+}
+
+static
+void rtw8723d_iqk_precfg_path(struct rtw_dev *rtwdev, enum rtw8723d_path path)
+{
+	if (path == PATH_S0) {
+		rtw8723d_iqk_rf_standby(rtwdev, RF_PATH_A);
+		rtw8723d_iqk_path_adda_on(rtwdev);
+	}
+
+	rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, EN_IQK);
+	rtw_write32(rtwdev, REG_TXIQK_11N, 0x01007c00);
+	rtw_write32(rtwdev, REG_RXIQK_11N, 0x01004800);
+
+	if (path == PATH_S1) {
+		rtw8723d_iqk_rf_standby(rtwdev, RF_PATH_B);
+		rtw8723d_iqk_path_adda_on(rtwdev);
+	}
+}
+
+#define PATH_IQK_RETRY	2
+
+static
+void rtw8723d_iqk_one_round(struct rtw_dev *rtwdev, s32 result[][IQK_NR], u8 t,
+			    const struct iqk_backup_regs *backup)
+{
+	u32 i;
+	u8 s1_ok, s0_ok;
+
+	rtw_dbg(rtwdev, RTW_DBG_RFK,
+		"[IQK] IQ Calibration for 1T1R_S0/S1 for %d times\n", t);
+
+	rtw8723d_iqk_path_adda_on(rtwdev);
+	rtw8723d_iqk_config_mac(rtwdev);
+	rtw_write32_mask(rtwdev, REG_CCK_ANT_SEL_11N, 0x0f000000, 0xf);
+	rtw_write32(rtwdev, REG_BB_RX_PATH_11N, 0x03a05611);
+	rtw_write32(rtwdev, REG_TRMUX_11N, 0x000800e4);
+	rtw_write32(rtwdev, REG_BB_PWR_SAV1_11N, 0x25204200);
+	rtw8723d_iqk_precfg_path(rtwdev, PATH_S1);
+
+	for (i = 0; i < PATH_IQK_RETRY; i++) {
+		s1_ok = rtw8723d_iqk_tx_path(rtwdev, &iqk_tx_cfg[PATH_S1], backup);
+		if (s1_ok == IQK_TX_OK) {
+			rtw_dbg(rtwdev, RTW_DBG_RFK,
+				"[IQK] path S1 Tx IQK Success!!\n");
+			result[t][IQK_S1_TX_X] =
+			  rtw_read32_mask(rtwdev, REG_IQK_RES_TX, BIT_MASK_RES_TX);
+			result[t][IQK_S1_TX_Y] =
+			  rtw_read32_mask(rtwdev, REG_IQK_RES_TY, BIT_MASK_RES_TY);
+			break;
+		}
+
+		rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path S1 Tx IQK Fail!!\n");
+		result[t][IQK_S1_TX_X] = 0x100;
+		result[t][IQK_S1_TX_Y] = 0x0;
+	}
+
+	for (i = 0; i < PATH_IQK_RETRY; i++) {
+		s1_ok = rtw8723d_iqk_rx_path(rtwdev, &iqk_tx_cfg[PATH_S1], backup);
+		if (s1_ok == (IQK_TX_OK | IQK_RX_OK)) {
+			rtw_dbg(rtwdev, RTW_DBG_RFK,
+				"[IQK] path S1 Rx IQK Success!!\n");
+			result[t][IQK_S1_RX_X] =
+			  rtw_read32_mask(rtwdev, REG_IQK_RES_RX, BIT_MASK_RES_RX);
+			result[t][IQK_S1_RX_Y] =
+			  rtw_read32_mask(rtwdev, REG_IQK_RES_RY, BIT_MASK_RES_RY);
+			break;
+		}
+
+		rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path S1 Rx IQK Fail!!\n");
+		result[t][IQK_S1_RX_X] = 0x100;
+		result[t][IQK_S1_RX_Y] = 0x0;
+	}
+
+	if (s1_ok == 0x0)
+		rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path S1 IQK is failed!!\n");
+
+	rtw8723d_iqk_precfg_path(rtwdev, PATH_S0);
+
+	for (i = 0; i < PATH_IQK_RETRY; i++) {
+		s0_ok = rtw8723d_iqk_tx_path(rtwdev, &iqk_tx_cfg[PATH_S0], backup);
+		if (s0_ok == IQK_TX_OK) {
+			rtw_dbg(rtwdev, RTW_DBG_RFK,
+				"[IQK] path S0 Tx IQK Success!!\n");
+			result[t][IQK_S0_TX_X] =
+			  rtw_read32_mask(rtwdev, REG_IQK_RES_TX, BIT_MASK_RES_TX);
+			result[t][IQK_S0_TX_Y] =
+			  rtw_read32_mask(rtwdev, REG_IQK_RES_TY, BIT_MASK_RES_TY);
+			break;
+		}
+
+		rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path S0 Tx IQK Fail!!\n");
+		result[t][IQK_S0_TX_X] = 0x100;
+		result[t][IQK_S0_TX_Y] = 0x0;
+	}
+
+	for (i = 0; i < PATH_IQK_RETRY; i++) {
+		s0_ok = rtw8723d_iqk_rx_path(rtwdev, &iqk_tx_cfg[PATH_S0], backup);
+		if (s0_ok == (IQK_TX_OK | IQK_RX_OK)) {
+			rtw_dbg(rtwdev, RTW_DBG_RFK,
+				"[IQK] path S0 Rx IQK Success!!\n");
+
+			result[t][IQK_S0_RX_X] =
+			  rtw_read32_mask(rtwdev, REG_IQK_RES_RX, BIT_MASK_RES_RX);
+			result[t][IQK_S0_RX_Y] =
+			  rtw_read32_mask(rtwdev, REG_IQK_RES_RY, BIT_MASK_RES_RY);
+			break;
+		}
+
+		rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path S0 Rx IQK Fail!!\n");
+		result[t][IQK_S0_RX_X] = 0x100;
+		result[t][IQK_S0_RX_Y] = 0x0;
+	}
+
+	if (s0_ok == 0x0)
+		rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path S0 IQK is failed!!\n");
+
+	rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, RST_IQK);
+	mdelay(1);
+
+	rtw_dbg(rtwdev, RTW_DBG_RFK,
+		"[IQK] back to BB mode, load original value!\n");
+}
+
+static void rtw8723d_phy_calibration(struct rtw_dev *rtwdev)
+{
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+	s32 result[IQK_ROUND_SIZE][IQK_NR];
+	struct iqk_backup_regs backup;
+	u8 i, j;
+	u8 final_candidate = IQK_ROUND_INVALID;
+	bool good;
+
+	rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] Start!!!\n");
+
+	memset(result, 0, sizeof(result));
+
+	rtw8723d_iqk_backup_path_ctrl(rtwdev, &backup);
+	rtw8723d_iqk_backup_lte_path_gnt(rtwdev, &backup);
+	rtw8723d_iqk_backup_regs(rtwdev, &backup);
+
+	for (i = IQK_ROUND_0; i <= IQK_ROUND_2; i++) {
+		rtw8723d_iqk_config_path_ctrl(rtwdev);
+		rtw8723d_iqk_config_lte_path_gnt(rtwdev);
+
+		rtw8723d_iqk_one_round(rtwdev, result, i, &backup);
+
+		if (i > IQK_ROUND_0)
+			rtw8723d_iqk_restore_regs(rtwdev, &backup);
+		rtw8723d_iqk_restore_lte_path_gnt(rtwdev, &backup);
+		rtw8723d_iqk_restore_path_ctrl(rtwdev, &backup);
+
+		for (j = IQK_ROUND_0; j < i; j++) {
+			good = rtw8723d_iqk_similarity_cmp(rtwdev, result, j, i);
+
+			if (good) {
+				final_candidate = j;
+				rtw_dbg(rtwdev, RTW_DBG_RFK,
+					"[IQK] cmp %d:%d final_candidate is %x\n",
+					j, i, final_candidate);
+				goto iqk_done;
+			}
+		}
+	}
+
+	if (final_candidate == IQK_ROUND_INVALID) {
+		s32 reg_tmp = 0;
+
+		for (i = 0; i < IQK_NR; i++)
+			reg_tmp += result[IQK_ROUND_HYBRID][i];
+
+		if (reg_tmp != 0) {
+			final_candidate = IQK_ROUND_HYBRID;
+		} else {
+			WARN(1, "IQK is failed\n");
+			goto out;
+		}
+	}
+
+iqk_done:
+	rtw8723d_iqk_fill_s1_matrix(rtwdev, result[final_candidate]);
+	rtw8723d_iqk_fill_s0_matrix(rtwdev, result[final_candidate]);
+
+	dm_info->iqk.result.s1_x = result[final_candidate][IQK_S1_TX_X];
+	dm_info->iqk.result.s1_y = result[final_candidate][IQK_S1_TX_Y];
+	dm_info->iqk.result.s0_x = result[final_candidate][IQK_S0_TX_X];
+	dm_info->iqk.result.s0_y = result[final_candidate][IQK_S0_TX_Y];
+	dm_info->iqk.done = true;
+
+out:
+	rtw_write32(rtwdev, REG_BB_SEL_BTG, backup.bb_sel_btg);
+
+	rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] final_candidate is %x\n",
+		final_candidate);
+
+	for (i = IQK_ROUND_0; i < IQK_ROUND_SIZE; i++)
+		rtw_dbg(rtwdev, RTW_DBG_RFK,
+			"[IQK] Result %u: rege94_s1=%x rege9c_s1=%x regea4_s1=%x regeac_s1=%x rege94_s0=%x rege9c_s0=%x regea4_s0=%x regeac_s0=%x %s\n",
+			i,
+			result[i][0], result[i][1], result[i][2], result[i][3],
+			result[i][4], result[i][5], result[i][6], result[i][7],
+			final_candidate == i ? "(final candidate)" : "");
+
+	rtw_dbg(rtwdev, RTW_DBG_RFK,
+		"[IQK]0xc80 = 0x%x 0xc94 = 0x%x 0xc14 = 0x%x 0xca0 = 0x%x\n",
+		rtw_read32(rtwdev, REG_OFDM_0_XA_TX_IQ_IMBALANCE),
+		rtw_read32(rtwdev, REG_TXIQK_MATRIXA_LSB2_11N),
+		rtw_read32(rtwdev, REG_A_RXIQI),
+		rtw_read32(rtwdev, REG_RXIQK_MATRIX_LSB_11N));
+	rtw_dbg(rtwdev, RTW_DBG_RFK,
+		"[IQK]0xcd0 = 0x%x 0xcd4 = 0x%x 0xcd8 = 0x%x\n",
+		rtw_read32(rtwdev, REG_TXIQ_AB_S0),
+		rtw_read32(rtwdev, REG_TXIQ_CD_S0),
+		rtw_read32(rtwdev, REG_RXIQ_AB_S0));
+
+	rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] finished\n");
+}
+
+/* for coex */
+static void rtw8723d_coex_cfg_init(struct rtw_dev *rtwdev)
+{
+	/* enable TBTT nterrupt */
+	rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);
+
+	/* BT report packet sample rate	 */
+	/* 0x790[5:0]=0x5 */
+	rtw_write8_set(rtwdev, REG_BT_TDMA_TIME, 0x05);
+
+	/* enable BT counter statistics */
+	rtw_write8(rtwdev, REG_BT_STAT_CTRL, 0x1);
+
+	/* enable PTA (3-wire function form BT side) */
+	rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_BT_PTA_EN);
+	rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_BT_AOD_GPIO3);
+
+	/* enable PTA (tx/rx signal form WiFi side) */
+	rtw_write8_set(rtwdev, REG_QUEUE_CTRL, BIT_PTA_WL_TX_EN);
+}
+
+static void rtw8723d_coex_cfg_gnt_fix(struct rtw_dev *rtwdev)
+{
+}
+
+static void rtw8723d_coex_cfg_gnt_debug(struct rtw_dev *rtwdev)
+{
+	rtw_write8_mask(rtwdev, REG_LEDCFG2, BIT(6), 0);
+	rtw_write8_mask(rtwdev, REG_PAD_CTRL1 + 3, BIT(0), 0);
+	rtw_write8_mask(rtwdev, REG_GPIO_INTM + 2, BIT(4), 0);
+	rtw_write8_mask(rtwdev, REG_GPIO_MUXCFG + 2, BIT(1), 0);
+	rtw_write8_mask(rtwdev, REG_PAD_CTRL1 + 3, BIT(1), 0);
+	rtw_write8_mask(rtwdev, REG_PAD_CTRL1 + 2, BIT(7), 0);
+	rtw_write8_mask(rtwdev, REG_SYS_CLKR + 1, BIT(1), 0);
+	rtw_write8_mask(rtwdev, REG_SYS_SDIO_CTRL + 3, BIT(3), 0);
+}
+
+static void rtw8723d_coex_cfg_rfe_type(struct rtw_dev *rtwdev)
+{
+	struct rtw_efuse *efuse = &rtwdev->efuse;
+	struct rtw_coex *coex = &rtwdev->coex;
+	struct rtw_coex_rfe *coex_rfe = &coex->rfe;
+	bool aux = efuse->bt_setting & BIT(6);
+
+	coex_rfe->rfe_module_type = rtwdev->efuse.rfe_option;
+	coex_rfe->ant_switch_polarity = 0;
+	coex_rfe->ant_switch_exist = false;
+	coex_rfe->ant_switch_with_bt = false;
+	coex_rfe->ant_switch_diversity = false;
+	coex_rfe->wlg_at_btg = true;
+
+	/* decide antenna at main or aux */
+	if (efuse->share_ant) {
+		if (aux)
+			rtw_write16(rtwdev, REG_BB_SEL_BTG, 0x80);
+		else
+			rtw_write16(rtwdev, REG_BB_SEL_BTG, 0x200);
+	} else {
+		if (aux)
+			rtw_write16(rtwdev, REG_BB_SEL_BTG, 0x280);
+		else
+			rtw_write16(rtwdev, REG_BB_SEL_BTG, 0x0);
+	}
+
+	/* disable LTE coex in wifi side */
+	rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, BIT_LTE_COEX_EN, 0x0);
+	rtw_coex_write_indirect_reg(rtwdev, LTE_WL_TRX_CTRL, MASKLWORD, 0xffff);
+	rtw_coex_write_indirect_reg(rtwdev, LTE_BT_TRX_CTRL, MASKLWORD, 0xffff);
+}
+
+static void rtw8723d_coex_cfg_wl_tx_power(struct rtw_dev *rtwdev, u8 wl_pwr)
+{
+	struct rtw_coex *coex = &rtwdev->coex;
+	struct rtw_coex_dm *coex_dm = &coex->dm;
+	static const u8	wl_tx_power[] = {0xb2, 0x90};
+	u8 pwr;
+
+	if (wl_pwr == coex_dm->cur_wl_pwr_lvl)
+		return;
+
+	coex_dm->cur_wl_pwr_lvl = wl_pwr;
+
+	if (coex_dm->cur_wl_pwr_lvl >= ARRAY_SIZE(wl_tx_power))
+		coex_dm->cur_wl_pwr_lvl = ARRAY_SIZE(wl_tx_power) - 1;
+
+	pwr = wl_tx_power[coex_dm->cur_wl_pwr_lvl];
+
+	rtw_write8(rtwdev, REG_ANA_PARAM1 + 3, pwr);
+}
+
+static void rtw8723d_coex_cfg_wl_rx_gain(struct rtw_dev *rtwdev, bool low_gain)
+{
+	struct rtw_coex *coex = &rtwdev->coex;
+	struct rtw_coex_dm *coex_dm = &coex->dm;
+	/* WL Rx Low gain on */
+	static const u32 wl_rx_low_gain_on[] = {
+		0xec120101, 0xeb130101, 0xce140101, 0xcd150101, 0xcc160101,
+		0xcb170101, 0xca180101, 0x8d190101, 0x8c1a0101, 0x8b1b0101,
+		0x4f1c0101, 0x4e1d0101, 0x4d1e0101, 0x4c1f0101, 0x0e200101,
+		0x0d210101, 0x0c220101, 0x0b230101, 0xcf240001, 0xce250001,
+		0xcd260001, 0xcc270001, 0x8f280001
+	};
+	/* WL Rx Low gain off */
+	static const u32 wl_rx_low_gain_off[] = {
+		0xec120101, 0xeb130101, 0xea140101, 0xe9150101, 0xe8160101,
+		0xe7170101, 0xe6180101, 0xe5190101, 0xe41a0101, 0xe31b0101,
+		0xe21c0101, 0xe11d0101, 0xe01e0101, 0x861f0101, 0x85200101,
+		0x84210101, 0x83220101, 0x82230101, 0x81240101, 0x80250101,
+		0x44260101, 0x43270101, 0x42280101
+	};
+	u8 i;
+
+	if (low_gain == coex_dm->cur_wl_rx_low_gain_en)
+		return;
+
+	coex_dm->cur_wl_rx_low_gain_en = low_gain;
+
+	if (coex_dm->cur_wl_rx_low_gain_en) {
+		for (i = 0; i < ARRAY_SIZE(wl_rx_low_gain_on); i++)
+			rtw_write32(rtwdev, REG_AGCRSSI, wl_rx_low_gain_on[i]);
+	} else {
+		for (i = 0; i < ARRAY_SIZE(wl_rx_low_gain_off); i++)
+			rtw_write32(rtwdev, REG_AGCRSSI, wl_rx_low_gain_off[i]);
+	}
+}
+
+static u8 rtw8723d_pwrtrack_get_limit_ofdm(struct rtw_dev *rtwdev)
+{
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+	u8 tx_rate = dm_info->tx_rate;
+	u8 limit_ofdm = 30;
+
+	switch (tx_rate) {
+	case DESC_RATE1M...DESC_RATE5_5M:
+	case DESC_RATE11M:
+		break;
+	case DESC_RATE6M...DESC_RATE48M:
+		limit_ofdm = 36;
+		break;
+	case DESC_RATE54M:
+		limit_ofdm = 34;
+		break;
+	case DESC_RATEMCS0...DESC_RATEMCS2:
+		limit_ofdm = 38;
+		break;
+	case DESC_RATEMCS3...DESC_RATEMCS4:
+		limit_ofdm = 36;
+		break;
+	case DESC_RATEMCS5...DESC_RATEMCS7:
+		limit_ofdm = 34;
+		break;
+	default:
+		rtw_warn(rtwdev, "pwrtrack unhandled tx_rate 0x%x\n", tx_rate);
+		break;
+	}
+
+	return limit_ofdm;
+}
+
+static void rtw8723d_set_iqk_matrix_by_result(struct rtw_dev *rtwdev,
+					      u32 ofdm_swing, u8 rf_path)
+{
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+	s32 ele_A, ele_D, ele_C;
+	s32 ele_A_ext, ele_C_ext, ele_D_ext;
+	s32 iqk_result_x;
+	s32 iqk_result_y;
+	s32 value32;
+
+	switch (rf_path) {
+	default:
+	case RF_PATH_A:
+		iqk_result_x = dm_info->iqk.result.s1_x;
+		iqk_result_y = dm_info->iqk.result.s1_y;
+		break;
+	case RF_PATH_B:
+		iqk_result_x = dm_info->iqk.result.s0_x;
+		iqk_result_y = dm_info->iqk.result.s0_y;
+		break;
+	}
+
+	/* new element D */
+	ele_D = OFDM_SWING_D(ofdm_swing);
+	iqk_mult(iqk_result_x, ele_D, &ele_D_ext);
+	/* new element A */
+	iqk_result_x = iqkxy_to_s32(iqk_result_x);
+	ele_A = iqk_mult(iqk_result_x, ele_D, &ele_A_ext);
+	/* new element C */
+	iqk_result_y = iqkxy_to_s32(iqk_result_y);
+	ele_C = iqk_mult(iqk_result_y, ele_D, &ele_C_ext);
+
+	switch (rf_path) {
+	case RF_PATH_A:
+	default:
+		/* write new elements A, C, D, and element B is always 0 */
+		value32 = BIT_SET_TXIQ_ELM_ACD(ele_A, ele_C, ele_D);
+		rtw_write32(rtwdev, REG_OFDM_0_XA_TX_IQ_IMBALANCE, value32);
+		value32 = BIT_SET_TXIQ_ELM_C1(ele_C);
+		rtw_write32_mask(rtwdev, REG_TXIQK_MATRIXA_LSB2_11N, MASKH4BITS,
+				 value32);
+		value32 = rtw_read32(rtwdev, REG_OFDM_0_ECCA_THRESHOLD);
+		value32 &= ~BIT_MASK_OFDM0_EXTS;
+		value32 |= BIT_SET_OFDM0_EXTS(ele_A_ext, ele_C_ext, ele_D_ext);
+		rtw_write32(rtwdev, REG_OFDM_0_ECCA_THRESHOLD, value32);
+		break;
+
+	case RF_PATH_B:
+		/* write new elements A, C, D, and element B is always 0 */
+		rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_D_S0, ele_D);
+		rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_C_S0, ele_C);
+		rtw_write32_mask(rtwdev, REG_TXIQ_AB_S0, BIT_MASK_TXIQ_A_S0, ele_A);
+
+		rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_D_EXT_S0,
+				 ele_D_ext);
+		rtw_write32_mask(rtwdev, REG_TXIQ_AB_S0, BIT_MASK_TXIQ_A_EXT_S0,
+				 ele_A_ext);
+		rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_C_EXT_S0,
+				 ele_C_ext);
+		break;
+	}
+}
+
+static void rtw8723d_set_iqk_matrix(struct rtw_dev *rtwdev, s8 ofdm_index,
+				    u8 rf_path)
+{
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+	s32 value32;
+	u32 ofdm_swing;
+
+	if (ofdm_index >= RTW_OFDM_SWING_TABLE_SIZE)
+		ofdm_index = RTW_OFDM_SWING_TABLE_SIZE - 1;
+	else if (ofdm_index < 0)
+		ofdm_index = 0;
+
+	ofdm_swing = rtw8723d_ofdm_swing_table[ofdm_index];
+
+	if (dm_info->iqk.done) {
+		rtw8723d_set_iqk_matrix_by_result(rtwdev, ofdm_swing, rf_path);
+		return;
+	}
+
+	switch (rf_path) {
+	case RF_PATH_A:
+	default:
+		rtw_write32(rtwdev, REG_OFDM_0_XA_TX_IQ_IMBALANCE, ofdm_swing);
+		rtw_write32_mask(rtwdev, REG_TXIQK_MATRIXA_LSB2_11N, MASKH4BITS,
+				 0x00);
+		value32 = rtw_read32(rtwdev, REG_OFDM_0_ECCA_THRESHOLD);
+		value32 &= ~BIT_MASK_OFDM0_EXTS;
+		rtw_write32(rtwdev, REG_OFDM_0_ECCA_THRESHOLD, value32);
+		break;
+
+	case RF_PATH_B:
+		/* image S1:c80 to S0:Cd0 and Cd4 */
+		rtw_write32_mask(rtwdev, REG_TXIQ_AB_S0, BIT_MASK_TXIQ_A_S0,
+				 OFDM_SWING_A(ofdm_swing));
+		rtw_write32_mask(rtwdev, REG_TXIQ_AB_S0, BIT_MASK_TXIQ_B_S0,
+				 OFDM_SWING_B(ofdm_swing));
+		rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_C_S0,
+				 OFDM_SWING_C(ofdm_swing));
+		rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_D_S0,
+				 OFDM_SWING_D(ofdm_swing));
+		rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_D_EXT_S0, 0x0);
+		rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_C_EXT_S0, 0x0);
+		rtw_write32_mask(rtwdev, REG_TXIQ_AB_S0, BIT_MASK_TXIQ_A_EXT_S0, 0x0);
+		break;
+	}
+}
+
+static void rtw8723d_pwrtrack_set_ofdm_pwr(struct rtw_dev *rtwdev, s8 swing_idx,
+					   s8 txagc_idx)
+{
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+
+	dm_info->txagc_remnant_ofdm = txagc_idx;
+
+	rtw8723d_set_iqk_matrix(rtwdev, swing_idx, RF_PATH_A);
+	rtw8723d_set_iqk_matrix(rtwdev, swing_idx, RF_PATH_B);
+}
+
+static void rtw8723d_pwrtrack_set_cck_pwr(struct rtw_dev *rtwdev, s8 swing_idx,
+					  s8 txagc_idx)
+{
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+
+	dm_info->txagc_remnant_cck = txagc_idx;
+
+	rtw_write32_mask(rtwdev, 0xab4, 0x000007FF,
+			 rtw8723d_cck_swing_table[swing_idx]);
+}
+
+static void rtw8723d_pwrtrack_set(struct rtw_dev *rtwdev, u8 path)
+{
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+	struct rtw_hal *hal = &rtwdev->hal;
+	u8 limit_ofdm;
+	u8 limit_cck = 40;
+	s8 final_ofdm_swing_index;
+	s8 final_cck_swing_index;
+
+	limit_ofdm = rtw8723d_pwrtrack_get_limit_ofdm(rtwdev);
+
+	final_ofdm_swing_index = RTW_DEF_OFDM_SWING_INDEX +
+				 dm_info->delta_power_index[path];
+	final_cck_swing_index = RTW_DEF_CCK_SWING_INDEX +
+				dm_info->delta_power_index[path];
+
+	if (final_ofdm_swing_index > limit_ofdm)
+		rtw8723d_pwrtrack_set_ofdm_pwr(rtwdev, limit_ofdm,
+					       final_ofdm_swing_index - limit_ofdm);
+	else if (final_ofdm_swing_index < 0)
+		rtw8723d_pwrtrack_set_ofdm_pwr(rtwdev, 0,
+					       final_ofdm_swing_index);
+	else
+		rtw8723d_pwrtrack_set_ofdm_pwr(rtwdev, final_ofdm_swing_index, 0);
+
+	if (final_cck_swing_index > limit_cck)
+		rtw8723d_pwrtrack_set_cck_pwr(rtwdev, limit_cck,
+					      final_cck_swing_index - limit_cck);
+	else if (final_cck_swing_index < 0)
+		rtw8723d_pwrtrack_set_cck_pwr(rtwdev, 0,
+					      final_cck_swing_index);
+	else
+		rtw8723d_pwrtrack_set_cck_pwr(rtwdev, final_cck_swing_index, 0);
+
+	rtw_phy_set_tx_power_level(rtwdev, hal->current_channel);
+}
+
+static void rtw8723d_pwrtrack_set_xtal(struct rtw_dev *rtwdev, u8 therm_path,
+				       u8 delta)
+{
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+	const struct rtw_pwr_track_tbl *tbl = rtwdev->chip->pwr_track_tbl;
+	const s8 *pwrtrk_xtal;
+	s8 xtal_cap;
+
+	if (dm_info->thermal_avg[therm_path] >
+	    rtwdev->efuse.thermal_meter[therm_path])
+		pwrtrk_xtal = tbl->pwrtrk_xtal_p;
+	else
+		pwrtrk_xtal = tbl->pwrtrk_xtal_n;
+
+	xtal_cap = rtwdev->efuse.crystal_cap & 0x3F;
+	xtal_cap = clamp_t(s8, xtal_cap + pwrtrk_xtal[delta], 0, 0x3F);
+	rtw_write32_mask(rtwdev, REG_AFE_CTRL3, BIT_MASK_XTAL,
+			 xtal_cap | (xtal_cap << 6));
+}
+
+static void rtw8723d_phy_pwrtrack(struct rtw_dev *rtwdev)
+{
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+	struct rtw_swing_table swing_table;
+	u8 thermal_value, delta, path;
+	bool do_iqk = false;
+
+	rtw_phy_config_swing_table(rtwdev, &swing_table);
+
+	if (rtwdev->efuse.thermal_meter[0] == 0xff)
+		return;
+
+	thermal_value = rtw_read_rf(rtwdev, RF_PATH_A, RF_T_METER, 0xfc00);
+
+	rtw_phy_pwrtrack_avg(rtwdev, thermal_value, RF_PATH_A);
+
+	do_iqk = rtw_phy_pwrtrack_need_iqk(rtwdev);
+
+	if (do_iqk)
+		rtw8723d_lck(rtwdev);
+
+	if (dm_info->pwr_trk_init_trigger)
+		dm_info->pwr_trk_init_trigger = false;
+	else if (!rtw_phy_pwrtrack_thermal_changed(rtwdev, thermal_value,
+						   RF_PATH_A))
+		goto iqk;
+
+	delta = rtw_phy_pwrtrack_get_delta(rtwdev, RF_PATH_A);
+
+	delta = min_t(u8, delta, RTW_PWR_TRK_TBL_SZ - 1);
+
+	for (path = 0; path < rtwdev->hal.rf_path_num; path++) {
+		s8 delta_cur, delta_last;
+
+		delta_last = dm_info->delta_power_index[path];
+		delta_cur = rtw_phy_pwrtrack_get_pwridx(rtwdev, &swing_table,
+							path, RF_PATH_A, delta);
+		if (delta_last == delta_cur)
+			continue;
+
+		dm_info->delta_power_index[path] = delta_cur;
+		rtw8723d_pwrtrack_set(rtwdev, path);
+	}
+
+	rtw8723d_pwrtrack_set_xtal(rtwdev, RF_PATH_A, delta);
+
+iqk:
+	if (do_iqk)
+		rtw8723d_phy_calibration(rtwdev);
+}
+
+void rtw8723d_pwr_track(struct rtw_dev *rtwdev)
+{
+	struct rtw_efuse *efuse = &rtwdev->efuse;
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+
+	if (efuse->power_track_type != 0)
+		return;
+
+	if (!dm_info->pwr_trk_triggered) {
+		rtw_write_rf(rtwdev, RF_PATH_A, RF_T_METER,
+			     GENMASK(17, 16), 0x03);
+		dm_info->pwr_trk_triggered = true;
+		return;
+	}
+
+	rtw8723d_phy_pwrtrack(rtwdev);
+	dm_info->pwr_trk_triggered = false;
+}
+
+static struct rtw_chip_ops rtw8723d_ops = {
+	.phy_set_param		= rtw8723d_phy_set_param,
+	.read_efuse		= rtw8723d_read_efuse,
+	.query_rx_desc		= rtw8723d_query_rx_desc,
+	.set_channel		= rtw8723d_set_channel,
+	.mac_init		= rtw8723d_mac_init,
+	.shutdown		= rtw8723d_shutdown,
+	.read_rf		= rtw_phy_read_rf_sipi,
+	.write_rf		= rtw_phy_write_rf_reg_sipi,
+	.set_tx_power_index	= rtw8723d_set_tx_power_index,
+	.set_antenna		= NULL,
+	.cfg_ldo25		= rtw8723d_cfg_ldo25,
+	.efuse_grant		= rtw8723d_efuse_grant,
+	.false_alarm_statistics	= rtw8723d_false_alarm_statistics,
+	.phy_calibration	= rtw8723d_phy_calibration,
+	.pwr_track		= rtw8723d_pwr_track,
+	.config_bfee		= NULL,
+	.set_gid_table		= NULL,
+	.cfg_csi_rate		= NULL,
+	.adaptivity_init	= NULL,
+	.adaptivity		= NULL,
+
+	.coex_set_init		= rtw8723d_coex_cfg_init,
+	.coex_set_ant_switch	= NULL,
+	.coex_set_gnt_fix	= rtw8723d_coex_cfg_gnt_fix,
+	.coex_set_gnt_debug	= rtw8723d_coex_cfg_gnt_debug,
+	.coex_set_rfe_type	= rtw8723d_coex_cfg_rfe_type,
+	.coex_set_wl_tx_power	= rtw8723d_coex_cfg_wl_tx_power,
+	.coex_set_wl_rx_gain	= rtw8723d_coex_cfg_wl_rx_gain,
+};
+
+/* Shared-Antenna Coex Table */
+static const struct coex_table_para table_sant_8723d[] = {
+	{0xffffffff, 0xffffffff}, /* case-0 */
+	{0x55555555, 0x55555555},
+	{0x65555555, 0x65555555},
+	{0xaaaaaaaa, 0xaaaaaaaa},
+	{0x5a5a5a5a, 0x5a5a5a5a},
+	{0xfafafafa, 0xfafafafa}, /* case-5 */
+	{0xa5555555, 0xaaaa5aaa},
+	{0x6a5a5a5a, 0x5a5a5a5a},
+	{0x6a5a5a5a, 0x6a5a5a5a},
+	{0x65555555, 0x5a5a5a5a},
+	{0x65555555, 0x6a5a5a5a}, /* case-10 */
+	{0x65555555, 0xfafafafa},
+	{0x65555555, 0x6a5a5aaa},
+	{0x65555555, 0x5aaa5aaa},
+	{0x65555555, 0xaaaa5aaa},
+	{0x65555555, 0xaaaaaaaa}, /* case-15 */
+	{0xffff55ff, 0xfafafafa},
+	{0xffff55ff, 0x6afa5afa},
+	{0xaaffffaa, 0xfafafafa},
+	{0xaa5555aa, 0x5a5a5a5a},
+	{0xaa5555aa, 0x6a5a5a5a}, /* case-20 */
+	{0xaa5555aa, 0xaaaaaaaa},
+	{0xffffffff, 0x5a5a5a5a},
+	{0xffffffff, 0x6a5a5a5a},
+	{0xffffffff, 0x55555555},
+	{0xffffffff, 0x6a5a5aaa}, /* case-25 */
+	{0x55555555, 0x5a5a5a5a},
+	{0x55555555, 0xaaaaaaaa},
+	{0x55555555, 0x6a6a6a6a},
+	{0x656a656a, 0x656a656a}
+};
+
+/* Non-Shared-Antenna Coex Table */
+static const struct coex_table_para table_nsant_8723d[] = {
+	{0xffffffff, 0xffffffff}, /* case-100 */
+	{0x55555555, 0x55555555},
+	{0x65555555, 0x65555555},
+	{0xaaaaaaaa, 0xaaaaaaaa},
+	{0x5a5a5a5a, 0x5a5a5a5a},
+	{0xfafafafa, 0xfafafafa}, /* case-105 */
+	{0x5afa5afa, 0x5afa5afa},
+	{0x55555555, 0xfafafafa},
+	{0x65555555, 0xfafafafa},
+	{0x65555555, 0x5a5a5a5a},
+	{0x65555555, 0x6a5a5a5a}, /* case-110 */
+	{0x65555555, 0xaaaaaaaa},
+	{0xffff55ff, 0xfafafafa},
+	{0xffff55ff, 0x5afa5afa},
+	{0xffff55ff, 0xaaaaaaaa},
+	{0xaaffffaa, 0xfafafafa}, /* case-115 */
+	{0xaaffffaa, 0x5afa5afa},
+	{0xaaffffaa, 0xaaaaaaaa},
+	{0xffffffff, 0xfafafafa},
+	{0xffffffff, 0x5afa5afa},
+	{0xffffffff, 0xaaaaaaaa},/* case-120 */
+	{0x55ff55ff, 0x5afa5afa},
+	{0x55ff55ff, 0xaaaaaaaa},
+	{0x55ff55ff, 0x55ff55ff}
+};
+
+/* Shared-Antenna TDMA */
+static const struct coex_tdma_para tdma_sant_8723d[] = {
+	{ {0x08, 0x00, 0x00, 0x00, 0x00} }, /* case-0 */
+	{ {0x61, 0x45, 0x03, 0x11, 0x11} }, /* case-1 */
+	{ {0x61, 0x3a, 0x03, 0x11, 0x11} },
+	{ {0x61, 0x20, 0x03, 0x11, 0x11} },
+	{ {0x61, 0x30, 0x03, 0x11, 0x11} },
+	{ {0x61, 0x10, 0x03, 0x11, 0x11} }, /* case-5 */
+	{ {0x61, 0x48, 0x03, 0x11, 0x10} },
+	{ {0x61, 0x3a, 0x03, 0x11, 0x10} },
+	{ {0x61, 0x30, 0x03, 0x11, 0x10} },
+	{ {0x61, 0x20, 0x03, 0x11, 0x10} },
+	{ {0x61, 0x10, 0x03, 0x11, 0x10} }, /* case-10 */
+	{ {0x61, 0x10, 0x03, 0x11, 0x14} },
+	{ {0x61, 0x08, 0x03, 0x10, 0x14} },
+	{ {0x51, 0x10, 0x03, 0x10, 0x54} },
+	{ {0x51, 0x10, 0x03, 0x10, 0x55} },
+	{ {0x51, 0x10, 0x07, 0x10, 0x54} }, /* case-15 */
+	{ {0x51, 0x45, 0x03, 0x10, 0x50} },
+	{ {0x51, 0x3a, 0x03, 0x10, 0x50} },
+	{ {0x51, 0x30, 0x03, 0x10, 0x50} },
+	{ {0x51, 0x20, 0x03, 0x10, 0x50} },
+	{ {0x51, 0x15, 0x03, 0x10, 0x50} }, /* case-20 */
+	{ {0x51, 0x4a, 0x03, 0x10, 0x50} },
+	{ {0x51, 0x0c, 0x03, 0x10, 0x54} },
+	{ {0x55, 0x08, 0x03, 0x10, 0x54} },
+	{ {0x65, 0x10, 0x03, 0x11, 0x11} },
+	{ {0x51, 0x10, 0x03, 0x10, 0x51} },
+	{ {0x61, 0x15, 0x03, 0x11, 0x10} }
+};
+
+/* Non-Shared-Antenna TDMA */
+static const struct coex_tdma_para tdma_nsant_8723d[] = {
+	{ {0x00, 0x00, 0x00, 0x40, 0x01} }, /* case-100 */
+	{ {0x61, 0x45, 0x03, 0x11, 0x11} }, /* case-101 */
+	{ {0x61, 0x3a, 0x03, 0x11, 0x11} },
+	{ {0x61, 0x30, 0x03, 0x11, 0x11} },
+	{ {0x61, 0x20, 0x03, 0x11, 0x11} },
+	{ {0x61, 0x10, 0x03, 0x11, 0x11} }, /* case-105 */
+	{ {0x61, 0x45, 0x03, 0x11, 0x10} },
+	{ {0x61, 0x3a, 0x03, 0x11, 0x10} },
+	{ {0x61, 0x30, 0x03, 0x11, 0x10} },
+	{ {0x61, 0x20, 0x03, 0x11, 0x10} },
+	{ {0x61, 0x10, 0x03, 0x11, 0x10} }, /* case-110 */
+	{ {0x61, 0x08, 0x03, 0x11, 0x14} },
+	{ {0x61, 0x08, 0x03, 0x10, 0x14} },
+	{ {0x51, 0x08, 0x03, 0x10, 0x54} },
+	{ {0x51, 0x08, 0x03, 0x10, 0x55} },
+	{ {0x51, 0x08, 0x07, 0x10, 0x54} }, /* case-115 */
+	{ {0x51, 0x45, 0x03, 0x10, 0x50} },
+	{ {0x51, 0x3a, 0x03, 0x10, 0x50} },
+	{ {0x51, 0x30, 0x03, 0x10, 0x50} },
+	{ {0x51, 0x20, 0x03, 0x10, 0x50} },
+	{ {0x51, 0x10, 0x03, 0x10, 0x50} }, /* case-120 */
+	{ {0x51, 0x08, 0x03, 0x10, 0x50} },
+};
+
+/* rssi in percentage % (dbm = % - 100) */
+static const u8 wl_rssi_step_8723d[] = {60, 50, 44, 30};
+static const u8 bt_rssi_step_8723d[] = {30, 30, 30, 30};
+static const struct coex_5g_afh_map afh_5g_8723d[] = { {0, 0, 0} };
+
+static const struct rtw_hw_reg btg_reg_8723d = {
+	.addr = REG_BTG_SEL, .mask = BIT_MASK_BTG_WL,
+};
+
+/* wl_tx_dec_power, bt_tx_dec_power, wl_rx_gain, bt_rx_lna_constrain */
+static const struct coex_rf_para rf_para_tx_8723d[] = {
+	{0, 0, false, 7},  /* for normal */
+	{0, 10, false, 7}, /* for WL-CPT */
+	{1, 0, true, 4},
+	{1, 2, true, 4},
+	{1, 10, true, 4},
+	{1, 15, true, 4}
+};
+
+static const struct coex_rf_para rf_para_rx_8723d[] = {
+	{0, 0, false, 7},  /* for normal */
+	{0, 10, false, 7}, /* for WL-CPT */
+	{1, 0, true, 5},
+	{1, 2, true, 5},
+	{1, 10, true, 5},
+	{1, 15, true, 5}
+};
+
+static struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8723d[] = {
+	{0x0005,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(3) | BIT(7), 0},
+	{0x0086,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_SDIO_MSK,
+	 RTW_PWR_ADDR_SDIO,
+	 RTW_PWR_CMD_WRITE, BIT(0), 0},
+	{0x0086,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_SDIO_MSK,
+	 RTW_PWR_ADDR_SDIO,
+	 RTW_PWR_CMD_POLLING, BIT(1), BIT(1)},
+	{0x004A,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_USB_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(0), 0},
+	{0x0005,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(3) | BIT(4), 0},
+	{0x0023,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_SDIO_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(4), 0},
+	{0x0301,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_PCI_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, 0xFF, 0},
+	{0xFFFF,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 0,
+	 RTW_PWR_CMD_END, 0, 0},
+};
+
+static struct rtw_pwr_seq_cmd trans_cardemu_to_act_8723d[] = {
+	{0x0020,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(0), BIT(0)},
+	{0x0001,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_DELAY, 1, RTW_PWR_DELAY_MS},
+	{0x0000,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(5), 0},
+	{0x0005,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, (BIT(4) | BIT(3) | BIT(2)), 0},
+	{0x0075,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_PCI_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(0), BIT(0)},
+	{0x0006,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_POLLING, BIT(1), BIT(1)},
+	{0x0075,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_PCI_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(0), 0},
+	{0x0006,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(0), BIT(0)},
+	{0x0005,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_POLLING, (BIT(1) | BIT(0)), 0},
+	{0x0005,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(7), 0},
+	{0x0005,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, (BIT(4) | BIT(3)), 0},
+	{0x0005,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(0), BIT(0)},
+	{0x0005,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_POLLING, BIT(0), 0},
+	{0x0010,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(6), BIT(6)},
+	{0x0049,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(1), BIT(1)},
+	{0x0063,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(1), BIT(1)},
+	{0x0062,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(1), 0},
+	{0x0058,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(0), BIT(0)},
+	{0x005A,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(1), BIT(1)},
+	{0x0068,
+	 RTW_PWR_CUT_TEST_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(3), BIT(3)},
+	{0x0069,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(6), BIT(6)},
+	{0x001f,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, 0xFF, 0x00},
+	{0x0077,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, 0xFF, 0x00},
+	{0x001f,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, 0xFF, 0x07},
+	{0x0077,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, 0xFF, 0x07},
+	{0xFFFF,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 0,
+	 RTW_PWR_CMD_END, 0, 0},
+};
+
+static struct rtw_pwr_seq_cmd *card_enable_flow_8723d[] = {
+	trans_carddis_to_cardemu_8723d,
+	trans_cardemu_to_act_8723d,
+	NULL
+};
+
+static struct rtw_pwr_seq_cmd trans_act_to_lps_8723d[] = {
+	{0x0301,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_PCI_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, 0xFF, 0xFF},
+	{0x0522,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, 0xFF, 0xFF},
+	{0x05F8,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_POLLING, 0xFF, 0},
+	{0x05F9,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_POLLING, 0xFF, 0},
+	{0x05FA,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_POLLING, 0xFF, 0},
+	{0x05FB,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_POLLING, 0xFF, 0},
+	{0x0002,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(0), 0},
+	{0x0002,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_DELAY, 0, RTW_PWR_DELAY_US},
+	{0x0002,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(1), 0},
+	{0x0100,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, 0xFF, 0x03},
+	{0x0101,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(1), 0},
+	{0x0093,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_SDIO_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, 0xFF, 0x00},
+	{0x0553,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(5), BIT(5)},
+	{0xFFFF,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 0,
+	 RTW_PWR_CMD_END, 0, 0},
+};
+
+static struct rtw_pwr_seq_cmd trans_act_to_pre_carddis_8723d[] = {
+	{0x0003,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(2), 0},
+	{0x0080,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, 0xFF, 0},
+	{0xFFFF,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 0,
+	 RTW_PWR_CMD_END, 0, 0},
+};
+
+static struct rtw_pwr_seq_cmd trans_act_to_cardemu_8723d[] = {
+	{0x0002,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(0), 0},
+	{0x0049,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(1), 0},
+	{0x0006,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(0), BIT(0)},
+	{0x0005,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(1), BIT(1)},
+	{0x0005,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_POLLING, BIT(1), 0},
+	{0x0010,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(6), 0},
+	{0x0000,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(5), BIT(5)},
+	{0x0020,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(0), 0},
+	{0xFFFF,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 0,
+	 RTW_PWR_CMD_END, 0, 0},
+};
+
+static struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8723d[] = {
+	{0x0007,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_SDIO_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, 0xFF, 0x20},
+	{0x0005,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(3) | BIT(4), BIT(3)},
+	{0x0005,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_PCI_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(2), BIT(2)},
+	{0x0005,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_PCI_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(3) | BIT(4), BIT(3) | BIT(4)},
+	{0x004A,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_USB_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(0), 1},
+	{0x0023,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_SDIO_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(4), BIT(4)},
+	{0x0086,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_SDIO_MSK,
+	 RTW_PWR_ADDR_SDIO,
+	 RTW_PWR_CMD_WRITE, BIT(0), BIT(0)},
+	{0x0086,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_SDIO_MSK,
+	 RTW_PWR_ADDR_SDIO,
+	 RTW_PWR_CMD_POLLING, BIT(1), 0},
+	{0xFFFF,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 0,
+	 RTW_PWR_CMD_END, 0, 0},
+};
+
+static struct rtw_pwr_seq_cmd trans_act_to_post_carddis_8723d[] = {
+	{0x001D,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(0), 0},
+	{0x001D,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(0), BIT(0)},
+	{0x001C,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, 0xFF, 0x0E},
+	{0xFFFF,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 0,
+	 RTW_PWR_CMD_END, 0, 0},
+};
+
+static struct rtw_pwr_seq_cmd *card_disable_flow_8723d[] = {
+	trans_act_to_lps_8723d,
+	trans_act_to_pre_carddis_8723d,
+	trans_act_to_cardemu_8723d,
+	trans_cardemu_to_carddis_8723d,
+	trans_act_to_post_carddis_8723d,
+	NULL
+};
+
+static struct rtw_page_table page_table_8723d[] = {
+	{12, 2, 2, 0, 1},
+	{12, 2, 2, 0, 1},
+	{12, 2, 2, 0, 1},
+	{12, 2, 2, 0, 1},
+	{12, 2, 2, 0, 1},
+};
+
+static struct rtw_rqpn rqpn_table_8723d[] = {
+	{RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL,
+	 RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW,
+	 RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH},
+	{RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL,
+	 RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW,
+	 RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH},
+	{RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL,
+	 RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_HIGH,
+	 RTW_DMA_MAPPING_HIGH, RTW_DMA_MAPPING_HIGH},
+	{RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL,
+	 RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW,
+	 RTW_DMA_MAPPING_HIGH, RTW_DMA_MAPPING_HIGH},
+	{RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL,
+	 RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW,
+	 RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH},
+};
+
+static struct rtw_prioq_addrs prioq_addrs_8723d = {
+	.prio[RTW_DMA_MAPPING_EXTRA] = {
+		.rsvd = REG_RQPN_NPQ + 2, .avail = REG_RQPN_NPQ + 3,
+	},
+	.prio[RTW_DMA_MAPPING_LOW] = {
+		.rsvd = REG_RQPN + 1, .avail = REG_FIFOPAGE_CTRL_2 + 1,
+	},
+	.prio[RTW_DMA_MAPPING_NORMAL] = {
+		.rsvd = REG_RQPN_NPQ, .avail = REG_RQPN_NPQ + 1,
+	},
+	.prio[RTW_DMA_MAPPING_HIGH] = {
+		.rsvd = REG_RQPN, .avail = REG_FIFOPAGE_CTRL_2,
+	},
+	.wsize = false,
+};
+
+static struct rtw_intf_phy_para pcie_gen1_param_8723d[] = {
+	{0x0008, 0x4a22,
+	 RTW_IP_SEL_PHY,
+	 RTW_INTF_PHY_CUT_ALL,
+	 RTW_INTF_PHY_PLATFORM_ALL},
+	{0x0009, 0x1000,
+	 RTW_IP_SEL_PHY,
+	 ~(RTW_INTF_PHY_CUT_A | RTW_INTF_PHY_CUT_B),
+	 RTW_INTF_PHY_PLATFORM_ALL},
+	{0xFFFF, 0x0000,
+	 RTW_IP_SEL_PHY,
+	 RTW_INTF_PHY_CUT_ALL,
+	 RTW_INTF_PHY_PLATFORM_ALL},
+};
+
+static struct rtw_intf_phy_para_table phy_para_table_8723d = {
+	.gen1_para	= pcie_gen1_param_8723d,
+	.n_gen1_para	= ARRAY_SIZE(pcie_gen1_param_8723d),
+};
+
+static struct rtw_hw_reg rtw8723d_dig[] = {
+	[0] = { .addr = 0xc50, .mask = 0x7f },
+	[1] = { .addr = 0xc50, .mask = 0x7f },
+};
+
+static struct rtw_hw_reg rtw8723d_dig_cck[] = {
+	[0] = { .addr = 0xa0c, .mask = 0x3f00 },
+};
+
+static struct rtw_rf_sipi_addr rtw8723d_rf_sipi_addr[] = {
+	[RF_PATH_A] = { .hssi_1 = 0x820, .lssi_read    = 0x8a0,
+			.hssi_2 = 0x824, .lssi_read_pi = 0x8b8},
+	[RF_PATH_B] = { .hssi_1 = 0x828, .lssi_read    = 0x8a4,
+			.hssi_2 = 0x82c, .lssi_read_pi = 0x8bc},
+};
+
+static struct rtw_ltecoex_addr rtw8723d_ltecoex_addr = {
+	.ctrl = REG_LTECOEX_CTRL,
+	.wdata = REG_LTECOEX_WRITE_DATA,
+	.rdata = REG_LTECOEX_READ_DATA,
+};
+
+static const struct rtw_rfe_def rtw8723d_rfe_defs[] = {
+	[0] = { .phy_pg_tbl	= &rtw8723d_bb_pg_tbl,
+		.txpwr_lmt_tbl	= &rtw8723d_txpwr_lmt_tbl,},
+};
+
+static const u8 rtw8723d_pwrtrk_2gb_n[] = {
+	0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 4, 4, 5, 5, 5,
+	6, 6, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 10, 10
+};
+
+static const u8 rtw8723d_pwrtrk_2gb_p[] = {
+	0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7,
+	7, 8, 8, 8, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10
+};
+
+static const u8 rtw8723d_pwrtrk_2ga_n[] = {
+	0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 4, 4, 5, 5, 5,
+	6, 6, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 10, 10
+};
+
+static const u8 rtw8723d_pwrtrk_2ga_p[] = {
+	0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7,
+	7, 8, 8, 8, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10
+};
+
+static const u8 rtw8723d_pwrtrk_2g_cck_b_n[] = {
+	0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+	6, 7, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11
+};
+
+static const u8 rtw8723d_pwrtrk_2g_cck_b_p[] = {
+	0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7,
+	7, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11
+};
+
+static const u8 rtw8723d_pwrtrk_2g_cck_a_n[] = {
+	0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+	6, 7, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11
+};
+
+static const u8 rtw8723d_pwrtrk_2g_cck_a_p[] = {
+	0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7,
+	7, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11
+};
+
+static const s8 rtw8723d_pwrtrk_xtal_n[] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static const s8 rtw8723d_pwrtrk_xtal_p[] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, -10, -12, -14, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16
+};
+
+static const struct rtw_pwr_track_tbl rtw8723d_rtw_pwr_track_tbl = {
+	.pwrtrk_2gb_n = rtw8723d_pwrtrk_2gb_n,
+	.pwrtrk_2gb_p = rtw8723d_pwrtrk_2gb_p,
+	.pwrtrk_2ga_n = rtw8723d_pwrtrk_2ga_n,
+	.pwrtrk_2ga_p = rtw8723d_pwrtrk_2ga_p,
+	.pwrtrk_2g_cckb_n = rtw8723d_pwrtrk_2g_cck_b_n,
+	.pwrtrk_2g_cckb_p = rtw8723d_pwrtrk_2g_cck_b_p,
+	.pwrtrk_2g_ccka_n = rtw8723d_pwrtrk_2g_cck_a_n,
+	.pwrtrk_2g_ccka_p = rtw8723d_pwrtrk_2g_cck_a_p,
+	.pwrtrk_xtal_p = rtw8723d_pwrtrk_xtal_p,
+	.pwrtrk_xtal_n = rtw8723d_pwrtrk_xtal_n,
+};
+
+static const struct rtw_reg_domain coex_info_hw_regs_8723d[] = {
+	{0x948, MASKDWORD, RTW_REG_DOMAIN_MAC32},
+	{0x67, BIT(7), RTW_REG_DOMAIN_MAC8},
+	{0, 0, RTW_REG_DOMAIN_NL},
+	{0x964, BIT(1), RTW_REG_DOMAIN_MAC8},
+	{0x864, BIT(0), RTW_REG_DOMAIN_MAC8},
+	{0xab7, BIT(5), RTW_REG_DOMAIN_MAC8},
+	{0xa01, BIT(7), RTW_REG_DOMAIN_MAC8},
+	{0, 0, RTW_REG_DOMAIN_NL},
+	{0x430, MASKDWORD, RTW_REG_DOMAIN_MAC32},
+	{0x434, MASKDWORD, RTW_REG_DOMAIN_MAC32},
+	{0x42a, MASKLWORD, RTW_REG_DOMAIN_MAC16},
+	{0x426, MASKBYTE0, RTW_REG_DOMAIN_MAC8},
+	{0x45e, BIT(3), RTW_REG_DOMAIN_MAC8},
+	{0, 0, RTW_REG_DOMAIN_NL},
+	{0x4c6, BIT(4), RTW_REG_DOMAIN_MAC8},
+	{0x40, BIT(5), RTW_REG_DOMAIN_MAC8},
+	{0x550, MASKDWORD, RTW_REG_DOMAIN_MAC32},
+	{0x522, MASKBYTE0, RTW_REG_DOMAIN_MAC8},
+	{0x953, BIT(1), RTW_REG_DOMAIN_MAC8},
+};
+
+struct rtw_chip_info rtw8723d_hw_spec = {
+	.ops = &rtw8723d_ops,
+	.id = RTW_CHIP_TYPE_8723D,
+	.fw_name = "rtw88/rtw8723d_fw.bin",
+	.wlan_cpu = RTW_WCPU_11N,
+	.tx_pkt_desc_sz = 40,
+	.tx_buf_desc_sz = 16,
+	.rx_pkt_desc_sz = 24,
+	.rx_buf_desc_sz = 8,
+	.phy_efuse_size = 512,
+	.log_efuse_size = 512,
+	.ptct_efuse_size = 96 + 1,
+	.txff_size = 32768,
+	.rxff_size = 16384,
+	.txgi_factor = 1,
+	.is_pwr_by_rate_dec = true,
+	.max_power_index = 0x3f,
+	.csi_buf_pg_num = 0,
+	.band = RTW_BAND_2G,
+	.page_size = 128,
+	.dig_min = 0x20,
+	.ht_supported = true,
+	.vht_supported = false,
+	.lps_deep_mode_supported = 0,
+	.sys_func_en = 0xFD,
+	.pwr_on_seq = card_enable_flow_8723d,
+	.pwr_off_seq = card_disable_flow_8723d,
+	.page_table = page_table_8723d,
+	.rqpn_table = rqpn_table_8723d,
+	.prioq_addrs = &prioq_addrs_8723d,
+	.intf_table = &phy_para_table_8723d,
+	.dig = rtw8723d_dig,
+	.dig_cck = rtw8723d_dig_cck,
+	.rf_sipi_addr = {0x840, 0x844},
+	.rf_sipi_read_addr = rtw8723d_rf_sipi_addr,
+	.fix_rf_phy_num = 2,
+	.ltecoex_addr = &rtw8723d_ltecoex_addr,
+	.mac_tbl = &rtw8723d_mac_tbl,
+	.agc_tbl = &rtw8723d_agc_tbl,
+	.bb_tbl = &rtw8723d_bb_tbl,
+	.rf_tbl = {&rtw8723d_rf_a_tbl},
+	.rfe_defs = rtw8723d_rfe_defs,
+	.rfe_defs_size = ARRAY_SIZE(rtw8723d_rfe_defs),
+	.pwr_track_tbl = &rtw8723d_rtw_pwr_track_tbl,
+	.iqk_threshold = 8,
+
+	.coex_para_ver = 0x1905302f,
+	.bt_desired_ver = 0x2f,
+	.scbd_support = true,
+	.new_scbd10_def = true,
+	.pstdma_type = COEX_PSTDMA_FORCE_LPSOFF,
+	.bt_rssi_type = COEX_BTRSSI_RATIO,
+	.ant_isolation = 15,
+	.rssi_tolerance = 2,
+	.wl_rssi_step = wl_rssi_step_8723d,
+	.bt_rssi_step = bt_rssi_step_8723d,
+	.table_sant_num = ARRAY_SIZE(table_sant_8723d),
+	.table_sant = table_sant_8723d,
+	.table_nsant_num = ARRAY_SIZE(table_nsant_8723d),
+	.table_nsant = table_nsant_8723d,
+	.tdma_sant_num = ARRAY_SIZE(tdma_sant_8723d),
+	.tdma_sant = tdma_sant_8723d,
+	.tdma_nsant_num = ARRAY_SIZE(tdma_nsant_8723d),
+	.tdma_nsant = tdma_nsant_8723d,
+	.wl_rf_para_num = ARRAY_SIZE(rf_para_tx_8723d),
+	.wl_rf_para_tx = rf_para_tx_8723d,
+	.wl_rf_para_rx = rf_para_rx_8723d,
+	.bt_afh_span_bw20 = 0x20,
+	.bt_afh_span_bw40 = 0x30,
+	.afh_5g_num = ARRAY_SIZE(afh_5g_8723d),
+	.afh_5g = afh_5g_8723d,
+	.btg_reg = &btg_reg_8723d,
+
+	.coex_info_hw_regs_num = ARRAY_SIZE(coex_info_hw_regs_8723d),
+	.coex_info_hw_regs = coex_info_hw_regs_8723d,
+};
+EXPORT_SYMBOL(rtw8723d_hw_spec);
+
+MODULE_FIRMWARE("rtw88/rtw8723d_fw.bin");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/rtw8723d.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/rtw8723d.h
@@ -0,0 +1,246 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2018-2019  Realtek Corporation
+ */
+
+#ifndef __RTW8723D_H__
+#define __RTW8723D_H__
+
+enum rtw8723d_path {
+	PATH_S1,
+	PATH_S0,
+	PATH_NR,
+};
+
+enum rtw8723d_iqk_round {
+	IQK_ROUND_0,
+	IQK_ROUND_1,
+	IQK_ROUND_2,
+	IQK_ROUND_HYBRID,
+	IQK_ROUND_SIZE,
+	IQK_ROUND_INVALID = 0xff,
+};
+
+enum rtw8723d_iqk_result {
+	IQK_S1_TX_X,
+	IQK_S1_TX_Y,
+	IQK_S1_RX_X,
+	IQK_S1_RX_Y,
+	IQK_S0_TX_X,
+	IQK_S0_TX_Y,
+	IQK_S0_RX_X,
+	IQK_S0_RX_Y,
+	IQK_NR,
+	IQK_SX_NR = IQK_NR / PATH_NR,
+};
+
+struct rtw8723de_efuse {
+	u8 mac_addr[ETH_ALEN];		/* 0xd0 */
+	u8 vender_id[2];
+	u8 device_id[2];
+	u8 sub_vender_id[2];
+	u8 sub_device_id[2];
+};
+
+struct rtw8723d_efuse {
+	__le16 rtl_id;
+	u8 rsvd[2];
+	u8 afe;
+	u8 rsvd1[11];
+
+	/* power index for four RF paths */
+	struct rtw_txpwr_idx txpwr_idx_table[4];
+
+	u8 channel_plan;		/* 0xb8 */
+	u8 xtal_k;
+	u8 thermal_meter;
+	u8 iqk_lck;
+	u8 pa_type;			/* 0xbc */
+	u8 lna_type_2g[2];		/* 0xbd */
+	u8 lna_type_5g[2];
+	u8 rf_board_option;
+	u8 rf_feature_option;
+	u8 rf_bt_setting;
+	u8 eeprom_version;
+	u8 eeprom_customer_id;
+	u8 tx_bb_swing_setting_2g;
+	u8 res_c7;
+	u8 tx_pwr_calibrate_rate;
+	u8 rf_antenna_option;		/* 0xc9 */
+	u8 rfe_option;
+	u8 country_code[2];
+	u8 res[3];
+	struct rtw8723de_efuse e;
+};
+
+/* phy status page0 */
+#define GET_PHY_STAT_P0_PWDB(phy_stat)                                         \
+	le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(15, 8))
+
+/* phy status page1 */
+#define GET_PHY_STAT_P1_PWDB_A(phy_stat)                                       \
+	le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(15, 8))
+#define GET_PHY_STAT_P1_PWDB_B(phy_stat)                                       \
+	le32_get_bits(*((__le32 *)(phy_stat) + 0x00), GENMASK(23, 16))
+#define GET_PHY_STAT_P1_RF_MODE(phy_stat)                                      \
+	le32_get_bits(*((__le32 *)(phy_stat) + 0x03), GENMASK(29, 28))
+#define GET_PHY_STAT_P1_L_RXSC(phy_stat)                                       \
+	le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(11, 8))
+#define GET_PHY_STAT_P1_HT_RXSC(phy_stat)                                      \
+	le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(15, 12))
+#define GET_PHY_STAT_P1_RXEVM_A(phy_stat)                                      \
+	le32_get_bits(*((__le32 *)(phy_stat) + 0x04), GENMASK(7, 0))
+#define GET_PHY_STAT_P1_CFO_TAIL_A(phy_stat)                                   \
+	le32_get_bits(*((__le32 *)(phy_stat) + 0x05), GENMASK(7, 0))
+#define GET_PHY_STAT_P1_RXSNR_A(phy_stat)                                      \
+	le32_get_bits(*((__le32 *)(phy_stat) + 0x06), GENMASK(7, 0))
+
+static inline s32 iqkxy_to_s32(s32 val)
+{
+	/* val is Q10.8 */
+	return sign_extend32(val, 9);
+}
+
+static inline s32 iqk_mult(s32 x, s32 y, s32 *ext)
+{
+	/* x, y and return value are Q10.8 */
+	s32 t;
+
+	t = x * y;
+	if (ext)
+		*ext = (t >> 7) & 0x1;	/* Q.16 --> Q.9; get LSB of Q.9 */
+
+	return (t >> 8);	/* Q.16 --> Q.8 */
+}
+
+#define REG_GPIO_INTM		0x0048
+#define REG_BTG_SEL		0x0067
+#define BIT_MASK_BTG_WL		BIT(7)
+#define REG_LTECOEX_PATH_CONTROL	0x0070
+#define REG_LTECOEX_CTRL	0x07c0
+#define REG_LTECOEX_WRITE_DATA	0x07c4
+#define REG_LTECOEX_READ_DATA	0x07c8
+#define REG_PSDFN		0x0808
+#define REG_BB_PWR_SAV1_11N	0x0874
+#define REG_ANA_PARAM1		0x0880
+#define REG_ANALOG_P4		0x088c
+#define REG_PSDRPT		0x08b4
+#define REG_FPGA1_RFMOD		0x0900
+#define REG_BB_SEL_BTG		0x0948
+#define REG_BBRX_DFIR		0x0954
+#define REG_CCK0_SYS		0x0a00
+#define REG_CCK_ANT_SEL_11N	0x0a04
+#define REG_CCK_FA_RST_11N	0x0a2c
+#define BIT_MASK_CCK_CNT_KEEP	BIT(12)
+#define BIT_MASK_CCK_CNT_EN	BIT(13)
+#define BIT_MASK_CCK_CNT_KPEN	(BIT_MASK_CCK_CNT_KEEP | BIT_MASK_CCK_CNT_EN)
+#define BIT_MASK_CCK_FA_KEEP	BIT(14)
+#define BIT_MASK_CCK_FA_EN	BIT(15)
+#define BIT_MASK_CCK_FA_KPEN	(BIT_MASK_CCK_FA_KEEP | BIT_MASK_CCK_FA_EN)
+#define REG_CCK_FA_LSB_11N	0x0a5c
+#define REG_CCK_FA_MSB_11N	0x0a58
+#define REG_CCK_CCA_CNT_11N	0x0a60
+#define BIT_MASK_CCK_FA_MSB	GENMASK(7, 0)
+#define BIT_MASK_CCK_FA_LSB	GENMASK(15, 8)
+#define REG_OFDM_FA_HOLDC_11N	0x0c00
+#define BIT_MASK_OFDM_FA_KEEP	BIT(31)
+#define REG_BB_RX_PATH_11N	0x0c04
+#define REG_TRMUX_11N		0x0c08
+#define REG_OFDM_FA_RSTC_11N	0x0c0c
+#define BIT_MASK_OFDM_FA_RST	BIT(31)
+#define REG_A_RXIQI		0x0c14
+#define BIT_MASK_RXIQ_S1_X	0x000003FF
+#define BIT_MASK_RXIQ_S1_Y1	0x0000FC00
+#define BIT_SET_RXIQ_S1_Y1(y)	((y) & 0x3F)
+#define REG_OFDM0_RXDSP		0x0c40
+#define REG_OFDM_0_ECCA_THRESHOLD	0x0c4c
+#define BIT_MASK_OFDM0_EXT_A	BIT(31)
+#define BIT_MASK_OFDM0_EXT_C	BIT(29)
+#define BIT_MASK_OFDM0_EXTS	(BIT(31) | BIT(29) | BIT(28))
+#define BIT_SET_OFDM0_EXTS(a, c, d) (((a) << 31) | ((c) << 29) | ((d) << 28))
+#define REG_OFDM0_XAAGC1	0x0c50
+#define REG_OFDM0_XBAGC1	0x0c58
+#define REG_AGCRSSI		0x0c78
+#define REG_OFDM_0_XA_TX_IQ_IMBALANCE	0x0c80
+#define BIT_MASK_TXIQ_ELM_A	0x03ff
+#define BIT_SET_TXIQ_ELM_ACD(a, c, d) (((d) << 22) | (((c) & 0x3F) << 16) |    \
+				       ((a) & 0x03ff))
+#define BIT_MASK_TXIQ_ELM_C	GENMASK(21, 16)
+#define BIT_SET_TXIQ_ELM_C2(c)	((c) & 0x3F)
+#define BIT_MASK_TXIQ_ELM_D	GENMASK(31, 22)
+#define REG_TXIQK_MATRIXA_LSB2_11N	0x0c94
+#define BIT_SET_TXIQ_ELM_C1(c)	(((c) & 0x000003C0) >> 6)
+#define REG_RXIQK_MATRIX_LSB_11N	0x0ca0
+#define BIT_MASK_RXIQ_S1_Y2	0xF0000000
+#define BIT_SET_RXIQ_S1_Y2(y)	(((y) >> 6) & 0xF)
+#define REG_TXIQ_AB_S0		0x0cd0
+#define BIT_MASK_TXIQ_A_S0	0x000007FE
+#define BIT_MASK_TXIQ_A_EXT_S0	BIT(0)
+#define BIT_MASK_TXIQ_B_S0	0x0007E000
+#define REG_TXIQ_CD_S0		0x0cd4
+#define BIT_MASK_TXIQ_C_S0	0x000007FE
+#define BIT_MASK_TXIQ_C_EXT_S0	BIT(0)
+#define BIT_MASK_TXIQ_D_S0	GENMASK(22, 13)
+#define BIT_MASK_TXIQ_D_EXT_S0	BIT(12)
+#define REG_RXIQ_AB_S0		0x0cd8
+#define BIT_MASK_RXIQ_X_S0	0x000003FF
+#define BIT_MASK_RXIQ_Y_S0	0x003FF000
+#define REG_OFDM_FA_TYPE1_11N	0x0cf0
+#define BIT_MASK_OFDM_FF_CNT	GENMASK(15, 0)
+#define BIT_MASK_OFDM_SF_CNT	GENMASK(31, 16)
+#define REG_OFDM_FA_RSTD_11N	0x0d00
+#define BIT_MASK_OFDM_FA_RST1	BIT(27)
+#define BIT_MASK_OFDM_FA_KEEP1	BIT(31)
+#define REG_CTX			0x0d03
+#define BIT_MASK_CTX_TYPE	GENMASK(6, 4)
+#define REG_OFDM1_CFOTRK	0x0d2c
+#define REG_OFDM1_CSI1		0x0d40
+#define REG_OFDM1_CSI2		0x0d44
+#define REG_OFDM1_CSI3		0x0d48
+#define REG_OFDM1_CSI4		0x0d4c
+#define REG_OFDM_FA_TYPE2_11N	0x0da0
+#define BIT_MASK_OFDM_CCA_CNT	GENMASK(15, 0)
+#define BIT_MASK_OFDM_PF_CNT	GENMASK(31, 16)
+#define REG_OFDM_FA_TYPE3_11N	0x0da4
+#define BIT_MASK_OFDM_RI_CNT	GENMASK(15, 0)
+#define BIT_MASK_OFDM_CRC_CNT	GENMASK(31, 16)
+#define REG_OFDM_FA_TYPE4_11N	0x0da8
+#define BIT_MASK_OFDM_MNS_CNT	GENMASK(15, 0)
+#define REG_FPGA0_IQK_11N	0x0e28
+#define BIT_MASK_IQK_MOD	0xffffff00
+#define EN_IQK			0x808000
+#define RST_IQK			0x000000
+#define REG_TXIQK_TONE_A_11N	0x0e30
+#define REG_RXIQK_TONE_A_11N	0x0e34
+#define REG_TXIQK_PI_A_11N	0x0e38
+#define REG_RXIQK_PI_A_11N	0x0e3c
+#define REG_TXIQK_11N		0x0e40
+#define BIT_SET_TXIQK_11N(x, y)	(0x80007C00 | ((x) << 16) | (y))
+#define REG_RXIQK_11N		0x0e44
+#define REG_IQK_AGC_PTS_11N	0x0e48
+#define REG_IQK_AGC_RSP_11N	0x0e4c
+#define REG_TX_IQK_TONE_B	0x0e50
+#define REG_RX_IQK_TONE_B	0x0e54
+#define REG_IQK_RES_TX		0x0e94
+#define BIT_MASK_RES_TX		GENMASK(25, 16)
+#define REG_IQK_RES_TY		0x0e9c
+#define BIT_MASK_RES_TY		GENMASK(25, 16)
+#define REG_IQK_RES_RX		0x0ea4
+#define BIT_MASK_RES_RX		GENMASK(25, 16)
+#define REG_IQK_RES_RY		0x0eac
+#define BIT_IQK_TX_FAIL		BIT(28)
+#define BIT_IQK_RX_FAIL		BIT(27)
+#define BIT_IQK_DONE		BIT(26)
+#define BIT_MASK_RES_RY		GENMASK(25, 16)
+#define REG_PAGE_F_RST_11N		0x0f14
+#define BIT_MASK_F_RST_ALL		BIT(16)
+#define REG_IGI_C_11N			0x0f84
+#define REG_IGI_D_11N			0x0f88
+#define REG_HT_CRC32_CNT_11N		0x0f90
+#define BIT_MASK_HT_CRC_OK		GENMASK(15, 0)
+#define BIT_MASK_HT_CRC_ERR		GENMASK(31, 16)
+#define REG_OFDM_CRC32_CNT_11N		0x0f94
+#define BIT_MASK_OFDM_LCRC_OK		GENMASK(15, 0)
+#define BIT_MASK_OFDM_LCRC_ERR		GENMASK(31, 16)
+#define REG_HT_CRC32_CNT_11N_AGG	0x0fb8
+
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/rtw8723d_table.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/rtw8723d_table.c
@@ -0,0 +1,1196 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2018-2019  Realtek Corporation
+ */
+
+#include "main.h"
+#include "phy.h"
+#include "rtw8723d_table.h"
+
+static const u32 rtw8723d_mac[] = {
+	0x020, 0x00000013,
+	0x02F, 0x00000010,
+	0x077, 0x00000007,
+	0x421, 0x0000000F,
+	0x428, 0x0000000A,
+	0x429, 0x00000010,
+	0x430, 0x00000000,
+	0x431, 0x00000000,
+	0x432, 0x00000000,
+	0x433, 0x00000001,
+	0x434, 0x00000002,
+	0x435, 0x00000003,
+	0x436, 0x00000005,
+	0x437, 0x00000007,
+	0x438, 0x00000000,
+	0x439, 0x00000000,
+	0x43A, 0x00000000,
+	0x43B, 0x00000001,
+	0x43C, 0x00000002,
+	0x43D, 0x00000003,
+	0x43E, 0x00000005,
+	0x43F, 0x00000007,
+	0x440, 0x0000005D,
+	0x441, 0x00000001,
+	0x442, 0x00000000,
+	0x444, 0x00000010,
+	0x445, 0x00000000,
+	0x446, 0x00000000,
+	0x447, 0x00000000,
+	0x448, 0x00000000,
+	0x449, 0x000000F0,
+	0x44A, 0x0000000F,
+	0x44B, 0x0000003E,
+	0x44C, 0x00000010,
+	0x44D, 0x00000000,
+	0x44E, 0x00000000,
+	0x44F, 0x00000000,
+	0x450, 0x00000000,
+	0x451, 0x000000F0,
+	0x452, 0x0000000F,
+	0x453, 0x00000000,
+	0x456, 0x0000005E,
+	0x460, 0x00000066,
+	0x461, 0x00000066,
+	0x4C8, 0x000000FF,
+	0x4C9, 0x00000008,
+	0x4CC, 0x000000FF,
+	0x4CD, 0x000000FF,
+	0x4CE, 0x00000001,
+	0x500, 0x00000026,
+	0x501, 0x000000A2,
+	0x502, 0x0000002F,
+	0x503, 0x00000000,
+	0x504, 0x00000028,
+	0x505, 0x000000A3,
+	0x506, 0x0000005E,
+	0x507, 0x00000000,
+	0x508, 0x0000002B,
+	0x509, 0x000000A4,
+	0x50A, 0x0000005E,
+	0x50B, 0x00000000,
+	0x50C, 0x0000004F,
+	0x50D, 0x000000A4,
+	0x50E, 0x00000000,
+	0x50F, 0x00000000,
+	0x512, 0x0000001C,
+	0x514, 0x0000000A,
+	0x516, 0x0000000A,
+	0x525, 0x0000004F,
+	0x550, 0x00000010,
+	0x551, 0x00000010,
+	0x559, 0x00000002,
+	0x55C, 0x00000028,
+	0x55D, 0x000000FF,
+	0x605, 0x00000030,
+	0x608, 0x0000000E,
+	0x609, 0x0000002A,
+	0x620, 0x000000FF,
+	0x621, 0x000000FF,
+	0x622, 0x000000FF,
+	0x623, 0x000000FF,
+	0x624, 0x000000FF,
+	0x625, 0x000000FF,
+	0x626, 0x000000FF,
+	0x627, 0x000000FF,
+	0x638, 0x00000028,
+	0x63C, 0x0000000A,
+	0x63D, 0x0000000A,
+	0x63E, 0x0000000C,
+	0x63F, 0x0000000C,
+	0x640, 0x00000040,
+	0x642, 0x00000040,
+	0x643, 0x00000000,
+	0x652, 0x000000C8,
+	0x66A, 0x000000B0,
+	0x66E, 0x00000005,
+	0x700, 0x00000021,
+	0x701, 0x00000043,
+	0x702, 0x00000065,
+	0x703, 0x00000087,
+	0x708, 0x00000021,
+	0x709, 0x00000043,
+	0x70A, 0x00000065,
+	0x70B, 0x00000087,
+	0x765, 0x00000018,
+	0x76E, 0x00000004,
+	0x7C0, 0x00000038,
+	0x7C2, 0x0000000F,
+	0x7C3, 0x000000C0,
+	0x073, 0x00000004,
+	0x7C4, 0x00000077,
+	0x07C, 0x00000003,
+	0x016, 0x000000B3,
+};
+
+RTW_DECL_TABLE_PHY_COND(rtw8723d_mac, rtw_phy_cfg_mac);
+
+static const u32 rtw8723d_agc[] = {
+	0xC78, 0xFE000101,
+	0xC78, 0xFD010101,
+	0xC78, 0xFC020101,
+	0xC78, 0xFB030101,
+	0xC78, 0xFA040101,
+	0xC78, 0xF9050101,
+	0xC78, 0xF8060101,
+	0xC78, 0xF7070101,
+	0xC78, 0xF6080101,
+	0xC78, 0xF5090101,
+	0xC78, 0xF40A0101,
+	0xC78, 0xF30B0101,
+	0xC78, 0xF20C0101,
+	0xC78, 0xF10D0101,
+	0xC78, 0xF00E0101,
+	0xC78, 0xEF0F0101,
+	0xC78, 0xEE100101,
+	0xC78, 0xED110101,
+	0xC78, 0xEC120101,
+	0xC78, 0xEB130101,
+	0xC78, 0xEA140101,
+	0xC78, 0xE9150101,
+	0xC78, 0xE8160101,
+	0xC78, 0xE7170101,
+	0xC78, 0xE6180101,
+	0xC78, 0xE5190101,
+	0xC78, 0xE41A0101,
+	0xC78, 0xE31B0101,
+	0xC78, 0xE21C0101,
+	0xC78, 0xE11D0101,
+	0xC78, 0xE01E0101,
+	0xC78, 0x861F0101,
+	0xC78, 0x85200101,
+	0xC78, 0x84210101,
+	0xC78, 0x83220101,
+	0xC78, 0x82230101,
+	0xC78, 0x81240101,
+	0xC78, 0x80250101,
+	0xC78, 0x44260101,
+	0xC78, 0x43270101,
+	0xC78, 0x42280101,
+	0xC78, 0x41290101,
+	0xC78, 0x402A0101,
+	0xC78, 0x022B0101,
+	0xC78, 0x012C0101,
+	0xC78, 0x002D0101,
+	0xC78, 0xC52E0001,
+	0xC78, 0xC42F0001,
+	0xC78, 0xC3300001,
+	0xC78, 0xC2310001,
+	0xC78, 0xC1320001,
+	0xC78, 0xC0330001,
+	0xC78, 0x04340001,
+	0xC78, 0x03350001,
+	0xC78, 0x02360001,
+	0xC78, 0x01370001,
+	0xC78, 0x00380001,
+	0xC78, 0x00390001,
+	0xC78, 0x003A0001,
+	0xC78, 0x003B0001,
+	0xC78, 0x003C0001,
+	0xC78, 0x003D0001,
+	0xC78, 0x003E0001,
+	0xC78, 0x003F0001,
+	0xC78, 0x6F002001,
+	0xC78, 0x6F012001,
+	0xC78, 0x6F022001,
+	0xC78, 0x6F032001,
+	0xC78, 0x6F042001,
+	0xC78, 0x6F052001,
+	0xC78, 0x6F062001,
+	0xC78, 0x6F072001,
+	0xC78, 0x6F082001,
+	0xC78, 0x6F092001,
+	0xC78, 0x6F0A2001,
+	0xC78, 0x6F0B2001,
+	0xC78, 0x6F0C2001,
+	0xC78, 0x6F0D2001,
+	0xC78, 0x6F0E2001,
+	0xC78, 0x6F0F2001,
+	0xC78, 0x6F102001,
+	0xC78, 0x6F112001,
+	0xC78, 0x6F122001,
+	0xC78, 0x6F132001,
+	0xC78, 0x6F142001,
+	0xC78, 0x6F152001,
+	0xC78, 0x6F162001,
+	0xC78, 0x6F172001,
+	0xC78, 0x6F182001,
+	0xC78, 0x6F192001,
+	0xC78, 0x6F1A2001,
+	0xC78, 0x6F1B2001,
+	0xC78, 0x6F1C2001,
+	0xC78, 0x6F1D2001,
+	0xC78, 0x6F1E2001,
+	0xC78, 0x6F1F2001,
+	0xC78, 0x6F202001,
+	0xC78, 0x6F212001,
+	0xC78, 0x6F222001,
+	0xC78, 0x6F232001,
+	0xC78, 0x6E242001,
+	0xC78, 0x6D252001,
+	0xC78, 0x6C262001,
+	0xC78, 0x6B272001,
+	0xC78, 0x6A282001,
+	0xC78, 0x69292001,
+	0xC78, 0x4B2A2001,
+	0xC78, 0x4A2B2001,
+	0xC78, 0x492C2001,
+	0xC78, 0x482D2001,
+	0xC78, 0x472E2001,
+	0xC78, 0x462F2001,
+	0xC78, 0x45302001,
+	0xC78, 0x44312001,
+	0xC78, 0x43322001,
+	0xC78, 0x42332001,
+	0xC78, 0x41342001,
+	0xC78, 0x40352001,
+	0xC78, 0x02362001,
+	0xC78, 0x01372001,
+	0xC78, 0x00382001,
+	0xC78, 0x00392001,
+	0xC78, 0x003A2001,
+	0xC78, 0x003B2001,
+	0xC78, 0x003C2001,
+	0xC78, 0x003D2001,
+	0xC78, 0x003E2001,
+	0xC78, 0x003F2001,
+	0xC78, 0x7F003101,
+	0xC78, 0x7F013101,
+	0xC78, 0x7F023101,
+	0xC78, 0x7F033101,
+	0xC78, 0x7F043101,
+	0xC78, 0x7F053101,
+	0xC78, 0x7F063101,
+	0xC78, 0x7F073101,
+	0xC78, 0x7E083101,
+	0xC78, 0x7D093101,
+	0xC78, 0x7C0A3101,
+	0xC78, 0x7B0B3101,
+	0xC78, 0x7A0C3101,
+	0xC78, 0x790D3101,
+	0xC78, 0x780E3101,
+	0xC78, 0x770F3101,
+	0xC78, 0x76103101,
+	0xC78, 0x75113101,
+	0xC78, 0x74123101,
+	0xC78, 0x73133101,
+	0xC78, 0x72143101,
+	0xC78, 0x71153101,
+	0xC78, 0x70163101,
+	0xC78, 0x6F173101,
+	0xC78, 0x6E183101,
+	0xC78, 0x6D193101,
+	0xC78, 0x6C1A3101,
+	0xC78, 0x6B1B3101,
+	0xC78, 0x6A1C3101,
+	0xC78, 0x691D3101,
+	0xC78, 0x681E3101,
+	0xC78, 0x4B1F3101,
+	0xC78, 0x4A203101,
+	0xC78, 0x49213101,
+	0xC78, 0x48223101,
+	0xC78, 0x47233101,
+	0xC78, 0x46243101,
+	0xC78, 0x45253101,
+	0xC78, 0x44263101,
+	0xC78, 0x43273101,
+	0xC78, 0x42283101,
+	0xC78, 0x41293101,
+	0xC78, 0x402A3101,
+	0xC78, 0x022B3101,
+	0xC78, 0x012C3101,
+	0xC78, 0x002D3101,
+	0xC78, 0x002E3101,
+	0xC78, 0x002F3101,
+	0xC78, 0x00303101,
+	0xC78, 0x00313101,
+	0xC78, 0x00323101,
+	0xC78, 0x00333101,
+	0xC78, 0x00343101,
+	0xC78, 0x00353101,
+	0xC78, 0x00363101,
+	0xC78, 0x00373101,
+	0xC78, 0x00383101,
+	0xC78, 0x00393101,
+	0xC78, 0x003A3101,
+	0xC78, 0x003B3101,
+	0xC78, 0x003C3101,
+	0xC78, 0x003D3101,
+	0xC78, 0x003E3101,
+	0xC78, 0x003F3101,
+	0xC78, 0xFE403101,
+	0xC78, 0xFD413101,
+	0xC78, 0xFC423101,
+	0xC78, 0xFB433101,
+	0xC78, 0xFA443101,
+	0xC78, 0xF9453101,
+	0xC78, 0xF8463101,
+	0xC78, 0xF7473101,
+	0xC78, 0xF6483101,
+	0xC78, 0xF5493101,
+	0xC78, 0xF44A3101,
+	0xC78, 0xF34B3101,
+	0xC78, 0xF24C3101,
+	0xC78, 0xF14D3101,
+	0xC78, 0xF04E3101,
+	0xC78, 0xEF4F3101,
+	0xC78, 0xEE503101,
+	0xC78, 0xED513101,
+	0xC78, 0xEC523101,
+	0xC78, 0xEB533101,
+	0xC78, 0xEA543101,
+	0xC78, 0xE9553101,
+	0xC78, 0xE8563101,
+	0xC78, 0xE7573101,
+	0xC78, 0xE6583101,
+	0xC78, 0xE5593101,
+	0xC78, 0xE45A3101,
+	0xC78, 0xE35B3101,
+	0xC78, 0xE25C3101,
+	0xC78, 0xE15D3101,
+	0xC78, 0xE05E3101,
+	0xC78, 0x865F3101,
+	0xC78, 0x85603101,
+	0xC78, 0x84613101,
+	0xC78, 0x83623101,
+	0xC78, 0x82633101,
+	0xC78, 0x81643101,
+	0xC78, 0x80653101,
+	0xC78, 0x80663101,
+	0xC78, 0x80673101,
+	0xC78, 0x80683101,
+	0xC78, 0x80693101,
+	0xC78, 0x806A3101,
+	0xC78, 0x806B3101,
+	0xC78, 0x806C3101,
+	0xC78, 0x806D3101,
+	0xC78, 0x806E3101,
+	0xC78, 0x806F3101,
+	0xC78, 0x80703101,
+	0xC78, 0x80713101,
+	0xC78, 0x80723101,
+	0xC78, 0x80733101,
+	0xC78, 0x80743101,
+	0xC78, 0x80753101,
+	0xC78, 0x80763101,
+	0xC78, 0x80773101,
+	0xC78, 0x80783101,
+	0xC78, 0x80793101,
+	0xC78, 0x807A3101,
+	0xC78, 0x807B3101,
+	0xC78, 0x807C3101,
+	0xC78, 0x807D3101,
+	0xC78, 0x807E3101,
+	0xC78, 0x807F3101,
+	0xC78, 0xEF402001,
+	0xC78, 0xEF412001,
+	0xC78, 0xEF422001,
+	0xC78, 0xEF432001,
+	0xC78, 0xEF442001,
+	0xC78, 0xEF452001,
+	0xC78, 0xEF462001,
+	0xC78, 0xEF472001,
+	0xC78, 0xEF482001,
+	0xC78, 0xEF492001,
+	0xC78, 0xEF4A2001,
+	0xC78, 0xEF4B2001,
+	0xC78, 0xEF4C2001,
+	0xC78, 0xEF4D2001,
+	0xC78, 0xEF4E2001,
+	0xC78, 0xEF4F2001,
+	0xC78, 0xEF502001,
+	0xC78, 0xEF512001,
+	0xC78, 0xEF522001,
+	0xC78, 0xEF532001,
+	0xC78, 0xEF542001,
+	0xC78, 0xEF552001,
+	0xC78, 0xEF562001,
+	0xC78, 0xEF572001,
+	0xC78, 0xEF582001,
+	0xC78, 0xEF592001,
+	0xC78, 0xEF5A2001,
+	0xC78, 0xEF5B2001,
+	0xC78, 0xEF5C2001,
+	0xC78, 0xEF5D2001,
+	0xC78, 0xEF5E2001,
+	0xC78, 0xEF5F2001,
+	0xC78, 0xEF602001,
+	0xC78, 0xEE612001,
+	0xC78, 0xED622001,
+	0xC78, 0xEC632001,
+	0xC78, 0xEB642001,
+	0xC78, 0xEA652001,
+	0xC78, 0xE9662001,
+	0xC78, 0xE8672001,
+	0xC78, 0xCB682001,
+	0xC78, 0xCA692001,
+	0xC78, 0xC96A2001,
+	0xC78, 0xC86B2001,
+	0xC78, 0xC76C2001,
+	0xC78, 0xC66D2001,
+	0xC78, 0xC56E2001,
+	0xC78, 0xC46F2001,
+	0xC78, 0xC3702001,
+	0xC78, 0xC2712001,
+	0xC78, 0xC1722001,
+	0xC78, 0xC0732001,
+	0xC78, 0x82742001,
+	0xC78, 0x81752001,
+	0xC78, 0x80762001,
+	0xC78, 0x80772001,
+	0xC78, 0x80782001,
+	0xC78, 0x80792001,
+	0xC78, 0x807A2001,
+	0xC78, 0x807B2001,
+	0xC78, 0x807C2001,
+	0xC78, 0x807D2001,
+	0xC78, 0x807E2001,
+	0xC78, 0x807F2001,
+	0xC78, 0xFA001101,
+	0xC78, 0xF9011101,
+	0xC78, 0xF8021101,
+	0xC78, 0xF7031101,
+	0xC78, 0xF6041101,
+	0xC78, 0xF5051101,
+	0xC78, 0xF4061101,
+	0xC78, 0xD7071101,
+	0xC78, 0xD6081101,
+	0xC78, 0xD5091101,
+	0xC78, 0xD40A1101,
+	0xC78, 0x970B1101,
+	0xC78, 0x960C1101,
+	0xC78, 0x950D1101,
+	0xC78, 0x940E1101,
+	0xC78, 0x930F1101,
+	0xC78, 0x92101101,
+	0xC78, 0x91111101,
+	0xC78, 0x90121101,
+	0xC78, 0x8F131101,
+	0xC78, 0x8E141101,
+	0xC78, 0x8D151101,
+	0xC78, 0x8C161101,
+	0xC78, 0x8B171101,
+	0xC78, 0x8A181101,
+	0xC78, 0x89191101,
+	0xC78, 0x881A1101,
+	0xC78, 0x871B1101,
+	0xC78, 0x861C1101,
+	0xC78, 0x851D1101,
+	0xC78, 0x841E1101,
+	0xC78, 0x831F1101,
+	0xC78, 0x82201101,
+	0xC78, 0x81211101,
+	0xC78, 0x80221101,
+	0xC78, 0x43231101,
+	0xC78, 0x42241101,
+	0xC78, 0x41251101,
+	0xC78, 0x04261101,
+	0xC78, 0x03271101,
+	0xC78, 0x02281101,
+	0xC78, 0x01291101,
+	0xC78, 0x002A1101,
+	0xC78, 0xC42B1001,
+	0xC78, 0xC32C1001,
+	0xC78, 0xC22D1001,
+	0xC78, 0xC12E1001,
+	0xC78, 0xC02F1001,
+	0xC78, 0x85301001,
+	0xC78, 0x84311001,
+	0xC78, 0x83321001,
+	0xC78, 0x82331001,
+	0xC78, 0x81341001,
+	0xC78, 0x80351001,
+	0xC78, 0x05361001,
+	0xC78, 0x04371001,
+	0xC78, 0x03381001,
+	0xC78, 0x02391001,
+	0xC78, 0x013A1001,
+	0xC78, 0x003B1001,
+	0xC78, 0x003C1001,
+	0xC78, 0x003D1001,
+	0xC78, 0x003E1001,
+	0xC78, 0x003F1001,
+	0xC50, 0x69553422,
+	0xC50, 0x69553420,
+};
+
+RTW_DECL_TABLE_PHY_COND(rtw8723d_agc, rtw_phy_cfg_agc);
+
+static const u32 rtw8723d_bb[] = {
+	0x800, 0x80046C00,
+	0x804, 0x00000003,
+	0x808, 0x0000FC00,
+	0x80C, 0x0000000A,
+	0x810, 0x10001331,
+	0x814, 0x020C3D10,
+	0x818, 0x00200385,
+	0x81C, 0x00000000,
+	0x820, 0x01000100,
+	0x824, 0x00390204,
+	0x828, 0x00000000,
+	0x82C, 0x00000000,
+	0x830, 0x00000000,
+	0x834, 0x00000000,
+	0x838, 0x00000000,
+	0x83C, 0x00000000,
+	0x840, 0x00010000,
+	0x844, 0x00000000,
+	0x848, 0x00000000,
+	0x84C, 0x00000000,
+	0x850, 0x00000000,
+	0x854, 0x00000000,
+	0x858, 0x569A11A9,
+	0x85C, 0x01000014,
+	0x860, 0x66F60110,
+	0x864, 0x461F0641,
+	0x868, 0x00000000,
+	0x86C, 0x27272700,
+	0x870, 0x07000460,
+	0x874, 0x25004000,
+	0x878, 0x00000808,
+	0x87C, 0x004F0201,
+	0x880, 0xB2002E12,
+	0x884, 0x00000007,
+	0x888, 0x00000000,
+	0x88C, 0xCCC000C0,
+	0x890, 0x00000800,
+	0x894, 0xFFFFFFFE,
+	0x898, 0x40302010,
+	0x89C, 0x00706050,
+	0x900, 0x00000000,
+	0x904, 0x00000023,
+	0x908, 0x00000000,
+	0x90C, 0x81121111,
+	0x910, 0x00000402,
+	0x914, 0x00000300,
+	0x920, 0x18C6318C,
+	0x924, 0x0000018C,
+	0x948, 0x99000000,
+	0x94C, 0x00000010,
+	0x950, 0x00003800,
+	0x954, 0x5A380000,
+	0x958, 0x4BC6D87A,
+	0x95C, 0x04EB9B79,
+	0x96C, 0x00000003,
+	0x970, 0x00000000,
+	0x974, 0x00000000,
+	0x978, 0x00000000,
+	0x97C, 0x13000000,
+	0x980, 0x00000000,
+	0xA00, 0x00D046C8,
+	0xA04, 0x80FF800C,
+	0xA08, 0x8C838300,
+	0xA0C, 0x2E20100F,
+	0xA10, 0x9500BB78,
+	0xA14, 0x1114D028,
+	0xA18, 0x00881117,
+	0xA1C, 0x89140F00,
+	0xA20, 0xE82C0001,
+	0xA24, 0x64B80C1C,
+	0xA28, 0x00008810,
+	0xA2C, 0x00D30000,
+	0xA70, 0x101FBF00,
+	0xA74, 0x00000007,
+	0xA78, 0x00008900,
+	0xA7C, 0x225B0606,
+	0xA80, 0x2180FA74,
+	0xA84, 0x00200000,
+	0xA88, 0x040C0000,
+	0xA8C, 0x12345678,
+	0xA90, 0xABCDEF00,
+	0xA94, 0x001B1B89,
+	0xA98, 0x00000000,
+	0xA9C, 0x00020000,
+	0xAA0, 0x00000000,
+	0xAA4, 0x0000000C,
+	0xAA8, 0xCA100008,
+	0xAAC, 0x01235667,
+	0xAB0, 0x00000000,
+	0xAB4, 0x20201402,
+	0xB2C, 0x00000000,
+	0xC00, 0x48071D40,
+	0xC04, 0x03A05611,
+	0xC08, 0x000000E4,
+	0xC0C, 0x6C6C6C6C,
+	0xC10, 0x28800000,
+	0xC14, 0x40000100,
+	0xC18, 0x08800000,
+	0xC1C, 0x40000100,
+	0xC20, 0x00000000,
+	0xC24, 0x00000000,
+	0xC28, 0x00000000,
+	0xC2C, 0x00000000,
+	0xC30, 0x69E9AC48,
+	0xC34, 0x31000040,
+	0xC38, 0x21688080,
+	0xC3C, 0x000016D4,
+	0xC40, 0x1F78403F,
+	0xC44, 0x00010036,
+	0xC48, 0xEC020107,
+	0xC4C, 0x007F037F,
+	0xC50, 0x69553420,
+	0xC54, 0x43BC0094,
+	0xC58, 0x00015969,
+	0xC5C, 0x00310492,
+	0xC60, 0x00280A00,
+	0xC64, 0x7112848B,
+	0xC68, 0x47C074FF,
+	0xC6C, 0x00000036,
+	0xC70, 0x2C7F000D,
+	0xC74, 0x020600DB,
+	0xC78, 0x0000001F,
+	0xC7C, 0x00B91612,
+	0xC80, 0x390000E4,
+	0xC84, 0x21F60000,
+	0xC88, 0x40000100,
+	0xC8C, 0x20200000,
+	0xC90, 0x00091521,
+	0xC94, 0x00000000,
+	0xC98, 0x00121820,
+	0xC9C, 0x00007F7F,
+	0xCA0, 0x00012000,
+	0xCA4, 0x800000A0,
+	0xCA8, 0x84E6C606,
+	0xCAC, 0x00000060,
+	0xCB0, 0x00000000,
+	0xCB4, 0x00000000,
+	0xCB8, 0x00000000,
+	0xCBC, 0x28000000,
+	0xCC0, 0x0010A3D0,
+	0xCC4, 0x00000F7D,
+	0xCC8, 0x000442D6,
+	0xCCC, 0x00000000,
+	0xCD0, 0x000001C8,
+	0xCD4, 0x001C8000,
+	0xCD8, 0x00000100,
+	0xCDC, 0x40100000,
+	0xCE0, 0x00222220,
+	0xCE4, 0x20000000,
+	0xCE8, 0x37644302,
+	0xCEC, 0x2F97D40C,
+	0xD00, 0x00030740,
+	0xD04, 0x40020401,
+	0xD08, 0x0000907F,
+	0xD0C, 0x20010201,
+	0xD10, 0xA0633333,
+	0xD14, 0x3333BC53,
+	0xD18, 0x7A8F5B6F,
+	0xD2C, 0xCC979975,
+	0xD30, 0x00000000,
+	0xD34, 0x40608000,
+	0xD38, 0x88000000,
+	0xD3C, 0xC0127343,
+	0xD40, 0x00000000,
+	0xD44, 0x00000000,
+	0xD48, 0x00000000,
+	0xD4C, 0x00000000,
+	0xD50, 0x00000038,
+	0xD54, 0x00000000,
+	0xD58, 0x00000282,
+	0xD5C, 0x30032064,
+	0xD60, 0x4653DE68,
+	0xD64, 0x04518A3C,
+	0xD68, 0x00002101,
+	0xE00, 0x2D2D2D2D,
+	0xE04, 0x2D2D2D2D,
+	0xE08, 0x0390272D,
+	0xE10, 0x2D2D2D2D,
+	0xE14, 0x2D2D2D2D,
+	0xE18, 0x2D2D2D2D,
+	0xE1C, 0x2D2D2D2D,
+	0xE28, 0x00000000,
+	0xE30, 0x1000DC1F,
+	0xE34, 0x10008C1F,
+	0xE38, 0x02140102,
+	0xE3C, 0x681604C2,
+	0xE40, 0x01007C00,
+	0xE44, 0x01004800,
+	0xE48, 0xFB000000,
+	0xE4C, 0x000028D1,
+	0xE50, 0x1000DC1F,
+	0xE54, 0x10008C1F,
+	0xE58, 0x02140102,
+	0xE5C, 0x28160D05,
+	0xE60, 0x00000008,
+	0xE68, 0x001B25A4,
+	0xE6C, 0x01C00014,
+	0xE70, 0x01C00016,
+	0xE74, 0x02000014,
+	0xE78, 0x02000014,
+	0xE7C, 0x02000014,
+	0xE80, 0x02000014,
+	0xE84, 0x01C00014,
+	0xE88, 0x02000014,
+	0xE8C, 0x01C00014,
+	0xED0, 0x01C00014,
+	0xED4, 0x01C00014,
+	0xED8, 0x01C00014,
+	0xEDC, 0x00000014,
+	0xEE0, 0x00000014,
+	0xEE8, 0x21555448,
+	0xEEC, 0x03C00014,
+	0xF14, 0x00000003,
+	0xF00, 0x00100300,
+	0xF08, 0x0000800B,
+	0xF0C, 0x0000F007,
+	0xF10, 0x0000A487,
+	0xF1C, 0x80000064,
+	0xF38, 0x00030155,
+	0xF3C, 0x0000003A,
+	0xF4C, 0x13000000,
+	0xF50, 0x00000000,
+	0xF18, 0x00000000,
+};
+
+RTW_DECL_TABLE_PHY_COND(rtw8723d_bb, rtw_phy_cfg_bb);
+
+static const struct rtw_phy_pg_cfg_pair rtw8723d_bb_pg[] = {
+	{ 0, 0, 0, 0x00000e08, 0x0000ff00, 0x00003200, },
+	{ 0, 0, 0, 0x0000086c, 0xffffff00, 0x32323200, },
+	{ 0, 0, 0, 0x00000e00, 0xffffffff, 0x32343434, },
+	{ 0, 0, 0, 0x00000e04, 0xffffffff, 0x28303032, },
+	{ 0, 0, 0, 0x00000e10, 0xffffffff, 0x30323234, },
+	{ 0, 0, 0, 0x00000e14, 0xffffffff, 0x26282830, },
+};
+
+RTW_DECL_TABLE_BB_PG(rtw8723d_bb_pg);
+
+static const u32 rtw8723d_rf_a[] = {
+		0x050, 0x0001C000,
+		0x049, 0x0004AA00,
+		0x000, 0x00010000,
+		0x0B1, 0x00054573,
+		0x0B4, 0x000508AB,
+		0x0B7, 0x00014787,
+		0x0B8, 0x000064CB,
+		0x01B, 0x00073A40,
+		0x051, 0x00038CAF,
+		0x052, 0x000FCCA3,
+		0x053, 0x00090F38,
+		0x054, 0x00011083,
+		0x057, 0x000D0000,
+		0x08D, 0x00000A1A,
+		0x082, 0x00082AAC,
+		0x08E, 0x00076940,
+		0x08F, 0x00088400,
+		0x061, 0x00038CAF,
+		0x062, 0x000FCCA3,
+		0x063, 0x00090F38,
+		0x064, 0x00011083,
+		0x067, 0x000D0000,
+		0x092, 0x00082AAC,
+		0x0EF, 0x00000400,
+		0x030, 0x000008CA,
+		0x030, 0x000018CA,
+		0x030, 0x000028CA,
+		0x030, 0x000038CA,
+		0x0EF, 0x00000000,
+		0x0EE, 0x00000400,
+		0x030, 0x000008CA,
+		0x030, 0x000018CA,
+		0x030, 0x000028CA,
+		0x030, 0x000038CA,
+		0x0EE, 0x00000000,
+		0x0EF, 0x00000100,
+		0x033, 0x00000000,
+		0x03F, 0x0000CCA3,
+		0x033, 0x00000001,
+		0x03F, 0x0000CCA3,
+		0x033, 0x00000002,
+		0x03F, 0x0000CCA3,
+		0x033, 0x00000003,
+		0x03F, 0x0000CCA3,
+		0x033, 0x00000004,
+		0x03F, 0x0000CCA3,
+		0x033, 0x00000005,
+		0x03F, 0x0000CCA3,
+		0x033, 0x00000006,
+		0x03F, 0x0000CCA3,
+		0x033, 0x00000007,
+		0x03F, 0x0000CCA3,
+		0x0EF, 0x00000000,
+		0x0EE, 0x00000100,
+		0x033, 0x00000000,
+		0x03F, 0x0000CCA3,
+		0x033, 0x00000001,
+		0x03F, 0x0000CCA3,
+		0x033, 0x00000002,
+		0x03F, 0x0000CCA3,
+		0x033, 0x00000003,
+		0x03F, 0x0000CCA3,
+		0x033, 0x00000004,
+		0x03F, 0x0000CCA3,
+		0x033, 0x00000005,
+		0x03F, 0x0000CCA3,
+		0x033, 0x00000006,
+		0x03F, 0x0000CCA3,
+		0x033, 0x00000007,
+		0x03F, 0x0000CCA3,
+		0x0EE, 0x00000000,
+		0x0EF, 0x00000800,
+		0x030, 0x0000002D,
+		0x030, 0x0000122C,
+		0x030, 0x0000222F,
+		0x030, 0x0000326C,
+		0x030, 0x0000466B,
+		0x030, 0x0000566E,
+		0x030, 0x000066EB,
+		0x030, 0x000077EC,
+		0x030, 0x000087EF,
+		0x030, 0x000097F2,
+		0x030, 0x0000A7F5,
+		0x0EF, 0x00000000,
+		0x0EE, 0x00000800,
+		0x030, 0x00000001,
+		0x030, 0x00001011,
+		0x030, 0x00002011,
+		0x030, 0x00003013,
+		0x030, 0x00004033,
+		0x030, 0x00005033,
+		0x030, 0x00006037,
+		0x030, 0x0000703F,
+		0x030, 0x0000803F,
+		0x030, 0x0000903F,
+		0x030, 0x0000A03F,
+		0x0EE, 0x00000000,
+		0x082, 0x00083B8C,
+		0x0ED, 0x00000008,
+		0x030, 0x000030F6,
+		0x030, 0x00002004,
+		0x030, 0x000010F6,
+		0x030, 0x000000F6,
+		0x0ED, 0x00000000,
+		0x092, 0x00083B8C,
+		0x0EC, 0x00000008,
+		0x030, 0x000030F6,
+		0x030, 0x00002004,
+		0x030, 0x000010F6,
+		0x030, 0x000000F6,
+		0x0EC, 0x00000000,
+		0x0EF, 0x00010000,
+		0x030, 0x0001C11C,
+		0x030, 0x000181F4,
+		0x030, 0x00014108,
+		0x030, 0x000101E4,
+		0x030, 0x0000C11C,
+		0x030, 0x000081F4,
+		0x030, 0x00004108,
+		0x030, 0x000001E4,
+		0x0EF, 0x00000000,
+		0x0EE, 0x00010000,
+		0x030, 0x0001C11C,
+		0x030, 0x000181F4,
+		0x030, 0x00014108,
+		0x030, 0x000101E4,
+		0x030, 0x0000C11C,
+		0x030, 0x000081F4,
+		0x030, 0x00004108,
+		0x030, 0x000001E4,
+		0x0EE, 0x00000000,
+		0x0EF, 0x00080000,
+		0x033, 0x00000007,
+		0x03E, 0x0000005F,
+		0x03F, 0x000B3FDB,
+		0x033, 0x00000004,
+		0x03E, 0x0000005D,
+		0x03F, 0x000BFFE0,
+		0x033, 0x00000005,
+		0x03E, 0x0000005D,
+		0x03F, 0x000FBFCE,
+		0x033, 0x00000006,
+		0x03E, 0x0000005F,
+		0x03F, 0x000A7FFB,
+		0x0EF, 0x00000000,
+		0x0EE, 0x00000002,
+		0x030, 0x00000001,
+		0x030, 0x00002001,
+		0x030, 0x00004001,
+		0x030, 0x00007001,
+		0x030, 0x00006001,
+		0x030, 0x00020001,
+		0x030, 0x00022001,
+		0x030, 0x00024001,
+		0x030, 0x00027001,
+		0x030, 0x00026001,
+		0x030, 0x00034001,
+		0x030, 0x00037001,
+		0x030, 0x00036001,
+		0x030, 0x00008000,
+		0x030, 0x0000A000,
+		0x030, 0x0000C000,
+	0x83000100,	0x00000000,	0x40000000,	0x00000000,
+		0x030, 0x0000E024,
+	0xA0000000,	0x00000000,
+		0x030, 0x0000E000,
+	0xB0000000,	0x00000000,
+		0x030, 0x0001C000,
+		0x030, 0x0001E000,
+		0x0EE, 0x00000000,
+		0x0EE, 0x00020000,
+		0x0EF, 0x00020000,
+		0x030, 0x00000F75,
+		0x030, 0x00002F55,
+		0x030, 0x00003F75,
+		0x0EE, 0x00000000,
+		0x0EF, 0x00000000,
+		0x018, 0x00008401,
+		0xFFE, 0x00000000,
+};
+
+RTW_DECL_TABLE_RF_RADIO(rtw8723d_rf_a, A);
+
+static const struct rtw_txpwr_lmt_cfg_pair rtw8723d_txpwr_lmt[] = {
+	{0, 0, 0, 0, 1, 30, },
+	{2, 0, 0, 0, 1, 30, },
+	{1, 0, 0, 0, 1, 30, },
+	{0, 0, 0, 0, 2, 30, },
+	{2, 0, 0, 0, 2, 30, },
+	{1, 0, 0, 0, 2, 30, },
+	{0, 0, 0, 0, 3, 30, },
+	{2, 0, 0, 0, 3, 30, },
+	{1, 0, 0, 0, 3, 30, },
+	{0, 0, 0, 0, 4, 30, },
+	{2, 0, 0, 0, 4, 30, },
+	{1, 0, 0, 0, 4, 30, },
+	{0, 0, 0, 0, 5, 30, },
+	{2, 0, 0, 0, 5, 30, },
+	{1, 0, 0, 0, 5, 30, },
+	{0, 0, 0, 0, 6, 30, },
+	{2, 0, 0, 0, 6, 30, },
+	{1, 0, 0, 0, 6, 30, },
+	{0, 0, 0, 0, 7, 30, },
+	{2, 0, 0, 0, 7, 30, },
+	{1, 0, 0, 0, 7, 30, },
+	{0, 0, 0, 0, 8, 30, },
+	{2, 0, 0, 0, 8, 30, },
+	{1, 0, 0, 0, 8, 30, },
+	{0, 0, 0, 0, 9, 30, },
+	{2, 0, 0, 0, 9, 30, },
+	{1, 0, 0, 0, 9, 30, },
+	{0, 0, 0, 0, 10, 30, },
+	{2, 0, 0, 0, 10, 30, },
+	{1, 0, 0, 0, 10, 30, },
+	{0, 0, 0, 0, 11, 30, },
+	{2, 0, 0, 0, 11, 30, },
+	{1, 0, 0, 0, 11, 30, },
+	{0, 0, 0, 0, 12, 30, },
+	{2, 0, 0, 0, 12, 30, },
+	{1, 0, 0, 0, 12, 30, },
+	{0, 0, 0, 0, 13, 17, },
+	{2, 0, 0, 0, 13, 30, },
+	{1, 0, 0, 0, 13, 30, },
+	{0, 0, 0, 0, 14, 63, },
+	{2, 0, 0, 0, 14, 63, },
+	{1, 0, 0, 0, 14, 30, },
+	{0, 0, 0, 1, 1, 26, },
+	{2, 0, 0, 1, 1, 31, },
+	{1, 0, 0, 1, 1, 31, },
+	{0, 0, 0, 1, 2, 28, },
+	{2, 0, 0, 1, 2, 31, },
+	{1, 0, 0, 1, 2, 31, },
+	{0, 0, 0, 1, 3, 30, },
+	{2, 0, 0, 1, 3, 31, },
+	{1, 0, 0, 1, 3, 31, },
+	{0, 0, 0, 1, 4, 30, },
+	{2, 0, 0, 1, 4, 31, },
+	{1, 0, 0, 1, 4, 31, },
+	{0, 0, 0, 1, 5, 30, },
+	{2, 0, 0, 1, 5, 31, },
+	{1, 0, 0, 1, 5, 31, },
+	{0, 0, 0, 1, 6, 30, },
+	{2, 0, 0, 1, 6, 31, },
+	{1, 0, 0, 1, 6, 31, },
+	{0, 0, 0, 1, 7, 30, },
+	{2, 0, 0, 1, 7, 31, },
+	{1, 0, 0, 1, 7, 31, },
+	{0, 0, 0, 1, 8, 30, },
+	{2, 0, 0, 1, 8, 31, },
+	{1, 0, 0, 1, 8, 31, },
+	{0, 0, 0, 1, 9, 30, },
+	{2, 0, 0, 1, 9, 31, },
+	{1, 0, 0, 1, 9, 31, },
+	{0, 0, 0, 1, 10, 28, },
+	{2, 0, 0, 1, 10, 31, },
+	{1, 0, 0, 1, 10, 31, },
+	{0, 0, 0, 1, 11, 26, },
+	{2, 0, 0, 1, 11, 31, },
+	{1, 0, 0, 1, 11, 31, },
+	{0, 0, 0, 1, 12, 24, },
+	{2, 0, 0, 1, 12, 31, },
+	{1, 0, 0, 1, 12, 31, },
+	{0, 0, 0, 1, 13, 14, },
+	{2, 0, 0, 1, 13, 31, },
+	{1, 0, 0, 1, 13, 31, },
+	{0, 0, 0, 1, 14, 63, },
+	{2, 0, 0, 1, 14, 63, },
+	{1, 0, 0, 1, 14, 63, },
+	{0, 0, 0, 2, 1, 24, },
+	{2, 0, 0, 2, 1, 31, },
+	{1, 0, 0, 2, 1, 31, },
+	{0, 0, 0, 2, 2, 26, },
+	{2, 0, 0, 2, 2, 31, },
+	{1, 0, 0, 2, 2, 31, },
+	{0, 0, 0, 2, 3, 30, },
+	{2, 0, 0, 2, 3, 31, },
+	{1, 0, 0, 2, 3, 31, },
+	{0, 0, 0, 2, 4, 30, },
+	{2, 0, 0, 2, 4, 31, },
+	{1, 0, 0, 2, 4, 31, },
+	{0, 0, 0, 2, 5, 30, },
+	{2, 0, 0, 2, 5, 31, },
+	{1, 0, 0, 2, 5, 31, },
+	{0, 0, 0, 2, 6, 30, },
+	{2, 0, 0, 2, 6, 31, },
+	{1, 0, 0, 2, 6, 31, },
+	{0, 0, 0, 2, 7, 30, },
+	{2, 0, 0, 2, 7, 31, },
+	{1, 0, 0, 2, 7, 31, },
+	{0, 0, 0, 2, 8, 30, },
+	{2, 0, 0, 2, 8, 31, },
+	{1, 0, 0, 2, 8, 31, },
+	{0, 0, 0, 2, 9, 30, },
+	{2, 0, 0, 2, 9, 31, },
+	{1, 0, 0, 2, 9, 31, },
+	{0, 0, 0, 2, 10, 26, },
+	{2, 0, 0, 2, 10, 31, },
+	{1, 0, 0, 2, 10, 31, },
+	{0, 0, 0, 2, 11, 24, },
+	{2, 0, 0, 2, 11, 31, },
+	{1, 0, 0, 2, 11, 31, },
+	{0, 0, 0, 2, 12, 23, },
+	{2, 0, 0, 2, 12, 31, },
+	{1, 0, 0, 2, 12, 31, },
+	{0, 0, 0, 2, 13, 13, },
+	{2, 0, 0, 2, 13, 31, },
+	{1, 0, 0, 2, 13, 31, },
+	{0, 0, 0, 2, 14, 63, },
+	{2, 0, 0, 2, 14, 63, },
+	{1, 0, 0, 2, 14, 63, },
+	{0, 0, 0, 3, 1, 28, },
+	{2, 0, 0, 3, 1, 30, },
+	{1, 0, 0, 3, 1, 30, },
+	{0, 0, 0, 3, 2, 28, },
+	{2, 0, 0, 3, 2, 30, },
+	{1, 0, 0, 3, 2, 30, },
+	{0, 0, 0, 3, 3, 30, },
+	{2, 0, 0, 3, 3, 30, },
+	{1, 0, 0, 3, 3, 30, },
+	{0, 0, 0, 3, 4, 30, },
+	{2, 0, 0, 3, 4, 30, },
+	{1, 0, 0, 3, 4, 30, },
+	{0, 0, 0, 3, 5, 30, },
+	{2, 0, 0, 3, 5, 30, },
+	{1, 0, 0, 3, 5, 30, },
+	{0, 0, 0, 3, 6, 30, },
+	{2, 0, 0, 3, 6, 30, },
+	{1, 0, 0, 3, 6, 30, },
+	{0, 0, 0, 3, 7, 30, },
+	{2, 0, 0, 3, 7, 30, },
+	{1, 0, 0, 3, 7, 30, },
+	{0, 0, 0, 3, 8, 30, },
+	{2, 0, 0, 3, 8, 30, },
+	{1, 0, 0, 3, 8, 30, },
+	{0, 0, 0, 3, 9, 28, },
+	{2, 0, 0, 3, 9, 30, },
+	{1, 0, 0, 3, 9, 30, },
+	{0, 0, 0, 3, 10, 28, },
+	{2, 0, 0, 3, 10, 30, },
+	{1, 0, 0, 3, 10, 30, },
+	{0, 0, 0, 3, 11, 28, },
+	{2, 0, 0, 3, 11, 30, },
+	{1, 0, 0, 3, 11, 30, },
+	{0, 0, 0, 3, 12, 63, },
+	{2, 0, 0, 3, 12, 30, },
+	{1, 0, 0, 3, 12, 30, },
+	{0, 0, 0, 3, 13, 63, },
+	{2, 0, 0, 3, 13, 30, },
+	{1, 0, 0, 3, 13, 30, },
+	{0, 0, 0, 3, 14, 63, },
+	{2, 0, 0, 3, 14, 63, },
+	{1, 0, 0, 3, 14, 63, },
+	{0, 0, 1, 2, 1, 63, },
+	{2, 0, 1, 2, 1, 63, },
+	{1, 0, 1, 2, 1, 63, },
+	{0, 0, 1, 2, 2, 63, },
+	{2, 0, 1, 2, 2, 63, },
+	{1, 0, 1, 2, 2, 63, },
+	{0, 0, 1, 2, 3, 24, },
+	{2, 0, 1, 2, 3, 30, },
+	{1, 0, 1, 2, 3, 30, },
+	{0, 0, 1, 2, 4, 24, },
+	{2, 0, 1, 2, 4, 30, },
+	{1, 0, 1, 2, 4, 30, },
+	{0, 0, 1, 2, 5, 24, },
+	{2, 0, 1, 2, 5, 30, },
+	{1, 0, 1, 2, 5, 30, },
+	{0, 0, 1, 2, 6, 24, },
+	{2, 0, 1, 2, 6, 30, },
+	{1, 0, 1, 2, 6, 30, },
+	{0, 0, 1, 2, 7, 24, },
+	{2, 0, 1, 2, 7, 30, },
+	{1, 0, 1, 2, 7, 30, },
+	{0, 0, 1, 2, 8, 24, },
+	{2, 0, 1, 2, 8, 30, },
+	{1, 0, 1, 2, 8, 30, },
+	{0, 0, 1, 2, 9, 24, },
+	{2, 0, 1, 2, 9, 30, },
+	{1, 0, 1, 2, 9, 30, },
+	{0, 0, 1, 2, 10, 22, },
+	{2, 0, 1, 2, 10, 30, },
+	{1, 0, 1, 2, 10, 30, },
+	{0, 0, 1, 2, 11, 20, },
+	{2, 0, 1, 2, 11, 30, },
+	{1, 0, 1, 2, 11, 30, },
+	{0, 0, 1, 2, 12, 63, },
+	{2, 0, 1, 2, 12, 30, },
+	{1, 0, 1, 2, 12, 30, },
+	{0, 0, 1, 2, 13, 63, },
+	{2, 0, 1, 2, 13, 30, },
+	{1, 0, 1, 2, 13, 30, },
+	{0, 0, 1, 2, 14, 63, },
+	{2, 0, 1, 2, 14, 63, },
+	{1, 0, 1, 2, 14, 63, },
+	{0, 0, 1, 3, 1, 63, },
+	{2, 0, 1, 3, 1, 63, },
+	{1, 0, 1, 3, 1, 63, },
+	{0, 0, 1, 3, 2, 63, },
+	{2, 0, 1, 3, 2, 63, },
+	{1, 0, 1, 3, 2, 63, },
+	{0, 0, 1, 3, 3, 26, },
+	{2, 0, 1, 3, 3, 26, },
+	{1, 0, 1, 3, 3, 26, },
+	{0, 0, 1, 3, 4, 26, },
+	{2, 0, 1, 3, 4, 26, },
+	{1, 0, 1, 3, 4, 26, },
+	{0, 0, 1, 3, 5, 26, },
+	{2, 0, 1, 3, 5, 26, },
+	{1, 0, 1, 3, 5, 26, },
+	{0, 0, 1, 3, 6, 26, },
+	{2, 0, 1, 3, 6, 26, },
+	{1, 0, 1, 3, 6, 26, },
+	{0, 0, 1, 3, 7, 26, },
+	{2, 0, 1, 3, 7, 26, },
+	{1, 0, 1, 3, 7, 26, },
+	{0, 0, 1, 3, 8, 26, },
+	{2, 0, 1, 3, 8, 26, },
+	{1, 0, 1, 3, 8, 26, },
+	{0, 0, 1, 3, 9, 26, },
+	{2, 0, 1, 3, 9, 26, },
+	{1, 0, 1, 3, 9, 26, },
+	{0, 0, 1, 3, 10, 26, },
+	{2, 0, 1, 3, 10, 26, },
+	{1, 0, 1, 3, 10, 26, },
+	{0, 0, 1, 3, 11, 26, },
+	{2, 0, 1, 3, 11, 26, },
+	{1, 0, 1, 3, 11, 26, },
+	{0, 0, 1, 3, 12, 63, },
+	{2, 0, 1, 3, 12, 26, },
+	{1, 0, 1, 3, 12, 26, },
+	{0, 0, 1, 3, 13, 63, },
+	{2, 0, 1, 3, 13, 26, },
+	{1, 0, 1, 3, 13, 26, },
+	{0, 0, 1, 3, 14, 63, },
+	{2, 0, 1, 3, 14, 63, },
+	{1, 0, 1, 3, 14, 63, },
+};
+
+RTW_DECL_TABLE_TXPWR_LMT(rtw8723d_txpwr_lmt);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/rtw8723d_table.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/rtw8723d_table.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2018-2019  Realtek Corporation
+ */
+
+#ifndef __RTW8723D_TABLE_H__
+#define __RTW8723D_TABLE_H__
+
+extern const struct rtw_table rtw8723d_mac_tbl;
+extern const struct rtw_table rtw8723d_agc_tbl;
+extern const struct rtw_table rtw8723d_bb_tbl;
+extern const struct rtw_table rtw8723d_bb_pg_tbl;
+extern const struct rtw_table rtw8723d_rf_a_tbl;
+extern const struct rtw_table rtw8723d_txpwr_lmt_tbl;
+
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/rtw8822b.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/rtw8822b.c
@@ -13,6 +13,7 @@
 #include "mac.h"
 #include "reg.h"
 #include "debug.h"
+#include "bf.h"
 
 static void rtw8822b_config_trx_mode(struct rtw_dev *rtwdev, u8 tx_path,
 				     u8 rx_path, bool is_tx2_path);
@@ -43,6 +44,8 @@
 	efuse->country_code[1] = map->country_code[1];
 	efuse->bt_setting = map->rf_bt_setting;
 	efuse->regd = map->rf_board_option & 0x7;
+	efuse->thermal_meter[RF_PATH_A] = map->thermal_meter;
+	efuse->thermal_meter_k = map->thermal_meter;
 
 	for (i = 0; i < 4; i++)
 		efuse->txpwr_idx_table[i] = map->txpwr_idx_table[i];
@@ -75,6 +78,56 @@
 	rtw_write32_mask(rtwdev, 0x974, (BIT(11) | BIT(10)), 0x3);
 }
 
+#define RTW_TXSCALE_SIZE 37
+static const u32 rtw8822b_txscale_tbl[RTW_TXSCALE_SIZE] = {
+	0x081, 0x088, 0x090, 0x099, 0x0a2, 0x0ac, 0x0b6, 0x0c0, 0x0cc, 0x0d8,
+	0x0e5, 0x0f2, 0x101, 0x110, 0x120, 0x131, 0x143, 0x156, 0x16a, 0x180,
+	0x197, 0x1af, 0x1c8, 0x1e3, 0x200, 0x21e, 0x23e, 0x261, 0x285, 0x2ab,
+	0x2d3, 0x2fe, 0x32b, 0x35c, 0x38e, 0x3c4, 0x3fe
+};
+
+static const u8 rtw8822b_get_swing_index(struct rtw_dev *rtwdev)
+{
+	u8 i = 0;
+	u32 swing, table_value;
+
+	swing = rtw_read32_mask(rtwdev, 0xc1c, 0xffe00000);
+	for (i = 0; i < RTW_TXSCALE_SIZE; i++) {
+		table_value = rtw8822b_txscale_tbl[i];
+		if (swing == table_value)
+			break;
+	}
+
+	return i;
+}
+
+static void rtw8822b_pwrtrack_init(struct rtw_dev *rtwdev)
+{
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+	u8 swing_idx = rtw8822b_get_swing_index(rtwdev);
+	u8 path;
+
+	if (swing_idx >= RTW_TXSCALE_SIZE)
+		dm_info->default_ofdm_index = 24;
+	else
+		dm_info->default_ofdm_index = swing_idx;
+
+	for (path = RF_PATH_A; path < rtwdev->hal.rf_path_num; path++) {
+		ewma_thermal_init(&dm_info->avg_thermal[path]);
+		dm_info->delta_power_index[path] = 0;
+	}
+	dm_info->pwr_trk_triggered = false;
+	dm_info->pwr_trk_init_trigger = true;
+	dm_info->thermal_meter_k = rtwdev->efuse.thermal_meter_k;
+}
+
+static void rtw8822b_phy_bf_init(struct rtw_dev *rtwdev)
+{
+	rtw_bf_phy_init(rtwdev);
+	/* Grouping bitmap parameters */
+	rtw_write32(rtwdev, 0x1C94, 0xAFFFAFFF);
+}
+
 static void rtw8822b_phy_set_param(struct rtw_dev *rtwdev)
 {
 	struct rtw_hal *hal = &rtwdev->hal;
@@ -106,6 +159,9 @@
 	rtw_phy_init(rtwdev);
 
 	rtw8822b_phy_rfe_init(rtwdev);
+	rtw8822b_pwrtrack_init(rtwdev);
+
+	rtw8822b_phy_bf_init(rtwdev);
 }
 
 #define WLAN_SLOT_TIME		0x09
@@ -211,9 +267,8 @@
 static void rtw8822b_set_channel_rfe_efem(struct rtw_dev *rtwdev, u8 channel)
 {
 	struct rtw_hal *hal = &rtwdev->hal;
-	bool is_channel_2g = (channel <= 14) ? true : false;
 
-	if (is_channel_2g) {
+	if (IS_CH_2G_BAND(channel)) {
 		rtw_write32s_mask(rtwdev, REG_RFESEL0, 0xffffff, 0x705770);
 		rtw_write32s_mask(rtwdev, REG_RFESEL8, MASKBYTE1, 0x57);
 		rtw_write32s_mask(rtwdev, REG_RFECTL, BIT(4), 0);
@@ -241,9 +296,8 @@
 static void rtw8822b_set_channel_rfe_ifem(struct rtw_dev *rtwdev, u8 channel)
 {
 	struct rtw_hal *hal = &rtwdev->hal;
-	bool is_channel_2g = (channel <= 14) ? true : false;
 
-	if (is_channel_2g) {
+	if (IS_CH_2G_BAND(channel)) {
 		/* signal source */
 		rtw_write32s_mask(rtwdev, REG_RFESEL0, 0xffffff, 0x745774);
 		rtw_write32s_mask(rtwdev, REG_RFESEL8, MASKBYTE1, 0x57);
@@ -255,7 +309,7 @@
 
 	rtw_write32s_mask(rtwdev, REG_RFEINV, BIT(11) | BIT(10) | 0x3f, 0x0);
 
-	if (is_channel_2g) {
+	if (IS_CH_2G_BAND(channel)) {
 		if (hal->antenna_rx == BB_PATH_AB ||
 		    hal->antenna_tx == BB_PATH_AB) {
 			/* 2TX or 2RX */
@@ -337,6 +391,7 @@
 
 static const struct rtw8822b_rfe_info rtw8822b_rfe_info[] = {
 	[2] = I2GE5G_CCUT(efem),
+	[3] = IFEM_EXT_CCUT(ifem),
 	[5] = IFEM_EXT_CCUT(ifem),
 };
 
@@ -350,7 +405,7 @@
 	u32 reg82c, reg830, reg838;
 	bool is_efem_cca = false, is_ifem_cca = false, is_rfe_type = false;
 
-	if (channel <= 14) {
+	if (IS_CH_2G_BAND(channel)) {
 		cca_ccut = rfe_info->cca_ccut_2g;
 
 		if (hal->antenna_rx == BB_PATH_A ||
@@ -381,7 +436,7 @@
 		is_efem_cca = true;
 		break;
 	case RTW_RFE_IFEM2G_EFEM5G:
-		if (channel <= 14)
+		if (IS_CH_2G_BAND(channel))
 			is_ifem_cca = true;
 		else
 			is_efem_cca = true;
@@ -405,9 +460,7 @@
 	if (is_efem_cca && !(hal->cut_version == RTW_CHIP_VER_CUT_B))
 		rtw_write32_mask(rtwdev, REG_L1WT, MASKDWORD, 0x9194b2b9);
 
-	if (bw == RTW_CHANNEL_WIDTH_20 &&
-	    ((channel >= 52 && channel <= 64) ||
-	     (channel >= 100 && channel <= 144)))
+	if (bw == RTW_CHANNEL_WIDTH_20 && IS_CH_5G_BAND_MID(channel))
 		rtw_write32_mask(rtwdev, REG_CCA2ND, 0xf0, 0x4);
 }
 
@@ -442,7 +495,7 @@
 	rf_reg18 &= ~(RF18_BAND_MASK | RF18_CHANNEL_MASK | RF18_RFSI_MASK |
 		      RF18_BW_MASK);
 
-	rf_reg18 |= (channel <= 14 ? RF18_BAND_2G : RF18_BAND_5G);
+	rf_reg18 |= (IS_CH_2G_BAND(channel) ? RF18_BAND_2G : RF18_BAND_5G);
 	rf_reg18 |= (channel & RF18_CHANNEL_MASK);
 	if (channel > 144)
 		rf_reg18 |= RF18_RFSI_GT_CH144;
@@ -464,13 +517,13 @@
 		break;
 	}
 
-	if (channel <= 14)
+	if (IS_CH_2G_BAND(channel))
 		rf_reg_be = 0x0;
-	else if (channel >= 36 && channel <= 64)
+	else if (IS_CH_5G_BAND_1(channel) || IS_CH_5G_BAND_2(channel))
 		rf_reg_be = low_band[(channel - 36) >> 1];
-	else if (channel >= 100 && channel <= 144)
+	else if (IS_CH_5G_BAND_3(channel))
 		rf_reg_be = middle_band[(channel - 100) >> 1];
-	else if (channel >= 149 && channel <= 177)
+	else if (IS_CH_5G_BAND_4(channel))
 		rf_reg_be = high_band[(channel - 149) >> 1];
 	else
 		goto err;
@@ -539,7 +592,7 @@
 	u8 rfe_option = efuse->rfe_option;
 	u32 val32;
 
-	if (channel <= 14) {
+	if (IS_CH_2G_BAND(channel)) {
 		rtw_write32_mask(rtwdev, REG_RXPSEL, BIT(28), 0x1);
 		rtw_write32_mask(rtwdev, REG_CCK_CHECK, BIT(7), 0x0);
 		rtw_write32_mask(rtwdev, REG_ENTXCCK, BIT(18), 0x0);
@@ -556,22 +609,22 @@
 		}
 
 		rtw_write32_mask(rtwdev, REG_RFEINV, 0x300, 0x2);
-	} else if (channel > 35) {
+	} else if (IS_CH_5G_BAND(channel)) {
 		rtw_write32_mask(rtwdev, REG_ENTXCCK, BIT(18), 0x1);
 		rtw_write32_mask(rtwdev, REG_CCK_CHECK, BIT(7), 0x1);
 		rtw_write32_mask(rtwdev, REG_RXPSEL, BIT(28), 0x0);
 		rtw_write32_mask(rtwdev, REG_RXCCAMSK, 0x0000FC00, 34);
 
-		if (channel >= 36 && channel <= 64)
+		if (IS_CH_5G_BAND_1(channel) || IS_CH_5G_BAND_2(channel))
 			rtw_write32_mask(rtwdev, REG_ACGG2TBL, 0x1f, 0x1);
-		else if (channel >= 100 && channel <= 144)
+		else if (IS_CH_5G_BAND_3(channel))
 			rtw_write32_mask(rtwdev, REG_ACGG2TBL, 0x1f, 0x2);
-		else if (channel >= 149)
+		else if (IS_CH_5G_BAND_4(channel))
 			rtw_write32_mask(rtwdev, REG_ACGG2TBL, 0x1f, 0x3);
 
-		if (channel >= 36 && channel <= 48)
+		if (IS_CH_5G_BAND_1(channel))
 			rtw_write32_mask(rtwdev, REG_CLKTRK, 0x1ffe0000, 0x494);
-		else if (channel >= 52 && channel <= 64)
+		else if (IS_CH_5G_BAND_2(channel))
 			rtw_write32_mask(rtwdev, REG_CLKTRK, 0x1ffe0000, 0x453);
 		else if (channel >= 100 && channel <= 116)
 			rtw_write32_mask(rtwdev, REG_CLKTRK, 0x1ffe0000, 0x452);
@@ -592,7 +645,7 @@
 		rtw_write32_mask(rtwdev, REG_ADC160, BIT(30), 0x1);
 		break;
 	case RTW_CHANNEL_WIDTH_40:
-		if (primary_ch_idx == 1)
+		if (primary_ch_idx == RTW_SC_20_UPPER)
 			rtw_write32_set(rtwdev, REG_RXSB, BIT(4));
 		else
 			rtw_write32_clr(rtwdev, REG_RXSB, BIT(4));
@@ -612,7 +665,7 @@
 
 		rtw_write32_mask(rtwdev, REG_ADC160, BIT(30), 0x1);
 
-		if (rfe_option == 2) {
+		if (rfe_option == 2 || rfe_option == 3) {
 			rtw_write32_mask(rtwdev, REG_L1PKWT, 0x0000f000, 0x6);
 			rtw_write32_mask(rtwdev, REG_ADC40, BIT(10), 0x1);
 		}
@@ -763,6 +816,7 @@
 static void query_phy_status_page0(struct rtw_dev *rtwdev, u8 *phy_status,
 				   struct rtw_rx_pkt_stat *pkt_stat)
 {
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
 	s8 min_rx_power = -120;
 	u8 pwdb = GET_PHY_STAT_P0_PWDB(phy_status);
 
@@ -772,13 +826,19 @@
 	pkt_stat->bw = RTW_CHANNEL_WIDTH_20;
 	pkt_stat->signal_power = max(pkt_stat->rx_power[RF_PATH_A],
 				     min_rx_power);
+	dm_info->rssi[RF_PATH_A] = pkt_stat->rssi;
 }
 
 static void query_phy_status_page1(struct rtw_dev *rtwdev, u8 *phy_status,
 				   struct rtw_rx_pkt_stat *pkt_stat)
 {
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
 	u8 rxsc, bw;
 	s8 min_rx_power = -120;
+	s8 rx_evm;
+	u8 evm_dbm = 0;
+	u8 rssi;
+	int path;
 
 	if (pkt_stat->rate > DESC_RATE11M && pkt_stat->rate < DESC_RATEMCS0)
 		rxsc = GET_PHY_STAT_P1_L_RXSC(phy_status);
@@ -801,6 +861,34 @@
 	pkt_stat->signal_power = max3(pkt_stat->rx_power[RF_PATH_A],
 				      pkt_stat->rx_power[RF_PATH_B],
 				      min_rx_power);
+
+	dm_info->curr_rx_rate = pkt_stat->rate;
+
+	pkt_stat->rx_evm[RF_PATH_A] = GET_PHY_STAT_P1_RXEVM_A(phy_status);
+	pkt_stat->rx_evm[RF_PATH_B] = GET_PHY_STAT_P1_RXEVM_B(phy_status);
+
+	pkt_stat->rx_snr[RF_PATH_A] = GET_PHY_STAT_P1_RXSNR_A(phy_status);
+	pkt_stat->rx_snr[RF_PATH_B] = GET_PHY_STAT_P1_RXSNR_B(phy_status);
+
+	pkt_stat->cfo_tail[RF_PATH_A] = GET_PHY_STAT_P1_CFO_TAIL_A(phy_status);
+	pkt_stat->cfo_tail[RF_PATH_B] = GET_PHY_STAT_P1_CFO_TAIL_B(phy_status);
+
+	for (path = 0; path <= rtwdev->hal.rf_path_num; path++) {
+		rssi = rtw_phy_rf_power_2_rssi(&pkt_stat->rx_power[path], 1);
+		dm_info->rssi[path] = rssi;
+		dm_info->rx_snr[path] = pkt_stat->rx_snr[path] >> 1;
+		dm_info->cfo_tail[path] = (pkt_stat->cfo_tail[path] * 5) >> 1;
+
+		rx_evm = pkt_stat->rx_evm[path];
+
+		if (rx_evm < 0) {
+			if (rx_evm == S8_MIN)
+				evm_dbm = 0;
+			else
+				evm_dbm = ((u8)-rx_evm >> 1);
+		}
+		dm_info->rx_evm_dbm[path] = evm_dbm;
+	}
 }
 
 static void query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status,
@@ -836,7 +924,8 @@
 	pkt_stat->phy_status = GET_RX_DESC_PHYST(rx_desc);
 	pkt_stat->icv_err = GET_RX_DESC_ICV_ERR(rx_desc);
 	pkt_stat->crc_err = GET_RX_DESC_CRC32(rx_desc);
-	pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc);
+	pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc) &&
+			      GET_RX_DESC_ENC_TYPE(rx_desc) != RX_DESC_ENC_NONE;
 	pkt_stat->is_c2h = GET_RX_DESC_C2H(rx_desc);
 	pkt_stat->pkt_len = GET_RX_DESC_PKT_LEN(rx_desc);
 	pkt_stat->drv_info_sz = GET_RX_DESC_DRV_INFO_SIZE(rx_desc);
@@ -935,7 +1024,7 @@
 	u8 ldo_pwr;
 
 	ldo_pwr = rtw_read8(rtwdev, REG_LDO_EFUSE_CTRL + 3);
-	ldo_pwr = enable ? ldo_pwr | BIT(7) : ldo_pwr & ~BIT(7);
+	ldo_pwr = enable ? ldo_pwr | BIT_LDO25_EN : ldo_pwr & ~BIT_LDO25_EN;
 	rtw_write8(rtwdev, REG_LDO_EFUSE_CTRL + 3, ldo_pwr);
 }
 
@@ -946,6 +1035,7 @@
 	u32 cck_fa_cnt;
 	u32 ofdm_fa_cnt;
 	u32 crc32_cnt;
+	u32 cca32_cnt;
 
 	cck_enable = rtw_read32(rtwdev, 0x808) & BIT(28);
 	cck_fa_cnt = rtw_read16(rtwdev, 0xa5c);
@@ -969,6 +1059,15 @@
 	dm_info->vht_ok_cnt = crc32_cnt & 0xffff;
 	dm_info->vht_err_cnt = (crc32_cnt & 0xffff0000) >> 16;
 
+	cca32_cnt = rtw_read32(rtwdev, 0xf08);
+	dm_info->ofdm_cca_cnt = ((cca32_cnt & 0xffff0000) >> 16);
+	dm_info->total_cca_cnt = dm_info->ofdm_cca_cnt;
+	if (cck_enable) {
+		cca32_cnt = rtw_read32(rtwdev, 0xfcc);
+		dm_info->cck_cca_cnt = cca32_cnt & 0xffff;
+		dm_info->total_cca_cnt += dm_info->cck_cca_cnt;
+	}
+
 	rtw_write32_set(rtwdev, 0x9a4, BIT(17));
 	rtw_write32_clr(rtwdev, 0x9a4, BIT(17));
 	rtw_write32_clr(rtwdev, 0xa2c, BIT(15));
@@ -1255,6 +1354,226 @@
 	}
 }
 
+static void rtw8822b_txagc_swing_offset(struct rtw_dev *rtwdev, u8 path,
+					u8 tx_pwr_idx_offset,
+					s8 *txagc_idx, u8 *swing_idx)
+{
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+	s8 delta_pwr_idx = dm_info->delta_power_index[path];
+	u8 swing_upper_bound = dm_info->default_ofdm_index + 10;
+	u8 swing_lower_bound = 0;
+	u8 max_tx_pwr_idx_offset = 0xf;
+	s8 agc_index = 0;
+	u8 swing_index = dm_info->default_ofdm_index;
+
+	tx_pwr_idx_offset = min_t(u8, tx_pwr_idx_offset, max_tx_pwr_idx_offset);
+
+	if (delta_pwr_idx >= 0) {
+		if (delta_pwr_idx <= tx_pwr_idx_offset) {
+			agc_index = delta_pwr_idx;
+			swing_index = dm_info->default_ofdm_index;
+		} else if (delta_pwr_idx > tx_pwr_idx_offset) {
+			agc_index = tx_pwr_idx_offset;
+			swing_index = dm_info->default_ofdm_index +
+					delta_pwr_idx - tx_pwr_idx_offset;
+			swing_index = min_t(u8, swing_index, swing_upper_bound);
+		}
+	} else {
+		if (dm_info->default_ofdm_index > abs(delta_pwr_idx))
+			swing_index =
+				dm_info->default_ofdm_index + delta_pwr_idx;
+		else
+			swing_index = swing_lower_bound;
+		swing_index = max_t(u8, swing_index, swing_lower_bound);
+
+		agc_index = 0;
+	}
+
+	if (swing_index >= RTW_TXSCALE_SIZE) {
+		rtw_warn(rtwdev, "swing index overflow\n");
+		swing_index = RTW_TXSCALE_SIZE - 1;
+	}
+	*txagc_idx = agc_index;
+	*swing_idx = swing_index;
+}
+
+static void rtw8822b_pwrtrack_set_pwr(struct rtw_dev *rtwdev, u8 path,
+				      u8 pwr_idx_offset)
+{
+	s8 txagc_idx;
+	u8 swing_idx;
+	u32 reg1, reg2;
+
+	if (path == RF_PATH_A) {
+		reg1 = 0xc94;
+		reg2 = 0xc1c;
+	} else if (path == RF_PATH_B) {
+		reg1 = 0xe94;
+		reg2 = 0xe1c;
+	} else {
+		return;
+	}
+
+	rtw8822b_txagc_swing_offset(rtwdev, path, pwr_idx_offset,
+				    &txagc_idx, &swing_idx);
+	rtw_write32_mask(rtwdev, reg1, GENMASK(29, 25), txagc_idx);
+	rtw_write32_mask(rtwdev, reg2, GENMASK(31, 21),
+			 rtw8822b_txscale_tbl[swing_idx]);
+}
+
+static void rtw8822b_pwrtrack_set(struct rtw_dev *rtwdev, u8 path)
+{
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+	u8 pwr_idx_offset, tx_pwr_idx;
+	u8 channel = rtwdev->hal.current_channel;
+	u8 band_width = rtwdev->hal.current_band_width;
+	u8 regd = rtwdev->regd.txpwr_regd;
+	u8 tx_rate = dm_info->tx_rate;
+	u8 max_pwr_idx = rtwdev->chip->max_power_index;
+
+	tx_pwr_idx = rtw_phy_get_tx_power_index(rtwdev, path, tx_rate,
+						band_width, channel, regd);
+
+	tx_pwr_idx = min_t(u8, tx_pwr_idx, max_pwr_idx);
+
+	pwr_idx_offset = max_pwr_idx - tx_pwr_idx;
+
+	rtw8822b_pwrtrack_set_pwr(rtwdev, path, pwr_idx_offset);
+}
+
+static void rtw8822b_phy_pwrtrack_path(struct rtw_dev *rtwdev,
+				       struct rtw_swing_table *swing_table,
+				       u8 path)
+{
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+	u8 power_idx_cur, power_idx_last;
+	u8 delta;
+
+	/* 8822B only has one thermal meter at PATH A */
+	delta = rtw_phy_pwrtrack_get_delta(rtwdev, RF_PATH_A);
+
+	power_idx_last = dm_info->delta_power_index[path];
+	power_idx_cur = rtw_phy_pwrtrack_get_pwridx(rtwdev, swing_table,
+						    path, RF_PATH_A, delta);
+
+	/* if delta of power indexes are the same, just skip */
+	if (power_idx_cur == power_idx_last)
+		return;
+
+	dm_info->delta_power_index[path] = power_idx_cur;
+	rtw8822b_pwrtrack_set(rtwdev, path);
+}
+
+static void rtw8822b_phy_pwrtrack(struct rtw_dev *rtwdev)
+{
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+	struct rtw_swing_table swing_table;
+	u8 thermal_value, path;
+
+	rtw_phy_config_swing_table(rtwdev, &swing_table);
+
+	if (rtwdev->efuse.thermal_meter[RF_PATH_A] == 0xff)
+		return;
+
+	thermal_value = rtw_read_rf(rtwdev, RF_PATH_A, RF_T_METER, 0xfc00);
+
+	rtw_phy_pwrtrack_avg(rtwdev, thermal_value, RF_PATH_A);
+
+	if (dm_info->pwr_trk_init_trigger)
+		dm_info->pwr_trk_init_trigger = false;
+	else if (!rtw_phy_pwrtrack_thermal_changed(rtwdev, thermal_value,
+						   RF_PATH_A))
+		goto iqk;
+
+	for (path = 0; path < rtwdev->hal.rf_path_num; path++)
+		rtw8822b_phy_pwrtrack_path(rtwdev, &swing_table, path);
+
+iqk:
+	if (rtw_phy_pwrtrack_need_iqk(rtwdev))
+		rtw8822b_do_iqk(rtwdev);
+}
+
+static void rtw8822b_pwr_track(struct rtw_dev *rtwdev)
+{
+	struct rtw_efuse *efuse = &rtwdev->efuse;
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+
+	if (efuse->power_track_type != 0)
+		return;
+
+	if (!dm_info->pwr_trk_triggered) {
+		rtw_write_rf(rtwdev, RF_PATH_A, RF_T_METER,
+			     GENMASK(17, 16), 0x03);
+		dm_info->pwr_trk_triggered = true;
+		return;
+	}
+
+	rtw8822b_phy_pwrtrack(rtwdev);
+	dm_info->pwr_trk_triggered = false;
+}
+
+static void rtw8822b_bf_config_bfee_su(struct rtw_dev *rtwdev,
+				       struct rtw_vif *vif,
+				       struct rtw_bfee *bfee, bool enable)
+{
+	if (enable)
+		rtw_bf_enable_bfee_su(rtwdev, vif, bfee);
+	else
+		rtw_bf_remove_bfee_su(rtwdev, bfee);
+}
+
+static void rtw8822b_bf_config_bfee_mu(struct rtw_dev *rtwdev,
+				       struct rtw_vif *vif,
+				       struct rtw_bfee *bfee, bool enable)
+{
+	if (enable)
+		rtw_bf_enable_bfee_mu(rtwdev, vif, bfee);
+	else
+		rtw_bf_remove_bfee_mu(rtwdev, bfee);
+}
+
+static void rtw8822b_bf_config_bfee(struct rtw_dev *rtwdev, struct rtw_vif *vif,
+				    struct rtw_bfee *bfee, bool enable)
+{
+	if (bfee->role == RTW_BFEE_SU)
+		rtw8822b_bf_config_bfee_su(rtwdev, vif, bfee, enable);
+	else if (bfee->role == RTW_BFEE_MU)
+		rtw8822b_bf_config_bfee_mu(rtwdev, vif, bfee, enable);
+	else
+		rtw_warn(rtwdev, "wrong bfee role\n");
+}
+
+static void rtw8822b_adaptivity_init(struct rtw_dev *rtwdev)
+{
+	rtw_phy_set_edcca_th(rtwdev, 0x7f, 0x7f);
+	/* mac edcca state setting */
+	rtw_write32_mask(rtwdev, REG_TX_PTCL_CTRL, BIT_DIS_EDCCA, 0);
+	rtw_write32_mask(rtwdev, REG_RD_CTRL, BIT_EDCCA_MSK_CNTDOWN_EN, 1);
+
+	rtw_write32_mask(rtwdev, REG_EDCCA_SOURCE, BIT_SOURCE_OPTION, 1);
+	rtw_write32_mask(rtwdev, REG_EDCCA_POW_MA, BIT_MA_LEVEL, 0);
+	/* edcca decistion opt */
+	rtw_write32_mask(rtwdev, REG_EDCCA_DECISION, BIT_EDCCA_OPTION, 1);
+}
+
+static void rtw8822b_adaptivity(struct rtw_dev *rtwdev)
+{
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+	s8 l2h, h2l;
+	u8 igi;
+
+	igi = dm_info->igi_history[0];
+	if (dm_info->edcca_mode == RTW_EDCCA_NORMAL) {
+		l2h = max_t(s8, igi + EDCCA_IGI_L2H_DIFF, EDCCA_TH_L2H_LB);
+		h2l = l2h - EDCCA_L2H_H2L_DIFF_NORMAL;
+	} else {
+		l2h = min_t(s8, igi, dm_info->l2h_th_ini);
+		h2l = l2h - EDCCA_L2H_H2L_DIFF;
+	}
+
+	rtw_phy_set_edcca_th(rtwdev, l2h, h2l);
+}
+
 static struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8822b[] = {
 	{0x0086,
 	 RTW_PWR_CUT_ALL_MSK,
@@ -1754,6 +2073,7 @@
 
 static const struct rtw_rfe_def rtw8822b_rfe_defs[] = {
 	[2] = RTW_DEF_RFE(8822b, 2, 2),
+	[3] = RTW_DEF_RFE(8822b, 3, 0),
 	[5] = RTW_DEF_RFE(8822b, 5, 5),
 };
 
@@ -1762,6 +2082,12 @@
 	[1] = { .addr = 0xe50, .mask = 0x7f },
 };
 
+static struct rtw_ltecoex_addr rtw8822b_ltecoex_addr = {
+	.ctrl = LTECOEX_ACCESS_CTRL,
+	.wdata = LTECOEX_WRITE_DATA,
+	.rdata = LTECOEX_READ_DATA,
+};
+
 static struct rtw_page_table page_table_8822b[] = {
 	{64, 64, 64, 64, 1},
 	{64, 64, 64, 64, 1},
@@ -1788,6 +2114,22 @@
 	 RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH},
 };
 
+static struct rtw_prioq_addrs prioq_addrs_8822b = {
+	.prio[RTW_DMA_MAPPING_EXTRA] = {
+		.rsvd = REG_FIFOPAGE_INFO_4, .avail = REG_FIFOPAGE_INFO_4 + 2,
+	},
+	.prio[RTW_DMA_MAPPING_LOW] = {
+		.rsvd = REG_FIFOPAGE_INFO_2, .avail = REG_FIFOPAGE_INFO_2 + 2,
+	},
+	.prio[RTW_DMA_MAPPING_NORMAL] = {
+		.rsvd = REG_FIFOPAGE_INFO_3, .avail = REG_FIFOPAGE_INFO_3 + 2,
+	},
+	.prio[RTW_DMA_MAPPING_HIGH] = {
+		.rsvd = REG_FIFOPAGE_INFO_1, .avail = REG_FIFOPAGE_INFO_1 + 2,
+	},
+	.wsize = true,
+};
+
 static struct rtw_chip_ops rtw8822b_ops = {
 	.phy_set_param		= rtw8822b_phy_set_param,
 	.read_efuse		= rtw8822b_read_efuse,
@@ -1801,6 +2143,12 @@
 	.cfg_ldo25		= rtw8822b_cfg_ldo25,
 	.false_alarm_statistics	= rtw8822b_false_alarm_statistics,
 	.phy_calibration	= rtw8822b_phy_calibration,
+	.pwr_track		= rtw8822b_pwr_track,
+	.config_bfee		= rtw8822b_bf_config_bfee,
+	.set_gid_table		= rtw_bf_set_gid_table,
+	.cfg_csi_rate		= rtw_bf_cfg_csi_rate,
+	.adaptivity_init	= rtw8822b_adaptivity_init,
+	.adaptivity		= rtw8822b_adaptivity,
 
 	.coex_set_init		= rtw8822b_coex_cfg_init,
 	.coex_set_ant_switch	= rtw8822b_coex_cfg_ant_switch,
@@ -1955,10 +2303,166 @@
 
 static_assert(ARRAY_SIZE(rf_para_tx_8822b) == ARRAY_SIZE(rf_para_rx_8822b));
 
+static const u8
+rtw8822b_pwrtrk_5gb_n[RTW_PWR_TRK_5G_NUM][RTW_PWR_TRK_TBL_SZ] = {
+	{ 0,  1,  2,  2,  3,  4,  5,  5,  6,  7,
+	  8,  8,  9, 10, 11, 11, 12, 13, 14, 14,
+	 15, 16, 17, 17, 18, 19, 20, 20, 21, 22 },
+	{ 0,  1,  2,  2,  3,  4,  5,  5,  6,  7,
+	  8,  8,  9, 10, 11, 11, 12, 13, 14, 14,
+	 15, 16, 17, 17, 18, 19, 20, 20, 21, 22 },
+	{ 0,  1,  2,  2,  3,  4,  5,  5,  6,  7,
+	  8,  8,  9, 10, 11, 11, 12, 13, 14, 14,
+	 15, 16, 17, 17, 18, 19, 20, 20, 21, 22 },
+};
+
+static const u8
+rtw8822b_pwrtrk_5gb_p[RTW_PWR_TRK_5G_NUM][RTW_PWR_TRK_TBL_SZ] = {
+	{ 0,  1,  2,  2,  3,  4,  5,  5,  6,  7,
+	  8,  9,  9, 10, 11, 12, 13, 14, 14, 15,
+	 16, 17, 18, 19, 19, 20, 21, 22, 22, 23 },
+	{ 0,  1,  2,  2,  3,  4,  5,  5,  6,  7,
+	  8,  9,  9, 10, 11, 12, 13, 14, 14, 15,
+	 16, 17, 18, 19, 19, 20, 21, 22, 22, 23 },
+	{ 0,  1,  2,  2,  3,  4,  5,  5,  6,  7,
+	  8,  9,  9, 10, 11, 12, 13, 14, 14, 15,
+	 16, 17, 18, 19, 19, 20, 21, 22, 22, 23 },
+};
+
+static const u8
+rtw8822b_pwrtrk_5ga_n[RTW_PWR_TRK_5G_NUM][RTW_PWR_TRK_TBL_SZ] = {
+	{ 0,  1,  2,  2,  3,  4,  5,  5,  6,  7,
+	  8,  8,  9, 10, 11, 11, 12, 13, 14, 14,
+	 15, 16, 17, 17, 18, 19, 20, 20, 21, 22 },
+	{ 0,  1,  2,  2,  3,  4,  5,  5,  6,  7,
+	  8,  8,  9, 10, 11, 11, 12, 13, 14, 14,
+	 15, 16, 17, 17, 18, 19, 20, 20, 21, 22 },
+	{ 0,  1,  2,  2,  3,  4,  5,  5,  6,  7,
+	  8,  8,  9, 10, 11, 11, 12, 13, 14, 14,
+	 15, 16, 17, 17, 18, 19, 20, 20, 21, 22 },
+};
+
+static const u8
+rtw8822b_pwrtrk_5ga_p[RTW_PWR_TRK_5G_NUM][RTW_PWR_TRK_TBL_SZ] = {
+	{ 0,  1,  2,  2,  3,  4,  5,  5,  6,  7,
+	  8,  9,  9, 10, 11, 12, 13, 14, 14, 15,
+	 16, 17, 18, 19, 19, 20, 21, 22, 22, 23},
+	{ 0,  1,  2,  2,  3,  4,  5,  5,  6,  7,
+	  8,  9,  9, 10, 11, 12, 13, 14, 14, 15,
+	 16, 17, 18, 19, 19, 20, 21, 22, 22, 23},
+	{ 0,  1,  2,  2,  3,  4,  5,  5,  6,  7,
+	  8,  9,  9, 10, 11, 12, 13, 14, 14, 15,
+	 16, 17, 18, 19, 19, 20, 21, 22, 22, 23},
+};
+
+static const u8 rtw8822b_pwrtrk_2gb_n[RTW_PWR_TRK_TBL_SZ] = {
+	0,  1,  1,  1,  2,  2,  3,  3,  3,  4,
+	4,  5,  5,  5,  6,  6,  7,  7,  7,  8,
+	8,  9,  9,  9, 10, 10, 11, 11, 11, 12
+};
+
+static const u8 rtw8822b_pwrtrk_2gb_p[RTW_PWR_TRK_TBL_SZ] = {
+	0,  0,  1,  1,  2,  2,  3,  3,  4,  4,
+	5,  5,  6,  6,  6,  7,  7,  8,  8,  9,
+	9, 10, 10, 11, 11, 12, 12, 12, 13, 13
+};
+
+static const u8 rtw8822b_pwrtrk_2ga_n[RTW_PWR_TRK_TBL_SZ] = {
+	0,  1,  1,  1,  2,  2,  3,  3,  3,  4,
+	4,  5,  5,  5,  6,  6,  7,  7,  7,  8,
+	8,  9,  9,  9, 10, 10, 11, 11, 11, 12
+};
+
+static const u8 rtw8822b_pwrtrk_2ga_p[RTW_PWR_TRK_TBL_SZ] = {
+	0,  1,  1,  2,  2,  3,  3,  4,  4,  5,
+	5,  6,  6,  7,  7,  8,  8,  9,  9, 10,
+	10, 11, 11, 12, 12, 13, 13, 14, 14, 15
+};
+
+static const u8 rtw8822b_pwrtrk_2g_cck_b_n[RTW_PWR_TRK_TBL_SZ] = {
+	0,  1,  1,  1,  2,  2,  3,  3,  3,  4,
+	4,  5,  5,  5,  6,  6,  7,  7,  7,  8,
+	8,  9,  9,  9, 10, 10, 11, 11, 11, 12
+};
+
+static const u8 rtw8822b_pwrtrk_2g_cck_b_p[RTW_PWR_TRK_TBL_SZ] = {
+	0,  0,  1,  1,  2,  2,  3,  3,  4,  4,
+	5,  5,  6,  6,  6,  7,  7,  8,  8,  9,
+	9, 10, 10, 11, 11, 12, 12, 12, 13, 13
+};
+
+static const u8 rtw8822b_pwrtrk_2g_cck_a_n[RTW_PWR_TRK_TBL_SZ] = {
+	0,  1,  1,  1,  2,  2,  3,  3,  3,  4,
+	4,  5,  5,  5,  6,  6,  7,  7,  7,  8,
+	8,  9,  9,  9, 10, 10, 11, 11, 11, 12
+};
+
+static const u8 rtw8822b_pwrtrk_2g_cck_a_p[RTW_PWR_TRK_TBL_SZ] = {
+	 0,  1,  1,  2,  2,  3,  3,  4,  4,  5,
+	 5,  6,  6,  7,  7,  8,  8,  9,  9, 10,
+	10, 11, 11, 12, 12, 13, 13, 14, 14, 15
+};
+
+static const struct rtw_pwr_track_tbl rtw8822b_rtw_pwr_track_tbl = {
+	.pwrtrk_5gb_n[RTW_PWR_TRK_5G_1] = rtw8822b_pwrtrk_5gb_n[RTW_PWR_TRK_5G_1],
+	.pwrtrk_5gb_n[RTW_PWR_TRK_5G_2] = rtw8822b_pwrtrk_5gb_n[RTW_PWR_TRK_5G_2],
+	.pwrtrk_5gb_n[RTW_PWR_TRK_5G_3] = rtw8822b_pwrtrk_5gb_n[RTW_PWR_TRK_5G_3],
+	.pwrtrk_5gb_p[RTW_PWR_TRK_5G_1] = rtw8822b_pwrtrk_5gb_p[RTW_PWR_TRK_5G_1],
+	.pwrtrk_5gb_p[RTW_PWR_TRK_5G_2] = rtw8822b_pwrtrk_5gb_p[RTW_PWR_TRK_5G_2],
+	.pwrtrk_5gb_p[RTW_PWR_TRK_5G_3] = rtw8822b_pwrtrk_5gb_p[RTW_PWR_TRK_5G_3],
+	.pwrtrk_5ga_n[RTW_PWR_TRK_5G_1] = rtw8822b_pwrtrk_5ga_n[RTW_PWR_TRK_5G_1],
+	.pwrtrk_5ga_n[RTW_PWR_TRK_5G_2] = rtw8822b_pwrtrk_5ga_n[RTW_PWR_TRK_5G_2],
+	.pwrtrk_5ga_n[RTW_PWR_TRK_5G_3] = rtw8822b_pwrtrk_5ga_n[RTW_PWR_TRK_5G_3],
+	.pwrtrk_5ga_p[RTW_PWR_TRK_5G_1] = rtw8822b_pwrtrk_5ga_p[RTW_PWR_TRK_5G_1],
+	.pwrtrk_5ga_p[RTW_PWR_TRK_5G_2] = rtw8822b_pwrtrk_5ga_p[RTW_PWR_TRK_5G_2],
+	.pwrtrk_5ga_p[RTW_PWR_TRK_5G_3] = rtw8822b_pwrtrk_5ga_p[RTW_PWR_TRK_5G_3],
+	.pwrtrk_2gb_n = rtw8822b_pwrtrk_2gb_n,
+	.pwrtrk_2gb_p = rtw8822b_pwrtrk_2gb_p,
+	.pwrtrk_2ga_n = rtw8822b_pwrtrk_2ga_n,
+	.pwrtrk_2ga_p = rtw8822b_pwrtrk_2ga_p,
+	.pwrtrk_2g_cckb_n = rtw8822b_pwrtrk_2g_cck_b_n,
+	.pwrtrk_2g_cckb_p = rtw8822b_pwrtrk_2g_cck_b_p,
+	.pwrtrk_2g_ccka_n = rtw8822b_pwrtrk_2g_cck_a_n,
+	.pwrtrk_2g_ccka_p = rtw8822b_pwrtrk_2g_cck_a_p,
+};
+
+static const struct rtw_reg_domain coex_info_hw_regs_8822b[] = {
+	{0xcb0, MASKDWORD, RTW_REG_DOMAIN_MAC32},
+	{0xcb4, MASKDWORD, RTW_REG_DOMAIN_MAC32},
+	{0xcba, MASKBYTE0, RTW_REG_DOMAIN_MAC8},
+	{0xcbd, MASKBYTE0, RTW_REG_DOMAIN_MAC8},
+	{0xc58, MASKBYTE0, RTW_REG_DOMAIN_MAC8},
+	{0xcbd, BIT(0), RTW_REG_DOMAIN_MAC8},
+	{0, 0, RTW_REG_DOMAIN_NL},
+	{0x430, MASKDWORD, RTW_REG_DOMAIN_MAC32},
+	{0x434, MASKDWORD, RTW_REG_DOMAIN_MAC32},
+	{0x42a, MASKLWORD, RTW_REG_DOMAIN_MAC16},
+	{0x426, MASKBYTE0, RTW_REG_DOMAIN_MAC8},
+	{0x45e, BIT(3), RTW_REG_DOMAIN_MAC8},
+	{0x454, MASKLWORD, RTW_REG_DOMAIN_MAC16},
+	{0, 0, RTW_REG_DOMAIN_NL},
+	{0x4c, BIT(24) | BIT(23), RTW_REG_DOMAIN_MAC32},
+	{0x64, BIT(0), RTW_REG_DOMAIN_MAC8},
+	{0x4c6, BIT(4), RTW_REG_DOMAIN_MAC8},
+	{0x40, BIT(5), RTW_REG_DOMAIN_MAC8},
+	{0x1, RFREG_MASK, RTW_REG_DOMAIN_RF_B},
+	{0, 0, RTW_REG_DOMAIN_NL},
+	{0x550, MASKDWORD, RTW_REG_DOMAIN_MAC32},
+	{0x522, MASKBYTE0, RTW_REG_DOMAIN_MAC8},
+	{0x953, BIT(1), RTW_REG_DOMAIN_MAC8},
+	{0xc50,  MASKBYTE0, RTW_REG_DOMAIN_MAC8},
+};
+
+static struct rtw_hw_reg_offset rtw8822b_edcca_th[] = {
+	[EDCCA_TH_L2H_IDX] = {{.addr = 0x8a4, .mask = MASKBYTE0}, .offset = 0},
+	[EDCCA_TH_H2L_IDX] = {{.addr = 0x8a4, .mask = MASKBYTE1}, .offset = 0},
+};
+
 struct rtw_chip_info rtw8822b_hw_spec = {
 	.ops = &rtw8822b_ops,
 	.id = RTW_CHIP_TYPE_8822B,
 	.fw_name = "rtw88/rtw8822b_fw.bin",
+	.wlan_cpu = RTW_WCPU_11AC,
 	.tx_pkt_desc_sz = 48,
 	.tx_buf_desc_sz = 16,
 	.rx_pkt_desc_sz = 24,
@@ -1977,21 +2481,32 @@
 	.dig_min = 0x1c,
 	.ht_supported = true,
 	.vht_supported = true,
+	.lps_deep_mode_supported = BIT(LPS_DEEP_MODE_LCLK),
 	.sys_func_en = 0xDC,
 	.pwr_on_seq = card_enable_flow_8822b,
 	.pwr_off_seq = card_disable_flow_8822b,
 	.page_table = page_table_8822b,
 	.rqpn_table = rqpn_table_8822b,
+	.prioq_addrs = &prioq_addrs_8822b,
 	.intf_table = &phy_para_table_8822b,
 	.dig = rtw8822b_dig,
+	.dig_cck = NULL,
 	.rf_base_addr = {0x2800, 0x2c00},
 	.rf_sipi_addr = {0xc90, 0xe90},
+	.ltecoex_addr = &rtw8822b_ltecoex_addr,
 	.mac_tbl = &rtw8822b_mac_tbl,
 	.agc_tbl = &rtw8822b_agc_tbl,
 	.bb_tbl = &rtw8822b_bb_tbl,
 	.rf_tbl = {&rtw8822b_rf_a_tbl, &rtw8822b_rf_b_tbl},
 	.rfe_defs = rtw8822b_rfe_defs,
 	.rfe_defs_size = ARRAY_SIZE(rtw8822b_rfe_defs),
+	.pwr_track_tbl = &rtw8822b_rtw_pwr_track_tbl,
+	.iqk_threshold = 8,
+	.bfer_su_max_num = 2,
+	.bfer_mu_max_num = 1,
+	.edcca_th = rtw8822b_edcca_th,
+	.l2h_th_ini_cs = 10 + EDCCA_IGI_BASE,
+	.l2h_th_ini_ad = -14 + EDCCA_IGI_BASE,
 
 	.coex_para_ver = 0x19062706,
 	.bt_desired_ver = 0x6,
@@ -2018,6 +2533,9 @@
 	.bt_afh_span_bw40 = 0x36,
 	.afh_5g_num = ARRAY_SIZE(afh_5g_8822b),
 	.afh_5g = afh_5g_8822b,
+
+	.coex_info_hw_regs_num = ARRAY_SIZE(coex_info_hw_regs_8822b),
+	.coex_info_hw_regs = coex_info_hw_regs_8822b,
 };
 EXPORT_SYMBOL(rtw8822b_hw_spec);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/rtw8822b.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/rtw8822b.h
@@ -127,6 +127,18 @@
 	le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(11, 8))
 #define GET_PHY_STAT_P1_HT_RXSC(phy_stat)                                      \
 	le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(15, 12))
+#define GET_PHY_STAT_P1_RXEVM_A(phy_stat)                                      \
+	le32_get_bits(*((__le32 *)(phy_stat) + 0x04), GENMASK(7, 0))
+#define GET_PHY_STAT_P1_RXEVM_B(phy_stat)                                      \
+	le32_get_bits(*((__le32 *)(phy_stat) + 0x04), GENMASK(15, 8))
+#define GET_PHY_STAT_P1_CFO_TAIL_A(phy_stat)                                 \
+	le32_get_bits(*((__le32 *)(phy_stat) + 0x05), GENMASK(7, 0))
+#define GET_PHY_STAT_P1_CFO_TAIL_B(phy_stat)                                 \
+	le32_get_bits(*((__le32 *)(phy_stat) + 0x05), GENMASK(15, 8))
+#define GET_PHY_STAT_P1_RXSNR_A(phy_stat)                                      \
+	le32_get_bits(*((__le32 *)(phy_stat) + 0x06), GENMASK(7, 0))
+#define GET_PHY_STAT_P1_RXSNR_B(phy_stat)                                      \
+	le32_get_bits(*((__le32 *)(phy_stat) + 0x06), GENMASK(15, 8))
 
 #define REG_HTSTFWT	0x800
 #define REG_RXPSEL	0x808
@@ -140,11 +152,17 @@
 #define REG_L1PKWT	0x840
 #define REG_MRC		0x850
 #define REG_CLKTRK	0x860
+#define REG_EDCCA_POW_MA	0x8a0
+#define BIT_MA_LEVEL	GENMASK(1, 0)
 #define REG_ADCCLK	0x8ac
 #define REG_ADC160	0x8c4
 #define REG_ADC40	0x8c8
+#define REG_EDCCA_DECISION	0x8dc
+#define BIT_EDCCA_OPTION	BIT(5)
 #define REG_CDDTXP	0x93c
 #define REG_TXPSEL1	0x940
+#define REG_EDCCA_SOURCE	0x944
+#define BIT_SOURCE_OPTION	GENMASK(29, 28)
 #define REG_ACBB0	0x948
 #define REG_ACBBRXFIR	0x94c
 #define REG_ACGG2TBL	0x958
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/rtw8822b_table.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/rtw8822b_table.c
@@ -11643,104 +11643,155 @@
 
 RTW_DECL_TABLE_PHY_COND(rtw8822b_bb, rtw_phy_cfg_bb);
 
-static const u32 rtw8822b_bb_pg_type2[] = {
-	0, 0, 0, 0x00000c20, 0xffffffff, 0x32343638,
-	0, 0, 0, 0x00000c24, 0xffffffff, 0x36384042,
-	0, 0, 0, 0x00000c28, 0xffffffff, 0x28303234,
-	0, 0, 0, 0x00000c2c, 0xffffffff, 0x34363840,
-	0, 0, 0, 0x00000c30, 0xffffffff, 0x26283032,
-	0, 0, 1, 0x00000c34, 0xffffffff, 0x34363840,
-	0, 0, 1, 0x00000c38, 0xffffffff, 0x26283032,
-	0, 0, 0, 0x00000c3c, 0xffffffff, 0x34363840,
-	0, 0, 0, 0x00000c40, 0xffffffff, 0x26283032,
-	0, 0, 0, 0x00000c44, 0xffffffff, 0x38402224,
-	0, 0, 1, 0x00000c48, 0xffffffff, 0x30323436,
-	0, 0, 1, 0x00000c4c, 0xffffffff, 0x22242628,
-	0, 1, 0, 0x00000e20, 0xffffffff, 0x32343638,
-	0, 1, 0, 0x00000e24, 0xffffffff, 0x36384042,
-	0, 1, 0, 0x00000e28, 0xffffffff, 0x28303234,
-	0, 1, 0, 0x00000e2c, 0xffffffff, 0x34363840,
-	0, 1, 0, 0x00000e30, 0xffffffff, 0x26283032,
-	0, 1, 1, 0x00000e34, 0xffffffff, 0x34363840,
-	0, 1, 1, 0x00000e38, 0xffffffff, 0x26283032,
-	0, 1, 0, 0x00000e3c, 0xffffffff, 0x34363840,
-	0, 1, 0, 0x00000e40, 0xffffffff, 0x26283032,
-	0, 1, 0, 0x00000e44, 0xffffffff, 0x38402224,
-	0, 1, 1, 0x00000e48, 0xffffffff, 0x30323436,
-	0, 1, 1, 0x00000e4c, 0xffffffff, 0x22242628,
-	1, 0, 0, 0x00000c24, 0xffffffff, 0x40424446,
-	1, 0, 0, 0x00000c28, 0xffffffff, 0x32343638,
-	1, 0, 0, 0x00000c2c, 0xffffffff, 0x38404244,
-	1, 0, 0, 0x00000c30, 0xffffffff, 0x30323436,
-	1, 0, 1, 0x00000c34, 0xffffffff, 0x38404244,
-	1, 0, 1, 0x00000c38, 0xffffffff, 0x30323436,
-	1, 0, 0, 0x00000c3c, 0xffffffff, 0x38404244,
-	1, 0, 0, 0x00000c40, 0xffffffff, 0x30323436,
-	1, 0, 0, 0x00000c44, 0xffffffff, 0x42442628,
-	1, 0, 1, 0x00000c48, 0xffffffff, 0x34363840,
-	1, 0, 1, 0x00000c4c, 0xffffffff, 0x26283032,
-	1, 1, 0, 0x00000e24, 0xffffffff, 0x40424446,
-	1, 1, 0, 0x00000e28, 0xffffffff, 0x32343638,
-	1, 1, 0, 0x00000e2c, 0xffffffff, 0x38404244,
-	1, 1, 0, 0x00000e30, 0xffffffff, 0x30323436,
-	1, 1, 1, 0x00000e34, 0xffffffff, 0x38404244,
-	1, 1, 1, 0x00000e38, 0xffffffff, 0x30323436,
-	1, 1, 0, 0x00000e3c, 0xffffffff, 0x38404244,
-	1, 1, 0, 0x00000e40, 0xffffffff, 0x30323436,
-	1, 1, 0, 0x00000e44, 0xffffffff, 0x42442628,
-	1, 1, 1, 0x00000e48, 0xffffffff, 0x34363840,
-	1, 1, 1, 0x00000e4c, 0xffffffff, 0x26283032
+static const struct rtw_phy_pg_cfg_pair rtw8822b_bb_pg_type2[] = {
+	{ 0, 0, 0, 0x00000c20, 0xffffffff, 0x32343638, },
+	{ 0, 0, 0, 0x00000c24, 0xffffffff, 0x36384042, },
+	{ 0, 0, 0, 0x00000c28, 0xffffffff, 0x28303234, },
+	{ 0, 0, 0, 0x00000c2c, 0xffffffff, 0x34363840, },
+	{ 0, 0, 0, 0x00000c30, 0xffffffff, 0x26283032, },
+	{ 0, 0, 1, 0x00000c34, 0xffffffff, 0x34363840, },
+	{ 0, 0, 1, 0x00000c38, 0xffffffff, 0x26283032, },
+	{ 0, 0, 0, 0x00000c3c, 0xffffffff, 0x34363840, },
+	{ 0, 0, 0, 0x00000c40, 0xffffffff, 0x26283032, },
+	{ 0, 0, 0, 0x00000c44, 0xffffffff, 0x38402224, },
+	{ 0, 0, 1, 0x00000c48, 0xffffffff, 0x30323436, },
+	{ 0, 0, 1, 0x00000c4c, 0xffffffff, 0x22242628, },
+	{ 0, 1, 0, 0x00000e20, 0xffffffff, 0x32343638, },
+	{ 0, 1, 0, 0x00000e24, 0xffffffff, 0x36384042, },
+	{ 0, 1, 0, 0x00000e28, 0xffffffff, 0x28303234, },
+	{ 0, 1, 0, 0x00000e2c, 0xffffffff, 0x34363840, },
+	{ 0, 1, 0, 0x00000e30, 0xffffffff, 0x26283032, },
+	{ 0, 1, 1, 0x00000e34, 0xffffffff, 0x34363840, },
+	{ 0, 1, 1, 0x00000e38, 0xffffffff, 0x26283032, },
+	{ 0, 1, 0, 0x00000e3c, 0xffffffff, 0x34363840, },
+	{ 0, 1, 0, 0x00000e40, 0xffffffff, 0x26283032, },
+	{ 0, 1, 0, 0x00000e44, 0xffffffff, 0x38402224, },
+	{ 0, 1, 1, 0x00000e48, 0xffffffff, 0x30323436, },
+	{ 0, 1, 1, 0x00000e4c, 0xffffffff, 0x22242628, },
+	{ 1, 0, 0, 0x00000c24, 0xffffffff, 0x40424446, },
+	{ 1, 0, 0, 0x00000c28, 0xffffffff, 0x32343638, },
+	{ 1, 0, 0, 0x00000c2c, 0xffffffff, 0x38404244, },
+	{ 1, 0, 0, 0x00000c30, 0xffffffff, 0x30323436, },
+	{ 1, 0, 1, 0x00000c34, 0xffffffff, 0x38404244, },
+	{ 1, 0, 1, 0x00000c38, 0xffffffff, 0x30323436, },
+	{ 1, 0, 0, 0x00000c3c, 0xffffffff, 0x38404244, },
+	{ 1, 0, 0, 0x00000c40, 0xffffffff, 0x30323436, },
+	{ 1, 0, 0, 0x00000c44, 0xffffffff, 0x42442628, },
+	{ 1, 0, 1, 0x00000c48, 0xffffffff, 0x34363840, },
+	{ 1, 0, 1, 0x00000c4c, 0xffffffff, 0x26283032, },
+	{ 1, 1, 0, 0x00000e24, 0xffffffff, 0x40424446, },
+	{ 1, 1, 0, 0x00000e28, 0xffffffff, 0x32343638, },
+	{ 1, 1, 0, 0x00000e2c, 0xffffffff, 0x38404244, },
+	{ 1, 1, 0, 0x00000e30, 0xffffffff, 0x30323436, },
+	{ 1, 1, 1, 0x00000e34, 0xffffffff, 0x38404244, },
+	{ 1, 1, 1, 0x00000e38, 0xffffffff, 0x30323436, },
+	{ 1, 1, 0, 0x00000e3c, 0xffffffff, 0x38404244, },
+	{ 1, 1, 0, 0x00000e40, 0xffffffff, 0x30323436, },
+	{ 1, 1, 0, 0x00000e44, 0xffffffff, 0x42442628, },
+	{ 1, 1, 1, 0x00000e48, 0xffffffff, 0x34363840, },
+	{ 1, 1, 1, 0x00000e4c, 0xffffffff, 0x26283032, },
 };
 
 RTW_DECL_TABLE_BB_PG(rtw8822b_bb_pg_type2);
 
-static const u32 rtw8822b_bb_pg_type5[] = {
-	0, 0, 0, 0x00000c20, 0xffffffff, 0x32343638,
-	0, 0, 0, 0x00000c24, 0xffffffff, 0x36384042,
-	0, 0, 0, 0x00000c28, 0xffffffff, 0x28303234,
-	0, 0, 0, 0x00000c2c, 0xffffffff, 0x34363840,
-	0, 0, 0, 0x00000c30, 0xffffffff, 0x26283032,
-	0, 0, 1, 0x00000c34, 0xffffffff, 0x34363840,
-	0, 0, 1, 0x00000c38, 0xffffffff, 0x26283032,
-	0, 0, 0, 0x00000c3c, 0xffffffff, 0x34363840,
-	0, 0, 0, 0x00000c40, 0xffffffff, 0x26283032,
-	0, 0, 0, 0x00000c44, 0xffffffff, 0x38402224,
-	0, 0, 1, 0x00000c48, 0xffffffff, 0x30323436,
-	0, 0, 1, 0x00000c4c, 0xffffffff, 0x22242628,
-	0, 1, 0, 0x00000e20, 0xffffffff, 0x32343638,
-	0, 1, 0, 0x00000e24, 0xffffffff, 0x36384042,
-	0, 1, 0, 0x00000e28, 0xffffffff, 0x28303234,
-	0, 1, 0, 0x00000e2c, 0xffffffff, 0x34363840,
-	0, 1, 0, 0x00000e30, 0xffffffff, 0x26283032,
-	0, 1, 1, 0x00000e34, 0xffffffff, 0x34363840,
-	0, 1, 1, 0x00000e38, 0xffffffff, 0x26283032,
-	0, 1, 0, 0x00000e3c, 0xffffffff, 0x34363840,
-	0, 1, 0, 0x00000e40, 0xffffffff, 0x26283032,
-	0, 1, 0, 0x00000e44, 0xffffffff, 0x38402224,
-	0, 1, 1, 0x00000e48, 0xffffffff, 0x30323436,
-	0, 1, 1, 0x00000e4c, 0xffffffff, 0x22242628,
-	1, 0, 0, 0x00000c24, 0xffffffff, 0x34363840,
-	1, 0, 0, 0x00000c28, 0xffffffff, 0x26283032,
-	1, 0, 0, 0x00000c2c, 0xffffffff, 0x32343638,
-	1, 0, 0, 0x00000c30, 0xffffffff, 0x24262830,
-	1, 0, 1, 0x00000c34, 0xffffffff, 0x32343638,
-	1, 0, 1, 0x00000c38, 0xffffffff, 0x24262830,
-	1, 0, 0, 0x00000c3c, 0xffffffff, 0x32343638,
-	1, 0, 0, 0x00000c40, 0xffffffff, 0x24262830,
-	1, 0, 0, 0x00000c44, 0xffffffff, 0x36382022,
-	1, 0, 1, 0x00000c48, 0xffffffff, 0x28303234,
-	1, 0, 1, 0x00000c4c, 0xffffffff, 0x20222426,
-	1, 1, 0, 0x00000e24, 0xffffffff, 0x34363840,
-	1, 1, 0, 0x00000e28, 0xffffffff, 0x26283032,
-	1, 1, 0, 0x00000e2c, 0xffffffff, 0x32343638,
-	1, 1, 0, 0x00000e30, 0xffffffff, 0x24262830,
-	1, 1, 1, 0x00000e34, 0xffffffff, 0x32343638,
-	1, 1, 1, 0x00000e38, 0xffffffff, 0x24262830,
-	1, 1, 0, 0x00000e3c, 0xffffffff, 0x32343638,
-	1, 1, 0, 0x00000e40, 0xffffffff, 0x24262830,
-	1, 1, 0, 0x00000e44, 0xffffffff, 0x36382022,
-	1, 1, 1, 0x00000e48, 0xffffffff, 0x28303234,
-	1, 1, 1, 0x00000e4c, 0xffffffff, 0x20222426
+static const struct rtw_phy_pg_cfg_pair rtw8822b_bb_pg_type3[] = {
+	{ 0, 0, 0, 0x00000c20, 0xffffffff, 0x32343638, },
+	{ 0, 0, 0, 0x00000c24, 0xffffffff, 0x36384042, },
+	{ 0, 0, 0, 0x00000c28, 0xffffffff, 0x28303234, },
+	{ 0, 0, 0, 0x00000c2c, 0xffffffff, 0x34363840, },
+	{ 0, 0, 0, 0x00000c30, 0xffffffff, 0x26283032, },
+	{ 0, 0, 1, 0x00000c34, 0xffffffff, 0x34363840, },
+	{ 0, 0, 1, 0x00000c38, 0xffffffff, 0x26283032, },
+	{ 0, 0, 0, 0x00000c3c, 0xffffffff, 0x34363840, },
+	{ 0, 0, 0, 0x00000c40, 0xffffffff, 0x26283032, },
+	{ 0, 0, 0, 0x00000c44, 0xffffffff, 0x38402224, },
+	{ 0, 0, 1, 0x00000c48, 0xffffffff, 0x30323436, },
+	{ 0, 0, 1, 0x00000c4c, 0xffffffff, 0x22242628, },
+	{ 0, 1, 0, 0x00000e20, 0xffffffff, 0x32343638, },
+	{ 0, 1, 0, 0x00000e24, 0xffffffff, 0x36384042, },
+	{ 0, 1, 0, 0x00000e28, 0xffffffff, 0x28303234, },
+	{ 0, 1, 0, 0x00000e2c, 0xffffffff, 0x34363840, },
+	{ 0, 1, 0, 0x00000e30, 0xffffffff, 0x26283032, },
+	{ 0, 1, 1, 0x00000e34, 0xffffffff, 0x34363840, },
+	{ 0, 1, 1, 0x00000e38, 0xffffffff, 0x26283032, },
+	{ 0, 1, 0, 0x00000e3c, 0xffffffff, 0x34363840, },
+	{ 0, 1, 0, 0x00000e40, 0xffffffff, 0x26283032, },
+	{ 0, 1, 0, 0x00000e44, 0xffffffff, 0x38402224, },
+	{ 0, 1, 1, 0x00000e48, 0xffffffff, 0x30323436, },
+	{ 0, 1, 1, 0x00000e4c, 0xffffffff, 0x22242628, },
+	{ 1, 0, 0, 0x00000c24, 0xffffffff, 0x34363840, },
+	{ 1, 0, 0, 0x00000c28, 0xffffffff, 0x26283032, },
+	{ 1, 0, 0, 0x00000c2c, 0xffffffff, 0x32343638, },
+	{ 1, 0, 0, 0x00000c30, 0xffffffff, 0x24262830, },
+	{ 1, 0, 1, 0x00000c34, 0xffffffff, 0x32343638, },
+	{ 1, 0, 1, 0x00000c38, 0xffffffff, 0x24262830, },
+	{ 1, 0, 0, 0x00000c3c, 0xffffffff, 0x32343638, },
+	{ 1, 0, 0, 0x00000c40, 0xffffffff, 0x24262830, },
+	{ 1, 0, 0, 0x00000c44, 0xffffffff, 0x36382022, },
+	{ 1, 0, 1, 0x00000c48, 0xffffffff, 0x28303234, },
+	{ 1, 0, 1, 0x00000c4c, 0xffffffff, 0x20222426, },
+	{ 1, 1, 0, 0x00000e24, 0xffffffff, 0x34363840, },
+	{ 1, 1, 0, 0x00000e28, 0xffffffff, 0x26283032, },
+	{ 1, 1, 0, 0x00000e2c, 0xffffffff, 0x32343638, },
+	{ 1, 1, 0, 0x00000e30, 0xffffffff, 0x24262830, },
+	{ 1, 1, 1, 0x00000e34, 0xffffffff, 0x32343638, },
+	{ 1, 1, 1, 0x00000e38, 0xffffffff, 0x24262830, },
+	{ 1, 1, 0, 0x00000e3c, 0xffffffff, 0x32343638, },
+	{ 1, 1, 0, 0x00000e40, 0xffffffff, 0x24262830, },
+	{ 1, 1, 0, 0x00000e44, 0xffffffff, 0x36382022, },
+	{ 1, 1, 1, 0x00000e48, 0xffffffff, 0x28303234, },
+	{ 1, 1, 1, 0x00000e4c, 0xffffffff, 0x20222426, },
+};
+
+RTW_DECL_TABLE_BB_PG(rtw8822b_bb_pg_type3);
+
+static const struct rtw_phy_pg_cfg_pair rtw8822b_bb_pg_type5[] = {
+	{ 0, 0, 0, 0x00000c20, 0xffffffff, 0x32343638, },
+	{ 0, 0, 0, 0x00000c24, 0xffffffff, 0x36384042, },
+	{ 0, 0, 0, 0x00000c28, 0xffffffff, 0x28303234, },
+	{ 0, 0, 0, 0x00000c2c, 0xffffffff, 0x34363840, },
+	{ 0, 0, 0, 0x00000c30, 0xffffffff, 0x26283032, },
+	{ 0, 0, 1, 0x00000c34, 0xffffffff, 0x34363840, },
+	{ 0, 0, 1, 0x00000c38, 0xffffffff, 0x26283032, },
+	{ 0, 0, 0, 0x00000c3c, 0xffffffff, 0x34363840, },
+	{ 0, 0, 0, 0x00000c40, 0xffffffff, 0x26283032, },
+	{ 0, 0, 0, 0x00000c44, 0xffffffff, 0x38402224, },
+	{ 0, 0, 1, 0x00000c48, 0xffffffff, 0x30323436, },
+	{ 0, 0, 1, 0x00000c4c, 0xffffffff, 0x22242628, },
+	{ 0, 1, 0, 0x00000e20, 0xffffffff, 0x32343638, },
+	{ 0, 1, 0, 0x00000e24, 0xffffffff, 0x36384042, },
+	{ 0, 1, 0, 0x00000e28, 0xffffffff, 0x28303234, },
+	{ 0, 1, 0, 0x00000e2c, 0xffffffff, 0x34363840, },
+	{ 0, 1, 0, 0x00000e30, 0xffffffff, 0x26283032, },
+	{ 0, 1, 1, 0x00000e34, 0xffffffff, 0x34363840, },
+	{ 0, 1, 1, 0x00000e38, 0xffffffff, 0x26283032, },
+	{ 0, 1, 0, 0x00000e3c, 0xffffffff, 0x34363840, },
+	{ 0, 1, 0, 0x00000e40, 0xffffffff, 0x26283032, },
+	{ 0, 1, 0, 0x00000e44, 0xffffffff, 0x38402224, },
+	{ 0, 1, 1, 0x00000e48, 0xffffffff, 0x30323436, },
+	{ 0, 1, 1, 0x00000e4c, 0xffffffff, 0x22242628, },
+	{ 1, 0, 0, 0x00000c24, 0xffffffff, 0x34363840, },
+	{ 1, 0, 0, 0x00000c28, 0xffffffff, 0x26283032, },
+	{ 1, 0, 0, 0x00000c2c, 0xffffffff, 0x32343638, },
+	{ 1, 0, 0, 0x00000c30, 0xffffffff, 0x24262830, },
+	{ 1, 0, 1, 0x00000c34, 0xffffffff, 0x32343638, },
+	{ 1, 0, 1, 0x00000c38, 0xffffffff, 0x24262830, },
+	{ 1, 0, 0, 0x00000c3c, 0xffffffff, 0x32343638, },
+	{ 1, 0, 0, 0x00000c40, 0xffffffff, 0x24262830, },
+	{ 1, 0, 0, 0x00000c44, 0xffffffff, 0x36382022, },
+	{ 1, 0, 1, 0x00000c48, 0xffffffff, 0x28303234, },
+	{ 1, 0, 1, 0x00000c4c, 0xffffffff, 0x20222426, },
+	{ 1, 1, 0, 0x00000e24, 0xffffffff, 0x34363840, },
+	{ 1, 1, 0, 0x00000e28, 0xffffffff, 0x26283032, },
+	{ 1, 1, 0, 0x00000e2c, 0xffffffff, 0x32343638, },
+	{ 1, 1, 0, 0x00000e30, 0xffffffff, 0x24262830, },
+	{ 1, 1, 1, 0x00000e34, 0xffffffff, 0x32343638, },
+	{ 1, 1, 1, 0x00000e38, 0xffffffff, 0x24262830, },
+	{ 1, 1, 0, 0x00000e3c, 0xffffffff, 0x32343638, },
+	{ 1, 1, 0, 0x00000e40, 0xffffffff, 0x24262830, },
+	{ 1, 1, 0, 0x00000e44, 0xffffffff, 0x36382022, },
+	{ 1, 1, 1, 0x00000e48, 0xffffffff, 0x28303234, },
+	{ 1, 1, 1, 0x00000e4c, 0xffffffff, 0x20222426, },
 };
 
 RTW_DECL_TABLE_BB_PG(rtw8822b_bb_pg_type5);
@@ -20382,6 +20433,596 @@
 
 RTW_DECL_TABLE_RF_RADIO(rtw8822b_rf_b, B);
 
+static const struct rtw_txpwr_lmt_cfg_pair rtw8822b_txpwr_lmt_type0[] = {
+	{ 0, 0, 0, 0, 1, 32, },
+	{ 2, 0, 0, 0, 1, 28, },
+	{ 1, 0, 0, 0, 1, 30, },
+	{ 0, 0, 0, 0, 2, 32, },
+	{ 2, 0, 0, 0, 2, 28, },
+	{ 1, 0, 0, 0, 2, 30, },
+	{ 0, 0, 0, 0, 3, 32, },
+	{ 2, 0, 0, 0, 3, 28, },
+	{ 1, 0, 0, 0, 3, 30, },
+	{ 0, 0, 0, 0, 4, 32, },
+	{ 2, 0, 0, 0, 4, 28, },
+	{ 1, 0, 0, 0, 4, 30, },
+	{ 0, 0, 0, 0, 5, 32, },
+	{ 2, 0, 0, 0, 5, 28, },
+	{ 1, 0, 0, 0, 5, 30, },
+	{ 0, 0, 0, 0, 6, 32, },
+	{ 2, 0, 0, 0, 6, 28, },
+	{ 1, 0, 0, 0, 6, 30, },
+	{ 0, 0, 0, 0, 7, 32, },
+	{ 2, 0, 0, 0, 7, 28, },
+	{ 1, 0, 0, 0, 7, 30, },
+	{ 0, 0, 0, 0, 8, 32, },
+	{ 2, 0, 0, 0, 8, 28, },
+	{ 1, 0, 0, 0, 8, 30, },
+	{ 0, 0, 0, 0, 9, 32, },
+	{ 2, 0, 0, 0, 9, 28, },
+	{ 1, 0, 0, 0, 9, 30, },
+	{ 0, 0, 0, 0, 10, 32, },
+	{ 2, 0, 0, 0, 10, 28, },
+	{ 1, 0, 0, 0, 10, 30, },
+	{ 0, 0, 0, 0, 11, 32, },
+	{ 2, 0, 0, 0, 11, 28, },
+	{ 1, 0, 0, 0, 11, 30, },
+	{ 0, 0, 0, 0, 12, 26, },
+	{ 2, 0, 0, 0, 12, 28, },
+	{ 1, 0, 0, 0, 12, 30, },
+	{ 0, 0, 0, 0, 13, 20, },
+	{ 2, 0, 0, 0, 13, 28, },
+	{ 1, 0, 0, 0, 13, 28, },
+	{ 0, 0, 0, 0, 14, 63, },
+	{ 2, 0, 0, 0, 14, 63, },
+	{ 1, 0, 0, 0, 14, 32, },
+	{ 0, 0, 0, 1, 1, 26, },
+	{ 2, 0, 0, 1, 1, 30, },
+	{ 1, 0, 0, 1, 1, 34, },
+	{ 0, 0, 0, 1, 2, 30, },
+	{ 2, 0, 0, 1, 2, 30, },
+	{ 1, 0, 0, 1, 2, 34, },
+	{ 0, 0, 0, 1, 3, 32, },
+	{ 2, 0, 0, 1, 3, 30, },
+	{ 1, 0, 0, 1, 3, 34, },
+	{ 0, 0, 0, 1, 4, 34, },
+	{ 2, 0, 0, 1, 4, 30, },
+	{ 1, 0, 0, 1, 4, 34, },
+	{ 0, 0, 0, 1, 5, 34, },
+	{ 2, 0, 0, 1, 5, 30, },
+	{ 1, 0, 0, 1, 5, 34, },
+	{ 0, 0, 0, 1, 6, 34, },
+	{ 2, 0, 0, 1, 6, 30, },
+	{ 1, 0, 0, 1, 6, 34, },
+	{ 0, 0, 0, 1, 7, 34, },
+	{ 2, 0, 0, 1, 7, 30, },
+	{ 1, 0, 0, 1, 7, 34, },
+	{ 0, 0, 0, 1, 8, 34, },
+	{ 2, 0, 0, 1, 8, 30, },
+	{ 1, 0, 0, 1, 8, 34, },
+	{ 0, 0, 0, 1, 9, 32, },
+	{ 2, 0, 0, 1, 9, 30, },
+	{ 1, 0, 0, 1, 9, 34, },
+	{ 0, 0, 0, 1, 10, 30, },
+	{ 2, 0, 0, 1, 10, 30, },
+	{ 1, 0, 0, 1, 10, 34, },
+	{ 0, 0, 0, 1, 11, 28, },
+	{ 2, 0, 0, 1, 11, 30, },
+	{ 1, 0, 0, 1, 11, 34, },
+	{ 0, 0, 0, 1, 12, 22, },
+	{ 2, 0, 0, 1, 12, 30, },
+	{ 1, 0, 0, 1, 12, 34, },
+	{ 0, 0, 0, 1, 13, 14, },
+	{ 2, 0, 0, 1, 13, 30, },
+	{ 1, 0, 0, 1, 13, 34, },
+	{ 0, 0, 0, 1, 14, 63, },
+	{ 2, 0, 0, 1, 14, 63, },
+	{ 1, 0, 0, 1, 14, 63, },
+	{ 0, 0, 0, 2, 1, 26, },
+	{ 2, 0, 0, 2, 1, 30, },
+	{ 1, 0, 0, 2, 1, 34, },
+	{ 0, 0, 0, 2, 2, 30, },
+	{ 2, 0, 0, 2, 2, 30, },
+	{ 1, 0, 0, 2, 2, 34, },
+	{ 0, 0, 0, 2, 3, 32, },
+	{ 2, 0, 0, 2, 3, 30, },
+	{ 1, 0, 0, 2, 3, 34, },
+	{ 0, 0, 0, 2, 4, 34, },
+	{ 2, 0, 0, 2, 4, 30, },
+	{ 1, 0, 0, 2, 4, 34, },
+	{ 0, 0, 0, 2, 5, 34, },
+	{ 2, 0, 0, 2, 5, 30, },
+	{ 1, 0, 0, 2, 5, 34, },
+	{ 0, 0, 0, 2, 6, 34, },
+	{ 2, 0, 0, 2, 6, 30, },
+	{ 1, 0, 0, 2, 6, 34, },
+	{ 0, 0, 0, 2, 7, 34, },
+	{ 2, 0, 0, 2, 7, 30, },
+	{ 1, 0, 0, 2, 7, 34, },
+	{ 0, 0, 0, 2, 8, 34, },
+	{ 2, 0, 0, 2, 8, 30, },
+	{ 1, 0, 0, 2, 8, 34, },
+	{ 0, 0, 0, 2, 9, 32, },
+	{ 2, 0, 0, 2, 9, 30, },
+	{ 1, 0, 0, 2, 9, 34, },
+	{ 0, 0, 0, 2, 10, 30, },
+	{ 2, 0, 0, 2, 10, 30, },
+	{ 1, 0, 0, 2, 10, 34, },
+	{ 0, 0, 0, 2, 11, 26, },
+	{ 2, 0, 0, 2, 11, 30, },
+	{ 1, 0, 0, 2, 11, 34, },
+	{ 0, 0, 0, 2, 12, 20, },
+	{ 2, 0, 0, 2, 12, 30, },
+	{ 1, 0, 0, 2, 12, 34, },
+	{ 0, 0, 0, 2, 13, 14, },
+	{ 2, 0, 0, 2, 13, 30, },
+	{ 1, 0, 0, 2, 13, 34, },
+	{ 0, 0, 0, 2, 14, 63, },
+	{ 2, 0, 0, 2, 14, 63, },
+	{ 1, 0, 0, 2, 14, 63, },
+	{ 0, 0, 0, 3, 1, 26, },
+	{ 2, 0, 0, 3, 1, 18, },
+	{ 1, 0, 0, 3, 1, 30, },
+	{ 0, 0, 0, 3, 2, 28, },
+	{ 2, 0, 0, 3, 2, 18, },
+	{ 1, 0, 0, 3, 2, 30, },
+	{ 0, 0, 0, 3, 3, 30, },
+	{ 2, 0, 0, 3, 3, 18, },
+	{ 1, 0, 0, 3, 3, 30, },
+	{ 0, 0, 0, 3, 4, 30, },
+	{ 2, 0, 0, 3, 4, 18, },
+	{ 1, 0, 0, 3, 4, 30, },
+	{ 0, 0, 0, 3, 5, 32, },
+	{ 2, 0, 0, 3, 5, 18, },
+	{ 1, 0, 0, 3, 5, 30, },
+	{ 0, 0, 0, 3, 6, 32, },
+	{ 2, 0, 0, 3, 6, 18, },
+	{ 1, 0, 0, 3, 6, 30, },
+	{ 0, 0, 0, 3, 7, 32, },
+	{ 2, 0, 0, 3, 7, 18, },
+	{ 1, 0, 0, 3, 7, 30, },
+	{ 0, 0, 0, 3, 8, 30, },
+	{ 2, 0, 0, 3, 8, 18, },
+	{ 1, 0, 0, 3, 8, 30, },
+	{ 0, 0, 0, 3, 9, 30, },
+	{ 2, 0, 0, 3, 9, 18, },
+	{ 1, 0, 0, 3, 9, 30, },
+	{ 0, 0, 0, 3, 10, 28, },
+	{ 2, 0, 0, 3, 10, 18, },
+	{ 1, 0, 0, 3, 10, 30, },
+	{ 0, 0, 0, 3, 11, 26, },
+	{ 2, 0, 0, 3, 11, 18, },
+	{ 1, 0, 0, 3, 11, 30, },
+	{ 0, 0, 0, 3, 12, 20, },
+	{ 2, 0, 0, 3, 12, 18, },
+	{ 1, 0, 0, 3, 12, 30, },
+	{ 0, 0, 0, 3, 13, 14, },
+	{ 2, 0, 0, 3, 13, 18, },
+	{ 1, 0, 0, 3, 13, 30, },
+	{ 0, 0, 0, 3, 14, 63, },
+	{ 2, 0, 0, 3, 14, 63, },
+	{ 1, 0, 0, 3, 14, 63, },
+	{ 0, 0, 1, 2, 1, 63, },
+	{ 2, 0, 1, 2, 1, 63, },
+	{ 1, 0, 1, 2, 1, 63, },
+	{ 0, 0, 1, 2, 2, 63, },
+	{ 2, 0, 1, 2, 2, 63, },
+	{ 1, 0, 1, 2, 2, 63, },
+	{ 0, 0, 1, 2, 3, 26, },
+	{ 2, 0, 1, 2, 3, 30, },
+	{ 1, 0, 1, 2, 3, 34, },
+	{ 0, 0, 1, 2, 4, 26, },
+	{ 2, 0, 1, 2, 4, 30, },
+	{ 1, 0, 1, 2, 4, 34, },
+	{ 0, 0, 1, 2, 5, 30, },
+	{ 2, 0, 1, 2, 5, 30, },
+	{ 1, 0, 1, 2, 5, 34, },
+	{ 0, 0, 1, 2, 6, 32, },
+	{ 2, 0, 1, 2, 6, 30, },
+	{ 1, 0, 1, 2, 6, 34, },
+	{ 0, 0, 1, 2, 7, 30, },
+	{ 2, 0, 1, 2, 7, 30, },
+	{ 1, 0, 1, 2, 7, 34, },
+	{ 0, 0, 1, 2, 8, 26, },
+	{ 2, 0, 1, 2, 8, 30, },
+	{ 1, 0, 1, 2, 8, 34, },
+	{ 0, 0, 1, 2, 9, 26, },
+	{ 2, 0, 1, 2, 9, 30, },
+	{ 1, 0, 1, 2, 9, 34, },
+	{ 0, 0, 1, 2, 10, 20, },
+	{ 2, 0, 1, 2, 10, 30, },
+	{ 1, 0, 1, 2, 10, 34, },
+	{ 0, 0, 1, 2, 11, 14, },
+	{ 2, 0, 1, 2, 11, 30, },
+	{ 1, 0, 1, 2, 11, 34, },
+	{ 0, 0, 1, 2, 12, 63, },
+	{ 2, 0, 1, 2, 12, 63, },
+	{ 1, 0, 1, 2, 12, 63, },
+	{ 0, 0, 1, 2, 13, 63, },
+	{ 2, 0, 1, 2, 13, 63, },
+	{ 1, 0, 1, 2, 13, 63, },
+	{ 0, 0, 1, 2, 14, 63, },
+	{ 2, 0, 1, 2, 14, 63, },
+	{ 1, 0, 1, 2, 14, 63, },
+	{ 0, 0, 1, 3, 1, 63, },
+	{ 2, 0, 1, 3, 1, 63, },
+	{ 1, 0, 1, 3, 1, 63, },
+	{ 0, 0, 1, 3, 2, 63, },
+	{ 2, 0, 1, 3, 2, 63, },
+	{ 1, 0, 1, 3, 2, 63, },
+	{ 0, 0, 1, 3, 3, 24, },
+	{ 2, 0, 1, 3, 3, 18, },
+	{ 1, 0, 1, 3, 3, 30, },
+	{ 0, 0, 1, 3, 4, 24, },
+	{ 2, 0, 1, 3, 4, 18, },
+	{ 1, 0, 1, 3, 4, 30, },
+	{ 0, 0, 1, 3, 5, 26, },
+	{ 2, 0, 1, 3, 5, 18, },
+	{ 1, 0, 1, 3, 5, 30, },
+	{ 0, 0, 1, 3, 6, 28, },
+	{ 2, 0, 1, 3, 6, 18, },
+	{ 1, 0, 1, 3, 6, 30, },
+	{ 0, 0, 1, 3, 7, 26, },
+	{ 2, 0, 1, 3, 7, 18, },
+	{ 1, 0, 1, 3, 7, 30, },
+	{ 0, 0, 1, 3, 8, 26, },
+	{ 2, 0, 1, 3, 8, 18, },
+	{ 1, 0, 1, 3, 8, 30, },
+	{ 0, 0, 1, 3, 9, 26, },
+	{ 2, 0, 1, 3, 9, 18, },
+	{ 1, 0, 1, 3, 9, 30, },
+	{ 0, 0, 1, 3, 10, 20, },
+	{ 2, 0, 1, 3, 10, 18, },
+	{ 1, 0, 1, 3, 10, 30, },
+	{ 0, 0, 1, 3, 11, 14, },
+	{ 2, 0, 1, 3, 11, 18, },
+	{ 1, 0, 1, 3, 11, 30, },
+	{ 0, 0, 1, 3, 12, 63, },
+	{ 2, 0, 1, 3, 12, 63, },
+	{ 1, 0, 1, 3, 12, 63, },
+	{ 0, 0, 1, 3, 13, 63, },
+	{ 2, 0, 1, 3, 13, 63, },
+	{ 1, 0, 1, 3, 13, 63, },
+	{ 0, 0, 1, 3, 14, 63, },
+	{ 2, 0, 1, 3, 14, 63, },
+	{ 1, 0, 1, 3, 14, 63, },
+	{ 0, 1, 0, 1, 36, 30, },
+	{ 2, 1, 0, 1, 36, 32, },
+	{ 1, 1, 0, 1, 36, 30, },
+	{ 0, 1, 0, 1, 40, 32, },
+	{ 2, 1, 0, 1, 40, 32, },
+	{ 1, 1, 0, 1, 40, 30, },
+	{ 0, 1, 0, 1, 44, 32, },
+	{ 2, 1, 0, 1, 44, 32, },
+	{ 1, 1, 0, 1, 44, 30, },
+	{ 0, 1, 0, 1, 48, 32, },
+	{ 2, 1, 0, 1, 48, 32, },
+	{ 1, 1, 0, 1, 48, 30, },
+	{ 0, 1, 0, 1, 52, 32, },
+	{ 2, 1, 0, 1, 52, 32, },
+	{ 1, 1, 0, 1, 52, 28, },
+	{ 0, 1, 0, 1, 56, 32, },
+	{ 2, 1, 0, 1, 56, 32, },
+	{ 1, 1, 0, 1, 56, 28, },
+	{ 0, 1, 0, 1, 60, 32, },
+	{ 2, 1, 0, 1, 60, 32, },
+	{ 1, 1, 0, 1, 60, 28, },
+	{ 0, 1, 0, 1, 64, 28, },
+	{ 2, 1, 0, 1, 64, 32, },
+	{ 1, 1, 0, 1, 64, 28, },
+	{ 0, 1, 0, 1, 100, 26, },
+	{ 2, 1, 0, 1, 100, 32, },
+	{ 1, 1, 0, 1, 100, 32, },
+	{ 0, 1, 0, 1, 104, 32, },
+	{ 2, 1, 0, 1, 104, 32, },
+	{ 1, 1, 0, 1, 104, 32, },
+	{ 0, 1, 0, 1, 108, 32, },
+	{ 2, 1, 0, 1, 108, 32, },
+	{ 1, 1, 0, 1, 108, 32, },
+	{ 0, 1, 0, 1, 112, 32, },
+	{ 2, 1, 0, 1, 112, 32, },
+	{ 1, 1, 0, 1, 112, 32, },
+	{ 0, 1, 0, 1, 116, 32, },
+	{ 2, 1, 0, 1, 116, 32, },
+	{ 1, 1, 0, 1, 116, 32, },
+	{ 0, 1, 0, 1, 120, 32, },
+	{ 2, 1, 0, 1, 120, 32, },
+	{ 1, 1, 0, 1, 120, 32, },
+	{ 0, 1, 0, 1, 124, 32, },
+	{ 2, 1, 0, 1, 124, 32, },
+	{ 1, 1, 0, 1, 124, 32, },
+	{ 0, 1, 0, 1, 128, 32, },
+	{ 2, 1, 0, 1, 128, 32, },
+	{ 1, 1, 0, 1, 128, 32, },
+	{ 0, 1, 0, 1, 132, 32, },
+	{ 2, 1, 0, 1, 132, 32, },
+	{ 1, 1, 0, 1, 132, 32, },
+	{ 0, 1, 0, 1, 136, 32, },
+	{ 2, 1, 0, 1, 136, 32, },
+	{ 1, 1, 0, 1, 136, 32, },
+	{ 0, 1, 0, 1, 140, 28, },
+	{ 2, 1, 0, 1, 140, 32, },
+	{ 1, 1, 0, 1, 140, 32, },
+	{ 0, 1, 0, 1, 144, 28, },
+	{ 2, 1, 0, 1, 144, 32, },
+	{ 1, 1, 0, 1, 144, 63, },
+	{ 0, 1, 0, 1, 149, 32, },
+	{ 2, 1, 0, 1, 149, 63, },
+	{ 1, 1, 0, 1, 149, 63, },
+	{ 0, 1, 0, 1, 153, 32, },
+	{ 2, 1, 0, 1, 153, 63, },
+	{ 1, 1, 0, 1, 153, 63, },
+	{ 0, 1, 0, 1, 157, 32, },
+	{ 2, 1, 0, 1, 157, 63, },
+	{ 1, 1, 0, 1, 157, 63, },
+	{ 0, 1, 0, 1, 161, 32, },
+	{ 2, 1, 0, 1, 161, 63, },
+	{ 1, 1, 0, 1, 161, 63, },
+	{ 0, 1, 0, 1, 165, 32, },
+	{ 2, 1, 0, 1, 165, 63, },
+	{ 1, 1, 0, 1, 165, 63, },
+	{ 0, 1, 0, 2, 36, 30, },
+	{ 2, 1, 0, 2, 36, 32, },
+	{ 1, 1, 0, 2, 36, 28, },
+	{ 0, 1, 0, 2, 40, 32, },
+	{ 2, 1, 0, 2, 40, 32, },
+	{ 1, 1, 0, 2, 40, 28, },
+	{ 0, 1, 0, 2, 44, 32, },
+	{ 2, 1, 0, 2, 44, 32, },
+	{ 1, 1, 0, 2, 44, 28, },
+	{ 0, 1, 0, 2, 48, 32, },
+	{ 2, 1, 0, 2, 48, 32, },
+	{ 1, 1, 0, 2, 48, 28, },
+	{ 0, 1, 0, 2, 52, 32, },
+	{ 2, 1, 0, 2, 52, 32, },
+	{ 1, 1, 0, 2, 52, 28, },
+	{ 0, 1, 0, 2, 56, 32, },
+	{ 2, 1, 0, 2, 56, 32, },
+	{ 1, 1, 0, 2, 56, 28, },
+	{ 0, 1, 0, 2, 60, 32, },
+	{ 2, 1, 0, 2, 60, 32, },
+	{ 1, 1, 0, 2, 60, 28, },
+	{ 0, 1, 0, 2, 64, 28, },
+	{ 2, 1, 0, 2, 64, 32, },
+	{ 1, 1, 0, 2, 64, 28, },
+	{ 0, 1, 0, 2, 100, 26, },
+	{ 2, 1, 0, 2, 100, 32, },
+	{ 1, 1, 0, 2, 100, 32, },
+	{ 0, 1, 0, 2, 104, 32, },
+	{ 2, 1, 0, 2, 104, 32, },
+	{ 1, 1, 0, 2, 104, 32, },
+	{ 0, 1, 0, 2, 108, 32, },
+	{ 2, 1, 0, 2, 108, 32, },
+	{ 1, 1, 0, 2, 108, 32, },
+	{ 0, 1, 0, 2, 112, 32, },
+	{ 2, 1, 0, 2, 112, 32, },
+	{ 1, 1, 0, 2, 112, 32, },
+	{ 0, 1, 0, 2, 116, 32, },
+	{ 2, 1, 0, 2, 116, 32, },
+	{ 1, 1, 0, 2, 116, 32, },
+	{ 0, 1, 0, 2, 120, 32, },
+	{ 2, 1, 0, 2, 120, 32, },
+	{ 1, 1, 0, 2, 120, 32, },
+	{ 0, 1, 0, 2, 124, 32, },
+	{ 2, 1, 0, 2, 124, 32, },
+	{ 1, 1, 0, 2, 124, 32, },
+	{ 0, 1, 0, 2, 128, 32, },
+	{ 2, 1, 0, 2, 128, 32, },
+	{ 1, 1, 0, 2, 128, 32, },
+	{ 0, 1, 0, 2, 132, 32, },
+	{ 2, 1, 0, 2, 132, 32, },
+	{ 1, 1, 0, 2, 132, 32, },
+	{ 0, 1, 0, 2, 136, 32, },
+	{ 2, 1, 0, 2, 136, 32, },
+	{ 1, 1, 0, 2, 136, 32, },
+	{ 0, 1, 0, 2, 140, 26, },
+	{ 2, 1, 0, 2, 140, 32, },
+	{ 1, 1, 0, 2, 140, 32, },
+	{ 0, 1, 0, 2, 144, 26, },
+	{ 2, 1, 0, 2, 144, 63, },
+	{ 1, 1, 0, 2, 144, 63, },
+	{ 0, 1, 0, 2, 149, 32, },
+	{ 2, 1, 0, 2, 149, 63, },
+	{ 1, 1, 0, 2, 149, 63, },
+	{ 0, 1, 0, 2, 153, 32, },
+	{ 2, 1, 0, 2, 153, 63, },
+	{ 1, 1, 0, 2, 153, 63, },
+	{ 0, 1, 0, 2, 157, 32, },
+	{ 2, 1, 0, 2, 157, 63, },
+	{ 1, 1, 0, 2, 157, 63, },
+	{ 0, 1, 0, 2, 161, 32, },
+	{ 2, 1, 0, 2, 161, 63, },
+	{ 1, 1, 0, 2, 161, 63, },
+	{ 0, 1, 0, 2, 165, 32, },
+	{ 2, 1, 0, 2, 165, 63, },
+	{ 1, 1, 0, 2, 165, 63, },
+	{ 0, 1, 0, 3, 36, 28, },
+	{ 2, 1, 0, 3, 36, 20, },
+	{ 1, 1, 0, 3, 36, 22, },
+	{ 0, 1, 0, 3, 40, 30, },
+	{ 2, 1, 0, 3, 40, 20, },
+	{ 1, 1, 0, 3, 40, 22, },
+	{ 0, 1, 0, 3, 44, 30, },
+	{ 2, 1, 0, 3, 44, 20, },
+	{ 1, 1, 0, 3, 44, 22, },
+	{ 0, 1, 0, 3, 48, 30, },
+	{ 2, 1, 0, 3, 48, 20, },
+	{ 1, 1, 0, 3, 48, 22, },
+	{ 0, 1, 0, 3, 52, 30, },
+	{ 2, 1, 0, 3, 52, 20, },
+	{ 1, 1, 0, 3, 52, 22, },
+	{ 0, 1, 0, 3, 56, 30, },
+	{ 2, 1, 0, 3, 56, 20, },
+	{ 1, 1, 0, 3, 56, 22, },
+	{ 0, 1, 0, 3, 60, 30, },
+	{ 2, 1, 0, 3, 60, 20, },
+	{ 1, 1, 0, 3, 60, 22, },
+	{ 0, 1, 0, 3, 64, 28, },
+	{ 2, 1, 0, 3, 64, 20, },
+	{ 1, 1, 0, 3, 64, 22, },
+	{ 0, 1, 0, 3, 100, 26, },
+	{ 2, 1, 0, 3, 100, 20, },
+	{ 1, 1, 0, 3, 100, 30, },
+	{ 0, 1, 0, 3, 104, 30, },
+	{ 2, 1, 0, 3, 104, 20, },
+	{ 1, 1, 0, 3, 104, 30, },
+	{ 0, 1, 0, 3, 108, 32, },
+	{ 2, 1, 0, 3, 108, 20, },
+	{ 1, 1, 0, 3, 108, 30, },
+	{ 0, 1, 0, 3, 112, 32, },
+	{ 2, 1, 0, 3, 112, 20, },
+	{ 1, 1, 0, 3, 112, 30, },
+	{ 0, 1, 0, 3, 116, 32, },
+	{ 2, 1, 0, 3, 116, 20, },
+	{ 1, 1, 0, 3, 116, 30, },
+	{ 0, 1, 0, 3, 120, 32, },
+	{ 2, 1, 0, 3, 120, 20, },
+	{ 1, 1, 0, 3, 120, 30, },
+	{ 0, 1, 0, 3, 124, 32, },
+	{ 2, 1, 0, 3, 124, 20, },
+	{ 1, 1, 0, 3, 124, 30, },
+	{ 0, 1, 0, 3, 128, 32, },
+	{ 2, 1, 0, 3, 128, 20, },
+	{ 1, 1, 0, 3, 128, 30, },
+	{ 0, 1, 0, 3, 132, 32, },
+	{ 2, 1, 0, 3, 132, 20, },
+	{ 1, 1, 0, 3, 132, 30, },
+	{ 0, 1, 0, 3, 136, 30, },
+	{ 2, 1, 0, 3, 136, 20, },
+	{ 1, 1, 0, 3, 136, 30, },
+	{ 0, 1, 0, 3, 140, 26, },
+	{ 2, 1, 0, 3, 140, 20, },
+	{ 1, 1, 0, 3, 140, 30, },
+	{ 0, 1, 0, 3, 144, 26, },
+	{ 2, 1, 0, 3, 144, 63, },
+	{ 1, 1, 0, 3, 144, 63, },
+	{ 0, 1, 0, 3, 149, 32, },
+	{ 2, 1, 0, 3, 149, 63, },
+	{ 1, 1, 0, 3, 149, 63, },
+	{ 0, 1, 0, 3, 153, 32, },
+	{ 2, 1, 0, 3, 153, 63, },
+	{ 1, 1, 0, 3, 153, 63, },
+	{ 0, 1, 0, 3, 157, 32, },
+	{ 2, 1, 0, 3, 157, 63, },
+	{ 1, 1, 0, 3, 157, 63, },
+	{ 0, 1, 0, 3, 161, 32, },
+	{ 2, 1, 0, 3, 161, 63, },
+	{ 1, 1, 0, 3, 161, 63, },
+	{ 0, 1, 0, 3, 165, 32, },
+	{ 2, 1, 0, 3, 165, 63, },
+	{ 1, 1, 0, 3, 165, 63, },
+	{ 0, 1, 1, 2, 38, 22, },
+	{ 2, 1, 1, 2, 38, 30, },
+	{ 1, 1, 1, 2, 38, 30, },
+	{ 0, 1, 1, 2, 46, 30, },
+	{ 2, 1, 1, 2, 46, 30, },
+	{ 1, 1, 1, 2, 46, 30, },
+	{ 0, 1, 1, 2, 54, 30, },
+	{ 2, 1, 1, 2, 54, 30, },
+	{ 1, 1, 1, 2, 54, 30, },
+	{ 0, 1, 1, 2, 62, 24, },
+	{ 2, 1, 1, 2, 62, 30, },
+	{ 1, 1, 1, 2, 62, 30, },
+	{ 0, 1, 1, 2, 102, 24, },
+	{ 2, 1, 1, 2, 102, 30, },
+	{ 1, 1, 1, 2, 102, 30, },
+	{ 0, 1, 1, 2, 110, 30, },
+	{ 2, 1, 1, 2, 110, 30, },
+	{ 1, 1, 1, 2, 110, 30, },
+	{ 0, 1, 1, 2, 118, 30, },
+	{ 2, 1, 1, 2, 118, 30, },
+	{ 1, 1, 1, 2, 118, 30, },
+	{ 0, 1, 1, 2, 126, 30, },
+	{ 2, 1, 1, 2, 126, 30, },
+	{ 1, 1, 1, 2, 126, 30, },
+	{ 0, 1, 1, 2, 134, 30, },
+	{ 2, 1, 1, 2, 134, 30, },
+	{ 1, 1, 1, 2, 134, 30, },
+	{ 0, 1, 1, 2, 142, 30, },
+	{ 2, 1, 1, 2, 142, 63, },
+	{ 1, 1, 1, 2, 142, 63, },
+	{ 0, 1, 1, 2, 151, 30, },
+	{ 2, 1, 1, 2, 151, 63, },
+	{ 1, 1, 1, 2, 151, 63, },
+	{ 0, 1, 1, 2, 159, 30, },
+	{ 2, 1, 1, 2, 159, 63, },
+	{ 1, 1, 1, 2, 159, 63, },
+	{ 0, 1, 1, 3, 38, 20, },
+	{ 2, 1, 1, 3, 38, 20, },
+	{ 1, 1, 1, 3, 38, 22, },
+	{ 0, 1, 1, 3, 46, 30, },
+	{ 2, 1, 1, 3, 46, 20, },
+	{ 1, 1, 1, 3, 46, 22, },
+	{ 0, 1, 1, 3, 54, 30, },
+	{ 2, 1, 1, 3, 54, 20, },
+	{ 1, 1, 1, 3, 54, 22, },
+	{ 0, 1, 1, 3, 62, 22, },
+	{ 2, 1, 1, 3, 62, 20, },
+	{ 1, 1, 1, 3, 62, 22, },
+	{ 0, 1, 1, 3, 102, 22, },
+	{ 2, 1, 1, 3, 102, 20, },
+	{ 1, 1, 1, 3, 102, 30, },
+	{ 0, 1, 1, 3, 110, 30, },
+	{ 2, 1, 1, 3, 110, 20, },
+	{ 1, 1, 1, 3, 110, 30, },
+	{ 0, 1, 1, 3, 118, 30, },
+	{ 2, 1, 1, 3, 118, 20, },
+	{ 1, 1, 1, 3, 118, 30, },
+	{ 0, 1, 1, 3, 126, 30, },
+	{ 2, 1, 1, 3, 126, 20, },
+	{ 1, 1, 1, 3, 126, 30, },
+	{ 0, 1, 1, 3, 134, 30, },
+	{ 2, 1, 1, 3, 134, 20, },
+	{ 1, 1, 1, 3, 134, 30, },
+	{ 0, 1, 1, 3, 142, 30, },
+	{ 2, 1, 1, 3, 142, 63, },
+	{ 1, 1, 1, 3, 142, 63, },
+	{ 0, 1, 1, 3, 151, 30, },
+	{ 2, 1, 1, 3, 151, 63, },
+	{ 1, 1, 1, 3, 151, 63, },
+	{ 0, 1, 1, 3, 159, 30, },
+	{ 2, 1, 1, 3, 159, 63, },
+	{ 1, 1, 1, 3, 159, 63, },
+	{ 0, 1, 2, 4, 42, 20, },
+	{ 2, 1, 2, 4, 42, 30, },
+	{ 1, 1, 2, 4, 42, 28, },
+	{ 0, 1, 2, 4, 58, 20, },
+	{ 2, 1, 2, 4, 58, 30, },
+	{ 1, 1, 2, 4, 58, 28, },
+	{ 0, 1, 2, 4, 106, 20, },
+	{ 2, 1, 2, 4, 106, 30, },
+	{ 1, 1, 2, 4, 106, 30, },
+	{ 0, 1, 2, 4, 122, 30, },
+	{ 2, 1, 2, 4, 122, 30, },
+	{ 1, 1, 2, 4, 122, 30, },
+	{ 0, 1, 2, 4, 138, 30, },
+	{ 2, 1, 2, 4, 138, 63, },
+	{ 1, 1, 2, 4, 138, 63, },
+	{ 0, 1, 2, 4, 155, 30, },
+	{ 2, 1, 2, 4, 155, 63, },
+	{ 1, 1, 2, 4, 155, 63, },
+	{ 0, 1, 2, 5, 42, 18, },
+	{ 2, 1, 2, 5, 42, 20, },
+	{ 1, 1, 2, 5, 42, 22, },
+	{ 0, 1, 2, 5, 58, 18, },
+	{ 2, 1, 2, 5, 58, 20, },
+	{ 1, 1, 2, 5, 58, 22, },
+	{ 0, 1, 2, 5, 106, 20, },
+	{ 2, 1, 2, 5, 106, 20, },
+	{ 1, 1, 2, 5, 106, 30, },
+	{ 0, 1, 2, 5, 122, 30, },
+	{ 2, 1, 2, 5, 122, 20, },
+	{ 1, 1, 2, 5, 122, 30, },
+	{ 0, 1, 2, 5, 138, 30, },
+	{ 2, 1, 2, 5, 138, 63, },
+	{ 1, 1, 2, 5, 138, 63, },
+	{ 0, 1, 2, 5, 155, 30, },
+	{ 2, 1, 2, 5, 155, 63, },
+	{ 1, 1, 2, 5, 155, 63, },
+};
+
+RTW_DECL_TABLE_TXPWR_LMT(rtw8822b_txpwr_lmt_type0);
+
 static const struct rtw_txpwr_lmt_cfg_pair rtw8822b_txpwr_lmt_type2[] = {
 	{ 0, 0, 0, 0, 1, 32, },
 	{ 2, 0, 0, 0, 1, 28, },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/rtw8822b_table.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/rtw8822b_table.h
@@ -9,9 +9,11 @@
 extern const struct rtw_table rtw8822b_agc_tbl;
 extern const struct rtw_table rtw8822b_bb_tbl;
 extern const struct rtw_table rtw8822b_bb_pg_type2_tbl;
+extern const struct rtw_table rtw8822b_bb_pg_type3_tbl;
 extern const struct rtw_table rtw8822b_bb_pg_type5_tbl;
 extern const struct rtw_table rtw8822b_rf_a_tbl;
 extern const struct rtw_table rtw8822b_rf_b_tbl;
+extern const struct rtw_table rtw8822b_txpwr_lmt_type0_tbl;
 extern const struct rtw_table rtw8822b_txpwr_lmt_type2_tbl;
 extern const struct rtw_table rtw8822b_txpwr_lmt_type5_tbl;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/rtw8822c.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/rtw8822c.c
@@ -14,6 +14,7 @@
 #include "reg.h"
 #include "debug.h"
 #include "util.h"
+#include "bf.h"
 
 static void rtw8822c_config_trx_mode(struct rtw_dev *rtwdev, u8 tx_path,
 				     u8 rx_path, bool is_tx2_path);
@@ -40,6 +41,11 @@
 	efuse->country_code[1] = map->country_code[1];
 	efuse->bt_setting = map->rf_bt_setting;
 	efuse->regd = map->rf_board_option & 0x7;
+	efuse->thermal_meter[RF_PATH_A] = map->path_a_thermal;
+	efuse->thermal_meter[RF_PATH_B] = map->path_b_thermal;
+	efuse->thermal_meter_k =
+			(map->path_a_thermal + map->path_b_thermal) >> 1;
+	efuse->power_track_type = (map->tx_pwr_calibrate_rate >> 4) & 0xf;
 
 	for (i = 0; i < 4; i++)
 		efuse->txpwr_idx_table[i] = map->txpwr_idx_table[i];
@@ -1000,6 +1006,21 @@
 	rtw8822c_rf_x2_check(rtwdev);
 }
 
+static void rtw8822c_pwrtrack_init(struct rtw_dev *rtwdev)
+{
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+	u8 path;
+
+	for (path = RF_PATH_A; path < RTW_RF_PATH_MAX; path++) {
+		dm_info->delta_power_index[path] = 0;
+		ewma_thermal_init(&dm_info->avg_thermal[path]);
+		dm_info->thermal_avg[path] = 0xff;
+	}
+
+	dm_info->pwr_trk_triggered = false;
+	dm_info->thermal_meter_k = rtwdev->efuse.thermal_meter_k;
+}
+
 static void rtw8822c_phy_set_param(struct rtw_dev *rtwdev)
 {
 	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
@@ -1047,6 +1068,9 @@
 	dm_info->cck_gi_l_bnd = ((cck_gi_l_bnd_msb << 4) | (cck_gi_l_bnd_lsb));
 
 	rtw8822c_rf_init(rtwdev);
+	rtw8822c_pwrtrack_init(rtwdev);
+
+	rtw_bf_phy_init(rtwdev);
 }
 
 #define WLAN_TXQ_RPT_EN		0x1F
@@ -1088,8 +1112,8 @@
 #define WLAN_AMPDU_MAX_TIME		0x70
 #define WLAN_RTS_LEN_TH			0xFF
 #define WLAN_RTS_TX_TIME_TH		0x08
-#define WLAN_MAX_AGG_PKT_LIMIT		0x20
-#define WLAN_RTS_MAX_AGG_PKT_LIMIT	0x20
+#define WLAN_MAX_AGG_PKT_LIMIT		0x3f
+#define WLAN_RTS_MAX_AGG_PKT_LIMIT	0x3f
 #define WLAN_PRE_TXCNT_TIME_TH		0x1E0
 #define FAST_EDCA_VO_TH		0x06
 #define FAST_EDCA_VI_TH		0x06
@@ -1112,6 +1136,7 @@
 #define WLAN_RTS_RATE_FB_RATE4_H	0x400003E0
 #define WLAN_RTS_RATE_FB_RATE5		0x0600F015
 #define WLAN_RTS_RATE_FB_RATE5_H	0x000000E0
+#define WLAN_MULTI_ADDR			0xFFFFFFFF
 
 #define WLAN_TX_FUNC_CFG1		0x30
 #define WLAN_TX_FUNC_CFG2		0x30
@@ -1221,6 +1246,8 @@
 	rtw_write8(rtwdev, REG_BCN_MAX_ERR, WLAN_BCN_MAX_ERR);
 
 	/* WMAC configuration */
+	rtw_write32(rtwdev, REG_MAR, WLAN_MULTI_ADDR);
+	rtw_write32(rtwdev, REG_MAR + 4, WLAN_MULTI_ADDR);
 	rtw_write8(rtwdev, REG_BBPSF_CTRL + 2, WLAN_RESP_TXRATE);
 	rtw_write8(rtwdev, REG_ACKTO, WLAN_ACK_TO);
 	rtw_write8(rtwdev, REG_ACKTO_CCK, WLAN_ACK_TO_CCK);
@@ -1262,6 +1289,17 @@
 	return 0;
 }
 
+static void rtw8822c_rstb_3wire(struct rtw_dev *rtwdev, bool enable)
+{
+	if (enable) {
+		rtw_write32_mask(rtwdev, REG_RSTB, BIT_RSTB_3WIRE, 0x1);
+		rtw_write32_mask(rtwdev, REG_ANAPAR_A, BIT_ANAPAR_UPDATE, 0x1);
+		rtw_write32_mask(rtwdev, REG_ANAPAR_B, BIT_ANAPAR_UPDATE, 0x1);
+	} else {
+		rtw_write32_mask(rtwdev, REG_RSTB, BIT_RSTB_3WIRE, 0x0);
+	}
+}
+
 static void rtw8822c_set_channel_rf(struct rtw_dev *rtwdev, u8 channel, u8 bw)
 {
 #define RF18_BAND_MASK		(BIT(16) | BIT(9) | BIT(8))
@@ -1284,11 +1322,11 @@
 	rf_reg18 &= ~(RF18_BAND_MASK | RF18_CHANNEL_MASK | RF18_RFSI_MASK |
 		      RF18_BW_MASK);
 
-	rf_reg18 |= (channel <= 14 ? RF18_BAND_2G : RF18_BAND_5G);
+	rf_reg18 |= (IS_CH_2G_BAND(channel) ? RF18_BAND_2G : RF18_BAND_5G);
 	rf_reg18 |= (channel & RF18_CHANNEL_MASK);
-	if (channel > 144)
+	if (IS_CH_5G_BAND_4(channel))
 		rf_reg18 |= RF18_RFSI_GT_CH140;
-	else if (channel >= 80)
+	else if (IS_CH_5G_BAND_3(channel))
 		rf_reg18 |= RF18_RFSI_GE_CH80;
 
 	switch (bw) {
@@ -1310,6 +1348,8 @@
 		break;
 	}
 
+	rtw8822c_rstb_3wire(rtwdev, false);
+
 	rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE2, 0x04, 0x01);
 	rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, 0x1f, 0x12);
 	rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, 0xfffff, rf_rxbb);
@@ -1322,6 +1362,8 @@
 
 	rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK, rf_reg18);
 	rtw_write_rf(rtwdev, RF_PATH_B, RF_CFGCH, RFREG_MASK, rf_reg18);
+
+	rtw8822c_rstb_3wire(rtwdev, true);
 }
 
 static void rtw8822c_toggle_igi(struct rtw_dev *rtwdev)
@@ -1338,7 +1380,7 @@
 static void rtw8822c_set_channel_bb(struct rtw_dev *rtwdev, u8 channel, u8 bw,
 				    u8 primary_ch_idx)
 {
-	if (channel <= 14) {
+	if (IS_CH_2G_BAND(channel)) {
 		rtw_write32_clr(rtwdev, REG_BGCTRL, BITS_RX_IQ_WEIGHT);
 		rtw_write32_mask(rtwdev, REG_RXCCKSEL, 0xf0000000, 0x8);
 		rtw_write32_set(rtwdev, REG_TXF4, BIT(20));
@@ -1403,7 +1445,7 @@
 			rtw_write32_mask(rtwdev, REG_TXDFIR0, 0x70, 0x3);
 		else
 			rtw_write32_mask(rtwdev, REG_TXDFIR0, 0x70, 0x1);
-	} else if (channel > 35) {
+	} else if (IS_CH_5G_BAND(channel)) {
 		rtw_write32_set(rtwdev, REG_CCKTXONLY, BIT_BB_CCK_CHECK_EN);
 		rtw_write32_set(rtwdev, REG_CCK_CHECK, BIT_CHECK_CCK_EN);
 		rtw_write32_set(rtwdev, REG_BGCTRL, BITS_RX_IQ_WEIGHT);
@@ -1411,17 +1453,17 @@
 		rtw_write32_mask(rtwdev, REG_RXCCKSEL, 0xf0000000, 0x0);
 		rtw_write32_mask(rtwdev, REG_CCAMSK, 0x3F000000, 0x22);
 		rtw_write32_mask(rtwdev, REG_TXDFIR0, 0x70, 0x3);
-		if (channel >= 36 && channel <= 64) {
+		if (IS_CH_5G_BAND_1(channel) || IS_CH_5G_BAND_2(channel)) {
 			rtw_write32_mask(rtwdev, REG_RXAGCCTL0, BITS_RXAGC_OFDM,
 					 0x1);
 			rtw_write32_mask(rtwdev, REG_RXAGCCTL, BITS_RXAGC_OFDM,
 					 0x1);
-		} else if (channel >= 100 && channel <= 144) {
+		} else if (IS_CH_5G_BAND_3(channel)) {
 			rtw_write32_mask(rtwdev, REG_RXAGCCTL0, BITS_RXAGC_OFDM,
 					 0x2);
 			rtw_write32_mask(rtwdev, REG_RXAGCCTL, BITS_RXAGC_OFDM,
 					 0x2);
-		} else if (channel >= 149) {
+		} else if (IS_CH_5G_BAND_4(channel)) {
 			rtw_write32_mask(rtwdev, REG_RXAGCCTL0, BITS_RXAGC_OFDM,
 					 0x3);
 			rtw_write32_mask(rtwdev, REG_RXAGCCTL, BITS_RXAGC_OFDM,
@@ -1455,7 +1497,7 @@
 		break;
 	case RTW_CHANNEL_WIDTH_40:
 		rtw_write32_mask(rtwdev, REG_CCKSB, BIT(4),
-				 (primary_ch_idx == 1 ? 1 : 0));
+				 (primary_ch_idx == RTW_SC_20_UPPER ? 1 : 0));
 		rtw_write32_mask(rtwdev, REG_TXBWCTL, 0xf, 0x5);
 		rtw_write32_mask(rtwdev, REG_TXBWCTL, 0xc0, 0x0);
 		rtw_write32_mask(rtwdev, REG_TXBWCTL, 0xff00,
@@ -1616,6 +1658,8 @@
 	u8 gain_a, gain_b;
 	s8 rx_power[RTW_RF_PATH_MAX];
 	s8 min_rx_power = -120;
+	u8 rssi;
+	int path;
 
 	rx_power[RF_PATH_A] = GET_PHY_STAT_P0_PWDB_A(phy_status);
 	rx_power[RF_PATH_B] = GET_PHY_STAT_P0_PWDB_B(phy_status);
@@ -1638,6 +1682,11 @@
 	pkt_stat->rx_power[RF_PATH_A] = rx_power[RF_PATH_A];
 	pkt_stat->rx_power[RF_PATH_B] = rx_power[RF_PATH_B];
 
+	for (path = 0; path <= rtwdev->hal.rf_path_num; path++) {
+		rssi = rtw_phy_rf_power_2_rssi(&pkt_stat->rx_power[path], 1);
+		dm_info->rssi[path] = rssi;
+	}
+
 	pkt_stat->rssi = rtw_phy_rf_power_2_rssi(pkt_stat->rx_power, 1);
 	pkt_stat->bw = RTW_CHANNEL_WIDTH_20;
 	pkt_stat->signal_power = max(pkt_stat->rx_power[RF_PATH_A],
@@ -1647,20 +1696,27 @@
 static void query_phy_status_page1(struct rtw_dev *rtwdev, u8 *phy_status,
 				   struct rtw_rx_pkt_stat *pkt_stat)
 {
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
 	u8 rxsc, bw;
 	s8 min_rx_power = -120;
+	s8 rx_evm;
+	u8 evm_dbm = 0;
+	u8 rssi;
+	int path;
 
 	if (pkt_stat->rate > DESC_RATE11M && pkt_stat->rate < DESC_RATEMCS0)
 		rxsc = GET_PHY_STAT_P1_L_RXSC(phy_status);
 	else
 		rxsc = GET_PHY_STAT_P1_HT_RXSC(phy_status);
 
-	if (rxsc >= 9 && rxsc <= 12)
+	if (rxsc == 0)
+		bw = rtwdev->hal.current_band_width;
+	else if (rxsc >= 1 && rxsc <= 8)
+		bw = RTW_CHANNEL_WIDTH_20;
+	else if (rxsc >= 9 && rxsc <= 12)
 		bw = RTW_CHANNEL_WIDTH_40;
-	else if (rxsc >= 13)
-		bw = RTW_CHANNEL_WIDTH_80;
 	else
-		bw = RTW_CHANNEL_WIDTH_20;
+		bw = RTW_CHANNEL_WIDTH_80;
 
 	pkt_stat->rx_power[RF_PATH_A] = GET_PHY_STAT_P1_PWDB_A(phy_status) - 110;
 	pkt_stat->rx_power[RF_PATH_B] = GET_PHY_STAT_P1_PWDB_B(phy_status) - 110;
@@ -1669,6 +1725,34 @@
 	pkt_stat->signal_power = max3(pkt_stat->rx_power[RF_PATH_A],
 				      pkt_stat->rx_power[RF_PATH_B],
 				      min_rx_power);
+
+	dm_info->curr_rx_rate = pkt_stat->rate;
+
+	pkt_stat->rx_evm[RF_PATH_A] = GET_PHY_STAT_P1_RXEVM_A(phy_status);
+	pkt_stat->rx_evm[RF_PATH_B] = GET_PHY_STAT_P1_RXEVM_B(phy_status);
+
+	pkt_stat->rx_snr[RF_PATH_A] = GET_PHY_STAT_P1_RXSNR_A(phy_status);
+	pkt_stat->rx_snr[RF_PATH_B] = GET_PHY_STAT_P1_RXSNR_B(phy_status);
+
+	pkt_stat->cfo_tail[RF_PATH_A] = GET_PHY_STAT_P1_CFO_TAIL_A(phy_status);
+	pkt_stat->cfo_tail[RF_PATH_B] = GET_PHY_STAT_P1_CFO_TAIL_B(phy_status);
+
+	for (path = 0; path <= rtwdev->hal.rf_path_num; path++) {
+		rssi = rtw_phy_rf_power_2_rssi(&pkt_stat->rx_power[path], 1);
+		dm_info->rssi[path] = rssi;
+		dm_info->rx_snr[path] = pkt_stat->rx_snr[path] >> 1;
+		dm_info->cfo_tail[path] = (pkt_stat->cfo_tail[path] * 5) >> 1;
+
+		rx_evm = pkt_stat->rx_evm[path];
+
+		if (rx_evm < 0) {
+			if (rx_evm == S8_MIN)
+				evm_dbm = 0;
+			else
+				evm_dbm = ((u8)-rx_evm >> 1);
+		}
+		dm_info->rx_evm_dbm[path] = evm_dbm;
+	}
 }
 
 static void query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status,
@@ -1704,7 +1788,8 @@
 	pkt_stat->phy_status = GET_RX_DESC_PHYST(rx_desc);
 	pkt_stat->icv_err = GET_RX_DESC_ICV_ERR(rx_desc);
 	pkt_stat->crc_err = GET_RX_DESC_CRC32(rx_desc);
-	pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc);
+	pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc) &&
+			      GET_RX_DESC_ENC_TYPE(rx_desc) != RX_DESC_ENC_NONE;
 	pkt_stat->is_c2h = GET_RX_DESC_C2H(rx_desc);
 	pkt_stat->pkt_len = GET_RX_DESC_PKT_LEN(rx_desc);
 	pkt_stat->drv_info_sz = GET_RX_DESC_DRV_INFO_SIZE(rx_desc);
@@ -1822,6 +1907,7 @@
 	u32 cck_enable;
 	u32 cck_fa_cnt;
 	u32 crc32_cnt;
+	u32 cca32_cnt;
 	u32 ofdm_fa_cnt;
 	u32 ofdm_fa_cnt1, ofdm_fa_cnt2, ofdm_fa_cnt3, ofdm_fa_cnt4, ofdm_fa_cnt5;
 	u16 parity_fail, rate_illegal, crc8_fail, mcs_fail, sb_search_fail,
@@ -1866,6 +1952,13 @@
 	dm_info->vht_ok_cnt = crc32_cnt & 0xffff;
 	dm_info->vht_err_cnt = (crc32_cnt & 0xffff0000) >> 16;
 
+	cca32_cnt = rtw_read32(rtwdev, 0x2c08);
+	dm_info->ofdm_cca_cnt = ((cca32_cnt & 0xffff0000) >> 16);
+	dm_info->cck_cca_cnt = cca32_cnt & 0xffff;
+	dm_info->total_cca_cnt = dm_info->ofdm_cca_cnt;
+	if (cck_enable)
+		dm_info->total_cca_cnt += dm_info->cck_cca_cnt;
+
 	rtw_write32_mask(rtwdev, REG_CCANRX, BIT_CCK_FA_RST, 0);
 	rtw_write32_mask(rtwdev, REG_CCANRX, BIT_CCK_FA_RST, 2);
 	rtw_write32_mask(rtwdev, REG_CCANRX, BIT_OFDM_FA_RST, 0);
@@ -2053,6 +2146,57 @@
 	}
 }
 
+static void rtw8822c_bf_enable_bfee_su(struct rtw_dev *rtwdev,
+				       struct rtw_vif *vif,
+				       struct rtw_bfee *bfee)
+{
+	u8 csi_rsc = 0;
+	u32 tmp6dc;
+
+	rtw_bf_enable_bfee_su(rtwdev, vif, bfee);
+
+	tmp6dc = rtw_read32(rtwdev, REG_BBPSF_CTRL) |
+			    BIT_WMAC_USE_NDPARATE |
+			    (csi_rsc << 13);
+	if (vif->net_type == RTW_NET_AP_MODE)
+		rtw_write32(rtwdev, REG_BBPSF_CTRL, tmp6dc | BIT(12));
+	else
+		rtw_write32(rtwdev, REG_BBPSF_CTRL, tmp6dc & ~BIT(12));
+
+	rtw_write32(rtwdev, REG_CSI_RRSR, 0x550);
+}
+
+static void rtw8822c_bf_config_bfee_su(struct rtw_dev *rtwdev,
+				       struct rtw_vif *vif,
+				       struct rtw_bfee *bfee, bool enable)
+{
+	if (enable)
+		rtw8822c_bf_enable_bfee_su(rtwdev, vif, bfee);
+	else
+		rtw_bf_remove_bfee_su(rtwdev, bfee);
+}
+
+static void rtw8822c_bf_config_bfee_mu(struct rtw_dev *rtwdev,
+				       struct rtw_vif *vif,
+				       struct rtw_bfee *bfee, bool enable)
+{
+	if (enable)
+		rtw_bf_enable_bfee_mu(rtwdev, vif, bfee);
+	else
+		rtw_bf_remove_bfee_mu(rtwdev, bfee);
+}
+
+static void rtw8822c_bf_config_bfee(struct rtw_dev *rtwdev, struct rtw_vif *vif,
+				    struct rtw_bfee *bfee, bool enable)
+{
+	if (bfee->role == RTW_BFEE_SU)
+		rtw8822c_bf_config_bfee_su(rtwdev, vif, bfee, enable);
+	else if (bfee->role == RTW_BFEE_MU)
+		rtw8822c_bf_config_bfee_mu(rtwdev, vif, bfee, enable);
+	else
+		rtw_warn(rtwdev, "wrong bfee role\n");
+}
+
 struct dpk_cfg_pair {
 	u32 addr;
 	u32 bitmask;
@@ -2603,9 +2747,9 @@
 {
 	if (coef_i == 0x1000 || coef_i == 0x0fff ||
 	    coef_q == 0x1000 || coef_q == 0x0fff)
-		return 1;
-	else
-		return 0;
+		return true;
+
+	return false;
 }
 
 static u32 rtw8822c_dpk_coef_transfer(struct rtw_dev *rtwdev)
@@ -2843,7 +2987,7 @@
 	dpk_info->dpk_gs[path] = tmp_gs;
 }
 
-void rtw8822c_dpk_cal_coef1(struct rtw_dev *rtwdev)
+static void rtw8822c_dpk_cal_coef1(struct rtw_dev *rtwdev)
 {
 	struct rtw_dpk_info *dpk_info = &rtwdev->dm_info.dpk_info;
 	u32 offset[DPK_RF_PATH_NUM] = {0, 0x58};
@@ -3084,7 +3228,7 @@
 	rtw8822c_do_dpk(rtwdev);
 }
 
-void rtw8822c_dpk_track(struct rtw_dev *rtwdev)
+static void rtw8822c_dpk_track(struct rtw_dev *rtwdev)
 {
 	struct rtw_dpk_info *dpk_info = &rtwdev->dm_info.dpk_info;
 	u8 path;
@@ -3168,8 +3312,8 @@
 static void rtw8822c_phy_cck_pd_set(struct rtw_dev *rtwdev, u8 new_lvl)
 {
 	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
-	s8 pd_lvl[4] = {2, 4, 6, 8};
-	s8 cs_lvl[4] = {2, 2, 2, 4};
+	s8 pd_lvl[CCK_PD_LV_MAX] = {0, 2, 4, 6, 8};
+	s8 cs_lvl[CCK_PD_LV_MAX] = {0, 2, 2, 2, 4};
 	u8 cur_lvl;
 	u8 nrx, bw;
 
@@ -3191,6 +3335,118 @@
 	dm_info->cck_pd_lv[bw][nrx] = new_lvl;
 }
 
+#define PWR_TRACK_MASK 0x7f
+static void rtw8822c_pwrtrack_set(struct rtw_dev *rtwdev, u8 rf_path)
+{
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+
+	switch (rf_path) {
+	case RF_PATH_A:
+		rtw_write32_mask(rtwdev, 0x18a0, PWR_TRACK_MASK,
+				 dm_info->delta_power_index[rf_path]);
+		break;
+	case RF_PATH_B:
+		rtw_write32_mask(rtwdev, 0x41a0, PWR_TRACK_MASK,
+				 dm_info->delta_power_index[rf_path]);
+		break;
+	default:
+		break;
+	}
+}
+
+static void rtw8822c_pwr_track_path(struct rtw_dev *rtwdev,
+				    struct rtw_swing_table *swing_table,
+				    u8 path)
+{
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+	u8 thermal_value, delta;
+
+	if (rtwdev->efuse.thermal_meter[path] == 0xff)
+		return;
+
+	thermal_value = rtw_read_rf(rtwdev, path, RF_T_METER, 0x7e);
+
+	rtw_phy_pwrtrack_avg(rtwdev, thermal_value, path);
+
+	delta = rtw_phy_pwrtrack_get_delta(rtwdev, path);
+
+	dm_info->delta_power_index[path] =
+		rtw_phy_pwrtrack_get_pwridx(rtwdev, swing_table, path, path,
+					    delta);
+
+	rtw8822c_pwrtrack_set(rtwdev, path);
+}
+
+static void __rtw8822c_pwr_track(struct rtw_dev *rtwdev)
+{
+	struct rtw_swing_table swing_table;
+	u8 i;
+
+	rtw_phy_config_swing_table(rtwdev, &swing_table);
+
+	for (i = 0; i < rtwdev->hal.rf_path_num; i++)
+		rtw8822c_pwr_track_path(rtwdev, &swing_table, i);
+
+	if (rtw_phy_pwrtrack_need_iqk(rtwdev))
+		rtw8822c_do_iqk(rtwdev);
+}
+
+static void rtw8822c_pwr_track(struct rtw_dev *rtwdev)
+{
+	struct rtw_efuse *efuse = &rtwdev->efuse;
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+
+	if (efuse->power_track_type != 0)
+		return;
+
+	if (!dm_info->pwr_trk_triggered) {
+		rtw_write_rf(rtwdev, RF_PATH_A, RF_T_METER, BIT(19), 0x01);
+		rtw_write_rf(rtwdev, RF_PATH_A, RF_T_METER, BIT(19), 0x00);
+		rtw_write_rf(rtwdev, RF_PATH_A, RF_T_METER, BIT(19), 0x01);
+
+		rtw_write_rf(rtwdev, RF_PATH_B, RF_T_METER, BIT(19), 0x01);
+		rtw_write_rf(rtwdev, RF_PATH_B, RF_T_METER, BIT(19), 0x00);
+		rtw_write_rf(rtwdev, RF_PATH_B, RF_T_METER, BIT(19), 0x01);
+
+		dm_info->pwr_trk_triggered = true;
+		return;
+	}
+
+	__rtw8822c_pwr_track(rtwdev);
+	dm_info->pwr_trk_triggered = false;
+}
+
+static void rtw8822c_adaptivity_init(struct rtw_dev *rtwdev)
+{
+	rtw_phy_set_edcca_th(rtwdev, 0x7f, 0x7f);
+	/* mac edcca state setting */
+	rtw_write32_mask(rtwdev, REG_TX_PTCL_CTRL, BIT_DIS_EDCCA, 0);
+	rtw_write32_mask(rtwdev, REG_RD_CTRL, BIT_EDCCA_MSK_CNTDOWN_EN, 1);
+	/* edcca decistion opt */
+	rtw_write32_mask(rtwdev, REG_EDCCA_DECISION, BIT_EDCCA_OPTION, 0);
+}
+
+static void rtw8822c_adaptivity(struct rtw_dev *rtwdev)
+{
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+	s8 l2h, h2l;
+	u8 igi;
+
+	igi = dm_info->igi_history[0];
+	if (dm_info->edcca_mode == RTW_EDCCA_NORMAL) {
+		l2h = max_t(s8, igi + EDCCA_IGI_L2H_DIFF, EDCCA_TH_L2H_LB);
+		h2l = l2h - EDCCA_L2H_H2L_DIFF_NORMAL;
+	} else {
+		if (igi < dm_info->l2h_th_ini - EDCCA_ADC_BACKOFF)
+			l2h = igi + EDCCA_ADC_BACKOFF;
+		else
+			l2h = dm_info->l2h_th_ini;
+		h2l = l2h - EDCCA_L2H_H2L_DIFF;
+	}
+
+	rtw_phy_set_edcca_th(rtwdev, l2h, h2l);
+}
+
 static struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8822c[] = {
 	{0x0086,
 	 RTW_PWR_CUT_ALL_MSK,
@@ -3279,12 +3535,12 @@
 	 RTW_PWR_CUT_ALL_MSK,
 	 RTW_PWR_INTF_ALL_MSK,
 	 RTW_PWR_ADDR_MAC,
-	 RTW_PWR_CMD_WRITE, BIT(7), 0},
-	{0x0005,
+	 RTW_PWR_CMD_WRITE, (BIT(4) | BIT(3)), 0},
+	{0x1018,
 	 RTW_PWR_CUT_ALL_MSK,
 	 RTW_PWR_INTF_ALL_MSK,
 	 RTW_PWR_ADDR_MAC,
-	 RTW_PWR_CMD_WRITE, (BIT(4) | BIT(3)), 0},
+	 RTW_PWR_CMD_WRITE, BIT(2), BIT(2)},
 	{0x0005,
 	 RTW_PWR_CUT_ALL_MSK,
 	 RTW_PWR_INTF_ALL_MSK,
@@ -3336,6 +3592,11 @@
 	 RTW_PWR_INTF_ALL_MSK,
 	 RTW_PWR_ADDR_MAC,
 	 RTW_PWR_CMD_WRITE, BIT(2), BIT(2)},
+	{0x1064,
+	 RTW_PWR_CUT_ALL_MSK,
+	 RTW_PWR_INTF_ALL_MSK,
+	 RTW_PWR_ADDR_MAC,
+	 RTW_PWR_CMD_WRITE, BIT(1), BIT(1)},
 	{0xFFFF,
 	 RTW_PWR_CUT_ALL_MSK,
 	 RTW_PWR_INTF_ALL_MSK,
@@ -3531,6 +3792,12 @@
 	[1] = { .addr = 0x1d70, .mask = 0x7f00 },
 };
 
+static struct rtw_ltecoex_addr rtw8822c_ltecoex_addr = {
+	.ctrl = LTECOEX_ACCESS_CTRL,
+	.wdata = LTECOEX_WRITE_DATA,
+	.rdata = LTECOEX_READ_DATA,
+};
+
 static struct rtw_page_table page_table_8822c[] = {
 	{64, 64, 64, 64, 1},
 	{64, 64, 64, 64, 1},
@@ -3557,6 +3824,22 @@
 	 RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH},
 };
 
+static struct rtw_prioq_addrs prioq_addrs_8822c = {
+	.prio[RTW_DMA_MAPPING_EXTRA] = {
+		.rsvd = REG_FIFOPAGE_INFO_4, .avail = REG_FIFOPAGE_INFO_4 + 2,
+	},
+	.prio[RTW_DMA_MAPPING_LOW] = {
+		.rsvd = REG_FIFOPAGE_INFO_2, .avail = REG_FIFOPAGE_INFO_2 + 2,
+	},
+	.prio[RTW_DMA_MAPPING_NORMAL] = {
+		.rsvd = REG_FIFOPAGE_INFO_3, .avail = REG_FIFOPAGE_INFO_3 + 2,
+	},
+	.prio[RTW_DMA_MAPPING_HIGH] = {
+		.rsvd = REG_FIFOPAGE_INFO_1, .avail = REG_FIFOPAGE_INFO_1 + 2,
+	},
+	.wsize = true,
+};
+
 static struct rtw_chip_ops rtw8822c_ops = {
 	.phy_set_param		= rtw8822c_phy_set_param,
 	.read_efuse		= rtw8822c_read_efuse,
@@ -3571,6 +3854,12 @@
 	.dpk_track		= rtw8822c_dpk_track,
 	.phy_calibration	= rtw8822c_phy_calibration,
 	.cck_pd_set		= rtw8822c_phy_cck_pd_set,
+	.pwr_track		= rtw8822c_pwr_track,
+	.config_bfee		= rtw8822c_bf_config_bfee,
+	.set_gid_table		= rtw_bf_set_gid_table,
+	.cfg_csi_rate		= rtw_bf_cfg_csi_rate,
+	.adaptivity_init	= rtw8822c_adaptivity_init,
+	.adaptivity		= rtw8822c_adaptivity,
 
 	.coex_set_init		= rtw8822c_coex_cfg_init,
 	.coex_set_ant_switch	= NULL,
@@ -3725,10 +4014,180 @@
 
 static_assert(ARRAY_SIZE(rf_para_tx_8822c) == ARRAY_SIZE(rf_para_rx_8822c));
 
+static const u8
+rtw8822c_pwrtrk_5gb_n[RTW_PWR_TRK_5G_NUM][RTW_PWR_TRK_TBL_SZ] = {
+	{ 0,  1,  2,  3,  5,  6,  7,  8,  9, 10,
+	 11, 12, 13, 14, 15, 16, 18, 19, 20, 21,
+	 22, 23, 24, 25, 26, 27, 28, 29, 30, 32 },
+	{ 0,  1,  2,  3,  5,  6,  7,  8,  9, 10,
+	 11, 12, 13, 14, 15, 16, 18, 19, 20, 21,
+	 22, 23, 24, 25, 26, 27, 28, 29, 30, 32 },
+	{ 0,  1,  2,  3,  5,  6,  7,  8,  9, 10,
+	 11, 12, 13, 14, 15, 16, 18, 19, 20, 21,
+	 22, 23, 24, 25, 26, 27, 28, 29, 30, 32 },
+};
+
+static const u8
+rtw8822c_pwrtrk_5gb_p[RTW_PWR_TRK_5G_NUM][RTW_PWR_TRK_TBL_SZ] = {
+	{ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
+	 10, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+	 19, 20, 21, 22, 22, 23, 24, 25, 26, 27 },
+	{ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
+	 10, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+	 19, 20, 21, 22, 22, 23, 24, 25, 26, 27 },
+	{ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
+	 10, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+	 19, 20, 21, 22, 22, 23, 24, 25, 26, 27 },
+};
+
+static const u8
+rtw8822c_pwrtrk_5ga_n[RTW_PWR_TRK_5G_NUM][RTW_PWR_TRK_TBL_SZ] = {
+	{ 0,  1,  2,  4,  5,  6,  7,  8,  9, 10,
+	 11, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+	 23, 24, 25, 26, 27, 28, 29, 30, 31, 33 },
+	{ 0,  1,  2,  4,  5,  6,  7,  8,  9, 10,
+	 11, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+	 23, 24, 25, 26, 27, 28, 29, 30, 31, 33 },
+	{ 0,  1,  2,  4,  5,  6,  7,  8,  9, 10,
+	 11, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+	 23, 24, 25, 26, 27, 28, 29, 30, 31, 33 },
+};
+
+static const u8
+rtw8822c_pwrtrk_5ga_p[RTW_PWR_TRK_5G_NUM][RTW_PWR_TRK_TBL_SZ] = {
+	{ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
+	 10, 11, 12, 13, 14, 15, 16, 17, 18, 20,
+	 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 },
+	{ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
+	 10, 11, 12, 13, 14, 15, 16, 17, 18, 20,
+	 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 },
+	{ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
+	 10, 11, 12, 13, 14, 15, 16, 17, 18, 20,
+	 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 },
+};
+
+static const u8 rtw8822c_pwrtrk_2gb_n[RTW_PWR_TRK_TBL_SZ] = {
+	 0,  1,  2,  3,  4,  4,  5,  6,  7,  8,
+	 9,  9, 10, 11, 12, 13, 14, 15, 15, 16,
+	17, 18, 19, 20, 20, 21, 22, 23, 24, 25
+};
+
+static const u8 rtw8822c_pwrtrk_2gb_p[RTW_PWR_TRK_TBL_SZ] = {
+	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
+	10, 11, 12, 13, 14, 14, 15, 16, 17, 18,
+	19, 20, 21, 22, 23, 24, 25, 26, 27, 28
+};
+
+static const u8 rtw8822c_pwrtrk_2ga_n[RTW_PWR_TRK_TBL_SZ] = {
+	 0,  1,  2,  2,  3,  4,  4,  5,  6,  6,
+	 7,  8,  8,  9,  9, 10, 11, 11, 12, 13,
+	13, 14, 15, 15, 16, 17, 17, 18, 19, 19
+};
+
+static const u8 rtw8822c_pwrtrk_2ga_p[RTW_PWR_TRK_TBL_SZ] = {
+	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
+	10, 11, 11, 12, 13, 14, 15, 16, 17, 18,
+	19, 20, 21, 22, 23, 24, 25, 25, 26, 27
+};
+
+static const u8 rtw8822c_pwrtrk_2g_cck_b_n[RTW_PWR_TRK_TBL_SZ] = {
+	 0,  1,  2,  3,  4,  5,  5,  6,  7,  8,
+	 9, 10, 11, 11, 12, 13, 14, 15, 16, 17,
+	17, 18, 19, 20, 21, 22, 23, 23, 24, 25
+};
+
+static const u8 rtw8822c_pwrtrk_2g_cck_b_p[RTW_PWR_TRK_TBL_SZ] = {
+	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
+	10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+	20, 21, 22, 23, 24, 25, 26, 27, 28, 29
+};
+
+static const u8 rtw8822c_pwrtrk_2g_cck_a_n[RTW_PWR_TRK_TBL_SZ] = {
+	 0,  1,  2,  3,  3,  4,  5,  6,  6,  7,
+	 8,  9,  9, 10, 11, 12, 12, 13, 14, 15,
+	15, 16, 17, 18, 18, 19, 20, 21, 21, 22
+};
+
+static const u8 rtw8822c_pwrtrk_2g_cck_a_p[RTW_PWR_TRK_TBL_SZ] = {
+	 0,  1,  2,  3,  4,  5,  5,  6,  7,  8,
+	 9, 10, 11, 11, 12, 13, 14, 15, 16, 17,
+	18, 18, 19, 20, 21, 22, 23, 24, 24, 25
+};
+
+static const struct rtw_pwr_track_tbl rtw8822c_rtw_pwr_track_tbl = {
+	.pwrtrk_5gb_n[RTW_PWR_TRK_5G_1] = rtw8822c_pwrtrk_5gb_n[RTW_PWR_TRK_5G_1],
+	.pwrtrk_5gb_n[RTW_PWR_TRK_5G_2] = rtw8822c_pwrtrk_5gb_n[RTW_PWR_TRK_5G_2],
+	.pwrtrk_5gb_n[RTW_PWR_TRK_5G_3] = rtw8822c_pwrtrk_5gb_n[RTW_PWR_TRK_5G_3],
+	.pwrtrk_5gb_p[RTW_PWR_TRK_5G_1] = rtw8822c_pwrtrk_5gb_p[RTW_PWR_TRK_5G_1],
+	.pwrtrk_5gb_p[RTW_PWR_TRK_5G_2] = rtw8822c_pwrtrk_5gb_p[RTW_PWR_TRK_5G_2],
+	.pwrtrk_5gb_p[RTW_PWR_TRK_5G_3] = rtw8822c_pwrtrk_5gb_p[RTW_PWR_TRK_5G_3],
+	.pwrtrk_5ga_n[RTW_PWR_TRK_5G_1] = rtw8822c_pwrtrk_5ga_n[RTW_PWR_TRK_5G_1],
+	.pwrtrk_5ga_n[RTW_PWR_TRK_5G_2] = rtw8822c_pwrtrk_5ga_n[RTW_PWR_TRK_5G_2],
+	.pwrtrk_5ga_n[RTW_PWR_TRK_5G_3] = rtw8822c_pwrtrk_5ga_n[RTW_PWR_TRK_5G_3],
+	.pwrtrk_5ga_p[RTW_PWR_TRK_5G_1] = rtw8822c_pwrtrk_5ga_p[RTW_PWR_TRK_5G_1],
+	.pwrtrk_5ga_p[RTW_PWR_TRK_5G_2] = rtw8822c_pwrtrk_5ga_p[RTW_PWR_TRK_5G_2],
+	.pwrtrk_5ga_p[RTW_PWR_TRK_5G_3] = rtw8822c_pwrtrk_5ga_p[RTW_PWR_TRK_5G_3],
+	.pwrtrk_2gb_n = rtw8822c_pwrtrk_2gb_n,
+	.pwrtrk_2gb_p = rtw8822c_pwrtrk_2gb_p,
+	.pwrtrk_2ga_n = rtw8822c_pwrtrk_2ga_n,
+	.pwrtrk_2ga_p = rtw8822c_pwrtrk_2ga_p,
+	.pwrtrk_2g_cckb_n = rtw8822c_pwrtrk_2g_cck_b_n,
+	.pwrtrk_2g_cckb_p = rtw8822c_pwrtrk_2g_cck_b_p,
+	.pwrtrk_2g_ccka_n = rtw8822c_pwrtrk_2g_cck_a_n,
+	.pwrtrk_2g_ccka_p = rtw8822c_pwrtrk_2g_cck_a_p,
+};
+
+static struct rtw_hw_reg_offset rtw8822c_edcca_th[] = {
+	[EDCCA_TH_L2H_IDX] = {
+		{.addr = 0x84c, .mask = MASKBYTE2}, .offset = 0x80
+	},
+	[EDCCA_TH_H2L_IDX] = {
+		{.addr = 0x84c, .mask = MASKBYTE3}, .offset = 0x80
+	},
+};
+
+#ifdef CONFIG_PM
+static const struct wiphy_wowlan_support rtw_wowlan_stub_8822c = {
+	.flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_GTK_REKEY_FAILURE |
+		 WIPHY_WOWLAN_DISCONNECT | WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
+		 WIPHY_WOWLAN_NET_DETECT,
+	.n_patterns = RTW_MAX_PATTERN_NUM,
+	.pattern_max_len = RTW_MAX_PATTERN_SIZE,
+	.pattern_min_len = 1,
+	.max_nd_match_sets = 4,
+};
+#endif
+
+static const struct rtw_reg_domain coex_info_hw_regs_8822c[] = {
+	{0x1860, BIT(3), RTW_REG_DOMAIN_MAC8},
+	{0x4160, BIT(3), RTW_REG_DOMAIN_MAC8},
+	{0x1c32, BIT(6), RTW_REG_DOMAIN_MAC8},
+	{0x1c38, BIT(28), RTW_REG_DOMAIN_MAC32},
+	{0, 0, RTW_REG_DOMAIN_NL},
+	{0x430, MASKDWORD, RTW_REG_DOMAIN_MAC32},
+	{0x434, MASKDWORD, RTW_REG_DOMAIN_MAC32},
+	{0x42a, MASKLWORD, RTW_REG_DOMAIN_MAC16},
+	{0x426, MASKBYTE0, RTW_REG_DOMAIN_MAC8},
+	{0x45e, BIT(3), RTW_REG_DOMAIN_MAC8},
+	{0x454, MASKLWORD, RTW_REG_DOMAIN_MAC16},
+	{0, 0, RTW_REG_DOMAIN_NL},
+	{0x4c, BIT(24) | BIT(23), RTW_REG_DOMAIN_MAC32},
+	{0x64, BIT(0), RTW_REG_DOMAIN_MAC8},
+	{0x4c6, BIT(4), RTW_REG_DOMAIN_MAC8},
+	{0x40, BIT(5), RTW_REG_DOMAIN_MAC8},
+	{0x1, RFREG_MASK, RTW_REG_DOMAIN_RF_B},
+	{0, 0, RTW_REG_DOMAIN_NL},
+	{0x550, MASKDWORD, RTW_REG_DOMAIN_MAC32},
+	{0x522, MASKBYTE0, RTW_REG_DOMAIN_MAC8},
+	{0x953, BIT(1), RTW_REG_DOMAIN_MAC8},
+	{0xc50, MASKBYTE0, RTW_REG_DOMAIN_MAC8},
+};
+
 struct rtw_chip_info rtw8822c_hw_spec = {
 	.ops = &rtw8822c_ops,
 	.id = RTW_CHIP_TYPE_8822C,
 	.fw_name = "rtw88/rtw8822c_fw.bin",
+	.wlan_cpu = RTW_WCPU_11AC,
 	.tx_pkt_desc_sz = 48,
 	.tx_buf_desc_sz = 16,
 	.rx_pkt_desc_sz = 24,
@@ -3747,15 +4206,19 @@
 	.dig_min = 0x20,
 	.ht_supported = true,
 	.vht_supported = true,
+	.lps_deep_mode_supported = BIT(LPS_DEEP_MODE_LCLK) | BIT(LPS_DEEP_MODE_PG),
 	.sys_func_en = 0xD8,
 	.pwr_on_seq = card_enable_flow_8822c,
 	.pwr_off_seq = card_disable_flow_8822c,
 	.page_table = page_table_8822c,
 	.rqpn_table = rqpn_table_8822c,
+	.prioq_addrs = &prioq_addrs_8822c,
 	.intf_table = &phy_para_table_8822c,
 	.dig = rtw8822c_dig,
+	.dig_cck = NULL,
 	.rf_base_addr = {0x3c00, 0x4c00},
 	.rf_sipi_addr = {0x1808, 0x4108},
+	.ltecoex_addr = &rtw8822c_ltecoex_addr,
 	.mac_tbl = &rtw8822c_mac_tbl,
 	.agc_tbl = &rtw8822c_agc_tbl,
 	.bb_tbl = &rtw8822c_bb_tbl,
@@ -3765,7 +4228,19 @@
 	.rfe_defs_size = ARRAY_SIZE(rtw8822c_rfe_defs),
 	.en_dis_dpd = true,
 	.dpd_ratemask = DIS_DPD_RATEALL,
-
+	.pwr_track_tbl = &rtw8822c_rtw_pwr_track_tbl,
+	.iqk_threshold = 8,
+	.bfer_su_max_num = 2,
+	.bfer_mu_max_num = 1,
+	.edcca_th = rtw8822c_edcca_th,
+	.l2h_th_ini_cs = 60,
+	.l2h_th_ini_ad = 45,
+
+#ifdef CONFIG_PM
+	.wow_fw_name = "rtw88/rtw8822c_wow_fw.bin",
+	.wowlan_stub = &rtw_wowlan_stub_8822c,
+	.max_sched_scan_ssids = 4,
+#endif
 	.coex_para_ver = 0x19062706,
 	.bt_desired_ver = 0x6,
 	.scbd_support = true,
@@ -3791,7 +4266,11 @@
 	.bt_afh_span_bw40 = 0x36,
 	.afh_5g_num = ARRAY_SIZE(afh_5g_8822c),
 	.afh_5g = afh_5g_8822c,
+
+	.coex_info_hw_regs_num = ARRAY_SIZE(coex_info_hw_regs_8822c),
+	.coex_info_hw_regs = coex_info_hw_regs_8822c,
 };
 EXPORT_SYMBOL(rtw8822c_hw_spec);
 
 MODULE_FIRMWARE("rtw88/rtw8822c_fw.bin");
+MODULE_FIRMWARE("rtw88/rtw8822c_wow_fw.bin");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/rtw8822c.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/rtw8822c.h
@@ -149,6 +149,18 @@
 	le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(11, 8))
 #define GET_PHY_STAT_P1_HT_RXSC(phy_stat)                                      \
 	le32_get_bits(*((__le32 *)(phy_stat) + 0x01), GENMASK(15, 12))
+#define GET_PHY_STAT_P1_RXEVM_A(phy_stat)                                      \
+	le32_get_bits(*((__le32 *)(phy_stat) + 0x04), GENMASK(7, 0))
+#define GET_PHY_STAT_P1_RXEVM_B(phy_stat)                                      \
+	le32_get_bits(*((__le32 *)(phy_stat) + 0x04), GENMASK(15, 8))
+#define GET_PHY_STAT_P1_CFO_TAIL_A(phy_stat)                                 \
+	le32_get_bits(*((__le32 *)(phy_stat) + 0x05), GENMASK(7, 0))
+#define GET_PHY_STAT_P1_CFO_TAIL_B(phy_stat)                                 \
+	le32_get_bits(*((__le32 *)(phy_stat) + 0x05), GENMASK(15, 8))
+#define GET_PHY_STAT_P1_RXSNR_A(phy_stat)                                      \
+	le32_get_bits(*((__le32 *)(phy_stat) + 0x06), GENMASK(7, 0))
+#define GET_PHY_STAT_P1_RXSNR_B(phy_stat)                                      \
+	le32_get_bits(*((__le32 *)(phy_stat) + 0x06), GENMASK(15, 8))
 
 #define REG_ANAPARLDO_POW_MAC	0x0029
 #define BIT_LDOE25_PON		BIT(0)
@@ -159,6 +171,8 @@
 #define REG_DFIRBW	0x810
 #define REG_ANTMAP0	0x820
 #define REG_ANTMAP	0x824
+#define REG_EDCCA_DECISION	0x844
+#define BIT_EDCCA_OPTION	GENMASK(30, 29)
 #define REG_DYMPRITH	0x86c
 #define REG_DYMENTH0	0x870
 #define REG_DYMENTH	0x874
@@ -178,6 +192,8 @@
 #define BIT_3WIRE_TX_EN		BIT(0)
 #define BIT_3WIRE_RX_EN		BIT(1)
 #define BIT_3WIRE_PI_ON		BIT(28)
+#define REG_ANAPAR_A	0x1830
+#define BIT_ANAPAR_UPDATE	BIT(29)
 #define REG_RXAGCCTL0	0x18ac
 #define BITS_RXAGC_CCK		GENMASK(15, 12)
 #define BITS_RXAGC_OFDM		GENMASK(8, 4)
@@ -211,6 +227,8 @@
 #define BIT_CCK_BLK_EN		BIT(1)
 #define BIT_CCK_OFDM_BLK_EN	(BIT(0) | BIT(1))
 #define REG_CCAMSK	0x1c80
+#define REG_RSTB	0x1c90
+#define BIT_RSTB_3WIRE		BIT(8)
 #define REG_RX_BREAK	0x1d2c
 #define BIT_COM_RX_GCK_EN	BIT(31)
 #define REG_RXFNCTL	0x1d30
@@ -231,6 +249,7 @@
 #define REG_OFDM_TXCNT	0x2de0
 #define REG_ORITXCODE2	0x4100
 #define REG_3WIRE2	0x410c
+#define REG_ANAPAR_B	0x4130
 #define REG_RXAGCCTL	0x41ac
 #define REG_DCKB_I_0	0x41bc
 #define REG_DCKB_I_1	0x41c0
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/rtw8822c_table.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/rtw8822c_table.c
@@ -1762,53 +1762,53 @@
 
 RTW_DECL_TABLE_PHY_COND(rtw8822c_bb, rtw_phy_cfg_bb);
 
-static const u32 rtw8822c_bb_pg_type0[] = {
-	0, 0, 0, 0x00000c20, 0xffffffff, 0x484c5054,
-	0, 0, 0, 0x00000c24, 0xffffffff, 0x54585c60,
-	0, 0, 0, 0x00000c28, 0xffffffff, 0x44484c50,
-	0, 0, 0, 0x00000c2c, 0xffffffff, 0x5054585c,
-	0, 0, 0, 0x00000c30, 0xffffffff, 0x4044484c,
-	0, 0, 1, 0x00000c34, 0xffffffff, 0x5054585c,
-	0, 0, 1, 0x00000c38, 0xffffffff, 0x4044484c,
-	0, 0, 0, 0x00000c3c, 0xffffffff, 0x5054585c,
-	0, 0, 0, 0x00000c40, 0xffffffff, 0x4044484c,
-	0, 0, 0, 0x00000c44, 0xffffffff, 0x585c383c,
-	0, 0, 1, 0x00000c48, 0xffffffff, 0x484c5054,
-	0, 0, 1, 0x00000c4c, 0xffffffff, 0x383c4044,
-	0, 1, 0, 0x00000e20, 0xffffffff, 0x484c5054,
-	0, 1, 0, 0x00000e24, 0xffffffff, 0x54585c60,
-	0, 1, 0, 0x00000e28, 0xffffffff, 0x44484c50,
-	0, 1, 0, 0x00000e2c, 0xffffffff, 0x5054585c,
-	0, 1, 0, 0x00000e30, 0xffffffff, 0x4044484c,
-	0, 1, 1, 0x00000e34, 0xffffffff, 0x5054585c,
-	0, 1, 1, 0x00000e38, 0xffffffff, 0x4044484c,
-	0, 1, 0, 0x00000e3c, 0xffffffff, 0x5054585c,
-	0, 1, 0, 0x00000e40, 0xffffffff, 0x4044484c,
-	0, 1, 0, 0x00000e44, 0xffffffff, 0x585c383c,
-	0, 1, 1, 0x00000e48, 0xffffffff, 0x484c5054,
-	0, 1, 1, 0x00000e4c, 0xffffffff, 0x383c4044,
-	1, 0, 0, 0x00000c24, 0xffffffff, 0x54585c60,
-	1, 0, 0, 0x00000c28, 0xffffffff, 0x44484c50,
-	1, 0, 0, 0x00000c2c, 0xffffffff, 0x5054585c,
-	1, 0, 0, 0x00000c30, 0xffffffff, 0x4044484c,
-	1, 0, 1, 0x00000c34, 0xffffffff, 0x5054585c,
-	1, 0, 1, 0x00000c38, 0xffffffff, 0x4044484c,
-	1, 0, 0, 0x00000c3c, 0xffffffff, 0x5054585c,
-	1, 0, 0, 0x00000c40, 0xffffffff, 0x4044484c,
-	1, 0, 0, 0x00000c44, 0xffffffff, 0x585c383c,
-	1, 0, 1, 0x00000c48, 0xffffffff, 0x484c5054,
-	1, 0, 1, 0x00000c4c, 0xffffffff, 0x383c4044,
-	1, 1, 0, 0x00000e24, 0xffffffff, 0x54585c60,
-	1, 1, 0, 0x00000e28, 0xffffffff, 0x44484c50,
-	1, 1, 0, 0x00000e2c, 0xffffffff, 0x5054585c,
-	1, 1, 0, 0x00000e30, 0xffffffff, 0x4044484c,
-	1, 1, 1, 0x00000e34, 0xffffffff, 0x5054585c,
-	1, 1, 1, 0x00000e38, 0xffffffff, 0x4044484c,
-	1, 1, 0, 0x00000e3c, 0xffffffff, 0x5054585c,
-	1, 1, 0, 0x00000e40, 0xffffffff, 0x4044484c,
-	1, 1, 0, 0x00000e44, 0xffffffff, 0x585c383c,
-	1, 1, 1, 0x00000e48, 0xffffffff, 0x484c5054,
-	1, 1, 1, 0x00000e4c, 0xffffffff, 0x383c4044
+static const struct rtw_phy_pg_cfg_pair rtw8822c_bb_pg_type0[] = {
+	{ 0, 0, 0, 0x00000c20, 0xffffffff, 0x484c5054, },
+	{ 0, 0, 0, 0x00000c24, 0xffffffff, 0x54585c60, },
+	{ 0, 0, 0, 0x00000c28, 0xffffffff, 0x44484c50, },
+	{ 0, 0, 0, 0x00000c2c, 0xffffffff, 0x5054585c, },
+	{ 0, 0, 0, 0x00000c30, 0xffffffff, 0x4044484c, },
+	{ 0, 0, 1, 0x00000c34, 0xffffffff, 0x5054585c, },
+	{ 0, 0, 1, 0x00000c38, 0xffffffff, 0x4044484c, },
+	{ 0, 0, 0, 0x00000c3c, 0xffffffff, 0x5054585c, },
+	{ 0, 0, 0, 0x00000c40, 0xffffffff, 0x4044484c, },
+	{ 0, 0, 0, 0x00000c44, 0xffffffff, 0x585c383c, },
+	{ 0, 0, 1, 0x00000c48, 0xffffffff, 0x484c5054, },
+	{ 0, 0, 1, 0x00000c4c, 0xffffffff, 0x383c4044, },
+	{ 0, 1, 0, 0x00000e20, 0xffffffff, 0x484c5054, },
+	{ 0, 1, 0, 0x00000e24, 0xffffffff, 0x54585c60, },
+	{ 0, 1, 0, 0x00000e28, 0xffffffff, 0x44484c50, },
+	{ 0, 1, 0, 0x00000e2c, 0xffffffff, 0x5054585c, },
+	{ 0, 1, 0, 0x00000e30, 0xffffffff, 0x4044484c, },
+	{ 0, 1, 1, 0x00000e34, 0xffffffff, 0x5054585c, },
+	{ 0, 1, 1, 0x00000e38, 0xffffffff, 0x4044484c, },
+	{ 0, 1, 0, 0x00000e3c, 0xffffffff, 0x5054585c, },
+	{ 0, 1, 0, 0x00000e40, 0xffffffff, 0x4044484c, },
+	{ 0, 1, 0, 0x00000e44, 0xffffffff, 0x585c383c, },
+	{ 0, 1, 1, 0x00000e48, 0xffffffff, 0x484c5054, },
+	{ 0, 1, 1, 0x00000e4c, 0xffffffff, 0x383c4044, },
+	{ 1, 0, 0, 0x00000c24, 0xffffffff, 0x54585c60, },
+	{ 1, 0, 0, 0x00000c28, 0xffffffff, 0x44484c50, },
+	{ 1, 0, 0, 0x00000c2c, 0xffffffff, 0x5054585c, },
+	{ 1, 0, 0, 0x00000c30, 0xffffffff, 0x4044484c, },
+	{ 1, 0, 1, 0x00000c34, 0xffffffff, 0x5054585c, },
+	{ 1, 0, 1, 0x00000c38, 0xffffffff, 0x4044484c, },
+	{ 1, 0, 0, 0x00000c3c, 0xffffffff, 0x5054585c, },
+	{ 1, 0, 0, 0x00000c40, 0xffffffff, 0x4044484c, },
+	{ 1, 0, 0, 0x00000c44, 0xffffffff, 0x585c383c, },
+	{ 1, 0, 1, 0x00000c48, 0xffffffff, 0x484c5054, },
+	{ 1, 0, 1, 0x00000c4c, 0xffffffff, 0x383c4044, },
+	{ 1, 1, 0, 0x00000e24, 0xffffffff, 0x54585c60, },
+	{ 1, 1, 0, 0x00000e28, 0xffffffff, 0x44484c50, },
+	{ 1, 1, 0, 0x00000e2c, 0xffffffff, 0x5054585c, },
+	{ 1, 1, 0, 0x00000e30, 0xffffffff, 0x4044484c, },
+	{ 1, 1, 1, 0x00000e34, 0xffffffff, 0x5054585c, },
+	{ 1, 1, 1, 0x00000e38, 0xffffffff, 0x4044484c, },
+	{ 1, 1, 0, 0x00000e3c, 0xffffffff, 0x5054585c, },
+	{ 1, 1, 0, 0x00000e40, 0xffffffff, 0x4044484c, },
+	{ 1, 1, 0, 0x00000e44, 0xffffffff, 0x585c383c, },
+	{ 1, 1, 1, 0x00000e48, 0xffffffff, 0x484c5054, },
+	{ 1, 1, 1, 0x00000e4c, 0xffffffff, 0x383c4044, },
 };
 
 RTW_DECL_TABLE_BB_PG(rtw8822c_bb_pg_type0);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/rx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/rx.c
@@ -5,6 +5,7 @@
 #include "main.h"
 #include "rx.h"
 #include "ps.h"
+#include "debug.h"
 
 void rtw_rx_stats(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
 		  struct sk_buff *skb)
@@ -25,8 +26,6 @@
 			rtwvif = (struct rtw_vif *)vif->drv_priv;
 			rtwvif->stats.rx_unicast += skb->len;
 			rtwvif->stats.rx_cnt++;
-			if (rtwvif->stats.rx_cnt > RTW_LPS_THRESHOLD)
-				rtw_leave_lps_irqsafe(rtwdev, rtwvif);
 		}
 	}
 }
@@ -39,6 +38,60 @@
 	u8 *bssid;
 };
 
+static void rtw_rx_phy_stat(struct rtw_dev *rtwdev,
+			    struct rtw_rx_pkt_stat *pkt_stat,
+			    struct ieee80211_hdr *hdr)
+{
+	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+	struct rtw_pkt_count *cur_pkt_cnt = &dm_info->cur_pkt_count;
+	u8 rate_ss, rate_ss_evm, evm_id;
+	u8 i, idx;
+
+	dm_info->curr_rx_rate = pkt_stat->rate;
+
+	if (ieee80211_is_beacon(hdr->frame_control))
+		cur_pkt_cnt->num_bcn_pkt++;
+
+	switch (pkt_stat->rate) {
+	case DESC_RATE1M...DESC_RATE11M:
+		goto pkt_num;
+	case DESC_RATE6M...DESC_RATE54M:
+		rate_ss = 0;
+		rate_ss_evm = 1;
+		evm_id = RTW_EVM_OFDM;
+		break;
+	case DESC_RATEMCS0...DESC_RATEMCS7:
+	case DESC_RATEVHT1SS_MCS0...DESC_RATEVHT1SS_MCS9:
+		rate_ss = 1;
+		rate_ss_evm = 1;
+		evm_id = RTW_EVM_1SS;
+		break;
+	case DESC_RATEMCS8...DESC_RATEMCS15:
+	case DESC_RATEVHT2SS_MCS0...DESC_RATEVHT2SS_MCS9:
+		rate_ss = 2;
+		rate_ss_evm = 2;
+		evm_id = RTW_EVM_2SS_A;
+		break;
+	default:
+		rtw_warn(rtwdev, "unknown pkt rate = %d\n", pkt_stat->rate);
+		return;
+	}
+
+	for (i = 0; i < rate_ss_evm; i++) {
+		idx = evm_id + i;
+		ewma_evm_add(&dm_info->ewma_evm[idx],
+			     dm_info->rx_evm_dbm[i]);
+	}
+
+	for (i = 0; i < rtwdev->hal.rf_path_num; i++) {
+		idx = RTW_SNR_OFDM_A + 4 * rate_ss + i;
+		ewma_snr_add(&dm_info->ewma_snr[idx],
+			     dm_info->rx_snr[i]);
+	}
+pkt_num:
+	cur_pkt_cnt->num_qry_pkt[pkt_stat->rate]++;
+}
+
 static void rtw_rx_addr_match_iter(void *data, u8 *mac,
 				   struct ieee80211_vif *vif)
 {
@@ -50,14 +103,16 @@
 	struct rtw_rx_pkt_stat *pkt_stat = iter_data->pkt_stat;
 	u8 *bssid = iter_data->bssid;
 
-	if (ether_addr_equal(vif->bss_conf.bssid, bssid) &&
-	    (ether_addr_equal(vif->addr, hdr->addr1) ||
-	     ieee80211_is_beacon(hdr->frame_control)))
-		sta = ieee80211_find_sta_by_ifaddr(rtwdev->hw, hdr->addr2,
-						   vif->addr);
-	else
+	if (!ether_addr_equal(vif->bss_conf.bssid, bssid))
 		return;
 
+	if (!(ether_addr_equal(vif->addr, hdr->addr1) ||
+	      ieee80211_is_beacon(hdr->frame_control)))
+		return;
+
+	rtw_rx_phy_stat(rtwdev, pkt_stat, hdr);
+	sta = ieee80211_find_sta_by_ifaddr(rtwdev->hw, hdr->addr2,
+					   vif->addr);
 	if (!sta)
 		return;
 
@@ -105,35 +160,17 @@
 	else if (pkt_stat->rate >= DESC_RATEMCS0)
 		rx_status->encoding = RX_ENC_HT;
 
-	if (pkt_stat->rate >= DESC_RATEVHT1SS_MCS0 &&
-	    pkt_stat->rate <= DESC_RATEVHT1SS_MCS9) {
-		rx_status->nss = 1;
-		rx_status->rate_idx = pkt_stat->rate - DESC_RATEVHT1SS_MCS0;
-	} else if (pkt_stat->rate >= DESC_RATEVHT2SS_MCS0 &&
-		   pkt_stat->rate <= DESC_RATEVHT2SS_MCS9) {
-		rx_status->nss = 2;
-		rx_status->rate_idx = pkt_stat->rate - DESC_RATEVHT2SS_MCS0;
-	} else if (pkt_stat->rate >= DESC_RATEVHT3SS_MCS0 &&
-		   pkt_stat->rate <= DESC_RATEVHT3SS_MCS9) {
-		rx_status->nss = 3;
-		rx_status->rate_idx = pkt_stat->rate - DESC_RATEVHT3SS_MCS0;
-	} else if (pkt_stat->rate >= DESC_RATEVHT4SS_MCS0 &&
-		   pkt_stat->rate <= DESC_RATEVHT4SS_MCS9) {
-		rx_status->nss = 4;
-		rx_status->rate_idx = pkt_stat->rate - DESC_RATEVHT4SS_MCS0;
-	} else if (pkt_stat->rate >= DESC_RATEMCS0 &&
-		   pkt_stat->rate <= DESC_RATEMCS15) {
-		rx_status->rate_idx = pkt_stat->rate - DESC_RATEMCS0;
-	} else if (rx_status->band == NL80211_BAND_5GHZ &&
-		   pkt_stat->rate >= DESC_RATE6M &&
-		   pkt_stat->rate <= DESC_RATE54M) {
+	if (rx_status->band == NL80211_BAND_5GHZ &&
+	    pkt_stat->rate >= DESC_RATE6M &&
+	    pkt_stat->rate <= DESC_RATE54M) {
 		rx_status->rate_idx = pkt_stat->rate - DESC_RATE6M;
 	} else if (rx_status->band == NL80211_BAND_2GHZ &&
 		   pkt_stat->rate >= DESC_RATE1M &&
 		   pkt_stat->rate <= DESC_RATE54M) {
 		rx_status->rate_idx = pkt_stat->rate - DESC_RATE1M;
-	} else {
-		rx_status->rate_idx = 0;
+	} else if (pkt_stat->rate >= DESC_RATEMCS0) {
+		rtw_desc_to_mcsrate(pkt_stat->rate, &rx_status->rate_idx,
+				    &rx_status->nss);
 	}
 
 	rx_status->flag |= RX_FLAG_MACTIME_START;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/rx.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/rx.h
@@ -5,6 +5,15 @@
 #ifndef __RTW_RX_H_
 #define __RTW_RX_H_
 
+enum rtw_rx_desc_enc {
+	RX_DESC_ENC_NONE	= 0,
+	RX_DESC_ENC_WEP40	= 1,
+	RX_DESC_ENC_TKIP_WO_MIC	= 2,
+	RX_DESC_ENC_TKIP_MIC	= 3,
+	RX_DESC_ENC_AES		= 4,
+	RX_DESC_ENC_WEP104	= 5,
+};
+
 #define GET_RX_DESC_PHYST(rxdesc)                                              \
 	le32_get_bits(*((__le32 *)(rxdesc) + 0x00), BIT(26))
 #define GET_RX_DESC_ICV_ERR(rxdesc)                                            \
@@ -21,6 +30,8 @@
 	le32_get_bits(*((__le32 *)(rxdesc) + 0x00), GENMASK(19, 16))
 #define GET_RX_DESC_SHIFT(rxdesc)                                              \
 	le32_get_bits(*((__le32 *)(rxdesc) + 0x00), GENMASK(25, 24))
+#define GET_RX_DESC_ENC_TYPE(rxdesc)                                           \
+	le32_get_bits(*((__le32 *)(rxdesc) + 0x00), GENMASK(22, 20))
 #define GET_RX_DESC_RX_RATE(rxdesc)                                            \
 	le32_get_bits(*((__le32 *)(rxdesc) + 0x03), GENMASK(6, 0))
 #define GET_RX_DESC_MACID(rxdesc)                                              \
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/sar.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/sar.c
@@ -0,0 +1,778 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2018-2019  Realtek Corporation
+ */
+
+#include <linux/acpi.h>
+#include "main.h"
+#include "debug.h"
+#include "phy.h"
+#include "sar.h"
+
+#define RTW_SAR_WRDS_CHAIN_NR	2
+
+enum rtw_sar_limit_index {
+	RTW_SAR_LMT_CH1_14,
+	RTW_SAR_LMT_CH36_64,
+	RTW_SAR_LMT_UND1,
+	RTW_SAR_LMT_CH100_144,
+	RTW_SAR_LMT_CH149_165,
+
+	RTW_SAR_LMT_TOTAL_NR,
+};
+
+struct rtw_sar_limits {
+	s8 limit[RTW_SAR_LMT_TOTAL_NR];
+};
+
+struct rtw_sar_wrds {
+	struct rtw_sar_limits chain[RTW_SAR_WRDS_CHAIN_NR];
+};
+
+#define ACPI_WRDS_METHOD	"WRDS"
+#define ACPI_WRDS_SIZE		sizeof(struct rtw_sar_wrds)
+#define ACPI_WRDS_TOTAL_SIZE	(sizeof(struct rtw_sar_wrds) + 2)
+#define ACPI_WIFI_DOMAIN	0x07
+
+#ifdef CONFIG_ACPI
+static union acpi_object *rtw_sar_get_acpiobj(struct rtw_dev *rtwdev,
+					      const char *method)
+{
+	struct device *dev = rtwdev->dev;
+	acpi_handle root_handle;
+	acpi_handle handle;
+	acpi_status status;
+	struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL};
+
+	/* Check device handler */
+	root_handle = ACPI_HANDLE(dev);
+	if (!root_handle) {
+		rtw_dbg(rtwdev, RTW_DBG_REGD,
+			"SAR: Could not retireve root port ACPI handle\n");
+		return NULL;
+	}
+
+	/* Get method's handler */
+	status = acpi_get_handle(root_handle, (acpi_string)method, &handle);
+	if (ACPI_FAILURE(status)) {
+		rtw_dbg(rtwdev, RTW_DBG_REGD, "SAR: %s method not found (0x%x)\n",
+			method, status);
+		return NULL;
+	}
+
+	/* Call specific method with no argument */
+	status = acpi_evaluate_object(handle, NULL, NULL, &buf);
+	if (ACPI_FAILURE(status)) {
+		rtw_dbg(rtwdev, RTW_DBG_REGD,
+			"SAR: %s invocation failed (0x%x)\n", method, status);
+		return NULL;
+	}
+
+	return buf.pointer;
+}
+
+static union acpi_object *rtw_sar_get_wifi_pkt(struct rtw_dev *rtwdev,
+					       union acpi_object *obj,
+					       u32 element_count)
+{
+	union acpi_object *wifi_pkg;
+	u32 i;
+
+	if (obj->type != ACPI_TYPE_PACKAGE ||
+	    obj->package.count < 2 ||
+	    obj->package.elements[0].type != ACPI_TYPE_INTEGER ||
+	    obj->package.elements[0].integer.value != 0) {
+		rtw_dbg(rtwdev, RTW_DBG_REGD,
+			"SAR: Unsupported wifi package structure\n");
+		return NULL;
+	}
+
+	/* loop through all the packages to find the one for WiFi */
+	for (i = 1; i < obj->package.count; i++) {
+		union acpi_object *domain;
+
+		wifi_pkg = &obj->package.elements[i];
+
+		/* Skip anything that is not a package with the right amount of
+		 * elements (i.e. domain_type, enabled/disabled plus the sar
+		 * table size.)
+		 */
+		if (wifi_pkg->type != ACPI_TYPE_PACKAGE ||
+		    wifi_pkg->package.count != element_count)
+			continue;
+
+		domain = &wifi_pkg->package.elements[0];
+		if (domain->type == ACPI_TYPE_INTEGER &&
+		    domain->integer.value == ACPI_WIFI_DOMAIN)
+			return wifi_pkg;
+	}
+
+	return NULL;
+}
+
+static void *rtw_sar_get_wrds_table(struct rtw_dev *rtwdev)
+{
+	union acpi_object *wrds, *wrds_pkg;
+	int i, idx = 2;
+	u8 *wrds_raw = NULL;
+
+	wrds = rtw_sar_get_acpiobj(rtwdev, ACPI_WRDS_METHOD);
+	if (!wrds)
+		return NULL;
+
+	wrds_pkg = rtw_sar_get_wifi_pkt(rtwdev, wrds, ACPI_WRDS_TOTAL_SIZE);
+	if (!wrds_pkg)
+		goto out;
+
+	/* WiFiSarEnable 0: ignore BIOS config; 1: use BIOS config */
+	if (wrds_pkg->package.elements[1].type != ACPI_TYPE_INTEGER ||
+	    wrds_pkg->package.elements[1].integer.value == 0)
+		goto out;
+
+	wrds_raw = kmalloc(ACPI_WRDS_SIZE, GFP_KERNEL);
+	if (!wrds_raw)
+		goto out;
+
+	/* read elements[2~11] */
+	for (i = 0; i < ACPI_WRDS_SIZE; i++) {
+		union acpi_object *entry;
+
+		entry = &wrds_pkg->package.elements[idx++];
+		if (entry->type != ACPI_TYPE_INTEGER ||
+		    entry->integer.value > U8_MAX) {
+			kfree(wrds_raw);
+			wrds_raw = NULL;
+			goto out;
+		}
+
+		wrds_raw[i] = entry->integer.value;
+	}
+out:
+	kfree(wrds);
+
+	return wrds_raw;
+}
+
+static void rtw_sar_apply_wrds(struct rtw_dev *rtwdev,
+			       const struct rtw_sar_wrds *wrds)
+{
+	int path;
+
+	for (path = 0; path < RTW_SAR_WRDS_CHAIN_NR; path++) {
+		rtw_phy_set_tx_power_sar(rtwdev, RTW_REGD_WW, path, 1, 14,
+					 wrds->chain[path].limit[RTW_SAR_LMT_CH1_14]);
+		rtw_phy_set_tx_power_sar(rtwdev, RTW_REGD_WW, path, 36, 64,
+					 wrds->chain[path].limit[RTW_SAR_LMT_CH36_64]);
+		rtw_phy_set_tx_power_sar(rtwdev, RTW_REGD_WW, path, 100, 144,
+					 wrds->chain[path].limit[RTW_SAR_LMT_CH100_144]);
+		rtw_phy_set_tx_power_sar(rtwdev, RTW_REGD_WW, path, 149, 165,
+					 wrds->chain[path].limit[RTW_SAR_LMT_CH149_165]);
+	}
+
+	rtwdev->sar.source = RTW_SAR_SOURCE_ACPI_STATIC;
+}
+
+static int rtw_sar_load_static_tables(struct rtw_dev *rtwdev)
+{
+	struct rtw_sar_wrds *wrds;
+
+	wrds = rtw_sar_get_wrds_table(rtwdev);
+	if (!wrds)
+		return -ENOENT;
+
+	rtw_dbg(rtwdev, RTW_DBG_REGD,
+		"SAR: Apply WRDS to TX power\n");
+
+	rtw_sar_apply_wrds(rtwdev, wrds);
+	kfree(wrds);
+
+	return 0;
+}
+
+#define ACPI_RWRD_METHOD	"RWRD"
+#define ACPI_RWSI_METHOD	"RWSI"
+#define ACPI_RWGS_METHOD	"RWGS"
+
+#define RTW_SAR_RWRD_ID_HP	0x5048
+#define RTW_SAR_RWRD_ID_RT	0x5452
+
+#define RTW_SAR_RWRD_CHAIN_NR	4
+
+struct rtw_sar_rwrd {
+	u16 id;
+	u8 en;
+	u8 count;
+	struct {
+		struct rtw_sar_limits chain[RTW_SAR_RWRD_CHAIN_NR];
+	} mode[0];
+} __packed;
+
+struct rtw_sar_rwsi_hp {
+	u8 index[RTW_SAR_RWRD_CHAIN_NR];
+} __packed;
+
+struct rtw_sar_rwsi_rt {
+	u8 index;
+} __packed;
+
+union rtw_sar_rwsi {
+	struct rtw_sar_rwsi_hp hp;
+	struct rtw_sar_rwsi_rt rt;
+};
+
+enum rtw_sar_rwgs_band {
+	RTW_SAR_RWGS_2G,
+	RTW_SAR_RWGS_5G,
+	RTW_SAR_RWGS_BAND_NR,
+};
+
+enum rtw_sar_rwgs_geo_hp {
+	RTW_SAR_RWGS_HP_FCC_IC,
+	RTW_SAR_RWGS_HP_ETSI_MKK,
+	RTW_SAR_RWGS_HP_WW_KCC,
+
+	RTW_SAR_RWGS_HP_NR,
+};
+
+struct rtw_sar_rwgs_hp {
+	struct {
+		struct {
+			s8 max;		/* Q1 + 10 */
+			s8 delta[4];	/* Q1 */
+		} band[RTW_SAR_RWGS_BAND_NR];
+	} geo[RTW_SAR_RWGS_HP_NR];
+} __packed;
+
+enum rtw_sar_rwgs_geo_rt {
+	RTW_SAR_RWGS_RT_FCC,
+	RTW_SAR_RWGS_RT_CE,
+	RTW_SAR_RWGS_RT_MKK,
+	RTW_SAR_RWGS_RT_IC,
+	RTW_SAR_RWGS_RT_KCC,
+	RTW_SAR_RWGS_RT_WW,
+
+	RTW_SAR_RWGS_RT_NR,
+};
+
+struct rtw_sar_rwgs_rt {
+	struct {
+		struct {
+			u8 max;		/* Q3 */
+			s8 delta;	/* Q1 */
+		} band[RTW_SAR_RWGS_BAND_NR];
+	} geo[RTW_SAR_RWGS_RT_NR];
+} __packed;
+
+union rtw_sar_rwgs {
+	struct rtw_sar_rwgs_hp hp;
+	struct rtw_sar_rwgs_rt rt;
+};
+
+struct rtw_sar_geo_map {
+	int idx;	/* index of rwgs.geo[] */
+	int rd;		/* RTW_REGD_xxx */
+};
+
+static const struct rtw_sar_geo_map geo_map_hp[] = {
+	{RTW_SAR_RWGS_HP_FCC_IC,   RTW_REGD_FCC},
+	{RTW_SAR_RWGS_HP_FCC_IC,   RTW_REGD_IC},
+	{RTW_SAR_RWGS_HP_ETSI_MKK, RTW_REGD_ETSI},
+	{RTW_SAR_RWGS_HP_ETSI_MKK, RTW_REGD_MKK},
+	{RTW_SAR_RWGS_HP_WW_KCC,   RTW_REGD_KCC},
+	{RTW_SAR_RWGS_HP_WW_KCC,   RTW_REGD_WW},
+};
+
+static const struct rtw_sar_geo_map geo_map_rt[] = {
+	{RTW_SAR_RWGS_RT_FCC, RTW_REGD_FCC},
+	{RTW_SAR_RWGS_RT_CE,  RTW_REGD_ETSI},
+	{RTW_SAR_RWGS_RT_MKK, RTW_REGD_MKK},
+	{RTW_SAR_RWGS_RT_IC,  RTW_REGD_IC},
+	{RTW_SAR_RWGS_RT_KCC, RTW_REGD_KCC},
+	{RTW_SAR_RWGS_RT_WW,  RTW_REGD_WW},
+};
+
+struct rtw_sar_read {
+	int (*rwsi_mode)(struct rtw_dev *rtwdev, int path);
+	int (*rwrd_base_q3)(struct rtw_dev *rtwdev, int mode, int path, int chidx);
+	int (*rwgs_delta_q3)(struct rtw_dev *rtwdev, int gi, int path, int band);
+	int (*rwgs_max_q3)(struct rtw_dev *rtwdev, int gi, int band);
+	const struct rtw_sar_geo_map *gm, *gm_end;
+	int rwsi_sz;
+	int rwgs_sz;
+	int rwgs_geos;
+};
+
+static int rwsi_mode_hp(struct rtw_dev *rtwdev, int path)
+{
+	return rtwdev->sar.rwsi->hp.index[path] - 1;
+}
+
+static int rwrd_base_q3_hp(struct rtw_dev *rtwdev, int mode, int path, int chidx)
+{
+	int sar;
+
+	sar = rtwdev->sar.rwrd->mode[mode].chain[path].limit[chidx];
+
+	return (10 << 3) + (sar << 2);
+}
+
+static int rwgs_delta_q3_hp(struct rtw_dev *rtwdev, int gi, int path, int band)
+{
+	return rtwdev->sar.rwgs->hp.geo[gi].band[band].delta[path] << 2;
+}
+
+static int rwgs_max_q3_hp(struct rtw_dev *rtwdev, int gi, int band)
+{
+	return (10 << 3) + (rtwdev->sar.rwgs->hp.geo[gi].band[band].max << 2);
+}
+
+static const struct rtw_sar_read sar_read_hp = {
+	.rwsi_mode = rwsi_mode_hp,
+	.rwrd_base_q3 = rwrd_base_q3_hp,
+	.rwgs_delta_q3 = rwgs_delta_q3_hp,
+	.rwgs_max_q3 = rwgs_max_q3_hp,
+	.gm = geo_map_hp,
+	.gm_end = geo_map_hp + ARRAY_SIZE(geo_map_hp),
+	.rwsi_sz = sizeof(struct rtw_sar_rwsi_hp),
+	.rwgs_sz = sizeof(struct rtw_sar_rwgs_hp),
+	.rwgs_geos = RTW_SAR_RWGS_HP_NR,
+};
+
+static int rwsi_mode_rt(struct rtw_dev *rtwdev, int path)
+{
+	return rtwdev->sar.rwsi->rt.index - 1;
+}
+
+static int rwrd_base_q3_rt(struct rtw_dev *rtwdev, int mode, int path, int chidx)
+{
+	return rtwdev->sar.rwrd->mode[mode].chain[path].limit[chidx] << 3;
+}
+
+static int rwgs_delta_q3_rt(struct rtw_dev *rtwdev, int gi, int path, int band)
+{
+	return rtwdev->sar.rwgs->rt.geo[gi].band[band].delta << 2;
+}
+
+static int rwgs_max_q3_rt(struct rtw_dev *rtwdev, int gi, int band)
+{
+	return rtwdev->sar.rwgs->rt.geo[gi].band[band].max;
+}
+
+static const struct rtw_sar_read sar_read_rt = {
+	.rwsi_mode = rwsi_mode_rt,
+	.rwrd_base_q3 = rwrd_base_q3_rt,
+	.rwgs_delta_q3 = rwgs_delta_q3_rt,
+	.rwgs_max_q3 = rwgs_max_q3_rt,
+	.gm = geo_map_rt,
+	.gm_end = geo_map_rt + ARRAY_SIZE(geo_map_rt),
+	.rwsi_sz = sizeof(struct rtw_sar_rwsi_rt),
+	.rwgs_sz = sizeof(struct rtw_sar_rwgs_rt),
+	.rwgs_geos = RTW_SAR_RWGS_RT_NR,
+};
+
+static u8 *rtw_sar_get_raw_package(struct rtw_dev *rtwdev,
+				   union acpi_object *obj, int *len)
+{
+	u8 *raw;
+	u32 i;
+
+	if (obj->type != ACPI_TYPE_PACKAGE || obj->package.count <= 0) {
+		rtw_dbg(rtwdev, RTW_DBG_REGD,
+			"SAR: Unsupported obj to dump\n");
+		return NULL;
+	}
+
+	raw = kmalloc(obj->package.count, GFP_KERNEL);
+	if (!raw)
+		return NULL;
+
+	for (i = 0; i < obj->package.count; i++) {
+		union acpi_object *element;
+
+		element = &obj->package.elements[i];
+
+		if (element->type != ACPI_TYPE_INTEGER) {
+			rtw_dbg(rtwdev, RTW_DBG_REGD,
+				"SAR: Unexpected element type\n");
+			kfree(raw);
+			return NULL;
+		}
+
+		raw[i] = (u8)element->integer.value;
+	}
+
+	*len = obj->package.count;
+
+	return raw;
+}
+
+static void *rtw_sar_get_raw_table(struct rtw_dev *rtwdev, const char *method,
+				   int *len)
+{
+	union acpi_object *obj;
+	u8 *raw;
+
+	obj = rtw_sar_get_acpiobj(rtwdev, method);
+	if (!obj)
+		return NULL;
+
+	raw = rtw_sar_get_raw_package(rtwdev, obj, len);
+	kfree(obj);
+
+	return raw;
+}
+
+static bool is_valid_rwrd(struct rtw_dev *rtwdev, const struct rtw_sar_rwrd *rwrd,
+			  int len)
+{
+	if (len < sizeof(*rwrd)) {
+		rtw_dbg(rtwdev, RTW_DBG_REGD,
+			"SAR: RWRD: len %d is too short\n", len);
+		return false;
+	}
+
+	switch (rwrd->id) {
+	case RTW_SAR_RWRD_ID_HP:
+		rtwdev->sar.read = &sar_read_hp;
+		break;
+	case RTW_SAR_RWRD_ID_RT:
+		rtwdev->sar.read = &sar_read_rt;
+		break;
+	default:
+		rtw_dbg(rtwdev, RTW_DBG_REGD,
+			"SAR: RWRD: ID %04x isn't supported\n", rwrd->id);
+		return false;
+	}
+
+	if (sizeof(*rwrd) + rwrd->count * sizeof(rwrd->mode[0]) != len) {
+		rtw_dbg(rtwdev, RTW_DBG_REGD,
+			"SAR: RWRD: len(%d) doesn't match count(%d)\n",
+			len, rwrd->count);
+		return false;
+	}
+
+	return true;
+}
+
+static bool is_valid_rwsi_idx(struct rtw_dev *rtwdev, const struct rtw_sar_rwrd *rwrd,
+			      const u8 index[], int len)
+{
+	/* index range is one based. i.e. 1 <= index[] <= rwrd->count */
+	int i;
+
+	for (i = 0; i < len; i++)
+		if (index[i] < 1 || index[i] > rwrd->count) {
+			rtw_dbg(rtwdev, RTW_DBG_REGD,
+				"SAR: RWSI: index is out of range\n");
+			return false;
+		}
+
+	return true;
+}
+
+static bool is_valid_rwsi(struct rtw_dev *rtwdev, const struct rtw_sar_rwrd *rwrd,
+			  const union rtw_sar_rwsi *rwsi, int len)
+{
+	const struct rtw_sar_read *r = rtwdev->sar.read;
+
+	if (r->rwsi_sz != len)
+		goto err;
+
+	if (rwrd->id == RTW_SAR_RWRD_ID_HP &&
+	    is_valid_rwsi_idx(rtwdev, rwrd, rwsi->hp.index, RTW_SAR_RWRD_CHAIN_NR))
+		return true;
+
+	if (rwrd->id == RTW_SAR_RWRD_ID_RT &&
+	    is_valid_rwsi_idx(rtwdev, rwrd, &rwsi->rt.index, 1)) {
+		return true;
+	}
+
+err:
+	rtw_dbg(rtwdev, RTW_DBG_REGD,
+		"SAR: RWSI: len doesn't match struct size\n");
+
+	return false;
+}
+
+static bool is_valid_rwgs(struct rtw_dev *rtwdev, const struct rtw_sar_rwrd *rwrd,
+			  const union rtw_sar_rwgs *rwgs, int len)
+{
+	const struct rtw_sar_read *r = rtwdev->sar.read;
+
+	if (r->rwgs_sz == len)
+		return true;
+
+	rtw_dbg(rtwdev, RTW_DBG_REGD,
+		"SAR: RWGS: len doesn't match struct size\n");
+
+	return false;
+}
+
+#ifdef CONFIG_RTW88_DEBUGFS
+void rtw_sar_dump_via_debugfs(struct rtw_dev *rtwdev, struct seq_file *m)
+{
+#define q3_int(q3)	((q3) >> 3)
+#define q3_fra(q3)	(((q3) & 0x7) * 125)
+
+	const struct rtw_sar_rwrd *rwrd = rtwdev->sar.rwrd;
+	const union rtw_sar_rwsi *rwsi = rtwdev->sar.rwsi;
+	const union rtw_sar_rwgs *rwgs = rtwdev->sar.rwgs;
+	const struct rtw_sar_read *r = rtwdev->sar.read;
+	int q3;
+	int mode;
+	int path;
+	int chidx;
+	int gi;
+	int band;
+
+	if (!rwrd || !rwsi || !rwgs || !r) {
+		seq_puts(m, "(No SAR data)\n");
+		return;
+	}
+
+	seq_printf(m, "Customer ID: 0x%04x\n", rwrd->id);
+	seq_printf(m, "WiFiEnable: 0x%x\n", rwrd->en);
+	seq_printf(m, "Total SAR Table Count: %d\n", rwrd->count);
+	seq_printf(m, "Current SAR Table Index: (%*ph)\n", r->rwsi_sz, rwsi);
+	seq_puts(m, "\n");
+
+	seq_printf(m, "Dump RWRD SAR RAW DATA. (Total Count: %ld)\n",
+		   rwrd->count * sizeof(rwrd->mode[0]));
+	for (mode = 0; mode < rwrd->count; mode++)
+		seq_printf(m, "%02x: %20ph\n", mode + 1, &rwrd->mode[mode]);
+	seq_puts(m, "\n");
+
+	seq_puts(m, "Show SAR PowerLimit:\n");
+	for (path = 0; path < 2; path++) {
+		mode = r->rwsi_mode(rtwdev, path);
+		q3 = r->rwrd_base_q3(rtwdev, mode, path, RTW_SAR_LMT_CH1_14);
+		seq_printf(m, "2.4G Antenna %d: [%d.%d] dBm\n", path,
+			   q3_int(q3), q3_fra(q3));
+	}
+	seq_puts(m, "\n");
+
+	for (path = 0; path < 2; path++) {
+		mode = r->rwsi_mode(rtwdev, path);
+		seq_printf(m, "5G Antenna %d: [", path);
+		for (chidx = RTW_SAR_LMT_CH36_64; chidx <= RTW_SAR_LMT_CH149_165;
+		     chidx++) {
+			q3 = r->rwrd_base_q3(rtwdev, mode, path, chidx);
+			seq_printf(m, "%d.%d, ", q3_int(q3), q3_fra(q3));
+		}
+		seq_puts(m, "] dBm\n");
+	}
+	seq_puts(m, "\n");
+
+	seq_printf(m, "Dump Geo-SAR Table RAW DATA. (Total Count: %d)\n",
+		   r->rwgs_sz);
+	for (gi = 0; gi < r->rwgs_geos; gi++) {
+		seq_printf(m, "geo-%d: %*ph\n", gi, r->rwgs_sz / r->rwgs_geos,
+			   (u8 *)rwgs + gi * (r->rwgs_sz / r->rwgs_geos));
+	}
+	seq_puts(m, "\n");
+
+	gi = 1;	/* take index 1 as an example */
+	seq_puts(m, "Show Geo-SAR PowerLimit:\n");
+	seq_printf(m, "2G Geo Table Index: %d\n", gi);
+	seq_printf(m, "5G Geo Table Index: %d\n", gi);
+	for (band = RTW_SAR_RWGS_2G; band < RTW_SAR_RWGS_BAND_NR; band++) {
+		seq_puts(m, "\n");
+		seq_printf(m, "%dGHz:\n", band == 0 ? 2 : 5);
+		q3 = r->rwgs_max_q3(rtwdev, gi, band);
+		seq_printf(m, "Max Power: [%d.%d] dBm\n", q3_int(q3),
+			   q3_fra(q3));
+		for (path = 0; path < 2; path++) {
+			q3 = r->rwgs_delta_q3(rtwdev, gi, path, band);
+			seq_printf(m, "Ant-%d delta value: [%d.%d] dB\n", path,
+				   q3_int(q3), q3_fra(q3));
+		}
+	}
+}
+#endif
+
+static void rtw_sar_apply_dynamic_tables(struct rtw_dev *rtwdev)
+{
+	struct rtw_hal *hal = &rtwdev->hal;
+	const struct rtw_sar_read *r = rtwdev->sar.read;
+	const struct rtw_sar_geo_map *gm = r->gm;
+	const struct rtw_sar_geo_map *gm_end = r->gm_end;
+	int path_num = min_t(int, RTW_SAR_RWRD_CHAIN_NR, hal->rf_path_num);
+	int path, mode;
+	int sar, delta, max;
+
+	for (; gm < gm_end; gm++) {
+		for (path = 0; path < path_num; path++) {
+			mode = r->rwsi_mode(rtwdev, path);
+
+			/* 2.4G part */
+			delta = r->rwgs_delta_q3(rtwdev, gm->idx, path, RTW_SAR_RWGS_2G);
+			max = r->rwgs_max_q3(rtwdev, gm->idx, RTW_SAR_RWGS_2G);
+
+			sar = r->rwrd_base_q3(rtwdev, mode, path, RTW_SAR_LMT_CH1_14);
+			sar = min(sar + delta, max);
+			rtw_phy_set_tx_power_sar(rtwdev, gm->rd, path, 1, 14, sar);
+
+			/* 5G part */
+			delta = r->rwgs_delta_q3(rtwdev, gm->idx, path, RTW_SAR_RWGS_5G);
+			max = r->rwgs_max_q3(rtwdev, gm->idx, RTW_SAR_RWGS_5G);
+
+			sar = r->rwrd_base_q3(rtwdev, mode, path, RTW_SAR_LMT_CH36_64);
+			sar = min(sar + delta, max);
+			rtw_phy_set_tx_power_sar(rtwdev, gm->rd, path, 36, 64, sar);
+
+			sar = r->rwrd_base_q3(rtwdev, mode, path, RTW_SAR_LMT_CH100_144);
+			sar = min(sar + delta, max);
+			rtw_phy_set_tx_power_sar(rtwdev, gm->rd, path, 100, 144, sar);
+
+			sar = r->rwrd_base_q3(rtwdev, mode, path, RTW_SAR_LMT_CH149_165);
+			sar = min(sar + delta, max);
+			rtw_phy_set_tx_power_sar(rtwdev, gm->rd, path, 149, 165, sar);
+		}
+	}
+
+	rtwdev->sar.source = RTW_SAR_SOURCE_ACPI_DYNAMIC;
+}
+
+static bool rtw_sar_is_rwsi_changed(struct rtw_dev *rtwdev)
+{
+	union rtw_sar_rwsi *rwsi, *old;
+	bool valid;
+	int len;
+
+	if (rtwdev->sar.source != RTW_SAR_SOURCE_ACPI_DYNAMIC)
+		return false;
+
+	if (!rtwdev->sar.rwrd || !rtwdev->sar.rwsi || !rtwdev->sar.rwgs)
+		return false;
+
+	rwsi = rtw_sar_get_raw_table(rtwdev, ACPI_RWSI_METHOD, &len);
+	if (!rwsi)
+		return false;
+	valid = is_valid_rwsi(rtwdev, rtwdev->sar.rwrd, rwsi, len);
+	if (!valid) {
+		kfree(rwsi);
+		return false;
+	}
+
+	if (memcmp(rwsi, rtwdev->sar.rwsi, len) == 0) {
+		kfree(rwsi);
+		return true;
+	}
+
+	old = rtwdev->sar.rwsi;
+	rtwdev->sar.rwsi = rwsi;
+	kfree(old);
+
+	rtw_dbg(rtwdev, RTW_DBG_REGD, "SAR: RWSI is changed\n");
+
+	rtw_sar_apply_dynamic_tables(rtwdev);
+
+	rtw_phy_set_tx_power_level(rtwdev, rtwdev->hal.current_channel);
+
+	return true;
+}
+
+static int rtw_sar_load_dynamic_tables(struct rtw_dev *rtwdev)
+{
+	struct rtw_sar_rwrd *rwrd;
+	union rtw_sar_rwsi *rwsi;
+	union rtw_sar_rwgs *rwgs;
+	int len;
+	bool valid;
+
+	rwrd = rtw_sar_get_raw_table(rtwdev, ACPI_RWRD_METHOD, &len);
+	if (!rwrd)
+		goto out;
+	valid = is_valid_rwrd(rtwdev, rwrd, len);
+	if (!valid)
+		goto out_rwrd;
+	if (!rwrd->en) {
+		rtw_dbg(rtwdev, RTW_DBG_REGD, "SAR: RWRD isn't enabled\n");
+		goto out_rwrd;
+	}
+
+	rwsi = rtw_sar_get_raw_table(rtwdev, ACPI_RWSI_METHOD, &len);
+	if (!rwsi)
+		goto out_rwrd;
+	valid = is_valid_rwsi(rtwdev, rwrd, rwsi, len);
+	if (!valid)
+		goto out_rwsi;
+
+	rwgs = rtw_sar_get_raw_table(rtwdev, ACPI_RWGS_METHOD, &len);
+	if (!rwgs)
+		goto out_rwsi;
+	valid = is_valid_rwgs(rtwdev, rwrd, rwgs, len);
+	if (!valid)
+		goto out_rwgs;
+
+	rtwdev->sar.rwrd = rwrd;
+	rtwdev->sar.rwsi = rwsi;
+	rtwdev->sar.rwgs = rwgs;
+
+	rtw_sar_apply_dynamic_tables(rtwdev);
+
+	rtw_dbg(rtwdev, RTW_DBG_REGD, "SAR: RWRD/RWSI/RWGS is adopted\n");
+
+	return 0;
+
+out_rwgs:
+	kfree(rwgs);
+out_rwsi:
+	kfree(rwsi);
+out_rwrd:
+	kfree(rwrd);
+out:
+	return -ENOENT;
+}
+#else
+static int rtw_sar_load_static_tables(struct rtw_dev *rtwdev)
+{
+	return -ENOENT;
+}
+
+static bool rtw_sar_is_rwsi_changed(struct rtw_dev *rtwdev)
+{
+	return false;
+}
+
+static int rtw_sar_load_dynamic_tables(struct rtw_dev *rtwdev)
+{
+	return -ENOENT;
+}
+
+#ifdef CONFIG_RTW88_DEBUGFS
+void rtw_sar_dump_via_debugfs(struct rtw_dev *rtwdev, struct seq_file *m)
+{
+	seq_puts(m, "(No SAR data)\n");
+}
+#endif
+#endif /* CONFIG_ACPI */
+
+void rtw_sar_load_table(struct rtw_dev *rtwdev)
+{
+	int ret;
+
+	ret = rtw_sar_load_dynamic_tables(rtwdev);
+	if (!ret)
+		return;	/* if dynamic SAR table is loaded, ignore static SAR table */
+
+	rtw_sar_load_static_tables(rtwdev);
+}
+
+void rtw_sar_release_table(struct rtw_dev *rtwdev)
+{
+	kfree(rtwdev->sar.rwrd);
+	kfree(rtwdev->sar.rwsi);
+	kfree(rtwdev->sar.rwgs);
+}
+
+void rtw_sar_work(struct work_struct *work)
+{
+	struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
+					      sar.work.work);
+
+	if (!rtw_sar_is_rwsi_changed(rtwdev))
+		return;
+
+	ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->sar.work,
+				     RTW_SAR_DELAY_TIME);
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/sar.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/sar.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2018-2019  Realtek Corporation
+ */
+
+#ifndef __RTW_SAR_H_
+#define __RTW_SAR_H_
+
+void rtw_sar_load_table(struct rtw_dev *rtwdev);
+void rtw_sar_release_table(struct rtw_dev *rtwdev);
+void rtw_sar_work(struct work_struct *work);
+void rtw_sar_dump_via_debugfs(struct rtw_dev *rtwdev, struct seq_file *m);
+
+#define RTW_SAR_DELAY_TIME	(10 * HZ)
+
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/sec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/sec.c
@@ -44,7 +44,7 @@
 
 	write_cmd = RTW_SEC_CMD_WRITE_ENABLE | RTW_SEC_CMD_POLLING;
 	addr = hw_key_idx << RTW_SEC_CAM_ENTRY_SHIFT;
-	for (i = 5; i >= 0; i--) {
+	for (i = 7; i >= 0; i--) {
 		switch (i) {
 		case 0:
 			content = ((key->keyidx & 0x3))		|
@@ -60,6 +60,10 @@
 				  (cam->addr[4]		<< 16)	|
 				  (cam->addr[5]		<< 24);
 			break;
+		case 6:
+		case 7:
+			content = 0;
+			break;
 		default:
 			j = (i - 2) << 2;
 			content = (key->key[j])			|
@@ -96,6 +100,27 @@
 	rtw_write32(rtwdev, RTW_SEC_CMD_REG, command);
 }
 
+u8 rtw_sec_cam_pg_backup(struct rtw_dev *rtwdev, u8 *used_cam)
+{
+	struct rtw_sec_desc *sec = &rtwdev->sec;
+	u8 offset = 0;
+	u8 count, n;
+
+	if (!used_cam)
+		return 0;
+
+	for (count = 0; count < MAX_PG_CAM_BACKUP_NUM; count++) {
+		n = find_next_bit(sec->cam_map, RTW_MAX_SEC_CAM_NUM, offset);
+		if (n == RTW_MAX_SEC_CAM_NUM)
+			break;
+
+		used_cam[count] = n;
+		offset = n + 1;
+	}
+
+	return count;
+}
+
 void rtw_sec_enable_sec_engine(struct rtw_dev *rtwdev)
 {
 	struct rtw_sec_desc *sec = &rtwdev->sec;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/sec.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/sec.h
@@ -34,6 +34,7 @@
 void rtw_sec_clear_cam(struct rtw_dev *rtwdev,
 		       struct rtw_sec_desc *sec,
 		       u8 hw_key_idx);
+u8 rtw_sec_cam_pg_backup(struct rtw_dev *rtwdev, u8 *used_cam);
 void rtw_sec_enable_sec_engine(struct rtw_dev *rtwdev);
 
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/tx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/tx.c
@@ -6,6 +6,7 @@
 #include "tx.h"
 #include "fw.h"
 #include "ps.h"
+#include "debug.h"
 
 static
 void rtw_tx_stats(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
@@ -27,8 +28,6 @@
 			rtwvif = (struct rtw_vif *)vif->drv_priv;
 			rtwvif->stats.tx_unicast += skb->len;
 			rtwvif->stats.tx_cnt++;
-			if (rtwvif->stats.tx_cnt > RTW_LPS_THRESHOLD)
-				rtw_leave_lps_irqsafe(rtwdev, rtwvif);
 		}
 	}
 }
@@ -58,6 +57,13 @@
 	SET_TX_DESC_DATA_SHORT(txdesc, pkt_info->short_gi);
 	SET_TX_DESC_SPE_RPT(txdesc, pkt_info->report);
 	SET_TX_DESC_SW_DEFINE(txdesc, pkt_info->sn);
+	SET_TX_DESC_USE_RTS(txdesc, pkt_info->rts);
+	SET_TX_DESC_NAVUSEHDR(txdesc, pkt_info->nav_use_hdr);
+	SET_TX_DESC_DISQSELSEQ(txdesc, pkt_info->dis_qselseq);
+	SET_TX_DESC_EN_HWSEQ(txdesc, pkt_info->en_hwseq);
+	SET_TX_DESC_EN_HWEXSEQ(txdesc, pkt_info->en_hw_exseq);
+	SET_TX_DESC_HW_SSN_SEL(txdesc, pkt_info->hw_ssn_sel);
+	SET_TX_DESC_BT_NULL(txdesc, pkt_info->bt_null);
 }
 EXPORT_SYMBOL(rtw_tx_fill_tx_desc);
 
@@ -153,7 +159,7 @@
 	if (skb_queue_len(&tx_report->queue) == 0)
 		return;
 
-	WARN(1, "purge skb(s) not reported by firmware\n");
+	rtw_dbg(rtwdev, RTW_DBG_TX, "purge skb(s) not reported by firmware\n");
 
 	spin_lock_irqsave(&tx_report->q_lock, flags);
 	skb_queue_purge(&tx_report->queue);
@@ -193,7 +199,7 @@
 	ieee80211_tx_status_irqsafe(rtwdev->hw, skb);
 }
 
-void rtw_tx_report_handle(struct rtw_dev *rtwdev, struct sk_buff *skb)
+void rtw_tx_report_handle(struct rtw_dev *rtwdev, struct sk_buff *skb, int src)
 {
 	struct rtw_tx_report *tx_report = &rtwdev->tx_report;
 	struct rtw_c2h_cmd *c2h;
@@ -204,8 +210,13 @@
 
 	c2h = get_c2h_from_skb(skb);
 
-	sn = GET_CCX_REPORT_SEQNUM(c2h->payload);
-	st = GET_CCX_REPORT_STATUS(c2h->payload);
+	if (src == C2H_CCX_TX_RPT) {
+		sn = GET_CCX_REPORT_SEQNUM_V0(c2h->payload);
+		st = GET_CCX_REPORT_STATUS_V0(c2h->payload);
+	} else {
+		sn = GET_CCX_REPORT_SEQNUM_V1(c2h->payload);
+		st = GET_CCX_REPORT_STATUS_V1(c2h->payload);
+	}
 
 	spin_lock_irqsave(&tx_report->q_lock, flags);
 	skb_queue_walk_safe(&tx_report->queue, cur, tmp) {
@@ -219,16 +230,62 @@
 	spin_unlock_irqrestore(&tx_report->q_lock, flags);
 }
 
-static void rtw_tx_mgmt_pkt_info_update(struct rtw_dev *rtwdev,
+static void rtw_tx_pkt_info_update_rate(struct rtw_dev *rtwdev,
 					struct rtw_tx_pkt_info *pkt_info,
-					struct ieee80211_tx_control *control,
 					struct sk_buff *skb)
 {
+	if (rtwdev->hal.current_band_type == RTW_BAND_2G) {
+		pkt_info->rate_id = RTW_RATEID_B_20M;
+		pkt_info->rate = DESC_RATE1M;
+	} else {
+		pkt_info->rate_id = RTW_RATEID_G;
+		pkt_info->rate = DESC_RATE6M;
+	}
+
 	pkt_info->use_rate = true;
-	pkt_info->rate_id = 6;
 	pkt_info->dis_rate_fallback = true;
 }
 
+static void rtw_tx_pkt_info_update_sec(struct rtw_dev *rtwdev,
+				       struct rtw_tx_pkt_info *pkt_info,
+				       struct sk_buff *skb)
+{
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	u8 sec_type = 0;
+
+	if (info && info->control.hw_key) {
+		struct ieee80211_key_conf *key = info->control.hw_key;
+
+		switch (key->cipher) {
+		case WLAN_CIPHER_SUITE_WEP40:
+		case WLAN_CIPHER_SUITE_WEP104:
+		case WLAN_CIPHER_SUITE_TKIP:
+			sec_type = 0x01;
+			break;
+		case WLAN_CIPHER_SUITE_CCMP:
+			sec_type = 0x03;
+			break;
+		default:
+			break;
+		}
+	}
+
+	pkt_info->sec_type = sec_type;
+}
+
+static void rtw_tx_mgmt_pkt_info_update(struct rtw_dev *rtwdev,
+					struct rtw_tx_pkt_info *pkt_info,
+					struct ieee80211_tx_control *control,
+					struct sk_buff *skb)
+{
+	rtw_tx_pkt_info_update_rate(rtwdev, pkt_info, skb);
+	pkt_info->dis_qselseq = true;
+	pkt_info->en_hwseq = true;
+	pkt_info->hw_ssn_sel = 0;
+	pkt_info->en_hw_exseq = false;
+	/* TODO: need to change hw port and hw ssn sel for multiple vifs */
+}
+
 static void rtw_tx_data_pkt_info_update(struct rtw_dev *rtwdev,
 					struct rtw_tx_pkt_info *pkt_info,
 					struct ieee80211_tx_control *control,
@@ -260,6 +317,9 @@
 		ampdu_density = get_tx_ampdu_density(sta);
 	}
 
+	if (info->control.use_rts)
+		pkt_info->rts = true;
+
 	if (sta->vht_cap.vht_supported)
 		rate = get_highest_vht_tx_rate(rtwdev, sta);
 	else if (sta->ht_cap.ht_supported)
@@ -299,7 +359,6 @@
 	struct rtw_sta_info *si;
 	struct ieee80211_vif *vif = NULL;
 	__le16 fc = hdr->frame_control;
-	u8 sec_type = 0;
 	bool bmc;
 
 	if (control->sta) {
@@ -312,23 +371,6 @@
 	else if (ieee80211_is_data(fc))
 		rtw_tx_data_pkt_info_update(rtwdev, pkt_info, control, skb);
 
-	if (info->control.hw_key) {
-		struct ieee80211_key_conf *key = info->control.hw_key;
-
-		switch (key->cipher) {
-		case WLAN_CIPHER_SUITE_WEP40:
-		case WLAN_CIPHER_SUITE_WEP104:
-		case WLAN_CIPHER_SUITE_TKIP:
-			sec_type = 0x01;
-			break;
-		case WLAN_CIPHER_SUITE_CCMP:
-			sec_type = 0x03;
-			break;
-		default:
-			break;
-		}
-	}
-
 	bmc = is_broadcast_ether_addr(hdr->addr1) ||
 	      is_multicast_ether_addr(hdr->addr1);
 
@@ -336,7 +378,7 @@
 		rtw_tx_report_enable(rtwdev, pkt_info);
 
 	pkt_info->bmc = bmc;
-	pkt_info->sec_type = sec_type;
+	rtw_tx_pkt_info_update_sec(rtwdev, pkt_info, skb);
 	pkt_info->tx_pkt_size = skb->len;
 	pkt_info->offset = chip->tx_pkt_desc_sz;
 	pkt_info->qsel = skb->priority;
@@ -346,22 +388,222 @@
 	rtw_tx_stats(rtwdev, vif, skb);
 }
 
-void rtw_rsvd_page_pkt_info_update(struct rtw_dev *rtwdev,
-				   struct rtw_tx_pkt_info *pkt_info,
-				   struct sk_buff *skb)
+void rtw_tx_rsvd_page_pkt_info_update(struct rtw_dev *rtwdev,
+				      struct rtw_tx_pkt_info *pkt_info,
+				      struct sk_buff *skb,
+				      enum rtw_rsvd_packet_type type)
 {
 	struct rtw_chip_info *chip = rtwdev->chip;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 	bool bmc;
 
+	/* A beacon or dummy reserved page packet indicates that it is the first
+	 * reserved page, and the qsel of it will be set in each hci.
+	 */
+	if (type != RSVD_BEACON && type != RSVD_DUMMY)
+		pkt_info->qsel = TX_DESC_QSEL_MGMT;
+
+	rtw_tx_pkt_info_update_rate(rtwdev, pkt_info, skb);
+
 	bmc = is_broadcast_ether_addr(hdr->addr1) ||
 	      is_multicast_ether_addr(hdr->addr1);
-	pkt_info->use_rate = true;
-	pkt_info->rate_id = 6;
-	pkt_info->dis_rate_fallback = true;
 	pkt_info->bmc = bmc;
 	pkt_info->tx_pkt_size = skb->len;
 	pkt_info->offset = chip->tx_pkt_desc_sz;
-	pkt_info->qsel = TX_DESC_QSEL_MGMT;
 	pkt_info->ls = true;
+	if (type == RSVD_PS_POLL) {
+		pkt_info->nav_use_hdr = true;
+	} else {
+		pkt_info->dis_qselseq = true;
+		pkt_info->en_hwseq = true;
+		pkt_info->hw_ssn_sel = 0;
+		pkt_info->en_hw_exseq = false;
+	}
+	if (type == RSVD_QOS_NULL)
+		pkt_info->bt_null = true;
+
+	rtw_tx_pkt_info_update_sec(rtwdev, pkt_info, skb);
+
+	/* TODO: need to change hw port and hw ssn sel for multiple vifs */
+}
+
+struct sk_buff *
+rtw_tx_write_data_rsvd_page_get(struct rtw_dev *rtwdev,
+				struct rtw_tx_pkt_info *pkt_info,
+				u8 *buf, u32 size)
+{
+	struct rtw_chip_info *chip = rtwdev->chip;
+	struct sk_buff *skb;
+	u32 tx_pkt_desc_sz;
+	u32 length;
+
+	tx_pkt_desc_sz = chip->tx_pkt_desc_sz;
+	length = size + tx_pkt_desc_sz;
+	skb = dev_alloc_skb(length);
+	if (!skb) {
+		rtw_err(rtwdev, "failed to alloc write data rsvd page skb\n");
+		return NULL;
+	}
+
+	skb_reserve(skb, tx_pkt_desc_sz);
+	skb_put_data(skb, buf, size);
+	rtw_tx_rsvd_page_pkt_info_update(rtwdev, pkt_info, skb, RSVD_BEACON);
+
+	return skb;
+}
+EXPORT_SYMBOL(rtw_tx_write_data_rsvd_page_get);
+
+struct sk_buff *
+rtw_tx_write_data_h2c_get(struct rtw_dev *rtwdev,
+			  struct rtw_tx_pkt_info *pkt_info,
+			  u8 *buf, u32 size)
+{
+	struct rtw_chip_info *chip = rtwdev->chip;
+	struct sk_buff *skb;
+	u32 tx_pkt_desc_sz;
+	u32 length;
+
+	tx_pkt_desc_sz = chip->tx_pkt_desc_sz;
+	length = size + tx_pkt_desc_sz;
+	skb = dev_alloc_skb(length);
+	if (!skb) {
+		rtw_err(rtwdev, "failed to alloc write data h2c skb\n");
+		return NULL;
+	}
+
+	skb_reserve(skb, tx_pkt_desc_sz);
+	skb_put_data(skb, buf, size);
+	pkt_info->tx_pkt_size = size;
+
+	return skb;
+}
+EXPORT_SYMBOL(rtw_tx_write_data_h2c_get);
+
+void rtw_tx(struct rtw_dev *rtwdev,
+	    struct ieee80211_tx_control *control,
+	    struct sk_buff *skb)
+{
+	struct rtw_tx_pkt_info pkt_info = {0};
+
+	rtw_tx_pkt_info_update(rtwdev, &pkt_info, control, skb);
+	if (rtw_hci_tx(rtwdev, &pkt_info, skb))
+		goto out;
+
+	return;
+
+out:
+	ieee80211_free_txskb(rtwdev->hw, skb);
+}
+
+static void rtw_txq_check_agg(struct rtw_dev *rtwdev,
+			      struct rtw_txq *rtwtxq,
+			      struct sk_buff *skb)
+{
+	struct ieee80211_txq *txq = rtwtxq_to_txq(rtwtxq);
+	struct ieee80211_tx_info *info;
+	struct rtw_sta_info *si;
+
+	if (test_bit(RTW_TXQ_AMPDU, &rtwtxq->flags)) {
+		info = IEEE80211_SKB_CB(skb);
+		info->flags |= IEEE80211_TX_CTL_AMPDU;
+		return;
+	}
+
+	if (skb_get_queue_mapping(skb) == IEEE80211_AC_VO)
+		return;
+
+	if (test_bit(RTW_TXQ_BLOCK_BA, &rtwtxq->flags))
+		return;
+
+	if (unlikely(skb->protocol == cpu_to_be16(ETH_P_PAE)))
+		return;
+
+	if (!txq->sta)
+		return;
+
+	si = (struct rtw_sta_info *)txq->sta->drv_priv;
+	set_bit(txq->tid, si->tid_ba);
+
+	ieee80211_queue_work(rtwdev->hw, &rtwdev->ba_work);
+}
+
+static bool rtw_txq_dequeue(struct rtw_dev *rtwdev,
+			    struct rtw_txq *rtwtxq)
+{
+	struct ieee80211_txq *txq = rtwtxq_to_txq(rtwtxq);
+	struct ieee80211_tx_control control;
+	struct sk_buff *skb;
+
+	skb = ieee80211_tx_dequeue(rtwdev->hw, txq);
+	if (!skb)
+		return false;
+
+	rtw_txq_check_agg(rtwdev, rtwtxq, skb);
+
+	control.sta = txq->sta;
+	rtw_tx(rtwdev, &control, skb);
+	rtwtxq->last_push = jiffies;
+
+	return true;
+}
+
+static void rtw_txq_push(struct rtw_dev *rtwdev,
+			 struct rtw_txq *rtwtxq,
+			 unsigned long frames)
+{
+	int i;
+
+	rcu_read_lock();
+
+	for (i = 0; i < frames; i++)
+		if (!rtw_txq_dequeue(rtwdev, rtwtxq))
+			break;
+
+	rcu_read_unlock();
+}
+
+void rtw_tx_tasklet(unsigned long data)
+{
+	struct rtw_dev *rtwdev = (void *)data;
+	struct rtw_txq *rtwtxq, *tmp;
+
+	spin_lock_bh(&rtwdev->txq_lock);
+
+	list_for_each_entry_safe(rtwtxq, tmp, &rtwdev->txqs, list) {
+		struct ieee80211_txq *txq = rtwtxq_to_txq(rtwtxq);
+		unsigned long frame_cnt;
+		unsigned long byte_cnt;
+
+		ieee80211_txq_get_depth(txq, &frame_cnt, &byte_cnt);
+		rtw_txq_push(rtwdev, rtwtxq, frame_cnt);
+
+		list_del_init(&rtwtxq->list);
+	}
+
+	spin_unlock_bh(&rtwdev->txq_lock);
+}
+
+void rtw_txq_init(struct rtw_dev *rtwdev, struct ieee80211_txq *txq)
+{
+	struct rtw_txq *rtwtxq;
+
+	if (!txq)
+		return;
+
+	rtwtxq = (struct rtw_txq *)txq->drv_priv;
+	INIT_LIST_HEAD(&rtwtxq->list);
+}
+
+void rtw_txq_cleanup(struct rtw_dev *rtwdev, struct ieee80211_txq *txq)
+{
+	struct rtw_txq *rtwtxq;
+
+	if (!txq)
+		return;
+
+	rtwtxq = (struct rtw_txq *)txq->drv_priv;
+	spin_lock_bh(&rtwdev->txq_lock);
+	if (!list_empty(&rtwtxq->list))
+		list_del_init(&rtwtxq->list);
+	spin_unlock_bh(&rtwdev->txq_lock);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/tx.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/tx.h
@@ -35,6 +35,8 @@
 	le32p_replace_bits((__le32 *)(txdesc) + 0x09, value, GENMASK(23, 12))
 #define SET_TX_DESC_MAX_AGG_NUM(txdesc, value)                                 \
 	le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, GENMASK(21, 17))
+#define SET_TX_DESC_USE_RTS(tx_desc, value)                                    \
+	le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, BIT(12))
 #define SET_TX_DESC_AMPDU_DENSITY(txdesc, value)                               \
 	le32p_replace_bits((__le32 *)(txdesc) + 0x02, value, GENMASK(22, 20))
 #define SET_TX_DESC_DATA_STBC(txdesc, value)                                   \
@@ -51,6 +53,18 @@
 	le32p_replace_bits((__le32 *)(txdesc) + 0x02, value, BIT(19))
 #define SET_TX_DESC_SW_DEFINE(tx_desc, value)                                  \
 	le32p_replace_bits((__le32 *)(txdesc) + 0x06, value, GENMASK(11, 0))
+#define SET_TX_DESC_NAVUSEHDR(txdesc, value)				       \
+	le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, BIT(15))
+#define SET_TX_DESC_DISQSELSEQ(txdesc, value)				       \
+	le32p_replace_bits((__le32 *)(txdesc) + 0x00, value, BIT(31))
+#define SET_TX_DESC_EN_HWSEQ(txdesc, value)				       \
+	le32p_replace_bits((__le32 *)(txdesc) + 0x08, value, BIT(15))
+#define SET_TX_DESC_EN_HWEXSEQ(txdesc, value)				       \
+	le32p_replace_bits((__le32 *)(txdesc) + 0x08, value, BIT(14))
+#define SET_TX_DESC_HW_SSN_SEL(txdesc, value)				       \
+	le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, GENMASK(7, 6))
+#define SET_TX_DESC_BT_NULL(txdesc, value)				       \
+	le32p_replace_bits((__le32 *)(txdesc) + 0x02, value, BIT(23))
 
 enum rtw_tx_desc_queue_select {
 	TX_DESC_QSEL_TID0	= 0,
@@ -75,15 +89,32 @@
 	TX_DESC_QSEL_H2C	= 19,
 };
 
+enum rtw_rsvd_packet_type;
+
+void rtw_tx(struct rtw_dev *rtwdev,
+	    struct ieee80211_tx_control *control,
+	    struct sk_buff *skb);
+void rtw_txq_init(struct rtw_dev *rtwdev, struct ieee80211_txq *txq);
+void rtw_txq_cleanup(struct rtw_dev *rtwdev, struct ieee80211_txq *txq);
+void rtw_tx_tasklet(unsigned long data);
 void rtw_tx_pkt_info_update(struct rtw_dev *rtwdev,
 			    struct rtw_tx_pkt_info *pkt_info,
 			    struct ieee80211_tx_control *control,
 			    struct sk_buff *skb);
 void rtw_tx_fill_tx_desc(struct rtw_tx_pkt_info *pkt_info, struct sk_buff *skb);
 void rtw_tx_report_enqueue(struct rtw_dev *rtwdev, struct sk_buff *skb, u8 sn);
-void rtw_tx_report_handle(struct rtw_dev *rtwdev, struct sk_buff *skb);
-void rtw_rsvd_page_pkt_info_update(struct rtw_dev *rtwdev,
-				   struct rtw_tx_pkt_info *pkt_info,
-				   struct sk_buff *skb);
+void rtw_tx_report_handle(struct rtw_dev *rtwdev, struct sk_buff *skb, int src);
+void rtw_tx_rsvd_page_pkt_info_update(struct rtw_dev *rtwdev,
+				      struct rtw_tx_pkt_info *pkt_info,
+				      struct sk_buff *skb,
+				      enum rtw_rsvd_packet_type type);
+struct sk_buff *
+rtw_tx_write_data_rsvd_page_get(struct rtw_dev *rtwdev,
+				struct rtw_tx_pkt_info *pkt_info,
+				u8 *buf, u32 size);
+struct sk_buff *
+rtw_tx_write_data_h2c_get(struct rtw_dev *rtwdev,
+			  struct rtw_tx_pkt_info *pkt_info,
+			  u8 *buf, u32 size);
 
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/util.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/util.c
@@ -22,22 +22,28 @@
 
 bool ltecoex_read_reg(struct rtw_dev *rtwdev, u16 offset, u32 *val)
 {
-	if (!check_hw_ready(rtwdev, LTECOEX_ACCESS_CTRL, LTECOEX_READY, 1))
+	struct rtw_chip_info *chip = rtwdev->chip;
+	struct rtw_ltecoex_addr *ltecoex = chip->ltecoex_addr;
+
+	if (!check_hw_ready(rtwdev, ltecoex->ctrl, LTECOEX_READY, 1))
 		return false;
 
-	rtw_write32(rtwdev, LTECOEX_ACCESS_CTRL, 0x800F0000 | offset);
-	*val = rtw_read32(rtwdev, LTECOEX_READ_DATA);
+	rtw_write32(rtwdev, ltecoex->ctrl, 0x800F0000 | offset);
+	*val = rtw_read32(rtwdev, ltecoex->rdata);
 
 	return true;
 }
 
 bool ltecoex_reg_write(struct rtw_dev *rtwdev, u16 offset, u32 value)
 {
-	if (!check_hw_ready(rtwdev, LTECOEX_ACCESS_CTRL, LTECOEX_READY, 1))
+	struct rtw_chip_info *chip = rtwdev->chip;
+	struct rtw_ltecoex_addr *ltecoex = chip->ltecoex_addr;
+
+	if (!check_hw_ready(rtwdev, ltecoex->ctrl, LTECOEX_READY, 1))
 		return false;
 
-	rtw_write32(rtwdev, LTECOEX_WRITE_DATA, value);
-	rtw_write32(rtwdev, LTECOEX_ACCESS_CTRL, 0xC00F0000 | offset);
+	rtw_write32(rtwdev, ltecoex->wdata, value);
+	rtw_write32(rtwdev, ltecoex->ctrl, 0xC00F0000 | offset);
 
 	return true;
 }
@@ -70,3 +76,30 @@
 		}
 	}
 }
+
+void rtw_desc_to_mcsrate(u16 rate, u8 *mcs, u8 *nss)
+{
+	if (rate <= DESC_RATE54M)
+		return;
+
+	if (rate >= DESC_RATEVHT1SS_MCS0 &&
+	    rate <= DESC_RATEVHT1SS_MCS9) {
+		*nss = 1;
+		*mcs = rate - DESC_RATEVHT1SS_MCS0;
+	} else if (rate >= DESC_RATEVHT2SS_MCS0 &&
+		   rate <= DESC_RATEVHT2SS_MCS9) {
+		*nss = 2;
+		*mcs = rate - DESC_RATEVHT2SS_MCS0;
+	} else if (rate >= DESC_RATEVHT3SS_MCS0 &&
+		   rate <= DESC_RATEVHT3SS_MCS9) {
+		*nss = 3;
+		*mcs = rate - DESC_RATEVHT3SS_MCS0;
+	} else if (rate >= DESC_RATEVHT4SS_MCS0 &&
+		   rate <= DESC_RATEVHT4SS_MCS9) {
+		*nss = 4;
+		*mcs = rate - DESC_RATEVHT4SS_MCS0;
+	} else if (rate >= DESC_RATEMCS0 &&
+		   rate <= DESC_RATEMCS15) {
+		*mcs = rate - DESC_RATEMCS0;
+	}
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/util.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/util.h
@@ -15,6 +15,8 @@
 			IEEE80211_IFACE_ITER_NORMAL, iterator, data)
 #define rtw_iterate_stas_atomic(rtwdev, iterator, data)                        \
 	ieee80211_iterate_stations_atomic(rtwdev->hw, iterator, data)
+#define rtw_iterate_keys(rtwdev, vif, iterator, data)			       \
+	ieee80211_iter_keys(rtwdev->hw, vif, iterator, data)
 
 static inline u8 *get_hdr_bssid(struct ieee80211_hdr *hdr)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/wow.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/wow.c
@@ -0,0 +1,882 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2018-2019  Realtek Corporation
+ */
+
+#include "main.h"
+#include "fw.h"
+#include "wow.h"
+#include "reg.h"
+#include "debug.h"
+#include "mac.h"
+#include "ps.h"
+
+static void rtw_wow_show_wakeup_reason(struct rtw_dev *rtwdev)
+{
+	u8 reason;
+
+	reason = rtw_read8(rtwdev, REG_WOWLAN_WAKE_REASON);
+
+	if (reason == RTW_WOW_RSN_RX_DEAUTH)
+		rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: Rx deauth\n");
+	else if (reason == RTW_WOW_RSN_DISCONNECT)
+		rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: AP is off\n");
+	else if (reason == RTW_WOW_RSN_RX_MAGIC_PKT)
+		rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: Rx magic packet\n");
+	else if (reason == RTW_WOW_RSN_RX_GTK_REKEY)
+		rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: Rx gtk rekey\n");
+	else if (reason == RTW_WOW_RSN_RX_PTK_REKEY)
+		rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: Rx ptk rekey\n");
+	else if (reason == RTW_WOW_RSN_RX_PATTERN_MATCH)
+		rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: Rx pattern match packet\n");
+	else if (reason == RTW_WOW_RSN_RX_NLO)
+		rtw_dbg(rtwdev, RTW_DBG_WOW, "Rx NLO\n");
+	else
+		rtw_warn(rtwdev, "Unknown wakeup reason %x\n", reason);
+}
+
+static void rtw_wow_pattern_write_cam(struct rtw_dev *rtwdev, u8 addr,
+				      u32 wdata)
+{
+	rtw_write32(rtwdev, REG_WKFMCAM_RWD, wdata);
+	rtw_write32(rtwdev, REG_WKFMCAM_CMD, BIT_WKFCAM_POLLING_V1 |
+		    BIT_WKFCAM_WE | BIT_WKFCAM_ADDR_V2(addr));
+
+	if (!check_hw_ready(rtwdev, REG_WKFMCAM_CMD, BIT_WKFCAM_POLLING_V1, 0))
+		rtw_err(rtwdev, "failed to write pattern cam\n");
+}
+
+static void rtw_wow_pattern_write_cam_ent(struct rtw_dev *rtwdev, u8 id,
+					  struct rtw_wow_pattern *rtw_pattern)
+{
+	int i;
+	u8 addr;
+	u32 wdata;
+
+	for (i = 0; i < RTW_MAX_PATTERN_MASK_SIZE / 4; i++) {
+		addr = (id << 3) + i;
+		wdata = rtw_pattern->mask[i * 4];
+		wdata |= rtw_pattern->mask[i * 4 + 1] << 8;
+		wdata |= rtw_pattern->mask[i * 4 + 2] << 16;
+		wdata |= rtw_pattern->mask[i * 4 + 3] << 24;
+		rtw_wow_pattern_write_cam(rtwdev, addr, wdata);
+	}
+
+	wdata = rtw_pattern->crc;
+	addr = (id << 3) + RTW_MAX_PATTERN_MASK_SIZE / 4;
+
+	switch (rtw_pattern->type) {
+	case RTW_PATTERN_BROADCAST:
+		wdata |= BIT_WKFMCAM_BC | BIT_WKFMCAM_VALID;
+		break;
+	case RTW_PATTERN_MULTICAST:
+		wdata |= BIT_WKFMCAM_MC | BIT_WKFMCAM_VALID;
+		break;
+	case RTW_PATTERN_UNICAST:
+		wdata |= BIT_WKFMCAM_UC | BIT_WKFMCAM_VALID;
+		break;
+	default:
+		break;
+	}
+	rtw_wow_pattern_write_cam(rtwdev, addr, wdata);
+}
+
+/* RTK internal CRC16 for Pattern Cam */
+static u16 __rtw_cal_crc16(u8 data, u16 crc)
+{
+	u8 shift_in, data_bit;
+	u8 crc_bit4, crc_bit11, crc_bit15;
+	u16 crc_result;
+	int index;
+
+	for (index = 0; index < 8; index++) {
+		crc_bit15 = ((crc & BIT(15)) ? 1 : 0);
+		data_bit = (data & (BIT(0) << index) ? 1 : 0);
+		shift_in = crc_bit15 ^ data_bit;
+
+		crc_result = crc << 1;
+
+		if (shift_in == 0)
+			crc_result &= (~BIT(0));
+		else
+			crc_result |= BIT(0);
+
+		crc_bit11 = ((crc & BIT(11)) ? 1 : 0) ^ shift_in;
+
+		if (crc_bit11 == 0)
+			crc_result &= (~BIT(12));
+		else
+			crc_result |= BIT(12);
+
+		crc_bit4 = ((crc & BIT(4)) ? 1 : 0) ^ shift_in;
+
+		if (crc_bit4 == 0)
+			crc_result &= (~BIT(5));
+		else
+			crc_result |= BIT(5);
+
+		crc = crc_result;
+	}
+	return crc;
+}
+
+static u16 rtw_calc_crc(u8 *pdata, int length)
+{
+	u16 crc = 0xffff;
+	int i;
+
+	for (i = 0; i < length; i++)
+		crc = __rtw_cal_crc16(pdata[i], crc);
+
+	/* get 1' complement */
+	return ~crc;
+}
+
+static void rtw_wow_pattern_generate(struct rtw_dev *rtwdev,
+				     struct rtw_vif *rtwvif,
+				     const struct cfg80211_pkt_pattern *pkt_pattern,
+				     struct rtw_wow_pattern *rtw_pattern)
+{
+	const u8 *mask;
+	const u8 *pattern;
+	u8 mask_hw[RTW_MAX_PATTERN_MASK_SIZE] = {0};
+	u8 content[RTW_MAX_PATTERN_SIZE] = {0};
+	u8 mac_addr[ETH_ALEN] = {0};
+	u8 mask_len;
+	u16 count;
+	int len;
+	int i;
+
+	pattern = pkt_pattern->pattern;
+	len = pkt_pattern->pattern_len;
+	mask = pkt_pattern->mask;
+
+	ether_addr_copy(mac_addr, rtwvif->mac_addr);
+	memset(rtw_pattern, 0, sizeof(*rtw_pattern));
+
+	mask_len = DIV_ROUND_UP(len, 8);
+
+	if (is_broadcast_ether_addr(pattern))
+		rtw_pattern->type = RTW_PATTERN_BROADCAST;
+	else if (is_multicast_ether_addr(pattern))
+		rtw_pattern->type = RTW_PATTERN_MULTICAST;
+	else if (ether_addr_equal(pattern, mac_addr))
+		rtw_pattern->type = RTW_PATTERN_UNICAST;
+	else
+		rtw_pattern->type = RTW_PATTERN_INVALID;
+
+	/* translate mask from os to mask for hw
+	 * pattern from OS uses 'ethenet frame', like this:
+	 * |    6   |    6   |   2  |     20    |  Variable  |  4  |
+	 * |--------+--------+------+-----------+------------+-----|
+	 * |    802.3 Mac Header    | IP Header | TCP Packet | FCS |
+	 * |   DA   |   SA   | Type |
+	 *
+	 * BUT, packet catched by our HW is in '802.11 frame', begin from LLC
+	 * |     24 or 30      |    6   |   2  |     20    |  Variable  |  4  |
+	 * |-------------------+--------+------+-----------+------------+-----|
+	 * | 802.11 MAC Header |       LLC     | IP Header | TCP Packet | FCS |
+	 *		       | Others | Tpye |
+	 *
+	 * Therefore, we need translate mask_from_OS to mask_to_hw.
+	 * We should left-shift mask by 6 bits, then set the new bit[0~5] = 0,
+	 * because new mask[0~5] means 'SA', but our HW packet begins from LLC,
+	 * bit[0~5] corresponds to first 6 Bytes in LLC, they just don't match.
+	 */
+
+	/* Shift 6 bits */
+	for (i = 0; i < mask_len - 1; i++) {
+		mask_hw[i] = u8_get_bits(mask[i], GENMASK(7, 6));
+		mask_hw[i] |= u8_get_bits(mask[i + 1], GENMASK(5, 0)) << 2;
+	}
+	mask_hw[i] = u8_get_bits(mask[i], GENMASK(7, 6));
+
+	/* Set bit 0-5 to zero */
+	mask_hw[0] &= (~GENMASK(5, 0));
+
+	memcpy(rtw_pattern->mask, mask_hw, RTW_MAX_PATTERN_MASK_SIZE);
+
+	/* To get the wake up pattern from the mask.
+	 * We do not count first 12 bits which means
+	 * DA[6] and SA[6] in the pattern to match HW design.
+	 */
+	count = 0;
+	for (i = 12; i < len; i++) {
+		if ((mask[i / 8] >> (i % 8)) & 0x01) {
+			content[count] = pattern[i];
+			count++;
+		}
+	}
+
+	rtw_pattern->crc = rtw_calc_crc(content, count);
+}
+
+static void rtw_wow_pattern_clear_cam(struct rtw_dev *rtwdev)
+{
+	bool ret;
+
+	rtw_write32(rtwdev, REG_WKFMCAM_CMD, BIT_WKFCAM_POLLING_V1 |
+		    BIT_WKFCAM_CLR_V1);
+
+	ret = check_hw_ready(rtwdev, REG_WKFMCAM_CMD, BIT_WKFCAM_POLLING_V1, 0);
+	if (!ret)
+		rtw_err(rtwdev, "failed to clean pattern cam\n");
+}
+
+static void rtw_wow_pattern_write(struct rtw_dev *rtwdev)
+{
+	struct rtw_wow_param *rtw_wow = &rtwdev->wow;
+	struct rtw_wow_pattern *rtw_pattern = rtw_wow->patterns;
+	int i = 0;
+
+	for (i = 0; i < rtw_wow->pattern_cnt; i++)
+		rtw_wow_pattern_write_cam_ent(rtwdev, i, rtw_pattern + i);
+}
+
+static void rtw_wow_pattern_clear(struct rtw_dev *rtwdev)
+{
+	struct rtw_wow_param *rtw_wow = &rtwdev->wow;
+
+	rtw_wow_pattern_clear_cam(rtwdev);
+
+	rtw_wow->pattern_cnt = 0;
+	memset(rtw_wow->patterns, 0, sizeof(rtw_wow->patterns));
+}
+
+static void rtw_wow_bb_stop(struct rtw_dev *rtwdev)
+{
+	struct rtw_wow_param *rtw_wow = &rtwdev->wow;
+
+	/* wait 100ms for firmware to finish TX */
+	msleep(100);
+
+	if (!rtw_read32_mask(rtwdev, REG_BCNQ_INFO, BIT_MGQ_CPU_EMPTY))
+		rtw_warn(rtwdev, "Wrong status of MGQ_CPU empty!\n");
+
+	rtw_wow->txpause = rtw_read8(rtwdev, REG_TXPAUSE);
+	rtw_write8(rtwdev, REG_TXPAUSE, 0xff);
+	rtw_write8_clr(rtwdev, REG_SYS_FUNC_EN, BIT_FEN_BB_RSTB);
+}
+
+static void rtw_wow_bb_start(struct rtw_dev *rtwdev)
+{
+	struct rtw_wow_param *rtw_wow = &rtwdev->wow;
+
+	rtw_write8_set(rtwdev, REG_SYS_FUNC_EN, BIT_FEN_BB_RSTB);
+	rtw_write8(rtwdev, REG_TXPAUSE, rtw_wow->txpause);
+}
+
+static void rtw_wow_rx_dma_stop(struct rtw_dev *rtwdev)
+{
+	/* wait 100ms for HW to finish rx dma */
+	msleep(100);
+
+	rtw_write32_set(rtwdev, REG_RXPKT_NUM, BIT_RW_RELEASE);
+
+	if (!check_hw_ready(rtwdev, REG_RXPKT_NUM, BIT_RXDMA_IDLE, 1))
+		rtw_err(rtwdev, "failed to stop rx dma\n");
+}
+
+static void rtw_wow_rx_dma_start(struct rtw_dev *rtwdev)
+{
+	rtw_write32_clr(rtwdev, REG_RXPKT_NUM, BIT_RW_RELEASE);
+}
+
+static int rtw_wow_check_fw_status(struct rtw_dev *rtwdev, bool wow_enable)
+{
+	/* wait 100ms for wow firmware to finish work */
+	msleep(100);
+
+	if (wow_enable) {
+		if (rtw_read8(rtwdev, REG_WOWLAN_WAKE_REASON))
+			goto wow_fail;
+	} else {
+		if (rtw_read32_mask(rtwdev, REG_FE1IMR, BIT_FS_RXDONE) ||
+		    rtw_read32_mask(rtwdev, REG_RXPKT_NUM, BIT_RW_RELEASE))
+			goto wow_fail;
+	}
+
+	return 0;
+
+wow_fail:
+	rtw_err(rtwdev, "failed to check wow status %s\n",
+		wow_enable ? "enabled" : "disabled");
+	return -EBUSY;
+}
+
+static void rtw_wow_fw_security_type_iter(struct ieee80211_hw *hw,
+					  struct ieee80211_vif *vif,
+					  struct ieee80211_sta *sta,
+					  struct ieee80211_key_conf *key,
+					  void *data)
+{
+	struct rtw_fw_key_type_iter_data *iter_data = data;
+	struct rtw_dev *rtwdev = hw->priv;
+	u8 hw_key_type;
+
+	if (vif != rtwdev->wow.wow_vif)
+		return;
+
+	switch (key->cipher) {
+	case WLAN_CIPHER_SUITE_WEP40:
+		hw_key_type = RTW_CAM_WEP40;
+		break;
+	case WLAN_CIPHER_SUITE_WEP104:
+		hw_key_type = RTW_CAM_WEP104;
+		break;
+	case WLAN_CIPHER_SUITE_TKIP:
+		hw_key_type = RTW_CAM_TKIP;
+		key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
+		break;
+	case WLAN_CIPHER_SUITE_CCMP:
+		hw_key_type = RTW_CAM_AES;
+		key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
+		break;
+	default:
+		rtw_err(rtwdev, "Unsupported key type for wowlan mode\n");
+		hw_key_type = 0;
+		break;
+	}
+
+	if (sta)
+		iter_data->pairwise_key_type = hw_key_type;
+	else
+		iter_data->group_key_type = hw_key_type;
+}
+
+static void rtw_wow_fw_security_type(struct rtw_dev *rtwdev)
+{
+	struct rtw_fw_key_type_iter_data data = {};
+	struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
+
+	data.rtwdev = rtwdev;
+	rtw_iterate_keys(rtwdev, wow_vif,
+			 rtw_wow_fw_security_type_iter, &data);
+	rtw_fw_set_aoac_global_info_cmd(rtwdev, data.pairwise_key_type,
+					data.group_key_type);
+}
+
+static int rtw_wow_fw_start(struct rtw_dev *rtwdev)
+{
+	struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
+	struct rtw_vif *rtwvif = (struct rtw_vif *)wow_vif->drv_priv;
+
+	if (rtw_wow_mgd_linked(rtwdev)) {
+		rtw_send_rsvd_page_h2c(rtwdev);
+		rtw_wow_pattern_write(rtwdev);
+		rtw_wow_fw_security_type(rtwdev);
+		rtw_fw_set_disconnect_decision_cmd(rtwdev, true);
+		rtw_fw_set_keep_alive_cmd(rtwdev, true);
+	} else if (rtw_wow_no_link(rtwdev)) {
+		rtw_fw_set_nlo_info(rtwdev, true);
+		rtw_fw_update_pkt_probe_req(rtwdev, NULL);
+		rtw_fw_channel_switch(rtwdev, true);
+	}
+
+	rtw_fw_set_default_port(rtwdev, rtwvif->port);
+	rtw_fw_set_wowlan_ctrl_cmd(rtwdev, true);
+	rtw_fw_set_remote_wake_ctrl_cmd(rtwdev, true);
+
+	return rtw_wow_check_fw_status(rtwdev, true);
+}
+
+static int rtw_wow_fw_stop(struct rtw_dev *rtwdev)
+{
+	if (rtw_wow_mgd_linked(rtwdev)) {
+		rtw_fw_set_disconnect_decision_cmd(rtwdev, false);
+		rtw_fw_set_keep_alive_cmd(rtwdev, false);
+		rtw_wow_pattern_clear(rtwdev);
+	} else if (rtw_wow_no_link(rtwdev)) {
+		rtw_fw_channel_switch(rtwdev, false);
+		rtw_fw_set_nlo_info(rtwdev, false);
+	}
+
+	rtw_fw_set_wowlan_ctrl_cmd(rtwdev, false);
+	rtw_fw_set_remote_wake_ctrl_cmd(rtwdev, false);
+
+	return rtw_wow_check_fw_status(rtwdev, false);
+}
+
+static void rtw_wow_avoid_reset_mac(struct rtw_dev *rtwdev)
+{
+	/* When resuming from wowlan mode, some hosts issue signal
+	 * (PCIE: PREST, USB: SE0RST) to device, and lead to reset
+	 * mac core. If it happens, the connection to AP will be lost.
+	 * Setting REG_RSV_CTRL Register can avoid this process.
+	 */
+	switch (rtw_hci_type(rtwdev)) {
+	case RTW_HCI_TYPE_PCIE:
+	case RTW_HCI_TYPE_USB:
+		rtw_write8(rtwdev, REG_RSV_CTRL, BIT_WLOCK_1C_B6);
+		rtw_write8(rtwdev, REG_RSV_CTRL,
+			   BIT_WLOCK_1C_B6 | BIT_R_DIS_PRST);
+		break;
+	default:
+		rtw_warn(rtwdev, "Unsupported hci type to disable reset MAC\n");
+		break;
+	}
+}
+
+static void rtw_wow_fw_media_status_iter(void *data, struct ieee80211_sta *sta)
+{
+	struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
+	struct rtw_fw_media_status_iter_data *iter_data = data;
+	struct rtw_dev *rtwdev = iter_data->rtwdev;
+
+	rtw_fw_media_status_report(rtwdev, si->mac_id, iter_data->connect);
+}
+
+static void rtw_wow_fw_media_status(struct rtw_dev *rtwdev, bool connect)
+{
+	struct rtw_fw_media_status_iter_data data;
+
+	data.rtwdev = rtwdev;
+	data.connect = connect;
+
+	rtw_iterate_stas_atomic(rtwdev, rtw_wow_fw_media_status_iter, &data);
+}
+
+static void rtw_wow_config_pno_rsvd_page(struct rtw_dev *rtwdev,
+					 struct rtw_vif *rtwvif)
+{
+	rtw_add_rsvd_page_pno(rtwdev, rtwvif);
+}
+
+static void rtw_wow_config_linked_rsvd_page(struct rtw_dev *rtwdev,
+					   struct rtw_vif *rtwvif)
+{
+	rtw_add_rsvd_page_sta(rtwdev, rtwvif);
+}
+
+static void rtw_wow_config_rsvd_page(struct rtw_dev *rtwdev,
+				     struct rtw_vif *rtwvif)
+{
+	rtw_remove_rsvd_page(rtwdev, rtwvif);
+
+	if (rtw_wow_mgd_linked(rtwdev)) {
+		rtw_wow_config_linked_rsvd_page(rtwdev, rtwvif);
+	} else if (test_bit(RTW_FLAG_WOWLAN, rtwdev->flags) &&
+		   rtw_wow_no_link(rtwdev)) {
+		rtw_wow_config_pno_rsvd_page(rtwdev, rtwvif);
+	}
+}
+
+static int rtw_wow_dl_fw_rsvd_page(struct rtw_dev *rtwdev)
+{
+	struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
+	struct rtw_vif *rtwvif = (struct rtw_vif *)wow_vif->drv_priv;
+
+	rtw_wow_config_rsvd_page(rtwdev, rtwvif);
+
+	return rtw_fw_download_rsvd_page(rtwdev);
+}
+
+static int rtw_wow_swap_fw(struct rtw_dev *rtwdev, enum rtw_fw_type type)
+{
+	struct rtw_fw_state *fw;
+	int ret;
+
+	switch (type) {
+	case RTW_WOWLAN_FW:
+		fw = &rtwdev->wow_fw;
+		break;
+
+	case RTW_NORMAL_FW:
+		fw = &rtwdev->fw;
+		break;
+
+	default:
+		rtw_warn(rtwdev, "unsupported firmware type to swap\n");
+		return -ENOENT;
+	}
+
+	ret = rtw_download_firmware(rtwdev, fw);
+	if (ret)
+		goto out;
+
+	rtw_fw_send_general_info(rtwdev);
+	rtw_fw_send_phydm_info(rtwdev);
+	rtw_wow_fw_media_status(rtwdev, true);
+
+out:
+	return ret;
+}
+
+static void rtw_wow_check_pno(struct rtw_dev *rtwdev,
+			      struct cfg80211_sched_scan_request *nd_config)
+{
+	struct rtw_wow_param *rtw_wow = &rtwdev->wow;
+	struct rtw_pno_request *pno_req = &rtw_wow->pno_req;
+	struct ieee80211_channel *channel;
+	int i, size;
+
+	if (!nd_config->n_match_sets || !nd_config->n_channels)
+		goto err;
+
+	pno_req->match_set_cnt = nd_config->n_match_sets;
+	size = sizeof(*pno_req->match_sets) * pno_req->match_set_cnt;
+	pno_req->match_sets = kmemdup(nd_config->match_sets, size, GFP_KERNEL);
+	if (!pno_req->match_sets)
+		goto err;
+
+	pno_req->channel_cnt = nd_config->n_channels;
+	size = sizeof(*nd_config->channels[0]) * nd_config->n_channels;
+	pno_req->channels = kmalloc(size, GFP_KERNEL);
+	if (!pno_req->channels)
+		goto channel_err;
+
+	for (i = 0 ; i < pno_req->channel_cnt; i++) {
+		channel = pno_req->channels + i;
+		memcpy(channel, nd_config->channels[i], sizeof(*channel));
+	}
+
+	pno_req->scan_plan = *nd_config->scan_plans;
+	pno_req->inited = true;
+
+	rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: net-detect is enabled\n");
+
+	return;
+
+channel_err:
+	kfree(pno_req->match_sets);
+
+err:
+	rtw_dbg(rtwdev, RTW_DBG_WOW, "WOW: net-detect is disabled\n");
+}
+
+static int rtw_wow_leave_linked_ps(struct rtw_dev *rtwdev)
+{
+	if (!test_bit(RTW_FLAG_WOWLAN, rtwdev->flags))
+		cancel_delayed_work_sync(&rtwdev->watch_dog_work);
+
+	rtw_leave_lps(rtwdev);
+
+	return 0;
+}
+
+static int rtw_wow_leave_no_link_ps(struct rtw_dev *rtwdev)
+{
+	struct rtw_wow_param *rtw_wow = &rtwdev->wow;
+	int ret = 0;
+
+	if (test_bit(RTW_FLAG_WOWLAN, rtwdev->flags)) {
+		if (rtw_fw_lps_deep_mode)
+			rtw_leave_lps_deep(rtwdev);
+	} else {
+		if (test_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags)) {
+			rtw_wow->ips_enabled = true;
+			ret = rtw_leave_ips(rtwdev);
+			if (ret)
+				return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int rtw_wow_leave_ps(struct rtw_dev *rtwdev)
+{
+	int ret = 0;
+
+	if (rtw_wow_mgd_linked(rtwdev))
+		ret = rtw_wow_leave_linked_ps(rtwdev);
+	else if (rtw_wow_no_link(rtwdev))
+		ret = rtw_wow_leave_no_link_ps(rtwdev);
+
+	return ret;
+}
+
+static int rtw_wow_restore_ps(struct rtw_dev *rtwdev)
+{
+	int ret = 0;
+
+	if (rtw_wow_no_link(rtwdev) && rtwdev->wow.ips_enabled)
+		ret = rtw_enter_ips(rtwdev);
+
+	return ret;
+}
+
+static int rtw_wow_enter_linked_ps(struct rtw_dev *rtwdev)
+{
+	struct rtw_wow_param *rtw_wow = &rtwdev->wow;
+	struct ieee80211_vif *wow_vif = rtw_wow->wow_vif;
+	struct rtw_vif *rtwvif = (struct rtw_vif *)wow_vif->drv_priv;
+
+	rtw_enter_lps(rtwdev, rtwvif->port);
+
+	return 0;
+}
+
+static int rtw_wow_enter_no_link_ps(struct rtw_dev *rtwdev)
+{
+	/* firmware enters deep ps by itself if supported */
+	set_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags);
+
+	return 0;
+}
+
+static int rtw_wow_enter_ps(struct rtw_dev *rtwdev)
+{
+	int ret = 0;
+
+	if (rtw_wow_mgd_linked(rtwdev))
+		ret = rtw_wow_enter_linked_ps(rtwdev);
+	else if (rtw_wow_no_link(rtwdev) && rtw_fw_lps_deep_mode)
+		ret = rtw_wow_enter_no_link_ps(rtwdev);
+
+	return ret;
+}
+
+static void rtw_wow_stop_trx(struct rtw_dev *rtwdev)
+{
+	rtw_wow_bb_stop(rtwdev);
+	rtw_wow_rx_dma_stop(rtwdev);
+}
+
+static int rtw_wow_start(struct rtw_dev *rtwdev)
+{
+	int ret;
+
+	ret = rtw_wow_fw_start(rtwdev);
+	if (ret)
+		goto out;
+
+	rtw_hci_stop(rtwdev);
+	rtw_wow_bb_start(rtwdev);
+	rtw_wow_avoid_reset_mac(rtwdev);
+
+out:
+	return ret;
+}
+
+static int rtw_wow_enable(struct rtw_dev *rtwdev)
+{
+	int ret = 0;
+
+	rtw_wow_stop_trx(rtwdev);
+
+	ret = rtw_wow_swap_fw(rtwdev, RTW_WOWLAN_FW);
+	if (ret) {
+		rtw_err(rtwdev, "failed to swap wow fw\n");
+		goto error;
+	}
+
+	set_bit(RTW_FLAG_WOWLAN, rtwdev->flags);
+
+	ret = rtw_wow_dl_fw_rsvd_page(rtwdev);
+	if (ret) {
+		rtw_err(rtwdev, "failed to download wowlan rsvd page\n");
+		goto error;
+	}
+
+	ret = rtw_wow_start(rtwdev);
+	if (ret) {
+		rtw_err(rtwdev, "failed to start wow\n");
+		goto error;
+	}
+
+	return ret;
+
+error:
+	clear_bit(RTW_FLAG_WOWLAN, rtwdev->flags);
+	return ret;
+}
+
+static int rtw_wow_stop(struct rtw_dev *rtwdev)
+{
+	int ret;
+
+	/* some HCI related registers will be reset after resume,
+	 * need to set them again.
+	 */
+	ret = rtw_hci_setup(rtwdev);
+	if (ret) {
+		rtw_err(rtwdev, "failed to setup hci\n");
+		return ret;
+	}
+
+	ret = rtw_hci_start(rtwdev);
+	if (ret) {
+		rtw_err(rtwdev, "failed to start hci\n");
+		return ret;
+	}
+
+	ret = rtw_wow_fw_stop(rtwdev);
+	if (ret)
+		rtw_err(rtwdev, "failed to stop wowlan fw\n");
+
+	rtw_wow_bb_stop(rtwdev);
+
+	return ret;
+}
+
+static void rtw_wow_resume_trx(struct rtw_dev *rtwdev)
+{
+	rtw_wow_rx_dma_start(rtwdev);
+	rtw_wow_bb_start(rtwdev);
+	ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->watch_dog_work,
+				     RTW_WATCH_DOG_DELAY_TIME);
+}
+
+static int rtw_wow_disable(struct rtw_dev *rtwdev)
+{
+	int ret;
+
+	clear_bit(RTW_FLAG_WOWLAN, rtwdev->flags);
+
+	ret = rtw_wow_stop(rtwdev);
+	if (ret) {
+		rtw_err(rtwdev, "failed to stop wow\n");
+		goto out;
+	}
+
+	ret = rtw_wow_swap_fw(rtwdev, RTW_NORMAL_FW);
+	if (ret) {
+		rtw_err(rtwdev, "failed to swap normal fw\n");
+		goto out;
+	}
+
+	ret = rtw_wow_dl_fw_rsvd_page(rtwdev);
+	if (ret)
+		rtw_err(rtwdev, "failed to download normal rsvd page\n");
+
+out:
+	rtw_wow_resume_trx(rtwdev);
+	return ret;
+}
+
+static void rtw_wow_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
+{
+	struct rtw_dev *rtwdev = data;
+	struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
+	struct rtw_wow_param *rtw_wow = &rtwdev->wow;
+
+	/* Current wowlan function support setting of only one STATION vif.
+	 * So when one suitable vif is found, stop the iteration.
+	 */
+	if (rtw_wow->wow_vif || vif->type != NL80211_IFTYPE_STATION)
+		return;
+
+	switch (rtwvif->net_type) {
+	case RTW_NET_MGD_LINKED:
+		rtw_wow->wow_vif = vif;
+		break;
+	case RTW_NET_NO_LINK:
+		if (rtw_wow->pno_req.inited)
+			rtwdev->wow.wow_vif = vif;
+		break;
+	default:
+		break;
+	}
+}
+
+static int rtw_wow_set_wakeups(struct rtw_dev *rtwdev,
+			       struct cfg80211_wowlan *wowlan)
+{
+	struct rtw_wow_param *rtw_wow = &rtwdev->wow;
+	struct rtw_wow_pattern *rtw_patterns = rtw_wow->patterns;
+	struct rtw_vif *rtwvif;
+	int i;
+
+	if (wowlan->disconnect)
+		set_bit(RTW_WOW_FLAG_EN_DISCONNECT, rtw_wow->flags);
+	if (wowlan->magic_pkt)
+		set_bit(RTW_WOW_FLAG_EN_MAGIC_PKT, rtw_wow->flags);
+	if (wowlan->gtk_rekey_failure)
+		set_bit(RTW_WOW_FLAG_EN_REKEY_PKT, rtw_wow->flags);
+
+	if (wowlan->nd_config)
+		rtw_wow_check_pno(rtwdev, wowlan->nd_config);
+
+	rtw_iterate_vifs_atomic(rtwdev, rtw_wow_vif_iter, rtwdev);
+	if (!rtw_wow->wow_vif)
+		return -EPERM;
+
+	rtwvif = (struct rtw_vif *)rtw_wow->wow_vif->drv_priv;
+	if (wowlan->n_patterns && wowlan->patterns) {
+		rtw_wow->pattern_cnt = wowlan->n_patterns;
+		for (i = 0; i < wowlan->n_patterns; i++)
+			rtw_wow_pattern_generate(rtwdev, rtwvif,
+						 wowlan->patterns + i,
+						 rtw_patterns + i);
+	}
+
+	return 0;
+}
+
+static void rtw_wow_clear_wakeups(struct rtw_dev *rtwdev)
+{
+	struct rtw_wow_param *rtw_wow = &rtwdev->wow;
+	struct rtw_pno_request *pno_req = &rtw_wow->pno_req;
+
+	if (pno_req->inited) {
+		kfree(pno_req->channels);
+		kfree(pno_req->match_sets);
+	}
+
+	memset(rtw_wow, 0, sizeof(rtwdev->wow));
+}
+
+int rtw_wow_suspend(struct rtw_dev *rtwdev, struct cfg80211_wowlan *wowlan)
+{
+	int ret = 0;
+
+	ret = rtw_wow_set_wakeups(rtwdev, wowlan);
+	if (ret) {
+		rtw_err(rtwdev, "failed to set wakeup event\n");
+		goto out;
+	}
+
+	ret = rtw_wow_leave_ps(rtwdev);
+	if (ret) {
+		rtw_err(rtwdev, "failed to leave ps from normal mode\n");
+		goto out;
+	}
+
+	ret = rtw_wow_enable(rtwdev);
+	if (ret) {
+		rtw_err(rtwdev, "failed to enable wow\n");
+		rtw_wow_restore_ps(rtwdev);
+		goto out;
+	}
+
+	ret = rtw_wow_enter_ps(rtwdev);
+	if (ret)
+		rtw_err(rtwdev, "failed to enter ps for wow\n");
+
+out:
+	return ret;
+}
+
+int rtw_wow_resume(struct rtw_dev *rtwdev)
+{
+	int ret;
+
+	/* If wowlan mode is not enabled, do nothing */
+	if (!test_bit(RTW_FLAG_WOWLAN, rtwdev->flags)) {
+		rtw_err(rtwdev, "wow is not enabled\n");
+		ret = -EPERM;
+		goto out;
+	}
+
+	ret = rtw_wow_leave_ps(rtwdev);
+	if (ret) {
+		rtw_err(rtwdev, "failed to leave ps from wowlan mode\n");
+		goto out;
+	}
+
+	rtw_wow_show_wakeup_reason(rtwdev);
+
+	ret = rtw_wow_disable(rtwdev);
+	if (ret) {
+		rtw_err(rtwdev, "failed to disable wow\n");
+		goto out;
+	}
+
+	ret = rtw_wow_restore_ps(rtwdev);
+	if (ret)
+		rtw_err(rtwdev, "failed to restore ps to normal mode\n");
+
+out:
+	rtw_wow_clear_wakeups(rtwdev);
+	return ret;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/realtek/rtw88/wow.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/realtek/rtw88/wow.h
@@ -0,0 +1,58 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2018-2019  Realtek Corporation
+ */
+
+#ifndef __RTW_WOW_H__
+#define __RTW_WOW_H__
+
+#define PNO_CHECK_BYTE 4
+
+enum rtw_wow_pattern_type {
+	RTW_PATTERN_BROADCAST = 0,
+	RTW_PATTERN_MULTICAST,
+	RTW_PATTERN_UNICAST,
+	RTW_PATTERN_VALID,
+	RTW_PATTERN_INVALID,
+};
+
+enum rtw_wake_reason {
+	RTW_WOW_RSN_RX_PTK_REKEY = 0x1,
+	RTW_WOW_RSN_RX_GTK_REKEY = 0x2,
+	RTW_WOW_RSN_RX_DEAUTH = 0x8,
+	RTW_WOW_RSN_DISCONNECT = 0x10,
+	RTW_WOW_RSN_RX_MAGIC_PKT = 0x21,
+	RTW_WOW_RSN_RX_PATTERN_MATCH = 0x23,
+	RTW_WOW_RSN_RX_NLO = 0x55,
+};
+
+struct rtw_fw_media_status_iter_data {
+	struct rtw_dev *rtwdev;
+	u8 connect;
+};
+
+struct rtw_fw_key_type_iter_data {
+	struct rtw_dev *rtwdev;
+	u8 group_key_type;
+	u8 pairwise_key_type;
+};
+
+static inline bool rtw_wow_mgd_linked(struct rtw_dev *rtwdev)
+{
+	struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
+	struct rtw_vif *rtwvif = (struct rtw_vif *)wow_vif->drv_priv;
+
+	return (rtwvif->net_type == RTW_NET_MGD_LINKED);
+}
+
+static inline bool rtw_wow_no_link(struct rtw_dev *rtwdev)
+{
+	struct ieee80211_vif *wow_vif = rtwdev->wow.wow_vif;
+	struct rtw_vif *rtwvif = (struct rtw_vif *)wow_vif->drv_priv;
+
+	return (rtwvif->net_type == RTW_NET_NO_LINK);
+}
+
+int rtw_wow_suspend(struct rtw_dev *rtwdev, struct cfg80211_wowlan *wowlan);
+int rtw_wow_resume(struct rtw_dev *rtwdev);
+
+#endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/rndis_wlan.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/rndis_wlan.c
@@ -700,8 +700,8 @@
 		struct rndis_query	*get;
 		struct rndis_query_c	*get_c;
 	} u;
-	int ret, buflen;
-	int resplen, respoffs, copylen;
+	int ret;
+	size_t buflen, resplen, respoffs, copylen;
 
 	buflen = *len + sizeof(*u.get);
 	if (buflen < CONTROL_BUFFER_SIZE)
@@ -736,22 +736,15 @@
 
 		if (respoffs > buflen) {
 			/* Device returned data offset outside buffer, error. */
-			netdev_dbg(dev->net, "%s(%s): received invalid "
-				"data offset: %d > %d\n", __func__,
-				oid_to_string(oid), respoffs, buflen);
+			netdev_dbg(dev->net,
+				   "%s(%s): received invalid data offset: %zu > %zu\n",
+				   __func__, oid_to_string(oid), respoffs, buflen);
 
 			ret = -EINVAL;
 			goto exit_unlock;
 		}
 
-		if ((resplen + respoffs) > buflen) {
-			/* Device would have returned more data if buffer would
-			 * have been big enough. Copy just the bits that we got.
-			 */
-			copylen = buflen - respoffs;
-		} else {
-			copylen = resplen;
-		}
+		copylen = min(resplen, buflen - respoffs);
 
 		if (copylen > *len)
 			copylen = *len;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/rsi/rsi_91x_coex.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/rsi/rsi_91x_coex.c
@@ -160,6 +160,7 @@
 			       rsi_coex_scheduler_thread,
 			       "Coex-Tx-Thread")) {
 		rsi_dbg(ERR_ZONE, "%s: Unable to init tx thrd\n", __func__);
+		kfree(coex_cb);
 		return -EINVAL;
 	}
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/rsi/rsi_91x_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/rsi/rsi_91x_core.c
@@ -400,6 +400,8 @@
 
 	info = IEEE80211_SKB_CB(skb);
 	tx_params = (struct skb_info *)info->driver_data;
+	/* info->driver_data and info->control part of union so make copy */
+	tx_params->have_key = !!info->control.hw_key;
 	wh = (struct ieee80211_hdr *)&skb->data[0];
 	tx_params->sta_id = 0;
 
@@ -464,7 +466,9 @@
 							      tid, 0);
 			}
 		}
-		if (skb->protocol == cpu_to_be16(ETH_P_PAE)) {
+
+		if (IEEE80211_SKB_CB(skb)->control.flags &
+		    IEEE80211_TX_CTRL_PORT_CTRL_PROTO) {
 			q_num = MGMT_SOFT_Q;
 			skb->priority = q_num;
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/rsi/rsi_91x_hal.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/rsi/rsi_91x_hal.c
@@ -162,12 +162,16 @@
 	u8 header_size;
 	u8 vap_id = 0;
 	u8 dword_align_bytes;
+	bool tx_eapol;
 	u16 seq_num;
 
 	info = IEEE80211_SKB_CB(skb);
 	vif = info->control.vif;
 	tx_params = (struct skb_info *)info->driver_data;
 
+	tx_eapol = IEEE80211_SKB_CB(skb)->control.flags &
+		   IEEE80211_TX_CTRL_PORT_CTRL_PROTO;
+
 	header_size = FRAME_DESC_SZ + sizeof(struct rsi_xtended_desc);
 	if (header_size > skb_headroom(skb)) {
 		rsi_dbg(ERR_ZONE, "%s: Unable to send pkt\n", __func__);
@@ -203,7 +207,7 @@
 		wh->frame_control |= cpu_to_le16(RSI_SET_PS_ENABLE);
 
 	if ((!(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) &&
-	    (common->secinfo.security_enable)) {
+	    tx_params->have_key) {
 		if (rsi_is_cipher_wep(common))
 			ieee80211_size += 4;
 		else
@@ -214,22 +218,24 @@
 			RSI_WIFI_DATA_Q);
 	data_desc->header_len = ieee80211_size;
 
-	if (common->min_rate != RSI_RATE_AUTO) {
+	if (common->rate_config[common->band].fixed_enabled) {
 		/* Send fixed rate */
+		u16 fixed_rate = common->rate_config[common->band].fixed_hw_rate;
+
 		data_desc->frame_info = cpu_to_le16(RATE_INFO_ENABLE);
-		data_desc->rate_info = cpu_to_le16(common->min_rate);
+		data_desc->rate_info = cpu_to_le16(fixed_rate);
 
 		if (conf_is_ht40(&common->priv->hw->conf))
 			data_desc->bbp_info = cpu_to_le16(FULL40M_ENABLE);
 
-		if ((common->vif_info[0].sgi) && (common->min_rate & 0x100)) {
+		if (common->vif_info[0].sgi && (fixed_rate & 0x100)) {
 		       /* Only MCS rates */
 			data_desc->rate_info |=
 				cpu_to_le16(ENABLE_SHORTGI_RATE);
 		}
 	}
 
-	if (skb->protocol == cpu_to_be16(ETH_P_PAE)) {
+	if (tx_eapol) {
 		rsi_dbg(INFO_ZONE, "*** Tx EAPOL ***\n");
 
 		data_desc->frame_info = cpu_to_le16(RATE_INFO_ENABLE);
@@ -248,7 +254,8 @@
 			rsi_set_len_qno(&data_desc->len_qno,
 					(skb->len - FRAME_DESC_SZ),
 					RSI_WIFI_MGMT_Q);
-		if ((skb->len - header_size) == EAPOL4_PACKET_LEN) {
+		if (((skb->len - header_size) == EAPOL4_PACKET_LEN) ||
+		    ((skb->len - header_size) == EAPOL4_PACKET_LEN - 2)) {
 			data_desc->misc_flags |=
 				RSI_DESC_REQUIRE_CFM_TO_HOST;
 			xtend_desc->confirm_frame_type = EAPOL4_CONFIRM;
@@ -469,9 +476,9 @@
 	}
 
 	if (common->band == NL80211_BAND_2GHZ)
-		bcn_frm->bbp_info |= cpu_to_le16(RSI_RATE_1);
+		bcn_frm->rate_info |= cpu_to_le16(RSI_RATE_1);
 	else
-		bcn_frm->bbp_info |= cpu_to_le16(RSI_RATE_6);
+		bcn_frm->rate_info |= cpu_to_le16(RSI_RATE_6);
 
 	if (mac_bcn->data[tim_offset + 2] == 0)
 		bcn_frm->frame_info |= cpu_to_le16(RSI_DATA_DESC_DTIM_BEACON);
@@ -622,6 +629,7 @@
 	bl_start_cmd_timer(adapter, timeout);
 	status = bl_write_cmd(adapter, cmd, exp_resp, &regout_val);
 	if (status < 0) {
+		bl_stop_cmd_timer(adapter);
 		rsi_dbg(ERR_ZONE,
 			"%s: Command %s (%0x) writing failed..\n",
 			__func__, str, cmd);
@@ -737,10 +745,9 @@
 	}
 
 	status = bl_cmd(adapter, cmd_req, cmd_resp, str);
-	if (status) {
-		bl_stop_cmd_timer(adapter);
+	if (status)
 		return status;
-	}
+
 	return 0;
 }
 
@@ -828,10 +835,9 @@
 
 	status = bl_cmd(adapter, EOF_REACHED, FW_LOADING_SUCCESSFUL,
 			"EOF_REACHED");
-	if (status) {
-		bl_stop_cmd_timer(adapter);
+	if (status)
 		return status;
-	}
+
 	rsi_dbg(INFO_ZONE, "FW loading is done and FW is running..\n");
 	return 0;
 }
@@ -849,6 +855,7 @@
 						  &regout_val,
 						  RSI_COMMON_REG_SIZE);
 		if (status < 0) {
+			bl_stop_cmd_timer(adapter);
 			rsi_dbg(ERR_ZONE,
 				"%s: REGOUT read failed\n", __func__);
 			return status;
@@ -1037,8 +1044,10 @@
 	}
 
 	ta_firmware = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
-	if (!ta_firmware)
+	if (!ta_firmware) {
+		status = -ENOMEM;
 		goto fail_release_fw;
+	}
 	fw_p = ta_firmware;
 	instructions_sz = fw_entry->size;
 	rsi_dbg(INFO_ZONE, "FW Length = %d bytes\n", instructions_sz);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -510,7 +510,6 @@
 	if ((vif->type == NL80211_IFTYPE_AP) ||
 	    (vif->type == NL80211_IFTYPE_P2P_GO)) {
 		rsi_send_rx_filter_frame(common, DISALLOW_BEACONS);
-		common->min_rate = RSI_RATE_AUTO;
 		for (i = 0; i < common->max_stations; i++)
 			common->stations[i].sta = NULL;
 	}
@@ -1027,7 +1026,6 @@
 	mutex_lock(&common->mutex);
 	switch (cmd) {
 	case SET_KEY:
-		secinfo->security_enable = true;
 		status = rsi_hal_key_config(hw, vif, key, sta);
 		if (status) {
 			mutex_unlock(&common->mutex);
@@ -1046,8 +1044,6 @@
 		break;
 
 	case DISABLE_KEY:
-		if (vif->type == NL80211_IFTYPE_STATION)
-			secinfo->security_enable = false;
 		rsi_dbg(ERR_ZONE, "%s: RSI del key\n", __func__);
 		memset(key, 0, sizeof(struct ieee80211_key_conf));
 		status = rsi_hal_key_config(hw, vif, key, sta);
@@ -1140,8 +1136,7 @@
 		else if ((vif->type == NL80211_IFTYPE_AP) ||
 			 (vif->type == NL80211_IFTYPE_P2P_GO))
 			rsta->seq_start[tid] = seq_no;
-		ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
-		status = 0;
+		status = IEEE80211_AMPDU_TX_START_IMMEDIATE;
 		break;
 
 	case IEEE80211_AMPDU_TX_STOP_CONT:
@@ -1214,20 +1209,32 @@
 				      struct ieee80211_vif *vif,
 				      const struct cfg80211_bitrate_mask *mask)
 {
+	const unsigned int mcs_offset = ARRAY_SIZE(rsi_rates);
 	struct rsi_hw *adapter = hw->priv;
 	struct rsi_common *common = adapter->priv;
-	enum nl80211_band band = hw->conf.chandef.chan->band;
+	int i;
 
 	mutex_lock(&common->mutex);
-	common->fixedrate_mask[band] = 0;
 
-	if (mask->control[band].legacy == 0xfff) {
-		common->fixedrate_mask[band] =
-			(mask->control[band].ht_mcs[0] << 12);
-	} else {
-		common->fixedrate_mask[band] =
-			mask->control[band].legacy;
+	for (i = 0; i < ARRAY_SIZE(common->rate_config); i++) {
+		struct rsi_rate_config *cfg = &common->rate_config[i];
+		u32 bm;
+
+		bm = mask->control[i].legacy | (mask->control[i].ht_mcs[0] << mcs_offset);
+		if (hweight32(bm) == 1) { /* single rate */
+			int rate_index = ffs(bm) - 1;
+
+			if (rate_index < mcs_offset)
+				cfg->fixed_hw_rate = rsi_rates[rate_index].hw_value;
+			else
+				cfg->fixed_hw_rate = rsi_mcsrates[rate_index - mcs_offset];
+			cfg->fixed_enabled = true;
+		} else {
+			cfg->configured_mask = bm;
+			cfg->fixed_enabled = false;
+		}
 	}
+
 	mutex_unlock(&common->mutex);
 
 	return 0;
@@ -1363,46 +1370,6 @@
 	ieee80211_rx_irqsafe(hw, skb);
 }
 
-static void rsi_set_min_rate(struct ieee80211_hw *hw,
-			     struct ieee80211_sta *sta,
-			     struct rsi_common *common)
-{
-	u8 band = hw->conf.chandef.chan->band;
-	u8 ii;
-	u32 rate_bitmap;
-	bool matched = false;
-
-	common->bitrate_mask[band] = sta->supp_rates[band];
-
-	rate_bitmap = (common->fixedrate_mask[band] & sta->supp_rates[band]);
-
-	if (rate_bitmap & 0xfff) {
-		/* Find out the min rate */
-		for (ii = 0; ii < ARRAY_SIZE(rsi_rates); ii++) {
-			if (rate_bitmap & BIT(ii)) {
-				common->min_rate = rsi_rates[ii].hw_value;
-				matched = true;
-				break;
-			}
-		}
-	}
-
-	common->vif_info[0].is_ht = sta->ht_cap.ht_supported;
-
-	if ((common->vif_info[0].is_ht) && (rate_bitmap >> 12)) {
-		for (ii = 0; ii < ARRAY_SIZE(rsi_mcsrates); ii++) {
-			if ((rate_bitmap >> 12) & BIT(ii)) {
-				common->min_rate = rsi_mcsrates[ii];
-				matched = true;
-				break;
-			}
-		}
-	}
-
-	if (!matched)
-		common->min_rate = 0xffff;
-}
-
 /**
  * rsi_mac80211_sta_add() - This function notifies driver about a peer getting
  *			    connected.
@@ -1501,9 +1468,9 @@
 
 	if ((vif->type == NL80211_IFTYPE_STATION) ||
 	    (vif->type == NL80211_IFTYPE_P2P_CLIENT)) {
-		rsi_set_min_rate(hw, sta, common);
+		common->bitrate_mask[common->band] = sta->supp_rates[common->band];
+		common->vif_info[0].is_ht = sta->ht_cap.ht_supported;
 		if (sta->ht_cap.ht_supported) {
-			common->vif_info[0].is_ht = true;
 			common->bitrate_mask[NL80211_BAND_2GHZ] =
 					sta->supp_rates[NL80211_BAND_2GHZ];
 			if ((sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ||
@@ -1577,7 +1544,6 @@
 		bss->qos = sta->wme;
 		common->bitrate_mask[NL80211_BAND_2GHZ] = 0;
 		common->bitrate_mask[NL80211_BAND_5GHZ] = 0;
-		common->min_rate = 0xffff;
 		common->vif_info[0].is_ht = false;
 		common->vif_info[0].sgi = false;
 		common->vif_info[0].seq_start = 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/rsi/rsi_91x_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/rsi/rsi_91x_main.c
@@ -23,6 +23,7 @@
 #include "rsi_common.h"
 #include "rsi_coex.h"
 #include "rsi_hal.h"
+#include "rsi_usb.h"
 
 u32 rsi_zone_enabled = /* INFO_ZONE |
 			INIT_ZONE |
@@ -167,6 +168,9 @@
 		frame_desc = &rx_pkt[index];
 		actual_length = *(u16 *)&frame_desc[0];
 		offset = *(u16 *)&frame_desc[2];
+		if (!rcv_pkt_len && offset >
+			RSI_MAX_RX_USB_PKT_SIZE - FRAME_DESC_SZ)
+			goto fail;
 
 		queueno = rsi_get_queueno(frame_desc, offset);
 		length = rsi_get_length(frame_desc, offset);
@@ -210,9 +214,10 @@
 			bt_pkt_type = frame_desc[offset + BT_RX_PKT_TYPE_OFST];
 			if (bt_pkt_type == BT_CARD_READY_IND) {
 				rsi_dbg(INFO_ZONE, "BT Card ready recvd\n");
-				if (rsi_bt_ops.attach(common, &g_proto_ops))
-					rsi_dbg(ERR_ZONE,
-						"Failed to attach BT module\n");
+				if (common->fsm_state == FSM_MAC_INIT_DONE)
+					rsi_attach_bt(common);
+				else
+					common->bt_defer_attach = true;
 			} else {
 				if (common->bt_adapter)
 					rsi_bt_ops.recv_pkt(common->bt_adapter,
@@ -277,6 +282,15 @@
 }
 #endif
 
+void rsi_attach_bt(struct rsi_common *common)
+{
+#ifdef CONFIG_RSI_COEX
+	if (rsi_bt_ops.attach(common, &g_proto_ops))
+		rsi_dbg(ERR_ZONE,
+			"Failed to attach BT module\n");
+#endif
+}
+
 /**
  * rsi_91x_init() - This function initializes os interface operations.
  * @void: Void.
@@ -358,6 +372,7 @@
 	if (common->coex_mode > 1) {
 		if (rsi_coex_attach(common)) {
 			rsi_dbg(ERR_ZONE, "Failed to init coex module\n");
+			rsi_kill_thread(&common->tx_thread);
 			goto err;
 		}
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/rsi/rsi_91x_mgmt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/rsi/rsi_91x_mgmt.c
@@ -276,7 +276,7 @@
 	common->channel_width = BW_20MHZ;
 	common->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
 	common->channel = 1;
-	common->min_rate = 0xffff;
+	memset(&common->rate_config, 0, sizeof(common->rate_config));
 	common->fsm_state = FSM_CARD_NOT_READY;
 	common->iface_down = true;
 	common->endpoint = EP_2GHZ_20MHZ;
@@ -1304,7 +1304,7 @@
 	u8 band = hw->conf.chandef.chan->band;
 	u8 num_supported_rates = 0;
 	u8 rate_table_offset, rate_offset = 0;
-	u32 rate_bitmap;
+	u32 rate_bitmap, configured_rates;
 	u16 *selected_rates, min_rate;
 	bool is_ht = false, is_sgi = false;
 	u16 frame_len = sizeof(struct rsi_auto_rate);
@@ -1354,6 +1354,10 @@
 			is_sgi = true;
 	}
 
+	/* Limit to any rates administratively configured by cfg80211 */
+	configured_rates = common->rate_config[band].configured_mask ?: 0xffffffff;
+	rate_bitmap &= configured_rates;
+
 	if (band == NL80211_BAND_2GHZ) {
 		if ((rate_bitmap == 0) && (is_ht))
 			min_rate = RSI_RATE_MCS0;
@@ -1379,10 +1383,13 @@
 	num_supported_rates = jj;
 
 	if (is_ht) {
-		for (ii = 0; ii < ARRAY_SIZE(mcs); ii++)
-			selected_rates[jj++] = mcs[ii];
-		num_supported_rates += ARRAY_SIZE(mcs);
-		rate_offset += ARRAY_SIZE(mcs);
+		for (ii = 0; ii < ARRAY_SIZE(mcs); ii++) {
+			if (configured_rates & BIT(ii + ARRAY_SIZE(rsi_rates))) {
+				selected_rates[jj++] = mcs[ii];
+				num_supported_rates++;
+				rate_offset++;
+			}
+		}
 	}
 
 	sort(selected_rates, jj, sizeof(u16), &rsi_compare, NULL);
@@ -1467,7 +1474,7 @@
 					      qos_enable,
 					      aid, sta_id,
 					      vif);
-		if (common->min_rate == 0xffff)
+		if (!common->rate_config[common->band].fixed_enabled)
 			rsi_send_auto_rate_request(common, sta, sta_id, vif);
 		if (opmode == RSI_OPMODE_STA &&
 		    !(assoc_cap & WLAN_CAPABILITY_PRIVACY) &&
@@ -1756,6 +1763,7 @@
 		skb_pull(skb, (64 - dword_align_bytes));
 	if (rsi_prepare_beacon(common, skb)) {
 		rsi_dbg(ERR_ZONE, "Failed to prepare beacon\n");
+		dev_kfree_skb(skb);
 		return -EINVAL;
 	}
 	skb_queue_tail(&common->tx_queue[MGMT_BEACON_Q], skb);
@@ -1787,8 +1795,7 @@
 			RSI_WIFI_MGMT_Q);
 	cmd_frame->desc.desc_dword0.frame_type = WOWLAN_CONFIG_PARAMS;
 	cmd_frame->host_sleep_status = sleep_status;
-	if (common->secinfo.security_enable &&
-	    common->secinfo.gtk_cipher)
+	if (common->secinfo.gtk_cipher)
 		flags |= RSI_WOW_GTK_REKEY;
 	if (sleep_status)
 		cmd_frame->wow_flags = flags;
@@ -2056,6 +2063,9 @@
 				if (common->reinit_hw) {
 					complete(&common->wlan_init_completion);
 				} else {
+					if (common->bt_defer_attach)
+						rsi_attach_bt(common);
+
 					return rsi_mac80211_attach(common);
 				}
 			}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/rsi/rsi_91x_sdio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/rsi/rsi_91x_sdio.c
@@ -24,10 +24,7 @@
 /* Default operating mode is wlan STA + BT */
 static u16 dev_oper_mode = DEV_OPMODE_STA_BT_DUAL;
 module_param(dev_oper_mode, ushort, 0444);
-MODULE_PARM_DESC(dev_oper_mode,
-		 "1[Wi-Fi], 4[BT], 8[BT LE], 5[Wi-Fi STA + BT classic]\n"
-		 "9[Wi-Fi STA + BT LE], 13[Wi-Fi STA + BT classic + BT LE]\n"
-		 "6[AP + BT classic], 14[AP + BT classic + BT LE]");
+MODULE_PARM_DESC(dev_oper_mode, DEV_OPMODE_PARAM_DESC);
 
 /**
  * rsi_sdio_set_cmd52_arg() - This function prepares cmd 52 read/write arg.
@@ -153,9 +150,7 @@
 	if (adapter->priv->fsm_state == FSM_FW_NOT_LOADED)
 		return;
 
-	dev->sdio_irq_task = current;
-	rsi_interrupt_handler(adapter);
-	dev->sdio_irq_task = NULL;
+	rsi_set_event(&dev->rx_thread.event);
 }
 
 /**
@@ -1059,8 +1054,6 @@
 		rsi_dbg(ERR_ZONE, "%s: Unable to init rx thrd\n", __func__);
 		goto fail_kill_thread;
 	}
-	skb_queue_head_init(&sdev->rx_q.head);
-	sdev->rx_q.num_rx_pkts = 0;
 
 	sdio_claim_host(pfunction);
 	if (sdio_claim_irq(pfunction, rsi_handle_interrupt)) {
@@ -1486,9 +1479,6 @@
 	if (sdev->write_fail)
 		rsi_dbg(INFO_ZONE, "###### Device is not ready #######\n");
 
-	if (rsi_set_sdio_pm_caps(adapter))
-		rsi_dbg(INFO_ZONE, "Setting power management caps failed\n");
-
 	rsi_dbg(INFO_ZONE, "***** RSI module shut down *****\n");
 }
 
@@ -1515,7 +1505,7 @@
 }
 static const struct dev_pm_ops rsi_pm_ops = {
 	.suspend = rsi_suspend,
-	.resume = rsi_resume,
+	.resume_noirq = rsi_resume,
 	.freeze = rsi_freeze,
 	.thaw = rsi_thaw,
 	.restore = rsi_restore,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
@@ -60,39 +60,20 @@
 	return status;
 }
 
+static void rsi_rx_handler(struct rsi_hw *adapter);
+
 void rsi_sdio_rx_thread(struct rsi_common *common)
 {
 	struct rsi_hw *adapter = common->priv;
 	struct rsi_91x_sdiodev *sdev = adapter->rsi_dev;
-	struct sk_buff *skb;
-	int status;
 
 	do {
 		rsi_wait_event(&sdev->rx_thread.event, EVENT_WAIT_FOREVER);
 		rsi_reset_event(&sdev->rx_thread.event);
+		rsi_rx_handler(adapter);
+	} while (!atomic_read(&sdev->rx_thread.thread_done));
 
-		while (true) {
-			if (atomic_read(&sdev->rx_thread.thread_done))
-				goto out;
-
-			skb = skb_dequeue(&sdev->rx_q.head);
-			if (!skb)
-				break;
-			if (sdev->rx_q.num_rx_pkts > 0)
-				sdev->rx_q.num_rx_pkts--;
-			status = rsi_read_pkt(common, skb->data, skb->len);
-			if (status) {
-				rsi_dbg(ERR_ZONE, "Failed to read the packet\n");
-				dev_kfree_skb(skb);
-				break;
-			}
-			dev_kfree_skb(skb);
-		}
-	} while (1);
-
-out:
 	rsi_dbg(INFO_ZONE, "%s: Terminated SDIO RX thread\n", __func__);
-	skb_queue_purge(&sdev->rx_q.head);
 	atomic_inc(&sdev->rx_thread.thread_done);
 	complete_and_exit(&sdev->rx_thread.completion, 0);
 }
@@ -113,10 +94,6 @@
 	u32 rcv_pkt_len = 0;
 	int status = 0;
 	u8 value = 0;
-	struct sk_buff *skb;
-
-	if (dev->rx_q.num_rx_pkts >= RSI_MAX_RX_PKTS)
-		return 0;
 
 	num_blks = ((adapter->interrupt_status & 1) |
 			((adapter->interrupt_status >> RECV_NUM_BLOCKS) << 1));
@@ -144,22 +121,19 @@
 
 	rcv_pkt_len = (num_blks * 256);
 
-	skb = dev_alloc_skb(rcv_pkt_len);
-	if (!skb)
-		return -ENOMEM;
-
-	status = rsi_sdio_host_intf_read_pkt(adapter, skb->data, rcv_pkt_len);
+	status = rsi_sdio_host_intf_read_pkt(adapter, dev->pktbuffer,
+					     rcv_pkt_len);
 	if (status) {
 		rsi_dbg(ERR_ZONE, "%s: Failed to read packet from card\n",
 			__func__);
-		dev_kfree_skb(skb);
 		return status;
 	}
-	skb_put(skb, rcv_pkt_len);
-	skb_queue_tail(&dev->rx_q.head, skb);
-	dev->rx_q.num_rx_pkts++;
 
-	rsi_set_event(&dev->rx_thread.event);
+	status = rsi_read_pkt(common, dev->pktbuffer, rcv_pkt_len);
+	if (status) {
+		rsi_dbg(ERR_ZONE, "Failed to read the packet\n");
+		return status;
+	}
 
 	return 0;
 }
@@ -251,12 +225,12 @@
 }
 
 /**
- * rsi_interrupt_handler() - This function read and process SDIO interrupts.
+ * rsi_rx_handler() - Read and process SDIO interrupts.
  * @adapter: Pointer to the adapter structure.
  *
  * Return: None.
  */
-void rsi_interrupt_handler(struct rsi_hw *adapter)
+static void rsi_rx_handler(struct rsi_hw *adapter)
 {
 	struct rsi_common *common = adapter->priv;
 	struct rsi_91x_sdiodev *dev =
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -16,6 +16,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/types.h>
 #include <net/rsi_91x.h>
 #include "rsi_usb.h"
 #include "rsi_hal.h"
@@ -24,12 +25,9 @@
 /* Default operating mode is wlan STA + BT */
 static u16 dev_oper_mode = DEV_OPMODE_STA_BT_DUAL;
 module_param(dev_oper_mode, ushort, 0444);
-MODULE_PARM_DESC(dev_oper_mode,
-		 "1[Wi-Fi], 4[BT], 8[BT LE], 5[Wi-Fi STA + BT classic]\n"
-		 "9[Wi-Fi STA + BT LE], 13[Wi-Fi STA + BT classic + BT LE]\n"
-		 "6[AP + BT classic], 14[AP + BT classic + BT LE]");
+MODULE_PARM_DESC(dev_oper_mode, DEV_OPMODE_PARAM_DESC);
 
-static int rsi_rx_urb_submit(struct rsi_hw *adapter, u8 ep_num);
+static int rsi_rx_urb_submit(struct rsi_hw *adapter, u8 ep_num, gfp_t flags);
 
 /**
  * rsi_usb_card_write() - This function writes to the USB Card.
@@ -60,7 +58,7 @@
 			      (void *)seg,
 			      (int)len,
 			      &transfer,
-			      HZ * 5);
+			      USB_CTRL_SET_TIMEOUT);
 
 	if (status < 0) {
 		rsi_dbg(ERR_ZONE,
@@ -117,7 +115,7 @@
 	__le16 buffer_size;
 	int ii, bin_found = 0, bout_found = 0;
 
-	iface_desc = &(interface->altsetting[0]);
+	iface_desc = interface->cur_altsetting;
 
 	for (ii = 0; ii < iface_desc->desc.bNumEndpoints; ++ii) {
 		endpoint = &(iface_desc->endpoint[ii].desc);
@@ -263,8 +261,12 @@
 	struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)rx_cb->data;
 	int status = -EINVAL;
 
+	if (!rx_cb->rx_skb)
+		return;
+
 	if (urb->status) {
 		dev_kfree_skb(rx_cb->rx_skb);
+		rx_cb->rx_skb = NULL;
 		return;
 	}
 
@@ -285,11 +287,22 @@
 	status = 0;
 
 out:
-	if (rsi_rx_urb_submit(dev->priv, rx_cb->ep_num))
+	if (rsi_rx_urb_submit(dev->priv, rx_cb->ep_num, GFP_ATOMIC))
 		rsi_dbg(ERR_ZONE, "%s: Failed in urb submission", __func__);
 
-	if (status)
+	if (status) {
 		dev_kfree_skb(rx_cb->rx_skb);
+		rx_cb->rx_skb = NULL;
+	}
+}
+
+static void rsi_rx_urb_kill(struct rsi_hw *adapter, u8 ep_num)
+{
+	struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
+	struct rx_usb_ctrl_block *rx_cb = &dev->rx_cb[ep_num - 1];
+	struct urb *urb = rx_cb->rx_urb;
+
+	usb_kill_urb(urb);
 }
 
 /**
@@ -298,7 +311,7 @@
  *
  * Return: 0 on success, a negative error code on failure.
  */
-static int rsi_rx_urb_submit(struct rsi_hw *adapter, u8 ep_num)
+static int rsi_rx_urb_submit(struct rsi_hw *adapter, u8 ep_num, gfp_t mem_flags)
 {
 	struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
 	struct rx_usb_ctrl_block *rx_cb = &dev->rx_cb[ep_num - 1];
@@ -307,7 +320,6 @@
 	struct sk_buff *skb;
 	u8 dword_align_bytes = 0;
 
-#define RSI_MAX_RX_USB_PKT_SIZE	3000
 	skb = dev_alloc_skb(RSI_MAX_RX_USB_PKT_SIZE);
 	if (!skb)
 		return -ENOMEM;
@@ -328,9 +340,11 @@
 			  rsi_rx_done_handler,
 			  rx_cb);
 
-	status = usb_submit_urb(urb, GFP_KERNEL);
-	if (status)
+	status = usb_submit_urb(urb, mem_flags);
+	if (status) {
 		rsi_dbg(ERR_ZONE, "%s: Failed in urb submission\n", __func__);
+		dev_kfree_skb(skb);
+	}
 
 	return status;
 }
@@ -721,24 +735,24 @@
 		if (ret < 0)
 			goto fail;
 	} else {
-		if ((rsi_usb_master_reg_write(adapter,
-					      NWP_WWD_INTERRUPT_TIMER,
-					      NWP_WWD_INT_TIMER_CLKS,
-					      RSI_9116_REG_SIZE)) < 0) {
+		ret = rsi_usb_master_reg_write(adapter,
+					       NWP_WWD_INTERRUPT_TIMER,
+					       NWP_WWD_INT_TIMER_CLKS,
+					       RSI_9116_REG_SIZE);
+		if (ret < 0)
 			goto fail;
-		}
-		if ((rsi_usb_master_reg_write(adapter,
-					      NWP_WWD_SYSTEM_RESET_TIMER,
-					      NWP_WWD_SYS_RESET_TIMER_CLKS,
-					      RSI_9116_REG_SIZE)) < 0) {
+		ret = rsi_usb_master_reg_write(adapter,
+					       NWP_WWD_SYSTEM_RESET_TIMER,
+					       NWP_WWD_SYS_RESET_TIMER_CLKS,
+					       RSI_9116_REG_SIZE);
+		if (ret < 0)
 			goto fail;
-		}
-		if ((rsi_usb_master_reg_write(adapter,
-					      NWP_WWD_MODE_AND_RSTART,
-					      NWP_WWD_TIMER_DISABLE,
-					      RSI_9116_REG_SIZE)) < 0) {
+		ret = rsi_usb_master_reg_write(adapter,
+					       NWP_WWD_MODE_AND_RSTART,
+					       NWP_WWD_TIMER_DISABLE,
+					       RSI_9116_REG_SIZE);
+		if (ret < 0)
 			goto fail;
-		}
 	}
 
 	rsi_dbg(INFO_ZONE, "Reset card done\n");
@@ -794,6 +808,7 @@
 	} else {
 		rsi_dbg(ERR_ZONE, "%s: Unsupported RSI device id 0x%x\n",
 			__func__, id->idProduct);
+		status = -ENODEV;
 		goto err1;
 	}
 
@@ -816,17 +831,20 @@
 		rsi_dbg(INIT_ZONE, "%s: Device Init Done\n", __func__);
 	}
 
-	status = rsi_rx_urb_submit(adapter, WLAN_EP);
+	status = rsi_rx_urb_submit(adapter, WLAN_EP, GFP_KERNEL);
 	if (status)
 		goto err1;
 
 	if (adapter->priv->coex_mode > 1) {
-		status = rsi_rx_urb_submit(adapter, BT_EP);
+		status = rsi_rx_urb_submit(adapter, BT_EP, GFP_KERNEL);
 		if (status)
-			goto err1;
+			goto err_kill_wlan_urb;
 	}
 
 	return 0;
+
+err_kill_wlan_urb:
+	rsi_rx_urb_kill(adapter, WLAN_EP);
 err1:
 	rsi_deinit_usb_interface(adapter);
 err:
@@ -857,6 +875,10 @@
 		adapter->priv->bt_adapter = NULL;
 	}
 
+	if (adapter->priv->coex_mode > 1)
+		rsi_rx_urb_kill(adapter, BT_EP);
+	rsi_rx_urb_kill(adapter, WLAN_EP);
+
 	rsi_reset_card(adapter);
 	rsi_deinit_usb_interface(adapter);
 	rsi_91x_deinit(adapter);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/rsi/rsi_hal.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/rsi/rsi_hal.h
@@ -28,6 +28,17 @@
 #define DEV_OPMODE_AP_BT		6
 #define DEV_OPMODE_AP_BT_DUAL		14
 
+#define DEV_OPMODE_PARAM_DESC		\
+	__stringify(DEV_OPMODE_WIFI_ALONE)	"[Wi-Fi alone], "	\
+	__stringify(DEV_OPMODE_BT_ALONE)	"[BT classic alone], "	\
+	__stringify(DEV_OPMODE_BT_LE_ALONE)	"[BT LE alone], "	\
+	__stringify(DEV_OPMODE_BT_DUAL)		"[BT classic + BT LE alone], " \
+	__stringify(DEV_OPMODE_STA_BT)		"[Wi-Fi STA + BT classic], " \
+	__stringify(DEV_OPMODE_STA_BT_LE)	"[Wi-Fi STA + BT LE], "	\
+	__stringify(DEV_OPMODE_STA_BT_DUAL)	"[Wi-Fi STA + BT classic + BT LE], " \
+	__stringify(DEV_OPMODE_AP_BT)		"[Wi-Fi AP + BT classic], "	\
+	__stringify(DEV_OPMODE_AP_BT_DUAL)	"[Wi-Fi AP + BT classic + BT LE]"
+
 #define FLASH_WRITE_CHUNK_SIZE		(4 * 1024)
 #define FLASH_SECTOR_SIZE		(4 * 1024)
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/rsi/rsi_main.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/rsi/rsi_main.h
@@ -61,6 +61,7 @@
 extern u32 rsi_zone_enabled;
 extern __printf(2, 3) void rsi_dbg(u32 zone, const char *fmt, ...);
 
+#define RSI_MAX_BANDS			2
 #define RSI_MAX_VIFS                    3
 #define NUM_EDCA_QUEUES                 4
 #define IEEE80211_ADDR_LEN              6
@@ -139,6 +140,7 @@
 	u8 internal_hdr_size;
 	struct ieee80211_vif *vif;
 	u8 vap_id;
+	bool have_key;
 };
 
 enum edca_queue {
@@ -151,7 +153,6 @@
 };
 
 struct security_info {
-	bool security_enable;
 	u32 ptk_cipher;
 	u32 gtk_cipher;
 };
@@ -230,6 +231,12 @@
 	u32 ps_options;
 };
 
+struct rsi_rate_config {
+	u32 configured_mask;	/* configured by mac80211 bits 0-11=legacy 12+ mcs */
+	u16 fixed_hw_rate;
+	bool fixed_enabled;
+};
+
 struct rsi_common {
 	struct rsi_hw *priv;
 	struct vif_priv vif_info[RSI_MAX_VIFS];
@@ -255,8 +262,8 @@
 	u8 channel_width;
 
 	u16 rts_threshold;
-	u16 bitrate_mask[2];
-	u32 fixedrate_mask[2];
+	u32 bitrate_mask[RSI_MAX_BANDS];
+	struct rsi_rate_config rate_config[RSI_MAX_BANDS];
 
 	u8 rf_reset;
 	struct transmit_q_stats tx_stats;
@@ -277,7 +284,6 @@
 	u8 mac_id;
 	u8 radio_id;
 	u16 rate_pwr[20];
-	u16 min_rate;
 
 	/* WMM algo related */
 	u8 selected_qnum;
@@ -321,6 +327,7 @@
 	struct ieee80211_vif *roc_vif;
 
 	bool eapol4_confirm;
+	bool bt_defer_attach;
 	void *bt_adapter;
 
 	struct cfg80211_scan_request *hwscan;
@@ -402,5 +409,6 @@
 
 enum rsi_host_intf rsi_get_host_intf(void *priv);
 void rsi_set_bt_context(void *priv, void *bt_context);
+void rsi_attach_bt(struct rsi_common *common);
 
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/rsi/rsi_sdio.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/rsi/rsi_sdio.h
@@ -111,11 +111,6 @@
 	u32 buf_available_counter;
 };
 
-struct rsi_sdio_rx_q {
-	u8 num_rx_pkts;
-	struct sk_buff_head head;
-};
-
 struct rsi_91x_sdiodev {
 	struct sdio_func *pfunction;
 	struct task_struct *sdio_irq_task;
@@ -128,11 +123,10 @@
 	u16 tx_blk_size;
 	u8 write_fail;
 	bool buff_status_updated;
-	struct rsi_sdio_rx_q rx_q;
 	struct rsi_thread rx_thread;
+	u8 pktbuffer[8192] __aligned(4);
 };
 
-void rsi_interrupt_handler(struct rsi_hw *adapter);
 int rsi_init_sdio_slave_regs(struct rsi_hw *adapter);
 int rsi_sdio_read_register(struct rsi_hw *adapter, u32 addr, u8 *data);
 int rsi_sdio_host_intf_read_pkt(struct rsi_hw *adapter, u8 *pkt, u32 length);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/rsi/rsi_usb.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/rsi/rsi_usb.h
@@ -44,6 +44,8 @@
 #define RSI_USB_BUF_SIZE	     4096
 #define RSI_USB_CTRL_BUF_SIZE	     0x04
 
+#define RSI_MAX_RX_USB_PKT_SIZE	3000
+
 struct rx_usb_ctrl_block {
 	u8 *data;
 	struct urb *rx_urb;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/st/cw1200/cw1200_sdio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/st/cw1200/cw1200_sdio.c
@@ -60,6 +60,7 @@
 	{ SDIO_DEVICE(SDIO_VENDOR_ID_STE, SDIO_DEVICE_ID_STE_CW1200) },
 	{ /* end: all zeroes */			},
 };
+MODULE_DEVICE_TABLE(sdio, cw1200_sdio_ids);
 
 /* hwbus_ops implemetation */
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/st/cw1200/fwio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/st/cw1200/fwio.c
@@ -320,12 +320,12 @@
 		goto out;
 	}
 
-	priv->hw_type = cw1200_get_hw_type(val32, &major_revision);
-	if (priv->hw_type < 0) {
+	ret = cw1200_get_hw_type(val32, &major_revision);
+	if (ret < 0) {
 		pr_err("Can't deduce hardware type.\n");
-		ret = -ENOTSUPP;
 		goto out;
 	}
+	priv->hw_type = ret;
 
 	/* Set DPLL Reg value, and read back to confirm writes work */
 	ret = cw1200_reg_write_32(priv, ST90TDS_TSET_GEN_R_W_REG_ID,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/st/cw1200/main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/st/cw1200/main.c
@@ -381,6 +381,7 @@
 				    CW1200_LINK_ID_MAX,
 				    cw1200_skb_dtor,
 				    priv)) {
+		destroy_workqueue(priv->workqueue);
 		ieee80211_free_hw(hw);
 		return NULL;
 	}
@@ -392,6 +393,7 @@
 			for (; i > 0; i--)
 				cw1200_queue_deinit(&priv->tx_queue[i - 1]);
 			cw1200_queue_stats_deinit(&priv->tx_queue_stats);
+			destroy_workqueue(priv->workqueue);
 			ieee80211_free_hw(hw);
 			return NULL;
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/st/cw1200/scan.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/st/cw1200/scan.c
@@ -120,8 +120,7 @@
 		++priv->scan.n_ssids;
 	}
 
-	if (frame.skb)
-		dev_kfree_skb(frame.skb);
+	dev_kfree_skb(frame.skb);
 	mutex_unlock(&priv->conf_mutex);
 	queue_work(priv->workqueue, &priv->scan.work);
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/st/cw1200/txrx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/st/cw1200/txrx.c
@@ -1170,7 +1170,7 @@
 		size_t ies_len = skb->len - (ies - (u8 *)(skb->data));
 
 		tim_ie = cfg80211_find_ie(WLAN_EID_TIM, ies, ies_len);
-		if (tim_ie) {
+		if (tim_ie && tim_ie[1] >= sizeof(struct ieee80211_tim_ie)) {
 			struct ieee80211_tim_ie *tim =
 				(struct ieee80211_tim_ie *)&tim_ie[2];
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ti/wl1251/cmd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ti/wl1251/cmd.c
@@ -466,9 +466,12 @@
 		cmd->channels[i].channel = channels[i]->hw_value;
 	}
 
-	cmd->params.ssid_len = ssid_len;
-	if (ssid)
-		memcpy(cmd->params.ssid, ssid, ssid_len);
+	if (ssid) {
+		int len = clamp_val(ssid_len, 0, IEEE80211_MAX_SSID_LEN);
+
+		cmd->params.ssid_len = len;
+		memcpy(cmd->params.ssid, ssid, len);
+	}
 
 	ret = wl1251_cmd_send(wl, CMD_SCAN, cmd, sizeof(*cmd));
 	if (ret < 0) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ti/wl1251/event.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ti/wl1251/event.c
@@ -70,7 +70,7 @@
 		break;
 	}
 
-	return 0;
+	return ret;
 }
 
 static void wl1251_event_mbox_dump(struct event_mailbox *mbox)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ti/wl12xx/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ti/wl12xx/Kconfig
@@ -1,10 +1,10 @@
 # SPDX-License-Identifier: GPL-2.0-only
 config WL12XX
-       tristate "TI wl12xx support"
+	tristate "TI wl12xx support"
 	depends on MAC80211
-       select WLCORE
-       ---help---
+	select WLCORE
+	---help---
 	  This module adds support for wireless adapters based on TI wl1271,
 	  wl1273, wl1281 and wl1283 chipsets. This module does *not* include
 	  support for wl1251.  For wl1251 support, use the separate homonymous
-	   driver instead.
+	  driver instead.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ti/wl12xx/main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ti/wl12xx/main.c
@@ -635,7 +635,6 @@
 		wl->quirks |= WLCORE_QUIRK_LEGACY_NVS |
 			      WLCORE_QUIRK_DUAL_PROBE_TMPL |
 			      WLCORE_QUIRK_TKIP_HEADER_SPACE |
-			      WLCORE_QUIRK_START_STA_FAILS |
 			      WLCORE_QUIRK_AP_ZERO_SESSION_ID;
 		wl->sr_fw_name = WL127X_FW_NAME_SINGLE;
 		wl->mr_fw_name = WL127X_FW_NAME_MULTI;
@@ -659,7 +658,6 @@
 		wl->quirks |= WLCORE_QUIRK_LEGACY_NVS |
 			      WLCORE_QUIRK_DUAL_PROBE_TMPL |
 			      WLCORE_QUIRK_TKIP_HEADER_SPACE |
-			      WLCORE_QUIRK_START_STA_FAILS |
 			      WLCORE_QUIRK_AP_ZERO_SESSION_ID;
 		wl->plt_fw_name = WL127X_PLT_FW_NAME;
 		wl->sr_fw_name = WL127X_FW_NAME_SINGLE;
@@ -688,7 +686,6 @@
 		wl->quirks |= WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN |
 			      WLCORE_QUIRK_DUAL_PROBE_TMPL |
 			      WLCORE_QUIRK_TKIP_HEADER_SPACE |
-			      WLCORE_QUIRK_START_STA_FAILS |
 			      WLCORE_QUIRK_AP_ZERO_SESSION_ID;
 
 		wlcore_set_min_fw_ver(wl, WL128X_CHIP_VER,
@@ -1506,6 +1503,13 @@
 	u32 mac1, mac2;
 	int ret;
 
+	/* Device may be in ELP from the bootloader or kexec */
+	ret = wlcore_write32(wl, WL12XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
+	if (ret < 0)
+		goto out;
+
+	usleep_range(500000, 700000);
+
 	ret = wlcore_set_partition(wl, &wl->ptable[PART_DRPW]);
 	if (ret < 0)
 		goto out;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ti/wlcore/main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ti/wlcore/main.c
@@ -2546,24 +2546,24 @@
 	if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags) ||
 	    test_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags)) {
 		ret = -EBUSY;
-		goto out;
+		goto out_unlock;
 	}
 
 
 	ret = wl12xx_init_vif_data(wl, vif);
 	if (ret < 0)
-		goto out;
+		goto out_unlock;
 
 	wlvif->wl = wl;
 	role_type = wl12xx_get_role_type(wl, wlvif);
 	if (role_type == WL12XX_INVALID_ROLE_TYPE) {
 		ret = -EINVAL;
-		goto out;
+		goto out_unlock;
 	}
 
 	ret = wlcore_allocate_hw_queue_base(wl, wlvif);
 	if (ret < 0)
-		goto out;
+		goto out_unlock;
 
 	/*
 	 * TODO: after the nvs issue will be solved, move this block
@@ -2578,7 +2578,7 @@
 
 		ret = wl12xx_init_fw(wl);
 		if (ret < 0)
-			goto out;
+			goto out_unlock;
 	}
 
 	/*
@@ -2862,21 +2862,8 @@
 
 	if (is_ibss)
 		ret = wl12xx_cmd_role_start_ibss(wl, wlvif);
-	else {
-		if (wl->quirks & WLCORE_QUIRK_START_STA_FAILS) {
-			/*
-			 * TODO: this is an ugly workaround for wl12xx fw
-			 * bug - we are not able to tx/rx after the first
-			 * start_sta, so make dummy start+stop calls,
-			 * and then call start_sta again.
-			 * this should be fixed in the fw.
-			 */
-			wl12xx_cmd_role_start_sta(wl, wlvif);
-			wl12xx_cmd_role_stop_sta(wl, wlvif);
-		}
-
+	else
 		ret = wl12xx_cmd_role_start_sta(wl, wlvif);
-	}
 
 	return ret;
 }
@@ -3658,8 +3645,10 @@
 		goto out;
 
 	ret = pm_runtime_get_sync(wl->dev);
-	if (ret < 0)
+	if (ret < 0) {
+		pm_runtime_put_autosuspend(wl->dev);
 		goto out;
+	}
 
 	ret = wlcore_cmd_regdomain_config_locked(wl);
 	if (ret < 0) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ti/wlcore/tx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ti/wlcore/tx.c
@@ -863,6 +863,7 @@
 
 	ret = wlcore_tx_work_locked(wl);
 	if (ret < 0) {
+		pm_runtime_put_noidle(wl->dev);
 		wl12xx_queue_recovery_work(wl);
 		goto out;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/ti/wlcore/wlcore.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -547,9 +547,6 @@
 /* Each RX/TX transaction requires an end-of-transaction transfer */
 #define WLCORE_QUIRK_END_OF_TRANSACTION		BIT(0)
 
-/* the first start_role(sta) sometimes doesn't work on wl12xx */
-#define WLCORE_QUIRK_START_STA_FAILS		BIT(1)
-
 /* wl127x and SPI don't support SDIO block size alignment */
 #define WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN		BIT(2)
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/virt_wifi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/virt_wifi.c
@@ -12,6 +12,7 @@
 #include <net/cfg80211.h>
 #include <net/rtnetlink.h>
 #include <linux/etherdevice.h>
+#include <linux/math64.h>
 #include <linux/module.h>
 
 static struct wiphy *common_wiphy;
@@ -135,6 +136,32 @@
 /* Assigned at module init. Guaranteed locally-administered and unicast. */
 static u8 fake_router_bssid[ETH_ALEN] __ro_after_init = {};
 
+#define VIRT_WIFI_SSID "VirtWifi"
+#define VIRT_WIFI_SSID_LEN 8
+
+static void virt_wifi_inform_bss(struct wiphy *wiphy)
+{
+	u64 tsf = div_u64(ktime_get_boottime_ns(), 1000);
+	struct cfg80211_bss *informed_bss;
+	static const struct {
+		u8 tag;
+		u8 len;
+		u8 ssid[8];
+	} __packed ssid = {
+		.tag = WLAN_EID_SSID,
+		.len = VIRT_WIFI_SSID_LEN,
+		.ssid = VIRT_WIFI_SSID,
+	};
+
+	informed_bss = cfg80211_inform_bss(wiphy, &channel_5ghz,
+					   CFG80211_BSS_FTYPE_PRESP,
+					   fake_router_bssid, tsf,
+					   WLAN_CAPABILITY_ESS, 0,
+					   (void *)&ssid, sizeof(ssid),
+					   DBM_TO_MBM(-50), GFP_KERNEL);
+	cfg80211_put_bss(wiphy, informed_bss);
+}
+
 /* Called with the rtnl lock held. */
 static int virt_wifi_scan(struct wiphy *wiphy,
 			  struct cfg80211_scan_request *request)
@@ -155,28 +182,13 @@
 /* Acquires and releases the rdev BSS lock. */
 static void virt_wifi_scan_result(struct work_struct *work)
 {
-	struct {
-		u8 tag;
-		u8 len;
-		u8 ssid[8];
-	} __packed ssid = {
-		.tag = WLAN_EID_SSID, .len = 8, .ssid = "VirtWifi",
-	};
-	struct cfg80211_bss *informed_bss;
 	struct virt_wifi_wiphy_priv *priv =
 		container_of(work, struct virt_wifi_wiphy_priv,
 			     scan_result.work);
 	struct wiphy *wiphy = priv_to_wiphy(priv);
 	struct cfg80211_scan_info scan_info = { .aborted = false };
 
-	informed_bss = cfg80211_inform_bss(wiphy, &channel_5ghz,
-					   CFG80211_BSS_FTYPE_PRESP,
-					   fake_router_bssid,
-					   ktime_get_boottime_ns(),
-					   WLAN_CAPABILITY_ESS, 0,
-					   (void *)&ssid, sizeof(ssid),
-					   DBM_TO_MBM(-50), GFP_KERNEL);
-	cfg80211_put_bss(wiphy, informed_bss);
+	virt_wifi_inform_bss(wiphy);
 
 	/* Schedules work which acquires and releases the rtnl lock. */
 	cfg80211_scan_done(priv->scan_request, &scan_info);
@@ -204,6 +216,8 @@
 	struct net_device *upperdev;
 	u32 tx_packets;
 	u32 tx_failed;
+	u32 connect_requested_ssid_len;
+	u8 connect_requested_ssid[IEEE80211_MAX_SSID_LEN];
 	u8 connect_requested_bss[ETH_ALEN];
 	bool is_up;
 	bool is_connected;
@@ -220,14 +234,22 @@
 	if (priv->being_deleted || !priv->is_up)
 		return -EBUSY;
 
+	if (!sme->ssid)
+		return -EINVAL;
+
+	priv->connect_requested_ssid_len = sme->ssid_len;
+	memcpy(priv->connect_requested_ssid, sme->ssid, sme->ssid_len);
+
 	could_schedule = schedule_delayed_work(&priv->connect, HZ * 2);
 	if (!could_schedule)
 		return -EBUSY;
 
-	if (sme->bssid)
+	if (sme->bssid) {
 		ether_addr_copy(priv->connect_requested_bss, sme->bssid);
-	else
+	} else {
+		virt_wifi_inform_bss(wiphy);
 		eth_zero_addr(priv->connect_requested_bss);
+	}
 
 	wiphy_debug(wiphy, "connect\n");
 
@@ -240,11 +262,16 @@
 	struct virt_wifi_netdev_priv *priv =
 		container_of(work, struct virt_wifi_netdev_priv, connect.work);
 	u8 *requested_bss = priv->connect_requested_bss;
-	bool has_addr = !is_zero_ether_addr(requested_bss);
 	bool right_addr = ether_addr_equal(requested_bss, fake_router_bssid);
+	bool right_ssid = priv->connect_requested_ssid_len == VIRT_WIFI_SSID_LEN &&
+			  !memcmp(priv->connect_requested_ssid, VIRT_WIFI_SSID,
+				  priv->connect_requested_ssid_len);
 	u16 status = WLAN_STATUS_SUCCESS;
 
-	if (!priv->is_up || (has_addr && !right_addr))
+	if (is_zero_ether_addr(requested_bss))
+		requested_bss = NULL;
+
+	if (!priv->is_up || (requested_bss && !right_addr) || !right_ssid)
 		status = WLAN_STATUS_UNSPECIFIED_FAILURE;
 	else
 		priv->is_connected = true;
@@ -450,7 +477,6 @@
 	 */
 	kfree(dev->ieee80211_ptr);
 	dev->ieee80211_ptr = NULL;
-	free_netdev(dev);
 }
 
 /* No lock interaction. */
@@ -458,7 +484,7 @@
 {
 	ether_setup(dev);
 	dev->netdev_ops = &virt_wifi_ops;
-	dev->priv_destructor = virt_wifi_net_device_destructor;
+	dev->needs_free_netdev  = true;
 }
 
 /* Called in a RCU read critical section from netif_receive_skb */
@@ -544,6 +570,7 @@
 		goto unregister_netdev;
 	}
 
+	dev->priv_destructor = virt_wifi_net_device_destructor;
 	priv->being_deleted = false;
 	priv->is_connected = false;
 	priv->is_up = false;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/wl3501.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/wl3501.h
@@ -379,16 +379,7 @@
 	u8	mib_value[100];
 };
 
-struct wl3501_join_req {
-	u16			    next_blk;
-	u8			    sig_id;
-	u8			    reserved;
-	struct iw_mgmt_data_rset    operational_rset;
-	u16			    reserved2;
-	u16			    timeout;
-	u16			    probe_delay;
-	u8			    timestamp[8];
-	u8			    local_time[8];
+struct wl3501_req {
 	u16			    beacon_period;
 	u16			    dtim_period;
 	u16			    cap_info;
@@ -401,6 +392,19 @@
 	struct iw_mgmt_data_rset    bss_basic_rset;
 };
 
+struct wl3501_join_req {
+	u16			    next_blk;
+	u8			    sig_id;
+	u8			    reserved;
+	struct iw_mgmt_data_rset    operational_rset;
+	u16			    reserved2;
+	u16			    timeout;
+	u16			    probe_delay;
+	u8			    timestamp[8];
+	u8			    local_time[8];
+	struct wl3501_req	    req;
+};
+
 struct wl3501_join_confirm {
 	u16	next_blk;
 	u8	sig_id;
@@ -443,16 +447,7 @@
 	u16			    status;
 	char			    timestamp[8];
 	char			    localtime[8];
-	u16			    beacon_period;
-	u16			    dtim_period;
-	u16			    cap_info;
-	u8			    bss_type;
-	u8			    bssid[ETH_ALEN];
-	struct iw_mgmt_essid_pset   ssid;
-	struct iw_mgmt_ds_pset	    ds_pset;
-	struct iw_mgmt_cf_pset	    cf_pset;
-	struct iw_mgmt_ibss_pset    ibss_pset;
-	struct iw_mgmt_data_rset    bss_basic_rset;
+	struct wl3501_req	    req;
 	u8			    rssi;
 };
 
@@ -471,8 +466,10 @@
 	u16	size;
 	u8	pri;
 	u8	service_class;
-	u8	daddr[ETH_ALEN];
-	u8	saddr[ETH_ALEN];
+	struct {
+		u8	daddr[ETH_ALEN];
+		u8	saddr[ETH_ALEN];
+	} addr;
 };
 
 struct wl3501_md_ind {
@@ -484,8 +481,10 @@
 	u8	reception;
 	u8	pri;
 	u8	service_class;
-	u8	daddr[ETH_ALEN];
-	u8	saddr[ETH_ALEN];
+	struct {
+		u8	daddr[ETH_ALEN];
+		u8	saddr[ETH_ALEN];
+	} addr;
 };
 
 struct wl3501_md_confirm {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/wl3501_cs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/wl3501_cs.c
@@ -134,8 +134,8 @@
 
 /**
  * iw_valid_channel - validate channel in regulatory domain
- * @reg_comain - regulatory domain
- * @channel - channel to validate
+ * @reg_domain: regulatory domain
+ * @channel: channel to validate
  *
  * Returns 0 if invalid in the specified regulatory domain, non-zero if valid.
  */
@@ -154,7 +154,7 @@
 
 /**
  * iw_default_channel - get default channel for a regulatory domain
- * @reg_comain - regulatory domain
+ * @reg_domain: regulatory domain
  *
  * Returns the default channel for a regulatory domain
  */
@@ -237,6 +237,7 @@
 
 /**
  * wl3501_set_to_wla - Move 'size' bytes from PC to card
+ * @this: Card
  * @dest: Card addressing space
  * @src: PC addressing space
  * @size: Bytes to move
@@ -259,6 +260,7 @@
 
 /**
  * wl3501_get_from_wla - Move 'size' bytes from card to PC
+ * @this: Card
  * @src: Card addressing space
  * @dest: PC addressing space
  * @size: Bytes to move
@@ -455,12 +457,10 @@
 
 /**
  * wl3501_send_pkt - Send a packet.
- * @this - card
- *
- * Send a packet.
- *
- * data = Ethernet raw frame.  (e.g. data[0] - data[5] is Dest MAC Addr,
+ * @this: Card
+ * @data: Ethernet raw frame.  (e.g. data[0] - data[5] is Dest MAC Addr,
  *                                   data[6] - data[11] is Src MAC Addr)
+ * @len: Packet length
  * Ref: IEEE 802.11
  */
 static int wl3501_send_pkt(struct wl3501_card *this, u8 *data, u16 len)
@@ -469,6 +469,7 @@
 	struct wl3501_md_req sig = {
 		.sig_id = WL3501_SIG_MD_REQ,
 	};
+	size_t sig_addr_len = sizeof(sig.addr);
 	u8 *pdata = (char *)data;
 	int rc = -EIO;
 
@@ -484,9 +485,9 @@
 			goto out;
 		}
 		rc = 0;
-		memcpy(&sig.daddr[0], pdata, 12);
-		pktlen = len - 12;
-		pdata += 12;
+		memcpy(&sig.addr, pdata, sig_addr_len);
+		pktlen = len - sig_addr_len;
+		pdata += sig_addr_len;
 		sig.data = bf;
 		if (((*pdata) * 256 + (*(pdata + 1))) > 1500) {
 			u8 addr4[ETH_ALEN] = {
@@ -589,7 +590,7 @@
 	struct wl3501_join_req sig = {
 		.sig_id		  = WL3501_SIG_JOIN_REQ,
 		.timeout	  = 10,
-		.ds_pset = {
+		.req.ds_pset = {
 			.el = {
 				.id  = IW_MGMT_INFO_ELEMENT_DS_PARAMETER_SET,
 				.len = 1,
@@ -598,7 +599,7 @@
 		},
 	};
 
-	memcpy(&sig.beacon_period, &this->bss_set[stas].beacon_period, 72);
+	memcpy(&sig.req, &this->bss_set[stas].req, sizeof(sig.req));
 	return wl3501_esbq_exec(this, &sig, sizeof(sig));
 }
 
@@ -666,35 +667,37 @@
 	if (sig.status == WL3501_STATUS_SUCCESS) {
 		pr_debug("success");
 		if ((this->net_type == IW_MODE_INFRA &&
-		     (sig.cap_info & WL3501_MGMT_CAPABILITY_ESS)) ||
+		     (sig.req.cap_info & WL3501_MGMT_CAPABILITY_ESS)) ||
 		    (this->net_type == IW_MODE_ADHOC &&
-		     (sig.cap_info & WL3501_MGMT_CAPABILITY_IBSS)) ||
+		     (sig.req.cap_info & WL3501_MGMT_CAPABILITY_IBSS)) ||
 		    this->net_type == IW_MODE_AUTO) {
 			if (!this->essid.el.len)
 				matchflag = 1;
 			else if (this->essid.el.len == 3 &&
 				 !memcmp(this->essid.essid, "ANY", 3))
 				matchflag = 1;
-			else if (this->essid.el.len != sig.ssid.el.len)
+			else if (this->essid.el.len != sig.req.ssid.el.len)
 				matchflag = 0;
-			else if (memcmp(this->essid.essid, sig.ssid.essid,
+			else if (memcmp(this->essid.essid, sig.req.ssid.essid,
 					this->essid.el.len))
 				matchflag = 0;
 			else
 				matchflag = 1;
 			if (matchflag) {
 				for (i = 0; i < this->bss_cnt; i++) {
-					if (ether_addr_equal_unaligned(this->bss_set[i].bssid, sig.bssid)) {
+					if (ether_addr_equal_unaligned(this->bss_set[i].req.bssid,
+								       sig.req.bssid)) {
 						matchflag = 0;
 						break;
 					}
 				}
 			}
 			if (matchflag && (i < 20)) {
-				memcpy(&this->bss_set[i].beacon_period,
-				       &sig.beacon_period, 73);
+				memcpy(&this->bss_set[i].req,
+				       &sig.req, sizeof(sig.req));
 				this->bss_cnt++;
 				this->rssi = sig.rssi;
+				this->bss_set[i].rssi = sig.rssi;
 			}
 		}
 	} else if (sig.status == WL3501_STATUS_TIMEOUT) {
@@ -720,7 +723,7 @@
 
 /**
  * wl3501_block_interrupt - Mask interrupt from SUTRO
- * @this - card
+ * @this: Card
  *
  * Mask interrupt from SUTRO. (i.e. SUTRO cannot interrupt the HOST)
  * Return: 1 if interrupt is originally enabled
@@ -737,7 +740,7 @@
 
 /**
  * wl3501_unblock_interrupt - Enable interrupt from SUTRO
- * @this - card
+ * @this: Card
  *
  * Enable interrupt from SUTRO. (i.e. SUTRO can interrupt the HOST)
  * Return: 1 if interrupt is originally enabled
@@ -886,19 +889,19 @@
 			if (this->join_sta_bss < this->bss_cnt) {
 				const int i = this->join_sta_bss;
 				memcpy(this->bssid,
-				       this->bss_set[i].bssid, ETH_ALEN);
-				this->chan = this->bss_set[i].ds_pset.chan;
+				       this->bss_set[i].req.bssid, ETH_ALEN);
+				this->chan = this->bss_set[i].req.ds_pset.chan;
 				iw_copy_mgmt_info_element(&this->keep_essid.el,
-						     &this->bss_set[i].ssid.el);
+						     &this->bss_set[i].req.ssid.el);
 				wl3501_mgmt_auth(this);
 			}
 		} else {
 			const int i = this->join_sta_bss;
 
-			memcpy(&this->bssid, &this->bss_set[i].bssid, ETH_ALEN);
-			this->chan = this->bss_set[i].ds_pset.chan;
+			memcpy(&this->bssid, &this->bss_set[i].req.bssid, ETH_ALEN);
+			this->chan = this->bss_set[i].req.ds_pset.chan;
 			iw_copy_mgmt_info_element(&this->keep_essid.el,
-						  &this->bss_set[i].ssid.el);
+						  &this->bss_set[i].req.ssid.el);
 			wl3501_online(dev);
 		}
 	} else {
@@ -980,7 +983,8 @@
 	} else {
 		skb->dev = dev;
 		skb_reserve(skb, 2); /* IP headers on 16 bytes boundaries */
-		skb_copy_to_linear_data(skb, (unsigned char *)&sig.daddr, 12);
+		skb_copy_to_linear_data(skb, (unsigned char *)&sig.addr,
+					sizeof(sig.addr));
 		wl3501_receive(this, skb->data, pkt_len);
 		skb_put(skb, pkt_len);
 		skb->protocol	= eth_type_trans(skb, dev);
@@ -1110,8 +1114,8 @@
 
 /**
  * wl3501_interrupt - Hardware interrupt from card.
- * @irq - Interrupt number
- * @dev_id - net_device
+ * @irq: Interrupt number
+ * @dev_id: net_device
  *
  * We must acknowledge the interrupt as soon as possible, and block the
  * interrupt from the same card immediately to prevent re-entry.
@@ -1247,7 +1251,7 @@
 
 /**
  * wl3501_reset - Reset the SUTRO.
- * @dev - network device
+ * @dev: network device
  *
  * It is almost the same as wl3501_open(). In fact, we may just wl3501_close()
  * and wl3501_open() again, but I wouldn't like to free_irq() when the driver
@@ -1324,7 +1328,7 @@
 	} else {
 		++dev->stats.tx_packets;
 		dev->stats.tx_bytes += skb->len;
-		kfree_skb(skb);
+		dev_kfree_skb_irq(skb);
 
 		if (this->tx_buffer_cnt < 2)
 			netif_stop_queue(dev);
@@ -1410,7 +1414,7 @@
 
 /**
  * wl3501_detach - deletes a driver "instance"
- * @link - FILL_IN
+ * @link: FILL_IN
  *
  * This deletes a driver "instance". The device is de-registered with Card
  * Services. If it has been released, all local data structures are freed.
@@ -1431,9 +1435,7 @@
 	wl3501_release(link);
 
 	unregister_netdev(dev);
-
-	if (link->priv)
-		free_netdev(link->priv);
+	free_netdev(dev);
 }
 
 static int wl3501_get_name(struct net_device *dev, struct iw_request_info *info,
@@ -1573,30 +1575,30 @@
 	for (i = 0; i < this->bss_cnt; ++i) {
 		iwe.cmd			= SIOCGIWAP;
 		iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
-		memcpy(iwe.u.ap_addr.sa_data, this->bss_set[i].bssid, ETH_ALEN);
+		memcpy(iwe.u.ap_addr.sa_data, this->bss_set[i].req.bssid, ETH_ALEN);
 		current_ev = iwe_stream_add_event(info, current_ev,
 						  extra + IW_SCAN_MAX_DATA,
 						  &iwe, IW_EV_ADDR_LEN);
 		iwe.cmd		  = SIOCGIWESSID;
 		iwe.u.data.flags  = 1;
-		iwe.u.data.length = this->bss_set[i].ssid.el.len;
+		iwe.u.data.length = this->bss_set[i].req.ssid.el.len;
 		current_ev = iwe_stream_add_point(info, current_ev,
 						  extra + IW_SCAN_MAX_DATA,
 						  &iwe,
-						  this->bss_set[i].ssid.essid);
+						  this->bss_set[i].req.ssid.essid);
 		iwe.cmd	   = SIOCGIWMODE;
-		iwe.u.mode = this->bss_set[i].bss_type;
+		iwe.u.mode = this->bss_set[i].req.bss_type;
 		current_ev = iwe_stream_add_event(info, current_ev,
 						  extra + IW_SCAN_MAX_DATA,
 						  &iwe, IW_EV_UINT_LEN);
 		iwe.cmd = SIOCGIWFREQ;
-		iwe.u.freq.m = this->bss_set[i].ds_pset.chan;
+		iwe.u.freq.m = this->bss_set[i].req.ds_pset.chan;
 		iwe.u.freq.e = 0;
 		current_ev = iwe_stream_add_event(info, current_ev,
 						  extra + IW_SCAN_MAX_DATA,
 						  &iwe, IW_EV_FREQ_LEN);
 		iwe.cmd = SIOCGIWENCODE;
-		if (this->bss_set[i].cap_info & WL3501_MGMT_CAPABILITY_PRIVACY)
+		if (this->bss_set[i].req.cap_info & WL3501_MGMT_CAPABILITY_PRIVACY)
 			iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
 		else
 			iwe.u.data.flags = IW_ENCODE_DISABLED;
@@ -1860,6 +1862,7 @@
 {
 	struct net_device *dev;
 	struct wl3501_card *this;
+	int ret;
 
 	/* The io structure describes IO port mapping */
 	p_dev->resource[0]->end	= 16;
@@ -1871,8 +1874,7 @@
 
 	dev = alloc_etherdev(sizeof(struct wl3501_card));
 	if (!dev)
-		goto out_link;
-
+		return -ENOMEM;
 
 	dev->netdev_ops		= &wl3501_netdev_ops;
 	dev->watchdog_timeo	= 5 * HZ;
@@ -1885,9 +1887,15 @@
 	netif_stop_queue(dev);
 	p_dev->priv = dev;
 
-	return wl3501_config(p_dev);
-out_link:
-	return -ENOMEM;
+	ret = wl3501_config(p_dev);
+	if (ret)
+		goto out_free_etherdev;
+
+	return 0;
+
+out_free_etherdev:
+	free_netdev(dev);
+	return ret;
 }
 
 static int wl3501_config(struct pcmcia_device *link)
@@ -1943,8 +1951,7 @@
 		goto failed;
 	}
 
-	for (i = 0; i < 6; i++)
-		dev->dev_addr[i] = ((char *)&this->mac_addr)[i];
+	eth_hw_addr_set(dev, this->mac_addr);
 
 	/* print probe information */
 	printk(KERN_INFO "%s: wl3501 @ 0x%3.3x, IRQ %d, "
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/wireless/zydas/zd1211rw/zd_usb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/wireless/zydas/zd1211rw/zd_usb.c
@@ -1263,7 +1263,7 @@
 static int eject_installer(struct usb_interface *intf)
 {
 	struct usb_device *udev = interface_to_usbdev(intf);
-	struct usb_host_interface *iface_desc = &intf->altsetting[0];
+	struct usb_host_interface *iface_desc = intf->cur_altsetting;
 	struct usb_endpoint_descriptor *endpoint;
 	unsigned char *cmd;
 	u8 bulk_out_ep;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/xen-netback/common.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/xen-netback/common.h
@@ -48,7 +48,6 @@
 #include <linux/debugfs.h>
 
 typedef unsigned int pending_ring_idx_t;
-#define INVALID_PENDING_RING_IDX (~0U)
 
 struct pending_tx_info {
 	struct xen_netif_tx_request req; /* tx request */
@@ -82,8 +81,6 @@
 /* Discriminate from any valid pending_idx value. */
 #define INVALID_PENDING_IDX 0xFFFF
 
-#define MAX_BUFFER_OFFSET XEN_PAGE_SIZE
-
 #define MAX_PENDING_REQS XEN_NETIF_TX_RING_SIZE
 
 /* The maximum number of frags is derived from the size of a grant (same
@@ -140,6 +137,20 @@
 	char name[QUEUE_NAME_SIZE]; /* DEVNAME-qN */
 	struct xenvif *vif; /* Parent VIF */
 
+	/*
+	 * TX/RX common EOI handling.
+	 * When feature-split-event-channels = 0, interrupt handler sets
+	 * NETBK_COMMON_EOI, otherwise NETBK_RX_EOI and NETBK_TX_EOI are set
+	 * by the RX and TX interrupt handlers.
+	 * RX and TX handler threads will issue an EOI when either
+	 * NETBK_COMMON_EOI or their specific bits (NETBK_RX_EOI or
+	 * NETBK_TX_EOI) are set and they will reset those bits.
+	 */
+	atomic_t eoi_pending;
+#define NETBK_RX_EOI		0x01
+#define NETBK_TX_EOI		0x02
+#define NETBK_COMMON_EOI	0x04
+
 	/* Use NAPI for guest TX */
 	struct napi_struct napi;
 	/* When feature-split-event-channels = 0, tx_irq = rx_irq. */
@@ -155,7 +166,7 @@
 	struct pending_tx_info pending_tx_info[MAX_PENDING_REQS];
 	grant_handle_t grant_tx_handle[MAX_PENDING_REQS];
 
-	struct gnttab_copy tx_copy_ops[MAX_PENDING_REQS];
+	struct gnttab_copy tx_copy_ops[2 * MAX_PENDING_REQS];
 	struct gnttab_map_grant_ref tx_map_ops[MAX_PENDING_REQS];
 	struct gnttab_unmap_grant_ref tx_unmap_ops[MAX_PENDING_REQS];
 	/* passed to gnttab_[un]map_refs with pages under (un)mapping */
@@ -189,6 +200,7 @@
 	unsigned int rx_queue_max;
 	unsigned int rx_queue_len;
 	unsigned long last_rx_time;
+	unsigned int rx_slots_needed;
 	bool stalled;
 
 	struct xenvif_copy_state rx_copy;
@@ -349,11 +361,6 @@
 int xenvif_xenbus_init(void);
 void xenvif_xenbus_fini(void);
 
-int xenvif_schedulable(struct xenvif *vif);
-
-int xenvif_queue_stopped(struct xenvif_queue *queue);
-void xenvif_wake_queue(struct xenvif_queue *queue);
-
 /* (Un)Map communication rings. */
 void xenvif_unmap_frontend_data_rings(struct xenvif_queue *queue);
 int xenvif_map_frontend_data_rings(struct xenvif_queue *queue,
@@ -375,17 +382,14 @@
 
 irqreturn_t xenvif_ctrl_irq_fn(int irq, void *data);
 
-void xenvif_rx_action(struct xenvif_queue *queue);
-void xenvif_rx_queue_tail(struct xenvif_queue *queue, struct sk_buff *skb);
+bool xenvif_have_rx_work(struct xenvif_queue *queue, bool test_kthread);
+bool xenvif_rx_queue_tail(struct xenvif_queue *queue, struct sk_buff *skb);
 
 void xenvif_carrier_on(struct xenvif *vif);
 
 /* Callback from stack when TX packet can be released */
 void xenvif_zerocopy_callback(struct ubuf_info *ubuf, bool zerocopy_success);
 
-/* Unmap a pending page and release it back to the guest */
-void xenvif_idx_unmap(struct xenvif_queue *queue, u16 pending_idx);
-
 static inline pending_ring_idx_t nr_pending_reqs(struct xenvif_queue *queue)
 {
 	return MAX_PENDING_REQS -
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/xen-netback/hash.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/xen-netback/hash.c
@@ -51,7 +51,8 @@
 
 	found = false;
 	oldest = NULL;
-	list_for_each_entry_rcu(entry, &vif->hash.cache.list, link) {
+	list_for_each_entry_rcu(entry, &vif->hash.cache.list, link,
+				lockdep_is_held(&vif->hash.cache.lock)) {
 		/* Make sure we don't add duplicate entries */
 		if (entry->len == len &&
 		    memcmp(entry->tag, tag, len) == 0)
@@ -94,7 +95,7 @@
 
 static void xenvif_flush_hash(struct xenvif *vif)
 {
-	struct xenvif_hash_cache_entry *entry;
+	struct xenvif_hash_cache_entry *entry, *n;
 	unsigned long flags;
 
 	if (xenvif_hash_cache_size == 0)
@@ -102,7 +103,7 @@
 
 	spin_lock_irqsave(&vif->hash.cache.lock, flags);
 
-	list_for_each_entry_rcu(entry, &vif->hash.cache.list, link) {
+	list_for_each_entry_safe(entry, n, &vif->hash.cache.list, link) {
 		list_del_rcu(&entry->link);
 		vif->hash.cache.count--;
 		kfree_rcu(entry, rcu);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/xen-netback/interface.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/xen-netback/interface.c
@@ -41,7 +41,6 @@
 #include <asm/xen/hypercall.h>
 #include <xen/balloon.h>
 
-#define XENVIF_QUEUE_LENGTH 32
 #define XENVIF_NAPI_WEIGHT  64
 
 /* Number of bytes allowed on the internal guest Rx queue. */
@@ -70,19 +69,35 @@
 	wake_up(&queue->dealloc_wq);
 }
 
-int xenvif_schedulable(struct xenvif *vif)
+static int xenvif_schedulable(struct xenvif *vif)
 {
 	return netif_running(vif->dev) &&
 		test_bit(VIF_STATUS_CONNECTED, &vif->status) &&
 		!vif->disabled;
 }
 
+static bool xenvif_handle_tx_interrupt(struct xenvif_queue *queue)
+{
+	bool rc;
+
+	rc = RING_HAS_UNCONSUMED_REQUESTS(&queue->tx);
+	if (rc)
+		napi_schedule(&queue->napi);
+	return rc;
+}
+
 static irqreturn_t xenvif_tx_interrupt(int irq, void *dev_id)
 {
 	struct xenvif_queue *queue = dev_id;
+	int old;
 
-	if (RING_HAS_UNCONSUMED_REQUESTS(&queue->tx))
-		napi_schedule(&queue->napi);
+	old = atomic_fetch_or(NETBK_TX_EOI, &queue->eoi_pending);
+	WARN(old & NETBK_TX_EOI, "Interrupt while EOI pending\n");
+
+	if (!xenvif_handle_tx_interrupt(queue)) {
+		atomic_andnot(NETBK_TX_EOI, &queue->eoi_pending);
+		xen_irq_lateeoi(irq, XEN_EOI_FLAG_SPURIOUS);
+	}
 
 	return IRQ_HANDLED;
 }
@@ -116,35 +131,50 @@
 	return work_done;
 }
 
+static bool xenvif_handle_rx_interrupt(struct xenvif_queue *queue)
+{
+	bool rc;
+
+	rc = xenvif_have_rx_work(queue, false);
+	if (rc)
+		xenvif_kick_thread(queue);
+	return rc;
+}
+
 static irqreturn_t xenvif_rx_interrupt(int irq, void *dev_id)
 {
 	struct xenvif_queue *queue = dev_id;
+	int old;
 
-	xenvif_kick_thread(queue);
+	old = atomic_fetch_or(NETBK_RX_EOI, &queue->eoi_pending);
+	WARN(old & NETBK_RX_EOI, "Interrupt while EOI pending\n");
+
+	if (!xenvif_handle_rx_interrupt(queue)) {
+		atomic_andnot(NETBK_RX_EOI, &queue->eoi_pending);
+		xen_irq_lateeoi(irq, XEN_EOI_FLAG_SPURIOUS);
+	}
 
 	return IRQ_HANDLED;
 }
 
 irqreturn_t xenvif_interrupt(int irq, void *dev_id)
 {
-	xenvif_tx_interrupt(irq, dev_id);
-	xenvif_rx_interrupt(irq, dev_id);
+	struct xenvif_queue *queue = dev_id;
+	int old;
+	bool has_rx, has_tx;
 
-	return IRQ_HANDLED;
-}
+	old = atomic_fetch_or(NETBK_COMMON_EOI, &queue->eoi_pending);
+	WARN(old, "Interrupt while EOI pending\n");
 
-int xenvif_queue_stopped(struct xenvif_queue *queue)
-{
-	struct net_device *dev = queue->vif->dev;
-	unsigned int id = queue->id;
-	return netif_tx_queue_stopped(netdev_get_tx_queue(dev, id));
-}
+	has_tx = xenvif_handle_tx_interrupt(queue);
+	has_rx = xenvif_handle_rx_interrupt(queue);
 
-void xenvif_wake_queue(struct xenvif_queue *queue)
-{
-	struct net_device *dev = queue->vif->dev;
-	unsigned int id = queue->id;
-	netif_tx_wake_queue(netdev_get_tx_queue(dev, id));
+	if (!has_rx && !has_tx) {
+		atomic_andnot(NETBK_COMMON_EOI, &queue->eoi_pending);
+		xen_irq_lateeoi(irq, XEN_EOI_FLAG_SPURIOUS);
+	}
+
+	return IRQ_HANDLED;
 }
 
 static u16 xenvif_select_queue(struct net_device *dev, struct sk_buff *skb,
@@ -224,14 +254,16 @@
 	if (vif->hash.alg == XEN_NETIF_CTRL_HASH_ALGORITHM_NONE)
 		skb_clear_hash(skb);
 
-	xenvif_rx_queue_tail(queue, skb);
+	if (!xenvif_rx_queue_tail(queue, skb))
+		goto drop;
+
 	xenvif_kick_thread(queue);
 
 	return NETDEV_TX_OK;
 
  drop:
 	vif->dev->stats.tx_dropped++;
-	dev_kfree_skb(skb);
+	dev_kfree_skb_any(skb);
 	return NETDEV_TX_OK;
 }
 
@@ -493,8 +525,6 @@
 	dev->features = dev->hw_features | NETIF_F_RXCSUM;
 	dev->ethtool_ops = &xenvif_ethtool_ops;
 
-	dev->tx_queue_len = XENVIF_QUEUE_LENGTH;
-
 	dev->min_mtu = ETH_MIN_MTU;
 	dev->max_mtu = ETH_MAX_MTU - VLAN_ETH_HLEN;
 
@@ -595,7 +625,7 @@
 	shared = (struct xen_netif_ctrl_sring *)addr;
 	BACK_RING_INIT(&vif->ctrl, shared, XEN_PAGE_SIZE);
 
-	err = bind_interdomain_evtchn_to_irq(vif->domid, evtchn);
+	err = bind_interdomain_evtchn_to_irq_lateeoi(vif->domid, evtchn);
 	if (err < 0)
 		goto err_unmap;
 
@@ -653,7 +683,7 @@
 
 	if (tx_evtchn == rx_evtchn) {
 		/* feature-split-event-channels == 0 */
-		err = bind_interdomain_evtchn_to_irqhandler(
+		err = bind_interdomain_evtchn_to_irqhandler_lateeoi(
 			queue->vif->domid, tx_evtchn, xenvif_interrupt, 0,
 			queue->name, queue);
 		if (err < 0)
@@ -664,7 +694,7 @@
 		/* feature-split-event-channels == 1 */
 		snprintf(queue->tx_irq_name, sizeof(queue->tx_irq_name),
 			 "%s-tx", queue->name);
-		err = bind_interdomain_evtchn_to_irqhandler(
+		err = bind_interdomain_evtchn_to_irqhandler_lateeoi(
 			queue->vif->domid, tx_evtchn, xenvif_tx_interrupt, 0,
 			queue->tx_irq_name, queue);
 		if (err < 0)
@@ -674,7 +704,7 @@
 
 		snprintf(queue->rx_irq_name, sizeof(queue->rx_irq_name),
 			 "%s-rx", queue->name);
-		err = bind_interdomain_evtchn_to_irqhandler(
+		err = bind_interdomain_evtchn_to_irqhandler_lateeoi(
 			queue->vif->domid, rx_evtchn, xenvif_rx_interrupt, 0,
 			queue->rx_irq_name, queue);
 		if (err < 0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/xen-netback/netback.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/xen-netback/netback.c
@@ -97,13 +97,14 @@
 MODULE_PARM_DESC(hash_cache_size, "Number of flows in the hash cache");
 
 static void xenvif_idx_release(struct xenvif_queue *queue, u16 pending_idx,
-			       u8 status);
+			       s8 status);
 
 static void make_tx_response(struct xenvif_queue *queue,
-			     struct xen_netif_tx_request *txp,
+			     const struct xen_netif_tx_request *txp,
 			     unsigned int extra_count,
-			     s8       st);
-static void push_tx_responses(struct xenvif_queue *queue);
+			     s8 status);
+
+static void xenvif_idx_unmap(struct xenvif_queue *queue, u16 pending_idx);
 
 static inline int tx_work_todo(struct xenvif_queue *queue);
 
@@ -162,6 +163,10 @@
 
 	if (more_to_do)
 		napi_schedule(&queue->napi);
+	else if (atomic_fetch_andnot(NETBK_TX_EOI | NETBK_COMMON_EOI,
+				     &queue->eoi_pending) &
+		 (NETBK_TX_EOI | NETBK_COMMON_EOI))
+		xen_irq_lateeoi(queue->tx_irq, 0);
 }
 
 static void tx_add_credit(struct xenvif_queue *queue)
@@ -195,13 +200,9 @@
 			  unsigned int extra_count, RING_IDX end)
 {
 	RING_IDX cons = queue->tx.req_cons;
-	unsigned long flags;
 
 	do {
-		spin_lock_irqsave(&queue->response_lock, flags);
 		make_tx_response(queue, txp, extra_count, XEN_NETIF_RSP_ERROR);
-		push_tx_responses(queue);
-		spin_unlock_irqrestore(&queue->response_lock, flags);
 		if (cons == end)
 			break;
 		RING_COPY_REQUEST(&queue->tx, cons++, txp);
@@ -319,10 +320,14 @@
 
 
 struct xenvif_tx_cb {
-	u16 pending_idx;
+	u16 copy_pending_idx[XEN_NETBK_LEGACY_SLOTS_MAX + 1];
+	u8 copy_count;
+	u32 split_mask;
 };
 
 #define XENVIF_TX_CB(skb) ((struct xenvif_tx_cb *)(skb)->cb)
+#define copy_pending_idx(skb, i) (XENVIF_TX_CB(skb)->copy_pending_idx[i])
+#define copy_count(skb) (XENVIF_TX_CB(skb)->copy_count)
 
 static inline void xenvif_tx_create_map_op(struct xenvif_queue *queue,
 					   u16 pending_idx,
@@ -345,6 +350,8 @@
 	struct sk_buff *skb =
 		alloc_skb(size + NET_SKB_PAD + NET_IP_ALIGN,
 			  GFP_ATOMIC | __GFP_NOWARN);
+
+	BUILD_BUG_ON(sizeof(*XENVIF_TX_CB(skb)) > sizeof(skb->cb));
 	if (unlikely(skb == NULL))
 		return NULL;
 
@@ -357,52 +364,152 @@
 	return skb;
 }
 
-static struct gnttab_map_grant_ref *xenvif_get_requests(struct xenvif_queue *queue,
-							struct sk_buff *skb,
-							struct xen_netif_tx_request *txp,
-							struct gnttab_map_grant_ref *gop,
-							unsigned int frag_overflow,
-							struct sk_buff *nskb)
+static void xenvif_get_requests(struct xenvif_queue *queue,
+				struct sk_buff *skb,
+				struct xen_netif_tx_request *first,
+				struct xen_netif_tx_request *txfrags,
+			        unsigned *copy_ops,
+			        unsigned *map_ops,
+				unsigned int frag_overflow,
+				struct sk_buff *nskb,
+				unsigned int extra_count,
+				unsigned int data_len)
 {
 	struct skb_shared_info *shinfo = skb_shinfo(skb);
 	skb_frag_t *frags = shinfo->frags;
-	u16 pending_idx = XENVIF_TX_CB(skb)->pending_idx;
-	int start;
+	u16 pending_idx;
 	pending_ring_idx_t index;
 	unsigned int nr_slots;
+	struct gnttab_copy *cop = queue->tx_copy_ops + *copy_ops;
+	struct gnttab_map_grant_ref *gop = queue->tx_map_ops + *map_ops;
+	struct xen_netif_tx_request *txp = first;
+
+	nr_slots = shinfo->nr_frags + frag_overflow + 1;
+
+	copy_count(skb) = 0;
+	XENVIF_TX_CB(skb)->split_mask = 0;
+
+	/* Create copy ops for exactly data_len bytes into the skb head. */
+	__skb_put(skb, data_len);
+	while (data_len > 0) {
+		int amount = data_len > txp->size ? txp->size : data_len;
+		bool split = false;
+
+		cop->source.u.ref = txp->gref;
+		cop->source.domid = queue->vif->domid;
+		cop->source.offset = txp->offset;
+
+		cop->dest.domid = DOMID_SELF;
+		cop->dest.offset = (offset_in_page(skb->data +
+						   skb_headlen(skb) -
+						   data_len)) & ~XEN_PAGE_MASK;
+		cop->dest.u.gmfn = virt_to_gfn(skb->data + skb_headlen(skb)
+				               - data_len);
+
+		/* Don't cross local page boundary! */
+		if (cop->dest.offset + amount > XEN_PAGE_SIZE) {
+			amount = XEN_PAGE_SIZE - cop->dest.offset;
+			XENVIF_TX_CB(skb)->split_mask |= 1U << copy_count(skb);
+			split = true;
+		}
+
+		cop->len = amount;
+		cop->flags = GNTCOPY_source_gref;
+
+		index = pending_index(queue->pending_cons);
+		pending_idx = queue->pending_ring[index];
+		callback_param(queue, pending_idx).ctx = NULL;
+		copy_pending_idx(skb, copy_count(skb)) = pending_idx;
+		if (!split)
+			copy_count(skb)++;
+
+		cop++;
+		data_len -= amount;
 
-	nr_slots = shinfo->nr_frags;
+		if (amount == txp->size) {
+			/* The copy op covered the full tx_request */
 
-	/* Skip first skb fragment if it is on same page as header fragment. */
-	start = (frag_get_pending_idx(&shinfo->frags[0]) == pending_idx);
+			memcpy(&queue->pending_tx_info[pending_idx].req,
+			       txp, sizeof(*txp));
+			queue->pending_tx_info[pending_idx].extra_count =
+				(txp == first) ? extra_count : 0;
+
+			if (txp == first)
+				txp = txfrags;
+			else
+				txp++;
+			queue->pending_cons++;
+			nr_slots--;
+		} else {
+			/* The copy op partially covered the tx_request.
+			 * The remainder will be mapped or copied in the next
+			 * iteration.
+			 */
+			txp->offset += amount;
+			txp->size -= amount;
+		}
+	}
+
+	for (shinfo->nr_frags = 0; nr_slots > 0 && shinfo->nr_frags < MAX_SKB_FRAGS;
+	     nr_slots--) {
+		if (unlikely(!txp->size)) {
+			make_tx_response(queue, txp, 0, XEN_NETIF_RSP_OKAY);
+			++txp;
+			continue;
+		}
 
-	for (shinfo->nr_frags = start; shinfo->nr_frags < nr_slots;
-	     shinfo->nr_frags++, txp++, gop++) {
 		index = pending_index(queue->pending_cons++);
 		pending_idx = queue->pending_ring[index];
-		xenvif_tx_create_map_op(queue, pending_idx, txp, 0, gop);
+		xenvif_tx_create_map_op(queue, pending_idx, txp,
+				        txp == first ? extra_count : 0, gop);
 		frag_set_pending_idx(&frags[shinfo->nr_frags], pending_idx);
+		++shinfo->nr_frags;
+		++gop;
+
+		if (txp == first)
+			txp = txfrags;
+		else
+			txp++;
 	}
 
-	if (frag_overflow) {
+	if (nr_slots > 0) {
 
 		shinfo = skb_shinfo(nskb);
 		frags = shinfo->frags;
 
-		for (shinfo->nr_frags = 0; shinfo->nr_frags < frag_overflow;
-		     shinfo->nr_frags++, txp++, gop++) {
+		for (shinfo->nr_frags = 0; shinfo->nr_frags < nr_slots; ++txp) {
+			if (unlikely(!txp->size)) {
+				make_tx_response(queue, txp, 0,
+						 XEN_NETIF_RSP_OKAY);
+				continue;
+			}
+
 			index = pending_index(queue->pending_cons++);
 			pending_idx = queue->pending_ring[index];
 			xenvif_tx_create_map_op(queue, pending_idx, txp, 0,
 						gop);
 			frag_set_pending_idx(&frags[shinfo->nr_frags],
 					     pending_idx);
+			++shinfo->nr_frags;
+			++gop;
+		}
+
+		if (shinfo->nr_frags) {
+			skb_shinfo(skb)->frag_list = nskb;
+			nskb = NULL;
 		}
+	}
 
-		skb_shinfo(skb)->frag_list = nskb;
+	if (nskb) {
+		/* A frag_list skb was allocated but it is no longer needed
+		 * because enough slots were converted to copy ops above or some
+		 * were empty.
+		 */
+		kfree_skb(nskb);
 	}
 
-	return gop;
+	(*copy_ops) = cop - queue->tx_copy_ops;
+	(*map_ops) = gop - queue->tx_map_ops;
 }
 
 static inline void xenvif_grant_handle_set(struct xenvif_queue *queue,
@@ -438,7 +545,7 @@
 			       struct gnttab_copy **gopp_copy)
 {
 	struct gnttab_map_grant_ref *gop_map = *gopp_map;
-	u16 pending_idx = XENVIF_TX_CB(skb)->pending_idx;
+	u16 pending_idx;
 	/* This always points to the shinfo of the skb being checked, which
 	 * could be either the first or the one on the frag_list
 	 */
@@ -449,24 +556,44 @@
 	struct skb_shared_info *first_shinfo = NULL;
 	int nr_frags = shinfo->nr_frags;
 	const bool sharedslot = nr_frags &&
-				frag_get_pending_idx(&shinfo->frags[0]) == pending_idx;
-	int i, err;
-
-	/* Check status of header. */
-	err = (*gopp_copy)->status;
-	if (unlikely(err)) {
-		if (net_ratelimit())
-			netdev_dbg(queue->vif->dev,
-				   "Grant copy of header failed! status: %d pending_idx: %u ref: %u\n",
-				   (*gopp_copy)->status,
-				   pending_idx,
-				   (*gopp_copy)->source.u.ref);
-		/* The first frag might still have this slot mapped */
-		if (!sharedslot)
-			xenvif_idx_release(queue, pending_idx,
-					   XEN_NETIF_RSP_ERROR);
+				frag_get_pending_idx(&shinfo->frags[0]) ==
+				    copy_pending_idx(skb, copy_count(skb) - 1);
+	int i, err = 0;
+
+	for (i = 0; i < copy_count(skb); i++) {
+		int newerr;
+
+		/* Check status of header. */
+		pending_idx = copy_pending_idx(skb, i);
+
+		newerr = (*gopp_copy)->status;
+
+		/* Split copies need to be handled together. */
+		if (XENVIF_TX_CB(skb)->split_mask & (1U << i)) {
+			(*gopp_copy)++;
+			if (!newerr)
+				newerr = (*gopp_copy)->status;
+		}
+		if (likely(!newerr)) {
+			/* The first frag might still have this slot mapped */
+			if (i < copy_count(skb) - 1 || !sharedslot)
+				xenvif_idx_release(queue, pending_idx,
+						   XEN_NETIF_RSP_OKAY);
+		} else {
+			err = newerr;
+			if (net_ratelimit())
+				netdev_dbg(queue->vif->dev,
+					   "Grant copy of header failed! status: %d pending_idx: %u ref: %u\n",
+					   (*gopp_copy)->status,
+					   pending_idx,
+					   (*gopp_copy)->source.u.ref);
+			/* The first frag might still have this slot mapped */
+			if (i < copy_count(skb) - 1 || !sharedslot)
+				xenvif_idx_release(queue, pending_idx,
+						   XEN_NETIF_RSP_ERROR);
+		}
+		(*gopp_copy)++;
 	}
-	(*gopp_copy)++;
 
 check_frags:
 	for (i = 0; i < nr_frags; i++, gop_map++) {
@@ -488,7 +615,7 @@
 				 * the header's copy failed, and they are
 				 * sharing a slot, send an error
 				 */
-				if (i == 0 && sharedslot)
+				if (i == 0 && !first_shinfo && sharedslot)
 					xenvif_idx_release(queue, pending_idx,
 							   XEN_NETIF_RSP_ERROR);
 				else
@@ -513,14 +640,6 @@
 		if (err)
 			continue;
 
-		/* First error: if the header haven't shared a slot with the
-		 * first frag, release it as well.
-		 */
-		if (!sharedslot)
-			xenvif_idx_release(queue,
-					   XENVIF_TX_CB(skb)->pending_idx,
-					   XEN_NETIF_RSP_OKAY);
-
 		/* Invalidate preceding fragments of this skb. */
 		for (j = 0; j < i; j++) {
 			pending_idx = frag_get_pending_idx(&shinfo->frags[j]);
@@ -790,7 +909,6 @@
 				     unsigned *copy_ops,
 				     unsigned *map_ops)
 {
-	struct gnttab_map_grant_ref *gop = queue->tx_map_ops;
 	struct sk_buff *skb, *nskb;
 	int ret;
 	unsigned int frag_overflow;
@@ -856,7 +974,6 @@
 					 (ret == 0) ?
 					 XEN_NETIF_RSP_OKAY :
 					 XEN_NETIF_RSP_ERROR);
-			push_tx_responses(queue);
 			continue;
 		}
 
@@ -868,12 +985,15 @@
 
 			make_tx_response(queue, &txreq, extra_count,
 					 XEN_NETIF_RSP_OKAY);
-			push_tx_responses(queue);
 			continue;
 		}
 
+		data_len = (txreq.size > XEN_NETBACK_TX_COPY_LEN) ?
+			XEN_NETBACK_TX_COPY_LEN : txreq.size;
+
 		ret = xenvif_count_requests(queue, &txreq, extra_count,
 					    txfrags, work_to_do);
+
 		if (unlikely(ret < 0))
 			break;
 
@@ -888,10 +1008,8 @@
 
 		/* No crossing a page as the payload mustn't fragment. */
 		if (unlikely((txreq.offset + txreq.size) > XEN_PAGE_SIZE)) {
-			netdev_err(queue->vif->dev,
-				   "txreq.offset: %u, size: %u, end: %lu\n",
-				   txreq.offset, txreq.size,
-				   (unsigned long)(txreq.offset&~XEN_PAGE_MASK) + txreq.size);
+			netdev_err(queue->vif->dev, "Cross page boundary, txreq.offset: %u, size: %u\n",
+				   txreq.offset, txreq.size);
 			xenvif_fatal_tx_err(queue->vif);
 			break;
 		}
@@ -899,9 +1017,8 @@
 		index = pending_index(queue->pending_cons);
 		pending_idx = queue->pending_ring[index];
 
-		data_len = (txreq.size > XEN_NETBACK_TX_COPY_LEN &&
-			    ret < XEN_NETBK_LEGACY_SLOTS_MAX) ?
-			XEN_NETBACK_TX_COPY_LEN : txreq.size;
+		if (ret >= XEN_NETBK_LEGACY_SLOTS_MAX - 1 && data_len < txreq.size)
+			data_len = txreq.size;
 
 		skb = xenvif_alloc_skb(data_len);
 		if (unlikely(skb == NULL)) {
@@ -912,8 +1029,6 @@
 		}
 
 		skb_shinfo(skb)->nr_frags = ret;
-		if (data_len < txreq.size)
-			skb_shinfo(skb)->nr_frags++;
 		/* At this point shinfo->nr_frags is in fact the number of
 		 * slots, which can be as large as XEN_NETBK_LEGACY_SLOTS_MAX.
 		 */
@@ -975,54 +1090,19 @@
 					     type);
 		}
 
-		XENVIF_TX_CB(skb)->pending_idx = pending_idx;
-
-		__skb_put(skb, data_len);
-		queue->tx_copy_ops[*copy_ops].source.u.ref = txreq.gref;
-		queue->tx_copy_ops[*copy_ops].source.domid = queue->vif->domid;
-		queue->tx_copy_ops[*copy_ops].source.offset = txreq.offset;
-
-		queue->tx_copy_ops[*copy_ops].dest.u.gmfn =
-			virt_to_gfn(skb->data);
-		queue->tx_copy_ops[*copy_ops].dest.domid = DOMID_SELF;
-		queue->tx_copy_ops[*copy_ops].dest.offset =
-			offset_in_page(skb->data) & ~XEN_PAGE_MASK;
-
-		queue->tx_copy_ops[*copy_ops].len = data_len;
-		queue->tx_copy_ops[*copy_ops].flags = GNTCOPY_source_gref;
-
-		(*copy_ops)++;
-
-		if (data_len < txreq.size) {
-			frag_set_pending_idx(&skb_shinfo(skb)->frags[0],
-					     pending_idx);
-			xenvif_tx_create_map_op(queue, pending_idx, &txreq,
-						extra_count, gop);
-			gop++;
-		} else {
-			frag_set_pending_idx(&skb_shinfo(skb)->frags[0],
-					     INVALID_PENDING_IDX);
-			memcpy(&queue->pending_tx_info[pending_idx].req,
-			       &txreq, sizeof(txreq));
-			queue->pending_tx_info[pending_idx].extra_count =
-				extra_count;
-		}
-
-		queue->pending_cons++;
-
-		gop = xenvif_get_requests(queue, skb, txfrags, gop,
-				          frag_overflow, nskb);
+		xenvif_get_requests(queue, skb, &txreq, txfrags, copy_ops,
+				    map_ops, frag_overflow, nskb, extra_count,
+				    data_len);
 
 		__skb_queue_tail(&queue->tx_queue, skb);
 
 		queue->tx.req_cons = idx;
 
-		if (((gop-queue->tx_map_ops) >= ARRAY_SIZE(queue->tx_map_ops)) ||
+		if ((*map_ops >= ARRAY_SIZE(queue->tx_map_ops)) ||
 		    (*copy_ops >= ARRAY_SIZE(queue->tx_copy_ops)))
 			break;
 	}
 
-	(*map_ops) = gop - queue->tx_map_ops;
 	return;
 }
 
@@ -1101,9 +1181,8 @@
 	while ((skb = __skb_dequeue(&queue->tx_queue)) != NULL) {
 		struct xen_netif_tx_request *txp;
 		u16 pending_idx;
-		unsigned data_len;
 
-		pending_idx = XENVIF_TX_CB(skb)->pending_idx;
+		pending_idx = copy_pending_idx(skb, 0);
 		txp = &queue->pending_tx_info[pending_idx].req;
 
 		/* Check the remap error code. */
@@ -1122,18 +1201,6 @@
 			continue;
 		}
 
-		data_len = skb->len;
-		callback_param(queue, pending_idx).ctx = NULL;
-		if (data_len < txp->size) {
-			/* Append the packet payload as a fragment. */
-			txp->offset += data_len;
-			txp->size -= data_len;
-		} else {
-			/* Schedule a response immediately. */
-			xenvif_idx_release(queue, pending_idx,
-					   XEN_NETIF_RSP_OKAY);
-		}
-
 		if (txp->flags & XEN_NETTXF_csum_blank)
 			skb->ip_summed = CHECKSUM_PARTIAL;
 		else if (txp->flags & XEN_NETTXF_data_validated)
@@ -1319,7 +1386,7 @@
 /* Called after netfront has transmitted */
 int xenvif_tx_action(struct xenvif_queue *queue, int budget)
 {
-	unsigned nr_mops, nr_cops = 0;
+	unsigned nr_mops = 0, nr_cops = 0;
 	int work_done, ret;
 
 	if (unlikely(!tx_work_todo(queue)))
@@ -1336,7 +1403,15 @@
 				      NULL,
 				      queue->pages_to_map,
 				      nr_mops);
-		BUG_ON(ret);
+		if (ret) {
+			unsigned int i;
+
+			netdev_err(queue->vif->dev, "Map fail: nr %u ret %d\n",
+				   nr_mops, ret);
+			for (i = 0; i < nr_mops; ++i)
+				WARN_ON_ONCE(queue->tx_map_ops[i].status ==
+				             GNTST_okay);
+		}
 	}
 
 	work_done = xenvif_tx_submit(queue);
@@ -1344,8 +1419,35 @@
 	return work_done;
 }
 
+static void _make_tx_response(struct xenvif_queue *queue,
+			     const struct xen_netif_tx_request *txp,
+			     unsigned int extra_count,
+			     s8 status)
+{
+	RING_IDX i = queue->tx.rsp_prod_pvt;
+	struct xen_netif_tx_response *resp;
+
+	resp = RING_GET_RESPONSE(&queue->tx, i);
+	resp->id     = txp->id;
+	resp->status = status;
+
+	while (extra_count-- != 0)
+		RING_GET_RESPONSE(&queue->tx, ++i)->status = XEN_NETIF_RSP_NULL;
+
+	queue->tx.rsp_prod_pvt = ++i;
+}
+
+static void push_tx_responses(struct xenvif_queue *queue)
+{
+	int notify;
+
+	RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&queue->tx, notify);
+	if (notify)
+		notify_remote_via_irq(queue->tx_irq);
+}
+
 static void xenvif_idx_release(struct xenvif_queue *queue, u16 pending_idx,
-			       u8 status)
+			       s8 status)
 {
 	struct pending_tx_info *pending_tx_info;
 	pending_ring_idx_t index;
@@ -1355,8 +1457,8 @@
 
 	spin_lock_irqsave(&queue->response_lock, flags);
 
-	make_tx_response(queue, &pending_tx_info->req,
-			 pending_tx_info->extra_count, status);
+	_make_tx_response(queue, &pending_tx_info->req,
+			  pending_tx_info->extra_count, status);
 
 	/* Release the pending index before pusing the Tx response so
 	 * its available before a new Tx request is pushed by the
@@ -1370,35 +1472,22 @@
 	spin_unlock_irqrestore(&queue->response_lock, flags);
 }
 
-
 static void make_tx_response(struct xenvif_queue *queue,
-			     struct xen_netif_tx_request *txp,
+			     const struct xen_netif_tx_request *txp,
 			     unsigned int extra_count,
-			     s8       st)
+			     s8 status)
 {
-	RING_IDX i = queue->tx.rsp_prod_pvt;
-	struct xen_netif_tx_response *resp;
-
-	resp = RING_GET_RESPONSE(&queue->tx, i);
-	resp->id     = txp->id;
-	resp->status = st;
-
-	while (extra_count-- != 0)
-		RING_GET_RESPONSE(&queue->tx, ++i)->status = XEN_NETIF_RSP_NULL;
+	unsigned long flags;
 
-	queue->tx.rsp_prod_pvt = ++i;
-}
+	spin_lock_irqsave(&queue->response_lock, flags);
 
-static void push_tx_responses(struct xenvif_queue *queue)
-{
-	int notify;
+	_make_tx_response(queue, txp, extra_count, status);
+	push_tx_responses(queue);
 
-	RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&queue->tx, notify);
-	if (notify)
-		notify_remote_via_irq(queue->tx_irq);
+	spin_unlock_irqrestore(&queue->response_lock, flags);
 }
 
-void xenvif_idx_unmap(struct xenvif_queue *queue, u16 pending_idx)
+static void xenvif_idx_unmap(struct xenvif_queue *queue, u16 pending_idx)
 {
 	int ret;
 	struct gnttab_unmap_grant_ref tx_unmap_op;
@@ -1622,9 +1711,14 @@
 irqreturn_t xenvif_ctrl_irq_fn(int irq, void *data)
 {
 	struct xenvif *vif = data;
+	unsigned int eoi_flag = XEN_EOI_FLAG_SPURIOUS;
 
-	while (xenvif_ctrl_work_todo(vif))
+	while (xenvif_ctrl_work_todo(vif)) {
 		xenvif_ctrl_action(vif);
+		eoi_flag = 0;
+	}
+
+	xen_irq_lateeoi(irq, eoi_flag);
 
 	return IRQ_HANDLED;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/xen-netback/rx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/xen-netback/rx.c
@@ -33,22 +33,37 @@
 #include <xen/xen.h>
 #include <xen/events.h>
 
+/*
+ * Update the needed ring page slots for the first SKB queued.
+ * Note that any call sequence outside the RX thread calling this function
+ * needs to wake up the RX thread via a call of xenvif_kick_thread()
+ * afterwards in order to avoid a race with putting the thread to sleep.
+ */
+static void xenvif_update_needed_slots(struct xenvif_queue *queue,
+				       const struct sk_buff *skb)
+{
+	unsigned int needed = 0;
+
+	if (skb) {
+		needed = DIV_ROUND_UP(skb->len, XEN_PAGE_SIZE);
+		if (skb_is_gso(skb))
+			needed++;
+		if (skb->sw_hash)
+			needed++;
+	}
+
+	WRITE_ONCE(queue->rx_slots_needed, needed);
+}
+
 static bool xenvif_rx_ring_slots_available(struct xenvif_queue *queue)
 {
 	RING_IDX prod, cons;
-	struct sk_buff *skb;
-	int needed;
+	unsigned int needed;
 
-	skb = skb_peek(&queue->rx_queue);
-	if (!skb)
+	needed = READ_ONCE(queue->rx_slots_needed);
+	if (!needed)
 		return false;
 
-	needed = DIV_ROUND_UP(skb->len, XEN_PAGE_SIZE);
-	if (skb_is_gso(skb))
-		needed++;
-	if (skb->sw_hash)
-		needed++;
-
 	do {
 		prod = queue->rx.sring->req_prod;
 		cons = queue->rx.req_cons;
@@ -67,22 +82,30 @@
 	return false;
 }
 
-void xenvif_rx_queue_tail(struct xenvif_queue *queue, struct sk_buff *skb)
+bool xenvif_rx_queue_tail(struct xenvif_queue *queue, struct sk_buff *skb)
 {
 	unsigned long flags;
+	bool ret = true;
 
 	spin_lock_irqsave(&queue->rx_queue.lock, flags);
 
-	__skb_queue_tail(&queue->rx_queue, skb);
-
-	queue->rx_queue_len += skb->len;
-	if (queue->rx_queue_len > queue->rx_queue_max) {
+	if (queue->rx_queue_len >= queue->rx_queue_max) {
 		struct net_device *dev = queue->vif->dev;
 
 		netif_tx_stop_queue(netdev_get_tx_queue(dev, queue->id));
+		ret = false;
+	} else {
+		if (skb_queue_empty(&queue->rx_queue))
+			xenvif_update_needed_slots(queue, skb);
+
+		__skb_queue_tail(&queue->rx_queue, skb);
+
+		queue->rx_queue_len += skb->len;
 	}
 
 	spin_unlock_irqrestore(&queue->rx_queue.lock, flags);
+
+	return ret;
 }
 
 static struct sk_buff *xenvif_rx_dequeue(struct xenvif_queue *queue)
@@ -93,6 +116,8 @@
 
 	skb = __skb_dequeue(&queue->rx_queue);
 	if (skb) {
+		xenvif_update_needed_slots(queue, skb_peek(&queue->rx_queue));
+
 		queue->rx_queue_len -= skb->len;
 		if (queue->rx_queue_len < queue->rx_queue_max) {
 			struct netdev_queue *txq;
@@ -127,6 +152,7 @@
 			break;
 		xenvif_rx_dequeue(queue);
 		kfree_skb(skb);
+		queue->vif->dev->stats.rx_dropped++;
 	}
 }
 
@@ -449,7 +475,7 @@
 
 #define RX_BATCH_SIZE 64
 
-void xenvif_rx_action(struct xenvif_queue *queue)
+static void xenvif_rx_action(struct xenvif_queue *queue)
 {
 	struct sk_buff_head completed_skbs;
 	unsigned int work_done = 0;
@@ -458,6 +484,7 @@
 	queue->rx_copy.completed = &completed_skbs;
 
 	while (xenvif_rx_ring_slots_available(queue) &&
+	       !skb_queue_empty(&queue->rx_queue) &&
 	       work_done < RX_BATCH_SIZE) {
 		xenvif_rx_skb(queue);
 		work_done++;
@@ -467,36 +494,40 @@
 	xenvif_rx_copy_flush(queue);
 }
 
-static bool xenvif_rx_queue_stalled(struct xenvif_queue *queue)
+static RING_IDX xenvif_rx_queue_slots(const struct xenvif_queue *queue)
 {
 	RING_IDX prod, cons;
 
 	prod = queue->rx.sring->req_prod;
 	cons = queue->rx.req_cons;
 
+	return prod - cons;
+}
+
+static bool xenvif_rx_queue_stalled(const struct xenvif_queue *queue)
+{
+	unsigned int needed = READ_ONCE(queue->rx_slots_needed);
+
 	return !queue->stalled &&
-		prod - cons < 1 &&
+		xenvif_rx_queue_slots(queue) < needed &&
 		time_after(jiffies,
 			   queue->last_rx_time + queue->vif->stall_timeout);
 }
 
 static bool xenvif_rx_queue_ready(struct xenvif_queue *queue)
 {
-	RING_IDX prod, cons;
-
-	prod = queue->rx.sring->req_prod;
-	cons = queue->rx.req_cons;
+	unsigned int needed = READ_ONCE(queue->rx_slots_needed);
 
-	return queue->stalled && prod - cons >= 1;
+	return queue->stalled && xenvif_rx_queue_slots(queue) >= needed;
 }
 
-static bool xenvif_have_rx_work(struct xenvif_queue *queue)
+bool xenvif_have_rx_work(struct xenvif_queue *queue, bool test_kthread)
 {
 	return xenvif_rx_ring_slots_available(queue) ||
 		(queue->vif->stall_timeout &&
 		 (xenvif_rx_queue_stalled(queue) ||
 		  xenvif_rx_queue_ready(queue))) ||
-		kthread_should_stop() ||
+		(test_kthread && kthread_should_stop()) ||
 		queue->vif->disabled;
 }
 
@@ -527,15 +558,20 @@
 {
 	DEFINE_WAIT(wait);
 
-	if (xenvif_have_rx_work(queue))
+	if (xenvif_have_rx_work(queue, true))
 		return;
 
 	for (;;) {
 		long ret;
 
 		prepare_to_wait(&queue->wq, &wait, TASK_INTERRUPTIBLE);
-		if (xenvif_have_rx_work(queue))
+		if (xenvif_have_rx_work(queue, true))
 			break;
+		if (atomic_fetch_andnot(NETBK_RX_EOI | NETBK_COMMON_EOI,
+					&queue->eoi_pending) &
+		    (NETBK_RX_EOI | NETBK_COMMON_EOI))
+			xen_irq_lateeoi(queue->rx_irq, 0);
+
 		ret = schedule_timeout(xenvif_rx_queue_timeout(queue));
 		if (!ret)
 			break;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/xen-netback/xenbus.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/xen-netback/xenbus.c
@@ -202,10 +202,10 @@
 	set_backend_state(be, XenbusStateClosed);
 
 	unregister_hotplug_status_watch(be);
+	xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status");
 	if (be->vif) {
 		kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
 		xen_unregister_watchers(be->vif);
-		xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status");
 		xenvif_free(be->vif);
 		be->vif = NULL;
 	}
@@ -713,12 +713,14 @@
 		return -ENOMEM;
 	snprintf(node, maxlen, "%s/rate", dev->nodename);
 	vif->credit_watch.node = node;
+	vif->credit_watch.will_handle = NULL;
 	vif->credit_watch.callback = xen_net_rate_changed;
 	err = register_xenbus_watch(&vif->credit_watch);
 	if (err) {
 		pr_err("Failed to set watcher %s\n", vif->credit_watch.node);
 		kfree(node);
 		vif->credit_watch.node = NULL;
+		vif->credit_watch.will_handle = NULL;
 		vif->credit_watch.callback = NULL;
 	}
 	return err;
@@ -765,6 +767,7 @@
 	snprintf(node, maxlen, "%s/request-multicast-control",
 		 dev->otherend);
 	vif->mcast_ctrl_watch.node = node;
+	vif->mcast_ctrl_watch.will_handle = NULL;
 	vif->mcast_ctrl_watch.callback = xen_mcast_ctrl_changed;
 	err = register_xenbus_watch(&vif->mcast_ctrl_watch);
 	if (err) {
@@ -772,6 +775,7 @@
 		       vif->mcast_ctrl_watch.node);
 		kfree(node);
 		vif->mcast_ctrl_watch.node = NULL;
+		vif->mcast_ctrl_watch.will_handle = NULL;
 		vif->mcast_ctrl_watch.callback = NULL;
 	}
 	return err;
@@ -975,7 +979,7 @@
 	xenvif_carrier_on(be->vif);
 
 	unregister_hotplug_status_watch(be);
-	err = xenbus_watch_pathfmt(dev, &be->hotplug_status_watch,
+	err = xenbus_watch_pathfmt(dev, &be->hotplug_status_watch, NULL,
 				   hotplug_status_changed,
 				   "%s/%s", dev->nodename, "hotplug-status");
 	if (!err)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/net/xen-netfront.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/net/xen-netfront.c
@@ -63,6 +63,12 @@
 MODULE_PARM_DESC(max_queues,
 		 "Maximum number of queues per virtual interface");
 
+static bool __read_mostly xennet_trusted = true;
+module_param_named(trusted, xennet_trusted, bool, 0644);
+MODULE_PARM_DESC(trusted, "Is the backend trusted");
+
+#define XENNET_TIMEOUT  (5 * HZ)
+
 static const struct ethtool_ops xennet_ethtool_ops;
 
 struct netfront_cb {
@@ -119,21 +125,17 @@
 
 	/*
 	 * {tx,rx}_skbs store outstanding skbuffs. Free tx_skb entries
-	 * are linked from tx_skb_freelist through skb_entry.link.
-	 *
-	 *  NB. Freelist index entries are always going to be less than
-	 *  PAGE_OFFSET, whereas pointers to skbs will always be equal or
-	 *  greater than PAGE_OFFSET: we use this property to distinguish
-	 *  them.
+	 * are linked from tx_skb_freelist through tx_link.
 	 */
-	union skb_entry {
-		struct sk_buff *skb;
-		unsigned long link;
-	} tx_skbs[NET_TX_RING_SIZE];
+	struct sk_buff *tx_skbs[NET_TX_RING_SIZE];
+	unsigned short tx_link[NET_TX_RING_SIZE];
+#define TX_LINK_NONE 0xffff
+#define TX_PENDING   0xfffe
 	grant_ref_t gref_tx_head;
 	grant_ref_t grant_tx_ref[NET_TX_RING_SIZE];
 	struct page *grant_tx_page[NET_TX_RING_SIZE];
 	unsigned tx_skb_freelist;
+	unsigned int tx_pend_queue;
 
 	spinlock_t   rx_lock ____cacheline_aligned_in_smp;
 	struct xen_netif_rx_front_ring rx;
@@ -144,6 +146,9 @@
 	struct sk_buff *rx_skbs[NET_RX_RING_SIZE];
 	grant_ref_t gref_rx_head;
 	grant_ref_t grant_rx_ref[NET_RX_RING_SIZE];
+
+	unsigned int rx_rsp_unconsumed;
+	spinlock_t rx_cons_lock;
 };
 
 struct netfront_info {
@@ -159,6 +164,12 @@
 	struct netfront_stats __percpu *rx_stats;
 	struct netfront_stats __percpu *tx_stats;
 
+	/* Is device behaving sane? */
+	bool broken;
+
+	/* Should skbs be bounced into a zeroed buffer? */
+	bool bounce;
+
 	atomic_t rx_gso_checksum_fixup;
 };
 
@@ -167,33 +178,25 @@
 	struct xen_netif_extra_info extras[XEN_NETIF_EXTRA_TYPE_MAX - 1];
 };
 
-static void skb_entry_set_link(union skb_entry *list, unsigned short id)
-{
-	list->link = id;
-}
-
-static int skb_entry_is_link(const union skb_entry *list)
-{
-	BUILD_BUG_ON(sizeof(list->skb) != sizeof(list->link));
-	return (unsigned long)list->skb < PAGE_OFFSET;
-}
-
 /*
  * Access macros for acquiring freeing slots in tx_skbs[].
  */
 
-static void add_id_to_freelist(unsigned *head, union skb_entry *list,
-			       unsigned short id)
+static void add_id_to_list(unsigned *head, unsigned short *list,
+			   unsigned short id)
 {
-	skb_entry_set_link(&list[id], *head);
+	list[id] = *head;
 	*head = id;
 }
 
-static unsigned short get_id_from_freelist(unsigned *head,
-					   union skb_entry *list)
+static unsigned short get_id_from_list(unsigned *head, unsigned short *list)
 {
 	unsigned int id = *head;
-	*head = list[id].link;
+
+	if (id != TX_LINK_NONE) {
+		*head = list[id];
+		list[id] = TX_LINK_NONE;
+	}
 	return id;
 }
 
@@ -265,7 +268,7 @@
 	if (unlikely(!skb))
 		return NULL;
 
-	page = alloc_page(GFP_ATOMIC | __GFP_NOWARN);
+	page = alloc_page(GFP_ATOMIC | __GFP_NOWARN | __GFP_ZERO);
 	if (!page) {
 		kfree_skb(skb);
 		return NULL;
@@ -349,7 +352,7 @@
 	unsigned int i = 0;
 	struct netfront_queue *queue = NULL;
 
-	if (!np->queues)
+	if (!np->queues || np->broken)
 		return -ENODEV;
 
 	for (i = 0; i < num_queues; ++i) {
@@ -371,41 +374,62 @@
 	return 0;
 }
 
-static void xennet_tx_buf_gc(struct netfront_queue *queue)
+static bool xennet_tx_buf_gc(struct netfront_queue *queue)
 {
 	RING_IDX cons, prod;
 	unsigned short id;
 	struct sk_buff *skb;
 	bool more_to_do;
+	bool work_done = false;
+	const struct device *dev = &queue->info->netdev->dev;
 
 	BUG_ON(!netif_carrier_ok(queue->info->netdev));
 
 	do {
 		prod = queue->tx.sring->rsp_prod;
+		if (RING_RESPONSE_PROD_OVERFLOW(&queue->tx, prod)) {
+			dev_alert(dev, "Illegal number of responses %u\n",
+				  prod - queue->tx.rsp_cons);
+			goto err;
+		}
 		rmb(); /* Ensure we see responses up to 'rp'. */
 
 		for (cons = queue->tx.rsp_cons; cons != prod; cons++) {
-			struct xen_netif_tx_response *txrsp;
+			struct xen_netif_tx_response txrsp;
 
-			txrsp = RING_GET_RESPONSE(&queue->tx, cons);
-			if (txrsp->status == XEN_NETIF_RSP_NULL)
+			work_done = true;
+
+			RING_COPY_RESPONSE(&queue->tx, cons, &txrsp);
+			if (txrsp.status == XEN_NETIF_RSP_NULL)
 				continue;
 
-			id  = txrsp->id;
-			skb = queue->tx_skbs[id].skb;
-			if (unlikely(gnttab_query_foreign_access(
-				queue->grant_tx_ref[id]) != 0)) {
-				pr_alert("%s: warning -- grant still in use by backend domain\n",
-					 __func__);
-				BUG();
+			id = txrsp.id;
+			if (id >= RING_SIZE(&queue->tx)) {
+				dev_alert(dev,
+					  "Response has incorrect id (%u)\n",
+					  id);
+				goto err;
+			}
+			if (queue->tx_link[id] != TX_PENDING) {
+				dev_alert(dev,
+					  "Response for inactive request\n");
+				goto err;
+			}
+
+			queue->tx_link[id] = TX_LINK_NONE;
+			skb = queue->tx_skbs[id];
+			queue->tx_skbs[id] = NULL;
+			if (unlikely(!gnttab_end_foreign_access_ref(
+				queue->grant_tx_ref[id], GNTMAP_readonly))) {
+				dev_alert(dev,
+					  "Grant still in use by backend domain\n");
+				goto err;
 			}
-			gnttab_end_foreign_access_ref(
-				queue->grant_tx_ref[id], GNTMAP_readonly);
 			gnttab_release_grant_reference(
 				&queue->gref_tx_head, queue->grant_tx_ref[id]);
 			queue->grant_tx_ref[id] = GRANT_INVALID_REF;
 			queue->grant_tx_page[id] = NULL;
-			add_id_to_freelist(&queue->tx_skb_freelist, queue->tx_skbs, id);
+			add_id_to_list(&queue->tx_skb_freelist, queue->tx_link, id);
 			dev_kfree_skb_irq(skb);
 		}
 
@@ -415,13 +439,22 @@
 	} while (more_to_do);
 
 	xennet_maybe_wake_tx(queue);
+
+	return work_done;
+
+ err:
+	queue->info->broken = true;
+	dev_alert(dev, "Disabled for further use\n");
+
+	return work_done;
 }
 
 struct xennet_gnttab_make_txreq {
 	struct netfront_queue *queue;
 	struct sk_buff *skb;
 	struct page *page;
-	struct xen_netif_tx_request *tx; /* Last request */
+	struct xen_netif_tx_request *tx;      /* Last request on ring page */
+	struct xen_netif_tx_request tx_local; /* Last request local copy*/
 	unsigned int size;
 };
 
@@ -437,7 +470,7 @@
 	struct netfront_queue *queue = info->queue;
 	struct sk_buff *skb = info->skb;
 
-	id = get_id_from_freelist(&queue->tx_skb_freelist, queue->tx_skbs);
+	id = get_id_from_list(&queue->tx_skb_freelist, queue->tx_link);
 	tx = RING_GET_REQUEST(&queue->tx, queue->tx.req_prod_pvt++);
 	ref = gnttab_claim_grant_reference(&queue->gref_tx_head);
 	WARN_ON_ONCE(IS_ERR_VALUE((unsigned long)(int)ref));
@@ -445,34 +478,37 @@
 	gnttab_grant_foreign_access_ref(ref, queue->info->xbdev->otherend_id,
 					gfn, GNTMAP_readonly);
 
-	queue->tx_skbs[id].skb = skb;
+	queue->tx_skbs[id] = skb;
 	queue->grant_tx_page[id] = page;
 	queue->grant_tx_ref[id] = ref;
 
-	tx->id = id;
-	tx->gref = ref;
-	tx->offset = offset;
-	tx->size = len;
-	tx->flags = 0;
+	info->tx_local.id = id;
+	info->tx_local.gref = ref;
+	info->tx_local.offset = offset;
+	info->tx_local.size = len;
+	info->tx_local.flags = 0;
+
+	*tx = info->tx_local;
+
+	/*
+	 * Put the request in the pending queue, it will be set to be pending
+	 * when the producer index is about to be raised.
+	 */
+	add_id_to_list(&queue->tx_pend_queue, queue->tx_link, id);
 
 	info->tx = tx;
-	info->size += tx->size;
+	info->size += info->tx_local.size;
 }
 
 static struct xen_netif_tx_request *xennet_make_first_txreq(
-	struct netfront_queue *queue, struct sk_buff *skb,
-	struct page *page, unsigned int offset, unsigned int len)
+	struct xennet_gnttab_make_txreq *info,
+	unsigned int offset, unsigned int len)
 {
-	struct xennet_gnttab_make_txreq info = {
-		.queue = queue,
-		.skb = skb,
-		.page = page,
-		.size = 0,
-	};
+	info->size = 0;
 
-	gnttab_for_one_grant(page, offset, len, xennet_tx_setup_grant, &info);
+	gnttab_for_one_grant(info->page, offset, len, xennet_tx_setup_grant, info);
 
-	return info.tx;
+	return info->tx;
 }
 
 static void xennet_make_one_txreq(unsigned long gfn, unsigned int offset,
@@ -485,35 +521,27 @@
 	xennet_tx_setup_grant(gfn, offset, len, data);
 }
 
-static struct xen_netif_tx_request *xennet_make_txreqs(
-	struct netfront_queue *queue, struct xen_netif_tx_request *tx,
-	struct sk_buff *skb, struct page *page,
+static void xennet_make_txreqs(
+	struct xennet_gnttab_make_txreq *info,
+	struct page *page,
 	unsigned int offset, unsigned int len)
 {
-	struct xennet_gnttab_make_txreq info = {
-		.queue = queue,
-		.skb = skb,
-		.tx = tx,
-	};
-
 	/* Skip unused frames from start of page */
 	page += offset >> PAGE_SHIFT;
 	offset &= ~PAGE_MASK;
 
 	while (len) {
-		info.page = page;
-		info.size = 0;
+		info->page = page;
+		info->size = 0;
 
 		gnttab_foreach_grant_in_range(page, offset, len,
 					      xennet_make_one_txreq,
-					      &info);
+					      info);
 
 		page++;
 		offset = 0;
-		len -= info.size;
+		len -= info->size;
 	}
-
-	return info.tx;
 }
 
 /*
@@ -560,13 +588,50 @@
 	return queue_idx;
 }
 
+static void xennet_mark_tx_pending(struct netfront_queue *queue)
+{
+	unsigned int i;
+
+	while ((i = get_id_from_list(&queue->tx_pend_queue, queue->tx_link)) !=
+		TX_LINK_NONE)
+		queue->tx_link[i] = TX_PENDING;
+}
+
+struct sk_buff *bounce_skb(const struct sk_buff *skb)
+{
+	unsigned int headerlen = skb_headroom(skb);
+	/* Align size to allocate full pages and avoid contiguous data leaks */
+	unsigned int size = ALIGN(skb_end_offset(skb) + skb->data_len,
+				  XEN_PAGE_SIZE);
+	struct sk_buff *n = alloc_skb(size, GFP_ATOMIC | __GFP_ZERO);
+
+	if (!n)
+		return NULL;
+
+	if (!IS_ALIGNED((uintptr_t)n->head, XEN_PAGE_SIZE)) {
+		WARN_ONCE(1, "misaligned skb allocated\n");
+		kfree_skb(n);
+		return NULL;
+	}
+
+	/* Set the data pointer */
+	skb_reserve(n, headerlen);
+	/* Set the tail pointer and length */
+	skb_put(n, skb->len);
+
+	BUG_ON(skb_copy_bits(skb, -headerlen, n->head, headerlen + skb->len));
+
+	skb_copy_header(n, skb);
+	return n;
+}
+
 #define MAX_XEN_SKB_FRAGS (65536 / XEN_PAGE_SIZE + 1)
 
 static netdev_tx_t xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct netfront_info *np = netdev_priv(dev);
 	struct netfront_stats *tx_stats = this_cpu_ptr(np->tx_stats);
-	struct xen_netif_tx_request *tx, *first_tx;
+	struct xen_netif_tx_request *first_tx;
 	unsigned int i;
 	int notify;
 	int slots;
@@ -575,6 +640,7 @@
 	unsigned int len;
 	unsigned long flags;
 	struct netfront_queue *queue = NULL;
+	struct xennet_gnttab_make_txreq info = { };
 	unsigned int num_queues = dev->real_num_tx_queues;
 	u16 queue_index;
 	struct sk_buff *nskb;
@@ -582,6 +648,8 @@
 	/* Drop the packet if no queues are set up */
 	if (num_queues < 1)
 		goto drop;
+	if (unlikely(np->broken))
+		goto drop;
 	/* Determine which queue to transmit this SKB on */
 	queue_index = skb_get_queue_mapping(skb);
 	queue = &np->queues[queue_index];
@@ -609,9 +677,13 @@
 
 	/* The first req should be at least ETH_HLEN size or the packet will be
 	 * dropped by netback.
+	 *
+	 * If the backend is not trusted bounce all data to zeroed pages to
+	 * avoid exposing contiguous data on the granted page not belonging to
+	 * the skb.
 	 */
-	if (unlikely(PAGE_SIZE - offset < ETH_HLEN)) {
-		nskb = skb_copy(skb, GFP_ATOMIC);
+	if (np->bounce || unlikely(PAGE_SIZE - offset < ETH_HLEN)) {
+		nskb = bounce_skb(skb);
 		if (!nskb)
 			goto drop;
 		dev_consume_skb_any(skb);
@@ -632,21 +704,24 @@
 	}
 
 	/* First request for the linear area. */
-	first_tx = tx = xennet_make_first_txreq(queue, skb,
-						page, offset, len);
-	offset += tx->size;
+	info.queue = queue;
+	info.skb = skb;
+	info.page = page;
+	first_tx = xennet_make_first_txreq(&info, offset, len);
+	offset += info.tx_local.size;
 	if (offset == PAGE_SIZE) {
 		page++;
 		offset = 0;
 	}
-	len -= tx->size;
+	len -= info.tx_local.size;
 
 	if (skb->ip_summed == CHECKSUM_PARTIAL)
 		/* local packet? */
-		tx->flags |= XEN_NETTXF_csum_blank | XEN_NETTXF_data_validated;
+		first_tx->flags |= XEN_NETTXF_csum_blank |
+				   XEN_NETTXF_data_validated;
 	else if (skb->ip_summed == CHECKSUM_UNNECESSARY)
 		/* remote but checksummed. */
-		tx->flags |= XEN_NETTXF_data_validated;
+		first_tx->flags |= XEN_NETTXF_data_validated;
 
 	/* Optional extra info after the first request. */
 	if (skb_shinfo(skb)->gso_size) {
@@ -655,7 +730,7 @@
 		gso = (struct xen_netif_extra_info *)
 			RING_GET_REQUEST(&queue->tx, queue->tx.req_prod_pvt++);
 
-		tx->flags |= XEN_NETTXF_extra_info;
+		first_tx->flags |= XEN_NETTXF_extra_info;
 
 		gso->u.gso.size = skb_shinfo(skb)->gso_size;
 		gso->u.gso.type = (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) ?
@@ -669,12 +744,12 @@
 	}
 
 	/* Requests for the rest of the linear area. */
-	tx = xennet_make_txreqs(queue, tx, skb, page, offset, len);
+	xennet_make_txreqs(&info, page, offset, len);
 
 	/* Requests for all the frags. */
 	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
 		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-		tx = xennet_make_txreqs(queue, tx, skb, skb_frag_page(frag),
+		xennet_make_txreqs(&info, skb_frag_page(frag),
 					skb_frag_off(frag),
 					skb_frag_size(frag));
 	}
@@ -682,6 +757,8 @@
 	/* First request has the packet length. */
 	first_tx->size = skb->len;
 
+	xennet_mark_tx_pending(queue);
+
 	RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&queue->tx, notify);
 	if (notify)
 		notify_remote_via_irq(queue->tx_irq);
@@ -710,7 +787,7 @@
 static int xennet_close(struct net_device *dev)
 {
 	struct netfront_info *np = netdev_priv(dev);
-	unsigned int num_queues = dev->real_num_tx_queues;
+	unsigned int num_queues = np->queues ? dev->real_num_tx_queues : 0;
 	unsigned int i;
 	struct netfront_queue *queue;
 	netif_tx_stop_all_queues(np->netdev);
@@ -721,6 +798,41 @@
 	return 0;
 }
 
+static void xennet_destroy_queues(struct netfront_info *info)
+{
+	unsigned int i;
+
+	if (!info->queues)
+		return;
+
+	for (i = 0; i < info->netdev->real_num_tx_queues; i++) {
+		struct netfront_queue *queue = &info->queues[i];
+
+		if (netif_running(info->netdev))
+			napi_disable(&queue->napi);
+		netif_napi_del(&queue->napi);
+	}
+
+	kfree(info->queues);
+	info->queues = NULL;
+}
+
+static void xennet_uninit(struct net_device *dev)
+{
+	struct netfront_info *np = netdev_priv(dev);
+	xennet_destroy_queues(np);
+}
+
+static void xennet_set_rx_rsp_cons(struct netfront_queue *queue, RING_IDX val)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&queue->rx_cons_lock, flags);
+	queue->rx.rsp_cons = val;
+	queue->rx_rsp_unconsumed = RING_HAS_UNCONSUMED_RESPONSES(&queue->rx);
+	spin_unlock_irqrestore(&queue->rx_cons_lock, flags);
+}
+
 static void xennet_move_rx_slot(struct netfront_queue *queue, struct sk_buff *skb,
 				grant_ref_t ref)
 {
@@ -739,7 +851,7 @@
 			     RING_IDX rp)
 
 {
-	struct xen_netif_extra_info *extra;
+	struct xen_netif_extra_info extra;
 	struct device *dev = &queue->info->netdev->dev;
 	RING_IDX cons = queue->rx.rsp_cons;
 	int err = 0;
@@ -755,26 +867,24 @@
 			break;
 		}
 
-		extra = (struct xen_netif_extra_info *)
-			RING_GET_RESPONSE(&queue->rx, ++cons);
+		RING_COPY_RESPONSE(&queue->rx, ++cons, &extra);
 
-		if (unlikely(!extra->type ||
-			     extra->type >= XEN_NETIF_EXTRA_TYPE_MAX)) {
+		if (unlikely(!extra.type ||
+			     extra.type >= XEN_NETIF_EXTRA_TYPE_MAX)) {
 			if (net_ratelimit())
 				dev_warn(dev, "Invalid extra type: %d\n",
-					extra->type);
+					 extra.type);
 			err = -EINVAL;
 		} else {
-			memcpy(&extras[extra->type - 1], extra,
-			       sizeof(*extra));
+			extras[extra.type - 1] = extra;
 		}
 
 		skb = xennet_get_rx_skb(queue, cons);
 		ref = xennet_get_rx_ref(queue, cons);
 		xennet_move_rx_slot(queue, skb, ref);
-	} while (extra->flags & XEN_NETIF_EXTRA_FLAG_MORE);
+	} while (extra.flags & XEN_NETIF_EXTRA_FLAG_MORE);
 
-	queue->rx.rsp_cons = cons;
+	xennet_set_rx_rsp_cons(queue, cons);
 	return err;
 }
 
@@ -782,7 +892,7 @@
 				struct netfront_rx_info *rinfo, RING_IDX rp,
 				struct sk_buff_head *list)
 {
-	struct xen_netif_rx_response *rx = &rinfo->rx;
+	struct xen_netif_rx_response *rx = &rinfo->rx, rx_local;
 	struct xen_netif_extra_info *extras = rinfo->extras;
 	struct device *dev = &queue->info->netdev->dev;
 	RING_IDX cons = queue->rx.rsp_cons;
@@ -791,7 +901,6 @@
 	int max = XEN_NETIF_NR_SLOTS_MIN + (rx->status <= RX_COPY_THRESHOLD);
 	int slots = 1;
 	int err = 0;
-	unsigned long ret;
 
 	if (rx->flags & XEN_NETRXF_extra_info) {
 		err = xennet_get_extras(queue, extras, rp);
@@ -822,8 +931,13 @@
 			goto next;
 		}
 
-		ret = gnttab_end_foreign_access_ref(ref, 0);
-		BUG_ON(!ret);
+		if (!gnttab_end_foreign_access_ref(ref, 0)) {
+			dev_alert(dev,
+				  "Grant still in use by backend domain\n");
+			queue->info->broken = true;
+			dev_alert(dev, "Disabled for further use\n");
+			return -EINVAL;
+		}
 
 		gnttab_release_grant_reference(&queue->gref_rx_head, ref);
 
@@ -840,7 +954,8 @@
 			break;
 		}
 
-		rx = RING_GET_RESPONSE(&queue->rx, cons + slots);
+		RING_COPY_RESPONSE(&queue->rx, cons + slots, &rx_local);
+		rx = &rx_local;
 		skb = xennet_get_rx_skb(queue, cons + slots);
 		ref = xennet_get_rx_ref(queue, cons + slots);
 		slots++;
@@ -853,7 +968,7 @@
 	}
 
 	if (unlikely(err))
-		queue->rx.rsp_cons = cons + slots;
+		xennet_set_rx_rsp_cons(queue, cons + slots);
 
 	return err;
 }
@@ -895,10 +1010,11 @@
 	struct sk_buff *nskb;
 
 	while ((nskb = __skb_dequeue(list))) {
-		struct xen_netif_rx_response *rx =
-			RING_GET_RESPONSE(&queue->rx, ++cons);
+		struct xen_netif_rx_response rx;
 		skb_frag_t *nfrag = &skb_shinfo(nskb)->frags[0];
 
+		RING_COPY_RESPONSE(&queue->rx, ++cons, &rx);
+
 		if (skb_shinfo(skb)->nr_frags == MAX_SKB_FRAGS) {
 			unsigned int pull_to = NETFRONT_SKB_CB(skb)->pull_to;
 
@@ -906,20 +1022,21 @@
 			__pskb_pull_tail(skb, pull_to - skb_headlen(skb));
 		}
 		if (unlikely(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS)) {
-			queue->rx.rsp_cons = ++cons + skb_queue_len(list);
+			xennet_set_rx_rsp_cons(queue,
+					       ++cons + skb_queue_len(list));
 			kfree_skb(nskb);
 			return -ENOENT;
 		}
 
 		skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
 				skb_frag_page(nfrag),
-				rx->offset, rx->status, PAGE_SIZE);
+				rx.offset, rx.status, PAGE_SIZE);
 
 		skb_shinfo(nskb)->nr_frags = 0;
 		kfree_skb(nskb);
 	}
 
-	queue->rx.rsp_cons = cons;
+	xennet_set_rx_rsp_cons(queue, cons);
 
 	return 0;
 }
@@ -1006,17 +1123,28 @@
 	skb_queue_head_init(&tmpq);
 
 	rp = queue->rx.sring->rsp_prod;
+	if (RING_RESPONSE_PROD_OVERFLOW(&queue->rx, rp)) {
+		dev_alert(&dev->dev, "Illegal number of responses %u\n",
+			  rp - queue->rx.rsp_cons);
+		queue->info->broken = true;
+		spin_unlock(&queue->rx_lock);
+		return 0;
+	}
 	rmb(); /* Ensure we see queued responses up to 'rp'. */
 
 	i = queue->rx.rsp_cons;
 	work_done = 0;
 	while ((i != rp) && (work_done < budget)) {
-		memcpy(rx, RING_GET_RESPONSE(&queue->rx, i), sizeof(*rx));
+		RING_COPY_RESPONSE(&queue->rx, i, rx);
 		memset(extras, 0, sizeof(rinfo.extras));
 
 		err = xennet_get_responses(queue, &rinfo, rp, &tmpq);
 
 		if (unlikely(err)) {
+			if (queue->info->broken) {
+				spin_unlock(&queue->rx_lock);
+				return 0;
+			}
 err:
 			while ((skb = __skb_dequeue(&tmpq)))
 				__skb_queue_tail(&errq, skb);
@@ -1033,7 +1161,9 @@
 
 			if (unlikely(xennet_set_skb_gso(skb, gso))) {
 				__skb_queue_head(&tmpq, skb);
-				queue->rx.rsp_cons += skb_queue_len(&tmpq);
+				xennet_set_rx_rsp_cons(queue,
+						       queue->rx.rsp_cons +
+						       skb_queue_len(&tmpq));
 				goto err;
 			}
 		}
@@ -1057,7 +1187,8 @@
 
 		__skb_queue_tail(&rxq, skb);
 
-		i = ++queue->rx.rsp_cons;
+		i = queue->rx.rsp_cons + 1;
+		xennet_set_rx_rsp_cons(queue, i);
 		work_done++;
 	}
 
@@ -1133,17 +1264,18 @@
 
 	for (i = 0; i < NET_TX_RING_SIZE; i++) {
 		/* Skip over entries which are actually freelist references */
-		if (skb_entry_is_link(&queue->tx_skbs[i]))
+		if (!queue->tx_skbs[i])
 			continue;
 
-		skb = queue->tx_skbs[i].skb;
+		skb = queue->tx_skbs[i];
+		queue->tx_skbs[i] = NULL;
 		get_page(queue->grant_tx_page[i]);
 		gnttab_end_foreign_access(queue->grant_tx_ref[i],
 					  GNTMAP_readonly,
 					  (unsigned long)page_address(queue->grant_tx_page[i]));
 		queue->grant_tx_page[i] = NULL;
 		queue->grant_tx_ref[i] = GRANT_INVALID_REF;
-		add_id_to_freelist(&queue->tx_skb_freelist, queue->tx_skbs, i);
+		add_id_to_list(&queue->tx_skb_freelist, queue->tx_link, i);
 		dev_kfree_skb_irq(skb);
 	}
 }
@@ -1218,34 +1350,79 @@
 	return 0;
 }
 
-static irqreturn_t xennet_tx_interrupt(int irq, void *dev_id)
+static bool xennet_handle_tx(struct netfront_queue *queue, unsigned int *eoi)
 {
-	struct netfront_queue *queue = dev_id;
 	unsigned long flags;
 
+	if (unlikely(queue->info->broken))
+		return false;
+
 	spin_lock_irqsave(&queue->tx_lock, flags);
-	xennet_tx_buf_gc(queue);
+	if (xennet_tx_buf_gc(queue))
+		*eoi = 0;
 	spin_unlock_irqrestore(&queue->tx_lock, flags);
 
+	return true;
+}
+
+static irqreturn_t xennet_tx_interrupt(int irq, void *dev_id)
+{
+	unsigned int eoiflag = XEN_EOI_FLAG_SPURIOUS;
+
+	if (likely(xennet_handle_tx(dev_id, &eoiflag)))
+		xen_irq_lateeoi(irq, eoiflag);
+
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t xennet_rx_interrupt(int irq, void *dev_id)
+static bool xennet_handle_rx(struct netfront_queue *queue, unsigned int *eoi)
 {
-	struct netfront_queue *queue = dev_id;
-	struct net_device *dev = queue->info->netdev;
+	unsigned int work_queued;
+	unsigned long flags;
+
+	if (unlikely(queue->info->broken))
+		return false;
 
-	if (likely(netif_carrier_ok(dev) &&
-		   RING_HAS_UNCONSUMED_RESPONSES(&queue->rx)))
+	spin_lock_irqsave(&queue->rx_cons_lock, flags);
+	work_queued = RING_HAS_UNCONSUMED_RESPONSES(&queue->rx);
+	if (work_queued > queue->rx_rsp_unconsumed) {
+		queue->rx_rsp_unconsumed = work_queued;
+		*eoi = 0;
+	} else if (unlikely(work_queued < queue->rx_rsp_unconsumed)) {
+		const struct device *dev = &queue->info->netdev->dev;
+
+		spin_unlock_irqrestore(&queue->rx_cons_lock, flags);
+		dev_alert(dev, "RX producer index going backwards\n");
+		dev_alert(dev, "Disabled for further use\n");
+		queue->info->broken = true;
+		return false;
+	}
+	spin_unlock_irqrestore(&queue->rx_cons_lock, flags);
+
+	if (likely(netif_carrier_ok(queue->info->netdev) && work_queued))
 		napi_schedule(&queue->napi);
 
+	return true;
+}
+
+static irqreturn_t xennet_rx_interrupt(int irq, void *dev_id)
+{
+	unsigned int eoiflag = XEN_EOI_FLAG_SPURIOUS;
+
+	if (likely(xennet_handle_rx(dev_id, &eoiflag)))
+		xen_irq_lateeoi(irq, eoiflag);
+
 	return IRQ_HANDLED;
 }
 
 static irqreturn_t xennet_interrupt(int irq, void *dev_id)
 {
-	xennet_tx_interrupt(irq, dev_id);
-	xennet_rx_interrupt(irq, dev_id);
+	unsigned int eoiflag = XEN_EOI_FLAG_SPURIOUS;
+
+	if (xennet_handle_tx(dev_id, &eoiflag) &&
+	    xennet_handle_rx(dev_id, &eoiflag))
+		xen_irq_lateeoi(irq, eoiflag);
+
 	return IRQ_HANDLED;
 }
 
@@ -1256,12 +1433,17 @@
 	struct netfront_info *info = netdev_priv(dev);
 	unsigned int num_queues = dev->real_num_tx_queues;
 	unsigned int i;
+
+	if (info->broken)
+		return;
+
 	for (i = 0; i < num_queues; ++i)
 		xennet_interrupt(0, &info->queues[i]);
 }
 #endif
 
 static const struct net_device_ops xennet_netdev_ops = {
+	.ndo_uninit          = xennet_uninit,
 	.ndo_open            = xennet_open,
 	.ndo_stop            = xennet_close,
 	.ndo_start_xmit      = xennet_start_xmit,
@@ -1334,12 +1516,15 @@
 
 	netif_carrier_off(netdev);
 
-	xenbus_switch_state(dev, XenbusStateInitialising);
-	wait_event(module_wq,
-		   xenbus_read_driver_state(dev->otherend) !=
-		   XenbusStateClosed &&
-		   xenbus_read_driver_state(dev->otherend) !=
-		   XenbusStateUnknown);
+	do {
+		xenbus_switch_state(dev, XenbusStateInitialising);
+		err = wait_event_timeout(module_wq,
+				 xenbus_read_driver_state(dev->otherend) !=
+				 XenbusStateClosed &&
+				 xenbus_read_driver_state(dev->otherend) !=
+				 XenbusStateUnknown, XENNET_TIMEOUT);
+	} while (!err);
+
 	return netdev;
 
  exit:
@@ -1434,7 +1619,17 @@
 
 	dev_dbg(&dev->dev, "%s\n", dev->nodename);
 
+	netif_tx_lock_bh(info->netdev);
+	netif_device_detach(info->netdev);
+	netif_tx_unlock_bh(info->netdev);
+
 	xennet_disconnect_backend(info);
+
+	rtnl_lock();
+	if (info->queues)
+		xennet_destroy_queues(info);
+	rtnl_unlock();
+
 	return 0;
 }
 
@@ -1468,9 +1663,10 @@
 	if (err < 0)
 		goto fail;
 
-	err = bind_evtchn_to_irqhandler(queue->tx_evtchn,
-					xennet_interrupt,
-					0, queue->info->netdev->name, queue);
+	err = bind_evtchn_to_irqhandler_lateeoi(queue->tx_evtchn,
+						xennet_interrupt, 0,
+						queue->info->netdev->name,
+						queue);
 	if (err < 0)
 		goto bind_fail;
 	queue->rx_evtchn = queue->tx_evtchn;
@@ -1498,18 +1694,18 @@
 
 	snprintf(queue->tx_irq_name, sizeof(queue->tx_irq_name),
 		 "%s-tx", queue->name);
-	err = bind_evtchn_to_irqhandler(queue->tx_evtchn,
-					xennet_tx_interrupt,
-					0, queue->tx_irq_name, queue);
+	err = bind_evtchn_to_irqhandler_lateeoi(queue->tx_evtchn,
+						xennet_tx_interrupt, 0,
+						queue->tx_irq_name, queue);
 	if (err < 0)
 		goto bind_tx_fail;
 	queue->tx_irq = err;
 
 	snprintf(queue->rx_irq_name, sizeof(queue->rx_irq_name),
 		 "%s-rx", queue->name);
-	err = bind_evtchn_to_irqhandler(queue->rx_evtchn,
-					xennet_rx_interrupt,
-					0, queue->rx_irq_name, queue);
+	err = bind_evtchn_to_irqhandler_lateeoi(queue->rx_evtchn,
+						xennet_rx_interrupt, 0,
+						queue->rx_irq_name, queue);
 	if (err < 0)
 		goto bind_rx_fail;
 	queue->rx_irq = err;
@@ -1533,7 +1729,7 @@
 			struct netfront_queue *queue, unsigned int feature_split_evtchn)
 {
 	struct xen_netif_tx_sring *txs;
-	struct xen_netif_rx_sring *rxs;
+	struct xen_netif_rx_sring *rxs = NULL;
 	grant_ref_t gref;
 	int err;
 
@@ -1553,21 +1749,21 @@
 
 	err = xenbus_grant_ring(dev, txs, 1, &gref);
 	if (err < 0)
-		goto grant_tx_ring_fail;
+		goto fail;
 	queue->tx_ring_ref = gref;
 
 	rxs = (struct xen_netif_rx_sring *)get_zeroed_page(GFP_NOIO | __GFP_HIGH);
 	if (!rxs) {
 		err = -ENOMEM;
 		xenbus_dev_fatal(dev, err, "allocating rx ring page");
-		goto alloc_rx_ring_fail;
+		goto fail;
 	}
 	SHARED_RING_INIT(rxs);
 	FRONT_RING_INIT(&queue->rx, rxs, XEN_PAGE_SIZE);
 
 	err = xenbus_grant_ring(dev, rxs, 1, &gref);
 	if (err < 0)
-		goto grant_rx_ring_fail;
+		goto fail;
 	queue->rx_ring_ref = gref;
 
 	if (feature_split_evtchn)
@@ -1580,22 +1776,28 @@
 		err = setup_netfront_single(queue);
 
 	if (err)
-		goto alloc_evtchn_fail;
+		goto fail;
 
 	return 0;
 
 	/* If we fail to setup netfront, it is safe to just revoke access to
 	 * granted pages because backend is not accessing it at this point.
 	 */
-alloc_evtchn_fail:
-	gnttab_end_foreign_access_ref(queue->rx_ring_ref, 0);
-grant_rx_ring_fail:
-	free_page((unsigned long)rxs);
-alloc_rx_ring_fail:
-	gnttab_end_foreign_access_ref(queue->tx_ring_ref, 0);
-grant_tx_ring_fail:
-	free_page((unsigned long)txs);
-fail:
+ fail:
+	if (queue->rx_ring_ref != GRANT_INVALID_REF) {
+		gnttab_end_foreign_access(queue->rx_ring_ref, 0,
+					  (unsigned long)rxs);
+		queue->rx_ring_ref = GRANT_INVALID_REF;
+	} else {
+		free_page((unsigned long)rxs);
+	}
+	if (queue->tx_ring_ref != GRANT_INVALID_REF) {
+		gnttab_end_foreign_access(queue->tx_ring_ref, 0,
+					  (unsigned long)txs);
+		queue->tx_ring_ref = GRANT_INVALID_REF;
+	} else {
+		free_page((unsigned long)txs);
+	}
 	return err;
 }
 
@@ -1611,6 +1813,7 @@
 
 	spin_lock_init(&queue->tx_lock);
 	spin_lock_init(&queue->rx_lock);
+	spin_lock_init(&queue->rx_cons_lock);
 
 	timer_setup(&queue->rx_refill_timer, rx_refill_timeout, 0);
 
@@ -1618,13 +1821,15 @@
 	snprintf(queue->name, sizeof(queue->name), "vif%s-q%u",
 		 devid, queue->id);
 
-	/* Initialise tx_skbs as a free chain containing every entry. */
+	/* Initialise tx_skb_freelist as a free chain containing every entry. */
 	queue->tx_skb_freelist = 0;
+	queue->tx_pend_queue = TX_LINK_NONE;
 	for (i = 0; i < NET_TX_RING_SIZE; i++) {
-		skb_entry_set_link(&queue->tx_skbs[i], i+1);
+		queue->tx_link[i] = i + 1;
 		queue->grant_tx_ref[i] = GRANT_INVALID_REF;
 		queue->grant_tx_page[i] = NULL;
 	}
+	queue->tx_link[NET_TX_RING_SIZE - 1] = TX_LINK_NONE;
 
 	/* Clear out rx_skbs */
 	for (i = 0; i < NET_RX_RING_SIZE; i++) {
@@ -1738,22 +1943,6 @@
 	return err;
 }
 
-static void xennet_destroy_queues(struct netfront_info *info)
-{
-	unsigned int i;
-
-	for (i = 0; i < info->netdev->real_num_tx_queues; i++) {
-		struct netfront_queue *queue = &info->queues[i];
-
-		if (netif_running(info->netdev))
-			napi_disable(&queue->napi);
-		netif_napi_del(&queue->napi);
-	}
-
-	kfree(info->queues);
-	info->queues = NULL;
-}
-
 static int xennet_create_queues(struct netfront_info *info,
 				unsigned int *num_queues)
 {
@@ -1809,6 +1998,10 @@
 
 	info->netdev->irq = 0;
 
+	/* Check if backend is trusted. */
+	info->bounce = !xennet_trusted ||
+		       !xenbus_read_unsigned(dev->nodename, "trusted", 1);
+
 	/* Check if backend supports multiple queues */
 	max_queues = xenbus_read_unsigned(info->xbdev->otherend,
 					  "multi-queue-max-queues", 1);
@@ -1829,6 +2022,9 @@
 	if (info->queues)
 		xennet_destroy_queues(info);
 
+	/* For the case of a reconnect reset the "broken" indicator. */
+	info->broken = false;
+
 	err = xennet_create_queues(info, &num_queues);
 	if (err < 0) {
 		xenbus_dev_fatal(dev, err, "creating queues");
@@ -1959,6 +2155,9 @@
 	err = talk_to_netback(np->xbdev, np);
 	if (err)
 		return err;
+	if (np->bounce)
+		dev_info(&np->xbdev->dev,
+			 "bouncing transmitted data to zeroed pages\n");
 
 	/* talk_to_netback() sets the correct number of queues */
 	num_queues = dev->real_num_tx_queues;
@@ -1982,6 +2181,10 @@
 	 * domain a kick because we've probably just requeued some
 	 * packets.
 	 */
+	netif_tx_lock_bh(np->netdev);
+	netif_device_attach(np->netdev);
+	netif_tx_unlock_bh(np->netdev);
+
 	netif_carrier_on(np->netdev);
 	for (j = 0; j < num_queues; ++j) {
 		queue = &np->queues[j];
@@ -2139,28 +2342,43 @@
 };
 #endif /* CONFIG_SYSFS */
 
-static int xennet_remove(struct xenbus_device *dev)
+static void xennet_bus_close(struct xenbus_device *dev)
 {
-	struct netfront_info *info = dev_get_drvdata(&dev->dev);
-
-	dev_dbg(&dev->dev, "%s\n", dev->nodename);
+	int ret;
 
-	if (xenbus_read_driver_state(dev->otherend) != XenbusStateClosed) {
+	if (xenbus_read_driver_state(dev->otherend) == XenbusStateClosed)
+		return;
+	do {
 		xenbus_switch_state(dev, XenbusStateClosing);
-		wait_event(module_wq,
-			   xenbus_read_driver_state(dev->otherend) ==
-			   XenbusStateClosing ||
-			   xenbus_read_driver_state(dev->otherend) ==
-			   XenbusStateUnknown);
+		ret = wait_event_timeout(module_wq,
+				   xenbus_read_driver_state(dev->otherend) ==
+				   XenbusStateClosing ||
+				   xenbus_read_driver_state(dev->otherend) ==
+				   XenbusStateClosed ||
+				   xenbus_read_driver_state(dev->otherend) ==
+				   XenbusStateUnknown,
+				   XENNET_TIMEOUT);
+	} while (!ret);
+
+	if (xenbus_read_driver_state(dev->otherend) == XenbusStateClosed)
+		return;
 
+	do {
 		xenbus_switch_state(dev, XenbusStateClosed);
-		wait_event(module_wq,
-			   xenbus_read_driver_state(dev->otherend) ==
-			   XenbusStateClosed ||
-			   xenbus_read_driver_state(dev->otherend) ==
-			   XenbusStateUnknown);
-	}
+		ret = wait_event_timeout(module_wq,
+				   xenbus_read_driver_state(dev->otherend) ==
+				   XenbusStateClosed ||
+				   xenbus_read_driver_state(dev->otherend) ==
+				   XenbusStateUnknown,
+				   XENNET_TIMEOUT);
+	} while (!ret);
+}
+
+static int xennet_remove(struct xenbus_device *dev)
+{
+	struct netfront_info *info = dev_get_drvdata(&dev->dev);
 
+	xennet_bus_close(dev);
 	xennet_disconnect_backend(info);
 
 	if (info->netdev->reg_state == NETREG_REGISTERED)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nfc/fdp/fdp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nfc/fdp/fdp.c
@@ -184,7 +184,7 @@
 	const struct firmware *fw;
 	struct sk_buff *skb;
 	unsigned long len;
-	u8 max_size, payload_size;
+	int max_size, payload_size;
 	int rc = 0;
 
 	if ((type == NCI_PATCH_TYPE_OTP && !info->otp_patch) ||
@@ -207,8 +207,7 @@
 
 	while (len) {
 
-		payload_size = min_t(unsigned long, (unsigned long) max_size,
-				     len);
+		payload_size = min_t(unsigned long, max_size, len);
 
 		skb = nci_skb_alloc(ndev, (NCI_CTRL_HDR_SIZE + payload_size),
 				    GFP_KERNEL);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nfc/fdp/i2c.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nfc/fdp/i2c.c
@@ -255,6 +255,9 @@
 					   len, sizeof(**fw_vsc_cfg),
 					   GFP_KERNEL);
 
+		if (!*fw_vsc_cfg)
+			goto alloc_err;
+
 		r = device_property_read_u8_array(dev, FDP_DP_FW_VSC_CFG_NAME,
 						  *fw_vsc_cfg, len);
 
@@ -268,6 +271,7 @@
 		*fw_vsc_cfg = NULL;
 	}
 
+alloc_err:
 	dev_dbg(dev, "Clock type: %d, clock frequency: %d, VSC: %s",
 		*clock_type, *clock_freq, *fw_vsc_cfg != NULL ? "yes" : "no");
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nfc/nfcmrvl/i2c.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nfc/nfcmrvl/i2c.c
@@ -151,10 +151,15 @@
 			ret = -EREMOTEIO;
 		} else
 			ret = 0;
+	}
+
+	if (ret) {
 		kfree_skb(skb);
+		return ret;
 	}
 
-	return ret;
+	consume_skb(skb);
+	return 0;
 }
 
 static void nfcmrvl_i2c_nci_update_config(struct nfcmrvl_private *priv,
@@ -186,9 +191,9 @@
 		pdata->irq_polarity = IRQF_TRIGGER_RISING;
 
 	ret = irq_of_parse_and_map(node, 0);
-	if (ret < 0) {
-		pr_err("Unable to get irq, error: %d\n", ret);
-		return ret;
+	if (!ret) {
+		pr_err("Unable to get irq\n");
+		return -EINVAL;
 	}
 	pdata->irq = ret;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nfc/nfcmrvl/main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nfc/nfcmrvl/main.c
@@ -194,6 +194,7 @@
 {
 	struct nci_dev *ndev = priv->ndev;
 
+	nci_unregister_device(ndev);
 	if (priv->ndev->nfc_dev->fw_download_in_progress)
 		nfcmrvl_fw_dnld_abort(priv);
 
@@ -202,7 +203,6 @@
 	if (gpio_is_valid(priv->config.reset_n_io))
 		gpio_free(priv->config.reset_n_io);
 
-	nci_unregister_device(ndev);
 	nci_free_device(ndev);
 	kfree(priv);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nfc/nfcmrvl/spi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nfc/nfcmrvl/spi.c
@@ -129,9 +129,9 @@
 	}
 
 	ret = irq_of_parse_and_map(node, 0);
-	if (ret < 0) {
-		pr_err("Unable to get irq, error: %d\n", ret);
-		return ret;
+	if (!ret) {
+		pr_err("Unable to get irq\n");
+		return -EINVAL;
 	}
 	pdata->irq = ret;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nfc/nfcmrvl/usb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nfc/nfcmrvl/usb.c
@@ -401,13 +401,25 @@
 	int err;
 
 	while ((urb = usb_get_from_anchor(&drv_data->deferred))) {
+		usb_anchor_urb(urb, &drv_data->tx_anchor);
+
 		err = usb_submit_urb(urb, GFP_ATOMIC);
-		if (err)
+		if (err) {
+			kfree(urb->setup_packet);
+			usb_unanchor_urb(urb);
+			usb_free_urb(urb);
 			break;
+		}
 
 		drv_data->tx_in_flight++;
+		usb_free_urb(urb);
+	}
+
+	/* Cleanup the rest deferred urbs. */
+	while ((urb = usb_get_from_anchor(&drv_data->deferred))) {
+		kfree(urb->setup_packet);
+		usb_free_urb(urb);
 	}
-	usb_scuttle_anchored_urbs(&drv_data->deferred);
 }
 
 static int nfcmrvl_resume(struct usb_interface *intf)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nfc/nfcsim.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nfc/nfcsim.c
@@ -192,8 +192,7 @@
 
 		if (!IS_ERR(skb))
 			dev_kfree_skb(skb);
-
-		skb = ERR_PTR(-ENODEV);
+		return;
 	}
 
 	dev->cb(dev->nfc_digital_dev, dev->arg, skb);
@@ -337,10 +336,6 @@
 static void nfcsim_debugfs_init(void)
 {
 	nfcsim_debugfs_root = debugfs_create_dir("nfcsim", NULL);
-
-	if (!nfcsim_debugfs_root)
-		pr_err("Could not create debugfs entry\n");
-
 }
 
 static void nfcsim_debugfs_remove(void)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nfc/nxp-nci/i2c.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nfc/nxp-nci/i2c.c
@@ -122,7 +122,9 @@
 	skb_put_data(*skb, &header, NXP_NCI_FW_HDR_LEN);
 
 	r = i2c_master_recv(client, skb_put(*skb, frame_len), frame_len);
-	if (r != frame_len) {
+	if (r < 0) {
+		goto fw_read_exit_free_skb;
+	} else if (r != frame_len) {
 		nfc_err(&client->dev,
 			"Invalid frame length: %u (expected %zu)\n",
 			r, frame_len);
@@ -162,8 +164,13 @@
 
 	skb_put_data(*skb, (void *)&header, NCI_CTRL_HDR_SIZE);
 
+	if (!header.plen)
+		return 0;
+
 	r = i2c_master_recv(client, skb_put(*skb, header.plen), header.plen);
-	if (r != header.plen) {
+	if (r < 0) {
+		goto nci_read_exit_free_skb;
+	} else if (r != header.plen) {
 		nfc_err(&client->dev,
 			"Invalid frame payload length: %u (expected %u)\n",
 			r, header.plen);
@@ -278,7 +285,7 @@
 
 	r = devm_acpi_dev_add_driver_gpios(dev, acpi_nxp_nci_gpios);
 	if (r)
-		return r;
+		dev_dbg(dev, "Unable to add GPIO mapping table\n");
 
 	phy->gpiod_en = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
 	if (IS_ERR(phy->gpiod_en)) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nfc/pn533/pn533.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nfc/pn533/pn533.c
@@ -185,6 +185,32 @@
 	u8 gt[];
 } __packed;
 
+struct pn532_autopoll_resp {
+	u8 type;
+	u8 ln;
+	u8 tg;
+	u8 tgdata[];
+};
+
+/* PN532_CMD_IN_AUTOPOLL */
+#define PN532_AUTOPOLL_POLLNR_INFINITE	0xff
+#define PN532_AUTOPOLL_PERIOD		0x03 /* in units of 150 ms */
+
+#define PN532_AUTOPOLL_TYPE_GENERIC_106		0x00
+#define PN532_AUTOPOLL_TYPE_GENERIC_212		0x01
+#define PN532_AUTOPOLL_TYPE_GENERIC_424		0x02
+#define PN532_AUTOPOLL_TYPE_JEWEL		0x04
+#define PN532_AUTOPOLL_TYPE_MIFARE		0x10
+#define PN532_AUTOPOLL_TYPE_FELICA212		0x11
+#define PN532_AUTOPOLL_TYPE_FELICA424		0x12
+#define PN532_AUTOPOLL_TYPE_ISOA		0x20
+#define PN532_AUTOPOLL_TYPE_ISOB		0x23
+#define PN532_AUTOPOLL_TYPE_DEP_PASSIVE_106	0x40
+#define PN532_AUTOPOLL_TYPE_DEP_PASSIVE_212	0x41
+#define PN532_AUTOPOLL_TYPE_DEP_PASSIVE_424	0x42
+#define PN532_AUTOPOLL_TYPE_DEP_ACTIVE_106	0x80
+#define PN532_AUTOPOLL_TYPE_DEP_ACTIVE_212	0x81
+#define PN532_AUTOPOLL_TYPE_DEP_ACTIVE_424	0x82
 
 /* PN533_TG_INIT_AS_TARGET */
 #define PN533_INIT_TARGET_PASSIVE 0x1
@@ -680,6 +706,9 @@
 	if (PN533_TYPE_A_SEL_CASCADE(type_a->sel_res) != 0)
 		return false;
 
+	if (type_a->nfcid_len > NFC_NFCID1_MAXSIZE)
+		return false;
+
 	return true;
 }
 
@@ -1290,6 +1319,8 @@
 	if (IS_ERR(resp))
 		return PTR_ERR(resp);
 
+	memset(&nfc_target, 0, sizeof(struct nfc_target));
+
 	rsp = (struct pn533_cmd_jump_dep_response *)resp->data;
 
 	rc = rsp->status & PN533_CMD_RET_MASK;
@@ -1389,6 +1420,101 @@
 	return rc;
 }
 
+static int pn533_autopoll_complete(struct pn533 *dev, void *arg,
+			       struct sk_buff *resp)
+{
+	struct pn532_autopoll_resp *apr;
+	struct nfc_target nfc_tgt;
+	u8 nbtg;
+	int rc;
+
+	if (IS_ERR(resp)) {
+		rc = PTR_ERR(resp);
+
+		nfc_err(dev->dev, "%s  autopoll complete error %d\n",
+			__func__, rc);
+
+		if (rc == -ENOENT) {
+			if (dev->poll_mod_count != 0)
+				return rc;
+			goto stop_poll;
+		} else if (rc < 0) {
+			nfc_err(dev->dev,
+				"Error %d when running autopoll\n", rc);
+			goto stop_poll;
+		}
+	}
+
+	nbtg = resp->data[0];
+	if ((nbtg > 2) || (nbtg <= 0))
+		return -EAGAIN;
+
+	apr = (struct pn532_autopoll_resp *)&resp->data[1];
+	while (nbtg--) {
+		memset(&nfc_tgt, 0, sizeof(struct nfc_target));
+		switch (apr->type) {
+		case PN532_AUTOPOLL_TYPE_ISOA:
+			dev_dbg(dev->dev, "ISOA\n");
+			rc = pn533_target_found_type_a(&nfc_tgt, apr->tgdata,
+						       apr->ln - 1);
+			break;
+		case PN532_AUTOPOLL_TYPE_FELICA212:
+		case PN532_AUTOPOLL_TYPE_FELICA424:
+			dev_dbg(dev->dev, "FELICA\n");
+			rc = pn533_target_found_felica(&nfc_tgt, apr->tgdata,
+						       apr->ln - 1);
+			break;
+		case PN532_AUTOPOLL_TYPE_JEWEL:
+			dev_dbg(dev->dev, "JEWEL\n");
+			rc = pn533_target_found_jewel(&nfc_tgt, apr->tgdata,
+						      apr->ln - 1);
+			break;
+		case PN532_AUTOPOLL_TYPE_ISOB:
+			dev_dbg(dev->dev, "ISOB\n");
+			rc = pn533_target_found_type_b(&nfc_tgt, apr->tgdata,
+						       apr->ln - 1);
+			break;
+		case PN532_AUTOPOLL_TYPE_MIFARE:
+			dev_dbg(dev->dev, "Mifare\n");
+			rc = pn533_target_found_type_a(&nfc_tgt, apr->tgdata,
+						       apr->ln - 1);
+			break;
+		default:
+			nfc_err(dev->dev,
+				    "Unknown current poll modulation\n");
+			rc = -EPROTO;
+		}
+
+		if (rc)
+			goto done;
+
+		if (!(nfc_tgt.supported_protocols & dev->poll_protocols)) {
+			nfc_err(dev->dev,
+				    "The Tg found doesn't have the desired protocol\n");
+			rc = -EAGAIN;
+			goto done;
+		}
+
+		dev->tgt_available_prots = nfc_tgt.supported_protocols;
+		apr = (struct pn532_autopoll_resp *)
+			(apr->tgdata + (apr->ln - 1));
+	}
+
+	pn533_poll_reset_mod_list(dev);
+	nfc_targets_found(dev->nfc_dev, &nfc_tgt, 1);
+
+done:
+	dev_kfree_skb(resp);
+	return rc;
+
+stop_poll:
+	nfc_err(dev->dev, "autopoll operation has been stopped\n");
+
+	pn533_poll_reset_mod_list(dev);
+	dev->poll_protocols = 0;
+	return rc;
+}
+
 static int pn533_poll_complete(struct pn533 *dev, void *arg,
 			       struct sk_buff *resp)
 {
@@ -1532,6 +1658,7 @@
 {
 	struct pn533 *dev = nfc_get_drvdata(nfc_dev);
 	struct pn533_poll_modulations *cur_mod;
+	struct sk_buff *skb;
 	u8 rand_mod;
 	int rc;
 
@@ -1557,9 +1684,78 @@
 			tm_protocols = 0;
 	}
 
-	pn533_poll_create_mod_list(dev, im_protocols, tm_protocols);
 	dev->poll_protocols = im_protocols;
 	dev->listen_protocols = tm_protocols;
+	if (dev->device_type == PN533_DEVICE_PN532_AUTOPOLL) {
+		skb = pn533_alloc_skb(dev, 4 + 6);
+		if (!skb)
+			return -ENOMEM;
+
+		*((u8 *)skb_put(skb, sizeof(u8))) =
+			PN532_AUTOPOLL_POLLNR_INFINITE;
+		*((u8 *)skb_put(skb, sizeof(u8))) = PN532_AUTOPOLL_PERIOD;
+
+		if ((im_protocols & NFC_PROTO_MIFARE_MASK) &&
+				(im_protocols & NFC_PROTO_ISO14443_MASK) &&
+				(im_protocols & NFC_PROTO_NFC_DEP_MASK))
+			*((u8 *)skb_put(skb, sizeof(u8))) =
+				PN532_AUTOPOLL_TYPE_GENERIC_106;
+		else {
+			if (im_protocols & NFC_PROTO_MIFARE_MASK)
+				*((u8 *)skb_put(skb, sizeof(u8))) =
+					PN532_AUTOPOLL_TYPE_MIFARE;
+
+			if (im_protocols & NFC_PROTO_ISO14443_MASK)
+				*((u8 *)skb_put(skb, sizeof(u8))) =
+					PN532_AUTOPOLL_TYPE_ISOA;
+
+			if (im_protocols & NFC_PROTO_NFC_DEP_MASK) {
+				*((u8 *)skb_put(skb, sizeof(u8))) =
+					PN532_AUTOPOLL_TYPE_DEP_PASSIVE_106;
+				*((u8 *)skb_put(skb, sizeof(u8))) =
+					PN532_AUTOPOLL_TYPE_DEP_PASSIVE_212;
+				*((u8 *)skb_put(skb, sizeof(u8))) =
+					PN532_AUTOPOLL_TYPE_DEP_PASSIVE_424;
+			}
+		}
+
+		if (im_protocols & NFC_PROTO_FELICA_MASK ||
+				im_protocols & NFC_PROTO_NFC_DEP_MASK) {
+			*((u8 *)skb_put(skb, sizeof(u8))) =
+				PN532_AUTOPOLL_TYPE_FELICA212;
+			*((u8 *)skb_put(skb, sizeof(u8))) =
+				PN532_AUTOPOLL_TYPE_FELICA424;
+		}
+
+		if (im_protocols & NFC_PROTO_JEWEL_MASK)
+			*((u8 *)skb_put(skb, sizeof(u8))) =
+				PN532_AUTOPOLL_TYPE_JEWEL;
+
+		if (im_protocols & NFC_PROTO_ISO14443_B_MASK)
+			*((u8 *)skb_put(skb, sizeof(u8))) =
+				PN532_AUTOPOLL_TYPE_ISOB;
+
+		if (tm_protocols)
+			*((u8 *)skb_put(skb, sizeof(u8))) =
+				PN532_AUTOPOLL_TYPE_DEP_ACTIVE_106;
+
+		rc = pn533_send_cmd_async(dev, PN533_CMD_IN_AUTOPOLL, skb,
+				pn533_autopoll_complete, NULL);
+
+		if (rc < 0)
+			dev_kfree_skb(skb);
+		else
+			dev->poll_mod_count++;
+
+		return rc;
+	}
+
+	pn533_poll_create_mod_list(dev, im_protocols, tm_protocols);
+	if (!dev->poll_mod_count) {
+		nfc_err(dev->dev,
+			"Poll mod list is empty\n");
+		return -EINVAL;
+	}
 
 	/* Do not always start polling from the same modulation */
 	get_random_bytes(&rand_mod, sizeof(rand_mod));
@@ -1771,6 +1967,8 @@
 
 		dev_dbg(dev->dev, "Creating new target\n");
 
+		memset(&nfc_target, 0, sizeof(struct nfc_target));
+
 		nfc_target.supported_protocols = NFC_PROTO_NFC_DEP_MASK;
 		nfc_target.nfcid1_len = 10;
 		memcpy(nfc_target.nfcid1, rsp->nfcid3t, nfc_target.nfcid1_len);
@@ -2069,7 +2267,7 @@
 		frag = pn533_alloc_skb(dev, frag_size);
 		if (!frag) {
 			skb_queue_purge(&dev->fragment_skb);
-			break;
+			return -ENOMEM;
 		}
 
 		if (!dev->tgt_mode) {
@@ -2140,7 +2338,7 @@
 		/* jumbo frame ? */
 		if (skb->len > PN533_CMD_DATAEXCH_DATA_MAXLEN) {
 			rc = pn533_fill_fragment_skbs(dev, skb);
-			if (rc <= 0)
+			if (rc < 0)
 				goto error;
 
 			skb = skb_dequeue(&dev->fragment_skb);
@@ -2212,7 +2410,7 @@
 	/* let's split in multiple chunks if size's too big */
 	if (skb->len > PN533_CMD_DATAEXCH_DATA_MAXLEN) {
 		rc = pn533_fill_fragment_skbs(dev, skb);
-		if (rc <= 0)
+		if (rc < 0)
 			goto error;
 
 		/* get the first skb */
@@ -2458,7 +2656,11 @@
 {
 	struct pn533 *dev = nfc_get_drvdata(nfc_dev);
 
-	if (dev->device_type == PN533_DEVICE_PN532) {
+	if (dev->phy_ops->dev_up)
+		dev->phy_ops->dev_up(dev);
+
+	if ((dev->device_type == PN533_DEVICE_PN532) ||
+		(dev->device_type == PN533_DEVICE_PN532_AUTOPOLL)) {
 		int rc = pn532_sam_configuration(nfc_dev);
 
 		if (rc)
@@ -2470,7 +2672,14 @@
 
 static int pn533_dev_down(struct nfc_dev *nfc_dev)
 {
-	return pn533_rf_field(nfc_dev, 0);
+	struct pn533 *dev = nfc_get_drvdata(nfc_dev);
+	int ret;
+
+	ret = pn533_rf_field(nfc_dev, 0);
+	if (dev->phy_ops->dev_down && !ret)
+		dev->phy_ops->dev_down(dev);
+
+	return ret;
 }
 
 static struct nfc_ops pn533_nfc_ops = {
@@ -2498,6 +2707,7 @@
 	case PN533_DEVICE_PASORI:
 	case PN533_DEVICE_ACR122U:
 	case PN533_DEVICE_PN532:
+	case PN533_DEVICE_PN532_AUTOPOLL:
 		max_retries.mx_rty_atr = 0x2;
 		max_retries.mx_rty_psl = 0x1;
 		max_retries.mx_rty_passive_act =
@@ -2534,6 +2744,7 @@
 	switch (dev->device_type) {
 	case PN533_DEVICE_STD:
 	case PN533_DEVICE_PN532:
+	case PN533_DEVICE_PN532_AUTOPOLL:
 		break;
 
 	case PN533_DEVICE_PASORI:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nfc/pn533/pn533.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/nfc/pn533/pn533.h
@@ -6,10 +6,11 @@
  * Copyright (C) 2012-2013 Tieto Poland
  */
 
-#define PN533_DEVICE_STD     0x1
-#define PN533_DEVICE_PASORI  0x2
-#define PN533_DEVICE_ACR122U 0x3
-#define PN533_DEVICE_PN532   0x4
+#define PN533_DEVICE_STD		0x1
+#define PN533_DEVICE_PASORI		0x2
+#define PN533_DEVICE_ACR122U		0x3
+#define PN533_DEVICE_PN532		0x4
+#define PN533_DEVICE_PN532_AUTOPOLL	0x5
 
 #define PN533_ALL_PROTOCOLS (NFC_PROTO_JEWEL_MASK | NFC_PROTO_MIFARE_MASK |\
 			     NFC_PROTO_FELICA_MASK | NFC_PROTO_ISO14443_MASK |\
@@ -70,6 +71,7 @@
 #define PN533_CMD_IN_ATR 0x50
 #define PN533_CMD_IN_RELEASE 0x52
 #define PN533_CMD_IN_JUMP_FOR_DEP 0x56
+#define PN533_CMD_IN_AUTOPOLL 0x60
 
 #define PN533_CMD_TG_INIT_AS_TARGET 0x8c
 #define PN533_CMD_TG_GET_DATA 0x86
@@ -207,6 +209,15 @@
 			  struct sk_buff *out);
 	int (*send_ack)(struct pn533 *dev, gfp_t flags);
 	void (*abort_cmd)(struct pn533 *priv, gfp_t flags);
+	/*
+	 * dev_up and dev_down are optional.
+	 * They are used to inform the phy layer that the nfc chip
+	 * is going to be really used very soon. The phy layer can then
+	 * bring up it's interface to the chip and have it suspended for power
+	 * saving reasons otherwise.
+	 */
+	void (*dev_up)(struct pn533 *priv);
+	void (*dev_down)(struct pn533 *priv);
 };
 
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nfc/pn533/usb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nfc/pn533/usb.c
@@ -153,10 +153,17 @@
 	return usb_submit_urb(phy->ack_urb, flags);
 }
 
+struct pn533_out_arg {
+	struct pn533_usb_phy *phy;
+	struct completion done;
+};
+
 static int pn533_usb_send_frame(struct pn533 *dev,
 				struct sk_buff *out)
 {
 	struct pn533_usb_phy *phy = dev->phy;
+	struct pn533_out_arg arg;
+	void *cntx;
 	int rc;
 
 	if (phy->priv == NULL)
@@ -168,10 +175,18 @@
 	print_hex_dump_debug("PN533 TX: ", DUMP_PREFIX_NONE, 16, 1,
 			     out->data, out->len, false);
 
+	arg.phy = phy;
+	init_completion(&arg.done);
+	cntx = phy->out_urb->context;
+	phy->out_urb->context = &arg;
+
 	rc = usb_submit_urb(phy->out_urb, GFP_KERNEL);
 	if (rc)
 		return rc;
 
+	wait_for_completion(&arg.done);
+	phy->out_urb->context = cntx;
+
 	if (dev->protocol_type == PN533_PROTO_REQ_RESP) {
 		/* request for response for sent packet directly */
 		rc = pn533_submit_urb_for_response(phy, GFP_KERNEL);
@@ -391,7 +406,7 @@
 		       cmd, sizeof(cmd), false);
 
 	rc = usb_bulk_msg(phy->udev, phy->out_urb->pipe, buffer, sizeof(cmd),
-			  &transferred, 0);
+			  &transferred, 5000);
 	kfree(buffer);
 	if (rc || (transferred != sizeof(cmd))) {
 		nfc_err(&phy->udev->dev,
@@ -412,7 +427,31 @@
 	return arg.rc;
 }
 
-static void pn533_send_complete(struct urb *urb)
+static void pn533_out_complete(struct urb *urb)
+{
+	struct pn533_out_arg *arg = urb->context;
+	struct pn533_usb_phy *phy = arg->phy;
+
+	switch (urb->status) {
+	case 0:
+		break; /* success */
+	case -ECONNRESET:
+	case -ENOENT:
+		dev_dbg(&phy->udev->dev,
+			"The urb has been stopped (status %d)\n",
+			urb->status);
+		break;
+	case -ESHUTDOWN:
+	default:
+		nfc_err(&phy->udev->dev,
+			"Urb failure (status %d)\n",
+			urb->status);
+	}
+
+	complete(&arg->done);
+}
+
+static void pn533_ack_complete(struct urb *urb)
 {
 	struct pn533_usb_phy *phy = urb->context;
 
@@ -500,10 +539,10 @@
 
 	usb_fill_bulk_urb(phy->out_urb, phy->udev,
 			  usb_sndbulkpipe(phy->udev, out_endpoint),
-			  NULL, 0, pn533_send_complete, phy);
+			  NULL, 0, pn533_out_complete, phy);
 	usb_fill_bulk_urb(phy->ack_urb, phy->udev,
 			  usb_sndbulkpipe(phy->udev, out_endpoint),
-			  NULL, 0, pn533_send_complete, phy);
+			  NULL, 0, pn533_ack_complete, phy);
 
 	switch (id->driver_info) {
 	case PN533_DEVICE_STD:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nfc/pn544/i2c.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nfc/pn544/i2c.c
@@ -225,6 +225,7 @@
 
 out:
 	gpiod_set_value_cansleep(phy->gpiod_en, !phy->en_polarity);
+	usleep_range(10000, 15000);
 }
 
 static void pn544_hci_i2c_enable_mode(struct pn544_i2c_phy *phy, int run_mode)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nfc/pn544/pn544.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nfc/pn544/pn544.c
@@ -693,7 +693,7 @@
 		    target->nfcid1_len != 10)
 			return -EOPNOTSUPP;
 
-		 return nfc_hci_send_cmd(hdev, NFC_HCI_RF_READER_A_GATE,
+		return nfc_hci_send_cmd(hdev, NFC_HCI_RF_READER_A_GATE,
 				     PN544_RF_READER_CMD_ACTIVATE_NEXT,
 				     target->nfcid1, target->nfcid1_len, NULL);
 	} else if (target->supported_protocols & (NFC_PROTO_JEWEL_MASK |
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nfc/port100.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nfc/port100.c
@@ -565,7 +565,7 @@
 {
 	struct port100_frame *frame = _frame;
 
-	frame->datalen = cpu_to_le16(le16_to_cpu(frame->datalen) + len);
+	le16_add_cpu(&frame->datalen, len);
 }
 
 static bool port100_rx_frame_is_valid(void *_frame)
@@ -1003,11 +1003,11 @@
 
 	skb = port100_alloc_skb(dev, 0);
 	if (!skb)
-		return -ENOMEM;
+		return 0;
 
 	resp = port100_send_cmd_sync(dev, PORT100_CMD_GET_COMMAND_TYPE, skb);
 	if (IS_ERR(resp))
-		return PTR_ERR(resp);
+		return 0;
 
 	if (resp->len < 8)
 		mask = 0;
@@ -1609,7 +1609,9 @@
 	nfc_digital_free_device(dev->nfc_digital_dev);
 
 error:
+	usb_kill_urb(dev->in_urb);
 	usb_free_urb(dev->in_urb);
+	usb_kill_urb(dev->out_urb);
 	usb_free_urb(dev->out_urb);
 	usb_put_dev(dev->udev);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nfc/s3fwrn5/core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nfc/s3fwrn5/core.c
@@ -97,11 +97,15 @@
 	}
 
 	ret = s3fwrn5_write(info, skb);
-	if (ret < 0)
+	if (ret < 0) {
 		kfree_skb(skb);
+		mutex_unlock(&info->mutex);
+		return ret;
+	}
 
+	consume_skb(skb);
 	mutex_unlock(&info->mutex);
-	return ret;
+	return 0;
 }
 
 static int s3fwrn5_nci_post_setup(struct nci_dev *ndev)
@@ -198,6 +202,7 @@
 	case S3FWRN5_MODE_FW:
 		return s3fwrn5_fw_recv_frame(ndev, skb);
 	default:
+		kfree_skb(skb);
 		return -ENODEV;
 	}
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nfc/s3fwrn5/firmware.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nfc/s3fwrn5/firmware.c
@@ -293,8 +293,10 @@
 	if (ret < 0)
 		return ret;
 
-	if (fw->fw->size < S3FWRN5_FW_IMAGE_HEADER_SIZE)
+	if (fw->fw->size < S3FWRN5_FW_IMAGE_HEADER_SIZE) {
+		release_firmware(fw->fw);
 		return -EINVAL;
+	}
 
 	memcpy(fw->date, fw->fw->data + 0x00, 12);
 	fw->date[12] = '\0';
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nfc/s3fwrn5/i2c.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nfc/s3fwrn5/i2c.c
@@ -26,8 +26,8 @@
 	struct i2c_client *i2c_dev;
 	struct nci_dev *ndev;
 
-	unsigned int gpio_en;
-	unsigned int gpio_fw_wake;
+	int gpio_en;
+	int gpio_fw_wake;
 
 	struct mutex mutex;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nfc/st-nci/ndlc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nfc/st-nci/ndlc.c
@@ -286,13 +286,15 @@
 
 void ndlc_remove(struct llt_ndlc *ndlc)
 {
-	st_nci_remove(ndlc->ndev);
-
 	/* cancel timers */
 	del_timer_sync(&ndlc->t1_timer);
 	del_timer_sync(&ndlc->t2_timer);
 	ndlc->t2_active = false;
 	ndlc->t1_active = false;
+	/* cancel work */
+	cancel_work_sync(&ndlc->sm_work);
+
+	st_nci_remove(ndlc->ndev);
 
 	skb_queue_purge(&ndlc->rcv_q);
 	skb_queue_purge(&ndlc->send_q);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nfc/st-nci/se.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nfc/st-nci/se.c
@@ -327,7 +327,7 @@
 		 * AID          81      5 to 16
 		 * PARAMETERS   82      0 to 255
 		 */
-		if (skb->len < NFC_MIN_AID_LENGTH + 2 &&
+		if (skb->len < NFC_MIN_AID_LENGTH + 2 ||
 		    skb->data[0] != NFC_EVT_TRANSACTION_AID_TAG)
 			return -EPROTO;
 
@@ -341,8 +341,10 @@
 
 		/* Check next byte is PARAMETERS tag (82) */
 		if (skb->data[transaction->aid_len + 2] !=
-		    NFC_EVT_TRANSACTION_PARAMS_TAG)
+		    NFC_EVT_TRANSACTION_PARAMS_TAG) {
+			devm_kfree(dev, transaction);
 			return -EPROTO;
+		}
 
 		transaction->params_len = skb->data[transaction->aid_len + 3];
 		memcpy(transaction->params, skb->data +
@@ -663,6 +665,12 @@
 					ST_NCI_EVT_TRANSMIT_DATA, apdu,
 					apdu_length);
 	default:
+		/* Need to free cb_context here as at the moment we can't
+		 * clearly indicate to the caller if the callback function
+		 * would be called (and free it) or not. In both cases a
+		 * negative value may be returned to the caller.
+		 */
+		kfree(cb_context);
 		return -ENODEV;
 	}
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nfc/st21nfca/dep.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nfc/st21nfca/dep.c
@@ -173,8 +173,10 @@
 		memcpy(atr_res->gbi, atr_req->gbi, gb_len);
 		r = nfc_set_remote_general_bytes(hdev->ndev, atr_res->gbi,
 						  gb_len);
-		if (r < 0)
+		if (r < 0) {
+			kfree_skb(skb);
 			return r;
+		}
 	}
 
 	info->dep_info.curr_nfc_dep_pni = 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nfc/st21nfca/i2c.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nfc/st21nfca/i2c.c
@@ -533,7 +533,8 @@
 	phy->gpiod_ena = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
 	if (IS_ERR(phy->gpiod_ena)) {
 		nfc_err(dev, "Unable to get ENABLE GPIO\n");
-		return PTR_ERR(phy->gpiod_ena);
+		r = PTR_ERR(phy->gpiod_ena);
+		goto out_free;
 	}
 
 	phy->se_status.is_ese_present =
@@ -544,7 +545,7 @@
 	r = st21nfca_hci_platform_init(phy);
 	if (r < 0) {
 		nfc_err(&client->dev, "Unable to reboot st21nfca\n");
-		return r;
+		goto out_free;
 	}
 
 	r = devm_request_threaded_irq(&client->dev, client->irq, NULL,
@@ -553,15 +554,23 @@
 				ST21NFCA_HCI_DRIVER_NAME, phy);
 	if (r < 0) {
 		nfc_err(&client->dev, "Unable to register IRQ handler\n");
-		return r;
+		goto out_free;
 	}
 
-	return st21nfca_hci_probe(phy, &i2c_phy_ops, LLC_SHDLC_NAME,
-					ST21NFCA_FRAME_HEADROOM,
-					ST21NFCA_FRAME_TAILROOM,
-					ST21NFCA_HCI_LLC_MAX_PAYLOAD,
-					&phy->hdev,
-					&phy->se_status);
+	r = st21nfca_hci_probe(phy, &i2c_phy_ops, LLC_SHDLC_NAME,
+			       ST21NFCA_FRAME_HEADROOM,
+			       ST21NFCA_FRAME_TAILROOM,
+			       ST21NFCA_HCI_LLC_MAX_PAYLOAD,
+			       &phy->hdev,
+			       &phy->se_status);
+	if (r)
+		goto out_free;
+
+	return 0;
+
+out_free:
+	kfree_skb(phy->pending_skb);
+	return r;
 }
 
 static int st21nfca_hci_i2c_remove(struct i2c_client *client)
@@ -574,6 +583,8 @@
 
 	if (phy->powered)
 		st21nfca_hci_i2c_disable(phy);
+	if (phy->pending_skb)
+		kfree_skb(phy->pending_skb);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nfc/st21nfca/se.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nfc/st21nfca/se.c
@@ -236,12 +236,18 @@
 					ST21NFCA_EVT_TRANSMIT_DATA,
 					apdu, apdu_length);
 	default:
+		/* Need to free cb_context here as at the moment we can't
+		 * clearly indicate to the caller if the callback function
+		 * would be called (and free it) or not. In both cases a
+		 * negative value may be returned to the caller.
+		 */
+		kfree(cb_context);
 		return -ENODEV;
 	}
 }
 EXPORT_SYMBOL(st21nfca_hci_se_io);
 
-static void st21nfca_se_wt_timeout(struct timer_list *t)
+static void st21nfca_se_wt_work(struct work_struct *work)
 {
 	/*
 	 * No answer from the secure element
@@ -254,8 +260,9 @@
 	 */
 	/* hardware reset managed through VCC_UICC_OUT power supply */
 	u8 param = 0x01;
-	struct st21nfca_hci_info *info = from_timer(info, t,
-						    se_info.bwi_timer);
+	struct st21nfca_hci_info *info = container_of(work,
+						struct st21nfca_hci_info,
+						se_info.timeout_work);
 
 	pr_debug("\n");
 
@@ -273,6 +280,13 @@
 	info->se_info.cb(info->se_info.cb_context, NULL, 0, -ETIME);
 }
 
+static void st21nfca_se_wt_timeout(struct timer_list *t)
+{
+	struct st21nfca_hci_info *info = from_timer(info, t, se_info.bwi_timer);
+
+	schedule_work(&info->se_info.timeout_work);
+}
+
 static void st21nfca_se_activation_timeout(struct timer_list *t)
 {
 	struct st21nfca_hci_info *info = from_timer(info, t,
@@ -296,6 +310,8 @@
 	int r = 0;
 	struct device *dev = &hdev->ndev->dev;
 	struct nfc_evt_transaction *transaction;
+	u32 aid_len;
+	u8 params_len;
 
 	pr_debug("connectivity gate event: %x\n", event);
 
@@ -304,34 +320,48 @@
 		r = nfc_se_connectivity(hdev->ndev, host);
 	break;
 	case ST21NFCA_EVT_TRANSACTION:
-		/*
-		 * According to specification etsi 102 622
+		/* According to specification etsi 102 622
 		 * 11.2.2.4 EVT_TRANSACTION Table 52
 		 * Description	Tag	Length
 		 * AID		81	5 to 16
 		 * PARAMETERS	82	0 to 255
+		 *
+		 * The key differences are aid storage length is variably sized
+		 * in the packet, but fixed in nfc_evt_transaction, and that the aid_len
+		 * is u8 in the packet, but u32 in the structure, and the tags in
+		 * the packet are not included in nfc_evt_transaction.
+		 *
+		 * size in bytes: 1          1       5-16 1             1           0-255
+		 * offset:        0          1       2    aid_len + 2   aid_len + 3 aid_len + 4
+		 * member name:   aid_tag(M) aid_len aid  params_tag(M) params_len  params
+		 * example:       0x81       5-16    X    0x82 0-255    X
 		 */
-		if (skb->len < NFC_MIN_AID_LENGTH + 2 &&
-		    skb->data[0] != NFC_EVT_TRANSACTION_AID_TAG)
+		if (skb->len < 2 || skb->data[0] != NFC_EVT_TRANSACTION_AID_TAG)
 			return -EPROTO;
 
-		transaction = (struct nfc_evt_transaction *)devm_kzalloc(dev,
-						   skb->len - 2, GFP_KERNEL);
+		aid_len = skb->data[1];
+
+		if (skb->len < aid_len + 4 || aid_len > sizeof(transaction->aid))
+			return -EPROTO;
+
+		params_len = skb->data[aid_len + 3];
+
+		/* Verify PARAMETERS tag is (82), and final check that there is enough
+		 * space in the packet to read everything.
+		 */
+		if ((skb->data[aid_len + 2] != NFC_EVT_TRANSACTION_PARAMS_TAG) ||
+		    (skb->len < aid_len + 4 + params_len))
+			return -EPROTO;
+
+		transaction = devm_kzalloc(dev, sizeof(*transaction) + params_len, GFP_KERNEL);
 		if (!transaction)
 			return -ENOMEM;
 
-		transaction->aid_len = skb->data[1];
-		memcpy(transaction->aid, &skb->data[2],
-		       transaction->aid_len);
-
-		/* Check next byte is PARAMETERS tag (82) */
-		if (skb->data[transaction->aid_len + 2] !=
-		    NFC_EVT_TRANSACTION_PARAMS_TAG)
-			return -EPROTO;
+		transaction->aid_len = aid_len;
+		transaction->params_len = params_len;
 
-		transaction->params_len = skb->data[transaction->aid_len + 3];
-		memcpy(transaction->params, skb->data +
-		       transaction->aid_len + 4, transaction->params_len);
+		memcpy(transaction->aid, &skb->data[2], aid_len);
+		memcpy(transaction->params, &skb->data[aid_len + 4], params_len);
 
 		r = nfc_se_transaction(hdev->ndev, host, transaction);
 	break;
@@ -355,6 +385,7 @@
 	switch (event) {
 	case ST21NFCA_EVT_TRANSMIT_DATA:
 		del_timer_sync(&info->se_info.bwi_timer);
+		cancel_work_sync(&info->se_info.timeout_work);
 		info->se_info.bwi_active = false;
 		r = nfc_hci_send_event(hdev, ST21NFCA_DEVICE_MGNT_GATE,
 				ST21NFCA_EVT_SE_END_OF_APDU_TRANSFER, NULL, 0);
@@ -384,6 +415,7 @@
 	struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
 
 	init_completion(&info->se_info.req_completion);
+	INIT_WORK(&info->se_info.timeout_work, st21nfca_se_wt_work);
 	/* initialize timers */
 	timer_setup(&info->se_info.bwi_timer, st21nfca_se_wt_timeout, 0);
 	info->se_info.bwi_active = false;
@@ -411,6 +443,7 @@
 	if (info->se_info.se_active)
 		del_timer_sync(&info->se_info.se_active_timer);
 
+	cancel_work_sync(&info->se_info.timeout_work);
 	info->se_info.bwi_active = false;
 	info->se_info.se_active = false;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nfc/st21nfca/st21nfca.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/nfc/st21nfca/st21nfca.h
@@ -141,6 +141,7 @@
 
 	se_io_cb_t cb;
 	void *cb_context;
+	struct work_struct timeout_work;
 };
 
 struct st21nfca_hci_info {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nfc/st95hf/core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nfc/st95hf/core.c
@@ -966,7 +966,7 @@
 	rc = down_killable(&stcontext->exchange_lock);
 	if (rc) {
 		WARN(1, "Semaphore is not found up in st95hf_in_send_cmd\n");
-		return rc;
+		goto free_skb_resp;
 	}
 
 	rc = st95hf_spi_send(&stcontext->spicontext, skb->data,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nfc/trf7970a.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nfc/trf7970a.c
@@ -424,7 +424,8 @@
 	enum trf7970a_state		state;
 	struct device			*dev;
 	struct spi_device		*spi;
-	struct regulator		*regulator;
+	struct regulator		*vin_regulator;
+	struct regulator		*vddio_regulator;
 	struct nfc_digital_dev		*ddev;
 	u32				quirks;
 	bool				is_initiator;
@@ -1883,7 +1884,7 @@
 	if (trf->state != TRF7970A_ST_PWR_OFF)
 		return 0;
 
-	ret = regulator_enable(trf->regulator);
+	ret = regulator_enable(trf->vin_regulator);
 	if (ret) {
 		dev_err(trf->dev, "%s - Can't enable VIN: %d\n", __func__, ret);
 		return ret;
@@ -1926,7 +1927,7 @@
 	if (trf->en2_gpiod && !(trf->quirks & TRF7970A_QUIRK_EN2_MUST_STAY_LOW))
 		gpiod_set_value_cansleep(trf->en2_gpiod, 0);
 
-	ret = regulator_disable(trf->regulator);
+	ret = regulator_disable(trf->vin_regulator);
 	if (ret)
 		dev_err(trf->dev, "%s - Can't disable VIN: %d\n", __func__,
 			ret);
@@ -2065,37 +2066,37 @@
 	mutex_init(&trf->lock);
 	INIT_DELAYED_WORK(&trf->timeout_work, trf7970a_timeout_work_handler);
 
-	trf->regulator = devm_regulator_get(&spi->dev, "vin");
-	if (IS_ERR(trf->regulator)) {
-		ret = PTR_ERR(trf->regulator);
+	trf->vin_regulator = devm_regulator_get(&spi->dev, "vin");
+	if (IS_ERR(trf->vin_regulator)) {
+		ret = PTR_ERR(trf->vin_regulator);
 		dev_err(trf->dev, "Can't get VIN regulator: %d\n", ret);
 		goto err_destroy_lock;
 	}
 
-	ret = regulator_enable(trf->regulator);
+	ret = regulator_enable(trf->vin_regulator);
 	if (ret) {
 		dev_err(trf->dev, "Can't enable VIN: %d\n", ret);
 		goto err_destroy_lock;
 	}
 
-	uvolts = regulator_get_voltage(trf->regulator);
+	uvolts = regulator_get_voltage(trf->vin_regulator);
 	if (uvolts > 4000000)
 		trf->chip_status_ctrl = TRF7970A_CHIP_STATUS_VRS5_3;
 
-	trf->regulator = devm_regulator_get(&spi->dev, "vdd-io");
-	if (IS_ERR(trf->regulator)) {
-		ret = PTR_ERR(trf->regulator);
+	trf->vddio_regulator = devm_regulator_get(&spi->dev, "vdd-io");
+	if (IS_ERR(trf->vddio_regulator)) {
+		ret = PTR_ERR(trf->vddio_regulator);
 		dev_err(trf->dev, "Can't get VDD_IO regulator: %d\n", ret);
-		goto err_destroy_lock;
+		goto err_disable_vin_regulator;
 	}
 
-	ret = regulator_enable(trf->regulator);
+	ret = regulator_enable(trf->vddio_regulator);
 	if (ret) {
 		dev_err(trf->dev, "Can't enable VDD_IO: %d\n", ret);
-		goto err_destroy_lock;
+		goto err_disable_vin_regulator;
 	}
 
-	if (regulator_get_voltage(trf->regulator) == 1800000) {
+	if (regulator_get_voltage(trf->vddio_regulator) == 1800000) {
 		trf->io_ctrl = TRF7970A_REG_IO_CTRL_IO_LOW;
 		dev_dbg(trf->dev, "trf7970a config vdd_io to 1.8V\n");
 	}
@@ -2108,7 +2109,7 @@
 	if (!trf->ddev) {
 		dev_err(trf->dev, "Can't allocate NFC digital device\n");
 		ret = -ENOMEM;
-		goto err_disable_regulator;
+		goto err_disable_vddio_regulator;
 	}
 
 	nfc_digital_set_parent_dev(trf->ddev, trf->dev);
@@ -2137,8 +2138,10 @@
 	trf7970a_shutdown(trf);
 err_free_ddev:
 	nfc_digital_free_device(trf->ddev);
-err_disable_regulator:
-	regulator_disable(trf->regulator);
+err_disable_vddio_regulator:
+	regulator_disable(trf->vddio_regulator);
+err_disable_vin_regulator:
+	regulator_disable(trf->vin_regulator);
 err_destroy_lock:
 	mutex_destroy(&trf->lock);
 	return ret;
@@ -2157,7 +2160,8 @@
 	nfc_digital_unregister_device(trf->ddev);
 	nfc_digital_free_device(trf->ddev);
 
-	regulator_disable(trf->regulator);
+	regulator_disable(trf->vddio_regulator);
+	regulator_disable(trf->vin_regulator);
 
 	mutex_destroy(&trf->lock);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ntb/core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ntb/core.c
@@ -214,10 +214,8 @@
 	case NTB_TOPO_B2B_DSD:
 		return NTB_PORT_SEC_DSD;
 	default:
-		break;
+		return 0;
 	}
-
-	return -EINVAL;
 }
 EXPORT_SYMBOL(ntb_default_port_number);
 
@@ -240,10 +238,8 @@
 	case NTB_TOPO_B2B_DSD:
 		return NTB_PORT_PRI_USD;
 	default:
-		break;
+		return 0;
 	}
-
-	return -EINVAL;
 }
 EXPORT_SYMBOL(ntb_default_peer_port_number);
 
@@ -315,4 +311,3 @@
 	bus_unregister(&ntb_bus);
 }
 module_exit(ntb_driver_exit);
-
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ntb/hw/amd/ntb_hw_amd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ntb/hw/amd/ntb_hw_amd.c
@@ -1036,6 +1036,7 @@
 
 err_dma_mask:
 	pci_clear_master(pdev);
+	pci_release_regions(pdev);
 err_pci_regions:
 	pci_disable_device(pdev);
 err_pci_enable:
@@ -1152,12 +1153,17 @@
 
 static int __init amd_ntb_pci_driver_init(void)
 {
+	int ret;
 	pr_info("%s %s\n", NTB_DESC, NTB_VER);
 
 	if (debugfs_initialized())
 		debugfs_dir = debugfs_create_dir(KBUILD_MODNAME, NULL);
 
-	return pci_register_driver(&amd_ntb_pci_driver);
+	ret = pci_register_driver(&amd_ntb_pci_driver);
+	if (ret)
+		debugfs_remove_recursive(debugfs_dir);
+
+	return ret;
 }
 module_init(amd_ntb_pci_driver_init);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ntb/hw/idt/ntb_hw_idt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ntb/hw/idt/ntb_hw_idt.c
@@ -2908,6 +2908,7 @@
 
 static int __init idt_pci_driver_init(void)
 {
+	int ret;
 	pr_info("%s %s\n", NTB_DESC, NTB_VER);
 
 	/* Create the top DebugFS directory if the FS is initialized */
@@ -2915,7 +2916,11 @@
 		dbgfs_topdir = debugfs_create_dir(KBUILD_MODNAME, NULL);
 
 	/* Register the NTB hardware driver to handle the PCI device */
-	return pci_register_driver(&idt_pci_driver);
+	ret = pci_register_driver(&idt_pci_driver);
+	if (ret)
+		debugfs_remove_recursive(dbgfs_topdir);
+
+	return ret;
 }
 module_init(idt_pci_driver_init);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ntb/hw/intel/ntb_hw_gen1.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ntb/hw/intel/ntb_hw_gen1.c
@@ -775,7 +775,7 @@
 		ndev->debugfs_dir =
 			debugfs_create_dir(pci_name(ndev->ntb.pdev),
 					   debugfs_dir);
-		if (!ndev->debugfs_dir)
+		if (IS_ERR(ndev->debugfs_dir))
 			ndev->debugfs_info = NULL;
 		else
 			ndev->debugfs_info =
@@ -2065,12 +2065,17 @@
 
 static int __init intel_ntb_pci_driver_init(void)
 {
+	int ret;
 	pr_info("%s %s\n", NTB_DESC, NTB_VER);
 
 	if (debugfs_initialized())
 		debugfs_dir = debugfs_create_dir(KBUILD_MODNAME, NULL);
 
-	return pci_register_driver(&intel_ntb_pci_driver);
+	ret = pci_register_driver(&intel_ntb_pci_driver);
+	if (ret)
+		debugfs_remove_recursive(debugfs_dir);
+
+	return ret;
 }
 module_init(intel_ntb_pci_driver_init);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ntb/hw/intel/ntb_hw_gen3.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ntb/hw/intel/ntb_hw_gen3.c
@@ -215,6 +215,9 @@
 	}
 
 	ndev->db_valid_mask = BIT_ULL(ndev->db_count) - 1;
+	/* Make sure we are not using DB's used for link status */
+	if (ndev->hwerr_flags & NTB_HWERR_MSIX_VECTOR32_BAD)
+		ndev->db_valid_mask &= ~ndev->db_link_mask;
 
 	ndev->reg->db_iowrite(ndev->db_valid_mask,
 			      ndev->self_mmio +
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ntb/hw/mscc/ntb_hw_switchtec.c
@@ -288,7 +288,7 @@
 	if (xlate_pos < 12)
 		return -EINVAL;
 
-	if (!IS_ALIGNED(addr, BIT_ULL(xlate_pos))) {
+	if (xlate_pos >= 0 && !IS_ALIGNED(addr, BIT_ULL(xlate_pos))) {
 		/*
 		 * In certain circumstances we can get a buffer that is
 		 * not aligned to its size. (Most of the time
@@ -1558,6 +1558,7 @@
 	switchtec_ntb_deinit_db_msg_irq(sndev);
 	switchtec_ntb_deinit_shared_mw(sndev);
 	switchtec_ntb_deinit_crosslink(sndev);
+	cancel_work_sync(&sndev->check_link_status_work);
 	kfree(sndev);
 	dev_info(dev, "ntb device unregistered\n");
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ntb/ntb_transport.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ntb/ntb_transport.c
@@ -412,7 +412,7 @@
 
 		rc = device_register(dev);
 		if (rc) {
-			kfree(client_dev);
+			put_device(dev);
 			goto err;
 		}
 
@@ -911,7 +911,7 @@
 	return 0;
 }
 
-static void ntb_qp_link_down_reset(struct ntb_transport_qp *qp)
+static void ntb_qp_link_context_reset(struct ntb_transport_qp *qp)
 {
 	qp->link_is_up = false;
 	qp->active = false;
@@ -934,6 +934,13 @@
 	qp->tx_async = 0;
 }
 
+static void ntb_qp_link_down_reset(struct ntb_transport_qp *qp)
+{
+	ntb_qp_link_context_reset(qp);
+	if (qp->remote_rx_info)
+		qp->remote_rx_info->entry = qp->rx_max_entry - 1;
+}
+
 static void ntb_qp_link_cleanup(struct ntb_transport_qp *qp)
 {
 	struct ntb_transport_ctx *nt = qp->transport;
@@ -1176,7 +1183,7 @@
 	qp->ndev = nt->ndev;
 	qp->client_ready = false;
 	qp->event_handler = NULL;
-	ntb_qp_link_down_reset(qp);
+	ntb_qp_link_context_reset(qp);
 
 	if (mw_num < qp_count % mw_count)
 		num_qps_mw = qp_count / mw_count + 1;
@@ -2278,9 +2285,13 @@
 	struct ntb_queue_entry *entry;
 	int rc;
 
-	if (!qp || !qp->link_is_up || !len)
+	if (!qp || !len)
 		return -EINVAL;
 
+	/* If the qp link is down already, just ignore. */
+	if (!qp->link_is_up)
+		return 0;
+
 	entry = ntb_list_rm(&qp->ntb_tx_free_q_lock, &qp->tx_free_q);
 	if (!entry) {
 		qp->tx_err_no_buf++;
@@ -2420,7 +2431,7 @@
 	unsigned int head = qp->tx_index;
 	unsigned int tail = qp->remote_rx_info->entry;
 
-	return tail > head ? tail - head : qp->tx_max_entry + tail - head;
+	return tail >= head ? tail - head : qp->tx_max_entry + tail - head;
 }
 EXPORT_SYMBOL_GPL(ntb_transport_tx_free_entry);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ntb/test/ntb_msi_test.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ntb/test/ntb_msi_test.c
@@ -372,8 +372,10 @@
 	if (ret)
 		goto remove_dbgfs;
 
-	if (!nm->isr_ctx)
+	if (!nm->isr_ctx) {
+		ret = -ENOMEM;
 		goto remove_dbgfs;
+	}
 
 	ntb_link_enable(ntb, NTB_SPEED_AUTO, NTB_WIDTH_AUTO);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ntb/test/ntb_perf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ntb/test/ntb_perf.c
@@ -158,6 +158,8 @@
 	/* NTB connection setup service */
 	struct work_struct	service;
 	unsigned long		sts;
+
+	struct completion init_comp;
 };
 #define to_peer_service(__work) \
 	container_of(__work, struct perf_peer, service)
@@ -546,6 +548,7 @@
 
 	/* Initialization is finally done */
 	set_bit(PERF_STS_DONE, &peer->sts);
+	complete_all(&peer->init_comp);
 
 	return 0;
 }
@@ -556,7 +559,7 @@
 		return;
 
 	(void)ntb_mw_clear_trans(peer->perf->ntb, peer->pidx, peer->gidx);
-	dma_free_coherent(&peer->perf->ntb->dev, peer->inbuf_size,
+	dma_free_coherent(&peer->perf->ntb->pdev->dev, peer->inbuf_size,
 			  peer->inbuf, peer->inbuf_xlat);
 	peer->inbuf = NULL;
 }
@@ -585,14 +588,16 @@
 
 	perf_free_inbuf(peer);
 
-	peer->inbuf = dma_alloc_coherent(&perf->ntb->dev, peer->inbuf_size,
-					 &peer->inbuf_xlat, GFP_KERNEL);
+	peer->inbuf = dma_alloc_coherent(&perf->ntb->pdev->dev,
+					 peer->inbuf_size, &peer->inbuf_xlat,
+					 GFP_KERNEL);
 	if (!peer->inbuf) {
 		dev_err(&perf->ntb->dev, "Failed to alloc inbuf of %pa\n",
 			&peer->inbuf_size);
 		return -ENOMEM;
 	}
 	if (!IS_ALIGNED(peer->inbuf_xlat, xlat_align)) {
+		ret = -EINVAL;
 		dev_err(&perf->ntb->dev, "Unaligned inbuf allocated\n");
 		goto err_free_inbuf;
 	}
@@ -636,6 +641,7 @@
 		perf_setup_outbuf(peer);
 
 	if (test_and_clear_bit(PERF_CMD_CLEAR, &peer->sts)) {
+		init_completion(&peer->init_comp);
 		clear_bit(PERF_STS_DONE, &peer->sts);
 		if (test_bit(0, &peer->perf->busy_flag) &&
 		    peer == peer->perf->test_peer) {
@@ -652,7 +658,7 @@
 {
 	u64 mask;
 
-	if (ntb_peer_mw_count(perf->ntb) < perf->pcnt + 1) {
+	if (ntb_peer_mw_count(perf->ntb) < perf->pcnt) {
 		dev_err(&perf->ntb->dev, "Not enough memory windows\n");
 		return -EINVAL;
 	}
@@ -832,10 +838,8 @@
 	dma_set_unmap(tx, unmap);
 
 	ret = dma_submit_error(dmaengine_submit(tx));
-	if (ret) {
-		dmaengine_unmap_put(unmap);
+	if (ret)
 		goto err_free_resource;
-	}
 
 	dmaengine_unmap_put(unmap);
 
@@ -1051,8 +1055,9 @@
 	struct perf_thread *pthr;
 	int tidx, ret;
 
-	if (!test_bit(PERF_STS_DONE, &peer->sts))
-		return -ENOLINK;
+	ret = wait_for_completion_interruptible(&peer->init_comp);
+	if (ret < 0)
+		return ret;
 
 	if (test_and_set_bit_lock(0, &perf->busy_flag))
 		return -EBUSY;
@@ -1418,10 +1423,21 @@
 			peer->gidx = pidx;
 		}
 		INIT_WORK(&peer->service, perf_service_work);
+		init_completion(&peer->init_comp);
 	}
 	if (perf->gidx == -1)
 		perf->gidx = pidx;
 
+	/*
+	 * Hardware with only two ports may not have unique port
+	 * numbers. In this case, the gidxs should all be zero.
+	 */
+	if (perf->pcnt == 1 &&  ntb_port_number(perf->ntb) == 0 &&
+	    ntb_peer_port_number(perf->ntb, 0) == 0) {
+		perf->gidx = 0;
+		perf->peers[0].gidx = 0;
+	}
+
 	for (pidx = 0; pidx < perf->pcnt; pidx++) {
 		ret = perf_setup_peer_mw(&perf->peers[pidx]);
 		if (ret)
@@ -1517,4 +1533,3 @@
 	destroy_workqueue(perf_wq);
 }
 module_exit(perf_exit);
-
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ntb/test/ntb_pingpong.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ntb/test/ntb_pingpong.c
@@ -121,15 +121,14 @@
 	link = ntb_link_is_up(pp->ntb, NULL, NULL);
 
 	/* Find next available peer */
-	if (link & pp->nmask) {
+	if (link & pp->nmask)
 		pidx = __ffs64(link & pp->nmask);
-		out_db = BIT_ULL(pidx + 1);
-	} else if (link & pp->pmask) {
+	else if (link & pp->pmask)
 		pidx = __ffs64(link & pp->pmask);
-		out_db = BIT_ULL(pidx);
-	} else {
+	else
 		return -ENODEV;
-	}
+
+	out_db = BIT_ULL(ntb_peer_port_number(pp->ntb, pidx));
 
 	spin_lock(&pp->lock);
 	pp->out_pidx = pidx;
@@ -303,7 +302,7 @@
 			break;
 	}
 
-	pp->in_db = BIT_ULL(pidx);
+	pp->in_db = BIT_ULL(lport);
 	pp->pmask = GENMASK_ULL(pidx, 0) >> 1;
 	pp->nmask = GENMASK_ULL(pcnt - 1, pidx);
 
@@ -435,4 +434,3 @@
 	debugfs_remove_recursive(pp_dbgfs_topdir);
 }
 module_exit(pp_exit);
-
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ntb/test/ntb_tool.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ntb/test/ntb_tool.c
@@ -367,14 +367,16 @@
 	u64 bits;
 	int n;
 
+	if (*offp)
+		return 0;
+
 	buf = kmalloc(size + 1, GFP_KERNEL);
 	if (!buf)
 		return -ENOMEM;
 
-	ret = simple_write_to_buffer(buf, size, offp, ubuf, size);
-	if (ret < 0) {
+	if (copy_from_user(buf, ubuf, size)) {
 		kfree(buf);
-		return ret;
+		return -EFAULT;
 	}
 
 	buf[size] = 0;
@@ -504,7 +506,7 @@
 	buf[1] = '\n';
 	buf[2] = '\0';
 
-	return simple_read_from_buffer(ubuf, size, offp, buf, 3);
+	return simple_read_from_buffer(ubuf, size, offp, buf, 2);
 }
 
 static TOOL_FOPS_RDWR(tool_peer_link_fops,
@@ -590,7 +592,7 @@
 	inmw->size = min_t(resource_size_t, req_size, size);
 	inmw->size = round_up(inmw->size, addr_align);
 	inmw->size = round_up(inmw->size, size_align);
-	inmw->mm_base = dma_alloc_coherent(&tc->ntb->dev, inmw->size,
+	inmw->mm_base = dma_alloc_coherent(&tc->ntb->pdev->dev, inmw->size,
 					   &inmw->dma_base, GFP_KERNEL);
 	if (!inmw->mm_base)
 		return -ENOMEM;
@@ -612,7 +614,7 @@
 	return 0;
 
 err_free_dma:
-	dma_free_coherent(&tc->ntb->dev, inmw->size, inmw->mm_base,
+	dma_free_coherent(&tc->ntb->pdev->dev, inmw->size, inmw->mm_base,
 			  inmw->dma_base);
 	inmw->mm_base = NULL;
 	inmw->dma_base = 0;
@@ -629,7 +631,7 @@
 
 	if (inmw->mm_base != NULL) {
 		ntb_mw_clear_trans(tc->ntb, pidx, widx);
-		dma_free_coherent(&tc->ntb->dev, inmw->size,
+		dma_free_coherent(&tc->ntb->pdev->dev, inmw->size,
 				  inmw->mm_base, inmw->dma_base);
 	}
 
@@ -996,6 +998,8 @@
 		tc->peers[pidx].outmws =
 			devm_kcalloc(&tc->ntb->dev, tc->peers[pidx].outmw_cnt,
 				   sizeof(*tc->peers[pidx].outmws), GFP_KERNEL);
+		if (tc->peers[pidx].outmws == NULL)
+			return -ENOMEM;
 
 		for (widx = 0; widx < tc->peers[pidx].outmw_cnt; widx++) {
 			tc->peers[pidx].outmws[widx].pidx = pidx;
@@ -1690,4 +1694,3 @@
 	debugfs_remove_recursive(tool_dbgfs_topdir);
 }
 module_exit(tool_exit);
-
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvdimm/btt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvdimm/btt.c
@@ -1261,11 +1261,11 @@
 
 		ret = btt_data_read(arena, page, off, postmap, cur_len);
 		if (ret) {
-			int rc;
-
 			/* Media error - set the e_flag */
-			rc = btt_map_write(arena, premap, postmap, 0, 1,
-				NVDIMM_IO_ATOMIC);
+			if (btt_map_write(arena, premap, postmap, 0, 1, NVDIMM_IO_ATOMIC))
+				dev_warn_ratelimited(to_dev(arena),
+					"Error persistently tracking bad blocks at %#x\n",
+					premap);
 			goto out_rtt;
 		}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvdimm/bus.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvdimm/bus.c
@@ -187,8 +187,8 @@
 	ndr_end = nd_region->ndr_start + nd_region->ndr_size - 1;
 
 	/* make sure we are in the region */
-	if (ctx->phys < nd_region->ndr_start
-			|| (ctx->phys + ctx->cleared) > ndr_end)
+	if (ctx->phys < nd_region->ndr_start ||
+	    (ctx->phys + ctx->cleared - 1) > ndr_end)
 		return 0;
 
 	sector = (ctx->phys - nd_region->ndr_start) / 512;
@@ -1010,8 +1010,10 @@
 			return -EFAULT;
 	}
 
-	if (!desc || (desc->out_num + desc->in_num == 0) ||
-			!test_bit(cmd, &cmd_mask))
+	if (!desc ||
+	    (desc->out_num + desc->in_num == 0) ||
+	    cmd > ND_CMD_CALL ||
+	    !test_bit(cmd, &cmd_mask))
 		return -ENOTTY;
 
 	/* fail write commands (when read-only) */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvdimm/dax_devs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvdimm/dax_devs.c
@@ -113,12 +113,12 @@
 
 	nvdimm_bus_lock(&ndns->dev);
 	nd_dax = nd_dax_alloc(nd_region);
-	nd_pfn = &nd_dax->nd_pfn;
-	dax_dev = nd_pfn_devinit(nd_pfn, ndns);
+	dax_dev = nd_dax_devinit(nd_dax, ndns);
 	nvdimm_bus_unlock(&ndns->dev);
 	if (!dax_dev)
 		return -ENOMEM;
 	pfn_sb = devm_kmalloc(dev, sizeof(*pfn_sb), GFP_KERNEL);
+	nd_pfn = &nd_dax->nd_pfn;
 	nd_pfn->pfn_sb = pfn_sb;
 	rc = nd_pfn_validate(nd_pfn, DAX_SIG);
 	dev_dbg(dev, "dax: %s\n", rc == 0 ? dev_name(dax_dev) : "<none>");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvdimm/dimm_devs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvdimm/dimm_devs.c
@@ -344,16 +344,16 @@
 }
 static DEVICE_ATTR_RO(state);
 
-static ssize_t available_slots_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
+static ssize_t __available_slots_show(struct nvdimm_drvdata *ndd, char *buf)
 {
-	struct nvdimm_drvdata *ndd = dev_get_drvdata(dev);
+	struct device *dev;
 	ssize_t rc;
 	u32 nfree;
 
 	if (!ndd)
 		return -ENXIO;
 
+	dev = ndd->dev;
 	nvdimm_bus_lock(dev);
 	nfree = nd_label_nfree(ndd);
 	if (nfree - 1 > nfree) {
@@ -365,6 +365,18 @@
 	nvdimm_bus_unlock(dev);
 	return rc;
 }
+
+static ssize_t available_slots_show(struct device *dev,
+				    struct device_attribute *attr, char *buf)
+{
+	ssize_t rc;
+
+	nd_device_lock(dev);
+	rc = __available_slots_show(dev_get_drvdata(dev), buf);
+	nd_device_unlock(dev);
+
+	return rc;
+}
 static DEVICE_ATTR_RO(available_slots);
 
 __weak ssize_t security_show(struct device *dev,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvdimm/label.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvdimm/label.c
@@ -980,6 +980,15 @@
 		}
 	}
 
+	/* release slots associated with any invalidated UUIDs */
+	mutex_lock(&nd_mapping->lock);
+	list_for_each_entry_safe(label_ent, e, &nd_mapping->labels, list)
+		if (test_and_clear_bit(ND_LABEL_REAP, &label_ent->flags)) {
+			reap_victim(nd_mapping, label_ent);
+			list_move(&label_ent->list, &list);
+		}
+	mutex_unlock(&nd_mapping->lock);
+
 	/*
 	 * Find the resource associated with the first label in the set
 	 * per the v1.2 namespace specification.
@@ -999,8 +1008,10 @@
 		if (is_old_resource(res, old_res_list, old_num_resources))
 			continue; /* carry-over */
 		slot = nd_label_alloc_slot(ndd);
-		if (slot == UINT_MAX)
+		if (slot == UINT_MAX) {
+			rc = -ENXIO;
 			goto abort;
+		}
 		dev_dbg(ndd->dev, "allocated: %d\n", slot);
 
 		nd_label = to_label(ndd, slot);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvdimm/namespace_devs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvdimm/namespace_devs.c
@@ -2486,7 +2486,7 @@
 
 static int init_active_labels(struct nd_region *nd_region)
 {
-	int i;
+	int i, rc = 0;
 
 	for (i = 0; i < nd_region->ndr_mappings; i++) {
 		struct nd_mapping *nd_mapping = &nd_region->mapping[i];
@@ -2505,13 +2505,14 @@
 			else if (test_bit(NDD_ALIASING, &nvdimm->flags))
 				/* fail, labels needed to disambiguate dpa */;
 			else
-				return 0;
+				continue;
 
 			dev_err(&nd_region->dev, "%s: is %s, failing probe\n",
 					dev_name(&nd_mapping->nvdimm->dev),
 					test_bit(NDD_LOCKED, &nvdimm->flags)
 					? "locked" : "disabled");
-			return -ENXIO;
+			rc = -ENXIO;
+			goto out;
 		}
 		nd_mapping->ndd = ndd;
 		atomic_inc(&nvdimm->busy);
@@ -2545,13 +2546,17 @@
 			break;
 	}
 
-	if (i < nd_region->ndr_mappings) {
+	if (i < nd_region->ndr_mappings)
+		rc = -ENOMEM;
+
+out:
+	if (rc) {
 		deactivate_labels(nd_region);
-		return -ENOMEM;
+		return rc;
 	}
 
 	return devm_add_action_or_reset(&nd_region->dev, deactivate_labels,
-			nd_region);
+					nd_region);
 }
 
 int nd_region_register_namespaces(struct nd_region *nd_region, int *err)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvdimm/nd.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvdimm/nd.h
@@ -326,6 +326,13 @@
 int nd_dax_probe(struct device *dev, struct nd_namespace_common *ndns);
 bool is_nd_dax(struct device *dev);
 struct device *nd_dax_create(struct nd_region *nd_region);
+static inline struct device *nd_dax_devinit(struct nd_dax *nd_dax,
+					    struct nd_namespace_common *ndns)
+{
+	if (!nd_dax)
+		return NULL;
+	return nd_pfn_devinit(&nd_dax->nd_pfn, ndns);
+}
 #else
 static inline int nd_dax_probe(struct device *dev,
 		struct nd_namespace_common *ndns)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvdimm/nd_virtio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvdimm/nd_virtio.c
@@ -44,6 +44,15 @@
 	unsigned long flags;
 	int err, err1;
 
+	/*
+	 * Don't bother to submit the request to the device if the device is
+	 * not activated.
+	 */
+	if (vdev->config->get_status(vdev) & VIRTIO_CONFIG_S_NEEDS_RESET) {
+		dev_info(&vdev->dev, "virtio pmem device needs a reset\n");
+		return -EIO;
+	}
+
 	might_sleep();
 	req_data = kmalloc(sizeof(*req_data), GFP_KERNEL);
 	if (!req_data)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvdimm/of_pmem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvdimm/of_pmem.c
@@ -42,7 +42,13 @@
 		return -ENOMEM;
 
 	priv->bus_desc.attr_groups = bus_attr_groups;
-	priv->bus_desc.provider_name = kstrdup(pdev->name, GFP_KERNEL);
+	priv->bus_desc.provider_name = devm_kstrdup(&pdev->dev, pdev->name,
+							GFP_KERNEL);
+	if (!priv->bus_desc.provider_name) {
+		kfree(priv);
+		return -ENOMEM;
+	}
+
 	priv->bus_desc.module = THIS_MODULE;
 	priv->bus_desc.of_node = np;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvdimm/pmem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvdimm/pmem.c
@@ -423,11 +423,11 @@
 		pmem->pfn_flags |= PFN_MAP;
 		memcpy(&bb_res, &pmem->pgmap.res, sizeof(bb_res));
 	} else {
+		addr = devm_memremap(dev, pmem->phys_addr,
+				pmem->size, ARCH_MEMREMAP_PMEM);
 		if (devm_add_action_or_reset(dev, pmem_release_queue,
 					&pmem->pgmap))
 			return -ENOMEM;
-		addr = devm_memremap(dev, pmem->phys_addr,
-				pmem->size, ARCH_MEMREMAP_PMEM);
 		memcpy(&bb_res, &nsio->res, sizeof(bb_res));
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvdimm/region_devs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvdimm/region_devs.c
@@ -898,7 +898,8 @@
 {
 	unsigned int cpu, lane;
 
-	cpu = get_cpu();
+	migrate_disable();
+	cpu = smp_processor_id();
 	if (nd_region->num_lanes < nr_cpu_ids) {
 		struct nd_percpu_lane *ndl_lock, *ndl_count;
 
@@ -917,16 +918,15 @@
 void nd_region_release_lane(struct nd_region *nd_region, unsigned int lane)
 {
 	if (nd_region->num_lanes < nr_cpu_ids) {
-		unsigned int cpu = get_cpu();
+		unsigned int cpu = smp_processor_id();
 		struct nd_percpu_lane *ndl_lock, *ndl_count;
 
 		ndl_count = per_cpu_ptr(nd_region->lane, cpu);
 		ndl_lock = per_cpu_ptr(nd_region->lane, lane);
 		if (--ndl_count->count == 0)
 			spin_unlock(&ndl_lock->lock);
-		put_cpu();
 	}
-	put_cpu();
+	migrate_enable();
 }
 EXPORT_SYMBOL(nd_region_release_lane);
 
@@ -1142,6 +1142,11 @@
 			|| !IS_ENABLED(CONFIG_ARCH_HAS_PMEM_API))
 		return -ENXIO;
 
+	/* Test if an explicit flush function is defined */
+	if (test_bit(ND_REGION_ASYNC, &nd_region->flags) && nd_region->flush)
+		return 1;
+
+	/* Test if any flush hints for the region are available */
 	for (i = 0; i < nd_region->ndr_mappings; i++) {
 		struct nd_mapping *nd_mapping = &nd_region->mapping[i];
 		struct nvdimm *nvdimm = nd_mapping->nvdimm;
@@ -1152,8 +1157,8 @@
 	}
 
 	/*
-	 * The platform defines dimm devices without hints, assume
-	 * platform persistence mechanism like ADR
+	 * The platform defines dimm devices without hints nor explicit flush,
+	 * assume platform persistence mechanism like ADR
 	 */
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvdimm/security.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvdimm/security.c
@@ -379,11 +379,6 @@
 			|| !nvdimm->sec.flags)
 		return -EOPNOTSUPP;
 
-	if (dev->driver == NULL) {
-		dev_dbg(dev, "Unable to overwrite while DIMM active.\n");
-		return -EINVAL;
-	}
-
 	rc = check_security_state(nvdimm);
 	if (rc)
 		return rc;
@@ -450,14 +445,19 @@
 	else
 		dev_dbg(&nvdimm->dev, "overwrite completed\n");
 
-	if (nvdimm->sec.overwrite_state)
-		sysfs_notify_dirent(nvdimm->sec.overwrite_state);
+	/*
+	 * Mark the overwrite work done and update dimm security flags,
+	 * then send a sysfs event notification to wake up userspace
+	 * poll threads to picked up the changed state.
+	 */
 	nvdimm->sec.overwrite_tmo = 0;
 	clear_bit(NDD_SECURITY_OVERWRITE, &nvdimm->flags);
 	clear_bit(NDD_WORK_PENDING, &nvdimm->flags);
-	put_device(&nvdimm->dev);
 	nvdimm->sec.flags = nvdimm_security_flags(nvdimm, NVDIMM_USER);
-	nvdimm->sec.flags = nvdimm_security_flags(nvdimm, NVDIMM_MASTER);
+	nvdimm->sec.ext_flags = nvdimm_security_flags(nvdimm, NVDIMM_MASTER);
+	if (nvdimm->sec.overwrite_state)
+		sysfs_notify_dirent(nvdimm->sec.overwrite_state);
+	put_device(&nvdimm->dev);
 }
 
 void nvdimm_security_overwrite_query(struct work_struct *work)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvme/host/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvme/host/Kconfig
@@ -62,8 +62,10 @@
 config NVME_TCP
 	tristate "NVM Express over Fabrics TCP host driver"
 	depends on INET
-	depends on BLK_DEV_NVME
+	depends on BLOCK
+	select NVME_CORE
 	select NVME_FABRICS
+	select CRYPTO
 	select CRYPTO_CRC32C
 	help
 	  This provides support for the NVMe over Fabrics protocol using
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvme/host/core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvme/host/core.c
@@ -6,6 +6,7 @@
 
 #include <linux/blkdev.h>
 #include <linux/blk-mq.h>
+#include <linux/compat.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/hdreg.h>
@@ -66,8 +67,8 @@
  * nvme_reset_wq - hosts nvme reset works
  * nvme_delete_wq - hosts nvme delete works
  *
- * nvme_wq will host works such are scan, aen handling, fw activation,
- * keep-alive error recovery, periodic reconnects etc. nvme_reset_wq
+ * nvme_wq will host works such as scan, aen handling, fw activation,
+ * keep-alive, periodic reconnects etc. nvme_reset_wq
  * runs reset works which also flush works hosted on nvme_wq for
  * serialization purposes. nvme_delete_wq host controller deletion
  * works which flush reset works for serialization.
@@ -287,11 +288,8 @@
 		nvme_req(req)->ctrl->comp_seen = true;
 
 	if (unlikely(status != BLK_STS_OK && nvme_req_needs_retry(req))) {
-		if ((req->cmd_flags & REQ_NVME_MPATH) &&
-		    blk_path_error(status)) {
-			nvme_failover_req(req);
+		if ((req->cmd_flags & REQ_NVME_MPATH) && nvme_failover_req(req))
 			return;
-		}
 
 		if (!blk_queue_dying(req->q)) {
 			nvme_retry_req(req);
@@ -313,12 +311,33 @@
 	if (blk_mq_request_completed(req))
 		return true;
 
-	nvme_req(req)->status = NVME_SC_HOST_PATH_ERROR;
+	nvme_req(req)->status = NVME_SC_HOST_ABORTED_CMD;
+	nvme_req(req)->flags |= NVME_REQ_CANCELLED;
 	blk_mq_complete_request(req);
 	return true;
 }
 EXPORT_SYMBOL_GPL(nvme_cancel_request);
 
+void nvme_cancel_tagset(struct nvme_ctrl *ctrl)
+{
+	if (ctrl->tagset) {
+		blk_mq_tagset_busy_iter(ctrl->tagset,
+				nvme_cancel_request, ctrl);
+		blk_mq_tagset_wait_completed_request(ctrl->tagset);
+	}
+}
+EXPORT_SYMBOL_GPL(nvme_cancel_tagset);
+
+void nvme_cancel_admin_tagset(struct nvme_ctrl *ctrl)
+{
+	if (ctrl->admin_tagset) {
+		blk_mq_tagset_busy_iter(ctrl->admin_tagset,
+				nvme_cancel_request, ctrl);
+		blk_mq_tagset_wait_completed_request(ctrl->admin_tagset);
+	}
+}
+EXPORT_SYMBOL_GPL(nvme_cancel_admin_tagset);
+
 bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl,
 		enum nvme_ctrl_state new_state)
 {
@@ -332,8 +351,6 @@
 	switch (new_state) {
 	case NVME_CTRL_LIVE:
 		switch (old_state) {
-		case NVME_CTRL_NEW:
-		case NVME_CTRL_RESETTING:
 		case NVME_CTRL_CONNECTING:
 			changed = true;
 			/* FALLTHRU */
@@ -437,7 +454,6 @@
 
 	nvme_mpath_remove_disk(head);
 	ida_simple_remove(&head->subsys->ns_ida, head->instance);
-	list_del_init(&head->entry);
 	cleanup_srcu_struct(&head->srcu);
 	nvme_put_subsystem(head->subsys);
 	kfree(head);
@@ -611,8 +627,14 @@
 	struct nvme_dsm_range *range;
 	struct bio *bio;
 
-	range = kmalloc_array(segments, sizeof(*range),
-				GFP_ATOMIC | __GFP_NOWARN);
+	/*
+	 * Some devices do not consider the DSM 'Number of Ranges' field when
+	 * determining how much data to DMA. Always allocate memory for maximum
+	 * number of segments to prevent device reading beyond end of buffer.
+	 */
+	static const size_t alloc_size = sizeof(*range) * NVME_DSM_MAX_RANGES;
+
+	range = kzalloc(alloc_size, GFP_ATOMIC | __GFP_NOWARN);
 	if (!range) {
 		/*
 		 * If we fail allocation our range, fallback to the controller
@@ -626,7 +648,7 @@
 	}
 
 	__rq_for_each_bio(bio, req) {
-		u64 slba = nvme_block_nr(ns, bio->bi_iter.bi_sector);
+		u64 slba = nvme_sect_to_lba(ns, bio->bi_iter.bi_sector);
 		u32 nlb = bio->bi_iter.bi_size >> ns->lba_shift;
 
 		if (n < segments) {
@@ -652,7 +674,7 @@
 
 	req->special_vec.bv_page = virt_to_page(range);
 	req->special_vec.bv_offset = offset_in_page(range);
-	req->special_vec.bv_len = sizeof(*range) * segments;
+	req->special_vec.bv_len = alloc_size;
 	req->rq_flags |= RQF_SPECIAL_PAYLOAD;
 
 	return BLK_STS_OK;
@@ -667,10 +689,13 @@
 	cmnd->write_zeroes.opcode = nvme_cmd_write_zeroes;
 	cmnd->write_zeroes.nsid = cpu_to_le32(ns->head->ns_id);
 	cmnd->write_zeroes.slba =
-		cpu_to_le64(nvme_block_nr(ns, blk_rq_pos(req)));
+		cpu_to_le64(nvme_sect_to_lba(ns, blk_rq_pos(req)));
 	cmnd->write_zeroes.length =
 		cpu_to_le16((blk_rq_bytes(req) >> ns->lba_shift) - 1);
-	cmnd->write_zeroes.control = 0;
+	if (nvme_ns_has_pi(ns))
+		cmnd->write_zeroes.control = cpu_to_le16(NVME_RW_PRINFO_PRACT);
+	else
+		cmnd->write_zeroes.control = 0;
 	return BLK_STS_OK;
 }
 
@@ -691,7 +716,7 @@
 
 	cmnd->rw.opcode = (rq_data_dir(req) ? nvme_cmd_write : nvme_cmd_read);
 	cmnd->rw.nsid = cpu_to_le32(ns->head->ns_id);
-	cmnd->rw.slba = cpu_to_le64(nvme_block_nr(ns, blk_rq_pos(req)));
+	cmnd->rw.slba = cpu_to_le64(nvme_sect_to_lba(ns, blk_rq_pos(req)));
 	cmnd->rw.length = cpu_to_le16((blk_rq_bytes(req) >> ns->lba_shift) - 1);
 
 	if (req_op(req) == REQ_OP_WRITE && ctrl->nr_streams)
@@ -738,6 +763,7 @@
 			clear_bit_unlock(0, &ns->ctrl->discard_page_busy);
 		else
 			kfree(page_address(page) + req->special_vec.bv_offset);
+		req->rq_flags &= ~RQF_SPECIAL_PAYLOAD;
 	}
 }
 EXPORT_SYMBOL_GPL(nvme_cleanup_cmd);
@@ -894,11 +920,16 @@
 	bool write = nvme_is_write(cmd);
 	struct nvme_ns *ns = q->queuedata;
 	struct gendisk *disk = ns ? ns->disk : NULL;
+	bool supports_metadata = disk && blk_get_integrity(disk);
+	bool has_metadata = meta_buffer && meta_len;
 	struct request *req;
 	struct bio *bio = NULL;
 	void *meta = NULL;
 	int ret;
 
+	if (has_metadata && !supports_metadata)
+		return -EINVAL;
+
 	req = nvme_alloc_request(q, cmd, 0, NVME_QID_ANY);
 	if (IS_ERR(req))
 		return PTR_ERR(req);
@@ -913,7 +944,7 @@
 			goto out;
 		bio = req->bio;
 		bio->bi_disk = disk;
-		if (disk && meta_buffer && meta_len) {
+		if (has_metadata) {
 			meta = nvme_add_user_metadata(bio, meta_buffer, meta_len,
 					meta_seed, write);
 			if (IS_ERR(meta)) {
@@ -966,7 +997,7 @@
 		startka = true;
 	spin_unlock_irqrestore(&ctrl->lock, flags);
 	if (startka)
-		schedule_delayed_work(&ctrl->ka_work, ctrl->kato * HZ);
+		queue_delayed_work(nvme_wq, &ctrl->ka_work, ctrl->kato * HZ);
 }
 
 static int nvme_keep_alive(struct nvme_ctrl *ctrl)
@@ -996,7 +1027,7 @@
 		dev_dbg(ctrl->device,
 			"reschedule traffic based keep-alive timer\n");
 		ctrl->comp_seen = false;
-		schedule_delayed_work(&ctrl->ka_work, ctrl->kato * HZ);
+		queue_delayed_work(nvme_wq, &ctrl->ka_work, ctrl->kato * HZ);
 		return;
 	}
 
@@ -1013,7 +1044,7 @@
 	if (unlikely(ctrl->kato == 0))
 		return;
 
-	schedule_delayed_work(&ctrl->ka_work, ctrl->kato * HZ);
+	queue_delayed_work(nvme_wq, &ctrl->ka_work, ctrl->kato * HZ);
 }
 
 void nvme_stop_keep_alive(struct nvme_ctrl *ctrl)
@@ -1025,6 +1056,19 @@
 }
 EXPORT_SYMBOL_GPL(nvme_stop_keep_alive);
 
+/*
+ * In NVMe 1.0 the CNS field was just a binary controller or namespace
+ * flag, thus sending any new CNS opcodes has a big chance of not working.
+ * Qemu unfortunately had that bug after reporting a 1.1 version compliance
+ * (but not for any later version).
+ */
+static bool nvme_ctrl_limited_cns(struct nvme_ctrl *ctrl)
+{
+	if (ctrl->quirks & NVME_QUIRK_IDENTIFY_CNS)
+		return ctrl->vs < NVME_VS(1, 2, 0);
+	return ctrl->vs < NVME_VS(1, 1, 0);
+}
+
 static int nvme_identify_ctrl(struct nvme_ctrl *dev, struct nvme_id_ctrl **id)
 {
 	struct nvme_command c = { };
@@ -1040,8 +1084,10 @@
 
 	error = nvme_submit_sync_cmd(dev->admin_q, &c, *id,
 			sizeof(struct nvme_id_ctrl));
-	if (error)
+	if (error) {
 		kfree(*id);
+		*id = NULL;
+	}
 	return error;
 }
 
@@ -1054,6 +1100,9 @@
 	int pos;
 	int len;
 
+	if (ctrl->quirks & NVME_QUIRK_NO_NS_DESC_LIST)
+		return 0;
+
 	c.identify.opcode = nvme_admin_identify;
 	c.identify.nsid = cpu_to_le32(nsid);
 	c.identify.cns = NVME_ID_CNS_NS_DESC_LIST;
@@ -1064,8 +1113,11 @@
 
 	status = nvme_submit_sync_cmd(ctrl->admin_q, &c, data,
 				      NVME_IDENTIFY_DATA_SIZE);
-	if (status)
+	if (status) {
+		dev_warn(ctrl->device,
+			"Identify Descriptors failed (%d)\n", status);
 		goto free_data;
+	}
 
 	for (pos = 0; pos < NVME_IDENTIFY_DATA_SIZE; pos += len) {
 		struct nvme_ns_id_desc *cur = data + pos;
@@ -1147,6 +1199,7 @@
 	if (error) {
 		dev_warn(ctrl->device, "Identify namespace failed (%d)\n", error);
 		kfree(*id);
+		*id = NULL;
 	}
 
 	return error;
@@ -1155,8 +1208,8 @@
 static int nvme_features(struct nvme_ctrl *dev, u8 op, unsigned int fid,
 		unsigned int dword11, void *buffer, size_t buflen, u32 *result)
 {
+	union nvme_result res = { 0 };
 	struct nvme_command c;
-	union nvme_result res;
 	int ret;
 
 	memset(&c, 0, sizeof(c));
@@ -1197,7 +1250,13 @@
 
 	status = nvme_set_features(ctrl, NVME_FEAT_NUM_QUEUES, q_count, NULL, 0,
 			&result);
-	if (status < 0)
+
+	/*
+	 * It's either a kernel error or the host observed a connection
+	 * lost. In either case it's not possible communicate with the
+	 * controller and thus enter the error code path.
+	 */
+	if (status < 0 || status == NVME_SC_HOST_PATH_ERROR)
 		return status;
 
 	/*
@@ -1238,6 +1297,18 @@
 	queue_work(nvme_wq, &ctrl->async_event_work);
 }
 
+/*
+ * Convert integer values from ioctl structures to user pointers, silently
+ * ignoring the upper bits in the compat case to match behaviour of 32-bit
+ * kernels.
+ */
+static void __user *nvme_to_user_ptr(uintptr_t ptrval)
+{
+	if (in_compat_syscall())
+		ptrval = (compat_uptr_t)ptrval;
+	return (void __user *)ptrval;
+}
+
 static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio)
 {
 	struct nvme_user_io io;
@@ -1260,8 +1331,21 @@
 	}
 
 	length = (io.nblocks + 1) << ns->lba_shift;
-	meta_len = (io.nblocks + 1) * ns->ms;
-	metadata = (void __user *)(uintptr_t)io.metadata;
+
+	if ((io.control & NVME_RW_PRINFO_PRACT) &&
+	    ns->ms == sizeof(struct t10_pi_tuple)) {
+		/*
+		 * Protection information is stripped/inserted by the
+		 * controller.
+		 */
+		if (nvme_to_user_ptr(io.metadata))
+			return -EINVAL;
+		meta_len = 0;
+		metadata = NULL;
+	} else {
+		meta_len = (io.nblocks + 1) * ns->ms;
+		metadata = nvme_to_user_ptr(io.metadata);
+	}
 
 	if (ns->ext) {
 		length += meta_len;
@@ -1284,7 +1368,7 @@
 	c.rw.appmask = cpu_to_le16(io.appmask);
 
 	return nvme_submit_user_cmd(ns->queue, &c,
-			(void __user *)(uintptr_t)io.addr, length,
+			nvme_to_user_ptr(io.addr), length,
 			metadata, meta_len, lower_32_bits(io.slba), NULL, 0);
 }
 
@@ -1404,9 +1488,9 @@
 
 	effects = nvme_passthru_start(ctrl, ns, cmd.opcode);
 	status = nvme_submit_user_cmd(ns ? ns->queue : ctrl->admin_q, &c,
-			(void __user *)(uintptr_t)cmd.addr, cmd.data_len,
-			(void __user *)(uintptr_t)cmd.metadata,
-			cmd.metadata_len, 0, &result, timeout);
+			nvme_to_user_ptr(cmd.addr), cmd.data_len,
+			nvme_to_user_ptr(cmd.metadata), cmd.metadata_len,
+			0, &result, timeout);
 	nvme_passthru_end(ctrl, effects);
 
 	if (status >= 0) {
@@ -1451,8 +1535,8 @@
 
 	effects = nvme_passthru_start(ctrl, ns, cmd.opcode);
 	status = nvme_submit_user_cmd(ns ? ns->queue : ctrl->admin_q, &c,
-			(void __user *)(uintptr_t)cmd.addr, cmd.data_len,
-			(void __user *)(uintptr_t)cmd.metadata, cmd.metadata_len,
+			nvme_to_user_ptr(cmd.addr), cmd.data_len,
+			nvme_to_user_ptr(cmd.metadata), cmd.metadata_len,
 			0, &cmd.result, timeout);
 	nvme_passthru_end(ctrl, effects);
 
@@ -1645,12 +1729,6 @@
 }
 #endif /* CONFIG_BLK_DEV_INTEGRITY */
 
-static void nvme_set_chunk_size(struct nvme_ns *ns)
-{
-	u32 chunk_size = (((u32)ns->noiob) << (ns->lba_shift - 9));
-	blk_queue_chunk_sectors(ns->queue, rounddown_pow_of_two(chunk_size));
-}
-
 static void nvme_config_discard(struct gendisk *disk, struct nvme_ns *ns)
 {
 	struct nvme_ctrl *ctrl = ns->ctrl;
@@ -1682,53 +1760,32 @@
 		blk_queue_max_write_zeroes_sectors(queue, UINT_MAX);
 }
 
-static void nvme_config_write_zeroes(struct gendisk *disk, struct nvme_ns *ns)
+/*
+ * Even though NVMe spec explicitly states that MDTS is not applicable to the
+ * write-zeroes, we are cautious and limit the size to the controllers
+ * max_hw_sectors value, which is based on the MDTS field and possibly other
+ * limiting factors.
+ */
+static void nvme_config_write_zeroes(struct request_queue *q,
+		struct nvme_ctrl *ctrl)
 {
-	u32 max_sectors;
-	unsigned short bs = 1 << ns->lba_shift;
-
-	if (!(ns->ctrl->oncs & NVME_CTRL_ONCS_WRITE_ZEROES) ||
-	    (ns->ctrl->quirks & NVME_QUIRK_DISABLE_WRITE_ZEROES))
-		return;
-	/*
-	 * Even though NVMe spec explicitly states that MDTS is not
-	 * applicable to the write-zeroes:- "The restriction does not apply to
-	 * commands that do not transfer data between the host and the
-	 * controller (e.g., Write Uncorrectable ro Write Zeroes command).".
-	 * In order to be more cautious use controller's max_hw_sectors value
-	 * to configure the maximum sectors for the write-zeroes which is
-	 * configured based on the controller's MDTS field in the
-	 * nvme_init_identify() if available.
-	 */
-	if (ns->ctrl->max_hw_sectors == UINT_MAX)
-		max_sectors = ((u32)(USHRT_MAX + 1) * bs) >> 9;
-	else
-		max_sectors = ((u32)(ns->ctrl->max_hw_sectors + 1) * bs) >> 9;
-
-	blk_queue_max_write_zeroes_sectors(disk->queue, max_sectors);
+	if ((ctrl->oncs & NVME_CTRL_ONCS_WRITE_ZEROES) &&
+	    !(ctrl->quirks & NVME_QUIRK_DISABLE_WRITE_ZEROES))
+		blk_queue_max_write_zeroes_sectors(q, ctrl->max_hw_sectors);
 }
 
 static int nvme_report_ns_ids(struct nvme_ctrl *ctrl, unsigned int nsid,
 		struct nvme_id_ns *id, struct nvme_ns_ids *ids)
 {
-	int ret = 0;
-
 	memset(ids, 0, sizeof(*ids));
 
 	if (ctrl->vs >= NVME_VS(1, 1, 0))
 		memcpy(ids->eui64, id->eui64, sizeof(id->eui64));
 	if (ctrl->vs >= NVME_VS(1, 2, 0))
 		memcpy(ids->nguid, id->nguid, sizeof(id->nguid));
-	if (ctrl->vs >= NVME_VS(1, 3, 0)) {
-		 /* Don't treat error as fatal we potentially
-		  * already have a NGUID or EUI-64
-		  */
-		ret = nvme_identify_ns_descs(ctrl, nsid, ids);
-		if (ret)
-			dev_warn(ctrl->device,
-				 "Identify Descriptors failed (%d)\n", ret);
-	}
-	return ret;
+	if (ctrl->vs >= NVME_VS(1, 3, 0))
+		return nvme_identify_ns_descs(ctrl, nsid, ids);
+	return 0;
 }
 
 static bool nvme_ns_ids_valid(struct nvme_ns_ids *ids)
@@ -1748,7 +1805,7 @@
 static void nvme_update_disk_info(struct gendisk *disk,
 		struct nvme_ns *ns, struct nvme_id_ns *id)
 {
-	sector_t capacity = le64_to_cpu(id->nsze) << (ns->lba_shift - 9);
+	sector_t capacity = nvme_lba_to_sect(ns, le64_to_cpu(id->nsze));
 	unsigned short bs = 1 << ns->lba_shift;
 	u32 atomic_bs, phys_bs, io_opt;
 
@@ -1801,7 +1858,7 @@
 	set_capacity(disk, capacity);
 
 	nvme_config_discard(disk, ns);
-	nvme_config_write_zeroes(disk, ns);
+	nvme_config_write_zeroes(disk->queue, ns->ctrl);
 
 	if (id->nsattr & (1 << 0))
 		set_disk_ro(disk, true);
@@ -1814,6 +1871,7 @@
 static void __nvme_revalidate_disk(struct gendisk *disk, struct nvme_id_ns *id)
 {
 	struct nvme_ns *ns = disk->private_data;
+	u32 iob;
 
 	/*
 	 * If identify namespace failed, use default 512 byte block size so
@@ -1822,7 +1880,13 @@
 	ns->lba_shift = id->lbaf[id->flbas & NVME_NS_FLBAS_LBA_MASK].ds;
 	if (ns->lba_shift == 0)
 		ns->lba_shift = 9;
-	ns->noiob = le16_to_cpu(id->noiob);
+
+	if ((ns->ctrl->quirks & NVME_QUIRK_STRIPE_SIZE) &&
+	    is_power_of_2(ns->ctrl->max_hw_sectors))
+		iob = ns->ctrl->max_hw_sectors;
+	else
+		iob = nvme_lba_to_sect(ns, le16_to_cpu(id->noiob));
+
 	ns->ms = le16_to_cpu(id->lbaf[id->flbas & NVME_NS_FLBAS_LBA_MASK].ms);
 	ns->ext = ns->ms && (id->flbas & NVME_NS_FLBAS_META_EXT);
 	/* the PI implementation requires metadata equal t10 pi tuple size */
@@ -1831,14 +1895,14 @@
 	else
 		ns->pi_type = 0;
 
-	if (ns->noiob)
-		nvme_set_chunk_size(ns);
+	if (iob)
+		blk_queue_chunk_sectors(ns->queue, rounddown_pow_of_two(iob));
 	nvme_update_disk_info(disk, ns, id);
 #ifdef CONFIG_NVME_MULTIPATH
 	if (ns->head->disk) {
 		nvme_update_disk_info(ns->head->disk, ns, id);
 		blk_queue_stack_limits(ns->head->disk->queue, ns->queue);
-		revalidate_disk(ns->head->disk);
+		nvme_mpath_update_disk_size(ns->head->disk);
 	}
 #endif
 }
@@ -1967,18 +2031,21 @@
 		enum pr_type type, bool abort)
 {
 	u32 cdw10 = nvme_pr_type(type) << 8 | (abort ? 2 : 1);
+
 	return nvme_pr_command(bdev, cdw10, old, new, nvme_cmd_resv_acquire);
 }
 
 static int nvme_pr_clear(struct block_device *bdev, u64 key)
 {
-	u32 cdw10 = 1 | (key ? 1 << 3 : 0);
-	return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_register);
+	u32 cdw10 = 1 | (key ? 0 : 1 << 3);
+
+	return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_release);
 }
 
 static int nvme_pr_release(struct block_device *bdev, u64 key, enum pr_type type)
 {
-	u32 cdw10 = nvme_pr_type(type) << 8 | (key ? 1 << 3 : 0);
+	u32 cdw10 = nvme_pr_type(type) << 8 | (key ? 0 : 1 << 3);
+
 	return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_release);
 }
 
@@ -2183,9 +2250,6 @@
 		blk_queue_max_hw_sectors(q, ctrl->max_hw_sectors);
 		blk_queue_max_segments(q, min_t(u32, max_segments, USHRT_MAX));
 	}
-	if ((ctrl->quirks & NVME_QUIRK_STRIPE_SIZE) &&
-	    is_power_of_2(ctrl->max_hw_sectors))
-		blk_queue_chunk_sectors(q, ctrl->max_hw_sectors);
 	blk_queue_virt_boundary(q, ctrl->page_size - 1);
 	if (ctrl->vwc & NVME_CTRL_VWC_PRESENT)
 		vwc = true;
@@ -2369,7 +2433,8 @@
 
 	if (ctrl->ps_max_latency_us != latency) {
 		ctrl->ps_max_latency_us = latency;
-		nvme_configure_apst(ctrl);
+		if (ctrl->state == NVME_CTRL_LIVE)
+			nvme_configure_apst(ctrl);
 	}
 }
 
@@ -2404,16 +2469,6 @@
 		.vid = 0x14a4,
 		.fr = "22301111",
 		.quirks = NVME_QUIRK_SIMPLE_SUSPEND,
-	},
-	{
-		/*
-		 * This Kingston E8FK11.T firmware version has no interrupt
-		 * after resume with actions related to suspend to idle
-		 * https://bugzilla.kernel.org/show_bug.cgi?id=204887
-		 */
-		.vid = 0x2646,
-		.fr = "E8FK11.T",
-		.quirks = NVME_QUIRK_SIMPLE_SUSPEND,
 	}
 };
 
@@ -2629,7 +2684,6 @@
 	nvme_init_subnqn(subsys, ctrl, id);
 	memcpy(subsys->serial, id->sn, sizeof(subsys->serial));
 	memcpy(subsys->model, id->mn, sizeof(subsys->model));
-	memcpy(subsys->firmware_rev, id->fr, sizeof(subsys->firmware_rev));
 	subsys->vendor_id = le16_to_cpu(id->vid);
 	subsys->cmic = id->cmic;
 	subsys->awupf = le16_to_cpu(id->awupf);
@@ -2765,10 +2819,6 @@
 	if (!ctrl->identified) {
 		int i;
 
-		ret = nvme_init_subsystem(ctrl, id);
-		if (ret)
-			goto out_free;
-
 		/*
 		 * Check for quirks.  Quirk can depend on firmware version,
 		 * so, in principle, the set of quirks present can change
@@ -2781,7 +2831,13 @@
 			if (quirk_matches(id, &core_quirks[i]))
 				ctrl->quirks |= core_quirks[i].quirks;
 		}
+
+		ret = nvme_init_subsystem(ctrl, id);
+		if (ret)
+			goto out_free;
 	}
+	memcpy(ctrl->subsys->firmware_rev, id->fr,
+	       sizeof(ctrl->subsys->firmware_rev));
 
 	if (force_apst && (ctrl->quirks & NVME_QUIRK_NO_DEEPEST_PS)) {
 		dev_warn(ctrl->device, "forcibly allowing all power states due to nvme_core.force_apst -- use at your own risk\n");
@@ -2868,7 +2924,7 @@
 		ctrl->hmmaxd = le16_to_cpu(id->hmmaxd);
 	}
 
-	ret = nvme_mpath_init(ctrl, id);
+	ret = nvme_mpath_init_identify(ctrl, id);
 	kfree(id);
 
 	if (ret < 0)
@@ -2917,10 +2973,26 @@
 		return -EWOULDBLOCK;
 	}
 
+	nvme_get_ctrl(ctrl);
+	if (!try_module_get(ctrl->ops->module)) {
+		nvme_put_ctrl(ctrl);
+		return -EINVAL;
+	}
+
 	file->private_data = ctrl;
 	return 0;
 }
 
+static int nvme_dev_release(struct inode *inode, struct file *file)
+{
+	struct nvme_ctrl *ctrl =
+		container_of(inode->i_cdev, struct nvme_ctrl, cdev);
+
+	module_put(ctrl->ops->module);
+	nvme_put_ctrl(ctrl);
+	return 0;
+}
+
 static int nvme_dev_user_cmd(struct nvme_ctrl *ctrl, void __user *argp)
 {
 	struct nvme_ns *ns;
@@ -2968,11 +3040,17 @@
 	case NVME_IOCTL_IO_CMD:
 		return nvme_dev_user_cmd(ctrl, argp);
 	case NVME_IOCTL_RESET:
+		if (!capable(CAP_SYS_ADMIN))
+			return -EACCES;
 		dev_warn(ctrl->device, "resetting controller\n");
 		return nvme_reset_ctrl_sync(ctrl);
 	case NVME_IOCTL_SUBSYS_RESET:
+		if (!capable(CAP_SYS_ADMIN))
+			return -EACCES;
 		return nvme_reset_subsystem(ctrl);
 	case NVME_IOCTL_RESCAN:
+		if (!capable(CAP_SYS_ADMIN))
+			return -EACCES;
 		nvme_queue_scan(ctrl);
 		return 0;
 	default:
@@ -2983,6 +3061,7 @@
 static const struct file_operations nvme_dev_fops = {
 	.owner		= THIS_MODULE,
 	.open		= nvme_dev_open,
+	.release	= nvme_dev_release,
 	.unlocked_ioctl	= nvme_dev_ioctl,
 	.compat_ioctl	= nvme_dev_ioctl,
 };
@@ -3181,6 +3260,10 @@
 {
 	struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
 
+	/* Can't delete non-created controllers */
+	if (!ctrl->created)
+		return -EBUSY;
+
 	if (device_remove_file_self(dev, attr))
 		nvme_delete_ctrl_sync(ctrl);
 	return count;
@@ -3306,7 +3389,6 @@
 
 	list_for_each_entry(h, &subsys->nsheads, entry) {
 		if (nvme_ns_ids_valid(&new->ids) &&
-		    !list_empty(&h->list) &&
 		    nvme_ns_ids_equal(&new->ids, &h->ids))
 			return -EINVAL;
 	}
@@ -3401,6 +3483,7 @@
 				"IDs don't match for shared namespace %d\n",
 					nsid);
 			ret = -EINVAL;
+			nvme_put_ns_head(head);
 			goto out_unlock;
 		}
 	}
@@ -3555,10 +3638,14 @@
 
 	return 0;
  out_put_disk:
+	/* prevent double queue cleanup */
+	ns->disk->queue = NULL;
 	put_disk(ns->disk);
  out_unlink_ns:
 	mutex_lock(&ctrl->subsys->lock);
 	list_del_rcu(&ns->siblings);
+	if (list_empty(&ns->head->list))
+		list_del_init(&ns->head->entry);
 	mutex_unlock(&ctrl->subsys->lock);
 	nvme_put_ns_head(ns->head);
  out_free_id:
@@ -3581,7 +3668,10 @@
 
 	mutex_lock(&ns->ctrl->subsys->lock);
 	list_del_rcu(&ns->siblings);
+	if (list_empty(&ns->head->list))
+		list_del_init(&ns->head->entry);
 	mutex_unlock(&ns->ctrl->subsys->lock);
+
 	synchronize_rcu(); /* guarantee not available in head->list */
 	nvme_mpath_clear_current_path(ns);
 	synchronize_srcu(&ns->head->srcu); /* wait for concurrent submissions */
@@ -3729,8 +3819,7 @@
 
 	mutex_lock(&ctrl->scan_lock);
 	nn = le32_to_cpu(id->nn);
-	if (ctrl->vs >= NVME_VS(1, 1, 0) &&
-	    !(ctrl->quirks & NVME_QUIRK_IDENTIFY_CNS)) {
+	if (!nvme_ctrl_limited_cns(ctrl)) {
 		if (!nvme_scan_ns_list(ctrl, nn))
 			goto out_free_id;
 	}
@@ -3830,7 +3919,14 @@
 		container_of(work, struct nvme_ctrl, async_event_work);
 
 	nvme_aen_uevent(ctrl);
-	ctrl->ops->submit_async_event(ctrl);
+
+	/*
+	 * The transport drivers must guarantee AER submission here is safe by
+	 * flushing ctrl async_event_work after changing the controller state
+	 * from LIVE and before freeing the admin queue.
+	*/
+	if (ctrl->state == NVME_CTRL_LIVE)
+		ctrl->ops->submit_async_event(ctrl);
 }
 
 static bool nvme_ctrl_pp_status(struct nvme_ctrl *ctrl)
@@ -3855,7 +3951,7 @@
 	if (!log)
 		return;
 
-	if (nvme_get_log(ctrl, NVME_NSID_ALL, 0, NVME_LOG_FW_SLOT, log,
+	if (nvme_get_log(ctrl, NVME_NSID_ALL, NVME_LOG_FW_SLOT, 0, log,
 			sizeof(*log), 0))
 		dev_warn(ctrl->device, "Get FW SLOT INFO log error\n");
 	kfree(log);
@@ -3893,11 +3989,19 @@
 	nvme_get_fw_slot_info(ctrl);
 }
 
-static void nvme_handle_aen_notice(struct nvme_ctrl *ctrl, u32 result)
+static u32 nvme_aer_type(u32 result)
 {
-	u32 aer_notice_type = (result & 0xff00) >> 8;
+	return result & 0x7;
+}
 
-	trace_nvme_async_event(ctrl, aer_notice_type);
+static u32 nvme_aer_subtype(u32 result)
+{
+	return (result & 0xff00) >> 8;
+}
+
+static void nvme_handle_aen_notice(struct nvme_ctrl *ctrl, u32 result)
+{
+	u32 aer_notice_type = nvme_aer_subtype(result);
 
 	switch (aer_notice_type) {
 	case NVME_AER_NOTICE_NS_CHANGED:
@@ -3928,24 +4032,40 @@
 	}
 }
 
+static void nvme_handle_aer_persistent_error(struct nvme_ctrl *ctrl)
+{
+	dev_warn(ctrl->device, "resetting controller due to AER\n");
+	nvme_reset_ctrl(ctrl);
+}
+
 void nvme_complete_async_event(struct nvme_ctrl *ctrl, __le16 status,
 		volatile union nvme_result *res)
 {
 	u32 result = le32_to_cpu(res->u32);
-	u32 aer_type = result & 0x07;
+	u32 aer_type = nvme_aer_type(result);
+	u32 aer_subtype = nvme_aer_subtype(result);
 
 	if (le16_to_cpu(status) >> 1 != NVME_SC_SUCCESS)
 		return;
 
+	trace_nvme_async_event(ctrl, result);
 	switch (aer_type) {
 	case NVME_AER_NOTICE:
 		nvme_handle_aen_notice(ctrl, result);
 		break;
 	case NVME_AER_ERROR:
+		/*
+		 * For a persistent internal error, don't run async_event_work
+		 * to submit a new AER. The controller reset will do it.
+		 */
+		if (aer_subtype == NVME_AER_ERROR_PERSIST_INT_ERR) {
+			nvme_handle_aer_persistent_error(ctrl);
+			return;
+		}
+		fallthrough;
 	case NVME_AER_SMART:
 	case NVME_AER_CSS:
 	case NVME_AER_VS:
-		trace_nvme_async_event(ctrl, aer_type);
 		ctrl->aen_result = result;
 		break;
 	default:
@@ -3961,6 +4081,8 @@
 	nvme_stop_keep_alive(ctrl);
 	flush_work(&ctrl->async_event_work);
 	cancel_work_sync(&ctrl->fw_act_work);
+	if (ctrl->ops->stop_ctrl)
+		ctrl->ops->stop_ctrl(ctrl);
 }
 EXPORT_SYMBOL_GPL(nvme_stop_ctrl);
 
@@ -3974,7 +4096,9 @@
 	if (ctrl->queue_count > 1) {
 		nvme_queue_scan(ctrl);
 		nvme_start_queues(ctrl);
+		nvme_mpath_update(ctrl);
 	}
+	ctrl->created = true;
 }
 EXPORT_SYMBOL_GPL(nvme_start_ctrl);
 
@@ -3992,7 +4116,7 @@
 		container_of(dev, struct nvme_ctrl, ctrl_device);
 	struct nvme_subsystem *subsys = ctrl->subsys;
 
-	if (subsys && ctrl->instance != subsys->instance)
+	if (!subsys || ctrl->instance != subsys->instance)
 		ida_simple_remove(&nvme_instance_ida, ctrl->instance);
 
 	kfree(ctrl->effects);
@@ -4065,6 +4189,7 @@
 	if (ret)
 		goto out_release_instance;
 
+	nvme_get_ctrl(ctrl);
 	cdev_init(&ctrl->cdev, &nvme_dev_fops);
 	ctrl->cdev.owner = ops->module;
 	ret = cdev_device_add(&ctrl->cdev, ctrl->device);
@@ -4080,9 +4205,11 @@
 		min(default_ps_max_latency_us, (unsigned long)S32_MAX));
 
 	nvme_fault_inject_init(&ctrl->fault_inject, dev_name(ctrl->device));
+	nvme_mpath_init_ctrl(ctrl);
 
 	return 0;
 out_free_name:
+	nvme_put_ctrl(ctrl);
 	kfree_const(ctrl->device->kobj.name);
 out_release_instance:
 	ida_simple_remove(&nvme_instance_ida, ctrl->instance);
@@ -4128,7 +4255,7 @@
 }
 EXPORT_SYMBOL_GPL(nvme_unfreeze);
 
-void nvme_wait_freeze_timeout(struct nvme_ctrl *ctrl, long timeout)
+int nvme_wait_freeze_timeout(struct nvme_ctrl *ctrl, long timeout)
 {
 	struct nvme_ns *ns;
 
@@ -4139,6 +4266,7 @@
 			break;
 	}
 	up_read(&ctrl->namespaces_rwsem);
+	return timeout;
 }
 EXPORT_SYMBOL_GPL(nvme_wait_freeze_timeout);
 
@@ -4186,8 +4314,7 @@
 }
 EXPORT_SYMBOL_GPL(nvme_start_queues);
 
-
-void nvme_sync_queues(struct nvme_ctrl *ctrl)
+void nvme_sync_io_queues(struct nvme_ctrl *ctrl)
 {
 	struct nvme_ns *ns;
 
@@ -4195,7 +4322,12 @@
 	list_for_each_entry(ns, &ctrl->namespaces, list)
 		blk_sync_queue(ns->queue);
 	up_read(&ctrl->namespaces_rwsem);
+}
+EXPORT_SYMBOL_GPL(nvme_sync_io_queues);
 
+void nvme_sync_queues(struct nvme_ctrl *ctrl)
+{
+	nvme_sync_io_queues(ctrl);
 	if (ctrl->admin_q)
 		blk_sync_queue(ctrl->admin_q);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvme/host/fabrics.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvme/host/fabrics.c
@@ -336,6 +336,11 @@
 			cmd->connect.recfmt);
 		break;
 
+	case NVME_SC_HOST_PATH_ERROR:
+		dev_err(ctrl->device,
+			"Connect command failed: host path error\n");
+		break;
+
 	default:
 		dev_err(ctrl->device,
 			"Connect command failed, error wo/DNR bit: %d\n",
@@ -565,10 +570,14 @@
 	struct nvme_request *req = nvme_req(rq);
 
 	/*
-	 * If we are in some state of setup or teardown only allow
-	 * internally generated commands.
+	 * currently we have a problem sending passthru commands
+	 * on the admin_q if the controller is not LIVE because we can't
+	 * make sure that they are going out after the admin connect,
+	 * controller enable and/or other commands in the initialization
+	 * sequence. until the controller will be LIVE, fail with
+	 * BLK_STS_RESOURCE so that they will be rescheduled.
 	 */
-	if (!blk_rq_is_passthrough(rq) || (req->flags & NVME_REQ_USERCMD))
+	if (rq->q == ctrl->admin_q && (req->flags & NVME_REQ_USERCMD))
 		return false;
 
 	/*
@@ -576,9 +585,8 @@
 	 * which is require to set the queue live in the appropinquate states.
 	 */
 	switch (ctrl->state) {
-	case NVME_CTRL_NEW:
 	case NVME_CTRL_CONNECTING:
-		if (nvme_is_fabrics(req->cmd) &&
+		if (blk_rq_is_passthrough(rq) && nvme_is_fabrics(req->cmd) &&
 		    req->cmd->fabrics.fctype == nvme_fabrics_type_connect)
 			return true;
 		break;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvme/host/fc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvme/host/fc.c
@@ -1224,7 +1224,7 @@
 	lsreq->rqstlen = sizeof(*assoc_rqst);
 	lsreq->rspaddr = assoc_acc;
 	lsreq->rsplen = sizeof(*assoc_acc);
-	lsreq->timeout = NVME_FC_CONNECT_TIMEOUT_SEC;
+	lsreq->timeout = NVME_FC_LS_TIMEOUT_SEC;
 
 	ret = nvme_fc_send_ls_req(ctrl->rport, lsop);
 	if (ret)
@@ -1264,7 +1264,7 @@
 	if (fcret) {
 		ret = -EBADF;
 		dev_err(ctrl->dev,
-			"q %d connect failed: %s\n",
+			"q %d Create Association LS failed: %s\n",
 			queue->qnum, validation_errors[fcret]);
 	} else {
 		ctrl->association_id =
@@ -1332,7 +1332,7 @@
 	lsreq->rqstlen = sizeof(*conn_rqst);
 	lsreq->rspaddr = conn_acc;
 	lsreq->rsplen = sizeof(*conn_acc);
-	lsreq->timeout = NVME_FC_CONNECT_TIMEOUT_SEC;
+	lsreq->timeout = NVME_FC_LS_TIMEOUT_SEC;
 
 	ret = nvme_fc_send_ls_req(ctrl->rport, lsop);
 	if (ret)
@@ -1363,7 +1363,7 @@
 	if (fcret) {
 		ret = -EBADF;
 		dev_err(ctrl->dev,
-			"q %d connect failed: %s\n",
+			"q %d Create I/O Connection LS failed: %s\n",
 			queue->qnum, validation_errors[fcret]);
 	} else {
 		queue->connection_id =
@@ -1376,7 +1376,7 @@
 out_no_memory:
 	if (ret)
 		dev_err(ctrl->dev,
-			"queue %d connect command failed (%d).\n",
+			"queue %d connect I/O queue failed (%d).\n",
 			queue->qnum, ret);
 	return ret;
 }
@@ -1413,8 +1413,8 @@
 static void
 nvme_fc_xmt_disconnect_assoc(struct nvme_fc_ctrl *ctrl)
 {
-	struct fcnvme_ls_disconnect_rqst *discon_rqst;
-	struct fcnvme_ls_disconnect_acc *discon_acc;
+	struct fcnvme_ls_disconnect_assoc_rqst *discon_rqst;
+	struct fcnvme_ls_disconnect_assoc_acc *discon_acc;
 	struct nvmefc_ls_req_op *lsop;
 	struct nvmefc_ls_req *lsreq;
 	int ret;
@@ -1430,11 +1430,11 @@
 	lsreq = &lsop->ls_req;
 
 	lsreq->private = (void *)&lsop[1];
-	discon_rqst = (struct fcnvme_ls_disconnect_rqst *)
+	discon_rqst = (struct fcnvme_ls_disconnect_assoc_rqst *)
 			(lsreq->private + ctrl->lport->ops->lsrqst_priv_sz);
-	discon_acc = (struct fcnvme_ls_disconnect_acc *)&discon_rqst[1];
+	discon_acc = (struct fcnvme_ls_disconnect_assoc_acc *)&discon_rqst[1];
 
-	discon_rqst->w0.ls_cmd = FCNVME_LS_DISCONNECT;
+	discon_rqst->w0.ls_cmd = FCNVME_LS_DISCONNECT_ASSOC;
 	discon_rqst->desc_list_len = cpu_to_be32(
 				sizeof(struct fcnvme_lsdesc_assoc_id) +
 				sizeof(struct fcnvme_lsdesc_disconn_cmd));
@@ -1451,22 +1451,17 @@
 	discon_rqst->discon_cmd.desc_len =
 			fcnvme_lsdesc_len(
 				sizeof(struct fcnvme_lsdesc_disconn_cmd));
-	discon_rqst->discon_cmd.scope = FCNVME_DISCONN_ASSOCIATION;
-	discon_rqst->discon_cmd.id = cpu_to_be64(ctrl->association_id);
 
 	lsreq->rqstaddr = discon_rqst;
 	lsreq->rqstlen = sizeof(*discon_rqst);
 	lsreq->rspaddr = discon_acc;
 	lsreq->rsplen = sizeof(*discon_acc);
-	lsreq->timeout = NVME_FC_CONNECT_TIMEOUT_SEC;
+	lsreq->timeout = NVME_FC_LS_TIMEOUT_SEC;
 
 	ret = nvme_fc_send_ls_req_async(ctrl->rport, lsop,
 				nvme_fc_disconnect_assoc_done);
 	if (ret)
 		kfree(lsop);
-
-	/* only meaningful part to terminating the association */
-	ctrl->association_id = 0;
 }
 
 
@@ -1608,7 +1603,7 @@
 				sizeof(op->rsp_iu), DMA_FROM_DEVICE);
 
 	if (opstate == FCPOP_STATE_ABORTED)
-		status = cpu_to_le16(NVME_SC_HOST_PATH_ERROR << 1);
+		status = cpu_to_le16(NVME_SC_HOST_ABORTED_CMD << 1);
 	else if (freq->status) {
 		status = cpu_to_le16(NVME_SC_HOST_PATH_ERROR << 1);
 		dev_info(ctrl->ctrl.device,
@@ -1662,7 +1657,7 @@
 					(freq->rcv_rsplen / 4) ||
 			     be32_to_cpu(op->rsp_iu.xfrd_len) !=
 					freq->transferred_length ||
-			     op->rsp_iu.status_code ||
+			     op->rsp_iu.ersp_result ||
 			     sqe->common.command_id != cqe->command_id)) {
 			status = cpu_to_le16(NVME_SC_HOST_PATH_ERROR << 1);
 			dev_info(ctrl->ctrl.device,
@@ -1672,7 +1667,7 @@
 				ctrl->cnum, be16_to_cpu(op->rsp_iu.iu_len),
 				be32_to_cpu(op->rsp_iu.xfrd_len),
 				freq->transferred_length,
-				op->rsp_iu.status_code,
+				op->rsp_iu.ersp_result,
 				sqe->common.command_id,
 				cqe->command_id);
 			goto done;
@@ -1731,16 +1726,21 @@
 	op->rq = rq;
 	op->rqno = rqno;
 
-	cmdiu->scsi_id = NVME_CMD_SCSI_ID;
+	cmdiu->format_id = NVME_CMD_FORMAT_ID;
 	cmdiu->fc_id = NVME_CMD_FC_ID;
 	cmdiu->iu_len = cpu_to_be16(sizeof(*cmdiu) / sizeof(u32));
+	if (queue->qnum)
+		cmdiu->rsv_cat = fccmnd_set_cat_css(0,
+					(NVME_CC_CSS_NVM >> NVME_CC_CSS_SHIFT));
+	else
+		cmdiu->rsv_cat = fccmnd_set_cat_admin(0);
 
 	op->fcp_req.cmddma = fc_dma_map_single(ctrl->lport->dev,
 				&op->cmd_iu, sizeof(op->cmd_iu), DMA_TO_DEVICE);
 	if (fc_dma_mapping_error(ctrl->lport->dev, op->fcp_req.cmddma)) {
 		dev_err(ctrl->dev,
 			"FCP Op failed - cmdiu dma mapping failed.\n");
-		ret = EFAULT;
+		ret = -EFAULT;
 		goto out_on_error;
 	}
 
@@ -1750,7 +1750,7 @@
 	if (fc_dma_mapping_error(ctrl->lport->dev, op->fcp_req.rspdma)) {
 		dev_err(ctrl->dev,
 			"FCP Op failed - rspiu dma mapping failed.\n");
-		ret = EFAULT;
+		ret = -EFAULT;
 	}
 
 	atomic_set(&op->state, FCPOP_STATE_IDLE);
@@ -1820,6 +1820,7 @@
 	struct nvme_fc_fcp_op *aen_op;
 	int i;
 
+	cancel_work_sync(&ctrl->ctrl.async_event_work);
 	aen_op = ctrl->aen_ops;
 	for (i = 0; i < NVME_NR_AEN_COMMANDS; i++, aen_op++) {
 		if (!aen_op->fcp_req.private)
@@ -2695,7 +2696,7 @@
 		/* warn if maxcmd is lower than queue_size */
 		dev_warn(ctrl->ctrl.device,
 			"queue_size %zu > ctrl maxcmd %u, reducing "
-			"to queue_size\n",
+			"to maxcmd\n",
 			opts->queue_size, ctrl->ctrl.maxcmd);
 		opts->queue_size = ctrl->ctrl.maxcmd;
 	}
@@ -2703,7 +2704,8 @@
 	if (opts->queue_size > ctrl->ctrl.sqsize + 1) {
 		/* warn if sqsize is lower than queue_size */
 		dev_warn(ctrl->ctrl.device,
-			"queue_size %zu > ctrl sqsize %u, clamping down\n",
+			"queue_size %zu > ctrl sqsize %u, reducing "
+			"to sqsize\n",
 			opts->queue_size, ctrl->ctrl.sqsize + 1);
 		opts->queue_size = ctrl->ctrl.sqsize + 1;
 	}
@@ -2739,6 +2741,7 @@
 out_disconnect_admin_queue:
 	/* send a Disconnect(association) LS to fc-nvme target */
 	nvme_fc_xmt_disconnect_assoc(ctrl);
+	ctrl->association_id = 0;
 out_delete_hw_queue:
 	__nvme_fc_delete_hw_queue(ctrl, &ctrl->queues[0], 0);
 out_free_queue:
@@ -2830,6 +2833,8 @@
 	if (ctrl->association_id)
 		nvme_fc_xmt_disconnect_assoc(ctrl);
 
+	ctrl->association_id = 0;
+
 	if (ctrl->ctrl.tagset) {
 		nvme_fc_delete_hw_io_queues(ctrl);
 		nvme_fc_free_io_queues(ctrl);
@@ -2907,10 +2912,22 @@
 static void
 __nvme_fc_terminate_io(struct nvme_fc_ctrl *ctrl)
 {
-	nvme_stop_keep_alive(&ctrl->ctrl);
+	/*
+	 * if state is connecting - the error occurred as part of a
+	 * reconnect attempt. The create_association error paths will
+	 * clean up any outstanding io.
+	 *
+	 * if it's a different state - ensure all pending io is
+	 * terminated. Given this can delay while waiting for the
+	 * aborted io to return, we recheck adapter state below
+	 * before changing state.
+	 */
+	if (ctrl->ctrl.state != NVME_CTRL_CONNECTING) {
+		nvme_stop_keep_alive(&ctrl->ctrl);
 
-	/* will block will waiting for io to terminate */
-	nvme_fc_delete_association(ctrl);
+		/* will block will waiting for io to terminate */
+		nvme_fc_delete_association(ctrl);
+	}
 
 	if (ctrl->ctrl.state != NVME_CTRL_CONNECTING &&
 	    !nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING))
@@ -3151,17 +3168,13 @@
 	list_add_tail(&ctrl->ctrl_list, &rport->ctrl_list);
 	spin_unlock_irqrestore(&rport->lock, flags);
 
-	if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_RESETTING) ||
-	    !nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING)) {
+	if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING)) {
 		dev_err(ctrl->ctrl.device,
 			"NVME-FC{%d}: failed to init ctrl state\n", ctrl->cnum);
 		goto fail_ctrl;
 	}
 
-	nvme_get_ctrl(&ctrl->ctrl);
-
 	if (!queue_delayed_work(nvme_wq, &ctrl->connect_work, 0)) {
-		nvme_put_ctrl(&ctrl->ctrl);
 		dev_err(ctrl->ctrl.device,
 			"NVME-FC{%d}: failed to schedule initial connect\n",
 			ctrl->cnum);
@@ -3186,6 +3199,7 @@
 
 	/* initiate nvme ctrl ref counting teardown */
 	nvme_uninit_ctrl(&ctrl->ctrl);
+	nvme_put_ctrl(&ctrl->ctrl);
 
 	/* Remove core ctrl ref. */
 	nvme_put_ctrl(&ctrl->ctrl);
@@ -3308,12 +3322,14 @@
 	spin_lock_irqsave(&nvme_fc_lock, flags);
 	list_for_each_entry(lport, &nvme_fc_lport_list, port_list) {
 		if (lport->localport.node_name != laddr.nn ||
-		    lport->localport.port_name != laddr.pn)
+		    lport->localport.port_name != laddr.pn ||
+		    lport->localport.port_state != FC_OBJSTATE_ONLINE)
 			continue;
 
 		list_for_each_entry(rport, &lport->endp_list, endp_list) {
 			if (rport->remoteport.node_name != raddr.nn ||
-			    rport->remoteport.port_name != raddr.pn)
+			    rport->remoteport.port_name != raddr.pn ||
+			    rport->remoteport.port_state != FC_OBJSTATE_ONLINE)
 				continue;
 
 			/* if fail to get reference fall through. Will error */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvme/host/multipath.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvme/host/multipath.c
@@ -3,6 +3,7 @@
  * Copyright (c) 2017-2018 Christoph Hellwig.
  */
 
+#include <linux/backing-dev.h>
 #include <linux/moduleparam.h>
 #include <trace/events/block.h>
 #include "nvme.h"
@@ -64,17 +65,12 @@
 	}
 }
 
-void nvme_failover_req(struct request *req)
+bool nvme_failover_req(struct request *req)
 {
 	struct nvme_ns *ns = req->q->queuedata;
 	u16 status = nvme_req(req)->status;
 	unsigned long flags;
 
-	spin_lock_irqsave(&ns->head->requeue_lock, flags);
-	blk_steal_bios(&ns->head->requeue_list, req);
-	spin_unlock_irqrestore(&ns->head->requeue_lock, flags);
-	blk_mq_end_request(req, 0);
-
 	switch (status & 0x7ff) {
 	case NVME_SC_ANA_TRANSITION:
 	case NVME_SC_ANA_INACCESSIBLE:
@@ -95,6 +91,7 @@
 		}
 		break;
 	case NVME_SC_HOST_PATH_ERROR:
+	case NVME_SC_HOST_ABORTED_CMD:
 		/*
 		 * Temporary transport disruption in talking to the controller.
 		 * Try to send on a new path.
@@ -102,15 +99,17 @@
 		nvme_mpath_clear_current_path(ns);
 		break;
 	default:
-		/*
-		 * Reset the controller for any non-ANA error as we don't know
-		 * what caused the error.
-		 */
-		nvme_reset_ctrl(ns->ctrl);
-		break;
+		/* This was a non-ANA error so follow the normal error path. */
+		return false;
 	}
 
+	spin_lock_irqsave(&ns->head->requeue_lock, flags);
+	blk_steal_bios(&ns->head->requeue_list, req);
+	spin_unlock_irqrestore(&ns->head->requeue_lock, flags);
+	blk_mq_end_request(req, 0);
+
 	kblockd_schedule_work(&ns->head->requeue_work);
+	return true;
 }
 
 void nvme_kick_requeue_lists(struct nvme_ctrl *ctrl)
@@ -157,13 +156,12 @@
 {
 	struct nvme_ns *ns;
 
-	mutex_lock(&ctrl->scan_lock);
 	down_read(&ctrl->namespaces_rwsem);
-	list_for_each_entry(ns, &ctrl->namespaces, list)
-		if (nvme_mpath_clear_current_path(ns))
-			kblockd_schedule_work(&ns->head->requeue_work);
+	list_for_each_entry(ns, &ctrl->namespaces, list) {
+		nvme_mpath_clear_current_path(ns);
+		kblockd_schedule_work(&ns->head->requeue_work);
+	}
 	up_read(&ctrl->namespaces_rwsem);
-	mutex_unlock(&ctrl->scan_lock);
 }
 
 static bool nvme_path_is_disabled(struct nvme_ns *ns)
@@ -182,7 +180,8 @@
 		if (nvme_path_is_disabled(ns))
 			continue;
 
-		if (READ_ONCE(head->subsys->iopolicy) == NVME_IOPOLICY_NUMA)
+		if (ns->ctrl->numa_node != NUMA_NO_NODE &&
+		    READ_ONCE(head->subsys->iopolicy) == NVME_IOPOLICY_NUMA)
 			distance = node_distance(node, ns->ctrl->numa_node);
 		else
 			distance = LOCAL_DISTANCE;
@@ -234,7 +233,7 @@
 	}
 
 	for (ns = nvme_next_ns(head, old);
-	     ns != old;
+	     ns && ns != old;
 	     ns = nvme_next_ns(head, ns)) {
 		if (nvme_path_is_disabled(ns))
 			continue;
@@ -247,6 +246,17 @@
 			fallback = ns;
 	}
 
+	/*
+	 * The loop above skips the current path for round-robin semantics.
+	 * Fall back to the current path if either:
+	 *  - no other optimized path found and current is optimized,
+	 *  - no other usable path found and current is usable.
+	 */
+	if (!nvme_path_is_disabled(old) &&
+	    (old->ana_state == NVME_ANA_OPTIMIZED ||
+	     (!fallback && old->ana_state == NVME_ANA_NONOPTIMIZED)))
+		return old;
+
 	if (!fallback)
 		return NULL;
 	found = fallback;
@@ -267,10 +277,13 @@
 	struct nvme_ns *ns;
 
 	ns = srcu_dereference(head->current_path[node], &head->srcu);
-	if (READ_ONCE(head->subsys->iopolicy) == NVME_IOPOLICY_RR && ns)
-		ns = nvme_round_robin_path(head, node, ns);
-	if (unlikely(!ns || !nvme_path_is_optimized(ns)))
-		ns = __nvme_find_path(head, node);
+	if (unlikely(!ns))
+		return __nvme_find_path(head, node);
+
+	if (READ_ONCE(head->subsys->iopolicy) == NVME_IOPOLICY_RR)
+		return nvme_round_robin_path(head, node, ns);
+	if (unlikely(!nvme_path_is_optimized(ns)))
+		return __nvme_find_path(head, node);
 	return ns;
 }
 
@@ -317,7 +330,7 @@
 		trace_block_bio_remap(bio->bi_disk->queue, bio,
 				      disk_devt(ns->head->disk),
 				      bio->bi_iter.bi_sector);
-		ret = direct_make_request(bio);
+		ret = generic_make_request(bio);
 	} else if (nvme_available_path(head)) {
 		dev_warn_ratelimited(dev, "no usable path - requeuing I/O\n");
 
@@ -412,26 +425,26 @@
 {
 	struct nvme_ns_head *head = ns->head;
 
-	lockdep_assert_held(&ns->head->lock);
-
 	if (!head->disk)
 		return;
 
-	if (!(head->disk->flags & GENHD_FL_UP))
+	if (!test_and_set_bit(NVME_NSHEAD_DISK_LIVE, &head->flags))
 		device_add_disk(&head->subsys->dev, head->disk,
 				nvme_ns_id_attr_groups);
 
+	mutex_lock(&head->lock);
 	if (nvme_path_is_optimized(ns)) {
 		int node, srcu_idx;
 
 		srcu_idx = srcu_read_lock(&head->srcu);
-		for_each_node(node)
+		for_each_online_node(node)
 			__nvme_find_path(head, node);
 		srcu_read_unlock(&head->srcu, srcu_idx);
 	}
+	mutex_unlock(&head->lock);
 
-	synchronize_srcu(&ns->head->srcu);
-	kblockd_schedule_work(&ns->head->requeue_work);
+	synchronize_srcu(&head->srcu);
+	kblockd_schedule_work(&head->requeue_work);
 }
 
 static int nvme_parse_ana_log(struct nvme_ctrl *ctrl, void *data,
@@ -446,8 +459,14 @@
 
 	for (i = 0; i < le16_to_cpu(ctrl->ana_log_buf->ngrps); i++) {
 		struct nvme_ana_group_desc *desc = base + offset;
-		u32 nr_nsids = le32_to_cpu(desc->nnsids);
-		size_t nsid_buf_size = nr_nsids * sizeof(__le32);
+		u32 nr_nsids;
+		size_t nsid_buf_size;
+
+		if (WARN_ON_ONCE(offset > ctrl->ana_log_size - sizeof(*desc)))
+			return -EINVAL;
+
+		nr_nsids = le32_to_cpu(desc->nnsids);
+		nsid_buf_size = nr_nsids * sizeof(__le32);
 
 		if (WARN_ON_ONCE(desc->grpid == 0))
 			return -EINVAL;
@@ -467,8 +486,6 @@
 			return error;
 
 		offset += nsid_buf_size;
-		if (WARN_ON_ONCE(offset > ctrl->ana_log_size - sizeof(*desc)))
-			return -EINVAL;
 	}
 
 	return 0;
@@ -482,14 +499,21 @@
 static void nvme_update_ns_ana_state(struct nvme_ana_group_desc *desc,
 		struct nvme_ns *ns)
 {
-	mutex_lock(&ns->head->lock);
 	ns->ana_grpid = le32_to_cpu(desc->grpid);
 	ns->ana_state = desc->state;
 	clear_bit(NVME_NS_ANA_PENDING, &ns->flags);
-
-	if (nvme_state_is_live(ns->ana_state))
+	/*
+	 * nvme_mpath_set_live() will trigger I/O to the multipath path device
+	 * and in turn to this path device.  However we cannot accept this I/O
+	 * if the controller is not live.  This may deadlock if called from
+	 * nvme_mpath_init_identify() and the ctrl will never complete
+	 * initialization, preventing I/O from completing.  For this case we
+	 * will reprocess the ANA log page in nvme_mpath_update() once the
+	 * controller is ready.
+	 */
+	if (nvme_state_is_live(ns->ana_state) &&
+	    ns->ctrl->state == NVME_CTRL_LIVE)
 		nvme_mpath_set_live(ns);
-	mutex_unlock(&ns->head->lock);
 }
 
 static int nvme_update_ana_state(struct nvme_ctrl *ctrl,
@@ -509,18 +533,21 @@
 	if (!nr_nsids)
 		return 0;
 
-	down_write(&ctrl->namespaces_rwsem);
+	down_read(&ctrl->namespaces_rwsem);
 	list_for_each_entry(ns, &ctrl->namespaces, list) {
-		unsigned nsid = le32_to_cpu(desc->nsids[n]);
-
+		unsigned nsid;
+again:
+		nsid = le32_to_cpu(desc->nsids[n]);
 		if (ns->head->ns_id < nsid)
 			continue;
 		if (ns->head->ns_id == nsid)
 			nvme_update_ns_ana_state(desc, ns);
 		if (++n == nr_nsids)
 			break;
+		if (ns->head->ns_id > nsid)
+			goto again;
 	}
-	up_write(&ctrl->namespaces_rwsem);
+	up_read(&ctrl->namespaces_rwsem);
 	return 0;
 }
 
@@ -569,6 +596,18 @@
 	nvme_read_ana_log(ctrl);
 }
 
+void nvme_mpath_update(struct nvme_ctrl *ctrl)
+{
+	u32 nr_change_groups = 0;
+
+	if (!ctrl->ana_log_buf)
+		return;
+
+	mutex_lock(&ctrl->ana_lock);
+	nvme_parse_ana_log(ctrl, &nr_change_groups, nvme_update_ana_state);
+	mutex_unlock(&ctrl->ana_lock);
+}
+
 static void nvme_anatt_timeout(struct timer_list *t)
 {
 	struct nvme_ctrl *ctrl = from_timer(ctrl, t, anatt_timer);
@@ -639,31 +678,49 @@
 }
 DEVICE_ATTR_RO(ana_state);
 
-static int nvme_set_ns_ana_state(struct nvme_ctrl *ctrl,
+static int nvme_lookup_ana_group_desc(struct nvme_ctrl *ctrl,
 		struct nvme_ana_group_desc *desc, void *data)
 {
-	struct nvme_ns *ns = data;
+	struct nvme_ana_group_desc *dst = data;
 
-	if (ns->ana_grpid == le32_to_cpu(desc->grpid)) {
-		nvme_update_ns_ana_state(desc, ns);
-		return -ENXIO; /* just break out of the loop */
-	}
+	if (desc->grpid != dst->grpid)
+		return 0;
 
-	return 0;
+	*dst = *desc;
+	return -ENXIO; /* just break out of the loop */
 }
 
 void nvme_mpath_add_disk(struct nvme_ns *ns, struct nvme_id_ns *id)
 {
 	if (nvme_ctrl_use_ana(ns->ctrl)) {
+		struct nvme_ana_group_desc desc = {
+			.grpid = id->anagrpid,
+			.state = 0,
+		};
+
 		mutex_lock(&ns->ctrl->ana_lock);
 		ns->ana_grpid = le32_to_cpu(id->anagrpid);
-		nvme_parse_ana_log(ns->ctrl, ns, nvme_set_ns_ana_state);
+		nvme_parse_ana_log(ns->ctrl, &desc, nvme_lookup_ana_group_desc);
 		mutex_unlock(&ns->ctrl->ana_lock);
+		if (desc.state) {
+			/* found the group desc: update */
+			nvme_update_ns_ana_state(&desc, ns);
+		} else {
+			/* group desc not found: trigger a re-read */
+			set_bit(NVME_NS_ANA_PENDING, &ns->flags);
+			queue_work(nvme_wq, &ns->ctrl->ana_work);
+		}
 	} else {
-		mutex_lock(&ns->head->lock);
 		ns->ana_state = NVME_ANA_OPTIMIZED; 
 		nvme_mpath_set_live(ns);
-		mutex_unlock(&ns->head->lock);
+	}
+
+	if (bdi_cap_stable_pages_required(ns->queue->backing_dev_info)) {
+		struct gendisk *disk = ns->head->disk;
+
+		if (disk)
+			disk->queue->backing_dev_info->capabilities |=
+					BDI_CAP_STABLE_WRITES;
 	}
 }
 
@@ -678,12 +735,29 @@
 	kblockd_schedule_work(&head->requeue_work);
 	flush_work(&head->requeue_work);
 	blk_cleanup_queue(head->disk->queue);
+	if (!test_bit(NVME_NSHEAD_DISK_LIVE, &head->flags)) {
+		/*
+		 * if device_add_disk wasn't called, prevent
+		 * disk release to put a bogus reference on the
+		 * request queue
+		 */
+		head->disk->queue = NULL;
+	}
 	put_disk(head->disk);
 }
 
-int nvme_mpath_init(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
+void nvme_mpath_init_ctrl(struct nvme_ctrl *ctrl)
 {
-	int error;
+	mutex_init(&ctrl->ana_lock);
+	timer_setup(&ctrl->anatt_timer, nvme_anatt_timeout, 0);
+	INIT_WORK(&ctrl->ana_work, nvme_ana_work);
+}
+
+int nvme_mpath_init_identify(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
+{
+	size_t max_transfer_size = ctrl->max_hw_sectors << SECTOR_SHIFT;
+	size_t ana_log_size;
+	int error = 0;
 
 	/* check if multipath is enabled and we have the capability */
 	if (!multipath || !ctrl->subsys || !(ctrl->subsys->cmic & (1 << 3)))
@@ -694,36 +768,31 @@
 	ctrl->nanagrpid = le32_to_cpu(id->nanagrpid);
 	ctrl->anagrpmax = le32_to_cpu(id->anagrpmax);
 
-	mutex_init(&ctrl->ana_lock);
-	timer_setup(&ctrl->anatt_timer, nvme_anatt_timeout, 0);
-	ctrl->ana_log_size = sizeof(struct nvme_ana_rsp_hdr) +
-		ctrl->nanagrpid * sizeof(struct nvme_ana_group_desc);
-	ctrl->ana_log_size += ctrl->max_namespaces * sizeof(__le32);
-
-	if (ctrl->ana_log_size > ctrl->max_hw_sectors << SECTOR_SHIFT) {
+	ana_log_size = sizeof(struct nvme_ana_rsp_hdr) +
+		ctrl->nanagrpid * sizeof(struct nvme_ana_group_desc) +
+		ctrl->max_namespaces * sizeof(__le32);
+	if (ana_log_size > max_transfer_size) {
 		dev_err(ctrl->device,
-			"ANA log page size (%zd) larger than MDTS (%d).\n",
-			ctrl->ana_log_size,
-			ctrl->max_hw_sectors << SECTOR_SHIFT);
+			"ANA log page size (%zd) larger than MDTS (%zd).\n",
+			ana_log_size, max_transfer_size);
 		dev_err(ctrl->device, "disabling ANA support.\n");
-		return 0;
+		goto out_uninit;
 	}
-
-	INIT_WORK(&ctrl->ana_work, nvme_ana_work);
-	ctrl->ana_log_buf = kmalloc(ctrl->ana_log_size, GFP_KERNEL);
-	if (!ctrl->ana_log_buf) {
-		error = -ENOMEM;
-		goto out;
+	if (ana_log_size > ctrl->ana_log_size) {
+		nvme_mpath_stop(ctrl);
+		kfree(ctrl->ana_log_buf);
+		ctrl->ana_log_buf = kmalloc(ana_log_size, GFP_KERNEL);
+		if (!ctrl->ana_log_buf)
+			return -ENOMEM;
 	}
-
+	ctrl->ana_log_size = ana_log_size;
 	error = nvme_read_ana_log(ctrl);
 	if (error)
-		goto out_free_ana_log_buf;
+		goto out_uninit;
 	return 0;
-out_free_ana_log_buf:
-	kfree(ctrl->ana_log_buf);
-	ctrl->ana_log_buf = NULL;
-out:
+
+out_uninit:
+	nvme_mpath_uninit(ctrl);
 	return error;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvme/host/nvme.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvme/host/nvme.h
@@ -115,6 +115,13 @@
 	 * Prevent tag overlap between queues
 	 */
 	NVME_QUIRK_SHARED_TAGS                  = (1 << 13),
+
+	/*
+	 * The controller doesn't handle the Identify Namespace
+	 * Identification Descriptor list subcommand despite claiming
+	 * NVMe 1.3 compliance.
+	 */
+	NVME_QUIRK_NO_NS_DESC_LIST		= (1 << 15),
 };
 
 /*
@@ -246,6 +253,7 @@
 	struct nvme_command ka_cmd;
 	struct work_struct fw_act_work;
 	unsigned long events;
+	bool created;
 
 #ifdef CONFIG_NVME_MULTIPATH
 	/* asymmetric namespace access: */
@@ -284,6 +292,11 @@
 	struct nvme_fault_inject fault_inject;
 };
 
+static inline enum nvme_ctrl_state nvme_ctrl_state(struct nvme_ctrl *ctrl)
+{
+	return READ_ONCE(ctrl->state);
+}
+
 enum nvme_iopolicy {
 	NVME_IOPOLICY_NUMA,
 	NVME_IOPOLICY_RR,
@@ -345,6 +358,8 @@
 	spinlock_t		requeue_lock;
 	struct work_struct	requeue_work;
 	struct mutex		lock;
+	unsigned long		flags;
+#define NVME_NSHEAD_DISK_LIVE	0
 	struct nvme_ns __rcu	*current_path[];
 #endif
 };
@@ -374,7 +389,6 @@
 #define NVME_NS_REMOVING	0
 #define NVME_NS_DEAD     	1
 #define NVME_NS_ANA_PENDING	2
-	u16 noiob;
 
 	struct nvme_fault_inject fault_inject;
 
@@ -393,6 +407,7 @@
 	void (*free_ctrl)(struct nvme_ctrl *ctrl);
 	void (*submit_async_event)(struct nvme_ctrl *ctrl);
 	void (*delete_ctrl)(struct nvme_ctrl *ctrl);
+	void (*stop_ctrl)(struct nvme_ctrl *ctrl);
 	int (*get_address)(struct nvme_ctrl *ctrl, char *buf, int size);
 };
 
@@ -412,16 +427,39 @@
 static inline void nvme_should_fail(struct request *req) {}
 #endif
 
+bool nvme_wait_reset(struct nvme_ctrl *ctrl);
+int nvme_try_sched_reset(struct nvme_ctrl *ctrl);
+
 static inline int nvme_reset_subsystem(struct nvme_ctrl *ctrl)
 {
+	int ret;
+
 	if (!ctrl->subsystem)
 		return -ENOTTY;
-	return ctrl->ops->reg_write32(ctrl, NVME_REG_NSSR, 0x4E564D65);
+	if (!nvme_wait_reset(ctrl))
+		return -EBUSY;
+
+	ret = ctrl->ops->reg_write32(ctrl, NVME_REG_NSSR, 0x4E564D65);
+	if (ret)
+		return ret;
+
+	return nvme_try_sched_reset(ctrl);
+}
+
+/*
+ * Convert a 512B sector number to a device logical block number.
+ */
+static inline u64 nvme_sect_to_lba(struct nvme_ns *ns, sector_t sector)
+{
+	return sector >> (ns->lba_shift - SECTOR_SHIFT);
 }
 
-static inline u64 nvme_block_nr(struct nvme_ns *ns, sector_t sector)
+/*
+ * Convert a device logical block number to a 512B sector number.
+ */
+static inline sector_t nvme_lba_to_sect(struct nvme_ns *ns, u64 lba)
 {
-	return (sector >> (ns->lba_shift - 9));
+	return lba << (ns->lba_shift - SECTOR_SHIFT);
 }
 
 static inline void nvme_end_request(struct request *req, __le16 status,
@@ -433,7 +471,8 @@
 	rq->result = result;
 	/* inject error when permitted by fault injection framework */
 	nvme_should_fail(req);
-	blk_mq_complete_request(req);
+	if (likely(!blk_should_fake_timeout(req->q)))
+		blk_mq_complete_request(req);
 }
 
 static inline void nvme_get_ctrl(struct nvme_ctrl *ctrl)
@@ -448,9 +487,10 @@
 
 void nvme_complete_rq(struct request *req);
 bool nvme_cancel_request(struct request *req, void *data, bool reserved);
+void nvme_cancel_tagset(struct nvme_ctrl *ctrl);
+void nvme_cancel_admin_tagset(struct nvme_ctrl *ctrl);
 bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl,
 		enum nvme_ctrl_state new_state);
-bool nvme_wait_reset(struct nvme_ctrl *ctrl);
 int nvme_disable_ctrl(struct nvme_ctrl *ctrl);
 int nvme_enable_ctrl(struct nvme_ctrl *ctrl);
 int nvme_shutdown_ctrl(struct nvme_ctrl *ctrl);
@@ -474,9 +514,10 @@
 void nvme_start_queues(struct nvme_ctrl *ctrl);
 void nvme_kill_queues(struct nvme_ctrl *ctrl);
 void nvme_sync_queues(struct nvme_ctrl *ctrl);
+void nvme_sync_io_queues(struct nvme_ctrl *ctrl);
 void nvme_unfreeze(struct nvme_ctrl *ctrl);
 void nvme_wait_freeze(struct nvme_ctrl *ctrl);
-void nvme_wait_freeze_timeout(struct nvme_ctrl *ctrl, long timeout);
+int nvme_wait_freeze_timeout(struct nvme_ctrl *ctrl, long timeout);
 void nvme_start_freeze(struct nvme_ctrl *ctrl);
 
 #define NVME_QID_ANY -1
@@ -501,7 +542,6 @@
 void nvme_stop_keep_alive(struct nvme_ctrl *ctrl);
 int nvme_reset_ctrl(struct nvme_ctrl *ctrl);
 int nvme_reset_ctrl_sync(struct nvme_ctrl *ctrl);
-int nvme_try_sched_reset(struct nvme_ctrl *ctrl);
 int nvme_delete_ctrl(struct nvme_ctrl *ctrl);
 
 int nvme_get_log(struct nvme_ctrl *ctrl, u32 nsid, u8 log_page, u8 lsp,
@@ -521,12 +561,14 @@
 void nvme_mpath_start_freeze(struct nvme_subsystem *subsys);
 void nvme_set_disk_name(char *disk_name, struct nvme_ns *ns,
 			struct nvme_ctrl *ctrl, int *flags);
-void nvme_failover_req(struct request *req);
+bool nvme_failover_req(struct request *req);
 void nvme_kick_requeue_lists(struct nvme_ctrl *ctrl);
 int nvme_mpath_alloc_disk(struct nvme_ctrl *ctrl,struct nvme_ns_head *head);
 void nvme_mpath_add_disk(struct nvme_ns *ns, struct nvme_id_ns *id);
 void nvme_mpath_remove_disk(struct nvme_ns_head *head);
-int nvme_mpath_init(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id);
+int nvme_mpath_init_identify(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id);
+void nvme_mpath_init_ctrl(struct nvme_ctrl *ctrl);
+void nvme_mpath_update(struct nvme_ctrl *ctrl);
 void nvme_mpath_uninit(struct nvme_ctrl *ctrl);
 void nvme_mpath_stop(struct nvme_ctrl *ctrl);
 bool nvme_mpath_clear_current_path(struct nvme_ns *ns);
@@ -551,6 +593,16 @@
 					 req->bio, status);
 }
 
+static inline void nvme_mpath_update_disk_size(struct gendisk *disk)
+{
+	struct block_device *bdev = bdget_disk(disk, 0);
+
+	if (bdev) {
+		bd_set_size(bdev, get_capacity(disk) << SECTOR_SHIFT);
+		bdput(bdev);
+	}
+}
+
 extern struct device_attribute dev_attr_ana_grpid;
 extern struct device_attribute dev_attr_ana_state;
 extern struct device_attribute subsys_attr_iopolicy;
@@ -570,8 +622,9 @@
 	sprintf(disk_name, "nvme%dn%d", ctrl->instance, ns->head->instance);
 }
 
-static inline void nvme_failover_req(struct request *req)
+static inline bool nvme_failover_req(struct request *req)
 {
+	return false;
 }
 static inline void nvme_kick_requeue_lists(struct nvme_ctrl *ctrl)
 {
@@ -602,7 +655,10 @@
         blk_status_t status)
 {
 }
-static inline int nvme_mpath_init(struct nvme_ctrl *ctrl,
+static inline void nvme_mpath_init_ctrl(struct nvme_ctrl *ctrl)
+{
+}
+static inline int nvme_mpath_init_identify(struct nvme_ctrl *ctrl,
 		struct nvme_id_ctrl *id)
 {
 	if (ctrl->subsys->cmic & (1 << 3))
@@ -610,6 +666,9 @@
 "Please enable CONFIG_NVME_MULTIPATH for full support of multi-port devices.\n");
 	return 0;
 }
+static inline void nvme_mpath_update(struct nvme_ctrl *ctrl)
+{
+}
 static inline void nvme_mpath_uninit(struct nvme_ctrl *ctrl)
 {
 }
@@ -625,6 +684,9 @@
 static inline void nvme_mpath_start_freeze(struct nvme_subsystem *subsys)
 {
 }
+static inline void nvme_mpath_update_disk_size(struct gendisk *disk)
+{
+}
 #endif /* CONFIG_NVME_MULTIPATH */
 
 #ifdef CONFIG_NVM
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvme/host/pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvme/host/pci.c
@@ -68,14 +68,14 @@
 module_param_cb(io_queue_depth, &io_queue_depth_ops, &io_queue_depth, 0644);
 MODULE_PARM_DESC(io_queue_depth, "set io queue depth, should >= 2");
 
-static int write_queues;
-module_param(write_queues, int, 0644);
+static unsigned int write_queues;
+module_param(write_queues, uint, 0644);
 MODULE_PARM_DESC(write_queues,
 	"Number of queues to use for writes. If not set, reads and writes "
 	"will share a queue set.");
 
-static int poll_queues;
-module_param(poll_queues, int, 0644);
+static unsigned int poll_queues;
+module_param(poll_queues, uint, 0644);
 MODULE_PARM_DESC(poll_queues, "Number of queues to use for polled IO.");
 
 struct nvme_dev;
@@ -117,17 +117,21 @@
 	mempool_t *iod_mempool;
 
 	/* shadow doorbell buffer support: */
-	u32 *dbbuf_dbs;
+	__le32 *dbbuf_dbs;
 	dma_addr_t dbbuf_dbs_dma_addr;
-	u32 *dbbuf_eis;
+	__le32 *dbbuf_eis;
 	dma_addr_t dbbuf_eis_dma_addr;
 
 	/* host memory buffer support: */
 	u64 host_mem_size;
 	u32 nr_host_mem_descs;
+	u32 host_mem_descs_size;
 	dma_addr_t host_mem_descs_dma;
 	struct nvme_host_mem_buf_desc *host_mem_descs;
 	void **host_mem_desc_bufs;
+	unsigned int nr_allocated_queues;
+	unsigned int nr_write_queues;
+	unsigned int nr_poll_queues;
 };
 
 static int io_queue_depth_set(const char *val, const struct kernel_param *kp)
@@ -167,7 +171,6 @@
 	 /* only used for poll queues: */
 	spinlock_t cq_poll_lock ____cacheline_aligned_in_smp;
 	volatile struct nvme_completion *cqes;
-	struct blk_mq_tags **tags;
 	dma_addr_t sq_dma_addr;
 	dma_addr_t cq_dma_addr;
 	u32 __iomem *q_db;
@@ -185,10 +188,10 @@
 #define NVMEQ_SQ_CMB		1
 #define NVMEQ_DELETE_ERROR	2
 #define NVMEQ_POLLED		3
-	u32 *dbbuf_sq_db;
-	u32 *dbbuf_cq_db;
-	u32 *dbbuf_sq_ei;
-	u32 *dbbuf_cq_ei;
+	__le32 *dbbuf_sq_db;
+	__le32 *dbbuf_cq_db;
+	__le32 *dbbuf_sq_ei;
+	__le32 *dbbuf_cq_ei;
 	struct completion delete_done;
 };
 
@@ -211,25 +214,14 @@
 	struct scatterlist *sg;
 };
 
-static unsigned int max_io_queues(void)
+static inline unsigned int nvme_dbbuf_size(struct nvme_dev *dev)
 {
-	return num_possible_cpus() + write_queues + poll_queues;
-}
-
-static unsigned int max_queue_count(void)
-{
-	/* IO queues + admin queue */
-	return 1 + max_io_queues();
-}
-
-static inline unsigned int nvme_dbbuf_size(u32 stride)
-{
-	return (max_queue_count() * 8 * stride);
+	return dev->nr_allocated_queues * 8 * dev->db_stride;
 }
 
 static int nvme_dbbuf_dma_alloc(struct nvme_dev *dev)
 {
-	unsigned int mem_size = nvme_dbbuf_size(dev->db_stride);
+	unsigned int mem_size = nvme_dbbuf_size(dev);
 
 	if (dev->dbbuf_dbs)
 		return 0;
@@ -254,7 +246,7 @@
 
 static void nvme_dbbuf_dma_free(struct nvme_dev *dev)
 {
-	unsigned int mem_size = nvme_dbbuf_size(dev->db_stride);
+	unsigned int mem_size = nvme_dbbuf_size(dev);
 
 	if (dev->dbbuf_dbs) {
 		dma_free_coherent(dev->dev, mem_size,
@@ -280,9 +272,21 @@
 	nvmeq->dbbuf_cq_ei = &dev->dbbuf_eis[cq_idx(qid, dev->db_stride)];
 }
 
+static void nvme_dbbuf_free(struct nvme_queue *nvmeq)
+{
+	if (!nvmeq->qid)
+		return;
+
+	nvmeq->dbbuf_sq_db = NULL;
+	nvmeq->dbbuf_cq_db = NULL;
+	nvmeq->dbbuf_sq_ei = NULL;
+	nvmeq->dbbuf_cq_ei = NULL;
+}
+
 static void nvme_dbbuf_set(struct nvme_dev *dev)
 {
 	struct nvme_command c;
+	unsigned int i;
 
 	if (!dev->dbbuf_dbs)
 		return;
@@ -296,6 +300,9 @@
 		dev_warn(dev->ctrl.device, "unable to set dbbuf\n");
 		/* Free memory and continue on */
 		nvme_dbbuf_dma_free(dev);
+
+		for (i = 1; i <= dev->online_queues; i++)
+			nvme_dbbuf_free(&dev->queues[i]);
 	}
 }
 
@@ -305,11 +312,11 @@
 }
 
 /* Update dbbuf and return true if an MMIO is required */
-static bool nvme_dbbuf_update_and_check_event(u16 value, u32 *dbbuf_db,
-					      volatile u32 *dbbuf_ei)
+static bool nvme_dbbuf_update_and_check_event(u16 value, __le32 *dbbuf_db,
+					      volatile __le32 *dbbuf_ei)
 {
 	if (dbbuf_db) {
-		u16 old_value;
+		u16 old_value, event_idx;
 
 		/*
 		 * Ensure that the queue is written before updating
@@ -317,8 +324,8 @@
 		 */
 		wmb();
 
-		old_value = *dbbuf_db;
-		*dbbuf_db = value;
+		old_value = le32_to_cpu(*dbbuf_db);
+		*dbbuf_db = cpu_to_le32(value);
 
 		/*
 		 * Ensure that the doorbell is updated before reading the event
@@ -328,7 +335,8 @@
 		 */
 		mb();
 
-		if (!nvme_dbbuf_need_event(*dbbuf_ei, value, old_value))
+		event_idx = le32_to_cpu(*dbbuf_ei);
+		if (!nvme_dbbuf_need_event(event_idx, value, old_value))
 			return false;
 	}
 
@@ -377,29 +385,17 @@
 
 	WARN_ON(hctx_idx != 0);
 	WARN_ON(dev->admin_tagset.tags[0] != hctx->tags);
-	WARN_ON(nvmeq->tags);
 
 	hctx->driver_data = nvmeq;
-	nvmeq->tags = &dev->admin_tagset.tags[0];
 	return 0;
 }
 
-static void nvme_admin_exit_hctx(struct blk_mq_hw_ctx *hctx, unsigned int hctx_idx)
-{
-	struct nvme_queue *nvmeq = hctx->driver_data;
-
-	nvmeq->tags = NULL;
-}
-
 static int nvme_init_hctx(struct blk_mq_hw_ctx *hctx, void *data,
 			  unsigned int hctx_idx)
 {
 	struct nvme_dev *dev = data;
 	struct nvme_queue *nvmeq = &dev->queues[hctx_idx + 1];
 
-	if (!nvmeq->tags)
-		nvmeq->tags = &dev->tagset.tags[hctx_idx];
-
 	WARN_ON(dev->tagset.tags[hctx_idx] != hctx->tags);
 	hctx->driver_data = nvmeq;
 	return 0;
@@ -534,50 +530,71 @@
 	return true;
 }
 
-static void nvme_unmap_data(struct nvme_dev *dev, struct request *req)
+static void nvme_free_prps(struct nvme_dev *dev, struct request *req)
 {
-	struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
 	const int last_prp = dev->ctrl.page_size / sizeof(__le64) - 1;
-	dma_addr_t dma_addr = iod->first_dma, next_dma_addr;
+	struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
+	dma_addr_t dma_addr = iod->first_dma;
 	int i;
 
-	if (iod->dma_len) {
-		dma_unmap_page(dev->dev, dma_addr, iod->dma_len,
-			       rq_dma_dir(req));
-		return;
+	for (i = 0; i < iod->npages; i++) {
+		__le64 *prp_list = nvme_pci_iod_list(req)[i];
+		dma_addr_t next_dma_addr = le64_to_cpu(prp_list[last_prp]);
+
+		dma_pool_free(dev->prp_page_pool, prp_list, dma_addr);
+		dma_addr = next_dma_addr;
 	}
 
-	WARN_ON_ONCE(!iod->nents);
+}
 
-	if (is_pci_p2pdma_page(sg_page(iod->sg)))
-		pci_p2pdma_unmap_sg(dev->dev, iod->sg, iod->nents,
-				    rq_dma_dir(req));
-	else
-		dma_unmap_sg(dev->dev, iod->sg, iod->nents, rq_dma_dir(req));
+static void nvme_free_sgls(struct nvme_dev *dev, struct request *req)
+{
+	const int last_sg = SGES_PER_PAGE - 1;
+	struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
+	dma_addr_t dma_addr = iod->first_dma;
+	int i;
 
+	for (i = 0; i < iod->npages; i++) {
+		struct nvme_sgl_desc *sg_list = nvme_pci_iod_list(req)[i];
+		dma_addr_t next_dma_addr = le64_to_cpu((sg_list[last_sg]).addr);
 
-	if (iod->npages == 0)
-		dma_pool_free(dev->prp_small_pool, nvme_pci_iod_list(req)[0],
-			dma_addr);
+		dma_pool_free(dev->prp_page_pool, sg_list, dma_addr);
+		dma_addr = next_dma_addr;
+	}
 
-	for (i = 0; i < iod->npages; i++) {
-		void *addr = nvme_pci_iod_list(req)[i];
+}
 
-		if (iod->use_sgl) {
-			struct nvme_sgl_desc *sg_list = addr;
+static void nvme_unmap_sg(struct nvme_dev *dev, struct request *req)
+{
+	struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
 
-			next_dma_addr =
-			    le64_to_cpu((sg_list[SGES_PER_PAGE - 1]).addr);
-		} else {
-			__le64 *prp_list = addr;
+	if (is_pci_p2pdma_page(sg_page(iod->sg)))
+		pci_p2pdma_unmap_sg(dev->dev, iod->sg, iod->nents,
+				    rq_dma_dir(req));
+	else
+		dma_unmap_sg(dev->dev, iod->sg, iod->nents, rq_dma_dir(req));
+}
 
-			next_dma_addr = le64_to_cpu(prp_list[last_prp]);
-		}
+static void nvme_unmap_data(struct nvme_dev *dev, struct request *req)
+{
+	struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
 
-		dma_pool_free(dev->prp_page_pool, addr, dma_addr);
-		dma_addr = next_dma_addr;
+	if (iod->dma_len) {
+		dma_unmap_page(dev->dev, iod->first_dma, iod->dma_len,
+			       rq_dma_dir(req));
+		return;
 	}
 
+	WARN_ON_ONCE(!iod->nents);
+
+	nvme_unmap_sg(dev, req);
+	if (iod->npages == 0)
+		dma_pool_free(dev->prp_small_pool, nvme_pci_iod_list(req)[0],
+			      iod->first_dma);
+	else if (iod->use_sgl)
+		nvme_free_sgls(dev, req);
+	else
+		nvme_free_prps(dev, req);
 	mempool_free(iod->sg, dev->iod_mempool);
 }
 
@@ -654,7 +671,7 @@
 			__le64 *old_prp_list = prp_list;
 			prp_list = dma_pool_alloc(pool, GFP_ATOMIC, &prp_dma);
 			if (!prp_list)
-				return BLK_STS_RESOURCE;
+				goto free_prps;
 			list[iod->npages++] = prp_list;
 			prp_list[0] = old_prp_list[i - 1];
 			old_prp_list[i - 1] = cpu_to_le64(prp_dma);
@@ -674,14 +691,14 @@
 		dma_addr = sg_dma_address(sg);
 		dma_len = sg_dma_len(sg);
 	}
-
 done:
 	cmnd->dptr.prp1 = cpu_to_le64(sg_dma_address(iod->sg));
 	cmnd->dptr.prp2 = cpu_to_le64(iod->first_dma);
-
 	return BLK_STS_OK;
-
- bad_sgl:
+free_prps:
+	nvme_free_prps(dev, req);
+	return BLK_STS_RESOURCE;
+bad_sgl:
 	WARN(DO_ONCE(nvme_print_sgl, iod->sg, iod->nents),
 			"Invalid SGL for payload:%d nents:%d\n",
 			blk_rq_payload_bytes(req), iod->nents);
@@ -753,7 +770,7 @@
 
 			sg_list = dma_pool_alloc(pool, GFP_ATOMIC, &sgl_dma);
 			if (!sg_list)
-				return BLK_STS_RESOURCE;
+				goto free_sgls;
 
 			i = 0;
 			nvme_pci_iod_list(req)[iod->npages++] = sg_list;
@@ -766,6 +783,9 @@
 	} while (--entries > 0);
 
 	return BLK_STS_OK;
+free_sgls:
+	nvme_free_sgls(dev, req);
+	return BLK_STS_RESOURCE;
 }
 
 static blk_status_t nvme_setup_prp_simple(struct nvme_dev *dev,
@@ -820,7 +840,7 @@
 				return nvme_setup_prp_simple(dev, req,
 							     &cmnd->rw, &bv);
 
-			if (iod->nvmeq->qid &&
+			if (iod->nvmeq->qid && sgl_threshold &&
 			    dev->ctrl.sgls & ((1 << 0) | (1 << 1)))
 				return nvme_setup_sgl_simple(dev, req,
 							     &cmnd->rw, &bv);
@@ -834,7 +854,7 @@
 	sg_init_table(iod->sg, blk_rq_nr_phys_segments(req));
 	iod->nents = blk_rq_map_sg(req->q, req, iod->sg);
 	if (!iod->nents)
-		goto out;
+		goto out_free_sg;
 
 	if (is_pci_p2pdma_page(sg_page(iod->sg)))
 		nr_mapped = pci_p2pdma_map_sg_attrs(dev->dev, iod->sg,
@@ -843,16 +863,21 @@
 		nr_mapped = dma_map_sg_attrs(dev->dev, iod->sg, iod->nents,
 					     rq_dma_dir(req), DMA_ATTR_NO_WARN);
 	if (!nr_mapped)
-		goto out;
+		goto out_free_sg;
 
 	iod->use_sgl = nvme_pci_use_sgls(dev, req);
 	if (iod->use_sgl)
 		ret = nvme_pci_setup_sgls(dev, req, &cmnd->rw, nr_mapped);
 	else
 		ret = nvme_pci_setup_prps(dev, req, &cmnd->rw);
-out:
 	if (ret != BLK_STS_OK)
-		nvme_unmap_data(dev, req);
+		goto out_unmap_sg;
+	return BLK_STS_OK;
+
+out_unmap_sg:
+	nvme_unmap_sg(dev, req);
+out_free_sg:
+	mempool_free(iod->sg, dev->iod_mempool);
 	return ret;
 }
 
@@ -914,7 +939,8 @@
 	nvme_submit_cmd(nvmeq, &cmnd, bd->last);
 	return BLK_STS_OK;
 out_unmap_data:
-	nvme_unmap_data(dev, req);
+	if (blk_rq_nr_phys_segments(req))
+		nvme_unmap_data(dev, req);
 out_free_cmd:
 	nvme_cleanup_cmd(req);
 	return ret;
@@ -950,18 +976,18 @@
 		writel(head, nvmeq->q_db + nvmeq->dev->db_stride);
 }
 
+static inline struct blk_mq_tags *nvme_queue_tagset(struct nvme_queue *nvmeq)
+{
+	if (!nvmeq->qid)
+		return nvmeq->dev->admin_tagset.tags[0];
+	return nvmeq->dev->tagset.tags[nvmeq->qid - 1];
+}
+
 static inline void nvme_handle_cqe(struct nvme_queue *nvmeq, u16 idx)
 {
 	volatile struct nvme_completion *cqe = &nvmeq->cqes[idx];
 	struct request *req;
 
-	if (unlikely(cqe->command_id >= nvmeq->q_depth)) {
-		dev_warn(nvmeq->dev->ctrl.device,
-			"invalid id %d completed on queue %d\n",
-			cqe->command_id, le16_to_cpu(cqe->sq_id));
-		return;
-	}
-
 	/*
 	 * AEN requests are special as they don't time out and can
 	 * survive any kind of queue freeze and often don't respond to
@@ -975,7 +1001,14 @@
 		return;
 	}
 
-	req = blk_mq_tag_to_rq(*nvmeq->tags, cqe->command_id);
+	req = blk_mq_tag_to_rq(nvme_queue_tagset(nvmeq), cqe->command_id);
+	if (unlikely(!req)) {
+		dev_warn(nvmeq->dev->ctrl.device,
+			"invalid id %d completed on queue %d\n",
+			cqe->command_id, le16_to_cpu(cqe->sq_id));
+		return;
+	}
+
 	trace_nvme_sq(req, cqe->sq_head, nvmeq->sq_tail);
 	nvme_end_request(req, cqe->status, cqe->result);
 }
@@ -1090,9 +1123,9 @@
 
 	spin_lock(&nvmeq->cq_poll_lock);
 	found = nvme_process_cq(nvmeq, &start, &end, -1);
+	nvme_complete_cqes(nvmeq, start, end);
 	spin_unlock(&nvmeq->cq_poll_lock);
 
-	nvme_complete_cqes(nvmeq, start, end);
 	return found;
 }
 
@@ -1288,8 +1321,8 @@
 		dev_warn_ratelimited(dev->ctrl.device,
 			 "I/O %d QID %d timeout, disable controller\n",
 			 req->tag, nvmeq->qid);
-		nvme_dev_disable(dev, true);
 		nvme_req(req)->flags |= NVME_REQ_CANCELLED;
+		nvme_dev_disable(dev, true);
 		return BLK_EH_DONE;
 	case NVME_CTRL_RESETTING:
 		return BLK_EH_RESET_TIMER;
@@ -1306,10 +1339,10 @@
 		dev_warn(dev->ctrl.device,
 			 "I/O %d QID %d timeout, reset controller\n",
 			 req->tag, nvmeq->qid);
+		nvme_req(req)->flags |= NVME_REQ_CANCELLED;
 		nvme_dev_disable(dev, false);
 		nvme_reset_ctrl(&dev->ctrl);
 
-		nvme_req(req)->flags |= NVME_REQ_CANCELLED;
 		return BLK_EH_DONE;
 	}
 
@@ -1413,6 +1446,23 @@
 	nvme_poll_irqdisable(nvmeq, -1);
 }
 
+/*
+ * Called only on a device that has been disabled and after all other threads
+ * that can check this device's completion queues have synced. This is the
+ * last chance for the driver to see a natural completion before
+ * nvme_cancel_request() terminates all incomplete requests.
+ */
+static void nvme_reap_pending_cqes(struct nvme_dev *dev)
+{
+	u16 start, end;
+	int i;
+
+	for (i = dev->ctrl.queue_count - 1; i > 0; i--) {
+		nvme_process_cq(&dev->queues[i], &start, &end, -1);
+		nvme_complete_cqes(&dev->queues[i], start, end);
+	}
+}
+
 static int nvme_cmb_qdepth(struct nvme_dev *dev, int nr_io_queues,
 				int entry_size)
 {
@@ -1578,7 +1628,6 @@
 	.queue_rq	= nvme_queue_rq,
 	.complete	= nvme_pci_complete_rq,
 	.init_hctx	= nvme_admin_init_hctx,
-	.exit_hctx      = nvme_admin_exit_hctx,
 	.init_request	= nvme_init_request,
 	.timeout	= nvme_timeout,
 };
@@ -1628,6 +1677,7 @@
 		dev->ctrl.admin_q = blk_mq_init_queue(&dev->admin_tagset);
 		if (IS_ERR(dev->ctrl.admin_q)) {
 			blk_mq_free_tag_set(&dev->admin_tagset);
+			dev->ctrl.admin_q = NULL;
 			return -ENOMEM;
 		}
 		if (!blk_get_queue(dev->ctrl.admin_q)) {
@@ -1875,10 +1925,10 @@
 
 	kfree(dev->host_mem_desc_bufs);
 	dev->host_mem_desc_bufs = NULL;
-	dma_free_coherent(dev->dev,
-			dev->nr_host_mem_descs * sizeof(*dev->host_mem_descs),
+	dma_free_coherent(dev->dev, dev->host_mem_descs_size,
 			dev->host_mem_descs, dev->host_mem_descs_dma);
 	dev->host_mem_descs = NULL;
+	dev->host_mem_descs_size = 0;
 	dev->nr_host_mem_descs = 0;
 }
 
@@ -1886,7 +1936,7 @@
 		u32 chunk_size)
 {
 	struct nvme_host_mem_buf_desc *descs;
-	u32 max_entries, len;
+	u32 max_entries, len, descs_size;
 	dma_addr_t descs_dma;
 	int i = 0;
 	void **bufs;
@@ -1899,8 +1949,9 @@
 	if (dev->ctrl.hmmaxd && dev->ctrl.hmmaxd < max_entries)
 		max_entries = dev->ctrl.hmmaxd;
 
-	descs = dma_alloc_coherent(dev->dev, max_entries * sizeof(*descs),
-				   &descs_dma, GFP_KERNEL);
+	descs_size = max_entries * sizeof(*descs);
+	descs = dma_alloc_coherent(dev->dev, descs_size, &descs_dma,
+			GFP_KERNEL);
 	if (!descs)
 		goto out;
 
@@ -1929,6 +1980,7 @@
 	dev->host_mem_size = size;
 	dev->host_mem_descs = descs;
 	dev->host_mem_descs_dma = descs_dma;
+	dev->host_mem_descs_size = descs_size;
 	dev->host_mem_desc_bufs = bufs;
 	return 0;
 
@@ -1943,8 +1995,7 @@
 
 	kfree(bufs);
 out_free_descs:
-	dma_free_coherent(dev->dev, max_entries * sizeof(*descs), descs,
-			descs_dma);
+	dma_free_coherent(dev->dev, descs_size, descs, descs_dma);
 out:
 	dev->host_mem_descs = NULL;
 	return -ENOMEM;
@@ -2020,7 +2071,7 @@
 static void nvme_calc_irq_sets(struct irq_affinity *affd, unsigned int nrirqs)
 {
 	struct nvme_dev *dev = affd->priv;
-	unsigned int nr_read_queues;
+	unsigned int nr_read_queues, nr_write_queues = dev->nr_write_queues;
 
 	/*
 	 * If there is no interupt available for queues, ensure that
@@ -2036,12 +2087,12 @@
 	if (!nrirqs) {
 		nrirqs = 1;
 		nr_read_queues = 0;
-	} else if (nrirqs == 1 || !write_queues) {
+	} else if (nrirqs == 1 || !nr_write_queues) {
 		nr_read_queues = 0;
-	} else if (write_queues >= nrirqs) {
+	} else if (nr_write_queues >= nrirqs) {
 		nr_read_queues = 1;
 	} else {
-		nr_read_queues = nrirqs - write_queues;
+		nr_read_queues = nrirqs - nr_write_queues;
 	}
 
 	dev->io_queues[HCTX_TYPE_DEFAULT] = nrirqs - nr_read_queues;
@@ -2060,21 +2111,17 @@
 		.priv		= dev,
 	};
 	unsigned int irq_queues, this_p_queues;
-	unsigned int nr_cpus = num_possible_cpus();
 
 	/*
 	 * Poll queues don't need interrupts, but we need at least one IO
 	 * queue left over for non-polled IO.
 	 */
-	this_p_queues = poll_queues;
+	this_p_queues = dev->nr_poll_queues;
 	if (this_p_queues >= nr_io_queues) {
 		this_p_queues = nr_io_queues - 1;
 		irq_queues = 1;
 	} else {
-		if (nr_cpus < nr_io_queues - this_p_queues)
-			irq_queues = nr_cpus + 1;
-		else
-			irq_queues = nr_io_queues - this_p_queues + 1;
+		irq_queues = nr_io_queues - this_p_queues + 1;
 	}
 	dev->io_queues[HCTX_TYPE_POLL] = this_p_queues;
 
@@ -2099,14 +2146,25 @@
 		__nvme_disable_io_queues(dev, nvme_admin_delete_cq);
 }
 
+static unsigned int nvme_max_io_queues(struct nvme_dev *dev)
+{
+	return num_possible_cpus() + dev->nr_write_queues + dev->nr_poll_queues;
+}
+
 static int nvme_setup_io_queues(struct nvme_dev *dev)
 {
 	struct nvme_queue *adminq = &dev->queues[0];
 	struct pci_dev *pdev = to_pci_dev(dev->dev);
-	int result, nr_io_queues;
+	unsigned int nr_io_queues;
 	unsigned long size;
+	int result;
 
-	nr_io_queues = max_io_queues();
+	/*
+	 * Sample the module parameters once at reset time so that we have
+	 * stable values to work with.
+	 */
+	dev->nr_write_queues = write_queues;
+	dev->nr_poll_queues = poll_queues;
 
 	/*
 	 * If tags are shared with admin queue (Apple bug), then
@@ -2114,6 +2172,9 @@
 	 */
 	if (dev->ctrl.quirks & NVME_QUIRK_SHARED_TAGS)
 		nr_io_queues = 1;
+	else
+		nr_io_queues = min(nvme_max_io_queues(dev),
+				   dev->nr_allocated_queues - 1);
 
 	result = nvme_set_queue_count(&dev->ctrl, &nr_io_queues);
 	if (result < 0)
@@ -2252,11 +2313,6 @@
 		if (timeout == 0)
 			return false;
 
-		/* handle any remaining CQEs */
-		if (opcode == nvme_admin_delete_cq &&
-		    !test_bit(NVMEQ_DELETE_ERROR, &nvmeq->flags))
-			nvme_poll_irqdisable(nvmeq, -1);
-
 		sent--;
 		if (nr_queues)
 			goto retry;
@@ -2445,6 +2501,7 @@
 	nvme_suspend_io_queues(dev);
 	nvme_suspend_queue(&dev->queues[0]);
 	nvme_pci_disable(dev);
+	nvme_reap_pending_cqes(dev);
 
 	blk_mq_tagset_busy_iter(&dev->tagset, nvme_cancel_request, &dev->ctrl);
 	blk_mq_tagset_busy_iter(&dev->admin_tagset, nvme_cancel_request, &dev->ctrl);
@@ -2538,7 +2595,9 @@
 	bool was_suspend = !!(dev->ctrl.ctrl_config & NVME_CC_SHN_NORMAL);
 	int result;
 
-	if (WARN_ON(dev->ctrl.state != NVME_CTRL_RESETTING)) {
+	if (dev->ctrl.state != NVME_CTRL_RESETTING) {
+		dev_warn(dev->ctrl.device, "ctrl state %d is not RESETTING\n",
+			 dev->ctrl.state);
 		result = -ENODEV;
 		goto out;
 	}
@@ -2751,8 +2810,27 @@
 		    (dmi_match(DMI_BOARD_NAME, "PRIME B350M-A") ||
 		     dmi_match(DMI_BOARD_NAME, "PRIME Z370-A")))
 			return NVME_QUIRK_NO_APST;
+	} else if ((pdev->vendor == 0x144d && (pdev->device == 0xa801 ||
+		    pdev->device == 0xa808 || pdev->device == 0xa809)) ||
+		   (pdev->vendor == 0x1e0f && pdev->device == 0x0001)) {
+		/*
+		 * Forcing to use host managed nvme power settings for
+		 * lowest idle power with quick resume latency on
+		 * Samsung and Toshiba SSDs based on suspend behavior
+		 * on Coffee Lake board for LENOVO C640
+		 */
+		if ((dmi_match(DMI_BOARD_VENDOR, "LENOVO")) &&
+		     dmi_match(DMI_BOARD_NAME, "LNVNB161216"))
+			return NVME_QUIRK_SIMPLE_SUSPEND;
 	}
 
+	/*
+	 * NVMe SSD drops off the PCIe bus after system idle
+	 * for 10 hours on a Lenovo N60z board.
+	 */
+	if (dmi_match(DMI_BOARD_NAME, "LXKT-ZXEG-N6"))
+		return NVME_QUIRK_NO_APST;
+
 	return 0;
 }
 
@@ -2773,15 +2851,16 @@
 	size_t alloc_size;
 
 	node = dev_to_node(&pdev->dev);
-	if (node == NUMA_NO_NODE)
-		set_dev_node(&pdev->dev, first_memory_node);
 
 	dev = kzalloc_node(sizeof(*dev), GFP_KERNEL, node);
 	if (!dev)
 		return -ENOMEM;
 
-	dev->queues = kcalloc_node(max_queue_count(), sizeof(struct nvme_queue),
-					GFP_KERNEL, node);
+	dev->nr_write_queues = write_queues;
+	dev->nr_poll_queues = poll_queues;
+	dev->nr_allocated_queues = nvme_max_io_queues(dev) + 1;
+	dev->queues = kcalloc_node(dev->nr_allocated_queues,
+			sizeof(struct nvme_queue), GFP_KERNEL, node);
 	if (!dev->queues)
 		goto free;
 
@@ -2827,7 +2906,6 @@
 	dev_info(dev->ctrl.device, "pci function %s\n", dev_name(&pdev->dev));
 
 	nvme_reset_ctrl(&dev->ctrl);
-	nvme_get_ctrl(&dev->ctrl);
 	async_schedule(nvme_async_probe, dev);
 
 	return 0;
@@ -2888,7 +2966,6 @@
 	if (!pci_device_is_present(pdev)) {
 		nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_DEAD);
 		nvme_dev_disable(dev, true);
-		nvme_dev_remove_admin(dev);
 	}
 
 	flush_work(&dev->ctrl.reset_work);
@@ -2948,9 +3025,15 @@
 	 * the PCI bus layer to put it into D3 in order to take the PCIe link
 	 * down, so as to allow the platform to achieve its minimum low-power
 	 * state (which may not be possible if the link is up).
+	 *
+	 * If a host memory buffer is enabled, shut down the device as the NVMe
+	 * specification allows the device to access the host memory buffer in
+	 * host DRAM from all power states, but hosts will fail access to DRAM
+	 * during S3.
 	 */
 	if (pm_suspend_via_firmware() || !ctrl->npss ||
 	    !pcie_aspm_enabled(pdev) ||
+	    ndev->nr_host_mem_descs ||
 	    (ndev->ctrl.quirks & NVME_QUIRK_SIMPLE_SUSPEND))
 		return nvme_disable_prepare_reset(ndev, true);
 
@@ -3082,14 +3165,18 @@
 				NVME_QUIRK_DEALLOCATE_ZEROES, },
 	{ PCI_VDEVICE(INTEL, 0xf1a5),	/* Intel 600P/P3100 */
 		.driver_data = NVME_QUIRK_NO_DEEPEST_PS |
-				NVME_QUIRK_MEDIUM_PRIO_SQ },
+				NVME_QUIRK_MEDIUM_PRIO_SQ |
+				NVME_QUIRK_DISABLE_WRITE_ZEROES, },
 	{ PCI_VDEVICE(INTEL, 0xf1a6),	/* Intel 760p/Pro 7600p */
 		.driver_data = NVME_QUIRK_IGNORE_DEV_SUBNQN, },
 	{ PCI_VDEVICE(INTEL, 0x5845),	/* Qemu emulated controller */
 		.driver_data = NVME_QUIRK_IDENTIFY_CNS |
 				NVME_QUIRK_DISABLE_WRITE_ZEROES, },
+	{ PCI_DEVICE(0x126f, 0x2263),	/* Silicon Motion unidentified */
+		.driver_data = NVME_QUIRK_NO_NS_DESC_LIST, },
 	{ PCI_DEVICE(0x1bb1, 0x0100),   /* Seagate Nytro Flash Storage */
-		.driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY, },
+		.driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY |
+				NVME_QUIRK_NO_NS_DESC_LIST, },
 	{ PCI_DEVICE(0x1c58, 0x0003),	/* HGST adapter */
 		.driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY, },
 	{ PCI_DEVICE(0x1c58, 0x0023),	/* WDC SN200 adapter */
@@ -3099,7 +3186,14 @@
 	{ PCI_DEVICE(0x144d, 0xa821),   /* Samsung PM1725 */
 		.driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY, },
 	{ PCI_DEVICE(0x144d, 0xa822),   /* Samsung PM1725a */
-		.driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY, },
+		.driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY |
+				NVME_QUIRK_DISABLE_WRITE_ZEROES|
+				NVME_QUIRK_IGNORE_DEV_SUBNQN, },
+	{ PCI_DEVICE(0x1987, 0x5016),	/* Phison E16 */
+		.driver_data = NVME_QUIRK_IGNORE_DEV_SUBNQN, },
+	{ PCI_DEVICE(0x1b4b, 0x1092),	/* Lexar 256 GB SSD */
+		.driver_data = NVME_QUIRK_NO_NS_DESC_LIST |
+				NVME_QUIRK_IGNORE_DEV_SUBNQN, },
 	{ PCI_DEVICE(0x1d1d, 0x1f1f),	/* LighNVM qemu device */
 		.driver_data = NVME_QUIRK_LIGHTNVM, },
 	{ PCI_DEVICE(0x1d1d, 0x2807),	/* CNEX WL */
@@ -3111,13 +3205,19 @@
 	{ PCI_DEVICE(0x1cc1, 0x8201),   /* ADATA SX8200PNP 512GB */
 		.driver_data = NVME_QUIRK_NO_DEEPEST_PS |
 				NVME_QUIRK_IGNORE_DEV_SUBNQN, },
-	{ PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2001) },
+	{ PCI_DEVICE(0x1c5c, 0x1504),   /* SK Hynix PC400 */
+		.driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, },
+	{ PCI_DEVICE(0x2646, 0x2263),   /* KINGSTON A2000 NVMe SSD  */
+		.driver_data = NVME_QUIRK_NO_DEEPEST_PS, },
+	{ PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2001),
+		.driver_data = NVME_QUIRK_SINGLE_VECTOR },
 	{ PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2003) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2005),
 		.driver_data = NVME_QUIRK_SINGLE_VECTOR |
 				NVME_QUIRK_128_BYTES_SQES |
 				NVME_QUIRK_SHARED_TAGS },
+
+	{ PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) },
 	{ 0, }
 };
 MODULE_DEVICE_TABLE(pci, nvme_id_table);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvme/host/rdma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvme/host/rdma.c
@@ -451,7 +451,7 @@
 	 * Spread I/O queues completion vectors according their queue index.
 	 * Admin queues can always go on completion vector 0.
 	 */
-	comp_vector = idx == 0 ? idx : idx - 1;
+	comp_vector = (idx == 0 ? idx : idx - 1) % ibdev->num_comp_vectors;
 
 	/* Polling queues need direct cq polling context */
 	if (nvme_rdma_poll_queue(queue))
@@ -665,10 +665,13 @@
 	if (ret)
 		return ret;
 
-	ctrl->ctrl.queue_count = nr_io_queues + 1;
-	if (ctrl->ctrl.queue_count < 2)
-		return 0;
+	if (nr_io_queues == 0) {
+		dev_err(ctrl->ctrl.device,
+			"unable to set any I/O queues\n");
+		return -ENOMEM;
+	}
 
+	ctrl->ctrl.queue_count = nr_io_queues + 1;
 	dev_info(ctrl->ctrl.device,
 		"creating %d I/O queues.\n", nr_io_queues);
 
@@ -768,6 +771,7 @@
 		blk_mq_free_tag_set(ctrl->ctrl.admin_tagset);
 	}
 	if (ctrl->async_event_sqe.data) {
+		cancel_work_sync(&ctrl->ctrl.async_event_work);
 		nvme_rdma_free_qe(ctrl->device->dev, &ctrl->async_event_sqe,
 				sizeof(struct nvme_command), DMA_TO_DEVICE);
 		ctrl->async_event_sqe.data = NULL;
@@ -834,12 +838,16 @@
 
 	error = nvme_init_identify(&ctrl->ctrl);
 	if (error)
-		goto out_stop_queue;
+		goto out_quiesce_queue;
 
 	return 0;
 
+out_quiesce_queue:
+	blk_mq_quiesce_queue(ctrl->ctrl.admin_q);
+	blk_sync_queue(ctrl->ctrl.admin_q);
 out_stop_queue:
 	nvme_rdma_stop_queue(&ctrl->queues[0]);
+	nvme_cancel_admin_tagset(&ctrl->ctrl);
 out_cleanup_queue:
 	if (new)
 		blk_cleanup_queue(ctrl->ctrl.admin_q);
@@ -850,9 +858,11 @@
 	if (new)
 		blk_mq_free_tag_set(ctrl->ctrl.admin_tagset);
 out_free_async_qe:
-	nvme_rdma_free_qe(ctrl->device->dev, &ctrl->async_event_sqe,
-		sizeof(struct nvme_command), DMA_TO_DEVICE);
-	ctrl->async_event_sqe.data = NULL;
+	if (ctrl->async_event_sqe.data) {
+		nvme_rdma_free_qe(ctrl->device->dev, &ctrl->async_event_sqe,
+			sizeof(struct nvme_command), DMA_TO_DEVICE);
+		ctrl->async_event_sqe.data = NULL;
+	}
 out_free_queue:
 	nvme_rdma_free_queue(&ctrl->queues[0]);
 	return error;
@@ -888,18 +898,38 @@
 			ret = PTR_ERR(ctrl->ctrl.connect_q);
 			goto out_free_tag_set;
 		}
-	} else {
-		blk_mq_update_nr_hw_queues(&ctrl->tag_set,
-			ctrl->ctrl.queue_count - 1);
 	}
 
 	ret = nvme_rdma_start_io_queues(ctrl);
 	if (ret)
 		goto out_cleanup_connect_q;
 
+	if (!new) {
+		nvme_start_freeze(&ctrl->ctrl);
+		nvme_start_queues(&ctrl->ctrl);
+		if (!nvme_wait_freeze_timeout(&ctrl->ctrl, NVME_IO_TIMEOUT)) {
+			/*
+			 * If we timed out waiting for freeze we are likely to
+			 * be stuck.  Fail the controller initialization just
+			 * to be safe.
+			 */
+			ret = -ENODEV;
+			nvme_unfreeze(&ctrl->ctrl);
+			goto out_wait_freeze_timed_out;
+		}
+		blk_mq_update_nr_hw_queues(ctrl->ctrl.tagset,
+			ctrl->ctrl.queue_count - 1);
+		nvme_unfreeze(&ctrl->ctrl);
+	}
+
 	return 0;
 
+out_wait_freeze_timed_out:
+	nvme_stop_queues(&ctrl->ctrl);
+	nvme_sync_io_queues(&ctrl->ctrl);
+	nvme_rdma_stop_io_queues(ctrl);
 out_cleanup_connect_q:
+	nvme_cancel_tagset(&ctrl->ctrl);
 	if (new)
 		blk_cleanup_queue(ctrl->ctrl.connect_q);
 out_free_tag_set:
@@ -914,6 +944,7 @@
 		bool remove)
 {
 	blk_mq_quiesce_queue(ctrl->ctrl.admin_q);
+	blk_sync_queue(ctrl->ctrl.admin_q);
 	nvme_rdma_stop_queue(&ctrl->queues[0]);
 	if (ctrl->ctrl.admin_tagset) {
 		blk_mq_tagset_busy_iter(ctrl->ctrl.admin_tagset,
@@ -930,6 +961,7 @@
 {
 	if (ctrl->ctrl.queue_count > 1) {
 		nvme_stop_queues(&ctrl->ctrl);
+		nvme_sync_io_queues(&ctrl->ctrl);
 		nvme_rdma_stop_io_queues(ctrl);
 		if (ctrl->ctrl.tagset) {
 			blk_mq_tagset_busy_iter(ctrl->ctrl.tagset,
@@ -942,6 +974,14 @@
 	}
 }
 
+static void nvme_rdma_stop_ctrl(struct nvme_ctrl *nctrl)
+{
+	struct nvme_rdma_ctrl *ctrl = to_rdma_ctrl(nctrl);
+
+	cancel_work_sync(&ctrl->err_work);
+	cancel_delayed_work_sync(&ctrl->reconnect_work);
+}
+
 static void nvme_rdma_free_ctrl(struct nvme_ctrl *nctrl)
 {
 	struct nvme_rdma_ctrl *ctrl = to_rdma_ctrl(nctrl);
@@ -988,11 +1028,13 @@
 		return ret;
 
 	if (ctrl->ctrl.icdoff) {
+		ret = -EOPNOTSUPP;
 		dev_err(ctrl->ctrl.device, "icdoff is not supported!\n");
 		goto destroy_admin;
 	}
 
 	if (!(ctrl->ctrl.sgls & (1 << 2))) {
+		ret = -EOPNOTSUPP;
 		dev_err(ctrl->ctrl.device,
 			"Mandatory keyed sgls are not supported!\n");
 		goto destroy_admin;
@@ -1032,10 +1074,18 @@
 	return 0;
 
 destroy_io:
-	if (ctrl->ctrl.queue_count > 1)
+	if (ctrl->ctrl.queue_count > 1) {
+		nvme_stop_queues(&ctrl->ctrl);
+		nvme_sync_io_queues(&ctrl->ctrl);
+		nvme_rdma_stop_io_queues(ctrl);
+		nvme_cancel_tagset(&ctrl->ctrl);
 		nvme_rdma_destroy_io_queues(ctrl, new);
+	}
 destroy_admin:
+	blk_mq_quiesce_queue(ctrl->ctrl.admin_q);
+	blk_sync_queue(ctrl->ctrl.admin_q);
 	nvme_rdma_stop_queue(&ctrl->queues[0]);
+	nvme_cancel_admin_tagset(&ctrl->ctrl);
 	nvme_rdma_destroy_admin_queue(ctrl, new);
 	return ret;
 }
@@ -1069,6 +1119,7 @@
 			struct nvme_rdma_ctrl, err_work);
 
 	nvme_stop_keep_alive(&ctrl->ctrl);
+	flush_work(&ctrl->ctrl.async_event_work);
 	nvme_rdma_teardown_io_queues(ctrl, false);
 	nvme_start_queues(&ctrl->ctrl);
 	nvme_rdma_teardown_admin_queue(ctrl, false);
@@ -1088,7 +1139,8 @@
 	if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_RESETTING))
 		return;
 
-	queue_work(nvme_wq, &ctrl->err_work);
+	dev_warn(ctrl->ctrl.device, "starting error recovery\n");
+	queue_work(nvme_reset_wq, &ctrl->err_work);
 }
 
 static void nvme_rdma_wr_error(struct ib_cq *cq, struct ib_wc *wc,
@@ -1494,6 +1546,14 @@
 		return;
 	}
 
+	/* sanity checking for received data length */
+	if (unlikely(wc->byte_len < len)) {
+		dev_err(queue->ctrl->ctrl.device,
+			"Unexpected nvme completion length(%d)\n", wc->byte_len);
+		nvme_rdma_error_recovery(queue->ctrl);
+		return;
+	}
+
 	ib_dma_sync_single_for_cpu(ibdev, qe->dma, len, DMA_FROM_DEVICE);
 	/*
 	 * AEN requests are special as they don't time out and can
@@ -1653,7 +1713,6 @@
 		complete(&queue->cm_done);
 		return 0;
 	case RDMA_CM_EVENT_REJECTED:
-		nvme_rdma_destroy_queue_ib(queue);
 		cm_error = nvme_rdma_conn_rejected(queue, ev);
 		break;
 	case RDMA_CM_EVENT_ROUTE_ERROR:
@@ -1691,6 +1750,18 @@
 	return 0;
 }
 
+static void nvme_rdma_complete_timed_out(struct request *rq)
+{
+	struct nvme_rdma_request *req = blk_mq_rq_to_pdu(rq);
+	struct nvme_rdma_queue *queue = req->queue;
+
+	nvme_rdma_stop_queue(queue);
+	if (blk_mq_request_started(rq) && !blk_mq_request_completed(rq)) {
+		nvme_req(rq)->status = NVME_SC_HOST_ABORTED_CMD;
+		blk_mq_complete_request(rq);
+	}
+}
+
 static enum blk_eh_timer_return
 nvme_rdma_timeout(struct request *rq, bool reserved)
 {
@@ -1701,29 +1772,29 @@
 	dev_warn(ctrl->ctrl.device, "I/O %d QID %d timeout\n",
 		 rq->tag, nvme_rdma_queue_idx(queue));
 
-	/*
-	 * Restart the timer if a controller reset is already scheduled. Any
-	 * timed out commands would be handled before entering the connecting
-	 * state.
-	 */
-	if (ctrl->ctrl.state == NVME_CTRL_RESETTING)
-		return BLK_EH_RESET_TIMER;
-
 	if (ctrl->ctrl.state != NVME_CTRL_LIVE) {
 		/*
-		 * Teardown immediately if controller times out while starting
-		 * or we are already started error recovery. all outstanding
-		 * requests are completed on shutdown, so we return BLK_EH_DONE.
+		 * If we are resetting, connecting or deleting we should
+		 * complete immediately because we may block controller
+		 * teardown or setup sequence
+		 * - ctrl disable/shutdown fabrics requests
+		 * - connect requests
+		 * - initialization admin requests
+		 * - I/O requests that entered after unquiescing and
+		 *   the controller stopped responding
+		 *
+		 * All other requests should be cancelled by the error
+		 * recovery work, so it's fine that we fail it here.
 		 */
-		flush_work(&ctrl->err_work);
-		nvme_rdma_teardown_io_queues(ctrl, false);
-		nvme_rdma_teardown_admin_queue(ctrl, false);
+		nvme_rdma_complete_timed_out(rq);
 		return BLK_EH_DONE;
 	}
 
-	dev_warn(ctrl->ctrl.device, "starting error recovery\n");
+	/*
+	 * LIVE state should trigger the normal error recovery which will
+	 * handle completing this request.
+	 */
 	nvme_rdma_error_recovery(ctrl);
-
 	return BLK_EH_RESET_TIMER;
 }
 
@@ -1885,9 +1956,6 @@
 
 static void nvme_rdma_shutdown_ctrl(struct nvme_rdma_ctrl *ctrl, bool shutdown)
 {
-	cancel_work_sync(&ctrl->err_work);
-	cancel_delayed_work_sync(&ctrl->reconnect_work);
-
 	nvme_rdma_teardown_io_queues(ctrl, shutdown);
 	blk_mq_quiesce_queue(ctrl->ctrl.admin_q);
 	if (shutdown)
@@ -1937,6 +2005,7 @@
 	.submit_async_event	= nvme_rdma_submit_async_event,
 	.delete_ctrl		= nvme_rdma_delete_ctrl,
 	.get_address		= nvmf_get_address,
+	.stop_ctrl		= nvme_rdma_stop_ctrl,
 };
 
 /*
@@ -2045,8 +2114,6 @@
 	dev_info(ctrl->ctrl.device, "new ctrl: NQN \"%s\", addr %pISpcs\n",
 		ctrl->ctrl.opts->subsysnqn, &ctrl->addr);
 
-	nvme_get_ctrl(&ctrl->ctrl);
-
 	mutex_lock(&nvme_rdma_ctrl_mutex);
 	list_add_tail(&ctrl->list, &nvme_rdma_ctrl_list);
 	mutex_unlock(&nvme_rdma_ctrl_mutex);
@@ -2056,6 +2123,7 @@
 out_uninit_ctrl:
 	nvme_uninit_ctrl(&ctrl->ctrl);
 	nvme_put_ctrl(&ctrl->ctrl);
+	nvme_put_ctrl(&ctrl->ctrl);
 	if (ret > 0)
 		ret = -EIO;
 	return ERR_PTR(ret);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvme/host/tcp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvme/host/tcp.c
@@ -164,16 +164,14 @@
 static inline bool nvme_tcp_has_inline_data(struct nvme_tcp_request *req)
 {
 	struct request *rq;
-	unsigned int bytes;
 
 	if (unlikely(nvme_tcp_async_req(req)))
 		return false; /* async events don't have a request */
 
 	rq = blk_mq_rq_from_pdu(req);
-	bytes = blk_rq_payload_bytes(rq);
 
-	return rq_data_dir(rq) == WRITE && bytes &&
-		bytes <= nvme_tcp_inline_data_size(req->queue);
+	return rq_data_dir(rq) == WRITE && req->data_len &&
+		req->data_len <= nvme_tcp_inline_data_size(req->queue);
 }
 
 static inline struct page *nvme_tcp_req_cur_page(struct nvme_tcp_request *req)
@@ -188,7 +186,7 @@
 
 static inline size_t nvme_tcp_req_cur_length(struct nvme_tcp_request *req)
 {
-	return min_t(size_t, req->iter.bvec->bv_len - req->iter.iov_offset,
+	return min_t(size_t, iov_iter_single_seg_count(&req->iter),
 			req->pdu_len - req->pdu_sent);
 }
 
@@ -422,7 +420,8 @@
 	if (!nvme_change_ctrl_state(ctrl, NVME_CTRL_RESETTING))
 		return;
 
-	queue_work(nvme_wq, &to_tcp_ctrl(ctrl)->err_work);
+	dev_warn(ctrl->device, "starting error recovery\n");
+	queue_work(nvme_reset_wq, &to_tcp_ctrl(ctrl)->err_work);
 }
 
 static int nvme_tcp_process_nvme_cqe(struct nvme_tcp_queue *queue,
@@ -513,6 +512,13 @@
 	req->pdu_len = le32_to_cpu(pdu->r2t_length);
 	req->pdu_sent = 0;
 
+	if (unlikely(!req->pdu_len)) {
+		dev_err(queue->ctrl->ctrl.device,
+			"req %d r2t len is %u, probably a bug...\n",
+			rq->tag, req->pdu_len);
+		return -EPROTO;
+	}
+
 	if (unlikely(req->data_sent + req->pdu_len > req->data_len)) {
 		dev_err(queue->ctrl->ctrl.device,
 			"req %d r2t len %u exceeded data len %u (%zu sent)\n",
@@ -636,17 +642,9 @@
 			      unsigned int *offset, size_t *len)
 {
 	struct nvme_tcp_data_pdu *pdu = (void *)queue->pdu;
-	struct nvme_tcp_request *req;
-	struct request *rq;
-
-	rq = blk_mq_tag_to_rq(nvme_tcp_tagset(queue), pdu->command_id);
-	if (!rq) {
-		dev_err(queue->ctrl->ctrl.device,
-			"queue %d tag %#x not found\n",
-			nvme_tcp_queue_id(queue), pdu->command_id);
-		return -ENOENT;
-	}
-	req = blk_mq_rq_to_pdu(rq);
+	struct request *rq =
+		blk_mq_tag_to_rq(nvme_tcp_tagset(queue), pdu->command_id);
+	struct nvme_tcp_request *req = blk_mq_rq_to_pdu(rq);
 
 	while (true) {
 		int recv_len, ret;
@@ -786,11 +784,11 @@
 {
 	struct nvme_tcp_queue *queue;
 
-	read_lock(&sk->sk_callback_lock);
+	read_lock_bh(&sk->sk_callback_lock);
 	queue = sk->sk_user_data;
 	if (likely(queue && queue->rd_enabled))
 		queue_work_on(queue->io_cpu, nvme_tcp_wq, &queue->io_work);
-	read_unlock(&sk->sk_callback_lock);
+	read_unlock_bh(&sk->sk_callback_lock);
 }
 
 static void nvme_tcp_write_space(struct sock *sk)
@@ -810,7 +808,7 @@
 {
 	struct nvme_tcp_queue *queue;
 
-	read_lock(&sk->sk_callback_lock);
+	read_lock_bh(&sk->sk_callback_lock);
 	queue = sk->sk_user_data;
 	if (!queue)
 		goto done;
@@ -832,7 +830,7 @@
 
 	queue->state_change(sk);
 done:
-	read_unlock(&sk->sk_callback_lock);
+	read_unlock_bh(&sk->sk_callback_lock);
 }
 
 static inline void nvme_tcp_done_send_req(struct nvme_tcp_queue *queue)
@@ -842,7 +840,15 @@
 
 static void nvme_tcp_fail_request(struct nvme_tcp_request *req)
 {
-	nvme_tcp_end_request(blk_mq_rq_from_pdu(req), NVME_SC_HOST_PATH_ERROR);
+	if (nvme_tcp_async_req(req)) {
+		union nvme_result res = {};
+
+		nvme_complete_async_event(&req->queue->ctrl->ctrl,
+				cpu_to_le16(NVME_SC_HOST_PATH_ERROR), &res);
+	} else {
+		nvme_tcp_end_request(blk_mq_rq_from_pdu(req),
+				NVME_SC_HOST_PATH_ERROR);
+	}
 }
 
 static int nvme_tcp_try_send_data(struct nvme_tcp_request *req)
@@ -861,12 +867,11 @@
 		else
 			flags |= MSG_MORE;
 
-		/* can't zcopy slab pages */
-		if (unlikely(PageSlab(page))) {
-			ret = sock_no_sendpage(queue->sock, page, offset, len,
+		if (sendpage_ok(page)) {
+			ret = kernel_sendpage(queue->sock, page, offset, len,
 					flags);
 		} else {
-			ret = kernel_sendpage(queue->sock, page, offset, len,
+			ret = sock_no_sendpage(queue->sock, page, offset, len,
 					flags);
 		}
 		if (ret <= 0)
@@ -965,7 +970,7 @@
 	int ret;
 	struct msghdr msg = { .msg_flags = MSG_DONTWAIT | MSG_EOR };
 	struct kvec iov = {
-		.iov_base = &req->ddgst + req->offset,
+		.iov_base = (u8 *)&req->ddgst + req->offset,
 		.iov_len = NVME_TCP_DIGEST_LENGTH - req->offset
 	};
 
@@ -1054,7 +1059,12 @@
 		} else if (unlikely(result < 0)) {
 			dev_err(queue->ctrl->ctrl.device,
 				"failed to send request %d\n", result);
-			if (result != -EPIPE)
+
+			/*
+			 * Fail the request unless peer closed the connection,
+			 * in which case error recovery flow will complete all.
+			 */
+			if ((result != -EPIPE) && (result != -ECONNRESET))
 				nvme_tcp_fail_request(queue->request);
 			nvme_tcp_done_send_req(queue);
 			return;
@@ -1064,7 +1074,7 @@
 		if (result > 0)
 			pending = true;
 
-		if (!pending)
+		if (!pending || !queue->rd_enabled)
 			return;
 
 	} while (!time_after(jiffies, deadline)); /* quota is exhausted */
@@ -1316,6 +1326,9 @@
 		}
 	}
 
+	/* Set 10 seconds timeout for icresp recvmsg */
+	queue->sock->sk->sk_rcvtimeo = 10 * HZ;
+
 	queue->sock->sk->sk_allocation = GFP_ATOMIC;
 	if (!qid)
 		n = 0;
@@ -1374,22 +1387,7 @@
 	if (ret)
 		goto err_init_connect;
 
-	queue->rd_enabled = true;
 	set_bit(NVME_TCP_Q_ALLOCATED, &queue->flags);
-	nvme_tcp_init_recv_ctx(queue);
-
-	write_lock_bh(&queue->sock->sk->sk_callback_lock);
-	queue->sock->sk->sk_user_data = queue;
-	queue->state_change = queue->sock->sk->sk_state_change;
-	queue->data_ready = queue->sock->sk->sk_data_ready;
-	queue->write_space = queue->sock->sk->sk_write_space;
-	queue->sock->sk->sk_data_ready = nvme_tcp_data_ready;
-	queue->sock->sk->sk_state_change = nvme_tcp_state_change;
-	queue->sock->sk->sk_write_space = nvme_tcp_write_space;
-#ifdef CONFIG_NET_RX_BUSY_POLL
-	queue->sock->sk->sk_ll_usec = 1;
-#endif
-	write_unlock_bh(&queue->sock->sk->sk_callback_lock);
 
 	return 0;
 
@@ -1406,7 +1404,7 @@
 	return ret;
 }
 
-static void nvme_tcp_restore_sock_calls(struct nvme_tcp_queue *queue)
+static void nvme_tcp_restore_sock_ops(struct nvme_tcp_queue *queue)
 {
 	struct socket *sock = queue->sock;
 
@@ -1421,7 +1419,7 @@
 static void __nvme_tcp_stop_queue(struct nvme_tcp_queue *queue)
 {
 	kernel_sock_shutdown(queue->sock, SHUT_RDWR);
-	nvme_tcp_restore_sock_calls(queue);
+	nvme_tcp_restore_sock_ops(queue);
 	cancel_work_sync(&queue->io_work);
 }
 
@@ -1432,25 +1430,45 @@
 
 	if (!test_and_clear_bit(NVME_TCP_Q_LIVE, &queue->flags))
 		return;
-
 	__nvme_tcp_stop_queue(queue);
 }
 
+static void nvme_tcp_setup_sock_ops(struct nvme_tcp_queue *queue)
+{
+	write_lock_bh(&queue->sock->sk->sk_callback_lock);
+	queue->sock->sk->sk_user_data = queue;
+	queue->state_change = queue->sock->sk->sk_state_change;
+	queue->data_ready = queue->sock->sk->sk_data_ready;
+	queue->write_space = queue->sock->sk->sk_write_space;
+	queue->sock->sk->sk_data_ready = nvme_tcp_data_ready;
+	queue->sock->sk->sk_state_change = nvme_tcp_state_change;
+	queue->sock->sk->sk_write_space = nvme_tcp_write_space;
+#ifdef CONFIG_NET_RX_BUSY_POLL
+	queue->sock->sk->sk_ll_usec = 1;
+#endif
+	write_unlock_bh(&queue->sock->sk->sk_callback_lock);
+}
+
 static int nvme_tcp_start_queue(struct nvme_ctrl *nctrl, int idx)
 {
 	struct nvme_tcp_ctrl *ctrl = to_tcp_ctrl(nctrl);
+	struct nvme_tcp_queue *queue = &ctrl->queues[idx];
 	int ret;
 
+	queue->rd_enabled = true;
+	nvme_tcp_init_recv_ctx(queue);
+	nvme_tcp_setup_sock_ops(queue);
+
 	if (idx)
 		ret = nvmf_connect_io_queue(nctrl, idx, false);
 	else
 		ret = nvmf_connect_admin_queue(nctrl);
 
 	if (!ret) {
-		set_bit(NVME_TCP_Q_LIVE, &ctrl->queues[idx].flags);
+		set_bit(NVME_TCP_Q_LIVE, &queue->flags);
 	} else {
-		if (test_bit(NVME_TCP_Q_ALLOCATED, &ctrl->queues[idx].flags))
-			__nvme_tcp_stop_queue(&ctrl->queues[idx]);
+		if (test_bit(NVME_TCP_Q_ALLOCATED, &queue->flags))
+			__nvme_tcp_stop_queue(queue);
 		dev_err(nctrl->device,
 			"failed to connect queue: %d ret=%d\n", idx, ret);
 	}
@@ -1500,6 +1518,7 @@
 static void nvme_tcp_free_admin_queue(struct nvme_ctrl *ctrl)
 {
 	if (to_tcp_ctrl(ctrl)->async_req.pdu) {
+		cancel_work_sync(&ctrl->async_event_work);
 		nvme_tcp_free_async_req(to_tcp_ctrl(ctrl));
 		to_tcp_ctrl(ctrl)->async_req.pdu = NULL;
 	}
@@ -1636,10 +1655,13 @@
 	if (ret)
 		return ret;
 
-	ctrl->queue_count = nr_io_queues + 1;
-	if (ctrl->queue_count < 2)
-		return 0;
+	if (nr_io_queues == 0) {
+		dev_err(ctrl->device,
+			"unable to set any I/O queues\n");
+		return -ENOMEM;
+	}
 
+	ctrl->queue_count = nr_io_queues + 1;
 	dev_info(ctrl->device,
 		"creating %d I/O queues.\n", nr_io_queues);
 
@@ -1678,18 +1700,38 @@
 			ret = PTR_ERR(ctrl->connect_q);
 			goto out_free_tag_set;
 		}
-	} else {
-		blk_mq_update_nr_hw_queues(ctrl->tagset,
-			ctrl->queue_count - 1);
 	}
 
 	ret = nvme_tcp_start_io_queues(ctrl);
 	if (ret)
 		goto out_cleanup_connect_q;
 
+	if (!new) {
+		nvme_start_freeze(ctrl);
+		nvme_start_queues(ctrl);
+		if (!nvme_wait_freeze_timeout(ctrl, NVME_IO_TIMEOUT)) {
+			/*
+			 * If we timed out waiting for freeze we are likely to
+			 * be stuck.  Fail the controller initialization just
+			 * to be safe.
+			 */
+			ret = -ENODEV;
+			nvme_unfreeze(ctrl);
+			goto out_wait_freeze_timed_out;
+		}
+		blk_mq_update_nr_hw_queues(ctrl->tagset,
+			ctrl->queue_count - 1);
+		nvme_unfreeze(ctrl);
+	}
+
 	return 0;
 
+out_wait_freeze_timed_out:
+	nvme_stop_queues(ctrl);
+	nvme_sync_io_queues(ctrl);
+	nvme_tcp_stop_io_queues(ctrl);
 out_cleanup_connect_q:
+	nvme_cancel_tagset(ctrl);
 	if (new)
 		blk_cleanup_queue(ctrl->connect_q);
 out_free_tag_set:
@@ -1751,12 +1793,16 @@
 
 	error = nvme_init_identify(ctrl);
 	if (error)
-		goto out_stop_queue;
+		goto out_quiesce_queue;
 
 	return 0;
 
+out_quiesce_queue:
+	blk_mq_quiesce_queue(ctrl->admin_q);
+	blk_sync_queue(ctrl->admin_q);
 out_stop_queue:
 	nvme_tcp_stop_queue(ctrl, 0);
+	nvme_cancel_admin_tagset(ctrl);
 out_cleanup_queue:
 	if (new)
 		blk_cleanup_queue(ctrl->admin_q);
@@ -1775,6 +1821,7 @@
 		bool remove)
 {
 	blk_mq_quiesce_queue(ctrl->admin_q);
+	blk_sync_queue(ctrl->admin_q);
 	nvme_tcp_stop_queue(ctrl, 0);
 	if (ctrl->admin_tagset) {
 		blk_mq_tagset_busy_iter(ctrl->admin_tagset,
@@ -1791,7 +1838,9 @@
 {
 	if (ctrl->queue_count <= 1)
 		return;
+	blk_mq_quiesce_queue(ctrl->admin_q);
 	nvme_stop_queues(ctrl);
+	nvme_sync_io_queues(ctrl);
 	nvme_tcp_stop_io_queues(ctrl);
 	if (ctrl->tagset) {
 		blk_mq_tagset_busy_iter(ctrl->tagset,
@@ -1866,10 +1915,18 @@
 	return 0;
 
 destroy_io:
-	if (ctrl->queue_count > 1)
+	if (ctrl->queue_count > 1) {
+		nvme_stop_queues(ctrl);
+		nvme_sync_io_queues(ctrl);
+		nvme_tcp_stop_io_queues(ctrl);
+		nvme_cancel_tagset(ctrl);
 		nvme_tcp_destroy_io_queues(ctrl, new);
+	}
 destroy_admin:
+	blk_mq_quiesce_queue(ctrl->admin_q);
+	blk_sync_queue(ctrl->admin_q);
 	nvme_tcp_stop_queue(ctrl, 0);
+	nvme_cancel_admin_tagset(ctrl);
 	nvme_tcp_destroy_admin_queue(ctrl, new);
 	return ret;
 }
@@ -1905,6 +1962,7 @@
 	struct nvme_ctrl *ctrl = &tcp_ctrl->ctrl;
 
 	nvme_stop_keep_alive(ctrl);
+	flush_work(&ctrl->async_event_work);
 	nvme_tcp_teardown_io_queues(ctrl, false);
 	/* unquiesce to fail fast pending requests */
 	nvme_start_queues(ctrl);
@@ -1922,9 +1980,6 @@
 
 static void nvme_tcp_teardown_ctrl(struct nvme_ctrl *ctrl, bool shutdown)
 {
-	cancel_work_sync(&to_tcp_ctrl(ctrl)->err_work);
-	cancel_delayed_work_sync(&to_tcp_ctrl(ctrl)->connect_work);
-
 	nvme_tcp_teardown_io_queues(ctrl, shutdown);
 	blk_mq_quiesce_queue(ctrl->admin_q);
 	if (shutdown)
@@ -1963,6 +2018,12 @@
 	nvme_tcp_reconnect_or_remove(ctrl);
 }
 
+static void nvme_tcp_stop_ctrl(struct nvme_ctrl *ctrl)
+{
+	cancel_work_sync(&to_tcp_ctrl(ctrl)->err_work);
+	cancel_delayed_work_sync(&to_tcp_ctrl(ctrl)->connect_work);
+}
+
 static void nvme_tcp_free_ctrl(struct nvme_ctrl *nctrl)
 {
 	struct nvme_tcp_ctrl *ctrl = to_tcp_ctrl(nctrl);
@@ -2039,40 +2100,52 @@
 	nvme_tcp_queue_request(&ctrl->async_req);
 }
 
+static void nvme_tcp_complete_timed_out(struct request *rq)
+{
+	struct nvme_tcp_request *req = blk_mq_rq_to_pdu(rq);
+	struct nvme_ctrl *ctrl = &req->queue->ctrl->ctrl;
+
+	nvme_tcp_stop_queue(ctrl, nvme_tcp_queue_id(req->queue));
+	if (blk_mq_request_started(rq) && !blk_mq_request_completed(rq)) {
+		nvme_req(rq)->status = NVME_SC_HOST_ABORTED_CMD;
+		blk_mq_complete_request(rq);
+	}
+}
+
 static enum blk_eh_timer_return
 nvme_tcp_timeout(struct request *rq, bool reserved)
 {
 	struct nvme_tcp_request *req = blk_mq_rq_to_pdu(rq);
-	struct nvme_tcp_ctrl *ctrl = req->queue->ctrl;
+	struct nvme_ctrl *ctrl = &req->queue->ctrl->ctrl;
 	struct nvme_tcp_cmd_pdu *pdu = req->pdu;
 
-	/*
-	 * Restart the timer if a controller reset is already scheduled. Any
-	 * timed out commands would be handled before entering the connecting
-	 * state.
-	 */
-	if (ctrl->ctrl.state == NVME_CTRL_RESETTING)
-		return BLK_EH_RESET_TIMER;
-
-	dev_warn(ctrl->ctrl.device,
+	dev_warn(ctrl->device,
 		"queue %d: timeout request %#x type %d\n",
 		nvme_tcp_queue_id(req->queue), rq->tag, pdu->hdr.type);
 
-	if (ctrl->ctrl.state != NVME_CTRL_LIVE) {
+	if (ctrl->state != NVME_CTRL_LIVE) {
 		/*
-		 * Teardown immediately if controller times out while starting
-		 * or we are already started error recovery. all outstanding
-		 * requests are completed on shutdown, so we return BLK_EH_DONE.
+		 * If we are resetting, connecting or deleting we should
+		 * complete immediately because we may block controller
+		 * teardown or setup sequence
+		 * - ctrl disable/shutdown fabrics requests
+		 * - connect requests
+		 * - initialization admin requests
+		 * - I/O requests that entered after unquiescing and
+		 *   the controller stopped responding
+		 *
+		 * All other requests should be cancelled by the error
+		 * recovery work, so it's fine that we fail it here.
 		 */
-		flush_work(&ctrl->err_work);
-		nvme_tcp_teardown_io_queues(&ctrl->ctrl, false);
-		nvme_tcp_teardown_admin_queue(&ctrl->ctrl, false);
+		nvme_tcp_complete_timed_out(rq);
 		return BLK_EH_DONE;
 	}
 
-	dev_warn(ctrl->ctrl.device, "starting error recovery\n");
-	nvme_tcp_error_recovery(&ctrl->ctrl);
-
+	/*
+	 * LIVE state should trigger the normal error recovery which will
+	 * handle completing this request.
+	 */
+	nvme_tcp_error_recovery(ctrl);
 	return BLK_EH_RESET_TIMER;
 }
 
@@ -2085,7 +2158,9 @@
 
 	c->common.flags |= NVME_CMD_SGL_METABUF;
 
-	if (rq_data_dir(rq) == WRITE && req->data_len &&
+	if (!blk_rq_nr_phys_segments(rq))
+		nvme_tcp_set_sg_null(c);
+	else if (rq_data_dir(rq) == WRITE &&
 	    req->data_len <= nvme_tcp_inline_data_size(queue))
 		nvme_tcp_set_sg_inline(queue, c, req->data_len);
 	else
@@ -2112,7 +2187,8 @@
 	req->data_sent = 0;
 	req->pdu_len = 0;
 	req->pdu_sent = 0;
-	req->data_len = blk_rq_payload_bytes(rq);
+	req->data_len = blk_rq_nr_phys_segments(rq) ?
+				blk_rq_payload_bytes(rq) : 0;
 	req->curr_bio = rq->bio;
 
 	if (rq_data_dir(rq) == WRITE &&
@@ -2256,6 +2332,7 @@
 	.submit_async_event	= nvme_tcp_submit_async_event,
 	.delete_ctrl		= nvme_tcp_delete_ctrl,
 	.get_address		= nvmf_get_address,
+	.stop_ctrl		= nvme_tcp_stop_ctrl,
 };
 
 static bool
@@ -2354,8 +2431,6 @@
 	dev_info(ctrl->ctrl.device, "new ctrl: NQN \"%s\", addr %pISp\n",
 		ctrl->ctrl.opts->subsysnqn, &ctrl->addr);
 
-	nvme_get_ctrl(&ctrl->ctrl);
-
 	mutex_lock(&nvme_tcp_ctrl_mutex);
 	list_add_tail(&ctrl->list, &nvme_tcp_ctrl_list);
 	mutex_unlock(&nvme_tcp_ctrl_mutex);
@@ -2365,6 +2440,7 @@
 out_uninit_ctrl:
 	nvme_uninit_ctrl(&ctrl->ctrl);
 	nvme_put_ctrl(&ctrl->ctrl);
+	nvme_put_ctrl(&ctrl->ctrl);
 	if (ret > 0)
 		ret = -EIO;
 	return ERR_PTR(ret);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvme/host/trace.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvme/host/trace.h
@@ -56,7 +56,7 @@
 		__field(u8, fctype)
 		__field(u16, cid)
 		__field(u32, nsid)
-		__field(u64, metadata)
+		__field(bool, metadata)
 		__array(u8, cdw10, 24)
 	    ),
 	    TP_fast_assign(
@@ -66,13 +66,13 @@
 		__entry->flags = cmd->common.flags;
 		__entry->cid = cmd->common.command_id;
 		__entry->nsid = le32_to_cpu(cmd->common.nsid);
-		__entry->metadata = le64_to_cpu(cmd->common.metadata);
+		__entry->metadata = !!blk_integrity_rq(req);
 		__entry->fctype = cmd->fabrics.fctype;
 		__assign_disk_name(__entry->disk, req->rq_disk);
 		memcpy(__entry->cdw10, &cmd->common.cdw10,
 			sizeof(__entry->cdw10));
 	    ),
-	    TP_printk("nvme%d: %sqid=%d, cmdid=%u, nsid=%u, flags=0x%x, meta=0x%llx, cmd=(%s %s)",
+	    TP_printk("nvme%d: %sqid=%d, cmdid=%u, nsid=%u, flags=0x%x, meta=0x%x, cmd=(%s %s)",
 		      __entry->ctrl_id, __print_disk_name(__entry->disk),
 		      __entry->qid, __entry->cid, __entry->nsid,
 		      __entry->flags, __entry->metadata,
@@ -127,15 +127,12 @@
 	),
 	TP_printk("nvme%d: NVME_AEN=%#08x [%s]",
 		__entry->ctrl_id, __entry->result,
-		__print_symbolic(__entry->result,
-		aer_name(NVME_AER_NOTICE_NS_CHANGED),
-		aer_name(NVME_AER_NOTICE_ANA),
-		aer_name(NVME_AER_NOTICE_FW_ACT_STARTING),
-		aer_name(NVME_AER_NOTICE_DISC_CHANGED),
-		aer_name(NVME_AER_ERROR),
-		aer_name(NVME_AER_SMART),
-		aer_name(NVME_AER_CSS),
-		aer_name(NVME_AER_VS))
+		__print_symbolic(__entry->result & 0x7,
+			aer_name(NVME_AER_ERROR),
+			aer_name(NVME_AER_SMART),
+			aer_name(NVME_AER_NOTICE),
+			aer_name(NVME_AER_CSS),
+			aer_name(NVME_AER_VS))
 	)
 );
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvme/target/configfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvme/target/configfs.c
@@ -507,10 +507,18 @@
 	if (strtobool(page, &enable))
 		return -EINVAL;
 
+	/*
+	 * take a global nvmet_config_sem because the disable routine has a
+	 * window where it releases the subsys-lock, giving a chance to
+	 * a parallel enable to concurrently execute causing the disable to
+	 * have a misaccounting of the ns percpu_ref.
+	 */
+	down_write(&nvmet_config_sem);
 	if (enable)
 		ret = nvmet_ns_enable(ns);
 	else
 		nvmet_ns_disable(ns);
+	up_write(&nvmet_config_sem);
 
 	return ret ? ret : count;
 }
@@ -1148,6 +1156,8 @@
 {
 	struct nvmet_port *port = to_nvmet_port(item);
 
+	/* Let inflight controllers teardown complete */
+	flush_scheduled_work();
 	list_del(&port->global_entry);
 
 	kfree(port->ana_state);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvme/target/core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvme/target/core.c
@@ -369,6 +369,9 @@
 
 static void nvmet_start_keep_alive_timer(struct nvmet_ctrl *ctrl)
 {
+	if (unlikely(ctrl->kato == 0))
+		return;
+
 	pr_debug("ctrl %d start keep-alive timer for %d secs\n",
 		ctrl->cntlid, ctrl->kato);
 
@@ -378,6 +381,9 @@
 
 static void nvmet_stop_keep_alive_timer(struct nvmet_ctrl *ctrl)
 {
+	if (unlikely(ctrl->kato == 0))
+		return;
+
 	pr_debug("ctrl %d stop keep-alive\n", ctrl->cntlid);
 
 	cancel_delayed_work_sync(&ctrl->ka_work);
@@ -555,7 +561,8 @@
 	} else {
 		struct nvmet_ns *old;
 
-		list_for_each_entry_rcu(old, &subsys->namespaces, dev_link) {
+		list_for_each_entry_rcu(old, &subsys->namespaces, dev_link,
+					lockdep_is_held(&subsys->lock)) {
 			BUG_ON(ns->nsid == old->nsid);
 			if (ns->nsid < old->nsid)
 				break;
@@ -702,6 +709,8 @@
 
 static void __nvmet_req_complete(struct nvmet_req *req, u16 status)
 {
+	struct nvmet_ns *ns = req->ns;
+
 	if (!req->sq->sqhd_disabled)
 		nvmet_update_sq_head(req);
 	req->cqe->sq_id = cpu_to_le16(req->sq->qid);
@@ -712,15 +721,17 @@
 
 	trace_nvmet_req_complete(req);
 
-	if (req->ns)
-		nvmet_put_namespace(req->ns);
 	req->ops->queue_response(req);
+	if (ns)
+		nvmet_put_namespace(ns);
 }
 
 void nvmet_req_complete(struct nvmet_req *req, u16 status)
 {
+	struct nvmet_sq *sq = req->sq;
+
 	__nvmet_req_complete(req, status);
-	percpu_ref_put(&req->sq->ref);
+	percpu_ref_put(&sq->ref);
 }
 EXPORT_SYMBOL_GPL(nvmet_req_complete);
 
@@ -871,8 +882,6 @@
 	req->error_loc = NVMET_NO_ERROR_LOC;
 	req->error_slba = 0;
 
-	trace_nvmet_req_init(req, req->cmd);
-
 	/* no support for fused commands yet */
 	if (unlikely(flags & (NVME_CMD_FUSE_FIRST | NVME_CMD_FUSE_SECOND))) {
 		req->error_loc = offsetof(struct nvme_common_command, flags);
@@ -906,6 +915,8 @@
 	if (status)
 		goto fail;
 
+	trace_nvmet_req_init(req, req->cmd);
+
 	if (unlikely(!percpu_ref_tryget_live(&sq->ref))) {
 		status = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
 		goto fail;
@@ -1024,9 +1035,20 @@
 {
 	lockdep_assert_held(&ctrl->lock);
 
-	if (nvmet_cc_iosqes(ctrl->cc) != NVME_NVM_IOSQES ||
-	    nvmet_cc_iocqes(ctrl->cc) != NVME_NVM_IOCQES ||
-	    nvmet_cc_mps(ctrl->cc) != 0 ||
+	/*
+	 * Only I/O controllers should verify iosqes,iocqes.
+	 * Strictly speaking, the spec says a discovery controller
+	 * should verify iosqes,iocqes are zeroed, however that
+	 * would break backwards compatibility, so don't enforce it.
+	 */
+	if (ctrl->subsys->type != NVME_NQN_DISC &&
+	    (nvmet_cc_iosqes(ctrl->cc) != NVME_NVM_IOSQES ||
+	     nvmet_cc_iocqes(ctrl->cc) != NVME_NVM_IOCQES)) {
+		ctrl->csts = NVME_CSTS_CFS;
+		return;
+	}
+
+	if (nvmet_cc_mps(ctrl->cc) != 0 ||
 	    nvmet_cc_ams(ctrl->cc) != 0 ||
 	    nvmet_cc_css(ctrl->cc) != 0) {
 		ctrl->csts = NVME_CSTS_CFS;
@@ -1041,7 +1063,8 @@
 	 * in case a host died before it enabled the controller.  Hence, simply
 	 * reset the keep alive timer when the controller is enabled.
 	 */
-	mod_delayed_work(system_wq, &ctrl->ka_work, ctrl->kato * HZ);
+	if (ctrl->kato)
+		mod_delayed_work(system_wq, &ctrl->ka_work, ctrl->kato * HZ);
 }
 
 static void nvmet_clear_ctrl(struct nvmet_ctrl *ctrl)
@@ -1084,19 +1107,19 @@
 	ctrl->cap |= NVMET_QUEUE_SIZE - 1;
 }
 
-u16 nvmet_ctrl_find_get(const char *subsysnqn, const char *hostnqn, u16 cntlid,
-		struct nvmet_req *req, struct nvmet_ctrl **ret)
+struct nvmet_ctrl *nvmet_ctrl_find_get(const char *subsysnqn,
+				       const char *hostnqn, u16 cntlid,
+				       struct nvmet_req *req)
 {
+	struct nvmet_ctrl *ctrl = NULL;
 	struct nvmet_subsys *subsys;
-	struct nvmet_ctrl *ctrl;
-	u16 status = 0;
 
 	subsys = nvmet_find_get_subsys(req->port, subsysnqn);
 	if (!subsys) {
 		pr_warn("connect request for invalid subsystem %s!\n",
 			subsysnqn);
 		req->cqe->result.u32 = IPO_IATTR_CONNECT_DATA(subsysnqn);
-		return NVME_SC_CONNECT_INVALID_PARAM | NVME_SC_DNR;
+		goto out;
 	}
 
 	mutex_lock(&subsys->lock);
@@ -1109,20 +1132,21 @@
 			if (!kref_get_unless_zero(&ctrl->ref))
 				continue;
 
-			*ret = ctrl;
-			goto out;
+			/* ctrl found */
+			goto found;
 		}
 	}
 
+	ctrl = NULL; /* ctrl not found */
 	pr_warn("could not find controller %d for subsys %s / host %s\n",
 		cntlid, subsysnqn, hostnqn);
 	req->cqe->result.u32 = IPO_IATTR_CONNECT_DATA(cntlid);
-	status = NVME_SC_CONNECT_INVALID_PARAM | NVME_SC_DNR;
 
-out:
+found:
 	mutex_unlock(&subsys->lock);
 	nvmet_subsys_put(subsys);
-	return status;
+out:
+	return ctrl;
 }
 
 u16 nvmet_check_ctrl_status(struct nvmet_req *req, struct nvme_command *cmd)
@@ -1174,7 +1198,8 @@
 
 	ctrl->p2p_client = get_device(req->p2p_client);
 
-	list_for_each_entry_rcu(ns, &ctrl->subsys->namespaces, dev_link)
+	list_for_each_entry_rcu(ns, &ctrl->subsys->namespaces, dev_link,
+				lockdep_is_held(&ctrl->subsys->lock))
 		nvmet_p2pmem_ns_add_p2p(ctrl, ns);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvme/target/fabrics-cmd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvme/target/fabrics-cmd.c
@@ -105,6 +105,7 @@
 	u16 qid = le16_to_cpu(c->qid);
 	u16 sqsize = le16_to_cpu(c->sqsize);
 	struct nvmet_ctrl *old;
+	u16 ret;
 
 	old = cmpxchg(&req->sq->ctrl, NULL, ctrl);
 	if (old) {
@@ -115,7 +116,9 @@
 	if (!sqsize) {
 		pr_warn("queue size zero!\n");
 		req->error_loc = offsetof(struct nvmf_connect_command, sqsize);
-		return NVME_SC_CONNECT_INVALID_PARAM | NVME_SC_DNR;
+		req->cqe->result.u32 = IPO_IATTR_CONNECT_SQE(sqsize);
+		ret = NVME_SC_CONNECT_INVALID_PARAM | NVME_SC_DNR;
+		goto err;
 	}
 
 	/* note: convert queue size from 0's-based value to 1's-based value */
@@ -128,16 +131,19 @@
 	}
 
 	if (ctrl->ops->install_queue) {
-		u16 ret = ctrl->ops->install_queue(req->sq);
-
+		ret = ctrl->ops->install_queue(req->sq);
 		if (ret) {
 			pr_err("failed to install queue %d cntlid %d ret %x\n",
-				qid, ret, ctrl->cntlid);
-			return ret;
+				qid, ctrl->cntlid, ret);
+			goto err;
 		}
 	}
 
 	return 0;
+
+err:
+	req->sq->ctrl = NULL;
+	return ret;
 }
 
 static void nvmet_execute_admin_connect(struct nvmet_req *req)
@@ -176,6 +182,8 @@
 		goto out;
 	}
 
+	d->subsysnqn[NVMF_NQN_FIELD_LEN - 1] = '\0';
+	d->hostnqn[NVMF_NQN_FIELD_LEN - 1] = '\0';
 	status = nvmet_alloc_ctrl(d->subsysnqn, d->hostnqn, req,
 				  le32_to_cpu(c->kato), &ctrl);
 	if (status) {
@@ -207,7 +215,7 @@
 {
 	struct nvmf_connect_command *c = &req->cmd->connect;
 	struct nvmf_connect_data *d;
-	struct nvmet_ctrl *ctrl = NULL;
+	struct nvmet_ctrl *ctrl;
 	u16 qid = le16_to_cpu(c->qid);
 	u16 status = 0;
 
@@ -231,11 +239,14 @@
 		goto out;
 	}
 
-	status = nvmet_ctrl_find_get(d->subsysnqn, d->hostnqn,
-				     le16_to_cpu(d->cntlid),
-				     req, &ctrl);
-	if (status)
+	d->subsysnqn[NVMF_NQN_FIELD_LEN - 1] = '\0';
+	d->hostnqn[NVMF_NQN_FIELD_LEN - 1] = '\0';
+	ctrl = nvmet_ctrl_find_get(d->subsysnqn, d->hostnqn,
+				   le16_to_cpu(d->cntlid), req);
+	if (!ctrl) {
+		status = NVME_SC_CONNECT_INVALID_PARAM | NVME_SC_DNR;
 		goto out;
+	}
 
 	if (unlikely(qid > ctrl->subsys->max_qid)) {
 		pr_warn("invalid queue id (%d)\n", qid);
@@ -245,11 +256,11 @@
 	}
 
 	status = nvmet_install_queue(ctrl, req);
-	if (status) {
-		/* pass back cntlid that had the issue of installing queue */
-		req->cqe->result.u16 = cpu_to_le16(ctrl->cntlid);
+	if (status)
 		goto out_ctrl_put;
-	}
+
+	/* pass back cntlid for successful completion */
+	req->cqe->result.u16 = cpu_to_le16(ctrl->cntlid);
 
 	pr_debug("adding queue %d to ctrl %d.\n", qid, ctrl->cntlid);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvme/target/fc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvme/target/fc.c
@@ -796,6 +796,9 @@
 	int idx;
 	bool needrandom = true;
 
+	if (!tgtport->pe)
+		return NULL;
+
 	assoc = kzalloc(sizeof(*assoc), GFP_KERNEL);
 	if (!assoc)
 		return NULL;
@@ -1362,8 +1365,10 @@
 		else {
 			queue = nvmet_fc_alloc_target_queue(iod->assoc, 0,
 					be16_to_cpu(rqst->assoc_cmd.sqsize));
-			if (!queue)
+			if (!queue) {
 				ret = VERR_QUEUE_ALLOC_FAIL;
+				nvmet_fc_tgt_a_put(iod->assoc);
+			}
 		}
 	}
 
@@ -1495,20 +1500,20 @@
 nvmet_fc_ls_disconnect(struct nvmet_fc_tgtport *tgtport,
 			struct nvmet_fc_ls_iod *iod)
 {
-	struct fcnvme_ls_disconnect_rqst *rqst =
-			(struct fcnvme_ls_disconnect_rqst *)iod->rqstbuf;
-	struct fcnvme_ls_disconnect_acc *acc =
-			(struct fcnvme_ls_disconnect_acc *)iod->rspbuf;
+	struct fcnvme_ls_disconnect_assoc_rqst *rqst =
+			(struct fcnvme_ls_disconnect_assoc_rqst *)iod->rqstbuf;
+	struct fcnvme_ls_disconnect_assoc_acc *acc =
+			(struct fcnvme_ls_disconnect_assoc_acc *)iod->rspbuf;
 	struct nvmet_fc_tgt_assoc *assoc;
 	int ret = 0;
 
 	memset(acc, 0, sizeof(*acc));
 
-	if (iod->rqstdatalen < sizeof(struct fcnvme_ls_disconnect_rqst))
+	if (iod->rqstdatalen < sizeof(struct fcnvme_ls_disconnect_assoc_rqst))
 		ret = VERR_DISCONN_LEN;
 	else if (rqst->desc_list_len !=
 			fcnvme_lsdesc_len(
-				sizeof(struct fcnvme_ls_disconnect_rqst)))
+				sizeof(struct fcnvme_ls_disconnect_assoc_rqst)))
 		ret = VERR_DISCONN_RQST_LEN;
 	else if (rqst->associd.desc_tag != cpu_to_be32(FCNVME_LSDESC_ASSOC_ID))
 		ret = VERR_ASSOC_ID;
@@ -1523,8 +1528,11 @@
 			fcnvme_lsdesc_len(
 				sizeof(struct fcnvme_lsdesc_disconn_cmd)))
 		ret = VERR_DISCONN_CMD_LEN;
-	else if ((rqst->discon_cmd.scope != FCNVME_DISCONN_ASSOCIATION) &&
-			(rqst->discon_cmd.scope != FCNVME_DISCONN_CONNECTION))
+	/*
+	 * As the standard changed on the LS, check if old format and scope
+	 * something other than Association (e.g. 0).
+	 */
+	else if (rqst->discon_cmd.rsvd8[0])
 		ret = VERR_DISCONN_SCOPE;
 	else {
 		/* match an active association */
@@ -1556,8 +1564,8 @@
 
 	nvmet_fc_format_rsp_hdr(acc, FCNVME_LS_ACC,
 			fcnvme_lsdesc_len(
-				sizeof(struct fcnvme_ls_disconnect_acc)),
-			FCNVME_LS_DISCONNECT);
+				sizeof(struct fcnvme_ls_disconnect_assoc_acc)),
+			FCNVME_LS_DISCONNECT_ASSOC);
 
 	/* release get taken in nvmet_fc_find_target_assoc */
 	nvmet_fc_tgt_a_put(iod->assoc);
@@ -1632,7 +1640,7 @@
 		/* Creates an IO Queue/Connection */
 		nvmet_fc_ls_create_connection(tgtport, iod);
 		break;
-	case FCNVME_LS_DISCONNECT:
+	case FCNVME_LS_DISCONNECT_ASSOC:
 		/* Terminate a Queue/Connection or the Association */
 		nvmet_fc_ls_disconnect(tgtport, iod);
 		break;
@@ -1994,9 +2002,9 @@
 			return;
 		if (fcpreq->fcp_error ||
 		    fcpreq->transferred_length != fcpreq->transfer_length) {
-			spin_lock(&fod->flock);
+			spin_lock_irqsave(&fod->flock, flags);
 			fod->abort = true;
-			spin_unlock(&fod->flock);
+			spin_unlock_irqrestore(&fod->flock, flags);
 
 			nvmet_req_complete(&fod->req, NVME_SC_INTERNAL);
 			return;
@@ -2152,13 +2160,6 @@
 	int ret;
 
 	/*
-	 * if there is no nvmet mapping to the targetport there
-	 * shouldn't be requests. just terminate them.
-	 */
-	if (!tgtport->pe)
-		goto transport_error;
-
-	/*
 	 * Fused commands are currently not supported in the linux
 	 * implementation.
 	 *
@@ -2185,6 +2186,8 @@
 
 	fod->req.cmd = &fod->cmdiubuf.sqe;
 	fod->req.cqe = &fod->rspiubuf.cqe;
+	if (!tgtport->pe)
+		goto transport_error;
 	fod->req.port = tgtport->pe->port;
 
 	/* clear any response payload */
@@ -2299,7 +2302,7 @@
 
 	/* validate iu, so the connection id can be used to find the queue */
 	if ((cmdiubuf_len != sizeof(*cmdiu)) ||
-			(cmdiu->scsi_id != NVME_CMD_SCSI_ID) ||
+			(cmdiu->format_id != NVME_CMD_FORMAT_ID) ||
 			(cmdiu->fc_id != NVME_CMD_FC_ID) ||
 			(be16_to_cpu(cmdiu->iu_len) != (sizeof(*cmdiu)/4)))
 		return -EIO;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvme/target/fcloop.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvme/target/fcloop.c
@@ -431,10 +431,11 @@
 	struct fcloop_fcpreq *tfcp_req =
 		container_of(work, struct fcloop_fcpreq, fcp_rcv_work);
 	struct nvmefc_fcp_req *fcpreq = tfcp_req->fcpreq;
+	unsigned long flags;
 	int ret = 0;
 	bool aborted = false;
 
-	spin_lock_irq(&tfcp_req->reqlock);
+	spin_lock_irqsave(&tfcp_req->reqlock, flags);
 	switch (tfcp_req->inistate) {
 	case INI_IO_START:
 		tfcp_req->inistate = INI_IO_ACTIVE;
@@ -443,11 +444,11 @@
 		aborted = true;
 		break;
 	default:
-		spin_unlock_irq(&tfcp_req->reqlock);
+		spin_unlock_irqrestore(&tfcp_req->reqlock, flags);
 		WARN_ON(1);
 		return;
 	}
-	spin_unlock_irq(&tfcp_req->reqlock);
+	spin_unlock_irqrestore(&tfcp_req->reqlock, flags);
 
 	if (unlikely(aborted))
 		ret = -ECANCELED;
@@ -468,8 +469,9 @@
 		container_of(work, struct fcloop_fcpreq, abort_rcv_work);
 	struct nvmefc_fcp_req *fcpreq;
 	bool completed = false;
+	unsigned long flags;
 
-	spin_lock_irq(&tfcp_req->reqlock);
+	spin_lock_irqsave(&tfcp_req->reqlock, flags);
 	fcpreq = tfcp_req->fcpreq;
 	switch (tfcp_req->inistate) {
 	case INI_IO_ABORTED:
@@ -478,11 +480,11 @@
 		completed = true;
 		break;
 	default:
-		spin_unlock_irq(&tfcp_req->reqlock);
+		spin_unlock_irqrestore(&tfcp_req->reqlock, flags);
 		WARN_ON(1);
 		return;
 	}
-	spin_unlock_irq(&tfcp_req->reqlock);
+	spin_unlock_irqrestore(&tfcp_req->reqlock, flags);
 
 	if (unlikely(completed)) {
 		/* remove reference taken in original abort downcall */
@@ -494,9 +496,9 @@
 		nvmet_fc_rcv_fcp_abort(tfcp_req->tport->targetport,
 					&tfcp_req->tgt_fcp_req);
 
-	spin_lock_irq(&tfcp_req->reqlock);
+	spin_lock_irqsave(&tfcp_req->reqlock, flags);
 	tfcp_req->fcpreq = NULL;
-	spin_unlock_irq(&tfcp_req->reqlock);
+	spin_unlock_irqrestore(&tfcp_req->reqlock, flags);
 
 	fcloop_call_host_done(fcpreq, tfcp_req, -ECANCELED);
 	/* call_host_done releases reference for abort downcall */
@@ -512,11 +514,12 @@
 	struct fcloop_fcpreq *tfcp_req =
 		container_of(work, struct fcloop_fcpreq, tio_done_work);
 	struct nvmefc_fcp_req *fcpreq;
+	unsigned long flags;
 
-	spin_lock_irq(&tfcp_req->reqlock);
+	spin_lock_irqsave(&tfcp_req->reqlock, flags);
 	fcpreq = tfcp_req->fcpreq;
 	tfcp_req->inistate = INI_IO_COMPLETED;
-	spin_unlock_irq(&tfcp_req->reqlock);
+	spin_unlock_irqrestore(&tfcp_req->reqlock, flags);
 
 	fcloop_call_host_done(fcpreq, tfcp_req, tfcp_req->status);
 }
@@ -620,13 +623,14 @@
 	u32 rsplen = 0, xfrlen = 0;
 	int fcp_err = 0, active, aborted;
 	u8 op = tgt_fcpreq->op;
+	unsigned long flags;
 
-	spin_lock_irq(&tfcp_req->reqlock);
+	spin_lock_irqsave(&tfcp_req->reqlock, flags);
 	fcpreq = tfcp_req->fcpreq;
 	active = tfcp_req->active;
 	aborted = tfcp_req->aborted;
 	tfcp_req->active = true;
-	spin_unlock_irq(&tfcp_req->reqlock);
+	spin_unlock_irqrestore(&tfcp_req->reqlock, flags);
 
 	if (unlikely(active))
 		/* illegal - call while i/o active */
@@ -634,9 +638,9 @@
 
 	if (unlikely(aborted)) {
 		/* target transport has aborted i/o prior */
-		spin_lock_irq(&tfcp_req->reqlock);
+		spin_lock_irqsave(&tfcp_req->reqlock, flags);
 		tfcp_req->active = false;
-		spin_unlock_irq(&tfcp_req->reqlock);
+		spin_unlock_irqrestore(&tfcp_req->reqlock, flags);
 		tgt_fcpreq->transferred_length = 0;
 		tgt_fcpreq->fcp_error = -ECANCELED;
 		tgt_fcpreq->done(tgt_fcpreq);
@@ -693,9 +697,9 @@
 		break;
 	}
 
-	spin_lock_irq(&tfcp_req->reqlock);
+	spin_lock_irqsave(&tfcp_req->reqlock, flags);
 	tfcp_req->active = false;
-	spin_unlock_irq(&tfcp_req->reqlock);
+	spin_unlock_irqrestore(&tfcp_req->reqlock, flags);
 
 	tgt_fcpreq->transferred_length = xfrlen;
 	tgt_fcpreq->fcp_error = fcp_err;
@@ -709,15 +713,16 @@
 			struct nvmefc_tgt_fcp_req *tgt_fcpreq)
 {
 	struct fcloop_fcpreq *tfcp_req = tgt_fcp_req_to_fcpreq(tgt_fcpreq);
+	unsigned long flags;
 
 	/*
 	 * mark aborted only in case there were 2 threads in transport
 	 * (one doing io, other doing abort) and only kills ops posted
 	 * after the abort request
 	 */
-	spin_lock_irq(&tfcp_req->reqlock);
+	spin_lock_irqsave(&tfcp_req->reqlock, flags);
 	tfcp_req->aborted = true;
-	spin_unlock_irq(&tfcp_req->reqlock);
+	spin_unlock_irqrestore(&tfcp_req->reqlock, flags);
 
 	tfcp_req->status = NVME_SC_INTERNAL;
 
@@ -753,6 +758,7 @@
 	struct fcloop_ini_fcpreq *inireq = fcpreq->private;
 	struct fcloop_fcpreq *tfcp_req;
 	bool abortio = true;
+	unsigned long flags;
 
 	spin_lock(&inireq->inilock);
 	tfcp_req = inireq->tfcp_req;
@@ -765,7 +771,7 @@
 		return;
 
 	/* break initiator/target relationship for io */
-	spin_lock_irq(&tfcp_req->reqlock);
+	spin_lock_irqsave(&tfcp_req->reqlock, flags);
 	switch (tfcp_req->inistate) {
 	case INI_IO_START:
 	case INI_IO_ACTIVE:
@@ -775,11 +781,11 @@
 		abortio = false;
 		break;
 	default:
-		spin_unlock_irq(&tfcp_req->reqlock);
+		spin_unlock_irqrestore(&tfcp_req->reqlock, flags);
 		WARN_ON(1);
 		return;
 	}
-	spin_unlock_irq(&tfcp_req->reqlock);
+	spin_unlock_irqrestore(&tfcp_req->reqlock, flags);
 
 	if (abortio)
 		/* leave the reference while the work item is scheduled */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvme/target/io-cmd-bdev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvme/target/io-cmd-bdev.c
@@ -36,7 +36,7 @@
 	 */
 	id->nsfeat |= 1 << 4;
 	/* NPWG = Namespace Preferred Write Granularity. 0's based */
-	id->npwg = lpp0b;
+	id->npwg = to0based(bdev_io_min(bdev) / bdev_logical_block_size(bdev));
 	/* NPWA = Namespace Preferred Write Alignment. 0's based */
 	id->npwa = id->npwg;
 	/* NPDG = Namespace Preferred Deallocate Granularity. 0's based */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvme/target/io-cmd-file.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvme/target/io-cmd-file.c
@@ -8,6 +8,7 @@
 #include <linux/uio.h>
 #include <linux/falloc.h>
 #include <linux/file.h>
+#include <linux/fs.h>
 #include "nvmet.h"
 
 #define NVMET_MAX_MPOOL_BVEC		16
@@ -38,9 +39,11 @@
 
 	ns->file = filp_open(ns->device_path, flags, 0);
 	if (IS_ERR(ns->file)) {
-		pr_err("failed to open file %s: (%ld)\n",
-				ns->device_path, PTR_ERR(ns->file));
-		return PTR_ERR(ns->file);
+		ret = PTR_ERR(ns->file);
+		pr_err("failed to open file %s: (%d)\n",
+			ns->device_path, ret);
+		ns->file = NULL;
+		return ret;
 	}
 
 	ret = vfs_getattr(&ns->file->f_path,
@@ -252,7 +255,8 @@
 
 	if (req->ns->buffered_io) {
 		if (likely(!req->f.mpool_alloc) &&
-				nvmet_file_execute_io(req, IOCB_NOWAIT))
+		    (req->ns->file->f_mode & FMODE_NOWAIT) &&
+		    nvmet_file_execute_io(req, IOCB_NOWAIT))
 			return;
 		nvmet_file_submit_buffered_io(req);
 	} else
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvme/target/loop.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvme/target/loop.c
@@ -252,7 +252,8 @@
 
 static void nvme_loop_destroy_admin_queue(struct nvme_loop_ctrl *ctrl)
 {
-	clear_bit(NVME_LOOP_Q_LIVE, &ctrl->queues[0].flags);
+	if (!test_and_clear_bit(NVME_LOOP_Q_LIVE, &ctrl->queues[0].flags))
+		return;
 	nvmet_sq_destroy(&ctrl->queues[0].nvme_sq);
 	blk_cleanup_queue(ctrl->ctrl.admin_q);
 	blk_cleanup_queue(ctrl->ctrl.fabrics_q);
@@ -288,6 +289,7 @@
 		clear_bit(NVME_LOOP_Q_LIVE, &ctrl->queues[i].flags);
 		nvmet_sq_destroy(&ctrl->queues[i].nvme_sq);
 	}
+	ctrl->ctrl.queue_count = 1;
 }
 
 static int nvme_loop_init_io_queues(struct nvme_loop_ctrl *ctrl)
@@ -394,6 +396,7 @@
 	return 0;
 
 out_cleanup_queue:
+	clear_bit(NVME_LOOP_Q_LIVE, &ctrl->queues[0].flags);
 	blk_cleanup_queue(ctrl->ctrl.admin_q);
 out_cleanup_fabrics_q:
 	blk_cleanup_queue(ctrl->ctrl.fabrics_q);
@@ -619,8 +622,6 @@
 	dev_info(ctrl->ctrl.device,
 		 "new ctrl: \"%s\"\n", ctrl->ctrl.opts->subsysnqn);
 
-	nvme_get_ctrl(&ctrl->ctrl);
-
 	changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_LIVE);
 	WARN_ON_ONCE(!changed);
 
@@ -638,6 +639,7 @@
 	kfree(ctrl->queues);
 out_uninit_ctrl:
 	nvme_uninit_ctrl(&ctrl->ctrl);
+	nvme_put_ctrl(&ctrl->ctrl);
 out_put_ctrl:
 	nvme_put_ctrl(&ctrl->ctrl);
 	if (ret > 0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvme/target/nvmet.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvme/target/nvmet.h
@@ -394,8 +394,9 @@
 void nvmet_update_cc(struct nvmet_ctrl *ctrl, u32 new);
 u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn,
 		struct nvmet_req *req, u32 kato, struct nvmet_ctrl **ctrlp);
-u16 nvmet_ctrl_find_get(const char *subsysnqn, const char *hostnqn, u16 cntlid,
-		struct nvmet_req *req, struct nvmet_ctrl **ret);
+struct nvmet_ctrl *nvmet_ctrl_find_get(const char *subsysnqn,
+				       const char *hostnqn, u16 cntlid,
+				       struct nvmet_req *req);
 void nvmet_ctrl_put(struct nvmet_ctrl *ctrl);
 u16 nvmet_check_ctrl_status(struct nvmet_req *req, struct nvme_command *cmd);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvme/target/rdma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvme/target/rdma.c
@@ -75,6 +75,7 @@
 
 struct nvmet_rdma_queue {
 	struct rdma_cm_id	*cm_id;
+	struct ib_qp		*qp;
 	struct nvmet_port	*port;
 	struct ib_cq		*cq;
 	atomic_t		sq_wr_avail;
@@ -427,12 +428,8 @@
 	return 0;
 
 out_free:
-	while (--i >= 0) {
-		struct nvmet_rdma_rsp *rsp = &queue->rsps[i];
-
-		list_del(&rsp->free_list);
-		nvmet_rdma_free_rsp(ndev, rsp);
-	}
+	while (--i >= 0)
+		nvmet_rdma_free_rsp(ndev, &queue->rsps[i]);
 	kfree(queue->rsps);
 out:
 	return ret;
@@ -443,12 +440,8 @@
 	struct nvmet_rdma_device *ndev = queue->dev;
 	int i, nr_rsps = queue->recv_queue_size * 2;
 
-	for (i = 0; i < nr_rsps; i++) {
-		struct nvmet_rdma_rsp *rsp = &queue->rsps[i];
-
-		list_del(&rsp->free_list);
-		nvmet_rdma_free_rsp(ndev, rsp);
-	}
+	for (i = 0; i < nr_rsps; i++)
+		nvmet_rdma_free_rsp(ndev, &queue->rsps[i]);
 	kfree(queue->rsps);
 }
 
@@ -464,7 +457,7 @@
 	if (ndev->srq)
 		ret = ib_post_srq_recv(ndev->srq, &cmd->wr, NULL);
 	else
-		ret = ib_post_recv(cmd->queue->cm_id->qp, &cmd->wr, NULL);
+		ret = ib_post_recv(cmd->queue->qp, &cmd->wr, NULL);
 
 	if (unlikely(ret))
 		pr_err("post_recv cmd failed\n");
@@ -503,7 +496,7 @@
 	atomic_add(1 + rsp->n_rdma, &queue->sq_wr_avail);
 
 	if (rsp->n_rdma) {
-		rdma_rw_ctx_destroy(&rsp->rw, queue->cm_id->qp,
+		rdma_rw_ctx_destroy(&rsp->rw, queue->qp,
 				queue->cm_id->port_num, rsp->req.sg,
 				rsp->req.sg_cnt, nvmet_data_dir(&rsp->req));
 	}
@@ -587,7 +580,7 @@
 
 	WARN_ON(rsp->n_rdma <= 0);
 	atomic_add(rsp->n_rdma, &queue->sq_wr_avail);
-	rdma_rw_ctx_destroy(&rsp->rw, queue->cm_id->qp,
+	rdma_rw_ctx_destroy(&rsp->rw, queue->qp,
 			queue->cm_id->port_num, rsp->req.sg,
 			rsp->req.sg_cnt, nvmet_data_dir(&rsp->req));
 	rsp->n_rdma = 0;
@@ -742,7 +735,7 @@
 	}
 
 	if (nvmet_rdma_need_data_in(rsp)) {
-		if (rdma_rw_ctx_post(&rsp->rw, queue->cm_id->qp,
+		if (rdma_rw_ctx_post(&rsp->rw, queue->qp,
 				queue->cm_id->port_num, &rsp->read_cqe, NULL))
 			nvmet_req_complete(&rsp->req, NVME_SC_DATA_XFER_ERROR);
 	} else {
@@ -784,6 +777,27 @@
 	nvmet_req_complete(&cmd->req, status);
 }
 
+static bool nvmet_rdma_recv_not_live(struct nvmet_rdma_queue *queue,
+		struct nvmet_rdma_rsp *rsp)
+{
+	unsigned long flags;
+	bool ret = true;
+
+	spin_lock_irqsave(&queue->state_lock, flags);
+	/*
+	 * recheck queue state is not live to prevent a race condition
+	 * with RDMA_CM_EVENT_ESTABLISHED handler.
+	 */
+	if (queue->state == NVMET_RDMA_Q_LIVE)
+		ret = false;
+	else if (queue->state == NVMET_RDMA_Q_CONNECTING)
+		list_add_tail(&rsp->wait_list, &queue->rsp_wait_list);
+	else
+		nvmet_rdma_put_rsp(rsp);
+	spin_unlock_irqrestore(&queue->state_lock, flags);
+	return ret;
+}
+
 static void nvmet_rdma_recv_done(struct ib_cq *cq, struct ib_wc *wc)
 {
 	struct nvmet_rdma_cmd *cmd =
@@ -825,17 +839,9 @@
 	rsp->req.port = queue->port;
 	rsp->n_rdma = 0;
 
-	if (unlikely(queue->state != NVMET_RDMA_Q_LIVE)) {
-		unsigned long flags;
-
-		spin_lock_irqsave(&queue->state_lock, flags);
-		if (queue->state == NVMET_RDMA_Q_CONNECTING)
-			list_add_tail(&rsp->wait_list, &queue->rsp_wait_list);
-		else
-			nvmet_rdma_put_rsp(rsp);
-		spin_unlock_irqrestore(&queue->state_lock, flags);
+	if (unlikely(queue->state != NVMET_RDMA_Q_LIVE) &&
+	    nvmet_rdma_recv_not_live(queue, rsp))
 		return;
-	}
 
 	nvmet_rdma_handle_command(queue, rsp);
 }
@@ -1025,6 +1031,7 @@
 		pr_err("failed to create_qp ret= %d\n", ret);
 		goto err_destroy_cq;
 	}
+	queue->qp = queue->cm_id->qp;
 
 	atomic_set(&queue->sq_wr_avail, qp_attr.cap.max_send_wr);
 
@@ -1053,11 +1060,10 @@
 
 static void nvmet_rdma_destroy_queue_ib(struct nvmet_rdma_queue *queue)
 {
-	struct ib_qp *qp = queue->cm_id->qp;
-
-	ib_drain_qp(qp);
-	rdma_destroy_id(queue->cm_id);
-	ib_destroy_qp(qp);
+	ib_drain_qp(queue->qp);
+	if (queue->cm_id)
+		rdma_destroy_id(queue->cm_id);
+	ib_destroy_qp(queue->qp);
 	ib_free_cq(queue->cq);
 }
 
@@ -1291,9 +1297,12 @@
 
 	ret = nvmet_rdma_cm_accept(cm_id, queue, &event->param.conn);
 	if (ret) {
-		schedule_work(&queue->release_work);
-		/* Destroying rdma_cm id is not needed here */
-		return 0;
+		/*
+		 * Don't destroy the cm_id in free path, as we implicitly
+		 * destroy the cm_id here with non-zero ret code.
+		 */
+		queue->cm_id = NULL;
+		goto free_queue;
 	}
 
 	mutex_lock(&nvmet_rdma_queue_mutex);
@@ -1302,6 +1311,8 @@
 
 	return 0;
 
+free_queue:
+	nvmet_rdma_free_queue(queue);
 put_device:
 	kref_put(&ndev->ref, nvmet_rdma_free_dev);
 
@@ -1345,6 +1356,16 @@
 	spin_lock_irqsave(&queue->state_lock, flags);
 	switch (queue->state) {
 	case NVMET_RDMA_Q_CONNECTING:
+		while (!list_empty(&queue->rsp_wait_list)) {
+			struct nvmet_rdma_rsp *rsp;
+
+			rsp = list_first_entry(&queue->rsp_wait_list,
+					       struct nvmet_rdma_rsp,
+					       wait_list);
+			list_del(&rsp->wait_list);
+			nvmet_rdma_put_rsp(rsp);
+		}
+		fallthrough;
 	case NVMET_RDMA_Q_LIVE:
 		queue->state = NVMET_RDMA_Q_DISCONNECTING;
 		disconnect = true;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvme/target/tcp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvme/target/tcp.c
@@ -18,6 +18,7 @@
 #include "nvmet.h"
 
 #define NVMET_TCP_DEF_INLINE_DATA_SIZE	(4 * PAGE_SIZE)
+#define NVMET_TCP_MAXH2CDATA		0x400000 /* 16M arbitrary limit */
 
 #define NVMET_TCP_RECV_BUDGET		8
 #define NVMET_TCP_SEND_BUDGET		8
@@ -150,6 +151,11 @@
 static inline u16 nvmet_tcp_cmd_tag(struct nvmet_tcp_queue *queue,
 		struct nvmet_tcp_cmd *cmd)
 {
+	if (unlikely(!queue->nr_cmds)) {
+		/* We didn't allocate cmds yet, send 0xffff */
+		return USHRT_MAX;
+	}
+
 	return cmd - queue->cmds;
 }
 
@@ -287,7 +293,7 @@
 	length = cmd->pdu_len;
 	cmd->nr_mapped = DIV_ROUND_UP(length, PAGE_SIZE);
 	offset = cmd->rbytes_done;
-	cmd->sg_idx = DIV_ROUND_UP(offset, PAGE_SIZE);
+	cmd->sg_idx = offset / PAGE_SIZE;
 	sg_offset = offset % PAGE_SIZE;
 	sg = &cmd->req.sg[cmd->sg_idx];
 
@@ -300,6 +306,7 @@
 		length -= iov_len;
 		sg = sg_next(sg);
 		iov++;
+		sg_offset = 0;
 	}
 
 	iov_iter_kvec(&cmd->recv_msg.msg_iter, READ, cmd->iov,
@@ -315,6 +322,15 @@
 		kernel_sock_shutdown(queue->sock, SHUT_RDWR);
 }
 
+static void nvmet_tcp_socket_error(struct nvmet_tcp_queue *queue, int status)
+{
+	queue->rcv_state = NVMET_TCP_RECV_ERR;
+	if (status == -EPIPE || status == -ECONNRESET)
+		kernel_sock_shutdown(queue->sock, SHUT_RDWR);
+	else
+		nvmet_tcp_fatal_error(queue);
+}
+
 static int nvmet_tcp_map_data(struct nvmet_tcp_cmd *cmd)
 {
 	struct nvme_sgl_desc *sgl = &cmd->req.cmd->common.dptr.sgl;
@@ -515,7 +531,7 @@
 	return 1;
 }
 
-static int nvmet_try_send_data(struct nvmet_tcp_cmd *cmd)
+static int nvmet_try_send_data(struct nvmet_tcp_cmd *cmd, bool last_in_batch)
 {
 	struct nvmet_tcp_queue *queue = cmd->queue;
 	int ret;
@@ -523,9 +539,15 @@
 	while (cmd->cur_sg) {
 		struct page *page = sg_page(cmd->cur_sg);
 		u32 left = cmd->cur_sg->length - cmd->offset;
+		int flags = MSG_DONTWAIT;
+
+		if ((!last_in_batch && cmd->queue->send_list_len) ||
+		    cmd->wbytes_done + left < cmd->req.transfer_len ||
+		    queue->data_digest || !queue->nvme_sq.sqhd_disabled)
+			flags |= MSG_MORE;
 
 		ret = kernel_sendpage(cmd->queue->sock, page, cmd->offset,
-					left, MSG_DONTWAIT | MSG_MORE);
+					left, flags);
 		if (ret <= 0)
 			return ret;
 
@@ -619,10 +641,11 @@
 static int nvmet_try_send_ddgst(struct nvmet_tcp_cmd *cmd)
 {
 	struct nvmet_tcp_queue *queue = cmd->queue;
+	int left = NVME_TCP_DIGEST_LENGTH - cmd->offset;
 	struct msghdr msg = { .msg_flags = MSG_DONTWAIT };
 	struct kvec iov = {
-		.iov_base = &cmd->exp_ddgst + cmd->offset,
-		.iov_len = NVME_TCP_DIGEST_LENGTH - cmd->offset
+		.iov_base = (u8 *)&cmd->exp_ddgst + cmd->offset,
+		.iov_len = left
 	};
 	int ret;
 
@@ -631,6 +654,10 @@
 		return ret;
 
 	cmd->offset += ret;
+	left -= ret;
+
+	if (left)
+		return -EAGAIN;
 
 	if (queue->nvme_sq.sqhd_disabled) {
 		cmd->queue->snd_cmd = NULL;
@@ -660,7 +687,7 @@
 	}
 
 	if (cmd->state == NVMET_TCP_SEND_DATA) {
-		ret = nvmet_try_send_data(cmd);
+		ret = nvmet_try_send_data(cmd, last_in_batch);
 		if (ret <= 0)
 			goto done_send;
 	}
@@ -697,11 +724,15 @@
 
 	for (i = 0; i < budget; i++) {
 		ret = nvmet_tcp_try_send_one(queue, i == budget - 1);
-		if (ret <= 0)
+		if (unlikely(ret < 0)) {
+			nvmet_tcp_socket_error(queue, ret);
+			goto done;
+		} else if (ret == 0) {
 			break;
+		}
 		(*sends)++;
 	}
-
+done:
 	return ret;
 }
 
@@ -761,6 +792,7 @@
 		pr_err("bad nvme-tcp pdu length (%d)\n",
 			le32_to_cpu(icreq->hdr.plen));
 		nvmet_tcp_fatal_error(queue);
+		return -EPROTO;
 	}
 
 	if (icreq->pfv != NVME_TCP_PFV_1_0) {
@@ -788,7 +820,7 @@
 	icresp->hdr.pdo = 0;
 	icresp->hdr.plen = cpu_to_le32(icresp->hdr.hlen);
 	icresp->pfv = cpu_to_le16(NVME_TCP_PFV_1_0);
-	icresp->maxdata = cpu_to_le32(0xffff); /* FIXME: support r2t */
+	icresp->maxdata = cpu_to_le32(NVMET_TCP_MAXH2CDATA);
 	icresp->cpda = 0;
 	if (queue->hdr_digest)
 		icresp->digest |= NVME_TCP_HDR_DIGEST_ENABLE;
@@ -799,15 +831,11 @@
 	iov.iov_len = sizeof(*icresp);
 	ret = kernel_sendmsg(queue->sock, &msg, &iov, 1, iov.iov_len);
 	if (ret < 0)
-		goto free_crypto;
+		return ret; /* queue removal will cleanup */
 
 	queue->state = NVMET_TCP_Q_LIVE;
 	nvmet_prepare_receive_pdu(queue);
 	return 0;
-free_crypto:
-	if (queue->hdr_digest || queue->data_digest)
-		nvmet_tcp_free_crypto(queue);
-	return ret;
 }
 
 static void nvmet_tcp_handle_req_failure(struct nvmet_tcp_queue *queue,
@@ -840,20 +868,43 @@
 {
 	struct nvme_tcp_data_pdu *data = &queue->pdu.data;
 	struct nvmet_tcp_cmd *cmd;
+	unsigned int exp_data_len;
 
-	cmd = &queue->cmds[data->ttag];
+	if (likely(queue->nr_cmds)) {
+		if (unlikely(data->ttag >= queue->nr_cmds)) {
+			pr_err("queue %d: received out of bound ttag %u, nr_cmds %u\n",
+				queue->idx, data->ttag, queue->nr_cmds);
+			nvmet_tcp_fatal_error(queue);
+			return -EPROTO;
+		}
+		cmd = &queue->cmds[data->ttag];
+	} else {
+		cmd = &queue->connect;
+	}
 
 	if (le32_to_cpu(data->data_offset) != cmd->rbytes_done) {
 		pr_err("ttag %u unexpected data offset %u (expected %u)\n",
 			data->ttag, le32_to_cpu(data->data_offset),
 			cmd->rbytes_done);
 		/* FIXME: use path and transport errors */
-		nvmet_req_complete(&cmd->req,
-			NVME_SC_INVALID_FIELD | NVME_SC_DNR);
+		nvmet_tcp_fatal_error(queue);
 		return -EPROTO;
 	}
 
+	exp_data_len = le32_to_cpu(data->hdr.plen) -
+			nvmet_tcp_hdgst_len(queue) -
+			nvmet_tcp_ddgst_len(queue) -
+			sizeof(*data);
+
 	cmd->pdu_len = le32_to_cpu(data->data_length);
+	if (unlikely(cmd->pdu_len != exp_data_len ||
+		     cmd->pdu_len == 0 ||
+		     cmd->pdu_len > NVMET_TCP_MAXH2CDATA)) {
+		pr_err("H2CData PDU len %u is invalid\n", cmd->pdu_len);
+		/* FIXME: use proper transport errors */
+		nvmet_tcp_fatal_error(queue);
+		return -EPROTO;
+	}
 	cmd->pdu_recv = 0;
 	nvmet_tcp_map_pdu_iovec(cmd);
 	queue->cmd = cmd;
@@ -1005,7 +1056,7 @@
 	}
 
 	if (queue->hdr_digest &&
-	    nvmet_tcp_verify_hdgst(queue, &queue->pdu, queue->offset)) {
+	    nvmet_tcp_verify_hdgst(queue, &queue->pdu, hdr->hlen)) {
 		nvmet_tcp_fatal_error(queue); /* fatal */
 		return -EPROTO;
 	}
@@ -1140,11 +1191,15 @@
 
 	for (i = 0; i < budget; i++) {
 		ret = nvmet_tcp_try_recv_one(queue);
-		if (ret <= 0)
+		if (unlikely(ret < 0)) {
+			nvmet_tcp_socket_error(queue, ret);
+			goto done;
+		} else if (ret == 0) {
 			break;
+		}
 		(*recvs)++;
 	}
-
+done:
 	return ret;
 }
 
@@ -1169,27 +1224,16 @@
 		pending = false;
 
 		ret = nvmet_tcp_try_recv(queue, NVMET_TCP_RECV_BUDGET, &ops);
-		if (ret > 0) {
+		if (ret > 0)
 			pending = true;
-		} else if (ret < 0) {
-			if (ret == -EPIPE || ret == -ECONNRESET)
-				kernel_sock_shutdown(queue->sock, SHUT_RDWR);
-			else
-				nvmet_tcp_fatal_error(queue);
+		else if (ret < 0)
 			return;
-		}
 
 		ret = nvmet_tcp_try_send(queue, NVMET_TCP_SEND_BUDGET, &ops);
-		if (ret > 0) {
-			/* transmitted message/data */
+		if (ret > 0)
 			pending = true;
-		} else if (ret < 0) {
-			if (ret == -EPIPE || ret == -ECONNRESET)
-				kernel_sock_shutdown(queue->sock, SHUT_RDWR);
-			else
-				nvmet_tcp_fatal_error(queue);
+		else if (ret < 0)
 			return;
-		}
 
 	} while (pending && ops < NVMET_TCP_IO_WORK_BUDGET);
 
@@ -1328,6 +1372,7 @@
 
 static void nvmet_tcp_release_queue_work(struct work_struct *w)
 {
+	struct page *page;
 	struct nvmet_tcp_queue *queue =
 		container_of(w, struct nvmet_tcp_queue, release_work);
 
@@ -1347,6 +1392,8 @@
 		nvmet_tcp_free_crypto(queue);
 	ida_simple_remove(&nvmet_tcp_queue_ida, queue->idx);
 
+	page = virt_to_head_page(queue->pf_cache.va);
+	__page_frag_cache_drain(page, queue->pf_cache.pagecnt_bias);
 	kfree(queue);
 }
 
@@ -1387,17 +1434,19 @@
 {
 	struct nvmet_tcp_queue *queue;
 
-	write_lock_bh(&sk->sk_callback_lock);
+	read_lock_bh(&sk->sk_callback_lock);
 	queue = sk->sk_user_data;
 	if (!queue)
 		goto done;
 
 	switch (sk->sk_state) {
+	case TCP_FIN_WAIT2:
+	case TCP_LAST_ACK:
+		break;
 	case TCP_FIN_WAIT1:
 	case TCP_CLOSE_WAIT:
 	case TCP_CLOSE:
 		/* FALLTHRU */
-		sk->sk_user_data = NULL;
 		nvmet_tcp_schedule_release_queue(queue);
 		break;
 	default:
@@ -1405,7 +1454,7 @@
 			queue->idx, sk->sk_state);
 	}
 done:
-	write_unlock_bh(&sk->sk_callback_lock);
+	read_unlock_bh(&sk->sk_callback_lock);
 }
 
 static int nvmet_tcp_set_queue_sock(struct nvmet_tcp_queue *queue)
@@ -1650,6 +1699,17 @@
 	return ret;
 }
 
+static void nvmet_tcp_destroy_port_queues(struct nvmet_tcp_port *port)
+{
+	struct nvmet_tcp_queue *queue;
+
+	mutex_lock(&nvmet_tcp_queue_mutex);
+	list_for_each_entry(queue, &nvmet_tcp_queue_list, queue_list)
+		if (queue->port == port)
+			kernel_sock_shutdown(queue->sock, SHUT_RDWR);
+	mutex_unlock(&nvmet_tcp_queue_mutex);
+}
+
 static void nvmet_tcp_remove_port(struct nvmet_port *nport)
 {
 	struct nvmet_tcp_port *port = nport->priv;
@@ -1659,6 +1719,11 @@
 	port->sock->sk->sk_user_data = NULL;
 	write_unlock_bh(&port->sock->sk->sk_callback_lock);
 	cancel_work_sync(&port->accept_work);
+	/*
+	 * Destroy the remaining queues, which are not belong to any
+	 * controller yet.
+	 */
+	nvmet_tcp_destroy_port_queues(port);
 
 	sock_release(port->sock);
 	kfree(port);
@@ -1686,8 +1751,10 @@
 	}
 
 	queue->nr_cmds = sq->size * 2;
-	if (nvmet_tcp_alloc_cmds(queue))
+	if (nvmet_tcp_alloc_cmds(queue)) {
+		queue->nr_cmds = 0;
 		return NVME_SC_INTERNAL;
+	}
 	return 0;
 }
 
@@ -1724,7 +1791,8 @@
 {
 	int ret;
 
-	nvmet_tcp_wq = alloc_workqueue("nvmet_tcp_wq", WQ_HIGHPRI, 0);
+	nvmet_tcp_wq = alloc_workqueue("nvmet_tcp_wq",
+				WQ_MEM_RECLAIM | WQ_HIGHPRI, 0);
 	if (!nvmet_tcp_wq)
 		return -ENOMEM;
 
@@ -1752,6 +1820,7 @@
 	flush_scheduled_work();
 
 	destroy_workqueue(nvmet_tcp_wq);
+	ida_destroy(&nvmet_tcp_queue_ida);
 }
 
 module_init(nvmet_tcp_init);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvme/target/trace.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvme/target/trace.c
@@ -195,7 +195,7 @@
 	return ret;
 }
 
-const char *nvmet_trace_ctrl_name(struct trace_seq *p, struct nvmet_ctrl *ctrl)
+const char *nvmet_trace_ctrl_id(struct trace_seq *p, u16 ctrl_id)
 {
 	const char *ret = trace_seq_buffer_ptr(p);
 
@@ -208,8 +208,8 @@
 	 * If we can know the extra data of the connect command in this stage,
 	 * we can update this print statement later.
 	 */
-	if (ctrl)
-		trace_seq_printf(p, "%d", ctrl->cntlid);
+	if (ctrl_id)
+		trace_seq_printf(p, "%d", ctrl_id);
 	else
 		trace_seq_printf(p, "_");
 	trace_seq_putc(p, 0);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvme/target/trace.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvme/target/trace.h
@@ -32,33 +32,32 @@
 	 nvmet_trace_parse_nvm_cmd(p, opcode, cdw10) :			\
 	 nvmet_trace_parse_admin_cmd(p, opcode, cdw10)))
 
-const char *nvmet_trace_ctrl_name(struct trace_seq *p, struct nvmet_ctrl *ctrl);
-#define __print_ctrl_name(ctrl)				\
-	nvmet_trace_ctrl_name(p, ctrl)
+const char *nvmet_trace_ctrl_id(struct trace_seq *p, u16 ctrl_id);
+#define __print_ctrl_id(ctrl_id)			\
+	nvmet_trace_ctrl_id(p, ctrl_id)
 
 const char *nvmet_trace_disk_name(struct trace_seq *p, char *name);
 #define __print_disk_name(name)				\
 	nvmet_trace_disk_name(p, name)
 
 #ifndef TRACE_HEADER_MULTI_READ
-static inline struct nvmet_ctrl *nvmet_req_to_ctrl(struct nvmet_req *req)
+static inline u16 nvmet_req_to_ctrl_id(struct nvmet_req *req)
 {
-	return req->sq->ctrl;
+	/*
+	 * The queue and controller pointers are not valid until an association
+	 * has been established.
+	 */
+	if (!req->sq || !req->sq->ctrl)
+		return 0;
+	return req->sq->ctrl->cntlid;
 }
 
-static inline void __assign_disk_name(char *name, struct nvmet_req *req,
-		bool init)
+static inline void __assign_req_name(char *name, struct nvmet_req *req)
 {
-	struct nvmet_ctrl *ctrl = nvmet_req_to_ctrl(req);
-	struct nvmet_ns *ns;
-
-	if ((init && req->sq->qid) || (!init && req->cq->qid)) {
-		ns = nvmet_find_namespace(ctrl, req->cmd->rw.nsid);
-		strncpy(name, ns->device_path, DISK_NAME_LEN);
-		return;
-	}
-
-	memset(name, 0, DISK_NAME_LEN);
+	if (req->ns)
+		strncpy(name, req->ns->device_path, DISK_NAME_LEN);
+	else
+		memset(name, 0, DISK_NAME_LEN);
 }
 #endif
 
@@ -67,7 +66,7 @@
 	TP_ARGS(req, cmd),
 	TP_STRUCT__entry(
 		__field(struct nvme_command *, cmd)
-		__field(struct nvmet_ctrl *, ctrl)
+		__field(u16, ctrl_id)
 		__array(char, disk, DISK_NAME_LEN)
 		__field(int, qid)
 		__field(u16, cid)
@@ -80,8 +79,8 @@
 	),
 	TP_fast_assign(
 		__entry->cmd = cmd;
-		__entry->ctrl = nvmet_req_to_ctrl(req);
-		__assign_disk_name(__entry->disk, req, true);
+		__entry->ctrl_id = nvmet_req_to_ctrl_id(req);
+		__assign_req_name(__entry->disk, req);
 		__entry->qid = req->sq->qid;
 		__entry->cid = cmd->common.command_id;
 		__entry->opcode = cmd->common.opcode;
@@ -94,7 +93,7 @@
 	),
 	TP_printk("nvmet%s: %sqid=%d, cmdid=%u, nsid=%u, flags=%#x, "
 		  "meta=%#llx, cmd=(%s, %s)",
-		__print_ctrl_name(__entry->ctrl),
+		__print_ctrl_id(__entry->ctrl_id),
 		__print_disk_name(__entry->disk),
 		__entry->qid, __entry->cid, __entry->nsid,
 		__entry->flags, __entry->metadata,
@@ -108,7 +107,7 @@
 	TP_PROTO(struct nvmet_req *req),
 	TP_ARGS(req),
 	TP_STRUCT__entry(
-		__field(struct nvmet_ctrl *, ctrl)
+		__field(u16, ctrl_id)
 		__array(char, disk, DISK_NAME_LEN)
 		__field(int, qid)
 		__field(int, cid)
@@ -116,15 +115,15 @@
 		__field(u16, status)
 	),
 	TP_fast_assign(
-		__entry->ctrl = nvmet_req_to_ctrl(req);
+		__entry->ctrl_id = nvmet_req_to_ctrl_id(req);
 		__entry->qid = req->cq->qid;
 		__entry->cid = req->cqe->command_id;
 		__entry->result = le64_to_cpu(req->cqe->result.u64);
 		__entry->status = le16_to_cpu(req->cqe->status) >> 1;
-		__assign_disk_name(__entry->disk, req, false);
+		__assign_req_name(__entry->disk, req);
 	),
 	TP_printk("nvmet%s: %sqid=%d, cmdid=%u, res=%#llx, status=%#x",
-		__print_ctrl_name(__entry->ctrl),
+		__print_ctrl_id(__entry->ctrl_id),
 		__print_disk_name(__entry->disk),
 		__entry->qid, __entry->cid, __entry->result, __entry->status)
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvmem/core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvmem/core.c
@@ -110,7 +110,7 @@
 	list_del(&cell->node);
 	mutex_unlock(&nvmem_mutex);
 	of_node_put(cell->np);
-	kfree(cell->name);
+	kfree_const(cell->name);
 	kfree(cell);
 }
 
@@ -130,9 +130,9 @@
 	blocking_notifier_call_chain(&nvmem_notifier, NVMEM_CELL_ADD, cell);
 }
 
-static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
-				   const struct nvmem_cell_info *info,
-				   struct nvmem_cell *cell)
+static int nvmem_cell_info_to_nvmem_cell_nodup(struct nvmem_device *nvmem,
+					const struct nvmem_cell_info *info,
+					struct nvmem_cell *cell)
 {
 	cell->nvmem = nvmem;
 	cell->offset = info->offset;
@@ -149,13 +149,30 @@
 	if (!IS_ALIGNED(cell->offset, nvmem->stride)) {
 		dev_err(&nvmem->dev,
 			"cell %s unaligned to nvmem stride %d\n",
-			cell->name, nvmem->stride);
+			cell->name ?: "<unknown>", nvmem->stride);
 		return -EINVAL;
 	}
 
 	return 0;
 }
 
+static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
+				const struct nvmem_cell_info *info,
+				struct nvmem_cell *cell)
+{
+	int err;
+
+	err = nvmem_cell_info_to_nvmem_cell_nodup(nvmem, info, cell);
+	if (err)
+		return err;
+
+	cell->name = kstrdup_const(info->name, GFP_KERNEL);
+	if (!cell->name)
+		return -ENOMEM;
+
+	return 0;
+}
+
 /**
  * nvmem_add_cells() - Add cell information to an nvmem device
  *
@@ -297,17 +314,21 @@
 
 	for_each_child_of_node(parent, child) {
 		addr = of_get_property(child, "reg", &len);
-		if (!addr || (len < 2 * sizeof(u32))) {
+		if (!addr)
+			continue;
+		if (len < 2 * sizeof(u32)) {
 			dev_err(dev, "nvmem: invalid reg on %pOF\n", child);
+			of_node_put(child);
 			return -EINVAL;
 		}
 
 		cell = kzalloc(sizeof(*cell), GFP_KERNEL);
-		if (!cell)
+		if (!cell) {
+			of_node_put(child);
 			return -ENOMEM;
+		}
 
 		cell->nvmem = nvmem;
-		cell->np = of_node_get(child);
 		cell->offset = be32_to_cpup(addr++);
 		cell->bytes = be32_to_cpup(addr);
 		cell->name = kasprintf(GFP_KERNEL, "%pOFn", child);
@@ -327,11 +348,13 @@
 			dev_err(dev, "cell %s unaligned to nvmem stride %d\n",
 				cell->name, nvmem->stride);
 			/* Cells already added will be freed later. */
-			kfree(cell->name);
+			kfree_const(cell->name);
 			kfree(cell);
+			of_node_put(child);
 			return -EINVAL;
 		}
 
+		cell->np = of_node_get(child);
 		nvmem_cell_add(cell);
 	}
 
@@ -416,7 +439,7 @@
 	if (config->cells) {
 		rval = nvmem_add_cells(nvmem, config->cells, config->ncells);
 		if (rval)
-			goto err_teardown_compat;
+			goto err_remove_cells;
 	}
 
 	rval = nvmem_add_cells_from_table(nvmem);
@@ -433,7 +456,6 @@
 
 err_remove_cells:
 	nvmem_device_remove_all_cells(nvmem);
-err_teardown_compat:
 	if (config->compat)
 		nvmem_sysfs_remove_compat(nvmem, config);
 err_device_del:
@@ -662,13 +684,13 @@
 EXPORT_SYMBOL_GPL(nvmem_device_put);
 
 /**
- * devm_nvmem_device_get() - Get nvmem cell of device form a given id
+ * devm_nvmem_device_get() - Get nvmem device of device form a given id
  *
  * @dev: Device that requests the nvmem device.
  * @id: name id for the requested nvmem device.
  *
- * Return: ERR_PTR() on error or a valid pointer to a struct nvmem_cell
- * on success.  The nvmem_cell will be freed by the automatically once the
+ * Return: ERR_PTR() on error or a valid pointer to a struct nvmem_device
+ * on success.  The nvmem_device will be freed by the automatically once the
  * device is freed.
  */
 struct nvmem_device *devm_nvmem_device_get(struct device *dev, const char *id)
@@ -931,7 +953,8 @@
 		*p-- = 0;
 
 	/* clear msb bits if any leftover in the last byte */
-	*p &= GENMASK((cell->nbits%BITS_PER_BYTE) - 1, 0);
+	if (cell->nbits % BITS_PER_BYTE)
+		*p &= GENMASK((cell->nbits % BITS_PER_BYTE) - 1, 0);
 }
 
 static int __nvmem_cell_read(struct nvmem_device *nvmem,
@@ -1060,6 +1083,8 @@
 		return -EINVAL;
 
 	if (cell->bit_offset || cell->nbits) {
+		if (len != BITS_TO_BYTES(cell->nbits) && len != cell->bytes)
+			return -EINVAL;
 		buf = nvmem_cell_prepare_write_buffer(cell, buf, len);
 		if (IS_ERR(buf))
 			return PTR_ERR(buf);
@@ -1172,7 +1197,7 @@
 	if (!nvmem)
 		return -EINVAL;
 
-	rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
+	rc = nvmem_cell_info_to_nvmem_cell_nodup(nvmem, info, &cell);
 	if (rc)
 		return rc;
 
@@ -1202,7 +1227,7 @@
 	if (!nvmem)
 		return -EINVAL;
 
-	rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
+	rc = nvmem_cell_info_to_nvmem_cell_nodup(nvmem, info, &cell);
 	if (rc)
 		return rc;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvmem/imx-ocotp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvmem/imx-ocotp.c
@@ -433,7 +433,7 @@
 };
 
 static const struct ocotp_params imx6sll_params = {
-	.nregs = 128,
+	.nregs = 80,
 	.bank_address_words = 0,
 	.set_timing = imx_ocotp_set_imx6_timing,
 };
@@ -445,13 +445,13 @@
 };
 
 static const struct ocotp_params imx6ul_params = {
-	.nregs = 128,
+	.nregs = 144,
 	.bank_address_words = 0,
 	.set_timing = imx_ocotp_set_imx6_timing,
 };
 
 static const struct ocotp_params imx6ull_params = {
-	.nregs = 64,
+	.nregs = 80,
 	.bank_address_words = 0,
 	.set_timing = imx_ocotp_set_imx6_timing,
 };
@@ -521,6 +521,10 @@
 	if (IS_ERR(priv->clk))
 		return PTR_ERR(priv->clk);
 
+	clk_prepare_enable(priv->clk);
+	imx_ocotp_clr_err_if_set(priv->base);
+	clk_disable_unprepare(priv->clk);
+
 	priv->params = of_device_get_match_data(&pdev->dev);
 	imx_ocotp_nvmem_config.size = 4 * priv->params->nregs;
 	imx_ocotp_nvmem_config.dev = dev;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvmem/meson-efuse.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvmem/meson-efuse.c
@@ -17,15 +17,25 @@
 static int meson_efuse_read(void *context, unsigned int offset,
 			    void *val, size_t bytes)
 {
-	return meson_sm_call_read((u8 *)val, bytes, SM_EFUSE_READ, offset,
-				  bytes, 0, 0, 0);
+	struct meson_sm_firmware *fw = context;
+	int ret;
+
+	ret = meson_sm_call_read(fw, (u8 *)val, bytes, SM_EFUSE_READ, offset,
+				 bytes, 0, 0, 0);
+
+	return ret < 0 ? ret : 0;
 }
 
 static int meson_efuse_write(void *context, unsigned int offset,
 			     void *val, size_t bytes)
 {
-	return meson_sm_call_write((u8 *)val, bytes, SM_EFUSE_WRITE, offset,
-				   bytes, 0, 0, 0);
+	struct meson_sm_firmware *fw = context;
+	int ret;
+
+	ret = meson_sm_call_write(fw, (u8 *)val, bytes, SM_EFUSE_WRITE, offset,
+				  bytes, 0, 0, 0);
+
+	return ret < 0 ? ret : 0;
 }
 
 static const struct of_device_id meson_efuse_match[] = {
@@ -37,35 +47,29 @@
 static int meson_efuse_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
+	struct meson_sm_firmware *fw;
+	struct device_node *sm_np;
 	struct nvmem_device *nvmem;
 	struct nvmem_config *econfig;
 	struct clk *clk;
 	unsigned int size;
-	int ret;
 
-	clk = devm_clk_get(dev, NULL);
-	if (IS_ERR(clk)) {
-		ret = PTR_ERR(clk);
-		if (ret != -EPROBE_DEFER)
-			dev_err(dev, "failed to get efuse gate");
-		return ret;
+	sm_np = of_parse_phandle(pdev->dev.of_node, "secure-monitor", 0);
+	if (!sm_np) {
+		dev_err(&pdev->dev, "no secure-monitor node\n");
+		return -ENODEV;
 	}
 
-	ret = clk_prepare_enable(clk);
-	if (ret) {
-		dev_err(dev, "failed to enable gate");
-		return ret;
-	}
-
-	ret = devm_add_action_or_reset(dev,
-				       (void(*)(void *))clk_disable_unprepare,
-				       clk);
-	if (ret) {
-		dev_err(dev, "failed to add disable callback");
-		return ret;
-	}
+	fw = meson_sm_get(sm_np);
+	of_node_put(sm_np);
+	if (!fw)
+		return -EPROBE_DEFER;
+
+	clk = devm_clk_get_enabled(dev, NULL);
+	if (IS_ERR(clk))
+		return dev_err_probe(dev, PTR_ERR(clk), "failed to get efuse gate");
 
-	if (meson_sm_call(SM_EFUSE_USER_MAX, &size, 0, 0, 0, 0, 0) < 0) {
+	if (meson_sm_call(fw, SM_EFUSE_USER_MAX, &size, 0, 0, 0, 0, 0) < 0) {
 		dev_err(dev, "failed to get max user");
 		return -EINVAL;
 	}
@@ -81,6 +85,7 @@
 	econfig->reg_read = meson_efuse_read;
 	econfig->reg_write = meson_efuse_write;
 	econfig->size = size;
+	econfig->priv = fw;
 
 	nvmem = devm_nvmem_register(&pdev->dev, econfig);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvmem/nvmem-sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvmem/nvmem-sysfs.c
@@ -56,6 +56,9 @@
 
 	count = round_down(count, nvmem->word_size);
 
+	if (!nvmem->reg_read)
+		return -EPERM;
+
 	rc = nvmem->reg_read(nvmem->priv, pos, buf, count);
 
 	if (rc)
@@ -90,6 +93,9 @@
 
 	count = round_down(count, nvmem->word_size);
 
+	if (!nvmem->reg_write)
+		return -EPERM;
+
 	rc = nvmem->reg_write(nvmem->priv, pos, buf, count);
 
 	if (rc)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvmem/qfprom.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvmem/qfprom.c
@@ -27,25 +27,11 @@
 	return 0;
 }
 
-static int qfprom_reg_write(void *context,
-			 unsigned int reg, void *_val, size_t bytes)
-{
-	struct qfprom_priv *priv = context;
-	u8 *val = _val;
-	int i = 0, words = bytes;
-
-	while (words--)
-		writeb(*val++, priv->base + reg + i++);
-
-	return 0;
-}
-
 static struct nvmem_config econfig = {
 	.name = "qfprom",
 	.stride = 1,
 	.word_size = 1,
 	.reg_read = qfprom_reg_read,
-	.reg_write = qfprom_reg_write,
 };
 
 static int qfprom_probe(struct platform_device *pdev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/nvmem/zynqmp_nvmem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/nvmem/zynqmp_nvmem.c
@@ -1,8 +1,9 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * Copyright (C) 2019 Xilinx, Inc.
+ * Copyright (C) 2017 - 2019 Xilinx, Inc.
  */
 
+#include <linux/dma-mapping.h>
 #include <linux/module.h>
 #include <linux/nvmem-provider.h>
 #include <linux/of.h>
@@ -10,40 +11,163 @@
 #include <linux/firmware/xlnx-zynqmp.h>
 
 #define SILICON_REVISION_MASK 0xF
+#define WORD_INBYTES		(4)
+#define SOC_VER_SIZE		(0x4)
+#define EFUSE_MEMORY_SIZE	(0xF4)
+#define UNUSED_SPACE		(0x8)
+#define ZYNQMP_NVMEM_SIZE	(SOC_VER_SIZE + UNUSED_SPACE + \
+				 EFUSE_MEMORY_SIZE)
+#define SOC_VERSION_OFFSET	(0x0)
+#define EFUSE_START_OFFSET	(0xC)
+#define EFUSE_END_OFFSET	(0xFC)
+#define EFUSE_NOT_ENABLED	(29)
+#define EFUSE_READ		(0)
+#define EFUSE_WRITE		(1)
 
-struct zynqmp_nvmem_data {
-	struct device *dev;
-	struct nvmem_device *nvmem;
+static const struct zynqmp_eemi_ops *eemi_ops;
+
+/**
+ * struct xilinx_efuse - the basic structure
+ * @src:	address of the buffer to store the data to be write/read
+ * @size:	no of words to be read/write
+ * @offset:	offset to be read/write`
+ * @flag:	0 - represents efuse read and 1- represents efuse write
+ *
+ * this structure stores all the required details to
+ * read/write efuse memory.
+ */
+struct xilinx_efuse {
+	u64 src;
+	u32 size;
+	u32 offset;
+	u32 flag;
+	u32 fullmap;
 };
 
-static const struct zynqmp_eemi_ops *eemi_ops;
+static int zynqmp_efuse_access(void *context, unsigned int offset,
+			       void *val, size_t bytes, unsigned int flag)
+{
+	size_t words = bytes / WORD_INBYTES;
+	struct device *dev = context;
+	dma_addr_t dma_addr, dma_buf;
+	struct xilinx_efuse *efuse;
+	char *data;
+	int ret;
+
+	if (!eemi_ops->efuse_access)
+		return -ENXIO;
+
+	if (bytes % WORD_INBYTES != 0) {
+		dev_err(dev,
+			"ERROR: Bytes requested should be word aligned\n\r");
+		return -ENOTSUPP;
+	}
+	if (offset % WORD_INBYTES != 0) {
+		dev_err(dev,
+			"ERROR: offset requested should be word aligned\n\r");
+		return -ENOTSUPP;
+	}
+
+	efuse = dma_alloc_coherent(dev, sizeof(struct xilinx_efuse),
+				   &dma_addr, GFP_KERNEL);
+	if (!efuse)
+		return -ENOMEM;
+
+	data = dma_alloc_coherent(dev, sizeof(bytes),
+				  &dma_buf, GFP_KERNEL);
+	if (!data) {
+		dma_free_coherent(dev, sizeof(struct xilinx_efuse),
+				  efuse, dma_addr);
+		return -ENOMEM;
+	}
+
+	if (flag == EFUSE_WRITE) {
+		memcpy(data, val, bytes);
+		efuse->flag = EFUSE_WRITE;
+	} else {
+		efuse->flag = EFUSE_READ;
+	}
+
+	efuse->src = dma_buf;
+	efuse->size = words;
+	efuse->offset = offset;
+
+	eemi_ops->efuse_access(dma_addr, &ret);
+	if (ret != 0) {
+		if (ret == EFUSE_NOT_ENABLED) {
+			dev_err(dev, "ERROR: efuse access is not enabled\n\r");
+			ret = -ENOTSUPP;
+			goto END;
+		}
+		dev_err(dev, "ERROR: in efuse read %x\n\r", ret);
+		ret = -EPERM;
+		goto END;
+	}
+
+	if (flag == EFUSE_READ)
+		memcpy(val, data, bytes);
+END:
+
+	dma_free_coherent(dev, sizeof(struct xilinx_efuse),
+			  efuse, dma_addr);
+	dma_free_coherent(dev, sizeof(bytes),
+			  data, dma_buf);
+
+	return ret;
+}
 
 static int zynqmp_nvmem_read(void *context, unsigned int offset,
-			     void *val, size_t bytes)
+					void *val, size_t bytes)
 {
 	int ret;
 	int idcode, version;
-	struct zynqmp_nvmem_data *priv = context;
 
 	if (!eemi_ops->get_chipid)
 		return -ENXIO;
 
-	ret = eemi_ops->get_chipid(&idcode, &version);
-	if (ret < 0)
-		return ret;
+	switch (offset) {
+	/* Soc version offset is zero */
+	case SOC_VERSION_OFFSET:
+		if (bytes != SOC_VER_SIZE)
+			return -ENOTSUPP;
+
+		ret = eemi_ops->get_chipid(&idcode, &version);
+		if (ret < 0)
+			return ret;
+
+		pr_debug("Read chipid val %x %x\n", idcode, version);
+		*(int *)val = version & SILICON_REVISION_MASK;
+		break;
+	/* Efuse offset starts from 0xc */
+	case EFUSE_START_OFFSET ... EFUSE_END_OFFSET:
+		ret = zynqmp_efuse_access(context, offset, val,
+					  bytes, EFUSE_READ);
+		break;
+	default:
+		*(u32 *)val = 0xDEADBEEF;
+		ret = 0;
+		break;
+	}
 
-	dev_dbg(priv->dev, "Read chipid val %x %x\n", idcode, version);
-	*(int *)val = version & SILICON_REVISION_MASK;
+	return ret;
+}
 
-	return 0;
+static int zynqmp_nvmem_write(void *context,
+			      unsigned int offset, void *val, size_t bytes)
+{
+	/* Efuse offset starts from 0xc */
+	if (offset < EFUSE_START_OFFSET)
+		return -ENOTSUPP;
+
+	return(zynqmp_efuse_access(context, offset,
+				   val, bytes, EFUSE_WRITE));
 }
 
 static struct nvmem_config econfig = {
 	.name = "zynqmp-nvmem",
 	.owner = THIS_MODULE,
 	.word_size = 1,
-	.size = 1,
-	.read_only = true,
+	.size = ZYNQMP_NVMEM_SIZE,
 };
 
 static const struct of_device_id zynqmp_nvmem_match[] = {
@@ -54,25 +178,24 @@
 
 static int zynqmp_nvmem_probe(struct platform_device *pdev)
 {
-	struct device *dev = &pdev->dev;
-	struct zynqmp_nvmem_data *priv;
-
-	priv = devm_kzalloc(dev, sizeof(struct zynqmp_nvmem_data), GFP_KERNEL);
-	if (!priv)
-		return -ENOMEM;
+	struct nvmem_device *nvmem;
 
 	eemi_ops = zynqmp_pm_get_eemi_ops();
 	if (IS_ERR(eemi_ops))
 		return PTR_ERR(eemi_ops);
 
-	priv->dev = dev;
-	econfig.dev = dev;
+	econfig.dev = &pdev->dev;
+	econfig.priv = &pdev->dev;
 	econfig.reg_read = zynqmp_nvmem_read;
-	econfig.priv = priv;
+	econfig.reg_write = zynqmp_nvmem_write;
+
+	nvmem = nvmem_register(&econfig);
+	if (IS_ERR(nvmem))
+		return PTR_ERR(nvmem);
 
-	priv->nvmem = devm_nvmem_register(dev, &econfig);
+	platform_set_drvdata(pdev, nvmem);
 
-	return PTR_ERR_OR_ZERO(priv->nvmem);
+	return 0;
 }
 
 static struct platform_driver zynqmp_nvmem_driver = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/of/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/of/Kconfig
@@ -103,4 +103,18 @@
 config OF_NUMA
 	bool
 
+config OF_DMA_DEFAULT_COHERENT
+	# arches should select this if DMA is coherent by default for OF devices
+	bool
+config OF_CONFIGFS
+	bool "Device Tree Overlay ConfigFS interface"
+	select CONFIGFS_FS
+	depends on OF_OVERLAY
+	help
+	  Select this option to enable simple user-space driven DT overlay
+	  interface to support device tree manipulated at runtime.
+	  Say Y here to include this support.
+
+	  If unsure, say N.
+
 endif # OF
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/of/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/of/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-y = base.o device.o platform.o property.o
 obj-$(CONFIG_OF_KOBJ) += kobj.o
+obj-$(CONFIG_OF_CONFIGFS) += configfs.o
 obj-$(CONFIG_OF_DYNAMIC) += dynamic.o
 obj-$(CONFIG_OF_FLATTREE) += fdt.o
 obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/of/address.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/of/address.c
@@ -692,7 +692,7 @@
 	if (ret < 0)
 		return of_get_parent(np);
 
-	return of_node_get(args.np);
+	return args.np;
 }
 
 u64 of_translate_dma_address(struct device_node *dev, const __be32 *in_addr)
@@ -998,11 +998,17 @@
  * @np:	device node
  *
  * It returns true if "dma-coherent" property was found
- * for this device in DT.
+ * for this device in the DT, or if DMA is coherent by
+ * default for OF devices on the current platform.
  */
 bool of_dma_is_coherent(struct device_node *np)
 {
-	struct device_node *node = of_node_get(np);
+	struct device_node *node;
+
+	if (IS_ENABLED(CONFIG_OF_DMA_DEFAULT_COHERENT))
+		return true;
+
+	node = of_node_get(np);
 
 	while (node) {
 		if (of_property_read_bool(node, "dma-coherent")) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/of/base.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/of/base.c
@@ -306,7 +306,7 @@
  * @prev:	Previous node or NULL to start iteration
  *		of_node_put() will be called on it
  *
- * Returns a node pointer with refcount incremented, use
+ * Return: A node pointer with refcount incremented, use
  * of_node_put() on it when done.
  */
 struct device_node *of_find_all_nodes(struct device_node *prev)
@@ -367,7 +367,7 @@
 	return (u32)phys_id == cpu;
 }
 
-/**
+/*
  * Checks if the given "prop_name" property holds the physical id of the
  * core/thread corresponding to the logical cpu 'cpu'. If 'thread' is not
  * NULL, local thread number within the core is returned in it.
@@ -436,7 +436,7 @@
  * before booting secondary cores. This function uses arch_match_cpu_phys_id
  * which can be overridden by architecture specific implementation.
  *
- * Returns a node pointer for the logical cpu with refcount incremented, use
+ * Return: A node pointer for the logical cpu with refcount incremented, use
  * of_node_put() on it when done. Returns NULL if not found.
  */
 struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
@@ -456,8 +456,8 @@
  *
  * @cpu_node: Pointer to the device_node for CPU.
  *
- * Returns the logical CPU number of the given CPU device_node.
- * Returns -ENODEV if the CPU is not found.
+ * Return: The logical CPU number of the given CPU device_node or -ENODEV if the
+ * CPU is not found.
  */
 int of_cpu_node_to_id(struct device_node *cpu_node)
 {
@@ -478,6 +478,42 @@
 EXPORT_SYMBOL(of_cpu_node_to_id);
 
 /**
+ * of_get_cpu_state_node - Get CPU's idle state node at the given index
+ *
+ * @cpu_node: The device node for the CPU
+ * @index: The index in the list of the idle states
+ *
+ * Two generic methods can be used to describe a CPU's idle states, either via
+ * a flattened description through the "cpu-idle-states" binding or via the
+ * hierarchical layout, using the "power-domains" and the "domain-idle-states"
+ * bindings. This function check for both and returns the idle state node for
+ * the requested index.
+ *
+ * Return: An idle state node if found at @index. The refcount is incremented
+ * for it, so call of_node_put() on it when done. Returns NULL if not found.
+ */
+struct device_node *of_get_cpu_state_node(struct device_node *cpu_node,
+					  int index)
+{
+	struct of_phandle_args args;
+	int err;
+
+	err = of_parse_phandle_with_args(cpu_node, "power-domains",
+					"#power-domain-cells", 0, &args);
+	if (!err) {
+		struct device_node *state_node =
+			of_parse_phandle(args.np, "domain-idle-states", index);
+
+		of_node_put(args.np);
+		if (state_node)
+			return state_node;
+	}
+
+	return of_parse_phandle(cpu_node, "cpu-idle-states", index);
+}
+EXPORT_SYMBOL(of_get_cpu_state_node);
+
+/**
  * __of_device_is_compatible() - Check if the node matches given constraints
  * @device: pointer to node
  * @compat: required compatible string, NULL or "" for any match
@@ -587,7 +623,7 @@
  * of_machine_is_compatible - Test root of device tree for a given compatible value
  * @compat: compatible string to look for in root node's compatible property.
  *
- * Returns a positive integer if the root node has the given value in its
+ * Return: A positive integer if the root node has the given value in its
  * compatible property.
  */
 int of_machine_is_compatible(const char *compat)
@@ -609,7 +645,7 @@
  *
  *  @device: Node to check for availability, with locks already held
  *
- *  Returns true if the status property is absent or set to "okay" or "ok",
+ *  Return: True if the status property is absent or set to "okay" or "ok",
  *  false otherwise
  */
 static bool __of_device_is_available(const struct device_node *device)
@@ -637,7 +673,7 @@
  *
  *  @device: Node to check for availability
  *
- *  Returns true if the status property is absent or set to "okay" or "ok",
+ *  Return: True if the status property is absent or set to "okay" or "ok",
  *  false otherwise
  */
 bool of_device_is_available(const struct device_node *device)
@@ -658,7 +694,7 @@
  *
  *  @device: Node to check for endianness
  *
- *  Returns true if the device has a "big-endian" property, or if the kernel
+ *  Return: True if the device has a "big-endian" property, or if the kernel
  *  was compiled for BE *and* the device has a "native-endian" property.
  *  Returns false otherwise.
  *
@@ -677,11 +713,11 @@
 EXPORT_SYMBOL(of_device_is_big_endian);
 
 /**
- *	of_get_parent - Get a node's parent if any
- *	@node:	Node to get parent
+ * of_get_parent - Get a node's parent if any
+ * @node:	Node to get parent
  *
- *	Returns a node pointer with refcount incremented, use
- *	of_node_put() on it when done.
+ * Return: A node pointer with refcount incremented, use
+ * of_node_put() on it when done.
  */
 struct device_node *of_get_parent(const struct device_node *node)
 {
@@ -699,15 +735,15 @@
 EXPORT_SYMBOL(of_get_parent);
 
 /**
- *	of_get_next_parent - Iterate to a node's parent
- *	@node:	Node to get parent of
+ * of_get_next_parent - Iterate to a node's parent
+ * @node:	Node to get parent of
  *
- *	This is like of_get_parent() except that it drops the
- *	refcount on the passed node, making it suitable for iterating
- *	through a node's parents.
+ * This is like of_get_parent() except that it drops the
+ * refcount on the passed node, making it suitable for iterating
+ * through a node's parents.
  *
- *	Returns a node pointer with refcount incremented, use
- *	of_node_put() on it when done.
+ * Return: A node pointer with refcount incremented, use
+ * of_node_put() on it when done.
  */
 struct device_node *of_get_next_parent(struct device_node *node)
 {
@@ -745,13 +781,13 @@
 	     child = __of_get_next_child(parent, child))
 
 /**
- *	of_get_next_child - Iterate a node childs
- *	@node:	parent node
- *	@prev:	previous child of the parent node, or NULL to get first
- *
- *	Returns a node pointer with refcount incremented, use of_node_put() on
- *	it when done. Returns NULL when prev is the last child. Decrements the
- *	refcount of prev.
+ * of_get_next_child - Iterate a node childs
+ * @node:	parent node
+ * @prev:	previous child of the parent node, or NULL to get first
+ *
+ * Return: A node pointer with refcount incremented, use of_node_put() on
+ * it when done. Returns NULL when prev is the last child. Decrements the
+ * refcount of prev.
  */
 struct device_node *of_get_next_child(const struct device_node *node,
 	struct device_node *prev)
@@ -767,12 +803,12 @@
 EXPORT_SYMBOL(of_get_next_child);
 
 /**
- *	of_get_next_available_child - Find the next available child node
- *	@node:	parent node
- *	@prev:	previous child of the parent node, or NULL to get first
+ * of_get_next_available_child - Find the next available child node
+ * @node:	parent node
+ * @prev:	previous child of the parent node, or NULL to get first
  *
- *      This function is like of_get_next_child(), except that it
- *      automatically skips any disabled nodes (i.e. status = "disabled").
+ * This function is like of_get_next_child(), except that it
+ * automatically skips any disabled nodes (i.e. status = "disabled").
  */
 struct device_node *of_get_next_available_child(const struct device_node *node,
 	struct device_node *prev)
@@ -798,12 +834,12 @@
 EXPORT_SYMBOL(of_get_next_available_child);
 
 /**
- *	of_get_next_cpu_node - Iterate on cpu nodes
- *	@prev:	previous child of the /cpus node, or NULL to get first
+ * of_get_next_cpu_node - Iterate on cpu nodes
+ * @prev:	previous child of the /cpus node, or NULL to get first
  *
- *	Returns a cpu node pointer with refcount incremented, use of_node_put()
- *	on it when done. Returns NULL when prev is the last child. Decrements
- *	the refcount of prev.
+ * Return: A cpu node pointer with refcount incremented, use of_node_put()
+ * on it when done. Returns NULL when prev is the last child. Decrements
+ * the refcount of prev.
  */
 struct device_node *of_get_next_cpu_node(struct device_node *prev)
 {
@@ -842,7 +878,7 @@
  * Lookup child node whose compatible property contains the given compatible
  * string.
  *
- * Returns a node pointer with refcount incremented, use of_node_put() on it
+ * Return: a node pointer with refcount incremented, use of_node_put() on it
  * when done; or NULL if not found.
  */
 struct device_node *of_get_compatible_child(const struct device_node *parent,
@@ -860,15 +896,15 @@
 EXPORT_SYMBOL(of_get_compatible_child);
 
 /**
- *	of_get_child_by_name - Find the child node by name for a given parent
- *	@node:	parent node
- *	@name:	child name to look for.
- *
- *      This function looks for child node for given matching name
- *
- *	Returns a node pointer if found, with refcount incremented, use
- *	of_node_put() on it when done.
- *	Returns NULL if node is not found.
+ * of_get_child_by_name - Find the child node by name for a given parent
+ * @node:	parent node
+ * @name:	child name to look for.
+ *
+ * This function looks for child node for given matching name
+ *
+ * Return: A node pointer if found, with refcount incremented, use
+ * of_node_put() on it when done.
+ * Returns NULL if node is not found.
  */
 struct device_node *of_get_child_by_name(const struct device_node *node,
 				const char *name)
@@ -919,22 +955,22 @@
 }
 
 /**
- *	of_find_node_opts_by_path - Find a node matching a full OF path
- *	@path: Either the full path to match, or if the path does not
- *	       start with '/', the name of a property of the /aliases
- *	       node (an alias).  In the case of an alias, the node
- *	       matching the alias' value will be returned.
- *	@opts: Address of a pointer into which to store the start of
- *	       an options string appended to the end of the path with
- *	       a ':' separator.
- *
- *	Valid paths:
- *		/foo/bar	Full path
- *		foo		Valid alias
- *		foo/bar		Valid alias + relative path
+ * of_find_node_opts_by_path - Find a node matching a full OF path
+ * @path: Either the full path to match, or if the path does not
+ *       start with '/', the name of a property of the /aliases
+ *       node (an alias).  In the case of an alias, the node
+ *       matching the alias' value will be returned.
+ * @opts: Address of a pointer into which to store the start of
+ *       an options string appended to the end of the path with
+ *       a ':' separator.
+ *
+ * Valid paths:
+ *  * /foo/bar	Full path
+ *  * foo	Valid alias
+ *  * foo/bar	Valid alias + relative path
  *
- *	Returns a node pointer with refcount incremented, use
- *	of_node_put() on it when done.
+ * Return: A node pointer with refcount incremented, use
+ * of_node_put() on it when done.
  */
 struct device_node *of_find_node_opts_by_path(const char *path, const char **opts)
 {
@@ -952,10 +988,10 @@
 	/* The path could begin with an alias */
 	if (*path != '/') {
 		int len;
-		const char *p = separator;
+		const char *p = strchrnul(path, '/');
 
-		if (!p)
-			p = strchrnul(path, '/');
+		if (separator && separator < p)
+			p = separator;
 		len = p - path;
 
 		/* of_aliases must not be NULL */
@@ -984,15 +1020,15 @@
 EXPORT_SYMBOL(of_find_node_opts_by_path);
 
 /**
- *	of_find_node_by_name - Find a node by its "name" property
- *	@from:	The node to start searching from or NULL; the node
+ * of_find_node_by_name - Find a node by its "name" property
+ * @from:	The node to start searching from or NULL; the node
  *		you pass will not be searched, only the next one
  *		will. Typically, you pass what the previous call
  *		returned. of_node_put() will be called on @from.
- *	@name:	The name string to match against
+ * @name:	The name string to match against
  *
- *	Returns a node pointer with refcount incremented, use
- *	of_node_put() on it when done.
+ * Return: A node pointer with refcount incremented, use
+ * of_node_put() on it when done.
  */
 struct device_node *of_find_node_by_name(struct device_node *from,
 	const char *name)
@@ -1011,16 +1047,16 @@
 EXPORT_SYMBOL(of_find_node_by_name);
 
 /**
- *	of_find_node_by_type - Find a node by its "device_type" property
- *	@from:	The node to start searching from, or NULL to start searching
+ * of_find_node_by_type - Find a node by its "device_type" property
+ * @from:	The node to start searching from, or NULL to start searching
  *		the entire device tree. The node you pass will not be
  *		searched, only the next one will; typically, you pass
  *		what the previous call returned. of_node_put() will be
  *		called on from for you.
- *	@type:	The type string to match against
+ * @type:	The type string to match against
  *
- *	Returns a node pointer with refcount incremented, use
- *	of_node_put() on it when done.
+ * Return: A node pointer with refcount incremented, use
+ * of_node_put() on it when done.
  */
 struct device_node *of_find_node_by_type(struct device_node *from,
 	const char *type)
@@ -1039,18 +1075,18 @@
 EXPORT_SYMBOL(of_find_node_by_type);
 
 /**
- *	of_find_compatible_node - Find a node based on type and one of the
+ * of_find_compatible_node - Find a node based on type and one of the
  *                                tokens in its "compatible" property
- *	@from:		The node to start searching from or NULL, the node
- *			you pass will not be searched, only the next one
- *			will; typically, you pass what the previous call
- *			returned. of_node_put() will be called on it
- *	@type:		The type string to match "device_type" or NULL to ignore
- *	@compatible:	The string to match to one of the tokens in the device
- *			"compatible" list.
+ * @from:	The node to start searching from or NULL, the node
+ *		you pass will not be searched, only the next one
+ *		will; typically, you pass what the previous call
+ *		returned. of_node_put() will be called on it
+ * @type:	The type string to match "device_type" or NULL to ignore
+ * @compatible:	The string to match to one of the tokens in the device
+ *		"compatible" list.
  *
- *	Returns a node pointer with refcount incremented, use
- *	of_node_put() on it when done.
+ * Return: A node pointer with refcount incremented, use
+ * of_node_put() on it when done.
  */
 struct device_node *of_find_compatible_node(struct device_node *from,
 	const char *type, const char *compatible)
@@ -1070,16 +1106,16 @@
 EXPORT_SYMBOL(of_find_compatible_node);
 
 /**
- *	of_find_node_with_property - Find a node which has a property with
- *                                   the given name.
- *	@from:		The node to start searching from or NULL, the node
- *			you pass will not be searched, only the next one
- *			will; typically, you pass what the previous call
- *			returned. of_node_put() will be called on it
- *	@prop_name:	The name of the property to look for.
+ * of_find_node_with_property - Find a node which has a property with
+ *                              the given name.
+ * @from:	The node to start searching from or NULL, the node
+ *		you pass will not be searched, only the next one
+ *		will; typically, you pass what the previous call
+ *		returned. of_node_put() will be called on it
+ * @prop_name:	The name of the property to look for.
  *
- *	Returns a node pointer with refcount incremented, use
- *	of_node_put() on it when done.
+ * Return: A node pointer with refcount incremented, use
+ * of_node_put() on it when done.
  */
 struct device_node *of_find_node_with_property(struct device_node *from,
 	const char *prop_name)
@@ -1128,10 +1164,10 @@
 
 /**
  * of_match_node - Tell if a device_node has a matching of_match structure
- *	@matches:	array of of device match structures to search in
- *	@node:		the of device structure to match against
+ * @matches:	array of of device match structures to search in
+ * @node:	the of device structure to match against
  *
- *	Low level utility function used by device matching.
+ * Low level utility function used by device matching.
  */
 const struct of_device_id *of_match_node(const struct of_device_id *matches,
 					 const struct device_node *node)
@@ -1147,17 +1183,17 @@
 EXPORT_SYMBOL(of_match_node);
 
 /**
- *	of_find_matching_node_and_match - Find a node based on an of_device_id
- *					  match table.
- *	@from:		The node to start searching from or NULL, the node
- *			you pass will not be searched, only the next one
- *			will; typically, you pass what the previous call
- *			returned. of_node_put() will be called on it
- *	@matches:	array of of device match structures to search in
- *	@match		Updated to point at the matches entry which matched
+ * of_find_matching_node_and_match - Find a node based on an of_device_id
+ *				     match table.
+ * @from:	The node to start searching from or NULL, the node
+ *		you pass will not be searched, only the next one
+ *		will; typically, you pass what the previous call
+ *		returned. of_node_put() will be called on it
+ * @matches:	array of of device match structures to search in
+ * @match:	Updated to point at the matches entry which matched
  *
- *	Returns a node pointer with refcount incremented, use
- *	of_node_put() on it when done.
+ * Return: A node pointer with refcount incremented, use
+ * of_node_put() on it when done.
  */
 struct device_node *of_find_matching_node_and_match(struct device_node *from,
 					const struct of_device_id *matches,
@@ -1196,7 +1232,7 @@
  * It does this by stripping the manufacturer prefix (as delimited by a ',')
  * from the first entry in the compatible list property.
  *
- * This routine returns 0 on success, <0 on failure.
+ * Return: This routine returns 0 on success, <0 on failure.
  */
 int of_modalias_node(struct device_node *node, char *modalias, int len)
 {
@@ -1216,7 +1252,7 @@
  * of_find_node_by_phandle - Find a node given a phandle
  * @handle:	phandle of the node to find
  *
- * Returns a node pointer with refcount incremented, use
+ * Return: A node pointer with refcount incremented, use
  * of_node_put() on it when done.
  */
 struct device_node *of_find_node_by_phandle(phandle handle)
@@ -1366,9 +1402,14 @@
 		 * property data length
 		 */
 		if (it->cur + count > it->list_end) {
-			pr_err("%pOF: %s = %d found %d\n",
-			       it->parent, it->cells_name,
-			       count, it->cell_count);
+			if (it->cells_name)
+				pr_err("%pOF: %s = %d found %td\n",
+					it->parent, it->cells_name,
+					count, it->list_end - it->cur);
+			else
+				pr_err("%pOF: phandle %s needs %d, found %td\n",
+					it->parent, of_node_full_name(it->node),
+					count, it->list_end - it->cur);
 			goto err;
 		}
 	}
@@ -1464,7 +1505,7 @@
  * @index: For properties holding a table of phandles, this is the index into
  *         the table
  *
- * Returns the device_node pointer with refcount incremented.  Use
+ * Return: The device_node pointer with refcount incremented.  Use
  * of_node_put() on it when done.
  */
 struct device_node *of_parse_phandle(const struct device_node *np,
@@ -1498,21 +1539,21 @@
  * Caller is responsible to call of_node_put() on the returned out_args->np
  * pointer.
  *
- * Example:
+ * Example::
  *
- * phandle1: node1 {
+ *  phandle1: node1 {
  *	#list-cells = <2>;
- * }
+ *  };
  *
- * phandle2: node2 {
+ *  phandle2: node2 {
  *	#list-cells = <1>;
- * }
+ *  };
  *
- * node3 {
+ *  node3 {
  *	list = <&phandle1 1 2 &phandle2 3>;
- * }
+ *  };
  *
- * To get a device_node of the `node2' node you may call this:
+ * To get a device_node of the ``node2`` node you may call this:
  * of_parse_phandle_with_args(node3, "list", "#list-cells", 1, &args);
  */
 int of_parse_phandle_with_args(const struct device_node *np, const char *list_name,
@@ -1550,29 +1591,29 @@
  * Caller is responsible to call of_node_put() on the returned out_args->np
  * pointer.
  *
- * Example:
- *
- * phandle1: node1 {
- *	#list-cells = <2>;
- * }
- *
- * phandle2: node2 {
- *	#list-cells = <1>;
- * }
+ * Example::
  *
- * phandle3: node3 {
- * 	#list-cells = <1>;
- * 	list-map = <0 &phandle2 3>,
- * 		   <1 &phandle2 2>,
- * 		   <2 &phandle1 5 1>;
- *	list-map-mask = <0x3>;
- * };
- *
- * node4 {
- *	list = <&phandle1 1 2 &phandle3 0>;
- * }
+ *  phandle1: node1 {
+ *  	#list-cells = <2>;
+ *  };
+ *
+ *  phandle2: node2 {
+ *  	#list-cells = <1>;
+ *  };
+ *
+ *  phandle3: node3 {
+ *  	#list-cells = <1>;
+ *  	list-map = <0 &phandle2 3>,
+ *  		   <1 &phandle2 2>,
+ *  		   <2 &phandle1 5 1>;
+ *  	list-map-mask = <0x3>;
+ *  };
+ *
+ *  node4 {
+ *  	list = <&phandle1 1 2 &phandle3 0>;
+ *  };
  *
- * To get a device_node of the `node2' node you may call this:
+ * To get a device_node of the ``node2`` node you may call this:
  * of_parse_phandle_with_args(node4, "list", "list", 1, &args);
  */
 int of_parse_phandle_with_args_map(const struct device_node *np,
@@ -1654,8 +1695,10 @@
 			map_len--;
 
 			/* Check if not found */
-			if (!new)
+			if (!new) {
+				ret = -EINVAL;
 				goto put;
+			}
 
 			if (!of_device_is_available(new))
 				match = 0;
@@ -1665,17 +1708,20 @@
 				goto put;
 
 			/* Check for malformed properties */
-			if (WARN_ON(new_size > MAX_PHANDLE_ARGS))
-				goto put;
-			if (map_len < new_size)
+			if (WARN_ON(new_size > MAX_PHANDLE_ARGS) ||
+			    map_len < new_size) {
+				ret = -EINVAL;
 				goto put;
+			}
 
 			/* Move forward by new node's #<list>-cells amount */
 			map += new_size;
 			map_len -= new_size;
 		}
-		if (!match)
+		if (!match) {
+			ret = -ENOENT;
 			goto put;
+		}
 
 		/* Get the <list>-map-pass-thru property (optional) */
 		pass = of_get_property(cur, pass_name, NULL);
@@ -1687,7 +1733,6 @@
 		 * specifier into the out_args structure, keeping the
 		 * bits specified in <list>-map-pass-thru.
 		 */
-		match_array = map - new_size;
 		for (i = 0; i < new_size; i++) {
 			__be32 val = *(map - new_size + i);
 
@@ -1696,6 +1741,7 @@
 				val |= cpu_to_be32(out_args->args[i]) & pass[i];
 			}
 
+			initial_match_array[i] = val;
 			out_args->args[i] = be32_to_cpu(val);
 		}
 		out_args->args_count = list_size = new_size;
@@ -1703,6 +1749,7 @@
 		out_args->np = new;
 		of_node_put(cur);
 		cur = new;
+		new = NULL;
 	}
 put:
 	of_node_put(cur);
@@ -1732,19 +1779,19 @@
  * Caller is responsible to call of_node_put() on the returned out_args->np
  * pointer.
  *
- * Example:
+ * Example::
  *
- * phandle1: node1 {
- * }
+ *  phandle1: node1 {
+ *  };
  *
- * phandle2: node2 {
- * }
+ *  phandle2: node2 {
+ *  };
  *
- * node3 {
- *	list = <&phandle1 0 2 &phandle2 2 3>;
- * }
+ *  node3 {
+ *  	list = <&phandle1 0 2 &phandle2 2 3>;
+ *  };
  *
- * To get a device_node of the `node2' node you may call this:
+ * To get a device_node of the ``node2`` node you may call this:
  * of_parse_phandle_with_fixed_args(node3, "list", 2, 1, &args);
  */
 int of_parse_phandle_with_fixed_args(const struct device_node *np,
@@ -1764,7 +1811,7 @@
  * @list_name:	property name that contains a list
  * @cells_name:	property name that specifies phandles' arguments count
  *
- * Returns the number of phandle + argument tuples within a property. It
+ * Return: The number of phandle + argument tuples within a property. It
  * is a typical pattern to encode a list of phandle and variable
  * arguments into a single property. The number of arguments is encoded
  * by a property in the phandle-target node. For example, a gpios
@@ -1812,6 +1859,8 @@
 
 /**
  * __of_add_property - Add a property to a node without lock operations
+ * @np:		Caller's Device Node
+ * @prob:	Property to add
  */
 int __of_add_property(struct device_node *np, struct property *prop)
 {
@@ -1833,6 +1882,8 @@
 
 /**
  * of_add_property - Add a property to a node
+ * @np:		Caller's Device Node
+ * @prob:	Property to add
  */
 int of_add_property(struct device_node *np, struct property *prop)
 {
@@ -1877,6 +1928,8 @@
 
 /**
  * of_remove_property - Remove a property from a node.
+ * @np:		Caller's Device Node
+ * @prob:	Property to remove
  *
  * Note that we don't actually remove it, since we have given out
  * who-knows-how-many pointers to the data using get-property.
@@ -1983,13 +2036,12 @@
 
 /**
  * of_alias_scan - Scan all properties of the 'aliases' node
+ * @dt_alloc:	An allocator that provides a virtual address to memory
+ *		for storing the resulting tree
  *
  * The function scans all the properties of the 'aliases' node and populates
  * the global lookup table with the properties.  It returns the
  * number of alias properties found, or an error code in case of failure.
- *
- * @dt_alloc:	An allocator that provides a virtual address to memory
- *		for storing the resulting tree
  */
 void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
 {
@@ -2058,7 +2110,9 @@
  * @stem:	Alias stem of the given device_node
  *
  * The function travels the lookup table to get the alias id for the given
- * device_node and alias stem.  It returns the alias id if found.
+ * device_node and alias stem.
+ *
+ * Return: The alias id if found.
  */
 int of_alias_get_id(struct device_node *np, const char *stem)
 {
@@ -2162,13 +2216,14 @@
 
 /**
  * of_console_check() - Test and setup console for DT setup
- * @dn - Pointer to device node
- * @name - Name to use for preferred console without index. ex. "ttyS"
- * @index - Index to use for preferred console.
+ * @dn: Pointer to device node
+ * @name: Name to use for preferred console without index. ex. "ttyS"
+ * @index: Index to use for preferred console.
  *
  * Check if the given device node matches the stdout-path property in the
- * /chosen node. If it does then register it as the preferred console and return
- * TRUE. Otherwise return FALSE.
+ * /chosen node. If it does then register it as the preferred console.
+ *
+ * Return: TRUE if console successfully setup. Otherwise return FALSE.
  */
 bool of_console_check(struct device_node *dn, char *name, int index)
 {
@@ -2184,12 +2239,12 @@
 EXPORT_SYMBOL_GPL(of_console_check);
 
 /**
- *	of_find_next_cache_node - Find a node's subsidiary cache
- *	@np:	node of type "cpu" or "cache"
+ * of_find_next_cache_node - Find a node's subsidiary cache
+ * @np:	node of type "cpu" or "cache"
  *
- *	Returns a node pointer with refcount incremented, use
- *	of_node_put() on it when done.  Caller should hold a reference
- *	to np.
+ * Return: A node pointer with refcount incremented, use
+ * of_node_put() on it when done.  Caller should hold a reference
+ * to np.
  */
 struct device_node *of_find_next_cache_node(const struct device_node *np)
 {
@@ -2219,7 +2274,7 @@
  *
  * @cpu: cpu number(logical index) for which the last cache level is needed
  *
- * Returns the the level at which the last cache is present. It is exactly
+ * Return: The the level at which the last cache is present. It is exactly
  * same as  the total number of cache levels for the given logical cpu.
  */
 int of_find_last_cache_level(unsigned int cpu)
@@ -2239,15 +2294,15 @@
 }
 
 /**
- * of_map_rid - Translate a requester ID through a downstream mapping.
+ * of_map_id - Translate an ID through a downstream mapping.
  * @np: root complex device node.
- * @rid: device requester ID to map.
+ * @id: device ID to map.
  * @map_name: property name of the map to use.
  * @map_mask_name: optional property name of the mask to use.
  * @target: optional pointer to a target device node.
  * @id_out: optional pointer to receive the translated ID.
  *
- * Given a device requester ID, look up the appropriate implementation-defined
+ * Given a device ID, look up the appropriate implementation-defined
  * platform ID and/or the target device which receives transactions on that
  * ID, as per the "iommu-map" and "msi-map" bindings. Either of @target or
  * @id_out may be NULL if only the other is required. If @target points to
@@ -2257,11 +2312,11 @@
  *
  * Return: 0 on success or a standard error code on failure.
  */
-int of_map_rid(struct device_node *np, u32 rid,
+int of_map_id(struct device_node *np, u32 id,
 	       const char *map_name, const char *map_mask_name,
 	       struct device_node **target, u32 *id_out)
 {
-	u32 map_mask, masked_rid;
+	u32 map_mask, masked_id;
 	int map_len;
 	const __be32 *map = NULL;
 
@@ -2273,7 +2328,7 @@
 		if (target)
 			return -ENODEV;
 		/* Otherwise, no map implies no translation */
-		*id_out = rid;
+		*id_out = id;
 		return 0;
 	}
 
@@ -2293,22 +2348,22 @@
 	if (map_mask_name)
 		of_property_read_u32(np, map_mask_name, &map_mask);
 
-	masked_rid = map_mask & rid;
+	masked_id = map_mask & id;
 	for ( ; map_len > 0; map_len -= 4 * sizeof(*map), map += 4) {
 		struct device_node *phandle_node;
-		u32 rid_base = be32_to_cpup(map + 0);
+		u32 id_base = be32_to_cpup(map + 0);
 		u32 phandle = be32_to_cpup(map + 1);
 		u32 out_base = be32_to_cpup(map + 2);
-		u32 rid_len = be32_to_cpup(map + 3);
+		u32 id_len = be32_to_cpup(map + 3);
 
-		if (rid_base & ~map_mask) {
-			pr_err("%pOF: Invalid %s translation - %s-mask (0x%x) ignores rid-base (0x%x)\n",
+		if (id_base & ~map_mask) {
+			pr_err("%pOF: Invalid %s translation - %s-mask (0x%x) ignores id-base (0x%x)\n",
 				np, map_name, map_name,
-				map_mask, rid_base);
+				map_mask, id_base);
 			return -EFAULT;
 		}
 
-		if (masked_rid < rid_base || masked_rid >= rid_base + rid_len)
+		if (masked_id < id_base || masked_id >= id_base + id_len)
 			continue;
 
 		phandle_node = of_find_node_by_phandle(phandle);
@@ -2326,20 +2381,20 @@
 		}
 
 		if (id_out)
-			*id_out = masked_rid - rid_base + out_base;
+			*id_out = masked_id - id_base + out_base;
 
-		pr_debug("%pOF: %s, using mask %08x, rid-base: %08x, out-base: %08x, length: %08x, rid: %08x -> %08x\n",
-			np, map_name, map_mask, rid_base, out_base,
-			rid_len, rid, masked_rid - rid_base + out_base);
+		pr_debug("%pOF: %s, using mask %08x, id-base: %08x, out-base: %08x, length: %08x, id: %08x -> %08x\n",
+			np, map_name, map_mask, id_base, out_base,
+			id_len, id, masked_id - id_base + out_base);
 		return 0;
 	}
 
-	pr_info("%pOF: no %s translation for rid 0x%x on %pOF\n", np, map_name,
-		rid, target && *target ? *target : NULL);
+	pr_info("%pOF: no %s translation for id 0x%x on %pOF\n", np, map_name,
+		id, target && *target ? *target : NULL);
 
 	/* Bypasses translation */
 	if (id_out)
-		*id_out = rid;
+		*id_out = id;
 	return 0;
 }
-EXPORT_SYMBOL_GPL(of_map_rid);
+EXPORT_SYMBOL_GPL(of_map_id);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/of/configfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/of/configfs.c
@@ -0,0 +1,294 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Configfs entries for device-tree
+ *
+ * Copyright (C) 2013 - Pantelis Antoniou <panto@antoniou-consulting.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <linux/ctype.h>
+#include <linux/cpu.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/spinlock.h>
+#include <linux/sizes.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/configfs.h>
+#include <linux/types.h>
+#include <linux/stat.h>
+#include <linux/limits.h>
+#include <linux/file.h>
+#include <linux/vmalloc.h>
+#include <linux/firmware.h>
+
+#include "of_private.h"
+
+struct cfs_overlay_item {
+	struct config_item	item;
+
+	char			path[PATH_MAX];
+
+	const struct firmware	*fw;
+	struct device_node	*overlay;
+	int			ov_id;
+
+	void			*dtbo;
+	int			dtbo_size;
+
+	void			*mem;
+};
+
+static DEFINE_MUTEX(overlay_lock);
+
+static int create_overlay(struct cfs_overlay_item *overlay, void *blob)
+{
+	int err;
+
+	/* FIXME */
+	err = of_overlay_fdt_apply(blob, overlay->dtbo_size, &overlay->ov_id);
+	if (err < 0) {
+		pr_err("%s: Failed to create overlay (err=%d)\n",
+		       __func__, err);
+		return err;
+	}
+
+	return err;
+}
+
+static inline struct cfs_overlay_item
+		*to_cfs_overlay_item(struct config_item *item)
+{
+	return item ? container_of(item, struct cfs_overlay_item, item) : NULL;
+}
+
+static ssize_t cfs_overlay_item_path_show(struct config_item *item, char *page)
+{
+	return sprintf(page, "%s\n", to_cfs_overlay_item(item)->path);
+}
+
+static ssize_t cfs_overlay_item_path_store(struct config_item *item,
+					   const char *page, size_t count)
+{
+	struct cfs_overlay_item *overlay = to_cfs_overlay_item(item);
+	const char *p = page;
+	char *s;
+	int err;
+
+	/* if it's set do not allow changes */
+	if (overlay->path[0] != '\0' || overlay->dtbo_size > 0)
+		return -EPERM;
+
+	/* copy to path buffer (and make sure it's always zero terminated */
+	count = snprintf(overlay->path, sizeof(overlay->path) - 1, "%s", p);
+	overlay->path[sizeof(overlay->path) - 1] = '\0';
+
+	/* strip trailing newlines */
+	s = overlay->path + strlen(overlay->path);
+	while (s > overlay->path && *--s == '\n')
+		*s = '\0';
+
+	pr_debug("%s: path is '%s'\n", __func__, overlay->path);
+
+	err = request_firmware(&overlay->fw, overlay->path, NULL);
+	if (err != 0)
+		goto out_err;
+
+	overlay->dtbo_size = overlay->fw->size;
+	err = create_overlay(overlay, (void *)overlay->fw->data);
+	if (err < 0)
+		goto out_err;
+
+	return count;
+
+out_err:
+
+	release_firmware(overlay->fw);
+	overlay->fw = NULL;
+
+	overlay->path[0] = '\0';
+
+	return count;
+}
+
+static ssize_t cfs_overlay_item_status_show(struct config_item *item,
+					    char *page)
+{
+	return sprintf(page, "%s\n", to_cfs_overlay_item(item)->ov_id >= 0 ?
+					"applied" : "unapplied");
+}
+
+CONFIGFS_ATTR(cfs_overlay_item_, path);
+CONFIGFS_ATTR_RO(cfs_overlay_item_, status);
+
+static struct configfs_attribute *cfs_overlay_attrs[] = {
+	&cfs_overlay_item_attr_path,
+	&cfs_overlay_item_attr_status,
+	NULL,
+};
+
+ssize_t cfs_overlay_item_dtbo_read(struct config_item *item,
+				   void *buf, size_t max_count)
+{
+	struct cfs_overlay_item *overlay = to_cfs_overlay_item(item);
+
+	pr_debug("%s: buf=%p max_count=%zu\n", __func__, buf, max_count);
+
+	if (!overlay->dtbo)
+		return 0;
+
+	/* copy if buffer provided */
+	if (buf) {
+		/* the buffer must be large enough */
+		if (overlay->dtbo_size > max_count)
+			return -ENOSPC;
+
+		memcpy(buf, overlay->dtbo, overlay->dtbo_size);
+	}
+
+	return overlay->dtbo_size;
+}
+
+ssize_t cfs_overlay_item_dtbo_write(struct config_item *item,
+				    const void *buf, size_t count)
+{
+	struct cfs_overlay_item *overlay = to_cfs_overlay_item(item);
+	int err;
+
+	/* if it's set do not allow changes */
+	if (overlay->path[0] != '\0' || overlay->dtbo_size > 0)
+		return -EPERM;
+
+	/* copy the contents */
+	overlay->dtbo = kmemdup(buf, count, GFP_KERNEL);
+	if (!overlay->dtbo)
+		return -ENOMEM;
+
+	overlay->dtbo_size = count;
+
+	err = create_overlay(overlay, overlay->dtbo);
+	if (err < 0)
+		goto out_err;
+
+	return count;
+
+out_err:
+	kfree(overlay->dtbo);
+	overlay->dtbo = NULL;
+	overlay->dtbo_size = 0;
+
+	return err;
+}
+
+CONFIGFS_BIN_ATTR(cfs_overlay_item_, dtbo, NULL, SZ_1M);
+
+static struct configfs_bin_attribute *cfs_overlay_bin_attrs[] = {
+	&cfs_overlay_item_attr_dtbo,
+	NULL,
+};
+
+static void cfs_overlay_release(struct config_item *item)
+{
+	struct cfs_overlay_item *overlay = to_cfs_overlay_item(item);
+
+	if (overlay->ov_id >= 0)
+		of_overlay_remove(&overlay->ov_id);
+	if (overlay->fw)
+		release_firmware(overlay->fw);
+	/* kfree with NULL is safe */
+	kfree(overlay->dtbo);
+	kfree(overlay->mem);
+	kfree(overlay);
+}
+
+static struct configfs_item_operations cfs_overlay_item_ops = {
+	.release		= cfs_overlay_release,
+};
+
+static struct config_item_type cfs_overlay_type = {
+	.ct_item_ops	= &cfs_overlay_item_ops,
+	.ct_attrs	= cfs_overlay_attrs,
+	.ct_bin_attrs	= cfs_overlay_bin_attrs,
+	.ct_owner	= THIS_MODULE,
+};
+
+static struct config_item
+	*cfs_overlay_group_make_item(struct config_group *group,
+				     const char *name)
+{
+	struct cfs_overlay_item *overlay;
+
+	overlay = kzalloc(sizeof(*overlay), GFP_KERNEL);
+	if (!overlay)
+		return ERR_PTR(-ENOMEM);
+	overlay->ov_id = -1;
+	config_item_init_type_name(&overlay->item, name, &cfs_overlay_type);
+
+	return &overlay->item;
+}
+
+static void cfs_overlay_group_drop_item(struct config_group *group,
+					struct config_item *item)
+{
+	struct cfs_overlay_item *overlay = to_cfs_overlay_item(item);
+
+	config_item_put(&overlay->item);
+}
+
+static struct configfs_group_operations overlays_ops = {
+	.make_item	= cfs_overlay_group_make_item,
+	.drop_item	= cfs_overlay_group_drop_item,
+};
+
+static struct config_item_type overlays_type = {
+	.ct_group_ops   = &overlays_ops,
+	.ct_owner       = THIS_MODULE,
+};
+
+static struct configfs_group_operations of_cfs_ops = {
+	/* empty - we don't allow anything to be created */
+};
+
+static struct config_item_type of_cfs_type = {
+	.ct_group_ops   = &of_cfs_ops,
+	.ct_owner       = THIS_MODULE,
+};
+
+struct config_group of_cfs_overlay_group;
+
+static struct configfs_subsystem of_cfs_subsys = {
+	.su_group = {
+		.cg_item = {
+			.ci_namebuf = "device-tree",
+			.ci_type = &of_cfs_type,
+		},
+	},
+	.su_mutex = __MUTEX_INITIALIZER(of_cfs_subsys.su_mutex),
+};
+
+static int __init of_cfs_init(void)
+{
+	int ret;
+
+	pr_info("%s\n", __func__);
+
+	config_group_init(&of_cfs_subsys.su_group);
+	config_group_init_type_name(&of_cfs_overlay_group, "overlays",
+				    &overlays_type);
+	configfs_add_default_group(&of_cfs_overlay_group,
+				   &of_cfs_subsys.su_group);
+
+	ret = configfs_register_subsystem(&of_cfs_subsys);
+	if (ret != 0) {
+		pr_err("%s: failed to register subsys\n", __func__);
+		goto out;
+	}
+	pr_info("%s: OK\n", __func__);
+out:
+	return ret;
+}
+late_initcall(of_cfs_init);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/of/device.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/of/device.c
@@ -213,14 +213,15 @@
 	csize = snprintf(str, len, "of:N%pOFn%c%s", dev->of_node, 'T',
 			 of_node_get_device_type(dev->of_node));
 	tsize = csize;
+	if (csize >= len)
+		csize = len > 0 ? len - 1 : 0;
 	len -= csize;
-	if (str)
-		str += csize;
+	str += csize;
 
 	of_property_for_each_string(dev->of_node, "compatible", p, compat) {
 		csize = strlen(compat) + 1;
 		tsize += csize;
-		if (csize > len)
+		if (csize >= len)
 			continue;
 
 		csize = snprintf(str, len, "C%s", compat);
@@ -246,12 +247,15 @@
 	if (size < 0)
 		return size;
 
-	str = kmalloc(size + 1, GFP_KERNEL);
+	/* Reserve an additional byte for the trailing '\0' */
+	size++;
+
+	str = kmalloc(size, GFP_KERNEL);
 	if (!str)
 		return -ENOMEM;
 
 	of_device_get_modalias(dev, str, size);
-	str[size] = '\0';
+	str[size - 1] = '\0';
 	ret = request_module(str);
 	kfree(str);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/of/dynamic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/of/dynamic.c
@@ -27,7 +27,7 @@
  * @node:	Node to inc refcount, NULL is supported to simplify writing of
  *		callers
  *
- * Returns node.
+ * Return: The node with refcount incremented.
  */
 struct device_node *of_node_get(struct device_node *node)
 {
@@ -104,8 +104,10 @@
  * @arg		- argument of the of notifier
  *
  * Returns the new state of a device based on the notifier used.
- * Returns 0 on device going from enabled to disabled, 1 on device
- * going from disabled to enabled and -1 on no change.
+ *
+ * Return: OF_RECONFIG_CHANGE_REMOVE on device going from enabled to
+ * disabled, OF_RECONFIG_CHANGE_ADD on device going from disabled to
+ * enabled and OF_RECONFIG_NO_CHANGE on no change.
  */
 int of_reconfig_get_state_change(unsigned long action, struct of_reconfig_data *pr)
 {
@@ -372,7 +374,8 @@
  * property structure and the property name & contents. The property's
  * flags have the OF_DYNAMIC bit set so that we can differentiate between
  * dynamically allocated properties and not.
- * Returns the newly allocated property or NULL on out of memory error.
+ *
+ * Return: The newly allocated property or NULL on out of memory error.
  */
 struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags)
 {
@@ -415,7 +418,7 @@
  * another node.  The node data are dynamically allocated and all the node
  * flags have the OF_DYNAMIC & OF_DETACHED bits set.
  *
- * Returns the newly allocated node or NULL on out of memory error.
+ * Return: The newly allocated node or NULL on out of memory error.
  */
 struct device_node *__of_node_dup(const struct device_node *np,
 				  const char *full_name)
@@ -781,7 +784,8 @@
  * Any side-effects of live tree state changes are applied here on
  * success, like creation/destruction of devices and side-effects
  * like creation of sysfs properties and directories.
- * Returns 0 on success, a negative error value in case of an error.
+ *
+ * Return: 0 on success, a negative error value in case of an error.
  * On error the partially applied effects are reverted.
  */
 int of_changeset_apply(struct of_changeset *ocs)
@@ -875,7 +879,8 @@
  * was before the application.
  * Any side-effects like creation/destruction of devices and
  * removal of sysfs properties and directories are applied.
- * Returns 0 on success, a negative error value in case of an error.
+ *
+ * Return: 0 on success, a negative error value in case of an error.
  */
 int of_changeset_revert(struct of_changeset *ocs)
 {
@@ -903,7 +908,8 @@
  * + OF_RECONFIG_ADD_PROPERTY
  * + OF_RECONFIG_REMOVE_PROPERTY,
  * + OF_RECONFIG_UPDATE_PROPERTY
- * Returns 0 on success, a negative error value in case of an error.
+ *
+ * Return: 0 on success, a negative error value in case of an error.
  */
 int of_changeset_action(struct of_changeset *ocs, unsigned long action,
 		struct device_node *np, struct property *prop)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/of/fdt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/of/fdt.c
@@ -282,7 +282,7 @@
  * @dad: Parent struct device_node
  * @nodepp: The device_node tree created by the call
  *
- * It returns the size of unflattened device tree or error code
+ * Return: The size of unflattened device tree or error code
  */
 static int unflatten_dt_nodes(const void *blob,
 			      void *mem,
@@ -315,7 +315,7 @@
 	for (offset = 0;
 	     offset >= 0 && depth >= initial_depth;
 	     offset = fdt_next_node(blob, offset, &depth)) {
-		if (WARN_ON_ONCE(depth >= FDT_MAX_DEPTH))
+		if (WARN_ON_ONCE(depth >= FDT_MAX_DEPTH - 1))
 			continue;
 
 		if (!IS_ENABLED(CONFIG_OF_KOBJ) &&
@@ -349,11 +349,6 @@
 
 /**
  * __unflatten_device_tree - create tree of device_nodes from flat blob
- *
- * unflattens a device-tree, creating the
- * tree of struct device_node. It also fills the "name" and "type"
- * pointers of the nodes so the normal device-tree walking functions
- * can be used.
  * @blob: The blob to expand
  * @dad: Parent device node
  * @mynodes: The device_node tree created by the call
@@ -361,7 +356,11 @@
  * for the resulting tree
  * @detached: if true set OF_DETACHED on @mynodes
  *
- * Returns NULL on failure or the memory chunk containing the unflattened
+ * unflattens a device-tree, creating the tree of struct device_node. It also
+ * fills the "name" and "type" pointers of the nodes so the normal device-tree
+ * walking functions can be used.
+ *
+ * Return: NULL on failure or the memory chunk containing the unflattened
  * device tree on success.
  */
 void *__unflatten_device_tree(const void *blob,
@@ -442,7 +441,7 @@
  * pointers of the nodes so the normal device-tree walking functions
  * can be used.
  *
- * Returns NULL on failure or the memory chunk containing the unflattened
+ * Return: NULL on failure or the memory chunk containing the unflattened
  * device tree on success.
  */
 void *of_fdt_unflatten_tree(const unsigned long *blob,
@@ -501,11 +500,11 @@
 
 		if (size &&
 		    early_init_dt_reserve_memory_arch(base, size, nomap) == 0)
-			pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %ld MiB\n",
-				uname, &base, (unsigned long)size / SZ_1M);
+			pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %lu MiB\n",
+				uname, &base, (unsigned long)(size / SZ_1M));
 		else
-			pr_info("Reserved memory: failed to reserve memory for node '%s': base %pa, size %ld MiB\n",
-				uname, &base, (unsigned long)size / SZ_1M);
+			pr_info("Reserved memory: failed to reserve memory for node '%s': base %pa, size %lu MiB\n",
+				uname, &base, (unsigned long)(size / SZ_1M));
 
 		len -= t_len;
 		if (first) {
@@ -720,7 +719,7 @@
  * @node: node to test
  * @compat: compatible string to compare with compatible list.
  *
- * On match, returns a non-zero value with smaller values returned for more
+ * Return: a non-zero value on match with smaller values returned for more
  * specific compatible values.
  */
 static int of_fdt_is_compatible(const void *blob,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/of/irq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/of/irq.c
@@ -48,7 +48,7 @@
  * of_irq_find_parent - Given a device node, find its interrupt parent node
  * @child: pointer to device node
  *
- * Returns a pointer to the interrupt parent node, or NULL if the interrupt
+ * Return: A pointer to the interrupt parent node, or NULL if the interrupt
  * parent could not be determined.
  */
 struct device_node *of_irq_find_parent(struct device_node *child)
@@ -81,14 +81,14 @@
  * @addr:	address specifier (start of "reg" property of the device) in be32 format
  * @out_irq:	structure of_phandle_args updated by this function
  *
- * Returns 0 on success and a negative number on error
- *
  * This function is a low-level interrupt tree walking function. It
  * can be used to do a partial walk with synthetized reg and interrupts
  * properties, for example when resolving PCI interrupts when no device
  * node exist for the parent. It takes an interrupt specifier structure as
  * input, walks the tree looking for any interrupt-map properties, translates
  * the specifier for each map, and then returns the translated map.
+ *
+ * Return: 0 on success and a negative number on error
  */
 int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
 {
@@ -288,7 +288,8 @@
 	struct device_node *p;
 	const __be32 *addr;
 	u32 intsize;
-	int i, res;
+	int i, res, addr_len;
+	__be32 addr_buf[3] = { 0 };
 
 	pr_debug("of_irq_parse_one: dev=%pOF, index=%d\n", device, index);
 
@@ -297,13 +298,20 @@
 		return of_irq_parse_oldworld(device, index, out_irq);
 
 	/* Get the reg property (if any) */
-	addr = of_get_property(device, "reg", NULL);
+	addr_len = 0;
+	addr = of_get_property(device, "reg", &addr_len);
+
+	/* Prevent out-of-bounds read in case of longer interrupt parent address size */
+	if (addr_len > sizeof(addr_buf))
+		addr_len = sizeof(addr_buf);
+	if (addr)
+		memcpy(addr_buf, addr, addr_len);
 
 	/* Try the new-style interrupts-extended first */
 	res = of_parse_phandle_with_args(device, "interrupts-extended",
 					"#interrupt-cells", index, out_irq);
 	if (!res)
-		return of_irq_parse_raw(addr, out_irq);
+		return of_irq_parse_raw(addr_buf, out_irq);
 
 	/* Look for the interrupt parent. */
 	p = of_irq_find_parent(device);
@@ -333,7 +341,7 @@
 
 
 	/* Check if there are any interrupt-map translations to process */
-	res = of_irq_parse_raw(addr, out_irq);
+	res = of_irq_parse_raw(addr_buf, out_irq);
  out:
 	of_node_put(p);
 	return res;
@@ -380,7 +388,7 @@
  * @dev: pointer to device tree node
  * @index: zero-based index of the IRQ
  *
- * Returns Linux IRQ number on success, or 0 on the IRQ mapping failure, or
+ * Return: Linux IRQ number on success, or 0 on the IRQ mapping failure, or
  * -EPROBE_DEFER if the IRQ domain is not yet created, or error code in case
  * of any other failure.
  */
@@ -407,7 +415,7 @@
  * @dev: pointer to device tree node
  * @name: IRQ name
  *
- * Returns Linux IRQ number on success, or 0 on the IRQ mapping failure, or
+ * Return: Linux IRQ number on success, or 0 on the IRQ mapping failure, or
  * -EPROBE_DEFER if the IRQ domain is not yet created, or error code in case
  * of any other failure.
  */
@@ -447,7 +455,7 @@
  * @res: array of resources to fill in
  * @nr_irqs: the number of IRQs (and upper bound for num of @res elements)
  *
- * Returns the size of the filled in table (up to @nr_irqs).
+ * Return: The size of the filled in table (up to @nr_irqs).
  */
 int of_irq_to_resource_table(struct device_node *dev, struct resource *res,
 		int nr_irqs)
@@ -576,55 +584,57 @@
 	}
 }
 
-static u32 __of_msi_map_rid(struct device *dev, struct device_node **np,
-			    u32 rid_in)
+static u32 __of_msi_map_id(struct device *dev, struct device_node **np,
+			    u32 id_in)
 {
 	struct device *parent_dev;
-	u32 rid_out = rid_in;
+	u32 id_out = id_in;
 
 	/*
 	 * Walk up the device parent links looking for one with a
 	 * "msi-map" property.
 	 */
 	for (parent_dev = dev; parent_dev; parent_dev = parent_dev->parent)
-		if (!of_map_rid(parent_dev->of_node, rid_in, "msi-map",
-				"msi-map-mask", np, &rid_out))
+		if (!of_map_id(parent_dev->of_node, id_in, "msi-map",
+				"msi-map-mask", np, &id_out))
 			break;
-	return rid_out;
+	return id_out;
 }
 
 /**
- * of_msi_map_rid - Map a MSI requester ID for a device.
+ * of_msi_map_id - Map a MSI ID for a device.
  * @dev: device for which the mapping is to be done.
  * @msi_np: device node of the expected msi controller.
- * @rid_in: unmapped MSI requester ID for the device.
+ * @id_in: unmapped MSI ID for the device.
  *
  * Walk up the device hierarchy looking for devices with a "msi-map"
- * property.  If found, apply the mapping to @rid_in.
+ * property.  If found, apply the mapping to @id_in.
  *
- * Returns the mapped MSI requester ID.
+ * Return: The mapped MSI ID.
  */
-u32 of_msi_map_rid(struct device *dev, struct device_node *msi_np, u32 rid_in)
+u32 of_msi_map_id(struct device *dev, struct device_node *msi_np, u32 id_in)
 {
-	return __of_msi_map_rid(dev, &msi_np, rid_in);
+	return __of_msi_map_id(dev, &msi_np, id_in);
 }
 
 /**
  * of_msi_map_get_device_domain - Use msi-map to find the relevant MSI domain
  * @dev: device for which the mapping is to be done.
- * @rid: Requester ID for the device.
+ * @id: Device ID.
+ * @bus_token: Bus token
  *
  * Walk up the device hierarchy looking for devices with a "msi-map"
  * property.
  *
  * Returns: the MSI domain for this device (or NULL on failure)
  */
-struct irq_domain *of_msi_map_get_device_domain(struct device *dev, u32 rid)
+struct irq_domain *of_msi_map_get_device_domain(struct device *dev, u32 id,
+						u32 bus_token)
 {
 	struct device_node *np = NULL;
 
-	__of_msi_map_rid(dev, &np, rid);
-	return irq_find_matching_host(np, DOMAIN_BUS_PCI_MSI);
+	__of_msi_map_id(dev, &np, id);
+	return irq_find_matching_host(np, bus_token);
 }
 
 /**
@@ -633,8 +643,7 @@
  * @np: device node for @dev
  * @token: bus type for this domain
  *
- * Parse the msi-parent property (both the simple and the complex
- * versions), and returns the corresponding MSI domain.
+ * Parse the msi-parent property and returns the corresponding MSI domain.
  *
  * Returns: the MSI domain for this device (or NULL on failure).
  */
@@ -642,33 +651,14 @@
 				     struct device_node *np,
 				     enum irq_domain_bus_token token)
 {
-	struct device_node *msi_np;
+	struct of_phandle_iterator it;
 	struct irq_domain *d;
+	int err;
 
-	/* Check for a single msi-parent property */
-	msi_np = of_parse_phandle(np, "msi-parent", 0);
-	if (msi_np && !of_property_read_bool(msi_np, "#msi-cells")) {
-		d = irq_find_matching_host(msi_np, token);
-		if (!d)
-			of_node_put(msi_np);
-		return d;
-	}
-
-	if (token == DOMAIN_BUS_PLATFORM_MSI) {
-		/* Check for the complex msi-parent version */
-		struct of_phandle_args args;
-		int index = 0;
-
-		while (!of_parse_phandle_with_args(np, "msi-parent",
-						   "#msi-cells",
-						   index, &args)) {
-			d = irq_find_matching_host(args.np, token);
-			if (d)
-				return d;
-
-			of_node_put(args.np);
-			index++;
-		}
+	of_for_each_phandle(&it, err, np, "msi-parent", "#msi-cells", 0) {
+		d = irq_find_matching_host(it.node, token);
+		if (d)
+			return d;
 	}
 
 	return NULL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/of/kobj.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/of/kobj.c
@@ -119,7 +119,7 @@
 	struct property *pp;
 	int rc;
 
-	if (!of_kset)
+	if (!IS_ENABLED(CONFIG_SYSFS) || !of_kset)
 		return 0;
 
 	np->kobj.kset = of_kset;
@@ -134,8 +134,6 @@
 	if (!name)
 		return -ENOMEM;
 
-	of_node_get(np);
-
 	rc = kobject_add(&np->kobj, parent, "%s", name);
 	kfree(name);
 	if (rc)
@@ -144,6 +142,7 @@
 	for_each_property_of_node(np, pp)
 		__of_add_property_sysfs(np, pp);
 
+	of_node_get(np);
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/of/of_mdio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/of/of_mdio.c
@@ -265,8 +265,14 @@
 				 child, addr);
 
 			if (of_mdiobus_child_is_phy(child)) {
+				/* -ENODEV is the return code that PHYLIB has
+				 * standardized on to indicate that bus
+				 * scanning should continue.
+				 */
 				rc = of_mdiobus_register_phy(mdio, child, addr);
-				if (rc && rc != -ENODEV)
+				if (!rc)
+					break;
+				if (rc != -ENODEV)
 					goto unregister;
 			}
 		}
@@ -275,6 +281,7 @@
 	return 0;
 
 unregister:
+	of_node_put(child);
 	mdiobus_unregister(mdio);
 	return rc;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/of/of_reserved_mem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/of/of_reserved_mem.c
@@ -134,9 +134,9 @@
 			ret = early_init_dt_alloc_reserved_memory_arch(size,
 					align, start, end, nomap, &base);
 			if (ret == 0) {
-				pr_debug("allocated memory for '%s' node: base %pa, size %ld MiB\n",
+				pr_debug("allocated memory for '%s' node: base %pa, size %lu MiB\n",
 					uname, &base,
-					(unsigned long)size / SZ_1M);
+					(unsigned long)(size / SZ_1M));
 				break;
 			}
 			len -= t_len;
@@ -146,8 +146,8 @@
 		ret = early_init_dt_alloc_reserved_memory_arch(size, align,
 							0, 0, nomap, &base);
 		if (ret == 0)
-			pr_debug("allocated memory for '%s' node: base %pa, size %ld MiB\n",
-				uname, &base, (unsigned long)size / SZ_1M);
+			pr_debug("allocated memory for '%s' node: base %pa, size %lu MiB\n",
+				uname, &base, (unsigned long)(size / SZ_1M));
 	}
 
 	if (base == 0) {
@@ -200,6 +200,16 @@
 	if (ra->base > rb->base)
 		return 1;
 
+	/*
+	 * Put the dynamic allocations (address == 0, size == 0) before static
+	 * allocations at address 0x0 so that overlap detection works
+	 * correctly.
+	 */
+	if (ra->size < rb->size)
+		return -1;
+	if (ra->size > rb->size)
+		return 1;
+
 	return 0;
 }
 
@@ -217,8 +227,7 @@
 
 		this = &reserved_mem[i];
 		next = &reserved_mem[i + 1];
-		if (!(this->base && next->base))
-			continue;
+
 		if (this->base + this->size > next->base) {
 			phys_addr_t this_end, next_end;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/of/overlay.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/of/overlay.c
@@ -170,9 +170,7 @@
 
 		ret = blocking_notifier_call_chain(&overlay_notify_chain,
 						   action, &nd);
-		if (ret == NOTIFY_OK || ret == NOTIFY_STOP)
-			return 0;
-		if (ret) {
+		if (notifier_to_errno(ret)) {
 			ret = notifier_to_errno(ret);
 			pr_err("overlay changeset %s notifier error %d, target: %pOF\n",
 			       of_overlay_action_name[action], ret, nd.target);
@@ -261,6 +259,8 @@
 
 	of_property_set_flag(new_prop, OF_DYNAMIC);
 
+	kfree(target_path);
+
 	return new_prop;
 
 err_free_new_prop:
@@ -296,7 +296,7 @@
  *
  * Update of property in symbols node is not allowed.
  *
- * Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if
+ * Return: 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if
  * invalid @overlay.
  */
 static int add_changeset_property(struct overlay_changeset *ovcs,
@@ -305,7 +305,6 @@
 {
 	struct property *new_prop = NULL, *prop;
 	int ret = 0;
-	bool check_for_non_overlay_node = false;
 
 	if (target->in_livetree)
 		if (!of_prop_cmp(overlay_prop->name, "name") ||
@@ -318,6 +317,25 @@
 	else
 		prop = NULL;
 
+	if (prop) {
+		if (!of_prop_cmp(prop->name, "#address-cells")) {
+			if (!of_prop_val_eq(prop, overlay_prop)) {
+				pr_err("ERROR: changing value of #address-cells is not allowed in %pOF\n",
+				       target->np);
+				ret = -EINVAL;
+			}
+			return ret;
+
+		} else if (!of_prop_cmp(prop->name, "#size-cells")) {
+			if (!of_prop_val_eq(prop, overlay_prop)) {
+				pr_err("ERROR: changing value of #size-cells is not allowed in %pOF\n",
+				       target->np);
+				ret = -EINVAL;
+			}
+			return ret;
+		}
+	}
+
 	if (is_symbols_prop) {
 		if (prop)
 			return -EINVAL;
@@ -330,33 +348,18 @@
 		return -ENOMEM;
 
 	if (!prop) {
-		check_for_non_overlay_node = true;
 		if (!target->in_livetree) {
 			new_prop->next = target->np->deadprops;
 			target->np->deadprops = new_prop;
 		}
 		ret = of_changeset_add_property(&ovcs->cset, target->np,
 						new_prop);
-	} else if (!of_prop_cmp(prop->name, "#address-cells")) {
-		if (!of_prop_val_eq(prop, new_prop)) {
-			pr_err("ERROR: changing value of #address-cells is not allowed in %pOF\n",
-			       target->np);
-			ret = -EINVAL;
-		}
-	} else if (!of_prop_cmp(prop->name, "#size-cells")) {
-		if (!of_prop_val_eq(prop, new_prop)) {
-			pr_err("ERROR: changing value of #size-cells is not allowed in %pOF\n",
-			       target->np);
-			ret = -EINVAL;
-		}
 	} else {
-		check_for_non_overlay_node = true;
 		ret = of_changeset_update_property(&ovcs->cset, target->np,
 						   new_prop);
 	}
 
-	if (check_for_non_overlay_node &&
-	    !of_node_check_flag(target->np, OF_OVERLAY))
+	if (!of_node_check_flag(target->np, OF_OVERLAY))
 		pr_err("WARNING: memory leak will occur if overlay removed, property: %pOF/%s\n",
 		       target->np, new_prop->name);
 
@@ -398,7 +401,7 @@
  *
  * NOTE_2: Multiple mods of created nodes not supported.
  *
- * Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if
+ * Return: 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if
  * invalid @overlay.
  */
 static int add_changeset_node(struct overlay_changeset *ovcs,
@@ -470,7 +473,7 @@
  *
  * Do not allow symbols node to have any children.
  *
- * Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if
+ * Return: 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if
  * invalid @overlay_node.
  */
 static int build_changeset_next_level(struct overlay_changeset *ovcs,
@@ -544,7 +547,7 @@
 
 		fn_1 = kasprintf(GFP_KERNEL, "%pOF", ce_1->np);
 		fn_2 = kasprintf(GFP_KERNEL, "%pOF", ce_2->np);
-		node_path_match = !strcmp(fn_1, fn_2);
+		node_path_match = !fn_1 || !fn_2 || !strcmp(fn_1, fn_2);
 		kfree(fn_1);
 		kfree(fn_2);
 		if (node_path_match) {
@@ -579,7 +582,7 @@
 
 		fn_1 = kasprintf(GFP_KERNEL, "%pOF", ce_1->np);
 		fn_2 = kasprintf(GFP_KERNEL, "%pOF", ce_2->np);
-		node_path_match = !strcmp(fn_1, fn_2);
+		node_path_match = !fn_1 || !fn_2 || !strcmp(fn_1, fn_2);
 		kfree(fn_1);
 		kfree(fn_2);
 		if (node_path_match &&
@@ -601,7 +604,7 @@
  * the same node or duplicate {add, delete, or update} properties entries
  * for the same property.
  *
- * Returns 0 on success, or -EINVAL if duplicate changeset entry found.
+ * Return: 0 on success, or -EINVAL if duplicate changeset entry found.
  */
 static int changeset_dup_entry_check(struct overlay_changeset *ovcs)
 {
@@ -625,7 +628,7 @@
  * any portions of the changeset that were successfully created will remain
  * in @ovcs->cset.
  *
- * Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if
+ * Return: 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if
  * invalid overlay in @ovcs->fragments[].
  */
 static int build_changeset(struct overlay_changeset *ovcs)
@@ -721,7 +724,7 @@
  * the top level of @tree.  The relevant top level nodes are the fragment
  * nodes and the __symbols__ node.  Any other top level node will be ignored.
  *
- * Returns 0 on success, -ENOMEM if memory allocation failure, -EINVAL if error
+ * Return: 0 on success, -ENOMEM if memory allocation failure, -EINVAL if error
  * detected in @tree, or -ENOSPC if idr_alloc() error.
  */
 static int init_overlay_changeset(struct overlay_changeset *ovcs,
@@ -1177,7 +1180,7 @@
  * If an error is returned by an overlay changeset post-remove notifier
  * then no further overlay changeset post-remove notifier will be called.
  *
- * Returns 0 on success, or a negative error number.  *ovcs_id is set to
+ * Return: 0 on success, or a negative error number.  *ovcs_id is set to
  * zero after reverting the changeset, even if a subsequent error occurs.
  */
 int of_overlay_remove(int *ovcs_id)
@@ -1264,7 +1267,7 @@
  *
  * Removes all overlays from the system in the correct order.
  *
- * Returns 0 on success, or a negative error number
+ * Return: 0 on success, or a negative error number
  */
 int of_overlay_remove_all(void)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/of/platform.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/of/platform.c
@@ -44,7 +44,7 @@
  * Takes a reference to the embedded struct device which needs to be dropped
  * after use.
  *
- * Returns platform_device pointer, or NULL if not found
+ * Return: platform_device pointer, or NULL if not found
  */
 struct platform_device *of_find_device_by_node(struct device_node *np)
 {
@@ -160,7 +160,7 @@
  * @platform_data: pointer to populate platform_data pointer with
  * @parent: Linux device model parent device.
  *
- * Returns pointer to created platform device, or NULL if a device was not
+ * Return: Pointer to created platform device, or NULL if a device was not
  * registered.  Unavailable devices will not get registered.
  */
 static struct platform_device *of_platform_device_create_pdata(
@@ -204,7 +204,7 @@
  * @bus_id: name to assign device
  * @parent: Linux device model parent device.
  *
- * Returns pointer to created platform device, or NULL if a device was not
+ * Return: Pointer to created platform device, or NULL if a device was not
  * registered.  Unavailable devices will not get registered.
  */
 struct platform_device *of_platform_device_create(struct device_node *np,
@@ -463,7 +463,7 @@
  * New board support should be using this function instead of
  * of_platform_bus_probe().
  *
- * Returns 0 on success, < 0 on failure.
+ * Return: 0 on success, < 0 on failure.
  */
 int of_platform_populate(struct device_node *root,
 			const struct of_device_id *matches,
@@ -594,7 +594,7 @@
  * Similar to of_platform_populate(), but will automatically call
  * of_platform_depopulate() when the device is unbound from the bus.
  *
- * Returns 0 on success, < 0 on failure.
+ * Return: 0 on success, < 0 on failure.
  */
 int devm_of_platform_populate(struct device *dev)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/of/property.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/of/property.c
@@ -36,9 +36,11 @@
  * @elem_size:	size of the individual element
  *
  * Search for a property in a device node and count the number of elements of
- * size elem_size in it. Returns number of elements on sucess, -EINVAL if the
- * property does not exist or its length does not match a multiple of elem_size
- * and -ENODATA if the property does not have a value.
+ * size elem_size in it.
+ *
+ * Return: The number of elements on sucess, -EINVAL if the property does not
+ * exist or its length does not match a multiple of elem_size and -ENODATA if
+ * the property does not have a value.
  */
 int of_property_count_elems_of_size(const struct device_node *np,
 				const char *propname, int elem_size)
@@ -70,8 +72,9 @@
  * @len:	if !=NULL, actual length is written to here
  *
  * Search for a property in a device node and valid the requested size.
- * Returns the property value on success, -EINVAL if the property does not
- *  exist, -ENODATA if property does not have a value, and -EOVERFLOW if the
+ *
+ * Return: The property value on success, -EINVAL if the property does not
+ * exist, -ENODATA if property does not have a value, and -EOVERFLOW if the
  * property data is too small or too large.
  *
  */
@@ -104,7 +107,9 @@
  * @out_value:	pointer to return value, modified only if no error.
  *
  * Search for a property in a device node and read nth 32-bit value from
- * it. Returns 0 on success, -EINVAL if the property does not exist,
+ * it.
+ *
+ * Return: 0 on success, -EINVAL if the property does not exist,
  * -ENODATA if property does not have a value, and -EOVERFLOW if the
  * property data isn't large enough.
  *
@@ -136,7 +141,9 @@
  * @out_value:	pointer to return value, modified only if no error.
  *
  * Search for a property in a device node and read nth 64-bit value from
- * it. Returns 0 on success, -EINVAL if the property does not exist,
+ * it.
+ *
+ * Return: 0 on success, -EINVAL if the property does not exist,
  * -ENODATA if property does not have a value, and -EOVERFLOW if the
  * property data isn't large enough.
  *
@@ -171,12 +178,14 @@
  *		sz_min will be read.
  *
  * Search for a property in a device node and read 8-bit value(s) from
- * it. Returns number of elements read on success, -EINVAL if the property
- * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW
- * if the property data is smaller than sz_min or longer than sz_max.
+ * it.
  *
  * dts entry of array should be like:
- *	property = /bits/ 8 <0x50 0x60 0x70>;
+ *  ``property = /bits/ 8 <0x50 0x60 0x70>;``
+ *
+ * Return: The number of elements read on success, -EINVAL if the property
+ * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW
+ * if the property data is smaller than sz_min or longer than sz_max.
  *
  * The out_values is modified only if a valid u8 value can be decoded.
  */
@@ -219,12 +228,14 @@
  *		sz_min will be read.
  *
  * Search for a property in a device node and read 16-bit value(s) from
- * it. Returns number of elements read on success, -EINVAL if the property
- * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW
- * if the property data is smaller than sz_min or longer than sz_max.
+ * it.
  *
  * dts entry of array should be like:
- *	property = /bits/ 16 <0x5000 0x6000 0x7000>;
+ *  ``property = /bits/ 16 <0x5000 0x6000 0x7000>;``
+ *
+ * Return: The number of elements read on success, -EINVAL if the property
+ * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW
+ * if the property data is smaller than sz_min or longer than sz_max.
  *
  * The out_values is modified only if a valid u16 value can be decoded.
  */
@@ -267,7 +278,9 @@
  *		sz_min will be read.
  *
  * Search for a property in a device node and read 32-bit value(s) from
- * it. Returns number of elements read on success, -EINVAL if the property
+ * it.
+ *
+ * Return: The number of elements read on success, -EINVAL if the property
  * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW
  * if the property data is smaller than sz_min or longer than sz_max.
  *
@@ -306,7 +319,9 @@
  * @out_value:	pointer to return value, modified only if return value is 0.
  *
  * Search for a property in a device node and read a 64-bit value from
- * it. Returns 0 on success, -EINVAL if the property does not exist,
+ * it.
+ *
+ * Return: 0 on success, -EINVAL if the property does not exist,
  * -ENODATA if property does not have a value, and -EOVERFLOW if the
  * property data isn't large enough.
  *
@@ -341,7 +356,9 @@
  *		sz_min will be read.
  *
  * Search for a property in a device node and read 64-bit value(s) from
- * it. Returns number of elements read on success, -EINVAL if the property
+ * it.
+ *
+ * Return: The number of elements read on success, -EINVAL if the property
  * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW
  * if the property data is smaller than sz_min or longer than sz_max.
  *
@@ -383,10 +400,11 @@
  *		return value is 0.
  *
  * Search for a property in a device tree node and retrieve a null
- * terminated string value (pointer to data, not a copy). Returns 0 on
- * success, -EINVAL if the property does not exist, -ENODATA if property
- * does not have a value, and -EILSEQ if the string is not null-terminated
- * within the length of the property data.
+ * terminated string value (pointer to data, not a copy).
+ *
+ * Return: 0 on success, -EINVAL if the property does not exist, -ENODATA if
+ * property does not have a value, and -EILSEQ if the string is not
+ * null-terminated within the length of the property data.
  *
  * The out_string pointer is modified only if a valid string can be decoded.
  */
@@ -750,7 +768,7 @@
  * @node: pointer to a local endpoint device_node
  *
  * Return: Remote port node associated with remote endpoint node linked
- *	   to @node. Use of_node_put() on it when done.
+ * to @node. Use of_node_put() on it when done.
  */
 struct device_node *of_graph_get_remote_port(const struct device_node *node)
 {
@@ -783,7 +801,7 @@
  * @endpoint: identifier (value of reg property) of the endpoint node
  *
  * Return: Remote device node associated with remote endpoint node linked
- *	   to @node. Use of_node_put() on it when done.
+ * to @node. Use of_node_put() on it when done.
  */
 struct device_node *of_graph_get_remote_node(const struct device_node *node,
 					     u32 port, u32 endpoint)
@@ -918,8 +936,10 @@
 						       nargs, index, &of_args);
 	if (ret < 0)
 		return ret;
-	if (!args)
+	if (!args) {
+		of_node_put(of_args.np);
 		return 0;
+	}
 
 	args->nargs = of_args.args_count;
 	args->fwnode = of_fwnode_handle(of_args.np);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/of/unittest-data/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/of/unittest-data/Makefile
@@ -21,7 +21,13 @@
 			    overlay_bad_add_dup_prop.dtb.o \
 			    overlay_bad_phandle.dtb.o \
 			    overlay_bad_symbol.dtb.o \
-			    overlay_base.dtb.o
+			    overlay_base.dtb.o \
+			    overlay_gpio_01.dtb.o \
+			    overlay_gpio_02a.dtb.o \
+			    overlay_gpio_02b.dtb.o \
+			    overlay_gpio_03.dtb.o \
+			    overlay_gpio_04a.dtb.o \
+			    overlay_gpio_04b.dtb.o
 
 # enable creation of __symbols__ node
 DTC_FLAGS_overlay += -@
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/of/unittest-data/overlay_gpio_01.dts
+++ linux-xilinx-zynqmp-5.4.0/drivers/of/unittest-data/overlay_gpio_01.dts
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+&unittest_test_bus {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	gpio@0 {
+		compatible = "unittest-gpio";
+		reg = <0>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		ngpios = <2>;
+		gpio-line-names = "line-A", "line-B";
+
+		line-b {
+			gpio-hog;
+			gpios = <2 0>;
+			input;
+			line-name = "line-B-input";
+		};
+	};
+};
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/of/unittest-data/overlay_gpio_02a.dts
+++ linux-xilinx-zynqmp-5.4.0/drivers/of/unittest-data/overlay_gpio_02a.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+&unittest_test_bus {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	gpio@2 {
+		compatible = "unittest-gpio";
+		reg = <2>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		ngpios = <2>;
+		gpio-line-names = "line-A", "line-B";
+	};
+};
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/of/unittest-data/overlay_gpio_02b.dts
+++ linux-xilinx-zynqmp-5.4.0/drivers/of/unittest-data/overlay_gpio_02b.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+&unittest_test_bus {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	gpio@2 {
+		line-a {
+			gpio-hog;
+			gpios = <1 0>;
+			input;
+			line-name = "line-A-input";
+		};
+	};
+};
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/of/unittest-data/overlay_gpio_03.dts
+++ linux-xilinx-zynqmp-5.4.0/drivers/of/unittest-data/overlay_gpio_03.dts
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+&unittest_test_bus {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	gpio@3 {
+		compatible = "unittest-gpio";
+		reg = <3>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		ngpios = <2>;
+		gpio-line-names = "line-A", "line-B", "line-C", "line-D";
+
+		line-d {
+			gpio-hog;
+			gpios = <4 0>;
+			input;
+			line-name = "line-D-input";
+		};
+	};
+};
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/of/unittest-data/overlay_gpio_04a.dts
+++ linux-xilinx-zynqmp-5.4.0/drivers/of/unittest-data/overlay_gpio_04a.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+&unittest_test_bus {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	gpio@4 {
+		compatible = "unittest-gpio";
+		reg = <4>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		ngpios = <2>;
+		gpio-line-names = "line-A", "line-B", "line-C", "line-D";
+	};
+};
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/of/unittest-data/overlay_gpio_04b.dts
+++ linux-xilinx-zynqmp-5.4.0/drivers/of/unittest-data/overlay_gpio_04b.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+&unittest_test_bus {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	gpio@4 {
+		line-c {
+			gpio-hog;
+			gpios = <3 0>;
+			input;
+			line-name = "line-C-input";
+		};
+	};
+};
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/of/unittest-data/tests-phandle.dtsi
+++ linux-xilinx-zynqmp-5.4.0/drivers/of/unittest-data/tests-phandle.dtsi
@@ -38,6 +38,13 @@
 				phandle-map-pass-thru = <0x0 0xf0>;
 			};
 
+			provider5: provider5 {
+				#phandle-cells = <2>;
+				phandle-map = <2 7 &provider4 2 3>;
+				phandle-map-mask = <0xff 0xf>;
+				phandle-map-pass-thru = <0x0 0xf0>;
+			};
+
 			consumer-a {
 				phandle-list =	<&provider1 1>,
 						<&provider2 2 0>,
@@ -64,7 +71,8 @@
 						<&provider4 4 0x100>,
 						<&provider4 0 0x61>,
 						<&provider0>,
-						<&provider4 19 0x20>;
+						<&provider4 19 0x20>,
+						<&provider5 2 7>;
 				phandle-list-bad-phandle = <12345678 0 0>;
 				phandle-list-bad-args = <&provider2 1 0>,
 							<&provider4 0>;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/of/unittest.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/of/unittest.c
@@ -23,6 +23,7 @@
 
 #include <linux/i2c.h>
 #include <linux/i2c-mux.h>
+#include <linux/gpio/driver.h>
 
 #include <linux/bitops.h>
 
@@ -45,6 +46,103 @@
 	failed; \
 })
 
+#ifdef CONFIG_OF_KOBJ
+#define OF_KREF_READ(NODE) kref_read(&(NODE)->kobj.kref)
+#else
+#define OF_KREF_READ(NODE) 1
+#endif
+
+/*
+ * Expected message may have a message level other than KERN_INFO.
+ * Print the expected message only if the current loglevel will allow
+ * the actual message to print.
+ */
+#define EXPECT_BEGIN(level, fmt, ...) \
+	printk(level pr_fmt("EXPECT \\ : ") fmt, ##__VA_ARGS__)
+
+#define EXPECT_END(level, fmt, ...) \
+	printk(level pr_fmt("EXPECT / : ") fmt, ##__VA_ARGS__)
+
+struct unittest_gpio_dev {
+	struct gpio_chip chip;
+};
+
+static int unittest_gpio_chip_request_count;
+static int unittest_gpio_probe_count;
+static int unittest_gpio_probe_pass_count;
+
+static int unittest_gpio_chip_request(struct gpio_chip *chip, unsigned int offset)
+{
+	unittest_gpio_chip_request_count++;
+
+	pr_debug("%s(): %s %d %d\n", __func__, chip->label, offset,
+		 unittest_gpio_chip_request_count);
+	return 0;
+}
+
+static int unittest_gpio_probe(struct platform_device *pdev)
+{
+	struct unittest_gpio_dev *devptr;
+	int ret;
+
+	unittest_gpio_probe_count++;
+
+	devptr = kzalloc(sizeof(*devptr), GFP_KERNEL);
+	if (!devptr)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, devptr);
+
+	devptr->chip.of_node = pdev->dev.of_node;
+	devptr->chip.label = "of-unittest-gpio";
+	devptr->chip.base = -1; /* dynamic allocation */
+	devptr->chip.ngpio = 5;
+	devptr->chip.request = unittest_gpio_chip_request;
+
+	ret = gpiochip_add_data(&devptr->chip, NULL);
+
+	unittest(!ret,
+		 "gpiochip_add_data() for node @%pOF failed, ret = %d\n", devptr->chip.of_node, ret);
+
+	if (!ret)
+		unittest_gpio_probe_pass_count++;
+	return ret;
+}
+
+static int unittest_gpio_remove(struct platform_device *pdev)
+{
+	struct unittest_gpio_dev *gdev = platform_get_drvdata(pdev);
+	struct device *dev = &pdev->dev;
+	struct device_node *np = pdev->dev.of_node;
+
+	dev_dbg(dev, "%s for node @%pOF\n", __func__, np);
+
+	if (!gdev)
+		return -EINVAL;
+
+	if (gdev->chip.base != -1)
+		gpiochip_remove(&gdev->chip);
+
+	platform_set_drvdata(pdev, NULL);
+	kfree(gdev);
+
+	return 0;
+}
+
+static const struct of_device_id unittest_gpio_id[] = {
+	{ .compatible = "unittest-gpio", },
+	{}
+};
+
+static struct platform_driver unittest_gpio_driver = {
+	.probe	= unittest_gpio_probe,
+	.remove	= unittest_gpio_remove,
+	.driver	= {
+		.name		= "unittest-gpio",
+		.of_match_table	= of_match_ptr(unittest_gpio_id),
+	},
+};
+
 static void __init of_unittest_find_node_by_name(void)
 {
 	struct device_node *np;
@@ -52,7 +150,7 @@
 
 	np = of_find_node_by_path("/testcase-data");
 	name = kasprintf(GFP_KERNEL, "%pOF", np);
-	unittest(np && !strcmp("/testcase-data", name),
+	unittest(np && name && !strcmp("/testcase-data", name),
 		"find /testcase-data failed\n");
 	of_node_put(np);
 	kfree(name);
@@ -63,14 +161,14 @@
 
 	np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a");
 	name = kasprintf(GFP_KERNEL, "%pOF", np);
-	unittest(np && !strcmp("/testcase-data/phandle-tests/consumer-a", name),
+	unittest(np && name && !strcmp("/testcase-data/phandle-tests/consumer-a", name),
 		"find /testcase-data/phandle-tests/consumer-a failed\n");
 	of_node_put(np);
 	kfree(name);
 
 	np = of_find_node_by_path("testcase-alias");
 	name = kasprintf(GFP_KERNEL, "%pOF", np);
-	unittest(np && !strcmp("/testcase-data", name),
+	unittest(np && name && !strcmp("/testcase-data", name),
 		"find testcase-alias failed\n");
 	of_node_put(np);
 	kfree(name);
@@ -81,7 +179,7 @@
 
 	np = of_find_node_by_path("testcase-alias/phandle-tests/consumer-a");
 	name = kasprintf(GFP_KERNEL, "%pOF", np);
-	unittest(np && !strcmp("/testcase-data/phandle-tests/consumer-a", name),
+	unittest(np && name && !strcmp("/testcase-data/phandle-tests/consumer-a", name),
 		"find testcase-alias/phandle-tests/consumer-a failed\n");
 	of_node_put(np);
 	kfree(name);
@@ -430,6 +528,9 @@
 
 		unittest(passed, "index %i - data error on node %pOF rc=%i\n",
 			 i, args.np, rc);
+
+		if (rc == 0)
+			of_node_put(args.np);
 	}
 
 	/* Check for missing list property */
@@ -471,8 +572,9 @@
 
 static void __init of_unittest_parse_phandle_with_args_map(void)
 {
-	struct device_node *np, *p0, *p1, *p2, *p3;
+	struct device_node *np, *p[6] = {};
 	struct of_phandle_args args;
+	unsigned int prefs[6];
 	int i, rc;
 
 	np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-b");
@@ -481,34 +583,24 @@
 		return;
 	}
 
-	p0 = of_find_node_by_path("/testcase-data/phandle-tests/provider0");
-	if (!p0) {
-		pr_err("missing testcase data\n");
-		return;
-	}
-
-	p1 = of_find_node_by_path("/testcase-data/phandle-tests/provider1");
-	if (!p1) {
-		pr_err("missing testcase data\n");
-		return;
-	}
-
-	p2 = of_find_node_by_path("/testcase-data/phandle-tests/provider2");
-	if (!p2) {
-		pr_err("missing testcase data\n");
-		return;
-	}
-
-	p3 = of_find_node_by_path("/testcase-data/phandle-tests/provider3");
-	if (!p3) {
-		pr_err("missing testcase data\n");
-		return;
+	p[0] = of_find_node_by_path("/testcase-data/phandle-tests/provider0");
+	p[1] = of_find_node_by_path("/testcase-data/phandle-tests/provider1");
+	p[2] = of_find_node_by_path("/testcase-data/phandle-tests/provider2");
+	p[3] = of_find_node_by_path("/testcase-data/phandle-tests/provider3");
+	p[4] = of_find_node_by_path("/testcase-data/phandle-tests/provider4");
+	p[5] = of_find_node_by_path("/testcase-data/phandle-tests/provider5");
+	for (i = 0; i < ARRAY_SIZE(p); ++i) {
+		if (!p[i]) {
+			pr_err("missing testcase data\n");
+			return;
+		}
+		prefs[i] = OF_KREF_READ(p[i]);
 	}
 
 	rc = of_count_phandle_with_args(np, "phandle-list", "#phandle-cells");
-	unittest(rc == 7, "of_count_phandle_with_args() returned %i, expected 7\n", rc);
+	unittest(rc == 8, "of_count_phandle_with_args() returned %i, expected 8\n", rc);
 
-	for (i = 0; i < 8; i++) {
+	for (i = 0; i < 9; i++) {
 		bool passed = true;
 
 		memset(&args, 0, sizeof(args));
@@ -519,13 +611,13 @@
 		switch (i) {
 		case 0:
 			passed &= !rc;
-			passed &= (args.np == p1);
+			passed &= (args.np == p[1]);
 			passed &= (args.args_count == 1);
 			passed &= (args.args[0] == 1);
 			break;
 		case 1:
 			passed &= !rc;
-			passed &= (args.np == p3);
+			passed &= (args.np == p[3]);
 			passed &= (args.args_count == 3);
 			passed &= (args.args[0] == 2);
 			passed &= (args.args[1] == 5);
@@ -536,28 +628,36 @@
 			break;
 		case 3:
 			passed &= !rc;
-			passed &= (args.np == p0);
+			passed &= (args.np == p[0]);
 			passed &= (args.args_count == 0);
 			break;
 		case 4:
 			passed &= !rc;
-			passed &= (args.np == p1);
+			passed &= (args.np == p[1]);
 			passed &= (args.args_count == 1);
 			passed &= (args.args[0] == 3);
 			break;
 		case 5:
 			passed &= !rc;
-			passed &= (args.np == p0);
+			passed &= (args.np == p[0]);
 			passed &= (args.args_count == 0);
 			break;
 		case 6:
 			passed &= !rc;
-			passed &= (args.np == p2);
+			passed &= (args.np == p[2]);
 			passed &= (args.args_count == 2);
 			passed &= (args.args[0] == 15);
 			passed &= (args.args[1] == 0x20);
 			break;
 		case 7:
+			passed &= !rc;
+			passed &= (args.np == p[3]);
+			passed &= (args.args_count == 3);
+			passed &= (args.args[0] == 2);
+			passed &= (args.args[1] == 5);
+			passed &= (args.args[2] == 3);
+			break;
+		case 8:
 			passed &= (rc == -ENOENT);
 			break;
 		default:
@@ -566,6 +666,9 @@
 
 		unittest(passed, "index %i - data error on node %s rc=%i\n",
 			 i, args.np->full_name, rc);
+
+		if (rc == 0)
+			of_node_put(args.np);
 	}
 
 	/* Check for missing list property */
@@ -591,6 +694,13 @@
 	rc = of_parse_phandle_with_args_map(np, "phandle-list-bad-args",
 					    "phandle", 1, &args);
 	unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc);
+
+	for (i = 0; i < ARRAY_SIZE(p); ++i) {
+		unittest(prefs[i] == OF_KREF_READ(p[i]),
+			 "provider%d: expected:%d got:%d\n",
+			 i, prefs[i], OF_KREF_READ(p[i]));
+		of_node_put(p[i]);
+	}
 }
 
 static void __init of_unittest_property_string(void)
@@ -776,6 +886,10 @@
 	unittest(!of_changeset_revert(&chgset), "revert failed\n");
 
 	of_changeset_destroy(&chgset);
+
+	of_node_put(n1);
+	of_node_put(n2);
+	of_node_put(n21);
 #endif
 }
 
@@ -1061,10 +1175,13 @@
 
 	of_platform_populate(np, match, NULL, &test_bus->dev);
 	for_each_child_of_node(np, child) {
-		for_each_child_of_node(child, grandchild)
-			unittest(of_find_device_by_node(grandchild),
+		for_each_child_of_node(child, grandchild) {
+			pdev = of_find_device_by_node(grandchild);
+			unittest(pdev,
 				 "Could not create device for node '%pOFn'\n",
 				 grandchild);
+			of_dev_put(pdev);
+		}
 	}
 
 	of_platform_depopulate(&test_bus->dev);
@@ -1144,10 +1261,14 @@
 	const char *full_name;
 
 	full_name = kasprintf(GFP_KERNEL, "%pOF", np);
+	if (!full_name)
+		return;
 
 	if (!strcmp(full_name, "/__local_fixups__") ||
-	    !strcmp(full_name, "/__fixups__"))
+	    !strcmp(full_name, "/__fixups__")) {
+		kfree(full_name);
 		return;
+	}
 
 	dup = of_find_node_by_path(full_name);
 	kfree(full_name);
@@ -1571,7 +1692,7 @@
 	}
 
 	/* unittest device must be again in before state */
-	if (of_unittest_device_exists(unittest_nr, PDEV_OVERLAY) != before) {
+	if (of_unittest_device_exists(unittest_nr, ovtype) != before) {
 		unittest(0, "%s with device @\"%s\" %s\n",
 				overlay_name_from_nr(overlay_nr),
 				unittest_path(unittest_nr, ovtype),
@@ -2091,6 +2212,153 @@
 
 #endif
 
+static void __init of_unittest_overlay_gpio(void)
+{
+	int chip_request_count;
+	int probe_pass_count;
+	int ret;
+
+	/*
+	 * tests: apply overlays before registering driver
+	 * Similar to installing a driver as a module, the
+	 * driver is registered after applying the overlays.
+	 *
+	 * - apply overlay_gpio_01
+	 * - apply overlay_gpio_02a
+	 * - apply overlay_gpio_02b
+	 * - register driver
+	 *
+	 * register driver will result in
+	 *   - probe and processing gpio hog for overlay_gpio_01
+	 *   - probe for overlay_gpio_02a
+	 *   - processing gpio for overlay_gpio_02b
+	 */
+
+	probe_pass_count = unittest_gpio_probe_pass_count;
+	chip_request_count = unittest_gpio_chip_request_count;
+
+	/*
+	 * overlay_gpio_01 contains gpio node and child gpio hog node
+	 * overlay_gpio_02a contains gpio node
+	 * overlay_gpio_02b contains child gpio hog node
+	 */
+
+	unittest(overlay_data_apply("overlay_gpio_01", NULL),
+		 "Adding overlay 'overlay_gpio_01' failed\n");
+
+	unittest(overlay_data_apply("overlay_gpio_02a", NULL),
+		 "Adding overlay 'overlay_gpio_02a' failed\n");
+
+	unittest(overlay_data_apply("overlay_gpio_02b", NULL),
+		 "Adding overlay 'overlay_gpio_02b' failed\n");
+
+	/*
+	 * messages are the result of the probes, after the
+	 * driver is registered
+	 */
+
+	EXPECT_BEGIN(KERN_INFO,
+		     "gpio-<<int>> (line-B-input): hogged as input\n");
+
+	EXPECT_BEGIN(KERN_INFO,
+		     "gpio-<<int>> (line-A-input): hogged as input\n");
+
+	ret = platform_driver_register(&unittest_gpio_driver);
+	if (unittest(ret == 0, "could not register unittest gpio driver\n"))
+		return;
+
+	EXPECT_END(KERN_INFO,
+		   "gpio-<<int>> (line-A-input): hogged as input\n");
+	EXPECT_END(KERN_INFO,
+		   "gpio-<<int>> (line-B-input): hogged as input\n");
+
+	unittest(probe_pass_count + 2 == unittest_gpio_probe_pass_count,
+		 "unittest_gpio_probe() failed or not called\n");
+
+	unittest(chip_request_count + 2 == unittest_gpio_chip_request_count,
+		 "unittest_gpio_chip_request() called %d times (expected 1 time)\n",
+		 unittest_gpio_chip_request_count - chip_request_count);
+
+	/*
+	 * tests: apply overlays after registering driver
+	 *
+	 * Similar to a driver built-in to the kernel, the
+	 * driver is registered before applying the overlays.
+	 *
+	 * overlay_gpio_03 contains gpio node and child gpio hog node
+	 *
+	 * - apply overlay_gpio_03
+	 *
+	 * apply overlay will result in
+	 *   - probe and processing gpio hog.
+	 */
+
+	probe_pass_count = unittest_gpio_probe_pass_count;
+	chip_request_count = unittest_gpio_chip_request_count;
+
+	EXPECT_BEGIN(KERN_INFO,
+		     "gpio-<<int>> (line-D-input): hogged as input\n");
+
+	/* overlay_gpio_03 contains gpio node and child gpio hog node */
+
+	unittest(overlay_data_apply("overlay_gpio_03", NULL),
+		 "Adding overlay 'overlay_gpio_03' failed\n");
+
+	EXPECT_END(KERN_INFO,
+		   "gpio-<<int>> (line-D-input): hogged as input\n");
+
+	unittest(probe_pass_count + 1 == unittest_gpio_probe_pass_count,
+		 "unittest_gpio_probe() failed or not called\n");
+
+	unittest(chip_request_count + 1 == unittest_gpio_chip_request_count,
+		 "unittest_gpio_chip_request() called %d times (expected 1 time)\n",
+		 unittest_gpio_chip_request_count - chip_request_count);
+
+	/*
+	 * overlay_gpio_04a contains gpio node
+	 *
+	 * - apply overlay_gpio_04a
+	 *
+	 * apply the overlay will result in
+	 *   - probe for overlay_gpio_04a
+	 */
+
+	probe_pass_count = unittest_gpio_probe_pass_count;
+	chip_request_count = unittest_gpio_chip_request_count;
+
+	/* overlay_gpio_04a contains gpio node */
+
+	unittest(overlay_data_apply("overlay_gpio_04a", NULL),
+		 "Adding overlay 'overlay_gpio_04a' failed\n");
+
+	unittest(probe_pass_count + 1 == unittest_gpio_probe_pass_count,
+		 "unittest_gpio_probe() failed or not called\n");
+
+	/*
+	 * overlay_gpio_04b contains child gpio hog node
+	 *
+	 * - apply overlay_gpio_04b
+	 *
+	 * apply the overlay will result in
+	 *   - processing gpio for overlay_gpio_04b
+	 */
+
+	EXPECT_BEGIN(KERN_INFO,
+		     "gpio-<<int>> (line-C-input): hogged as input\n");
+
+	/* overlay_gpio_04b contains child gpio hog node */
+
+	unittest(overlay_data_apply("overlay_gpio_04b", NULL),
+		 "Adding overlay 'overlay_gpio_04b' failed\n");
+
+	EXPECT_END(KERN_INFO,
+		   "gpio-<<int>> (line-C-input): hogged as input\n");
+
+	unittest(chip_request_count + 1 == unittest_gpio_chip_request_count,
+		 "unittest_gpio_chip_request() called %d times (expected 1 time)\n",
+		 unittest_gpio_chip_request_count - chip_request_count);
+}
+
 static void __init of_unittest_overlay(void)
 {
 	struct device_node *bus_np = NULL;
@@ -2150,6 +2418,8 @@
 	of_unittest_overlay_i2c_cleanup();
 #endif
 
+	of_unittest_overlay_gpio();
+
 	of_unittest_destroy_tracked_overlays();
 
 out:
@@ -2203,6 +2473,12 @@
 OVERLAY_INFO_EXTERN(overlay_12);
 OVERLAY_INFO_EXTERN(overlay_13);
 OVERLAY_INFO_EXTERN(overlay_15);
+OVERLAY_INFO_EXTERN(overlay_gpio_01);
+OVERLAY_INFO_EXTERN(overlay_gpio_02a);
+OVERLAY_INFO_EXTERN(overlay_gpio_02b);
+OVERLAY_INFO_EXTERN(overlay_gpio_03);
+OVERLAY_INFO_EXTERN(overlay_gpio_04a);
+OVERLAY_INFO_EXTERN(overlay_gpio_04b);
 OVERLAY_INFO_EXTERN(overlay_bad_add_dup_node);
 OVERLAY_INFO_EXTERN(overlay_bad_add_dup_prop);
 OVERLAY_INFO_EXTERN(overlay_bad_phandle);
@@ -2227,6 +2503,12 @@
 	OVERLAY_INFO(overlay_12, 0),
 	OVERLAY_INFO(overlay_13, 0),
 	OVERLAY_INFO(overlay_15, 0),
+	OVERLAY_INFO(overlay_gpio_01, 0),
+	OVERLAY_INFO(overlay_gpio_02a, 0),
+	OVERLAY_INFO(overlay_gpio_02b, 0),
+	OVERLAY_INFO(overlay_gpio_03, 0),
+	OVERLAY_INFO(overlay_gpio_04a, 0),
+	OVERLAY_INFO(overlay_gpio_04b, 0),
 	OVERLAY_INFO(overlay_bad_add_dup_node, -EINVAL),
 	OVERLAY_INFO(overlay_bad_add_dup_prop, -EINVAL),
 	OVERLAY_INFO(overlay_bad_phandle, -EINVAL),
@@ -2472,8 +2754,11 @@
 				goto err_unlock;
 			}
 			if (__of_add_property(of_symbols, new_prop)) {
+				kfree(new_prop->name);
+				kfree(new_prop->value);
+				kfree(new_prop);
 				/* "name" auto-generated by unflatten */
-				if (!strcmp(new_prop->name, "name"))
+				if (!strcmp(prop->name, "name"))
 					continue;
 				unittest(0, "duplicate property '%s' in overlay_base node __symbols__",
 					 prop->name);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/opp/core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/opp/core.c
@@ -843,10 +843,12 @@
 
 	/* Return early if nothing to do */
 	if (old_freq == freq) {
-		dev_dbg(dev, "%s: old/new frequencies (%lu Hz) are same, nothing to do\n",
-			__func__, freq);
-		ret = 0;
-		goto put_opp_table;
+		if (!opp_table->required_opp_tables && !opp_table->regulators) {
+			dev_dbg(dev, "%s: old/new frequencies (%lu Hz) are same, nothing to do\n",
+				__func__, freq);
+			ret = 0;
+			goto put_opp_table;
+		}
 	}
 
 	temp_freq = old_freq;
@@ -988,7 +990,6 @@
 	BLOCKING_INIT_NOTIFIER_HEAD(&opp_table->head);
 	INIT_LIST_HEAD(&opp_table->opp_list);
 	kref_init(&opp_table->kref);
-	kref_init(&opp_table->list_kref);
 
 	/* Secure the device table modification */
 	list_add(&opp_table->node, &opp_tables);
@@ -1045,6 +1046,10 @@
 	struct opp_table *opp_table = container_of(kref, struct opp_table, kref);
 	struct opp_device *opp_dev, *temp;
 
+	/* Drop the lock as soon as we can */
+	list_del(&opp_table->node);
+	mutex_unlock(&opp_table_lock);
+
 	_of_clear_opp_table(opp_table);
 
 	/* Release clk */
@@ -1066,37 +1071,7 @@
 
 	mutex_destroy(&opp_table->genpd_virt_dev_lock);
 	mutex_destroy(&opp_table->lock);
-	list_del(&opp_table->node);
 	kfree(opp_table);
-
-	mutex_unlock(&opp_table_lock);
-}
-
-void _opp_remove_all_static(struct opp_table *opp_table)
-{
-	struct dev_pm_opp *opp, *tmp;
-
-	list_for_each_entry_safe(opp, tmp, &opp_table->opp_list, node) {
-		if (!opp->dynamic)
-			dev_pm_opp_put(opp);
-	}
-
-	opp_table->parsed_static_opps = false;
-}
-
-static void _opp_table_list_kref_release(struct kref *kref)
-{
-	struct opp_table *opp_table = container_of(kref, struct opp_table,
-						   list_kref);
-
-	_opp_remove_all_static(opp_table);
-	mutex_unlock(&opp_table_lock);
-}
-
-void _put_opp_list_kref(struct opp_table *opp_table)
-{
-	kref_put_mutex(&opp_table->list_kref, _opp_table_list_kref_release,
-		       &opp_table_lock);
 }
 
 void dev_pm_opp_put_opp_table(struct opp_table *opp_table)
@@ -1202,6 +1177,24 @@
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_remove);
 
+void _opp_remove_all_static(struct opp_table *opp_table)
+{
+	struct dev_pm_opp *opp, *tmp;
+
+	mutex_lock(&opp_table->lock);
+
+	if (!opp_table->parsed_static_opps || --opp_table->parsed_static_opps)
+		goto unlock;
+
+	list_for_each_entry_safe(opp, tmp, &opp_table->opp_list, node) {
+		if (!opp->dynamic)
+			dev_pm_opp_put_unlocked(opp);
+	}
+
+unlock:
+	mutex_unlock(&opp_table->lock);
+}
+
 /**
  * dev_pm_opp_remove_all_dynamic() - Remove all dynamically created OPPs
  * @dev:	device for which we do this operation
@@ -1804,6 +1797,9 @@
 {
 	int index;
 
+	if (!opp_table->genpd_virt_devs)
+		return;
+
 	for (index = 0; index < opp_table->required_opp_count; index++) {
 		if (!opp_table->genpd_virt_devs[index])
 			continue;
@@ -1850,6 +1846,9 @@
 	if (!opp_table)
 		return ERR_PTR(-ENOMEM);
 
+	if (opp_table->genpd_virt_devs)
+		return opp_table;
+
 	/*
 	 * If the genpd's OPP table isn't already initialized, parsing of the
 	 * required-opps fail for dev. We should retry this after genpd's OPP
@@ -1882,8 +1881,8 @@
 		}
 
 		virt_dev = dev_pm_domain_attach_by_name(dev, *name);
-		if (IS_ERR(virt_dev)) {
-			ret = PTR_ERR(virt_dev);
+		if (IS_ERR_OR_NULL(virt_dev)) {
+			ret = virt_dev ? PTR_ERR(virt_dev) : -ENODEV;
 			dev_err(dev, "Couldn't attach to pm_domain: %d\n", ret);
 			goto err;
 		}
@@ -2207,7 +2206,7 @@
 		return;
 	}
 
-	_put_opp_list_kref(opp_table);
+	_opp_remove_all_static(opp_table);
 
 	/* Drop reference taken by _find_opp_table() */
 	dev_pm_opp_put_opp_table(opp_table);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/opp/debugfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/opp/debugfs.c
@@ -162,7 +162,7 @@
 
 	dentry = debugfs_rename(rootdir, opp_dev->dentry, rootdir,
 				opp_table->dentry_name);
-	if (!dentry) {
+	if (IS_ERR(dentry)) {
 		dev_err(dev, "%s: Failed to rename link from: %s to %s\n",
 			__func__, dev_name(opp_dev->dev), dev_name(dev));
 		return;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/opp/of.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/opp/of.c
@@ -95,15 +95,7 @@
 static struct device_node *of_parse_required_opp(struct device_node *np,
 						 int index)
 {
-	struct device_node *required_np;
-
-	required_np = of_parse_phandle(np, "required-opps", index);
-	if (unlikely(!required_np)) {
-		pr_err("%s: Unable to parse required-opps: %pOF, index: %d\n",
-		       __func__, np, index);
-	}
-
-	return required_np;
+	return of_parse_phandle(np, "required-opps", index);
 }
 
 /* The caller must call dev_pm_opp_put_opp_table() after the table is used */
@@ -647,7 +639,7 @@
 free_opp:
 	_opp_free(new_opp);
 
-	return ERR_PTR(ret);
+	return ret ? ERR_PTR(ret) : NULL;
 }
 
 /* Initializes OPP tables based on new bindings */
@@ -658,17 +650,15 @@
 	struct dev_pm_opp *opp;
 
 	/* OPP table is already initialized for the device */
+	mutex_lock(&opp_table->lock);
 	if (opp_table->parsed_static_opps) {
-		kref_get(&opp_table->list_kref);
+		opp_table->parsed_static_opps++;
+		mutex_unlock(&opp_table->lock);
 		return 0;
 	}
 
-	/*
-	 * Re-initialize list_kref every time we add static OPPs to the OPP
-	 * table as the reference count may be 0 after the last tie static OPPs
-	 * were removed.
-	 */
-	kref_init(&opp_table->list_kref);
+	opp_table->parsed_static_opps = 1;
+	mutex_unlock(&opp_table->lock);
 
 	/* We have opp-table node now, iterate over it and add OPPs */
 	for_each_available_child_of_node(opp_table->np, np) {
@@ -678,15 +668,18 @@
 			dev_err(dev, "%s: Failed to add OPP, %d\n", __func__,
 				ret);
 			of_node_put(np);
-			return ret;
+			goto remove_static_opp;
 		} else if (opp) {
 			count++;
 		}
 	}
 
-	/* There should be one of more OPP defined */
-	if (WARN_ON(!count))
-		return -ENOENT;
+	/* There should be one or more OPPs defined */
+	if (!count) {
+		dev_err(dev, "%s: no supported OPPs", __func__);
+		ret = -ENOENT;
+		goto remove_static_opp;
+	}
 
 	list_for_each_entry(opp, &opp_table->opp_list, node)
 		pstate_count += !!opp->pstate;
@@ -695,15 +688,19 @@
 	if (pstate_count && pstate_count != count) {
 		dev_err(dev, "Not all nodes have performance state set (%d: %d)\n",
 			count, pstate_count);
-		return -ENOENT;
+		ret = -ENOENT;
+		goto remove_static_opp;
 	}
 
 	if (pstate_count)
 		opp_table->genpd_performance_state = true;
 
-	opp_table->parsed_static_opps = true;
-
 	return 0;
+
+remove_static_opp:
+	_opp_remove_all_static(opp_table);
+
+	return ret;
 }
 
 /* Initializes OPP tables based on old-deprecated bindings */
@@ -729,6 +726,10 @@
 		return -EINVAL;
 	}
 
+	mutex_lock(&opp_table->lock);
+	opp_table->parsed_static_opps = 1;
+	mutex_unlock(&opp_table->lock);
+
 	val = prop->value;
 	while (nr) {
 		unsigned long freq = be32_to_cpup(val++) * 1000;
@@ -738,6 +739,7 @@
 		if (ret) {
 			dev_err(dev, "%s: Failed to add OPP %ld (%d)\n",
 				__func__, freq, ret);
+			_opp_remove_all_static(opp_table);
 			return ret;
 		}
 		nr -= 2;
@@ -986,7 +988,7 @@
 
 	required_np = of_parse_required_opp(np, index);
 	if (!required_np)
-		return -EINVAL;
+		return -ENODEV;
 
 	opp_table = _find_table_of_opp_np(required_np);
 	if (IS_ERR(opp_table)) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/opp/opp.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/opp/opp.h
@@ -127,11 +127,10 @@
  * @dev_list:	list of devices that share these OPPs
  * @opp_list:	table of opps
  * @kref:	for reference count of the table.
- * @list_kref:	for reference count of the OPP list.
  * @lock:	mutex protecting the opp_list and dev_list.
  * @np:		struct device_node pointer for opp's DT node.
  * @clock_latency_ns_max: Max clock latency in nanoseconds.
- * @parsed_static_opps: True if OPPs are initialized from DT.
+ * @parsed_static_opps: Count of devices for which OPPs are initialized from DT.
  * @shared_opp: OPP is shared between multiple devices.
  * @suspend_opp: Pointer to OPP to be used during device suspend.
  * @genpd_virt_dev_lock: Mutex protecting the genpd virtual device pointers.
@@ -167,7 +166,6 @@
 	struct list_head dev_list;
 	struct list_head opp_list;
 	struct kref kref;
-	struct kref list_kref;
 	struct mutex lock;
 
 	struct device_node *np;
@@ -176,7 +174,7 @@
 	/* For backward compatibility with v1 bindings */
 	unsigned int voltage_tolerance_v1;
 
-	bool parsed_static_opps;
+	unsigned int parsed_static_opps;
 	enum opp_table_access shared_opp;
 	struct dev_pm_opp *suspend_opp;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/parisc/ccio-dma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/parisc/ccio-dma.c
@@ -1003,7 +1003,7 @@
 	ioc->usg_calls++;
 #endif
 
-	while(sg_dma_len(sglist) && nents--) {
+	while (nents && sg_dma_len(sglist)) {
 
 #ifdef CCIO_COLLECT_STATS
 		ioc->usg_pages += sg_dma_len(sglist) >> PAGE_SHIFT;
@@ -1011,6 +1011,7 @@
 		ccio_unmap_page(dev, sg_dma_address(sglist),
 				  sg_dma_len(sglist), direction, 0);
 		++sglist;
+		nents--;
 	}
 
 	DBG_RUN_SG("%s() DONE (nents %d)\n", __func__, nents);
@@ -1377,15 +1378,17 @@
 	}
 }
 
-static void __init ccio_init_resources(struct ioc *ioc)
+static int __init ccio_init_resources(struct ioc *ioc)
 {
 	struct resource *res = ioc->mmio_region;
 	char *name = kmalloc(14, GFP_KERNEL);
-
+	if (unlikely(!name))
+		return -ENOMEM;
 	snprintf(name, 14, "GSC Bus [%d/]", ioc->hw_path);
 
 	ccio_init_resource(res, name, &ioc->ioc_regs->io_io_low);
 	ccio_init_resource(res + 1, name, &ioc->ioc_regs->io_io_low_hv);
+	return 0;
 }
 
 static int new_ioc_area(struct resource *res, unsigned long size,
@@ -1540,7 +1543,11 @@
 		return -ENOMEM;
 	}
 	ccio_ioc_init(ioc);
-	ccio_init_resources(ioc);
+	if (ccio_init_resources(ioc)) {
+		iounmap(ioc->ioc_regs);
+		kfree(ioc);
+		return -ENOMEM;
+	}
 	hppa_dma_ops = &ccio_ops;
 
 	hba = kzalloc(sizeof(*hba), GFP_KERNEL);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/parisc/dino.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/parisc/dino.c
@@ -142,9 +142,8 @@
 {
 	struct pci_hba_data	hba;	/* 'C' inheritance - must be first */
 	spinlock_t		dinosaur_pen;
-	unsigned long		txn_addr; /* EIR addr to generate interrupt */ 
-	u32			txn_data; /* EIR data assign to each dino */ 
 	u32 			imr;	  /* IRQ's which are enabled */ 
+	struct gsc_irq		gsc_irq;
 	int			global_irq[DINO_LOCAL_IRQS]; /* map IMR bit to global irq */
 #ifdef DINO_DEBUG
 	unsigned int		dino_irr0; /* save most recent IRQ line stat */
@@ -156,15 +155,6 @@
 	return container_of(hba, struct dino_device, hba);
 }
 
-/* Check if PCI device is behind a Card-mode Dino. */
-static int pci_dev_is_behind_card_dino(struct pci_dev *dev)
-{
-	struct dino_device *dino_dev;
-
-	dino_dev = DINO_DEV(parisc_walk_tree(dev->bus->bridge));
-	return is_card_dino(&dino_dev->hba.dev->id);
-}
-
 /*
  * Dino Configuration Space Accessor Functions
  */
@@ -348,14 +338,43 @@
 	if (tmp & DINO_MASK_IRQ(local_irq)) {
 		DBG(KERN_WARNING "%s(): IRQ asserted! (ILR 0x%x)\n",
 				__func__, tmp);
-		gsc_writel(dino_dev->txn_data, dino_dev->txn_addr);
+		gsc_writel(dino_dev->gsc_irq.txn_data, dino_dev->gsc_irq.txn_addr);
 	}
 }
 
+#ifdef CONFIG_SMP
+static int dino_set_affinity_irq(struct irq_data *d, const struct cpumask *dest,
+				bool force)
+{
+	struct dino_device *dino_dev = irq_data_get_irq_chip_data(d);
+	struct cpumask tmask;
+	int cpu_irq;
+	u32 eim;
+
+	if (!cpumask_and(&tmask, dest, cpu_online_mask))
+		return -EINVAL;
+
+	cpu_irq = cpu_check_affinity(d, &tmask);
+	if (cpu_irq < 0)
+		return cpu_irq;
+
+	dino_dev->gsc_irq.txn_addr = txn_affinity_addr(d->irq, cpu_irq);
+	eim = ((u32) dino_dev->gsc_irq.txn_addr) | dino_dev->gsc_irq.txn_data;
+	__raw_writel(eim, dino_dev->hba.base_addr+DINO_IAR0);
+
+	irq_data_update_effective_affinity(d, &tmask);
+
+	return IRQ_SET_MASK_OK;
+}
+#endif
+
 static struct irq_chip dino_interrupt_type = {
 	.name		= "GSC-PCI",
 	.irq_unmask	= dino_unmask_irq,
 	.irq_mask	= dino_mask_irq,
+#ifdef CONFIG_SMP
+	.irq_set_affinity = dino_set_affinity_irq,
+#endif
 };
 
 
@@ -447,6 +466,15 @@
 DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_6832, quirk_cirrus_cardbus );
 
 #ifdef CONFIG_TULIP
+/* Check if PCI device is behind a Card-mode Dino. */
+static int pci_dev_is_behind_card_dino(struct pci_dev *dev)
+{
+	struct dino_device *dino_dev;
+
+	dino_dev = DINO_DEV(parisc_walk_tree(dev->bus->bridge));
+	return is_card_dino(&dino_dev->hba.dev->id);
+}
+
 static void pci_fixup_tulip(struct pci_dev *dev)
 {
 	if (!pci_dev_is_behind_card_dino(dev))
@@ -806,7 +834,6 @@
 {
 	int status;
 	u32 eim;
-	struct gsc_irq gsc_irq;
 	struct resource *res;
 
 	pcibios_register_hba(&dino_dev->hba);
@@ -821,10 +848,8 @@
 	**   still only has 11 IRQ input lines - just map some of them
 	**   to a different processor.
 	*/
-	dev->irq = gsc_alloc_irq(&gsc_irq);
-	dino_dev->txn_addr = gsc_irq.txn_addr;
-	dino_dev->txn_data = gsc_irq.txn_data;
-	eim = ((u32) gsc_irq.txn_addr) | gsc_irq.txn_data;
+	dev->irq = gsc_alloc_irq(&dino_dev->gsc_irq);
+	eim = ((u32) dino_dev->gsc_irq.txn_addr) | dino_dev->gsc_irq.txn_data;
 
 	/* 
 	** Dino needs a PA "IRQ" to get a processor's attention.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/parisc/gsc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/parisc/gsc.c
@@ -135,10 +135,41 @@
 	 */
 }
 
+#ifdef CONFIG_SMP
+static int gsc_set_affinity_irq(struct irq_data *d, const struct cpumask *dest,
+				bool force)
+{
+	struct gsc_asic *gsc_dev = irq_data_get_irq_chip_data(d);
+	struct cpumask tmask;
+	int cpu_irq;
+
+	if (!cpumask_and(&tmask, dest, cpu_online_mask))
+		return -EINVAL;
+
+	cpu_irq = cpu_check_affinity(d, &tmask);
+	if (cpu_irq < 0)
+		return cpu_irq;
+
+	gsc_dev->gsc_irq.txn_addr = txn_affinity_addr(d->irq, cpu_irq);
+	gsc_dev->eim = ((u32) gsc_dev->gsc_irq.txn_addr) | gsc_dev->gsc_irq.txn_data;
+
+	/* switch IRQ's for devices below LASI/WAX to other CPU */
+	gsc_writel(gsc_dev->eim, gsc_dev->hpa + OFFSET_IAR);
+
+	irq_data_update_effective_affinity(d, &tmask);
+
+	return IRQ_SET_MASK_OK;
+}
+#endif
+
+
 static struct irq_chip gsc_asic_interrupt_type = {
 	.name		=	"GSC-ASIC",
 	.irq_unmask	=	gsc_asic_unmask_irq,
 	.irq_mask	=	gsc_asic_mask_irq,
+#ifdef CONFIG_SMP
+	.irq_set_affinity =	gsc_set_affinity_irq,
+#endif
 };
 
 int gsc_assign_irq(struct irq_chip *type, void *data)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/parisc/gsc.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/parisc/gsc.h
@@ -31,6 +31,7 @@
 	int version;
 	int type;
 	int eim;
+	struct gsc_irq gsc_irq;
 	int global_irq[32];
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/parisc/iosapic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/parisc/iosapic.c
@@ -202,9 +202,9 @@
 
 static DEFINE_SPINLOCK(iosapic_lock);
 
-static inline void iosapic_eoi(void __iomem *addr, unsigned int data)
+static inline void iosapic_eoi(__le32 __iomem *addr, __le32 data)
 {
-	__raw_writel(data, addr);
+	__raw_writel((__force u32)data, addr);
 }
 
 /*
@@ -875,6 +875,7 @@
 
 	return vi->txn_irq;
 }
+EXPORT_SYMBOL(iosapic_serial_irq);
 #endif
 
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/parisc/iosapic_private.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/parisc/iosapic_private.h
@@ -118,8 +118,8 @@
 struct vector_info {
 	struct iosapic_info *iosapic;	/* I/O SAPIC this vector is on */
 	struct irt_entry *irte;		/* IRT entry */
-	u32 __iomem *eoi_addr;		/* precalculate EOI reg address */
-	u32	eoi_data;		/* IA64: ?       PA: swapped txn_data */
+	__le32 __iomem *eoi_addr;	/* precalculate EOI reg address */
+	__le32	eoi_data;		/* IA64: ?       PA: swapped txn_data */
 	int	txn_irq;		/* virtual IRQ number for processor */
 	ulong	txn_addr;		/* IA64: id_eid  PA: partial HPA */
 	u32	txn_data;		/* CPU interrupt bit */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/parisc/lasi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/parisc/lasi.c
@@ -163,7 +163,6 @@
 {
 	extern void (*chassis_power_off)(void);
 	struct gsc_asic *lasi;
-	struct gsc_irq gsc_irq;
 	int ret;
 
 	lasi = kzalloc(sizeof(*lasi), GFP_KERNEL);
@@ -185,7 +184,7 @@
 	lasi_init_irq(lasi);
 
 	/* the IRQ lasi should use */
-	dev->irq = gsc_alloc_irq(&gsc_irq);
+	dev->irq = gsc_alloc_irq(&lasi->gsc_irq);
 	if (dev->irq < 0) {
 		printk(KERN_ERR "%s(): cannot get GSC irq\n",
 				__func__);
@@ -193,9 +192,9 @@
 		return -EBUSY;
 	}
 
-	lasi->eim = ((u32) gsc_irq.txn_addr) | gsc_irq.txn_data;
+	lasi->eim = ((u32) lasi->gsc_irq.txn_addr) | lasi->gsc_irq.txn_data;
 
-	ret = request_irq(gsc_irq.irq, gsc_asic_intr, 0, "lasi", lasi);
+	ret = request_irq(lasi->gsc_irq.irq, gsc_asic_intr, 0, "lasi", lasi);
 	if (ret < 0) {
 		kfree(lasi);
 		return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/parisc/led.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/parisc/led.c
@@ -56,8 +56,8 @@
 static int led_type __read_mostly = -1;
 static unsigned char lastleds;	/* LED state from most recent update */
 static unsigned int led_heartbeat __read_mostly = 1;
-static unsigned int led_diskio    __read_mostly = 1;
-static unsigned int led_lanrxtx   __read_mostly = 1;
+static unsigned int led_diskio    __read_mostly;
+static unsigned int led_lanrxtx   __read_mostly;
 static char lcd_text[32]          __read_mostly;
 static char lcd_text_default[32]  __read_mostly;
 static int  lcd_no_led_support    __read_mostly = 0; /* KittyHawk doesn't support LED on its LCD */
@@ -137,6 +137,9 @@
 
 	/* Create the work queue and queue the LED task */
 	led_wq = create_singlethread_workqueue("led_wq");	
+	if (!led_wq)
+		return -ENOMEM;
+
 	queue_delayed_work(led_wq, &led_task, 0);
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/parisc/pdc_stable.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/parisc/pdc_stable.c
@@ -979,8 +979,10 @@
 		entry->kobj.kset = paths_kset;
 		err = kobject_init_and_add(&entry->kobj, &ktype_pdcspath, NULL,
 					   "%s", entry->name);
-		if (err)
+		if (err) {
+			kobject_put(&entry->kobj);
 			return err;
+		}
 
 		/* kobject is now registered */
 		write_lock(&entry->rw_lock);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/parisc/sba_iommu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/parisc/sba_iommu.c
@@ -1047,7 +1047,7 @@
 	spin_unlock_irqrestore(&ioc->res_lock, flags);
 #endif
 
-	while (sg_dma_len(sglist) && nents--) {
+	while (nents && sg_dma_len(sglist)) {
 
 		sba_unmap_page(dev, sg_dma_address(sglist), sg_dma_len(sglist),
 				direction, 0);
@@ -1056,6 +1056,7 @@
 		ioc->usingle_calls--;	/* kluge since call is unmap_sg() */
 #endif
 		++sglist;
+		nents--;
 	}
 
 	DBG_RUN_SG("%s() DONE (nents %d)\n", __func__,  nents);
@@ -1270,7 +1271,7 @@
 	** (one that doesn't overlap memory or LMMIO space) in the
 	** IBASE and IMASK registers.
 	*/
-	ioc->ibase = READ_REG(ioc->ioc_hpa + IOC_IBASE);
+	ioc->ibase = READ_REG(ioc->ioc_hpa + IOC_IBASE) & ~0x1fffffULL;
 	iova_space_size = ~(READ_REG(ioc->ioc_hpa + IOC_IMASK) & 0xFFFFFFFFUL) + 1;
 
 	if ((ioc->ibase < 0xfed00000UL) && ((ioc->ibase + iova_space_size) > 0xfee00000UL)) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/parisc/wax.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/parisc/wax.c
@@ -68,7 +68,6 @@
 {
 	struct gsc_asic *wax;
 	struct parisc_device *parent;
-	struct gsc_irq gsc_irq;
 	int ret;
 
 	wax = kzalloc(sizeof(*wax), GFP_KERNEL);
@@ -85,7 +84,7 @@
 	wax_init_irq(wax);
 
 	/* the IRQ wax should use */
-	dev->irq = gsc_claim_irq(&gsc_irq, WAX_GSC_IRQ);
+	dev->irq = gsc_claim_irq(&wax->gsc_irq, WAX_GSC_IRQ);
 	if (dev->irq < 0) {
 		printk(KERN_ERR "%s(): cannot get GSC irq\n",
 				__func__);
@@ -93,9 +92,9 @@
 		return -EBUSY;
 	}
 
-	wax->eim = ((u32) gsc_irq.txn_addr) | gsc_irq.txn_data;
+	wax->eim = ((u32) wax->gsc_irq.txn_addr) | wax->gsc_irq.txn_data;
 
-	ret = request_irq(gsc_irq.irq, gsc_asic_intr, 0, "wax", wax);
+	ret = request_irq(wax->gsc_irq.irq, gsc_asic_intr, 0, "wax", wax);
 	if (ret < 0) {
 		kfree(wax);
 		return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/parport/daisy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/parport/daisy.c
@@ -109,8 +109,7 @@
 	    ((num_ports = num_mux_ports(port)) == 2 || num_ports == 4)) {
 		/* Leave original as port zero. */
 		port->muxport = 0;
-		printk(KERN_INFO
-			"%s: 1st (default) port of %d-way multiplexor\n",
+		pr_info("%s: 1st (default) port of %d-way multiplexor\n",
 			port->name, num_ports);
 		for (i = 1; i < num_ports; i++) {
 			/* Clone the port. */
@@ -123,8 +122,7 @@
 				continue;
 			}
 
-			printk(KERN_INFO
-				"%s: %d%s port of %d-way multiplexor on %s\n",
+			pr_info("%s: %d%s port of %d-way multiplexor on %s\n",
 				extra->name, i + 1, th[i + 1], num_ports,
 				port->name);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/parport/ieee1284.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/parport/ieee1284.c
@@ -329,7 +329,7 @@
 #ifndef CONFIG_PARPORT_1284
 	if (mode == IEEE1284_MODE_COMPAT)
 		return 0;
-	printk (KERN_ERR "parport: IEEE1284 not supported in this kernel\n");
+	pr_err("parport: IEEE1284 not supported in this kernel\n");
 	return -1;
 #else
 	int m = mode & ~IEEE1284_ADDR;
@@ -694,7 +694,7 @@
 ssize_t parport_read (struct parport *port, void *buffer, size_t len)
 {
 #ifndef CONFIG_PARPORT_1284
-	printk (KERN_ERR "parport: IEEE1284 not supported in this kernel\n");
+	pr_err("parport: IEEE1284 not supported in this kernel\n");
 	return -ENODEV;
 #else
 	int mode = port->physport->ieee1284.mode;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/parport/ieee1284_ops.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/parport/ieee1284_ops.c
@@ -535,7 +535,7 @@
 				goto out;
 
 			/* Yield the port for a while. */
-			if (count && dev->port->irq != PARPORT_IRQ_NONE) {
+			if (dev->port->irq != PARPORT_IRQ_NONE) {
 				parport_release (dev);
 				schedule_timeout_interruptible(msecs_to_jiffies(40));
 				parport_claim_or_block (dev);
@@ -599,8 +599,7 @@
 			DPRINTK (KERN_DEBUG "ECP read timed out at 45\n");
 
 			if (command)
-				printk (KERN_WARNING
-					"%s: command ignored (%02x)\n",
+				pr_warn("%s: command ignored (%02x)\n",
 					port->name, byte);
 
 			break;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/parport/parport_amiga.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/parport/parport_amiga.c
@@ -212,7 +212,7 @@
 	if (err)
 		goto out_irq;
 
-	printk(KERN_INFO "%s: Amiga built-in port using irq\n", p->name);
+	pr_info("%s: Amiga built-in port using irq\n", p->name);
 	/* XXX: set operating mode */
 	parport_announce_port(p);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/parport/parport_atari.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/parport/parport_atari.c
@@ -200,7 +200,7 @@
 		}
 
 		this_port = p;
-		printk(KERN_INFO "%s: Atari built-in port using irq\n", p->name);
+		pr_info("%s: Atari built-in port using irq\n", p->name);
 		parport_announce_port (p);
 
 		return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/parport/parport_cs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/parport/parport_cs.c
@@ -142,10 +142,8 @@
 			      link->irq, PARPORT_DMA_NONE,
 			      &link->dev, IRQF_SHARED);
     if (p == NULL) {
-	printk(KERN_NOTICE "parport_cs: parport_pc_probe_port() at "
-	       "0x%3x, irq %u failed\n",
-	       (unsigned int) link->resource[0]->start,
-	       link->irq);
+	    pr_notice("parport_cs: parport_pc_probe_port() at 0x%3x, irq %u failed\n",
+		      (unsigned int)link->resource[0]->start, link->irq);
 	goto failed;
     }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/parport/parport_gsc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/parport/parport_gsc.c
@@ -282,7 +282,7 @@
 	p->size = (p->modes & PARPORT_MODE_EPP)?8:3;
 	p->private_data = priv;
 
-	printk(KERN_INFO "%s: PC-style at 0x%lx", p->name, p->base);
+	pr_info("%s: PC-style at 0x%lx", p->name, p->base);
 	p->irq = irq;
 	if (p->irq == PARPORT_IRQ_AUTO) {
 		p->irq = PARPORT_IRQ_NONE;
@@ -299,12 +299,16 @@
 		p->dma = PARPORT_DMA_NONE;
 
 	pr_cont(" [");
-#define printmode(x) {if(p->modes&PARPORT_MODE_##x){pr_cont("%s%s",f?",":"",#x);f++;}}
+#define printmode(x)							\
+do {									\
+	if (p->modes & PARPORT_MODE_##x)				\
+		pr_cont("%s%s", f++ ? "," : "", #x);			\
+} while (0)
 	{
 		int f = 0;
 		printmode(PCSPP);
 		printmode(TRISTATE);
-		printmode(COMPAT)
+		printmode(COMPAT);
 		printmode(EPP);
 //		printmode(ECP);
 //		printmode(DMA);
@@ -315,8 +319,7 @@
 	if (p->irq != PARPORT_IRQ_NONE) {
 		if (request_irq (p->irq, parport_irq_handler,
 				 0, p->name, p)) {
-			printk (KERN_WARNING "%s: irq %d in use, "
-				"resorting to polled operation\n",
+			pr_warn("%s: irq %d in use, resorting to polled operation\n",
 				p->name, p->irq);
 			p->irq = PARPORT_IRQ_NONE;
 			p->dma = PARPORT_DMA_NONE;
@@ -347,7 +350,7 @@
 	unsigned long port;
 
 	if (!dev->irq) {
-		printk(KERN_WARNING "IRQ not found for parallel device at 0x%llx\n",
+		pr_warn("IRQ not found for parallel device at 0x%llx\n",
 			(unsigned long long)dev->hpa.start);
 		return -ENODEV;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/parport/parport_ip32.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/parport/parport_ip32.c
@@ -1337,9 +1337,8 @@
 			ecr = parport_ip32_read_econtrol(p);
 			if ((ecr & ECR_F_EMPTY) && !(ecr & ECR_SERVINTR)
 			    && !lost_interrupt) {
-				printk(KERN_WARNING PPIP32
-				       "%s: lost interrupt in %s\n",
-				       p->name, __func__);
+				pr_warn(PPIP32 "%s: lost interrupt in %s\n",
+					p->name, __func__);
 				lost_interrupt = 1;
 			}
 		}
@@ -1643,8 +1642,8 @@
 				       DSR_nBUSY | DSR_nFAULT)) {
 		/* Avoid to flood the logs */
 		if (ready_before)
-			printk(KERN_INFO PPIP32 "%s: not ready in %s\n",
-			       p->name, __func__);
+			pr_info(PPIP32 "%s: not ready in %s\n",
+				p->name, __func__);
 		ready_before = 0;
 		goto stop;
 	}
@@ -1724,8 +1723,8 @@
 				       DSR_nBUSY | DSR_nFAULT)) {
 		/* Avoid to flood the logs */
 		if (ready_before)
-			printk(KERN_INFO PPIP32 "%s: not ready in %s\n",
-			       p->name, __func__);
+			pr_info(PPIP32 "%s: not ready in %s\n",
+				p->name, __func__);
 		ready_before = 0;
 		goto stop;
 	}
@@ -2064,8 +2063,7 @@
 	p->modes |= PARPORT_MODE_TRISTATE;
 
 	if (!parport_ip32_fifo_supported(p)) {
-		printk(KERN_WARNING PPIP32
-		       "%s: error: FIFO disabled\n", p->name);
+		pr_warn(PPIP32 "%s: error: FIFO disabled\n", p->name);
 		/* Disable hardware modes depending on a working FIFO. */
 		features &= ~PARPORT_IP32_ENABLE_SPP;
 		features &= ~PARPORT_IP32_ENABLE_ECP;
@@ -2077,8 +2075,7 @@
 	if (features & PARPORT_IP32_ENABLE_IRQ) {
 		int irq = MACEISA_PARALLEL_IRQ;
 		if (request_irq(irq, parport_ip32_interrupt, 0, p->name, p)) {
-			printk(KERN_WARNING PPIP32
-			       "%s: error: IRQ disabled\n", p->name);
+			pr_warn(PPIP32 "%s: error: IRQ disabled\n", p->name);
 			/* DMA cannot work without interrupts. */
 			features &= ~PARPORT_IP32_ENABLE_DMA;
 		} else {
@@ -2091,8 +2088,7 @@
 	/* Allocate DMA resources */
 	if (features & PARPORT_IP32_ENABLE_DMA) {
 		if (parport_ip32_dma_register())
-			printk(KERN_WARNING PPIP32
-			       "%s: error: DMA disabled\n", p->name);
+			pr_warn(PPIP32 "%s: error: DMA disabled\n", p->name);
 		else {
 			pr_probe(p, "DMA support enabled\n");
 			p->dma = 0; /* arbitrary value != PARPORT_DMA_NONE */
@@ -2134,8 +2130,7 @@
 	parport_ip32_dump_state(p, "end init", 0);
 
 	/* Print out what we found */
-	printk(KERN_INFO "%s: SGI IP32 at 0x%lx (0x%lx)",
-	       p->name, p->base, p->base_hi);
+	pr_info("%s: SGI IP32 at 0x%lx (0x%lx)", p->name, p->base, p->base_hi);
 	if (p->irq != PARPORT_IRQ_NONE)
 		printk(", irq %d", p->irq);
 	printk(" [");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/parport/parport_mfc3.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/parport/parport_mfc3.c
@@ -325,7 +325,7 @@
 		p->dev = &z->dev;
 
 		this_port[pias++] = p;
-		printk(KERN_INFO "%s: Multiface III port using irq\n", p->name);
+		pr_info("%s: Multiface III port using irq\n", p->name);
 		/* XXX: set operating mode */
 
 		p->private_data = (void *)piabase;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/parport/parport_pc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/parport/parport_pc.c
@@ -475,7 +475,7 @@
 	const unsigned char *bufp = buf;
 	size_t left = length;
 	unsigned long expire = jiffies + port->physport->cad->timeout;
-	const int fifo = FIFO(port);
+	const unsigned long fifo = FIFO(port);
 	int poll_for = 8; /* 80 usecs */
 	const struct parport_pc_private *priv = port->physport->private_data;
 	const int fifo_depth = priv->fifo_depth;
@@ -982,28 +982,24 @@
 	outb(0xaa, io);
 
 	if (verbose_probing) {
-		printk(KERN_INFO
-			"SMSC 37c669 LPT Config: cr_1=0x%02x, 4=0x%02x, "
-			"A=0x%2x, 23=0x%02x, 26=0x%02x, 27=0x%02x\n",
+		pr_info("SMSC 37c669 LPT Config: cr_1=0x%02x, 4=0x%02x, A=0x%2x, 23=0x%02x, 26=0x%02x, 27=0x%02x\n",
 			cr1, cr4, cra, cr23, cr26, cr27);
 
 		/* The documentation calls DMA and IRQ-Lines by letters, so
 		   the board maker can/will wire them
 		   appropriately/randomly...  G=reserved H=IDE-irq, */
-		printk(KERN_INFO
-	"SMSC LPT Config: io=0x%04x, irq=%c, dma=%c, fifo threshold=%d\n",
-				cr23 * 4,
-				(cr27 & 0x0f) ? 'A' - 1 + (cr27 & 0x0f) : '-',
-				(cr26 & 0x0f) ? 'A' - 1 + (cr26 & 0x0f) : '-',
-				cra & 0x0f);
-		printk(KERN_INFO "SMSC LPT Config: enabled=%s power=%s\n",
-		       (cr23 * 4 >= 0x100) ? "yes" : "no",
-		       (cr1 & 4) ? "yes" : "no");
-		printk(KERN_INFO
-			"SMSC LPT Config: Port mode=%s, EPP version =%s\n",
-				(cr1 & 0x08) ? "Standard mode only (SPP)"
-					      : modes[cr4 & 0x03],
-				(cr4 & 0x40) ? "1.7" : "1.9");
+		pr_info("SMSC LPT Config: io=0x%04x, irq=%c, dma=%c, fifo threshold=%d\n",
+			cr23 * 4,
+			(cr27 & 0x0f) ? 'A' - 1 + (cr27 & 0x0f) : '-',
+			(cr26 & 0x0f) ? 'A' - 1 + (cr26 & 0x0f) : '-',
+			cra & 0x0f);
+		pr_info("SMSC LPT Config: enabled=%s power=%s\n",
+			(cr23 * 4 >= 0x100) ? "yes" : "no",
+			(cr1 & 4) ? "yes" : "no");
+		pr_info("SMSC LPT Config: Port mode=%s, EPP version =%s\n",
+			(cr1 & 0x08) ? "Standard mode only (SPP)"
+			: modes[cr4 & 0x03],
+			(cr4 & 0x40) ? "1.7" : "1.9");
 	}
 
 	/* Heuristics !  BIOS setup for this mainboard device limits
@@ -1013,7 +1009,7 @@
 	if (cr23 * 4 >= 0x100) { /* if active */
 		s = find_free_superio();
 		if (s == NULL)
-			printk(KERN_INFO "Super-IO: too many chips!\n");
+			pr_info("Super-IO: too many chips!\n");
 		else {
 			int d;
 			switch (cr23 * 4) {
@@ -1078,26 +1074,24 @@
 	outb(0xaa, io);
 
 	if (verbose_probing) {
-		printk(KERN_INFO
-    "Winbond LPT Config: cr_30=%02x 60,61=%02x%02x 70=%02x 74=%02x, f0=%02x\n",
-					cr30, cr60, cr61, cr70, cr74, crf0);
-		printk(KERN_INFO "Winbond LPT Config: active=%s, io=0x%02x%02x irq=%d, ",
-		       (cr30 & 0x01) ? "yes" : "no", cr60, cr61, cr70 & 0x0f);
+		pr_info("Winbond LPT Config: cr_30=%02x 60,61=%02x%02x 70=%02x 74=%02x, f0=%02x\n",
+			cr30, cr60, cr61, cr70, cr74, crf0);
+		pr_info("Winbond LPT Config: active=%s, io=0x%02x%02x irq=%d, ",
+			(cr30 & 0x01) ? "yes" : "no", cr60, cr61, cr70 & 0x0f);
 		if ((cr74 & 0x07) > 3)
 			pr_cont("dma=none\n");
 		else
 			pr_cont("dma=%d\n", cr74 & 0x07);
-		printk(KERN_INFO
-		    "Winbond LPT Config: irqtype=%s, ECP fifo threshold=%d\n",
-					irqtypes[crf0>>7], (crf0>>3)&0x0f);
-		printk(KERN_INFO "Winbond LPT Config: Port mode=%s\n",
-					modes[crf0 & 0x07]);
+		pr_info("Winbond LPT Config: irqtype=%s, ECP fifo threshold=%d\n",
+			irqtypes[crf0 >> 7], (crf0 >> 3) & 0x0f);
+		pr_info("Winbond LPT Config: Port mode=%s\n",
+			modes[crf0 & 0x07]);
 	}
 
 	if (cr30 & 0x01) { /* the settings can be interrogated later ... */
 		s = find_free_superio();
 		if (s == NULL)
-			printk(KERN_INFO "Super-IO: too many chips!\n");
+			pr_info("Super-IO: too many chips!\n");
 		else {
 			s->io = (cr60 << 8) | cr61;
 			s->irq = cr70 & 0x0f;
@@ -1151,9 +1145,8 @@
 		progif = 0;
 
 	if (verbose_probing)
-		printk(KERN_INFO "Winbond chip at EFER=0x%x key=0x%02x "
-		       "devid=%02x devrev=%02x oldid=%02x type=%s\n",
-		       efer, key, devid, devrev, oldid, type);
+		pr_info("Winbond chip at EFER=0x%x key=0x%02x devid=%02x devrev=%02x oldid=%02x type=%s\n",
+			efer, key, devid, devrev, oldid, type);
 
 	if (progif == 2)
 		show_parconfig_winbond(efer, key);
@@ -1184,9 +1177,8 @@
 		type = "37c666GT";
 
 	if (verbose_probing)
-		printk(KERN_INFO "SMSC chip at EFER=0x%x "
-		       "key=0x%02x devid=%02x devrev=%02x type=%s\n",
-		       efer, key, devid, devrev, type);
+		pr_info("SMSC chip at EFER=0x%x key=0x%02x devid=%02x devrev=%02x type=%s\n",
+			efer, key, devid, devrev, type);
 
 	if (func)
 		func(efer, key);
@@ -1358,7 +1350,7 @@
 	dev |= inb(0x2f);
 	if (dev == 0x8712 || dev == 0x8705 || dev == 0x8715 ||
 	    dev == 0x8716 || dev == 0x8718 || dev == 0x8726) {
-		printk(KERN_INFO "IT%04X SuperIO detected.\n", dev);
+		pr_info("IT%04X SuperIO detected\n", dev);
 		outb(0x07, 0x2E);	/* Parallel Port */
 		outb(0x03, 0x2F);
 		outb(0xF0, 0x2E);	/* BOOT 0x80 off */
@@ -1445,8 +1437,8 @@
 	if (user_specified)
 		/* That didn't work, but the user thinks there's a
 		 * port here. */
-		printk(KERN_INFO "parport 0x%lx (WARNING): CTR: "
-			"wrote 0x%02x, read 0x%02x\n", pb->base, w, r);
+		pr_info("parport 0x%lx (WARNING): CTR: wrote 0x%02x, read 0x%02x\n",
+			pb->base, w, r);
 
 	/* Try the data register.  The data lines aren't tri-stated at
 	 * this stage, so we expect back what we wrote. */
@@ -1464,10 +1456,9 @@
 	if (user_specified) {
 		/* Didn't work, but the user is convinced this is the
 		 * place. */
-		printk(KERN_INFO "parport 0x%lx (WARNING): DATA: "
-			"wrote 0x%02x, read 0x%02x\n", pb->base, w, r);
-		printk(KERN_INFO "parport 0x%lx: You gave this address, "
-			"but there is probably no parallel port there!\n",
+		pr_info("parport 0x%lx (WARNING): DATA: wrote 0x%02x, read 0x%02x\n",
+			pb->base, w, r);
+		pr_info("parport 0x%lx: You gave this address, but there is probably no parallel port there!\n",
 			pb->base);
 	}
 
@@ -1642,7 +1633,7 @@
 
 	if (i <= priv->fifo_depth) {
 		if (verbose_probing)
-			printk(KERN_INFO "0x%lx: readIntrThreshold is %d\n",
+			pr_info("0x%lx: readIntrThreshold is %d\n",
 				pb->base, i);
 	} else
 		/* Number of bytes we can read if we get an interrupt. */
@@ -1657,17 +1648,14 @@
 	switch (pword) {
 	case 0:
 		pword = 2;
-		printk(KERN_WARNING "0x%lx: Unsupported pword size!\n",
-			pb->base);
+		pr_warn("0x%lx: Unsupported pword size!\n", pb->base);
 		break;
 	case 2:
 		pword = 4;
-		printk(KERN_WARNING "0x%lx: Unsupported pword size!\n",
-			pb->base);
+		pr_warn("0x%lx: Unsupported pword size!\n", pb->base);
 		break;
 	default:
-		printk(KERN_WARNING "0x%lx: Unknown implementation ID\n",
-			pb->base);
+		pr_warn("0x%lx: Unknown implementation ID\n", pb->base);
 		/* Fall through - Assume 1 */
 	case 1:
 		pword = 1;
@@ -2107,9 +2095,9 @@
 
 	p->size = (p->modes & PARPORT_MODE_EPP) ? 8 : 3;
 
-	printk(KERN_INFO "%s: PC-style at 0x%lx", p->name, p->base);
+	pr_info("%s: PC-style at 0x%lx", p->name, p->base);
 	if (p->base_hi && priv->ecr)
-		printk(KERN_CONT " (0x%lx)", p->base_hi);
+		pr_cont(" (0x%lx)", p->base_hi);
 	if (p->irq == PARPORT_IRQ_AUTO) {
 		p->irq = PARPORT_IRQ_NONE;
 		parport_irq_probe(p);
@@ -2120,7 +2108,7 @@
 		p->irq = PARPORT_IRQ_NONE;
 	}
 	if (p->irq != PARPORT_IRQ_NONE) {
-		printk(KERN_CONT ", irq %d", p->irq);
+		pr_cont(", irq %d", p->irq);
 		priv->ctr_writable |= 0x10;
 
 		if (p->dma == PARPORT_DMA_AUTO) {
@@ -2144,41 +2132,39 @@
 		/* p->ops->ecp_read_data = parport_pc_ecp_read_block_pio; */
 #endif /* IEEE 1284 support */
 		if (p->dma != PARPORT_DMA_NONE) {
-			printk(KERN_CONT ", dma %d", p->dma);
+			pr_cont(", dma %d", p->dma);
 			p->modes |= PARPORT_MODE_DMA;
 		} else
-			printk(KERN_CONT ", using FIFO");
+			pr_cont(", using FIFO");
 	} else
 		/* We can't use the DMA channel after all. */
 		p->dma = PARPORT_DMA_NONE;
 #endif /* Allowed to use FIFO/DMA */
 
-	printk(KERN_CONT " [");
+	pr_cont(" [");
 
-#define printmode(x) \
-	{\
-		if (p->modes & PARPORT_MODE_##x) {\
-			printk(KERN_CONT "%s%s", f ? "," : "", #x);\
-			f++;\
-		} \
-	}
+#define printmode(x)							\
+do {									\
+	if (p->modes & PARPORT_MODE_##x)				\
+		pr_cont("%s%s", f++ ? "," : "", #x);			\
+} while (0)
 
 	{
 		int f = 0;
 		printmode(PCSPP);
 		printmode(TRISTATE);
-		printmode(COMPAT)
+		printmode(COMPAT);
 		printmode(EPP);
 		printmode(ECP);
 		printmode(DMA);
 	}
 #undef printmode
 #ifndef CONFIG_PARPORT_1284
-	printk(KERN_CONT "(,...)");
+	pr_cont("(,...)");
 #endif /* CONFIG_PARPORT_1284 */
-	printk(KERN_CONT "]\n");
+	pr_cont("]\n");
 	if (probedirq != PARPORT_IRQ_NONE)
-		printk(KERN_INFO "%s: irq %d detected\n", p->name, probedirq);
+		pr_info("%s: irq %d detected\n", p->name, probedirq);
 
 	/* If No ECP release the ports grabbed above. */
 	if (ECR_res && (p->modes & PARPORT_MODE_ECP) == 0) {
@@ -2193,8 +2179,7 @@
 	if (p->irq != PARPORT_IRQ_NONE) {
 		if (request_irq(p->irq, parport_irq_handler,
 				 irqflags, p->name, p)) {
-			printk(KERN_WARNING "%s: irq %d in use, "
-				"resorting to polled operation\n",
+			pr_warn("%s: irq %d in use, resorting to polled operation\n",
 				p->name, p->irq);
 			p->irq = PARPORT_IRQ_NONE;
 			p->dma = PARPORT_DMA_NONE;
@@ -2204,8 +2189,7 @@
 #ifdef HAS_DMA
 		if (p->dma != PARPORT_DMA_NONE) {
 			if (request_dma(p->dma, p->name)) {
-				printk(KERN_WARNING "%s: dma %d in use, "
-					"resorting to PIO operation\n",
+				pr_warn("%s: dma %d in use, resorting to PIO operation\n",
 					p->name, p->dma);
 				p->dma = PARPORT_DMA_NONE;
 			} else {
@@ -2215,9 +2199,7 @@
 						       &priv->dma_handle,
 						       GFP_KERNEL);
 				if (!priv->dma_buf) {
-					printk(KERN_WARNING "%s: "
-						"cannot get buffer for DMA, "
-						"resorting to PIO operation\n",
+					pr_warn("%s: cannot get buffer for DMA, resorting to PIO operation\n",
 						p->name);
 					free_dma(p->dma);
 					p->dma = PARPORT_DMA_NONE;
@@ -2330,7 +2312,7 @@
 		}
 	}
 	if (i >= 5) {
-		printk(KERN_INFO "parport_pc: cannot find ITE8872 INTA\n");
+		pr_info("parport_pc: cannot find ITE8872 INTA\n");
 		return 0;
 	}
 
@@ -2339,29 +2321,28 @@
 
 	switch (type) {
 	case 0x2:
-		printk(KERN_INFO "parport_pc: ITE8871 found (1P)\n");
+		pr_info("parport_pc: ITE8871 found (1P)\n");
 		ite8872set = 0x64200000;
 		break;
 	case 0xa:
-		printk(KERN_INFO "parport_pc: ITE8875 found (1P)\n");
+		pr_info("parport_pc: ITE8875 found (1P)\n");
 		ite8872set = 0x64200000;
 		break;
 	case 0xe:
-		printk(KERN_INFO "parport_pc: ITE8872 found (2S1P)\n");
+		pr_info("parport_pc: ITE8872 found (2S1P)\n");
 		ite8872set = 0x64e00000;
 		break;
 	case 0x6:
-		printk(KERN_INFO "parport_pc: ITE8873 found (1S)\n");
+		pr_info("parport_pc: ITE8873 found (1S)\n");
 		release_region(inta_addr[i], 32);
 		return 0;
 	case 0x8:
-		printk(KERN_INFO "parport_pc: ITE8874 found (2S)\n");
+		pr_info("parport_pc: ITE8874 found (2S)\n");
 		release_region(inta_addr[i], 32);
 		return 0;
 	default:
-		printk(KERN_INFO "parport_pc: unknown ITE887x\n");
-		printk(KERN_INFO "parport_pc: please mail 'lspci -nvv' "
-			"output to Rich.Liu@ite.com.tw\n");
+		pr_info("parport_pc: unknown ITE887x\n");
+		pr_info("parport_pc: please mail 'lspci -nvv' output to Rich.Liu@ite.com.tw\n");
 		release_region(inta_addr[i], 32);
 		return 0;
 	}
@@ -2396,9 +2377,8 @@
 	release_region(inta_addr[i], 32);
 	if (parport_pc_probe_port(ite8872_lpt, ite8872_lpthi,
 				   irq, PARPORT_DMA_NONE, &pdev->dev, 0)) {
-		printk(KERN_INFO
-			"parport_pc: ITE 8872 parallel port: io=0x%X",
-								ite8872_lpt);
+		pr_info("parport_pc: ITE 8872 parallel port: io=0x%X",
+			ite8872_lpt);
 		if (irq != PARPORT_IRQ_NONE)
 			pr_cont(", irq=%d", irq);
 		pr_cont("\n");
@@ -2525,7 +2505,7 @@
 	pci_write_config_byte(pdev, via->via_pci_superio_config_reg, tmp);
 
 	if (siofunc == VIA_FUNCTION_PARPORT_DISABLE) {
-		printk(KERN_INFO "parport_pc: VIA parallel port disabled in BIOS\n");
+		pr_info("parport_pc: VIA parallel port disabled in BIOS\n");
 		return 0;
 	}
 
@@ -2558,9 +2538,8 @@
 	case 0x278:
 		port2 = 0x678; break;
 	default:
-		printk(KERN_INFO
-			"parport_pc: Weird VIA parport base 0x%X, ignoring\n",
-									port1);
+		pr_info("parport_pc: Weird VIA parport base 0x%X, ignoring\n",
+			port1);
 		return 0;
 	}
 
@@ -2579,8 +2558,7 @@
 
 	/* finally, do the probe with values obtained */
 	if (parport_pc_probe_port(port1, port2, irq, dma, &pdev->dev, 0)) {
-		printk(KERN_INFO
-			"parport_pc: VIA parallel port: io=0x%X", port1);
+		pr_info("parport_pc: VIA parallel port: io=0x%X", port1);
 		if (irq != PARPORT_IRQ_NONE)
 			pr_cont(", irq=%d", irq);
 		if (dma != PARPORT_DMA_NONE)
@@ -2589,7 +2567,7 @@
 		return 1;
 	}
 
-	printk(KERN_WARNING "parport_pc: Strange, can't probe VIA parallel port: io=0x%X, irq=%d, dma=%d\n",
+	pr_warn("parport_pc: Strange, can't probe VIA parallel port: io=0x%X, irq=%d, dma=%d\n",
 		port1, irq, dma);
 	return 0;
 }
@@ -2646,8 +2624,11 @@
 	netmos_9815,
 	netmos_9901,
 	netmos_9865,
+	asix_ax99100,
 	quatech_sppxp100,
 	wch_ch382l,
+	brainboxes_uc146,
+	brainboxes_px203,
 };
 
 
@@ -2709,8 +2690,11 @@
 	/* netmos_9815 */		{ 2, { { 0, 1 }, { 2, 3 }, } },
 	/* netmos_9901 */               { 1, { { 0, -1 }, } },
 	/* netmos_9865 */               { 1, { { 0, -1 }, } },
+	/* asix_ax99100 */		{ 1, { { 0, 1 }, } },
 	/* quatech_sppxp100 */		{ 1, { { 0, 1 }, } },
 	/* wch_ch382l */		{ 1, { { 2, -1 }, } },
+	/* brainboxes_uc146 */	{ 1, { { 3, -1 }, } },
+	/* brainboxes_px203 */	{ 1, { { 0, -1 }, } },
 };
 
 static const struct pci_device_id parport_pc_pci_tbl[] = {
@@ -2797,11 +2781,31 @@
 	  0xA000, 0x1000, 0, 0, netmos_9865 },
 	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865,
 	  0xA000, 0x2000, 0, 0, netmos_9865 },
+	/* ASIX AX99100 PCIe to Multi I/O Controller */
+	{ PCI_VENDOR_ID_ASIX, PCI_DEVICE_ID_ASIX_AX99100,
+	  0xA000, 0x2000, 0, 0, asix_ax99100 },
 	/* Quatech SPPXP-100 Parallel port PCI ExpressCard */
 	{ PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_SPPXP_100,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, quatech_sppxp100 },
 	/* WCH CH382L PCI-E single parallel port card */
 	{ 0x1c00, 0x3050, 0x1c00, 0x3050, 0, 0, wch_ch382l },
+	/* Brainboxes IX-500/550 */
+	{ PCI_VENDOR_ID_INTASHIELD, 0x402a,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_pcie_pport },
+	/* Brainboxes UC-146/UC-157 */
+	{ PCI_VENDOR_ID_INTASHIELD, 0x0be1,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, brainboxes_uc146 },
+	{ PCI_VENDOR_ID_INTASHIELD, 0x0be2,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, brainboxes_uc146 },
+	/* Brainboxes PX-146/PX-257 */
+	{ PCI_VENDOR_ID_INTASHIELD, 0x401c,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_pcie_pport },
+	/* Brainboxes PX-203 */
+	{ PCI_VENDOR_ID_INTASHIELD, 0x4007,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, brainboxes_px203 },
+	/* Brainboxes PX-475 */
+	{ PCI_VENDOR_ID_INTASHIELD, 0x401f,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_pcie_pport },
 	{ 0, } /* terminate list */
 };
 MODULE_DEVICE_TABLE(pci, parport_pc_pci_tbl);
@@ -3111,7 +3115,7 @@
 		if (ep != s)
 			*val = r;
 		else {
-			printk(KERN_ERR "parport: bad specifier `%s'\n", s);
+			pr_err("parport: bad specifier `%s'\n", s);
 			return -1;
 		}
 	}
@@ -3201,10 +3205,7 @@
 				irqval[0] = val;
 				break;
 			default:
-				printk(KERN_WARNING
-					"parport_pc: irq specified "
-					"without base address.  Use 'io=' "
-					"to specify one\n");
+				pr_warn("parport_pc: irq specified without base address.  Use 'io=' to specify one\n");
 			}
 
 		if (dma[0] && !parport_parse_dma(dma[0], &val))
@@ -3214,10 +3215,7 @@
 				dmaval[0] = val;
 				break;
 			default:
-				printk(KERN_WARNING
-					"parport_pc: dma specified "
-					"without base address.  Use 'io=' "
-					"to specify one\n");
+				pr_warn("parport_pc: dma specified without base address.  Use 'io=' to specify one\n");
 			}
 	}
 	return 0;
@@ -3256,12 +3254,12 @@
 
 	val = simple_strtoul(str, &endptr, 0);
 	if (endptr == str) {
-		printk(KERN_WARNING "parport=%s not understood\n", str);
+		pr_warn("parport=%s not understood\n", str);
 		return 1;
 	}
 
 	if (parport_setup_ptr == PARPORT_PC_MAX_PORTS) {
-		printk(KERN_ERR "parport=%s ignored, too many ports\n", str);
+		pr_err("parport=%s ignored, too many ports\n", str);
 		return 1;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/parport/parport_serial.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/parport/parport_serial.c
@@ -65,6 +65,10 @@
 	sunix_5069a,
 	sunix_5079a,
 	sunix_5099a,
+	brainboxes_uc257,
+	brainboxes_is300,
+	brainboxes_uc414,
+	brainboxes_px263,
 };
 
 /* each element directly indexed from enum list, above */
@@ -158,6 +162,10 @@
 	/* sunix_5069a */		{ 1, { { 1, 2 }, } },
 	/* sunix_5079a */		{ 1, { { 1, 2 }, } },
 	/* sunix_5099a */		{ 1, { { 1, 2 }, } },
+	/* brainboxes_uc257 */	{ 1, { { 3, -1 }, } },
+	/* brainboxes_is300 */	{ 1, { { 3, -1 }, } },
+	/* brainboxes_uc414 */  { 1, { { 3, -1 }, } },
+	/* brainboxes_px263 */	{ 1, { { 3, -1 }, } },
 };
 
 static struct pci_device_id parport_serial_pci_tbl[] = {
@@ -277,6 +285,38 @@
 	{ PCI_VENDOR_ID_SUNIX, PCI_DEVICE_ID_SUNIX_1999, PCI_VENDOR_ID_SUNIX,
 	  0x0104, 0, 0, sunix_5099a },
 
+	/* Brainboxes UC-203 */
+	{ PCI_VENDOR_ID_INTASHIELD, 0x0bc1,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, brainboxes_uc257 },
+	{ PCI_VENDOR_ID_INTASHIELD, 0x0bc2,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, brainboxes_uc257 },
+
+	/* Brainboxes UC-257 */
+	{ PCI_VENDOR_ID_INTASHIELD, 0x0861,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, brainboxes_uc257 },
+	{ PCI_VENDOR_ID_INTASHIELD, 0x0862,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, brainboxes_uc257 },
+	{ PCI_VENDOR_ID_INTASHIELD, 0x0863,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, brainboxes_uc257 },
+
+	/* Brainboxes UC-414 */
+	{ PCI_VENDOR_ID_INTASHIELD, 0x0e61,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, brainboxes_uc414 },
+
+	/* Brainboxes UC-475 */
+	{ PCI_VENDOR_ID_INTASHIELD, 0x0981,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, brainboxes_uc257 },
+	{ PCI_VENDOR_ID_INTASHIELD, 0x0982,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, brainboxes_uc257 },
+
+	/* Brainboxes IS-300/IS-500 */
+	{ PCI_VENDOR_ID_INTASHIELD, 0x0da0,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, brainboxes_is300 },
+
+	/* Brainboxes PX-263/PX-295 */
+	{ PCI_VENDOR_ID_INTASHIELD, 0x402c,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, brainboxes_px263 },
+
 	{ 0, } /* terminate list */
 };
 MODULE_DEVICE_TABLE(pci,parport_serial_pci_tbl);
@@ -542,6 +582,30 @@
 		.base_baud      = 921600,
 		.uart_offset	= 0x8,
 	},
+	[brainboxes_uc257] = {
+		.flags		= FL_BASE2,
+		.num_ports	= 2,
+		.base_baud	= 115200,
+		.uart_offset	= 8,
+	},
+	[brainboxes_is300] = {
+		.flags		= FL_BASE2,
+		.num_ports	= 1,
+		.base_baud	= 115200,
+		.uart_offset	= 8,
+	},
+	[brainboxes_uc414] = {
+		.flags		= FL_BASE2,
+		.num_ports	= 4,
+		.base_baud	= 115200,
+		.uart_offset	= 8,
+	},
+	[brainboxes_px263] = {
+		.flags		= FL_BASE2,
+		.num_ports	= 4,
+		.base_baud	= 921600,
+		.uart_offset	= 8,
+	},
 };
 
 struct parport_serial_private {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/parport/parport_sunbpp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/parport/parport_sunbpp.c
@@ -314,7 +314,7 @@
 	value_tcr &= ~P_TCR_DIR;
 	sbus_writeb(value_tcr, &regs->p_tcr);
 
-	printk(KERN_INFO "%s: sunbpp at 0x%lx\n", p->name, p->base);
+	pr_info("%s: sunbpp at 0x%lx\n", p->name, p->base);
 
 	dev_set_drvdata(&op->dev, p);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/parport/probe.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/parport/probe.c
@@ -38,7 +38,7 @@
 {
 	struct parport_device_info *info = &port->probe_info[device + 1];
 
-	printk(KERN_INFO "%s", port->name);
+	pr_info("%s", port->name);
 
 	if (device >= 0)
 		printk (" (addr %d)", device);
@@ -58,7 +58,7 @@
 	struct parport_device_info *info = &port->probe_info[device + 1];
 
 	if (!txt) {
-		printk(KERN_WARNING "%s probe: memory squeeze\n", port->name);
+		pr_warn("%s probe: memory squeeze\n", port->name);
 		return;
 	}
 	strcpy(txt, str);
@@ -98,7 +98,8 @@
 						goto rock_on;
 					}
 				}
-				printk(KERN_WARNING "%s probe: warning, class '%s' not understood.\n", port->name, sep);
+				pr_warn("%s probe: warning, class '%s' not understood\n",
+					port->name, sep);
 				info->class = PARPORT_CLASS_OTHER;
 			} else if (!strcmp(p, "CMD") ||
 				   !strcmp(p, "COMMAND SET")) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/parport/procfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/parport/procfs.c
@@ -51,12 +51,12 @@
 	
 	for (dev = port->devices; dev ; dev = dev->next) {
 		if(dev == port->cad) {
-			len += sprintf(buffer, "%s\n", dev->name);
+			len += scnprintf(buffer, sizeof(buffer), "%s\n", dev->name);
 		}
 	}
 
 	if(!len) {
-		len += sprintf(buffer, "%s\n", "none");
+		len += scnprintf(buffer, sizeof(buffer), "%s\n", "none");
 	}
 
 	if (len > *lenp)
@@ -87,19 +87,19 @@
 	}
 	
 	if ((str = info->class_name) != NULL)
-		len += sprintf (buffer + len, "CLASS:%s;\n", str);
+		len += scnprintf (buffer + len, sizeof(buffer) - len, "CLASS:%s;\n", str);
 
 	if ((str = info->model) != NULL)
-		len += sprintf (buffer + len, "MODEL:%s;\n", str);
+		len += scnprintf (buffer + len, sizeof(buffer) - len, "MODEL:%s;\n", str);
 
 	if ((str = info->mfr) != NULL)
-		len += sprintf (buffer + len, "MANUFACTURER:%s;\n", str);
+		len += scnprintf (buffer + len, sizeof(buffer) - len, "MANUFACTURER:%s;\n", str);
 
 	if ((str = info->description) != NULL)
-		len += sprintf (buffer + len, "DESCRIPTION:%s;\n", str);
+		len += scnprintf (buffer + len, sizeof(buffer) - len, "DESCRIPTION:%s;\n", str);
 
 	if ((str = info->cmdset) != NULL)
-		len += sprintf (buffer + len, "COMMAND SET:%s;\n", str);
+		len += scnprintf (buffer + len, sizeof(buffer) - len, "COMMAND SET:%s;\n", str);
 
 	if (len > *lenp)
 		len = *lenp;
@@ -117,7 +117,7 @@
 				 size_t *lenp, loff_t *ppos)
 {
 	struct parport *port = (struct parport *)table->extra1;
-	char buffer[20];
+	char buffer[64];
 	int len = 0;
 
 	if (*ppos) {
@@ -128,7 +128,7 @@
 	if (write) /* permissions prevent this anyway */
 		return -EACCES;
 
-	len += sprintf (buffer, "%lu\t%lu\n", port->base, port->base_hi);
+	len += scnprintf (buffer, sizeof(buffer), "%lu\t%lu\n", port->base, port->base_hi);
 
 	if (len > *lenp)
 		len = *lenp;
@@ -156,7 +156,7 @@
 	if (write) /* permissions prevent this anyway */
 		return -EACCES;
 
-	len += sprintf (buffer, "%d\n", port->irq);
+	len += scnprintf (buffer, sizeof(buffer), "%d\n", port->irq);
 
 	if (len > *lenp)
 		len = *lenp;
@@ -184,7 +184,7 @@
 	if (write) /* permissions prevent this anyway */
 		return -EACCES;
 
-	len += sprintf (buffer, "%d\n", port->dma);
+	len += scnprintf (buffer, sizeof(buffer), "%d\n", port->dma);
 
 	if (len > *lenp)
 		len = *lenp;
@@ -213,7 +213,11 @@
 		return -EACCES;
 
 	{
-#define printmode(x) {if(port->modes&PARPORT_MODE_##x){len+=sprintf(buffer+len,"%s%s",f?",":"",#x);f++;}}
+#define printmode(x)							\
+do {									\
+	if (port->modes & PARPORT_MODE_##x)				\
+		len += scnprintf(buffer + len, sizeof(buffer) - len, "%s%s", f++ ? "," : "", #x); \
+} while (0)
 		int f = 0;
 		printmode(PCSPP);
 		printmode(TRISTATE);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/parport/share.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/parport/share.c
@@ -230,6 +230,18 @@
 	return 0;
 }
 
+/*
+ * Iterates through all the devices connected to the bus and return 1
+ * if the device is a parallel port.
+ */
+
+static int port_detect(struct device *dev, void *dev_drv)
+{
+	if (is_parport(dev))
+		return 1;
+	return 0;
+}
+
 /**
  *	parport_register_driver - register a parallel port device driver
  *	@drv: structure describing the driver
@@ -282,6 +294,15 @@
 		if (ret)
 			return ret;
 
+		/*
+		 * check if bus has any parallel port registered, if
+		 * none is found then load the lowlevel driver.
+		 */
+		ret = bus_for_each_dev(&parport_bus_type, NULL, NULL,
+				       port_detect);
+		if (!ret)
+			get_lowlevel_driver();
+
 		mutex_lock(&registration_lock);
 		if (drv->match_port)
 			bus_for_each_dev(&parport_bus_type, NULL, drv,
@@ -534,8 +555,8 @@
 #endif
 
 	if (!port->dev)
-		printk(KERN_WARNING "%s: fix this legacy no-device port driver!\n",
-		       port->name);
+		pr_warn("%s: fix this legacy no-device port driver!\n",
+			port->name);
 
 	parport_proc_register(port);
 	mutex_lock(&registration_lock);
@@ -707,7 +728,8 @@
 
 	if (flags & PARPORT_DEV_LURK) {
 		if (!pf || !kf) {
-			printk(KERN_INFO "%s: refused to register lurking device (%s) without callbacks\n", port->name, name);
+			pr_info("%s: refused to register lurking device (%s) without callbacks\n",
+				port->name, name);
 			return NULL;
 		}
 	}
@@ -976,7 +998,7 @@
 
 #ifdef PARPORT_PARANOID
 	if (!dev) {
-		printk(KERN_ERR "parport_unregister_device: passed NULL\n");
+		pr_err("%s: passed NULL\n", __func__);
 		return;
 	}
 #endif
@@ -1117,8 +1139,7 @@
 	unsigned long flags;
 
 	if (port->cad == dev) {
-		printk(KERN_INFO "%s: %s already owner\n",
-		       dev->port->name,dev->name);
+		pr_info("%s: %s already owner\n", dev->port->name, dev->name);
 		return 0;
 	}
 
@@ -1138,9 +1159,8 @@
 			 * I think we'll actually deadlock rather than
 			 * get here, but just in case..
 			 */
-			printk(KERN_WARNING
-			       "%s: %s released port when preempted!\n",
-			       port->name, oldcad->name);
+			pr_warn("%s: %s released port when preempted!\n",
+				port->name, oldcad->name);
 			if (port->cad)
 				goto blocked;
 		}
@@ -1300,8 +1320,8 @@
 	write_lock_irqsave(&port->cad_lock, flags);
 	if (port->cad != dev) {
 		write_unlock_irqrestore(&port->cad_lock, flags);
-		printk(KERN_WARNING "%s: %s tried to release parport when not owner\n",
-		       port->name, dev->name);
+		pr_warn("%s: %s tried to release parport when not owner\n",
+			port->name, dev->name);
 		return;
 	}
 
@@ -1341,7 +1361,8 @@
 			if (dev->port->cad) /* racy but no matter */
 				return;
 		} else {
-			printk(KERN_ERR "%s: don't know how to wake %s\n", port->name, pd->name);
+			pr_err("%s: don't know how to wake %s\n",
+			       port->name, pd->name);
 		}
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/Kconfig
@@ -52,7 +52,7 @@
 	   If you don't know what to do here, say Y.
 
 config PCI_MSI_IRQ_DOMAIN
-	def_bool ARC || ARM || ARM64 || X86 || RISCV
+	def_bool y
 	depends on PCI_MSI
 	select GENERIC_MSI_IRQ_DOMAIN
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/access.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/access.c
@@ -160,9 +160,12 @@
 	 * write happen to have any RW1C (write-one-to-clear) bits set, we
 	 * just inadvertently cleared something we shouldn't have.
 	 */
-	dev_warn_ratelimited(&bus->dev, "%d-byte config write to %04x:%02x:%02x.%d offset %#x may corrupt adjacent RW1C bits\n",
-			     size, pci_domain_nr(bus), bus->number,
-			     PCI_SLOT(devfn), PCI_FUNC(devfn), where);
+	if (!bus->unsafe_warn) {
+		dev_warn(&bus->dev, "%d-byte config write to %04x:%02x:%02x.%d offset %#x may corrupt adjacent RW1C bits\n",
+			 size, pci_domain_nr(bus), bus->number,
+			 PCI_SLOT(devfn), PCI_FUNC(devfn), where);
+		bus->unsafe_warn = 1;
+	}
 
 	mask = ~(((1 << (size * 8)) - 1) << ((where & 0x3) * 8));
 	tmp = readl(addr) & mask;
@@ -204,17 +207,13 @@
 static DECLARE_WAIT_QUEUE_HEAD(pci_cfg_wait);
 
 static noinline void pci_wait_cfg(struct pci_dev *dev)
+	__must_hold(&pci_lock)
 {
-	DECLARE_WAITQUEUE(wait, current);
-
-	__add_wait_queue(&pci_cfg_wait, &wait);
 	do {
-		set_current_state(TASK_UNINTERRUPTIBLE);
 		raw_spin_unlock_irq(&pci_lock);
-		schedule();
+		wait_event(pci_cfg_wait, !dev->block_cfg_access);
 		raw_spin_lock_irq(&pci_lock);
 	} while (dev->block_cfg_access);
-	__remove_wait_queue(&pci_cfg_wait, &wait);
 }
 
 /* Returns 0 on success, negative values indicate error. */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/bus.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/bus.c
@@ -322,12 +322,8 @@
 
 	dev->match_driver = true;
 	retval = device_attach(&dev->dev);
-	if (retval < 0 && retval != -EPROBE_DEFER) {
+	if (retval < 0 && retval != -EPROBE_DEFER)
 		pci_warn(dev, "device attach failed (%d)\n", retval);
-		pci_proc_detach_device(dev);
-		pci_remove_sysfs_dev_files(dev);
-		return;
-	}
 
 	pci_dev_assign_added(dev, true);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/controller/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/controller/Kconfig
@@ -109,6 +109,14 @@
 	  Say 'Y' here if you want kernel to support the Xilinx AXI PCIe
 	  Host Bridge driver.
 
+config PCIE_XDMA_PL
+	bool "Xilinx XDMA PL PCIe host bridge support"
+	depends on ARCH_ZYNQMP || MICROBLAZE
+	depends on PCI_MSI_IRQ_DOMAIN
+	help
+	  Say 'Y' here if you want kernel to enable support the
+	  Xilinx XDMA PL PCIe Host Bridge driver.
+
 config PCI_XGENE
 	bool "X-Gene PCIe controller"
 	depends on ARM64 || COMPILE_TEST
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/controller/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/controller/Makefile
@@ -12,6 +12,7 @@
 obj-$(CONFIG_PCIE_RCAR) += pcie-rcar.o
 obj-$(CONFIG_PCI_HOST_COMMON) += pci-host-common.o
 obj-$(CONFIG_PCI_HOST_GENERIC) += pci-host-generic.o
+obj-$(CONFIG_PCIE_XDMA_PL) += pcie-xdma-pl.o
 obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o
 obj-$(CONFIG_PCIE_XILINX_NWL) += pcie-xilinx-nwl.o
 obj-$(CONFIG_PCI_V3_SEMI) += pci-v3-semi.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/controller/dwc/pci-imx6.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/controller/dwc/pci-imx6.c
@@ -413,6 +413,11 @@
 			dev_err(dev, "failed to disable vpcie regulator: %d\n",
 				ret);
 	}
+
+	/* Some boards don't have PCIe reset GPIO. */
+	if (gpio_is_valid(imx6_pcie->reset_gpio))
+		gpio_set_value_cansleep(imx6_pcie->reset_gpio,
+					imx6_pcie->gpio_active_high);
 }
 
 static unsigned int imx6_pcie_grp_offset(const struct imx6_pcie *imx6_pcie)
@@ -535,15 +540,6 @@
 	/* allow the clocks to stabilize */
 	usleep_range(200, 500);
 
-	/* Some boards don't have PCIe reset GPIO. */
-	if (gpio_is_valid(imx6_pcie->reset_gpio)) {
-		gpio_set_value_cansleep(imx6_pcie->reset_gpio,
-					imx6_pcie->gpio_active_high);
-		msleep(100);
-		gpio_set_value_cansleep(imx6_pcie->reset_gpio,
-					!imx6_pcie->gpio_active_high);
-	}
-
 	switch (imx6_pcie->drvdata->variant) {
 	case IMX8MQ:
 		reset_control_deassert(imx6_pcie->pciephy_reset);
@@ -586,6 +582,15 @@
 		break;
 	}
 
+	/* Some boards don't have PCIe reset GPIO. */
+	if (gpio_is_valid(imx6_pcie->reset_gpio)) {
+		msleep(100);
+		gpio_set_value_cansleep(imx6_pcie->reset_gpio,
+					!imx6_pcie->gpio_active_high);
+		/* Wait for 100ms after PERST# deassertion (PCIe r5.0, 6.6.1) */
+		msleep(100);
+	}
+
 	return;
 
 err_ref_clk:
@@ -1290,6 +1295,13 @@
 static int __init imx6_pcie_init(void)
 {
 #ifdef CONFIG_ARM
+	struct device_node *np;
+
+	np = of_find_matching_node(NULL, imx6_pcie_of_match);
+	if (!np)
+		return -ENODEV;
+	of_node_put(np);
+
 	/*
 	 * Since probe() can be deferred we need to make sure that
 	 * hook_fault_code is not called after __init memory is freed
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/controller/dwc/pci-keystone.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/controller/dwc/pci-keystone.c
@@ -35,6 +35,11 @@
 #define PCIE_DEVICEID_SHIFT	16
 
 /* Application registers */
+#define PID				0x000
+#define RTL				GENMASK(15, 11)
+#define RTL_SHIFT			11
+#define AM6_PCI_PG1_RTL_VER		0x15
+
 #define CMD_STATUS			0x004
 #define LTSSM_EN_VAL		        BIT(0)
 #define OB_XLAT_EN_VAL		        BIT(1)
@@ -107,6 +112,8 @@
 
 #define to_keystone_pcie(x)		dev_get_drvdata((x)->dev)
 
+#define PCI_DEVICE_ID_TI_AM654X		0xb00c
+
 struct ks_pcie_of_data {
 	enum dw_pcie_device_mode mode;
 	const struct dw_pcie_host_ops *host_ops;
@@ -422,7 +429,7 @@
 				   lower_32_bits(start) | OB_ENABLEN);
 		ks_pcie_app_writel(ks_pcie, OB_OFFSET_HI(i),
 				   upper_32_bits(start));
-		start += OB_WIN_SIZE;
+		start += OB_WIN_SIZE * SZ_1M;
 	}
 
 	val = ks_pcie_app_readl(ks_pcie, CMD_STATUS);
@@ -510,7 +517,7 @@
 	/* Disable Link training */
 	val = ks_pcie_app_readl(ks_pcie, CMD_STATUS);
 	val &= ~LTSSM_EN_VAL;
-	ks_pcie_app_writel(ks_pcie, CMD_STATUS, LTSSM_EN_VAL | val);
+	ks_pcie_app_writel(ks_pcie, CMD_STATUS, val);
 }
 
 static int ks_pcie_start_link(struct dw_pcie *pci)
@@ -534,7 +541,11 @@
 static void ks_pcie_quirk(struct pci_dev *dev)
 {
 	struct pci_bus *bus = dev->bus;
+	struct keystone_pcie *ks_pcie;
+	struct device *bridge_dev;
 	struct pci_dev *bridge;
+	u32 val;
+
 	static const struct pci_device_id rc_pci_devids[] = {
 		{ PCI_DEVICE(PCI_VENDOR_ID_TI, PCIE_RC_K2HK),
 		 .class = PCI_CLASS_BRIDGE_PCI << 8, .class_mask = ~0, },
@@ -546,6 +557,11 @@
 		 .class = PCI_CLASS_BRIDGE_PCI << 8, .class_mask = ~0, },
 		{ 0, },
 	};
+	static const struct pci_device_id am6_pci_devids[] = {
+		{ PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_AM654X),
+		 .class = PCI_CLASS_BRIDGE_PCI << 8, .class_mask = ~0, },
+		{ 0, },
+	};
 
 	if (pci_is_root_bus(bus))
 		bridge = dev;
@@ -567,10 +583,36 @@
 	 */
 	if (pci_match_id(rc_pci_devids, bridge)) {
 		if (pcie_get_readrq(dev) > 256) {
-			dev_info(&dev->dev, "limiting MRRS to 256\n");
+			dev_info(&dev->dev, "limiting MRRS to 256 bytes\n");
 			pcie_set_readrq(dev, 256);
 		}
 	}
+
+	/*
+	 * Memory transactions fail with PCI controller in AM654 PG1.0
+	 * when MRRS is set to more than 128 bytes. Force the MRRS to
+	 * 128 bytes in all downstream devices.
+	 */
+	if (pci_match_id(am6_pci_devids, bridge)) {
+		bridge_dev = pci_get_host_bridge_device(dev);
+		if (!bridge_dev || !bridge_dev->parent)
+			return;
+
+		ks_pcie = dev_get_drvdata(bridge_dev->parent);
+		if (!ks_pcie)
+			return;
+
+		val = ks_pcie_app_readl(ks_pcie, PID);
+		val &= RTL;
+		val >>= RTL_SHIFT;
+		if (val != AM6_PCI_PG1_RTL_VER)
+			return;
+
+		if (pcie_get_readrq(dev) > 128) {
+			dev_info(&dev->dev, "limiting MRRS to 128 bytes\n");
+			pcie_set_readrq(dev, 128);
+		}
+	}
 }
 DECLARE_PCI_FIXUP_ENABLE(PCI_ANY_ID, PCI_ANY_ID, ks_pcie_quirk);
 
@@ -861,8 +903,8 @@
 	return ks_pcie_handle_error_irq(ks_pcie);
 }
 
-static int __init ks_pcie_add_pcie_port(struct keystone_pcie *ks_pcie,
-					struct platform_device *pdev)
+static int ks_pcie_add_pcie_port(struct keystone_pcie *ks_pcie,
+				 struct platform_device *pdev)
 {
 	struct dw_pcie *pci = ks_pcie->pci;
 	struct pcie_port *pp = &pci->pp;
@@ -992,8 +1034,8 @@
 	.get_features = &ks_pcie_am654_get_features,
 };
 
-static int __init ks_pcie_add_pcie_ep(struct keystone_pcie *ks_pcie,
-				      struct platform_device *pdev)
+static int ks_pcie_add_pcie_ep(struct keystone_pcie *ks_pcie,
+			       struct platform_device *pdev)
 {
 	int ret;
 	struct dw_pcie_ep *ep;
@@ -1181,7 +1223,7 @@
 	{ },
 };
 
-static int __init ks_pcie_probe(struct platform_device *pdev)
+static int ks_pcie_probe(struct platform_device *pdev)
 {
 	const struct dw_pcie_host_ops *host_ops;
 	const struct dw_pcie_ep_ops *ep_ops;
@@ -1305,7 +1347,16 @@
 		goto err_link;
 	}
 
+	/* Obtain references to the PHYs */
+	for (i = 0; i < num_lanes; i++)
+		phy_pm_runtime_get_sync(ks_pcie->phy[i]);
+
 	ret = ks_pcie_enable_phy(ks_pcie);
+
+	/* Release references to the PHYs */
+	for (i = 0; i < num_lanes; i++)
+		phy_pm_runtime_put_sync(ks_pcie->phy[i]);
+
 	if (ret) {
 		dev_err(dev, "failed to enable phy\n");
 		goto err_link;
@@ -1354,7 +1405,7 @@
 		ret = of_property_read_u32(np, "num-viewport", &num_viewport);
 		if (ret < 0) {
 			dev_err(dev, "unable to read *num-viewport* property\n");
-			return ret;
+			goto err_get_sync;
 		}
 
 		/*
@@ -1407,7 +1458,7 @@
 	return ret;
 }
 
-static int __exit ks_pcie_remove(struct platform_device *pdev)
+static int ks_pcie_remove(struct platform_device *pdev)
 {
 	struct keystone_pcie *ks_pcie = platform_get_drvdata(pdev);
 	struct device_link **link = ks_pcie->link;
@@ -1423,9 +1474,9 @@
 	return 0;
 }
 
-static struct platform_driver ks_pcie_driver __refdata = {
+static struct platform_driver ks_pcie_driver = {
 	.probe  = ks_pcie_probe,
-	.remove = __exit_p(ks_pcie_remove),
+	.remove = ks_pcie_remove,
 	.driver = {
 		.name	= "keystone-pcie",
 		.of_match_table = of_match_ptr(ks_pcie_of_match),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/controller/dwc/pci-meson.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/controller/dwc/pci-meson.c
@@ -250,15 +250,15 @@
 	if (IS_ERR(res->port_clk))
 		return PTR_ERR(res->port_clk);
 
-	res->mipi_gate = meson_pcie_probe_clock(dev, "pcie_mipi_en", 0);
+	res->mipi_gate = meson_pcie_probe_clock(dev, "mipi", 0);
 	if (IS_ERR(res->mipi_gate))
 		return PTR_ERR(res->mipi_gate);
 
-	res->general_clk = meson_pcie_probe_clock(dev, "pcie_general", 0);
+	res->general_clk = meson_pcie_probe_clock(dev, "general", 0);
 	if (IS_ERR(res->general_clk))
 		return PTR_ERR(res->general_clk);
 
-	res->clk = meson_pcie_probe_clock(dev, "pcie", 0);
+	res->clk = meson_pcie_probe_clock(dev, "pclk", 0);
 	if (IS_ERR(res->clk))
 		return PTR_ERR(res->clk);
 
@@ -301,11 +301,11 @@
 	meson_cfg_writel(mp, val, PCIE_CFG0);
 
 	val = meson_elb_readl(mp, PCIE_PORT_LINK_CTRL_OFF);
-	val &= ~LINK_CAPABLE_MASK;
+	val &= ~(LINK_CAPABLE_MASK | FAST_LINK_MODE);
 	meson_elb_writel(mp, val, PCIE_PORT_LINK_CTRL_OFF);
 
 	val = meson_elb_readl(mp, PCIE_PORT_LINK_CTRL_OFF);
-	val |= LINK_CAPABLE_X1 | FAST_LINK_MODE;
+	val |= LINK_CAPABLE_X1;
 	meson_elb_writel(mp, val, PCIE_PORT_LINK_CTRL_OFF);
 
 	val = meson_elb_readl(mp, PCIE_GEN2_CTRL_OFF);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/controller/dwc/pcie-designware-host.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -78,7 +78,8 @@
 irqreturn_t dw_handle_msi_irq(struct pcie_port *pp)
 {
 	int i, pos, irq;
-	u32 val, num_ctrls;
+	unsigned long val;
+	u32 status, num_ctrls;
 	irqreturn_t ret = IRQ_NONE;
 
 	num_ctrls = pp->num_vectors / MAX_MSI_IRQS_PER_CTRL;
@@ -86,14 +87,14 @@
 	for (i = 0; i < num_ctrls; i++) {
 		dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_STATUS +
 					(i * MSI_REG_CTRL_BLOCK_SIZE),
-				    4, &val);
-		if (!val)
+				    4, &status);
+		if (!status)
 			continue;
 
 		ret = IRQ_HANDLED;
+		val = status;
 		pos = 0;
-		while ((pos = find_next_bit((unsigned long *) &val,
-					    MAX_MSI_IRQS_PER_CTRL,
+		while ((pos = find_next_bit(&val, MAX_MSI_IRQS_PER_CTRL,
 					    pos)) != MAX_MSI_IRQS_PER_CTRL) {
 			irq = irq_find_mapping(pp->irq_domain,
 					       (i * MAX_MSI_IRQS_PER_CTRL) +
@@ -262,6 +263,8 @@
 		return -ENOMEM;
 	}
 
+	irq_domain_update_bus_token(pp->irq_domain, DOMAIN_BUS_NEXUS);
+
 	pp->msi_domain = pci_msi_create_irq_domain(fwnode,
 						   &dw_pcie_msi_domain_info,
 						   pp->irq_domain);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/controller/dwc/pcie-qcom.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/controller/dwc/pcie-qcom.c
@@ -45,7 +45,13 @@
 #define PCIE_CAP_CPL_TIMEOUT_DISABLE		0x10
 
 #define PCIE20_PARF_PHY_CTRL			0x40
+#define PHY_CTRL_PHY_TX0_TERM_OFFSET_MASK	GENMASK(20, 16)
+#define PHY_CTRL_PHY_TX0_TERM_OFFSET(x)		((x) << 16)
+
 #define PCIE20_PARF_PHY_REFCLK			0x4C
+#define PHY_REFCLK_SSP_EN			BIT(16)
+#define PHY_REFCLK_USE_PAD			BIT(12)
+
 #define PCIE20_PARF_DBI_BASE_ADDR		0x168
 #define PCIE20_PARF_SLV_ADDR_SPACE_SIZE		0x16C
 #define PCIE20_PARF_MHI_CLOCK_RESET_CTRL	0x174
@@ -76,6 +82,18 @@
 #define DBI_RO_WR_EN				1
 
 #define PERST_DELAY_US				1000
+/* PARF registers */
+#define PCIE20_PARF_PCS_DEEMPH			0x34
+#define PCS_DEEMPH_TX_DEEMPH_GEN1(x)		((x) << 16)
+#define PCS_DEEMPH_TX_DEEMPH_GEN2_3_5DB(x)	((x) << 8)
+#define PCS_DEEMPH_TX_DEEMPH_GEN2_6DB(x)	((x) << 0)
+
+#define PCIE20_PARF_PCS_SWING			0x38
+#define PCS_SWING_TX_SWING_FULL(x)		((x) << 8)
+#define PCS_SWING_TX_SWING_LOW(x)		((x) << 0)
+
+#define PCIE20_PARF_CONFIG_BITS		0x50
+#define PHY_RX0_EQ(x)				((x) << 24)
 
 #define PCIE20_v3_PARF_SLV_ADDR_SPACE_SIZE	0x358
 #define SLV_ADDR_SPACE_SZ			0x10000000
@@ -85,11 +103,14 @@
 	struct clk *iface_clk;
 	struct clk *core_clk;
 	struct clk *phy_clk;
+	struct clk *aux_clk;
+	struct clk *ref_clk;
 	struct reset_control *pci_reset;
 	struct reset_control *axi_reset;
 	struct reset_control *ahb_reset;
 	struct reset_control *por_reset;
 	struct reset_control *phy_reset;
+	struct reset_control *ext_reset;
 	struct regulator_bulk_data supplies[QCOM_PCIE_2_1_0_MAX_SUPPLY];
 };
 
@@ -235,6 +256,14 @@
 	if (IS_ERR(res->phy_clk))
 		return PTR_ERR(res->phy_clk);
 
+	res->aux_clk = devm_clk_get_optional(dev, "aux");
+	if (IS_ERR(res->aux_clk))
+		return PTR_ERR(res->aux_clk);
+
+	res->ref_clk = devm_clk_get_optional(dev, "ref");
+	if (IS_ERR(res->ref_clk))
+		return PTR_ERR(res->ref_clk);
+
 	res->pci_reset = devm_reset_control_get_exclusive(dev, "pci");
 	if (IS_ERR(res->pci_reset))
 		return PTR_ERR(res->pci_reset);
@@ -251,6 +280,10 @@
 	if (IS_ERR(res->por_reset))
 		return PTR_ERR(res->por_reset);
 
+	res->ext_reset = devm_reset_control_get_optional_exclusive(dev, "ext");
+	if (IS_ERR(res->ext_reset))
+		return PTR_ERR(res->ext_reset);
+
 	res->phy_reset = devm_reset_control_get_exclusive(dev, "phy");
 	return PTR_ERR_OR_ZERO(res->phy_reset);
 }
@@ -259,14 +292,20 @@
 {
 	struct qcom_pcie_resources_2_1_0 *res = &pcie->res.v2_1_0;
 
+	clk_disable_unprepare(res->phy_clk);
 	reset_control_assert(res->pci_reset);
 	reset_control_assert(res->axi_reset);
 	reset_control_assert(res->ahb_reset);
 	reset_control_assert(res->por_reset);
-	reset_control_assert(res->pci_reset);
+	reset_control_assert(res->ext_reset);
+	reset_control_assert(res->phy_reset);
 	clk_disable_unprepare(res->iface_clk);
 	clk_disable_unprepare(res->core_clk);
-	clk_disable_unprepare(res->phy_clk);
+	clk_disable_unprepare(res->aux_clk);
+	clk_disable_unprepare(res->ref_clk);
+
+	writel(1, pcie->parf + PCIE20_PARF_PHY_CTRL);
+
 	regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies);
 }
 
@@ -275,9 +314,20 @@
 	struct qcom_pcie_resources_2_1_0 *res = &pcie->res.v2_1_0;
 	struct dw_pcie *pci = pcie->pci;
 	struct device *dev = pci->dev;
+	struct device_node *node = dev->of_node;
 	u32 val;
 	int ret;
 
+	/* reset the PCIe interface as uboot can leave it undefined state */
+	reset_control_assert(res->pci_reset);
+	reset_control_assert(res->axi_reset);
+	reset_control_assert(res->ahb_reset);
+	reset_control_assert(res->por_reset);
+	reset_control_assert(res->ext_reset);
+	reset_control_assert(res->phy_reset);
+
+	writel(1, pcie->parf + PCIE20_PARF_PHY_CTRL);
+
 	ret = regulator_bulk_enable(ARRAY_SIZE(res->supplies), res->supplies);
 	if (ret < 0) {
 		dev_err(dev, "cannot enable regulators\n");
@@ -296,32 +346,66 @@
 		goto err_assert_ahb;
 	}
 
-	ret = clk_prepare_enable(res->phy_clk);
-	if (ret) {
-		dev_err(dev, "cannot prepare/enable phy clock\n");
-		goto err_clk_phy;
-	}
-
 	ret = clk_prepare_enable(res->core_clk);
 	if (ret) {
 		dev_err(dev, "cannot prepare/enable core clock\n");
 		goto err_clk_core;
 	}
 
+	ret = clk_prepare_enable(res->aux_clk);
+	if (ret) {
+		dev_err(dev, "cannot prepare/enable aux clock\n");
+		goto err_clk_aux;
+	}
+
+	ret = clk_prepare_enable(res->ref_clk);
+	if (ret) {
+		dev_err(dev, "cannot prepare/enable ref clock\n");
+		goto err_clk_ref;
+	}
+
 	ret = reset_control_deassert(res->ahb_reset);
 	if (ret) {
 		dev_err(dev, "cannot deassert ahb reset\n");
 		goto err_deassert_ahb;
 	}
 
+	ret = reset_control_deassert(res->ext_reset);
+	if (ret) {
+		dev_err(dev, "cannot deassert ext reset\n");
+		goto err_deassert_ahb;
+	}
+
 	/* enable PCIe clocks and resets */
 	val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL);
 	val &= ~BIT(0);
 	writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL);
 
+	if (of_device_is_compatible(node, "qcom,pcie-ipq8064")) {
+		writel(PCS_DEEMPH_TX_DEEMPH_GEN1(24) |
+			       PCS_DEEMPH_TX_DEEMPH_GEN2_3_5DB(24) |
+			       PCS_DEEMPH_TX_DEEMPH_GEN2_6DB(34),
+		       pcie->parf + PCIE20_PARF_PCS_DEEMPH);
+		writel(PCS_SWING_TX_SWING_FULL(120) |
+			       PCS_SWING_TX_SWING_LOW(120),
+		       pcie->parf + PCIE20_PARF_PCS_SWING);
+		writel(PHY_RX0_EQ(4), pcie->parf + PCIE20_PARF_CONFIG_BITS);
+	}
+
+	if (of_device_is_compatible(node, "qcom,pcie-ipq8064")) {
+		/* set TX termination offset */
+		val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL);
+		val &= ~PHY_CTRL_PHY_TX0_TERM_OFFSET_MASK;
+		val |= PHY_CTRL_PHY_TX0_TERM_OFFSET(7);
+		writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL);
+	}
+
 	/* enable external reference clock */
 	val = readl(pcie->parf + PCIE20_PARF_PHY_REFCLK);
-	val |= BIT(16);
+	/* USE_PAD is required only for ipq806x */
+	if (!of_device_is_compatible(node, "qcom,pcie-apq8064"))
+		val &= ~PHY_REFCLK_USE_PAD;
+	val |= PHY_REFCLK_SSP_EN;
 	writel(val, pcie->parf + PCIE20_PARF_PHY_REFCLK);
 
 	ret = reset_control_deassert(res->phy_reset);
@@ -348,6 +432,12 @@
 		return ret;
 	}
 
+	ret = clk_prepare_enable(res->phy_clk);
+	if (ret) {
+		dev_err(dev, "cannot prepare/enable phy clock\n");
+		goto err_deassert_ahb;
+	}
+
 	/* wait for clock acquisition */
 	usleep_range(1000, 1500);
 
@@ -361,10 +451,12 @@
 	return 0;
 
 err_deassert_ahb:
+	clk_disable_unprepare(res->ref_clk);
+err_clk_ref:
+	clk_disable_unprepare(res->aux_clk);
+err_clk_aux:
 	clk_disable_unprepare(res->core_clk);
 err_clk_core:
-	clk_disable_unprepare(res->phy_clk);
-err_clk_phy:
 	clk_disable_unprepare(res->iface_clk);
 err_assert_ahb:
 	regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies);
@@ -1251,22 +1343,21 @@
 	}
 
 	ret = phy_init(pcie->phy);
-	if (ret) {
-		pm_runtime_disable(&pdev->dev);
+	if (ret)
 		goto err_pm_runtime_put;
-	}
 
 	platform_set_drvdata(pdev, pcie);
 
 	ret = dw_pcie_host_init(pp);
 	if (ret) {
 		dev_err(dev, "cannot initialize host\n");
-		pm_runtime_disable(&pdev->dev);
-		goto err_pm_runtime_put;
+		goto err_phy_exit;
 	}
 
 	return 0;
 
+err_phy_exit:
+	phy_exit(pcie->phy);
 err_pm_runtime_put:
 	pm_runtime_put(dev);
 	pm_runtime_disable(dev);
@@ -1289,7 +1380,13 @@
 {
 	dev->class = PCI_CLASS_BRIDGE_PCI << 8;
 }
-DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, PCI_ANY_ID, qcom_fixup_class);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x0101, qcom_fixup_class);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x0104, qcom_fixup_class);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x0106, qcom_fixup_class);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x0107, qcom_fixup_class);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x0302, qcom_fixup_class);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x1000, qcom_fixup_class);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x1001, qcom_fixup_class);
 
 static struct platform_driver qcom_pcie_driver = {
 	.probe = qcom_pcie_probe,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/controller/dwc/pcie-tegra194.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/controller/dwc/pcie-tegra194.c
@@ -7,6 +7,7 @@
  * Author: Vidya Sagar <vidyas@nvidia.com>
  */
 
+#include <linux/bitfield.h>
 #include <linux/clk.h>
 #include <linux/debugfs.h>
 #include <linux/delay.h>
@@ -321,8 +322,7 @@
 	 */
 	val = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKSTA);
 	if (val & PCI_EXP_LNKSTA_LBMS) {
-		current_link_width = (val & PCI_EXP_LNKSTA_NLW) >>
-				     PCI_EXP_LNKSTA_NLW_SHIFT;
+		current_link_width = FIELD_GET(PCI_EXP_LNKSTA_NLW, val);
 		if (pcie->init_link_width > current_link_width) {
 			dev_warn(pci->dev, "PCIe link is bad, width reduced\n");
 			val = dw_pcie_readw_dbi(pci, pcie->pcie_cap_base +
@@ -345,15 +345,14 @@
 {
 	struct dw_pcie *pci = &pcie->pci;
 	struct pcie_port *pp = &pci->pp;
-	u32 val, tmp;
+	u32 val, status_l0, status_l1;
 	u16 val_w;
 
-	val = appl_readl(pcie, APPL_INTR_STATUS_L0);
-	if (val & APPL_INTR_STATUS_L0_LINK_STATE_INT) {
-		val = appl_readl(pcie, APPL_INTR_STATUS_L1_0_0);
-		if (val & APPL_INTR_STATUS_L1_0_0_LINK_REQ_RST_NOT_CHGED) {
-			appl_writel(pcie, val, APPL_INTR_STATUS_L1_0_0);
-
+	status_l0 = appl_readl(pcie, APPL_INTR_STATUS_L0);
+	if (status_l0 & APPL_INTR_STATUS_L0_LINK_STATE_INT) {
+		status_l1 = appl_readl(pcie, APPL_INTR_STATUS_L1_0_0);
+		appl_writel(pcie, status_l1, APPL_INTR_STATUS_L1_0_0);
+		if (status_l1 & APPL_INTR_STATUS_L1_0_0_LINK_REQ_RST_NOT_CHGED) {
 			/* SBR & Surprise Link Down WAR */
 			val = appl_readl(pcie, APPL_CAR_RESET_OVRD);
 			val &= ~APPL_CAR_RESET_OVRD_CYA_OVERRIDE_CORE_RST_N;
@@ -369,15 +368,15 @@
 		}
 	}
 
-	if (val & APPL_INTR_STATUS_L0_INT_INT) {
-		val = appl_readl(pcie, APPL_INTR_STATUS_L1_8_0);
-		if (val & APPL_INTR_STATUS_L1_8_0_AUTO_BW_INT_STS) {
+	if (status_l0 & APPL_INTR_STATUS_L0_INT_INT) {
+		status_l1 = appl_readl(pcie, APPL_INTR_STATUS_L1_8_0);
+		if (status_l1 & APPL_INTR_STATUS_L1_8_0_AUTO_BW_INT_STS) {
 			appl_writel(pcie,
 				    APPL_INTR_STATUS_L1_8_0_AUTO_BW_INT_STS,
 				    APPL_INTR_STATUS_L1_8_0);
 			apply_bad_link_workaround(pp);
 		}
-		if (val & APPL_INTR_STATUS_L1_8_0_BW_MGT_INT_STS) {
+		if (status_l1 & APPL_INTR_STATUS_L1_8_0_BW_MGT_INT_STS) {
 			appl_writel(pcie,
 				    APPL_INTR_STATUS_L1_8_0_BW_MGT_INT_STS,
 				    APPL_INTR_STATUS_L1_8_0);
@@ -389,25 +388,24 @@
 		}
 	}
 
-	val = appl_readl(pcie, APPL_INTR_STATUS_L0);
-	if (val & APPL_INTR_STATUS_L0_CDM_REG_CHK_INT) {
-		val = appl_readl(pcie, APPL_INTR_STATUS_L1_18);
-		tmp = dw_pcie_readl_dbi(pci, PCIE_PL_CHK_REG_CONTROL_STATUS);
-		if (val & APPL_INTR_STATUS_L1_18_CDM_REG_CHK_CMPLT) {
+	if (status_l0 & APPL_INTR_STATUS_L0_CDM_REG_CHK_INT) {
+		status_l1 = appl_readl(pcie, APPL_INTR_STATUS_L1_18);
+		val = dw_pcie_readl_dbi(pci, PCIE_PL_CHK_REG_CONTROL_STATUS);
+		if (status_l1 & APPL_INTR_STATUS_L1_18_CDM_REG_CHK_CMPLT) {
 			dev_info(pci->dev, "CDM check complete\n");
-			tmp |= PCIE_PL_CHK_REG_CHK_REG_COMPLETE;
+			val |= PCIE_PL_CHK_REG_CHK_REG_COMPLETE;
 		}
-		if (val & APPL_INTR_STATUS_L1_18_CDM_REG_CHK_CMP_ERR) {
+		if (status_l1 & APPL_INTR_STATUS_L1_18_CDM_REG_CHK_CMP_ERR) {
 			dev_err(pci->dev, "CDM comparison mismatch\n");
-			tmp |= PCIE_PL_CHK_REG_CHK_REG_COMPARISON_ERROR;
+			val |= PCIE_PL_CHK_REG_CHK_REG_COMPARISON_ERROR;
 		}
-		if (val & APPL_INTR_STATUS_L1_18_CDM_REG_CHK_LOGIC_ERR) {
+		if (status_l1 & APPL_INTR_STATUS_L1_18_CDM_REG_CHK_LOGIC_ERR) {
 			dev_err(pci->dev, "CDM Logic error\n");
-			tmp |= PCIE_PL_CHK_REG_CHK_REG_LOGIC_ERROR;
+			val |= PCIE_PL_CHK_REG_CHK_REG_LOGIC_ERROR;
 		}
-		dw_pcie_writel_dbi(pci, PCIE_PL_CHK_REG_CONTROL_STATUS, tmp);
-		tmp = dw_pcie_readl_dbi(pci, PCIE_PL_CHK_REG_ERR_ADDR);
-		dev_err(pci->dev, "CDM Error Address Offset = 0x%08X\n", tmp);
+		dw_pcie_writel_dbi(pci, PCIE_PL_CHK_REG_CONTROL_STATUS, val);
+		val = dw_pcie_readl_dbi(pci, PCIE_PL_CHK_REG_ERR_ADDR);
+		dev_err(pci->dev, "CDM Error Address Offset = 0x%08X\n", val);
 	}
 
 	return IRQ_HANDLED;
@@ -598,8 +596,7 @@
 
 	val_w = dw_pcie_readw_dbi(&pcie->pci, pcie->pcie_cap_base +
 				  PCI_EXP_LNKSTA);
-	pcie->init_link_width = (val_w & PCI_EXP_LNKSTA_NLW) >>
-				PCI_EXP_LNKSTA_NLW_SHIFT;
+	pcie->init_link_width = FIELD_GET(PCI_EXP_LNKSTA_NLW, val_w);
 
 	val_w = dw_pcie_readw_dbi(&pcie->pci, pcie->pcie_cap_base +
 				  PCI_EXP_LNKCTL);
@@ -775,7 +772,7 @@
 	/* Configure Max lane width from DT */
 	val = dw_pcie_readl_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKCAP);
 	val &= ~PCI_EXP_LNKCAP_MLW;
-	val |= (pcie->num_lanes << PCI_EXP_LNKSTA_NLW_SHIFT);
+	val |= FIELD_PREP(PCI_EXP_LNKCAP_MLW, pcie->num_lanes);
 	dw_pcie_writel_dbi(pci, pcie->pcie_cap_base + PCI_EXP_LNKCAP, val);
 
 	config_gen3_gen4_eq_presets(pcie);
@@ -856,7 +853,7 @@
 		offset = dw_pcie_find_ext_capability(pci, PCI_EXT_CAP_ID_DLF);
 		val = dw_pcie_readl_dbi(pci, offset + PCI_DLF_CAP);
 		val &= ~PCI_DLF_EXCHANGE_ENABLE;
-		dw_pcie_writel_dbi(pci, offset, val);
+		dw_pcie_writel_dbi(pci, offset + PCI_DLF_CAP, val);
 
 		tegra_pcie_prepare_host(pp);
 
@@ -1395,7 +1392,7 @@
 	ret = pinctrl_pm_select_default_state(dev);
 	if (ret < 0) {
 		dev_err(dev, "Failed to configure sideband pins: %d\n", ret);
-		goto fail_pinctrl;
+		goto fail_pm_get_sync;
 	}
 
 	tegra_pcie_init_controller(pcie);
@@ -1422,9 +1419,8 @@
 
 fail_host_init:
 	tegra_pcie_deinit_controller(pcie);
-fail_pinctrl:
-	pm_runtime_put_sync(dev);
 fail_pm_get_sync:
+	pm_runtime_put_sync(dev);
 	pm_runtime_disable(dev);
 	return ret;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/controller/pci-aardvark.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/controller/pci-aardvark.c
@@ -9,6 +9,7 @@
  */
 
 #include <linux/delay.h>
+#include <linux/gpio/consumer.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
@@ -17,6 +18,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/of_address.h>
+#include <linux/of_gpio.h>
 #include <linux/of_pci.h>
 
 #include "../pci.h"
@@ -25,21 +27,8 @@
 /* PCIe core registers */
 #define PCIE_CORE_DEV_ID_REG					0x0
 #define PCIE_CORE_CMD_STATUS_REG				0x4
-#define     PCIE_CORE_CMD_IO_ACCESS_EN				BIT(0)
-#define     PCIE_CORE_CMD_MEM_ACCESS_EN				BIT(1)
-#define     PCIE_CORE_CMD_MEM_IO_REQ_EN				BIT(2)
 #define PCIE_CORE_DEV_REV_REG					0x8
 #define PCIE_CORE_PCIEXP_CAP					0xc0
-#define PCIE_CORE_DEV_CTRL_STATS_REG				0xc8
-#define     PCIE_CORE_DEV_CTRL_STATS_RELAX_ORDER_DISABLE	(0 << 4)
-#define     PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ_SHIFT	5
-#define     PCIE_CORE_DEV_CTRL_STATS_SNOOP_DISABLE		(0 << 11)
-#define     PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SIZE_SHIFT	12
-#define     PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SZ		0x2
-#define PCIE_CORE_LINK_CTRL_STAT_REG				0xd0
-#define     PCIE_CORE_LINK_L0S_ENTRY				BIT(0)
-#define     PCIE_CORE_LINK_TRAINING				BIT(5)
-#define     PCIE_CORE_LINK_WIDTH_SHIFT				20
 #define PCIE_CORE_ERR_CAPCTL_REG				0x118
 #define     PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX			BIT(5)
 #define     PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX_EN			BIT(6)
@@ -61,7 +50,8 @@
 #define   PIO_COMPLETION_STATUS_UR		1
 #define   PIO_COMPLETION_STATUS_CRS		2
 #define   PIO_COMPLETION_STATUS_CA		4
-#define   PIO_NON_POSTED_REQ			BIT(0)
+#define   PIO_NON_POSTED_REQ			BIT(10)
+#define   PIO_ERR_STATUS			BIT(11)
 #define PIO_ADDR_LS				(PIO_BASE_ADDR + 0x8)
 #define PIO_ADDR_MS				(PIO_BASE_ADDR + 0xc)
 #define PIO_WR_DATA				(PIO_BASE_ADDR + 0x10)
@@ -107,27 +97,112 @@
 #define     PCIE_ISR0_MSI_INT_PENDING		BIT(24)
 #define     PCIE_ISR0_INTX_ASSERT(val)		BIT(16 + (val))
 #define     PCIE_ISR0_INTX_DEASSERT(val)	BIT(20 + (val))
-#define	    PCIE_ISR0_ALL_MASK			GENMASK(26, 0)
+#define     PCIE_ISR0_ALL_MASK			GENMASK(31, 0)
 #define PCIE_ISR1_REG				(CONTROL_BASE_ADDR + 0x48)
 #define PCIE_ISR1_MASK_REG			(CONTROL_BASE_ADDR + 0x4C)
 #define     PCIE_ISR1_POWER_STATE_CHANGE	BIT(4)
 #define     PCIE_ISR1_FLUSH			BIT(5)
 #define     PCIE_ISR1_INTX_ASSERT(val)		BIT(8 + (val))
-#define     PCIE_ISR1_ALL_MASK			GENMASK(11, 4)
+#define     PCIE_ISR1_ALL_MASK			GENMASK(31, 0)
 #define PCIE_MSI_ADDR_LOW_REG			(CONTROL_BASE_ADDR + 0x50)
 #define PCIE_MSI_ADDR_HIGH_REG			(CONTROL_BASE_ADDR + 0x54)
 #define PCIE_MSI_STATUS_REG			(CONTROL_BASE_ADDR + 0x58)
 #define PCIE_MSI_MASK_REG			(CONTROL_BASE_ADDR + 0x5C)
+#define     PCIE_MSI_ALL_MASK			GENMASK(31, 0)
 #define PCIE_MSI_PAYLOAD_REG			(CONTROL_BASE_ADDR + 0x9C)
+#define     PCIE_MSI_DATA_MASK			GENMASK(15, 0)
+
+/* PCIe window configuration */
+#define OB_WIN_BASE_ADDR			0x4c00
+#define OB_WIN_BLOCK_SIZE			0x20
+#define OB_WIN_COUNT				8
+#define OB_WIN_REG_ADDR(win, offset)		(OB_WIN_BASE_ADDR + \
+						  OB_WIN_BLOCK_SIZE * (win) + \
+						  (offset))
+#define OB_WIN_MATCH_LS(win)			OB_WIN_REG_ADDR(win, 0x00)
+#define     OB_WIN_ENABLE			BIT(0)
+#define OB_WIN_MATCH_MS(win)			OB_WIN_REG_ADDR(win, 0x04)
+#define OB_WIN_REMAP_LS(win)			OB_WIN_REG_ADDR(win, 0x08)
+#define OB_WIN_REMAP_MS(win)			OB_WIN_REG_ADDR(win, 0x0c)
+#define OB_WIN_MASK_LS(win)			OB_WIN_REG_ADDR(win, 0x10)
+#define OB_WIN_MASK_MS(win)			OB_WIN_REG_ADDR(win, 0x14)
+#define OB_WIN_ACTIONS(win)			OB_WIN_REG_ADDR(win, 0x18)
+#define OB_WIN_DEFAULT_ACTIONS			(OB_WIN_ACTIONS(OB_WIN_COUNT-1) + 0x4)
+#define     OB_WIN_FUNC_NUM_MASK		GENMASK(31, 24)
+#define     OB_WIN_FUNC_NUM_SHIFT		24
+#define     OB_WIN_FUNC_NUM_ENABLE		BIT(23)
+#define     OB_WIN_BUS_NUM_BITS_MASK		GENMASK(22, 20)
+#define     OB_WIN_BUS_NUM_BITS_SHIFT		20
+#define     OB_WIN_MSG_CODE_ENABLE		BIT(22)
+#define     OB_WIN_MSG_CODE_MASK		GENMASK(21, 14)
+#define     OB_WIN_MSG_CODE_SHIFT		14
+#define     OB_WIN_MSG_PAYLOAD_LEN		BIT(12)
+#define     OB_WIN_ATTR_ENABLE			BIT(11)
+#define     OB_WIN_ATTR_TC_MASK			GENMASK(10, 8)
+#define     OB_WIN_ATTR_TC_SHIFT		8
+#define     OB_WIN_ATTR_RELAXED			BIT(7)
+#define     OB_WIN_ATTR_NOSNOOP			BIT(6)
+#define     OB_WIN_ATTR_POISON			BIT(5)
+#define     OB_WIN_ATTR_IDO			BIT(4)
+#define     OB_WIN_TYPE_MASK			GENMASK(3, 0)
+#define     OB_WIN_TYPE_SHIFT			0
+#define     OB_WIN_TYPE_MEM			0x0
+#define     OB_WIN_TYPE_IO			0x4
+#define     OB_WIN_TYPE_CONFIG_TYPE0		0x8
+#define     OB_WIN_TYPE_CONFIG_TYPE1		0x9
+#define     OB_WIN_TYPE_MSG			0xc
 
 /* LMI registers base address and register offsets */
 #define LMI_BASE_ADDR				0x6000
 #define CFG_REG					(LMI_BASE_ADDR + 0x0)
 #define     LTSSM_SHIFT				24
 #define     LTSSM_MASK				0x3f
-#define     LTSSM_L0				0x10
 #define     RC_BAR_CONFIG			0x300
 
+/* LTSSM values in CFG_REG */
+enum {
+	LTSSM_DETECT_QUIET			= 0x0,
+	LTSSM_DETECT_ACTIVE			= 0x1,
+	LTSSM_POLLING_ACTIVE			= 0x2,
+	LTSSM_POLLING_COMPLIANCE		= 0x3,
+	LTSSM_POLLING_CONFIGURATION		= 0x4,
+	LTSSM_CONFIG_LINKWIDTH_START		= 0x5,
+	LTSSM_CONFIG_LINKWIDTH_ACCEPT		= 0x6,
+	LTSSM_CONFIG_LANENUM_ACCEPT		= 0x7,
+	LTSSM_CONFIG_LANENUM_WAIT		= 0x8,
+	LTSSM_CONFIG_COMPLETE			= 0x9,
+	LTSSM_CONFIG_IDLE			= 0xa,
+	LTSSM_RECOVERY_RCVR_LOCK		= 0xb,
+	LTSSM_RECOVERY_SPEED			= 0xc,
+	LTSSM_RECOVERY_RCVR_CFG			= 0xd,
+	LTSSM_RECOVERY_IDLE			= 0xe,
+	LTSSM_L0				= 0x10,
+	LTSSM_RX_L0S_ENTRY			= 0x11,
+	LTSSM_RX_L0S_IDLE			= 0x12,
+	LTSSM_RX_L0S_FTS			= 0x13,
+	LTSSM_TX_L0S_ENTRY			= 0x14,
+	LTSSM_TX_L0S_IDLE			= 0x15,
+	LTSSM_TX_L0S_FTS			= 0x16,
+	LTSSM_L1_ENTRY				= 0x17,
+	LTSSM_L1_IDLE				= 0x18,
+	LTSSM_L2_IDLE				= 0x19,
+	LTSSM_L2_TRANSMIT_WAKE			= 0x1a,
+	LTSSM_DISABLED				= 0x20,
+	LTSSM_LOOPBACK_ENTRY_MASTER		= 0x21,
+	LTSSM_LOOPBACK_ACTIVE_MASTER		= 0x22,
+	LTSSM_LOOPBACK_EXIT_MASTER		= 0x23,
+	LTSSM_LOOPBACK_ENTRY_SLAVE		= 0x24,
+	LTSSM_LOOPBACK_ACTIVE_SLAVE		= 0x25,
+	LTSSM_LOOPBACK_EXIT_SLAVE		= 0x26,
+	LTSSM_HOT_RESET				= 0x27,
+	LTSSM_RECOVERY_EQUALIZATION_PHASE0	= 0x28,
+	LTSSM_RECOVERY_EQUALIZATION_PHASE1	= 0x29,
+	LTSSM_RECOVERY_EQUALIZATION_PHASE2	= 0x2a,
+	LTSSM_RECOVERY_EQUALIZATION_PHASE3	= 0x2b,
+};
+
+#define VENDOR_ID_REG				(LMI_BASE_ADDR + 0x44)
+
 /* PCIe core controller registers */
 #define CTRL_CORE_BASE_ADDR			0x18000
 #define CTRL_CONFIG_REG				(CTRL_CORE_BASE_ADDR + 0x0)
@@ -158,7 +233,7 @@
 #define     PCIE_IRQ_MSI_INT2_DET		BIT(21)
 #define     PCIE_IRQ_RC_DBELL_DET		BIT(22)
 #define     PCIE_IRQ_EP_STATUS			BIT(23)
-#define     PCIE_IRQ_ALL_MASK			0xfff0fb
+#define     PCIE_IRQ_ALL_MASK			GENMASK(31, 0)
 #define     PCIE_IRQ_ENABLE_INTS_MASK		PCIE_IRQ_CORE_INT
 
 /* Transaction types */
@@ -175,20 +250,33 @@
 	(PCIE_CONF_BUS(bus) | PCIE_CONF_DEV(PCI_SLOT(devfn))	| \
 	 PCIE_CONF_FUNC(PCI_FUNC(devfn)) | PCIE_CONF_REG(where))
 
-#define PIO_TIMEOUT_MS			1
+#define PIO_RETRY_CNT			750000 /* 1.5 s */
+#define PIO_RETRY_DELAY			2 /* 2 us*/
 
 #define LINK_WAIT_MAX_RETRIES		10
 #define LINK_WAIT_USLEEP_MIN		90000
 #define LINK_WAIT_USLEEP_MAX		100000
+#define RETRAIN_WAIT_MAX_RETRIES	10
+#define RETRAIN_WAIT_USLEEP_US		2000
 
 #define MSI_IRQ_NUM			32
 
+#define CFG_RD_CRS_VAL			0xffff0001
+
 struct advk_pcie {
 	struct platform_device *pdev;
 	void __iomem *base;
 	struct list_head resources;
+	struct {
+		phys_addr_t match;
+		phys_addr_t remap;
+		phys_addr_t mask;
+		u32 actions;
+	} wins[OB_WIN_COUNT];
+	u8 wins_count;
 	struct irq_domain *irq_domain;
 	struct irq_chip irq_chip;
+	raw_spinlock_t irq_lock;
 	struct irq_domain *msi_domain;
 	struct irq_domain *msi_inner_domain;
 	struct irq_chip msi_bottom_irq_chip;
@@ -198,7 +286,9 @@
 	struct mutex msi_used_lock;
 	u16 msi_msg;
 	int root_bus_nr;
+	int link_gen;
 	struct pci_bridge_emul bridge;
+	struct gpio_desc *reset_gpio;
 };
 
 static inline void advk_writel(struct advk_pcie *pcie, u32 val, u64 reg)
@@ -211,37 +301,186 @@
 	return readl(pcie->base + reg);
 }
 
-static int advk_pcie_link_up(struct advk_pcie *pcie)
+static u8 advk_pcie_ltssm_state(struct advk_pcie *pcie)
 {
-	u32 val, ltssm_state;
+	u32 val;
+	u8 ltssm_state;
 
 	val = advk_readl(pcie, CFG_REG);
 	ltssm_state = (val >> LTSSM_SHIFT) & LTSSM_MASK;
-	return ltssm_state >= LTSSM_L0;
+	return ltssm_state;
+}
+
+static inline bool advk_pcie_link_up(struct advk_pcie *pcie)
+{
+	/* check if LTSSM is in normal operation - some L* state */
+	u8 ltssm_state = advk_pcie_ltssm_state(pcie);
+	return ltssm_state >= LTSSM_L0 && ltssm_state < LTSSM_DISABLED;
+}
+
+static inline bool advk_pcie_link_active(struct advk_pcie *pcie)
+{
+	/*
+	 * According to PCIe Base specification 3.0, Table 4-14: Link
+	 * Status Mapped to the LTSSM, and 4.2.6.3.6 Configuration.Idle
+	 * is Link Up mapped to LTSSM Configuration.Idle, Recovery, L0,
+	 * L0s, L1 and L2 states. And according to 3.2.1. Data Link
+	 * Control and Management State Machine Rules is DL Up status
+	 * reported in DL Active state.
+	 */
+	u8 ltssm_state = advk_pcie_ltssm_state(pcie);
+	return ltssm_state >= LTSSM_CONFIG_IDLE && ltssm_state < LTSSM_DISABLED;
+}
+
+static inline bool advk_pcie_link_training(struct advk_pcie *pcie)
+{
+	/*
+	 * According to PCIe Base specification 3.0, Table 4-14: Link
+	 * Status Mapped to the LTSSM is Link Training mapped to LTSSM
+	 * Configuration and Recovery states.
+	 */
+	u8 ltssm_state = advk_pcie_ltssm_state(pcie);
+	return ((ltssm_state >= LTSSM_CONFIG_LINKWIDTH_START &&
+		 ltssm_state < LTSSM_L0) ||
+		(ltssm_state >= LTSSM_RECOVERY_EQUALIZATION_PHASE0 &&
+		 ltssm_state <= LTSSM_RECOVERY_EQUALIZATION_PHASE3));
 }
 
 static int advk_pcie_wait_for_link(struct advk_pcie *pcie)
 {
-	struct device *dev = &pcie->pdev->dev;
 	int retries;
 
 	/* check if the link is up or not */
 	for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) {
-		if (advk_pcie_link_up(pcie)) {
-			dev_info(dev, "link up\n");
+		if (advk_pcie_link_up(pcie))
 			return 0;
-		}
 
 		usleep_range(LINK_WAIT_USLEEP_MIN, LINK_WAIT_USLEEP_MAX);
 	}
 
-	dev_err(dev, "link never came up\n");
 	return -ETIMEDOUT;
 }
 
+static void advk_pcie_wait_for_retrain(struct advk_pcie *pcie)
+{
+	size_t retries;
+
+	for (retries = 0; retries < RETRAIN_WAIT_MAX_RETRIES; ++retries) {
+		if (advk_pcie_link_training(pcie))
+			break;
+		udelay(RETRAIN_WAIT_USLEEP_US);
+	}
+}
+
+static void advk_pcie_issue_perst(struct advk_pcie *pcie)
+{
+	if (!pcie->reset_gpio)
+		return;
+
+	/* 10ms delay is needed for some cards */
+	dev_info(&pcie->pdev->dev, "issuing PERST via reset GPIO for 10ms\n");
+	gpiod_set_value_cansleep(pcie->reset_gpio, 1);
+	usleep_range(10000, 11000);
+	gpiod_set_value_cansleep(pcie->reset_gpio, 0);
+}
+
+static void advk_pcie_train_link(struct advk_pcie *pcie)
+{
+	struct device *dev = &pcie->pdev->dev;
+	u32 reg;
+	int ret;
+
+	/*
+	 * Setup PCIe rev / gen compliance based on device tree property
+	 * 'max-link-speed' which also forces maximal link speed.
+	 */
+	reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
+	reg &= ~PCIE_GEN_SEL_MSK;
+	if (pcie->link_gen == 3)
+		reg |= SPEED_GEN_3;
+	else if (pcie->link_gen == 2)
+		reg |= SPEED_GEN_2;
+	else
+		reg |= SPEED_GEN_1;
+	advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
+
+	/*
+	 * Set maximal link speed value also into PCIe Link Control 2 register.
+	 * Armada 3700 Functional Specification says that default value is based
+	 * on SPEED_GEN but tests showed that default value is always 8.0 GT/s.
+	 */
+	reg = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKCTL2);
+	reg &= ~PCI_EXP_LNKCTL2_TLS;
+	if (pcie->link_gen == 3)
+		reg |= PCI_EXP_LNKCTL2_TLS_8_0GT;
+	else if (pcie->link_gen == 2)
+		reg |= PCI_EXP_LNKCTL2_TLS_5_0GT;
+	else
+		reg |= PCI_EXP_LNKCTL2_TLS_2_5GT;
+	advk_writel(pcie, reg, PCIE_CORE_PCIEXP_CAP + PCI_EXP_LNKCTL2);
+
+	/* Enable link training after selecting PCIe generation */
+	reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
+	reg |= LINK_TRAINING_EN;
+	advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
+
+	/*
+	 * Reset PCIe card via PERST# signal. Some cards are not detected
+	 * during link training when they are in some non-initial state.
+	 */
+	advk_pcie_issue_perst(pcie);
+
+	/*
+	 * PERST# signal could have been asserted by pinctrl subsystem before
+	 * probe() callback has been called or issued explicitly by reset gpio
+	 * function advk_pcie_issue_perst(), making the endpoint going into
+	 * fundamental reset. As required by PCI Express spec (PCI Express
+	 * Base Specification, REV. 4.0 PCI Express, February 19 2014, 6.6.1
+	 * Conventional Reset) a delay for at least 100ms after such a reset
+	 * before sending a Configuration Request to the device is needed.
+	 * So wait until PCIe link is up. Function advk_pcie_wait_for_link()
+	 * waits for link at least 900ms.
+	 */
+	ret = advk_pcie_wait_for_link(pcie);
+	if (ret < 0)
+		dev_err(dev, "link never came up\n");
+	else
+		dev_info(dev, "link up\n");
+}
+
+/*
+ * Set PCIe address window register which could be used for memory
+ * mapping.
+ */
+static void advk_pcie_set_ob_win(struct advk_pcie *pcie, u8 win_num,
+				 phys_addr_t match, phys_addr_t remap,
+				 phys_addr_t mask, u32 actions)
+{
+	advk_writel(pcie, OB_WIN_ENABLE |
+			  lower_32_bits(match), OB_WIN_MATCH_LS(win_num));
+	advk_writel(pcie, upper_32_bits(match), OB_WIN_MATCH_MS(win_num));
+	advk_writel(pcie, lower_32_bits(remap), OB_WIN_REMAP_LS(win_num));
+	advk_writel(pcie, upper_32_bits(remap), OB_WIN_REMAP_MS(win_num));
+	advk_writel(pcie, lower_32_bits(mask), OB_WIN_MASK_LS(win_num));
+	advk_writel(pcie, upper_32_bits(mask), OB_WIN_MASK_MS(win_num));
+	advk_writel(pcie, actions, OB_WIN_ACTIONS(win_num));
+}
+
+static void advk_pcie_disable_ob_win(struct advk_pcie *pcie, u8 win_num)
+{
+	advk_writel(pcie, 0, OB_WIN_MATCH_LS(win_num));
+	advk_writel(pcie, 0, OB_WIN_MATCH_MS(win_num));
+	advk_writel(pcie, 0, OB_WIN_REMAP_LS(win_num));
+	advk_writel(pcie, 0, OB_WIN_REMAP_MS(win_num));
+	advk_writel(pcie, 0, OB_WIN_MASK_LS(win_num));
+	advk_writel(pcie, 0, OB_WIN_MASK_MS(win_num));
+	advk_writel(pcie, 0, OB_WIN_ACTIONS(win_num));
+}
+
 static void advk_pcie_setup_hw(struct advk_pcie *pcie)
 {
 	u32 reg;
+	int i;
 
 	/* Set to Direct mode */
 	reg = advk_readl(pcie, CTRL_CONFIG_REG);
@@ -254,6 +493,41 @@
 	reg |= (IS_RC_MSK << IS_RC_SHIFT);
 	advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
 
+	/*
+	 * Replace incorrect PCI vendor id value 0x1b4b by correct value 0x11ab.
+	 * VENDOR_ID_REG contains vendor id in low 16 bits and subsystem vendor
+	 * id in high 16 bits. Updating this register changes readback value of
+	 * read-only vendor id bits in PCIE_CORE_DEV_ID_REG register. Workaround
+	 * for erratum 4.1: "The value of device and vendor ID is incorrect".
+	 */
+	reg = (PCI_VENDOR_ID_MARVELL << 16) | PCI_VENDOR_ID_MARVELL;
+	advk_writel(pcie, reg, VENDOR_ID_REG);
+
+	/*
+	 * Change Class Code of PCI Bridge device to PCI Bridge (0x600400),
+	 * because the default value is Mass storage controller (0x010400).
+	 *
+	 * Note that this Aardvark PCI Bridge does not have compliant Type 1
+	 * Configuration Space and it even cannot be accessed via Aardvark's
+	 * PCI config space access method. Something like config space is
+	 * available in internal Aardvark registers starting at offset 0x0
+	 * and is reported as Type 0. In range 0x10 - 0x34 it has totally
+	 * different registers.
+	 *
+	 * Therefore driver uses emulation of PCI Bridge which emulates
+	 * access to configuration space via internal Aardvark registers or
+	 * emulated configuration buffer.
+	 */
+	reg = advk_readl(pcie, PCIE_CORE_DEV_REV_REG);
+	reg &= ~0xffffff00;
+	reg |= (PCI_CLASS_BRIDGE_PCI << 8) << 8;
+	advk_writel(pcie, reg, PCIE_CORE_DEV_REV_REG);
+
+	/* Disable Root Bridge I/O space, memory space and bus mastering */
+	reg = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG);
+	reg &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+	advk_writel(pcie, reg, PCIE_CORE_CMD_STATUS_REG);
+
 	/* Set Advanced Error Capabilities and Control PF0 register */
 	reg = PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX |
 		PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX_EN |
@@ -261,42 +535,34 @@
 		PCIE_CORE_ERR_CAPCTL_ECRC_CHCK_RCV;
 	advk_writel(pcie, reg, PCIE_CORE_ERR_CAPCTL_REG);
 
-	/* Set PCIe Device Control and Status 1 PF0 register */
-	reg = PCIE_CORE_DEV_CTRL_STATS_RELAX_ORDER_DISABLE |
-		(7 << PCIE_CORE_DEV_CTRL_STATS_MAX_PAYLOAD_SZ_SHIFT) |
-		PCIE_CORE_DEV_CTRL_STATS_SNOOP_DISABLE |
-		(PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SZ <<
-		 PCIE_CORE_DEV_CTRL_STATS_MAX_RD_REQ_SIZE_SHIFT);
-	advk_writel(pcie, reg, PCIE_CORE_DEV_CTRL_STATS_REG);
+	/* Set PCIe Device Control register */
+	reg = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + PCI_EXP_DEVCTL);
+	reg &= ~PCI_EXP_DEVCTL_RELAX_EN;
+	reg &= ~PCI_EXP_DEVCTL_NOSNOOP_EN;
+	reg &= ~PCI_EXP_DEVCTL_PAYLOAD;
+	reg &= ~PCI_EXP_DEVCTL_READRQ;
+	reg |= PCI_EXP_DEVCTL_PAYLOAD_512B;
+	reg |= PCI_EXP_DEVCTL_READRQ_512B;
+	advk_writel(pcie, reg, PCIE_CORE_PCIEXP_CAP + PCI_EXP_DEVCTL);
 
 	/* Program PCIe Control 2 to disable strict ordering */
 	reg = PCIE_CORE_CTRL2_RESERVED |
 		PCIE_CORE_CTRL2_TD_ENABLE;
 	advk_writel(pcie, reg, PCIE_CORE_CTRL2_REG);
 
-	/* Set GEN2 */
-	reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
-	reg &= ~PCIE_GEN_SEL_MSK;
-	reg |= SPEED_GEN_2;
-	advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
-
 	/* Set lane X1 */
 	reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
 	reg &= ~LANE_CNT_MSK;
 	reg |= LANE_COUNT_1;
 	advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
 
-	/* Enable link training */
-	reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
-	reg |= LINK_TRAINING_EN;
-	advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
-
 	/* Enable MSI */
 	reg = advk_readl(pcie, PCIE_CORE_CTRL2_REG);
 	reg |= PCIE_CORE_CTRL2_MSI_ENABLE;
 	advk_writel(pcie, reg, PCIE_CORE_CTRL2_REG);
 
 	/* Clear all interrupts */
+	advk_writel(pcie, PCIE_MSI_ALL_MASK, PCIE_MSI_STATUS_REG);
 	advk_writel(pcie, PCIE_ISR0_ALL_MASK, PCIE_ISR0_REG);
 	advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_REG);
 	advk_writel(pcie, PCIE_IRQ_ALL_MASK, HOST_CTRL_INT_STATUS_REG);
@@ -309,97 +575,244 @@
 	advk_writel(pcie, PCIE_ISR1_ALL_MASK, PCIE_ISR1_MASK_REG);
 
 	/* Unmask all MSIs */
-	advk_writel(pcie, 0, PCIE_MSI_MASK_REG);
+	advk_writel(pcie, ~(u32)PCIE_MSI_ALL_MASK, PCIE_MSI_MASK_REG);
 
 	/* Enable summary interrupt for GIC SPI source */
 	reg = PCIE_IRQ_ALL_MASK & (~PCIE_IRQ_ENABLE_INTS_MASK);
 	advk_writel(pcie, reg, HOST_CTRL_INT_MASK_REG);
 
+	/*
+	 * Enable AXI address window location generation:
+	 * When it is enabled, the default outbound window
+	 * configurations (Default User Field: 0xD0074CFC)
+	 * are used to transparent address translation for
+	 * the outbound transactions. Thus, PCIe address
+	 * windows are not required for transparent memory
+	 * access when default outbound window configuration
+	 * is set for memory access.
+	 */
 	reg = advk_readl(pcie, PCIE_CORE_CTRL2_REG);
 	reg |= PCIE_CORE_CTRL2_OB_WIN_ENABLE;
 	advk_writel(pcie, reg, PCIE_CORE_CTRL2_REG);
 
-	/* Bypass the address window mapping for PIO */
+	/*
+	 * Set memory access in Default User Field so it
+	 * is not required to configure PCIe address for
+	 * transparent memory access.
+	 */
+	advk_writel(pcie, OB_WIN_TYPE_MEM, OB_WIN_DEFAULT_ACTIONS);
+
+	/*
+	 * Bypass the address window mapping for PIO:
+	 * Since PIO access already contains all required
+	 * info over AXI interface by PIO registers, the
+	 * address window is not required.
+	 */
 	reg = advk_readl(pcie, PIO_CTRL);
 	reg |= PIO_CTRL_ADDR_WIN_DISABLE;
 	advk_writel(pcie, reg, PIO_CTRL);
 
-	/* Start link training */
-	reg = advk_readl(pcie, PCIE_CORE_LINK_CTRL_STAT_REG);
-	reg |= PCIE_CORE_LINK_TRAINING;
-	advk_writel(pcie, reg, PCIE_CORE_LINK_CTRL_STAT_REG);
-
-	advk_pcie_wait_for_link(pcie);
-
-	reg = PCIE_CORE_LINK_L0S_ENTRY |
-		(1 << PCIE_CORE_LINK_WIDTH_SHIFT);
-	advk_writel(pcie, reg, PCIE_CORE_LINK_CTRL_STAT_REG);
+	/*
+	 * Configure PCIe address windows for non-memory or
+	 * non-transparent access as by default PCIe uses
+	 * transparent memory access.
+	 */
+	for (i = 0; i < pcie->wins_count; i++)
+		advk_pcie_set_ob_win(pcie, i,
+				     pcie->wins[i].match, pcie->wins[i].remap,
+				     pcie->wins[i].mask, pcie->wins[i].actions);
+
+	/* Disable remaining PCIe outbound windows */
+	for (i = pcie->wins_count; i < OB_WIN_COUNT; i++)
+		advk_pcie_disable_ob_win(pcie, i);
 
-	reg = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG);
-	reg |= PCIE_CORE_CMD_MEM_ACCESS_EN |
-		PCIE_CORE_CMD_IO_ACCESS_EN |
-		PCIE_CORE_CMD_MEM_IO_REQ_EN;
-	advk_writel(pcie, reg, PCIE_CORE_CMD_STATUS_REG);
+	advk_pcie_train_link(pcie);
 }
 
-static void advk_pcie_check_pio_status(struct advk_pcie *pcie)
+static int advk_pcie_check_pio_status(struct advk_pcie *pcie, bool allow_crs, u32 *val)
 {
 	struct device *dev = &pcie->pdev->dev;
 	u32 reg;
 	unsigned int status;
 	char *strcomp_status, *str_posted;
+	int ret;
 
 	reg = advk_readl(pcie, PIO_STAT);
 	status = (reg & PIO_COMPLETION_STATUS_MASK) >>
 		PIO_COMPLETION_STATUS_SHIFT;
 
-	if (!status)
-		return;
-
+	/*
+	 * According to HW spec, the PIO status check sequence as below:
+	 * 1) even if COMPLETION_STATUS(bit9:7) indicates successful,
+	 *    it still needs to check Error Status(bit11), only when this bit
+	 *    indicates no error happen, the operation is successful.
+	 * 2) value Unsupported Request(1) of COMPLETION_STATUS(bit9:7) only
+	 *    means a PIO write error, and for PIO read it is successful with
+	 *    a read value of 0xFFFFFFFF.
+	 * 3) value Completion Retry Status(CRS) of COMPLETION_STATUS(bit9:7)
+	 *    only means a PIO write error, and for PIO read it is successful
+	 *    with a read value of 0xFFFF0001.
+	 * 4) value Completer Abort (CA) of COMPLETION_STATUS(bit9:7) means
+	 *    error for both PIO read and PIO write operation.
+	 * 5) other errors are indicated as 'unknown'.
+	 */
 	switch (status) {
+	case PIO_COMPLETION_STATUS_OK:
+		if (reg & PIO_ERR_STATUS) {
+			strcomp_status = "COMP_ERR";
+			ret = -EFAULT;
+			break;
+		}
+		/* Get the read result */
+		if (val)
+			*val = advk_readl(pcie, PIO_RD_DATA);
+		/* No error */
+		strcomp_status = NULL;
+		ret = 0;
+		break;
 	case PIO_COMPLETION_STATUS_UR:
 		strcomp_status = "UR";
+		ret = -EOPNOTSUPP;
 		break;
 	case PIO_COMPLETION_STATUS_CRS:
+		if (allow_crs && val) {
+			/* PCIe r4.0, sec 2.3.2, says:
+			 * If CRS Software Visibility is enabled:
+			 * For a Configuration Read Request that includes both
+			 * bytes of the Vendor ID field of a device Function's
+			 * Configuration Space Header, the Root Complex must
+			 * complete the Request to the host by returning a
+			 * read-data value of 0001h for the Vendor ID field and
+			 * all '1's for any additional bytes included in the
+			 * request.
+			 *
+			 * So CRS in this case is not an error status.
+			 */
+			*val = CFG_RD_CRS_VAL;
+			strcomp_status = NULL;
+			ret = 0;
+			break;
+		}
+		/* PCIe r4.0, sec 2.3.2, says:
+		 * If CRS Software Visibility is not enabled, the Root Complex
+		 * must re-issue the Configuration Request as a new Request.
+		 * If CRS Software Visibility is enabled: For a Configuration
+		 * Write Request or for any other Configuration Read Request,
+		 * the Root Complex must re-issue the Configuration Request as
+		 * a new Request.
+		 * A Root Complex implementation may choose to limit the number
+		 * of Configuration Request/CRS Completion Status loops before
+		 * determining that something is wrong with the target of the
+		 * Request and taking appropriate action, e.g., complete the
+		 * Request to the host as a failed transaction.
+		 *
+		 * So return -EAGAIN and caller (pci-aardvark.c driver) will
+		 * re-issue request again up to the PIO_RETRY_CNT retries.
+		 */
 		strcomp_status = "CRS";
+		ret = -EAGAIN;
 		break;
 	case PIO_COMPLETION_STATUS_CA:
 		strcomp_status = "CA";
+		ret = -ECANCELED;
 		break;
 	default:
 		strcomp_status = "Unknown";
+		ret = -EINVAL;
 		break;
 	}
 
+	if (!strcomp_status)
+		return ret;
+
 	if (reg & PIO_NON_POSTED_REQ)
 		str_posted = "Non-posted";
 	else
 		str_posted = "Posted";
 
-	dev_err(dev, "%s PIO Response Status: %s, %#x @ %#x\n",
+	dev_dbg(dev, "%s PIO Response Status: %s, %#x @ %#x\n",
 		str_posted, strcomp_status, reg, advk_readl(pcie, PIO_ADDR_LS));
+
+	return ret;
 }
 
 static int advk_pcie_wait_pio(struct advk_pcie *pcie)
 {
 	struct device *dev = &pcie->pdev->dev;
-	unsigned long timeout;
-
-	timeout = jiffies + msecs_to_jiffies(PIO_TIMEOUT_MS);
+	int i;
 
-	while (time_before(jiffies, timeout)) {
+	for (i = 1; i <= PIO_RETRY_CNT; i++) {
 		u32 start, isr;
 
 		start = advk_readl(pcie, PIO_START);
 		isr = advk_readl(pcie, PIO_ISR);
 		if (!start && isr)
-			return 0;
+			return i;
+		udelay(PIO_RETRY_DELAY);
 	}
 
-	dev_err(dev, "config read/write timed out\n");
+	dev_err(dev, "PIO read/write transfer time out\n");
 	return -ETIMEDOUT;
 }
 
+static pci_bridge_emul_read_status_t
+advk_pci_bridge_emul_base_conf_read(struct pci_bridge_emul *bridge,
+				    int reg, u32 *value)
+{
+	struct advk_pcie *pcie = bridge->data;
+
+	switch (reg) {
+	case PCI_COMMAND:
+		*value = advk_readl(pcie, PCIE_CORE_CMD_STATUS_REG);
+		return PCI_BRIDGE_EMUL_HANDLED;
+
+	case PCI_INTERRUPT_LINE: {
+		/*
+		 * From the whole 32bit register we support reading from HW only
+		 * one bit: PCI_BRIDGE_CTL_BUS_RESET.
+		 * Other bits are retrieved only from emulated config buffer.
+		 */
+		__le32 *cfgspace = (__le32 *)&bridge->conf;
+		u32 val = le32_to_cpu(cfgspace[PCI_INTERRUPT_LINE / 4]);
+		if (advk_readl(pcie, PCIE_CORE_CTRL1_REG) & HOT_RESET_GEN)
+			val |= PCI_BRIDGE_CTL_BUS_RESET << 16;
+		else
+			val &= ~(PCI_BRIDGE_CTL_BUS_RESET << 16);
+		*value = val;
+		return PCI_BRIDGE_EMUL_HANDLED;
+	}
+
+	default:
+		return PCI_BRIDGE_EMUL_NOT_HANDLED;
+	}
+}
+
+static void
+advk_pci_bridge_emul_base_conf_write(struct pci_bridge_emul *bridge,
+				     int reg, u32 old, u32 new, u32 mask)
+{
+	struct advk_pcie *pcie = bridge->data;
+
+	switch (reg) {
+	case PCI_COMMAND:
+		advk_writel(pcie, new, PCIE_CORE_CMD_STATUS_REG);
+		break;
+
+	case PCI_INTERRUPT_LINE:
+		if (mask & (PCI_BRIDGE_CTL_BUS_RESET << 16)) {
+			u32 val = advk_readl(pcie, PCIE_CORE_CTRL1_REG);
+			if (new & (PCI_BRIDGE_CTL_BUS_RESET << 16))
+				val |= HOT_RESET_GEN;
+			else
+				val &= ~HOT_RESET_GEN;
+			advk_writel(pcie, val, PCIE_CORE_CTRL1_REG);
+		}
+		break;
+
+	default:
+		break;
+	}
+}
 
 static pci_bridge_emul_read_status_t
 advk_pci_bridge_emul_pcie_conf_read(struct pci_bridge_emul *bridge,
@@ -415,22 +828,47 @@
 
 	case PCI_EXP_RTCTL: {
 		u32 val = advk_readl(pcie, PCIE_ISR0_MASK_REG);
-		*value = (val & PCIE_MSG_PM_PME_MASK) ? PCI_EXP_RTCTL_PMEIE : 0;
+		*value = (val & PCIE_MSG_PM_PME_MASK) ? 0 : PCI_EXP_RTCTL_PMEIE;
+		*value |= le16_to_cpu(bridge->pcie_conf.rootctl) & PCI_EXP_RTCTL_CRSSVE;
+		*value |= PCI_EXP_RTCAP_CRSVIS << 16;
 		return PCI_BRIDGE_EMUL_HANDLED;
 	}
 
 	case PCI_EXP_RTSTA: {
 		u32 isr0 = advk_readl(pcie, PCIE_ISR0_REG);
 		u32 msglog = advk_readl(pcie, PCIE_MSG_LOG_REG);
-		*value = (isr0 & PCIE_MSG_PM_PME_MASK) << 16 | (msglog >> 16);
+		*value = msglog >> 16;
+		if (isr0 & PCIE_MSG_PM_PME_MASK)
+			*value |= PCI_EXP_RTSTA_PME;
+		return PCI_BRIDGE_EMUL_HANDLED;
+	}
+
+	case PCI_EXP_LNKCAP: {
+		u32 val = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg);
+		/*
+		 * PCI_EXP_LNKCAP_DLLLARC bit is hardwired in aardvark HW to 0.
+		 * But support for PCI_EXP_LNKSTA_DLLLA is emulated via ltssm
+		 * state so explicitly enable PCI_EXP_LNKCAP_DLLLARC flag.
+		 */
+		val |= PCI_EXP_LNKCAP_DLLLARC;
+		*value = val;
+		return PCI_BRIDGE_EMUL_HANDLED;
+	}
+
+	case PCI_EXP_LNKCTL: {
+		/* u32 contains both PCI_EXP_LNKCTL and PCI_EXP_LNKSTA */
+		u32 val = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg) &
+			~(PCI_EXP_LNKSTA_LT << 16);
+		if (advk_pcie_link_training(pcie))
+			val |= (PCI_EXP_LNKSTA_LT << 16);
+		if (advk_pcie_link_active(pcie))
+			val |= (PCI_EXP_LNKSTA_DLLLA << 16);
+		*value = val;
 		return PCI_BRIDGE_EMUL_HANDLED;
 	}
 
-	case PCI_CAP_LIST_ID:
 	case PCI_EXP_DEVCAP:
 	case PCI_EXP_DEVCTL:
-	case PCI_EXP_LNKCAP:
-	case PCI_EXP_LNKCTL:
 		*value = advk_readl(pcie, PCIE_CORE_PCIEXP_CAP + reg);
 		return PCI_BRIDGE_EMUL_HANDLED;
 	default:
@@ -447,14 +885,24 @@
 
 	switch (reg) {
 	case PCI_EXP_DEVCTL:
+		advk_writel(pcie, new, PCIE_CORE_PCIEXP_CAP + reg);
+		break;
+
 	case PCI_EXP_LNKCTL:
 		advk_writel(pcie, new, PCIE_CORE_PCIEXP_CAP + reg);
+		if (new & PCI_EXP_LNKCTL_RL)
+			advk_pcie_wait_for_retrain(pcie);
 		break;
 
-	case PCI_EXP_RTCTL:
-		new = (new & PCI_EXP_RTCTL_PMEIE) << 3;
-		advk_writel(pcie, new, PCIE_ISR0_MASK_REG);
+	case PCI_EXP_RTCTL: {
+		/* Only mask/unmask PME interrupt */
+		u32 val = advk_readl(pcie, PCIE_ISR0_MASK_REG) &
+			~PCIE_MSG_PM_PME_MASK;
+		if ((new & PCI_EXP_RTCTL_PMEIE) == 0)
+			val |= PCIE_MSG_PM_PME_MASK;
+		advk_writel(pcie, val, PCIE_ISR0_MASK_REG);
 		break;
+	}
 
 	case PCI_EXP_RTSTA:
 		new = (new & PCI_EXP_RTSTA_PME) >> 9;
@@ -467,6 +915,8 @@
 }
 
 static struct pci_bridge_emul_ops advk_pci_bridge_emul_ops = {
+	.read_base = advk_pci_bridge_emul_base_conf_read,
+	.write_base = advk_pci_bridge_emul_base_conf_write,
 	.read_pcie = advk_pci_bridge_emul_pcie_conf_read,
 	.write_pcie = advk_pci_bridge_emul_pcie_conf_write,
 };
@@ -475,32 +925,39 @@
  * Initialize the configuration space of the PCI-to-PCI bridge
  * associated with the given PCIe interface.
  */
-static void advk_sw_pci_bridge_init(struct advk_pcie *pcie)
+static int advk_sw_pci_bridge_init(struct advk_pcie *pcie)
 {
 	struct pci_bridge_emul *bridge = &pcie->bridge;
 
-	bridge->conf.vendor = advk_readl(pcie, PCIE_CORE_DEV_ID_REG) & 0xffff;
-	bridge->conf.device = advk_readl(pcie, PCIE_CORE_DEV_ID_REG) >> 16;
+	bridge->conf.vendor =
+		cpu_to_le16(advk_readl(pcie, PCIE_CORE_DEV_ID_REG) & 0xffff);
+	bridge->conf.device =
+		cpu_to_le16(advk_readl(pcie, PCIE_CORE_DEV_ID_REG) >> 16);
 	bridge->conf.class_revision =
-		advk_readl(pcie, PCIE_CORE_DEV_REV_REG) & 0xff;
+		cpu_to_le32(advk_readl(pcie, PCIE_CORE_DEV_REV_REG) & 0xff);
 
 	/* Support 32 bits I/O addressing */
 	bridge->conf.iobase = PCI_IO_RANGE_TYPE_32;
 	bridge->conf.iolimit = PCI_IO_RANGE_TYPE_32;
 
 	/* Support 64 bits memory pref */
-	bridge->conf.pref_mem_base = PCI_PREF_RANGE_TYPE_64;
-	bridge->conf.pref_mem_limit = PCI_PREF_RANGE_TYPE_64;
+	bridge->conf.pref_mem_base = cpu_to_le16(PCI_PREF_RANGE_TYPE_64);
+	bridge->conf.pref_mem_limit = cpu_to_le16(PCI_PREF_RANGE_TYPE_64);
 
 	/* Support interrupt A for MSI feature */
 	bridge->conf.intpin = PCIE_CORE_INT_A_ASSERT_ENABLE;
 
+	/* Aardvark HW provides PCIe Capability structure in version 2 */
+	bridge->pcie_conf.cap = cpu_to_le16(2);
+
+	/* Indicates supports for Completion Retry Status */
+	bridge->pcie_conf.rootcap = cpu_to_le16(PCI_EXP_RTCAP_CRSVIS);
+
 	bridge->has_pcie = true;
 	bridge->data = pcie;
 	bridge->ops = &advk_pci_bridge_emul_ops;
 
-	pci_bridge_emul_init(bridge, 0);
-
+	return pci_bridge_emul_init(bridge, 0);
 }
 
 static bool advk_pcie_valid_device(struct advk_pcie *pcie, struct pci_bus *bus,
@@ -509,13 +966,51 @@
 	if ((bus->number == pcie->root_bus_nr) && PCI_SLOT(devfn) != 0)
 		return false;
 
+	/*
+	 * If the link goes down after we check for link-up, nothing bad
+	 * happens but the config access times out.
+	 */
+	if (bus->number != pcie->root_bus_nr && !advk_pcie_link_up(pcie))
+		return false;
+
 	return true;
 }
 
+static bool advk_pcie_pio_is_running(struct advk_pcie *pcie)
+{
+	struct device *dev = &pcie->pdev->dev;
+
+	/*
+	 * Trying to start a new PIO transfer when previous has not completed
+	 * cause External Abort on CPU which results in kernel panic:
+	 *
+	 *     SError Interrupt on CPU0, code 0xbf000002 -- SError
+	 *     Kernel panic - not syncing: Asynchronous SError Interrupt
+	 *
+	 * Functions advk_pcie_rd_conf() and advk_pcie_wr_conf() are protected
+	 * by raw_spin_lock_irqsave() at pci_lock_config() level to prevent
+	 * concurrent calls at the same time. But because PIO transfer may take
+	 * about 1.5s when link is down or card is disconnected, it means that
+	 * advk_pcie_wait_pio() does not always have to wait for completion.
+	 *
+	 * Some versions of ARM Trusted Firmware handles this External Abort at
+	 * EL3 level and mask it to prevent kernel panic. Relevant TF-A commit:
+	 * https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/commit/?id=3c7dcdac5c50
+	 */
+	if (advk_readl(pcie, PIO_START)) {
+		dev_err(dev, "Previous PIO read/write transfer is still running\n");
+		return true;
+	}
+
+	return false;
+}
+
 static int advk_pcie_rd_conf(struct pci_bus *bus, u32 devfn,
 			     int where, int size, u32 *val)
 {
 	struct advk_pcie *pcie = bus->sysdata;
+	int retry_count;
+	bool allow_crs;
 	u32 reg;
 	int ret;
 
@@ -528,9 +1023,17 @@
 		return pci_bridge_emul_conf_read(&pcie->bridge, where,
 						 size, val);
 
-	/* Start PIO */
-	advk_writel(pcie, 0, PIO_START);
-	advk_writel(pcie, 1, PIO_ISR);
+	/*
+	 * Completion Retry Status is possible to return only when reading all
+	 * 4 bytes from PCI_VENDOR_ID and PCI_DEVICE_ID registers at once and
+	 * CRSSVE flag on Root Bridge is enabled.
+	 */
+	allow_crs = (where == PCI_VENDOR_ID) && (size == 4) &&
+		    (le16_to_cpu(pcie->bridge.pcie_conf.rootctl) &
+		     PCI_EXP_RTCTL_CRSSVE);
+
+	if (advk_pcie_pio_is_running(pcie))
+		goto try_crs;
 
 	/* Program the control register */
 	reg = advk_readl(pcie, PIO_CTRL);
@@ -549,23 +1052,45 @@
 	/* Program the data strobe */
 	advk_writel(pcie, 0xf, PIO_WR_DATA_STRB);
 
-	/* Start the transfer */
-	advk_writel(pcie, 1, PIO_START);
+	retry_count = 0;
+	do {
+		/* Clear PIO DONE ISR and start the transfer */
+		advk_writel(pcie, 1, PIO_ISR);
+		advk_writel(pcie, 1, PIO_START);
+
+		ret = advk_pcie_wait_pio(pcie);
+		if (ret < 0)
+			goto try_crs;
+
+		retry_count += ret;
+
+		/* Check PIO status and get the read result */
+		ret = advk_pcie_check_pio_status(pcie, allow_crs, val);
+	} while (ret == -EAGAIN && retry_count < PIO_RETRY_CNT);
 
-	ret = advk_pcie_wait_pio(pcie);
 	if (ret < 0)
-		return PCIBIOS_SET_FAILED;
+		goto fail;
 
-	advk_pcie_check_pio_status(pcie);
-
-	/* Get the read result */
-	*val = advk_readl(pcie, PIO_RD_DATA);
 	if (size == 1)
 		*val = (*val >> (8 * (where & 3))) & 0xff;
 	else if (size == 2)
 		*val = (*val >> (8 * (where & 3))) & 0xffff;
 
 	return PCIBIOS_SUCCESSFUL;
+
+try_crs:
+	/*
+	 * If it is possible, return Completion Retry Status so that caller
+	 * tries to issue the request again instead of failing.
+	 */
+	if (allow_crs) {
+		*val = CFG_RD_CRS_VAL;
+		return PCIBIOS_SUCCESSFUL;
+	}
+
+fail:
+	*val = 0xffffffff;
+	return PCIBIOS_SET_FAILED;
 }
 
 static int advk_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
@@ -574,6 +1099,7 @@
 	struct advk_pcie *pcie = bus->sysdata;
 	u32 reg;
 	u32 data_strobe = 0x0;
+	int retry_count;
 	int offset;
 	int ret;
 
@@ -587,9 +1113,8 @@
 	if (where % size)
 		return PCIBIOS_SET_FAILED;
 
-	/* Start PIO */
-	advk_writel(pcie, 0, PIO_START);
-	advk_writel(pcie, 1, PIO_ISR);
+	if (advk_pcie_pio_is_running(pcie))
+		return PCIBIOS_SET_FAILED;
 
 	/* Program the control register */
 	reg = advk_readl(pcie, PIO_CTRL);
@@ -616,16 +1141,22 @@
 	/* Program the data strobe */
 	advk_writel(pcie, data_strobe, PIO_WR_DATA_STRB);
 
-	/* Start the transfer */
-	advk_writel(pcie, 1, PIO_START);
+	retry_count = 0;
+	do {
+		/* Clear PIO DONE ISR and start the transfer */
+		advk_writel(pcie, 1, PIO_ISR);
+		advk_writel(pcie, 1, PIO_START);
+
+		ret = advk_pcie_wait_pio(pcie);
+		if (ret < 0)
+			return PCIBIOS_SET_FAILED;
 
-	ret = advk_pcie_wait_pio(pcie);
-	if (ret < 0)
-		return PCIBIOS_SET_FAILED;
+		retry_count += ret;
 
-	advk_pcie_check_pio_status(pcie);
+		ret = advk_pcie_check_pio_status(pcie, false, NULL);
+	} while (ret == -EAGAIN && retry_count < PIO_RETRY_CNT);
 
-	return PCIBIOS_SUCCESSFUL;
+	return ret < 0 ? PCIBIOS_SET_FAILED : PCIBIOS_SUCCESSFUL;
 }
 
 static struct pci_ops advk_pcie_ops = {
@@ -641,7 +1172,7 @@
 
 	msg->address_lo = lower_32_bits(msi_msg);
 	msg->address_hi = upper_32_bits(msi_msg);
-	msg->data = data->irq;
+	msg->data = data->hwirq;
 }
 
 static int advk_msi_set_affinity(struct irq_data *irq_data,
@@ -658,15 +1189,11 @@
 	int hwirq, i;
 
 	mutex_lock(&pcie->msi_used_lock);
-	hwirq = bitmap_find_next_zero_area(pcie->msi_used, MSI_IRQ_NUM,
-					   0, nr_irqs, 0);
-	if (hwirq >= MSI_IRQ_NUM) {
-		mutex_unlock(&pcie->msi_used_lock);
-		return -ENOSPC;
-	}
-
-	bitmap_set(pcie->msi_used, hwirq, nr_irqs);
+	hwirq = bitmap_find_free_region(pcie->msi_used, MSI_IRQ_NUM,
+					order_base_2(nr_irqs));
 	mutex_unlock(&pcie->msi_used_lock);
+	if (hwirq < 0)
+		return -ENOSPC;
 
 	for (i = 0; i < nr_irqs; i++)
 		irq_domain_set_info(domain, virq + i, hwirq + i,
@@ -674,7 +1201,7 @@
 				    domain->host_data, handle_simple_irq,
 				    NULL, NULL);
 
-	return hwirq;
+	return 0;
 }
 
 static void advk_msi_irq_domain_free(struct irq_domain *domain,
@@ -684,7 +1211,7 @@
 	struct advk_pcie *pcie = domain->host_data;
 
 	mutex_lock(&pcie->msi_used_lock);
-	bitmap_clear(pcie->msi_used, d->hwirq, nr_irqs);
+	bitmap_release_region(pcie->msi_used, d->hwirq, order_base_2(nr_irqs));
 	mutex_unlock(&pcie->msi_used_lock);
 }
 
@@ -697,22 +1224,28 @@
 {
 	struct advk_pcie *pcie = d->domain->host_data;
 	irq_hw_number_t hwirq = irqd_to_hwirq(d);
+	unsigned long flags;
 	u32 mask;
 
+	raw_spin_lock_irqsave(&pcie->irq_lock, flags);
 	mask = advk_readl(pcie, PCIE_ISR1_MASK_REG);
 	mask |= PCIE_ISR1_INTX_ASSERT(hwirq);
 	advk_writel(pcie, mask, PCIE_ISR1_MASK_REG);
+	raw_spin_unlock_irqrestore(&pcie->irq_lock, flags);
 }
 
 static void advk_pcie_irq_unmask(struct irq_data *d)
 {
 	struct advk_pcie *pcie = d->domain->host_data;
 	irq_hw_number_t hwirq = irqd_to_hwirq(d);
+	unsigned long flags;
 	u32 mask;
 
+	raw_spin_lock_irqsave(&pcie->irq_lock, flags);
 	mask = advk_readl(pcie, PCIE_ISR1_MASK_REG);
 	mask &= ~PCIE_ISR1_INTX_ASSERT(hwirq);
 	advk_writel(pcie, mask, PCIE_ISR1_MASK_REG);
+	raw_spin_unlock_irqrestore(&pcie->irq_lock, flags);
 }
 
 static int advk_pcie_irq_map(struct irq_domain *h,
@@ -796,6 +1329,8 @@
 	struct irq_chip *irq_chip;
 	int ret = 0;
 
+	raw_spin_lock_init(&pcie->irq_lock);
+
 	pcie_intc_node =  of_get_next_child(node, NULL);
 	if (!pcie_intc_node) {
 		dev_err(dev, "No PCIe Intc node found\n");
@@ -837,19 +1372,19 @@
 static void advk_pcie_handle_msi(struct advk_pcie *pcie)
 {
 	u32 msi_val, msi_mask, msi_status, msi_idx;
-	u16 msi_data;
+	int virq;
 
 	msi_mask = advk_readl(pcie, PCIE_MSI_MASK_REG);
 	msi_val = advk_readl(pcie, PCIE_MSI_STATUS_REG);
-	msi_status = msi_val & ~msi_mask;
+	msi_status = msi_val & ((~msi_mask) & PCIE_MSI_ALL_MASK);
 
 	for (msi_idx = 0; msi_idx < MSI_IRQ_NUM; msi_idx++) {
 		if (!(BIT(msi_idx) & msi_status))
 			continue;
 
 		advk_writel(pcie, BIT(msi_idx), PCIE_MSI_STATUS_REG);
-		msi_data = advk_readl(pcie, PCIE_MSI_PAYLOAD_REG) & 0xFF;
-		generic_handle_irq(msi_data);
+		virq = irq_find_mapping(pcie->msi_inner_domain, msi_idx);
+		generic_handle_irq(virq);
 	}
 
 	advk_writel(pcie, PCIE_ISR0_MSI_INT_PENDING,
@@ -870,12 +1405,6 @@
 	isr1_mask = advk_readl(pcie, PCIE_ISR1_MASK_REG);
 	isr1_status = isr1_val & ((~isr1_mask) & PCIE_ISR1_ALL_MASK);
 
-	if (!isr0_status && !isr1_status) {
-		advk_writel(pcie, isr0_val, PCIE_ISR0_REG);
-		advk_writel(pcie, isr1_val, PCIE_ISR1_REG);
-		return;
-	}
-
 	/* Process MSI interrupts */
 	if (isr0_status & PCIE_ISR0_MSI_INT_PENDING)
 		advk_pcie_handle_msi(pcie);
@@ -968,6 +1497,7 @@
 	struct advk_pcie *pcie;
 	struct resource *res;
 	struct pci_host_bridge *bridge;
+	struct resource_entry *entry;
 	int ret, irq;
 
 	bridge = devm_pci_alloc_host_bridge(dev, sizeof(struct advk_pcie));
@@ -997,9 +1527,109 @@
 		return ret;
 	}
 
+	resource_list_for_each_entry(entry, &pcie->resources) {
+		resource_size_t start = entry->res->start;
+		resource_size_t size = resource_size(entry->res);
+		unsigned long type = resource_type(entry->res);
+		u64 win_size;
+
+		/*
+		 * Aardvark hardware allows to configure also PCIe window
+		 * for config type 0 and type 1 mapping, but driver uses
+		 * only PIO for issuing configuration transfers which does
+		 * not use PCIe window configuration.
+		 */
+		if (type != IORESOURCE_MEM && type != IORESOURCE_MEM_64 &&
+		    type != IORESOURCE_IO)
+			continue;
+
+		/*
+		 * Skip transparent memory resources. Default outbound access
+		 * configuration is set to transparent memory access so it
+		 * does not need window configuration.
+		 */
+		if ((type == IORESOURCE_MEM || type == IORESOURCE_MEM_64) &&
+		    entry->offset == 0)
+			continue;
+
+		/*
+		 * The n-th PCIe window is configured by tuple (match, remap, mask)
+		 * and an access to address A uses this window if A matches the
+		 * match with given mask.
+		 * So every PCIe window size must be a power of two and every start
+		 * address must be aligned to window size. Minimal size is 64 KiB
+		 * because lower 16 bits of mask must be zero. Remapped address
+		 * may have set only bits from the mask.
+		 */
+		while (pcie->wins_count < OB_WIN_COUNT && size > 0) {
+			/* Calculate the largest aligned window size */
+			win_size = (1ULL << (fls64(size)-1)) |
+				   (start ? (1ULL << __ffs64(start)) : 0);
+			win_size = 1ULL << __ffs64(win_size);
+			if (win_size < 0x10000)
+				break;
+
+			dev_dbg(dev,
+				"Configuring PCIe window %d: [0x%llx-0x%llx] as %lu\n",
+				pcie->wins_count, (unsigned long long)start,
+				(unsigned long long)start + win_size, type);
+
+			if (type == IORESOURCE_IO) {
+				pcie->wins[pcie->wins_count].actions = OB_WIN_TYPE_IO;
+				pcie->wins[pcie->wins_count].match = pci_pio_to_address(start);
+			} else {
+				pcie->wins[pcie->wins_count].actions = OB_WIN_TYPE_MEM;
+				pcie->wins[pcie->wins_count].match = start;
+			}
+			pcie->wins[pcie->wins_count].remap = start - entry->offset;
+			pcie->wins[pcie->wins_count].mask = ~(win_size - 1);
+
+			if (pcie->wins[pcie->wins_count].remap & (win_size - 1))
+				break;
+
+			start += win_size;
+			size -= win_size;
+			pcie->wins_count++;
+		}
+
+		if (size > 0) {
+			dev_err(&pcie->pdev->dev,
+				"Invalid PCIe region [0x%llx-0x%llx]\n",
+				(unsigned long long)entry->res->start,
+				(unsigned long long)entry->res->end + 1);
+			return -EINVAL;
+		}
+	}
+
+	pcie->reset_gpio = devm_gpiod_get_from_of_node(dev, dev->of_node,
+						       "reset-gpios", 0,
+						       GPIOD_OUT_LOW,
+						       "pcie1-reset");
+	ret = PTR_ERR_OR_ZERO(pcie->reset_gpio);
+	if (ret) {
+		if (ret == -ENOENT) {
+			pcie->reset_gpio = NULL;
+		} else {
+			if (ret != -EPROBE_DEFER)
+				dev_err(dev, "Failed to get reset-gpio: %i\n",
+					ret);
+			return ret;
+		}
+	}
+
+	ret = of_pci_get_max_link_speed(dev->of_node);
+	if (ret <= 0 || ret > 3)
+		pcie->link_gen = 3;
+	else
+		pcie->link_gen = ret;
+
 	advk_pcie_setup_hw(pcie);
 
-	advk_sw_pci_bridge_init(pcie);
+	ret = advk_sw_pci_bridge_init(pcie);
+	if (ret) {
+		dev_err(dev, "Failed to register emulated root PCI bridge\n");
+		return ret;
+	}
 
 	ret = advk_pcie_init_irq_domain(pcie);
 	if (ret) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/controller/pci-ftpci100.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/controller/pci-ftpci100.c
@@ -458,22 +458,12 @@
 	p->dev = dev;
 
 	/* Retrieve and enable optional clocks */
-	clk = devm_clk_get(dev, "PCLK");
+	clk = devm_clk_get_enabled(dev, "PCLK");
 	if (IS_ERR(clk))
 		return PTR_ERR(clk);
-	ret = clk_prepare_enable(clk);
-	if (ret) {
-		dev_err(dev, "could not prepare PCLK\n");
-		return ret;
-	}
-	p->bus_clk = devm_clk_get(dev, "PCICLK");
+	p->bus_clk = devm_clk_get_enabled(dev, "PCICLK");
 	if (IS_ERR(p->bus_clk))
 		return PTR_ERR(p->bus_clk);
-	ret = clk_prepare_enable(p->bus_clk);
-	if (ret) {
-		dev_err(dev, "could not prepare PCICLK\n");
-		return ret;
-	}
 
 	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	p->base = devm_ioremap_resource(dev, regs);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/controller/pci-hyperv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/controller/pci-hyperv.c
@@ -682,8 +682,8 @@
 		   PCI_CAPABILITY_LIST) {
 		/* ROM BARs are unimplemented */
 		*val = 0;
-	} else if (where >= PCI_INTERRUPT_LINE && where + size <=
-		   PCI_INTERRUPT_PIN) {
+	} else if ((where >= PCI_INTERRUPT_LINE && where + size <= PCI_INTERRUPT_PIN) ||
+		   (where >= PCI_INTERRUPT_PIN && where + size <= PCI_MIN_GNT)) {
 		/*
 		 * Interrupt Line and Interrupt PIN are hard-wired to zero
 		 * because this front-end only supports message-signaled
@@ -1110,6 +1110,10 @@
 		u8 buffer[sizeof(struct pci_delete_interrupt)];
 	} ctxt;
 
+	if (!int_desc->vector_count) {
+		kfree(int_desc);
+		return;
+	}
 	memset(&ctxt, 0, sizeof(ctxt));
 	int_pkt = (struct pci_delete_interrupt *)&ctxt.pkt.message;
 	int_pkt->message_type.type =
@@ -1172,6 +1176,28 @@
 	pci_msi_mask_irq(data);
 }
 
+static unsigned int hv_msi_get_int_vector(struct irq_data *data)
+{
+	struct irq_cfg *cfg = irqd_cfg(data);
+
+	return cfg->vector;
+}
+
+static int hv_msi_prepare(struct irq_domain *domain, struct device *dev,
+			  int nvec, msi_alloc_info_t *info)
+{
+	int ret = pci_msi_prepare(domain, dev, nvec, info);
+
+	/*
+	 * By using the interrupt remapper in the hypervisor IOMMU, contiguous
+	 * CPU vectors is not needed for multi-MSI
+	 */
+	if (info->type == X86_IRQ_ALLOC_TYPE_MSI)
+		info->flags &= ~X86_IRQ_ALLOC_CONTIGUOUS_VECTORS;
+
+	return ret;
+}
+
 /**
  * hv_irq_unmask() - "Unmask" the IRQ by setting its current
  * affinity.
@@ -1187,6 +1213,7 @@
 	struct msi_desc *msi_desc = irq_data_get_msi_desc(data);
 	struct irq_cfg *cfg = irqd_cfg(data);
 	struct retarget_msi_interrupt *params;
+	struct tran_int_desc *int_desc;
 	struct hv_pcibus_device *hbus;
 	struct cpumask *dest;
 	cpumask_var_t tmp;
@@ -1201,6 +1228,7 @@
 	pdev = msi_desc_to_pci_dev(msi_desc);
 	pbus = pdev->bus;
 	hbus = container_of(pbus->sysdata, struct hv_pcibus_device, sysdata);
+	int_desc = data->chip_data;
 
 	spin_lock_irqsave(&hbus->retarget_msi_interrupt_lock, flags);
 
@@ -1208,8 +1236,8 @@
 	memset(params, 0, sizeof(*params));
 	params->partition_id = HV_PARTITION_ID_SELF;
 	params->int_entry.source = 1; /* MSI(-X) */
-	params->int_entry.address = msi_desc->msg.address_lo;
-	params->int_entry.data = msi_desc->msg.data;
+	params->int_entry.address = int_desc->address & 0xffffffff;
+	params->int_entry.data = int_desc->data;
 	params->device_id = (hbus->hdev->dev_instance.b[5] << 24) |
 			   (hbus->hdev->dev_instance.b[4] << 16) |
 			   (hbus->hdev->dev_instance.b[7] << 8) |
@@ -1296,12 +1324,12 @@
 
 static u32 hv_compose_msi_req_v1(
 	struct pci_create_interrupt *int_pkt, struct cpumask *affinity,
-	u32 slot, u8 vector)
+	u32 slot, u8 vector, u8 vector_count)
 {
 	int_pkt->message_type.type = PCI_CREATE_INTERRUPT_MESSAGE;
 	int_pkt->wslot.slot = slot;
 	int_pkt->int_desc.vector = vector;
-	int_pkt->int_desc.vector_count = 1;
+	int_pkt->int_desc.vector_count = vector_count;
 	int_pkt->int_desc.delivery_mode = dest_Fixed;
 
 	/*
@@ -1315,14 +1343,14 @@
 
 static u32 hv_compose_msi_req_v2(
 	struct pci_create_interrupt2 *int_pkt, struct cpumask *affinity,
-	u32 slot, u8 vector)
+	u32 slot, u8 vector, u8 vector_count)
 {
 	int cpu;
 
 	int_pkt->message_type.type = PCI_CREATE_INTERRUPT_MESSAGE2;
 	int_pkt->wslot.slot = slot;
 	int_pkt->int_desc.vector = vector;
-	int_pkt->int_desc.vector_count = 1;
+	int_pkt->int_desc.vector_count = vector_count;
 	int_pkt->int_desc.delivery_mode = dest_Fixed;
 
 	/*
@@ -1350,7 +1378,6 @@
  */
 static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
 {
-	struct irq_cfg *cfg = irqd_cfg(data);
 	struct hv_pcibus_device *hbus;
 	struct hv_pci_dev *hpdev;
 	struct pci_bus *pbus;
@@ -1359,6 +1386,8 @@
 	unsigned long flags;
 	struct compose_comp_ctxt comp;
 	struct tran_int_desc *int_desc;
+	struct msi_desc *msi_desc;
+	u8 vector, vector_count;
 	struct {
 		struct pci_packet pci_pkt;
 		union {
@@ -1370,7 +1399,17 @@
 	u32 size;
 	int ret;
 
-	pdev = msi_desc_to_pci_dev(irq_data_get_msi_desc(data));
+	/* Reuse the previous allocation */
+	if (data->chip_data) {
+		int_desc = data->chip_data;
+		msg->address_hi = int_desc->address >> 32;
+		msg->address_lo = int_desc->address & 0xffffffff;
+		msg->data = int_desc->data;
+		return;
+	}
+
+	msi_desc  = irq_data_get_msi_desc(data);
+	pdev = msi_desc_to_pci_dev(msi_desc);
 	dest = irq_data_get_effective_affinity_mask(data);
 	pbus = pdev->bus;
 	hbus = container_of(pbus->sysdata, struct hv_pcibus_device, sysdata);
@@ -1378,17 +1417,40 @@
 	if (!hpdev)
 		goto return_null_message;
 
-	/* Free any previous message that might have already been composed. */
-	if (data->chip_data) {
-		int_desc = data->chip_data;
-		data->chip_data = NULL;
-		hv_int_desc_free(hpdev, int_desc);
-	}
-
 	int_desc = kzalloc(sizeof(*int_desc), GFP_ATOMIC);
 	if (!int_desc)
 		goto drop_reference;
 
+	if (!msi_desc->msi_attrib.is_msix && msi_desc->nvec_used > 1) {
+		/*
+		 * If this is not the first MSI of Multi MSI, we already have
+		 * a mapping.  Can exit early.
+		 */
+		if (msi_desc->irq != data->irq) {
+			data->chip_data = int_desc;
+			int_desc->address = msi_desc->msg.address_lo |
+					    (u64)msi_desc->msg.address_hi << 32;
+			int_desc->data = msi_desc->msg.data +
+					 (data->irq - msi_desc->irq);
+			msg->address_hi = msi_desc->msg.address_hi;
+			msg->address_lo = msi_desc->msg.address_lo;
+			msg->data = int_desc->data;
+			put_pcichild(hpdev);
+			return;
+		}
+		/*
+		 * The vector we select here is a dummy value.  The correct
+		 * value gets sent to the hypervisor in unmask().  This needs
+		 * to be aligned with the count, and also not zero.  Multi-msi
+		 * is powers of 2 up to 32, so 32 will always work here.
+		 */
+		vector = 32;
+		vector_count = msi_desc->nvec_used;
+	} else {
+		vector = hv_msi_get_int_vector(data);
+		vector_count = 1;
+	}
+
 	memset(&ctxt, 0, sizeof(ctxt));
 	init_completion(&comp.comp_pkt.host_event);
 	ctxt.pci_pkt.completion_func = hv_pci_compose_compl;
@@ -1399,14 +1461,16 @@
 		size = hv_compose_msi_req_v1(&ctxt.int_pkts.v1,
 					dest,
 					hpdev->desc.win_slot.slot,
-					cfg->vector);
+					vector,
+					vector_count);
 		break;
 
 	case PCI_PROTOCOL_VERSION_1_2:
 		size = hv_compose_msi_req_v2(&ctxt.int_pkts.v2,
 					dest,
 					hpdev->desc.win_slot.slot,
-					cfg->vector);
+					vector,
+					vector_count);
 		break;
 
 	default:
@@ -1518,7 +1582,7 @@
 
 static struct msi_domain_ops hv_msi_ops = {
 	.get_hwirq	= hv_msi_domain_ops_get_hwirq,
-	.msi_prepare	= pci_msi_prepare,
+	.msi_prepare	= hv_msi_prepare,
 	.set_desc	= pci_msi_set_desc,
 	.msi_free	= hv_msi_free,
 };
@@ -2675,6 +2739,24 @@
 	if (!ret)
 		ret = wait_for_response(hdev, &comp);
 
+	/*
+	 * In the case of fast device addition/removal, it's possible that
+	 * vmbus_sendpacket() or wait_for_response() returns -ENODEV but we
+	 * already got a PCI_BUS_RELATIONS* message from the host and the
+	 * channel callback already scheduled a work to hbus->wq, which can be
+	 * running pci_devices_present_work() -> survey_child_resources() ->
+	 * complete(&hbus->survey_event), even after hv_pci_query_relations()
+	 * exits and the stack variable 'comp' is no longer valid; as a result,
+	 * a hang or a page fault may happen when the complete() calls
+	 * raw_spin_lock_irqsave(). Flush hbus->wq before we exit from
+	 * hv_pci_query_relations() to avoid the issues. Note: if 'ret' is
+	 * -ENODEV, there can't be any more work item scheduled to hbus->wq
+	 * after the flush_workqueue(): see vmbus_onoffer_rescind() ->
+	 * vmbus_reset_channel_cb(), vmbus_rescind_cleanup() ->
+	 * channel->rescind = true.
+	 */
+	flush_workqueue(hbus->wq);
+
 	return ret;
 }
 
@@ -3121,6 +3203,9 @@
 
 static int __init init_hv_pci_drv(void)
 {
+	if (!hv_is_hyperv_initialized())
+		return -ENODEV;
+
 	/* Set the invalid domain number's bit, so it will not be used */
 	set_bit(HVPCI_DOM_INVALID, hvpci_dom_map);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/controller/pci-mvebu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/controller/pci-mvebu.c
@@ -105,6 +105,7 @@
 	struct mvebu_pcie_window memwin;
 	struct mvebu_pcie_window iowin;
 	u32 saved_pcie_stat;
+	struct resource regs;
 };
 
 static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
@@ -149,7 +150,9 @@
 
 /*
  * Setup PCIE BARs and Address Decode Wins:
- * BAR[0,2] -> disabled, BAR[1] -> covers all DRAM banks
+ * BAR[0] -> internal registers (needed for MSI)
+ * BAR[1] -> covers all DRAM banks
+ * BAR[2] -> Disabled
  * WIN[0-3] -> DRAM bank[0-3]
  */
 static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
@@ -203,6 +206,12 @@
 	mvebu_writel(port, 0, PCIE_BAR_HI_OFF(1));
 	mvebu_writel(port, ((size - 1) & 0xffff0000) | 1,
 		     PCIE_BAR_CTRL_OFF(1));
+
+	/*
+	 * Point BAR[0] to the device's internal registers.
+	 */
+	mvebu_writel(port, round_down(port->regs.start, SZ_1M), PCIE_BAR_LO_OFF(0));
+	mvebu_writel(port, 0, PCIE_BAR_HI_OFF(0));
 }
 
 static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
@@ -567,6 +576,8 @@
 static void mvebu_pci_bridge_emul_init(struct mvebu_pcie_port *port)
 {
 	struct pci_bridge_emul *bridge = &port->bridge;
+	u32 pcie_cap = mvebu_readl(port, PCIE_CAP_PCIEXP);
+	u8 pcie_cap_ver = ((pcie_cap >> 16) & PCI_EXP_FLAGS_VERS);
 
 	bridge->conf.vendor = PCI_VENDOR_ID_MARVELL;
 	bridge->conf.device = mvebu_readl(port, PCIE_DEV_ID_OFF) >> 16;
@@ -579,6 +590,12 @@
 		bridge->conf.iolimit = PCI_IO_RANGE_TYPE_32;
 	}
 
+	/*
+	 * Older mvebu hardware provides PCIe Capability structure only in
+	 * version 1. New hardware provides it in version 2.
+	 */
+	bridge->pcie_conf.cap = cpu_to_le16(pcie_cap_ver);
+
 	bridge->has_pcie = true;
 	bridge->data = port;
 	bridge->ops = &mvebu_pci_bridge_emul_ops;
@@ -708,14 +725,13 @@
 					      struct device_node *np,
 					      struct mvebu_pcie_port *port)
 {
-	struct resource regs;
 	int ret = 0;
 
-	ret = of_address_to_resource(np, 0, &regs);
+	ret = of_address_to_resource(np, 0, &port->regs);
 	if (ret)
 		return ERR_PTR(ret);
 
-	return devm_ioremap_resource(&pdev->dev, &regs);
+	return devm_ioremap_resource(&pdev->dev, &port->regs);
 }
 
 #define DT_FLAGS_TO_TYPE(flags)       (((flags) >> 24) & 0x03)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/controller/pci-tegra.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/controller/pci-tegra.c
@@ -181,13 +181,6 @@
 
 #define AFI_PEXBIAS_CTRL_0		0x168
 
-#define RP_PRIV_XP_DL		0x00000494
-#define  RP_PRIV_XP_DL_GEN2_UPD_FC_TSHOLD	(0x1ff << 1)
-
-#define RP_RX_HDR_LIMIT		0x00000e00
-#define  RP_RX_HDR_LIMIT_PW_MASK	(0xff << 8)
-#define  RP_RX_HDR_LIMIT_PW		(0x0e << 8)
-
 #define RP_ECTL_2_R1	0x00000e84
 #define  RP_ECTL_2_R1_RX_CTLE_1C_MASK		0xffff
 
@@ -323,7 +316,6 @@
 	bool program_uphy;
 	bool update_clamp_threshold;
 	bool program_deskew_time;
-	bool raw_violation_fixup;
 	bool update_fc_timer;
 	bool has_cache_bars;
 	struct {
@@ -669,23 +661,6 @@
 		writel(value, port->base + RP_VEND_CTL0);
 	}
 
-	/* Fixup for read after write violation. */
-	if (soc->raw_violation_fixup) {
-		value = readl(port->base + RP_RX_HDR_LIMIT);
-		value &= ~RP_RX_HDR_LIMIT_PW_MASK;
-		value |= RP_RX_HDR_LIMIT_PW;
-		writel(value, port->base + RP_RX_HDR_LIMIT);
-
-		value = readl(port->base + RP_PRIV_XP_DL);
-		value |= RP_PRIV_XP_DL_GEN2_UPD_FC_TSHOLD;
-		writel(value, port->base + RP_PRIV_XP_DL);
-
-		value = readl(port->base + RP_VEND_XP);
-		value &= ~RP_VEND_XP_UPDATE_FC_THRESHOLD_MASK;
-		value |= soc->update_fc_threshold;
-		writel(value, port->base + RP_VEND_XP);
-	}
-
 	if (soc->update_fc_timer) {
 		value = readl(port->base + RP_VEND_XP);
 		value &= ~RP_VEND_XP_UPDATE_FC_THRESHOLD_MASK;
@@ -2292,13 +2267,15 @@
 		rp->np = port;
 
 		rp->base = devm_pci_remap_cfg_resource(dev, &rp->regs);
-		if (IS_ERR(rp->base))
-			return PTR_ERR(rp->base);
+		if (IS_ERR(rp->base)) {
+			err = PTR_ERR(rp->base);
+			goto err_node_put;
+		}
 
 		label = devm_kasprintf(dev, GFP_KERNEL, "pex-reset-%u", index);
 		if (!label) {
-			dev_err(dev, "failed to create reset GPIO label\n");
-			return -ENOMEM;
+			err = -ENOMEM;
+			goto err_node_put;
 		}
 
 		/*
@@ -2314,9 +2291,10 @@
 			if (PTR_ERR(rp->reset_gpio) == -ENOENT) {
 				rp->reset_gpio = NULL;
 			} else {
-				dev_err(dev, "failed to get reset GPIO: %d\n",
-					err);
-				return PTR_ERR(rp->reset_gpio);
+				dev_err(dev, "failed to get reset GPIO: %ld\n",
+					PTR_ERR(rp->reset_gpio));
+				err = PTR_ERR(rp->reset_gpio);
+				goto err_node_put;
 			}
 		}
 
@@ -2499,7 +2477,6 @@
 	.num_ports = 2,
 	.ports = tegra20_pcie_ports,
 	.msi_base_shift = 0,
-	.afi_pex2_ctrl = 0x128,
 	.pads_pll_ctl = PADS_PLL_CTL_TEGRA20,
 	.tx_ref_sel = PADS_PLL_CTL_TXCLKREF_DIV10,
 	.pads_refclk_cfg0 = 0xfa5cfa5c,
@@ -2512,7 +2489,6 @@
 	.program_uphy = true,
 	.update_clamp_threshold = false,
 	.program_deskew_time = false,
-	.raw_violation_fixup = false,
 	.update_fc_timer = false,
 	.has_cache_bars = true,
 	.ectl.enable = false,
@@ -2528,6 +2504,7 @@
 	.num_ports = 3,
 	.ports = tegra30_pcie_ports,
 	.msi_base_shift = 8,
+	.afi_pex2_ctrl = 0x128,
 	.pads_pll_ctl = PADS_PLL_CTL_TEGRA30,
 	.tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN,
 	.pads_refclk_cfg0 = 0xfa5cfa5c,
@@ -2541,7 +2518,6 @@
 	.program_uphy = true,
 	.update_clamp_threshold = false,
 	.program_deskew_time = false,
-	.raw_violation_fixup = false,
 	.update_fc_timer = false,
 	.has_cache_bars = false,
 	.ectl.enable = false,
@@ -2554,8 +2530,6 @@
 	.pads_pll_ctl = PADS_PLL_CTL_TEGRA30,
 	.tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN,
 	.pads_refclk_cfg0 = 0x44ac44ac,
-	/* FC threshold is bit[25:18] */
-	.update_fc_threshold = 0x03fc0000,
 	.has_pex_clkreq_en = true,
 	.has_pex_bias_ctrl = true,
 	.has_intr_prsnt_sense = true,
@@ -2565,7 +2539,6 @@
 	.program_uphy = true,
 	.update_clamp_threshold = true,
 	.program_deskew_time = false,
-	.raw_violation_fixup = true,
 	.update_fc_timer = false,
 	.has_cache_bars = false,
 	.ectl.enable = false,
@@ -2589,7 +2562,6 @@
 	.program_uphy = true,
 	.update_clamp_threshold = true,
 	.program_deskew_time = true,
-	.raw_violation_fixup = false,
 	.update_fc_timer = true,
 	.has_cache_bars = false,
 	.ectl = {
@@ -2631,7 +2603,6 @@
 	.program_uphy = false,
 	.update_clamp_threshold = false,
 	.program_deskew_time = false,
-	.raw_violation_fixup = false,
 	.update_fc_timer = false,
 	.has_cache_bars = false,
 	.ectl.enable = false,
@@ -2645,6 +2616,7 @@
 	{ .compatible = "nvidia,tegra20-pcie", .data = &tegra20_pcie },
 	{ },
 };
+MODULE_DEVICE_TABLE(of, tegra_pcie_of_match);
 
 static void *tegra_pcie_ports_seq_start(struct seq_file *s, loff_t *pos)
 {
@@ -2798,9 +2770,9 @@
 
 	pm_runtime_enable(pcie->dev);
 	err = pm_runtime_get_sync(pcie->dev);
-	if (err) {
+	if (err < 0) {
 		dev_err(dev, "fail to enable pcie controller: %d\n", err);
-		goto teardown_msi;
+		goto pm_runtime_put;
 	}
 
 	err = tegra_pcie_request_resources(pcie);
@@ -2840,7 +2812,6 @@
 pm_runtime_put:
 	pm_runtime_put_sync(pcie->dev);
 	pm_runtime_disable(pcie->dev);
-teardown_msi:
 	tegra_pcie_msi_teardown(pcie);
 put_resources:
 	tegra_pcie_put_resources(pcie);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/controller/pci-thunder-ecam.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/controller/pci-thunder-ecam.c
@@ -116,7 +116,7 @@
 	 * the config space access window.  Since we are working with
 	 * the high-order 32 bits, shift everything down by 32 bits.
 	 */
-	node_bits = (cfg->res.start >> 32) & (1 << 12);
+	node_bits = upper_32_bits(cfg->res.start) & (1 << 12);
 
 	v |= node_bits;
 	set_val(v, where, size, val);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/controller/pci-thunder-pem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/controller/pci-thunder-pem.c
@@ -11,6 +11,7 @@
 #include <linux/pci-acpi.h>
 #include <linux/pci-ecam.h>
 #include <linux/platform_device.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
 #include "../pci.h"
 
 #if defined(CONFIG_PCI_HOST_THUNDER_PEM) || (defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS))
@@ -314,9 +315,9 @@
 	 * structure here for the BAR.
 	 */
 	bar4_start = res_pem->start + 0xf00000;
-	pem_pci->ea_entry[0] = (u32)bar4_start | 2;
-	pem_pci->ea_entry[1] = (u32)(res_pem->end - bar4_start) & ~3u;
-	pem_pci->ea_entry[2] = (u32)(bar4_start >> 32);
+	pem_pci->ea_entry[0] = lower_32_bits(bar4_start) | 2;
+	pem_pci->ea_entry[1] = lower_32_bits(res_pem->end - bar4_start) & ~3u;
+	pem_pci->ea_entry[2] = upper_32_bits(bar4_start);
 
 	cfg->priv = pem_pci;
 	return 0;
@@ -324,9 +325,9 @@
 
 #if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)
 
-#define PEM_RES_BASE		0x87e0c0000000UL
-#define PEM_NODE_MASK		GENMASK(45, 44)
-#define PEM_INDX_MASK		GENMASK(26, 24)
+#define PEM_RES_BASE		0x87e0c0000000ULL
+#define PEM_NODE_MASK		GENMASK_ULL(45, 44)
+#define PEM_INDX_MASK		GENMASK_ULL(26, 24)
 #define PEM_MIN_DOM_IN_NODE	4
 #define PEM_MAX_DOM_IN_NODE	10
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/controller/pci-v3-semi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/controller/pci-v3-semi.c
@@ -743,7 +743,7 @@
 	int ret;
 	LIST_HEAD(res);
 
-	host = pci_alloc_host_bridge(sizeof(*v3));
+	host = devm_pci_alloc_host_bridge(dev, sizeof(*v3));
 	if (!host)
 		return -ENOMEM;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/controller/pci-xgene-msi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/controller/pci-xgene-msi.c
@@ -384,13 +384,9 @@
 		if (!msi_group->gic_irq)
 			continue;
 
-		irq_set_chained_handler(msi_group->gic_irq,
-					xgene_msi_isr);
-		err = irq_set_handler_data(msi_group->gic_irq, msi_group);
-		if (err) {
-			pr_err("failed to register GIC IRQ handler\n");
-			return -EINVAL;
-		}
+		irq_set_chained_handler_and_data(msi_group->gic_irq,
+			xgene_msi_isr, msi_group);
+
 		/*
 		 * Statically allocate MSI GIC IRQs to each CPU core.
 		 * With 8-core X-Gene v1, 2 MSI GIC IRQs are allocated
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/controller/pcie-cadence-ep.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/controller/pcie-cadence-ep.c
@@ -178,8 +178,7 @@
 	struct cdns_pcie *pcie = &ep->pcie;
 	u32 r;
 
-	r = find_first_zero_bit(&ep->ob_region_map,
-				sizeof(ep->ob_region_map) * BITS_PER_LONG);
+	r = find_first_zero_bit(&ep->ob_region_map, BITS_PER_LONG);
 	if (r >= ep->max_regions - 1) {
 		dev_err(&epc->dev, "no free outbound region\n");
 		return -EINVAL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/controller/pcie-cadence-host.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/controller/pcie-cadence-host.c
@@ -102,6 +102,7 @@
 {
 	struct cdns_pcie *pcie = &rc->pcie;
 	u32 value, ctrl;
+	u32 id;
 
 	/*
 	 * Set the root complex BAR configuration register:
@@ -121,8 +122,12 @@
 	cdns_pcie_writel(pcie, CDNS_PCIE_LM_RC_BAR_CFG, value);
 
 	/* Set root port configuration space */
-	if (rc->vendor_id != 0xffff)
-		cdns_pcie_rp_writew(pcie, PCI_VENDOR_ID, rc->vendor_id);
+	if (rc->vendor_id != 0xffff) {
+		id = CDNS_PCIE_LM_ID_VENDOR(rc->vendor_id) |
+			CDNS_PCIE_LM_ID_SUBSYS(rc->vendor_id);
+		cdns_pcie_writel(pcie, CDNS_PCIE_LM_ID, id);
+	}
+
 	if (rc->device_id != 0xffff)
 		cdns_pcie_rp_writew(pcie, PCI_DEVICE_ID, rc->device_id);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/controller/pcie-iproc-msi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/controller/pcie-iproc-msi.c
@@ -171,7 +171,7 @@
 
 static struct msi_domain_info iproc_msi_domain_info = {
 	.flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
-		MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX,
+		MSI_FLAG_PCI_MSIX,
 	.chip = &iproc_msi_irq_chip,
 };
 
@@ -209,15 +209,20 @@
 	struct iproc_msi *msi = irq_data_get_irq_chip_data(data);
 	int target_cpu = cpumask_first(mask);
 	int curr_cpu;
+	int ret;
 
 	curr_cpu = hwirq_to_cpu(msi, data->hwirq);
 	if (curr_cpu == target_cpu)
-		return IRQ_SET_MASK_OK_DONE;
+		ret = IRQ_SET_MASK_OK_DONE;
+	else {
+		/* steer MSI to the target CPU */
+		data->hwirq = hwirq_to_canonical_hwirq(msi, data->hwirq) + target_cpu;
+		ret = IRQ_SET_MASK_OK;
+	}
 
-	/* steer MSI to the target CPU */
-	data->hwirq = hwirq_to_canonical_hwirq(msi, data->hwirq) + target_cpu;
+	irq_data_update_effective_affinity(data, cpumask_of(target_cpu));
 
-	return IRQ_SET_MASK_OK;
+	return ret;
 }
 
 static void iproc_msi_irq_compose_msi_msg(struct irq_data *data,
@@ -245,20 +250,23 @@
 	struct iproc_msi *msi = domain->host_data;
 	int hwirq, i;
 
+	if (msi->nr_cpus > 1 && nr_irqs > 1)
+		return -EINVAL;
+
 	mutex_lock(&msi->bitmap_lock);
 
-	/* Allocate 'nr_cpus' number of MSI vectors each time */
-	hwirq = bitmap_find_next_zero_area(msi->bitmap, msi->nr_msi_vecs, 0,
-					   msi->nr_cpus, 0);
-	if (hwirq < msi->nr_msi_vecs) {
-		bitmap_set(msi->bitmap, hwirq, msi->nr_cpus);
-	} else {
-		mutex_unlock(&msi->bitmap_lock);
-		return -ENOSPC;
-	}
+	/*
+	 * Allocate 'nr_irqs' multiplied by 'nr_cpus' number of MSI vectors
+	 * each time
+	 */
+	hwirq = bitmap_find_free_region(msi->bitmap, msi->nr_msi_vecs,
+					order_base_2(msi->nr_cpus * nr_irqs));
 
 	mutex_unlock(&msi->bitmap_lock);
 
+	if (hwirq < 0)
+		return -ENOSPC;
+
 	for (i = 0; i < nr_irqs; i++) {
 		irq_domain_set_info(domain, virq + i, hwirq + i,
 				    &iproc_msi_bottom_irq_chip,
@@ -266,7 +274,7 @@
 				    NULL, NULL);
 	}
 
-	return hwirq;
+	return 0;
 }
 
 static void iproc_msi_irq_domain_free(struct irq_domain *domain,
@@ -279,7 +287,8 @@
 	mutex_lock(&msi->bitmap_lock);
 
 	hwirq = hwirq_to_canonical_hwirq(msi, data->hwirq);
-	bitmap_clear(msi->bitmap, hwirq, msi->nr_cpus);
+	bitmap_release_region(msi->bitmap, hwirq,
+			      order_base_2(msi->nr_cpus * nr_irqs));
 
 	mutex_unlock(&msi->bitmap_lock);
 
@@ -533,6 +542,9 @@
 	mutex_init(&msi->bitmap_lock);
 	msi->nr_cpus = num_possible_cpus();
 
+	if (msi->nr_cpus == 1)
+		iproc_msi_domain_info.flags |=  MSI_FLAG_MULTI_PCI_MSI;
+
 	msi->nr_irqs = of_irq_count(node);
 	if (!msi->nr_irqs) {
 		dev_err(pcie->dev, "found no MSI GIC interrupt\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/controller/pcie-iproc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/controller/pcie-iproc.c
@@ -307,7 +307,7 @@
 };
 
 /* iProc PCIe PAXB BCMA registers */
-static const u16 iproc_pcie_reg_paxb_bcma[] = {
+static const u16 iproc_pcie_reg_paxb_bcma[IPROC_PCIE_MAX_NUM_REG] = {
 	[IPROC_PCIE_CLK_CTRL]		= 0x000,
 	[IPROC_PCIE_CFG_IND_ADDR]	= 0x120,
 	[IPROC_PCIE_CFG_IND_DATA]	= 0x124,
@@ -318,7 +318,7 @@
 };
 
 /* iProc PCIe PAXB registers */
-static const u16 iproc_pcie_reg_paxb[] = {
+static const u16 iproc_pcie_reg_paxb[IPROC_PCIE_MAX_NUM_REG] = {
 	[IPROC_PCIE_CLK_CTRL]		= 0x000,
 	[IPROC_PCIE_CFG_IND_ADDR]	= 0x120,
 	[IPROC_PCIE_CFG_IND_DATA]	= 0x124,
@@ -334,7 +334,7 @@
 };
 
 /* iProc PCIe PAXB v2 registers */
-static const u16 iproc_pcie_reg_paxb_v2[] = {
+static const u16 iproc_pcie_reg_paxb_v2[IPROC_PCIE_MAX_NUM_REG] = {
 	[IPROC_PCIE_CLK_CTRL]		= 0x000,
 	[IPROC_PCIE_CFG_IND_ADDR]	= 0x120,
 	[IPROC_PCIE_CFG_IND_DATA]	= 0x124,
@@ -363,7 +363,7 @@
 };
 
 /* iProc PCIe PAXC v1 registers */
-static const u16 iproc_pcie_reg_paxc[] = {
+static const u16 iproc_pcie_reg_paxc[IPROC_PCIE_MAX_NUM_REG] = {
 	[IPROC_PCIE_CLK_CTRL]		= 0x000,
 	[IPROC_PCIE_CFG_IND_ADDR]	= 0x1f0,
 	[IPROC_PCIE_CFG_IND_DATA]	= 0x1f4,
@@ -372,7 +372,7 @@
 };
 
 /* iProc PCIe PAXC v2 registers */
-static const u16 iproc_pcie_reg_paxc_v2[] = {
+static const u16 iproc_pcie_reg_paxc_v2[IPROC_PCIE_MAX_NUM_REG] = {
 	[IPROC_PCIE_MSI_GIC_MODE]	= 0x050,
 	[IPROC_PCIE_MSI_BASE_ADDR]	= 0x074,
 	[IPROC_PCIE_MSI_WINDOW_SIZE]	= 0x078,
@@ -1608,6 +1608,30 @@
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0xd804,
 			quirk_paxc_disable_msi_parsing);
 
+static void quirk_paxc_bridge(struct pci_dev *pdev)
+{
+	/*
+	 * The PCI config space is shared with the PAXC root port and the first
+	 * Ethernet device.  So, we need to workaround this by telling the PCI
+	 * code that the bridge is not an Ethernet device.
+	 */
+	if (pdev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
+		pdev->class = PCI_CLASS_BRIDGE_PCI << 8;
+
+	/*
+	 * MPSS is not being set properly (as it is currently 0).  This is
+	 * because that area of the PCI config space is hard coded to zero, and
+	 * is not modifiable by firmware.  Set this to 2 (e.g., 512 byte MPS)
+	 * so that the MPS can be set to the real max value.
+	 */
+	pdev->pcie_mpss = 2;
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0x16cd, quirk_paxc_bridge);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0x16f0, quirk_paxc_bridge);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0xd750, quirk_paxc_bridge);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0xd802, quirk_paxc_bridge);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0xd804, quirk_paxc_bridge);
+
 MODULE_AUTHOR("Ray Jui <rjui@broadcom.com>");
 MODULE_DESCRIPTION("Broadcom iPROC PCIe common driver");
 MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/controller/pcie-mediatek.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/controller/pcie-mediatek.c
@@ -623,14 +623,20 @@
 		if (status & MSI_STATUS){
 			unsigned long imsi_status;
 
+			/*
+			 * The interrupt status can be cleared even if the
+			 * MSI status remains pending. As such, given the
+			 * edge-triggered interrupt type, its status should
+			 * be cleared before being dispatched to the
+			 * handler of the underlying device.
+			 */
+			writel(MSI_STATUS, port->base + PCIE_INT_STATUS);
 			while ((imsi_status = readl(port->base + PCIE_IMSI_STATUS))) {
 				for_each_set_bit(bit, &imsi_status, MTK_MSI_IRQS_NUM) {
 					virq = irq_find_mapping(port->inner_domain, bit);
 					generic_handle_irq(virq);
 				}
 			}
-			/* Clear MSI interrupt status */
-			writel(MSI_STATUS, port->base + PCIE_INT_STATUS);
 		}
 	}
 
@@ -1063,14 +1069,14 @@
 		err = of_pci_get_devfn(child);
 		if (err < 0) {
 			dev_err(dev, "failed to parse devfn: %d\n", err);
-			return err;
+			goto error_put_node;
 		}
 
 		slot = PCI_SLOT(err);
 
 		err = mtk_pcie_parse_port(pcie, child, slot);
 		if (err)
-			return err;
+			goto error_put_node;
 	}
 
 	err = mtk_pcie_subsys_powerup(pcie);
@@ -1086,6 +1092,9 @@
 		mtk_pcie_subsys_powerdown(pcie);
 
 	return 0;
+error_put_node:
+	of_node_put(child);
+	return err;
 }
 
 static int mtk_pcie_probe(struct platform_device *pdev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/controller/pcie-mobiveil.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/controller/pcie-mobiveil.c
@@ -235,7 +235,7 @@
 	return PCIBIOS_SUCCESSFUL;
 }
 
-static u32 csr_read(struct mobiveil_pcie *pcie, u32 off, size_t size)
+static u32 mobiveil_csr_read(struct mobiveil_pcie *pcie, u32 off, size_t size)
 {
 	void *addr;
 	u32 val;
@@ -250,7 +250,8 @@
 	return val;
 }
 
-static void csr_write(struct mobiveil_pcie *pcie, u32 val, u32 off, size_t size)
+static void mobiveil_csr_write(struct mobiveil_pcie *pcie, u32 val, u32 off,
+			       size_t size)
 {
 	void *addr;
 	int ret;
@@ -262,19 +263,19 @@
 		dev_err(&pcie->pdev->dev, "write CSR address failed\n");
 }
 
-static u32 csr_readl(struct mobiveil_pcie *pcie, u32 off)
+static u32 mobiveil_csr_readl(struct mobiveil_pcie *pcie, u32 off)
 {
-	return csr_read(pcie, off, 0x4);
+	return mobiveil_csr_read(pcie, off, 0x4);
 }
 
-static void csr_writel(struct mobiveil_pcie *pcie, u32 val, u32 off)
+static void mobiveil_csr_writel(struct mobiveil_pcie *pcie, u32 val, u32 off)
 {
-	csr_write(pcie, val, off, 0x4);
+	mobiveil_csr_write(pcie, val, off, 0x4);
 }
 
 static bool mobiveil_pcie_link_up(struct mobiveil_pcie *pcie)
 {
-	return (csr_readl(pcie, LTSSM_STATUS) &
+	return (mobiveil_csr_readl(pcie, LTSSM_STATUS) &
 		LTSSM_STATUS_L0_MASK) == LTSSM_STATUS_L0;
 }
 
@@ -323,7 +324,7 @@
 		PCI_SLOT(devfn) << PAB_DEVICE_SHIFT |
 		PCI_FUNC(devfn) << PAB_FUNCTION_SHIFT;
 
-	csr_writel(pcie, value, PAB_AXI_AMAP_PEX_WIN_L(WIN_NUM_0));
+	mobiveil_csr_writel(pcie, value, PAB_AXI_AMAP_PEX_WIN_L(WIN_NUM_0));
 
 	return pcie->config_axi_slave_base + where;
 }
@@ -353,13 +354,14 @@
 	chained_irq_enter(chip, desc);
 
 	/* read INTx status */
-	val = csr_readl(pcie, PAB_INTP_AMBA_MISC_STAT);
-	mask = csr_readl(pcie, PAB_INTP_AMBA_MISC_ENB);
+	val = mobiveil_csr_readl(pcie, PAB_INTP_AMBA_MISC_STAT);
+	mask = mobiveil_csr_readl(pcie, PAB_INTP_AMBA_MISC_ENB);
 	intr_status = val & mask;
 
 	/* Handle INTx */
 	if (intr_status & PAB_INTP_INTX_MASK) {
-		shifted_status = csr_readl(pcie, PAB_INTP_AMBA_MISC_STAT);
+		shifted_status = mobiveil_csr_readl(pcie,
+						    PAB_INTP_AMBA_MISC_STAT);
 		shifted_status &= PAB_INTP_INTX_MASK;
 		shifted_status >>= PAB_INTX_START;
 		do {
@@ -373,12 +375,13 @@
 							    bit);
 
 				/* clear interrupt handled */
-				csr_writel(pcie, 1 << (PAB_INTX_START + bit),
-					   PAB_INTP_AMBA_MISC_STAT);
+				mobiveil_csr_writel(pcie,
+						    1 << (PAB_INTX_START + bit),
+						    PAB_INTP_AMBA_MISC_STAT);
 			}
 
-			shifted_status = csr_readl(pcie,
-						   PAB_INTP_AMBA_MISC_STAT);
+			shifted_status = mobiveil_csr_readl(pcie,
+							    PAB_INTP_AMBA_MISC_STAT);
 			shifted_status &= PAB_INTP_INTX_MASK;
 			shifted_status >>= PAB_INTX_START;
 		} while (shifted_status != 0);
@@ -413,7 +416,7 @@
 	}
 
 	/* Clear the interrupt status */
-	csr_writel(pcie, intr_status, PAB_INTP_AMBA_MISC_STAT);
+	mobiveil_csr_writel(pcie, intr_status, PAB_INTP_AMBA_MISC_STAT);
 	chained_irq_exit(chip, desc);
 }
 
@@ -474,24 +477,24 @@
 		return;
 	}
 
-	value = csr_readl(pcie, PAB_PEX_AMAP_CTRL(win_num));
+	value = mobiveil_csr_readl(pcie, PAB_PEX_AMAP_CTRL(win_num));
 	value &= ~(AMAP_CTRL_TYPE_MASK << AMAP_CTRL_TYPE_SHIFT | WIN_SIZE_MASK);
 	value |= type << AMAP_CTRL_TYPE_SHIFT | 1 << AMAP_CTRL_EN_SHIFT |
 		 (lower_32_bits(size64) & WIN_SIZE_MASK);
-	csr_writel(pcie, value, PAB_PEX_AMAP_CTRL(win_num));
+	mobiveil_csr_writel(pcie, value, PAB_PEX_AMAP_CTRL(win_num));
 
-	csr_writel(pcie, upper_32_bits(size64),
-		   PAB_EXT_PEX_AMAP_SIZEN(win_num));
+	mobiveil_csr_writel(pcie, upper_32_bits(size64),
+			    PAB_EXT_PEX_AMAP_SIZEN(win_num));
 
-	csr_writel(pcie, lower_32_bits(cpu_addr),
-		   PAB_PEX_AMAP_AXI_WIN(win_num));
-	csr_writel(pcie, upper_32_bits(cpu_addr),
-		   PAB_EXT_PEX_AMAP_AXI_WIN(win_num));
-
-	csr_writel(pcie, lower_32_bits(pci_addr),
-		   PAB_PEX_AMAP_PEX_WIN_L(win_num));
-	csr_writel(pcie, upper_32_bits(pci_addr),
-		   PAB_PEX_AMAP_PEX_WIN_H(win_num));
+	mobiveil_csr_writel(pcie, lower_32_bits(cpu_addr),
+			    PAB_PEX_AMAP_AXI_WIN(win_num));
+	mobiveil_csr_writel(pcie, upper_32_bits(cpu_addr),
+			    PAB_EXT_PEX_AMAP_AXI_WIN(win_num));
+
+	mobiveil_csr_writel(pcie, lower_32_bits(pci_addr),
+			    PAB_PEX_AMAP_PEX_WIN_L(win_num));
+	mobiveil_csr_writel(pcie, upper_32_bits(pci_addr),
+			    PAB_PEX_AMAP_PEX_WIN_H(win_num));
 
 	pcie->ib_wins_configured++;
 }
@@ -515,27 +518,29 @@
 	 * program Enable Bit to 1, Type Bit to (00) base 2, AXI Window Size Bit
 	 * to 4 KB in PAB_AXI_AMAP_CTRL register
 	 */
-	value = csr_readl(pcie, PAB_AXI_AMAP_CTRL(win_num));
+	value = mobiveil_csr_readl(pcie, PAB_AXI_AMAP_CTRL(win_num));
 	value &= ~(WIN_TYPE_MASK << WIN_TYPE_SHIFT | WIN_SIZE_MASK);
 	value |= 1 << WIN_ENABLE_SHIFT | type << WIN_TYPE_SHIFT |
 		 (lower_32_bits(size64) & WIN_SIZE_MASK);
-	csr_writel(pcie, value, PAB_AXI_AMAP_CTRL(win_num));
+	mobiveil_csr_writel(pcie, value, PAB_AXI_AMAP_CTRL(win_num));
 
-	csr_writel(pcie, upper_32_bits(size64), PAB_EXT_AXI_AMAP_SIZE(win_num));
+	mobiveil_csr_writel(pcie, upper_32_bits(size64),
+			    PAB_EXT_AXI_AMAP_SIZE(win_num));
 
 	/*
 	 * program AXI window base with appropriate value in
 	 * PAB_AXI_AMAP_AXI_WIN0 register
 	 */
-	csr_writel(pcie, lower_32_bits(cpu_addr) & (~AXI_WINDOW_ALIGN_MASK),
-		   PAB_AXI_AMAP_AXI_WIN(win_num));
-	csr_writel(pcie, upper_32_bits(cpu_addr),
-		   PAB_EXT_AXI_AMAP_AXI_WIN(win_num));
-
-	csr_writel(pcie, lower_32_bits(pci_addr),
-		   PAB_AXI_AMAP_PEX_WIN_L(win_num));
-	csr_writel(pcie, upper_32_bits(pci_addr),
-		   PAB_AXI_AMAP_PEX_WIN_H(win_num));
+	mobiveil_csr_writel(pcie,
+			    lower_32_bits(cpu_addr) & (~AXI_WINDOW_ALIGN_MASK),
+			    PAB_AXI_AMAP_AXI_WIN(win_num));
+	mobiveil_csr_writel(pcie, upper_32_bits(cpu_addr),
+			    PAB_EXT_AXI_AMAP_AXI_WIN(win_num));
+
+	mobiveil_csr_writel(pcie, lower_32_bits(pci_addr),
+			    PAB_AXI_AMAP_PEX_WIN_L(win_num));
+	mobiveil_csr_writel(pcie, upper_32_bits(pci_addr),
+			    PAB_AXI_AMAP_PEX_WIN_H(win_num));
 
 	pcie->ob_wins_configured++;
 }
@@ -579,42 +584,42 @@
 	struct resource_entry *win;
 
 	/* setup bus numbers */
-	value = csr_readl(pcie, PCI_PRIMARY_BUS);
+	value = mobiveil_csr_readl(pcie, PCI_PRIMARY_BUS);
 	value &= 0xff000000;
 	value |= 0x00ff0100;
-	csr_writel(pcie, value, PCI_PRIMARY_BUS);
+	mobiveil_csr_writel(pcie, value, PCI_PRIMARY_BUS);
 
 	/*
 	 * program Bus Master Enable Bit in Command Register in PAB Config
 	 * Space
 	 */
-	value = csr_readl(pcie, PCI_COMMAND);
+	value = mobiveil_csr_readl(pcie, PCI_COMMAND);
 	value |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
-	csr_writel(pcie, value, PCI_COMMAND);
+	mobiveil_csr_writel(pcie, value, PCI_COMMAND);
 
 	/*
 	 * program PIO Enable Bit to 1 (and PEX PIO Enable to 1) in PAB_CTRL
 	 * register
 	 */
-	pab_ctrl = csr_readl(pcie, PAB_CTRL);
+	pab_ctrl = mobiveil_csr_readl(pcie, PAB_CTRL);
 	pab_ctrl |= (1 << AMBA_PIO_ENABLE_SHIFT) | (1 << PEX_PIO_ENABLE_SHIFT);
-	csr_writel(pcie, pab_ctrl, PAB_CTRL);
+	mobiveil_csr_writel(pcie, pab_ctrl, PAB_CTRL);
 
-	csr_writel(pcie, (PAB_INTP_INTX_MASK | PAB_INTP_MSI_MASK),
-		   PAB_INTP_AMBA_MISC_ENB);
+	mobiveil_csr_writel(pcie, (PAB_INTP_INTX_MASK | PAB_INTP_MSI_MASK),
+			    PAB_INTP_AMBA_MISC_ENB);
 
 	/*
 	 * program PIO Enable Bit to 1 and Config Window Enable Bit to 1 in
 	 * PAB_AXI_PIO_CTRL Register
 	 */
-	value = csr_readl(pcie, PAB_AXI_PIO_CTRL);
+	value = mobiveil_csr_readl(pcie, PAB_AXI_PIO_CTRL);
 	value |= APIO_EN_MASK;
-	csr_writel(pcie, value, PAB_AXI_PIO_CTRL);
+	mobiveil_csr_writel(pcie, value, PAB_AXI_PIO_CTRL);
 
 	/* Enable PCIe PIO master */
-	value = csr_readl(pcie, PAB_PEX_PIO_CTRL);
+	value = mobiveil_csr_readl(pcie, PAB_PEX_PIO_CTRL);
 	value |= 1 << PIO_ENABLE_SHIFT;
-	csr_writel(pcie, value, PAB_PEX_PIO_CTRL);
+	mobiveil_csr_writel(pcie, value, PAB_PEX_PIO_CTRL);
 
 	/*
 	 * we'll program one outbound window for config reads and
@@ -647,10 +652,10 @@
 	}
 
 	/* fixup for PCIe class register */
-	value = csr_readl(pcie, PAB_INTP_AXI_PIO_CLASS);
+	value = mobiveil_csr_readl(pcie, PAB_INTP_AXI_PIO_CLASS);
 	value &= 0xff;
 	value |= (PCI_CLASS_BRIDGE_PCI << 16);
-	csr_writel(pcie, value, PAB_INTP_AXI_PIO_CLASS);
+	mobiveil_csr_writel(pcie, value, PAB_INTP_AXI_PIO_CLASS);
 
 	/* setup MSI hardware registers */
 	mobiveil_pcie_enable_msi(pcie);
@@ -668,9 +673,9 @@
 	pcie = irq_desc_get_chip_data(desc);
 	mask = 1 << ((data->hwirq + PAB_INTX_START) - 1);
 	raw_spin_lock_irqsave(&pcie->intx_mask_lock, flags);
-	shifted_val = csr_readl(pcie, PAB_INTP_AMBA_MISC_ENB);
+	shifted_val = mobiveil_csr_readl(pcie, PAB_INTP_AMBA_MISC_ENB);
 	shifted_val &= ~mask;
-	csr_writel(pcie, shifted_val, PAB_INTP_AMBA_MISC_ENB);
+	mobiveil_csr_writel(pcie, shifted_val, PAB_INTP_AMBA_MISC_ENB);
 	raw_spin_unlock_irqrestore(&pcie->intx_mask_lock, flags);
 }
 
@@ -684,9 +689,9 @@
 	pcie = irq_desc_get_chip_data(desc);
 	mask = 1 << ((data->hwirq + PAB_INTX_START) - 1);
 	raw_spin_lock_irqsave(&pcie->intx_mask_lock, flags);
-	shifted_val = csr_readl(pcie, PAB_INTP_AMBA_MISC_ENB);
+	shifted_val = mobiveil_csr_readl(pcie, PAB_INTP_AMBA_MISC_ENB);
 	shifted_val |= mask;
-	csr_writel(pcie, shifted_val, PAB_INTP_AMBA_MISC_ENB);
+	mobiveil_csr_writel(pcie, shifted_val, PAB_INTP_AMBA_MISC_ENB);
 	raw_spin_unlock_irqrestore(&pcie->intx_mask_lock, flags);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/controller/pcie-rcar.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/controller/pcie-rcar.c
@@ -93,8 +93,11 @@
 #define  LINK_SPEED_2_5GTS	(1 << 16)
 #define  LINK_SPEED_5_0GTS	(2 << 16)
 #define MACCTLR			0x011058
+#define  MACCTLR_NFTS_MASK	GENMASK(23, 16)	/* The name is from SH7786 */
 #define  SPEED_CHANGE		BIT(24)
 #define  SCRAMBLE_DISABLE	BIT(27)
+#define  LTSMDIS		BIT(31)
+#define  MACCTLR_INIT_VAL	(LTSMDIS | MACCTLR_NFTS_MASK)
 #define PMSR			0x01105c
 #define MACS2R			0x011078
 #define MACCGSPSETR		0x011084
@@ -332,11 +335,12 @@
 };
 
 static void rcar_pcie_setup_window(int win, struct rcar_pcie *pcie,
-				   struct resource *res)
+				   struct resource_entry *window)
 {
 	/* Setup PCIe address space mappings for each resource */
 	resource_size_t size;
 	resource_size_t res_start;
+	struct resource *res = window->res;
 	u32 mask;
 
 	rcar_pci_write_reg(pcie, 0x00000000, PCIEPTCTLR(win));
@@ -350,9 +354,9 @@
 	rcar_pci_write_reg(pcie, mask << 7, PCIEPAMR(win));
 
 	if (res->flags & IORESOURCE_IO)
-		res_start = pci_pio_to_address(res->start);
+		res_start = pci_pio_to_address(res->start) - window->offset;
 	else
-		res_start = res->start;
+		res_start = res->start - window->offset;
 
 	rcar_pci_write_reg(pcie, upper_32_bits(res_start), PCIEPAUR(win));
 	rcar_pci_write_reg(pcie, lower_32_bits(res_start) & ~0x7F,
@@ -381,7 +385,7 @@
 		switch (resource_type(res)) {
 		case IORESOURCE_IO:
 		case IORESOURCE_MEM:
-			rcar_pcie_setup_window(i, pci, res);
+			rcar_pcie_setup_window(i, pci, win);
 			i++;
 			break;
 		case IORESOURCE_BUS:
@@ -615,6 +619,8 @@
 	if (IS_ENABLED(CONFIG_PCI_MSI))
 		rcar_pci_write_reg(pcie, 0x801f0000, PCIEMSITXR);
 
+	rcar_pci_write_reg(pcie, MACCTLR_INIT_VAL, MACCTLR);
+
 	/* Finish initialization - establish a PCI Express link */
 	rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR);
 
@@ -1237,6 +1243,7 @@
 		return 0;
 
 	/* Re-establish the PCIe link */
+	rcar_pci_write_reg(pcie, MACCTLR_INIT_VAL, MACCTLR);
 	rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR);
 	return rcar_pcie_wait_for_dl(pcie);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/controller/pcie-rockchip-ep.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/controller/pcie-rockchip-ep.c
@@ -66,18 +66,26 @@
 			    ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR1(region));
 }
 
+static int rockchip_pcie_ep_ob_atu_num_bits(struct rockchip_pcie *rockchip,
+					    u64 pci_addr, size_t size)
+{
+	int num_pass_bits = fls64(pci_addr ^ (pci_addr + size - 1));
+
+	return clamp(num_pass_bits,
+		     ROCKCHIP_PCIE_AT_MIN_NUM_BITS,
+		     ROCKCHIP_PCIE_AT_MAX_NUM_BITS);
+}
+
 static void rockchip_pcie_prog_ep_ob_atu(struct rockchip_pcie *rockchip, u8 fn,
 					 u32 r, u32 type, u64 cpu_addr,
 					 u64 pci_addr, size_t size)
 {
-	u64 sz = 1ULL << fls64(size - 1);
-	int num_pass_bits = ilog2(sz);
+	int num_pass_bits;
 	u32 addr0, addr1, desc0, desc1;
 	bool is_nor_msg = (type == AXI_WRAPPER_NOR_MSG);
 
-	/* The minimal region size is 1MB */
-	if (num_pass_bits < 8)
-		num_pass_bits = 8;
+	num_pass_bits = rockchip_pcie_ep_ob_atu_num_bits(rockchip,
+							 pci_addr, size);
 
 	cpu_addr -= rockchip->mem_res->start;
 	addr0 = ((is_nor_msg ? 0x10 : (num_pass_bits - 1)) &
@@ -124,20 +132,20 @@
 static int rockchip_pcie_ep_write_header(struct pci_epc *epc, u8 fn,
 					 struct pci_epf_header *hdr)
 {
+	u32 reg;
 	struct rockchip_pcie_ep *ep = epc_get_drvdata(epc);
 	struct rockchip_pcie *rockchip = &ep->rockchip;
 
 	/* All functions share the same vendor ID with function 0 */
 	if (fn == 0) {
-		u32 vid_regs = (hdr->vendorid & GENMASK(15, 0)) |
-			       (hdr->subsys_vendor_id & GENMASK(31, 16)) << 16;
-
-		rockchip_pcie_write(rockchip, vid_regs,
+		rockchip_pcie_write(rockchip,
+				    hdr->vendorid | hdr->subsys_vendor_id << 16,
 				    PCIE_CORE_CONFIG_VENDOR);
 	}
 
-	rockchip_pcie_write(rockchip, hdr->deviceid << 16,
-			    ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + PCI_VENDOR_ID);
+	reg = rockchip_pcie_read(rockchip, PCIE_EP_CONFIG_DID_VID);
+	reg = (reg & 0xFFFF) | (hdr->deviceid << 16);
+	rockchip_pcie_write(rockchip, reg, PCIE_EP_CONFIG_DID_VID);
 
 	rockchip_pcie_write(rockchip,
 			    hdr->revid |
@@ -263,8 +271,7 @@
 	struct rockchip_pcie *pcie = &ep->rockchip;
 	u32 r;
 
-	r = find_first_zero_bit(&ep->ob_region_map,
-				sizeof(ep->ob_region_map) * BITS_PER_LONG);
+	r = find_first_zero_bit(&ep->ob_region_map, BITS_PER_LONG);
 	/*
 	 * Region 0 is reserved for configuration space and shouldn't
 	 * be used elsewhere per TRM, so leave it out.
@@ -312,15 +319,15 @@
 {
 	struct rockchip_pcie_ep *ep = epc_get_drvdata(epc);
 	struct rockchip_pcie *rockchip = &ep->rockchip;
-	u16 flags;
+	u32 flags;
 
 	flags = rockchip_pcie_read(rockchip,
 				   ROCKCHIP_PCIE_EP_FUNC_BASE(fn) +
 				   ROCKCHIP_PCIE_EP_MSI_CTRL_REG);
 	flags &= ~ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_MASK;
 	flags |=
-	   ((multi_msg_cap << 1) <<  ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_OFFSET) |
-	   PCI_MSI_FLAGS_64BIT;
+	   (multi_msg_cap << ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_OFFSET) |
+	   (PCI_MSI_FLAGS_64BIT << ROCKCHIP_PCIE_EP_MSI_FLAGS_OFFSET);
 	flags &= ~ROCKCHIP_PCIE_EP_MSI_CTRL_MASK_MSI_CAP;
 	rockchip_pcie_write(rockchip, flags,
 			    ROCKCHIP_PCIE_EP_FUNC_BASE(fn) +
@@ -332,7 +339,7 @@
 {
 	struct rockchip_pcie_ep *ep = epc_get_drvdata(epc);
 	struct rockchip_pcie *rockchip = &ep->rockchip;
-	u16 flags;
+	u32 flags;
 
 	flags = rockchip_pcie_read(rockchip,
 				   ROCKCHIP_PCIE_EP_FUNC_BASE(fn) +
@@ -345,48 +352,25 @@
 }
 
 static void rockchip_pcie_ep_assert_intx(struct rockchip_pcie_ep *ep, u8 fn,
-					 u8 intx, bool is_asserted)
+					 u8 intx, bool do_assert)
 {
 	struct rockchip_pcie *rockchip = &ep->rockchip;
-	u32 r = ep->max_regions - 1;
-	u32 offset;
-	u32 status;
-	u8 msg_code;
-
-	if (unlikely(ep->irq_pci_addr != ROCKCHIP_PCIE_EP_PCI_LEGACY_IRQ_ADDR ||
-		     ep->irq_pci_fn != fn)) {
-		rockchip_pcie_prog_ep_ob_atu(rockchip, fn, r,
-					     AXI_WRAPPER_NOR_MSG,
-					     ep->irq_phys_addr, 0, 0);
-		ep->irq_pci_addr = ROCKCHIP_PCIE_EP_PCI_LEGACY_IRQ_ADDR;
-		ep->irq_pci_fn = fn;
-	}
 
 	intx &= 3;
-	if (is_asserted) {
+
+	if (do_assert) {
 		ep->irq_pending |= BIT(intx);
-		msg_code = ROCKCHIP_PCIE_MSG_CODE_ASSERT_INTA + intx;
+		rockchip_pcie_write(rockchip,
+				    PCIE_CLIENT_INT_IN_ASSERT |
+				    PCIE_CLIENT_INT_PEND_ST_PEND,
+				    PCIE_CLIENT_LEGACY_INT_CTRL);
 	} else {
 		ep->irq_pending &= ~BIT(intx);
-		msg_code = ROCKCHIP_PCIE_MSG_CODE_DEASSERT_INTA + intx;
-	}
-
-	status = rockchip_pcie_read(rockchip,
-				    ROCKCHIP_PCIE_EP_FUNC_BASE(fn) +
-				    ROCKCHIP_PCIE_EP_CMD_STATUS);
-	status &= ROCKCHIP_PCIE_EP_CMD_STATUS_IS;
-
-	if ((status != 0) ^ (ep->irq_pending != 0)) {
-		status ^= ROCKCHIP_PCIE_EP_CMD_STATUS_IS;
-		rockchip_pcie_write(rockchip, status,
-				    ROCKCHIP_PCIE_EP_FUNC_BASE(fn) +
-				    ROCKCHIP_PCIE_EP_CMD_STATUS);
+		rockchip_pcie_write(rockchip,
+				    PCIE_CLIENT_INT_IN_DEASSERT |
+				    PCIE_CLIENT_INT_PEND_ST_NORMAL,
+				    PCIE_CLIENT_LEGACY_INT_CTRL);
 	}
-
-	offset =
-	   ROCKCHIP_PCIE_MSG_ROUTING(ROCKCHIP_PCIE_MSG_ROUTING_LOCAL_INTX) |
-	   ROCKCHIP_PCIE_MSG_CODE(msg_code) | ROCKCHIP_PCIE_MSG_NO_DATA;
-	writel(0, ep->irq_cpu_addr + offset);
 }
 
 static int rockchip_pcie_ep_send_legacy_irq(struct rockchip_pcie_ep *ep, u8 fn,
@@ -416,7 +400,7 @@
 					 u8 interrupt_num)
 {
 	struct rockchip_pcie *rockchip = &ep->rockchip;
-	u16 flags, mme, data, data_mask;
+	u32 flags, mme, data, data_mask;
 	u8 msi_count;
 	u64 pci_addr, pci_addr_mask = 0xff;
 
@@ -506,6 +490,7 @@
 	.linkup_notifier = false,
 	.msi_capable = true,
 	.msix_capable = false,
+	.align = 256,
 };
 
 static const struct pci_epc_features*
@@ -631,6 +616,9 @@
 
 	ep->irq_pci_addr = ROCKCHIP_PCIE_EP_DUMMY_IRQ_ADDR;
 
+	rockchip_pcie_write(rockchip, PCIE_CLIENT_CONF_ENABLE,
+			    PCIE_CLIENT_CONFIG);
+
 	return 0;
 err_epc_mem_exit:
 	pci_epc_mem_exit(epc);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/controller/pcie-rockchip.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/controller/pcie-rockchip.c
@@ -14,6 +14,7 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/gpio/consumer.h>
+#include <linux/iopoll.h>
 #include <linux/of_pci.h>
 #include <linux/phy/phy.h>
 #include <linux/platform_device.h>
@@ -83,7 +84,7 @@
 	}
 
 	rockchip->mgmt_sticky_rst = devm_reset_control_get_exclusive(dev,
-								     "mgmt-sticky");
+								"mgmt-sticky");
 	if (IS_ERR(rockchip->mgmt_sticky_rst)) {
 		if (PTR_ERR(rockchip->mgmt_sticky_rst) != -EPROBE_DEFER)
 			dev_err(dev, "missing mgmt-sticky reset property in node\n");
@@ -119,11 +120,11 @@
 	}
 
 	if (rockchip->is_rc) {
-		rockchip->ep_gpio = devm_gpiod_get(dev, "ep", GPIOD_OUT_HIGH);
-		if (IS_ERR(rockchip->ep_gpio)) {
-			dev_err(dev, "missing ep-gpios property in node\n");
-			return PTR_ERR(rockchip->ep_gpio);
-		}
+		rockchip->ep_gpio = devm_gpiod_get_optional(dev, "ep",
+							    GPIOD_OUT_LOW);
+		if (IS_ERR(rockchip->ep_gpio))
+			return dev_err_probe(dev, PTR_ERR(rockchip->ep_gpio),
+					     "failed to get ep GPIO\n");
 	}
 
 	rockchip->aclk_pcie = devm_clk_get(dev, "aclk");
@@ -154,6 +155,12 @@
 }
 EXPORT_SYMBOL_GPL(rockchip_pcie_parse_dt);
 
+#define rockchip_pcie_read_addr(addr) rockchip_pcie_read(rockchip, addr)
+/* 100 ms max wait time for PHY PLLs to lock */
+#define RK_PHY_PLL_LOCK_TIMEOUT_US 100000
+/* Sleep should be less than 20ms */
+#define RK_PHY_PLL_LOCK_SLEEP_US 1000
+
 int rockchip_pcie_init_port(struct rockchip_pcie *rockchip)
 {
 	struct device *dev = rockchip->dev;
@@ -255,6 +262,16 @@
 		}
 	}
 
+	err = readx_poll_timeout(rockchip_pcie_read_addr,
+				 PCIE_CLIENT_SIDE_BAND_STATUS,
+				 regs, !(regs & PCIE_CLIENT_PHY_ST),
+				 RK_PHY_PLL_LOCK_SLEEP_US,
+				 RK_PHY_PLL_LOCK_TIMEOUT_US);
+	if (err) {
+		dev_err(dev, "PHY PLLs could not lock, %d\n", err);
+		goto err_power_off_phy;
+	}
+
 	/*
 	 * Please don't reorder the deassert sequence of the following
 	 * four reset pins.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/controller/pcie-rockchip.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/controller/pcie-rockchip.h
@@ -37,6 +37,13 @@
 #define   PCIE_CLIENT_MODE_EP            HIWORD_UPDATE(0x0040, 0)
 #define   PCIE_CLIENT_GEN_SEL_1		  HIWORD_UPDATE(0x0080, 0)
 #define   PCIE_CLIENT_GEN_SEL_2		  HIWORD_UPDATE_BIT(0x0080)
+#define PCIE_CLIENT_LEGACY_INT_CTRL	(PCIE_CLIENT_BASE + 0x0c)
+#define   PCIE_CLIENT_INT_IN_ASSERT		HIWORD_UPDATE_BIT(0x0002)
+#define   PCIE_CLIENT_INT_IN_DEASSERT		HIWORD_UPDATE(0x0002, 0)
+#define   PCIE_CLIENT_INT_PEND_ST_PEND		HIWORD_UPDATE_BIT(0x0001)
+#define   PCIE_CLIENT_INT_PEND_ST_NORMAL	HIWORD_UPDATE(0x0001, 0)
+#define PCIE_CLIENT_SIDE_BAND_STATUS	(PCIE_CLIENT_BASE + 0x20)
+#define   PCIE_CLIENT_PHY_ST			BIT(12)
 #define PCIE_CLIENT_DEBUG_OUT_0		(PCIE_CLIENT_BASE + 0x3c)
 #define   PCIE_CLIENT_DEBUG_LTSSM_MASK		GENMASK(5, 0)
 #define   PCIE_CLIENT_DEBUG_LTSSM_L1		0x18
@@ -132,6 +139,8 @@
 #define PCIE_RC_RP_ATS_BASE		0x400000
 #define PCIE_RC_CONFIG_NORMAL_BASE	0x800000
 #define PCIE_RC_CONFIG_BASE		0xa00000
+#define PCIE_EP_CONFIG_BASE		0xa00000
+#define PCIE_EP_CONFIG_DID_VID		(PCIE_EP_CONFIG_BASE + 0x00)
 #define PCIE_RC_CONFIG_RID_CCR		(PCIE_RC_CONFIG_BASE + 0x08)
 #define   PCIE_RC_CONFIG_SCC_SHIFT		16
 #define PCIE_RC_CONFIG_DCR		(PCIE_RC_CONFIG_BASE + 0xc4)
@@ -223,6 +232,7 @@
 #define ROCKCHIP_PCIE_EP_CMD_STATUS			0x4
 #define   ROCKCHIP_PCIE_EP_CMD_STATUS_IS		BIT(19)
 #define ROCKCHIP_PCIE_EP_MSI_CTRL_REG			0x90
+#define   ROCKCHIP_PCIE_EP_MSI_FLAGS_OFFSET		16
 #define   ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_OFFSET		17
 #define   ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_MASK		GENMASK(19, 17)
 #define   ROCKCHIP_PCIE_EP_MSI_CTRL_MME_OFFSET		20
@@ -230,8 +240,11 @@
 #define   ROCKCHIP_PCIE_EP_MSI_CTRL_ME				BIT(16)
 #define   ROCKCHIP_PCIE_EP_MSI_CTRL_MASK_MSI_CAP	BIT(24)
 #define ROCKCHIP_PCIE_EP_DUMMY_IRQ_ADDR				0x1
-#define ROCKCHIP_PCIE_EP_PCI_LEGACY_IRQ_ADDR		0x3
 #define ROCKCHIP_PCIE_EP_FUNC_BASE(fn)	(((fn) << 12) & GENMASK(19, 12))
+
+#define ROCKCHIP_PCIE_AT_MIN_NUM_BITS  8
+#define ROCKCHIP_PCIE_AT_MAX_NUM_BITS  20
+
 #define ROCKCHIP_PCIE_AT_IB_EP_FUNC_BAR_ADDR0(fn, bar) \
 	(PCIE_RC_RP_ATS_BASE + 0x0840 + (fn) * 0x0040 + (bar) * 0x0008)
 #define ROCKCHIP_PCIE_AT_IB_EP_FUNC_BAR_ADDR1(fn, bar) \
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/controller/pcie-xdma-pl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/controller/pcie-xdma-pl.c
@@ -0,0 +1,912 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * PCIe host controller driver for Xilinx XDMA PCIe Bridge
+ *
+ * Copyright (C) 2017 Xilinx, Inc. All rights reserved.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/msi.h>
+#include <linux/of_address.h>
+#include <linux/of_pci.h>
+#include <linux/of_platform.h>
+#include <linux/of_irq.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/irqchip/chained_irq.h>
+
+#include "../pci.h"
+
+/* Register definitions */
+#define XILINX_PCIE_REG_VSEC		0x0000012c
+#define XILINX_PCIE_REG_BIR		0x00000130
+#define XILINX_PCIE_REG_IDR		0x00000138
+#define XILINX_PCIE_REG_IMR		0x0000013c
+#define XILINX_PCIE_REG_PSCR		0x00000144
+#define XILINX_PCIE_REG_RPSC		0x00000148
+#define XILINX_PCIE_REG_MSIBASE1	0x0000014c
+#define XILINX_PCIE_REG_MSIBASE2	0x00000150
+#define XILINX_PCIE_REG_RPEFR		0x00000154
+#define XILINX_PCIE_REG_RPIFR1		0x00000158
+#define XILINX_PCIE_REG_RPIFR2		0x0000015c
+#define XILINX_PCIE_REG_IDRN            0x00000160
+#define XILINX_PCIE_REG_IDRN_MASK       0x00000164
+#define XILINX_PCIE_REG_MSI_LOW		0x00000170
+#define XILINX_PCIE_REG_MSI_HI		0x00000174
+#define XILINX_PCIE_REG_MSI_LOW_MASK	0x00000178
+#define XILINX_PCIE_REG_MSI_HI_MASK	0x0000017c
+
+/* Interrupt registers definitions */
+#define XILINX_PCIE_INTR_LINK_DOWN	BIT(0)
+#define XILINX_PCIE_INTR_HOT_RESET	BIT(3)
+#define XILINX_PCIE_INTR_CFG_TIMEOUT	BIT(8)
+#define XILINX_PCIE_INTR_CORRECTABLE	BIT(9)
+#define XILINX_PCIE_INTR_NONFATAL	BIT(10)
+#define XILINX_PCIE_INTR_FATAL		BIT(11)
+#define XILINX_PCIE_INTR_INTX		BIT(16)
+#define XILINX_PCIE_INTR_MSI		BIT(17)
+#define XILINX_PCIE_INTR_SLV_UNSUPP	BIT(20)
+#define XILINX_PCIE_INTR_SLV_UNEXP	BIT(21)
+#define XILINX_PCIE_INTR_SLV_COMPL	BIT(22)
+#define XILINX_PCIE_INTR_SLV_ERRP	BIT(23)
+#define XILINX_PCIE_INTR_SLV_CMPABT	BIT(24)
+#define XILINX_PCIE_INTR_SLV_ILLBUR	BIT(25)
+#define XILINX_PCIE_INTR_MST_DECERR	BIT(26)
+#define XILINX_PCIE_INTR_MST_SLVERR	BIT(27)
+#define XILINX_PCIE_IMR_ALL_MASK	0x0FF30FE9
+#define XILINX_PCIE_IDR_ALL_MASK	0xFFFFFFFF
+#define XILINX_PCIE_IDRN_MASK           GENMASK(19, 16)
+
+/* Root Port Error FIFO Read Register definitions */
+#define XILINX_PCIE_RPEFR_ERR_VALID	BIT(18)
+#define XILINX_PCIE_RPEFR_REQ_ID	GENMASK(15, 0)
+#define XILINX_PCIE_RPEFR_ALL_MASK	0xFFFFFFFF
+
+/* Root Port Interrupt FIFO Read Register 1 definitions */
+#define XILINX_PCIE_RPIFR1_INTR_VALID	BIT(31)
+#define XILINX_PCIE_RPIFR1_MSI_INTR	BIT(30)
+#define XILINX_PCIE_RPIFR1_INTR_MASK	GENMASK(28, 27)
+#define XILINX_PCIE_RPIFR1_ALL_MASK	0xFFFFFFFF
+#define XILINX_PCIE_RPIFR1_INTR_SHIFT	27
+#define XILINX_PCIE_IDRN_SHIFT          16
+#define XILINX_PCIE_VSEC_REV_MASK	GENMASK(19, 16)
+#define XILINX_PCIE_VSEC_REV_SHIFT	16
+#define XILINX_PCIE_FIFO_SHIFT		5
+
+/* Bridge Info Register definitions */
+#define XILINX_PCIE_BIR_ECAM_SZ_MASK	GENMASK(18, 16)
+#define XILINX_PCIE_BIR_ECAM_SZ_SHIFT	16
+
+/* Root Port Interrupt FIFO Read Register 2 definitions */
+#define XILINX_PCIE_RPIFR2_MSG_DATA	GENMASK(15, 0)
+
+/* Root Port Status/control Register definitions */
+#define XILINX_PCIE_REG_RPSC_BEN	BIT(0)
+
+/* Phy Status/Control Register definitions */
+#define XILINX_PCIE_REG_PSCR_LNKUP	BIT(11)
+
+/* ECAM definitions */
+#define ECAM_BUS_NUM_SHIFT		20
+#define ECAM_DEV_NUM_SHIFT		12
+
+/* Number of MSI IRQs */
+#define XILINX_NUM_MSI_IRQS		64
+#define INTX_NUM                        4
+
+/* For CPM Versal */
+#define CPM_BRIDGE_BASE_OFF		0xCD8
+#define XILINX_PCIE_MISC_IR_STATUS	0x00000340
+#define XILINX_PCIE_MISC_IR_ENABLE	0x00000348
+#define XILINX_PCIE_MISC_IR_LOCAL	BIT(1)
+
+/* CPM versal Interrupt registers */
+#define XILINX_PCIE_INTR_CFG_PCIE_TIMEOUT	BIT(4)
+#define XILINX_PCIE_INTR_CFG_ERR_POISON		BIT(12)
+#define XILINX_PCIE_INTR_PME_TO_ACK_RCVD	BIT(15)
+#define XILINX_PCIE_INTR_PM_PME_RCVD		BIT(17)
+#define XILINX_PCIE_INTR_SLV_PCIE_TIMEOUT	BIT(28)
+
+#define XILINX_PCIE_IMR_ALL_MASK_CPM		0x1FF39FF9
+
+enum msi_mode {
+	MSI_DECD_MODE = 1,
+	MSI_FIFO_MODE,
+};
+
+enum xdma_config {
+	XDMA_ZYNQMP_PL = 1,
+	XDMA_VERSAL_CPM,
+	XDMA_VERSAL_PL,
+};
+
+struct xilinx_msi {
+	struct irq_domain *msi_domain;
+	unsigned long *bitmap;
+	struct irq_domain *dev_domain;
+	struct mutex lock;		/* protect bitmap variable */
+	unsigned long msi_pages;
+	int irq_msi0;
+	int irq_msi1;
+};
+
+/**
+ * struct xilinx_pcie_port - PCIe port information
+ * @reg_base: IO Mapped Register Base
+ * @cpm_base: CPM SLCR Register Base
+ * @irq: Interrupt number
+ * @root_busno: Root Bus number
+ * @dev: Device pointer
+ * @leg_domain: Legacy IRQ domain pointer
+ * @resources: Bus Resources
+ * @msi: MSI information
+ * @irq_misc: Legacy and error interrupt number
+ * @msi_mode: MSI mode
+ * @xdma_config: XDMA IP configuration
+ */
+struct xilinx_pcie_port {
+	void __iomem *reg_base;
+	void __iomem *cpm_base;
+	u32 irq;
+	u8 root_busno;
+	struct device *dev;
+	struct irq_domain *leg_domain;
+	struct list_head resources;
+	struct xilinx_msi msi;
+	int irq_misc;
+	u8 msi_mode;
+	u8 xdma_config;
+};
+
+static inline u32 pcie_read(struct xilinx_pcie_port *port, u32 reg)
+{
+	if (port->xdma_config == XDMA_ZYNQMP_PL)
+		return readl(port->reg_base + reg);
+	else
+		return readl(port->reg_base + reg + CPM_BRIDGE_BASE_OFF);
+}
+
+static inline void pcie_write(struct xilinx_pcie_port *port, u32 val, u32 reg)
+{
+	if (port->xdma_config == XDMA_ZYNQMP_PL)
+		writel(val, port->reg_base + reg);
+	else
+		writel(val, port->reg_base + reg + CPM_BRIDGE_BASE_OFF);
+}
+
+static inline bool xilinx_pcie_link_is_up(struct xilinx_pcie_port *port)
+{
+	return (pcie_read(port, XILINX_PCIE_REG_PSCR) &
+		XILINX_PCIE_REG_PSCR_LNKUP) ? 1 : 0;
+}
+
+/**
+ * xilinx_pcie_clear_err_interrupts - Clear Error Interrupts
+ * @port: PCIe port information
+ */
+static void xilinx_pcie_clear_err_interrupts(struct xilinx_pcie_port *port)
+{
+	unsigned long val = pcie_read(port, XILINX_PCIE_REG_RPEFR);
+
+	if (val & XILINX_PCIE_RPEFR_ERR_VALID) {
+		dev_dbg(port->dev, "Requester ID %lu\n",
+			val & XILINX_PCIE_RPEFR_REQ_ID);
+		pcie_write(port, XILINX_PCIE_RPEFR_ALL_MASK,
+			   XILINX_PCIE_REG_RPEFR);
+	}
+}
+
+/**
+ * xilinx_pcie_valid_device - Check if a valid device is present on bus
+ * @bus: PCI Bus structure
+ * @devfn: device/function
+ *
+ * Return: 'true' on success and 'false' if invalid device is found
+ */
+static bool xilinx_pcie_valid_device(struct pci_bus *bus, unsigned int devfn)
+{
+	struct xilinx_pcie_port *port = bus->sysdata;
+
+	/* Check if link is up when trying to access downstream ports */
+	if (bus->number != port->root_busno)
+		if (!xilinx_pcie_link_is_up(port))
+			return false;
+
+	/* Only one device down on each root port */
+	if (bus->number == port->root_busno && devfn > 0)
+		return false;
+
+	return true;
+}
+
+/**
+ * xilinx_pcie_map_bus - Get configuration base
+ * @bus: PCI Bus structure
+ * @devfn: Device/function
+ * @where: Offset from base
+ *
+ * Return: Base address of the configuration space needed to be
+ *	   accessed.
+ */
+static void __iomem *xilinx_pcie_map_bus(struct pci_bus *bus,
+					 unsigned int devfn, int where)
+{
+	struct xilinx_pcie_port *port = bus->sysdata;
+	int relbus;
+
+	if (!xilinx_pcie_valid_device(bus, devfn))
+		return NULL;
+
+	relbus = (bus->number << ECAM_BUS_NUM_SHIFT) |
+		 (devfn << ECAM_DEV_NUM_SHIFT);
+
+	return port->reg_base + relbus + where;
+}
+
+/* PCIe operations */
+static struct pci_ops xilinx_pcie_ops = {
+	.map_bus = xilinx_pcie_map_bus,
+	.read	= pci_generic_config_read,
+	.write	= pci_generic_config_write,
+};
+
+/**
+ * xilinx_pcie_enable_msi - Enable MSI support
+ * @port: PCIe port information
+ */
+static void xilinx_pcie_enable_msi(struct xilinx_pcie_port *port)
+{
+	struct xilinx_msi *msi = &port->msi;
+	phys_addr_t msg_addr;
+
+	msi->msi_pages = __get_free_pages(GFP_KERNEL, 0);
+	msg_addr = virt_to_phys((void *)msi->msi_pages);
+	pcie_write(port, upper_32_bits(msg_addr), XILINX_PCIE_REG_MSIBASE1);
+	pcie_write(port, lower_32_bits(msg_addr), XILINX_PCIE_REG_MSIBASE2);
+}
+
+/**
+ * xilinx_pcie_intx_map - Set the handler for the INTx and mark IRQ as valid
+ * @domain: IRQ domain
+ * @irq: Virtual IRQ number
+ * @hwirq: HW interrupt number
+ *
+ * Return: Always returns 0.
+ */
+static int xilinx_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
+				irq_hw_number_t hwirq)
+{
+	irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq);
+	irq_set_chip_data(irq, domain->host_data);
+	irq_set_status_flags(irq, IRQ_LEVEL);
+
+	return 0;
+}
+
+/* INTx IRQ Domain operations */
+static const struct irq_domain_ops intx_domain_ops = {
+	.map = xilinx_pcie_intx_map,
+	.xlate = pci_irqd_intx_xlate,
+};
+
+static void xilinx_pcie_handle_msi_irq(struct xilinx_pcie_port *port,
+				       u32 status_reg)
+{
+	struct xilinx_msi *msi;
+	unsigned long status;
+	u32 bit;
+	u32 virq;
+
+	msi = &port->msi;
+
+	while ((status = pcie_read(port, status_reg)) != 0) {
+		for_each_set_bit(bit, &status, 32) {
+			pcie_write(port, 1 << bit, status_reg);
+			if (status_reg == XILINX_PCIE_REG_MSI_HI)
+				bit = bit + 32;
+			virq = irq_find_mapping(msi->dev_domain, bit);
+			if (virq)
+				generic_handle_irq(virq);
+		}
+	}
+}
+
+static void xilinx_pcie_msi_handler_high(struct irq_desc *desc)
+{
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct xilinx_pcie_port *port = irq_desc_get_handler_data(desc);
+
+	chained_irq_enter(chip, desc);
+	xilinx_pcie_handle_msi_irq(port, XILINX_PCIE_REG_MSI_HI);
+	chained_irq_exit(chip, desc);
+}
+
+static void xilinx_pcie_msi_handler_low(struct irq_desc *desc)
+{
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct xilinx_pcie_port *port = irq_desc_get_handler_data(desc);
+
+	chained_irq_enter(chip, desc);
+	xilinx_pcie_handle_msi_irq(port, XILINX_PCIE_REG_MSI_LOW);
+	chained_irq_exit(chip, desc);
+}
+
+/**
+ * xilinx_pcie_intr_handler - Interrupt Service Handler
+ * @irq: IRQ number
+ * @data: PCIe port information
+ *
+ * Return: IRQ_HANDLED on success and IRQ_NONE on failure
+ */
+static irqreturn_t xilinx_pcie_intr_handler(int irq, void *data)
+{
+	struct xilinx_pcie_port *port = (struct xilinx_pcie_port *)data;
+	u32 val, mask, status, msi_data, bit;
+	unsigned long intr_val;
+
+	/* Read interrupt decode and mask registers */
+	val = pcie_read(port, XILINX_PCIE_REG_IDR);
+	mask = pcie_read(port, XILINX_PCIE_REG_IMR);
+
+	status = val & mask;
+	if (!status)
+		return IRQ_NONE;
+
+	if (status & XILINX_PCIE_INTR_LINK_DOWN)
+		dev_warn(port->dev, "Link Down\n");
+
+	if (status & XILINX_PCIE_INTR_HOT_RESET)
+		dev_info(port->dev, "Hot reset\n");
+
+	if (status & XILINX_PCIE_INTR_CFG_TIMEOUT)
+		dev_warn(port->dev, "ECAM access timeout\n");
+
+	if (status & XILINX_PCIE_INTR_CORRECTABLE) {
+		dev_warn(port->dev, "Correctable error message\n");
+		xilinx_pcie_clear_err_interrupts(port);
+	}
+
+	if (status & XILINX_PCIE_INTR_NONFATAL) {
+		dev_warn(port->dev, "Non fatal error message\n");
+		xilinx_pcie_clear_err_interrupts(port);
+	}
+
+	if (status & XILINX_PCIE_INTR_FATAL) {
+		dev_warn(port->dev, "Fatal error message\n");
+		xilinx_pcie_clear_err_interrupts(port);
+	}
+
+	if (status & XILINX_PCIE_INTR_INTX) {
+		/* Handle INTx Interrupt */
+		intr_val = pcie_read(port, XILINX_PCIE_REG_IDRN);
+		intr_val = intr_val >> XILINX_PCIE_IDRN_SHIFT;
+
+		for_each_set_bit(bit, &intr_val, INTX_NUM)
+			generic_handle_irq(irq_find_mapping(port->leg_domain,
+							    bit));
+	}
+
+	if (port->msi_mode == MSI_FIFO_MODE &&
+	    (status & XILINX_PCIE_INTR_MSI) && (!port->cpm_base)) {
+		/* MSI Interrupt */
+		val = pcie_read(port, XILINX_PCIE_REG_RPIFR1);
+
+		if (!(val & XILINX_PCIE_RPIFR1_INTR_VALID)) {
+			dev_warn(port->dev, "RP Intr FIFO1 read error\n");
+			goto error;
+		}
+
+		if (val & XILINX_PCIE_RPIFR1_MSI_INTR) {
+			msi_data = pcie_read(port, XILINX_PCIE_REG_RPIFR2) &
+				   XILINX_PCIE_RPIFR2_MSG_DATA;
+
+			/* Clear interrupt FIFO register 1 */
+			pcie_write(port, XILINX_PCIE_RPIFR1_ALL_MASK,
+				   XILINX_PCIE_REG_RPIFR1);
+
+			if (IS_ENABLED(CONFIG_PCI_MSI)) {
+				/* Handle MSI Interrupt */
+				val = irq_find_mapping(port->msi.dev_domain,
+						       msi_data);
+				if (val)
+					generic_handle_irq(val);
+			}
+		}
+	}
+
+	if (status & XILINX_PCIE_INTR_SLV_UNSUPP)
+		dev_warn(port->dev, "Slave unsupported request\n");
+
+	if (status & XILINX_PCIE_INTR_SLV_UNEXP)
+		dev_warn(port->dev, "Slave unexpected completion\n");
+
+	if (status & XILINX_PCIE_INTR_SLV_COMPL)
+		dev_warn(port->dev, "Slave completion timeout\n");
+
+	if (status & XILINX_PCIE_INTR_SLV_ERRP)
+		dev_warn(port->dev, "Slave Error Poison\n");
+
+	if (status & XILINX_PCIE_INTR_SLV_CMPABT)
+		dev_warn(port->dev, "Slave Completer Abort\n");
+
+	if (status & XILINX_PCIE_INTR_SLV_ILLBUR)
+		dev_warn(port->dev, "Slave Illegal Burst\n");
+
+	if (status & XILINX_PCIE_INTR_MST_DECERR)
+		dev_warn(port->dev, "Master decode error\n");
+
+	if (status & XILINX_PCIE_INTR_MST_SLVERR)
+		dev_warn(port->dev, "Master slave error\n");
+
+	if (port->cpm_base) {
+		if (status & XILINX_PCIE_INTR_CFG_PCIE_TIMEOUT)
+			dev_warn(port->dev, "PCIe ECAM access timeout\n");
+
+		if (status & XILINX_PCIE_INTR_CFG_ERR_POISON)
+			dev_warn(port->dev, "ECAM poisoned completion received\n");
+
+		if (status & XILINX_PCIE_INTR_PME_TO_ACK_RCVD)
+			dev_warn(port->dev, "PME_TO_ACK message received\n");
+
+		if (status & XILINX_PCIE_INTR_PM_PME_RCVD)
+			dev_warn(port->dev, "PM_PME message received\n");
+
+		if (status & XILINX_PCIE_INTR_SLV_PCIE_TIMEOUT)
+			dev_warn(port->dev, "PCIe completion timeout received\n");
+	}
+
+error:
+	/* Clear the Interrupt Decode register */
+	pcie_write(port, status, XILINX_PCIE_REG_IDR);
+	if (port->cpm_base) {
+		val = readl(port->cpm_base + XILINX_PCIE_MISC_IR_STATUS);
+		if (val)
+			writel(val,
+			       port->cpm_base + XILINX_PCIE_MISC_IR_STATUS);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static struct irq_chip xilinx_msi_irq_chip = {
+	.name = "xilinx_pcie:msi",
+	.irq_enable = pci_msi_unmask_irq,
+	.irq_disable = pci_msi_mask_irq,
+	.irq_mask = pci_msi_mask_irq,
+	.irq_unmask = pci_msi_unmask_irq,
+};
+
+static struct msi_domain_info xilinx_msi_domain_info = {
+	.flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
+		MSI_FLAG_MULTI_PCI_MSI),
+	.chip = &xilinx_msi_irq_chip,
+};
+
+static void xilinx_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
+{
+	struct xilinx_pcie_port *pcie = irq_data_get_irq_chip_data(data);
+	struct xilinx_msi *msi = &pcie->msi;
+	phys_addr_t msi_addr;
+
+	msi_addr = virt_to_phys((void *)msi->msi_pages);
+	msg->address_lo = lower_32_bits(msi_addr);
+	msg->address_hi = upper_32_bits(msi_addr);
+	msg->data = data->hwirq;
+}
+
+static int xilinx_msi_set_affinity(struct irq_data *irq_data,
+				   const struct cpumask *mask, bool force)
+{
+	return -EINVAL;
+}
+
+static struct irq_chip xilinx_irq_chip = {
+	.name = "Xilinx MSI",
+	.irq_compose_msi_msg = xilinx_compose_msi_msg,
+	.irq_set_affinity = xilinx_msi_set_affinity,
+};
+
+static int xilinx_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
+				   unsigned int nr_irqs, void *args)
+{
+	struct xilinx_pcie_port *pcie = domain->host_data;
+	struct xilinx_msi *msi = &pcie->msi;
+	int bit;
+	int i;
+
+	mutex_lock(&msi->lock);
+	bit = bitmap_find_free_region(msi->bitmap, XILINX_NUM_MSI_IRQS,
+				      get_count_order(nr_irqs));
+	if (bit < 0) {
+		mutex_unlock(&msi->lock);
+		return -ENOSPC;
+	}
+
+	for (i = 0; i < nr_irqs; i++) {
+		irq_domain_set_info(domain, virq + i, bit + i, &xilinx_irq_chip,
+				    domain->host_data, handle_simple_irq,
+				    NULL, NULL);
+	}
+	mutex_unlock(&msi->lock);
+	return 0;
+}
+
+static void xilinx_irq_domain_free(struct irq_domain *domain, unsigned int virq,
+				   unsigned int nr_irqs)
+{
+	struct irq_data *data = irq_domain_get_irq_data(domain, virq);
+	struct xilinx_pcie_port *pcie = irq_data_get_irq_chip_data(data);
+	struct xilinx_msi *msi = &pcie->msi;
+
+	mutex_lock(&msi->lock);
+	bitmap_release_region(msi->bitmap, data->hwirq,
+			      get_count_order(nr_irqs));
+	mutex_unlock(&msi->lock);
+}
+
+static const struct irq_domain_ops dev_msi_domain_ops = {
+	.alloc  = xilinx_irq_domain_alloc,
+	.free   = xilinx_irq_domain_free,
+};
+
+static int xilinx_pcie_init_msi_irq_domain(struct xilinx_pcie_port *port)
+{
+	struct fwnode_handle *fwnode = of_node_to_fwnode(port->dev->of_node);
+	struct xilinx_msi *msi = &port->msi;
+	int size = BITS_TO_LONGS(XILINX_NUM_MSI_IRQS) * sizeof(long);
+
+	msi->dev_domain = irq_domain_add_linear(NULL, XILINX_NUM_MSI_IRQS,
+						&dev_msi_domain_ops, port);
+	if (!msi->dev_domain) {
+		dev_err(port->dev, "failed to create dev IRQ domain\n");
+		return -ENOMEM;
+	}
+	msi->msi_domain = pci_msi_create_irq_domain(fwnode,
+						    &xilinx_msi_domain_info,
+						    msi->dev_domain);
+	if (!msi->msi_domain) {
+		dev_err(port->dev, "failed to create msi IRQ domain\n");
+		irq_domain_remove(msi->dev_domain);
+		return -ENOMEM;
+	}
+
+	mutex_init(&msi->lock);
+	msi->bitmap = kzalloc(size, GFP_KERNEL);
+	if (!msi->bitmap)
+		return -ENOMEM;
+
+	xilinx_pcie_enable_msi(port);
+
+	return 0;
+}
+
+/**
+ * xilinx_pcie_init_irq_domain - Initialize IRQ domain
+ * @port: PCIe port information
+ *
+ * Return: '0' on success and error value on failure
+ */
+static int xilinx_pcie_init_irq_domain(struct xilinx_pcie_port *port)
+{
+	struct device *dev = port->dev;
+	struct device_node *node = dev->of_node;
+	struct device_node *pcie_intc_node;
+
+	/* Setup INTx */
+	pcie_intc_node = of_get_next_child(node, NULL);
+	if (!pcie_intc_node) {
+		dev_err(dev, "No PCIe Intc node found\n");
+		return PTR_ERR(pcie_intc_node);
+	}
+
+	port->leg_domain = irq_domain_add_linear(pcie_intc_node, INTX_NUM,
+						 &intx_domain_ops,
+						 port);
+	if (!port->leg_domain) {
+		dev_err(dev, "Failed to get a INTx IRQ domain\n");
+		return PTR_ERR(port->leg_domain);
+	}
+
+	xilinx_pcie_init_msi_irq_domain(port);
+
+	return 0;
+}
+
+/**
+ * xilinx_pcie_init_port - Initialize hardware
+ * @port: PCIe port information
+ */
+static void xilinx_pcie_init_port(struct xilinx_pcie_port *port)
+{
+	if (xilinx_pcie_link_is_up(port))
+		dev_info(port->dev, "PCIe Link is UP\n");
+	else
+		dev_info(port->dev, "PCIe Link is DOWN\n");
+
+	/* Disable all interrupts */
+	pcie_write(port, ~XILINX_PCIE_IDR_ALL_MASK,
+		   XILINX_PCIE_REG_IMR);
+
+	/* Clear pending interrupts */
+	pcie_write(port, pcie_read(port, XILINX_PCIE_REG_IDR) &
+			 XILINX_PCIE_IMR_ALL_MASK,
+		   XILINX_PCIE_REG_IDR);
+
+	/* Enable all interrupts */
+	if (!port->cpm_base)
+		pcie_write(port, XILINX_PCIE_IMR_ALL_MASK,
+			   XILINX_PCIE_REG_IMR);
+	pcie_write(port, XILINX_PCIE_IDRN_MASK, XILINX_PCIE_REG_IDRN_MASK);
+	if (port->msi_mode == MSI_DECD_MODE) {
+		pcie_write(port, XILINX_PCIE_IDR_ALL_MASK,
+			   XILINX_PCIE_REG_MSI_LOW_MASK);
+		pcie_write(port, XILINX_PCIE_IDR_ALL_MASK,
+			   XILINX_PCIE_REG_MSI_HI_MASK);
+	}
+	/* Enable the Bridge enable bit */
+	pcie_write(port, pcie_read(port, XILINX_PCIE_REG_RPSC) |
+			 XILINX_PCIE_REG_RPSC_BEN,
+		   XILINX_PCIE_REG_RPSC);
+
+	if (port->cpm_base) {
+		writel(XILINX_PCIE_MISC_IR_LOCAL,
+		       port->cpm_base + XILINX_PCIE_MISC_IR_ENABLE);
+		pcie_write(port, XILINX_PCIE_IMR_ALL_MASK_CPM,
+			   XILINX_PCIE_REG_IMR);
+	}
+}
+
+static int xilinx_request_misc_irq(struct xilinx_pcie_port *port)
+{
+	struct device *dev = port->dev;
+	struct platform_device *pdev = to_platform_device(dev);
+	int err;
+
+	port->irq_misc = platform_get_irq_byname(pdev, "misc");
+	if (port->irq_misc <= 0) {
+		dev_err(dev, "Unable to find misc IRQ line\n");
+		return port->irq_misc;
+	}
+	err = devm_request_irq(dev, port->irq_misc,
+			       xilinx_pcie_intr_handler,
+			       IRQF_SHARED | IRQF_NO_THREAD,
+			       "xilinx-pcie", port);
+	if (err) {
+		dev_err(dev, "unable to request misc IRQ line %d\n",
+			port->irq_misc);
+		return err;
+	}
+
+	return 0;
+}
+
+static int xilinx_request_msi_irq(struct xilinx_pcie_port *port)
+{
+	struct device *dev = port->dev;
+	struct platform_device *pdev = to_platform_device(dev);
+
+	port->msi.irq_msi0 = platform_get_irq_byname(pdev, "msi0");
+	if (port->msi.irq_msi0 <= 0) {
+		dev_err(dev, "Unable to find msi0 IRQ line\n");
+		return port->msi.irq_msi0;
+	}
+
+	irq_set_chained_handler_and_data(port->msi.irq_msi0,
+					 xilinx_pcie_msi_handler_low,
+					 port);
+
+	port->msi.irq_msi1 = platform_get_irq_byname(pdev, "msi1");
+	if (port->msi.irq_msi1 <= 0) {
+		dev_err(dev, "Unable to find msi1 IRQ line\n");
+		return port->msi.irq_msi1;
+	}
+
+	irq_set_chained_handler_and_data(port->msi.irq_msi1,
+					 xilinx_pcie_msi_handler_high,
+					 port);
+
+	return 0;
+}
+
+/**
+ * xilinx_pcie_parse_dt - Parse Device tree
+ * @port: PCIe port information
+ *
+ * Return: '0' on success and error value on failure
+ */
+static int xilinx_pcie_parse_dt(struct xilinx_pcie_port *port)
+{
+	struct device *dev = port->dev;
+	struct device_node *node = dev->of_node;
+	struct resource regs;
+	const char *type;
+	int err, mode_val, val;
+
+	if (of_device_is_compatible(node, "xlnx,xdma-host-3.00"))
+		port->xdma_config = XDMA_ZYNQMP_PL;
+	else if (of_device_is_compatible(node, "xlnx,pcie-dma-versal-2.0"))
+		port->xdma_config = XDMA_VERSAL_PL;
+	else if (of_device_is_compatible(node, "xlnx,versal-cpm-host-1.00"))
+		port->xdma_config = XDMA_VERSAL_CPM;
+
+	if (port->xdma_config == XDMA_ZYNQMP_PL ||
+	    port->xdma_config == XDMA_VERSAL_PL) {
+		type = of_get_property(node, "device_type", NULL);
+		if (!type || strcmp(type, "pci")) {
+			dev_err(dev, "invalid \"device_type\" %s\n", type);
+			return -EINVAL;
+		}
+
+		err = of_address_to_resource(node, 0, &regs);
+		if (err) {
+			dev_err(dev, "missing \"reg\" property\n");
+			return err;
+		}
+
+		port->reg_base = devm_ioremap_resource(dev, &regs);
+		if (IS_ERR(port->reg_base))
+			return PTR_ERR(port->reg_base);
+
+		if (port->xdma_config == XDMA_ZYNQMP_PL) {
+			val = pcie_read(port, XILINX_PCIE_REG_BIR);
+			val = (val >> XILINX_PCIE_FIFO_SHIFT) & MSI_DECD_MODE;
+			mode_val = pcie_read(port, XILINX_PCIE_REG_VSEC) &
+					XILINX_PCIE_VSEC_REV_MASK;
+			mode_val = mode_val >> XILINX_PCIE_VSEC_REV_SHIFT;
+			if (mode_val && !val) {
+				port->msi_mode = MSI_DECD_MODE;
+				dev_info(dev, "Using MSI Decode mode\n");
+			} else {
+				port->msi_mode = MSI_FIFO_MODE;
+				dev_info(dev, "Using MSI FIFO mode\n");
+			}
+		}
+
+		if (port->xdma_config == XDMA_VERSAL_PL)
+			port->msi_mode = MSI_DECD_MODE;
+
+		if (port->msi_mode == MSI_DECD_MODE) {
+			err = xilinx_request_misc_irq(port);
+			if (err)
+				return err;
+
+			err = xilinx_request_msi_irq(port);
+			if (err)
+				return err;
+
+		} else if (port->msi_mode == MSI_FIFO_MODE) {
+			port->irq = irq_of_parse_and_map(node, 0);
+			if (!port->irq) {
+				dev_err(dev, "Unable to find IRQ line\n");
+				return -ENXIO;
+			}
+
+			err = devm_request_irq(dev, port->irq,
+					       xilinx_pcie_intr_handler,
+					       IRQF_SHARED | IRQF_NO_THREAD,
+					       "xilinx-pcie", port);
+			if (err) {
+				dev_err(dev, "unable to request irq %d\n",
+					port->irq);
+				return err;
+			}
+		}
+	} else if (port->xdma_config == XDMA_VERSAL_CPM) {
+		struct resource *res;
+		struct platform_device *pdev = to_platform_device(dev);
+
+		res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg");
+		port->reg_base = devm_ioremap_resource(dev, res);
+		if (IS_ERR(port->reg_base))
+			return PTR_ERR(port->reg_base);
+
+		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+						   "cpm_slcr");
+		port->cpm_base = devm_ioremap_resource(dev, res);
+		if (IS_ERR(port->cpm_base))
+			return PTR_ERR(port->cpm_base);
+
+		err = xilinx_request_misc_irq(port);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
+/**
+ * xilinx_pcie_probe - Probe function
+ * @pdev: Platform device pointer
+ *
+ * Return: '0' on success and error value on failure
+ */
+static int xilinx_pcie_probe(struct platform_device *pdev)
+{
+	struct xilinx_pcie_port *port;
+	struct device *dev = &pdev->dev;
+	struct pci_bus *bus;
+	struct pci_bus *child;
+	struct pci_host_bridge *bridge;
+	int err;
+	resource_size_t iobase = 0;
+	LIST_HEAD(res);
+
+	bridge = devm_pci_alloc_host_bridge(dev, sizeof(*port));
+	if (!bridge)
+		return -ENODEV;
+
+	port = pci_host_bridge_priv(bridge);
+
+	port->dev = dev;
+
+	err = xilinx_pcie_parse_dt(port);
+	if (err) {
+		dev_err(dev, "Parsing DT failed\n");
+		return err;
+	}
+
+	xilinx_pcie_init_port(port);
+
+	err = xilinx_pcie_init_irq_domain(port);
+	if (err) {
+		dev_err(dev, "Failed creating IRQ Domain\n");
+		return err;
+	}
+
+	err = devm_of_pci_get_host_bridge_resources(dev, 0, 0xff, &res,
+						    &iobase);
+	if (err) {
+		dev_err(dev, "Getting bridge resources failed\n");
+		return err;
+	}
+
+	err = devm_request_pci_bus_resources(dev, &res);
+	if (err)
+		goto error;
+
+	list_splice_init(&res, &bridge->windows);
+	bridge->dev.parent = dev;
+	bridge->sysdata = port;
+	bridge->busnr = port->root_busno;
+	bridge->ops = &xilinx_pcie_ops;
+	bridge->map_irq = of_irq_parse_and_map_pci;
+	bridge->swizzle_irq = pci_common_swizzle;
+
+	err = pci_scan_root_bus_bridge(bridge);
+	if (err)
+		goto error;
+
+	bus = bridge->bus;
+
+	pci_assign_unassigned_bus_resources(bus);
+	list_for_each_entry(child, &bus->children, node)
+		pcie_bus_configure_settings(child);
+	pci_bus_add_devices(bus);
+	return 0;
+
+error:
+	pci_free_resource_list(&res);
+	return err;
+}
+
+static const struct of_device_id xilinx_pcie_of_match[] = {
+	{ .compatible = "xlnx,xdma-host-3.00", },
+	{ .compatible = "xlnx,versal-cpm-host-1.00", },
+	{ .compatible = "xlnx,pcie-dma-versal-2.0", },
+	{}
+};
+
+static struct platform_driver xilinx_pcie_driver = {
+	.driver = {
+		.name = "xilinx-xdma-pcie",
+		.of_match_table = xilinx_pcie_of_match,
+		.suppress_bind_attrs = true,
+	},
+	.probe = xilinx_pcie_probe,
+};
+
+builtin_platform_driver(xilinx_pcie_driver);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/controller/pcie-xilinx-nwl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/controller/pcie-xilinx-nwl.c
@@ -6,6 +6,7 @@
  * (C) Copyright 2014 - 2015, Xilinx, Inc.
  */
 
+#include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
@@ -78,8 +79,8 @@
 #define MSGF_MISC_SR_NON_FATAL_DEV	BIT(22)
 #define MSGF_MISC_SR_FATAL_DEV		BIT(23)
 #define MSGF_MISC_SR_LINK_DOWN		BIT(24)
-#define MSGF_MSIC_SR_LINK_AUTO_BWIDTH	BIT(25)
-#define MSGF_MSIC_SR_LINK_BWIDTH	BIT(26)
+#define MSGF_MISC_SR_LINK_AUTO_BWIDTH	BIT(25)
+#define MSGF_MISC_SR_LINK_BWIDTH	BIT(26)
 
 #define MSGF_MISC_SR_MASKALL		(MSGF_MISC_SR_RXMSG_AVAIL | \
 					MSGF_MISC_SR_RXMSG_OVER | \
@@ -94,8 +95,8 @@
 					MSGF_MISC_SR_NON_FATAL_DEV | \
 					MSGF_MISC_SR_FATAL_DEV | \
 					MSGF_MISC_SR_LINK_DOWN | \
-					MSGF_MSIC_SR_LINK_AUTO_BWIDTH | \
-					MSGF_MSIC_SR_LINK_BWIDTH)
+					MSGF_MISC_SR_LINK_AUTO_BWIDTH | \
+					MSGF_MISC_SR_LINK_BWIDTH)
 
 /* Legacy interrupt status mask bits */
 #define MSGF_LEG_SR_INTA		BIT(0)
@@ -169,6 +170,7 @@
 	u8 root_busno;
 	struct nwl_msi msi;
 	struct irq_domain *legacy_irq_domain;
+	struct clk *clk;
 	raw_spinlock_t leg_mask_lock;
 };
 
@@ -306,10 +308,10 @@
 	if (misc_stat & MSGF_MISC_SR_FATAL_DEV)
 		dev_err(dev, "Fatal Error Detected\n");
 
-	if (misc_stat & MSGF_MSIC_SR_LINK_AUTO_BWIDTH)
+	if (misc_stat & MSGF_MISC_SR_LINK_AUTO_BWIDTH)
 		dev_info(dev, "Link Autonomous Bandwidth Management Status bit set\n");
 
-	if (misc_stat & MSGF_MSIC_SR_LINK_BWIDTH)
+	if (misc_stat & MSGF_MISC_SR_LINK_BWIDTH)
 		dev_info(dev, "Link Bandwidth Management Status bit set\n");
 
 	/* Clear misc interrupt status */
@@ -382,14 +384,12 @@
 
 static void nwl_mask_leg_irq(struct irq_data *data)
 {
-	struct irq_desc *desc = irq_to_desc(data->irq);
-	struct nwl_pcie *pcie;
+	struct nwl_pcie *pcie = irq_data_get_irq_chip_data(data);
 	unsigned long flags;
 	u32 mask;
 	u32 val;
 
-	pcie = irq_desc_get_chip_data(desc);
-	mask = 1 << (data->hwirq - 1);
+	mask = 1 << data->hwirq;
 	raw_spin_lock_irqsave(&pcie->leg_mask_lock, flags);
 	val = nwl_bridge_readl(pcie, MSGF_LEG_MASK);
 	nwl_bridge_writel(pcie, (val & (~mask)), MSGF_LEG_MASK);
@@ -398,14 +398,12 @@
 
 static void nwl_unmask_leg_irq(struct irq_data *data)
 {
-	struct irq_desc *desc = irq_to_desc(data->irq);
-	struct nwl_pcie *pcie;
+	struct nwl_pcie *pcie = irq_data_get_irq_chip_data(data);
 	unsigned long flags;
 	u32 mask;
 	u32 val;
 
-	pcie = irq_desc_get_chip_data(desc);
-	mask = 1 << (data->hwirq - 1);
+	mask = 1 << data->hwirq;
 	raw_spin_lock_irqsave(&pcie->leg_mask_lock, flags);
 	val = nwl_bridge_readl(pcie, MSGF_LEG_MASK);
 	nwl_bridge_writel(pcie, (val | mask), MSGF_LEG_MASK);
@@ -491,7 +489,7 @@
 
 	for (i = 0; i < nr_irqs; i++) {
 		irq_domain_set_info(domain, virq + i, bit + i, &nwl_irq_chip,
-				domain->host_data, handle_simple_irq,
+				    domain->host_data, handle_simple_irq,
 				NULL, NULL);
 	}
 	mutex_unlock(&msi->lock);
@@ -499,7 +497,7 @@
 }
 
 static void nwl_irq_domain_free(struct irq_domain *domain, unsigned int virq,
-					unsigned int nr_irqs)
+				unsigned int nr_irqs)
 {
 	struct irq_data *data = irq_domain_get_irq_data(domain, virq);
 	struct nwl_pcie *pcie = irq_data_get_irq_chip_data(data);
@@ -753,7 +751,6 @@
 	/* Enable all misc interrupts */
 	nwl_bridge_writel(pcie, MSGF_MISC_SR_MASKALL, MSGF_MISC_MASK);
 
-
 	/* Disable all legacy interrupts */
 	nwl_bridge_writel(pcie, (u32)~MSGF_LEG_SR_MASKALL, MSGF_LEG_MASK);
 
@@ -839,6 +836,16 @@
 		return err;
 	}
 
+	pcie->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(pcie->clk))
+		return PTR_ERR(pcie->clk);
+
+	err = clk_prepare_enable(pcie->clk);
+	if (err) {
+		dev_err(dev, "can't enable PCIe ref clock\n");
+		return err;
+	}
+
 	err = nwl_pcie_bridge_init(pcie);
 	if (err) {
 		dev_err(dev, "HW Initialization failed\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/controller/vmd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/controller/vmd.c
@@ -593,25 +593,41 @@
 			if (!membar2)
 				return -ENOMEM;
 			offset[0] = vmd->dev->resource[VMD_MEMBAR1].start -
-					readq(membar2 + MB2_SHADOW_OFFSET);
+					(readq(membar2 + MB2_SHADOW_OFFSET) &
+					 PCI_BASE_ADDRESS_MEM_MASK);
 			offset[1] = vmd->dev->resource[VMD_MEMBAR2].start -
-					readq(membar2 + MB2_SHADOW_OFFSET + 8);
+					(readq(membar2 + MB2_SHADOW_OFFSET + 8) &
+					 PCI_BASE_ADDRESS_MEM_MASK);
 			pci_iounmap(vmd->dev, membar2);
 		}
 	}
 
 	/*
 	 * Certain VMD devices may have a root port configuration option which
-	 * limits the bus range to between 0-127 or 128-255
+	 * limits the bus range to between 0-127, 128-255, or 224-255
 	 */
 	if (features & VMD_FEAT_HAS_BUS_RESTRICTIONS) {
-		u32 vmcap, vmconfig;
+		u16 reg16;
 
-		pci_read_config_dword(vmd->dev, PCI_REG_VMCAP, &vmcap);
-		pci_read_config_dword(vmd->dev, PCI_REG_VMCONFIG, &vmconfig);
-		if (BUS_RESTRICT_CAP(vmcap) &&
-		    (BUS_RESTRICT_CFG(vmconfig) == 0x1))
-			vmd->busn_start = 128;
+		pci_read_config_word(vmd->dev, PCI_REG_VMCAP, &reg16);
+		if (BUS_RESTRICT_CAP(reg16)) {
+			pci_read_config_word(vmd->dev, PCI_REG_VMCONFIG,
+					     &reg16);
+
+			switch (BUS_RESTRICT_CFG(reg16)) {
+			case 1:
+				vmd->busn_start = 128;
+				break;
+			case 2:
+				vmd->busn_start = 224;
+				break;
+			case 3:
+				pci_err(vmd->dev, "Unknown Bus Offset Setting\n");
+				return -ENODEV;
+			default:
+				break;
+			}
+		}
 	}
 
 	res = &vmd->dev->resource[VMD_CFGBAR];
@@ -678,9 +694,10 @@
 
 	vmd->irq_domain = pci_msi_create_irq_domain(fn, &vmd_msi_domain_info,
 						    x86_vector_domain);
-	irq_domain_free_fwnode(fn);
-	if (!vmd->irq_domain)
+	if (!vmd->irq_domain) {
+		irq_domain_free_fwnode(fn);
 		return -ENODEV;
+	}
 
 	pci_add_resource(&resources, &vmd->resources[0]);
 	pci_add_resource_offset(&resources, &vmd->resources[1], offset[0]);
@@ -691,6 +708,7 @@
 	if (!vmd->bus) {
 		pci_free_resource_list(&resources);
 		irq_domain_remove(vmd->irq_domain);
+		irq_domain_free_fwnode(fn);
 		return -ENODEV;
 	}
 
@@ -805,6 +823,7 @@
 static void vmd_remove(struct pci_dev *dev)
 {
 	struct vmd_dev *vmd = pci_get_drvdata(dev);
+	struct fwnode_handle *fn = vmd->irq_domain->fwnode;
 
 	sysfs_remove_link(&vmd->dev->dev.kobj, "domain");
 	pci_stop_root_bus(vmd->bus);
@@ -813,6 +832,7 @@
 	vmd_teardown_dma_ops(vmd);
 	vmd_detach_resources(vmd);
 	irq_domain_remove(vmd->irq_domain);
+	irq_domain_free_fwnode(fn);
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -854,6 +874,8 @@
 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VMD_28C0),
 		.driver_data = VMD_FEAT_HAS_MEMBAR_SHADOW |
 				VMD_FEAT_HAS_BUS_RESTRICTIONS,},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_VMD_9A0B),
+		.driver_data = VMD_FEAT_HAS_BUS_RESTRICTIONS,},
 	{0,}
 };
 MODULE_DEVICE_TABLE(pci, vmd_ids);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/ecam.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/ecam.c
@@ -164,4 +164,14 @@
 		.write		= pci_generic_config_write32,
 	}
 };
+
+/* ECAM ops for 32-bit read only (non-compliant) */
+struct pci_ecam_ops pci_32b_read_ops = {
+	.bus_shift	= 20,
+	.pci_ops	= {
+		.map_bus	= pci_ecam_map_bus,
+		.read		= pci_generic_config_read32,
+		.write		= pci_generic_config_write,
+	}
+};
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/endpoint/functions/pci-epf-test.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/endpoint/functions/pci-epf-test.c
@@ -604,6 +604,7 @@
 
 	ret = pci_epf_register_driver(&test_driver);
 	if (ret) {
+		destroy_workqueue(kpcitest_workqueue);
 		pr_err("Failed to register pci epf test driver --> %d\n", ret);
 		return ret;
 	}
@@ -614,6 +615,8 @@
 
 static void __exit pci_epf_test_exit(void)
 {
+	if (kpcitest_workqueue)
+		destroy_workqueue(kpcitest_workqueue);
 	pci_epf_unregister_driver(&test_driver);
 }
 module_exit(pci_epf_test_exit);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/endpoint/pci-epc-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/endpoint/pci-epc-core.c
@@ -578,7 +578,7 @@
 {
 	int r;
 
-	r = devres_destroy(dev, devm_pci_epc_release, devm_pci_epc_match,
+	r = devres_release(dev, devm_pci_epc_release, devm_pci_epc_match,
 			   epc);
 	dev_WARN_ONCE(dev, r, "couldn't find PCI EPC resource\n");
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/endpoint/pci-epc-mem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/endpoint/pci-epc-mem.c
@@ -79,6 +79,7 @@
 	mem->page_size = page_size;
 	mem->pages = pages;
 	mem->size = size;
+	mutex_init(&mem->lock);
 
 	epc->mem = mem;
 
@@ -122,7 +123,7 @@
 				     phys_addr_t *phys_addr, size_t size)
 {
 	int pageno;
-	void __iomem *virt_addr;
+	void __iomem *virt_addr = NULL;
 	struct pci_epc_mem *mem = epc->mem;
 	unsigned int page_shift = ilog2(mem->page_size);
 	int order;
@@ -130,15 +131,18 @@
 	size = ALIGN(size, mem->page_size);
 	order = pci_epc_mem_get_order(mem, size);
 
+	mutex_lock(&mem->lock);
 	pageno = bitmap_find_free_region(mem->bitmap, mem->pages, order);
 	if (pageno < 0)
-		return NULL;
+		goto ret;
 
 	*phys_addr = mem->phys_base + (pageno << page_shift);
 	virt_addr = ioremap(*phys_addr, size);
 	if (!virt_addr)
 		bitmap_release_region(mem->bitmap, pageno, order);
 
+ret:
+	mutex_unlock(&mem->lock);
 	return virt_addr;
 }
 EXPORT_SYMBOL_GPL(pci_epc_mem_alloc_addr);
@@ -164,7 +168,9 @@
 	pageno = (phys_addr - mem->phys_base) >> page_shift;
 	size = ALIGN(size, mem->page_size);
 	order = pci_epc_mem_get_order(mem, size);
+	mutex_lock(&mem->lock);
 	bitmap_release_region(mem->bitmap, pageno, order);
+	mutex_unlock(&mem->lock);
 }
 EXPORT_SYMBOL_GPL(pci_epc_mem_free_addr);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/hotplug/TODO
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/hotplug/TODO
@@ -40,9 +40,6 @@
 
 * The return value of pci_hp_register() is not checked.
 
-* iounmap(io_mem) is called in the error path of ebda_rsrc_controller()
-  and once more in the error path of its caller ibmphp_access_ebda().
-
 * The various slot data structures are difficult to follow and need to be
   simplified.  A lot of functions are too large and too complex, they need
   to be broken up into smaller, manageable pieces.  Negative examples are
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/hotplug/acpiphp_glue.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/hotplug/acpiphp_glue.c
@@ -122,13 +122,21 @@
 	struct acpiphp_context *context;
 
 	acpi_lock_hp_context();
+
 	context = acpiphp_get_context(adev);
-	if (!context || context->func.parent->is_going_away) {
-		acpi_unlock_hp_context();
-		return NULL;
+	if (!context)
+		goto unlock;
+
+	if (context->func.parent->is_going_away) {
+		acpiphp_put_context(context);
+		context = NULL;
+		goto unlock;
 	}
+
 	get_bridge(context->func.parent);
 	acpiphp_put_context(context);
+
+unlock:
 	acpi_unlock_hp_context();
 	return context;
 }
@@ -449,8 +457,15 @@
 
 	/* Scan non-hotplug bridges that need to be reconfigured */
 	for_each_pci_bridge(dev, bus) {
-		if (!hotplug_is_native(dev))
-			max = pci_scan_bridge(bus, dev, max, 1);
+		if (hotplug_is_native(dev))
+			continue;
+
+		max = pci_scan_bridge(bus, dev, max, 1);
+		if (dev->subordinate) {
+			pcibios_resource_survey_bus(dev->subordinate);
+			pci_bus_size_bridges(dev->subordinate);
+			pci_bus_assign_resources(dev->subordinate);
+		}
 	}
 }
 
@@ -480,7 +495,6 @@
 			if (PCI_SLOT(dev->devfn) == slot->device)
 				acpiphp_native_scan_bridge(dev);
 		}
-		pci_assign_unassigned_bridge_resources(bus->self);
 	} else {
 		LIST_HEAD(add_list);
 		int max, pass;
@@ -526,6 +540,7 @@
 			slot->flags &= ~SLOT_ENABLED;
 			continue;
 		}
+		pci_dev_put(dev);
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/hotplug/cpqphp_pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/hotplug/cpqphp_pci.c
@@ -135,11 +135,13 @@
 static int PCI_RefinedAccessConfig(struct pci_bus *bus, unsigned int devfn, u8 offset, u32 *value)
 {
 	u32 vendID = 0;
+	int ret;
 
-	if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &vendID) == -1)
-		return -1;
-	if (vendID == 0xffffffff)
-		return -1;
+	ret = pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &vendID);
+	if (ret != PCIBIOS_SUCCESSFUL)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	if (PCI_POSSIBLE_ERROR(vendID))
+		return PCIBIOS_DEVICE_NOT_FOUND;
 	return pci_bus_read_config_dword(bus, devfn, offset, value);
 }
 
@@ -200,13 +202,15 @@
 {
 	u16 tdevice;
 	u32 work;
+	int ret;
 	u8 tbus;
 
 	ctrl->pci_bus->number = bus_num;
 
 	for (tdevice = 0; tdevice < 0xFF; tdevice++) {
 		/* Scan for access first */
-		if (PCI_RefinedAccessConfig(ctrl->pci_bus, tdevice, 0x08, &work) == -1)
+		ret = PCI_RefinedAccessConfig(ctrl->pci_bus, tdevice, 0x08, &work);
+		if (ret)
 			continue;
 		dbg("Looking for nonbridge bus_num %d dev_num %d\n", bus_num, tdevice);
 		/* Yep we got one. Not a bridge ? */
@@ -218,7 +222,8 @@
 	}
 	for (tdevice = 0; tdevice < 0xFF; tdevice++) {
 		/* Scan for access first */
-		if (PCI_RefinedAccessConfig(ctrl->pci_bus, tdevice, 0x08, &work) == -1)
+		ret = PCI_RefinedAccessConfig(ctrl->pci_bus, tdevice, 0x08, &work);
+		if (ret)
 			continue;
 		dbg("Looking for bridge bus_num %d dev_num %d\n", bus_num, tdevice);
 		/* Yep we got one. bridge ? */
@@ -251,7 +256,7 @@
 			*dev_num = tdevice;
 			ctrl->pci_bus->number = tbus;
 			pci_bus_read_config_dword(ctrl->pci_bus, *dev_num, PCI_VENDOR_ID, &work);
-			if (!nobridge || (work == 0xffffffff))
+			if (!nobridge || PCI_POSSIBLE_ERROR(work))
 				return 0;
 
 			dbg("bus_num %d devfn %d\n", *bus_num, *dev_num);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/hotplug/ibmphp_ebda.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/hotplug/ibmphp_ebda.c
@@ -714,8 +714,7 @@
 		/* init hpc structure */
 		hpc_ptr = alloc_ebda_hpc(slot_num, bus_num);
 		if (!hpc_ptr) {
-			rc = -ENOMEM;
-			goto error_no_hpc;
+			return -ENOMEM;
 		}
 		hpc_ptr->ctlr_id = ctlr_id;
 		hpc_ptr->ctlr_relative_id = ctlr;
@@ -910,8 +909,6 @@
 	kfree(tmp_slot);
 error_no_slot:
 	free_ebda_hpc(hpc_ptr);
-error_no_hpc:
-	iounmap(io_mem);
 	return rc;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/hotplug/pciehp.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/hotplug/pciehp.h
@@ -72,6 +72,9 @@
  * @reset_lock: prevents access to the Data Link Layer Link Active bit in the
  *	Link Status register and to the Presence Detect State bit in the Slot
  *	Status register during a slot reset which may cause them to flap
+ * @depth: Number of additional hotplug ports in the path to the root bus,
+ *	used as lock subclass for @reset_lock
+ * @ist_running: flag to keep user request waiting while IRQ thread is running
  * @request_result: result of last user request submitted to the IRQ thread
  * @requester: wait queue to wake up on completion of user request,
  *	used for synchronous slot enable/disable request via sysfs
@@ -101,6 +104,8 @@
 
 	struct hotplug_slot hotplug_slot;	/* hotplug core interface */
 	struct rw_semaphore reset_lock;
+	unsigned int depth;
+	unsigned int ist_running;
 	int request_result;
 	wait_queue_head_t requester;
 };
@@ -172,10 +177,10 @@
 
 void pciehp_get_latch_status(struct controller *ctrl, u8 *status);
 int pciehp_query_power_fault(struct controller *ctrl);
-bool pciehp_card_present(struct controller *ctrl);
-bool pciehp_card_present_or_link_active(struct controller *ctrl);
+int pciehp_card_present(struct controller *ctrl);
+int pciehp_card_present_or_link_active(struct controller *ctrl);
 int pciehp_check_link_status(struct controller *ctrl);
-bool pciehp_check_link_active(struct controller *ctrl);
+int pciehp_check_link_active(struct controller *ctrl);
 void pciehp_release_ctrl(struct controller *ctrl);
 
 int pciehp_sysfs_enable_slot(struct hotplug_slot *hotplug_slot);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/hotplug/pciehp_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/hotplug/pciehp_core.c
@@ -139,10 +139,15 @@
 {
 	struct controller *ctrl = to_ctrl(hotplug_slot);
 	struct pci_dev *pdev = ctrl->pcie->port;
+	int ret;
 
 	pci_config_pm_runtime_get(pdev);
-	*value = pciehp_card_present_or_link_active(ctrl);
+	ret = pciehp_card_present_or_link_active(ctrl);
 	pci_config_pm_runtime_put(pdev);
+	if (ret < 0)
+		return ret;
+
+	*value = ret;
 	return 0;
 }
 
@@ -158,13 +163,13 @@
  */
 static void pciehp_check_presence(struct controller *ctrl)
 {
-	bool occupied;
+	int occupied;
 
-	down_read(&ctrl->reset_lock);
+	down_read_nested(&ctrl->reset_lock, ctrl->depth);
 	mutex_lock(&ctrl->state_lock);
 
 	occupied = pciehp_card_present_or_link_active(ctrl);
-	if ((occupied && (ctrl->state == OFF_STATE ||
+	if ((occupied > 0 && (ctrl->state == OFF_STATE ||
 			  ctrl->state == BLINKINGON_STATE)) ||
 	    (!occupied && (ctrl->state == ON_STATE ||
 			   ctrl->state == BLINKINGOFF_STATE)))
@@ -253,7 +258,7 @@
 	return pcie_ports_native || host->native_pme;
 }
 
-static int pciehp_suspend(struct pcie_device *dev)
+static void pciehp_disable_interrupt(struct pcie_device *dev)
 {
 	/*
 	 * Disable hotplug interrupt so that it does not trigger
@@ -261,7 +266,19 @@
 	 */
 	if (pme_is_native(dev))
 		pcie_disable_interrupt(get_service_data(dev));
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int pciehp_suspend(struct pcie_device *dev)
+{
+	/*
+	 * If the port is already runtime suspended we can keep it that
+	 * way.
+	 */
+	if (dev_pm_smart_suspend_and_suspended(&dev->port->dev))
+		return 0;
 
+	pciehp_disable_interrupt(dev);
 	return 0;
 }
 
@@ -279,6 +296,7 @@
 
 	return 0;
 }
+#endif
 
 static int pciehp_resume(struct pcie_device *dev)
 {
@@ -292,6 +310,12 @@
 	return 0;
 }
 
+static int pciehp_runtime_suspend(struct pcie_device *dev)
+{
+	pciehp_disable_interrupt(dev);
+	return 0;
+}
+
 static int pciehp_runtime_resume(struct pcie_device *dev)
 {
 	struct controller *ctrl = get_service_data(dev);
@@ -318,10 +342,12 @@
 	.remove		= pciehp_remove,
 
 #ifdef	CONFIG_PM
+#ifdef	CONFIG_PM_SLEEP
 	.suspend	= pciehp_suspend,
 	.resume_noirq	= pciehp_resume_noirq,
 	.resume		= pciehp_resume,
-	.runtime_suspend = pciehp_suspend,
+#endif
+	.runtime_suspend = pciehp_runtime_suspend,
 	.runtime_resume	= pciehp_runtime_resume,
 #endif	/* PM */
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/hotplug/pciehp_ctrl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/hotplug/pciehp_ctrl.c
@@ -226,7 +226,7 @@
 
 void pciehp_handle_presence_or_link_change(struct controller *ctrl, u32 events)
 {
-	bool present, link_active;
+	int present, link_active;
 
 	/*
 	 * If the slot is on and presence or link has changed, turn it off.
@@ -257,7 +257,15 @@
 	mutex_lock(&ctrl->state_lock);
 	present = pciehp_card_present(ctrl);
 	link_active = pciehp_check_link_active(ctrl);
-	if (!present && !link_active) {
+	if (present <= 0 && link_active <= 0) {
+		if (ctrl->state == BLINKINGON_STATE) {
+			ctrl->state = OFF_STATE;
+			cancel_delayed_work(&ctrl->button_work);
+			pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF,
+					      INDICATOR_NOOP);
+			ctrl_info(ctrl, "Slot(%s): Card not present\n",
+				  slot_name(ctrl));
+		}
 		mutex_unlock(&ctrl->state_lock);
 		return;
 	}
@@ -375,7 +383,8 @@
 		ctrl->request_result = -ENODEV;
 		pciehp_request(ctrl, PCI_EXP_SLTSTA_PDC);
 		wait_event(ctrl->requester,
-			   !atomic_read(&ctrl->pending_events));
+			   !atomic_read(&ctrl->pending_events) &&
+			   !ctrl->ist_running);
 		return ctrl->request_result;
 	case POWERON_STATE:
 		ctrl_info(ctrl, "Slot(%s): Already in powering on state\n",
@@ -408,7 +417,8 @@
 		mutex_unlock(&ctrl->state_lock);
 		pciehp_request(ctrl, DISABLE_SLOT);
 		wait_event(ctrl->requester,
-			   !atomic_read(&ctrl->pending_events));
+			   !atomic_read(&ctrl->pending_events) &&
+			   !ctrl->ist_running);
 		return ctrl->request_result;
 	case POWEROFF_STATE:
 		ctrl_info(ctrl, "Slot(%s): Already in powering off state\n",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/hotplug/pciehp_hpc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/hotplug/pciehp_hpc.c
@@ -79,6 +79,8 @@
 		if (slot_status & PCI_EXP_SLTSTA_CC) {
 			pcie_capability_write_word(pdev, PCI_EXP_SLTSTA,
 						   PCI_EXP_SLTSTA_CC);
+			ctrl->cmd_busy = 0;
+			smp_mb();
 			return 1;
 		}
 		if (timeout < 0)
@@ -201,17 +203,29 @@
 	pcie_do_write_cmd(ctrl, cmd, mask, false);
 }
 
-bool pciehp_check_link_active(struct controller *ctrl)
+/**
+ * pciehp_check_link_active() - Is the link active
+ * @ctrl: PCIe hotplug controller
+ *
+ * Check whether the downstream link is currently active. Note it is
+ * possible that the card is removed immediately after this so the
+ * caller may need to take it into account.
+ *
+ * If the hotplug controller itself is not available anymore returns
+ * %-ENODEV.
+ */
+int pciehp_check_link_active(struct controller *ctrl)
 {
 	struct pci_dev *pdev = ctrl_dev(ctrl);
 	u16 lnk_status;
-	bool ret;
+	int ret;
 
-	pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status);
-	ret = !!(lnk_status & PCI_EXP_LNKSTA_DLLLA);
+	ret = pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status);
+	if (ret == PCIBIOS_DEVICE_NOT_FOUND || lnk_status == (u16)~0)
+		return -ENODEV;
 
-	if (ret)
-		ctrl_dbg(ctrl, "%s: lnk_status = %x\n", __func__, lnk_status);
+	ret = !!(lnk_status & PCI_EXP_LNKSTA_DLLLA);
+	ctrl_dbg(ctrl, "%s: lnk_status = %x\n", __func__, lnk_status);
 
 	return ret;
 }
@@ -279,17 +293,11 @@
 static int __pciehp_link_set(struct controller *ctrl, bool enable)
 {
 	struct pci_dev *pdev = ctrl_dev(ctrl);
-	u16 lnk_ctrl;
 
-	pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &lnk_ctrl);
+	pcie_capability_clear_and_set_word(pdev, PCI_EXP_LNKCTL,
+					   PCI_EXP_LNKCTL_LD,
+					   enable ? 0 : PCI_EXP_LNKCTL_LD);
 
-	if (enable)
-		lnk_ctrl &= ~PCI_EXP_LNKCTL_LD;
-	else
-		lnk_ctrl |= PCI_EXP_LNKCTL_LD;
-
-	pcie_capability_write_word(pdev, PCI_EXP_LNKCTL, lnk_ctrl);
-	ctrl_dbg(ctrl, "%s: lnk_ctrl = %x\n", __func__, lnk_ctrl);
 	return 0;
 }
 
@@ -373,13 +381,29 @@
 	*status = !!(slot_status & PCI_EXP_SLTSTA_MRLSS);
 }
 
-bool pciehp_card_present(struct controller *ctrl)
+/**
+ * pciehp_card_present() - Is the card present
+ * @ctrl: PCIe hotplug controller
+ *
+ * Function checks whether the card is currently present in the slot and
+ * in that case returns true. Note it is possible that the card is
+ * removed immediately after the check so the caller may need to take
+ * this into account.
+ *
+ * It the hotplug controller itself is not available anymore returns
+ * %-ENODEV.
+ */
+int pciehp_card_present(struct controller *ctrl)
 {
 	struct pci_dev *pdev = ctrl_dev(ctrl);
 	u16 slot_status;
+	int ret;
 
-	pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status);
-	return slot_status & PCI_EXP_SLTSTA_PDS;
+	ret = pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status);
+	if (ret == PCIBIOS_DEVICE_NOT_FOUND || slot_status == (u16)~0)
+		return -ENODEV;
+
+	return !!(slot_status & PCI_EXP_SLTSTA_PDS);
 }
 
 /**
@@ -390,10 +414,19 @@
  * Presence Detect State bit, this helper also returns true if the Link Active
  * bit is set.  This is a concession to broken hotplug ports which hardwire
  * Presence Detect State to zero, such as Wilocity's [1ae9:0200].
+ *
+ * Returns: %1 if the slot is occupied and %0 if it is not. If the hotplug
+ *	    port is not present anymore returns %-ENODEV.
  */
-bool pciehp_card_present_or_link_active(struct controller *ctrl)
+int pciehp_card_present_or_link_active(struct controller *ctrl)
 {
-	return pciehp_card_present(ctrl) || pciehp_check_link_active(ctrl);
+	int ret;
+
+	ret = pciehp_card_present(ctrl);
+	if (ret)
+		return ret;
+
+	return pciehp_check_link_active(ctrl);
 }
 
 int pciehp_query_power_fault(struct controller *ctrl)
@@ -492,7 +525,7 @@
 	struct controller *ctrl = (struct controller *)dev_id;
 	struct pci_dev *pdev = ctrl_dev(ctrl);
 	struct device *parent = pdev->dev.parent;
-	u16 status, events;
+	u16 status, events = 0;
 
 	/*
 	 * Interrupts only occur in D3hot or shallower and only if enabled
@@ -517,6 +550,7 @@
 		}
 	}
 
+read_status:
 	pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &status);
 	if (status == (u16) ~0) {
 		ctrl_info(ctrl, "%s: no response from device\n", __func__);
@@ -529,24 +563,39 @@
 	 * Slot Status contains plain status bits as well as event
 	 * notification bits; right now we only want the event bits.
 	 */
-	events = status & (PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD |
-			   PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_CC |
-			   PCI_EXP_SLTSTA_DLLSC);
+	status &= PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD |
+		  PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_CC |
+		  PCI_EXP_SLTSTA_DLLSC;
 
 	/*
 	 * If we've already reported a power fault, don't report it again
 	 * until we've done something to handle it.
 	 */
 	if (ctrl->power_fault_detected)
-		events &= ~PCI_EXP_SLTSTA_PFD;
+		status &= ~PCI_EXP_SLTSTA_PFD;
+	else if (status & PCI_EXP_SLTSTA_PFD)
+		ctrl->power_fault_detected = true;
 
+	events |= status;
 	if (!events) {
 		if (parent)
 			pm_runtime_put(parent);
 		return IRQ_NONE;
 	}
 
-	pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, events);
+	if (status) {
+		pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, status);
+
+		/*
+		 * In MSI mode, all event bits must be zero before the port
+		 * will send a new interrupt (PCIe Base Spec r5.0 sec 6.7.3.4).
+		 * So re-read the Slot Status register in case a bit was set
+		 * between read and write.
+		 */
+		if (pci_dev_msi_enabled(pdev) && !pciehp_poll_mode)
+			goto read_status;
+	}
+
 	ctrl_dbg(ctrl, "pending interrupts %#06x from Slot Status\n", events);
 	if (parent)
 		pm_runtime_put(parent);
@@ -583,23 +632,22 @@
 	irqreturn_t ret;
 	u32 events;
 
+	ctrl->ist_running = true;
 	pci_config_pm_runtime_get(pdev);
 
 	/* rerun pciehp_isr() if the port was inaccessible on interrupt */
 	if (atomic_fetch_and(~RERUN_ISR, &ctrl->pending_events) & RERUN_ISR) {
 		ret = pciehp_isr(irq, dev_id);
 		enable_irq(irq);
-		if (ret != IRQ_WAKE_THREAD) {
-			pci_config_pm_runtime_put(pdev);
-			return ret;
-		}
+		if (ret != IRQ_WAKE_THREAD)
+			goto out;
 	}
 
 	synchronize_hardirq(irq);
 	events = atomic_xchg(&ctrl->pending_events, 0);
 	if (!events) {
-		pci_config_pm_runtime_put(pdev);
-		return IRQ_NONE;
+		ret = IRQ_NONE;
+		goto out;
 	}
 
 	/* Check Attention Button Pressed */
@@ -610,8 +658,7 @@
 	}
 
 	/* Check Power Fault Detected */
-	if ((events & PCI_EXP_SLTSTA_PFD) && !ctrl->power_fault_detected) {
-		ctrl->power_fault_detected = 1;
+	if (events & PCI_EXP_SLTSTA_PFD) {
 		ctrl_err(ctrl, "Slot(%s): Power fault\n", slot_name(ctrl));
 		pciehp_set_indicators(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF,
 				      PCI_EXP_SLTCTL_ATTN_IND_ON);
@@ -621,16 +668,19 @@
 	 * Disable requests have higher priority than Presence Detect Changed
 	 * or Data Link Layer State Changed events.
 	 */
-	down_read(&ctrl->reset_lock);
+	down_read_nested(&ctrl->reset_lock, ctrl->depth);
 	if (events & DISABLE_SLOT)
 		pciehp_handle_disable_request(ctrl);
 	else if (events & (PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_DLLSC))
 		pciehp_handle_presence_or_link_change(ctrl, events);
 	up_read(&ctrl->reset_lock);
 
+	ret = IRQ_HANDLED;
+out:
 	pci_config_pm_runtime_put(pdev);
+	ctrl->ist_running = false;
 	wake_up(&ctrl->requester);
-	return IRQ_HANDLED;
+	return ret;
 }
 
 static int pciehp_poll(void *data)
@@ -715,7 +765,9 @@
 {
 	u16 mask;
 
-	mask = PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_DLLSCE;
+	mask = PCI_EXP_SLTCTL_DLLSCE;
+	if (!pciehp_poll_mode)
+		mask |= PCI_EXP_SLTCTL_HPIE;
 	pcie_write_cmd(ctrl, mask, mask);
 }
 
@@ -752,7 +804,7 @@
 	if (probe)
 		return 0;
 
-	down_write(&ctrl->reset_lock);
+	down_write_nested(&ctrl->reset_lock, ctrl->depth);
 
 	if (!ATTN_BUTTN(ctrl)) {
 		ctrl_mask |= PCI_EXP_SLTCTL_PDCE;
@@ -808,6 +860,20 @@
 
 #define FLAG(x, y)	(((x) & (y)) ? '+' : '-')
 
+static inline int pcie_hotplug_depth(struct pci_dev *dev)
+{
+	struct pci_bus *bus = dev->bus;
+	int depth = 0;
+
+	while (bus->parent) {
+		bus = bus->parent;
+		if (bus->self && bus->self->is_hotplug_bridge)
+			depth++;
+	}
+
+	return depth;
+}
+
 struct controller *pcie_init(struct pcie_device *dev)
 {
 	struct controller *ctrl;
@@ -821,6 +887,7 @@
 		return NULL;
 
 	ctrl->pcie = dev;
+	ctrl->depth = pcie_hotplug_depth(dev->port);
 	pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP, &slot_cap);
 
 	if (pdev->hotplug_user_indicators)
@@ -903,6 +970,8 @@
 }
 DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_INTEL, PCI_ANY_ID,
 			      PCI_CLASS_BRIDGE_PCI, 8, quirk_cmd_compl);
+DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_QCOM, 0x0110,
+			      PCI_CLASS_BRIDGE_PCI, 8, quirk_cmd_compl);
 DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_QCOM, 0x0400,
 			      PCI_CLASS_BRIDGE_PCI, 8, quirk_cmd_compl);
 DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_QCOM, 0x0401,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/hotplug/pciehp_pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/hotplug/pciehp_pci.c
@@ -63,7 +63,14 @@
 
 	pci_assign_unassigned_bridge_resources(bridge);
 	pcie_bus_configure_settings(parent);
+
+	/*
+	 * Release reset_lock during driver binding
+	 * to avoid AB-BA deadlock with device_lock.
+	 */
+	up_read(&ctrl->reset_lock);
 	pci_bus_add_devices(parent);
+	down_read_nested(&ctrl->reset_lock, ctrl->depth);
 
  out:
 	pci_unlock_rescan_remove();
@@ -104,7 +111,15 @@
 	list_for_each_entry_safe_reverse(dev, temp, &parent->devices,
 					 bus_list) {
 		pci_dev_get(dev);
+
+		/*
+		 * Release reset_lock during driver unbinding
+		 * to avoid AB-BA deadlock with device_lock.
+		 */
+		up_read(&ctrl->reset_lock);
 		pci_stop_and_remove_bus_device(dev);
+		down_read_nested(&ctrl->reset_lock, ctrl->depth);
+
 		/*
 		 * Ensure that no new Requests will be generated from
 		 * the device.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/hotplug/pnv_php.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/hotplug/pnv_php.c
@@ -18,6 +18,9 @@
 #define DRIVER_AUTHOR	"Gavin Shan, IBM Corporation"
 #define DRIVER_DESC	"PowerPC PowerNV PCI Hotplug Driver"
 
+#define SLOT_WARN(sl, x...) \
+	((sl)->pdev ? pci_warn((sl)->pdev, x) : dev_warn(&(sl)->bus->dev, x))
+
 struct pnv_php_event {
 	bool			added;
 	struct pnv_php_slot	*php_slot;
@@ -35,7 +38,6 @@
 				bool disable_device)
 {
 	struct pci_dev *pdev = php_slot->pdev;
-	int irq = php_slot->irq;
 	u16 ctrl;
 
 	if (php_slot->irq > 0) {
@@ -54,7 +56,7 @@
 		php_slot->wq = NULL;
 	}
 
-	if (disable_device || irq > 0) {
+	if (disable_device) {
 		if (pdev->msix_enabled)
 			pci_disable_msix(pdev);
 		else if (pdev->msi_enabled)
@@ -151,17 +153,11 @@
 static void pnv_php_detach_device_nodes(struct device_node *parent)
 {
 	struct device_node *dn;
-	int refcount;
 
 	for_each_child_of_node(parent, dn) {
 		pnv_php_detach_device_nodes(dn);
 
 		of_node_put(dn);
-		refcount = kref_read(&dn->kobj.kref);
-		if (refcount != 1)
-			pr_warn("Invalid refcount %d on <%pOF>\n",
-				refcount, dn);
-
 		of_detach_node(dn);
 	}
 }
@@ -271,7 +267,7 @@
 
 	ret = pnv_pci_get_device_tree(php_slot->dn->phandle, fdt1, 0x10000);
 	if (ret) {
-		pci_warn(php_slot->pdev, "Error %d getting FDT blob\n", ret);
+		SLOT_WARN(php_slot, "Error %d getting FDT blob\n", ret);
 		goto free_fdt1;
 	}
 
@@ -285,7 +281,7 @@
 	dt = of_fdt_unflatten_tree(fdt, php_slot->dn, NULL);
 	if (!dt) {
 		ret = -EINVAL;
-		pci_warn(php_slot->pdev, "Cannot unflatten FDT\n");
+		SLOT_WARN(php_slot, "Cannot unflatten FDT\n");
 		goto free_fdt;
 	}
 
@@ -295,15 +291,15 @@
 	ret = pnv_php_populate_changeset(&php_slot->ocs, php_slot->dn);
 	if (ret) {
 		pnv_php_reverse_nodes(php_slot->dn);
-		pci_warn(php_slot->pdev, "Error %d populating changeset\n",
-			 ret);
+		SLOT_WARN(php_slot, "Error %d populating changeset\n",
+			  ret);
 		goto free_dt;
 	}
 
 	php_slot->dn->child = NULL;
 	ret = of_changeset_apply(&php_slot->ocs);
 	if (ret) {
-		pci_warn(php_slot->pdev, "Error %d applying changeset\n", ret);
+		SLOT_WARN(php_slot, "Error %d applying changeset\n", ret);
 		goto destroy_changeset;
 	}
 
@@ -342,18 +338,19 @@
 	ret = pnv_pci_set_power_state(php_slot->id, state, &msg);
 	if (ret > 0) {
 		if (be64_to_cpu(msg.params[1]) != php_slot->dn->phandle	||
-		    be64_to_cpu(msg.params[2]) != state			||
-		    be64_to_cpu(msg.params[3]) != OPAL_SUCCESS) {
-			pci_warn(php_slot->pdev, "Wrong msg (%lld, %lld, %lld)\n",
-				 be64_to_cpu(msg.params[1]),
-				 be64_to_cpu(msg.params[2]),
-				 be64_to_cpu(msg.params[3]));
+		    be64_to_cpu(msg.params[2]) != state) {
+			SLOT_WARN(php_slot, "Wrong msg (%lld, %lld, %lld)\n",
+				  be64_to_cpu(msg.params[1]),
+				  be64_to_cpu(msg.params[2]),
+				  be64_to_cpu(msg.params[3]));
 			return -ENOMSG;
 		}
+		if (be64_to_cpu(msg.params[3]) != OPAL_SUCCESS) {
+			ret = -ENODEV;
+			goto error;
+		}
 	} else if (ret < 0) {
-		pci_warn(php_slot->pdev, "Error %d powering %s\n",
-			 ret, (state == OPAL_PCI_SLOT_POWER_ON) ? "on" : "off");
-		return ret;
+		goto error;
 	}
 
 	if (state == OPAL_PCI_SLOT_POWER_OFF || state == OPAL_PCI_SLOT_OFFLINE)
@@ -362,6 +359,11 @@
 		ret = pnv_php_add_devtree(php_slot);
 
 	return ret;
+
+error:
+	SLOT_WARN(php_slot, "Error %d powering %s\n",
+		  ret, (state == OPAL_PCI_SLOT_POWER_ON) ? "on" : "off");
+	return ret;
 }
 EXPORT_SYMBOL_GPL(pnv_php_set_slot_power_state);
 
@@ -378,8 +380,8 @@
 	 */
 	ret = pnv_pci_get_power_state(php_slot->id, &power_state);
 	if (ret) {
-		pci_warn(php_slot->pdev, "Error %d getting power status\n",
-			 ret);
+		SLOT_WARN(php_slot, "Error %d getting power status\n",
+			  ret);
 	} else {
 		*state = power_state;
 	}
@@ -402,7 +404,7 @@
 		*state = presence;
 		ret = 0;
 	} else {
-		pci_warn(php_slot->pdev, "Error %d getting presence\n", ret);
+		SLOT_WARN(php_slot, "Error %d getting presence\n", ret);
 	}
 
 	return ret;
@@ -566,7 +568,13 @@
 	struct pnv_php_slot *php_slot = to_pnv_php_slot(slot);
 	int ret;
 
-	if (php_slot->state != PNV_PHP_STATE_POPULATED)
+	/*
+	 * Allow to disable a slot already in the registered state to
+	 * cover cases where the slot couldn't be enabled and never
+	 * reached the populated state
+	 */
+	if (php_slot->state != PNV_PHP_STATE_POPULATED &&
+	    php_slot->state != PNV_PHP_STATE_REGISTERED)
 		return 0;
 
 	/* Remove all devices behind the slot */
@@ -675,7 +683,7 @@
 	ret = pci_hp_register(&php_slot->slot, php_slot->bus,
 			      php_slot->slot_no, php_slot->name);
 	if (ret) {
-		pci_warn(php_slot->pdev, "Error %d registering slot\n", ret);
+		SLOT_WARN(php_slot, "Error %d registering slot\n", ret);
 		return ret;
 	}
 
@@ -728,7 +736,7 @@
 	/* Enable MSIx */
 	ret = pci_enable_msix_exact(pdev, &entry, 1);
 	if (ret) {
-		pci_warn(pdev, "Error %d enabling MSIx\n", ret);
+		SLOT_WARN(php_slot, "Error %d enabling MSIx\n", ret);
 		return ret;
 	}
 
@@ -778,8 +786,9 @@
 		   (sts & PCI_EXP_SLTSTA_PDC)) {
 		ret = pnv_pci_get_presence_state(php_slot->id, &presence);
 		if (ret) {
-			pci_warn(pdev, "PCI slot [%s] error %d getting presence (0x%04x), to retry the operation.\n",
-				 php_slot->name, ret, sts);
+			SLOT_WARN(php_slot,
+				  "PCI slot [%s] error %d getting presence (0x%04x), to retry the operation.\n",
+				  php_slot->name, ret, sts);
 			return IRQ_HANDLED;
 		}
 
@@ -809,8 +818,9 @@
 	 */
 	event = kzalloc(sizeof(*event), GFP_ATOMIC);
 	if (!event) {
-		pci_warn(pdev, "PCI slot [%s] missed hotplug event 0x%04x\n",
-			 php_slot->name, sts);
+		SLOT_WARN(php_slot,
+			  "PCI slot [%s] missed hotplug event 0x%04x\n",
+			  php_slot->name, sts);
 		return IRQ_HANDLED;
 	}
 
@@ -834,7 +844,7 @@
 	/* Allocate workqueue */
 	php_slot->wq = alloc_workqueue("pciehp-%s", 0, 0, php_slot->name);
 	if (!php_slot->wq) {
-		pci_warn(pdev, "Cannot alloc workqueue\n");
+		SLOT_WARN(php_slot, "Cannot alloc workqueue\n");
 		pnv_php_disable_irq(php_slot, true);
 		return;
 	}
@@ -858,7 +868,7 @@
 			  php_slot->name, php_slot);
 	if (ret) {
 		pnv_php_disable_irq(php_slot, true);
-		pci_warn(pdev, "Error %d enabling IRQ %d\n", ret, irq);
+		SLOT_WARN(php_slot, "Error %d enabling IRQ %d\n", ret, irq);
 		return;
 	}
 
@@ -894,7 +904,7 @@
 
 	ret = pci_enable_device(pdev);
 	if (ret) {
-		pci_warn(pdev, "Error %d enabling device\n", ret);
+		SLOT_WARN(php_slot, "Error %d enabling device\n", ret);
 		return;
 	}
 
@@ -1009,6 +1019,8 @@
 	for_each_compatible_node(dn, NULL, "ibm,ioda3-phb")
 		pnv_php_register(dn);
 
+	for_each_compatible_node(dn, NULL, "ibm,ioda2-npu2-opencapi-phb")
+		pnv_php_register_one(dn); /* slot directly under the PHB */
 	return 0;
 }
 
@@ -1021,6 +1033,9 @@
 
 	for_each_compatible_node(dn, NULL, "ibm,ioda3-phb")
 		pnv_php_unregister(dn);
+
+	for_each_compatible_node(dn, NULL, "ibm,ioda2-npu2-opencapi-phb")
+		pnv_php_unregister_one(dn); /* slot directly under the PHB */
 }
 
 module_init(pnv_php_init);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/hotplug/rpadlpar_sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/hotplug/rpadlpar_sysfs.c
@@ -34,12 +34,11 @@
 	if (nbytes >= MAX_DRC_NAME_LEN)
 		return 0;
 
-	memcpy(drc_name, buf, nbytes);
+	strscpy(drc_name, buf, nbytes + 1);
 
 	end = strchr(drc_name, '\n');
-	if (!end)
-		end = &drc_name[nbytes];
-	*end = '\0';
+	if (end)
+		*end = '\0';
 
 	rc = dlpar_add_slot(drc_name);
 	if (rc)
@@ -65,12 +64,11 @@
 	if (nbytes >= MAX_DRC_NAME_LEN)
 		return 0;
 
-	memcpy(drc_name, buf, nbytes);
+	strscpy(drc_name, buf, nbytes + 1);
 
 	end = strchr(drc_name, '\n');
-	if (!end)
-		end = &drc_name[nbytes];
-	*end = '\0';
+	if (end)
+		*end = '\0';
 
 	rc = dlpar_remove_slot(drc_name);
 	if (rc)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/hotplug/rpaphp_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/hotplug/rpaphp_core.c
@@ -154,11 +154,11 @@
 	return speed;
 }
 
-static int get_children_props(struct device_node *dn, const int **drc_indexes,
-		const int **drc_names, const int **drc_types,
-		const int **drc_power_domains)
+static int get_children_props(struct device_node *dn, const __be32 **drc_indexes,
+			      const __be32 **drc_names, const __be32 **drc_types,
+			      const __be32 **drc_power_domains)
 {
-	const int *indexes, *names, *types, *domains;
+	const __be32 *indexes, *names, *types, *domains;
 
 	indexes = of_get_property(dn, "ibm,drc-indexes", NULL);
 	names = of_get_property(dn, "ibm,drc-names", NULL);
@@ -194,8 +194,8 @@
 				char *drc_type, unsigned int my_index)
 {
 	char *name_tmp, *type_tmp;
-	const int *indexes, *names;
-	const int *types, *domains;
+	const __be32 *indexes, *names;
+	const __be32 *types, *domains;
 	int i, rc;
 
 	rc = get_children_props(dn->parent, &indexes, &names, &types, &domains);
@@ -208,7 +208,7 @@
 
 	/* Iterate through parent properties, looking for my-drc-index */
 	for (i = 0; i < be32_to_cpu(indexes[0]); i++) {
-		if ((unsigned int) indexes[i + 1] == my_index)
+		if (be32_to_cpu(indexes[i + 1]) == my_index)
 			break;
 
 		name_tmp += (strlen(name_tmp) + 1);
@@ -239,6 +239,8 @@
 	value = of_prop_next_u32(info, NULL, &entries);
 	if (!value)
 		return -EINVAL;
+	else
+		value++;
 
 	for (j = 0; j < entries; j++) {
 		of_read_drc_info_cell(&info, &value, &drc);
@@ -246,9 +248,10 @@
 		/* Should now know end of current entry */
 
 		/* Found it */
-		if (my_index <= drc.last_drc_index) {
+		if (my_index >= drc.drc_index_start && my_index <= drc.last_drc_index) {
+			int index = my_index - drc.drc_index_start;
 			sprintf(cell_drc_name, "%s%d", drc.drc_name_prefix,
-				my_index);
+				drc.drc_name_suffix_start + index);
 			break;
 		}
 	}
@@ -265,7 +268,7 @@
 int rpaphp_check_drc_props(struct device_node *dn, char *drc_name,
 			char *drc_type)
 {
-	const unsigned int *my_index;
+	const __be32 *my_index;
 
 	my_index = of_get_property(dn, "ibm,my-drc-index", NULL);
 	if (!my_index) {
@@ -273,12 +276,12 @@
 		return -EINVAL;
 	}
 
-	if (firmware_has_feature(FW_FEATURE_DRC_INFO))
+	if (of_find_property(dn->parent, "ibm,drc-info", NULL))
 		return rpaphp_check_drc_props_v2(dn, drc_name, drc_type,
-						*my_index);
+						be32_to_cpu(*my_index));
 	else
 		return rpaphp_check_drc_props_v1(dn, drc_name, drc_type,
-						*my_index);
+						be32_to_cpu(*my_index));
 }
 EXPORT_SYMBOL_GPL(rpaphp_check_drc_props);
 
@@ -309,10 +312,11 @@
  * for built-in pci slots (even when the built-in slots are
  * dlparable.)
  */
-static int is_php_dn(struct device_node *dn, const int **indexes,
-		const int **names, const int **types, const int **power_domains)
+static int is_php_dn(struct device_node *dn, const __be32 **indexes,
+		     const __be32 **names, const __be32 **types,
+		     const __be32 **power_domains)
 {
-	const int *drc_types;
+	const __be32 *drc_types;
 	int rc;
 
 	rc = get_children_props(dn, indexes, names, &drc_types, power_domains);
@@ -347,7 +351,7 @@
 	struct slot *slot;
 	int retval = 0;
 	int i;
-	const int *indexes, *names, *types, *power_domains;
+	const __be32 *indexes, *names, *types, *power_domains;
 	char *name, *type;
 
 	if (!dn->name || strcmp(dn->name, "pci"))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/hotplug/s390_pci_hpc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/hotplug/s390_pci_hpc.c
@@ -19,7 +19,6 @@
 #include <asm/sclp.h>
 
 #define SLOT_NAME_SIZE	10
-static LIST_HEAD(s390_hotplug_slot_list);
 
 static int zpci_fn_configured(enum zpci_state state)
 {
@@ -27,104 +26,90 @@
 	       state == ZPCI_FN_STATE_ONLINE;
 }
 
-/*
- * struct slot - slot information for each *physical* slot
- */
-struct slot {
-	struct list_head slot_list;
-	struct hotplug_slot hotplug_slot;
-	struct zpci_dev *zdev;
-};
-
-static inline struct slot *to_slot(struct hotplug_slot *hotplug_slot)
-{
-	return container_of(hotplug_slot, struct slot, hotplug_slot);
-}
-
-static inline int slot_configure(struct slot *slot)
+static inline int zdev_configure(struct zpci_dev *zdev)
 {
-	int ret = sclp_pci_configure(slot->zdev->fid);
+	int ret = sclp_pci_configure(zdev->fid);
 
-	zpci_dbg(3, "conf fid:%x, rc:%d\n", slot->zdev->fid, ret);
+	zpci_dbg(3, "conf fid:%x, rc:%d\n", zdev->fid, ret);
 	if (!ret)
-		slot->zdev->state = ZPCI_FN_STATE_CONFIGURED;
+		zdev->state = ZPCI_FN_STATE_CONFIGURED;
 
 	return ret;
 }
 
-static inline int slot_deconfigure(struct slot *slot)
+static inline int zdev_deconfigure(struct zpci_dev *zdev)
 {
-	int ret = sclp_pci_deconfigure(slot->zdev->fid);
+	int ret = sclp_pci_deconfigure(zdev->fid);
 
-	zpci_dbg(3, "deconf fid:%x, rc:%d\n", slot->zdev->fid, ret);
+	zpci_dbg(3, "deconf fid:%x, rc:%d\n", zdev->fid, ret);
 	if (!ret)
-		slot->zdev->state = ZPCI_FN_STATE_STANDBY;
+		zdev->state = ZPCI_FN_STATE_STANDBY;
 
 	return ret;
 }
 
 static int enable_slot(struct hotplug_slot *hotplug_slot)
 {
-	struct slot *slot = to_slot(hotplug_slot);
+	struct zpci_dev *zdev = container_of(hotplug_slot, struct zpci_dev,
+					     hotplug_slot);
+	struct zpci_bus *zbus = zdev->zbus;
 	int rc;
 
-	if (slot->zdev->state != ZPCI_FN_STATE_STANDBY)
+	if (zdev->state != ZPCI_FN_STATE_STANDBY)
 		return -EIO;
 
-	rc = slot_configure(slot);
+	rc = zdev_configure(zdev);
 	if (rc)
 		return rc;
 
-	rc = zpci_enable_device(slot->zdev);
+	rc = zpci_enable_device(zdev);
 	if (rc)
 		goto out_deconfigure;
 
-	pci_scan_slot(slot->zdev->bus, ZPCI_DEVFN);
+	pci_scan_slot(zbus->bus, zdev->devfn);
 	pci_lock_rescan_remove();
-	pci_bus_add_devices(slot->zdev->bus);
+	pci_bus_add_devices(zbus->bus);
 	pci_unlock_rescan_remove();
 
 	return rc;
 
 out_deconfigure:
-	slot_deconfigure(slot);
+	zdev_deconfigure(zdev);
 	return rc;
 }
 
 static int disable_slot(struct hotplug_slot *hotplug_slot)
 {
-	struct slot *slot = to_slot(hotplug_slot);
+	struct zpci_dev *zdev = container_of(hotplug_slot, struct zpci_dev,
+					     hotplug_slot);
 	struct pci_dev *pdev;
 	int rc;
 
-	if (!zpci_fn_configured(slot->zdev->state))
+	if (!zpci_fn_configured(zdev->state))
 		return -EIO;
 
-	pdev = pci_get_slot(slot->zdev->bus, ZPCI_DEVFN);
-	if (pdev) {
-		pci_stop_and_remove_bus_device_locked(pdev);
+	pdev = pci_get_slot(zdev->zbus->bus, zdev->devfn);
+	if (pdev && pci_num_vf(pdev)) {
 		pci_dev_put(pdev);
+		return -EBUSY;
 	}
+	pci_dev_put(pdev);
+
+	zpci_remove_device(zdev, false);
 
-	rc = zpci_disable_device(slot->zdev);
+	rc = zpci_disable_device(zdev);
 	if (rc)
 		return rc;
 
-	return slot_deconfigure(slot);
+	return zdev_deconfigure(zdev);
 }
 
 static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
 {
-	struct slot *slot = to_slot(hotplug_slot);
+	struct zpci_dev *zdev = container_of(hotplug_slot, struct zpci_dev,
+					     hotplug_slot);
 
-	switch (slot->zdev->state) {
-	case ZPCI_FN_STATE_STANDBY:
-		*value = 0;
-		break;
-	default:
-		*value = 1;
-		break;
-	}
+	*value = zpci_is_device_configured(zdev) ? 1 : 0;
 	return 0;
 }
 
@@ -145,44 +130,16 @@
 int zpci_init_slot(struct zpci_dev *zdev)
 {
 	char name[SLOT_NAME_SIZE];
-	struct slot *slot;
-	int rc;
+	struct zpci_bus *zbus = zdev->zbus;
 
-	if (!zdev)
-		return 0;
-
-	slot = kzalloc(sizeof(*slot), GFP_KERNEL);
-	if (!slot)
-		goto error;
-
-	slot->zdev = zdev;
-	slot->hotplug_slot.ops = &s390_hotplug_slot_ops;
+	zdev->hotplug_slot.ops = &s390_hotplug_slot_ops;
 
 	snprintf(name, SLOT_NAME_SIZE, "%08x", zdev->fid);
-	rc = pci_hp_register(&slot->hotplug_slot, zdev->bus,
-			     ZPCI_DEVFN, name);
-	if (rc)
-		goto error_reg;
-
-	list_add(&slot->slot_list, &s390_hotplug_slot_list);
-	return 0;
-
-error_reg:
-	kfree(slot);
-error:
-	return -ENOMEM;
+	return pci_hp_register(&zdev->hotplug_slot, zbus->bus,
+			       zdev->devfn, name);
 }
 
 void zpci_exit_slot(struct zpci_dev *zdev)
 {
-	struct slot *slot, *next;
-
-	list_for_each_entry_safe(slot, next, &s390_hotplug_slot_list,
-				 slot_list) {
-		if (slot->zdev != zdev)
-			continue;
-		list_del(&slot->slot_list);
-		pci_hp_deregister(&slot->hotplug_slot);
-		kfree(slot);
-	}
+	pci_hp_deregister(&zdev->hotplug_slot);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/iov.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/iov.c
@@ -134,12 +134,35 @@
 			     &physfn->sriov->subsystem_device);
 }
 
+int pci_iov_sysfs_link(struct pci_dev *dev,
+		struct pci_dev *virtfn, int id)
+{
+	char buf[VIRTFN_ID_LEN];
+	int rc;
+
+	sprintf(buf, "virtfn%u", id);
+	rc = sysfs_create_link(&dev->dev.kobj, &virtfn->dev.kobj, buf);
+	if (rc)
+		goto failed;
+	rc = sysfs_create_link(&virtfn->dev.kobj, &dev->dev.kobj, "physfn");
+	if (rc)
+		goto failed1;
+
+	kobject_uevent(&virtfn->dev.kobj, KOBJ_CHANGE);
+
+	return 0;
+
+failed1:
+	sysfs_remove_link(&dev->dev.kobj, buf);
+failed:
+	return rc;
+}
+
 int pci_iov_add_virtfn(struct pci_dev *dev, int id)
 {
 	int i;
 	int rc = -ENOMEM;
 	u64 size;
-	char buf[VIRTFN_ID_LEN];
 	struct pci_dev *virtfn;
 	struct resource *res;
 	struct pci_sriov *iov = dev->sriov;
@@ -158,6 +181,7 @@
 	virtfn->device = iov->vf_device;
 	virtfn->is_virtfn = 1;
 	virtfn->physfn = pci_dev_get(dev);
+	virtfn->no_command_memory = 1;
 
 	if (id == 0)
 		pci_read_vf_config_common(virtfn);
@@ -183,26 +207,16 @@
 	}
 
 	pci_device_add(virtfn, virtfn->bus);
-
-	sprintf(buf, "virtfn%u", id);
-	rc = sysfs_create_link(&dev->dev.kobj, &virtfn->dev.kobj, buf);
+	rc = pci_iov_sysfs_link(dev, virtfn, id);
 	if (rc)
-		goto failed2;
-	rc = sysfs_create_link(&virtfn->dev.kobj, &dev->dev.kobj, "physfn");
-	if (rc)
-		goto failed3;
-
-	kobject_uevent(&virtfn->dev.kobj, KOBJ_CHANGE);
+		goto failed1;
 
 	pci_bus_add_device(virtfn);
 
 	return 0;
 
-failed3:
-	sysfs_remove_link(&dev->dev.kobj, buf);
-failed2:
-	pci_stop_and_remove_bus_device(virtfn);
 failed1:
+	pci_stop_and_remove_bus_device(virtfn);
 	pci_dev_put(dev);
 failed0:
 	virtfn_remove_bus(dev->bus, bus);
@@ -254,8 +268,14 @@
 				 char *buf)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
+	u16 num_vfs;
+
+	/* Serialize vs sriov_numvfs_store() so readers see valid num_VFs */
+	device_lock(&pdev->dev);
+	num_vfs = pdev->sriov->num_VFs;
+	device_unlock(&pdev->dev);
 
-	return sprintf(buf, "%u\n", pdev->sriov->num_VFs);
+	return sprintf(buf, "%u\n", num_vfs);
 }
 
 /*
@@ -553,9 +573,6 @@
 	struct pci_sriov *iov = dev->sriov;
 	int i;
 
-	if (dev->no_vf_scan)
-		return;
-
 	for (i = 0; i < iov->num_VFs; i++)
 		pci_iov_remove_virtfn(dev, i);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/irq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/irq.c
@@ -94,6 +94,8 @@
 	va_start(ap, fmt);
 	devname = kvasprintf(GFP_KERNEL, fmt, ap);
 	va_end(ap);
+	if (!devname)
+		return -ENOMEM;
 
 	ret = request_threaded_irq(pci_irq_vector(dev, nr), handler, thread_fn,
 				   irqflags, devname, dev_id);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/msi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/msi.c
@@ -170,24 +170,25 @@
  * reliably as devices without an INTx disable bit will then generate a
  * level IRQ which will never be cleared.
  */
-u32 __pci_msi_desc_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
+void __pci_msi_desc_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
 {
-	u32 mask_bits = desc->masked;
+	raw_spinlock_t *lock = &desc->dev->msi_lock;
+	unsigned long flags;
 
 	if (pci_msi_ignore_mask || !desc->msi_attrib.maskbit)
-		return 0;
+		return;
 
-	mask_bits &= ~mask;
-	mask_bits |= flag;
+	raw_spin_lock_irqsave(lock, flags);
+	desc->masked &= ~mask;
+	desc->masked |= flag;
 	pci_write_config_dword(msi_desc_to_pci_dev(desc), desc->mask_pos,
-			       mask_bits);
-
-	return mask_bits;
+			       desc->masked);
+	raw_spin_unlock_irqrestore(lock, flags);
 }
 
 static void msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
 {
-	desc->masked = __pci_msi_desc_mask_irq(desc, mask, flag);
+	__pci_msi_desc_mask_irq(desc, mask, flag);
 }
 
 static void __iomem *pci_msix_desc_addr(struct msi_desc *desc)
@@ -213,12 +214,13 @@
 
 	if (pci_msi_ignore_mask)
 		return 0;
+
 	desc_addr = pci_msix_desc_addr(desc);
 	if (!desc_addr)
 		return 0;
 
 	mask_bits &= ~PCI_MSIX_ENTRY_CTRL_MASKBIT;
-	if (flag)
+	if (flag & PCI_MSIX_ENTRY_CTRL_MASKBIT)
 		mask_bits |= PCI_MSIX_ENTRY_CTRL_MASKBIT;
 
 	writel(mask_bits, desc_addr + PCI_MSIX_ENTRY_VECTOR_CTRL);
@@ -315,13 +317,31 @@
 		/* Don't touch the hardware now */
 	} else if (entry->msi_attrib.is_msix) {
 		void __iomem *base = pci_msix_desc_addr(entry);
+		bool unmasked = !(entry->masked & PCI_MSIX_ENTRY_CTRL_MASKBIT);
 
 		if (!base)
 			goto skip;
 
+		/*
+		 * The specification mandates that the entry is masked
+		 * when the message is modified:
+		 *
+		 * "If software changes the Address or Data value of an
+		 * entry while the entry is unmasked, the result is
+		 * undefined."
+		 */
+		if (unmasked)
+			__pci_msix_desc_mask_irq(entry, PCI_MSIX_ENTRY_CTRL_MASKBIT);
+
 		writel(msg->address_lo, base + PCI_MSIX_ENTRY_LOWER_ADDR);
 		writel(msg->address_hi, base + PCI_MSIX_ENTRY_UPPER_ADDR);
 		writel(msg->data, base + PCI_MSIX_ENTRY_DATA);
+
+		if (unmasked)
+			__pci_msix_desc_mask_irq(entry, 0);
+
+		/* Ensure that the writes are visible in the device */
+		readl(base + PCI_MSIX_ENTRY_DATA);
 	} else {
 		int pos = dev->msi_cap;
 		u16 msgctl;
@@ -342,6 +362,8 @@
 			pci_write_config_word(dev, pos + PCI_MSI_DATA_32,
 					      msg->data);
 		}
+		/* Ensure that the writes are visible in the device */
+		pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &msgctl);
 	}
 
 skip:
@@ -373,18 +395,6 @@
 			for (i = 0; i < entry->nvec_used; i++)
 				BUG_ON(irq_has_action(entry->irq + i));
 
-	pci_msi_teardown_msi_irqs(dev);
-
-	list_for_each_entry_safe(entry, tmp, msi_list, list) {
-		if (entry->msi_attrib.is_msix) {
-			if (list_is_last(&entry->list, msi_list))
-				iounmap(entry->mask_base);
-		}
-
-		list_del(&entry->list);
-		free_msi_entry(entry);
-	}
-
 	if (dev->msi_irq_groups) {
 		sysfs_remove_groups(&dev->dev.kobj, dev->msi_irq_groups);
 		msi_attrs = dev->msi_irq_groups[0]->attrs;
@@ -400,6 +410,18 @@
 		kfree(dev->msi_irq_groups);
 		dev->msi_irq_groups = NULL;
 	}
+
+	pci_msi_teardown_msi_irqs(dev);
+
+	list_for_each_entry_safe(entry, tmp, msi_list, list) {
+		if (entry->msi_attrib.is_msix) {
+			if (list_is_last(&entry->list, msi_list))
+				iounmap(entry->mask_base);
+		}
+
+		list_del(&entry->list);
+		free_msi_entry(entry);
+	}
 }
 
 static void pci_intx_for_msi(struct pci_dev *dev, int enable)
@@ -569,6 +591,9 @@
 		goto out;
 
 	pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);
+	/* Lies, damned lies, and MSIs */
+	if (dev->dev_flags & PCI_DEV_FLAGS_HAS_MSI_MASKING)
+		control |= PCI_MSI_FLAGS_MASKBIT;
 
 	entry->msi_attrib.is_msix	= 0;
 	entry->msi_attrib.is_64		= !!(control & PCI_MSI_FLAGS_64BIT);
@@ -641,21 +666,21 @@
 	/* Configure MSI capability structure */
 	ret = pci_msi_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSI);
 	if (ret) {
-		msi_mask_irq(entry, mask, ~mask);
+		msi_mask_irq(entry, mask, 0);
 		free_msi_irqs(dev);
 		return ret;
 	}
 
 	ret = msi_verify_entries(dev);
 	if (ret) {
-		msi_mask_irq(entry, mask, ~mask);
+		msi_mask_irq(entry, mask, 0);
 		free_msi_irqs(dev);
 		return ret;
 	}
 
 	ret = populate_msi_sysfs(dev);
 	if (ret) {
-		msi_mask_irq(entry, mask, ~mask);
+		msi_mask_irq(entry, mask, 0);
 		free_msi_irqs(dev);
 		return ret;
 	}
@@ -696,6 +721,7 @@
 {
 	struct irq_affinity_desc *curmsk, *masks = NULL;
 	struct msi_desc *entry;
+	void __iomem *addr;
 	int ret, i;
 	int vec_count = pci_msix_vec_count(dev);
 
@@ -716,6 +742,7 @@
 
 		entry->msi_attrib.is_msix	= 1;
 		entry->msi_attrib.is_64		= 1;
+
 		if (entries)
 			entry->msi_attrib.entry_nr = entries[i].entry;
 		else
@@ -727,6 +754,10 @@
 		entry->msi_attrib.default_irq	= dev->irq;
 		entry->mask_base		= base;
 
+		addr = pci_msix_desc_addr(entry);
+		if (addr)
+			entry->masked = readl(addr + PCI_MSIX_ENTRY_VECTOR_CTRL);
+
 		list_add_tail(&entry->list, dev_to_msi_list(&dev->dev));
 		if (masks)
 			curmsk++;
@@ -737,26 +768,28 @@
 	return ret;
 }
 
-static void msix_program_entries(struct pci_dev *dev,
-				 struct msix_entry *entries)
+static void msix_update_entries(struct pci_dev *dev, struct msix_entry *entries)
 {
 	struct msi_desc *entry;
-	int i = 0;
-	void __iomem *desc_addr;
 
 	for_each_pci_msi_entry(entry, dev) {
-		if (entries)
-			entries[i++].vector = entry->irq;
+		if (entries) {
+			entries->vector = entry->irq;
+			entries++;
+		}
+	}
+}
 
-		desc_addr = pci_msix_desc_addr(entry);
-		if (desc_addr)
-			entry->masked = readl(desc_addr +
-					      PCI_MSIX_ENTRY_VECTOR_CTRL);
-		else
-			entry->masked = 0;
+static void msix_mask_all(void __iomem *base, int tsize)
+{
+	u32 ctrl = PCI_MSIX_ENTRY_CTRL_MASKBIT;
+	int i;
 
-		msix_mask_irq(entry, 1);
-	}
+	if (pci_msi_ignore_mask)
+		return;
+
+	for (i = 0; i < tsize; i++, base += PCI_MSIX_ENTRY_SIZE)
+		writel(ctrl, base + PCI_MSIX_ENTRY_VECTOR_CTRL);
 }
 
 /**
@@ -773,22 +806,33 @@
 static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries,
 				int nvec, struct irq_affinity *affd)
 {
-	int ret;
-	u16 control;
 	void __iomem *base;
+	int ret, tsize;
+	u16 control;
 
-	/* Ensure MSI-X is disabled while it is set up */
-	pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0);
+	/*
+	 * Some devices require MSI-X to be enabled before the MSI-X
+	 * registers can be accessed.  Mask all the vectors to prevent
+	 * interrupts coming in before they're fully set up.
+	 */
+	pci_msix_clear_and_set_ctrl(dev, 0, PCI_MSIX_FLAGS_MASKALL |
+				    PCI_MSIX_FLAGS_ENABLE);
 
 	pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control);
 	/* Request & Map MSI-X table region */
-	base = msix_map_region(dev, msix_table_size(control));
-	if (!base)
-		return -ENOMEM;
+	tsize = msix_table_size(control);
+	base = msix_map_region(dev, tsize);
+	if (!base) {
+		ret = -ENOMEM;
+		goto out_disable;
+	}
+
+	/* Ensure that all table entries are masked. */
+	msix_mask_all(base, tsize);
 
 	ret = msix_setup_entries(dev, base, entries, nvec, affd);
 	if (ret)
-		return ret;
+		goto out_disable;
 
 	ret = pci_msi_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSIX);
 	if (ret)
@@ -799,15 +843,7 @@
 	if (ret)
 		goto out_free;
 
-	/*
-	 * Some devices require MSI-X to be enabled before we can touch the
-	 * MSI-X registers.  We need to mask all the vectors to prevent
-	 * interrupts coming in before they're fully set up.
-	 */
-	pci_msix_clear_and_set_ctrl(dev, 0,
-				PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS_ENABLE);
-
-	msix_program_entries(dev, entries);
+	msix_update_entries(dev, entries);
 
 	ret = populate_msi_sysfs(dev);
 	if (ret)
@@ -841,6 +877,9 @@
 out_free:
 	free_msi_irqs(dev);
 
+out_disable:
+	pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS_ENABLE, 0);
+
 	return ret;
 }
 
@@ -928,8 +967,7 @@
 
 	/* Return the device with MSI unmasked as initial states */
 	mask = msi_mask(desc->msi_attrib.multi_cap);
-	/* Keep cached state to be restored */
-	__pci_msi_desc_mask_irq(desc, mask, ~mask);
+	msi_mask_irq(desc, mask, 0);
 
 	/* Restore dev->irq to its default pin-assertion IRQ */
 	dev->irq = desc->msi_attrib.default_irq;
@@ -1014,10 +1052,8 @@
 	}
 
 	/* Return the device with MSI-X masked as initial states */
-	for_each_pci_msi_entry(entry, dev) {
-		/* Keep cached states to be restored */
+	for_each_pci_msi_entry(entry, dev)
 		__pci_msix_desc_mask_irq(entry, 1);
-	}
 
 	pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0);
 	pci_intx_for_msi(dev, 1);
@@ -1251,19 +1287,24 @@
 
 /**
  * pci_irq_vector - return Linux IRQ number of a device vector
- * @dev: PCI device to operate on
- * @nr: device-relative interrupt vector index (0-based).
+ * @dev:	PCI device to operate on
+ * @nr:		Interrupt vector index (0-based)
+ *
+ * @nr has the following meanings depending on the interrupt mode:
+ *   MSI-X:	The index in the MSI-X vector table
+ *   MSI:	The index of the enabled MSI vectors
+ *   INTx:	Must be 0
+ *
+ * Return: The Linux interrupt number or -EINVAl if @nr is out of range.
  */
 int pci_irq_vector(struct pci_dev *dev, unsigned int nr)
 {
 	if (dev->msix_enabled) {
 		struct msi_desc *entry;
-		int i = 0;
 
 		for_each_pci_msi_entry(entry, dev) {
-			if (i == nr)
+			if (entry->msi_attrib.entry_nr == nr)
 				return entry->irq;
-			i++;
 		}
 		WARN_ON_ONCE(1);
 		return -EINVAL;
@@ -1287,17 +1328,22 @@
  * pci_irq_get_affinity - return the affinity of a particular MSI vector
  * @dev:	PCI device to operate on
  * @nr:		device-relative interrupt vector index (0-based).
+ *
+ * @nr has the following meanings depending on the interrupt mode:
+ *   MSI-X:	The index in the MSI-X vector table
+ *   MSI:	The index of the enabled MSI vectors
+ *   INTx:	Must be 0
+ *
+ * Return: A cpumask pointer or NULL if @nr is out of range
  */
 const struct cpumask *pci_irq_get_affinity(struct pci_dev *dev, int nr)
 {
 	if (dev->msix_enabled) {
 		struct msi_desc *entry;
-		int i = 0;
 
 		for_each_pci_msi_entry(entry, dev) {
-			if (i == nr)
+			if (entry->msi_attrib.entry_nr == nr)
 				return &entry->affinity->mask;
-			i++;
 		}
 		WARN_ON_ONCE(1);
 		return NULL;
@@ -1375,7 +1421,7 @@
 {
 	return (irq_hw_number_t)desc->msi_attrib.entry_nr |
 		pci_dev_id(dev) << 11 |
-		(pci_domain_nr(dev->bus) & 0xFFFFFFFF) << 27;
+		((irq_hw_number_t)(pci_domain_nr(dev->bus) & 0xFFFFFFFF)) << 27;
 }
 
 static inline bool pci_msi_desc_is_multi_msi(struct msi_desc *desc)
@@ -1550,8 +1596,8 @@
 	pci_for_each_dma_alias(pdev, get_msi_id_cb, &rid);
 
 	of_node = irq_domain_get_of_node(domain);
-	rid = of_node ? of_msi_map_rid(&pdev->dev, of_node, rid) :
-			iort_msi_map_rid(&pdev->dev, rid);
+	rid = of_node ? of_msi_map_id(&pdev->dev, of_node, rid) :
+			iort_msi_map_id(&pdev->dev, rid);
 
 	return rid;
 }
@@ -1571,9 +1617,10 @@
 	u32 rid = pci_dev_id(pdev);
 
 	pci_for_each_dma_alias(pdev, get_msi_id_cb, &rid);
-	dom = of_msi_map_get_device_domain(&pdev->dev, rid);
+	dom = of_msi_map_get_device_domain(&pdev->dev, rid, DOMAIN_BUS_PCI_MSI);
 	if (!dom)
-		dom = iort_get_device_domain(&pdev->dev, rid);
+		dom = iort_get_device_domain(&pdev->dev, rid,
+					     DOMAIN_BUS_PCI_MSI);
 	return dom;
 }
 #endif /* CONFIG_PCI_MSI_IRQ_DOMAIN */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/p2pdma.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/p2pdma.c
@@ -292,10 +292,41 @@
 	{}
 };
 
+/*
+ * This lookup function tries to find the PCI device corresponding to a given
+ * host bridge.
+ *
+ * It assumes the host bridge device is the first PCI device in the
+ * bus->devices list and that the devfn is 00.0. These assumptions should hold
+ * for all the devices in the whitelist above.
+ *
+ * This function is equivalent to pci_get_slot(host->bus, 0), however it does
+ * not take the pci_bus_sem lock seeing __host_bridge_whitelist() must not
+ * sleep.
+ *
+ * For this to be safe, the caller should hold a reference to a device on the
+ * bridge, which should ensure the host_bridge device will not be freed
+ * or removed from the head of the devices list.
+ */
+static struct pci_dev *pci_host_bridge_dev(struct pci_host_bridge *host)
+{
+	struct pci_dev *root;
+
+	root = list_first_entry_or_null(&host->bus->devices,
+					struct pci_dev, bus_list);
+
+	if (!root)
+		return NULL;
+	if (root->devfn != PCI_DEVFN(0, 0))
+		return NULL;
+
+	return root;
+}
+
 static bool __host_bridge_whitelist(struct pci_host_bridge *host,
 				    bool same_host_bridge)
 {
-	struct pci_dev *root = pci_get_slot(host->bus, PCI_DEVFN(0, 0));
+	struct pci_dev *root = pci_host_bridge_dev(host);
 	const struct pci_p2pdma_whitelist_entry *entry;
 	unsigned short vendor, device;
 
@@ -304,7 +335,6 @@
 
 	vendor = root->vendor;
 	device = root->device;
-	pci_dev_put(root);
 
 	for (entry = pci_p2pdma_whitelist; entry->vendor; entry++) {
 		if (vendor != entry->vendor || device != entry->device)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/pci-acpi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/pci-acpi.c
@@ -909,7 +909,7 @@
 {
 	int acpi_state, d_max;
 
-	if (pdev->no_d3cold)
+	if (pdev->no_d3cold || !pdev->d3cold_allowed)
 		d_max = ACPI_STATE_D3_HOT;
 	else
 		d_max = ACPI_STATE_D3_COLD;
@@ -944,6 +944,16 @@
 	if (!dev->is_hotplug_bridge)
 		return false;
 
+	/* Assume D3 support if the bridge is power-manageable by ACPI. */
+	adev = ACPI_COMPANION(&dev->dev);
+	if (!adev && !pci_dev_is_added(dev)) {
+		adev = acpi_pci_find_companion(&dev->dev);
+		ACPI_COMPANION_SET(&dev->dev, adev);
+	}
+
+	if (adev && acpi_device_power_manageable(adev))
+		return true;
+
 	/*
 	 * Look for a special _DSD property for the root port and if it
 	 * is set we know the hierarchy behind it supports D3 just fine.
@@ -1050,7 +1060,7 @@
 {
 	while (bus->parent) {
 		if (acpi_pm_device_can_wakeup(&bus->self->dev))
-			return acpi_pm_set_bridge_wakeup(&bus->self->dev, enable);
+			return acpi_pm_set_device_wakeup(&bus->self->dev, enable);
 
 		bus = bus->parent;
 	}
@@ -1058,7 +1068,7 @@
 	/* We have reached the root bus. */
 	if (bus->bridge) {
 		if (acpi_pm_device_can_wakeup(bus->bridge))
-			return acpi_pm_set_bridge_wakeup(bus->bridge, enable);
+			return acpi_pm_set_device_wakeup(bus->bridge, enable);
 	}
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/pci-bridge-emul.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/pci-bridge-emul.c
@@ -21,8 +21,9 @@
 #include "pci-bridge-emul.h"
 
 #define PCI_BRIDGE_CONF_END	PCI_STD_HEADER_SIZEOF
+#define PCI_CAP_PCIE_SIZEOF	(PCI_EXP_SLTSTA2 + 2)
 #define PCI_CAP_PCIE_START	PCI_BRIDGE_CONF_END
-#define PCI_CAP_PCIE_END	(PCI_CAP_PCIE_START + PCI_EXP_SLTSTA2 + 2)
+#define PCI_CAP_PCIE_END	(PCI_CAP_PCIE_START + PCI_CAP_PCIE_SIZEOF)
 
 struct pci_bridge_reg_behavior {
 	/* Read-only bits */
@@ -38,7 +39,8 @@
 	u32 rsvd;
 };
 
-static const struct pci_bridge_reg_behavior pci_regs_behavior[] = {
+static const
+struct pci_bridge_reg_behavior pci_regs_behavior[PCI_STD_HEADER_SIZEOF / 4] = {
 	[PCI_VENDOR_ID / 4] = { .ro = ~0 },
 	[PCI_COMMAND / 4] = {
 		.rw = (PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
@@ -173,7 +175,8 @@
 	},
 };
 
-static const struct pci_bridge_reg_behavior pcie_cap_regs_behavior[] = {
+static const
+struct pci_bridge_reg_behavior pcie_cap_regs_behavior[PCI_CAP_PCIE_SIZEOF / 4] = {
 	[PCI_CAP_LIST_ID / 4] = {
 		/*
 		 * Capability ID, Next Capability Pointer and
@@ -195,8 +198,8 @@
 		 * RO, the rest is reserved
 		 */
 		.w1c = GENMASK(19, 16),
-		.ro = GENMASK(20, 19),
-		.rsvd = GENMASK(31, 21),
+		.ro = GENMASK(21, 20),
+		.rsvd = GENMASK(31, 22),
 	},
 
 	[PCI_EXP_LNKCAP / 4] = {
@@ -236,7 +239,7 @@
 			PCI_EXP_SLTSTA_CC | PCI_EXP_SLTSTA_DLLSC) << 16,
 		.ro = (PCI_EXP_SLTSTA_MRLSS | PCI_EXP_SLTSTA_PDS |
 		       PCI_EXP_SLTSTA_EIS) << 16,
-		.rsvd = GENMASK(15, 12) | (GENMASK(15, 9) << 16),
+		.rsvd = GENMASK(15, 13) | (GENMASK(15, 9) << 16),
 	},
 
 	[PCI_EXP_RTCTL / 4] = {
@@ -270,10 +273,12 @@
 int pci_bridge_emul_init(struct pci_bridge_emul *bridge,
 			 unsigned int flags)
 {
-	bridge->conf.class_revision |= PCI_CLASS_BRIDGE_PCI << 16;
+	BUILD_BUG_ON(sizeof(bridge->conf) != PCI_BRIDGE_CONF_END);
+
+	bridge->conf.class_revision |= cpu_to_le32(PCI_CLASS_BRIDGE_PCI << 16);
 	bridge->conf.header_type = PCI_HEADER_TYPE_BRIDGE;
 	bridge->conf.cache_line_size = 0x10;
-	bridge->conf.status = PCI_STATUS_CAP_LIST;
+	bridge->conf.status = cpu_to_le16(PCI_STATUS_CAP_LIST);
 	bridge->pci_regs_behavior = kmemdup(pci_regs_behavior,
 					    sizeof(pci_regs_behavior),
 					    GFP_KERNEL);
@@ -282,10 +287,9 @@
 
 	if (bridge->has_pcie) {
 		bridge->conf.capabilities_pointer = PCI_CAP_PCIE_START;
+		bridge->conf.status |= cpu_to_le16(PCI_STATUS_CAP_LIST);
 		bridge->pcie_conf.cap_id = PCI_CAP_ID_EXP;
-		/* Set PCIe v2, root port, slot support */
-		bridge->pcie_conf.cap = PCI_EXP_TYPE_ROOT_PORT << 4 | 2 |
-			PCI_EXP_FLAGS_SLOT;
+		bridge->pcie_conf.cap |= cpu_to_le16(PCI_EXP_TYPE_ROOT_PORT << 4);
 		bridge->pcie_cap_regs_behavior =
 			kmemdup(pcie_cap_regs_behavior,
 				sizeof(pcie_cap_regs_behavior),
@@ -294,6 +298,27 @@
 			kfree(bridge->pci_regs_behavior);
 			return -ENOMEM;
 		}
+		/* These bits are applicable only for PCI and reserved on PCIe */
+		bridge->pci_regs_behavior[PCI_CACHE_LINE_SIZE / 4].ro &=
+			~GENMASK(15, 8);
+		bridge->pci_regs_behavior[PCI_COMMAND / 4].ro &=
+			~((PCI_COMMAND_SPECIAL | PCI_COMMAND_INVALIDATE |
+			   PCI_COMMAND_VGA_PALETTE | PCI_COMMAND_WAIT |
+			   PCI_COMMAND_FAST_BACK) |
+			  (PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK |
+			   PCI_STATUS_DEVSEL_MASK) << 16);
+		bridge->pci_regs_behavior[PCI_PRIMARY_BUS / 4].ro &=
+			~GENMASK(31, 24);
+		bridge->pci_regs_behavior[PCI_IO_BASE / 4].ro &=
+			~((PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK |
+			   PCI_STATUS_DEVSEL_MASK) << 16);
+		bridge->pci_regs_behavior[PCI_INTERRUPT_LINE / 4].rw &=
+			~((PCI_BRIDGE_CTL_MASTER_ABORT |
+			   BIT(8) | BIT(9) | BIT(11)) << 16);
+		bridge->pci_regs_behavior[PCI_INTERRUPT_LINE / 4].ro &=
+			~((PCI_BRIDGE_CTL_FAST_BACK) << 16);
+		bridge->pci_regs_behavior[PCI_INTERRUPT_LINE / 4].w1c &=
+			~(BIT(10) << 16);
 	}
 
 	if (flags & PCI_BRIDGE_EMUL_NO_PREFETCHABLE_BAR) {
@@ -327,7 +352,7 @@
 	int reg = where & ~3;
 	pci_bridge_emul_read_status_t (*read_op)(struct pci_bridge_emul *bridge,
 						 int reg, u32 *value);
-	u32 *cfgspace;
+	__le32 *cfgspace;
 	const struct pci_bridge_reg_behavior *behavior;
 
 	if (bridge->has_pcie && reg >= PCI_CAP_PCIE_END) {
@@ -343,11 +368,11 @@
 	if (bridge->has_pcie && reg >= PCI_CAP_PCIE_START) {
 		reg -= PCI_CAP_PCIE_START;
 		read_op = bridge->ops->read_pcie;
-		cfgspace = (u32 *) &bridge->pcie_conf;
+		cfgspace = (__le32 *) &bridge->pcie_conf;
 		behavior = bridge->pcie_cap_regs_behavior;
 	} else {
 		read_op = bridge->ops->read_base;
-		cfgspace = (u32 *) &bridge->conf;
+		cfgspace = (__le32 *) &bridge->conf;
 		behavior = bridge->pci_regs_behavior;
 	}
 
@@ -357,7 +382,7 @@
 		ret = PCI_BRIDGE_EMUL_NOT_HANDLED;
 
 	if (ret == PCI_BRIDGE_EMUL_NOT_HANDLED)
-		*value = cfgspace[reg / 4];
+		*value = le32_to_cpu(cfgspace[reg / 4]);
 
 	/*
 	 * Make sure we never return any reserved bit with a value
@@ -387,7 +412,7 @@
 	int mask, ret, old, new, shift;
 	void (*write_op)(struct pci_bridge_emul *bridge, int reg,
 			 u32 old, u32 new, u32 mask);
-	u32 *cfgspace;
+	__le32 *cfgspace;
 	const struct pci_bridge_reg_behavior *behavior;
 
 	if (bridge->has_pcie && reg >= PCI_CAP_PCIE_END)
@@ -414,11 +439,11 @@
 	if (bridge->has_pcie && reg >= PCI_CAP_PCIE_START) {
 		reg -= PCI_CAP_PCIE_START;
 		write_op = bridge->ops->write_pcie;
-		cfgspace = (u32 *) &bridge->pcie_conf;
+		cfgspace = (__le32 *) &bridge->pcie_conf;
 		behavior = bridge->pcie_cap_regs_behavior;
 	} else {
 		write_op = bridge->ops->write_base;
-		cfgspace = (u32 *) &bridge->conf;
+		cfgspace = (__le32 *) &bridge->conf;
 		behavior = bridge->pci_regs_behavior;
 	}
 
@@ -431,7 +456,20 @@
 	/* Clear the W1C bits */
 	new &= ~((value << shift) & (behavior[reg / 4].w1c & mask));
 
-	cfgspace[reg / 4] = new;
+	/* Save the new value with the cleared W1C bits into the cfgspace */
+	cfgspace[reg / 4] = cpu_to_le32(new);
+
+	/*
+	 * Clear the W1C bits not specified by the write mask, so that the
+	 * write_op() does not clear them.
+	 */
+	new &= ~(behavior[reg / 4].w1c & ~mask);
+
+	/*
+	 * Set the W1C bits specified by the write mask, so that write_op()
+	 * knows about that they are to be cleared.
+	 */
+	new |= (value << shift) & (behavior[reg / 4].w1c & mask);
 
 	if (write_op)
 		write_op(bridge, reg, old, new, mask);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/pci-bridge-emul.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/pci-bridge-emul.h
@@ -6,65 +6,65 @@
 
 /* PCI configuration space of a PCI-to-PCI bridge. */
 struct pci_bridge_emul_conf {
-	u16 vendor;
-	u16 device;
-	u16 command;
-	u16 status;
-	u32 class_revision;
+	__le16 vendor;
+	__le16 device;
+	__le16 command;
+	__le16 status;
+	__le32 class_revision;
 	u8 cache_line_size;
 	u8 latency_timer;
 	u8 header_type;
 	u8 bist;
-	u32 bar[2];
+	__le32 bar[2];
 	u8 primary_bus;
 	u8 secondary_bus;
 	u8 subordinate_bus;
 	u8 secondary_latency_timer;
 	u8 iobase;
 	u8 iolimit;
-	u16 secondary_status;
-	u16 membase;
-	u16 memlimit;
-	u16 pref_mem_base;
-	u16 pref_mem_limit;
-	u32 prefbaseupper;
-	u32 preflimitupper;
-	u16 iobaseupper;
-	u16 iolimitupper;
+	__le16 secondary_status;
+	__le16 membase;
+	__le16 memlimit;
+	__le16 pref_mem_base;
+	__le16 pref_mem_limit;
+	__le32 prefbaseupper;
+	__le32 preflimitupper;
+	__le16 iobaseupper;
+	__le16 iolimitupper;
 	u8 capabilities_pointer;
 	u8 reserve[3];
-	u32 romaddr;
+	__le32 romaddr;
 	u8 intline;
 	u8 intpin;
-	u16 bridgectrl;
+	__le16 bridgectrl;
 };
 
 /* PCI configuration space of the PCIe capabilities */
 struct pci_bridge_emul_pcie_conf {
 	u8 cap_id;
 	u8 next;
-	u16 cap;
-	u32 devcap;
-	u16 devctl;
-	u16 devsta;
-	u32 lnkcap;
-	u16 lnkctl;
-	u16 lnksta;
-	u32 slotcap;
-	u16 slotctl;
-	u16 slotsta;
-	u16 rootctl;
-	u16 rsvd;
-	u32 rootsta;
-	u32 devcap2;
-	u16 devctl2;
-	u16 devsta2;
-	u32 lnkcap2;
-	u16 lnkctl2;
-	u16 lnksta2;
-	u32 slotcap2;
-	u16 slotctl2;
-	u16 slotsta2;
+	__le16 cap;
+	__le32 devcap;
+	__le16 devctl;
+	__le16 devsta;
+	__le32 lnkcap;
+	__le16 lnkctl;
+	__le16 lnksta;
+	__le32 slotcap;
+	__le16 slotctl;
+	__le16 slotsta;
+	__le16 rootctl;
+	__le16 rootcap;
+	__le32 rootsta;
+	__le32 devcap2;
+	__le16 devctl2;
+	__le16 devsta2;
+	__le32 lnkcap2;
+	__le16 lnkctl2;
+	__le16 lnksta2;
+	__le32 slotcap2;
+	__le16 slotctl2;
+	__le16 slotsta2;
 };
 
 struct pci_bridge_emul;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/pci-driver.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/pci-driver.c
@@ -439,16 +439,21 @@
 	struct pci_dev *pci_dev = to_pci_dev(dev);
 	struct pci_driver *drv = pci_dev->driver;
 
-	if (drv) {
-		if (drv->remove) {
-			pm_runtime_get_sync(dev);
-			drv->remove(pci_dev);
-			pm_runtime_put_noidle(dev);
-		}
-		pcibios_free_irq(pci_dev);
-		pci_dev->driver = NULL;
-		pci_iov_remove(pci_dev);
-	}
+	if (drv->remove) {
+		pm_runtime_get_sync(dev);
+		/*
+		 * If the driver provides a .runtime_idle() callback and it has
+		 * started to run already, it may continue to run in parallel
+		 * with the code below, so wait until all of the runtime PM
+		 * activity has completed.
+		 */
+		pm_runtime_barrier(dev);
+		drv->remove(pci_dev);
+		pm_runtime_put_noidle(dev);
+	}
+	pcibios_free_irq(pci_dev);
+	pci_dev->driver = NULL;
+	pci_iov_remove(pci_dev);
 
 	/* Undo the runtime PM settings in local_pci_probe() */
 	pm_runtime_put_sync(dev);
@@ -919,6 +924,8 @@
 	struct pci_dev *pci_dev = to_pci_dev(dev);
 	struct device_driver *drv = dev->driver;
 	int error = 0;
+	pci_power_t prev_state = pci_dev->current_state;
+	bool skip_bus_pm = pci_dev->skip_bus_pm;
 
 	if (dev_pm_may_skip_resume(dev))
 		return 0;
@@ -937,16 +944,18 @@
 	 * configuration here and attempting to put them into D0 again is
 	 * pointless, so avoid doing that.
 	 */
-	if (!(pci_dev->skip_bus_pm && pm_suspend_no_platform()))
+	if (!(skip_bus_pm && pm_suspend_no_platform()))
 		pci_pm_default_resume_early(pci_dev);
 
 	pci_fixup_device(pci_fixup_resume_early, pci_dev);
+	pcie_pme_root_status_cleanup(pci_dev);
+
+	if (!skip_bus_pm && prev_state == PCI_D3cold)
+		pci_bridge_wait_for_secondary_bus(pci_dev, "resume", PCI_RESET_WAIT);
 
 	if (pci_has_legacy_pm_support(pci_dev))
 		return pci_legacy_resume_early(dev);
 
-	pcie_pme_root_status_cleanup(pci_dev);
-
 	if (drv && drv->pm && drv->pm->resume_noirq)
 		error = drv->pm->resume_noirq(dev);
 
@@ -1076,17 +1085,22 @@
 			return error;
 	}
 
-	if (pci_has_legacy_pm_support(pci_dev))
-		return pci_legacy_resume_early(dev);
-
 	/*
-	 * pci_restore_state() requires the device to be in D0 (because of MSI
-	 * restoration among other things), so force it into D0 in case the
-	 * driver's "freeze" callbacks put it into a low-power state directly.
+	 * Both the legacy ->resume_early() and the new pm->thaw_noirq()
+	 * callbacks assume the device has been returned to D0 and its
+	 * config state has been restored.
+	 *
+	 * In addition, pci_restore_state() restores MSI-X state in MMIO
+	 * space, which requires the device to be in D0, so return it to D0
+	 * in case the driver's "freeze" callbacks put it into a low-power
+	 * state.
 	 */
 	pci_set_power_state(pci_dev, PCI_D0);
 	pci_restore_state(pci_dev);
 
+	if (pci_has_legacy_pm_support(pci_dev))
+		return pci_legacy_resume_early(dev);
+
 	if (drv && drv->pm && drv->pm->thaw_noirq)
 		error = drv->pm->thaw_noirq(dev);
 
@@ -1329,6 +1343,7 @@
 	int rc = 0;
 	struct pci_dev *pci_dev = to_pci_dev(dev);
 	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+	pci_power_t prev_state = pci_dev->current_state;
 
 	/*
 	 * Restoring config space is necessary even if the device is not bound
@@ -1344,6 +1359,9 @@
 	pci_enable_wake(pci_dev, PCI_D0, false);
 	pci_fixup_device(pci_fixup_resume, pci_dev);
 
+	if (prev_state == PCI_D3cold)
+		pci_bridge_wait_for_secondary_bus(pci_dev, "resume", PCI_RESET_WAIT);
+
 	if (pm && pm->runtime_resume)
 		rc = pm->runtime_resume(dev);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/pci-label.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/pci-label.c
@@ -162,7 +162,7 @@
 	len = utf16s_to_utf8s((const wchar_t *)obj->buffer.pointer,
 			      obj->buffer.length,
 			      UTF16_LITTLE_ENDIAN,
-			      buf, PAGE_SIZE);
+			      buf, PAGE_SIZE - 1);
 	buf[len] = '\n';
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/pci-sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/pci-sysfs.c
@@ -156,7 +156,8 @@
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
 
-	return sprintf(buf, "%s\n", PCIE_SPEED2STR(pcie_get_speed_cap(pdev)));
+	return sprintf(buf, "%s\n",
+		       pci_speed_string(pcie_get_speed_cap(pdev)));
 }
 static DEVICE_ATTR_RO(max_link_speed);
 
@@ -175,33 +176,15 @@
 	struct pci_dev *pci_dev = to_pci_dev(dev);
 	u16 linkstat;
 	int err;
-	const char *speed;
+	enum pci_bus_speed speed;
 
 	err = pcie_capability_read_word(pci_dev, PCI_EXP_LNKSTA, &linkstat);
 	if (err)
 		return -EINVAL;
 
-	switch (linkstat & PCI_EXP_LNKSTA_CLS) {
-	case PCI_EXP_LNKSTA_CLS_32_0GB:
-		speed = "32 GT/s";
-		break;
-	case PCI_EXP_LNKSTA_CLS_16_0GB:
-		speed = "16 GT/s";
-		break;
-	case PCI_EXP_LNKSTA_CLS_8_0GB:
-		speed = "8 GT/s";
-		break;
-	case PCI_EXP_LNKSTA_CLS_5_0GB:
-		speed = "5 GT/s";
-		break;
-	case PCI_EXP_LNKSTA_CLS_2_5GB:
-		speed = "2.5 GT/s";
-		break;
-	default:
-		speed = "Unknown speed";
-	}
+	speed = pcie_link_speed[linkstat & PCI_EXP_LNKSTA_CLS];
 
-	return sprintf(buf, "%s\n", speed);
+	return sprintf(buf, "%s\n", pci_speed_string(speed));
 }
 static DEVICE_ATTR_RO(current_link_speed);
 
@@ -464,7 +447,8 @@
 	}
 	return count;
 }
-static DEVICE_ATTR_WO(dev_rescan);
+static struct device_attribute dev_attr_dev_rescan = __ATTR(rescan, 0200, NULL,
+							    dev_rescan_store);
 
 static ssize_t remove_store(struct device *dev, struct device_attribute *attr,
 			    const char *buf, size_t count)
@@ -501,7 +485,33 @@
 	}
 	return count;
 }
-static DEVICE_ATTR_WO(bus_rescan);
+static struct device_attribute dev_attr_bus_rescan = __ATTR(rescan, 0200, NULL,
+							    bus_rescan_store);
+
+static ssize_t reset_subordinate_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct pci_bus *bus = pdev->subordinate;
+	unsigned long val;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	if (kstrtoul(buf, 0, &val) < 0)
+		return -EINVAL;
+
+	if (val) {
+		int ret = __pci_reset_bus(bus);
+
+		if (ret)
+			return ret;
+	}
+
+	return count;
+}
+static DEVICE_ATTR_WO(reset_subordinate);
 
 #if defined(CONFIG_PM) && defined(CONFIG_ACPI)
 static ssize_t d3cold_allowed_store(struct device *dev,
@@ -515,10 +525,7 @@
 		return -EINVAL;
 
 	pdev->d3cold_allowed = !!val;
-	if (pdev->d3cold_allowed)
-		pci_d3cold_enable(pdev);
-	else
-		pci_d3cold_disable(pdev);
+	pci_bridge_d3_update(pdev);
 
 	pm_runtime_resume(dev);
 
@@ -629,6 +636,7 @@
 static struct attribute *pci_bridge_attrs[] = {
 	&dev_attr_subordinate_bus_number.attr,
 	&dev_attr_secondary_bus_number.attr,
+	&dev_attr_reset_subordinate.attr,
 	NULL,
 };
 
@@ -1155,11 +1163,9 @@
 
 	sysfs_bin_attr_init(res_attr);
 	if (write_combine) {
-		pdev->res_attr_wc[num] = res_attr;
 		sprintf(res_attr_name, "resource%d_wc", num);
 		res_attr->mmap = pci_mmap_resource_wc;
 	} else {
-		pdev->res_attr[num] = res_attr;
 		sprintf(res_attr_name, "resource%d", num);
 		if (pci_resource_flags(pdev, num) & IORESOURCE_IO) {
 			res_attr->read = pci_read_resource_io;
@@ -1175,10 +1181,17 @@
 	res_attr->size = pci_resource_len(pdev, num);
 	res_attr->private = (void *)(unsigned long)num;
 	retval = sysfs_create_bin_file(&pdev->dev.kobj, res_attr);
-	if (retval)
+	if (retval) {
 		kfree(res_attr);
+		return retval;
+	}
 
-	return retval;
+	if (write_combine)
+		pdev->res_attr_wc[num] = res_attr;
+	else
+		pdev->res_attr[num] = res_attr;
+
+	return 0;
 }
 
 /**
@@ -1330,7 +1343,6 @@
 	int retval;
 
 	pcie_vpd_create_sysfs_dev_files(dev);
-	pcie_aspm_create_sysfs_dev_files(dev);
 
 	if (dev->reset_fn) {
 		retval = device_create_file(&dev->dev, &dev_attr_reset);
@@ -1340,7 +1352,6 @@
 	return 0;
 
 error:
-	pcie_aspm_remove_sysfs_dev_files(dev);
 	pcie_vpd_remove_sysfs_dev_files(dev);
 	return retval;
 }
@@ -1416,7 +1427,6 @@
 static void pci_remove_capabilities_sysfs(struct pci_dev *dev)
 {
 	pcie_vpd_remove_sysfs_dev_files(dev);
-	pcie_aspm_remove_sysfs_dev_files(dev);
 	if (dev->reset_fn) {
 		device_remove_file(&dev->dev, &dev_attr_reset);
 		dev->reset_fn = 0;
@@ -1588,6 +1598,9 @@
 #ifdef CONFIG_PCIEAER
 	&aer_stats_attr_group,
 #endif
+#ifdef CONFIG_PCIEASPM
+	&aspm_ctrl_attr_group,
+#endif
 	NULL,
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/pci.c
@@ -224,7 +224,7 @@
 
 	*endptr = strchrnul(path, ';');
 
-	wpath = kmemdup_nul(path, *endptr - path, GFP_KERNEL);
+	wpath = kmemdup_nul(path, *endptr - path, GFP_ATOMIC);
 	if (!wpath)
 		return -ENOMEM;
 
@@ -802,7 +802,9 @@
 
 static inline bool platform_pci_bridge_d3(struct pci_dev *dev)
 {
-	return pci_platform_pm ? pci_platform_pm->bridge_d3(dev) : false;
+	if (pci_platform_pm && pci_platform_pm->bridge_d3)
+		return pci_platform_pm->bridge_d3(dev);
+	return false;
 }
 
 /**
@@ -1019,8 +1021,6 @@
 		 * because have already delayed for the bridge.
 		 */
 		if (dev->runtime_d3cold) {
-			if (dev->d3cold_delay && !dev->imm_ready)
-				msleep(dev->d3cold_delay);
 			/*
 			 * When powering on a bridge from D3cold, the
 			 * whole hierarchy may be powered on into
@@ -1672,11 +1672,7 @@
 	 * so that things like MSI message writing will behave as expected
 	 * (e.g. if the device really is in D0 at enable time).
 	 */
-	if (dev->pm_cap) {
-		u16 pmcsr;
-		pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);
-		dev->current_state = (pmcsr & PCI_PM_CTRL_STATE_MASK);
-	}
+	pci_update_current_state(dev, dev->current_state);
 
 	if (atomic_inc_return(&dev->enable_cnt) > 1)
 		return 0;		/* already enabled */
@@ -2253,7 +2249,14 @@
 	if (enable) {
 		int error;
 
-		if (pci_pme_capable(dev, state))
+		/*
+		 * Enable PME signaling if the device can signal PME from
+		 * D3cold regardless of whether or not it can signal PME from
+		 * the current target state, because that will allow it to
+		 * signal PME when the hierarchy above it goes into D3cold and
+		 * the device itself ends up in D3cold as a result of that.
+		 */
+		if (pci_pme_capable(dev, state) || pci_pme_capable(dev, PCI_D3cold))
 			pci_pme_active(dev, true);
 		else
 			ret = 1;
@@ -2357,16 +2360,20 @@
 	if (dev->current_state == PCI_D3cold)
 		target_state = PCI_D3cold;
 
-	if (wakeup) {
+	if (wakeup && dev->pme_support) {
+		pci_power_t state = target_state;
+
 		/*
 		 * Find the deepest state from which the device can generate
 		 * PME#.
 		 */
-		if (dev->pme_support) {
-			while (target_state
-			      && !(dev->pme_support & (1 << target_state)))
-				target_state--;
-		}
+		while (state && !(dev->pme_support & (1 << state)))
+			state--;
+
+		if (state)
+			return state;
+		else if (dev->pme_support & 1)
+			return PCI_D0;
 	}
 
 	return target_state;
@@ -2607,6 +2614,30 @@
 			DMI_MATCH(DMI_BOARD_NAME, "X299 DESIGNARE EX-CF"),
 		},
 	},
+	{
+		/*
+		 * Downstream device is not accessible after putting a root port
+		 * into D3cold and back into D0 on Elo Continental Z2 board
+		 */
+		.ident = "Elo Continental Z2",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "Elo Touch Solutions"),
+			DMI_MATCH(DMI_BOARD_NAME, "Geminilake"),
+			DMI_MATCH(DMI_BOARD_VERSION, "Continental Z2"),
+		},
+	},
+	{
+		/*
+		 * Changing power state of root port dGPU is connected fails
+		 * https://gitlab.freedesktop.org/drm/amd/-/issues/3229
+		 */
+		.ident = "Hewlett-Packard HP Pavilion 17 Notebook PC/1972",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
+			DMI_MATCH(DMI_BOARD_NAME, "1972"),
+			DMI_MATCH(DMI_BOARD_VERSION, "95.33"),
+		},
+	},
 #endif
 	{ }
 };
@@ -3471,7 +3502,14 @@
 		return 0;
 
 	pci_read_config_dword(pdev, pos + PCI_REBAR_CAP, &cap);
-	return (cap & PCI_REBAR_CAP_SIZES) >> 4;
+	cap &= PCI_REBAR_CAP_SIZES;
+
+	/* Sapphire RX 5600 XT Pulse has an invalid cap dword for BAR 0 */
+	if (pdev->vendor == PCI_VENDOR_ID_ATI && pdev->device == 0x731f &&
+	    bar == 0 && cap == 0x7000)
+		cap = 0x3f000;
+
+	return cap >> 4;
 }
 
 /**
@@ -3896,6 +3934,10 @@
 	ret = logic_pio_register_range(range);
 	if (ret)
 		kfree(range);
+
+	/* Ignore duplicates due to deferred probing */
+	if (ret == -EEXIST)
+		ret = 0;
 #endif
 
 	return ret;
@@ -4453,7 +4495,7 @@
 			return -ENOTTY;
 		}
 
-		if (delay > 1000)
+		if (delay > PCI_RESET_WAIT)
 			pci_info(dev, "not ready %dms after %s; waiting\n",
 				 delay - 1, reset_type);
 
@@ -4462,7 +4504,7 @@
 		pci_read_config_dword(dev, PCI_COMMAND, &id);
 	}
 
-	if (delay > 1000)
+	if (delay > PCI_RESET_WAIT)
 		pci_info(dev, "ready %dms after %s\n", delay - 1,
 			 reset_type);
 
@@ -4605,14 +4647,17 @@
 
 	return pci_dev_wait(dev, "PM D3->D0", PCIE_RESET_READY_POLL_MS);
 }
+
 /**
- * pcie_wait_for_link - Wait until link is active or inactive
+ * pcie_wait_for_link_delay - Wait until link is active or inactive
  * @pdev: Bridge device
  * @active: waiting for active or inactive?
+ * @delay: Delay to wait after link has become active (in ms)
  *
  * Use this to wait till link becomes active or inactive.
  */
-bool pcie_wait_for_link(struct pci_dev *pdev, bool active)
+static bool pcie_wait_for_link_delay(struct pci_dev *pdev, bool active,
+				     int delay)
 {
 	int timeout = 1000;
 	bool ret;
@@ -4620,10 +4665,10 @@
 
 	/*
 	 * Some controllers might not implement link active reporting. In this
-	 * case, we wait for 1000 + 100 ms.
+	 * case, we wait for 1000 ms + any delay requested by the caller.
 	 */
 	if (!pdev->link_active_reporting) {
-		msleep(1100);
+		msleep(timeout + delay);
 		return true;
 	}
 
@@ -4649,13 +4694,146 @@
 		timeout -= 10;
 	}
 	if (active && ret)
-		msleep(100);
+		msleep(delay);
 	else if (ret != active)
 		pci_info(pdev, "Data Link Layer Link Active not %s in 1000 msec\n",
 			active ? "set" : "cleared");
 	return ret == active;
 }
 
+/**
+ * pcie_wait_for_link - Wait until link is active or inactive
+ * @pdev: Bridge device
+ * @active: waiting for active or inactive?
+ *
+ * Use this to wait till link becomes active or inactive.
+ */
+bool pcie_wait_for_link(struct pci_dev *pdev, bool active)
+{
+	return pcie_wait_for_link_delay(pdev, active, 100);
+}
+
+/*
+ * Find maximum D3cold delay required by all the devices on the bus.  The
+ * spec says 100 ms, but firmware can lower it and we allow drivers to
+ * increase it as well.
+ *
+ * Called with @pci_bus_sem locked for reading.
+ */
+static int pci_bus_max_d3cold_delay(const struct pci_bus *bus)
+{
+	const struct pci_dev *pdev;
+	int min_delay = 100;
+	int max_delay = 0;
+
+	list_for_each_entry(pdev, &bus->devices, bus_list) {
+		if (pdev->d3cold_delay < min_delay)
+			min_delay = pdev->d3cold_delay;
+		if (pdev->d3cold_delay > max_delay)
+			max_delay = pdev->d3cold_delay;
+	}
+
+	return max(min_delay, max_delay);
+}
+
+/**
+ * pci_bridge_wait_for_secondary_bus - Wait for secondary bus to be accessible
+ * @dev: PCI bridge
+ * @reset_type: reset type in human-readable form
+ * @timeout: maximum time to wait for devices on secondary bus (milliseconds)
+ *
+ * Handle necessary delays before access to the devices on the secondary
+ * side of the bridge are permitted after D3cold to D0 transition
+ * or Conventional Reset.
+ *
+ * For PCIe this means the delays in PCIe 5.0 section 6.6.1. For
+ * conventional PCI it means Tpvrh + Trhfa specified in PCI 3.0 section
+ * 4.3.2.
+ *
+ * Return 0 on success or -ENOTTY if the first device on the secondary bus
+ * failed to become accessible.
+ */
+int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type,
+				      int timeout)
+{
+	struct pci_dev *child;
+	int delay;
+
+	if (pci_dev_is_disconnected(dev))
+		return 0;
+
+	if (!pci_is_bridge(dev))
+		return 0;
+
+	down_read(&pci_bus_sem);
+
+	/*
+	 * We only deal with devices that are present currently on the bus.
+	 * For any hot-added devices the access delay is handled in pciehp
+	 * board_added(). In case of ACPI hotplug the firmware is expected
+	 * to configure the devices before OS is notified.
+	 */
+	if (!dev->subordinate || list_empty(&dev->subordinate->devices)) {
+		up_read(&pci_bus_sem);
+		return 0;
+	}
+
+	/* Take d3cold_delay requirements into account */
+	delay = pci_bus_max_d3cold_delay(dev->subordinate);
+	if (!delay) {
+		up_read(&pci_bus_sem);
+		return 0;
+	}
+
+	child = list_first_entry(&dev->subordinate->devices, struct pci_dev,
+				 bus_list);
+	up_read(&pci_bus_sem);
+
+	/*
+	 * Conventional PCI and PCI-X we need to wait Tpvrh + Trhfa before
+	 * accessing the device after reset (that is 1000 ms + 100 ms).
+	 */
+	if (!pci_is_pcie(dev)) {
+		pci_dbg(dev, "waiting %d ms for secondary bus\n", 1000 + delay);
+		msleep(1000 + delay);
+		return 0;
+	}
+
+	/*
+	 * For PCIe downstream and root ports that do not support speeds
+	 * greater than 5 GT/s need to wait minimum 100 ms. For higher
+	 * speeds (gen3) we need to wait first for the data link layer to
+	 * become active.
+	 *
+	 * However, 100 ms is the minimum and the PCIe spec says the
+	 * software must allow at least 1s before it can determine that the
+	 * device that did not respond is a broken device. There is
+	 * evidence that 100 ms is not always enough, for example certain
+	 * Titan Ridge xHCI controller does not always respond to
+	 * configuration requests if we only wait for 100 ms (see
+	 * https://bugzilla.kernel.org/show_bug.cgi?id=203885).
+	 *
+	 * Therefore we wait for 100 ms and check for the device presence
+	 * until the timeout expires.
+	 */
+	if (!pcie_downstream_port(dev))
+		return 0;
+
+	if (pcie_get_speed_cap(dev) <= PCIE_SPEED_5_0GT) {
+		pci_dbg(dev, "waiting %d ms for downstream link\n", delay);
+		msleep(delay);
+	} else {
+		pci_dbg(dev, "waiting %d ms for downstream link, after activation\n",
+			delay);
+		if (!pcie_wait_for_link_delay(dev, true, delay)) {
+			/* Did not train, no need to wait any further */
+			return -ENOTTY;
+		}
+	}
+
+	return pci_dev_wait(child, reset_type, timeout - delay);
+}
+
 void pci_reset_secondary_bus(struct pci_dev *dev)
 {
 	u16 ctrl;
@@ -4672,15 +4850,6 @@
 
 	ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET;
 	pci_write_config_word(dev, PCI_BRIDGE_CONTROL, ctrl);
-
-	/*
-	 * Trhfa for conventional PCI is 2^25 clock cycles.
-	 * Assuming a minimum 33MHz clock this results in a 1s
-	 * delay before we can consider subordinate devices to
-	 * be re-initialized.  PCIe has some ways to shorten this,
-	 * but we don't make use of them yet.
-	 */
-	ssleep(1);
 }
 
 void __weak pcibios_reset_secondary_bus(struct pci_dev *dev)
@@ -4699,7 +4868,8 @@
 {
 	pcibios_reset_secondary_bus(dev);
 
-	return pci_dev_wait(dev, "bus reset", PCIE_RESET_READY_POLL_MS);
+	return pci_bridge_wait_for_secondary_bus(dev, "bus reset",
+						 PCIE_RESET_READY_POLL_MS);
 }
 EXPORT_SYMBOL_GPL(pci_bridge_secondary_bus_reset);
 
@@ -4753,18 +4923,18 @@
 
 static void pci_dev_lock(struct pci_dev *dev)
 {
-	pci_cfg_access_lock(dev);
 	/* block PM suspend, driver probe, etc. */
 	device_lock(&dev->dev);
+	pci_cfg_access_lock(dev);
 }
 
 /* Return 1 on successful lock, 0 on contention */
 static int pci_dev_trylock(struct pci_dev *dev)
 {
-	if (pci_cfg_access_trylock(dev)) {
-		if (device_trylock(&dev->dev))
+	if (device_trylock(&dev->dev)) {
+		if (pci_cfg_access_trylock(dev))
 			return 1;
-		pci_cfg_access_unlock(dev);
+		device_unlock(&dev->dev);
 	}
 
 	return 0;
@@ -4772,8 +4942,8 @@
 
 static void pci_dev_unlock(struct pci_dev *dev)
 {
-	device_unlock(&dev->dev);
 	pci_cfg_access_unlock(dev);
+	device_unlock(&dev->dev);
 }
 
 static void pci_dev_save_and_disable(struct pci_dev *dev)
@@ -5030,10 +5200,12 @@
 {
 	struct pci_dev *dev;
 
+	pci_dev_lock(bus->self);
 	list_for_each_entry(dev, &bus->devices, bus_list) {
-		pci_dev_lock(dev);
 		if (dev->subordinate)
 			pci_bus_lock(dev->subordinate);
+		else
+			pci_dev_lock(dev);
 	}
 }
 
@@ -5045,8 +5217,10 @@
 	list_for_each_entry(dev, &bus->devices, bus_list) {
 		if (dev->subordinate)
 			pci_bus_unlock(dev->subordinate);
-		pci_dev_unlock(dev);
+		else
+			pci_dev_unlock(dev);
 	}
+	pci_dev_unlock(bus->self);
 }
 
 /* Return 1 on successful lock, 0 on contention */
@@ -5054,15 +5228,15 @@
 {
 	struct pci_dev *dev;
 
+	if (!pci_dev_trylock(bus->self))
+		return 0;
+
 	list_for_each_entry(dev, &bus->devices, bus_list) {
-		if (!pci_dev_trylock(dev))
-			goto unlock;
 		if (dev->subordinate) {
-			if (!pci_bus_trylock(dev->subordinate)) {
-				pci_dev_unlock(dev);
+			if (!pci_bus_trylock(dev->subordinate))
 				goto unlock;
-			}
-		}
+		} else if (!pci_dev_trylock(dev))
+			goto unlock;
 	}
 	return 1;
 
@@ -5070,8 +5244,10 @@
 	list_for_each_entry_continue_reverse(dev, &bus->devices, bus_list) {
 		if (dev->subordinate)
 			pci_bus_unlock(dev->subordinate);
-		pci_dev_unlock(dev);
+		else
+			pci_dev_unlock(dev);
 	}
+	pci_dev_unlock(bus->self);
 	return 0;
 }
 
@@ -5103,9 +5279,10 @@
 	list_for_each_entry(dev, &slot->bus->devices, bus_list) {
 		if (!dev->slot || dev->slot != slot)
 			continue;
-		pci_dev_lock(dev);
 		if (dev->subordinate)
 			pci_bus_lock(dev->subordinate);
+		else
+			pci_dev_lock(dev);
 	}
 }
 
@@ -5131,14 +5308,13 @@
 	list_for_each_entry(dev, &slot->bus->devices, bus_list) {
 		if (!dev->slot || dev->slot != slot)
 			continue;
-		if (!pci_dev_trylock(dev))
-			goto unlock;
 		if (dev->subordinate) {
 			if (!pci_bus_trylock(dev->subordinate)) {
 				pci_dev_unlock(dev);
 				goto unlock;
 			}
-		}
+		} else if (!pci_dev_trylock(dev))
+			goto unlock;
 	}
 	return 1;
 
@@ -5149,7 +5325,8 @@
 			continue;
 		if (dev->subordinate)
 			pci_bus_unlock(dev->subordinate);
-		pci_dev_unlock(dev);
+		else
+			pci_dev_unlock(dev);
 	}
 	return 0;
 }
@@ -5361,7 +5538,7 @@
  *
  * Same as above except return -EAGAIN if the bus cannot be locked
  */
-static int __pci_reset_bus(struct pci_bus *bus)
+int __pci_reset_bus(struct pci_bus *bus)
 {
 	int rc;
 
@@ -5657,19 +5834,10 @@
 	 * where only 2.5 GT/s and 5.0 GT/s speeds were defined.
 	 */
 	pcie_capability_read_dword(dev, PCI_EXP_LNKCAP2, &lnkcap2);
-	if (lnkcap2) { /* PCIe r3.0-compliant */
-		if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_32_0GB)
-			return PCIE_SPEED_32_0GT;
-		else if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_16_0GB)
-			return PCIE_SPEED_16_0GT;
-		else if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_8_0GB)
-			return PCIE_SPEED_8_0GT;
-		else if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_5_0GB)
-			return PCIE_SPEED_5_0GT;
-		else if (lnkcap2 & PCI_EXP_LNKCAP2_SLS_2_5GB)
-			return PCIE_SPEED_2_5GT;
-		return PCI_SPEED_UNKNOWN;
-	}
+
+	/* PCIe r3.0-compliant */
+	if (lnkcap2)
+		return PCIE_LNKCAP2_SLS2SPEED(lnkcap2);
 
 	pcie_capability_read_dword(dev, PCI_EXP_LNKCAP, &lnkcap);
 	if ((lnkcap & PCI_EXP_LNKCAP_SLS) == PCI_EXP_LNKCAP_SLS_5_0GB)
@@ -5745,14 +5913,14 @@
 	if (bw_avail >= bw_cap && verbose)
 		pci_info(dev, "%u.%03u Gb/s available PCIe bandwidth (%s x%d link)\n",
 			 bw_cap / 1000, bw_cap % 1000,
-			 PCIE_SPEED2STR(speed_cap), width_cap);
+			 pci_speed_string(speed_cap), width_cap);
 	else if (bw_avail < bw_cap)
 		pci_info(dev, "%u.%03u Gb/s available PCIe bandwidth, limited by %s x%d link at %s (capable of %u.%03u Gb/s with %s x%d link)\n",
 			 bw_avail / 1000, bw_avail % 1000,
-			 PCIE_SPEED2STR(speed), width,
+			 pci_speed_string(speed), width,
 			 limiting_dev ? pci_name(limiting_dev) : "<unknown>",
 			 bw_cap / 1000, bw_cap % 1000,
-			 PCIE_SPEED2STR(speed_cap), width_cap);
+			 pci_speed_string(speed_cap), width_cap);
 }
 
 /**
@@ -5854,10 +6022,29 @@
 	return 0;
 }
 
+#ifdef CONFIG_ACPI
+bool pci_pr3_present(struct pci_dev *pdev)
+{
+	struct acpi_device *adev;
+
+	if (acpi_disabled)
+		return false;
+
+	adev = ACPI_COMPANION(&pdev->dev);
+	if (!adev)
+		return false;
+
+	return adev->power.flags.power_resources &&
+		acpi_has_method(adev->handle, "_PR3");
+}
+EXPORT_SYMBOL_GPL(pci_pr3_present);
+#endif
+
 /**
  * pci_add_dma_alias - Add a DMA devfn alias for a device
  * @dev: the PCI device for which alias is added
- * @devfn: alias slot and function
+ * @devfn_from: alias slot and function
+ * @nr_devfns: number of subsequent devfns to alias
  *
  * This helper encodes an 8-bit devfn as a bit number in dma_alias_mask
  * which is used to program permissible bus-devfn source addresses for DMA
@@ -5873,18 +6060,29 @@
  * cannot be left as a userspace activity).  DMA aliases should therefore
  * be configured via quirks, such as the PCI fixup header quirk.
  */
-void pci_add_dma_alias(struct pci_dev *dev, u8 devfn)
+void pci_add_dma_alias(struct pci_dev *dev, u8 devfn_from, unsigned nr_devfns)
 {
+	int devfn_to;
+
+	nr_devfns = min(nr_devfns, (unsigned) MAX_NR_DEVFNS - devfn_from);
+	devfn_to = devfn_from + nr_devfns - 1;
+
 	if (!dev->dma_alias_mask)
-		dev->dma_alias_mask = bitmap_zalloc(U8_MAX, GFP_KERNEL);
+		dev->dma_alias_mask = bitmap_zalloc(MAX_NR_DEVFNS, GFP_KERNEL);
 	if (!dev->dma_alias_mask) {
 		pci_warn(dev, "Unable to allocate DMA alias mask\n");
 		return;
 	}
 
-	set_bit(devfn, dev->dma_alias_mask);
-	pci_info(dev, "Enabling fixed DMA alias to %02x.%d\n",
-		 PCI_SLOT(devfn), PCI_FUNC(devfn));
+	bitmap_set(dev->dma_alias_mask, devfn_from, nr_devfns);
+
+	if (nr_devfns == 1)
+		pci_info(dev, "Enabling fixed DMA alias to %02x.%d\n",
+				PCI_SLOT(devfn_from), PCI_FUNC(devfn_from));
+	else if (nr_devfns > 1)
+		pci_info(dev, "Enabling fixed DMA alias for devfn range from %02x.%d to %02x.%d\n",
+				PCI_SLOT(devfn_from), PCI_FUNC(devfn_from),
+				PCI_SLOT(devfn_to), PCI_FUNC(devfn_to));
 }
 
 bool pci_devs_are_dma_aliases(struct pci_dev *dev1, struct pci_dev *dev2)
@@ -5899,6 +6097,8 @@
 {
 	u32 v;
 
+	/* Check PF if pdev is a VF, since VF Vendor/Device IDs are 0xffff */
+	pdev = pci_physfn(pdev);
 	if (pci_dev_is_disconnected(pdev))
 		return false;
 	return pci_bus_read_dev_vendor_id(pdev->bus, pdev->devfn, &v, 0);
@@ -5965,19 +6165,21 @@
 	while (*p) {
 		count = 0;
 		if (sscanf(p, "%d%n", &align_order, &count) == 1 &&
-							p[count] == '@') {
+		    p[count] == '@') {
 			p += count + 1;
+			if (align_order > 63) {
+				pr_err("PCI: Invalid requested alignment (order %d)\n",
+				       align_order);
+				align_order = PAGE_SHIFT;
+			}
 		} else {
-			align_order = -1;
+			align_order = PAGE_SHIFT;
 		}
 
 		ret = pci_dev_str_match(dev, p, &p);
 		if (ret == 1) {
 			*resize = true;
-			if (align_order == -1)
-				align = PAGE_SIZE;
-			else
-				align = 1 << align_order;
+			align = 1ULL << align_order;
 			break;
 		} else if (ret < 0) {
 			pr_err("PCI: Can't parse resource_alignment parameter: %s\n",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/pci.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/pci.h
@@ -4,6 +4,9 @@
 
 #include <linux/pci.h>
 
+/* Number of possible devfns: 0.0 to 1f.7 inclusive */
+#define MAX_NR_DEVFNS 256
+
 #define PCI_FIND_CAP_TTL	48
 
 #define PCI_VSEC_ID_INTEL_TBT	0x1234	/* Thunderbolt */
@@ -38,12 +41,20 @@
 int pci_probe_reset_function(struct pci_dev *dev);
 int pci_bridge_secondary_bus_reset(struct pci_dev *dev);
 int pci_bus_error_reset(struct pci_dev *dev);
+int __pci_reset_bus(struct pci_bus *bus);
 
 #define PCI_PM_D2_DELAY         200
 #define PCI_PM_D3_WAIT          10
 #define PCI_PM_D3COLD_WAIT      100
 #define PCI_PM_BUS_WAIT         50
 
+/*
+ * Following exit from Conventional Reset, devices must be ready within 1 sec
+ * (PCIe r6.0 sec 6.6.1).  A D3cold to D0 transition implies a Conventional
+ * Reset (PCIe r6.0 sec 5.8).
+ */
+#define PCI_RESET_WAIT		1000	/* msec */
+
 /**
  * struct pci_platform_pm_ops - Firmware PM callbacks
  *
@@ -104,6 +115,8 @@
 void pci_free_cap_save_buffers(struct pci_dev *dev);
 bool pci_bridge_d3_possible(struct pci_dev *dev);
 void pci_bridge_d3_update(struct pci_dev *dev);
+int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type,
+				      int timeout);
 
 static inline void pci_wakeup_event(struct pci_dev *dev)
 {
@@ -286,22 +299,25 @@
 struct pci_bus *pci_bus_get(struct pci_bus *bus);
 void pci_bus_put(struct pci_bus *bus);
 
-/* PCIe link information */
-#define PCIE_SPEED2STR(speed) \
-	((speed) == PCIE_SPEED_16_0GT ? "16 GT/s" : \
-	 (speed) == PCIE_SPEED_8_0GT ? "8 GT/s" : \
-	 (speed) == PCIE_SPEED_5_0GT ? "5 GT/s" : \
-	 (speed) == PCIE_SPEED_2_5GT ? "2.5 GT/s" : \
-	 "Unknown speed")
+/* PCIe link information from Link Capabilities 2 */
+#define PCIE_LNKCAP2_SLS2SPEED(lnkcap2) \
+	((lnkcap2) & PCI_EXP_LNKCAP2_SLS_32_0GB ? PCIE_SPEED_32_0GT : \
+	 (lnkcap2) & PCI_EXP_LNKCAP2_SLS_16_0GB ? PCIE_SPEED_16_0GT : \
+	 (lnkcap2) & PCI_EXP_LNKCAP2_SLS_8_0GB ? PCIE_SPEED_8_0GT : \
+	 (lnkcap2) & PCI_EXP_LNKCAP2_SLS_5_0GB ? PCIE_SPEED_5_0GT : \
+	 (lnkcap2) & PCI_EXP_LNKCAP2_SLS_2_5GB ? PCIE_SPEED_2_5GT : \
+	 PCI_SPEED_UNKNOWN)
 
 /* PCIe speed to Mb/s reduced by encoding overhead */
 #define PCIE_SPEED2MBS_ENC(speed) \
-	((speed) == PCIE_SPEED_16_0GT ? 16000*128/130 : \
+	((speed) == PCIE_SPEED_32_0GT ? 32000*128/130 : \
+	 (speed) == PCIE_SPEED_16_0GT ? 16000*128/130 : \
 	 (speed) == PCIE_SPEED_8_0GT  ?  8000*128/130 : \
 	 (speed) == PCIE_SPEED_5_0GT  ?  5000*8/10 : \
 	 (speed) == PCIE_SPEED_2_5GT  ?  2500*8/10 : \
 	 0)
 
+const char *pci_speed_string(enum pci_bus_speed speed);
 enum pci_bus_speed pcie_get_speed_cap(struct pci_dev *dev);
 enum pcie_link_width pcie_get_width_cap(struct pci_dev *dev);
 u32 pcie_bandwidth_capable(struct pci_dev *dev, enum pci_bus_speed *speed,
@@ -342,62 +358,40 @@
  * @dev - pci device to set new error_state
  * @new - the state we want dev to be in
  *
- * Must be called with device_lock held.
+ * If the device is experiencing perm_failure, it has to remain in that state.
+ * Any other transition is allowed.
  *
  * Returns true if state has been changed to the requested state.
  */
 static inline bool pci_dev_set_io_state(struct pci_dev *dev,
 					pci_channel_state_t new)
 {
-	bool changed = false;
+	pci_channel_state_t old;
 
-	device_lock_assert(&dev->dev);
 	switch (new) {
 	case pci_channel_io_perm_failure:
-		switch (dev->error_state) {
-		case pci_channel_io_frozen:
-		case pci_channel_io_normal:
-		case pci_channel_io_perm_failure:
-			changed = true;
-			break;
-		}
-		break;
+		xchg(&dev->error_state, pci_channel_io_perm_failure);
+		return true;
 	case pci_channel_io_frozen:
-		switch (dev->error_state) {
-		case pci_channel_io_frozen:
-		case pci_channel_io_normal:
-			changed = true;
-			break;
-		}
-		break;
+		old = cmpxchg(&dev->error_state, pci_channel_io_normal,
+			      pci_channel_io_frozen);
+		return old != pci_channel_io_perm_failure;
 	case pci_channel_io_normal:
-		switch (dev->error_state) {
-		case pci_channel_io_frozen:
-		case pci_channel_io_normal:
-			changed = true;
-			break;
-		}
-		break;
+		old = cmpxchg(&dev->error_state, pci_channel_io_frozen,
+			      pci_channel_io_normal);
+		return old != pci_channel_io_perm_failure;
+	default:
+		return false;
 	}
-	if (changed)
-		dev->error_state = new;
-	return changed;
 }
 
 static inline int pci_dev_set_disconnected(struct pci_dev *dev, void *unused)
 {
-	device_lock(&dev->dev);
 	pci_dev_set_io_state(dev, pci_channel_io_perm_failure);
-	device_unlock(&dev->dev);
 
 	return 0;
 }
 
-static inline bool pci_dev_is_disconnected(const struct pci_dev *dev)
-{
-	return dev->error_state == pci_channel_io_perm_failure;
-}
-
 /* pci_dev priv_flags */
 #define PCI_DEV_ADDED 0
 
@@ -541,14 +535,6 @@
 static inline void pcie_aspm_powersave_config_link(struct pci_dev *pdev) { }
 #endif
 
-#ifdef CONFIG_PCIEASPM_DEBUG
-void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev);
-void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev);
-#else
-static inline void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev) { }
-static inline void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev) { }
-#endif
-
 #ifdef CONFIG_PCIE_ECRC
 void pcie_set_ecrc_checking(struct pci_dev *dev);
 void pcie_ecrc_get_policy(char *str);
@@ -584,6 +570,12 @@
 #if defined(CONFIG_PCI_QUIRKS) && defined(CONFIG_ARM64)
 int acpi_get_rc_resources(struct device *dev, const char *hid, u16 segment,
 			  struct resource *res);
+#else
+static inline int acpi_get_rc_resources(struct device *dev, const char *hid,
+					u16 segment, struct resource *res)
+{
+	return -ENODEV;
+}
 #endif
 
 u32 pci_rebar_get_possible_sizes(struct pci_dev *pdev, int bar);
@@ -667,4 +659,8 @@
 }
 #endif
 
+#ifdef CONFIG_PCIEASPM
+extern const struct attribute_group aspm_ctrl_attr_group;
+#endif
+
 #endif /* DRIVERS_PCI_H */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/pcie/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/pcie/Kconfig
@@ -79,13 +79,6 @@
 
 	  When in doubt, say Y.
 
-config PCIEASPM_DEBUG
-	bool "Debug PCI Express ASPM"
-	depends on PCIEASPM
-	help
-	  This enables PCI Express ASPM debug support. It will add per-device
-	  interface to control ASPM.
-
 choice
 	prompt "Default ASPM policy"
 	default PCIEASPM_DEFAULT
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/pcie/aer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/pcie/aer.c
@@ -782,7 +782,7 @@
 	u8 bus = info->id >> 8;
 	u8 devfn = info->id & 0xff;
 
-	pci_info(dev, "%s%s error received: %04x:%02x:%02x.%d\n",
+	pci_info(dev, "%s%s error message received from %04x:%02x:%02x.%d\n",
 		 info->multi_error_valid ? "Multiple " : "",
 		 aer_error_severity_string[info->severity],
 		 pci_domain_nr(dev->bus), bus, PCI_SLOT(devfn),
@@ -968,7 +968,12 @@
 	pci_walk_bus(parent->subordinate, find_device_iter, e_info);
 
 	if (!e_info->error_dev_num) {
-		pci_info(parent, "can't find device of ID%04x\n", e_info->id);
+		u8 bus = e_info->id >> 8;
+		u8 devfn = e_info->id & 0xff;
+
+		pci_info(parent, "found no error details for %04x:%02x:%02x.%d\n",
+			 pci_domain_nr(parent->bus), bus, PCI_SLOT(devfn),
+			 PCI_FUNC(devfn));
 		return false;
 	}
 	return true;
@@ -1212,7 +1217,7 @@
 {
 	struct pcie_device *dev = (struct pcie_device *)context;
 	struct aer_rpc *rpc = get_service_data(dev);
-	struct aer_err_source uninitialized_var(e_src);
+	struct aer_err_source e_src;
 
 	if (kfifo_is_empty(&rpc->aer_fifo))
 		return IRQ_NONE;
@@ -1387,6 +1392,7 @@
 		return -ENOMEM;
 
 	rpc->rpd = port;
+	INIT_KFIFO(rpc->aer_fifo);
 	set_service_data(dev, rpc);
 
 	status = devm_request_threaded_irq(device, dev->irq, aer_irq, aer_isr,
@@ -1401,6 +1407,22 @@
 	return 0;
 }
 
+static int aer_suspend(struct pcie_device *dev)
+{
+	struct aer_rpc *rpc = get_service_data(dev);
+
+	aer_disable_rootport(rpc);
+	return 0;
+}
+
+static int aer_resume(struct pcie_device *dev)
+{
+	struct aer_rpc *rpc = get_service_data(dev);
+
+	aer_enable_rootport(rpc);
+	return 0;
+}
+
 /**
  * aer_root_reset - reset link on Root Port
  * @dev: pointer to Root Port's pci_dev data structure
@@ -1441,6 +1463,8 @@
 	.service	= PCIE_PORT_SERVICE_AER,
 
 	.probe		= aer_probe,
+	.suspend	= aer_suspend,
+	.resume		= aer_resume,
 	.remove		= aer_remove,
 	.reset_link	= aer_root_reset,
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/pcie/aspm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/pcie/aspm.c
@@ -64,6 +64,7 @@
 	u32 clkpm_capable:1;		/* Clock PM capable? */
 	u32 clkpm_enabled:1;		/* Current Clock PM state */
 	u32 clkpm_default:1;		/* Default Clock PM state by BIOS */
+	u32 clkpm_disable:1;		/* Clock PM disabled */
 
 	/* Exit latencies */
 	struct aspm_latency latency_up;	/* Upstream direction exit latency */
@@ -161,8 +162,11 @@
 
 static void pcie_set_clkpm(struct pcie_link_state *link, int enable)
 {
-	/* Don't enable Clock PM if the link is not Clock PM capable */
-	if (!link->clkpm_capable)
+	/*
+	 * Don't enable Clock PM if the link is not Clock PM capable
+	 * or Clock PM is disabled
+	 */
+	if (!link->clkpm_capable || link->clkpm_disable)
 		enable = 0;
 	/* Need nothing if the specified equals to current state */
 	if (link->clkpm_enabled == enable)
@@ -192,15 +196,43 @@
 	}
 	link->clkpm_enabled = enabled;
 	link->clkpm_default = enabled;
-	link->clkpm_capable = (blacklist) ? 0 : capable;
+	link->clkpm_capable = capable;
+	link->clkpm_disable = blacklist ? 1 : 0;
 }
 
-static bool pcie_retrain_link(struct pcie_link_state *link)
+static int pcie_wait_for_retrain(struct pci_dev *pdev)
 {
-	struct pci_dev *parent = link->pdev;
 	unsigned long end_jiffies;
 	u16 reg16;
 
+	/* Wait for Link Training to be cleared by hardware */
+	end_jiffies = jiffies + LINK_RETRAIN_TIMEOUT;
+	do {
+		pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &reg16);
+		if (!(reg16 & PCI_EXP_LNKSTA_LT))
+			return 0;
+		msleep(1);
+	} while (time_before(jiffies, end_jiffies));
+
+	return -ETIMEDOUT;
+}
+
+static int pcie_retrain_link(struct pcie_link_state *link)
+{
+	struct pci_dev *parent = link->pdev;
+	int rc;
+	u16 reg16;
+
+	/*
+	 * Ensure the updated LNKCTL parameters are used during link
+	 * training by checking that there is no ongoing link training to
+	 * avoid LTSSM race as recommended in Implementation Note at the
+	 * end of PCIe r6.0.1 sec 7.5.3.7.
+	 */
+	rc = pcie_wait_for_retrain(parent);
+	if (rc)
+		return rc;
+
 	pcie_capability_read_word(parent, PCI_EXP_LNKCTL, &reg16);
 	reg16 |= PCI_EXP_LNKCTL_RL;
 	pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16);
@@ -214,15 +246,7 @@
 		pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16);
 	}
 
-	/* Wait for link training end. Break out after waiting for timeout */
-	end_jiffies = jiffies + LINK_RETRAIN_TIMEOUT;
-	do {
-		pcie_capability_read_word(parent, PCI_EXP_LNKSTA, &reg16);
-		if (!(reg16 & PCI_EXP_LNKSTA_LT))
-			break;
-		msleep(1);
-	} while (time_before(jiffies, end_jiffies));
-	return !(reg16 & PCI_EXP_LNKSTA_LT);
+	return pcie_wait_for_retrain(parent);
 }
 
 /*
@@ -233,7 +257,7 @@
 static void pcie_aspm_configure_common_clock(struct pcie_link_state *link)
 {
 	int same_clock = 1;
-	u16 reg16, parent_reg, child_reg[8];
+	u16 reg16, ccc, parent_old_ccc, child_old_ccc[8];
 	struct pci_dev *child, *parent = link->pdev;
 	struct pci_bus *linkbus = parent->subordinate;
 	/*
@@ -255,6 +279,7 @@
 
 	/* Port might be already in common clock mode */
 	pcie_capability_read_word(parent, PCI_EXP_LNKCTL, &reg16);
+	parent_old_ccc = reg16 & PCI_EXP_LNKCTL_CCC;
 	if (same_clock && (reg16 & PCI_EXP_LNKCTL_CCC)) {
 		bool consistent = true;
 
@@ -271,35 +296,30 @@
 		pci_warn(parent, "ASPM: current common clock configuration is broken, reconfiguring\n");
 	}
 
+	ccc = same_clock ? PCI_EXP_LNKCTL_CCC : 0;
 	/* Configure downstream component, all functions */
 	list_for_each_entry(child, &linkbus->devices, bus_list) {
 		pcie_capability_read_word(child, PCI_EXP_LNKCTL, &reg16);
-		child_reg[PCI_FUNC(child->devfn)] = reg16;
-		if (same_clock)
-			reg16 |= PCI_EXP_LNKCTL_CCC;
-		else
-			reg16 &= ~PCI_EXP_LNKCTL_CCC;
-		pcie_capability_write_word(child, PCI_EXP_LNKCTL, reg16);
+		child_old_ccc[PCI_FUNC(child->devfn)] = reg16 & PCI_EXP_LNKCTL_CCC;
+		pcie_capability_clear_and_set_word(child, PCI_EXP_LNKCTL,
+						   PCI_EXP_LNKCTL_CCC, ccc);
 	}
 
 	/* Configure upstream component */
-	pcie_capability_read_word(parent, PCI_EXP_LNKCTL, &reg16);
-	parent_reg = reg16;
-	if (same_clock)
-		reg16 |= PCI_EXP_LNKCTL_CCC;
-	else
-		reg16 &= ~PCI_EXP_LNKCTL_CCC;
-	pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16);
+	pcie_capability_clear_and_set_word(parent, PCI_EXP_LNKCTL,
+					   PCI_EXP_LNKCTL_CCC, ccc);
 
-	if (pcie_retrain_link(link))
-		return;
+	if (pcie_retrain_link(link)) {
 
-	/* Training failed. Restore common clock configurations */
-	pci_err(parent, "ASPM: Could not configure common clock\n");
-	list_for_each_entry(child, &linkbus->devices, bus_list)
-		pcie_capability_write_word(child, PCI_EXP_LNKCTL,
-					   child_reg[PCI_FUNC(child->devfn)]);
-	pcie_capability_write_word(parent, PCI_EXP_LNKCTL, parent_reg);
+		/* Training failed. Restore common clock configurations */
+		pci_err(parent, "ASPM: Could not configure common clock\n");
+		list_for_each_entry(child, &linkbus->devices, bus_list)
+			pcie_capability_clear_and_set_word(child, PCI_EXP_LNKCTL,
+							   PCI_EXP_LNKCTL_CCC,
+							   child_old_ccc[PCI_FUNC(child->devfn)]);
+		pcie_capability_clear_and_set_word(parent, PCI_EXP_LNKCTL,
+						   PCI_EXP_LNKCTL_CCC, parent_old_ccc);
+	}
 }
 
 /* Convert L0s latency encoding to ns */
@@ -623,16 +643,6 @@
 
 	/* Setup initial capable state. Will be updated later */
 	link->aspm_capable = link->aspm_support;
-	/*
-	 * If the downstream component has pci bridge function, don't
-	 * do ASPM for now.
-	 */
-	list_for_each_entry(child, &linkbus->devices, bus_list) {
-		if (pci_pcie_type(child) == PCI_EXP_TYPE_PCI_BRIDGE) {
-			link->aspm_disable = ASPM_STATE_ALL;
-			break;
-		}
-	}
 
 	/* Get and check endpoint acceptable latencies */
 	list_for_each_entry(child, &linkbus->devices, bus_list) {
@@ -742,9 +752,9 @@
 
 	/* Enable what we need to enable */
 	pci_clear_and_set_dword(parent, up_cap_ptr + PCI_L1SS_CTL1,
-				PCI_L1SS_CAP_L1_PM_SS, val);
+				PCI_L1SS_CTL1_L1SS_MASK, val);
 	pci_clear_and_set_dword(child, dw_cap_ptr + PCI_L1SS_CTL1,
-				PCI_L1SS_CAP_L1_PM_SS, val);
+				PCI_L1SS_CTL1_L1SS_MASK, val);
 }
 
 static void pcie_config_aspm_dev(struct pci_dev *pdev, u32 val)
@@ -894,6 +904,14 @@
 	return link;
 }
 
+static void pcie_aspm_update_sysfs_visibility(struct pci_dev *pdev)
+{
+	struct pci_dev *child;
+
+	list_for_each_entry(child, &pdev->subordinate->devices, bus_list)
+		sysfs_update_group(&child->dev.kobj, &aspm_ctrl_attr_group);
+}
+
 /*
  * pcie_aspm_init_link_state: Initiate PCI express link state.
  * It is called after the pcie and its children devices are scanned.
@@ -955,6 +973,8 @@
 		pcie_set_clkpm(link, policy_to_clkpm_state(link));
 	}
 
+	pcie_aspm_update_sysfs_visibility(pdev);
+
 unlock:
 	mutex_unlock(&aspm_lock);
 out:
@@ -996,21 +1016,24 @@
 
 	down_read(&pci_bus_sem);
 	mutex_lock(&aspm_lock);
-	/*
-	 * All PCIe functions are in one slot, remove one function will remove
-	 * the whole slot, so just wait until we are the last function left.
-	 */
-	if (!list_empty(&parent->subordinate->devices))
-		goto out;
 
 	link = parent->link_state;
 	root = link->root;
 	parent_link = link->parent;
 
-	/* All functions are removed, so just disable ASPM for the link */
+	/*
+	 * Free the parent link state, no later than function 0 (i.e.
+	 * link->downstream) being removed.
+	 *
+	 * Do not free the link state any earlier. If function 0 is a
+	 * switch upstream port, this link state is parent_link to all
+	 * subordinate ones.
+	 */
+	if (pdev != link->downstream)
+		goto out;
+
 	pcie_config_aspm_link(link, 0);
 	list_del(&link->sibling);
-	/* Clock PM is for endpoint device */
 	free_link_state(link);
 
 	/* Recheck latencies and configure upstream links */
@@ -1018,7 +1041,8 @@
 		pcie_update_aspm_capable(root);
 		pcie_config_aspm_path(parent_link);
 	}
-out:
+
+ out:
 	mutex_unlock(&aspm_lock);
 	up_read(&pci_bus_sem);
 }
@@ -1061,19 +1085,26 @@
 	up_read(&pci_bus_sem);
 }
 
-static int __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem)
+static struct pcie_link_state *pcie_aspm_get_link(struct pci_dev *pdev)
 {
-	struct pci_dev *parent = pdev->bus->self;
-	struct pcie_link_state *link;
+	struct pci_dev *bridge;
 
 	if (!pci_is_pcie(pdev))
-		return 0;
+		return NULL;
 
-	if (pcie_downstream_port(pdev))
-		parent = pdev;
-	if (!parent || !parent->link_state)
-		return -EINVAL;
+	bridge = pci_upstream_bridge(pdev);
+	if (!bridge || !pci_is_pcie(bridge))
+		return NULL;
 
+	return bridge->link_state;
+}
+
+static int __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem)
+{
+	struct pcie_link_state *link = pcie_aspm_get_link(pdev);
+
+	if (!link)
+		return -EINVAL;
 	/*
 	 * A driver requested that ASPM be disabled on this device, but
 	 * if we don't have permission to manage ASPM (e.g., on ACPI
@@ -1090,17 +1121,24 @@
 	if (sem)
 		down_read(&pci_bus_sem);
 	mutex_lock(&aspm_lock);
-	link = parent->link_state;
 	if (state & PCIE_LINK_STATE_L0S)
 		link->aspm_disable |= ASPM_STATE_L0S;
 	if (state & PCIE_LINK_STATE_L1)
-		link->aspm_disable |= ASPM_STATE_L1;
+		/* L1 PM substates require L1 */
+		link->aspm_disable |= ASPM_STATE_L1 | ASPM_STATE_L1SS;
+	if (state & PCIE_LINK_STATE_L1_1)
+		link->aspm_disable |= ASPM_STATE_L1_1;
+	if (state & PCIE_LINK_STATE_L1_2)
+		link->aspm_disable |= ASPM_STATE_L1_2;
+	if (state & PCIE_LINK_STATE_L1_1_PCIPM)
+		link->aspm_disable |= ASPM_STATE_L1_1_PCIPM;
+	if (state & PCIE_LINK_STATE_L1_2_PCIPM)
+		link->aspm_disable |= ASPM_STATE_L1_2_PCIPM;
 	pcie_config_aspm_link(link, policy_to_aspm_state(link));
 
-	if (state & PCIE_LINK_STATE_CLKPM) {
-		link->clkpm_capable = 0;
-		pcie_set_clkpm(link, 0);
-	}
+	if (state & PCIE_LINK_STATE_CLKPM)
+		link->clkpm_disable = 1;
+	pcie_set_clkpm(link, policy_to_clkpm_state(link));
 	mutex_unlock(&aspm_lock);
 	if (sem)
 		up_read(&pci_bus_sem);
@@ -1163,6 +1201,7 @@
 			cnt += sprintf(buffer + cnt, "[%s] ", policy_str[i]);
 		else
 			cnt += sprintf(buffer + cnt, "%s ", policy_str[i]);
+	cnt += sprintf(buffer + cnt, "\n");
 	return cnt;
 }
 
@@ -1172,127 +1211,161 @@
 /**
  * pcie_aspm_enabled - Check if PCIe ASPM has been enabled for a device.
  * @pdev: Target device.
+ *
+ * Relies on the upstream bridge's link_state being valid.  The link_state
+ * is deallocated only when the last child of the bridge (i.e., @pdev or a
+ * sibling) is removed, and the caller should be holding a reference to
+ * @pdev, so this should be safe.
  */
 bool pcie_aspm_enabled(struct pci_dev *pdev)
 {
-	struct pci_dev *bridge = pci_upstream_bridge(pdev);
-	bool ret;
+	struct pcie_link_state *link = pcie_aspm_get_link(pdev);
 
-	if (!bridge)
+	if (!link)
 		return false;
 
-	mutex_lock(&aspm_lock);
-	ret = bridge->link_state ? !!bridge->link_state->aspm_enabled : false;
-	mutex_unlock(&aspm_lock);
-
-	return ret;
+	return link->aspm_enabled;
 }
 EXPORT_SYMBOL_GPL(pcie_aspm_enabled);
 
-#ifdef CONFIG_PCIEASPM_DEBUG
-static ssize_t link_state_show(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
+static ssize_t aspm_attr_show_common(struct device *dev,
+				     struct device_attribute *attr,
+				     char *buf, u8 state)
 {
-	struct pci_dev *pci_device = to_pci_dev(dev);
-	struct pcie_link_state *link_state = pci_device->link_state;
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct pcie_link_state *link = pcie_aspm_get_link(pdev);
 
-	return sprintf(buf, "%d\n", link_state->aspm_enabled);
+	return sprintf(buf, "%d\n", (link->aspm_enabled & state) ? 1 : 0);
 }
 
-static ssize_t link_state_store(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t n)
+static ssize_t aspm_attr_store_common(struct device *dev,
+				      struct device_attribute *attr,
+				      const char *buf, size_t len, u8 state)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
-	struct pcie_link_state *link, *root = pdev->link_state->root;
-	u32 state;
-
-	if (aspm_disabled)
-		return -EPERM;
+	struct pcie_link_state *link = pcie_aspm_get_link(pdev);
+	bool state_enable;
 
-	if (kstrtouint(buf, 10, &state))
-		return -EINVAL;
-	if ((state & ~ASPM_STATE_ALL) != 0)
+	if (strtobool(buf, &state_enable) < 0)
 		return -EINVAL;
 
 	down_read(&pci_bus_sem);
 	mutex_lock(&aspm_lock);
-	list_for_each_entry(link, &link_list, sibling) {
-		if (link->root != root)
-			continue;
-		pcie_config_aspm_link(link, state);
+
+	if (state_enable) {
+		link->aspm_disable &= ~state;
+		/* need to enable L1 for substates */
+		if (state & ASPM_STATE_L1SS)
+			link->aspm_disable &= ~ASPM_STATE_L1;
+	} else {
+		link->aspm_disable |= state;
 	}
+
+	pcie_config_aspm_link(link, policy_to_aspm_state(link));
+
 	mutex_unlock(&aspm_lock);
 	up_read(&pci_bus_sem);
-	return n;
+
+	return len;
 }
 
-static ssize_t clk_ctl_show(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
+#define ASPM_ATTR(_f, _s)						\
+static ssize_t _f##_show(struct device *dev,				\
+			 struct device_attribute *attr, char *buf)	\
+{ return aspm_attr_show_common(dev, attr, buf, ASPM_STATE_##_s); }	\
+									\
+static ssize_t _f##_store(struct device *dev,				\
+			  struct device_attribute *attr,		\
+			  const char *buf, size_t len)			\
+{ return aspm_attr_store_common(dev, attr, buf, len, ASPM_STATE_##_s); }
+
+ASPM_ATTR(l0s_aspm, L0S)
+ASPM_ATTR(l1_aspm, L1)
+ASPM_ATTR(l1_1_aspm, L1_1)
+ASPM_ATTR(l1_2_aspm, L1_2)
+ASPM_ATTR(l1_1_pcipm, L1_1_PCIPM)
+ASPM_ATTR(l1_2_pcipm, L1_2_PCIPM)
+
+static ssize_t clkpm_show(struct device *dev,
+			  struct device_attribute *attr, char *buf)
 {
-	struct pci_dev *pci_device = to_pci_dev(dev);
-	struct pcie_link_state *link_state = pci_device->link_state;
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct pcie_link_state *link = pcie_aspm_get_link(pdev);
 
-	return sprintf(buf, "%d\n", link_state->clkpm_enabled);
+	return sprintf(buf, "%d\n", link->clkpm_enabled);
 }
 
-static ssize_t clk_ctl_store(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t n)
+static ssize_t clkpm_store(struct device *dev,
+			   struct device_attribute *attr,
+			   const char *buf, size_t len)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
-	bool state;
+	struct pcie_link_state *link = pcie_aspm_get_link(pdev);
+	bool state_enable;
 
-	if (strtobool(buf, &state))
+	if (strtobool(buf, &state_enable) < 0)
 		return -EINVAL;
 
 	down_read(&pci_bus_sem);
 	mutex_lock(&aspm_lock);
-	pcie_set_clkpm_nocheck(pdev->link_state, state);
+
+	link->clkpm_disable = !state_enable;
+	pcie_set_clkpm(link, policy_to_clkpm_state(link));
+
 	mutex_unlock(&aspm_lock);
 	up_read(&pci_bus_sem);
 
-	return n;
+	return len;
 }
 
-static DEVICE_ATTR_RW(link_state);
-static DEVICE_ATTR_RW(clk_ctl);
+static DEVICE_ATTR_RW(clkpm);
+static DEVICE_ATTR_RW(l0s_aspm);
+static DEVICE_ATTR_RW(l1_aspm);
+static DEVICE_ATTR_RW(l1_1_aspm);
+static DEVICE_ATTR_RW(l1_2_aspm);
+static DEVICE_ATTR_RW(l1_1_pcipm);
+static DEVICE_ATTR_RW(l1_2_pcipm);
+
+static struct attribute *aspm_ctrl_attrs[] = {
+	&dev_attr_clkpm.attr,
+	&dev_attr_l0s_aspm.attr,
+	&dev_attr_l1_aspm.attr,
+	&dev_attr_l1_1_aspm.attr,
+	&dev_attr_l1_2_aspm.attr,
+	&dev_attr_l1_1_pcipm.attr,
+	&dev_attr_l1_2_pcipm.attr,
+	NULL
+};
 
-static char power_group[] = "power";
-void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev)
+static umode_t aspm_ctrl_attrs_are_visible(struct kobject *kobj,
+					   struct attribute *a, int n)
 {
-	struct pcie_link_state *link_state = pdev->link_state;
-
-	if (!link_state)
-		return;
-
-	if (link_state->aspm_support)
-		sysfs_add_file_to_group(&pdev->dev.kobj,
-			&dev_attr_link_state.attr, power_group);
-	if (link_state->clkpm_capable)
-		sysfs_add_file_to_group(&pdev->dev.kobj,
-			&dev_attr_clk_ctl.attr, power_group);
-}
+	struct device *dev = kobj_to_dev(kobj);
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct pcie_link_state *link = pcie_aspm_get_link(pdev);
+	static const u8 aspm_state_map[] = {
+		ASPM_STATE_L0S,
+		ASPM_STATE_L1,
+		ASPM_STATE_L1_1,
+		ASPM_STATE_L1_2,
+		ASPM_STATE_L1_1_PCIPM,
+		ASPM_STATE_L1_2_PCIPM,
+	};
 
-void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev)
-{
-	struct pcie_link_state *link_state = pdev->link_state;
+	if (aspm_disabled || !link)
+		return 0;
 
-	if (!link_state)
-		return;
+	if (n == 0)
+		return link->clkpm_capable ? a->mode : 0;
 
-	if (link_state->aspm_support)
-		sysfs_remove_file_from_group(&pdev->dev.kobj,
-			&dev_attr_link_state.attr, power_group);
-	if (link_state->clkpm_capable)
-		sysfs_remove_file_from_group(&pdev->dev.kobj,
-			&dev_attr_clk_ctl.attr, power_group);
+	return link->aspm_capable & aspm_state_map[n - 1] ? a->mode : 0;
 }
-#endif
+
+const struct attribute_group aspm_ctrl_attr_group = {
+	.name = "link",
+	.attrs = aspm_ctrl_attrs,
+	.is_visible = aspm_ctrl_attrs_are_visible,
+};
 
 static int __init pcie_aspm_disable(char *str)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/pcie/dpc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/pcie/dpc.c
@@ -195,7 +195,7 @@
 
 	for (i = 0; i < dpc->rp_log_size - 5; i++) {
 		pci_read_config_dword(pdev,
-			cap + PCI_EXP_DPC_RP_PIO_TLPPREFIX_LOG, &prefix);
+			cap + PCI_EXP_DPC_RP_PIO_TLPPREFIX_LOG + i * 4, &prefix);
 		pci_err(pdev, "TLP Prefix Header: dw%d, %#010x\n", i, prefix);
 	}
  clear_status:
@@ -291,7 +291,7 @@
 	int status;
 	u16 ctl, cap;
 
-	if (pcie_aer_get_firmware_first(pdev))
+	if (pcie_aer_get_firmware_first(pdev) && !pcie_ports_dpc_native)
 		return -ENOTSUPP;
 
 	dpc = devm_kzalloc(device, sizeof(*dpc), GFP_KERNEL);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/pcie/portdrv.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/pcie/portdrv.h
@@ -25,6 +25,8 @@
 
 #define PCIE_PORT_DEVICE_MAXSERVICES   5
 
+extern bool pcie_ports_dpc_native;
+
 #ifdef CONFIG_PCIEAER
 int pcie_aer_init(void);
 #else
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/pcie/portdrv_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/pcie/portdrv_core.c
@@ -214,10 +214,12 @@
 
 		/*
 		 * Disable hot-plug interrupts in case they have been enabled
-		 * by the BIOS and the hot-plug service driver is not loaded.
+		 * by the BIOS and the hot-plug service driver won't be loaded
+		 * to handle them.
 		 */
-		pcie_capability_clear_word(dev, PCI_EXP_SLTCTL,
-			  PCI_EXP_SLTCTL_CCIE | PCI_EXP_SLTCTL_HPIE);
+		if (!IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE))
+			pcie_capability_clear_word(dev, PCI_EXP_SLTCTL,
+				PCI_EXP_SLTCTL_CCIE | PCI_EXP_SLTCTL_HPIE);
 	}
 
 #ifdef CONFIG_PCIEAER
@@ -250,13 +252,23 @@
 		pcie_pme_interrupt_enable(dev, false);
 	}
 
+	/*
+	 * With dpc-native, allow Linux to use DPC even if it doesn't have
+	 * permission to use AER.
+	 */
 	if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_DPC) &&
-	    pci_aer_available() && services & PCIE_PORT_SERVICE_AER)
+	    pci_aer_available() &&
+	    (pcie_ports_dpc_native || (services & PCIE_PORT_SERVICE_AER)))
 		services |= PCIE_PORT_SERVICE_DPC;
 
 	if (pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM ||
-	    pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT)
-		services |= PCIE_PORT_SERVICE_BWNOTIF;
+	    pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT) {
+		u32 linkcap;
+
+		pcie_capability_read_dword(dev, PCI_EXP_LNKCAP, &linkcap);
+		if (linkcap & PCI_EXP_LNKCAP_LBNC)
+			services |= PCIE_PORT_SERVICE_BWNOTIF;
+	}
 
 	return services;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/pcie/portdrv_pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/pcie/portdrv_pci.c
@@ -29,12 +29,20 @@
  */
 bool pcie_ports_native;
 
+/*
+ * If the user specified "pcie_ports=dpc-native", use the Linux DPC PCIe
+ * service even if the platform hasn't given us permission.
+ */
+bool pcie_ports_dpc_native;
+
 static int __init pcie_port_setup(char *str)
 {
 	if (!strncmp(str, "compat", 6))
 		pcie_ports_disabled = true;
 	else if (!strncmp(str, "native", 6))
 		pcie_ports_native = true;
+	else if (!strncmp(str, "dpc-native", 10))
+		pcie_ports_dpc_native = true;
 
 	return 1;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/pcie/ptm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/pcie/ptm.c
@@ -21,7 +21,7 @@
 		snprintf(clock_desc, sizeof(clock_desc), ">254ns");
 		break;
 	default:
-		snprintf(clock_desc, sizeof(clock_desc), "%udns",
+		snprintf(clock_desc, sizeof(clock_desc), "%uns",
 			 dev->ptm_granularity);
 		break;
 	}
@@ -39,10 +39,6 @@
 	if (!pci_is_pcie(dev))
 		return;
 
-	pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_PTM);
-	if (!pos)
-		return;
-
 	/*
 	 * Enable PTM only on interior devices (root ports, switch ports,
 	 * etc.) on the assumption that it causes no link traffic until an
@@ -52,6 +48,23 @@
 	     pci_pcie_type(dev) == PCI_EXP_TYPE_RC_END))
 		return;
 
+	/*
+	 * Switch Downstream Ports are not permitted to have a PTM
+	 * capability; their PTM behavior is controlled by the Upstream
+	 * Port (PCIe r5.0, sec 7.9.16).
+	 */
+	ups = pci_upstream_bridge(dev);
+	if (pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM &&
+	    ups && ups->ptm_enabled) {
+		dev->ptm_granularity = ups->ptm_granularity;
+		dev->ptm_enabled = 1;
+		return;
+	}
+
+	pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_PTM);
+	if (!pos)
+		return;
+
 	pci_read_config_dword(dev, pos + PCI_PTM_CAP, &cap);
 	local_clock = (cap & PCI_PTM_GRANULARITY_MASK) >> 8;
 
@@ -61,7 +74,6 @@
 	 * the spec recommendation (PCIe r3.1, sec 7.32.3), select the
 	 * furthest upstream Time Source as the PTM Root.
 	 */
-	ups = pci_upstream_bridge(dev);
 	if (ups && ups->ptm_enabled) {
 		ctrl = PCI_PTM_CTRL_ENABLE;
 		if (ups->ptm_granularity == 0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/probe.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/probe.c
@@ -564,7 +564,7 @@
 	return b;
 }
 
-static void devm_pci_release_host_bridge_dev(struct device *dev)
+static void pci_release_host_bridge_dev(struct device *dev)
 {
 	struct pci_host_bridge *bridge = to_pci_host_bridge(dev);
 
@@ -572,12 +572,8 @@
 		bridge->release_fn(bridge);
 
 	pci_free_resource_list(&bridge->windows);
-}
-
-static void pci_release_host_bridge_dev(struct device *dev)
-{
-	devm_pci_release_host_bridge_dev(dev);
-	kfree(to_pci_host_bridge(dev));
+	pci_free_resource_list(&bridge->dma_ranges);
+	kfree(bridge);
 }
 
 static void pci_init_host_bridge(struct pci_host_bridge *bridge)
@@ -596,6 +592,8 @@
 	bridge->native_shpc_hotplug = 1;
 	bridge->native_pme = 1;
 	bridge->native_ltr = 1;
+
+	device_initialize(&bridge->dev);
 }
 
 struct pci_host_bridge *pci_alloc_host_bridge(size_t priv)
@@ -613,17 +611,25 @@
 }
 EXPORT_SYMBOL(pci_alloc_host_bridge);
 
+static void devm_pci_alloc_host_bridge_release(void *data)
+{
+	pci_free_host_bridge(data);
+}
+
 struct pci_host_bridge *devm_pci_alloc_host_bridge(struct device *dev,
 						   size_t priv)
 {
+	int ret;
 	struct pci_host_bridge *bridge;
 
-	bridge = devm_kzalloc(dev, sizeof(*bridge) + priv, GFP_KERNEL);
+	bridge = pci_alloc_host_bridge(priv);
 	if (!bridge)
 		return NULL;
 
-	pci_init_host_bridge(bridge);
-	bridge->dev.release = devm_pci_release_host_bridge_dev;
+	ret = devm_add_action_or_reset(dev, devm_pci_alloc_host_bridge_release,
+				       bridge);
+	if (ret)
+		return NULL;
 
 	return bridge;
 }
@@ -631,13 +637,11 @@
 
 void pci_free_host_bridge(struct pci_host_bridge *bridge)
 {
-	pci_free_resource_list(&bridge->windows);
-	pci_free_resource_list(&bridge->dma_ranges);
-
-	kfree(bridge);
+	put_device(&bridge->dev);
 }
 EXPORT_SYMBOL(pci_free_host_bridge);
 
+/* Indexed by PCI_X_SSTATUS_FREQ (secondary bus mode and frequency) */
 static const unsigned char pcix_bus_speed[] = {
 	PCI_SPEED_UNKNOWN,		/* 0 */
 	PCI_SPEED_66MHz_PCIX,		/* 1 */
@@ -657,6 +661,7 @@
 	PCI_SPEED_133MHz_PCIX_533	/* F */
 };
 
+/* Indexed by PCI_EXP_LNKCAP_SLS, PCI_EXP_LNKSTA_CLS */
 const unsigned char pcie_link_speed[] = {
 	PCI_SPEED_UNKNOWN,		/* 0 */
 	PCIE_SPEED_2_5GT,		/* 1 */
@@ -675,6 +680,44 @@
 	PCI_SPEED_UNKNOWN,		/* E */
 	PCI_SPEED_UNKNOWN		/* F */
 };
+EXPORT_SYMBOL_GPL(pcie_link_speed);
+
+const char *pci_speed_string(enum pci_bus_speed speed)
+{
+	/* Indexed by the pci_bus_speed enum */
+	static const char *speed_strings[] = {
+	    "33 MHz PCI",		/* 0x00 */
+	    "66 MHz PCI",		/* 0x01 */
+	    "66 MHz PCI-X",		/* 0x02 */
+	    "100 MHz PCI-X",		/* 0x03 */
+	    "133 MHz PCI-X",		/* 0x04 */
+	    NULL,			/* 0x05 */
+	    NULL,			/* 0x06 */
+	    NULL,			/* 0x07 */
+	    NULL,			/* 0x08 */
+	    "66 MHz PCI-X 266",		/* 0x09 */
+	    "100 MHz PCI-X 266",	/* 0x0a */
+	    "133 MHz PCI-X 266",	/* 0x0b */
+	    "Unknown AGP",		/* 0x0c */
+	    "1x AGP",			/* 0x0d */
+	    "2x AGP",			/* 0x0e */
+	    "4x AGP",			/* 0x0f */
+	    "8x AGP",			/* 0x10 */
+	    "66 MHz PCI-X 533",		/* 0x11 */
+	    "100 MHz PCI-X 533",	/* 0x12 */
+	    "133 MHz PCI-X 533",	/* 0x13 */
+	    "2.5 GT/s PCIe",		/* 0x14 */
+	    "5.0 GT/s PCIe",		/* 0x15 */
+	    "8.0 GT/s PCIe",		/* 0x16 */
+	    "16.0 GT/s PCIe",		/* 0x17 */
+	    "32.0 GT/s PCIe",		/* 0x18 */
+	};
+
+	if (speed < ARRAY_SIZE(speed_strings))
+		return speed_strings[speed];
+	return "Unknown";
+}
+EXPORT_SYMBOL_GPL(pci_speed_string);
 
 void pcie_update_link_speed(struct pci_bus *bus, u16 linksta)
 {
@@ -865,9 +908,9 @@
 	if (err)
 		goto free;
 
-	err = device_register(&bridge->dev);
+	err = device_add(&bridge->dev);
 	if (err)
-		put_device(&bridge->dev);
+		goto free;
 
 	bus->bridge = get_device(&bridge->dev);
 	device_enable_async_suspend(bus->bridge);
@@ -931,7 +974,7 @@
 
 unregister:
 	put_device(&bridge->dev);
-	device_unregister(&bridge->dev);
+	device_del(&bridge->dev);
 
 free:
 	kfree(bus);
@@ -1089,14 +1132,15 @@
  * @sec: updated with secondary bus number from EA
  * @sub: updated with subordinate bus number from EA
  *
- * If @dev is a bridge with EA capability, update @sec and @sub with
- * fixed bus numbers from the capability and return true.  Otherwise,
- * return false.
+ * If @dev is a bridge with EA capability that specifies valid secondary
+ * and subordinate bus numbers, return true with the bus numbers in @sec
+ * and @sub.  Otherwise return false.
  */
 static bool pci_ea_fixed_busnrs(struct pci_dev *dev, u8 *sec, u8 *sub)
 {
 	int ea, offset;
 	u32 dw;
+	u8 ea_sec, ea_sub;
 
 	if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE)
 		return false;
@@ -1108,8 +1152,13 @@
 
 	offset = ea + PCI_EA_FIRST_ENT;
 	pci_read_config_dword(dev, offset, &dw);
-	*sec =  dw & PCI_EA_SEC_BUS_MASK;
-	*sub = (dw & PCI_EA_SUB_BUS_MASK) >> PCI_EA_SUB_BUS_SHIFT;
+	ea_sec =  dw & PCI_EA_SEC_BUS_MASK;
+	ea_sub = (dw & PCI_EA_SUB_BUS_MASK) >> PCI_EA_SUB_BUS_SHIFT;
+	if (ea_sec  == 0 || ea_sub < ea_sec)
+		return false;
+
+	*sec = ea_sec;
+	*sub = ea_sub;
 	return true;
 }
 
@@ -1770,7 +1819,7 @@
 	/* Device class may be changed after fixup */
 	class = dev->class >> 8;
 
-	if (dev->non_compliant_bars) {
+	if (dev->non_compliant_bars && !dev->mmio_always_on) {
 		pci_read_config_word(dev, PCI_COMMAND, &cmd);
 		if (cmd & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
 			pci_info(dev, "device has non-compliant BARs; disabling IO/MEM decoding\n");
@@ -1882,13 +1931,33 @@
 	struct pci_dev *bridge = pci_upstream_bridge(dev);
 	int mps, mpss, p_mps, rc;
 
-	if (!pci_is_pcie(dev) || !bridge || !pci_is_pcie(bridge))
+	if (!pci_is_pcie(dev))
 		return;
 
 	/* MPS and MRRS fields are of type 'RsvdP' for VFs, short-circuit out */
 	if (dev->is_virtfn)
 		return;
 
+	/*
+	 * For Root Complex Integrated Endpoints, program the maximum
+	 * supported value unless limited by the PCIE_BUS_PEER2PEER case.
+	 */
+	if (pci_pcie_type(dev) == PCI_EXP_TYPE_RC_END) {
+		if (pcie_bus_config == PCIE_BUS_PEER2PEER)
+			mps = 128;
+		else
+			mps = 128 << dev->pcie_mpss;
+		rc = pcie_set_mps(dev, mps);
+		if (rc) {
+			pci_warn(dev, "can't set Max Payload Size to %d; if necessary, use \"pci=pcie_bus_safe\" and report a bug\n",
+				 mps);
+		}
+		return;
+	}
+
+	if (!bridge || !pci_is_pcie(bridge))
+		return;
+
 	mps = pcie_get_mps(dev);
 	p_mps = pcie_get_mps(bridge);
 
@@ -2271,6 +2340,7 @@
 	pci_set_of_node(dev);
 
 	if (pci_setup_device(dev)) {
+		pci_release_of_node(dev);
 		pci_bus_put(dev->bus);
 		kfree(dev);
 		return NULL;
@@ -2916,7 +2986,7 @@
 	return bridge->bus;
 
 err_out:
-	kfree(bridge);
+	put_device(&bridge->dev);
 	return NULL;
 }
 EXPORT_SYMBOL_GPL(pci_create_root_bus);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/quirks.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/quirks.c
@@ -27,6 +27,7 @@
 #include <linux/nvme.h>
 #include <linux/platform_data/x86/apple.h>
 #include <linux/pm_runtime.h>
+#include <linux/suspend.h>
 #include <linux/switchtec.h>
 #include <asm/dma.h>	/* isa_dma_bridge_buggy */
 #include "pci.h"
@@ -205,6 +206,21 @@
 DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_ANY_ID, PCI_ANY_ID,
 				PCI_CLASS_BRIDGE_HOST, 8, quirk_mmio_always_on);
 
+/* The BAR0 ~ BAR4 of Marvell 9125 device can't be accessed
+*  by IO resource file, and need to skip the files
+*/
+static void quirk_marvell_mask_bar(struct pci_dev *dev)
+{
+	int i;
+
+	for (i = 0; i < 5; i++)
+		if (dev->resource[i].start)
+			dev->resource[i].start =
+				dev->resource[i].end = 0;
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9125,
+				quirk_marvell_mask_bar);
+
 /*
  * The Mellanox Tavor device gives false positive parity errors.  Mark this
  * device with a broken_parity_status to allow PCI scanning code to "skip"
@@ -596,7 +612,7 @@
 /*
  * In the AMD NL platform, this device ([1022:7912]) has a class code of
  * PCI_CLASS_SERIAL_USB_XHCI (0x0c0330), which means the xhci driver will
- * claim it.
+ * claim it. The same applies on the VanGogh platform device ([1022:163a]).
  *
  * But the dwc3 driver is a more specific driver for this device, and we'd
  * prefer to use it instead of xhci. To prevent xhci from claiming the
@@ -604,17 +620,22 @@
  * defines as "USB device (not host controller)". The dwc3 driver can then
  * claim it based on its Vendor and Device ID.
  */
-static void quirk_amd_nl_class(struct pci_dev *pdev)
+static void quirk_amd_dwc_class(struct pci_dev *pdev)
 {
 	u32 class = pdev->class;
 
-	/* Use "USB Device (not host controller)" class */
-	pdev->class = PCI_CLASS_SERIAL_USB_DEVICE;
-	pci_info(pdev, "PCI class overridden (%#08x -> %#08x) so dwc3 driver can claim this instead of xhci\n",
-		 class, pdev->class);
+	if (class != PCI_CLASS_SERIAL_USB_DEVICE) {
+		/* Use "USB Device (not host controller)" class */
+		pdev->class = PCI_CLASS_SERIAL_USB_DEVICE;
+		pci_info(pdev,
+			"PCI class overridden (%#08x -> %#08x) so dwc3 driver can claim this instead of xhci\n",
+			class, pdev->class);
+	}
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_NL_USB,
-		quirk_amd_nl_class);
+		quirk_amd_dwc_class);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VANGOGH_USB,
+		quirk_amd_dwc_class);
 
 /*
  * Synopsys USB 3.x host HAPS platform has a class code of
@@ -1871,19 +1892,41 @@
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	0x260a, quirk_intel_pcie_pm);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	0x260b, quirk_intel_pcie_pm);
 
+static void quirk_d3hot_delay(struct pci_dev *dev, unsigned int delay)
+{
+	if (dev->d3_delay >= delay)
+		return;
+
+	dev->d3_delay = delay;
+	pci_info(dev, "extending delay after power-on from D3hot to %d msec\n",
+		 dev->d3_delay);
+}
+
 static void quirk_radeon_pm(struct pci_dev *dev)
 {
 	if (dev->subsystem_vendor == PCI_VENDOR_ID_APPLE &&
-	    dev->subsystem_device == 0x00e2) {
-		if (dev->d3_delay < 20) {
-			dev->d3_delay = 20;
-			pci_info(dev, "extending delay after power-on from D3 to %d msec\n",
-				 dev->d3_delay);
-		}
-	}
+	    dev->subsystem_device == 0x00e2)
+		quirk_d3hot_delay(dev, 20);
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x6741, quirk_radeon_pm);
 
+/*
+ * Ryzen5/7 XHCI controllers fail upon resume from runtime suspend or s2idle.
+ * https://bugzilla.kernel.org/show_bug.cgi?id=205587
+ *
+ * The kernel attempts to transition these devices to D3cold, but that seems
+ * to be ineffective on the platforms in question; the PCI device appears to
+ * remain on in D3hot state. The D3hot-to-D0 transition then requires an
+ * extended delay in order to succeed.
+ */
+static void quirk_ryzen_xhci_d3hot(struct pci_dev *dev)
+{
+	quirk_d3hot_delay(dev, 20);
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x15e0, quirk_ryzen_xhci_d3hot);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x15e1, quirk_ryzen_xhci_d3hot);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x1639, quirk_ryzen_xhci_d3hot);
+
 #ifdef CONFIG_X86_IO_APIC
 static int dmi_disable_ioapicreroute(const struct dmi_system_id *d)
 {
@@ -1949,26 +1992,92 @@
 /*
  * IO-APIC1 on 6300ESB generates boot interrupts, see Intel order no
  * 300641-004US, section 5.7.3.
+ *
+ * Core IO on Xeon E5 1600/2600/4600, see Intel order no 326509-003.
+ * Core IO on Xeon E5 v2, see Intel order no 329188-003.
+ * Core IO on Xeon E7 v2, see Intel order no 329595-002.
+ * Core IO on Xeon E5 v3, see Intel order no 330784-003.
+ * Core IO on Xeon E7 v3, see Intel order no 332315-001US.
+ * Core IO on Xeon E5 v4, see Intel order no 333810-002US.
+ * Core IO on Xeon E7 v4, see Intel order no 332315-001US.
+ * Core IO on Xeon D-1500, see Intel order no 332051-001.
+ * Core IO on Xeon Scalable, see Intel order no 610950.
  */
-#define INTEL_6300_IOAPIC_ABAR		0x40
+#define INTEL_6300_IOAPIC_ABAR		0x40	/* Bus 0, Dev 29, Func 5 */
 #define INTEL_6300_DISABLE_BOOT_IRQ	(1<<14)
 
+#define INTEL_CIPINTRC_CFG_OFFSET	0x14C	/* Bus 0, Dev 5, Func 0 */
+#define INTEL_CIPINTRC_DIS_INTX_ICH	(1<<25)
+
 static void quirk_disable_intel_boot_interrupt(struct pci_dev *dev)
 {
 	u16 pci_config_word;
+	u32 pci_config_dword;
 
 	if (noioapicquirk)
 		return;
 
-	pci_read_config_word(dev, INTEL_6300_IOAPIC_ABAR, &pci_config_word);
-	pci_config_word |= INTEL_6300_DISABLE_BOOT_IRQ;
-	pci_write_config_word(dev, INTEL_6300_IOAPIC_ABAR, pci_config_word);
-
+	switch (dev->device) {
+	case PCI_DEVICE_ID_INTEL_ESB_10:
+		pci_read_config_word(dev, INTEL_6300_IOAPIC_ABAR,
+				     &pci_config_word);
+		pci_config_word |= INTEL_6300_DISABLE_BOOT_IRQ;
+		pci_write_config_word(dev, INTEL_6300_IOAPIC_ABAR,
+				      pci_config_word);
+		break;
+	case 0x3c28:	/* Xeon E5 1600/2600/4600	*/
+	case 0x0e28:	/* Xeon E5/E7 V2		*/
+	case 0x2f28:	/* Xeon E5/E7 V3,V4		*/
+	case 0x6f28:	/* Xeon D-1500			*/
+	case 0x2034:	/* Xeon Scalable Family		*/
+		pci_read_config_dword(dev, INTEL_CIPINTRC_CFG_OFFSET,
+				      &pci_config_dword);
+		pci_config_dword |= INTEL_CIPINTRC_DIS_INTX_ICH;
+		pci_write_config_dword(dev, INTEL_CIPINTRC_CFG_OFFSET,
+				       pci_config_dword);
+		break;
+	default:
+		return;
+	}
 	pci_info(dev, "disabled boot interrupts on device [%04x:%04x]\n",
 		 dev->vendor, dev->device);
 }
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_ESB_10,	quirk_disable_intel_boot_interrupt);
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_ESB_10,	quirk_disable_intel_boot_interrupt);
+/*
+ * Device 29 Func 5 Device IDs of IO-APIC
+ * containing ABAR—APIC1 Alternate Base Address Register
+ */
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ESB_10,
+		quirk_disable_intel_boot_interrupt);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_ESB_10,
+		quirk_disable_intel_boot_interrupt);
+
+/*
+ * Device 5 Func 0 Device IDs of Core IO modules/hubs
+ * containing Coherent Interface Protocol Interrupt Control
+ *
+ * Device IDs obtained from volume 2 datasheets of commented
+ * families above.
+ */
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	0x3c28,
+		quirk_disable_intel_boot_interrupt);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	0x0e28,
+		quirk_disable_intel_boot_interrupt);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	0x2f28,
+		quirk_disable_intel_boot_interrupt);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	0x6f28,
+		quirk_disable_intel_boot_interrupt);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	0x2034,
+		quirk_disable_intel_boot_interrupt);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	0x3c28,
+		quirk_disable_intel_boot_interrupt);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	0x0e28,
+		quirk_disable_intel_boot_interrupt);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	0x2f28,
+		quirk_disable_intel_boot_interrupt);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	0x6f28,
+		quirk_disable_intel_boot_interrupt);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	0x2034,
+		quirk_disable_intel_boot_interrupt);
 
 /* Disable boot interrupts on HT-1000 */
 #define BC_HT1000_FEATURE_REG		0x64
@@ -2243,6 +2352,19 @@
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10f4, quirk_disable_aspm_l0s);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1508, quirk_disable_aspm_l0s);
 
+static void quirk_disable_aspm_l0s_l1(struct pci_dev *dev)
+{
+	pci_info(dev, "Disabling ASPM L0s/L1\n");
+	pci_disable_link_state(dev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
+}
+
+/*
+ * ASM1083/1085 PCIe-PCI bridge devices cause AER timeout errors on the
+ * upstream PCIe root port when ASPM is enabled. At least L0s mode is affected;
+ * disable both L0s and L1 for now to be safe.
+ */
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASMEDIA, 0x1080, quirk_disable_aspm_l0s_l1);
+
 /*
  * Some Pericom PCIe-to-PCI bridges in reverse mode need the PCIe Retrain
  * Link bit cleared after starting the link retrain process to allow this
@@ -2381,32 +2503,6 @@
 			 PCI_DEVICE_ID_TIGON3_5719,
 			 quirk_brcm_5719_limit_mrrs);
 
-#ifdef CONFIG_PCIE_IPROC_PLATFORM
-static void quirk_paxc_bridge(struct pci_dev *pdev)
-{
-	/*
-	 * The PCI config space is shared with the PAXC root port and the first
-	 * Ethernet device.  So, we need to workaround this by telling the PCI
-	 * code that the bridge is not an Ethernet device.
-	 */
-	if (pdev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
-		pdev->class = PCI_CLASS_BRIDGE_PCI << 8;
-
-	/*
-	 * MPSS is not being set properly (as it is currently 0).  This is
-	 * because that area of the PCI config space is hard coded to zero, and
-	 * is not modifiable by firmware.  Set this to 2 (e.g., 512 byte MPS)
-	 * so that the MPS can be set to the real max value.
-	 */
-	pdev->pcie_mpss = 2;
-}
-DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0x16cd, quirk_paxc_bridge);
-DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0x16f0, quirk_paxc_bridge);
-DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0xd750, quirk_paxc_bridge);
-DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0xd802, quirk_paxc_bridge);
-DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0xd804, quirk_paxc_bridge);
-#endif
-
 /*
  * Originally in EDAC sources for i82875P: Intel tells BIOS developers to
  * hide device 6 which configures the overflow device access containing the
@@ -3170,12 +3266,13 @@
 {
 	dev->pcie_mpss = 1; /* 256 bytes */
 }
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SOLARFLARE,
-			 PCI_DEVICE_ID_SOLARFLARE_SFC4000A_0, fixup_mpss_256);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SOLARFLARE,
-			 PCI_DEVICE_ID_SOLARFLARE_SFC4000A_1, fixup_mpss_256);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SOLARFLARE,
-			 PCI_DEVICE_ID_SOLARFLARE_SFC4000B, fixup_mpss_256);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SOLARFLARE,
+			PCI_DEVICE_ID_SOLARFLARE_SFC4000A_0, fixup_mpss_256);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SOLARFLARE,
+			PCI_DEVICE_ID_SOLARFLARE_SFC4000A_1, fixup_mpss_256);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SOLARFLARE,
+			PCI_DEVICE_ID_SOLARFLARE_SFC4000B, fixup_mpss_256);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ASMEDIA, 0x0612, fixup_mpss_256);
 
 /*
  * Intel 5000 and 5100 Memory controllers have an erratum with read completion
@@ -3359,6 +3456,8 @@
 			quirk_broken_intx_masking);
 DECLARE_PCI_FIXUP_FINAL(0x1b7c, 0x0004, /* Ceton InfiniTV4 */
 			quirk_broken_intx_masking);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_20K2,
+			quirk_broken_intx_masking);
 
 /*
  * Realtek RTL8169 PCI Gigabit Ethernet Controller (rev 10)
@@ -3484,6 +3583,18 @@
 }
 
 /*
+ * Some NVIDIA GPU devices do not work with bus reset, SBR needs to be
+ * prevented for those affected devices.
+ */
+static void quirk_nvidia_no_bus_reset(struct pci_dev *dev)
+{
+	if ((dev->device & 0xffc0) == 0x2340)
+		quirk_no_bus_reset(dev);
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
+			 quirk_nvidia_no_bus_reset);
+
+/*
  * Some Atheros AR9xxx and QCA988x chips do not behave after a bus reset.
  * The device will throw a Link Down error on AER-capable systems and
  * regardless of AER, config space of the device is never accessible again
@@ -3495,6 +3606,7 @@
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x003c, quirk_no_bus_reset);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0033, quirk_no_bus_reset);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x0034, quirk_no_bus_reset);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x003e, quirk_no_bus_reset);
 
 /*
  * Root port on some Cavium CN8xxx chips do not successfully complete a bus
@@ -3503,6 +3615,16 @@
  */
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CAVIUM, 0xa100, quirk_no_bus_reset);
 
+/*
+ * Some TI KeyStone C667X devices do not support bus/hot reset.  The PCIESS
+ * automatically disables LTSSM when Secondary Bus Reset is received and
+ * the device stops working.  Prevent bus reset for these devices.  With
+ * this change, the device can be assigned to VMs with VFIO, but it will
+ * leak state between VMs.  Reference
+ * https://e2e.ti.com/support/processors/f/791/t/954382
+ */
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TI, 0xb005, quirk_no_bus_reset);
+
 static void quirk_no_pm_reset(struct pci_dev *dev)
 {
 	/*
@@ -3525,6 +3647,19 @@
 			       PCI_CLASS_DISPLAY_VGA, 8, quirk_no_pm_reset);
 
 /*
+ * Spectrum-{1,2,3,4} devices report that a D3hot->D0 transition causes a reset
+ * (i.e., they advertise NoSoftRst-). However, this transition does not have
+ * any effect on the device: It continues to be operational and network ports
+ * remain up. Advertising this support makes it seem as if a PM reset is viable
+ * for these devices. Mark it as unavailable to skip it when testing reset
+ * methods.
+ */
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MELLANOX, 0xcb84, quirk_no_pm_reset);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MELLANOX, 0xcf6c, quirk_no_pm_reset);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MELLANOX, 0xcf70, quirk_no_pm_reset);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MELLANOX, 0xcf80, quirk_no_pm_reset);
+
+/*
  * Thunderbolt controllers with broken MSI hotplug signaling:
  * Entire 1st generation (Light Ridge, Eagle Ridge, Light Peak) and part
  * of the 2nd generation (Cactus Ridge 4C up to revision 1, Port Ridge).
@@ -3571,6 +3706,16 @@
 		return;
 	if (pci_pcie_type(dev) != PCI_EXP_TYPE_UPSTREAM)
 		return;
+
+	/*
+	 * SXIO/SXFP/SXLF turns off power to the Thunderbolt controller.
+	 * We don't know how to turn it back on again, but firmware does,
+	 * so we can only use SXIO/SXFP/SXLF if we're suspending via
+	 * firmware.
+	 */
+	if (!pm_suspend_via_firmware())
+		return;
+
 	bridge = ACPI_HANDLE(&dev->dev);
 	if (!bridge)
 		return;
@@ -3895,6 +4040,69 @@
 	return 0;
 }
 
+#define PCI_DEVICE_ID_HINIC_VF      0x375E
+#define HINIC_VF_FLR_TYPE           0x1000
+#define HINIC_VF_FLR_CAP_BIT        (1UL << 30)
+#define HINIC_VF_OP                 0xE80
+#define HINIC_VF_FLR_PROC_BIT       (1UL << 18)
+#define HINIC_OPERATION_TIMEOUT     15000	/* 15 seconds */
+
+/* Device-specific reset method for Huawei Intelligent NIC virtual functions */
+static int reset_hinic_vf_dev(struct pci_dev *pdev, int probe)
+{
+	unsigned long timeout;
+	void __iomem *bar;
+	u32 val;
+
+	if (probe)
+		return 0;
+
+	bar = pci_iomap(pdev, 0, 0);
+	if (!bar)
+		return -ENOTTY;
+
+	/* Get and check firmware capabilities */
+	val = ioread32be(bar + HINIC_VF_FLR_TYPE);
+	if (!(val & HINIC_VF_FLR_CAP_BIT)) {
+		pci_iounmap(pdev, bar);
+		return -ENOTTY;
+	}
+
+	/* Set HINIC_VF_FLR_PROC_BIT for the start of FLR */
+	val = ioread32be(bar + HINIC_VF_OP);
+	val = val | HINIC_VF_FLR_PROC_BIT;
+	iowrite32be(val, bar + HINIC_VF_OP);
+
+	pcie_flr(pdev);
+
+	/*
+	 * The device must recapture its Bus and Device Numbers after FLR
+	 * in order generate Completions.  Issue a config write to let the
+	 * device capture this information.
+	 */
+	pci_write_config_word(pdev, PCI_VENDOR_ID, 0);
+
+	/* Firmware clears HINIC_VF_FLR_PROC_BIT when reset is complete */
+	timeout = jiffies + msecs_to_jiffies(HINIC_OPERATION_TIMEOUT);
+	do {
+		val = ioread32be(bar + HINIC_VF_OP);
+		if (!(val & HINIC_VF_FLR_PROC_BIT))
+			goto reset_complete;
+		msleep(20);
+	} while (time_before(jiffies, timeout));
+
+	val = ioread32be(bar + HINIC_VF_OP);
+	if (!(val & HINIC_VF_FLR_PROC_BIT))
+		goto reset_complete;
+
+	pci_warn(pdev, "Reset dev timeout, FLR ack reg: %#010x\n", val);
+
+reset_complete:
+	pci_iounmap(pdev, bar);
+
+	return 0;
+}
+
 static const struct pci_dev_reset_methods pci_dev_reset_methods[] = {
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82599_SFP_VF,
 		 reset_intel_82599_sfp_virtfn },
@@ -3906,6 +4114,8 @@
 	{ PCI_VENDOR_ID_INTEL, 0x0953, delay_250ms_after_flr },
 	{ PCI_VENDOR_ID_CHELSIO, PCI_ANY_ID,
 		reset_chelsio_generic_dev },
+	{ PCI_VENDOR_ID_HUAWEI, PCI_DEVICE_ID_HINIC_VF,
+		reset_hinic_vf_dev },
 	{ 0 }
 };
 
@@ -3932,7 +4142,7 @@
 static void quirk_dma_func0_alias(struct pci_dev *dev)
 {
 	if (PCI_FUNC(dev->devfn) != 0)
-		pci_add_dma_alias(dev, PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
+		pci_add_dma_alias(dev, PCI_DEVFN(PCI_SLOT(dev->devfn), 0), 1);
 }
 
 /*
@@ -3943,10 +4153,14 @@
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_RICOH, 0xe832, quirk_dma_func0_alias);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_RICOH, 0xe476, quirk_dma_func0_alias);
 
+/* Some Glenfly chips use function 0 as the PCIe Requester ID for DMA */
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_GLENFLY, 0x3d40, quirk_dma_func0_alias);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_GLENFLY, 0x3d41, quirk_dma_func0_alias);
+
 static void quirk_dma_func1_alias(struct pci_dev *dev)
 {
 	if (PCI_FUNC(dev->devfn) != 1)
-		pci_add_dma_alias(dev, PCI_DEVFN(PCI_SLOT(dev->devfn), 1));
+		pci_add_dma_alias(dev, PCI_DEVFN(PCI_SLOT(dev->devfn), 1), 1);
 }
 
 /*
@@ -3959,6 +4173,9 @@
 			 quirk_dma_func1_alias);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9123,
 			 quirk_dma_func1_alias);
+/* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c136 */
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9125,
+			 quirk_dma_func1_alias);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9128,
 			 quirk_dma_func1_alias);
 /* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c14 */
@@ -3981,12 +4198,17 @@
 /* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c46 */
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x91a0,
 			 quirk_dma_func1_alias);
+/* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c135 */
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9215,
+			 quirk_dma_func1_alias);
 /* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c127 */
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9220,
 			 quirk_dma_func1_alias);
 /* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c49 */
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9230,
 			 quirk_dma_func1_alias);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9235,
+			 quirk_dma_func1_alias);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TTI, 0x0642,
 			 quirk_dma_func1_alias);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TTI, 0x0645,
@@ -4031,7 +4253,7 @@
 
 	id = pci_match_id(fixed_dma_alias_tbl, dev);
 	if (id)
-		pci_add_dma_alias(dev, id->driver_data);
+		pci_add_dma_alias(dev, id->driver_data, 1);
 }
 
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ADAPTEC2, 0x0285, quirk_fixed_dma_alias);
@@ -4073,14 +4295,43 @@
  */
 static void quirk_mic_x200_dma_alias(struct pci_dev *pdev)
 {
-	pci_add_dma_alias(pdev, PCI_DEVFN(0x10, 0x0));
-	pci_add_dma_alias(pdev, PCI_DEVFN(0x11, 0x0));
-	pci_add_dma_alias(pdev, PCI_DEVFN(0x12, 0x3));
+	pci_add_dma_alias(pdev, PCI_DEVFN(0x10, 0x0), 1);
+	pci_add_dma_alias(pdev, PCI_DEVFN(0x11, 0x0), 1);
+	pci_add_dma_alias(pdev, PCI_DEVFN(0x12, 0x3), 1);
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2260, quirk_mic_x200_dma_alias);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2264, quirk_mic_x200_dma_alias);
 
 /*
+ * Intel Visual Compute Accelerator (VCA) is a family of PCIe add-in devices
+ * exposing computational units via Non Transparent Bridges (NTB, PEX 87xx).
+ *
+ * Similarly to MIC x200, we need to add DMA aliases to allow buffer access
+ * when IOMMU is enabled.  These aliases allow computational unit access to
+ * host memory.  These aliases mark the whole VCA device as one IOMMU
+ * group.
+ *
+ * All possible slot numbers (0x20) are used, since we are unable to tell
+ * what slot is used on other side.  This quirk is intended for both host
+ * and computational unit sides.  The VCA devices have up to five functions
+ * (four for DMA channels and one additional).
+ */
+static void quirk_pex_vca_alias(struct pci_dev *pdev)
+{
+	const unsigned int num_pci_slots = 0x20;
+	unsigned int slot;
+
+	for (slot = 0; slot < num_pci_slots; slot++)
+		pci_add_dma_alias(pdev, PCI_DEVFN(slot, 0x0), 5);
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2954, quirk_pex_vca_alias);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2955, quirk_pex_vca_alias);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2956, quirk_pex_vca_alias);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2958, quirk_pex_vca_alias);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2959, quirk_pex_vca_alias);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x295A, quirk_pex_vca_alias);
+
+/*
  * The IOMMU and interrupt controller on Broadcom Vulcan/Cavium ThunderX2 are
  * associated not at the root bus, but at a bridge below. This quirk avoids
  * generating invalid DMA aliases.
@@ -4263,6 +4514,47 @@
 			 quirk_chelsio_T5_disable_root_port_attributes);
 
 /*
+ * pci_acs_ctrl_enabled - compare desired ACS controls with those provided
+ *			  by a device
+ * @acs_ctrl_req: Bitmask of desired ACS controls
+ * @acs_ctrl_ena: Bitmask of ACS controls enabled or provided implicitly by
+ *		  the hardware design
+ *
+ * Return 1 if all ACS controls in the @acs_ctrl_req bitmask are included
+ * in @acs_ctrl_ena, i.e., the device provides all the access controls the
+ * caller desires.  Return 0 otherwise.
+ */
+static int pci_acs_ctrl_enabled(u16 acs_ctrl_req, u16 acs_ctrl_ena)
+{
+	if ((acs_ctrl_req & acs_ctrl_ena) == acs_ctrl_req)
+		return 1;
+	return 0;
+}
+
+/*
+ * Many Zhaoxin Root Ports and Switch Downstream Ports have no ACS capability.
+ * But the implementation could block peer-to-peer transactions between them
+ * and provide ACS-like functionality.
+ */
+static int  pci_quirk_zhaoxin_pcie_ports_acs(struct pci_dev *dev, u16 acs_flags)
+{
+	if (!pci_is_pcie(dev) ||
+	    ((pci_pcie_type(dev) != PCI_EXP_TYPE_ROOT_PORT) &&
+	     (pci_pcie_type(dev) != PCI_EXP_TYPE_DOWNSTREAM)))
+		return -ENOTTY;
+
+	switch (dev->device) {
+	case 0x0710 ... 0x071e:
+	case 0x0721:
+	case 0x0723 ... 0x0732:
+		return pci_acs_ctrl_enabled(acs_flags,
+			PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF);
+	}
+
+	return false;
+}
+
+/*
  * AMD has indicated that the devices below do not support peer-to-peer
  * in any system where they are found in the southbridge with an AMD
  * IOMMU in the system.  Multifunction devices that do not support
@@ -4302,10 +4594,12 @@
 	if (ACPI_FAILURE(status))
 		return -ENODEV;
 
+	acpi_put_table(header);
+
 	/* Filter out flags not applicable to multifunction */
 	acs_flags &= (PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_EC | PCI_ACS_DT);
 
-	return acs_flags & ~(PCI_ACS_RR | PCI_ACS_CR) ? 0 : 1;
+	return pci_acs_ctrl_enabled(acs_flags, PCI_ACS_RR | PCI_ACS_CR);
 #else
 	return -ENODEV;
 #endif
@@ -4313,33 +4607,38 @@
 
 static bool pci_quirk_cavium_acs_match(struct pci_dev *dev)
 {
+	if (!pci_is_pcie(dev) || pci_pcie_type(dev) != PCI_EXP_TYPE_ROOT_PORT)
+		return false;
+
+	switch (dev->device) {
 	/*
-	 * Effectively selects all downstream ports for whole ThunderX 1
-	 * family by 0xf800 mask (which represents 8 SoCs), while the lower
-	 * bits of device ID are used to indicate which subdevice is used
-	 * within the SoC.
-	 */
-	return (pci_is_pcie(dev) &&
-		(pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT) &&
-		((dev->device & 0xf800) == 0xa000));
+	 * Effectively selects all downstream ports for whole ThunderX1
+	 * (which represents 8 SoCs).
+	 */
+	case 0xa000 ... 0xa7ff: /* ThunderX1 */
+	case 0xaf84:  /* ThunderX2 */
+	case 0xb884:  /* ThunderX3 */
+		return true;
+	default:
+		return false;
+	}
 }
 
 static int pci_quirk_cavium_acs(struct pci_dev *dev, u16 acs_flags)
 {
+	if (!pci_quirk_cavium_acs_match(dev))
+		return -ENOTTY;
+
 	/*
-	 * Cavium root ports don't advertise an ACS capability.  However,
+	 * Cavium Root Ports don't advertise an ACS capability.  However,
 	 * the RTL internally implements similar protection as if ACS had
-	 * Request Redirection, Completion Redirection, Source Validation,
+	 * Source Validation, Request Redirection, Completion Redirection,
 	 * and Upstream Forwarding features enabled.  Assert that the
 	 * hardware implements and enables equivalent ACS functionality for
 	 * these flags.
 	 */
-	acs_flags &= ~(PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_SV | PCI_ACS_UF);
-
-	if (!pci_quirk_cavium_acs_match(dev))
-		return -ENOTTY;
-
-	return acs_flags ? 0 : 1;
+	return pci_acs_ctrl_enabled(acs_flags,
+		PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF);
 }
 
 static int pci_quirk_xgene_acs(struct pci_dev *dev, u16 acs_flags)
@@ -4349,13 +4648,12 @@
 	 * transactions with others, allowing masking out these bits as if they
 	 * were unimplemented in the ACS capability.
 	 */
-	acs_flags &= ~(PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF);
-
-	return acs_flags ? 0 : 1;
+	return pci_acs_ctrl_enabled(acs_flags,
+		PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF);
 }
 
 /*
- * Many Intel PCH root ports do provide ACS-like features to disable peer
+ * Many Intel PCH Root Ports do provide ACS-like features to disable peer
  * transactions and validate bus numbers in requests, but do not provide an
  * actual PCIe ACS capability.  This is the list of device IDs known to fall
  * into that category as provided by Intel in Red Hat bugzilla 1037684.
@@ -4403,37 +4701,44 @@
 	return false;
 }
 
-#define INTEL_PCH_ACS_FLAGS (PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF | PCI_ACS_SV)
-
 static int pci_quirk_intel_pch_acs(struct pci_dev *dev, u16 acs_flags)
 {
-	u16 flags = dev->dev_flags & PCI_DEV_FLAGS_ACS_ENABLED_QUIRK ?
-		    INTEL_PCH_ACS_FLAGS : 0;
-
 	if (!pci_quirk_intel_pch_acs_match(dev))
 		return -ENOTTY;
 
-	return acs_flags & ~flags ? 0 : 1;
+	if (dev->dev_flags & PCI_DEV_FLAGS_ACS_ENABLED_QUIRK)
+		return pci_acs_ctrl_enabled(acs_flags,
+			PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF);
+
+	return pci_acs_ctrl_enabled(acs_flags, 0);
 }
 
 /*
- * These QCOM root ports do provide ACS-like features to disable peer
+ * These QCOM Root Ports do provide ACS-like features to disable peer
  * transactions and validate bus numbers in requests, but do not provide an
  * actual PCIe ACS capability.  Hardware supports source validation but it
  * will report the issue as Completer Abort instead of ACS Violation.
- * Hardware doesn't support peer-to-peer and each root port is a root
- * complex with unique segment numbers.  It is not possible for one root
- * port to pass traffic to another root port.  All PCIe transactions are
- * terminated inside the root port.
+ * Hardware doesn't support peer-to-peer and each Root Port is a Root
+ * Complex with unique segment numbers.  It is not possible for one Root
+ * Port to pass traffic to another Root Port.  All PCIe transactions are
+ * terminated inside the Root Port.
  */
 static int pci_quirk_qcom_rp_acs(struct pci_dev *dev, u16 acs_flags)
 {
-	u16 flags = (PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF | PCI_ACS_SV);
-	int ret = acs_flags & ~flags ? 0 : 1;
-
-	pci_info(dev, "Using QCOM ACS Quirk (%d)\n", ret);
+	return pci_acs_ctrl_enabled(acs_flags,
+		PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF);
+}
 
-	return ret;
+/*
+ * Each of these NXP Root Ports is in a Root Complex with a unique segment
+ * number and does provide isolation features to disable peer transactions
+ * and validate bus numbers in requests, but does not provide an ACS
+ * capability.
+ */
+static int pci_quirk_nxp_rp_acs(struct pci_dev *dev, u16 acs_flags)
+{
+	return pci_acs_ctrl_enabled(acs_flags,
+		PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF);
 }
 
 static int pci_quirk_al_acs(struct pci_dev *dev, u16 acs_flags)
@@ -4505,6 +4810,7 @@
 		return false;
 
 	switch (dev->device) {
+	case 0x06ac ... 0x06c3: /* Comet Lake */
 	case 0xa110 ... 0xa11f: case 0xa167 ... 0xa16a: /* Sunrise Point */
 	case 0xa290 ... 0xa29f: case 0xa2e7 ... 0xa2ee: /* Union Point */
 	case 0x9d10 ... 0x9d1b: /* 7th & 8th Gen Mobile */
@@ -4534,7 +4840,7 @@
 
 	pci_read_config_dword(dev, pos + INTEL_SPT_ACS_CTRL, &ctrl);
 
-	return acs_flags & ~ctrl ? 0 : 1;
+	return pci_acs_ctrl_enabled(acs_flags, ctrl);
 }
 
 static int pci_quirk_mf_endpoint_acs(struct pci_dev *dev, u16 acs_flags)
@@ -4548,10 +4854,23 @@
 	 * perform peer-to-peer with other functions, allowing us to mask out
 	 * these bits as if they were unimplemented in the ACS capability.
 	 */
-	acs_flags &= ~(PCI_ACS_SV | PCI_ACS_TB | PCI_ACS_RR |
-		       PCI_ACS_CR | PCI_ACS_UF | PCI_ACS_DT);
+	return pci_acs_ctrl_enabled(acs_flags,
+		PCI_ACS_SV | PCI_ACS_TB | PCI_ACS_RR |
+		PCI_ACS_CR | PCI_ACS_UF | PCI_ACS_DT);
+}
 
-	return acs_flags ? 0 : 1;
+static int pci_quirk_rciep_acs(struct pci_dev *dev, u16 acs_flags)
+{
+	/*
+	 * Intel RCiEP's are required to allow p2p only on translated
+	 * addresses.  Refer to Intel VT-d specification, r3.1, sec 3.16,
+	 * "Root-Complex Peer to Peer Considerations".
+	 */
+	if (pci_pcie_type(dev) != PCI_EXP_TYPE_RC_END)
+		return -ENOTTY;
+
+	return pci_acs_ctrl_enabled(acs_flags,
+		PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF);
 }
 
 static int pci_quirk_brcm_acs(struct pci_dev *dev, u16 acs_flags)
@@ -4562,9 +4881,31 @@
 	 * Allow each Root Port to be in a separate IOMMU group by masking
 	 * SV/RR/CR/UF bits.
 	 */
-	acs_flags &= ~(PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF);
+	return pci_acs_ctrl_enabled(acs_flags,
+		PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF);
+}
 
-	return acs_flags ? 0 : 1;
+/*
+ * Wangxun 40G/25G/10G/1G NICs have no ACS capability, but on
+ * multi-function devices, the hardware isolates the functions by
+ * directing all peer-to-peer traffic upstream as though PCI_ACS_RR and
+ * PCI_ACS_CR were set.
+ * SFxxx 1G NICs(em).
+ * RP1000/RP2000 10G NICs(sp).
+ * FF5xxx 40G/25G/10G NICs(aml).
+ */
+static int  pci_quirk_wangxun_nic_acs(struct pci_dev *dev, u16 acs_flags)
+{
+	switch (dev->device) {
+	case 0x0100 ... 0x010F: /* EM */
+	case 0x1001: case 0x2001: /* SP */
+	case 0x5010: case 0x5025: case 0x5040: /* AML */
+	case 0x5110: case 0x5125: case 0x5140: /* AML */
+		return pci_acs_ctrl_enabled(acs_flags,
+			PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF);
+	}
+
+	return false;
 }
 
 static const struct pci_dev_acs_enabled {
@@ -4637,9 +4978,12 @@
 	/* I219 */
 	{ PCI_VENDOR_ID_INTEL, 0x15b7, pci_quirk_mf_endpoint_acs },
 	{ PCI_VENDOR_ID_INTEL, 0x15b8, pci_quirk_mf_endpoint_acs },
+	{ PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_rciep_acs },
 	/* QCOM QDF2xxx root ports */
 	{ PCI_VENDOR_ID_QCOM, 0x0400, pci_quirk_qcom_rp_acs },
 	{ PCI_VENDOR_ID_QCOM, 0x0401, pci_quirk_qcom_rp_acs },
+	/* QCOM SA8775P root port */
+	{ PCI_VENDOR_ID_QCOM, 0x0115, pci_quirk_qcom_rp_acs },
 	/* HXT SD4800 root ports. The ACS design is same as QCOM QDF2xxx */
 	{ PCI_VENDOR_ID_HXT, 0x0401, pci_quirk_qcom_rp_acs },
 	/* Intel PCH root ports */
@@ -4649,6 +4993,10 @@
 	{ 0x10df, 0x720, pci_quirk_mf_endpoint_acs }, /* Emulex Skyhawk-R */
 	/* Cavium ThunderX */
 	{ PCI_VENDOR_ID_CAVIUM, PCI_ANY_ID, pci_quirk_cavium_acs },
+	/* Cavium multi-function devices */
+	{ PCI_VENDOR_ID_CAVIUM, 0xA026, pci_quirk_mf_endpoint_acs },
+	{ PCI_VENDOR_ID_CAVIUM, 0xA059, pci_quirk_mf_endpoint_acs },
+	{ PCI_VENDOR_ID_CAVIUM, 0xA060, pci_quirk_mf_endpoint_acs },
 	/* APM X-Gene */
 	{ PCI_VENDOR_ID_AMCC, 0xE004, pci_quirk_xgene_acs },
 	/* Ampere Computing */
@@ -4660,12 +5008,73 @@
 	{ PCI_VENDOR_ID_AMPERE, 0xE00A, pci_quirk_xgene_acs },
 	{ PCI_VENDOR_ID_AMPERE, 0xE00B, pci_quirk_xgene_acs },
 	{ PCI_VENDOR_ID_AMPERE, 0xE00C, pci_quirk_xgene_acs },
+	/* Broadcom multi-function device */
+	{ PCI_VENDOR_ID_BROADCOM, 0x16D7, pci_quirk_mf_endpoint_acs },
+	{ PCI_VENDOR_ID_BROADCOM, 0x1750, pci_quirk_mf_endpoint_acs },
+	{ PCI_VENDOR_ID_BROADCOM, 0x1751, pci_quirk_mf_endpoint_acs },
+	{ PCI_VENDOR_ID_BROADCOM, 0x1752, pci_quirk_mf_endpoint_acs },
+	{ PCI_VENDOR_ID_BROADCOM, 0x1760, pci_quirk_mf_endpoint_acs },
+	{ PCI_VENDOR_ID_BROADCOM, 0x1761, pci_quirk_mf_endpoint_acs },
+	{ PCI_VENDOR_ID_BROADCOM, 0x1762, pci_quirk_mf_endpoint_acs },
+	{ PCI_VENDOR_ID_BROADCOM, 0x1763, pci_quirk_mf_endpoint_acs },
 	{ PCI_VENDOR_ID_BROADCOM, 0xD714, pci_quirk_brcm_acs },
 	/* Amazon Annapurna Labs */
 	{ PCI_VENDOR_ID_AMAZON_ANNAPURNA_LABS, 0x0031, pci_quirk_al_acs },
+	/* Zhaoxin multi-function devices */
+	{ PCI_VENDOR_ID_ZHAOXIN, 0x3038, pci_quirk_mf_endpoint_acs },
+	{ PCI_VENDOR_ID_ZHAOXIN, 0x3104, pci_quirk_mf_endpoint_acs },
+	{ PCI_VENDOR_ID_ZHAOXIN, 0x9083, pci_quirk_mf_endpoint_acs },
+	/* NXP root ports, xx=16, 12, or 08 cores */
+	/* LX2xx0A : without security features + CAN-FD */
+	{ PCI_VENDOR_ID_NXP, 0x8d81, pci_quirk_nxp_rp_acs },
+	{ PCI_VENDOR_ID_NXP, 0x8da1, pci_quirk_nxp_rp_acs },
+	{ PCI_VENDOR_ID_NXP, 0x8d83, pci_quirk_nxp_rp_acs },
+	/* LX2xx0C : security features + CAN-FD */
+	{ PCI_VENDOR_ID_NXP, 0x8d80, pci_quirk_nxp_rp_acs },
+	{ PCI_VENDOR_ID_NXP, 0x8da0, pci_quirk_nxp_rp_acs },
+	{ PCI_VENDOR_ID_NXP, 0x8d82, pci_quirk_nxp_rp_acs },
+	/* LX2xx0E : security features + CAN */
+	{ PCI_VENDOR_ID_NXP, 0x8d90, pci_quirk_nxp_rp_acs },
+	{ PCI_VENDOR_ID_NXP, 0x8db0, pci_quirk_nxp_rp_acs },
+	{ PCI_VENDOR_ID_NXP, 0x8d92, pci_quirk_nxp_rp_acs },
+	/* LX2xx0N : without security features + CAN */
+	{ PCI_VENDOR_ID_NXP, 0x8d91, pci_quirk_nxp_rp_acs },
+	{ PCI_VENDOR_ID_NXP, 0x8db1, pci_quirk_nxp_rp_acs },
+	{ PCI_VENDOR_ID_NXP, 0x8d93, pci_quirk_nxp_rp_acs },
+	/* LX2xx2A : without security features + CAN-FD */
+	{ PCI_VENDOR_ID_NXP, 0x8d89, pci_quirk_nxp_rp_acs },
+	{ PCI_VENDOR_ID_NXP, 0x8da9, pci_quirk_nxp_rp_acs },
+	{ PCI_VENDOR_ID_NXP, 0x8d8b, pci_quirk_nxp_rp_acs },
+	/* LX2xx2C : security features + CAN-FD */
+	{ PCI_VENDOR_ID_NXP, 0x8d88, pci_quirk_nxp_rp_acs },
+	{ PCI_VENDOR_ID_NXP, 0x8da8, pci_quirk_nxp_rp_acs },
+	{ PCI_VENDOR_ID_NXP, 0x8d8a, pci_quirk_nxp_rp_acs },
+	/* LX2xx2E : security features + CAN */
+	{ PCI_VENDOR_ID_NXP, 0x8d98, pci_quirk_nxp_rp_acs },
+	{ PCI_VENDOR_ID_NXP, 0x8db8, pci_quirk_nxp_rp_acs },
+	{ PCI_VENDOR_ID_NXP, 0x8d9a, pci_quirk_nxp_rp_acs },
+	/* LX2xx2N : without security features + CAN */
+	{ PCI_VENDOR_ID_NXP, 0x8d99, pci_quirk_nxp_rp_acs },
+	{ PCI_VENDOR_ID_NXP, 0x8db9, pci_quirk_nxp_rp_acs },
+	{ PCI_VENDOR_ID_NXP, 0x8d9b, pci_quirk_nxp_rp_acs },
+	/* Zhaoxin Root/Downstream Ports */
+	{ PCI_VENDOR_ID_ZHAOXIN, PCI_ANY_ID, pci_quirk_zhaoxin_pcie_ports_acs },
+	/* Wangxun nics */
+	{ PCI_VENDOR_ID_WANGXUN, PCI_ANY_ID, pci_quirk_wangxun_nic_acs },
 	{ 0 }
 };
 
+/*
+ * pci_dev_specific_acs_enabled - check whether device provides ACS controls
+ * @dev:	PCI device
+ * @acs_flags:	Bitmask of desired ACS controls
+ *
+ * Returns:
+ *   -ENOTTY:	No quirk applies to this device; we can't tell whether the
+ *		device provides the desired controls
+ *   0:		Device does not provide all the desired controls
+ *   >0:	Device provides all the controls in @acs_flags
+ */
 int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags)
 {
 	const struct pci_dev_acs_enabled *i;
@@ -4706,7 +5115,7 @@
 #define INTEL_BSPR_REG_BPPD  (1 << 9)
 
 /* Upstream Peer Decode Configuration Register */
-#define INTEL_UPDCR_REG 0x1114
+#define INTEL_UPDCR_REG 0x1014
 /* 5:0 Peer Decode Enable bits */
 #define INTEL_UPDCR_REG_MASK 0x3f
 
@@ -4985,13 +5394,47 @@
 }
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x443, quirk_intel_qat_vf_cap);
 
-/* FLR may cause some 82579 devices to hang */
-static void quirk_intel_no_flr(struct pci_dev *dev)
+/*
+ * FLR may cause the following to devices to hang:
+ *
+ * AMD Starship/Matisse HD Audio Controller 0x1487
+ * AMD Starship USB 3.0 Host Controller 0x148c
+ * AMD Matisse USB 3.0 Host Controller 0x149c
+ * Intel 82579LM Gigabit Ethernet Controller 0x1502
+ * Intel 82579V Gigabit Ethernet Controller 0x1503
+ *
+ */
+static void quirk_no_flr(struct pci_dev *dev)
 {
 	dev->dev_flags |= PCI_DEV_FLAGS_NO_FLR_RESET;
 }
-DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1502, quirk_intel_no_flr);
-DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1503, quirk_intel_no_flr);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AMD, 0x1487, quirk_no_flr);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AMD, 0x148c, quirk_no_flr);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AMD, 0x149c, quirk_no_flr);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AMD, 0x7901, quirk_no_flr);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1502, quirk_no_flr);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1503, quirk_no_flr);
+
+static void quirk_intel_th_rtit_bar(struct pci_dev *dev)
+{
+	struct resource *r = &dev->resource[4];
+
+	/*
+	 * Hello, Denverton!
+	 * Denverton reports 2k of RTIT_BAR (resource 4), which can't be
+	 * right given the 16 threads. When Intel TH gets enabled, the
+	 * actual resource overlaps the XHCI MMIO space and causes it
+	 * to die.
+	 * We're not really using RTIT_BAR at all at the moment, so it's
+	 * a safe choice to disable this resource.
+	 */
+	if (r->end == r->start + 0x7ff) {
+		r->flags = 0;
+		r->start = 0;
+		r->end   = 0;
+	}
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x19e1, quirk_intel_th_rtit_bar);
 
 static void quirk_no_ext_tags(struct pci_dev *pdev)
 {
@@ -5005,6 +5448,7 @@
 
 	pci_walk_bus(bridge->bus, pci_configure_extended_tags, NULL);
 }
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_3WARE, 0x1004, quirk_no_ext_tags);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, 0x0132, quirk_no_ext_tags);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, 0x0140, quirk_no_ext_tags);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, 0x0141, quirk_no_ext_tags);
@@ -5014,19 +5458,55 @@
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, 0x0422, quirk_no_ext_tags);
 
 #ifdef CONFIG_PCI_ATS
-/*
- * Some devices have a broken ATS implementation causing IOMMU stalls.
- * Don't use ATS for those devices.
- */
 static void quirk_no_ats(struct pci_dev *pdev)
 {
-	pci_info(pdev, "disabling ATS (broken on this device)\n");
+	pci_info(pdev, "disabling ATS\n");
 	pdev->ats_cap = 0;
 }
 
+/*
+ * Some devices require additional driver setup to enable ATS.  Don't use
+ * ATS for those devices as ATS will be enabled before the driver has had a
+ * chance to load and configure the device.
+ */
+static void quirk_amd_harvest_no_ats(struct pci_dev *pdev)
+{
+	if ((pdev->device == 0x7312 && pdev->revision != 0x00) ||
+	    (pdev->device == 0x7340 && pdev->revision != 0xc5) ||
+	    (pdev->device == 0x7341 && pdev->revision != 0x00))
+		return;
+
+	quirk_no_ats(pdev);
+}
+
 /* AMD Stoney platform GPU */
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x98e4, quirk_no_ats);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x6900, quirk_no_ats);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x98e4, quirk_amd_harvest_no_ats);
+/* AMD Iceland dGPU */
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x6900, quirk_amd_harvest_no_ats);
+/* AMD Navi10 dGPU */
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x7312, quirk_amd_harvest_no_ats);
+/* AMD Navi14 dGPU */
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x7340, quirk_amd_harvest_no_ats);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x7341, quirk_amd_harvest_no_ats);
+
+/*
+ * Intel IPU E2000 revisions before C0 implement incorrect endianness
+ * in ATS Invalidate Request message body. Disable ATS for those devices.
+ */
+static void quirk_intel_e2000_no_ats(struct pci_dev *pdev)
+{
+	if (pdev->revision < 0x20)
+		quirk_no_ats(pdev);
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1451, quirk_intel_e2000_no_ats);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1452, quirk_intel_e2000_no_ats);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1453, quirk_intel_e2000_no_ats);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1454, quirk_intel_e2000_no_ats);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1455, quirk_intel_e2000_no_ats);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1457, quirk_intel_e2000_no_ats);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1459, quirk_intel_e2000_no_ats);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x145a, quirk_intel_e2000_no_ats);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x145c, quirk_intel_e2000_no_ats);
 #endif /* CONFIG_PCI_ATS */
 
 /* Freescale PCIe doesn't support MSI in RC mode */
@@ -5090,7 +5570,7 @@
 			      PCI_CLASS_MULTIMEDIA_HD_AUDIO, 8, quirk_gpu_hda);
 
 /*
- * Create device link for NVIDIA GPU with integrated USB xHCI Host
+ * Create device link for GPUs with integrated USB xHCI Host
  * controller to VGA.
  */
 static void quirk_gpu_usb(struct pci_dev *usb)
@@ -5099,9 +5579,11 @@
 }
 DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
 			      PCI_CLASS_SERIAL_USB, 8, quirk_gpu_usb);
+DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_ATI, PCI_ANY_ID,
+			      PCI_CLASS_SERIAL_USB, 8, quirk_gpu_usb);
 
 /*
- * Create device link for NVIDIA GPU with integrated Type-C UCSI controller
+ * Create device link for GPUs with integrated Type-C UCSI controller
  * to VGA. Currently there is no class code defined for UCSI device over PCI
  * so using UNKNOWN class for now and it will be updated when UCSI
  * over PCI gets a class code.
@@ -5114,6 +5596,9 @@
 DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
 			      PCI_CLASS_SERIAL_UNKNOWN, 8,
 			      quirk_gpu_usb_typec_ucsi);
+DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_ATI, PCI_ANY_ID,
+			      PCI_CLASS_SERIAL_UNKNOWN, 8,
+			      quirk_gpu_usb_typec_ucsi);
 
 /*
  * Enable the NVIDIA GPU integrated HDA controller if the BIOS left it
@@ -5273,7 +5758,7 @@
 			pci_dbg(pdev,
 				"Aliasing Partition %d Proxy ID %02x.%d\n",
 				pp, PCI_SLOT(devfn), PCI_FUNC(devfn));
-			pci_add_dma_alias(pdev, devfn);
+			pci_add_dma_alias(pdev, devfn, 1);
 		}
 	}
 
@@ -5316,6 +5801,21 @@
 SWITCHTEC_QUIRK(0x8576);  /* PFXI 96XG3 */
 
 /*
+ * The PLX NTB uses devfn proxy IDs to move TLPs between NT endpoints.
+ * These IDs are used to forward responses to the originator on the other
+ * side of the NTB.  Alias all possible IDs to the NTB to permit access when
+ * the IOMMU is turned on.
+ */
+static void quirk_plx_ntb_dma_alias(struct pci_dev *pdev)
+{
+	pci_info(pdev, "Setting PLX NTB proxy ID aliases\n");
+	/* PLX NTB may use all 256 devfns */
+	pci_add_dma_alias(pdev, 0, 256);
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_PLX, 0x87b0, quirk_plx_ntb_dma_alias);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_PLX, 0x87b1, quirk_plx_ntb_dma_alias);
+
+/*
  * On Lenovo Thinkpad P50 SKUs with a Nvidia Quadro M1000M, the BIOS does
  * not always reset the secondary Nvidia GPU between reboots if the system
  * is configured to use Hybrid Graphics mode.  This results in the GPU
@@ -5372,3 +5872,40 @@
 DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_NVIDIA, 0x13b1,
 			      PCI_CLASS_DISPLAY_VGA, 8,
 			      quirk_reset_lenovo_thinkpad_p50_nvgpu);
+
+/*
+ * Device [1b21:2142]
+ * When in D0, PME# doesn't get asserted when plugging USB 3.0 device.
+ */
+static void pci_fixup_no_d0_pme(struct pci_dev *dev)
+{
+	pci_info(dev, "PME# does not work under D0, disabling it\n");
+	dev->pme_support &= ~(PCI_PM_CAP_PME_D0 >> PCI_PM_CAP_PME_SHIFT);
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASMEDIA, 0x2142, pci_fixup_no_d0_pme);
+
+static void apex_pci_fixup_class(struct pci_dev *pdev)
+{
+	pdev->class = (PCI_CLASS_SYSTEM_OTHER << 8) | pdev->class;
+}
+DECLARE_PCI_FIXUP_CLASS_HEADER(0x1ac1, 0x089a,
+			       PCI_CLASS_NOT_DEFINED, 8, apex_pci_fixup_class);
+
+static void nvidia_ion_ahci_fixup(struct pci_dev *pdev)
+{
+	pdev->dev_flags |= PCI_DEV_FLAGS_HAS_MSI_MASKING;
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, 0x0ab8, nvidia_ion_ahci_fixup);
+
+/*
+ * Device [12d8:0x400e] and [12d8:0x400f]
+ * These devices advertise PME# support in all power states but don't
+ * reliably assert it.
+ */
+static void pci_fixup_no_pme(struct pci_dev *dev)
+{
+	pci_info(dev, "PME# is unreliable, disabling it\n");
+	dev->pme_support = 0;
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_PERICOM, 0x400e, pci_fixup_no_pme);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_PERICOM, 0x400f, pci_fixup_no_pme);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/remove.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/remove.c
@@ -160,6 +160,6 @@
 	host_bridge->bus = NULL;
 
 	/* remove the host bridge */
-	device_unregister(&host_bridge->dev);
+	device_del(&host_bridge->dev);
 }
 EXPORT_SYMBOL_GPL(pci_remove_root_bus);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/rom.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/rom.c
@@ -195,20 +195,3 @@
 		pci_disable_rom(pdev);
 }
 EXPORT_SYMBOL(pci_unmap_rom);
-
-/**
- * pci_platform_rom - provides a pointer to any ROM image provided by the
- * platform
- * @pdev: pointer to pci device struct
- * @size: pointer to receive size of pci window over ROM
- */
-void __iomem *pci_platform_rom(struct pci_dev *pdev, size_t *size)
-{
-	if (pdev->rom && pdev->romlen) {
-		*size = pdev->romlen;
-		return phys_to_virt((phys_addr_t)pdev->rom);
-	}
-
-	return NULL;
-}
-EXPORT_SYMBOL(pci_platform_rom);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/search.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/search.c
@@ -41,9 +41,9 @@
 	 * DMA, iterate over that too.
 	 */
 	if (unlikely(pdev->dma_alias_mask)) {
-		u8 devfn;
+		unsigned int devfn;
 
-		for_each_set_bit(devfn, pdev->dma_alias_mask, U8_MAX) {
+		for_each_set_bit(devfn, pdev->dma_alias_mask, MAX_NR_DEVFNS) {
 			ret = fn(pdev, PCI_DEVID(pdev->bus->number, devfn),
 				 data);
 			if (ret)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/setup-bus.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/setup-bus.c
@@ -752,24 +752,32 @@
 }
 
 /*
- * Helper function for sizing routines: find first available bus resource
- * of a given type.  Note: we intentionally skip the bus resources which
- * have already been assigned (that is, have non-NULL parent resource).
+ * Helper function for sizing routines.  Assigned resources have non-NULL
+ * parent resource.
+ *
+ * Return first unassigned resource of the correct type.  If there is none,
+ * return first assigned resource of the correct type.  If none of the
+ * above, return NULL.
+ *
+ * Returning an assigned resource of the correct type allows the caller to
+ * distinguish between already assigned and no resource of the correct type.
  */
-static struct resource *find_free_bus_resource(struct pci_bus *bus,
-					       unsigned long type_mask,
-					       unsigned long type)
+static struct resource *find_bus_resource_of_type(struct pci_bus *bus,
+						  unsigned long type_mask,
+						  unsigned long type)
 {
+	struct resource *r, *r_assigned = NULL;
 	int i;
-	struct resource *r;
 
 	pci_bus_for_each_resource(bus, r, i) {
 		if (r == &ioport_resource || r == &iomem_resource)
 			continue;
 		if (r && (r->flags & type_mask) == type && !r->parent)
 			return r;
+		if (r && (r->flags & type_mask) == type && !r_assigned)
+			r_assigned = r;
 	}
-	return NULL;
+	return r_assigned;
 }
 
 static resource_size_t calculate_iosize(resource_size_t size,
@@ -810,11 +818,9 @@
 		size = min_size;
 	if (old_size == 1)
 		old_size = 0;
-	if (size < old_size)
-		size = old_size;
 
-	size = ALIGN(max(size, add_size) + children_add_size, align);
-	return size;
+	size = max(size, add_size) + children_add_size;
+	return ALIGN(max(size, old_size), align);
 }
 
 resource_size_t __weak pcibios_window_alignment(struct pci_bus *bus,
@@ -866,8 +872,8 @@
 			 struct list_head *realloc_head)
 {
 	struct pci_dev *dev;
-	struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO,
-							IORESOURCE_IO);
+	struct resource *b_res = find_bus_resource_of_type(bus, IORESOURCE_IO,
+							   IORESOURCE_IO);
 	resource_size_t size = 0, size0 = 0, size1 = 0;
 	resource_size_t children_add_size = 0;
 	resource_size_t min_align, align;
@@ -875,6 +881,10 @@
 	if (!b_res)
 		return;
 
+	/* If resource is already assigned, nothing more to do */
+	if (b_res->parent)
+		return;
+
 	min_align = window_alignment(bus, IORESOURCE_IO);
 	list_for_each_entry(dev, &bus->devices, bus_list) {
 		int i;
@@ -978,7 +988,7 @@
 	resource_size_t min_align, align, size, size0, size1;
 	resource_size_t aligns[18]; /* Alignments from 1MB to 128GB */
 	int order, max_order;
-	struct resource *b_res = find_free_bus_resource(bus,
+	struct resource *b_res = find_bus_resource_of_type(bus,
 					mask | IORESOURCE_PREFETCH, type);
 	resource_size_t children_add_size = 0;
 	resource_size_t children_add_align = 0;
@@ -987,6 +997,10 @@
 	if (!b_res)
 		return -ENOSPC;
 
+	/* If resource is already assigned, nothing more to do */
+	if (b_res->parent)
+		return 0;
+
 	memset(aligns, 0, sizeof(aligns));
 	max_order = 0;
 	size = 0;
@@ -1785,12 +1799,18 @@
 	/* Restore size and flags */
 	list_for_each_entry(fail_res, &fail_head, list) {
 		struct resource *res = fail_res->res;
+		int idx;
 
 		res->start = fail_res->start;
 		res->end = fail_res->end;
 		res->flags = fail_res->flags;
-		if (fail_res->dev->subordinate)
-			res->flags = 0;
+
+		if (pci_is_bridge(fail_res->dev)) {
+			idx = res - &fail_res->dev->resource[0];
+			if (idx >= PCI_BRIDGE_RESOURCES &&
+			    idx <= PCI_BRIDGE_RESOURCE_END)
+				res->flags = 0;
+		}
 	}
 	free_list(&fail_head);
 
@@ -2037,12 +2057,18 @@
 	/* Restore size and flags */
 	list_for_each_entry(fail_res, &fail_head, list) {
 		struct resource *res = fail_res->res;
+		int idx;
 
 		res->start = fail_res->start;
 		res->end = fail_res->end;
 		res->flags = fail_res->flags;
-		if (fail_res->dev->subordinate)
-			res->flags = 0;
+
+		if (pci_is_bridge(fail_res->dev)) {
+			idx = res - &fail_res->dev->resource[0];
+			if (idx >= PCI_BRIDGE_RESOURCES &&
+			    idx <= PCI_BRIDGE_RESOURCE_END)
+				res->flags = 0;
+		}
 	}
 	free_list(&fail_head);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/setup-res.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/setup-res.c
@@ -209,6 +209,17 @@
 
 	root = pci_find_parent_resource(dev, res);
 	if (!root) {
+		/*
+		 * If dev is behind a bridge, accesses will only reach it
+		 * if res is inside the relevant bridge window.
+		 */
+		if (pci_upstream_bridge(dev))
+			return -ENXIO;
+
+		/*
+		 * On the root bus, assume the host bridge will forward
+		 * everything.
+		 */
 		if (res->flags & IORESOURCE_IO)
 			root = &ioport_resource;
 		else
@@ -409,10 +420,16 @@
 int pci_resize_resource(struct pci_dev *dev, int resno, int size)
 {
 	struct resource *res = dev->resource + resno;
+	struct pci_host_bridge *host;
 	int old, ret;
 	u32 sizes;
 	u16 cmd;
 
+	/* Check if we must preserve the firmware's resource assignment */
+	host = pci_find_host_bridge(dev->bus);
+	if (host->preserve_config)
+		return -ENOTSUPP;
+
 	/* Make sure the resource isn't assigned before resizing it. */
 	if (!(res->flags & IORESOURCE_UNSET))
 		return -EBUSY;
@@ -439,10 +456,11 @@
 	res->end = res->start + pci_rebar_size_to_bytes(size) - 1;
 
 	/* Check if the new config works by trying to assign everything. */
-	ret = pci_reassign_bridge_resources(dev->bus->self, res->flags);
-	if (ret)
-		goto error_resize;
-
+	if (dev->bus->self) {
+		ret = pci_reassign_bridge_resources(dev->bus->self, res->flags);
+		if (ret)
+			goto error_resize;
+	}
 	return 0;
 
 error_resize:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/slot.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/slot.c
@@ -49,45 +49,9 @@
 				slot->number);
 }
 
-/* these strings match up with the values in pci_bus_speed */
-static const char *pci_bus_speed_strings[] = {
-	"33 MHz PCI",		/* 0x00 */
-	"66 MHz PCI",		/* 0x01 */
-	"66 MHz PCI-X",		/* 0x02 */
-	"100 MHz PCI-X",	/* 0x03 */
-	"133 MHz PCI-X",	/* 0x04 */
-	NULL,			/* 0x05 */
-	NULL,			/* 0x06 */
-	NULL,			/* 0x07 */
-	NULL,			/* 0x08 */
-	"66 MHz PCI-X 266",	/* 0x09 */
-	"100 MHz PCI-X 266",	/* 0x0a */
-	"133 MHz PCI-X 266",	/* 0x0b */
-	"Unknown AGP",		/* 0x0c */
-	"1x AGP",		/* 0x0d */
-	"2x AGP",		/* 0x0e */
-	"4x AGP",		/* 0x0f */
-	"8x AGP",		/* 0x10 */
-	"66 MHz PCI-X 533",	/* 0x11 */
-	"100 MHz PCI-X 533",	/* 0x12 */
-	"133 MHz PCI-X 533",	/* 0x13 */
-	"2.5 GT/s PCIe",	/* 0x14 */
-	"5.0 GT/s PCIe",	/* 0x15 */
-	"8.0 GT/s PCIe",	/* 0x16 */
-	"16.0 GT/s PCIe",	/* 0x17 */
-	"32.0 GT/s PCIe",	/* 0x18 */
-};
-
 static ssize_t bus_speed_read(enum pci_bus_speed speed, char *buf)
 {
-	const char *speed_string;
-
-	if (speed < ARRAY_SIZE(pci_bus_speed_strings))
-		speed_string = pci_bus_speed_strings[speed];
-	else
-		speed_string = "Unknown";
-
-	return sprintf(buf, "%s\n", speed_string);
+	return sprintf(buf, "%s\n", pci_speed_string(speed));
 }
 
 static ssize_t max_speed_read_file(struct pci_slot *slot, char *buf)
@@ -115,6 +79,7 @@
 	up_read(&pci_bus_sem);
 
 	list_del(&slot->list);
+	pci_bus_put(slot->bus);
 
 	kfree(slot);
 }
@@ -296,7 +261,7 @@
 		goto err;
 	}
 
-	slot->bus = parent;
+	slot->bus = pci_bus_get(parent);
 	slot->number = slot_nr;
 
 	slot->kobj.kset = pci_slots_kset;
@@ -304,16 +269,20 @@
 	slot_name = make_slot_name(name);
 	if (!slot_name) {
 		err = -ENOMEM;
+		pci_bus_put(slot->bus);
+		kfree(slot);
 		goto err;
 	}
 
+	INIT_LIST_HEAD(&slot->list);
+	list_add(&slot->list, &parent->slots);
+
 	err = kobject_init_and_add(&slot->kobj, &pci_slot_ktype, NULL,
 				   "%s", slot_name);
-	if (err)
+	if (err) {
+		kobject_put(&slot->kobj);
 		goto err;
-
-	INIT_LIST_HEAD(&slot->list);
-	list_add(&slot->list, &parent->slots);
+	}
 
 	down_read(&pci_bus_sem);
 	list_for_each_entry(dev, &parent->devices, bus_list)
@@ -329,7 +298,6 @@
 	mutex_unlock(&pci_slot_mutex);
 	return slot;
 err:
-	kfree(slot);
 	slot = ERR_PTR(err);
 	goto out;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/switch/switchtec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/switch/switchtec.c
@@ -175,7 +175,7 @@
 	kref_get(&stuser->kref);
 	stuser->read_len = sizeof(stuser->data);
 	stuser_set_state(stuser, MRPC_QUEUED);
-	init_completion(&stuser->comp);
+	reinit_completion(&stuser->comp);
 	list_add_tail(&stuser->list, &stdev->mrpc_queue);
 
 	mrpc_cmd_submit(stdev);
@@ -675,7 +675,7 @@
 		return -ENOMEM;
 
 	s->global = ioread32(&stdev->mmio_sw_event->global_summary);
-	s->part_bitmap = ioread32(&stdev->mmio_sw_event->part_event_bitmap);
+	s->part_bitmap = ioread64(&stdev->mmio_sw_event->part_event_bitmap);
 	s->local_part = ioread32(&stdev->mmio_part_cfg->part_event_summary);
 
 	for (i = 0; i < stdev->partition_count; i++) {
@@ -1082,13 +1082,6 @@
 {
 	struct switchtec_dev *stdev = to_stdev(dev);
 
-	if (stdev->dma_mrpc) {
-		iowrite32(0, &stdev->mmio_mrpc->dma_en);
-		flush_wc_buf(stdev);
-		writeq(0, &stdev->mmio_mrpc->dma_addr);
-		dma_free_coherent(&stdev->pdev->dev, sizeof(*stdev->dma_mrpc),
-				stdev->dma_mrpc, stdev->dma_mrpc_dma_addr);
-	}
 	kfree(stdev);
 }
 
@@ -1131,7 +1124,7 @@
 		return ERR_PTR(-ENOMEM);
 
 	stdev->alive = true;
-	stdev->pdev = pdev;
+	stdev->pdev = pci_dev_get(pdev);
 	INIT_LIST_HEAD(&stdev->mrpc_queue);
 	mutex_init(&stdev->mrpc_mutex);
 	stdev->mrpc_busy = 0;
@@ -1165,6 +1158,7 @@
 	return stdev;
 
 err_put:
+	pci_dev_put(stdev->pdev);
 	put_device(&stdev->dev);
 	return ERR_PTR(rc);
 }
@@ -1276,7 +1270,7 @@
 	if (nvecs < 0)
 		return nvecs;
 
-	event_irq = ioread32(&stdev->mmio_part_cfg->vep_vector_number);
+	event_irq = ioread16(&stdev->mmio_part_cfg->vep_vector_number);
 	if (event_irq < 0 || event_irq >= nvecs)
 		return -EFAULT;
 
@@ -1349,7 +1343,7 @@
 	if (rc)
 		return rc;
 
-	rc = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
+	rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
 	if (rc)
 		return rc;
 
@@ -1407,6 +1401,18 @@
 	return 0;
 }
 
+static void switchtec_exit_pci(struct switchtec_dev *stdev)
+{
+	if (stdev->dma_mrpc) {
+		iowrite32(0, &stdev->mmio_mrpc->dma_en);
+		flush_wc_buf(stdev);
+		writeq(0, &stdev->mmio_mrpc->dma_addr);
+		dma_free_coherent(&stdev->pdev->dev, sizeof(*stdev->dma_mrpc),
+				  stdev->dma_mrpc, stdev->dma_mrpc_dma_addr);
+		stdev->dma_mrpc = NULL;
+	}
+}
+
 static int switchtec_pci_probe(struct pci_dev *pdev,
 			       const struct pci_device_id *id)
 {
@@ -1427,7 +1433,7 @@
 	rc = switchtec_init_isr(stdev);
 	if (rc) {
 		dev_err(&stdev->dev, "failed to init isr.\n");
-		goto err_put;
+		goto err_exit_pci;
 	}
 
 	iowrite32(SWITCHTEC_EVENT_CLEAR |
@@ -1448,6 +1454,8 @@
 
 err_devadd:
 	stdev_kill(stdev);
+err_exit_pci:
+	switchtec_exit_pci(stdev);
 err_put:
 	ida_simple_remove(&switchtec_minor_ida, MINOR(stdev->dev.devt));
 	put_device(&stdev->dev);
@@ -1464,6 +1472,9 @@
 	ida_simple_remove(&switchtec_minor_ida, MINOR(stdev->dev.devt));
 	dev_info(&stdev->dev, "unregistered.\n");
 	stdev_kill(stdev);
+	switchtec_exit_pci(stdev);
+	pci_dev_put(stdev->pdev);
+	stdev->pdev = NULL;
 	put_device(&stdev->dev);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/syscall.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/syscall.c
@@ -20,10 +20,12 @@
 	u16 word;
 	u32 dword;
 	long err;
-	long cfg_ret;
+	int cfg_ret;
 
+	err = -EPERM;
+	dev = NULL;
 	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
+		goto error;
 
 	err = -ENODEV;
 	dev = pci_get_domain_bus_and_slot(0, bus, dfn);
@@ -46,7 +48,7 @@
 	}
 
 	err = -EIO;
-	if (cfg_ret != PCIBIOS_SUCCESSFUL)
+	if (cfg_ret)
 		goto error;
 
 	switch (len) {
@@ -105,7 +107,7 @@
 		if (err)
 			break;
 		err = pci_user_write_config_byte(dev, off, byte);
-		if (err != PCIBIOS_SUCCESSFUL)
+		if (err)
 			err = -EIO;
 		break;
 
@@ -114,7 +116,7 @@
 		if (err)
 			break;
 		err = pci_user_write_config_word(dev, off, word);
-		if (err != PCIBIOS_SUCCESSFUL)
+		if (err)
 			err = -EIO;
 		break;
 
@@ -123,7 +125,7 @@
 		if (err)
 			break;
 		err = pci_user_write_config_dword(dev, off, dword);
-		if (err != PCIBIOS_SUCCESSFUL)
+		if (err)
 			err = -EIO;
 		break;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pci/vpd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pci/vpd.c
@@ -570,7 +570,6 @@
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x005f, quirk_blacklist_vpd);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, PCI_ANY_ID,
 		quirk_blacklist_vpd);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_QLOGIC, 0x2261, quirk_blacklist_vpd);
 /*
  * The Amazon Annapurna Labs 0x0031 device id is reused for other non Root Port
  * device types, so the quirk is registered for the PCI_CLASS_BRIDGE_PCI class.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pcmcia/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/pcmcia/Kconfig
@@ -151,7 +151,7 @@
 
 config PCMCIA_ALCHEMY_DEVBOARD
 	tristate "Alchemy Db/Pb1xxx PCMCIA socket services"
-	depends on MIPS_ALCHEMY && PCMCIA
+	depends on MIPS_DB1XXX && PCMCIA
 	help
 	  Enable this driver of you want PCMCIA support on your Alchemy
 	  Db1000, Db/Pb1100, Db/Pb1500, Db/Pb1550, Db/Pb1200, DB1300
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pcmcia/cs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pcmcia/cs.c
@@ -605,6 +605,7 @@
 		dev_warn(&skt->dev, "PCMCIA: unable to register socket\n");
 		skt->thread = NULL;
 		complete(&skt->thread_done);
+		put_device(&skt->dev);
 		return 0;
 	}
 	ret = pccard_sysfs_add_socket(&skt->dev);
@@ -666,18 +667,16 @@
 		if (events || sysfs_events)
 			continue;
 
+		set_current_state(TASK_INTERRUPTIBLE);
 		if (kthread_should_stop())
 			break;
 
-		set_current_state(TASK_INTERRUPTIBLE);
-
 		schedule();
 
-		/* make sure we are running */
-		__set_current_state(TASK_RUNNING);
-
 		try_to_freeze();
 	}
+	/* make sure we are running before we exit */
+	__set_current_state(TASK_RUNNING);
 
 	/* shut down socket, if a device is still present */
 	if (skt->state & SOCKET_PRESENT) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pcmcia/ds.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pcmcia/ds.c
@@ -518,9 +518,6 @@
 	/* by default don't allow DMA */
 	p_dev->dma_mask = DMA_MASK_NONE;
 	p_dev->dev.dma_mask = &p_dev->dma_mask;
-	dev_set_name(&p_dev->dev, "%d.%d", p_dev->socket->sock, p_dev->device_no);
-	if (!dev_name(&p_dev->dev))
-		goto err_free;
 	p_dev->devname = kasprintf(GFP_KERNEL, "pcmcia%s", dev_name(&p_dev->dev));
 	if (!p_dev->devname)
 		goto err_free;
@@ -578,8 +575,15 @@
 
 	pcmcia_device_query(p_dev);
 
-	if (device_register(&p_dev->dev))
-		goto err_unreg;
+	dev_set_name(&p_dev->dev, "%d.%d", p_dev->socket->sock, p_dev->device_no);
+	if (device_register(&p_dev->dev)) {
+		mutex_lock(&s->ops_mutex);
+		list_del(&p_dev->socket_device_list);
+		s->device_count--;
+		mutex_unlock(&s->ops_mutex);
+		put_device(&p_dev->dev);
+		return NULL;
+	}
 
 	return p_dev;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pcmcia/i82092.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pcmcia/i82092.c
@@ -106,6 +106,7 @@
 	for (i = 0;i<socket_count;i++) {
 		sockets[i].card_state = 1; /* 1 = present but empty */
 		sockets[i].io_base = pci_resource_start(dev, 0);
+		sockets[i].dev = dev;
 		sockets[i].socket.features |= SS_CAP_PCCARD;
 		sockets[i].socket.map_size = 0x1000;
 		sockets[i].socket.irq_mask = 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pcmcia/rsrc_nonstatic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pcmcia/rsrc_nonstatic.c
@@ -690,6 +690,9 @@
 	unsigned long min = base;
 	int ret;
 
+	if (!res)
+		return NULL;
+
 	data.mask = align - 1;
 	data.offset = base & data.mask;
 	data.map = &s_data->io_db;
@@ -809,6 +812,9 @@
 	unsigned long min, max;
 	int ret, i, j;
 
+	if (!res)
+		return NULL;
+
 	low = low || !(s->features & SS_CAP_PAGE_REGS);
 
 	data.mask = align - 1;
@@ -1047,6 +1053,8 @@
 		q = p->next;
 		kfree(p);
 	}
+
+	kfree(data);
 }
 
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pcmcia/yenta_socket.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pcmcia/yenta_socket.c
@@ -637,11 +637,11 @@
 		start = PCIBIOS_MIN_CARDBUS_IO;
 		end = ~0U;
 	} else {
-		unsigned long avail = root->end - root->start;
+		unsigned long avail = resource_size(root);
 		int i;
 		size = BRIDGE_MEM_MAX;
-		if (size > avail/8) {
-			size = (avail+1)/8;
+		if (size > (avail - 1) / 8) {
+			size = avail / 8;
 			/* round size down to next power of 2 */
 			i = 0;
 			while ((size /= 2) != 0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/perf/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/perf/Kconfig
@@ -79,13 +79,6 @@
 	  can give information about memory throughput and other related
 	  events.
 
-config HISI_PMU
-       bool "HiSilicon SoC PMU"
-       depends on ARM64 && ACPI
-       help
-         Support for HiSilicon SoC uncore performance monitoring
-         unit (PMU), such as: L3C, HHA and DDRC.
-
 config QCOM_L2_PMU
 	bool "Qualcomm Technologies L2-cache PMU"
 	depends on ARCH_QCOM && ARM64 && ACPI
@@ -129,4 +122,6 @@
 	  Extension, which provides periodic sampling of operations in
 	  the CPU pipeline and reports this via the perf AUX interface.
 
+source "drivers/perf/hisilicon/Kconfig"
+
 endmenu
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/perf/arm-cci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/perf/arm-cci.c
@@ -1720,6 +1720,7 @@
 	.driver = {
 		   .name = DRIVER_NAME,
 		   .of_match_table = arm_cci_pmu_matches,
+		   .suppress_bind_attrs = true,
 		  },
 	.probe = cci_pmu_probe,
 	.remove = cci_pmu_remove,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/perf/arm-ccn.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/perf/arm-ccn.c
@@ -1545,6 +1545,7 @@
 	.driver = {
 		.name = "arm-ccn",
 		.of_match_table = arm_ccn_match,
+		.suppress_bind_attrs = true,
 	},
 	.probe = arm_ccn_probe,
 	.remove = arm_ccn_remove,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/perf/arm_dsu_pmu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/perf/arm_dsu_pmu.c
@@ -759,6 +759,7 @@
 	.driver = {
 		.name	= DRVNAME,
 		.of_match_table = of_match_ptr(dsu_pmu_of_match),
+		.suppress_bind_attrs = true,
 	},
 	.probe = dsu_pmu_device_probe,
 	.remove = dsu_pmu_device_remove,
@@ -815,7 +816,11 @@
 	if (ret < 0)
 		return ret;
 	dsu_pmu_cpuhp_state = ret;
-	return platform_driver_register(&dsu_pmu_driver);
+	ret = platform_driver_register(&dsu_pmu_driver);
+	if (ret)
+		cpuhp_remove_multi_state(dsu_pmu_cpuhp_state);
+
+	return ret;
 }
 
 static void __exit dsu_pmu_exit(void)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/perf/arm_pmu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/perf/arm_pmu.c
@@ -322,6 +322,9 @@
 	if (!validate_event(event->pmu, &fake_pmu, leader))
 		return -EINVAL;
 
+	if (event == leader)
+		return 0;
+
 	for_each_sibling_event(sibling, leader) {
 		if (!validate_event(event->pmu, &fake_pmu, sibling))
 			return -EINVAL;
@@ -411,12 +414,7 @@
 		local64_set(&hwc->period_left, hwc->sample_period);
 	}
 
-	if (event->group_leader != event) {
-		if (validate_group(event) != 0)
-			return -EINVAL;
-	}
-
-	return 0;
+	return validate_group(event);
 }
 
 static int armpmu_event_init(struct perf_event *event)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/perf/arm_pmu_acpi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/perf/arm_pmu_acpi.c
@@ -24,8 +24,6 @@
 	int gsi, trigger;
 
 	gicc = acpi_cpu_get_madt_gicc(cpu);
-	if (WARN_ON(!gicc))
-		return -EINVAL;
 
 	gsi = gicc->performance_interrupt;
 
@@ -64,11 +62,10 @@
 	int gsi;
 
 	gicc = acpi_cpu_get_madt_gicc(cpu);
-	if (!gicc)
-		return;
 
 	gsi = gicc->performance_interrupt;
-	acpi_unregister_gsi(gsi);
+	if (gsi)
+		acpi_unregister_gsi(gsi);
 }
 
 #if IS_ENABLED(CONFIG_ARM_SPE_PMU)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/perf/arm_pmu_platform.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/perf/arm_pmu_platform.c
@@ -118,7 +118,7 @@
 
 	if (num_irqs == 1) {
 		int irq = platform_get_irq(pdev, 0);
-		if (irq && irq_is_percpu_devid(irq))
+		if ((irq > 0) && irq_is_percpu_devid(irq))
 			return pmu_parse_percpu_irq(pmu, irq);
 	}
 
@@ -236,7 +236,7 @@
 
 	ret = armpmu_register(pmu);
 	if (ret)
-		goto out_free;
+		goto out_free_irqs;
 
 	return 0;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/perf/arm_smmuv3_pmu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/perf/arm_smmuv3_pmu.c
@@ -95,6 +95,7 @@
 #define SMMU_PMCG_PA_SHIFT              12
 
 #define SMMU_PMCG_EVCNTR_RDONLY         BIT(0)
+#define SMMU_PMCG_HARDEN_DISABLE        BIT(1)
 
 static int cpuhp_state_num;
 
@@ -138,6 +139,20 @@
 	writel(SMMU_PMCG_CR_ENABLE, smmu_pmu->reg_base + SMMU_PMCG_CR);
 }
 
+static int smmu_pmu_apply_event_filter(struct smmu_pmu *smmu_pmu,
+				       struct perf_event *event, int idx);
+
+static inline void smmu_pmu_enable_quirk_hip08_09(struct pmu *pmu)
+{
+	struct smmu_pmu *smmu_pmu = to_smmu_pmu(pmu);
+	unsigned int idx;
+
+	for_each_set_bit(idx, smmu_pmu->used_counters, smmu_pmu->num_counters)
+		smmu_pmu_apply_event_filter(smmu_pmu, smmu_pmu->events[idx], idx);
+
+	smmu_pmu_enable(pmu);
+}
+
 static inline void smmu_pmu_disable(struct pmu *pmu)
 {
 	struct smmu_pmu *smmu_pmu = to_smmu_pmu(pmu);
@@ -146,6 +161,22 @@
 	writel(0, smmu_pmu->reg_base + SMMU_PMCG_IRQ_CTRL);
 }
 
+static inline void smmu_pmu_disable_quirk_hip08_09(struct pmu *pmu)
+{
+	struct smmu_pmu *smmu_pmu = to_smmu_pmu(pmu);
+	unsigned int idx;
+
+	/*
+	 * The global disable of PMU sometimes fail to stop the counting.
+	 * Harden this by writing an invalid event type to each used counter
+	 * to forcibly stop counting.
+	 */
+	for_each_set_bit(idx, smmu_pmu->used_counters, smmu_pmu->num_counters)
+		writel(0xffff, smmu_pmu->reg_base + SMMU_PMCG_EVTYPER(idx));
+
+	smmu_pmu_disable(pmu);
+}
+
 static inline void smmu_pmu_counter_set_value(struct smmu_pmu *smmu_pmu,
 					      u32 idx, u64 value)
 {
@@ -275,7 +306,7 @@
 				       struct perf_event *event, int idx)
 {
 	u32 span, sid;
-	unsigned int num_ctrs = smmu_pmu->num_counters;
+	unsigned int cur_idx, num_ctrs = smmu_pmu->num_counters;
 	bool filter_en = !!get_filter_enable(event);
 
 	span = filter_en ? get_filter_span(event) :
@@ -283,17 +314,19 @@
 	sid = filter_en ? get_filter_stream_id(event) :
 			   SMMU_PMCG_DEFAULT_FILTER_SID;
 
-	/* Support individual filter settings */
-	if (!smmu_pmu->global_filter) {
+	cur_idx = find_first_bit(smmu_pmu->used_counters, num_ctrs);
+	/*
+	 * Per-counter filtering, or scheduling the first globally-filtered
+	 * event into an empty PMU so idx == 0 and it works out equivalent.
+	 */
+	if (!smmu_pmu->global_filter || cur_idx == num_ctrs) {
 		smmu_pmu_set_event_filter(event, idx, span, sid);
 		return 0;
 	}
 
-	/* Requested settings same as current global settings*/
-	idx = find_first_bit(smmu_pmu->used_counters, num_ctrs);
-	if (idx == num_ctrs ||
-	    smmu_pmu_check_global_filter(smmu_pmu->events[idx], event)) {
-		smmu_pmu_set_event_filter(event, 0, span, sid);
+	/* Otherwise, must match whatever's currently scheduled */
+	if (smmu_pmu_check_global_filter(smmu_pmu->events[cur_idx], event)) {
+		smmu_pmu_set_evtyper(smmu_pmu, idx, get_event(event));
 		return 0;
 	}
 
@@ -717,7 +750,10 @@
 	switch (model) {
 	case IORT_SMMU_V3_PMCG_HISI_HIP08:
 		/* HiSilicon Erratum 162001800 */
-		smmu_pmu->options |= SMMU_PMCG_EVCNTR_RDONLY;
+		smmu_pmu->options |= SMMU_PMCG_EVCNTR_RDONLY | SMMU_PMCG_HARDEN_DISABLE;
+		break;
+	case IORT_SMMU_V3_PMCG_HISI_HIP09:
+		smmu_pmu->options |= SMMU_PMCG_HARDEN_DISABLE;
 		break;
 	}
 
@@ -742,6 +778,7 @@
 	platform_set_drvdata(pdev, smmu_pmu);
 
 	smmu_pmu->pmu = (struct pmu) {
+		.module		= THIS_MODULE,
 		.task_ctx_nr    = perf_invalid_context,
 		.pmu_enable	= smmu_pmu_enable,
 		.pmu_disable	= smmu_pmu_disable,
@@ -772,7 +809,7 @@
 		smmu_pmu->reloc_base = smmu_pmu->reg_base;
 	}
 
-	irq = platform_get_irq(pdev, 0);
+	irq = platform_get_irq_optional(pdev, 0);
 	if (irq > 0)
 		smmu_pmu->irq = irq;
 
@@ -805,6 +842,16 @@
 
 	smmu_pmu_get_acpi_options(smmu_pmu);
 
+	/*
+	 * For platforms suffer this quirk, the PMU disable sometimes fails to
+	 * stop the counters. This will leads to inaccurate or error counting.
+	 * Forcibly disable the counters with these quirk handler.
+	 */
+	if (smmu_pmu->options & SMMU_PMCG_HARDEN_DISABLE) {
+		smmu_pmu->pmu.pmu_enable = smmu_pmu_enable_quirk_hip08_09;
+		smmu_pmu->pmu.pmu_disable = smmu_pmu_disable_quirk_hip08_09;
+	}
+
 	/* Pick one CPU to be the preferred one to use */
 	smmu_pmu->on_cpu = raw_smp_processor_id();
 	WARN_ON(irq_set_affinity_hint(smmu_pmu->irq,
@@ -815,7 +862,7 @@
 	if (err) {
 		dev_err(dev, "Error %d registering hotplug, PMU @%pa\n",
 			err, &res_0->start);
-		goto out_cpuhp_err;
+		goto out_clear_affinity;
 	}
 
 	err = perf_pmu_register(&smmu_pmu->pmu, name, -1);
@@ -834,8 +881,8 @@
 
 out_unregister:
 	cpuhp_state_remove_instance_nocalls(cpuhp_state_num, &smmu_pmu->node);
-out_cpuhp_err:
-	put_cpu();
+out_clear_affinity:
+	irq_set_affinity_hint(smmu_pmu->irq, NULL);
 	return err;
 }
 
@@ -845,6 +892,7 @@
 
 	perf_pmu_unregister(&smmu_pmu->pmu);
 	cpuhp_state_remove_instance_nocalls(cpuhp_state_num, &smmu_pmu->node);
+	irq_set_affinity_hint(smmu_pmu->irq, NULL);
 
 	return 0;
 }
@@ -859,6 +907,7 @@
 static struct platform_driver smmu_pmu_driver = {
 	.driver = {
 		.name = "arm-smmu-v3-pmcg",
+		.suppress_bind_attrs = true,
 	},
 	.probe = smmu_pmu_probe,
 	.remove = smmu_pmu_remove,
@@ -867,6 +916,8 @@
 
 static int __init arm_smmu_pmu_init(void)
 {
+	int ret;
+
 	cpuhp_state_num = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
 						  "perf/arm/pmcg:online",
 						  NULL,
@@ -874,7 +925,11 @@
 	if (cpuhp_state_num < 0)
 		return cpuhp_state_num;
 
-	return platform_driver_register(&smmu_pmu_driver);
+	ret = platform_driver_register(&smmu_pmu_driver);
+	if (ret)
+		cpuhp_remove_multi_state(cpuhp_state_num);
+
+	return ret;
 }
 module_init(arm_smmu_pmu_init);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/perf/arm_spe_pmu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/perf/arm_spe_pmu.c
@@ -1228,6 +1228,7 @@
 	.driver	= {
 		.name		= DRVNAME,
 		.of_match_table	= of_match_ptr(arm_spe_pmu_of_match),
+		.suppress_bind_attrs = true,
 	},
 	.probe	= arm_spe_pmu_device_probe,
 	.remove	= arm_spe_pmu_device_remove,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/perf/fsl_imx8_ddr_perf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/perf/fsl_imx8_ddr_perf.c
@@ -29,7 +29,7 @@
 #define CNTL_OVER_MASK		0xFFFFFFFE
 
 #define CNTL_CSV_SHIFT		24
-#define CNTL_CSV_MASK		(0xFF << CNTL_CSV_SHIFT)
+#define CNTL_CSV_MASK		(0xFFU << CNTL_CSV_SHIFT)
 
 #define EVENT_CYCLES_ID		0
 #define EVENT_CYCLES_COUNTER	0
@@ -45,7 +45,8 @@
 static DEFINE_IDA(ddr_ida);
 
 /* DDR Perf hardware feature */
-#define DDR_CAP_AXI_ID_FILTER          0x1     /* support AXI ID filter */
+#define DDR_CAP_AXI_ID_FILTER			0x1     /* support AXI ID filter */
+#define DDR_CAP_AXI_ID_FILTER_ENHANCED		0x3     /* support enhanced AXI ID filter */
 
 struct fsl_ddr_devtype_data {
 	unsigned int quirks;    /* quirks needed for different DDR Perf core */
@@ -76,6 +77,7 @@
 	const struct fsl_ddr_devtype_data *devtype_data;
 	int irq;
 	int id;
+	int active_counter;
 };
 
 static ssize_t ddr_perf_cpumask_show(struct device *dev,
@@ -178,6 +180,36 @@
 	NULL,
 };
 
+static bool ddr_perf_is_filtered(struct perf_event *event)
+{
+	return event->attr.config == 0x41 || event->attr.config == 0x42;
+}
+
+static u32 ddr_perf_filter_val(struct perf_event *event)
+{
+	return event->attr.config1;
+}
+
+static bool ddr_perf_filters_compatible(struct perf_event *a,
+					struct perf_event *b)
+{
+	if (!ddr_perf_is_filtered(a))
+		return true;
+	if (!ddr_perf_is_filtered(b))
+		return true;
+	return ddr_perf_filter_val(a) == ddr_perf_filter_val(b);
+}
+
+static bool ddr_perf_is_enhanced_filtered(struct perf_event *event)
+{
+	unsigned int filt;
+	struct ddr_pmu *pmu = to_ddr_pmu(event->pmu);
+
+	filt = pmu->devtype_data->quirks & DDR_CAP_AXI_ID_FILTER_ENHANCED;
+	return (filt == DDR_CAP_AXI_ID_FILTER_ENHANCED) &&
+		ddr_perf_is_filtered(event);
+}
+
 static u32 ddr_perf_alloc_counter(struct ddr_pmu *pmu, int event)
 {
 	int i;
@@ -209,27 +241,17 @@
 
 static u32 ddr_perf_read_counter(struct ddr_pmu *pmu, int counter)
 {
-	return readl_relaxed(pmu->base + COUNTER_READ + counter * 4);
-}
+	struct perf_event *event = pmu->events[counter];
+	void __iomem *base = pmu->base;
 
-static bool ddr_perf_is_filtered(struct perf_event *event)
-{
-	return event->attr.config == 0x41 || event->attr.config == 0x42;
-}
-
-static u32 ddr_perf_filter_val(struct perf_event *event)
-{
-	return event->attr.config1;
-}
-
-static bool ddr_perf_filters_compatible(struct perf_event *a,
-					struct perf_event *b)
-{
-	if (!ddr_perf_is_filtered(a))
-		return true;
-	if (!ddr_perf_is_filtered(b))
-		return true;
-	return ddr_perf_filter_val(a) == ddr_perf_filter_val(b);
+	/*
+	 * return bytes instead of bursts from ddr transaction for
+	 * axid-read and axid-write event if PMU core supports enhanced
+	 * filter.
+	 */
+	base += ddr_perf_is_enhanced_filtered(event) ? COUNTER_DPCR1 :
+						       COUNTER_READ;
+	return readl_relaxed(base + counter * 4);
 }
 
 static int ddr_perf_event_init(struct perf_event *event)
@@ -306,9 +328,10 @@
 
 	if (enable) {
 		/*
-		 * must disable first, then enable again
-		 * otherwise, cycle counter will not work
-		 * if previous state is enabled.
+		 * cycle counter is special which should firstly write 0 then
+		 * write 1 into CLEAR bit to clear it. Other counters only
+		 * need write 0 into CLEAR bit and it turns out to be 1 by
+		 * hardware. Below enable flow is harmless for all counters.
 		 */
 		writel(0, pmu->base + reg);
 		val = CNTL_EN | CNTL_CLEAR;
@@ -316,7 +339,8 @@
 		writel(val, pmu->base + reg);
 	} else {
 		/* Disable counter */
-		writel(0, pmu->base + reg);
+		val = readl_relaxed(pmu->base + reg) & CNTL_EN_MASK;
+		writel(val, pmu->base + reg);
 	}
 }
 
@@ -330,6 +354,10 @@
 
 	ddr_perf_counter_enable(pmu, event->attr.config, counter, true);
 
+	if (!pmu->active_counter++)
+		ddr_perf_counter_enable(pmu, EVENT_CYCLES_ID,
+			EVENT_CYCLES_COUNTER, true);
+
 	hwc->state = 0;
 }
 
@@ -384,6 +412,10 @@
 	ddr_perf_counter_enable(pmu, event->attr.config, counter, false);
 	ddr_perf_event_update(event);
 
+	if (!--pmu->active_counter)
+		ddr_perf_counter_enable(pmu, EVENT_CYCLES_ID,
+			EVENT_CYCLES_COUNTER, false);
+
 	hwc->state |= PERF_HES_STOPPED;
 }
 
@@ -402,25 +434,10 @@
 
 static void ddr_perf_pmu_enable(struct pmu *pmu)
 {
-	struct ddr_pmu *ddr_pmu = to_ddr_pmu(pmu);
-
-	/* enable cycle counter if cycle is not active event list */
-	if (ddr_pmu->events[EVENT_CYCLES_COUNTER] == NULL)
-		ddr_perf_counter_enable(ddr_pmu,
-				      EVENT_CYCLES_ID,
-				      EVENT_CYCLES_COUNTER,
-				      true);
 }
 
 static void ddr_perf_pmu_disable(struct pmu *pmu)
 {
-	struct ddr_pmu *ddr_pmu = to_ddr_pmu(pmu);
-
-	if (ddr_pmu->events[EVENT_CYCLES_COUNTER] == NULL)
-		ddr_perf_counter_enable(ddr_pmu,
-				      EVENT_CYCLES_ID,
-				      EVENT_CYCLES_COUNTER,
-				      false);
 }
 
 static int ddr_perf_init(struct ddr_pmu *pmu, void __iomem *base,
@@ -428,6 +445,7 @@
 {
 	*pmu = (struct ddr_pmu) {
 		.pmu = (struct pmu) {
+			.module	      = THIS_MODULE,
 			.capabilities = PERF_PMU_CAP_NO_EXCLUDE,
 			.task_ctx_nr = perf_invalid_context,
 			.attr_groups = attr_groups,
@@ -538,8 +556,10 @@
 
 	name = devm_kasprintf(&pdev->dev, GFP_KERNEL, DDR_PERF_DEV_NAME "%d",
 			      num);
-	if (!name)
-		return -ENOMEM;
+	if (!name) {
+		ret = -ENOMEM;
+		goto cpuhp_state_err;
+	}
 
 	pmu->devtype_data = of_device_get_match_data(&pdev->dev);
 
@@ -551,13 +571,17 @@
 
 	if (ret < 0) {
 		dev_err(&pdev->dev, "cpuhp_setup_state_multi failed\n");
-		goto ddr_perf_err;
+		goto cpuhp_state_err;
 	}
 
 	pmu->cpuhp_state = ret;
 
 	/* Register the pmu instance for cpu hotplug */
-	cpuhp_state_add_instance_nocalls(pmu->cpuhp_state, &pmu->node);
+	ret = cpuhp_state_add_instance_nocalls(pmu->cpuhp_state, &pmu->node);
+	if (ret) {
+		dev_err(&pdev->dev, "Error %d registering hotplug\n", ret);
+		goto cpuhp_instance_err;
+	}
 
 	/* Request irq */
 	irq = of_irq_get(np, 0);
@@ -591,9 +615,10 @@
 	return 0;
 
 ddr_perf_err:
-	if (pmu->cpuhp_state)
-		cpuhp_state_remove_instance_nocalls(pmu->cpuhp_state, &pmu->node);
-
+	cpuhp_state_remove_instance_nocalls(pmu->cpuhp_state, &pmu->node);
+cpuhp_instance_err:
+	cpuhp_remove_multi_state(pmu->cpuhp_state);
+cpuhp_state_err:
 	ida_simple_remove(&ddr_ida, pmu->id);
 	dev_warn(&pdev->dev, "i.MX8 DDR Perf PMU failed (%d), disabled\n", ret);
 	return ret;
@@ -604,6 +629,7 @@
 	struct ddr_pmu *pmu = platform_get_drvdata(pdev);
 
 	cpuhp_state_remove_instance_nocalls(pmu->cpuhp_state, &pmu->node);
+	cpuhp_remove_multi_state(pmu->cpuhp_state);
 	irq_set_affinity_hint(pmu->irq, NULL);
 
 	perf_pmu_unregister(&pmu->pmu);
@@ -616,6 +642,7 @@
 	.driver         = {
 		.name   = "imx-ddr-pmu",
 		.of_match_table = imx_ddr_pmu_dt_ids,
+		.suppress_bind_attrs = true,
 	},
 	.probe          = ddr_perf_probe,
 	.remove         = ddr_perf_remove,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/perf/hisilicon/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/perf/hisilicon/Kconfig
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0-only
+config HISI_PMU
+	tristate "HiSilicon SoC PMU drivers"
+	depends on ARM64 && ACPI
+	  help
+	  Support for HiSilicon SoC L3 Cache performance monitor, Hydra Home
+	  Agent performance monitor and DDR Controller performance monitor.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/perf/hisilicon/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/perf/hisilicon/Makefile
@@ -1,2 +1,3 @@
 # SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_HISI_PMU) += hisi_uncore_pmu.o hisi_uncore_l3c_pmu.o hisi_uncore_hha_pmu.o hisi_uncore_ddrc_pmu.o
+obj-$(CONFIG_HISI_PMU) += hisi_uncore_pmu.o hisi_uncore_l3c_pmu.o \
+			  hisi_uncore_hha_pmu.o hisi_uncore_ddrc_pmu.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c
@@ -381,6 +381,7 @@
 			      ddrc_pmu->sccl_id, ddrc_pmu->index_id);
 	ddrc_pmu->pmu = (struct pmu) {
 		.name		= name,
+		.module		= THIS_MODULE,
 		.task_ctx_nr	= perf_invalid_context,
 		.event_init	= hisi_uncore_pmu_event_init,
 		.pmu_enable	= hisi_uncore_pmu_enable,
@@ -397,8 +398,9 @@
 	ret = perf_pmu_register(&ddrc_pmu->pmu, name, -1);
 	if (ret) {
 		dev_err(ddrc_pmu->dev, "DDRC PMU register failed!\n");
-		cpuhp_state_remove_instance(CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE,
-					    &ddrc_pmu->node);
+		cpuhp_state_remove_instance_nocalls(
+			CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE, &ddrc_pmu->node);
+		irq_set_affinity_hint(ddrc_pmu->irq, NULL);
 	}
 
 	return ret;
@@ -409,8 +411,9 @@
 	struct hisi_pmu *ddrc_pmu = platform_get_drvdata(pdev);
 
 	perf_pmu_unregister(&ddrc_pmu->pmu);
-	cpuhp_state_remove_instance(CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE,
-				    &ddrc_pmu->node);
+	cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_DDRC_ONLINE,
+					    &ddrc_pmu->node);
+	irq_set_affinity_hint(ddrc_pmu->irq, NULL);
 
 	return 0;
 }
@@ -419,6 +422,7 @@
 	.driver = {
 		.name = "hisi_ddrc_pmu",
 		.acpi_match_table = ACPI_PTR(hisi_ddrc_pmu_acpi_match),
+		.suppress_bind_attrs = true,
 	},
 	.probe = hisi_ddrc_pmu_probe,
 	.remove = hisi_ddrc_pmu_remove,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c
@@ -285,7 +285,7 @@
 	HISI_PMU_EVENT_ATTR(rx_wbip,		0x05),
 	HISI_PMU_EVENT_ATTR(rx_wtistash,	0x11),
 	HISI_PMU_EVENT_ATTR(rd_ddr_64b,		0x1c),
-	HISI_PMU_EVENT_ATTR(wr_dr_64b,		0x1d),
+	HISI_PMU_EVENT_ATTR(wr_ddr_64b,		0x1d),
 	HISI_PMU_EVENT_ATTR(rd_ddr_128b,	0x1e),
 	HISI_PMU_EVENT_ATTR(wr_ddr_128b,	0x1f),
 	HISI_PMU_EVENT_ATTR(spill_num,		0x20),
@@ -392,6 +392,7 @@
 			      hha_pmu->sccl_id, hha_pmu->index_id);
 	hha_pmu->pmu = (struct pmu) {
 		.name		= name,
+		.module		= THIS_MODULE,
 		.task_ctx_nr	= perf_invalid_context,
 		.event_init	= hisi_uncore_pmu_event_init,
 		.pmu_enable	= hisi_uncore_pmu_enable,
@@ -408,8 +409,9 @@
 	ret = perf_pmu_register(&hha_pmu->pmu, name, -1);
 	if (ret) {
 		dev_err(hha_pmu->dev, "HHA PMU register failed!\n");
-		cpuhp_state_remove_instance(CPUHP_AP_PERF_ARM_HISI_HHA_ONLINE,
-					    &hha_pmu->node);
+		cpuhp_state_remove_instance_nocalls(
+			CPUHP_AP_PERF_ARM_HISI_HHA_ONLINE, &hha_pmu->node);
+		irq_set_affinity_hint(hha_pmu->irq, NULL);
 	}
 
 	return ret;
@@ -420,8 +422,9 @@
 	struct hisi_pmu *hha_pmu = platform_get_drvdata(pdev);
 
 	perf_pmu_unregister(&hha_pmu->pmu);
-	cpuhp_state_remove_instance(CPUHP_AP_PERF_ARM_HISI_HHA_ONLINE,
-				    &hha_pmu->node);
+	cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_HHA_ONLINE,
+					    &hha_pmu->node);
+	irq_set_affinity_hint(hha_pmu->irq, NULL);
 
 	return 0;
 }
@@ -430,6 +433,7 @@
 	.driver = {
 		.name = "hisi_hha_pmu",
 		.acpi_match_table = ACPI_PTR(hisi_hha_pmu_acpi_match),
+		.suppress_bind_attrs = true,
 	},
 	.probe = hisi_hha_pmu_probe,
 	.remove = hisi_hha_pmu_remove,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/perf/hisilicon/hisi_uncore_l3c_pmu.c
@@ -35,7 +35,7 @@
 /* L3C has 8-counters */
 #define L3C_NR_COUNTERS		0x8
 
-#define L3C_PERF_CTRL_EN	0x20000
+#define L3C_PERF_CTRL_EN	0x10000
 #define L3C_EVTYPE_NONE		0xff
 
 /*
@@ -382,6 +382,7 @@
 			      l3c_pmu->sccl_id, l3c_pmu->index_id);
 	l3c_pmu->pmu = (struct pmu) {
 		.name		= name,
+		.module		= THIS_MODULE,
 		.task_ctx_nr	= perf_invalid_context,
 		.event_init	= hisi_uncore_pmu_event_init,
 		.pmu_enable	= hisi_uncore_pmu_enable,
@@ -398,8 +399,9 @@
 	ret = perf_pmu_register(&l3c_pmu->pmu, name, -1);
 	if (ret) {
 		dev_err(l3c_pmu->dev, "L3C PMU register failed!\n");
-		cpuhp_state_remove_instance(CPUHP_AP_PERF_ARM_HISI_L3_ONLINE,
-					    &l3c_pmu->node);
+		cpuhp_state_remove_instance_nocalls(
+			CPUHP_AP_PERF_ARM_HISI_L3_ONLINE, &l3c_pmu->node);
+		irq_set_affinity_hint(l3c_pmu->irq, NULL);
 	}
 
 	return ret;
@@ -410,8 +412,9 @@
 	struct hisi_pmu *l3c_pmu = platform_get_drvdata(pdev);
 
 	perf_pmu_unregister(&l3c_pmu->pmu);
-	cpuhp_state_remove_instance(CPUHP_AP_PERF_ARM_HISI_L3_ONLINE,
-				    &l3c_pmu->node);
+	cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_HISI_L3_ONLINE,
+					    &l3c_pmu->node);
+	irq_set_affinity_hint(l3c_pmu->irq, NULL);
 
 	return 0;
 }
@@ -420,6 +423,7 @@
 	.driver = {
 		.name = "hisi_l3c_pmu",
 		.acpi_match_table = ACPI_PTR(hisi_l3c_pmu_acpi_match),
+		.suppress_bind_attrs = true,
 	},
 	.probe = hisi_l3c_pmu_probe,
 	.remove = hisi_l3c_pmu_remove,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/perf/hisilicon/hisi_uncore_pmu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/perf/hisilicon/hisi_uncore_pmu.c
@@ -34,6 +34,7 @@
 
 	return sprintf(buf, "%s\n", (char *)eattr->var);
 }
+EXPORT_SYMBOL_GPL(hisi_format_sysfs_show);
 
 /*
  * PMU event attributes
@@ -47,6 +48,7 @@
 
 	return sprintf(page, "config=0x%lx\n", (unsigned long)eattr->var);
 }
+EXPORT_SYMBOL_GPL(hisi_event_sysfs_show);
 
 /*
  * sysfs cpumask attributes. For uncore PMU, we only have a single CPU to show
@@ -58,6 +60,7 @@
 
 	return sprintf(buf, "%d\n", hisi_pmu->on_cpu);
 }
+EXPORT_SYMBOL_GPL(hisi_cpumask_sysfs_show);
 
 static bool hisi_validate_event_group(struct perf_event *event)
 {
@@ -96,6 +99,7 @@
 {
 	return idx >= 0 && idx < hisi_pmu->num_counters;
 }
+EXPORT_SYMBOL_GPL(hisi_uncore_pmu_counter_valid);
 
 int hisi_uncore_pmu_get_event_idx(struct perf_event *event)
 {
@@ -112,6 +116,7 @@
 
 	return idx;
 }
+EXPORT_SYMBOL_GPL(hisi_uncore_pmu_get_event_idx);
 
 static void hisi_uncore_pmu_clear_event_idx(struct hisi_pmu *hisi_pmu, int idx)
 {
@@ -172,6 +177,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(hisi_uncore_pmu_event_init);
 
 /*
  * Set the counter to count the event that we're interested in,
@@ -219,6 +225,7 @@
 	/* Write start value to the hardware event counter */
 	hisi_pmu->ops->write_counter(hisi_pmu, hwc, val);
 }
+EXPORT_SYMBOL_GPL(hisi_uncore_pmu_set_event_period);
 
 void hisi_uncore_pmu_event_update(struct perf_event *event)
 {
@@ -239,6 +246,7 @@
 		HISI_MAX_PERIOD(hisi_pmu->counter_bits);
 	local64_add(delta, &event->count);
 }
+EXPORT_SYMBOL_GPL(hisi_uncore_pmu_event_update);
 
 void hisi_uncore_pmu_start(struct perf_event *event, int flags)
 {
@@ -261,6 +269,7 @@
 	hisi_uncore_pmu_enable_event(event);
 	perf_event_update_userpage(event);
 }
+EXPORT_SYMBOL_GPL(hisi_uncore_pmu_start);
 
 void hisi_uncore_pmu_stop(struct perf_event *event, int flags)
 {
@@ -277,6 +286,7 @@
 	hisi_uncore_pmu_event_update(event);
 	hwc->state |= PERF_HES_UPTODATE;
 }
+EXPORT_SYMBOL_GPL(hisi_uncore_pmu_stop);
 
 int hisi_uncore_pmu_add(struct perf_event *event, int flags)
 {
@@ -299,6 +309,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(hisi_uncore_pmu_add);
 
 void hisi_uncore_pmu_del(struct perf_event *event, int flags)
 {
@@ -310,12 +321,14 @@
 	perf_event_update_userpage(event);
 	hisi_pmu->pmu_events.hw_events[hwc->idx] = NULL;
 }
+EXPORT_SYMBOL_GPL(hisi_uncore_pmu_del);
 
 void hisi_uncore_pmu_read(struct perf_event *event)
 {
 	/* Read hardware counter and update the perf counter statistics */
 	hisi_uncore_pmu_event_update(event);
 }
+EXPORT_SYMBOL_GPL(hisi_uncore_pmu_read);
 
 void hisi_uncore_pmu_enable(struct pmu *pmu)
 {
@@ -328,6 +341,7 @@
 
 	hisi_pmu->ops->start_counters(hisi_pmu);
 }
+EXPORT_SYMBOL_GPL(hisi_uncore_pmu_enable);
 
 void hisi_uncore_pmu_disable(struct pmu *pmu)
 {
@@ -335,6 +349,7 @@
 
 	hisi_pmu->ops->stop_counters(hisi_pmu);
 }
+EXPORT_SYMBOL_GPL(hisi_uncore_pmu_disable);
 
 /*
  * Read Super CPU cluster and CPU cluster ID from MPIDR_EL1.
@@ -398,10 +413,11 @@
 	hisi_pmu->on_cpu = cpu;
 
 	/* Overflow interrupt also should use the same CPU */
-	WARN_ON(irq_set_affinity(hisi_pmu->irq, cpumask_of(cpu)));
+	WARN_ON(irq_set_affinity_hint(hisi_pmu->irq, cpumask_of(cpu)));
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(hisi_uncore_pmu_online_cpu);
 
 int hisi_uncore_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node)
 {
@@ -430,7 +446,10 @@
 	perf_pmu_migrate_context(&hisi_pmu->pmu, cpu, target);
 	/* Use this CPU for event counting */
 	hisi_pmu->on_cpu = target;
-	WARN_ON(irq_set_affinity(hisi_pmu->irq, cpumask_of(target)));
+	WARN_ON(irq_set_affinity_hint(hisi_pmu->irq, cpumask_of(target)));
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(hisi_uncore_pmu_offline_cpu);
+
+MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/perf/qcom_l2_pmu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/perf/qcom_l2_pmu.c
@@ -781,7 +781,7 @@
 {
 	u64 mpidr;
 	int cpu_cluster_id;
-	struct cluster_pmu *cluster = NULL;
+	struct cluster_pmu *cluster;
 
 	/*
 	 * This assumes that the cluster_id is in MPIDR[aff1] for
@@ -803,10 +803,10 @@
 			 cluster->cluster_id);
 		cpumask_set_cpu(cpu, &cluster->cluster_cpus);
 		*per_cpu_ptr(l2cache_pmu->pmu_cluster, cpu) = cluster;
-		break;
+		return cluster;
 	}
 
-	return cluster;
+	return NULL;
 }
 
 static int l2cache_pmu_online_cpu(unsigned int cpu, struct hlist_node *node)
@@ -1028,6 +1028,7 @@
 	.driver = {
 		.name = "qcom-l2cache-pmu",
 		.acpi_match_table = ACPI_PTR(l2_cache_pmu_acpi_match),
+		.suppress_bind_attrs = true,
 	},
 	.probe = l2_cache_pmu_probe,
 	.remove = l2_cache_pmu_remove,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/perf/qcom_l3_pmu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/perf/qcom_l3_pmu.c
@@ -814,6 +814,7 @@
 	.driver = {
 		.name = "qcom-l3cache-pmu",
 		.acpi_match_table = ACPI_PTR(qcom_l3_cache_pmu_acpi_match),
+		.suppress_bind_attrs = true,
 	},
 	.probe = qcom_l3_cache_pmu_probe,
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/perf/thunderx2_pmu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/perf/thunderx2_pmu.c
@@ -627,14 +627,17 @@
 	list_for_each_entry(rentry, &list, node) {
 		if (resource_type(rentry->res) == IORESOURCE_MEM) {
 			res = *rentry->res;
+			rentry = NULL;
 			break;
 		}
 	}
+	acpi_dev_free_resource_list(&list);
 
-	if (!rentry->res)
+	if (rentry) {
+		dev_err(dev, "PMU type %d: Fail to find resource\n", type);
 		return NULL;
+	}
 
-	acpi_dev_free_resource_list(&list);
 	base = devm_ioremap_resource(dev, &res);
 	if (IS_ERR(base)) {
 		dev_err(dev, "PMU type %d: Fail to map resource\n", type);
@@ -816,6 +819,7 @@
 	.driver = {
 		.name		= "tx2-uncore-pmu",
 		.acpi_match_table = ACPI_PTR(tx2_uncore_acpi_match),
+		.suppress_bind_attrs = true,
 	},
 	.probe = tx2_uncore_probe,
 	.remove = tx2_uncore_remove,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/perf/xgene_pmu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/perf/xgene_pmu.c
@@ -1459,17 +1459,6 @@
 }
 
 #if defined(CONFIG_ACPI)
-static int acpi_pmu_dev_add_resource(struct acpi_resource *ares, void *data)
-{
-	struct resource *res = data;
-
-	if (ares->type == ACPI_RESOURCE_TYPE_FIXED_MEMORY32)
-		acpi_dev_resource_memory(ares, res);
-
-	/* Always tell the ACPI core to skip this resource */
-	return 1;
-}
-
 static struct
 xgene_pmu_dev_ctx *acpi_get_pmu_hw_inf(struct xgene_pmu *xgene_pmu,
 				       struct acpi_device *adev, u32 type)
@@ -1481,6 +1470,7 @@
 	struct hw_pmu_info *inf;
 	void __iomem *dev_csr;
 	struct resource res;
+	struct resource_entry *rentry;
 	int enable_bit;
 	int rc;
 
@@ -1489,11 +1479,23 @@
 		return NULL;
 
 	INIT_LIST_HEAD(&resource_list);
-	rc = acpi_dev_get_resources(adev, &resource_list,
-				    acpi_pmu_dev_add_resource, &res);
+	rc = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
+	if (rc <= 0) {
+		dev_err(dev, "PMU type %d: No resources found\n", type);
+		return NULL;
+	}
+
+	list_for_each_entry(rentry, &resource_list, node) {
+		if (resource_type(rentry->res) == IORESOURCE_MEM) {
+			res = *rentry->res;
+			rentry = NULL;
+			break;
+		}
+	}
 	acpi_dev_free_resource_list(&resource_list);
-	if (rc < 0) {
-		dev_err(dev, "PMU type %d: No resource address found\n", type);
+
+	if (rentry) {
+		dev_err(dev, "PMU type %d: No memory resource found\n", type);
 		return NULL;
 	}
 
@@ -1981,6 +1983,7 @@
 		.name		= "xgene-pmu",
 		.of_match_table = xgene_pmu_of_match,
 		.acpi_match_table = ACPI_PTR(xgene_pmu_acpi_match),
+		.suppress_bind_attrs = true,
 	},
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/Kconfig
@@ -67,6 +67,15 @@
 source "drivers/phy/samsung/Kconfig"
 source "drivers/phy/socionext/Kconfig"
 source "drivers/phy/st/Kconfig"
+
+config PHY_XILINX_ZYNQMP
+	tristate "Xilinx ZynqMP PHY driver"
+	depends on ARCH_ZYNQMP
+	select GENERIC_PHY
+	help
+	  Enable this to support ZynqMP High Speed Gigabit Transceiver
+	  that is part of ZynqMP SoC.
+
 source "drivers/phy/tegra/Kconfig"
 source "drivers/phy/ti/Kconfig"
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/Makefile
@@ -28,3 +28,4 @@
 					   socionext/	\
 					   st/		\
 					   ti/
+obj-$(CONFIG_PHY_XILINX_ZYNQMP)		+= phy-zynqmp.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/allwinner/phy-sun4i-usb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/allwinner/phy-sun4i-usb.c
@@ -545,13 +545,14 @@
 	struct sun4i_usb_phy_data *data =
 		container_of(work, struct sun4i_usb_phy_data, detect.work);
 	struct phy *phy0 = data->phys[0].phy;
-	struct sun4i_usb_phy *phy = phy_get_drvdata(phy0);
+	struct sun4i_usb_phy *phy;
 	bool force_session_end, id_notify = false, vbus_notify = false;
 	int id_det, vbus_det;
 
-	if (phy0 == NULL)
+	if (!phy0)
 		return;
 
+	phy = phy_get_drvdata(phy0);
 	id_det = sun4i_usb_phy0_get_id_det(data);
 	vbus_det = sun4i_usb_phy0_get_vbus_det(data);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/broadcom/phy-bcm-sr-usb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/broadcom/phy-bcm-sr-usb.c
@@ -16,8 +16,6 @@
 };
 
 enum bcm_usb_phy_reg {
-	PLL_NDIV_FRAC,
-	PLL_NDIV_INT,
 	PLL_CTRL,
 	PHY_CTRL,
 	PHY_PLL_CTRL,
@@ -31,18 +29,11 @@
 };
 
 static const u8 bcm_usb_combo_phy_hs[] = {
-	[PLL_NDIV_FRAC]	= 0x04,
-	[PLL_NDIV_INT]	= 0x08,
 	[PLL_CTRL]	= 0x0c,
 	[PHY_CTRL]	= 0x10,
 };
 
-#define HSPLL_NDIV_INT_VAL	0x13
-#define HSPLL_NDIV_FRAC_VAL	0x1005
-
 static const u8 bcm_usb_hs_phy[] = {
-	[PLL_NDIV_FRAC]	= 0x0,
-	[PLL_NDIV_INT]	= 0x4,
 	[PLL_CTRL]	= 0x8,
 	[PHY_CTRL]	= 0xc,
 };
@@ -52,7 +43,6 @@
 	SSPLL_SUSPEND_EN,
 	PLL_SEQ_START,
 	PLL_LOCK,
-	PLL_PDIV,
 };
 
 static const u8 u3pll_ctrl[] = {
@@ -66,29 +56,17 @@
 #define HSPLL_PDIV_VAL		0x1
 
 static const u8 u2pll_ctrl[] = {
-	[PLL_PDIV]	= 1,
 	[PLL_RESETB]	= 5,
 	[PLL_LOCK]	= 6,
 };
 
 enum bcm_usb_phy_ctrl_bits {
 	CORERDY,
-	AFE_LDO_PWRDWNB,
-	AFE_PLL_PWRDWNB,
-	AFE_BG_PWRDWNB,
-	PHY_ISO,
 	PHY_RESETB,
 	PHY_PCTL,
 };
 
 #define PHY_PCTL_MASK	0xffff
-/*
- * 0x0806 of PCTL_VAL has below bits set
- * BIT-8 : refclk divider 1
- * BIT-3:2: device mode; mode is not effect
- * BIT-1: soft reset active low
- */
-#define HSPHY_PCTL_VAL	0x0806
 #define SSPHY_PCTL_VAL	0x0006
 
 static const u8 u3phy_ctrl[] = {
@@ -98,10 +76,6 @@
 
 static const u8 u2phy_ctrl[] = {
 	[CORERDY]		= 0,
-	[AFE_LDO_PWRDWNB]	= 1,
-	[AFE_PLL_PWRDWNB]	= 2,
-	[AFE_BG_PWRDWNB]	= 3,
-	[PHY_ISO]		= 4,
 	[PHY_RESETB]		= 5,
 	[PHY_PCTL]		= 6,
 };
@@ -186,38 +160,13 @@
 	int ret = 0;
 	void __iomem *regs = phy_cfg->regs;
 	const u8 *offset;
-	u32 rd_data;
 
 	offset = phy_cfg->offset;
 
-	writel(HSPLL_NDIV_INT_VAL, regs + offset[PLL_NDIV_INT]);
-	writel(HSPLL_NDIV_FRAC_VAL, regs + offset[PLL_NDIV_FRAC]);
-
-	rd_data = readl(regs + offset[PLL_CTRL]);
-	rd_data &= ~(HSPLL_PDIV_MASK << u2pll_ctrl[PLL_PDIV]);
-	rd_data |= (HSPLL_PDIV_VAL << u2pll_ctrl[PLL_PDIV]);
-	writel(rd_data, regs + offset[PLL_CTRL]);
-
-	/* Set Core Ready high */
-	bcm_usb_reg32_setbits(regs + offset[PHY_CTRL],
-			      BIT(u2phy_ctrl[CORERDY]));
-
-	/* Maximum timeout for Core Ready done */
-	msleep(30);
-
+	bcm_usb_reg32_clrbits(regs + offset[PLL_CTRL],
+			      BIT(u2pll_ctrl[PLL_RESETB]));
 	bcm_usb_reg32_setbits(regs + offset[PLL_CTRL],
 			      BIT(u2pll_ctrl[PLL_RESETB]));
-	bcm_usb_reg32_setbits(regs + offset[PHY_CTRL],
-			      BIT(u2phy_ctrl[PHY_RESETB]));
-
-
-	rd_data = readl(regs + offset[PHY_CTRL]);
-	rd_data &= ~(PHY_PCTL_MASK << u2phy_ctrl[PHY_PCTL]);
-	rd_data |= (HSPHY_PCTL_VAL << u2phy_ctrl[PHY_PCTL]);
-	writel(rd_data, regs + offset[PHY_CTRL]);
-
-	/* Maximum timeout for PLL reset done */
-	msleep(30);
 
 	ret = bcm_usb_pll_lock_check(regs + offset[PLL_CTRL],
 				     BIT(u2pll_ctrl[PLL_LOCK]));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/hisilicon/phy-hisi-inno-usb2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/hisilicon/phy-hisi-inno-usb2.c
@@ -155,7 +155,7 @@
 		phy_set_drvdata(phy, &priv->ports[i]);
 		i++;
 
-		if (i > INNO_PHY_PORT_NUM) {
+		if (i >= INNO_PHY_PORT_NUM) {
 			dev_warn(dev, "Support %d ports in maximum\n", i);
 			break;
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/lantiq/phy-lantiq-vrx200-pcie.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/lantiq/phy-lantiq-vrx200-pcie.c
@@ -323,7 +323,8 @@
 		goto err_disable_pdi_clk;
 
 	/* Check if we are in "startup ready" status */
-	if (ltq_vrx200_pcie_phy_wait_for_pll(phy) != 0)
+	ret = ltq_vrx200_pcie_phy_wait_for_pll(phy);
+	if (ret)
 		goto err_disable_phy_clk;
 
 	ltq_vrx200_pcie_phy_apply_workarounds(phy);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/marvell/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/marvell/Kconfig
@@ -3,8 +3,8 @@
 # Phy drivers for Marvell platforms
 #
 config ARMADA375_USBCLUSTER_PHY
-	def_bool y
-	depends on MACH_ARMADA_375 || COMPILE_TEST
+	bool "Armada 375 USB cluster PHY support" if COMPILE_TEST
+	default y if MACH_ARMADA_375
 	depends on OF && HAS_IOMEM
 	select GENERIC_PHY
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/marvell/phy-armada38x-comphy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/marvell/phy-armada38x-comphy.c
@@ -41,6 +41,7 @@
 
 struct a38x_comphy {
 	void __iomem *base;
+	void __iomem *conf;
 	struct device *dev;
 	struct a38x_comphy_lane lane[MAX_A38X_COMPHY];
 };
@@ -54,6 +55,21 @@
 	{ 0, 0, 3 },
 };
 
+static void a38x_set_conf(struct a38x_comphy_lane *lane, bool enable)
+{
+	struct a38x_comphy *priv = lane->priv;
+	u32 conf;
+
+	if (priv->conf) {
+		conf = readl_relaxed(priv->conf);
+		if (enable)
+			conf |= BIT(lane->port);
+		else
+			conf &= ~BIT(lane->port);
+		writel(conf, priv->conf);
+	}
+}
+
 static void a38x_comphy_set_reg(struct a38x_comphy_lane *lane,
 				unsigned int offset, u32 mask, u32 value)
 {
@@ -97,6 +113,7 @@
 {
 	struct a38x_comphy_lane *lane = phy_get_drvdata(phy);
 	unsigned int gen;
+	int ret;
 
 	if (mode != PHY_MODE_ETHERNET)
 		return -EINVAL;
@@ -115,13 +132,20 @@
 		return -EINVAL;
 	}
 
+	a38x_set_conf(lane, false);
+
 	a38x_comphy_set_speed(lane, gen, gen);
 
-	return a38x_comphy_poll(lane, COMPHY_STAT1,
-				COMPHY_STAT1_PLL_RDY_TX |
-				COMPHY_STAT1_PLL_RDY_RX,
-				COMPHY_STAT1_PLL_RDY_TX |
-				COMPHY_STAT1_PLL_RDY_RX);
+	ret = a38x_comphy_poll(lane, COMPHY_STAT1,
+			       COMPHY_STAT1_PLL_RDY_TX |
+			       COMPHY_STAT1_PLL_RDY_RX,
+			       COMPHY_STAT1_PLL_RDY_TX |
+			       COMPHY_STAT1_PLL_RDY_RX);
+
+	if (ret == 0)
+		a38x_set_conf(lane, true);
+
+	return ret;
 }
 
 static const struct phy_ops a38x_comphy_ops = {
@@ -174,14 +198,21 @@
 	if (!priv)
 		return -ENOMEM;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	base = devm_ioremap_resource(&pdev->dev, res);
+	base = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(base))
 		return PTR_ERR(base);
 
 	priv->dev = &pdev->dev;
 	priv->base = base;
 
+	/* Optional */
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "conf");
+	if (res) {
+		priv->conf = devm_ioremap_resource(&pdev->dev, res);
+		if (IS_ERR(priv->conf))
+			return PTR_ERR(priv->conf);
+	}
+
 	for_each_available_child_of_node(pdev->dev.of_node, child) {
 		struct phy *phy;
 		int ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/marvell/phy-mvebu-a3700-comphy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/marvell/phy-mvebu-a3700-comphy.c
@@ -26,7 +26,6 @@
 #define COMPHY_SIP_POWER_ON			0x82000001
 #define COMPHY_SIP_POWER_OFF			0x82000002
 #define COMPHY_SIP_PLL_LOCK			0x82000003
-#define COMPHY_FW_NOT_SUPPORTED			(-1)
 
 #define COMPHY_FW_MODE_SATA			0x1
 #define COMPHY_FW_MODE_SGMII			0x2
@@ -112,10 +111,19 @@
 				  unsigned long mode)
 {
 	struct arm_smccc_res res;
+	s32 ret;
 
 	arm_smccc_smc(function, lane, mode, 0, 0, 0, 0, 0, &res);
+	ret = res.a0;
 
-	return res.a0;
+	switch (ret) {
+	case SMCCC_RET_SUCCESS:
+		return 0;
+	case SMCCC_RET_NOT_SUPPORTED:
+		return -EOPNOTSUPP;
+	default:
+		return -EINVAL;
+	}
 }
 
 static int mvebu_a3700_comphy_get_fw_mode(int lane, int port,
@@ -220,7 +228,7 @@
 	}
 
 	ret = mvebu_a3700_comphy_smc(COMPHY_SIP_POWER_ON, lane->id, fw_param);
-	if (ret == COMPHY_FW_NOT_SUPPORTED)
+	if (ret == -EOPNOTSUPP)
 		dev_err(lane->dev,
 			"unsupported SMC call, try updating your firmware\n");
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/marvell/phy-mvebu-cp110-comphy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/marvell/phy-mvebu-cp110-comphy.c
@@ -123,7 +123,6 @@
 
 #define COMPHY_SIP_POWER_ON	0x82000001
 #define COMPHY_SIP_POWER_OFF	0x82000002
-#define COMPHY_FW_NOT_SUPPORTED	(-1)
 
 /*
  * A lane is described by the following bitfields:
@@ -273,10 +272,19 @@
 			    unsigned long lane, unsigned long mode)
 {
 	struct arm_smccc_res res;
+	s32 ret;
 
 	arm_smccc_smc(function, phys, lane, mode, 0, 0, 0, 0, &res);
+	ret = res.a0;
 
-	return res.a0;
+	switch (ret) {
+	case SMCCC_RET_SUCCESS:
+		return 0;
+	case SMCCC_RET_NOT_SUPPORTED:
+		return -EOPNOTSUPP;
+	default:
+		return -EINVAL;
+	}
 }
 
 static int mvebu_comphy_get_mode(bool fw_mode, int lane, int port,
@@ -819,7 +827,7 @@
 	if (!ret)
 		return ret;
 
-	if (ret == COMPHY_FW_NOT_SUPPORTED)
+	if (ret == -EOPNOTSUPP)
 		dev_err(priv->dev,
 			"unsupported SMC call, try updating your firmware\n");
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/motorola/phy-cpcap-usb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/motorola/phy-cpcap-usb.c
@@ -115,7 +115,7 @@
 enum cpcap_gpio_mode {
 	CPCAP_DM_DP,
 	CPCAP_MDM_RX_TX,
-	CPCAP_UNKNOWN,
+	CPCAP_UNKNOWN_DISABLED,	/* Seems to disable USB lines */
 	CPCAP_OTG_DM_DP,
 };
 
@@ -207,6 +207,19 @@
 static int cpcap_usb_set_uart_mode(struct cpcap_phy_ddata *ddata);
 static int cpcap_usb_set_usb_mode(struct cpcap_phy_ddata *ddata);
 
+static void cpcap_usb_try_musb_mailbox(struct cpcap_phy_ddata *ddata,
+				       enum musb_vbus_id_status status)
+{
+	int error;
+
+	error = musb_mailbox(status);
+	if (!error)
+		return;
+
+	dev_dbg(ddata->dev, "%s: musb_mailbox failed: %i\n",
+		__func__, error);
+}
+
 static void cpcap_usb_detect(struct work_struct *work)
 {
 	struct cpcap_phy_ddata *ddata;
@@ -226,9 +239,7 @@
 		if (error)
 			goto out_err;
 
-		error = musb_mailbox(MUSB_ID_GROUND);
-		if (error)
-			goto out_err;
+		cpcap_usb_try_musb_mailbox(ddata, MUSB_ID_GROUND);
 
 		error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
 					   CPCAP_BIT_VBUSSTBY_EN |
@@ -257,9 +268,7 @@
 			error = cpcap_usb_set_usb_mode(ddata);
 			if (error)
 				goto out_err;
-			error = musb_mailbox(MUSB_ID_GROUND);
-			if (error)
-				goto out_err;
+			cpcap_usb_try_musb_mailbox(ddata, MUSB_ID_GROUND);
 
 			return;
 		}
@@ -269,22 +278,18 @@
 		error = cpcap_usb_set_usb_mode(ddata);
 		if (error)
 			goto out_err;
-		error = musb_mailbox(MUSB_VBUS_VALID);
-		if (error)
-			goto out_err;
+		cpcap_usb_try_musb_mailbox(ddata, MUSB_VBUS_VALID);
 
 		return;
 	}
 
+	cpcap_usb_try_musb_mailbox(ddata, MUSB_VBUS_OFF);
+
 	/* Default to debug UART mode */
 	error = cpcap_usb_set_uart_mode(ddata);
 	if (error)
 		goto out_err;
 
-	error = musb_mailbox(MUSB_VBUS_OFF);
-	if (error)
-		goto out_err;
-
 	dev_dbg(ddata->dev, "set UART mode\n");
 
 	return;
@@ -376,7 +381,8 @@
 {
 	int error;
 
-	error = cpcap_usb_gpio_set_mode(ddata, CPCAP_DM_DP);
+	/* Disable lines to prevent glitches from waking up mdm6600 */
+	error = cpcap_usb_gpio_set_mode(ddata, CPCAP_UNKNOWN_DISABLED);
 	if (error)
 		goto out_err;
 
@@ -403,6 +409,11 @@
 	if (error)
 		goto out_err;
 
+	/* Enable UART mode */
+	error = cpcap_usb_gpio_set_mode(ddata, CPCAP_DM_DP);
+	if (error)
+		goto out_err;
+
 	return 0;
 
 out_err:
@@ -415,7 +426,8 @@
 {
 	int error;
 
-	error = cpcap_usb_gpio_set_mode(ddata, CPCAP_OTG_DM_DP);
+	/* Disable lines to prevent glitches from waking up mdm6600 */
+	error = cpcap_usb_gpio_set_mode(ddata, CPCAP_UNKNOWN_DISABLED);
 	if (error)
 		return error;
 
@@ -455,6 +467,11 @@
 	if (error)
 		goto out_err;
 
+	/* Enable USB mode */
+	error = cpcap_usb_gpio_set_mode(ddata, CPCAP_OTG_DM_DP);
+	if (error)
+		goto out_err;
+
 	return 0;
 
 out_err:
@@ -608,35 +625,42 @@
 	generic_phy = devm_phy_create(ddata->dev, NULL, &ops);
 	if (IS_ERR(generic_phy)) {
 		error = PTR_ERR(generic_phy);
-		return PTR_ERR(generic_phy);
+		goto out_reg_disable;
 	}
 
 	phy_set_drvdata(generic_phy, ddata);
 
 	phy_provider = devm_of_phy_provider_register(ddata->dev,
 						     of_phy_simple_xlate);
-	if (IS_ERR(phy_provider))
-		return PTR_ERR(phy_provider);
+	if (IS_ERR(phy_provider)) {
+		error = PTR_ERR(phy_provider);
+		goto out_reg_disable;
+	}
 
 	error = cpcap_usb_init_optional_pins(ddata);
 	if (error)
-		return error;
+		goto out_reg_disable;
 
 	cpcap_usb_init_optional_gpios(ddata);
 
 	error = cpcap_usb_init_iio(ddata);
 	if (error)
-		return error;
+		goto out_reg_disable;
 
 	error = cpcap_usb_init_interrupts(pdev, ddata);
 	if (error)
-		return error;
+		goto out_reg_disable;
 
 	usb_add_phy_dev(&ddata->phy);
 	atomic_set(&ddata->active, 1);
 	schedule_delayed_work(&ddata->detect_work, msecs_to_jiffies(1));
 
 	return 0;
+
+out_reg_disable:
+	regulator_disable(ddata->vusb);
+
+	return error;
 }
 
 static int cpcap_usb_phy_remove(struct platform_device *pdev)
@@ -649,9 +673,7 @@
 	if (error)
 		dev_err(ddata->dev, "could not set UART mode\n");
 
-	error = musb_mailbox(MUSB_VBUS_OFF);
-	if (error)
-		dev_err(ddata->dev, "could not set mailbox\n");
+	cpcap_usb_try_musb_mailbox(ddata, MUSB_VBUS_OFF);
 
 	usb_remove_phy(&ddata->phy);
 	cancel_delayed_work_sync(&ddata->detect_work);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/motorola/phy-mapphone-mdm6600.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/motorola/phy-mapphone-mdm6600.c
@@ -20,6 +20,7 @@
 
 #define PHY_MDM6600_PHY_DELAY_MS	4000	/* PHY enable 2.2s to 3.5s */
 #define PHY_MDM6600_ENABLED_DELAY_MS	8000	/* 8s more total for MDM6600 */
+#define PHY_MDM6600_WAKE_KICK_MS	600	/* time on after GPIO toggle */
 #define MDM6600_MODEM_IDLE_DELAY_MS	1000	/* modem after USB suspend */
 #define MDM6600_MODEM_WAKE_DELAY_MS	200	/* modem response after idle */
 
@@ -121,16 +122,10 @@
 {
 	struct phy_mdm6600 *ddata = phy_get_drvdata(x);
 	struct gpio_desc *enable_gpio = ddata->ctrl_gpios[PHY_MDM6600_ENABLE];
-	int error;
 
 	if (!ddata->enabled)
 		return -ENODEV;
 
-	error = pinctrl_pm_select_default_state(ddata->dev);
-	if (error)
-		dev_warn(ddata->dev, "%s: error with default_state: %i\n",
-			 __func__, error);
-
 	gpiod_set_value_cansleep(enable_gpio, 1);
 
 	/* Allow aggressive PM for USB, it's only needed for n_gsm port */
@@ -159,11 +154,6 @@
 
 	gpiod_set_value_cansleep(enable_gpio, 0);
 
-	error = pinctrl_pm_select_sleep_state(ddata->dev);
-	if (error)
-		dev_warn(ddata->dev, "%s: error with sleep_state: %i\n",
-			 __func__, error);
-
 	return 0;
 }
 
@@ -200,7 +190,7 @@
 	struct phy_mdm6600 *ddata;
 	struct device *dev;
 	DECLARE_BITMAP(values, PHY_MDM6600_NR_STATUS_LINES);
-	int error, i, val = 0;
+	int error;
 
 	ddata = container_of(work, struct phy_mdm6600, status_work.work);
 	dev = ddata->dev;
@@ -212,16 +202,11 @@
 	if (error)
 		return;
 
-	for (i = 0; i < PHY_MDM6600_NR_STATUS_LINES; i++) {
-		val |= test_bit(i, values) << i;
-		dev_dbg(ddata->dev, "XXX %s: i: %i values[i]: %i val: %i\n",
-			__func__, i, test_bit(i, values), val);
-	}
-	ddata->status = values[0];
+	ddata->status = values[0] & ((1 << PHY_MDM6600_NR_STATUS_LINES) - 1);
 
 	dev_info(dev, "modem status: %i %s\n",
 		 ddata->status,
-		 phy_mdm6600_status_name[ddata->status & 7]);
+		 phy_mdm6600_status_name[ddata->status]);
 	complete(&ddata->ack);
 }
 
@@ -248,10 +233,24 @@
 {
 	struct phy_mdm6600 *ddata = data;
 	struct gpio_desc *mode_gpio1;
+	int error, wakeup;
 
 	mode_gpio1 = ddata->mode_gpios->desc[PHY_MDM6600_MODE1];
-	dev_dbg(ddata->dev, "OOB wake on mode_gpio1: %i\n",
-		gpiod_get_value(mode_gpio1));
+	wakeup = gpiod_get_value(mode_gpio1);
+	if (!wakeup)
+		return IRQ_NONE;
+
+	dev_dbg(ddata->dev, "OOB wake on mode_gpio1: %i\n", wakeup);
+	error = pm_runtime_get_sync(ddata->dev);
+	if (error < 0) {
+		pm_runtime_put_noidle(ddata->dev);
+
+		return IRQ_NONE;
+	}
+
+	/* Just wake-up and kick the autosuspend timer */
+	pm_runtime_mark_last_busy(ddata->dev);
+	pm_runtime_put_autosuspend(ddata->dev);
 
 	return IRQ_HANDLED;
 }
@@ -445,6 +444,7 @@
 {
 	struct gpio_desc *reset_gpio =
 		ddata->ctrl_gpios[PHY_MDM6600_RESET];
+	int error;
 
 	ddata->enabled = false;
 	phy_mdm6600_cmd(ddata, PHY_MDM6600_CMD_BP_SHUTDOWN_REQ);
@@ -460,6 +460,17 @@
 	} else {
 		dev_err(ddata->dev, "Timed out powering down\n");
 	}
+
+	/*
+	 * Keep reset gpio high with padconf internal pull-up resistor to
+	 * prevent modem from waking up during deeper SoC idle states. The
+	 * gpio bank lines can have glitches if not in the always-on wkup
+	 * domain.
+	 */
+	error = pinctrl_pm_select_sleep_state(ddata->dev);
+	if (error)
+		dev_warn(ddata->dev, "%s: error with sleep_state: %i\n",
+			 __func__, error);
 }
 
 static void phy_mdm6600_deferred_power_on(struct work_struct *work)
@@ -501,8 +512,14 @@
 
 	ddata = container_of(work, struct phy_mdm6600, modem_wake_work.work);
 	phy_mdm6600_wake_modem(ddata);
+
+	/*
+	 * The modem does not always stay awake 1.2 seconds after toggling
+	 * the wake GPIO, and sometimes it idles after about some 600 ms
+	 * making writes time out.
+	 */
 	schedule_delayed_work(&ddata->modem_wake_work,
-			      msecs_to_jiffies(MDM6600_MODEM_IDLE_DELAY_MS));
+			      msecs_to_jiffies(PHY_MDM6600_WAKE_KICK_MS));
 }
 
 static int __maybe_unused phy_mdm6600_runtime_suspend(struct device *dev)
@@ -554,12 +571,6 @@
 	ddata->dev = &pdev->dev;
 	platform_set_drvdata(pdev, ddata);
 
-	/* Active state selected in phy_mdm6600_power_on() */
-	error = pinctrl_pm_select_sleep_state(ddata->dev);
-	if (error)
-		dev_warn(ddata->dev, "%s: error with sleep_state: %i\n",
-			 __func__, error);
-
 	error = phy_mdm6600_init_lines(ddata);
 	if (error)
 		return error;
@@ -610,8 +621,11 @@
 	pm_runtime_put_autosuspend(ddata->dev);
 
 cleanup:
-	if (error < 0)
+	if (error < 0) {
 		phy_mdm6600_device_power_off(ddata);
+		pm_runtime_disable(ddata->dev);
+		pm_runtime_dont_use_autosuspend(ddata->dev);
+	}
 
 	return error;
 }
@@ -621,6 +635,7 @@
 	struct phy_mdm6600 *ddata = platform_get_drvdata(pdev);
 	struct gpio_desc *reset_gpio = ddata->ctrl_gpios[PHY_MDM6600_RESET];
 
+	pm_runtime_get_noresume(ddata->dev);
 	pm_runtime_dont_use_autosuspend(ddata->dev);
 	pm_runtime_put_sync(ddata->dev);
 	pm_runtime_disable(ddata->dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/phy-core-mipi-dphy.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/phy-core-mipi-dphy.c
@@ -66,10 +66,10 @@
 	cfg->hs_trail = max(4 * 8 * ui, 60000 + 4 * 4 * ui);
 
 	cfg->init = 100;
-	cfg->lpx = 60000;
+	cfg->lpx = 50000;
 	cfg->ta_get = 5 * cfg->lpx;
 	cfg->ta_go = 4 * cfg->lpx;
-	cfg->ta_sure = 2 * cfg->lpx;
+	cfg->ta_sure = cfg->lpx;
 	cfg->wakeup = 1000;
 
 	cfg->hs_clk_rate = hs_clk_rate;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/phy-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/phy-core.c
@@ -138,8 +138,10 @@
 			return phy_provider;
 
 		for_each_child_of_node(phy_provider->children, child)
-			if (child == node)
+			if (child == node) {
+				of_node_put(child);
 				return phy_provider;
+			}
 	}
 
 	return ERR_PTR(-EPROBE_DEFER);
@@ -507,8 +509,10 @@
 		return ERR_PTR(-ENODEV);
 
 	/* This phy type handled by the usb-phy subsystem for now */
-	if (of_device_is_compatible(args.np, "usb-nop-xceiv"))
-		return ERR_PTR(-ENODEV);
+	if (of_device_is_compatible(args.np, "usb-nop-xceiv")) {
+		phy = ERR_PTR(-ENODEV);
+		goto out_put_node;
+	}
 
 	mutex_lock(&phy_provider_mutex);
 	phy_provider = of_phy_provider_lookup(args.np);
@@ -530,6 +534,7 @@
 
 out_unlock:
 	mutex_unlock(&phy_provider_mutex);
+out_put_node:
 	of_node_put(args.np);
 
 	return phy;
@@ -601,7 +606,7 @@
 	if (!phy)
 		return;
 
-	r = devres_destroy(dev, devm_phy_release, devm_phy_match, phy);
+	r = devres_release(dev, devm_phy_release, devm_phy_match, phy);
 	dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n");
 }
 EXPORT_SYMBOL_GPL(devm_phy_put);
@@ -953,7 +958,7 @@
 {
 	int r;
 
-	r = devres_destroy(dev, devm_phy_consume, devm_phy_match, phy);
+	r = devres_release(dev, devm_phy_consume, devm_phy_match, phy);
 	dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n");
 }
 EXPORT_SYMBOL_GPL(devm_phy_destroy);
@@ -1089,11 +1094,12 @@
  * of_phy_provider_unregister to unregister the phy provider.
  */
 void devm_of_phy_provider_unregister(struct device *dev,
-	struct phy_provider *phy_provider) {
+				     struct phy_provider *phy_provider)
+{
 	int r;
 
-	r = devres_destroy(dev, devm_phy_provider_release, devm_phy_match,
-		phy_provider);
+	r = devres_release(dev, devm_phy_provider_release, devm_phy_match,
+			   phy_provider);
 	dev_WARN_ONCE(dev, r, "couldn't find PHY provider device resource\n");
 }
 EXPORT_SYMBOL_GPL(devm_of_phy_provider_unregister);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/phy-zynqmp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/phy-zynqmp.c
@@ -0,0 +1,1583 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * phy-zynqmp.c - PHY driver for Xilinx ZynqMP GT.
+ *
+ * Copyright (C) 2015 - 2016 Xilinx Inc.
+ *
+ * Author: Subbaraya Sundeep <sbhatta@xilinx.com>
+ * Author: Anurag Kumar Vulisha <anuragku@xilinx.com>
+ *
+ * This driver is tested for USB and SATA currently.
+ * Other controllers PCIe, Display Port and SGMII should also
+ * work but that is experimental as of now.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/phy/phy.h>
+#include <linux/phy/phy-zynqmp.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <dt-bindings/phy/phy.h>
+#include <linux/soc/xilinx/zynqmp/fw.h>
+#include <linux/firmware/xlnx-zynqmp.h>
+#include <linux/reset.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+
+#define MAX_LANES			4
+
+#define RST_TIMEOUT			1000
+
+#define ICM_CFG0			0x10010
+#define ICM_CFG1			0x10014
+#define ICM_CFG0_L0_MASK		0x07
+#define ICM_CFG0_L1_MASK		0x70
+#define ICM_CFG1_L2_MASK		0x07
+#define ICM_CFG2_L3_MASK		0x70
+
+#define TM_CMN_RST			0x10018
+#define TM_CMN_RST_MASK			0x3
+#define TM_CMN_RST_EN			0x1
+#define TM_CMN_RST_SET			0x2
+
+#define ICM_PROTOCOL_PD			0x0
+#define ICM_PROTOCOL_PCIE		0x1
+#define ICM_PROTOCOL_SATA		0x2
+#define ICM_PROTOCOL_USB		0x3
+#define ICM_PROTOCOL_DP			0x4
+#define ICM_PROTOCOL_SGMII		0x5
+
+#define PLL_REF_SEL0			0x10000
+#define PLL_REF_OFFSET			0x4
+#define PLL_FREQ_MASK			0x1F
+
+#define L0_L0_REF_CLK_SEL		0x2860
+
+#define L0_PLL_STATUS_READ_1		0x23E4
+#define PLL_STATUS_READ_OFFSET		0x4000
+#define PLL_STATUS_LOCKED		0x10
+
+#define L0_PLL_SS_STEP_SIZE_0_LSB	0x2370
+#define L0_PLL_SS_STEP_SIZE_1		0x2374
+#define L0_PLL_SS_STEP_SIZE_2		0x2378
+#define L0_PLL_SS_STEP_SIZE_3_MSB	0x237C
+#define STEP_SIZE_OFFSET		0x4000
+#define STEP_SIZE_0_MASK		0xFF
+#define STEP_SIZE_1_MASK		0xFF
+#define STEP_SIZE_2_MASK		0xFF
+#define STEP_SIZE_3_MASK		0x3
+#define FORCE_STEP_SIZE			0x10
+#define FORCE_STEPS			0x20
+
+#define L0_PLL_SS_STEPS_0_LSB		0x2368
+#define L0_PLL_SS_STEPS_1_MSB		0x236C
+#define STEPS_OFFSET			0x4000
+#define STEPS_0_MASK			0xFF
+#define STEPS_1_MASK			0x07
+
+#define BGCAL_REF_SEL			0x10028
+#define BGCAL_REF_VALUE			0x0C
+
+#define L3_TM_CALIB_DIG19		0xEC4C
+#define L3_TM_CALIB_DIG19_NSW		0x07
+
+#define TM_OVERRIDE_NSW_CODE            0x20
+
+#define L3_CALIB_DONE_STATUS		0xEF14
+#define CALIB_DONE			0x02
+
+#define L0_TXPMA_ST_3			0x0B0C
+#define DN_CALIB_CODE			0x3F
+#define DN_CALIB_SHIFT			3
+
+#define L3_TM_CALIB_DIG18		0xEC48
+#define L3_TM_CALIB_DIG18_NSW		0xE0
+#define NSW_SHIFT			5
+#define NSW_PIPE_SHIFT			4
+
+#define L0_TM_PLL_DIG_37		0x2094
+#define TM_PLL_DIG_37_OFFSET		0x4000
+#define TM_COARSE_CODE_LIMIT		0x10
+
+#define L0_TM_DIG_6			0x106C
+#define TM_DIG_6_OFFSET			0x4000
+#define TM_DISABLE_DESCRAMBLE_DECODER	0x0F
+
+#define L0_TX_DIG_61			0x00F4
+#define TX_DIG_61_OFFSET		0x4000
+#define TM_DISABLE_SCRAMBLE_ENCODER	0x0F
+
+#define L0_TX_ANA_TM_18			0x0048
+#define TX_ANA_TM_18_OFFSET		0x4000
+
+#define L0_TX_ANA_TM_118		0x01D8
+#define TX_ANA_TM_118_OFFSET		0x4000
+#define L0_TX_ANA_TM_118_FORCE_17_0	BIT(0)
+
+#define L0_TXPMD_TM_45			0x0CB4
+#define TXPMD_TM_45_OFFSET		0x4000
+#define L0_TXPMD_TM_45_OVER_DP_MAIN	BIT(0)
+#define L0_TXPMD_TM_45_ENABLE_DP_MAIN	BIT(1)
+#define L0_TXPMD_TM_45_OVER_DP_POST1	BIT(2)
+#define L0_TXPMD_TM_45_ENABLE_DP_POST1	BIT(3)
+#define L0_TXPMD_TM_45_OVER_DP_POST2	BIT(4)
+#define L0_TXPMD_TM_45_ENABLE_DP_POST2	BIT(5)
+
+#define L0_TXPMD_TM_48			0x0CC0
+#define TXPMD_TM_48_OFFSET		0x4000
+
+#define TX_PROT_BUS_WIDTH		0x10040
+#define RX_PROT_BUS_WIDTH		0x10044
+
+#define PROT_BUS_WIDTH_SHIFT		2
+#define PROT_BUS_WIDTH_10		0x0
+#define PROT_BUS_WIDTH_20		0x1
+#define PROT_BUS_WIDTH_40		0x2
+
+#define LANE_CLK_SHARE_MASK		0x8F
+
+#define SATA_CONTROL_OFFSET		0x0100
+
+#define CONTROLLERS_PER_LANE		5
+
+#define PIPE_CLK_OFFSET			0x7c
+#define PIPE_CLK_ON			1
+#define PIPE_CLK_OFF			0
+#define PIPE_POWER_OFFSET		0x80
+#define PIPE_POWER_ON			1
+#define PIPE_POWER_OFF			0
+
+#define XPSGTR_TYPE_USB0	0 /* USB controller 0 */
+#define XPSGTR_TYPE_USB1	1 /* USB controller 1 */
+#define XPSGTR_TYPE_SATA_0	2 /* SATA controller lane 0 */
+#define XPSGTR_TYPE_SATA_1	3 /* SATA controller lane 1 */
+#define XPSGTR_TYPE_PCIE_0	4 /* PCIe controller lane 0 */
+#define XPSGTR_TYPE_PCIE_1	5 /* PCIe controller lane 1 */
+#define XPSGTR_TYPE_PCIE_2	6 /* PCIe controller lane 2 */
+#define XPSGTR_TYPE_PCIE_3	7 /* PCIe controller lane 3 */
+#define XPSGTR_TYPE_DP_0	8 /* Display Port controller lane 0 */
+#define XPSGTR_TYPE_DP_1	9 /* Display Port controller lane 1 */
+#define XPSGTR_TYPE_SGMII0	10 /* Ethernet SGMII controller 0 */
+#define XPSGTR_TYPE_SGMII1	11 /* Ethernet SGMII controller 1 */
+#define XPSGTR_TYPE_SGMII2	12 /* Ethernet SGMII controller 2 */
+#define XPSGTR_TYPE_SGMII3	13 /* Ethernet SGMII controller 3 */
+
+/*
+ * This table holds the valid combinations of controllers and
+ * lanes(Interconnect Matrix).
+ */
+static unsigned int icm_matrix[][CONTROLLERS_PER_LANE] = {
+	{ XPSGTR_TYPE_PCIE_0, XPSGTR_TYPE_SATA_0, XPSGTR_TYPE_USB0,
+		XPSGTR_TYPE_DP_1, XPSGTR_TYPE_SGMII0 },
+	{ XPSGTR_TYPE_PCIE_1, XPSGTR_TYPE_SATA_1, XPSGTR_TYPE_USB0,
+		XPSGTR_TYPE_DP_0, XPSGTR_TYPE_SGMII1 },
+	{ XPSGTR_TYPE_PCIE_2, XPSGTR_TYPE_SATA_0, XPSGTR_TYPE_USB0,
+		XPSGTR_TYPE_DP_1, XPSGTR_TYPE_SGMII2 },
+	{ XPSGTR_TYPE_PCIE_3, XPSGTR_TYPE_SATA_1, XPSGTR_TYPE_USB1,
+		XPSGTR_TYPE_DP_0, XPSGTR_TYPE_SGMII3 }
+};
+
+/* Allowed PLL reference clock frequencies */
+enum pll_frequencies {
+	REF_19_2M = 0,
+	REF_20M,
+	REF_24M,
+	REF_26M,
+	REF_27M,
+	REF_38_4M,
+	REF_40M,
+	REF_52M,
+	REF_100M,
+	REF_108M,
+	REF_125M,
+	REF_135M,
+	REF_150M,
+};
+
+/**
+ * struct xpsgtr_phy - representation of a lane
+ * @phy: pointer to the kernel PHY device
+ * @type: controller which uses this lane
+ * @lane: lane number
+ * @protocol: protocol in which the lane operates
+ * @ref_clk: enum of allowed ref clock rates for this lane PLL
+ * @pll_lock: PLL status
+ * @skip_phy_init: skip phy_init() if true
+ * @data: pointer to hold private data
+ * @refclk_rate: PLL reference clock frequency
+ * @share_laneclk: lane number of the clock to be shared
+ */
+struct xpsgtr_phy {
+	struct phy *phy;
+	u8 type;
+	u8 lane;
+	u8 protocol;
+	enum pll_frequencies ref_clk;
+	bool pll_lock;
+	bool skip_phy_init;
+	void *data;
+	u32 refclk_rate;
+	u32 share_laneclk;
+};
+
+/**
+ * struct xpsgtr_ssc - structure to hold SSC settings for a lane
+ * @refclk_rate: PLL reference clock frequency
+ * @pll_ref_clk: value to be written to register for corresponding ref clk rate
+ * @steps: number of steps of SSC (Spread Spectrum Clock)
+ * @step_size: step size of each step
+ */
+struct xpsgtr_ssc {
+	u32 refclk_rate;
+	u8  pll_ref_clk;
+	u32 steps;
+	u32 step_size;
+};
+
+/* lookup table to hold all settings needed for a ref clock frequency */
+static struct xpsgtr_ssc ssc_lookup[] = {
+	{19200000, 0x05, 608, 264020},
+	{20000000, 0x06, 634, 243454},
+	{24000000, 0x07, 760, 168973},
+	{26000000, 0x08, 824, 143860},
+	{27000000, 0x09, 856, 86551},
+	{38400000, 0x0A, 1218, 65896},
+	{40000000, 0x0B, 634, 243454},
+	{52000000, 0x0C, 824, 143860},
+	{100000000, 0x0D, 1058, 87533},
+	{108000000, 0x0E, 856, 86551},
+	{125000000, 0x0F, 992, 119497},
+	{135000000, 0x10, 1070, 55393},
+	{150000000, 0x11, 792, 187091}
+};
+
+/**
+ * struct xpsgtr_dev - representation of a ZynMP GT device
+ * @dev: pointer to device
+ * @serdes: serdes base address
+ * @siou: siou base address
+ * @gtr_mutex: mutex for locking
+ * @phys: pointer to all the lanes
+ * @tx_term_fix: fix for GT issue
+ * @saved_icm_cfg0: stored value of ICM CFG0 register
+ * @saved_icm_cfg1: stored value of ICM CFG1 register
+ * @sata_rst: a reset control for SATA
+ * @dp_rst: a reset control for DP
+ * @usb0_crst: a reset control for usb0 core
+ * @usb1_crst: a reset control for usb1 core
+ * @usb0_hibrst: a reset control for usb0 hibernation module
+ * @usb1_hibrst: a reset control for usb1 hibernation module
+ * @usb0_apbrst: a reset control for usb0 apb bus
+ * @usb1_apbrst: a reset control for usb1 apb bus
+ * @gem0_rst: a reset control for gem0
+ * @gem1_rst: a reset control for gem1
+ * @gem2_rst: a reset control for gem2
+ * @gem3_rst: a reset control for gem3
+ */
+struct xpsgtr_dev {
+	struct device *dev;
+	void __iomem *serdes;
+	void __iomem *siou;
+	struct mutex gtr_mutex; /* mutex for locking */
+	struct xpsgtr_phy **phys;
+	bool tx_term_fix;
+	unsigned int saved_icm_cfg0;
+	unsigned int saved_icm_cfg1;
+	struct reset_control *sata_rst;
+	struct reset_control *dp_rst;
+	struct reset_control *usb0_crst;
+	struct reset_control *usb1_crst;
+	struct reset_control *usb0_hibrst;
+	struct reset_control *usb1_hibrst;
+	struct reset_control *usb0_apbrst;
+	struct reset_control *usb1_apbrst;
+	struct reset_control *gem0_rst;
+	struct reset_control *gem1_rst;
+	struct reset_control *gem2_rst;
+	struct reset_control *gem3_rst;
+};
+
+static const struct zynqmp_eemi_ops *eemi_ops;
+
+int xpsgtr_override_deemph(struct phy *phy, u8 plvl, u8 vlvl)
+{
+	struct xpsgtr_phy *gtr_phy = phy_get_drvdata(phy);
+	struct xpsgtr_dev *gtr_dev = gtr_phy->data;
+	static u8 pe[4][4] = { { 0x2, 0x2, 0x2, 0x2 },
+			       { 0x1, 0x1, 0x1, 0xff },
+			       { 0x0, 0x0, 0xff, 0xff },
+			       { 0xff, 0xff, 0xff, 0xff } };
+
+	writel(pe[plvl][vlvl],
+	       gtr_dev->serdes + gtr_phy->lane * TX_ANA_TM_18_OFFSET +
+	       L0_TX_ANA_TM_18);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(xpsgtr_override_deemph);
+
+int xpsgtr_margining_factor(struct phy *phy, u8 plvl, u8 vlvl)
+{
+	struct xpsgtr_phy *gtr_phy = phy_get_drvdata(phy);
+	struct xpsgtr_dev *gtr_dev = gtr_phy->data;
+	static u8 vs[4][4] = { { 0x2a, 0x27, 0x24, 0x20 },
+			       { 0x27, 0x23, 0x20, 0xff },
+			       { 0x24, 0x20, 0xff, 0xff },
+			       { 0xff, 0xff, 0xff, 0xff } };
+
+	writel(vs[plvl][vlvl],
+	       gtr_dev->serdes + gtr_phy->lane * TXPMD_TM_48_OFFSET +
+	       L0_TXPMD_TM_48);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(xpsgtr_margining_factor);
+
+/**
+ * xpsgtr_configure_pll - configures SSC settings for a lane
+ * @gtr_phy: pointer to lane
+ */
+static void xpsgtr_configure_pll(struct xpsgtr_phy *gtr_phy)
+{
+	struct xpsgtr_dev *gtr_dev = gtr_phy->data;
+	u32 reg;
+	u32 offset;
+	u32 steps;
+	u32 size;
+	u8 pll_ref_clk;
+
+	steps = ssc_lookup[gtr_phy->ref_clk].steps;
+	size = ssc_lookup[gtr_phy->ref_clk].step_size;
+	pll_ref_clk = ssc_lookup[gtr_phy->ref_clk].pll_ref_clk;
+
+	offset = gtr_phy->lane * PLL_REF_OFFSET + PLL_REF_SEL0;
+	reg = readl(gtr_dev->serdes + offset);
+	reg = (reg & ~PLL_FREQ_MASK) | pll_ref_clk;
+	writel(reg, gtr_dev->serdes + offset);
+
+	/* Enable lane clock sharing, if required */
+	if (gtr_phy->share_laneclk != gtr_phy->lane) {
+		/* Lane3 Ref Clock Selection Register */
+		offset = gtr_phy->lane * PLL_REF_OFFSET + L0_L0_REF_CLK_SEL;
+		reg = readl(gtr_dev->serdes + offset);
+		reg = (reg & ~LANE_CLK_SHARE_MASK) |
+				(1 << gtr_phy->share_laneclk);
+		writel(reg, gtr_dev->serdes + offset);
+	}
+
+	/* SSC step size [7:0] */
+	offset = gtr_phy->lane * STEP_SIZE_OFFSET + L0_PLL_SS_STEP_SIZE_0_LSB;
+	reg = readl(gtr_dev->serdes + offset);
+	reg = (reg & ~STEP_SIZE_0_MASK) |
+		(size & STEP_SIZE_0_MASK);
+	writel(reg, gtr_dev->serdes + offset);
+
+	/* SSC step size [15:8] */
+	size = size >> 8;
+	offset = gtr_phy->lane * STEP_SIZE_OFFSET + L0_PLL_SS_STEP_SIZE_1;
+	reg = readl(gtr_dev->serdes + offset);
+	reg = (reg & ~STEP_SIZE_1_MASK) |
+		(size & STEP_SIZE_1_MASK);
+	writel(reg, gtr_dev->serdes + offset);
+
+	/* SSC step size [23:16] */
+	size = size >> 8;
+	offset = gtr_phy->lane * STEP_SIZE_OFFSET + L0_PLL_SS_STEP_SIZE_2;
+	reg = readl(gtr_dev->serdes + offset);
+	reg = (reg & ~STEP_SIZE_2_MASK) |
+		(size & STEP_SIZE_2_MASK);
+	writel(reg, gtr_dev->serdes + offset);
+
+	/* SSC steps [7:0] */
+	offset = gtr_phy->lane * STEPS_OFFSET + L0_PLL_SS_STEPS_0_LSB;
+	reg = readl(gtr_dev->serdes + offset);
+	reg = (reg & ~STEPS_0_MASK) |
+		(steps & STEPS_0_MASK);
+	writel(reg, gtr_dev->serdes + offset);
+
+	/* SSC steps [10:8] */
+	steps = steps >> 8;
+	offset = gtr_phy->lane * STEPS_OFFSET + L0_PLL_SS_STEPS_1_MSB;
+	reg = readl(gtr_dev->serdes + offset);
+	reg = (reg & ~STEPS_1_MASK) |
+		(steps & STEPS_1_MASK);
+	writel(reg, gtr_dev->serdes + offset);
+
+	/* SSC step size [24:25] */
+	size = size >> 8;
+	offset = gtr_phy->lane * STEP_SIZE_OFFSET + L0_PLL_SS_STEP_SIZE_3_MSB;
+	reg = readl(gtr_dev->serdes + offset);
+	reg = (reg & ~STEP_SIZE_3_MASK) |
+		(size & STEP_SIZE_3_MASK);
+	reg |= FORCE_STEP_SIZE | FORCE_STEPS;
+	writel(reg, gtr_dev->serdes + offset);
+}
+
+/**
+ * xpsgtr_lane_setprotocol - sets required protocol in ICM registers
+ * @gtr_phy: pointer to lane
+ */
+static void xpsgtr_lane_setprotocol(struct xpsgtr_phy *gtr_phy)
+{
+	struct xpsgtr_dev *gtr_dev = gtr_phy->data;
+	u32 reg;
+	u8 protocol = gtr_phy->protocol;
+
+	switch (gtr_phy->lane) {
+	case 0:
+		reg = readl(gtr_dev->serdes + ICM_CFG0);
+		reg = (reg & ~ICM_CFG0_L0_MASK) | protocol;
+		writel(reg, gtr_dev->serdes + ICM_CFG0);
+		break;
+	case 1:
+		reg = readl(gtr_dev->serdes + ICM_CFG0);
+		reg = (reg & ~ICM_CFG0_L1_MASK) | (protocol << 4);
+		writel(reg, gtr_dev->serdes + ICM_CFG0);
+		break;
+	case 2:
+		reg = readl(gtr_dev->serdes + ICM_CFG1);
+		reg = (reg & ~ICM_CFG0_L0_MASK) | protocol;
+		writel(reg, gtr_dev->serdes + ICM_CFG1);
+		break;
+	case 3:
+		reg = readl(gtr_dev->serdes + ICM_CFG1);
+		reg = (reg & ~ICM_CFG0_L1_MASK) | (protocol << 4);
+		writel(reg, gtr_dev->serdes + ICM_CFG1);
+		break;
+	default:
+		/* We already checked 0 <= lane <= 3 */
+		break;
+	}
+}
+
+/**
+ * xpsgtr_get_ssc - gets the required ssc settings based on clk rate
+ * @gtr_phy: pointer to lane
+ *
+ * Return: 0 on success or error on failure
+ */
+static int xpsgtr_get_ssc(struct xpsgtr_phy *gtr_phy)
+{
+	u32 i;
+
+	/*
+	 * Assign the required spread spectrum(SSC) settings
+	 * from lane refernce clk rate
+	 */
+	for (i = 0 ; i < ARRAY_SIZE(ssc_lookup); i++) {
+		if (gtr_phy->refclk_rate == ssc_lookup[i].refclk_rate) {
+			gtr_phy->ref_clk = i;
+			return 0;
+		}
+	}
+
+	/* Did not get valid ssc settings*/
+	return -EINVAL;
+}
+
+/**
+ * xpsgtr_configure_lane - configures SSC settings for a lane
+ * @gtr_phy: pointer to lane
+ *
+ * Return: 0 on success or error on failure
+ */
+static int xpsgtr_configure_lane(struct xpsgtr_phy *gtr_phy)
+{
+	switch (gtr_phy->type) {
+	case XPSGTR_TYPE_USB0:
+	case XPSGTR_TYPE_USB1:
+		gtr_phy->protocol = ICM_PROTOCOL_USB;
+		break;
+	case XPSGTR_TYPE_SATA_0:
+	case XPSGTR_TYPE_SATA_1:
+		gtr_phy->protocol = ICM_PROTOCOL_SATA;
+		break;
+	case XPSGTR_TYPE_DP_0:
+	case XPSGTR_TYPE_DP_1:
+		gtr_phy->protocol = ICM_PROTOCOL_DP;
+		break;
+	case XPSGTR_TYPE_PCIE_0:
+	case XPSGTR_TYPE_PCIE_1:
+	case XPSGTR_TYPE_PCIE_2:
+	case XPSGTR_TYPE_PCIE_3:
+		gtr_phy->protocol = ICM_PROTOCOL_PCIE;
+		break;
+	case XPSGTR_TYPE_SGMII0:
+	case XPSGTR_TYPE_SGMII1:
+	case XPSGTR_TYPE_SGMII2:
+	case XPSGTR_TYPE_SGMII3:
+		gtr_phy->protocol = ICM_PROTOCOL_SGMII;
+		break;
+	default:
+		gtr_phy->protocol = ICM_PROTOCOL_PD;
+		break;
+	}
+
+	/* Get SSC settinsg for refernce clk rate */
+	if (xpsgtr_get_ssc(gtr_phy) < 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
+ * xpsgtr_config_usbpipe - configures the PIPE3 signals for USB
+ * @gtr_phy: pointer to gtr phy device
+ */
+static void xpsgtr_config_usbpipe(struct xpsgtr_phy *gtr_phy)
+{
+	struct phy *phy = gtr_phy->phy;
+	struct xpsgtr_dev *gtr_dev = gtr_phy->data;
+	void __iomem *regs = dev_get_platdata(&phy->dev);
+
+	if (regs) {
+		/* Set PIPE power present signal */
+		writel(PIPE_POWER_ON, regs + PIPE_POWER_OFFSET);
+		/* Clear PIPE CLK signal */
+		writel(PIPE_CLK_OFF, regs + PIPE_CLK_OFFSET);
+	} else {
+		dev_info(gtr_dev->dev,
+			 "%s: No valid Platform_data found\n", __func__);
+	}
+}
+
+/**
+ * xpsgtr_reset_assert - asserts reset using reset framework
+ * @rstc: pointer to reset_control
+ *
+ * Return: 0 on success or error on failure
+ */
+static int xpsgtr_reset_assert(struct reset_control *rstc)
+{
+	unsigned long loop_time = msecs_to_jiffies(RST_TIMEOUT);
+	unsigned long timeout;
+
+	reset_control_assert(rstc);
+
+	/* wait until reset is asserted or timeout */
+	timeout = jiffies + loop_time;
+
+	while (!time_after_eq(jiffies, timeout)) {
+		if (reset_control_status(rstc) > 0)
+			return 0;
+
+		cpu_relax();
+	}
+
+	return -ETIMEDOUT;
+}
+
+/**
+ * xpsgtr_reset_release - de-asserts reset using reset framework
+ * @rstc: pointer to reset_control
+ *
+ * Return: 0 on success or error on failure
+ */
+static int xpsgtr_reset_release(struct reset_control *rstc)
+{
+	unsigned long loop_time = msecs_to_jiffies(RST_TIMEOUT);
+	unsigned long timeout;
+
+	reset_control_deassert(rstc);
+
+	/* wait until reset is de-asserted or timeout */
+	timeout = jiffies + loop_time;
+	while (!time_after_eq(jiffies, timeout)) {
+		if (!reset_control_status(rstc))
+			return 0;
+
+		cpu_relax();
+	}
+
+	return -ETIMEDOUT;
+}
+
+/**
+ * xpsgtr_controller_reset - puts controller in reset
+ * @gtr_phy: pointer to lane
+ *
+ * Return: 0 on success or error on failure
+ */
+static int xpsgtr_controller_reset(struct xpsgtr_phy *gtr_phy)
+{
+	struct xpsgtr_dev *gtr_dev = gtr_phy->data;
+	int ret;
+
+	switch (gtr_phy->type) {
+	case XPSGTR_TYPE_USB0:
+		ret = xpsgtr_reset_assert(gtr_dev->usb0_crst);
+		ret = xpsgtr_reset_assert(gtr_dev->usb0_hibrst);
+		ret = xpsgtr_reset_assert(gtr_dev->usb0_apbrst);
+		break;
+	case XPSGTR_TYPE_USB1:
+		ret = xpsgtr_reset_assert(gtr_dev->usb1_crst);
+		ret = xpsgtr_reset_assert(gtr_dev->usb1_hibrst);
+		ret = xpsgtr_reset_assert(gtr_dev->usb1_apbrst);
+		break;
+	case XPSGTR_TYPE_SATA_0:
+	case XPSGTR_TYPE_SATA_1:
+		ret = xpsgtr_reset_assert(gtr_dev->sata_rst);
+		break;
+	case XPSGTR_TYPE_DP_0:
+	case XPSGTR_TYPE_DP_1:
+		ret = xpsgtr_reset_assert(gtr_dev->dp_rst);
+		break;
+	case XPSGTR_TYPE_SGMII0:
+		ret = xpsgtr_reset_assert(gtr_dev->gem0_rst);
+		break;
+	case XPSGTR_TYPE_SGMII1:
+		ret = xpsgtr_reset_assert(gtr_dev->gem1_rst);
+		break;
+	case XPSGTR_TYPE_SGMII2:
+		ret = xpsgtr_reset_assert(gtr_dev->gem2_rst);
+		break;
+	case XPSGTR_TYPE_SGMII3:
+		ret = xpsgtr_reset_assert(gtr_dev->gem3_rst);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * xpsgtr_controller_release_reset - releases controller from reset
+ * @gtr_phy: pointer to lane
+ *
+ * Return: 0 on success or error on failure
+ */
+static int xpsgtr_controller_release_reset(struct xpsgtr_phy *gtr_phy)
+{
+	struct xpsgtr_dev *gtr_dev = gtr_phy->data;
+	int ret;
+
+	switch (gtr_phy->type) {
+	case XPSGTR_TYPE_USB0:
+		xpsgtr_reset_release(gtr_dev->usb0_apbrst);
+
+		/* Config PIPE3 signals after releasing APB reset */
+		xpsgtr_config_usbpipe(gtr_phy);
+
+		ret = xpsgtr_reset_release(gtr_dev->usb0_crst);
+		ret = xpsgtr_reset_release(gtr_dev->usb0_hibrst);
+		break;
+	case XPSGTR_TYPE_USB1:
+		xpsgtr_reset_release(gtr_dev->usb1_apbrst);
+
+		/* Config PIPE3 signals after releasing APB reset */
+		xpsgtr_config_usbpipe(gtr_phy);
+
+		ret = xpsgtr_reset_release(gtr_dev->usb1_crst);
+		ret = xpsgtr_reset_release(gtr_dev->usb1_hibrst);
+		break;
+	case XPSGTR_TYPE_SATA_0:
+	case XPSGTR_TYPE_SATA_1:
+		ret = xpsgtr_reset_release(gtr_dev->sata_rst);
+		break;
+	case XPSGTR_TYPE_DP_0:
+	case XPSGTR_TYPE_DP_1:
+		ret = xpsgtr_reset_release(gtr_dev->dp_rst);
+		break;
+	case XPSGTR_TYPE_SGMII0:
+		ret = xpsgtr_reset_release(gtr_dev->gem0_rst);
+		break;
+	case XPSGTR_TYPE_SGMII1:
+		ret = xpsgtr_reset_release(gtr_dev->gem1_rst);
+		break;
+	case XPSGTR_TYPE_SGMII2:
+		ret = xpsgtr_reset_release(gtr_dev->gem2_rst);
+		break;
+	case XPSGTR_TYPE_SGMII3:
+		ret = xpsgtr_reset_release(gtr_dev->gem3_rst);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * xpsgtr_usb_rst_assert - assert USB core reset
+ * @phy: pointer to phy
+ *
+ * Return: 0 on success or error on failure
+ */
+int xpsgtr_usb_crst_assert(struct phy *phy)
+{
+	struct xpsgtr_phy *gtr_phy = phy_get_drvdata(phy);
+	struct xpsgtr_dev *gtr_dev = gtr_phy->data;
+	int ret;
+
+	switch (gtr_phy->type) {
+	case XPSGTR_TYPE_USB0:
+		ret = xpsgtr_reset_assert(gtr_dev->usb0_crst);
+		break;
+	case XPSGTR_TYPE_USB1:
+		ret = xpsgtr_reset_assert(gtr_dev->usb1_crst);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(xpsgtr_usb_crst_assert);
+
+/**
+ * xpsgtr_usb_rst_release - release USB core reset
+ * @phy: pointer to phy
+ *
+ * Return: 0 on success or error on failure
+ */
+int xpsgtr_usb_crst_release(struct phy *phy)
+{
+	struct xpsgtr_phy *gtr_phy = phy_get_drvdata(phy);
+	struct xpsgtr_dev *gtr_dev = gtr_phy->data;
+	int ret;
+
+	switch (gtr_phy->type) {
+	case XPSGTR_TYPE_USB0:
+		ret = xpsgtr_reset_release(gtr_dev->usb0_crst);
+		break;
+	case XPSGTR_TYPE_USB1:
+		ret = xpsgtr_reset_release(gtr_dev->usb1_crst);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(xpsgtr_usb_crst_release);
+
+int xpsgtr_wait_pll_lock(struct phy *phy)
+{
+	struct xpsgtr_phy *gtr_phy = phy_get_drvdata(phy);
+	struct xpsgtr_dev *gtr_dev = gtr_phy->data;
+	u32 offset, reg;
+	u32 timeout = 1000;
+	int ret = 0;
+
+	/* Check pll is locked */
+	offset = gtr_phy->lane * PLL_STATUS_READ_OFFSET + L0_PLL_STATUS_READ_1;
+	dev_dbg(gtr_dev->dev, "Waiting for PLL lock...\n");
+
+	do {
+		reg = readl(gtr_dev->serdes + offset);
+		if ((reg & PLL_STATUS_LOCKED) == PLL_STATUS_LOCKED)
+			break;
+
+		if (!--timeout) {
+			dev_err(gtr_dev->dev, "PLL lock time out\n");
+			ret = -ETIMEDOUT;
+			break;
+		}
+		udelay(1);
+	} while (1);
+
+	if (ret == 0)
+		gtr_phy->pll_lock = true;
+
+	dev_info(gtr_dev->dev, "Lane:%d type:%d protocol:%d pll_locked:%s\n",
+		 gtr_phy->lane, gtr_phy->type, gtr_phy->protocol,
+		 gtr_phy->pll_lock ? "yes" : "no");
+	return ret;
+}
+EXPORT_SYMBOL_GPL(xpsgtr_wait_pll_lock);
+
+/**
+ * xpsgtr_set_txwidth - This function sets the tx bus width of the lane
+ * @gtr_phy: pointer to lane
+ * @width: tx bus width size
+ */
+static void xpsgtr_set_txwidth(struct xpsgtr_phy *gtr_phy, u32 width)
+{
+	struct xpsgtr_dev *gtr_dev = gtr_phy->data;
+
+	writel(gtr_phy->lane * PROT_BUS_WIDTH_SHIFT >> width,
+	       gtr_dev->serdes + TX_PROT_BUS_WIDTH);
+}
+
+/**
+ * xpsgtr_set_rxwidth - This function sets the rx bus width of the lane
+ * @gtr_phy: pointer to lane
+ * @width: rx bus width size
+ */
+static void xpsgtr_set_rxwidth(struct xpsgtr_phy *gtr_phy, u32 width)
+{
+	struct xpsgtr_dev *gtr_dev = gtr_phy->data;
+
+	writel(gtr_phy->lane * PROT_BUS_WIDTH_SHIFT >> width,
+	       gtr_dev->serdes + RX_PROT_BUS_WIDTH);
+}
+
+/**
+ * xpsgtr_bypass_scramenc - This bypasses scrambler and 8b/10b encoder feature
+ * @gtr_phy: pointer to lane
+ */
+static void xpsgtr_bypass_scramenc(struct xpsgtr_phy *gtr_phy)
+{
+	u32 offset;
+	struct xpsgtr_dev *gtr_dev = gtr_phy->data;
+
+	/* bypass Scrambler and 8b/10b Encoder */
+	offset = gtr_phy->lane * TX_DIG_61_OFFSET + L0_TX_DIG_61;
+	writel(TM_DISABLE_SCRAMBLE_ENCODER, gtr_dev->serdes + offset);
+}
+
+/**
+ * xpsgtr_bypass_descramdec - bypasses descrambler and 8b/10b encoder feature
+ * @gtr_phy: pointer to lane
+ */
+static void xpsgtr_bypass_descramdec(struct xpsgtr_phy *gtr_phy)
+{
+	u32 offset;
+	struct xpsgtr_dev *gtr_dev = gtr_phy->data;
+
+	/* bypass Descrambler and 8b/10b decoder */
+	offset = gtr_phy->lane * TM_DIG_6_OFFSET + L0_TM_DIG_6;
+	writel(TM_DISABLE_DESCRAMBLE_DECODER, gtr_dev->serdes + offset);
+}
+
+/**
+ * xpsgtr_misc_sgmii - miscellaneous settings for SGMII
+ * @gtr_phy: pointer to lane
+ */
+static void xpsgtr_misc_sgmii(struct xpsgtr_phy *gtr_phy)
+{
+	/* Set SGMII protocol tx bus width 10 bits */
+	xpsgtr_set_txwidth(gtr_phy, PROT_BUS_WIDTH_10);
+
+	/* Set SGMII protocol rx bus width 10 bits */
+	xpsgtr_set_rxwidth(gtr_phy, PROT_BUS_WIDTH_10);
+
+	/* bypass Descrambler and 8b/10b decoder */
+	xpsgtr_bypass_descramdec(gtr_phy);
+
+	/* bypass Scrambler and 8b/10b Encoder */
+	xpsgtr_bypass_scramenc(gtr_phy);
+}
+
+/**
+ * xpsgtr_misc_sata - miscellaneous settings for SATA
+ * @gtr_phy: pointer to lane
+ */
+static void xpsgtr_misc_sata(struct xpsgtr_phy *gtr_phy)
+{
+	struct xpsgtr_dev *gtr_dev = gtr_phy->data;
+
+	/* bypass Descrambler and 8b/10b decoder */
+	xpsgtr_bypass_descramdec(gtr_phy);
+
+	/* bypass Scrambler and 8b/10b Encoder */
+	xpsgtr_bypass_scramenc(gtr_phy);
+
+	writel(gtr_phy->lane, gtr_dev->siou + SATA_CONTROL_OFFSET);
+}
+
+/**
+ * xpsgtr_ulpi_reset - This function perform's ULPI reset sequence.
+ * @gtr_phy: pointer to lane
+ *
+ * Return: 0 on success, -EINVAL on non existing USB type or error from
+ * communication with firmware
+ */
+static int xpsgtr_ulpi_reset(struct xpsgtr_phy *gtr_phy)
+{
+	u32 node_id;
+	int ret = 0;
+	struct xpsgtr_dev *gtr_dev = gtr_phy->data;
+
+	if (!eemi_ops->ioctl)
+		return -ENOTSUPP;
+
+	switch (gtr_phy->type) {
+	case XPSGTR_TYPE_USB0:
+		node_id = NODE_USB_0;
+		break;
+	case XPSGTR_TYPE_USB1:
+		node_id = NODE_USB_1;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = eemi_ops->ioctl(node_id, IOCTL_ULPI_RESET, 0, 0, NULL);
+	if (ret < 0)
+		dev_err(gtr_dev->dev, "failed to perform ULPI reset\n");
+
+	return ret;
+}
+
+/**
+ * xpsgtr_set_sgmii_pcs - This function sets the sgmii mode for GEM.
+ * @gtr_phy: pointer to lane
+ *
+ * Return: 0 on success, -EINVAL on non existing SGMII type or error from
+ * communication with firmware
+ */
+static int xpsgtr_set_sgmii_pcs(struct xpsgtr_phy *gtr_phy)
+{
+	u32 node_id;
+	int ret = 0;
+	struct xpsgtr_dev *gtr_dev = gtr_phy->data;
+
+	if (!eemi_ops->ioctl)
+		return -ENOTSUPP;
+
+	/* Set the PCS signal detect to 1 */
+	switch (gtr_phy->type) {
+	case XPSGTR_TYPE_SGMII0:
+		node_id = NODE_ETH_0;
+		break;
+	case XPSGTR_TYPE_SGMII1:
+		node_id = NODE_ETH_1;
+		break;
+	case XPSGTR_TYPE_SGMII2:
+		node_id = NODE_ETH_2;
+		break;
+	case XPSGTR_TYPE_SGMII3:
+		node_id = NODE_ETH_3;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = eemi_ops->ioctl(node_id, IOCTL_SET_SGMII_MODE,
+			     PM_SGMII_ENABLE, 0, NULL);
+	if (ret < 0) {
+		dev_err(gtr_dev->dev, "failed to set GEM to SGMII mode\n");
+		return ret;
+	}
+
+	return ret;
+}
+
+/**
+ * xpsgtr_phyinit_required - check if phy_init for the lane can be skipped
+ * @gtr_phy: pointer to the phy lane
+ *
+ * Return: true if phy_init can be skipped or false
+ */
+static bool xpsgtr_phyinit_required(struct xpsgtr_phy *gtr_phy)
+{
+	/*
+	 * As USB may save the snapshot of the states during hibernation, doing
+	 * phy_init() will put the USB controller into reset, resulting in the
+	 * losing of the saved snapshot. So try to avoid phy_init() for USB
+	 * except when gtr_phy->skip_phy_init is false (this happens when FPD is
+	 * shutdown during suspend or when gt lane is changed from current one)
+	 */
+	if (gtr_phy->protocol == ICM_PROTOCOL_USB && gtr_phy->skip_phy_init)
+		return true;
+	else
+		return false;
+}
+
+/**
+ * xpsgtr_phy_init - initializes a lane
+ * @phy: pointer to kernel PHY device
+ *
+ * Return: 0 on success or error on failure
+ */
+static int xpsgtr_phy_init(struct phy *phy)
+{
+	struct xpsgtr_phy *gtr_phy = phy_get_drvdata(phy);
+	struct xpsgtr_dev *gtr_dev = gtr_phy->data;
+	int ret = 0;
+	u32 offset;
+	u32 reg;
+	u32 nsw;
+	u32 timeout = 500;
+
+	mutex_lock(&gtr_dev->gtr_mutex);
+
+	/* Check if phy_init() is required  */
+	if (xpsgtr_phyinit_required(gtr_phy))
+		goto out;
+
+	/* Put controller in reset */
+	ret = xpsgtr_controller_reset(gtr_phy);
+	if (ret != 0) {
+		dev_err(gtr_dev->dev, "Failed to assert reset\n");
+		goto out;
+	}
+
+	/*
+	 * There is a functional issue in the GT. The TX termination resistance
+	 * can be out of spec due to a bug in the calibration logic. Below is
+	 * the workaround to fix it. This below is required for XCZU9EG silicon.
+	 */
+	if (gtr_dev->tx_term_fix) {
+		/* Enabling Test Mode control for CMN Rest */
+		reg = readl(gtr_dev->serdes + TM_CMN_RST);
+		reg = (reg & ~TM_CMN_RST_MASK) | TM_CMN_RST_SET;
+		writel(reg, gtr_dev->serdes + TM_CMN_RST);
+
+		/* Set Test Mode reset */
+		reg = readl(gtr_dev->serdes + TM_CMN_RST);
+		reg = (reg & ~TM_CMN_RST_MASK) | TM_CMN_RST_EN;
+		writel(reg, gtr_dev->serdes + TM_CMN_RST);
+
+		writel(0x00, gtr_dev->serdes + L3_TM_CALIB_DIG18);
+		writel(TM_OVERRIDE_NSW_CODE, gtr_dev->serdes +
+				L3_TM_CALIB_DIG19);
+
+		/* As a part of work around sequence for PMOS calibration fix,
+		 * we need to configure any lane ICM_CFG to valid protocol. This
+		 * will deassert the CMN_Resetn signal.
+		 */
+		xpsgtr_lane_setprotocol(gtr_phy);
+
+		/* Clear Test Mode reset */
+		reg = readl(gtr_dev->serdes + TM_CMN_RST);
+		reg = (reg & ~TM_CMN_RST_MASK) | TM_CMN_RST_SET;
+		writel(reg, gtr_dev->serdes + TM_CMN_RST);
+
+		dev_dbg(gtr_dev->dev, "calibrating...\n");
+
+		do {
+			reg = readl(gtr_dev->serdes + L3_CALIB_DONE_STATUS);
+			if ((reg & CALIB_DONE) == CALIB_DONE)
+				break;
+
+			if (!--timeout) {
+				dev_err(gtr_dev->dev, "calibration time out\n");
+				ret = -ETIMEDOUT;
+				goto out;
+			}
+			udelay(1);
+		} while (1);
+
+		dev_dbg(gtr_dev->dev, "calibration done\n");
+
+		/* Reading NMOS Register Code */
+		nsw = readl(gtr_dev->serdes + L0_TXPMA_ST_3);
+
+		/* Set Test Mode reset */
+		reg = readl(gtr_dev->serdes + TM_CMN_RST);
+		reg = (reg & ~TM_CMN_RST_MASK) | TM_CMN_RST_EN;
+		writel(reg, gtr_dev->serdes + TM_CMN_RST);
+
+		nsw = nsw & DN_CALIB_CODE;
+
+		/* Writing NMOS register values back [5:3] */
+		reg = nsw >> DN_CALIB_SHIFT;
+		writel(reg, gtr_dev->serdes + L3_TM_CALIB_DIG19);
+
+		/* Writing NMOS register value [2:0] */
+		reg = ((nsw & 0x7) << NSW_SHIFT) | (1 << NSW_PIPE_SHIFT);
+		writel(reg, gtr_dev->serdes + L3_TM_CALIB_DIG18);
+
+		/* Clear Test Mode reset */
+		reg = readl(gtr_dev->serdes + TM_CMN_RST);
+		reg = (reg & ~TM_CMN_RST_MASK) | TM_CMN_RST_SET;
+		writel(reg, gtr_dev->serdes + TM_CMN_RST);
+
+		gtr_dev->tx_term_fix = false;
+	}
+
+	/* Enable coarse code saturation limiting logic */
+	offset = gtr_phy->lane * TM_PLL_DIG_37_OFFSET + L0_TM_PLL_DIG_37;
+	writel(TM_COARSE_CODE_LIMIT, gtr_dev->serdes + offset);
+
+	xpsgtr_configure_pll(gtr_phy);
+	xpsgtr_lane_setprotocol(gtr_phy);
+
+	if (gtr_phy->protocol == ICM_PROTOCOL_SATA)
+		xpsgtr_misc_sata(gtr_phy);
+
+	if (gtr_phy->protocol == ICM_PROTOCOL_SGMII)
+		xpsgtr_misc_sgmii(gtr_phy);
+
+	/* Bring controller out of reset */
+	ret = xpsgtr_controller_release_reset(gtr_phy);
+	if (ret != 0) {
+		dev_err(gtr_dev->dev, "Failed to release reset\n");
+		goto out;
+	}
+
+	/* Wait till pll is locked for all protocols except DP. For DP
+	 * pll locking function will be called from driver.
+	 */
+	if (gtr_phy->protocol != ICM_PROTOCOL_DP) {
+		ret = xpsgtr_wait_pll_lock(phy);
+		if (ret != 0)
+			goto out;
+	} else {
+		offset = gtr_phy->lane * TXPMD_TM_45_OFFSET + L0_TXPMD_TM_45;
+		reg = L0_TXPMD_TM_45_OVER_DP_MAIN |
+		      L0_TXPMD_TM_45_ENABLE_DP_MAIN |
+		      L0_TXPMD_TM_45_OVER_DP_POST1 |
+		      L0_TXPMD_TM_45_OVER_DP_POST2 |
+		      L0_TXPMD_TM_45_ENABLE_DP_POST2;
+		writel(reg, gtr_dev->serdes + offset);
+		offset = gtr_phy->lane * TX_ANA_TM_118_OFFSET +
+			 L0_TX_ANA_TM_118;
+		writel(L0_TX_ANA_TM_118_FORCE_17_0,
+		       gtr_dev->serdes + offset);
+	}
+
+	/* Do ULPI reset for usb */
+	if (gtr_phy->protocol == ICM_PROTOCOL_USB)
+		ret = xpsgtr_ulpi_reset(gtr_phy);
+
+	/* Select SGMII Mode for GEM and set the PCS Signal detect*/
+	if (gtr_phy->protocol == ICM_PROTOCOL_SGMII)
+		ret = xpsgtr_set_sgmii_pcs(gtr_phy);
+out:
+	mutex_unlock(&gtr_dev->gtr_mutex);
+	return ret;
+}
+
+/**
+ * xpsgtr_set_lanetype - derives lane type from dts arguments
+ * @gtr_phy: pointer to lane
+ * @controller: type of controller
+ * @instance_num: instance number of the controller in case multilane controller
+ *
+ * Return: 0 on success or error on failure
+ */
+static int xpsgtr_set_lanetype(struct xpsgtr_phy *gtr_phy, u8 controller,
+			       u8 instance_num)
+{
+	switch (controller) {
+	case PHY_TYPE_SATA:
+		if (instance_num == 0)
+			gtr_phy->type = XPSGTR_TYPE_SATA_0;
+		else if (instance_num == 1)
+			gtr_phy->type = XPSGTR_TYPE_SATA_1;
+		else
+			return -EINVAL;
+		break;
+	case PHY_TYPE_USB3:
+		if (instance_num == 0)
+			gtr_phy->type = XPSGTR_TYPE_USB0;
+		else if (instance_num == 1)
+			gtr_phy->type = XPSGTR_TYPE_USB1;
+		else
+			return -EINVAL;
+		break;
+	case PHY_TYPE_DP:
+		if (instance_num == 0)
+			gtr_phy->type = XPSGTR_TYPE_DP_0;
+		else if (instance_num == 1)
+			gtr_phy->type = XPSGTR_TYPE_DP_1;
+		else
+			return -EINVAL;
+		break;
+	case PHY_TYPE_PCIE:
+		if (instance_num == 0)
+			gtr_phy->type = XPSGTR_TYPE_PCIE_0;
+		else if (instance_num == 1)
+			gtr_phy->type = XPSGTR_TYPE_PCIE_1;
+		else if (instance_num == 2)
+			gtr_phy->type = XPSGTR_TYPE_PCIE_2;
+		else if (instance_num == 3)
+			gtr_phy->type = XPSGTR_TYPE_PCIE_3;
+		else
+			return -EINVAL;
+		break;
+	case PHY_TYPE_SGMII:
+		if (instance_num == 0)
+			gtr_phy->type = XPSGTR_TYPE_SGMII0;
+		else if (instance_num == 1)
+			gtr_phy->type = XPSGTR_TYPE_SGMII1;
+		else if (instance_num == 2)
+			gtr_phy->type = XPSGTR_TYPE_SGMII2;
+		else if (instance_num == 3)
+			gtr_phy->type = XPSGTR_TYPE_SGMII3;
+		else
+			return -EINVAL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * xpsgtr_xlate - provides a PHY specific to a controller
+ * @dev: pointer to device
+ * @args: arguments from dts
+ *
+ * Return: pointer to kernel PHY device or error on failure
+ */
+static struct phy *xpsgtr_xlate(struct device *dev,
+				struct of_phandle_args *args)
+{
+	struct xpsgtr_dev *gtr_dev = dev_get_drvdata(dev);
+	struct xpsgtr_phy *gtr_phy = NULL;
+	struct device_node *phynode = args->np;
+	int index;
+	int i;
+	u8 controller;
+	u8 instance_num;
+
+	if (args->args_count != 4) {
+		dev_err(dev, "Invalid number of cells in 'phy' property\n");
+		return ERR_PTR(-EINVAL);
+	}
+	if (!of_device_is_available(phynode)) {
+		dev_warn(dev, "requested PHY is disabled\n");
+		return ERR_PTR(-ENODEV);
+	}
+	for (index = 0; index < of_get_child_count(dev->of_node); index++) {
+		if (phynode == gtr_dev->phys[index]->phy->dev.of_node) {
+			gtr_phy = gtr_dev->phys[index];
+			break;
+		}
+	}
+	if (!gtr_phy) {
+		dev_err(dev, "failed to find appropriate phy\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	/* get type of controller from phys */
+	controller = args->args[0];
+
+	/* get controller instance number */
+	instance_num = args->args[1];
+
+	/* Check if lane sharing is required */
+	gtr_phy->share_laneclk = args->args[2];
+
+	/* get the required clk rate for controller from phys */
+	gtr_phy->refclk_rate = args->args[3];
+
+	/* derive lane type */
+	if (xpsgtr_set_lanetype(gtr_phy, controller, instance_num) < 0) {
+		dev_err(gtr_dev->dev, "Invalid lane type\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	/* configures SSC settings for a lane */
+	if (xpsgtr_configure_lane(gtr_phy) < 0) {
+		dev_err(gtr_dev->dev, "Invalid clock rate: %d\n",
+			gtr_phy->refclk_rate);
+		return ERR_PTR(-EINVAL);
+	}
+
+	/*
+	 * Check Interconnect Matrix is obeyed i.e, given lane type
+	 * is allowed to operate on the lane.
+	 */
+	for (i = 0; i < CONTROLLERS_PER_LANE; i++) {
+		if (icm_matrix[index][i] == gtr_phy->type)
+			return gtr_phy->phy;
+	}
+
+	/* Should not reach here */
+	return ERR_PTR(-EINVAL);
+}
+
+/**
+ * xpsgtr_phy_exit - clears previous initialized variables
+ * @phy: pointer to kernel PHY device
+ *
+ * Return: 0 on success
+ */
+static int xpsgtr_phy_exit(struct phy *phy)
+{
+	struct xpsgtr_phy *gtr_phy = phy_get_drvdata(phy);
+
+	/* As we are exiting, clear skip_phy_init flag */
+	gtr_phy->skip_phy_init = false;
+
+	return 0;
+}
+
+static struct phy_ops xpsgtr_phyops = {
+	.init		= xpsgtr_phy_init,
+	.exit		= xpsgtr_phy_exit,
+	.owner		= THIS_MODULE,
+};
+
+/*
+ * xpsgtr_get_resets - Gets reset signals based on reset-names property
+ * @gtr_dev: pointer to structure which stores reset information
+ *
+ * Return: 0 on success or error value on failure
+ */
+static int xpsgtr_get_resets(struct xpsgtr_dev *gtr_dev)
+{
+	char *name;
+	struct reset_control *rst_temp;
+
+	gtr_dev->sata_rst = devm_reset_control_get(gtr_dev->dev, "sata_rst");
+	if (IS_ERR(gtr_dev->sata_rst)) {
+		name = "sata_rst";
+		rst_temp = gtr_dev->sata_rst;
+		goto error;
+	}
+
+	gtr_dev->dp_rst = devm_reset_control_get(gtr_dev->dev, "dp_rst");
+	if (IS_ERR(gtr_dev->dp_rst)) {
+		name = "dp_rst";
+		rst_temp = gtr_dev->dp_rst;
+		goto error;
+	}
+
+	gtr_dev->usb0_crst = devm_reset_control_get(gtr_dev->dev, "usb0_crst");
+	if (IS_ERR(gtr_dev->usb0_crst)) {
+		name = "usb0_crst";
+		rst_temp = gtr_dev->usb0_crst;
+		goto error;
+	}
+
+	gtr_dev->usb1_crst = devm_reset_control_get(gtr_dev->dev, "usb1_crst");
+	if (IS_ERR(gtr_dev->usb1_crst)) {
+		name = "usb1_crst";
+		rst_temp = gtr_dev->usb1_crst;
+		goto error;
+	}
+
+	gtr_dev->usb0_hibrst = devm_reset_control_get(gtr_dev->dev,
+						      "usb0_hibrst");
+	if (IS_ERR(gtr_dev->usb0_hibrst)) {
+		name = "usb0_hibrst";
+		rst_temp = gtr_dev->usb0_hibrst;
+		goto error;
+	}
+
+	gtr_dev->usb1_hibrst = devm_reset_control_get(gtr_dev->dev,
+						      "usb1_hibrst");
+	if (IS_ERR(gtr_dev->usb1_hibrst)) {
+		name = "usb1_hibrst";
+		rst_temp = gtr_dev->usb1_hibrst;
+		goto error;
+	}
+
+	gtr_dev->usb0_apbrst = devm_reset_control_get(gtr_dev->dev,
+						      "usb0_apbrst");
+	if (IS_ERR(gtr_dev->usb0_apbrst)) {
+		name = "usb0_apbrst";
+		rst_temp = gtr_dev->usb0_apbrst;
+		goto error;
+	}
+
+	gtr_dev->usb1_apbrst = devm_reset_control_get(gtr_dev->dev,
+						      "usb1_apbrst");
+	if (IS_ERR(gtr_dev->usb1_apbrst)) {
+		name = "usb1_apbrst";
+		rst_temp = gtr_dev->usb1_apbrst;
+		goto error;
+	}
+
+	gtr_dev->gem0_rst = devm_reset_control_get(gtr_dev->dev, "gem0_rst");
+	if (IS_ERR(gtr_dev->gem0_rst)) {
+		name = "gem0_rst";
+		rst_temp = gtr_dev->gem0_rst;
+		goto error;
+	}
+
+	gtr_dev->gem1_rst = devm_reset_control_get(gtr_dev->dev, "gem1_rst");
+	if (IS_ERR(gtr_dev->gem1_rst)) {
+		name = "gem1_rst";
+		rst_temp = gtr_dev->gem1_rst;
+		goto error;
+	}
+
+	gtr_dev->gem2_rst = devm_reset_control_get(gtr_dev->dev, "gem2_rst");
+	if (IS_ERR(gtr_dev->gem2_rst)) {
+		name = "gem2_rst";
+		rst_temp = gtr_dev->gem2_rst;
+		goto error;
+	}
+
+	gtr_dev->gem3_rst = devm_reset_control_get(gtr_dev->dev, "gem3_rst");
+	if (IS_ERR(gtr_dev->gem3_rst)) {
+		name = "gem3_rst";
+		rst_temp = gtr_dev->gem3_rst;
+		goto error;
+	}
+
+	return 0;
+error:
+	dev_err(gtr_dev->dev, "failed to get %s reset signal\n", name);
+	return PTR_ERR(rst_temp);
+}
+
+/**
+ * xpsgtr_probe - The device probe function for driver initialization.
+ * @pdev: pointer to the platform device structure.
+ *
+ * Return: 0 for success and error value on failure
+ */
+static int xpsgtr_probe(struct platform_device *pdev)
+{
+	struct device_node *child, *np = pdev->dev.of_node;
+	struct xpsgtr_dev *gtr_dev;
+	struct phy_provider *provider;
+	struct phy *phy;
+	struct resource *res;
+	char *soc_rev;
+	int lanecount, port = 0, index = 0;
+	int err;
+
+	if (of_device_is_compatible(np, "xlnx,zynqmp-psgtr"))
+		dev_warn(&pdev->dev, "This binding is deprecated, please use new compatible binding\n");
+
+	eemi_ops = zynqmp_pm_get_eemi_ops();
+	if (IS_ERR(eemi_ops))
+		return PTR_ERR(eemi_ops);
+
+	gtr_dev = devm_kzalloc(&pdev->dev, sizeof(*gtr_dev), GFP_KERNEL);
+	if (!gtr_dev)
+		return -ENOMEM;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "serdes");
+	gtr_dev->serdes = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(gtr_dev->serdes))
+		return PTR_ERR(gtr_dev->serdes);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "siou");
+	gtr_dev->siou = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(gtr_dev->siou))
+		return PTR_ERR(gtr_dev->siou);
+
+	lanecount = of_get_child_count(np);
+	if (lanecount > MAX_LANES || lanecount == 0)
+		return -EINVAL;
+
+	gtr_dev->phys = devm_kzalloc(&pdev->dev, sizeof(phy) * lanecount,
+				     GFP_KERNEL);
+	if (!gtr_dev->phys)
+		return -ENOMEM;
+
+	gtr_dev->dev = &pdev->dev;
+	platform_set_drvdata(pdev, gtr_dev);
+	mutex_init(&gtr_dev->gtr_mutex);
+
+	/* Deferred probe is also handled if nvmem is not ready */
+	soc_rev = zynqmp_nvmem_get_silicon_version(&pdev->dev,
+						   "soc_revision");
+	if (IS_ERR(soc_rev))
+		return PTR_ERR(soc_rev);
+
+	if (*soc_rev == ZYNQMP_SILICON_V1)
+		gtr_dev->tx_term_fix = true;
+
+	kfree(soc_rev);
+
+	err = xpsgtr_get_resets(gtr_dev);
+	if (err) {
+		dev_err(&pdev->dev, "failed to get resets: %d\n", err);
+		return err;
+	}
+
+	for_each_child_of_node(np, child) {
+		struct xpsgtr_phy *gtr_phy;
+
+		gtr_phy = devm_kzalloc(&pdev->dev, sizeof(*gtr_phy),
+				       GFP_KERNEL);
+		if (!gtr_phy)
+			return -ENOMEM;
+
+		/* Assign lane number to gtr_phy instance */
+		gtr_phy->lane = index;
+
+		/* Disable lane sharing as default */
+		gtr_phy->share_laneclk = -1;
+
+		gtr_dev->phys[port] = gtr_phy;
+		phy = devm_phy_create(&pdev->dev, child, &xpsgtr_phyops);
+		if (IS_ERR(phy)) {
+			dev_err(&pdev->dev, "failed to create PHY\n");
+			return PTR_ERR(phy);
+		}
+		gtr_dev->phys[port]->phy = phy;
+		phy_set_drvdata(phy, gtr_dev->phys[port]);
+		gtr_phy->data = gtr_dev;
+		port++;
+		index++;
+	}
+	provider = devm_of_phy_provider_register(&pdev->dev, xpsgtr_xlate);
+	if (IS_ERR(provider)) {
+		dev_err(&pdev->dev, "registering provider failed\n");
+			return PTR_ERR(provider);
+	}
+	return 0;
+}
+
+static int xpsgtr_suspend(struct device *dev)
+{
+	struct xpsgtr_dev *gtr_dev = dev_get_drvdata(dev);
+
+	/* Save the ICM_CFG registers */
+	gtr_dev->saved_icm_cfg0 = readl(gtr_dev->serdes + ICM_CFG0);
+	gtr_dev->saved_icm_cfg1 = readl(gtr_dev->serdes + ICM_CFG1);
+
+	return 0;
+}
+
+static int xpsgtr_resume(struct device *dev)
+{
+	unsigned int icm_cfg0, icm_cfg1, index;
+	bool skip_phy_init;
+	struct xpsgtr_phy *gtr_phy;
+	struct xpsgtr_dev *gtr_dev = dev_get_drvdata(dev);
+
+	icm_cfg0 = readl(gtr_dev->serdes + ICM_CFG0);
+	icm_cfg1 = readl(gtr_dev->serdes + ICM_CFG1);
+
+	/* Just return if no gt lanes got configured before suspend */
+	if (!gtr_dev->saved_icm_cfg0 && !gtr_dev->saved_icm_cfg1)
+		return 0;
+
+	/* Check if the ICM configurations changed after suspend */
+	if (icm_cfg0 == gtr_dev->saved_icm_cfg0 &&
+	    icm_cfg1 == gtr_dev->saved_icm_cfg1)
+		skip_phy_init = true;
+	else
+		skip_phy_init = false;
+
+	/* This below updates the skip_phy_init for all gtr_phy instances `*/
+	for (index = 0; index < of_get_child_count(dev->of_node); index++) {
+		gtr_phy = gtr_dev->phys[index];
+		gtr_phy->skip_phy_init = skip_phy_init;
+	}
+
+	return 0;
+}
+
+static const struct dev_pm_ops xpsgtr_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(xpsgtr_suspend, xpsgtr_resume)
+};
+
+/* Match table for of_platform binding */
+static const struct of_device_id xpsgtr_of_match[] = {
+	{ .compatible = "xlnx,zynqmp-psgtr", },
+	{ .compatible = "xlnx,zynqmp-psgtr-v1.1", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, xpsgtr_of_match);
+
+static struct platform_driver xpsgtr_driver = {
+	.probe = xpsgtr_probe,
+	.driver = {
+		.name = "xilinx-psgtr",
+		.of_match_table	= xpsgtr_of_match,
+		.pm =  &xpsgtr_pm_ops,
+	},
+};
+
+module_platform_driver(xpsgtr_driver);
+
+MODULE_AUTHOR("Xilinx Inc.");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Xilinx ZynqMP High speed Gigabit Transceiver");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/qualcomm/phy-qcom-apq8064-sata.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/qualcomm/phy-qcom-apq8064-sata.c
@@ -80,7 +80,7 @@
 		if (readl_relaxed(addr) & mask)
 			return 0;
 
-		 usleep_range(DELAY_INTERVAL_US, DELAY_INTERVAL_US + 50);
+		usleep_range(DELAY_INTERVAL_US, DELAY_INTERVAL_US + 50);
 	} while (!time_after(jiffies, timeout));
 
 	return (readl_relaxed(addr) & mask) ? 0 : -ETIMEDOUT;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/qualcomm/phy-qcom-qmp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/qualcomm/phy-qcom-qmp.c
@@ -66,7 +66,7 @@
 /* QPHY_V3_PCS_MISC_CLAMP_ENABLE register bits */
 #define CLAMP_EN				BIT(0) /* enables i/o clamp_n */
 
-#define PHY_INIT_COMPLETE_TIMEOUT		1000
+#define PHY_INIT_COMPLETE_TIMEOUT		10000
 #define POWER_DOWN_DELAY_US_MIN			10
 #define POWER_DOWN_DELAY_US_MAX			11
 
@@ -402,8 +402,8 @@
 	QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0xf),
 	QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x1),
 	QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x0),
-	QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0x1f),
-	QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x3f),
+	QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0xff),
+	QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x1f),
 	QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x6),
 	QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0xf),
 	QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x0),
@@ -429,7 +429,6 @@
 	QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x0),
 	QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80),
 	QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CTRL_BY_PSM, 0x1),
-	QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL, 0xa),
 	QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x1),
 	QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31),
 	QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x1),
@@ -438,7 +437,6 @@
 	QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0x2f),
 	QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x19),
 	QMP_PHY_INIT_CFG(QSERDES_COM_CLK_EP_DIV, 0x19),
-	QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x7),
 };
 
 static const struct qmp_phy_init_tbl ipq8074_pcie_tx_tbl[] = {
@@ -446,6 +444,8 @@
 	QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x6),
 	QMP_PHY_INIT_CFG(QSERDES_TX_RES_CODE_LANE_OFFSET, 0x2),
 	QMP_PHY_INIT_CFG(QSERDES_TX_RCV_DETECT_LVL_2, 0x12),
+	QMP_PHY_INIT_CFG(QSERDES_TX_EMP_POST1_LVL, 0x36),
+	QMP_PHY_INIT_CFG(QSERDES_TX_SLEW_CNTL, 0x0a),
 };
 
 static const struct qmp_phy_init_tbl ipq8074_pcie_rx_tbl[] = {
@@ -456,7 +456,6 @@
 	QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xdb),
 	QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b),
 	QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x4),
-	QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN_HALF, 0x4),
 };
 
 static const struct qmp_phy_init_tbl ipq8074_pcie_pcs_tbl[] = {
@@ -1107,6 +1106,9 @@
 	.pwrdn_ctrl		= SW_PWRDN,
 };
 
+static const char * const ipq8074_pciephy_clk_l[] = {
+	"aux", "cfg_ahb",
+};
 /* list of resets */
 static const char * const ipq8074_pciephy_reset_l[] = {
 	"phy", "common",
@@ -1124,8 +1126,8 @@
 	.rx_tbl_num		= ARRAY_SIZE(ipq8074_pcie_rx_tbl),
 	.pcs_tbl		= ipq8074_pcie_pcs_tbl,
 	.pcs_tbl_num		= ARRAY_SIZE(ipq8074_pcie_pcs_tbl),
-	.clk_list		= NULL,
-	.num_clks		= 0,
+	.clk_list		= ipq8074_pciephy_clk_l,
+	.num_clks		= ARRAY_SIZE(ipq8074_pciephy_clk_l),
 	.reset_list		= ipq8074_pciephy_reset_l,
 	.num_resets		= ARRAY_SIZE(ipq8074_pciephy_reset_l),
 	.vreg_list		= NULL,
@@ -1515,7 +1517,7 @@
 	qcom_qmp_phy_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num);
 	ret = reset_control_deassert(qmp->ufs_reset);
 	if (ret)
-		goto err_lane_rst;
+		goto err_pcs_ready;
 
 	/*
 	 * Pull out PHY from POWER DOWN state.
@@ -1858,6 +1860,11 @@
 	.owner		= THIS_MODULE,
 };
 
+static void qcom_qmp_reset_control_put(void *data)
+{
+	reset_control_put(data);
+}
+
 static
 int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id)
 {
@@ -1927,7 +1934,7 @@
 	 * all phys that don't need this.
 	 */
 	snprintf(prop_name, sizeof(prop_name), "pipe%d", id);
-	qphy->pipe_clk = of_clk_get_by_name(np, prop_name);
+	qphy->pipe_clk = devm_get_clk_from_child(dev, np, prop_name);
 	if (IS_ERR(qphy->pipe_clk)) {
 		if (qmp->cfg->type == PHY_TYPE_PCIE ||
 		    qmp->cfg->type == PHY_TYPE_USB3) {
@@ -1949,6 +1956,10 @@
 			dev_err(dev, "failed to get lane%d reset\n", id);
 			return PTR_ERR(qphy->lane_rst);
 		}
+		ret = devm_add_action_or_reset(dev, qcom_qmp_reset_control_put,
+					       qphy->lane_rst);
+		if (ret)
+			return ret;
 	}
 
 	if (qmp->cfg->type == PHY_TYPE_UFS)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/qualcomm/phy-qcom-qmp.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/qualcomm/phy-qcom-qmp.h
@@ -77,6 +77,8 @@
 #define QSERDES_COM_CORECLK_DIV_MODE1			0x1bc
 
 /* Only for QMP V2 PHY - TX registers */
+#define QSERDES_TX_EMP_POST1_LVL			0x018
+#define QSERDES_TX_SLEW_CNTL				0x040
 #define QSERDES_TX_RES_CODE_LANE_OFFSET			0x054
 #define QSERDES_TX_DEBUG_BUS_SEL			0x064
 #define QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN	0x068
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/qualcomm/phy-qcom-qusb2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/qualcomm/phy-qcom-qusb2.c
@@ -432,7 +432,7 @@
 {
 	struct device *dev = &qphy->phy->dev;
 	const struct qusb2_phy_cfg *cfg = qphy->cfg;
-	u8 *val;
+	u8 *val, hstx_trim;
 
 	/* efuse register is optional */
 	if (!qphy->cell)
@@ -446,7 +446,13 @@
 	 * set while configuring the phy.
 	 */
 	val = nvmem_cell_read(qphy->cell, NULL);
-	if (IS_ERR(val) || !val[0]) {
+	if (IS_ERR(val)) {
+		dev_dbg(dev, "failed to read a valid hs-tx trim value\n");
+		return;
+	}
+	hstx_trim = val[0];
+	kfree(val);
+	if (!hstx_trim) {
 		dev_dbg(dev, "failed to read a valid hs-tx trim value\n");
 		return;
 	}
@@ -454,12 +460,10 @@
 	/* Fused TUNE1/2 value is the higher nibble only */
 	if (cfg->update_tune1_with_efuse)
 		qusb2_write_mask(qphy->base, cfg->regs[QUSB2PHY_PORT_TUNE1],
-				 val[0] << HSTX_TRIM_SHIFT,
-				 HSTX_TRIM_MASK);
+				 hstx_trim << HSTX_TRIM_SHIFT, HSTX_TRIM_MASK);
 	else
 		qusb2_write_mask(qphy->base, cfg->regs[QUSB2PHY_PORT_TUNE2],
-				 val[0] << HSTX_TRIM_SHIFT,
-				 HSTX_TRIM_MASK);
+				 hstx_trim << HSTX_TRIM_SHIFT, HSTX_TRIM_MASK);
 }
 
 static int qusb2_phy_set_mode(struct phy *phy,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/qualcomm/phy-qcom-usb-hs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/qualcomm/phy-qcom-usb-hs.c
@@ -158,8 +158,8 @@
 		/* setup initial state */
 		qcom_usb_hs_phy_vbus_notifier(&uphy->vbus_notify, state,
 					      uphy->vbus_edev);
-		ret = devm_extcon_register_notifier(&ulpi->dev, uphy->vbus_edev,
-				EXTCON_USB, &uphy->vbus_notify);
+		ret = extcon_register_notifier(uphy->vbus_edev, EXTCON_USB,
+					       &uphy->vbus_notify);
 		if (ret)
 			goto err_ulpi;
 	}
@@ -180,6 +180,9 @@
 {
 	struct qcom_usb_hs_phy *uphy = phy_get_drvdata(phy);
 
+	if (uphy->vbus_edev)
+		extcon_unregister_notifier(uphy->vbus_edev, EXTCON_USB,
+					   &uphy->vbus_notify);
 	regulator_disable(uphy->v3p3);
 	regulator_disable(uphy->v1p8);
 	clk_disable_unprepare(uphy->sleep_clk);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/qualcomm/phy-qcom-usb-hsic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/qualcomm/phy-qcom-usb-hsic.c
@@ -54,8 +54,10 @@
 
 	/* Configure pins for HSIC functionality */
 	pins_default = pinctrl_lookup_state(uphy->pctl, PINCTRL_STATE_DEFAULT);
-	if (IS_ERR(pins_default))
-		return PTR_ERR(pins_default);
+	if (IS_ERR(pins_default)) {
+		ret = PTR_ERR(pins_default);
+		goto err_ulpi;
+	}
 
 	ret = pinctrl_select_state(uphy->pctl, pins_default);
 	if (ret)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/renesas/phy-rcar-gen2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/renesas/phy-rcar-gen2.c
@@ -71,6 +71,7 @@
 struct rcar_gen2_phy_data {
 	const struct phy_ops *gen2_phy_ops;
 	const u32 (*select_value)[PHYS_PER_CHANNEL];
+	const u32 num_channels;
 };
 
 static int rcar_gen2_phy_init(struct phy *p)
@@ -271,11 +272,13 @@
 static const struct rcar_gen2_phy_data rcar_gen2_usb_phy_data = {
 	.gen2_phy_ops = &rcar_gen2_phy_ops,
 	.select_value = pci_select_value,
+	.num_channels = ARRAY_SIZE(pci_select_value),
 };
 
 static const struct rcar_gen2_phy_data rz_g1c_usb_phy_data = {
 	.gen2_phy_ops = &rz_g1c_phy_ops,
 	.select_value = usb20_select_value,
+	.num_channels = ARRAY_SIZE(usb20_select_value),
 };
 
 static const struct of_device_id rcar_gen2_phy_match_table[] = {
@@ -389,7 +392,7 @@
 		channel->selected_phy = -1;
 
 		error = of_property_read_u32(np, "reg", &channel_num);
-		if (error || channel_num > 2) {
+		if (error || channel_num >= data->num_channels) {
 			dev_err(dev, "Invalid \"reg\" property\n");
 			of_node_put(np);
 			return error;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/renesas/phy-rcar-gen3-usb2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/renesas/phy-rcar-gen3-usb2.c
@@ -21,6 +21,7 @@
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/regulator/consumer.h>
+#include <linux/string.h>
 #include <linux/usb/of.h>
 #include <linux/workqueue.h>
 
@@ -110,6 +111,7 @@
 	struct work_struct work;
 	struct mutex lock;	/* protects rphys[...].powered */
 	enum usb_dr_mode dr_mode;
+	int irq;
 	bool extcon_host;
 	bool is_otg_channel;
 	bool uses_otg_pins;
@@ -320,9 +322,9 @@
 	if (!ch->is_otg_channel || !rcar_gen3_is_any_rphy_initialized(ch))
 		return -EIO;
 
-	if (!strncmp(buf, "host", strlen("host")))
+	if (sysfs_streq(buf, "host"))
 		new_mode = PHY_MODE_USB_HOST;
-	else if (!strncmp(buf, "peripheral", strlen("peripheral")))
+	else if (sysfs_streq(buf, "peripheral"))
 		new_mode = PHY_MODE_USB_DEVICE;
 	else
 		return -EINVAL;
@@ -388,12 +390,38 @@
 	rcar_gen3_device_recognition(ch);
 }
 
+static irqreturn_t rcar_gen3_phy_usb2_irq(int irq, void *_ch)
+{
+	struct rcar_gen3_chan *ch = _ch;
+	void __iomem *usb2_base = ch->base;
+	u32 status = readl(usb2_base + USB2_OBINTSTA);
+	irqreturn_t ret = IRQ_NONE;
+
+	if (status & USB2_OBINT_BITS) {
+		dev_vdbg(ch->dev, "%s: %08x\n", __func__, status);
+		writel(USB2_OBINT_BITS, usb2_base + USB2_OBINTSTA);
+		rcar_gen3_device_recognition(ch);
+		ret = IRQ_HANDLED;
+	}
+
+	return ret;
+}
+
 static int rcar_gen3_phy_usb2_init(struct phy *p)
 {
 	struct rcar_gen3_phy *rphy = phy_get_drvdata(p);
 	struct rcar_gen3_chan *channel = rphy->ch;
 	void __iomem *usb2_base = channel->base;
 	u32 val;
+	int ret;
+
+	if (!rcar_gen3_is_any_rphy_initialized(channel) && channel->irq >= 0) {
+		INIT_WORK(&channel->work, rcar_gen3_phy_usb2_work);
+		ret = request_irq(channel->irq, rcar_gen3_phy_usb2_irq,
+				  IRQF_SHARED, dev_name(channel->dev), channel);
+		if (ret < 0)
+			dev_err(channel->dev, "No irq handler (%d)\n", channel->irq);
+	}
 
 	/* Initialize USB2 part */
 	val = readl(usb2_base + USB2_INT_ENABLE);
@@ -432,6 +460,9 @@
 		val &= ~USB2_INT_ENABLE_UCOM_INTEN;
 	writel(val, usb2_base + USB2_INT_ENABLE);
 
+	if (channel->irq >= 0 && !rcar_gen3_is_any_rphy_initialized(channel))
+		free_irq(channel->irq, channel);
+
 	return 0;
 }
 
@@ -502,23 +533,6 @@
 	.owner		= THIS_MODULE,
 };
 
-static irqreturn_t rcar_gen3_phy_usb2_irq(int irq, void *_ch)
-{
-	struct rcar_gen3_chan *ch = _ch;
-	void __iomem *usb2_base = ch->base;
-	u32 status = readl(usb2_base + USB2_OBINTSTA);
-	irqreturn_t ret = IRQ_NONE;
-
-	if (status & USB2_OBINT_BITS) {
-		dev_vdbg(ch->dev, "%s: %08x\n", __func__, status);
-		writel(USB2_OBINT_BITS, usb2_base + USB2_OBINTSTA);
-		rcar_gen3_device_recognition(ch);
-		ret = IRQ_HANDLED;
-	}
-
-	return ret;
-}
-
 static const struct of_device_id rcar_gen3_phy_usb2_match_table[] = {
 	{
 		.compatible = "renesas,usb2-phy-r8a77470",
@@ -597,7 +611,7 @@
 	struct phy_provider *provider;
 	struct resource *res;
 	const struct phy_ops *phy_usb2_ops;
-	int irq, ret = 0, i;
+	int ret = 0, i;
 
 	if (!dev->of_node) {
 		dev_err(dev, "This driver needs device tree\n");
@@ -613,20 +627,10 @@
 	if (IS_ERR(channel->base))
 		return PTR_ERR(channel->base);
 
-	/* call request_irq for OTG */
-	irq = platform_get_irq(pdev, 0);
-	if (irq >= 0) {
-		INIT_WORK(&channel->work, rcar_gen3_phy_usb2_work);
-		irq = devm_request_irq(dev, irq, rcar_gen3_phy_usb2_irq,
-				       IRQF_SHARED, dev_name(dev), channel);
-		if (irq < 0)
-			dev_err(dev, "No irq handler (%d)\n", irq);
-	}
-
+	/* get irq number here and request_irq for OTG in phy_init */
+	channel->irq = platform_get_irq_optional(pdev, 0);
 	channel->dr_mode = rcar_gen3_get_dr_mode(dev->of_node);
 	if (channel->dr_mode != USB_DR_MODE_UNKNOWN) {
-		int ret;
-
 		channel->is_otg_channel = true;
 		channel->uses_otg_pins = !of_property_read_bool(dev->of_node,
 							"renesas,no-otg-pins");
@@ -648,8 +652,10 @@
 	 */
 	pm_runtime_enable(dev);
 	phy_usb2_ops = of_device_get_match_data(dev);
-	if (!phy_usb2_ops)
-		return -EINVAL;
+	if (!phy_usb2_ops) {
+		ret = -EINVAL;
+		goto error;
+	}
 
 	mutex_init(&channel->lock);
 	for (i = 0; i < NUM_OF_PHYS; i++) {
@@ -683,8 +689,6 @@
 		ret = PTR_ERR(provider);
 		goto error;
 	} else if (channel->is_otg_channel) {
-		int ret;
-
 		ret = device_create_file(dev, &dev_attr_role);
 		if (ret < 0)
 			goto error;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/rockchip/phy-rockchip-emmc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/rockchip/phy-rockchip-emmc.c
@@ -240,15 +240,17 @@
 	 * - SDHCI driver to get the PHY
 	 * - SDHCI driver to init the PHY
 	 *
-	 * The clock is optional, so upon any error we just set to NULL.
+	 * The clock is optional, using clk_get_optional() to get the clock
+	 * and do error processing if the return value != NULL
 	 *
 	 * NOTE: we don't do anything special for EPROBE_DEFER here.  Given the
 	 * above expected use case, EPROBE_DEFER isn't sensible to expect, so
 	 * it's just like any other error.
 	 */
-	rk_phy->emmcclk = clk_get(&phy->dev, "emmcclk");
+	rk_phy->emmcclk = clk_get_optional(&phy->dev, "emmcclk");
 	if (IS_ERR(rk_phy->emmcclk)) {
-		dev_dbg(&phy->dev, "Error getting emmcclk: %d\n", ret);
+		ret = PTR_ERR(rk_phy->emmcclk);
+		dev_err(&phy->dev, "Error getting emmcclk: %d\n", ret);
 		rk_phy->emmcclk = NULL;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
@@ -603,6 +603,8 @@
 {
 	const struct pre_pll_config *cfg = pre_pll_cfg_table;
 
+	rate = (rate / 1000) * 1000;
+
 	for (; cfg->pixclock != 0; cfg++)
 		if (cfg->pixclock == rate && !cfg->fracdiv)
 			break;
@@ -743,10 +745,12 @@
 		do_div(vco, (nd * (no_a == 1 ? no_b : no_a) * no_d * 2));
 	}
 
-	inno->pixclock = vco;
-	dev_dbg(inno->dev, "%s rate %lu\n", __func__, inno->pixclock);
+	inno->pixclock = DIV_ROUND_CLOSEST((unsigned long)vco, 1000) * 1000;
+
+	dev_dbg(inno->dev, "%s rate %lu vco %llu\n",
+		__func__, inno->pixclock, vco);
 
-	return vco;
+	return inno->pixclock;
 }
 
 static long inno_hdmi_phy_rk3328_clk_round_rate(struct clk_hw *hw,
@@ -755,6 +759,8 @@
 {
 	const struct pre_pll_config *cfg = pre_pll_cfg_table;
 
+	rate = (rate / 1000) * 1000;
+
 	for (; cfg->pixclock != 0; cfg++)
 		if (cfg->pixclock == rate)
 			break;
@@ -786,8 +792,8 @@
 			 RK3328_PRE_PLL_POWER_DOWN);
 
 	/* Configure pre-pll */
-	inno_update_bits(inno, 0xa0, RK3228_PCLK_VCO_DIV_5_MASK,
-			 RK3228_PCLK_VCO_DIV_5(cfg->vco_div_5_en));
+	inno_update_bits(inno, 0xa0, RK3328_PCLK_VCO_DIV_5_MASK,
+			 RK3328_PCLK_VCO_DIV_5(cfg->vco_div_5_en));
 	inno_write(inno, 0xa1, RK3328_PRE_PLL_PRE_DIV(cfg->prediv));
 
 	val = RK3328_SPREAD_SPECTRUM_MOD_DISABLE;
@@ -1017,9 +1023,10 @@
 
 	inno_write(inno, 0xac, RK3328_POST_PLL_FB_DIV_7_0(cfg->fbdiv));
 	if (cfg->postdiv == 1) {
-		inno_write(inno, 0xaa, RK3328_POST_PLL_REFCLK_SEL_TMDS);
 		inno_write(inno, 0xab, RK3328_POST_PLL_FB_DIV_8(cfg->fbdiv) |
 			   RK3328_POST_PLL_PRE_DIV(cfg->prediv));
+		inno_write(inno, 0xaa, RK3328_POST_PLL_REFCLK_SEL_TMDS |
+			   RK3328_POST_PLL_POWER_DOWN);
 	} else {
 		v = (cfg->postdiv / 2) - 1;
 		v &= RK3328_POST_PLL_POST_DIV_MASK;
@@ -1027,7 +1034,8 @@
 		inno_write(inno, 0xab, RK3328_POST_PLL_FB_DIV_8(cfg->fbdiv) |
 			   RK3328_POST_PLL_PRE_DIV(cfg->prediv));
 		inno_write(inno, 0xaa, RK3328_POST_PLL_POST_DIV_ENABLE |
-			   RK3328_POST_PLL_REFCLK_SEL_TMDS);
+			   RK3328_POST_PLL_REFCLK_SEL_TMDS |
+			   RK3328_POST_PLL_POWER_DOWN);
 	}
 
 	for (v = 0; v < 14; v++)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/rockchip/phy-rockchip-inno-usb2.c
@@ -467,8 +467,10 @@
 		return ret;
 
 	ret = property_enable(base, &rport->port_cfg->phy_sus, false);
-	if (ret)
+	if (ret) {
+		clk_disable_unprepare(rphy->clk480m);
 		return ret;
+	}
 
 	/* waiting for the utmi_clk to become stable */
 	usleep_range(1500, 2000);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/rockchip/phy-rockchip-typec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/rockchip/phy-rockchip-typec.c
@@ -808,9 +808,8 @@
 	struct extcon_dev *edev = tcphy->extcon;
 	union extcon_property_value property;
 	unsigned int id;
-	bool ufp, dp;
 	u8 mode;
-	int ret;
+	int ret, ufp, dp;
 
 	if (!edev)
 		return MODE_DFP_USB;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/samsung/phy-exynos5-usbdrd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/samsung/phy-exynos5-usbdrd.c
@@ -287,9 +287,9 @@
 	reg |=	PHYCLKRST_REFCLKSEL_EXT_REFCLK;
 
 	/* FSEL settings corresponding to reference clock */
-	reg &= ~PHYCLKRST_FSEL_PIPE_MASK |
-		PHYCLKRST_MPLL_MULTIPLIER_MASK |
-		PHYCLKRST_SSC_REFCLKSEL_MASK;
+	reg &= ~(PHYCLKRST_FSEL_PIPE_MASK |
+		 PHYCLKRST_MPLL_MULTIPLIER_MASK |
+		 PHYCLKRST_SSC_REFCLKSEL_MASK);
 	switch (phy_drd->extrefclk) {
 	case EXYNOS5_FSEL_50MHZ:
 		reg |= (PHYCLKRST_MPLL_MULTIPLIER_50M_REF |
@@ -331,9 +331,9 @@
 	reg &= ~PHYCLKRST_REFCLKSEL_MASK;
 	reg |=	PHYCLKRST_REFCLKSEL_EXT_REFCLK;
 
-	reg &= ~PHYCLKRST_FSEL_UTMI_MASK |
-		PHYCLKRST_MPLL_MULTIPLIER_MASK |
-		PHYCLKRST_SSC_REFCLKSEL_MASK;
+	reg &= ~(PHYCLKRST_FSEL_UTMI_MASK |
+		 PHYCLKRST_MPLL_MULTIPLIER_MASK |
+		 PHYCLKRST_SSC_REFCLKSEL_MASK);
 	reg |= PHYCLKRST_FSEL(phy_drd->extrefclk);
 
 	return reg;
@@ -714,7 +714,9 @@
 	struct phy_usb_instance *inst = phy_get_drvdata(phy);
 	struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
 
-	return exynos5420_usbdrd_phy_calibrate(phy_drd);
+	if (inst->phy_cfg->id == EXYNOS5_DRDPHY_UTMI)
+		return exynos5420_usbdrd_phy_calibrate(phy_drd);
+	return 0;
 }
 
 static const struct phy_ops exynos5_usbdrd_phy_ops = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/samsung/phy-exynos5250-sata.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/samsung/phy-exynos5250-sata.c
@@ -190,6 +190,7 @@
 		return -EINVAL;
 
 	sata_phy->client = of_find_i2c_device_by_node(node);
+	of_node_put(node);
 	if (!sata_phy->client)
 		return -EPROBE_DEFER;
 
@@ -198,20 +199,21 @@
 	sata_phy->phyclk = devm_clk_get(dev, "sata_phyctrl");
 	if (IS_ERR(sata_phy->phyclk)) {
 		dev_err(dev, "failed to get clk for PHY\n");
-		return PTR_ERR(sata_phy->phyclk);
+		ret = PTR_ERR(sata_phy->phyclk);
+		goto put_dev;
 	}
 
 	ret = clk_prepare_enable(sata_phy->phyclk);
 	if (ret < 0) {
 		dev_err(dev, "failed to enable source clk\n");
-		return ret;
+		goto put_dev;
 	}
 
 	sata_phy->phy = devm_phy_create(dev, NULL, &exynos_sata_phy_ops);
 	if (IS_ERR(sata_phy->phy)) {
-		clk_disable_unprepare(sata_phy->phyclk);
 		dev_err(dev, "failed to create PHY\n");
-		return PTR_ERR(sata_phy->phy);
+		ret = PTR_ERR(sata_phy->phy);
+		goto clk_disable;
 	}
 
 	phy_set_drvdata(sata_phy->phy, sata_phy);
@@ -219,11 +221,18 @@
 	phy_provider = devm_of_phy_provider_register(dev,
 					of_phy_simple_xlate);
 	if (IS_ERR(phy_provider)) {
-		clk_disable_unprepare(sata_phy->phyclk);
-		return PTR_ERR(phy_provider);
+		ret = PTR_ERR(phy_provider);
+		goto clk_disable;
 	}
 
 	return 0;
+
+clk_disable:
+	clk_disable_unprepare(sata_phy->phyclk);
+put_dev:
+	put_device(&sata_phy->client->dev);
+
+	return ret;
 }
 
 static const struct of_device_id exynos_sata_phy_of_match[] = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/samsung/phy-s5pv210-usb2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/samsung/phy-s5pv210-usb2.c
@@ -139,6 +139,10 @@
 		udelay(10);
 		rst &= ~rstbits;
 		writel(rst, drv->reg_phy + S5PV210_UPHYRST);
+		/* The following delay is necessary for the reset sequence to be
+		 * completed
+		 */
+		udelay(80);
 	} else {
 		pwr = readl(drv->reg_phy + S5PV210_UPHYPWR);
 		pwr |= phypwr;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/socionext/phy-uniphier-pcie.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/socionext/phy-uniphier-pcie.c
@@ -20,11 +20,13 @@
 
 /* PHY */
 #define PCL_PHY_TEST_I		0x2000
-#define PCL_PHY_TEST_O		0x2004
 #define TESTI_DAT_MASK		GENMASK(13, 6)
 #define TESTI_ADR_MASK		GENMASK(5, 1)
 #define TESTI_WR_EN		BIT(0)
 
+#define PCL_PHY_TEST_O		0x2004
+#define TESTO_DAT_MASK		GENMASK(7, 0)
+
 #define PCL_PHY_RESET		0x200c
 #define PCL_PHY_RESET_N_MNMODE	BIT(8)	/* =1:manual */
 #define PCL_PHY_RESET_N		BIT(0)	/* =1:deasssert */
@@ -72,11 +74,12 @@
 	val  = FIELD_PREP(TESTI_DAT_MASK, 1);
 	val |= FIELD_PREP(TESTI_ADR_MASK, reg);
 	uniphier_pciephy_testio_write(priv, val);
-	val = readl(priv->base + PCL_PHY_TEST_O);
+	val = readl(priv->base + PCL_PHY_TEST_O) & TESTO_DAT_MASK;
 
 	/* update value */
-	val &= ~FIELD_PREP(TESTI_DAT_MASK, mask);
-	val  = FIELD_PREP(TESTI_DAT_MASK, mask & param);
+	val &= ~mask;
+	val |= mask & param;
+	val = FIELD_PREP(TESTI_DAT_MASK, val);
 	val |= FIELD_PREP(TESTI_ADR_MASK, reg);
 	uniphier_pciephy_testio_write(priv, val);
 	uniphier_pciephy_testio_write(priv, val | TESTI_WR_EN);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/socionext/phy-uniphier-usb3ss.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/socionext/phy-uniphier-usb3ss.c
@@ -22,11 +22,13 @@
 #include <linux/reset.h>
 
 #define SSPHY_TESTI		0x0
-#define SSPHY_TESTO		0x4
 #define TESTI_DAT_MASK		GENMASK(13, 6)
 #define TESTI_ADR_MASK		GENMASK(5, 1)
 #define TESTI_WR_EN		BIT(0)
 
+#define SSPHY_TESTO		0x4
+#define TESTO_DAT_MASK		GENMASK(7, 0)
+
 #define PHY_F(regno, msb, lsb) { (regno), (msb), (lsb) }
 
 #define CDR_CPD_TRIM	PHY_F(7, 3, 0)	/* RxPLL charge pump current */
@@ -84,12 +86,12 @@
 	val  = FIELD_PREP(TESTI_DAT_MASK, 1);
 	val |= FIELD_PREP(TESTI_ADR_MASK, p->field.reg_no);
 	uniphier_u3ssphy_testio_write(priv, val);
-	val = readl(priv->base + SSPHY_TESTO);
+	val = readl(priv->base + SSPHY_TESTO) & TESTO_DAT_MASK;
 
 	/* update value */
-	val &= ~FIELD_PREP(TESTI_DAT_MASK, field_mask);
+	val &= ~field_mask;
 	data = field_mask & (p->value << p->field.lsb);
-	val  = FIELD_PREP(TESTI_DAT_MASK, data);
+	val  = FIELD_PREP(TESTI_DAT_MASK, data | val);
 	val |= FIELD_PREP(TESTI_ADR_MASK, p->field.reg_no);
 	uniphier_u3ssphy_testio_write(priv, val);
 	uniphier_u3ssphy_testio_write(priv, val | TESTI_WR_EN);
@@ -315,6 +317,10 @@
 		.data = &uniphier_pro4_data,
 	},
 	{
+		.compatible = "socionext,uniphier-pro5-usb3-ssphy",
+		.data = &uniphier_pro4_data,
+	},
+	{
 		.compatible = "socionext,uniphier-pxs2-usb3-ssphy",
 		.data = &uniphier_pxs2_data,
 	},
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/st/phy-miphy28lp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/st/phy-miphy28lp.c
@@ -9,6 +9,7 @@
 
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/iopoll.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/of.h>
@@ -484,19 +485,11 @@
 
 static inline int miphy28lp_wait_compensation(struct miphy28lp_phy *miphy_phy)
 {
-	unsigned long finish = jiffies + 5 * HZ;
 	u8 val;
 
 	/* Waiting for Compensation to complete */
-	do {
-		val = readb_relaxed(miphy_phy->base + MIPHY_COMP_FSM_6);
-
-		if (time_after_eq(jiffies, finish))
-			return -EBUSY;
-		cpu_relax();
-	} while (!(val & COMP_DONE));
-
-	return 0;
+	return readb_relaxed_poll_timeout(miphy_phy->base + MIPHY_COMP_FSM_6,
+					  val, val & COMP_DONE, 1, 5 * USEC_PER_SEC);
 }
 
 
@@ -805,7 +798,6 @@
 
 static inline int miphy_is_ready(struct miphy28lp_phy *miphy_phy)
 {
-	unsigned long finish = jiffies + 5 * HZ;
 	u8 mask = HFC_PLL | HFC_RDY;
 	u8 val;
 
@@ -816,21 +808,14 @@
 	if (miphy_phy->type == PHY_TYPE_SATA)
 		mask |= PHY_RDY;
 
-	do {
-		val = readb_relaxed(miphy_phy->base + MIPHY_STATUS_1);
-		if ((val & mask) != mask)
-			cpu_relax();
-		else
-			return 0;
-	} while (!time_after_eq(jiffies, finish));
-
-	return -EBUSY;
+	return readb_relaxed_poll_timeout(miphy_phy->base + MIPHY_STATUS_1,
+					  val, (val & mask) == mask, 1,
+					  5 * USEC_PER_SEC);
 }
 
 static int miphy_osc_is_ready(struct miphy28lp_phy *miphy_phy)
 {
 	struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
-	unsigned long finish = jiffies + 5 * HZ;
 	u32 val;
 
 	if (!miphy_phy->osc_rdy)
@@ -839,17 +824,10 @@
 	if (!miphy_phy->syscfg_reg[SYSCFG_STATUS])
 		return -EINVAL;
 
-	do {
-		regmap_read(miphy_dev->regmap,
-				miphy_phy->syscfg_reg[SYSCFG_STATUS], &val);
-
-		if ((val & MIPHY_OSC_RDY) != MIPHY_OSC_RDY)
-			cpu_relax();
-		else
-			return 0;
-	} while (!time_after_eq(jiffies, finish));
-
-	return -EBUSY;
+	return regmap_read_poll_timeout(miphy_dev->regmap,
+					miphy_phy->syscfg_reg[SYSCFG_STATUS],
+					val, val & MIPHY_OSC_RDY, 1,
+					5 * USEC_PER_SEC);
 }
 
 static int miphy28lp_get_resource_byname(struct device_node *child,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/st/phy-stm32-usbphyc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/st/phy-stm32-usbphyc.c
@@ -393,6 +393,8 @@
 		ret = of_property_read_u32(child, "reg", &index);
 		if (ret || index > usbphyc->nphys) {
 			dev_err(&phy->dev, "invalid reg property: %d\n", ret);
+			if (!ret)
+				ret = -EINVAL;
 			goto put_child;
 		}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/tegra/xusb-tegra186.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/tegra/xusb-tegra186.c
@@ -415,6 +415,7 @@
 	unsigned int index = lane->index;
 	struct device *dev = padctl->dev;
 	int err;
+	u32 reg;
 
 	port = tegra_xusb_find_usb2_port(padctl, index);
 	if (!port) {
@@ -422,6 +423,16 @@
 		return -ENODEV;
 	}
 
+	if (port->mode == USB_DR_MODE_OTG ||
+	    port->mode == USB_DR_MODE_PERIPHERAL) {
+		/* reset VBUS&ID OVERRIDE */
+		reg = padctl_readl(padctl, USB2_VBUS_ID);
+		reg &= ~VBUS_OVERRIDE;
+		reg &= ~ID_OVERRIDE(~0);
+		reg |= ID_OVERRIDE_FLOATING;
+		padctl_writel(padctl, reg, USB2_VBUS_ID);
+	}
+
 	if (port->supply && port->mode == USB_DR_MODE_HOST) {
 		err = regulator_disable(port->supply);
 		if (err) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/tegra/xusb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/tegra/xusb.c
@@ -443,7 +443,7 @@
 	name = kasprintf(GFP_KERNEL, "%s-%u", type, index);
 	if (!name) {
 		of_node_put(ports);
-		return ERR_PTR(-ENOMEM);
+		return NULL;
 	}
 	np = of_get_child_by_name(ports, name);
 	kfree(name);
@@ -606,6 +606,7 @@
 	usb2->base.lane = usb2->base.ops->map(&usb2->base);
 	if (IS_ERR(usb2->base.lane)) {
 		err = PTR_ERR(usb2->base.lane);
+		tegra_xusb_port_unregister(&usb2->base);
 		goto out;
 	}
 
@@ -658,6 +659,7 @@
 	ulpi->base.lane = ulpi->base.ops->map(&ulpi->base);
 	if (IS_ERR(ulpi->base.lane)) {
 		err = PTR_ERR(ulpi->base.lane);
+		tegra_xusb_port_unregister(&ulpi->base);
 		goto out;
 	}
 
@@ -949,6 +951,7 @@
 reset:
 	reset_control_assert(padctl->rst);
 remove:
+	platform_set_drvdata(pdev, NULL);
 	soc->ops->remove(padctl);
 	return err;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/ti/phy-am654-serdes.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/ti/phy-am654-serdes.c
@@ -625,8 +625,10 @@
 	pm_runtime_enable(dev);
 
 	phy = devm_phy_create(dev, NULL, &ops);
-	if (IS_ERR(phy))
-		return PTR_ERR(phy);
+	if (IS_ERR(phy)) {
+		ret = PTR_ERR(phy);
+		goto clk_err;
+	}
 
 	phy_set_drvdata(phy, am654_phy);
 	phy_provider = devm_of_phy_provider_register(dev, serdes_am654_xlate);
@@ -639,7 +641,7 @@
 
 clk_err:
 	of_clk_del_provider(node);
-
+	pm_runtime_disable(dev);
 	return ret;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/ti/phy-dm816x-usb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/ti/phy-dm816x-usb.c
@@ -246,19 +246,28 @@
 
 	pm_runtime_enable(phy->dev);
 	generic_phy = devm_phy_create(phy->dev, NULL, &ops);
-	if (IS_ERR(generic_phy))
-		return PTR_ERR(generic_phy);
+	if (IS_ERR(generic_phy)) {
+		error = PTR_ERR(generic_phy);
+		goto clk_unprepare;
+	}
 
 	phy_set_drvdata(generic_phy, phy);
 
 	phy_provider = devm_of_phy_provider_register(phy->dev,
 						     of_phy_simple_xlate);
-	if (IS_ERR(phy_provider))
-		return PTR_ERR(phy_provider);
+	if (IS_ERR(phy_provider)) {
+		error = PTR_ERR(phy_provider);
+		goto clk_unprepare;
+	}
 
 	usb_add_phy_dev(&phy->phy);
 
 	return 0;
+
+clk_unprepare:
+	pm_runtime_disable(phy->dev);
+	clk_unprepare(phy->refclk);
+	return error;
 }
 
 static int dm816x_usb_phy_remove(struct platform_device *pdev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/ti/phy-gmii-sel.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/ti/phy-gmii-sel.c
@@ -69,31 +69,31 @@
 		break;
 
 	case PHY_INTERFACE_MODE_RGMII:
+	case PHY_INTERFACE_MODE_RGMII_RXID:
 		gmii_sel_mode = AM33XX_GMII_SEL_MODE_RGMII;
 		break;
 
 	case PHY_INTERFACE_MODE_RGMII_ID:
-	case PHY_INTERFACE_MODE_RGMII_RXID:
 	case PHY_INTERFACE_MODE_RGMII_TXID:
 		gmii_sel_mode = AM33XX_GMII_SEL_MODE_RGMII;
 		rgmii_id = 1;
 		break;
 
 	case PHY_INTERFACE_MODE_MII:
-		mode = AM33XX_GMII_SEL_MODE_MII;
+	case PHY_INTERFACE_MODE_GMII:
+		gmii_sel_mode = AM33XX_GMII_SEL_MODE_MII;
 		break;
 
 	default:
-		dev_warn(dev,
-			 "port%u: unsupported mode: \"%s\". Defaulting to MII.\n",
-			 if_phy->id, phy_modes(rgmii_id));
+		dev_warn(dev, "port%u: unsupported mode: \"%s\"\n",
+			 if_phy->id, phy_modes(submode));
 		return -EINVAL;
 	}
 
 	if_phy->phy_if_mode = submode;
 
 	dev_dbg(dev, "%s id:%u mode:%u rgmii_id:%d rmii_clk_ext:%d\n",
-		__func__, if_phy->id, mode, rgmii_id,
+		__func__, if_phy->id, submode, rgmii_id,
 		if_phy->rmii_clock_external);
 
 	regfield = if_phy->fields[PHY_GMII_SEL_PORT_MODE];
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/ti/phy-omap-usb2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/ti/phy-omap-usb2.c
@@ -58,7 +58,7 @@
 {
 	struct omap_usb *phy = phy_to_omapusb(otg->usb_phy);
 
-	if (!phy->comparator)
+	if (!phy->comparator || !phy->comparator->set_vbus)
 		return -ENODEV;
 
 	return phy->comparator->set_vbus(phy->comparator, enabled);
@@ -68,7 +68,7 @@
 {
 	struct omap_usb *phy = phy_to_omapusb(otg->usb_phy);
 
-	if (!phy->comparator)
+	if (!phy->comparator || !phy->comparator->start_srp)
 		return -ENODEV;
 
 	return phy->comparator->start_srp(phy->comparator);
@@ -157,7 +157,7 @@
 	return 0;
 
 err1:
-	clk_disable(phy->wkupclk);
+	clk_disable_unprepare(phy->wkupclk);
 
 err0:
 	return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/phy/ti/phy-twl4030-usb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/phy/ti/phy-twl4030-usb.c
@@ -779,7 +779,7 @@
 
 	usb_remove_phy(&twl->phy);
 	pm_runtime_get_sync(twl->dev);
-	cancel_delayed_work(&twl->id_workaround_work);
+	cancel_delayed_work_sync(&twl->id_workaround_work);
 	device_remove_file(twl->dev, &dev_attr_vbus);
 
 	/* set transceiver mode to power on defaults */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/Kconfig
@@ -372,6 +372,14 @@
 	help
 	  This selects the pinctrl driver for RK805.
 
+config PINCTRL_ZYNQMP
+	bool "Pinctrl driver for Xilinx ZynqMP"
+	depends on ARCH_ZYNQMP
+	select PINMUX
+	select GENERIC_PINCONF
+	help
+	  This selects the pinctrl driver for Xilinx ZynqMP.
+
 config PINCTRL_OCELOT
 	bool "Pinctrl driver for the Microsemi Ocelot and Jaguar2 SoCs"
 	depends on OF
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/Makefile
@@ -45,6 +45,7 @@
 obj-$(CONFIG_PINCTRL_ZYNQ)	+= pinctrl-zynq.o
 obj-$(CONFIG_PINCTRL_INGENIC)	+= pinctrl-ingenic.o
 obj-$(CONFIG_PINCTRL_RK805)	+= pinctrl-rk805.o
+obj-$(CONFIG_PINCTRL_ZYNQMP)	+= pinctrl-zynqmp.o
 obj-$(CONFIG_PINCTRL_OCELOT)	+= pinctrl-ocelot.o
 
 obj-y				+= actions/
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c
@@ -334,7 +334,7 @@
 
 #define D22 40
 SIG_EXPR_LIST_DECL_SESG(D22, SD1CLK, SD1, SIG_DESC_SET(SCU414, 8));
-SIG_EXPR_LIST_DECL_SEMG(D22, PWM8, PWM8G0, PWM8, SIG_DESC_SET(SCU414, 8));
+SIG_EXPR_LIST_DECL_SEMG(D22, PWM8, PWM8G0, PWM8, SIG_DESC_SET(SCU4B4, 8));
 PIN_DECL_2(D22, GPIOF0, SD1CLK, PWM8);
 GROUP_DECL(PWM8G0, D22);
 
@@ -1088,60 +1088,52 @@
 
 #define AB7 176
 SIG_EXPR_LIST_DECL_SESG(AB7, LAD0, LPC, SIG_DESC_SET(SCU434, 16),
-			  SIG_DESC_CLEAR(SCU510, 6));
-SIG_EXPR_LIST_DECL_SESG(AB7, ESPID0, ESPI, SIG_DESC_SET(SCU434, 16),
 			  SIG_DESC_SET(SCU510, 6));
+SIG_EXPR_LIST_DECL_SESG(AB7, ESPID0, ESPI, SIG_DESC_SET(SCU434, 16));
 PIN_DECL_2(AB7, GPIOW0, LAD0, ESPID0);
 
 #define AB8 177
 SIG_EXPR_LIST_DECL_SESG(AB8, LAD1, LPC, SIG_DESC_SET(SCU434, 17),
-			  SIG_DESC_CLEAR(SCU510, 6));
-SIG_EXPR_LIST_DECL_SESG(AB8, ESPID1, ESPI, SIG_DESC_SET(SCU434, 17),
 			  SIG_DESC_SET(SCU510, 6));
+SIG_EXPR_LIST_DECL_SESG(AB8, ESPID1, ESPI, SIG_DESC_SET(SCU434, 17));
 PIN_DECL_2(AB8, GPIOW1, LAD1, ESPID1);
 
 #define AC8 178
 SIG_EXPR_LIST_DECL_SESG(AC8, LAD2, LPC, SIG_DESC_SET(SCU434, 18),
-			  SIG_DESC_CLEAR(SCU510, 6));
-SIG_EXPR_LIST_DECL_SESG(AC8, ESPID2, ESPI, SIG_DESC_SET(SCU434, 18),
 			  SIG_DESC_SET(SCU510, 6));
+SIG_EXPR_LIST_DECL_SESG(AC8, ESPID2, ESPI, SIG_DESC_SET(SCU434, 18));
 PIN_DECL_2(AC8, GPIOW2, LAD2, ESPID2);
 
 #define AC7 179
 SIG_EXPR_LIST_DECL_SESG(AC7, LAD3, LPC, SIG_DESC_SET(SCU434, 19),
-			  SIG_DESC_CLEAR(SCU510, 6));
-SIG_EXPR_LIST_DECL_SESG(AC7, ESPID3, ESPI, SIG_DESC_SET(SCU434, 19),
 			  SIG_DESC_SET(SCU510, 6));
+SIG_EXPR_LIST_DECL_SESG(AC7, ESPID3, ESPI, SIG_DESC_SET(SCU434, 19));
 PIN_DECL_2(AC7, GPIOW3, LAD3, ESPID3);
 
 #define AE7 180
 SIG_EXPR_LIST_DECL_SESG(AE7, LCLK, LPC, SIG_DESC_SET(SCU434, 20),
-			  SIG_DESC_CLEAR(SCU510, 6));
-SIG_EXPR_LIST_DECL_SESG(AE7, ESPICK, ESPI, SIG_DESC_SET(SCU434, 20),
 			  SIG_DESC_SET(SCU510, 6));
+SIG_EXPR_LIST_DECL_SESG(AE7, ESPICK, ESPI, SIG_DESC_SET(SCU434, 20));
 PIN_DECL_2(AE7, GPIOW4, LCLK, ESPICK);
 
 #define AF7 181
 SIG_EXPR_LIST_DECL_SESG(AF7, LFRAME, LPC, SIG_DESC_SET(SCU434, 21),
-			  SIG_DESC_CLEAR(SCU510, 6));
-SIG_EXPR_LIST_DECL_SESG(AF7, ESPICS, ESPI, SIG_DESC_SET(SCU434, 21),
 			  SIG_DESC_SET(SCU510, 6));
+SIG_EXPR_LIST_DECL_SESG(AF7, ESPICS, ESPI, SIG_DESC_SET(SCU434, 21));
 PIN_DECL_2(AF7, GPIOW5, LFRAME, ESPICS);
 
 #define AD7 182
 SIG_EXPR_LIST_DECL_SESG(AD7, LSIRQ, LSIRQ, SIG_DESC_SET(SCU434, 22),
-			  SIG_DESC_CLEAR(SCU510, 6));
-SIG_EXPR_LIST_DECL_SESG(AD7, ESPIALT, ESPIALT, SIG_DESC_SET(SCU434, 22),
 			  SIG_DESC_SET(SCU510, 6));
+SIG_EXPR_LIST_DECL_SESG(AD7, ESPIALT, ESPIALT, SIG_DESC_SET(SCU434, 22));
 PIN_DECL_2(AD7, GPIOW6, LSIRQ, ESPIALT);
 FUNC_GROUP_DECL(LSIRQ, AD7);
 FUNC_GROUP_DECL(ESPIALT, AD7);
 
 #define AD8 183
 SIG_EXPR_LIST_DECL_SESG(AD8, LPCRST, LPC, SIG_DESC_SET(SCU434, 23),
-			  SIG_DESC_CLEAR(SCU510, 6));
-SIG_EXPR_LIST_DECL_SESG(AD8, ESPIRST, ESPI, SIG_DESC_SET(SCU434, 23),
 			  SIG_DESC_SET(SCU510, 6));
+SIG_EXPR_LIST_DECL_SESG(AD8, ESPIRST, ESPI, SIG_DESC_SET(SCU434, 23));
 PIN_DECL_2(AD8, GPIOW7, LPCRST, ESPIRST);
 
 FUNC_GROUP_DECL(LPC, AB7, AB8, AC8, AC7, AE7, AF7, AD8);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/aspeed/pinctrl-aspeed.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/aspeed/pinctrl-aspeed.c
@@ -115,7 +115,7 @@
 	int ret = 0;
 
 	if (!exprs)
-		return true;
+		return -EINVAL;
 
 	while (*exprs && !ret) {
 		ret = aspeed_sig_expr_disable(ctx, *exprs);
@@ -277,13 +277,76 @@
 static bool aspeed_expr_is_gpio(const struct aspeed_sig_expr *expr)
 {
 	/*
-	 * The signal type is GPIO if the signal name has "GPIO" as a prefix.
-	 * strncmp (rather than strcmp) is used to implement the prefix
-	 * requirement.
+	 * We need to differentiate between GPIO and non-GPIO signals to
+	 * implement the gpio_request_enable() interface. For better or worse
+	 * the ASPEED pinctrl driver uses the expression names to determine
+	 * whether an expression will mux a pin for GPIO.
 	 *
-	 * expr->signal might look like "GPIOT3" in the GPIO case.
+	 * Generally we have the following - A GPIO such as B1 has:
+	 *
+	 *    - expr->signal set to "GPIOB1"
+	 *    - expr->function set to "GPIOB1"
+	 *
+	 * Using this fact we can determine whether the provided expression is
+	 * a GPIO expression by testing the signal name for the string prefix
+	 * "GPIO".
+	 *
+	 * However, some GPIOs are input-only, and the ASPEED datasheets name
+	 * them differently. An input-only GPIO such as T0 has:
+	 *
+	 *    - expr->signal set to "GPIT0"
+	 *    - expr->function set to "GPIT0"
+	 *
+	 * It's tempting to generalise the prefix test from "GPIO" to "GPI" to
+	 * account for both GPIOs and GPIs, but in doing so we run aground on
+	 * another feature:
+	 *
+	 * Some pins in the ASPEED BMC SoCs have a "pass-through" GPIO
+	 * function where the input state of one pin is replicated as the
+	 * output state of another (as if they were shorted together - a mux
+	 * configuration that is typically enabled by hardware strapping).
+	 * This feature allows the BMC to pass e.g. power button state through
+	 * to the host while the BMC is yet to boot, but take control of the
+	 * button state once the BMC has booted by muxing each pin as a
+	 * separate, pin-specific GPIO.
+	 *
+	 * Conceptually this pass-through mode is a form of GPIO and is named
+	 * as such in the datasheets, e.g. "GPID0". This naming similarity
+	 * trips us up with the simple GPI-prefixed-signal-name scheme
+	 * discussed above, as the pass-through configuration is not what we
+	 * want when muxing a pin as GPIO for the GPIO subsystem.
+	 *
+	 * On e.g. the AST2400, a pass-through function "GPID0" is grouped on
+	 * balls A18 and D16, where we have:
+	 *
+	 *    For ball A18:
+	 *    - expr->signal set to "GPID0IN"
+	 *    - expr->function set to "GPID0"
+	 *
+	 *    For ball D16:
+	 *    - expr->signal set to "GPID0OUT"
+	 *    - expr->function set to "GPID0"
+	 *
+	 * By contrast, the pin-specific GPIO expressions for the same pins are
+	 * as follows:
+	 *
+	 *    For ball A18:
+	 *    - expr->signal looks like "GPIOD0"
+	 *    - expr->function looks like "GPIOD0"
+	 *
+	 *    For ball D16:
+	 *    - expr->signal looks like "GPIOD1"
+	 *    - expr->function looks like "GPIOD1"
+	 *
+	 * Testing both the signal _and_ function names gives us the means
+	 * differentiate the pass-through GPIO pinmux configuration from the
+	 * pin-specific configuration that the GPIO subsystem is after: An
+	 * expression is a pin-specific (non-pass-through) GPIO configuration
+	 * if the signal prefix is "GPI" and the signal name matches the
+	 * function name.
 	 */
-	return strncmp(expr->signal, "GPIO", 4) == 0;
+	return !strncmp(expr->signal, "GPI", 3) &&
+			!strcmp(expr->signal, expr->function);
 }
 
 static bool aspeed_gpio_in_exprs(const struct aspeed_sig_expr **exprs)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/aspeed/pinmux-aspeed.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/aspeed/pinmux-aspeed.h
@@ -452,10 +452,11 @@
  * evaluation of the descriptors.
  *
  * @signal: The signal name for the priority level on the pin. If the signal
- *          type is GPIO, then the signal name must begin with the string
- *          "GPIO", e.g. GPIOA0, GPIOT4 etc.
+ *          type is GPIO, then the signal name must begin with the
+ *          prefix "GPI", e.g. GPIOA0, GPIT0 etc.
  * @function: The name of the function the signal participates in for the
- *            associated expression
+ *            associated expression. For pin-specific GPIO, the function
+ *            name must match the signal name.
  * @ndescs: The number of signal descriptors in the expression
  * @descs: Pointer to an array of signal descriptors that comprise the
  *         function expression
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/bcm/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/bcm/Kconfig
@@ -23,6 +23,7 @@
 	select PINMUX
 	select PINCONF
 	select GENERIC_PINCONF
+	select GPIOLIB
 	select GPIOLIB_IRQCHIP
 	default ARCH_BCM2835 || ARCH_BRCMSTB
 	help
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/bcm/pinctrl-bcm281xx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/bcm/pinctrl-bcm281xx.c
@@ -981,7 +981,7 @@
 	.reg_bits = 32,
 	.reg_stride = 4,
 	.val_bits = 32,
-	.max_register = BCM281XX_PIN_VC_CAM3_SDA,
+	.max_register = BCM281XX_PIN_VC_CAM3_SDA * 4,
 };
 
 static int bcm281xx_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/bcm/pinctrl-bcm2835.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/bcm/pinctrl-bcm2835.c
@@ -19,6 +19,7 @@
 #include <linux/irq.h>
 #include <linux/irqdesc.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/of_address.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
@@ -37,12 +38,10 @@
 
 #define MODULE_NAME "pinctrl-bcm2835"
 #define BCM2835_NUM_GPIOS 54
+#define BCM2711_NUM_GPIOS 58
 #define BCM2835_NUM_BANKS 2
 #define BCM2835_NUM_IRQS  3
 
-#define BCM2835_PIN_BITMAP_SZ \
-	DIV_ROUND_UP(BCM2835_NUM_GPIOS, sizeof(unsigned long) * 8)
-
 /* GPIO register offsets */
 #define GPFSEL0		0x0	/* Function Select */
 #define GPSET0		0x1c	/* Pin Output Set */
@@ -78,13 +77,15 @@
 struct bcm2835_pinctrl {
 	struct device *dev;
 	void __iomem *base;
+	int *wake_irq;
 
 	/* note: locking assumes each bank will have its own unsigned long */
 	unsigned long enabled_irq_map[BCM2835_NUM_BANKS];
-	unsigned int irq_type[BCM2835_NUM_GPIOS];
+	unsigned int irq_type[BCM2711_NUM_GPIOS];
 
 	struct pinctrl_dev *pctl_dev;
 	struct gpio_chip gpio_chip;
+	struct pinctrl_desc pctl_desc;
 	struct pinctrl_gpio_range gpio_range;
 
 	raw_spinlock_t irq_lock[BCM2835_NUM_BANKS];
@@ -147,6 +148,10 @@
 	BCM2835_GPIO_PIN(51),
 	BCM2835_GPIO_PIN(52),
 	BCM2835_GPIO_PIN(53),
+	BCM2835_GPIO_PIN(54),
+	BCM2835_GPIO_PIN(55),
+	BCM2835_GPIO_PIN(56),
+	BCM2835_GPIO_PIN(57),
 };
 
 /* one pin per group */
@@ -205,6 +210,10 @@
 	"gpio51",
 	"gpio52",
 	"gpio53",
+	"gpio54",
+	"gpio55",
+	"gpio56",
+	"gpio57",
 };
 
 enum bcm2835_fsel {
@@ -355,6 +364,22 @@
 	.can_sleep = false,
 };
 
+static const struct gpio_chip bcm2711_gpio_chip = {
+	.label = "pinctrl-bcm2711",
+	.owner = THIS_MODULE,
+	.request = gpiochip_generic_request,
+	.free = gpiochip_generic_free,
+	.direction_input = bcm2835_gpio_direction_input,
+	.direction_output = bcm2835_gpio_direction_output,
+	.get_direction = bcm2835_gpio_get_direction,
+	.get = bcm2835_gpio_get,
+	.set = bcm2835_gpio_set,
+	.set_config = gpiochip_generic_config,
+	.base = -1,
+	.ngpio = BCM2711_NUM_GPIOS,
+	.can_sleep = false,
+};
+
 static void bcm2835_gpio_irq_handle_bank(struct bcm2835_pinctrl *pc,
 					 unsigned int bank, u32 mask)
 {
@@ -401,7 +426,7 @@
 		bcm2835_gpio_irq_handle_bank(pc, 0, 0xf0000000);
 		bcm2835_gpio_irq_handle_bank(pc, 1, 0x00003fff);
 		break;
-	case 2: /* IRQ2 covers GPIOs 46-53 */
+	case 2: /* IRQ2 covers GPIOs 46-57 */
 		bcm2835_gpio_irq_handle_bank(pc, 1, 0x003fc000);
 		break;
 	}
@@ -409,6 +434,11 @@
 	chained_irq_exit(host_chip, desc);
 }
 
+static irqreturn_t bcm2835_gpio_wake_irq_handler(int irq, void *dev_id)
+{
+	return IRQ_HANDLED;
+}
+
 static inline void __bcm2835_gpio_irq_config(struct bcm2835_pinctrl *pc,
 	unsigned reg, unsigned offset, bool enable)
 {
@@ -608,6 +638,34 @@
 	bcm2835_gpio_set_bit(pc, GPEDS0, gpio);
 }
 
+static int bcm2835_gpio_irq_set_wake(struct irq_data *data, unsigned int on)
+{
+	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
+	struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
+	unsigned gpio = irqd_to_hwirq(data);
+	unsigned int irqgroup;
+	int ret = -EINVAL;
+
+	if (!pc->wake_irq)
+		return ret;
+
+	if (gpio <= 27)
+		irqgroup = 0;
+	else if (gpio >= 28 && gpio <= 45)
+		irqgroup = 1;
+	else if (gpio >= 46 && gpio <= 57)
+		irqgroup = 2;
+	else
+		return ret;
+
+	if (on)
+		ret = enable_irq_wake(pc->wake_irq[irqgroup]);
+	else
+		ret = disable_irq_wake(pc->wake_irq[irqgroup]);
+
+	return ret;
+}
+
 static struct irq_chip bcm2835_gpio_irq_chip = {
 	.name = MODULE_NAME,
 	.irq_enable = bcm2835_gpio_irq_enable,
@@ -616,11 +674,13 @@
 	.irq_ack = bcm2835_gpio_irq_ack,
 	.irq_mask = bcm2835_gpio_irq_disable,
 	.irq_unmask = bcm2835_gpio_irq_enable,
+	.irq_set_wake = bcm2835_gpio_irq_set_wake,
+	.flags = IRQCHIP_MASK_ON_SUSPEND,
 };
 
 static int bcm2835_pctl_get_groups_count(struct pinctrl_dev *pctldev)
 {
-	return ARRAY_SIZE(bcm2835_gpio_groups);
+	return BCM2835_NUM_GPIOS;
 }
 
 static const char *bcm2835_pctl_get_group_name(struct pinctrl_dev *pctldev,
@@ -778,7 +838,7 @@
 		err = of_property_read_u32_index(np, "brcm,pins", i, &pin);
 		if (err)
 			goto out;
-		if (pin >= ARRAY_SIZE(bcm2835_gpio_pins)) {
+		if (pin >= pc->pctl_desc.npins) {
 			dev_err(pc->dev, "%pOF: invalid brcm,pins value %d\n",
 				np, pin);
 			err = -EINVAL;
@@ -854,7 +914,7 @@
 {
 	/* every pin can do every function */
 	*groups = bcm2835_gpio_groups;
-	*num_groups = ARRAY_SIZE(bcm2835_gpio_groups);
+	*num_groups = BCM2835_NUM_GPIOS;
 
 	return 0;
 }
@@ -1054,29 +1114,66 @@
 	.pin_config_set = bcm2711_pinconf_set,
 };
 
-static struct pinctrl_desc bcm2835_pinctrl_desc = {
+static const struct pinctrl_desc bcm2835_pinctrl_desc = {
 	.name = MODULE_NAME,
 	.pins = bcm2835_gpio_pins,
-	.npins = ARRAY_SIZE(bcm2835_gpio_pins),
+	.npins = BCM2835_NUM_GPIOS,
 	.pctlops = &bcm2835_pctl_ops,
 	.pmxops = &bcm2835_pmx_ops,
 	.confops = &bcm2835_pinconf_ops,
 	.owner = THIS_MODULE,
 };
 
-static struct pinctrl_gpio_range bcm2835_pinctrl_gpio_range = {
+static const struct pinctrl_desc bcm2711_pinctrl_desc = {
+	.name = "pinctrl-bcm2711",
+	.pins = bcm2835_gpio_pins,
+	.npins = BCM2711_NUM_GPIOS,
+	.pctlops = &bcm2835_pctl_ops,
+	.pmxops = &bcm2835_pmx_ops,
+	.confops = &bcm2711_pinconf_ops,
+	.owner = THIS_MODULE,
+};
+
+static const struct pinctrl_gpio_range bcm2835_pinctrl_gpio_range = {
 	.name = MODULE_NAME,
 	.npins = BCM2835_NUM_GPIOS,
 };
 
+static const struct pinctrl_gpio_range bcm2711_pinctrl_gpio_range = {
+	.name = "pinctrl-bcm2711",
+	.npins = BCM2711_NUM_GPIOS,
+};
+
+struct bcm_plat_data {
+	const struct gpio_chip *gpio_chip;
+	const struct pinctrl_desc *pctl_desc;
+	const struct pinctrl_gpio_range *gpio_range;
+};
+
+static const struct bcm_plat_data bcm2835_plat_data = {
+	.gpio_chip = &bcm2835_gpio_chip,
+	.pctl_desc = &bcm2835_pinctrl_desc,
+	.gpio_range = &bcm2835_pinctrl_gpio_range,
+};
+
+static const struct bcm_plat_data bcm2711_plat_data = {
+	.gpio_chip = &bcm2711_gpio_chip,
+	.pctl_desc = &bcm2711_pinctrl_desc,
+	.gpio_range = &bcm2711_pinctrl_gpio_range,
+};
+
 static const struct of_device_id bcm2835_pinctrl_match[] = {
 	{
 		.compatible = "brcm,bcm2835-gpio",
-		.data = &bcm2835_pinconf_ops,
+		.data = &bcm2835_plat_data,
 	},
 	{
 		.compatible = "brcm,bcm2711-gpio",
-		.data = &bcm2711_pinconf_ops,
+		.data = &bcm2711_plat_data,
+	},
+	{
+		.compatible = "brcm,bcm7211-gpio",
+		.data = &bcm2711_plat_data,
 	},
 	{}
 };
@@ -1085,14 +1182,16 @@
 {
 	struct device *dev = &pdev->dev;
 	struct device_node *np = dev->of_node;
+	const struct bcm_plat_data *pdata;
 	struct bcm2835_pinctrl *pc;
 	struct gpio_irq_chip *girq;
 	struct resource iomem;
 	int err, i;
 	const struct of_device_id *match;
+	int is_7211 = 0;
 
-	BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_pins) != BCM2835_NUM_GPIOS);
-	BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_groups) != BCM2835_NUM_GPIOS);
+	BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_pins) != BCM2711_NUM_GPIOS);
+	BUILD_BUG_ON(ARRAY_SIZE(bcm2835_gpio_groups) != BCM2711_NUM_GPIOS);
 
 	pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL);
 	if (!pc)
@@ -1111,7 +1210,14 @@
 	if (IS_ERR(pc->base))
 		return PTR_ERR(pc->base);
 
-	pc->gpio_chip = bcm2835_gpio_chip;
+	match = of_match_node(bcm2835_pinctrl_match, pdev->dev.of_node);
+	if (!match)
+		return -EINVAL;
+
+	pdata = match->data;
+	is_7211 = of_device_is_compatible(np, "brcm,bcm7211-gpio");
+
+	pc->gpio_chip = *pdata->gpio_chip;
 	pc->gpio_chip.parent = dev;
 	pc->gpio_chip.of_node = np;
 
@@ -1135,6 +1241,18 @@
 		raw_spin_lock_init(&pc->irq_lock[i]);
 	}
 
+	pc->pctl_desc = *pdata->pctl_desc;
+	pc->pctl_dev = devm_pinctrl_register(dev, &pc->pctl_desc, pc);
+	if (IS_ERR(pc->pctl_dev)) {
+		gpiochip_remove(&pc->gpio_chip);
+		return PTR_ERR(pc->pctl_dev);
+	}
+
+	pc->gpio_range = *pdata->gpio_range;
+	pc->gpio_range.base = pc->gpio_chip.base;
+	pc->gpio_range.gc = &pc->gpio_chip;
+	pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range);
+
 	girq = &pc->gpio_chip.irq;
 	girq->chip = &bcm2835_gpio_irq_chip;
 	girq->parent_handler = bcm2835_gpio_irq_handler;
@@ -1142,8 +1260,21 @@
 	girq->parents = devm_kcalloc(dev, BCM2835_NUM_IRQS,
 				     sizeof(*girq->parents),
 				     GFP_KERNEL);
-	if (!girq->parents)
-		return -ENOMEM;
+	if (!girq->parents) {
+		err = -ENOMEM;
+		goto out_remove;
+	}
+
+	if (is_7211) {
+		pc->wake_irq = devm_kcalloc(dev, BCM2835_NUM_IRQS,
+					    sizeof(*pc->wake_irq),
+					    GFP_KERNEL);
+		if (!pc->wake_irq) {
+			err = -ENOMEM;
+			goto out_remove;
+		}
+	}
+
 	/*
 	 * Use the same handler for all groups: this is necessary
 	 * since we use one gpiochip to cover all lines - the
@@ -1151,35 +1282,50 @@
 	 * bank that was firing the IRQ and look up the per-group
 	 * and bank data.
 	 */
-	for (i = 0; i < BCM2835_NUM_IRQS; i++)
+	for (i = 0; i < BCM2835_NUM_IRQS; i++) {
+		int len;
+		char *name;
+
 		girq->parents[i] = irq_of_parse_and_map(np, i);
+		if (!is_7211)
+			continue;
+
+		/* Skip over the all banks interrupts */
+		pc->wake_irq[i] = irq_of_parse_and_map(np, i +
+						       BCM2835_NUM_IRQS + 1);
+
+		len = strlen(dev_name(pc->dev)) + 16;
+		name = devm_kzalloc(pc->dev, len, GFP_KERNEL);
+		if (!name) {
+			err = -ENOMEM;
+			goto out_remove;
+		}
+
+		snprintf(name, len, "%s:bank%d", dev_name(pc->dev), i);
+
+		/* These are optional interrupts */
+		err = devm_request_irq(dev, pc->wake_irq[i],
+				       bcm2835_gpio_wake_irq_handler,
+				       IRQF_SHARED, name, pc);
+		if (err)
+			dev_warn(dev, "unable to request wake IRQ %d\n",
+				 pc->wake_irq[i]);
+	}
+
 	girq->default_type = IRQ_TYPE_NONE;
 	girq->handler = handle_level_irq;
 
 	err = gpiochip_add_data(&pc->gpio_chip, pc);
 	if (err) {
 		dev_err(dev, "could not add GPIO chip\n");
-		return err;
-	}
-
-	match = of_match_node(bcm2835_pinctrl_match, pdev->dev.of_node);
-	if (match) {
-		bcm2835_pinctrl_desc.confops =
-			(const struct pinconf_ops *)match->data;
+		goto out_remove;
 	}
 
-	pc->pctl_dev = devm_pinctrl_register(dev, &bcm2835_pinctrl_desc, pc);
-	if (IS_ERR(pc->pctl_dev)) {
-		gpiochip_remove(&pc->gpio_chip);
-		return PTR_ERR(pc->pctl_dev);
-	}
-
-	pc->gpio_range = bcm2835_pinctrl_gpio_range;
-	pc->gpio_range.base = pc->gpio_chip.base;
-	pc->gpio_range.gc = &pc->gpio_chip;
-	pinctrl_add_gpio_range(pc->pctl_dev, &pc->gpio_range);
-
 	return 0;
+
+out_remove:
+	pinctrl_remove_gpio_range(pc->pctl_dev, &pc->gpio_range);
+	return err;
 }
 
 static struct platform_driver bcm2835_pinctrl_driver = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/bcm/pinctrl-ns.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/bcm/pinctrl-ns.c
@@ -5,7 +5,6 @@
 
 #include <linux/err.h>
 #include <linux/io.h>
-#include <linux/mfd/syscon.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -13,7 +12,6 @@
 #include <linux/pinctrl/pinctrl.h>
 #include <linux/pinctrl/pinmux.h>
 #include <linux/platform_device.h>
-#include <linux/regmap.h>
 #include <linux/slab.h>
 
 #define FLAG_BCM4708		BIT(1)
@@ -24,8 +22,7 @@
 	struct device *dev;
 	unsigned int chipset_flag;
 	struct pinctrl_dev *pctldev;
-	struct regmap *regmap;
-	u32 offset;
+	void __iomem *base;
 
 	struct pinctrl_desc pctldesc;
 	struct ns_pinctrl_group *groups;
@@ -232,9 +229,9 @@
 		unset |= BIT(pin_number);
 	}
 
-	regmap_read(ns_pinctrl->regmap, ns_pinctrl->offset, &tmp);
+	tmp = readl(ns_pinctrl->base);
 	tmp &= ~unset;
-	regmap_write(ns_pinctrl->regmap, ns_pinctrl->offset, tmp);
+	writel(tmp, ns_pinctrl->base);
 
 	return 0;
 }
@@ -266,13 +263,13 @@
 static int ns_pinctrl_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
-	struct device_node *np = dev->of_node;
 	const struct of_device_id *of_id;
 	struct ns_pinctrl *ns_pinctrl;
 	struct pinctrl_desc *pctldesc;
 	struct pinctrl_pin_desc *pin;
 	struct ns_pinctrl_group *group;
 	struct ns_pinctrl_function *function;
+	struct resource *res;
 	int i;
 
 	ns_pinctrl = devm_kzalloc(dev, sizeof(*ns_pinctrl), GFP_KERNEL);
@@ -290,18 +287,12 @@
 		return -EINVAL;
 	ns_pinctrl->chipset_flag = (uintptr_t)of_id->data;
 
-	ns_pinctrl->regmap = syscon_node_to_regmap(of_get_parent(np));
-	if (IS_ERR(ns_pinctrl->regmap)) {
-		int err = PTR_ERR(ns_pinctrl->regmap);
-
-		dev_err(dev, "Failed to map pinctrl regs: %d\n", err);
-
-		return err;
-	}
-
-	if (of_property_read_u32(np, "offset", &ns_pinctrl->offset)) {
-		dev_err(dev, "Failed to get register offset\n");
-		return -ENOENT;
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+					   "cru_gpio_control");
+	ns_pinctrl->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(ns_pinctrl->base)) {
+		dev_err(dev, "Failed to map pinctrl regs\n");
+		return PTR_ERR(ns_pinctrl->base);
 	}
 
 	memcpy(pctldesc, &ns_pinctrl_desc, sizeof(*pctldesc));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/cirrus/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/cirrus/Kconfig
@@ -1,7 +1,9 @@
 # SPDX-License-Identifier: GPL-2.0-only
 config PINCTRL_LOCHNAGAR
 	tristate "Cirrus Logic Lochnagar pinctrl driver"
-	depends on MFD_LOCHNAGAR
+	# Avoid clash caused by MIPS defining RST, which is used in the driver
+	depends on MFD_LOCHNAGAR && !MIPS
+	select GPIOLIB
 	select PINMUX
 	select PINCONF
 	select GENERIC_PINCONF
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/core.c
@@ -203,6 +203,7 @@
 				    const struct pinctrl_pin_desc *pin)
 {
 	struct pin_desc *pindesc;
+	int error;
 
 	pindesc = pin_desc_get(pctldev, pin->number);
 	if (pindesc) {
@@ -224,18 +225,25 @@
 	} else {
 		pindesc->name = kasprintf(GFP_KERNEL, "PIN%u", pin->number);
 		if (!pindesc->name) {
-			kfree(pindesc);
-			return -ENOMEM;
+			error = -ENOMEM;
+			goto failed;
 		}
 		pindesc->dynamic_name = true;
 	}
 
 	pindesc->drv_data = pin->drv_data;
 
-	radix_tree_insert(&pctldev->pin_desc_tree, pin->number, pindesc);
+	error = radix_tree_insert(&pctldev->pin_desc_tree, pin->number, pindesc);
+	if (error)
+		goto failed;
+
 	pr_debug("registered pin %d (%s) on %s\n",
 		 pin->number, pindesc->name, pctldev->desc->name);
 	return 0;
+
+failed:
+	kfree(pindesc);
+	return error;
 }
 
 static int pinctrl_register_pins(struct pinctrl_dev *pctldev,
@@ -1082,8 +1090,8 @@
 		 * an -EPROBE_DEFER later, as that is the worst case.
 		 */
 		if (ret == -EPROBE_DEFER) {
-			pinctrl_free(p, false);
 			mutex_unlock(&pinctrl_maps_mutex);
+			pinctrl_free(p, false);
 			return ERR_PTR(ret);
 		}
 	}
@@ -1237,17 +1245,17 @@
 static int pinctrl_commit_state(struct pinctrl *p, struct pinctrl_state *state)
 {
 	struct pinctrl_setting *setting, *setting2;
-	struct pinctrl_state *old_state = p->state;
+	struct pinctrl_state *old_state = READ_ONCE(p->state);
 	int ret;
 
-	if (p->state) {
+	if (old_state) {
 		/*
 		 * For each pinmux setting in the old state, forget SW's record
 		 * of mux owner for that pingroup. Any pingroups which are
 		 * still owned by the new state will be re-acquired by the call
 		 * to pinmux_enable_setting() in the loop below.
 		 */
-		list_for_each_entry(setting, &p->state->settings, node) {
+		list_for_each_entry(setting, &old_state->settings, node) {
 			if (setting->type != PIN_MAP_TYPE_MUX_GROUP)
 				continue;
 			pinmux_disable_setting(setting);
@@ -1256,7 +1264,7 @@
 
 	p->state = NULL;
 
-	/* Apply all the settings for the new state */
+	/* Apply all the settings for the new state - pinmux first */
 	list_for_each_entry(setting, &state->settings, node) {
 		switch (setting->type) {
 		case PIN_MAP_TYPE_MUX_GROUP:
@@ -1264,6 +1272,27 @@
 			break;
 		case PIN_MAP_TYPE_CONFIGS_PIN:
 		case PIN_MAP_TYPE_CONFIGS_GROUP:
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+		}
+
+		if (ret < 0)
+			goto unapply_new_state;
+
+		/* Do not link hogs (circular dependency) */
+		if (p != setting->pctldev->p)
+			pinctrl_link_add(setting->pctldev, p->dev);
+	}
+
+	/* Apply all the settings for the new state - pinconf after */
+	list_for_each_entry(setting, &state->settings, node) {
+		switch (setting->type) {
+		case PIN_MAP_TYPE_MUX_GROUP:
+			break;
+		case PIN_MAP_TYPE_CONFIGS_PIN:
+		case PIN_MAP_TYPE_CONFIGS_GROUP:
 			ret = pinconf_apply_setting(setting);
 			break;
 		default:
@@ -2009,6 +2038,14 @@
 	return ERR_PTR(ret);
 }
 
+static void pinctrl_uninit_controller(struct pinctrl_dev *pctldev, struct pinctrl_desc *pctldesc)
+{
+	pinctrl_free_pindescs(pctldev, pctldesc->pins,
+			      pctldesc->npins);
+	mutex_destroy(&pctldev->mutex);
+	kfree(pctldev);
+}
+
 static int pinctrl_claim_hogs(struct pinctrl_dev *pctldev)
 {
 	pctldev->p = create_pinctrl(pctldev->dev, pctldev);
@@ -2025,7 +2062,6 @@
 		return PTR_ERR(pctldev->p);
 	}
 
-	kref_get(&pctldev->p->users);
 	pctldev->hog_default =
 		pinctrl_lookup_state(pctldev->p, PINCTRL_STATE_DEFAULT);
 	if (IS_ERR(pctldev->hog_default)) {
@@ -2054,11 +2090,7 @@
 
 	error = pinctrl_claim_hogs(pctldev);
 	if (error) {
-		dev_err(pctldev->dev, "could not claim hogs: %i\n",
-			error);
-		mutex_destroy(&pctldev->mutex);
-		kfree(pctldev);
-
+		dev_err(pctldev->dev, "could not claim hogs: %i\n", error);
 		return error;
 	}
 
@@ -2094,8 +2126,10 @@
 		return pctldev;
 
 	error = pinctrl_enable(pctldev);
-	if (error)
+	if (error) {
+		pinctrl_uninit_controller(pctldev, pctldesc);
 		return ERR_PTR(error);
+	}
 
 	return pctldev;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/devicetree.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/devicetree.c
@@ -29,6 +29,13 @@
 static void dt_free_map(struct pinctrl_dev *pctldev,
 		     struct pinctrl_map *map, unsigned num_maps)
 {
+	int i;
+
+	for (i = 0; i < num_maps; ++i) {
+		kfree_const(map[i].dev_name);
+		map[i].dev_name = NULL;
+	}
+
 	if (pctldev) {
 		const struct pinctrl_ops *ops = pctldev->desc->pctlops;
 		if (ops->dt_free_map)
@@ -63,7 +70,13 @@
 
 	/* Initialize common mapping table entry fields */
 	for (i = 0; i < num_maps; i++) {
-		map[i].dev_name = dev_name(p->dev);
+		const char *devname;
+
+		devname = kstrdup_const(dev_name(p->dev), GFP_KERNEL);
+		if (!devname)
+			goto err_free_map;
+
+		map[i].dev_name = devname;
 		map[i].name = statename;
 		if (pctldev)
 			map[i].ctrl_dev_name = dev_name(pctldev->dev);
@@ -71,10 +84,8 @@
 
 	/* Remember the converted mapping table entries */
 	dt_map = kzalloc(sizeof(*dt_map), GFP_KERNEL);
-	if (!dt_map) {
-		dt_free_map(pctldev, map, num_maps);
-		return -ENOMEM;
-	}
+	if (!dt_map)
+		goto err_free_map;
 
 	dt_map->pctldev = pctldev;
 	dt_map->map = map;
@@ -82,6 +93,10 @@
 	list_add_tail(&dt_map->node, &p->dt_maps);
 
 	return pinctrl_register_map(map, num_maps, false);
+
+err_free_map:
+	dt_free_map(pctldev, map, num_maps);
+	return -ENOMEM;
 }
 
 struct pinctrl_dev *of_pinctrl_get(struct device_node *np)
@@ -208,12 +223,16 @@
 	for (state = 0; ; state++) {
 		/* Retrieve the pinctrl-* property */
 		propname = kasprintf(GFP_KERNEL, "pinctrl-%d", state);
+		if (!propname) {
+			ret = -ENOMEM;
+			goto err;
+		}
 		prop = of_find_property(np, propname, &size);
 		kfree(propname);
 		if (!prop) {
 			if (state == 0) {
-				of_node_put(np);
-				return -ENODEV;
+				ret = -ENODEV;
+				goto err;
 			}
 			break;
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/freescale/pinctrl-imx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/freescale/pinctrl-imx.c
@@ -774,16 +774,6 @@
 	return 0;
 }
 
-/*
- * imx_free_resources() - free memory used by this driver
- * @info: info driver instance
- */
-static void imx_free_resources(struct imx_pinctrl *ipctl)
-{
-	if (ipctl->pctl)
-		pinctrl_unregister(ipctl->pctl);
-}
-
 int imx_pinctrl_probe(struct platform_device *pdev,
 		      const struct imx_pinctrl_soc_info *info)
 {
@@ -874,23 +864,18 @@
 					     &ipctl->pctl);
 	if (ret) {
 		dev_err(&pdev->dev, "could not register IMX pinctrl driver\n");
-		goto free;
+		return ret;
 	}
 
 	ret = imx_pinctrl_probe_dt(pdev, ipctl);
 	if (ret) {
 		dev_err(&pdev->dev, "fail to probe dt properties\n");
-		goto free;
+		return ret;
 	}
 
 	dev_info(&pdev->dev, "initialized IMX pinctrl driver\n");
 
 	return pinctrl_enable(ipctl->pctl);
-
-free:
-	imx_free_resources(ipctl);
-
-	return ret;
 }
 
 static int __maybe_unused imx_pinctrl_suspend(struct device *dev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/freescale/pinctrl-imx1-core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/freescale/pinctrl-imx1-core.c
@@ -638,7 +638,6 @@
 
 	ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
 	if (ret) {
-		pinctrl_unregister(ipctl->pctl);
 		dev_err(&pdev->dev, "Failed to populate subdevices\n");
 		return ret;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/freescale/pinctrl-mxs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/freescale/pinctrl-mxs.c
@@ -405,8 +405,8 @@
 	int ret;
 	u32 val;
 
-	child = of_get_next_child(np, NULL);
-	if (!child) {
+	val = of_get_child_count(np);
+	if (val == 0) {
 		dev_err(&pdev->dev, "no group is defined\n");
 		return -ENOENT;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/freescale/pinctrl-scu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/freescale/pinctrl-scu.c
@@ -23,12 +23,12 @@
 	struct imx_sc_rpc_msg hdr;
 	u32 val;
 	u16 pad;
-} __packed;
+} __packed __aligned(4);
 
 struct imx_sc_msg_req_pad_get {
 	struct imx_sc_rpc_msg hdr;
 	u16 pad;
-} __packed;
+} __packed __aligned(4);
 
 struct imx_sc_msg_resp_pad_get {
 	struct imx_sc_rpc_msg hdr;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/intel/pinctrl-baytrail.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/intel/pinctrl-baytrail.c
@@ -110,7 +110,6 @@
 	struct platform_device *pdev;
 	struct pinctrl_dev *pctl_dev;
 	struct pinctrl_desc pctl_desc;
-	raw_spinlock_t lock;
 	const struct intel_pinctrl_soc_data *soc_data;
 	struct intel_community *communities_copy;
 	struct byt_gpio_pin_context *saved_context;
@@ -549,6 +548,8 @@
 	NULL
 };
 
+static DEFINE_RAW_SPINLOCK(byt_lock);
+
 static struct intel_community *byt_get_community(struct byt_gpio *vg,
 						 unsigned int pin)
 {
@@ -658,7 +659,7 @@
 	unsigned long flags;
 	int i;
 
-	raw_spin_lock_irqsave(&vg->lock, flags);
+	raw_spin_lock_irqsave(&byt_lock, flags);
 
 	for (i = 0; i < group.npins; i++) {
 		void __iomem *padcfg0;
@@ -678,7 +679,7 @@
 		writel(value, padcfg0);
 	}
 
-	raw_spin_unlock_irqrestore(&vg->lock, flags);
+	raw_spin_unlock_irqrestore(&byt_lock, flags);
 }
 
 static void byt_set_group_mixed_mux(struct byt_gpio *vg,
@@ -688,7 +689,7 @@
 	unsigned long flags;
 	int i;
 
-	raw_spin_lock_irqsave(&vg->lock, flags);
+	raw_spin_lock_irqsave(&byt_lock, flags);
 
 	for (i = 0; i < group.npins; i++) {
 		void __iomem *padcfg0;
@@ -708,7 +709,7 @@
 		writel(value, padcfg0);
 	}
 
-	raw_spin_unlock_irqrestore(&vg->lock, flags);
+	raw_spin_unlock_irqrestore(&byt_lock, flags);
 }
 
 static int byt_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector,
@@ -749,11 +750,17 @@
 	unsigned long flags;
 	u32 value;
 
-	raw_spin_lock_irqsave(&vg->lock, flags);
+	raw_spin_lock_irqsave(&byt_lock, flags);
 	value = readl(reg);
-	value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
+
+	/* Do not clear direct-irq enabled IRQs (from gpio_disable_free) */
+	if (value & BYT_DIRECT_IRQ_EN)
+		/* nothing to do */ ;
+	else
+		value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
+
 	writel(value, reg);
-	raw_spin_unlock_irqrestore(&vg->lock, flags);
+	raw_spin_unlock_irqrestore(&byt_lock, flags);
 }
 
 static int byt_gpio_request_enable(struct pinctrl_dev *pctl_dev,
@@ -765,7 +772,7 @@
 	u32 value, gpio_mux;
 	unsigned long flags;
 
-	raw_spin_lock_irqsave(&vg->lock, flags);
+	raw_spin_lock_irqsave(&byt_lock, flags);
 
 	/*
 	 * In most cases, func pin mux 000 means GPIO function.
@@ -787,7 +794,7 @@
 			 "pin %u forcibly re-configured as GPIO\n", offset);
 	}
 
-	raw_spin_unlock_irqrestore(&vg->lock, flags);
+	raw_spin_unlock_irqrestore(&byt_lock, flags);
 
 	pm_runtime_get(&vg->pdev->dev);
 
@@ -804,6 +811,21 @@
 	pm_runtime_put(&vg->pdev->dev);
 }
 
+static void byt_gpio_direct_irq_check(struct byt_gpio *vg,
+				      unsigned int offset)
+{
+	void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
+
+	/*
+	 * Before making any direction modifications, do a check if gpio is set
+	 * for direct IRQ. On Bay Trail, setting GPIO to output does not make
+	 * sense, so let's at least inform the caller before they shoot
+	 * themselves in the foot.
+	 */
+	if (readl(conf_reg) & BYT_DIRECT_IRQ_EN)
+		dev_info_once(&vg->pdev->dev, "Potential Error: Setting GPIO with direct_irq_en to output");
+}
+
 static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev,
 				  struct pinctrl_gpio_range *range,
 				  unsigned int offset,
@@ -811,28 +833,21 @@
 {
 	struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev);
 	void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
-	void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG);
 	unsigned long flags;
 	u32 value;
 
-	raw_spin_lock_irqsave(&vg->lock, flags);
+	raw_spin_lock_irqsave(&byt_lock, flags);
 
 	value = readl(val_reg);
 	value &= ~BYT_DIR_MASK;
 	if (input)
 		value |= BYT_OUTPUT_EN;
 	else
-		/*
-		 * Before making any direction modifications, do a check if gpio
-		 * is set for direct IRQ.  On baytrail, setting GPIO to output
-		 * does not make sense, so let's at least warn the caller before
-		 * they shoot themselves in the foot.
-		 */
-		WARN(readl(conf_reg) & BYT_DIRECT_IRQ_EN,
-		     "Potential Error: Setting GPIO with direct_irq_en to output");
+		byt_gpio_direct_irq_check(vg, offset);
+
 	writel(value, val_reg);
 
-	raw_spin_unlock_irqrestore(&vg->lock, flags);
+	raw_spin_unlock_irqrestore(&byt_lock, flags);
 
 	return 0;
 }
@@ -901,11 +916,11 @@
 	u32 conf, pull, val, debounce;
 	u16 arg = 0;
 
-	raw_spin_lock_irqsave(&vg->lock, flags);
+	raw_spin_lock_irqsave(&byt_lock, flags);
 	conf = readl(conf_reg);
 	pull = conf & BYT_PULL_ASSIGN_MASK;
 	val = readl(val_reg);
-	raw_spin_unlock_irqrestore(&vg->lock, flags);
+	raw_spin_unlock_irqrestore(&byt_lock, flags);
 
 	switch (param) {
 	case PIN_CONFIG_BIAS_DISABLE:
@@ -932,9 +947,9 @@
 		if (!(conf & BYT_DEBOUNCE_EN))
 			return -EINVAL;
 
-		raw_spin_lock_irqsave(&vg->lock, flags);
+		raw_spin_lock_irqsave(&byt_lock, flags);
 		debounce = readl(db_reg);
-		raw_spin_unlock_irqrestore(&vg->lock, flags);
+		raw_spin_unlock_irqrestore(&byt_lock, flags);
 
 		switch (debounce & BYT_DEBOUNCE_PULSE_MASK) {
 		case BYT_DEBOUNCE_PULSE_375US:
@@ -986,7 +1001,7 @@
 	u32 conf, val, debounce;
 	int i, ret = 0;
 
-	raw_spin_lock_irqsave(&vg->lock, flags);
+	raw_spin_lock_irqsave(&byt_lock, flags);
 
 	conf = readl(conf_reg);
 	val = readl(val_reg);
@@ -1045,7 +1060,6 @@
 			break;
 		case PIN_CONFIG_INPUT_DEBOUNCE:
 			debounce = readl(db_reg);
-			debounce &= ~BYT_DEBOUNCE_PULSE_MASK;
 
 			if (arg)
 				conf |= BYT_DEBOUNCE_EN;
@@ -1054,24 +1068,31 @@
 
 			switch (arg) {
 			case 375:
+				debounce &= ~BYT_DEBOUNCE_PULSE_MASK;
 				debounce |= BYT_DEBOUNCE_PULSE_375US;
 				break;
 			case 750:
+				debounce &= ~BYT_DEBOUNCE_PULSE_MASK;
 				debounce |= BYT_DEBOUNCE_PULSE_750US;
 				break;
 			case 1500:
+				debounce &= ~BYT_DEBOUNCE_PULSE_MASK;
 				debounce |= BYT_DEBOUNCE_PULSE_1500US;
 				break;
 			case 3000:
+				debounce &= ~BYT_DEBOUNCE_PULSE_MASK;
 				debounce |= BYT_DEBOUNCE_PULSE_3MS;
 				break;
 			case 6000:
+				debounce &= ~BYT_DEBOUNCE_PULSE_MASK;
 				debounce |= BYT_DEBOUNCE_PULSE_6MS;
 				break;
 			case 12000:
+				debounce &= ~BYT_DEBOUNCE_PULSE_MASK;
 				debounce |= BYT_DEBOUNCE_PULSE_12MS;
 				break;
 			case 24000:
+				debounce &= ~BYT_DEBOUNCE_PULSE_MASK;
 				debounce |= BYT_DEBOUNCE_PULSE_24MS;
 				break;
 			default:
@@ -1094,7 +1115,7 @@
 	if (!ret)
 		writel(conf, conf_reg);
 
-	raw_spin_unlock_irqrestore(&vg->lock, flags);
+	raw_spin_unlock_irqrestore(&byt_lock, flags);
 
 	return ret;
 }
@@ -1119,9 +1140,9 @@
 	unsigned long flags;
 	u32 val;
 
-	raw_spin_lock_irqsave(&vg->lock, flags);
+	raw_spin_lock_irqsave(&byt_lock, flags);
 	val = readl(reg);
-	raw_spin_unlock_irqrestore(&vg->lock, flags);
+	raw_spin_unlock_irqrestore(&byt_lock, flags);
 
 	return !!(val & BYT_LEVEL);
 }
@@ -1136,13 +1157,13 @@
 	if (!reg)
 		return;
 
-	raw_spin_lock_irqsave(&vg->lock, flags);
+	raw_spin_lock_irqsave(&byt_lock, flags);
 	old_val = readl(reg);
 	if (value)
 		writel(old_val | BYT_LEVEL, reg);
 	else
 		writel(old_val & ~BYT_LEVEL, reg);
-	raw_spin_unlock_irqrestore(&vg->lock, flags);
+	raw_spin_unlock_irqrestore(&byt_lock, flags);
 }
 
 static int byt_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
@@ -1155,9 +1176,9 @@
 	if (!reg)
 		return -EINVAL;
 
-	raw_spin_lock_irqsave(&vg->lock, flags);
+	raw_spin_lock_irqsave(&byt_lock, flags);
 	value = readl(reg);
-	raw_spin_unlock_irqrestore(&vg->lock, flags);
+	raw_spin_unlock_irqrestore(&byt_lock, flags);
 
 	if (!(value & BYT_OUTPUT_EN))
 		return 0;
@@ -1169,19 +1190,50 @@
 
 static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
 {
-	return pinctrl_gpio_direction_input(chip->base + offset);
+	struct byt_gpio *vg = gpiochip_get_data(chip);
+	void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
+	unsigned long flags;
+	u32 reg;
+
+	raw_spin_lock_irqsave(&byt_lock, flags);
+
+	reg = readl(val_reg);
+	reg &= ~BYT_DIR_MASK;
+	reg |= BYT_OUTPUT_EN;
+	writel(reg, val_reg);
+
+	raw_spin_unlock_irqrestore(&byt_lock, flags);
+	return 0;
 }
 
+/*
+ * Note despite the temptation this MUST NOT be converted into a call to
+ * pinctrl_gpio_direction_output() + byt_gpio_set() that does not work this
+ * MUST be done as a single BYT_VAL_REG register write.
+ * See the commit message of the commit adding this comment for details.
+ */
 static int byt_gpio_direction_output(struct gpio_chip *chip,
 				     unsigned int offset, int value)
 {
-	int ret = pinctrl_gpio_direction_output(chip->base + offset);
+	struct byt_gpio *vg = gpiochip_get_data(chip);
+	void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG);
+	unsigned long flags;
+	u32 reg;
 
-	if (ret)
-		return ret;
+	raw_spin_lock_irqsave(&byt_lock, flags);
 
-	byt_gpio_set(chip, offset, value);
+	byt_gpio_direct_irq_check(vg, offset);
 
+	reg = readl(val_reg);
+	reg &= ~BYT_DIR_MASK;
+	if (value)
+		reg |= BYT_LEVEL;
+	else
+		reg &= ~BYT_LEVEL;
+
+	writel(reg, val_reg);
+
+	raw_spin_unlock_irqrestore(&byt_lock, flags);
 	return 0;
 }
 
@@ -1200,14 +1252,14 @@
 		const char *label;
 		unsigned int pin;
 
-		raw_spin_lock_irqsave(&vg->lock, flags);
+		raw_spin_lock_irqsave(&byt_lock, flags);
 		pin = vg->soc_data->pins[i].number;
 		reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
 		if (!reg) {
 			seq_printf(s,
 				   "Could not retrieve pin %i conf0 reg\n",
 				   pin);
-			raw_spin_unlock_irqrestore(&vg->lock, flags);
+			raw_spin_unlock_irqrestore(&byt_lock, flags);
 			continue;
 		}
 		conf0 = readl(reg);
@@ -1216,11 +1268,11 @@
 		if (!reg) {
 			seq_printf(s,
 				   "Could not retrieve pin %i val reg\n", pin);
-			raw_spin_unlock_irqrestore(&vg->lock, flags);
+			raw_spin_unlock_irqrestore(&byt_lock, flags);
 			continue;
 		}
 		val = readl(reg);
-		raw_spin_unlock_irqrestore(&vg->lock, flags);
+		raw_spin_unlock_irqrestore(&byt_lock, flags);
 
 		comm = byt_get_community(vg, pin);
 		if (!comm) {
@@ -1290,6 +1342,7 @@
 	.direction_output	= byt_gpio_direction_output,
 	.get			= byt_gpio_get,
 	.set			= byt_gpio_set,
+	.set_config		= gpiochip_generic_config,
 	.dbg_show		= byt_gpio_dbg_show,
 };
 
@@ -1304,9 +1357,9 @@
 	if (!reg)
 		return;
 
-	raw_spin_lock(&vg->lock);
+	raw_spin_lock(&byt_lock);
 	writel(BIT(offset % 32), reg);
-	raw_spin_unlock(&vg->lock);
+	raw_spin_unlock(&byt_lock);
 }
 
 static void byt_irq_mask(struct irq_data *d)
@@ -1330,7 +1383,7 @@
 	if (!reg)
 		return;
 
-	raw_spin_lock_irqsave(&vg->lock, flags);
+	raw_spin_lock_irqsave(&byt_lock, flags);
 	value = readl(reg);
 
 	switch (irqd_get_trigger_type(d)) {
@@ -1353,7 +1406,7 @@
 
 	writel(value, reg);
 
-	raw_spin_unlock_irqrestore(&vg->lock, flags);
+	raw_spin_unlock_irqrestore(&byt_lock, flags);
 }
 
 static int byt_irq_type(struct irq_data *d, unsigned int type)
@@ -1367,7 +1420,7 @@
 	if (!reg || offset >= vg->chip.ngpio)
 		return -EINVAL;
 
-	raw_spin_lock_irqsave(&vg->lock, flags);
+	raw_spin_lock_irqsave(&byt_lock, flags);
 	value = readl(reg);
 
 	WARN(value & BYT_DIRECT_IRQ_EN,
@@ -1389,7 +1442,7 @@
 	else if (type & IRQ_TYPE_LEVEL_MASK)
 		irq_set_handler_locked(d, handle_level_irq);
 
-	raw_spin_unlock_irqrestore(&vg->lock, flags);
+	raw_spin_unlock_irqrestore(&byt_lock, flags);
 
 	return 0;
 }
@@ -1425,9 +1478,9 @@
 			continue;
 		}
 
-		raw_spin_lock(&vg->lock);
+		raw_spin_lock(&byt_lock);
 		pending = readl(reg);
-		raw_spin_unlock(&vg->lock);
+		raw_spin_unlock(&byt_lock);
 		for_each_set_bit(pin, &pending, 32) {
 			virq = irq_find_mapping(vg->chip.irq.domain, base + pin);
 			generic_handle_irq(virq);
@@ -1638,8 +1691,6 @@
 		return PTR_ERR(vg->pctl_dev);
 	}
 
-	raw_spin_lock_init(&vg->lock);
-
 	ret = byt_gpio_probe(vg);
 	if (ret)
 		return ret;
@@ -1654,8 +1705,11 @@
 static int byt_gpio_suspend(struct device *dev)
 {
 	struct byt_gpio *vg = dev_get_drvdata(dev);
+	unsigned long flags;
 	int i;
 
+	raw_spin_lock_irqsave(&byt_lock, flags);
+
 	for (i = 0; i < vg->soc_data->npins; i++) {
 		void __iomem *reg;
 		u32 value;
@@ -1676,14 +1730,18 @@
 		vg->saved_context[i].val = value;
 	}
 
+	raw_spin_unlock_irqrestore(&byt_lock, flags);
 	return 0;
 }
 
 static int byt_gpio_resume(struct device *dev)
 {
 	struct byt_gpio *vg = dev_get_drvdata(dev);
+	unsigned long flags;
 	int i;
 
+	raw_spin_lock_irqsave(&byt_lock, flags);
+
 	for (i = 0; i < vg->soc_data->npins; i++) {
 		void __iomem *reg;
 		u32 value;
@@ -1721,6 +1779,7 @@
 		}
 	}
 
+	raw_spin_unlock_irqrestore(&byt_lock, flags);
 	return 0;
 }
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/intel/pinctrl-cherryview.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/intel/pinctrl-cherryview.c
@@ -1021,11 +1021,6 @@
 
 		break;
 
-	case PIN_CONFIG_DRIVE_OPEN_DRAIN:
-		if (!(ctrl1 & CHV_PADCTRL1_ODEN))
-			return -EINVAL;
-		break;
-
 	case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: {
 		u32 cfg;
 
@@ -1035,6 +1030,16 @@
 			return -EINVAL;
 
 		break;
+
+	case PIN_CONFIG_DRIVE_PUSH_PULL:
+		if (ctrl1 & CHV_PADCTRL1_ODEN)
+			return -EINVAL;
+		break;
+
+	case PIN_CONFIG_DRIVE_OPEN_DRAIN:
+		if (!(ctrl1 & CHV_PADCTRL1_ODEN))
+			return -EINVAL;
+		break;
 	}
 
 	default:
@@ -1474,11 +1479,15 @@
 	struct chv_pinctrl *pctrl = gpiochip_get_data(gc);
 	struct irq_chip *chip = irq_desc_get_chip(desc);
 	unsigned long pending;
+	unsigned long flags;
 	u32 intr_line;
 
 	chained_irq_enter(chip, desc);
 
+	raw_spin_lock_irqsave(&chv_lock, flags);
 	pending = readl(pctrl->regs + CHV_INTSTAT);
+	raw_spin_unlock_irqrestore(&chv_lock, flags);
+
 	for_each_set_bit(intr_line, &pending, pctrl->community->nirqs) {
 		unsigned irq, offset;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/intel/pinctrl-intel.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/intel/pinctrl-intel.c
@@ -459,9 +459,14 @@
 	writel(value, padcfg0);
 }
 
+static int __intel_gpio_get_gpio_mode(u32 value)
+{
+	return (value & PADCFG0_PMODE_MASK) >> PADCFG0_PMODE_SHIFT;
+}
+
 static int intel_gpio_get_gpio_mode(void __iomem *padcfg0)
 {
-	return (readl(padcfg0) & PADCFG0_PMODE_MASK) >> PADCFG0_PMODE_SHIFT;
+	return __intel_gpio_get_gpio_mode(readl(padcfg0));
 }
 
 static void intel_gpio_set_gpio_mode(void __iomem *padcfg0)
@@ -662,6 +667,10 @@
 
 		value |= PADCFG1_TERM_UP;
 
+		/* Set default strength value in case none is given */
+		if (arg == 1)
+			arg = 5000;
+
 		switch (arg) {
 		case 20000:
 			value |= PADCFG1_TERM_20K << PADCFG1_TERM_SHIFT;
@@ -684,6 +693,10 @@
 	case PIN_CONFIG_BIAS_PULL_DOWN:
 		value &= ~(PADCFG1_TERM_UP | PADCFG1_TERM_MASK);
 
+		/* Set default strength value in case none is given */
+		if (arg == 1)
+			arg = 5000;
+
 		switch (arg) {
 		case 20000:
 			value |= PADCFG1_TERM_20K << PADCFG1_TERM_SHIFT;
@@ -1497,9 +1510,16 @@
 EXPORT_SYMBOL_GPL(intel_pinctrl_probe_by_uid);
 
 #ifdef CONFIG_PM_SLEEP
+static bool __intel_gpio_is_direct_irq(u32 value)
+{
+	return (value & PADCFG0_GPIROUTIOXAPIC) && (value & PADCFG0_GPIOTXDIS) &&
+	       (__intel_gpio_get_gpio_mode(value) == PADCFG0_PMODE_GPIO);
+}
+
 static bool intel_pinctrl_should_save(struct intel_pinctrl *pctrl, unsigned int pin)
 {
 	const struct pin_desc *pd = pin_desc_get(pctrl->pctldev, pin);
+	u32 value;
 
 	if (!pd || !intel_pad_usable(pctrl, pin))
 		return false;
@@ -1514,6 +1534,24 @@
 	    gpiochip_line_is_irq(&pctrl->chip, intel_pin_to_gpio(pctrl, pin)))
 		return true;
 
+	/*
+	 * The firmware on some systems may configure GPIO pins to be
+	 * an interrupt source in so called "direct IRQ" mode. In such
+	 * cases the GPIO controller driver has no idea if those pins
+	 * are being used or not. At the same time, there is a known bug
+	 * in the firmwares that don't restore the pin settings correctly
+	 * after suspend, i.e. by an unknown reason the Rx value becomes
+	 * inverted.
+	 *
+	 * Hence, let's save and restore the pins that are configured
+	 * as GPIOs in the input mode with GPIROUTIOXAPIC bit set.
+	 *
+	 * See https://bugzilla.kernel.org/show_bug.cgi?id=214749.
+	 */
+	value = readl(intel_get_padcfg(pctrl, pin, PADCFG0));
+	if (__intel_gpio_is_direct_irq(value))
+		return true;
+
 	return false;
 }
 
@@ -1623,7 +1661,12 @@
 		void __iomem *padcfg;
 		u32 val;
 
-		if (!intel_pinctrl_should_save(pctrl, desc->number))
+		if (!(intel_pinctrl_should_save(pctrl, desc->number) ||
+		      /*
+		       * If the firmware mangled the register contents too much,
+		       * check the saved value for the Direct IRQ mode.
+		       */
+		      __intel_gpio_is_direct_irq(pads[i].padcfg0)))
 			continue;
 
 		padcfg = intel_get_padcfg(pctrl, desc->number, PADCFG0);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/intel/pinctrl-lewisburg.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/intel/pinctrl-lewisburg.c
@@ -33,6 +33,7 @@
 		.npins = ((e) - (s) + 1),		\
 	}
 
+/* Lewisburg */
 static const struct pinctrl_pin_desc lbg_pins[] = {
 	/* GPP_A */
 	PINCTRL_PIN(0, "RCINB"),
@@ -72,7 +73,7 @@
 	PINCTRL_PIN(33, "SRCCLKREQB_4"),
 	PINCTRL_PIN(34, "SRCCLKREQB_5"),
 	PINCTRL_PIN(35, "GPP_B_11"),
-	PINCTRL_PIN(36, "GLB_RST_WARN_N"),
+	PINCTRL_PIN(36, "SLP_S0B"),
 	PINCTRL_PIN(37, "PLTRSTB"),
 	PINCTRL_PIN(38, "SPKR"),
 	PINCTRL_PIN(39, "GPP_B_15"),
@@ -185,96 +186,96 @@
 	PINCTRL_PIN(141, "GBE_PCI_DIS"),
 	PINCTRL_PIN(142, "GBE_LAN_DIS"),
 	PINCTRL_PIN(143, "GPP_I_10"),
-	PINCTRL_PIN(144, "GPIO_RCOMP_3P3"),
 	/* GPP_J */
-	PINCTRL_PIN(145, "GBE_LED_0_0"),
-	PINCTRL_PIN(146, "GBE_LED_0_1"),
-	PINCTRL_PIN(147, "GBE_LED_1_0"),
-	PINCTRL_PIN(148, "GBE_LED_1_1"),
-	PINCTRL_PIN(149, "GBE_LED_2_0"),
-	PINCTRL_PIN(150, "GBE_LED_2_1"),
-	PINCTRL_PIN(151, "GBE_LED_3_0"),
-	PINCTRL_PIN(152, "GBE_LED_3_1"),
-	PINCTRL_PIN(153, "GBE_SCL_0"),
-	PINCTRL_PIN(154, "GBE_SDA_0"),
-	PINCTRL_PIN(155, "GBE_SCL_1"),
-	PINCTRL_PIN(156, "GBE_SDA_1"),
-	PINCTRL_PIN(157, "GBE_SCL_2"),
-	PINCTRL_PIN(158, "GBE_SDA_2"),
-	PINCTRL_PIN(159, "GBE_SCL_3"),
-	PINCTRL_PIN(160, "GBE_SDA_3"),
-	PINCTRL_PIN(161, "GBE_SDP_0_0"),
-	PINCTRL_PIN(162, "GBE_SDP_0_1"),
-	PINCTRL_PIN(163, "GBE_SDP_1_0"),
-	PINCTRL_PIN(164, "GBE_SDP_1_1"),
-	PINCTRL_PIN(165, "GBE_SDP_2_0"),
-	PINCTRL_PIN(166, "GBE_SDP_2_1"),
-	PINCTRL_PIN(167, "GBE_SDP_3_0"),
-	PINCTRL_PIN(168, "GBE_SDP_3_1"),
+	PINCTRL_PIN(144, "GBE_LED_0_0"),
+	PINCTRL_PIN(145, "GBE_LED_0_1"),
+	PINCTRL_PIN(146, "GBE_LED_1_0"),
+	PINCTRL_PIN(147, "GBE_LED_1_1"),
+	PINCTRL_PIN(148, "GBE_LED_2_0"),
+	PINCTRL_PIN(149, "GBE_LED_2_1"),
+	PINCTRL_PIN(150, "GBE_LED_3_0"),
+	PINCTRL_PIN(151, "GBE_LED_3_1"),
+	PINCTRL_PIN(152, "GBE_SCL_0"),
+	PINCTRL_PIN(153, "GBE_SDA_0"),
+	PINCTRL_PIN(154, "GBE_SCL_1"),
+	PINCTRL_PIN(155, "GBE_SDA_1"),
+	PINCTRL_PIN(156, "GBE_SCL_2"),
+	PINCTRL_PIN(157, "GBE_SDA_2"),
+	PINCTRL_PIN(158, "GBE_SCL_3"),
+	PINCTRL_PIN(159, "GBE_SDA_3"),
+	PINCTRL_PIN(160, "GBE_SDP_0_0"),
+	PINCTRL_PIN(161, "GBE_SDP_0_1"),
+	PINCTRL_PIN(162, "GBE_SDP_1_0"),
+	PINCTRL_PIN(163, "GBE_SDP_1_1"),
+	PINCTRL_PIN(164, "GBE_SDP_2_0"),
+	PINCTRL_PIN(165, "GBE_SDP_2_1"),
+	PINCTRL_PIN(166, "GBE_SDP_3_0"),
+	PINCTRL_PIN(167, "GBE_SDP_3_1"),
 	/* GPP_K */
-	PINCTRL_PIN(169, "GBE_RMIICLK"),
-	PINCTRL_PIN(170, "GBE_RMII_TXD_0"),
-	PINCTRL_PIN(171, "GBE_RMII_TXD_1"),
+	PINCTRL_PIN(168, "GBE_RMIICLK"),
+	PINCTRL_PIN(169, "GBE_RMII_RXD_0"),
+	PINCTRL_PIN(170, "GBE_RMII_RXD_1"),
+	PINCTRL_PIN(171, "GBE_RMII_CRS_DV"),
 	PINCTRL_PIN(172, "GBE_RMII_TX_EN"),
-	PINCTRL_PIN(173, "GBE_RMII_CRS_DV"),
-	PINCTRL_PIN(174, "GBE_RMII_RXD_0"),
-	PINCTRL_PIN(175, "GBE_RMII_RXD_1"),
-	PINCTRL_PIN(176, "GBE_RMII_RX_ER"),
-	PINCTRL_PIN(177, "GBE_RMII_ARBIN"),
-	PINCTRL_PIN(178, "GBE_RMII_ARB_OUT"),
-	PINCTRL_PIN(179, "PE_RST_N"),
-	PINCTRL_PIN(180, "GPIO_RCOMP_1P8_3P3"),
+	PINCTRL_PIN(173, "GBE_RMII_TXD_0"),
+	PINCTRL_PIN(174, "GBE_RMII_TXD_1"),
+	PINCTRL_PIN(175, "GBE_RMII_RX_ER"),
+	PINCTRL_PIN(176, "GBE_RMII_ARBIN"),
+	PINCTRL_PIN(177, "GBE_RMII_ARB_OUT"),
+	PINCTRL_PIN(178, "PE_RST_N"),
 	/* GPP_G */
-	PINCTRL_PIN(181, "FAN_TACH_0"),
-	PINCTRL_PIN(182, "FAN_TACH_1"),
-	PINCTRL_PIN(183, "FAN_TACH_2"),
-	PINCTRL_PIN(184, "FAN_TACH_3"),
-	PINCTRL_PIN(185, "FAN_TACH_4"),
-	PINCTRL_PIN(186, "FAN_TACH_5"),
-	PINCTRL_PIN(187, "FAN_TACH_6"),
-	PINCTRL_PIN(188, "FAN_TACH_7"),
-	PINCTRL_PIN(189, "FAN_PWM_0"),
-	PINCTRL_PIN(190, "FAN_PWM_1"),
-	PINCTRL_PIN(191, "FAN_PWM_2"),
-	PINCTRL_PIN(192, "FAN_PWM_3"),
-	PINCTRL_PIN(193, "GSXDOUT"),
-	PINCTRL_PIN(194, "GSXSLOAD"),
-	PINCTRL_PIN(195, "GSXDIN"),
-	PINCTRL_PIN(196, "GSXSRESETB"),
-	PINCTRL_PIN(197, "GSXCLK"),
-	PINCTRL_PIN(198, "ADR_COMPLETE"),
-	PINCTRL_PIN(199, "NMIB"),
-	PINCTRL_PIN(200, "SMIB"),
-	PINCTRL_PIN(201, "SSATA_DEVSLP_0"),
-	PINCTRL_PIN(202, "SSATA_DEVSLP_1"),
-	PINCTRL_PIN(203, "SSATA_DEVSLP_2"),
-	PINCTRL_PIN(204, "SSATAXPCIE0_SSATAGP0"),
+	PINCTRL_PIN(179, "FAN_TACH_0"),
+	PINCTRL_PIN(180, "FAN_TACH_1"),
+	PINCTRL_PIN(181, "FAN_TACH_2"),
+	PINCTRL_PIN(182, "FAN_TACH_3"),
+	PINCTRL_PIN(183, "FAN_TACH_4"),
+	PINCTRL_PIN(184, "FAN_TACH_5"),
+	PINCTRL_PIN(185, "FAN_TACH_6"),
+	PINCTRL_PIN(186, "FAN_TACH_7"),
+	PINCTRL_PIN(187, "FAN_PWM_0"),
+	PINCTRL_PIN(188, "FAN_PWM_1"),
+	PINCTRL_PIN(189, "FAN_PWM_2"),
+	PINCTRL_PIN(190, "FAN_PWM_3"),
+	PINCTRL_PIN(191, "GSXDOUT"),
+	PINCTRL_PIN(192, "GSXSLOAD"),
+	PINCTRL_PIN(193, "GSXDIN"),
+	PINCTRL_PIN(194, "GSXSRESETB"),
+	PINCTRL_PIN(195, "GSXCLK"),
+	PINCTRL_PIN(196, "ADR_COMPLETE"),
+	PINCTRL_PIN(197, "NMIB"),
+	PINCTRL_PIN(198, "SMIB"),
+	PINCTRL_PIN(199, "SSATA_DEVSLP_0"),
+	PINCTRL_PIN(200, "SSATA_DEVSLP_1"),
+	PINCTRL_PIN(201, "SSATA_DEVSLP_2"),
+	PINCTRL_PIN(202, "SSATAXPCIE0_SSATAGP0"),
 	/* GPP_H */
-	PINCTRL_PIN(205, "SRCCLKREQB_6"),
-	PINCTRL_PIN(206, "SRCCLKREQB_7"),
-	PINCTRL_PIN(207, "SRCCLKREQB_8"),
-	PINCTRL_PIN(208, "SRCCLKREQB_9"),
-	PINCTRL_PIN(209, "SRCCLKREQB_10"),
-	PINCTRL_PIN(210, "SRCCLKREQB_11"),
-	PINCTRL_PIN(211, "SRCCLKREQB_12"),
-	PINCTRL_PIN(212, "SRCCLKREQB_13"),
-	PINCTRL_PIN(213, "SRCCLKREQB_14"),
-	PINCTRL_PIN(214, "SRCCLKREQB_15"),
-	PINCTRL_PIN(215, "SML2CLK"),
-	PINCTRL_PIN(216, "SML2DATA"),
-	PINCTRL_PIN(217, "SML2ALERTB"),
-	PINCTRL_PIN(218, "SML3CLK"),
-	PINCTRL_PIN(219, "SML3DATA"),
-	PINCTRL_PIN(220, "SML3ALERTB"),
-	PINCTRL_PIN(221, "SML4CLK"),
-	PINCTRL_PIN(222, "SML4DATA"),
-	PINCTRL_PIN(223, "SML4ALERTB"),
-	PINCTRL_PIN(224, "SSATAXPCIE1_SSATAGP1"),
-	PINCTRL_PIN(225, "SSATAXPCIE2_SSATAGP2"),
-	PINCTRL_PIN(226, "SSATAXPCIE3_SSATAGP3"),
-	PINCTRL_PIN(227, "SSATAXPCIE4_SSATAGP4"),
-	PINCTRL_PIN(228, "SSATAXPCIE5_SSATAGP5"),
+	PINCTRL_PIN(203, "SRCCLKREQB_6"),
+	PINCTRL_PIN(204, "SRCCLKREQB_7"),
+	PINCTRL_PIN(205, "SRCCLKREQB_8"),
+	PINCTRL_PIN(206, "SRCCLKREQB_9"),
+	PINCTRL_PIN(207, "SRCCLKREQB_10"),
+	PINCTRL_PIN(208, "SRCCLKREQB_11"),
+	PINCTRL_PIN(209, "SRCCLKREQB_12"),
+	PINCTRL_PIN(210, "SRCCLKREQB_13"),
+	PINCTRL_PIN(211, "SRCCLKREQB_14"),
+	PINCTRL_PIN(212, "SRCCLKREQB_15"),
+	PINCTRL_PIN(213, "SML2CLK"),
+	PINCTRL_PIN(214, "SML2DATA"),
+	PINCTRL_PIN(215, "SML2ALERTB"),
+	PINCTRL_PIN(216, "SML3CLK"),
+	PINCTRL_PIN(217, "SML3DATA"),
+	PINCTRL_PIN(218, "SML3ALERTB"),
+	PINCTRL_PIN(219, "SML4CLK"),
+	PINCTRL_PIN(220, "SML4DATA"),
+	PINCTRL_PIN(221, "SML4ALERTB"),
+	PINCTRL_PIN(222, "SSATAXPCIE1_SSATAGP1"),
+	PINCTRL_PIN(223, "SSATAXPCIE2_SSATAGP2"),
+	PINCTRL_PIN(224, "SSATAXPCIE3_SSATAGP3"),
+	PINCTRL_PIN(225, "SSATAXPCIE4_SSATAGP4"),
+	PINCTRL_PIN(226, "SSATAXPCIE5_SSATAGP5"),
 	/* GPP_L */
+	PINCTRL_PIN(227, "GPP_L_0"),
+	PINCTRL_PIN(228, "EC_CSME_INTR_OUT"),
 	PINCTRL_PIN(229, "VISA2CH0_D0"),
 	PINCTRL_PIN(230, "VISA2CH0_D1"),
 	PINCTRL_PIN(231, "VISA2CH0_D2"),
@@ -298,9 +299,9 @@
 static const struct intel_community lbg_communities[] = {
 	LBG_COMMUNITY(0, 0, 71),
 	LBG_COMMUNITY(1, 72, 132),
-	LBG_COMMUNITY(3, 133, 144),
-	LBG_COMMUNITY(4, 145, 180),
-	LBG_COMMUNITY(5, 181, 246),
+	LBG_COMMUNITY(3, 133, 143),
+	LBG_COMMUNITY(4, 144, 178),
+	LBG_COMMUNITY(5, 179, 246),
 };
 
 static const struct intel_pinctrl_soc_data lbg_soc_data = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/intel/pinctrl-merrifield.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/intel/pinctrl-merrifield.c
@@ -741,6 +741,10 @@
 		mask |= BUFCFG_Px_EN_MASK | BUFCFG_PUPD_VAL_MASK;
 		bits |= BUFCFG_PU_EN;
 
+		/* Set default strength value in case none is given */
+		if (arg == 1)
+			arg = 20000;
+
 		switch (arg) {
 		case 50000:
 			bits |= BUFCFG_PUPD_VAL_50K << BUFCFG_PUPD_VAL_SHIFT;
@@ -761,6 +765,10 @@
 		mask |= BUFCFG_Px_EN_MASK | BUFCFG_PUPD_VAL_MASK;
 		bits |= BUFCFG_PD_EN;
 
+		/* Set default strength value in case none is given */
+		if (arg == 1)
+			arg = 20000;
+
 		switch (arg) {
 		case 50000:
 			bits |= BUFCFG_PUPD_VAL_50K << BUFCFG_PUPD_VAL_SHIFT;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/intel/pinctrl-sunrisepoint.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/intel/pinctrl-sunrisepoint.c
@@ -15,17 +15,18 @@
 
 #include "pinctrl-intel.h"
 
-#define SPT_PAD_OWN	0x020
-#define SPT_PADCFGLOCK	0x0a0
-#define SPT_HOSTSW_OWN	0x0d0
-#define SPT_GPI_IS	0x100
-#define SPT_GPI_IE	0x120
+#define SPT_PAD_OWN		0x020
+#define SPT_H_PADCFGLOCK	0x090
+#define SPT_LP_PADCFGLOCK	0x0a0
+#define SPT_HOSTSW_OWN		0x0d0
+#define SPT_GPI_IS		0x100
+#define SPT_GPI_IE		0x120
 
 #define SPT_COMMUNITY(b, s, e)				\
 	{						\
 		.barno = (b),				\
 		.padown_offset = SPT_PAD_OWN,		\
-		.padcfglock_offset = SPT_PADCFGLOCK,	\
+		.padcfglock_offset = SPT_LP_PADCFGLOCK,	\
 		.hostown_offset = SPT_HOSTSW_OWN,	\
 		.is_offset = SPT_GPI_IS,		\
 		.ie_offset = SPT_GPI_IE,		\
@@ -47,8 +48,9 @@
 	{						\
 		.barno = (b),				\
 		.padown_offset = SPT_PAD_OWN,		\
-		.padcfglock_offset = SPT_PADCFGLOCK,	\
+		.padcfglock_offset = SPT_H_PADCFGLOCK,	\
 		.hostown_offset = SPT_HOSTSW_OWN,	\
+		.is_offset = SPT_GPI_IS,		\
 		.ie_offset = SPT_GPI_IE,		\
 		.pin_base = (s),			\
 		.npins = ((e) - (s) + 1),		\
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/mediatek/mtk-eint.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/mediatek/mtk-eint.c
@@ -277,12 +277,15 @@
 
 static unsigned int mtk_eint_hw_init(struct mtk_eint *eint)
 {
-	void __iomem *reg = eint->base + eint->regs->dom_en;
+	void __iomem *dom_en = eint->base + eint->regs->dom_en;
+	void __iomem *mask_set = eint->base + eint->regs->mask_set;
 	unsigned int i;
 
 	for (i = 0; i < eint->hw->ap_num; i += 32) {
-		writel(0xffffffff, reg);
-		reg += 4;
+		writel(0xffffffff, dom_en);
+		writel(0xffffffff, mask_set);
+		dom_en += 4;
+		mask_set += 4;
 	}
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/mediatek/pinctrl-mt6765.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/mediatek/pinctrl-mt6765.c
@@ -1070,15 +1070,12 @@
 	.ngrps = ARRAY_SIZE(mtk_pins_mt6765),
 	.eint_hw = &mt6765_eint_hw,
 	.gpio_m = 0,
-	.ies_present = true,
 	.base_names = mt6765_pinctrl_register_base_names,
 	.nbase_names = ARRAY_SIZE(mt6765_pinctrl_register_base_names),
-	.bias_disable_set = mtk_pinconf_bias_disable_set,
-	.bias_disable_get = mtk_pinconf_bias_disable_get,
-	.bias_set = mtk_pinconf_bias_set,
-	.bias_get = mtk_pinconf_bias_get,
-	.drive_set = mtk_pinconf_drive_set_rev1,
-	.drive_get = mtk_pinconf_drive_get_rev1,
+	.bias_set_combo = mtk_pinconf_bias_set_combo,
+	.bias_get_combo = mtk_pinconf_bias_get_combo,
+	.drive_set = mtk_pinconf_drive_set_raw,
+	.drive_get = mtk_pinconf_drive_get_raw,
 	.adv_pull_get = mtk_pinconf_adv_pull_get,
 	.adv_pull_set = mtk_pinconf_adv_pull_set,
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/mediatek/pinctrl-mt8183.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/mediatek/pinctrl-mt8183.c
@@ -554,13 +554,10 @@
 	.ngrps = ARRAY_SIZE(mtk_pins_mt8183),
 	.eint_hw = &mt8183_eint_hw,
 	.gpio_m = 0,
-	.ies_present = true,
 	.base_names = mt8183_pinctrl_register_base_names,
 	.nbase_names = ARRAY_SIZE(mt8183_pinctrl_register_base_names),
-	.bias_disable_set = mtk_pinconf_bias_disable_set_rev1,
-	.bias_disable_get = mtk_pinconf_bias_disable_get_rev1,
-	.bias_set = mtk_pinconf_bias_set_rev1,
-	.bias_get = mtk_pinconf_bias_get_rev1,
+	.bias_set_combo = mtk_pinconf_bias_set_combo,
+	.bias_get_combo = mtk_pinconf_bias_get_combo,
 	.drive_set = mtk_pinconf_drive_set_rev1,
 	.drive_get = mtk_pinconf_drive_get_rev1,
 	.adv_pull_get = mtk_pinconf_adv_pull_get,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
@@ -6,6 +6,7 @@
  *
  */
 
+#include <dt-bindings/pinctrl/mt65xx.h>
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/gpio/driver.h>
@@ -66,34 +67,44 @@
 				   const struct mtk_pin_desc *desc,
 				   int field, struct mtk_pin_field *pfd)
 {
-	const struct mtk_pin_field_calc *c, *e;
+	const struct mtk_pin_field_calc *c;
 	const struct mtk_pin_reg_calc *rc;
+	int start = 0, end, check;
+	bool found = false;
 	u32 bits;
 
 	if (hw->soc->reg_cal && hw->soc->reg_cal[field].range) {
 		rc = &hw->soc->reg_cal[field];
 	} else {
 		dev_dbg(hw->dev,
-			"Not support field %d for pin %d (%s)\n",
-			field, desc->number, desc->name);
+			"Not support field %d for this soc\n", field);
 		return -ENOTSUPP;
 	}
 
-	c = rc->range;
-	e = c + rc->nranges;
+	end = rc->nranges - 1;
 
-	while (c < e) {
-		if (desc->number >= c->s_pin && desc->number <= c->e_pin)
+	while (start <= end) {
+		check = (start + end) >> 1;
+		if (desc->number >= rc->range[check].s_pin
+		 && desc->number <= rc->range[check].e_pin) {
+			found = true;
+			break;
+		} else if (start == end)
 			break;
-		c++;
+		else if (desc->number < rc->range[check].s_pin)
+			end = check - 1;
+		else
+			start = check + 1;
 	}
 
-	if (c >= e) {
+	if (!found) {
 		dev_dbg(hw->dev, "Not support field %d for pin = %d (%s)\n",
 			field, desc->number, desc->name);
 		return -ENOTSUPP;
 	}
 
+	c = rc->range + check;
+
 	if (c->i_base > hw->nbase - 1) {
 		dev_err(hw->dev,
 			"Invalid base for field %d for pin = %d (%s)\n",
@@ -182,6 +193,9 @@
 	if (err)
 		return err;
 
+	if (value < 0 || value > pf.mask)
+		return -EINVAL;
+
 	if (!pf.next)
 		mtk_rmw(hw, pf.index, pf.offset, pf.mask << pf.bitpos,
 			(value & pf.mask) << pf.bitpos);
@@ -236,8 +250,12 @@
 	desc = (const struct mtk_pin_desc *)hw->soc->pins;
 	*gpio_chip = &hw->chip;
 
-	/* Be greedy to guess first gpio_n is equal to eint_n */
-	if (desc[eint_n].eint.eint_n == eint_n)
+	/*
+	 * Be greedy to guess first gpio_n is equal to eint_n.
+	 * Only eint virtual eint number is greater than gpio number.
+	 */
+	if (hw->soc->npins > eint_n &&
+	    desc[eint_n].eint.eint_n == eint_n)
 		*gpio_n = eint_n;
 	else
 		*gpio_n = mtk_xt_find_eint_num(hw, eint_n);
@@ -502,6 +520,226 @@
 	return 0;
 }
 
+/* Combo for the following pull register type:
+ * 1. PU + PD
+ * 2. PULLSEL + PULLEN
+ * 3. PUPD + R0 + R1
+ */
+static int mtk_pinconf_bias_set_pu_pd(struct mtk_pinctrl *hw,
+				const struct mtk_pin_desc *desc,
+				u32 pullup, u32 arg)
+{
+	int err, pu, pd;
+
+	if (arg == MTK_DISABLE) {
+		pu = 0;
+		pd = 0;
+	} else if ((arg == MTK_ENABLE) && pullup) {
+		pu = 1;
+		pd = 0;
+	} else if ((arg == MTK_ENABLE) && !pullup) {
+		pu = 0;
+		pd = 1;
+	} else {
+		err = -EINVAL;
+		goto out;
+	}
+
+	err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PU, pu);
+	if (err)
+		goto out;
+
+	err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PD, pd);
+
+out:
+	return err;
+}
+
+static int mtk_pinconf_bias_set_pullsel_pullen(struct mtk_pinctrl *hw,
+				const struct mtk_pin_desc *desc,
+				u32 pullup, u32 arg)
+{
+	int err, enable;
+
+	if (arg == MTK_DISABLE)
+		enable = 0;
+	else if (arg == MTK_ENABLE)
+		enable = 1;
+	else {
+		err = -EINVAL;
+		goto out;
+	}
+
+	err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PULLEN, enable);
+	if (err)
+		goto out;
+
+	err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PULLSEL, pullup);
+
+out:
+	return err;
+}
+
+static int mtk_pinconf_bias_set_pupd_r1_r0(struct mtk_pinctrl *hw,
+				const struct mtk_pin_desc *desc,
+				u32 pullup, u32 arg)
+{
+	int err, r0, r1;
+
+	if ((arg == MTK_DISABLE) || (arg == MTK_PUPD_SET_R1R0_00)) {
+		pullup = 0;
+		r0 = 0;
+		r1 = 0;
+	} else if (arg == MTK_PUPD_SET_R1R0_01) {
+		r0 = 1;
+		r1 = 0;
+	} else if (arg == MTK_PUPD_SET_R1R0_10) {
+		r0 = 0;
+		r1 = 1;
+	} else if (arg == MTK_PUPD_SET_R1R0_11) {
+		r0 = 1;
+		r1 = 1;
+	} else {
+		err = -EINVAL;
+		goto out;
+	}
+
+	/* MTK HW PUPD bit: 1 for pull-down, 0 for pull-up */
+	err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_PUPD, !pullup);
+	if (err)
+		goto out;
+
+	err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_R0, r0);
+	if (err)
+		goto out;
+
+	err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_R1, r1);
+
+out:
+	return err;
+}
+
+static int mtk_pinconf_bias_get_pu_pd(struct mtk_pinctrl *hw,
+				const struct mtk_pin_desc *desc,
+				u32 *pullup, u32 *enable)
+{
+	int err, pu, pd;
+
+	err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PU, &pu);
+	if (err)
+		goto out;
+
+	err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PD, &pd);
+	if (err)
+		goto out;
+
+	if (pu == 0 && pd == 0) {
+		*pullup = 0;
+		*enable = MTK_DISABLE;
+	} else if (pu == 1 && pd == 0) {
+		*pullup = 1;
+		*enable = MTK_ENABLE;
+	} else if (pu == 0 && pd == 1) {
+		*pullup = 0;
+		*enable = MTK_ENABLE;
+	} else
+		err = -EINVAL;
+
+out:
+	return err;
+}
+
+static int mtk_pinconf_bias_get_pullsel_pullen(struct mtk_pinctrl *hw,
+				const struct mtk_pin_desc *desc,
+				u32 *pullup, u32 *enable)
+{
+	int err;
+
+	err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PULLSEL, pullup);
+	if (err)
+		goto out;
+
+	err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PULLEN, enable);
+
+out:
+	return err;
+}
+
+static int mtk_pinconf_bias_get_pupd_r1_r0(struct mtk_pinctrl *hw,
+				const struct mtk_pin_desc *desc,
+				u32 *pullup, u32 *enable)
+{
+	int err, r0, r1;
+
+	err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_PUPD, pullup);
+	if (err)
+		goto out;
+	/* MTK HW PUPD bit: 1 for pull-down, 0 for pull-up */
+	*pullup = !(*pullup);
+
+	err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_R0, &r0);
+	if (err)
+		goto out;
+
+	err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_R1, &r1);
+	if (err)
+		goto out;
+
+	if ((r1 == 0) && (r0 == 0))
+		*enable = MTK_PUPD_SET_R1R0_00;
+	else if ((r1 == 0) && (r0 == 1))
+		*enable = MTK_PUPD_SET_R1R0_01;
+	else if ((r1 == 1) && (r0 == 0))
+		*enable = MTK_PUPD_SET_R1R0_10;
+	else if ((r1 == 1) && (r0 == 1))
+		*enable = MTK_PUPD_SET_R1R0_11;
+	else
+		err = -EINVAL;
+
+out:
+	return err;
+}
+
+int mtk_pinconf_bias_set_combo(struct mtk_pinctrl *hw,
+				const struct mtk_pin_desc *desc,
+				u32 pullup, u32 arg)
+{
+	int err;
+
+	err = mtk_pinconf_bias_set_pu_pd(hw, desc, pullup, arg);
+	if (!err)
+		goto out;
+
+	err = mtk_pinconf_bias_set_pullsel_pullen(hw, desc, pullup, arg);
+	if (!err)
+		goto out;
+
+	err = mtk_pinconf_bias_set_pupd_r1_r0(hw, desc, pullup, arg);
+
+out:
+	return err;
+}
+
+int mtk_pinconf_bias_get_combo(struct mtk_pinctrl *hw,
+			      const struct mtk_pin_desc *desc,
+			      u32 *pullup, u32 *enable)
+{
+	int err;
+
+	err = mtk_pinconf_bias_get_pu_pd(hw, desc, pullup, enable);
+	if (!err)
+		goto out;
+
+	err = mtk_pinconf_bias_get_pullsel_pullen(hw, desc, pullup, enable);
+	if (!err)
+		goto out;
+
+	err = mtk_pinconf_bias_get_pupd_r1_r0(hw, desc, pullup, enable);
+
+out:
+	return err;
+}
+
 /* Revision 0 */
 int mtk_pinconf_drive_set(struct mtk_pinctrl *hw,
 			  const struct mtk_pin_desc *desc, u32 arg)
@@ -593,6 +831,18 @@
 	return 0;
 }
 
+int mtk_pinconf_drive_set_raw(struct mtk_pinctrl *hw,
+			       const struct mtk_pin_desc *desc, u32 arg)
+{
+	return mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DRV, arg);
+}
+
+int mtk_pinconf_drive_get_raw(struct mtk_pinctrl *hw,
+			       const struct mtk_pin_desc *desc, int *val)
+{
+	return mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DRV, val);
+}
+
 int mtk_pinconf_adv_pull_set(struct mtk_pinctrl *hw,
 			     const struct mtk_pin_desc *desc, bool pullup,
 			     u32 arg)
@@ -626,7 +876,9 @@
 			if (err)
 				return err;
 		} else {
-			return -ENOTSUPP;
+			err = mtk_pinconf_bias_set_rev1(hw, desc, pullup);
+			if (err)
+				err = mtk_pinconf_bias_set(hw, desc, pullup);
 		}
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.h
@@ -216,6 +216,11 @@
 	int (*bias_get)(struct mtk_pinctrl *hw,
 			const struct mtk_pin_desc *desc, bool pullup, int *res);
 
+	int (*bias_set_combo)(struct mtk_pinctrl *hw,
+			const struct mtk_pin_desc *desc, u32 pullup, u32 arg);
+	int (*bias_get_combo)(struct mtk_pinctrl *hw,
+			const struct mtk_pin_desc *desc, u32 *pullup, u32 *arg);
+
 	int (*drive_set)(struct mtk_pinctrl *hw,
 			 const struct mtk_pin_desc *desc, u32 arg);
 	int (*drive_get)(struct mtk_pinctrl *hw,
@@ -277,6 +282,12 @@
 int mtk_pinconf_bias_get_rev1(struct mtk_pinctrl *hw,
 			      const struct mtk_pin_desc *desc, bool pullup,
 			      int *res);
+int mtk_pinconf_bias_set_combo(struct mtk_pinctrl *hw,
+				const struct mtk_pin_desc *desc,
+				u32 pullup, u32 enable);
+int mtk_pinconf_bias_get_combo(struct mtk_pinctrl *hw,
+			      const struct mtk_pin_desc *desc,
+			      u32 *pullup, u32 *enable);
 
 int mtk_pinconf_drive_set(struct mtk_pinctrl *hw,
 			  const struct mtk_pin_desc *desc, u32 arg);
@@ -288,6 +299,11 @@
 int mtk_pinconf_drive_get_rev1(struct mtk_pinctrl *hw,
 			       const struct mtk_pin_desc *desc, int *val);
 
+int mtk_pinconf_drive_set_raw(struct mtk_pinctrl *hw,
+			       const struct mtk_pin_desc *desc, u32 arg);
+int mtk_pinconf_drive_get_raw(struct mtk_pinctrl *hw,
+			       const struct mtk_pin_desc *desc, int *val);
+
 int mtk_pinconf_adv_pull_set(struct mtk_pinctrl *hw,
 			     const struct mtk_pin_desc *desc, bool pullup,
 			     u32 arg);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
@@ -1038,6 +1038,7 @@
 	node = of_parse_phandle(np, "mediatek,pctl-regmap", 0);
 	if (node) {
 		pctl->regmap1 = syscon_node_to_regmap(node);
+		of_node_put(node);
 		if (IS_ERR(pctl->regmap1))
 			return PTR_ERR(pctl->regmap1);
 	} else if (regmap) {
@@ -1051,6 +1052,7 @@
 	node = of_parse_phandle(np, "mediatek,pctl-regmap", 1);
 	if (node) {
 		pctl->regmap2 = syscon_node_to_regmap(node);
+		of_node_put(node);
 		if (IS_ERR(pctl->regmap2))
 			return PTR_ERR(pctl->regmap2);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/mediatek/pinctrl-paris.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/mediatek/pinctrl-paris.c
@@ -78,265 +78,186 @@
 {
 	struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
 	u32 param = pinconf_to_config_param(*config);
-	int val, val2, err, reg, ret = 1;
+	int pullup, reg, err = -ENOTSUPP, ret = 1;
 	const struct mtk_pin_desc *desc;
 
+	if (pin >= hw->soc->npins)
+		return -EINVAL;
+
 	desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
 
 	switch (param) {
 	case PIN_CONFIG_BIAS_DISABLE:
-		if (hw->soc->bias_disable_get) {
-			err = hw->soc->bias_disable_get(hw, desc, &ret);
-			if (err)
-				return err;
-		} else {
-			return -ENOTSUPP;
-		}
-		break;
 	case PIN_CONFIG_BIAS_PULL_UP:
-		if (hw->soc->bias_get) {
-			err = hw->soc->bias_get(hw, desc, 1, &ret);
-			if (err)
-				return err;
-		} else {
-			return -ENOTSUPP;
-		}
-		break;
 	case PIN_CONFIG_BIAS_PULL_DOWN:
-		if (hw->soc->bias_get) {
-			err = hw->soc->bias_get(hw, desc, 0, &ret);
-			if (err)
-				return err;
-		} else {
-			return -ENOTSUPP;
+		if (!hw->soc->bias_get_combo)
+			break;
+		err = hw->soc->bias_get_combo(hw, desc, &pullup, &ret);
+		if (err)
+			break;
+		if (ret == MTK_PUPD_SET_R1R0_00)
+			ret = MTK_DISABLE;
+		if (param == PIN_CONFIG_BIAS_DISABLE) {
+			if (ret != MTK_DISABLE)
+				err = -EINVAL;
+		} else if (param == PIN_CONFIG_BIAS_PULL_UP) {
+			if (!pullup || ret == MTK_DISABLE)
+				err = -EINVAL;
+		} else if (param == PIN_CONFIG_BIAS_PULL_DOWN) {
+			if (pullup || ret == MTK_DISABLE)
+				err = -EINVAL;
 		}
 		break;
 	case PIN_CONFIG_SLEW_RATE:
-		err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SR, &val);
-		if (err)
-			return err;
-
-		if (!val)
-			return -EINVAL;
-
+		err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SR, &ret);
 		break;
 	case PIN_CONFIG_INPUT_ENABLE:
-	case PIN_CONFIG_OUTPUT_ENABLE:
-		err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &val);
+		err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_IES, &ret);
+		if (!ret)
+			err = -EINVAL;
+		break;
+	case PIN_CONFIG_OUTPUT:
+		err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &ret);
 		if (err)
-			return err;
+			break;
 
-		/* HW takes input mode as zero; output mode as non-zero */
-		if ((val && param == PIN_CONFIG_INPUT_ENABLE) ||
-		    (!val && param == PIN_CONFIG_OUTPUT_ENABLE))
-			return -EINVAL;
+		if (!ret) {
+			err = -EINVAL;
+			break;
+		}
 
+		err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DO, &ret);
 		break;
 	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
-		err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &val);
-		if (err)
-			return err;
-
-		err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SMT, &val2);
+		err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &ret);
 		if (err)
-			return err;
-
-		if (val || !val2)
-			return -EINVAL;
+			break;
+		/* return error when in output mode
+		 * because schmitt trigger only work in input mode
+		 */
+		if (ret) {
+			err = -EINVAL;
+			break;
+		}
 
+		err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SMT, &ret);
+		if (!ret)
+			err = -EINVAL;
 		break;
 	case PIN_CONFIG_DRIVE_STRENGTH:
-		if (hw->soc->drive_get) {
-			err = hw->soc->drive_get(hw, desc, &ret);
-			if (err)
-				return err;
-		} else {
-			err = -ENOTSUPP;
-		}
+		if (!hw->soc->drive_get)
+			break;
+		err = hw->soc->drive_get(hw, desc, &ret);
 		break;
 	case MTK_PIN_CONFIG_TDSEL:
 	case MTK_PIN_CONFIG_RDSEL:
 		reg = (param == MTK_PIN_CONFIG_TDSEL) ?
 		       PINCTRL_PIN_REG_TDSEL : PINCTRL_PIN_REG_RDSEL;
-
-		err = mtk_hw_get_value(hw, desc, reg, &val);
-		if (err)
-			return err;
-
-		ret = val;
-
+		err = mtk_hw_get_value(hw, desc, reg, &ret);
 		break;
 	case MTK_PIN_CONFIG_PU_ADV:
 	case MTK_PIN_CONFIG_PD_ADV:
-		if (hw->soc->adv_pull_get) {
-			bool pullup;
-
-			pullup = param == MTK_PIN_CONFIG_PU_ADV;
-			err = hw->soc->adv_pull_get(hw, desc, pullup, &ret);
-			if (err)
-				return err;
-		} else {
-			return -ENOTSUPP;
-		}
+		if (!hw->soc->adv_pull_get)
+			break;
+		pullup = param == MTK_PIN_CONFIG_PU_ADV;
+		err = hw->soc->adv_pull_get(hw, desc, pullup, &ret);
 		break;
 	case MTK_PIN_CONFIG_DRV_ADV:
-		if (hw->soc->adv_drive_get) {
-			err = hw->soc->adv_drive_get(hw, desc, &ret);
-			if (err)
-				return err;
-		} else {
-			return -ENOTSUPP;
-		}
+		if (!hw->soc->adv_drive_get)
+			break;
+		err = hw->soc->adv_drive_get(hw, desc, &ret);
 		break;
-	default:
-		return -ENOTSUPP;
 	}
 
-	*config = pinconf_to_config_packed(param, ret);
+	if (!err)
+		*config = pinconf_to_config_packed(param, ret);
 
-	return 0;
+	return err;
 }
 
 static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
-			   enum pin_config_param param,
-			   enum pin_config_param arg)
+			   enum pin_config_param param, u32 arg)
 {
 	struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
 	const struct mtk_pin_desc *desc;
-	int err = 0;
+	int err = -ENOTSUPP;
 	u32 reg;
 
+	if (pin >= hw->soc->npins)
+		return -EINVAL;
+
 	desc = (const struct mtk_pin_desc *)&hw->soc->pins[pin];
 
 	switch ((u32)param) {
 	case PIN_CONFIG_BIAS_DISABLE:
-		if (hw->soc->bias_disable_set) {
-			err = hw->soc->bias_disable_set(hw, desc);
-			if (err)
-				return err;
-		} else {
-			return -ENOTSUPP;
-		}
+		if (!hw->soc->bias_set_combo)
+			break;
+		err = hw->soc->bias_set_combo(hw, desc, 0, MTK_DISABLE);
 		break;
 	case PIN_CONFIG_BIAS_PULL_UP:
-		if (hw->soc->bias_set) {
-			err = hw->soc->bias_set(hw, desc, 1);
-			if (err)
-				return err;
-		} else {
-			return -ENOTSUPP;
-		}
+		if (!hw->soc->bias_set_combo)
+			break;
+		err = hw->soc->bias_set_combo(hw, desc, 1, arg);
 		break;
 	case PIN_CONFIG_BIAS_PULL_DOWN:
-		if (hw->soc->bias_set) {
-			err = hw->soc->bias_set(hw, desc, 0);
-			if (err)
-				return err;
-		} else {
-			return -ENOTSUPP;
-		}
-		break;
-	case PIN_CONFIG_OUTPUT_ENABLE:
-		err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT,
-				       MTK_DISABLE);
-		if (err)
-			goto err;
-
-		err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
-				       MTK_OUTPUT);
-		if (err)
-			goto err;
+		if (!hw->soc->bias_set_combo)
+			break;
+		err = hw->soc->bias_set_combo(hw, desc, 0, arg);
 		break;
 	case PIN_CONFIG_INPUT_ENABLE:
-		if (hw->soc->ies_present) {
-			mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_IES,
-					 MTK_ENABLE);
-		}
-
-		err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
-				       MTK_INPUT);
-		if (err)
-			goto err;
+		/* regard all non-zero value as enable */
+		err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_IES, !!arg);
 		break;
 	case PIN_CONFIG_SLEW_RATE:
-		err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SR,
-				       arg);
-		if (err)
-			goto err;
-
+		/* regard all non-zero value as enable */
+		err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SR, !!arg);
 		break;
 	case PIN_CONFIG_OUTPUT:
 		err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
 				       MTK_OUTPUT);
 		if (err)
-			goto err;
+			break;
 
 		err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DO,
 				       arg);
-		if (err)
-			goto err;
 		break;
+	case PIN_CONFIG_INPUT_SCHMITT:
 	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
 		/* arg = 1: Input mode & SMT enable ;
 		 * arg = 0: Output mode & SMT disable
 		 */
-		arg = arg ? 2 : 1;
-		err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
-				       arg & 1);
+		err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR, !arg);
 		if (err)
-			goto err;
+			break;
 
-		err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT,
-				       !!(arg & 2));
-		if (err)
-			goto err;
+		err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT, !!arg);
 		break;
 	case PIN_CONFIG_DRIVE_STRENGTH:
-		if (hw->soc->drive_set) {
-			err = hw->soc->drive_set(hw, desc, arg);
-			if (err)
-				return err;
-		} else {
-			return -ENOTSUPP;
-		}
+		if (!hw->soc->drive_set)
+			break;
+		err = hw->soc->drive_set(hw, desc, arg);
 		break;
 	case MTK_PIN_CONFIG_TDSEL:
 	case MTK_PIN_CONFIG_RDSEL:
 		reg = (param == MTK_PIN_CONFIG_TDSEL) ?
 		       PINCTRL_PIN_REG_TDSEL : PINCTRL_PIN_REG_RDSEL;
-
 		err = mtk_hw_set_value(hw, desc, reg, arg);
-		if (err)
-			goto err;
 		break;
 	case MTK_PIN_CONFIG_PU_ADV:
 	case MTK_PIN_CONFIG_PD_ADV:
-		if (hw->soc->adv_pull_set) {
-			bool pullup;
-
-			pullup = param == MTK_PIN_CONFIG_PU_ADV;
-			err = hw->soc->adv_pull_set(hw, desc, pullup,
-						    arg);
-			if (err)
-				return err;
-		} else {
-			return -ENOTSUPP;
-		}
+		if (!hw->soc->adv_pull_set)
+			break;
+		err = hw->soc->adv_pull_set(hw, desc,
+					    (param == MTK_PIN_CONFIG_PU_ADV),
+					    arg);
 		break;
 	case MTK_PIN_CONFIG_DRV_ADV:
-		if (hw->soc->adv_drive_set) {
-			err = hw->soc->adv_drive_set(hw, desc, arg);
-			if (err)
-				return err;
-		} else {
-			return -ENOTSUPP;
-		}
+		if (!hw->soc->adv_drive_set)
+			break;
+		err = hw->soc->adv_drive_set(hw, desc, arg);
 		break;
-	default:
-		err = -ENOTSUPP;
 	}
 
-err:
 	return err;
 }
 
@@ -647,10 +568,10 @@
 			       unsigned long *config)
 {
 	struct mtk_pinctrl *hw = pinctrl_dev_get_drvdata(pctldev);
+	struct mtk_pinctrl_group *grp = &hw->groups[group];
 
-	*config = hw->groups[group].config;
-
-	return 0;
+	 /* One pin per group only */
+	return mtk_pinconf_get(pctldev, grp->pin, config);
 }
 
 static int mtk_pconf_group_set(struct pinctrl_dev *pctldev, unsigned group,
@@ -666,8 +587,6 @@
 				      pinconf_to_config_argument(configs[i]));
 		if (ret < 0)
 			return ret;
-
-		grp->config = configs[i];
 	}
 
 	return 0;
@@ -693,6 +612,9 @@
 	const struct mtk_pin_desc *desc;
 	int value, err;
 
+	if (gpio >= hw->soc->npins)
+		return -EINVAL;
+
 	desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio];
 
 	err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &value);
@@ -708,6 +630,9 @@
 	const struct mtk_pin_desc *desc;
 	int value, err;
 
+	if (gpio >= hw->soc->npins)
+		return -EINVAL;
+
 	desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio];
 
 	err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DI, &value);
@@ -722,6 +647,9 @@
 	struct mtk_pinctrl *hw = gpiochip_get_data(chip);
 	const struct mtk_pin_desc *desc;
 
+	if (gpio >= hw->soc->npins)
+		return;
+
 	desc = (const struct mtk_pin_desc *)&hw->soc->pins[gpio];
 
 	mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DO, !!value);
@@ -729,12 +657,22 @@
 
 static int mtk_gpio_direction_input(struct gpio_chip *chip, unsigned int gpio)
 {
+	struct mtk_pinctrl *hw = gpiochip_get_data(chip);
+
+	if (gpio >= hw->soc->npins)
+		return -EINVAL;
+
 	return pinctrl_gpio_direction_input(chip->base + gpio);
 }
 
 static int mtk_gpio_direction_output(struct gpio_chip *chip, unsigned int gpio,
 				     int value)
 {
+	struct mtk_pinctrl *hw = gpiochip_get_data(chip);
+
+	if (gpio >= hw->soc->npins)
+		return -EINVAL;
+
 	mtk_gpio_set(chip, gpio, value);
 
 	return pinctrl_gpio_direction_output(chip->base + gpio);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/meson/pinctrl-meson-axg.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/meson/pinctrl-meson-axg.c
@@ -400,6 +400,7 @@
 	GPIO_GROUP(GPIOA_15),
 	GPIO_GROUP(GPIOA_16),
 	GPIO_GROUP(GPIOA_17),
+	GPIO_GROUP(GPIOA_18),
 	GPIO_GROUP(GPIOA_19),
 	GPIO_GROUP(GPIOA_20),
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/meson/pinctrl-meson-gxl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/meson/pinctrl-meson-gxl.c
@@ -147,8 +147,8 @@
 static const unsigned int sdio_d1_pins[]	= { GPIOX_1 };
 static const unsigned int sdio_d2_pins[]	= { GPIOX_2 };
 static const unsigned int sdio_d3_pins[]	= { GPIOX_3 };
-static const unsigned int sdio_cmd_pins[]	= { GPIOX_4 };
-static const unsigned int sdio_clk_pins[]	= { GPIOX_5 };
+static const unsigned int sdio_clk_pins[]	= { GPIOX_4 };
+static const unsigned int sdio_cmd_pins[]	= { GPIOX_5 };
 static const unsigned int sdio_irq_pins[]	= { GPIOX_7 };
 
 static const unsigned int nand_ce0_pins[]	= { BOOT_8 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/meson/pinctrl-meson.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/meson/pinctrl-meson.c
@@ -441,6 +441,7 @@
 		return ret;
 
 	meson_calc_reg_and_bit(bank, pin, REG_DS, &reg, &bit);
+	bit = bit << 1;
 
 	ret = regmap_read(pc->reg_ds, reg, &val);
 	if (ret)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
@@ -166,10 +166,14 @@
 	PIN_GRP_GPIO("jtag", 20, 5, BIT(0), "jtag"),
 	PIN_GRP_GPIO("sdio0", 8, 3, BIT(1), "sdio"),
 	PIN_GRP_GPIO("emmc_nb", 27, 9, BIT(2), "emmc"),
-	PIN_GRP_GPIO("pwm0", 11, 1, BIT(3), "pwm"),
-	PIN_GRP_GPIO("pwm1", 12, 1, BIT(4), "pwm"),
-	PIN_GRP_GPIO("pwm2", 13, 1, BIT(5), "pwm"),
-	PIN_GRP_GPIO("pwm3", 14, 1, BIT(6), "pwm"),
+	PIN_GRP_GPIO_3("pwm0", 11, 1, BIT(3) | BIT(20), 0, BIT(20), BIT(3),
+		       "pwm", "led"),
+	PIN_GRP_GPIO_3("pwm1", 12, 1, BIT(4) | BIT(21), 0, BIT(21), BIT(4),
+		       "pwm", "led"),
+	PIN_GRP_GPIO_3("pwm2", 13, 1, BIT(5) | BIT(22), 0, BIT(22), BIT(5),
+		       "pwm", "led"),
+	PIN_GRP_GPIO_3("pwm3", 14, 1, BIT(6) | BIT(23), 0, BIT(23), BIT(6),
+		       "pwm", "led"),
 	PIN_GRP_GPIO("pmic1", 7, 1, BIT(7), "pmic"),
 	PIN_GRP_GPIO("pmic0", 6, 1, BIT(8), "pmic"),
 	PIN_GRP_GPIO("i2c2", 2, 2, BIT(9), "i2c"),
@@ -183,11 +187,6 @@
 	PIN_GRP_EXTRA("uart2", 9, 2, BIT(1) | BIT(13) | BIT(14) | BIT(19),
 		      BIT(1) | BIT(13) | BIT(14), BIT(1) | BIT(19),
 		      18, 2, "gpio", "uart"),
-	PIN_GRP_GPIO_2("led0_od", 11, 1, BIT(20), BIT(20), 0, "led"),
-	PIN_GRP_GPIO_2("led1_od", 12, 1, BIT(21), BIT(21), 0, "led"),
-	PIN_GRP_GPIO_2("led2_od", 13, 1, BIT(22), BIT(22), 0, "led"),
-	PIN_GRP_GPIO_2("led3_od", 14, 1, BIT(23), BIT(23), 0, "led"),
-
 };
 
 static struct armada_37xx_pin_group armada_37xx_sb_groups[] = {
@@ -595,10 +594,10 @@
 		regmap_read(info->regmap, in_reg, &in_val);
 
 		/* Set initial polarity based on current input level. */
-		if (in_val & d->mask)
-			val |= d->mask;		/* falling */
+		if (in_val & BIT(d->hwirq % GPIO_PER_REG))
+			val |= BIT(d->hwirq % GPIO_PER_REG);	/* falling */
 		else
-			val &= ~d->mask;	/* rising */
+			val &= ~(BIT(d->hwirq % GPIO_PER_REG));	/* rising */
 		break;
 	}
 	default:
@@ -774,7 +773,7 @@
 	for (i = 0; i < nr_irq_parent; i++) {
 		int irq = irq_of_parse_and_map(np, i);
 
-		if (irq < 0)
+		if (!irq)
 			continue;
 
 		gpiochip_set_chained_irqchip(gc, irqchip, irq,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/mvebu/pinctrl-armada-xp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/mvebu/pinctrl-armada-xp.c
@@ -414,7 +414,7 @@
 		 MPP_VAR_FUNCTION(0x1, "i2c0", "sck",        V_98DX3236_PLUS)),
 	MPP_MODE(15,
 		 MPP_VAR_FUNCTION(0x0, "gpio", NULL,         V_98DX3236_PLUS),
-		 MPP_VAR_FUNCTION(0x4, "i2c0", "sda",        V_98DX3236_PLUS)),
+		 MPP_VAR_FUNCTION(0x1, "i2c0", "sda",        V_98DX3236_PLUS)),
 	MPP_MODE(16,
 		 MPP_VAR_FUNCTION(0x0, "gpo", NULL,          V_98DX3236_PLUS),
 		 MPP_VAR_FUNCTION(0x4, "dev", "oe",          V_98DX3236_PLUS)),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/mvebu/pinctrl-dove.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/mvebu/pinctrl-dove.c
@@ -769,7 +769,7 @@
 		of_match_device(dove_pinctrl_of_match, &pdev->dev);
 	struct mvebu_mpp_ctrl_data *mpp_data;
 	void __iomem *base;
-	int i;
+	int i, ret;
 
 	pdev->dev.platform_data = (void *)match->data;
 
@@ -786,13 +786,17 @@
 
 	mpp_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	base = devm_ioremap_resource(&pdev->dev, mpp_res);
-	if (IS_ERR(base))
-		return PTR_ERR(base);
+	if (IS_ERR(base)) {
+		ret = PTR_ERR(base);
+		goto err_probe;
+	}
 
 	mpp_data = devm_kcalloc(&pdev->dev, dove_pinctrl_info.ncontrols,
 				sizeof(*mpp_data), GFP_KERNEL);
-	if (!mpp_data)
-		return -ENOMEM;
+	if (!mpp_data) {
+		ret = -ENOMEM;
+		goto err_probe;
+	}
 
 	dove_pinctrl_info.control_data = mpp_data;
 	for (i = 0; i < ARRAY_SIZE(dove_mpp_controls); i++)
@@ -811,8 +815,10 @@
 	}
 
 	mpp4_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(mpp4_base))
-		return PTR_ERR(mpp4_base);
+	if (IS_ERR(mpp4_base)) {
+		ret = PTR_ERR(mpp4_base);
+		goto err_probe;
+	}
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
 	if (!res) {
@@ -823,8 +829,10 @@
 	}
 
 	pmu_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(pmu_base))
-		return PTR_ERR(pmu_base);
+	if (IS_ERR(pmu_base)) {
+		ret = PTR_ERR(pmu_base);
+		goto err_probe;
+	}
 
 	gconfmap = syscon_regmap_lookup_by_compatible("marvell,dove-global-config");
 	if (IS_ERR(gconfmap)) {
@@ -834,12 +842,17 @@
 		adjust_resource(&fb_res,
 			(mpp_res->start & INT_REGS_MASK) + GC_REGS_OFFS, 0x14);
 		gc_base = devm_ioremap_resource(&pdev->dev, &fb_res);
-		if (IS_ERR(gc_base))
-			return PTR_ERR(gc_base);
+		if (IS_ERR(gc_base)) {
+			ret = PTR_ERR(gc_base);
+			goto err_probe;
+		}
+
 		gconfmap = devm_regmap_init_mmio(&pdev->dev,
 						 gc_base, &gc_regmap_config);
-		if (IS_ERR(gconfmap))
-			return PTR_ERR(gconfmap);
+		if (IS_ERR(gconfmap)) {
+			ret = PTR_ERR(gconfmap);
+			goto err_probe;
+		}
 	}
 
 	/* Warn on any missing DT resource */
@@ -847,6 +860,9 @@
 		dev_warn(&pdev->dev, FW_BUG "Missing pinctrl regs in DTB. Please update your firmware.\n");
 
 	return mvebu_pinctrl_probe(pdev);
+err_probe:
+	clk_disable_unprepare(clk);
+	return ret;
 }
 
 static struct platform_driver dove_pinctrl_driver = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/nomadik/pinctrl-nomadik.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/nomadik/pinctrl-nomadik.c
@@ -1461,8 +1461,10 @@
 
 	has_config = nmk_pinctrl_dt_get_config(np, &configs);
 	np_config = of_parse_phandle(np, "ste,config", 0);
-	if (np_config)
+	if (np_config) {
 		has_config |= nmk_pinctrl_dt_get_config(np_config, &configs);
+		of_node_put(np_config);
+	}
 	if (has_config) {
 		const char *gpio_name;
 		const char *pin;
@@ -1923,8 +1925,10 @@
 	}
 
 	prcm_np = of_parse_phandle(np, "prcm", 0);
-	if (prcm_np)
+	if (prcm_np) {
 		npct->prcm_base = of_iomap(prcm_np, 0);
+		of_node_put(prcm_np);
+	}
 	if (!npct->prcm_base) {
 		if (version == PINCTRL_NMK_STN8815) {
 			dev_info(&pdev->dev,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c
@@ -78,7 +78,6 @@
 	struct gpio_chip	gc;
 	int			irqbase;
 	int			irq;
-	void			*priv;
 	struct irq_chip		irq_chip;
 	u32			pinctrl_id;
 	int (*direction_input)(struct gpio_chip *chip, unsigned offset);
@@ -226,7 +225,7 @@
 	chained_irq_enter(chip, desc);
 	sts = ioread32(bank->base + NPCM7XX_GP_N_EVST);
 	en  = ioread32(bank->base + NPCM7XX_GP_N_EVEN);
-	dev_dbg(chip->parent_device, "==> got irq sts %.8x %.8x\n", sts,
+	dev_dbg(bank->gc.parent, "==> got irq sts %.8x %.8x\n", sts,
 		en);
 
 	sts &= en;
@@ -241,33 +240,33 @@
 		gpiochip_get_data(irq_data_get_irq_chip_data(d));
 	unsigned int gpio = BIT(d->hwirq);
 
-	dev_dbg(d->chip->parent_device, "setirqtype: %u.%u = %u\n", gpio,
+	dev_dbg(bank->gc.parent, "setirqtype: %u.%u = %u\n", gpio,
 		d->irq, type);
 	switch (type) {
 	case IRQ_TYPE_EDGE_RISING:
-		dev_dbg(d->chip->parent_device, "edge.rising\n");
+		dev_dbg(bank->gc.parent, "edge.rising\n");
 		npcm_gpio_clr(&bank->gc, bank->base + NPCM7XX_GP_N_EVBE, gpio);
 		npcm_gpio_clr(&bank->gc, bank->base + NPCM7XX_GP_N_POL, gpio);
 		break;
 	case IRQ_TYPE_EDGE_FALLING:
-		dev_dbg(d->chip->parent_device, "edge.falling\n");
+		dev_dbg(bank->gc.parent, "edge.falling\n");
 		npcm_gpio_clr(&bank->gc, bank->base + NPCM7XX_GP_N_EVBE, gpio);
 		npcm_gpio_set(&bank->gc, bank->base + NPCM7XX_GP_N_POL, gpio);
 		break;
 	case IRQ_TYPE_EDGE_BOTH:
-		dev_dbg(d->chip->parent_device, "edge.both\n");
+		dev_dbg(bank->gc.parent, "edge.both\n");
 		npcm_gpio_set(&bank->gc, bank->base + NPCM7XX_GP_N_EVBE, gpio);
 		break;
 	case IRQ_TYPE_LEVEL_LOW:
-		dev_dbg(d->chip->parent_device, "level.low\n");
+		dev_dbg(bank->gc.parent, "level.low\n");
 		npcm_gpio_set(&bank->gc, bank->base + NPCM7XX_GP_N_POL, gpio);
 		break;
 	case IRQ_TYPE_LEVEL_HIGH:
-		dev_dbg(d->chip->parent_device, "level.high\n");
+		dev_dbg(bank->gc.parent, "level.high\n");
 		npcm_gpio_clr(&bank->gc, bank->base + NPCM7XX_GP_N_POL, gpio);
 		break;
 	default:
-		dev_dbg(d->chip->parent_device, "invalid irq type\n");
+		dev_dbg(bank->gc.parent, "invalid irq type\n");
 		return -EINVAL;
 	}
 
@@ -289,7 +288,7 @@
 		gpiochip_get_data(irq_data_get_irq_chip_data(d));
 	unsigned int gpio = d->hwirq;
 
-	dev_dbg(d->chip->parent_device, "irq_ack: %u.%u\n", gpio, d->irq);
+	dev_dbg(bank->gc.parent, "irq_ack: %u.%u\n", gpio, d->irq);
 	iowrite32(BIT(gpio), bank->base + NPCM7XX_GP_N_EVST);
 }
 
@@ -301,7 +300,7 @@
 	unsigned int gpio = d->hwirq;
 
 	/* Clear events */
-	dev_dbg(d->chip->parent_device, "irq_mask: %u.%u\n", gpio, d->irq);
+	dev_dbg(bank->gc.parent, "irq_mask: %u.%u\n", gpio, d->irq);
 	iowrite32(BIT(gpio), bank->base + NPCM7XX_GP_N_EVENC);
 }
 
@@ -313,7 +312,7 @@
 	unsigned int gpio = d->hwirq;
 
 	/* Enable events */
-	dev_dbg(d->chip->parent_device, "irq_unmask: %u.%u\n", gpio, d->irq);
+	dev_dbg(bank->gc.parent, "irq_unmask: %u.%u\n", gpio, d->irq);
 	iowrite32(BIT(gpio), bank->base + NPCM7XX_GP_N_EVENS);
 }
 
@@ -323,7 +322,7 @@
 	unsigned int gpio = d->hwirq;
 
 	/* active-high, input, clear interrupt, enable interrupt */
-	dev_dbg(d->chip->parent_device, "startup: %u.%u\n", gpio, d->irq);
+	dev_dbg(gc->parent, "startup: %u.%u\n", gpio, d->irq);
 	npcmgpio_direction_input(gc, gpio);
 	npcmgpio_irq_ack(d);
 	npcmgpio_irq_unmask(d);
@@ -905,7 +904,7 @@
 #define DRIVE_STRENGTH_HI_SHIFT		12
 #define DRIVE_STRENGTH_MASK		0x0000FF00
 
-#define DS(lo, hi)	(((lo) << DRIVE_STRENGTH_LO_SHIFT) | \
+#define DSTR(lo, hi)	(((lo) << DRIVE_STRENGTH_LO_SHIFT) | \
 			 ((hi) << DRIVE_STRENGTH_HI_SHIFT))
 #define DSLO(x)		(((x) >> DRIVE_STRENGTH_LO_SHIFT) & 0xF)
 #define DSHI(x)		(((x) >> DRIVE_STRENGTH_HI_SHIFT) & 0xF)
@@ -925,31 +924,31 @@
 static const struct npcm7xx_pincfg pincfg[] = {
 	/*	PIN	  FUNCTION 1		   FUNCTION 2		  FUNCTION 3	    FLAGS */
 	NPCM7XX_PINCFG(0,	 iox1, MFSEL1, 30,	  none, NONE, 0,	none, NONE, 0,	     0),
-	NPCM7XX_PINCFG(1,	 iox1, MFSEL1, 30,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12)),
-	NPCM7XX_PINCFG(2,	 iox1, MFSEL1, 30,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12)),
+	NPCM7XX_PINCFG(1,	 iox1, MFSEL1, 30,	  none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12)),
+	NPCM7XX_PINCFG(2,	 iox1, MFSEL1, 30,	  none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12)),
 	NPCM7XX_PINCFG(3,	 iox1, MFSEL1, 30,	  none, NONE, 0,	none, NONE, 0,	     0),
 	NPCM7XX_PINCFG(4,	 iox2, MFSEL3, 14,	 smb1d, I2CSEGSEL, 7,	none, NONE, 0,	     SLEW),
 	NPCM7XX_PINCFG(5,	 iox2, MFSEL3, 14,	 smb1d, I2CSEGSEL, 7,	none, NONE, 0,	     SLEW),
 	NPCM7XX_PINCFG(6,	 iox2, MFSEL3, 14,	 smb2d, I2CSEGSEL, 10,  none, NONE, 0,       SLEW),
 	NPCM7XX_PINCFG(7,	 iox2, MFSEL3, 14,	 smb2d, I2CSEGSEL, 10,  none, NONE, 0,       SLEW),
-	NPCM7XX_PINCFG(8,      lkgpo1, FLOCKR1, 4,        none, NONE, 0,	none, NONE, 0,	     DS(8, 12)),
-	NPCM7XX_PINCFG(9,      lkgpo2, FLOCKR1, 8,        none, NONE, 0,	none, NONE, 0,	     DS(8, 12)),
-	NPCM7XX_PINCFG(10,	 ioxh, MFSEL3, 18,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12)),
-	NPCM7XX_PINCFG(11,	 ioxh, MFSEL3, 18,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12)),
+	NPCM7XX_PINCFG(8,      lkgpo1, FLOCKR1, 4,        none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12)),
+	NPCM7XX_PINCFG(9,      lkgpo2, FLOCKR1, 8,        none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12)),
+	NPCM7XX_PINCFG(10,	 ioxh, MFSEL3, 18,	  none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12)),
+	NPCM7XX_PINCFG(11,	 ioxh, MFSEL3, 18,	  none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12)),
 	NPCM7XX_PINCFG(12,	 gspi, MFSEL1, 24,	 smb5b, I2CSEGSEL, 19,  none, NONE, 0,	     SLEW),
 	NPCM7XX_PINCFG(13,	 gspi, MFSEL1, 24,	 smb5b, I2CSEGSEL, 19,  none, NONE, 0,	     SLEW),
 	NPCM7XX_PINCFG(14,	 gspi, MFSEL1, 24,	 smb5c, I2CSEGSEL, 20,	none, NONE, 0,	     SLEW),
 	NPCM7XX_PINCFG(15,	 gspi, MFSEL1, 24,	 smb5c, I2CSEGSEL, 20,	none, NONE, 0,	     SLEW),
-	NPCM7XX_PINCFG(16,     lkgpo0, FLOCKR1, 0,        none, NONE, 0,	none, NONE, 0,	     DS(8, 12)),
-	NPCM7XX_PINCFG(17,      pspi2, MFSEL3, 13,     smb4den, I2CSEGSEL, 23,  none, NONE, 0,       DS(8, 12)),
-	NPCM7XX_PINCFG(18,      pspi2, MFSEL3, 13,	 smb4b, I2CSEGSEL, 14,  none, NONE, 0,	     DS(8, 12)),
-	NPCM7XX_PINCFG(19,      pspi2, MFSEL3, 13,	 smb4b, I2CSEGSEL, 14,  none, NONE, 0,	     DS(8, 12)),
+	NPCM7XX_PINCFG(16,     lkgpo0, FLOCKR1, 0,        none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12)),
+	NPCM7XX_PINCFG(17,      pspi2, MFSEL3, 13,     smb4den, I2CSEGSEL, 23,  none, NONE, 0,       DSTR(8, 12)),
+	NPCM7XX_PINCFG(18,      pspi2, MFSEL3, 13,	 smb4b, I2CSEGSEL, 14,  none, NONE, 0,	     DSTR(8, 12)),
+	NPCM7XX_PINCFG(19,      pspi2, MFSEL3, 13,	 smb4b, I2CSEGSEL, 14,  none, NONE, 0,	     DSTR(8, 12)),
 	NPCM7XX_PINCFG(20,	smb4c, I2CSEGSEL, 15,    smb15, MFSEL3, 8,      none, NONE, 0,	     0),
 	NPCM7XX_PINCFG(21,	smb4c, I2CSEGSEL, 15,    smb15, MFSEL3, 8,      none, NONE, 0,	     0),
 	NPCM7XX_PINCFG(22,      smb4d, I2CSEGSEL, 16,	 smb14, MFSEL3, 7,      none, NONE, 0,	     0),
 	NPCM7XX_PINCFG(23,      smb4d, I2CSEGSEL, 16,	 smb14, MFSEL3, 7,      none, NONE, 0,	     0),
-	NPCM7XX_PINCFG(24,	 ioxh, MFSEL3, 18,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12)),
-	NPCM7XX_PINCFG(25,	 ioxh, MFSEL3, 18,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12)),
+	NPCM7XX_PINCFG(24,	 ioxh, MFSEL3, 18,	  none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12)),
+	NPCM7XX_PINCFG(25,	 ioxh, MFSEL3, 18,	  none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12)),
 	NPCM7XX_PINCFG(26,	 smb5, MFSEL1, 2,	  none, NONE, 0,	none, NONE, 0,	     0),
 	NPCM7XX_PINCFG(27,	 smb5, MFSEL1, 2,	  none, NONE, 0,	none, NONE, 0,	     0),
 	NPCM7XX_PINCFG(28,	 smb4, MFSEL1, 1,	  none, NONE, 0,	none, NONE, 0,	     0),
@@ -965,12 +964,12 @@
 	NPCM7XX_PINCFG(39,	smb3b, I2CSEGSEL, 11,	  none, NONE, 0,	none, NONE, 0,	     SLEW),
 	NPCM7XX_PINCFG(40,	smb3b, I2CSEGSEL, 11,	  none, NONE, 0,	none, NONE, 0,	     SLEW),
 	NPCM7XX_PINCFG(41,  bmcuart0a, MFSEL1, 9,         none, NONE, 0,	none, NONE, 0,	     0),
-	NPCM7XX_PINCFG(42,  bmcuart0a, MFSEL1, 9,         none, NONE, 0,	none, NONE, 0,	     DS(2, 4) | GPO),
+	NPCM7XX_PINCFG(42,  bmcuart0a, MFSEL1, 9,         none, NONE, 0,	none, NONE, 0,	     DSTR(2, 4) | GPO),
 	NPCM7XX_PINCFG(43,      uart1, MFSEL1, 10,	 jtag2, MFSEL4, 0,  bmcuart1, MFSEL3, 24,    0),
 	NPCM7XX_PINCFG(44,      uart1, MFSEL1, 10,	 jtag2, MFSEL4, 0,  bmcuart1, MFSEL3, 24,    0),
 	NPCM7XX_PINCFG(45,      uart1, MFSEL1, 10,	 jtag2, MFSEL4, 0,	none, NONE, 0,	     0),
-	NPCM7XX_PINCFG(46,      uart1, MFSEL1, 10,	 jtag2, MFSEL4, 0,	none, NONE, 0,	     DS(2, 8)),
-	NPCM7XX_PINCFG(47,      uart1, MFSEL1, 10,	 jtag2, MFSEL4, 0,	none, NONE, 0,	     DS(2, 8)),
+	NPCM7XX_PINCFG(46,      uart1, MFSEL1, 10,	 jtag2, MFSEL4, 0,	none, NONE, 0,	     DSTR(2, 8)),
+	NPCM7XX_PINCFG(47,      uart1, MFSEL1, 10,	 jtag2, MFSEL4, 0,	none, NONE, 0,	     DSTR(2, 8)),
 	NPCM7XX_PINCFG(48,	uart2, MFSEL1, 11,   bmcuart0b, MFSEL4, 1,      none, NONE, 0,	     GPO),
 	NPCM7XX_PINCFG(49,	uart2, MFSEL1, 11,   bmcuart0b, MFSEL4, 1,      none, NONE, 0,	     0),
 	NPCM7XX_PINCFG(50,	uart2, MFSEL1, 11,	  none, NONE, 0,        none, NONE, 0,	     0),
@@ -980,8 +979,8 @@
 	NPCM7XX_PINCFG(54,	uart2, MFSEL1, 11,	  none, NONE, 0,        none, NONE, 0,	     0),
 	NPCM7XX_PINCFG(55,	uart2, MFSEL1, 11,	  none, NONE, 0,        none, NONE, 0,	     0),
 	NPCM7XX_PINCFG(56,	r1err, MFSEL1, 12,	  none, NONE, 0,	none, NONE, 0,	     0),
-	NPCM7XX_PINCFG(57,       r1md, MFSEL1, 13,        none, NONE, 0,        none, NONE, 0,       DS(2, 4)),
-	NPCM7XX_PINCFG(58,       r1md, MFSEL1, 13,        none, NONE, 0,	none, NONE, 0,	     DS(2, 4)),
+	NPCM7XX_PINCFG(57,       r1md, MFSEL1, 13,        none, NONE, 0,        none, NONE, 0,       DSTR(2, 4)),
+	NPCM7XX_PINCFG(58,       r1md, MFSEL1, 13,        none, NONE, 0,	none, NONE, 0,	     DSTR(2, 4)),
 	NPCM7XX_PINCFG(59,	smb3d, I2CSEGSEL, 13,	  none, NONE, 0,	none, NONE, 0,	     0),
 	NPCM7XX_PINCFG(60,	smb3d, I2CSEGSEL, 13,	  none, NONE, 0,	none, NONE, 0,	     0),
 	NPCM7XX_PINCFG(61,      uart1, MFSEL1, 10,	  none, NONE, 0,	none, NONE, 0,     GPO),
@@ -1004,19 +1003,19 @@
 	NPCM7XX_PINCFG(77,    fanin13, MFSEL2, 13,        none, NONE, 0,	none, NONE, 0,	     0),
 	NPCM7XX_PINCFG(78,    fanin14, MFSEL2, 14,        none, NONE, 0,	none, NONE, 0,	     0),
 	NPCM7XX_PINCFG(79,    fanin15, MFSEL2, 15,        none, NONE, 0,	none, NONE, 0,	     0),
-	NPCM7XX_PINCFG(80,	 pwm0, MFSEL2, 16,        none, NONE, 0,	none, NONE, 0,	     DS(4, 8)),
-	NPCM7XX_PINCFG(81,	 pwm1, MFSEL2, 17,        none, NONE, 0,	none, NONE, 0,	     DS(4, 8)),
-	NPCM7XX_PINCFG(82,	 pwm2, MFSEL2, 18,        none, NONE, 0,	none, NONE, 0,	     DS(4, 8)),
-	NPCM7XX_PINCFG(83,	 pwm3, MFSEL2, 19,        none, NONE, 0,	none, NONE, 0,	     DS(4, 8)),
-	NPCM7XX_PINCFG(84,         r2, MFSEL1, 14,        none, NONE, 0,        none, NONE, 0,	     DS(8, 12) | SLEW),
-	NPCM7XX_PINCFG(85,         r2, MFSEL1, 14,        none, NONE, 0,        none, NONE, 0,	     DS(8, 12) | SLEW),
-	NPCM7XX_PINCFG(86,         r2, MFSEL1, 14,        none, NONE, 0,        none, NONE, 0,	     DS(8, 12) | SLEW),
+	NPCM7XX_PINCFG(80,	 pwm0, MFSEL2, 16,        none, NONE, 0,	none, NONE, 0,	     DSTR(4, 8)),
+	NPCM7XX_PINCFG(81,	 pwm1, MFSEL2, 17,        none, NONE, 0,	none, NONE, 0,	     DSTR(4, 8)),
+	NPCM7XX_PINCFG(82,	 pwm2, MFSEL2, 18,        none, NONE, 0,	none, NONE, 0,	     DSTR(4, 8)),
+	NPCM7XX_PINCFG(83,	 pwm3, MFSEL2, 19,        none, NONE, 0,	none, NONE, 0,	     DSTR(4, 8)),
+	NPCM7XX_PINCFG(84,         r2, MFSEL1, 14,        none, NONE, 0,        none, NONE, 0,	     DSTR(8, 12) | SLEW),
+	NPCM7XX_PINCFG(85,         r2, MFSEL1, 14,        none, NONE, 0,        none, NONE, 0,	     DSTR(8, 12) | SLEW),
+	NPCM7XX_PINCFG(86,         r2, MFSEL1, 14,        none, NONE, 0,        none, NONE, 0,	     DSTR(8, 12) | SLEW),
 	NPCM7XX_PINCFG(87,         r2, MFSEL1, 14,        none, NONE, 0,        none, NONE, 0,	     0),
 	NPCM7XX_PINCFG(88,         r2, MFSEL1, 14,        none, NONE, 0,        none, NONE, 0,	     0),
 	NPCM7XX_PINCFG(89,         r2, MFSEL1, 14,        none, NONE, 0,        none, NONE, 0,	     0),
 	NPCM7XX_PINCFG(90,      r2err, MFSEL1, 15,        none, NONE, 0,        none, NONE, 0,       0),
-	NPCM7XX_PINCFG(91,       r2md, MFSEL1, 16,	  none, NONE, 0,        none, NONE, 0,	     DS(2, 4)),
-	NPCM7XX_PINCFG(92,       r2md, MFSEL1, 16,	  none, NONE, 0,        none, NONE, 0,	     DS(2, 4)),
+	NPCM7XX_PINCFG(91,       r2md, MFSEL1, 16,	  none, NONE, 0,        none, NONE, 0,	     DSTR(2, 4)),
+	NPCM7XX_PINCFG(92,       r2md, MFSEL1, 16,	  none, NONE, 0,        none, NONE, 0,	     DSTR(2, 4)),
 	NPCM7XX_PINCFG(93,    ga20kbc, MFSEL1, 17,	 smb5d, I2CSEGSEL, 21,  none, NONE, 0,	     0),
 	NPCM7XX_PINCFG(94,    ga20kbc, MFSEL1, 17,	 smb5d, I2CSEGSEL, 21,  none, NONE, 0,	     0),
 	NPCM7XX_PINCFG(95,	  lpc, NONE, 0,		  espi, MFSEL4, 8,      gpio, MFSEL1, 26,    0),
@@ -1062,34 +1061,34 @@
 	NPCM7XX_PINCFG(133,	smb10, MFSEL4, 13,	  none, NONE, 0,	none, NONE, 0,	     0),
 	NPCM7XX_PINCFG(134,	smb11, MFSEL4, 14,	  none, NONE, 0,	none, NONE, 0,	     0),
 	NPCM7XX_PINCFG(135,	smb11, MFSEL4, 14,	  none, NONE, 0,	none, NONE, 0,	     0),
-	NPCM7XX_PINCFG(136,	  sd1, MFSEL3, 12,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
-	NPCM7XX_PINCFG(137,	  sd1, MFSEL3, 12,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
-	NPCM7XX_PINCFG(138,	  sd1, MFSEL3, 12,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
-	NPCM7XX_PINCFG(139,	  sd1, MFSEL3, 12,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
-	NPCM7XX_PINCFG(140,	  sd1, MFSEL3, 12,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
+	NPCM7XX_PINCFG(136,	  sd1, MFSEL3, 12,	  none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12) | SLEW),
+	NPCM7XX_PINCFG(137,	  sd1, MFSEL3, 12,	  none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12) | SLEW),
+	NPCM7XX_PINCFG(138,	  sd1, MFSEL3, 12,	  none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12) | SLEW),
+	NPCM7XX_PINCFG(139,	  sd1, MFSEL3, 12,	  none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12) | SLEW),
+	NPCM7XX_PINCFG(140,	  sd1, MFSEL3, 12,	  none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12) | SLEW),
 	NPCM7XX_PINCFG(141,	  sd1, MFSEL3, 12,	  none, NONE, 0,	none, NONE, 0,	     0),
-	NPCM7XX_PINCFG(142,	  sd1, MFSEL3, 12,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
+	NPCM7XX_PINCFG(142,	  sd1, MFSEL3, 12,	  none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12) | SLEW),
 	NPCM7XX_PINCFG(143,       sd1, MFSEL3, 12,      sd1pwr, MFSEL4, 5,      none, NONE, 0,       0),
-	NPCM7XX_PINCFG(144,	 pwm4, MFSEL2, 20,	  none, NONE, 0,	none, NONE, 0,	     DS(4, 8)),
-	NPCM7XX_PINCFG(145,	 pwm5, MFSEL2, 21,	  none, NONE, 0,	none, NONE, 0,	     DS(4, 8)),
-	NPCM7XX_PINCFG(146,	 pwm6, MFSEL2, 22,	  none, NONE, 0,	none, NONE, 0,	     DS(4, 8)),
-	NPCM7XX_PINCFG(147,	 pwm7, MFSEL2, 23,	  none, NONE, 0,	none, NONE, 0,	     DS(4, 8)),
-	NPCM7XX_PINCFG(148,	 mmc8, MFSEL3, 11,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
-	NPCM7XX_PINCFG(149,	 mmc8, MFSEL3, 11,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
-	NPCM7XX_PINCFG(150,	 mmc8, MFSEL3, 11,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
-	NPCM7XX_PINCFG(151,	 mmc8, MFSEL3, 11,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
-	NPCM7XX_PINCFG(152,	  mmc, MFSEL3, 10,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
+	NPCM7XX_PINCFG(144,	 pwm4, MFSEL2, 20,	  none, NONE, 0,	none, NONE, 0,	     DSTR(4, 8)),
+	NPCM7XX_PINCFG(145,	 pwm5, MFSEL2, 21,	  none, NONE, 0,	none, NONE, 0,	     DSTR(4, 8)),
+	NPCM7XX_PINCFG(146,	 pwm6, MFSEL2, 22,	  none, NONE, 0,	none, NONE, 0,	     DSTR(4, 8)),
+	NPCM7XX_PINCFG(147,	 pwm7, MFSEL2, 23,	  none, NONE, 0,	none, NONE, 0,	     DSTR(4, 8)),
+	NPCM7XX_PINCFG(148,	 mmc8, MFSEL3, 11,	  none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12) | SLEW),
+	NPCM7XX_PINCFG(149,	 mmc8, MFSEL3, 11,	  none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12) | SLEW),
+	NPCM7XX_PINCFG(150,	 mmc8, MFSEL3, 11,	  none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12) | SLEW),
+	NPCM7XX_PINCFG(151,	 mmc8, MFSEL3, 11,	  none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12) | SLEW),
+	NPCM7XX_PINCFG(152,	  mmc, MFSEL3, 10,	  none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12) | SLEW),
 	NPCM7XX_PINCFG(153,     mmcwp, FLOCKR1, 24,       none, NONE, 0,	none, NONE, 0,	     0),  /* Z1/A1 */
-	NPCM7XX_PINCFG(154,	  mmc, MFSEL3, 10,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
+	NPCM7XX_PINCFG(154,	  mmc, MFSEL3, 10,	  none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12) | SLEW),
 	NPCM7XX_PINCFG(155,     mmccd, MFSEL3, 25,      mmcrst, MFSEL4, 6,      none, NONE, 0,       0),  /* Z1/A1 */
-	NPCM7XX_PINCFG(156,	  mmc, MFSEL3, 10,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
-	NPCM7XX_PINCFG(157,	  mmc, MFSEL3, 10,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
-	NPCM7XX_PINCFG(158,	  mmc, MFSEL3, 10,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
-	NPCM7XX_PINCFG(159,	  mmc, MFSEL3, 10,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
-
-	NPCM7XX_PINCFG(160,    clkout, MFSEL1, 21,        none, NONE, 0,        none, NONE, 0,	     DS(8, 12) | SLEW),
-	NPCM7XX_PINCFG(161,	  lpc, NONE, 0,		  espi, MFSEL4, 8,      gpio, MFSEL1, 26,    DS(8, 12)),
-	NPCM7XX_PINCFG(162,    serirq, NONE, 0,           gpio, MFSEL1, 31,	none, NONE, 0,	     DS(8, 12)),
+	NPCM7XX_PINCFG(156,	  mmc, MFSEL3, 10,	  none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12) | SLEW),
+	NPCM7XX_PINCFG(157,	  mmc, MFSEL3, 10,	  none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12) | SLEW),
+	NPCM7XX_PINCFG(158,	  mmc, MFSEL3, 10,	  none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12) | SLEW),
+	NPCM7XX_PINCFG(159,	  mmc, MFSEL3, 10,	  none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12) | SLEW),
+
+	NPCM7XX_PINCFG(160,    clkout, MFSEL1, 21,        none, NONE, 0,        none, NONE, 0,	     DSTR(8, 12) | SLEW),
+	NPCM7XX_PINCFG(161,	  lpc, NONE, 0,		  espi, MFSEL4, 8,      gpio, MFSEL1, 26,    DSTR(8, 12)),
+	NPCM7XX_PINCFG(162,    serirq, NONE, 0,           gpio, MFSEL1, 31,	none, NONE, 0,	     DSTR(8, 12)),
 	NPCM7XX_PINCFG(163,	  lpc, NONE, 0,		  espi, MFSEL4, 8,      gpio, MFSEL1, 26,    0),
 	NPCM7XX_PINCFG(164,	  lpc, NONE, 0,		  espi, MFSEL4, 8,      gpio, MFSEL1, 26,    SLEWLPC),
 	NPCM7XX_PINCFG(165,	  lpc, NONE, 0,		  espi, MFSEL4, 8,      gpio, MFSEL1, 26,    SLEWLPC),
@@ -1102,25 +1101,25 @@
 	NPCM7XX_PINCFG(172,	 smb6, MFSEL3, 1,	  none, NONE, 0,	none, NONE, 0,	     0),
 	NPCM7XX_PINCFG(173,	 smb7, MFSEL3, 2,	  none, NONE, 0,	none, NONE, 0,	     0),
 	NPCM7XX_PINCFG(174,	 smb7, MFSEL3, 2,	  none, NONE, 0,	none, NONE, 0,	     0),
-	NPCM7XX_PINCFG(175,	pspi1, MFSEL3, 4,       faninx, MFSEL3, 3,      none, NONE, 0,	     DS(8, 12)),
-	NPCM7XX_PINCFG(176,     pspi1, MFSEL3, 4,       faninx, MFSEL3, 3,      none, NONE, 0,	     DS(8, 12)),
-	NPCM7XX_PINCFG(177,     pspi1, MFSEL3, 4,       faninx, MFSEL3, 3,      none, NONE, 0,	     DS(8, 12)),
-	NPCM7XX_PINCFG(178,	   r1, MFSEL3, 9,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
-	NPCM7XX_PINCFG(179,	   r1, MFSEL3, 9,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
-	NPCM7XX_PINCFG(180,	   r1, MFSEL3, 9,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
+	NPCM7XX_PINCFG(175,	pspi1, MFSEL3, 4,       faninx, MFSEL3, 3,      none, NONE, 0,	     DSTR(8, 12)),
+	NPCM7XX_PINCFG(176,     pspi1, MFSEL3, 4,       faninx, MFSEL3, 3,      none, NONE, 0,	     DSTR(8, 12)),
+	NPCM7XX_PINCFG(177,     pspi1, MFSEL3, 4,       faninx, MFSEL3, 3,      none, NONE, 0,	     DSTR(8, 12)),
+	NPCM7XX_PINCFG(178,	   r1, MFSEL3, 9,	  none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12) | SLEW),
+	NPCM7XX_PINCFG(179,	   r1, MFSEL3, 9,	  none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12) | SLEW),
+	NPCM7XX_PINCFG(180,	   r1, MFSEL3, 9,	  none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12) | SLEW),
 	NPCM7XX_PINCFG(181,	   r1, MFSEL3, 9,	  none, NONE, 0,	none, NONE, 0,	     0),
 	NPCM7XX_PINCFG(182,	   r1, MFSEL3, 9,	  none, NONE, 0,	none, NONE, 0,	     0),
-	NPCM7XX_PINCFG(183,     spi3, MFSEL4, 16,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
-	NPCM7XX_PINCFG(184,     spi3, MFSEL4, 16,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW | GPO),
-	NPCM7XX_PINCFG(185,     spi3, MFSEL4, 16,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW | GPO),
-	NPCM7XX_PINCFG(186,     spi3, MFSEL4, 16,	  none, NONE, 0,	none, NONE, 0,	     DS(8, 12)),
-	NPCM7XX_PINCFG(187,   spi3cs1, MFSEL4, 17,        none, NONE, 0,	none, NONE, 0,	     DS(8, 12)),
-	NPCM7XX_PINCFG(188,  spi3quad, MFSEL4, 20,     spi3cs2, MFSEL4, 18,     none, NONE, 0,    DS(8, 12) | SLEW),
-	NPCM7XX_PINCFG(189,  spi3quad, MFSEL4, 20,     spi3cs3, MFSEL4, 19,     none, NONE, 0,    DS(8, 12) | SLEW),
-	NPCM7XX_PINCFG(190,      gpio, FLOCKR1, 20,   nprd_smi, NONE, 0,	none, NONE, 0,	     DS(2, 4)),
-	NPCM7XX_PINCFG(191,	 none, NONE, 0,		  none, NONE, 0,	none, NONE, 0,	     DS(8, 12)),  /* XX */
+	NPCM7XX_PINCFG(183,     spi3, MFSEL4, 16,	  none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12) | SLEW),
+	NPCM7XX_PINCFG(184,     spi3, MFSEL4, 16,	  none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12) | SLEW | GPO),
+	NPCM7XX_PINCFG(185,     spi3, MFSEL4, 16,	  none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12) | SLEW | GPO),
+	NPCM7XX_PINCFG(186,     spi3, MFSEL4, 16,	  none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12)),
+	NPCM7XX_PINCFG(187,   spi3cs1, MFSEL4, 17,        none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12)),
+	NPCM7XX_PINCFG(188,  spi3quad, MFSEL4, 20,     spi3cs2, MFSEL4, 18,     none, NONE, 0,    DSTR(8, 12) | SLEW),
+	NPCM7XX_PINCFG(189,  spi3quad, MFSEL4, 20,     spi3cs3, MFSEL4, 19,     none, NONE, 0,    DSTR(8, 12) | SLEW),
+	NPCM7XX_PINCFG(190,      gpio, FLOCKR1, 20,   nprd_smi, NONE, 0,	none, NONE, 0,	     DSTR(2, 4)),
+	NPCM7XX_PINCFG(191,	 none, NONE, 0,		  none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12)),  /* XX */
 
-	NPCM7XX_PINCFG(192,	 none, NONE, 0,		  none, NONE, 0,	none, NONE, 0,	     DS(8, 12)),  /* XX */
+	NPCM7XX_PINCFG(192,	 none, NONE, 0,		  none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12)),  /* XX */
 	NPCM7XX_PINCFG(193,	   r1, MFSEL3, 9,	  none, NONE, 0,	none, NONE, 0,	     0),
 	NPCM7XX_PINCFG(194,	smb0b, I2CSEGSEL, 0,	  none, NONE, 0,	none, NONE, 0,	     0),
 	NPCM7XX_PINCFG(195,	smb0b, I2CSEGSEL, 0,	  none, NONE, 0,	none, NONE, 0,	     0),
@@ -1131,11 +1130,11 @@
 	NPCM7XX_PINCFG(200,        r2, MFSEL1, 14,        none, NONE, 0,        none, NONE, 0,       0),
 	NPCM7XX_PINCFG(201,	   r1, MFSEL3, 9,	  none, NONE, 0,	none, NONE, 0,	     0),
 	NPCM7XX_PINCFG(202,	smb0c, I2CSEGSEL, 1,	  none, NONE, 0,	none, NONE, 0,	     0),
-	NPCM7XX_PINCFG(203,    faninx, MFSEL3, 3,         none, NONE, 0,	none, NONE, 0,	     DS(8, 12)),
+	NPCM7XX_PINCFG(203,    faninx, MFSEL3, 3,         none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12)),
 	NPCM7XX_PINCFG(204,	  ddc, NONE, 0,           gpio, MFSEL3, 22,	none, NONE, 0,	     SLEW),
 	NPCM7XX_PINCFG(205,	  ddc, NONE, 0,           gpio, MFSEL3, 22,	none, NONE, 0,	     SLEW),
-	NPCM7XX_PINCFG(206,	  ddc, NONE, 0,           gpio, MFSEL3, 22,	none, NONE, 0,	     DS(4, 8)),
-	NPCM7XX_PINCFG(207,	  ddc, NONE, 0,           gpio, MFSEL3, 22,	none, NONE, 0,	     DS(4, 8)),
+	NPCM7XX_PINCFG(206,	  ddc, NONE, 0,           gpio, MFSEL3, 22,	none, NONE, 0,	     DSTR(4, 8)),
+	NPCM7XX_PINCFG(207,	  ddc, NONE, 0,           gpio, MFSEL3, 22,	none, NONE, 0,	     DSTR(4, 8)),
 	NPCM7XX_PINCFG(208,       rg2, MFSEL4, 24,         ddr, MFSEL3, 26,     none, NONE, 0,       0),
 	NPCM7XX_PINCFG(209,       rg2, MFSEL4, 24,         ddr, MFSEL3, 26,     none, NONE, 0,       0),
 	NPCM7XX_PINCFG(210,       rg2, MFSEL4, 24,         ddr, MFSEL3, 26,     none, NONE, 0,       0),
@@ -1147,20 +1146,20 @@
 	NPCM7XX_PINCFG(216,   rg2mdio, MFSEL4, 23,         ddr, MFSEL3, 26,     none, NONE, 0,       0),
 	NPCM7XX_PINCFG(217,   rg2mdio, MFSEL4, 23,         ddr, MFSEL3, 26,     none, NONE, 0,       0),
 	NPCM7XX_PINCFG(218,     wdog1, MFSEL3, 19,        none, NONE, 0,	none, NONE, 0,	     0),
-	NPCM7XX_PINCFG(219,     wdog2, MFSEL3, 20,        none, NONE, 0,	none, NONE, 0,	     DS(4, 8)),
+	NPCM7XX_PINCFG(219,     wdog2, MFSEL3, 20,        none, NONE, 0,	none, NONE, 0,	     DSTR(4, 8)),
 	NPCM7XX_PINCFG(220,	smb12, MFSEL3, 5,	  none, NONE, 0,	none, NONE, 0,	     0),
 	NPCM7XX_PINCFG(221,	smb12, MFSEL3, 5,	  none, NONE, 0,	none, NONE, 0,	     0),
 	NPCM7XX_PINCFG(222,     smb13, MFSEL3, 6,         none, NONE, 0,	none, NONE, 0,	     0),
 	NPCM7XX_PINCFG(223,     smb13, MFSEL3, 6,         none, NONE, 0,	none, NONE, 0,	     0),
 
 	NPCM7XX_PINCFG(224,	 spix, MFSEL4, 27,        none, NONE, 0,	none, NONE, 0,	     SLEW),
-	NPCM7XX_PINCFG(225,	 spix, MFSEL4, 27,        none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW | GPO),
-	NPCM7XX_PINCFG(226,	 spix, MFSEL4, 27,        none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW | GPO),
-	NPCM7XX_PINCFG(227,	 spix, MFSEL4, 27,        none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
-	NPCM7XX_PINCFG(228,   spixcs1, MFSEL4, 28,        none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
-	NPCM7XX_PINCFG(229,	 spix, MFSEL4, 27,        none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
-	NPCM7XX_PINCFG(230,	 spix, MFSEL4, 27,        none, NONE, 0,	none, NONE, 0,	     DS(8, 12) | SLEW),
-	NPCM7XX_PINCFG(231,    clkreq, MFSEL4, 9,         none, NONE, 0,        none, NONE, 0,	     DS(8, 12)),
+	NPCM7XX_PINCFG(225,	 spix, MFSEL4, 27,        none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12) | SLEW | GPO),
+	NPCM7XX_PINCFG(226,	 spix, MFSEL4, 27,        none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12) | SLEW | GPO),
+	NPCM7XX_PINCFG(227,	 spix, MFSEL4, 27,        none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12) | SLEW),
+	NPCM7XX_PINCFG(228,   spixcs1, MFSEL4, 28,        none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12) | SLEW),
+	NPCM7XX_PINCFG(229,	 spix, MFSEL4, 27,        none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12) | SLEW),
+	NPCM7XX_PINCFG(230,	 spix, MFSEL4, 27,        none, NONE, 0,	none, NONE, 0,	     DSTR(8, 12) | SLEW),
+	NPCM7XX_PINCFG(231,    clkreq, MFSEL4, 9,         none, NONE, 0,        none, NONE, 0,	     DSTR(8, 12)),
 	NPCM7XX_PINCFG(253,	 none, NONE, 0,		  none, NONE, 0,	none, NONE, 0,	     GPI), /* SDHC1 power */
 	NPCM7XX_PINCFG(254,	 none, NONE, 0,		  none, NONE, 0,	none, NONE, 0,	     GPI), /* SDHC2 power */
 	NPCM7XX_PINCFG(255,	 none, NONE, 0,		  none, NONE, 0,	none, NONE, 0,	     GPI), /* DACOSEL */
@@ -1561,7 +1560,7 @@
 {
 	struct npcm7xx_pinctrl *npcm = pinctrl_dev_get_drvdata(pctldev);
 
-	dev_dbg(npcm->dev, "group size: %d\n", ARRAY_SIZE(npcm7xx_groups));
+	dev_dbg(npcm->dev, "group size: %zu\n", ARRAY_SIZE(npcm7xx_groups));
 	return ARRAY_SIZE(npcm7xx_groups);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/pinconf-generic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/pinconf-generic.c
@@ -30,10 +30,10 @@
 	PCONFDUMP(PIN_CONFIG_BIAS_BUS_HOLD, "input bias bus hold", NULL, false),
 	PCONFDUMP(PIN_CONFIG_BIAS_DISABLE, "input bias disabled", NULL, false),
 	PCONFDUMP(PIN_CONFIG_BIAS_HIGH_IMPEDANCE, "input bias high impedance", NULL, false),
-	PCONFDUMP(PIN_CONFIG_BIAS_PULL_DOWN, "input bias pull down", NULL, false),
+	PCONFDUMP(PIN_CONFIG_BIAS_PULL_DOWN, "input bias pull down", "ohms", true),
 	PCONFDUMP(PIN_CONFIG_BIAS_PULL_PIN_DEFAULT,
-				"input bias pull to pin specific state", NULL, false),
-	PCONFDUMP(PIN_CONFIG_BIAS_PULL_UP, "input bias pull up", NULL, false),
+				"input bias pull to pin specific state", "ohms", true),
+	PCONFDUMP(PIN_CONFIG_BIAS_PULL_UP, "input bias pull up", "ohms", true),
 	PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_DRAIN, "output drive open drain", NULL, false),
 	PCONFDUMP(PIN_CONFIG_DRIVE_OPEN_SOURCE, "output drive open source", NULL, false),
 	PCONFDUMP(PIN_CONFIG_DRIVE_PUSH_PULL, "output drive push pull", NULL, false),
@@ -391,8 +391,10 @@
 	for_each_available_child_of_node(np_config, np) {
 		ret = pinconf_generic_dt_subnode_to_map(pctldev, np, map,
 					&reserved_maps, num_maps, type);
-		if (ret < 0)
+		if (ret < 0) {
+			of_node_put(np);
 			goto exit;
+		}
 	}
 	return 0;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/pinctrl-amd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/pinctrl-amd.c
@@ -123,6 +123,14 @@
 	struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
 
 	raw_spin_lock_irqsave(&gpio_dev->lock, flags);
+
+	/* Use special handling for Pin0 debounce */
+	if (offset == 0) {
+		pin_reg = readl(gpio_dev->base + WAKE_INT_MASTER_REG);
+		if (pin_reg & INTERNAL_GPIO0_DEBOUNCE)
+			debounce = 0;
+	}
+
 	pin_reg = readl(gpio_dev->base + offset * 4);
 
 	if (debounce) {
@@ -153,7 +161,7 @@
 			pin_reg |= BIT(DB_TMR_OUT_UNIT_OFF);
 			pin_reg &= ~BIT(DB_TMR_LARGE_OFF);
 		} else if (debounce < 250000) {
-			time = debounce / 15600;
+			time = debounce / 15625;
 			pin_reg |= time & DB_TMR_OUT_MASK;
 			pin_reg &= ~BIT(DB_TMR_OUT_UNIT_OFF);
 			pin_reg |= BIT(DB_TMR_LARGE_OFF);
@@ -163,14 +171,14 @@
 			pin_reg |= BIT(DB_TMR_OUT_UNIT_OFF);
 			pin_reg |= BIT(DB_TMR_LARGE_OFF);
 		} else {
-			pin_reg &= ~DB_CNTRl_MASK;
+			pin_reg &= ~(DB_CNTRl_MASK << DB_CNTRL_OFF);
 			ret = -EINVAL;
 		}
 	} else {
 		pin_reg &= ~BIT(DB_TMR_OUT_UNIT_OFF);
 		pin_reg &= ~BIT(DB_TMR_LARGE_OFF);
 		pin_reg &= ~DB_TMR_OUT_MASK;
-		pin_reg &= ~DB_CNTRl_MASK;
+		pin_reg &= ~(DB_CNTRl_MASK << DB_CNTRL_OFF);
 	}
 	writel(pin_reg, gpio_dev->base + offset * 4);
 	raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
@@ -178,18 +186,6 @@
 	return ret;
 }
 
-static int amd_gpio_set_config(struct gpio_chip *gc, unsigned offset,
-			       unsigned long config)
-{
-	u32 debounce;
-
-	if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
-		return -ENOTSUPP;
-
-	debounce = pinconf_to_config_argument(config);
-	return amd_gpio_set_debounce(gc, offset, debounce);
-}
-
 #ifdef CONFIG_DEBUG_FS
 static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc)
 {
@@ -212,6 +208,7 @@
 	char *output_value;
 	char *output_enable;
 
+	seq_printf(s, "WAKE_INT_MASTER_REG: 0x%08x\n", readl(gpio_dev->base + WAKE_INT_MASTER_REG));
 	for (bank = 0; bank < gpio_dev->hwbank_num; bank++) {
 		seq_printf(s, "GPIO bank%d\t", bank);
 
@@ -435,7 +432,6 @@
 		pin_reg &= ~BIT(LEVEL_TRIG_OFF);
 		pin_reg &= ~(ACTIVE_LEVEL_MASK << ACTIVE_LEVEL_OFF);
 		pin_reg |= ACTIVE_HIGH << ACTIVE_LEVEL_OFF;
-		pin_reg |= DB_TYPE_REMOVE_GLITCH << DB_CNTRL_OFF;
 		irq_set_handler_locked(d, handle_edge_irq);
 		break;
 
@@ -443,7 +439,6 @@
 		pin_reg &= ~BIT(LEVEL_TRIG_OFF);
 		pin_reg &= ~(ACTIVE_LEVEL_MASK << ACTIVE_LEVEL_OFF);
 		pin_reg |= ACTIVE_LOW << ACTIVE_LEVEL_OFF;
-		pin_reg |= DB_TYPE_REMOVE_GLITCH << DB_CNTRL_OFF;
 		irq_set_handler_locked(d, handle_edge_irq);
 		break;
 
@@ -451,7 +446,6 @@
 		pin_reg &= ~BIT(LEVEL_TRIG_OFF);
 		pin_reg &= ~(ACTIVE_LEVEL_MASK << ACTIVE_LEVEL_OFF);
 		pin_reg |= BOTH_EADGE << ACTIVE_LEVEL_OFF;
-		pin_reg |= DB_TYPE_REMOVE_GLITCH << DB_CNTRL_OFF;
 		irq_set_handler_locked(d, handle_edge_irq);
 		break;
 
@@ -459,8 +453,6 @@
 		pin_reg |= LEVEL_TRIGGER << LEVEL_TRIG_OFF;
 		pin_reg &= ~(ACTIVE_LEVEL_MASK << ACTIVE_LEVEL_OFF);
 		pin_reg |= ACTIVE_HIGH << ACTIVE_LEVEL_OFF;
-		pin_reg &= ~(DB_CNTRl_MASK << DB_CNTRL_OFF);
-		pin_reg |= DB_TYPE_PRESERVE_LOW_GLITCH << DB_CNTRL_OFF;
 		irq_set_handler_locked(d, handle_level_irq);
 		break;
 
@@ -468,8 +460,6 @@
 		pin_reg |= LEVEL_TRIGGER << LEVEL_TRIG_OFF;
 		pin_reg &= ~(ACTIVE_LEVEL_MASK << ACTIVE_LEVEL_OFF);
 		pin_reg |= ACTIVE_LOW << ACTIVE_LEVEL_OFF;
-		pin_reg &= ~(DB_CNTRl_MASK << DB_CNTRL_OFF);
-		pin_reg |= DB_TYPE_PRESERVE_HIGH_GLITCH << DB_CNTRL_OFF;
 		irq_set_handler_locked(d, handle_level_irq);
 		break;
 
@@ -540,7 +530,8 @@
 	irqreturn_t ret = IRQ_NONE;
 	unsigned int i, irqnr;
 	unsigned long flags;
-	u32 *regs, regval;
+	u32 __iomem *regs;
+	u32  regval;
 	u64 status, mask;
 
 	/* Read the wake status */
@@ -668,7 +659,7 @@
 		break;
 
 	default:
-		dev_err(&gpio_dev->pdev->dev, "Invalid config param %04x\n",
+		dev_dbg(&gpio_dev->pdev->dev, "Invalid config param %04x\n",
 			param);
 		return -ENOTSUPP;
 	}
@@ -679,7 +670,7 @@
 }
 
 static int amd_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
-				unsigned long *configs, unsigned num_configs)
+			   unsigned long *configs, unsigned int num_configs)
 {
 	int i;
 	u32 arg;
@@ -721,7 +712,7 @@
 			break;
 
 		default:
-			dev_err(&gpio_dev->pdev->dev,
+			dev_dbg(&gpio_dev->pdev->dev,
 				"Invalid config param %04x\n", param);
 			ret = -ENOTSUPP;
 		}
@@ -769,6 +760,20 @@
 	return 0;
 }
 
+static int amd_gpio_set_config(struct gpio_chip *gc, unsigned int pin,
+			       unsigned long config)
+{
+	struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
+
+	if (pinconf_to_config_param(config) == PIN_CONFIG_INPUT_DEBOUNCE) {
+		u32 debounce = pinconf_to_config_argument(config);
+
+		return amd_gpio_set_debounce(gc, pin, debounce);
+	}
+
+	return amd_pinconf_set(gpio_dev->pctrl, pin, &config, 1);
+}
+
 static const struct pinconf_ops amd_pinconf_ops = {
 	.pin_config_get		= amd_pinconf_get,
 	.pin_config_set		= amd_pinconf_set,
@@ -776,6 +781,34 @@
 	.pin_config_group_set = amd_pinconf_group_set,
 };
 
+static void amd_gpio_irq_init(struct amd_gpio *gpio_dev)
+{
+	struct pinctrl_desc *desc = gpio_dev->pctrl->desc;
+	unsigned long flags;
+	u32 pin_reg, mask;
+	int i;
+
+	mask = BIT(WAKE_CNTRL_OFF_S0I3) | BIT(WAKE_CNTRL_OFF_S3) |
+		BIT(INTERRUPT_MASK_OFF) | BIT(INTERRUPT_ENABLE_OFF) |
+		BIT(WAKE_CNTRL_OFF_S4);
+
+	for (i = 0; i < desc->npins; i++) {
+		int pin = desc->pins[i].number;
+		const struct pin_desc *pd = pin_desc_get(gpio_dev->pctrl, pin);
+
+		if (!pd)
+			continue;
+
+		raw_spin_lock_irqsave(&gpio_dev->lock, flags);
+
+		pin_reg = readl(gpio_dev->base + pin * 4);
+		pin_reg &= ~mask;
+		writel(pin_reg, gpio_dev->base + pin * 4);
+
+		raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
+	}
+}
+
 #ifdef CONFIG_PM_SLEEP
 static bool amd_gpio_should_save(struct amd_gpio *gpio_dev, unsigned int pin)
 {
@@ -799,6 +832,7 @@
 {
 	struct amd_gpio *gpio_dev = dev_get_drvdata(dev);
 	struct pinctrl_desc *desc = gpio_dev->pctrl->desc;
+	unsigned long flags;
 	int i;
 
 	for (i = 0; i < desc->npins; i++) {
@@ -807,7 +841,9 @@
 		if (!amd_gpio_should_save(gpio_dev, pin))
 			continue;
 
-		gpio_dev->saved_regs[i] = readl(gpio_dev->base + pin*4);
+		raw_spin_lock_irqsave(&gpio_dev->lock, flags);
+		gpio_dev->saved_regs[i] = readl(gpio_dev->base + pin * 4) & ~PIN_IRQ_PENDING;
+		raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
 	}
 
 	return 0;
@@ -817,6 +853,7 @@
 {
 	struct amd_gpio *gpio_dev = dev_get_drvdata(dev);
 	struct pinctrl_desc *desc = gpio_dev->pctrl->desc;
+	unsigned long flags;
 	int i;
 
 	for (i = 0; i < desc->npins; i++) {
@@ -825,7 +862,10 @@
 		if (!amd_gpio_should_save(gpio_dev, pin))
 			continue;
 
-		writel(gpio_dev->saved_regs[i], gpio_dev->base + pin*4);
+		raw_spin_lock_irqsave(&gpio_dev->lock, flags);
+		gpio_dev->saved_regs[i] |= readl(gpio_dev->base + pin * 4) & PIN_IRQ_PENDING;
+		writel(gpio_dev->saved_regs[i], gpio_dev->base + pin * 4);
+		raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
 	}
 
 	return 0;
@@ -851,6 +891,7 @@
 	int irq_base;
 	struct resource *res;
 	struct amd_gpio *gpio_dev;
+	struct gpio_irq_chip *girq;
 
 	gpio_dev = devm_kzalloc(&pdev->dev,
 				sizeof(struct amd_gpio), GFP_KERNEL);
@@ -912,6 +953,18 @@
 		return PTR_ERR(gpio_dev->pctrl);
 	}
 
+	/* Disable and mask interrupts */
+	amd_gpio_irq_init(gpio_dev);
+
+	girq = &gpio_dev->gc.irq;
+	girq->chip = &amd_gpio_irqchip;
+	/* This will let us handle the parent IRQ in the driver */
+	girq->parent_handler = NULL;
+	girq->num_parents = 0;
+	girq->parents = NULL;
+	girq->default_type = IRQ_TYPE_NONE;
+	girq->handler = handle_simple_irq;
+
 	ret = gpiochip_add_data(&gpio_dev->gc, gpio_dev);
 	if (ret)
 		return ret;
@@ -923,17 +976,6 @@
 		goto out2;
 	}
 
-	ret = gpiochip_irqchip_add(&gpio_dev->gc,
-				&amd_gpio_irqchip,
-				0,
-				handle_simple_irq,
-				IRQ_TYPE_NONE);
-	if (ret) {
-		dev_err(&pdev->dev, "could not add irqchip\n");
-		ret = -ENODEV;
-		goto out2;
-	}
-
 	ret = devm_request_irq(&pdev->dev, irq_base, amd_gpio_irq_handler,
 			       IRQF_SHARED, KBUILD_MODNAME, gpio_dev);
 	if (ret)
@@ -964,6 +1006,7 @@
 static const struct acpi_device_id amd_gpio_acpi_match[] = {
 	{ "AMD0030", 0 },
 	{ "AMDI0030", 0},
+	{ "AMDI0031", 0},
 	{ },
 };
 MODULE_DEVICE_TABLE(acpi, amd_gpio_acpi_match);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/pinctrl-amd.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/pinctrl-amd.h
@@ -17,6 +17,7 @@
 #define AMD_GPIO_PINS_BANK3     32
 
 #define WAKE_INT_MASTER_REG 0xfc
+#define INTERNAL_GPIO0_DEBOUNCE (1 << 15)
 #define EOI_MASK (1 << 29)
 
 #define WAKE_INT_STATUS_REG0 0x2f8
@@ -252,7 +253,7 @@
 	{
 		.name = "uart0",
 		.pins = uart0_pins,
-		.npins = 9,
+		.npins = 5,
 	},
 	{
 		.name = "uart1",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/pinctrl-at91-pio4.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/pinctrl-at91-pio4.c
@@ -928,6 +928,13 @@
 	}
 };
 
+/*
+ * This lock class allows to tell lockdep that parent IRQ and children IRQ do
+ * not share the same class so it does not raise false positive
+ */
+static struct lock_class_key atmel_lock_key;
+static struct lock_class_key atmel_request_key;
+
 static int atmel_pinctrl_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -1011,8 +1018,10 @@
 
 		pin_desc[i].number = i;
 		/* Pin naming convention: P(bank_name)(bank_pin_number). */
-		pin_desc[i].name = kasprintf(GFP_KERNEL, "P%c%d",
-					     bank + 'A', line);
+		pin_desc[i].name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "P%c%d",
+						  bank + 'A', line);
+		if (!pin_desc[i].name)
+			return -ENOMEM;
 
 		group->name = group_names[i] = pin_desc[i].name;
 		group->pin = pin_desc[i].number;
@@ -1069,7 +1078,6 @@
 		dev_err(dev, "can't add the irq domain\n");
 		return -ENODEV;
 	}
-	atmel_pioctrl->irq_domain->name = "atmel gpio";
 
 	for (i = 0; i < atmel_pioctrl->npins; i++) {
 		int irq = irq_create_mapping(atmel_pioctrl->irq_domain, i);
@@ -1077,6 +1085,7 @@
 		irq_set_chip_and_handler(irq, &atmel_gpio_irq_chip,
 					 handle_simple_irq);
 		irq_set_chip_data(irq, atmel_pioctrl);
+		irq_set_lockdep_class(irq, &atmel_lock_key, &atmel_request_key);
 		dev_dbg(dev,
 			"atmel gpio irq domain: hwirq: %d, linux irq: %d\n",
 			i, irq);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/pinctrl-at91.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/pinctrl-at91.c
@@ -1398,8 +1398,11 @@
 
 	/* We will handle a range of GPIO pins */
 	for (i = 0; i < gpio_banks; i++)
-		if (gpio_chips[i])
+		if (gpio_chips[i]) {
 			pinctrl_add_gpio_range(info->pctl, &gpio_chips[i]->range);
+			gpiochip_add_pin_range(&gpio_chips[i]->chip, dev_name(info->pctl->dev), 0,
+				gpio_chips[i]->range.pin_base, gpio_chips[i]->range.npins);
+		}
 
 	dev_info(&pdev->dev, "initialized AT91 pinctrl driver\n");
 
@@ -1891,7 +1894,7 @@
 	}
 
 	for (i = 0; i < chip->ngpio; i++)
-		names[i] = kasprintf(GFP_KERNEL, "pio%c%d", alias_idx + 'A', i);
+		names[i] = devm_kasprintf(&pdev->dev, GFP_KERNEL, "pio%c%d", alias_idx + 'A', i);
 
 	chip->names = (const char *const *)names;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/pinctrl-falcon.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/pinctrl-falcon.c
@@ -431,27 +431,31 @@
 
 	/* load and remap the pad resources of the different banks */
 	for_each_compatible_node(np, NULL, "lantiq,pad-falcon") {
-		struct platform_device *ppdev = of_find_device_by_node(np);
 		const __be32 *bank = of_get_property(np, "lantiq,bank", NULL);
 		struct resource res;
+		struct platform_device *ppdev;
 		u32 avail;
 		int pins;
 
 		if (!of_device_is_available(np))
 			continue;
 
-		if (!ppdev) {
-			dev_err(&pdev->dev, "failed to find pad pdev\n");
-			continue;
-		}
 		if (!bank || *bank >= PORTS)
 			continue;
 		if (of_address_to_resource(np, 0, &res))
 			continue;
+
+		ppdev = of_find_device_by_node(np);
+		if (!ppdev) {
+			dev_err(&pdev->dev, "failed to find pad pdev\n");
+			continue;
+		}
+
 		falcon_info.clk[*bank] = clk_get(&ppdev->dev, NULL);
+		put_device(&ppdev->dev);
 		if (IS_ERR(falcon_info.clk[*bank])) {
 			dev_err(&ppdev->dev, "failed to get clock\n");
-			of_node_put(np)
+			of_node_put(np);
 			return PTR_ERR(falcon_info.clk[*bank]);
 		}
 		falcon_info.membase[*bank] = devm_ioremap_resource(&pdev->dev,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/pinctrl-ingenic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/pinctrl-ingenic.c
@@ -348,7 +348,7 @@
 };
 
 static const u32 jz4760_pull_ups[6] = {
-	0xffffffff, 0xfffcf3ff, 0xffffffff, 0xffffcfff, 0xfffffb7c, 0xfffff00f,
+	0xffffffff, 0xfffcf3ff, 0xffffffff, 0xffffcfff, 0xfffffb7c, 0x0000000f,
 };
 
 static const u32 jz4760_pull_downs[6] = {
@@ -611,11 +611,11 @@
 };
 
 static const u32 jz4770_pull_ups[6] = {
-	0x3fffffff, 0xfff0030c, 0xffffffff, 0xffff4fff, 0xfffffb7c, 0xffa7f00f,
+	0x3fffffff, 0xfff0f3fc, 0xffffffff, 0xffff4fff, 0xfffffb7c, 0x0024f00f,
 };
 
 static const u32 jz4770_pull_downs[6] = {
-	0x00000000, 0x000f0c03, 0x00000000, 0x0000b000, 0x00000483, 0x00580ff0,
+	0x00000000, 0x000f0c03, 0x00000000, 0x0000b000, 0x00000483, 0x005b0ff0,
 };
 
 static int jz4770_uart0_data_pins[] = { 0xa0, 0xa3, };
@@ -1378,7 +1378,7 @@
 static void ingenic_gpio_set_value(struct ingenic_gpio_chip *jzgc,
 				   u8 offset, int value)
 {
-	if (jzgc->jzpc->version >= ID_JZ4760)
+	if (jzgc->jzpc->version >= ID_JZ4770)
 		ingenic_gpio_set_bit(jzgc, JZ4760_GPIO_PAT0, offset, !!value);
 	else
 		ingenic_gpio_set_bit(jzgc, JZ4740_GPIO_DATA, offset, !!value);
@@ -1389,7 +1389,7 @@
 {
 	u8 reg1, reg2;
 
-	if (jzgc->jzpc->version >= ID_JZ4760) {
+	if (jzgc->jzpc->version >= ID_JZ4770) {
 		reg1 = JZ4760_GPIO_PAT1;
 		reg2 = JZ4760_GPIO_PAT0;
 	} else {
@@ -1464,7 +1464,7 @@
 	struct ingenic_gpio_chip *jzgc = gpiochip_get_data(gc);
 	int irq = irqd->hwirq;
 
-	if (jzgc->jzpc->version >= ID_JZ4760)
+	if (jzgc->jzpc->version >= ID_JZ4770)
 		ingenic_gpio_set_bit(jzgc, JZ4760_GPIO_INT, irq, true);
 	else
 		ingenic_gpio_set_bit(jzgc, JZ4740_GPIO_SELECT, irq, true);
@@ -1480,7 +1480,7 @@
 
 	ingenic_gpio_irq_mask(irqd);
 
-	if (jzgc->jzpc->version >= ID_JZ4760)
+	if (jzgc->jzpc->version >= ID_JZ4770)
 		ingenic_gpio_set_bit(jzgc, JZ4760_GPIO_INT, irq, false);
 	else
 		ingenic_gpio_set_bit(jzgc, JZ4740_GPIO_SELECT, irq, false);
@@ -1500,12 +1500,12 @@
 		 */
 		high = ingenic_gpio_get_value(jzgc, irq);
 		if (high)
-			irq_set_type(jzgc, irq, IRQ_TYPE_EDGE_FALLING);
+			irq_set_type(jzgc, irq, IRQ_TYPE_LEVEL_LOW);
 		else
-			irq_set_type(jzgc, irq, IRQ_TYPE_EDGE_RISING);
+			irq_set_type(jzgc, irq, IRQ_TYPE_LEVEL_HIGH);
 	}
 
-	if (jzgc->jzpc->version >= ID_JZ4760)
+	if (jzgc->jzpc->version >= ID_JZ4770)
 		ingenic_gpio_set_bit(jzgc, JZ4760_GPIO_FLAG, irq, false);
 	else
 		ingenic_gpio_set_bit(jzgc, JZ4740_GPIO_DATA, irq, true);
@@ -1538,7 +1538,7 @@
 		 */
 		bool high = ingenic_gpio_get_value(jzgc, irqd->hwirq);
 
-		type = high ? IRQ_TYPE_EDGE_FALLING : IRQ_TYPE_EDGE_RISING;
+		type = high ? IRQ_TYPE_LEVEL_LOW : IRQ_TYPE_LEVEL_HIGH;
 	}
 
 	irq_set_type(jzgc, irqd->hwirq, type);
@@ -1562,7 +1562,7 @@
 
 	chained_irq_enter(irq_chip, desc);
 
-	if (jzgc->jzpc->version >= ID_JZ4760)
+	if (jzgc->jzpc->version >= ID_JZ4770)
 		flag = ingenic_gpio_read_reg(jzgc, JZ4760_GPIO_FLAG);
 	else
 		flag = ingenic_gpio_read_reg(jzgc, JZ4740_GPIO_FLAG);
@@ -1643,8 +1643,9 @@
 	struct ingenic_pinctrl *jzpc = jzgc->jzpc;
 	unsigned int pin = gc->base + offset;
 
-	if (jzpc->version >= ID_JZ4760)
-		return ingenic_get_pin_config(jzpc, pin, JZ4760_GPIO_PAT1);
+	if (jzpc->version >= ID_JZ4770)
+		return ingenic_get_pin_config(jzpc, pin, JZ4760_GPIO_INT) ||
+			ingenic_get_pin_config(jzpc, pin, JZ4760_GPIO_PAT1);
 
 	if (ingenic_get_pin_config(jzpc, pin, JZ4740_GPIO_SELECT))
 		return true;
@@ -1675,7 +1676,7 @@
 		ingenic_shadow_config_pin(jzpc, pin, JZ4760_GPIO_PAT1, func & 0x2);
 		ingenic_shadow_config_pin(jzpc, pin, JZ4760_GPIO_PAT0, func & 0x1);
 		ingenic_shadow_config_pin_load(jzpc, pin);
-	} else if (jzpc->version >= ID_JZ4760) {
+	} else if (jzpc->version >= ID_JZ4770) {
 		ingenic_config_pin(jzpc, pin, JZ4760_GPIO_INT, false);
 		ingenic_config_pin(jzpc, pin, GPIO_MSK, false);
 		ingenic_config_pin(jzpc, pin, JZ4760_GPIO_PAT1, func & 0x2);
@@ -1683,7 +1684,7 @@
 	} else {
 		ingenic_config_pin(jzpc, pin, JZ4740_GPIO_FUNC, true);
 		ingenic_config_pin(jzpc, pin, JZ4740_GPIO_TRIG, func & 0x2);
-		ingenic_config_pin(jzpc, pin, JZ4740_GPIO_SELECT, func > 0);
+		ingenic_config_pin(jzpc, pin, JZ4740_GPIO_SELECT, func & 0x1);
 	}
 
 	return 0;
@@ -1733,7 +1734,7 @@
 		ingenic_shadow_config_pin(jzpc, pin, GPIO_MSK, true);
 		ingenic_shadow_config_pin(jzpc, pin, JZ4760_GPIO_PAT1, input);
 		ingenic_shadow_config_pin_load(jzpc, pin);
-	} else if (jzpc->version >= ID_JZ4760) {
+	} else if (jzpc->version >= ID_JZ4770) {
 		ingenic_config_pin(jzpc, pin, JZ4760_GPIO_INT, false);
 		ingenic_config_pin(jzpc, pin, GPIO_MSK, true);
 		ingenic_config_pin(jzpc, pin, JZ4760_GPIO_PAT1, input);
@@ -1763,7 +1764,7 @@
 	unsigned int offt = pin / PINS_PER_GPIO_CHIP;
 	bool pull;
 
-	if (jzpc->version >= ID_JZ4760)
+	if (jzpc->version >= ID_JZ4770)
 		pull = !ingenic_get_pin_config(jzpc, pin, JZ4760_GPIO_PEN);
 	else
 		pull = !ingenic_get_pin_config(jzpc, pin, JZ4740_GPIO_PULL_DIS);
@@ -1795,7 +1796,7 @@
 static void ingenic_set_bias(struct ingenic_pinctrl *jzpc,
 		unsigned int pin, bool enabled)
 {
-	if (jzpc->version >= ID_JZ4760)
+	if (jzpc->version >= ID_JZ4770)
 		ingenic_config_pin(jzpc, pin, JZ4760_GPIO_PEN, !enabled);
 	else
 		ingenic_config_pin(jzpc, pin, JZ4740_GPIO_PULL_DIS, !enabled);
@@ -1845,7 +1846,8 @@
 			break;
 
 		default:
-			unreachable();
+			/* unreachable */
+			break;
 		}
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/pinctrl-mcp23s08.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/pinctrl-mcp23s08.c
@@ -120,9 +120,10 @@
 	.num_reg_defaults = ARRAY_SIZE(mcp23x08_defaults),
 	.cache_type = REGCACHE_FLAT,
 	.max_register = MCP_OLAT,
+	.disable_locking = true, /* mcp->lock protects the regmap */
 };
 
-static const struct reg_default mcp23x16_defaults[] = {
+static const struct reg_default mcp23x17_defaults[] = {
 	{.reg = MCP_IODIR << 1,		.def = 0xffff},
 	{.reg = MCP_IPOL << 1,		.def = 0x0000},
 	{.reg = MCP_GPINTEN << 1,	.def = 0x0000},
@@ -133,23 +134,23 @@
 	{.reg = MCP_OLAT << 1,		.def = 0x0000},
 };
 
-static const struct regmap_range mcp23x16_volatile_range = {
+static const struct regmap_range mcp23x17_volatile_range = {
 	.range_min = MCP_INTF << 1,
 	.range_max = MCP_GPIO << 1,
 };
 
-static const struct regmap_access_table mcp23x16_volatile_table = {
-	.yes_ranges = &mcp23x16_volatile_range,
+static const struct regmap_access_table mcp23x17_volatile_table = {
+	.yes_ranges = &mcp23x17_volatile_range,
 	.n_yes_ranges = 1,
 };
 
-static const struct regmap_range mcp23x16_precious_range = {
-	.range_min = MCP_GPIO << 1,
+static const struct regmap_range mcp23x17_precious_range = {
+	.range_min = MCP_INTCAP << 1,
 	.range_max = MCP_GPIO << 1,
 };
 
-static const struct regmap_access_table mcp23x16_precious_table = {
-	.yes_ranges = &mcp23x16_precious_range,
+static const struct regmap_access_table mcp23x17_precious_table = {
+	.yes_ranges = &mcp23x17_precious_range,
 	.n_yes_ranges = 1,
 };
 
@@ -159,12 +160,13 @@
 
 	.reg_stride = 2,
 	.max_register = MCP_OLAT << 1,
-	.volatile_table = &mcp23x16_volatile_table,
-	.precious_table = &mcp23x16_precious_table,
-	.reg_defaults = mcp23x16_defaults,
-	.num_reg_defaults = ARRAY_SIZE(mcp23x16_defaults),
+	.volatile_table = &mcp23x17_volatile_table,
+	.precious_table = &mcp23x17_precious_table,
+	.reg_defaults = mcp23x17_defaults,
+	.num_reg_defaults = ARRAY_SIZE(mcp23x17_defaults),
 	.cache_type = REGCACHE_FLAT,
 	.val_format_endian = REGMAP_ENDIAN_LITTLE,
+	.disable_locking = true, /* mcp->lock protects the regmap */
 };
 
 static int mcp_read(struct mcp23s08 *mcp, unsigned int reg, unsigned int *val)
@@ -261,7 +263,9 @@
 
 	switch (param) {
 	case PIN_CONFIG_BIAS_PULL_UP:
+		mutex_lock(&mcp->lock);
 		ret = mcp_read(mcp, MCP_GPPU, &data);
+		mutex_unlock(&mcp->lock);
 		if (ret < 0)
 			return ret;
 		status = (data & BIT(pin)) ? 1 : 0;
@@ -290,7 +294,9 @@
 
 		switch (param) {
 		case PIN_CONFIG_BIAS_PULL_UP:
+			mutex_lock(&mcp->lock);
 			ret = mcp_set_bit(mcp, MCP_GPPU, pin, arg);
+			mutex_unlock(&mcp->lock);
 			break;
 		default:
 			dev_dbg(mcp->dev, "Invalid config param %04x\n", param);
@@ -459,6 +465,11 @@
 	if (mcp_read(mcp, MCP_INTF, &intf))
 		goto unlock;
 
+	if (intf == 0) {
+		/* There is no interrupt pending */
+		goto unlock;
+	}
+
 	if (mcp_read(mcp, MCP_INTCAP, &intcap))
 		goto unlock;
 
@@ -476,11 +487,6 @@
 	mcp->cached_gpio = gpio;
 	mutex_unlock(&mcp->lock);
 
-	if (intf == 0) {
-		/* There is no interrupt pending */
-		return IRQ_HANDLED;
-	}
-
 	dev_dbg(mcp->chip.parent,
 		"intcap 0x%04X intf 0x%04X gpio_orig 0x%04X gpio 0x%04X\n",
 		intcap, intf, gpio_orig, gpio);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/pinctrl-ocelot.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/pinctrl-ocelot.c
@@ -420,7 +420,7 @@
 	regmap_update_bits(info->map, REG_ALT(0, info, pin->pin),
 			   BIT(p), f << p);
 	regmap_update_bits(info->map, REG_ALT(1, info, pin->pin),
-			   BIT(p), f << (p - 1));
+			   BIT(p), (f >> 1) << p);
 
 	return 0;
 }
@@ -711,25 +711,26 @@
 	struct irq_chip *parent_chip = irq_desc_get_chip(desc);
 	struct gpio_chip *chip = irq_desc_get_handler_data(desc);
 	struct ocelot_pinctrl *info = gpiochip_get_data(chip);
+	unsigned int id_reg = OCELOT_GPIO_INTR_IDENT * info->stride;
 	unsigned int reg = 0, irq, i;
 	unsigned long irqs;
 
+	chained_irq_enter(parent_chip, desc);
+
 	for (i = 0; i < info->stride; i++) {
-		regmap_read(info->map, OCELOT_GPIO_INTR_IDENT + 4 * i, &reg);
+		regmap_read(info->map, id_reg + 4 * i, &reg);
 		if (!reg)
 			continue;
 
-		chained_irq_enter(parent_chip, desc);
-
 		irqs = reg;
 
 		for_each_set_bit(irq, &irqs,
 				 min(32U, info->desc->npins - 32 * i))
 			generic_handle_irq(irq_linear_revmap(chip->irq.domain,
 							     irq + 32 * i));
-
-		chained_irq_exit(parent_chip, desc);
 	}
+
+	chained_irq_exit(parent_chip, desc);
 }
 
 static int ocelot_gpiochip_register(struct platform_device *pdev,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/pinctrl-pistachio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/pinctrl-pistachio.c
@@ -1370,10 +1370,10 @@
 		}
 
 		irq = irq_of_parse_and_map(child, 0);
-		if (irq < 0) {
-			dev_err(pctl->dev, "No IRQ for bank %u: %d\n", i, irq);
+		if (!irq) {
+			dev_err(pctl->dev, "No IRQ for bank %u\n", i);
 			of_node_put(child);
-			ret = irq;
+			ret = -EINVAL;
 			goto err;
 		}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/pinctrl-rockchip.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/pinctrl-rockchip.c
@@ -62,7 +62,7 @@
 	RK3399,
 };
 
-/**
+/*
  * Encode variants of iomux registers into a type variable
  */
 #define IOMUX_GPIO_ONLY		BIT(0)
@@ -72,6 +72,7 @@
 #define IOMUX_WIDTH_3BIT	BIT(4)
 
 /**
+ * struct rockchip_iomux
  * @type: iomux variant using IOMUX_* constants
  * @offset: if initialized to -1 it will be autocalculated, by specifying
  *	    an initial offset value the relevant source offset can be reset
@@ -82,7 +83,7 @@
 	int				offset;
 };
 
-/**
+/*
  * enum type index corresponding to rockchip_perpin_drv_list arrays index.
  */
 enum rockchip_pin_drv_type {
@@ -94,7 +95,7 @@
 	DRV_TYPE_MAX
 };
 
-/**
+/*
  * enum type index corresponding to rockchip_pull_list arrays index.
  */
 enum rockchip_pin_pull_type {
@@ -104,6 +105,7 @@
 };
 
 /**
+ * struct rockchip_drv
  * @drv_type: drive strength variant using rockchip_perpin_drv_type
  * @offset: if initialized to -1 it will be autocalculated, by specifying
  *	    an initial offset value the relevant source offset can be reset
@@ -117,8 +119,9 @@
 };
 
 /**
+ * struct rockchip_pin_bank
  * @reg_base: register base of the gpio bank
- * @reg_pull: optional separate register for additional pull settings
+ * @regmap_pull: optional separate register for additional pull settings
  * @clk: clock of the gpio bank
  * @irq: interrupt of the gpio bank
  * @saved_masks: Saved content of GPIO_INTEN at suspend time.
@@ -136,6 +139,8 @@
  * @gpio_chip: gpiolib chip
  * @grange: gpio range
  * @slock: spinlock for the gpio bank
+ * @toggle_edge_mode: bit mask to toggle (falling/rising) edge mode
+ * @recalced_mask: bit mask to indicate a need to recalulate the mask
  * @route_mask: bits describing the routing pins of per bank
  */
 struct rockchip_pin_bank {
@@ -310,6 +315,7 @@
  * @bank_num: bank number.
  * @pin: index at register or used to calc index.
  * @func: the min pin.
+ * @route_location: the mux route location (same, pmu, grf).
  * @route_offset: the max pin.
  * @route_val: the register offset.
  */
@@ -322,8 +328,6 @@
 	u32 route_val;
 };
 
-/**
- */
 struct rockchip_pin_ctrl {
 	struct rockchip_pin_bank	*pin_banks;
 	u32				nr_banks;
@@ -361,9 +365,7 @@
  * @name: name of the pin group, used to lookup the group.
  * @pins: the pins included in this group.
  * @npins: number of pins included in this group.
- * @func: the mux function number to be programmed when selected.
- * @configs: the config values to be set for each pin
- * @nconfigs: number of configs for each pin
+ * @data: local pin configuration
  */
 struct rockchip_pin_group {
 	const char			*name;
@@ -376,7 +378,7 @@
  * struct rockchip_pmx_func: represent a pin function.
  * @name: name of the pin function, used to lookup the function.
  * @groups: one or more names of pin groups that provide this function.
- * @num_groups: number of groups included in @groups.
+ * @ngroups: number of groups included in @groups.
  */
 struct rockchip_pmx_func {
 	const char		*name;
@@ -506,8 +508,8 @@
 	}
 
 	map_num += grp->npins;
-	new_map = devm_kcalloc(pctldev->dev, map_num, sizeof(*new_map),
-								GFP_KERNEL);
+
+	new_map = kcalloc(map_num, sizeof(*new_map), GFP_KERNEL);
 	if (!new_map)
 		return -ENOMEM;
 
@@ -517,7 +519,7 @@
 	/* create mux map */
 	parent = of_get_parent(np);
 	if (!parent) {
-		devm_kfree(pctldev->dev, new_map);
+		kfree(new_map);
 		return -EINVAL;
 	}
 	new_map[0].type = PIN_MAP_TYPE_MUX_GROUP;
@@ -544,6 +546,7 @@
 static void rockchip_dt_free_map(struct pinctrl_dev *pctldev,
 				    struct pinctrl_map *map, unsigned num_maps)
 {
+	kfree(map);
 }
 
 static const struct pinctrl_ops rockchip_pctrl_ops = {
@@ -658,23 +661,68 @@
 
 static struct rockchip_mux_recalced_data rk3328_mux_recalced_data[] = {
 	{
-		.num = 2,
-		.pin = 12,
-		.reg = 0x24,
-		.bit = 8,
-		.mask = 0x3
-	}, {
+		/* gpio2_b7_sel */
 		.num = 2,
 		.pin = 15,
 		.reg = 0x28,
 		.bit = 0,
 		.mask = 0x7
 	}, {
+		/* gpio2_c7_sel */
 		.num = 2,
 		.pin = 23,
 		.reg = 0x30,
 		.bit = 14,
 		.mask = 0x3
+	}, {
+		/* gpio3_b1_sel */
+		.num = 3,
+		.pin = 9,
+		.reg = 0x44,
+		.bit = 2,
+		.mask = 0x3
+	}, {
+		/* gpio3_b2_sel */
+		.num = 3,
+		.pin = 10,
+		.reg = 0x44,
+		.bit = 4,
+		.mask = 0x3
+	}, {
+		/* gpio3_b3_sel */
+		.num = 3,
+		.pin = 11,
+		.reg = 0x44,
+		.bit = 6,
+		.mask = 0x3
+	}, {
+		/* gpio3_b4_sel */
+		.num = 3,
+		.pin = 12,
+		.reg = 0x44,
+		.bit = 8,
+		.mask = 0x3
+	}, {
+		/* gpio3_b5_sel */
+		.num = 3,
+		.pin = 13,
+		.reg = 0x44,
+		.bit = 10,
+		.mask = 0x3
+	}, {
+		/* gpio3_b6_sel */
+		.num = 3,
+		.pin = 14,
+		.reg = 0x44,
+		.bit = 12,
+		.mask = 0x3
+	}, {
+		/* gpio3_b7_sel */
+		.num = 3,
+		.pin = 15,
+		.reg = 0x44,
+		.bit = 14,
+		.mask = 0x3
 	},
 };
 
@@ -2187,8 +2235,10 @@
 
 	if (ret) {
 		/* revert the already done pin settings */
-		for (cnt--; cnt >= 0; cnt--)
+		for (cnt--; cnt >= 0; cnt--) {
+			bank = pin_to_bank(info, pins[cnt]);
 			rockchip_set_mux(bank, pins[cnt] - bank->pin_base, 0);
+		}
 
 		return ret;
 	}
@@ -2533,6 +2583,7 @@
 		np_config = of_find_node_by_phandle(be32_to_cpup(phandle));
 		ret = pinconf_generic_parse_dt_config(np_config, NULL,
 				&grp->data[j].configs, &grp->data[j].nconfigs);
+		of_node_put(np_config);
 		if (ret)
 			return ret;
 	}
@@ -2810,7 +2861,9 @@
 	if (!bank->domain)
 		return -ENXIO;
 
+	clk_enable(bank->clk);
 	virq = irq_create_mapping(bank->domain, offset);
+	clk_disable(bank->clk);
 
 	return (virq) ? : -ENXIO;
 }
@@ -3383,12 +3436,15 @@
 static int __maybe_unused rockchip_pinctrl_resume(struct device *dev)
 {
 	struct rockchip_pinctrl *info = dev_get_drvdata(dev);
-	int ret = regmap_write(info->regmap_base, RK3288_GRF_GPIO6C_IOMUX,
-			       rk3288_grf_gpio6c_iomux |
-			       GPIO6C6_SEL_WRITE_ENABLE);
+	int ret;
 
-	if (ret)
-		return ret;
+	if (info->ctrl->type == RK3288) {
+		ret = regmap_write(info->regmap_base, RK3288_GRF_GPIO6C_IOMUX,
+				   rk3288_grf_gpio6c_iomux |
+				   GPIO6C6_SEL_WRITE_ENABLE);
+		if (ret)
+			return ret;
+	}
 
 	return pinctrl_force_default(info->pctl_dev);
 }
@@ -3427,6 +3483,7 @@
 	node = of_parse_phandle(np, "rockchip,grf", 0);
 	if (node) {
 		info->regmap_base = syscon_node_to_regmap(node);
+		of_node_put(node);
 		if (IS_ERR(info->regmap_base))
 			return PTR_ERR(info->regmap_base);
 	} else {
@@ -3463,6 +3520,7 @@
 	node = of_parse_phandle(np, "rockchip,pmu", 0);
 	if (node) {
 		info->regmap_pmu = syscon_node_to_regmap(node);
+		of_node_put(node);
 		if (IS_ERR(info->regmap_pmu))
 			return PTR_ERR(info->regmap_pmu);
 	}
@@ -3713,7 +3771,7 @@
 	PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", 0, 0, 0, 0),
 	PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", 0, 0, 0, 0),
 	PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", 0,
-			     IOMUX_WIDTH_3BIT,
+			     0,
 			     IOMUX_WIDTH_3BIT,
 			     0),
 	PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/pinctrl-rza1.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/pinctrl-rza1.c
@@ -418,7 +418,7 @@
 };
 
 static const struct rza1_swio_entry rza1l_swio_entries[] = {
-	[0] = { ARRAY_SIZE(rza1h_swio_pins), rza1h_swio_pins },
+	[0] = { ARRAY_SIZE(rza1l_swio_pins), rza1l_swio_pins },
 };
 
 /* RZ/A1L (r7s72102x) pinmux flags table */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/pinctrl-rza2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/pinctrl-rza2.c
@@ -14,6 +14,7 @@
 #include <linux/gpio/driver.h>
 #include <linux/io.h>
 #include <linux/module.h>
+#include <linux/mutex.h>
 #include <linux/of_device.h>
 #include <linux/pinctrl/pinmux.h>
 
@@ -46,6 +47,7 @@
 	struct pinctrl_dev *pctl;
 	struct pinctrl_gpio_range gpio_range;
 	int npins;
+	struct mutex mutex; /* serialize adding groups and functions */
 };
 
 #define RZA2_PDR(port)		(0x0000 + (port) * 2)	/* Direction 16-bit */
@@ -213,8 +215,8 @@
 	"PC_0", "PC_1", "PC_2", "PC_3", "PC_4", "PC_5", "PC_6", "PC_7",
 	"PD_0", "PD_1", "PD_2", "PD_3", "PD_4", "PD_5", "PD_6", "PD_7",
 	"PE_0", "PE_1", "PE_2", "PE_3", "PE_4", "PE_5", "PE_6", "PE_7",
-	"PF_0", "PF_1", "PF_2", "PF_3", "P0_4", "PF_5", "PF_6", "PF_7",
-	"PG_0", "PG_1", "PG_2", "P0_3", "PG_4", "PG_5", "PG_6", "PG_7",
+	"PF_0", "PF_1", "PF_2", "PF_3", "PF_4", "PF_5", "PF_6", "PF_7",
+	"PG_0", "PG_1", "PG_2", "PG_3", "PG_4", "PG_5", "PG_6", "PG_7",
 	"PH_0", "PH_1", "PH_2", "PH_3", "PH_4", "PH_5", "PH_6", "PH_7",
 	/* port I does not exist */
 	"PJ_0", "PJ_1", "PJ_2", "PJ_3", "PJ_4", "PJ_5", "PJ_6", "PJ_7",
@@ -251,6 +253,8 @@
 		return ret;
 	}
 
+	of_node_put(of_args.np);
+
 	if ((of_args.args[0] != 0) ||
 	    (of_args.args[1] != 0) ||
 	    (of_args.args[2] != priv->npins)) {
@@ -359,10 +363,14 @@
 		psel_val[i] = MUX_FUNC(value);
 	}
 
+	mutex_lock(&priv->mutex);
+
 	/* Register a single pin group listing all the pins we read from DT */
 	gsel = pinctrl_generic_add_group(pctldev, np->name, pins, npins, NULL);
-	if (gsel < 0)
-		return gsel;
+	if (gsel < 0) {
+		ret = gsel;
+		goto unlock;
+	}
 
 	/*
 	 * Register a single group function where the 'data' is an array PSEL
@@ -391,6 +399,8 @@
 	(*map)->data.mux.function = np->name;
 	*num_maps = 1;
 
+	mutex_unlock(&priv->mutex);
+
 	return 0;
 
 remove_function:
@@ -399,6 +409,9 @@
 remove_group:
 	pinctrl_generic_remove_group(pctldev, gsel);
 
+unlock:
+	mutex_unlock(&priv->mutex);
+
 	dev_err(priv->dev, "Unable to parse DT node %s\n", np->name);
 
 	return ret;
@@ -476,6 +489,8 @@
 	if (IS_ERR(priv->base))
 		return PTR_ERR(priv->base);
 
+	mutex_init(&priv->mutex);
+
 	platform_set_drvdata(pdev, priv);
 
 	priv->npins = (int)(uintptr_t)of_device_get_match_data(&pdev->dev) *
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/pinctrl-single.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/pinctrl-single.c
@@ -323,6 +323,8 @@
 		return -ENOTSUPP;
 	fselector = setting->func;
 	function = pinmux_generic_get_function(pctldev, fselector);
+	if (!function)
+		return -EINVAL;
 	*func = function->data;
 	if (!(*func)) {
 		dev_err(pcs->dev, "%s could not find function%i\n",
@@ -345,6 +347,8 @@
 	if (!pcs->fmask)
 		return 0;
 	function = pinmux_generic_get_function(pctldev, fselector);
+	if (!function)
+		return -EINVAL;
 	func = function->data;
 	if (!func)
 		return -EINVAL;
@@ -703,7 +707,7 @@
 
 	mux_bytes = pcs->width / BITS_PER_BYTE;
 
-	if (pcs->bits_per_mux) {
+	if (pcs->bits_per_mux && pcs->fmask) {
 		pcs->bits_per_pin = fls(pcs->fmask);
 		nr_pins = (pcs->size * BITS_PER_BYTE) / pcs->bits_per_pin;
 		num_pins_in_register = pcs->width / pcs->bits_per_pin;
@@ -916,7 +920,7 @@
 
 	/* If pinconf isn't supported, don't parse properties in below. */
 	if (!PCS_HAS_PINCONF)
-		return 0;
+		return -ENOTSUPP;
 
 	/* cacluate how much properties are supported in current node */
 	for (i = 0; i < ARRAY_SIZE(prop2); i++) {
@@ -928,7 +932,7 @@
 			nconfs++;
 	}
 	if (!nconfs)
-		return 0;
+		return -ENOTSUPP;
 
 	func->conf = devm_kcalloc(pcs->dev,
 				  nconfs, sizeof(struct pcs_conf_vals),
@@ -1056,9 +1060,12 @@
 
 	if (PCS_HAS_PINCONF && function) {
 		res = pcs_parse_pinconf(pcs, np, function, map);
-		if (res)
+		if (res == 0)
+			*num_maps = 2;
+		else if (res == -ENOTSUPP)
+			*num_maps = 1;
+		else
 			goto free_pingroups;
-		*num_maps = 2;
 	} else {
 		*num_maps = 1;
 	}
@@ -1198,6 +1205,7 @@
 
 	if (PCS_HAS_PINCONF) {
 		dev_err(pcs->dev, "pinconf not supported\n");
+		res = -ENOTSUPP;
 		goto free_pingroups;
 	}
 
@@ -1305,7 +1313,6 @@
 static void pcs_free_resources(struct pcs_device *pcs)
 {
 	pcs_irq_free(pcs);
-	pinctrl_unregister(pcs->pctl);
 
 #if IS_BUILTIN(CONFIG_PINCTRL_SINGLE)
 	if (pcs->missing_nr_pinctrl_cells)
@@ -1858,7 +1865,7 @@
 	if (ret < 0)
 		goto free;
 
-	ret = pinctrl_register_and_init(&pcs->desc, pcs->dev, pcs, &pcs->pctl);
+	ret = devm_pinctrl_register_and_init(pcs->dev, &pcs->desc, pcs, &pcs->pctl);
 	if (ret) {
 		dev_err(pcs->dev, "could not register single pinctrl driver\n");
 		goto free;
@@ -1891,8 +1898,11 @@
 
 	dev_info(pcs->dev, "%i pins, size %u\n", pcs->desc.npins, pcs->size);
 
-	return pinctrl_enable(pcs->pctl);
+	ret = pinctrl_enable(pcs->pctl);
+	if (ret)
+		goto free;
 
+	return 0;
 free:
 	pcs_free_resources(pcs);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/pinctrl-stmfx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/pinctrl-stmfx.c
@@ -540,7 +540,7 @@
 	u8 pending[NR_GPIO_REGS];
 	u8 src[NR_GPIO_REGS] = {0, 0, 0};
 	unsigned long n, status;
-	int ret;
+	int i, ret;
 
 	ret = regmap_bulk_read(pctl->stmfx->map, STMFX_REG_IRQ_GPI_PENDING,
 			       &pending, NR_GPIO_REGS);
@@ -550,7 +550,9 @@
 	regmap_bulk_write(pctl->stmfx->map, STMFX_REG_IRQ_GPI_SRC,
 			  src, NR_GPIO_REGS);
 
-	status = *(unsigned long *)pending;
+	BUILD_BUG_ON(NR_GPIO_REGS > sizeof(status));
+	for (i = 0, status = 0; i < NR_GPIO_REGS; i++)
+		status |= (unsigned long)pending[i] << (i * 8);
 	for_each_set_bit(n, &status, gc->ngpio) {
 		handle_nested_irq(irq_find_mapping(gc->irq.domain, n));
 		stmfx_pinctrl_irq_toggle_trigger(pctl, n);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/pinctrl-zynq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/pinctrl-zynq.c
@@ -8,6 +8,7 @@
  */
 #include <linux/io.h>
 #include <linux/mfd/syscon.h>
+#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
@@ -1208,8 +1209,4 @@
 	.probe = zynq_pinctrl_probe,
 };
 
-static int __init zynq_pinctrl_init(void)
-{
-	return platform_driver_register(&zynq_pinctrl_driver);
-}
-arch_initcall(zynq_pinctrl_init);
+module_platform_driver(zynq_pinctrl_driver);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/pinctrl-zynqmp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/pinctrl-zynqmp.c
@@ -0,0 +1,1071 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * ZynqMP pin controller
+ *
+ *  Copyright (C) 2017-2018 Xilinx, Inc.
+ *
+ *  Jolly Shah <jollys@xilinx.com>
+ *  Rajan Vaja <rajanv@xilinx.com>
+ *  Chirag Parekh <chirag.parekh@xilinx.com>
+ */
+
+#include <linux/module.h>
+#include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
+#include <linux/firmware/xlnx-zynqmp.h>
+#include <linux/init.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include "core.h"
+#include "pinctrl-utils.h"
+
+#define ZYNQMP_PIN_PREFIX			"MIO"
+#define PINCTRL_GET_FUNC_NAME_RESP_LEN		16
+#define MAX_FUNC_NAME_LEN			16
+#define MAX_GROUP_PIN				50
+#define END_OF_FUNCTIONS			"END_OF_FUNCTIONS"
+#define NUM_GROUPS_PER_RESP			6
+
+#define PINCTRL_GET_FUNC_GROUPS_RESP_LEN	12
+#define PINCTRL_GET_PIN_GROUPS_RESP_LEN		12
+#define NA_GROUP				-1
+#define RESERVED_GROUP				-2
+
+/**
+ * struct zynqmp_pmux_function - a pinmux function
+ * @name:	Name of the pinmux function
+ * @groups:	List of pingroups for this function
+ * @ngroups:	Number of entries in @groups
+ * @node:`	Firmware node matching with for function
+ *
+ * This structure holds information about pin control function
+ * and function group names supporting that function.
+ */
+struct zynqmp_pmux_function {
+	char name[MAX_FUNC_NAME_LEN];
+	const char * const *groups;
+	unsigned int ngroups;
+};
+
+/**
+ * struct zynqmp_pinctrl - driver data
+ * @pctrl:	Pinctrl device
+ * @groups:	Pingroups
+ * @ngroups:	Number of @groups
+ * @funcs:	Pinmux functions
+ * @nfuncs:	Number of @funcs
+ *
+ * This struct is stored as driver data and used to retrieve
+ * information regarding pin control functions, groups and
+ * group pins.
+ */
+struct zynqmp_pinctrl {
+	struct pinctrl_dev *pctrl;
+	const struct zynqmp_pctrl_group *groups;
+	unsigned int ngroups;
+	const struct zynqmp_pmux_function *funcs;
+	unsigned int nfuncs;
+};
+
+/**
+ * struct zynqmp_pctrl_group - Pin control group info
+ * @name:	Group name
+ * @pins:	Group pin numbers
+ * @npins:	Number of pins in group
+ */
+struct zynqmp_pctrl_group {
+	const char *name;
+	unsigned int pins[MAX_GROUP_PIN];
+	unsigned int npins;
+};
+
+/**
+ * enum zynqmp_pin_config_param - possible pin configuration parameters
+ * @PIN_CONFIG_IOSTANDARD:	if the pin can select an IO standard,
+ *				the argument to this parameter (on a
+ *				custom format) tells the driver which
+ *				alternative IO standard to use
+ * @PIN_CONFIG_SCHMITTCMOS:	this parameter (on a custom format) allows
+ *				to select schmitt or cmos input for MIO pins
+ */
+enum zynqmp_pin_config_param {
+	PIN_CONFIG_IOSTANDARD = PIN_CONFIG_END + 1,
+	PIN_CONFIG_SCHMITTCMOS,
+};
+
+static const struct pinconf_generic_params zynqmp_dt_params[] = {
+	{"io-standard", PIN_CONFIG_IOSTANDARD, IO_STANDARD_LVCMOS18},
+	{"schmitt-cmos", PIN_CONFIG_SCHMITTCMOS, PIN_INPUT_TYPE_SCHMITT},
+};
+
+#ifdef CONFIG_DEBUG_FS
+static const struct
+pin_config_item zynqmp_conf_items[ARRAY_SIZE(zynqmp_dt_params)] = {
+	PCONFDUMP(PIN_CONFIG_IOSTANDARD, "IO-standard", NULL, true),
+	PCONFDUMP(PIN_CONFIG_SCHMITTCMOS, "schmitt-cmos", NULL, true),
+};
+#endif
+
+static const struct zynqmp_eemi_ops *eemi_ops;
+static struct pinctrl_desc zynqmp_desc;
+
+/**
+ * zynqmp_pctrl_get_groups_count() - get group count
+ * @pctldev:	Pincontrol device pointer.
+ *
+ * Get total groups count.
+ *
+ * Return: group count.
+ */
+static int zynqmp_pctrl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+	struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+
+	return pctrl->ngroups;
+}
+
+/**
+ * zynqmp_pctrl_get_group_name() - get group name
+ * @pctldev:	Pincontrol device pointer.
+ * @selector:	Group ID.
+ *
+ * Get gorup's name.
+ *
+ * Return: group name.
+ */
+static const char *zynqmp_pctrl_get_group_name(struct pinctrl_dev *pctldev,
+					       unsigned int selector)
+{
+	struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+
+	return pctrl->groups[selector].name;
+}
+
+/**
+ * zynqmp_pctrl_get_group_pins() - get group pins
+ * @pctldev:	Pincontrol device pointer.
+ * @selector:	Group ID.
+ * @pins:	Pin numbers.
+ * @npins:	Number of pins in group.
+ *
+ * Get gorup's pin count and pin number.
+ *
+ * Return: Success.
+ */
+static int zynqmp_pctrl_get_group_pins(struct pinctrl_dev *pctldev,
+				       unsigned int selector,
+				       const unsigned int **pins,
+				       unsigned int *npins)
+{
+	struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+
+	*pins = pctrl->groups[selector].pins;
+	*npins = pctrl->groups[selector].npins;
+
+	return 0;
+}
+
+static const struct pinctrl_ops zynqmp_pctrl_ops = {
+	.get_groups_count = zynqmp_pctrl_get_groups_count,
+	.get_group_name = zynqmp_pctrl_get_group_name,
+	.get_group_pins = zynqmp_pctrl_get_group_pins,
+	.dt_node_to_map = pinconf_generic_dt_node_to_map_all,
+	.dt_free_map = pinctrl_utils_free_map,
+};
+
+/**
+ * zynqmp_pinmux_request_pin() - Request a pin for muxing
+ * @pctldev:	Pincontrol device pointer.
+ * @pin:	Pin number.
+ *
+ * Request a pin from firmware for muxing.
+ *
+ * Return: 0 on success else error code.
+ */
+static int zynqmp_pinmux_request_pin(struct pinctrl_dev *pctldev,
+				     unsigned int pin)
+{
+	int ret;
+
+	if (!eemi_ops->pinctrl_request)
+		return -ENOTSUPP;
+
+	ret = eemi_ops->pinctrl_request(pin);
+	if (ret) {
+		dev_err(pctldev->dev, "request failed for pin %u\n", pin);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+/**
+ * zynqmp_pmux_get_functions_count() - get number of functions
+ * @pctldev:	Pincontrol device pointer.
+ *
+ * Get total function count.
+ *
+ * Return: function count.
+ */
+static int zynqmp_pmux_get_functions_count(struct pinctrl_dev *pctldev)
+{
+	struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+
+	return pctrl->nfuncs;
+}
+
+/**
+ * zynqmp_pmux_get_function_name() - get function name
+ * @pctldev:	Pincontrol device pointer.
+ * @selector:	Function ID.
+ *
+ * Get function's name.
+ *
+ * Return: function name.
+ */
+static const char *zynqmp_pmux_get_function_name(struct pinctrl_dev *pctldev,
+						 unsigned int selector)
+{
+	struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+
+	return pctrl->funcs[selector].name;
+}
+
+/**
+ * zynqmp_pmux_get_function_groups() - Get groups for the function
+ * @pctldev:	Pincontrol device pointer.
+ * @selector:	Function ID
+ * @groups:	Group names.
+ * @num_groups:	Number of function groups.
+ *
+ * Get function's group count and group names.
+ *
+ * Return: Success.
+ */
+static int zynqmp_pmux_get_function_groups(struct pinctrl_dev *pctldev,
+					   unsigned int selector,
+					   const char * const **groups,
+					   unsigned * const num_groups)
+{
+	struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+
+	*groups = pctrl->funcs[selector].groups;
+	*num_groups = pctrl->funcs[selector].ngroups;
+
+	return 0;
+}
+
+/**
+ * zynqmp_pinmux_set_mux() - Set requested function for the group
+ * @pctldev:	Pincontrol device pointer.
+ * @function:	Function ID.
+ * @group:	Group ID.
+ *
+ * Loop though all pins of group and call firmware API
+ * to set requested function for all pins in group.
+ *
+ * Return: 0 on success else error code.
+ */
+static int zynqmp_pinmux_set_mux(struct pinctrl_dev *pctldev,
+				 unsigned int function,
+				 unsigned int group)
+{
+	struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+	const struct zynqmp_pctrl_group *pgrp = &pctrl->groups[group];
+	int ret, i;
+
+	if (!eemi_ops->pinctrl_set_function)
+		return -ENOTSUPP;
+
+	for (i = 0; i < pgrp->npins; i++) {
+		unsigned int pin = pgrp->pins[i];
+
+		ret = eemi_ops->pinctrl_set_function(pin, function);
+		if (ret) {
+			dev_err(pctldev->dev, "set mux failed for pin %u\n",
+				pin);
+			return -EIO;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * zynqmp_pinmux_release_pin() - Release a pin
+ * @pctldev:	Pincontrol device pointer.
+ * @pin:	Pin number.
+ *
+ * Release a pin from firmware.
+ *
+ * Return: 0 on success else error code.
+ */
+static int zynqmp_pinmux_release_pin(struct pinctrl_dev *pctldev,
+				     unsigned int pin)
+{
+	int ret;
+
+	if (!eemi_ops->pinctrl_release)
+		return -ENOTSUPP;
+
+	ret = eemi_ops->pinctrl_release(pin);
+	if (ret) {
+		dev_err(pctldev->dev, "free pin failed for pin %u\n",
+			pin);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static const struct pinmux_ops zynqmp_pinmux_ops = {
+	.request = zynqmp_pinmux_request_pin,
+	.get_functions_count = zynqmp_pmux_get_functions_count,
+	.get_function_name = zynqmp_pmux_get_function_name,
+	.get_function_groups = zynqmp_pmux_get_function_groups,
+	.set_mux = zynqmp_pinmux_set_mux,
+	.free = zynqmp_pinmux_release_pin,
+};
+
+/**
+ * zynqmp_pinconf_cfg_get() - get config value for the pin
+ * @pctldev:	Pin control device pointer.
+ * @pin:	Pin number.
+ * @config:	Value of config param.
+ *
+ * Get value of the requested configuration parameter for the
+ * given pin.
+ *
+ * Return: 0 on success else error code.
+ */
+static int zynqmp_pinconf_cfg_get(struct pinctrl_dev *pctldev,
+				  unsigned int pin,
+				  unsigned long *config)
+{
+	int ret;
+	unsigned int arg = 0, param = pinconf_to_config_param(*config);
+
+	if (!eemi_ops->pinctrl_get_config)
+		return -ENOTSUPP;
+
+	if (pin >= zynqmp_desc.npins)
+		return -ENOTSUPP;
+
+	switch (param) {
+	case PIN_CONFIG_SLEW_RATE:
+		ret = eemi_ops->pinctrl_get_config(pin,
+				PM_PINCTRL_CONFIG_SLEW_RATE,
+				&arg);
+		break;
+	case PIN_CONFIG_BIAS_PULL_UP:
+		ret = eemi_ops->pinctrl_get_config(pin,
+				PM_PINCTRL_CONFIG_PULL_CTRL,
+				&arg);
+		if (arg != PM_PINCTRL_BIAS_PULL_UP)
+			return -EINVAL;
+		arg = 1;
+		break;
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+		ret = eemi_ops->pinctrl_get_config(pin,
+				PM_PINCTRL_CONFIG_PULL_CTRL,
+				&arg);
+		if (arg != PM_PINCTRL_BIAS_PULL_DOWN)
+			return -EINVAL;
+		arg = 1;
+		break;
+	case PIN_CONFIG_BIAS_DISABLE:
+		ret = eemi_ops->pinctrl_get_config(pin,
+				PM_PINCTRL_CONFIG_BIAS_STATUS,
+				&arg);
+		if (arg != PM_PINCTRL_BIAS_DISABLE)
+			return -EINVAL;
+		arg = 1;
+		break;
+	case PIN_CONFIG_IOSTANDARD:
+		ret = eemi_ops->pinctrl_get_config(pin,
+				PM_PINCTRL_CONFIG_VOLTAGE_STATUS,
+				&arg);
+		break;
+	case PIN_CONFIG_SCHMITTCMOS:
+		ret = eemi_ops->pinctrl_get_config(pin,
+				PM_PINCTRL_CONFIG_SCHMITT_CMOS,
+				&arg);
+		break;
+	case PIN_CONFIG_DRIVE_STRENGTH:
+		ret = eemi_ops->pinctrl_get_config(pin,
+				PM_PINCTRL_CONFIG_DRIVE_STRENGTH,
+				&arg);
+		switch (arg) {
+		case PM_PINCTRL_DRIVE_STRENGTH_2MA:
+			arg = DRIVE_STRENGTH_2MA;
+			break;
+		case PM_PINCTRL_DRIVE_STRENGTH_4MA:
+			arg = DRIVE_STRENGTH_4MA;
+			break;
+		case PM_PINCTRL_DRIVE_STRENGTH_8MA:
+			arg = DRIVE_STRENGTH_8MA;
+			break;
+		case PM_PINCTRL_DRIVE_STRENGTH_12MA:
+			arg = DRIVE_STRENGTH_12MA;
+			break;
+		default:
+			/* Invalid drive strength */
+			dev_warn(pctldev->dev,
+				 "Invalid drive strength for pin %d\n",
+				 pin);
+			return -EINVAL;
+		}
+		break;
+	default:
+		ret = -ENOTSUPP;
+		break;
+	}
+
+	*config = pinconf_to_config_packed(param, arg);
+	return ret;
+}
+
+/**
+ * zynqmp_pinconf_cfg_set() - Set requested config for the pin
+ * @pctldev:	Pincontrol device pointer.
+ * @pin:	Pin number.
+ * @configs:	Configuration to set.
+ * @num_groups:	Number of configurations.
+ *
+ * Loop though all configurations and call firmware API
+ * to set requested configurations for the pin.
+ *
+ * Return: 0 on success else error code.
+ */
+static int zynqmp_pinconf_cfg_set(struct pinctrl_dev *pctldev,
+				  unsigned int pin, unsigned long *configs,
+				  unsigned int num_configs)
+{
+	int i, ret;
+
+	if (!eemi_ops->pinctrl_set_config)
+		return -ENOTSUPP;
+
+	if (pin >= zynqmp_desc.npins)
+		return -ENOTSUPP;
+
+	for (i = 0; i < num_configs; i++) {
+		unsigned int param = pinconf_to_config_param(configs[i]);
+		unsigned int arg = pinconf_to_config_argument(configs[i]);
+		unsigned int value;
+
+		switch (param) {
+		case PIN_CONFIG_SLEW_RATE:
+			ret = eemi_ops->pinctrl_set_config(pin,
+					PM_PINCTRL_CONFIG_SLEW_RATE,
+					arg);
+			break;
+		case PIN_CONFIG_BIAS_PULL_UP:
+			ret = eemi_ops->pinctrl_set_config(pin,
+					PM_PINCTRL_CONFIG_PULL_CTRL,
+					PM_PINCTRL_BIAS_PULL_UP);
+			break;
+		case PIN_CONFIG_BIAS_PULL_DOWN:
+			ret = eemi_ops->pinctrl_set_config(pin,
+					PM_PINCTRL_CONFIG_PULL_CTRL,
+					PM_PINCTRL_BIAS_PULL_DOWN);
+			break;
+		case PIN_CONFIG_BIAS_DISABLE:
+			ret = eemi_ops->pinctrl_set_config(pin,
+					PM_PINCTRL_CONFIG_BIAS_STATUS,
+					PM_PINCTRL_BIAS_DISABLE);
+			break;
+		case PIN_CONFIG_SCHMITTCMOS:
+			ret = eemi_ops->pinctrl_set_config(pin,
+					PM_PINCTRL_CONFIG_SCHMITT_CMOS,
+					arg);
+			break;
+		case PIN_CONFIG_DRIVE_STRENGTH:
+			switch (arg) {
+			case DRIVE_STRENGTH_2MA:
+				value = PM_PINCTRL_DRIVE_STRENGTH_2MA;
+				break;
+			case DRIVE_STRENGTH_4MA:
+				value = PM_PINCTRL_DRIVE_STRENGTH_4MA;
+				break;
+			case DRIVE_STRENGTH_8MA:
+				value = PM_PINCTRL_DRIVE_STRENGTH_8MA;
+				break;
+			case DRIVE_STRENGTH_12MA:
+				value = PM_PINCTRL_DRIVE_STRENGTH_12MA;
+				break;
+			default:
+				/* Invalid drive strength */
+				dev_warn(pctldev->dev,
+					 "Invalid drive strength for pin %d\n",
+					 pin);
+				return -EINVAL;
+			}
+
+			ret = eemi_ops->pinctrl_set_config(pin,
+					PM_PINCTRL_CONFIG_DRIVE_STRENGTH,
+					value);
+			break;
+		case PIN_CONFIG_IOSTANDARD:
+			ret = eemi_ops->pinctrl_get_config(pin,
+					PM_PINCTRL_CONFIG_VOLTAGE_STATUS,
+					&value);
+
+			if (arg != value)
+				dev_warn(pctldev->dev,
+					 "Invalid IO Standard requested for pin %d\n",
+					 pin);
+			break;
+		case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
+		case PIN_CONFIG_LOW_POWER_MODE:
+			/*
+			 * This cases are mentioned in dts but configurable
+			 * registers are unknown. So falling through to ignore
+			 * boot time warnings as of now.
+			 */
+			ret = 0;
+			break;
+		default:
+			dev_warn(pctldev->dev,
+				 "unsupported configuration parameter '%u'\n",
+				 param);
+			ret = -ENOTSUPP;
+			break;
+		}
+		if (ret)
+			dev_warn(pctldev->dev,
+				 "%s failed: pin %u param %u value %u\n",
+				 __func__, pin, param, arg);
+	}
+
+	return 0;
+}
+
+/**
+ * zynqmp_pinconf_group_set() - Set requested config for the group
+ * @pctldev:	Pincontrol device pointer.
+ * @selector:	Group ID.
+ * @configs:	Configuration to set.
+ * @num_groups:	Number of configurations.
+ *
+ * Call function to set configs for each pin in group.
+ *
+ * Return: 0 on success else error code.
+ */
+static int zynqmp_pinconf_group_set(struct pinctrl_dev *pctldev,
+				    unsigned int selector,
+				    unsigned long *configs,
+				    unsigned int num_configs)
+{
+	int i, ret;
+	struct zynqmp_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
+	const struct zynqmp_pctrl_group *pgrp = &pctrl->groups[selector];
+
+	for (i = 0; i < pgrp->npins; i++) {
+		ret = zynqmp_pinconf_cfg_set(pctldev, pgrp->pins[i], configs,
+					     num_configs);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static const struct pinconf_ops zynqmp_pinconf_ops = {
+	.is_generic = true,
+	.pin_config_get = zynqmp_pinconf_cfg_get,
+	.pin_config_set = zynqmp_pinconf_cfg_set,
+	.pin_config_group_set = zynqmp_pinconf_group_set,
+};
+
+static struct pinctrl_desc zynqmp_desc = {
+	.name = "zynqmp_pinctrl",
+	.owner = THIS_MODULE,
+	.pctlops = &zynqmp_pctrl_ops,
+	.pmxops = &zynqmp_pinmux_ops,
+	.confops = &zynqmp_pinconf_ops,
+};
+
+/**
+ * zynqmp_pinctrl_get_function_groups() - get groups for the function
+ * @fid:	Function ID.
+ * @index:	Group index.
+ * @groups:	Groups data.
+ *
+ * Call firmware API to get groups for the given function.
+ *
+ * Return: 0 on success else error code.
+ */
+static int zynqmp_pinctrl_get_function_groups(u32 fid, u32 index, u16 *groups)
+{
+	struct zynqmp_pm_query_data qdata = {0};
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	int ret;
+
+	qdata.qid = PM_QID_PINCTRL_GET_FUNCTION_GROUPS;
+	qdata.arg1 = fid;
+	qdata.arg2 = index;
+
+	ret = eemi_ops->query_data(qdata, ret_payload);
+	if (ret)
+		return ret;
+
+	memcpy(groups, &ret_payload[1], PINCTRL_GET_FUNC_GROUPS_RESP_LEN);
+
+	return ret;
+}
+
+/**
+ * zynqmp_pinctrl_get_func_num_groups() - get number of groups in function
+ * @fid:	Function ID.
+ * @ngroups:	Number of groups in function.
+ *
+ * Call firmware API to get number of group in function.
+ *
+ * Return: 0 on success else error code.
+ */
+static int zynqmp_pinctrl_get_func_num_groups(u32 fid, unsigned int *ngroups)
+{
+	struct zynqmp_pm_query_data qdata = {0};
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	int ret;
+
+	qdata.qid = PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS;
+	qdata.arg1 = fid;
+
+	ret = eemi_ops->query_data(qdata, ret_payload);
+	if (ret)
+		return ret;
+
+	*ngroups = ret_payload[1];
+
+	return ret;
+}
+
+/**
+ * zynqmp_pinctrl_prepare_func_groups() - prepare function and groups data
+ * @dev:	Device pointer.
+ * @fid:	Function ID.
+ * @func:	Function data.
+ * @groups:	Groups data.
+ *
+ * Query firmware to get group IDs for each function. Firmware returns
+ * group IDs. Based on gorup index for the function, group names in
+ * function are stored. For example, first gorup in "eth0" function
+ * is named as "eth0_0", second as "eth0_1" and so on.
+ *
+ * Based on group ID received from firmware, function stores name of
+ * group for that group ID. For an example, if "eth0" first group ID
+ * is x, groups[x] name will be stored as "eth0_0".
+ *
+ * Once done for each function, each function would have its group names,
+ * and each groups would also have their names.
+ *
+ * Return: 0 on success else error code.
+ */
+static int zynqmp_pinctrl_prepare_func_groups(struct device *dev, u32 fid,
+					      struct zynqmp_pmux_function *func,
+					      struct zynqmp_pctrl_group *groups)
+{
+	u16 resp[NUM_GROUPS_PER_RESP] = {0};
+	const char **fgroups;
+	int ret = 0, index, i;
+
+	fgroups = devm_kzalloc(dev, sizeof(*fgroups) * func->ngroups,
+			       GFP_KERNEL);
+	if (!fgroups)
+		return -ENOMEM;
+
+	for (index = 0; index < func->ngroups; index += NUM_GROUPS_PER_RESP) {
+		ret = zynqmp_pinctrl_get_function_groups(fid, index, resp);
+		if (ret)
+			return ret;
+
+		for (i = 0; i < NUM_GROUPS_PER_RESP; i++) {
+			if (resp[i] == (u16)NA_GROUP)
+				goto done;
+			if (resp[i] == (u16)RESERVED_GROUP)
+				continue;
+			fgroups[index + i] = devm_kasprintf(dev, GFP_KERNEL,
+							    "%s_%d_grp",
+							    func->name,
+							    index + i);
+			groups[resp[i]].name = devm_kasprintf(dev, GFP_KERNEL,
+							      "%s_%d_grp",
+							      func->name,
+							      index + i);
+		}
+	}
+done:
+	func->groups = fgroups;
+
+	return ret;
+}
+
+/**
+ * zynqmp_pinctrl_get_function_name() - get function name
+ * @fid:	Function ID.
+ * @name:	Function name
+ *
+ * Call firmware API to get name of given function.
+ *
+ * Return: 0 on success else error code.
+ */
+static int zynqmp_pinctrl_get_function_name(u32 fid, char *name)
+{
+	struct zynqmp_pm_query_data qdata = {0};
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+
+	qdata.qid = PM_QID_PINCTRL_GET_FUNCTION_NAME;
+	qdata.arg1 = fid;
+
+	eemi_ops->query_data(qdata, ret_payload);
+	memcpy(name, ret_payload, PINCTRL_GET_FUNC_NAME_RESP_LEN);
+
+	return 0;
+}
+
+/**
+ * zynqmp_pinctrl_get_num_functions() - get number of supported functions
+ * @nfuncs:	Number of functions.
+ *
+ * Call firmware API to get number of functions supported by system/board.
+ *
+ * Return: 0 on success else error code.
+ */
+static int zynqmp_pinctrl_get_num_functions(unsigned int *nfuncs)
+{
+	struct zynqmp_pm_query_data qdata = {0};
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	int ret;
+
+	qdata.qid = PM_QID_PINCTRL_GET_NUM_FUNCTIONS;
+
+	ret = eemi_ops->query_data(qdata, ret_payload);
+	if (ret)
+		return ret;
+
+	*nfuncs = ret_payload[1];
+
+	return ret;
+}
+
+/**
+ * zynqmp_pinctrl_get_pin_groups() - get groups for the pin
+ * @pin:	Pin number.
+ * @index:	Group index.
+ * @groups:	Groups data.
+ *
+ * Call firmware API to get groups for the given pin.
+ *
+ * Return: 0 on success else error code.
+ */
+static int zynqmp_pinctrl_get_pin_groups(u32 pin, u32 index, u16 *groups)
+{
+	struct zynqmp_pm_query_data qdata = {0};
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	int ret;
+
+	qdata.qid = PM_QID_PINCTRL_GET_PIN_GROUPS;
+	qdata.arg1 = pin;
+	qdata.arg2 = index;
+
+	ret = eemi_ops->query_data(qdata, ret_payload);
+	if (ret)
+		return ret;
+
+	memcpy(groups, &ret_payload[1], PINCTRL_GET_PIN_GROUPS_RESP_LEN);
+
+	return ret;
+}
+
+/**
+ * zynqmp_pinctrl_group_add_pin() - add pin to given group
+ * @group:	Group data.
+ * @pin:	Pin number.
+ *
+ * Add pin number to respective group's pin array at end and
+ * increment pin count for the group.
+ *
+ * Return: 0 on success else error code.
+ */
+static void zynqmp_pinctrl_group_add_pin(struct zynqmp_pctrl_group *group,
+					 unsigned int pin)
+{
+	group->pins[group->npins++] = pin;
+}
+
+/**
+ * zynqmp_pinctrl_create_pin_groups() - assign pins to respective groups
+ * @dev:	Device pointer.
+ * @groups:	Groups data.
+ * @pin:	Pin number.
+ *
+ * Query firmware to get groups available for the given pin.
+ * Based on firmware response(group IDs for the pin), add
+ * pin number to respective group's pin array.
+ *
+ * Once all pins are queries, each groups would have its number
+ * of pins and pin numbers data.
+ *
+ * Return: 0 on success else error code.
+ */
+static int zynqmp_pinctrl_create_pin_groups(struct device *dev,
+					    struct zynqmp_pctrl_group *groups,
+					    unsigned int pin)
+{
+	int ret, i, index = 0;
+	u16 resp[NUM_GROUPS_PER_RESP] = {0};
+
+	do {
+		ret = zynqmp_pinctrl_get_pin_groups(pin, index, resp);
+		if (ret)
+			return ret;
+
+		for (i = 0; i < NUM_GROUPS_PER_RESP; i++) {
+			if (resp[i] == (u16)NA_GROUP)
+				goto done;
+			if (resp[i] == (u16)RESERVED_GROUP)
+				continue;
+			zynqmp_pinctrl_group_add_pin(&groups[resp[i]], pin);
+		}
+		index += NUM_GROUPS_PER_RESP;
+	} while (1);
+
+done:
+	return ret;
+}
+
+/**
+ * zynqmp_pinctrl_prepare_group_pins() - prepare each group's pin data
+ * @dev:	Device pointer.
+ * @groups:	Groups data.
+ * @ngroups:	Number of groups.
+ *
+ * Prepare pin number and number of pins data for each pins.
+ *
+ * Return: 0 on success else error code.
+ */
+static int zynqmp_pinctrl_prepare_group_pins(struct device *dev,
+					     struct zynqmp_pctrl_group *groups,
+					     unsigned int ngroups)
+{
+	unsigned int pin;
+	int ret = 0;
+
+	for (pin = 0; pin < zynqmp_desc.npins; pin++) {
+		ret = zynqmp_pinctrl_create_pin_groups(dev, groups, pin);
+		if (ret)
+			goto done;
+	}
+done:
+	return ret;
+}
+
+/**
+ * zynqmp_pinctrl_prepare_function_info() - prepare function info
+ * @dev:	Device pointer.
+ * @pctrl:	Pin control driver data.
+ *
+ * Query firmware for functions, groups and pin information and
+ * prepare pin control driver data.
+ *
+ * Query number of functions and number of function groups (number
+ * of groups in given function) to allocate required memory buffers
+ * for functions and groups. Once buffers are allocated to store
+ * functions and groups data, query and store required information
+ * (numbe of groups and group names for each function, number of
+ * pins and pin numbers for each group).
+ *
+ * Return: 0 on success else error code.
+ */
+static int zynqmp_pinctrl_prepare_function_info(struct device *dev,
+						struct zynqmp_pinctrl *pctrl)
+{
+	struct zynqmp_pmux_function *funcs;
+	struct zynqmp_pctrl_group *groups;
+	int ret, i;
+
+	ret = zynqmp_pinctrl_get_num_functions(&pctrl->nfuncs);
+	if (ret)
+		return ret;
+
+	funcs = devm_kzalloc(dev, sizeof(*funcs) * pctrl->nfuncs, GFP_KERNEL);
+	if (!funcs)
+		return -ENOMEM;
+
+	for (i = 0; i < pctrl->nfuncs; i++) {
+		zynqmp_pinctrl_get_function_name(i, funcs[i].name);
+
+		ret = zynqmp_pinctrl_get_func_num_groups(i, &funcs[i].ngroups);
+		if (ret)
+			goto err;
+		pctrl->ngroups += funcs[i].ngroups;
+	}
+
+	groups = devm_kzalloc(dev, sizeof(*groups) * pctrl->ngroups,
+			      GFP_KERNEL);
+	if (!groups)
+		return -ENOMEM;
+
+	for (i = 0; i < pctrl->nfuncs; i++) {
+		ret = zynqmp_pinctrl_prepare_func_groups(dev, i, &funcs[i],
+							 groups);
+		if (ret)
+			goto err;
+	}
+
+	ret = zynqmp_pinctrl_prepare_group_pins(dev, groups, pctrl->ngroups);
+	if (ret)
+		goto err;
+
+	pctrl->funcs = funcs;
+	pctrl->groups = groups;
+
+err:
+	return ret;
+}
+
+/**
+ * zynqmp_pinctrl_get_num_pins() - get number of pins in system
+ * @npins:	Number of pins in system/board.
+ *
+ * Call firmware API to get number of pins.
+ *
+ * Return: 0 on success else error code.
+ */
+static int zynqmp_pinctrl_get_num_pins(unsigned int *npins)
+{
+	struct zynqmp_pm_query_data qdata = {0};
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	int ret;
+
+	qdata.qid = PM_QID_PINCTRL_GET_NUM_PINS;
+
+	ret = eemi_ops->query_data(qdata, ret_payload);
+	if (ret)
+		return ret;
+
+	*npins = ret_payload[1];
+
+	return ret;
+}
+
+/**
+ * zynqmp_pinctrl_prepare_pin_desc() - prepare pin description info
+ * @dev:		Device pointer.
+ * @zynqmp_pins:	Pin information.
+ * @npins:		Number of pins.
+ *
+ * Query number of pins information from firmware and prepare pin
+ * description containing pin number and pin name.
+ *
+ * Return: 0 on success else error code.
+ */
+static int zynqmp_pinctrl_prepare_pin_desc(struct device *dev,
+		const struct pinctrl_pin_desc **zynqmp_pins,
+		unsigned int *npins)
+{
+	struct pinctrl_pin_desc *pins, *pin;
+	int ret;
+	int i;
+
+	ret = zynqmp_pinctrl_get_num_pins(npins);
+	if (ret)
+		return ret;
+
+	pins = devm_kzalloc(dev, sizeof(*pins) * *npins, GFP_KERNEL);
+	if (!pins)
+		return -ENOMEM;
+
+	for (i = 0; i < *npins; i++) {
+		pin = &pins[i];
+		pin->number = i;
+		pin->name = devm_kasprintf(dev, GFP_KERNEL, "%s%d",
+					   ZYNQMP_PIN_PREFIX, i);
+	}
+
+	*zynqmp_pins = pins;
+
+	return 0;
+}
+
+static int zynqmp_pinctrl_probe(struct platform_device *pdev)
+{
+	struct zynqmp_pinctrl *pctrl;
+	int ret;
+
+	if (of_device_is_compatible(pdev->dev.of_node, "xlnx,pinctrl-zynqmp")) {
+		dev_err(&pdev->dev, "ERROR: This binding is deprecated, please use new compatible binding\n");
+		return -ENOENT;
+	}
+
+	pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL);
+	if (!pctrl)
+		return -ENOMEM;
+
+	eemi_ops = zynqmp_pm_get_eemi_ops();
+	if (IS_ERR(eemi_ops))
+		return PTR_ERR(eemi_ops);
+
+	if (!eemi_ops->query_data) {
+		dev_err(&pdev->dev, "%s: Firmware interface not available\n",
+			__func__);
+		ret = -ENOTSUPP;
+		goto err;
+	}
+
+	ret = zynqmp_pinctrl_prepare_pin_desc(&pdev->dev,
+					      &zynqmp_desc.pins,
+					      &zynqmp_desc.npins);
+	if (ret) {
+		dev_err(&pdev->dev, "%s() pin desc prepare fail with %d\n",
+			__func__, ret);
+		goto err;
+	}
+
+	ret = zynqmp_pinctrl_prepare_function_info(&pdev->dev, pctrl);
+	if (ret) {
+		dev_err(&pdev->dev, "%s() function info prepare fail with %d\n",
+			__func__, ret);
+		goto err;
+	}
+
+	pctrl->pctrl = pinctrl_register(&zynqmp_desc, &pdev->dev, pctrl);
+	if (IS_ERR(pctrl->pctrl)) {
+		ret = PTR_ERR(pctrl->pctrl);
+		goto err;
+	}
+	platform_set_drvdata(pdev, pctrl);
+
+	dev_info(&pdev->dev, "zynqmp pinctrl initialized\n");
+err:
+	return ret;
+}
+
+static int zynqmp_pinctrl_remove(struct platform_device *pdev)
+{
+	struct zynqmp_pinctrl *pctrl = platform_get_drvdata(pdev);
+
+	pinctrl_unregister(pctrl->pctrl);
+
+	return 0;
+}
+
+static const struct of_device_id zynqmp_pinctrl_of_match[] = {
+	{ .compatible = "xlnx,zynqmp-pinctrl" },
+	{ .compatible = "xlnx,pinctrl-zynqmp" },
+	{ }
+};
+
+static struct platform_driver zynqmp_pinctrl_driver = {
+	.driver = {
+		.name = "zynqmp-pinctrl",
+		.of_match_table = zynqmp_pinctrl_of_match,
+	},
+	.probe = zynqmp_pinctrl_probe,
+	.remove = zynqmp_pinctrl_remove,
+};
+
+module_platform_driver(zynqmp_pinctrl_driver);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/pinmux.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/pinmux.c
@@ -85,7 +85,7 @@
 	const struct pinmux_ops *ops = pctldev->desc->pmxops;
 
 	/* Can't inspect pin, assume it can be used */
-	if (!desc)
+	if (!desc || !ops)
 		return true;
 
 	if (ops->strict && desc->mux_usecount)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/qcom/pinctrl-msm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -688,7 +688,7 @@
 
 		pol = msm_readl_intr_cfg(pctrl, g);
 		pol ^= BIT(g->intr_polarity_bit);
-		msm_writel_intr_cfg(val, pctrl, g);
+		msm_writel_intr_cfg(pol, pctrl, g);
 
 		val2 = msm_readl_io(pctrl, g) & BIT(g->in_bit);
 		intstat = msm_readl_intr_status(pctrl, g);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/qcom/pinctrl-msm8916.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/qcom/pinctrl-msm8916.c
@@ -844,8 +844,8 @@
 	PINGROUP(28, pwr_modem_enabled_a, NA, NA, NA, NA, NA, qdss_tracedata_b, NA, atest_combodac),
 	PINGROUP(29, cci_i2c, NA, NA, NA, NA, NA, qdss_tracedata_b, NA, atest_combodac),
 	PINGROUP(30, cci_i2c, NA, NA, NA, NA, NA, NA, NA, qdss_tracedata_b),
-	PINGROUP(31, cci_timer0, NA, NA, NA, NA, NA, NA, NA, NA),
-	PINGROUP(32, cci_timer1, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(31, cci_timer0, flash_strobe, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(32, cci_timer1, flash_strobe, NA, NA, NA, NA, NA, NA, NA),
 	PINGROUP(33, cci_async, NA, NA, NA, NA, NA, NA, NA, qdss_tracedata_b),
 	PINGROUP(34, pwr_nav_enabled_a, NA, NA, NA, NA, NA, NA, NA, qdss_tracedata_b),
 	PINGROUP(35, pwr_crypto_enabled_a, NA, NA, NA, NA, NA, NA, NA, qdss_tracedata_b),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/qcom/pinctrl-sc7180.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/qcom/pinctrl-sc7180.c
@@ -77,6 +77,7 @@
 		.intr_cfg_reg = 0,			\
 		.intr_status_reg = 0,			\
 		.intr_target_reg = 0,			\
+		.tile = SOUTH,				\
 		.mux_bit = -1,				\
 		.pull_bit = pull,			\
 		.drv_bit = drv,				\
@@ -102,6 +103,7 @@
 		.intr_cfg_reg = 0,			\
 		.intr_status_reg = 0,			\
 		.intr_target_reg = 0,			\
+		.tile = SOUTH,				\
 		.mux_bit = -1,				\
 		.pull_bit = 3,				\
 		.drv_bit = 0,				\
@@ -1087,14 +1089,14 @@
 	[116] = PINGROUP(116, WEST, qup04, qup04, _, _, _, _, _, _, _),
 	[117] = PINGROUP(117, WEST, dp_hot, _, _, _, _, _, _, _, _),
 	[118] = PINGROUP(118, WEST, _, _, _, _, _, _, _, _, _),
-	[119] = UFS_RESET(ufs_reset, 0x97f000),
-	[120] = SDC_QDSD_PINGROUP(sdc1_rclk, 0x97a000, 15, 0),
-	[121] = SDC_QDSD_PINGROUP(sdc1_clk, 0x97a000, 13, 6),
-	[122] = SDC_QDSD_PINGROUP(sdc1_cmd, 0x97a000, 11, 3),
-	[123] = SDC_QDSD_PINGROUP(sdc1_data, 0x97a000, 9, 0),
-	[124] = SDC_QDSD_PINGROUP(sdc2_clk, 0x97b000, 14, 6),
-	[125] = SDC_QDSD_PINGROUP(sdc2_cmd, 0x97b000, 11, 3),
-	[126] = SDC_QDSD_PINGROUP(sdc2_data, 0x97b000, 9, 0),
+	[119] = UFS_RESET(ufs_reset, 0x7f000),
+	[120] = SDC_QDSD_PINGROUP(sdc1_rclk, 0x7a000, 15, 0),
+	[121] = SDC_QDSD_PINGROUP(sdc1_clk, 0x7a000, 13, 6),
+	[122] = SDC_QDSD_PINGROUP(sdc1_cmd, 0x7a000, 11, 3),
+	[123] = SDC_QDSD_PINGROUP(sdc1_data, 0x7a000, 9, 0),
+	[124] = SDC_QDSD_PINGROUP(sdc2_clk, 0x7b000, 14, 6),
+	[125] = SDC_QDSD_PINGROUP(sdc2_cmd, 0x7b000, 11, 3),
+	[126] = SDC_QDSD_PINGROUP(sdc2_data, 0x7b000, 9, 0),
 };
 
 static const struct msm_pinctrl_soc_data sc7180_pinctrl = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
@@ -170,6 +170,7 @@
 	struct regmap	*map;
 	struct pinctrl_dev *ctrl;
 	struct gpio_chip chip;
+	struct irq_chip irq;
 };
 
 static const struct pinconf_generic_params pmic_gpio_bindings[] = {
@@ -917,16 +918,6 @@
 	return 0;
 }
 
-static struct irq_chip pmic_gpio_irq_chip = {
-	.name = "spmi-gpio",
-	.irq_ack = irq_chip_ack_parent,
-	.irq_mask = irq_chip_mask_parent,
-	.irq_unmask = irq_chip_unmask_parent,
-	.irq_set_type = irq_chip_set_type_parent,
-	.irq_set_wake = irq_chip_set_wake_parent,
-	.flags = IRQCHIP_MASK_ON_SUSPEND,
-};
-
 static int pmic_gpio_domain_translate(struct irq_domain *domain,
 				      struct irq_fwspec *fwspec,
 				      unsigned long *hwirq,
@@ -1053,8 +1044,16 @@
 	if (!parent_domain)
 		return -ENXIO;
 
+	state->irq.name = "spmi-gpio",
+	state->irq.irq_ack = irq_chip_ack_parent,
+	state->irq.irq_mask = irq_chip_mask_parent,
+	state->irq.irq_unmask = irq_chip_unmask_parent,
+	state->irq.irq_set_type = irq_chip_set_type_parent,
+	state->irq.irq_set_wake = irq_chip_set_wake_parent,
+	state->irq.flags = IRQCHIP_MASK_ON_SUSPEND,
+
 	girq = &state->chip.irq;
-	girq->chip = &pmic_gpio_irq_chip;
+	girq->chip = &state->irq;
 	girq->default_type = IRQ_TYPE_NONE;
 	girq->handler = handle_level_irq;
 	girq->fwnode = of_node_to_fwnode(state->dev->of_node);
@@ -1107,6 +1106,8 @@
 static const struct of_device_id pmic_gpio_of_match[] = {
 	{ .compatible = "qcom,pm8005-gpio", .data = (void *) 4 },
 	{ .compatible = "qcom,pm8916-gpio", .data = (void *) 4 },
+	/* pm8937 has 8 GPIOs with holes on 3, 4 and 6 */
+	{ .compatible = "qcom,pm8937-gpio", .data = (void *) 8 },
 	{ .compatible = "qcom,pm8941-gpio", .data = (void *) 36 },
 	{ .compatible = "qcom,pm8994-gpio", .data = (void *) 22 },
 	{ .compatible = "qcom,pmi8994-gpio", .data = (void *) 10 },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/samsung/pinctrl-exynos.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/samsung/pinctrl-exynos.c
@@ -40,6 +40,8 @@
 	u32 eint_pend;
 	u32 eint_wake_mask_value;
 	u32 eint_wake_mask_reg;
+	void (*set_eint_wakeup_mask)(struct samsung_pinctrl_drv_data *drvdata,
+				     struct exynos_irq_chip *irq_chip);
 };
 
 static inline struct exynos_irq_chip *to_exynos_irq_chip(struct irq_chip *chip)
@@ -53,7 +55,7 @@
 	struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
 	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
 	unsigned long reg_mask = our_chip->eint_mask + bank->eint_offset;
-	unsigned long mask;
+	unsigned int mask;
 	unsigned long flags;
 
 	spin_lock_irqsave(&bank->slock, flags);
@@ -81,7 +83,7 @@
 	struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
 	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
 	unsigned long reg_mask = our_chip->eint_mask + bank->eint_offset;
-	unsigned long mask;
+	unsigned int mask;
 	unsigned long flags;
 
 	/*
@@ -265,6 +267,7 @@
 	u32 eint_con;
 	u32 eint_fltcon0;
 	u32 eint_fltcon1;
+	u32 eint_mask;
 };
 
 /*
@@ -342,6 +345,47 @@
 	return 0;
 }
 
+static void
+exynos_pinctrl_set_eint_wakeup_mask(struct samsung_pinctrl_drv_data *drvdata,
+				    struct exynos_irq_chip *irq_chip)
+{
+	struct regmap *pmu_regs;
+
+	if (!drvdata->retention_ctrl || !drvdata->retention_ctrl->priv) {
+		dev_warn(drvdata->dev,
+			 "No retention data configured bank with external wakeup interrupt. Wake-up mask will not be set.\n");
+		return;
+	}
+
+	pmu_regs = drvdata->retention_ctrl->priv;
+	dev_info(drvdata->dev,
+		 "Setting external wakeup interrupt mask: 0x%x\n",
+		 irq_chip->eint_wake_mask_value);
+
+	regmap_write(pmu_regs, irq_chip->eint_wake_mask_reg,
+		     irq_chip->eint_wake_mask_value);
+}
+
+static void
+s5pv210_pinctrl_set_eint_wakeup_mask(struct samsung_pinctrl_drv_data *drvdata,
+				    struct exynos_irq_chip *irq_chip)
+
+{
+	void __iomem *clk_base;
+
+	if (!drvdata->retention_ctrl || !drvdata->retention_ctrl->priv) {
+		dev_warn(drvdata->dev,
+			 "No retention data configured bank with external wakeup interrupt. Wake-up mask will not be set.\n");
+		return;
+	}
+
+
+	clk_base = (void __iomem *) drvdata->retention_ctrl->priv;
+
+	__raw_writel(irq_chip->eint_wake_mask_value,
+		     clk_base + irq_chip->eint_wake_mask_reg);
+}
+
 /*
  * irq_chip for wakeup interrupts
  */
@@ -360,8 +404,9 @@
 	.eint_mask = EXYNOS_WKUP_EMASK_OFFSET,
 	.eint_pend = EXYNOS_WKUP_EPEND_OFFSET,
 	.eint_wake_mask_value = EXYNOS_EINT_WAKEUP_MASK_DISABLED,
-	/* Only difference with exynos4210_wkup_irq_chip: */
+	/* Only differences with exynos4210_wkup_irq_chip: */
 	.eint_wake_mask_reg = S5PV210_EINT_WAKEUP_MASK,
+	.set_eint_wakeup_mask = s5pv210_pinctrl_set_eint_wakeup_mask,
 };
 
 static const struct exynos_irq_chip exynos4210_wkup_irq_chip __initconst = {
@@ -380,6 +425,7 @@
 	.eint_pend = EXYNOS_WKUP_EPEND_OFFSET,
 	.eint_wake_mask_value = EXYNOS_EINT_WAKEUP_MASK_DISABLED,
 	.eint_wake_mask_reg = EXYNOS_EINT_WAKEUP_MASK,
+	.set_eint_wakeup_mask = exynos_pinctrl_set_eint_wakeup_mask,
 };
 
 static const struct exynos_irq_chip exynos7_wkup_irq_chip __initconst = {
@@ -398,6 +444,7 @@
 	.eint_pend = EXYNOS7_WKUP_EPEND_OFFSET,
 	.eint_wake_mask_value = EXYNOS_EINT_WAKEUP_MASK_DISABLED,
 	.eint_wake_mask_reg = EXYNOS5433_EINT_WAKEUP_MASK,
+	.set_eint_wakeup_mask = exynos_pinctrl_set_eint_wakeup_mask,
 };
 
 /* list of external wakeup controllers supported */
@@ -427,7 +474,7 @@
 	chained_irq_exit(chip, desc);
 }
 
-static inline void exynos_irq_demux_eint(unsigned long pend,
+static inline void exynos_irq_demux_eint(unsigned int pend,
 						struct irq_domain *domain)
 {
 	unsigned int irq;
@@ -444,8 +491,8 @@
 {
 	struct irq_chip *chip = irq_desc_get_chip(desc);
 	struct exynos_muxed_weint_data *eintd = irq_desc_get_handler_data(desc);
-	unsigned long pend;
-	unsigned long mask;
+	unsigned int pend;
+	unsigned int mask;
 	int i;
 
 	chained_irq_enter(chip, desc);
@@ -486,8 +533,10 @@
 		if (match) {
 			irq_chip = kmemdup(match->data,
 				sizeof(*irq_chip), GFP_KERNEL);
-			if (!irq_chip)
+			if (!irq_chip) {
+				of_node_put(np);
 				return -ENOMEM;
+			}
 			wkup_np = np;
 			break;
 		}
@@ -504,6 +553,7 @@
 				bank->nr_pins, &exynos_eint_irqd_ops, bank);
 		if (!bank->irq_domain) {
 			dev_err(dev, "wkup irq domain add failed\n");
+			of_node_put(wkup_np);
 			return -ENXIO;
 		}
 
@@ -518,8 +568,10 @@
 		weint_data = devm_kcalloc(dev,
 					  bank->nr_pins, sizeof(*weint_data),
 					  GFP_KERNEL);
-		if (!weint_data)
+		if (!weint_data) {
+			of_node_put(wkup_np);
 			return -ENOMEM;
+		}
 
 		for (idx = 0; idx < bank->nr_pins; ++idx) {
 			irq = irq_of_parse_and_map(bank->of_node, idx);
@@ -536,10 +588,13 @@
 		}
 	}
 
-	if (!muxed_banks)
+	if (!muxed_banks) {
+		of_node_put(wkup_np);
 		return 0;
+	}
 
 	irq = irq_of_parse_and_map(wkup_np, 0);
+	of_node_put(wkup_np);
 	if (!irq) {
 		dev_err(dev, "irq number for muxed EINTs not found\n");
 		return 0;
@@ -566,27 +621,6 @@
 	return 0;
 }
 
-static void
-exynos_pinctrl_set_eint_wakeup_mask(struct samsung_pinctrl_drv_data *drvdata,
-				    struct exynos_irq_chip *irq_chip)
-{
-	struct regmap *pmu_regs;
-
-	if (!drvdata->retention_ctrl || !drvdata->retention_ctrl->priv) {
-		dev_warn(drvdata->dev,
-			 "No retention data configured bank with external wakeup interrupt. Wake-up mask will not be set.\n");
-		return;
-	}
-
-	pmu_regs = drvdata->retention_ctrl->priv;
-	dev_info(drvdata->dev,
-		 "Setting external wakeup interrupt mask: 0x%x\n",
-		 irq_chip->eint_wake_mask_value);
-
-	regmap_write(pmu_regs, irq_chip->eint_wake_mask_reg,
-		     irq_chip->eint_wake_mask_value);
-}
-
 static void exynos_pinctrl_suspend_bank(
 				struct samsung_pinctrl_drv_data *drvdata,
 				struct samsung_pin_bank *bank)
@@ -600,10 +634,13 @@
 						+ 2 * bank->eint_offset);
 	save->eint_fltcon1 = readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
 						+ 2 * bank->eint_offset + 4);
+	save->eint_mask = readl(regs + bank->irq_chip->eint_mask
+						+ bank->eint_offset);
 
 	pr_debug("%s: save     con %#010x\n", bank->name, save->eint_con);
 	pr_debug("%s: save fltcon0 %#010x\n", bank->name, save->eint_fltcon0);
 	pr_debug("%s: save fltcon1 %#010x\n", bank->name, save->eint_fltcon1);
+	pr_debug("%s: save    mask %#010x\n", bank->name, save->eint_mask);
 }
 
 void exynos_pinctrl_suspend(struct samsung_pinctrl_drv_data *drvdata)
@@ -618,8 +655,8 @@
 		else if (bank->eint_type == EINT_TYPE_WKUP) {
 			if (!irq_chip) {
 				irq_chip = bank->irq_chip;
-				exynos_pinctrl_set_eint_wakeup_mask(drvdata,
-								    irq_chip);
+				irq_chip->set_eint_wakeup_mask(drvdata,
+							       irq_chip);
 			} else if (bank->irq_chip != irq_chip) {
 				dev_warn(drvdata->dev,
 					 "More than one external wakeup interrupt chip configured (bank: %s). This is not supported by hardware nor by driver.\n",
@@ -645,6 +682,9 @@
 	pr_debug("%s: fltcon1 %#010x => %#010x\n", bank->name,
 			readl(regs + EXYNOS_GPIO_EFLTCON_OFFSET
 			+ 2 * bank->eint_offset + 4), save->eint_fltcon1);
+	pr_debug("%s:    mask %#010x => %#010x\n", bank->name,
+			readl(regs + bank->irq_chip->eint_mask
+			+ bank->eint_offset), save->eint_mask);
 
 	writel(save->eint_con, regs + EXYNOS_GPIO_ECON_OFFSET
 						+ bank->eint_offset);
@@ -652,6 +692,8 @@
 						+ 2 * bank->eint_offset);
 	writel(save->eint_fltcon1, regs + EXYNOS_GPIO_EFLTCON_OFFSET
 						+ 2 * bank->eint_offset + 4);
+	writel(save->eint_mask, regs + bank->irq_chip->eint_mask
+						+ bank->eint_offset);
 }
 
 void exynos_pinctrl_resume(struct samsung_pinctrl_drv_data *drvdata)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/samsung/pinctrl-s3c24xx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/samsung/pinctrl-s3c24xx.c
@@ -490,8 +490,10 @@
 		return -ENODEV;
 
 	eint_data = devm_kzalloc(dev, sizeof(*eint_data), GFP_KERNEL);
-	if (!eint_data)
+	if (!eint_data) {
+		of_node_put(eint_np);
 		return -ENOMEM;
+	}
 
 	eint_data->drvdata = d;
 
@@ -503,12 +505,14 @@
 		irq = irq_of_parse_and_map(eint_np, i);
 		if (!irq) {
 			dev_err(dev, "failed to get wakeup EINT IRQ %d\n", i);
+			of_node_put(eint_np);
 			return -ENXIO;
 		}
 
 		eint_data->parents[i] = irq;
 		irq_set_chained_handler_and_data(irq, handlers[i], eint_data);
 	}
+	of_node_put(eint_np);
 
 	bank = d->pin_banks;
 	for (i = 0; i < d->nr_banks; ++i, ++bank) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/samsung/pinctrl-s3c64xx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/samsung/pinctrl-s3c64xx.c
@@ -704,8 +704,10 @@
 		return -ENODEV;
 
 	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
-	if (!data)
+	if (!data) {
+		of_node_put(eint0_np);
 		return -ENOMEM;
+	}
 	data->drvdata = d;
 
 	for (i = 0; i < NUM_EINT0_IRQ; ++i) {
@@ -714,6 +716,7 @@
 		irq = irq_of_parse_and_map(eint0_np, i);
 		if (!irq) {
 			dev_err(dev, "failed to get wakeup EINT IRQ %d\n", i);
+			of_node_put(eint0_np);
 			return -ENXIO;
 		}
 
@@ -721,6 +724,7 @@
 						 s3c64xx_eint0_handlers[i],
 						 data);
 	}
+	of_node_put(eint0_np);
 
 	bank = d->pin_banks;
 	for (i = 0; i < d->nr_banks; ++i, ++bank) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/samsung/pinctrl-samsung.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/samsung/pinctrl-samsung.c
@@ -272,6 +272,7 @@
 						&reserved_maps, num_maps);
 		if (ret < 0) {
 			samsung_dt_free_map(pctldev, *map, *num_maps);
+			of_node_put(np);
 			return ret;
 		}
 	}
@@ -785,8 +786,10 @@
 		if (!of_get_child_count(cfg_np)) {
 			ret = samsung_pinctrl_create_function(dev, drvdata,
 							cfg_np, func);
-			if (ret < 0)
+			if (ret < 0) {
+				of_node_put(cfg_np);
 				return ERR_PTR(ret);
+			}
 			if (ret > 0) {
 				++func;
 				++func_cnt;
@@ -797,8 +800,11 @@
 		for_each_child_of_node(cfg_np, func_np) {
 			ret = samsung_pinctrl_create_function(dev, drvdata,
 						func_np, func);
-			if (ret < 0)
+			if (ret < 0) {
+				of_node_put(func_np);
+				of_node_put(cfg_np);
 				return ERR_PTR(ret);
+			}
 			if (ret > 0) {
 				++func;
 				++func_cnt;
@@ -912,7 +918,7 @@
 		pin_bank->grange.pin_base = drvdata->pin_base
 						+ pin_bank->pin_base;
 		pin_bank->grange.base = pin_bank->grange.pin_base;
-		pin_bank->grange.npins = pin_bank->gpio_chip.ngpio;
+		pin_bank->grange.npins = pin_bank->nr_pins;
 		pin_bank->grange.gc = &pin_bank->gpio_chip;
 		pinctrl_add_gpio_range(drvdata->pctl_dev, &pin_bank->grange);
 	}
@@ -996,6 +1002,16 @@
 	return &(of_data->ctrl[id]);
 }
 
+static void samsung_banks_of_node_put(struct samsung_pinctrl_drv_data *d)
+{
+	struct samsung_pin_bank *bank;
+	unsigned int i;
+
+	bank = d->pin_banks;
+	for (i = 0; i < d->nr_banks; ++i, ++bank)
+		of_node_put(bank->of_node);
+}
+
 /* retrieve the soc specific data */
 static const struct samsung_pin_ctrl *
 samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d,
@@ -1110,19 +1126,19 @@
 	if (ctrl->retention_data) {
 		drvdata->retention_ctrl = ctrl->retention_data->init(drvdata,
 							  ctrl->retention_data);
-		if (IS_ERR(drvdata->retention_ctrl))
-			return PTR_ERR(drvdata->retention_ctrl);
+		if (IS_ERR(drvdata->retention_ctrl)) {
+			ret = PTR_ERR(drvdata->retention_ctrl);
+			goto err_put_banks;
+		}
 	}
 
 	ret = samsung_pinctrl_register(pdev, drvdata);
 	if (ret)
-		return ret;
+		goto err_put_banks;
 
 	ret = samsung_gpiolib_register(pdev, drvdata);
-	if (ret) {
-		samsung_pinctrl_unregister(pdev, drvdata);
-		return ret;
-	}
+	if (ret)
+		goto err_unregister;
 
 	if (ctrl->eint_gpio_init)
 		ctrl->eint_gpio_init(drvdata);
@@ -1132,6 +1148,12 @@
 	platform_set_drvdata(pdev, drvdata);
 
 	return 0;
+
+err_unregister:
+	samsung_pinctrl_unregister(pdev, drvdata);
+err_put_banks:
+	samsung_banks_of_node_put(drvdata);
+	return ret;
 }
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/sh-pfc/core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/sh-pfc/core.c
@@ -29,12 +29,12 @@
 static int sh_pfc_map_resources(struct sh_pfc *pfc,
 				struct platform_device *pdev)
 {
-	unsigned int num_windows, num_irqs;
 	struct sh_pfc_window *windows;
 	unsigned int *irqs = NULL;
+	unsigned int num_windows;
 	struct resource *res;
 	unsigned int i;
-	int irq;
+	int num_irqs;
 
 	/* Count the MEM and IRQ resources. */
 	for (num_windows = 0;; num_windows++) {
@@ -42,17 +42,13 @@
 		if (!res)
 			break;
 	}
-	for (num_irqs = 0;; num_irqs++) {
-		irq = platform_get_irq(pdev, num_irqs);
-		if (irq == -EPROBE_DEFER)
-			return irq;
-		if (irq < 0)
-			break;
-	}
-
 	if (num_windows == 0)
 		return -EINVAL;
 
+	num_irqs = platform_irq_count(pdev);
+	if (num_irqs < 0)
+		return num_irqs;
+
 	/* Allocate memory windows and IRQs arrays. */
 	windows = devm_kcalloc(pfc->dev, num_windows, sizeof(*windows),
 			       GFP_KERNEL);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/sh-pfc/pfc-r8a77470.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/sh-pfc/pfc-r8a77470.c
@@ -2121,7 +2121,7 @@
 	VI0_CLK_MARK,
 };
 /* - VIN1 ------------------------------------------------------------------- */
-static const union vin_data vin1_data_pins = {
+static const union vin_data12 vin1_data_pins = {
 	.data12 = {
 		RCAR_GP_PIN(3,  1), RCAR_GP_PIN(3, 2),
 		RCAR_GP_PIN(3,  3), RCAR_GP_PIN(3, 4),
@@ -2131,7 +2131,7 @@
 		RCAR_GP_PIN(3, 15), RCAR_GP_PIN(3, 16),
 	},
 };
-static const union vin_data vin1_data_mux = {
+static const union vin_data12 vin1_data_mux = {
 	.data12 = {
 		VI1_DATA0_MARK, VI1_DATA1_MARK,
 		VI1_DATA2_MARK, VI1_DATA3_MARK,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/sh-pfc/pfc-r8a7778.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/sh-pfc/pfc-r8a7778.c
@@ -2305,7 +2305,7 @@
 		FN_ATAG0_A,	0,		FN_REMOCON_B,	0,
 		/* IP0_11_8 [4] */
 		FN_SD1_DAT2_A,	FN_MMC_D2,	0,		FN_BS,
-		FN_ATADIR0_A,	0,		FN_SDSELF_B,	0,
+		FN_ATADIR0_A,	0,		FN_SDSELF_A,	0,
 		FN_PWM4_B,	0,		0,		0,
 		0,		0,		0,		0,
 		/* IP0_7_5 [3] */
@@ -2349,7 +2349,7 @@
 		FN_TS_SDAT0_A,	0,		0,		0,
 		0,		0,		0,		0,
 		/* IP1_10_8 [3] */
-		FN_SD1_CLK_B,	FN_MMC_D6,	0,		FN_A24,
+		FN_SD1_CD_A,	FN_MMC_D6,	0,		FN_A24,
 		FN_DREQ1_A,	0,		FN_HRX0_B,	FN_TS_SPSYNC0_A,
 		/* IP1_7_5 [3] */
 		FN_A23,		FN_HTX0_B,	FN_TX2_B,	FN_DACK2_A,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/sh-pfc/pfc-r8a7796.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/sh-pfc/pfc-r8a7796.c
@@ -68,6 +68,7 @@
 	PIN_NOGP_CFG(QSPI1_MOSI_IO0, "QSPI1_MOSI_IO0", fn, CFG_FLAGS),	\
 	PIN_NOGP_CFG(QSPI1_SPCLK, "QSPI1_SPCLK", fn, CFG_FLAGS),	\
 	PIN_NOGP_CFG(QSPI1_SSL, "QSPI1_SSL", fn, CFG_FLAGS),		\
+	PIN_NOGP_CFG(PRESET_N, "PRESET#", fn, SH_PFC_PIN_CFG_PULL_DOWN),\
 	PIN_NOGP_CFG(RPC_INT_N, "RPC_INT#", fn, CFG_FLAGS),		\
 	PIN_NOGP_CFG(RPC_RESET_N, "RPC_RESET#", fn, CFG_FLAGS),		\
 	PIN_NOGP_CFG(RPC_WP_N, "RPC_WP#", fn, CFG_FLAGS),		\
@@ -6109,7 +6110,7 @@
 		[ 4] = RCAR_GP_PIN(6, 29),	/* USB30_OVC */
 		[ 5] = RCAR_GP_PIN(6, 30),	/* GP6_30 */
 		[ 6] = RCAR_GP_PIN(6, 31),	/* GP6_31 */
-		[ 7] = SH_PFC_PIN_NONE,
+		[ 7] = PIN_PRESET_N,		/* PRESET# */
 		[ 8] = SH_PFC_PIN_NONE,
 		[ 9] = SH_PFC_PIN_NONE,
 		[10] = SH_PFC_PIN_NONE,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/sh-pfc/pfc-r8a77965.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/sh-pfc/pfc-r8a77965.c
@@ -5984,7 +5984,7 @@
 		{ PIN_DU_DOTCLKIN1,    0, 2 },	/* DU_DOTCLKIN1 */
 	} },
 	{ PINMUX_DRIVE_REG("DRVCTRL12", 0xe6060330) {
-		{ PIN_DU_DOTCLKIN3,   28, 2 },	/* DU_DOTCLKIN3 */
+		{ PIN_DU_DOTCLKIN3,   24, 2 },	/* DU_DOTCLKIN3 */
 		{ PIN_FSCLKST,        20, 2 },	/* FSCLKST */
 		{ PIN_TMS,             4, 2 },	/* TMS */
 	} },
@@ -6240,8 +6240,8 @@
 		[31] = PIN_DU_DOTCLKIN1,	/* DU_DOTCLKIN1 */
 	} },
 	{ PINMUX_BIAS_REG("PUEN3", 0xe606040c, "PUD3", 0xe606044c) {
-		[ 0] = PIN_DU_DOTCLKIN3,	/* DU_DOTCLKIN3 */
-		[ 1] = SH_PFC_PIN_NONE,
+		[ 0] = SH_PFC_PIN_NONE,
+		[ 1] = PIN_DU_DOTCLKIN3,	/* DU_DOTCLKIN3 */
 		[ 2] = PIN_FSCLKST,		/* FSCLKST */
 		[ 3] = PIN_EXTALR,		/* EXTALR*/
 		[ 4] = PIN_TRST_N,		/* TRST# */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/sh-pfc/pfc-r8a77990.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/sh-pfc/pfc-r8a77990.c
@@ -54,10 +54,10 @@
 	PIN_NOGP_CFG(FSCLKST_N, "FSCLKST_N", fn, CFG_FLAGS),		\
 	PIN_NOGP_CFG(MLB_REF, "MLB_REF", fn, CFG_FLAGS),		\
 	PIN_NOGP_CFG(PRESETOUT_N, "PRESETOUT_N", fn, CFG_FLAGS),	\
-	PIN_NOGP_CFG(TCK, "TCK", fn, CFG_FLAGS),			\
-	PIN_NOGP_CFG(TDI, "TDI", fn, CFG_FLAGS),			\
-	PIN_NOGP_CFG(TMS, "TMS", fn, CFG_FLAGS),			\
-	PIN_NOGP_CFG(TRST_N, "TRST_N", fn, CFG_FLAGS)
+	PIN_NOGP_CFG(TCK, "TCK", fn, SH_PFC_PIN_CFG_PULL_UP),		\
+	PIN_NOGP_CFG(TDI, "TDI", fn, SH_PFC_PIN_CFG_PULL_UP),		\
+	PIN_NOGP_CFG(TMS, "TMS", fn, SH_PFC_PIN_CFG_PULL_UP),		\
+	PIN_NOGP_CFG(TRST_N, "TRST_N", fn, SH_PFC_PIN_CFG_PULL_UP)
 
 /*
  * F_() : just information
@@ -448,6 +448,8 @@
 #define MOD_SEL0_1_0	   REV4(FM(SEL_SPEED_PULSE_IF_0),	FM(SEL_SPEED_PULSE_IF_1),	FM(SEL_SPEED_PULSE_IF_2),	F_(0, 0))
 
 /* MOD_SEL1 */			/* 0 */				/* 1 */				/* 2 */				/* 3 */			/* 4 */			/* 5 */		/* 6 */		/* 7 */
+#define MOD_SEL1_31		FM(SEL_SIMCARD_0)		FM(SEL_SIMCARD_1)
+#define MOD_SEL1_30		FM(SEL_SSI2_0)			FM(SEL_SSI2_1)
 #define MOD_SEL1_29		FM(SEL_TIMER_TMU_0)		FM(SEL_TIMER_TMU_1)
 #define MOD_SEL1_28		FM(SEL_USB_20_CH0_0)		FM(SEL_USB_20_CH0_1)
 #define MOD_SEL1_26		FM(SEL_DRIF2_0)			FM(SEL_DRIF2_1)
@@ -468,7 +470,8 @@
 
 #define PINMUX_MOD_SELS	\
 \
-MOD_SEL0_30_29 \
+			MOD_SEL1_31 \
+MOD_SEL0_30_29		MOD_SEL1_30 \
 			MOD_SEL1_29 \
 MOD_SEL0_28		MOD_SEL1_28 \
 MOD_SEL0_27_26 \
@@ -1058,7 +1061,7 @@
 	PINMUX_IPSR_MSEL(IP10_27_24,		RIF0_CLK_B,	SEL_DRIF0_1),
 	PINMUX_IPSR_MSEL(IP10_27_24,		SCL2_B,		SEL_I2C2_1),
 	PINMUX_IPSR_MSEL(IP10_27_24,		TCLK1_A,	SEL_TIMER_TMU_0),
-	PINMUX_IPSR_GPSR(IP10_27_24,		SSI_SCK2_B),
+	PINMUX_IPSR_MSEL(IP10_27_24,		SSI_SCK2_B,	SEL_SSI2_1),
 	PINMUX_IPSR_GPSR(IP10_27_24,		TS_SCK0),
 
 	PINMUX_IPSR_GPSR(IP10_31_28,		SD0_WP),
@@ -1067,7 +1070,7 @@
 	PINMUX_IPSR_MSEL(IP10_31_28,		RIF0_D0_B,	SEL_DRIF0_1),
 	PINMUX_IPSR_MSEL(IP10_31_28,		SDA2_B,		SEL_I2C2_1),
 	PINMUX_IPSR_MSEL(IP10_31_28,		TCLK2_A,	SEL_TIMER_TMU_0),
-	PINMUX_IPSR_GPSR(IP10_31_28,		SSI_WS2_B),
+	PINMUX_IPSR_MSEL(IP10_31_28,		SSI_WS2_B,	SEL_SSI2_1),
 	PINMUX_IPSR_GPSR(IP10_31_28,		TS_SDAT0),
 
 	/* IPSR11 */
@@ -1085,13 +1088,13 @@
 
 	PINMUX_IPSR_MSEL(IP11_11_8,		RX0_A,		SEL_SCIF0_0),
 	PINMUX_IPSR_MSEL(IP11_11_8,		HRX1_A,		SEL_HSCIF1_0),
-	PINMUX_IPSR_GPSR(IP11_11_8,		SSI_SCK2_A),
+	PINMUX_IPSR_MSEL(IP11_11_8,		SSI_SCK2_A,	SEL_SSI2_0),
 	PINMUX_IPSR_GPSR(IP11_11_8,		RIF1_SYNC),
 	PINMUX_IPSR_GPSR(IP11_11_8,		TS_SCK1),
 
 	PINMUX_IPSR_MSEL(IP11_15_12,		TX0_A,		SEL_SCIF0_0),
 	PINMUX_IPSR_GPSR(IP11_15_12,		HTX1_A),
-	PINMUX_IPSR_GPSR(IP11_15_12,		SSI_WS2_A),
+	PINMUX_IPSR_MSEL(IP11_15_12,		SSI_WS2_A,	SEL_SSI2_0),
 	PINMUX_IPSR_GPSR(IP11_15_12,		RIF1_D0),
 	PINMUX_IPSR_GPSR(IP11_15_12,		TS_SDAT1),
 
@@ -1196,7 +1199,7 @@
 	PINMUX_IPSR_MSEL(IP13_19_16,		RIF0_D1_A,	SEL_DRIF0_0),
 	PINMUX_IPSR_MSEL(IP13_19_16,		SDA1_B,		SEL_I2C1_1),
 	PINMUX_IPSR_MSEL(IP13_19_16,		TCLK2_B,	SEL_TIMER_TMU_1),
-	PINMUX_IPSR_GPSR(IP13_19_16,		SIM0_D_A),
+	PINMUX_IPSR_MSEL(IP13_19_16,		SIM0_D_A,	SEL_SIMCARD_0),
 
 	PINMUX_IPSR_GPSR(IP13_23_20,		MLB_DAT),
 	PINMUX_IPSR_MSEL(IP13_23_20,		TX0_B,		SEL_SCIF0_1),
@@ -1264,7 +1267,7 @@
 	PINMUX_IPSR_GPSR(IP15_15_12,		TPU0TO2),
 	PINMUX_IPSR_MSEL(IP15_15_12,		SDA1_D,		SEL_I2C1_3),
 	PINMUX_IPSR_MSEL(IP15_15_12,		FSO_CFE_1_N_B,	SEL_FSO_1),
-	PINMUX_IPSR_GPSR(IP15_15_12,		SIM0_D_B),
+	PINMUX_IPSR_MSEL(IP15_15_12,		SIM0_D_B,	SEL_SIMCARD_1),
 
 	PINMUX_IPSR_GPSR(IP15_19_16,		SSI_SDATA6),
 	PINMUX_IPSR_MSEL(IP15_19_16,		HRTS2_N_A,	SEL_HSCIF2_0),
@@ -4957,11 +4960,11 @@
 		MOD_SEL0_1_0 ))
 	},
 	{ PINMUX_CFG_REG_VAR("MOD_SEL1", 0xe6060504, 32,
-			     GROUP(2, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1,
-				   2, 2, 2, 1, 1, 2, 1, 4),
+			     GROUP(1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1,
+				   1, 2, 2, 2, 1, 1, 2, 1, 4),
 			     GROUP(
-		/* RESERVED 31, 30 */
-		0, 0, 0, 0,
+		MOD_SEL1_31
+		MOD_SEL1_30
 		MOD_SEL1_29
 		MOD_SEL1_28
 		/* RESERVED 27 */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/sh-pfc/pfc-sh7264.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/sh-pfc/pfc-sh7264.c
@@ -497,17 +497,15 @@
 	SD_WP_MARK, SD_CLK_MARK, SD_CMD_MARK,
 	CRX0_MARK, CRX1_MARK,
 	CTX0_MARK, CTX1_MARK,
+	CRX0_CRX1_MARK, CTX0_CTX1_MARK,
 
 	PWM1A_MARK, PWM1B_MARK, PWM1C_MARK, PWM1D_MARK,
 	PWM1E_MARK, PWM1F_MARK, PWM1G_MARK, PWM1H_MARK,
 	PWM2A_MARK, PWM2B_MARK, PWM2C_MARK, PWM2D_MARK,
 	PWM2E_MARK, PWM2F_MARK, PWM2G_MARK, PWM2H_MARK,
 	IERXD_MARK, IETXD_MARK,
-	CRX0_CRX1_MARK,
 	WDTOVF_MARK,
 
-	CRX0X1_MARK,
-
 	/* DMAC */
 	TEND0_MARK, DACK0_MARK, DREQ0_MARK,
 	TEND1_MARK, DACK1_MARK, DREQ1_MARK,
@@ -995,12 +993,12 @@
 
 	PINMUX_DATA(PJ3_DATA, PJ3MD_00),
 	PINMUX_DATA(CRX1_MARK, PJ3MD_01),
-	PINMUX_DATA(CRX0X1_MARK, PJ3MD_10),
+	PINMUX_DATA(CRX0_CRX1_MARK, PJ3MD_10),
 	PINMUX_DATA(IRQ1_PJ_MARK, PJ3MD_11),
 
 	PINMUX_DATA(PJ2_DATA, PJ2MD_000),
 	PINMUX_DATA(CTX1_MARK, PJ2MD_001),
-	PINMUX_DATA(CRX0_CRX1_MARK, PJ2MD_010),
+	PINMUX_DATA(CTX0_CTX1_MARK, PJ2MD_010),
 	PINMUX_DATA(CS2_MARK, PJ2MD_011),
 	PINMUX_DATA(SCK0_MARK, PJ2MD_100),
 	PINMUX_DATA(LCD_M_DISP_MARK, PJ2MD_101),
@@ -1245,6 +1243,7 @@
 	GPIO_FN(CTX1),
 	GPIO_FN(CRX1),
 	GPIO_FN(CTX0),
+	GPIO_FN(CTX0_CTX1),
 	GPIO_FN(CRX0),
 	GPIO_FN(CRX0_CRX1),
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/sh-pfc/pfc-sh7269.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/sh-pfc/pfc-sh7269.c
@@ -737,13 +737,12 @@
 	CRX0_MARK, CTX0_MARK,
 	CRX1_MARK, CTX1_MARK,
 	CRX2_MARK, CTX2_MARK,
-	CRX0_CRX1_MARK,
-	CRX0_CRX1_CRX2_MARK,
-	CTX0CTX1CTX2_MARK,
+	CRX0_CRX1_MARK, CTX0_CTX1_MARK,
+	CRX0_CRX1_CRX2_MARK, CTX0_CTX1_CTX2_MARK,
 	CRX1_PJ22_MARK, CTX1_PJ23_MARK,
 	CRX2_PJ20_MARK, CTX2_PJ21_MARK,
-	CRX0CRX1_PJ22_MARK,
-	CRX0CRX1CRX2_PJ20_MARK,
+	CRX0_CRX1_PJ22_MARK, CTX0_CTX1_PJ23_MARK,
+	CRX0_CRX1_CRX2_PJ20_MARK, CTX0_CTX1_CTX2_PJ21_MARK,
 
 	/* VDC */
 	DV_CLK_MARK,
@@ -821,6 +820,7 @@
 	PINMUX_DATA(CS3_MARK, PC8MD_001),
 	PINMUX_DATA(TXD7_MARK, PC8MD_010),
 	PINMUX_DATA(CTX1_MARK, PC8MD_011),
+	PINMUX_DATA(CTX0_CTX1_MARK, PC8MD_100),
 
 	PINMUX_DATA(PC7_DATA, PC7MD_000),
 	PINMUX_DATA(CKE_MARK, PC7MD_001),
@@ -833,11 +833,12 @@
 	PINMUX_DATA(CAS_MARK, PC6MD_001),
 	PINMUX_DATA(SCK7_MARK, PC6MD_010),
 	PINMUX_DATA(CTX0_MARK, PC6MD_011),
+	PINMUX_DATA(CTX0_CTX1_CTX2_MARK, PC6MD_100),
 
 	PINMUX_DATA(PC5_DATA, PC5MD_000),
 	PINMUX_DATA(RAS_MARK, PC5MD_001),
 	PINMUX_DATA(CRX0_MARK, PC5MD_011),
-	PINMUX_DATA(CTX0CTX1CTX2_MARK, PC5MD_100),
+	PINMUX_DATA(CTX0_CTX1_CTX2_MARK, PC5MD_100),
 	PINMUX_DATA(IRQ0_PC_MARK, PC5MD_101),
 
 	PINMUX_DATA(PC4_DATA, PC4MD_00),
@@ -1289,30 +1290,32 @@
 	PINMUX_DATA(LCD_DATA23_PJ23_MARK, PJ23MD_010),
 	PINMUX_DATA(LCD_TCON6_MARK, PJ23MD_011),
 	PINMUX_DATA(IRQ3_PJ_MARK, PJ23MD_100),
-	PINMUX_DATA(CTX1_MARK, PJ23MD_101),
+	PINMUX_DATA(CTX1_PJ23_MARK, PJ23MD_101),
+	PINMUX_DATA(CTX0_CTX1_PJ23_MARK, PJ23MD_110),
 
 	PINMUX_DATA(PJ22_DATA, PJ22MD_000),
 	PINMUX_DATA(DV_DATA22_MARK, PJ22MD_001),
 	PINMUX_DATA(LCD_DATA22_PJ22_MARK, PJ22MD_010),
 	PINMUX_DATA(LCD_TCON5_MARK, PJ22MD_011),
 	PINMUX_DATA(IRQ2_PJ_MARK, PJ22MD_100),
-	PINMUX_DATA(CRX1_MARK, PJ22MD_101),
-	PINMUX_DATA(CRX0_CRX1_MARK, PJ22MD_110),
+	PINMUX_DATA(CRX1_PJ22_MARK, PJ22MD_101),
+	PINMUX_DATA(CRX0_CRX1_PJ22_MARK, PJ22MD_110),
 
 	PINMUX_DATA(PJ21_DATA, PJ21MD_000),
 	PINMUX_DATA(DV_DATA21_MARK, PJ21MD_001),
 	PINMUX_DATA(LCD_DATA21_PJ21_MARK, PJ21MD_010),
 	PINMUX_DATA(LCD_TCON4_MARK, PJ21MD_011),
 	PINMUX_DATA(IRQ1_PJ_MARK, PJ21MD_100),
-	PINMUX_DATA(CTX2_MARK, PJ21MD_101),
+	PINMUX_DATA(CTX2_PJ21_MARK, PJ21MD_101),
+	PINMUX_DATA(CTX0_CTX1_CTX2_PJ21_MARK, PJ21MD_110),
 
 	PINMUX_DATA(PJ20_DATA, PJ20MD_000),
 	PINMUX_DATA(DV_DATA20_MARK, PJ20MD_001),
 	PINMUX_DATA(LCD_DATA20_PJ20_MARK, PJ20MD_010),
 	PINMUX_DATA(LCD_TCON3_MARK, PJ20MD_011),
 	PINMUX_DATA(IRQ0_PJ_MARK, PJ20MD_100),
-	PINMUX_DATA(CRX2_MARK, PJ20MD_101),
-	PINMUX_DATA(CRX0CRX1CRX2_PJ20_MARK, PJ20MD_110),
+	PINMUX_DATA(CRX2_PJ20_MARK, PJ20MD_101),
+	PINMUX_DATA(CRX0_CRX1_CRX2_PJ20_MARK, PJ20MD_110),
 
 	PINMUX_DATA(PJ19_DATA, PJ19MD_000),
 	PINMUX_DATA(DV_DATA19_MARK, PJ19MD_001),
@@ -1663,12 +1666,24 @@
 	GPIO_FN(WDTOVF),
 
 	/* CAN */
+	GPIO_FN(CTX2),
+	GPIO_FN(CRX2),
 	GPIO_FN(CTX1),
 	GPIO_FN(CRX1),
 	GPIO_FN(CTX0),
 	GPIO_FN(CRX0),
+	GPIO_FN(CTX0_CTX1),
 	GPIO_FN(CRX0_CRX1),
+	GPIO_FN(CTX0_CTX1_CTX2),
 	GPIO_FN(CRX0_CRX1_CRX2),
+	GPIO_FN(CTX2_PJ21),
+	GPIO_FN(CRX2_PJ20),
+	GPIO_FN(CTX1_PJ23),
+	GPIO_FN(CRX1_PJ22),
+	GPIO_FN(CTX0_CTX1_PJ23),
+	GPIO_FN(CRX0_CRX1_PJ22),
+	GPIO_FN(CTX0_CTX1_CTX2_PJ21),
+	GPIO_FN(CRX0_CRX1_CRX2_PJ20),
 
 	/* DMAC */
 	GPIO_FN(TEND0),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/sh-pfc/pfc-sh7734.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/sh-pfc/pfc-sh7734.c
@@ -1450,7 +1450,7 @@
 	GPIO_FN(ET0_ETXD2_A),
 	GPIO_FN(EX_CS5), GPIO_FN(SD1_CMD_A), GPIO_FN(ATADIR), GPIO_FN(QSSL_B),
 	GPIO_FN(ET0_ETXD3_A),
-	GPIO_FN(RD_WR), GPIO_FN(TCLK1_B),
+	GPIO_FN(RD_WR), GPIO_FN(TCLK0), GPIO_FN(CAN_CLK_B), GPIO_FN(ET0_ETXD4),
 	GPIO_FN(EX_WAIT0), GPIO_FN(TCLK1_B),
 	GPIO_FN(EX_WAIT1), GPIO_FN(SD1_DAT0_A), GPIO_FN(DREQ2),
 		GPIO_FN(CAN1_TX_C), GPIO_FN(ET0_LINK_C), GPIO_FN(ET0_ETXD5_A),
@@ -1949,7 +1949,7 @@
 	    /* IP3_20 [1] */
 		FN_EX_WAIT0, FN_TCLK1_B,
 	    /* IP3_19_18 [2] */
-		FN_RD_WR, FN_TCLK1_B, 0, 0,
+		FN_RD_WR, FN_TCLK0, FN_CAN_CLK_B, FN_ET0_ETXD4,
 	    /* IP3_17_15 [3] */
 		FN_EX_CS5, FN_SD1_CMD_A, FN_ATADIR, FN_QSSL_B,
 		FN_ET0_ETXD3_A, 0, 0, 0,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/sh-pfc/sh_pfc.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/sh-pfc/sh_pfc.h
@@ -422,12 +422,12 @@
 /*
  * Describe a pinmux configuration in which a pin is physically multiplexed
  * with other pins.
- *   - ipsr: IPSR field (unused, for documentation purposes only)
+ *   - ipsr: IPSR field
  *   - fn: Function name
  *   - psel: Physical multiplexing selector
  */
 #define PINMUX_IPSR_PHYS(ipsr, fn, psel) \
-	PINMUX_DATA(fn##_MARK, FN_##psel)
+	PINMUX_DATA(fn##_MARK, FN_##psel, FN_##ipsr)
 
 /*
  * Describe a pinmux configuration for a single-function pin with GPIO
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/stm32/pinctrl-stm32.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/stm32/pinctrl-stm32.c
@@ -1153,7 +1153,7 @@
 	struct resource res;
 	struct reset_control *rstc;
 	int npins = STM32_GPIO_PINS_PER_BANK;
-	int bank_nr, err;
+	int bank_nr, err, i = 0;
 
 	rstc = of_reset_control_get_exclusive(np, NULL);
 	if (!IS_ERR(rstc))
@@ -1182,9 +1182,14 @@
 
 	of_property_read_string(np, "st,bank-name", &bank->gpio_chip.label);
 
-	if (!of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, 0, &args)) {
+	if (!of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, i, &args)) {
 		bank_nr = args.args[1] / STM32_GPIO_PINS_PER_BANK;
 		bank->gpio_chip.base = args.args[1];
+
+		/* get the last defined gpio line (offset + nb of pins) */
+		npins = args.args[0] + args.args[2];
+		while (!of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, ++i, &args))
+			npins = max(npins, (int)(args.args[0] + args.args[2]));
 	} else {
 		bank_nr = pctl->nbanks;
 		bank->gpio_chip.base = bank_nr * STM32_GPIO_PINS_PER_BANK;
@@ -1210,15 +1215,17 @@
 	bank->bank_ioport_nr = bank_ioport_nr;
 	spin_lock_init(&bank->lock);
 
-	/* create irq hierarchical domain */
-	bank->fwnode = of_node_to_fwnode(np);
+	if (pctl->domain) {
+		/* create irq hierarchical domain */
+		bank->fwnode = of_node_to_fwnode(np);
 
-	bank->domain = irq_domain_create_hierarchy(pctl->domain, 0,
-					STM32_GPIO_IRQ_LINE, bank->fwnode,
-					&stm32_gpio_domain_ops, bank);
+		bank->domain = irq_domain_create_hierarchy(pctl->domain, 0, STM32_GPIO_IRQ_LINE,
+							   bank->fwnode, &stm32_gpio_domain_ops,
+							   bank);
 
-	if (!bank->domain)
-		return -ENODEV;
+		if (!bank->domain)
+			return -ENODEV;
+	}
 
 	err = gpiochip_add_data(&bank->gpio_chip, bank);
 	if (err) {
@@ -1243,6 +1250,7 @@
 		return ERR_PTR(-ENXIO);
 
 	domain = irq_find_host(parent);
+	of_node_put(parent);
 	if (!domain)
 		/* domain not registered yet */
 		return ERR_PTR(-EPROBE_DEFER);
@@ -1388,6 +1396,8 @@
 	pctl->domain = stm32_pctrl_get_irq_domain(np);
 	if (IS_ERR(pctl->domain))
 		return PTR_ERR(pctl->domain);
+	if (!pctl->domain)
+		dev_warn(dev, "pinctrl without interrupt support\n");
 
 	/* hwspinlock is optional */
 	hwlock_id = of_hwspin_lock_get_id(pdev->dev.of_node, 0);
@@ -1549,8 +1559,8 @@
 	struct stm32_pinctrl_group *g = pctl->groups;
 	int i;
 
-	for (i = g->pin; i < g->pin + pctl->ngroups; i++)
-		stm32_pinctrl_restore_gpio_regs(pctl, i);
+	for (i = 0; i < pctl->ngroups; i++, g++)
+		stm32_pinctrl_restore_gpio_regs(pctl, g->pin);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/sunxi/pinctrl-sun50i-h6-r.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/sunxi/pinctrl-sun50i-h6-r.c
@@ -105,6 +105,7 @@
 	.npins = ARRAY_SIZE(sun50i_h6_r_pins),
 	.pin_base = PL_BASE,
 	.irq_banks = 2,
+	.io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_SEL,
 };
 
 static int sun50i_h6_r_pinctrl_probe(struct platform_device *pdev)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c
@@ -158,26 +158,26 @@
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 14),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
-		  SUNXI_FUNCTION(0x2, "nand"),		/* DQ6 */
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* DQ6 */
 		  SUNXI_FUNCTION(0x3, "mmc2")),		/* D6 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 15),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
-		  SUNXI_FUNCTION(0x2, "nand"),		/* DQ7 */
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* DQ7 */
 		  SUNXI_FUNCTION(0x3, "mmc2")),		/* D7 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 16),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
-		  SUNXI_FUNCTION(0x2, "nand"),		/* DQS */
+		  SUNXI_FUNCTION(0x2, "nand0"),		/* DQS */
 		  SUNXI_FUNCTION(0x3, "mmc2")),		/* RST */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 17),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
-		  SUNXI_FUNCTION(0x2, "nand")),		/* CE2 */
+		  SUNXI_FUNCTION(0x2, "nand0")),	/* CE2 */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 18),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
-		  SUNXI_FUNCTION(0x2, "nand")),		/* CE3 */
+		  SUNXI_FUNCTION(0x2, "nand0")),	/* CE3 */
 	/* Hole */
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 2),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/sunxi/pinctrl-suniv-f1c100s.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/sunxi/pinctrl-suniv-f1c100s.c
@@ -204,7 +204,7 @@
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
 		  SUNXI_FUNCTION(0x1, "gpio_out"),
 		  SUNXI_FUNCTION(0x2, "lcd"),		/* D20 */
-		  SUNXI_FUNCTION(0x3, "lvds1"),		/* RX */
+		  SUNXI_FUNCTION(0x3, "uart2"),		/* RX */
 		  SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 14)),
 	SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 15),
 		  SUNXI_FUNCTION(0x0, "gpio_in"),
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -536,6 +536,8 @@
 	struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
 	int i;
 
+	pin -= pctl->desc->pin_base;
+
 	for (i = 0; i < num_configs; i++) {
 		enum pin_config_param param;
 		unsigned long flags;
@@ -614,7 +616,7 @@
 					 unsigned pin,
 					 struct regulator *supply)
 {
-	unsigned short bank = pin / PINS_PER_BANK;
+	unsigned short bank;
 	unsigned long flags;
 	u32 val, reg;
 	int uV;
@@ -630,6 +632,9 @@
 	if (uV == 0)
 		return 0;
 
+	pin -= pctl->desc->pin_base;
+	bank = pin / PINS_PER_BANK;
+
 	switch (pctl->desc->io_bias_cfg_variant) {
 	case BIAS_VOLTAGE_GRP_CONFIG:
 		/*
@@ -647,8 +652,6 @@
 		else
 			val = 0xD; /* 3.3V */
 
-		pin -= pctl->desc->pin_base;
-
 		reg = readl(pctl->membase + sunxi_grp_config_reg(pin));
 		reg &= ~IO_BIAS_MASK;
 		writel(reg | val, pctl->membase + sunxi_grp_config_reg(pin));
@@ -1130,20 +1133,22 @@
 	if (bank == pctl->desc->irq_banks)
 		return;
 
+	chained_irq_enter(chip, desc);
+
 	reg = sunxi_irq_status_reg_from_bank(pctl->desc, bank);
 	val = readl(pctl->membase + reg);
 
 	if (val) {
 		int irqoffset;
 
-		chained_irq_enter(chip, desc);
 		for_each_set_bit(irqoffset, &val, IRQ_PER_BANK) {
 			int pin_irq = irq_find_mapping(pctl->domain,
 						       bank * IRQ_PER_BANK + irqoffset);
 			generic_handle_irq(pin_irq);
 		}
-		chained_irq_exit(chip, desc);
 	}
+
+	chained_irq_exit(chip, desc);
 }
 
 static int sunxi_pinctrl_add_function(struct sunxi_pinctrl *pctl,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/tegra/pinctrl-tegra.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/tegra/pinctrl-tegra.c
@@ -685,8 +685,8 @@
 }
 
 const struct dev_pm_ops tegra_pinctrl_pm = {
-	.suspend = &tegra_pinctrl_suspend,
-	.resume = &tegra_pinctrl_resume
+	.suspend_noirq = &tegra_pinctrl_suspend,
+	.resume_noirq = &tegra_pinctrl_resume
 };
 
 static bool gpio_node_has_range(const char *compatible)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pinctrl/ti/pinctrl-ti-iodelay.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pinctrl/ti/pinctrl-ti-iodelay.c
@@ -496,7 +496,7 @@
 		return -EINVAL;
 
 	rows = pinctrl_count_index_with_args(np, name);
-	if (rows == -EINVAL)
+	if (rows < 0)
 		return rows;
 
 	*map = devm_kzalloc(iod->dev, sizeof(**map), GFP_KERNEL);
@@ -881,7 +881,7 @@
 	iod->desc.name = dev_name(dev);
 	iod->desc.owner = THIS_MODULE;
 
-	ret = pinctrl_register_and_init(&iod->desc, dev, iod, &iod->pctl);
+	ret = devm_pinctrl_register_and_init(dev, &iod->desc, iod, &iod->pctl);
 	if (ret) {
 		dev_err(dev, "Failed to register pinctrl\n");
 		goto exit_out;
@@ -889,7 +889,11 @@
 
 	platform_set_drvdata(pdev, iod);
 
-	return pinctrl_enable(iod->pctl);
+	ret = pinctrl_enable(iod->pctl);
+	if (ret)
+		goto exit_out;
+
+	return 0;
 
 exit_out:
 	of_node_put(np);
@@ -906,12 +910,6 @@
 {
 	struct ti_iodelay_device *iod = platform_get_drvdata(pdev);
 
-	if (!iod)
-		return 0;
-
-	if (iod->pctl)
-		pinctrl_unregister(iod->pctl);
-
 	ti_iodelay_pinconf_deinit_dev(iod);
 
 	/* Expect other allocations to be freed by devm */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/chrome/chromeos_laptop.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/chrome/chromeos_laptop.c
@@ -716,6 +716,7 @@
 chromeos_laptop_prepare_i2c_peripherals(struct chromeos_laptop *cros_laptop,
 					const struct chromeos_laptop *src)
 {
+	struct i2c_peripheral *i2c_peripherals;
 	struct i2c_peripheral *i2c_dev;
 	struct i2c_board_info *info;
 	int i;
@@ -724,17 +725,15 @@
 	if (!src->num_i2c_peripherals)
 		return 0;
 
-	cros_laptop->i2c_peripherals = kmemdup(src->i2c_peripherals,
-					       src->num_i2c_peripherals *
-						sizeof(*src->i2c_peripherals),
-					       GFP_KERNEL);
-	if (!cros_laptop->i2c_peripherals)
+	i2c_peripherals = kmemdup(src->i2c_peripherals,
+					      src->num_i2c_peripherals *
+					  sizeof(*src->i2c_peripherals),
+					  GFP_KERNEL);
+	if (!i2c_peripherals)
 		return -ENOMEM;
 
-	cros_laptop->num_i2c_peripherals = src->num_i2c_peripherals;
-
-	for (i = 0; i < cros_laptop->num_i2c_peripherals; i++) {
-		i2c_dev = &cros_laptop->i2c_peripherals[i];
+	for (i = 0; i < src->num_i2c_peripherals; i++) {
+		i2c_dev = &i2c_peripherals[i];
 		info = &i2c_dev->board_info;
 
 		error = chromeos_laptop_setup_irq(i2c_dev);
@@ -752,16 +751,19 @@
 		}
 	}
 
+	cros_laptop->i2c_peripherals = i2c_peripherals;
+	cros_laptop->num_i2c_peripherals = src->num_i2c_peripherals;
+
 	return 0;
 
 err_out:
 	while (--i >= 0) {
-		i2c_dev = &cros_laptop->i2c_peripherals[i];
+		i2c_dev = &i2c_peripherals[i];
 		info = &i2c_dev->board_info;
 		if (info->properties)
 			property_entries_free(info->properties);
 	}
-	kfree(cros_laptop->i2c_peripherals);
+	kfree(i2c_peripherals);
 	return error;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/chrome/cros_ec_chardev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/chrome/cros_ec_chardev.c
@@ -285,7 +285,7 @@
 	    u_cmd.insize > EC_MAX_MSG_BYTES)
 		return -EINVAL;
 
-	s_cmd = kmalloc(sizeof(*s_cmd) + max(u_cmd.outsize, u_cmd.insize),
+	s_cmd = kzalloc(sizeof(*s_cmd) + max(u_cmd.outsize, u_cmd.insize),
 			GFP_KERNEL);
 	if (!s_cmd)
 		return -ENOMEM;
@@ -328,6 +328,9 @@
 	if (copy_from_user(&s_mem, arg, sizeof(s_mem)))
 		return -EFAULT;
 
+	if (s_mem.bytes > sizeof(s_mem.buffer))
+		return -EINVAL;
+
 	num = ec_dev->cmd_readmem(ec_dev, s_mem.offset, s_mem.bytes,
 				  s_mem.buffer);
 	if (num <= 0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/chrome/cros_ec_debugfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/chrome/cros_ec_debugfs.c
@@ -26,6 +26,9 @@
 
 #define CIRC_ADD(idx, size, value)	(((idx) + (value)) & ((size) - 1))
 
+/* waitqueue for log readers */
+static DECLARE_WAIT_QUEUE_HEAD(cros_ec_debugfs_log_wq);
+
 /**
  * struct cros_ec_debugfs - EC debugging information.
  *
@@ -34,7 +37,6 @@
  * @log_buffer: circular buffer for console log information
  * @read_msg: preallocated EC command and buffer to read console log
  * @log_mutex: mutex to protect circular buffer
- * @log_wq: waitqueue for log readers
  * @log_poll_work: recurring task to poll EC for new console log data
  * @panicinfo_blob: panicinfo debugfs blob
  */
@@ -45,7 +47,6 @@
 	struct circ_buf log_buffer;
 	struct cros_ec_command *read_msg;
 	struct mutex log_mutex;
-	wait_queue_head_t log_wq;
 	struct delayed_work log_poll_work;
 	/* EC panicinfo */
 	struct debugfs_blob_wrapper panicinfo_blob;
@@ -108,7 +109,7 @@
 			buf_space--;
 		}
 
-		wake_up(&debug_info->log_wq);
+		wake_up(&cros_ec_debugfs_log_wq);
 	}
 
 	mutex_unlock(&debug_info->log_mutex);
@@ -142,7 +143,7 @@
 
 		mutex_unlock(&debug_info->log_mutex);
 
-		ret = wait_event_interruptible(debug_info->log_wq,
+		ret = wait_event_interruptible(cros_ec_debugfs_log_wq,
 					CIRC_CNT(cb->head, cb->tail, LOG_SIZE));
 		if (ret < 0)
 			return ret;
@@ -174,7 +175,7 @@
 	struct cros_ec_debugfs *debug_info = file->private_data;
 	__poll_t mask = 0;
 
-	poll_wait(file, &debug_info->log_wq, wait);
+	poll_wait(file, &cros_ec_debugfs_log_wq, wait);
 
 	mutex_lock(&debug_info->log_mutex);
 	if (CIRC_CNT(debug_info->log_buffer.head,
@@ -307,6 +308,7 @@
 	if (!msg)
 		return 0;
 
+	msg->version = 1;
 	msg->command = EC_CMD_GET_CMD_VERSIONS + ec->cmd_offset;
 	msg->outsize = sizeof(*params);
 	msg->insize = sizeof(*response);
@@ -359,7 +361,6 @@
 	debug_info->log_buffer.tail = 0;
 
 	mutex_init(&debug_info->log_mutex);
-	init_waitqueue_head(&debug_info->log_wq);
 
 	debugfs_create_file("console_log", S_IFREG | 0444, debug_info->dir,
 			    debug_info, &cros_ec_console_log_fops);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/chrome/cros_ec_ishtp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/chrome/cros_ec_ishtp.c
@@ -645,8 +645,10 @@
 
 	/* Register croc_ec_dev mfd */
 	rv = cros_ec_dev_init(client_data);
-	if (rv)
+	if (rv) {
+		down_write(&init_lock);
 		goto end_cros_ec_dev_init_error;
+	}
 
 	return 0;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/chrome/cros_ec_proto.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/chrome/cros_ec_proto.c
@@ -213,6 +213,15 @@
 	msg->insize = sizeof(struct ec_response_get_protocol_info);
 
 	ret = send_command(ec_dev, msg);
+	/*
+	 * Send command once again when timeout occurred.
+	 * Fingerprint MCU (FPMCU) is restarted during system boot which
+	 * introduces small window in which FPMCU won't respond for any
+	 * messages sent by kernel. There is no need to wait before next
+	 * attempt because we waited at least EC_MSG_DEADLINE_MS.
+	 */
+	if (ret == -ETIMEDOUT)
+		ret = send_command(ec_dev, msg);
 
 	if (ret < 0) {
 		dev_dbg(ec_dev->dev,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/chrome/cros_ec_rpmsg.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/chrome/cros_ec_rpmsg.c
@@ -42,6 +42,8 @@
 	struct completion xfer_ack;
 	struct work_struct host_event_work;
 	struct rpmsg_endpoint *ept;
+	bool has_pending_host_event;
+	bool probe_done;
 };
 
 /**
@@ -186,7 +188,14 @@
 		memcpy(ec_dev->din, resp->data, len);
 		complete(&ec_rpmsg->xfer_ack);
 	} else if (resp->type == HOST_EVENT_MARK) {
-		schedule_work(&ec_rpmsg->host_event_work);
+		/*
+		 * If the host event is sent before cros_ec_register is
+		 * finished, queue the host event.
+		 */
+		if (ec_rpmsg->probe_done)
+			schedule_work(&ec_rpmsg->host_event_work);
+		else
+			ec_rpmsg->has_pending_host_event = true;
 	} else {
 		dev_warn(ec_dev->dev, "rpmsg received invalid type = %d",
 			 resp->type);
@@ -249,6 +258,11 @@
 		return ret;
 	}
 
+	ec_rpmsg->probe_done = true;
+
+	if (ec_rpmsg->has_pending_host_event)
+		schedule_work(&ec_rpmsg->host_event_work);
+
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/chrome/cros_ec_spi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/chrome/cros_ec_spi.c
@@ -739,7 +739,6 @@
 	int err;
 
 	spi->bits_per_word = 8;
-	spi->mode = SPI_MODE_0;
 	spi->rt = true;
 	err = spi_setup(spi);
 	if (err < 0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/chrome/wilco_ec/telemetry.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/chrome/wilco_ec/telemetry.c
@@ -406,8 +406,8 @@
 	struct telem_device_data *dev_data = platform_get_drvdata(pdev);
 
 	cdev_device_del(&dev_data->cdev, &dev_data->dev);
-	put_device(&dev_data->dev);
 	ida_simple_remove(&telem_ida, MINOR(dev_data->dev.devt));
+	put_device(&dev_data->dev);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/mellanox/mlxbf-tmfifo.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/mellanox/mlxbf-tmfifo.c
@@ -56,6 +56,7 @@
  * @vq: pointer to the virtio virtqueue
  * @desc: current descriptor of the pending packet
  * @desc_head: head descriptor of the pending packet
+ * @drop_desc: dummy desc for packet dropping
  * @cur_len: processed length of the current descriptor
  * @rem_len: remaining length of the pending packet
  * @pkt_len: total length of the pending packet
@@ -72,6 +73,7 @@
 	struct virtqueue *vq;
 	struct vring_desc *desc;
 	struct vring_desc *desc_head;
+	struct vring_desc drop_desc;
 	int cur_len;
 	int rem_len;
 	u32 pkt_len;
@@ -83,6 +85,14 @@
 	struct mlxbf_tmfifo *fifo;
 };
 
+/* Check whether vring is in drop mode. */
+#define IS_VRING_DROP(_r) ({ \
+	typeof(_r) (r) = (_r); \
+	(r->desc_head == &r->drop_desc ? true : false); })
+
+/* A stub length to drop maximum length packet. */
+#define VRING_DROP_DESC_MAX_LEN		GENMASK(15, 0)
+
 /* Interrupt types. */
 enum {
 	MLXBF_TM_RX_LWM_IRQ,
@@ -149,7 +159,7 @@
  * @work: work struct for deferred process
  * @timer: background timer
  * @vring: Tx/Rx ring
- * @spin_lock: spin lock
+ * @spin_lock: Tx/Rx spin lock
  * @is_ready: ready flag
  */
 struct mlxbf_tmfifo {
@@ -164,7 +174,7 @@
 	struct work_struct work;
 	struct timer_list timer;
 	struct mlxbf_tmfifo_vring *vring[2];
-	spinlock_t spin_lock;		/* spin lock */
+	spinlock_t spin_lock[2];	/* spin lock */
 	bool is_ready;
 };
 
@@ -195,7 +205,7 @@
 static efi_char16_t mlxbf_tmfifo_efi_name[] = L"RshimMacAddr";
 
 /* Maximum L2 header length. */
-#define MLXBF_TMFIFO_NET_L2_OVERHEAD	36
+#define MLXBF_TMFIFO_NET_L2_OVERHEAD	(ETH_HLEN + VLAN_HLEN)
 
 /* Supported virtio-net features. */
 #define MLXBF_TMFIFO_NET_FEATURES \
@@ -243,6 +253,7 @@
 		vring->align = SMP_CACHE_BYTES;
 		vring->index = i;
 		vring->vdev_id = tm_vdev->vdev.id.device;
+		vring->drop_desc.len = VRING_DROP_DESC_MAX_LEN;
 		dev = &tm_vdev->vdev.dev;
 
 		size = vring_size(vring->num, vring->align);
@@ -294,6 +305,9 @@
 	if (vring->next_avail == virtio16_to_cpu(vdev, vr->avail->idx))
 		return NULL;
 
+	/* Make sure 'avail->idx' is visible already. */
+	virtio_rmb(false);
+
 	idx = vring->next_avail % vr->num;
 	head = virtio16_to_cpu(vdev, vr->avail->ring[idx]);
 	if (WARN_ON(head >= vr->num))
@@ -322,7 +336,7 @@
 	 * done or not. Add a memory barrier here to make sure the update above
 	 * completes before updating the idx.
 	 */
-	mb();
+	virtio_mb(false);
 	vr->used->idx = cpu_to_virtio16(vdev, vr_idx + 1);
 }
 
@@ -345,7 +359,7 @@
 	return len;
 }
 
-static void mlxbf_tmfifo_release_pending_pkt(struct mlxbf_tmfifo_vring *vring)
+static void mlxbf_tmfifo_release_pkt(struct mlxbf_tmfifo_vring *vring)
 {
 	struct vring_desc *desc_head;
 	u32 len = 0;
@@ -525,7 +539,7 @@
 	writeq(*(u64 *)&hdr, fifo->tx_base + MLXBF_TMFIFO_TX_DATA);
 
 	/* Use spin-lock to protect the 'cons->tx_buf'. */
-	spin_lock_irqsave(&fifo->spin_lock, flags);
+	spin_lock_irqsave(&fifo->spin_lock[0], flags);
 
 	while (size > 0) {
 		addr = cons->tx_buf.buf + cons->tx_buf.tail;
@@ -552,7 +566,7 @@
 		}
 	}
 
-	spin_unlock_irqrestore(&fifo->spin_lock, flags);
+	spin_unlock_irqrestore(&fifo->spin_lock[0], flags);
 }
 
 /* Rx/Tx one word in the descriptor buffer. */
@@ -574,19 +588,26 @@
 
 	if (vring->cur_len + sizeof(u64) <= len) {
 		/* The whole word. */
-		if (is_rx)
-			memcpy(addr + vring->cur_len, &data, sizeof(u64));
-		else
-			memcpy(&data, addr + vring->cur_len, sizeof(u64));
+		if (is_rx) {
+			if (!IS_VRING_DROP(vring))
+				memcpy(addr + vring->cur_len, &data,
+				       sizeof(u64));
+		} else {
+			memcpy(&data, addr + vring->cur_len,
+			       sizeof(u64));
+		}
 		vring->cur_len += sizeof(u64);
 	} else {
 		/* Leftover bytes. */
-		if (is_rx)
-			memcpy(addr + vring->cur_len, &data,
-			       len - vring->cur_len);
-		else
+		if (is_rx) {
+			if (!IS_VRING_DROP(vring))
+				memcpy(addr + vring->cur_len, &data,
+				       len - vring->cur_len);
+		} else {
+			data = 0;
 			memcpy(&data, addr + vring->cur_len,
 			       len - vring->cur_len);
+		}
 		vring->cur_len = len;
 	}
 
@@ -603,13 +624,14 @@
  * flag is set.
  */
 static void mlxbf_tmfifo_rxtx_header(struct mlxbf_tmfifo_vring *vring,
-				     struct vring_desc *desc,
+				     struct vring_desc **desc,
 				     bool is_rx, bool *vring_change)
 {
 	struct mlxbf_tmfifo *fifo = vring->fifo;
 	struct virtio_net_config *config;
 	struct mlxbf_tmfifo_msg_hdr hdr;
 	int vdev_id, hdr_len;
+	bool drop_rx = false;
 
 	/* Read/Write packet header. */
 	if (is_rx) {
@@ -625,9 +647,12 @@
 			vdev_id = VIRTIO_ID_NET;
 			hdr_len = sizeof(struct virtio_net_hdr);
 			config = &fifo->vdev[vdev_id]->config.net;
-			if (ntohs(hdr.len) > config->mtu +
-			    MLXBF_TMFIFO_NET_L2_OVERHEAD)
-				return;
+			/* A legacy-only interface for now. */
+			if (ntohs(hdr.len) >
+			    __virtio16_to_cpu(virtio_legacy_is_little_endian(),
+					      config->mtu) +
+					      MLXBF_TMFIFO_NET_L2_OVERHEAD)
+				drop_rx = true;
 		} else {
 			vdev_id = VIRTIO_ID_CONSOLE;
 			hdr_len = 0;
@@ -642,16 +667,25 @@
 
 			if (!tm_dev2)
 				return;
-			vring->desc = desc;
+			vring->desc = *desc;
 			vring = &tm_dev2->vrings[MLXBF_TMFIFO_VRING_RX];
 			*vring_change = true;
 		}
+
+		if (drop_rx && !IS_VRING_DROP(vring)) {
+			if (vring->desc_head)
+				mlxbf_tmfifo_release_pkt(vring);
+			*desc = &vring->drop_desc;
+			vring->desc_head = *desc;
+			vring->desc = *desc;
+		}
+
 		vring->pkt_len = ntohs(hdr.len) + hdr_len;
 	} else {
 		/* Network virtio has an extra header. */
 		hdr_len = (vring->vdev_id == VIRTIO_ID_NET) ?
 			   sizeof(struct virtio_net_hdr) : 0;
-		vring->pkt_len = mlxbf_tmfifo_get_pkt_len(vring, desc);
+		vring->pkt_len = mlxbf_tmfifo_get_pkt_len(vring, *desc);
 		hdr.type = (vring->vdev_id == VIRTIO_ID_NET) ?
 			    VIRTIO_ID_NET : VIRTIO_ID_CONSOLE;
 		hdr.len = htons(vring->pkt_len - hdr_len);
@@ -684,15 +718,23 @@
 	/* Get the descriptor of the next packet. */
 	if (!vring->desc) {
 		desc = mlxbf_tmfifo_get_next_pkt(vring, is_rx);
-		if (!desc)
-			return false;
+		if (!desc) {
+			/* Drop next Rx packet to avoid stuck. */
+			if (is_rx) {
+				desc = &vring->drop_desc;
+				vring->desc_head = desc;
+				vring->desc = desc;
+			} else {
+				return false;
+			}
+		}
 	} else {
 		desc = vring->desc;
 	}
 
 	/* Beginning of a packet. Start to Rx/Tx packet header. */
 	if (vring->pkt_len == 0) {
-		mlxbf_tmfifo_rxtx_header(vring, desc, is_rx, &vring_change);
+		mlxbf_tmfifo_rxtx_header(vring, &desc, is_rx, &vring_change);
 		(*avail)--;
 
 		/* Return if new packet is for another ring. */
@@ -718,22 +760,35 @@
 		vring->rem_len -= len;
 
 		/* Get the next desc on the chain. */
-		if (vring->rem_len > 0 &&
+		if (!IS_VRING_DROP(vring) && vring->rem_len > 0 &&
 		    (virtio16_to_cpu(vdev, desc->flags) & VRING_DESC_F_NEXT)) {
 			idx = virtio16_to_cpu(vdev, desc->next);
 			desc = &vr->desc[idx];
 			goto mlxbf_tmfifo_desc_done;
 		}
 
-		/* Done and release the pending packet. */
-		mlxbf_tmfifo_release_pending_pkt(vring);
+		/* Done and release the packet. */
 		desc = NULL;
 		fifo->vring[is_rx] = NULL;
+		if (!IS_VRING_DROP(vring)) {
+			mlxbf_tmfifo_release_pkt(vring);
+		} else {
+			vring->pkt_len = 0;
+			vring->desc_head = NULL;
+			vring->desc = NULL;
+			return false;
+		}
+
+		/*
+		 * Make sure the load/store are in order before
+		 * returning back to virtio.
+		 */
+		virtio_mb(false);
 
 		/* Notify upper layer that packet is done. */
-		spin_lock_irqsave(&fifo->spin_lock, flags);
+		spin_lock_irqsave(&fifo->spin_lock[is_rx], flags);
 		vring_interrupt(0, vring->vq);
-		spin_unlock_irqrestore(&fifo->spin_lock, flags);
+		spin_unlock_irqrestore(&fifo->spin_lock[is_rx], flags);
 	}
 
 mlxbf_tmfifo_desc_done:
@@ -852,10 +907,11 @@
 		 * worker handler.
 		 */
 		if (vring->vdev_id == VIRTIO_ID_CONSOLE) {
-			spin_lock_irqsave(&fifo->spin_lock, flags);
+			spin_lock_irqsave(&fifo->spin_lock[0], flags);
 			tm_vdev = fifo->vdev[VIRTIO_ID_CONSOLE];
 			mlxbf_tmfifo_console_output(tm_vdev, vring);
-			spin_unlock_irqrestore(&fifo->spin_lock, flags);
+			spin_unlock_irqrestore(&fifo->spin_lock[0], flags);
+			set_bit(MLXBF_TM_TX_LWM_IRQ, &fifo->pend_events);
 		} else if (test_and_set_bit(MLXBF_TM_TX_LWM_IRQ,
 					    &fifo->pend_events)) {
 			return true;
@@ -901,7 +957,7 @@
 
 		/* Release the pending packet. */
 		if (vring->desc)
-			mlxbf_tmfifo_release_pending_pkt(vring);
+			mlxbf_tmfifo_release_pkt(vring);
 		vq = vring->vq;
 		if (vq) {
 			vring->vq = NULL;
@@ -1189,7 +1245,8 @@
 	if (!fifo)
 		return -ENOMEM;
 
-	spin_lock_init(&fifo->spin_lock);
+	spin_lock_init(&fifo->spin_lock[0]);
+	spin_lock_init(&fifo->spin_lock[1]);
 	INIT_WORK(&fifo->work, mlxbf_tmfifo_work_handler);
 	mutex_init(&fifo->lock);
 
@@ -1230,8 +1287,12 @@
 
 	/* Create the network vdev. */
 	memset(&net_config, 0, sizeof(net_config));
-	net_config.mtu = ETH_DATA_LEN;
-	net_config.status = VIRTIO_NET_S_LINK_UP;
+
+	/* A legacy-only interface for now. */
+	net_config.mtu = __cpu_to_virtio16(virtio_legacy_is_little_endian(),
+					   ETH_DATA_LEN);
+	net_config.status = __cpu_to_virtio16(virtio_legacy_is_little_endian(),
+					      VIRTIO_NET_S_LINK_UP);
 	mlxbf_tmfifo_get_cfg_mac(net_config.mac);
 	rc = mlxbf_tmfifo_create_vdev(dev, fifo, VIRTIO_ID_NET,
 				      MLXBF_TMFIFO_NET_FEATURES, &net_config,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/mellanox/mlxreg-io.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/mellanox/mlxreg-io.c
@@ -123,7 +123,7 @@
 		return -EINVAL;
 
 	/* Convert buffer to input value. */
-	ret = kstrtou32(buf, len, &input_val);
+	ret = kstrtou32(buf, 0, &input_val);
 	if (ret)
 		return ret;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/mips/cpu_hwmon.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/mips/cpu_hwmon.c
@@ -161,11 +161,14 @@
 
 	cpu_hwmon_dev = hwmon_device_register(NULL);
 	if (IS_ERR(cpu_hwmon_dev)) {
-		ret = -ENOMEM;
+		ret = PTR_ERR(cpu_hwmon_dev);
 		pr_err("hwmon_device_register fail!\n");
 		goto fail_hwmon_device_register;
 	}
 
+	if (!csr_temp_enable && !loongson_chiptemp[0])
+		return -ENODEV;
+
 	nr_packages = loongson_sysconf.nr_cpus /
 		loongson_sysconf.cores_per_package;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/olpc/olpc-ec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/olpc/olpc-ec.c
@@ -265,7 +265,7 @@
 	int i, m;
 	unsigned char ec_cmd[EC_MAX_CMD_ARGS];
 	unsigned int ec_cmd_int[EC_MAX_CMD_ARGS];
-	char cmdbuf[64];
+	char cmdbuf[64] = "";
 	int ec_cmd_bytes;
 
 	mutex_lock(&ec_dbgfs_lock);
@@ -426,11 +426,8 @@
 
 	/* get the EC revision */
 	err = olpc_ec_cmd(EC_FIRMWARE_REV, NULL, 0, &ec->version, 1);
-	if (err) {
-		ec_priv = NULL;
-		kfree(ec);
-		return err;
-	}
+	if (err)
+		goto error;
 
 	config.dev = pdev->dev.parent;
 	config.driver_data = ec;
@@ -439,11 +436,17 @@
 								&config);
 	if (IS_ERR(ec->dcon_rdev)) {
 		dev_err(&pdev->dev, "failed to register DCON regulator\n");
-		return PTR_ERR(ec->dcon_rdev);
+		err = PTR_ERR(ec->dcon_rdev);
+		goto error;
 	}
 
 	ec->dbgfs_dir = olpc_ec_setup_debugfs();
 
+	return 0;
+
+error:
+	ec_priv = NULL;
+	kfree(ec);
 	return err;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/Kconfig
@@ -261,6 +261,20 @@
 	 image for the image update to take effect.
 	 See <file:Documentation/driver-api/dell_rbu.rst> for more details on the driver.
 
+config DELL_UART_BACKLIGHT
+	tristate "Dell AIO UART Backlight driver"
+	depends on SERIAL_8250
+	depends on ACPI
+	---help---
+	  Say Y here if you want to support Dell AIO UART backlight interface.
+	  The Dell AIO machines released after 2017 come with a UART interface
+	  to communicate with the backlight scalar board. This driver creates
+	  a standard backlight interface and talks to the scalar board through
+	  UART to adjust the AIO screen brightness.
+
+	  To compile this driver as a module, choose M here: the module will
+	  be called dell_uart_backlight.
+
 
 config FUJITSU_LAPTOP
 	tristate "Fujitsu Laptop Extras"
@@ -269,6 +283,7 @@
 	depends on BACKLIGHT_CLASS_DEVICE
 	depends on ACPI_VIDEO || ACPI_VIDEO = n
 	select INPUT_SPARSEKMAP
+	select NEW_LEDS
 	select LEDS_CLASS
 	---help---
 	  This is a driver for laptops built by Fujitsu:
@@ -806,7 +821,6 @@
 	tristate "PEAQ 2-in-1 WMI hotkey driver"
 	depends on ACPI_WMI
 	depends on INPUT
-	select INPUT_POLLDEV
 	help
 	 Say Y here if you want to support WMI-based hotkeys on PEAQ 2-in-1s.
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/Makefile
@@ -26,6 +26,7 @@
 obj-$(CONFIG_DELL_SMO8800)	+= dell-smo8800.o
 obj-$(CONFIG_DELL_RBTN)		+= dell-rbtn.o
 obj-$(CONFIG_DELL_RBU)          += dell_rbu.o
+obj-$(CONFIG_DELL_UART_BACKLIGHT) += dell-uart-backlight.o
 obj-$(CONFIG_ACER_WMI)		+= acer-wmi.o
 obj-$(CONFIG_ACER_WIRELESS)	+= acer-wireless.o
 obj-$(CONFIG_ACERHDF)		+= acerhdf.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/acer-wmi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/acer-wmi.c
@@ -30,6 +30,7 @@
 #include <linux/input/sparse-keymap.h>
 #include <acpi/video.h>
 
+ACPI_MODULE_NAME(KBUILD_MODNAME);
 MODULE_AUTHOR("Carlos Corbacho");
 MODULE_DESCRIPTION("Acer Laptop WMI Extras Driver");
 MODULE_LICENSE("GPL");
@@ -80,7 +81,7 @@
 
 enum acer_wmi_event_ids {
 	WMID_HOTKEY_EVENT = 0x1,
-	WMID_ACCEL_EVENT = 0x5,
+	WMID_ACCEL_OR_KBD_DOCK_EVENT = 0x5,
 };
 
 static const struct key_entry acer_wmi_keymap[] __initconst = {
@@ -92,6 +93,7 @@
 	{KE_KEY, 0x22, {KEY_PROG2} },    /* Arcade */
 	{KE_KEY, 0x23, {KEY_PROG3} },    /* P_Key */
 	{KE_KEY, 0x24, {KEY_PROG4} },    /* Social networking_Key */
+	{KE_KEY, 0x27, {KEY_HELP} },
 	{KE_KEY, 0x29, {KEY_PROG3} },    /* P_Key for TM8372 */
 	{KE_IGNORE, 0x41, {KEY_MUTE} },
 	{KE_IGNORE, 0x42, {KEY_PREVIOUSSONG} },
@@ -105,12 +107,19 @@
 	{KE_IGNORE, 0x48, {KEY_VOLUMEUP} },
 	{KE_IGNORE, 0x49, {KEY_VOLUMEDOWN} },
 	{KE_IGNORE, 0x4a, {KEY_VOLUMEDOWN} },
-	{KE_IGNORE, 0x61, {KEY_SWITCHVIDEOMODE} },
+	/*
+	 * 0x61 is KEY_SWITCHVIDEOMODE. Usually this is a duplicate input event
+	 * with the "Video Bus" input device events. But sometimes it is not
+	 * a dup. Map it to KEY_UNKNOWN instead of using KE_IGNORE so that
+	 * udev/hwdb can override it on systems where it is not a dup.
+	 */
+	{KE_KEY, 0x61, {KEY_UNKNOWN} },
 	{KE_IGNORE, 0x62, {KEY_BRIGHTNESSUP} },
 	{KE_IGNORE, 0x63, {KEY_BRIGHTNESSDOWN} },
 	{KE_KEY, 0x64, {KEY_SWITCHVIDEOMODE} },	/* Display Switch */
 	{KE_IGNORE, 0x81, {KEY_SLEEP} },
 	{KE_KEY, 0x82, {KEY_TOUCHPAD_TOGGLE} },	/* Touch Pad Toggle */
+	{KE_IGNORE, 0x84, {KEY_KBDILLUMTOGGLE} }, /* Automatic Keyboard background light toggle */
 	{KE_KEY, KEY_TOUCHPAD_ON, {KEY_TOUCHPAD_ON} },
 	{KE_KEY, KEY_TOUCHPAD_OFF, {KEY_TOUCHPAD_OFF} },
 	{KE_IGNORE, 0x83, {KEY_TOUCHPAD_TOGGLE} },
@@ -127,7 +136,9 @@
 	u8 function;
 	u8 key_num;
 	u16 device_state;
-	u32 reserved;
+	u16 reserved1;
+	u8 kbd_dock_state;
+	u8 reserved2;
 } __attribute__((packed));
 
 /*
@@ -205,14 +216,13 @@
 /*
  * Interface capability flags
  */
-#define ACER_CAP_MAILLED		(1<<0)
-#define ACER_CAP_WIRELESS		(1<<1)
-#define ACER_CAP_BLUETOOTH		(1<<2)
-#define ACER_CAP_BRIGHTNESS		(1<<3)
-#define ACER_CAP_THREEG			(1<<4)
-#define ACER_CAP_ACCEL			(1<<5)
-#define ACER_CAP_RFBTN			(1<<6)
-#define ACER_CAP_ANY			(0xFFFFFFFF)
+#define ACER_CAP_MAILLED		BIT(0)
+#define ACER_CAP_WIRELESS		BIT(1)
+#define ACER_CAP_BLUETOOTH		BIT(2)
+#define ACER_CAP_BRIGHTNESS		BIT(3)
+#define ACER_CAP_THREEG			BIT(4)
+#define ACER_CAP_SET_FUNCTION_MODE	BIT(5)
+#define ACER_CAP_KBD_DOCK		BIT(6)
 
 /*
  * Interface type flags
@@ -235,6 +245,7 @@
 static int brightness = -1;
 static int threeg = -1;
 static int force_series;
+static int force_caps = -1;
 static bool ec_raw_mode;
 static bool has_type_aa;
 static u16 commun_func_bitmap;
@@ -244,11 +255,13 @@
 module_param(brightness, int, 0444);
 module_param(threeg, int, 0444);
 module_param(force_series, int, 0444);
+module_param(force_caps, int, 0444);
 module_param(ec_raw_mode, bool, 0444);
 MODULE_PARM_DESC(mailled, "Set initial state of Mail LED");
 MODULE_PARM_DESC(brightness, "Set initial LCD backlight brightness");
 MODULE_PARM_DESC(threeg, "Set initial state of 3G hardware");
 MODULE_PARM_DESC(force_series, "Force a different laptop series");
+MODULE_PARM_DESC(force_caps, "Force the capability bitmask to this value");
 MODULE_PARM_DESC(ec_raw_mode, "Enable EC raw mode");
 
 struct acer_data {
@@ -318,6 +331,15 @@
 	return 1;
 }
 
+static int __init set_force_caps(const struct dmi_system_id *dmi)
+{
+	if (force_caps == -1) {
+		force_caps = (uintptr_t)dmi->driver_data;
+		pr_info("Found %s, set force_caps to 0x%x\n", dmi->ident, force_caps);
+	}
+	return 1;
+}
+
 static struct quirk_entry quirk_unknown = {
 };
 
@@ -496,6 +518,42 @@
 		},
 		.driver_data = &quirk_acer_travelmate_2490,
 	},
+	{
+		.callback = set_force_caps,
+		.ident = "Acer Aspire Switch 10E SW3-016",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW3-016"),
+		},
+		.driver_data = (void *)ACER_CAP_KBD_DOCK,
+	},
+	{
+		.callback = set_force_caps,
+		.ident = "Acer Aspire Switch 10 SW5-012",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW5-012"),
+		},
+		.driver_data = (void *)ACER_CAP_KBD_DOCK,
+	},
+	{
+		.callback = set_force_caps,
+		.ident = "Acer Aspire Switch V 10 SW5-017",
+		.matches = {
+			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "SW5-017"),
+		},
+		.driver_data = (void *)ACER_CAP_KBD_DOCK,
+	},
+	{
+		.callback = set_force_caps,
+		.ident = "Acer One 10 (S1003)",
+		.matches = {
+			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "One S1003"),
+		},
+		.driver_data = (void *)ACER_CAP_KBD_DOCK,
+	},
 	{}
 };
 
@@ -1252,10 +1310,8 @@
 		interface->capability |= ACER_CAP_THREEG;
 	if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_BLUETOOTH)
 		interface->capability |= ACER_CAP_BLUETOOTH;
-	if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_RFBTN) {
-		interface->capability |= ACER_CAP_RFBTN;
+	if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_RFBTN)
 		commun_func_bitmap &= ~ACER_WMID3_GDS_RFBTN;
-	}
 
 	commun_fn_key_number = type_aa->commun_fn_key_number;
 }
@@ -1519,7 +1575,7 @@
 	struct acpi_buffer output;
 	union acpi_object out_obj[5];
 
-	if (!has_cap(ACER_CAP_ACCEL))
+	if (!acer_wmi_accel_dev)
 		return -1;
 
 	output.length = sizeof(out_obj);
@@ -1543,6 +1599,71 @@
 }
 
 /*
+ * Switch series keyboard dock status
+ */
+static int acer_kbd_dock_state_to_sw_tablet_mode(u8 kbd_dock_state)
+{
+	switch (kbd_dock_state) {
+	case 0x01: /* Docked, traditional clamshell laptop mode */
+		return 0;
+	case 0x04: /* Stand-alone tablet */
+	case 0x40: /* Docked, tent mode, keyboard not usable */
+		return 1;
+	default:
+		pr_warn("Unknown kbd_dock_state 0x%02x\n", kbd_dock_state);
+	}
+
+	return 0;
+}
+
+static void acer_kbd_dock_get_initial_state(void)
+{
+	u8 *output, input[8] = { 0x05, 0x00, };
+	struct acpi_buffer input_buf = { sizeof(input), input };
+	struct acpi_buffer output_buf = { ACPI_ALLOCATE_BUFFER, NULL };
+	union acpi_object *obj;
+	acpi_status status;
+	int sw_tablet_mode;
+
+	status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input_buf, &output_buf);
+	if (ACPI_FAILURE(status)) {
+		ACPI_EXCEPTION((AE_INFO, status, "Error getting keyboard-dock initial status"));
+		return;
+	}
+
+	obj = output_buf.pointer;
+	if (!obj || obj->type != ACPI_TYPE_BUFFER || obj->buffer.length != 8) {
+		pr_err("Unexpected output format getting keyboard-dock initial status\n");
+		goto out_free_obj;
+	}
+
+	output = obj->buffer.pointer;
+	if (output[0] != 0x00 || (output[3] != 0x05 && output[3] != 0x45)) {
+		pr_err("Unexpected output [0]=0x%02x [3]=0x%02x getting keyboard-dock initial status\n",
+		       output[0], output[3]);
+		goto out_free_obj;
+	}
+
+	sw_tablet_mode = acer_kbd_dock_state_to_sw_tablet_mode(output[4]);
+	input_report_switch(acer_wmi_input_dev, SW_TABLET_MODE, sw_tablet_mode);
+
+out_free_obj:
+	kfree(obj);
+}
+
+static void acer_kbd_dock_event(const struct event_return_value *event)
+{
+	int sw_tablet_mode;
+
+	if (!has_cap(ACER_CAP_KBD_DOCK))
+		return;
+
+	sw_tablet_mode = acer_kbd_dock_state_to_sw_tablet_mode(event->kbd_dock_state);
+	input_report_switch(acer_wmi_input_dev, SW_TABLET_MODE, sw_tablet_mode);
+	input_sync(acer_wmi_input_dev);
+}
+
+/*
  * Rfkill devices
  */
 static void acer_rfkill_update(struct work_struct *ignored);
@@ -1769,8 +1890,9 @@
 			sparse_keymap_report_event(acer_wmi_input_dev, scancode, 1, true);
 		}
 		break;
-	case WMID_ACCEL_EVENT:
+	case WMID_ACCEL_OR_KBD_DOCK_EVENT:
 		acer_gsensor_event();
+		acer_kbd_dock_event(&return_value);
 		break;
 	default:
 		pr_warn("Unknown function number - %d - %d\n",
@@ -1893,8 +2015,6 @@
 	gsensor_handle = acpi_device_handle(adev);
 	acpi_dev_put(adev);
 
-	interface->capability |= ACER_CAP_ACCEL;
-
 	acer_wmi_accel_dev = input_allocate_device();
 	if (!acer_wmi_accel_dev)
 		return -ENOMEM;
@@ -1920,11 +2040,6 @@
 	return err;
 }
 
-static void acer_wmi_accel_destroy(void)
-{
-	input_unregister_device(acer_wmi_accel_dev);
-}
-
 static int __init acer_wmi_input_setup(void)
 {
 	acpi_status status;
@@ -1942,6 +2057,9 @@
 	if (err)
 		goto err_free_dev;
 
+	if (has_cap(ACER_CAP_KBD_DOCK))
+		input_set_capability(acer_wmi_input_dev, EV_SW, SW_TABLET_MODE);
+
 	status = wmi_install_notify_handler(ACERWMID_EVENT_GUID,
 						acer_wmi_notify, NULL);
 	if (ACPI_FAILURE(status)) {
@@ -1949,6 +2067,9 @@
 		goto err_free_dev;
 	}
 
+	if (has_cap(ACER_CAP_KBD_DOCK))
+		acer_kbd_dock_get_initial_state();
+
 	err = input_register_device(acer_wmi_input_dev);
 	if (err)
 		goto err_uninstall_notifier;
@@ -2079,7 +2200,7 @@
 	if (has_cap(ACER_CAP_BRIGHTNESS))
 		set_u32(data->brightness, ACER_CAP_BRIGHTNESS);
 
-	if (has_cap(ACER_CAP_ACCEL))
+	if (acer_wmi_accel_dev)
 		acer_gsensor_init();
 
 	return 0;
@@ -2180,7 +2301,7 @@
 		}
 		/* WMID always provides brightness methods */
 		interface->capability |= ACER_CAP_BRIGHTNESS;
-	} else if (!wmi_has_guid(WMID_GUID2) && interface && !has_type_aa) {
+	} else if (!wmi_has_guid(WMID_GUID2) && interface && !has_type_aa && force_caps == -1) {
 		pr_err("No WMID device detection method found\n");
 		return -ENODEV;
 	}
@@ -2210,7 +2331,14 @@
 	if (acpi_video_get_backlight_type() != acpi_backlight_vendor)
 		interface->capability &= ~ACER_CAP_BRIGHTNESS;
 
-	if (wmi_has_guid(WMID_GUID3)) {
+	if (wmi_has_guid(WMID_GUID3))
+		interface->capability |= ACER_CAP_SET_FUNCTION_MODE;
+
+	if (force_caps != -1)
+		interface->capability = force_caps;
+
+	if (wmi_has_guid(WMID_GUID3) &&
+	    (interface->capability & ACER_CAP_SET_FUNCTION_MODE)) {
 		if (ACPI_FAILURE(acer_wmi_enable_rf_button()))
 			pr_warn("Cannot enable RF Button Driver\n");
 
@@ -2269,8 +2397,8 @@
 error_platform_register:
 	if (wmi_has_guid(ACERWMID_EVENT_GUID))
 		acer_wmi_input_destroy();
-	if (has_cap(ACER_CAP_ACCEL))
-		acer_wmi_accel_destroy();
+	if (acer_wmi_accel_dev)
+		input_unregister_device(acer_wmi_accel_dev);
 
 	return err;
 }
@@ -2280,8 +2408,8 @@
 	if (wmi_has_guid(ACERWMID_EVENT_GUID))
 		acer_wmi_input_destroy();
 
-	if (has_cap(ACER_CAP_ACCEL))
-		acer_wmi_accel_destroy();
+	if (acer_wmi_accel_dev)
+		input_unregister_device(acer_wmi_accel_dev);
 
 	remove_debugfs();
 	platform_device_unregister(acer_platform_device);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/apple-gmux.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/apple-gmux.c
@@ -625,7 +625,7 @@
 	}
 
 	gmux_data->iostart = res->start;
-	gmux_data->iolen = res->end - res->start;
+	gmux_data->iolen = resource_size(res);
 
 	if (gmux_data->iolen < GMUX_MIN_IO_LEN) {
 		pr_err("gmux I/O region too small (%lu < %u)\n",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/asus-nb-wmi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/asus-nb-wmi.c
@@ -110,6 +110,16 @@
 	.wmi_force_als_set = true,
 };
 
+static struct quirk_entry quirk_asus_ga401i = {
+	.wmi_backlight_power = true,
+	.wmi_backlight_set_devstate = true,
+};
+
+static struct quirk_entry quirk_asus_ga502i = {
+	.wmi_backlight_power = true,
+	.wmi_backlight_set_devstate = true,
+};
+
 static int dmi_matched(const struct dmi_system_id *dmi)
 {
 	pr_info("Identified laptop model '%s'\n", dmi->ident);
@@ -411,6 +421,78 @@
 		},
 		.driver_data = &quirk_asus_forceals,
 	},
+	{
+		.callback = dmi_matched,
+		.ident = "ASUSTeK COMPUTER INC. GA401IH",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "GA401IH"),
+		},
+		.driver_data = &quirk_asus_ga401i,
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "ASUSTeK COMPUTER INC. GA401II",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "GA401II"),
+		},
+		.driver_data = &quirk_asus_ga401i,
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "ASUSTeK COMPUTER INC. GA401IU",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "GA401IU"),
+		},
+		.driver_data = &quirk_asus_ga401i,
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "ASUSTeK COMPUTER INC. GA401IV",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "GA401IV"),
+		},
+		.driver_data = &quirk_asus_ga401i,
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "ASUSTeK COMPUTER INC. GA401IVC",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "GA401IVC"),
+		},
+		.driver_data = &quirk_asus_ga401i,
+	},
+		{
+		.callback = dmi_matched,
+		.ident = "ASUSTeK COMPUTER INC. GA502II",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "GA502II"),
+		},
+		.driver_data = &quirk_asus_ga502i,
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "ASUSTeK COMPUTER INC. GA502IU",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "GA502IU"),
+		},
+		.driver_data = &quirk_asus_ga502i,
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "ASUSTeK COMPUTER INC. GA502IV",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "GA502IV"),
+		},
+		.driver_data = &quirk_asus_ga502i,
+	},
 	{},
 };
 
@@ -446,6 +528,7 @@
 	{ KE_KEY, 0x30, { KEY_VOLUMEUP } },
 	{ KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
 	{ KE_KEY, 0x32, { KEY_MUTE } },
+	{ KE_KEY, 0x33, { KEY_SCREENLOCK } },
 	{ KE_KEY, 0x35, { KEY_SCREENLOCK } },
 	{ KE_KEY, 0x40, { KEY_PREVIOUSSONG } },
 	{ KE_KEY, 0x41, { KEY_NEXTSONG } },
@@ -472,6 +555,7 @@
 	{ KE_KEY, 0x6B, { KEY_TOUCHPAD_TOGGLE } },
 	{ KE_IGNORE, 0x6E, },  /* Low Battery notification */
 	{ KE_KEY, 0x7a, { KEY_ALS_TOGGLE } }, /* Ambient Light Sensor Toggle */
+	{ KE_IGNORE, 0x7B, }, /* Charger connect/disconnect notification */
 	{ KE_KEY, 0x7c, { KEY_MICMUTE } },
 	{ KE_KEY, 0x7D, { KEY_BLUETOOTH } }, /* Bluetooth Enable */
 	{ KE_KEY, 0x7E, { KEY_BLUETOOTH } }, /* Bluetooth Disable */
@@ -497,9 +581,11 @@
 	{ KE_KEY, 0xA6, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + TV + HDMI */
 	{ KE_KEY, 0xA7, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + CRT + TV + HDMI */
 	{ KE_KEY, 0xB5, { KEY_CALC } },
+	{ KE_IGNORE, 0xC0, }, /* External display connect/disconnect notification */
 	{ KE_KEY, 0xC4, { KEY_KBDILLUMUP } },
 	{ KE_KEY, 0xC5, { KEY_KBDILLUMDOWN } },
 	{ KE_IGNORE, 0xC6, },  /* Ambient Light Sensor notification */
+	{ KE_IGNORE, 0xCF, },	/* AC mode */
 	{ KE_KEY, 0xFA, { KEY_PROG2 } },           /* Lid flip action */
 	{ KE_END, 0},
 };
@@ -514,9 +600,33 @@
 	.detect_quirks = asus_nb_wmi_quirks,
 };
 
+static const struct dmi_system_id asus_nb_wmi_blacklist[] __initconst = {
+	{
+		/*
+		 * asus-nb-wm adds no functionality. The T100TA has a detachable
+		 * USB kbd, so no hotkeys and it has no WMI rfkill; and loading
+		 * asus-nb-wm causes the camera LED to turn and _stay_ on.
+		 */
+		.matches = {
+			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TA"),
+		},
+	},
+	{
+		/* The Asus T200TA has the same issue as the T100TA */
+		.matches = {
+			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T200TA"),
+		},
+	},
+	{} /* Terminating entry */
+};
 
 static int __init asus_nb_wmi_init(void)
 {
+	if (dmi_check_system(asus_nb_wmi_blacklist))
+		return -ENODEV;
+
 	return asus_wmi_register_driver(&asus_nb_wmi_driver);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/asus-wmi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/asus-wmi.c
@@ -111,6 +111,8 @@
 	u32 arg0;
 	u32 arg1;
 	u32 arg2; /* At least TUF Gaming series uses 3 dword input buffer. */
+	u32 arg4;
+	u32 arg5;
 } __packed;
 
 /*
@@ -418,8 +420,12 @@
 {
 	/* The WMI method does not provide a way to specific a battery, so we
 	 * just assume it is the first battery.
+	 * Note: On some newer ASUS laptops (Zenbook UM431DA), the primary/first
+	 * battery is named BATT.
 	 */
-	if (strcmp(battery->desc->name, "BAT0") != 0)
+	if (strcmp(battery->desc->name, "BAT0") != 0 &&
+	    strcmp(battery->desc->name, "BAT1") != 0 &&
+	    strcmp(battery->desc->name, "BATT") != 0)
 		return -ENODEV;
 
 	if (device_create_file(&battery->dev,
@@ -512,13 +518,7 @@
 {
 	int ctrl_param = 0;
 
-	/*
-	 * bits 0-2: level
-	 * bit 7: light on/off
-	 */
-	if (asus->kbd_led_wk > 0)
-		ctrl_param = 0x80 | (asus->kbd_led_wk & 0x7F);
-
+	ctrl_param = 0x80 | (asus->kbd_led_wk & 0x7F);
 	asus_wmi_set_devstate(ASUS_WMI_DEVID_KBD_BACKLIGHT, ctrl_param, NULL);
 }
 
@@ -1195,6 +1195,8 @@
 	pci_write_config_dword(xhci_pdev, USB_INTEL_XUSB2PR,
 				cpu_to_le32(ports_available));
 
+	pci_dev_put(xhci_pdev);
+
 	pr_info("set USB_INTEL_XUSB2PR old: 0x%04x, new: 0x%04x\n",
 			orig_ports_available, ports_available);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/asus-wmi.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/asus-wmi.h
@@ -18,7 +18,7 @@
 #include <linux/i8042.h>
 
 #define ASUS_WMI_KEY_IGNORE (-1)
-#define ASUS_WMI_BRN_DOWN	0x20
+#define ASUS_WMI_BRN_DOWN	0x2e
 #define ASUS_WMI_BRN_UP		0x2f
 
 struct module;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/dell-laptop.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/dell-laptop.c
@@ -33,6 +33,7 @@
 
 struct quirk_entry {
 	bool touchpad_led;
+	bool kbd_led_not_present;
 	bool kbd_led_levels_off_1;
 	bool kbd_missing_ac_tag;
 
@@ -73,6 +74,10 @@
 	.kbd_led_levels_off_1 = true,
 };
 
+static struct quirk_entry quirk_dell_inspiron_1012 = {
+	.kbd_led_not_present = true,
+};
+
 static struct platform_driver platform_driver = {
 	.driver = {
 		.name = "dell-laptop",
@@ -310,6 +315,24 @@
 		},
 		.driver_data = &quirk_dell_latitude_e6410,
 	},
+	{
+		.callback = dmi_matched,
+		.ident = "Dell Inspiron 1012",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1012"),
+		},
+		.driver_data = &quirk_dell_inspiron_1012,
+	},
+	{
+		.callback = dmi_matched,
+		.ident = "Dell Inspiron 1018",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1018"),
+		},
+		.driver_data = &quirk_dell_inspiron_1012,
+	},
 	{ }
 };
 
@@ -1493,6 +1516,9 @@
 {
 	int ret;
 
+	if (quirks && quirks->kbd_led_not_present)
+		return;
+
 	ret = kbd_init_info();
 	kbd_init_tokens();
 
@@ -2178,10 +2204,13 @@
 
 	dell_laptop_register_notifier(&dell_laptop_notifier);
 
-	micmute_led_cdev.brightness = ledtrig_audio_get(LED_AUDIO_MICMUTE);
-	ret = led_classdev_register(&platform_device->dev, &micmute_led_cdev);
-	if (ret < 0)
-		goto fail_led;
+	if (dell_smbios_find_token(GLOBAL_MIC_MUTE_DISABLE) &&
+	    dell_smbios_find_token(GLOBAL_MIC_MUTE_ENABLE)) {
+		micmute_led_cdev.brightness = ledtrig_audio_get(LED_AUDIO_MICMUTE);
+		ret = led_classdev_register(&platform_device->dev, &micmute_led_cdev);
+		if (ret < 0)
+			goto fail_led;
+	}
 
 	if (acpi_video_get_backlight_type() != acpi_backlight_vendor)
 		return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/dell-smbios-base.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/dell-smbios-base.c
@@ -594,6 +594,7 @@
 	if (wmi && smm) {
 		pr_err("No SMBIOS backends available (wmi: %d, smm: %d)\n",
 			wmi, smm);
+		ret = -ENODEV;
 		goto fail_create_group;
 	}
 
@@ -609,7 +610,10 @@
 	return 0;
 
 fail_sysfs:
-	free_group(platform_device);
+	if (!wmi)
+		exit_dell_smbios_wmi();
+	if (!smm)
+		exit_dell_smbios_smm();
 
 fail_create_group:
 	platform_device_del(platform_device);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/dell-smbios-wmi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/dell-smbios-wmi.c
@@ -69,6 +69,7 @@
 		if (obj->type == ACPI_TYPE_INTEGER)
 			dev_dbg(&wdev->dev, "SMBIOS call failed: %llu\n",
 				obj->integer.value);
+		kfree(output.pointer);
 		return -EIO;
 	}
 	memcpy(&priv->buf->std, obj->buffer.pointer, obj->buffer.length);
@@ -271,7 +272,8 @@
 
 void exit_dell_smbios_wmi(void)
 {
-	wmi_driver_unregister(&dell_smbios_wmi_driver);
+	if (wmi_supported)
+		wmi_driver_unregister(&dell_smbios_wmi_driver);
 }
 
 MODULE_DEVICE_TABLE(wmi, dell_smbios_wmi_id_table);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/dell-uart-backlight.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/dell-uart-backlight.c
@@ -0,0 +1,530 @@
+/*
+ *  Dell AIO Serial Backlight Driver
+ *
+ *  Copyright (C) 2017 AceLan Kao <acelan.kao@canonical.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/acpi.h>
+#include <linux/serial_8250.h>
+#include <linux/delay.h>
+#include <linux/backlight.h>
+#include <linux/dmi.h>
+#include <acpi/video.h>
+
+#include "dell-uart-backlight.h"
+
+struct dell_uart_backlight {
+	struct device *dev;
+	struct backlight_device *dell_uart_bd;
+	struct mutex brightness_mutex;
+	int line;
+	int bl_power;
+};
+struct uart_8250_port *serial8250_get_port(int line);
+static struct tty_struct *tty;
+static struct file *ftty;
+
+unsigned int (*io_serial_in)(struct uart_port *p, int offset);
+int (*uart_write)(struct tty_struct *tty, const unsigned char *buf, int count);
+int (*uart_chars_in_buffer)(struct tty_struct *tty);
+
+static bool force;
+module_param(force, bool, 0444);
+MODULE_PARM_DESC(force, "load the driver regardless of the scalar status");
+
+static struct dell_uart_bl_cmd uart_cmd[] = {
+	/*
+	 * Get Firmware Version: Tool uses this command to get firmware version.
+	 * Command: 0x6A 0x06 0x8F (Length:3 Type: 0x0A, Cmd:6 Checksum:0x8F)
+	 * Return data: 0x0D 0x06 Data checksum (Length:13,Cmd:0x06,
+	 *              Data :F/W version(APRILIA=APR27-VXXX,PHINE=PHI23-VXXX),
+	 *              checksum:SUM(Length and Cmd and Data)xor 0xFF .
+	 */
+	[DELL_UART_GET_FIRMWARE_VER] = {
+		.cmd	= {0x6A, 0x06, 0x8F},
+		.tx_len	= 3,
+	},
+	/*
+	 * Get Scalar Status: Tool uses this command to check if scalar IC controls brightness.
+	 * Command: 0x6A 0x1F 0x8F (Length:3 Type: 0x0A, Cmd:0x1F Checksum:0x76)
+	 * Return data: 0x04 0x1F Data checksum
+	 * (Data = 0: scalar cannot adjust brightness, Data = 1: scalar can adjust brightness)
+	 */
+	[DELL_UART_GET_SCALAR] = {
+		.cmd	= {0x6A,0x1F,0x76},
+		.ret	= {0x04,0x1F,0x00,0x00},
+		.tx_len	= 3,
+		.rx_len	= 4,
+	},
+	/*
+	 * Get Brightness level: Application uses this command for scaler to
+	 *                       get brightness.
+	 * Command: 0x6A 0x0C 0x89
+	 *          (Length:3 Type: 0x0A, Cmd:0x0C, Checksum:0x89)
+	 * Return data: 0x04 0x0C Data checksum
+	 * (Length:4 Cmd: 0x0C Data: brightness level
+	 *           checksum: SUM(Length and Cmd and Data)xor 0xFF)
+	 *           brightness level which ranges from 0~100.
+	 */
+	[DELL_UART_GET_BRIGHTNESS] = {
+		.cmd	= {0x6A, 0x0C, 0x89},
+		.ret	= {0x04, 0x0C, 0x00, 0x00},
+		.tx_len	= 3,
+		.rx_len	= 4,
+	},
+	/* Set Brightness level: Application uses this command for scaler to
+	 *                       set brightness.
+	 * Command: 0x8A 0x0B Byte2 Checksum (Length:4 Type: 0x0A, Cmd:0x0B)
+	 *          where Byte2 is the brightness level which ranges from 0~100.
+	 * Return data: 0x03 0x0B 0xF1(Length:3,Cmd:B,checksum:0xF1)
+	 * Scaler must send the 3bytes ack within 1 second when success,
+	 * other value if error
+	 */
+	[DELL_UART_SET_BRIGHTNESS] = {
+		.cmd	= {0x8A, 0x0B, 0x0, 0x0},
+		.ret	= {0x03, 0x0B, 0xF1},
+		.tx_len	= 4,
+		.rx_len	= 3,
+	},
+	/*
+	 * Screen ON/OFF Control: Application uses this command to control
+	 *                        screen ON or OFF.
+	 * Command: 0x8A 0x0E Byte2 Checksum (Length:4 Type: 0x0A, Cmd:0x0E)
+	 *          where
+	 *          Byte2=0 to turn OFF the screen.
+	 *          Byte2=1 to turn ON the screen
+	 *          Other value of Byte2 is reserved and invalid.
+	 * Return data: 0x03 0x0E 0xEE(Length:3,Cmd:E,checksum:0xEE)
+	 */
+	[DELL_UART_SET_BACKLIGHT_POWER] = {
+		.cmd	= {0x8A, 0x0E, 0x00, 0x0},
+		.ret	= {0x03, 0x0E, 0xEE},
+		.tx_len	= 4,
+		.rx_len	= 3,
+	},
+};
+
+static const struct dmi_system_id dell_uart_backlight_alpha_platform[] __initconst = {
+	{
+		.ident = "Dell Inspiron 7777 AIO",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7777 AIO"),
+		},
+	},
+	{
+		.ident = "Dell Inspiron 5477 AIO",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5477 AIO"),
+		},
+	},
+	{
+		.ident = "Dell OptiPlex 7769 AIO",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 7769 AIO"),
+		},
+	},
+	{
+		.ident = "Dell OptiPlex 5260 AIO",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 5260 AIO"),
+		},
+	},
+	{ }
+};
+
+static int dell_uart_write(struct uart_8250_port *up, __u8 *buf, int len)
+{
+	int actual = 0;
+	struct uart_port *port = &up->port;
+
+	tty_port_tty_wakeup(&port->state->port);
+	tty = tty_port_tty_get(&port->state->port);
+	actual = uart_write(tty, buf, len);
+	while (uart_chars_in_buffer(tty))
+		udelay(10);
+
+	return actual;
+}
+
+static int dell_uart_read(struct uart_8250_port *up, __u8 *buf, int len)
+{
+	int i, retry;
+	unsigned long flags;
+
+	spin_lock_irqsave(&up->port.lock, flags);
+	for (i = 0; i < len; i++) {
+		retry = 10;
+		while (!(io_serial_in(&up->port, UART_LSR) & UART_LSR_DR)) {
+			if (--retry == 0)
+				break;
+			mdelay(20);
+		}
+
+		if (retry == 0)
+			break;
+		buf[i] = io_serial_in(&up->port, UART_RX);
+	}
+	spin_unlock_irqrestore(&up->port.lock, flags);
+
+	return i;
+}
+
+static void dell_uart_dump_cmd(const char *func, const char *prefix,
+			       const char *cmd, int len)
+{
+	char buf[80];
+
+	snprintf(buf, 80, "dell_uart_backlight:%s:%s", func, prefix);
+	if (len != 0)
+		print_hex_dump_debug(buf, DUMP_PREFIX_NONE,
+					16, 1, cmd, len, false);
+	else
+		pr_debug("dell_uart_backlight:%s:%sNULL\n", func, prefix);
+
+}
+
+/*
+ * checksum: SUM(Length and Cmd and Data)xor 0xFF)
+ */
+static unsigned char dell_uart_checksum(unsigned char *buf, int len)
+{
+	unsigned char val = 0;
+
+	while (len-- > 0)
+		val += buf[len];
+
+	return val ^ 0xff;
+}
+
+/*
+ * There is no command to get backlight power status,
+ * so we set the backlight power to "on" while initializing,
+ * and then track and report its status by bl_power variable
+ */
+static inline int dell_uart_get_bl_power(struct dell_uart_backlight *dell_pdata)
+{
+	return dell_pdata->bl_power;
+}
+
+static int dell_uart_set_bl_power(struct backlight_device *bd, int power)
+{
+	struct dell_uart_bl_cmd *bl_cmd =
+		&uart_cmd[DELL_UART_SET_BACKLIGHT_POWER];
+	struct dell_uart_backlight *dell_pdata = bl_get_data(bd);
+	struct uart_8250_port *uart = serial8250_get_port(dell_pdata->line);
+	int rx_len;
+
+	if (power != FB_BLANK_POWERDOWN)
+		power = FB_BLANK_UNBLANK;
+
+	bl_cmd->cmd[2] = power ? 0 : 1;
+	bl_cmd->cmd[3] = dell_uart_checksum(bl_cmd->cmd, bl_cmd->tx_len - 1);
+
+	dell_uart_dump_cmd(__func__, "tx: ", bl_cmd->cmd, bl_cmd->tx_len);
+
+	if (mutex_lock_killable(&dell_pdata->brightness_mutex) < 0) {
+		pr_debug("Failed to get mutex_lock");
+		return 0;
+	}
+
+	dell_uart_write(uart, bl_cmd->cmd, bl_cmd->tx_len);
+	rx_len = dell_uart_read(uart, bl_cmd->ret, bl_cmd->rx_len);
+
+	mutex_unlock(&dell_pdata->brightness_mutex);
+
+	dell_uart_dump_cmd(__func__, "rx: ", bl_cmd->ret, rx_len);
+
+	bd->props.power = power;
+	dell_pdata->bl_power = power;
+
+	return 0;
+}
+
+static int dell_uart_get_brightness(struct backlight_device *bd)
+{
+	struct dell_uart_bl_cmd *bl_cmd = &uart_cmd[DELL_UART_GET_BRIGHTNESS];
+	struct dell_uart_backlight *dell_pdata = bl_get_data(bd);
+	struct uart_8250_port *uart = serial8250_get_port(dell_pdata->line);
+	int rx_len, brightness = 0;
+
+	dell_uart_dump_cmd(__func__, "tx: ", bl_cmd->cmd, bl_cmd->tx_len);
+
+	if (mutex_lock_killable(&dell_pdata->brightness_mutex) < 0) {
+		pr_debug("Failed to get mutex_lock");
+		return 0;
+	}
+
+	dell_uart_write(uart, bl_cmd->cmd, bl_cmd->tx_len);
+	rx_len = dell_uart_read(uart, bl_cmd->ret, bl_cmd->rx_len);
+
+	mutex_unlock(&dell_pdata->brightness_mutex);
+
+	dell_uart_dump_cmd(__func__, "rx: ", bl_cmd->ret, rx_len);
+
+	brightness = (unsigned int)bl_cmd->ret[2];
+
+	return brightness;
+}
+
+static int dell_uart_update_status(struct backlight_device *bd)
+{
+	struct dell_uart_bl_cmd *bl_cmd = &uart_cmd[DELL_UART_SET_BRIGHTNESS];
+	struct dell_uart_backlight *dell_pdata = bl_get_data(bd);
+	struct uart_8250_port *uart = serial8250_get_port(dell_pdata->line);
+	int rx_len;
+
+	bl_cmd->cmd[2] = bd->props.brightness;
+	bl_cmd->cmd[3] = dell_uart_checksum(bl_cmd->cmd, bl_cmd->tx_len - 1);
+
+	dell_uart_dump_cmd(__func__, "tx: ", bl_cmd->cmd, bl_cmd->tx_len);
+
+	if (mutex_lock_killable(&dell_pdata->brightness_mutex) < 0) {
+		pr_debug("Failed to get mutex_lock");
+		return 0;
+	}
+
+	dell_uart_write(uart, bl_cmd->cmd, bl_cmd->tx_len);
+	rx_len = dell_uart_read(uart, bl_cmd->ret, bl_cmd->rx_len);
+
+	mutex_unlock(&dell_pdata->brightness_mutex);
+
+	dell_uart_dump_cmd(__func__, "rx: ", bl_cmd->ret, rx_len);
+
+	if (bd->props.power != dell_uart_get_bl_power(dell_pdata))
+		dell_uart_set_bl_power(bd, bd->props.power);
+
+	return 0;
+}
+
+static int dell_uart_get_scalar_status(struct dell_uart_backlight *dell_pdata)
+{
+	struct dell_uart_bl_cmd *bl_cmd = &uart_cmd[DELL_UART_GET_SCALAR];
+	struct uart_8250_port *uart = serial8250_get_port(dell_pdata->line);
+	int rx_len;
+	int status = 0, retry = 50;
+
+	dell_uart_dump_cmd(__func__, "tx: ", bl_cmd->cmd, bl_cmd->tx_len);
+
+	if (mutex_lock_killable(&dell_pdata->brightness_mutex) < 0) {
+		pr_debug("Failed to get mutex_lock");
+		return 0;
+	}
+
+	dell_uart_write(uart, bl_cmd->cmd, bl_cmd->tx_len);
+	do {
+		rx_len = dell_uart_read(uart, bl_cmd->ret, bl_cmd->rx_len);
+		if (rx_len == 0)
+			msleep(100);
+	} while (rx_len == 0 && --retry);
+
+	mutex_unlock(&dell_pdata->brightness_mutex);
+
+	dell_uart_dump_cmd(__func__, "rx: ", bl_cmd->ret, rx_len);
+
+	if (rx_len == 4)
+		status = (unsigned int)bl_cmd->ret[2];
+
+	return status;
+}
+
+static int dell_uart_show_firmware_ver(struct dell_uart_backlight *dell_pdata)
+{
+	struct dell_uart_bl_cmd *bl_cmd = &uart_cmd[DELL_UART_GET_FIRMWARE_VER];
+	struct uart_8250_port *uart = serial8250_get_port(dell_pdata->line);
+	int rx_len = 0, retry = 10;
+
+	dell_uart_dump_cmd(__func__, "tx: ", bl_cmd->cmd, bl_cmd->tx_len);
+
+	if (mutex_lock_killable(&dell_pdata->brightness_mutex) < 0) {
+		pr_debug("Failed to get mutex_lock");
+		return -1;
+	}
+
+	dell_uart_write(uart, bl_cmd->cmd, bl_cmd->tx_len);
+	while (retry-- > 0) {
+		/* first byte is data length */
+		dell_uart_read(uart, bl_cmd->ret, 1);
+		rx_len = (int)bl_cmd->ret[0];
+		if (bl_cmd->ret[0] > 80 || bl_cmd->ret[0] == 0) {
+			pr_debug("Failed to get firmware version\n");
+			if (retry == 0) {
+				mutex_unlock(&dell_pdata->brightness_mutex);
+				return -1;
+			}
+			msleep(100);
+			continue;
+		}
+
+		dell_uart_read(uart, bl_cmd->ret+1, rx_len-1);
+		break;
+	}
+	mutex_unlock(&dell_pdata->brightness_mutex);
+
+	dell_uart_dump_cmd(__func__, "rx: ", bl_cmd->ret, rx_len);
+
+	pr_debug("Firmare str(%d)= %s\n", (int)bl_cmd->ret[0], bl_cmd->ret+2);
+	return rx_len;
+}
+
+static const struct backlight_ops dell_uart_backlight_ops = {
+	.get_brightness = dell_uart_get_brightness,
+	.update_status = dell_uart_update_status,
+};
+
+static int dell_uart_startup(struct dell_uart_backlight *dell_pdata)
+{
+	struct uart_8250_port *uartp;
+	struct uart_port *port;
+
+	dell_pdata->line = 0;
+	uartp = serial8250_get_port(dell_pdata->line);
+	port = &uartp->port;
+	tty = port->state->port.tty;
+	io_serial_in = port->serial_in;
+	uart_write = tty->driver->ops->write;
+	uart_chars_in_buffer = tty->driver->ops->chars_in_buffer;
+
+	return 0;
+}
+
+static int dell_uart_bl_add(struct acpi_device *dev)
+{
+	struct dell_uart_backlight *dell_pdata;
+	struct backlight_properties props;
+	struct backlight_device *dell_uart_bd;
+
+	dell_pdata = kzalloc(sizeof(struct dell_uart_backlight), GFP_KERNEL);
+	if (!dell_pdata) {
+		pr_debug("Failed to allocate memory for dell_uart_backlight\n");
+		return -ENOMEM;
+	}
+	dell_pdata->dev = &dev->dev;
+	dell_uart_startup(dell_pdata);
+	dev->driver_data = dell_pdata;
+
+	mutex_init(&dell_pdata->brightness_mutex);
+
+	if (!force) {
+		if (dmi_check_system(dell_uart_backlight_alpha_platform)) {
+			/* try another command to make sure there is no scalar IC */
+			if (dell_uart_show_firmware_ver(dell_pdata) <= 4) {
+				pr_debug("Scalar is not in charge of brightness adjustment.\n");
+				kzfree(dell_pdata);
+				return -ENODEV;
+			}
+		}
+		else if (!dell_uart_get_scalar_status(dell_pdata)) {
+			pr_debug("Scalar is not in charge of brightness adjustment.\n");
+			kzfree(dell_pdata);
+			return -ENODEV;
+		}
+	}
+	dell_uart_show_firmware_ver(dell_pdata);
+
+	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_PLATFORM;
+	props.max_brightness = 100;
+
+	dell_uart_bd = backlight_device_register("dell_uart_backlight",
+						 &dev->dev,
+						 dell_pdata,
+						 &dell_uart_backlight_ops,
+						 &props);
+	if (IS_ERR(dell_uart_bd)) {
+		kzfree(dell_pdata);
+		pr_debug("Backlight registration failed\n");
+		return PTR_ERR(dell_uart_bd);
+	}
+
+	dell_pdata->dell_uart_bd = dell_uart_bd;
+
+	dell_uart_set_bl_power(dell_uart_bd, FB_BLANK_UNBLANK);
+	dell_uart_bd->props.brightness = 100;
+	backlight_update_status(dell_uart_bd);
+
+	/* unregister acpi backlight interface */
+	acpi_video_set_dmi_backlight_type(acpi_backlight_vendor);
+
+	return 0;
+}
+
+static int dell_uart_bl_remove(struct acpi_device *dev)
+{
+	struct dell_uart_backlight *dell_pdata = dev->driver_data;
+
+	backlight_device_unregister(dell_pdata->dell_uart_bd);
+	kzfree(dell_pdata);
+
+	return 0;
+}
+
+static int dell_uart_bl_suspend(struct device *dev)
+{
+	filp_close(ftty, NULL);
+	return 0;
+}
+
+static int dell_uart_bl_resume(struct device *dev)
+{
+	ftty = filp_open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY, 0);
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(dell_uart_bl_pm, dell_uart_bl_suspend, dell_uart_bl_resume);
+
+static const struct acpi_device_id dell_uart_bl_ids[] = {
+	{"DELL0501", 0},
+	{"", 0},
+};
+
+static struct acpi_driver dell_uart_backlight_driver = {
+	.name = "Dell AIO serial backlight",
+	.ids = dell_uart_bl_ids,
+	.ops = {
+		.add = dell_uart_bl_add,
+		.remove = dell_uart_bl_remove,
+	},
+	.drv.pm = &dell_uart_bl_pm,
+};
+
+static int __init dell_uart_bl_init(void)
+{
+	ftty = filp_open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY, 0);
+	if (IS_ERR(ftty)) {
+		pr_debug("cannot open /dev/ttyS0\n");
+		return -EINVAL;
+	}
+
+	return acpi_bus_register_driver(&dell_uart_backlight_driver);
+}
+
+static void __exit dell_uart_bl_exit(void)
+{
+	filp_close(ftty, NULL);
+
+	acpi_bus_unregister_driver(&dell_uart_backlight_driver);
+}
+
+module_init(dell_uart_bl_init);
+module_exit(dell_uart_bl_exit);
+MODULE_DEVICE_TABLE(acpi, dell_uart_bl_ids);
+MODULE_DESCRIPTION("Dell AIO Serial Backlight module");
+MODULE_AUTHOR("AceLan Kao <acelan.kao@canonical.com>");
+MODULE_LICENSE("GPL");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/dell-uart-backlight.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/dell-uart-backlight.h
@@ -0,0 +1,36 @@
+/*
+ *  Dell AIO Serial Backlight Driver
+ *
+ *  Copyright (C) 2017 AceLan Kao <acelan.kao@canonical.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ */
+
+#ifndef _DELL_UART_BACKLIGHT_H_
+#define _DELL_UART_BACKLIGHT_H_
+
+enum {
+	DELL_UART_GET_FIRMWARE_VER,
+	DELL_UART_GET_SCALAR,
+	DELL_UART_GET_BRIGHTNESS,
+	DELL_UART_SET_BRIGHTNESS,
+	DELL_UART_SET_BACKLIGHT_POWER,
+};
+
+struct dell_uart_bl_cmd {
+	unsigned char	cmd[10];
+	unsigned char	ret[80];
+	unsigned short	tx_len;
+	unsigned short	rx_len;
+};
+
+#endif /* _DELL_UART_BACKLIGHT_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/gpd-pocket-fan.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/gpd-pocket-fan.c
@@ -16,17 +16,27 @@
 
 #define MAX_SPEED 3
 
-static int temp_limits[3] = { 55000, 60000, 65000 };
+#define TEMP_LIMIT0_DEFAULT	55000
+#define TEMP_LIMIT1_DEFAULT	60000
+#define TEMP_LIMIT2_DEFAULT	65000
+
+#define HYSTERESIS_DEFAULT	3000
+
+#define SPEED_ON_AC_DEFAULT	2
+
+static int temp_limits[3] = {
+	TEMP_LIMIT0_DEFAULT, TEMP_LIMIT1_DEFAULT, TEMP_LIMIT2_DEFAULT,
+};
 module_param_array(temp_limits, int, NULL, 0444);
 MODULE_PARM_DESC(temp_limits,
 		 "Millicelsius values above which the fan speed increases");
 
-static int hysteresis = 3000;
+static int hysteresis = HYSTERESIS_DEFAULT;
 module_param(hysteresis, int, 0444);
 MODULE_PARM_DESC(hysteresis,
 		 "Hysteresis in millicelsius before lowering the fan speed");
 
-static int speed_on_ac = 2;
+static int speed_on_ac = SPEED_ON_AC_DEFAULT;
 module_param(speed_on_ac, int, 0444);
 MODULE_PARM_DESC(speed_on_ac,
 		 "minimum fan speed to allow when system is powered by AC");
@@ -117,21 +127,24 @@
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(temp_limits); i++) {
-		if (temp_limits[i] < 40000 || temp_limits[i] > 70000) {
-			dev_err(&pdev->dev, "Invalid temp-limit %d (must be between 40000 and 70000)\n",
+		if (temp_limits[i] < 20000 || temp_limits[i] > 90000) {
+			dev_err(&pdev->dev, "Invalid temp-limit %d (must be between 20000 and 90000)\n",
 				temp_limits[i]);
-			return -EINVAL;
+			temp_limits[0] = TEMP_LIMIT0_DEFAULT;
+			temp_limits[1] = TEMP_LIMIT1_DEFAULT;
+			temp_limits[2] = TEMP_LIMIT2_DEFAULT;
+			break;
 		}
 	}
 	if (hysteresis < 1000 || hysteresis > 10000) {
 		dev_err(&pdev->dev, "Invalid hysteresis %d (must be between 1000 and 10000)\n",
 			hysteresis);
-		return -EINVAL;
+		hysteresis = HYSTERESIS_DEFAULT;
 	}
 	if (speed_on_ac < 0 || speed_on_ac > MAX_SPEED) {
 		dev_err(&pdev->dev, "Invalid speed_on_ac %d (must be between 0 and 3)\n",
 			speed_on_ac);
-		return -EINVAL;
+		speed_on_ac = SPEED_ON_AC_DEFAULT;
 	}
 
 	fan = devm_kzalloc(&pdev->dev, sizeof(*fan), GFP_KERNEL);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/hdaps.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/hdaps.c
@@ -366,7 +366,7 @@
 static ssize_t hdaps_temp1_show(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
-	u8 uninitialized_var(temp);
+	u8 temp;
 	int ret;
 
 	ret = hdaps_readb_one(HDAPS_PORT_TEMP1, &temp);
@@ -379,7 +379,7 @@
 static ssize_t hdaps_temp2_show(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
-	u8 uninitialized_var(temp);
+	u8 temp;
 	int ret;
 
 	ret = hdaps_readb_one(HDAPS_PORT_TEMP2, &temp);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/hp-wireless.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/hp-wireless.c
@@ -17,12 +17,14 @@
 MODULE_AUTHOR("Alex Hung");
 MODULE_ALIAS("acpi*:HPQ6001:*");
 MODULE_ALIAS("acpi*:WSTADEF:*");
+MODULE_ALIAS("acpi*:AMDI0051:*");
 
 static struct input_dev *hpwl_input_dev;
 
 static const struct acpi_device_id hpwl_ids[] = {
 	{"HPQ6001", 0},
 	{"WSTADEF", 0},
+	{"AMDI0051", 0},
 	{"", 0},
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/hp-wmi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/hp-wmi.c
@@ -32,6 +32,10 @@
 MODULE_ALIAS("wmi:95F24279-4D7B-4334-9387-ACCDC67EF61C");
 MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4");
 
+static int enable_tablet_mode_sw = -1;
+module_param(enable_tablet_mode_sw, int, 0444);
+MODULE_PARM_DESC(enable_tablet_mode_sw, "Enable SW_TABLET_MODE reporting (-1=auto, 0=no, 1=yes)");
+
 #define HPWMI_EVENT_GUID "95F24279-4D7B-4334-9387-ACCDC67EF61C"
 #define HPWMI_BIOS_GUID "5FB7F034-2C63-45e9-BE91-3D44E2C707E4"
 
@@ -58,6 +62,8 @@
 	HPWMI_BACKLIT_KB_BRIGHTNESS	= 0x0D,
 	HPWMI_PEAKSHIFT_PERIOD		= 0x0F,
 	HPWMI_BATTERY_CHARGE_PERIOD	= 0x10,
+	HPWMI_SANITIZATION_MODE		= 0x17,
+	HPWMI_SMART_EXPERIENCE_APP	= 0x21,
 };
 
 struct bios_args {
@@ -65,7 +71,7 @@
 	u32 command;
 	u32 commandtype;
 	u32 datasize;
-	u32 data;
+	u8 data[128];
 };
 
 enum hp_wmi_commandtype {
@@ -216,7 +222,7 @@
 		.command = command,
 		.commandtype = query,
 		.datasize = insize,
-		.data = 0,
+		.data = { 0 },
 	};
 	struct acpi_buffer input = { sizeof(struct bios_args), &args };
 	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -228,7 +234,7 @@
 
 	if (WARN_ON(insize > sizeof(args.data)))
 		return -EINVAL;
-	memcpy(&args.data, buffer, insize);
+	memcpy(&args.data[0], buffer, insize);
 
 	wmi_evaluate_method(HPWMI_BIOS_GUID, 0, mid, &input, &output);
 
@@ -300,7 +306,7 @@
 
 static int __init hp_wmi_bios_2009_later(void)
 {
-	int state = 0;
+	u8 state[128];
 	int ret = hp_wmi_perform_query(HPWMI_FEATURE2_QUERY, HPWMI_READ, &state,
 				       sizeof(state), sizeof(state));
 	if (!ret)
@@ -380,7 +386,7 @@
 	int err, i;
 
 	err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, HPWMI_READ, &state,
-				   0, sizeof(state));
+				   sizeof(state), sizeof(state));
 	if (err)
 		return err;
 
@@ -461,8 +467,14 @@
 static ssize_t als_store(struct device *dev, struct device_attribute *attr,
 			 const char *buf, size_t count)
 {
-	u32 tmp = simple_strtoul(buf, NULL, 10);
-	int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, HPWMI_WRITE, &tmp,
+	u32 tmp;
+	int ret;
+
+	ret = kstrtou32(buf, 10, &tmp);
+	if (ret)
+		return ret;
+
+	ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, HPWMI_WRITE, &tmp,
 				       sizeof(tmp), sizeof(tmp));
 	if (ret)
 		return ret < 0 ? ret : -EINVAL;
@@ -619,6 +631,10 @@
 		break;
 	case HPWMI_BATTERY_CHARGE_PERIOD:
 		break;
+	case HPWMI_SANITIZATION_MODE:
+		break;
+	case HPWMI_SMART_EXPERIENCE_APP:
+		break;
 	default:
 		pr_info("Unknown event_id - %d - 0x%x\n", event_id, event_data);
 		break;
@@ -648,10 +664,12 @@
 	}
 
 	/* Tablet mode */
-	val = hp_wmi_hw_state(HPWMI_TABLET_MASK);
-	if (!(val < 0)) {
-		__set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit);
-		input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, val);
+	if (enable_tablet_mode_sw > 0) {
+		val = hp_wmi_hw_state(HPWMI_TABLET_MASK);
+		if (val >= 0) {
+			__set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit);
+			input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, val);
+		}
 	}
 
 	err = sparse_keymap_setup(hp_wmi_input_dev, hp_wmi_keymap, NULL);
@@ -778,7 +796,7 @@
 	int err, i;
 
 	err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, HPWMI_READ, &state,
-				   0, sizeof(state));
+				   sizeof(state), sizeof(state));
 	if (err)
 		return err < 0 ? err : -EINVAL;
 
@@ -865,8 +883,16 @@
 	wwan_rfkill = NULL;
 	rfkill2_count = 0;
 
-	if (hp_wmi_rfkill_setup(device))
-		hp_wmi_rfkill2_setup(device);
+	/*
+	 * In pre-2009 BIOS, command 1Bh return 0x4 to indicate that
+	 * BIOS no longer controls the power for the wireless
+	 * devices. All features supported by this command will no
+	 * longer be supported.
+	 */
+	if (!hp_wmi_bios_2009_later()) {
+		if (hp_wmi_rfkill_setup(device))
+			hp_wmi_rfkill2_setup(device);
+	}
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/hp_accel.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/hp_accel.c
@@ -88,6 +88,9 @@
 static int lis3lv02d_acpi_init(struct lis3lv02d *lis3)
 {
 	struct acpi_device *dev = lis3->bus_priv;
+	if (!lis3->init_required)
+		return 0;
+
 	if (acpi_evaluate_object(dev->handle, METHOD_NAME__INI,
 				 NULL, NULL) != AE_OK)
 		return -EINVAL;
@@ -356,6 +359,7 @@
 	}
 
 	/* call the core layer do its init */
+	lis3_dev.init_required = true;
 	ret = lis3lv02d_init_device(&lis3_dev);
 	if (ret)
 		return ret;
@@ -368,9 +372,11 @@
 	INIT_WORK(&hpled_led.work, delayed_set_status_worker);
 	ret = led_classdev_register(NULL, &hpled_led.led_classdev);
 	if (ret) {
+		i8042_remove_filter(hp_accel_i8042_filter);
 		lis3lv02d_joystick_disable(&lis3_dev);
 		lis3lv02d_poweroff(&lis3_dev);
 		flush_work(&hpled_led.work);
+		lis3lv02d_remove_fs(&lis3_dev);
 		return ret;
 	}
 
@@ -403,11 +409,27 @@
 
 static int lis3lv02d_resume(struct device *dev)
 {
+	lis3_dev.init_required = false;
+	lis3lv02d_poweron(&lis3_dev);
+	return 0;
+}
+
+static int lis3lv02d_restore(struct device *dev)
+{
+	lis3_dev.init_required = true;
 	lis3lv02d_poweron(&lis3_dev);
 	return 0;
 }
 
-static SIMPLE_DEV_PM_OPS(hp_accel_pm, lis3lv02d_suspend, lis3lv02d_resume);
+static const struct dev_pm_ops hp_accel_pm = {
+	.suspend = lis3lv02d_suspend,
+	.resume = lis3lv02d_resume,
+	.freeze = lis3lv02d_suspend,
+	.thaw = lis3lv02d_resume,
+	.poweroff = lis3lv02d_suspend,
+	.restore = lis3lv02d_restore,
+};
+
 #define HP_ACCEL_PM (&hp_accel_pm)
 #else
 #define HP_ACCEL_PM NULL
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/huawei-wmi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/huawei-wmi.c
@@ -41,6 +41,8 @@
 	{ KE_IGNORE, 0x293, { KEY_KBDILLUMTOGGLE } },
 	{ KE_IGNORE, 0x294, { KEY_KBDILLUMUP } },
 	{ KE_IGNORE, 0x295, { KEY_KBDILLUMUP } },
+	// Ignore Ambient Light Sensoring
+	{ KE_KEY,    0x2c1, { KEY_RESERVED } },
 	{ KE_END,	 0 }
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/i2c-multi-instantiate.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/i2c-multi-instantiate.c
@@ -166,13 +166,29 @@
 	{}
 };
 
-static const struct i2c_inst_data int3515_data[]  = {
-	{ "tps6598x", IRQ_RESOURCE_APIC, 0 },
-	{ "tps6598x", IRQ_RESOURCE_APIC, 1 },
-	{ "tps6598x", IRQ_RESOURCE_APIC, 2 },
-	{ "tps6598x", IRQ_RESOURCE_APIC, 3 },
-	{}
-};
+/*
+ * Device with _HID INT3515 (TI PD controllers) has some unresolved interrupt
+ * issues. The most common problem seen is interrupt flood.
+ *
+ * There are at least two known causes. Firstly, on some boards, the
+ * I2CSerialBus resource index does not match the Interrupt resource, i.e. they
+ * are not one-to-one mapped like in the array below. Secondly, on some boards
+ * the IRQ line from the PD controller is not actually connected at all. But the
+ * interrupt flood is also seen on some boards where those are not a problem, so
+ * there are some other problems as well.
+ *
+ * Because of the issues with the interrupt, the device is disabled for now. If
+ * you wish to debug the issues, uncomment the below, and add an entry for the
+ * INT3515 device to the i2c_multi_instance_ids table.
+ *
+ * static const struct i2c_inst_data int3515_data[]  = {
+ *	{ "tps6598x", IRQ_RESOURCE_APIC, 0 },
+ *	{ "tps6598x", IRQ_RESOURCE_APIC, 1 },
+ *	{ "tps6598x", IRQ_RESOURCE_APIC, 2 },
+ *	{ "tps6598x", IRQ_RESOURCE_APIC, 3 },
+ *	{ }
+ * };
+ */
 
 /*
  * Note new device-ids must also be added to i2c_multi_instantiate_ids in
@@ -181,7 +197,6 @@
 static const struct acpi_device_id i2c_multi_inst_acpi_ids[] = {
 	{ "BSG1160", (unsigned long)bsg1160_data },
 	{ "BSG2150", (unsigned long)bsg2150_data },
-	{ "INT3515", (unsigned long)int3515_data },
 	{ }
 };
 MODULE_DEVICE_TABLE(acpi, i2c_multi_inst_acpi_ids);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/ideapad-laptop.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/ideapad-laptop.c
@@ -92,6 +92,7 @@
 	struct dentry *debug;
 	unsigned long cfg;
 	bool has_hw_rfkill_switch;
+	bool has_touchpad_switch;
 	const char *fnesc_guid;
 };
 
@@ -535,7 +536,9 @@
 	} else if (attr == &dev_attr_fn_lock.attr) {
 		supported = acpi_has_method(priv->adev->handle, "HALS") &&
 			acpi_has_method(priv->adev->handle, "SALS");
-	} else
+	} else if (attr == &dev_attr_touchpad.attr)
+		supported = priv->has_touchpad_switch;
+	else
 		supported = true;
 
 	return supported ? attr->mode : 0;
@@ -867,6 +870,9 @@
 {
 	unsigned long value;
 
+	if (!priv->has_touchpad_switch)
+		return;
+
 	/* Without reading from EC touchpad LED doesn't switch state */
 	if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value)) {
 		/* Some IdeaPads don't really turn off touchpad - they only
@@ -989,6 +995,9 @@
 	priv->platform_device = pdev;
 	priv->has_hw_rfkill_switch = dmi_check_system(hw_rfkill_list);
 
+	/* Most ideapads with ELAN0634 touchpad don't use EC touchpad switch */
+	priv->has_touchpad_switch = !acpi_dev_present("ELAN0634", NULL, -1);
+
 	ret = ideapad_sysfs_init(priv);
 	if (ret)
 		return ret;
@@ -1006,6 +1015,10 @@
 	if (!priv->has_hw_rfkill_switch)
 		write_ec_cmd(priv->adev->handle, VPCCMD_W_RF, 1);
 
+	/* The same for Touchpad */
+	if (!priv->has_touchpad_switch)
+		write_ec_cmd(priv->adev->handle, VPCCMD_W_TOUCHPAD, 1);
+
 	for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
 		if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg))
 			ideapad_register_rfkill(priv, i);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/intel-hid.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/intel-hid.c
@@ -20,8 +20,11 @@
 
 static const struct acpi_device_id intel_hid_ids[] = {
 	{"INT33D5", 0},
+	{"INTC1051", 0},
+	{"INTC1054", 0},
 	{"", 0},
 };
+MODULE_DEVICE_TABLE(acpi, intel_hid_ids);
 
 /* In theory, these are HID usages. */
 static const struct key_entry intel_hid_keymap[] = {
@@ -77,6 +80,20 @@
 			DMI_MATCH(DMI_PRODUCT_NAME, "Wacom MobileStudio Pro 16"),
 		},
 	},
+	{
+		.ident = "HP Spectre x2 (2015)",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x2 Detachable"),
+		},
+	},
+	{
+		.ident = "Lenovo ThinkPad X1 Tablet Gen 2",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+			DMI_MATCH(DMI_PRODUCT_FAMILY, "ThinkPad X1 Tablet Gen 2"),
+		},
+	},
 	{ }
 };
 
@@ -435,7 +452,7 @@
 static int intel_hid_probe(struct platform_device *device)
 {
 	acpi_handle handle = ACPI_HANDLE(&device->dev);
-	unsigned long long mode;
+	unsigned long long mode, dummy;
 	struct intel_hid_priv *priv;
 	acpi_status status;
 	int err;
@@ -487,18 +504,15 @@
 	if (err)
 		goto err_remove_notify;
 
-	if (priv->array) {
-		unsigned long long dummy;
-
-		intel_button_array_enable(&device->dev, true);
+	intel_button_array_enable(&device->dev, true);
 
-		/* Call button load method to enable HID power button */
-		if (!intel_hid_evaluate_method(handle, INTEL_HID_DSM_BTNL_FN,
-					       &dummy)) {
-			dev_warn(&device->dev,
-				 "failed to enable HID power button\n");
-		}
-	}
+	/*
+	 * Call button load method to enable HID power button
+	 * Always do this since it activates events on some devices without
+	 * a button array too.
+	 */
+	if (!intel_hid_evaluate_method(handle, INTEL_HID_DSM_BTNL_FN, &dummy))
+		dev_warn(&device->dev, "failed to enable HID power button\n");
 
 	device_init_wakeup(&device->dev, true);
 	/*
@@ -540,7 +554,6 @@
 	.probe = intel_hid_probe,
 	.remove = intel_hid_remove,
 };
-MODULE_DEVICE_TABLE(acpi, intel_hid_ids);
 
 /*
  * Unfortunately, some laptops provide a _HID="INT33D5" device with
@@ -563,7 +576,7 @@
 		return AE_OK;
 
 	if (acpi_match_device_ids(dev, ids) == 0)
-		if (acpi_create_platform_device(dev, NULL))
+		if (!IS_ERR_OR_NULL(acpi_create_platform_device(dev, NULL)))
 			dev_info(&dev->dev,
 				 "intel-hid: created platform device\n");
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/intel-vbtn.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/intel-vbtn.c
@@ -15,9 +15,13 @@
 #include <linux/platform_device.h>
 #include <linux/suspend.h>
 
+/* Returned when NOT in tablet mode on some HP Stream x360 11 models */
+#define VGBS_TABLET_MODE_FLAG_ALT	0x10
 /* When NOT in tablet mode, VGBS returns with the flag 0x40 */
-#define TABLET_MODE_FLAG 0x40
-#define DOCK_MODE_FLAG   0x80
+#define VGBS_TABLET_MODE_FLAG		0x40
+#define VGBS_DOCK_MODE_FLAG		0x80
+
+#define VGBS_TABLET_MODE_FLAGS (VGBS_TABLET_MODE_FLAG | VGBS_TABLET_MODE_FLAG_ALT)
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("AceLan Kao");
@@ -39,28 +43,59 @@
 	{ KE_IGNORE, 0xC7, { KEY_VOLUMEDOWN } },	/* volume-down key release */
 	{ KE_KEY,    0xC8, { KEY_ROTATE_LOCK_TOGGLE } },	/* rotate-lock key press */
 	{ KE_KEY,    0xC9, { KEY_ROTATE_LOCK_TOGGLE } },	/* rotate-lock key release */
-	{ KE_SW,     0xCA, { .sw = { SW_DOCK, 1 } } },		/* Docked */
-	{ KE_SW,     0xCB, { .sw = { SW_DOCK, 0 } } },		/* Undocked */
+};
+
+static const struct key_entry intel_vbtn_switchmap[] = {
+	/*
+	 * SW_DOCK should only be reported for docking stations, but DSDTs using the
+	 * intel-vbtn code, always seem to use this for 2-in-1s / convertibles and set
+	 * SW_DOCK=1 when in laptop-mode (in tandem with setting SW_TABLET_MODE=0).
+	 * This causes userspace to think the laptop is docked to a port-replicator
+	 * and to disable suspend-on-lid-close, which is undesirable.
+	 * Map the dock events to KEY_IGNORE to avoid this broken SW_DOCK reporting.
+	 */
+	{ KE_IGNORE, 0xCA, { .sw = { SW_DOCK, 1 } } },		/* Docked */
+	{ KE_IGNORE, 0xCB, { .sw = { SW_DOCK, 0 } } },		/* Undocked */
 	{ KE_SW,     0xCC, { .sw = { SW_TABLET_MODE, 1 } } },	/* Tablet */
 	{ KE_SW,     0xCD, { .sw = { SW_TABLET_MODE, 0 } } },	/* Laptop */
-	{ KE_END },
 };
 
+#define KEYMAP_LEN \
+	(ARRAY_SIZE(intel_vbtn_keymap) + ARRAY_SIZE(intel_vbtn_switchmap) + 1)
+
 struct intel_vbtn_priv {
+	struct key_entry keymap[KEYMAP_LEN];
 	struct input_dev *input_dev;
+	bool has_switches;
 	bool wakeup_mode;
 };
 
 static int intel_vbtn_input_setup(struct platform_device *device)
 {
 	struct intel_vbtn_priv *priv = dev_get_drvdata(&device->dev);
-	int ret;
+	int ret, keymap_len = 0;
+
+	if (true) {
+		memcpy(&priv->keymap[keymap_len], intel_vbtn_keymap,
+		       ARRAY_SIZE(intel_vbtn_keymap) *
+		       sizeof(struct key_entry));
+		keymap_len += ARRAY_SIZE(intel_vbtn_keymap);
+	}
+
+	if (priv->has_switches) {
+		memcpy(&priv->keymap[keymap_len], intel_vbtn_switchmap,
+		       ARRAY_SIZE(intel_vbtn_switchmap) *
+		       sizeof(struct key_entry));
+		keymap_len += ARRAY_SIZE(intel_vbtn_switchmap);
+	}
+
+	priv->keymap[keymap_len].type = KE_END;
 
 	priv->input_dev = devm_input_allocate_device(&device->dev);
 	if (!priv->input_dev)
 		return -ENOMEM;
 
-	ret = sparse_keymap_setup(priv->input_dev, intel_vbtn_keymap, NULL);
+	ret = sparse_keymap_setup(priv->input_dev, priv->keymap, NULL);
 	if (ret)
 		return ret;
 
@@ -115,31 +150,86 @@
 
 static void detect_tablet_mode(struct platform_device *device)
 {
-	const char *chassis_type = dmi_get_system_info(DMI_CHASSIS_TYPE);
 	struct intel_vbtn_priv *priv = dev_get_drvdata(&device->dev);
 	acpi_handle handle = ACPI_HANDLE(&device->dev);
-	struct acpi_buffer vgbs_output = { ACPI_ALLOCATE_BUFFER, NULL };
-	union acpi_object *obj;
+	unsigned long long vgbs;
 	acpi_status status;
 	int m;
 
-	if (!(chassis_type && strcmp(chassis_type, "31") == 0))
-		goto out;
-
-	status = acpi_evaluate_object(handle, "VGBS", NULL, &vgbs_output);
+	status = acpi_evaluate_integer(handle, "VGBS", NULL, &vgbs);
 	if (ACPI_FAILURE(status))
-		goto out;
-
-	obj = vgbs_output.pointer;
-	if (!(obj && obj->type == ACPI_TYPE_INTEGER))
-		goto out;
+		return;
 
-	m = !(obj->integer.value & TABLET_MODE_FLAG);
+	m = !(vgbs & VGBS_TABLET_MODE_FLAGS);
 	input_report_switch(priv->input_dev, SW_TABLET_MODE, m);
-	m = (obj->integer.value & DOCK_MODE_FLAG) ? 1 : 0;
+	m = (vgbs & VGBS_DOCK_MODE_FLAG) ? 1 : 0;
 	input_report_switch(priv->input_dev, SW_DOCK, m);
-out:
-	kfree(vgbs_output.pointer);
+}
+
+/*
+ * There are several laptops (non 2-in-1) models out there which support VGBS,
+ * but simply always return 0, which we translate to SW_TABLET_MODE=1. This in
+ * turn causes userspace (libinput) to suppress events from the builtin
+ * keyboard and touchpad, making the laptop essentially unusable.
+ *
+ * Since the problem of wrongly reporting SW_TABLET_MODE=1 in combination
+ * with libinput, leads to a non-usable system. Where as OTOH many people will
+ * not even notice when SW_TABLET_MODE is not being reported, a DMI based allow
+ * list is used here. This list mainly matches on the chassis-type of 2-in-1s.
+ *
+ * There are also some 2-in-1s which use the intel-vbtn ACPI interface to report
+ * SW_TABLET_MODE with a chassis-type of 8 ("Portable") or 10 ("Notebook"),
+ * these are matched on a per model basis, since many normal laptops with a
+ * possible broken VGBS ACPI-method also use these chassis-types.
+ */
+static const struct dmi_system_id dmi_switches_allow_list[] = {
+	{
+		.matches = {
+			DMI_EXACT_MATCH(DMI_CHASSIS_TYPE, "31" /* Convertible */),
+		},
+	},
+	{
+		.matches = {
+			DMI_EXACT_MATCH(DMI_CHASSIS_TYPE, "32" /* Detachable */),
+		},
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Venue 11 Pro 7130"),
+		},
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion 13 x360 PC"),
+		},
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Switch SA5-271"),
+		},
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7352"),
+		},
+	},
+	{} /* Array terminator */
+};
+
+static bool intel_vbtn_has_switches(acpi_handle handle)
+{
+	unsigned long long vgbs;
+	acpi_status status;
+
+	if (!dmi_check_system(dmi_switches_allow_list))
+		return false;
+
+	status = acpi_evaluate_integer(handle, "VGBS", NULL, &vgbs);
+	return ACPI_SUCCESS(status);
 }
 
 static int intel_vbtn_probe(struct platform_device *device)
@@ -160,13 +250,16 @@
 		return -ENOMEM;
 	dev_set_drvdata(&device->dev, priv);
 
+	priv->has_switches = intel_vbtn_has_switches(handle);
+
 	err = intel_vbtn_input_setup(device);
 	if (err) {
 		pr_err("Failed to setup Intel Virtual Button\n");
 		return err;
 	}
 
-	detect_tablet_mode(device);
+	if (priv->has_switches)
+		detect_tablet_mode(device);
 
 	status = acpi_install_notify_handler(handle,
 					     ACPI_DEVICE_NOTIFY,
@@ -251,7 +344,7 @@
 		return AE_OK;
 
 	if (acpi_match_device_ids(dev, ids) == 0)
-		if (acpi_create_platform_device(dev, NULL))
+		if (!IS_ERR_OR_NULL(acpi_create_platform_device(dev, NULL)))
 			dev_info(&dev->dev,
 				 "intel-vbtn: created platform device\n");
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/intel_bxtwc_tmu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/intel_bxtwc_tmu.c
@@ -48,9 +48,8 @@
 static int bxt_wcove_tmu_probe(struct platform_device *pdev)
 {
 	struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
-	struct regmap_irq_chip_data *regmap_irq_chip;
 	struct wcove_tmu *wctmu;
-	int ret, virq, irq;
+	int ret;
 
 	wctmu = devm_kzalloc(&pdev->dev, sizeof(*wctmu), GFP_KERNEL);
 	if (!wctmu)
@@ -59,27 +58,18 @@
 	wctmu->dev = &pdev->dev;
 	wctmu->regmap = pmic->regmap;
 
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0)
-		return irq;
+	wctmu->irq = platform_get_irq(pdev, 0);
+	if (wctmu->irq < 0)
+		return wctmu->irq;
 
-	regmap_irq_chip = pmic->irq_chip_data_tmu;
-	virq = regmap_irq_get_virq(regmap_irq_chip, irq);
-	if (virq < 0) {
-		dev_err(&pdev->dev,
-			"failed to get virtual interrupt=%d\n", irq);
-		return virq;
-	}
-
-	ret = devm_request_threaded_irq(&pdev->dev, virq,
+	ret = devm_request_threaded_irq(&pdev->dev, wctmu->irq,
 					NULL, bxt_wcove_tmu_irq_handler,
 					IRQF_ONESHOT, "bxt_wcove_tmu", wctmu);
 	if (ret) {
 		dev_err(&pdev->dev, "request irq failed: %d,virq: %d\n",
-							ret, virq);
+			ret, wctmu->irq);
 		return ret;
 	}
-	wctmu->irq = virq;
 
 	/* Unmask TMU second level Wake & System alarm */
 	regmap_update_bits(wctmu->regmap, BXTWC_MTMUIRQ_REG,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/intel_int0002_vgpio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/intel_int0002_vgpio.c
@@ -127,6 +127,14 @@
 	return IRQ_HANDLED;
 }
 
+static bool int0002_check_wake(void *data)
+{
+	u32 gpe_sts_reg;
+
+	gpe_sts_reg = inl(GPE0A_STS_PORT);
+	return (gpe_sts_reg & GPE0A_PME_B0_STS_BIT);
+}
+
 static struct irq_chip int0002_byt_irqchip = {
 	.name			= DRV_NAME,
 	.irq_ack		= int0002_irq_ack,
@@ -220,6 +228,7 @@
 
 	gpiochip_set_chained_irqchip(chip, irq_chip, irq, NULL);
 
+	acpi_register_wakeup_handler(irq, int0002_check_wake, NULL);
 	device_init_wakeup(dev, true);
 	return 0;
 }
@@ -227,6 +236,7 @@
 static int int0002_remove(struct platform_device *pdev)
 {
 	device_init_wakeup(&pdev->dev, false);
+	acpi_unregister_wakeup_handler(int0002_check_wake, NULL);
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/intel_ips.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/intel_ips.c
@@ -1432,6 +1432,14 @@
 			DMI_MATCH(DMI_PRODUCT_NAME, "HP ProBook"),
 		},
 	},
+	{
+		.callback = ips_blacklist_callback,
+		.ident = "G60JX",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "G60JX"),
+		},
+	},
 	{ }	/* terminating entry */
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/intel_mid_powerbtn.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/intel_mid_powerbtn.c
@@ -146,9 +146,10 @@
 
 	input_set_capability(input, EV_KEY, KEY_POWER);
 
-	ddata = (struct mid_pb_ddata *)id->driver_data;
+	ddata = devm_kmemdup(&pdev->dev, (void *)id->driver_data,
+			     sizeof(*ddata), GFP_KERNEL);
 	if (!ddata)
-		return -ENODATA;
+		return -ENOMEM;
 
 	ddata->dev = &pdev->dev;
 	ddata->irq = irq;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/intel_pmc_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/intel_pmc_core.c
@@ -158,8 +158,9 @@
 	.pm_vric1_offset = SPT_PMC_VRIC1_OFFSET,
 };
 
-/* Cannonlake: PGD PFET Enable Ack Status Register(s) bitmap */
+/* Cannon Lake: PGD PFET Enable Ack Status Register(s) bitmap */
 static const struct pmc_bit_map cnp_pfear_map[] = {
+	/* Reserved for Cannon Lake but valid for Comet Lake */
 	{"PMC",                 BIT(0)},
 	{"OPI-DMI",             BIT(1)},
 	{"SPI/eSPI",            BIT(2)},
@@ -185,7 +186,7 @@
 	{"SDX",                 BIT(4)},
 	{"SPE",                 BIT(5)},
 	{"Fuse",                BIT(6)},
-	/* Reserved for Cannonlake but valid for Icelake */
+	/* Reserved for Cannon Lake but valid for Ice Lake and Comet Lake */
 	{"SBR8",		BIT(7)},
 
 	{"CSME_FSC",            BIT(0)},
@@ -229,12 +230,12 @@
 	{"HDA_PGD4",            BIT(2)},
 	{"HDA_PGD5",            BIT(3)},
 	{"HDA_PGD6",            BIT(4)},
-	/* Reserved for Cannonlake but valid for Icelake */
+	/* Reserved for Cannon Lake but valid for Ice Lake and Comet Lake */
 	{"PSF6",		BIT(5)},
 	{"PSF7",		BIT(6)},
 	{"PSF8",		BIT(7)},
 
-	/* Icelake generation onwards only */
+	/* Ice Lake generation onwards only */
 	{"RES_65",		BIT(0)},
 	{"RES_66",		BIT(1)},
 	{"RES_67",		BIT(2)},
@@ -324,7 +325,7 @@
 	{"ISH",			CNP_PMC_LTR_ISH},
 	{"UFSX2",		CNP_PMC_LTR_UFSX2},
 	{"EMMC",		CNP_PMC_LTR_EMMC},
-	/* Reserved for Cannonlake but valid for Icelake */
+	/* Reserved for Cannon Lake but valid for Ice Lake */
 	{"WIGIG",		ICL_PMC_LTR_WIGIG},
 	/* Below two cannot be used for LTR_IGNORE */
 	{"CURRENT_PLATFORM",	CNP_PMC_LTR_CUR_PLT},
@@ -813,6 +814,8 @@
 	INTEL_CPU_FAM6(CANNONLAKE_L, cnp_reg_map),
 	INTEL_CPU_FAM6(ICELAKE_L, icl_reg_map),
 	INTEL_CPU_FAM6(ICELAKE_NNPI, icl_reg_map),
+	INTEL_CPU_FAM6(COMETLAKE, cnp_reg_map),
+	INTEL_CPU_FAM6(COMETLAKE_L, cnp_reg_map),
 	{}
 };
 
@@ -828,9 +831,15 @@
  * the platform BIOS enforces 24Mhx Crystal to shutdown
  * before PMC can assert SLP_S0#.
  */
+static bool xtal_ignore;
 static int quirk_xtal_ignore(const struct dmi_system_id *id)
 {
-	struct pmc_dev *pmcdev = &pmc;
+	xtal_ignore = true;
+	return 0;
+}
+
+static void pmc_core_xtal_ignore(struct pmc_dev *pmcdev)
+{
 	u32 value;
 
 	value = pmc_core_reg_read(pmcdev, pmcdev->map->pm_vric1_offset);
@@ -839,7 +848,6 @@
 	/* Low Voltage Mode Enable */
 	value &= ~SPT_PMC_VRIC1_SLPS0LVEN;
 	pmc_core_reg_write(pmcdev, pmcdev->map->pm_vric1_offset, value);
-	return 0;
 }
 
 static const struct dmi_system_id pmc_core_dmi_table[]  = {
@@ -854,6 +862,14 @@
 	{}
 };
 
+static void pmc_core_do_dmi_quirks(struct pmc_dev *pmcdev)
+{
+	dmi_check_system(pmc_core_dmi_table);
+
+	if (xtal_ignore)
+		pmc_core_xtal_ignore(pmcdev);
+}
+
 static int pmc_core_probe(struct platform_device *pdev)
 {
 	static bool device_initialized;
@@ -871,8 +887,8 @@
 	pmcdev->map = (struct pmc_reg_map *)cpu_id->driver_data;
 
 	/*
-	 * Coffeelake has CPU ID of Kabylake and Cannonlake PCH. So here
-	 * Sunrisepoint PCH regmap can't be used. Use Cannonlake PCH regmap
+	 * Coffee Lake has CPU ID of Kaby Lake and Cannon Lake PCH. So here
+	 * Sunrisepoint PCH regmap can't be used. Use Cannon Lake PCH regmap
 	 * in this case.
 	 */
 	if (pmcdev->map == &spt_reg_map && !pci_dev_present(pmc_pci_ids))
@@ -895,7 +911,7 @@
 	mutex_init(&pmcdev->lock);
 	platform_set_drvdata(pdev, pmcdev);
 	pmcdev->pmc_xram_read_bit = pmc_core_check_read_lock_bit();
-	dmi_check_system(pmc_core_dmi_table);
+	pmc_core_do_dmi_quirks(pmcdev);
 
 	pmc_core_dbgfs_register(pmcdev);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/intel_pmc_core_pltdrv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/intel_pmc_core_pltdrv.c
@@ -18,6 +18,8 @@
 #include <asm/cpu_device_id.h>
 #include <asm/intel-family.h>
 
+#include <xen/xen.h>
+
 static void intel_pmc_core_release(struct device *dev)
 {
 	/* Nothing to do. */
@@ -44,6 +46,8 @@
 	INTEL_CPU_FAM6(KABYLAKE, pmc_core_device),
 	INTEL_CPU_FAM6(CANNONLAKE_L, pmc_core_device),
 	INTEL_CPU_FAM6(ICELAKE_L, pmc_core_device),
+	INTEL_CPU_FAM6(COMETLAKE, pmc_core_device),
+	INTEL_CPU_FAM6(COMETLAKE_L, pmc_core_device),
 	{}
 };
 MODULE_DEVICE_TABLE(x86cpu, intel_pmc_core_platform_ids);
@@ -54,6 +58,13 @@
 	if (acpi_dev_present("INT33A1", NULL, -1))
 		return -ENODEV;
 
+	/*
+	 * Skip forcefully attaching the device for VMs. Make an exception for
+	 * Xen dom0, which does have full hardware access.
+	 */
+	if (cpu_feature_enabled(X86_FEATURE_HYPERVISOR) && !xen_initial_domain())
+		return -ENODEV;
+
 	if (!x86_match_cpu(intel_pmc_core_platform_ids))
 		return -ENODEV;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/intel_punit_ipc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/intel_punit_ipc.c
@@ -8,7 +8,6 @@
  * which provide mailbox interface for power management usage.
  */
 
-#include <linux/acpi.h>
 #include <linux/bitops.h>
 #include <linux/delay.h>
 #include <linux/device.h>
@@ -328,13 +327,14 @@
 	{ "INT34D4", 0 },
 	{ }
 };
+MODULE_DEVICE_TABLE(acpi, punit_ipc_acpi_ids);
 
 static struct platform_driver intel_punit_ipc_driver = {
 	.probe = intel_punit_ipc_probe,
 	.remove = intel_punit_ipc_remove,
 	.driver = {
 		.name = "intel_punit_ipc",
-		.acpi_match_table = ACPI_PTR(punit_ipc_acpi_ids),
+		.acpi_match_table = punit_ipc_acpi_ids,
 	},
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/intel_scu_ipc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/intel_scu_ipc.c
@@ -67,26 +67,22 @@
 struct intel_scu_ipc_pdata_t {
 	u32 i2c_base;
 	u32 i2c_len;
-	u8 irq_mode;
 };
 
 static const struct intel_scu_ipc_pdata_t intel_scu_ipc_lincroft_pdata = {
 	.i2c_base = 0xff12b000,
 	.i2c_len = 0x10,
-	.irq_mode = 0,
 };
 
 /* Penwell and Cloverview */
 static const struct intel_scu_ipc_pdata_t intel_scu_ipc_penwell_pdata = {
 	.i2c_base = 0xff12b000,
 	.i2c_len = 0x10,
-	.irq_mode = 1,
 };
 
 static const struct intel_scu_ipc_pdata_t intel_scu_ipc_tangier_pdata = {
 	.i2c_base  = 0xff00d000,
 	.i2c_len = 0x10,
-	.irq_mode = 0,
 };
 
 struct intel_scu_ipc_dev {
@@ -99,6 +95,9 @@
 
 static struct intel_scu_ipc_dev  ipcdev; /* Only one for now */
 
+#define IPC_STATUS		0x04
+#define IPC_STATUS_IRQ		BIT(2)
+
 /*
  * IPC Read Buffer (Read Only):
  * 16 byte buffer for receiving data from SCU, if IPC command
@@ -120,11 +119,8 @@
  */
 static inline void ipc_command(struct intel_scu_ipc_dev *scu, u32 cmd)
 {
-	if (scu->irq_mode) {
-		reinit_completion(&scu->cmd_complete);
-		writel(cmd | IPC_IOC, scu->ipc_base);
-	}
-	writel(cmd, scu->ipc_base);
+	reinit_completion(&scu->cmd_complete);
+	writel(cmd | IPC_IOC, scu->ipc_base);
 }
 
 /*
@@ -185,7 +181,7 @@
 	return 0;
 }
 
-/* Wait till ipc ioc interrupt is received or timeout in 3 HZ */
+/* Wait till ipc ioc interrupt is received or timeout in 10 HZ */
 static inline int ipc_wait_for_interrupt(struct intel_scu_ipc_dev *scu)
 {
 	int status;
@@ -610,9 +606,10 @@
 static irqreturn_t ioc(int irq, void *dev_id)
 {
 	struct intel_scu_ipc_dev *scu = dev_id;
+	int status = ipc_read_status(scu);
 
-	if (scu->irq_mode)
-		complete(&scu->cmd_complete);
+	writel(status | IPC_STATUS_IRQ, scu->ipc_base + IPC_STATUS);
+	complete(&scu->cmd_complete);
 
 	return IRQ_HANDLED;
 }
@@ -638,8 +635,6 @@
 	if (!pdata)
 		return -ENODEV;
 
-	scu->irq_mode = pdata->irq_mode;
-
 	err = pcim_enable_device(pdev);
 	if (err)
 		return err;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/intel_speed_select_if/isst_if_common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/intel_speed_select_if/isst_if_common.c
@@ -529,7 +529,10 @@
 	return ret;
 }
 
-static DEFINE_MUTEX(punit_misc_dev_lock);
+/* Lock to prevent module registration when already opened by user space */
+static DEFINE_MUTEX(punit_misc_dev_open_lock);
+/* Lock to allow one share misc device for all ISST interace */
+static DEFINE_MUTEX(punit_misc_dev_reg_lock);
 static int misc_usage_count;
 static int misc_device_ret;
 static int misc_device_open;
@@ -539,7 +542,7 @@
 	int i, ret = 0;
 
 	/* Fail open, if a module is going away */
-	mutex_lock(&punit_misc_dev_lock);
+	mutex_lock(&punit_misc_dev_open_lock);
 	for (i = 0; i < ISST_IF_DEV_MAX; ++i) {
 		struct isst_if_cmd_cb *cb = &punit_callbacks[i];
 
@@ -561,7 +564,7 @@
 	} else {
 		misc_device_open++;
 	}
-	mutex_unlock(&punit_misc_dev_lock);
+	mutex_unlock(&punit_misc_dev_open_lock);
 
 	return ret;
 }
@@ -570,7 +573,7 @@
 {
 	int i;
 
-	mutex_lock(&punit_misc_dev_lock);
+	mutex_lock(&punit_misc_dev_open_lock);
 	misc_device_open--;
 	for (i = 0; i < ISST_IF_DEV_MAX; ++i) {
 		struct isst_if_cmd_cb *cb = &punit_callbacks[i];
@@ -578,7 +581,7 @@
 		if (cb->registered)
 			module_put(cb->owner);
 	}
-	mutex_unlock(&punit_misc_dev_lock);
+	mutex_unlock(&punit_misc_dev_open_lock);
 
 	return 0;
 }
@@ -595,6 +598,43 @@
 	.fops		= &isst_if_char_driver_ops,
 };
 
+static int isst_misc_reg(void)
+{
+	mutex_lock(&punit_misc_dev_reg_lock);
+	if (misc_device_ret)
+		goto unlock_exit;
+
+	if (!misc_usage_count) {
+		misc_device_ret = isst_if_cpu_info_init();
+		if (misc_device_ret)
+			goto unlock_exit;
+
+		misc_device_ret = misc_register(&isst_if_char_driver);
+		if (misc_device_ret) {
+			isst_if_cpu_info_exit();
+			goto unlock_exit;
+		}
+	}
+	misc_usage_count++;
+
+unlock_exit:
+	mutex_unlock(&punit_misc_dev_reg_lock);
+
+	return misc_device_ret;
+}
+
+static void isst_misc_unreg(void)
+{
+	mutex_lock(&punit_misc_dev_reg_lock);
+	if (misc_usage_count)
+		misc_usage_count--;
+	if (!misc_usage_count && !misc_device_ret) {
+		misc_deregister(&isst_if_char_driver);
+		isst_if_cpu_info_exit();
+	}
+	mutex_unlock(&punit_misc_dev_reg_lock);
+}
+
 /**
  * isst_if_cdev_register() - Register callback for IOCTL
  * @device_type: The device type this callback handling.
@@ -612,38 +652,31 @@
  */
 int isst_if_cdev_register(int device_type, struct isst_if_cmd_cb *cb)
 {
-	if (misc_device_ret)
-		return misc_device_ret;
+	int ret;
 
 	if (device_type >= ISST_IF_DEV_MAX)
 		return -EINVAL;
 
-	mutex_lock(&punit_misc_dev_lock);
+	mutex_lock(&punit_misc_dev_open_lock);
+	/* Device is already open, we don't want to add new callbacks */
 	if (misc_device_open) {
-		mutex_unlock(&punit_misc_dev_lock);
+		mutex_unlock(&punit_misc_dev_open_lock);
 		return -EAGAIN;
 	}
-	if (!misc_usage_count) {
-		int ret;
-
-		misc_device_ret = misc_register(&isst_if_char_driver);
-		if (misc_device_ret)
-			goto unlock_exit;
-
-		ret = isst_if_cpu_info_init();
-		if (ret) {
-			misc_deregister(&isst_if_char_driver);
-			misc_device_ret = ret;
-			goto unlock_exit;
-		}
-	}
 	memcpy(&punit_callbacks[device_type], cb, sizeof(*cb));
 	punit_callbacks[device_type].registered = 1;
-	misc_usage_count++;
-unlock_exit:
-	mutex_unlock(&punit_misc_dev_lock);
+	mutex_unlock(&punit_misc_dev_open_lock);
 
-	return misc_device_ret;
+	ret = isst_misc_reg();
+	if (ret) {
+		/*
+		 * No need of mutex as the misc device register failed
+		 * as no one can open device yet. Hence no contention.
+		 */
+		punit_callbacks[device_type].registered = 0;
+		return ret;
+	}
+	return 0;
 }
 EXPORT_SYMBOL_GPL(isst_if_cdev_register);
 
@@ -658,16 +691,12 @@
  */
 void isst_if_cdev_unregister(int device_type)
 {
-	mutex_lock(&punit_misc_dev_lock);
-	misc_usage_count--;
+	isst_misc_unreg();
+	mutex_lock(&punit_misc_dev_open_lock);
 	punit_callbacks[device_type].registered = 0;
 	if (device_type == ISST_IF_DEV_MBOX)
 		isst_delete_hash();
-	if (!misc_usage_count && !misc_device_ret) {
-		misc_deregister(&isst_if_char_driver);
-		isst_if_cpu_info_exit();
-	}
-	mutex_unlock(&punit_misc_dev_lock);
+	mutex_unlock(&punit_misc_dev_open_lock);
 }
 EXPORT_SYMBOL_GPL(isst_if_cdev_unregister);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/intel_speed_select_if/isst_if_common.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/intel_speed_select_if/isst_if_common.h
@@ -13,6 +13,9 @@
 #define INTEL_RAPL_PRIO_DEVID_0	0x3451
 #define INTEL_CFG_MBOX_DEVID_0	0x3459
 
+#define INTEL_RAPL_PRIO_DEVID_1 0x3251
+#define INTEL_CFG_MBOX_DEVID_1  0x3259
+
 /*
  * Validate maximum commands in a single request.
  * This is enough to handle command to every core in one ioctl, or all
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/intel_speed_select_if/isst_if_mbox_pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/intel_speed_select_if/isst_if_mbox_pci.c
@@ -148,6 +148,7 @@
 
 static const struct pci_device_id isst_if_mbox_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, INTEL_CFG_MBOX_DEVID_0)},
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, INTEL_CFG_MBOX_DEVID_1)},
 	{ 0 },
 };
 MODULE_DEVICE_TABLE(pci, isst_if_mbox_ids);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/intel_speed_select_if/isst_if_mmio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/intel_speed_select_if/isst_if_mmio.c
@@ -72,6 +72,7 @@
 
 static const struct pci_device_id isst_if_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, INTEL_RAPL_PRIO_DEVID_0)},
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, INTEL_RAPL_PRIO_DEVID_1)},
 	{ 0 },
 };
 MODULE_DEVICE_TABLE(pci, isst_if_ids);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/intel_telemetry_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/intel_telemetry_core.c
@@ -102,7 +102,7 @@
 /**
  * telemetry_update_events() - Update telemetry Configuration
  * @pss_evtconfig: PSS related config. No change if num_evts = 0.
- * @pss_evtconfig: IOSS related config. No change if num_evts = 0.
+ * @ioss_evtconfig: IOSS related config. No change if num_evts = 0.
  *
  * This API updates the IOSS & PSS Telemetry configuration. Old config
  * is overwritten. Call telemetry_reset_events when logging is over
@@ -176,7 +176,7 @@
 /**
  * telemetry_get_eventconfig() - Returns the pss and ioss events enabled
  * @pss_evtconfig: Pointer to PSS related configuration.
- * @pss_evtconfig: Pointer to IOSS related configuration.
+ * @ioss_evtconfig: Pointer to IOSS related configuration.
  * @pss_len:	   Number of u32 elements allocated for pss_evtconfig array
  * @ioss_len:	   Number of u32 elements allocated for ioss_evtconfig array
  *
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/mlx-platform.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/mlx-platform.c
@@ -234,24 +234,6 @@
 };
 
 /* Platform hotplug devices */
-static struct i2c_board_info mlxplat_mlxcpld_psu[] = {
-	{
-		I2C_BOARD_INFO("24c02", 0x51),
-	},
-	{
-		I2C_BOARD_INFO("24c02", 0x50),
-	},
-};
-
-static struct i2c_board_info mlxplat_mlxcpld_ng_psu[] = {
-	{
-		I2C_BOARD_INFO("24c32", 0x51),
-	},
-	{
-		I2C_BOARD_INFO("24c32", 0x50),
-	},
-};
-
 static struct i2c_board_info mlxplat_mlxcpld_pwr[] = {
 	{
 		I2C_BOARD_INFO("dps460", 0x59),
@@ -282,15 +264,13 @@
 		.label = "psu1",
 		.reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
 		.mask = BIT(0),
-		.hpdev.brdinfo = &mlxplat_mlxcpld_psu[0],
-		.hpdev.nr = MLXPLAT_CPLD_PSU_DEFAULT_NR,
+		.hpdev.nr = MLXPLAT_CPLD_NR_NONE,
 	},
 	{
 		.label = "psu2",
 		.reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
 		.mask = BIT(1),
-		.hpdev.brdinfo = &mlxplat_mlxcpld_psu[1],
-		.hpdev.nr = MLXPLAT_CPLD_PSU_DEFAULT_NR,
+		.hpdev.nr = MLXPLAT_CPLD_NR_NONE,
 	},
 };
 
@@ -357,7 +337,7 @@
 		.aggr_mask = MLXPLAT_CPLD_AGGR_PSU_MASK_DEF,
 		.reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
 		.mask = MLXPLAT_CPLD_PSU_MASK,
-		.count = ARRAY_SIZE(mlxplat_mlxcpld_psu),
+		.count = ARRAY_SIZE(mlxplat_mlxcpld_default_psu_items_data),
 		.inversed = 1,
 		.health = false,
 	},
@@ -366,7 +346,7 @@
 		.aggr_mask = MLXPLAT_CPLD_AGGR_PWR_MASK_DEF,
 		.reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET,
 		.mask = MLXPLAT_CPLD_PWR_MASK,
-		.count = ARRAY_SIZE(mlxplat_mlxcpld_pwr),
+		.count = ARRAY_SIZE(mlxplat_mlxcpld_default_pwr_items_data),
 		.inversed = 0,
 		.health = false,
 	},
@@ -375,7 +355,7 @@
 		.aggr_mask = MLXPLAT_CPLD_AGGR_FAN_MASK_DEF,
 		.reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET,
 		.mask = MLXPLAT_CPLD_FAN_MASK,
-		.count = ARRAY_SIZE(mlxplat_mlxcpld_fan),
+		.count = ARRAY_SIZE(mlxplat_mlxcpld_default_fan_items_data),
 		.inversed = 1,
 		.health = false,
 	},
@@ -453,15 +433,13 @@
 		.label = "psu1",
 		.reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
 		.mask = BIT(0),
-		.hpdev.brdinfo = &mlxplat_mlxcpld_psu[0],
-		.hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR,
+		.hpdev.nr = MLXPLAT_CPLD_NR_NONE,
 	},
 	{
 		.label = "psu2",
 		.reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
 		.mask = BIT(1),
-		.hpdev.brdinfo = &mlxplat_mlxcpld_psu[1],
-		.hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR,
+		.hpdev.nr = MLXPLAT_CPLD_NR_NONE,
 	},
 };
 
@@ -611,15 +589,13 @@
 		.label = "psu1",
 		.reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
 		.mask = BIT(0),
-		.hpdev.brdinfo = &mlxplat_mlxcpld_ng_psu[0],
-		.hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR,
+		.hpdev.nr = MLXPLAT_CPLD_NR_NONE,
 	},
 	{
 		.label = "psu2",
 		.reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET,
 		.mask = BIT(1),
-		.hpdev.brdinfo = &mlxplat_mlxcpld_ng_psu[1],
-		.hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR,
+		.hpdev.nr = MLXPLAT_CPLD_NR_NONE,
 	},
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/msi-laptop.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/msi-laptop.c
@@ -210,7 +210,7 @@
 		return -EINVAL;
 
 	if (quirks->ec_read_only)
-		return -EOPNOTSUPP;
+		return 0;
 
 	/* read current device state */
 	result = ec_read(MSI_STANDARD_EC_COMMAND_ADDRESS, &rdata);
@@ -596,11 +596,10 @@
 	{
 		.ident = "MSI S270",
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD"),
+			DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "MS-1013"),
 			DMI_MATCH(DMI_PRODUCT_VERSION, "0131"),
-			DMI_MATCH(DMI_CHASSIS_VENDOR,
-				  "MICRO-STAR INT'L CO.,LTD")
+			DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-STAR INT")
 		},
 		.driver_data = &quirk_old_ec_model,
 		.callback = dmi_check_cb
@@ -633,8 +632,7 @@
 			DMI_MATCH(DMI_SYS_VENDOR, "NOTEBOOK"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "SAM2000"),
 			DMI_MATCH(DMI_PRODUCT_VERSION, "0131"),
-			DMI_MATCH(DMI_CHASSIS_VENDOR,
-				  "MICRO-STAR INT'L CO.,LTD")
+			DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-STAR INT")
 		},
 		.driver_data = &quirk_old_ec_model,
 		.callback = dmi_check_cb
@@ -843,15 +841,15 @@
 static void msi_init_rfkill(struct work_struct *ignored)
 {
 	if (rfk_wlan) {
-		rfkill_set_sw_state(rfk_wlan, !wlan_s);
+		msi_rfkill_set_state(rfk_wlan, !wlan_s);
 		rfkill_wlan_set(NULL, !wlan_s);
 	}
 	if (rfk_bluetooth) {
-		rfkill_set_sw_state(rfk_bluetooth, !bluetooth_s);
+		msi_rfkill_set_state(rfk_bluetooth, !bluetooth_s);
 		rfkill_bluetooth_set(NULL, !bluetooth_s);
 	}
 	if (rfk_threeg) {
-		rfkill_set_sw_state(rfk_threeg, !threeg_s);
+		msi_rfkill_set_state(rfk_threeg, !threeg_s);
 		rfkill_threeg_set(NULL, !threeg_s);
 	}
 }
@@ -1048,8 +1046,7 @@
 		return -EINVAL;
 
 	/* Register backlight stuff */
-
-	if (quirks->old_ec_model ||
+	if (quirks->old_ec_model &&
 	    acpi_video_get_backlight_type() == acpi_backlight_vendor) {
 		struct backlight_properties props;
 		memset(&props, 0, sizeof(struct backlight_properties));
@@ -1117,6 +1114,8 @@
 fail_create_group:
 	if (quirks->load_scm_model) {
 		i8042_remove_filter(msi_laptop_i8042_filter);
+		cancel_delayed_work_sync(&msi_touchpad_dwork);
+		input_unregister_device(msi_laptop_input_dev);
 		cancel_delayed_work_sync(&msi_rfkill_dwork);
 		cancel_work_sync(&msi_rfkill_work);
 		rfkill_cleanup();
@@ -1137,6 +1136,7 @@
 {
 	if (quirks->load_scm_model) {
 		i8042_remove_filter(msi_laptop_i8042_filter);
+		cancel_delayed_work_sync(&msi_touchpad_dwork);
 		input_unregister_device(msi_laptop_input_dev);
 		cancel_delayed_work_sync(&msi_rfkill_dwork);
 		cancel_work_sync(&msi_rfkill_work);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/mxm-wmi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/mxm-wmi.c
@@ -35,13 +35,11 @@
 		.xarg = 1,
 	};
 	struct acpi_buffer input = { (acpi_size)sizeof(args), &args };
-	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
 	acpi_status status;
 
 	printk("calling mux switch %d\n", adapter);
 
-	status = wmi_evaluate_method(MXM_WMMX_GUID, 0x0, adapter, &input,
-				     &output);
+	status = wmi_evaluate_method(MXM_WMMX_GUID, 0x0, adapter, &input, NULL);
 
 	if (ACPI_FAILURE(status))
 		return status;
@@ -60,13 +58,11 @@
 		.xarg = 1,
 	};
 	struct acpi_buffer input = { (acpi_size)sizeof(args), &args };
-	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
 	acpi_status status;
 
 	printk("calling mux switch %d\n", adapter);
 
-	status = wmi_evaluate_method(MXM_WMMX_GUID, 0x0, adapter, &input,
-				     &output);
+	status = wmi_evaluate_method(MXM_WMMX_GUID, 0x0, adapter, &input, NULL);
 
 	if (ACPI_FAILURE(status))
 		return status;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/pcengines-apuv2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/pcengines-apuv2.c
@@ -78,7 +78,6 @@
 	{ .name = "apu:green:1" },
 	{ .name = "apu:green:2" },
 	{ .name = "apu:green:3" },
-	{ .name = "apu:simswap" },
 };
 
 static const struct gpio_led_platform_data apu2_leds_pdata = {
@@ -95,8 +94,7 @@
 				NULL, 1, GPIO_ACTIVE_LOW),
 		GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_LED3,
 				NULL, 2, GPIO_ACTIVE_LOW),
-		GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_REG_SIMSWAP,
-				NULL, 3, GPIO_ACTIVE_LOW),
+		{} /* Terminating entry */
 	}
 };
 
@@ -126,6 +124,7 @@
 	.table = {
 		GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_MODESW,
 				NULL, 0, GPIO_ACTIVE_LOW),
+		{} /* Terminating entry */
 	}
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/peaq-wmi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/peaq-wmi.c
@@ -6,7 +6,7 @@
 
 #include <linux/acpi.h>
 #include <linux/dmi.h>
-#include <linux/input-polldev.h>
+#include <linux/input.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 
@@ -18,8 +18,7 @@
 
 MODULE_ALIAS("wmi:"PEAQ_DOLBY_BUTTON_GUID);
 
-static unsigned int peaq_ignore_events_counter;
-static struct input_polled_dev *peaq_poll_dev;
+static struct input_dev *peaq_poll_dev;
 
 /*
  * The Dolby button (yes really a Dolby button) causes an ACPI variable to get
@@ -28,8 +27,10 @@
  * (if polling after the release) or twice (polling between press and release).
  * We ignore events for 0.5s after the first event to avoid reporting 2 presses.
  */
-static void peaq_wmi_poll(struct input_polled_dev *dev)
+static void peaq_wmi_poll(struct input_dev *input_dev)
 {
+	static unsigned long last_event_time;
+	static bool had_events;
 	union acpi_object obj;
 	acpi_status status;
 	u32 dummy = 0;
@@ -44,22 +45,25 @@
 		return;
 
 	if (obj.type != ACPI_TYPE_INTEGER) {
-		dev_err(&peaq_poll_dev->input->dev,
+		dev_err(&input_dev->dev,
 			"Error WMBC did not return an integer\n");
 		return;
 	}
 
-	if (peaq_ignore_events_counter && peaq_ignore_events_counter--)
+	if (!obj.integer.value)
 		return;
 
-	if (obj.integer.value) {
-		input_event(peaq_poll_dev->input, EV_KEY, KEY_SOUND, 1);
-		input_sync(peaq_poll_dev->input);
-		input_event(peaq_poll_dev->input, EV_KEY, KEY_SOUND, 0);
-		input_sync(peaq_poll_dev->input);
-		peaq_ignore_events_counter = max(1u,
-			PEAQ_POLL_IGNORE_MS / peaq_poll_dev->poll_interval);
-	}
+	if (had_events && time_before(jiffies, last_event_time +
+					msecs_to_jiffies(PEAQ_POLL_IGNORE_MS)))
+		return;
+
+	input_event(input_dev, EV_KEY, KEY_SOUND, 1);
+	input_sync(input_dev);
+	input_event(input_dev, EV_KEY, KEY_SOUND, 0);
+	input_sync(input_dev);
+
+	last_event_time = jiffies;
+	had_events = true;
 }
 
 /* Some other devices (Shuttle XS35) use the same WMI GUID for other purposes */
@@ -75,6 +79,8 @@
 
 static int __init peaq_wmi_init(void)
 {
+	int err;
+
 	/* WMI GUID is not unique, also check for a DMI match */
 	if (!dmi_check_system(peaq_dmi_table))
 		return -ENODEV;
@@ -82,24 +88,36 @@
 	if (!wmi_has_guid(PEAQ_DOLBY_BUTTON_GUID))
 		return -ENODEV;
 
-	peaq_poll_dev = input_allocate_polled_device();
+	peaq_poll_dev = input_allocate_device();
 	if (!peaq_poll_dev)
 		return -ENOMEM;
 
-	peaq_poll_dev->poll = peaq_wmi_poll;
-	peaq_poll_dev->poll_interval = PEAQ_POLL_INTERVAL_MS;
-	peaq_poll_dev->poll_interval_max = PEAQ_POLL_MAX_MS;
-	peaq_poll_dev->input->name = "PEAQ WMI hotkeys";
-	peaq_poll_dev->input->phys = "wmi/input0";
-	peaq_poll_dev->input->id.bustype = BUS_HOST;
-	input_set_capability(peaq_poll_dev->input, EV_KEY, KEY_SOUND);
-
-	return input_register_polled_device(peaq_poll_dev);
+	peaq_poll_dev->name = "PEAQ WMI hotkeys";
+	peaq_poll_dev->phys = "wmi/input0";
+	peaq_poll_dev->id.bustype = BUS_HOST;
+	input_set_capability(peaq_poll_dev, EV_KEY, KEY_SOUND);
+
+	err = input_setup_polling(peaq_poll_dev, peaq_wmi_poll);
+	if (err)
+		goto err_out;
+
+	input_set_poll_interval(peaq_poll_dev, PEAQ_POLL_INTERVAL_MS);
+	input_set_max_poll_interval(peaq_poll_dev, PEAQ_POLL_MAX_MS);
+
+	err = input_register_device(peaq_poll_dev);
+	if (err)
+		goto err_out;
+
+	return 0;
+
+err_out:
+	input_free_device(peaq_poll_dev);
+	return err;
 }
 
 static void __exit peaq_wmi_exit(void)
 {
-	input_unregister_polled_device(peaq_poll_dev);
+	input_unregister_device(peaq_poll_dev);
 }
 
 module_init(peaq_wmi_init);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/pmc_atom.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/pmc_atom.c
@@ -244,7 +244,7 @@
 	pm1_cnt_port = acpi_base_addr + PM1_CNT;
 
 	pm1_cnt_value = inl(pm1_cnt_port);
-	pm1_cnt_value &= SLEEP_TYPE_MASK;
+	pm1_cnt_value &= ~SLEEP_TYPE_MASK;
 	pm1_cnt_value |= SLEEP_TYPE_S5;
 	pm1_cnt_value |= SLEEP_ENABLE;
 
@@ -385,34 +385,18 @@
 	},
 	{
 		/* pmc_plt_clk* - are used for ethernet controllers */
-		.ident = "Beckhoff CB3163",
+		.ident = "Lex 2I385SW",
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Beckhoff Automation"),
-			DMI_MATCH(DMI_BOARD_NAME, "CB3163"),
-		},
-	},
-	{
-		/* pmc_plt_clk* - are used for ethernet controllers */
-		.ident = "Beckhoff CB4063",
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Beckhoff Automation"),
-			DMI_MATCH(DMI_BOARD_NAME, "CB4063"),
-		},
-	},
-	{
-		/* pmc_plt_clk* - are used for ethernet controllers */
-		.ident = "Beckhoff CB6263",
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Beckhoff Automation"),
-			DMI_MATCH(DMI_BOARD_NAME, "CB6263"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Lex BayTrail"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "2I385SW"),
 		},
 	},
 	{
 		/* pmc_plt_clk* - are used for ethernet controllers */
-		.ident = "Beckhoff CB6363",
+		.ident = "Beckhoff Baytrail",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Beckhoff Automation"),
-			DMI_MATCH(DMI_BOARD_NAME, "CB6363"),
+			DMI_MATCH(DMI_PRODUCT_FAMILY, "CBxx63"),
 		},
 	},
 	{
@@ -429,6 +413,14 @@
 			DMI_MATCH(DMI_PRODUCT_VERSION, "6AV7882-0"),
 		},
 	},
+	{
+		.ident = "CONNECT X300",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "SIEMENS AG"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "A5E45074588"),
+		},
+	},
+
 	{ /*sentinel*/ }
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/samsung-laptop.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/samsung-laptop.c
@@ -1121,8 +1121,6 @@
 
 	if (value > samsung->kbd_led.max_brightness)
 		value = samsung->kbd_led.max_brightness;
-	else if (value < 0)
-		value = 0;
 
 	samsung->kbd_led_wk = value;
 	queue_work(samsung->led_workqueue, &samsung->kbd_led_work);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/sony-laptop.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/sony-laptop.c
@@ -1899,14 +1899,21 @@
 		break;
 	}
 
-	ret = sony_call_snc_handle(handle, probe_base, &result);
-	if (ret)
-		return ret;
+	/*
+	 * Only probe if there is a separate probe_base, otherwise the probe call
+	 * is equivalent to __sony_nc_kbd_backlight_mode_set(0), resulting in
+	 * the keyboard backlight being turned off.
+	 */
+	if (probe_base) {
+		ret = sony_call_snc_handle(handle, probe_base, &result);
+		if (ret)
+			return ret;
 
-	if ((handle == 0x0137 && !(result & 0x02)) ||
-			!(result & 0x01)) {
-		dprintk("no backlight keyboard found\n");
-		return 0;
+		if ((handle == 0x0137 && !(result & 0x02)) ||
+				!(result & 0x01)) {
+			dprintk("no backlight keyboard found\n");
+			return 0;
+		}
 	}
 
 	kbdbl_ctl = kzalloc(sizeof(*kbdbl_ctl), GFP_KERNEL);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/thinkpad_acpi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/thinkpad_acpi.c
@@ -1188,15 +1188,6 @@
 	return status;
 }
 
-/* Query FW and update rfkill sw state for all rfkill switches */
-static void tpacpi_rfk_update_swstate_all(void)
-{
-	unsigned int i;
-
-	for (i = 0; i < TPACPI_RFK_SW_MAX; i++)
-		tpacpi_rfk_update_swstate(tpacpi_rfkill_switches[i]);
-}
-
 /*
  * Sync the HW-blocking state of all rfkill switches,
  * do notice it causes the rfkill core to schedule uevents
@@ -2587,7 +2578,7 @@
  */
 static int hotkey_kthread(void *data)
 {
-	struct tp_nvram_state s[2];
+	struct tp_nvram_state s[2] = { 0 };
 	u32 poll_mask, event_mask;
 	unsigned int si, so;
 	unsigned long t;
@@ -3135,9 +3126,6 @@
 	if (wlsw == TPACPI_RFK_RADIO_OFF)
 		tpacpi_rfk_update_hwblock_state(true);
 
-	/* Sync sw blocking state */
-	tpacpi_rfk_update_swstate_all();
-
 	/* Sync hw blocking state last if it is hw-unblocked */
 	if (wlsw == TPACPI_RFK_RADIO_ON)
 		tpacpi_rfk_update_hwblock_state(false);
@@ -3232,7 +3220,14 @@
 
 		in_tablet_mode = hotkey_gmms_get_tablet_mode(res,
 							     &has_tablet_mode);
-		if (has_tablet_mode)
+		/*
+		 * The Yoga 11e series has 2 accelerometers described by a
+		 * BOSC0200 ACPI node. This setup relies on a Windows service
+		 * which calls special ACPI methods on this node to report
+		 * the laptop/tent/tablet mode to the EC. The bmc150 iio driver
+		 * does not support this, so skip the hotkey on these models.
+		 */
+		if (has_tablet_mode && !acpi_dev_present("BOSC0200", "1", -1))
 			tp_features.hotkey_tablet = TP_HOTKEY_TABLET_USES_GMMS;
 		type = "GMMS";
 	} else if (acpi_evalf(hkey_handle, &res, "MHKG", "qd")) {
@@ -4082,13 +4077,19 @@
 
 	case TP_HKEY_EV_KEY_NUMLOCK:
 	case TP_HKEY_EV_KEY_FN:
-	case TP_HKEY_EV_KEY_FN_ESC:
 		/* key press events, we just ignore them as long as the EC
 		 * is still reporting them in the normal keyboard stream */
 		*send_acpi_ev = false;
 		*ignore_acpi_ev = true;
 		return true;
 
+	case TP_HKEY_EV_KEY_FN_ESC:
+		/* Get the media key status to foce the status LED to update */
+		acpi_evalf(hkey_handle, NULL, "GMKS", "v");
+		*send_acpi_ev = false;
+		*ignore_acpi_ev = true;
+		return true;
+
 	case TP_HKEY_EV_TABLET_CHANGED:
 		tpacpi_input_send_tabletsw();
 		hotkey_tablet_mode_notify_change();
@@ -4238,6 +4239,7 @@
 		pr_err("error while attempting to reset the event firmware interface\n");
 
 	tpacpi_send_radiosw_update();
+	tpacpi_input_send_tabletsw();
 	hotkey_tablet_mode_notify_change();
 	hotkey_wakeup_reason_notify_change();
 	hotkey_wakeup_hotunplug_complete_notify_change();
@@ -6270,6 +6272,7 @@
 enum { /* TPACPI_THERMAL_TPEC_* */
 	TP_EC_THERMAL_TMP0 = 0x78,	/* ACPI EC regs TMP 0..7 */
 	TP_EC_THERMAL_TMP8 = 0xC0,	/* ACPI EC regs TMP 8..15 */
+	TP_EC_FUNCREV      = 0xEF,      /* ACPI EC Functional revision */
 	TP_EC_THERMAL_TMP_NA = -128,	/* ACPI EC sensor not available */
 
 	TPACPI_THERMAL_SENSOR_NA = -128000, /* Sensor not available */
@@ -6468,7 +6471,7 @@
 
 static int __init thermal_init(struct ibm_init_struct *iibm)
 {
-	u8 t, ta1, ta2;
+	u8 t, ta1, ta2, ver = 0;
 	int i;
 	int acpi_tmp7;
 	int res;
@@ -6483,7 +6486,14 @@
 		 * 0x78-0x7F, 0xC0-0xC7.  Registers return 0x00 for
 		 * non-implemented, thermal sensors return 0x80 when
 		 * not available
+		 * The above rule is unfortunately flawed. This has been seen with
+		 * 0xC2 (power supply ID) causing thermal control problems.
+		 * The EC version can be determined by offset 0xEF and at least for
+		 * version 3 the Lenovo firmware team confirmed that registers 0xC0-0xC7
+		 * are not thermal registers.
 		 */
+		if (!acpi_ec_read(TP_EC_FUNCREV, &ver))
+			pr_warn("Thinkpad ACPI EC unable to access EC version\n");
 
 		ta1 = ta2 = 0;
 		for (i = 0; i < 8; i++) {
@@ -6493,11 +6503,13 @@
 				ta1 = 0;
 				break;
 			}
-			if (acpi_ec_read(TP_EC_THERMAL_TMP8 + i, &t)) {
-				ta2 |= t;
-			} else {
-				ta1 = 0;
-				break;
+			if (ver < 3) {
+				if (acpi_ec_read(TP_EC_THERMAL_TMP8 + i, &t)) {
+					ta2 |= t;
+				} else {
+					ta1 = 0;
+					break;
+				}
 			}
 		}
 		if (ta1 == 0) {
@@ -6510,9 +6522,12 @@
 				thermal_read_mode = TPACPI_THERMAL_NONE;
 			}
 		} else {
-			thermal_read_mode =
-			    (ta2 != 0) ?
-			    TPACPI_THERMAL_TPEC_16 : TPACPI_THERMAL_TPEC_8;
+			if (ver >= 3)
+				thermal_read_mode = TPACPI_THERMAL_TPEC_8;
+			else
+				thermal_read_mode =
+					(ta2 != 0) ?
+					TPACPI_THERMAL_TPEC_16 : TPACPI_THERMAL_TPEC_8;
 		}
 	} else if (acpi_tmp7) {
 		if (tpacpi_is_ibm() &&
@@ -6863,8 +6878,10 @@
 	list_for_each_entry(child, &device->children, node) {
 		acpi_status status = acpi_evaluate_object(child->handle, "_BCL",
 							  NULL, &buffer);
-		if (ACPI_FAILURE(status))
+		if (ACPI_FAILURE(status)) {
+			buffer.length = ACPI_ALLOCATE_BUFFER;
 			continue;
+		}
 
 		obj = (union acpi_object *)buffer.pointer;
 		if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) {
@@ -6997,10 +7014,13 @@
 			pr_warn("Cannot enable backlight brightness support, ACPI is already handling it.  Refer to the acpi_backlight kernel parameter.\n");
 			return 1;
 		}
-	} else if (tp_features.bright_acpimode && brightness_enable > 1) {
-		pr_notice("Standard ACPI backlight interface not available, thinkpad_acpi native brightness control enabled\n");
+	} else if (!tp_features.bright_acpimode) {
+		pr_notice("ACPI backlight interface not available\n");
+		return 1;
 	}
 
+	pr_notice("ACPI native brightness control enabled\n");
+
 	/*
 	 * Check for module parameter bogosity, note that we
 	 * init brightness_mode to TPACPI_BRGHT_MODE_MAX in order to be
@@ -9057,7 +9077,7 @@
 
 	if (strlencmp(cmd, "level auto") == 0)
 		level = TP_EC_FAN_AUTO;
-	else if ((strlencmp(cmd, "level disengaged") == 0) |
+	else if ((strlencmp(cmd, "level disengaged") == 0) ||
 			(strlencmp(cmd, "level full-speed") == 0))
 		level = TP_EC_FAN_FULLSPEED;
 	else if (sscanf(cmd, "level %d", &level) != 1)
@@ -9682,11 +9702,14 @@
 	 * Individual addressing is broken on models that expose the
 	 * primary battery as BAT1.
 	 */
+	TPACPI_Q_LNV('G', '8', true),       /* ThinkPad X131e */
+	TPACPI_Q_LNV('8', 'F', true),       /* Thinkpad X120e */
 	TPACPI_Q_LNV('J', '7', true),       /* B5400 */
 	TPACPI_Q_LNV('J', 'I', true),       /* Thinkpad 11e */
 	TPACPI_Q_LNV3('R', '0', 'B', true), /* Thinkpad 11e gen 3 */
 	TPACPI_Q_LNV3('R', '0', 'C', true), /* Thinkpad 13 */
 	TPACPI_Q_LNV3('R', '0', 'J', true), /* Thinkpad 13 gen 2 */
+	TPACPI_Q_LNV3('R', '0', 'K', true), /* Thinkpad 11e gen 4 celeron BIOS */
 };
 
 static int __init tpacpi_battery_init(struct ibm_init_struct *ibm)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/toshiba_acpi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/toshiba_acpi.c
@@ -1485,7 +1485,7 @@
 	struct toshiba_acpi_dev *dev = PDE_DATA(file_inode(file));
 	char *buffer;
 	char *cmd;
-	int lcd_out, crt_out, tv_out;
+	int lcd_out = -1, crt_out = -1, tv_out = -1;
 	int remain = count;
 	int value;
 	int ret;
@@ -1517,7 +1517,6 @@
 
 	kfree(cmd);
 
-	lcd_out = crt_out = tv_out = -1;
 	ret = get_video_status(dev, &video_out);
 	if (!ret) {
 		unsigned int new_video_out = video_out;
@@ -2842,6 +2841,7 @@
 
 	if (!dev->info_supported && !dev->system_event_supported) {
 		pr_warn("No hotkey query interface found\n");
+		error = -EINVAL;
 		goto err_remove_filter;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/touchscreen_dmi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/touchscreen_dmi.c
@@ -169,6 +169,23 @@
 	.properties     = connect_tablet9_props,
 };
 
+static const struct property_entry csl_panther_tab_hd_props[] = {
+	PROPERTY_ENTRY_U32("touchscreen-min-x", 1),
+	PROPERTY_ENTRY_U32("touchscreen-min-y", 20),
+	PROPERTY_ENTRY_U32("touchscreen-size-x", 1980),
+	PROPERTY_ENTRY_U32("touchscreen-size-y", 1526),
+	PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
+	PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
+	PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-csl-panther-tab-hd.fw"),
+	PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+	{ }
+};
+
+static const struct ts_dmi_data csl_panther_tab_hd_data = {
+	.acpi_name      = "MSSL1680:00",
+	.properties     = csl_panther_tab_hd_props,
+};
+
 static const struct property_entry cube_iwork8_air_props[] = {
 	PROPERTY_ENTRY_U32("touchscreen-min-x", 1),
 	PROPERTY_ENTRY_U32("touchscreen-min-y", 3),
@@ -215,6 +232,22 @@
 	.properties	= dexp_ursus_7w_props,
 };
 
+static const struct property_entry dexp_ursus_kx210i_props[] = {
+	PROPERTY_ENTRY_U32("touchscreen-min-x", 5),
+	PROPERTY_ENTRY_U32("touchscreen-min-y",  2),
+	PROPERTY_ENTRY_U32("touchscreen-size-x", 1720),
+	PROPERTY_ENTRY_U32("touchscreen-size-y", 1137),
+	PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-dexp-ursus-kx210i.fw"),
+	PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+	PROPERTY_ENTRY_BOOL("silead,home-button"),
+	{ }
+};
+
+static const struct ts_dmi_data dexp_ursus_kx210i_data = {
+	.acpi_name	= "MSSL1680:00",
+	.properties	= dexp_ursus_kx210i_props,
+};
+
 static const struct property_entry digma_citi_e200_props[] = {
 	PROPERTY_ENTRY_U32("touchscreen-size-x", 1980),
 	PROPERTY_ENTRY_U32("touchscreen-size-y", 1500),
@@ -231,6 +264,16 @@
 	.properties	= digma_citi_e200_props,
 };
 
+static const struct property_entry estar_beauty_hd_props[] = {
+	PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
+	{ }
+};
+
+static const struct ts_dmi_data estar_beauty_hd_data = {
+	.acpi_name	= "GDIX1001:00",
+	.properties	= estar_beauty_hd_props,
+};
+
 static const struct property_entry gp_electronic_t701_props[] = {
 	PROPERTY_ENTRY_U32("touchscreen-size-x", 960),
 	PROPERTY_ENTRY_U32("touchscreen-size-y", 640),
@@ -264,6 +307,21 @@
 	.properties	= irbis_tw90_props,
 };
 
+static const struct property_entry irbis_tw118_props[] = {
+	PROPERTY_ENTRY_U32("touchscreen-min-x", 20),
+	PROPERTY_ENTRY_U32("touchscreen-min-y", 30),
+	PROPERTY_ENTRY_U32("touchscreen-size-x", 1960),
+	PROPERTY_ENTRY_U32("touchscreen-size-y", 1510),
+	PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-irbis-tw118.fw"),
+	PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+	{ }
+};
+
+static const struct ts_dmi_data irbis_tw118_data = {
+	.acpi_name	= "MSSL1680:00",
+	.properties	= irbis_tw118_props,
+};
+
 static const struct property_entry itworks_tw891_props[] = {
 	PROPERTY_ENTRY_U32("touchscreen-min-x", 1),
 	PROPERTY_ENTRY_U32("touchscreen-min-y", 5),
@@ -697,6 +755,14 @@
 		},
 	},
 	{
+		/* CSL Panther Tab HD */
+		.driver_data = (void *)&csl_panther_tab_hd_data,
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "CSL Computer GmbH & Co. KG"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "CSL Panther Tab HD"),
+		},
+	},
+	{
 		/* CUBE iwork8 Air */
 		.driver_data = (void *)&cube_iwork8_air_data,
 		.matches = {
@@ -724,6 +790,14 @@
 		},
 	},
 	{
+		/* DEXP Ursus KX210i */
+		.driver_data = (void *)&dexp_ursus_kx210i_data,
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "INSYDE Corp."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "S107I"),
+		},
+	},
+	{
 		/* Digma Citi E200 */
 		.driver_data = (void *)&digma_citi_e200_data,
 		.matches = {
@@ -733,6 +807,14 @@
 		},
 	},
 	{
+		/* Estar Beauty HD (MID 7316R) */
+		.driver_data = (void *)&estar_beauty_hd_data,
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Estar"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "eSTAR BEAUTY HD Intel Quad core"),
+		},
+	},
+	{
 		/* GP-electronic T701 */
 		.driver_data = (void *)&gp_electronic_t701_data,
 		.matches = {
@@ -759,6 +841,14 @@
 		},
 	},
 	{
+		/* Irbis TW118 */
+		.driver_data = (void *)&irbis_tw118_data,
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "IRBIS"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "TW118"),
+		},
+	},
+	{
 		/* I.T.Works TW891 */
 		.driver_data = (void *)&itworks_tw891_data,
 		.matches = {
@@ -798,6 +888,14 @@
 		},
 	},
 	{
+		/* Mediacom WinPad 7.0 W700 (same hw as Wintron surftab 7") */
+		.driver_data = (void *)&trekstor_surftab_wintron70_data,
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "MEDIACOM"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "WinPad 7 W10 - WPW700"),
+		},
+	},
+	{
 		/* Mediacom Flexbook Edge 11 (same hw as TS Primebook C11) */
 		.driver_data = (void *)&trekstor_primebook_c11_data,
 		.matches = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/wmi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/wmi.c
@@ -39,7 +39,7 @@
 static LIST_HEAD(wmi_block_list);
 
 struct guid_block {
-	char guid[16];
+	guid_t guid;
 	union {
 		char object_id[2];
 		struct {
@@ -110,17 +110,17 @@
 
 static bool find_guid(const char *guid_string, struct wmi_block **out)
 {
-	uuid_le guid_input;
+	guid_t guid_input;
 	struct wmi_block *wblock;
 	struct guid_block *block;
 
-	if (uuid_le_to_bin(guid_string, &guid_input))
+	if (guid_parse(guid_string, &guid_input))
 		return false;
 
 	list_for_each_entry(wblock, &wmi_block_list, list) {
 		block = &wblock->gblock;
 
-		if (memcmp(block->guid, &guid_input, 16) == 0) {
+		if (guid_equal(&block->guid, &guid_input)) {
 			if (out)
 				*out = wblock;
 			return true;
@@ -129,11 +129,20 @@
 	return false;
 }
 
+static bool guid_parse_and_compare(const char *string, const guid_t *guid)
+{
+	guid_t guid_input;
+
+	if (guid_parse(string, &guid_input))
+		return false;
+
+	return guid_equal(&guid_input, guid);
+}
+
 static const void *find_guid_context(struct wmi_block *wblock,
 				      struct wmi_driver *wdriver)
 {
 	const struct wmi_device_id *id;
-	uuid_le guid_input;
 
 	if (wblock == NULL || wdriver == NULL)
 		return NULL;
@@ -142,9 +151,7 @@
 
 	id = wdriver->id_table;
 	while (*id->guid_string) {
-		if (uuid_le_to_bin(id->guid_string, &guid_input))
-			continue;
-		if (!memcmp(wblock->gblock.guid, &guid_input, 16))
+		if (guid_parse_and_compare(id->guid_string, &wblock->gblock.guid))
 			return id->context;
 		id++;
 	}
@@ -177,7 +184,7 @@
 
 static acpi_status wmi_method_enable(struct wmi_block *wblock, int enable)
 {
-	struct guid_block *block = NULL;
+	struct guid_block *block;
 	char method[5];
 	acpi_status status;
 	acpi_handle handle;
@@ -251,8 +258,8 @@
 acpi_status wmidev_evaluate_method(struct wmi_device *wdev, u8 instance,
 	u32 method_id, const struct acpi_buffer *in, struct acpi_buffer *out)
 {
-	struct guid_block *block = NULL;
-	struct wmi_block *wblock = NULL;
+	struct guid_block *block;
+	struct wmi_block *wblock;
 	acpi_handle handle;
 	acpi_status status;
 	struct acpi_object_list input;
@@ -299,7 +306,7 @@
 static acpi_status __query_block(struct wmi_block *wblock, u8 instance,
 				 struct acpi_buffer *out)
 {
-	struct guid_block *block = NULL;
+	struct guid_block *block;
 	acpi_handle handle;
 	acpi_status status, wc_status = AE_ERROR;
 	struct acpi_object_list input;
@@ -353,7 +360,14 @@
 	 * the WQxx method failed - we should disable collection anyway.
 	 */
 	if ((block->flags & ACPI_WMI_EXPENSIVE) && ACPI_SUCCESS(wc_status)) {
-		status = acpi_execute_simple_method(handle, wc_method, 0);
+		/*
+		 * Ignore whether this WCxx call succeeds or not since
+		 * the previously executed WQxx method call might have
+		 * succeeded, and returning the failing status code
+		 * of this call would throw away the result of the WQxx
+		 * call, potentially leaking memory.
+		 */
+		acpi_execute_simple_method(handle, wc_method, 0);
 	}
 
 	return status;
@@ -405,8 +419,8 @@
 acpi_status wmi_set_block(const char *guid_string, u8 instance,
 			  const struct acpi_buffer *in)
 {
-	struct guid_block *block = NULL;
 	struct wmi_block *wblock = NULL;
+	struct guid_block *block;
 	acpi_handle handle;
 	struct acpi_object_list input;
 	union acpi_object params[2];
@@ -449,7 +463,7 @@
 
 static void wmi_dump_wdg(const struct guid_block *g)
 {
-	pr_info("%pUL:\n", g->guid);
+	pr_info("%pUL:\n", &g->guid);
 	if (g->flags & ACPI_WMI_EVENT)
 		pr_info("\tnotify_id: 0x%02X\n", g->notify_id);
 	else
@@ -519,18 +533,18 @@
 {
 	struct wmi_block *block;
 	acpi_status status = AE_NOT_EXIST;
-	uuid_le guid_input;
+	guid_t guid_input;
 
 	if (!guid || !handler)
 		return AE_BAD_PARAMETER;
 
-	if (uuid_le_to_bin(guid, &guid_input))
+	if (guid_parse(guid, &guid_input))
 		return AE_BAD_PARAMETER;
 
 	list_for_each_entry(block, &wmi_block_list, list) {
 		acpi_status wmi_status;
 
-		if (memcmp(block->gblock.guid, &guid_input, 16) == 0) {
+		if (guid_equal(&block->gblock.guid, &guid_input)) {
 			if (block->handler &&
 			    block->handler != wmi_notify_debug)
 				return AE_ALREADY_ACQUIRED;
@@ -558,18 +572,18 @@
 {
 	struct wmi_block *block;
 	acpi_status status = AE_NOT_EXIST;
-	uuid_le guid_input;
+	guid_t guid_input;
 
 	if (!guid)
 		return AE_BAD_PARAMETER;
 
-	if (uuid_le_to_bin(guid, &guid_input))
+	if (guid_parse(guid, &guid_input))
 		return AE_BAD_PARAMETER;
 
 	list_for_each_entry(block, &wmi_block_list, list) {
 		acpi_status wmi_status;
 
-		if (memcmp(block->gblock.guid, &guid_input, 16) == 0) {
+		if (guid_equal(&block->gblock.guid, &guid_input)) {
 			if (!block->handler ||
 			    block->handler == wmi_notify_debug)
 				return AE_NULL_ENTRY;
@@ -605,7 +619,6 @@
 {
 	struct acpi_object_list input;
 	union acpi_object params[1];
-	struct guid_block *gblock;
 	struct wmi_block *wblock;
 
 	input.count = 1;
@@ -614,7 +627,7 @@
 	params[0].integer.value = event;
 
 	list_for_each_entry(wblock, &wmi_block_list, list) {
-		gblock = &wblock->gblock;
+		struct guid_block *gblock = &wblock->gblock;
 
 		if ((gblock->flags & ACPI_WMI_EVENT) &&
 			(gblock->notify_id == event))
@@ -675,7 +688,7 @@
 {
 	struct wmi_block *wblock = dev_to_wblock(dev);
 
-	return sprintf(buf, "wmi:%pUL\n", wblock->gblock.guid);
+	return sprintf(buf, "wmi:%pUL\n", &wblock->gblock.guid);
 }
 static DEVICE_ATTR_RO(modalias);
 
@@ -684,7 +697,7 @@
 {
 	struct wmi_block *wblock = dev_to_wblock(dev);
 
-	return sprintf(buf, "%pUL\n", wblock->gblock.guid);
+	return sprintf(buf, "%pUL\n", &wblock->gblock.guid);
 }
 static DEVICE_ATTR_RO(guid);
 
@@ -767,10 +780,10 @@
 {
 	struct wmi_block *wblock = dev_to_wblock(dev);
 
-	if (add_uevent_var(env, "MODALIAS=wmi:%pUL", wblock->gblock.guid))
+	if (add_uevent_var(env, "MODALIAS=wmi:%pUL", &wblock->gblock.guid))
 		return -ENOMEM;
 
-	if (add_uevent_var(env, "WMI_GUID=%pUL", wblock->gblock.guid))
+	if (add_uevent_var(env, "WMI_GUID=%pUL", &wblock->gblock.guid))
 		return -ENOMEM;
 
 	return 0;
@@ -794,11 +807,7 @@
 		return 0;
 
 	while (*id->guid_string) {
-		uuid_le driver_guid;
-
-		if (WARN_ON(uuid_le_to_bin(id->guid_string, &driver_guid)))
-			continue;
-		if (!memcmp(&driver_guid, wblock->gblock.guid, 16))
+		if (guid_parse_and_compare(id->guid_string, &wblock->gblock.guid))
 			return 1;
 
 		id++;
@@ -808,21 +817,13 @@
 }
 static int wmi_char_open(struct inode *inode, struct file *filp)
 {
-	const char *driver_name = filp->f_path.dentry->d_iname;
-	struct wmi_block *wblock = NULL;
-	struct wmi_block *next = NULL;
-
-	list_for_each_entry_safe(wblock, next, &wmi_block_list, list) {
-		if (!wblock->dev.dev.driver)
-			continue;
-		if (strcmp(driver_name, wblock->dev.dev.driver->name) == 0) {
-			filp->private_data = wblock;
-			break;
-		}
-	}
+	/*
+	 * The miscdevice already stores a pointer to itself
+	 * inside filp->private_data
+	 */
+	struct wmi_block *wblock = container_of(filp->private_data, struct wmi_block, char_dev);
 
-	if (!filp->private_data)
-		return -ENODEV;
+	filp->private_data = wblock;
 
 	return nonseekable_open(inode, filp);
 }
@@ -842,8 +843,8 @@
 	struct wmi_ioctl_buffer __user *input =
 		(struct wmi_ioctl_buffer __user *) arg;
 	struct wmi_block *wblock = filp->private_data;
-	struct wmi_ioctl_buffer *buf = NULL;
-	struct wmi_driver *wdriver = NULL;
+	struct wmi_ioctl_buffer *buf;
+	struct wmi_driver *wdriver;
 	int ret;
 
 	if (_IOC_TYPE(cmd) != WMI_IOC)
@@ -1032,7 +1033,6 @@
 };
 
 static int wmi_create_device(struct device *wmi_bus_dev,
-			     const struct guid_block *gblock,
 			     struct wmi_block *wblock,
 			     struct acpi_device *device)
 {
@@ -1040,12 +1040,12 @@
 	char method[5];
 	int result;
 
-	if (gblock->flags & ACPI_WMI_EVENT) {
+	if (wblock->gblock.flags & ACPI_WMI_EVENT) {
 		wblock->dev.dev.type = &wmi_type_event;
 		goto out_init;
 	}
 
-	if (gblock->flags & ACPI_WMI_METHOD) {
+	if (wblock->gblock.flags & ACPI_WMI_METHOD) {
 		wblock->dev.dev.type = &wmi_type_method;
 		mutex_init(&wblock->char_mutex);
 		goto out_init;
@@ -1095,7 +1095,7 @@
 	wblock->dev.dev.bus = &wmi_bus_type;
 	wblock->dev.dev.parent = wmi_bus_dev;
 
-	dev_set_name(&wblock->dev.dev, "%pUL", gblock->guid);
+	dev_set_name(&wblock->dev.dev, "%pUL", &wblock->gblock.guid);
 
 	device_initialize(&wblock->dev.dev);
 
@@ -1115,13 +1115,12 @@
 	}
 }
 
-static bool guid_already_parsed(struct acpi_device *device,
-				const u8 *guid)
+static bool guid_already_parsed(struct acpi_device *device, const guid_t *guid)
 {
 	struct wmi_block *wblock;
 
 	list_for_each_entry(wblock, &wmi_block_list, list) {
-		if (memcmp(wblock->gblock.guid, guid, 16) == 0) {
+		if (guid_equal(&wblock->gblock.guid, guid)) {
 			/*
 			 * Because we historically didn't track the relationship
 			 * between GUIDs and ACPI nodes, we don't know whether
@@ -1147,8 +1146,8 @@
 	struct wmi_block *wblock, *next;
 	union acpi_object *obj;
 	acpi_status status;
-	int retval = 0;
 	u32 i, total;
+	int retval;
 
 	status = acpi_evaluate_object(device->handle, "_WDG", NULL, &out);
 	if (ACPI_FAILURE(status))
@@ -1159,8 +1158,8 @@
 		return -ENXIO;
 
 	if (obj->type != ACPI_TYPE_BUFFER) {
-		retval = -ENXIO;
-		goto out_free_pointer;
+		kfree(obj);
+		return -ENXIO;
 	}
 
 	gblock = (const struct guid_block *)obj->buffer.pointer;
@@ -1176,19 +1175,19 @@
 		 * case yet, so for now, we'll just ignore the duplicate
 		 * for device creation.
 		 */
-		if (guid_already_parsed(device, gblock[i].guid))
+		if (guid_already_parsed(device, &gblock[i].guid))
 			continue;
 
 		wblock = kzalloc(sizeof(struct wmi_block), GFP_KERNEL);
 		if (!wblock) {
-			retval = -ENOMEM;
-			break;
+			dev_err(wmi_bus_dev, "Failed to allocate %pUL\n", &gblock[i].guid);
+			continue;
 		}
 
 		wblock->acpi_device = device;
 		wblock->gblock = gblock[i];
 
-		retval = wmi_create_device(wmi_bus_dev, &gblock[i], wblock, device);
+		retval = wmi_create_device(wmi_bus_dev, wblock, device);
 		if (retval) {
 			kfree(wblock);
 			continue;
@@ -1213,7 +1212,7 @@
 		retval = device_add(&wblock->dev.dev);
 		if (retval) {
 			dev_err(wmi_bus_dev, "failed to register %pUL\n",
-				wblock->gblock.guid);
+				&wblock->gblock.guid);
 			if (debug_event)
 				wmi_method_enable(wblock, 0);
 			list_del(&wblock->list);
@@ -1221,9 +1220,9 @@
 		}
 	}
 
-out_free_pointer:
-	kfree(out.pointer);
-	return retval;
+	kfree(obj);
+
+	return 0;
 }
 
 /*
@@ -1273,12 +1272,11 @@
 static void acpi_wmi_notify_handler(acpi_handle handle, u32 event,
 				    void *context)
 {
-	struct guid_block *block;
 	struct wmi_block *wblock;
 	bool found_it = false;
 
 	list_for_each_entry(wblock, &wmi_block_list, list) {
-		block = &wblock->gblock;
+		struct guid_block *block = &wblock->gblock;
 
 		if (wblock->acpi_device->handle == handle &&
 		    (block->flags & ACPI_WMI_EVENT) &&
@@ -1326,10 +1324,8 @@
 		wblock->handler(event, wblock->handler_data);
 	}
 
-	if (debug_event) {
-		pr_info("DEBUG Event GUID: %pUL\n",
-			wblock->gblock.guid);
-	}
+	if (debug_event)
+		pr_info("DEBUG Event GUID: %pUL\n", &wblock->gblock.guid);
 
 	acpi_bus_generate_netlink_event(
 		wblock->acpi_device->pnp.device_class,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/platform/x86/xiaomi-wmi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/platform/x86/xiaomi-wmi.c
@@ -23,7 +23,7 @@
 	unsigned int key_code;
 };
 
-int xiaomi_wmi_probe(struct wmi_device *wdev, const void *context)
+static int xiaomi_wmi_probe(struct wmi_device *wdev, const void *context)
 {
 	struct xiaomi_wmi *data;
 
@@ -48,7 +48,7 @@
 	return input_register_device(data->input_dev);
 }
 
-void xiaomi_wmi_notify(struct wmi_device *wdev, union acpi_object *dummy)
+static void xiaomi_wmi_notify(struct wmi_device *wdev, union acpi_object *dummy)
 {
 	struct xiaomi_wmi *data;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pnp/core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pnp/core.c
@@ -160,14 +160,14 @@
 	dev->dev.coherent_dma_mask = dev->dma_mask;
 	dev->dev.release = &pnp_release_device;
 
-	dev_set_name(&dev->dev, "%02x:%02x", dev->protocol->number, dev->number);
-
 	dev_id = pnp_add_id(dev, pnpid);
 	if (!dev_id) {
 		kfree(dev);
 		return NULL;
 	}
 
+	dev_set_name(&dev->dev, "%02x:%02x", dev->protocol->number, dev->number);
+
 	return dev;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pnp/isapnp/core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pnp/isapnp/core.c
@@ -27,6 +27,7 @@
 #include <linux/init.h>
 #include <linux/isapnp.h>
 #include <linux/mutex.h>
+#include <linux/async.h>
 #include <asm/io.h>
 
 #include "../base.h"
@@ -973,7 +974,7 @@
 	.disable = isapnp_disable_resources,
 };
 
-static int __init isapnp_init(void)
+static int __init real_isapnp_init(void)
 {
 	int cards;
 	struct pnp_card *card;
@@ -1067,6 +1068,16 @@
 	return 0;
 }
 
+static void __init async_isapnp_init(void *unused, async_cookie_t cookie)
+{
+	(void)real_isapnp_init();
+}
+
+static int __init isapnp_init(void)
+{
+	async_schedule(async_isapnp_init, NULL);
+	return 0;
+}
 device_initcall(isapnp_init);
 
 /* format is: noisapnp */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pnp/pnpacpi/rsparser.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pnp/pnpacpi/rsparser.c
@@ -151,13 +151,13 @@
 static void pnpacpi_parse_allocated_vendor(struct pnp_dev *dev,
 				    struct acpi_resource_vendor_typed *vendor)
 {
-	if (vendor_resource_matches(dev, vendor, &hp_ccsr_uuid, 16)) {
-		u64 start, length;
+	struct { u64 start, length; } range;
 
-		memcpy(&start, vendor->byte_data, sizeof(start));
-		memcpy(&length, vendor->byte_data + 8, sizeof(length));
-
-		pnp_add_mem_resource(dev, start, start + length - 1, 0);
+	if (vendor_resource_matches(dev, vendor, &hp_ccsr_uuid,
+				    sizeof(range))) {
+		memcpy(&range, vendor->byte_data, sizeof(range));
+		pnp_add_mem_resource(dev, range.start, range.start +
+				     range.length - 1, 0);
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/avs/smartreflex.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/avs/smartreflex.c
@@ -213,10 +213,10 @@
 
 	if (sr_class->notify && sr_class->notify_flags && sr_info->irq) {
 		ret = devm_request_irq(&sr_info->pdev->dev, sr_info->irq,
-				       sr_interrupt, 0, sr_info->name, sr_info);
+				       sr_interrupt, IRQF_NO_AUTOEN,
+				       sr_info->name, sr_info);
 		if (ret)
 			goto error;
-		disable_irq(sr_info->irq);
 	}
 
 	if (pdata && pdata->enable_on_init)
@@ -942,6 +942,7 @@
 err_debugfs:
 	debugfs_remove_recursive(sr_info->dbg_dir);
 err_list_del:
+	pm_runtime_disable(&pdev->dev);
 	list_del(&sr_info->node);
 
 	pm_runtime_put_sync(&pdev->dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/reset/arm-versatile-reboot.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/reset/arm-versatile-reboot.c
@@ -146,6 +146,7 @@
 	versatile_reboot_type = (enum versatile_reboot)reboot_id->data;
 
 	syscon_regmap = syscon_node_to_regmap(np);
+	of_node_put(np);
 	if (IS_ERR(syscon_regmap))
 		return PTR_ERR(syscon_regmap);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/reset/at91-sama5d2_shdwc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/reset/at91-sama5d2_shdwc.c
@@ -37,7 +37,7 @@
 
 #define AT91_SHDW_MR	0x04		/* Shut Down Mode Register */
 #define AT91_SHDW_WKUPDBC_SHIFT	24
-#define AT91_SHDW_WKUPDBC_MASK	GENMASK(31, 16)
+#define AT91_SHDW_WKUPDBC_MASK	GENMASK(26, 24)
 #define AT91_SHDW_WKUPDBC(x)	(((x) << AT91_SHDW_WKUPDBC_SHIFT) \
 						& AT91_SHDW_WKUPDBC_MASK)
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/reset/brcmstb-reboot.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/reset/brcmstb-reboot.c
@@ -72,9 +72,6 @@
 		return NOTIFY_DONE;
 	}
 
-	while (1)
-		;
-
 	return NOTIFY_DONE;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/reset/gemini-poweroff.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/reset/gemini-poweroff.c
@@ -107,8 +107,8 @@
 		return PTR_ERR(gpw->base);
 
 	irq = platform_get_irq(pdev, 0);
-	if (!irq)
-		return -EINVAL;
+	if (irq < 0)
+		return irq;
 
 	gpw->dev = dev;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/reset/gpio-poweroff.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/reset/gpio-poweroff.c
@@ -90,6 +90,7 @@
 	{ .compatible = "gpio-poweroff", },
 	{},
 };
+MODULE_DEVICE_TABLE(of, of_gpio_poweroff_match);
 
 static struct platform_driver gpio_poweroff_driver = {
 	.probe = gpio_poweroff_probe,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/reset/ltc2952-poweroff.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/reset/ltc2952-poweroff.c
@@ -160,8 +160,8 @@
 
 static void ltc2952_poweroff_default(struct ltc2952_poweroff *data)
 {
-	data->wde_interval = 300L * 1E6L;
-	data->trigger_delay = ktime_set(2, 500L*1E6L);
+	data->wde_interval = 300L * NSEC_PER_MSEC;
+	data->trigger_delay = ktime_set(2, 500L * NSEC_PER_MSEC);
 
 	hrtimer_init(&data->timer_trigger, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 	data->timer_trigger.function = ltc2952_poweroff_timer_trigger;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/reset/vexpress-poweroff.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/reset/vexpress-poweroff.c
@@ -143,6 +143,7 @@
 	.driver = {
 		.name = "vexpress-reset",
 		.of_match_table = vexpress_reset_of_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/88pm860x_battery.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/88pm860x_battery.c
@@ -433,7 +433,7 @@
 	int ret;
 	int data;
 	int bat_remove;
-	int soc;
+	int soc = 0;
 
 	/* measure enable on GPADC1 */
 	data = MEAS1_GP1;
@@ -496,7 +496,9 @@
 	}
 	mutex_unlock(&info->lock);
 
-	calc_soc(info, OCV_MODE_ACTIVE, &soc);
+	ret = calc_soc(info, OCV_MODE_ACTIVE, &soc);
+	if (ret < 0)
+		goto out;
 
 	data = pm860x_reg_read(info->i2c, PM8607_POWER_UP_LOG);
 	bat_remove = data & BAT_WU_LOG;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/Kconfig
@@ -577,7 +577,7 @@
 	tristate "TI BQ24250/24251/24257 battery charger driver"
 	depends on I2C
 	depends on GPIOLIB || COMPILE_TEST
-	depends on REGMAP_I2C
+	select REGMAP_I2C
 	help
 	  Say Y to enable support for the TI BQ24250, BQ24251, and BQ24257 battery
 	  chargers.
@@ -643,7 +643,8 @@
 
 config BATTERY_RT5033
 	tristate "RT5033 fuel gauge support"
-	depends on MFD_RT5033
+	depends on I2C
+	select REGMAP_I2C
 	help
 	  This adds support for battery fuel gauge in Richtek RT5033 PMIC.
 	  The fuelgauge calculates and determines the battery state of charge
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/ab8500_btemp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/ab8500_btemp.c
@@ -919,10 +919,8 @@
  */
 static void ab8500_btemp_external_power_changed(struct power_supply *psy)
 {
-	struct ab8500_btemp *di = power_supply_get_drvdata(psy);
-
-	class_for_each_device(power_supply_class, NULL,
-		di->btemp_psy, ab8500_btemp_get_ext_psy_data);
+	class_for_each_device(power_supply_class, NULL, psy,
+			      ab8500_btemp_get_ext_psy_data);
 }
 
 /* ab8500 btemp driver interrupts and their respective isr */
@@ -1120,6 +1118,7 @@
 	{ .compatible = "stericsson,ab8500-btemp", },
 	{ },
 };
+MODULE_DEVICE_TABLE(of, ab8500_btemp_match);
 
 static struct platform_driver ab8500_btemp_driver = {
 	.probe = ab8500_btemp_probe,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/ab8500_charger.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/ab8500_charger.c
@@ -407,6 +407,14 @@
 static void ab8500_power_supply_changed(struct ab8500_charger *di,
 					struct power_supply *psy)
 {
+	/*
+	 * This happens if we get notifications or interrupts and
+	 * the platform has been configured not to support one or
+	 * other type of charging.
+	 */
+	if (!psy)
+		return;
+
 	if (di->autopower_cfg) {
 		if (!di->usb.charger_connected &&
 		    !di->ac.charger_connected &&
@@ -433,7 +441,15 @@
 		if (!connected)
 			di->flags.vbus_drop_end = false;
 
-		sysfs_notify(&di->usb_chg.psy->dev.kobj, NULL, "present");
+		/*
+		 * Sometimes the platform is configured not to support
+		 * USB charging and no psy has been created, but we still
+		 * will get these notifications.
+		 */
+		if (di->usb_chg.psy) {
+			sysfs_notify(&di->usb_chg.psy->dev.kobj, NULL,
+				     "present");
+		}
 
 		if (connected) {
 			mutex_lock(&di->charger_attached_mutex);
@@ -3617,6 +3633,7 @@
 	{ .compatible = "stericsson,ab8500-charger", },
 	{ },
 };
+MODULE_DEVICE_TABLE(of, ab8500_charger_match);
 
 static struct platform_driver ab8500_charger_driver = {
 	.probe = ab8500_charger_probe,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/ab8500_fg.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/ab8500_fg.c
@@ -2380,10 +2380,8 @@
  */
 static void ab8500_fg_external_power_changed(struct power_supply *psy)
 {
-	struct ab8500_fg *di = power_supply_get_drvdata(psy);
-
-	class_for_each_device(power_supply_class, NULL,
-		di->fg_psy, ab8500_fg_get_ext_psy_data);
+	class_for_each_device(power_supply_class, NULL, psy,
+			      ab8500_fg_get_ext_psy_data);
 }
 
 /**
@@ -2541,8 +2539,10 @@
 	ret = kobject_init_and_add(&di->fg_kobject,
 		&ab8500_fg_ktype,
 		NULL, "battery");
-	if (ret < 0)
+	if (ret < 0) {
+		kobject_put(&di->fg_kobject);
 		dev_err(di->dev, "failed to create sysfs entry\n");
+	}
 
 	return ret;
 }
@@ -3230,6 +3230,7 @@
 	{ .compatible = "stericsson,ab8500-fg", },
 	{ },
 };
+MODULE_DEVICE_TABLE(of, ab8500_fg_match);
 
 static struct platform_driver ab8500_fg_driver = {
 	.probe = ab8500_fg_probe,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/adp5061.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/adp5061.c
@@ -427,11 +427,11 @@
 	if (ret < 0)
 		return ret;
 
-	chg_type = adp5061_chg_type[ADP5061_CHG_STATUS_1_CHG_STATUS(status1)];
-	if (chg_type > ADP5061_CHG_FAST_CV)
+	chg_type = ADP5061_CHG_STATUS_1_CHG_STATUS(status1);
+	if (chg_type >= ARRAY_SIZE(adp5061_chg_type))
 		val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
 	else
-		val->intval = chg_type;
+		val->intval = adp5061_chg_type[chg_type];
 
 	return ret;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/axp20x_ac_power.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/axp20x_ac_power.c
@@ -23,6 +23,8 @@
 #define AXP20X_PWR_STATUS_ACIN_PRESENT	BIT(7)
 #define AXP20X_PWR_STATUS_ACIN_AVAIL	BIT(6)
 
+#define AXP813_ACIN_PATH_SEL		BIT(7)
+
 #define AXP813_VHOLD_MASK		GENMASK(5, 3)
 #define AXP813_VHOLD_UV_TO_BIT(x)	((((x) / 100000) - 40) << 3)
 #define AXP813_VHOLD_REG_TO_UV(x)	\
@@ -40,6 +42,7 @@
 	struct power_supply *supply;
 	struct iio_channel *acin_v;
 	struct iio_channel *acin_i;
+	bool has_acin_path_sel;
 };
 
 static irqreturn_t axp20x_ac_power_irq(int irq, void *devid)
@@ -86,6 +89,17 @@
 			return ret;
 
 		val->intval = !!(reg & AXP20X_PWR_STATUS_ACIN_AVAIL);
+
+		/* ACIN_PATH_SEL disables ACIN even if ACIN_AVAIL is set. */
+		if (val->intval && power->has_acin_path_sel) {
+			ret = regmap_read(power->regmap, AXP813_ACIN_PATH_CTRL,
+					  &reg);
+			if (ret)
+				return ret;
+
+			val->intval = !!(reg & AXP813_ACIN_PATH_SEL);
+		}
+
 		return 0;
 
 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
@@ -224,21 +238,25 @@
 struct axp_data {
 	const struct power_supply_desc	*power_desc;
 	bool				acin_adc;
+	bool				acin_path_sel;
 };
 
 static const struct axp_data axp20x_data = {
-	.power_desc = &axp20x_ac_power_desc,
-	.acin_adc = true,
+	.power_desc	= &axp20x_ac_power_desc,
+	.acin_adc	= true,
+	.acin_path_sel	= false,
 };
 
 static const struct axp_data axp22x_data = {
-	.power_desc = &axp22x_ac_power_desc,
-	.acin_adc = false,
+	.power_desc	= &axp22x_ac_power_desc,
+	.acin_adc	= false,
+	.acin_path_sel	= false,
 };
 
 static const struct axp_data axp813_data = {
-	.power_desc = &axp813_ac_power_desc,
-	.acin_adc = false,
+	.power_desc	= &axp813_ac_power_desc,
+	.acin_adc	= false,
+	.acin_path_sel	= true,
 };
 
 static int axp20x_ac_power_probe(struct platform_device *pdev)
@@ -282,6 +300,7 @@
 	}
 
 	power->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+	power->has_acin_path_sel = axp_data->acin_path_sel;
 
 	platform_set_drvdata(pdev, power);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/axp20x_battery.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/axp20x_battery.c
@@ -40,6 +40,7 @@
 #define AXP209_FG_PERCENT		GENMASK(6, 0)
 #define AXP22X_FG_VALID			BIT(7)
 
+#define AXP20X_CHRG_CTRL1_ENABLE	BIT(7)
 #define AXP20X_CHRG_CTRL1_TGT_VOLT	GENMASK(6, 5)
 #define AXP20X_CHRG_CTRL1_TGT_4_1V	(0 << 5)
 #define AXP20X_CHRG_CTRL1_TGT_4_15V	(1 << 5)
@@ -185,7 +186,6 @@
 				   union power_supply_propval *val)
 {
 	struct axp20x_batt_ps *axp20x_batt = power_supply_get_drvdata(psy);
-	struct iio_channel *chan;
 	int ret = 0, reg, val1;
 
 	switch (psp) {
@@ -265,12 +265,12 @@
 		if (ret)
 			return ret;
 
-		if (reg & AXP20X_PWR_STATUS_BAT_CHARGING)
-			chan = axp20x_batt->batt_chrg_i;
-		else
-			chan = axp20x_batt->batt_dischrg_i;
-
-		ret = iio_read_channel_processed(chan, &val->intval);
+		if (reg & AXP20X_PWR_STATUS_BAT_CHARGING) {
+			ret = iio_read_channel_processed(axp20x_batt->batt_chrg_i, &val->intval);
+		} else {
+			ret = iio_read_channel_processed(axp20x_batt->batt_dischrg_i, &val1);
+			val->intval = -val1;
+		}
 		if (ret)
 			return ret;
 
@@ -304,11 +304,11 @@
 		val->intval = reg & AXP209_FG_PERCENT;
 		break;
 
-	case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+	case POWER_SUPPLY_PROP_VOLTAGE_MAX:
 		return axp20x_batt->data->get_max_voltage(axp20x_batt,
 							  &val->intval);
 
-	case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+	case POWER_SUPPLY_PROP_VOLTAGE_MIN:
 		ret = regmap_read(axp20x_batt->regmap, AXP20X_V_OFF, &reg);
 		if (ret)
 			return ret;
@@ -456,10 +456,10 @@
 	struct axp20x_batt_ps *axp20x_batt = power_supply_get_drvdata(psy);
 
 	switch (psp) {
-	case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+	case POWER_SUPPLY_PROP_VOLTAGE_MIN:
 		return axp20x_set_voltage_min_design(axp20x_batt, val->intval);
 
-	case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+	case POWER_SUPPLY_PROP_VOLTAGE_MAX:
 		return axp20x_batt->data->set_max_voltage(axp20x_batt, val->intval);
 
 	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
@@ -468,7 +468,18 @@
 	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
 		return axp20x_set_max_constant_charge_current(axp20x_batt,
 							      val->intval);
-
+	case POWER_SUPPLY_PROP_STATUS:
+		switch (val->intval) {
+		case POWER_SUPPLY_STATUS_CHARGING:
+			return regmap_update_bits(axp20x_batt->regmap, AXP20X_CHRG_CTRL1,
+				AXP20X_CHRG_CTRL1_ENABLE, AXP20X_CHRG_CTRL1_ENABLE);
+
+		case POWER_SUPPLY_STATUS_DISCHARGING:
+		case POWER_SUPPLY_STATUS_NOT_CHARGING:
+			return regmap_update_bits(axp20x_batt->regmap, AXP20X_CHRG_CTRL1,
+				AXP20X_CHRG_CTRL1_ENABLE, 0);
+		}
+		fallthrough;
 	default:
 		return -EINVAL;
 	}
@@ -483,16 +494,17 @@
 	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
 	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
 	POWER_SUPPLY_PROP_HEALTH,
-	POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
-	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+	POWER_SUPPLY_PROP_VOLTAGE_MAX,
+	POWER_SUPPLY_PROP_VOLTAGE_MIN,
 	POWER_SUPPLY_PROP_CAPACITY,
 };
 
 static int axp20x_battery_prop_writeable(struct power_supply *psy,
 					 enum power_supply_property psp)
 {
-	return psp == POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN ||
-	       psp == POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN ||
+	return psp == POWER_SUPPLY_PROP_STATUS ||
+	       psp == POWER_SUPPLY_PROP_VOLTAGE_MIN ||
+	       psp == POWER_SUPPLY_PROP_VOLTAGE_MAX ||
 	       psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT ||
 	       psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/axp288_charger.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/axp288_charger.c
@@ -21,6 +21,7 @@
 #include <linux/property.h>
 #include <linux/mfd/axp20x.h>
 #include <linux/extcon.h>
+#include <linux/dmi.h>
 
 #define PS_STAT_VBUS_TRIGGER		BIT(0)
 #define PS_STAT_BAT_CHRG_DIR		BIT(2)
@@ -40,11 +41,11 @@
 #define VBUS_ISPOUT_CUR_LIM_1500MA	0x1	/* 1500mA */
 #define VBUS_ISPOUT_CUR_LIM_2000MA	0x2	/* 2000mA */
 #define VBUS_ISPOUT_CUR_NO_LIM		0x3	/* 2500mA */
-#define VBUS_ISPOUT_VHOLD_SET_MASK	0x31
+#define VBUS_ISPOUT_VHOLD_SET_MASK	0x38
 #define VBUS_ISPOUT_VHOLD_SET_BIT_POS	0x3
 #define VBUS_ISPOUT_VHOLD_SET_OFFSET	4000	/* 4000mV */
 #define VBUS_ISPOUT_VHOLD_SET_LSB_RES	100	/* 100mV */
-#define VBUS_ISPOUT_VHOLD_SET_4300MV	0x3	/* 4300mV */
+#define VBUS_ISPOUT_VHOLD_SET_4400MV	0x4	/* 4400mV */
 #define VBUS_ISPOUT_VBUS_PATH_DIS	BIT(7)
 
 #define CHRG_CCCV_CC_MASK		0xf		/* 4 bits */
@@ -167,18 +168,18 @@
 	u8 reg_val;
 	int ret;
 
-	if (cv <= CV_4100MV) {
-		reg_val = CHRG_CCCV_CV_4100MV;
-		cv = CV_4100MV;
-	} else if (cv <= CV_4150MV) {
-		reg_val = CHRG_CCCV_CV_4150MV;
-		cv = CV_4150MV;
-	} else if (cv <= CV_4200MV) {
+	if (cv >= CV_4350MV) {
+		reg_val = CHRG_CCCV_CV_4350MV;
+		cv = CV_4350MV;
+	} else if (cv >= CV_4200MV) {
 		reg_val = CHRG_CCCV_CV_4200MV;
 		cv = CV_4200MV;
+	} else if (cv >= CV_4150MV) {
+		reg_val = CHRG_CCCV_CV_4150MV;
+		cv = CV_4150MV;
 	} else {
-		reg_val = CHRG_CCCV_CV_4350MV;
-		cv = CV_4350MV;
+		reg_val = CHRG_CCCV_CV_4100MV;
+		cv = CV_4100MV;
 	}
 
 	reg_val = reg_val << CHRG_CCCV_CV_BIT_POS;
@@ -370,8 +371,8 @@
 			dev_warn(&info->pdev->dev, "set charge current failed\n");
 		break;
 	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
-		scaled_val = min(val->intval, info->max_cv);
-		scaled_val = DIV_ROUND_CLOSEST(scaled_val, 1000);
+		scaled_val = DIV_ROUND_CLOSEST(val->intval, 1000);
+		scaled_val = min(scaled_val, info->max_cv);
 		ret = axp288_charger_set_cv(info, scaled_val);
 		if (ret < 0)
 			dev_warn(&info->pdev->dev, "set charge voltage failed\n");
@@ -545,6 +546,55 @@
 	return IRQ_HANDLED;
 }
 
+/*
+ * The HP Pavilion x2 10 series comes in a number of variants:
+ * Bay Trail SoC    + AXP288 PMIC, Micro-USB, DMI_BOARD_NAME: "8021"
+ * Bay Trail SoC    + AXP288 PMIC, Type-C,    DMI_BOARD_NAME: "815D"
+ * Cherry Trail SoC + AXP288 PMIC, Type-C,    DMI_BOARD_NAME: "813E"
+ * Cherry Trail SoC + TI PMIC,     Type-C,    DMI_BOARD_NAME: "827C" or "82F4"
+ *
+ * The variants with the AXP288 + Type-C connector are all kinds of special:
+ *
+ * 1. They use a Type-C connector which the AXP288 does not support, so when
+ * using a Type-C charger it is not recognized. Unlike most AXP288 devices,
+ * this model actually has mostly working ACPI AC / Battery code, the ACPI code
+ * "solves" this by simply setting the input_current_limit to 3A.
+ * There are still some issues with the ACPI code, so we use this native driver,
+ * and to solve the charging not working (500mA is not enough) issue we hardcode
+ * the 3A input_current_limit like the ACPI code does.
+ *
+ * 2. If no charger is connected the machine boots with the vbus-path disabled.
+ * Normally this is done when a 5V boost converter is active to avoid the PMIC
+ * trying to charge from the 5V boost converter's output. This is done when
+ * an OTG host cable is inserted and the ID pin on the micro-B receptacle is
+ * pulled low and the ID pin has an ACPI event handler associated with it
+ * which re-enables the vbus-path when the ID pin is pulled high when the
+ * OTG host cable is removed. The Type-C connector has no ID pin, there is
+ * no ID pin handler and there appears to be no 5V boost converter, so we
+ * end up not charging because the vbus-path is disabled, until we unplug
+ * the charger which automatically clears the vbus-path disable bit and then
+ * on the second plug-in of the adapter we start charging. To solve the not
+ * charging on first charger plugin we unconditionally enable the vbus-path at
+ * probe on this model, which is safe since there is no 5V boost converter.
+ */
+static const struct dmi_system_id axp288_hp_x2_dmi_ids[] = {
+	{
+		.matches = {
+			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"),
+			DMI_EXACT_MATCH(DMI_BOARD_NAME, "815D"),
+		},
+	},
+	{
+		.matches = {
+			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "HP"),
+			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"),
+			DMI_EXACT_MATCH(DMI_BOARD_NAME, "813E"),
+		},
+	},
+	{} /* Terminating entry */
+};
+
 static void axp288_charger_extcon_evt_worker(struct work_struct *work)
 {
 	struct axp288_chrg_info *info =
@@ -568,7 +618,11 @@
 	}
 
 	/* Determine cable/charger type */
-	if (extcon_get_state(edev, EXTCON_CHG_USB_SDP) > 0) {
+	if (dmi_check_system(axp288_hp_x2_dmi_ids)) {
+		/* See comment above axp288_hp_x2_dmi_ids declaration */
+		dev_dbg(&info->pdev->dev, "HP X2 with Type-C, setting inlmt to 3A\n");
+		current_limit = 3000000;
+	} else if (extcon_get_state(edev, EXTCON_CHG_USB_SDP) > 0) {
 		dev_dbg(&info->pdev->dev, "USB SDP charger is connected\n");
 		current_limit = 500000;
 	} else if (extcon_get_state(edev, EXTCON_CHG_USB_CDP) > 0) {
@@ -685,6 +739,23 @@
 		return ret;
 	}
 
+	if (dmi_check_system(axp288_hp_x2_dmi_ids)) {
+		/* See comment above axp288_hp_x2_dmi_ids declaration */
+		ret = axp288_charger_vbus_path_select(info, true);
+		if (ret < 0)
+			return ret;
+	} else {
+		/* Set Vhold to the factory default / recommended 4.4V */
+		val = VBUS_ISPOUT_VHOLD_SET_4400MV << VBUS_ISPOUT_VHOLD_SET_BIT_POS;
+		ret = regmap_update_bits(info->regmap, AXP20X_VBUS_IPSOUT_MGMT,
+					 VBUS_ISPOUT_VHOLD_SET_MASK, val);
+		if (ret < 0) {
+			dev_err(&info->pdev->dev, "register(%x) write error(%d)\n",
+				AXP20X_VBUS_IPSOUT_MGMT, ret);
+			return ret;
+		}
+	}
+
 	/* Read current charge voltage and current limit */
 	ret = regmap_read(info->regmap, AXP20X_CHRG_CTRL1, &val);
 	if (ret < 0) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/axp288_fuel_gauge.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/axp288_fuel_gauge.c
@@ -149,7 +149,7 @@
 	}
 
 	if (ret < 0) {
-		dev_err(&info->pdev->dev, "axp288 reg read err:%d\n", ret);
+		dev_err(&info->pdev->dev, "Error reading reg 0x%02x err: %d\n", reg, ret);
 		return ret;
 	}
 
@@ -163,7 +163,7 @@
 	ret = regmap_write(info->regmap, reg, (unsigned int)val);
 
 	if (ret < 0)
-		dev_err(&info->pdev->dev, "axp288 reg write err:%d\n", ret);
+		dev_err(&info->pdev->dev, "Error writing reg 0x%02x err: %d\n", reg, ret);
 
 	return ret;
 }
@@ -706,14 +706,14 @@
 	{
 		/* Intel Cherry Trail Compute Stick, Windows version */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Intel"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "STK1AW32SC"),
 		},
 	},
 	{
 		/* Intel Cherry Trail Compute Stick, version without an OS */
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
+			DMI_MATCH(DMI_SYS_VENDOR, "Intel"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "STK1A32SC"),
 		},
 	},
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/bd70528-charger.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/bd70528-charger.c
@@ -741,3 +741,4 @@
 MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
 MODULE_DESCRIPTION("BD70528 power-supply driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:bd70528-power");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/bq24190_charger.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/bq24190_charger.c
@@ -41,6 +41,7 @@
 #define BQ24190_REG_POC_CHG_CONFIG_DISABLE		0x0
 #define BQ24190_REG_POC_CHG_CONFIG_CHARGE		0x1
 #define BQ24190_REG_POC_CHG_CONFIG_OTG			0x2
+#define BQ24190_REG_POC_CHG_CONFIG_OTG_ALT		0x3
 #define BQ24190_REG_POC_SYS_MIN_MASK		(BIT(3) | BIT(2) | BIT(1))
 #define BQ24190_REG_POC_SYS_MIN_SHIFT		1
 #define BQ24190_REG_POC_SYS_MIN_MIN			3000
@@ -448,8 +449,10 @@
 		return -EINVAL;
 
 	ret = pm_runtime_get_sync(bdi->dev);
-	if (ret < 0)
+	if (ret < 0) {
+		pm_runtime_put_noidle(bdi->dev);
 		return ret;
+	}
 
 	ret = bq24190_read_mask(bdi, info->reg, info->mask, info->shift, &v);
 	if (ret)
@@ -548,7 +551,11 @@
 	pm_runtime_mark_last_busy(bdi->dev);
 	pm_runtime_put_autosuspend(bdi->dev);
 
-	return ret ? ret : val == BQ24190_REG_POC_CHG_CONFIG_OTG;
+	if (ret)
+		return ret;
+
+	return (val == BQ24190_REG_POC_CHG_CONFIG_OTG ||
+		val == BQ24190_REG_POC_CHG_CONFIG_OTG_ALT);
 }
 
 static const struct regulator_ops bq24190_vbus_ops = {
@@ -1075,8 +1082,10 @@
 	dev_dbg(bdi->dev, "prop: %d\n", psp);
 
 	ret = pm_runtime_get_sync(bdi->dev);
-	if (ret < 0)
+	if (ret < 0) {
+		pm_runtime_put_noidle(bdi->dev);
 		return ret;
+	}
 
 	switch (psp) {
 	case POWER_SUPPLY_PROP_CHARGE_TYPE:
@@ -1147,8 +1156,10 @@
 	dev_dbg(bdi->dev, "prop: %d\n", psp);
 
 	ret = pm_runtime_get_sync(bdi->dev);
-	if (ret < 0)
+	if (ret < 0) {
+		pm_runtime_put_noidle(bdi->dev);
 		return ret;
+	}
 
 	switch (psp) {
 	case POWER_SUPPLY_PROP_ONLINE:
@@ -1200,8 +1211,19 @@
 	struct bq24190_dev_info *bdi =
 		container_of(work, struct bq24190_dev_info,
 			     input_current_limit_work.work);
+	union power_supply_propval val;
+	int ret;
 
-	power_supply_set_input_current_limit_from_supplier(bdi->charger);
+	ret = power_supply_get_property_from_supplier(bdi->charger,
+						      POWER_SUPPLY_PROP_CURRENT_MAX,
+						      &val);
+	if (ret)
+		return;
+
+	bq24190_charger_set_property(bdi->charger,
+				     POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
+				     &val);
+	power_supply_changed(bdi->charger);
 }
 
 /* Sync the input-current-limit with our parent supply (if we have one) */
@@ -1408,8 +1430,10 @@
 	dev_dbg(bdi->dev, "prop: %d\n", psp);
 
 	ret = pm_runtime_get_sync(bdi->dev);
-	if (ret < 0)
+	if (ret < 0) {
+		pm_runtime_put_noidle(bdi->dev);
 		return ret;
+	}
 
 	switch (psp) {
 	case POWER_SUPPLY_PROP_STATUS:
@@ -1454,8 +1478,10 @@
 	dev_dbg(bdi->dev, "prop: %d\n", psp);
 
 	ret = pm_runtime_get_sync(bdi->dev);
-	if (ret < 0)
+	if (ret < 0) {
+		pm_runtime_put_noidle(bdi->dev);
 		return ret;
+	}
 
 	switch (psp) {
 	case POWER_SUPPLY_PROP_ONLINE:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/bq25890_charger.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/bq25890_charger.c
@@ -531,12 +531,12 @@
 
 	if (!new_state->online) {			     /* power removed */
 		/* disable ADC */
-		ret = bq25890_field_write(bq, F_CONV_START, 0);
+		ret = bq25890_field_write(bq, F_CONV_RATE, 0);
 		if (ret < 0)
 			goto error;
 	} else if (!old_state.online) {			    /* power inserted */
 		/* enable ADC, to have control of charge current/voltage */
-		ret = bq25890_field_write(bq, F_CONV_START, 1);
+		ret = bq25890_field_write(bq, F_CONV_RATE, 1);
 		if (ret < 0)
 			goto error;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/bq27xxx_battery.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/bq27xxx_battery.c
@@ -886,10 +886,8 @@
 		return ret;
 
 	mutex_lock(&bq27xxx_list_lock);
-	list_for_each_entry(di, &bq27xxx_battery_devices, list) {
-		cancel_delayed_work_sync(&di->work);
-		schedule_delayed_work(&di->work, 0);
-	}
+	list_for_each_entry(di, &bq27xxx_battery_devices, list)
+		mod_delayed_work(system_wq, &di->work, 0);
 	mutex_unlock(&bq27xxx_list_lock);
 
 	return ret;
@@ -1500,27 +1498,6 @@
 }
 
 /*
- * Read an average power register.
- * Return < 0 if something fails.
- */
-static int bq27xxx_battery_read_pwr_avg(struct bq27xxx_device_info *di)
-{
-	int tval;
-
-	tval = bq27xxx_read(di, BQ27XXX_REG_AP, false);
-	if (tval < 0) {
-		dev_err(di->dev, "error reading average power register  %02x: %d\n",
-			BQ27XXX_REG_AP, tval);
-		return tval;
-	}
-
-	if (di->opts & BQ27XXX_O_ZERO)
-		return (tval * BQ27XXX_POWER_CONSTANT) / BQ27XXX_RS;
-	else
-		return tval;
-}
-
-/*
  * Returns true if a battery over temperature condition is detected
  */
 static bool bq27xxx_battery_overtemp(struct bq27xxx_device_info *di, u16 flags)
@@ -1568,7 +1545,7 @@
 	return POWER_SUPPLY_HEALTH_GOOD;
 }
 
-void bq27xxx_battery_update(struct bq27xxx_device_info *di)
+static void bq27xxx_battery_update_unlocked(struct bq27xxx_device_info *di)
 {
 	struct bq27xxx_reg_cache cache = {0, };
 	bool has_ci_flag = di->opts & BQ27XXX_O_ZERO;
@@ -1604,8 +1581,6 @@
 		}
 		if (di->regs[BQ27XXX_REG_CYCT] != INVALID_REG_ADDR)
 			cache.cycle_count = bq27xxx_battery_read_cyct(di);
-		if (di->regs[BQ27XXX_REG_AP] != INVALID_REG_ADDR)
-			cache.power_avg = bq27xxx_battery_read_pwr_avg(di);
 
 		/* We only have to read charge design full once */
 		if (di->charge_design_full <= 0)
@@ -1620,6 +1595,16 @@
 		di->cache = cache;
 
 	di->last_update = jiffies;
+
+	if (!di->removed && poll_interval > 0)
+		mod_delayed_work(system_wq, &di->work, poll_interval * HZ);
+}
+
+void bq27xxx_battery_update(struct bq27xxx_device_info *di)
+{
+	mutex_lock(&di->lock);
+	bq27xxx_battery_update_unlocked(di);
+	mutex_unlock(&di->lock);
 }
 EXPORT_SYMBOL_GPL(bq27xxx_battery_update);
 
@@ -1630,9 +1615,6 @@
 				     work.work);
 
 	bq27xxx_battery_update(di);
-
-	if (poll_interval > 0)
-		schedule_delayed_work(&di->work, poll_interval * HZ);
 }
 
 /*
@@ -1668,6 +1650,32 @@
 	return 0;
 }
 
+/*
+ * Get the average power in µW
+ * Return < 0 if something fails.
+ */
+static int bq27xxx_battery_pwr_avg(struct bq27xxx_device_info *di,
+				   union power_supply_propval *val)
+{
+	int power;
+
+	power = bq27xxx_read(di, BQ27XXX_REG_AP, false);
+	if (power < 0) {
+		dev_err(di->dev,
+			"error reading average power register %02x: %d\n",
+			BQ27XXX_REG_AP, power);
+		return power;
+	}
+
+	if (di->opts & BQ27XXX_O_ZERO)
+		val->intval = (power * BQ27XXX_POWER_CONSTANT) / BQ27XXX_RS;
+	else
+		/* Other gauges return a signed value in units of 10mW */
+		val->intval = (int)((s16)power) * 10000;
+
+	return 0;
+}
+
 static int bq27xxx_battery_status(struct bq27xxx_device_info *di,
 				  union power_supply_propval *val)
 {
@@ -1678,8 +1686,6 @@
 			status = POWER_SUPPLY_STATUS_FULL;
 		else if (di->cache.flags & BQ27000_FLAG_CHGS)
 			status = POWER_SUPPLY_STATUS_CHARGING;
-		else if (power_supply_am_i_supplied(di->bat) > 0)
-			status = POWER_SUPPLY_STATUS_NOT_CHARGING;
 		else
 			status = POWER_SUPPLY_STATUS_DISCHARGING;
 	} else {
@@ -1691,6 +1697,10 @@
 			status = POWER_SUPPLY_STATUS_CHARGING;
 	}
 
+	if ((status == POWER_SUPPLY_STATUS_DISCHARGING) &&
+	    (power_supply_am_i_supplied(di->bat) > 0))
+		status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+
 	val->intval = status;
 
 	return 0;
@@ -1765,10 +1775,8 @@
 	struct bq27xxx_device_info *di = power_supply_get_drvdata(psy);
 
 	mutex_lock(&di->lock);
-	if (time_is_before_jiffies(di->last_update + 5 * HZ)) {
-		cancel_delayed_work_sync(&di->work);
-		bq27xxx_battery_poll(&di->work.work);
-	}
+	if (time_is_before_jiffies(di->last_update + 5 * HZ))
+		bq27xxx_battery_update_unlocked(di);
 	mutex_unlock(&di->lock);
 
 	if (psp != POWER_SUPPLY_PROP_PRESENT && di->cache.flags < 0)
@@ -1833,7 +1841,7 @@
 		ret = bq27xxx_simple_value(di->cache.energy, val);
 		break;
 	case POWER_SUPPLY_PROP_POWER_AVG:
-		ret = bq27xxx_simple_value(di->cache.power_avg, val);
+		ret = bq27xxx_battery_pwr_avg(di, val);
 		break;
 	case POWER_SUPPLY_PROP_HEALTH:
 		ret = bq27xxx_simple_value(di->cache.health, val);
@@ -1852,8 +1860,8 @@
 {
 	struct bq27xxx_device_info *di = power_supply_get_drvdata(psy);
 
-	cancel_delayed_work_sync(&di->work);
-	schedule_delayed_work(&di->work, 0);
+	/* After charger plug in/out wait 0.5s for things to stabilize */
+	mod_delayed_work(system_wq, &di->work, HZ / 2);
 }
 
 int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
@@ -1885,7 +1893,10 @@
 
 	di->bat = power_supply_register_no_ws(di->dev, psy_desc, &psy_cfg);
 	if (IS_ERR(di->bat)) {
-		dev_err(di->dev, "failed to register battery\n");
+		if (PTR_ERR(di->bat) == -EPROBE_DEFER)
+			dev_dbg(di->dev, "failed to register battery, deferring probe\n");
+		else
+			dev_err(di->dev, "failed to register battery\n");
 		return PTR_ERR(di->bat);
 	}
 
@@ -1902,22 +1913,18 @@
 
 void bq27xxx_battery_teardown(struct bq27xxx_device_info *di)
 {
-	/*
-	 * power_supply_unregister call bq27xxx_battery_get_property which
-	 * call bq27xxx_battery_poll.
-	 * Make sure that bq27xxx_battery_poll will not call
-	 * schedule_delayed_work again after unregister (which cause OOPS).
-	 */
-	poll_interval = 0;
-
-	cancel_delayed_work_sync(&di->work);
-
-	power_supply_unregister(di->bat);
-
 	mutex_lock(&bq27xxx_list_lock);
 	list_del(&di->list);
 	mutex_unlock(&bq27xxx_list_lock);
 
+	/* Set removed to avoid bq27xxx_battery_update() re-queuing the work */
+	mutex_lock(&di->lock);
+	di->removed = true;
+	mutex_unlock(&di->lock);
+
+	cancel_delayed_work_sync(&di->work);
+
+	power_supply_unregister(di->bat);
 	mutex_destroy(&di->lock);
 }
 EXPORT_SYMBOL_GPL(bq27xxx_battery_teardown);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/bq27xxx_battery_i2c.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/bq27xxx_battery_i2c.c
@@ -187,7 +187,7 @@
 	i2c_set_clientdata(client, di);
 
 	if (client->irq) {
-		ret = devm_request_threaded_irq(&client->dev, client->irq,
+		ret = request_threaded_irq(client->irq,
 				NULL, bq27xxx_battery_irq_handler_thread,
 				IRQF_ONESHOT,
 				di->name, di);
@@ -195,7 +195,8 @@
 			dev_err(&client->dev,
 				"Unable to register IRQ %d error %d\n",
 				client->irq, ret);
-			return ret;
+			bq27xxx_battery_teardown(di);
+			goto err_failed;
 		}
 	}
 
@@ -216,6 +217,9 @@
 {
 	struct bq27xxx_device_info *di = i2c_get_clientdata(client);
 
+	if (client->irq)
+		free_irq(client->irq, di);
+
 	bq27xxx_battery_teardown(di);
 
 	mutex_lock(&battery_mutex);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/charger-manager.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/charger-manager.c
@@ -1470,6 +1470,7 @@
 	},
 	{},
 };
+MODULE_DEVICE_TABLE(of, charger_manager_match);
 
 static struct charger_desc *of_cm_parse_desc(struct device *dev)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/cpcap-battery.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/cpcap-battery.c
@@ -562,12 +562,14 @@
 	switch (d->action) {
 	case CPCAP_BATTERY_IRQ_ACTION_BATTERY_LOW:
 		if (latest->current_ua >= 0)
-			dev_warn(ddata->dev, "Battery low at 3.3V!\n");
+			dev_warn(ddata->dev, "Battery low at %imV!\n",
+				latest->voltage / 1000);
 		break;
 	case CPCAP_BATTERY_IRQ_ACTION_POWEROFF:
-		if (latest->current_ua >= 0) {
+		if (latest->current_ua >= 0 && latest->voltage <= 3200000) {
 			dev_emerg(ddata->dev,
-				  "Battery empty at 3.1V, powering off\n");
+				  "Battery empty at %imV, powering off\n",
+				  latest->voltage / 1000);
 			orderly_poweroff(true);
 		}
 		break;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/cros_usbpd-charger.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/cros_usbpd-charger.c
@@ -282,7 +282,7 @@
 		port->psy_current_max = 0;
 		break;
 	default:
-		dev_err(dev, "Port %d: default case!\n", port->port_number);
+		dev_dbg(dev, "Port %d: default case!\n", port->port_number);
 		port->psy_usb_type = POWER_SUPPLY_USB_TYPE_SDP;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/da9150-charger.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/da9150-charger.c
@@ -662,6 +662,7 @@
 
 	if (!IS_ERR_OR_NULL(charger->usb_phy))
 		usb_unregister_notifier(charger->usb_phy, &charger->otg_nb);
+	cancel_work_sync(&charger->otg_work);
 
 	power_supply_unregister(charger->battery);
 	power_supply_unregister(charger->usb);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/da9150-fg.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/da9150-fg.c
@@ -247,9 +247,9 @@
 				      DA9150_QIF_SD_GAIN_SIZE);
 	da9150_fg_read_sync_end(fg);
 
-	div = (u64) (sd_gain * shunt_val * 65536ULL);
+	div = 65536ULL * sd_gain * shunt_val;
 	do_div(div, 1000000);
-	res = (u64) (iavg * 1000000ULL);
+	res = 1000000ULL * iavg;
 	do_div(res, div);
 
 	val->intval = (int) res;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/generic-adc-battery.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/generic-adc-battery.c
@@ -138,6 +138,9 @@
 			result);
 	if (ret < 0)
 		pr_err("read channel error\n");
+	else
+		*result *= 1000;
+
 	return ret;
 }
 
@@ -382,7 +385,7 @@
 	}
 
 	kfree(adc_bat->psy_desc.properties);
-	cancel_delayed_work(&adc_bat->bat_work);
+	cancel_delayed_work_sync(&adc_bat->bat_work);
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/ingenic-battery.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/ingenic-battery.c
@@ -100,10 +100,17 @@
 		return -EINVAL;
 	}
 
-	return iio_write_channel_attribute(bat->channel,
-					   scale_raw[best_idx],
-					   scale_raw[best_idx + 1],
-					   IIO_CHAN_INFO_SCALE);
+	/* Only set scale if there is more than one (fractional) entry */
+	if (scale_len > 2) {
+		ret = iio_write_channel_attribute(bat->channel,
+						  scale_raw[best_idx],
+						  scale_raw[best_idx + 1],
+						  IIO_CHAN_INFO_SCALE);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
 }
 
 static enum power_supply_property ingenic_battery_properties[] = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/lp8788-charger.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/lp8788-charger.c
@@ -501,7 +501,7 @@
 
 		ret = request_threaded_irq(virq, NULL,
 					lp8788_charger_irq_thread,
-					0, name, pchg);
+					IRQF_ONESHOT, name, pchg);
 		if (ret)
 			break;
 	}
@@ -572,27 +572,14 @@
 		return;
 
 	/* ADC channel for battery voltage */
-	chan = iio_channel_get(dev, pdata->adc_vbatt);
+	chan = devm_iio_channel_get(dev, pdata->adc_vbatt);
 	pchg->chan[LP8788_VBATT] = IS_ERR(chan) ? NULL : chan;
 
 	/* ADC channel for battery temperature */
-	chan = iio_channel_get(dev, pdata->adc_batt_temp);
+	chan = devm_iio_channel_get(dev, pdata->adc_batt_temp);
 	pchg->chan[LP8788_BATT_TEMP] = IS_ERR(chan) ? NULL : chan;
 }
 
-static void lp8788_release_adc_channel(struct lp8788_charger *pchg)
-{
-	int i;
-
-	for (i = 0; i < LP8788_NUM_CHG_ADC; i++) {
-		if (!pchg->chan[i])
-			continue;
-
-		iio_channel_release(pchg->chan[i]);
-		pchg->chan[i] = NULL;
-	}
-}
-
 static ssize_t lp8788_show_charger_status(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
@@ -735,7 +722,6 @@
 	flush_work(&pchg->charger_work);
 	lp8788_irq_unregister(pdev, pchg);
 	lp8788_psy_unregister(pchg);
-	lp8788_release_adc_channel(pchg);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/ltc2941-battery-gauge.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/ltc2941-battery-gauge.c
@@ -449,7 +449,7 @@
 {
 	struct ltc294x_info *info = i2c_get_clientdata(client);
 
-	cancel_delayed_work(&info->work);
+	cancel_delayed_work_sync(&info->work);
 	power_supply_unregister(info->supply);
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/max17040_battery.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/max17040_battery.c
@@ -105,7 +105,7 @@
 
 	vcell = max17040_read_reg(client, MAX17040_VCELL);
 
-	chip->vcell = vcell;
+	chip->vcell = (vcell >> 4) * 1250;
 }
 
 static void max17040_get_soc(struct i2c_client *client)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/max17042_battery.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/max17042_battery.c
@@ -312,7 +312,10 @@
 		val->intval = data * 625 / 8;
 		break;
 	case POWER_SUPPLY_PROP_CAPACITY:
-		ret = regmap_read(map, MAX17042_RepSOC, &data);
+		if (chip->pdata->enable_current_sense)
+			ret = regmap_read(map, MAX17042_RepSOC, &data);
+		else
+			ret = regmap_read(map, MAX17042_VFSOC, &data);
 		if (ret < 0)
 			return ret;
 
@@ -726,7 +729,7 @@
 	struct max17042_config_data *config = chip->pdata->config_data;
 
 	max17042_override_por(map, MAX17042_TGAIN, config->tgain);
-	max17042_override_por(map, MAx17042_TOFF, config->toff);
+	max17042_override_por(map, MAX17042_TOFF, config->toff);
 	max17042_override_por(map, MAX17042_CGAIN, config->cgain);
 	max17042_override_por(map, MAX17042_COFF, config->coff);
 
@@ -831,10 +834,14 @@
 	/* program interrupt thesholds such that we should
 	 * get interrupt for every 'off' perc change in the soc
 	 */
-	regmap_read(map, MAX17042_RepSOC, &soc);
+	if (chip->pdata->enable_current_sense)
+		regmap_read(map, MAX17042_RepSOC, &soc);
+	else
+		regmap_read(map, MAX17042_VFSOC, &soc);
 	soc >>= 8;
 	soc_tr = (soc + off) << 8;
-	soc_tr |= (soc - off);
+	if (off < soc)
+		soc_tr |= soc - off;
 	regmap_write(map, MAX17042_SALRT_Th, soc_tr);
 }
 
@@ -842,8 +849,12 @@
 {
 	struct max17042_chip *chip = dev;
 	u32 val;
+	int ret;
+
+	ret = regmap_read(chip->regmap, MAX17042_STATUS, &val);
+	if (ret)
+		return IRQ_HANDLED;
 
-	regmap_read(chip->regmap, MAX17042_STATUS, &val);
 	if ((val & STATUS_INTR_SOCMIN_BIT) ||
 		(val & STATUS_INTR_SOCMAX_BIT)) {
 		dev_info(&chip->client->dev, "SOC threshold INTR\n");
@@ -1076,7 +1087,7 @@
 	}
 
 	if (client->irq) {
-		unsigned int flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
+		unsigned int flags = IRQF_ONESHOT;
 
 		/*
 		 * On ACPI systems the IRQ may be handled by ACPI-event code,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/max77693_charger.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/max77693_charger.c
@@ -556,7 +556,7 @@
 	case 4700000:
 	case 4800000:
 	case 4900000:
-		data = (uvolt - 4700000) / 100000;
+		data = ((uvolt - 4700000) / 100000) + 1;
 		break;
 	default:
 		dev_err(chg->dev, "Wrong value for charge input voltage regulation threshold\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/pm2301_charger.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/pm2301_charger.c
@@ -1095,7 +1095,7 @@
 	ret = request_threaded_irq(gpio_to_irq(pm2->pdata->gpio_irq_number),
 				NULL,
 				pm2xxx_charger_irq[0].isr,
-				pm2->pdata->irq_type,
+				pm2->pdata->irq_type | IRQF_ONESHOT,
 				pm2xxx_charger_irq[0].name, pm2);
 
 	if (ret != 0) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/power_supply_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/power_supply_core.c
@@ -347,6 +347,10 @@
 	struct power_supply *psy = dev_get_drvdata(dev);
 	unsigned int *count = data;
 
+	if (!psy->desc->get_property(psy, POWER_SUPPLY_PROP_SCOPE, &ret))
+		if (ret.intval == POWER_SUPPLY_SCOPE_DEVICE)
+			return 0;
+
 	(*count)++;
 	if (psy->desc->type != POWER_SUPPLY_TYPE_BATTERY)
 		if (!psy->desc->get_property(psy, POWER_SUPPLY_PROP_ONLINE,
@@ -365,8 +369,8 @@
 				      __power_supply_is_system_supplied);
 
 	/*
-	 * If no power class device was found at all, most probably we are
-	 * running on a desktop system, so assume we are on mains power.
+	 * If no system scope power class device was found at all, most probably we
+	 * are running on a desktop system, so assume we are on mains power.
 	 */
 	if (count == 0)
 		return 1;
@@ -375,46 +379,49 @@
 }
 EXPORT_SYMBOL_GPL(power_supply_is_system_supplied);
 
-static int __power_supply_get_supplier_max_current(struct device *dev,
-						   void *data)
+struct psy_get_supplier_prop_data {
+	struct power_supply *psy;
+	enum power_supply_property psp;
+	union power_supply_propval *val;
+};
+
+static int __power_supply_get_supplier_property(struct device *dev, void *_data)
 {
-	union power_supply_propval ret = {0,};
 	struct power_supply *epsy = dev_get_drvdata(dev);
-	struct power_supply *psy = data;
+	struct psy_get_supplier_prop_data *data = _data;
 
-	if (__power_supply_is_supplied_by(epsy, psy))
-		if (!epsy->desc->get_property(epsy,
-					      POWER_SUPPLY_PROP_CURRENT_MAX,
-					      &ret))
-			return ret.intval;
+	if (__power_supply_is_supplied_by(epsy, data->psy))
+		if (!epsy->desc->get_property(epsy, data->psp, data->val))
+			return 1; /* Success */
 
-	return 0;
+	return 0; /* Continue iterating */
 }
 
-int power_supply_set_input_current_limit_from_supplier(struct power_supply *psy)
+int power_supply_get_property_from_supplier(struct power_supply *psy,
+					    enum power_supply_property psp,
+					    union power_supply_propval *val)
 {
-	union power_supply_propval val = {0,};
-	int curr;
-
-	if (!psy->desc->set_property)
-		return -EINVAL;
+	struct psy_get_supplier_prop_data data = {
+		.psy = psy,
+		.psp = psp,
+		.val = val,
+	};
+	int ret;
 
 	/*
 	 * This function is not intended for use with a supply with multiple
-	 * suppliers, we simply pick the first supply to report a non 0
-	 * max-current.
+	 * suppliers, we simply pick the first supply to report the psp.
 	 */
-	curr = class_for_each_device(power_supply_class, NULL, psy,
-				      __power_supply_get_supplier_max_current);
-	if (curr <= 0)
-		return (curr == 0) ? -ENODEV : curr;
-
-	val.intval = curr;
+	ret = class_for_each_device(power_supply_class, NULL, &data,
+				    __power_supply_get_supplier_property);
+	if (ret < 0)
+		return ret;
+	if (ret == 0)
+		return -ENODEV;
 
-	return psy->desc->set_property(psy,
-				POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, &val);
+	return 0;
 }
-EXPORT_SYMBOL_GPL(power_supply_set_input_current_limit_from_supplier);
+EXPORT_SYMBOL_GPL(power_supply_get_property_from_supplier);
 
 int power_supply_set_battery_charged(struct power_supply *psy)
 {
@@ -472,8 +479,6 @@
  */
 void power_supply_put(struct power_supply *psy)
 {
-	might_sleep();
-
 	atomic_dec(&psy->use_cnt);
 	put_device(&psy->dev);
 }
@@ -648,6 +653,11 @@
 		int i, tab_len, size;
 
 		propname = kasprintf(GFP_KERNEL, "ocv-capacity-table-%d", index);
+		if (!propname) {
+			power_supply_put_battery_info(psy, info);
+			err = -ENOMEM;
+			goto out_put_node;
+		}
 		list = of_get_property(battery_np, propname, &size);
 		if (!list || !size) {
 			dev_err(&psy->dev, "failed to get %s\n", propname);
@@ -742,6 +752,10 @@
 		return NULL;
 
 	for (i = 0; i < POWER_SUPPLY_OCV_TEMP_MAX; i++) {
+		/* Out of capacity tables */
+		if (!info->ocv_table[i])
+			break;
+
 		temp_diff = abs(info->ocv_temp[i] - temp);
 
 		if (temp_diff < best_temp_diff) {
@@ -1100,8 +1114,8 @@
 register_cooler_failed:
 	psy_unregister_thermal(psy);
 register_thermal_failed:
-	device_del(dev);
 wakeup_init_failed:
+	device_del(dev);
 device_add_failed:
 check_supplies_failed:
 dev_set_name_failed:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/power_supply_hwmon.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/power_supply_hwmon.c
@@ -144,7 +144,7 @@
 					  u32 attr, int channel,
 					  const char **str)
 {
-	*str = channel ? "temp" : "temp ambient";
+	*str = channel ? "temp ambient" : "temp";
 	return 0;
 }
 
@@ -304,7 +304,7 @@
 		goto error;
 	}
 
-	ret = devm_add_action(dev, power_supply_hwmon_bitmap_free,
+	ret = devm_add_action_or_reset(dev, power_supply_hwmon_bitmap_free,
 			      psyhw->props);
 	if (ret)
 		goto error;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/power_supply_leds.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/power_supply_leds.c
@@ -34,8 +34,9 @@
 		led_trigger_event(psy->charging_full_trig, LED_FULL);
 		led_trigger_event(psy->charging_trig, LED_OFF);
 		led_trigger_event(psy->full_trig, LED_FULL);
-		led_trigger_event(psy->charging_blink_full_solid_trig,
-			LED_FULL);
+		/* Going from blink to LED on requires a LED_OFF event to stop blink */
+		led_trigger_event(psy->charging_blink_full_solid_trig, LED_OFF);
+		led_trigger_event(psy->charging_blink_full_solid_trig, LED_FULL);
 		break;
 	case POWER_SUPPLY_STATUS_CHARGING:
 		led_trigger_event(psy->charging_full_trig, LED_FULL);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/power_supply_sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/power_supply_sysfs.c
@@ -127,7 +127,8 @@
 
 		if (ret < 0) {
 			if (ret == -ENODATA)
-				dev_dbg(dev, "driver has no data for `%s' property\n",
+				dev_dbg_ratelimited(dev,
+					"driver has no data for `%s' property\n",
 					attr->attr.name);
 			else if (ret != -ENODEV && ret != -EAGAIN)
 				dev_err_ratelimited(dev,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/rt5033_battery.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/rt5033_battery.c
@@ -60,7 +60,7 @@
 	regmap_read(battery->regmap, regh, &msb);
 	regmap_read(battery->regmap, regl, &lsb);
 
-	ret = ((msb << 4) + (lsb >> 4)) * 1250 / 1000;
+	ret = ((msb << 4) + (lsb >> 4)) * 1250;
 
 	return ret;
 }
@@ -164,9 +164,16 @@
 };
 MODULE_DEVICE_TABLE(i2c, rt5033_battery_id);
 
+static const struct of_device_id rt5033_battery_of_match[] = {
+	{ .compatible = "richtek,rt5033-battery", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, rt5033_battery_of_match);
+
 static struct i2c_driver rt5033_battery_driver = {
 	.driver = {
 		.name = "rt5033-battery",
+		.of_match_table = rt5033_battery_of_match,
 	},
 	.probe = rt5033_battery_probe,
 	.remove = rt5033_battery_remove,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/rt9455_charger.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/rt9455_charger.c
@@ -193,6 +193,7 @@
 	4450000, 4450000, 4450000, 4450000, 4450000, 4450000, 4450000, 4450000
 };
 
+#if IS_ENABLED(CONFIG_USB_PHY)
 /*
  * When the charger is in boost mode, REG02[7:2] represent boost output
  * voltage.
@@ -208,6 +209,7 @@
 	5600000, 5600000, 5600000, 5600000, 5600000, 5600000, 5600000, 5600000,
 	5600000, 5600000, 5600000, 5600000, 5600000, 5600000, 5600000, 5600000,
 };
+#endif
 
 /* REG07[3:0] (VMREG) in uV */
 static const int rt9455_vmreg_values[] = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/s3c_adc_battery.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/s3c_adc_battery.c
@@ -394,7 +394,7 @@
 		gpio_free(pdata->gpio_charge_finished);
 	}
 
-	cancel_delayed_work(&bat_work);
+	cancel_delayed_work_sync(&bat_work);
 
 	if (pdata->exit)
 		pdata->exit();
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/sbs-charger.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/sbs-charger.c
@@ -25,7 +25,7 @@
 #define SBS_CHARGER_REG_STATUS			0x13
 #define SBS_CHARGER_REG_ALARM_WARNING		0x16
 
-#define SBS_CHARGER_STATUS_CHARGE_INHIBITED	BIT(1)
+#define SBS_CHARGER_STATUS_CHARGE_INHIBITED	BIT(0)
 #define SBS_CHARGER_STATUS_RES_COLD		BIT(9)
 #define SBS_CHARGER_STATUS_RES_HOT		BIT(10)
 #define SBS_CHARGER_STATUS_BATTERY_PRESENT	BIT(14)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/sc2731_charger.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/sc2731_charger.c
@@ -524,6 +524,7 @@
 	{ .compatible = "sprd,sc2731-charger", },
 	{ }
 };
+MODULE_DEVICE_TABLE(of, sc2731_charger_of_match);
 
 static struct platform_driver sc2731_charger_driver = {
 	.driver = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/sc27xx_fuel_gauge.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/sc27xx_fuel_gauge.c
@@ -634,13 +634,6 @@
 	return ret;
 }
 
-static void sc27xx_fgu_external_power_changed(struct power_supply *psy)
-{
-	struct sc27xx_fgu_data *data = power_supply_get_drvdata(psy);
-
-	power_supply_changed(data->battery);
-}
-
 static int sc27xx_fgu_property_is_writeable(struct power_supply *psy,
 					    enum power_supply_property psp)
 {
@@ -671,7 +664,7 @@
 	.num_properties		= ARRAY_SIZE(sc27xx_fgu_props),
 	.get_property		= sc27xx_fgu_get_property,
 	.set_property		= sc27xx_fgu_set_property,
-	.external_power_changed	= sc27xx_fgu_external_power_changed,
+	.external_power_changed	= power_supply_changed,
 	.property_is_writeable	= sc27xx_fgu_property_is_writeable,
 };
 
@@ -1215,6 +1208,7 @@
 	{ .compatible = "sprd,sc2731-fgu", },
 	{ }
 };
+MODULE_DEVICE_TABLE(of, sc27xx_fgu_of_match);
 
 static struct platform_driver sc27xx_fgu_driver = {
 	.probe = sc27xx_fgu_probe,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/smb347-charger.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/smb347-charger.c
@@ -1138,6 +1138,7 @@
 	switch (reg) {
 	case IRQSTAT_A:
 	case IRQSTAT_C:
+	case IRQSTAT_D:
 	case IRQSTAT_E:
 	case IRQSTAT_F:
 	case STAT_A:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/test_power.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/test_power.c
@@ -341,6 +341,7 @@
 static int param_get_ac_online(char *buffer, const struct kernel_param *kp)
 {
 	strcpy(buffer, map_get_key(map_ac_online, ac_online, "unknown"));
+	strcat(buffer, "\n");
 	return strlen(buffer);
 }
 
@@ -354,6 +355,7 @@
 static int param_get_usb_online(char *buffer, const struct kernel_param *kp)
 {
 	strcpy(buffer, map_get_key(map_ac_online, usb_online, "unknown"));
+	strcat(buffer, "\n");
 	return strlen(buffer);
 }
 
@@ -368,6 +370,7 @@
 static int param_get_battery_status(char *buffer, const struct kernel_param *kp)
 {
 	strcpy(buffer, map_get_key(map_status, battery_status, "unknown"));
+	strcat(buffer, "\n");
 	return strlen(buffer);
 }
 
@@ -382,6 +385,7 @@
 static int param_get_battery_health(char *buffer, const struct kernel_param *kp)
 {
 	strcpy(buffer, map_get_key(map_health, battery_health, "unknown"));
+	strcat(buffer, "\n");
 	return strlen(buffer);
 }
 
@@ -397,6 +401,7 @@
 					const struct kernel_param *kp)
 {
 	strcpy(buffer, map_get_key(map_present, battery_present, "unknown"));
+	strcat(buffer, "\n");
 	return strlen(buffer);
 }
 
@@ -414,6 +419,7 @@
 {
 	strcpy(buffer,
 		map_get_key(map_technology, battery_technology, "unknown"));
+	strcat(buffer, "\n");
 	return strlen(buffer);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/tps65090-charger.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/tps65090-charger.c
@@ -301,7 +301,7 @@
 
 	if (irq != -ENXIO) {
 		ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
-			tps65090_charger_isr, 0, "tps65090-charger", cdata);
+			tps65090_charger_isr, IRQF_ONESHOT, "tps65090-charger", cdata);
 		if (ret) {
 			dev_err(cdata->dev,
 				"Unable to register irq %d err %d\n", irq,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/tps65217_charger.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/tps65217_charger.c
@@ -238,7 +238,7 @@
 	for (i = 0; i < NUM_CHARGER_IRQS; i++) {
 		ret = devm_request_threaded_irq(&pdev->dev, irq[i], NULL,
 						tps65217_charger_irq,
-						0, "tps65217-charger",
+						IRQF_ONESHOT, "tps65217-charger",
 						charger);
 		if (ret) {
 			dev_err(charger->dev,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/power/supply/wm8350_power.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/power/supply/wm8350_power.c
@@ -408,44 +408,112 @@
  *		Initialisation
  *********************************************************************/
 
-static void wm8350_init_charger(struct wm8350 *wm8350)
+static int wm8350_init_charger(struct wm8350 *wm8350)
 {
+	int ret;
+
 	/* register our interest in charger events */
-	wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT,
+	ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT,
 			    wm8350_charger_handler, 0, "Battery hot", wm8350);
-	wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD,
+	if (ret)
+		goto err;
+
+	ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD,
 			    wm8350_charger_handler, 0, "Battery cold", wm8350);
-	wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL,
+	if (ret)
+		goto free_chg_bat_hot;
+
+	ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL,
 			    wm8350_charger_handler, 0, "Battery fail", wm8350);
-	wm8350_register_irq(wm8350, WM8350_IRQ_CHG_TO,
+	if (ret)
+		goto free_chg_bat_cold;
+
+	ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_TO,
 			    wm8350_charger_handler, 0,
 			    "Charger timeout", wm8350);
-	wm8350_register_irq(wm8350, WM8350_IRQ_CHG_END,
+	if (ret)
+		goto free_chg_bat_fail;
+
+	ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_END,
 			    wm8350_charger_handler, 0,
 			    "Charge end", wm8350);
-	wm8350_register_irq(wm8350, WM8350_IRQ_CHG_START,
+	if (ret)
+		goto free_chg_to;
+
+	ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_START,
 			    wm8350_charger_handler, 0,
 			    "Charge start", wm8350);
-	wm8350_register_irq(wm8350, WM8350_IRQ_CHG_FAST_RDY,
+	if (ret)
+		goto free_chg_end;
+
+	ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_FAST_RDY,
 			    wm8350_charger_handler, 0,
 			    "Fast charge ready", wm8350);
-	wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9,
+	if (ret)
+		goto free_chg_start;
+
+	ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9,
 			    wm8350_charger_handler, 0,
 			    "Battery <3.9V", wm8350);
-	wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1,
+	if (ret)
+		goto free_chg_fast_rdy;
+
+	ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1,
 			    wm8350_charger_handler, 0,
 			    "Battery <3.1V", wm8350);
-	wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85,
+	if (ret)
+		goto free_chg_vbatt_lt_3p9;
+
+	ret = wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85,
 			    wm8350_charger_handler, 0,
 			    "Battery <2.85V", wm8350);
+	if (ret)
+		goto free_chg_vbatt_lt_3p1;
 
 	/* and supply change events */
-	wm8350_register_irq(wm8350, WM8350_IRQ_EXT_USB_FB,
+	ret = wm8350_register_irq(wm8350, WM8350_IRQ_EXT_USB_FB,
 			    wm8350_charger_handler, 0, "USB", wm8350);
-	wm8350_register_irq(wm8350, WM8350_IRQ_EXT_WALL_FB,
+	if (ret)
+		goto free_chg_vbatt_lt_2p85;
+
+	ret = wm8350_register_irq(wm8350, WM8350_IRQ_EXT_WALL_FB,
 			    wm8350_charger_handler, 0, "Wall", wm8350);
-	wm8350_register_irq(wm8350, WM8350_IRQ_EXT_BAT_FB,
+	if (ret)
+		goto free_ext_usb_fb;
+
+	ret = wm8350_register_irq(wm8350, WM8350_IRQ_EXT_BAT_FB,
 			    wm8350_charger_handler, 0, "Battery", wm8350);
+	if (ret)
+		goto free_ext_wall_fb;
+
+	return 0;
+
+free_ext_wall_fb:
+	wm8350_free_irq(wm8350, WM8350_IRQ_EXT_WALL_FB, wm8350);
+free_ext_usb_fb:
+	wm8350_free_irq(wm8350, WM8350_IRQ_EXT_USB_FB, wm8350);
+free_chg_vbatt_lt_2p85:
+	wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85, wm8350);
+free_chg_vbatt_lt_3p1:
+	wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1, wm8350);
+free_chg_vbatt_lt_3p9:
+	wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9, wm8350);
+free_chg_fast_rdy:
+	wm8350_free_irq(wm8350, WM8350_IRQ_CHG_FAST_RDY, wm8350);
+free_chg_start:
+	wm8350_free_irq(wm8350, WM8350_IRQ_CHG_START, wm8350);
+free_chg_end:
+	wm8350_free_irq(wm8350, WM8350_IRQ_CHG_END, wm8350);
+free_chg_to:
+	wm8350_free_irq(wm8350, WM8350_IRQ_CHG_TO, wm8350);
+free_chg_bat_fail:
+	wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL, wm8350);
+free_chg_bat_cold:
+	wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD, wm8350);
+free_chg_bat_hot:
+	wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT, wm8350);
+err:
+	return ret;
 }
 
 static void free_charger_irq(struct wm8350 *wm8350)
@@ -456,6 +524,7 @@
 	wm8350_free_irq(wm8350, WM8350_IRQ_CHG_TO, wm8350);
 	wm8350_free_irq(wm8350, WM8350_IRQ_CHG_END, wm8350);
 	wm8350_free_irq(wm8350, WM8350_IRQ_CHG_START, wm8350);
+	wm8350_free_irq(wm8350, WM8350_IRQ_CHG_FAST_RDY, wm8350);
 	wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9, wm8350);
 	wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1, wm8350);
 	wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85, wm8350);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/powercap/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/powercap/Kconfig
@@ -18,10 +18,12 @@
 # Client driver configurations go here.
 config INTEL_RAPL_CORE
 	tristate
+	depends on PCI
+	select IOSF_MBI
 
 config INTEL_RAPL
 	tristate "Intel RAPL Support via MSR Interface"
-	depends on X86 && IOSF_MBI
+	depends on X86 && PCI
 	select INTEL_RAPL_CORE
 	---help---
 	  This enables support for the Intel Running Average Power Limit (RAPL)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/powercap/intel_rapl_common.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/powercap/intel_rapl_common.c
@@ -885,6 +885,9 @@
 		y = value & 0x1f;
 		value = (1 << y) * (4 + f) * rp->time_unit / 4;
 	} else {
+		if (value < rp->time_unit)
+			return 0;
+
 		do_div(value, rp->time_unit);
 		y = ilog2(value);
 		f = div64_u64(4 * (value - (1 << y)), 1 << y);
@@ -978,6 +981,8 @@
 	INTEL_CPU_FAM6(ICELAKE_NNPI, rapl_defaults_core),
 	INTEL_CPU_FAM6(ICELAKE_X, rapl_defaults_hsw_server),
 	INTEL_CPU_FAM6(ICELAKE_D, rapl_defaults_hsw_server),
+	INTEL_CPU_FAM6(COMETLAKE_L, rapl_defaults_core),
+	INTEL_CPU_FAM6(COMETLAKE, rapl_defaults_core),
 
 	INTEL_CPU_FAM6(ATOM_SILVERMONT, rapl_defaults_byt),
 	INTEL_CPU_FAM6(ATOM_AIRMONT, rapl_defaults_cht),
@@ -1293,6 +1298,9 @@
 	struct cpuinfo_x86 *c = &cpu_data(cpu);
 	int ret;
 
+	if (!rapl_defaults)
+		return ERR_PTR(-ENODEV);
+
 	rp = kzalloc(sizeof(struct rapl_package), GFP_KERNEL);
 	if (!rp)
 		return ERR_PTR(-ENOMEM);
@@ -1419,7 +1427,7 @@
 
 	id = x86_match_cpu(rapl_ids);
 	if (!id) {
-		pr_err("driver does not support CPU family %d model %d\n",
+		pr_info("driver does not support CPU family %d model %d\n",
 		       boot_cpu_data.x86, boot_cpu_data.x86_model);
 
 		return -ENODEV;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/powercap/intel_rapl_msr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/powercap/intel_rapl_msr.c
@@ -22,7 +22,6 @@
 #include <linux/processor.h>
 #include <linux/platform_device.h>
 
-#include <asm/iosf_mbi.h>
 #include <asm/cpu_device_id.h>
 #include <asm/intel-family.h>
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/powercap/powercap_sys.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/powercap/powercap_sys.c
@@ -224,46 +224,46 @@
 
 	for (i = 0; i < MAX_CONSTRAINTS_PER_ZONE; ++i) {
 		ret = create_constraint_attribute(i, "power_limit_uw",
-					S_IWUSR | S_IRUGO,
+					S_IWUSR | S_IRUSR,
 					&constraint_attrs[i].power_limit_attr,
 					show_constraint_power_limit_uw,
 					store_constraint_power_limit_uw);
 		if (ret)
 			goto err_alloc;
 		ret = create_constraint_attribute(i, "time_window_us",
-					S_IWUSR | S_IRUGO,
+					S_IWUSR | S_IRUSR,
 					&constraint_attrs[i].time_window_attr,
 					show_constraint_time_window_us,
 					store_constraint_time_window_us);
 		if (ret)
 			goto err_alloc;
-		ret = create_constraint_attribute(i, "name", S_IRUGO,
+		ret = create_constraint_attribute(i, "name", S_IRUSR,
 				&constraint_attrs[i].name_attr,
 				show_constraint_name,
 				NULL);
 		if (ret)
 			goto err_alloc;
-		ret = create_constraint_attribute(i, "max_power_uw", S_IRUGO,
+		ret = create_constraint_attribute(i, "max_power_uw", S_IRUSR,
 				&constraint_attrs[i].max_power_attr,
 				show_constraint_max_power_uw,
 				NULL);
 		if (ret)
 			goto err_alloc;
-		ret = create_constraint_attribute(i, "min_power_uw", S_IRUGO,
+		ret = create_constraint_attribute(i, "min_power_uw", S_IRUSR,
 				&constraint_attrs[i].min_power_attr,
 				show_constraint_min_power_uw,
 				NULL);
 		if (ret)
 			goto err_alloc;
 		ret = create_constraint_attribute(i, "max_time_window_us",
-				S_IRUGO,
+				S_IRUSR,
 				&constraint_attrs[i].max_time_window_attr,
 				show_constraint_max_time_window_us,
 				NULL);
 		if (ret)
 			goto err_alloc;
 		ret = create_constraint_attribute(i, "min_time_window_us",
-				S_IRUGO,
+				S_IRUSR,
 				&constraint_attrs[i].min_time_window_attr,
 				show_constraint_min_time_window_us,
 				NULL);
@@ -362,23 +362,29 @@
 	int count = 0;
 
 	power_zone->zone_dev_attrs[count++] = &dev_attr_name.attr;
-	if (power_zone->ops->get_max_energy_range_uj)
+	if (power_zone->ops->get_max_energy_range_uj) {
+		dev_attr_max_energy_range_uj.attr.mode = S_IRUSR;
 		power_zone->zone_dev_attrs[count++] =
 					&dev_attr_max_energy_range_uj.attr;
+	}
 	if (power_zone->ops->get_energy_uj) {
 		if (power_zone->ops->reset_energy_uj)
-			dev_attr_energy_uj.attr.mode = S_IWUSR | S_IRUGO;
+			dev_attr_energy_uj.attr.mode = S_IWUSR | S_IRUSR;
 		else
-			dev_attr_energy_uj.attr.mode = S_IRUGO;
+			dev_attr_energy_uj.attr.mode = S_IRUSR;
 		power_zone->zone_dev_attrs[count++] =
 					&dev_attr_energy_uj.attr;
 	}
-	if (power_zone->ops->get_power_uw)
+	if (power_zone->ops->get_power_uw) {
+		dev_attr_power_uw.attr.mode = S_IRUSR;
 		power_zone->zone_dev_attrs[count++] =
 					&dev_attr_power_uw.attr;
-	if (power_zone->ops->get_max_power_range_uw)
+	}
+	if (power_zone->ops->get_max_power_range_uw) {
+		dev_attr_max_power_range_uw.attr.mode = S_IRUSR;
 		power_zone->zone_dev_attrs[count++] =
 					&dev_attr_max_power_range_uw.attr;
+	}
 	power_zone->zone_dev_attrs[count] = NULL;
 	power_zone->zone_attr_count = count;
 }
@@ -530,9 +536,6 @@
 	power_zone->name = kstrdup(name, GFP_KERNEL);
 	if (!power_zone->name)
 		goto err_name_alloc;
-	dev_set_name(&power_zone->dev, "%s:%x",
-					dev_name(power_zone->dev.parent),
-					power_zone->id);
 	power_zone->constraints = kcalloc(nr_constraints,
 					  sizeof(*power_zone->constraints),
 					  GFP_KERNEL);
@@ -555,9 +558,16 @@
 	power_zone->dev_attr_groups[0] = &power_zone->dev_zone_attr_group;
 	power_zone->dev_attr_groups[1] = NULL;
 	power_zone->dev.groups = power_zone->dev_attr_groups;
+	dev_set_name(&power_zone->dev, "%s:%x",
+					dev_name(power_zone->dev.parent),
+					power_zone->id);
 	result = device_register(&power_zone->dev);
-	if (result)
-		goto err_dev_ret;
+	if (result) {
+		put_device(&power_zone->dev);
+		mutex_unlock(&control_type->lock);
+
+		return ERR_PTR(result);
+	}
 
 	control_type->nr_zones++;
 	mutex_unlock(&control_type->lock);
@@ -623,8 +633,7 @@
 	dev_set_name(&control_type->dev, "%s", name);
 	result = device_register(&control_type->dev);
 	if (result) {
-		if (control_type->allocated)
-			kfree(control_type);
+		put_device(&control_type->dev);
 		return ERR_PTR(result);
 	}
 	idr_init(&control_type->idr);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pps/clients/pps-gpio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pps/clients/pps-gpio.c
@@ -232,8 +232,8 @@
 		return -EINVAL;
 	}
 
-	dev_info(data->pps->dev, "Registered IRQ %d as PPS source\n",
-		 data->irq);
+	dev_dbg(&data->pps->dev, "Registered IRQ %d as PPS source\n",
+		data->irq);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pps/clients/pps-ktimer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pps/clients/pps-ktimer.c
@@ -56,7 +56,7 @@
 
 static void __exit pps_ktimer_exit(void)
 {
-	dev_info(pps->dev, "ktimer PPS source unregistered\n");
+	dev_dbg(&pps->dev, "ktimer PPS source unregistered\n");
 
 	del_timer_sync(&ktimer);
 	pps_unregister_source(pps);
@@ -74,7 +74,7 @@
 	timer_setup(&ktimer, pps_ktimer_event, 0);
 	mod_timer(&ktimer, jiffies + HZ);
 
-	dev_info(pps->dev, "ktimer PPS source registered\n");
+	dev_dbg(&pps->dev, "ktimer PPS source registered\n");
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pps/clients/pps-ldisc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pps/clients/pps-ldisc.c
@@ -34,7 +34,7 @@
 	pps_event(pps, &ts, status ? PPS_CAPTUREASSERT :
 			PPS_CAPTURECLEAR, NULL);
 
-	dev_dbg(pps->dev, "PPS %s at %lu\n",
+	dev_dbg(&pps->dev, "PPS %s at %lu\n",
 			status ? "assert" : "clear", jiffies);
 }
 
@@ -71,7 +71,7 @@
 		goto err_unregister;
 	}
 
-	dev_info(pps->dev, "source \"%s\" added\n", info.path);
+	dev_dbg(&pps->dev, "source \"%s\" added\n", info.path);
 
 	return 0;
 
@@ -91,7 +91,7 @@
 	if (WARN_ON(!pps))
 		return;
 
-	dev_info(pps->dev, "removed\n");
+	dev_info(&pps->dev, "removed\n");
 	pps_unregister_source(pps);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pps/clients/pps_parport.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pps/clients/pps_parport.c
@@ -83,7 +83,7 @@
 	/* check the signal (no signal means the pulse is lost this time) */
 	if (!signal_is_set(port)) {
 		local_irq_restore(flags);
-		dev_err(dev->pps->dev, "lost the signal\n");
+		dev_err(&dev->pps->dev, "lost the signal\n");
 		goto out_assert;
 	}
 
@@ -100,7 +100,7 @@
 	/* timeout */
 	dev->cw_err++;
 	if (dev->cw_err >= CLEAR_WAIT_MAX_ERRORS) {
-		dev_err(dev->pps->dev, "disabled clear edge capture after %d"
+		dev_err(&dev->pps->dev, "disabled clear edge capture after %d"
 				" timeouts\n", dev->cw_err);
 		dev->cw = 0;
 		dev->cw_err = 0;
@@ -144,7 +144,10 @@
 		return;
 	}
 
-	index = ida_simple_get(&pps_client_index, 0, 0, GFP_KERNEL);
+	index = ida_alloc(&pps_client_index, GFP_KERNEL);
+	if (index < 0)
+		goto err_free_device;
+
 	memset(&pps_client_cb, 0, sizeof(pps_client_cb));
 	pps_client_cb.private = device;
 	pps_client_cb.irq_func = parport_irq;
@@ -155,7 +158,7 @@
 						    index);
 	if (!device->pardev) {
 		pr_err("couldn't register with %s\n", port->name);
-		goto err_free;
+		goto err_free_ida;
 	}
 
 	if (parport_claim_or_block(device->pardev) < 0) {
@@ -183,8 +186,9 @@
 	parport_release(device->pardev);
 err_unregister_dev:
 	parport_unregister_device(device->pardev);
-err_free:
-	ida_simple_remove(&pps_client_index, index);
+err_free_ida:
+	ida_free(&pps_client_index, index);
+err_free_device:
 	kfree(device);
 }
 
@@ -204,7 +208,7 @@
 	pps_unregister_source(device->pps);
 	parport_release(pardev);
 	parport_unregister_device(pardev);
-	ida_simple_remove(&pps_client_index, device->index);
+	ida_free(&pps_client_index, device->index);
 	kfree(device);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pps/kapi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pps/kapi.c
@@ -41,7 +41,7 @@
 static void pps_echo_client_default(struct pps_device *pps, int event,
 		void *data)
 {
-	dev_info(pps->dev, "echo %s %s\n",
+	dev_info(&pps->dev, "echo %s %s\n",
 		event & PPS_CAPTUREASSERT ? "assert" : "",
 		event & PPS_CAPTURECLEAR ? "clear" : "");
 }
@@ -112,7 +112,7 @@
 		goto kfree_pps;
 	}
 
-	dev_info(pps->dev, "new PPS source %s\n", info->name);
+	dev_dbg(&pps->dev, "new PPS source %s\n", info->name);
 
 	return pps;
 
@@ -166,7 +166,7 @@
 	/* check event type */
 	BUG_ON((event & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR)) == 0);
 
-	dev_dbg(pps->dev, "PPS event at %lld.%09ld\n",
+	dev_dbg(&pps->dev, "PPS event at %lld.%09ld\n",
 			(s64)ts->ts_real.tv_sec, ts->ts_real.tv_nsec);
 
 	timespec_to_pps_ktime(&ts_real, ts->ts_real);
@@ -188,7 +188,7 @@
 		/* Save the time stamp */
 		pps->assert_tu = ts_real;
 		pps->assert_sequence++;
-		dev_dbg(pps->dev, "capture assert seq #%u\n",
+		dev_dbg(&pps->dev, "capture assert seq #%u\n",
 			pps->assert_sequence);
 
 		captured = ~0;
@@ -202,7 +202,7 @@
 		/* Save the time stamp */
 		pps->clear_tu = ts_real;
 		pps->clear_sequence++;
-		dev_dbg(pps->dev, "capture clear seq #%u\n",
+		dev_dbg(&pps->dev, "capture clear seq #%u\n",
 			pps->clear_sequence);
 
 		captured = ~0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pps/kc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pps/kc.c
@@ -43,11 +43,11 @@
 			pps_kc_hardpps_mode = 0;
 			pps_kc_hardpps_dev = NULL;
 			spin_unlock_irq(&pps_kc_hardpps_lock);
-			dev_info(pps->dev, "unbound kernel"
+			dev_info(&pps->dev, "unbound kernel"
 					" consumer\n");
 		} else {
 			spin_unlock_irq(&pps_kc_hardpps_lock);
-			dev_err(pps->dev, "selected kernel consumer"
+			dev_err(&pps->dev, "selected kernel consumer"
 					" is not bound\n");
 			return -EINVAL;
 		}
@@ -57,11 +57,11 @@
 			pps_kc_hardpps_mode = bind_args->edge;
 			pps_kc_hardpps_dev = pps;
 			spin_unlock_irq(&pps_kc_hardpps_lock);
-			dev_info(pps->dev, "bound kernel consumer: "
+			dev_info(&pps->dev, "bound kernel consumer: "
 				"edge=0x%x\n", bind_args->edge);
 		} else {
 			spin_unlock_irq(&pps_kc_hardpps_lock);
-			dev_err(pps->dev, "another kernel consumer"
+			dev_err(&pps->dev, "another kernel consumer"
 					" is already bound\n");
 			return -EINVAL;
 		}
@@ -83,7 +83,7 @@
 		pps_kc_hardpps_mode = 0;
 		pps_kc_hardpps_dev = NULL;
 		spin_unlock_irq(&pps_kc_hardpps_lock);
-		dev_info(pps->dev, "unbound kernel consumer"
+		dev_info(&pps->dev, "unbound kernel consumer"
 				" on device removal\n");
 	} else
 		spin_unlock_irq(&pps_kc_hardpps_lock);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pps/pps.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pps/pps.c
@@ -25,7 +25,7 @@
  * Local variables
  */
 
-static dev_t pps_devt;
+static int pps_major;
 static struct class *pps_class;
 
 static DEFINE_MUTEX(pps_idr_lock);
@@ -62,7 +62,7 @@
 	else {
 		unsigned long ticks;
 
-		dev_dbg(pps->dev, "timeout %lld.%09d\n",
+		dev_dbg(&pps->dev, "timeout %lld.%09d\n",
 				(long long) fdata->timeout.sec,
 				fdata->timeout.nsec);
 		ticks = fdata->timeout.sec * HZ;
@@ -80,7 +80,7 @@
 
 	/* Check for pending signals */
 	if (err == -ERESTARTSYS) {
-		dev_dbg(pps->dev, "pending signal caught\n");
+		dev_dbg(&pps->dev, "pending signal caught\n");
 		return -EINTR;
 	}
 
@@ -98,7 +98,7 @@
 
 	switch (cmd) {
 	case PPS_GETPARAMS:
-		dev_dbg(pps->dev, "PPS_GETPARAMS\n");
+		dev_dbg(&pps->dev, "PPS_GETPARAMS\n");
 
 		spin_lock_irq(&pps->lock);
 
@@ -114,7 +114,7 @@
 		break;
 
 	case PPS_SETPARAMS:
-		dev_dbg(pps->dev, "PPS_SETPARAMS\n");
+		dev_dbg(&pps->dev, "PPS_SETPARAMS\n");
 
 		/* Check the capabilities */
 		if (!capable(CAP_SYS_TIME))
@@ -124,14 +124,14 @@
 		if (err)
 			return -EFAULT;
 		if (!(params.mode & (PPS_CAPTUREASSERT | PPS_CAPTURECLEAR))) {
-			dev_dbg(pps->dev, "capture mode unspecified (%x)\n",
+			dev_dbg(&pps->dev, "capture mode unspecified (%x)\n",
 								params.mode);
 			return -EINVAL;
 		}
 
 		/* Check for supported capabilities */
 		if ((params.mode & ~pps->info.mode) != 0) {
-			dev_dbg(pps->dev, "unsupported capabilities (%x)\n",
+			dev_dbg(&pps->dev, "unsupported capabilities (%x)\n",
 								params.mode);
 			return -EINVAL;
 		}
@@ -144,7 +144,7 @@
 		/* Restore the read only parameters */
 		if ((params.mode & (PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP)) == 0) {
 			/* section 3.3 of RFC 2783 interpreted */
-			dev_dbg(pps->dev, "time format unspecified (%x)\n",
+			dev_dbg(&pps->dev, "time format unspecified (%x)\n",
 								params.mode);
 			pps->params.mode |= PPS_TSFMT_TSPEC;
 		}
@@ -165,7 +165,7 @@
 		break;
 
 	case PPS_GETCAP:
-		dev_dbg(pps->dev, "PPS_GETCAP\n");
+		dev_dbg(&pps->dev, "PPS_GETCAP\n");
 
 		err = put_user(pps->info.mode, iuarg);
 		if (err)
@@ -176,7 +176,7 @@
 	case PPS_FETCH: {
 		struct pps_fdata fdata;
 
-		dev_dbg(pps->dev, "PPS_FETCH\n");
+		dev_dbg(&pps->dev, "PPS_FETCH\n");
 
 		err = copy_from_user(&fdata, uarg, sizeof(struct pps_fdata));
 		if (err)
@@ -206,7 +206,7 @@
 	case PPS_KC_BIND: {
 		struct pps_bind_args bind_args;
 
-		dev_dbg(pps->dev, "PPS_KC_BIND\n");
+		dev_dbg(&pps->dev, "PPS_KC_BIND\n");
 
 		/* Check the capabilities */
 		if (!capable(CAP_SYS_TIME))
@@ -218,7 +218,7 @@
 
 		/* Check for supported capabilities */
 		if ((bind_args.edge & ~pps->info.mode) != 0) {
-			dev_err(pps->dev, "unsupported capabilities (%x)\n",
+			dev_err(&pps->dev, "unsupported capabilities (%x)\n",
 					bind_args.edge);
 			return -EINVAL;
 		}
@@ -227,7 +227,7 @@
 		if (bind_args.tsformat != PPS_TSFMT_TSPEC ||
 				(bind_args.edge & ~PPS_CAPTUREBOTH) != 0 ||
 				bind_args.consumer != PPS_KC_HARDPPS) {
-			dev_err(pps->dev, "invalid kernel consumer bind"
+			dev_err(&pps->dev, "invalid kernel consumer bind"
 					" parameters (%x)\n", bind_args.edge);
 			return -EINVAL;
 		}
@@ -259,7 +259,7 @@
 		struct pps_fdata fdata;
 		int err;
 
-		dev_dbg(pps->dev, "PPS_FETCH\n");
+		dev_dbg(&pps->dev, "PPS_FETCH\n");
 
 		err = copy_from_user(&compat, uarg, sizeof(struct pps_fdata_compat));
 		if (err)
@@ -296,20 +296,36 @@
 #define pps_cdev_compat_ioctl	NULL
 #endif
 
+static struct pps_device *pps_idr_get(unsigned long id)
+{
+	struct pps_device *pps;
+
+	mutex_lock(&pps_idr_lock);
+	pps = idr_find(&pps_idr, id);
+	if (pps)
+		get_device(&pps->dev);
+
+	mutex_unlock(&pps_idr_lock);
+	return pps;
+}
+
 static int pps_cdev_open(struct inode *inode, struct file *file)
 {
-	struct pps_device *pps = container_of(inode->i_cdev,
-						struct pps_device, cdev);
+	struct pps_device *pps = pps_idr_get(iminor(inode));
+
+	if (!pps)
+		return -ENODEV;
+
 	file->private_data = pps;
-	kobject_get(&pps->dev->kobj);
 	return 0;
 }
 
 static int pps_cdev_release(struct inode *inode, struct file *file)
 {
-	struct pps_device *pps = container_of(inode->i_cdev,
-						struct pps_device, cdev);
-	kobject_put(&pps->dev->kobj);
+	struct pps_device *pps = file->private_data;
+
+	WARN_ON(pps->id != iminor(inode));
+	put_device(&pps->dev);
 	return 0;
 }
 
@@ -332,22 +348,13 @@
 {
 	struct pps_device *pps = dev_get_drvdata(dev);
 
-	cdev_del(&pps->cdev);
-
-	/* Now we can release the ID for re-use */
 	pr_debug("deallocating pps%d\n", pps->id);
-	mutex_lock(&pps_idr_lock);
-	idr_remove(&pps_idr, pps->id);
-	mutex_unlock(&pps_idr_lock);
-
-	kfree(dev);
 	kfree(pps);
 }
 
 int pps_register_cdev(struct pps_device *pps)
 {
 	int err;
-	dev_t devt;
 
 	mutex_lock(&pps_idr_lock);
 	/*
@@ -364,40 +371,29 @@
 		goto out_unlock;
 	}
 	pps->id = err;
-	mutex_unlock(&pps_idr_lock);
-
-	devt = MKDEV(MAJOR(pps_devt), pps->id);
-
-	cdev_init(&pps->cdev, &pps_cdev_fops);
-	pps->cdev.owner = pps->info.owner;
 
-	err = cdev_add(&pps->cdev, devt, 1);
-	if (err) {
-		pr_err("%s: failed to add char device %d:%d\n",
-				pps->info.name, MAJOR(pps_devt), pps->id);
+	pps->dev.class = pps_class;
+	pps->dev.parent = pps->info.dev;
+	pps->dev.devt = MKDEV(pps_major, pps->id);
+	dev_set_drvdata(&pps->dev, pps);
+	dev_set_name(&pps->dev, "pps%d", pps->id);
+	err = device_register(&pps->dev);
+	if (err)
 		goto free_idr;
-	}
-	pps->dev = device_create(pps_class, pps->info.dev, devt, pps,
-							"pps%d", pps->id);
-	if (IS_ERR(pps->dev)) {
-		err = PTR_ERR(pps->dev);
-		goto del_cdev;
-	}
 
 	/* Override the release function with our own */
-	pps->dev->release = pps_device_destruct;
+	pps->dev.release = pps_device_destruct;
 
-	pr_debug("source %s got cdev (%d:%d)\n", pps->info.name,
-			MAJOR(pps_devt), pps->id);
+	pr_debug("source %s got cdev (%d:%d)\n", pps->info.name, pps_major,
+		 pps->id);
 
+	get_device(&pps->dev);
+	mutex_unlock(&pps_idr_lock);
 	return 0;
 
-del_cdev:
-	cdev_del(&pps->cdev);
-
 free_idr:
-	mutex_lock(&pps_idr_lock);
 	idr_remove(&pps_idr, pps->id);
+	put_device(&pps->dev);
 out_unlock:
 	mutex_unlock(&pps_idr_lock);
 	return err;
@@ -407,7 +403,13 @@
 {
 	pr_debug("unregistering pps%d\n", pps->id);
 	pps->lookup_cookie = NULL;
-	device_destroy(pps_class, pps->dev->devt);
+	device_destroy(pps_class, pps->dev.devt);
+
+	/* Now we can release the ID for re-use */
+	mutex_lock(&pps_idr_lock);
+	idr_remove(&pps_idr, pps->id);
+	put_device(&pps->dev);
+	mutex_unlock(&pps_idr_lock);
 }
 
 /*
@@ -427,6 +429,11 @@
  * so that it will not be used again, even if the pps device cannot
  * be removed from the idr due to pending references holding the minor
  * number in use.
+ *
+ * Since pps_idr holds a reference to the device, the returned
+ * pps_device is guaranteed to be valid until pps_unregister_cdev() is
+ * called on it. But after calling pps_unregister_cdev(), it may be
+ * freed at any time.
  */
 struct pps_device *pps_lookup_dev(void const *cookie)
 {
@@ -449,13 +456,11 @@
 static void __exit pps_exit(void)
 {
 	class_destroy(pps_class);
-	unregister_chrdev_region(pps_devt, PPS_MAX_SOURCES);
+	__unregister_chrdev(pps_major, 0, PPS_MAX_SOURCES, "pps");
 }
 
 static int __init pps_init(void)
 {
-	int err;
-
 	pps_class = class_create(THIS_MODULE, "pps");
 	if (IS_ERR(pps_class)) {
 		pr_err("failed to allocate class\n");
@@ -463,8 +468,9 @@
 	}
 	pps_class->dev_groups = pps_groups;
 
-	err = alloc_chrdev_region(&pps_devt, 0, PPS_MAX_SOURCES, "pps");
-	if (err < 0) {
+	pps_major = __register_chrdev(0, 0, PPS_MAX_SOURCES, "pps",
+				      &pps_cdev_fops);
+	if (pps_major < 0) {
 		pr_err("failed to allocate char device region\n");
 		goto remove_class;
 	}
@@ -477,8 +483,7 @@
 
 remove_class:
 	class_destroy(pps_class);
-
-	return err;
+	return pps_major;
 }
 
 subsys_initcall(pps_init);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ps3/ps3stor_lib.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ps3/ps3stor_lib.c
@@ -189,7 +189,7 @@
 	dev->bounce_lpar = ps3_mm_phys_to_lpar(__pa(dev->bounce_buf));
 	dev->bounce_dma = dma_map_single(&dev->sbd.core, dev->bounce_buf,
 					 dev->bounce_size, DMA_BIDIRECTIONAL);
-	if (!dev->bounce_dma) {
+	if (dma_mapping_error(&dev->sbd.core, dev->bounce_dma)) {
 		dev_err(&dev->sbd.core, "%s:%u: map DMA region failed\n",
 			__func__, __LINE__);
 		error = -ENODEV;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ptp/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/ptp/Kconfig
@@ -92,7 +92,8 @@
 config PTP_1588_CLOCK_PCH
 	tristate "Intel PCH EG20T as PTP clock"
 	depends on X86_32 || COMPILE_TEST
-	depends on HAS_IOMEM && NET
+	depends on HAS_IOMEM && PCI
+	depends on NET
 	imply PTP_1588_CLOCK
 	help
 	  This driver adds support for using the PCH EG20T as a PTP
@@ -119,4 +120,14 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called ptp_kvm.
 
+config PTP_1588_CLOCK_XILINX
+	tristate "XILINX PTP clock"
+	depends on PTP_1588_CLOCK
+	help
+	  This driver adds support for Xilinx PTP clock. It provides
+	  timer-syncer support with time and fine adjustment capabilities.
+
+	  It is usually used with Xilinx AXI Ethernet driver with HW
+	  timestamping support.
+
 endmenu
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ptp/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/ptp/Makefile
@@ -9,6 +9,7 @@
 obj-$(CONFIG_PTP_1588_CLOCK_IXP46X)	+= ptp_ixp46x.o
 obj-$(CONFIG_PTP_1588_CLOCK_PCH)	+= ptp_pch.o
 obj-$(CONFIG_PTP_1588_CLOCK_KVM)	+= ptp_kvm.o
+obj-$(CONFIG_PTP_1588_CLOCK_XILINX)	+= ptp_xilinx.o
 obj-$(CONFIG_PTP_1588_CLOCK_QORIQ)	+= ptp-qoriq.o
 ptp-qoriq-y				+= ptp_qoriq.o
 ptp-qoriq-$(CONFIG_DEBUG_FS)		+= ptp_qoriq_debugfs.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ptp/ptp_chardev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ptp/ptp_chardev.c
@@ -84,7 +84,8 @@
 	}
 
 	if (info->verify(info, pin, func, chan)) {
-		pr_err("driver cannot use function %u on pin %u\n", func, chan);
+		pr_err("driver cannot use function %u and channel %u on pin %u\n",
+		       func, chan, pin);
 		return -EOPNOTSUPP;
 	}
 
@@ -443,7 +444,8 @@
 
 	for (i = 0; i < cnt; i++) {
 		event[i] = queue->buf[queue->head];
-		queue->head = (queue->head + 1) % PTP_MAX_TIMESTAMPS;
+		/* Paired with READ_ONCE() in queue_cnt() */
+		WRITE_ONCE(queue->head, (queue->head + 1) % PTP_MAX_TIMESTAMPS);
 	}
 
 	spin_unlock_irqrestore(&queue->lock, flags);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ptp/ptp_clock.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ptp/ptp_clock.c
@@ -55,15 +55,16 @@
 	dst->t.sec = seconds;
 	dst->t.nsec = remainder;
 
+	/* Both WRITE_ONCE() are paired with READ_ONCE() in queue_cnt() */
 	if (!queue_free(queue))
-		queue->head = (queue->head + 1) % PTP_MAX_TIMESTAMPS;
+		WRITE_ONCE(queue->head, (queue->head + 1) % PTP_MAX_TIMESTAMPS);
 
-	queue->tail = (queue->tail + 1) % PTP_MAX_TIMESTAMPS;
+	WRITE_ONCE(queue->tail, (queue->tail + 1) % PTP_MAX_TIMESTAMPS);
 
 	spin_unlock_irqrestore(&queue->lock, flags);
 }
 
-s32 scaled_ppm_to_ppb(long ppm)
+long scaled_ppm_to_ppb(long ppm)
 {
 	/*
 	 * The 'freq' field in the 'struct timex' is in parts per
@@ -80,7 +81,7 @@
 	s64 ppb = 1 + ppm;
 	ppb *= 125;
 	ppb >>= 13;
-	return (s32) ppb;
+	return (long) ppb;
 }
 EXPORT_SYMBOL(scaled_ppm_to_ppb);
 
@@ -138,7 +139,7 @@
 		delta = ktime_to_ns(kt);
 		err = ops->adjtime(ops, delta);
 	} else if (tx->modes & ADJ_FREQUENCY) {
-		s32 ppb = scaled_ppm_to_ppb(tx->freq);
+		long ppb = scaled_ppm_to_ppb(tx->freq);
 		if (ppb > ops->max_adj || ppb < -ops->max_adj)
 			return -ERANGE;
 		if (ops->adjfine)
@@ -166,16 +167,25 @@
 	.read		= ptp_read,
 };
 
-static void delete_ptp_clock(struct posix_clock *pc)
+static void ptp_clock_release(struct device *dev)
 {
-	struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
+	struct ptp_clock *ptp = container_of(dev, struct ptp_clock, dev);
 
+	/* Release the clock's resources. */
+	if (ptp->pps_source)
+		pps_unregister_source(ptp->pps_source);
+	ptp_cleanup_pin_groups(ptp);
 	mutex_destroy(&ptp->tsevq_mux);
 	mutex_destroy(&ptp->pincfg_mux);
 	ida_simple_remove(&ptp_clocks_map, ptp->index);
 	kfree(ptp);
 }
 
+static int ptp_enable(struct ptp_clock_info *ptp, struct ptp_clock_request *request, int on)
+{
+	return -EOPNOTSUPP;
+}
+
 static void ptp_aux_kworker(struct kthread_work *work)
 {
 	struct ptp_clock *ptp = container_of(work, struct ptp_clock,
@@ -213,7 +223,6 @@
 	}
 
 	ptp->clock.ops = ptp_clock_ops;
-	ptp->clock.release = delete_ptp_clock;
 	ptp->info = info;
 	ptp->devid = MKDEV(major, index);
 	ptp->index = index;
@@ -222,6 +231,9 @@
 	mutex_init(&ptp->pincfg_mux);
 	init_waitqueue_head(&ptp->tsev_wq);
 
+	if (!ptp->info->enable)
+		ptp->info->enable = ptp_enable;
+
 	if (ptp->info->do_aux_work) {
 		kthread_init_delayed_work(&ptp->aux_work, ptp_aux_kworker);
 		ptp->kworker = kthread_create_worker(0, "ptp%d", ptp->index);
@@ -236,15 +248,6 @@
 	if (err)
 		goto no_pin_groups;
 
-	/* Create a new device in our class. */
-	ptp->dev = device_create_with_groups(ptp_class, parent, ptp->devid,
-					     ptp, ptp->pin_attr_groups,
-					     "ptp%d", ptp->index);
-	if (IS_ERR(ptp->dev)) {
-		err = PTR_ERR(ptp->dev);
-		goto no_device;
-	}
-
 	/* Register a new PPS source. */
 	if (info->pps) {
 		struct pps_source_info pps;
@@ -260,8 +263,18 @@
 		}
 	}
 
-	/* Create a posix clock. */
-	err = posix_clock_register(&ptp->clock, ptp->devid);
+	/* Initialize a new device of our class in our clock structure. */
+	device_initialize(&ptp->dev);
+	ptp->dev.devt = ptp->devid;
+	ptp->dev.class = ptp_class;
+	ptp->dev.parent = parent;
+	ptp->dev.groups = ptp->pin_attr_groups;
+	ptp->dev.release = ptp_clock_release;
+	dev_set_drvdata(&ptp->dev, ptp);
+	dev_set_name(&ptp->dev, "ptp%d", ptp->index);
+
+	/* Create a posix clock and link it to the device. */
+	err = posix_clock_register(&ptp->clock, &ptp->dev);
 	if (err) {
 		pr_err("failed to create posix clock\n");
 		goto no_clock;
@@ -273,8 +286,6 @@
 	if (ptp->pps_source)
 		pps_unregister_source(ptp->pps_source);
 no_pps:
-	device_destroy(ptp_class, ptp->devid);
-no_device:
 	ptp_cleanup_pin_groups(ptp);
 no_pin_groups:
 	if (ptp->kworker)
@@ -299,15 +310,8 @@
 		kthread_cancel_delayed_work_sync(&ptp->aux_work);
 		kthread_destroy_worker(ptp->kworker);
 	}
-
-	/* Release the clock's resources. */
-	if (ptp->pps_source)
-		pps_unregister_source(ptp->pps_source);
-
-	device_destroy(ptp_class, ptp->devid);
-	ptp_cleanup_pin_groups(ptp);
-
 	posix_clock_unregister(&ptp->clock);
+
 	return 0;
 }
 EXPORT_SYMBOL(ptp_clock_unregister);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ptp/ptp_pch.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ptp/ptp_pch.c
@@ -683,6 +683,7 @@
 	 },
 	{0}
 };
+MODULE_DEVICE_TABLE(pci, pch_ieee1588_pcidev_id);
 
 static struct pci_driver pch_driver = {
 	.name = KBUILD_MODNAME,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ptp/ptp_private.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/ptp/ptp_private.h
@@ -28,7 +28,7 @@
 
 struct ptp_clock {
 	struct posix_clock clock;
-	struct device *dev;
+	struct device dev;
 	struct ptp_clock_info *info;
 	dev_t devid;
 	int index; /* index into clocks.map */
@@ -55,9 +55,13 @@
  * that a writer might concurrently increment the tail does not
  * matter, since the queue remains nonempty nonetheless.
  */
-static inline int queue_cnt(struct timestamp_event_queue *q)
+static inline int queue_cnt(const struct timestamp_event_queue *q)
 {
-	int cnt = q->tail - q->head;
+	/*
+	 * Paired with WRITE_ONCE() in enqueue_external_timestamp(),
+	 * ptp_read(), extts_fifo_show().
+	 */
+	int cnt = READ_ONCE(q->tail) - READ_ONCE(q->head);
 	return cnt < 0 ? PTP_MAX_TIMESTAMPS + cnt : cnt;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ptp/ptp_qoriq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ptp/ptp_qoriq.c
@@ -604,7 +604,7 @@
 	return 0;
 
 no_clock:
-	iounmap(ptp_qoriq->base);
+	iounmap(base);
 no_ioremap:
 	release_resource(ptp_qoriq->rsrc);
 no_resource:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ptp/ptp_sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ptp/ptp_sysfs.c
@@ -13,7 +13,7 @@
 			       struct device_attribute *attr, char *page)
 {
 	struct ptp_clock *ptp = dev_get_drvdata(dev);
-	return snprintf(page, PAGE_SIZE-1, "%s\n", ptp->info->name);
+	return sysfs_emit(page, "%s\n", ptp->info->name);
 }
 static DEVICE_ATTR_RO(clock_name);
 
@@ -78,7 +78,8 @@
 	qcnt = queue_cnt(queue);
 	if (qcnt) {
 		event = queue->buf[queue->head];
-		queue->head = (queue->head + 1) % PTP_MAX_TIMESTAMPS;
+		/* Paired with READ_ONCE() in queue_cnt() */
+		WRITE_ONCE(queue->head, (queue->head + 1) % PTP_MAX_TIMESTAMPS);
 	}
 	spin_unlock_irqrestore(&queue->lock, flags);
 
@@ -227,7 +228,7 @@
 
 	mutex_unlock(&ptp->pincfg_mux);
 
-	return snprintf(page, PAGE_SIZE, "%u %u\n", func, chan);
+	return sysfs_emit(page, "%u %u\n", func, chan);
 }
 
 static ssize_t ptp_pin_store(struct device *dev, struct device_attribute *attr,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ptp/ptp_xilinx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ptp/ptp_xilinx.c
@@ -0,0 +1,394 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Xilinx 1588 PTP timer syncer driver
+ *
+ * Copyright (c) 2020 Xilinx, Inc. All rights reserved.
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/ptp_clock_kernel.h>
+#include <linux/platform_device.h>
+#include <linux/of_irq.h>
+
+/* Register offset definitions */
+#define XPTPTIMER_TOD_CONFIG_OFFSET	0x0000
+#define XPTPTIMER_TOD_SNAPSHOT_OFFSET	0x0004
+#define XPTPTIMER_IER_OFFSET		0x0008
+#define XPTPTIMER_ISR_OFFSET		0x000C
+#define XPTPTIMER_TOD_SW_SEC_0_OFFSET	0x0010
+#define XPTPTIMER_TOD_SW_SEC_1_OFFSET	0x0014
+#define XPTPTIMER_TOD_SW_NS_OFFSET	0x0018
+#define XPTPTIMER_TOD_SW_LOAD_OFFSET	0x001C
+#define XPTPTIMER_TOD_SEC_SYS_OFST_0_OFFSET	0x0028
+#define XPTPTIMER_TOD_SEC_SYS_OFST_1_OFFSET	0x002C
+#define XPTPTIMER_TOD_NS_SYS_OFST_OFFSET	0x0030
+
+#define XPTPTIMER_SYS_SEC_0_OFFSET	0x0100
+#define XPTPTIMER_SYS_SEC_1_OFFSET	0x0104
+#define XPTPTIMER_SYS_NS_OFFSET		0x0108
+
+#define XPTPTIMER_PORT_TX_PERIOD_0_OFFSET	0x0208
+#define XPTPTIMER_PORT_TX_PERIOD_1_OFFSET	0x020C
+#define XPTPTIMER_PORT_TX_NS_SNAP_OFFSET	0x0214
+#define XPTPTIMER_PORT_TX_SEC_0_SNAP_OFFSET	0x0218
+#define XPTPTIMER_PORT_TX_SEC_1_SNAP_OFFSET	0x021C
+#define XPTPTIMER_PORT_RX_PERIOD_0_OFFSET	0x0228
+#define XPTPTIMER_PORT_RX_PERIOD_1_OFFSET	0x022C
+#define XPTPTIMER_PORT_RX_NS_SNAP_OFFSET	0x0234
+#define XPTPTIMER_PORT_RX_SEC_0_SNAP_OFFSET	0x0238
+#define XPTPTIMER_PORT_RX_SEC_1_SNAP_OFFSET	0x023C
+
+#define XPTPTIMER_CFG_MAIN_TOD_EN	BIT(0)
+#define XPTPTIMER_CFG_ENABLE_PORT0	BIT(4)
+
+#define XPTPTIMER_MAX_SEC_SIZE		48
+#define XPTPTIMER_MAX_SEC_MASK		GENMASK(XPTPTIMER_MAX_SEC_SIZE - 1, 0)
+
+#define XPTPTIMER_TOD_OFFSET_NEG	BIT(47)
+
+#define XPTPTIMER_SNAPSHOT_MASK		BIT(0)
+#define XPTPTIMER_LOAD_TOD_MASK		BIT(0)
+#define XPTPTIMER_LOAD_OFFSET_MASK	BIT(1)
+
+/* TODO This should be derived from the system design */
+#define XPTPTIMER_CLOCK_PERIOD		4
+#define XPTPTIMER_PERIOD_SHIFT		48
+
+#define PPM_FRACTION	16
+
+struct xlnx_ptp_timer {
+	struct		device *dev;
+	void __iomem		*baseaddr;
+	struct ptp_clock	*ptp_clock;
+	struct ptp_clock_info	ptp_clock_info;
+	spinlock_t		reg_lock; /* For reg access */
+	u64			incr;
+	s64			timeoffset;
+	s32			static_delay;
+};
+
+/* I/O accessors */
+static inline u32 xlnx_ptp_ior(struct xlnx_ptp_timer *timer, off_t reg)
+{
+	return ioread32(timer->baseaddr + reg);
+}
+
+static inline void xlnx_ptp_iow(struct xlnx_ptp_timer *timer, off_t reg,
+				u32 value)
+{
+	iowrite32(value, (timer->baseaddr + reg));
+}
+
+/*
+ * Inline timer helpers
+ */
+static inline void xlnx_tod_read(struct xlnx_ptp_timer *timer,
+				 struct timespec64 *ts)
+{
+	u32 sech, secl, nsec;
+
+	xlnx_ptp_iow(timer, XPTPTIMER_TOD_SNAPSHOT_OFFSET,
+		     XPTPTIMER_SNAPSHOT_MASK);
+
+	/* use TX port here */
+	nsec = xlnx_ptp_ior(timer, XPTPTIMER_PORT_TX_NS_SNAP_OFFSET);
+	secl = xlnx_ptp_ior(timer, XPTPTIMER_PORT_TX_SEC_0_SNAP_OFFSET);
+	sech = xlnx_ptp_ior(timer, XPTPTIMER_PORT_TX_SEC_1_SNAP_OFFSET);
+
+	ts->tv_nsec = nsec;
+	ts->tv_sec = (((u64)sech << 32) | secl) & XPTPTIMER_MAX_SEC_MASK;
+}
+
+static inline void xlnx_tod_offset_write(struct xlnx_ptp_timer *timer,
+					 const struct timespec64 *ts)
+{
+	xlnx_ptp_iow(timer, XPTPTIMER_TOD_SEC_SYS_OFST_1_OFFSET,
+		     upper_32_bits(ts->tv_sec));
+	xlnx_ptp_iow(timer, XPTPTIMER_TOD_SEC_SYS_OFST_0_OFFSET,
+		     lower_32_bits(ts->tv_sec));
+	xlnx_ptp_iow(timer, XPTPTIMER_TOD_NS_SYS_OFST_OFFSET,
+		     (u32)(ts->tv_nsec));
+
+	xlnx_ptp_iow(timer, XPTPTIMER_TOD_SW_LOAD_OFFSET,
+		     XPTPTIMER_LOAD_OFFSET_MASK);
+}
+
+static inline void xlnx_tod_load_write(struct xlnx_ptp_timer *timer,
+				       const struct timespec64 *ts)
+{
+	struct timespec64 offset;
+
+	offset.tv_sec = 0;
+	offset.tv_nsec = 0;
+
+	xlnx_ptp_iow(timer, XPTPTIMER_TOD_SW_SEC_1_OFFSET,
+		     upper_32_bits(ts->tv_sec));
+	xlnx_ptp_iow(timer, XPTPTIMER_TOD_SW_SEC_0_OFFSET,
+		     lower_32_bits(ts->tv_sec));
+	xlnx_ptp_iow(timer, XPTPTIMER_TOD_SW_NS_OFFSET, ts->tv_nsec);
+
+	/* Make sure offset registers are cleared */
+	xlnx_tod_offset_write(timer, &offset);
+	xlnx_ptp_iow(timer, XPTPTIMER_TOD_SW_LOAD_OFFSET,
+		     XPTPTIMER_LOAD_OFFSET_MASK);
+
+	xlnx_ptp_iow(timer, XPTPTIMER_TOD_SW_LOAD_OFFSET,
+		     XPTPTIMER_LOAD_TOD_MASK);
+	timer->timeoffset = 0;
+}
+
+static inline void xlnx_port_period_write(struct xlnx_ptp_timer *timer, u64 adj)
+{
+	u32 adjhigh = upper_32_bits(adj);
+
+	xlnx_ptp_iow(timer, XPTPTIMER_PORT_TX_PERIOD_0_OFFSET, (u32)(adj));
+	xlnx_ptp_iow(timer, XPTPTIMER_PORT_RX_PERIOD_0_OFFSET, (u32)(adj));
+	spin_lock(&timer->reg_lock);
+	xlnx_ptp_iow(timer, XPTPTIMER_PORT_TX_PERIOD_1_OFFSET, adjhigh);
+	xlnx_ptp_iow(timer, XPTPTIMER_PORT_RX_PERIOD_1_OFFSET, adjhigh);
+
+	spin_unlock(&timer->reg_lock);
+}
+
+/*
+ * PTP clock operations
+ */
+/**
+ * xlnx_ptp_adjfine - Fine adjustment of the frequency on the hardware clock
+ * @ptp: ptp clock structure
+ * @scaled_ppm: signed scaled parts per million for frequency adjustment.
+ * Return: 0 on success
+ * TX and RX port periods are reloaded with the adjusted value.
+ *
+ */
+static int xlnx_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
+{
+	struct xlnx_ptp_timer *timer = container_of(ptp, struct xlnx_ptp_timer,
+					ptp_clock_info);
+	bool neg_adj = false;
+	u64 adj;
+
+	if (scaled_ppm < 0) {
+		neg_adj = true;
+		scaled_ppm = -scaled_ppm;
+	}
+
+	adj = mul_u64_u32_div(timer->incr, scaled_ppm, USEC_PER_SEC);
+	adj >>= PPM_FRACTION; /* remove fractions */
+	adj = neg_adj ? (timer->incr - adj) : (timer->incr + adj);
+
+	xlnx_port_period_write(timer, adj);
+
+	return 0;
+}
+
+/**
+ * xlnx_ptp_adjtime - Adjust the current time on the hardware clock
+ * @ptp: ptp clock structure
+ * @delta: signed time in ns to be adjusted.
+ * Return: 0 on success
+ * System, TX and RX ports are reloaded with the adjusted time.
+ *
+ */
+static int xlnx_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+	struct xlnx_ptp_timer *timer = container_of(ptp, struct xlnx_ptp_timer,
+						ptp_clock_info);
+	struct timespec64 offset;
+	u64 sign = 0;
+	s64 cumulative_delta = timer->timeoffset;
+
+	spin_lock(&timer->reg_lock);
+
+	/* Fixed offset between system and port timer */
+	delta += timer->static_delay;
+	cumulative_delta += delta;
+	timer->timeoffset = cumulative_delta;
+	if (cumulative_delta < 0) {
+		sign = XPTPTIMER_TOD_OFFSET_NEG;
+		cumulative_delta = -cumulative_delta;
+	}
+	offset = ns_to_timespec64(cumulative_delta);
+	offset.tv_sec |= sign;
+
+	xlnx_tod_offset_write(timer, (const struct timespec64 *)&offset);
+
+	spin_unlock(&timer->reg_lock);
+
+	return 0;
+}
+
+/**
+ * xlnx_ptp_gettime - Get the current time on the hardware clock
+ * @ptp: ptp clock structure
+ * @ts: timespec64 containing the current TX port timer time.
+ * Return: 0 on success
+ * Since TX and RX ports are initialized and adjusted simultaneously,
+ * they should be the same.
+ *
+ */
+static int xlnx_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
+{
+	struct xlnx_ptp_timer *timer = container_of(ptp, struct xlnx_ptp_timer,
+						    ptp_clock_info);
+
+	spin_lock(&timer->reg_lock);
+	xlnx_tod_read(timer, ts);
+	spin_unlock(&timer->reg_lock);
+
+	return 0;
+}
+
+/**
+ * xlnx_ptp_settime - Set the current time on the hardware clock
+ * @ptp: ptp clock structure
+ * @ts: timespec64 containing the new time
+ * Return: 0 on success
+ *
+ * The hardware loads the entire new value when a load register is triggered.
+ */
+static int xlnx_ptp_settime(struct ptp_clock_info *ptp,
+			    const struct timespec64 *ts)
+{
+	struct xlnx_ptp_timer *timer = container_of(ptp, struct xlnx_ptp_timer,
+					ptp_clock_info);
+
+	spin_lock(&timer->reg_lock);
+	xlnx_tod_load_write(timer, ts);
+	spin_unlock(&timer->reg_lock);
+
+	return 0;
+}
+
+static int xlnx_ptp_enable(struct ptp_clock_info *ptp,
+			   struct ptp_clock_request *rq, int on)
+{
+	return -EOPNOTSUPP;
+}
+
+static struct ptp_clock_info xlnx_ptp_clock_info = {
+	.owner		= THIS_MODULE,
+	.name		= "Xilinx Timer",
+	.max_adj	= 64000000,	/* Safe max adjutment for clock rate */
+	.n_ext_ts	= 0,
+	.adjfine	= xlnx_ptp_adjfine,
+	.adjtime	= xlnx_ptp_adjtime,
+	.gettime64	= xlnx_ptp_gettime,
+	.settime64	= xlnx_ptp_settime,
+	.enable		= xlnx_ptp_enable,
+};
+
+static int xlnx_ptp_timer_probe(struct platform_device *pdev)
+{
+	struct xlnx_ptp_timer *timer;
+	struct resource *r_mem;
+	int err = 0;
+	struct timespec64 ts, tsp;
+	u32 nsec, sech, secl;
+
+	timer = devm_kzalloc(&pdev->dev, sizeof(*timer), GFP_KERNEL);
+	if (!timer)
+		return -ENOMEM;
+
+	timer->dev = &pdev->dev;
+
+	r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	timer->baseaddr = devm_ioremap_resource(&pdev->dev, r_mem);
+	if (IS_ERR(timer->baseaddr)) {
+		err = PTR_ERR(timer->baseaddr);
+		return err;
+	}
+
+	spin_lock_init(&timer->reg_lock);
+
+	timer->ptp_clock_info = xlnx_ptp_clock_info;
+
+	timer->ptp_clock = ptp_clock_register(&timer->ptp_clock_info,
+					      &pdev->dev);
+	if (IS_ERR(timer->ptp_clock)) {
+		err = PTR_ERR(timer->ptp_clock);
+		dev_err(&pdev->dev, "Failed to register ptp clock\n");
+		return err;
+	}
+
+	xlnx_ptp_iow(timer, XPTPTIMER_TOD_CONFIG_OFFSET,
+		     XPTPTIMER_CFG_MAIN_TOD_EN | XPTPTIMER_CFG_ENABLE_PORT0);
+	/*
+	 * TODO: This clock rate should be derived from system design.
+	 * This is design specific - for ex. 250MHz port clock rate; period is
+	 * 10^9/250 is 4ns. Set port timer PERIOD BEFORE calling settime,
+	 * so that the initial LOAD triggers everything together.
+	 */
+	timer->incr = ((u64)XPTPTIMER_CLOCK_PERIOD << XPTPTIMER_PERIOD_SHIFT);
+	xlnx_port_period_write(timer, timer->incr);
+
+	/* Initialize current time */
+	ts = ns_to_timespec64(ktime_to_ns(ktime_get_real()));
+	xlnx_ptp_settime(&timer->ptp_clock_info, &ts);
+
+	/*
+	 * A static delay of 7-8 clock cycles is expected between system and
+	 * port timer which should be 28-32ns on this system with 250MHz clock.
+	 */
+	xlnx_ptp_iow(timer, XPTPTIMER_TOD_SNAPSHOT_OFFSET,
+		     XPTPTIMER_SNAPSHOT_MASK);
+	nsec = xlnx_ptp_ior(timer, XPTPTIMER_SYS_NS_OFFSET);
+	sech = xlnx_ptp_ior(timer, XPTPTIMER_SYS_SEC_1_OFFSET);
+	secl = xlnx_ptp_ior(timer, XPTPTIMER_SYS_SEC_0_OFFSET);
+	ts.tv_nsec = nsec;
+	ts.tv_sec = (((u64)sech << 32) | secl) & XPTPTIMER_MAX_SEC_MASK;
+
+	nsec = xlnx_ptp_ior(timer, XPTPTIMER_PORT_TX_NS_SNAP_OFFSET);
+	secl = xlnx_ptp_ior(timer, XPTPTIMER_PORT_TX_SEC_0_SNAP_OFFSET);
+	sech = xlnx_ptp_ior(timer, XPTPTIMER_PORT_TX_SEC_1_SNAP_OFFSET);
+	tsp.tv_nsec = nsec;
+	tsp.tv_sec = (((u64)sech << 32) | secl) & XPTPTIMER_MAX_SEC_MASK;
+
+	ts = timespec64_sub(ts, tsp);
+	timer->static_delay = timespec64_to_ns(&ts);
+	dev_dbg(&pdev->dev, "Static delay %d\n", timer->static_delay);
+
+	platform_set_drvdata(pdev, timer);
+
+	dev_info(&pdev->dev, "Xilinx PTP timer driver probed\n");
+
+	return 0;
+}
+
+static int xlnx_ptp_timer_remove(struct platform_device *pdev)
+{
+	struct xlnx_ptp_timer *timer = platform_get_drvdata(pdev);
+
+	ptp_clock_unregister(timer->ptp_clock);
+
+	return 0;
+}
+
+static const struct of_device_id timer_1588_of_match[] = {
+	{ .compatible = "xlnx,timer-syncer-1588-1.0", },
+		{ /* end of table */ }
+};
+MODULE_DEVICE_TABLE(of, timer_1588_of_match);
+
+static struct platform_driver xlnx_ptp_timer_driver = {
+	.probe		= xlnx_ptp_timer_probe,
+	.remove		= xlnx_ptp_timer_remove,
+	.driver		= {
+		.name = "xlnx_ptp_timer",
+		.of_match_table = timer_1588_of_match,
+	},
+};
+
+module_platform_driver(xlnx_ptp_timer_driver);
+
+MODULE_AUTHOR("Xilinx, Inc.");
+MODULE_DESCRIPTION("PTP Timer Syncer driver");
+MODULE_LICENSE("GPL");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pwm/pwm-bcm-iproc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pwm/pwm-bcm-iproc.c
@@ -85,8 +85,6 @@
 	u64 tmp, multi, rate;
 	u32 value, prescale;
 
-	rate = clk_get_rate(ip->clk);
-
 	value = readl(ip->base + IPROC_PWM_CTRL_OFFSET);
 
 	if (value & BIT(IPROC_PWM_CTRL_EN_SHIFT(pwm->hwpwm)))
@@ -99,6 +97,13 @@
 	else
 		state->polarity = PWM_POLARITY_INVERSED;
 
+	rate = clk_get_rate(ip->clk);
+	if (rate == 0) {
+		state->period = 0;
+		state->duty_cycle = 0;
+		return;
+	}
+
 	value = readl(ip->base + IPROC_PWM_PRESCALE_OFFSET);
 	prescale = value >> IPROC_PWM_PRESCALE_SHIFT(pwm->hwpwm);
 	prescale &= IPROC_PWM_PRESCALE_MAX;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pwm/pwm-bcm2835.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pwm/pwm-bcm2835.c
@@ -166,6 +166,7 @@
 
 	pc->chip.dev = &pdev->dev;
 	pc->chip.ops = &bcm2835_pwm_ops;
+	pc->chip.base = -1;
 	pc->chip.npwm = 2;
 	pc->chip.of_xlate = of_pwm_xlate_with_flags;
 	pc->chip.of_pwm_n_cells = 3;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pwm/pwm-brcmstb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pwm/pwm-brcmstb.c
@@ -298,7 +298,7 @@
 {
 	struct brcmstb_pwm *p = dev_get_drvdata(dev);
 
-	clk_disable(p->clk);
+	clk_disable_unprepare(p->clk);
 
 	return 0;
 }
@@ -307,7 +307,7 @@
 {
 	struct brcmstb_pwm *p = dev_get_drvdata(dev);
 
-	clk_enable(p->clk);
+	clk_prepare_enable(p->clk);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pwm/pwm-cros-ec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pwm/pwm-cros-ec.c
@@ -125,6 +125,7 @@
 
 	state->enabled = (ret > 0);
 	state->period = EC_PWM_MAX_DUTY;
+	state->polarity = PWM_POLARITY_NORMAL;
 
 	/* Note that "disabled" and "duty cycle == 0" are treated the same */
 	state->duty_cycle = ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pwm/pwm-hibvt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pwm/pwm-hibvt.c
@@ -146,6 +146,7 @@
 
 	value = readl(base + PWM_CTRL_ADDR(pwm->hwpwm));
 	state->enabled = (PWM_ENABLE_MASK & value);
+	state->polarity = (PWM_POLARITY_MASK & value) ? PWM_POLARITY_INVERSED : PWM_POLARITY_NORMAL;
 }
 
 static int hibvt_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pwm/pwm-img.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pwm/pwm-img.c
@@ -129,8 +129,10 @@
 	duty = DIV_ROUND_UP(timebase * duty_ns, period_ns);
 
 	ret = pm_runtime_get_sync(chip->dev);
-	if (ret < 0)
+	if (ret < 0) {
+		pm_runtime_put_autosuspend(chip->dev);
 		return ret;
+	}
 
 	val = img_pwm_readl(pwm_chip, PWM_CTRL_CFG);
 	val &= ~(PWM_CTRL_CFG_DIV_MASK << PWM_CTRL_CFG_DIV_SHIFT(pwm->hwpwm));
@@ -154,7 +156,7 @@
 	struct img_pwm_chip *pwm_chip = to_img_pwm_chip(chip);
 	int ret;
 
-	ret = pm_runtime_get_sync(chip->dev);
+	ret = pm_runtime_resume_and_get(chip->dev);
 	if (ret < 0)
 		return ret;
 
@@ -275,6 +277,8 @@
 		return PTR_ERR(pwm->pwm_clk);
 	}
 
+	platform_set_drvdata(pdev, pwm);
+
 	pm_runtime_set_autosuspend_delay(&pdev->dev, IMG_PWM_PM_TIMEOUT);
 	pm_runtime_use_autosuspend(&pdev->dev);
 	pm_runtime_enable(&pdev->dev);
@@ -311,7 +315,6 @@
 		goto err_suspend;
 	}
 
-	platform_set_drvdata(pdev, pwm);
 	return 0;
 
 err_suspend:
@@ -326,21 +329,7 @@
 static int img_pwm_remove(struct platform_device *pdev)
 {
 	struct img_pwm_chip *pwm_chip = platform_get_drvdata(pdev);
-	u32 val;
-	unsigned int i;
-	int ret;
-
-	ret = pm_runtime_get_sync(&pdev->dev);
-	if (ret < 0)
-		return ret;
-
-	for (i = 0; i < pwm_chip->chip.npwm; i++) {
-		val = img_pwm_readl(pwm_chip, PWM_CTRL_CFG);
-		val &= ~BIT(i);
-		img_pwm_writel(pwm_chip, PWM_CTRL_CFG, val);
-	}
 
-	pm_runtime_put(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 	if (!pm_runtime_status_suspended(&pdev->dev))
 		img_pwm_runtime_suspend(&pdev->dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pwm/pwm-imx-tpm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pwm/pwm-imx-tpm.c
@@ -108,7 +108,9 @@
 	p->prescale = prescale;
 
 	period_count = (clock_unit + ((1 << prescale) >> 1)) >> prescale;
-	p->mod = period_count;
+	if (period_count == 0)
+		return -EINVAL;
+	p->mod = period_count - 1;
 
 	/* calculate real period HW can support */
 	tmp = (u64)period_count << prescale;
@@ -405,6 +407,13 @@
 	if (tpm->enable_count > 0)
 		return -EBUSY;
 
+	/*
+	 * Force 'real_period' to be zero to force period update code
+	 * can be executed after system resume back, since suspend causes
+	 * the period related registers to become their reset values.
+	 */
+	tpm->real_period = 0;
+
 	clk_disable_unprepare(tpm->clk);
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pwm/pwm-imx1.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pwm/pwm-imx1.c
@@ -180,8 +180,6 @@
 {
 	struct pwm_imx1_chip *imx = platform_get_drvdata(pdev);
 
-	pwm_imx1_clk_disable_unprepare(&imx->chip);
-
 	return pwmchip_remove(&imx->chip);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pwm/pwm-jz4740.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pwm/pwm-jz4740.c
@@ -92,11 +92,12 @@
 {
 	struct jz4740_pwm_chip *jz4740 = to_jz4740(pwm->chip);
 	unsigned long long tmp;
-	unsigned long period, duty;
+	unsigned long rate, period, duty;
 	unsigned int prescaler = 0;
 	uint16_t ctrl;
 
-	tmp = (unsigned long long)clk_get_rate(jz4740->clk) * state->period;
+	rate = clk_get_rate(jz4740->clk);
+	tmp = rate * state->period;
 	do_div(tmp, 1000000000);
 	period = tmp;
 
@@ -108,8 +109,8 @@
 	if (prescaler == 6)
 		return -EINVAL;
 
-	tmp = (unsigned long long)period * state->duty_cycle;
-	do_div(tmp, state->period);
+	tmp = (unsigned long long)rate * state->duty_cycle;
+	do_div(tmp, NSEC_PER_SEC);
 	duty = period - tmp;
 
 	if (duty >= period)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pwm/pwm-lp3943.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pwm/pwm-lp3943.c
@@ -125,6 +125,7 @@
 	if (err)
 		return err;
 
+	duty_ns = min(duty_ns, period_ns);
 	val = (u8)(duty_ns * LP3943_MAX_DUTY / period_ns);
 
 	return lp3943_write_byte(lp3943, reg_duty, val);
@@ -275,6 +276,7 @@
 	lp3943_pwm->chip.dev = &pdev->dev;
 	lp3943_pwm->chip.ops = &lp3943_pwm_ops;
 	lp3943_pwm->chip.npwm = LP3943_NUM_PWMS;
+	lp3943_pwm->chip.base = -1;
 
 	platform_set_drvdata(pdev, lp3943_pwm);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pwm/pwm-lpc18xx-sct.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pwm/pwm-lpc18xx-sct.c
@@ -400,12 +400,6 @@
 	lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_LIMIT,
 			   BIT(lpc18xx_pwm->period_event));
 
-	ret = pwmchip_add(&lpc18xx_pwm->chip);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "pwmchip_add failed: %d\n", ret);
-		goto disable_pwmclk;
-	}
-
 	for (i = 0; i < lpc18xx_pwm->chip.npwm; i++) {
 		struct lpc18xx_pwm_data *data;
 
@@ -415,14 +409,12 @@
 				    GFP_KERNEL);
 		if (!data) {
 			ret = -ENOMEM;
-			goto remove_pwmchip;
+			goto disable_pwmclk;
 		}
 
 		pwm_set_chip_data(pwm, data);
 	}
 
-	platform_set_drvdata(pdev, lpc18xx_pwm);
-
 	val = lpc18xx_pwm_readl(lpc18xx_pwm, LPC18XX_PWM_CTRL);
 	val &= ~LPC18XX_PWM_BIDIR;
 	val &= ~LPC18XX_PWM_CTRL_HALT;
@@ -430,10 +422,16 @@
 	val |= LPC18XX_PWM_PRE(0);
 	lpc18xx_pwm_writel(lpc18xx_pwm, LPC18XX_PWM_CTRL, val);
 
+	ret = pwmchip_add(&lpc18xx_pwm->chip);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "pwmchip_add failed: %d\n", ret);
+		goto disable_pwmclk;
+	}
+
+	platform_set_drvdata(pdev, lpc18xx_pwm);
+
 	return 0;
 
-remove_pwmchip:
-	pwmchip_remove(&lpc18xx_pwm->chip);
 disable_pwmclk:
 	clk_disable_unprepare(lpc18xx_pwm->pwm_clk);
 	return ret;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pwm/pwm-lpc32xx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pwm/pwm-lpc32xx.c
@@ -51,10 +51,10 @@
 	if (duty_cycles > 255)
 		duty_cycles = 255;
 
-	val = readl(lpc32xx->base + (pwm->hwpwm << 2));
+	val = readl(lpc32xx->base);
 	val &= ~0xFFFF;
 	val |= (period_cycles << 8) | duty_cycles;
-	writel(val, lpc32xx->base + (pwm->hwpwm << 2));
+	writel(val, lpc32xx->base);
 
 	return 0;
 }
@@ -69,9 +69,9 @@
 	if (ret)
 		return ret;
 
-	val = readl(lpc32xx->base + (pwm->hwpwm << 2));
+	val = readl(lpc32xx->base);
 	val |= PWM_ENABLE;
-	writel(val, lpc32xx->base + (pwm->hwpwm << 2));
+	writel(val, lpc32xx->base);
 
 	return 0;
 }
@@ -81,9 +81,9 @@
 	struct lpc32xx_pwm_chip *lpc32xx = to_lpc32xx_pwm_chip(chip);
 	u32 val;
 
-	val = readl(lpc32xx->base + (pwm->hwpwm << 2));
+	val = readl(lpc32xx->base);
 	val &= ~PWM_ENABLE;
-	writel(val, lpc32xx->base + (pwm->hwpwm << 2));
+	writel(val, lpc32xx->base);
 
 	clk_disable_unprepare(lpc32xx->clk);
 }
@@ -120,17 +120,17 @@
 	lpc32xx->chip.npwm = 1;
 	lpc32xx->chip.base = -1;
 
+	/* If PWM is disabled, configure the output to the default value */
+	val = readl(lpc32xx->base);
+	val &= ~PWM_PIN_LEVEL;
+	writel(val, lpc32xx->base);
+
 	ret = pwmchip_add(&lpc32xx->chip);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "failed to add PWM chip, error %d\n", ret);
 		return ret;
 	}
 
-	/* When PWM is disable, configure the output to the default value */
-	val = readl(lpc32xx->base + (lpc32xx->chip.pwms[0].hwpwm << 2));
-	val &= ~PWM_PIN_LEVEL;
-	writel(val, lpc32xx->base + (lpc32xx->chip.pwms[0].hwpwm << 2));
-
 	platform_set_drvdata(pdev, lpc32xx);
 
 	return 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pwm/pwm-lpss.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pwm/pwm-lpss.c
@@ -93,10 +93,12 @@
 	 * The equation is:
 	 * base_unit = round(base_unit_range * freq / c)
 	 */
-	base_unit_range = BIT(lpwm->info->base_unit_bits) - 1;
+	base_unit_range = BIT(lpwm->info->base_unit_bits);
 	freq *= base_unit_range;
 
 	base_unit = DIV_ROUND_CLOSEST_ULL(freq, c);
+	/* base_unit must not be 0 and we also want to avoid overflowing it */
+	base_unit = clamp_val(base_unit, 1, base_unit_range - 1);
 
 	on_time_div = 255ULL * duty_ns;
 	do_div(on_time_div, period_ns);
@@ -104,8 +106,7 @@
 
 	orig_ctrl = ctrl = pwm_lpss_read(pwm);
 	ctrl &= ~PWM_ON_TIME_DIV_MASK;
-	ctrl &= ~(base_unit_range << PWM_BASE_UNIT_SHIFT);
-	base_unit &= base_unit_range;
+	ctrl &= ~((base_unit_range - 1) << PWM_BASE_UNIT_SHIFT);
 	ctrl |= (u32) base_unit << PWM_BASE_UNIT_SHIFT;
 	ctrl |= on_time_div;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pwm/pwm-meson.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pwm/pwm-meson.c
@@ -147,12 +147,13 @@
 		return err;
 	}
 
-	return pwm_set_chip_data(pwm, channel);
+	return 0;
 }
 
 static void meson_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
 {
-	struct meson_pwm_channel *channel = pwm_get_chip_data(pwm);
+	struct meson_pwm *meson = to_meson_pwm(chip);
+	struct meson_pwm_channel *channel = &meson->channels[pwm->hwpwm];
 
 	if (channel)
 		clk_disable_unprepare(channel->clk);
@@ -161,13 +162,20 @@
 static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm,
 			  const struct pwm_state *state)
 {
-	struct meson_pwm_channel *channel = pwm_get_chip_data(pwm);
-	unsigned int duty, period, pre_div, cnt, duty_cnt;
-	unsigned long fin_freq = -1;
+	struct meson_pwm_channel *channel = &meson->channels[pwm->hwpwm];
+	unsigned int pre_div, cnt, duty_cnt;
+	unsigned long fin_freq;
+	u64 duty, period;
 
 	duty = state->duty_cycle;
 	period = state->period;
 
+	/*
+	 * Note this is wrong. The result is an output wave that isn't really
+	 * inverted and so is wrongly identified by .get_state as normal.
+	 * Fixing this needs some care however as some machines might rely on
+	 * this.
+	 */
 	if (state->polarity == PWM_POLARITY_INVERSED)
 		duty = period - duty;
 
@@ -179,19 +187,19 @@
 
 	dev_dbg(meson->chip.dev, "fin_freq: %lu Hz\n", fin_freq);
 
-	pre_div = div64_u64(fin_freq * (u64)period, NSEC_PER_SEC * 0xffffLL);
+	pre_div = div64_u64(fin_freq * period, NSEC_PER_SEC * 0xffffLL);
 	if (pre_div > MISC_CLK_DIV_MASK) {
 		dev_err(meson->chip.dev, "unable to get period pre_div\n");
 		return -EINVAL;
 	}
 
-	cnt = div64_u64(fin_freq * (u64)period, NSEC_PER_SEC * (pre_div + 1));
+	cnt = div64_u64(fin_freq * period, NSEC_PER_SEC * (pre_div + 1));
 	if (cnt > 0xffff) {
 		dev_err(meson->chip.dev, "unable to get period cnt\n");
 		return -EINVAL;
 	}
 
-	dev_dbg(meson->chip.dev, "period=%u pre_div=%u cnt=%u\n", period,
+	dev_dbg(meson->chip.dev, "period=%llu pre_div=%u cnt=%u\n", period,
 		pre_div, cnt);
 
 	if (duty == period) {
@@ -204,14 +212,13 @@
 		channel->lo = cnt;
 	} else {
 		/* Then check is we can have the duty with the same pre_div */
-		duty_cnt = div64_u64(fin_freq * (u64)duty,
-				     NSEC_PER_SEC * (pre_div + 1));
+		duty_cnt = div64_u64(fin_freq * duty, NSEC_PER_SEC * (pre_div + 1));
 		if (duty_cnt > 0xffff) {
 			dev_err(meson->chip.dev, "unable to get duty cycle\n");
 			return -EINVAL;
 		}
 
-		dev_dbg(meson->chip.dev, "duty=%u pre_div=%u duty_cnt=%u\n",
+		dev_dbg(meson->chip.dev, "duty=%llu pre_div=%u duty_cnt=%u\n",
 			duty, pre_div, duty_cnt);
 
 		channel->pre_div = pre_div;
@@ -224,7 +231,7 @@
 
 static void meson_pwm_enable(struct meson_pwm *meson, struct pwm_device *pwm)
 {
-	struct meson_pwm_channel *channel = pwm_get_chip_data(pwm);
+	struct meson_pwm_channel *channel = &meson->channels[pwm->hwpwm];
 	struct meson_pwm_channel_data *channel_data;
 	unsigned long flags;
 	u32 value;
@@ -267,8 +274,8 @@
 static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
 			   const struct pwm_state *state)
 {
-	struct meson_pwm_channel *channel = pwm_get_chip_data(pwm);
 	struct meson_pwm *meson = to_meson_pwm(chip);
+	struct meson_pwm_channel *channel = &meson->channels[pwm->hwpwm];
 	int err = 0;
 
 	if (!state)
@@ -366,6 +373,7 @@
 		state->period = 0;
 		state->duty_cycle = 0;
 	}
+	state->polarity = PWM_POLARITY_NORMAL;
 }
 
 static const struct pwm_ops meson_pwm_ops = {
@@ -417,7 +425,7 @@
 };
 
 static const char * const pwm_axg_ao_parent_names[] = {
-	"aoclk81", "xtal", "fclk_div4", "fclk_div5"
+	"xtal", "axg_ao_clk81", "fclk_div4", "fclk_div5"
 };
 
 static const struct meson_pwm_data pwm_axg_ao_data = {
@@ -426,7 +434,7 @@
 };
 
 static const char * const pwm_g12a_ao_ab_parent_names[] = {
-	"xtal", "aoclk81", "fclk_div4", "fclk_div5"
+	"xtal", "g12a_ao_clk81", "fclk_div4", "fclk_div5"
 };
 
 static const struct meson_pwm_data pwm_g12a_ao_ab_data = {
@@ -435,7 +443,7 @@
 };
 
 static const char * const pwm_g12a_ao_cd_parent_names[] = {
-	"xtal", "aoclk81",
+	"xtal", "g12a_ao_clk81",
 };
 
 static const struct meson_pwm_data pwm_g12a_ao_cd_data = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pwm/pwm-mtk-disp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pwm/pwm-mtk-disp.c
@@ -74,6 +74,19 @@
 	u64 div, rate;
 	int err;
 
+	err = clk_prepare_enable(mdp->clk_main);
+	if (err < 0) {
+		dev_err(chip->dev, "Can't enable mdp->clk_main: %pe\n", ERR_PTR(err));
+		return err;
+	}
+
+	err = clk_prepare_enable(mdp->clk_mm);
+	if (err < 0) {
+		dev_err(chip->dev, "Can't enable mdp->clk_mm: %pe\n", ERR_PTR(err));
+		clk_disable_unprepare(mdp->clk_main);
+		return err;
+	}
+
 	/*
 	 * Find period, high_width and clk_div to suit duty_ns and period_ns.
 	 * Calculate proper div value to keep period value in the bound.
@@ -87,8 +100,11 @@
 	rate = clk_get_rate(mdp->clk_main);
 	clk_div = div_u64(rate * period_ns, NSEC_PER_SEC) >>
 			  PWM_PERIOD_BIT_WIDTH;
-	if (clk_div > PWM_CLKDIV_MAX)
+	if (clk_div > PWM_CLKDIV_MAX) {
+		clk_disable_unprepare(mdp->clk_mm);
+		clk_disable_unprepare(mdp->clk_main);
 		return -EINVAL;
+	}
 
 	div = NSEC_PER_SEC * (clk_div + 1);
 	period = div64_u64(rate * period_ns, div);
@@ -98,14 +114,17 @@
 	high_width = div64_u64(rate * duty_ns, div);
 	value = period | (high_width << PWM_HIGH_WIDTH_SHIFT);
 
-	err = clk_enable(mdp->clk_main);
-	if (err < 0)
-		return err;
-
-	err = clk_enable(mdp->clk_mm);
-	if (err < 0) {
-		clk_disable(mdp->clk_main);
-		return err;
+	if (mdp->data->bls_debug && !mdp->data->has_commit) {
+		/*
+		 * For MT2701, disable double buffer before writing register
+		 * and select manual mode and use PWM_PERIOD/PWM_HIGH_WIDTH.
+		 */
+		mtk_disp_pwm_update_bits(mdp, mdp->data->bls_debug,
+					 mdp->data->bls_debug_mask,
+					 mdp->data->bls_debug_mask);
+		mtk_disp_pwm_update_bits(mdp, mdp->data->con0,
+					 mdp->data->con0_sel,
+					 mdp->data->con0_sel);
 	}
 
 	mtk_disp_pwm_update_bits(mdp, mdp->data->con0,
@@ -124,8 +143,8 @@
 					 0x0);
 	}
 
-	clk_disable(mdp->clk_mm);
-	clk_disable(mdp->clk_main);
+	clk_disable_unprepare(mdp->clk_mm);
+	clk_disable_unprepare(mdp->clk_main);
 
 	return 0;
 }
@@ -135,13 +154,16 @@
 	struct mtk_disp_pwm *mdp = to_mtk_disp_pwm(chip);
 	int err;
 
-	err = clk_enable(mdp->clk_main);
-	if (err < 0)
+	err = clk_prepare_enable(mdp->clk_main);
+	if (err < 0) {
+		dev_err(chip->dev, "Can't enable mdp->clk_main: %pe\n", ERR_PTR(err));
 		return err;
+	}
 
-	err = clk_enable(mdp->clk_mm);
+	err = clk_prepare_enable(mdp->clk_mm);
 	if (err < 0) {
-		clk_disable(mdp->clk_main);
+		dev_err(chip->dev, "Can't enable mdp->clk_mm: %pe\n", ERR_PTR(err));
+		clk_disable_unprepare(mdp->clk_main);
 		return err;
 	}
 
@@ -158,8 +180,8 @@
 	mtk_disp_pwm_update_bits(mdp, DISP_PWM_EN, mdp->data->enable_mask,
 				 0x0);
 
-	clk_disable(mdp->clk_mm);
-	clk_disable(mdp->clk_main);
+	clk_disable_unprepare(mdp->clk_mm);
+	clk_disable_unprepare(mdp->clk_main);
 }
 
 static const struct pwm_ops mtk_disp_pwm_ops = {
@@ -194,14 +216,6 @@
 	if (IS_ERR(mdp->clk_mm))
 		return PTR_ERR(mdp->clk_mm);
 
-	ret = clk_prepare(mdp->clk_main);
-	if (ret < 0)
-		return ret;
-
-	ret = clk_prepare(mdp->clk_mm);
-	if (ret < 0)
-		goto disable_clk_main;
-
 	mdp->chip.dev = &pdev->dev;
 	mdp->chip.ops = &mtk_disp_pwm_ops;
 	mdp->chip.base = -1;
@@ -209,44 +223,22 @@
 
 	ret = pwmchip_add(&mdp->chip);
 	if (ret < 0) {
-		dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
-		goto disable_clk_mm;
+		dev_err(&pdev->dev, "pwmchip_add() failed: %pe\n", ERR_PTR(ret));
+		return ret;
 	}
 
 	platform_set_drvdata(pdev, mdp);
 
-	/*
-	 * For MT2701, disable double buffer before writing register
-	 * and select manual mode and use PWM_PERIOD/PWM_HIGH_WIDTH.
-	 */
-	if (!mdp->data->has_commit) {
-		mtk_disp_pwm_update_bits(mdp, mdp->data->bls_debug,
-					 mdp->data->bls_debug_mask,
-					 mdp->data->bls_debug_mask);
-		mtk_disp_pwm_update_bits(mdp, mdp->data->con0,
-					 mdp->data->con0_sel,
-					 mdp->data->con0_sel);
-	}
-
 	return 0;
-
-disable_clk_mm:
-	clk_unprepare(mdp->clk_mm);
-disable_clk_main:
-	clk_unprepare(mdp->clk_main);
-	return ret;
 }
 
 static int mtk_disp_pwm_remove(struct platform_device *pdev)
 {
 	struct mtk_disp_pwm *mdp = platform_get_drvdata(pdev);
-	int ret;
 
-	ret = pwmchip_remove(&mdp->chip);
-	clk_unprepare(mdp->clk_mm);
-	clk_unprepare(mdp->clk_main);
+	pwmchip_remove(&mdp->chip);
 
-	return ret;
+	return 0;
 }
 
 static const struct mtk_pwm_data mt2701_pwm_data = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pwm/pwm-omap-dmtimer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pwm/pwm-omap-dmtimer.c
@@ -256,7 +256,7 @@
 	if (!timer_pdev) {
 		dev_err(&pdev->dev, "Unable to find Timer pdev\n");
 		ret = -ENODEV;
-		goto put;
+		goto err_find_timer_pdev;
 	}
 
 	timer_pdata = dev_get_platdata(&timer_pdev->dev);
@@ -264,7 +264,7 @@
 		dev_dbg(&pdev->dev,
 			 "dmtimer pdata structure NULL, deferring probe\n");
 		ret = -EPROBE_DEFER;
-		goto put;
+		goto err_platdata;
 	}
 
 	pdata = timer_pdata->timer_ops;
@@ -283,30 +283,25 @@
 	    !pdata->write_counter) {
 		dev_err(&pdev->dev, "Incomplete dmtimer pdata structure\n");
 		ret = -EINVAL;
-		goto put;
+		goto err_platdata;
 	}
 
 	if (!of_get_property(timer, "ti,timer-pwm", NULL)) {
 		dev_err(&pdev->dev, "Missing ti,timer-pwm capability\n");
 		ret = -ENODEV;
-		goto put;
+		goto err_timer_property;
 	}
 
 	dm_timer = pdata->request_by_node(timer);
 	if (!dm_timer) {
 		ret = -EPROBE_DEFER;
-		goto put;
+		goto err_request_timer;
 	}
 
-put:
-	of_node_put(timer);
-	if (ret < 0)
-		return ret;
-
 	omap = devm_kzalloc(&pdev->dev, sizeof(*omap), GFP_KERNEL);
 	if (!omap) {
-		pdata->free(dm_timer);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto err_alloc_omap;
 	}
 
 	omap->pdata = pdata;
@@ -339,27 +334,56 @@
 	ret = pwmchip_add(&omap->chip);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "failed to register PWM\n");
-		omap->pdata->free(omap->dm_timer);
-		return ret;
+		goto err_pwmchip_add;
 	}
 
+	of_node_put(timer);
+
 	platform_set_drvdata(pdev, omap);
 
 	return 0;
+
+err_pwmchip_add:
+
+	/*
+	 * *omap is allocated using devm_kzalloc,
+	 * so no free necessary here
+	 */
+err_alloc_omap:
+
+	pdata->free(dm_timer);
+err_request_timer:
+
+err_timer_property:
+err_platdata:
+
+	put_device(&timer_pdev->dev);
+err_find_timer_pdev:
+
+	of_node_put(timer);
+
+	return ret;
 }
 
 static int pwm_omap_dmtimer_remove(struct platform_device *pdev)
 {
 	struct pwm_omap_dmtimer_chip *omap = platform_get_drvdata(pdev);
+	int ret;
+
+	ret = pwmchip_remove(&omap->chip);
+	if (ret)
+		return ret;
 
 	if (pm_runtime_active(&omap->dm_timer_pdev->dev))
 		omap->pdata->stop(omap->dm_timer);
 
 	omap->pdata->free(omap->dm_timer);
 
+	put_device(&omap->dm_timer_pdev->dev);
+
 	mutex_destroy(&omap->mutex);
 
-	return pwmchip_remove(&omap->chip);
+	return 0;
 }
 
 static const struct of_device_id pwm_omap_dmtimer_of_match[] = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pwm/pwm-pca9685.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pwm/pwm-pca9685.c
@@ -20,6 +20,7 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/pm_runtime.h>
+#include <linux/bitmap.h>
 
 /*
  * Because the PCA9685 has only one prescaler per chip, changing the period of
@@ -74,6 +75,7 @@
 #if IS_ENABLED(CONFIG_GPIOLIB)
 	struct mutex lock;
 	struct gpio_chip gpio;
+	DECLARE_BITMAP(pwms_inuse, PCA9685_MAXCHAN + 1);
 #endif
 };
 
@@ -83,51 +85,51 @@
 }
 
 #if IS_ENABLED(CONFIG_GPIOLIB)
-static int pca9685_pwm_gpio_request(struct gpio_chip *gpio, unsigned int offset)
+static bool pca9685_pwm_test_and_set_inuse(struct pca9685 *pca, int pwm_idx)
 {
-	struct pca9685 *pca = gpiochip_get_data(gpio);
-	struct pwm_device *pwm;
+	bool is_inuse;
 
 	mutex_lock(&pca->lock);
-
-	pwm = &pca->chip.pwms[offset];
-
-	if (pwm->flags & (PWMF_REQUESTED | PWMF_EXPORTED)) {
-		mutex_unlock(&pca->lock);
-		return -EBUSY;
+	if (pwm_idx >= PCA9685_MAXCHAN) {
+		/*
+		 * "all LEDs" channel:
+		 * pretend already in use if any of the PWMs are requested
+		 */
+		if (!bitmap_empty(pca->pwms_inuse, PCA9685_MAXCHAN)) {
+			is_inuse = true;
+			goto out;
+		}
+	} else {
+		/*
+		 * regular channel:
+		 * pretend already in use if the "all LEDs" channel is requested
+		 */
+		if (test_bit(PCA9685_MAXCHAN, pca->pwms_inuse)) {
+			is_inuse = true;
+			goto out;
+		}
 	}
-
-	pwm_set_chip_data(pwm, (void *)1);
-
+	is_inuse = test_and_set_bit(pwm_idx, pca->pwms_inuse);
+out:
 	mutex_unlock(&pca->lock);
-	pm_runtime_get_sync(pca->chip.dev);
-	return 0;
+	return is_inuse;
 }
 
-static bool pca9685_pwm_is_gpio(struct pca9685 *pca, struct pwm_device *pwm)
+static void pca9685_pwm_clear_inuse(struct pca9685 *pca, int pwm_idx)
 {
-	bool is_gpio = false;
-
 	mutex_lock(&pca->lock);
+	clear_bit(pwm_idx, pca->pwms_inuse);
+	mutex_unlock(&pca->lock);
+}
 
-	if (pwm->hwpwm >= PCA9685_MAXCHAN) {
-		unsigned int i;
-
-		/*
-		 * Check if any of the GPIOs are requested and in that case
-		 * prevent using the "all LEDs" channel.
-		 */
-		for (i = 0; i < pca->gpio.ngpio; i++)
-			if (gpiochip_is_requested(&pca->gpio, i)) {
-				is_gpio = true;
-				break;
-			}
-	} else if (pwm_get_chip_data(pwm)) {
-		is_gpio = true;
-	}
+static int pca9685_pwm_gpio_request(struct gpio_chip *gpio, unsigned int offset)
+{
+	struct pca9685 *pca = gpiochip_get_data(gpio);
 
-	mutex_unlock(&pca->lock);
-	return is_gpio;
+	if (pca9685_pwm_test_and_set_inuse(pca, offset))
+		return -EBUSY;
+	pm_runtime_get_sync(pca->chip.dev);
+	return 0;
 }
 
 static int pca9685_pwm_gpio_get(struct gpio_chip *gpio, unsigned int offset)
@@ -159,13 +161,10 @@
 static void pca9685_pwm_gpio_free(struct gpio_chip *gpio, unsigned int offset)
 {
 	struct pca9685 *pca = gpiochip_get_data(gpio);
-	struct pwm_device *pwm;
 
 	pca9685_pwm_gpio_set(gpio, offset, 0);
 	pm_runtime_put(pca->chip.dev);
-	mutex_lock(&pca->lock);
-	pwm = &pca->chip.pwms[offset];
-	mutex_unlock(&pca->lock);
+	pca9685_pwm_clear_inuse(pca, offset);
 }
 
 static int pca9685_pwm_gpio_get_direction(struct gpio_chip *chip,
@@ -217,12 +216,17 @@
 	return devm_gpiochip_add_data(dev, &pca->gpio, pca);
 }
 #else
-static inline bool pca9685_pwm_is_gpio(struct pca9685 *pca,
-				       struct pwm_device *pwm)
+static inline bool pca9685_pwm_test_and_set_inuse(struct pca9685 *pca,
+						  int pwm_idx)
 {
 	return false;
 }
 
+static inline void
+pca9685_pwm_clear_inuse(struct pca9685 *pca, int pwm_idx)
+{
+}
+
 static inline int pca9685_pwm_gpio_probe(struct pca9685 *pca)
 {
 	return 0;
@@ -406,7 +410,7 @@
 {
 	struct pca9685 *pca = to_pca(chip);
 
-	if (pca9685_pwm_is_gpio(pca, pwm))
+	if (pca9685_pwm_test_and_set_inuse(pca, pwm->hwpwm))
 		return -EBUSY;
 	pm_runtime_get_sync(chip->dev);
 
@@ -415,8 +419,11 @@
 
 static void pca9685_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
 {
+	struct pca9685 *pca = to_pca(chip);
+
 	pca9685_pwm_disable(chip, pwm);
 	pm_runtime_put(chip->dev);
+	pca9685_pwm_clear_inuse(pca, pwm->hwpwm);
 }
 
 static const struct pwm_ops pca9685_pwm_ops = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pwm/pwm-rcar.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pwm/pwm-rcar.c
@@ -228,24 +228,28 @@
 	rcar_pwm->chip.base = -1;
 	rcar_pwm->chip.npwm = 1;
 
+	pm_runtime_enable(&pdev->dev);
+
 	ret = pwmchip_add(&rcar_pwm->chip);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "failed to register PWM chip: %d\n", ret);
+		pm_runtime_disable(&pdev->dev);
 		return ret;
 	}
 
-	pm_runtime_enable(&pdev->dev);
-
 	return 0;
 }
 
 static int rcar_pwm_remove(struct platform_device *pdev)
 {
 	struct rcar_pwm_chip *rcar_pwm = platform_get_drvdata(pdev);
+	int ret;
+
+	ret = pwmchip_remove(&rcar_pwm->chip);
 
 	pm_runtime_disable(&pdev->dev);
 
-	return pwmchip_remove(&rcar_pwm->chip);
+	return ret;
 }
 
 static const struct of_device_id rcar_pwm_of_table[] = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pwm/pwm-renesas-tpu.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pwm/pwm-renesas-tpu.c
@@ -415,16 +415,17 @@
 	tpu->chip.base = -1;
 	tpu->chip.npwm = TPU_CHANNEL_MAX;
 
+	pm_runtime_enable(&pdev->dev);
+
 	ret = pwmchip_add(&tpu->chip);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "failed to register PWM chip\n");
+		pm_runtime_disable(&pdev->dev);
 		return ret;
 	}
 
 	dev_info(&pdev->dev, "TPU PWM %d registered\n", tpu->pdev->id);
 
-	pm_runtime_enable(&pdev->dev);
-
 	return 0;
 }
 
@@ -434,12 +435,10 @@
 	int ret;
 
 	ret = pwmchip_remove(&tpu->chip);
-	if (ret)
-		return ret;
 
 	pm_runtime_disable(&pdev->dev);
 
-	return 0;
+	return ret;
 }
 
 #ifdef CONFIG_OF
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pwm/pwm-rockchip.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pwm/pwm-rockchip.c
@@ -361,7 +361,6 @@
 
 	ret = pwmchip_add(&pc->chip);
 	if (ret < 0) {
-		clk_unprepare(pc->clk);
 		dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
 		goto err_pclk;
 	}
@@ -384,20 +383,6 @@
 {
 	struct rockchip_pwm_chip *pc = platform_get_drvdata(pdev);
 
-	/*
-	 * Disable the PWM clk before unpreparing it if the PWM device is still
-	 * running. This should only happen when the last PWM user left it
-	 * enabled, or when nobody requested a PWM that was previously enabled
-	 * by the bootloader.
-	 *
-	 * FIXME: Maybe the core should disable all PWM devices in
-	 * pwmchip_remove(). In this case we'd only have to call
-	 * clk_unprepare() after pwmchip_remove().
-	 *
-	 */
-	if (pwm_is_enabled(pc->chip.pwms))
-		clk_disable(pc->clk);
-
 	clk_unprepare(pc->pclk);
 	clk_unprepare(pc->clk);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pwm/pwm-sifive.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pwm/pwm-sifive.c
@@ -43,7 +43,7 @@
 
 struct pwm_sifive_ddata {
 	struct pwm_chip	chip;
-	struct mutex lock; /* lock to protect user_count */
+	struct mutex lock; /* lock to protect user_count and approx_period */
 	struct notifier_block notifier;
 	struct clk *clk;
 	void __iomem *regs;
@@ -78,6 +78,7 @@
 	mutex_unlock(&ddata->lock);
 }
 
+/* Called holding ddata->lock */
 static void pwm_sifive_update_clock(struct pwm_sifive_ddata *ddata,
 				    unsigned long rate)
 {
@@ -166,7 +167,6 @@
 		return ret;
 	}
 
-	mutex_lock(&ddata->lock);
 	cur_state = pwm->state;
 	enabled = cur_state.enabled;
 
@@ -185,14 +185,23 @@
 	/* The hardware cannot generate a 100% duty cycle */
 	frac = min(frac, (1U << PWM_SIFIVE_CMPWIDTH) - 1);
 
+	mutex_lock(&ddata->lock);
 	if (state->period != ddata->approx_period) {
-		if (ddata->user_count != 1) {
+		/*
+		 * Don't let a 2nd user change the period underneath the 1st user.
+		 * However if ddate->approx_period == 0 this is the first time we set
+		 * any period, so let whoever gets here first set the period so other
+		 * users who agree on the period won't fail.
+		 */
+		if (ddata->user_count != 1 && ddata->approx_period) {
+			mutex_unlock(&ddata->lock);
 			ret = -EBUSY;
 			goto exit;
 		}
 		ddata->approx_period = state->period;
 		pwm_sifive_update_clock(ddata, clk_get_rate(ddata->clk));
 	}
+	mutex_unlock(&ddata->lock);
 
 	writel(frac, ddata->regs + PWM_SIFIVE_PWMCMP0 +
 	       pwm->hwpwm * PWM_SIFIVE_SIZE_PWMCMP);
@@ -202,7 +211,6 @@
 
 exit:
 	clk_disable(ddata->clk);
-	mutex_unlock(&ddata->lock);
 	return ret;
 }
 
@@ -221,8 +229,11 @@
 	struct pwm_sifive_ddata *ddata =
 		container_of(nb, struct pwm_sifive_ddata, notifier);
 
-	if (event == POST_RATE_CHANGE)
+	if (event == POST_RATE_CHANGE) {
+		mutex_lock(&ddata->lock);
 		pwm_sifive_update_clock(ddata, ndata->new_rate);
+		mutex_unlock(&ddata->lock);
+	}
 
 	return NOTIFY_OK;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pwm/pwm-spear.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pwm/pwm-spear.c
@@ -231,10 +231,6 @@
 static int spear_pwm_remove(struct platform_device *pdev)
 {
 	struct spear_pwm_chip *pc = platform_get_drvdata(pdev);
-	int i;
-
-	for (i = 0; i < NUM_PWM; i++)
-		pwm_disable(&pc->chip.pwms[i]);
 
 	/* clk was prepared in probe, hence unprepare it here */
 	clk_unprepare(pc->clk);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pwm/pwm-sprd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pwm/pwm-sprd.c
@@ -109,6 +109,7 @@
 	duty = val & SPRD_PWM_DUTY_MSK;
 	tmp = (prescale + 1) * NSEC_PER_SEC * duty;
 	state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, chn->clk_rate);
+	state->polarity = PWM_POLARITY_NORMAL;
 
 	/* Disable PWM clocks if the PWM channel is not in enable state. */
 	if (!state->enabled)
@@ -180,13 +181,10 @@
 			}
 		}
 
-		if (state->period != cstate->period ||
-		    state->duty_cycle != cstate->duty_cycle) {
-			ret = sprd_pwm_config(spc, pwm, state->duty_cycle,
-					      state->period);
-			if (ret)
-				return ret;
-		}
+		ret = sprd_pwm_config(spc, pwm, state->duty_cycle,
+				      state->period);
+		if (ret)
+			return ret;
 
 		sprd_pwm_write(spc, pwm->hwpwm, SPRD_PWM_ENABLE, 1);
 	} else if (cstate->enabled) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pwm/pwm-sti.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pwm/pwm-sti.c
@@ -79,6 +79,7 @@
 	unsigned int cpt_num_devs;
 	unsigned int max_pwm_cnt;
 	unsigned int max_prescale;
+	struct sti_cpt_ddata *ddata;
 };
 
 struct sti_pwm_chip {
@@ -314,7 +315,7 @@
 {
 	struct sti_pwm_chip *pc = to_sti_pwmchip(chip);
 	struct sti_pwm_compat_data *cdata = pc->cdata;
-	struct sti_cpt_ddata *ddata = pwm_get_chip_data(pwm);
+	struct sti_cpt_ddata *ddata = &cdata->ddata[pwm->hwpwm];
 	struct device *dev = pc->dev;
 	unsigned int effective_ticks;
 	unsigned long long high, low;
@@ -417,7 +418,7 @@
 	while (cpt_int_stat) {
 		devicenum = ffs(cpt_int_stat) - 1;
 
-		ddata = pwm_get_chip_data(&pc->chip.pwms[devicenum]);
+		ddata = &pc->cdata->ddata[devicenum];
 
 		/*
 		 * Capture input:
@@ -593,61 +594,55 @@
 	if (ret)
 		return ret;
 
-	if (!cdata->pwm_num_devs)
-		goto skip_pwm;
-
-	pc->pwm_clk = of_clk_get_by_name(dev->of_node, "pwm");
-	if (IS_ERR(pc->pwm_clk)) {
-		dev_err(dev, "failed to get PWM clock\n");
-		return PTR_ERR(pc->pwm_clk);
-	}
+	if (cdata->pwm_num_devs) {
+		pc->pwm_clk = of_clk_get_by_name(dev->of_node, "pwm");
+		if (IS_ERR(pc->pwm_clk)) {
+			dev_err(dev, "failed to get PWM clock\n");
+			return PTR_ERR(pc->pwm_clk);
+		}
 
-	ret = clk_prepare(pc->pwm_clk);
-	if (ret) {
-		dev_err(dev, "failed to prepare clock\n");
-		return ret;
+		ret = clk_prepare(pc->pwm_clk);
+		if (ret) {
+			dev_err(dev, "failed to prepare clock\n");
+			return ret;
+		}
 	}
 
-skip_pwm:
-	if (!cdata->cpt_num_devs)
-		goto skip_cpt;
+	if (cdata->cpt_num_devs) {
+		pc->cpt_clk = of_clk_get_by_name(dev->of_node, "capture");
+		if (IS_ERR(pc->cpt_clk)) {
+			dev_err(dev, "failed to get PWM capture clock\n");
+			return PTR_ERR(pc->cpt_clk);
+		}
 
-	pc->cpt_clk = of_clk_get_by_name(dev->of_node, "capture");
-	if (IS_ERR(pc->cpt_clk)) {
-		dev_err(dev, "failed to get PWM capture clock\n");
-		return PTR_ERR(pc->cpt_clk);
-	}
+		ret = clk_prepare(pc->cpt_clk);
+		if (ret) {
+			dev_err(dev, "failed to prepare clock\n");
+			return ret;
+		}
 
-	ret = clk_prepare(pc->cpt_clk);
-	if (ret) {
-		dev_err(dev, "failed to prepare clock\n");
-		return ret;
+		cdata->ddata = devm_kzalloc(dev, cdata->cpt_num_devs * sizeof(*cdata->ddata), GFP_KERNEL);
+		if (!cdata->ddata)
+			return -ENOMEM;
 	}
 
-skip_cpt:
 	pc->chip.dev = dev;
 	pc->chip.ops = &sti_pwm_ops;
 	pc->chip.base = -1;
 	pc->chip.npwm = pc->cdata->pwm_num_devs;
 
-	ret = pwmchip_add(&pc->chip);
-	if (ret < 0) {
-		clk_unprepare(pc->pwm_clk);
-		clk_unprepare(pc->cpt_clk);
-		return ret;
-	}
-
 	for (i = 0; i < cdata->cpt_num_devs; i++) {
-		struct sti_cpt_ddata *ddata;
-
-		ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
-		if (!ddata)
-			return -ENOMEM;
+		struct sti_cpt_ddata *ddata = &cdata->ddata[i];
 
 		init_waitqueue_head(&ddata->wait);
 		mutex_init(&ddata->lock);
+	}
 
-		pwm_set_chip_data(&pc->chip.pwms[i], ddata);
+	ret = pwmchip_add(&pc->chip);
+	if (ret < 0) {
+		clk_unprepare(pc->pwm_clk);
+		clk_unprepare(pc->cpt_clk);
+		return ret;
 	}
 
 	platform_set_drvdata(pdev, pc);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pwm/pwm-stm32-lp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pwm/pwm-stm32-lp.c
@@ -127,7 +127,7 @@
 
 	/* ensure CMP & ARR registers are properly written */
 	ret = regmap_read_poll_timeout(priv->regmap, STM32_LPTIM_ISR, val,
-				       (val & STM32_LPTIM_CMPOK_ARROK),
+				       (val & STM32_LPTIM_CMPOK_ARROK) == STM32_LPTIM_CMPOK_ARROK,
 				       100, 1000);
 	if (ret) {
 		dev_err(priv->chip.dev, "ARR/CMP registers write issue\n");
@@ -225,8 +225,6 @@
 {
 	struct stm32_pwm_lp *priv = platform_get_drvdata(pdev);
 
-	pwm_disable(&priv->chip.pwms[0]);
-
 	return pwmchip_remove(&priv->chip);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pwm/pwm-stm32.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pwm/pwm-stm32.c
@@ -337,6 +337,9 @@
 
 	prd = div;
 
+	if (!prd)
+		return -EINVAL;
+
 	if (prescaler > MAX_TIM_PSC)
 		return -EINVAL;
 
@@ -448,8 +451,9 @@
 
 	enabled = pwm->state.enabled;
 
-	if (enabled && !state->enabled) {
-		stm32_pwm_disable(priv, pwm->hwpwm);
+	if (!state->enabled) {
+		if (enabled)
+			stm32_pwm_disable(priv, pwm->hwpwm);
 		return 0;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pwm/pwm-sun4i.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pwm/pwm-sun4i.c
@@ -137,10 +137,10 @@
 
 	val = sun4i_pwm_readl(sun4i_pwm, PWM_CH_PRD(pwm->hwpwm));
 
-	tmp = prescaler * NSEC_PER_SEC * PWM_REG_DTY(val);
+	tmp = (u64)prescaler * NSEC_PER_SEC * PWM_REG_DTY(val);
 	state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, clk_rate);
 
-	tmp = prescaler * NSEC_PER_SEC * PWM_REG_PRD(val);
+	tmp = (u64)prescaler * NSEC_PER_SEC * PWM_REG_PRD(val);
 	state->period = DIV_ROUND_CLOSEST_ULL(tmp, clk_rate);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pwm/pwm-tegra.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pwm/pwm-tegra.c
@@ -232,7 +232,6 @@
 static int tegra_pwm_remove(struct platform_device *pdev)
 {
 	struct tegra_pwm_chip *pc = platform_get_drvdata(pdev);
-	unsigned int i;
 	int err;
 
 	if (WARN_ON(!pc))
@@ -242,18 +241,6 @@
 	if (err < 0)
 		return err;
 
-	for (i = 0; i < pc->chip.npwm; i++) {
-		struct pwm_device *pwm = &pc->chip.pwms[i];
-
-		if (!pwm_is_enabled(pwm))
-			if (clk_prepare_enable(pc->clk) < 0)
-				continue;
-
-		pwm_writel(pc, i, 0);
-
-		clk_disable_unprepare(pc->clk);
-	}
-
 	reset_control_assert(pc->rst);
 	clk_disable_unprepare(pc->clk);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pwm/pwm-zx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pwm/pwm-zx.c
@@ -238,6 +238,7 @@
 	ret = pwmchip_add(&zpc->chip);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret);
+		clk_disable_unprepare(zpc->pclk);
 		return ret;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/pwm/sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/pwm/sysfs.c
@@ -424,6 +424,13 @@
 		if (!export)
 			continue;
 
+		/* If pwmchip was not enabled before suspend, do nothing. */
+		if (!export->suspend.enabled) {
+			/* release lock taken in pwm_class_get_state */
+			mutex_unlock(&export->lock);
+			continue;
+		}
+
 		state.enabled = export->suspend.enabled;
 		ret = pwm_class_apply_state(export, pwm, &state);
 		if (ret < 0)
@@ -448,7 +455,17 @@
 		if (!export)
 			continue;
 
+		/*
+		 * If pwmchip was not enabled before suspend, save
+		 * state for resume time and do nothing else.
+		 */
 		export->suspend = state;
+		if (!state.enabled) {
+			/* release lock taken in pwm_class_get_state */
+			mutex_unlock(&export->lock);
+			continue;
+		}
+
 		state.enabled = false;
 		ret = pwm_class_apply_state(export, pwm, &state);
 		if (ret < 0) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rapidio/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/rapidio/Kconfig
@@ -37,7 +37,7 @@
 config RAPIDIO_DMA_ENGINE
 	bool "DMA Engine support for RapidIO"
 	depends on RAPIDIO
-	select DMADEVICES
+	depends on DMADEVICES
 	select DMA_ENGINE
 	help
 	  Say Y here if you want to use DMA Engine frameork for RapidIO data
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rapidio/devices/rio_mport_cdev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rapidio/devices/rio_mport_cdev.c
@@ -873,9 +873,15 @@
 				rmcd_error("get_user_pages_unlocked err=%ld",
 					   pinned);
 				nr_pages = 0;
-			} else
+			} else {
 				rmcd_error("pinned %ld out of %ld pages",
 					   pinned, nr_pages);
+				/*
+				 * Set nr_pages up to mean "how many pages to unpin, in
+				 * the error handler:
+				 */
+				nr_pages = pinned;
+			}
 			ret = -EFAULT;
 			goto err_pg;
 		}
@@ -1677,6 +1683,7 @@
 	struct rio_dev *rdev;
 	struct rio_switch *rswitch = NULL;
 	struct rio_mport *mport;
+	struct device *dev;
 	size_t size;
 	u32 rval;
 	u32 swpinfo = 0;
@@ -1691,8 +1698,10 @@
 	rmcd_debug(RDEV, "name:%s ct:0x%x did:0x%x hc:0x%x", dev_info.name,
 		   dev_info.comptag, dev_info.destid, dev_info.hopcount);
 
-	if (bus_find_device_by_name(&rio_bus_type, NULL, dev_info.name)) {
+	dev = bus_find_device_by_name(&rio_bus_type, NULL, dev_info.name);
+	if (dev) {
 		rmcd_debug(RDEV, "device %s already exists", dev_info.name);
+		put_device(dev);
 		return -EEXIST;
 	}
 
@@ -1734,7 +1743,8 @@
 		err = rio_add_net(net);
 		if (err) {
 			rmcd_debug(RDEV, "failed to register net, err=%d", err);
-			kfree(net);
+			put_device(&net->dev);
+			mport->net = NULL;
 			goto cleanup;
 		}
 	}
@@ -1798,8 +1808,11 @@
 		rio_init_dbell_res(&rdev->riores[RIO_DOORBELL_RESOURCE],
 				   0, 0xffff);
 	err = rio_add_device(rdev);
-	if (err)
-		goto cleanup;
+	if (err) {
+		put_device(&rdev->dev);
+		return err;
+	}
+
 	rio_dev_get(rdev);
 
 	return 0;
@@ -1895,10 +1908,6 @@
 
 	priv->md = chdev;
 
-	mutex_lock(&chdev->file_mutex);
-	list_add_tail(&priv->list, &chdev->file_list);
-	mutex_unlock(&chdev->file_mutex);
-
 	INIT_LIST_HEAD(&priv->db_filters);
 	INIT_LIST_HEAD(&priv->pw_filters);
 	spin_lock_init(&priv->fifo_lock);
@@ -1907,6 +1916,7 @@
 			  sizeof(struct rio_event) * MPORT_EVENT_DEPTH,
 			  GFP_KERNEL);
 	if (ret < 0) {
+		put_device(&chdev->dev);
 		dev_err(&chdev->dev, DRV_NAME ": kfifo_alloc failed\n");
 		ret = -ENOMEM;
 		goto err_fifo;
@@ -1917,6 +1927,9 @@
 	spin_lock_init(&priv->req_lock);
 	mutex_init(&priv->dma_lock);
 #endif
+	mutex_lock(&chdev->file_mutex);
+	list_add_tail(&priv->list, &chdev->file_list);
+	mutex_unlock(&chdev->file_mutex);
 
 	filp->private_data = priv;
 	goto out;
@@ -2379,13 +2392,6 @@
 	cdev_init(&md->cdev, &mport_fops);
 	md->cdev.owner = THIS_MODULE;
 
-	ret = cdev_device_add(&md->cdev, &md->dev);
-	if (ret) {
-		rmcd_error("Failed to register mport %d (err=%d)",
-		       mport->id, ret);
-		goto err_cdev;
-	}
-
 	INIT_LIST_HEAD(&md->doorbells);
 	spin_lock_init(&md->db_lock);
 	INIT_LIST_HEAD(&md->portwrites);
@@ -2405,6 +2411,13 @@
 #else
 	md->properties.transfer_mode |= RIO_TRANSFER_MODE_TRANSFER;
 #endif
+
+	ret = cdev_device_add(&md->cdev, &md->dev);
+	if (ret) {
+		rmcd_error("Failed to register mport %d (err=%d)",
+		       mport->id, ret);
+		goto err_cdev;
+	}
 	ret = rio_query_mport(mport, &attr);
 	if (!ret) {
 		md->properties.flags = attr.flags;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rapidio/rio-scan.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rapidio/rio-scan.c
@@ -456,8 +456,12 @@
 				   0, 0xffff);
 
 	ret = rio_add_device(rdev);
-	if (ret)
-		goto cleanup;
+	if (ret) {
+		if (rswitch)
+			kfree(rswitch->route_table);
+		put_device(&rdev->dev);
+		return NULL;
+	}
 
 	rio_dev_get(rdev);
 
@@ -869,7 +873,10 @@
 		dev_set_name(&net->dev, "rnet_%d", net->id);
 		net->dev.parent = &mport->dev;
 		net->dev.release = rio_scan_release_dev;
-		rio_add_net(net);
+		if (rio_add_net(net)) {
+			put_device(&net->dev);
+			net = NULL;
+		}
 	}
 
 	return net;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rapidio/rio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rapidio/rio.c
@@ -2267,11 +2267,16 @@
 	atomic_set(&port->state, RIO_DEVICE_RUNNING);
 
 	res = device_register(&port->dev);
-	if (res)
+	if (res) {
 		dev_err(&port->dev, "RIO: mport%d registration failed ERR=%d\n",
 			port->id, res);
-	else
+		mutex_lock(&rio_mport_list_lock);
+		list_del(&port->node);
+		mutex_unlock(&rio_mport_list_lock);
+		put_device(&port->dev);
+	} else {
 		dev_dbg(&port->dev, "RIO: registered mport%d\n", port->id);
+	}
 
 	return res;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rapidio/rio_cm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rapidio/rio_cm.c
@@ -2127,6 +2127,14 @@
 		return -ENODEV;
 	}
 
+	cm->rx_wq = create_workqueue(DRV_NAME "/rxq");
+	if (!cm->rx_wq) {
+		rio_release_inb_mbox(mport, cmbox);
+		rio_release_outb_mbox(mport, cmbox);
+		kfree(cm);
+		return -ENOMEM;
+	}
+
 	/*
 	 * Allocate and register inbound messaging buffers to be ready
 	 * to receive channel and system management requests
@@ -2137,15 +2145,6 @@
 	cm->rx_slots = RIOCM_RX_RING_SIZE;
 	mutex_init(&cm->rx_lock);
 	riocm_rx_fill(cm, RIOCM_RX_RING_SIZE);
-	cm->rx_wq = create_workqueue(DRV_NAME "/rxq");
-	if (!cm->rx_wq) {
-		riocm_error("failed to allocate IBMBOX_%d on %s",
-			    cmbox, mport->name);
-		rio_release_outb_mbox(mport, cmbox);
-		kfree(cm);
-		return -ENOMEM;
-	}
-
 	INIT_WORK(&cm->rx_work, rio_ibmsg_handler);
 
 	cm->tx_slot = 0;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/ras/cec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/ras/cec.c
@@ -309,11 +309,20 @@
 	return ret;
 }
 
+/**
+ * cec_add_elem - Add an element to the CEC array.
+ * @pfn:	page frame number to insert
+ *
+ * Return values:
+ * - <0:	on error
+ * -  0:	on success
+ * - >0:	when the inserted pfn was offlined
+ */
 int cec_add_elem(u64 pfn)
 {
 	struct ce_array *ca = &ce_arr;
+	int count, err, ret = 0;
 	unsigned int to = 0;
-	int count, ret = 0;
 
 	/*
 	 * We can be called very early on the identify_cpu() path where we are
@@ -330,8 +339,8 @@
 	if (ca->n == MAX_ELEMS)
 		WARN_ON(!del_lru_elem_unlocked(ca));
 
-	ret = find_elem(ca, pfn, &to);
-	if (ret < 0) {
+	err = find_elem(ca, pfn, &to);
+	if (err < 0) {
 		/*
 		 * Shift range [to-end] to make room for one more element.
 		 */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/Kconfig
@@ -268,6 +268,22 @@
 	  This driver can also be built as a module. If so, the module
 	  will be called da9063-regulator.
 
+config REGULATOR_DA9121
+	tristate "Dialog Semiconductor DA9121/DA9130/DA9217/DA9122/DA9131/DA9220/DA9132 regulator"
+	depends on I2C
+	select REGMAP_I2C
+	help
+	  Say y here to support for the Dialog Semiconductor DA9121
+	  family of devices.
+
+	  The DA9121/DA9130/DA9217/DA9122/DA9131/DA9220/DA9132 regulators are
+	  controlled through an I2C interface. This driver can also be built
+	  as a module.
+	  DA9121/DA9130 - Single channel dual phase 10A buck converter
+	  DA9217	- Single channel dual phase 6A buck converter
+	  DA9122/DA9131 - Dual channel single phase  5A buck converter
+	  DA9220/DA9132 - Dual channel single phase  3A buck converter
+
 config REGULATOR_DA9210
 	tristate "Dialog Semiconductor DA9210 regulator"
 	depends on I2C
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/Makefile
@@ -35,6 +35,7 @@
 obj-$(CONFIG_REGULATOR_DA9055)	+= da9055-regulator.o
 obj-$(CONFIG_REGULATOR_DA9062)	+= da9062-regulator.o
 obj-$(CONFIG_REGULATOR_DA9063)	+= da9063-regulator.o
+obj-$(CONFIG_REGULATOR_DA9121) += da9121-regulator.o
 obj-$(CONFIG_REGULATOR_DA9210) += da9210-regulator.o
 obj-$(CONFIG_REGULATOR_DA9211) += da9211-regulator.o
 obj-$(CONFIG_REGULATOR_DBX500_PRCMU) += dbx500-prcmu.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/ab8500.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/ab8500.c
@@ -953,23 +953,6 @@
 		.update_val_idle	= 0x82,
 		.update_val_normal	= 0x02,
 	},
-	[AB8505_LDO_USB] = {
-		.desc = {
-			.name           = "LDO-USB",
-			.ops            = &ab8500_regulator_mode_ops,
-			.type           = REGULATOR_VOLTAGE,
-			.id             = AB8505_LDO_USB,
-			.owner          = THIS_MODULE,
-			.n_voltages     = 1,
-			.volt_table	= fixed_3300000_voltage,
-		},
-		.update_bank            = 0x03,
-		.update_reg             = 0x82,
-		.update_mask            = 0x03,
-		.update_val		= 0x01,
-		.update_val_idle	= 0x03,
-		.update_val_normal	= 0x01,
-	},
 	[AB8505_LDO_AUDIO] = {
 		.desc = {
 			.name		= "LDO-AUDIO",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/axp20x-regulator.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/axp20x-regulator.c
@@ -42,8 +42,9 @@
 
 #define AXP20X_DCDC2_V_OUT_MASK		GENMASK(5, 0)
 #define AXP20X_DCDC3_V_OUT_MASK		GENMASK(7, 0)
-#define AXP20X_LDO24_V_OUT_MASK		GENMASK(7, 4)
+#define AXP20X_LDO2_V_OUT_MASK		GENMASK(7, 4)
 #define AXP20X_LDO3_V_OUT_MASK		GENMASK(6, 0)
+#define AXP20X_LDO4_V_OUT_MASK		GENMASK(3, 0)
 #define AXP20X_LDO5_V_OUT_MASK		GENMASK(7, 4)
 
 #define AXP20X_PWR_OUT_EXTEN_MASK	BIT_MASK(0)
@@ -413,10 +414,13 @@
 		int i;
 
 		for (i = 0; i < rate_count; i++) {
-			if (ramp <= slew_rates[i])
-				cfg = AXP20X_DCDC2_LDO3_V_RAMP_LDO3_RATE(i);
-			else
+			if (ramp > slew_rates[i])
 				break;
+
+			if (id == AXP20X_DCDC2)
+				cfg = AXP20X_DCDC2_LDO3_V_RAMP_DCDC2_RATE(i);
+			else
+				cfg = AXP20X_DCDC2_LDO3_V_RAMP_LDO3_RATE(i);
 		}
 
 		if (cfg == 0xff) {
@@ -541,14 +545,14 @@
 		 AXP20X_PWR_OUT_CTRL, AXP20X_PWR_OUT_DCDC3_MASK),
 	AXP_DESC_FIXED(AXP20X, LDO1, "ldo1", "acin", 1300),
 	AXP_DESC(AXP20X, LDO2, "ldo2", "ldo24in", 1800, 3300, 100,
-		 AXP20X_LDO24_V_OUT, AXP20X_LDO24_V_OUT_MASK,
+		 AXP20X_LDO24_V_OUT, AXP20X_LDO2_V_OUT_MASK,
 		 AXP20X_PWR_OUT_CTRL, AXP20X_PWR_OUT_LDO2_MASK),
 	AXP_DESC(AXP20X, LDO3, "ldo3", "ldo3in", 700, 3500, 25,
 		 AXP20X_LDO3_V_OUT, AXP20X_LDO3_V_OUT_MASK,
 		 AXP20X_PWR_OUT_CTRL, AXP20X_PWR_OUT_LDO3_MASK),
 	AXP_DESC_RANGES(AXP20X, LDO4, "ldo4", "ldo24in",
 			axp20x_ldo4_ranges, AXP20X_LDO4_V_OUT_NUM_VOLTAGES,
-			AXP20X_LDO24_V_OUT, AXP20X_LDO24_V_OUT_MASK,
+			AXP20X_LDO24_V_OUT, AXP20X_LDO4_V_OUT_MASK,
 			AXP20X_PWR_OUT_CTRL, AXP20X_PWR_OUT_LDO4_MASK),
 	AXP_DESC_IO(AXP20X, LDO5, "ldo5", "ldo5in", 1800, 3300, 100,
 		    AXP20X_LDO5_V_OUT, AXP20X_LDO5_V_OUT_MASK,
@@ -592,7 +596,7 @@
 		 AXP22X_DLDO1_V_OUT, AXP22X_DLDO1_V_OUT_MASK,
 		 AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_DLDO1_MASK),
 	AXP_DESC(AXP22X, DLDO2, "dldo2", "dldoin", 700, 3300, 100,
-		 AXP22X_DLDO2_V_OUT, AXP22X_PWR_OUT_DLDO2_MASK,
+		 AXP22X_DLDO2_V_OUT, AXP22X_DLDO2_V_OUT_MASK,
 		 AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_DLDO2_MASK),
 	AXP_DESC(AXP22X, DLDO3, "dldo3", "dldoin", 700, 3300, 100,
 		 AXP22X_DLDO3_V_OUT, AXP22X_DLDO3_V_OUT_MASK,
@@ -605,7 +609,7 @@
 		 AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_ELDO1_MASK),
 	AXP_DESC(AXP22X, ELDO2, "eldo2", "eldoin", 700, 3300, 100,
 		 AXP22X_ELDO2_V_OUT, AXP22X_ELDO2_V_OUT_MASK,
-		 AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_ELDO1_MASK),
+		 AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_ELDO2_MASK),
 	AXP_DESC(AXP22X, ELDO3, "eldo3", "eldoin", 700, 3300, 100,
 		 AXP22X_ELDO3_V_OUT, AXP22X_ELDO3_V_OUT_MASK,
 		 AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_ELDO3_MASK),
@@ -1068,7 +1072,7 @@
 static int axp20x_regulator_parse_dt(struct platform_device *pdev)
 {
 	struct device_node *np, *regulators;
-	int ret;
+	int ret = 0;
 	u32 dcdcfreq = 0;
 
 	np = of_node_get(pdev->dev.parent->of_node);
@@ -1083,13 +1087,12 @@
 		ret = axp20x_set_dcdc_freq(pdev, dcdcfreq);
 		if (ret < 0) {
 			dev_err(&pdev->dev, "Error setting dcdc frequency: %d\n", ret);
-			return ret;
 		}
-
 		of_node_put(regulators);
 	}
 
-	return 0;
+	of_node_put(np);
+	return ret;
 }
 
 static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 workmode)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/bd70528-regulator.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/bd70528-regulator.c
@@ -101,7 +101,6 @@
 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
 	.set_voltage_time_sel = regulator_set_voltage_time_sel,
-	.set_ramp_delay = bd70528_set_ramp_delay,
 };
 
 static const struct regulator_ops bd70528_led_ops = {
@@ -286,3 +285,4 @@
 MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
 MODULE_DESCRIPTION("BD70528 voltage regulator driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:bd70528-pmic");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/bd718x7-regulator.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/bd718x7-regulator.c
@@ -15,6 +15,36 @@
 #include <linux/regulator/of_regulator.h>
 #include <linux/slab.h>
 
+/* Typical regulator startup times as per data sheet in uS */
+#define BD71847_BUCK1_STARTUP_TIME 144
+#define BD71847_BUCK2_STARTUP_TIME 162
+#define BD71847_BUCK3_STARTUP_TIME 162
+#define BD71847_BUCK4_STARTUP_TIME 240
+#define BD71847_BUCK5_STARTUP_TIME 270
+#define BD71847_BUCK6_STARTUP_TIME 200
+#define BD71847_LDO1_STARTUP_TIME  440
+#define BD71847_LDO2_STARTUP_TIME  370
+#define BD71847_LDO3_STARTUP_TIME  310
+#define BD71847_LDO4_STARTUP_TIME  400
+#define BD71847_LDO5_STARTUP_TIME  530
+#define BD71847_LDO6_STARTUP_TIME  400
+
+#define BD71837_BUCK1_STARTUP_TIME 160
+#define BD71837_BUCK2_STARTUP_TIME 180
+#define BD71837_BUCK3_STARTUP_TIME 180
+#define BD71837_BUCK4_STARTUP_TIME 180
+#define BD71837_BUCK5_STARTUP_TIME 160
+#define BD71837_BUCK6_STARTUP_TIME 240
+#define BD71837_BUCK7_STARTUP_TIME 220
+#define BD71837_BUCK8_STARTUP_TIME 200
+#define BD71837_LDO1_STARTUP_TIME  440
+#define BD71837_LDO2_STARTUP_TIME  370
+#define BD71837_LDO3_STARTUP_TIME  310
+#define BD71837_LDO4_STARTUP_TIME  400
+#define BD71837_LDO5_STARTUP_TIME  310
+#define BD71837_LDO6_STARTUP_TIME  400
+#define BD71837_LDO7_STARTUP_TIME  530
+
 /*
  * BUCK1/2/3/4
  * BUCK1RAMPRATE[1:0] BUCK1 DVS ramp rate setting
@@ -495,6 +525,7 @@
 			.vsel_mask = DVS_BUCK_RUN_MASK,
 			.enable_reg = BD718XX_REG_BUCK1_CTRL,
 			.enable_mask = BD718XX_BUCK_EN,
+			.enable_time = BD71847_BUCK1_STARTUP_TIME,
 			.owner = THIS_MODULE,
 			.of_parse_cb = buck1_set_hw_dvs_levels,
 		},
@@ -519,6 +550,7 @@
 			.vsel_mask = DVS_BUCK_RUN_MASK,
 			.enable_reg = BD718XX_REG_BUCK2_CTRL,
 			.enable_mask = BD718XX_BUCK_EN,
+			.enable_time = BD71847_BUCK2_STARTUP_TIME,
 			.owner = THIS_MODULE,
 			.of_parse_cb = buck2_set_hw_dvs_levels,
 		},
@@ -547,6 +579,7 @@
 			.linear_range_selectors = bd71847_buck3_volt_range_sel,
 			.enable_reg = BD718XX_REG_1ST_NODVS_BUCK_CTRL,
 			.enable_mask = BD718XX_BUCK_EN,
+			.enable_time = BD71847_BUCK3_STARTUP_TIME,
 			.owner = THIS_MODULE,
 		},
 		.init = {
@@ -574,6 +607,7 @@
 			.vsel_range_mask = BD71847_BUCK4_RANGE_MASK,
 			.linear_range_selectors = bd71847_buck4_volt_range_sel,
 			.enable_mask = BD718XX_BUCK_EN,
+			.enable_time = BD71847_BUCK4_STARTUP_TIME,
 			.owner = THIS_MODULE,
 		},
 		.init = {
@@ -596,6 +630,7 @@
 			.vsel_mask = BD718XX_3RD_NODVS_BUCK_MASK,
 			.enable_reg = BD718XX_REG_3RD_NODVS_BUCK_CTRL,
 			.enable_mask = BD718XX_BUCK_EN,
+			.enable_time = BD71847_BUCK5_STARTUP_TIME,
 			.owner = THIS_MODULE,
 		},
 		.init = {
@@ -620,6 +655,7 @@
 			.vsel_mask = BD718XX_4TH_NODVS_BUCK_MASK,
 			.enable_reg = BD718XX_REG_4TH_NODVS_BUCK_CTRL,
 			.enable_mask = BD718XX_BUCK_EN,
+			.enable_time = BD71847_BUCK6_STARTUP_TIME,
 			.owner = THIS_MODULE,
 		},
 		.init = {
@@ -646,6 +682,7 @@
 			.linear_range_selectors = bd718xx_ldo1_volt_range_sel,
 			.enable_reg = BD718XX_REG_LDO1_VOLT,
 			.enable_mask = BD718XX_LDO_EN,
+			.enable_time = BD71847_LDO1_STARTUP_TIME,
 			.owner = THIS_MODULE,
 		},
 		.init = {
@@ -668,6 +705,7 @@
 			.n_voltages = ARRAY_SIZE(ldo_2_volts),
 			.enable_reg = BD718XX_REG_LDO2_VOLT,
 			.enable_mask = BD718XX_LDO_EN,
+			.enable_time = BD71847_LDO2_STARTUP_TIME,
 			.owner = THIS_MODULE,
 		},
 		.init = {
@@ -691,6 +729,7 @@
 			.vsel_mask = BD718XX_LDO3_MASK,
 			.enable_reg = BD718XX_REG_LDO3_VOLT,
 			.enable_mask = BD718XX_LDO_EN,
+			.enable_time = BD71847_LDO3_STARTUP_TIME,
 			.owner = THIS_MODULE,
 		},
 		.init = {
@@ -714,6 +753,7 @@
 			.vsel_mask = BD718XX_LDO4_MASK,
 			.enable_reg = BD718XX_REG_LDO4_VOLT,
 			.enable_mask = BD718XX_LDO_EN,
+			.enable_time = BD71847_LDO4_STARTUP_TIME,
 			.owner = THIS_MODULE,
 		},
 		.init = {
@@ -740,6 +780,7 @@
 			.linear_range_selectors = bd71847_ldo5_volt_range_sel,
 			.enable_reg = BD718XX_REG_LDO5_VOLT,
 			.enable_mask = BD718XX_LDO_EN,
+			.enable_time = BD71847_LDO5_STARTUP_TIME,
 			.owner = THIS_MODULE,
 		},
 		.init = {
@@ -765,6 +806,7 @@
 			.vsel_mask = BD718XX_LDO6_MASK,
 			.enable_reg = BD718XX_REG_LDO6_VOLT,
 			.enable_mask = BD718XX_LDO_EN,
+			.enable_time = BD71847_LDO6_STARTUP_TIME,
 			.owner = THIS_MODULE,
 		},
 		.init = {
@@ -791,6 +833,7 @@
 			.vsel_mask = DVS_BUCK_RUN_MASK,
 			.enable_reg = BD718XX_REG_BUCK1_CTRL,
 			.enable_mask = BD718XX_BUCK_EN,
+			.enable_time = BD71837_BUCK1_STARTUP_TIME,
 			.owner = THIS_MODULE,
 			.of_parse_cb = buck1_set_hw_dvs_levels,
 		},
@@ -815,6 +858,7 @@
 			.vsel_mask = DVS_BUCK_RUN_MASK,
 			.enable_reg = BD718XX_REG_BUCK2_CTRL,
 			.enable_mask = BD718XX_BUCK_EN,
+			.enable_time = BD71837_BUCK2_STARTUP_TIME,
 			.owner = THIS_MODULE,
 			.of_parse_cb = buck2_set_hw_dvs_levels,
 		},
@@ -839,6 +883,7 @@
 			.vsel_mask = DVS_BUCK_RUN_MASK,
 			.enable_reg = BD71837_REG_BUCK3_CTRL,
 			.enable_mask = BD718XX_BUCK_EN,
+			.enable_time = BD71837_BUCK3_STARTUP_TIME,
 			.owner = THIS_MODULE,
 			.of_parse_cb = buck3_set_hw_dvs_levels,
 		},
@@ -863,6 +908,7 @@
 			.vsel_mask = DVS_BUCK_RUN_MASK,
 			.enable_reg = BD71837_REG_BUCK4_CTRL,
 			.enable_mask = BD718XX_BUCK_EN,
+			.enable_time = BD71837_BUCK4_STARTUP_TIME,
 			.owner = THIS_MODULE,
 			.of_parse_cb = buck4_set_hw_dvs_levels,
 		},
@@ -891,6 +937,7 @@
 			.linear_range_selectors = bd71837_buck5_volt_range_sel,
 			.enable_reg = BD718XX_REG_1ST_NODVS_BUCK_CTRL,
 			.enable_mask = BD718XX_BUCK_EN,
+			.enable_time = BD71837_BUCK5_STARTUP_TIME,
 			.owner = THIS_MODULE,
 		},
 		.init = {
@@ -915,6 +962,7 @@
 			.vsel_mask = BD71837_BUCK6_MASK,
 			.enable_reg = BD718XX_REG_2ND_NODVS_BUCK_CTRL,
 			.enable_mask = BD718XX_BUCK_EN,
+			.enable_time = BD71837_BUCK6_STARTUP_TIME,
 			.owner = THIS_MODULE,
 		},
 		.init = {
@@ -937,6 +985,7 @@
 			.vsel_mask = BD718XX_3RD_NODVS_BUCK_MASK,
 			.enable_reg = BD718XX_REG_3RD_NODVS_BUCK_CTRL,
 			.enable_mask = BD718XX_BUCK_EN,
+			.enable_time = BD71837_BUCK7_STARTUP_TIME,
 			.owner = THIS_MODULE,
 		},
 		.init = {
@@ -961,6 +1010,7 @@
 			.vsel_mask = BD718XX_4TH_NODVS_BUCK_MASK,
 			.enable_reg = BD718XX_REG_4TH_NODVS_BUCK_CTRL,
 			.enable_mask = BD718XX_BUCK_EN,
+			.enable_time = BD71837_BUCK8_STARTUP_TIME,
 			.owner = THIS_MODULE,
 		},
 		.init = {
@@ -987,6 +1037,7 @@
 			.linear_range_selectors = bd718xx_ldo1_volt_range_sel,
 			.enable_reg = BD718XX_REG_LDO1_VOLT,
 			.enable_mask = BD718XX_LDO_EN,
+			.enable_time = BD71837_LDO1_STARTUP_TIME,
 			.owner = THIS_MODULE,
 		},
 		.init = {
@@ -1009,6 +1060,7 @@
 			.n_voltages = ARRAY_SIZE(ldo_2_volts),
 			.enable_reg = BD718XX_REG_LDO2_VOLT,
 			.enable_mask = BD718XX_LDO_EN,
+			.enable_time = BD71837_LDO2_STARTUP_TIME,
 			.owner = THIS_MODULE,
 		},
 		.init = {
@@ -1032,6 +1084,7 @@
 			.vsel_mask = BD718XX_LDO3_MASK,
 			.enable_reg = BD718XX_REG_LDO3_VOLT,
 			.enable_mask = BD718XX_LDO_EN,
+			.enable_time = BD71837_LDO3_STARTUP_TIME,
 			.owner = THIS_MODULE,
 		},
 		.init = {
@@ -1055,6 +1108,7 @@
 			.vsel_mask = BD718XX_LDO4_MASK,
 			.enable_reg = BD718XX_REG_LDO4_VOLT,
 			.enable_mask = BD718XX_LDO_EN,
+			.enable_time = BD71837_LDO4_STARTUP_TIME,
 			.owner = THIS_MODULE,
 		},
 		.init = {
@@ -1080,6 +1134,7 @@
 			.vsel_mask = BD71837_LDO5_MASK,
 			.enable_reg = BD718XX_REG_LDO5_VOLT,
 			.enable_mask = BD718XX_LDO_EN,
+			.enable_time = BD71837_LDO5_STARTUP_TIME,
 			.owner = THIS_MODULE,
 		},
 		.init = {
@@ -1107,6 +1162,7 @@
 			.vsel_mask = BD718XX_LDO6_MASK,
 			.enable_reg = BD718XX_REG_LDO6_VOLT,
 			.enable_mask = BD718XX_LDO_EN,
+			.enable_time = BD71837_LDO6_STARTUP_TIME,
 			.owner = THIS_MODULE,
 		},
 		.init = {
@@ -1132,6 +1188,7 @@
 			.vsel_mask = BD71837_LDO7_MASK,
 			.enable_reg = BD71837_REG_LDO7_VOLT,
 			.enable_mask = BD718XX_LDO_EN,
+			.enable_time = BD71837_LDO7_STARTUP_TIME,
 			.owner = THIS_MODULE,
 		},
 		.init = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/bd9571mwv-regulator.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/bd9571mwv-regulator.c
@@ -124,7 +124,7 @@
 
 static const struct regulator_desc regulators[] = {
 	BD9571MWV_REG("VD09", "vd09", VD09, avs_ops, 0, 0x7f,
-		      0x80, 600000, 10000, 0x3c),
+		      0x6f, 600000, 10000, 0x3c),
 	BD9571MWV_REG("VD18", "vd18", VD18, vid_ops, BD9571MWV_VD18_VID, 0xf,
 		      16, 1625000, 25000, 0),
 	BD9571MWV_REG("VD25", "vd25", VD25, vid_ops, BD9571MWV_VD25_VID, 0xf,
@@ -133,7 +133,7 @@
 		      11, 2800000, 100000, 0),
 	BD9571MWV_REG("DVFS", "dvfs", DVFS, reg_ops,
 		      BD9571MWV_DVFS_MONIVDAC, 0x7f,
-		      0x80, 600000, 10000, 0x3c),
+		      0x6f, 600000, 10000, 0x3c),
 };
 
 #ifdef CONFIG_PM_SLEEP
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/core.c
@@ -217,6 +217,78 @@
 }
 EXPORT_SYMBOL_GPL(regulator_unlock);
 
+/**
+ * regulator_lock_two - lock two regulators
+ * @rdev1:		first regulator
+ * @rdev2:		second regulator
+ * @ww_ctx:		w/w mutex acquire context
+ *
+ * Locks both rdevs using the regulator_ww_class.
+ */
+static void regulator_lock_two(struct regulator_dev *rdev1,
+			       struct regulator_dev *rdev2,
+			       struct ww_acquire_ctx *ww_ctx)
+{
+	struct regulator_dev *tmp;
+	int ret;
+
+	ww_acquire_init(ww_ctx, &regulator_ww_class);
+
+	/* Try to just grab both of them */
+	ret = regulator_lock_nested(rdev1, ww_ctx);
+	WARN_ON(ret);
+	ret = regulator_lock_nested(rdev2, ww_ctx);
+	if (ret != -EDEADLOCK) {
+		WARN_ON(ret);
+		goto exit;
+	}
+
+	while (true) {
+		/*
+		 * Start of loop: rdev1 was locked and rdev2 was contended.
+		 * Need to unlock rdev1, slowly lock rdev2, then try rdev1
+		 * again.
+		 */
+		regulator_unlock(rdev1);
+
+		ww_mutex_lock_slow(&rdev2->mutex, ww_ctx);
+		rdev2->ref_cnt++;
+		rdev2->mutex_owner = current;
+		ret = regulator_lock_nested(rdev1, ww_ctx);
+
+		if (ret == -EDEADLOCK) {
+			/* More contention; swap which needs to be slow */
+			tmp = rdev1;
+			rdev1 = rdev2;
+			rdev2 = tmp;
+		} else {
+			WARN_ON(ret);
+			break;
+		}
+	}
+
+exit:
+	ww_acquire_done(ww_ctx);
+}
+
+/**
+ * regulator_unlock_two - unlock two regulators
+ * @rdev1:		first regulator
+ * @rdev2:		second regulator
+ * @ww_ctx:		w/w mutex acquire context
+ *
+ * The inverse of regulator_lock_two().
+ */
+
+static void regulator_unlock_two(struct regulator_dev *rdev1,
+				 struct regulator_dev *rdev2,
+				 struct ww_acquire_ctx *ww_ctx)
+{
+	regulator_unlock(rdev2);
+	regulator_unlock(rdev1);
+	ww_acquire_fini(ww_ctx);
+}
+
 static bool regulator_supply_is_couple(struct regulator_dev *rdev)
 {
 	struct regulator_dev *c_rdev;
@@ -235,8 +307,8 @@
 static void regulator_unlock_recursive(struct regulator_dev *rdev,
 				       unsigned int n_coupled)
 {
-	struct regulator_dev *c_rdev;
-	int i;
+	struct regulator_dev *c_rdev, *supply_rdev;
+	int i, supply_n_coupled;
 
 	for (i = n_coupled; i > 0; i--) {
 		c_rdev = rdev->coupling_desc.coupled_rdevs[i - 1];
@@ -244,10 +316,13 @@
 		if (!c_rdev)
 			continue;
 
-		if (c_rdev->supply && !regulator_supply_is_couple(c_rdev))
-			regulator_unlock_recursive(
-					c_rdev->supply->rdev,
-					c_rdev->coupling_desc.n_coupled);
+		if (c_rdev->supply && !regulator_supply_is_couple(c_rdev)) {
+			supply_rdev = c_rdev->supply->rdev;
+			supply_n_coupled = supply_rdev->coupling_desc.n_coupled;
+
+			regulator_unlock_recursive(supply_rdev,
+						   supply_n_coupled);
+		}
 
 		regulator_unlock(c_rdev);
 	}
@@ -341,6 +416,7 @@
 			ww_mutex_lock_slow(&new_contended_rdev->mutex, ww_ctx);
 			old_contended_rdev = new_contended_rdev;
 			old_contended_rdev->ref_cnt++;
+			old_contended_rdev->mutex_owner = current;
 		}
 
 		err = regulator_lock_recursive(rdev,
@@ -953,7 +1029,7 @@
 		/* get input voltage */
 		input_uV = 0;
 		if (rdev->supply)
-			input_uV = regulator_get_voltage(rdev->supply);
+			input_uV = regulator_get_voltage_rdev(rdev->supply->rdev);
 		if (input_uV <= 0)
 			input_uV = rdev->constraints->input_uV;
 		if (input_uV <= 0) {
@@ -1272,7 +1348,6 @@
 /**
  * set_machine_constraints - sets regulator constraints
  * @rdev: regulator source
- * @constraints: constraints to apply
  *
  * Allows platform initialisation code to define and constrain
  * regulator circuits e.g. valid voltage/current ranges, etc.  NOTE:
@@ -1280,21 +1355,11 @@
  * regulator operations to proceed i.e. set_voltage, set_current_limit,
  * set_mode.
  */
-static int set_machine_constraints(struct regulator_dev *rdev,
-	const struct regulation_constraints *constraints)
+static int set_machine_constraints(struct regulator_dev *rdev)
 {
 	int ret = 0;
 	const struct regulator_ops *ops = rdev->desc->ops;
 
-	if (constraints)
-		rdev->constraints = kmemdup(constraints, sizeof(*constraints),
-					    GFP_KERNEL);
-	else
-		rdev->constraints = kzalloc(sizeof(*constraints),
-					    GFP_KERNEL);
-	if (!rdev->constraints)
-		return -ENOMEM;
-
 	ret = machine_constraints_voltage(rdev, rdev->constraints);
 	if (ret != 0)
 		return ret;
@@ -1389,7 +1454,19 @@
 	 * and we have control then make sure it is enabled.
 	 */
 	if (rdev->constraints->always_on || rdev->constraints->boot_on) {
-		if (rdev->supply) {
+		/* If we want to enable this regulator, make sure that we know
+		 * the supplying regulator.
+		 */
+		if (rdev->supply_name && !rdev->supply)
+			return -EPROBE_DEFER;
+
+		/* If supplying regulator has already been enabled,
+		 * it's not intended to have use_count increment
+		 * when rdev is only boot-on.
+		 */
+		if (rdev->supply &&
+		    (rdev->constraints->always_on ||
+		     !regulator_is_enabled(rdev->supply))) {
 			ret = regulator_enable(rdev->supply);
 			if (ret < 0) {
 				_regulator_put(rdev->supply);
@@ -1403,7 +1480,9 @@
 			rdev_err(rdev, "failed to enable\n");
 			return ret;
 		}
-		rdev->use_count++;
+
+		if (rdev->constraints->always_on)
+			rdev->use_count++;
 	}
 
 	print_constraints(rdev);
@@ -1412,8 +1491,8 @@
 
 /**
  * set_supply - set regulator supply regulator
- * @rdev: regulator name
- * @supply_rdev: supply regulator name
+ * @rdev: regulator (locked)
+ * @supply_rdev: supply regulator (locked))
  *
  * Called by platform initialisation code to set the supply regulator for this
  * regulator. This ensures that a regulators supply will also be enabled by the
@@ -1431,6 +1510,7 @@
 
 	rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY");
 	if (rdev->supply == NULL) {
+		module_put(supply_rdev->owner);
 		err = -ENOMEM;
 		return err;
 	}
@@ -1454,7 +1534,7 @@
 				      const char *consumer_dev_name,
 				      const char *supply)
 {
-	struct regulator_map *node;
+	struct regulator_map *node, *new_node;
 	int has_dev;
 
 	if (supply == NULL)
@@ -1465,6 +1545,22 @@
 	else
 		has_dev = 0;
 
+	new_node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL);
+	if (new_node == NULL)
+		return -ENOMEM;
+
+	new_node->regulator = rdev;
+	new_node->supply = supply;
+
+	if (has_dev) {
+		new_node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL);
+		if (new_node->dev_name == NULL) {
+			kfree(new_node);
+			return -ENOMEM;
+		}
+	}
+
+	mutex_lock(&regulator_list_mutex);
 	list_for_each_entry(node, &regulator_map_list, list) {
 		if (node->dev_name && consumer_dev_name) {
 			if (strcmp(node->dev_name, consumer_dev_name) != 0)
@@ -1482,26 +1578,19 @@
 			 node->regulator->desc->name,
 			 supply,
 			 dev_name(&rdev->dev), rdev_get_name(rdev));
-		return -EBUSY;
+		goto fail;
 	}
 
-	node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL);
-	if (node == NULL)
-		return -ENOMEM;
-
-	node->regulator = rdev;
-	node->supply = supply;
-
-	if (has_dev) {
-		node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL);
-		if (node->dev_name == NULL) {
-			kfree(node);
-			return -ENOMEM;
-		}
-	}
+	list_add(&new_node->list, &regulator_map_list);
+	mutex_unlock(&regulator_list_mutex);
 
-	list_add(&node->list, &regulator_map_list);
 	return 0;
+
+fail:
+	mutex_unlock(&regulator_list_mutex);
+	kfree(new_node->dev_name);
+	kfree(new_node);
+	return -EBUSY;
 }
 
 static void unset_regulator_supplies(struct regulator_dev *rdev)
@@ -1573,57 +1662,69 @@
 					  const char *supply_name)
 {
 	struct regulator *regulator;
-	char buf[REG_STR_SIZE];
-	int err, size;
+	int err = 0;
+
+	lockdep_assert_held_once(&rdev->mutex.base);
+
+	if (dev) {
+		char buf[REG_STR_SIZE];
+		int size;
+
+		size = snprintf(buf, REG_STR_SIZE, "%s-%s",
+				dev->kobj.name, supply_name);
+		if (size >= REG_STR_SIZE)
+			return NULL;
+
+		supply_name = kstrdup(buf, GFP_KERNEL);
+		if (supply_name == NULL)
+			return NULL;
+	} else {
+		supply_name = kstrdup_const(supply_name, GFP_KERNEL);
+		if (supply_name == NULL)
+			return NULL;
+	}
 
 	regulator = kzalloc(sizeof(*regulator), GFP_KERNEL);
-	if (regulator == NULL)
+	if (regulator == NULL) {
+		kfree_const(supply_name);
 		return NULL;
+	}
 
-	regulator_lock(rdev);
 	regulator->rdev = rdev;
+	regulator->supply_name = supply_name;
+
 	list_add(&regulator->list, &rdev->consumer_list);
 
 	if (dev) {
 		regulator->dev = dev;
 
 		/* Add a link to the device sysfs entry */
-		size = snprintf(buf, REG_STR_SIZE, "%s-%s",
-				dev->kobj.name, supply_name);
-		if (size >= REG_STR_SIZE)
-			goto overflow_err;
-
-		regulator->supply_name = kstrdup(buf, GFP_KERNEL);
-		if (regulator->supply_name == NULL)
-			goto overflow_err;
-
 		err = sysfs_create_link_nowarn(&rdev->dev.kobj, &dev->kobj,
-					buf);
+					       supply_name);
 		if (err) {
 			rdev_dbg(rdev, "could not add device link %s err %d\n",
 				  dev->kobj.name, err);
 			/* non-fatal */
 		}
-	} else {
-		regulator->supply_name = kstrdup_const(supply_name, GFP_KERNEL);
-		if (regulator->supply_name == NULL)
-			goto overflow_err;
 	}
 
-	regulator->debugfs = debugfs_create_dir(regulator->supply_name,
-						rdev->debugfs);
-	if (!regulator->debugfs) {
-		rdev_dbg(rdev, "Failed to create debugfs directory\n");
-	} else {
+	if (err != -EEXIST) {
+		regulator->debugfs = debugfs_create_dir(supply_name, rdev->debugfs);
+		if (IS_ERR(regulator->debugfs)) {
+			rdev_dbg(rdev, "Failed to create debugfs directory\n");
+			regulator->debugfs = NULL;
+		}
+	}
+
+	if (regulator->debugfs) {
 		debugfs_create_u32("uA_load", 0444, regulator->debugfs,
 				   &regulator->uA_load);
 		debugfs_create_u32("min_uV", 0444, regulator->debugfs,
 				   &regulator->voltage[PM_SUSPEND_ON].min_uV);
 		debugfs_create_u32("max_uV", 0444, regulator->debugfs,
 				   &regulator->voltage[PM_SUSPEND_ON].max_uV);
-		debugfs_create_file("constraint_flags", 0444,
-				    regulator->debugfs, regulator,
-				    &constraint_flags_fops);
+		debugfs_create_file("constraint_flags", 0444, regulator->debugfs,
+				    regulator, &constraint_flags_fops);
 	}
 
 	/*
@@ -1635,13 +1736,7 @@
 	    _regulator_is_enabled(rdev))
 		regulator->always_on = true;
 
-	regulator_unlock(rdev);
 	return regulator;
-overflow_err:
-	list_del(&regulator->list);
-	kfree(regulator);
-	regulator_unlock(rdev);
-	return NULL;
 }
 
 static int _regulator_get_enable_time(struct regulator_dev *rdev)
@@ -1722,6 +1817,7 @@
 		node = of_get_regulator(dev, supply);
 		if (node) {
 			r = of_find_regulator_by_node(node);
+			of_node_put(node);
 			if (r)
 				return r;
 
@@ -1766,13 +1862,14 @@
 {
 	struct regulator_dev *r;
 	struct device *dev = rdev->dev.parent;
-	int ret;
+	struct ww_acquire_ctx ww_ctx;
+	int ret = 0;
 
 	/* No supply to resolve? */
 	if (!rdev->supply_name)
 		return 0;
 
-	/* Supply already resolved? */
+	/* Supply already resolved? (fast-path without locking contention) */
 	if (rdev->supply)
 		return 0;
 
@@ -1782,7 +1879,7 @@
 
 		/* Did the lookup explicitly defer for us? */
 		if (ret == -EPROBE_DEFER)
-			return ret;
+			goto out;
 
 		if (have_full_constraints()) {
 			r = dummy_regulator_rdev;
@@ -1790,8 +1887,20 @@
 		} else {
 			dev_err(dev, "Failed to resolve %s-supply for %s\n",
 				rdev->supply_name, rdev->desc->name);
-			return -EPROBE_DEFER;
+			ret = -EPROBE_DEFER;
+			goto out;
+		}
+	}
+
+	if (r == rdev) {
+		dev_err(dev, "Supply for %s (%s) resolved to itself\n",
+			rdev->desc->name, rdev->supply_name);
+		if (!have_full_constraints()) {
+			ret = -EINVAL;
+			goto out;
 		}
+		r = dummy_regulator_rdev;
+		get_device(&r->dev);
 	}
 
 	/*
@@ -1803,7 +1912,8 @@
 	if (r->dev.parent && r->dev.parent != rdev->dev.parent) {
 		if (!device_is_bound(r->dev.parent)) {
 			put_device(&r->dev);
-			return -EPROBE_DEFER;
+			ret = -EPROBE_DEFER;
+			goto out;
 		}
 	}
 
@@ -1811,15 +1921,32 @@
 	ret = regulator_resolve_supply(r);
 	if (ret < 0) {
 		put_device(&r->dev);
-		return ret;
+		goto out;
+	}
+
+	/*
+	 * Recheck rdev->supply with rdev->mutex lock held to avoid a race
+	 * between rdev->supply null check and setting rdev->supply in
+	 * set_supply() from concurrent tasks.
+	 */
+	regulator_lock_two(rdev, r, &ww_ctx);
+
+	/* Supply just resolved by a concurrent task? */
+	if (rdev->supply) {
+		regulator_unlock_two(rdev, r, &ww_ctx);
+		put_device(&r->dev);
+		goto out;
 	}
 
 	ret = set_supply(rdev, r);
 	if (ret < 0) {
+		regulator_unlock_two(rdev, r, &ww_ctx);
 		put_device(&r->dev);
-		return ret;
+		goto out;
 	}
 
+	regulator_unlock_two(rdev, r, &ww_ctx);
+
 	/*
 	 * In set_machine_constraints() we may have turned this regulator on
 	 * but we couldn't propagate to the supply if it hadn't been resolved
@@ -1830,11 +1957,12 @@
 		if (ret < 0) {
 			_regulator_put(rdev->supply);
 			rdev->supply = NULL;
-			return ret;
+			goto out;
 		}
 	}
 
-	return 0;
+out:
+	return ret;
 }
 
 /* Internal regulator request function */
@@ -1932,11 +2060,13 @@
 		return regulator;
 	}
 
+	regulator_lock(rdev);
 	regulator = create_regulator(rdev, dev, id);
+	regulator_unlock(rdev);
 	if (regulator == NULL) {
 		regulator = ERR_PTR(-ENOMEM);
-		put_device(&rdev->dev);
 		module_put(rdev->owner);
+		put_device(&rdev->dev);
 		return regulator;
 	}
 
@@ -1945,10 +2075,13 @@
 		rdev->exclusive = 1;
 
 		ret = _regulator_is_enabled(rdev);
-		if (ret > 0)
+		if (ret > 0) {
 			rdev->use_count = 1;
-		else
+			regulator->enable_count = 1;
+		} else {
 			rdev->use_count = 0;
+			regulator->enable_count = 0;
+		}
 	}
 
 	device_link_add(dev, &rdev->dev, DL_FLAG_STATELESS);
@@ -2057,13 +2190,13 @@
 
 	rdev->open_count--;
 	rdev->exclusive = 0;
-	put_device(&rdev->dev);
 	regulator_unlock(rdev);
 
 	kfree_const(regulator->supply_name);
 	kfree(regulator);
 
 	module_put(rdev->owner);
+	put_device(&rdev->dev);
 }
 
 /**
@@ -2215,10 +2348,13 @@
 static int regulator_ena_gpio_request(struct regulator_dev *rdev,
 				const struct regulator_config *config)
 {
-	struct regulator_enable_gpio *pin;
+	struct regulator_enable_gpio *pin, *new_pin;
 	struct gpio_desc *gpiod;
 
 	gpiod = config->ena_gpiod;
+	new_pin = kzalloc(sizeof(*new_pin), GFP_KERNEL);
+
+	mutex_lock(&regulator_list_mutex);
 
 	list_for_each_entry(pin, &regulator_ena_gpio_list, list) {
 		if (pin->gpiod == gpiod) {
@@ -2227,9 +2363,13 @@
 		}
 	}
 
-	pin = kzalloc(sizeof(struct regulator_enable_gpio), GFP_KERNEL);
-	if (pin == NULL)
+	if (new_pin == NULL) {
+		mutex_unlock(&regulator_list_mutex);
 		return -ENOMEM;
+	}
+
+	pin = new_pin;
+	new_pin = NULL;
 
 	pin->gpiod = gpiod;
 	list_add(&pin->list, &regulator_ena_gpio_list);
@@ -2237,6 +2377,10 @@
 update_ena_gpio_to_rdev:
 	pin->request_count++;
 	rdev->ena_pin = pin;
+
+	mutex_unlock(&regulator_list_mutex);
+	kfree(new_pin);
+
 	return 0;
 }
 
@@ -2429,13 +2573,18 @@
  */
 static int _regulator_handle_consumer_enable(struct regulator *regulator)
 {
+	int ret;
 	struct regulator_dev *rdev = regulator->rdev;
 
 	lockdep_assert_held_once(&rdev->mutex.base);
 
 	regulator->enable_count++;
-	if (regulator->uA_load && regulator->enable_count == 1)
-		return drms_uA_update(rdev);
+	if (regulator->uA_load && regulator->enable_count == 1) {
+		ret = drms_uA_update(rdev);
+		if (ret)
+			regulator->enable_count--;
+		return ret;
+	}
 
 	return 0;
 }
@@ -2514,7 +2663,8 @@
 		/* Fallthrough on positive return values - already enabled */
 	}
 
-	rdev->use_count++;
+	if (regulator->enable_count == 1)
+		rdev->use_count++;
 
 	return 0;
 
@@ -2592,37 +2742,40 @@
 
 	lockdep_assert_held_once(&rdev->mutex.base);
 
-	if (WARN(rdev->use_count <= 0,
+	if (WARN(regulator->enable_count == 0,
 		 "unbalanced disables for %s\n", rdev_get_name(rdev)))
 		return -EIO;
 
-	/* are we the last user and permitted to disable ? */
-	if (rdev->use_count == 1 &&
-	    (rdev->constraints && !rdev->constraints->always_on)) {
-
-		/* we are last user */
-		if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS)) {
-			ret = _notifier_call_chain(rdev,
-						   REGULATOR_EVENT_PRE_DISABLE,
-						   NULL);
-			if (ret & NOTIFY_STOP_MASK)
-				return -EINVAL;
-
-			ret = _regulator_do_disable(rdev);
-			if (ret < 0) {
-				rdev_err(rdev, "failed to disable\n");
-				_notifier_call_chain(rdev,
-						REGULATOR_EVENT_ABORT_DISABLE,
+	if (regulator->enable_count == 1) {
+	/* disabling last enable_count from this regulator */
+		/* are we the last user and permitted to disable ? */
+		if (rdev->use_count == 1 &&
+		    (rdev->constraints && !rdev->constraints->always_on)) {
+
+			/* we are last user */
+			if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS)) {
+				ret = _notifier_call_chain(rdev,
+							   REGULATOR_EVENT_PRE_DISABLE,
+							   NULL);
+				if (ret & NOTIFY_STOP_MASK)
+					return -EINVAL;
+
+				ret = _regulator_do_disable(rdev);
+				if (ret < 0) {
+					rdev_err(rdev, "failed to disable\n");
+					_notifier_call_chain(rdev,
+							REGULATOR_EVENT_ABORT_DISABLE,
+							NULL);
+					return ret;
+				}
+				_notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE,
 						NULL);
-				return ret;
 			}
-			_notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE,
-					NULL);
-		}
 
-		rdev->use_count = 0;
-	} else if (rdev->use_count > 1) {
-		rdev->use_count--;
+			rdev->use_count = 0;
+		} else if (rdev->use_count > 1) {
+			rdev->use_count--;
+		}
 	}
 
 	if (ret == 0)
@@ -2921,6 +3074,7 @@
 
 	return map ? map : ERR_PTR(-EOPNOTSUPP);
 }
+EXPORT_SYMBOL_GPL(regulator_get_regmap);
 
 /**
  * regulator_get_hardware_vsel_register - get the HW voltage selector register
@@ -3460,6 +3614,7 @@
 out:
 	return ret;
 }
+EXPORT_SYMBOL_GPL(regulator_set_voltage_rdev);
 
 static int regulator_limit_voltage_step(struct regulator_dev *rdev,
 					int *current_uV, int *min_uV)
@@ -4016,6 +4171,8 @@
 		ret = rdev->desc->fixed_uV;
 	} else if (rdev->supply) {
 		ret = regulator_get_voltage_rdev(rdev->supply->rdev);
+	} else if (rdev->supply_name) {
+		return -EPROBE_DEFER;
 	} else {
 		return -EINVAL;
 	}
@@ -4024,6 +4181,7 @@
 		return ret;
 	return ret - rdev->constraints->uV_offset;
 }
+EXPORT_SYMBOL_GPL(regulator_get_voltage_rdev);
 
 /**
  * regulator_get_voltage - get regulator output voltage
@@ -4736,6 +4894,7 @@
 {
 	struct regulator_dev *rdev = dev_get_drvdata(dev);
 
+	debugfs_remove_recursive(rdev->debugfs);
 	kfree(rdev->constraints);
 	of_node_put(rdev->dev.of_node);
 	kfree(rdev);
@@ -4755,10 +4914,8 @@
 	}
 
 	rdev->debugfs = debugfs_create_dir(rname, debugfs_root);
-	if (!rdev->debugfs) {
-		rdev_warn(rdev, "Failed to create debugfs directory\n");
-		return;
-	}
+	if (IS_ERR(rdev->debugfs))
+		rdev_dbg(rdev, "Failed to create debugfs directory\n");
 
 	debugfs_create_u32("use_count", 0444, rdev->debugfs,
 			   &rdev->use_count);
@@ -4853,13 +5010,9 @@
 			return;
 		}
 
-		regulator_lock(c_rdev);
-
 		c_desc->coupled_rdevs[i] = c_rdev;
 		c_desc->n_resolved++;
 
-		regulator_unlock(c_rdev);
-
 		regulator_resolve_coupling(c_rdev);
 	}
 }
@@ -4944,7 +5097,10 @@
 	if (!of_check_coupling_data(rdev))
 		return -EPERM;
 
+	mutex_lock(&regulator_list_mutex);
 	rdev->coupling_desc.coupler = regulator_find_coupler(rdev);
+	mutex_unlock(&regulator_list_mutex);
+
 	if (IS_ERR(rdev->coupling_desc.coupler)) {
 		err = PTR_ERR(rdev->coupling_desc.coupler);
 		rdev_err(rdev, "failed to get coupler: %d\n", err);
@@ -4983,7 +5139,6 @@
 regulator_register(const struct regulator_desc *regulator_desc,
 		   const struct regulator_config *cfg)
 {
-	const struct regulation_constraints *constraints = NULL;
 	const struct regulator_init_data *init_data;
 	struct regulator_config *config = NULL;
 	static atomic_t regulator_no = ATOMIC_INIT(-1);
@@ -5039,6 +5194,7 @@
 		ret = -ENOMEM;
 		goto rinse;
 	}
+	device_initialize(&rdev->dev);
 
 	/*
 	 * Duplicate the config so the driver could override it after
@@ -5046,9 +5202,8 @@
 	 */
 	config = kmemdup(cfg, sizeof(*cfg), GFP_KERNEL);
 	if (config == NULL) {
-		kfree(rdev);
 		ret = -ENOMEM;
-		goto rinse;
+		goto clean;
 	}
 
 	init_data = regulator_of_get_init_data(dev, regulator_desc, config,
@@ -5060,10 +5215,8 @@
 	 * from a gpio extender or something else.
 	 */
 	if (PTR_ERR(init_data) == -EPROBE_DEFER) {
-		kfree(config);
-		kfree(rdev);
 		ret = -EPROBE_DEFER;
-		goto rinse;
+		goto clean;
 	}
 
 	/*
@@ -5104,9 +5257,7 @@
 	}
 
 	if (config->ena_gpiod) {
-		mutex_lock(&regulator_list_mutex);
 		ret = regulator_ena_gpio_request(rdev, config);
-		mutex_unlock(&regulator_list_mutex);
 		if (ret != 0) {
 			rdev_err(rdev, "Failed to request enable GPIO: %d\n",
 				 ret);
@@ -5122,49 +5273,59 @@
 	rdev->dev.parent = dev;
 	dev_set_name(&rdev->dev, "regulator.%lu",
 		    (unsigned long) atomic_inc_return(&regulator_no));
+	dev_set_drvdata(&rdev->dev, rdev);
 
 	/* set regulator constraints */
 	if (init_data)
-		constraints = &init_data->constraints;
+		rdev->constraints = kmemdup(&init_data->constraints,
+					    sizeof(*rdev->constraints),
+					    GFP_KERNEL);
+	else
+		rdev->constraints = kzalloc(sizeof(*rdev->constraints),
+					    GFP_KERNEL);
+	if (!rdev->constraints) {
+		ret = -ENOMEM;
+		goto wash;
+	}
 
 	if (init_data && init_data->supply_regulator)
 		rdev->supply_name = init_data->supply_regulator;
 	else if (regulator_desc->supply_name)
 		rdev->supply_name = regulator_desc->supply_name;
 
-	/*
-	 * Attempt to resolve the regulator supply, if specified,
-	 * but don't return an error if we fail because we will try
-	 * to resolve it again later as more regulators are added.
-	 */
-	if (regulator_resolve_supply(rdev))
-		rdev_dbg(rdev, "unable to resolve supply\n");
-
-	ret = set_machine_constraints(rdev, constraints);
+	ret = set_machine_constraints(rdev);
+	if (ret == -EPROBE_DEFER) {
+		/* Regulator might be in bypass mode and so needs its supply
+		 * to set the constraints */
+		/* FIXME: this currently triggers a chicken-and-egg problem
+		 * when creating -SUPPLY symlink in sysfs to a regulator
+		 * that is just being created */
+		ret = regulator_resolve_supply(rdev);
+		if (!ret)
+			ret = set_machine_constraints(rdev);
+		else
+			rdev_dbg(rdev, "unable to resolve supply early: %pe\n",
+				 ERR_PTR(ret));
+	}
 	if (ret < 0)
 		goto wash;
 
-	mutex_lock(&regulator_list_mutex);
 	ret = regulator_init_coupling(rdev);
-	mutex_unlock(&regulator_list_mutex);
 	if (ret < 0)
 		goto wash;
 
 	/* add consumers devices */
 	if (init_data) {
-		mutex_lock(&regulator_list_mutex);
 		for (i = 0; i < init_data->num_consumer_supplies; i++) {
 			ret = set_consumer_device_supply(rdev,
 				init_data->consumer_supplies[i].dev_name,
 				init_data->consumer_supplies[i].supply);
 			if (ret < 0) {
-				mutex_unlock(&regulator_list_mutex);
 				dev_err(dev, "Failed to set supply %s\n",
 					init_data->consumer_supplies[i].supply);
 				goto unset_supplies;
 			}
 		}
-		mutex_unlock(&regulator_list_mutex);
 	}
 
 	if (!rdev->desc->ops->get_voltage &&
@@ -5172,12 +5333,9 @@
 	    !rdev->desc->fixed_uV)
 		rdev->is_switch = true;
 
-	dev_set_drvdata(&rdev->dev, rdev);
-	ret = device_register(&rdev->dev);
-	if (ret != 0) {
-		put_device(&rdev->dev);
+	ret = device_add(&rdev->dev);
+	if (ret != 0)
 		goto unset_supplies;
-	}
 
 	rdev_init_debugfs(rdev);
 
@@ -5198,15 +5356,16 @@
 	regulator_remove_coupling(rdev);
 	mutex_unlock(&regulator_list_mutex);
 wash:
-	kfree(rdev->constraints);
+	regulator_put(rdev->supply);
+	kfree(rdev->coupling_desc.coupled_rdevs);
 	mutex_lock(&regulator_list_mutex);
 	regulator_ena_gpio_free(rdev);
 	mutex_unlock(&regulator_list_mutex);
 clean:
 	if (dangling_of_gpiod)
 		gpiod_put(config->ena_gpiod);
-	kfree(rdev);
 	kfree(config);
+	put_device(&rdev->dev);
 rinse:
 	if (dangling_cfg_gpiod)
 		gpiod_put(cfg->ena_gpiod);
@@ -5235,7 +5394,6 @@
 
 	mutex_lock(&regulator_list_mutex);
 
-	debugfs_remove_recursive(rdev->debugfs);
 	WARN_ON(rdev->open_count);
 	regulator_remove_coupling(rdev);
 	unset_regulator_supplies(rdev);
@@ -5579,6 +5737,7 @@
 			ww_mutex_lock_slow(&new_contended_rdev->mutex, ww_ctx);
 			old_contended_rdev = new_contended_rdev;
 			old_contended_rdev->ref_cnt++;
+			old_contended_rdev->mutex_owner = current;
 		}
 
 		err = regulator_summary_lock_all(ww_ctx,
@@ -5639,8 +5798,8 @@
 	ret = class_register(&regulator_class);
 
 	debugfs_root = debugfs_create_dir("regulator", NULL);
-	if (!debugfs_root)
-		pr_warn("regulator: Failed to create debugfs directory\n");
+	if (IS_ERR(debugfs_root))
+		pr_debug("regulator: Failed to create debugfs directory\n");
 
 #ifdef CONFIG_DEBUG_FS
 	debugfs_create_file("supply_map", 0444, debugfs_root, NULL,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/da9052-regulator.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/da9052-regulator.c
@@ -250,7 +250,8 @@
 	case DA9052_ID_BUCK3:
 	case DA9052_ID_LDO2:
 	case DA9052_ID_LDO3:
-		ret = (new_sel - old_sel) * info->step_uV / 6250;
+		ret = DIV_ROUND_UP(abs(new_sel - old_sel) * info->step_uV,
+				   6250);
 		break;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/da9121-regulator.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/da9121-regulator.c
@@ -0,0 +1,1479 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * DA9121 Single-channel dual-phase 10A buck converter
+ * DA9130 Single-channel dual-phase 10A buck converter (Automotive)
+ * DA9217 Single-channel dual-phase  6A buck converter
+ * DA9122 Dual-channel single-phase  5A buck converter
+ * DA9131 Dual-channel single-phase  5A buck converter (Automotive)
+ * DA9220 Dual-channel single-phase  3A buck converter
+ * DA9132 Dual-channel single-phase  3A buck converter (Automotive)
+ *
+ * Copyright (C) 2019  Dialog Semiconductor
+ *
+ * Author: Steve Twiss for Dialog Semiconductor
+ * Author: Adam Ward for Dialog Semiconductor
+ *
+ */
+
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/gpio/consumer.h>
+#include <linux/regulator/driver.h>
+#include <linux/regmap.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/workqueue.h>
+#include "da9121-regulator.h"
+
+/*
+ * Minimum, maximum and default polling millisecond periods are provided
+ * here as an example. It is expected that any final implementation will
+ * include a modification of these settings to match the required
+ * application.
+ */
+#define DA9121_DEFAULT_POLLING_PERIOD_MS	3000
+#define DA9121_MAX_POLLING_PERIOD_MS		10000
+#define DA9121_MIN_POLLING_PERIOD_MS		1000
+
+/* Device ID list */
+#define DA9121_DEVICE_ID	0x05
+#define DA9121_VARIANT_MRC_BASE	0x2
+#define DA9130_VARIANT_VRC	0X0
+#define DA9131_VARIANT_VRC	0X1
+#define DA9122_VARIANT_VRC	0x2
+#define DA9217_VARIANT_VRC	0x7
+
+/* Regulator types - first index into local_da9121_regulators[][] */
+enum device_variant {
+	DA9121_TYPE_DA9121_DA9130,
+	DA9121_TYPE_DA9220_DA9132,
+	DA9121_TYPE_DA9122_DA9131,
+	DA9121_TYPE_DA9217,
+	DA9121_TYPE_NUM
+};
+
+/*
+ * Regulator Names - for da9121_matches[], chip->rdev[], and second index into
+ * local_da9121_regulators[][]
+ */
+enum {
+	DA9121_INDEX_BUCK1,
+	DA9121_INDEX_BUCK2,
+	DA9121_MAX_REGULATORS
+};
+
+/*
+ * Regulator IDs - buck id in local_da9121_regulators[][], used to find buck's
+ * current/mode register info
+ */
+enum {
+	DA9121_DA9130_ID_BUCK1,
+	DA9220_DA9132_ID_BUCK1,
+	DA9220_DA9132_ID_BUCK2,
+	DA9122_DA9131_ID_BUCK1,
+	DA9122_DA9131_ID_BUCK2,
+	DA9217_ID_BUCK1
+};
+
+/* Device tree data */
+struct da9121_dt_data {
+	unsigned int num_matches;
+	struct gpio_desc *gpiod_ren[DA9121_MAX_REGULATORS];
+	struct device_node *reg_node[DA9121_MAX_REGULATORS];
+	struct regulator_init_data *init_data[DA9121_MAX_REGULATORS];
+};
+
+/* Chip data */
+struct da9121 {
+	struct device *dev;
+	struct delayed_work work;
+	struct regmap *regmap;
+	struct da9121_dt_data *dt_data;
+	struct regulator_dev *rdev[DA9121_MAX_REGULATORS];
+	unsigned int persistent[2];
+	unsigned int passive_delay;
+	int chip_irq;
+	int variant_id;
+};
+
+/*
+ * Define ranges for different variants, enabling translation to/from
+ * registers. Maximums give scope to allow for transients.
+ */
+struct da9121_range {
+	int val_min;
+	int val_max;
+	int val_stp;
+	int reg_min;
+	int reg_max;
+};
+
+struct da9121_range da9121_10A_2phase_current = {
+	.val_min =  7000000,
+	.val_max = 20000000,
+	.val_stp =  1000000,
+	.reg_min = 1,
+	.reg_max = 14,
+};
+
+struct da9121_range da9121_6A_2phase_current = {
+	.val_min =  7000000,
+	.val_max = 12000000,
+	.val_stp =  1000000,
+	.reg_min = 1,
+	.reg_max = 6,
+};
+
+struct da9121_range da9121_5A_1phase_current = {
+	.val_min =  3500000,
+	.val_max = 10000000,
+	.val_stp =   500000,
+	.reg_min = 1,
+	.reg_max = 14,
+};
+
+struct da9121_range da9121_3A_1phase_current = {
+	.val_min = 3500000,
+	.val_max = 6000000,
+	.val_stp =  500000,
+	.reg_min = 1,
+	.reg_max = 6,
+};
+
+struct da9121_variant {
+	int num_bucks;
+	int num_phases;
+	struct da9121_range *current_range;
+};
+
+static const struct da9121_variant variant_parameters[] = {
+	{ 1, 2, &da9121_10A_2phase_current },	/* DA9121_TYPE_DA9121_DA9130 */
+	{ 2, 1, &da9121_3A_1phase_current  },	/* DA9121_TYPE_DA9220_DA9132 */
+	{ 2, 1, &da9121_5A_1phase_current  },	/* DA9121_TYPE_DA9122_DA9131 */
+	{ 1, 2, &da9121_6A_2phase_current  },	/* DA9121_TYPE_DA9217 */
+};
+
+static void da9121_status_poll_on(struct work_struct *work)
+{
+	struct da9121 *chip = container_of(work, struct da9121, work.work);
+	enum { R0 = 0, R1, R2, REG_MAX_NUM };
+	int status[REG_MAX_NUM] = {0};
+	int clear[REG_MAX_NUM] = {0};
+	unsigned long delay;
+	int i;
+	int ret;
+
+	/*
+	 * If persistent-notification, status will be true
+	 * If not persistent-notification any longer, status will be false
+	 */
+	ret = regmap_bulk_read(chip->regmap, DA9121_REG_SYS_STATUS_0,
+			       (void *)status, (size_t)REG_MAX_NUM);
+	if (ret < 0) {
+		dev_err(chip->dev,
+			"Failed to read STATUS registers: %d\n", ret);
+		goto error;
+	}
+
+	/* 0 TEMP_CRIT */
+	if ((chip->persistent[R0] & DA9121_MASK_SYS_EVENT_0_E_TEMP_CRIT) &&
+	    !(status[R0] & DA9121_MASK_SYS_STATUS_0_TEMP_CRIT)) {
+		clear[R0] |= DA9121_MASK_SYS_MASK_0_M_TEMP_CRIT;
+		chip->persistent[R0] &= ~DA9121_MASK_SYS_EVENT_0_E_TEMP_CRIT;
+	}
+	/* 0 TEMP_WARN */
+	if ((chip->persistent[R0] & DA9121_MASK_SYS_EVENT_0_E_TEMP_WARN) &&
+	    !(status[R0] & DA9121_MASK_SYS_STATUS_0_TEMP_WARN)) {
+		clear[R0] |= DA9121_MASK_SYS_MASK_0_M_TEMP_WARN;
+		chip->persistent[R0] &= ~DA9121_MASK_SYS_EVENT_0_E_TEMP_WARN;
+	}
+
+	/* 1 OV1 */
+	if ((chip->persistent[R1] & DA9121_MASK_SYS_EVENT_1_E_OV1) &&
+	    !(status[R1] & DA9121_MASK_SYS_STATUS_1_OV1)) {
+		clear[R1] |= DA9121_MASK_SYS_MASK_1_M_OV1;
+		chip->persistent[R1] &= ~DA9121_MASK_SYS_EVENT_1_E_OV1;
+	}
+	/* 1 UV1 */
+	if ((chip->persistent[R1] & DA9121_MASK_SYS_EVENT_1_E_UV1) &&
+	    !(status[R1] & DA9121_MASK_SYS_STATUS_1_UV1)) {
+		clear[R1] |= DA9121_MASK_SYS_MASK_1_M_UV1;
+		chip->persistent[R1] &= ~DA9121_MASK_SYS_EVENT_1_E_UV1;
+	}
+	/* 1 OC1 */
+	if ((chip->persistent[R1] & DA9121_MASK_SYS_EVENT_1_E_OC1) &&
+	    !(status[R1] & DA9121_MASK_SYS_STATUS_1_OC1)) {
+		clear[R1] |= DA9121_MASK_SYS_MASK_1_M_OC1;
+		chip->persistent[R1] &= ~DA9121_MASK_SYS_EVENT_1_E_OC1;
+	}
+
+	if (variant_parameters[chip->variant_id].num_bucks == 2) {
+		/* 1 OV2 */
+		if ((chip->persistent[R1] & DA9xxx_MASK_SYS_EVENT_1_E_OV2) &&
+		    !(status[R1] & DA9xxx_MASK_SYS_STATUS_1_OV2)) {
+			clear[R1] |= DA9xxx_MASK_SYS_MASK_1_M_OV2;
+			chip->persistent[R1] &= ~DA9xxx_MASK_SYS_EVENT_1_E_OV2;
+		}
+		/* 1 UV2 */
+		if ((chip->persistent[R1] & DA9xxx_MASK_SYS_EVENT_1_E_UV2) &&
+		    !(status[R1] & DA9xxx_MASK_SYS_STATUS_1_UV2)) {
+			clear[R1] |= DA9xxx_MASK_SYS_MASK_1_M_UV2;
+			chip->persistent[R1] &= ~DA9xxx_MASK_SYS_EVENT_1_E_UV2;
+		}
+		/* 1 OC2 */
+		if ((chip->persistent[R1] & DA9xxx_MASK_SYS_EVENT_1_E_OC2) &&
+		    !(status[R1] & DA9xxx_MASK_SYS_STATUS_1_OC2)) {
+			clear[R1] |= DA9xxx_MASK_SYS_MASK_1_M_OC2;
+			chip->persistent[R1] &= ~DA9xxx_MASK_SYS_EVENT_1_E_OC2;
+		}
+	}
+
+	for (i = R0; i < REG_MAX_NUM - 1; i++) {
+		if (clear[i]) {
+			unsigned int reg = DA9121_REG_SYS_MASK_0 + i;
+			unsigned int mbit = clear[i];
+
+			ret = regmap_update_bits(chip->regmap, reg, mbit, 0);
+			if (ret < 0) {
+				dev_err(chip->dev,
+					"Failed to unmask 0x%02x %d\n",
+					reg, ret);
+				goto error;
+			}
+		}
+	}
+
+	if (chip->persistent[R0] | chip->persistent[R1]) {
+		delay = msecs_to_jiffies(chip->passive_delay);
+		queue_delayed_work(system_freezable_wq, &chip->work, delay);
+	}
+
+error:
+	return;
+}
+
+static bool da9121_rdev_to_buck_reg_mask(struct regulator_dev *rdev, bool mode,
+					 unsigned int *reg, unsigned int *msk)
+{
+	struct da9121 *chip = rdev_get_drvdata(rdev);
+	int id = rdev_get_id(rdev);
+
+	switch (id) {
+	case DA9121_DA9130_ID_BUCK1:
+	case DA9220_DA9132_ID_BUCK1:
+	case DA9122_DA9131_ID_BUCK1:
+	case DA9217_ID_BUCK1:
+		if (mode) {
+			*reg = DA9121_REG_BUCK_BUCK1_4;
+			*msk = DA9121_MASK_BUCK_BUCKX_4_CHX_A_MODE;
+		} else {
+			*reg = DA9121_REG_BUCK_BUCK1_2;
+			*msk = DA9121_MASK_BUCK_BUCKX_2_CHX_ILIM;
+		}
+		break;
+	case DA9220_DA9132_ID_BUCK2:
+	case DA9122_DA9131_ID_BUCK2:
+		if (mode) {
+			*reg = DA9xxx_REG_BUCK_BUCK2_4;
+			*msk = DA9121_MASK_BUCK_BUCKX_4_CHX_A_MODE;
+		} else {
+			*reg = DA9xxx_REG_BUCK_BUCK2_2;
+			*msk = DA9121_MASK_BUCK_BUCKX_2_CHX_ILIM;
+		}
+		break;
+	default:
+		dev_err(chip->dev, "Invalid regulator ID\n");
+		return false;
+	}
+	return true;
+}
+
+static int da9121_get_current_limit(struct regulator_dev *rdev)
+{
+	struct da9121 *chip = rdev_get_drvdata(rdev);
+	struct da9121_range *current_range = variant_parameters[chip->variant_id].current_range;
+	unsigned int reg = 0;
+	unsigned int msk = 0;
+	unsigned int val = 0;
+	int ret = 0;
+
+	if (!da9121_rdev_to_buck_reg_mask(rdev, false, &reg, &msk))
+		return -EINVAL;
+
+	ret = regmap_read(chip->regmap, reg, &val);
+	if (ret < 0) {
+		dev_err(chip->dev, "Cannot read BUCK register: %d\n", ret);
+		goto error;
+	}
+
+	if (val < current_range->reg_min) {
+		ret = -EACCES;
+		goto error;
+	}
+
+	if (val > current_range->reg_max) {
+		ret = -EINVAL;
+		goto error;
+	}
+
+	return current_range->val_min + (current_range->val_stp * (val - current_range->reg_min));
+error:
+	return ret;
+}
+
+static int da9121_ceiling_selector(struct regulator_dev *rdev,
+				   int min, int max, unsigned int *selector)
+{
+	struct da9121 *chip = rdev_get_drvdata(rdev);
+	struct da9121_range *current_range = variant_parameters[chip->variant_id].current_range;
+	unsigned int level;
+	unsigned int i = 0;
+	unsigned int sel = 0;
+	int ret = 0;
+
+	if (current_range->val_min > max || current_range->val_max < min) {
+		dev_err(chip->dev,
+			"Requested current out of regulator capability\n");
+		ret = -EINVAL;
+		goto error;
+	}
+
+	level = current_range->val_max;
+	for (i = current_range->reg_max; i >= current_range->reg_min; i--) {
+		if (level <= max) {
+			sel = i;
+			break;
+		}
+		level -= current_range->val_stp;
+	}
+
+	if (level < min) {
+		dev_err(chip->dev,
+			"Best match falls below minimum requested current\n");
+		ret = -EINVAL;
+		goto error;
+	}
+
+	*selector = sel;
+error:
+	return ret;
+}
+
+static int da9121_set_current_limit(struct regulator_dev *rdev,
+				    int min_ua, int max_ua)
+{
+	struct da9121 *chip = rdev_get_drvdata(rdev);
+	struct da9121_range *current_range = variant_parameters[chip->variant_id].current_range;
+	unsigned int sel = 0;
+	unsigned int reg = 0;
+	unsigned int msk = 0;
+	int ret = 0;
+
+	if (min_ua < current_range->val_min ||
+	    max_ua > current_range->val_max) {
+		ret = -EINVAL;
+		goto error;
+	}
+
+	ret = da9121_ceiling_selector(rdev, min_ua, max_ua, &sel);
+	if (ret < 0)
+		goto error;
+
+	if (!da9121_rdev_to_buck_reg_mask(rdev, false, &reg, &msk))
+		return -EINVAL;
+
+	ret = regmap_update_bits(chip->regmap, reg, msk, (unsigned int)sel);
+	if (ret < 0)
+		dev_err(chip->dev, "Cannot update BUCK register %02x, err: %d\n", reg, ret);
+
+error:
+	return ret;
+}
+
+static unsigned int da9121_map_mode(unsigned int mode)
+{
+	switch (mode) {
+	case DA9121_BUCK_MODE_FORCE_PWM:
+		return REGULATOR_MODE_FAST;
+	case DA9121_BUCK_MODE_FORCE_PWM_SHEDDING:
+		return REGULATOR_MODE_NORMAL;
+	case DA9121_BUCK_MODE_AUTO:
+		return REGULATOR_MODE_IDLE;
+	case DA9121_BUCK_MODE_FORCE_PFM:
+		return REGULATOR_MODE_STANDBY;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int da9121_buck_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+	struct da9121 *chip = rdev_get_drvdata(rdev);
+	unsigned int val;
+	unsigned int reg;
+	unsigned int msk;
+
+	switch (mode) {
+	case REGULATOR_MODE_FAST:
+		val = DA9121_BUCK_MODE_FORCE_PWM;
+		break;
+	case REGULATOR_MODE_NORMAL:
+		val = DA9121_BUCK_MODE_FORCE_PWM_SHEDDING;
+		break;
+	case REGULATOR_MODE_IDLE:
+		val = DA9121_BUCK_MODE_AUTO;
+		break;
+	case REGULATOR_MODE_STANDBY:
+		val = DA9121_BUCK_MODE_FORCE_PFM;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (!da9121_rdev_to_buck_reg_mask(rdev, true, &reg, &msk))
+		return -EINVAL;
+
+	return regmap_update_bits(chip->regmap, reg, msk, val);
+}
+
+static unsigned int da9121_buck_get_mode(struct regulator_dev *rdev)
+{
+	struct da9121 *chip = rdev_get_drvdata(rdev);
+	unsigned int reg;
+	unsigned int msk;
+	unsigned int val;
+	int ret = 0;
+
+	if (!da9121_rdev_to_buck_reg_mask(rdev, true, &reg, &msk))
+		return -EINVAL;
+
+	ret = regmap_read(chip->regmap, reg, &val);
+	if (ret < 0) {
+		dev_err(chip->dev, "Cannot read BUCK register: %d\n", ret);
+		return -EINVAL;
+	}
+
+	return da9121_map_mode(val & msk);
+}
+
+static const struct regulator_ops da9121_buck_ops = {
+	.enable            = regulator_enable_regmap,
+	.disable           = regulator_disable_regmap,
+	.is_enabled        = regulator_is_enabled_regmap,
+	.set_voltage_sel   = regulator_set_voltage_sel_regmap,
+	.get_voltage_sel   = regulator_get_voltage_sel_regmap,
+	.list_voltage      = regulator_list_voltage_linear,
+	.get_current_limit = da9121_get_current_limit,
+	.set_current_limit = da9121_set_current_limit,
+	.set_mode          = da9121_buck_set_mode,
+	.get_mode          = da9121_buck_get_mode,
+};
+
+static struct of_regulator_match da9121_matches[] = {
+	[DA9121_INDEX_BUCK1] = { .name = "buck1" },
+	[DA9121_INDEX_BUCK2] = { .name = "buck2" },
+};
+
+/* DA9121 regulator model */
+static struct regulator_desc local_da9121_regulators[DA9121_TYPE_NUM][DA9121_MAX_REGULATORS] = {
+	[DA9121_TYPE_DA9121_DA9130] = {
+		[DA9121_INDEX_BUCK1] = {
+			.id = DA9121_DA9130_ID_BUCK1,
+			.name = "DA9121/DA9130 BUCK1",
+			.of_match = of_match_ptr((const char *)
+				     &da9121_matches[DA9121_INDEX_BUCK1].name),
+			.of_map_mode = da9121_map_mode,
+			.regulators_node = of_match_ptr("regulators"),
+			.ops = &da9121_buck_ops,
+			.type = REGULATOR_VOLTAGE,
+			.enable_reg = DA9121_REG_BUCK_BUCK1_0,
+			.enable_mask = DA9121_MASK_BUCK_BUCKX_0_CHX_EN,
+			.vsel_reg = DA9121_REG_BUCK_BUCK1_5,
+			.vsel_mask = DA9121_MASK_BUCK_BUCKX_5_CHX_A_VOUT,
+			.linear_min_sel = 30,
+			.n_voltages = 191,
+			.min_uV = 300000,
+			.uV_step = 10000,
+			.owner = THIS_MODULE,
+		}
+	},
+	[DA9121_TYPE_DA9220_DA9132] = {
+		[DA9121_INDEX_BUCK1] = {
+			.id = DA9220_DA9132_ID_BUCK1,
+			.name = "DA9220/DA9132 BUCK1",
+			.of_match = of_match_ptr((const char *)
+				     &da9121_matches[DA9121_INDEX_BUCK1].name),
+			.of_map_mode = da9121_map_mode,
+			.regulators_node = of_match_ptr("regulators"),
+			.ops = &da9121_buck_ops,
+			.type = REGULATOR_VOLTAGE,
+			.enable_reg = DA9121_REG_BUCK_BUCK1_0,
+			.enable_mask = DA9121_MASK_BUCK_BUCKX_0_CHX_EN,
+			.vsel_reg = DA9121_REG_BUCK_BUCK1_5,
+			.vsel_mask = DA9121_MASK_BUCK_BUCKX_5_CHX_A_VOUT,
+			.linear_min_sel = 30,
+			.n_voltages = 191,
+			.min_uV = 300000,
+			.uV_step = 10000,
+			.owner = THIS_MODULE,
+		},
+		[DA9121_INDEX_BUCK2] = {
+			.id = DA9220_DA9132_ID_BUCK2,
+			.name = "DA9220/DA9132 BUCK2",
+			.of_match = of_match_ptr((const char *)
+				     &da9121_matches[DA9121_INDEX_BUCK2].name),
+			.of_map_mode = da9121_map_mode,
+			.regulators_node = of_match_ptr("regulators"),
+			.ops = &da9121_buck_ops,
+			.type = REGULATOR_VOLTAGE,
+			.enable_reg = DA9xxx_REG_BUCK_BUCK2_0,
+			.enable_mask = DA9121_MASK_BUCK_BUCKX_0_CHX_EN,
+			.vsel_reg = DA9xxx_REG_BUCK_BUCK2_5,
+			.vsel_mask = DA9121_MASK_BUCK_BUCKX_5_CHX_A_VOUT,
+			.linear_min_sel = 30,
+			.n_voltages = 191,
+			.min_uV = 300000,
+			.uV_step = 10000,
+			.owner = THIS_MODULE,
+		}
+	},
+	[DA9121_TYPE_DA9122_DA9131] = {
+		[DA9121_INDEX_BUCK1] = {
+			.id = DA9122_DA9131_ID_BUCK1,
+			.name = "DA9122/DA9131 BUCK1",
+			.of_match = of_match_ptr((const char *)
+				     &da9121_matches[DA9121_INDEX_BUCK1].name),
+			.of_map_mode = da9121_map_mode,
+			.regulators_node = of_match_ptr("regulators"),
+			.ops = &da9121_buck_ops,
+			.type = REGULATOR_VOLTAGE,
+			.enable_reg = DA9121_REG_BUCK_BUCK1_0,
+			.enable_mask = DA9121_MASK_BUCK_BUCKX_0_CHX_EN,
+			.vsel_reg = DA9121_REG_BUCK_BUCK1_5,
+			.vsel_mask = DA9121_MASK_BUCK_BUCKX_5_CHX_A_VOUT,
+			.linear_min_sel = 30,
+			.n_voltages = 191,
+			.min_uV = 300000,
+			.uV_step = 10000,
+			.owner = THIS_MODULE,
+		},
+		[DA9121_INDEX_BUCK2] = {
+			.id = DA9122_DA9131_ID_BUCK2,
+			.name = "DA9122/DA9131 BUCK2",
+			.of_match = of_match_ptr((const char *)
+				     &da9121_matches[DA9121_INDEX_BUCK2].name),
+			.of_map_mode = da9121_map_mode,
+			.regulators_node = of_match_ptr("regulators"),
+			.ops = &da9121_buck_ops,
+			.type = REGULATOR_VOLTAGE,
+			.enable_reg = DA9xxx_REG_BUCK_BUCK2_0,
+			.enable_mask = DA9121_MASK_BUCK_BUCKX_0_CHX_EN,
+			.vsel_reg = DA9xxx_REG_BUCK_BUCK2_5,
+			.vsel_mask = DA9121_MASK_BUCK_BUCKX_5_CHX_A_VOUT,
+			.linear_min_sel = 30,
+			.n_voltages = 191,
+			.min_uV = 300000,
+			.uV_step = 10000,
+			.owner = THIS_MODULE,
+		}
+	},
+	[DA9121_TYPE_DA9217] = {
+		[DA9121_INDEX_BUCK1] = {
+			.id = DA9217_ID_BUCK1,
+			.name = "DA9217 BUCK1",
+			.of_match = of_match_ptr((const char *)
+				     &da9121_matches[DA9121_INDEX_BUCK1].name),
+			.of_map_mode = da9121_map_mode,
+			.regulators_node = of_match_ptr("regulators"),
+			.ops = &da9121_buck_ops,
+			.type = REGULATOR_VOLTAGE,
+			.enable_reg = DA9121_REG_BUCK_BUCK1_0,
+			.enable_mask = DA9121_MASK_BUCK_BUCKX_0_CHX_EN,
+			.vsel_reg = DA9121_REG_BUCK_BUCK1_5,
+			.vsel_mask = DA9121_MASK_BUCK_BUCKX_5_CHX_A_VOUT,
+			.linear_min_sel = 30,
+			.n_voltages = 191,
+			.min_uV = 300000,
+			.uV_step = 10000,
+			.owner = THIS_MODULE,
+		}
+	}
+};
+
+static int da9121_parse_regulators_dt(struct da9121 *chip)
+{
+	struct da9121_dt_data *data = NULL;
+	struct device_node *node;
+	int num_matches = 0;
+	int ret = 0;
+	int i, n;
+
+	node = of_get_child_by_name(chip->dev->of_node, "regulators");
+	if (!node) {
+		dev_err(chip->dev, "Regulators node not found\n");
+		ret = -ENODEV;
+		goto error;
+	}
+
+	num_matches = of_regulator_match(chip->dev, node, da9121_matches,
+					 ARRAY_SIZE(da9121_matches));
+	of_node_put(node);
+	if (num_matches < 0) {
+		dev_err(chip->dev, "Failed while matching regulators\n");
+		ret = -EINVAL;
+		goto error;
+	}
+
+	/* Interrupt assumptions require at least one buck to be configured */
+	if (num_matches == 0) {
+		dev_err(chip->dev, "Did not match any regulators in the DT\n");
+		goto error;
+	}
+
+	data = devm_kzalloc(chip->dev,
+			    sizeof(struct da9121_dt_data), GFP_KERNEL);
+	if (!data) {
+		ret = -ENOMEM;
+		goto error;
+	}
+
+	data->num_matches = (unsigned int)num_matches;
+
+	n = 0;
+	for (i = 0; i < ARRAY_SIZE(da9121_matches); i++) {
+		if (!da9121_matches[i].init_data)
+			continue;
+
+		data->init_data[n] = da9121_matches[i].init_data;
+		data->reg_node[n] = da9121_matches[i].of_node;
+		data->gpiod_ren[n] = devm_gpiod_get_from_of_node(chip->dev,
+								 da9121_matches[i].of_node,
+								 "enable-gpio",
+								 0,
+								 GPIOD_OUT_HIGH,
+								 "da9121-enable");
+		if (IS_ERR(data->gpiod_ren[n]))
+			data->gpiod_ren[n] = NULL;
+
+		if (variant_parameters[chip->variant_id].num_bucks == 2) {
+			u32 ripple_cancel;
+			u32 reg = (i ? DA9xxx_REG_BUCK_BUCK2_7
+					  : DA9121_REG_BUCK_BUCK1_7);
+			if (!of_property_read_u32(da9121_matches[i].of_node,
+						  "dlg,ripple-cancel",
+						  &ripple_cancel)) {
+				/* Write to BUCK_BUCKx_7 : CHx_RIPPLE_CANCEL */
+				ret = regmap_update_bits(chip->regmap, reg,
+							 DA9xxx_MASK_BUCK_BUCKX_7_CHX_RIPPLE_CANCEL,
+							 ripple_cancel);
+				if (ret < 0)
+					dev_err(chip->dev,
+						"Cannot update BUCK register %02x, err: %d\n",
+						reg, ret);
+			}
+		}
+		n++;
+	}
+
+	chip->dt_data = data;
+error:
+	return ret;
+}
+
+static inline int da9121_handle_notifier(struct da9121 *chip,
+					 struct regulator_dev *rdev,
+					 unsigned int event_bank,
+					 unsigned int event,
+					 unsigned int ebit)
+{
+	enum { R0 = 0, R1, R2, REG_MAX_NUM };
+	unsigned long notification = 0;
+	int ret = 0;
+
+	if (event & ebit) {
+		switch (event_bank) {
+		case DA9121_REG_SYS_EVENT_0:
+			switch (event & ebit) {
+			case DA9121_MASK_SYS_EVENT_0_E_TEMP_CRIT:
+				chip->persistent[R0] |= DA9121_MASK_SYS_EVENT_0_E_TEMP_CRIT;
+				notification |= REGULATOR_EVENT_OVER_TEMP |
+						REGULATOR_EVENT_DISABLE;
+				break;
+			case DA9121_MASK_SYS_EVENT_0_E_TEMP_WARN:
+				chip->persistent[R0] |= DA9121_MASK_SYS_EVENT_0_E_TEMP_WARN;
+				notification |= REGULATOR_EVENT_OVER_TEMP;
+				break;
+			default:
+				dev_warn(chip->dev,
+					 "Unhandled event in bank0 0x%02x\n",
+					 event & ebit);
+				ret = -EINVAL;
+				break;
+			}
+			break;
+		case DA9121_REG_SYS_EVENT_1:
+			switch (event & ebit) {
+			case DA9121_MASK_SYS_EVENT_1_E_OV1:
+				chip->persistent[R1] |= DA9121_MASK_SYS_EVENT_1_E_OV1;
+				notification |= REGULATOR_EVENT_REGULATION_OUT;
+				break;
+			case DA9121_MASK_SYS_EVENT_1_E_UV1:
+				chip->persistent[R1] |= DA9121_MASK_SYS_EVENT_1_E_UV1;
+				notification |= REGULATOR_EVENT_UNDER_VOLTAGE;
+				break;
+			case DA9121_MASK_SYS_EVENT_1_E_OC1:
+				chip->persistent[R1] |= DA9121_MASK_SYS_EVENT_1_E_OC1;
+				notification |= REGULATOR_EVENT_OVER_CURRENT;
+				break;
+			case DA9xxx_MASK_SYS_EVENT_1_E_OV2:
+				chip->persistent[R1] |= DA9xxx_MASK_SYS_EVENT_1_E_OV2;
+				notification |= REGULATOR_EVENT_REGULATION_OUT;
+				break;
+			case DA9xxx_MASK_SYS_EVENT_1_E_UV2:
+				chip->persistent[R1] |= DA9xxx_MASK_SYS_EVENT_1_E_UV2;
+				notification |= REGULATOR_EVENT_UNDER_VOLTAGE;
+				break;
+			case DA9xxx_MASK_SYS_EVENT_1_E_OC2:
+				chip->persistent[R1] |= DA9xxx_MASK_SYS_EVENT_1_E_OC2;
+				notification |= REGULATOR_EVENT_OVER_CURRENT;
+				break;
+			default:
+				dev_warn(chip->dev,
+					 "Unhandled event in bank1 0x%02x\n",
+					 event & ebit);
+				ret = -EINVAL;
+				break;
+			}
+			break;
+		default:
+			dev_warn(chip->dev,
+				 "Unhandled event bank 0x%02x\n", event_bank);
+			ret = -EINVAL;
+			goto error;
+		}
+
+		regulator_lock(rdev);
+		regulator_notifier_call_chain(rdev, notification, NULL);
+		regulator_unlock(rdev);
+	}
+
+error:
+	return ret;
+}
+
+static irqreturn_t da9121_irq_handler(int irq, void *data)
+{
+	struct da9121 *chip = data;
+	struct regulator_dev *rdev;
+	enum { R0 = 0, R1, R2, REG_MAX_NUM };
+	int event[REG_MAX_NUM] = {0};
+	int handled[REG_MAX_NUM] = {0};
+	int mask[REG_MAX_NUM] = {0};
+	int ret = IRQ_NONE;
+	int i;
+	int err;
+
+	err = regmap_bulk_read(chip->regmap, DA9121_REG_SYS_EVENT_0,
+			       (void *)event, (size_t)REG_MAX_NUM);
+	if (err < 0) {
+		dev_err(chip->dev, "Failed to read EVENT registers %d\n", err);
+		ret = IRQ_NONE;
+		goto error;
+	}
+
+	err = regmap_bulk_read(chip->regmap, DA9121_REG_SYS_MASK_0,
+			       (void *)mask, (size_t)REG_MAX_NUM);
+	if (err < 0) {
+		dev_err(chip->dev,
+			"Failed to read MASK registers: %d\n", ret);
+		ret = IRQ_NONE;
+		goto error;
+	}
+
+	rdev = chip->rdev[DA9121_INDEX_BUCK1];
+
+	/* 0 SYSTEM_GOOD */
+	if (!(mask[R0] & DA9xxx_MASK_SYS_MASK_0_M_SG) &&
+	    (event[R0] & DA9xxx_MASK_SYS_EVENT_0_E_SG)) {
+		dev_warn(chip->dev, "Handled E_SG\n");
+		handled[R0] |= DA9xxx_MASK_SYS_EVENT_0_E_SG;
+		ret = IRQ_HANDLED;
+	}
+
+	/* 0 TEMP_CRIT */
+	if (!(mask[R0] & DA9121_MASK_SYS_MASK_0_M_TEMP_CRIT) &&
+	    (event[R0] & DA9121_MASK_SYS_EVENT_0_E_TEMP_CRIT)) {
+		err = da9121_handle_notifier(chip, rdev,
+					     DA9121_REG_SYS_EVENT_0, event[R0],
+					     DA9121_MASK_SYS_EVENT_0_E_TEMP_CRIT);
+		if (!err) {
+			handled[R0] |= DA9121_MASK_SYS_EVENT_0_E_TEMP_CRIT;
+			ret = IRQ_HANDLED;
+		}
+	}
+
+	/* 0 TEMP_WARN */
+	if (!(mask[R0] & DA9121_MASK_SYS_MASK_0_M_TEMP_WARN) &&
+	    (event[R0] & DA9121_MASK_SYS_EVENT_0_E_TEMP_WARN)) {
+		err = da9121_handle_notifier(chip, rdev,
+					     DA9121_REG_SYS_EVENT_0, event[R0],
+					     DA9121_MASK_SYS_EVENT_0_E_TEMP_WARN);
+		if (!err) {
+			handled[R0] |= DA9121_MASK_SYS_EVENT_0_E_TEMP_WARN;
+			ret = IRQ_HANDLED;
+		}
+	}
+
+	if (event[R0] != handled[R0]) {
+		dev_warn(chip->dev,
+			 "Unhandled event in bank0 0x%02x\n",
+			 event[R0] ^ handled[R0]);
+	}
+
+	/* 1 PG1 */
+	if (!(mask[R1] & DA9121_MASK_SYS_MASK_1_M_PG1) &&
+	    (event[R1] & DA9121_MASK_SYS_EVENT_1_E_PG1)) {
+		dev_warn(chip->dev, "Handled E_PG1\n");
+		handled[R1] |= DA9121_MASK_SYS_EVENT_1_E_PG1;
+		ret = IRQ_HANDLED;
+	}
+
+	/* 1 OV1 */
+	if (!(mask[R1] & DA9121_MASK_SYS_MASK_1_M_OV1) &&
+	    (event[R1] & DA9121_MASK_SYS_EVENT_1_E_OV1)) {
+		err = da9121_handle_notifier(chip, rdev,
+					     DA9121_REG_SYS_EVENT_1, event[R1],
+					     DA9121_MASK_SYS_EVENT_1_E_OV1);
+		if (!err) {
+			handled[R1] |= DA9121_MASK_SYS_EVENT_1_E_OV1;
+			ret = IRQ_HANDLED;
+		}
+	}
+
+	/* 1 UV1 */
+	if (!(mask[R1] & DA9121_MASK_SYS_MASK_1_M_UV1) &&
+	    (event[R1] & DA9121_MASK_SYS_EVENT_1_E_UV1)) {
+		err = da9121_handle_notifier(chip, rdev,
+					     DA9121_REG_SYS_EVENT_1, event[R1],
+					     DA9121_MASK_SYS_EVENT_1_E_UV1);
+		if (!err) {
+			handled[R1] |= DA9121_MASK_SYS_EVENT_1_E_UV1;
+			ret = IRQ_HANDLED;
+		}
+	}
+
+	/* 1 OC1 */
+	if (!(mask[R1] & DA9121_MASK_SYS_MASK_1_M_OC1) &&
+	    (event[R1] & DA9121_MASK_SYS_EVENT_1_E_OC1)) {
+		err = da9121_handle_notifier(chip, rdev,
+					     DA9121_REG_SYS_EVENT_1, event[R1],
+					     DA9121_MASK_SYS_EVENT_1_E_OC1);
+		if (!err) {
+			handled[R1] |= DA9121_MASK_SYS_EVENT_1_E_OC1;
+			ret = IRQ_HANDLED;
+		}
+	}
+
+	if (variant_parameters[chip->variant_id].num_bucks == 2) {
+		struct regulator_dev *rdev2;
+
+		rdev2 = chip->rdev[DA9121_INDEX_BUCK2];
+
+		/* 1 PG2 */
+		if (!(mask[R1] & DA9xxx_MASK_SYS_MASK_1_M_PG2) &&
+		    (event[R1] & DA9xxx_MASK_SYS_EVENT_1_E_PG2)) {
+			dev_warn(chip->dev, "Handled E_PG2\n");
+			handled[R1] |= DA9xxx_MASK_SYS_EVENT_1_E_PG2;
+			ret = IRQ_HANDLED;
+		}
+
+		/* 1 OV2 */
+		if (!(mask[R1] & DA9xxx_MASK_SYS_MASK_1_M_OV2) &&
+		    (event[R1] & DA9xxx_MASK_SYS_EVENT_1_E_OV2)) {
+			err = da9121_handle_notifier(chip, rdev2,
+						     DA9121_REG_SYS_EVENT_1, event[R1],
+						     DA9xxx_MASK_SYS_EVENT_1_E_OV2);
+			if (!err) {
+				handled[R1] |= DA9xxx_MASK_SYS_EVENT_1_E_OV2;
+				ret = IRQ_HANDLED;
+			}
+		}
+
+		/* 1 UV2 */
+		if (!(mask[R1] & DA9xxx_MASK_SYS_MASK_1_M_UV2) &&
+		    (event[R1] & DA9xxx_MASK_SYS_EVENT_1_E_UV2)) {
+			err = da9121_handle_notifier(chip, rdev2,
+						     DA9121_REG_SYS_EVENT_1, event[R1],
+						     DA9xxx_MASK_SYS_EVENT_1_E_UV2);
+			if (!err) {
+				handled[R1] |= DA9xxx_MASK_SYS_EVENT_1_E_UV2;
+				ret = IRQ_HANDLED;
+			}
+		}
+
+		/* 1 OC2 */
+		if (!(mask[R1] & DA9xxx_MASK_SYS_MASK_1_M_OC2) &&
+		    (event[R1] & DA9xxx_MASK_SYS_EVENT_1_E_OC2)) {
+			err = da9121_handle_notifier(chip, rdev2,
+						     DA9121_REG_SYS_EVENT_1, event[R1],
+						     DA9xxx_MASK_SYS_EVENT_1_E_OC2);
+			if (!err) {
+				handled[R1] |= DA9xxx_MASK_SYS_EVENT_1_E_OC2;
+				ret = IRQ_HANDLED;
+			}
+		}
+	}
+
+	if (event[R1] != handled[R1]) {
+		dev_warn(chip->dev,
+			 "Unhandled event in bank1 0x%02x\n",
+			 event[R1] ^ handled[R1]);
+	}
+
+	/* DA9121_REG_SYS_EVENT_2 */
+	if (!(mask[R2] & DA9121_MASK_SYS_MASK_2_M_GPIO2) &&
+	    (event[R2] & DA9121_MASK_SYS_EVENT_2_E_GPIO2)) {
+		dev_warn(chip->dev, "Handled E_GPIO2\n");
+		handled[R2] |= DA9121_MASK_SYS_EVENT_2_E_GPIO2;
+		ret = IRQ_HANDLED;
+	}
+
+	if (!(mask[R2] & DA9121_MASK_SYS_MASK_2_M_GPIO1) &&
+	    (event[R2] & DA9121_MASK_SYS_EVENT_2_E_GPIO1)) {
+		dev_warn(chip->dev, "Handled E_GPIO1\n");
+		handled[R2] |= DA9121_MASK_SYS_EVENT_2_E_GPIO1;
+		ret = IRQ_HANDLED;
+	}
+
+	if (!(mask[R2] & DA9121_MASK_SYS_MASK_2_M_GPIO0) &&
+	    (event[R2] & DA9121_MASK_SYS_EVENT_2_E_GPIO0)) {
+		dev_warn(chip->dev, "Handled E_GPIO0\n");
+		handled[R2] |= DA9121_MASK_SYS_EVENT_2_E_GPIO0;
+		ret = IRQ_HANDLED;
+	}
+
+	if (event[R2] != handled[R2]) {
+		dev_warn(chip->dev,
+			 "Unhandled event in bank2 0x%02x\n",
+			 event[R2] ^ handled[R2]);
+	}
+
+	/* Mask the interrupts for persistent events OV, OC, UV, WARN, CRIT */
+	for (i = R0; i < REG_MAX_NUM - 1; i++) {
+		if (handled[i]) {
+			unsigned int reg = DA9121_REG_SYS_MASK_0 + i;
+			unsigned int mbit = handled[i];
+
+			err = regmap_update_bits(chip->regmap, reg, mbit, mbit);
+			if (err < 0) {
+				dev_err(chip->dev,
+					"Failed to mask 0x%02x interrupt %d\n",
+					reg, err);
+				ret = IRQ_NONE;
+				goto error;
+			}
+		}
+	}
+
+	/* clear the events */
+	if (handled[R0] | handled[R1] | handled[R2]) {
+		err = regmap_bulk_write(chip->regmap, DA9121_REG_SYS_EVENT_0,
+					(const void *)handled, (size_t)REG_MAX_NUM);
+		if (err < 0) {
+			dev_err(chip->dev, "Fail to write EVENTs %d\n", err);
+			ret = IRQ_NONE;
+			goto error;
+		}
+	}
+
+	queue_delayed_work(system_freezable_wq, &chip->work, 0);
+error:
+	return ret;
+}
+
+static int da9121_set_regulator_config(struct da9121 *chip)
+{
+	struct regulator_config config = { };
+	unsigned int max_matches = chip->dt_data->num_matches;
+	int ret = 0;
+	int i;
+
+	if (max_matches > variant_parameters[chip->variant_id].num_bucks) {
+		dev_err(chip->dev, "Too many regulators in the DT\n");
+		ret = -EINVAL;
+		goto error;
+	}
+
+	for (i = 0; i < max_matches; i++) {
+		struct regulator_desc *regl_desc = &local_da9121_regulators[chip->variant_id][i];
+		int id = regl_desc->id;
+
+		config.init_data = chip->dt_data->init_data[i];
+		config.dev = chip->dev;
+		config.driver_data = chip;
+		config.regmap = chip->regmap;
+		config.of_node = chip->dt_data->reg_node[i];
+
+		switch (id) {
+		case DA9121_DA9130_ID_BUCK1:
+		case DA9220_DA9132_ID_BUCK1:
+		case DA9122_DA9131_ID_BUCK1:
+		case DA9217_ID_BUCK1:
+		case DA9220_DA9132_ID_BUCK2:
+		case DA9122_DA9131_ID_BUCK2:
+			config.ena_gpiod = chip->dt_data->gpiod_ren[i];
+			break;
+		default:
+			dev_err(chip->dev, "Invalid regulator ID\n");
+			ret = -EINVAL;
+			goto error;
+		}
+
+		chip->rdev[i] = devm_regulator_register(chip->dev,
+							regl_desc, &config);
+		if (IS_ERR(chip->rdev[i])) {
+			dev_err(chip->dev, "Failed to register regulator %s, %d/%d of_map_mode:%p\n",
+				regl_desc->name, (i + 1), max_matches, regl_desc->of_map_mode);
+			ret = PTR_ERR(chip->rdev[i]);
+			goto error;
+		}
+	}
+
+error:
+	return ret;
+}
+
+/* DA9121 chip register model */
+static const struct regmap_range da9121_1ch_2ph_readable_ranges[] = {
+	regmap_reg_range(DA9121_REG_SYS_STATUS_0, DA9121_REG_SYS_MASK_3),
+	regmap_reg_range(DA9121_REG_SYS_CONFIG_2, DA9121_REG_SYS_CONFIG_3),
+	regmap_reg_range(DA9121_REG_SYS_GPIO0_0, DA9121_REG_SYS_GPIO2_1),
+	regmap_reg_range(DA9121_REG_BUCK_BUCK1_0, DA9121_REG_BUCK_BUCK1_6),
+	regmap_reg_range(DA9121_REG_OTP_DEVICE_ID, DA9121_REG_OTP_CONFIG_ID),
+};
+
+static const struct regmap_access_table da9121_1ch_2ph_readable_table = {
+	.yes_ranges = da9121_1ch_2ph_readable_ranges,
+	.n_yes_ranges = ARRAY_SIZE(da9121_1ch_2ph_readable_ranges),
+};
+
+static const struct regmap_range da9121_2ch_1ph_readable_ranges[] = {
+	regmap_reg_range(DA9121_REG_SYS_STATUS_0, DA9121_REG_SYS_MASK_3),
+	regmap_reg_range(DA9121_REG_SYS_CONFIG_2, DA9121_REG_SYS_CONFIG_3),
+	regmap_reg_range(DA9121_REG_SYS_GPIO0_0, DA9121_REG_SYS_GPIO2_1),
+	regmap_reg_range(DA9121_REG_BUCK_BUCK1_0, DA9121_REG_BUCK_BUCK1_7),
+	regmap_reg_range(DA9xxx_REG_BUCK_BUCK2_0, DA9xxx_REG_BUCK_BUCK2_7),
+	regmap_reg_range(DA9121_REG_OTP_DEVICE_ID, DA9121_REG_OTP_CONFIG_ID),
+};
+
+static const struct regmap_access_table da9121_2ch_1ph_readable_table = {
+	.yes_ranges = da9121_2ch_1ph_readable_ranges,
+	.n_yes_ranges = ARRAY_SIZE(da9121_2ch_1ph_readable_ranges),
+};
+
+static const struct regmap_range da9121_1ch_2ph_writeable_ranges[] = {
+	regmap_reg_range(DA9121_REG_SYS_EVENT_0, DA9121_REG_SYS_MASK_3),
+	regmap_reg_range(DA9121_REG_SYS_CONFIG_2, DA9121_REG_SYS_CONFIG_3),
+	regmap_reg_range(DA9121_REG_SYS_GPIO0_0, DA9121_REG_SYS_GPIO2_1),
+	regmap_reg_range(DA9121_REG_BUCK_BUCK1_0, DA9121_REG_BUCK_BUCK1_2),
+	regmap_reg_range(DA9121_REG_BUCK_BUCK1_4, DA9121_REG_BUCK_BUCK1_6),
+};
+
+static const struct regmap_access_table da9121_1ch_2ph_writeable_table = {
+	.yes_ranges = da9121_1ch_2ph_writeable_ranges,
+	.n_yes_ranges = ARRAY_SIZE(da9121_1ch_2ph_writeable_ranges),
+};
+
+static const struct regmap_range da9121_2ch_1ph_writeable_ranges[] = {
+	regmap_reg_range(DA9121_REG_SYS_EVENT_0, DA9121_REG_SYS_MASK_3),
+	regmap_reg_range(DA9121_REG_SYS_CONFIG_2, DA9121_REG_SYS_CONFIG_3),
+	regmap_reg_range(DA9121_REG_SYS_GPIO0_0, DA9121_REG_SYS_GPIO2_1),
+	regmap_reg_range(DA9121_REG_BUCK_BUCK1_0, DA9121_REG_BUCK_BUCK1_2),
+	regmap_reg_range(DA9121_REG_BUCK_BUCK1_4, DA9121_REG_BUCK_BUCK1_7),
+	regmap_reg_range(DA9xxx_REG_BUCK_BUCK2_0, DA9xxx_REG_BUCK_BUCK2_2),
+	regmap_reg_range(DA9xxx_REG_BUCK_BUCK2_4, DA9xxx_REG_BUCK_BUCK2_7),
+};
+
+static const struct regmap_access_table da9121_2ch_1ph_writeable_table = {
+	.yes_ranges = da9121_2ch_1ph_writeable_ranges,
+	.n_yes_ranges = ARRAY_SIZE(da9121_2ch_1ph_writeable_ranges),
+};
+
+static const struct regmap_range da9121_volatile_ranges[] = {
+	regmap_reg_range(DA9121_REG_SYS_STATUS_0, DA9121_REG_SYS_EVENT_2),
+	regmap_reg_range(DA9121_REG_SYS_GPIO0_0, DA9121_REG_SYS_GPIO2_1),
+	regmap_reg_range(DA9121_REG_BUCK_BUCK1_0, DA9121_REG_BUCK_BUCK1_6),
+};
+
+static const struct regmap_access_table da9121_volatile_table = {
+	.yes_ranges = da9121_volatile_ranges,
+	.n_yes_ranges = ARRAY_SIZE(da9121_volatile_ranges),
+};
+
+/* DA9121 regmap config for 1 channel 2 phase variants */
+static struct regmap_config da9121_1ch_2ph_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = DA9121_REG_OTP_CONFIG_ID,
+	.rd_table = &da9121_1ch_2ph_readable_table,
+	.wr_table = &da9121_1ch_2ph_writeable_table,
+	.volatile_table = &da9121_volatile_table,
+	.cache_type = REGCACHE_RBTREE,
+};
+
+/* DA9121 regmap config for 2 channel 1 phase variants */
+static struct regmap_config da9121_2ch_1ph_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = DA9121_REG_OTP_CONFIG_ID,
+	.rd_table = &da9121_2ch_1ph_readable_table,
+	.wr_table = &da9121_2ch_1ph_writeable_table,
+	.volatile_table = &da9121_volatile_table,
+	.cache_type = REGCACHE_RBTREE,
+};
+
+static int da9121_i2c_reg_read(struct i2c_client *client, u8 addr,
+			       u8 *buf, int count)
+{
+	struct i2c_msg xfer[2];
+	int ret;
+
+	xfer[0].addr = client->addr;
+	xfer[0].flags = 0;
+	xfer[0].len = 1;
+	xfer[0].buf = &addr;
+
+	xfer[1].addr = client->addr;
+	xfer[1].flags = I2C_M_RD;
+	xfer[1].len = 1;
+	xfer[1].buf = buf;
+
+	ret = i2c_transfer(client->adapter, xfer, 2);
+	if (ret < 0) {
+		dev_err(&client->dev, "Device read failed: %d\n", ret);
+		return ret;
+	}
+
+	if (ret != 2) {
+		dev_err(&client->dev, "Device read failed to complete\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int da9121_get_device_type(struct i2c_client *i2c, struct da9121 *chip)
+{
+	u8 device_id;
+	u8 variant_id;
+	u8 variant_mrc, variant_vrc;
+	char *type;
+	const char *name;
+	bool device_config_match = false;
+	int ret = 0;
+
+	ret = da9121_i2c_reg_read(i2c, DA9121_REG_OTP_DEVICE_ID,
+				  &device_id, 1);
+	if (ret < 0) {
+		dev_err(chip->dev, "Failed to read device ID: %d\n", ret);
+		goto error;
+	}
+
+	ret = da9121_i2c_reg_read(i2c, DA9121_REG_OTP_VARIANT_ID,
+				  &variant_id, 1);
+	if (ret < 0) {
+		dev_err(chip->dev, "Cannot read chip variant ID: %d\n", ret);
+		goto error;
+	}
+
+	if (device_id != DA9121_DEVICE_ID) {
+		dev_err(chip->dev, "Invalid device ID: 0x%02x\n", device_id);
+		ret = -ENODEV;
+		goto error;
+	}
+
+	name = of_get_property(chip->dev->of_node, "compatible", NULL);
+	if (!name) {
+		dev_err(chip->dev, "Cannot get device not compatible string.\n");
+		goto error;
+	}
+
+	variant_vrc = variant_id & DA9121_MASK_OTP_VARIANT_ID_VRC;
+
+	switch (variant_vrc) {
+	case DA9130_VARIANT_VRC:
+		type = "DA9121/DA9130";
+		device_config_match = (chip->variant_id == DA9121_TYPE_DA9121_DA9130);
+		break;
+	case DA9131_VARIANT_VRC:
+		type = "DA9122/DA9131";
+		device_config_match = (chip->variant_id == DA9121_TYPE_DA9122_DA9131);
+		break;
+	case DA9217_VARIANT_VRC:
+		type = "DA9217";
+		device_config_match = (chip->variant_id == DA9121_TYPE_DA9217);
+		break;
+	default:
+		type = "Unknown";
+		break;
+	}
+
+	dev_info(chip->dev,
+		 "Device detected (device-ID: 0x%02X, var-ID: 0x%02X, %s)\n",
+		 device_id, variant_id, type);
+
+	if (!device_config_match) {
+		dev_err(chip->dev, "Device tree configuration '%s'does not match detected device.\n"
+			, name);
+		goto error;
+	}
+
+	variant_mrc = (variant_id & DA9121_MASK_OTP_VARIANT_ID_MRC)
+			>> DA9121_SHIFT_OTP_VARIANT_ID_MRC;
+
+	if (variant_mrc < DA9121_VARIANT_MRC_BASE) {
+		dev_err(chip->dev,
+			"Cannot support variant MRC: 0x%02X\n", variant_mrc);
+		ret = -ENODEV;
+	}
+error:
+	return ret;
+}
+
+static int da9121_assign_chip_model(struct i2c_client *i2c,
+				    struct da9121 *chip)
+{
+	struct regmap_config *regmap = NULL;
+	int ret = 0;
+
+	chip->dev = &i2c->dev;
+
+	ret = da9121_get_device_type(i2c, chip);
+	if (ret)
+		return ret;
+
+	switch (chip->variant_id) {
+	case DA9121_TYPE_DA9121_DA9130:
+	case DA9121_TYPE_DA9217:
+		regmap = &da9121_1ch_2ph_regmap_config;
+		break;
+	case DA9121_TYPE_DA9122_DA9131:
+	case DA9121_TYPE_DA9220_DA9132:
+		regmap = &da9121_2ch_1ph_regmap_config;
+	}
+
+	/* Set these up for of_regulator_match call which may want .of_map_modes */
+	da9121_matches[0].desc = &local_da9121_regulators[chip->variant_id][0];
+	da9121_matches[1].desc = &local_da9121_regulators[chip->variant_id][1];
+
+	chip->regmap = devm_regmap_init_i2c(i2c, regmap);
+	if (IS_ERR(chip->regmap)) {
+		ret = PTR_ERR(chip->regmap);
+		dev_err(chip->dev, "Failed to configure a register map: %d\n",
+			ret);
+	}
+
+	return ret;
+}
+
+static int da9121_set_irq_masks(struct da9121 *chip, bool mask_irqs)
+{
+	unsigned int mask0, update0;
+	unsigned int mask1, update1;
+	unsigned int mask3;
+	int ret = 0;
+
+	if (chip->chip_irq != 0) {
+		mask0 = DA9121_MASK_SYS_MASK_0_M_TEMP_CRIT |
+			DA9121_MASK_SYS_MASK_0_M_TEMP_WARN;
+
+		mask1 = DA9121_MASK_SYS_MASK_1_M_OV1 |
+			DA9121_MASK_SYS_MASK_1_M_UV1 |
+			DA9121_MASK_SYS_MASK_1_M_OC1;
+
+		if (mask_irqs) {
+			update0 = mask0;
+			update1 = mask1;
+		} else {
+			update0 = 0;
+			update1 = 0;
+		}
+
+		ret = regmap_update_bits(chip->regmap,
+					 DA9121_REG_SYS_MASK_0, mask0, update0);
+		if (ret < 0) {
+			dev_err(chip->dev, "Failed to write MASK 0 reg %d\n",
+				ret);
+			goto error;
+		}
+
+		ret = regmap_update_bits(chip->regmap,
+					 DA9121_REG_SYS_MASK_1, mask1, update1);
+		if (ret < 0) {
+			dev_err(chip->dev, "Failed to write MASK 1 reg %d\n",
+				ret);
+			goto error;
+		}
+
+		/* permanently disable IRQs for VR_HOT and PG1_STAT */
+		mask3 = DA9121_MASK_SYS_MASK_3_M_VR_HOT |
+			DA9121_MASK_SYS_MASK_3_M_PG1_STAT;
+
+		ret = regmap_update_bits(chip->regmap,
+					 DA9121_REG_SYS_MASK_3, mask3, mask3);
+		if (ret < 0) {
+			dev_err(chip->dev, "Failed to write MASK 3 reg %d\n",
+				ret);
+			goto error;
+		}
+	}
+
+error:
+	return ret;
+}
+
+static int da9121_config_irq(struct i2c_client *i2c, struct da9121 *chip)
+{
+	unsigned int p_delay = DA9121_DEFAULT_POLLING_PERIOD_MS;
+	int ret = 0;
+
+	chip->chip_irq = i2c->irq;
+
+	if (chip->chip_irq != 0) {
+		if (!of_property_read_u32(chip->dev->of_node,
+					  "dlg,irq-polling-delay-passive",
+					  &p_delay)) {
+			if (p_delay < DA9121_MIN_POLLING_PERIOD_MS ||
+			    p_delay > DA9121_MAX_POLLING_PERIOD_MS) {
+				dev_warn(chip->dev,
+					 "Out-of-range polling period %d ms\n",
+					 p_delay);
+				p_delay = DA9121_DEFAULT_POLLING_PERIOD_MS;
+			}
+		}
+
+		chip->passive_delay = p_delay;
+
+		ret = devm_request_threaded_irq(chip->dev, chip->chip_irq, NULL,
+						da9121_irq_handler,
+						IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+						"da9121", chip);
+		if (ret != 0) {
+			dev_err(chip->dev, "Failed IRQ request: %d\n",
+				chip->chip_irq);
+			goto error;
+		}
+
+		ret = da9121_set_irq_masks(chip, false);
+		if (ret != 0) {
+			dev_err(chip->dev, "Failed to set IRQ masks: %d\n",
+				ret);
+			goto error;
+		}
+
+		INIT_DELAYED_WORK(&chip->work, da9121_status_poll_on);
+		dev_info(chip->dev, "Interrupt polling period set at %d ms\n",
+			 chip->passive_delay);
+	}
+error:
+	return ret;
+}
+
+static const struct of_device_id da9121_dt_ids[] = {
+	{ .compatible = "dlg,da9121", .data = (void *)DA9121_TYPE_DA9121_DA9130 },
+	{ .compatible = "dlg,da9130", .data = (void *)DA9121_TYPE_DA9121_DA9130 },
+	{ .compatible = "dlg,da9217", .data = (void *)DA9121_TYPE_DA9217 },
+	{ .compatible = "dlg,da9122", .data = (void *)DA9121_TYPE_DA9122_DA9131 },
+	{ .compatible = "dlg,da9131", .data = (void *)DA9121_TYPE_DA9122_DA9131 },
+	{ .compatible = "dlg,da9220", .data = (void *)DA9121_TYPE_DA9220_DA9132 },
+	{ .compatible = "dlg,da9132", .data = (void *)DA9121_TYPE_DA9220_DA9132 },
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, da9121_dt_ids);
+
+static inline int da9121_of_get_id(struct device *dev)
+{
+	const struct of_device_id *id = of_match_device(da9121_dt_ids, dev);
+
+	if (id)
+		return (uintptr_t)id->data;
+
+	dev_err(dev, "%s: Failed\n", __func__);
+	return -EINVAL;
+}
+
+static int da9121_i2c_probe(struct i2c_client *i2c,
+			    const struct i2c_device_id *id)
+{
+	struct da9121 *chip;
+	int ret = 0;
+
+	chip = devm_kzalloc(&i2c->dev, sizeof(struct da9121), GFP_KERNEL);
+	if (!chip) {
+		ret = -ENOMEM;
+		goto error;
+	}
+
+	chip->variant_id = da9121_of_get_id(&i2c->dev);
+
+	ret = da9121_assign_chip_model(i2c, chip);
+	if (ret < 0)
+		goto error;
+
+	ret = da9121_set_irq_masks(chip, true);
+	if (ret != 0) {
+		dev_err(chip->dev, "Failed to set IRQ masks: %d\n", ret);
+		goto error;
+	}
+
+	ret = da9121_parse_regulators_dt(chip);
+	if (ret < 0)
+		goto error;
+
+	ret = da9121_set_regulator_config(chip);
+	if (ret < 0)
+		goto error;
+
+	ret = da9121_config_irq(i2c, chip);
+	if (ret < 0)
+		goto error;
+
+error:
+	return ret;
+}
+
+static int da9121_i2c_remove(struct i2c_client *i2c)
+{
+	struct da9121 *chip = i2c_get_clientdata(i2c);
+	int ret = 0;
+
+	ret = da9121_set_irq_masks(chip, true);
+	if (ret != 0) {
+		dev_err(chip->dev, "Failed to set IRQ masks: %d\n", ret);
+		goto error;
+	}
+
+	cancel_delayed_work(&chip->work);
+error:
+	return ret;
+}
+
+static struct i2c_driver da9121_regulator_driver = {
+	.driver = {
+		.name = "da9121",
+		.of_match_table = of_match_ptr(da9121_dt_ids),
+	},
+	.probe = da9121_i2c_probe,
+	.remove = da9121_i2c_remove,
+};
+
+module_i2c_driver(da9121_regulator_driver);
+
+MODULE_AUTHOR("Steve Twiss <stwiss.opensource@diasemi.com>");
+MODULE_AUTHOR("Adam Ward <award.opensource@diasemi.com>");
+MODULE_DESCRIPTION("DA9121 Buck regulator driver");
+MODULE_LICENSE("GPL");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/da9121-regulator.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/da9121-regulator.h
@@ -0,0 +1,257 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * DA9121 Single-channel dual-phase 10A buck converter
+ * DA9130 Single-channel dual-phase 10A buck converter (Automotive)
+ * DA9217 Single-channel dual-phase  6A buck converter
+ * DA9122 Dual-channel single-phase  5A buck converter
+ * DA9131 Dual-channel single-phase  5A buck converter (Automotive)
+ * DA9220 Dual-channel single-phase  3A buck converter
+ * DA9132 Dual-channel single-phase  3A buck converter (Automotive)
+ *
+ * Copyright (C) 2020  Dialog Semiconductor
+ *
+ * Authors: Steve Twiss, Dialog Semiconductor
+ *          Adam Ward, Dialog Semiconductor
+ */
+
+#ifndef __DA9121_REGISTERS_H__
+#define __DA9121_REGISTERS_H__
+
+/*
+ * Values for: DA9121_REG_BUCK_BUCKx_4 registers, fields CHx_y_MODE
+ *             DA9121_REG_BUCK_BUCKx_7 registers, fields CHx_RIPPLE_CANCEL
+ */
+#include <dt-bindings/regulator/dlg,da9121-regulator.h>
+
+/* Registers */
+
+#define DA9121_REG_SYS_STATUS_0		0x01
+#define DA9121_REG_SYS_STATUS_1		0x02
+#define DA9121_REG_SYS_STATUS_2		0x03
+#define DA9121_REG_SYS_EVENT_0		0x04
+#define DA9121_REG_SYS_EVENT_1		0x05
+#define DA9121_REG_SYS_EVENT_2		0x06
+#define DA9121_REG_SYS_MASK_0		0x07
+#define DA9121_REG_SYS_MASK_1		0x08
+#define DA9121_REG_SYS_MASK_2		0x09
+#define DA9121_REG_SYS_MASK_3		0x0A
+#define DA9121_REG_SYS_CONFIG_0		0x0B
+#define DA9121_REG_SYS_CONFIG_1		0x0C
+#define DA9121_REG_SYS_CONFIG_2		0x0D
+#define DA9121_REG_SYS_CONFIG_3		0x0E
+#define DA9121_REG_SYS_GPIO0_0		0x10
+#define DA9121_REG_SYS_GPIO0_1		0x11
+#define DA9121_REG_SYS_GPIO1_0		0x12
+#define DA9121_REG_SYS_GPIO1_1		0x13
+#define DA9121_REG_SYS_GPIO2_0		0x14
+#define DA9121_REG_SYS_GPIO2_1		0x15
+#define DA9121_REG_BUCK_BUCK1_0		0x20
+#define DA9121_REG_BUCK_BUCK1_1		0x21
+#define DA9121_REG_BUCK_BUCK1_2		0x22
+#define DA9121_REG_BUCK_BUCK1_3		0x23
+#define DA9121_REG_BUCK_BUCK1_4		0x24
+#define DA9121_REG_BUCK_BUCK1_5		0x25
+#define DA9121_REG_BUCK_BUCK1_6		0x26
+#define DA9121_REG_BUCK_BUCK1_7		0x27
+#define DA9xxx_REG_BUCK_BUCK2_0		0x28
+#define DA9xxx_REG_BUCK_BUCK2_1		0x29
+#define DA9xxx_REG_BUCK_BUCK2_2		0x2A
+#define DA9xxx_REG_BUCK_BUCK2_3		0x2B
+#define DA9xxx_REG_BUCK_BUCK2_4		0x2C
+#define DA9xxx_REG_BUCK_BUCK2_5		0x2D
+#define DA9xxx_REG_BUCK_BUCK2_6		0x2E
+#define DA9xxx_REG_BUCK_BUCK2_7		0x2F
+#define DA9121_REG_OTP_DEVICE_ID	0x48
+#define DA9121_REG_OTP_VARIANT_ID	0x49
+#define DA9121_REG_OTP_CUSTOMER_ID	0x4A
+#define DA9121_REG_OTP_CONFIG_ID	0x4B
+
+/* Register bits */
+
+/* DA9121_REG_SYS_STATUS_0 */
+
+#define DA9xxx_MASK_SYS_STATUS_0_SG			BIT(2)
+#define DA9121_MASK_SYS_STATUS_0_TEMP_CRIT		BIT(1)
+#define DA9121_MASK_SYS_STATUS_0_TEMP_WARN		BIT(0)
+
+/* DA9121_REG_SYS_STATUS_1 */
+
+#define DA9xxx_MASK_SYS_STATUS_1_PG2			BIT(7)
+#define DA9xxx_MASK_SYS_STATUS_1_OV2			BIT(6)
+#define DA9xxx_MASK_SYS_STATUS_1_UV2			BIT(5)
+#define DA9xxx_MASK_SYS_STATUS_1_OC2			BIT(4)
+#define DA9121_MASK_SYS_STATUS_1_PG1			BIT(3)
+#define DA9121_MASK_SYS_STATUS_1_OV1			BIT(2)
+#define DA9121_MASK_SYS_STATUS_1_UV1			BIT(1)
+#define DA9121_MASK_SYS_STATUS_1_OC1			BIT(0)
+
+/* DA9121_REG_SYS_STATUS_2 */
+
+#define DA9121_MASK_SYS_STATUS_2_GPIO2			BIT(2)
+#define DA9121_MASK_SYS_STATUS_2_GPIO1			BIT(1)
+#define DA9121_MASK_SYS_STATUS_2_GPIO0			BIT(0)
+
+/* DA9121_REG_SYS_EVENT_0 */
+
+#define DA9xxx_MASK_SYS_EVENT_0_E_SG			BIT(2)
+#define DA9121_MASK_SYS_EVENT_0_E_TEMP_CRIT		BIT(1)
+#define DA9121_MASK_SYS_EVENT_0_E_TEMP_WARN		BIT(0)
+
+/* DA9121_REG_SYS_EVENT_1 */
+
+#define DA9xxx_MASK_SYS_EVENT_1_E_PG2			BIT(7)
+#define DA9xxx_MASK_SYS_EVENT_1_E_OV2			BIT(6)
+#define DA9xxx_MASK_SYS_EVENT_1_E_UV2			BIT(5)
+#define DA9xxx_MASK_SYS_EVENT_1_E_OC2			BIT(4)
+#define DA9121_MASK_SYS_EVENT_1_E_PG1			BIT(3)
+#define DA9121_MASK_SYS_EVENT_1_E_OV1			BIT(2)
+#define DA9121_MASK_SYS_EVENT_1_E_UV1			BIT(1)
+#define DA9121_MASK_SYS_EVENT_1_E_OC1			BIT(0)
+
+/* DA9121_REG_SYS_EVENT_2 */
+
+#define DA9121_MASK_SYS_EVENT_2_E_GPIO2			BIT(2)
+#define DA9121_MASK_SYS_EVENT_2_E_GPIO1			BIT(1)
+#define DA9121_MASK_SYS_EVENT_2_E_GPIO0			BIT(0)
+
+/* DA9121_REG_SYS_MASK_0 */
+
+#define DA9xxx_MASK_SYS_MASK_0_M_SG			BIT(2)
+#define DA9121_MASK_SYS_MASK_0_M_TEMP_CRIT		BIT(1)
+#define DA9121_MASK_SYS_MASK_0_M_TEMP_WARN		BIT(0)
+
+/* DA9121_REG_SYS_MASK_1 */
+
+#define DA9xxx_MASK_SYS_MASK_1_M_PG2			BIT(7)
+#define DA9xxx_MASK_SYS_MASK_1_M_OV2			BIT(6)
+#define DA9xxx_MASK_SYS_MASK_1_M_UV2			BIT(5)
+#define DA9xxx_MASK_SYS_MASK_1_M_OC2			BIT(4)
+#define DA9121_MASK_SYS_MASK_1_M_PG1			BIT(3)
+#define DA9121_MASK_SYS_MASK_1_M_OV1			BIT(2)
+#define DA9121_MASK_SYS_MASK_1_M_UV1			BIT(1)
+#define DA9121_MASK_SYS_MASK_1_M_OC1			BIT(0)
+
+/* DA9121_REG_SYS_MASK_2 */
+
+#define DA9121_MASK_SYS_MASK_2_M_GPIO2			BIT(2)
+#define DA9121_MASK_SYS_MASK_2_M_GPIO1			BIT(1)
+#define DA9121_MASK_SYS_MASK_2_M_GPIO0			BIT(0)
+
+/* DA9122_REG_SYS_MASK_3 */
+
+#define DA9121_MASK_SYS_MASK_3_M_VR_HOT			BIT(3)
+#define DA9xxx_MASK_SYS_MASK_3_M_SG_STAT		BIT(2)
+#define DA9xxx_MASK_SYS_MASK_3_M_PG2_STAT		BIT(1)
+#define DA9121_MASK_SYS_MASK_3_M_PG1_STAT		BIT(0)
+
+/* DA9121_REG_SYS_CONFIG_2 */
+
+#define DA9121_MASK_SYS_CONFIG_2_OC_LATCHOFF		0x60
+#define DA9121_MASK_SYS_CONFIG_2_OC_DVC_MASK		BIT(4)
+#define DA9121_MASK_SYS_CONFIG_2_PG_DVC_MASK		0xC0
+
+/* DA9121_REG_SYS_CONFIG_3 */
+
+#define DA9121_MASK_SYS_CONFIG_3_OSC_TUNE		0X70
+#define DA9121_MASK_SYS_CONFIG_3_I2C_TIMEOUT		BIT(1)
+
+/* DA9121_REG_SYS_GPIO0_0 */
+
+#define DA9121_MASK_SYS_GPIO0_0_GPIO0_MODE		0X1E
+#define DA9121_MASK_SYS_GPIO0_0_GPIO0_OBUF		BIT(0)
+
+/* DA9121_REG_SYS_GPIO0_1 */
+
+#define DA9121_MASK_SYS_GPIO0_1_GPIO0_DEB_FALL		BIT(7)
+#define DA9121_MASK_SYS_GPIO0_1_GPIO0_DEB_RISE		BIT(6)
+#define DA9121_MASK_SYS_GPIO0_1_GPIO0_DEB		0x30
+#define DA9121_MASK_SYS_GPIO0_1_GPIO0_PUPD		BIT(3)
+#define DA9121_MASK_SYS_GPIO0_1_GPIO0_POL		BIT(2)
+#define DA9121_MASK_SYS_GPIO0_1_GPIO0_TRIG		0x03
+
+/* DA9121_REG_SYS_GPIO1_0 */
+
+#define DA9121_MASK_SYS_GPIO1_0_GPIO1_MODE		0x1E
+#define DA9121_MASK_SYS_GPIO1_0_GPIO1_OBUF		BIT(0)
+
+/* DA9121_REG_SYS_GPIO1_1 */
+
+#define DA9121_MASK_SYS_GPIO1_1_GPIO1_DEB_FALL		BIT(7)
+#define DA9121_MASK_SYS_GPIO1_1_GPIO1_DEB_RISE		BIT(6)
+#define DA9121_MASK_SYS_GPIO1_1_GPIO1_DEB		0x30
+#define DA9121_MASK_SYS_GPIO1_1_GPIO1_PUPD		BIT(3)
+#define DA9121_MASK_SYS_GPIO1_1_GPIO1_POL		BIT(2)
+#define DA9121_MASK_SYS_GPIO1_1_GPIO1_TRIG		0x03
+
+/* DA9121_REG_SYS_GPIO2_0 */
+
+#define DA9121_MASK_SYS_GPIO2_0_GPIO2_MODE		0x1E
+#define DA9121_MASK_SYS_GPIO2_0_GPIO2_OBUF		BIT(0)
+
+/* DA9121_REG_SYS_GPIO2_1 */
+
+#define DA9121_MASK_SYS_GPIO2_1_GPIO2_DEB_FALL		BIT(7)
+#define DA9121_MASK_SYS_GPIO2_1_GPIO2_DEB_RISE		BIT(6)
+#define DA9121_MASK_SYS_GPIO2_1_GPIO2_DEB		0x30
+#define DA9121_MASK_SYS_GPIO2_1_GPIO2_PUPD		BIT(3)
+#define DA9121_MASK_SYS_GPIO2_1_GPIO2_POL		BIT(2)
+#define DA9121_MASK_SYS_GPIO2_1_GPIO2_TRIG		0x03
+
+/* DA9121_REG_BUCK_BUCK1_0 / DA9xxx_REG_BUCK_BUCK2_0 */
+
+#define DA9121_MASK_BUCK_BUCKX_0_CHX_SR_DVC_DWN		0x70
+#define DA9121_MASK_BUCK_BUCKX_0_CHX_SR_DVC_UP		0x0E
+#define DA9121_MASK_BUCK_BUCKX_0_CHX_EN			BIT(0)
+
+/* DA9121_REG_BUCK_BUCK1_1 / DA9xxx_REG_BUCK_BUCK2_1 */
+
+#define DA9121_MASK_BUCK_BUCKX_1_CHX_SR_SHDN		0x70
+#define DA9121_MASK_BUCK_BUCKX_1_CHX_SR_STARTUP		0x0E
+#define DA9121_MASK_BUCK_BUCKX_1_CHX_PD_DIS		BIT(0)
+
+/* DA9121_REG_BUCK_BUCK1_2 / DA9xxx_REG_BUCK_BUCK2_2 */
+
+#define DA9121_MASK_BUCK_BUCKX_2_CHX_ILIM		0x0F
+
+/* DA9121_REG_BUCK_BUCK1_3 / DA9xxx_REG_BUCK_BUCK2_3 */
+
+#define DA9121_MASK_BUCK_BUCKX_3_CHX_VMAX		0xFF
+
+/* DA9121_REG_BUCK_BUCK1_4 / DA9xxx_REG_BUCK_BUCK2_4 */
+
+#define DA9121_MASK_BUCK_BUCKX_4_CHX_VSEL		BIT(4)
+#define DA9121_MASK_BUCK_BUCKX_4_CHX_B_MODE		0x0C
+#define DA9121_MASK_BUCK_BUCKX_4_CHX_A_MODE		0x03
+
+/* DA9121_REG_BUCK_BUCK1_5 / DA9xxx_REG_BUCK_BUCK2_5 */
+
+#define DA9121_MASK_BUCK_BUCKX_5_CHX_A_VOUT		0xFF
+
+/* DA9121_REG_BUCK_BUCK1_6 / DA9xxx_REG_BUCK_BUCK2_6 */
+
+#define DA9121_MASK_BUCK_BUCKX_6_CHX_B_VOUT		0xFF
+
+/* DA9121_REG_BUCK_BUCK1_7 / DA9xxx_REG_BUCK_BUCK2_7 */
+
+#define DA9xxx_MASK_BUCK_BUCKX_7_CHX_RIPPLE_CANCEL	0x03
+
+/* DA9121_REG_OTP_DEVICE_ID */
+
+#define DA9121_MASK_OTP_DEVICE_ID_DEV_ID		0xFF
+
+/* DA9121_REG_OTP_VARIANT_ID */
+
+#define DA9121_SHIFT_OTP_VARIANT_ID_MRC			4
+#define DA9121_MASK_OTP_VARIANT_ID_MRC			0xF0
+#define DA9121_SHIFT_OTP_VARIANT_ID_VRC			0
+#define DA9121_MASK_OTP_VARIANT_ID_VRC			0x0F
+
+/* DA9121_REG_OTP_CUSTOMER_ID */
+
+#define DA9121_MASK_OTP_CUSTOMER_ID_CUST_ID		0xFF
+
+/* DA9121_REG_OTP_CONFIG_ID */
+
+#define DA9121_MASK_OTP_CONFIG_ID_CONFIG_REV		0xFF
+
+#endif /* __DA9121_REGISTERS_H__ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/da9211-regulator.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/da9211-regulator.c
@@ -471,6 +471,12 @@
 
 	chip->chip_irq = i2c->irq;
 
+	ret = da9211_regulator_init(chip);
+	if (ret < 0) {
+		dev_err(chip->dev, "Failed to initialize regulator: %d\n", ret);
+		return ret;
+	}
+
 	if (chip->chip_irq != 0) {
 		ret = devm_request_threaded_irq(chip->dev, chip->chip_irq, NULL,
 					da9211_irq_handler,
@@ -485,11 +491,6 @@
 		dev_warn(chip->dev, "No IRQ configured\n");
 	}
 
-	ret = da9211_regulator_init(chip);
-
-	if (ret < 0)
-		dev_err(chip->dev, "Failed to initialize regulator: %d\n", ret);
-
 	return ret;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/fan53555.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/fan53555.c
@@ -8,18 +8,19 @@
 // Copyright (c) 2012 Marvell Technology Ltd.
 // Yunfan Zhang <yfzhang@marvell.com>
 
+#include <linux/bits.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
 #include <linux/module.h>
+#include <linux/of_device.h>
 #include <linux/param.h>
-#include <linux/err.h>
 #include <linux/platform_device.h>
+#include <linux/regmap.h>
 #include <linux/regulator/driver.h>
+#include <linux/regulator/fan53555.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/of_regulator.h>
-#include <linux/of_device.h>
-#include <linux/i2c.h>
 #include <linux/slab.h>
-#include <linux/regmap.h>
-#include <linux/regulator/fan53555.h>
 
 /* Voltage setting */
 #define FAN53555_VSEL0		0x00
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/fixed.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/fixed.c
@@ -181,8 +181,8 @@
 
 		drvdata->enable_clock = devm_clk_get(dev, NULL);
 		if (IS_ERR(drvdata->enable_clock)) {
-			dev_err(dev, "Cant get enable-clock from devicetree\n");
-			return -ENOENT;
+			dev_err(dev, "Can't get enable-clock from devicetree\n");
+			return PTR_ERR(drvdata->enable_clock);
 		}
 	} else {
 		drvdata->desc.ops = &fixed_voltage_ops;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/helpers.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/helpers.c
@@ -13,6 +13,8 @@
 #include <linux/regulator/driver.h>
 #include <linux/module.h>
 
+#include "internal.h"
+
 /**
  * regulator_is_enabled_regmap - standard is_enabled() for regmap users
  *
@@ -881,3 +883,15 @@
 		consumers[i].supply = supply_names[i];
 }
 EXPORT_SYMBOL_GPL(regulator_bulk_set_supply_names);
+
+/**
+ * regulator_is_equal - test whether two regulators are the same
+ *
+ * @reg1: first regulator to operate on
+ * @reg2: second regulator to operate on
+ */
+bool regulator_is_equal(struct regulator *reg1, struct regulator *reg2)
+{
+	return reg1->rdev == reg2->rdev;
+}
+EXPORT_SYMBOL_GPL(regulator_is_equal);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/hi6421-regulator.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/hi6421-regulator.c
@@ -366,9 +366,8 @@
 
 static int hi6421_regulator_enable(struct regulator_dev *rdev)
 {
-	struct hi6421_regulator_pdata *pdata;
+	struct hi6421_regulator_pdata *pdata = rdev_get_drvdata(rdev);
 
-	pdata = dev_get_drvdata(rdev->dev.parent);
 	/* hi6421 spec requires regulator enablement must be serialized:
 	 *  - Because when BUCK, LDO switching from off to on, it will have
 	 *    a huge instantaneous current; so you can not turn on two or
@@ -385,9 +384,10 @@
 
 static unsigned int hi6421_regulator_ldo_get_mode(struct regulator_dev *rdev)
 {
-	struct hi6421_regulator_info *info = rdev_get_drvdata(rdev);
-	u32 reg_val;
+	struct hi6421_regulator_info *info;
+	unsigned int reg_val;
 
+	info = container_of(rdev->desc, struct hi6421_regulator_info, desc);
 	regmap_read(rdev->regmap, rdev->desc->enable_reg, &reg_val);
 	if (reg_val & info->mode_mask)
 		return REGULATOR_MODE_IDLE;
@@ -397,9 +397,10 @@
 
 static unsigned int hi6421_regulator_buck_get_mode(struct regulator_dev *rdev)
 {
-	struct hi6421_regulator_info *info = rdev_get_drvdata(rdev);
-	u32 reg_val;
+	struct hi6421_regulator_info *info;
+	unsigned int reg_val;
 
+	info = container_of(rdev->desc, struct hi6421_regulator_info, desc);
 	regmap_read(rdev->regmap, rdev->desc->enable_reg, &reg_val);
 	if (reg_val & info->mode_mask)
 		return REGULATOR_MODE_STANDBY;
@@ -410,9 +411,10 @@
 static int hi6421_regulator_ldo_set_mode(struct regulator_dev *rdev,
 						unsigned int mode)
 {
-	struct hi6421_regulator_info *info = rdev_get_drvdata(rdev);
-	u32 new_mode;
+	struct hi6421_regulator_info *info;
+	unsigned int new_mode;
 
+	info = container_of(rdev->desc, struct hi6421_regulator_info, desc);
 	switch (mode) {
 	case REGULATOR_MODE_NORMAL:
 		new_mode = 0;
@@ -434,9 +436,10 @@
 static int hi6421_regulator_buck_set_mode(struct regulator_dev *rdev,
 						unsigned int mode)
 {
-	struct hi6421_regulator_info *info = rdev_get_drvdata(rdev);
-	u32 new_mode;
+	struct hi6421_regulator_info *info;
+	unsigned int new_mode;
 
+	info = container_of(rdev->desc, struct hi6421_regulator_info, desc);
 	switch (mode) {
 	case REGULATOR_MODE_NORMAL:
 		new_mode = 0;
@@ -459,7 +462,9 @@
 hi6421_regulator_ldo_get_optimum_mode(struct regulator_dev *rdev,
 			int input_uV, int output_uV, int load_uA)
 {
-	struct hi6421_regulator_info *info = rdev_get_drvdata(rdev);
+	struct hi6421_regulator_info *info;
+
+	info = container_of(rdev->desc, struct hi6421_regulator_info, desc);
 
 	if (load_uA > info->eco_microamp)
 		return REGULATOR_MODE_NORMAL;
@@ -543,14 +548,13 @@
 	if (!pdata)
 		return -ENOMEM;
 	mutex_init(&pdata->lock);
-	platform_set_drvdata(pdev, pdata);
 
 	for (i = 0; i < ARRAY_SIZE(hi6421_regulator_info); i++) {
 		/* assign per-regulator data */
 		info = &hi6421_regulator_info[i];
 
 		config.dev = pdev->dev.parent;
-		config.driver_data = info;
+		config.driver_data = pdata;
 		config.regmap = pmic->regmap;
 
 		rdev = devm_regulator_register(&pdev->dev, &info->desc,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/hi655x-regulator.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/hi655x-regulator.c
@@ -72,7 +72,7 @@
 static int hi655x_is_enabled(struct regulator_dev *rdev)
 {
 	unsigned int value = 0;
-	struct hi655x_regulator *regulator = rdev_get_drvdata(rdev);
+	const struct hi655x_regulator *regulator = rdev_get_drvdata(rdev);
 
 	regmap_read(rdev->regmap, regulator->status_reg, &value);
 	return (value & rdev->desc->enable_mask);
@@ -80,7 +80,7 @@
 
 static int hi655x_disable(struct regulator_dev *rdev)
 {
-	struct hi655x_regulator *regulator = rdev_get_drvdata(rdev);
+	const struct hi655x_regulator *regulator = rdev_get_drvdata(rdev);
 
 	return regmap_write(rdev->regmap, regulator->disable_reg,
 			    rdev->desc->enable_mask);
@@ -169,7 +169,6 @@
 static int hi655x_regulator_probe(struct platform_device *pdev)
 {
 	unsigned int i;
-	struct hi655x_regulator *regulator;
 	struct hi655x_pmic *pmic;
 	struct regulator_config config = { };
 	struct regulator_dev *rdev;
@@ -180,22 +179,17 @@
 		return -ENODEV;
 	}
 
-	regulator = devm_kzalloc(&pdev->dev, sizeof(*regulator), GFP_KERNEL);
-	if (!regulator)
-		return -ENOMEM;
-
-	platform_set_drvdata(pdev, regulator);
-
 	config.dev = pdev->dev.parent;
 	config.regmap = pmic->regmap;
-	config.driver_data = regulator;
 	for (i = 0; i < ARRAY_SIZE(regulators); i++) {
+		config.driver_data = (void *) &regulators[i];
+
 		rdev = devm_regulator_register(&pdev->dev,
 					       &regulators[i].rdesc,
 					       &config);
 		if (IS_ERR(rdev)) {
 			dev_err(&pdev->dev, "failed to register regulator %s\n",
-				regulator->rdesc.name);
+				regulators[i].rdesc.name);
 			return PTR_ERR(rdev);
 		}
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/max77620-regulator.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/max77620-regulator.c
@@ -814,6 +814,13 @@
 	config.dev = dev;
 	config.driver_data = pmic;
 
+	/*
+	 * Set of_node_reuse flag to prevent driver core from attempting to
+	 * claim any pinmux resources already claimed by the parent device.
+	 * Otherwise PMIC driver will fail to re-probe.
+	 */
+	device_set_of_node_from_dev(&pdev->dev, pdev->dev.parent);
+
 	for (id = 0; id < MAX77620_NUM_REGS; id++) {
 		struct regulator_dev *rdev;
 		struct regulator_desc *rdesc;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/max77802-regulator.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/max77802-regulator.c
@@ -95,9 +95,11 @@
 {
 	unsigned int val = MAX77802_OFF_PWRREQ;
 	struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
-	int id = rdev_get_id(rdev);
+	unsigned int id = rdev_get_id(rdev);
 	int shift = max77802_get_opmode_shift(id);
 
+	if (WARN_ON_ONCE(id >= ARRAY_SIZE(max77802->opmode)))
+		return -EINVAL;
 	max77802->opmode[id] = val;
 	return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
 				  rdev->desc->enable_mask, val << shift);
@@ -111,7 +113,7 @@
 static int max77802_set_mode(struct regulator_dev *rdev, unsigned int mode)
 {
 	struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
-	int id = rdev_get_id(rdev);
+	unsigned int id = rdev_get_id(rdev);
 	unsigned int val;
 	int shift = max77802_get_opmode_shift(id);
 
@@ -128,6 +130,9 @@
 		return -EINVAL;
 	}
 
+	if (WARN_ON_ONCE(id >= ARRAY_SIZE(max77802->opmode)))
+		return -EINVAL;
+
 	max77802->opmode[id] = val;
 	return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
 				  rdev->desc->enable_mask, val << shift);
@@ -136,8 +141,10 @@
 static unsigned max77802_get_mode(struct regulator_dev *rdev)
 {
 	struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
-	int id = rdev_get_id(rdev);
+	unsigned int id = rdev_get_id(rdev);
 
+	if (WARN_ON_ONCE(id >= ARRAY_SIZE(max77802->opmode)))
+		return -EINVAL;
 	return max77802_map_mode(max77802->opmode[id]);
 }
 
@@ -161,10 +168,13 @@
 				     unsigned int mode)
 {
 	struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
-	int id = rdev_get_id(rdev);
+	unsigned int id = rdev_get_id(rdev);
 	unsigned int val;
 	int shift = max77802_get_opmode_shift(id);
 
+	if (WARN_ON_ONCE(id >= ARRAY_SIZE(max77802->opmode)))
+		return -EINVAL;
+
 	/*
 	 * If the regulator has been disabled for suspend
 	 * then is invalid to try setting a suspend mode.
@@ -210,9 +220,11 @@
 static int max77802_enable(struct regulator_dev *rdev)
 {
 	struct max77802_regulator_prv *max77802 = rdev_get_drvdata(rdev);
-	int id = rdev_get_id(rdev);
+	unsigned int id = rdev_get_id(rdev);
 	int shift = max77802_get_opmode_shift(id);
 
+	if (WARN_ON_ONCE(id >= ARRAY_SIZE(max77802->opmode)))
+		return -EINVAL;
 	if (max77802->opmode[id] == MAX77802_OFF_PWRREQ)
 		max77802->opmode[id] = MAX77802_OPMODE_NORMAL;
 
@@ -541,7 +553,7 @@
 
 	for (i = 0; i < MAX77802_REG_MAX; i++) {
 		struct regulator_dev *rdev;
-		int id = regulators[i].id;
+		unsigned int id = regulators[i].id;
 		int shift = max77802_get_opmode_shift(id);
 		int ret;
 
@@ -559,10 +571,12 @@
 		 * the hardware reports OFF as the regulator operating mode.
 		 * Default to operating mode NORMAL in that case.
 		 */
-		if (val == MAX77802_STATUS_OFF)
-			max77802->opmode[id] = MAX77802_OPMODE_NORMAL;
-		else
-			max77802->opmode[id] = val;
+		if (id < ARRAY_SIZE(max77802->opmode)) {
+			if (val == MAX77802_STATUS_OFF)
+				max77802->opmode[id] = MAX77802_OPMODE_NORMAL;
+			else
+				max77802->opmode[id] = val;
+		}
 
 		rdev = devm_regulator_register(&pdev->dev,
 					       &regulators[i], &config);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/max8907-regulator.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/max8907-regulator.c
@@ -296,7 +296,10 @@
 	memcpy(pmic->desc, max8907_regulators, sizeof(pmic->desc));
 
 	/* Backwards compatibility with MAX8907B; SD1 uses different voltages */
-	regmap_read(max8907->regmap_gen, MAX8907_REG_II2RR, &val);
+	ret = regmap_read(max8907->regmap_gen, MAX8907_REG_II2RR, &val);
+	if (ret)
+		return ret;
+
 	if ((val & MAX8907_II2RR_VERSION_MASK) ==
 	    MAX8907_II2RR_VERSION_REV_B) {
 		pmic->desc[MAX8907_SD1].min_uV = 637500;
@@ -333,14 +336,20 @@
 		}
 
 		if (pmic->desc[i].ops == &max8907_ldo_ops) {
-			regmap_read(config.regmap, pmic->desc[i].enable_reg,
+			ret = regmap_read(config.regmap, pmic->desc[i].enable_reg,
 				    &val);
+			if (ret)
+				return ret;
+
 			if ((val & MAX8907_MASK_LDO_SEQ) !=
 			    MAX8907_MASK_LDO_SEQ)
 				pmic->desc[i].ops = &max8907_ldo_hwctl_ops;
 		} else if (pmic->desc[i].ops == &max8907_out5v_ops) {
-			regmap_read(config.regmap, pmic->desc[i].enable_reg,
+			ret = regmap_read(config.regmap, pmic->desc[i].enable_reg,
 				    &val);
+			if (ret)
+				return ret;
+
 			if ((val & (MAX8907_MASK_OUT5V_VINEN |
 						MAX8907_MASK_OUT5V_ENSRC)) !=
 			    MAX8907_MASK_OUT5V_ENSRC)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/mt6358-regulator.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/mt6358-regulator.c
@@ -457,7 +457,7 @@
 	MT6358_REG_FIXED("ldo_vaud28", VAUD28,
 			 MT6358_LDO_VAUD28_CON0, 0, 2800000),
 	MT6358_LDO("ldo_vdram2", VDRAM2, vdram2_voltages, vdram2_idx,
-		   MT6358_LDO_VDRAM2_CON0, 0, MT6358_LDO_VDRAM2_ELR0, 0x10, 0),
+		   MT6358_LDO_VDRAM2_CON0, 0, MT6358_LDO_VDRAM2_ELR0, 0xf, 0),
 	MT6358_LDO("ldo_vsim1", VSIM1, vsim_voltages, vsim_idx,
 		   MT6358_LDO_VSIM1_CON0, 0, MT6358_VSIM1_ANA_CON0, 0xf00, 8),
 	MT6358_LDO("ldo_vibr", VIBR, vibr_voltages, vibr_idx,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/of_regulator.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/of_regulator.c
@@ -206,8 +206,12 @@
 		}
 
 		suspend_np = of_get_child_by_name(np, regulator_states[i]);
-		if (!suspend_np || !suspend_state)
+		if (!suspend_np)
 			continue;
+		if (!suspend_state) {
+			of_node_put(suspend_np);
+			continue;
+		}
 
 		if (!of_property_read_u32(suspend_np, "regulator-mode",
 					  &pval)) {
@@ -373,7 +377,7 @@
 					"failed to parse DT for regulator %pOFn\n",
 					child);
 				of_node_put(child);
-				return -EINVAL;
+				goto err_put;
 			}
 			match->of_node = of_node_get(child);
 			count++;
@@ -382,6 +386,18 @@
 	}
 
 	return count;
+
+err_put:
+	for (i = 0; i < num_matches; i++) {
+		struct of_regulator_match *match = &matches[i];
+
+		match->init_data = NULL;
+		if (match->of_node) {
+			of_node_put(match->of_node);
+			match->of_node = NULL;
+		}
+	}
+	return -EINVAL;
 }
 EXPORT_SYMBOL_GPL(of_regulator_match);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/pfuze100-regulator.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/pfuze100-regulator.c
@@ -209,6 +209,19 @@
 
 };
 
+static const struct regulator_ops pfuze3000_sw_regulator_ops = {
+	.enable = regulator_enable_regmap,
+	.disable = regulator_disable_regmap,
+	.is_enabled = regulator_is_enabled_regmap,
+	.list_voltage = regulator_list_voltage_table,
+	.map_voltage = regulator_map_voltage_ascend,
+	.set_voltage_sel = regulator_set_voltage_sel_regmap,
+	.get_voltage_sel = regulator_get_voltage_sel_regmap,
+	.set_voltage_time_sel = regulator_set_voltage_time_sel,
+	.set_ramp_delay = pfuze100_set_ramp_delay,
+
+};
+
 #define PFUZE100_FIXED_REG(_chip, _name, base, voltage)	\
 	[_chip ## _ ## _name] = {	\
 		.desc = {	\
@@ -318,23 +331,28 @@
 	.stby_mask = 0x20,	\
 }
 
-
-#define PFUZE3000_SW2_REG(_chip, _name, base, min, max, step)	{	\
-	.desc = {	\
-		.name = #_name,\
-		.n_voltages = ((max) - (min)) / (step) + 1,	\
-		.ops = &pfuze100_sw_regulator_ops,	\
-		.type = REGULATOR_VOLTAGE,	\
-		.id = _chip ## _ ## _name,	\
-		.owner = THIS_MODULE,	\
-		.min_uV = (min),	\
-		.uV_step = (step),	\
-		.vsel_reg = (base) + PFUZE100_VOL_OFFSET,	\
-		.vsel_mask = 0x7,	\
-	},	\
-	.stby_reg = (base) + PFUZE100_STANDBY_OFFSET,	\
-	.stby_mask = 0x7,	\
-}
+/* No linar case for the some switches of PFUZE3000 */
+#define PFUZE3000_SW_REG(_chip, _name, base, mask, voltages)	\
+	[_chip ## _ ##  _name] = {	\
+		.desc = {	\
+			.name = #_name,	\
+			.n_voltages = ARRAY_SIZE(voltages),	\
+			.ops = &pfuze3000_sw_regulator_ops,	\
+			.type = REGULATOR_VOLTAGE,	\
+			.id = _chip ## _ ## _name,	\
+			.owner = THIS_MODULE,	\
+			.volt_table = voltages,	\
+			.vsel_reg = (base) + PFUZE100_VOL_OFFSET,	\
+			.vsel_mask = (mask),	\
+			.enable_reg = (base) + PFUZE100_MODE_OFFSET,	\
+			.enable_mask = 0xf,	\
+			.enable_val = 0x8,	\
+			.enable_time = 500,	\
+		},	\
+		.stby_reg = (base) + PFUZE100_STANDBY_OFFSET,	\
+		.stby_mask = (mask),	\
+		.sw_reg = true,		\
+	}
 
 #define PFUZE3000_SW3_REG(_chip, _name, base, min, max, step)	{	\
 	.desc = {	\
@@ -391,9 +409,9 @@
 };
 
 static struct pfuze_regulator pfuze3000_regulators[] = {
-	PFUZE100_SWB_REG(PFUZE3000, SW1A, PFUZE100_SW1ABVOL, 0x1f, pfuze3000_sw1a),
+	PFUZE3000_SW_REG(PFUZE3000, SW1A, PFUZE100_SW1ABVOL, 0x1f, pfuze3000_sw1a),
 	PFUZE100_SW_REG(PFUZE3000, SW1B, PFUZE100_SW1CVOL, 700000, 1475000, 25000),
-	PFUZE100_SWB_REG(PFUZE3000, SW2, PFUZE100_SW2VOL, 0x7, pfuze3000_sw2lo),
+	PFUZE3000_SW_REG(PFUZE3000, SW2, PFUZE100_SW2VOL, 0x7, pfuze3000_sw2lo),
 	PFUZE3000_SW3_REG(PFUZE3000, SW3, PFUZE100_SW3AVOL, 900000, 1650000, 50000),
 	PFUZE100_SWB_REG(PFUZE3000, SWBST, PFUZE100_SWBSTCON1, 0x3, pfuze100_swbst),
 	PFUZE100_SWB_REG(PFUZE3000, VSNVS, PFUZE100_VSNVSVOL, 0x7, pfuze100_vsnvs),
@@ -407,8 +425,8 @@
 };
 
 static struct pfuze_regulator pfuze3001_regulators[] = {
-	PFUZE100_SWB_REG(PFUZE3001, SW1, PFUZE100_SW1ABVOL, 0x1f, pfuze3000_sw1a),
-	PFUZE100_SWB_REG(PFUZE3001, SW2, PFUZE100_SW2VOL, 0x7, pfuze3000_sw2lo),
+	PFUZE3000_SW_REG(PFUZE3001, SW1, PFUZE100_SW1ABVOL, 0x1f, pfuze3000_sw1a),
+	PFUZE3000_SW_REG(PFUZE3001, SW2, PFUZE100_SW2VOL, 0x7, pfuze3000_sw2lo),
 	PFUZE3000_SW3_REG(PFUZE3001, SW3, PFUZE100_SW3AVOL, 900000, 1650000, 50000),
 	PFUZE100_SWB_REG(PFUZE3001, VSNVS, PFUZE100_VSNVSVOL, 0x7, pfuze100_vsnvs),
 	PFUZE100_VGEN_REG(PFUZE3001, VLDO1, PFUZE100_VGEN1VOL, 1800000, 3300000, 100000),
@@ -510,6 +528,7 @@
 	parent = of_get_child_by_name(np, "regulators");
 	if (!parent) {
 		dev_err(dev, "regulators node not found\n");
+		of_node_put(np);
 		return -EINVAL;
 	}
 
@@ -539,6 +558,7 @@
 	}
 
 	of_node_put(parent);
+	of_node_put(np);
 	if (ret < 0) {
 		dev_err(dev, "Error parsing regulator init data: %d\n",
 			ret);
@@ -768,7 +788,7 @@
 		((pfuze_chip->chip_id == PFUZE3000) ? "3000" : "3001"))));
 
 	memcpy(pfuze_chip->regulator_descs, pfuze_chip->pfuze_regulators,
-		sizeof(pfuze_chip->regulator_descs));
+		regulator_num * sizeof(struct pfuze_regulator));
 
 	ret = pfuze_parse_regulators_dt(pfuze_chip);
 	if (ret)
@@ -815,11 +835,14 @@
 		 * the switched regulator till yet.
 		 */
 		if (pfuze_chip->flags & PFUZE_FLAG_DISABLE_SW) {
-			if (pfuze_chip->regulator_descs[i].sw_reg) {
-				desc->ops = &pfuze100_sw_disable_regulator_ops;
-				desc->enable_val = 0x8;
-				desc->disable_val = 0x0;
-				desc->enable_time = 500;
+			if (pfuze_chip->chip_id == PFUZE100 ||
+				pfuze_chip->chip_id == PFUZE200) {
+				if (pfuze_chip->regulator_descs[i].sw_reg) {
+					desc->ops = &pfuze100_sw_disable_regulator_ops;
+					desc->enable_val = 0x8;
+					desc->disable_val = 0x0;
+					desc->enable_time = 500;
+				}
 			}
 		}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/pwm-regulator.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/pwm-regulator.c
@@ -158,6 +158,9 @@
 	pwm_get_state(drvdata->pwm, &pstate);
 
 	voltage = pwm_get_relative_duty_cycle(&pstate, duty_unit);
+	if (voltage < min(max_uV_duty, min_uV_duty) ||
+	    voltage > max(max_uV_duty, min_uV_duty))
+		return -ENOTRECOVERABLE;
 
 	/*
 	 * The dutycycle for min_uV might be greater than the one for max_uV.
@@ -279,7 +282,7 @@
 		return ret;
 	}
 
-	drvdata->state			= -EINVAL;
+	drvdata->state			= -ENOTRECOVERABLE;
 	drvdata->duty_cycle_table	= duty_cycle_table;
 	drvdata->desc.ops = &pwm_regulator_voltage_table_ops;
 	drvdata->desc.n_voltages	= length / sizeof(*duty_cycle_table);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/qcom-rpmh-regulator.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/qcom-rpmh-regulator.c
@@ -726,8 +726,8 @@
 static const struct rpmh_vreg_hw_data pmic5_hfsmps515 = {
 	.regulator_type = VRM,
 	.ops = &rpmh_regulator_vrm_ops,
-	.voltage_range = REGULATOR_LINEAR_RANGE(2800000, 0, 4, 1600),
-	.n_voltages = 5,
+	.voltage_range = REGULATOR_LINEAR_RANGE(320000, 0, 235, 16000),
+	.n_voltages = 236,
 	.pmic_mode_map = pmic_mode_map_pmic5_smps,
 	.of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode,
 };
@@ -832,11 +832,11 @@
 	RPMH_VREG("ldo10",  "ldo%s10", &pmic5_pldo,      "vdd-l2-l10"),
 	RPMH_VREG("ldo11",  "ldo%s11", &pmic5_nldo,      "vdd-l1-l8-l11"),
 	RPMH_VREG("ldo12",  "ldo%s12", &pmic5_pldo_lv,   "vdd-l7-l12-l14-l15"),
-	RPMH_VREG("ldo13",  "ldo%s13", &pmic5_pldo,      "vdd-l13-l6-l17"),
+	RPMH_VREG("ldo13",  "ldo%s13", &pmic5_pldo,      "vdd-l13-l16-l17"),
 	RPMH_VREG("ldo14",  "ldo%s14", &pmic5_pldo_lv,   "vdd-l7-l12-l14-l15"),
 	RPMH_VREG("ldo15",  "ldo%s15", &pmic5_pldo_lv,   "vdd-l7-l12-l14-l15"),
-	RPMH_VREG("ldo16",  "ldo%s16", &pmic5_pldo,      "vdd-l13-l6-l17"),
-	RPMH_VREG("ldo17",  "ldo%s17", &pmic5_pldo,      "vdd-l13-l6-l17"),
+	RPMH_VREG("ldo16",  "ldo%s16", &pmic5_pldo,      "vdd-l13-l16-l17"),
+	RPMH_VREG("ldo17",  "ldo%s17", &pmic5_pldo,      "vdd-l13-l16-l17"),
 	RPMH_VREG("ldo18",  "ldo%s18", &pmic5_nldo,      "vdd-l3-l4-l5-l18"),
 	{},
 };
@@ -857,7 +857,7 @@
 	RPMH_VREG("ldo5",   "ldo%s5",  &pmic5_pldo,      "vdd-l4-l5-l6"),
 	RPMH_VREG("ldo6",   "ldo%s6",  &pmic5_pldo,      "vdd-l4-l5-l6"),
 	RPMH_VREG("ldo7",   "ldo%s7",  &pmic5_pldo,      "vdd-l7-l11"),
-	RPMH_VREG("ldo8",   "ldo%s8",  &pmic5_pldo_lv,   "vdd-l1-l8-l11"),
+	RPMH_VREG("ldo8",   "ldo%s8",  &pmic5_pldo_lv,   "vdd-l1-l8"),
 	RPMH_VREG("ldo9",   "ldo%s9",  &pmic5_pldo,      "vdd-l9-l10"),
 	RPMH_VREG("ldo10",  "ldo%s10", &pmic5_pldo,      "vdd-l9-l10"),
 	RPMH_VREG("ldo11",  "ldo%s11", &pmic5_pldo,      "vdd-l7-l11"),
@@ -874,7 +874,7 @@
 	RPMH_VREG("ldo4",   "ldo%s4",  &pmic5_nldo,      "vdd-l4"),
 	RPMH_VREG("ldo5",   "ldo%s5",  &pmic5_pldo,      "vdd-l5-l6"),
 	RPMH_VREG("ldo6",   "ldo%s6",  &pmic5_pldo,      "vdd-l5-l6"),
-	RPMH_VREG("ldo7",   "ldo%s6",  &pmic5_pldo_lv,   "vdd-l7"),
+	RPMH_VREG("ldo7",   "ldo%s7",  &pmic5_pldo_lv,   "vdd-l7"),
 	{},
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/qcom_rpm-regulator.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/qcom_rpm-regulator.c
@@ -812,6 +812,12 @@
 };
 
 static const struct rpm_regulator_data rpm_pm8058_regulators[] = {
+	{ "s0",   QCOM_RPM_PM8058_SMPS0,  &pm8058_smps, "vdd_s0" },
+	{ "s1",   QCOM_RPM_PM8058_SMPS1,  &pm8058_smps, "vdd_s1" },
+	{ "s2",   QCOM_RPM_PM8058_SMPS2,  &pm8058_smps, "vdd_s2" },
+	{ "s3",   QCOM_RPM_PM8058_SMPS3,  &pm8058_smps, "vdd_s3" },
+	{ "s4",   QCOM_RPM_PM8058_SMPS4,  &pm8058_smps, "vdd_s4" },
+
 	{ "l0",   QCOM_RPM_PM8058_LDO0,   &pm8058_nldo, "vdd_l0_l1_lvs"	},
 	{ "l1",   QCOM_RPM_PM8058_LDO1,   &pm8058_nldo, "vdd_l0_l1_lvs" },
 	{ "l2",   QCOM_RPM_PM8058_LDO2,   &pm8058_pldo, "vdd_l2_l11_l12" },
@@ -839,12 +845,6 @@
 	{ "l24",  QCOM_RPM_PM8058_LDO24,  &pm8058_nldo, "vdd_l23_l24_l25" },
 	{ "l25",  QCOM_RPM_PM8058_LDO25,  &pm8058_nldo, "vdd_l23_l24_l25" },
 
-	{ "s0",   QCOM_RPM_PM8058_SMPS0,  &pm8058_smps, "vdd_s0" },
-	{ "s1",   QCOM_RPM_PM8058_SMPS1,  &pm8058_smps, "vdd_s1" },
-	{ "s2",   QCOM_RPM_PM8058_SMPS2,  &pm8058_smps, "vdd_s2" },
-	{ "s3",   QCOM_RPM_PM8058_SMPS3,  &pm8058_smps, "vdd_s3" },
-	{ "s4",   QCOM_RPM_PM8058_SMPS4,  &pm8058_smps, "vdd_s4" },
-
 	{ "lvs0", QCOM_RPM_PM8058_LVS0, &pm8058_switch, "vdd_l0_l1_lvs" },
 	{ "lvs1", QCOM_RPM_PM8058_LVS1, &pm8058_switch, "vdd_l0_l1_lvs" },
 
@@ -853,6 +853,12 @@
 };
 
 static const struct rpm_regulator_data rpm_pm8901_regulators[] = {
+	{ "s0",   QCOM_RPM_PM8901_SMPS0, &pm8901_ftsmps, "vdd_s0" },
+	{ "s1",   QCOM_RPM_PM8901_SMPS1, &pm8901_ftsmps, "vdd_s1" },
+	{ "s2",   QCOM_RPM_PM8901_SMPS2, &pm8901_ftsmps, "vdd_s2" },
+	{ "s3",   QCOM_RPM_PM8901_SMPS3, &pm8901_ftsmps, "vdd_s3" },
+	{ "s4",   QCOM_RPM_PM8901_SMPS4, &pm8901_ftsmps, "vdd_s4" },
+
 	{ "l0",   QCOM_RPM_PM8901_LDO0, &pm8901_nldo, "vdd_l0" },
 	{ "l1",   QCOM_RPM_PM8901_LDO1, &pm8901_pldo, "vdd_l1" },
 	{ "l2",   QCOM_RPM_PM8901_LDO2, &pm8901_pldo, "vdd_l2" },
@@ -861,12 +867,6 @@
 	{ "l5",   QCOM_RPM_PM8901_LDO5, &pm8901_pldo, "vdd_l5" },
 	{ "l6",   QCOM_RPM_PM8901_LDO6, &pm8901_pldo, "vdd_l6" },
 
-	{ "s0",   QCOM_RPM_PM8901_SMPS0, &pm8901_ftsmps, "vdd_s0" },
-	{ "s1",   QCOM_RPM_PM8901_SMPS1, &pm8901_ftsmps, "vdd_s1" },
-	{ "s2",   QCOM_RPM_PM8901_SMPS2, &pm8901_ftsmps, "vdd_s2" },
-	{ "s3",   QCOM_RPM_PM8901_SMPS3, &pm8901_ftsmps, "vdd_s3" },
-	{ "s4",   QCOM_RPM_PM8901_SMPS4, &pm8901_ftsmps, "vdd_s4" },
-
 	{ "lvs0", QCOM_RPM_PM8901_LVS0, &pm8901_switch, "lvs0_in" },
 	{ "lvs1", QCOM_RPM_PM8901_LVS1, &pm8901_switch, "lvs1_in" },
 	{ "lvs2", QCOM_RPM_PM8901_LVS2, &pm8901_switch, "lvs2_in" },
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/qcom_smd-regulator.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/qcom_smd-regulator.c
@@ -9,6 +9,7 @@
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
 #include <linux/soc/qcom/smd-rpm.h>
 
 struct qcom_rpm_reg {
@@ -776,52 +777,93 @@
 };
 MODULE_DEVICE_TABLE(of, rpm_of_match);
 
-static int rpm_reg_probe(struct platform_device *pdev)
+/**
+ * rpm_regulator_init_vreg() - initialize all attributes of a qcom_smd-regulator
+ * @vreg:		Pointer to the individual qcom_smd-regulator resource
+ * @dev:		Pointer to the top level qcom_smd-regulator PMIC device
+ * @node:		Pointer to the individual qcom_smd-regulator resource
+ *			device node
+ * @rpm:		Pointer to the rpm bus node
+ * @pmic_rpm_data:	Pointer to a null-terminated array of qcom_smd-regulator
+ *			resources defined for the top level PMIC device
+ *
+ * Return: 0 on success, errno on failure
+ */
+static int rpm_regulator_init_vreg(struct qcom_rpm_reg *vreg, struct device *dev,
+				   struct device_node *node, struct qcom_smd_rpm *rpm,
+				   const struct rpm_regulator_data *pmic_rpm_data)
 {
-	const struct rpm_regulator_data *reg;
-	const struct of_device_id *match;
-	struct regulator_config config = { };
+	struct regulator_config config = {};
+	const struct rpm_regulator_data *rpm_data;
 	struct regulator_dev *rdev;
+	int ret;
+
+	for (rpm_data = pmic_rpm_data; rpm_data->name; rpm_data++)
+		if (of_node_name_eq(node, rpm_data->name))
+			break;
+
+	if (!rpm_data->name) {
+		dev_err(dev, "Unknown regulator %pOFn\n", node);
+		return -EINVAL;
+	}
+
+	vreg->dev	= dev;
+	vreg->rpm	= rpm;
+	vreg->type	= rpm_data->type;
+	vreg->id	= rpm_data->id;
+
+	memcpy(&vreg->desc, rpm_data->desc, sizeof(vreg->desc));
+	vreg->desc.name = rpm_data->name;
+	vreg->desc.supply_name = rpm_data->supply;
+	vreg->desc.owner = THIS_MODULE;
+	vreg->desc.type = REGULATOR_VOLTAGE;
+	vreg->desc.of_match = rpm_data->name;
+
+	config.dev		= dev;
+	config.of_node		= node;
+	config.driver_data	= vreg;
+
+	rdev = devm_regulator_register(dev, &vreg->desc, &config);
+	if (IS_ERR(rdev)) {
+		ret = PTR_ERR(rdev);
+		dev_err(dev, "%pOFn: devm_regulator_register() failed, ret=%d\n", node, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int rpm_reg_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	const struct rpm_regulator_data *vreg_data;
+	struct device_node *node;
 	struct qcom_rpm_reg *vreg;
 	struct qcom_smd_rpm *rpm;
+	int ret;
 
 	rpm = dev_get_drvdata(pdev->dev.parent);
 	if (!rpm) {
-		dev_err(&pdev->dev, "unable to retrieve handle to rpm\n");
+		dev_err(&pdev->dev, "Unable to retrieve handle to rpm\n");
 		return -ENODEV;
 	}
 
-	match = of_match_device(rpm_of_match, &pdev->dev);
-	if (!match) {
-		dev_err(&pdev->dev, "failed to match device\n");
+	vreg_data = of_device_get_match_data(dev);
+	if (!vreg_data)
 		return -ENODEV;
-	}
 
-	for (reg = match->data; reg->name; reg++) {
+	for_each_available_child_of_node(dev->of_node, node) {
 		vreg = devm_kzalloc(&pdev->dev, sizeof(*vreg), GFP_KERNEL);
-		if (!vreg)
+		if (!vreg) {
+			of_node_put(node);
 			return -ENOMEM;
+		}
+
+		ret = rpm_regulator_init_vreg(vreg, dev, node, rpm, vreg_data);
 
-		vreg->dev = &pdev->dev;
-		vreg->type = reg->type;
-		vreg->id = reg->id;
-		vreg->rpm = rpm;
-
-		memcpy(&vreg->desc, reg->desc, sizeof(vreg->desc));
-
-		vreg->desc.id = -1;
-		vreg->desc.owner = THIS_MODULE;
-		vreg->desc.type = REGULATOR_VOLTAGE;
-		vreg->desc.name = reg->name;
-		vreg->desc.supply_name = reg->supply;
-		vreg->desc.of_match = reg->name;
-
-		config.dev = &pdev->dev;
-		config.driver_data = vreg;
-		rdev = devm_regulator_register(&pdev->dev, &vreg->desc, &config);
-		if (IS_ERR(rdev)) {
-			dev_err(&pdev->dev, "failed to register %s\n", reg->name);
-			return PTR_ERR(rdev);
+		if (ret < 0) {
+			of_node_put(node);
+			return ret;
 		}
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/rk808-regulator.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/rk808-regulator.c
@@ -959,6 +959,8 @@
 		.n_linear_ranges = ARRAY_SIZE(rk817_buck1_voltage_ranges),
 		.vsel_reg = RK817_BUCK3_ON_VSEL_REG,
 		.vsel_mask = RK817_BUCK_VSEL_MASK,
+		.apply_reg = RK817_POWER_CONFIG,
+		.apply_bit = RK817_BUCK3_FB_RES_INTER,
 		.enable_reg = RK817_POWER_EN_REG(0),
 		.enable_mask = ENABLE_MASK(RK817_ID_DCDC3),
 		.enable_val = ENABLE_MASK(RK817_ID_DCDC3),
@@ -1297,7 +1299,7 @@
 		}
 
 		if (!pdata->dvs_gpio[i]) {
-			dev_warn(dev, "there is no dvs%d gpio\n", i);
+			dev_info(dev, "there is no dvs%d gpio\n", i);
 			continue;
 		}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/rn5t618-regulator.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/rn5t618-regulator.c
@@ -148,6 +148,7 @@
 
 module_platform_driver(rn5t618_regulator_driver);
 
+MODULE_ALIAS("platform:rn5t618-regulator");
 MODULE_AUTHOR("Beniamino Galvani <b.galvani@gmail.com>");
 MODULE_DESCRIPTION("RN5T618 regulator driver");
 MODULE_LICENSE("GPL v2");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/s5m8767.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/s5m8767.c
@@ -544,14 +544,18 @@
 	rdata = devm_kcalloc(&pdev->dev,
 			     pdata->num_regulators, sizeof(*rdata),
 			     GFP_KERNEL);
-	if (!rdata)
+	if (!rdata) {
+		of_node_put(regulators_np);
 		return -ENOMEM;
+	}
 
 	rmode = devm_kcalloc(&pdev->dev,
 			     pdata->num_regulators, sizeof(*rmode),
 			     GFP_KERNEL);
-	if (!rmode)
+	if (!rmode) {
+		of_node_put(regulators_np);
 		return -ENOMEM;
+	}
 
 	pdata->regulators = rdata;
 	pdata->opmode = rmode;
@@ -574,10 +578,13 @@
 			0,
 			GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE,
 			"s5m8767");
-		if (PTR_ERR(rdata->ext_control_gpiod) == -ENOENT)
+		if (PTR_ERR(rdata->ext_control_gpiod) == -ENOENT) {
 			rdata->ext_control_gpiod = NULL;
-		else if (IS_ERR(rdata->ext_control_gpiod))
+		} else if (IS_ERR(rdata->ext_control_gpiod)) {
+			of_node_put(reg_np);
+			of_node_put(regulators_np);
 			return PTR_ERR(rdata->ext_control_gpiod);
+		}
 
 		rdata->id = i;
 		rdata->initdata = of_get_regulator_init_data(
@@ -844,18 +851,15 @@
 	/* DS4 GPIO */
 	gpio_direction_output(pdata->buck_ds[2], 0x0);
 
-	if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs ||
-	   pdata->buck4_gpiodvs) {
-		regmap_update_bits(s5m8767->iodev->regmap_pmic,
-				S5M8767_REG_BUCK2CTRL, 1 << 1,
-				(pdata->buck2_gpiodvs) ? (1 << 1) : (0 << 1));
-		regmap_update_bits(s5m8767->iodev->regmap_pmic,
-				S5M8767_REG_BUCK3CTRL, 1 << 1,
-				(pdata->buck3_gpiodvs) ? (1 << 1) : (0 << 1));
-		regmap_update_bits(s5m8767->iodev->regmap_pmic,
-				S5M8767_REG_BUCK4CTRL, 1 << 1,
-				(pdata->buck4_gpiodvs) ? (1 << 1) : (0 << 1));
-	}
+	regmap_update_bits(s5m8767->iodev->regmap_pmic,
+			   S5M8767_REG_BUCK2CTRL, 1 << 1,
+			   (pdata->buck2_gpiodvs) ? (1 << 1) : (0 << 1));
+	regmap_update_bits(s5m8767->iodev->regmap_pmic,
+			   S5M8767_REG_BUCK3CTRL, 1 << 1,
+			   (pdata->buck3_gpiodvs) ? (1 << 1) : (0 << 1));
+	regmap_update_bits(s5m8767->iodev->regmap_pmic,
+			   S5M8767_REG_BUCK4CTRL, 1 << 1,
+			   (pdata->buck4_gpiodvs) ? (1 << 1) : (0 << 1));
 
 	/* Initialize GPIO DVS registers */
 	for (i = 0; i < 8; i++) {
@@ -920,10 +924,14 @@
 
 	for (i = 0; i < pdata->num_regulators; i++) {
 		const struct sec_voltage_desc *desc;
-		int id = pdata->regulators[i].id;
+		unsigned int id = pdata->regulators[i].id;
 		int enable_reg, enable_val;
 		struct regulator_dev *rdev;
 
+		BUILD_BUG_ON(ARRAY_SIZE(regulators) != ARRAY_SIZE(reg_voltage_map));
+		if (WARN_ON_ONCE(id >= ARRAY_SIZE(regulators)))
+			continue;
+
 		desc = reg_voltage_map[id];
 		if (desc) {
 			regulators[id].n_voltages =
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/slg51000-regulator.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/slg51000-regulator.c
@@ -465,6 +465,8 @@
 		chip->cs_gpiod = cs_gpiod;
 	}
 
+	usleep_range(10000, 11000);
+
 	i2c_set_clientdata(client, chip);
 	chip->chip_irq = client->irq;
 	chip->dev = dev;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/stm32-pwr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/stm32-pwr.c
@@ -129,17 +129,16 @@
 
 static int stm32_pwr_regulator_probe(struct platform_device *pdev)
 {
-	struct device_node *np = pdev->dev.of_node;
 	struct stm32_pwr_reg *priv;
 	void __iomem *base;
 	struct regulator_dev *rdev;
 	struct regulator_config config = { };
 	int i, ret = 0;
 
-	base = of_iomap(np, 0);
-	if (!base) {
+	base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(base)) {
 		dev_err(&pdev->dev, "Unable to map IO memory\n");
-		return -ENOMEM;
+		return PTR_ERR(base);
 	}
 
 	config.dev = &pdev->dev;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/stm32-vrefbuf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/stm32-vrefbuf.c
@@ -88,7 +88,7 @@
 	}
 
 	val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
-	val = (val & ~STM32_ENVR) | STM32_HIZ;
+	val &= ~STM32_ENVR;
 	writel_relaxed(val, priv->base + STM32_VREFBUF_CSR);
 
 	pm_runtime_mark_last_busy(priv->dev);
@@ -175,6 +175,7 @@
 	.volt_table = stm32_vrefbuf_voltages,
 	.n_voltages = ARRAY_SIZE(stm32_vrefbuf_voltages),
 	.ops = &stm32_vrefbuf_volt_ops,
+	.off_on_delay = 1000,
 	.type = REGULATOR_VOLTAGE,
 	.owner = THIS_MODULE,
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/ti-abb-regulator.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/ti-abb-regulator.c
@@ -342,8 +342,17 @@
 		return ret;
 	}
 
-	/* If data is exactly the same, then just update index, no change */
 	info = &abb->info[sel];
+	/*
+	 * When Linux kernel is starting up, we are'nt sure of the
+	 * Bias configuration that bootloader has configured.
+	 * So, we get to know the actual setting the first time
+	 * we are asked to transition.
+	 */
+	if (abb->current_info_idx == -EINVAL)
+		goto just_set_abb;
+
+	/* If data is exactly the same, then just update index, no change */
 	oinfo = &abb->info[abb->current_info_idx];
 	if (!memcmp(info, oinfo, sizeof(*info))) {
 		dev_dbg(dev, "%s: Same data new idx=%d, old idx=%d\n", __func__,
@@ -351,6 +360,7 @@
 		goto out;
 	}
 
+just_set_abb:
 	ret = ti_abb_set_opp(rdev, abb, info);
 
 out:
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/twl6030-regulator.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/twl6030-regulator.c
@@ -67,6 +67,7 @@
 #define TWL6030_CFG_STATE_SLEEP	0x03
 #define TWL6030_CFG_STATE_GRP_SHIFT	5
 #define TWL6030_CFG_STATE_APP_SHIFT	2
+#define TWL6030_CFG_STATE_MASK		0x03
 #define TWL6030_CFG_STATE_APP_MASK	(0x03 << TWL6030_CFG_STATE_APP_SHIFT)
 #define TWL6030_CFG_STATE_APP(v)	(((v) & TWL6030_CFG_STATE_APP_MASK) >>\
 						TWL6030_CFG_STATE_APP_SHIFT)
@@ -128,13 +129,14 @@
 		if (grp < 0)
 			return grp;
 		grp &= P1_GRP_6030;
+		val = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_STATE);
+		val = TWL6030_CFG_STATE_APP(val);
 	} else {
+		val = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_STATE);
+		val &= TWL6030_CFG_STATE_MASK;
 		grp = 1;
 	}
 
-	val = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_STATE);
-	val = TWL6030_CFG_STATE_APP(val);
-
 	return grp && (val == TWL6030_CFG_STATE_ON);
 }
 
@@ -187,7 +189,12 @@
 
 	val = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_STATE);
 
-	switch (TWL6030_CFG_STATE_APP(val)) {
+	if (info->features & TWL6032_SUBCLASS)
+		val &= TWL6030_CFG_STATE_MASK;
+	else
+		val = TWL6030_CFG_STATE_APP(val);
+
+	switch (val) {
 	case TWL6030_CFG_STATE_ON:
 		return REGULATOR_STATUS_NORMAL;
 
@@ -530,6 +537,7 @@
 #define TWL6032_ADJUSTABLE_LDO(label, offset) \
 static const struct twlreg_info TWL6032_INFO_##label = { \
 	.base = offset, \
+	.features = TWL6032_SUBCLASS, \
 	.desc = { \
 		.name = #label, \
 		.id = TWL6032_REG_##label, \
@@ -562,6 +570,7 @@
 #define TWL6032_ADJUSTABLE_SMPS(label, offset) \
 static const struct twlreg_info TWLSMPS_INFO_##label = { \
 	.base = offset, \
+	.features = TWL6032_SUBCLASS, \
 	.desc = { \
 		.name = #label, \
 		.id = TWL6032_REG_##label, \
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/uniphier-regulator.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/uniphier-regulator.c
@@ -203,6 +203,7 @@
 	},
 	{ /* Sentinel */ },
 };
+MODULE_DEVICE_TABLE(of, uniphier_regulator_match);
 
 static struct platform_driver uniphier_regulator_driver = {
 	.probe = uniphier_regulator_probe,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/vctrl-regulator.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/vctrl-regulator.c
@@ -11,10 +11,13 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/regulator/coupler.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/of_regulator.h>
 #include <linux/sort.h>
 
+#include "internal.h"
+
 struct vctrl_voltage_range {
 	int min_uV;
 	int max_uV;
@@ -34,7 +37,6 @@
 struct vctrl_data {
 	struct regulator_dev *rdev;
 	struct regulator_desc desc;
-	struct regulator *ctrl_reg;
 	bool enabled;
 	unsigned int min_slew_down_rate;
 	unsigned int ovp_threshold;
@@ -79,7 +81,12 @@
 static int vctrl_get_voltage(struct regulator_dev *rdev)
 {
 	struct vctrl_data *vctrl = rdev_get_drvdata(rdev);
-	int ctrl_uV = regulator_get_voltage(vctrl->ctrl_reg);
+	int ctrl_uV;
+
+	if (!rdev->supply)
+		return -EPROBE_DEFER;
+
+	ctrl_uV = regulator_get_voltage_rdev(rdev->supply->rdev);
 
 	return vctrl_calc_output_voltage(vctrl, ctrl_uV);
 }
@@ -89,17 +96,22 @@
 			     unsigned int *selector)
 {
 	struct vctrl_data *vctrl = rdev_get_drvdata(rdev);
-	struct regulator *ctrl_reg = vctrl->ctrl_reg;
-	int orig_ctrl_uV = regulator_get_voltage(ctrl_reg);
-	int uV = vctrl_calc_output_voltage(vctrl, orig_ctrl_uV);
+	int orig_ctrl_uV;
+	int uV;
 	int ret;
 
+	if (!rdev->supply)
+		return -EPROBE_DEFER;
+
+	orig_ctrl_uV = regulator_get_voltage_rdev(rdev->supply->rdev);
+	uV = vctrl_calc_output_voltage(vctrl, orig_ctrl_uV);
+
 	if (req_min_uV >= uV || !vctrl->ovp_threshold)
 		/* voltage rising or no OVP */
-		return regulator_set_voltage(
-			ctrl_reg,
+		return regulator_set_voltage_rdev(rdev->supply->rdev,
 			vctrl_calc_ctrl_voltage(vctrl, req_min_uV),
-			vctrl_calc_ctrl_voltage(vctrl, req_max_uV));
+			vctrl_calc_ctrl_voltage(vctrl, req_max_uV),
+			PM_SUSPEND_ON);
 
 	while (uV > req_min_uV) {
 		int max_drop_uV = (uV * vctrl->ovp_threshold) / 100;
@@ -114,9 +126,10 @@
 		next_uV = max_t(int, req_min_uV, uV - max_drop_uV);
 		next_ctrl_uV = vctrl_calc_ctrl_voltage(vctrl, next_uV);
 
-		ret = regulator_set_voltage(ctrl_reg,
+		ret = regulator_set_voltage_rdev(rdev->supply->rdev,
+					    next_ctrl_uV,
 					    next_ctrl_uV,
-					    next_ctrl_uV);
+					    PM_SUSPEND_ON);
 		if (ret)
 			goto err;
 
@@ -130,7 +143,8 @@
 
 err:
 	/* Try to go back to original voltage */
-	regulator_set_voltage(ctrl_reg, orig_ctrl_uV, orig_ctrl_uV);
+	regulator_set_voltage_rdev(rdev->supply->rdev, orig_ctrl_uV, orig_ctrl_uV,
+				   PM_SUSPEND_ON);
 
 	return ret;
 }
@@ -146,18 +160,21 @@
 				 unsigned int selector)
 {
 	struct vctrl_data *vctrl = rdev_get_drvdata(rdev);
-	struct regulator *ctrl_reg = vctrl->ctrl_reg;
 	unsigned int orig_sel = vctrl->sel;
 	int ret;
 
+	if (!rdev->supply)
+		return -EPROBE_DEFER;
+
 	if (selector >= rdev->desc->n_voltages)
 		return -EINVAL;
 
 	if (selector >= vctrl->sel || !vctrl->ovp_threshold) {
 		/* voltage rising or no OVP */
-		ret = regulator_set_voltage(ctrl_reg,
+		ret = regulator_set_voltage_rdev(rdev->supply->rdev,
+					    vctrl->vtable[selector].ctrl,
 					    vctrl->vtable[selector].ctrl,
-					    vctrl->vtable[selector].ctrl);
+					    PM_SUSPEND_ON);
 		if (!ret)
 			vctrl->sel = selector;
 
@@ -173,9 +190,10 @@
 		else
 			next_sel = vctrl->vtable[vctrl->sel].ovp_min_sel;
 
-		ret = regulator_set_voltage(ctrl_reg,
+		ret = regulator_set_voltage_rdev(rdev->supply->rdev,
 					    vctrl->vtable[next_sel].ctrl,
-					    vctrl->vtable[next_sel].ctrl);
+					    vctrl->vtable[next_sel].ctrl,
+					    PM_SUSPEND_ON);
 		if (ret) {
 			dev_err(&rdev->dev,
 				"failed to set control voltage to %duV\n",
@@ -195,9 +213,10 @@
 err:
 	if (vctrl->sel != orig_sel) {
 		/* Try to go back to original voltage */
-		if (!regulator_set_voltage(ctrl_reg,
+		if (!regulator_set_voltage_rdev(rdev->supply->rdev,
+					   vctrl->vtable[orig_sel].ctrl,
 					   vctrl->vtable[orig_sel].ctrl,
-					   vctrl->vtable[orig_sel].ctrl))
+					   PM_SUSPEND_ON))
 			vctrl->sel = orig_sel;
 		else
 			dev_warn(&rdev->dev,
@@ -226,10 +245,6 @@
 	u32 pval;
 	u32 vrange_ctrl[2];
 
-	vctrl->ctrl_reg = devm_regulator_get(&pdev->dev, "ctrl");
-	if (IS_ERR(vctrl->ctrl_reg))
-		return PTR_ERR(vctrl->ctrl_reg);
-
 	ret = of_property_read_u32(np, "ovp-threshold-percent", &pval);
 	if (!ret) {
 		vctrl->ovp_threshold = pval;
@@ -307,11 +322,11 @@
 	return at->ctrl - bt->ctrl;
 }
 
-static int vctrl_init_vtable(struct platform_device *pdev)
+static int vctrl_init_vtable(struct platform_device *pdev,
+			     struct regulator *ctrl_reg)
 {
 	struct vctrl_data *vctrl = platform_get_drvdata(pdev);
 	struct regulator_desc *rdesc = &vctrl->desc;
-	struct regulator *ctrl_reg = vctrl->ctrl_reg;
 	struct vctrl_voltage_range *vrange_ctrl = &vctrl->vrange.ctrl;
 	int n_voltages;
 	int ctrl_uV;
@@ -387,23 +402,19 @@
 static int vctrl_enable(struct regulator_dev *rdev)
 {
 	struct vctrl_data *vctrl = rdev_get_drvdata(rdev);
-	int ret = regulator_enable(vctrl->ctrl_reg);
 
-	if (!ret)
-		vctrl->enabled = true;
+	vctrl->enabled = true;
 
-	return ret;
+	return 0;
 }
 
 static int vctrl_disable(struct regulator_dev *rdev)
 {
 	struct vctrl_data *vctrl = rdev_get_drvdata(rdev);
-	int ret = regulator_disable(vctrl->ctrl_reg);
 
-	if (!ret)
-		vctrl->enabled = false;
+	vctrl->enabled = false;
 
-	return ret;
+	return 0;
 }
 
 static int vctrl_is_enabled(struct regulator_dev *rdev)
@@ -439,6 +450,7 @@
 	struct regulator_desc *rdesc;
 	struct regulator_config cfg = { };
 	struct vctrl_voltage_range *vrange_ctrl;
+	struct regulator *ctrl_reg;
 	int ctrl_uV;
 	int ret;
 
@@ -453,15 +465,20 @@
 	if (ret)
 		return ret;
 
+	ctrl_reg = devm_regulator_get(&pdev->dev, "ctrl");
+	if (IS_ERR(ctrl_reg))
+		return PTR_ERR(ctrl_reg);
+
 	vrange_ctrl = &vctrl->vrange.ctrl;
 
 	rdesc = &vctrl->desc;
 	rdesc->name = "vctrl";
 	rdesc->type = REGULATOR_VOLTAGE;
 	rdesc->owner = THIS_MODULE;
+	rdesc->supply_name = "ctrl";
 
-	if ((regulator_get_linear_step(vctrl->ctrl_reg) == 1) ||
-	    (regulator_count_voltages(vctrl->ctrl_reg) == -EINVAL)) {
+	if ((regulator_get_linear_step(ctrl_reg) == 1) ||
+	    (regulator_count_voltages(ctrl_reg) == -EINVAL)) {
 		rdesc->continuous_voltage_range = true;
 		rdesc->ops = &vctrl_ops_cont;
 	} else {
@@ -478,11 +495,12 @@
 	cfg.init_data = init_data;
 
 	if (!rdesc->continuous_voltage_range) {
-		ret = vctrl_init_vtable(pdev);
+		ret = vctrl_init_vtable(pdev, ctrl_reg);
 		if (ret)
 			return ret;
 
-		ctrl_uV = regulator_get_voltage(vctrl->ctrl_reg);
+		/* Use locked consumer API when not in regulator framework */
+		ctrl_uV = regulator_get_voltage(ctrl_reg);
 		if (ctrl_uV < 0) {
 			dev_err(&pdev->dev, "failed to get control voltage\n");
 			return ctrl_uV;
@@ -505,6 +523,9 @@
 		}
 	}
 
+	/* Drop ctrl-supply here in favor of regulator core managed supply */
+	devm_regulator_put(ctrl_reg);
+
 	vctrl->rdev = devm_regulator_register(&pdev->dev, rdesc, &cfg);
 	if (IS_ERR(vctrl->rdev)) {
 		ret = PTR_ERR(vctrl->rdev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/regulator/wm8994-regulator.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/regulator/wm8994-regulator.c
@@ -82,6 +82,35 @@
 		.min_uV = 2400000,
 		.uV_step = 100000,
 		.enable_time = 3000,
+		.off_on_delay = 36000,
+		.owner = THIS_MODULE,
+	},
+	{
+		.name = "LDO2",
+		.id = 2,
+		.type = REGULATOR_VOLTAGE,
+		.n_voltages = WM8994_LDO2_MAX_SELECTOR + 1,
+		.vsel_reg = WM8994_LDO_2,
+		.vsel_mask = WM8994_LDO2_VSEL_MASK,
+		.ops = &wm8994_ldo2_ops,
+		.enable_time = 3000,
+		.off_on_delay = 36000,
+		.owner = THIS_MODULE,
+	},
+};
+
+static const struct regulator_desc wm8958_ldo_desc[] = {
+	{
+		.name = "LDO1",
+		.id = 1,
+		.type = REGULATOR_VOLTAGE,
+		.n_voltages = WM8994_LDO1_MAX_SELECTOR + 1,
+		.vsel_reg = WM8994_LDO_1,
+		.vsel_mask = WM8994_LDO1_VSEL_MASK,
+		.ops = &wm8994_ldo1_ops,
+		.min_uV = 2400000,
+		.uV_step = 100000,
+		.enable_time = 3000,
 		.owner = THIS_MODULE,
 	},
 	{
@@ -172,9 +201,16 @@
 	 * regulator core and we need not worry about it on the
 	 * error path.
 	 */
-	ldo->regulator = devm_regulator_register(&pdev->dev,
-						 &wm8994_ldo_desc[id],
-						 &config);
+	if (ldo->wm8994->type == WM8994) {
+		ldo->regulator = devm_regulator_register(&pdev->dev,
+							 &wm8994_ldo_desc[id],
+							 &config);
+	} else {
+		ldo->regulator = devm_regulator_register(&pdev->dev,
+							 &wm8958_ldo_desc[id],
+							 &config);
+	}
+
 	if (IS_ERR(ldo->regulator)) {
 		ret = PTR_ERR(ldo->regulator);
 		dev_err(wm8994->dev, "Failed to register LDO%d: %d\n",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/remoteproc/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/remoteproc/Kconfig
@@ -196,6 +196,26 @@
 	  processor framework.
 	  This can be either built-in or a loadable module.
 
+config ZYNQ_REMOTEPROC
+	tristate "Support ZYNQ remoteproc"
+	depends on ARCH_ZYNQ && SMP && !DEBUG_SG
+	select RPMSG_VIRTIO
+	select HOTPLUG_CPU
+	select SRAM
+	help
+	  Say y here to support Xilinx ZynQ remote processors (the second
+	  ARM CORTEX-A9 cpu) via the remote processor framework.
+
+config ZYNQMP_R5_REMOTEPROC
+	tristate "ZynqMP_r5 remoteproc support"
+	depends on ARM64 && PM && ARCH_ZYNQMP
+	select RPMSG_VIRTIO
+	select MAILBOX
+	select ZYNQMP_IPI_MBOX
+	help
+	  Say y here to support ZynqMP R5 remote processors via the remote
+	  processor framework.
+
 config ST_SLIM_REMOTEPROC
 	tristate
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/remoteproc/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/remoteproc/Makefile
@@ -25,5 +25,7 @@
 qcom_wcnss_pil-y			+= qcom_wcnss.o
 qcom_wcnss_pil-y			+= qcom_wcnss_iris.o
 obj-$(CONFIG_ST_REMOTEPROC)		+= st_remoteproc.o
+obj-$(CONFIG_ZYNQ_REMOTEPROC)		+= zynq_remoteproc.o
+obj-$(CONFIG_ZYNQMP_R5_REMOTEPROC)	+= zynqmp_r5_remoteproc.o
 obj-$(CONFIG_ST_SLIM_REMOTEPROC)	+= st_slim_rproc.o
 obj-$(CONFIG_STM32_RPROC)		+= stm32_rproc.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/remoteproc/imx_rproc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/remoteproc/imx_rproc.c
@@ -286,6 +286,11 @@
 		struct resource res;
 
 		node = of_parse_phandle(np, "memory-region", a);
+		if (!node)
+			continue;
+		/* Not map vdevbuffer, vdevring region */
+		if (!strncmp(node->name, "vdev", strlen("vdev")))
+			continue;
 		err = of_address_to_resource(node, 0, &res);
 		if (err) {
 			dev_err(dev, "unable to resolve memory region\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/remoteproc/qcom_q6v5.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/remoteproc/qcom_q6v5.c
@@ -151,6 +151,8 @@
 {
 	int ret;
 
+	q6v5->running = false;
+
 	qcom_smem_state_update_bits(q6v5->state,
 				    BIT(q6v5->stop_bit), BIT(q6v5->stop_bit));
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/remoteproc/qcom_q6v5_adsp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/remoteproc/qcom_q6v5_adsp.c
@@ -184,8 +184,10 @@
 
 	dev_pm_genpd_set_performance_state(adsp->dev, INT_MAX);
 	ret = pm_runtime_get_sync(adsp->dev);
-	if (ret)
+	if (ret) {
+		pm_runtime_put_noidle(adsp->dev);
 		goto disable_xo_clk;
+	}
 
 	ret = clk_bulk_prepare_enable(adsp->num_clks, adsp->clks);
 	if (ret) {
@@ -345,15 +347,12 @@
 				struct platform_device *pdev)
 {
 	struct device_node *syscon;
-	struct resource *res;
 	int ret;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	adsp->qdsp6ss_base = devm_ioremap(&pdev->dev, res->start,
-			resource_size(res));
-	if (!adsp->qdsp6ss_base) {
+	adsp->qdsp6ss_base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(adsp->qdsp6ss_base)) {
 		dev_err(adsp->dev, "failed to map QDSP6SS registers\n");
-		return -ENOMEM;
+		return PTR_ERR(adsp->qdsp6ss_base);
 	}
 
 	syscon = of_parse_phandle(pdev->dev.of_node, "qcom,halt-regs", 0);
@@ -390,6 +389,7 @@
 	}
 
 	ret = of_address_to_resource(node, 0, &r);
+	of_node_put(node);
 	if (ret)
 		return ret;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/remoteproc/qcom_q6v5_mss.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/remoteproc/qcom_q6v5_mss.c
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
+#include <linux/of_reserved_mem.h>
 #include <linux/platform_device.h>
 #include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
@@ -175,6 +176,9 @@
 	void *mba_region;
 	size_t mba_size;
 
+	phys_addr_t mdata_phys;
+	size_t mdata_size;
+
 	phys_addr_t mpss_phys;
 	phys_addr_t mpss_reloc;
 	void *mpss_region;
@@ -331,8 +335,11 @@
 	for (i = 0; i < pd_count; i++) {
 		dev_pm_genpd_set_performance_state(pds[i], INT_MAX);
 		ret = pm_runtime_get_sync(pds[i]);
-		if (ret < 0)
+		if (ret < 0) {
+			pm_runtime_put_noidle(pds[i]);
+			dev_pm_genpd_set_performance_state(pds[i], 0);
 			goto unroll_pd_votes;
+		}
 	}
 
 	return 0;
@@ -381,6 +388,12 @@
 {
 	struct q6v5 *qproc = rproc->priv;
 
+	/* MBA is restricted to a maximum size of 1M */
+	if (fw->size > qproc->mba_size || fw->size > SZ_1M) {
+		dev_err(qproc->dev, "MBA firmware load failed\n");
+		return -EINVAL;
+	}
+
 	memcpy(qproc->mba_region, fw->data, fw->size);
 
 	return 0;
@@ -670,15 +683,35 @@
 	if (IS_ERR(metadata))
 		return PTR_ERR(metadata);
 
-	ptr = dma_alloc_attrs(qproc->dev, size, &phys, GFP_KERNEL, dma_attrs);
-	if (!ptr) {
-		kfree(metadata);
-		dev_err(qproc->dev, "failed to allocate mdt buffer\n");
-		return -ENOMEM;
+	if (qproc->mdata_phys) {
+		if (size > qproc->mdata_size) {
+			ret = -EINVAL;
+			dev_err(qproc->dev, "metadata size outside memory range\n");
+			goto free_metadata;
+		}
+
+		phys = qproc->mdata_phys;
+		ptr = memremap(qproc->mdata_phys, size, MEMREMAP_WC);
+		if (!ptr) {
+			ret = -EBUSY;
+			dev_err(qproc->dev, "unable to map memory region: %pa+%zx\n",
+				&qproc->mdata_phys, size);
+			goto free_metadata;
+		}
+	} else {
+		ptr = dma_alloc_attrs(qproc->dev, size, &phys, GFP_KERNEL, dma_attrs);
+		if (!ptr) {
+			ret = -ENOMEM;
+			dev_err(qproc->dev, "failed to allocate mdt buffer\n");
+			goto free_metadata;
+		}
 	}
 
 	memcpy(ptr, metadata, size);
 
+	if (qproc->mdata_phys)
+		memunmap(ptr);
+
 	/* Hypervisor mapping to access metadata by modem */
 	mdata_perm = BIT(QCOM_SCM_VMID_HLOS);
 	ret = q6v5_xfer_mem_ownership(qproc, &mdata_perm, true, phys, size);
@@ -705,7 +738,9 @@
 			 "mdt buffer not reclaimed system may become unstable\n");
 
 free_dma_attrs:
-	dma_free_attrs(qproc->dev, size, ptr, phys, dma_attrs);
+	if (!qproc->mdata_phys)
+		dma_free_attrs(qproc->dev, size, ptr, phys, dma_attrs);
+free_metadata:
 	kfree(metadata);
 
 	return ret < 0 ? ret : 0;
@@ -875,11 +910,6 @@
 		writel(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);
 	}
 
-	ret = q6v5_xfer_mem_ownership(qproc, &qproc->mpss_perm,
-				      false, qproc->mpss_phys,
-				      qproc->mpss_size);
-	WARN_ON(ret);
-
 	q6v5_reset_assert(qproc);
 
 	q6v5_clk_disable(qproc->dev, qproc->reset_clks,
@@ -909,6 +939,23 @@
 	}
 }
 
+static int q6v5_reload_mba(struct rproc *rproc)
+{
+	struct q6v5 *qproc = rproc->priv;
+	const struct firmware *fw;
+	int ret;
+
+	ret = request_firmware(&fw, rproc->firmware, qproc->dev);
+	if (ret < 0)
+		return ret;
+
+	q6v5_load(rproc, fw);
+	ret = q6v5_mba_load(qproc);
+	release_firmware(fw);
+
+	return ret;
+}
+
 static int q6v5_mpss_load(struct q6v5 *qproc)
 {
 	const struct elf32_phdr *phdrs;
@@ -969,6 +1016,14 @@
 			max_addr = ALIGN(phdr->p_paddr + phdr->p_memsz, SZ_4K);
 	}
 
+	/**
+	 * In case of a modem subsystem restart on secure devices, the modem
+	 * memory can be reclaimed only after MBA is loaded. For modem cold
+	 * boot this will be a nop
+	 */
+	q6v5_xfer_mem_ownership(qproc, &qproc->mpss_perm, false,
+				qproc->mpss_phys, qproc->mpss_size);
+
 	mpss_reloc = relocate ? min_addr : qproc->mpss_phys;
 	qproc->mpss_reloc = mpss_reloc;
 	/* Load firmware segments */
@@ -985,7 +1040,13 @@
 			goto release_firmware;
 		}
 
-		ptr = qproc->mpss_region + offset;
+		ptr = ioremap_wc(qproc->mpss_phys + offset, phdr->p_memsz);
+		if (!ptr) {
+			dev_err(qproc->dev,
+				"unable to map memory region: %pa+%zx-%x\n",
+				&qproc->mpss_phys, offset, phdr->p_memsz);
+			goto release_firmware;
+		}
 
 		if (phdr->p_filesz && phdr->p_offset < fw->size) {
 			/* Firmware is large enough to be non-split */
@@ -994,6 +1055,7 @@
 					"failed to load segment %d from truncated file %s\n",
 					i, fw_name);
 				ret = -EINVAL;
+				iounmap(ptr);
 				goto release_firmware;
 			}
 
@@ -1001,14 +1063,14 @@
 		} else if (phdr->p_filesz) {
 			/* Replace "xxx.xxx" with "xxx.bxx" */
 			sprintf(fw_name + fw_name_len - 3, "b%02d", i);
-			ret = request_firmware(&seg_fw, fw_name, qproc->dev);
+			ret = request_firmware_into_buf(&seg_fw, fw_name, qproc->dev,
+							ptr, phdr->p_filesz);
 			if (ret) {
 				dev_err(qproc->dev, "failed to load %s\n", fw_name);
+				iounmap(ptr);
 				goto release_firmware;
 			}
 
-			memcpy(ptr, seg_fw->data, seg_fw->size);
-
 			release_firmware(seg_fw);
 		}
 
@@ -1016,6 +1078,7 @@
 			memset(ptr + phdr->p_filesz, 0,
 			       phdr->p_memsz - phdr->p_filesz);
 		}
+		iounmap(ptr);
 		size += phdr->p_memsz;
 	}
 
@@ -1055,23 +1118,43 @@
 	int ret = 0;
 	struct q6v5 *qproc = rproc->priv;
 	unsigned long mask = BIT((unsigned long)segment->priv);
-	void *ptr = rproc_da_to_va(rproc, segment->da, segment->size);
+	int offset = segment->da - qproc->mpss_reloc;
+	void *ptr = NULL;
 
 	/* Unlock mba before copying segments */
-	if (!qproc->dump_mba_loaded)
-		ret = q6v5_mba_load(qproc);
+	if (!qproc->dump_mba_loaded) {
+		ret = q6v5_reload_mba(rproc);
+		if (!ret) {
+			/* Reset ownership back to Linux to copy segments */
+			ret = q6v5_xfer_mem_ownership(qproc, &qproc->mpss_perm,
+						      false,
+						      qproc->mpss_phys,
+						      qproc->mpss_size);
+		}
+	}
 
-	if (!ptr || ret)
-		memset(dest, 0xff, segment->size);
-	else
+	if (!ret)
+		ptr = ioremap_wc(qproc->mpss_phys + offset, segment->size);
+
+	if (ptr) {
 		memcpy(dest, ptr, segment->size);
+		iounmap(ptr);
+	} else {
+		memset(dest, 0xff, segment->size);
+	}
 
 	qproc->dump_segment_mask |= mask;
 
 	/* Reclaim mba after copying segments */
 	if (qproc->dump_segment_mask == qproc->dump_complete_mask) {
-		if (qproc->dump_mba_loaded)
+		if (qproc->dump_mba_loaded) {
+			/* Try to reset ownership back to Q6 */
+			q6v5_xfer_mem_ownership(qproc, &qproc->mpss_perm,
+						true,
+						qproc->mpss_phys,
+						qproc->mpss_size);
 			q6v5_mba_reclaim(qproc);
+		}
 	}
 }
 
@@ -1111,10 +1194,6 @@
 	return 0;
 
 reclaim_mpss:
-	xfermemop_ret = q6v5_xfer_mem_ownership(qproc, &qproc->mpss_perm,
-						false, qproc->mpss_phys,
-						qproc->mpss_size);
-	WARN_ON(xfermemop_ret);
 	q6v5_mba_reclaim(qproc);
 
 	return ret;
@@ -1330,6 +1409,7 @@
 static int q6v5_alloc_memory_region(struct q6v5 *qproc)
 {
 	struct device_node *child;
+	struct reserved_mem *rmem;
 	struct device_node *node;
 	struct resource r;
 	int ret;
@@ -1363,13 +1443,27 @@
 
 	qproc->mpss_phys = qproc->mpss_reloc = r.start;
 	qproc->mpss_size = resource_size(&r);
-	qproc->mpss_region = devm_ioremap_wc(qproc->dev, qproc->mpss_phys, qproc->mpss_size);
-	if (!qproc->mpss_region) {
-		dev_err(qproc->dev, "unable to map memory region: %pa+%zx\n",
-			&r.start, qproc->mpss_size);
-		return -EBUSY;
+
+	if (!child) {
+		node = of_parse_phandle(qproc->dev->of_node, "memory-region", 2);
+	} else {
+		child = of_get_child_by_name(qproc->dev->of_node, "metadata");
+		node = of_parse_phandle(child, "memory-region", 0);
+		of_node_put(child);
 	}
 
+	if (!node)
+		return 0;
+
+	rmem = of_reserved_mem_lookup(node);
+	if (!rmem) {
+		dev_err(qproc->dev, "unable to resolve metadata region\n");
+		return -EINVAL;
+	}
+
+	qproc->mdata_phys = rmem->base;
+	qproc->mdata_size = rmem->size;
+
 	return 0;
 }
 
@@ -1410,7 +1504,7 @@
 	ret = of_property_read_string_index(pdev->dev.of_node, "firmware-name",
 					    1, &qproc->hexagon_mdt_image);
 	if (ret < 0 && ret != -EINVAL)
-		return ret;
+		goto free_rproc;
 
 	platform_set_drvdata(pdev, qproc);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/remoteproc/qcom_q6v5_pas.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/remoteproc/qcom_q6v5_pas.c
@@ -230,6 +230,7 @@
 	}
 
 	ret = of_address_to_resource(node, 0, &r);
+	of_node_put(node);
 	if (ret)
 		return ret;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/remoteproc/qcom_sysmon.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/remoteproc/qcom_sysmon.c
@@ -518,7 +518,9 @@
 		if (sysmon->shutdown_irq != -ENODATA) {
 			dev_err(sysmon->dev,
 				"failed to retrieve shutdown-ack IRQ\n");
-			return ERR_PTR(sysmon->shutdown_irq);
+			ret = sysmon->shutdown_irq;
+			kfree(sysmon);
+			return ERR_PTR(ret);
 		}
 	} else {
 		ret = devm_request_threaded_irq(sysmon->dev,
@@ -529,6 +531,7 @@
 		if (ret) {
 			dev_err(sysmon->dev,
 				"failed to acquire shutdown-ack IRQ\n");
+			kfree(sysmon);
 			return ERR_PTR(ret);
 		}
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/remoteproc/qcom_wcnss.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/remoteproc/qcom_wcnss.c
@@ -407,6 +407,7 @@
 			     irq_handler_t thread_fn)
 {
 	int ret;
+	int irq_number;
 
 	ret = platform_get_irq_byname(pdev, name);
 	if (ret < 0 && optional) {
@@ -417,14 +418,19 @@
 		return ret;
 	}
 
+	irq_number = ret;
+
 	ret = devm_request_threaded_irq(&pdev->dev, ret,
 					NULL, thread_fn,
 					IRQF_TRIGGER_RISING | IRQF_ONESHOT,
 					"wcnss", wcnss);
-	if (ret)
+	if (ret) {
 		dev_err(&pdev->dev, "request %s IRQ failed\n", name);
+		return ret;
+	}
 
-	return ret;
+	/* Return the IRQ number if the IRQ was successfully acquired */
+	return irq_number;
 }
 
 static int wcnss_alloc_memory_region(struct qcom_wcnss *wcnss)
@@ -440,6 +446,7 @@
 	}
 
 	ret = of_address_to_resource(node, 0, &r);
+	of_node_put(node);
 	if (ret)
 		return ret;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/remoteproc/remoteproc_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/remoteproc/remoteproc_core.c
@@ -400,7 +400,7 @@
 void rproc_free_vring(struct rproc_vring *rvring)
 {
 	struct rproc *rproc = rvring->rvdev->rproc;
-	int idx = rvring->rvdev->vring - rvring;
+	int idx = rvring - rvring->rvdev->vring;
 	struct fw_rsc_vdev *rsc;
 
 	idr_remove(&rproc->notifyids, rvring->notifyid);
@@ -511,7 +511,7 @@
 
 	/* Initialise vdev subdevice */
 	snprintf(name, sizeof(name), "vdev%dbuffer", rvdev->index);
-	rvdev->dev.parent = rproc->dev.parent;
+	rvdev->dev.parent = &rproc->dev;
 	rvdev->dev.dma_pfn_offset = rproc->dev.parent->dma_pfn_offset;
 	rvdev->dev.release = rproc_rvdev_release;
 	dev_set_name(&rvdev->dev, "%s#%s", dev_name(rvdev->dev.parent), name);
@@ -2036,6 +2036,7 @@
 	rproc->dev.type = &rproc_type;
 	rproc->dev.class = &rproc_class;
 	rproc->dev.driver_data = rproc;
+	idr_init(&rproc->notifyids);
 
 	/* Assign a unique device index and name */
 	rproc->index = ida_simple_get(&rproc_dev_index, 0, 0, GFP_KERNEL);
@@ -2060,8 +2061,6 @@
 
 	mutex_init(&rproc->lock);
 
-	idr_init(&rproc->notifyids);
-
 	INIT_LIST_HEAD(&rproc->carveouts);
 	INIT_LIST_HEAD(&rproc->mappings);
 	INIT_LIST_HEAD(&rproc->traces);
@@ -2224,7 +2223,7 @@
 
 	return 0;
 }
-module_init(remoteproc_init);
+subsys_initcall(remoteproc_init);
 
 static void __exit remoteproc_exit(void)
 {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/remoteproc/remoteproc_internal.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/remoteproc/remoteproc_internal.h
@@ -119,4 +119,27 @@
 	return NULL;
 }
 
+static inline
+bool rproc_allow_sysfs_kick(struct rproc *rproc)
+{
+	return (rproc->sysfs_kick) ? true : false;
+}
+
+static inline
+bool rproc_peek_remote_kick(struct rproc *rproc, char *buf, size_t *len)
+{
+	if (rproc->ops->peek_remote_kick)
+		return rproc->ops->peek_remote_kick(rproc, buf, len);
+	else
+		return false;
+}
+
+static inline
+void rproc_ack_remote_kick(struct rproc *rproc)
+{
+	if (rproc->ops->ack_remote_kick)
+		rproc->ops->ack_remote_kick(rproc);
+}
+
+int rproc_create_kick_sysfs(struct rproc *rproc);
 #endif /* REMOTEPROC_INTERNAL_H */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/remoteproc/remoteproc_sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/remoteproc/remoteproc_sysfs.c
@@ -113,6 +113,85 @@
 }
 static DEVICE_ATTR_RW(state);
 
+/**
+ * kick_store() - Kick remote from sysfs.
+ * @dev: remoteproc device
+ * @attr: sysfs device attribute
+ * @buf: sysfs buffer
+ * @count: size of the contents in buf
+ *
+ * It will just raise a signal, no content is expected for now.
+ *
+ * Return: the input count if it allows kick from sysfs,
+ * as it is always expected to succeed.
+ */
+static ssize_t kick_store(struct device *dev,
+			  struct device_attribute *attr,
+			  const char *buf, size_t count)
+{
+	struct rproc *rproc = to_rproc(dev);
+	int id;
+	size_t cpy_len;
+
+	(void)attr;
+	cpy_len = count <= sizeof(id) ? count : sizeof(id);
+	memcpy((char *)(&id), buf, cpy_len);
+
+	if (rproc->ops->kick)
+		rproc->ops->kick(rproc, id);
+	else
+		count = -EINVAL;
+	return count;
+}
+static DEVICE_ATTR_WO(kick);
+
+/**
+ * remote_kick_show() - Check if remote has kicked
+ * @dev: remoteproc device
+ * @attr: sysfs device attribute
+ * @buf: sysfs buffer
+ *
+ * It will check if the remote has kicked.
+ *
+ * Return: always 2, and the value in the sysfs buffer
+ * shows if the remote has kicked. '0' - not kicked, '1' - kicked.
+ */
+static ssize_t remote_kick_show(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	struct rproc *rproc = to_rproc(dev);
+
+	buf[0] = '0';
+	buf[1] = '\n';
+	if (rproc_peek_remote_kick(rproc, NULL, NULL))
+		buf[0] = '1';
+	return 2;
+}
+
+/**
+ * remote_kick_store() - Ack the kick from remote
+ * @dev: remoteproc device
+ * @attr: sysfs device attribute
+ * @buf: sysfs buffer
+ * @count: size of the contents in buf
+ *
+ * It will ack the remote, no response contents is expected.
+ *
+ * Return: the input count if it allows kick from sysfs,
+ * as it is always expected to succeed.
+ */
+static ssize_t remote_kick_store(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	struct rproc *rproc = to_rproc(dev);
+
+	rproc_ack_remote_kick(rproc);
+	return count;
+}
+static DEVICE_ATTR_RW(remote_kick);
+
 /* Expose the name of the remote processor via sysfs */
 static ssize_t name_show(struct device *dev, struct device_attribute *attr,
 			 char *buf)
@@ -144,6 +223,34 @@
 	.dev_groups	= rproc_devgroups,
 };
 
+/**
+ * rproc_create_kick_sysfs() - create kick remote sysfs entry
+ * @rproc: remoteproc
+ *
+ * It will create kick remote sysfs entry if kick remote
+ * from sysfs is allowed.
+ *
+ * Return: 0 for success, and negative value for failure.
+ */
+int rproc_create_kick_sysfs(struct rproc *rproc)
+{
+	struct device *dev = &rproc->dev;
+	int ret;
+
+	if (!rproc_allow_sysfs_kick(rproc))
+		return -EINVAL;
+	ret = sysfs_create_file(&dev->kobj, &dev_attr_kick.attr);
+	if (ret) {
+		dev_err(dev, "failed to create sysfs for kick.\n");
+		return ret;
+	}
+	ret = sysfs_create_file(&dev->kobj, &dev_attr_remote_kick.attr);
+	if (ret)
+		dev_err(dev, "failed to create sysfs for remote kick.\n");
+	return ret;
+}
+EXPORT_SYMBOL(rproc_create_kick_sysfs);
+
 int __init rproc_init_sysfs(void)
 {
 	/* create remoteproc device class for sysfs */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/remoteproc/remoteproc_virtio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/remoteproc/remoteproc_virtio.c
@@ -334,6 +334,13 @@
 	struct rproc_mem_entry *mem;
 	int ret;
 
+	if (rproc->ops->kick == NULL) {
+		ret = -EINVAL;
+		dev_err(dev, ".kick method not defined for %s",
+				rproc->name);
+		goto out;
+	}
+
 	/* Try to find dedicated vdev buffer carveout */
 	mem = rproc_find_carveout_by_name(rproc, "vdev%dbuffer", rvdev->index);
 	if (mem) {
@@ -368,6 +375,18 @@
 				goto out;
 			}
 		}
+	} else {
+		struct device_node *np = rproc->dev.parent->of_node;
+
+		/*
+		 * If we don't have dedicated buffer, just attempt to re-assign
+		 * the reserved memory from our parent. A default memory-region
+		 * at index 0 from the parent's memory-regions is assigned for
+		 * the rvdev dev to allocate from. Failure is non-critical and
+		 * the allocations will fall back to global pools, so don't
+		 * check return value either.
+		 */
+		of_reserved_mem_device_init_by_idx(dev, np, 0);
 	}
 
 	/* Allocate virtio device */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/remoteproc/st_remoteproc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/remoteproc/st_remoteproc.c
@@ -129,6 +129,7 @@
 	while (of_phandle_iterator_next(&it) == 0) {
 		rmem = of_reserved_mem_lookup(it.node);
 		if (!rmem) {
+			of_node_put(it.node);
 			dev_err(dev, "unable to acquire memory-region\n");
 			return -EINVAL;
 		}
@@ -150,8 +151,10 @@
 							   it.node->name);
 		}
 
-		if (!mem)
+		if (!mem) {
+			of_node_put(it.node);
 			return -ENOMEM;
+		}
 
 		rproc_add_carveout(rproc, mem);
 		index++;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/remoteproc/stm32_rproc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/remoteproc/stm32_rproc.c
@@ -211,11 +211,13 @@
 	while (of_phandle_iterator_next(&it) == 0) {
 		rmem = of_reserved_mem_lookup(it.node);
 		if (!rmem) {
+			of_node_put(it.node);
 			dev_err(dev, "unable to acquire memory-region\n");
 			return -EINVAL;
 		}
 
 		if (stm32_rproc_pa_to_da(rproc, rmem->base, &da) < 0) {
+			of_node_put(it.node);
 			dev_err(dev, "memory region not valid %pa\n",
 				&rmem->base);
 			return -EINVAL;
@@ -242,8 +244,10 @@
 							   it.node->name);
 		}
 
-		if (!mem)
+		if (!mem) {
+			of_node_put(it.node);
 			return -ENOMEM;
+		}
 
 		rproc_add_carveout(rproc, mem);
 		index++;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/remoteproc/zynq_remoteproc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/remoteproc/zynq_remoteproc.c
@@ -0,0 +1,463 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Zynq Remote Processor driver
+ *
+ * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2012 PetaLogix
+ *
+ * Based on origin OMAP Remote Processor driver
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Copyright (C) 2011 Google, Inc.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/remoteproc.h>
+#include <linux/interrupt.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_reserved_mem.h>
+#include <linux/smp.h>
+#include <linux/irqchip/arm-gic.h>
+#include <asm/outercache.h>
+#include <linux/slab.h>
+#include <linux/cpu.h>
+#include <linux/genalloc.h>
+#include <../../arch/arm/mach-zynq/common.h>
+
+#include "remoteproc_internal.h"
+
+#define MAX_NUM_VRINGS 2
+#define NOTIFYID_ANY (-1)
+/* Maximum on chip memories used by the driver*/
+#define MAX_ON_CHIP_MEMS        32
+
+/* Structure for storing IRQs */
+struct irq_list {
+	int irq;
+	struct list_head list;
+};
+
+/* Structure for IPIs */
+struct ipi_info {
+	u32 irq;
+	u32 notifyid;
+	bool pending;
+};
+
+/**
+ * struct zynq_mem_res - zynq memory resource for firmware memory
+ * @res: memory resource
+ * @node: list node
+ */
+struct zynq_mem_res {
+	struct resource res;
+	struct list_head node;
+};
+
+/**
+ * struct zynq_rproc_data - zynq rproc private data
+ * @irqs: inter processor soft IRQs
+ * @rproc: pointer to remoteproc instance
+ * @ipis: interrupt processor interrupts statistics
+ * @fw_mems: list of firmware memories
+ */
+struct zynq_rproc_pdata {
+	struct irq_list irqs;
+	struct rproc *rproc;
+	struct ipi_info ipis[MAX_NUM_VRINGS];
+	struct list_head fw_mems;
+};
+
+static bool autoboot __read_mostly;
+
+/* Store rproc for IPI handler */
+static struct rproc *rproc;
+static struct work_struct workqueue;
+
+static void handle_event(struct work_struct *work)
+{
+	struct zynq_rproc_pdata *local = rproc->priv;
+
+	if (rproc_vq_interrupt(local->rproc, local->ipis[0].notifyid) ==
+				IRQ_NONE)
+		dev_dbg(rproc->dev.parent, "no message found in vqid 0\n");
+}
+
+static void ipi_kick(void)
+{
+	dev_dbg(rproc->dev.parent, "KICK Linux because of pending message\n");
+	schedule_work(&workqueue);
+}
+
+static void kick_pending_ipi(struct rproc *rproc)
+{
+	struct zynq_rproc_pdata *local = rproc->priv;
+	int i;
+
+	for (i = 0; i < MAX_NUM_VRINGS; i++) {
+		/* Send swirq to firmware */
+		if (local->ipis[i].pending) {
+			gic_raise_softirq(cpumask_of(1),
+					  local->ipis[i].irq);
+			local->ipis[i].pending = false;
+		}
+	}
+}
+
+static int zynq_rproc_start(struct rproc *rproc)
+{
+	struct device *dev = rproc->dev.parent;
+	int ret;
+
+	dev_dbg(dev, "%s\n", __func__);
+	INIT_WORK(&workqueue, handle_event);
+
+	ret = cpu_down(1);
+	/* EBUSY means CPU is already released */
+	if (ret && (ret != -EBUSY)) {
+		dev_err(dev, "Can't release cpu1\n");
+		return ret;
+	}
+
+	ret = zynq_cpun_start(rproc->bootaddr, 1);
+	/* Trigger pending kicks */
+	kick_pending_ipi(rproc);
+
+	return ret;
+}
+
+/* kick a firmware */
+static void zynq_rproc_kick(struct rproc *rproc, int vqid)
+{
+	struct device *dev = rproc->dev.parent;
+	struct zynq_rproc_pdata *local = rproc->priv;
+	struct rproc_vdev *rvdev, *rvtmp;
+	int i;
+
+	dev_dbg(dev, "KICK Firmware to start send messages vqid %d\n", vqid);
+
+	list_for_each_entry_safe(rvdev, rvtmp, &rproc->rvdevs, node) {
+		for (i = 0; i < MAX_NUM_VRINGS; i++) {
+			struct rproc_vring *rvring = &rvdev->vring[i];
+
+			/* Send swirq to firmware */
+			if (rvring->notifyid == vqid) {
+				local->ipis[i].notifyid = vqid;
+				/* As we do not turn off CPU1 until start,
+				 * we delay firmware kick
+				 */
+				if (rproc->state == RPROC_RUNNING)
+					gic_raise_softirq(cpumask_of(1),
+							  local->ipis[i].irq);
+				else
+					local->ipis[i].pending = true;
+			}
+		}
+	}
+}
+
+/* power off the remote processor */
+static int zynq_rproc_stop(struct rproc *rproc)
+{
+	int ret;
+	struct device *dev = rproc->dev.parent;
+
+	dev_dbg(rproc->dev.parent, "%s\n", __func__);
+
+	/* Cpu can't be power on - for example in nosmp mode */
+	ret = cpu_up(1);
+	if (ret)
+		dev_err(dev, "Can't power on cpu1 %d\n", ret);
+
+	return 0;
+}
+
+static int zynq_parse_fw(struct rproc *rproc, const struct firmware *fw)
+{
+	int num_mems, i, ret;
+	struct device *dev = rproc->dev.parent;
+	struct device_node *np = dev->of_node;
+	struct rproc_mem_entry *mem;
+
+	num_mems = of_count_phandle_with_args(np, "memory-region", NULL);
+	if (num_mems <= 0)
+		return 0;
+	for (i = 0; i < num_mems; i++) {
+		struct device_node *node;
+		struct reserved_mem *rmem;
+
+		node = of_parse_phandle(np, "memory-region", i);
+		rmem = of_reserved_mem_lookup(node);
+		if (!rmem) {
+			dev_err(dev, "unable to acquire memory-region\n");
+			return -EINVAL;
+		}
+		if (strstr(node->name, "vdev") &&
+			strstr(node->name, "buffer")) {
+			/* Register DMA region */
+			mem = rproc_mem_entry_init(dev, NULL,
+						   (dma_addr_t)rmem->base,
+						   rmem->size, rmem->base,
+						   NULL, NULL,
+						   node->name);
+			if (!mem) {
+				dev_err(dev,
+					"unable to initialize memory-region %s \n",
+					node->name);
+				return -ENOMEM;
+			}
+			rproc_add_carveout(rproc, mem);
+		} else if (strstr(node->name, "vdev") &&
+			   strstr(node->name, "vring")) {
+			/* Register vring */
+			mem = rproc_mem_entry_init(dev, NULL,
+						   (dma_addr_t)rmem->base,
+						   rmem->size, rmem->base,
+						   NULL, NULL,
+						   node->name);
+			mem->va = devm_ioremap_wc(dev, rmem->base, rmem->size);
+			if (!mem->va)
+				return -ENOMEM;
+			if (!mem) {
+				dev_err(dev,
+					"unable to initialize memory-region %s\n",
+					node->name);
+				return -ENOMEM;
+			}
+			rproc_add_carveout(rproc, mem);
+		} else {
+			mem = rproc_of_resm_mem_entry_init(dev, i,
+							rmem->size,
+							rmem->base,
+							node->name);
+			if (!mem) {
+				dev_err(dev,
+					"unable to initialize memory-region %s \n",
+					node->name);
+				return -ENOMEM;
+			}
+			mem->va = devm_ioremap_wc(dev, rmem->base, rmem->size);
+			if (!mem->va)
+				return -ENOMEM;
+
+			rproc_add_carveout(rproc, mem);
+		}
+	}
+
+	ret = rproc_elf_load_rsc_table(rproc, fw);
+	if (ret == -EINVAL)
+		ret = 0;
+	return ret;
+}
+
+static struct rproc_ops zynq_rproc_ops = {
+	.start		= zynq_rproc_start,
+	.stop		= zynq_rproc_stop,
+	.load		= rproc_elf_load_segments,
+	.parse_fw	= zynq_parse_fw,
+	.find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table,
+	.get_boot_addr	= rproc_elf_get_boot_addr,
+	.kick		= zynq_rproc_kick,
+};
+
+/* Just to detect bug if interrupt forwarding is broken */
+static irqreturn_t zynq_remoteproc_interrupt(int irq, void *dev_id)
+{
+	struct device *dev = dev_id;
+
+	dev_err(dev, "GIC IRQ %d is not forwarded correctly\n", irq);
+
+	/*
+	 *  MS: Calling this function doesn't need to be BUG
+	 * especially for cases where firmware doesn't disable
+	 * interrupts. In next probing can be som interrupts pending.
+	 * The next scenario is for cases when you want to monitor
+	 * non frequent interrupt through Linux kernel. Interrupt happen
+	 * and it is forwarded to Linux which update own statistic
+	 * in (/proc/interrupt) and forward it to firmware.
+	 *
+	 * gic_set_cpu(1, irq);	- setup cpu1 as destination cpu
+	 * gic_raise_softirq(cpumask_of(1), irq); - forward irq to firmware
+	 */
+
+	gic_set_cpu(1, irq);
+	return IRQ_HANDLED;
+}
+
+static void clear_irq(struct rproc *rproc)
+{
+	struct list_head *pos, *q;
+	struct irq_list *tmp;
+	struct zynq_rproc_pdata *local = rproc->priv;
+
+	dev_info(rproc->dev.parent, "Deleting the irq_list\n");
+	list_for_each_safe(pos, q, &local->irqs.list) {
+		tmp = list_entry(pos, struct irq_list, list);
+		free_irq(tmp->irq, rproc->dev.parent);
+		gic_set_cpu(0, tmp->irq);
+		list_del(pos);
+		kfree(tmp);
+	}
+}
+
+static int zynq_remoteproc_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct irq_list *tmp;
+	int count = 0;
+	struct zynq_rproc_pdata *local;
+
+	rproc = rproc_alloc(&pdev->dev, dev_name(&pdev->dev),
+			    &zynq_rproc_ops, NULL,
+		sizeof(struct zynq_rproc_pdata));
+	if (!rproc) {
+		dev_err(&pdev->dev, "rproc allocation failed\n");
+		ret = -ENOMEM;
+		return ret;
+	}
+	local = rproc->priv;
+	local->rproc = rproc;
+
+	platform_set_drvdata(pdev, rproc);
+
+	ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+	if (ret) {
+		dev_err(&pdev->dev, "dma_set_coherent_mask: %d\n", ret);
+		goto dma_mask_fault;
+	}
+
+	/* Init list for IRQs - it can be long list */
+	INIT_LIST_HEAD(&local->irqs.list);
+
+	/* Alloc IRQ based on DTS to be sure that no other driver will use it */
+	while (1) {
+		int irq;
+
+		irq = platform_get_irq(pdev, count++);
+		if (irq == -ENXIO || irq == -EINVAL)
+			break;
+
+		tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
+		if (!tmp) {
+			ret = -ENOMEM;
+			goto irq_fault;
+		}
+
+		tmp->irq = irq;
+
+		dev_dbg(&pdev->dev, "%d: Alloc irq: %d\n", count, tmp->irq);
+
+		/* Allocating shared IRQs will ensure that any module will
+		 * use these IRQs
+		 */
+		ret = request_irq(tmp->irq, zynq_remoteproc_interrupt, 0,
+				  dev_name(&pdev->dev), &pdev->dev);
+		if (ret) {
+			dev_err(&pdev->dev, "IRQ %d already allocated\n",
+				tmp->irq);
+			goto irq_fault;
+		}
+
+		/*
+		 * MS: Here is place for detecting problem with firmware
+		 * which doesn't work correctly with interrupts
+		 *
+		 * MS: Comment if you want to count IRQs on Linux
+		 */
+		gic_set_cpu(1, tmp->irq);
+		list_add(&tmp->list, &local->irqs.list);
+	}
+
+	/* Allocate free IPI number */
+	/* Read vring0 ipi number */
+	ret = of_property_read_u32(pdev->dev.of_node, "vring0",
+				   &local->ipis[0].irq);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "unable to read property");
+		goto irq_fault;
+	}
+
+	ret = set_ipi_handler(local->ipis[0].irq, ipi_kick,
+			      "Firmware kick");
+	if (ret) {
+		dev_err(&pdev->dev, "IPI handler already registered\n");
+		goto irq_fault;
+	}
+
+	/* Read vring1 ipi number */
+	ret = of_property_read_u32(pdev->dev.of_node, "vring1",
+				   &local->ipis[1].irq);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "unable to read property");
+		goto ipi_fault;
+	}
+
+	rproc->auto_boot = autoboot;
+
+	ret = rproc_add(local->rproc);
+	if (ret) {
+		dev_err(&pdev->dev, "rproc registration failed\n");
+		goto ipi_fault;
+	}
+
+	return 0;
+
+ipi_fault:
+	clear_ipi_handler(local->ipis[0].irq);
+
+irq_fault:
+	clear_irq(rproc);
+
+dma_mask_fault:
+	rproc_free(rproc);
+
+	return ret;
+}
+
+static int zynq_remoteproc_remove(struct platform_device *pdev)
+{
+	struct rproc *rproc = platform_get_drvdata(pdev);
+	struct zynq_rproc_pdata *local = rproc->priv;
+
+	dev_info(&pdev->dev, "%s\n", __func__);
+
+	rproc_del(rproc);
+
+	clear_ipi_handler(local->ipis[0].irq);
+	clear_irq(rproc);
+
+	of_reserved_mem_device_release(&pdev->dev);
+	rproc_free(rproc);
+
+	return 0;
+}
+
+/* Match table for OF platform binding */
+static const struct of_device_id zynq_remoteproc_match[] = {
+	{ .compatible = "xlnx,zynq_remoteproc", },
+	{ /* end of list */ },
+};
+MODULE_DEVICE_TABLE(of, zynq_remoteproc_match);
+
+static struct platform_driver zynq_remoteproc_driver = {
+	.probe = zynq_remoteproc_probe,
+	.remove = zynq_remoteproc_remove,
+	.driver = {
+		.name = "zynq_remoteproc",
+		.of_match_table = zynq_remoteproc_match,
+	},
+};
+module_platform_driver(zynq_remoteproc_driver);
+
+module_param_named(autoboot,  autoboot, bool, 0444);
+MODULE_PARM_DESC(autoboot,
+		 "enable | disable autoboot. (default: false)");
+
+MODULE_AUTHOR("Michal Simek <monstr@monstr.eu");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Zynq remote processor control driver");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/remoteproc/zynqmp_r5_remoteproc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/remoteproc/zynqmp_r5_remoteproc.c
@@ -0,0 +1,979 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Zynq R5 Remote Processor driver
+ *
+ * Copyright (C) 2015 - 2018 Xilinx Inc.
+ * Copyright (C) 2015 Jason Wu <j.wu@xilinx.com>
+ *
+ * Based on origin OMAP and Zynq Remote Processor driver
+ *
+ * Copyright (C) 2012 Michal Simek <monstr@monstr.eu>
+ * Copyright (C) 2012 PetaLogix
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Copyright (C) 2011 Google, Inc.
+ */
+
+#include <linux/atomic.h>
+#include <linux/cpu.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/firmware/xlnx-zynqmp.h>
+#include <linux/genalloc.h>
+#include <linux/idr.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/mailbox_client.h>
+#include <linux/mailbox/zynqmp-ipi-message.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/of_reserved_mem.h>
+#include <linux/pfn.h>
+#include <linux/platform_device.h>
+#include <linux/remoteproc.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+
+#include "remoteproc_internal.h"
+
+#define MAX_RPROCS	2 /* Support up to 2 RPU */
+#define MAX_MEM_PNODES	4 /* Max power nodes for one RPU memory instance */
+
+#define DEFAULT_FIRMWARE_NAME	"rproc-rpu-fw"
+
+/* PM proc states */
+#define PM_PROC_STATE_ACTIVE 1U
+
+/* IPI buffer MAX length */
+#define IPI_BUF_LEN_MAX	32U
+/* RX mailbox client buffer max length */
+#define RX_MBOX_CLIENT_BUF_MAX	(IPI_BUF_LEN_MAX + \
+				 sizeof(struct zynqmp_ipi_message))
+
+static bool autoboot __read_mostly;
+static bool allow_sysfs_kick __read_mostly;
+
+static const struct zynqmp_eemi_ops *eemi_ops;
+
+/**
+ * struct zynqmp_r5_mem - zynqmp rpu memory data
+ * @pnode_id: TCM power domain ids
+ * @res: memory resource
+ * @node: list node
+ */
+struct zynqmp_r5_mem {
+	u32 pnode_id[MAX_MEM_PNODES];
+	struct resource res;
+	struct list_head node;
+};
+
+/**
+ * struct zynqmp_r5_pdata - zynqmp rpu remote processor private data
+ * @dev: device of RPU instance
+ * @rproc: rproc handle
+ * @parent: RPU slot platform data
+ * @pnode_id: RPU CPU power domain id
+ * @mems: memory resources
+ * @is_r5_mode_set: indicate if r5 operation mode is set
+ * @tx_mc: tx mailbox client
+ * @rx_mc: rx mailbox client
+ * @tx_chan: tx mailbox channel
+ * @rx_chan: rx mailbox channel
+ * @workqueue: workqueue for the RPU remoteproc
+ * @tx_mc_skbs: socket buffers for tx mailbox client
+ * @rx_mc_buf: rx mailbox client buffer to save the rx message
+ * @remote_kick: flag to indicate if there is a kick from remote
+ */
+struct zynqmp_r5_pdata {
+	struct device dev;
+	struct rproc *rproc;
+	struct zynqmp_rpu_domain_pdata *parent;
+	u32 pnode_id;
+	struct list_head mems;
+	bool is_r5_mode_set;
+	struct mbox_client tx_mc;
+	struct mbox_client rx_mc;
+	struct mbox_chan *tx_chan;
+	struct mbox_chan *rx_chan;
+	struct work_struct workqueue;
+	struct sk_buff_head tx_mc_skbs;
+	unsigned char rx_mc_buf[RX_MBOX_CLIENT_BUF_MAX];
+	atomic_t remote_kick;
+};
+
+/**
+ * struct zynqmp_rpu_domain_pdata - zynqmp rpu platform data
+ * @rpus: table of RPUs
+ * @rpu_mode: RPU core configuration
+ */
+struct zynqmp_rpu_domain_pdata {
+	struct zynqmp_r5_pdata rpus[MAX_RPROCS];
+	enum rpu_oper_mode rpu_mode;
+};
+
+/*
+ * r5_set_mode - set RPU operation mode
+ * @pdata: Remote processor private data
+ *
+ * set RPU oepration mode
+ *
+ * Return: 0 for success, negative value for failure
+ */
+static int r5_set_mode(struct zynqmp_r5_pdata *pdata)
+{
+	u32 val[PAYLOAD_ARG_CNT] = {0}, expect;
+	struct zynqmp_rpu_domain_pdata *parent;
+	struct device *dev = &pdata->dev;
+	int ret;
+
+	if (pdata->is_r5_mode_set)
+		return 0;
+	parent = pdata->parent;
+	expect = (u32)parent->rpu_mode;
+	ret = eemi_ops->ioctl(pdata->pnode_id, IOCTL_GET_RPU_OPER_MODE,
+			  0, 0, val);
+	if (ret < 0) {
+		dev_err(dev, "failed to get RPU oper mode.\n");
+		return ret;
+	}
+	if (val[0] == expect) {
+		dev_dbg(dev, "RPU mode matches: %x\n", val[0]);
+	} else {
+		ret = eemi_ops->ioctl(pdata->pnode_id,
+				  IOCTL_SET_RPU_OPER_MODE,
+				  expect, 0, val);
+		if (ret < 0) {
+			dev_err(dev,
+				"failed to set RPU oper mode.\n");
+			return ret;
+		}
+	}
+	if (expect == (u32)PM_RPU_MODE_LOCKSTEP)
+		expect = (u32)PM_RPU_TCM_COMB;
+	else
+		expect = (u32)PM_RPU_TCM_SPLIT;
+	ret = eemi_ops->ioctl(pdata->pnode_id, IOCTL_TCM_COMB_CONFIG,
+			  expect, 0, val);
+	if (ret < 0) {
+		dev_err(dev, "failed to config TCM to %x.\n",
+			expect);
+		return ret;
+	}
+	pdata->is_r5_mode_set = true;
+	return 0;
+}
+
+/**
+ * r5_is_running - check if r5 is running
+ * @pdata: Remote processor private data
+ *
+ * check if R5 is running
+ *
+ * Return: true if r5 is running, false otherwise
+ */
+static bool r5_is_running(struct zynqmp_r5_pdata *pdata)
+{
+	u32 status, requirements, usage;
+	struct device *dev = &pdata->dev;
+
+	if (eemi_ops->get_node_status(pdata->pnode_id,
+				      &status, &requirements, &usage)) {
+		dev_err(dev, "Failed to get RPU node %d status.\n",
+			pdata->pnode_id);
+		return false;
+	} else if (status != PM_PROC_STATE_ACTIVE) {
+		dev_dbg(dev, "RPU is not running.\n");
+		return false;
+	}
+
+	dev_dbg(dev, "RPU is running.\n");
+	return true;
+}
+
+/*
+ * ZynqMP R5 remoteproc memory release function
+ */
+static int zynqmp_r5_mem_release(struct rproc *rproc,
+				 struct rproc_mem_entry *mem)
+{
+	struct zynqmp_r5_mem *priv;
+	int i, ret;
+	struct device *dev = &rproc->dev;
+
+	priv = mem->priv;
+	if (!priv)
+		return 0;
+	for (i = 0; i < MAX_MEM_PNODES; i++) {
+		if (priv->pnode_id[i]) {
+			dev_dbg(dev, "%s, pnode %d\n",
+				__func__, priv->pnode_id[i]);
+			ret = eemi_ops->release_node(priv->pnode_id[i]);
+			if (ret < 0) {
+				dev_err(dev,
+					"failed to release power node: %u\n",
+					priv->pnode_id[i]);
+				return ret;
+			}
+		} else {
+			break;
+		}
+	}
+	return 0;
+}
+
+/*
+ * ZynqMP R5 remoteproc operations
+ */
+static int zynqmp_r5_rproc_start(struct rproc *rproc)
+{
+	struct device *dev = rproc->dev.parent;
+	struct zynqmp_r5_pdata *local = rproc->priv;
+	enum rpu_boot_mem bootmem;
+	int ret;
+
+	/* Set up R5 */
+	ret = r5_set_mode(local);
+	if (ret) {
+		dev_err(dev, "failed to set R5 operation mode.\n");
+		return ret;
+	}
+	if ((rproc->bootaddr & 0xF0000000) == 0xF0000000)
+		bootmem = PM_RPU_BOOTMEM_HIVEC;
+	else
+		bootmem = PM_RPU_BOOTMEM_LOVEC;
+	dev_info(dev, "RPU boot from %s.",
+		 bootmem == PM_RPU_BOOTMEM_HIVEC ? "OCM" : "TCM");
+
+	ret = eemi_ops->request_wakeup(local->pnode_id, 1, bootmem,
+				       ZYNQMP_PM_REQUEST_ACK_NO);
+	if (ret < 0) {
+		dev_err(dev, "failed to boot R5.\n");
+		return ret;
+	}
+	return 0;
+}
+
+static int zynqmp_r5_rproc_stop(struct rproc *rproc)
+{
+	struct zynqmp_r5_pdata *local = rproc->priv;
+	int ret;
+
+	ret = eemi_ops->force_powerdown(local->pnode_id,
+					ZYNQMP_PM_REQUEST_ACK_BLOCKING);
+	if (ret < 0) {
+		dev_err(&local->dev, "failed to shutdown R5.\n");
+		return ret;
+	}
+	local->is_r5_mode_set = false;
+	return 0;
+}
+
+
+static int zynqmp_r5_parse_fw(struct rproc *rproc, const struct firmware *fw)
+{
+	int num_mems, i, ret;
+	struct zynqmp_r5_pdata *pdata = rproc->priv;
+	struct device *dev = &pdata->dev;
+	struct device_node *np = dev->of_node;
+	struct rproc_mem_entry *mem;
+	struct device_node *child;
+	struct resource rsc;
+
+	num_mems = of_count_phandle_with_args(np, "memory-region", NULL);
+	if (num_mems <= 0)
+		return 0;
+
+	for (i = 0; i < num_mems; i++) {
+		struct device_node *node;
+		struct zynqmp_r5_mem *zynqmp_mem;
+		struct reserved_mem *rmem;
+
+		node = of_parse_phandle(np, "memory-region", i);
+		rmem = of_reserved_mem_lookup(node);
+		if (!rmem) {
+			dev_err(dev, "unable to acquire memory-region\n");
+			return -EINVAL;
+		}
+		if (strstr(node->name, "vdev") &&
+			strstr(node->name, "buffer")) {
+			int id;
+			char name[16];
+
+			id = node->name[8] - '0';
+			snprintf(name, sizeof(name), "vdev%dbuffer", id);
+			/* Register DMA region */
+			mem = rproc_mem_entry_init(dev, NULL,
+						   (dma_addr_t)rmem->base,
+						   rmem->size, rmem->base,
+						   NULL, NULL,
+						   name);
+			if (!mem) {
+				dev_err(dev, "unable to initialize memory-region %s\n",
+						node->name);
+				return -ENOMEM;
+			}
+			dev_dbg(dev, "parsed %s at  %llx\r\n", mem->name,
+				mem->dma);
+			rproc_add_carveout(rproc, mem);
+			continue;
+		} else if (strstr(node->name, "vdev") &&
+				    strstr(node->name, "vring")) {
+			int id, vring_id;
+			char name[16];
+
+			id = node->name[8] - '0';
+			vring_id = node->name[14] - '0';
+			snprintf(name, sizeof(name), "vdev%dvring%d", id,
+				 vring_id);
+			/* Register vring */
+			mem = rproc_mem_entry_init(dev, NULL,
+						   (dma_addr_t)rmem->base,
+						   rmem->size, rmem->base,
+						   NULL, NULL,
+						   name);
+			mem->va = devm_ioremap_wc(dev, rmem->base, rmem->size);
+			if (!mem->va)
+				return -ENOMEM;
+			if (!mem) {
+				dev_err(dev, "unable to initialize memory-region %s\n",
+						node->name);
+				return -ENOMEM;
+			}
+			dev_dbg(dev, "parsed %s at %llx\r\n", mem->name,
+				mem->dma);
+			rproc_add_carveout(rproc, mem);
+			continue;
+		} else {
+			mem = rproc_of_resm_mem_entry_init(dev, i,
+							rmem->size,
+							rmem->base,
+							node->name);
+			if (!mem) {
+				dev_err(dev, "unable to initialize memory-region %s \n",
+						node->name);
+				return -ENOMEM;
+			}
+			mem->va = devm_ioremap_wc(dev, rmem->base, rmem->size);
+			if (!mem->va)
+				return -ENOMEM;
+
+			rproc_add_carveout(rproc, mem);
+		}
+		if (!mem)
+			return -ENOMEM;
+
+
+		/*
+		 * It is non-DMA memory, used for firmware loading.
+		 * It will be added to the R5 remoteproc mappings later.
+		 */
+		zynqmp_mem = devm_kzalloc(dev, sizeof(*zynqmp_mem), GFP_KERNEL);
+		if (!zynqmp_mem)
+			return -ENOMEM;
+		ret = of_address_to_resource(node, 0, &zynqmp_mem->res);
+		if (ret) {
+			dev_err(dev, "unable to resolve memory region.\n");
+			return ret;
+		}
+		list_add_tail(&zynqmp_mem->node, &pdata->mems);
+		dev_dbg(dev, "%s, non-dma mem %s\n",
+			__func__, of_node_full_name(node));
+	}
+
+	/* map TCM memories */
+	for_each_available_child_of_node(np, child) {
+		struct property *prop;
+		const __be32 *cur;
+		u32 pnode_id;
+		void *va;
+		dma_addr_t dma;
+		resource_size_t size;
+
+		ret = of_address_to_resource(child, 0, &rsc);
+
+		i = 0;
+		of_property_for_each_u32(child, "pnode-id", prop, cur,
+								pnode_id) {
+			ret = eemi_ops->request_node(pnode_id,
+						ZYNQMP_PM_CAPABILITY_ACCESS, 0,
+						ZYNQMP_PM_REQUEST_ACK_BLOCKING);
+			if (ret < 0) {
+				dev_err(dev, "failed to request power node: %u\n",
+						pnode_id);
+				return ret;
+			}
+			ret = r5_set_mode(pdata);
+			if (ret < 0) {
+				dev_err(dev, "failed to set R5 operation mode.\n");
+				return ret;
+			}
+		}
+		size = resource_size(&rsc);
+
+		va = devm_ioremap_wc(dev, rsc.start, size);
+		if (!va)
+			return -ENOMEM;
+
+		/* zero out tcm base address */
+		if (rsc.start & 0xffe00000) {
+				rsc.start &= 0x000fffff;
+		/* handle tcm banks 1 a and b (0xffe9000 and oxffeb0000) */
+				if (rsc.start & 0x80000)
+					rsc.start -= 0x90000;
+		}
+
+		dma = (dma_addr_t)rsc.start;
+		mem = rproc_mem_entry_init(dev, va, dma, (int)size, rsc.start,
+						 NULL, zynqmp_r5_mem_release,
+						 rsc.name);
+		if (!mem)
+			return -ENOMEM;
+
+		rproc_add_carveout(rproc, mem);
+	}
+
+	ret = rproc_elf_load_rsc_table(rproc, fw);
+	if (ret == -EINVAL)
+		ret = 0;
+	return ret;
+}
+
+/* kick a firmware */
+static void zynqmp_r5_rproc_kick(struct rproc *rproc, int vqid)
+{
+	struct device *dev = rproc->dev.parent;
+	struct zynqmp_r5_pdata *local = rproc->priv;
+
+	dev_dbg(dev, "KICK Firmware to start send messages vqid %d\n", vqid);
+
+	if (vqid < 0) {
+		/* If vqid is negative, does not pass the vqid to
+		 * mailbox. As vqid is supposed to be 0 or possive.
+		 * It also gives a way to just kick instead but
+		 * not use the IPI buffer. It is better to provide
+		 * a proper way to pass the short message, which will
+		 * need to sync to upstream first, for now,
+		 * use negative vqid to assume no message will be
+		 * passed with IPI buffer, but just raise interrupt.
+		 * This will be faster as it doesn't need to copy the
+		 * message to the IPI buffer.
+		 *
+		 * It will ignore the return, as failure is due to
+		 * there already kicks in the mailbox queue.
+		 */
+		(void)mbox_send_message(local->tx_chan, NULL);
+	} else {
+		struct sk_buff *skb;
+		unsigned int skb_len;
+		struct zynqmp_ipi_message *mb_msg;
+		int ret;
+
+		skb_len = (unsigned int)(sizeof(vqid) + sizeof(mb_msg));
+		skb = alloc_skb(skb_len, GFP_ATOMIC);
+		if (!skb) {
+			dev_err(dev,
+				"Failed to allocate skb to kick remote.\n");
+			return;
+		}
+		mb_msg = (struct zynqmp_ipi_message *)skb_put(skb, skb_len);
+		mb_msg->len = sizeof(vqid);
+		memcpy(mb_msg->data, &vqid, sizeof(vqid));
+		skb_queue_tail(&local->tx_mc_skbs, skb);
+		ret = mbox_send_message(local->tx_chan, mb_msg);
+		if (ret < 0) {
+			dev_warn(dev, "Failed to kick remote.\n");
+			skb_dequeue_tail(&local->tx_mc_skbs);
+			kfree_skb(skb);
+		}
+	}
+}
+
+static bool zynqmp_r5_rproc_peek_remote_kick(struct rproc *rproc,
+					     char *buf, size_t *len)
+{
+	struct device *dev = rproc->dev.parent;
+	struct zynqmp_r5_pdata *local = rproc->priv;
+
+	dev_dbg(dev, "Peek if remote has kicked\n");
+
+	if (atomic_read(&local->remote_kick) != 0) {
+		if (buf && len) {
+			struct zynqmp_ipi_message *msg;
+
+			msg = (struct zynqmp_ipi_message *)local->rx_mc_buf;
+			memcpy(buf, msg->data, msg->len);
+			*len = (size_t)msg->len;
+		}
+		return true;
+	} else {
+		return false;
+	}
+}
+
+static void zynqmp_r5_rproc_ack_remote_kick(struct rproc *rproc)
+{
+	struct device *dev = rproc->dev.parent;
+	struct zynqmp_r5_pdata *local = rproc->priv;
+
+	dev_dbg(dev, "Ack remote\n");
+
+	atomic_set(&local->remote_kick, 0);
+	(void)mbox_send_message(local->rx_chan, NULL);
+}
+
+static struct rproc_ops zynqmp_r5_rproc_ops = {
+	.start		= zynqmp_r5_rproc_start,
+	.stop		= zynqmp_r5_rproc_stop,
+	.load		= rproc_elf_load_segments,
+	.parse_fw	= zynqmp_r5_parse_fw,
+	.find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table,
+	.sanity_check	= rproc_elf_sanity_check,
+	.get_boot_addr	= rproc_elf_get_boot_addr,
+	.kick		= zynqmp_r5_rproc_kick,
+	.peek_remote_kick	= zynqmp_r5_rproc_peek_remote_kick,
+	.ack_remote_kick	= zynqmp_r5_rproc_ack_remote_kick,
+};
+
+/* zynqmp_r5_mem_probe() - probes RPU TCM memory device
+ * @pdata: pointer to the RPU remoteproc private data
+ * @node: pointer to the memory node
+ *
+ * Function to retrieve memories resources for RPU TCM memory device.
+ */
+static int zynqmp_r5_mem_probe(struct zynqmp_r5_pdata *pdata,
+			       struct device_node *node)
+{
+	struct device *dev;
+	struct zynqmp_r5_mem *mem;
+	int ret;
+
+	dev = &pdata->dev;
+	mem = devm_kzalloc(dev, sizeof(*mem), GFP_KERNEL);
+	if (!mem)
+		return -ENOMEM;
+	ret = of_address_to_resource(node, 0, &mem->res);
+	if (ret < 0) {
+		dev_err(dev, "failed to get resource of memory %s",
+			of_node_full_name(node));
+		return -EINVAL;
+	}
+
+	/* Get the power domain id */
+	if (of_find_property(node, "pnode-id", NULL)) {
+		struct property *prop;
+		const __be32 *cur;
+		u32 val;
+		int i = 0;
+
+		of_property_for_each_u32(node, "pnode-id", prop, cur, val)
+			mem->pnode_id[i++] = val;
+	}
+	list_add_tail(&mem->node, &pdata->mems);
+	return 0;
+}
+
+/**
+ * zynqmp_r5_release() - ZynqMP R5 device release function
+ * @dev: pointer to the device struct of ZynqMP R5
+ *
+ * Function to release ZynqMP R5 device.
+ */
+static void zynqmp_r5_release(struct device *dev)
+{
+	struct zynqmp_r5_pdata *pdata;
+	struct rproc *rproc;
+	struct sk_buff *skb;
+
+	pdata = dev_get_drvdata(dev);
+	rproc = pdata->rproc;
+	if (rproc) {
+		rproc_del(rproc);
+		rproc_free(rproc);
+	}
+	if (pdata->tx_chan)
+		mbox_free_channel(pdata->tx_chan);
+	if (pdata->rx_chan)
+		mbox_free_channel(pdata->rx_chan);
+	/* Discard all SKBs */
+	while (!skb_queue_empty(&pdata->tx_mc_skbs)) {
+		skb = skb_dequeue(&pdata->tx_mc_skbs);
+		kfree_skb(skb);
+	}
+
+	put_device(dev->parent);
+}
+
+/**
+ * event_notified_idr_cb() - event notified idr callback
+ * @id: idr id
+ * @ptr: pointer to idr private data
+ * @data: data passed to idr_for_each callback
+ *
+ * Pass notification to remtoeproc virtio
+ *
+ * Return: 0. having return is to satisfy the idr_for_each() function
+ *          pointer input argument requirement.
+ **/
+static int event_notified_idr_cb(int id, void *ptr, void *data)
+{
+	struct rproc *rproc = data;
+
+	(void)rproc_vq_interrupt(rproc, id);
+	return 0;
+}
+
+/**
+ * handle_event_notified() - remoteproc notification work funciton
+ * @work: pointer to the work structure
+ *
+ * It checks each registered remoteproc notify IDs.
+ */
+static void handle_event_notified(struct work_struct *work)
+{
+	struct rproc *rproc;
+	struct zynqmp_r5_pdata *local;
+
+	local = container_of(work, struct zynqmp_r5_pdata, workqueue);
+
+	(void)mbox_send_message(local->rx_chan, NULL);
+	rproc = local->rproc;
+	if (rproc->sysfs_kick) {
+		sysfs_notify(&rproc->dev.kobj, NULL, "remote_kick");
+		return;
+	}
+	/*
+	 * We only use IPI for interrupt. The firmware side may or may
+	 * not write the notifyid when it trigger IPI.
+	 * And thus, we scan through all the registered notifyids.
+	 */
+	idr_for_each(&rproc->notifyids, event_notified_idr_cb, rproc);
+}
+
+/**
+ * zynqmp_r5_mb_rx_cb() - Receive channel mailbox callback
+ * @cl: mailbox client
+ * @mssg: message pointer
+ *
+ * It will schedule the R5 notification work.
+ */
+static void zynqmp_r5_mb_rx_cb(struct mbox_client *cl, void *mssg)
+{
+	struct zynqmp_r5_pdata *local;
+
+	local = container_of(cl, struct zynqmp_r5_pdata, rx_mc);
+	if (mssg) {
+		struct zynqmp_ipi_message *ipi_msg, *buf_msg;
+		size_t len;
+
+		ipi_msg = (struct zynqmp_ipi_message *)mssg;
+		buf_msg = (struct zynqmp_ipi_message *)local->rx_mc_buf;
+		len = (ipi_msg->len >= IPI_BUF_LEN_MAX) ?
+		      IPI_BUF_LEN_MAX : ipi_msg->len;
+		buf_msg->len = len;
+		memcpy(buf_msg->data, ipi_msg->data, len);
+	}
+	atomic_set(&local->remote_kick, 1);
+	schedule_work(&local->workqueue);
+}
+
+/**
+ * zynqmp_r5_mb_tx_done() - Request has been sent to the remote
+ * @cl: mailbox client
+ * @mssg: pointer to the message which has been sent
+ * @r: status of last TX - OK or error
+ *
+ * It will be called by the mailbox framework when the last TX has done.
+ */
+static void zynqmp_r5_mb_tx_done(struct mbox_client *cl, void *mssg, int r)
+{
+	struct zynqmp_r5_pdata *local;
+	struct sk_buff *skb;
+
+	if (!mssg)
+		return;
+	local = container_of(cl, struct zynqmp_r5_pdata, tx_mc);
+	skb = skb_dequeue(&local->tx_mc_skbs);
+	kfree_skb(skb);
+}
+
+/**
+ * zynqmp_r5_setup_mbox() - Setup mailboxes
+ *
+ * @pdata: pointer to the ZynqMP R5 processor platform data
+ * @node: pointer of the device node
+ *
+ * Function to setup mailboxes to talk to RPU.
+ *
+ * Return: 0 for success, negative value for failure.
+ */
+static int zynqmp_r5_setup_mbox(struct zynqmp_r5_pdata *pdata,
+				struct device_node *node)
+{
+	struct device *dev = &pdata->dev;
+	struct mbox_client *mclient;
+
+	/* Setup TX mailbox channel client */
+	mclient = &pdata->tx_mc;
+	mclient->dev = dev;
+	mclient->rx_callback = NULL;
+	mclient->tx_block = false;
+	mclient->knows_txdone = false;
+	mclient->tx_done = zynqmp_r5_mb_tx_done;
+
+	/* Setup TX mailbox channel client */
+	mclient = &pdata->rx_mc;
+	mclient->dev = dev;
+	mclient->rx_callback = zynqmp_r5_mb_rx_cb;
+	mclient->tx_block = false;
+	mclient->knows_txdone = false;
+
+	INIT_WORK(&pdata->workqueue, handle_event_notified);
+
+	atomic_set(&pdata->remote_kick, 0);
+	/* Request TX and RX channels */
+	pdata->tx_chan = mbox_request_channel_byname(&pdata->tx_mc, "tx");
+	if (IS_ERR(pdata->tx_chan)) {
+		dev_err(dev, "failed to request mbox tx channel.\n");
+		pdata->tx_chan = NULL;
+		return -EINVAL;
+	}
+	pdata->rx_chan = mbox_request_channel_byname(&pdata->rx_mc, "rx");
+	if (IS_ERR(pdata->rx_chan)) {
+		dev_err(dev, "failed to request mbox rx channel.\n");
+		pdata->rx_chan = NULL;
+		return -EINVAL;
+	}
+	skb_queue_head_init(&pdata->tx_mc_skbs);
+	return 0;
+}
+
+/**
+ * zynqmp_r5_probe() - Probes ZynqMP R5 processor device node
+ * @pdata: pointer to the ZynqMP R5 processor platform data
+ * @pdev: parent RPU domain platform device
+ * @node: pointer of the device node
+ *
+ * Function to retrieve the information of the ZynqMP R5 device node.
+ *
+ * Return: 0 for success, negative value for failure.
+ */
+static int zynqmp_r5_probe(struct zynqmp_r5_pdata *pdata,
+			   struct platform_device *pdev,
+			   struct device_node *node)
+{
+	struct device *dev = &pdata->dev;
+	struct rproc *rproc;
+	struct device_node *nc;
+	int ret;
+
+	/* Create device for ZynqMP R5 device */
+	dev->parent = &pdev->dev;
+	dev->release = zynqmp_r5_release;
+	dev->of_node = node;
+	dev_set_name(dev, "%s", of_node_full_name(node));
+	dev_set_drvdata(dev, pdata);
+	ret = device_register(dev);
+	if (ret) {
+		dev_err(dev, "failed to register device.\n");
+		return ret;
+	}
+	get_device(&pdev->dev);
+
+	/* Allocate remoteproc instance */
+	rproc = rproc_alloc(dev, dev_name(dev), &zynqmp_r5_rproc_ops, NULL, 0);
+	if (!rproc) {
+		dev_err(dev, "rproc allocation failed.\n");
+		ret = -ENOMEM;
+		goto error;
+	}
+	rproc->auto_boot = autoboot;
+	pdata->rproc = rproc;
+	rproc->priv = pdata;
+
+	/*
+	 * The device has not been spawned from a device tree, so
+	 * arch_setup_dma_ops has not been not called, thus leaving
+	 * the device with dummy DMA ops.
+	 * Fix this by inheriting the parent's DMA ops and mask.
+	 */
+	rproc->dev.dma_mask = pdev->dev.dma_mask;
+	set_dma_ops(&rproc->dev, get_dma_ops(&pdev->dev));
+
+	/* Probe R5 memory devices */
+	INIT_LIST_HEAD(&pdata->mems);
+	for_each_available_child_of_node(node, nc) {
+		ret = zynqmp_r5_mem_probe(pdata, nc);
+		if (ret) {
+			dev_err(dev, "failed to probe memory %s.\n",
+				of_node_full_name(nc));
+			goto error;
+		}
+	}
+
+	/* Set up DMA mask */
+	ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
+	if (ret) {
+		dev_warn(dev, "dma_set_coherent_mask failed: %d\n", ret);
+		/* If DMA is not configured yet, try to configure it. */
+		ret = of_dma_configure(dev, node, true);
+		if (ret) {
+			dev_err(dev, "failed to configure DMA.\n");
+			goto error;
+		}
+	}
+
+	/* Get R5 power domain node */
+	ret = of_property_read_u32(node, "pnode-id", &pdata->pnode_id);
+	if (ret) {
+		dev_err(dev, "failed to get power node id.\n");
+		goto error;
+	}
+
+	/* Check if R5 is running */
+	if (r5_is_running(pdata)) {
+		atomic_inc(&rproc->power);
+		rproc->state = RPROC_RUNNING;
+	}
+
+	if (!of_get_property(dev->of_node, "mboxes", NULL)) {
+		dev_info(dev, "no mailboxes.\n");
+	} else {
+		ret = zynqmp_r5_setup_mbox(pdata, node);
+		if (ret < 0)
+			goto error;
+	}
+
+	/* Add R5 remoteproc */
+	ret = rproc_add(rproc);
+	if (ret) {
+		dev_err(dev, "rproc registration failed\n");
+		goto error;
+	}
+
+	if (allow_sysfs_kick) {
+		dev_info(dev, "Trying to create remote sysfs entry.\n");
+		rproc->sysfs_kick = 1;
+		(void)rproc_create_kick_sysfs(rproc);
+	}
+
+	return 0;
+error:
+	if (pdata->rproc)
+		rproc_free(pdata->rproc);
+	pdata->rproc = NULL;
+	device_unregister(dev);
+	put_device(&pdev->dev);
+	return ret;
+}
+
+static int zynqmp_r5_remoteproc_probe(struct platform_device *pdev)
+{
+	const unsigned char *prop;
+	int ret = 0, i;
+	struct zynqmp_rpu_domain_pdata *local;
+	struct device *dev = &pdev->dev;
+	struct device_node *nc;
+
+	eemi_ops = zynqmp_pm_get_eemi_ops();
+	if (IS_ERR(eemi_ops))
+		return PTR_ERR(eemi_ops);
+
+	local = devm_kzalloc(dev, sizeof(*local), GFP_KERNEL);
+	if (!local)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, local);
+
+	prop = of_get_property(dev->of_node, "core_conf", NULL);
+	if (!prop) {
+		dev_err(&pdev->dev, "core_conf is not used.\n");
+		return -EINVAL;
+	}
+
+	dev_info(dev, "RPU core_conf: %s\n", prop);
+	if (!strcmp(prop, "split")) {
+		local->rpu_mode = PM_RPU_MODE_SPLIT;
+	} else if (!strcmp(prop, "lockstep")) {
+		local->rpu_mode = PM_RPU_MODE_LOCKSTEP;
+	} else {
+		dev_err(dev,
+			"Invalid core_conf mode provided - %s , %d\n",
+			prop, (int)local->rpu_mode);
+		return -EINVAL;
+	}
+
+	i = 0;
+	for_each_available_child_of_node(dev->of_node, nc) {
+		local->rpus[i].parent = local;
+		ret = zynqmp_r5_probe(&local->rpus[i], pdev, nc);
+		if (ret) {
+			dev_err(dev, "failed to probe rpu %s.\n",
+				of_node_full_name(nc));
+			return ret;
+		}
+		i++;
+	}
+
+	return 0;
+}
+
+static int zynqmp_r5_remoteproc_remove(struct platform_device *pdev)
+{
+	struct zynqmp_rpu_domain_pdata *local = platform_get_drvdata(pdev);
+	int i;
+
+	for (i = 0; i < MAX_RPROCS; i++) {
+		struct zynqmp_r5_pdata *rpu = &local->rpus[i];
+		struct rproc *rproc;
+
+		rproc = rpu->rproc;
+		if (rproc) {
+			rproc_del(rproc);
+			rproc_free(rproc);
+			rpu->rproc = NULL;
+		}
+		if (rpu->tx_chan) {
+			mbox_free_channel(rpu->tx_chan);
+			rpu->tx_chan = NULL;
+		}
+		if (rpu->rx_chan) {
+			mbox_free_channel(rpu->rx_chan);
+			rpu->rx_chan = NULL;
+		}
+
+		device_unregister(&rpu->dev);
+	}
+
+	return 0;
+}
+
+/* Match table for OF platform binding */
+static const struct of_device_id zynqmp_r5_remoteproc_match[] = {
+	{ .compatible = "xlnx,zynqmp-r5-remoteproc-1.0", },
+	{ /* end of list */ },
+};
+MODULE_DEVICE_TABLE(of, zynqmp_r5_remoteproc_match);
+
+static struct platform_driver zynqmp_r5_remoteproc_driver = {
+	.probe = zynqmp_r5_remoteproc_probe,
+	.remove = zynqmp_r5_remoteproc_remove,
+	.driver = {
+		.name = "zynqmp_r5_remoteproc",
+		.of_match_table = zynqmp_r5_remoteproc_match,
+	},
+};
+module_platform_driver(zynqmp_r5_remoteproc_driver);
+
+module_param_named(autoboot,  autoboot, bool, 0444);
+MODULE_PARM_DESC(autoboot,
+		 "enable | disable autoboot. (default: true)");
+module_param_named(allow_sysfs_kick, allow_sysfs_kick, bool, 0444);
+MODULE_PARM_DESC(allow_sysfs_kick,
+		 "enable | disable allow kick from sysfs. (default: false)");
+
+MODULE_AUTHOR("Jason Wu <j.wu@xilinx.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("ZynqMP R5 remote processor control driver");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/reset/core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/reset/core.c
@@ -565,7 +565,10 @@
 	if (!rstc)
 		return ERR_PTR(-ENOMEM);
 
-	try_module_get(rcdev->owner);
+	if (!try_module_get(rcdev->owner)) {
+		kfree(rstc);
+		return ERR_PTR(-ENODEV);
+	}
 
 	rstc->rcdev = rcdev;
 	list_add(&rstc->list, &rcdev->reset_control_head);
@@ -594,6 +597,9 @@
 {
 	lockdep_assert_held(&reset_list_mutex);
 
+	if (IS_ERR_OR_NULL(rstc))
+		return;
+
 	kref_put(&rstc->refcnt, __reset_control_release);
 }
 
@@ -787,7 +793,7 @@
 		return ERR_PTR(-ENOMEM);
 
 	rstc = __reset_control_get(dev, id, index, shared, optional, acquired);
-	if (!IS_ERR(rstc)) {
+	if (!IS_ERR_OR_NULL(rstc)) {
 		*ptr = rstc;
 		devres_add(dev, ptr);
 	} else {
@@ -861,8 +867,7 @@
  * @acquired: only one reset control may be acquired for a given controller
  *            and ID
  *
- * Returns pointer to allocated reset_control_array on success or
- * error on failure
+ * Returns pointer to allocated reset_control on success or error on failure
  */
 struct reset_control *
 of_reset_control_array_get(struct device_node *np, bool shared, bool optional,
@@ -915,8 +920,7 @@
  * that just have to be asserted or deasserted, without any
  * requirements on the order.
  *
- * Returns pointer to allocated reset_control_array on success or
- * error on failure
+ * Returns pointer to allocated reset_control on success or error on failure
  */
 struct reset_control *
 devm_reset_control_array_get(struct device *dev, bool shared, bool optional)
@@ -930,7 +934,7 @@
 		return ERR_PTR(-ENOMEM);
 
 	rstc = of_reset_control_array_get(dev->of_node, shared, optional, true);
-	if (IS_ERR(rstc)) {
+	if (IS_ERR_OR_NULL(rstc)) {
 		devres_free(devres);
 		return rstc;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/reset/hisilicon/hi6220_reset.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/reset/hisilicon/hi6220_reset.c
@@ -33,6 +33,7 @@
 enum hi6220_reset_ctrl_type {
 	PERIPHERAL,
 	MEDIA,
+	AO,
 };
 
 struct hi6220_reset_data {
@@ -92,6 +93,65 @@
 	.deassert = hi6220_media_deassert,
 };
 
+#define AO_SCTRL_SC_PW_CLKEN0     0x800
+#define AO_SCTRL_SC_PW_CLKDIS0    0x804
+
+#define AO_SCTRL_SC_PW_RSTEN0     0x810
+#define AO_SCTRL_SC_PW_RSTDIS0    0x814
+
+#define AO_SCTRL_SC_PW_ISOEN0     0x820
+#define AO_SCTRL_SC_PW_ISODIS0    0x824
+#define AO_MAX_INDEX              12
+
+static int hi6220_ao_assert(struct reset_controller_dev *rc_dev,
+			       unsigned long idx)
+{
+	struct hi6220_reset_data *data = to_reset_data(rc_dev);
+	struct regmap *regmap = data->regmap;
+	int ret;
+
+	ret = regmap_write(regmap, AO_SCTRL_SC_PW_RSTEN0, BIT(idx));
+	if (ret)
+		return ret;
+
+	ret = regmap_write(regmap, AO_SCTRL_SC_PW_ISOEN0, BIT(idx));
+	if (ret)
+		return ret;
+
+	ret = regmap_write(regmap, AO_SCTRL_SC_PW_CLKDIS0, BIT(idx));
+	return ret;
+}
+
+static int hi6220_ao_deassert(struct reset_controller_dev *rc_dev,
+				 unsigned long idx)
+{
+	struct hi6220_reset_data *data = to_reset_data(rc_dev);
+	struct regmap *regmap = data->regmap;
+	int ret;
+
+	/*
+	 * It was suggested to disable isolation before enabling
+	 * the clocks and deasserting reset, to avoid glitches.
+	 * But this order is preserved to keep it matching the
+	 * vendor code.
+	 */
+	ret = regmap_write(regmap, AO_SCTRL_SC_PW_RSTDIS0, BIT(idx));
+	if (ret)
+		return ret;
+
+	ret = regmap_write(regmap, AO_SCTRL_SC_PW_ISODIS0, BIT(idx));
+	if (ret)
+		return ret;
+
+	ret = regmap_write(regmap, AO_SCTRL_SC_PW_CLKEN0, BIT(idx));
+	return ret;
+}
+
+static const struct reset_control_ops hi6220_ao_reset_ops = {
+	.assert = hi6220_ao_assert,
+	.deassert = hi6220_ao_deassert,
+};
+
 static int hi6220_reset_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
@@ -104,7 +164,7 @@
 	if (!data)
 		return -ENOMEM;
 
-	type = (enum hi6220_reset_ctrl_type)of_device_get_match_data(dev);
+	type = (uintptr_t)of_device_get_match_data(dev);
 
 	regmap = syscon_node_to_regmap(np);
 	if (IS_ERR(regmap)) {
@@ -117,9 +177,12 @@
 	if (type == MEDIA) {
 		data->rc_dev.ops = &hi6220_media_reset_ops;
 		data->rc_dev.nr_resets = MEDIA_MAX_INDEX;
-	} else {
+	} else if (type == PERIPHERAL) {
 		data->rc_dev.ops = &hi6220_peripheral_reset_ops;
 		data->rc_dev.nr_resets = PERIPH_MAX_INDEX;
+	} else {
+		data->rc_dev.ops = &hi6220_ao_reset_ops;
+		data->rc_dev.nr_resets = AO_MAX_INDEX;
 	}
 
 	return reset_controller_register(&data->rc_dev);
@@ -134,6 +197,10 @@
 		.compatible = "hisilicon,hi6220-mediactrl",
 		.data = (void *)MEDIA,
 	},
+	{
+		.compatible = "hisilicon,hi6220-aoctrl",
+		.data = (void *)AO,
+	},
 	{ /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, hi6220_reset_match);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/reset/reset-a10sr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/reset/reset-a10sr.c
@@ -118,6 +118,7 @@
 	.probe	= a10sr_reset_probe,
 	.driver = {
 		.name		= "altr_a10sr_reset",
+		.of_match_table	= a10sr_reset_of_match,
 	},
 };
 module_platform_driver(a10sr_reset_driver);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/reset/reset-berlin.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/reset/reset-berlin.c
@@ -68,13 +68,14 @@
 
 static int berlin2_reset_probe(struct platform_device *pdev)
 {
-	struct device_node *parent_np = of_get_parent(pdev->dev.of_node);
+	struct device_node *parent_np;
 	struct berlin_reset_priv *priv;
 
 	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
 
+	parent_np = of_get_parent(pdev->dev.of_node);
 	priv->regmap = syscon_node_to_regmap(parent_np);
 	of_node_put(parent_np);
 	if (IS_ERR(priv->regmap))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/reset/reset-brcmstb.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/reset/reset-brcmstb.c
@@ -91,12 +91,6 @@
 		return -ENOMEM;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!IS_ALIGNED(res->start, SW_INIT_BANK_SIZE) ||
-	    !IS_ALIGNED(resource_size(res), SW_INIT_BANK_SIZE)) {
-		dev_err(kdev, "incorrect register range\n");
-		return -EINVAL;
-	}
-
 	priv->base = devm_ioremap_resource(kdev, res);
 	if (IS_ERR(priv->base))
 		return PTR_ERR(priv->base);
@@ -117,6 +111,7 @@
 	{ .compatible = "brcm,brcmstb-reset" },
 	{ /* sentinel */ }
 };
+MODULE_DEVICE_TABLE(of, brcmstb_reset_of_match);
 
 static struct platform_driver brcmstb_reset_driver = {
 	.probe	= brcmstb_reset_probe,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/reset/reset-socfpga.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/reset/reset-socfpga.c
@@ -86,3 +86,29 @@
 	for_each_matching_node(np, socfpga_early_reset_dt_ids)
 		a10_reset_init(np);
 }
+
+/*
+ * The early driver is problematic, because it doesn't register
+ * itself as a driver. This causes certain device links to prevent
+ * consumer devices from probing. The hacky solution is to register
+ * an empty driver, whose only job is to attach itself to the reset
+ * manager and call probe.
+ */
+static const struct of_device_id socfpga_reset_dt_ids[] = {
+	{ .compatible = "altr,rst-mgr", },
+	{ /* sentinel */ },
+};
+
+static int reset_simple_probe(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static struct platform_driver reset_socfpga_driver = {
+	.probe	= reset_simple_probe,
+	.driver = {
+		.name		= "socfpga-reset",
+		.of_match_table	= socfpga_reset_dt_ids,
+	},
+};
+builtin_platform_driver(reset_socfpga_driver);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/reset/reset-ti-sci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/reset/reset-ti-sci.c
@@ -1,7 +1,7 @@
 /*
  * Texas Instrument's System Control Interface (TI-SCI) reset driver
  *
- * Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2015-2017 Texas Instruments Incorporated - https://www.ti.com/
  *	Andrew F. Davis <afd@ti.com>
  *
  * This program is free software; you can redistribute it and/or modify
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/reset/reset-ti-syscon.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/reset/reset-ti-syscon.c
@@ -58,8 +58,8 @@
 	unsigned int nr_controls;
 };
 
-#define to_ti_syscon_reset_data(rcdev)	\
-	container_of(rcdev, struct ti_syscon_reset_data, rcdev)
+#define to_ti_syscon_reset_data(_rcdev)	\
+	container_of(_rcdev, struct ti_syscon_reset_data, rcdev)
 
 /**
  * ti_syscon_reset_assert() - assert device reset
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/reset/reset-uniphier.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/reset/reset-uniphier.c
@@ -193,8 +193,8 @@
 #define UNIPHIER_PERI_RESET_FI2C(id, ch)		\
 	UNIPHIER_RESETX((id), 0x114, 24 + (ch))
 
-#define UNIPHIER_PERI_RESET_SCSSI(id)			\
-	UNIPHIER_RESETX((id), 0x110, 17)
+#define UNIPHIER_PERI_RESET_SCSSI(id, ch)		\
+	UNIPHIER_RESETX((id), 0x110, 17 + (ch))
 
 #define UNIPHIER_PERI_RESET_MCSSI(id)			\
 	UNIPHIER_RESETX((id), 0x114, 14)
@@ -209,7 +209,7 @@
 	UNIPHIER_PERI_RESET_I2C(6, 2),
 	UNIPHIER_PERI_RESET_I2C(7, 3),
 	UNIPHIER_PERI_RESET_I2C(8, 4),
-	UNIPHIER_PERI_RESET_SCSSI(11),
+	UNIPHIER_PERI_RESET_SCSSI(11, 0),
 	UNIPHIER_RESET_END,
 };
 
@@ -225,8 +225,11 @@
 	UNIPHIER_PERI_RESET_FI2C(8, 4),
 	UNIPHIER_PERI_RESET_FI2C(9, 5),
 	UNIPHIER_PERI_RESET_FI2C(10, 6),
-	UNIPHIER_PERI_RESET_SCSSI(11),
-	UNIPHIER_PERI_RESET_MCSSI(12),
+	UNIPHIER_PERI_RESET_SCSSI(11, 0),
+	UNIPHIER_PERI_RESET_SCSSI(12, 1),
+	UNIPHIER_PERI_RESET_SCSSI(13, 2),
+	UNIPHIER_PERI_RESET_SCSSI(14, 3),
+	UNIPHIER_PERI_RESET_MCSSI(15),
 	UNIPHIER_RESET_END,
 };
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/reset/reset-zynqmp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/reset/reset-zynqmp.c
@@ -46,7 +46,8 @@
 			       unsigned long id)
 {
 	struct zynqmp_reset_data *priv = to_zynqmp_reset_data(rcdev);
-	int val, err;
+	int err;
+	u32 val;
 
 	err = priv->eemi_ops->reset_get_status(ZYNQMP_RESET_ID + id, &val);
 	if (err)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/reset/tegra/reset-bpmp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/reset/tegra/reset-bpmp.c
@@ -20,6 +20,7 @@
 	struct tegra_bpmp *bpmp = to_tegra_bpmp(rstc);
 	struct mrq_reset_request request;
 	struct tegra_bpmp_message msg;
+	int err;
 
 	memset(&request, 0, sizeof(request));
 	request.cmd = command;
@@ -30,7 +31,13 @@
 	msg.tx.data = &request;
 	msg.tx.size = sizeof(request);
 
-	return tegra_bpmp_transfer(bpmp, &msg);
+	err = tegra_bpmp_transfer(bpmp, &msg);
+	if (err)
+		return err;
+	if (msg.rx.ret)
+		return -EINVAL;
+
+	return 0;
 }
 
 static int tegra_bpmp_reset_module(struct reset_controller_dev *rstc,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rpmsg/qcom_glink_native.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rpmsg/qcom_glink_native.c
@@ -92,6 +92,8 @@
  * @rcids:	idr of all channels with a known remote channel id
  * @features:	remote features
  * @intentless:	flag to indicate that there is no intent
+ * @tx_avail_notify: Waitqueue for pending tx tasks
+ * @sent_read_notify: flag to check cmd sent or not
  */
 struct qcom_glink {
 	struct device *dev;
@@ -118,6 +120,8 @@
 	unsigned long features;
 
 	bool intentless;
+	wait_queue_head_t tx_avail_notify;
+	bool sent_read_notify;
 };
 
 enum {
@@ -187,20 +191,20 @@
 
 static const struct rpmsg_endpoint_ops glink_endpoint_ops;
 
-#define RPM_CMD_VERSION			0
-#define RPM_CMD_VERSION_ACK		1
-#define RPM_CMD_OPEN			2
-#define RPM_CMD_CLOSE			3
-#define RPM_CMD_OPEN_ACK		4
-#define RPM_CMD_INTENT			5
-#define RPM_CMD_RX_DONE			6
-#define RPM_CMD_RX_INTENT_REQ		7
-#define RPM_CMD_RX_INTENT_REQ_ACK	8
-#define RPM_CMD_TX_DATA			9
-#define RPM_CMD_CLOSE_ACK		11
-#define RPM_CMD_TX_DATA_CONT		12
-#define RPM_CMD_READ_NOTIF		13
-#define RPM_CMD_RX_DONE_W_REUSE		14
+#define GLINK_CMD_VERSION		0
+#define GLINK_CMD_VERSION_ACK		1
+#define GLINK_CMD_OPEN			2
+#define GLINK_CMD_CLOSE			3
+#define GLINK_CMD_OPEN_ACK		4
+#define GLINK_CMD_INTENT		5
+#define GLINK_CMD_RX_DONE		6
+#define GLINK_CMD_RX_INTENT_REQ		7
+#define GLINK_CMD_RX_INTENT_REQ_ACK	8
+#define GLINK_CMD_TX_DATA		9
+#define GLINK_CMD_CLOSE_ACK		11
+#define GLINK_CMD_TX_DATA_CONT		12
+#define GLINK_CMD_READ_NOTIF		13
+#define GLINK_CMD_RX_DONE_W_REUSE	14
 
 #define GLINK_FEATURE_INTENTLESS	BIT(1)
 
@@ -222,6 +226,10 @@
 
 	channel->glink = glink;
 	channel->name = kstrdup(name, GFP_KERNEL);
+	if (!channel->name) {
+		kfree(channel);
+		return ERR_PTR(-ENOMEM);
+	}
 
 	init_completion(&channel->open_req);
 	init_completion(&channel->open_ack);
@@ -241,10 +249,31 @@
 {
 	struct glink_channel *channel = container_of(ref, struct glink_channel,
 						     refcount);
+	struct glink_core_rx_intent *intent;
+	struct glink_core_rx_intent *tmp;
 	unsigned long flags;
+	int iid;
+
+	/* cancel pending rx_done work */
+	cancel_work_sync(&channel->intent_work);
 
 	spin_lock_irqsave(&channel->intent_lock, flags);
+	/* Free all non-reuse intents pending rx_done work */
+	list_for_each_entry_safe(intent, tmp, &channel->done_intents, node) {
+		if (!intent->reuse) {
+			kfree(intent->data);
+			kfree(intent);
+		}
+	}
+
+	idr_for_each_entry(&channel->liids, tmp, iid) {
+		kfree(tmp->data);
+		kfree(tmp);
+	}
 	idr_destroy(&channel->liids);
+
+	idr_for_each_entry(&channel->riids, tmp, iid)
+		kfree(tmp);
 	idr_destroy(&channel->riids);
 	spin_unlock_irqrestore(&channel->intent_lock, flags);
 
@@ -280,6 +309,20 @@
 	glink->tx_pipe->write(glink->tx_pipe, hdr, hlen, data, dlen);
 }
 
+static void qcom_glink_send_read_notify(struct qcom_glink *glink)
+{
+	struct glink_msg msg;
+
+	msg.cmd = cpu_to_le16(GLINK_CMD_READ_NOTIF);
+	msg.param1 = 0;
+	msg.param2 = 0;
+
+	qcom_glink_tx_write(glink, &msg, sizeof(msg), NULL, 0);
+
+	mbox_send_message(glink->mbox_chan, NULL);
+	mbox_client_txdone(glink->mbox_chan, 0);
+}
+
 static int qcom_glink_tx(struct qcom_glink *glink,
 			 const void *hdr, size_t hlen,
 			 const void *data, size_t dlen, bool wait)
@@ -300,12 +343,21 @@
 			goto out;
 		}
 
+		if (!glink->sent_read_notify) {
+			glink->sent_read_notify = true;
+			qcom_glink_send_read_notify(glink);
+		}
+
 		/* Wait without holding the tx_lock */
 		spin_unlock_irqrestore(&glink->tx_lock, flags);
 
-		usleep_range(10000, 15000);
+		wait_event_timeout(glink->tx_avail_notify,
+				   qcom_glink_tx_avail(glink) >= tlen, 10 * HZ);
 
 		spin_lock_irqsave(&glink->tx_lock, flags);
+
+		if (qcom_glink_tx_avail(glink) >= tlen)
+			glink->sent_read_notify = false;
 	}
 
 	qcom_glink_tx_write(glink, hdr, hlen, data, dlen);
@@ -323,7 +375,7 @@
 {
 	struct glink_msg msg;
 
-	msg.cmd = cpu_to_le16(RPM_CMD_VERSION);
+	msg.cmd = cpu_to_le16(GLINK_CMD_VERSION);
 	msg.param1 = cpu_to_le16(GLINK_VERSION_1);
 	msg.param2 = cpu_to_le32(glink->features);
 
@@ -334,7 +386,7 @@
 {
 	struct glink_msg msg;
 
-	msg.cmd = cpu_to_le16(RPM_CMD_VERSION_ACK);
+	msg.cmd = cpu_to_le16(GLINK_CMD_VERSION_ACK);
 	msg.param1 = cpu_to_le16(GLINK_VERSION_1);
 	msg.param2 = cpu_to_le32(glink->features);
 
@@ -346,7 +398,7 @@
 {
 	struct glink_msg msg;
 
-	msg.cmd = cpu_to_le16(RPM_CMD_OPEN_ACK);
+	msg.cmd = cpu_to_le16(GLINK_CMD_OPEN_ACK);
 	msg.param1 = cpu_to_le16(channel->rcid);
 	msg.param2 = cpu_to_le32(0);
 
@@ -372,11 +424,11 @@
 }
 
 /**
- * qcom_glink_send_open_req() - send a RPM_CMD_OPEN request to the remote
+ * qcom_glink_send_open_req() - send a GLINK_CMD_OPEN request to the remote
  * @glink: Ptr to the glink edge
  * @channel: Ptr to the channel that the open req is sent
  *
- * Allocates a local channel id and sends a RPM_CMD_OPEN message to the remote.
+ * Allocates a local channel id and sends a GLINK_CMD_OPEN message to the remote.
  * Will return with refcount held, regardless of outcome.
  *
  * Returns 0 on success, negative errno otherwise.
@@ -405,7 +457,7 @@
 
 	channel->lcid = ret;
 
-	req.msg.cmd = cpu_to_le16(RPM_CMD_OPEN);
+	req.msg.cmd = cpu_to_le16(GLINK_CMD_OPEN);
 	req.msg.param1 = cpu_to_le16(channel->lcid);
 	req.msg.param2 = cpu_to_le32(name_len);
 	strcpy(req.name, channel->name);
@@ -430,7 +482,7 @@
 {
 	struct glink_msg req;
 
-	req.cmd = cpu_to_le16(RPM_CMD_CLOSE);
+	req.cmd = cpu_to_le16(GLINK_CMD_CLOSE);
 	req.param1 = cpu_to_le16(channel->lcid);
 	req.param2 = 0;
 
@@ -442,7 +494,7 @@
 {
 	struct glink_msg req;
 
-	req.cmd = cpu_to_le16(RPM_CMD_CLOSE_ACK);
+	req.cmd = cpu_to_le16(GLINK_CMD_CLOSE_ACK);
 	req.param1 = cpu_to_le16(rcid);
 	req.param2 = 0;
 
@@ -473,7 +525,7 @@
 		iid = intent->id;
 		reuse = intent->reuse;
 
-		cmd.id = reuse ? RPM_CMD_RX_DONE_W_REUSE : RPM_CMD_RX_DONE;
+		cmd.id = reuse ? GLINK_CMD_RX_DONE_W_REUSE : GLINK_CMD_RX_DONE;
 		cmd.lcid = cid;
 		cmd.liid = iid;
 
@@ -585,7 +637,7 @@
 {
 	struct glink_msg msg;
 
-	msg.cmd = cpu_to_le16(RPM_CMD_RX_INTENT_REQ_ACK);
+	msg.cmd = cpu_to_le16(GLINK_CMD_RX_INTENT_REQ_ACK);
 	msg.param1 = cpu_to_le16(channel->lcid);
 	msg.param2 = cpu_to_le32(granted);
 
@@ -616,7 +668,7 @@
 	} __packed;
 	struct command cmd;
 
-	cmd.id = cpu_to_le16(RPM_CMD_INTENT);
+	cmd.id = cpu_to_le16(GLINK_CMD_INTENT);
 	cmd.lcid = cpu_to_le16(channel->lcid);
 	cmd.count = cpu_to_le32(1);
 	cmd.size = cpu_to_le32(intent->size);
@@ -836,6 +888,7 @@
 			dev_err(glink->dev,
 				"no intent found for channel %s intent %d",
 				channel->name, liid);
+			ret = -ENOENT;
 			goto advance_rx;
 		}
 	}
@@ -907,6 +960,7 @@
 	spin_unlock_irqrestore(&glink->idr_lock, flags);
 	if (!channel) {
 		dev_err(glink->dev, "intents for non-existing channel\n");
+		qcom_glink_rx_advance(glink, ALIGN(msglen, 8));
 		return;
 	}
 
@@ -949,7 +1003,7 @@
 		return -EINVAL;
 	}
 
-	complete(&channel->open_ack);
+	complete_all(&channel->open_ack);
 
 	return 0;
 }
@@ -964,6 +1018,9 @@
 	unsigned int cmd;
 	int ret = 0;
 
+	/* To wakeup any blocking writers */
+	wake_up_all(&glink->tx_avail_notify);
+
 	for (;;) {
 		avail = qcom_glink_rx_avail(glink);
 		if (avail < sizeof(msg))
@@ -976,42 +1033,43 @@
 		param2 = le32_to_cpu(msg.param2);
 
 		switch (cmd) {
-		case RPM_CMD_VERSION:
-		case RPM_CMD_VERSION_ACK:
-		case RPM_CMD_CLOSE:
-		case RPM_CMD_CLOSE_ACK:
-		case RPM_CMD_RX_INTENT_REQ:
+		case GLINK_CMD_VERSION:
+		case GLINK_CMD_VERSION_ACK:
+		case GLINK_CMD_CLOSE:
+		case GLINK_CMD_CLOSE_ACK:
+		case GLINK_CMD_RX_INTENT_REQ:
 			ret = qcom_glink_rx_defer(glink, 0);
 			break;
-		case RPM_CMD_OPEN_ACK:
+		case GLINK_CMD_OPEN_ACK:
 			ret = qcom_glink_rx_open_ack(glink, param1);
 			qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8));
 			break;
-		case RPM_CMD_OPEN:
-			ret = qcom_glink_rx_defer(glink, param2);
+		case GLINK_CMD_OPEN:
+			/* upper 16 bits of param2 are the "prio" field */
+			ret = qcom_glink_rx_defer(glink, param2 & 0xffff);
 			break;
-		case RPM_CMD_TX_DATA:
-		case RPM_CMD_TX_DATA_CONT:
+		case GLINK_CMD_TX_DATA:
+		case GLINK_CMD_TX_DATA_CONT:
 			ret = qcom_glink_rx_data(glink, avail);
 			break;
-		case RPM_CMD_READ_NOTIF:
+		case GLINK_CMD_READ_NOTIF:
 			qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8));
 
 			mbox_send_message(glink->mbox_chan, NULL);
 			mbox_client_txdone(glink->mbox_chan, 0);
 			break;
-		case RPM_CMD_INTENT:
+		case GLINK_CMD_INTENT:
 			qcom_glink_handle_intent(glink, param1, param2, avail);
 			break;
-		case RPM_CMD_RX_DONE:
+		case GLINK_CMD_RX_DONE:
 			qcom_glink_handle_rx_done(glink, param1, param2, false);
 			qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8));
 			break;
-		case RPM_CMD_RX_DONE_W_REUSE:
+		case GLINK_CMD_RX_DONE_W_REUSE:
 			qcom_glink_handle_rx_done(glink, param1, param2, true);
 			qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8));
 			break;
-		case RPM_CMD_RX_INTENT_REQ_ACK:
+		case GLINK_CMD_RX_INTENT_REQ_ACK:
 			qcom_glink_handle_intent_req_ack(glink, param1, param2);
 			qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8));
 			break;
@@ -1094,13 +1152,12 @@
 close_link:
 	/*
 	 * Send a close request to "undo" our open-ack. The close-ack will
-	 * release the last reference.
+	 * release qcom_glink_send_open_req() reference and the last reference
+	 * will be relesed after receiving remote_close or transport unregister
+	 * by calling qcom_glink_native_remove().
 	 */
 	qcom_glink_send_close_req(glink, channel);
 
-	/* Release qcom_glink_send_open_req() reference */
-	kref_put(&channel->refcount, qcom_glink_channel_release);
-
 	return ret;
 }
 
@@ -1158,7 +1215,7 @@
 	__be32 *val = defaults;
 	int size;
 
-	if (glink->intentless)
+	if (glink->intentless || !completion_done(&channel->open_ack))
 		return 0;
 
 	prop = of_find_property(np, "qcom,intents", NULL);
@@ -1215,7 +1272,7 @@
 
 	reinit_completion(&channel->intent_req_comp);
 
-	cmd.id = RPM_CMD_RX_INTENT_REQ;
+	cmd.id = GLINK_CMD_RX_INTENT_REQ;
 	cmd.cid = channel->lcid;
 	cmd.size = size;
 
@@ -1250,6 +1307,8 @@
 	} __packed req;
 	int ret;
 	unsigned long flags;
+	int chunk_size = len;
+	int left_size = 0;
 
 	if (!glink->intentless) {
 		while (!intent) {
@@ -1283,18 +1342,48 @@
 		iid = intent->id;
 	}
 
-	req.msg.cmd = cpu_to_le16(RPM_CMD_TX_DATA);
+	if (wait && chunk_size > SZ_8K) {
+		chunk_size = SZ_8K;
+		left_size = len - chunk_size;
+	}
+	req.msg.cmd = cpu_to_le16(GLINK_CMD_TX_DATA);
 	req.msg.param1 = cpu_to_le16(channel->lcid);
 	req.msg.param2 = cpu_to_le32(iid);
-	req.chunk_size = cpu_to_le32(len);
-	req.left_size = cpu_to_le32(0);
+	req.chunk_size = cpu_to_le32(chunk_size);
+	req.left_size = cpu_to_le32(left_size);
 
-	ret = qcom_glink_tx(glink, &req, sizeof(req), data, len, wait);
+	ret = qcom_glink_tx(glink, &req, sizeof(req), data, chunk_size, wait);
 
 	/* Mark intent available if we failed */
-	if (ret && intent)
-		intent->in_use = false;
+	if (ret) {
+		if (intent)
+			intent->in_use = false;
+		return ret;
+	}
+
+	while (left_size > 0) {
+		data = (void *)((char *)data + chunk_size);
+		chunk_size = left_size;
+		if (chunk_size > SZ_8K)
+			chunk_size = SZ_8K;
+		left_size -= chunk_size;
+
+		req.msg.cmd = cpu_to_le16(GLINK_CMD_TX_DATA_CONT);
+		req.msg.param1 = cpu_to_le16(channel->lcid);
+		req.msg.param2 = cpu_to_le32(iid);
+		req.chunk_size = cpu_to_le32(chunk_size);
+		req.left_size = cpu_to_le32(left_size);
+
+		ret = qcom_glink_tx(glink, &req, sizeof(req), data,
+				    chunk_size, wait);
 
+		/* Mark intent available if we failed */
+		if (ret) {
+			if (intent)
+				intent->in_use = false;
+			break;
+		}
+	}
 	return ret;
 }
 
@@ -1353,6 +1442,7 @@
 	struct glink_channel *channel = to_glink_channel(rpdev->ept);
 
 	channel->rpdev = NULL;
+	kfree(rpdev->driver_override);
 	kfree(rpdev);
 }
 
@@ -1393,7 +1483,7 @@
 	channel->rcid = ret;
 	spin_unlock_irqrestore(&glink->idr_lock, flags);
 
-	complete(&channel->open_req);
+	complete_all(&channel->open_req);
 
 	if (create_device) {
 		rpdev = kzalloc(sizeof(*rpdev), GFP_KERNEL);
@@ -1415,15 +1505,13 @@
 
 		ret = rpmsg_register_device(rpdev);
 		if (ret)
-			goto free_rpdev;
+			goto rcid_remove;
 
 		channel->rpdev = rpdev;
 	}
 
 	return 0;
 
-free_rpdev:
-	kfree(rpdev);
 rcid_remove:
 	spin_lock_irqsave(&glink->idr_lock, flags);
 	idr_remove(&glink->rcids, channel->rcid);
@@ -1453,7 +1541,7 @@
 	cancel_work_sync(&channel->intent_work);
 
 	if (channel->rpdev) {
-		strncpy(chinfo.name, channel->name, sizeof(chinfo.name));
+		strscpy_pad(chinfo.name, channel->name, sizeof(chinfo.name));
 		chinfo.src = RPMSG_ADDR_ANY;
 		chinfo.dst = RPMSG_ADDR_ANY;
 
@@ -1475,6 +1563,9 @@
 	struct glink_channel *channel;
 	unsigned long flags;
 
+	/* To wakeup any blocking writers */
+	wake_up_all(&glink->tx_avail_notify);
+
 	spin_lock_irqsave(&glink->idr_lock, flags);
 	channel = idr_find(&glink->lcids, lcid);
 	if (WARN(!channel, "close ack on unknown channel\n")) {
@@ -1517,22 +1608,22 @@
 		param2 = le32_to_cpu(msg->param2);
 
 		switch (cmd) {
-		case RPM_CMD_VERSION:
+		case GLINK_CMD_VERSION:
 			qcom_glink_receive_version(glink, param1, param2);
 			break;
-		case RPM_CMD_VERSION_ACK:
+		case GLINK_CMD_VERSION_ACK:
 			qcom_glink_receive_version_ack(glink, param1, param2);
 			break;
-		case RPM_CMD_OPEN:
+		case GLINK_CMD_OPEN:
 			qcom_glink_rx_open(glink, param1, msg->data);
 			break;
-		case RPM_CMD_CLOSE:
+		case GLINK_CMD_CLOSE:
 			qcom_glink_rx_close(glink, param1);
 			break;
-		case RPM_CMD_CLOSE_ACK:
+		case GLINK_CMD_CLOSE_ACK:
 			qcom_glink_rx_close_ack(glink, param1);
 			break;
-		case RPM_CMD_RX_INTENT_REQ:
+		case GLINK_CMD_RX_INTENT_REQ:
 			qcom_glink_handle_intent_req(glink, param1, param2);
 			break;
 		default:
@@ -1544,6 +1635,18 @@
 	}
 }
 
+static void qcom_glink_cancel_rx_work(struct qcom_glink *glink)
+{
+	struct glink_defer_cmd *dcmd;
+	struct glink_defer_cmd *tmp;
+
+	/* cancel any pending deferred rx_work */
+	cancel_work_sync(&glink->rx_work);
+
+	list_for_each_entry_safe(dcmd, tmp, &glink->rx_queue, node)
+		kfree(dcmd);
+}
+
 struct qcom_glink *qcom_glink_native_probe(struct device *dev,
 					   unsigned long features,
 					   struct qcom_glink_pipe *rx,
@@ -1569,6 +1672,7 @@
 	spin_lock_init(&glink->rx_lock);
 	INIT_LIST_HEAD(&glink->rx_queue);
 	INIT_WORK(&glink->rx_work, qcom_glink_work);
+	init_waitqueue_head(&glink->tx_avail_notify);
 
 	spin_lock_init(&glink->idr_lock);
 	idr_init(&glink->lcids);
@@ -1619,23 +1723,24 @@
 	struct glink_channel *channel;
 	int cid;
 	int ret;
-	unsigned long flags;
 
 	disable_irq(glink->irq);
-	cancel_work_sync(&glink->rx_work);
+	qcom_glink_cancel_rx_work(glink);
 
 	ret = device_for_each_child(glink->dev, NULL, qcom_glink_remove_device);
 	if (ret)
 		dev_warn(glink->dev, "Can't remove GLINK devices: %d\n", ret);
 
-	spin_lock_irqsave(&glink->idr_lock, flags);
 	/* Release any defunct local channels, waiting for close-ack */
 	idr_for_each_entry(&glink->lcids, channel, cid)
 		kref_put(&channel->refcount, qcom_glink_channel_release);
 
+	/* Release any defunct local channels, waiting for close-req */
+	idr_for_each_entry(&glink->rcids, channel, cid)
+		kref_put(&channel->refcount, qcom_glink_channel_release);
+
 	idr_destroy(&glink->lcids);
 	idr_destroy(&glink->rcids);
-	spin_unlock_irqrestore(&glink->idr_lock, flags);
 	mbox_free_channel(glink->mbox_chan);
 }
 EXPORT_SYMBOL_GPL(qcom_glink_native_remove);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rpmsg/qcom_glink_smem.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rpmsg/qcom_glink_smem.c
@@ -105,7 +105,7 @@
 	tail = le32_to_cpu(*pipe->tail);
 
 	tail += count;
-	if (tail > pipe->native.length)
+	if (tail >= pipe->native.length)
 		tail -= pipe->native.length;
 
 	*pipe->tail = cpu_to_le32(tail);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rpmsg/qcom_smd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rpmsg/qcom_smd.c
@@ -1073,7 +1073,7 @@
 
 	/* Assign public information to the rpmsg_device */
 	rpdev = &qsdev->rpdev;
-	strncpy(rpdev->id.name, channel->name, RPMSG_NAME_SIZE);
+	strscpy_pad(rpdev->id.name, channel->name, RPMSG_NAME_SIZE);
 	rpdev->src = RPMSG_ADDR_ANY;
 	rpdev->dst = RPMSG_ADDR_ANY;
 
@@ -1304,7 +1304,7 @@
 
 		spin_unlock_irqrestore(&edge->channels_lock, flags);
 
-		strncpy(chinfo.name, channel->name, sizeof(chinfo.name));
+		strscpy_pad(chinfo.name, channel->name, sizeof(chinfo.name));
 		chinfo.src = RPMSG_ADDR_ANY;
 		chinfo.dst = RPMSG_ADDR_ANY;
 		rpmsg_unregister_device(&edge->dev, &chinfo);
@@ -1338,7 +1338,7 @@
 	ret = of_property_read_u32(node, key, &edge->edge_id);
 	if (ret) {
 		dev_err(dev, "edge missing %s property\n", key);
-		return -EINVAL;
+		goto put_node;
 	}
 
 	edge->remote_pid = QCOM_SMEM_HOST_ANY;
@@ -1349,32 +1349,38 @@
 	edge->mbox_client.knows_txdone = true;
 	edge->mbox_chan = mbox_request_channel(&edge->mbox_client, 0);
 	if (IS_ERR(edge->mbox_chan)) {
-		if (PTR_ERR(edge->mbox_chan) != -ENODEV)
-			return PTR_ERR(edge->mbox_chan);
+		if (PTR_ERR(edge->mbox_chan) != -ENODEV) {
+			ret = PTR_ERR(edge->mbox_chan);
+			goto put_node;
+		}
 
 		edge->mbox_chan = NULL;
 
 		syscon_np = of_parse_phandle(node, "qcom,ipc", 0);
 		if (!syscon_np) {
 			dev_err(dev, "no qcom,ipc node\n");
-			return -ENODEV;
+			ret = -ENODEV;
+			goto put_node;
 		}
 
 		edge->ipc_regmap = syscon_node_to_regmap(syscon_np);
-		if (IS_ERR(edge->ipc_regmap))
-			return PTR_ERR(edge->ipc_regmap);
+		of_node_put(syscon_np);
+		if (IS_ERR(edge->ipc_regmap)) {
+			ret = PTR_ERR(edge->ipc_regmap);
+			goto put_node;
+		}
 
 		key = "qcom,ipc";
 		ret = of_property_read_u32_index(node, key, 1, &edge->ipc_offset);
 		if (ret < 0) {
 			dev_err(dev, "no offset in %s\n", key);
-			return -EINVAL;
+			goto put_node;
 		}
 
 		ret = of_property_read_u32_index(node, key, 2, &edge->ipc_bit);
 		if (ret < 0) {
 			dev_err(dev, "no bit in %s\n", key);
-			return -EINVAL;
+			goto put_node;
 		}
 	}
 
@@ -1383,9 +1389,10 @@
 		edge->name = node->name;
 
 	irq = irq_of_parse_and_map(node, 0);
-	if (irq < 0) {
+	if (!irq) {
 		dev_err(dev, "required smd interrupt missing\n");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto put_node;
 	}
 
 	ret = devm_request_irq(dev, irq,
@@ -1393,12 +1400,18 @@
 			       node->name, edge);
 	if (ret) {
 		dev_err(dev, "failed to request smd irq\n");
-		return ret;
+		goto put_node;
 	}
 
 	edge->irq = irq;
 
 	return 0;
+
+put_node:
+	of_node_put(node);
+	edge->of_node = NULL;
+
+	return ret;
 }
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rpmsg/rpmsg_char.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rpmsg/rpmsg_char.c
@@ -92,7 +92,7 @@
 	/* wake up any blocked readers */
 	wake_up_interruptible(&eptdev->readq);
 
-	device_del(&eptdev->dev);
+	cdev_device_del(&eptdev->cdev, &eptdev->dev);
 	put_device(&eptdev->dev);
 
 	return 0;
@@ -227,8 +227,10 @@
 	if (!kbuf)
 		return -ENOMEM;
 
-	if (!copy_from_iter_full(kbuf, len, from))
-		return -EFAULT;
+	if (!copy_from_iter_full(kbuf, len, from)) {
+		ret = -EFAULT;
+		goto free_kbuf;
+	}
 
 	if (mutex_lock_interruptible(&eptdev->ept_lock)) {
 		ret = -ERESTARTSYS;
@@ -334,7 +336,6 @@
 
 	ida_simple_remove(&rpmsg_ept_ida, dev->id);
 	ida_simple_remove(&rpmsg_minor_ida, MINOR(eptdev->dev.devt));
-	cdev_del(&eptdev->cdev);
 	kfree(eptdev);
 }
 
@@ -379,19 +380,13 @@
 	dev->id = ret;
 	dev_set_name(dev, "rpmsg%d", ret);
 
-	ret = cdev_add(&eptdev->cdev, dev->devt, 1);
+	ret = cdev_device_add(&eptdev->cdev, &eptdev->dev);
 	if (ret)
 		goto free_ept_ida;
 
 	/* We can now rely on the release function for cleanup */
 	dev->release = rpmsg_eptdev_release_device;
 
-	ret = device_add(dev);
-	if (ret) {
-		dev_err(dev, "device_add failed: %d\n", ret);
-		put_device(dev);
-	}
-
 	return ret;
 
 free_ept_ida:
@@ -460,7 +455,6 @@
 
 	ida_simple_remove(&rpmsg_ctrl_ida, dev->id);
 	ida_simple_remove(&rpmsg_minor_ida, MINOR(dev->devt));
-	cdev_del(&ctrldev->cdev);
 	kfree(ctrldev);
 }
 
@@ -495,19 +489,13 @@
 	dev->id = ret;
 	dev_set_name(&ctrldev->dev, "rpmsg_ctrl%d", ret);
 
-	ret = cdev_add(&ctrldev->cdev, dev->devt, 1);
+	ret = cdev_device_add(&ctrldev->cdev, &ctrldev->dev);
 	if (ret)
 		goto free_ctrl_ida;
 
 	/* We can now rely on the release function for cleanup */
 	dev->release = rpmsg_ctrldev_release_device;
 
-	ret = device_add(dev);
-	if (ret) {
-		dev_err(&rpdev->dev, "device_add failed: %d\n", ret);
-		put_device(dev);
-	}
-
 	dev_set_drvdata(&rpdev->dev, ctrldev);
 
 	return ret;
@@ -533,7 +521,7 @@
 	if (ret)
 		dev_warn(&rpdev->dev, "failed to nuke endpoints: %d\n", ret);
 
-	device_del(&ctrldev->dev);
+	cdev_device_del(&ctrldev->cdev, &ctrldev->dev);
 	put_device(&ctrldev->dev);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rpmsg/rpmsg_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rpmsg/rpmsg_core.c
@@ -332,7 +332,8 @@
 	      const char *buf, size_t sz)				\
 {									\
 	struct rpmsg_device *rpdev = to_rpmsg_device(dev);		\
-	char *new, *old;						\
+	const char *old;						\
+	char *new;							\
 									\
 	new = kstrndup(buf, sz, GFP_KERNEL);				\
 	if (!new)							\
@@ -473,13 +474,25 @@
 	err = rpdrv->probe(rpdev);
 	if (err) {
 		dev_err(dev, "%s: failed: %d\n", __func__, err);
-		if (ept)
-			rpmsg_destroy_ept(ept);
-		goto out;
+		goto destroy_ept;
 	}
 
-	if (ept && rpdev->ops->announce_create)
+	if (ept && rpdev->ops->announce_create) {
 		err = rpdev->ops->announce_create(rpdev);
+		if (err) {
+			dev_err(dev, "failed to announce creation\n");
+			goto remove_rpdev;
+		}
+	}
+
+	return 0;
+
+remove_rpdev:
+	if (rpdrv->remove)
+		rpdrv->remove(rpdev);
+destroy_ept:
+	if (ept)
+		rpmsg_destroy_ept(ept);
 out:
 	return err;
 }
@@ -513,24 +526,52 @@
 	.remove		= rpmsg_dev_remove,
 };
 
-int rpmsg_register_device(struct rpmsg_device *rpdev)
+/*
+ * A helper for registering rpmsg device with driver override and name.
+ * Drivers should not be using it, but instead rpmsg_register_device().
+ */
+int rpmsg_register_device_override(struct rpmsg_device *rpdev,
+				   const char *driver_override)
 {
 	struct device *dev = &rpdev->dev;
 	int ret;
 
+	if (driver_override)
+		strcpy(rpdev->id.name, driver_override);
+
 	dev_set_name(&rpdev->dev, "%s.%s.%d.%d", dev_name(dev->parent),
 		     rpdev->id.name, rpdev->src, rpdev->dst);
 
 	rpdev->dev.bus = &rpmsg_bus;
 
-	ret = device_register(&rpdev->dev);
+	device_initialize(dev);
+	if (driver_override) {
+		ret = driver_set_override(dev, &rpdev->driver_override,
+					  driver_override,
+					  strlen(driver_override));
+		if (ret) {
+			dev_err(dev, "device_set_override failed: %d\n", ret);
+			put_device(dev);
+			return ret;
+		}
+	}
+
+	ret = device_add(dev);
 	if (ret) {
-		dev_err(dev, "device_register failed: %d\n", ret);
+		dev_err(dev, "device_add failed: %d\n", ret);
+		kfree(rpdev->driver_override);
+		rpdev->driver_override = NULL;
 		put_device(&rpdev->dev);
 	}
 
 	return ret;
 }
+EXPORT_SYMBOL(rpmsg_register_device_override);
+
+int rpmsg_register_device(struct rpmsg_device *rpdev)
+{
+	return rpmsg_register_device_override(rpdev, NULL);
+}
 EXPORT_SYMBOL(rpmsg_register_device);
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rpmsg/rpmsg_internal.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/rpmsg/rpmsg_internal.h
@@ -84,10 +84,7 @@
  */
 static inline int rpmsg_chrdev_register_device(struct rpmsg_device *rpdev)
 {
-	strcpy(rpdev->id.name, "rpmsg_chrdev");
-	rpdev->driver_override = "rpmsg_chrdev";
-
-	return rpmsg_register_device(rpdev);
+	return rpmsg_register_device_override(rpdev, "rpmsg_ctrl");
 }
 
 #endif
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rpmsg/virtio_rpmsg_bus.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -381,6 +381,7 @@
 	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
 	struct virtio_rpmsg_channel *vch = to_virtio_rpmsg_channel(rpdev);
 
+	kfree(rpdev->driver_override);
 	kfree(vch);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/Kconfig
@@ -217,6 +217,15 @@
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-ac100.
 
+config RTC_DRV_AM1805
+	tristate "Ambiq micro AM1805 RTC driver"
+	help
+	  If you say yes here you get support for Ambiq micro AM1805 RTC
+	  chip.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-am1805.
+
 config RTC_DRV_BRCMSTB
 	tristate "Broadcom STB wake-timer"
 	depends on ARCH_BRCMSTB || BMIPS_GENERIC || COMPILE_TEST
@@ -240,6 +249,7 @@
 
 config RTC_DRV_DS1307
 	tristate "Dallas/Maxim DS1307/37/38/39/40/41, ST M41T00, EPSON RX-8025, ISL12057"
+	select REGMAP_I2C
 	help
 	  If you say yes here you get support for various compatible RTC
 	  chips (often with battery backup) connected with I2C. This driver
@@ -326,6 +336,7 @@
 config RTC_DRV_MAX8907
 	tristate "Maxim MAX8907"
 	depends on MFD_MAX8907 || COMPILE_TEST
+	select REGMAP_IRQ
 	help
 	  If you say yes here you will get support for the
 	  RTC of Maxim MAX8907 PMIC.
@@ -623,6 +634,7 @@
 
 config RTC_DRV_RX8010
 	tristate "Epson RX8010SJ"
+	select REGMAP_I2C
 	help
 	  If you say yes here you get support for the Epson RX8010SJ RTC
 	  chip.
@@ -632,6 +644,7 @@
 
 config RTC_DRV_RX8581
 	tristate "Epson RX-8571/RX-8581"
+	select REGMAP_I2C
 	help
 	  If you say yes here you will get support for the Epson RX-8571/
 	  RX-8581.
@@ -659,6 +672,7 @@
 
 config RTC_DRV_RV3028
 	tristate "Micro Crystal RV3028"
+	select REGMAP_I2C
 	help
 	  If you say yes here you get support for the Micro Crystal
 	  RV3028.
@@ -679,6 +693,7 @@
 	tristate "Samsung S2M/S5M series"
 	depends on MFD_SEC_CORE || COMPILE_TEST
 	select REGMAP_IRQ
+	select REGMAP_I2C
 	help
 	  If you say yes here you will get support for the
 	  RTC of Samsung S2MPS14 and S5M PMIC series.
@@ -688,6 +703,7 @@
 
 config RTC_DRV_SD3078
     tristate "ZXW Shenzhen whwave SD3078"
+    select REGMAP_I2C
     help
       If you say yes here you get support for the ZXW Shenzhen whwave
       SD3078 RTC chips.
@@ -859,14 +875,14 @@
 	default m if I2C=m
 	default y if I2C=y
 	default y if SPI_MASTER=y
-	select REGMAP_I2C if I2C
-	select REGMAP_SPI if SPI_MASTER
 
 comment "SPI and I2C RTC drivers"
 
 config RTC_DRV_DS3232
 	tristate "Dallas/Maxim DS3232/DS3234"
 	depends on RTC_I2C_AND_SPI
+	select REGMAP_I2C if I2C
+	select REGMAP_SPI if SPI_MASTER
 	help
 	  If you say yes here you get support for Dallas Semiconductor
 	  DS3232 and DS3234 real-time clock chips. If an interrupt is associated
@@ -886,6 +902,8 @@
 config RTC_DRV_PCF2127
 	tristate "NXP PCF2127"
 	depends on RTC_I2C_AND_SPI
+	select REGMAP_I2C if I2C
+	select REGMAP_SPI if SPI_MASTER
 	select WATCHDOG_CORE if WATCHDOG
 	help
 	  If you say yes here you get support for the NXP PCF2127/29 RTC
@@ -902,6 +920,8 @@
 config RTC_DRV_RV3029C2
 	tristate "Micro Crystal RV3029/3049"
 	depends on RTC_I2C_AND_SPI
+	select REGMAP_I2C if I2C
+	select REGMAP_SPI if SPI_MASTER
 	help
 	  If you say yes here you get support for the Micro Crystal
 	  RV3029 and RV3049 RTC chips.
@@ -1800,7 +1820,8 @@
 
 config RTC_DRV_MT6397
 	tristate "MediaTek PMIC based RTC"
-	depends on MFD_MT6397 || (COMPILE_TEST && IRQ_DOMAIN)
+	depends on MFD_MT6397 || COMPILE_TEST
+	select IRQ_DOMAIN
 	help
 	  This selects the MediaTek(R) RTC driver. RTC is part of MediaTek
 	  MT6397 PMIC. You should enable MT6397 PMIC MFD before select
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/Makefile
@@ -31,6 +31,7 @@
 obj-$(CONFIG_RTC_DRV_ABEOZ9)	+= rtc-ab-eoz9.o
 obj-$(CONFIG_RTC_DRV_ABX80X)	+= rtc-abx80x.o
 obj-$(CONFIG_RTC_DRV_AC100)	+= rtc-ac100.o
+obj-$(CONFIG_RTC_DRV_AM1805)	+= rtc-am1805.o
 obj-$(CONFIG_RTC_DRV_ARMADA38X)	+= rtc-armada38x.o
 obj-$(CONFIG_RTC_DRV_AS3722)	+= rtc-as3722.o
 obj-$(CONFIG_RTC_DRV_ASM9260)	+= rtc-asm9260.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/class.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/class.c
@@ -26,6 +26,15 @@
 static void rtc_device_release(struct device *dev)
 {
 	struct rtc_device *rtc = to_rtc_device(dev);
+	struct timerqueue_head *head = &rtc->timerqueue;
+	struct timerqueue_node *node;
+
+	mutex_lock(&rtc->ops_lock);
+	while ((node = timerqueue_getnext(head)))
+		timerqueue_del(head, node);
+	mutex_unlock(&rtc->ops_lock);
+
+	cancel_work_sync(&rtc->irqwork);
 
 	ida_simple_remove(&rtc_ida, rtc->id);
 	kfree(rtc);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/interface.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/interface.c
@@ -125,7 +125,7 @@
 
 int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm)
 {
-	int err;
+	int err, uie;
 
 	err = rtc_valid_tm(tm);
 	if (err != 0)
@@ -137,6 +137,17 @@
 
 	rtc_subtract_offset(rtc, tm);
 
+#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
+	uie = rtc->uie_rtctimer.enabled || rtc->uie_irq_active;
+#else
+	uie = rtc->uie_rtctimer.enabled;
+#endif
+	if (uie) {
+		err = rtc_update_irq_enable(rtc, 0);
+		if (err)
+			return err;
+	}
+
 	err = mutex_lock_interruptible(&rtc->ops_lock);
 	if (err)
 		return err;
@@ -153,6 +164,12 @@
 	/* A timer might have just expired */
 	schedule_work(&rtc->irqwork);
 
+	if (uie) {
+		err = rtc_update_irq_enable(rtc, 1);
+		if (err)
+			return err;
+	}
+
 	trace_rtc_set_time(rtc_tm_to_time64(tm), err);
 	return err;
 }
@@ -257,10 +274,9 @@
 			return err;
 
 		/* full-function RTCs won't have such missing fields */
-		if (rtc_valid_tm(&alarm->time) == 0) {
-			rtc_add_offset(rtc, &alarm->time);
-			return 0;
-		}
+		err = rtc_valid_tm(&alarm->time);
+		if (!err)
+			goto done;
 
 		/* get the "after" timestamp, to detect wrapped fields */
 		err = rtc_read_time(rtc, &now);
@@ -362,6 +378,8 @@
 	if (err)
 		dev_warn(&rtc->dev, "invalid alarm value: %ptR\n",
 			 &alarm->time);
+	else
+		rtc_add_offset(rtc, &alarm->time);
 
 	return err;
 }
@@ -776,9 +794,13 @@
 	struct timerqueue_node *next = timerqueue_getnext(&rtc->timerqueue);
 	struct rtc_time tm;
 	ktime_t now;
+	int err;
+
+	err = __rtc_read_time(rtc, &tm);
+	if (err)
+		return err;
 
 	timer->enabled = 1;
-	__rtc_read_time(rtc, &tm);
 	now = rtc_tm_to_ktime(tm);
 
 	/* Skip over expired timers */
@@ -792,7 +814,6 @@
 	trace_rtc_timer_enqueue(timer);
 	if (!next || ktime_before(timer->node.expires, next->expires)) {
 		struct rtc_wkalrm alarm;
-		int err;
 
 		alarm.time = rtc_ktime_to_tm(timer->node.expires);
 		alarm.enabled = 1;
@@ -873,13 +894,18 @@
 	struct timerqueue_node *next;
 	ktime_t now;
 	struct rtc_time tm;
+	int err;
 
 	struct rtc_device *rtc =
 		container_of(work, struct rtc_device, irqwork);
 
 	mutex_lock(&rtc->ops_lock);
 again:
-	__rtc_read_time(rtc, &tm);
+	err = __rtc_read_time(rtc, &tm);
+	if (err) {
+		mutex_unlock(&rtc->ops_lock);
+		return;
+	}
 	now = rtc_tm_to_ktime(tm);
 	while ((next = timerqueue_getnext(&rtc->timerqueue))) {
 		if (next->expires > now)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/proc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/proc.c
@@ -23,8 +23,8 @@
 	int size;
 	char name[NAME_SIZE];
 
-	size = scnprintf(name, NAME_SIZE, "rtc%d", rtc->id);
-	if (size > NAME_SIZE)
+	size = snprintf(name, NAME_SIZE, "rtc%d", rtc->id);
+	if (size >= NAME_SIZE)
 		return false;
 
 	return !strncmp(name, CONFIG_RTC_HCTOSYS_DEVICE, NAME_SIZE);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-88pm860x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-88pm860x.c
@@ -336,6 +336,10 @@
 	info->dev = &pdev->dev;
 	dev_set_drvdata(&pdev->dev, info);
 
+	info->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
+	if (IS_ERR(info->rtc_dev))
+		return PTR_ERR(info->rtc_dev);
+
 	ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL,
 					rtc_update_handler, IRQF_ONESHOT, "rtc",
 					info);
@@ -377,13 +381,11 @@
 		}
 	}
 
-	info->rtc_dev = devm_rtc_device_register(&pdev->dev, "88pm860x-rtc",
-					    &pm860x_rtc_ops, THIS_MODULE);
-	ret = PTR_ERR(info->rtc_dev);
-	if (IS_ERR(info->rtc_dev)) {
-		dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret);
+	info->rtc_dev->ops = &pm860x_rtc_ops;
+
+	ret = rtc_register_device(info->rtc_dev);
+	if (ret)
 		return ret;
-	}
 
 	/*
 	 * enable internal XO instead of internal 3.25MHz clock since it can
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-ab-eoz9.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-ab-eoz9.c
@@ -281,13 +281,6 @@
 	if (ret < 0)
 		return ret;
 
-	if ((val & ABEOZ9_REG_CTRL_STATUS_V1F) ||
-	    (val & ABEOZ9_REG_CTRL_STATUS_V2F)) {
-		dev_err(dev,
-			"thermometer might be disabled due to low voltage\n");
-		return -EINVAL;
-	}
-
 	switch (attr) {
 	case hwmon_temp_input:
 		ret = regmap_read(regmap, ABEOZ9_REG_REG_TEMP, &val);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-abx80x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-abx80x.c
@@ -36,7 +36,7 @@
 #define ABX8XX_REG_STATUS	0x0f
 #define ABX8XX_STATUS_AF	BIT(2)
 #define ABX8XX_STATUS_BLF	BIT(4)
-#define ABX8XX_STATUS_WDT	BIT(6)
+#define ABX8XX_STATUS_WDT	BIT(5)
 
 #define ABX8XX_REG_CTRL1	0x10
 #define ABX8XX_CTRL_WRITE	BIT(0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-am1805.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-am1805.c
@@ -0,0 +1,1562 @@
+/*
+ * Copyright (C) 2016 Eurotech S.p.A.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/*
+ * Version History.
+ * 2016-10-26	0.6.0	fixed time fields in rtc_read_alarm function
+ *
+ * 2016-10-03	0.5.0	notify that UIE is not supported by our hw
+ *			add mutex lock/unlock to read/set time functions
+ *
+ * 2016-07-12	0.4-0	Add clock_adj parameter for XT clock calibration
+ *
+ * 2016-04-20	0.3.0	Add board turn on feature
+ *			Feature is enabled as parameter and can be changed
+ *			via sysfs
+ *			Trickle charger as module parameter
+ *
+ * 2016-04-01	0.2.0	Add alarm, watchdog functionality
+ *			watchdog create a 60ms pulse on sRST pin 3.3V -> 0 -> 3.3V
+ *			alarm create a 250ms pulse on nIRQ pin 3.3V -> 0 -> 3.3V
+ *
+ * 2016-01-22	0.1.0	First Release
+ *			date time get/set commands
+ *			256 byte get/set via sysfs.
+ *			ram_address allows to get/set ram_byte
+ *			watchdog
+ *
+ */
+
+#include <linux/bcd.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/rtc.h>
+#include <linux/pm.h>
+#include <linux/pm_wakeup.h>
+#include <linux/watchdog.h>
+#include <linux/jiffies.h>
+
+#define DEFAULT_FORCE_SMBUS 0
+static bool force_smbus = DEFAULT_FORCE_SMBUS;
+module_param(force_smbus, bool, 0444);
+MODULE_PARM_DESC(force_smbus, "force smbus protocol (default="
+	__MODULE_STRING(DEFAULT_FORCE_SMBUS) ")");
+
+#define DEFAULT_WATCHDOG_TIMEOUT        30
+static int timeout = DEFAULT_WATCHDOG_TIMEOUT;
+module_param(timeout, int, 0444);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=124, default="
+	__MODULE_STRING(DEFAULT_WATCHDOG_TIMEOUT) ")");
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0444);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
+	__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+#define DEFAULT_DISABLE_ON_BOOT 1
+static bool disable_on_boot = DEFAULT_DISABLE_ON_BOOT;
+module_param(disable_on_boot, bool, 0444);
+MODULE_PARM_DESC(disable_on_boot, "Watchdog automatically disabled at boot time (default="
+	__MODULE_STRING(DEFAULT_DISABLE_ON_BOOT)")");
+
+/*
+ * the following paramweter could be removed since revA board should
+ * provide WDT IRQ to cortex via RST pin only
+ */
+#define DEFAULT_STEERING 1
+static bool watchdog_steering = DEFAULT_STEERING;
+module_param(watchdog_steering, bool, 0444);
+MODULE_PARM_DESC(watchdog_steering, "Watchdog IRQ steering : 0 WIRQ , 1 RST (default="
+	__MODULE_STRING(DEFAULT_STEERING)")");
+
+#define DEFAULT_BOARD_TURN_ON 0
+static bool board_turn_on = DEFAULT_BOARD_TURN_ON;
+module_param(board_turn_on, bool, 0444);
+MODULE_PARM_DESC(board_turn_on, "Enable board turn on via alarm route (default="
+	__MODULE_STRING(DEFAULT_BOARD_TURN_ON)")");
+
+#define DEFAULT_TRICKLE_REGISTER 0x00
+static int trickle_register = DEFAULT_TRICKLE_REGISTER;
+module_param(trickle_register, int, 0444);
+MODULE_PARM_DESC(trickle_register, "trickle charger register (default="
+	__MODULE_STRING(DEFAULT_TRICKLE_REGISTER)")");
+
+#define DEFAULT_XT_CLOCK_ADJ 0
+static int xt_clock_adj = DEFAULT_XT_CLOCK_ADJ;
+module_param(xt_clock_adj, int, 0444);
+MODULE_PARM_DESC(xt_clock_adj, "Adj parameter as per Ambiq micro procedure (default="
+	__MODULE_STRING(DEFAULT_XT_CLOCK_ADJ)")");
+
+#define DRIVER_NAME "rtc-am1805"
+#define DRIVER_VERSION "0.6.0"
+
+#define AM1805_IDENTITY_CODE	0x18
+#define SECONDS_BITS	0x7F
+#define MINUTES_BITS	0x7F
+#define HOURS_BITS	0x3F
+#define DATE_BITS	0x3F
+#define MONTHS_BITS	0x1F
+#define WEEKDAY_BITS	0x07
+
+#define REG_HUNDREDS_ADDR	0x00	// hundreds of seconds register address
+#define REG_SECONDS_ADDR	0x01	// seconds register address
+#define REG_MINUTES_ADDR	0x02	// minutes register address
+#define REG_HOURS_ADDR		0x03	// hours register address
+#define REG_MDAY_ADDR		0x04	// day of the month register address
+#define REG_MONTH_ADDR		0x05	// month register address
+#define REG_YEAR_ADDR		0x06	// years register address
+#define REG_WDAY_ADDR		0x07	// day of the week register address
+
+#define REG_ALM_HUNDREDS_ADDR	0x08	// Alarm hundreds of seconds register address
+#define REG_ALM_SECONDS_ADDR	0x09	// Alarm seconds register address
+#define REG_ALM_MINUTES_ADDR	0x0A	// Alarm minutes register address
+#define REG_ALM_HOURS_ADDR	0x0B	// Alarm hours register address
+#define REG_ALM_MDAY_ADDR	0x0C	// Alarm day of the month register address
+#define REG_ALM_MONTH_ADDR	0x0D	// Alarm month register address
+#define REG_ALM_WDAY_ADDR	0x0E	// Alarm day of the week register address
+
+#define REG_STATUS_ADDR		0x0F	// status register address
+#define REG_STATUS_ALM	(1 << 2)	// Alarm function enabled
+#define REG_STATUS_WDT	(1 << 5)	// Watchdog expired bit
+#define REG_STATUS_CB	(1 << 7)	// Century rollover bit
+
+#define REG_CONTROL1_ADDR	0x10	// control1 register address
+#define REG_CONTROL1_WRTC	1	// write enable for counter registers
+#define REG_CONTROL1_PWR2	(1 << 1)	// PWR2
+#define REG_CONTROL1_ARST	(1 << 2)	// auto reset on read
+#define REG_CONTROL1_RSP	(1 << 3)	// nRST polarity 1 high 0 low
+#define REG_CONTROL1_OUT	(1 << 4)	// nIRQ pin static value
+#define REG_CONTROL1_OUTB	(1 << 5)	// nIRQ2 pin static value
+#define REG_CONTROL1_1224	(1 << 6)	// 12/24 format selection 0 = 24h
+#define REG_CONTROL1_STOP	(1 << 7)	// stop the clocking system
+
+#define REG_CONTROL2_ADDR	0x11	// control2 register address
+#define REG_CONTROL2_OUT2S_BITS 0x1C	// control2 register out2s bits
+#define REG_IRQ_MASK_ADDR	0x12	// Interrupt Mask register address
+#define REG_IRQ_MASK_AIE	(1 << 2)	// Alarm interrupt enable
+
+#define REG_XT_CALIB_ADDR	0x14	// XT calibration register address
+#define REG_XT_CALIB_OFFSETX_MASK	0x7F	// OFFSET X BIT MASK
+#define REG_XT_CALIB_CMDX	0x80	// cmdx field
+
+
+#define REG_TIMER_CTRL_ADDR	0x18	// Countdown timer control register address
+#define REG_TIMER_CTRL_RPT_BITS 0x1C	// only the RPT bits
+
+#define REG_WATCHDOG_ADDR	0x1B	// watchdog register address
+#define REG_WATCHDOG_WDS	(1 << 7)	// watchodg steering bit
+#define WRB_1_SECOND	0x02		//watchdog clock 1Hz
+#define WRB_4_SECONDS	0x03		//watchdog clock 1/4 Hz
+
+#define REG_OSC_STATUS_ADDR	0x1D	// oscillator status register address
+#define REG_OSC_STATUS_ACAL_MASK 0x60	// ACAL bit field mask
+#define REG_OSC_STATUS_ACAL_0	0x00
+#define REG_OSC_STATUS_ACAL_1	0x40
+#define REG_OSC_STATUS_ACAL_2	0x80
+#define REG_OSC_STATUS_ACAL_3	0xC0
+
+#define REG_CONFIGKEY_ADDR	0x1F	// configuration key register address
+
+
+#define REG_TRICKLE_ADDR	0x20	// trickle charger register
+
+#define REG_IDENTITY_ADDR	0x28	// identity register address must contain 0x18
+
+#define REG_EXTRAM_ADDR		0x3F	// Extension ram register address
+#define REG_EXTRAM_XADA		(1 << 2)  //select bank of memory
+
+static struct i2c_driver am1805_driver;
+
+struct am1805_data {
+	struct i2c_client   *client;
+	struct rtc_device   *rtc;
+	struct mutex        mutex;
+	int	use_smbus;
+	int	watchdog_timeout;
+	int	watchdog_disable_on_boot;
+	int	watchdog_steering;
+	int	watchdog_registered;
+	int	watchdog_enabled;
+	unsigned char	watchdog_reg;
+	unsigned long int	watchdog_start_jiffies;
+	int	ram_byte_file_created;
+	int	ram_address_file_created;
+	unsigned char	ram_address;
+	int	board_turn_on;
+	int	board_turn_on_file_created;
+	unsigned char trickle_register;
+};
+
+static int am1805_read(struct am1805_data *amq, u8 *buf, int len)
+{
+	int err, i;
+	u8 base_reg;
+	struct i2c_msg	msgs[] = {
+
+		{
+			.addr = amq->client->addr,
+			.flags = (amq->client->flags & I2C_M_TEN),
+			.len = 1,
+			.buf = buf,
+		},
+		{
+			.addr = amq->client->addr,
+			.flags = (amq->client->flags & I2C_M_TEN) | I2C_M_RD,
+			.len = len,
+			.buf = buf,
+		},
+	};
+	if (amq->use_smbus) {
+		/* use SMBUS transfer protocol */
+		base_reg = buf[0];
+		for (i = 0; i < len; i++) {
+			err = i2c_smbus_read_byte_data(amq->client, base_reg);
+			if (err < 0) {
+				dev_err(&amq->client->dev,
+					"read transfer error reg 0x%02X\n",
+					base_reg);
+				break;
+			}
+			buf[i] = (u8)err;
+			base_reg++;
+			err = 0;
+		}
+	} else {
+		/* use I2C transfer protocol */
+		err = i2c_transfer(amq->client->adapter, msgs, 2);
+
+		if (err != 2) {
+			dev_err(&amq->client->dev, "I2C read transfer error\n");
+			err = -EIO;
+		} else {
+			err = 0;
+		}
+	}
+	return err;
+}
+
+static int am1805_write(struct am1805_data *amq, u8 *buf, int len)
+{
+	int err = 0, i;
+	u8 base_reg;
+	struct i2c_msg msgs[] = {
+		{
+		 .addr = amq->client->addr,
+			.flags = (amq->client->flags & I2C_M_TEN),
+		 .len = len + 1,
+		 .buf = buf,
+		 },
+	};
+
+	if (amq->use_smbus) {
+		/* use SMBUS transfer protocol */
+		base_reg = buf[0];
+		for (i = 1; i <= len; i++) {
+			err = i2c_smbus_write_byte_data(amq->client, base_reg,
+							buf[i]);
+			if (err < 0) {
+				dev_err(&amq->client->dev,
+					"write transfer error reg 0x%02X\n",
+					base_reg);
+				break;
+			}
+			base_reg++;
+		}
+	} else {
+		/* use I2C transfer protocol */
+		err = i2c_transfer(amq->client->adapter, msgs, 1);
+		if (err != 1) {
+			dev_err(&amq->client->dev, "I2C write transfer error\n");
+			err = -EIO;
+		} else {
+			err = 0;
+		}
+	}
+	return err;
+}
+
+
+static int am1805_stop_rtc(struct am1805_data *amq)
+{
+	u8 regs[2];
+	int err;
+
+	regs[0] = REG_CONTROL1_ADDR;
+
+	err = am1805_read(amq, regs, 1);
+	if (err < 0)
+		return err;
+	regs[1] = regs[0];
+	regs[0] = REG_CONTROL1_ADDR;
+
+
+	regs[1] |= (REG_CONTROL1_STOP|REG_CONTROL1_WRTC);
+
+	err = am1805_write(amq, regs, 1);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+
+static int am1805_start_rtc(struct am1805_data *amq)
+{
+	u8 regs[2];
+	int err;
+
+	regs[0] = REG_CONTROL1_ADDR;
+
+	err = am1805_read(amq, regs, 1);
+	if (err < 0)
+		return err;
+	regs[1] = regs[0];
+	regs[0] = REG_CONTROL1_ADDR;
+
+	regs[1] &= (~(REG_CONTROL1_STOP|REG_CONTROL1_WRTC));
+
+	err = am1805_write(amq, regs, 1);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static int am1805_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct am1805_data *amq;
+	u8 regs[8];
+	int err;
+
+	amq = i2c_get_clientdata(client);
+	mutex_lock(&amq->mutex);
+
+	regs[0] = REG_SECONDS_ADDR;
+	err = am1805_read(amq, regs, 7);
+	if (err)
+		goto exit;
+
+	/* read the status register */
+	regs[7] = REG_STATUS_ADDR;
+	err = am1805_read(amq, &regs[7], 1);
+	if (err)
+		goto exit;
+	regs[0] &= SECONDS_BITS;
+	regs[1] &= MINUTES_BITS;
+	regs[2] &= HOURS_BITS;
+	regs[3] &= DATE_BITS;
+	regs[4] &= MONTHS_BITS;
+	regs[6] &= WEEKDAY_BITS;
+
+	tm->tm_sec = bcd2bin(regs[0]);
+	tm->tm_min = bcd2bin(regs[1]);
+	tm->tm_hour = bcd2bin(regs[2]);
+	tm->tm_mday = bcd2bin(regs[3]);
+	tm->tm_mon = bcd2bin(regs[4]);
+	tm->tm_mon--;
+	tm->tm_year = bcd2bin(regs[5])+100;
+
+	if (regs[7] & REG_STATUS_CB)
+		tm->tm_year += 100;
+	tm->tm_wday = regs[6];
+
+	err = rtc_valid_tm(tm);
+exit:
+	mutex_unlock(&amq->mutex);
+	return err;
+}
+
+
+static int am1805_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct am1805_data *amq;
+	u8 regs[10];
+	int err;
+
+	amq = i2c_get_clientdata(client);
+
+	mutex_lock(&amq->mutex);
+
+	err = am1805_stop_rtc(amq);
+	if (err < 0)
+		goto exit;
+	regs[0] = REG_HUNDREDS_ADDR;
+	regs[1] = bin2bcd(0);
+	regs[2] = bin2bcd(tm->tm_sec);
+	regs[3] = bin2bcd(tm->tm_min);
+	regs[4] = bin2bcd(tm->tm_hour);
+	regs[5] = bin2bcd(tm->tm_mday);
+	regs[6] = bin2bcd(tm->tm_mon+1);
+	regs[7] = bin2bcd(tm->tm_year - 100);
+	regs[8] = tm->tm_wday;
+
+
+	err = am1805_write(amq, regs, 8);
+	if (am1805_start_rtc(amq))
+		err =  -1;
+exit:
+	mutex_unlock(&amq->mutex);
+	return err;
+}
+
+/*******************************************************************************
+ * RAM byte
+ * 256 bytes available
+ * read return the byte pointed by ram_address
+ * write store the values in ram_address
+ */
+
+static ssize_t am1805_ram_byte_show(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	int err;
+	unsigned char ram_byte;
+	struct i2c_client *client;
+	struct am1805_data *amq;
+
+	client = to_i2c_client(dev);
+	amq = i2c_get_clientdata(client);
+	dev_dbg(&client->dev, "[%s]\n", __func__);
+
+	mutex_lock(&amq->mutex);
+	ram_byte = amq->ram_address;
+	ram_byte |= 0x80;
+	err = am1805_read(amq, &ram_byte, 1);
+	mutex_unlock(&amq->mutex);
+
+	if (err == 0)
+		err = sprintf(buf, "%02X\n", ram_byte);
+	return err;
+}
+
+static ssize_t am1805_ram_byte_store(struct device *dev,
+				      struct device_attribute *attr,
+				      const char *buf, size_t count)
+{
+	int err;
+	unsigned char reg[2];
+	struct i2c_client *client;
+	struct am1805_data *amq;
+
+	client = to_i2c_client(dev);
+	amq = i2c_get_clientdata(client);
+	dev_dbg(&client->dev, "[%s]\n", __func__);
+	mutex_lock(&amq->mutex);
+
+	err = kstrtou8(buf, 10, &reg[1]);
+	if (err == 0) {
+		reg[0] = amq->ram_address;
+		reg[0] |= 0x80;
+		err = am1805_write(amq, reg, 1);
+	}
+
+	mutex_unlock(&amq->mutex);
+	if (err)
+		return err;
+	return count;
+}
+
+static const struct device_attribute am1805_ram_byte_device_attribute = {
+	.attr.name  = "ram_byte",
+	.attr.mode  = 0600,
+	.show       = am1805_ram_byte_show,
+	.store      = am1805_ram_byte_store,
+};
+/****** END RAM BYTE ATTIBUTES  ********/
+
+/*******************************************************************************
+ * RAM Address
+ * 256 bytes available
+ * read return current ram_address
+ * write store the values in ram_address and set Extension Ram register
+ */
+
+static ssize_t am1805_ram_address_show(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	int err;
+	struct i2c_client *client;
+	struct am1805_data *amq;
+
+	client = to_i2c_client(dev);
+	amq = i2c_get_clientdata(client);
+	dev_dbg(&client->dev, "[%s]\n", __func__);
+
+	mutex_lock(&amq->mutex);
+	err = sprintf(buf, "%02X\n", amq->ram_address);
+	mutex_unlock(&amq->mutex);
+	return err;
+}
+
+static ssize_t am1805_ram_address_store(struct device *dev,
+					 struct device_attribute *attr,
+					 const char *buf, size_t count)
+{
+	int err;
+	unsigned char reg[2], ram_addr;
+	struct i2c_client *client;
+	struct am1805_data *amq;
+
+	client = to_i2c_client(dev);
+	amq = i2c_get_clientdata(client);
+	dev_dbg(&client->dev, "[%s]\n", __func__);
+	mutex_lock(&amq->mutex);
+
+	err = kstrtou8(buf, 10, &ram_addr);
+	if (err == 0) {
+		reg[0] = (unsigned char)(ram_addr ^ amq->ram_address);
+		reg[0] &= 0x80;
+		if (reg[0] == 0) {
+			/* no changes , same bank of memory) */
+			amq->ram_address = ram_addr;
+		} else {
+			reg[0] = REG_EXTRAM_ADDR;
+			err = am1805_read(amq, reg, 1);
+			if (err == 0) {
+				reg[1] = reg[0];
+				reg[0] = REG_EXTRAM_ADDR;
+				if (ram_addr & 0x80)
+					reg[1] |= REG_EXTRAM_XADA;
+				else
+					reg[1] &=  ~REG_EXTRAM_XADA;
+				err = am1805_write(amq, reg, 1);
+				if (err == 0)
+					amq->ram_address = ram_addr;
+			}
+		}
+	}
+
+	mutex_unlock(&amq->mutex);
+	if (err)
+		return err;
+	return count;
+}
+
+static const struct device_attribute am1805_ram_address_device_attribute = {
+	.attr.name  = "ram_address",
+	.attr.mode  = 0600,
+	.show       = am1805_ram_address_show,
+	.store      = am1805_ram_address_store,
+};
+/****** END RAM ADDRESS ATTIBUTES  ********/
+
+
+/*******************************************************************************
+ * WATCHDOG
+ * gettimeleft function is implemented via jiffies since hw doesn't support
+ * this capability
+ */
+
+static int am1805_watchdog_compute_seconds(int *seconds,
+					    unsigned char *wdt_reg, int steer)
+{
+	int err = 0;
+	unsigned char reg_value = 0x00;
+
+	/* WatchDog-duration = BMB x stepsize */
+	if (*seconds > 120) {
+		*seconds = 124;
+		reg_value = 31;
+		reg_value <<= 2;
+		reg_value |= WRB_4_SECONDS;
+	} else if (*seconds > 31) {
+		reg_value = (unsigned char)(*seconds);
+		reg_value >>= 2;
+		if (((int)reg_value * 4) != *seconds)
+			reg_value++;
+		*seconds = reg_value;
+		*seconds <<= 2;
+		reg_value <<= 2;
+		reg_value |= WRB_4_SECONDS;
+	} else if (*seconds >= 0) {
+		reg_value = (unsigned char)*seconds;
+		reg_value <<= 2;
+		reg_value |= WRB_1_SECOND;
+	} else {
+		err =  -EINVAL;
+	}
+	if (steer)
+		reg_value |= REG_WATCHDOG_WDS;
+	if (wdt_reg != NULL)
+		*wdt_reg = reg_value;
+	return err;
+}
+
+static int am1805_watchdog_disable(struct am1805_data *am_data)
+{
+	int err;
+	unsigned char regs[2];
+
+	/* disable wdt */
+	regs[0] = REG_WATCHDOG_ADDR;
+	if (am_data->watchdog_steering)
+		regs[1] = (unsigned char)REG_WATCHDOG_WDS;
+	else
+		regs[1] = 0x00;
+	err = am1805_write(am_data, regs, 1);
+	if (err) {
+		dev_err(&am_data->client->dev,
+			"[%s] write watchdog reg ERROR\n", __func__);
+		return err;
+	}
+	regs[0] = REG_STATUS_ADDR;
+	err = am1805_read(am_data, regs, 1);
+	if (err) {
+		dev_err(&am_data->client->dev,
+			"[%s] read status reg ERROR\n", __func__);
+		return err;
+	}
+	regs[1] = regs[0];
+	regs[0] = REG_STATUS_ADDR;
+	regs[1] &=  ~REG_STATUS_WDT;
+	err = am1805_write(am_data, regs, 1);
+	if (err)
+		dev_err(&am_data->client->dev,
+			"[%s] write status reg ERROR\n", __func__);
+	am_data->watchdog_enabled = 0;
+	return err;
+}
+
+static int am1805_watchdog_enable(struct am1805_data *am_data)
+{
+	int err;
+	unsigned char regs[2];
+
+	err = am1805_watchdog_disable(am_data);
+	if (err)
+		return err;
+	/* CALCULATE THE REFRESH VALUE */
+	err = am1805_watchdog_compute_seconds(&am_data->watchdog_timeout,
+					      &am_data->watchdog_reg,
+					      am_data->watchdog_steering);
+	if (err) {
+		dev_err(&am_data->client->dev,
+			"[%s] problems while computing actual timeout\n",
+			__func__);
+		return err;
+	}
+
+	regs[0] = REG_WATCHDOG_ADDR;
+	regs[1] = am_data->watchdog_reg;
+	err = am1805_write(am_data, regs, 1);
+	if (err) {
+		dev_err(&am_data->client->dev,
+			"[%s] write watchdog reg ERROR\n", __func__);
+		return err;
+	}
+	am_data->watchdog_start_jiffies = jiffies;
+	am_data->watchdog_enabled = 1;
+	return 0;
+}
+
+static int am1805_watchdog_start_op(struct watchdog_device *device)
+{
+	int err;
+	struct i2c_client *client;
+	struct am1805_data *amq;
+
+	client = watchdog_get_drvdata(device);
+	amq = i2c_get_clientdata(client);
+	dev_dbg(&client->dev, "[%s]\n", __func__);
+
+	mutex_lock(&amq->mutex);
+	/* disable wdt */
+	//err=am1805_watchdog_disable(amq);
+	//if (err==0) {
+		err = am1805_watchdog_enable(amq);
+		if (err == 0)
+			dev_dbg(&client->dev,
+				"[%s] watchdog enabled, seconds = %d\n",
+				__func__, amq->watchdog_timeout);
+	//}
+	mutex_unlock(&amq->mutex);
+	return err;
+}
+
+static int am1805_watchdog_stop_op(struct watchdog_device *device)
+{
+	int err;
+	struct i2c_client *client;
+	struct am1805_data *amq;
+
+	client = watchdog_get_drvdata(device);
+	amq = i2c_get_clientdata(client);
+	dev_dbg(&client->dev, "[%s]\n", __func__);
+
+	mutex_lock(&amq->mutex);
+	err = am1805_watchdog_disable(amq);
+	if (err == 0)
+		dev_dbg(&client->dev, "[%s] watchdog disabled\n", __func__);
+	mutex_unlock(&amq->mutex);
+	return err;
+}
+
+static int am1805_watchdog_ping_op(struct watchdog_device *device)
+{
+	unsigned char regs[2];
+	int err;
+	struct i2c_client *client;
+	struct am1805_data *amq;
+
+	client = watchdog_get_drvdata(device);
+	amq = i2c_get_clientdata(client);
+	dev_dbg(&client->dev, "[%s]\n", __func__);
+
+	mutex_lock(&amq->mutex);
+	if (amq->watchdog_enabled) {
+		regs[0] = REG_WATCHDOG_ADDR;
+		regs[1] = amq->watchdog_reg;
+		err = am1805_write(amq, regs, 1);
+		if (err)
+			dev_err(&amq->client->dev,
+				"[%s] write watchdog reg ERROR\n", __func__);
+	} else {
+		err = 0;
+		dev_dbg(&client->dev, "[%s] can not ping disabled watchdog\n",
+			__func__);
+	}
+	mutex_unlock(&amq->mutex);
+	return err;
+}
+
+static int am1805_watchdog_set_timeout_op(struct watchdog_device *device,
+					   unsigned int timeout)
+{
+	int err;
+	unsigned int seconds;
+	struct i2c_client *client;
+	struct am1805_data *amq;
+	unsigned char reg_data;
+
+	client = watchdog_get_drvdata(device);
+	amq = i2c_get_clientdata(client);
+
+	dev_dbg(&client->dev, "[%s]\n", __func__);
+	seconds = (int)timeout;
+	mutex_lock(&amq->mutex);
+	err = am1805_watchdog_compute_seconds((int *)&seconds, &reg_data,
+					      amq->watchdog_steering);
+	if (err == 0) {
+		device->timeout = (unsigned int)seconds;
+		amq->watchdog_timeout = seconds;
+		amq->watchdog_reg = reg_data;
+	} else
+		dev_err(&client->dev,
+			"[%s] problems while computing actual timeout\n",
+			__func__);
+
+	mutex_unlock(&amq->mutex);
+	return 0;
+}
+
+static unsigned int am1805_watchdog_get_timeleft_op(struct watchdog_device
+						     *device)
+{
+	unsigned int time_left;
+	struct i2c_client *client;
+	struct am1805_data *amq;
+
+	client = watchdog_get_drvdata(device);
+	amq = i2c_get_clientdata(client);
+	dev_dbg(&client->dev, "[%s]\n", __func__);
+	mutex_lock(&amq->mutex);
+	time_left = jiffies;
+	time_left -= amq->watchdog_start_jiffies;
+	time_left = (unsigned int)(time_left/HZ);
+	mutex_unlock(&amq->mutex);
+	return time_left;
+}
+
+static struct watchdog_info am1805_watchdog_info = {
+	.options	= WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING
+			  | WDIOF_MAGICCLOSE,
+	.firmware_version = 0x00000100,
+	.identity       = "AM1805 Watchdog",
+};
+
+static struct watchdog_ops am1805_watchdog_ops = {
+	.owner          = THIS_MODULE,
+	.start          = am1805_watchdog_start_op,
+	.stop           = am1805_watchdog_stop_op,
+	.ping           = am1805_watchdog_ping_op,
+	.set_timeout    = am1805_watchdog_set_timeout_op,
+	.get_timeleft   = am1805_watchdog_get_timeleft_op,
+};
+
+static struct watchdog_device am1805_watchdog_device = {
+	.info           = &am1805_watchdog_info,
+	.ops            = &am1805_watchdog_ops,
+	.timeout        = DEFAULT_WATCHDOG_TIMEOUT,
+	.min_timeout    = 1,
+	.max_timeout    = 124,
+};
+
+/****** END Watchdog FUNCTIONS  ********/
+
+/****** START ALARM FUNCTIONS   ********/
+
+static int am1805_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+	int err;
+	unsigned char regs[7];
+	struct i2c_client *client;
+	struct am1805_data *amq;
+
+	client = to_i2c_client(dev);
+	amq = i2c_get_clientdata(client);
+	dev_dbg(&client->dev, "[%s]\n", __func__);
+	mutex_lock(&amq->mutex);
+	regs[0] = REG_ALM_SECONDS_ADDR;
+	err = am1805_read(amq, regs, 6);
+	if (err) {
+		dev_err(&client->dev, "[%s] read %02X 6 register\n", __func__,
+			REG_ALM_SECONDS_ADDR);
+		goto exit;
+	}
+	regs[0] &= SECONDS_BITS;
+	regs[1] &= MINUTES_BITS;
+	regs[2] &= HOURS_BITS;
+	regs[3] &= DATE_BITS;
+	regs[4] &= MONTHS_BITS;
+	regs[5] &= WEEKDAY_BITS;
+
+	alarm->time.tm_sec  = bcd2bin(regs[0]);
+	alarm->time.tm_min  = bcd2bin(regs[1]);
+	alarm->time.tm_hour = bcd2bin(regs[2]);
+	alarm->time.tm_mday = bcd2bin(regs[3]);
+	alarm->time.tm_mon  = bcd2bin(regs[4]);
+	if (alarm->time.tm_mon > 0)
+		alarm->time.tm_mon--;
+	alarm->time.tm_wday = regs[5];
+
+	alarm->time.tm_year = -1;
+	alarm->time.tm_yday = -1;
+	alarm->time.tm_isdst = -1;
+
+	regs[0] = REG_IRQ_MASK_ADDR;
+	err = am1805_read(amq, regs, 1);
+	if (err) {
+		dev_err(&client->dev, "[%s] read %02X 1 register\n", __func__,
+			REG_IRQ_MASK_ADDR);
+		goto exit;
+	}
+	alarm->enabled = (regs[0] & REG_IRQ_MASK_AIE) ? 1 : 0;
+
+	regs[0] = REG_STATUS_ADDR;
+	err = am1805_read(amq, regs, 1);
+	if (err) {
+		dev_err(&client->dev, "[%s] read %02X 1 register\n",
+			__func__, REG_STATUS_ADDR);
+		goto exit;
+	}
+	alarm->pending = (regs[0] & REG_STATUS_ALM) ? 1 : 0;
+exit:
+	mutex_unlock(&amq->mutex);
+	return err;
+}
+
+
+static int am1805_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+	int err;
+	unsigned char regs[8];
+	unsigned char timer_ctrl_reg, irq_mask_reg;
+	struct i2c_client *client;
+	struct am1805_data *amq;
+
+	client = to_i2c_client(dev);
+	amq = i2c_get_clientdata(client);
+	dev_dbg(&client->dev, "[%s]\n", __func__);
+	/* Disable alarm */
+	mutex_lock(&amq->mutex);
+	regs[0] = REG_TIMER_CTRL_ADDR;
+	err = am1805_read(amq, regs, 1);
+	if (err) {
+		dev_err(&client->dev, "[%s] read %02X 1 register\n",
+			__func__, REG_TIMER_CTRL_ADDR);
+		err = -EIO;
+		goto exit;
+	}
+	regs[1] = regs[0];
+	regs[0] = REG_TIMER_CTRL_ADDR;
+	regs[1] &= (unsigned char)(~REG_TIMER_CTRL_RPT_BITS);
+	timer_ctrl_reg = regs[1];
+	err = am1805_write(amq, regs, 1);
+	if (err) {
+		dev_err(&client->dev, "[%s] write %02X 1 register\n",
+			__func__, REG_TIMER_CTRL_ADDR);
+		err = -EIO;
+		goto exit;
+	}
+
+	regs[0] = REG_IRQ_MASK_ADDR;
+	err = am1805_read(amq, regs, 1);
+	if (err) {
+		dev_err(&client->dev, "[%s] read %02X 1 register\n",
+			__func__, REG_IRQ_MASK_ADDR);
+		err = -EIO;
+		goto exit;
+	}
+	regs[1] = regs[0];
+	regs[0] = REG_IRQ_MASK_ADDR;
+	regs[1] &= (unsigned char)(~REG_IRQ_MASK_AIE);
+	irq_mask_reg = regs[1];
+	err = am1805_write(amq, regs, 1);
+	if (err) {
+		dev_err(&client->dev, "[%s] write %02X 1 register\n",
+			__func__, REG_IRQ_MASK_ADDR);
+		err = -EIO;
+		goto exit;
+	}
+	regs[0] = REG_STATUS_ADDR;
+	err = am1805_read(amq, regs, 1);
+	if (err) {
+		dev_err(&client->dev, "[%s] read %02X 1 register\n",
+			__func__, REG_STATUS_ADDR);
+		err = -EIO;
+		goto exit;
+	}
+	regs[1] = regs[0];
+	regs[0] = REG_STATUS_ADDR;
+	regs[1] &= (unsigned char)(~REG_STATUS_ALM);
+	err = am1805_write(amq, regs, 1);
+	if (err) {
+		dev_err(&client->dev, "[%s] write %02X 1 register\n",
+			__func__, REG_STATUS_ADDR);
+		err = -EIO;
+		goto exit;
+	}
+	if (alarm->enabled) {
+		regs[0] = REG_ALM_HUNDREDS_ADDR;
+		regs[1] = bin2bcd(0);	/* hundreds of seconds */
+		regs[2] = bin2bcd(alarm->time.tm_sec);
+		regs[3] = bin2bcd(alarm->time.tm_min);
+		regs[4] = bin2bcd(alarm->time.tm_hour);
+		regs[5] = bin2bcd(alarm->time.tm_mday);
+		regs[6] = bin2bcd(alarm->time.tm_mon + 1);
+		regs[7] = (unsigned char)(alarm->time.tm_wday & 0x07);
+		err = am1805_write(amq, regs, 7);
+		if (err) {
+			dev_err(&client->dev, "[%s] write %02X 7 register\n",
+				__func__, REG_ALM_HUNDREDS_ADDR);
+			err = -EIO;
+			goto exit;
+		}
+		regs[0] = REG_IRQ_MASK_ADDR;
+		regs[1] = irq_mask_reg;
+		regs[1] |= REG_IRQ_MASK_AIE;
+		err = am1805_write(amq, regs, 1);
+		if (err) {
+			dev_err(&client->dev, "[%s] write %02X 1 register\n",
+				__func__, REG_IRQ_MASK_ADDR);
+			err = -EIO;
+			goto exit;
+		}
+		regs[0] = REG_TIMER_CTRL_ADDR;
+		regs[1] = timer_ctrl_reg;
+		regs[1] |= (unsigned char)(1 << 2);
+		err = am1805_write(amq, regs, 1);
+		if (err) {
+			dev_err(&client->dev,
+				"[%s] write %02X 1 register\n", __func__,
+				REG_TIMER_CTRL_ADDR);
+			err = -EIO;
+		}
+	}
+exit:
+	mutex_unlock(&amq->mutex);
+	return err;
+}
+
+static ssize_t am1805_board_turn_on_show(struct device *dev,
+					  struct device_attribute *attr,
+					  char *buf)
+{
+	int err;
+	struct i2c_client *client;
+	struct am1805_data *amq;
+
+	client = to_i2c_client(dev);
+	amq = i2c_get_clientdata(client);
+	dev_dbg(&client->dev, "[%s]\n", __func__);
+	if (amq->board_turn_on)
+		err = sprintf(buf, "1\n");
+	else
+		err = sprintf(buf, "0\n");
+	return err;
+}
+
+static ssize_t am1805_board_turn_on_store(struct device *dev,
+					   struct device_attribute *attr,
+					   const char *buf, size_t count)
+{
+	int err, value;
+	struct i2c_client *client;
+	struct am1805_data *amq;
+	unsigned char regs[4];
+
+	client = to_i2c_client(dev);
+	amq = i2c_get_clientdata(client);
+	dev_dbg(&client->dev, "[%s]\n", __func__);
+	mutex_lock(&amq->mutex);
+
+	err = kstrtos32(buf, 10, &value);
+	if (err == 0) {
+		regs[0] = REG_CONTROL1_ADDR;
+		err = am1805_read(amq, regs, 2);
+		if (err) {
+			dev_err(&client->dev,
+				"[%s] read %02X register , count=2\n",
+				__func__, REG_CONTROL1_ADDR);
+			err = -EIO;
+			goto exit;
+		}
+		regs[2] = regs[1];
+		regs[1] = regs[0];
+		regs[0] = REG_CONTROL1_ADDR;
+		regs[1] |= REG_CONTROL1_OUTB;
+		regs[2] &= (unsigned char)(~REG_CONTROL2_OUT2S_BITS);
+		if (value == 0) {
+			regs[2] |= (unsigned char)(7 << 2);
+			amq->board_turn_on = 0;
+		} else {
+			regs[2] |= (unsigned char)(3 << 2);
+			amq->board_turn_on = 1;
+		}
+		err = am1805_write(amq, regs, 2);
+		if (err) {
+			dev_err(&client->dev,
+				"[%s] write %02X register , count=2\n",
+				__func__, REG_CONTROL1_ADDR);
+			err = -EIO;
+			goto exit;
+		} else
+			err = count;
+	}
+exit:
+	mutex_unlock(&amq->mutex);
+	return err;
+}
+
+static const struct device_attribute am1805_board_turn_on_device_attribute = {
+	.attr.name  = "board_turn_on",
+	.attr.mode  = 0600,
+	.show       = am1805_board_turn_on_show,
+	.store      = am1805_board_turn_on_store,
+};
+
+/****** END ALARM FUNCTIONS     ********/
+
+static const struct rtc_class_ops am1805_rtc_ops = {
+	.read_time	= am1805_rtc_read_time,
+	.set_time	= am1805_rtc_set_time,
+	.set_alarm	= am1805_rtc_set_alarm,
+	.read_alarm	= am1805_rtc_read_alarm,
+};
+
+static void am1805_unload(struct i2c_client *client)
+{
+	struct am1805_data *amq;
+
+	dev_dbg(&client->dev, "[%s]\n", __func__);
+
+	amq = i2c_get_clientdata(client);
+	if (amq->ram_byte_file_created) {
+		sysfs_remove_file(&client->dev.kobj,
+				  &am1805_ram_byte_device_attribute.attr);
+	}
+	if (amq->ram_address_file_created) {
+		sysfs_remove_file(&client->dev.kobj,
+				  &am1805_ram_address_device_attribute.attr);
+	}
+	if (amq->board_turn_on_file_created) {
+		sysfs_remove_file(&client->dev.kobj,
+				  &am1805_board_turn_on_device_attribute.attr);
+	}
+
+	if (amq->watchdog_registered) {
+		device_wakeup_disable(&client->dev);
+		watchdog_unregister_device(&am1805_watchdog_device);
+	}
+	devm_kfree(&client->dev, amq);
+}
+
+static int am1805_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct am1805_data *amq;
+	int err;
+	u8 regs[2];
+	u8 xt_calib_value = 0;
+	u32 smbus_func = (I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA
+			  | I2C_FUNC_SMBUS_I2C_BLOCK);
+
+	dev_info(&client->dev, "probe_start, driver version %s\n",
+		 DRIVER_VERSION);
+
+	amq = devm_kzalloc(&client->dev, sizeof(struct am1805_data),
+			   GFP_KERNEL);
+	if (amq == NULL) {
+		err = -ENOMEM;
+		dev_err(&client->dev,
+			"failed to allocate memory for module data: %d\n", err);
+		goto exit;
+	}
+	amq->ram_byte_file_created = 0;
+	amq->ram_address_file_created = 0;
+	amq->watchdog_timeout = timeout;
+	amq->watchdog_disable_on_boot = disable_on_boot;
+	amq->watchdog_steering = watchdog_steering;
+	amq->watchdog_enabled = 0;
+	amq->board_turn_on = board_turn_on;
+	amq->board_turn_on_file_created = 0;
+	amq->trickle_register = (unsigned char)trickle_register;
+	if (amq->watchdog_steering)
+		amq->watchdog_reg = REG_WATCHDOG_WDS;
+	else
+		amq->watchdog_reg = 0;
+	amq->watchdog_start_jiffies = 0;
+	amq->watchdog_registered = 0;
+	if ((i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+	    && (force_smbus == 0)) {
+		amq->use_smbus = 0;
+	} else {
+		dev_warn(&client->dev, "client not i2c capable\n");
+		if (i2c_check_functionality(client->adapter, smbus_func)) {
+			amq->use_smbus = 1;
+			dev_warn(&client->dev, "client smbus capable\n");
+		} else {
+			err = -ENODEV;
+			dev_err(&client->dev, "client not SMBUS capable\n");
+			goto exit;
+		}
+	}
+
+	mutex_init(&amq->mutex);
+
+	amq->client = client;
+	i2c_set_clientdata(client, amq);
+
+	/* check identity register */
+	regs[0] = REG_IDENTITY_ADDR;
+	if (am1805_read(amq, regs, 1)) {
+		err = -ENODEV;
+		dev_err(&client->dev,
+			"fail to fetch identity register 0x%02X\n",
+			REG_IDENTITY_ADDR);
+		goto exit;
+	}
+
+	if (regs[0] != AM1805_IDENTITY_CODE) {
+		err = -ENODEV;
+		dev_err(&client->dev,
+			"chip not found,invalid identity code 0x%02X\n",
+			regs[0]);
+		goto exit;
+
+	}
+
+	/* set the trickle_register */
+	regs[0] = REG_CONFIGKEY_ADDR;
+	regs[1] = 0x9D;
+	if (am1805_write(amq, regs, 1)) {
+		err = -ENODEV;
+		dev_err(&client->dev,
+			"fail to set configuration key register\n");
+		goto exit;
+	}
+	regs[0] = REG_TRICKLE_ADDR;
+	regs[1] = amq->trickle_register;
+	if (am1805_write(amq, regs, 1)) {
+		err = -ENODEV;
+		dev_err(&client->dev, "fail to set trickle register\n");
+		goto exit;
+	}
+
+	/* set extended ram register to default value */
+	amq->ram_address = 0x00;
+	regs[0] = REG_EXTRAM_ADDR;
+
+	if (am1805_read(amq, regs, 1)) {
+		err = -ENODEV;
+		dev_err(&client->dev, "fail to fetch extension ram register\n");
+		goto exit;
+	}
+	regs[1] = regs[0];
+	regs[0] = REG_EXTRAM_ADDR;
+	regs[1] &= ~REG_EXTRAM_XADA;
+
+	if (am1805_write(amq, regs, 1)) {
+		err = -ENODEV;
+		dev_err(&client->dev, "fail to set extension ram register\n");
+		goto exit;
+	}
+
+	/* ulock LKO2 in oscillator status register in order to drive OUTB */
+	/*
+	 * Bit_6-7 xtcal = 0
+	 * Bit_5 LKO2 = 0
+	 * Bit_4 OMODE = 0
+	 * Bit_2-3 RESERVED = 0
+	 * Bit_1 OF = 1
+	 * Bit_0 ACF = 0
+	 */
+	/* calibrate the XT oscillator */
+	regs[1] = 0x02;
+	xt_calib_value = 0x00;
+	if (xt_clock_adj <  -320)
+		dev_warn(&client->dev,
+			 "XT frequency too high to be calibrated adj = %d\n",
+			 xt_clock_adj);
+	else if (xt_clock_adj <  -256) {
+		/* XTCAL=3 CMDX=1 OFFSETX=(adj+192)/2 */
+		regs[1] |= REG_OSC_STATUS_ACAL_3;
+		xt_calib_value = (unsigned char)((int)(xt_clock_adj+192)>>1);
+		xt_calib_value &= REG_XT_CALIB_OFFSETX_MASK;
+		xt_calib_value |= REG_XT_CALIB_CMDX;
+	} else if (xt_clock_adj <  -192) {
+		/* XTCAL=3 CMDX=0 OFFSETX=(adj+192) */
+		regs[1] |= REG_OSC_STATUS_ACAL_3;
+		xt_calib_value = (unsigned char)((int)(xt_clock_adj+192));
+		xt_calib_value &= REG_XT_CALIB_OFFSETX_MASK;
+	} else if (xt_clock_adj <  -128) {
+		/* XTCAL=2 CMDX=0 OFFSETX=(adj+128) */
+		regs[1] |= REG_OSC_STATUS_ACAL_2;
+		xt_calib_value = (unsigned char)((int)(xt_clock_adj+128));
+		xt_calib_value &= REG_XT_CALIB_OFFSETX_MASK;
+	} else if (xt_clock_adj <  -64) {
+		/* XTCAL=1 CMDX=0 OFFSETX=(adj+64) */
+		regs[1] |= REG_OSC_STATUS_ACAL_1;
+		xt_calib_value = (unsigned char)((int)(xt_clock_adj+64));
+		xt_calib_value &= REG_XT_CALIB_OFFSETX_MASK;
+	} else if (xt_clock_adj < 64) {
+		/* XTCAL=0 CMDX=0 OFFSETX=(adj) */
+		regs[1] |= REG_OSC_STATUS_ACAL_0;
+		xt_calib_value = (unsigned char)(xt_clock_adj);
+		xt_calib_value &= REG_XT_CALIB_OFFSETX_MASK;
+	} else if (xt_clock_adj < 128) {
+		/* XTCAL=0 CMDX=1 OFFSETX=(adj)/2 */
+		regs[1] |= REG_OSC_STATUS_ACAL_0;
+		xt_calib_value = (unsigned char)((int)(xt_clock_adj>>1));
+		xt_calib_value &= REG_XT_CALIB_OFFSETX_MASK;
+		xt_calib_value |= REG_XT_CALIB_CMDX;
+	} else
+		dev_warn(&client->dev,
+			 "XT frequency too low to be calibrated adj = %d\n",
+			 xt_clock_adj);
+
+	regs[0] = REG_OSC_STATUS_ADDR;
+	if (am1805_write(amq, regs, 1)) {
+		err = -ENODEV;
+		dev_err(&client->dev,
+			"fail to set oscillator status register\n");
+		goto exit;
+	}
+
+	/* Calibration XT Register */
+	regs[0] = REG_XT_CALIB_ADDR;
+	regs[1] = xt_calib_value;
+	if (am1805_write(amq, regs, 1)) {
+		err = -ENODEV;
+		dev_err(&client->dev, "fail to set XT calibration register\n");
+		goto exit;
+	}
+
+	/*
+	 * CONTROL1 register
+	 * STOP = 0	12/24 = 0
+	 * OUTB = 1 remove power latch due to rtc , OUT = 1
+	 * RSP = 0 due to watchdog  active low
+	 * ARST = 0	PWR2 = 1 WRTC = 1
+	 */
+	regs[0] = REG_CONTROL1_ADDR;
+	regs[1] = (REG_CONTROL1_OUTB|REG_CONTROL1_OUT | REG_CONTROL1_PWR2
+		   | REG_CONTROL1_WRTC);
+	if (am1805_write(amq, regs, 1)) {
+		err = -ENODEV;
+		dev_err(&client->dev, "fail to set control1 register\n");
+		goto exit;
+	}
+
+	/*
+	 * CONTROL2 register
+	 * Bit_6-7 reseved = 0
+	 * Bit_5   RS1E	= 0 due to watchdog
+	 * Bit_2-4 OUT2S = 7 (board_turn_on =0) ; (3 board turn on =1)
+	 * Bit_0-1 OUT1S = 3 due to alarm
+	 */
+	regs[0] = REG_CONTROL2_ADDR;
+	regs[1] = 0;
+	if (amq->board_turn_on)
+		regs[1] |= 0x03;
+	else
+		regs[1] |= 0x07;
+	regs[1] <<= 2;
+	regs[1] |= 0x03;
+
+	if (am1805_write(amq, regs, 1)) {
+		err = -ENODEV;
+		dev_err(&client->dev, "fail to set control2 register\n");
+		goto exit;
+	}
+
+	/*
+	 * alarm IRQ must be on level
+	 * Bit_7   CEB = 1
+	 * Bit_5-6 IM = 3 ALARM IRQ 1/4 sec
+	 * Bit_4 BLIE = 0
+	 * Bit_3 TIE = 0
+	 * Bit_2 AIE = 0
+	 * Bit_1 EX2E = 0
+	 * Bit_0 EX1E = 0
+	 */
+	regs[0] = REG_IRQ_MASK_ADDR;
+	regs[1] = 0xE0;	/* set im field to 0 */
+	if (am1805_write(amq, regs, 1)) {
+		err = -ENODEV;
+		dev_err(&client->dev, "fail to set interrupt mask register\n");
+		goto exit;
+	}
+	/*
+	 * Disable alarm interrupt
+	 * Bit_7 TE = 0
+	 * Bit_6 TM = 0
+	 * Bit_5 TRPT = 1
+	 * Bit_2-4 RPT=0	ALARM DISABLE
+	 * Bit_0-1 TFS=3
+	 */
+	regs[0] = REG_TIMER_CTRL_ADDR;
+	regs[1] = 0x23;
+	if (am1805_write(amq, regs, 1)) {
+		err = -ENODEV;
+		dev_err(&client->dev,
+			"fail to set countdown timer control register\n");
+		goto exit;
+	}
+
+
+	/* clear the status register */
+	regs[0] = REG_STATUS_ADDR;
+	regs[1] = 0x00;
+	if (am1805_write(amq, regs, 1)) {
+		err = -ENODEV;
+		dev_err(&client->dev, "fail to clear status register\n");
+		goto exit;
+	}
+
+	amq->rtc = devm_rtc_device_register(&client->dev,
+					    am1805_driver.driver.name,
+					    &am1805_rtc_ops, THIS_MODULE);
+
+	if (IS_ERR(amq->rtc)) {
+		dev_err(&client->dev, "fail to register rtc device\n");
+		err = PTR_ERR(amq->rtc);
+		goto exit;
+	}
+	amq->rtc->uie_unsupported = 1;
+
+
+	/* RAM byte initialization */
+	err = sysfs_create_file(&client->dev.kobj,
+				&am1805_ram_byte_device_attribute.attr);
+	if (err) {
+		dev_err(&client->dev, "fail to create sysfs file \"%s\"\n",
+			am1805_ram_byte_device_attribute.attr.name);
+		goto exit;
+	}
+	amq->ram_byte_file_created = 1;
+
+	/* RAM address initialization */
+	err = sysfs_create_file(&client->dev.kobj,
+				&am1805_ram_address_device_attribute.attr);
+	if (err) {
+		dev_err(&client->dev, "fail to create sysfs file \"%s\"\n",
+			am1805_ram_address_device_attribute.attr.name);
+		goto exit;
+	}
+	amq->ram_address_file_created = 1;
+
+	/* board turn on initialization */
+	err = sysfs_create_file(&client->dev.kobj,
+				&am1805_board_turn_on_device_attribute.attr);
+	if (err) {
+		dev_err(&client->dev, "fail to create sysfs file \"%s\"\n",
+			am1805_board_turn_on_device_attribute.attr.name);
+		goto exit;
+	}
+	amq->board_turn_on_file_created = 1;
+
+	/* Watchdog driver registration */
+	watchdog_set_drvdata(&am1805_watchdog_device, client);
+	watchdog_init_timeout(&am1805_watchdog_device, amq->watchdog_timeout,
+			      NULL);
+	watchdog_set_nowayout(&am1805_watchdog_device, nowayout);
+	err = watchdog_register_device(&am1805_watchdog_device);
+	if (err) {
+		dev_err(&client->dev,
+			"ERROR, FAIL to register watchdog device\n");
+		goto exit;
+	}
+	amq->watchdog_registered = 1;
+	dev_info(&client->dev, "registered %s as watchdog%d\n",
+		 am1805_driver.driver.name, am1805_watchdog_device.id);
+
+	if (amq->watchdog_disable_on_boot) {
+		dev_info(&client->dev, "watchdog timer disabled at boot\n");
+		err = am1805_watchdog_disable(amq);
+		if (err)
+			goto exit;
+	} else {
+		dev_info(&client->dev,
+			 "watchdog timer enabled at boot, %d s\n",
+			 amq->watchdog_timeout);
+		err = am1805_watchdog_enable(amq);
+		if (err)
+			goto exit;
+	}
+	err = device_init_wakeup(&client->dev, true);
+	if (err)
+		dev_err(&client->dev, "dev_init_wakeup [%d] FAIL\n", err);
+	dev_info(&client->dev, "probe_end, init OK\n");
+	return 0;
+exit:
+	dev_info(&client->dev, "probe_end, init FAIL\n");
+	am1805_unload(client);
+	return err;
+}
+
+static int am1805_remove(struct i2c_client *client)
+{
+	dev_dbg(&client->dev, "[%s]\n", __func__);
+	am1805_unload(client);
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int am1805_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct am1805_data *amq;
+	unsigned char regs[2];
+	int err;
+
+	amq = i2c_get_clientdata(client);
+
+	dev_dbg(&client->dev, "[%s]\n", __func__);
+	mutex_lock(&amq->mutex);
+	/* is alarm expired? */
+	regs[0] = REG_STATUS_ADDR;
+	err = am1805_read(amq, regs, 1);
+	if (err) {
+		dev_err(&client->dev, "[%s] read %02X 1 register\n",
+			__func__, REG_STATUS_ADDR);
+		err = -EIO;
+		goto exit;
+	}
+
+	if (regs[0] & REG_STATUS_ALM) {
+		/* Disable alarm */
+		regs[0] = REG_TIMER_CTRL_ADDR;
+		err = am1805_read(amq, regs, 1);
+		if (err) {
+			dev_err(&client->dev, "[%s] read %02X 1 register\n",
+				__func__, REG_TIMER_CTRL_ADDR);
+			err = -EIO;
+			goto exit;
+		}
+		regs[1] = regs[0];
+		regs[0] = REG_TIMER_CTRL_ADDR;
+		regs[1] &= (unsigned char)(~REG_TIMER_CTRL_RPT_BITS);
+		err = am1805_write(amq, regs, 1);
+		if (err) {
+			dev_err(&client->dev, "[%s] write %02X 1 register\n",
+				__func__, REG_TIMER_CTRL_ADDR);
+			err = -EIO;
+			goto exit;
+		}
+
+		regs[0] = REG_IRQ_MASK_ADDR;
+		err = am1805_read(amq, regs, 1);
+		if (err) {
+			dev_err(&client->dev, "[%s] read %02X 1 register\n",
+				__func__, REG_IRQ_MASK_ADDR);
+			err = -EIO;
+			goto exit;
+		}
+		regs[1] = regs[0];
+		regs[0] = REG_IRQ_MASK_ADDR;
+		regs[1] &= (unsigned char)(~REG_IRQ_MASK_AIE);
+		err = am1805_write(amq, regs, 1);
+		if (err) {
+			dev_err(&client->dev, "[%s] write %02X 1 register\n",
+				__func__, REG_IRQ_MASK_ADDR);
+			err = -EIO;
+			goto exit;
+		}
+		regs[0] = REG_STATUS_ADDR;
+		err = am1805_read(amq, regs, 1);
+		if (err) {
+			dev_err(&client->dev, "[%s] read %02X 1 register\n",
+				__func__, REG_STATUS_ADDR);
+			err = -EIO;
+			goto exit;
+		}
+		regs[1] = regs[0];
+		regs[0] = REG_STATUS_ADDR;
+		regs[1] &= (unsigned char)(~REG_STATUS_ALM);
+		err = am1805_write(amq, regs, 1);
+		if (err) {
+			dev_err(&client->dev, "[%s] write %02X 1 register\n",
+				__func__, REG_STATUS_ADDR);
+			err = -EIO;
+			goto exit;
+		}
+	}
+
+exit:
+	mutex_unlock(&amq->mutex);
+	return err;
+}
+
+static int am1805_suspend(struct device *dev)
+{
+	/* nothing to do at the moment */
+	return 0;
+}
+#else
+#define am1805_suspend	NULL
+#define am1805_resume	NULL
+#endif /* CONFIG_PM_SLEEP */
+
+static SIMPLE_DEV_PM_OPS(am1805_pm, am1805_suspend, am1805_resume);
+
+static const struct i2c_device_id am1805_id[] = {
+	{ "am1805", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, am1805_id);
+
+static struct i2c_driver am1805_driver = {
+	.driver = {
+		.name = DRIVER_NAME,
+		.owner = THIS_MODULE,
+		.pm    = &am1805_pm,
+	},
+	.probe = am1805_probe,
+	.remove = am1805_remove,
+	.id_table = am1805_id,
+};
+module_i2c_driver(am1805_driver);
+
+MODULE_AUTHOR("Pierluigi Driusso <pierluigi.driusso@eurotech.com>");
+MODULE_DESCRIPTION("Ambiq micro AM1805 RTC driver");
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION(DRIVER_VERSION);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-at91sam9.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-at91sam9.c
@@ -370,6 +370,7 @@
 		return ret;
 
 	rtc->gpbr = syscon_node_to_regmap(args.np);
+	of_node_put(args.np);
 	rtc->gpbr_offset = args.args[0];
 	if (IS_ERR(rtc->gpbr)) {
 		dev_err(&pdev->dev, "failed to retrieve gpbr regmap, aborting.\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-bd70528.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-bd70528.c
@@ -491,3 +491,4 @@
 MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
 MODULE_DESCRIPTION("BD70528 RTC driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:bd70528-rtc");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-brcmstb-waketimer.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-brcmstb-waketimer.c
@@ -277,6 +277,7 @@
 	struct brcmstb_waketmr *timer = dev_get_drvdata(&pdev->dev);
 
 	unregister_reboot_notifier(&timer->reboot_notifier);
+	clk_disable_unprepare(timer->clk);
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-cmos.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-cmos.c
@@ -463,7 +463,10 @@
 	min = t->time.tm_min;
 	sec = t->time.tm_sec;
 
+	spin_lock_irq(&rtc_lock);
 	rtc_control = CMOS_READ(RTC_CONTROL);
+	spin_unlock_irq(&rtc_lock);
+
 	if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
 		/* Writing 0xff means "don't care" or "match all".  */
 		mon = (mon <= 12) ? bin2bcd(mon) : 0xff;
@@ -594,11 +597,10 @@
 			   size_t count)
 {
 	unsigned char *buf = val;
-	int	retval;
 
 	off += NVRAM_OFFSET;
 	spin_lock_irq(&rtc_lock);
-	for (retval = 0; count; count--, off++, retval++) {
+	for (; count; count--, off++) {
 		if (off < 128)
 			*buf++ = CMOS_READ(off);
 		else if (can_bank2)
@@ -608,7 +610,7 @@
 	}
 	spin_unlock_irq(&rtc_lock);
 
-	return retval;
+	return count ? -EIO : 0;
 }
 
 static int cmos_nvram_write(void *priv, unsigned int off, void *val,
@@ -616,7 +618,6 @@
 {
 	struct cmos_rtc	*cmos = priv;
 	unsigned char	*buf = val;
-	int		retval;
 
 	/* NOTE:  on at least PCs and Ataris, the boot firmware uses a
 	 * checksum on part of the NVRAM data.  That's currently ignored
@@ -625,7 +626,7 @@
 	 */
 	off += NVRAM_OFFSET;
 	spin_lock_irq(&rtc_lock);
-	for (retval = 0; count; count--, off++, retval++) {
+	for (; count; count--, off++) {
 		/* don't trash RTC registers */
 		if (off == cmos->day_alrm
 				|| off == cmos->mon_alrm
@@ -640,7 +641,7 @@
 	}
 	spin_unlock_irq(&rtc_lock);
 
-	return retval;
+	return count ? -EIO : 0;
 }
 
 /*----------------------------------------------------------------*/
@@ -850,7 +851,7 @@
 			rtc_cmos_int_handler = cmos_interrupt;
 
 		retval = request_irq(rtc_irq, rtc_cmos_int_handler,
-				IRQF_SHARED, dev_name(&cmos_rtc.rtc->dev),
+				0, dev_name(&cmos_rtc.rtc->dev),
 				cmos_rtc.rtc);
 		if (retval < 0) {
 			dev_dbg(dev, "IRQ %d is already in use\n", rtc_irq);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-ds1307.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-ds1307.c
@@ -265,7 +265,11 @@
 	t->tm_min = bcd2bin(regs[DS1307_REG_MIN] & 0x7f);
 	tmp = regs[DS1307_REG_HOUR] & 0x3f;
 	t->tm_hour = bcd2bin(tmp);
-	t->tm_wday = bcd2bin(regs[DS1307_REG_WDAY] & 0x07) - 1;
+	/* rx8130 is bit position, not BCD */
+	if (ds1307->type == rx_8130)
+		t->tm_wday = fls(regs[DS1307_REG_WDAY] & 0x7f);
+	else
+		t->tm_wday = bcd2bin(regs[DS1307_REG_WDAY] & 0x07) - 1;
 	t->tm_mday = bcd2bin(regs[DS1307_REG_MDAY] & 0x3f);
 	tmp = regs[DS1307_REG_MONTH] & 0x1f;
 	t->tm_mon = bcd2bin(tmp) - 1;
@@ -312,7 +316,11 @@
 	regs[DS1307_REG_SECS] = bin2bcd(t->tm_sec);
 	regs[DS1307_REG_MIN] = bin2bcd(t->tm_min);
 	regs[DS1307_REG_HOUR] = bin2bcd(t->tm_hour);
-	regs[DS1307_REG_WDAY] = bin2bcd(t->tm_wday + 1);
+	/* rx8130 is bit position, not BCD */
+	if (ds1307->type == rx_8130)
+		regs[DS1307_REG_WDAY] = 1 << t->tm_wday;
+	else
+		regs[DS1307_REG_WDAY] = bin2bcd(t->tm_wday + 1);
 	regs[DS1307_REG_MDAY] = bin2bcd(t->tm_mday);
 	regs[DS1307_REG_MONTH] = bin2bcd(t->tm_mon + 1);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-ds1374.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-ds1374.c
@@ -620,6 +620,10 @@
 	if (!ds1374)
 		return -ENOMEM;
 
+	ds1374->rtc = devm_rtc_allocate_device(&client->dev);
+	if (IS_ERR(ds1374->rtc))
+		return PTR_ERR(ds1374->rtc);
+
 	ds1374->client = client;
 	i2c_set_clientdata(client, ds1374);
 
@@ -641,12 +645,11 @@
 		device_set_wakeup_capable(&client->dev, 1);
 	}
 
-	ds1374->rtc = devm_rtc_device_register(&client->dev, client->name,
-						&ds1374_rtc_ops, THIS_MODULE);
-	if (IS_ERR(ds1374->rtc)) {
-		dev_err(&client->dev, "unable to register the class device\n");
-		return PTR_ERR(ds1374->rtc);
-	}
+	ds1374->rtc->ops = &ds1374_rtc_ops;
+
+	ret = rtc_register_device(ds1374->rtc);
+	if (ret)
+		return ret;
 
 #ifdef CONFIG_RTC_DRV_DS1374_WDT
 	save_client = client;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-ds1685.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-ds1685.c
@@ -1437,7 +1437,7 @@
 		unreachable();
 	}
 }
-EXPORT_SYMBOL(ds1685_rtc_poweroff);
+EXPORT_SYMBOL_GPL(ds1685_rtc_poweroff);
 /* ----------------------------------------------------------------------- */
 
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-ep93xx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-ep93xx.c
@@ -33,7 +33,7 @@
 static int ep93xx_rtc_get_swcomp(struct device *dev, unsigned short *preload,
 				 unsigned short *delete)
 {
-	struct ep93xx_rtc *ep93xx_rtc = dev_get_platdata(dev);
+	struct ep93xx_rtc *ep93xx_rtc = dev_get_drvdata(dev);
 	unsigned long comp;
 
 	comp = readl(ep93xx_rtc->mmio_base + EP93XX_RTC_SWCOMP);
@@ -51,7 +51,7 @@
 
 static int ep93xx_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
-	struct ep93xx_rtc *ep93xx_rtc = dev_get_platdata(dev);
+	struct ep93xx_rtc *ep93xx_rtc = dev_get_drvdata(dev);
 	unsigned long time;
 
 	time = readl(ep93xx_rtc->mmio_base + EP93XX_RTC_DATA);
@@ -62,7 +62,7 @@
 
 static int ep93xx_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
-	struct ep93xx_rtc *ep93xx_rtc = dev_get_platdata(dev);
+	struct ep93xx_rtc *ep93xx_rtc = dev_get_drvdata(dev);
 	unsigned long secs = rtc_tm_to_time64(tm);
 
 	writel(secs + 1, ep93xx_rtc->mmio_base + EP93XX_RTC_LOAD);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-fsl-ftm-alarm.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-fsl-ftm-alarm.c
@@ -316,6 +316,7 @@
 	{ .compatible = "fsl,lx2160a-ftm-alarm", },
 	{ },
 };
+MODULE_DEVICE_TABLE(of, ftm_rtc_match);
 
 static struct platform_driver ftm_rtc_driver = {
 	.probe		= ftm_rtc_probe,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-goldfish.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-goldfish.c
@@ -73,6 +73,7 @@
 		rtc_alarm64 = rtc_tm_to_time64(&alrm->time) * NSEC_PER_SEC;
 		writel((rtc_alarm64 >> 32), base + TIMER_ALARM_HIGH);
 		writel(rtc_alarm64, base + TIMER_ALARM_LOW);
+		writel(1, base + TIMER_IRQ_ENABLED);
 	} else {
 		/*
 		 * if this function was called with enabled=0
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-hym8563.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-hym8563.c
@@ -97,7 +97,7 @@
 
 	if (!hym8563->valid) {
 		dev_warn(&client->dev, "no valid clock/calendar values available\n");
-		return -EPERM;
+		return -EINVAL;
 	}
 
 	ret = i2c_smbus_read_i2c_block_data(client, HYM8563_SEC, 7, buf);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-isl1208.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-isl1208.c
@@ -743,14 +743,13 @@
 {
 	struct isl1208_state *isl1208 = priv;
 	struct i2c_client *client = to_i2c_client(isl1208->rtc->dev.parent);
-	int ret;
 
 	/* nvmem sanitizes offset/count for us, but count==0 is possible */
 	if (!count)
 		return count;
-	ret = isl1208_i2c_read_regs(client, ISL1208_REG_USR1 + off, buf,
+
+	return isl1208_i2c_read_regs(client, ISL1208_REG_USR1 + off, buf,
 				    count);
-	return ret == 0 ? count : ret;
 }
 
 static int isl1208_nvmem_write(void *priv, unsigned int off, void *buf,
@@ -758,15 +757,13 @@
 {
 	struct isl1208_state *isl1208 = priv;
 	struct i2c_client *client = to_i2c_client(isl1208->rtc->dev.parent);
-	int ret;
 
 	/* nvmem sanitizes off/count for us, but count==0 is possible */
 	if (!count)
 		return count;
-	ret = isl1208_i2c_set_regs(client, ISL1208_REG_USR1 + off, buf,
-				   count);
 
-	return ret == 0 ? count : ret;
+	return isl1208_i2c_set_regs(client, ISL1208_REG_USR1 + off, buf,
+				   count);
 }
 
 static const struct nvmem_config isl1208_nvmem_config = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-max77686.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-max77686.c
@@ -707,8 +707,8 @@
 
 add_rtc_irq:
 	ret = regmap_add_irq_chip(info->rtc_regmap, info->rtc_irq,
-				  IRQF_TRIGGER_FALLING | IRQF_ONESHOT |
-				  IRQF_SHARED, 0, info->drv_data->rtc_irq_chip,
+				  IRQF_ONESHOT | IRQF_SHARED,
+				  0, info->drv_data->rtc_irq_chip,
 				  &info->rtc_irq_data);
 	if (ret < 0) {
 		dev_err(info->dev, "Failed to add RTC irq chip: %d\n", ret);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-mc13xxx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-mc13xxx.c
@@ -308,8 +308,10 @@
 	mc13xxx_unlock(mc13xxx);
 
 	ret = rtc_register_device(priv->rtc);
-	if (ret)
+	if (ret) {
+		mc13xxx_lock(mc13xxx);
 		goto err_irq_request;
+	}
 
 	return 0;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-mc146818-lib.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-mc146818-lib.c
@@ -83,7 +83,7 @@
 	time->tm_year += real_year - 72;
 #endif
 
-	if (century > 20)
+	if (century > 19)
 		time->tm_year += (century - 19) * 100;
 
 	/*
@@ -99,6 +99,17 @@
 }
 EXPORT_SYMBOL_GPL(mc146818_get_time);
 
+/* AMD systems don't allow access to AltCentury with DV1 */
+static bool apply_amd_register_a_behavior(void)
+{
+#ifdef CONFIG_X86
+	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD ||
+	    boot_cpu_data.x86_vendor == X86_VENDOR_HYGON)
+		return true;
+#endif
+	return false;
+}
+
 /* Set the current date and time in the real time clock. */
 int mc146818_set_time(struct rtc_time *time)
 {
@@ -172,7 +183,10 @@
 	save_control = CMOS_READ(RTC_CONTROL);
 	CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
 	save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
-	CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+	if (apply_amd_register_a_behavior())
+		CMOS_WRITE((save_freq_select & ~RTC_AMD_BANK_SELECT), RTC_FREQ_SELECT);
+	else
+		CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
 
 #ifdef CONFIG_MACH_DECSTATION
 	CMOS_WRITE(real_yrs, RTC_DEC_YEAR);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-meson-vrtc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-meson-vrtc.c
@@ -23,7 +23,7 @@
 	struct timespec64 time;
 
 	dev_dbg(dev, "%s\n", __func__);
-	ktime_get_raw_ts64(&time);
+	ktime_get_real_ts64(&time);
 	rtc_time64_to_tm(time.tv_sec, tm);
 
 	return 0;
@@ -101,7 +101,7 @@
 		long alarm_secs;
 		struct timespec64 time;
 
-		ktime_get_raw_ts64(&time);
+		ktime_get_real_ts64(&time);
 		local_time = time.tv_sec;
 
 		dev_dbg(dev, "alarm_time = %lus, local_time=%lus\n",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-msm6242.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-msm6242.c
@@ -133,7 +133,8 @@
 		      msm6242_read(priv, MSM6242_SECOND1);
 	tm->tm_min  = msm6242_read(priv, MSM6242_MINUTE10) * 10 +
 		      msm6242_read(priv, MSM6242_MINUTE1);
-	tm->tm_hour = (msm6242_read(priv, MSM6242_HOUR10 & 3)) * 10 +
+	tm->tm_hour = (msm6242_read(priv, MSM6242_HOUR10) &
+		       MSM6242_HOUR10_HR_MASK) * 10 +
 		      msm6242_read(priv, MSM6242_HOUR1);
 	tm->tm_mday = msm6242_read(priv, MSM6242_DAY10) * 10 +
 		      msm6242_read(priv, MSM6242_DAY1);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-mt6397.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-mt6397.c
@@ -47,6 +47,14 @@
 
 #define RTC_AL_SEC		0x0018
 
+#define RTC_AL_SEC_MASK		0x003f
+#define RTC_AL_MIN_MASK		0x003f
+#define RTC_AL_HOU_MASK		0x001f
+#define RTC_AL_DOM_MASK		0x001f
+#define RTC_AL_DOW_MASK		0x0007
+#define RTC_AL_MTH_MASK		0x000f
+#define RTC_AL_YEA_MASK		0x007f
+
 #define RTC_PDN2		0x002e
 #define RTC_PDN2_PWRON_ALARM	BIT(4)
 
@@ -103,7 +111,7 @@
 		irqen = irqsta & ~RTC_IRQ_EN_AL;
 		mutex_lock(&rtc->lock);
 		if (regmap_write(rtc->regmap, rtc->addr_base + RTC_IRQ_EN,
-				 irqen) < 0)
+				 irqen) == 0)
 			mtk_rtc_write_trigger(rtc);
 		mutex_unlock(&rtc->lock);
 
@@ -225,12 +233,12 @@
 	alm->pending = !!(pdn2 & RTC_PDN2_PWRON_ALARM);
 	mutex_unlock(&rtc->lock);
 
-	tm->tm_sec = data[RTC_OFFSET_SEC];
-	tm->tm_min = data[RTC_OFFSET_MIN];
-	tm->tm_hour = data[RTC_OFFSET_HOUR];
-	tm->tm_mday = data[RTC_OFFSET_DOM];
-	tm->tm_mon = data[RTC_OFFSET_MTH];
-	tm->tm_year = data[RTC_OFFSET_YEAR];
+	tm->tm_sec = data[RTC_OFFSET_SEC] & RTC_AL_SEC_MASK;
+	tm->tm_min = data[RTC_OFFSET_MIN] & RTC_AL_MIN_MASK;
+	tm->tm_hour = data[RTC_OFFSET_HOUR] & RTC_AL_HOU_MASK;
+	tm->tm_mday = data[RTC_OFFSET_DOM] & RTC_AL_DOM_MASK;
+	tm->tm_mon = data[RTC_OFFSET_MTH] & RTC_AL_MTH_MASK;
+	tm->tm_year = data[RTC_OFFSET_YEAR] & RTC_AL_YEA_MASK;
 
 	tm->tm_year += RTC_MIN_YEAR_OFFSET;
 	tm->tm_mon--;
@@ -251,14 +259,25 @@
 	tm->tm_year -= RTC_MIN_YEAR_OFFSET;
 	tm->tm_mon++;
 
-	data[RTC_OFFSET_SEC] = tm->tm_sec;
-	data[RTC_OFFSET_MIN] = tm->tm_min;
-	data[RTC_OFFSET_HOUR] = tm->tm_hour;
-	data[RTC_OFFSET_DOM] = tm->tm_mday;
-	data[RTC_OFFSET_MTH] = tm->tm_mon;
-	data[RTC_OFFSET_YEAR] = tm->tm_year;
-
 	mutex_lock(&rtc->lock);
+	ret = regmap_bulk_read(rtc->regmap, rtc->addr_base + RTC_AL_SEC,
+			       data, RTC_OFFSET_COUNT);
+	if (ret < 0)
+		goto exit;
+
+	data[RTC_OFFSET_SEC] = ((data[RTC_OFFSET_SEC] & ~(RTC_AL_SEC_MASK)) |
+				(tm->tm_sec & RTC_AL_SEC_MASK));
+	data[RTC_OFFSET_MIN] = ((data[RTC_OFFSET_MIN] & ~(RTC_AL_MIN_MASK)) |
+				(tm->tm_min & RTC_AL_MIN_MASK));
+	data[RTC_OFFSET_HOUR] = ((data[RTC_OFFSET_HOUR] & ~(RTC_AL_HOU_MASK)) |
+				(tm->tm_hour & RTC_AL_HOU_MASK));
+	data[RTC_OFFSET_DOM] = ((data[RTC_OFFSET_DOM] & ~(RTC_AL_DOM_MASK)) |
+				(tm->tm_mday & RTC_AL_DOM_MASK));
+	data[RTC_OFFSET_MTH] = ((data[RTC_OFFSET_MTH] & ~(RTC_AL_MTH_MASK)) |
+				(tm->tm_mon & RTC_AL_MTH_MASK));
+	data[RTC_OFFSET_YEAR] = ((data[RTC_OFFSET_YEAR] & ~(RTC_AL_YEA_MASK)) |
+				(tm->tm_year & RTC_AL_YEA_MASK));
+
 	if (alm->enabled) {
 		ret = regmap_bulk_write(rtc->regmap,
 					rtc->addr_base + RTC_AL_SEC,
@@ -312,6 +331,8 @@
 		return -ENOMEM;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -EINVAL;
 	rtc->addr_base = res->start;
 
 	rtc->irq = platform_get_irq(pdev, 0);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-mxc_v2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-mxc_v2.c
@@ -337,8 +337,10 @@
 	}
 
 	pdata->rtc = devm_rtc_allocate_device(&pdev->dev);
-	if (IS_ERR(pdata->rtc))
+	if (IS_ERR(pdata->rtc)) {
+		clk_disable_unprepare(pdata->clk);
 		return PTR_ERR(pdata->rtc);
+	}
 
 	pdata->rtc->ops = &mxc_rtc_ops;
 	pdata->rtc->range_max = U32_MAX;
@@ -373,6 +375,7 @@
 	{ .compatible = "fsl,imx53-rtc", },
 	{}
 };
+MODULE_DEVICE_TABLE(of, mxc_ids);
 
 static struct platform_driver mxc_rtc_driver = {
 	.driver = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-omap.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-omap.c
@@ -26,6 +26,7 @@
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/rtc.h>
+#include <linux/rtc/rtc-omap.h>
 
 /*
  * The OMAP RTC is a year/month/day/hours/minutes/seconds BCD clock
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-pcf2127.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-pcf2127.c
@@ -230,10 +230,8 @@
 	if (ret)
 		return ret;
 
-	ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_RAM_RD_CMD,
-			       val, bytes);
-
-	return ret ?: bytes;
+	return regmap_bulk_read(pcf2127->regmap, PCF2127_REG_RAM_RD_CMD,
+				val, bytes);
 }
 
 static int pcf2127_nvmem_write(void *priv, unsigned int offset,
@@ -248,10 +246,8 @@
 	if (ret)
 		return ret;
 
-	ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_WRT_CMD,
-				val, bytes);
-
-	return ret ?: bytes;
+	return regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_WRT_CMD,
+				 val, bytes);
 }
 
 /* watchdog driver */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-pcf85063.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-pcf85063.c
@@ -159,10 +159,10 @@
 	if (ret)
 		return ret;
 
-	alrm->time.tm_sec = bcd2bin(buf[0]);
-	alrm->time.tm_min = bcd2bin(buf[1]);
-	alrm->time.tm_hour = bcd2bin(buf[2]);
-	alrm->time.tm_mday = bcd2bin(buf[3]);
+	alrm->time.tm_sec = bcd2bin(buf[0] & 0x7f);
+	alrm->time.tm_min = bcd2bin(buf[1] & 0x7f);
+	alrm->time.tm_hour = bcd2bin(buf[2] & 0x3f);
+	alrm->time.tm_mday = bcd2bin(buf[3] & 0x3f);
 
 	ret = regmap_read(pcf85063->regmap, PCF85063_REG_CTRL2, &val);
 	if (ret)
@@ -332,7 +332,16 @@
 static int pcf85063_nvmem_read(void *priv, unsigned int offset,
 			       void *val, size_t bytes)
 {
-	return regmap_read(priv, PCF85063_REG_RAM, val);
+	unsigned int tmp;
+	int ret;
+
+	ret = regmap_read(priv, PCF85063_REG_RAM, &tmp);
+	if (ret < 0)
+		return ret;
+
+	*(u8 *)val = tmp;
+
+	return 0;
 }
 
 static int pcf85063_nvmem_write(void *priv, unsigned int offset,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-pcf85363.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-pcf85363.c
@@ -407,7 +407,7 @@
 	if (client->irq > 0) {
 		regmap_write(pcf85363->regmap, CTRL_FLAGS, 0);
 		regmap_update_bits(pcf85363->regmap, CTRL_PIN_IO,
-				   PIN_IO_INTA_OUT, PIN_IO_INTAPM);
+				   PIN_IO_INTAPM, PIN_IO_INTA_OUT);
 		ret = devm_request_threaded_irq(&client->dev, client->irq,
 						NULL, pcf85363_rtc_handle_irq,
 						IRQF_TRIGGER_LOW | IRQF_ONESHOT,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-pic32.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-pic32.c
@@ -326,16 +326,16 @@
 
 	spin_lock_init(&pdata->alarm_lock);
 
+	pdata->rtc = devm_rtc_allocate_device(&pdev->dev);
+	if (IS_ERR(pdata->rtc))
+		return PTR_ERR(pdata->rtc);
+
 	clk_prepare_enable(pdata->clk);
 
 	pic32_rtc_enable(pdata, 1);
 
 	device_init_wakeup(&pdev->dev, 1);
 
-	pdata->rtc = devm_rtc_allocate_device(&pdev->dev);
-	if (IS_ERR(pdata->rtc))
-		return PTR_ERR(pdata->rtc);
-
 	pdata->rtc->ops = &pic32_rtcops;
 	pdata->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
 	pdata->rtc->range_max = RTC_TIMESTAMP_END_2099;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-pl031.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-pl031.c
@@ -379,8 +379,10 @@
 
 	device_init_wakeup(&adev->dev, true);
 	ldata->rtc = devm_rtc_allocate_device(&adev->dev);
-	if (IS_ERR(ldata->rtc))
-		return PTR_ERR(ldata->rtc);
+	if (IS_ERR(ldata->rtc)) {
+		ret = PTR_ERR(ldata->rtc);
+		goto out;
+	}
 
 	ldata->rtc->ops = ops;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-pm8xxx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-pm8xxx.c
@@ -219,7 +219,6 @@
 {
 	int rc, i;
 	u8 value[NUM_8_BIT_RTC_REGS];
-	unsigned int ctrl_reg;
 	unsigned long secs, irq_flags;
 	struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
 	const struct pm8xxx_rtc_regs *regs = rtc_dd->regs;
@@ -231,6 +230,11 @@
 		secs >>= 8;
 	}
 
+	rc = regmap_update_bits(rtc_dd->regmap, regs->alarm_ctrl,
+				regs->alarm_en, 0);
+	if (rc)
+		return rc;
+
 	spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags);
 
 	rc = regmap_bulk_write(rtc_dd->regmap, regs->alarm_rw, value,
@@ -240,19 +244,11 @@
 		goto rtc_rw_fail;
 	}
 
-	rc = regmap_read(rtc_dd->regmap, regs->alarm_ctrl, &ctrl_reg);
-	if (rc)
-		goto rtc_rw_fail;
-
-	if (alarm->enabled)
-		ctrl_reg |= regs->alarm_en;
-	else
-		ctrl_reg &= ~regs->alarm_en;
-
-	rc = regmap_write(rtc_dd->regmap, regs->alarm_ctrl, ctrl_reg);
-	if (rc) {
-		dev_err(dev, "Write to RTC alarm control register failed\n");
-		goto rtc_rw_fail;
+	if (alarm->enabled) {
+		rc = regmap_update_bits(rtc_dd->regmap, regs->alarm_ctrl,
+					regs->alarm_en, regs->alarm_en);
+		if (rc)
+			goto rtc_rw_fail;
 	}
 
 	dev_dbg(dev, "Alarm Set for h:m:s=%ptRt, y-m-d=%ptRdr\n",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-pxa.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-pxa.c
@@ -330,6 +330,10 @@
 	if (sa1100_rtc->irq_alarm < 0)
 		return -ENXIO;
 
+	sa1100_rtc->rtc = devm_rtc_allocate_device(&pdev->dev);
+	if (IS_ERR(sa1100_rtc->rtc))
+		return PTR_ERR(sa1100_rtc->rtc);
+
 	pxa_rtc->base = devm_ioremap(dev, pxa_rtc->ress->start,
 				resource_size(pxa_rtc->ress));
 	if (!pxa_rtc->base) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-rv3028.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-rv3028.c
@@ -625,6 +625,8 @@
 		return -ENOMEM;
 
 	rv3028->regmap = devm_regmap_init_i2c(client, &regmap_config);
+	if (IS_ERR(rv3028->regmap))
+		return PTR_ERR(rv3028->regmap);
 
 	i2c_set_clientdata(client, rv3028);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-rx8010.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-rx8010.c
@@ -424,16 +424,26 @@
 	}
 }
 
-static struct rtc_class_ops rx8010_rtc_ops = {
+static const struct rtc_class_ops rx8010_rtc_ops_default = {
 	.read_time = rx8010_get_time,
 	.set_time = rx8010_set_time,
 	.ioctl = rx8010_ioctl,
 };
 
+static const struct rtc_class_ops rx8010_rtc_ops_alarm = {
+	.read_time = rx8010_get_time,
+	.set_time = rx8010_set_time,
+	.ioctl = rx8010_ioctl,
+	.read_alarm = rx8010_read_alarm,
+	.set_alarm = rx8010_set_alarm,
+	.alarm_irq_enable = rx8010_alarm_irq_enable,
+};
+
 static int rx8010_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
 	struct i2c_adapter *adapter = client->adapter;
+	const struct rtc_class_ops *rtc_ops;
 	struct rx8010_data *rx8010;
 	int err = 0;
 
@@ -464,16 +474,16 @@
 
 		if (err) {
 			dev_err(&client->dev, "unable to request IRQ\n");
-			client->irq = 0;
-		} else {
-			rx8010_rtc_ops.read_alarm = rx8010_read_alarm;
-			rx8010_rtc_ops.set_alarm = rx8010_set_alarm;
-			rx8010_rtc_ops.alarm_irq_enable = rx8010_alarm_irq_enable;
+			return err;
 		}
+
+		rtc_ops = &rx8010_rtc_ops_alarm;
+	} else {
+		rtc_ops = &rx8010_rtc_ops_default;
 	}
 
 	rx8010->rtc = devm_rtc_device_register(&client->dev, client->name,
-		&rx8010_rtc_ops, THIS_MODULE);
+					       rtc_ops, THIS_MODULE);
 
 	if (IS_ERR(rx8010->rtc)) {
 		dev_err(&client->dev, "unable to register the class device\n");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-sa1100.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-sa1100.c
@@ -182,7 +182,6 @@
 
 int sa1100_rtc_init(struct platform_device *pdev, struct sa1100_rtc *info)
 {
-	struct rtc_device *rtc;
 	int ret;
 
 	spin_lock_init(&info->lock);
@@ -211,15 +210,14 @@
 		writel_relaxed(0, info->rcnr);
 	}
 
-	rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &sa1100_rtc_ops,
-					THIS_MODULE);
-	if (IS_ERR(rtc)) {
+	info->rtc->ops = &sa1100_rtc_ops;
+	info->rtc->max_user_freq = RTC_FREQ;
+
+	ret = rtc_register_device(info->rtc);
+	if (ret) {
 		clk_disable_unprepare(info->clk);
-		return PTR_ERR(rtc);
+		return ret;
 	}
-	info->rtc = rtc;
-
-	rtc->max_user_freq = RTC_FREQ;
 
 	/* Fix for a nasty initialization problem the in SA11xx RTSR register.
 	 * See also the comments in sa1100_rtc_interrupt().
@@ -268,6 +266,10 @@
 	info->irq_1hz = irq_1hz;
 	info->irq_alarm = irq_alarm;
 
+	info->rtc = devm_rtc_allocate_device(&pdev->dev);
+	if (IS_ERR(info->rtc))
+		return PTR_ERR(info->rtc);
+
 	ret = devm_request_irq(&pdev->dev, irq_1hz, sa1100_rtc_interrupt, 0,
 			       "rtc 1Hz", &pdev->dev);
 	if (ret) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-snvs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-snvs.c
@@ -33,6 +33,14 @@
 #define SNVS_LPPGDR_INIT	0x41736166
 #define CNTR_TO_SECS_SH		15
 
+/* The maximum RTC clock cycles that are allowed to pass between two
+ * consecutive clock counter register reads. If the values are corrupted a
+ * bigger difference is expected. The RTC frequency is 32kHz. With 320 cycles
+ * we end at 10ms which should be enough for most cases. If it once takes
+ * longer than expected we do a retry.
+ */
+#define MAX_RTC_READ_DIFF_CYCLES	320
+
 struct snvs_rtc_data {
 	struct rtc_device *rtc;
 	struct regmap *regmap;
@@ -57,6 +65,7 @@
 static u32 rtc_read_lp_counter(struct snvs_rtc_data *data)
 {
 	u64 read1, read2;
+	s64 diff;
 	unsigned int timeout = 100;
 
 	/* As expected, the registers might update between the read of the LSB
@@ -67,7 +76,8 @@
 	do {
 		read2 = read1;
 		read1 = rtc_read_lpsrt(data);
-	} while (read1 != read2 && --timeout);
+		diff = read1 - read2;
+	} while (((diff < 0) || (diff > MAX_RTC_READ_DIFF_CYCLES)) && --timeout);
 	if (!timeout)
 		dev_err(&data->rtc->dev, "Timeout trying to get valid LPSRT Counter read\n");
 
@@ -79,13 +89,15 @@
 static int rtc_read_lp_counter_lsb(struct snvs_rtc_data *data, u32 *lsb)
 {
 	u32 count1, count2;
+	s32 diff;
 	unsigned int timeout = 100;
 
 	regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1);
 	do {
 		count2 = count1;
 		regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1);
-	} while (count1 != count2 && --timeout);
+		diff = count1 - count2;
+	} while (((diff < 0) || (diff > MAX_RTC_READ_DIFF_CYCLES)) && --timeout);
 	if (!timeout) {
 		dev_err(&data->rtc->dev, "Timeout trying to get valid LPSRT Counter read\n");
 		return -ETIMEDOUT;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-st-lpc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-st-lpc.c
@@ -221,17 +221,16 @@
 		return -EINVAL;
 	}
 
-	ret = devm_request_irq(&pdev->dev, rtc->irq, st_rtc_handler, 0,
-			       pdev->name, rtc);
+	ret = devm_request_irq(&pdev->dev, rtc->irq, st_rtc_handler,
+			       IRQF_NO_AUTOEN, pdev->name, rtc);
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to request irq %i\n", rtc->irq);
 		return ret;
 	}
 
 	enable_irq_wake(rtc->irq);
-	disable_irq(rtc->irq);
 
-	rtc->clk = clk_get(&pdev->dev, NULL);
+	rtc->clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(rtc->clk)) {
 		dev_err(&pdev->dev, "Unable to request clock\n");
 		return PTR_ERR(rtc->clk);
@@ -241,6 +240,7 @@
 
 	rtc->clkrate = clk_get_rate(rtc->clk);
 	if (!rtc->clkrate) {
+		clk_disable_unprepare(rtc->clk);
 		dev_err(&pdev->dev, "Unable to fetch clock rate\n");
 		return -EINVAL;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-stm32.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-stm32.c
@@ -756,7 +756,7 @@
 
 	ret = clk_prepare_enable(rtc->rtc_ck);
 	if (ret)
-		goto err;
+		goto err_no_rtc_ck;
 
 	if (rtc->data->need_dbp)
 		regmap_update_bits(rtc->dbp, rtc->dbp_reg,
@@ -832,10 +832,12 @@
 	}
 
 	return 0;
+
 err:
+	clk_disable_unprepare(rtc->rtc_ck);
+err_no_rtc_ck:
 	if (rtc->data->has_pclk)
 		clk_disable_unprepare(rtc->pclk);
-	clk_disable_unprepare(rtc->rtc_ck);
 
 	if (rtc->data->need_dbp)
 		regmap_update_bits(rtc->dbp, rtc->dbp_reg, rtc->dbp_mask, 0);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-sun6i.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-sun6i.c
@@ -129,7 +129,6 @@
 	unsigned int fixed_prescaler : 16;
 	unsigned int has_prescaler : 1;
 	unsigned int has_out_clk : 1;
-	unsigned int export_iosc : 1;
 	unsigned int has_losc_en : 1;
 	unsigned int has_auto_swt : 1;
 };
@@ -251,23 +250,19 @@
 		writel(reg, rtc->base + SUN6I_LOSC_CTRL);
 	}
 
-	/* Switch to the external, more precise, oscillator */
-	reg |= SUN6I_LOSC_CTRL_EXT_OSC;
-	if (rtc->data->has_losc_en)
-		reg |= SUN6I_LOSC_CTRL_EXT_LOSC_EN;
+	/* Switch to the external, more precise, oscillator, if present */
+	if (of_get_property(node, "clocks", NULL)) {
+		reg |= SUN6I_LOSC_CTRL_EXT_OSC;
+		if (rtc->data->has_losc_en)
+			reg |= SUN6I_LOSC_CTRL_EXT_LOSC_EN;
+	}
 	writel(reg, rtc->base + SUN6I_LOSC_CTRL);
 
 	/* Yes, I know, this is ugly. */
 	sun6i_rtc = rtc;
 
-	/* Deal with old DTs */
-	if (!of_get_property(node, "clocks", NULL))
-		goto err;
-
-	/* Only read IOSC name from device tree if it is exported */
-	if (rtc->data->export_iosc)
-		of_property_read_string_index(node, "clock-output-names", 2,
-					      &iosc_name);
+	of_property_read_string_index(node, "clock-output-names", 2,
+				      &iosc_name);
 
 	rtc->int_osc = clk_hw_register_fixed_rate_with_accuracy(NULL,
 								iosc_name,
@@ -276,15 +271,17 @@
 								300000000);
 	if (IS_ERR(rtc->int_osc)) {
 		pr_crit("Couldn't register the internal oscillator\n");
-		return;
+		goto err;
 	}
 
 	parents[0] = clk_hw_get_name(rtc->int_osc);
+	/* If there is no external oscillator, this will be NULL and ... */
 	parents[1] = of_clk_get_parent_name(node, 0);
 
 	rtc->hw.init = &init;
 
 	init.parent_names = parents;
+	/* ... number of clock parents will be 1. */
 	init.num_parents = of_clk_get_parent_count(node) + 1;
 	of_property_read_string_index(node, "clock-output-names", 0,
 				      &init.name);
@@ -292,7 +289,7 @@
 	rtc->losc = clk_register(NULL, &rtc->hw);
 	if (IS_ERR(rtc->losc)) {
 		pr_crit("Couldn't register the LOSC clock\n");
-		return;
+		goto err_register;
 	}
 
 	of_property_read_string_index(node, "clock-output-names", 1,
@@ -303,19 +300,18 @@
 					  &rtc->lock);
 	if (IS_ERR(rtc->ext_losc)) {
 		pr_crit("Couldn't register the LOSC external gate\n");
-		return;
+		goto err_register;
 	}
 
-	clk_data->num = 2;
+	clk_data->num = 3;
 	clk_data->hws[0] = &rtc->hw;
 	clk_data->hws[1] = __clk_get_hw(rtc->ext_losc);
-	if (rtc->data->export_iosc) {
-		clk_data->hws[2] = rtc->int_osc;
-		clk_data->num = 3;
-	}
+	clk_data->hws[2] = rtc->int_osc;
 	of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
 	return;
 
+err_register:
+	clk_hw_unregister_fixed_rate(rtc->int_osc);
 err:
 	kfree(clk_data);
 }
@@ -350,7 +346,6 @@
 	.fixed_prescaler = 32,
 	.has_prescaler = 1,
 	.has_out_clk = 1,
-	.export_iosc = 1,
 };
 
 static void __init sun8i_h3_rtc_clk_init(struct device_node *node)
@@ -368,7 +363,6 @@
 	.fixed_prescaler = 32,
 	.has_prescaler = 1,
 	.has_out_clk = 1,
-	.export_iosc = 1,
 	.has_losc_en = 1,
 	.has_auto_swt = 1,
 };
@@ -380,6 +374,22 @@
 CLK_OF_DECLARE_DRIVER(sun50i_h6_rtc_clk, "allwinner,sun50i-h6-rtc",
 		      sun50i_h6_rtc_clk_init);
 
+/*
+ * The R40 user manual is self-conflicting on whether the prescaler is
+ * fixed or configurable. The clock diagram shows it as fixed, but there
+ * is also a configurable divider in the RTC block.
+ */
+static const struct sun6i_rtc_clk_data sun8i_r40_rtc_data = {
+	.rc_osc_rate = 16000000,
+	.fixed_prescaler = 512,
+};
+static void __init sun8i_r40_rtc_clk_init(struct device_node *node)
+{
+	sun6i_rtc_clk_init(node, &sun8i_r40_rtc_data);
+}
+CLK_OF_DECLARE_DRIVER(sun8i_r40_rtc_clk, "allwinner,sun8i-r40-rtc",
+		      sun8i_r40_rtc_clk_init);
+
 static const struct sun6i_rtc_clk_data sun8i_v3_rtc_data = {
 	.rc_osc_rate = 32000,
 	.has_out_clk = 1,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-tps65910.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-tps65910.c
@@ -460,6 +460,6 @@
 };
 
 module_platform_driver(tps65910_rtc_driver);
-MODULE_ALIAS("platform:rtc-tps65910");
+MODULE_ALIAS("platform:tps65910-rtc");
 MODULE_AUTHOR("Venu Byravarasu <vbyravarasu@nvidia.com>");
 MODULE_LICENSE("GPL");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-wm8350.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-wm8350.c
@@ -432,14 +432,21 @@
 		return ret;
 	}
 
-	wm8350_register_irq(wm8350, WM8350_IRQ_RTC_SEC,
+	ret = wm8350_register_irq(wm8350, WM8350_IRQ_RTC_SEC,
 			    wm8350_rtc_update_handler, 0,
 			    "RTC Seconds", wm8350);
+	if (ret)
+		return ret;
+
 	wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC);
 
-	wm8350_register_irq(wm8350, WM8350_IRQ_RTC_ALM,
+	ret = wm8350_register_irq(wm8350, WM8350_IRQ_RTC_ALM,
 			    wm8350_rtc_alarm_handler, 0,
 			    "RTC Alarm", wm8350);
+	if (ret) {
+		wm8350_free_irq(wm8350, WM8350_IRQ_RTC_SEC, wm8350);
+		return ret;
+	}
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/rtc/rtc-zynqmp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/rtc/rtc-zynqmp.c
@@ -38,13 +38,21 @@
 
 #define RTC_CALIB_DEF		0x198233
 #define RTC_CALIB_MASK		0x1FFFFF
+#define RTC_ALRM_MASK          BIT(1)
+#define RTC_MSEC               1000
+#define RTC_FR_MASK		0xF0000
+#define RTC_SEC_MAX_VAL		0xFFFFFFFF
+#define RTC_FR_MAX_TICKS	16
+#define RTC_OFFSET_MAX		150000
+#define RTC_OFFSET_MIN		-150000
+#define RTC_PPB			1000000000LL
 
 struct xlnx_rtc_dev {
 	struct rtc_device	*rtc;
 	void __iomem		*reg_base;
 	int			alarm_irq;
 	int			sec_irq;
-	int			calibval;
+	unsigned int		calibval;
 };
 
 static int xlnx_rtc_set_time(struct device *dev, struct rtc_time *tm)
@@ -94,7 +102,7 @@
 		 * RTC has updated the CURRENT_TIME with the time written into
 		 * SET_TIME_WRITE register.
 		 */
-		rtc_time64_to_tm(readl(xrtcdev->reg_base + RTC_CUR_TM), tm);
+		read_time = readl(xrtcdev->reg_base + RTC_CUR_TM);
 	} else {
 		/*
 		 * Time written in SET_TIME_WRITE has not yet updated into
@@ -104,8 +112,8 @@
 		 * reading.
 		 */
 		read_time = readl(xrtcdev->reg_base + RTC_SET_TM_RD) - 1;
-		rtc_time64_to_tm(read_time, tm);
 	}
+	rtc_time64_to_tm(read_time, tm);
 
 	return 0;
 }
@@ -124,11 +132,28 @@
 {
 	struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);
 
-	if (enabled)
+	unsigned int status;
+	ulong timeout;
+
+	timeout = jiffies + msecs_to_jiffies(RTC_MSEC);
+
+	if (enabled) {
+		while (1) {
+			status = readl(xrtcdev->reg_base + RTC_INT_STS);
+			if (!((status & RTC_ALRM_MASK) == RTC_ALRM_MASK))
+				break;
+
+			if (time_after_eq(jiffies, timeout)) {
+				dev_err(dev, "Time out occur, while clearing alarm status bit\n");
+				return -ETIMEDOUT;
+			}
+			writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_STS);
+		}
+
 		writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_EN);
-	else
+	} else {
 		writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_DIS);
-
+	}
 	return 0;
 }
 
@@ -165,12 +190,84 @@
 	writel(xrtcdev->calibval, (xrtcdev->reg_base + RTC_CALIB_WR));
 }
 
+static int xlnx_rtc_read_offset(struct device *dev, long *offset)
+{
+	struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);
+	long offset_val;
+	unsigned int reg;
+	unsigned int tick_mult = RTC_PPB / xrtcdev->calibval;
+
+	reg = readl(xrtcdev->reg_base + RTC_CALIB_RD);
+
+	/* Offset with seconds ticks */
+	offset_val = reg & RTC_TICK_MASK;
+	offset_val = offset_val - xrtcdev->calibval;
+	offset_val = offset_val * tick_mult;
+
+	/* Offset with fractional ticks */
+	if (reg & RTC_FR_EN)
+		offset_val += ((reg & RTC_FR_MASK) >> RTC_FR_DATSHIFT)
+			* (tick_mult / RTC_FR_MAX_TICKS);
+	*offset = offset_val;
+
+	return 0;
+}
+
+static int xlnx_rtc_set_offset(struct device *dev, long offset)
+{
+	struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);
+	short int  max_tick;
+	unsigned char fract_tick = 0;
+	unsigned int calibval;
+	int fract_offset;
+	unsigned int tick_mult = RTC_PPB / xrtcdev->calibval;
+
+	/* Make sure offset value is within supported range */
+	if (offset < RTC_OFFSET_MIN || offset > RTC_OFFSET_MAX)
+		return -ERANGE;
+
+	/* Number ticks for given offset */
+	max_tick = div_s64_rem(offset, tick_mult, &fract_offset);
+
+	/* Number fractional ticks for given offset */
+	if (fract_offset) {
+		if (fract_offset < 0) {
+			fract_offset = fract_offset + tick_mult;
+			max_tick--;
+		}
+		if (fract_offset > (tick_mult / RTC_FR_MAX_TICKS)) {
+			for (fract_tick = 1; fract_tick < 16; fract_tick++) {
+				if (fract_offset <=
+				    (fract_tick *
+				     (tick_mult / RTC_FR_MAX_TICKS)))
+					break;
+			}
+		}
+	}
+
+	/* Zynqmp RTC uses second and fractional tick
+	 * counters for compensation
+	 */
+	calibval = max_tick + xrtcdev->calibval;
+
+	if (fract_tick)
+		calibval |= RTC_FR_EN;
+
+	calibval |= (fract_tick << RTC_FR_DATSHIFT);
+
+	writel(calibval, (xrtcdev->reg_base + RTC_CALIB_WR));
+
+	return 0;
+}
+
 static const struct rtc_class_ops xlnx_rtc_ops = {
 	.set_time	  = xlnx_rtc_set_time,
 	.read_time	  = xlnx_rtc_read_time,
 	.read_alarm	  = xlnx_rtc_read_alarm,
 	.set_alarm	  = xlnx_rtc_set_alarm,
 	.alarm_irq_enable = xlnx_rtc_alarm_irq_enable,
+	.read_offset	  = xlnx_rtc_read_offset,
+	.set_offset	  = xlnx_rtc_set_offset,
 };
 
 static irqreturn_t xlnx_rtc_interrupt(int irq, void *id)
@@ -183,8 +280,8 @@
 	if (!(status & (RTC_INT_SEC | RTC_INT_ALRM)))
 		return IRQ_NONE;
 
-	/* Clear RTC_INT_ALRM interrupt only */
-	writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_STS);
+	/* Disable RTC_INT_ALRM interrupt only */
+	writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_DIS);
 
 	if (status & RTC_INT_ALRM)
 		rtc_update_irq(xrtcdev->rtc, 1, RTC_IRQF | RTC_AF);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/block/dasd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/block/dasd.c
@@ -178,6 +178,8 @@
 		     (unsigned long) block);
 	INIT_LIST_HEAD(&block->ccw_queue);
 	spin_lock_init(&block->queue_lock);
+	INIT_LIST_HEAD(&block->format_list);
+	spin_lock_init(&block->format_lock);
 	timer_setup(&block->timer, dasd_block_timeout, 0);
 	spin_lock_init(&block->profile.lock);
 
@@ -735,18 +737,20 @@
 	 * we count each request only once.
 	 */
 	device = cqr->startdev;
-	if (device->profile.data) {
-		counter = 1; /* request is not yet queued on the start device */
-		list_for_each(l, &device->ccw_queue)
-			if (++counter >= 31)
-				break;
-	}
+	if (!device->profile.data)
+		return;
+
+	spin_lock(get_ccwdev_lock(device->cdev));
+	counter = 1; /* request is not yet queued on the start device */
+	list_for_each(l, &device->ccw_queue)
+		if (++counter >= 31)
+			break;
+	spin_unlock(get_ccwdev_lock(device->cdev));
+
 	spin_lock(&device->profile.lock);
-	if (device->profile.data) {
-		device->profile.data->dasd_io_nr_req[counter]++;
-		if (rq_data_dir(req) == READ)
-			device->profile.data->dasd_read_nr_req[counter]++;
-	}
+	device->profile.data->dasd_io_nr_req[counter]++;
+	if (rq_data_dir(req) == READ)
+		device->profile.data->dasd_read_nr_req[counter]++;
 	spin_unlock(&device->profile.lock);
 }
 
@@ -1460,6 +1464,13 @@
 		if (!cqr->lpm)
 			cqr->lpm = dasd_path_get_opm(device);
 	}
+	/*
+	 * remember the amount of formatted tracks to prevent double format on
+	 * ESE devices
+	 */
+	if (cqr->block)
+		cqr->trkcount = atomic_read(&cqr->block->trkcount);
+
 	if (cqr->cpmode == 1) {
 		rc = ccw_device_tm_start(device->cdev, cqr->cpaddr,
 					 (long) cqr, cqr->lpm);
@@ -1654,9 +1665,15 @@
 	if (!sense)
 		return 0;
 
-	return !!(sense[1] & SNS1_NO_REC_FOUND) ||
-		!!(sense[1] & SNS1_FILE_PROTECTED) ||
-		scsw_cstat(&irb->scsw) == SCHN_STAT_INCORR_LEN;
+	if (sense[1] & SNS1_NO_REC_FOUND)
+		return 1;
+
+	if ((sense[1] & SNS1_INV_TRACK_FORMAT) &&
+	    scsw_is_tm(&irb->scsw) &&
+	    !(sense[2] & SNS2_ENV_DATA_PRESENT))
+		return 1;
+
+	return 0;
 }
 
 static int dasd_ese_oos_cond(u8 *sense)
@@ -1677,7 +1694,8 @@
 	struct dasd_device *device;
 	unsigned long now;
 	int nrf_suppressed = 0;
-	int fp_suppressed = 0;
+	int it_suppressed = 0;
+	struct request *req;
 	u8 *sense = NULL;
 	int expires;
 
@@ -1731,8 +1749,9 @@
 		 */
 		sense = dasd_get_sense(irb);
 		if (sense) {
-			fp_suppressed = (sense[1] & SNS1_FILE_PROTECTED) &&
-				test_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags);
+			it_suppressed =	(sense[1] & SNS1_INV_TRACK_FORMAT) &&
+				!(sense[2] & SNS2_ENV_DATA_PRESENT) &&
+				test_bit(DASD_CQR_SUPPRESS_IT, &cqr->flags);
 			nrf_suppressed = (sense[1] & SNS1_NO_REC_FOUND) &&
 				test_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags);
 
@@ -1747,7 +1766,7 @@
 				return;
 			}
 		}
-		if (!(fp_suppressed || nrf_suppressed))
+		if (!(it_suppressed || nrf_suppressed))
 			device->discipline->dump_sense_dbf(device, irb, "int");
 
 		if (device->features & DASD_FEATURE_ERPLOG)
@@ -1778,21 +1797,32 @@
 	}
 
 	if (dasd_ese_needs_format(cqr->block, irb)) {
-		if (rq_data_dir((struct request *)cqr->callback_data) == READ) {
-			device->discipline->ese_read(cqr);
+		req = dasd_get_callback_data(cqr);
+		if (!req) {
+			cqr->status = DASD_CQR_ERROR;
+			return;
+		}
+		if (rq_data_dir(req) == READ) {
+			device->discipline->ese_read(cqr, irb);
 			cqr->status = DASD_CQR_SUCCESS;
 			cqr->stopclk = now;
 			dasd_device_clear_timer(device);
 			dasd_schedule_device_bh(device);
 			return;
 		}
-		fcqr = device->discipline->ese_format(device, cqr);
+		fcqr = device->discipline->ese_format(device, cqr, irb);
 		if (IS_ERR(fcqr)) {
+			if (PTR_ERR(fcqr) == -EINVAL) {
+				cqr->status = DASD_CQR_ERROR;
+				return;
+			}
 			/*
 			 * If we can't format now, let the request go
 			 * one extra round. Maybe we can format later.
 			 */
 			cqr->status = DASD_CQR_QUEUED;
+			dasd_schedule_device_bh(device);
+			return;
 		} else {
 			fcqr->status = DASD_CQR_QUEUED;
 			cqr->status = DASD_CQR_QUEUED;
@@ -2107,8 +2137,8 @@
 	if (device->stopped &
 	    ~(DASD_STOPPED_DC_WAIT | DASD_UNRESUMED_PM))
 		return;
-	rc = device->discipline->verify_path(device,
-					     dasd_path_get_tbvpm(device));
+	rc = device->discipline->pe_handler(device,
+					    dasd_path_get_tbvpm(device));
 	if (rc)
 		dasd_device_set_timer(device, 50);
 	else
@@ -2490,14 +2520,17 @@
 	rc = 0;
 	list_for_each_entry_safe(cqr, n, ccw_queue, blocklist) {
 		/*
-		 * In some cases the 'File Protected' or 'Incorrect Length'
-		 * error might be expected and error recovery would be
-		 * unnecessary in these cases.	Check if the according suppress
-		 * bit is set.
+		 * In some cases certain errors might be expected and
+		 * error recovery would be unnecessary in these cases.
+		 * Check if the according suppress bit is set.
 		 */
 		sense = dasd_get_sense(&cqr->irb);
-		if (sense && sense[1] & SNS1_FILE_PROTECTED &&
-		    test_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags))
+		if (sense && (sense[1] & SNS1_INV_TRACK_FORMAT) &&
+		    !(sense[2] & SNS2_ENV_DATA_PRESENT) &&
+		    test_bit(DASD_CQR_SUPPRESS_IT, &cqr->flags))
+			continue;
+		if (sense && (sense[1] & SNS1_NO_REC_FOUND) &&
+		    test_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags))
 			continue;
 		if (scsw_cstat(&cqr->irb.scsw) == 0x40 &&
 		    test_bit(DASD_CQR_SUPPRESS_IL, &cqr->flags))
@@ -2748,11 +2781,13 @@
 {
 	struct request *req;
 	blk_status_t error = BLK_STS_OK;
+	unsigned int proc_bytes;
 	int status;
 
 	req = (struct request *) cqr->callback_data;
 	dasd_profile_end(cqr->block, cqr, req);
 
+	proc_bytes = cqr->proc_bytes;
 	status = cqr->block->base->discipline->free_cp(cqr, req);
 	if (status < 0)
 		error = errno_to_blk_status(status);
@@ -2783,7 +2818,17 @@
 		blk_mq_end_request(req, error);
 		blk_mq_run_hw_queues(req->q, true);
 	} else {
-		blk_mq_complete_request(req);
+		/*
+		 * Partial completed requests can happen with ESE devices.
+		 * During read we might have gotten a NRF error and have to
+		 * complete a request partially.
+		 */
+		if (proc_bytes) {
+			blk_update_request(req, BLK_STS_OK, proc_bytes);
+			blk_mq_requeue_request(req, true);
+		} else if (likely(!blk_should_fake_timeout(req->q))) {
+			blk_mq_complete_request(req);
+		}
 	}
 }
 
@@ -2952,35 +2997,32 @@
  * Requeue a request back to the block request queue
  * only works for block requests
  */
-static int _dasd_requeue_request(struct dasd_ccw_req *cqr)
+static void _dasd_requeue_request(struct dasd_ccw_req *cqr)
 {
-	struct dasd_block *block = cqr->block;
 	struct request *req;
 
-	if (!block)
-		return -EINVAL;
+	/*
+	 * If the request is an ERP request there is nothing to requeue.
+	 * This will be done with the remaining original request.
+	 */
+	if (cqr->refers)
+		return;
 	spin_lock_irq(&cqr->dq->lock);
 	req = (struct request *) cqr->callback_data;
-	blk_mq_requeue_request(req, false);
+	blk_mq_requeue_request(req, true);
 	spin_unlock_irq(&cqr->dq->lock);
 
-	return 0;
+	return;
 }
 
-/*
- * Go through all request on the dasd_block request queue, cancel them
- * on the respective dasd_device, and return them to the generic
- * block layer.
- */
-static int dasd_flush_block_queue(struct dasd_block *block)
+static int _dasd_requests_to_flushqueue(struct dasd_block *block,
+					struct list_head *flush_queue)
 {
 	struct dasd_ccw_req *cqr, *n;
-	int rc, i;
-	struct list_head flush_queue;
 	unsigned long flags;
+	int rc, i;
 
-	INIT_LIST_HEAD(&flush_queue);
-	spin_lock_bh(&block->queue_lock);
+	spin_lock_irqsave(&block->queue_lock, flags);
 	rc = 0;
 restart:
 	list_for_each_entry_safe(cqr, n, &block->ccw_queue, blocklist) {
@@ -2995,13 +3037,32 @@
 		 * is returned from the dasd_device layer.
 		 */
 		cqr->callback = _dasd_wake_block_flush_cb;
-		for (i = 0; cqr != NULL; cqr = cqr->refers, i++)
-			list_move_tail(&cqr->blocklist, &flush_queue);
+		for (i = 0; cqr; cqr = cqr->refers, i++)
+			list_move_tail(&cqr->blocklist, flush_queue);
 		if (i > 1)
 			/* moved more than one request - need to restart */
 			goto restart;
 	}
-	spin_unlock_bh(&block->queue_lock);
+	spin_unlock_irqrestore(&block->queue_lock, flags);
+
+	return rc;
+}
+
+/*
+ * Go through all request on the dasd_block request queue, cancel them
+ * on the respective dasd_device, and return them to the generic
+ * block layer.
+ */
+static int dasd_flush_block_queue(struct dasd_block *block)
+{
+	struct dasd_ccw_req *cqr, *n;
+	struct list_head flush_queue;
+	unsigned long flags;
+	int rc;
+
+	INIT_LIST_HEAD(&flush_queue);
+	rc = _dasd_requests_to_flushqueue(block, &flush_queue);
+
 	/* Now call the callback function of flushed requests */
 restart_cb:
 	list_for_each_entry_safe(cqr, n, &flush_queue, blocklist) {
@@ -3060,7 +3121,8 @@
 
 	basedev = block->base;
 	spin_lock_irq(&dq->lock);
-	if (basedev->state < DASD_STATE_READY) {
+	if (basedev->state < DASD_STATE_READY ||
+	    test_bit(DASD_FLAG_OFFLINE, &basedev->flags)) {
 		DBF_DEV_EVENT(DBF_ERR, basedev,
 			      "device not ready for request %p", req);
 		rc = BLK_STS_IOERR;
@@ -3495,8 +3557,6 @@
 	struct dasd_device *device;
 	struct dasd_block *block;
 
-	cdev->handler = NULL;
-
 	device = dasd_device_from_cdev(cdev);
 	if (IS_ERR(device)) {
 		dasd_remove_sysfs_files(cdev);
@@ -3515,6 +3575,7 @@
 	 * no quite down yet.
 	 */
 	dasd_set_target_state(device, DASD_STATE_NEW);
+	cdev->handler = NULL;
 	/* dasd_delete_device destroys the device reference. */
 	block = device->block;
 	dasd_delete_device(device);
@@ -3938,75 +3999,36 @@
  */
 static int dasd_generic_requeue_all_requests(struct dasd_device *device)
 {
+	struct dasd_block *block = device->block;
 	struct list_head requeue_queue;
 	struct dasd_ccw_req *cqr, *n;
-	struct dasd_ccw_req *refers;
 	int rc;
 
-	INIT_LIST_HEAD(&requeue_queue);
-	spin_lock_irq(get_ccwdev_lock(device->cdev));
-	rc = 0;
-	list_for_each_entry_safe(cqr, n, &device->ccw_queue, devlist) {
-		/* Check status and move request to flush_queue */
-		if (cqr->status == DASD_CQR_IN_IO) {
-			rc = device->discipline->term_IO(cqr);
-			if (rc) {
-				/* unable to terminate requeust */
-				dev_err(&device->cdev->dev,
-					"Unable to terminate request %p "
-					"on suspend\n", cqr);
-				spin_unlock_irq(get_ccwdev_lock(device->cdev));
-				dasd_put_device(device);
-				return rc;
-			}
-		}
-		list_move_tail(&cqr->devlist, &requeue_queue);
-	}
-	spin_unlock_irq(get_ccwdev_lock(device->cdev));
-
-	list_for_each_entry_safe(cqr, n, &requeue_queue, devlist) {
-		wait_event(dasd_flush_wq,
-			   (cqr->status != DASD_CQR_CLEAR_PENDING));
+	if (!block)
+		return 0;
 
-		/*
-		 * requeue requests to blocklayer will only work
-		 * for block device requests
-		 */
-		if (_dasd_requeue_request(cqr))
-			continue;
+	INIT_LIST_HEAD(&requeue_queue);
+	rc = _dasd_requests_to_flushqueue(block, &requeue_queue);
 
-		/* remove requests from device and block queue */
-		list_del_init(&cqr->devlist);
-		while (cqr->refers != NULL) {
-			refers = cqr->refers;
-			/* remove the request from the block queue */
-			list_del(&cqr->blocklist);
-			/* free the finished erp request */
-			dasd_free_erp_request(cqr, cqr->memdev);
-			cqr = refers;
+	/* Now call the callback function of flushed requests */
+restart_cb:
+	list_for_each_entry_safe(cqr, n, &requeue_queue, blocklist) {
+		wait_event(dasd_flush_wq, (cqr->status < DASD_CQR_QUEUED));
+		/* Process finished ERP request. */
+		if (cqr->refers) {
+			spin_lock_bh(&block->queue_lock);
+			__dasd_process_erp(block->base, cqr);
+			spin_unlock_bh(&block->queue_lock);
+			/* restart list_for_xx loop since dasd_process_erp
+			 * might remove multiple elements
+			 */
+			goto restart_cb;
 		}
-
-		/*
-		 * _dasd_requeue_request already checked for a valid
-		 * blockdevice, no need to check again
-		 * all erp requests (cqr->refers) have a cqr->block
-		 * pointer copy from the original cqr
-		 */
+		_dasd_requeue_request(cqr);
 		list_del_init(&cqr->blocklist);
 		cqr->block->base->discipline->free_cp(
 			cqr, (struct request *) cqr->callback_data);
 	}
-
-	/*
-	 * if requests remain then they are internal request
-	 * and go back to the device queue
-	 */
-	if (!list_empty(&requeue_queue)) {
-		/* move freeze_queue to start of the ccw_queue */
-		spin_lock_irq(get_ccwdev_lock(device->cdev));
-		list_splice_tail(&requeue_queue, &device->ccw_queue);
-		spin_unlock_irq(get_ccwdev_lock(device->cdev));
-	}
 	dasd_schedule_device_bh(device);
 	return rc;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/block/dasd_3990_erp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/block/dasd_3990_erp.c
@@ -1401,14 +1401,8 @@
 
 	struct dasd_device *device = erp->startdev;
 
-	/*
-	 * In some cases the 'File Protected' error might be expected and
-	 * log messages shouldn't be written then.
-	 * Check if the according suppress bit is set.
-	 */
-	if (!test_bit(DASD_CQR_SUPPRESS_FP, &erp->flags))
-		dev_err(&device->cdev->dev,
-			"Accessing the DASD failed because of a hardware error\n");
+	dev_err(&device->cdev->dev,
+		"Accessing the DASD failed because of a hardware error\n");
 
 	return dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);
 
@@ -2436,7 +2430,7 @@
 	erp->block    = cqr->block;
 	erp->magic    = cqr->magic;
 	erp->expires  = cqr->expires;
-	erp->retries  = 256;
+	erp->retries  = device->default_retries;
 	erp->buildclk = get_tod_clock();
 	erp->status = DASD_CQR_FILLED;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/block/dasd_alias.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/block/dasd_alias.c
@@ -256,7 +256,6 @@
 		return;
 	device->discipline->get_uid(device, &uid);
 	spin_lock_irqsave(&lcu->lock, flags);
-	list_del_init(&device->alias_list);
 	/* make sure that the workers don't use this device */
 	if (device == lcu->suc_data.device) {
 		spin_unlock_irqrestore(&lcu->lock, flags);
@@ -283,6 +282,7 @@
 
 	spin_lock_irqsave(&aliastree.lock, flags);
 	spin_lock(&lcu->lock);
+	list_del_init(&device->alias_list);
 	if (list_empty(&lcu->grouplist) &&
 	    list_empty(&lcu->active_devices) &&
 	    list_empty(&lcu->inactive_devices)) {
@@ -462,11 +462,19 @@
 	spin_unlock_irqrestore(&lcu->lock, flags);
 
 	rc = dasd_sleep_on(cqr);
-	if (rc && !suborder_not_supported(cqr)) {
+	if (!rc)
+		goto out;
+
+	if (suborder_not_supported(cqr)) {
+		/* suborder not supported or device unusable for IO */
+		rc = -EOPNOTSUPP;
+	} else {
+		/* IO failed but should be retried */
 		spin_lock_irqsave(&lcu->lock, flags);
 		lcu->flags |= NEED_UAC_UPDATE;
 		spin_unlock_irqrestore(&lcu->lock, flags);
 	}
+out:
 	dasd_sfree_request(cqr, cqr->memdev);
 	return rc;
 }
@@ -503,6 +511,14 @@
 		return rc;
 
 	spin_lock_irqsave(&lcu->lock, flags);
+	/*
+	 * there is another update needed skip the remaining handling
+	 * the data might already be outdated
+	 * but especially do not add the device to an LCU with pending
+	 * update
+	 */
+	if (lcu->flags & NEED_UAC_UPDATE)
+		goto out;
 	lcu->pav = NO_PAV;
 	for (i = 0; i < MAX_DEVICES_PER_LCU; ++i) {
 		switch (lcu->uac->unit[i].ua_type) {
@@ -521,6 +537,7 @@
 				 alias_list) {
 		_add_device_to_lcu(lcu, device, refdev);
 	}
+out:
 	spin_unlock_irqrestore(&lcu->lock, flags);
 	return 0;
 }
@@ -625,6 +642,7 @@
 	}
 	if (lcu->flags & UPDATE_PENDING) {
 		list_move(&device->alias_list, &lcu->active_devices);
+		private->pavgroup = NULL;
 		_schedule_lcu_update(lcu, device);
 	}
 	spin_unlock_irqrestore(&lcu->lock, flags);
@@ -657,12 +675,12 @@
 struct dasd_device *dasd_alias_get_start_dev(struct dasd_device *base_device)
 {
 	struct dasd_eckd_private *alias_priv, *private = base_device->private;
-	struct alias_pav_group *group = private->pavgroup;
 	struct alias_lcu *lcu = private->lcu;
 	struct dasd_device *alias_device;
+	struct alias_pav_group *group;
 	unsigned long flags;
 
-	if (!group || !lcu)
+	if (!lcu)
 		return NULL;
 	if (lcu->pav == NO_PAV ||
 	    lcu->flags & (NEED_UAC_UPDATE | UPDATE_PENDING))
@@ -679,6 +697,11 @@
 	}
 
 	spin_lock_irqsave(&lcu->lock, flags);
+	group = private->pavgroup;
+	if (!group) {
+		spin_unlock_irqrestore(&lcu->lock, flags);
+		return NULL;
+	}
 	alias_device = group->next;
 	if (!alias_device) {
 		if (list_empty(&group->aliaslist)) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/block/dasd_diag.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/block/dasd_diag.c
@@ -58,7 +58,7 @@
 
 struct dasd_diag_req {
 	unsigned int block_count;
-	struct dasd_diag_bio bio[0];
+	struct dasd_diag_bio bio[];
 };
 
 static const u8 DASD_DIAG_CMS1[] = { 0xc3, 0xd4, 0xe2, 0xf1 };/* EBCDIC CMS1 */
@@ -319,7 +319,7 @@
 	struct dasd_diag_characteristics *rdc_data;
 	struct vtoc_cms_label *label;
 	struct dasd_block *block;
-	struct dasd_diag_bio bio;
+	struct dasd_diag_bio *bio;
 	unsigned int sb, bsize;
 	blocknum_t end_block;
 	int rc;
@@ -395,29 +395,36 @@
 		rc = -ENOMEM;
 		goto out;
 	}
+	bio = kzalloc(sizeof(*bio), GFP_KERNEL);
+	if (bio == NULL)  {
+		DBF_DEV_EVENT(DBF_WARNING, device, "%s",
+			      "No memory to allocate initialization bio");
+		rc = -ENOMEM;
+		goto out_label;
+	}
 	rc = 0;
 	end_block = 0;
 	/* try all sizes - needed for ECKD devices */
 	for (bsize = 512; bsize <= PAGE_SIZE; bsize <<= 1) {
 		mdsk_init_io(device, bsize, 0, &end_block);
-		memset(&bio, 0, sizeof (struct dasd_diag_bio));
-		bio.type = MDSK_READ_REQ;
-		bio.block_number = private->pt_block + 1;
-		bio.buffer = label;
+		memset(bio, 0, sizeof(*bio));
+		bio->type = MDSK_READ_REQ;
+		bio->block_number = private->pt_block + 1;
+		bio->buffer = label;
 		memset(&private->iob, 0, sizeof (struct dasd_diag_rw_io));
 		private->iob.dev_nr = rdc_data->dev_nr;
 		private->iob.key = 0;
 		private->iob.flags = 0;	/* do synchronous io */
 		private->iob.block_count = 1;
 		private->iob.interrupt_params = 0;
-		private->iob.bio_list = &bio;
+		private->iob.bio_list = bio;
 		private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT;
 		rc = dia250(&private->iob, RW_BIO);
 		if (rc == 3) {
 			pr_warn("%s: A 64-bit DIAG call failed\n",
 				dev_name(&device->cdev->dev));
 			rc = -EOPNOTSUPP;
-			goto out_label;
+			goto out_bio;
 		}
 		mdsk_term_io(device);
 		if (rc == 0)
@@ -427,7 +434,7 @@
 		pr_warn("%s: Accessing the DASD failed because of an incorrect format (rc=%d)\n",
 			dev_name(&device->cdev->dev), rc);
 		rc = -EIO;
-		goto out_label;
+		goto out_bio;
 	}
 	/* check for label block */
 	if (memcmp(label->label_id, DASD_DIAG_CMS1,
@@ -457,6 +464,8 @@
 			(rc == 4) ? ", read-only device" : "");
 		rc = 0;
 	}
+out_bio:
+	kfree(bio);
 out_label:
 	free_page((long) label);
 out:
@@ -635,12 +644,17 @@
 	blk_queue_segment_boundary(q, PAGE_SIZE - 1);
 }
 
+static int dasd_diag_pe_handler(struct dasd_device *device, __u8 tbvpm)
+{
+	return dasd_generic_verify_path(device, tbvpm);
+}
+
 static struct dasd_discipline dasd_diag_discipline = {
 	.owner = THIS_MODULE,
 	.name = "DIAG",
 	.ebcname = "DIAG",
 	.check_device = dasd_diag_check_device,
-	.verify_path = dasd_generic_verify_path,
+	.pe_handler = dasd_diag_pe_handler,
 	.fill_geometry = dasd_diag_fill_geometry,
 	.setup_blk_queue = dasd_diag_setup_blk_queue,
 	.start_IO = dasd_start_diag,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/block/dasd_eckd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/block/dasd_eckd.c
@@ -103,7 +103,7 @@
 };
 
 /* definitions for the path verification worker */
-struct path_verification_work_data {
+struct pe_handler_work_data {
 	struct work_struct worker;
 	struct dasd_device *device;
 	struct dasd_ccw_req cqr;
@@ -112,8 +112,8 @@
 	int isglobal;
 	__u8 tbvpm;
 };
-static struct path_verification_work_data *path_verification_worker;
-static DEFINE_MUTEX(dasd_path_verification_mutex);
+static struct pe_handler_work_data *pe_handler_worker;
+static DEFINE_MUTEX(dasd_pe_handler_mutex);
 
 struct check_attention_work_data {
 	struct work_struct worker;
@@ -207,6 +207,45 @@
 	geo->head |= head;
 }
 
+/*
+ * calculate failing track from sense data depending if
+ * it is an EAV device or not
+ */
+static int dasd_eckd_track_from_irb(struct irb *irb, struct dasd_device *device,
+				    sector_t *track)
+{
+	struct dasd_eckd_private *private = device->private;
+	u8 *sense = NULL;
+	u32 cyl;
+	u8 head;
+
+	sense = dasd_get_sense(irb);
+	if (!sense) {
+		DBF_DEV_EVENT(DBF_WARNING, device, "%s",
+			      "ESE error no sense data\n");
+		return -EINVAL;
+	}
+	if (!(sense[27] & DASD_SENSE_BIT_2)) {
+		DBF_DEV_EVENT(DBF_WARNING, device, "%s",
+			      "ESE error no valid track data\n");
+		return -EINVAL;
+	}
+
+	if (sense[27] & DASD_SENSE_BIT_3) {
+		/* enhanced addressing */
+		cyl = sense[30] << 20;
+		cyl |= (sense[31] & 0xF0) << 12;
+		cyl |= sense[28] << 8;
+		cyl |= sense[29];
+	} else {
+		cyl = sense[29] << 8;
+		cyl |= sense[30];
+	}
+	head = sense[31] & 0x0F;
+	*track = cyl * private->rdc_data.trk_per_cyl + head;
+	return 0;
+}
+
 static int set_timestamp(struct ccw1 *ccw, struct DE_eckd_data *data,
 		     struct dasd_device *device)
 {
@@ -1128,7 +1167,8 @@
 {
 	struct dasd_eckd_private *private = device->private;
 	int fcx_in_css, fcx_in_gneq, fcx_in_features;
-	int tpm, mdc;
+	unsigned int mdc;
+	int tpm;
 
 	if (dasd_nofcx)
 		return 0;
@@ -1142,7 +1182,7 @@
 		return 0;
 
 	mdc = ccw_device_get_mdc(device->cdev, 0);
-	if (mdc < 0) {
+	if (mdc == 0) {
 		dev_warn(&device->cdev->dev, "Detecting the maximum supported data size for zHPF requests failed\n");
 		return 0;
 	} else {
@@ -1153,12 +1193,12 @@
 static int verify_fcx_max_data(struct dasd_device *device, __u8 lpm)
 {
 	struct dasd_eckd_private *private = device->private;
-	int mdc;
+	unsigned int mdc;
 	u32 fcx_max_data;
 
 	if (private->fcx_max_data) {
 		mdc = ccw_device_get_mdc(device->cdev, lpm);
-		if ((mdc < 0)) {
+		if (mdc == 0) {
 			dev_warn(&device->cdev->dev,
 				 "Detecting the maximum data size for zHPF "
 				 "requests failed (rc=%d) for a new path %x\n",
@@ -1179,7 +1219,7 @@
 }
 
 static int rebuild_device_uid(struct dasd_device *device,
-			      struct path_verification_work_data *data)
+			      struct pe_handler_work_data *data)
 {
 	struct dasd_eckd_private *private = device->private;
 	__u8 lpm, opm = dasd_path_get_opm(device);
@@ -1217,10 +1257,9 @@
 	return rc;
 }
 
-static void do_path_verification_work(struct work_struct *work)
+static void dasd_eckd_path_available_action(struct dasd_device *device,
+					    struct pe_handler_work_data *data)
 {
-	struct path_verification_work_data *data;
-	struct dasd_device *device;
 	struct dasd_eckd_private path_private;
 	struct dasd_uid *uid;
 	__u8 path_rcd_buf[DASD_ECKD_RCD_DATA_SIZE];
@@ -1229,19 +1268,6 @@
 	char print_uid[60];
 	int rc;
 
-	data = container_of(work, struct path_verification_work_data, worker);
-	device = data->device;
-
-	/* delay path verification until device was resumed */
-	if (test_bit(DASD_FLAG_SUSPENDED, &device->flags)) {
-		schedule_work(work);
-		return;
-	}
-	/* check if path verification already running and delay if so */
-	if (test_and_set_bit(DASD_FLAG_PATH_VERIFY, &device->flags)) {
-		schedule_work(work);
-		return;
-	}
 	opm = 0;
 	npm = 0;
 	ppm = 0;
@@ -1378,30 +1404,54 @@
 		dasd_path_add_nohpfpm(device, hpfpm);
 		spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
 	}
+}
+
+static void do_pe_handler_work(struct work_struct *work)
+{
+	struct pe_handler_work_data *data;
+	struct dasd_device *device;
+
+	data = container_of(work, struct pe_handler_work_data, worker);
+	device = data->device;
+
+	/* delay path verification until device was resumed */
+	if (test_bit(DASD_FLAG_SUSPENDED, &device->flags)) {
+		schedule_work(work);
+		return;
+	}
+	/* check if path verification already running and delay if so */
+	if (test_and_set_bit(DASD_FLAG_PATH_VERIFY, &device->flags)) {
+		schedule_work(work);
+		return;
+	}
+
+	dasd_eckd_path_available_action(device, data);
+
 	clear_bit(DASD_FLAG_PATH_VERIFY, &device->flags);
 	dasd_put_device(device);
 	if (data->isglobal)
-		mutex_unlock(&dasd_path_verification_mutex);
+		mutex_unlock(&dasd_pe_handler_mutex);
 	else
 		kfree(data);
 }
 
-static int dasd_eckd_verify_path(struct dasd_device *device, __u8 lpm)
+static int dasd_eckd_pe_handler(struct dasd_device *device, __u8 lpm)
 {
-	struct path_verification_work_data *data;
+	struct pe_handler_work_data *data;
 
 	data = kmalloc(sizeof(*data), GFP_ATOMIC | GFP_DMA);
 	if (!data) {
-		if (mutex_trylock(&dasd_path_verification_mutex)) {
-			data = path_verification_worker;
+		if (mutex_trylock(&dasd_pe_handler_mutex)) {
+			data = pe_handler_worker;
 			data->isglobal = 1;
-		} else
+		} else {
 			return -ENOMEM;
+		}
 	} else {
 		memset(data, 0, sizeof(*data));
 		data->isglobal = 0;
 	}
-	INIT_WORK(&data->worker, do_path_verification_work);
+	INIT_WORK(&data->worker, do_pe_handler_work);
 	dasd_get_device(device);
 	data->device = device;
 	data->tbvpm = lpm;
@@ -2073,7 +2123,7 @@
 	dasd_free_block(device->block);
 	device->block = NULL;
 out_err1:
-	kfree(private->conf_data);
+	dasd_eckd_clear_conf_data(device);
 	kfree(device->private);
 	device->private = NULL;
 	return rc;
@@ -2082,7 +2132,6 @@
 static void dasd_eckd_uncheck_device(struct dasd_device *device)
 {
 	struct dasd_eckd_private *private = device->private;
-	int i;
 
 	if (!private)
 		return;
@@ -2092,21 +2141,7 @@
 	private->sneq = NULL;
 	private->vdsneq = NULL;
 	private->gneq = NULL;
-	private->conf_len = 0;
-	for (i = 0; i < 8; i++) {
-		kfree(device->path[i].conf_data);
-		if ((__u8 *)device->path[i].conf_data ==
-		    private->conf_data) {
-			private->conf_data = NULL;
-			private->conf_len = 0;
-		}
-		device->path[i].conf_data = NULL;
-		device->path[i].cssid = 0;
-		device->path[i].ssid = 0;
-		device->path[i].chpid = 0;
-	}
-	kfree(private->conf_data);
-	private->conf_data = NULL;
+	dasd_eckd_clear_conf_data(device);
 }
 
 static struct dasd_ccw_req *
@@ -2166,6 +2201,7 @@
 	cqr->status = DASD_CQR_FILLED;
 	/* Set flags to suppress output for expected errors */
 	set_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags);
+	set_bit(DASD_CQR_SUPPRESS_IT, &cqr->flags);
 
 	return cqr;
 }
@@ -2447,7 +2483,6 @@
 	cqr->buildclk = get_tod_clock();
 	cqr->status = DASD_CQR_FILLED;
 	/* Set flags to suppress output for expected errors */
-	set_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags);
 	set_bit(DASD_CQR_SUPPRESS_IL, &cqr->flags);
 
 	return cqr;
@@ -3000,6 +3035,49 @@
 					     0, NULL);
 }
 
+static bool test_and_set_format_track(struct dasd_format_entry *to_format,
+				      struct dasd_ccw_req *cqr)
+{
+	struct dasd_block *block = cqr->block;
+	struct dasd_format_entry *format;
+	unsigned long flags;
+	bool rc = false;
+
+	spin_lock_irqsave(&block->format_lock, flags);
+	if (cqr->trkcount != atomic_read(&block->trkcount)) {
+		/*
+		 * The number of formatted tracks has changed after request
+		 * start and we can not tell if the current track was involved.
+		 * To avoid data corruption treat it as if the current track is
+		 * involved
+		 */
+		rc = true;
+		goto out;
+	}
+	list_for_each_entry(format, &block->format_list, list) {
+		if (format->track == to_format->track) {
+			rc = true;
+			goto out;
+		}
+	}
+	list_add_tail(&to_format->list, &block->format_list);
+
+out:
+	spin_unlock_irqrestore(&block->format_lock, flags);
+	return rc;
+}
+
+static void clear_format_track(struct dasd_format_entry *format,
+			      struct dasd_block *block)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&block->format_lock, flags);
+	atomic_inc(&block->trkcount);
+	list_del_init(&format->list);
+	spin_unlock_irqrestore(&block->format_lock, flags);
+}
+
 /*
  * Callback function to free ESE format requests.
  */
@@ -3007,15 +3085,19 @@
 {
 	struct dasd_device *device = cqr->startdev;
 	struct dasd_eckd_private *private = device->private;
+	struct dasd_format_entry *format = data;
 
+	clear_format_track(format, cqr->basedev->block);
 	private->count--;
 	dasd_ffree_request(cqr, device);
 }
 
 static struct dasd_ccw_req *
-dasd_eckd_ese_format(struct dasd_device *startdev, struct dasd_ccw_req *cqr)
+dasd_eckd_ese_format(struct dasd_device *startdev, struct dasd_ccw_req *cqr,
+		     struct irb *irb)
 {
 	struct dasd_eckd_private *private;
+	struct dasd_format_entry *format;
 	struct format_data_t fdata;
 	unsigned int recs_per_trk;
 	struct dasd_ccw_req *fcqr;
@@ -3025,23 +3107,42 @@
 	struct request *req;
 	sector_t first_trk;
 	sector_t last_trk;
+	sector_t curr_trk;
 	int rc;
 
-	req = cqr->callback_data;
-	base = cqr->block->base;
+	req = dasd_get_callback_data(cqr);
+	block = cqr->block;
+	base = block->base;
 	private = base->private;
-	block = base->block;
 	blksize = block->bp_block;
 	recs_per_trk = recs_per_track(&private->rdc_data, 0, blksize);
+	format = &startdev->format_entry;
 
 	first_trk = blk_rq_pos(req) >> block->s2b_shift;
 	sector_div(first_trk, recs_per_trk);
 	last_trk =
 		(blk_rq_pos(req) + blk_rq_sectors(req) - 1) >> block->s2b_shift;
 	sector_div(last_trk, recs_per_trk);
+	rc = dasd_eckd_track_from_irb(irb, base, &curr_trk);
+	if (rc)
+		return ERR_PTR(rc);
+
+	if (curr_trk < first_trk || curr_trk > last_trk) {
+		DBF_DEV_EVENT(DBF_WARNING, startdev,
+			      "ESE error track %llu not within range %llu - %llu\n",
+			      curr_trk, first_trk, last_trk);
+		return ERR_PTR(-EINVAL);
+	}
+	format->track = curr_trk;
+	/* test if track is already in formatting by another thread */
+	if (test_and_set_format_track(format, cqr)) {
+		/* this is no real error so do not count down retries */
+		cqr->retries++;
+		return ERR_PTR(-EEXIST);
+	}
 
-	fdata.start_unit = first_trk;
-	fdata.stop_unit = last_trk;
+	fdata.start_unit = curr_trk;
+	fdata.stop_unit = curr_trk;
 	fdata.blksize = blksize;
 	fdata.intensity = private->uses_cdl ? DASD_FMT_INT_COMPAT : 0;
 
@@ -3058,6 +3159,7 @@
 		return fcqr;
 
 	fcqr->callback = dasd_eckd_ese_format_cb;
+	fcqr->callback_data = (void *) format;
 
 	return fcqr;
 }
@@ -3065,29 +3167,86 @@
 /*
  * When data is read from an unformatted area of an ESE volume, this function
  * returns zeroed data and thereby mimics a read of zero data.
+ *
+ * The first unformatted track is the one that got the NRF error, the address is
+ * encoded in the sense data.
+ *
+ * All tracks before have returned valid data and should not be touched.
+ * All tracks after the unformatted track might be formatted or not. This is
+ * currently not known, remember the processed data and return the remainder of
+ * the request to the blocklayer in __dasd_cleanup_cqr().
  */
-static void dasd_eckd_ese_read(struct dasd_ccw_req *cqr)
+static int dasd_eckd_ese_read(struct dasd_ccw_req *cqr, struct irb *irb)
 {
+	struct dasd_eckd_private *private;
+	sector_t first_trk, last_trk;
+	sector_t first_blk, last_blk;
 	unsigned int blksize, off;
+	unsigned int recs_per_trk;
 	struct dasd_device *base;
 	struct req_iterator iter;
+	struct dasd_block *block;
+	unsigned int skip_block;
+	unsigned int blk_count;
 	struct request *req;
 	struct bio_vec bv;
+	sector_t curr_trk;
+	sector_t end_blk;
 	char *dst;
+	int rc;
 
 	req = (struct request *) cqr->callback_data;
 	base = cqr->block->base;
 	blksize = base->block->bp_block;
+	block =  cqr->block;
+	private = base->private;
+	skip_block = 0;
+	blk_count = 0;
+
+	recs_per_trk = recs_per_track(&private->rdc_data, 0, blksize);
+	first_trk = first_blk = blk_rq_pos(req) >> block->s2b_shift;
+	sector_div(first_trk, recs_per_trk);
+	last_trk = last_blk =
+		(blk_rq_pos(req) + blk_rq_sectors(req) - 1) >> block->s2b_shift;
+	sector_div(last_trk, recs_per_trk);
+	rc = dasd_eckd_track_from_irb(irb, base, &curr_trk);
+	if (rc)
+		return rc;
+
+	/* sanity check if the current track from sense data is valid */
+	if (curr_trk < first_trk || curr_trk > last_trk) {
+		DBF_DEV_EVENT(DBF_WARNING, base,
+			      "ESE error track %llu not within range %llu - %llu\n",
+			      curr_trk, first_trk, last_trk);
+		return -EINVAL;
+	}
+
+	/*
+	 * if not the first track got the NRF error we have to skip over valid
+	 * blocks
+	 */
+	if (curr_trk != first_trk)
+		skip_block = curr_trk * recs_per_trk - first_blk;
+
+	/* we have no information beyond the current track */
+	end_blk = (curr_trk + 1) * recs_per_trk;
 
 	rq_for_each_segment(bv, req, iter) {
 		dst = page_address(bv.bv_page) + bv.bv_offset;
 		for (off = 0; off < bv.bv_len; off += blksize) {
-			if (dst && rq_data_dir(req) == READ) {
-				dst += off;
-				memset(dst, 0, blksize);
+			if (first_blk + blk_count >= end_blk) {
+				cqr->proc_bytes = blk_count * blksize;
+				return 0;
 			}
+			if (dst && !skip_block)
+				memset(dst, 0, blksize);
+			else
+				skip_block--;
+			dst += blksize;
+			blk_count++;
 		}
 	}
+	return 0;
 }
 
 /*
@@ -3872,8 +4031,6 @@
 
 	/* Set flags to suppress output for expected errors */
 	if (dasd_eckd_is_ese(basedev)) {
-		set_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags);
-		set_bit(DASD_CQR_SUPPRESS_IL, &cqr->flags);
 		set_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags);
 	}
 
@@ -4375,9 +4532,8 @@
 
 	/* Set flags to suppress output for expected errors */
 	if (dasd_eckd_is_ese(basedev)) {
-		set_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags);
-		set_bit(DASD_CQR_SUPPRESS_IL, &cqr->flags);
 		set_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags);
+		set_bit(DASD_CQR_SUPPRESS_IT, &cqr->flags);
 	}
 
 	return cqr;
@@ -4478,7 +4634,6 @@
 	struct dasd_device *basedev;
 	struct req_iterator iter;
 	struct dasd_ccw_req *cqr;
-	unsigned int first_offs;
 	unsigned int trkcount;
 	unsigned long *idaws;
 	unsigned int size;
@@ -4512,7 +4667,6 @@
 	last_trk = (blk_rq_pos(req) + blk_rq_sectors(req) - 1) /
 		DASD_RAW_SECTORS_PER_TRACK;
 	trkcount = last_trk - first_trk + 1;
-	first_offs = 0;
 
 	if (rq_data_dir(req) == READ)
 		cmd = DASD_ECKD_CCW_READ_TRACK;
@@ -4556,13 +4710,13 @@
 
 	if (use_prefix) {
 		prefix_LRE(ccw++, data, first_trk, last_trk, cmd, basedev,
-			   startdev, 1, first_offs + 1, trkcount, 0, 0);
+			   startdev, 1, 0, trkcount, 0, 0);
 	} else {
 		define_extent(ccw++, data, first_trk, last_trk, cmd, basedev, 0);
 		ccw[-1].flags |= CCW_FLAG_CC;
 
 		data += sizeof(struct DE_eckd_data);
-		locate_record_ext(ccw++, data, first_trk, first_offs + 1,
+		locate_record_ext(ccw++, data, first_trk, 0,
 				  trkcount, cmd, basedev, 0, 0);
 	}
 
@@ -5549,36 +5703,32 @@
 {
 	u8 *sense = dasd_get_sense(irb);
 
-	if (scsw_is_tm(&irb->scsw)) {
-		/*
-		 * In some cases the 'File Protected' or 'Incorrect Length'
-		 * error might be expected and log messages shouldn't be written
-		 * then. Check if the according suppress bit is set.
-		 */
-		if (sense && (sense[1] & SNS1_FILE_PROTECTED) &&
-		    test_bit(DASD_CQR_SUPPRESS_FP, &req->flags))
-			return;
-		if (scsw_cstat(&irb->scsw) == 0x40 &&
-		    test_bit(DASD_CQR_SUPPRESS_IL, &req->flags))
-			return;
+	/*
+	 * In some cases certain errors might be expected and
+	 * log messages shouldn't be written then.
+	 * Check if the according suppress bit is set.
+	 */
+	if (sense && (sense[1] & SNS1_INV_TRACK_FORMAT) &&
+	    !(sense[2] & SNS2_ENV_DATA_PRESENT) &&
+	    test_bit(DASD_CQR_SUPPRESS_IT, &req->flags))
+		return;
 
-		dasd_eckd_dump_sense_tcw(device, req, irb);
-	} else {
-		/*
-		 * In some cases the 'Command Reject' or 'No Record Found'
-		 * error might be expected and log messages shouldn't be
-		 * written then. Check if the according suppress bit is set.
-		 */
-		if (sense && sense[0] & SNS0_CMD_REJECT &&
-		    test_bit(DASD_CQR_SUPPRESS_CR, &req->flags))
-			return;
+	if (sense && sense[0] & SNS0_CMD_REJECT &&
+	    test_bit(DASD_CQR_SUPPRESS_CR, &req->flags))
+		return;
 
-		if (sense && sense[1] & SNS1_NO_REC_FOUND &&
-		    test_bit(DASD_CQR_SUPPRESS_NRF, &req->flags))
-			return;
+	if (sense && sense[1] & SNS1_NO_REC_FOUND &&
+	    test_bit(DASD_CQR_SUPPRESS_NRF, &req->flags))
+		return;
 
+	if (scsw_cstat(&irb->scsw) == 0x40 &&
+	    test_bit(DASD_CQR_SUPPRESS_IL, &req->flags))
+		return;
+
+	if (scsw_is_tm(&irb->scsw))
+		dasd_eckd_dump_sense_tcw(device, req, irb);
+	else
 		dasd_eckd_dump_sense_ccw(device, req, irb);
-	}
 }
 
 static int dasd_eckd_pm_freeze(struct dasd_device *device)
@@ -6547,7 +6697,7 @@
 	.check_device = dasd_eckd_check_characteristics,
 	.uncheck_device = dasd_eckd_uncheck_device,
 	.do_analysis = dasd_eckd_do_analysis,
-	.verify_path = dasd_eckd_verify_path,
+	.pe_handler = dasd_eckd_pe_handler,
 	.basic_to_ready = dasd_eckd_basic_to_ready,
 	.online_to_ready = dasd_eckd_online_to_ready,
 	.basic_to_known = dasd_eckd_basic_to_known,
@@ -6606,18 +6756,20 @@
 		return -ENOMEM;
 	dasd_vol_info_req = kmalloc(sizeof(*dasd_vol_info_req),
 				    GFP_KERNEL | GFP_DMA);
-	if (!dasd_vol_info_req)
+	if (!dasd_vol_info_req) {
+		kfree(dasd_reserve_req);
 		return -ENOMEM;
-	path_verification_worker = kmalloc(sizeof(*path_verification_worker),
-				   GFP_KERNEL | GFP_DMA);
-	if (!path_verification_worker) {
+	}
+	pe_handler_worker = kmalloc(sizeof(*pe_handler_worker),
+				    GFP_KERNEL | GFP_DMA);
+	if (!pe_handler_worker) {
 		kfree(dasd_reserve_req);
 		kfree(dasd_vol_info_req);
 		return -ENOMEM;
 	}
 	rawpadpage = (void *)__get_free_page(GFP_KERNEL);
 	if (!rawpadpage) {
-		kfree(path_verification_worker);
+		kfree(pe_handler_worker);
 		kfree(dasd_reserve_req);
 		kfree(dasd_vol_info_req);
 		return -ENOMEM;
@@ -6626,7 +6778,7 @@
 	if (!ret)
 		wait_for_device_probe();
 	else {
-		kfree(path_verification_worker);
+		kfree(pe_handler_worker);
 		kfree(dasd_reserve_req);
 		kfree(dasd_vol_info_req);
 		free_page((unsigned long)rawpadpage);
@@ -6638,7 +6790,7 @@
 dasd_eckd_cleanup(void)
 {
 	ccw_driver_unregister(&dasd_eckd_driver);
-	kfree(path_verification_worker);
+	kfree(pe_handler_worker);
 	kfree(dasd_reserve_req);
 	free_page((unsigned long)rawpadpage);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/block/dasd_eckd.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/block/dasd_eckd.h
@@ -220,7 +220,7 @@
 	__u8 imbedded_count;
 	__u8 extended_operation;
 	__u16 extended_parameter_length;
-	__u8 extended_parameter[0];
+	__u8 extended_parameter[];
 } __attribute__ ((packed));
 
 /* Prefix data for format 0x00 and 0x01 */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/block/dasd_fba.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/block/dasd_fba.c
@@ -40,6 +40,7 @@
 MODULE_LICENSE("GPL");
 
 static struct dasd_discipline dasd_fba_discipline;
+static void *dasd_fba_zero_page;
 
 struct dasd_fba_private {
 	struct dasd_fba_characteristics rdc_data;
@@ -270,7 +271,7 @@
 	ccw->cmd_code = DASD_FBA_CCW_WRITE;
 	ccw->flags |= CCW_FLAG_SLI;
 	ccw->count = count;
-	ccw->cda = (__u32) (addr_t) page_to_phys(ZERO_PAGE(0));
+	ccw->cda = (__u32) (addr_t) dasd_fba_zero_page;
 }
 
 /*
@@ -802,13 +803,18 @@
 	blk_queue_flag_set(QUEUE_FLAG_DISCARD, q);
 }
 
+static int dasd_fba_pe_handler(struct dasd_device *device, __u8 tbvpm)
+{
+	return dasd_generic_verify_path(device, tbvpm);
+}
+
 static struct dasd_discipline dasd_fba_discipline = {
 	.owner = THIS_MODULE,
 	.name = "FBA ",
 	.ebcname = "FBA ",
 	.check_device = dasd_fba_check_characteristics,
 	.do_analysis = dasd_fba_do_analysis,
-	.verify_path = dasd_generic_verify_path,
+	.pe_handler = dasd_fba_pe_handler,
 	.setup_blk_queue = dasd_fba_setup_blk_queue,
 	.fill_geometry = dasd_fba_fill_geometry,
 	.start_IO = dasd_start_IO,
@@ -830,6 +836,11 @@
 	int ret;
 
 	ASCEBC(dasd_fba_discipline.ebcname, 4);
+
+	dasd_fba_zero_page = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
+	if (!dasd_fba_zero_page)
+		return -ENOMEM;
+
 	ret = ccw_driver_register(&dasd_fba_driver);
 	if (!ret)
 		wait_for_device_probe();
@@ -841,6 +852,7 @@
 dasd_fba_cleanup(void)
 {
 	ccw_driver_unregister(&dasd_fba_driver);
+	free_page((unsigned long)dasd_fba_zero_page);
 }
 
 module_init(dasd_fba_init);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/block/dasd_int.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/block/dasd_int.h
@@ -187,6 +187,8 @@
 
 	void (*callback)(struct dasd_ccw_req *, void *data);
 	void *callback_data;
+	unsigned int proc_bytes;	/* bytes for partial completion */
+	unsigned int trkcount;		/* count formatted tracks */
 };
 
 /*
@@ -224,7 +226,7 @@
  * The following flags are used to suppress output of certain errors.
  */
 #define DASD_CQR_SUPPRESS_NRF	4	/* Suppress 'No Record Found' error */
-#define DASD_CQR_SUPPRESS_FP	5	/* Suppress 'File Protected' error*/
+#define DASD_CQR_SUPPRESS_IT	5	/* Suppress 'Invalid Track' error*/
 #define DASD_CQR_SUPPRESS_IL	6	/* Suppress 'Incorrect Length' error */
 #define DASD_CQR_SUPPRESS_CR	7	/* Suppress 'Command Reject' error */
 
@@ -296,7 +298,7 @@
 	 * e.g. verify that new path is compatible with the current
 	 * configuration.
 	 */
-	int (*verify_path)(struct dasd_device *, __u8);
+	int (*pe_handler)(struct dasd_device *, __u8);
 
 	/*
 	 * Last things to do when a device is set online, and first things
@@ -387,8 +389,9 @@
 	int (*ext_pool_warn_thrshld)(struct dasd_device *);
 	int (*ext_pool_oos)(struct dasd_device *);
 	int (*ext_pool_exhaust)(struct dasd_device *, struct dasd_ccw_req *);
-	struct dasd_ccw_req *(*ese_format)(struct dasd_device *, struct dasd_ccw_req *);
-	void (*ese_read)(struct dasd_ccw_req *);
+	struct dasd_ccw_req *(*ese_format)(struct dasd_device *,
+					   struct dasd_ccw_req *, struct irb *);
+	int (*ese_read)(struct dasd_ccw_req *, struct irb *);
 };
 
 extern struct dasd_discipline *dasd_diag_discipline_pointer;
@@ -474,6 +477,11 @@
 	spinlock_t lock;
 };
 
+struct dasd_format_entry {
+	struct list_head list;
+	sector_t track;
+};
+
 struct dasd_device {
 	/* Block device stuff. */
 	struct dasd_block *block;
@@ -539,6 +547,7 @@
 	struct dentry *debugfs_dentry;
 	struct dentry *hosts_dentry;
 	struct dasd_profile profile;
+	struct dasd_format_entry format_entry;
 };
 
 struct dasd_block {
@@ -564,6 +573,10 @@
 
 	struct dentry *debugfs_dentry;
 	struct dasd_profile profile;
+
+	struct list_head format_list;
+	spinlock_t format_lock;
+	atomic_t trkcount;
 };
 
 struct dasd_attention_data {
@@ -712,6 +725,18 @@
 	return 0;
 }
 
+/*
+ * return the callback data of the original request in case there are
+ * ERP requests build on top of it
+ */
+static inline void *dasd_get_callback_data(struct dasd_ccw_req *cqr)
+{
+	while (cqr->refers)
+		cqr = cqr->refers;
+
+	return cqr->callback_data;
+}
+
 /* externals in dasd.c */
 #define DASD_PROFILE_OFF	 0
 #define DASD_PROFILE_ON 	 1
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/block/dasd_ioctl.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/block/dasd_ioctl.c
@@ -137,6 +137,7 @@
 	spin_unlock_irqrestore(get_ccwdev_lock(base->cdev), flags);
 
 	dasd_schedule_block_bh(block);
+	dasd_schedule_device_bh(base);
 	return 0;
 }
 
@@ -457,10 +458,9 @@
 /*
  * Return dasd information. Used for BIODASDINFO and BIODASDINFO2.
  */
-static int dasd_ioctl_information(struct dasd_block *block,
-				  unsigned int cmd, void __user *argp)
+static int __dasd_ioctl_information(struct dasd_block *block,
+		struct dasd_information2_t *dasd_info)
 {
-	struct dasd_information2_t *dasd_info;
 	struct subchannel_id sch_id;
 	struct ccw_dev_id dev_id;
 	struct dasd_device *base;
@@ -473,15 +473,9 @@
 	if (!base->discipline || !base->discipline->fill_info)
 		return -EINVAL;
 
-	dasd_info = kzalloc(sizeof(struct dasd_information2_t), GFP_KERNEL);
-	if (dasd_info == NULL)
-		return -ENOMEM;
-
 	rc = base->discipline->fill_info(base, dasd_info);
-	if (rc) {
-		kfree(dasd_info);
+	if (rc)
 		return rc;
-	}
 
 	cdev = base->cdev;
 	ccw_device_get_id(cdev, &dev_id);
@@ -516,19 +510,28 @@
 
 	memcpy(dasd_info->type, base->discipline->name, 4);
 
-	spin_lock_irqsave(&block->queue_lock, flags);
+	spin_lock_irqsave(get_ccwdev_lock(base->cdev), flags);
 	list_for_each(l, &base->ccw_queue)
 		dasd_info->chanq_len++;
-	spin_unlock_irqrestore(&block->queue_lock, flags);
+	spin_unlock_irqrestore(get_ccwdev_lock(base->cdev), flags);
+	return 0;
+}
 
-	rc = 0;
-	if (copy_to_user(argp, dasd_info,
-			 ((cmd == (unsigned int) BIODASDINFO2) ?
-			  sizeof(struct dasd_information2_t) :
-			  sizeof(struct dasd_information_t))))
-		rc = -EFAULT;
+static int dasd_ioctl_information(struct dasd_block *block, void __user *argp,
+		size_t copy_size)
+{
+	struct dasd_information2_t *dasd_info;
+	int error;
+
+	dasd_info = kzalloc(sizeof(*dasd_info), GFP_KERNEL);
+	if (!dasd_info)
+		return -ENOMEM;
+
+	error = __dasd_ioctl_information(block, dasd_info);
+	if (!error && copy_to_user(argp, dasd_info, copy_size))
+		error = -EFAULT;
 	kfree(dasd_info);
-	return rc;
+	return error;
 }
 
 /*
@@ -622,10 +625,12 @@
 		rc = dasd_ioctl_check_format(bdev, argp);
 		break;
 	case BIODASDINFO:
-		rc = dasd_ioctl_information(block, cmd, argp);
+		rc = dasd_ioctl_information(block, argp,
+				sizeof(struct dasd_information_t));
 		break;
 	case BIODASDINFO2:
-		rc = dasd_ioctl_information(block, cmd, argp);
+		rc = dasd_ioctl_information(block, argp,
+				sizeof(struct dasd_information2_t));
 		break;
 	case BIODASDPRRD:
 		rc = dasd_ioctl_read_profile(block, argp);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/block/scm_blk.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/block/scm_blk.c
@@ -18,6 +18,7 @@
 #include <linux/genhd.h>
 #include <linux/slab.h>
 #include <linux/list.h>
+#include <linux/io.h>
 #include <asm/eadm.h>
 #include "scm_blk.h"
 
@@ -131,7 +132,7 @@
 
 	for (i = 0; i < nr_requests_per_io && scmrq->request[i]; i++) {
 		msb = &scmrq->aob->msb[i];
-		aidaw = msb->data_addr;
+		aidaw = (u64)phys_to_virt(msb->data_addr);
 
 		if ((msb->flags & MSB_FLAG_IDA) && aidaw &&
 		    IS_ALIGNED(aidaw, PAGE_SIZE))
@@ -196,12 +197,12 @@
 	msb->scm_addr = scmdev->address + ((u64) blk_rq_pos(req) << 9);
 	msb->oc = (rq_data_dir(req) == READ) ? MSB_OC_READ : MSB_OC_WRITE;
 	msb->flags |= MSB_FLAG_IDA;
-	msb->data_addr = (u64) aidaw;
+	msb->data_addr = (u64)virt_to_phys(aidaw);
 
 	rq_for_each_segment(bv, req, iter) {
 		WARN_ON(bv.bv_offset);
 		msb->blk_count += bv.bv_len >> 12;
-		aidaw->data_addr = (u64) page_address(bv.bv_page);
+		aidaw->data_addr = virt_to_phys(page_address(bv.bv_page));
 		aidaw++;
 	}
 
@@ -256,7 +257,8 @@
 	for (i = 0; i < nr_requests_per_io && scmrq->request[i]; i++) {
 		error = blk_mq_rq_to_pdu(scmrq->request[i]);
 		*error = scmrq->error;
-		blk_mq_complete_request(scmrq->request[i]);
+		if (likely(!blk_should_fake_timeout(scmrq->request[i]->q)))
+			blk_mq_complete_request(scmrq->request[i]);
 	}
 
 	atomic_dec(&bdev->queued_reqs);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/char/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/char/Makefile
@@ -34,6 +34,8 @@
 
 obj-$(CONFIG_PCI) += sclp_pci.o
 
+obj-$(subst m,y,$(CONFIG_ZCRYPT)) += sclp_ap.o
+
 obj-$(CONFIG_VMLOGRDR) += vmlogrdr.o
 obj-$(CONFIG_VMCP) += vmcp.o
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/char/keyboard.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/char/keyboard.h
@@ -56,7 +56,7 @@
 kbd_put_queue(struct tty_port *port, int ch)
 {
 	tty_insert_flip_char(port, ch, 0);
-	tty_schedule_flip(port);
+	tty_flip_buffer_push(port);
 }
 
 static inline void
@@ -64,5 +64,5 @@
 {
 	while (*cp)
 		tty_insert_flip_char(port, *cp++, 0);
-	tty_schedule_flip(port);
+	tty_flip_buffer_push(port);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/char/raw3270.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/char/raw3270.h
@@ -211,7 +211,7 @@
 	struct list_head update;
 	unsigned long size;
 	unsigned long len;
-	char string[0];
+	char string[];
 } __attribute__ ((aligned(8)));
 
 static inline struct string *
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/char/sclp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/char/sclp.c
@@ -1208,6 +1208,7 @@
 fail_unregister_reboot_notifier:
 	unregister_reboot_notifier(&sclp_reboot_notifier);
 fail_init_state_uninitialized:
+	list_del(&sclp_state_change_event.list);
 	sclp_init_state = sclp_init_state_uninitialized;
 	free_page((unsigned long) sclp_read_sccb);
 	free_page((unsigned long) sclp_init_sccb);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/char/sclp.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/char/sclp.h
@@ -229,7 +229,7 @@
 #define SCLP_HAS_CPU_INFO	(sclp.facilities & 0x0800000000000000ULL)
 #define SCLP_HAS_CPU_RECONFIG	(sclp.facilities & 0x0400000000000000ULL)
 #define SCLP_HAS_PCI_RECONFIG	(sclp.facilities & 0x0000000040000000ULL)
-
+#define SCLP_HAS_AP_RECONFIG	(sclp.facilities & 0x0000000100000000ULL)
 
 struct gds_subvector {
 	u8	length;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/char/sclp_ap.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/char/sclp_ap.c
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * s390 crypto adapter related sclp functions.
+ *
+ * Copyright IBM Corp. 2020
+ */
+#define KMSG_COMPONENT "sclp_cmd"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
+#include <linux/export.h>
+#include <linux/slab.h>
+#include <asm/sclp.h>
+#include "sclp.h"
+
+#define SCLP_CMDW_CONFIGURE_AP			0x001f0001
+#define SCLP_CMDW_DECONFIGURE_AP		0x001e0001
+
+struct ap_cfg_sccb {
+	struct sccb_header header;
+} __packed;
+
+static int do_ap_configure(sclp_cmdw_t cmd, u32 apid)
+{
+	struct ap_cfg_sccb *sccb;
+	int rc;
+
+	if (!SCLP_HAS_AP_RECONFIG)
+		return -EOPNOTSUPP;
+
+	sccb = (struct ap_cfg_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
+	if (!sccb)
+		return -ENOMEM;
+
+	sccb->header.length = PAGE_SIZE;
+	cmd |= (apid & 0xFF) << 8;
+	rc = sclp_sync_request(cmd, sccb);
+	if (rc)
+		goto out;
+	switch (sccb->header.response_code) {
+	case 0x0020: case 0x0120: case 0x0440: case 0x0450:
+		break;
+	default:
+		pr_warn("configure AP adapter %u failed: cmd=0x%08x response=0x%04x\n",
+			apid, cmd, sccb->header.response_code);
+		rc = -EIO;
+		break;
+	}
+out:
+	free_page((unsigned long) sccb);
+	return rc;
+}
+
+int sclp_ap_configure(u32 apid)
+{
+	return do_ap_configure(SCLP_CMDW_CONFIGURE_AP, apid);
+}
+EXPORT_SYMBOL(sclp_ap_configure);
+
+int sclp_ap_deconfigure(u32 apid)
+{
+	return do_ap_configure(SCLP_CMDW_DECONFIGURE_AP, apid);
+}
+EXPORT_SYMBOL(sclp_ap_deconfigure);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/char/sclp_early.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/char/sclp_early.c
@@ -40,13 +40,14 @@
 	sclp.has_gisaf = !!(sccb->fac118 & 0x08);
 	sclp.has_hvs = !!(sccb->fac119 & 0x80);
 	sclp.has_kss = !!(sccb->fac98 & 0x01);
-	sclp.has_sipl = !!(sccb->cbl & 0x4000);
 	if (sccb->fac85 & 0x02)
 		S390_lowcore.machine_flags |= MACHINE_FLAG_ESOP;
 	if (sccb->fac91 & 0x40)
 		S390_lowcore.machine_flags |= MACHINE_FLAG_TLB_GUEST;
 	if (sccb->cpuoff > 134)
 		sclp.has_diag318 = !!(sccb->byte_134 & 0x80);
+	if (sccb->cpuoff > 137)
+		sclp.has_sipl = !!(sccb->cbl & 0x4000);
 	sclp.rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2;
 	sclp.rzm = sccb->rnsize ? sccb->rnsize : sccb->rnsize2;
 	sclp.rzm <<= 20;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/char/sclp_pci.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/char/sclp_pci.c
@@ -39,7 +39,7 @@
 	u8 atype;
 	u32 fh;
 	u32 fid;
-	u8 data[0];
+	u8 data[];
 } __packed;
 
 struct err_notify_sccb {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/char/sclp_sd.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/char/sclp_sd.c
@@ -319,8 +319,14 @@
 			  &esize);
 	if (rc) {
 		/* Cancel running request if interrupted */
-		if (rc == -ERESTARTSYS)
-			sclp_sd_sync(page, SD_EQ_HALT, di, 0, 0, NULL, NULL);
+		if (rc == -ERESTARTSYS) {
+			if (sclp_sd_sync(page, SD_EQ_HALT, di, 0, 0, NULL, NULL)) {
+				pr_warn("Could not stop Store Data request - leaking at least %zu bytes\n",
+					(size_t)dsize * PAGE_SIZE);
+				data = NULL;
+				asce = 0;
+			}
+		}
 		vfree(data);
 		goto out;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/char/sclp_vt220.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/char/sclp_vt220.c
@@ -35,8 +35,8 @@
 #define SCLP_VT220_MINOR		65
 #define SCLP_VT220_DRIVER_NAME		"sclp_vt220"
 #define SCLP_VT220_DEVICE_NAME		"ttysclp"
-#define SCLP_VT220_CONSOLE_NAME		"ttyS"
-#define SCLP_VT220_CONSOLE_INDEX	1	/* console=ttyS1 */
+#define SCLP_VT220_CONSOLE_NAME		"ttysclp"
+#define SCLP_VT220_CONSOLE_INDEX	0	/* console=ttysclp0 */
 
 /* Representation of a single write request */
 struct sclp_vt220_request {
@@ -325,7 +325,7 @@
 	buffer = (void *) ((addr_t) sccb + sccb->header.length);
 
 	if (convertlf) {
-		/* Perform Linefeed conversion (0x0a -> 0x0a 0x0d)*/
+		/* Perform Linefeed conversion (0x0a -> 0x0d 0x0a)*/
 		for (from=0, to=0;
 		     (from < count) && (to < sclp_vt220_space_left(request));
 		     from++) {
@@ -334,8 +334,8 @@
 			/* Perform conversion */
 			if (c == 0x0a) {
 				if (to + 1 < sclp_vt220_space_left(request)) {
-					((unsigned char *) buffer)[to++] = c;
 					((unsigned char *) buffer)[to++] = 0x0d;
+					((unsigned char *) buffer)[to++] = c;
 				} else
 					break;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/char/tape_std.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/char/tape_std.c
@@ -53,7 +53,6 @@
 tape_std_assign(struct tape_device *device)
 {
 	int                  rc;
-	struct timer_list    timeout;
 	struct tape_request *request;
 
 	request = tape_alloc_request(2, 11);
@@ -70,7 +69,7 @@
 	 * So we set up a timeout for this call.
 	 */
 	timer_setup(&request->timer, tape_std_assign_timeout, 0);
-	mod_timer(&timeout, jiffies + 2 * HZ);
+	mod_timer(&request->timer, jiffies + msecs_to_jiffies(2000));
 
 	rc = tape_do_io_interruptible(device, request);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/char/zcore.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/char/zcore.c
@@ -53,6 +53,7 @@
 static struct dentry *zcore_hsa_file;
 static struct ipl_parameter_block *zcore_ipl_block;
 
+static DEFINE_MUTEX(hsa_buf_mutex);
 static char hsa_buf[PAGE_SIZE] __aligned(PAGE_SIZE);
 
 /*
@@ -69,19 +70,24 @@
 	if (!hsa_available)
 		return -ENODATA;
 
+	mutex_lock(&hsa_buf_mutex);
 	while (count) {
 		if (sclp_sdias_copy(hsa_buf, src / PAGE_SIZE + 2, 1)) {
 			TRACE("sclp_sdias_copy() failed\n");
+			mutex_unlock(&hsa_buf_mutex);
 			return -EIO;
 		}
 		offset = src % PAGE_SIZE;
 		bytes = min(PAGE_SIZE - offset, count);
-		if (copy_to_user(dest, hsa_buf + offset, bytes))
+		if (copy_to_user(dest, hsa_buf + offset, bytes)) {
+			mutex_unlock(&hsa_buf_mutex);
 			return -EFAULT;
+		}
 		src += bytes;
 		dest += bytes;
 		count -= bytes;
 	}
+	mutex_unlock(&hsa_buf_mutex);
 	return 0;
 }
 
@@ -99,9 +105,11 @@
 	if (!hsa_available)
 		return -ENODATA;
 
+	mutex_lock(&hsa_buf_mutex);
 	while (count) {
 		if (sclp_sdias_copy(hsa_buf, src / PAGE_SIZE + 2, 1)) {
 			TRACE("sclp_sdias_copy() failed\n");
+			mutex_unlock(&hsa_buf_mutex);
 			return -EIO;
 		}
 		offset = src % PAGE_SIZE;
@@ -111,6 +119,7 @@
 		dest += bytes;
 		count -= bytes;
 	}
+	mutex_unlock(&hsa_buf_mutex);
 	return 0;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/cio/airq.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/cio/airq.c
@@ -105,16 +105,12 @@
 	return IRQ_HANDLED;
 }
 
-static struct irqaction airq_interrupt = {
-	.name	 = "AIO",
-	.handler = do_airq_interrupt,
-};
-
 void __init init_airq_interrupts(void)
 {
 	irq_set_chip_and_handler(THIN_INTERRUPT,
 				 &dummy_irq_chip, handle_percpu_irq);
-	setup_irq(THIN_INTERRUPT, &airq_interrupt);
+	if (request_irq(THIN_INTERRUPT, do_airq_interrupt, 0, "AIO", NULL))
+		panic("Failed to register AIO interrupt\n");
 }
 
 static inline unsigned long iv_size(unsigned long bits)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/cio/blacklist.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/cio/blacklist.c
@@ -303,8 +303,10 @@
 cio_ignore_proc_seq_next(struct seq_file *s, void *it, loff_t *offset)
 {
 	struct ccwdev_iter *iter;
+	loff_t p = *offset;
 
-	if (*offset >= (__MAX_SUBCHANNEL + 1) * (__MAX_SSID + 1))
+	(*offset)++;
+	if (p >= (__MAX_SUBCHANNEL + 1) * (__MAX_SSID + 1))
 		return NULL;
 	iter = it;
 	if (iter->devno == __MAX_SUBCHANNEL) {
@@ -314,7 +316,6 @@
 			return NULL;
 	} else
 		iter->devno++;
-	(*offset)++;
 	return iter;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/cio/chp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/cio/chp.c
@@ -255,6 +255,9 @@
 	if (!num_args)
 		return count;
 
+	/* Wait until previous actions have settled. */
+	css_wait_for_slow_path();
+
 	if (!strncasecmp(cmd, "on", 2) || !strcmp(cmd, "1")) {
 		mutex_lock(&cp->lock);
 		error = s390_vary_chpid(cp->chpid, 1);
@@ -643,7 +646,8 @@
 	if (time_after(jiffies, chp_info_expires)) {
 		/* Data is too old, update. */
 		rc = sclp_chp_read_info(&chp_info);
-		chp_info_expires = jiffies + CHP_INFO_UPDATE_INTERVAL ;
+		if (!rc)
+			chp_info_expires = jiffies + CHP_INFO_UPDATE_INTERVAL;
 	}
 	mutex_unlock(&info_lock);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/cio/chsc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/cio/chsc.c
@@ -753,8 +753,6 @@
 {
 	struct channel_path *chp = chpid_to_chp(chpid);
 
-	/* Wait until previous actions have settled. */
-	css_wait_for_slow_path();
 	/*
 	 * Redo PathVerification on the devices the chpid connects to
 	 */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/cio/cio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/cio/cio.c
@@ -563,16 +563,12 @@
 	return IRQ_HANDLED;
 }
 
-static struct irqaction io_interrupt = {
-	.name	 = "I/O",
-	.handler = do_cio_interrupt,
-};
-
 void __init init_cio_interrupts(void)
 {
 	irq_set_chip_and_handler(IO_INTERRUPT,
 				 &dummy_irq_chip, handle_percpu_irq);
-	setup_irq(IO_INTERRUPT, &io_interrupt);
+	if (request_irq(IO_INTERRUPT, do_cio_interrupt, 0, "I/O", NULL))
+		panic("Failed to register I/O interrupt\n");
 }
 
 #ifdef CONFIG_CCW_CONSOLE
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/cio/css.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/cio/css.c
@@ -426,9 +426,26 @@
 }
 static DEVICE_ATTR_RO(pimpampom);
 
+static ssize_t dev_busid_show(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	struct subchannel *sch = to_subchannel(dev);
+	struct pmcw *pmcw = &sch->schib.pmcw;
+
+	if ((pmcw->st == SUBCHANNEL_TYPE_IO && pmcw->dnv) ||
+	    (pmcw->st == SUBCHANNEL_TYPE_MSG && pmcw->w))
+		return sysfs_emit(buf, "0.%x.%04x\n", sch->schid.ssid,
+				  pmcw->dev);
+	else
+		return sysfs_emit(buf, "none\n");
+}
+static DEVICE_ATTR_RO(dev_busid);
+
 static struct attribute *io_subchannel_type_attrs[] = {
 	&dev_attr_chpids.attr,
 	&dev_attr_pimpampom.attr,
+	&dev_attr_dev_busid.attr,
 	NULL,
 };
 ATTRIBUTE_GROUPS(io_subchannel_type);
@@ -677,6 +694,11 @@
 		rc = css_evaluate_known_subchannel(sch, 1);
 		if (rc == -EAGAIN)
 			css_schedule_eval(sch->schid);
+		/*
+		 * The loop might take long time for platforms with lots of
+		 * known devices. Allow scheduling here.
+		 */
+		cond_resched();
 	}
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/cio/device.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/cio/device.c
@@ -849,8 +849,10 @@
 	 * Now we know this subchannel will stay, we can throw
 	 * our delayed uevent.
 	 */
-	dev_set_uevent_suppress(&sch->dev, 0);
-	kobject_uevent(&sch->dev.kobj, KOBJ_ADD);
+	if (dev_get_uevent_suppress(&sch->dev)) {
+		dev_set_uevent_suppress(&sch->dev, 0);
+		kobject_uevent(&sch->dev.kobj, KOBJ_ADD);
+	}
 	/* make it known to the system */
 	ret = ccw_device_add(cdev);
 	if (ret) {
@@ -1058,8 +1060,11 @@
 		 * Throw the delayed uevent for the subchannel, register
 		 * the ccw_device and exit.
 		 */
-		dev_set_uevent_suppress(&sch->dev, 0);
-		kobject_uevent(&sch->dev.kobj, KOBJ_ADD);
+		if (dev_get_uevent_suppress(&sch->dev)) {
+			/* should always be the case for the console */
+			dev_set_uevent_suppress(&sch->dev, 0);
+			kobject_uevent(&sch->dev.kobj, KOBJ_ADD);
+		}
 		cdev = sch_get_cdev(sch);
 		rc = ccw_device_add(cdev);
 		if (rc) {
@@ -1380,6 +1385,7 @@
 enum io_sch_action {
 	IO_SCH_UNREG,
 	IO_SCH_ORPH_UNREG,
+	IO_SCH_UNREG_CDEV,
 	IO_SCH_ATTACH,
 	IO_SCH_UNREG_ATTACH,
 	IO_SCH_ORPH_ATTACH,
@@ -1412,7 +1418,7 @@
 	}
 	if ((sch->schib.pmcw.pam & sch->opm) == 0) {
 		if (ccw_device_notify(cdev, CIO_NO_PATH) != NOTIFY_OK)
-			return IO_SCH_UNREG;
+			return IO_SCH_UNREG_CDEV;
 		return IO_SCH_DISC;
 	}
 	if (device_is_disconnected(cdev))
@@ -1474,6 +1480,7 @@
 	case IO_SCH_ORPH_ATTACH:
 		ccw_device_set_disconnected(cdev);
 		break;
+	case IO_SCH_UNREG_CDEV:
 	case IO_SCH_UNREG_ATTACH:
 	case IO_SCH_UNREG:
 		if (!cdev)
@@ -1507,6 +1514,7 @@
 		if (rc)
 			goto out;
 		break;
+	case IO_SCH_UNREG_CDEV:
 	case IO_SCH_UNREG_ATTACH:
 		spin_lock_irqsave(sch->lock, flags);
 		if (cdev->private->flags.resuming) {
@@ -1659,10 +1667,10 @@
 	struct io_subchannel_private *io_priv = to_io_private(sch);
 
 	set_io_private(sch, NULL);
-	put_device(&sch->dev);
-	put_device(&cdev->dev);
 	dma_free_coherent(&sch->dev, sizeof(*io_priv->dma_area),
 			  io_priv->dma_area, io_priv->dma_area_dma);
+	put_device(&sch->dev);
+	put_device(&cdev->dev);
 	kfree(io_priv);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/cio/device_ops.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/cio/device_ops.c
@@ -635,7 +635,7 @@
  * @mask: mask of paths to use
  *
  * Return the number of 64K-bytes blocks all paths at least support
- * for a transport command. Return values <= 0 indicate failures.
+ * for a transport command. Return value 0 indicates failure.
  */
 int ccw_device_get_mdc(struct ccw_device *cdev, u8 mask)
 {
@@ -717,13 +717,23 @@
  */
 void *ccw_device_dma_zalloc(struct ccw_device *cdev, size_t size)
 {
-	return cio_gp_dma_zalloc(cdev->private->dma_pool, &cdev->dev, size);
+	void *addr;
+
+	if (!get_device(&cdev->dev))
+		return NULL;
+	addr = cio_gp_dma_zalloc(cdev->private->dma_pool, &cdev->dev, size);
+	if (IS_ERR_OR_NULL(addr))
+		put_device(&cdev->dev);
+	return addr;
 }
 EXPORT_SYMBOL(ccw_device_dma_zalloc);
 
 void ccw_device_dma_free(struct ccw_device *cdev, void *cpu_addr, size_t size)
 {
+	if (!cpu_addr)
+		return;
 	cio_gp_dma_free(cdev->private->dma_pool, cpu_addr, size);
+	put_device(&cdev->dev);
 }
 EXPORT_SYMBOL(ccw_device_dma_free);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/cio/idset.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/cio/idset.c
@@ -13,23 +13,24 @@
 struct idset {
 	int num_ssid;
 	int num_id;
-	unsigned long bitmap[0];
+	unsigned long bitmap[];
 };
 
-static inline unsigned long bitmap_size(int num_ssid, int num_id)
+static inline unsigned long idset_bitmap_size(int num_ssid, int num_id)
 {
-	return BITS_TO_LONGS(num_ssid * num_id) * sizeof(unsigned long);
+	return bitmap_size(size_mul(num_ssid, num_id));
 }
 
 static struct idset *idset_new(int num_ssid, int num_id)
 {
 	struct idset *set;
 
-	set = vmalloc(sizeof(struct idset) + bitmap_size(num_ssid, num_id));
+	set = vmalloc(sizeof(struct idset) +
+		      idset_bitmap_size(num_ssid, num_id));
 	if (set) {
 		set->num_ssid = num_ssid;
 		set->num_id = num_id;
-		memset(set->bitmap, 0, bitmap_size(num_ssid, num_id));
+		memset(set->bitmap, 0, idset_bitmap_size(num_ssid, num_id));
 	}
 	return set;
 }
@@ -41,7 +42,8 @@
 
 void idset_fill(struct idset *set)
 {
-	memset(set->bitmap, 0xff, bitmap_size(set->num_ssid, set->num_id));
+	memset(set->bitmap, 0xff,
+	       idset_bitmap_size(set->num_ssid, set->num_id));
 }
 
 static inline void idset_add(struct idset *set, int ssid, int id)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/cio/qdio.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/cio/qdio.h
@@ -82,21 +82,22 @@
 #define QDIO_SIGA_WRITE		0x00
 #define QDIO_SIGA_READ		0x01
 #define QDIO_SIGA_SYNC		0x02
+#define QDIO_SIGA_WRITEM	0x03
 #define QDIO_SIGA_WRITEQ	0x04
 #define QDIO_SIGA_QEBSM_FLAG	0x80
 
 static inline int do_sqbs(u64 token, unsigned char state, int queue,
 			  int *start, int *count)
 {
-	register unsigned long _ccq asm ("0") = *count;
-	register unsigned long _token asm ("1") = token;
 	unsigned long _queuestart = ((unsigned long)queue << 32) | *start;
+	unsigned long _ccq = *count;
 
 	asm volatile(
-		"	.insn	rsy,0xeb000000008A,%1,0,0(%2)"
-		: "+d" (_ccq), "+d" (_queuestart)
-		: "d" ((unsigned long)state), "d" (_token)
-		: "memory", "cc");
+		"	lgr	1,%[token]\n"
+		"	.insn	rsy,0xeb000000008a,%[qs],%[ccq],0(%[state])"
+		: [ccq] "+&d" (_ccq), [qs] "+&d" (_queuestart)
+		: [state] "a" ((unsigned long)state), [token] "d" (token)
+		: "memory", "cc", "1");
 	*count = _ccq & 0xff;
 	*start = _queuestart & 0xff;
 
@@ -106,16 +107,17 @@
 static inline int do_eqbs(u64 token, unsigned char *state, int queue,
 			  int *start, int *count, int ack)
 {
-	register unsigned long _ccq asm ("0") = *count;
-	register unsigned long _token asm ("1") = token;
 	unsigned long _queuestart = ((unsigned long)queue << 32) | *start;
 	unsigned long _state = (unsigned long)ack << 63;
+	unsigned long _ccq = *count;
 
 	asm volatile(
-		"	.insn	rrf,0xB99c0000,%1,%2,0,0"
-		: "+d" (_ccq), "+d" (_queuestart), "+d" (_state)
-		: "d" (_token)
-		: "memory", "cc");
+		"	lgr	1,%[token]\n"
+		"	.insn	rrf,0xb99c0000,%[qs],%[state],%[ccq],0"
+		: [ccq] "+&d" (_ccq), [qs] "+&d" (_queuestart),
+		  [state] "+&d" (_state)
+		: [token] "d" (token)
+		: "memory", "cc", "1");
 	*count = _ccq & 0xff;
 	*start = _queuestart & 0xff;
 	*state = _state & 0xff;
@@ -372,7 +374,6 @@
 extern u64 last_ai_time;
 
 /* prototypes for thin interrupt */
-void qdio_setup_thinint(struct qdio_irq *irq_ptr);
 int qdio_establish_thinint(struct qdio_irq *irq_ptr);
 void qdio_shutdown_thinint(struct qdio_irq *irq_ptr);
 void tiqdio_add_input_queues(struct qdio_irq *irq_ptr);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/cio/qdio_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/cio/qdio_main.c
@@ -31,38 +31,41 @@
 MODULE_LICENSE("GPL");
 
 static inline int do_siga_sync(unsigned long schid,
-			       unsigned int out_mask, unsigned int in_mask,
+			       unsigned long out_mask, unsigned long in_mask,
 			       unsigned int fc)
 {
-	register unsigned long __fc asm ("0") = fc;
-	register unsigned long __schid asm ("1") = schid;
-	register unsigned long out asm ("2") = out_mask;
-	register unsigned long in asm ("3") = in_mask;
 	int cc;
 
 	asm volatile(
+		"	lgr	0,%[fc]\n"
+		"	lgr	1,%[schid]\n"
+		"	lgr	2,%[out]\n"
+		"	lgr	3,%[in]\n"
 		"	siga	0\n"
-		"	ipm	%0\n"
-		"	srl	%0,28\n"
-		: "=d" (cc)
-		: "d" (__fc), "d" (__schid), "d" (out), "d" (in) : "cc");
+		"	ipm	%[cc]\n"
+		"	srl	%[cc],28\n"
+		: [cc] "=&d" (cc)
+		: [fc] "d" (fc), [schid] "d" (schid),
+		  [out] "d" (out_mask), [in] "d" (in_mask)
+		: "cc", "0", "1", "2", "3");
 	return cc;
 }
 
-static inline int do_siga_input(unsigned long schid, unsigned int mask,
-				unsigned int fc)
+static inline int do_siga_input(unsigned long schid, unsigned long mask,
+				unsigned long fc)
 {
-	register unsigned long __fc asm ("0") = fc;
-	register unsigned long __schid asm ("1") = schid;
-	register unsigned long __mask asm ("2") = mask;
 	int cc;
 
 	asm volatile(
+		"	lgr	0,%[fc]\n"
+		"	lgr	1,%[schid]\n"
+		"	lgr	2,%[mask]\n"
 		"	siga	0\n"
-		"	ipm	%0\n"
-		"	srl	%0,28\n"
-		: "=d" (cc)
-		: "d" (__fc), "d" (__schid), "d" (__mask) : "cc");
+		"	ipm	%[cc]\n"
+		"	srl	%[cc],28\n"
+		: [cc] "=&d" (cc)
+		: [fc] "d" (fc), [schid] "d" (schid), [mask] "d" (mask)
+		: "cc", "0", "1", "2");
 	return cc;
 }
 
@@ -78,23 +81,24 @@
  * Note: For IQDC unicast queues only the highest priority queue is processed.
  */
 static inline int do_siga_output(unsigned long schid, unsigned long mask,
-				 unsigned int *bb, unsigned int fc,
+				 unsigned int *bb, unsigned long fc,
 				 unsigned long aob)
 {
-	register unsigned long __fc asm("0") = fc;
-	register unsigned long __schid asm("1") = schid;
-	register unsigned long __mask asm("2") = mask;
-	register unsigned long __aob asm("3") = aob;
 	int cc;
 
 	asm volatile(
+		"	lgr	0,%[fc]\n"
+		"	lgr	1,%[schid]\n"
+		"	lgr	2,%[mask]\n"
+		"	lgr	3,%[aob]\n"
 		"	siga	0\n"
-		"	ipm	%0\n"
-		"	srl	%0,28\n"
-		: "=d" (cc), "+d" (__fc), "+d" (__aob)
-		: "d" (__schid), "d" (__mask)
-		: "cc");
-	*bb = __fc >> 31;
+		"	lgr	%[fc],0\n"
+		"	ipm	%[cc]\n"
+		"	srl	%[cc],28\n"
+		: [cc] "=&d" (cc), [fc] "+&d" (fc)
+		: [schid] "d" (schid), [mask] "d" (mask), [aob] "d" (aob)
+		: "cc", "0", "1", "2", "3");
+	*bb = fc >> 31;
 	return cc;
 }
 
@@ -310,18 +314,19 @@
 		return qdio_siga_sync(q, q->mask, 0);
 }
 
-static int qdio_siga_output(struct qdio_q *q, unsigned int *busy_bit,
-	unsigned long aob)
+static int qdio_siga_output(struct qdio_q *q, unsigned int count,
+			    unsigned int *busy_bit, unsigned long aob)
 {
 	unsigned long schid = *((u32 *) &q->irq_ptr->schid);
 	unsigned int fc = QDIO_SIGA_WRITE;
 	u64 start_time = 0;
 	int retries = 0, cc;
-	unsigned long laob = 0;
 
-	if (aob) {
-		fc = QDIO_SIGA_WRITEQ;
-		laob = aob;
+	if (queue_type(q) == QDIO_IQDIO_QFMT && !multicast_outbound(q)) {
+		if (count > 1)
+			fc = QDIO_SIGA_WRITEM;
+		else if (aob)
+			fc = QDIO_SIGA_WRITEQ;
 	}
 
 	if (is_qebsm(q)) {
@@ -329,7 +334,7 @@
 		fc |= QDIO_SIGA_QEBSM_FLAG;
 	}
 again:
-	cc = do_siga_output(schid, q->mask, busy_bit, fc, laob);
+	cc = do_siga_output(schid, q->mask, busy_bit, fc, aob);
 
 	/* hipersocket busy condition */
 	if (unlikely(*busy_bit)) {
@@ -781,7 +786,8 @@
 	return count;
 }
 
-static int qdio_kick_outbound_q(struct qdio_q *q, unsigned long aob)
+static int qdio_kick_outbound_q(struct qdio_q *q, unsigned int count,
+				unsigned long aob)
 {
 	int retries = 0, cc;
 	unsigned int busy_bit;
@@ -793,7 +799,7 @@
 retry:
 	qperf_inc(q, siga_write);
 
-	cc = qdio_siga_output(q, &busy_bit, aob);
+	cc = qdio_siga_output(q, count, &busy_bit, aob);
 	switch (cc) {
 	case 0:
 		break;
@@ -1526,7 +1532,7 @@
  * @count: how many buffers are filled
  */
 static int handle_outbound(struct qdio_q *q, unsigned int callflags,
-			   int bufnr, int count)
+			   unsigned int bufnr, unsigned int count)
 {
 	const unsigned int scan_threshold = q->irq_ptr->scan_threshold;
 	unsigned char state = 0;
@@ -1549,13 +1555,10 @@
 	if (queue_type(q) == QDIO_IQDIO_QFMT) {
 		unsigned long phys_aob = 0;
 
-		/* One SIGA-W per buffer required for unicast HSI */
-		WARN_ON_ONCE(count > 1 && !multicast_outbound(q));
-
-		if (q->u.out.use_cq)
+		if (q->u.out.use_cq && count == 1)
 			phys_aob = qdio_aob_for_buffer(&q->u.out, bufnr);
 
-		rc = qdio_kick_outbound_q(q, phys_aob);
+		rc = qdio_kick_outbound_q(q, count, phys_aob);
 	} else if (need_siga_sync(q)) {
 		rc = qdio_siga_sync_q(q);
 	} else if (count < QDIO_MAX_BUFFERS_PER_Q &&
@@ -1564,7 +1567,7 @@
 		/* The previous buffer is not processed yet, tack on. */
 		qperf_inc(q, fast_requeue);
 	} else {
-		rc = qdio_kick_outbound_q(q, 0);
+		rc = qdio_kick_outbound_q(q, count, 0);
 	}
 
 	/* Let drivers implement their own completion scanning: */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/cio/qdio_setup.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/cio/qdio_setup.c
@@ -8,6 +8,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/export.h>
+#include <linux/io.h>
 #include <asm/qdio.h>
 
 #include "cio.h"
@@ -207,7 +208,7 @@
 
 	/* fill in sl */
 	for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++)
-		q->sl->element[j].sbal = (unsigned long)q->sbal[j];
+		q->sl->element[j].sbal = virt_to_phys(q->sbal[j]);
 }
 
 static void setup_queues(struct qdio_irq *irq_ptr,
@@ -478,7 +479,6 @@
 	setup_queues(irq_ptr, init_data);
 
 	setup_qib(irq_ptr, init_data);
-	qdio_setup_thinint(irq_ptr);
 	set_impl_params(irq_ptr, init_data->qib_param_field_format,
 			init_data->qib_param_field,
 			init_data->input_slib_elements,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/cio/qdio_thinint.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/cio/qdio_thinint.c
@@ -268,17 +268,19 @@
 
 int qdio_establish_thinint(struct qdio_irq *irq_ptr)
 {
+	int rc;
+
 	if (!is_thinint_irq(irq_ptr))
 		return 0;
-	return set_subchannel_ind(irq_ptr, 0);
-}
 
-void qdio_setup_thinint(struct qdio_irq *irq_ptr)
-{
-	if (!is_thinint_irq(irq_ptr))
-		return;
 	irq_ptr->dsci = get_indicator();
 	DBF_HEX(&irq_ptr->dsci, sizeof(void *));
+
+	rc = set_subchannel_ind(irq_ptr, 0);
+	if (rc)
+		put_indicator(irq_ptr->dsci);
+
+	return rc;
 }
 
 void qdio_shutdown_thinint(struct qdio_irq *irq_ptr)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/cio/trace.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/cio/trace.h
@@ -50,7 +50,7 @@
 		__entry->devno = schib->pmcw.dev;
 		__entry->schib = *schib;
 		__entry->pmcw_ena = schib->pmcw.ena;
-		__entry->pmcw_st = schib->pmcw.ena;
+		__entry->pmcw_st = schib->pmcw.st;
 		__entry->pmcw_dnv = schib->pmcw.dnv;
 		__entry->pmcw_dev = schib->pmcw.dev;
 		__entry->pmcw_lpm = schib->pmcw.lpm;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/cio/vfio_ccw_cp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/cio/vfio_ccw_cp.c
@@ -636,6 +636,10 @@
 {
 	int ret;
 
+	/* this is an error in the caller */
+	if (cp->initialized)
+		return -EBUSY;
+
 	/*
 	 * XXX:
 	 * Only support prefetch enable mode now.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/cio/vfio_ccw_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/cio/vfio_ccw_drv.c
@@ -83,6 +83,7 @@
 	struct vfio_ccw_private *private;
 	struct irb *irb;
 	bool is_final;
+	bool cp_is_finished = false;
 
 	private = container_of(work, struct vfio_ccw_private, io_work);
 	irb = &private->irb;
@@ -91,14 +92,21 @@
 		     (SCSW_ACTL_DEVACT | SCSW_ACTL_SCHACT));
 	if (scsw_is_solicited(&irb->scsw)) {
 		cp_update_scsw(&private->cp, &irb->scsw);
-		if (is_final && private->state == VFIO_CCW_STATE_CP_PENDING)
+		if (is_final && private->state == VFIO_CCW_STATE_CP_PENDING) {
 			cp_free(&private->cp);
+			cp_is_finished = true;
+		}
 	}
 	mutex_lock(&private->io_mutex);
 	memcpy(private->io_region->irb_area, irb, sizeof(*irb));
 	mutex_unlock(&private->io_mutex);
 
-	if (private->mdev && is_final)
+	/*
+	 * Reset to IDLE only if processing of a channel program
+	 * has finished. Do not overwrite a possible processing
+	 * state if the final interrupt was for HSCH or CSCH.
+	 */
+	if (private->mdev && cp_is_finished)
 		private->state = VFIO_CCW_STATE_IDLE;
 
 	if (private->io_trigger)
@@ -167,6 +175,11 @@
 	if (ret)
 		goto out_disable;
 
+	if (dev_get_uevent_suppress(&sch->dev)) {
+		dev_set_uevent_suppress(&sch->dev, 0);
+		kobject_uevent(&sch->dev.kobj, KOBJ_ADD);
+	}
+
 	VFIO_CCW_MSG_EVENT(4, "bound to subchannel %x.%x.%04x\n",
 			   sch->schid.cssid, sch->schid.ssid,
 			   sch->schid.sch_no);
@@ -234,19 +247,11 @@
 	if (work_pending(&sch->todo_work))
 		goto out_unlock;
 
-	if (cio_update_schib(sch)) {
-		vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_NOT_OPER);
-		rc = 0;
-		goto out_unlock;
-	}
-
-	private = dev_get_drvdata(&sch->dev);
-	if (private->state == VFIO_CCW_STATE_NOT_OPER) {
-		private->state = private->mdev ? VFIO_CCW_STATE_IDLE :
-				 VFIO_CCW_STATE_STANDBY;
-	}
 	rc = 0;
 
+	if (cio_update_schib(sch))
+		vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_NOT_OPER);
+
 out_unlock:
 	spin_unlock_irqrestore(sch->lock, flags);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/cio/vfio_ccw_ops.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/cio/vfio_ccw_ops.c
@@ -506,7 +506,7 @@
 		if (ret)
 			return ret;
 
-		return copy_to_user((void __user *)arg, &info, minsz);
+		return copy_to_user((void __user *)arg, &info, minsz) ? -EFAULT : 0;
 	}
 	case VFIO_DEVICE_GET_REGION_INFO:
 	{
@@ -524,7 +524,7 @@
 		if (ret)
 			return ret;
 
-		return copy_to_user((void __user *)arg, &info, minsz);
+		return copy_to_user((void __user *)arg, &info, minsz) ? -EFAULT : 0;
 	}
 	case VFIO_DEVICE_GET_IRQ_INFO:
 	{
@@ -545,7 +545,7 @@
 		if (info.count == -1)
 			return -EINVAL;
 
-		return copy_to_user((void __user *)arg, &info, minsz);
+		return copy_to_user((void __user *)arg, &info, minsz) ? -EFAULT : 0;
 	}
 	case VFIO_DEVICE_SET_IRQS:
 	{
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/crypto/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/crypto/Makefile
@@ -7,7 +7,8 @@
 obj-$(subst m,y,$(CONFIG_ZCRYPT)) += ap.o
 # zcrypt_api.o and zcrypt_msgtype*.o depend on ap.o
 zcrypt-objs := zcrypt_api.o zcrypt_card.o zcrypt_queue.o
-zcrypt-objs += zcrypt_msgtype6.o zcrypt_msgtype50.o zcrypt_ccamisc.o
+zcrypt-objs += zcrypt_msgtype6.o zcrypt_msgtype50.o
+zcrypt-objs += zcrypt_ccamisc.o zcrypt_ep11misc.o
 obj-$(CONFIG_ZCRYPT) += zcrypt.o
 # adapter drivers depend on ap.o and zcrypt.o
 obj-$(CONFIG_ZCRYPT) += zcrypt_cex2c.o zcrypt_cex2a.o zcrypt_cex4.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/crypto/ap_bus.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/crypto/ap_bus.c
@@ -18,13 +18,13 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/err.h>
+#include <linux/freezer.h>
 #include <linux/interrupt.h>
 #include <linux/workqueue.h>
 #include <linux/slab.h>
 #include <linux/notifier.h>
 #include <linux/kthread.h>
 #include <linux/mutex.h>
-#include <linux/suspend.h>
 #include <asm/airq.h>
 #include <linux/atomic.h>
 #include <asm/isc.h>
@@ -60,10 +60,15 @@
 module_param_named(aqmask, aqm_str, charp, 0440);
 MODULE_PARM_DESC(aqmask, "AP bus domain mask.");
 
+atomic_t ap_max_msg_size = ATOMIC_INIT(AP_DEFAULT_MAX_MSG_SIZE);
+EXPORT_SYMBOL(ap_max_msg_size);
+
 static struct device *ap_root_device;
 
-DEFINE_SPINLOCK(ap_list_lock);
-LIST_HEAD(ap_card_list);
+/* Hashtable of all queue devices on the AP bus */
+DEFINE_HASHTABLE(ap_queues, 8);
+/* lock used for the ap_queues hashtable */
+DEFINE_SPINLOCK(ap_queues_lock);
 
 /* Default permissions (ioctl, card and domain masking) */
 struct ap_perms ap_perms;
@@ -71,8 +76,7 @@
 DEFINE_MUTEX(ap_perms_mutex);
 EXPORT_SYMBOL(ap_perms_mutex);
 
-static struct ap_config_info *ap_configuration;
-static bool initialised;
+static struct ap_config_info *ap_qci_info;
 
 /*
  * AP bus related debug feature things.
@@ -91,7 +95,7 @@
  * Tasklet & timer for AP request polling and interrupts
  */
 static void ap_tasklet_fn(unsigned long);
-static DECLARE_TASKLET(ap_tasklet, ap_tasklet_fn, 0);
+static DECLARE_TASKLET_OLD(ap_tasklet, ap_tasklet_fn);
 static DECLARE_WAIT_QUEUE_HEAD(ap_poll_wait);
 static struct task_struct *ap_poll_kthread;
 static DEFINE_MUTEX(ap_poll_thread_mutex);
@@ -103,16 +107,11 @@
  */
 static unsigned long long poll_timeout = 250000;
 
-/* Suspend flag */
-static int ap_suspend_flag;
-/* Maximum domain id */
-static int ap_max_domain_id;
-/*
- * Flag to check if domain was set through module parameter domain=. This is
- * important when supsend and resume is done in a z/VM environment where the
- * domain might change.
- */
-static int user_set_domain;
+/* Maximum domain id, if not given via qci */
+static int ap_max_domain_id = 15;
+/* Maximum adapter id, if not given via qci */
+static int ap_max_adapter_id = 63;
+
 static struct bus_type ap_bus_type;
 
 /* Adapter interrupt definitions */
@@ -159,12 +158,12 @@
 }
 
 /**
- * ap_configuration_available(): Test if AP configuration
- * information is available.
+ * ap_qci_available(): Test if AP configuration
+ * information can be queried via QCI subfunction.
  *
- * Returns 1 if AP configuration information is available.
+ * Returns 1 if subfunction PQAP(QCI) is available.
  */
-static int ap_configuration_available(void)
+static int ap_qci_available(void)
 {
 	return test_facility(12);
 }
@@ -187,22 +186,22 @@
  */
 static inline int ap_qact_available(void)
 {
-	if (ap_configuration)
-		return ap_configuration->qact;
+	if (ap_qci_info)
+		return ap_qci_info->qact;
 	return 0;
 }
 
 /*
- * ap_query_configuration(): Fetch cryptographic config info
+ * ap_fetch_qci_info(): Fetch cryptographic config info
  *
  * Returns the ap configuration info fetched via PQAP(QCI).
  * On success 0 is returned, on failure a negative errno
  * is returned, e.g. if the PQAP(QCI) instruction is not
  * available, the return value will be -EOPNOTSUPP.
  */
-static inline int ap_query_configuration(struct ap_config_info *info)
+static inline int ap_fetch_qci_info(struct ap_config_info *info)
 {
-	if (!ap_configuration_available())
+	if (!ap_qci_available())
 		return -EOPNOTSUPP;
 	if (!info)
 		return -EINVAL;
@@ -210,21 +209,40 @@
 }
 
 /**
- * ap_init_configuration(): Allocate and query configuration array.
+ * ap_init_qci_info(): Allocate and query qci config info.
+ * Does also update the static variables ap_max_domain_id
+ * and ap_max_adapter_id if this info is available.
+
  */
-static void ap_init_configuration(void)
+static void __init ap_init_qci_info(void)
 {
-	if (!ap_configuration_available())
+	if (!ap_qci_available()) {
+		AP_DBF_INFO("%s QCI not supported\n", __func__);
 		return;
+	}
 
-	ap_configuration = kzalloc(sizeof(*ap_configuration), GFP_KERNEL);
-	if (!ap_configuration)
+	ap_qci_info = kzalloc(sizeof(*ap_qci_info), GFP_KERNEL);
+	if (!ap_qci_info)
 		return;
-	if (ap_query_configuration(ap_configuration) != 0) {
-		kfree(ap_configuration);
-		ap_configuration = NULL;
+	if (ap_fetch_qci_info(ap_qci_info) != 0) {
+		kfree(ap_qci_info);
+		ap_qci_info = NULL;
 		return;
 	}
+	AP_DBF_INFO("%s successful fetched initial qci info\n", __func__);
+
+	if (ap_qci_info->apxa) {
+		if (ap_qci_info->Na) {
+			ap_max_adapter_id = ap_qci_info->Na;
+			AP_DBF_INFO("%s new ap_max_adapter_id is %d\n",
+				    __func__, ap_max_adapter_id);
+		}
+		if (ap_qci_info->Nd) {
+			ap_max_domain_id = ap_qci_info->Nd;
+			AP_DBF_INFO("%s new ap_max_domain_id is %d\n",
+				    __func__, ap_max_domain_id);
+		}
+	}
 }
 
 /*
@@ -238,7 +256,6 @@
 
 /*
  * ap_test_config_card_id(): Test, whether an AP card ID is configured.
- * @id AP card ID
  *
  * Returns 0 if the card is not configured
  *	   1 if the card is configured or
@@ -246,16 +263,16 @@
  */
 static inline int ap_test_config_card_id(unsigned int id)
 {
-	if (!ap_configuration)	/* QCI not supported */
-		/* only ids 0...3F may be probed */
-		return id < 0x40 ? 1 : 0;
-	return ap_test_config(ap_configuration->apm, id);
+	if (id > ap_max_adapter_id)
+		return 0;
+	if (ap_qci_info)
+		return ap_test_config(ap_qci_info->apm, id);
+	return 1;
 }
 
 /*
  * ap_test_config_usage_domain(): Test, whether an AP usage domain
  * is configured.
- * @domain AP usage domain ID
  *
  * Returns 0 if the usage domain is not configured
  *	   1 if the usage domain is configured or
@@ -263,9 +280,11 @@
  */
 int ap_test_config_usage_domain(unsigned int domain)
 {
-	if (!ap_configuration)	/* QCI not supported */
-		return domain < 16;
-	return ap_test_config(ap_configuration->aqm, domain);
+	if (domain > ap_max_domain_id)
+		return 0;
+	if (ap_qci_info)
+		return ap_test_config(ap_qci_info->aqm, domain);
+	return 1;
 }
 EXPORT_SYMBOL(ap_test_config_usage_domain);
 
@@ -279,43 +298,62 @@
  */
 int ap_test_config_ctrl_domain(unsigned int domain)
 {
-	if (!ap_configuration)	/* QCI not supported */
+	if (!ap_qci_info || domain > ap_max_domain_id)
 		return 0;
-	return ap_test_config(ap_configuration->adm, domain);
+	return ap_test_config(ap_qci_info->adm, domain);
 }
 EXPORT_SYMBOL(ap_test_config_ctrl_domain);
 
-/**
- * ap_query_queue(): Check if an AP queue is available.
- * @qid: The AP queue number
- * @queue_depth: Pointer to queue depth value
- * @device_type: Pointer to device type value
- * @facilities: Pointer to facility indicator
+/*
+ * ap_queue_info(): Check and get AP queue info.
+ * Returns true if TAPQ succeeded and the info is filled or
+ * false otherwise.
  */
-static int ap_query_queue(ap_qid_t qid, int *queue_depth, int *device_type,
-			  unsigned int *facilities)
+static bool ap_queue_info(ap_qid_t qid, int *q_type, unsigned int *q_fac,
+			  int *q_depth, int *q_ml, bool *q_decfg)
 {
 	struct ap_queue_status status;
-	unsigned long info;
-	int nd;
-
-	if (!ap_test_config_card_id(AP_QID_CARD(qid)))
-		return -ENODEV;
+	union {
+		unsigned long value;
+		struct {
+			unsigned int fac   : 32; /* facility bits */
+			unsigned int at	   :  8; /* ap type */
+			unsigned int _res1 :  8;
+			unsigned int _res2 :  4;
+			unsigned int ml	   :  4; /* apxl ml */
+			unsigned int _res3 :  4;
+			unsigned int qd	   :  4; /* queue depth */
+		} tapq_gr2;
+	} tapq_info;
+
+	tapq_info.value = 0;
+
+	/* make sure we don't run into a specifiation exception */
+	if (AP_QID_CARD(qid) > ap_max_adapter_id ||
+	    AP_QID_QUEUE(qid) > ap_max_domain_id)
+		return false;
 
-	status = ap_test_queue(qid, ap_apft_available(), &info);
+	/* call TAPQ on this APQN */
+	status = ap_test_queue(qid, ap_apft_available(), &tapq_info.value);
 	switch (status.response_code) {
 	case AP_RESPONSE_NORMAL:
-		*queue_depth = (int)(info & 0xff);
-		*device_type = (int)((info >> 24) & 0xff);
-		*facilities = (unsigned int)(info >> 32);
-		/* Update maximum domain id */
-		nd = (info >> 16) & 0xff;
-		/* if N bit is available, z13 and newer */
-		if ((info & (1UL << 57)) && nd > 0)
-			ap_max_domain_id = nd;
-		else /* older machine types */
-			ap_max_domain_id = 15;
-		switch (*device_type) {
+	case AP_RESPONSE_RESET_IN_PROGRESS:
+	case AP_RESPONSE_DECONFIGURED:
+	case AP_RESPONSE_CHECKSTOPPED:
+	case AP_RESPONSE_BUSY:
+		/*
+		 * According to the architecture in all these cases the
+		 * info should be filled. All bits 0 is not possible as
+		 * there is at least one of the mode bits set.
+		 */
+		if (WARN_ON_ONCE(!tapq_info.value))
+			return false;
+		*q_type = tapq_info.tapq_gr2.at;
+		*q_fac = tapq_info.tapq_gr2.fac;
+		*q_depth = tapq_info.tapq_gr2.qd;
+		*q_ml = tapq_info.tapq_gr2.ml;
+		*q_decfg = status.response_code == AP_RESPONSE_DECONFIGURED;
+		switch (*q_type) {
 			/* For CEX2 and CEX3 the available functions
 			 * are not reflected by the facilities bits.
 			 * Instead it is coded into the type. So here
@@ -323,45 +361,39 @@
 			 */
 		case AP_DEVICE_TYPE_CEX2A:
 		case AP_DEVICE_TYPE_CEX3A:
-			*facilities |= 0x08000000;
+			*q_fac |= 0x08000000;
 			break;
 		case AP_DEVICE_TYPE_CEX2C:
 		case AP_DEVICE_TYPE_CEX3C:
-			*facilities |= 0x10000000;
+			*q_fac |= 0x10000000;
 			break;
 		default:
 			break;
 		}
-		return 0;
-	case AP_RESPONSE_Q_NOT_AVAIL:
-	case AP_RESPONSE_DECONFIGURED:
-	case AP_RESPONSE_CHECKSTOPPED:
-	case AP_RESPONSE_INVALID_ADDRESS:
-		return -ENODEV;
-	case AP_RESPONSE_RESET_IN_PROGRESS:
-	case AP_RESPONSE_OTHERWISE_CHANGED:
-	case AP_RESPONSE_BUSY:
-		return -EBUSY;
+		return true;
 	default:
-		BUG();
+		/*
+		 * A response code which indicates, there is no info available.
+		 */
+		return false;
 	}
 }
 
-void ap_wait(enum ap_wait wait)
+void ap_wait(enum ap_sm_wait wait)
 {
 	ktime_t hr_time;
 
 	switch (wait) {
-	case AP_WAIT_AGAIN:
-	case AP_WAIT_INTERRUPT:
+	case AP_SM_WAIT_AGAIN:
+	case AP_SM_WAIT_INTERRUPT:
 		if (ap_using_interrupts())
 			break;
 		if (ap_poll_kthread) {
 			wake_up(&ap_poll_wait);
 			break;
 		}
-		/* Fall through */
-	case AP_WAIT_TIMEOUT:
+		fallthrough;
+	case AP_SM_WAIT_TIMEOUT:
 		spin_lock_bh(&ap_poll_timer_lock);
 		if (!hrtimer_is_queued(&ap_poll_timer)) {
 			hr_time = poll_timeout;
@@ -370,7 +402,7 @@
 		}
 		spin_unlock_bh(&ap_poll_timer_lock);
 		break;
-	case AP_WAIT_NONE:
+	case AP_SM_WAIT_NONE:
 	default:
 		break;
 	}
@@ -386,10 +418,8 @@
 {
 	struct ap_queue *aq = from_timer(aq, t, timeout);
 
-	if (ap_suspend_flag)
-		return;
 	spin_lock_bh(&aq->lock);
-	ap_wait(ap_sm_event(aq, AP_EVENT_TIMEOUT));
+	ap_wait(ap_sm_event(aq, AP_SM_EVENT_TIMEOUT));
 	spin_unlock_bh(&aq->lock);
 }
 
@@ -401,8 +431,7 @@
  */
 static enum hrtimer_restart ap_poll_timeout(struct hrtimer *unused)
 {
-	if (!ap_suspend_flag)
-		tasklet_schedule(&ap_tasklet);
+	tasklet_schedule(&ap_tasklet);
 	return HRTIMER_NORESTART;
 }
 
@@ -413,8 +442,7 @@
 static void ap_interrupt_handler(struct airq_struct *airq, bool floating)
 {
 	inc_irq_stat(IRQIO_APB);
-	if (!ap_suspend_flag)
-		tasklet_schedule(&ap_tasklet);
+	tasklet_schedule(&ap_tasklet);
 }
 
 /**
@@ -425,9 +453,9 @@
  */
 static void ap_tasklet_fn(unsigned long dummy)
 {
-	struct ap_card *ac;
+	int bkt;
 	struct ap_queue *aq;
-	enum ap_wait wait = AP_WAIT_NONE;
+	enum ap_sm_wait wait = AP_SM_WAIT_NONE;
 
 	/* Reset the indicator if interrupts are used. Thus new interrupts can
 	 * be received. Doing it in the beginning of the tasklet is therefor
@@ -436,34 +464,30 @@
 	if (ap_using_interrupts())
 		xchg(ap_airq.lsi_ptr, 0);
 
-	spin_lock_bh(&ap_list_lock);
-	for_each_ap_card(ac) {
-		for_each_ap_queue(aq, ac) {
-			spin_lock_bh(&aq->lock);
-			wait = min(wait, ap_sm_event_loop(aq, AP_EVENT_POLL));
-			spin_unlock_bh(&aq->lock);
-		}
+	spin_lock_bh(&ap_queues_lock);
+	hash_for_each(ap_queues, bkt, aq, hnode) {
+		spin_lock_bh(&aq->lock);
+		wait = min(wait, ap_sm_event_loop(aq, AP_SM_EVENT_POLL));
+		spin_unlock_bh(&aq->lock);
 	}
-	spin_unlock_bh(&ap_list_lock);
+	spin_unlock_bh(&ap_queues_lock);
 
 	ap_wait(wait);
 }
 
 static int ap_pending_requests(void)
 {
-	struct ap_card *ac;
+	int bkt;
 	struct ap_queue *aq;
 
-	spin_lock_bh(&ap_list_lock);
-	for_each_ap_card(ac) {
-		for_each_ap_queue(aq, ac) {
-			if (aq->queue_count == 0)
-				continue;
-			spin_unlock_bh(&ap_list_lock);
-			return 1;
-		}
+	spin_lock_bh(&ap_queues_lock);
+	hash_for_each(ap_queues, bkt, aq, hnode) {
+		if (aq->queue_count == 0)
+			continue;
+		spin_unlock_bh(&ap_queues_lock);
+		return 1;
 	}
-	spin_unlock_bh(&ap_list_lock);
+	spin_unlock_bh(&ap_queues_lock);
 	return 0;
 }
 
@@ -486,7 +510,7 @@
 	while (!kthread_should_stop()) {
 		add_wait_queue(&ap_poll_wait, &wait);
 		set_current_state(TASK_INTERRUPTIBLE);
-		if (ap_suspend_flag || !ap_pending_requests()) {
+		if (!ap_pending_requests()) {
 			schedule();
 			try_to_freeze();
 		}
@@ -587,51 +611,6 @@
 	return retval;
 }
 
-static int ap_dev_suspend(struct device *dev)
-{
-	struct ap_device *ap_dev = to_ap_dev(dev);
-
-	if (ap_dev->drv && ap_dev->drv->suspend)
-		ap_dev->drv->suspend(ap_dev);
-	return 0;
-}
-
-static int ap_dev_resume(struct device *dev)
-{
-	struct ap_device *ap_dev = to_ap_dev(dev);
-
-	if (ap_dev->drv && ap_dev->drv->resume)
-		ap_dev->drv->resume(ap_dev);
-	return 0;
-}
-
-static void ap_bus_suspend(void)
-{
-	AP_DBF(DBF_DEBUG, "%s running\n", __func__);
-
-	ap_suspend_flag = 1;
-	/*
-	 * Disable scanning for devices, thus we do not want to scan
-	 * for them after removing.
-	 */
-	flush_work(&ap_scan_work);
-	tasklet_disable(&ap_tasklet);
-}
-
-static int __ap_card_devices_unregister(struct device *dev, void *dummy)
-{
-	if (is_card_dev(dev))
-		device_unregister(dev);
-	return 0;
-}
-
-static int __ap_queue_devices_unregister(struct device *dev, void *dummy)
-{
-	if (is_queue_dev(dev))
-		device_unregister(dev);
-	return 0;
-}
-
 static int __ap_queue_devices_with_id_unregister(struct device *dev, void *data)
 {
 	if (is_queue_dev(dev) &&
@@ -640,67 +619,10 @@
 	return 0;
 }
 
-static void ap_bus_resume(void)
-{
-	int rc;
-
-	AP_DBF(DBF_DEBUG, "%s running\n", __func__);
-
-	/* remove all queue devices */
-	bus_for_each_dev(&ap_bus_type, NULL, NULL,
-			 __ap_queue_devices_unregister);
-	/* remove all card devices */
-	bus_for_each_dev(&ap_bus_type, NULL, NULL,
-			 __ap_card_devices_unregister);
-
-	/* Reset thin interrupt setting */
-	if (ap_interrupts_available() && !ap_using_interrupts()) {
-		rc = register_adapter_interrupt(&ap_airq);
-		ap_airq_flag = (rc == 0);
-	}
-	if (!ap_interrupts_available() && ap_using_interrupts()) {
-		unregister_adapter_interrupt(&ap_airq);
-		ap_airq_flag = 0;
-	}
-	/* Reset domain */
-	if (!user_set_domain)
-		ap_domain_index = -1;
-	/* Get things going again */
-	ap_suspend_flag = 0;
-	if (ap_airq_flag)
-		xchg(ap_airq.lsi_ptr, 0);
-	tasklet_enable(&ap_tasklet);
-	queue_work(system_long_wq, &ap_scan_work);
-}
-
-static int ap_power_event(struct notifier_block *this, unsigned long event,
-			  void *ptr)
-{
-	switch (event) {
-	case PM_HIBERNATION_PREPARE:
-	case PM_SUSPEND_PREPARE:
-		ap_bus_suspend();
-		break;
-	case PM_POST_HIBERNATION:
-	case PM_POST_SUSPEND:
-		ap_bus_resume();
-		break;
-	default:
-		break;
-	}
-	return NOTIFY_DONE;
-}
-static struct notifier_block ap_power_notifier = {
-	.notifier_call = ap_power_event,
-};
-
-static SIMPLE_DEV_PM_OPS(ap_bus_pm_ops, ap_dev_suspend, ap_dev_resume);
-
 static struct bus_type ap_bus_type = {
 	.name = "ap",
 	.match = &ap_bus_match,
 	.uevent = &ap_uevent,
-	.pm = &ap_bus_pm_ops,
 };
 
 static int __ap_revise_reserved(struct device *dev, void *dummy)
@@ -717,8 +639,8 @@
 		drvres = to_ap_drv(dev->driver)->flags
 			& AP_DRIVER_FLAG_DEFAULT;
 		if (!!devres != !!drvres) {
-			AP_DBF(DBF_DEBUG, "reprobing queue=%02x.%04x\n",
-			       card, queue);
+			AP_DBF_DBG("reprobing queue=%02x.%04x\n",
+				   card, queue);
 			rc = device_reprobe(dev);
 		}
 	}
@@ -775,7 +697,10 @@
 {
 	struct ap_device *ap_dev = to_ap_dev(dev);
 	struct ap_driver *ap_drv = to_ap_drv(dev->driver);
-	int card, queue, devres, drvres, rc;
+	int card, queue, devres, drvres, rc = -ENODEV;
+
+	if (!get_device(dev))
+		return rc;
 
 	if (is_queue_dev(dev)) {
 		/*
@@ -792,33 +717,30 @@
 		mutex_unlock(&ap_perms_mutex);
 		drvres = ap_drv->flags & AP_DRIVER_FLAG_DEFAULT;
 		if (!!devres != !!drvres)
-			return -ENODEV;
-		/* (re-)init queue's state machine */
-		ap_queue_reinit_state(to_ap_queue(dev));
+			goto out;
 	}
 
 	/* Add queue/card to list of active queues/cards */
-	spin_lock_bh(&ap_list_lock);
-	if (is_card_dev(dev))
-		list_add(&to_ap_card(dev)->list, &ap_card_list);
-	else
-		list_add(&to_ap_queue(dev)->list,
-			 &to_ap_queue(dev)->card->queues);
-	spin_unlock_bh(&ap_list_lock);
+	spin_lock_bh(&ap_queues_lock);
+	if (is_queue_dev(dev))
+		hash_add(ap_queues, &to_ap_queue(dev)->hnode,
+			 to_ap_queue(dev)->qid);
+	spin_unlock_bh(&ap_queues_lock);
 
 	ap_dev->drv = ap_drv;
 	rc = ap_drv->probe ? ap_drv->probe(ap_dev) : -ENODEV;
 
 	if (rc) {
-		spin_lock_bh(&ap_list_lock);
-		if (is_card_dev(dev))
-			list_del_init(&to_ap_card(dev)->list);
-		else
-			list_del_init(&to_ap_queue(dev)->list);
-		spin_unlock_bh(&ap_list_lock);
+		spin_lock_bh(&ap_queues_lock);
+		if (is_queue_dev(dev))
+			hash_del(&to_ap_queue(dev)->hnode);
+		spin_unlock_bh(&ap_queues_lock);
 		ap_dev->drv = NULL;
 	}
 
+out:
+	if (rc)
+		put_device(dev);
 	return rc;
 }
 
@@ -840,24 +762,40 @@
 		ap_queue_remove(to_ap_queue(dev));
 
 	/* Remove queue/card from list of active queues/cards */
-	spin_lock_bh(&ap_list_lock);
-	if (is_card_dev(dev))
-		list_del_init(&to_ap_card(dev)->list);
-	else
-		list_del_init(&to_ap_queue(dev)->list);
-	spin_unlock_bh(&ap_list_lock);
+	spin_lock_bh(&ap_queues_lock);
+	if (is_queue_dev(dev))
+		hash_del(&to_ap_queue(dev)->hnode);
+	spin_unlock_bh(&ap_queues_lock);
+
+	put_device(dev);
 
 	return 0;
 }
 
+struct ap_queue *ap_get_qdev(ap_qid_t qid)
+{
+	int bkt;
+	struct ap_queue *aq;
+
+	spin_lock_bh(&ap_queues_lock);
+	hash_for_each(ap_queues, bkt, aq, hnode) {
+		if (aq->qid == qid) {
+			get_device(&aq->ap_dev.device);
+			spin_unlock_bh(&ap_queues_lock);
+			return aq;
+		}
+	}
+	spin_unlock_bh(&ap_queues_lock);
+
+	return NULL;
+}
+EXPORT_SYMBOL(ap_get_qdev);
+
 int ap_driver_register(struct ap_driver *ap_drv, struct module *owner,
 		       char *name)
 {
 	struct device_driver *drv = &ap_drv->driver;
 
-	if (!initialised)
-		return -ENODEV;
-
 	drv->bus = &ap_bus_type;
 	drv->probe = ap_device_probe;
 	drv->remove = ap_device_remove;
@@ -875,8 +813,6 @@
 
 void ap_bus_force_rescan(void)
 {
-	if (ap_suspend_flag)
-		return;
 	/* processing a asynchronous bus rescan */
 	del_timer(&ap_config_timer);
 	queue_work(system_long_wq, &ap_scan_work);
@@ -889,7 +825,7 @@
 */
 void ap_bus_cfg_chg(void)
 {
-	AP_DBF(DBF_INFO, "%s config change, forcing bus rescan\n", __func__);
+	AP_DBF_DBG("%s config change, forcing bus rescan\n", __func__);
 
 	ap_bus_force_rescan();
 }
@@ -949,7 +885,7 @@
  */
 static int modify_bitmap(const char *str, unsigned long *bitmap, int bits)
 {
-	int a, i, z;
+	unsigned long a, i, z;
 	char *np, sign;
 
 	/* bits needs to be a multiple of 8 */
@@ -1023,7 +959,7 @@
 
 static ssize_t ap_domain_show(struct bus_type *bus, char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "%d\n", ap_domain_index);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", ap_domain_index);
 }
 
 static ssize_t ap_domain_store(struct bus_type *bus,
@@ -1035,11 +971,12 @@
 	    domain < 0 || domain > ap_max_domain_id ||
 	    !test_bit_inv(domain, ap_perms.aqm))
 		return -EINVAL;
+
 	spin_lock_bh(&ap_domain_lock);
 	ap_domain_index = domain;
 	spin_unlock_bh(&ap_domain_lock);
 
-	AP_DBF(DBF_DEBUG, "stored new default domain=%d\n", domain);
+	AP_DBF_INFO("stored new default domain=%d\n", domain);
 
 	return count;
 }
@@ -1048,60 +985,60 @@
 
 static ssize_t ap_control_domain_mask_show(struct bus_type *bus, char *buf)
 {
-	if (!ap_configuration)	/* QCI not supported */
-		return snprintf(buf, PAGE_SIZE, "not supported\n");
+	if (!ap_qci_info)	/* QCI not supported */
+		return scnprintf(buf, PAGE_SIZE, "not supported\n");
 
-	return snprintf(buf, PAGE_SIZE,
-			"0x%08x%08x%08x%08x%08x%08x%08x%08x\n",
-			ap_configuration->adm[0], ap_configuration->adm[1],
-			ap_configuration->adm[2], ap_configuration->adm[3],
-			ap_configuration->adm[4], ap_configuration->adm[5],
-			ap_configuration->adm[6], ap_configuration->adm[7]);
+	return scnprintf(buf, PAGE_SIZE,
+			 "0x%08x%08x%08x%08x%08x%08x%08x%08x\n",
+			 ap_qci_info->adm[0], ap_qci_info->adm[1],
+			 ap_qci_info->adm[2], ap_qci_info->adm[3],
+			 ap_qci_info->adm[4], ap_qci_info->adm[5],
+			 ap_qci_info->adm[6], ap_qci_info->adm[7]);
 }
 
 static BUS_ATTR_RO(ap_control_domain_mask);
 
 static ssize_t ap_usage_domain_mask_show(struct bus_type *bus, char *buf)
 {
-	if (!ap_configuration)	/* QCI not supported */
-		return snprintf(buf, PAGE_SIZE, "not supported\n");
+	if (!ap_qci_info)	/* QCI not supported */
+		return scnprintf(buf, PAGE_SIZE, "not supported\n");
 
-	return snprintf(buf, PAGE_SIZE,
-			"0x%08x%08x%08x%08x%08x%08x%08x%08x\n",
-			ap_configuration->aqm[0], ap_configuration->aqm[1],
-			ap_configuration->aqm[2], ap_configuration->aqm[3],
-			ap_configuration->aqm[4], ap_configuration->aqm[5],
-			ap_configuration->aqm[6], ap_configuration->aqm[7]);
+	return scnprintf(buf, PAGE_SIZE,
+			 "0x%08x%08x%08x%08x%08x%08x%08x%08x\n",
+			 ap_qci_info->aqm[0], ap_qci_info->aqm[1],
+			 ap_qci_info->aqm[2], ap_qci_info->aqm[3],
+			 ap_qci_info->aqm[4], ap_qci_info->aqm[5],
+			 ap_qci_info->aqm[6], ap_qci_info->aqm[7]);
 }
 
 static BUS_ATTR_RO(ap_usage_domain_mask);
 
 static ssize_t ap_adapter_mask_show(struct bus_type *bus, char *buf)
 {
-	if (!ap_configuration)	/* QCI not supported */
-		return snprintf(buf, PAGE_SIZE, "not supported\n");
+	if (!ap_qci_info)	/* QCI not supported */
+		return scnprintf(buf, PAGE_SIZE, "not supported\n");
 
-	return snprintf(buf, PAGE_SIZE,
-			"0x%08x%08x%08x%08x%08x%08x%08x%08x\n",
-			ap_configuration->apm[0], ap_configuration->apm[1],
-			ap_configuration->apm[2], ap_configuration->apm[3],
-			ap_configuration->apm[4], ap_configuration->apm[5],
-			ap_configuration->apm[6], ap_configuration->apm[7]);
+	return scnprintf(buf, PAGE_SIZE,
+			 "0x%08x%08x%08x%08x%08x%08x%08x%08x\n",
+			 ap_qci_info->apm[0], ap_qci_info->apm[1],
+			 ap_qci_info->apm[2], ap_qci_info->apm[3],
+			 ap_qci_info->apm[4], ap_qci_info->apm[5],
+			 ap_qci_info->apm[6], ap_qci_info->apm[7]);
 }
 
 static BUS_ATTR_RO(ap_adapter_mask);
 
 static ssize_t ap_interrupts_show(struct bus_type *bus, char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "%d\n",
-			ap_using_interrupts() ? 1 : 0);
+	return scnprintf(buf, PAGE_SIZE, "%d\n",
+			 ap_using_interrupts() ? 1 : 0);
 }
 
 static BUS_ATTR_RO(ap_interrupts);
 
 static ssize_t config_time_show(struct bus_type *bus, char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "%d\n", ap_config_time);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", ap_config_time);
 }
 
 static ssize_t config_time_store(struct bus_type *bus,
@@ -1120,7 +1057,7 @@
 
 static ssize_t poll_thread_show(struct bus_type *bus, char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "%d\n", ap_poll_kthread ? 1 : 0);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", ap_poll_kthread ? 1 : 0);
 }
 
 static ssize_t poll_thread_store(struct bus_type *bus,
@@ -1143,7 +1080,7 @@
 
 static ssize_t poll_timeout_show(struct bus_type *bus, char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "%llu\n", poll_timeout);
+	return scnprintf(buf, PAGE_SIZE, "%llu\n", poll_timeout);
 }
 
 static ssize_t poll_timeout_store(struct bus_type *bus, const char *buf,
@@ -1172,27 +1109,28 @@
 
 static ssize_t ap_max_domain_id_show(struct bus_type *bus, char *buf)
 {
-	int max_domain_id;
-
-	if (ap_configuration)
-		max_domain_id = ap_max_domain_id ? : -1;
-	else
-		max_domain_id = 15;
-	return snprintf(buf, PAGE_SIZE, "%d\n", max_domain_id);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", ap_max_domain_id);
 }
 
 static BUS_ATTR_RO(ap_max_domain_id);
 
+static ssize_t ap_max_adapter_id_show(struct bus_type *bus, char *buf)
+{
+	return scnprintf(buf, PAGE_SIZE, "%d\n", ap_max_adapter_id);
+}
+
+static BUS_ATTR_RO(ap_max_adapter_id);
+
 static ssize_t apmask_show(struct bus_type *bus, char *buf)
 {
 	int rc;
 
 	if (mutex_lock_interruptible(&ap_perms_mutex))
 		return -ERESTARTSYS;
-	rc = snprintf(buf, PAGE_SIZE,
-		      "0x%016lx%016lx%016lx%016lx\n",
-		      ap_perms.apm[0], ap_perms.apm[1],
-		      ap_perms.apm[2], ap_perms.apm[3]);
+	rc = scnprintf(buf, PAGE_SIZE,
+		       "0x%016lx%016lx%016lx%016lx\n",
+		       ap_perms.apm[0], ap_perms.apm[1],
+		       ap_perms.apm[2], ap_perms.apm[3]);
 	mutex_unlock(&ap_perms_mutex);
 
 	return rc;
@@ -1220,10 +1158,10 @@
 
 	if (mutex_lock_interruptible(&ap_perms_mutex))
 		return -ERESTARTSYS;
-	rc = snprintf(buf, PAGE_SIZE,
-		      "0x%016lx%016lx%016lx%016lx\n",
-		      ap_perms.aqm[0], ap_perms.aqm[1],
-		      ap_perms.aqm[2], ap_perms.aqm[3]);
+	rc = scnprintf(buf, PAGE_SIZE,
+		       "0x%016lx%016lx%016lx%016lx\n",
+		       ap_perms.aqm[0], ap_perms.aqm[1],
+		       ap_perms.aqm[2], ap_perms.aqm[3]);
 	mutex_unlock(&ap_perms_mutex);
 
 	return rc;
@@ -1255,6 +1193,7 @@
 	&bus_attr_ap_interrupts,
 	&bus_attr_poll_timeout,
 	&bus_attr_ap_max_domain_id,
+	&bus_attr_ap_max_adapter_id,
 	&bus_attr_apmask,
 	&bus_attr_aqmask,
 	NULL,
@@ -1266,47 +1205,42 @@
  */
 static void ap_select_domain(void)
 {
-	int count, max_count, best_domain;
 	struct ap_queue_status status;
-	int i, j;
+	int card, dom;
 
 	/*
-	 * We want to use a single domain. Either the one specified with
-	 * the "domain=" parameter or the domain with the maximum number
-	 * of devices.
+	 * Choose the default domain. Either the one specified with
+	 * the "domain=" parameter or the first domain with at least
+	 * one valid APQN.
 	 */
 	spin_lock_bh(&ap_domain_lock);
 	if (ap_domain_index >= 0) {
 		/* Domain has already been selected. */
-		spin_unlock_bh(&ap_domain_lock);
-		return;
+		goto out;
 	}
-	best_domain = -1;
-	max_count = 0;
-	for (i = 0; i < AP_DOMAINS; i++) {
-		if (!ap_test_config_usage_domain(i) ||
-		    !test_bit_inv(i, ap_perms.aqm))
+	for (dom = 0; dom <= ap_max_domain_id; dom++) {
+		if (!ap_test_config_usage_domain(dom) ||
+		    !test_bit_inv(dom, ap_perms.aqm))
 			continue;
-		count = 0;
-		for (j = 0; j < AP_DEVICES; j++) {
-			if (!ap_test_config_card_id(j))
+		for (card = 0; card <= ap_max_adapter_id; card++) {
+			if (!ap_test_config_card_id(card) ||
+			    !test_bit_inv(card, ap_perms.apm))
 				continue;
-			status = ap_test_queue(AP_MKQID(j, i),
+			status = ap_test_queue(AP_MKQID(card, dom),
 					       ap_apft_available(),
 					       NULL);
-			if (status.response_code != AP_RESPONSE_NORMAL)
-				continue;
-			count++;
-		}
-		if (count > max_count) {
-			max_count = count;
-			best_domain = i;
+			if (status.response_code == AP_RESPONSE_NORMAL)
+				break;
 		}
+		if (card <= ap_max_adapter_id)
+			break;
 	}
-	if (best_domain >= 0) {
-		ap_domain_index = best_domain;
-		AP_DBF(DBF_DEBUG, "new ap_domain_index=%d\n", ap_domain_index);
+	if (dom <= ap_max_domain_id) {
+		ap_domain_index = dom;
+		AP_DBF_INFO("%s new default domain is %d\n",
+			    __func__, ap_domain_index);
 	}
+out:
 	spin_unlock_bh(&ap_domain_lock);
 }
 
@@ -1320,8 +1254,11 @@
 	int comp_type = 0;
 
 	/* < CEX2A is not supported */
-	if (rawtype < AP_DEVICE_TYPE_CEX2A)
+	if (rawtype < AP_DEVICE_TYPE_CEX2A) {
+		AP_DBF_WARN("get_comp_type queue=%02x.%04x unsupported type %d\n",
+			    AP_QID_CARD(qid), AP_QID_QUEUE(qid), rawtype);
 		return 0;
+	}
 	/* up to CEX7 known and fully supported */
 	if (rawtype <= AP_DEVICE_TYPE_CEX7)
 		return rawtype;
@@ -1343,11 +1280,12 @@
 			comp_type = apinfo.cat;
 	}
 	if (!comp_type)
-		AP_DBF(DBF_WARN, "queue=%02x.%04x unable to map type %d\n",
-		       AP_QID_CARD(qid), AP_QID_QUEUE(qid), rawtype);
+		AP_DBF_WARN("get_comp_type queue=%02x.%04x unable to map type %d\n",
+			    AP_QID_CARD(qid), AP_QID_QUEUE(qid), rawtype);
 	else if (comp_type != rawtype)
-		AP_DBF(DBF_INFO, "queue=%02x.%04x map type %d to %d\n",
-		       AP_QID_CARD(qid), AP_QID_QUEUE(qid), rawtype, comp_type);
+		AP_DBF_INFO("get_comp_type queue=%02x.%04x map type %d to %d\n",
+			    AP_QID_CARD(qid), AP_QID_QUEUE(qid),
+			    rawtype, comp_type);
 	return comp_type;
 }
 
@@ -1381,156 +1319,287 @@
 
 /*
  * Helper function for ap_scan_bus().
- * Does the scan bus job for the given adapter id.
+ * Remove card device and associated queue devices.
+ */
+static inline void ap_scan_rm_card_dev_and_queue_devs(struct ap_card *ac)
+{
+	bus_for_each_dev(&ap_bus_type, NULL,
+			 (void *)(long) ac->id,
+			 __ap_queue_devices_with_id_unregister);
+	device_unregister(&ac->ap_dev.device);
+}
+
+/*
+ * Helper function for ap_scan_bus().
+ * Does the scan bus job for all the domains within
+ * a valid adapter given by an ap_card ptr.
  */
-static void _ap_scan_bus_adapter(int id)
+static inline void ap_scan_domains(struct ap_card *ac)
 {
+	bool decfg;
 	ap_qid_t qid;
 	unsigned int func;
-	struct ap_card *ac;
 	struct device *dev;
 	struct ap_queue *aq;
-	int rc, dom, depth, type, comp_type, borked;
-
-	/* check if there is a card device registered with this id */
-	dev = bus_find_device(&ap_bus_type, NULL,
-			      (void *)(long) id,
-			      __match_card_device_with_id);
-	ac = dev ? to_ap_card(dev) : NULL;
-	if (!ap_test_config_card_id(id)) {
-		if (dev) {
-			/* Card device has been removed from configuration */
-			bus_for_each_dev(&ap_bus_type, NULL,
-					 (void *)(long) id,
-					 __ap_queue_devices_with_id_unregister);
-			device_unregister(dev);
-			put_device(dev);
-		}
-		return;
-	}
+	int rc, dom, depth, type, ml;
 
 	/*
-	 * This card id is enabled in the configuration. If we already have
-	 * a card device with this id, check if type and functions are still
-	 * the very same. Also verify that at least one queue is available.
+	 * Go through the configuration for the domains and compare them
+	 * to the existing queue devices. Also take care of the config
+	 * and error state for the queue devices.
 	 */
-	if (ac) {
-		/* find the first valid queue */
-		for (dom = 0; dom < AP_DOMAINS; dom++) {
-			qid = AP_MKQID(id, dom);
-			if (ap_query_queue(qid, &depth, &type, &func) == 0)
-				break;
-		}
-		borked = 0;
-		if (dom >= AP_DOMAINS) {
-			/* no accessible queue on this card */
-			borked = 1;
-		} else if (ac->raw_hwtype != type) {
-			/* card type has changed */
-			AP_DBF(DBF_INFO, "card=%02x type changed.\n", id);
-			borked = 1;
-		} else if (ac->functions != func) {
-			/* card functions have changed */
-			AP_DBF(DBF_INFO, "card=%02x functions changed.\n", id);
-			borked = 1;
-		}
-		if (borked) {
-			/* unregister card device and associated queues */
-			bus_for_each_dev(&ap_bus_type, NULL,
-					 (void *)(long) id,
-					 __ap_queue_devices_with_id_unregister);
-			device_unregister(dev);
-			put_device(dev);
-			/* go back if there is no valid queue on this card */
-			if (dom >= AP_DOMAINS)
-				return;
-			ac = NULL;
-		}
-	}
 
-	/*
-	 * Go through all possible queue ids. Check and maybe create or release
-	 * queue devices for this card. If there exists no card device yet,
-	 * create a card device also.
-	 */
-	for (dom = 0; dom < AP_DOMAINS; dom++) {
-		qid = AP_MKQID(id, dom);
+	for (dom = 0; dom <= ap_max_domain_id; dom++) {
+		qid = AP_MKQID(ac->id, dom);
 		dev = bus_find_device(&ap_bus_type, NULL,
 				      (void *)(long) qid,
 				      __match_queue_device_with_qid);
 		aq = dev ? to_ap_queue(dev) : NULL;
 		if (!ap_test_config_usage_domain(dom)) {
 			if (dev) {
-				/* Queue device exists but has been
-				 * removed from configuration.
-				 */
+				AP_DBF_INFO("%s(%d,%d) not in config any more, rm queue device\n",
+					    __func__, ac->id, dom);
 				device_unregister(dev);
 				put_device(dev);
 			}
 			continue;
 		}
-		/* try to fetch infos about this queue */
-		rc = ap_query_queue(qid, &depth, &type, &func);
-		if (dev) {
-			if (rc == -ENODEV)
-				borked = 1;
-			else {
-				spin_lock_bh(&aq->lock);
-				borked = aq->state == AP_STATE_BORKED;
-				spin_unlock_bh(&aq->lock);
-			}
-			if (borked) {
-				/* Remove broken device */
-				AP_DBF(DBF_DEBUG,
-				       "removing broken queue=%02x.%04x\n",
-				       id, dom);
+		/* domain is valid, get info from this APQN */
+		if (!ap_queue_info(qid, &type, &func, &depth, &ml, &decfg)) {
+			if (aq) {
+				AP_DBF_INFO(
+					"%s(%d,%d) ap_queue_info() not successful, rm queue device\n",
+					__func__, ac->id, dom);
 				device_unregister(dev);
+				put_device(dev);
 			}
-			put_device(dev);
 			continue;
 		}
-		if (rc)
-			continue;
-		/* a new queue device is needed, check out comp type */
-		comp_type = ap_get_compatible_type(qid, type, func);
-		if (!comp_type)
-			continue;
-		/* maybe a card device needs to be created first */
-		if (!ac) {
-			ac = ap_card_create(id, depth, type, comp_type, func);
-			if (!ac)
+		/* if no queue device exists, create a new one */
+		if (!aq) {
+			aq = ap_queue_create(qid, ac->ap_dev.device_type);
+			if (!aq) {
+				AP_DBF_WARN("%s(%d,%d) ap_queue_create() failed\n",
+					    __func__, ac->id, dom);
 				continue;
-			ac->ap_dev.device.bus = &ap_bus_type;
-			ac->ap_dev.device.parent = ap_root_device;
-			dev_set_name(&ac->ap_dev.device, "card%02x", id);
-			/* Register card device with AP bus */
-			rc = device_register(&ac->ap_dev.device);
+			}
+			aq->card = ac;
+			aq->config = !decfg;
+			dev = &aq->ap_dev.device;
+			dev->bus = &ap_bus_type;
+			dev->parent = &ac->ap_dev.device;
+			dev_set_name(dev, "%02x.%04x", ac->id, dom);
+			/* register queue device */
+			rc = device_register(dev);
 			if (rc) {
-				put_device(&ac->ap_dev.device);
-				ac = NULL;
-				break;
+				AP_DBF_WARN("%s(%d,%d) device_register() failed\n",
+					    __func__, ac->id, dom);
+				goto put_dev_and_continue;
 			}
 			/* get it and thus adjust reference counter */
-			get_device(&ac->ap_dev.device);
+			get_device(dev);
+			if (decfg)
+				AP_DBF_INFO("%s(%d,%d) new (decfg) queue device created\n",
+					    __func__, ac->id, dom);
+			else
+				AP_DBF_INFO("%s(%d,%d) new queue device created\n",
+					    __func__, ac->id, dom);
+			goto put_dev_and_continue;
 		}
-		/* now create the new queue device */
-		aq = ap_queue_create(qid, comp_type);
-		if (!aq)
-			continue;
-		aq->card = ac;
-		aq->ap_dev.device.bus = &ap_bus_type;
-		aq->ap_dev.device.parent = &ac->ap_dev.device;
-		dev_set_name(&aq->ap_dev.device, "%02x.%04x", id, dom);
-		/* Register queue device */
-		rc = device_register(&aq->ap_dev.device);
+		/* Check config state on the already existing queue device */
+		spin_lock_bh(&aq->lock);
+		if (decfg && aq->config) {
+			/* config off this queue device */
+			aq->config = false;
+			if (aq->dev_state > AP_DEV_STATE_UNINITIATED) {
+				aq->dev_state = AP_DEV_STATE_ERROR;
+				aq->last_err_rc = AP_RESPONSE_DECONFIGURED;
+			}
+			spin_unlock_bh(&aq->lock);
+			AP_DBF_INFO("%s(%d,%d) queue device config off\n",
+				    __func__, ac->id, dom);
+			/* 'receive' pending messages with -EAGAIN */
+			ap_flush_queue(aq);
+			goto put_dev_and_continue;
+		}
+		if (!decfg && !aq->config) {
+			/* config on this queue device */
+			aq->config = true;
+			if (aq->dev_state > AP_DEV_STATE_UNINITIATED) {
+				aq->dev_state = AP_DEV_STATE_OPERATING;
+				aq->sm_state = AP_SM_STATE_RESET_START;
+			}
+			spin_unlock_bh(&aq->lock);
+			AP_DBF_INFO("%s(%d,%d) queue device config on\n",
+				    __func__, ac->id, dom);
+			goto put_dev_and_continue;
+		}
+		/* handle other error states */
+		if (!decfg && aq->dev_state == AP_DEV_STATE_ERROR) {
+			spin_unlock_bh(&aq->lock);
+			/* 'receive' pending messages with -EAGAIN */
+			ap_flush_queue(aq);
+			/* re-init (with reset) the queue device */
+			ap_queue_init_state(aq);
+			AP_DBF_INFO("%s(%d,%d) queue device reinit enforced\n",
+				    __func__, ac->id, dom);
+			goto put_dev_and_continue;
+		}
+		spin_unlock_bh(&aq->lock);
+put_dev_and_continue:
+		put_device(dev);
+	}
+}
+
+/*
+ * Helper function for ap_scan_bus().
+ * Does the scan bus job for the given adapter id.
+ */
+static inline void ap_scan_adapter(int ap)
+{
+	bool decfg;
+	ap_qid_t qid;
+	unsigned int func;
+	struct device *dev;
+	struct ap_card *ac;
+	int rc, dom, depth, type, comp_type, ml;
+
+	/* Is there currently a card device for this adapter ? */
+	dev = bus_find_device(&ap_bus_type, NULL,
+			      (void *)(long) ap,
+			      __match_card_device_with_id);
+	ac = dev ? to_ap_card(dev) : NULL;
+
+	/* Adapter not in configuration ? */
+	if (!ap_test_config_card_id(ap)) {
+		if (ac) {
+			AP_DBF_INFO("%s(%d) ap not in config any more, rm card and queue devices\n",
+				    __func__, ap);
+			ap_scan_rm_card_dev_and_queue_devs(ac);
+			put_device(dev);
+		}
+		return;
+	}
+
+	/*
+	 * Adapter ap is valid in the current configuration. So do some checks:
+	 * If no card device exists, build one. If a card device exists, check
+	 * for type and functions changed. For all this we need to find a valid
+	 * APQN first.
+	 */
+
+	for (dom = 0; dom <= ap_max_domain_id; dom++)
+		if (ap_test_config_usage_domain(dom)) {
+			qid = AP_MKQID(ap, dom);
+			if (ap_queue_info(qid, &type, &func,
+					  &depth, &ml, &decfg))
+				break;
+		}
+	if (dom > ap_max_domain_id) {
+		/* Could not find a valid APQN for this adapter */
+		if (ac) {
+			AP_DBF_INFO(
+				"%s(%d) no type info (no APQN found), rm card and queue devices\n",
+				__func__, ap);
+			ap_scan_rm_card_dev_and_queue_devs(ac);
+			put_device(dev);
+		} else {
+			AP_DBF_DBG("%s(%d) no type info (no APQN found), ignored\n",
+				   __func__, ap);
+		}
+		return;
+	}
+	if (!type) {
+		/* No apdater type info available, an unusable adapter */
+		if (ac) {
+			AP_DBF_INFO("%s(%d) no valid type (0) info, rm card and queue devices\n",
+				    __func__, ap);
+			ap_scan_rm_card_dev_and_queue_devs(ac);
+			put_device(dev);
+		} else {
+			AP_DBF_DBG("%s(%d) no valid type (0) info, ignored\n",
+				   __func__, ap);
+		}
+		return;
+	}
+
+	if (ac) {
+		/* Check APQN against existing card device for changes */
+		if (ac->raw_hwtype != type) {
+			AP_DBF_INFO("%s(%d) hwtype %d changed, rm card and queue devices\n",
+				    __func__, ap, type);
+			ap_scan_rm_card_dev_and_queue_devs(ac);
+			put_device(dev);
+			ac = NULL;
+		} else if (ac->functions != func) {
+			AP_DBF_INFO("%s(%d) functions 0x%08x changed, rm card and queue devices\n",
+				    __func__, ap, type);
+			ap_scan_rm_card_dev_and_queue_devs(ac);
+			put_device(dev);
+			ac = NULL;
+		} else {
+			if (decfg && ac->config) {
+				ac->config = false;
+				AP_DBF_INFO("%s(%d) card device config off\n",
+					    __func__, ap);
+
+			}
+			if (!decfg && !ac->config) {
+				ac->config = true;
+				AP_DBF_INFO("%s(%d) card device config on\n",
+					    __func__, ap);
+			}
+		}
+	}
+
+	if (!ac) {
+		/* Build a new card device */
+		comp_type = ap_get_compatible_type(qid, type, func);
+		if (!comp_type) {
+			AP_DBF_WARN("%s(%d) type %d, can't get compatibility type\n",
+				    __func__, ap, type);
+			return;
+		}
+		ac = ap_card_create(ap, depth, type, comp_type, func, ml);
+		if (!ac) {
+			AP_DBF_WARN("%s(%d) ap_card_create() failed\n",
+				    __func__, ap);
+			return;
+		}
+		ac->config = !decfg;
+		dev = &ac->ap_dev.device;
+		dev->bus = &ap_bus_type;
+		dev->parent = ap_root_device;
+		dev_set_name(dev, "card%02x", ap);
+		/* maybe enlarge ap_max_msg_size to support this card */
+		if (ac->maxmsgsize > atomic_read(&ap_max_msg_size)) {
+			atomic_set(&ap_max_msg_size, ac->maxmsgsize);
+			AP_DBF_INFO("%s(%d) ap_max_msg_size update to %d byte\n",
+				    __func__, ap, atomic_read(&ap_max_msg_size));
+		}
+		/* Register the new card device with AP bus */
+		rc = device_register(dev);
 		if (rc) {
-			put_device(&aq->ap_dev.device);
-			continue;
+			AP_DBF_WARN("%s(%d) device_register() failed\n",
+				    __func__, ap);
+			put_device(dev);
+			return;
 		}
-	} /* end domain loop */
+		/* get it and thus adjust reference counter */
+		get_device(dev);
+		if (decfg)
+			AP_DBF_INFO("%s(%d) new (decfg) card device type=%d func=0x%08x created\n",
+				    __func__, ap, type, func);
+		else
+			AP_DBF_INFO("%s(%d) new card device type=%d func=0x%08x created\n",
+				    __func__, ap, type, func);
+	}
+
+	/* Verify the domains and the queue devices for this card */
+	ap_scan_domains(ac);
 
-	if (ac)
-		put_device(&ac->ap_dev.device);
+	/* release the card device */
+	put_device(&ac->ap_dev.device);
 }
 
 /**
@@ -1539,16 +1608,16 @@
  */
 static void ap_scan_bus(struct work_struct *unused)
 {
-	int id;
+	int ap;
 
-	AP_DBF(DBF_DEBUG, "%s running\n", __func__);
-
-	ap_query_configuration(ap_configuration);
+	ap_fetch_qci_info(ap_qci_info);
 	ap_select_domain();
 
+	AP_DBF_DBG("%s running\n", __func__);
+
 	/* loop over all possible adapters */
-	for (id = 0; id < AP_DEVICES; id++)
-		_ap_scan_bus_adapter(id);
+	for (ap = 0; ap <= ap_max_adapter_id; ap++)
+		ap_scan_adapter(ap);
 
 	/* check if there is at least one queue available with default domain */
 	if (ap_domain_index >= 0) {
@@ -1559,9 +1628,8 @@
 		if (dev)
 			put_device(dev);
 		else
-			AP_DBF(DBF_INFO,
-			       "no queue device with default domain %d available\n",
-			       ap_domain_index);
+			AP_DBF_INFO("no queue device with default domain %d available\n",
+				    ap_domain_index);
 	}
 
 	mod_timer(&ap_config_timer, jiffies + ap_config_time * HZ);
@@ -1569,8 +1637,6 @@
 
 static void ap_config_timeout(struct timer_list *unused)
 {
-	if (ap_suspend_flag)
-		return;
 	queue_work(system_long_wq, &ap_scan_work);
 }
 
@@ -1613,7 +1679,6 @@
  */
 static int __init ap_module_init(void)
 {
-	int max_domain_id;
 	int rc, i;
 
 	rc = ap_debug_init();
@@ -1625,30 +1690,25 @@
 		return -ENODEV;
 	}
 
+	/* init ap_queue hashtable */
+	hash_init(ap_queues);
+
 	/* set up the AP permissions (ioctls, ap and aq masks) */
 	ap_perms_init();
 
 	/* Get AP configuration data if available */
-	ap_init_configuration();
+	ap_init_qci_info();
 
-	if (ap_configuration)
-		max_domain_id =
-			ap_max_domain_id ? ap_max_domain_id : AP_DOMAINS - 1;
-	else
-		max_domain_id = 15;
-	if (ap_domain_index < -1 || ap_domain_index > max_domain_id ||
+	/* check default domain setting */
+	if (ap_domain_index < -1 || ap_domain_index > ap_max_domain_id ||
 	    (ap_domain_index >= 0 &&
 	     !test_bit_inv(ap_domain_index, ap_perms.aqm))) {
 		pr_warn("%d is not a valid cryptographic domain\n",
 			ap_domain_index);
 		ap_domain_index = -1;
 	}
-	/* In resume callback we need to know if the user had set the domain.
-	 * If so, we can not just reset it.
-	 */
-	if (ap_domain_index >= 0)
-		user_set_domain = 1;
 
+	/* enable interrupts if available */
 	if (ap_interrupts_available()) {
 		rc = register_adapter_interrupt(&ap_airq);
 		ap_airq_flag = (rc == 0);
@@ -1679,7 +1739,6 @@
 	 */
 	if (MACHINE_IS_VM)
 		poll_timeout = 1500000;
-	spin_lock_init(&ap_poll_timer_lock);
 	hrtimer_init(&ap_poll_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
 	ap_poll_timer.function = ap_poll_timeout;
 
@@ -1690,17 +1749,10 @@
 			goto out_work;
 	}
 
-	rc = register_pm_notifier(&ap_power_notifier);
-	if (rc)
-		goto out_pm;
-
 	queue_work(system_long_wq, &ap_scan_work);
-	initialised = true;
 
 	return 0;
 
-out_pm:
-	ap_poll_thread_stop();
 out_work:
 	hrtimer_cancel(&ap_poll_timer);
 	root_device_unregister(ap_root_device);
@@ -1711,7 +1763,7 @@
 out:
 	if (ap_using_interrupts())
 		unregister_adapter_interrupt(&ap_airq);
-	kfree(ap_configuration);
+	kfree(ap_qci_info);
 	return rc;
 }
 device_initcall(ap_module_init);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/crypto/ap_bus.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/crypto/ap_bus.h
@@ -15,6 +15,7 @@
 
 #include <linux/device.h>
 #include <linux/types.h>
+#include <linux/hashtable.h>
 #include <asm/isc.h>
 #include <asm/ap.h>
 
@@ -24,11 +25,14 @@
 #define AP_RESET_TIMEOUT (HZ*0.7)	/* Time in ticks for reset timeouts. */
 #define AP_CONFIG_TIME 30	/* Time in seconds between AP bus rescans. */
 #define AP_POLL_TIME 1		/* Time in ticks between receive polls. */
+#define AP_DEFAULT_MAX_MSG_SIZE (12 * 1024)
+#define AP_TAPQ_ML_FIELD_CHUNK_SIZE (4096)
 
 extern int ap_domain_index;
+extern atomic_t ap_max_msg_size;
 
-extern spinlock_t ap_list_lock;
-extern struct list_head ap_card_list;
+extern DECLARE_HASHTABLE(ap_queues, 8);
+extern spinlock_t ap_queues_lock;
 
 static inline int ap_test_bit(unsigned int *ptr, unsigned int nr)
 {
@@ -49,6 +53,7 @@
 #define AP_RESPONSE_NO_FIRST_PART	0x13
 #define AP_RESPONSE_MESSAGE_TOO_BIG	0x15
 #define AP_RESPONSE_REQ_FAC_NOT_INST	0x16
+#define AP_RESPONSE_INVALID_DOMAIN	0x42
 
 /*
  * Known device types
@@ -82,40 +87,47 @@
 #define AP_INTR_ENABLED		1	/* AP interrupt enabled */
 
 /*
- * AP device states
+ * AP queue state machine states
  */
-enum ap_state {
-	AP_STATE_RESET_START,
-	AP_STATE_RESET_WAIT,
-	AP_STATE_SETIRQ_WAIT,
-	AP_STATE_IDLE,
-	AP_STATE_WORKING,
-	AP_STATE_QUEUE_FULL,
-	AP_STATE_SUSPEND_WAIT,
-	AP_STATE_REMOVE,	/* about to be removed from driver */
-	AP_STATE_UNBOUND,	/* momentary not bound to a driver */
-	AP_STATE_BORKED,	/* broken */
-	NR_AP_STATES
+enum ap_sm_state {
+	AP_SM_STATE_RESET_START = 0,
+	AP_SM_STATE_RESET_WAIT,
+	AP_SM_STATE_SETIRQ_WAIT,
+	AP_SM_STATE_IDLE,
+	AP_SM_STATE_WORKING,
+	AP_SM_STATE_QUEUE_FULL,
+	NR_AP_SM_STATES
 };
 
 /*
- * AP device events
+ * AP queue state machine events
  */
-enum ap_event {
-	AP_EVENT_POLL,
-	AP_EVENT_TIMEOUT,
-	NR_AP_EVENTS
+enum ap_sm_event {
+	AP_SM_EVENT_POLL,
+	AP_SM_EVENT_TIMEOUT,
+	NR_AP_SM_EVENTS
 };
 
 /*
- * AP wait behaviour
+ * AP queue state wait behaviour
  */
-enum ap_wait {
-	AP_WAIT_AGAIN,		/* retry immediately */
-	AP_WAIT_TIMEOUT,	/* wait for timeout */
-	AP_WAIT_INTERRUPT,	/* wait for thin interrupt (if available) */
-	AP_WAIT_NONE,		/* no wait */
-	NR_AP_WAIT
+enum ap_sm_wait {
+	AP_SM_WAIT_AGAIN,	/* retry immediately */
+	AP_SM_WAIT_TIMEOUT,	/* wait for timeout */
+	AP_SM_WAIT_INTERRUPT,	/* wait for thin interrupt (if available) */
+	AP_SM_WAIT_NONE,	/* no wait */
+	NR_AP_SM_WAIT
+};
+
+/*
+ * AP queue device states
+ */
+enum ap_dev_state {
+	AP_DEV_STATE_UNINITIATED = 0,	/* fresh and virgin, not touched */
+	AP_DEV_STATE_OPERATING,		/* queue dev is working normal */
+	AP_DEV_STATE_SHUTDOWN,		/* remove/unbind/shutdown in progress */
+	AP_DEV_STATE_ERROR,		/* device is in error state */
+	NR_AP_DEV_STATES
 };
 
 struct ap_device;
@@ -136,8 +148,6 @@
 
 	int (*probe)(struct ap_device *);
 	void (*remove)(struct ap_device *);
-	void (*suspend)(struct ap_device *);
-	void (*resume)(struct ap_device *);
 };
 
 #define to_ap_drv(x) container_of((x), struct ap_driver, driver)
@@ -155,56 +165,86 @@
 
 struct ap_card {
 	struct ap_device ap_dev;
-	struct list_head list;		/* Private list of AP cards. */
-	struct list_head queues;	/* List of assoc. AP queues */
 	void *private;			/* ap driver private pointer. */
 	int raw_hwtype;			/* AP raw hardware type. */
 	unsigned int functions;		/* AP device function bitfield. */
 	int queue_depth;		/* AP queue depth.*/
 	int id;				/* AP card number. */
-	atomic_t total_request_count;	/* # requests ever for this AP device.*/
+	unsigned int maxmsgsize;	/* AP msg limit for this card */
+	bool config;			/* configured state */
+	atomic64_t total_request_count;	/* # requests ever for this AP device.*/
 };
 
 #define to_ap_card(x) container_of((x), struct ap_card, ap_dev.device)
 
 struct ap_queue {
 	struct ap_device ap_dev;
-	struct list_head list;		/* Private list of AP queues. */
+	struct hlist_node hnode;	/* Node for the ap_queues hashtable */
 	struct ap_card *card;		/* Ptr to assoc. AP card. */
 	spinlock_t lock;		/* Per device lock. */
 	void *private;			/* ap driver private pointer. */
+	enum ap_dev_state dev_state;	/* queue device state */
+	bool config;			/* configured state */
 	ap_qid_t qid;			/* AP queue id. */
 	int interrupt;			/* indicate if interrupts are enabled */
 	int queue_count;		/* # messages currently on AP queue. */
-	enum ap_state state;		/* State of the AP device. */
 	int pendingq_count;		/* # requests on pendingq list. */
 	int requestq_count;		/* # requests on requestq list. */
-	int total_request_count;	/* # requests ever for this AP device.*/
+	u64 total_request_count;	/* # requests ever for this AP device.*/
 	int request_timeout;		/* Request timeout in jiffies. */
 	struct timer_list timeout;	/* Timer for request timeouts. */
 	struct list_head pendingq;	/* List of message sent to AP queue. */
 	struct list_head requestq;	/* List of message yet to be sent. */
 	struct ap_message *reply;	/* Per device reply message. */
+	enum ap_sm_state sm_state;	/* ap queue state machine state */
+	int last_err_rc;		/* last error state response code */
 };
 
 #define to_ap_queue(x) container_of((x), struct ap_queue, ap_dev.device)
 
-typedef enum ap_wait (ap_func_t)(struct ap_queue *queue);
+typedef enum ap_sm_wait (ap_func_t)(struct ap_queue *queue);
+
+/* failure injection cmd struct */
+struct ap_fi {
+	union {
+		u16 cmd;		/* fi flags + action */
+		struct {
+			u8 flags;	/* fi flags only */
+			u8 action;	/* fi action only */
+		};
+	};
+};
+
+/* all currently known fi actions */
+enum ap_fi_actions {
+	AP_FI_ACTION_CCA_AGENT_FF   = 0x01,
+	AP_FI_ACTION_CCA_DOM_INVAL  = 0x02,
+	AP_FI_ACTION_NQAP_QID_INVAL = 0x03,
+};
+
+/* all currently known fi flags */
+enum ap_fi_flags {
+	AP_FI_FLAG_NO_RETRY	  = 0x01,
+	AP_FI_FLAG_TOGGLE_SPECIAL = 0x02,
+};
 
 struct ap_message {
 	struct list_head list;		/* Request queueing. */
 	unsigned long long psmid;	/* Message id. */
-	void *message;			/* Pointer to message buffer. */
-	size_t length;			/* Message length. */
+	void *msg;			/* Pointer to message buffer. */
+	unsigned int len;		/* actual msg len in msg buffer */
+	unsigned int bufsize;		/* allocated msg buffer size */
+	u16 flags;			/* Flags, see AP_MSG_FLAG_xxx */
+	struct ap_fi fi;		/* Failure Injection cmd */
 	int rc;				/* Return code for this message */
-
 	void *private;			/* ap driver private pointer. */
-	unsigned int special:1;		/* Used for special commands. */
 	/* receive is called from tasklet context */
 	void (*receive)(struct ap_queue *, struct ap_message *,
 			struct ap_message *);
 };
 
+#define AP_MSG_FLAG_SPECIAL  1		/* flag msg as 'special' with NQAP */
+
 /**
  * ap_init_message() - Initialize ap_message.
  * Initialize a message before using. Otherwise this might result in
@@ -222,16 +262,10 @@
  */
 static inline void ap_release_message(struct ap_message *ap_msg)
 {
-	kzfree(ap_msg->message);
+	kzfree(ap_msg->msg);
 	kzfree(ap_msg->private);
 }
 
-#define for_each_ap_card(_ac) \
-	list_for_each_entry(_ac, &ap_card_list, list)
-
-#define for_each_ap_queue(_aq, _ac) \
-	list_for_each_entry(_aq, &(_ac)->queues, list)
-
 /*
  * Note: don't use ap_send/ap_recv after using ap_queue_message
  * for the first time. Otherwise the ap message queue will get
@@ -240,15 +274,15 @@
 int ap_send(ap_qid_t, unsigned long long, void *, size_t);
 int ap_recv(ap_qid_t, unsigned long long *, void *, size_t);
 
-enum ap_wait ap_sm_event(struct ap_queue *aq, enum ap_event event);
-enum ap_wait ap_sm_event_loop(struct ap_queue *aq, enum ap_event event);
+enum ap_sm_wait ap_sm_event(struct ap_queue *aq, enum ap_sm_event event);
+enum ap_sm_wait ap_sm_event_loop(struct ap_queue *aq, enum ap_sm_event event);
 
-void ap_queue_message(struct ap_queue *aq, struct ap_message *ap_msg);
+int ap_queue_message(struct ap_queue *aq, struct ap_message *ap_msg);
 void ap_cancel_message(struct ap_queue *aq, struct ap_message *ap_msg);
 void ap_flush_queue(struct ap_queue *aq);
 
 void *ap_airq_ptr(void);
-void ap_wait(enum ap_wait wait);
+void ap_wait(enum ap_sm_wait wait);
 void ap_request_timeout(struct timer_list *t);
 void ap_bus_force_rescan(void);
 
@@ -259,12 +293,10 @@
 struct ap_queue *ap_queue_create(ap_qid_t qid, int device_type);
 void ap_queue_prepare_remove(struct ap_queue *aq);
 void ap_queue_remove(struct ap_queue *aq);
-void ap_queue_suspend(struct ap_device *ap_dev);
-void ap_queue_resume(struct ap_device *ap_dev);
-void ap_queue_reinit_state(struct ap_queue *aq);
+void ap_queue_init_state(struct ap_queue *aq);
 
-struct ap_card *ap_card_create(int id, int queue_depth, int raw_device_type,
-			       int comp_device_type, unsigned int functions);
+struct ap_card *ap_card_create(int id, int queue_depth, int raw_type,
+			       int comp_type, unsigned int functions, int ml);
 
 struct ap_perms {
 	unsigned long ioctlm[BITS_TO_LONGS(AP_IOCTLS)];
@@ -275,6 +307,16 @@
 extern struct mutex ap_perms_mutex;
 
 /*
+ * Get ap_queue device for this qid.
+ * Returns ptr to the struct ap_queue device or NULL if there
+ * was no ap_queue device with this qid found. When something is
+ * found, the reference count of the embedded device is increased.
+ * So the caller has to decrease the reference count after use
+ * with a call to put_device(&aq->ap_dev.device).
+ */
+struct ap_queue *ap_get_qdev(ap_qid_t qid);
+
+/*
  * check APQN for owned/reserved by ap bus and default driver(s).
  * Checks if this APQN is or will be in use by the ap bus
  * and the default set of drivers.
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/crypto/ap_card.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/crypto/ap_card.c
@@ -12,6 +12,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <asm/facility.h>
+#include <asm/sclp.h>
 
 #include "ap_bus.h"
 
@@ -23,7 +24,7 @@
 {
 	struct ap_card *ac = to_ap_card(dev);
 
-	return snprintf(buf, PAGE_SIZE, "%d\n", ac->ap_dev.device_type);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", ac->ap_dev.device_type);
 }
 
 static DEVICE_ATTR_RO(hwtype);
@@ -33,7 +34,7 @@
 {
 	struct ap_card *ac = to_ap_card(dev);
 
-	return snprintf(buf, PAGE_SIZE, "%d\n", ac->raw_hwtype);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", ac->raw_hwtype);
 }
 
 static DEVICE_ATTR_RO(raw_hwtype);
@@ -43,7 +44,7 @@
 {
 	struct ap_card *ac = to_ap_card(dev);
 
-	return snprintf(buf, PAGE_SIZE, "%d\n", ac->queue_depth);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", ac->queue_depth);
 }
 
 static DEVICE_ATTR_RO(depth);
@@ -53,7 +54,7 @@
 {
 	struct ap_card *ac = to_ap_card(dev);
 
-	return snprintf(buf, PAGE_SIZE, "0x%08X\n", ac->functions);
+	return scnprintf(buf, PAGE_SIZE, "0x%08X\n", ac->functions);
 }
 
 static DEVICE_ATTR_RO(ap_functions);
@@ -63,27 +64,29 @@
 				  char *buf)
 {
 	struct ap_card *ac = to_ap_card(dev);
-	unsigned int req_cnt;
+	u64 req_cnt;
 
 	req_cnt = 0;
-	spin_lock_bh(&ap_list_lock);
-	req_cnt = atomic_read(&ac->total_request_count);
-	spin_unlock_bh(&ap_list_lock);
-	return snprintf(buf, PAGE_SIZE, "%d\n", req_cnt);
+	spin_lock_bh(&ap_queues_lock);
+	req_cnt = atomic64_read(&ac->total_request_count);
+	spin_unlock_bh(&ap_queues_lock);
+	return scnprintf(buf, PAGE_SIZE, "%llu\n", req_cnt);
 }
 
 static ssize_t request_count_store(struct device *dev,
 				   struct device_attribute *attr,
 				   const char *buf, size_t count)
 {
-	struct ap_card *ac = to_ap_card(dev);
+	int bkt;
 	struct ap_queue *aq;
+	struct ap_card *ac = to_ap_card(dev);
 
-	spin_lock_bh(&ap_list_lock);
-	for_each_ap_queue(aq, ac)
-		aq->total_request_count = 0;
-	spin_unlock_bh(&ap_list_lock);
-	atomic_set(&ac->total_request_count, 0);
+	spin_lock_bh(&ap_queues_lock);
+	hash_for_each(ap_queues, bkt, aq, hnode)
+		if (ac == aq->card)
+			aq->total_request_count = 0;
+	spin_unlock_bh(&ap_queues_lock);
+	atomic64_set(&ac->total_request_count, 0);
 
 	return count;
 }
@@ -93,16 +96,18 @@
 static ssize_t requestq_count_show(struct device *dev,
 				   struct device_attribute *attr, char *buf)
 {
-	struct ap_card *ac = to_ap_card(dev);
+	int bkt;
 	struct ap_queue *aq;
 	unsigned int reqq_cnt;
+	struct ap_card *ac = to_ap_card(dev);
 
 	reqq_cnt = 0;
-	spin_lock_bh(&ap_list_lock);
-	for_each_ap_queue(aq, ac)
-		reqq_cnt += aq->requestq_count;
-	spin_unlock_bh(&ap_list_lock);
-	return snprintf(buf, PAGE_SIZE, "%d\n", reqq_cnt);
+	spin_lock_bh(&ap_queues_lock);
+	hash_for_each(ap_queues, bkt, aq, hnode)
+		if (ac == aq->card)
+			reqq_cnt += aq->requestq_count;
+	spin_unlock_bh(&ap_queues_lock);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", reqq_cnt);
 }
 
 static DEVICE_ATTR_RO(requestq_count);
@@ -110,16 +115,18 @@
 static ssize_t pendingq_count_show(struct device *dev,
 				   struct device_attribute *attr, char *buf)
 {
-	struct ap_card *ac = to_ap_card(dev);
+	int bkt;
 	struct ap_queue *aq;
 	unsigned int penq_cnt;
+	struct ap_card *ac = to_ap_card(dev);
 
 	penq_cnt = 0;
-	spin_lock_bh(&ap_list_lock);
-	for_each_ap_queue(aq, ac)
-		penq_cnt += aq->pendingq_count;
-	spin_unlock_bh(&ap_list_lock);
-	return snprintf(buf, PAGE_SIZE, "%d\n", penq_cnt);
+	spin_lock_bh(&ap_queues_lock);
+	hash_for_each(ap_queues, bkt, aq, hnode)
+		if (ac == aq->card)
+			penq_cnt += aq->pendingq_count;
+	spin_unlock_bh(&ap_queues_lock);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", penq_cnt);
 }
 
 static DEVICE_ATTR_RO(pendingq_count);
@@ -127,11 +134,54 @@
 static ssize_t modalias_show(struct device *dev,
 			     struct device_attribute *attr, char *buf)
 {
-	return sprintf(buf, "ap:t%02X\n", to_ap_dev(dev)->device_type);
+	return scnprintf(buf, PAGE_SIZE, "ap:t%02X\n",
+			 to_ap_dev(dev)->device_type);
 }
 
 static DEVICE_ATTR_RO(modalias);
 
+static ssize_t config_show(struct device *dev,
+			   struct device_attribute *attr, char *buf)
+{
+	struct ap_card *ac = to_ap_card(dev);
+
+	return scnprintf(buf, PAGE_SIZE, "%d\n", ac->config ? 1 : 0);
+}
+
+static ssize_t config_store(struct device *dev,
+			    struct device_attribute *attr,
+			    const char *buf, size_t count)
+{
+	int rc = 0, cfg;
+	struct ap_card *ac = to_ap_card(dev);
+
+	if (sscanf(buf, "%d\n", &cfg) != 1 || cfg < 0 || cfg > 1)
+		return -EINVAL;
+
+	if (cfg && !ac->config)
+		rc = sclp_ap_configure(ac->id);
+	else if (!cfg && ac->config)
+		rc = sclp_ap_deconfigure(ac->id);
+	if (rc)
+		return rc;
+
+	ac->config = cfg ? true : false;
+
+	return count;
+}
+
+static DEVICE_ATTR_RW(config);
+
+static ssize_t max_msg_size_show(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	struct ap_card *ac = to_ap_card(dev);
+
+	return scnprintf(buf, PAGE_SIZE, "%u\n", ac->maxmsgsize);
+}
+
+static DEVICE_ATTR_RO(max_msg_size);
+
 static struct attribute *ap_card_dev_attrs[] = {
 	&dev_attr_hwtype.attr,
 	&dev_attr_raw_hwtype.attr,
@@ -141,6 +191,8 @@
 	&dev_attr_requestq_count.attr,
 	&dev_attr_pendingq_count.attr,
 	&dev_attr_modalias.attr,
+	&dev_attr_config.attr,
+	&dev_attr_max_msg_size.attr,
 	NULL
 };
 
@@ -162,24 +214,17 @@
 {
 	struct ap_card *ac = to_ap_card(dev);
 
-	if (!list_empty(&ac->list)) {
-		spin_lock_bh(&ap_list_lock);
-		list_del_init(&ac->list);
-		spin_unlock_bh(&ap_list_lock);
-	}
 	kfree(ac);
 }
 
 struct ap_card *ap_card_create(int id, int queue_depth, int raw_type,
-			       int comp_type, unsigned int functions)
+			       int comp_type, unsigned int functions, int ml)
 {
 	struct ap_card *ac;
 
 	ac = kzalloc(sizeof(*ac), GFP_KERNEL);
 	if (!ac)
 		return NULL;
-	INIT_LIST_HEAD(&ac->list);
-	INIT_LIST_HEAD(&ac->queues);
 	ac->ap_dev.device.release = ap_card_device_release;
 	ac->ap_dev.device.type = &ap_card_type;
 	ac->ap_dev.device_type = comp_type;
@@ -187,5 +232,8 @@
 	ac->queue_depth = queue_depth;
 	ac->functions = functions;
 	ac->id = id;
+	ac->maxmsgsize = ml > 0 ?
+		ml * AP_TAPQ_ML_FIELD_CHUNK_SIZE : AP_DEFAULT_MAX_MSG_SIZE;
+
 	return ac;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/crypto/ap_debug.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/crypto/ap_debug.h
@@ -20,6 +20,14 @@
 
 #define AP_DBF(...)					\
 	debug_sprintf_event(ap_dbf_info, ##__VA_ARGS__)
+#define AP_DBF_ERR(...)					\
+	debug_sprintf_event(ap_dbf_info, DBF_ERR, ##__VA_ARGS__)
+#define AP_DBF_WARN(...)					\
+	debug_sprintf_event(ap_dbf_info, DBF_WARN, ##__VA_ARGS__)
+#define AP_DBF_INFO(...)					\
+	debug_sprintf_event(ap_dbf_info, DBF_INFO, ##__VA_ARGS__)
+#define AP_DBF_DBG(...)					\
+	debug_sprintf_event(ap_dbf_info, DBF_DEBUG, ##__VA_ARGS__)
 
 extern debug_info_t *ap_dbf_info;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/crypto/ap_queue.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/crypto/ap_queue.c
@@ -69,9 +69,9 @@
  */
 static inline struct ap_queue_status
 __ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length,
-	  unsigned int special)
+	  int special)
 {
-	if (special == 1)
+	if (special)
 		qid |= 0x400000UL;
 	return ap_nqap(qid, psmid, msg, length);
 }
@@ -119,9 +119,9 @@
 
 /* State machine definitions and helpers */
 
-static enum ap_wait ap_sm_nop(struct ap_queue *aq)
+static enum ap_sm_wait ap_sm_nop(struct ap_queue *aq)
 {
-	return AP_WAIT_NONE;
+	return AP_SM_WAIT_NONE;
 }
 
 /**
@@ -129,18 +129,19 @@
  *	not change the state of the device.
  * @aq: pointer to the AP queue
  *
- * Returns AP_WAIT_NONE, AP_WAIT_AGAIN, or AP_WAIT_INTERRUPT
+ * Returns AP_SM_WAIT_NONE, AP_SM_WAIT_AGAIN, or AP_SM_WAIT_INTERRUPT
  */
 static struct ap_queue_status ap_sm_recv(struct ap_queue *aq)
 {
 	struct ap_queue_status status;
 	struct ap_message *ap_msg;
+	bool found = false;
 
 	status = ap_dqap(aq->qid, &aq->reply->psmid,
-			 aq->reply->message, aq->reply->length);
+			 aq->reply->msg, aq->reply->bufsize);
 	switch (status.response_code) {
 	case AP_RESPONSE_NORMAL:
-		aq->queue_count--;
+		aq->queue_count = max_t(int, 0, aq->queue_count - 1);
 		if (aq->queue_count > 0)
 			mod_timer(&aq->timeout,
 				  jiffies + aq->request_timeout);
@@ -150,9 +151,15 @@
 			list_del_init(&ap_msg->list);
 			aq->pendingq_count--;
 			ap_msg->receive(aq, ap_msg, aq->reply);
+			found = true;
 			break;
 		}
-		/* fall through */
+		if (!found) {
+			AP_DBF_WARN("%s unassociated reply psmid=0x%016llx on 0x%02x.%04x\n",
+				    __func__, aq->reply->psmid,
+				    AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
+		}
+		fallthrough;
 	case AP_RESPONSE_NO_PENDING_REPLY:
 		if (!status.queue_empty || aq->queue_count <= 0)
 			break;
@@ -172,56 +179,35 @@
  * ap_sm_read(): Receive pending reply messages from an AP queue.
  * @aq: pointer to the AP queue
  *
- * Returns AP_WAIT_NONE, AP_WAIT_AGAIN, or AP_WAIT_INTERRUPT
+ * Returns AP_SM_WAIT_NONE, AP_SM_WAIT_AGAIN, or AP_SM_WAIT_INTERRUPT
  */
-static enum ap_wait ap_sm_read(struct ap_queue *aq)
+static enum ap_sm_wait ap_sm_read(struct ap_queue *aq)
 {
 	struct ap_queue_status status;
 
 	if (!aq->reply)
-		return AP_WAIT_NONE;
+		return AP_SM_WAIT_NONE;
 	status = ap_sm_recv(aq);
 	switch (status.response_code) {
 	case AP_RESPONSE_NORMAL:
 		if (aq->queue_count > 0) {
-			aq->state = AP_STATE_WORKING;
-			return AP_WAIT_AGAIN;
+			aq->sm_state = AP_SM_STATE_WORKING;
+			return AP_SM_WAIT_AGAIN;
 		}
-		aq->state = AP_STATE_IDLE;
-		return AP_WAIT_NONE;
+		aq->sm_state = AP_SM_STATE_IDLE;
+		return AP_SM_WAIT_NONE;
 	case AP_RESPONSE_NO_PENDING_REPLY:
 		if (aq->queue_count > 0)
-			return AP_WAIT_INTERRUPT;
-		aq->state = AP_STATE_IDLE;
-		return AP_WAIT_NONE;
-	default:
-		aq->state = AP_STATE_BORKED;
-		return AP_WAIT_NONE;
-	}
-}
-
-/**
- * ap_sm_suspend_read(): Receive pending reply messages from an AP queue
- * without changing the device state in between. In suspend mode we don't
- * allow sending new requests, therefore just fetch pending replies.
- * @aq: pointer to the AP queue
- *
- * Returns AP_WAIT_NONE or AP_WAIT_AGAIN
- */
-static enum ap_wait ap_sm_suspend_read(struct ap_queue *aq)
-{
-	struct ap_queue_status status;
-
-	if (!aq->reply)
-		return AP_WAIT_NONE;
-	status = ap_sm_recv(aq);
-	switch (status.response_code) {
-	case AP_RESPONSE_NORMAL:
-		if (aq->queue_count > 0)
-			return AP_WAIT_AGAIN;
-		/* fall through */
+			return AP_SM_WAIT_INTERRUPT;
+		aq->sm_state = AP_SM_STATE_IDLE;
+		return AP_SM_WAIT_NONE;
 	default:
-		return AP_WAIT_NONE;
+		aq->dev_state = AP_DEV_STATE_ERROR;
+		aq->last_err_rc = status.response_code;
+		AP_DBF_WARN("%s RC 0x%02x on 0x%02x.%04x -> AP_DEV_STATE_ERROR\n",
+			    __func__, status.response_code,
+			    AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
+		return AP_SM_WAIT_NONE;
 	}
 }
 
@@ -229,48 +215,64 @@
  * ap_sm_write(): Send messages from the request queue to an AP queue.
  * @aq: pointer to the AP queue
  *
- * Returns AP_WAIT_NONE, AP_WAIT_AGAIN, or AP_WAIT_INTERRUPT
+ * Returns AP_SM_WAIT_NONE, AP_SM_WAIT_AGAIN, or AP_SM_WAIT_INTERRUPT
  */
-static enum ap_wait ap_sm_write(struct ap_queue *aq)
+static enum ap_sm_wait ap_sm_write(struct ap_queue *aq)
 {
 	struct ap_queue_status status;
 	struct ap_message *ap_msg;
+	ap_qid_t qid = aq->qid;
 
 	if (aq->requestq_count <= 0)
-		return AP_WAIT_NONE;
+		return AP_SM_WAIT_NONE;
 	/* Start the next request on the queue. */
 	ap_msg = list_entry(aq->requestq.next, struct ap_message, list);
-	status = __ap_send(aq->qid, ap_msg->psmid,
-			   ap_msg->message, ap_msg->length, ap_msg->special);
+#ifdef CONFIG_ZCRYPT_DEBUG
+	if (ap_msg->fi.action == AP_FI_ACTION_NQAP_QID_INVAL) {
+		AP_DBF_WARN("%s fi cmd 0x%04x: forcing invalid qid 0xFF00\n",
+			    __func__, ap_msg->fi.cmd);
+		qid = 0xFF00;
+	}
+#endif
+	status = __ap_send(qid, ap_msg->psmid,
+			   ap_msg->msg, ap_msg->len,
+			   ap_msg->flags & AP_MSG_FLAG_SPECIAL);
 	switch (status.response_code) {
 	case AP_RESPONSE_NORMAL:
-		aq->queue_count++;
+		aq->queue_count = max_t(int, 1, aq->queue_count + 1);
 		if (aq->queue_count == 1)
 			mod_timer(&aq->timeout, jiffies + aq->request_timeout);
 		list_move_tail(&ap_msg->list, &aq->pendingq);
 		aq->requestq_count--;
 		aq->pendingq_count++;
 		if (aq->queue_count < aq->card->queue_depth) {
-			aq->state = AP_STATE_WORKING;
-			return AP_WAIT_AGAIN;
+			aq->sm_state = AP_SM_STATE_WORKING;
+			return AP_SM_WAIT_AGAIN;
 		}
-		/* fall through */
+		fallthrough;
 	case AP_RESPONSE_Q_FULL:
-		aq->state = AP_STATE_QUEUE_FULL;
-		return AP_WAIT_INTERRUPT;
+		aq->sm_state = AP_SM_STATE_QUEUE_FULL;
+		return AP_SM_WAIT_INTERRUPT;
 	case AP_RESPONSE_RESET_IN_PROGRESS:
-		aq->state = AP_STATE_RESET_WAIT;
-		return AP_WAIT_TIMEOUT;
+		aq->sm_state = AP_SM_STATE_RESET_WAIT;
+		return AP_SM_WAIT_TIMEOUT;
+	case AP_RESPONSE_INVALID_DOMAIN:
+		AP_DBF(DBF_WARN, "AP_RESPONSE_INVALID_DOMAIN on NQAP\n");
+		fallthrough;
 	case AP_RESPONSE_MESSAGE_TOO_BIG:
 	case AP_RESPONSE_REQ_FAC_NOT_INST:
 		list_del_init(&ap_msg->list);
 		aq->requestq_count--;
 		ap_msg->rc = -EINVAL;
 		ap_msg->receive(aq, ap_msg, NULL);
-		return AP_WAIT_AGAIN;
+		return AP_SM_WAIT_AGAIN;
 	default:
-		aq->state = AP_STATE_BORKED;
-		return AP_WAIT_NONE;
+		aq->dev_state = AP_DEV_STATE_ERROR;
+		aq->last_err_rc = status.response_code;
+		AP_DBF_WARN("%s RC 0x%02x on 0x%02x.%04x -> AP_DEV_STATE_ERROR\n",
+			    __func__, status.response_code,
+			    AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
+		return AP_SM_WAIT_NONE;
 	}
 }
 
@@ -278,9 +280,9 @@
  * ap_sm_read_write(): Send and receive messages to/from an AP queue.
  * @aq: pointer to the AP queue
  *
- * Returns AP_WAIT_NONE, AP_WAIT_AGAIN, or AP_WAIT_INTERRUPT
+ * Returns AP_SM_WAIT_NONE, AP_SM_WAIT_AGAIN, or AP_SM_WAIT_INTERRUPT
  */
-static enum ap_wait ap_sm_read_write(struct ap_queue *aq)
+static enum ap_sm_wait ap_sm_read_write(struct ap_queue *aq)
 {
 	return min(ap_sm_read(aq), ap_sm_write(aq));
 }
@@ -291,7 +293,7 @@
  *
  * Submit the Reset command to an AP queue.
  */
-static enum ap_wait ap_sm_reset(struct ap_queue *aq)
+static enum ap_sm_wait ap_sm_reset(struct ap_queue *aq)
 {
 	struct ap_queue_status status;
 
@@ -299,17 +301,16 @@
 	switch (status.response_code) {
 	case AP_RESPONSE_NORMAL:
 	case AP_RESPONSE_RESET_IN_PROGRESS:
-		aq->state = AP_STATE_RESET_WAIT;
+		aq->sm_state = AP_SM_STATE_RESET_WAIT;
 		aq->interrupt = AP_INTR_DISABLED;
-		return AP_WAIT_TIMEOUT;
-	case AP_RESPONSE_BUSY:
-		return AP_WAIT_TIMEOUT;
-	case AP_RESPONSE_Q_NOT_AVAIL:
-	case AP_RESPONSE_DECONFIGURED:
-	case AP_RESPONSE_CHECKSTOPPED:
+		return AP_SM_WAIT_TIMEOUT;
 	default:
-		aq->state = AP_STATE_BORKED;
-		return AP_WAIT_NONE;
+		aq->dev_state = AP_DEV_STATE_ERROR;
+		aq->last_err_rc = status.response_code;
+		AP_DBF_WARN("%s RC 0x%02x on 0x%02x.%04x -> AP_DEV_STATE_ERROR\n",
+			    __func__, status.response_code,
+			    AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
+		return AP_SM_WAIT_NONE;
 	}
 }
 
@@ -319,7 +320,7 @@
  *
  * Returns AP_POLL_IMMEDIATELY, AP_POLL_AFTER_TIMEROUT or 0.
  */
-static enum ap_wait ap_sm_reset_wait(struct ap_queue *aq)
+static enum ap_sm_wait ap_sm_reset_wait(struct ap_queue *aq)
 {
 	struct ap_queue_status status;
 	void *lsi_ptr;
@@ -335,20 +336,24 @@
 	case AP_RESPONSE_NORMAL:
 		lsi_ptr = ap_airq_ptr();
 		if (lsi_ptr && ap_queue_enable_interruption(aq, lsi_ptr) == 0)
-			aq->state = AP_STATE_SETIRQ_WAIT;
+			aq->sm_state = AP_SM_STATE_SETIRQ_WAIT;
 		else
-			aq->state = (aq->queue_count > 0) ?
-				AP_STATE_WORKING : AP_STATE_IDLE;
-		return AP_WAIT_AGAIN;
+			aq->sm_state = (aq->queue_count > 0) ?
+				AP_SM_STATE_WORKING : AP_SM_STATE_IDLE;
+		return AP_SM_WAIT_AGAIN;
 	case AP_RESPONSE_BUSY:
 	case AP_RESPONSE_RESET_IN_PROGRESS:
-		return AP_WAIT_TIMEOUT;
+		return AP_SM_WAIT_TIMEOUT;
 	case AP_RESPONSE_Q_NOT_AVAIL:
 	case AP_RESPONSE_DECONFIGURED:
 	case AP_RESPONSE_CHECKSTOPPED:
 	default:
-		aq->state = AP_STATE_BORKED;
-		return AP_WAIT_NONE;
+		aq->dev_state = AP_DEV_STATE_ERROR;
+		aq->last_err_rc = status.response_code;
+		AP_DBF_WARN("%s RC 0x%02x on 0x%02x.%04x -> AP_DEV_STATE_ERROR\n",
+			    __func__, status.response_code,
+			    AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
+		return AP_SM_WAIT_NONE;
 	}
 }
 
@@ -358,7 +363,7 @@
  *
  * Returns AP_POLL_IMMEDIATELY, AP_POLL_AFTER_TIMEROUT or 0.
  */
-static enum ap_wait ap_sm_setirq_wait(struct ap_queue *aq)
+static enum ap_sm_wait ap_sm_setirq_wait(struct ap_queue *aq)
 {
 	struct ap_queue_status status;
 
@@ -372,106 +377,75 @@
 	if (status.irq_enabled == 1) {
 		/* Irqs are now enabled */
 		aq->interrupt = AP_INTR_ENABLED;
-		aq->state = (aq->queue_count > 0) ?
-			AP_STATE_WORKING : AP_STATE_IDLE;
+		aq->sm_state = (aq->queue_count > 0) ?
+			AP_SM_STATE_WORKING : AP_SM_STATE_IDLE;
 	}
 
 	switch (status.response_code) {
 	case AP_RESPONSE_NORMAL:
 		if (aq->queue_count > 0)
-			return AP_WAIT_AGAIN;
-		/* fallthrough */
+			return AP_SM_WAIT_AGAIN;
+		fallthrough;
 	case AP_RESPONSE_NO_PENDING_REPLY:
-		return AP_WAIT_TIMEOUT;
+		return AP_SM_WAIT_TIMEOUT;
 	default:
-		aq->state = AP_STATE_BORKED;
-		return AP_WAIT_NONE;
+		aq->dev_state = AP_DEV_STATE_ERROR;
+		aq->last_err_rc = status.response_code;
+		AP_DBF_WARN("%s RC 0x%02x on 0x%02x.%04x -> AP_DEV_STATE_ERROR\n",
+			    __func__, status.response_code,
+			    AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
+		return AP_SM_WAIT_NONE;
 	}
 }
 
 /*
  * AP state machine jump table
  */
-static ap_func_t *ap_jumptable[NR_AP_STATES][NR_AP_EVENTS] = {
-	[AP_STATE_RESET_START] = {
-		[AP_EVENT_POLL] = ap_sm_reset,
-		[AP_EVENT_TIMEOUT] = ap_sm_nop,
-	},
-	[AP_STATE_RESET_WAIT] = {
-		[AP_EVENT_POLL] = ap_sm_reset_wait,
-		[AP_EVENT_TIMEOUT] = ap_sm_nop,
-	},
-	[AP_STATE_SETIRQ_WAIT] = {
-		[AP_EVENT_POLL] = ap_sm_setirq_wait,
-		[AP_EVENT_TIMEOUT] = ap_sm_nop,
+static ap_func_t *ap_jumptable[NR_AP_SM_STATES][NR_AP_SM_EVENTS] = {
+	[AP_SM_STATE_RESET_START] = {
+		[AP_SM_EVENT_POLL] = ap_sm_reset,
+		[AP_SM_EVENT_TIMEOUT] = ap_sm_nop,
 	},
-	[AP_STATE_IDLE] = {
-		[AP_EVENT_POLL] = ap_sm_write,
-		[AP_EVENT_TIMEOUT] = ap_sm_nop,
+	[AP_SM_STATE_RESET_WAIT] = {
+		[AP_SM_EVENT_POLL] = ap_sm_reset_wait,
+		[AP_SM_EVENT_TIMEOUT] = ap_sm_nop,
 	},
-	[AP_STATE_WORKING] = {
-		[AP_EVENT_POLL] = ap_sm_read_write,
-		[AP_EVENT_TIMEOUT] = ap_sm_reset,
+	[AP_SM_STATE_SETIRQ_WAIT] = {
+		[AP_SM_EVENT_POLL] = ap_sm_setirq_wait,
+		[AP_SM_EVENT_TIMEOUT] = ap_sm_nop,
 	},
-	[AP_STATE_QUEUE_FULL] = {
-		[AP_EVENT_POLL] = ap_sm_read,
-		[AP_EVENT_TIMEOUT] = ap_sm_reset,
+	[AP_SM_STATE_IDLE] = {
+		[AP_SM_EVENT_POLL] = ap_sm_write,
+		[AP_SM_EVENT_TIMEOUT] = ap_sm_nop,
 	},
-	[AP_STATE_SUSPEND_WAIT] = {
-		[AP_EVENT_POLL] = ap_sm_suspend_read,
-		[AP_EVENT_TIMEOUT] = ap_sm_nop,
+	[AP_SM_STATE_WORKING] = {
+		[AP_SM_EVENT_POLL] = ap_sm_read_write,
+		[AP_SM_EVENT_TIMEOUT] = ap_sm_reset,
 	},
-	[AP_STATE_REMOVE] = {
-		[AP_EVENT_POLL] = ap_sm_nop,
-		[AP_EVENT_TIMEOUT] = ap_sm_nop,
-	},
-	[AP_STATE_UNBOUND] = {
-		[AP_EVENT_POLL] = ap_sm_nop,
-		[AP_EVENT_TIMEOUT] = ap_sm_nop,
-	},
-	[AP_STATE_BORKED] = {
-		[AP_EVENT_POLL] = ap_sm_nop,
-		[AP_EVENT_TIMEOUT] = ap_sm_nop,
+	[AP_SM_STATE_QUEUE_FULL] = {
+		[AP_SM_EVENT_POLL] = ap_sm_read,
+		[AP_SM_EVENT_TIMEOUT] = ap_sm_reset,
 	},
 };
 
-enum ap_wait ap_sm_event(struct ap_queue *aq, enum ap_event event)
+enum ap_sm_wait ap_sm_event(struct ap_queue *aq, enum ap_sm_event event)
 {
-	return ap_jumptable[aq->state][event](aq);
+	if (aq->dev_state > AP_DEV_STATE_UNINITIATED)
+		return ap_jumptable[aq->sm_state][event](aq);
+	else
+		return AP_SM_WAIT_NONE;
 }
 
-enum ap_wait ap_sm_event_loop(struct ap_queue *aq, enum ap_event event)
+enum ap_sm_wait ap_sm_event_loop(struct ap_queue *aq, enum ap_sm_event event)
 {
-	enum ap_wait wait;
+	enum ap_sm_wait wait;
 
-	while ((wait = ap_sm_event(aq, event)) == AP_WAIT_AGAIN)
+	while ((wait = ap_sm_event(aq, event)) == AP_SM_WAIT_AGAIN)
 		;
 	return wait;
 }
 
 /*
- * Power management for queue devices
- */
-void ap_queue_suspend(struct ap_device *ap_dev)
-{
-	struct ap_queue *aq = to_ap_queue(&ap_dev->device);
-
-	/* Poll on the device until all requests are finished. */
-	spin_lock_bh(&aq->lock);
-	aq->state = AP_STATE_SUSPEND_WAIT;
-	while (ap_sm_event(aq, AP_EVENT_POLL) != AP_WAIT_NONE)
-		;
-	aq->state = AP_STATE_BORKED;
-	spin_unlock_bh(&aq->lock);
-}
-EXPORT_SYMBOL(ap_queue_suspend);
-
-void ap_queue_resume(struct ap_device *ap_dev)
-{
-}
-EXPORT_SYMBOL(ap_queue_resume);
-
-/*
  * AP queue related attributes.
  */
 static ssize_t request_count_show(struct device *dev,
@@ -479,12 +453,20 @@
 				  char *buf)
 {
 	struct ap_queue *aq = to_ap_queue(dev);
-	unsigned int req_cnt;
+	bool valid = false;
+	u64 req_cnt;
 
 	spin_lock_bh(&aq->lock);
-	req_cnt = aq->total_request_count;
+	if (aq->dev_state > AP_DEV_STATE_UNINITIATED) {
+		req_cnt = aq->total_request_count;
+		valid = true;
+	}
 	spin_unlock_bh(&aq->lock);
-	return snprintf(buf, PAGE_SIZE, "%d\n", req_cnt);
+
+	if (valid)
+		return scnprintf(buf, PAGE_SIZE, "%llu\n", req_cnt);
+	else
+		return scnprintf(buf, PAGE_SIZE, "-\n");
 }
 
 static ssize_t request_count_store(struct device *dev,
@@ -509,9 +491,10 @@
 	unsigned int reqq_cnt = 0;
 
 	spin_lock_bh(&aq->lock);
-	reqq_cnt = aq->requestq_count;
+	if (aq->dev_state > AP_DEV_STATE_UNINITIATED)
+		reqq_cnt = aq->requestq_count;
 	spin_unlock_bh(&aq->lock);
-	return snprintf(buf, PAGE_SIZE, "%d\n", reqq_cnt);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", reqq_cnt);
 }
 
 static DEVICE_ATTR_RO(requestq_count);
@@ -523,9 +506,10 @@
 	unsigned int penq_cnt = 0;
 
 	spin_lock_bh(&aq->lock);
-	penq_cnt = aq->pendingq_count;
+	if (aq->dev_state > AP_DEV_STATE_UNINITIATED)
+		penq_cnt = aq->pendingq_count;
 	spin_unlock_bh(&aq->lock);
-	return snprintf(buf, PAGE_SIZE, "%d\n", penq_cnt);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", penq_cnt);
 }
 
 static DEVICE_ATTR_RO(pendingq_count);
@@ -537,17 +521,17 @@
 	int rc = 0;
 
 	spin_lock_bh(&aq->lock);
-	switch (aq->state) {
-	case AP_STATE_RESET_START:
-	case AP_STATE_RESET_WAIT:
-		rc = snprintf(buf, PAGE_SIZE, "Reset in progress.\n");
+	switch (aq->sm_state) {
+	case AP_SM_STATE_RESET_START:
+	case AP_SM_STATE_RESET_WAIT:
+		rc = scnprintf(buf, PAGE_SIZE, "Reset in progress.\n");
 		break;
-	case AP_STATE_WORKING:
-	case AP_STATE_QUEUE_FULL:
-		rc = snprintf(buf, PAGE_SIZE, "Reset Timer armed.\n");
+	case AP_SM_STATE_WORKING:
+	case AP_SM_STATE_QUEUE_FULL:
+		rc = scnprintf(buf, PAGE_SIZE, "Reset Timer armed.\n");
 		break;
 	default:
-		rc = snprintf(buf, PAGE_SIZE, "No Reset Timer set.\n");
+		rc = scnprintf(buf, PAGE_SIZE, "No Reset Timer set.\n");
 	}
 	spin_unlock_bh(&aq->lock);
 	return rc;
@@ -561,8 +545,8 @@
 
 	spin_lock_bh(&aq->lock);
 	__ap_flush_queue(aq);
-	aq->state = AP_STATE_RESET_START;
-	ap_wait(ap_sm_event(aq, AP_EVENT_POLL));
+	aq->sm_state = AP_SM_STATE_RESET_START;
+	ap_wait(ap_sm_event(aq, AP_SM_EVENT_POLL));
 	spin_unlock_bh(&aq->lock);
 
 	AP_DBF(DBF_INFO, "reset queue=%02x.%04x triggered by user\n",
@@ -580,24 +564,150 @@
 	int rc = 0;
 
 	spin_lock_bh(&aq->lock);
-	if (aq->state == AP_STATE_SETIRQ_WAIT)
-		rc = snprintf(buf, PAGE_SIZE, "Enable Interrupt pending.\n");
+	if (aq->sm_state == AP_SM_STATE_SETIRQ_WAIT)
+		rc = scnprintf(buf, PAGE_SIZE, "Enable Interrupt pending.\n");
 	else if (aq->interrupt == AP_INTR_ENABLED)
-		rc = snprintf(buf, PAGE_SIZE, "Interrupts enabled.\n");
+		rc = scnprintf(buf, PAGE_SIZE, "Interrupts enabled.\n");
 	else
-		rc = snprintf(buf, PAGE_SIZE, "Interrupts disabled.\n");
+		rc = scnprintf(buf, PAGE_SIZE, "Interrupts disabled.\n");
 	spin_unlock_bh(&aq->lock);
 	return rc;
 }
 
 static DEVICE_ATTR_RO(interrupt);
 
+static ssize_t config_show(struct device *dev,
+			     struct device_attribute *attr, char *buf)
+{
+	struct ap_queue *aq = to_ap_queue(dev);
+	int rc;
+
+	spin_lock_bh(&aq->lock);
+	rc = scnprintf(buf, PAGE_SIZE, "%d\n", aq->config ? 1 : 0);
+	spin_unlock_bh(&aq->lock);
+	return rc;
+}
+
+static DEVICE_ATTR_RO(config);
+
+#ifdef CONFIG_ZCRYPT_DEBUG
+static ssize_t states_show(struct device *dev,
+			   struct device_attribute *attr, char *buf)
+{
+	struct ap_queue *aq = to_ap_queue(dev);
+	int rc = 0;
+
+	spin_lock_bh(&aq->lock);
+	/* queue device state */
+	switch (aq->dev_state) {
+	case AP_DEV_STATE_UNINITIATED:
+		rc = scnprintf(buf, PAGE_SIZE, "UNINITIATED\n");
+		break;
+	case AP_DEV_STATE_OPERATING:
+		rc = scnprintf(buf, PAGE_SIZE, "OPERATING");
+		break;
+	case AP_DEV_STATE_SHUTDOWN:
+		rc = scnprintf(buf, PAGE_SIZE, "SHUTDOWN");
+		break;
+	case AP_DEV_STATE_ERROR:
+		rc = scnprintf(buf, PAGE_SIZE, "ERROR");
+		break;
+	default:
+		rc = scnprintf(buf, PAGE_SIZE, "UNKNOWN");
+	}
+	/* state machine state */
+	if (aq->dev_state) {
+		switch (aq->sm_state) {
+		case AP_SM_STATE_RESET_START:
+			rc += scnprintf(buf + rc, PAGE_SIZE - rc,
+					" [RESET_START]\n");
+			break;
+		case AP_SM_STATE_RESET_WAIT:
+			rc += scnprintf(buf + rc, PAGE_SIZE - rc,
+					" [RESET_WAIT]\n");
+			break;
+		case AP_SM_STATE_SETIRQ_WAIT:
+			rc += scnprintf(buf + rc, PAGE_SIZE - rc,
+					" [SETIRQ_WAIT]\n");
+			break;
+		case AP_SM_STATE_IDLE:
+			rc += scnprintf(buf + rc, PAGE_SIZE - rc,
+					" [IDLE]\n");
+			break;
+		case AP_SM_STATE_WORKING:
+			rc += scnprintf(buf + rc, PAGE_SIZE - rc,
+					" [WORKING]\n");
+			break;
+		case AP_SM_STATE_QUEUE_FULL:
+			rc += scnprintf(buf + rc, PAGE_SIZE - rc,
+					" [FULL]\n");
+			break;
+		default:
+			rc += scnprintf(buf + rc, PAGE_SIZE - rc,
+					" [UNKNOWN]\n");
+		}
+	}
+	spin_unlock_bh(&aq->lock);
+
+	return rc;
+}
+static DEVICE_ATTR_RO(states);
+
+static ssize_t last_err_rc_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct ap_queue *aq = to_ap_queue(dev);
+	int rc;
+
+	spin_lock_bh(&aq->lock);
+	rc = aq->last_err_rc;
+	spin_unlock_bh(&aq->lock);
+
+	switch (rc) {
+	case AP_RESPONSE_NORMAL:
+		return scnprintf(buf, PAGE_SIZE, "NORMAL\n");
+	case AP_RESPONSE_Q_NOT_AVAIL:
+		return scnprintf(buf, PAGE_SIZE, "Q_NOT_AVAIL\n");
+	case AP_RESPONSE_RESET_IN_PROGRESS:
+		return scnprintf(buf, PAGE_SIZE, "RESET_IN_PROGRESS\n");
+	case AP_RESPONSE_DECONFIGURED:
+		return scnprintf(buf, PAGE_SIZE, "DECONFIGURED\n");
+	case AP_RESPONSE_CHECKSTOPPED:
+		return scnprintf(buf, PAGE_SIZE, "CHECKSTOPPED\n");
+	case AP_RESPONSE_BUSY:
+		return scnprintf(buf, PAGE_SIZE, "BUSY\n");
+	case AP_RESPONSE_INVALID_ADDRESS:
+		return scnprintf(buf, PAGE_SIZE, "INVALID_ADDRESS\n");
+	case AP_RESPONSE_OTHERWISE_CHANGED:
+		return scnprintf(buf, PAGE_SIZE, "OTHERWISE_CHANGED\n");
+	case AP_RESPONSE_Q_FULL:
+		return scnprintf(buf, PAGE_SIZE, "Q_FULL/NO_PENDING_REPLY\n");
+	case AP_RESPONSE_INDEX_TOO_BIG:
+		return scnprintf(buf, PAGE_SIZE, "INDEX_TOO_BIG\n");
+	case AP_RESPONSE_NO_FIRST_PART:
+		return scnprintf(buf, PAGE_SIZE, "NO_FIRST_PART\n");
+	case AP_RESPONSE_MESSAGE_TOO_BIG:
+		return scnprintf(buf, PAGE_SIZE, "MESSAGE_TOO_BIG\n");
+	case AP_RESPONSE_REQ_FAC_NOT_INST:
+		return scnprintf(buf, PAGE_SIZE, "REQ_FAC_NOT_INST\n");
+	default:
+		return scnprintf(buf, PAGE_SIZE, "response code %d\n", rc);
+	}
+}
+static DEVICE_ATTR_RO(last_err_rc);
+#endif
+
 static struct attribute *ap_queue_dev_attrs[] = {
 	&dev_attr_request_count.attr,
 	&dev_attr_requestq_count.attr,
 	&dev_attr_pendingq_count.attr,
 	&dev_attr_reset.attr,
 	&dev_attr_interrupt.attr,
+	&dev_attr_config.attr,
+#ifdef CONFIG_ZCRYPT_DEBUG
+	&dev_attr_states.attr,
+	&dev_attr_last_err_rc.attr,
+#endif
 	NULL
 };
 
@@ -619,11 +729,10 @@
 {
 	struct ap_queue *aq = to_ap_queue(dev);
 
-	if (!list_empty(&aq->list)) {
-		spin_lock_bh(&ap_list_lock);
-		list_del_init(&aq->list);
-		spin_unlock_bh(&ap_list_lock);
-	}
+	spin_lock_bh(&ap_queues_lock);
+	hash_del(&aq->hnode);
+	spin_unlock_bh(&ap_queues_lock);
+
 	kfree(aq);
 }
 
@@ -638,10 +747,8 @@
 	aq->ap_dev.device.type = &ap_queue_type;
 	aq->ap_dev.device_type = device_type;
 	aq->qid = qid;
-	aq->state = AP_STATE_RESET_START;
 	aq->interrupt = AP_INTR_DISABLED;
 	spin_lock_init(&aq->lock);
-	INIT_LIST_HEAD(&aq->list);
 	INIT_LIST_HEAD(&aq->pendingq);
 	INIT_LIST_HEAD(&aq->requestq);
 	timer_setup(&aq->timeout, ap_request_timeout, 0);
@@ -654,7 +761,7 @@
 	aq->reply = reply;
 
 	spin_lock_bh(&aq->lock);
-	ap_wait(ap_sm_event(aq, AP_EVENT_POLL));
+	ap_wait(ap_sm_event(aq, AP_SM_EVENT_POLL));
 	spin_unlock_bh(&aq->lock);
 }
 EXPORT_SYMBOL(ap_queue_init_reply);
@@ -664,22 +771,30 @@
  * @aq: The AP device to queue the message to
  * @ap_msg: The message that is to be added
  */
-void ap_queue_message(struct ap_queue *aq, struct ap_message *ap_msg)
+int ap_queue_message(struct ap_queue *aq, struct ap_message *ap_msg)
 {
-	/* For asynchronous message handling a valid receive-callback
-	 * is required.
-	 */
+	int rc = 0;
+
+	/* msg needs to have a valid receive-callback */
 	BUG_ON(!ap_msg->receive);
 
 	spin_lock_bh(&aq->lock);
-	/* Queue the message. */
-	list_add_tail(&ap_msg->list, &aq->requestq);
-	aq->requestq_count++;
-	aq->total_request_count++;
-	atomic_inc(&aq->card->total_request_count);
+
+	/* only allow to queue new messages if device state is ok */
+	if (aq->dev_state == AP_DEV_STATE_OPERATING) {
+		list_add_tail(&ap_msg->list, &aq->requestq);
+		aq->requestq_count++;
+		aq->total_request_count++;
+		atomic64_inc(&aq->card->total_request_count);
+	} else
+		rc = -ENODEV;
+
 	/* Send/receive as many request from the queue as possible. */
-	ap_wait(ap_sm_event_loop(aq, AP_EVENT_POLL));
+	ap_wait(ap_sm_event_loop(aq, AP_SM_EVENT_POLL));
+
 	spin_unlock_bh(&aq->lock);
+
+	return rc;
 }
 EXPORT_SYMBOL(ap_queue_message);
 
@@ -750,8 +865,8 @@
 	spin_lock_bh(&aq->lock);
 	/* flush queue */
 	__ap_flush_queue(aq);
-	/* set REMOVE state to prevent new messages are queued in */
-	aq->state = AP_STATE_REMOVE;
+	/* move queue device state to SHUTDOWN in progress */
+	aq->dev_state = AP_DEV_STATE_SHUTDOWN;
 	spin_unlock_bh(&aq->lock);
 	del_timer_sync(&aq->timeout);
 }
@@ -759,22 +874,23 @@
 void ap_queue_remove(struct ap_queue *aq)
 {
 	/*
-	 * all messages have been flushed and the state is
-	 * AP_STATE_REMOVE. Now reset with zero which also
-	 * clears the irq registration and move the state
-	 * to AP_STATE_UNBOUND to signal that this queue
-	 * is not used by any driver currently.
+	 * all messages have been flushed and the device state
+	 * is SHUTDOWN. Now reset with zero which also clears
+	 * the irq registration and move the device state
+	 * to the initial value AP_DEV_STATE_UNINITIATED.
 	 */
 	spin_lock_bh(&aq->lock);
 	ap_zapq(aq->qid);
-	aq->state = AP_STATE_UNBOUND;
+	aq->dev_state = AP_DEV_STATE_UNINITIATED;
 	spin_unlock_bh(&aq->lock);
 }
 
-void ap_queue_reinit_state(struct ap_queue *aq)
+void ap_queue_init_state(struct ap_queue *aq)
 {
 	spin_lock_bh(&aq->lock);
-	aq->state = AP_STATE_RESET_START;
-	ap_wait(ap_sm_event(aq, AP_EVENT_POLL));
+	aq->dev_state = AP_DEV_STATE_OPERATING;
+	aq->sm_state = AP_SM_STATE_RESET_START;
+	ap_wait(ap_sm_event(aq, AP_SM_EVENT_POLL));
 	spin_unlock_bh(&aq->lock);
 }
+EXPORT_SYMBOL(ap_queue_init_state);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/crypto/pkey_api.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/crypto/pkey_api.c
@@ -25,6 +25,7 @@
 
 #include "zcrypt_api.h"
 #include "zcrypt_ccamisc.h"
+#include "zcrypt_ep11misc.h"
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("IBM Corporation");
@@ -33,9 +34,6 @@
 #define KEYBLOBBUFSIZE 8192  /* key buffer size used for internal processing */
 #define MAXAPQNSINLIST 64    /* max 64 apqns within a apqn list */
 
-/* mask of available pckmo subfunctions, fetched once at module init */
-static cpacf_mask_t pckmo_functions;
-
 /*
  * debug feature data and functions
  */
@@ -71,6 +69,17 @@
 	u8  protkey[MAXPROTKEYSIZE]; /* the protected key blob */
 } __packed;
 
+/* inside view of a clear key token (type 0x00 version 0x02) */
+struct clearaeskeytoken {
+	u8  type;	 /* 0x00 for PAES specific key tokens */
+	u8  res0[3];
+	u8  version;	 /* 0x02 for clear AES key token */
+	u8  res1[3];
+	u32 keytype;	 /* key type, one of the PKEY_KEYTYPE values */
+	u32 len;	 /* bytes actually stored in clearkey[] */
+	u8  clearkey[]; /* clear key value */
+} __packed;
+
 /*
  * Create a protected key from a clear key value.
  */
@@ -78,6 +87,9 @@
 			    const struct pkey_clrkey *clrkey,
 			    struct pkey_protkey *protkey)
 {
+	/* mask of available pckmo subfunctions */
+	static cpacf_mask_t pckmo_functions;
+
 	long fc;
 	int keysize;
 	u8 paramblock[64];
@@ -101,11 +113,13 @@
 		return -EINVAL;
 	}
 
-	/*
-	 * Check if the needed pckmo subfunction is available.
-	 * These subfunctions can be enabled/disabled by customers
-	 * in the LPAR profile or may even change on the fly.
-	 */
+	/* Did we already check for PCKMO ? */
+	if (!pckmo_functions.bytes[0]) {
+		/* no, so check now */
+		if (!cpacf_query(CPACF_PCKMO, &pckmo_functions))
+			return -ENODEV;
+	}
+	/* check for the pckmo subfunction we need now */
 	if (!cpacf_test_func(&pckmo_functions, fc)) {
 		DEBUG_ERR("%s pckmo functions not available\n", __func__);
 		return -ENODEV;
@@ -173,6 +187,72 @@
 }
 
 /*
+ * Construct EP11 key with given clear key value.
+ */
+static int pkey_clr2ep11key(const u8 *clrkey, size_t clrkeylen,
+			    u8 *keybuf, size_t *keybuflen)
+{
+	int i, rc;
+	u16 card, dom;
+	u32 nr_apqns, *apqns = NULL;
+
+	/* build a list of apqns suitable for ep11 keys with cpacf support */
+	rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF,
+			    ZCRYPT_CEX7, EP11_API_V, NULL);
+	if (rc)
+		goto out;
+
+	/* go through the list of apqns and try to bild an ep11 key */
+	for (rc = -ENODEV, i = 0; i < nr_apqns; i++) {
+		card = apqns[i] >> 16;
+		dom = apqns[i] & 0xFFFF;
+		rc = ep11_clr2keyblob(card, dom, clrkeylen * 8,
+				      0, clrkey, keybuf, keybuflen);
+		if (rc == 0)
+			break;
+	}
+
+out:
+	kfree(apqns);
+	if (rc)
+		DEBUG_DBG("%s failed rc=%d\n", __func__, rc);
+	return rc;
+}
+
+/*
+ * Find card and transform EP11 secure key into protected key.
+ */
+static int pkey_ep11key2pkey(const u8 *key, struct pkey_protkey *pkey)
+{
+	int i, rc;
+	u16 card, dom;
+	u32 nr_apqns, *apqns = NULL;
+	struct ep11keyblob *kb = (struct ep11keyblob *) key;
+
+	/* build a list of apqns suitable for this key */
+	rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF,
+			    ZCRYPT_CEX7, EP11_API_V, kb->wkvp);
+	if (rc)
+		goto out;
+
+	/* go through the list of apqns and try to derive an pkey */
+	for (rc = -ENODEV, i = 0; i < nr_apqns; i++) {
+		card = apqns[i] >> 16;
+		dom = apqns[i] & 0xFFFF;
+		rc = ep11_key2protkey(card, dom, key, kb->head.len,
+				      pkey->protkey, &pkey->len, &pkey->type);
+		if (rc == 0)
+			break;
+	}
+
+out:
+	kfree(apqns);
+	if (rc)
+		DEBUG_DBG("%s failed rc=%d\n", __func__, rc);
+	return rc;
+}
+
+/*
  * Verify key and give back some info about the key.
  */
 static int pkey_verifykey(const struct pkey_seckey *seckey,
@@ -305,26 +385,90 @@
 static int pkey_nonccatok2pkey(const u8 *key, u32 keylen,
 			       struct pkey_protkey *protkey)
 {
+	int rc = -EINVAL;
+	u8 *tmpbuf = NULL;
 	struct keytoken_header *hdr = (struct keytoken_header *)key;
-	struct protaeskeytoken *t;
 
 	switch (hdr->version) {
-	case TOKVER_PROTECTED_KEY:
-		if (keylen != sizeof(struct protaeskeytoken))
-			return -EINVAL;
+	case TOKVER_PROTECTED_KEY: {
+		struct protaeskeytoken *t;
 
+		if (keylen != sizeof(struct protaeskeytoken))
+			goto out;
 		t = (struct protaeskeytoken *)key;
 		protkey->len = t->len;
 		protkey->type = t->keytype;
 		memcpy(protkey->protkey, t->protkey,
 		       sizeof(protkey->protkey));
+		rc = pkey_verifyprotkey(protkey);
+		break;
+	}
+	case TOKVER_CLEAR_KEY: {
+		struct clearaeskeytoken *t;
+		struct pkey_clrkey ckey;
+		union u_tmpbuf {
+			u8 skey[SECKEYBLOBSIZE];
+			u8 ep11key[MAXEP11AESKEYBLOBSIZE];
+		};
+		size_t tmpbuflen = sizeof(union u_tmpbuf);
 
-		return pkey_verifyprotkey(protkey);
+		if (keylen < sizeof(struct clearaeskeytoken))
+			goto out;
+		t = (struct clearaeskeytoken *)key;
+		if (keylen != sizeof(*t) + t->len)
+			goto out;
+		if ((t->keytype == PKEY_KEYTYPE_AES_128 && t->len == 16)
+		    || (t->keytype == PKEY_KEYTYPE_AES_192 && t->len == 24)
+		    || (t->keytype == PKEY_KEYTYPE_AES_256 && t->len == 32))
+			memcpy(ckey.clrkey, t->clearkey, t->len);
+		else
+			goto out;
+		/* alloc temp key buffer space */
+		tmpbuf = kmalloc(tmpbuflen, GFP_ATOMIC);
+		if (!tmpbuf) {
+			rc = -ENOMEM;
+			goto out;
+		}
+		/* try direct way with the PCKMO instruction */
+		rc = pkey_clr2protkey(t->keytype, &ckey, protkey);
+		if (rc == 0)
+			break;
+		/* PCKMO failed, so try the CCA secure key way */
+		rc = cca_clr2seckey(0xFFFF, 0xFFFF, t->keytype,
+				    ckey.clrkey, tmpbuf);
+		if (rc == 0)
+			rc = pkey_skey2pkey(tmpbuf, protkey);
+		if (rc == 0)
+			break;
+		/* if the CCA way also failed, let's try via EP11 */
+		rc = pkey_clr2ep11key(ckey.clrkey, t->len,
+				      tmpbuf, &tmpbuflen);
+		if (rc == 0)
+			rc = pkey_ep11key2pkey(tmpbuf, protkey);
+		/* now we should really have an protected key */
+		DEBUG_ERR("%s unable to build protected key from clear",
+			  __func__);
+		break;
+	}
+	case TOKVER_EP11_AES: {
+		if (keylen < MINEP11AESKEYBLOBSIZE)
+			goto out;
+		/* check ep11 key for exportable as protected key */
+		rc = ep11_check_aeskeyblob(debug_info, 3, key, 0, 1);
+		if (rc)
+			goto out;
+		rc = pkey_ep11key2pkey(key, protkey);
+		break;
+	}
 	default:
 		DEBUG_ERR("%s unknown/unsupported non-CCA token version %d\n",
 			  __func__, hdr->version);
-		return -EINVAL;
+		rc = -EINVAL;
 	}
+
+out:
+	kfree(tmpbuf);
+	return rc;
 }
 
 /*
@@ -403,6 +547,10 @@
 		if (*keybufsize < SECKEYBLOBSIZE)
 			return -EINVAL;
 		break;
+	case PKEY_TYPE_EP11:
+		if (*keybufsize < MINEP11AESKEYBLOBSIZE)
+			return -EINVAL;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -419,7 +567,10 @@
 	for (i = 0, rc = -ENODEV; i < nr_apqns; i++) {
 		card = apqns[i].card;
 		dom = apqns[i].domain;
-		if (ktype == PKEY_TYPE_CCA_DATA) {
+		if (ktype == PKEY_TYPE_EP11) {
+			rc = ep11_genaeskey(card, dom, ksize, kflags,
+					    keybuf, keybufsize);
+		} else if (ktype == PKEY_TYPE_CCA_DATA) {
 			rc = cca_genseckey(card, dom, ksize, keybuf);
 			*keybufsize = (rc ? 0 : SECKEYBLOBSIZE);
 		} else /* TOKVER_CCA_VLSC */
@@ -450,6 +601,10 @@
 		if (*keybufsize < SECKEYBLOBSIZE)
 			return -EINVAL;
 		break;
+	case PKEY_TYPE_EP11:
+		if (*keybufsize < MINEP11AESKEYBLOBSIZE)
+			return -EINVAL;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -466,7 +621,10 @@
 	for (i = 0, rc = -ENODEV; i < nr_apqns; i++) {
 		card = apqns[i].card;
 		dom = apqns[i].domain;
-		if (ktype == PKEY_TYPE_CCA_DATA) {
+		if (ktype == PKEY_TYPE_EP11) {
+			rc = ep11_clr2keyblob(card, dom, ksize, kflags,
+					      clrkey, keybuf, keybufsize);
+		} else if (ktype == PKEY_TYPE_CCA_DATA) {
 			rc = cca_clr2seckey(card, dom, ksize,
 					    clrkey, keybuf);
 			*keybufsize = (rc ? 0 : SECKEYBLOBSIZE);
@@ -489,11 +647,11 @@
 	u32 _nr_apqns, *_apqns = NULL;
 	struct keytoken_header *hdr = (struct keytoken_header *)key;
 
-	if (keylen < sizeof(struct keytoken_header) ||
-	    hdr->type != TOKTYPE_CCA_INTERNAL)
+	if (keylen < sizeof(struct keytoken_header))
 		return -EINVAL;
 
-	if (hdr->version == TOKVER_CCA_AES) {
+	if (hdr->type == TOKTYPE_CCA_INTERNAL
+	    && hdr->version == TOKVER_CCA_AES) {
 		struct secaeskeytoken *t = (struct secaeskeytoken *)key;
 
 		rc = cca_check_secaeskeytoken(debug_info, 3, key, 0);
@@ -505,13 +663,14 @@
 			*ksize = (enum pkey_key_size) t->bitsize;
 
 		rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain,
-				   ZCRYPT_CEX3C, t->mkvp, 0, 1);
+				   ZCRYPT_CEX3C, AES_MK_SET, t->mkvp, 0, 1);
 		if (rc == 0 && flags)
 			*flags = PKEY_FLAGS_MATCH_CUR_MKVP;
 		if (rc == -ENODEV) {
 			rc = cca_findcard2(&_apqns, &_nr_apqns,
 					   *cardnr, *domain,
-					   ZCRYPT_CEX3C, 0, t->mkvp, 1);
+					   ZCRYPT_CEX3C, AES_MK_SET,
+					   0, t->mkvp, 1);
 			if (rc == 0 && flags)
 				*flags = PKEY_FLAGS_MATCH_ALT_MKVP;
 		}
@@ -521,7 +680,8 @@
 		*cardnr = ((struct pkey_apqn *)_apqns)->card;
 		*domain = ((struct pkey_apqn *)_apqns)->domain;
 
-	} else if (hdr->version == TOKVER_CCA_VLSC) {
+	} else if (hdr->type == TOKTYPE_CCA_INTERNAL
+		   && hdr->version == TOKVER_CCA_VLSC) {
 		struct cipherkeytoken *t = (struct cipherkeytoken *)key;
 
 		rc = cca_check_secaescipherkey(debug_info, 3, key, 0, 1);
@@ -540,13 +700,14 @@
 		}
 
 		rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain,
-				   ZCRYPT_CEX6, t->mkvp0, 0, 1);
+				   ZCRYPT_CEX6, AES_MK_SET, t->mkvp0, 0, 1);
 		if (rc == 0 && flags)
 			*flags = PKEY_FLAGS_MATCH_CUR_MKVP;
 		if (rc == -ENODEV) {
 			rc = cca_findcard2(&_apqns, &_nr_apqns,
 					   *cardnr, *domain,
-					   ZCRYPT_CEX6, 0, t->mkvp0, 1);
+					   ZCRYPT_CEX6, AES_MK_SET,
+					   0, t->mkvp0, 1);
 			if (rc == 0 && flags)
 				*flags = PKEY_FLAGS_MATCH_ALT_MKVP;
 		}
@@ -556,6 +717,29 @@
 		*cardnr = ((struct pkey_apqn *)_apqns)->card;
 		*domain = ((struct pkey_apqn *)_apqns)->domain;
 
+	} else if (hdr->type == TOKTYPE_NON_CCA
+		   && hdr->version == TOKVER_EP11_AES) {
+		struct ep11keyblob *kb = (struct ep11keyblob *)key;
+
+		rc = ep11_check_aeskeyblob(debug_info, 3, key, 0, 1);
+		if (rc)
+			goto out;
+		if (ktype)
+			*ktype = PKEY_TYPE_EP11;
+		if (ksize)
+			*ksize = kb->head.keybitlen;
+
+		rc = ep11_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain,
+				    ZCRYPT_CEX7, EP11_API_V, kb->wkvp);
+		if (rc)
+			goto out;
+
+		if (flags)
+			*flags = PKEY_FLAGS_MATCH_CUR_MKVP;
+
+		*cardnr = ((struct pkey_apqn *)_apqns)->card;
+		*domain = ((struct pkey_apqn *)_apqns)->domain;
+
 	} else
 		rc = -EINVAL;
 
@@ -578,30 +762,32 @@
 	if (keylen < sizeof(struct keytoken_header))
 		return -EINVAL;
 
-	switch (hdr->type) {
-	case TOKTYPE_NON_CCA:
-		return pkey_nonccatok2pkey(key, keylen, pkey);
-	case TOKTYPE_CCA_INTERNAL:
-		switch (hdr->version) {
-		case TOKVER_CCA_AES:
+	if (hdr->type == TOKTYPE_CCA_INTERNAL) {
+		if (hdr->version == TOKVER_CCA_AES) {
 			if (keylen != sizeof(struct secaeskeytoken))
 				return -EINVAL;
 			if (cca_check_secaeskeytoken(debug_info, 3, key, 0))
 				return -EINVAL;
-			break;
-		case TOKVER_CCA_VLSC:
+		} else if (hdr->version == TOKVER_CCA_VLSC) {
 			if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE)
 				return -EINVAL;
 			if (cca_check_secaescipherkey(debug_info, 3, key, 0, 1))
 				return -EINVAL;
-			break;
-		default:
+		} else {
 			DEBUG_ERR("%s unknown CCA internal token version %d\n",
 				  __func__, hdr->version);
 			return -EINVAL;
 		}
-		break;
-	default:
+	} else if (hdr->type == TOKTYPE_NON_CCA) {
+		if (hdr->version == TOKVER_EP11_AES) {
+			if (keylen < sizeof(struct ep11keyblob))
+				return -EINVAL;
+			if (ep11_check_aeskeyblob(debug_info, 3, key, 0, 1))
+				return -EINVAL;
+		} else {
+			return pkey_nonccatok2pkey(key, keylen, pkey);
+		}
+	} else {
 		DEBUG_ERR("%s unknown/unsupported blob type %d\n",
 			  __func__, hdr->type);
 		return -EINVAL;
@@ -611,12 +797,21 @@
 	for (i = 0, rc = -ENODEV; i < nr_apqns; i++) {
 		card = apqns[i].card;
 		dom = apqns[i].domain;
-		if (hdr->version == TOKVER_CCA_AES)
+		if (hdr->type == TOKTYPE_CCA_INTERNAL
+		    && hdr->version == TOKVER_CCA_AES)
 			rc = cca_sec2protkey(card, dom, key, pkey->protkey,
 					     &pkey->len, &pkey->type);
-		else /* TOKVER_CCA_VLSC */
+		else if (hdr->type == TOKTYPE_CCA_INTERNAL
+			 && hdr->version == TOKVER_CCA_VLSC)
 			rc = cca_cipher2protkey(card, dom, key, pkey->protkey,
 						&pkey->len, &pkey->type);
+		else { /* EP11 AES secure key blob */
+			struct ep11keyblob *kb = (struct ep11keyblob *) key;
+
+			rc = ep11_key2protkey(card, dom, key, kb->head.len,
+					      pkey->protkey, &pkey->len,
+					      &pkey->type);
+		}
 		if (rc == 0)
 			break;
 	}
@@ -631,12 +826,24 @@
 	u32 _nr_apqns, *_apqns = NULL;
 	struct keytoken_header *hdr = (struct keytoken_header *)key;
 
-	if (keylen < sizeof(struct keytoken_header) ||
-	    hdr->type != TOKTYPE_CCA_INTERNAL ||
-	    flags == 0)
+	if (keylen < sizeof(struct keytoken_header) || flags == 0)
 		return -EINVAL;
 
-	if (hdr->version == TOKVER_CCA_AES || hdr->version == TOKVER_CCA_VLSC) {
+	if (hdr->type == TOKTYPE_NON_CCA && hdr->version == TOKVER_EP11_AES) {
+		int minhwtype = 0, api = 0;
+		struct ep11keyblob *kb = (struct ep11keyblob *) key;
+
+		if (flags != PKEY_FLAGS_MATCH_CUR_MKVP)
+			return -EINVAL;
+		if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) {
+			minhwtype = ZCRYPT_CEX7;
+			api = EP11_API_V;
+		}
+		rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
+				    minhwtype, api, kb->wkvp);
+		if (rc)
+			goto out;
+	} else if (hdr->type == TOKTYPE_CCA_INTERNAL) {
 		int minhwtype = ZCRYPT_CEX3C;
 		u64 cur_mkvp = 0, old_mkvp = 0;
 
@@ -647,7 +854,7 @@
 				cur_mkvp = t->mkvp;
 			if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
 				old_mkvp = t->mkvp;
-		} else {
+		} else if (hdr->version == TOKVER_CCA_VLSC) {
 			struct cipherkeytoken *t = (struct cipherkeytoken *)key;
 
 			minhwtype = ZCRYPT_CEX6;
@@ -655,19 +862,25 @@
 				cur_mkvp = t->mkvp0;
 			if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
 				old_mkvp = t->mkvp0;
+		} else {
+			/* unknown cca internal token type */
+			return -EINVAL;
 		}
 		rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
-				   minhwtype, cur_mkvp, old_mkvp, 1);
+				   minhwtype, AES_MK_SET,
+				   cur_mkvp, old_mkvp, 1);
 		if (rc)
 			goto out;
-		if (apqns) {
-			if (*nr_apqns < _nr_apqns)
-				rc = -ENOSPC;
-			else
-				memcpy(apqns, _apqns, _nr_apqns * sizeof(u32));
-		}
-		*nr_apqns = _nr_apqns;
+	} else
+		return -EINVAL;
+
+	if (apqns) {
+		if (*nr_apqns < _nr_apqns)
+			rc = -ENOSPC;
+		else
+			memcpy(apqns, _apqns, _nr_apqns * sizeof(u32));
 	}
+	*nr_apqns = _nr_apqns;
 
 out:
 	kfree(_apqns);
@@ -692,17 +905,30 @@
 		if (ktype == PKEY_TYPE_CCA_CIPHER)
 			minhwtype = ZCRYPT_CEX6;
 		rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
-				   minhwtype, cur_mkvp, old_mkvp, 1);
+				   minhwtype, AES_MK_SET,
+				   cur_mkvp, old_mkvp, 1);
 		if (rc)
 			goto out;
-		if (apqns) {
-			if (*nr_apqns < _nr_apqns)
-				rc = -ENOSPC;
-			else
-				memcpy(apqns, _apqns, _nr_apqns * sizeof(u32));
-		}
-		*nr_apqns = _nr_apqns;
+	} else if (ktype == PKEY_TYPE_EP11) {
+		u8 *wkvp = NULL;
+
+		if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
+			wkvp = cur_mkvp;
+		rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
+				    ZCRYPT_CEX7, EP11_API_V, wkvp);
+		if (rc)
+			goto out;
+
+	} else
+		return -EINVAL;
+
+	if (apqns) {
+		if (*nr_apqns < _nr_apqns)
+			rc = -ENOSPC;
+		else
+			memcpy(apqns, _apqns, _nr_apqns * sizeof(u32));
 	}
+	*nr_apqns = _nr_apqns;
 
 out:
 	kfree(_apqns);
@@ -715,36 +941,18 @@
 
 static void *_copy_key_from_user(void __user *ukey, size_t keylen)
 {
-	void *kkey;
-
 	if (!ukey || keylen < MINKEYBLOBSIZE || keylen > KEYBLOBBUFSIZE)
 		return ERR_PTR(-EINVAL);
-	kkey = kmalloc(keylen, GFP_KERNEL);
-	if (!kkey)
-		return ERR_PTR(-ENOMEM);
-	if (copy_from_user(kkey, ukey, keylen)) {
-		kfree(kkey);
-		return ERR_PTR(-EFAULT);
-	}
 
-	return kkey;
+	return memdup_user(ukey, keylen);
 }
 
 static void *_copy_apqns_from_user(void __user *uapqns, size_t nr_apqns)
 {
-	void *kapqns = NULL;
-	size_t nbytes;
+	if (!uapqns || nr_apqns == 0)
+		return NULL;
 
-	if (uapqns && nr_apqns > 0) {
-		nbytes = nr_apqns * sizeof(struct pkey_apqn);
-		kapqns = kmalloc(nbytes, GFP_KERNEL);
-		if (!kapqns)
-			return ERR_PTR(-ENOMEM);
-		if (copy_from_user(kapqns, uapqns, nbytes))
-			return ERR_PTR(-EFAULT);
-	}
-
-	return kapqns;
+	return memdup_user(uapqns, nr_apqns * sizeof(struct pkey_apqn));
 }
 
 static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
@@ -777,10 +985,8 @@
 		rc = cca_clr2seckey(kcs.cardnr, kcs.domain, kcs.keytype,
 				    kcs.clrkey.clrkey, kcs.seckey.seckey);
 		DEBUG_DBG("%s cca_clr2seckey()=%d\n", __func__, rc);
-		if (rc)
-			break;
-		if (copy_to_user(ucs, &kcs, sizeof(kcs)))
-			return -EFAULT;
+		if (!rc && copy_to_user(ucs, &kcs, sizeof(kcs)))
+			rc = -EFAULT;
 		memzero_explicit(&kcs, sizeof(kcs));
 		break;
 	}
@@ -792,7 +998,7 @@
 			return -EFAULT;
 		rc = cca_sec2protkey(ksp.cardnr, ksp.domain,
 				     ksp.seckey.seckey, ksp.protkey.protkey,
-				     NULL, &ksp.protkey.type);
+				     &ksp.protkey.len, &ksp.protkey.type);
 		DEBUG_DBG("%s cca_sec2protkey()=%d\n", __func__, rc);
 		if (rc)
 			break;
@@ -809,10 +1015,8 @@
 		rc = pkey_clr2protkey(kcp.keytype,
 				      &kcp.clrkey, &kcp.protkey);
 		DEBUG_DBG("%s pkey_clr2protkey()=%d\n", __func__, rc);
-		if (rc)
-			break;
-		if (copy_to_user(ucp, &kcp, sizeof(kcp)))
-			return -EFAULT;
+		if (!rc && copy_to_user(ucp, &kcp, sizeof(kcp)))
+			rc = -EFAULT;
 		memzero_explicit(&kcp, sizeof(kcp));
 		break;
 	}
@@ -955,11 +1159,14 @@
 		if (copy_from_user(&kcs, ucs, sizeof(kcs)))
 			return -EFAULT;
 		apqns = _copy_apqns_from_user(kcs.apqns, kcs.apqn_entries);
-		if (IS_ERR(apqns))
+		if (IS_ERR(apqns)) {
+			memzero_explicit(&kcs, sizeof(kcs));
 			return PTR_ERR(apqns);
+		}
 		kkey = kmalloc(klen, GFP_KERNEL);
 		if (!kkey) {
 			kfree(apqns);
+			memzero_explicit(&kcs, sizeof(kcs));
 			return -ENOMEM;
 		}
 		rc = pkey_clr2seckey2(apqns, kcs.apqn_entries,
@@ -969,15 +1176,18 @@
 		kfree(apqns);
 		if (rc) {
 			kfree(kkey);
+			memzero_explicit(&kcs, sizeof(kcs));
 			break;
 		}
 		if (kcs.key) {
 			if (kcs.keylen < klen) {
 				kfree(kkey);
+				memzero_explicit(&kcs, sizeof(kcs));
 				return -EINVAL;
 			}
 			if (copy_to_user(kcs.key, kkey, klen)) {
 				kfree(kkey);
+				memzero_explicit(&kcs, sizeof(kcs));
 				return -EFAULT;
 			}
 		}
@@ -1375,8 +1585,9 @@
 					    bool is_xts, char *buf, loff_t off,
 					    size_t count)
 {
-	size_t keysize;
-	int rc;
+	int i, rc, card, dom;
+	u32 nr_apqns, *apqns = NULL;
+	size_t keysize = CCACIPHERTOKENSIZE;
 
 	if (off != 0 || count < CCACIPHERTOKENSIZE)
 		return -EINVAL;
@@ -1384,22 +1595,31 @@
 		if (count < 2 * CCACIPHERTOKENSIZE)
 			return -EINVAL;
 
-	keysize = CCACIPHERTOKENSIZE;
-	rc = cca_gencipherkey(-1, -1, keybits, 0, buf, &keysize);
+	/* build a list of apqns able to generate an cipher key */
+	rc = cca_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF,
+			   ZCRYPT_CEX6, 0, 0, 0, 0);
 	if (rc)
 		return rc;
-	memset(buf + keysize, 0, CCACIPHERTOKENSIZE - keysize);
 
-	if (is_xts) {
-		keysize = CCACIPHERTOKENSIZE;
-		rc = cca_gencipherkey(-1, -1, keybits, 0,
-				      buf + CCACIPHERTOKENSIZE, &keysize);
+	memset(buf, 0, is_xts ? 2 * keysize : keysize);
+
+	/* simple try all apqns from the list */
+	for (i = 0, rc = -ENODEV; i < nr_apqns; i++) {
+		card = apqns[i] >> 16;
+		dom = apqns[i] & 0xFFFF;
+		rc = cca_gencipherkey(card, dom, keybits, 0, buf, &keysize);
+		if (rc == 0)
+			break;
+	}
 		if (rc)
 			return rc;
-		memset(buf + CCACIPHERTOKENSIZE + keysize, 0,
-		       CCACIPHERTOKENSIZE - keysize);
 
-		return 2 * CCACIPHERTOKENSIZE;
+	if (is_xts) {
+		keysize = CCACIPHERTOKENSIZE;
+		buf += CCACIPHERTOKENSIZE;
+		rc = cca_gencipherkey(card, dom, keybits, 0, buf, &keysize);
+		if (rc == 0)
+			return 2 * CCACIPHERTOKENSIZE;
 	}
 
 	return CCACIPHERTOKENSIZE;
@@ -1475,10 +1695,134 @@
 	.bin_attrs = ccacipher_attrs,
 };
 
+/*
+ * Sysfs attribute read function for all ep11 aes key binary attributes.
+ * The implementation can not deal with partial reads, because a new random
+ * secure key blob is generated with each read. In case of partial reads
+ * (i.e. off != 0 or count < key blob size) -EINVAL is returned.
+ * This function and the sysfs attributes using it provide EP11 key blobs
+ * padded to the upper limit of MAXEP11AESKEYBLOBSIZE which is currently
+ * 320 bytes.
+ */
+static ssize_t pkey_ep11_aes_attr_read(enum pkey_key_size keybits,
+				       bool is_xts, char *buf, loff_t off,
+				       size_t count)
+{
+	int i, rc, card, dom;
+	u32 nr_apqns, *apqns = NULL;
+	size_t keysize = MAXEP11AESKEYBLOBSIZE;
+
+	if (off != 0 || count < MAXEP11AESKEYBLOBSIZE)
+		return -EINVAL;
+	if (is_xts)
+		if (count < 2 * MAXEP11AESKEYBLOBSIZE)
+			return -EINVAL;
+
+	/* build a list of apqns able to generate an cipher key */
+	rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF,
+			    ZCRYPT_CEX7, EP11_API_V, NULL);
+	if (rc)
+		return rc;
+
+	memset(buf, 0, is_xts ? 2 * keysize : keysize);
+
+	/* simple try all apqns from the list */
+	for (i = 0, rc = -ENODEV; i < nr_apqns; i++) {
+		card = apqns[i] >> 16;
+		dom = apqns[i] & 0xFFFF;
+		rc = ep11_genaeskey(card, dom, keybits, 0, buf, &keysize);
+		if (rc == 0)
+			break;
+	}
+	if (rc)
+		return rc;
+
+	if (is_xts) {
+		keysize = MAXEP11AESKEYBLOBSIZE;
+		buf += MAXEP11AESKEYBLOBSIZE;
+		rc = ep11_genaeskey(card, dom, keybits, 0, buf, &keysize);
+		if (rc == 0)
+			return 2 * MAXEP11AESKEYBLOBSIZE;
+	}
+
+	return MAXEP11AESKEYBLOBSIZE;
+}
+
+static ssize_t ep11_aes_128_read(struct file *filp,
+				 struct kobject *kobj,
+				 struct bin_attribute *attr,
+				 char *buf, loff_t off,
+				 size_t count)
+{
+	return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_128, false, buf,
+				       off, count);
+}
+
+static ssize_t ep11_aes_192_read(struct file *filp,
+				 struct kobject *kobj,
+				 struct bin_attribute *attr,
+				 char *buf, loff_t off,
+				 size_t count)
+{
+	return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_192, false, buf,
+				       off, count);
+}
+
+static ssize_t ep11_aes_256_read(struct file *filp,
+				 struct kobject *kobj,
+				 struct bin_attribute *attr,
+				 char *buf, loff_t off,
+				 size_t count)
+{
+	return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_256, false, buf,
+				       off, count);
+}
+
+static ssize_t ep11_aes_128_xts_read(struct file *filp,
+				     struct kobject *kobj,
+				     struct bin_attribute *attr,
+				     char *buf, loff_t off,
+				     size_t count)
+{
+	return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_128, true, buf,
+				       off, count);
+}
+
+static ssize_t ep11_aes_256_xts_read(struct file *filp,
+				     struct kobject *kobj,
+				     struct bin_attribute *attr,
+				     char *buf, loff_t off,
+				     size_t count)
+{
+	return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_256, true, buf,
+				       off, count);
+}
+
+static BIN_ATTR_RO(ep11_aes_128, MAXEP11AESKEYBLOBSIZE);
+static BIN_ATTR_RO(ep11_aes_192, MAXEP11AESKEYBLOBSIZE);
+static BIN_ATTR_RO(ep11_aes_256, MAXEP11AESKEYBLOBSIZE);
+static BIN_ATTR_RO(ep11_aes_128_xts, 2 * MAXEP11AESKEYBLOBSIZE);
+static BIN_ATTR_RO(ep11_aes_256_xts, 2 * MAXEP11AESKEYBLOBSIZE);
+
+static struct bin_attribute *ep11_attrs[] = {
+	&bin_attr_ep11_aes_128,
+	&bin_attr_ep11_aes_192,
+	&bin_attr_ep11_aes_256,
+	&bin_attr_ep11_aes_128_xts,
+	&bin_attr_ep11_aes_256_xts,
+	NULL
+};
+
+static struct attribute_group ep11_attr_group = {
+	.name	   = "ep11",
+	.bin_attrs = ep11_attrs,
+};
+
 static const struct attribute_group *pkey_attr_groups[] = {
 	&protkey_attr_group,
 	&ccadata_attr_group,
 	&ccacipher_attr_group,
+	&ep11_attr_group,
 	NULL,
 };
 
@@ -1502,7 +1846,7 @@
  */
 static int __init pkey_init(void)
 {
-	cpacf_mask_t kmc_functions;
+	cpacf_mask_t func_mask;
 
 	/*
 	 * The pckmo instruction should be available - even if we don't
@@ -1510,15 +1854,15 @@
 	 * is also the minimum level for the kmc instructions which
 	 * are able to work with protected keys.
 	 */
-	if (!cpacf_query(CPACF_PCKMO, &pckmo_functions))
+	if (!cpacf_query(CPACF_PCKMO, &func_mask))
 		return -ENODEV;
 
 	/* check for kmc instructions available */
-	if (!cpacf_query(CPACF_KMC, &kmc_functions))
+	if (!cpacf_query(CPACF_KMC, &func_mask))
 		return -ENODEV;
-	if (!cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_128) ||
-	    !cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_192) ||
-	    !cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_256))
+	if (!cpacf_test_func(&func_mask, CPACF_KMC_PAES_128) ||
+	    !cpacf_test_func(&func_mask, CPACF_KMC_PAES_192) ||
+	    !cpacf_test_func(&func_mask, CPACF_KMC_PAES_256))
 		return -ENODEV;
 
 	pkey_debug_init();
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/crypto/vfio_ap_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/crypto/vfio_ap_drv.c
@@ -71,23 +71,20 @@
 static void vfio_ap_queue_dev_remove(struct ap_device *apdev)
 {
 	struct vfio_ap_queue *q;
-	int apid, apqi;
 
 	mutex_lock(&matrix_dev->lock);
 	q = dev_get_drvdata(&apdev->device);
+	vfio_ap_mdev_reset_queue(q, 1);
 	dev_set_drvdata(&apdev->device, NULL);
-	apid = AP_QID_CARD(q->apqn);
-	apqi = AP_QID_QUEUE(q->apqn);
-	vfio_ap_mdev_reset_queue(apid, apqi, 1);
-	vfio_ap_irq_disable(q);
 	kfree(q);
 	mutex_unlock(&matrix_dev->lock);
 }
 
 static void vfio_ap_matrix_dev_release(struct device *dev)
 {
-	struct ap_matrix_dev *matrix_dev = dev_get_drvdata(dev);
+	struct ap_matrix_dev *matrix_dev;
 
+	matrix_dev = container_of(dev, struct ap_matrix_dev, device);
 	kfree(matrix_dev);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/crypto/vfio_ap_ops.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/crypto/vfio_ap_ops.c
@@ -25,6 +25,7 @@
 #define VFIO_AP_MDEV_NAME_HWVIRT "VFIO AP Passthrough Device"
 
 static int vfio_ap_mdev_reset_queues(struct mdev_device *mdev);
+static struct vfio_ap_queue *vfio_ap_find_queue(int apqn);
 
 static int match_apqn(struct device *dev, const void *data)
 {
@@ -49,20 +50,15 @@
 					int apqn)
 {
 	struct vfio_ap_queue *q;
-	struct device *dev;
 
 	if (!test_bit_inv(AP_QID_CARD(apqn), matrix_mdev->matrix.apm))
 		return NULL;
 	if (!test_bit_inv(AP_QID_QUEUE(apqn), matrix_mdev->matrix.aqm))
 		return NULL;
 
-	dev = driver_find_device(&matrix_dev->vfio_ap_drv->driver, NULL,
-				 &apqn, match_apqn);
-	if (!dev)
-		return NULL;
-	q = dev_get_drvdata(dev);
-	q->matrix_mdev = matrix_mdev;
-	put_device(dev);
+	q = vfio_ap_find_queue(apqn);
+	if (q)
+		q->matrix_mdev = matrix_mdev;
 
 	return q;
 }
@@ -119,13 +115,18 @@
  */
 static void vfio_ap_free_aqic_resources(struct vfio_ap_queue *q)
 {
-	if (q->saved_isc != VFIO_AP_ISC_INVALID && q->matrix_mdev)
+	if (!q)
+		return;
+	if (q->saved_isc != VFIO_AP_ISC_INVALID &&
+	    !WARN_ON(!(q->matrix_mdev && q->matrix_mdev->kvm))) {
 		kvm_s390_gisc_unregister(q->matrix_mdev->kvm, q->saved_isc);
-	if (q->saved_pfn && q->matrix_mdev)
+		q->saved_isc = VFIO_AP_ISC_INVALID;
+	}
+	if (q->saved_pfn && !WARN_ON(!q->matrix_mdev)) {
 		vfio_unpin_pages(mdev_dev(q->matrix_mdev->mdev),
 				 &q->saved_pfn, 1);
-	q->saved_pfn = 0;
-	q->saved_isc = VFIO_AP_ISC_INVALID;
+		q->saved_pfn = 0;
+	}
 }
 
 /**
@@ -144,7 +145,7 @@
  * Returns if ap_aqic function failed with invalid, deconfigured or
  * checkstopped AP.
  */
-struct ap_queue_status vfio_ap_irq_disable(struct vfio_ap_queue *q)
+static struct ap_queue_status vfio_ap_irq_disable(struct vfio_ap_queue *q)
 {
 	struct ap_qirq_ctrl aqic_gisa = {};
 	struct ap_queue_status status;
@@ -1114,48 +1115,70 @@
 	return NOTIFY_OK;
 }
 
-static void vfio_ap_irq_disable_apqn(int apqn)
+static struct vfio_ap_queue *vfio_ap_find_queue(int apqn)
 {
 	struct device *dev;
-	struct vfio_ap_queue *q;
+	struct vfio_ap_queue *q = NULL;
 
 	dev = driver_find_device(&matrix_dev->vfio_ap_drv->driver, NULL,
 				 &apqn, match_apqn);
 	if (dev) {
 		q = dev_get_drvdata(dev);
-		vfio_ap_irq_disable(q);
 		put_device(dev);
 	}
+
+	return q;
 }
 
-int vfio_ap_mdev_reset_queue(unsigned int apid, unsigned int apqi,
+int vfio_ap_mdev_reset_queue(struct vfio_ap_queue *q,
 			     unsigned int retry)
 {
 	struct ap_queue_status status;
+	int ret;
 	int retry2 = 2;
-	int apqn = AP_MKQID(apid, apqi);
 
-	do {
-		status = ap_zapq(apqn);
-		switch (status.response_code) {
-		case AP_RESPONSE_NORMAL:
-			while (!status.queue_empty && retry2--) {
-				msleep(20);
-				status = ap_tapq(apqn, NULL);
-			}
-			WARN_ON_ONCE(retry2 <= 0);
-			return 0;
-		case AP_RESPONSE_RESET_IN_PROGRESS:
-		case AP_RESPONSE_BUSY:
+	if (!q)
+		return 0;
+
+retry_zapq:
+	status = ap_zapq(q->apqn);
+	switch (status.response_code) {
+	case AP_RESPONSE_NORMAL:
+		ret = 0;
+		break;
+	case AP_RESPONSE_RESET_IN_PROGRESS:
+		if (retry--) {
 			msleep(20);
-			break;
-		default:
-			/* things are really broken, give up */
-			return -EIO;
+			goto retry_zapq;
 		}
-	} while (retry--);
+		ret = -EBUSY;
+		break;
+	case AP_RESPONSE_Q_NOT_AVAIL:
+	case AP_RESPONSE_DECONFIGURED:
+	case AP_RESPONSE_CHECKSTOPPED:
+		WARN_ON_ONCE(status.irq_enabled);
+		ret = -EBUSY;
+		goto free_resources;
+	default:
+		/* things are really broken, give up */
+		WARN(true, "PQAP/ZAPQ completed with invalid rc (%x)\n",
+		     status.response_code);
+		return -EIO;
+	}
+
+	/* wait for the reset to take effect */
+	while (retry2--) {
+		if (status.queue_empty && !status.irq_enabled)
+			break;
+		msleep(20);
+		status = ap_tapq(q->apqn, NULL);
+	}
+	WARN_ON_ONCE(retry2 <= 0);
 
-	return -EBUSY;
+free_resources:
+	vfio_ap_free_aqic_resources(q);
+
+	return ret;
 }
 
 static int vfio_ap_mdev_reset_queues(struct mdev_device *mdev)
@@ -1163,13 +1186,15 @@
 	int ret;
 	int rc = 0;
 	unsigned long apid, apqi;
+	struct vfio_ap_queue *q;
 	struct ap_matrix_mdev *matrix_mdev = mdev_get_drvdata(mdev);
 
 	for_each_set_bit_inv(apid, matrix_mdev->matrix.apm,
 			     matrix_mdev->matrix.apm_max + 1) {
 		for_each_set_bit_inv(apqi, matrix_mdev->matrix.aqm,
 				     matrix_mdev->matrix.aqm_max + 1) {
-			ret = vfio_ap_mdev_reset_queue(apid, apqi, 1);
+			q = vfio_ap_find_queue(AP_MKQID(apid, apqi));
+			ret = vfio_ap_mdev_reset_queue(q, 1);
 			/*
 			 * Regardless whether a queue turns out to be busy, or
 			 * is not operational, we need to continue resetting
@@ -1177,7 +1202,6 @@
 			 */
 			if (ret)
 				rc = ret;
-			vfio_ap_irq_disable_apqn(AP_MKQID(apid, apqi));
 		}
 	}
 
@@ -1255,7 +1279,7 @@
 	info.num_regions = 0;
 	info.num_irqs = 0;
 
-	return copy_to_user((void __user *)arg, &info, minsz);
+	return copy_to_user((void __user *)arg, &info, minsz) ? -EFAULT : 0;
 }
 
 static ssize_t vfio_ap_mdev_ioctl(struct mdev_device *mdev,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/crypto/vfio_ap_private.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/crypto/vfio_ap_private.h
@@ -88,11 +88,6 @@
 	struct mdev_device *mdev;
 };
 
-extern int vfio_ap_mdev_register(void);
-extern void vfio_ap_mdev_unregister(void);
-int vfio_ap_mdev_reset_queue(unsigned int apid, unsigned int apqi,
-			     unsigned int retry);
-
 struct vfio_ap_queue {
 	struct ap_matrix_mdev *matrix_mdev;
 	unsigned long saved_pfn;
@@ -100,5 +95,10 @@
 #define VFIO_AP_ISC_INVALID 0xff
 	unsigned char saved_isc;
 };
-struct ap_queue_status vfio_ap_irq_disable(struct vfio_ap_queue *q);
+
+int vfio_ap_mdev_register(void);
+void vfio_ap_mdev_unregister(void);
+int vfio_ap_mdev_reset_queue(struct vfio_ap_queue *q,
+			     unsigned int retry);
+
 #endif /* _VFIO_AP_PRIVATE_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/crypto/zcrypt_api.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/crypto/zcrypt_api.c
@@ -25,6 +25,7 @@
 #include <linux/debugfs.h>
 #include <linux/cdev.h>
 #include <linux/ctype.h>
+#include <linux/capability.h>
 #include <asm/debug.h>
 
 #define CREATE_TRACE_POINTS
@@ -36,6 +37,7 @@
 #include "zcrypt_msgtype6.h"
 #include "zcrypt_msgtype50.h"
 #include "zcrypt_ccamisc.h"
+#include "zcrypt_ep11misc.h"
 
 /*
  * Module description.
@@ -397,6 +399,7 @@
 			 ZCRYPT_NAME "_%d", (int) MINOR(devt));
 	nodename[sizeof(nodename)-1] = '\0';
 	if (dev_set_name(&zcdndev->device, nodename)) {
+		kfree(zcdndev);
 		rc = -EINVAL;
 		goto unlockout;
 	}
@@ -573,6 +576,7 @@
 {
 	if (!zq || !try_module_get(zq->queue->ap_dev.drv->driver.owner))
 		return NULL;
+	zcrypt_card_get(zc);
 	zcrypt_queue_get(zq);
 	get_device(&zq->queue->ap_dev.device);
 	atomic_add(weight, &zc->load);
@@ -592,6 +596,7 @@
 	atomic_sub(weight, &zq->load);
 	put_device(&zq->queue->ap_dev.device);
 	zcrypt_queue_put(zq);
+	zcrypt_card_put(zc);
 	module_put(mod);
 }
 
@@ -601,13 +606,13 @@
 				       unsigned int pref_weight)
 {
 	if (!pref_zc)
-		return false;
+		return true;
 	weight += atomic_read(&zc->load);
 	pref_weight += atomic_read(&pref_zc->load);
 	if (weight == pref_weight)
-		return atomic_read(&zc->card->total_request_count) >
-			atomic_read(&pref_zc->card->total_request_count);
-	return weight > pref_weight;
+		return atomic64_read(&zc->card->total_request_count) <
+			atomic64_read(&pref_zc->card->total_request_count);
+	return weight < pref_weight;
 }
 
 static inline bool zcrypt_queue_compare(struct zcrypt_queue *zq,
@@ -616,30 +621,39 @@
 					unsigned int pref_weight)
 {
 	if (!pref_zq)
-		return false;
+		return true;
 	weight += atomic_read(&zq->load);
 	pref_weight += atomic_read(&pref_zq->load);
 	if (weight == pref_weight)
-		return zq->queue->total_request_count >
+		return zq->queue->total_request_count <
 			pref_zq->queue->total_request_count;
-	return weight > pref_weight;
+	return weight < pref_weight;
 }
 
 /*
  * zcrypt ioctls.
  */
 static long zcrypt_rsa_modexpo(struct ap_perms *perms,
+			       struct zcrypt_track *tr,
 			       struct ica_rsa_modexpo *mex)
 {
 	struct zcrypt_card *zc, *pref_zc;
 	struct zcrypt_queue *zq, *pref_zq;
-	unsigned int weight, pref_weight;
+	struct ap_message ap_msg;
+	unsigned int wgt = 0, pref_wgt = 0;
 	unsigned int func_code;
-	int qid = 0, rc = -ENODEV;
+	int cpen, qpen, qid = 0, rc = -ENODEV;
 	struct module *mod;
 
 	trace_s390_zcrypt_req(mex, TP_ICARSAMODEXPO);
 
+	ap_init_message(&ap_msg);
+
+#ifdef CONFIG_ZCRYPT_DEBUG
+	if (tr && tr->fi.cmd)
+		ap_msg.fi.cmd = tr->fi.cmd;
+#endif
+
 	if (mex->outputdatalength < mex->inputdatalength) {
 		func_code = 0;
 		rc = -EINVAL;
@@ -661,8 +675,9 @@
 	pref_zq = NULL;
 	spin_lock(&zcrypt_list_lock);
 	for_each_zcrypt_card(zc) {
-		/* Check for online accelarator and CCA cards */
-		if (!zc->online || !(zc->card->functions & 0x18000000))
+		/* Check for useable accelarator or CCA card */
+		if (!zc->online || !zc->card->config ||
+		    !(zc->card->functions & 0x18000000))
 			continue;
 		/* Check for size limits */
 		if (zc->min_mod_size > mex->inputdatalength ||
@@ -672,26 +687,35 @@
 		if (!zcrypt_check_card(perms, zc->card->id))
 			continue;
 		/* get weight index of the card device	*/
-		weight = zc->speed_rating[func_code];
-		if (zcrypt_card_compare(zc, pref_zc, weight, pref_weight))
+		wgt = zc->speed_rating[func_code];
+		/* penalty if this msg was previously sent via this card */
+		cpen = (tr && tr->again_counter && tr->last_qid &&
+			AP_QID_CARD(tr->last_qid) == zc->card->id) ?
+			TRACK_AGAIN_CARD_WEIGHT_PENALTY : 0;
+		if (!zcrypt_card_compare(zc, pref_zc, wgt + cpen, pref_wgt))
 			continue;
 		for_each_zcrypt_queue(zq, zc) {
-			/* check if device is online and eligible */
-			if (!zq->online || !zq->ops->rsa_modexpo)
+			/* check if device is useable and eligible */
+			if (!zq->online || !zq->ops->rsa_modexpo ||
+			    !zq->queue->config)
 				continue;
 			/* check if device node has admission for this queue */
 			if (!zcrypt_check_queue(perms,
 						AP_QID_QUEUE(zq->queue->qid)))
 				continue;
-			if (zcrypt_queue_compare(zq, pref_zq,
-						 weight, pref_weight))
+			/* penalty if the msg was previously sent at this qid */
+			qpen = (tr && tr->again_counter && tr->last_qid &&
+				tr->last_qid == zq->queue->qid) ?
+				TRACK_AGAIN_QUEUE_WEIGHT_PENALTY : 0;
+			if (!zcrypt_queue_compare(zq, pref_zq,
+						  wgt + cpen + qpen, pref_wgt))
 				continue;
 			pref_zc = zc;
 			pref_zq = zq;
-			pref_weight = weight;
+			pref_wgt = wgt + cpen + qpen;
 		}
 	}
-	pref_zq = zcrypt_pick_queue(pref_zc, pref_zq, &mod, weight);
+	pref_zq = zcrypt_pick_queue(pref_zc, pref_zq, &mod, wgt);
 	spin_unlock(&zcrypt_list_lock);
 
 	if (!pref_zq) {
@@ -700,30 +724,44 @@
 	}
 
 	qid = pref_zq->queue->qid;
-	rc = pref_zq->ops->rsa_modexpo(pref_zq, mex);
+	rc = pref_zq->ops->rsa_modexpo(pref_zq, mex, &ap_msg);
 
 	spin_lock(&zcrypt_list_lock);
-	zcrypt_drop_queue(pref_zc, pref_zq, mod, weight);
+	zcrypt_drop_queue(pref_zc, pref_zq, mod, wgt);
 	spin_unlock(&zcrypt_list_lock);
 
 out:
+	ap_release_message(&ap_msg);
+	if (tr) {
+		tr->last_rc = rc;
+		tr->last_qid = qid;
+	}
 	trace_s390_zcrypt_rep(mex, func_code, rc,
 			      AP_QID_CARD(qid), AP_QID_QUEUE(qid));
 	return rc;
 }
 
 static long zcrypt_rsa_crt(struct ap_perms *perms,
+			   struct zcrypt_track *tr,
 			   struct ica_rsa_modexpo_crt *crt)
 {
 	struct zcrypt_card *zc, *pref_zc;
 	struct zcrypt_queue *zq, *pref_zq;
-	unsigned int weight, pref_weight;
+	struct ap_message ap_msg;
+	unsigned int wgt = 0, pref_wgt = 0;
 	unsigned int func_code;
-	int qid = 0, rc = -ENODEV;
+	int cpen, qpen, qid = 0, rc = -ENODEV;
 	struct module *mod;
 
 	trace_s390_zcrypt_req(crt, TP_ICARSACRT);
 
+	ap_init_message(&ap_msg);
+
+#ifdef CONFIG_ZCRYPT_DEBUG
+	if (tr && tr->fi.cmd)
+		ap_msg.fi.cmd = tr->fi.cmd;
+#endif
+
 	if (crt->outputdatalength < crt->inputdatalength) {
 		func_code = 0;
 		rc = -EINVAL;
@@ -745,8 +783,9 @@
 	pref_zq = NULL;
 	spin_lock(&zcrypt_list_lock);
 	for_each_zcrypt_card(zc) {
-		/* Check for online accelarator and CCA cards */
-		if (!zc->online || !(zc->card->functions & 0x18000000))
+		/* Check for useable accelarator or CCA card */
+		if (!zc->online || !zc->card->config ||
+		    !(zc->card->functions & 0x18000000))
 			continue;
 		/* Check for size limits */
 		if (zc->min_mod_size > crt->inputdatalength ||
@@ -756,26 +795,35 @@
 		if (!zcrypt_check_card(perms, zc->card->id))
 			continue;
 		/* get weight index of the card device	*/
-		weight = zc->speed_rating[func_code];
-		if (zcrypt_card_compare(zc, pref_zc, weight, pref_weight))
+		wgt = zc->speed_rating[func_code];
+		/* penalty if this msg was previously sent via this card */
+		cpen = (tr && tr->again_counter && tr->last_qid &&
+			AP_QID_CARD(tr->last_qid) == zc->card->id) ?
+			TRACK_AGAIN_CARD_WEIGHT_PENALTY : 0;
+		if (!zcrypt_card_compare(zc, pref_zc, wgt + cpen, pref_wgt))
 			continue;
 		for_each_zcrypt_queue(zq, zc) {
-			/* check if device is online and eligible */
-			if (!zq->online || !zq->ops->rsa_modexpo_crt)
+			/* check if device is useable and eligible */
+			if (!zq->online || !zq->ops->rsa_modexpo_crt ||
+			    !zq->queue->config)
 				continue;
 			/* check if device node has admission for this queue */
 			if (!zcrypt_check_queue(perms,
 						AP_QID_QUEUE(zq->queue->qid)))
 				continue;
-			if (zcrypt_queue_compare(zq, pref_zq,
-						 weight, pref_weight))
+			/* penalty if the msg was previously sent at this qid */
+			qpen = (tr && tr->again_counter && tr->last_qid &&
+				tr->last_qid == zq->queue->qid) ?
+				TRACK_AGAIN_QUEUE_WEIGHT_PENALTY : 0;
+			if (!zcrypt_queue_compare(zq, pref_zq,
+						  wgt + cpen + qpen, pref_wgt))
 				continue;
 			pref_zc = zc;
 			pref_zq = zq;
-			pref_weight = weight;
+			pref_wgt = wgt + cpen + qpen;
 		}
 	}
-	pref_zq = zcrypt_pick_queue(pref_zc, pref_zq, &mod, weight);
+	pref_zq = zcrypt_pick_queue(pref_zc, pref_zq, &mod, wgt);
 	spin_unlock(&zcrypt_list_lock);
 
 	if (!pref_zq) {
@@ -784,35 +832,52 @@
 	}
 
 	qid = pref_zq->queue->qid;
-	rc = pref_zq->ops->rsa_modexpo_crt(pref_zq, crt);
+	rc = pref_zq->ops->rsa_modexpo_crt(pref_zq, crt, &ap_msg);
 
 	spin_lock(&zcrypt_list_lock);
-	zcrypt_drop_queue(pref_zc, pref_zq, mod, weight);
+	zcrypt_drop_queue(pref_zc, pref_zq, mod, wgt);
 	spin_unlock(&zcrypt_list_lock);
 
 out:
+	ap_release_message(&ap_msg);
+	if (tr) {
+		tr->last_rc = rc;
+		tr->last_qid = qid;
+	}
 	trace_s390_zcrypt_rep(crt, func_code, rc,
 			      AP_QID_CARD(qid), AP_QID_QUEUE(qid));
 	return rc;
 }
 
-static long _zcrypt_send_cprb(struct ap_perms *perms,
+static long _zcrypt_send_cprb(bool userspace, struct ap_perms *perms,
+			      struct zcrypt_track *tr,
 			      struct ica_xcRB *xcRB)
 {
 	struct zcrypt_card *zc, *pref_zc;
 	struct zcrypt_queue *zq, *pref_zq;
 	struct ap_message ap_msg;
-	unsigned int weight, pref_weight;
+	unsigned int wgt = 0, pref_wgt = 0;
 	unsigned int func_code;
 	unsigned short *domain, tdom;
-	int qid = 0, rc = -ENODEV;
+	int cpen, qpen, qid = 0, rc = -ENODEV;
 	struct module *mod;
 
 	trace_s390_zcrypt_req(xcRB, TB_ZSECSENDCPRB);
 
 	xcRB->status = 0;
 	ap_init_message(&ap_msg);
-	rc = get_cprb_fc(xcRB, &ap_msg, &func_code, &domain);
+
+#ifdef CONFIG_ZCRYPT_DEBUG
+	if (tr && tr->fi.cmd)
+		ap_msg.fi.cmd = tr->fi.cmd;
+	if (tr && tr->fi.action == AP_FI_ACTION_CCA_AGENT_FF) {
+		ZCRYPT_DBF_WARN("%s fi cmd 0x%04x: forcing invalid agent_ID 'FF'\n",
+				__func__, tr->fi.cmd);
+		xcRB->agent_ID = 0x4646;
+	}
+#endif
+
+	rc = get_cprb_fc(userspace, xcRB, &ap_msg, &func_code, &domain);
 	if (rc)
 		goto out;
 
@@ -821,7 +886,7 @@
 	 * domain but a control only domain, use the default domain as target.
 	 */
 	tdom = *domain;
-	if (tdom >= 0 && tdom < AP_DOMAINS &&
+	if (tdom < AP_DOMAINS &&
 	    !ap_test_config_usage_domain(tdom) &&
 	    ap_test_config_ctrl_domain(tdom) &&
 	    ap_domain_index >= 0)
@@ -831,40 +896,53 @@
 	pref_zq = NULL;
 	spin_lock(&zcrypt_list_lock);
 	for_each_zcrypt_card(zc) {
-		/* Check for online CCA cards */
-		if (!zc->online || !(zc->card->functions & 0x10000000))
+		/* Check for useable CCA card */
+		if (!zc->online || !zc->card->config ||
+		    !(zc->card->functions & 0x10000000))
 			continue;
 		/* Check for user selected CCA card */
 		if (xcRB->user_defined != AUTOSELECT &&
 		    xcRB->user_defined != zc->card->id)
 			continue;
+		/* check if request size exceeds card max msg size */
+		if (ap_msg.len > zc->card->maxmsgsize)
+			continue;
 		/* check if device node has admission for this card */
 		if (!zcrypt_check_card(perms, zc->card->id))
 			continue;
 		/* get weight index of the card device	*/
-		weight = speed_idx_cca(func_code) * zc->speed_rating[SECKEY];
-		if (zcrypt_card_compare(zc, pref_zc, weight, pref_weight))
+		wgt = speed_idx_cca(func_code) * zc->speed_rating[SECKEY];
+		/* penalty if this msg was previously sent via this card */
+		cpen = (tr && tr->again_counter && tr->last_qid &&
+			AP_QID_CARD(tr->last_qid) == zc->card->id) ?
+			TRACK_AGAIN_CARD_WEIGHT_PENALTY : 0;
+		if (!zcrypt_card_compare(zc, pref_zc, wgt + cpen, pref_wgt))
 			continue;
 		for_each_zcrypt_queue(zq, zc) {
-			/* check if device is online and eligible */
+			/* check for device useable and eligible */
 			if (!zq->online ||
 			    !zq->ops->send_cprb ||
-			    (tdom != (unsigned short) AUTOSELECT &&
+			    !zq->queue->config ||
+			    (tdom != AUTOSEL_DOM &&
 			     tdom != AP_QID_QUEUE(zq->queue->qid)))
 				continue;
 			/* check if device node has admission for this queue */
 			if (!zcrypt_check_queue(perms,
 						AP_QID_QUEUE(zq->queue->qid)))
 				continue;
-			if (zcrypt_queue_compare(zq, pref_zq,
-						 weight, pref_weight))
+			/* penalty if the msg was previously sent at this qid */
+			qpen = (tr && tr->again_counter && tr->last_qid &&
+				tr->last_qid == zq->queue->qid) ?
+				TRACK_AGAIN_QUEUE_WEIGHT_PENALTY : 0;
+			if (!zcrypt_queue_compare(zq, pref_zq,
+						  wgt + cpen + qpen, pref_wgt))
 				continue;
 			pref_zc = zc;
 			pref_zq = zq;
-			pref_weight = weight;
+			pref_wgt = wgt + cpen + qpen;
 		}
 	}
-	pref_zq = zcrypt_pick_queue(pref_zc, pref_zq, &mod, weight);
+	pref_zq = zcrypt_pick_queue(pref_zc, pref_zq, &mod, wgt);
 	spin_unlock(&zcrypt_list_lock);
 
 	if (!pref_zq) {
@@ -874,17 +952,29 @@
 
 	/* in case of auto select, provide the correct domain */
 	qid = pref_zq->queue->qid;
-	if (*domain == (unsigned short) AUTOSELECT)
+	if (*domain == AUTOSEL_DOM)
 		*domain = AP_QID_QUEUE(qid);
 
-	rc = pref_zq->ops->send_cprb(pref_zq, xcRB, &ap_msg);
+#ifdef CONFIG_ZCRYPT_DEBUG
+	if (tr && tr->fi.action == AP_FI_ACTION_CCA_DOM_INVAL) {
+		ZCRYPT_DBF_WARN("%s fi cmd 0x%04x: forcing invalid domain\n",
+				__func__, tr->fi.cmd);
+		*domain = 99;
+	}
+#endif
+
+	rc = pref_zq->ops->send_cprb(userspace, pref_zq, xcRB, &ap_msg);
 
 	spin_lock(&zcrypt_list_lock);
-	zcrypt_drop_queue(pref_zc, pref_zq, mod, weight);
+	zcrypt_drop_queue(pref_zc, pref_zq, mod, wgt);
 	spin_unlock(&zcrypt_list_lock);
 
 out:
 	ap_release_message(&ap_msg);
+	if (tr) {
+		tr->last_rc = rc;
+		tr->last_qid = qid;
+	}
 	trace_s390_zcrypt_rep(xcRB, func_code, rc,
 			      AP_QID_CARD(qid), AP_QID_QUEUE(qid));
 	return rc;
@@ -892,7 +982,7 @@
 
 long zcrypt_send_cprb(struct ica_xcRB *xcRB)
 {
-	return _zcrypt_send_cprb(&ap_perms, xcRB);
+	return _zcrypt_send_cprb(false, &ap_perms, NULL, xcRB);
 }
 EXPORT_SYMBOL(zcrypt_send_cprb);
 
@@ -901,7 +991,7 @@
 				 struct ep11_target_dev *targets)
 {
 	while (target_num-- > 0) {
-		if (dev_id == targets->ap_id)
+		if (targets->ap_id == dev_id || targets->ap_id == AUTOSEL_AP)
 			return true;
 		targets++;
 	}
@@ -912,31 +1002,40 @@
 				  unsigned short target_num,
 				  struct ep11_target_dev *targets)
 {
+	int card = AP_QID_CARD(dev_qid), dom = AP_QID_QUEUE(dev_qid);
+
 	while (target_num-- > 0) {
-		if (AP_MKQID(targets->ap_id, targets->dom_id) == dev_qid)
+		if ((targets->ap_id == card || targets->ap_id == AUTOSEL_AP) &&
+		    (targets->dom_id == dom || targets->dom_id == AUTOSEL_DOM))
 			return true;
 		targets++;
 	}
 	return false;
 }
 
-static long zcrypt_send_ep11_cprb(struct ap_perms *perms,
-				  struct ep11_urb *xcrb)
+static long _zcrypt_send_ep11_cprb(bool userspace, struct ap_perms *perms,
+				   struct zcrypt_track *tr,
+				   struct ep11_urb *xcrb)
 {
 	struct zcrypt_card *zc, *pref_zc;
 	struct zcrypt_queue *zq, *pref_zq;
 	struct ep11_target_dev *targets;
 	unsigned short target_num;
-	unsigned int weight, pref_weight;
+	unsigned int wgt = 0, pref_wgt = 0;
 	unsigned int func_code;
 	struct ap_message ap_msg;
-	int qid = 0, rc = -ENODEV;
+	int cpen, qpen, qid = 0, rc = -ENODEV;
 	struct module *mod;
 
 	trace_s390_zcrypt_req(xcrb, TP_ZSENDEP11CPRB);
 
 	ap_init_message(&ap_msg);
 
+#ifdef CONFIG_ZCRYPT_DEBUG
+	if (tr && tr->fi.cmd)
+		ap_msg.fi.cmd = tr->fi.cmd;
+#endif
+
 	target_num = (unsigned short) xcrb->targets_num;
 
 	/* empty list indicates autoselect (all available targets) */
@@ -952,7 +1051,7 @@
 		}
 
 		uptr = (struct ep11_target_dev __force __user *) xcrb->targets;
-		if (copy_from_user(targets, uptr,
+		if (z_copy_from_user(userspace, targets, uptr,
 				   target_num * sizeof(*targets))) {
 			func_code = 0;
 			rc = -EFAULT;
@@ -960,7 +1059,7 @@
 		}
 	}
 
-	rc = get_ep11cprb_fc(xcrb, &ap_msg, &func_code);
+	rc = get_ep11cprb_fc(userspace, xcrb, &ap_msg, &func_code);
 	if (rc)
 		goto out_free;
 
@@ -968,24 +1067,33 @@
 	pref_zq = NULL;
 	spin_lock(&zcrypt_list_lock);
 	for_each_zcrypt_card(zc) {
-		/* Check for online EP11 cards */
-		if (!zc->online || !(zc->card->functions & 0x04000000))
+		/* Check for useable EP11 card */
+		if (!zc->online || !zc->card->config ||
+		    !(zc->card->functions & 0x04000000))
 			continue;
 		/* Check for user selected EP11 card */
 		if (targets &&
 		    !is_desired_ep11_card(zc->card->id, target_num, targets))
 			continue;
+		/* check if request size exceeds card max msg size */
+		if (ap_msg.len > zc->card->maxmsgsize)
+			continue;
 		/* check if device node has admission for this card */
 		if (!zcrypt_check_card(perms, zc->card->id))
 			continue;
 		/* get weight index of the card device	*/
-		weight = speed_idx_ep11(func_code) * zc->speed_rating[SECKEY];
-		if (zcrypt_card_compare(zc, pref_zc, weight, pref_weight))
+		wgt = speed_idx_ep11(func_code) * zc->speed_rating[SECKEY];
+		/* penalty if this msg was previously sent via this card */
+		cpen = (tr && tr->again_counter && tr->last_qid &&
+			AP_QID_CARD(tr->last_qid) == zc->card->id) ?
+			TRACK_AGAIN_CARD_WEIGHT_PENALTY : 0;
+		if (!zcrypt_card_compare(zc, pref_zc, wgt + cpen, pref_wgt))
 			continue;
 		for_each_zcrypt_queue(zq, zc) {
-			/* check if device is online and eligible */
+			/* check if device is useable and eligible */
 			if (!zq->online ||
 			    !zq->ops->send_ep11_cprb ||
+			    !zq->queue->config ||
 			    (targets &&
 			     !is_desired_ep11_queue(zq->queue->qid,
 						    target_num, targets)))
@@ -994,15 +1102,19 @@
 			if (!zcrypt_check_queue(perms,
 						AP_QID_QUEUE(zq->queue->qid)))
 				continue;
-			if (zcrypt_queue_compare(zq, pref_zq,
-						 weight, pref_weight))
+			/* penalty if the msg was previously sent at this qid */
+			qpen = (tr && tr->again_counter && tr->last_qid &&
+				tr->last_qid == zq->queue->qid) ?
+				TRACK_AGAIN_QUEUE_WEIGHT_PENALTY : 0;
+			if (!zcrypt_queue_compare(zq, pref_zq,
+						  wgt + cpen + qpen, pref_wgt))
 				continue;
 			pref_zc = zc;
 			pref_zq = zq;
-			pref_weight = weight;
+			pref_wgt = wgt + cpen + qpen;
 		}
 	}
-	pref_zq = zcrypt_pick_queue(pref_zc, pref_zq, &mod, weight);
+	pref_zq = zcrypt_pick_queue(pref_zc, pref_zq, &mod, wgt);
 	spin_unlock(&zcrypt_list_lock);
 
 	if (!pref_zq) {
@@ -1011,26 +1123,36 @@
 	}
 
 	qid = pref_zq->queue->qid;
-	rc = pref_zq->ops->send_ep11_cprb(pref_zq, xcrb, &ap_msg);
+	rc = pref_zq->ops->send_ep11_cprb(userspace, pref_zq, xcrb, &ap_msg);
 
 	spin_lock(&zcrypt_list_lock);
-	zcrypt_drop_queue(pref_zc, pref_zq, mod, weight);
+	zcrypt_drop_queue(pref_zc, pref_zq, mod, wgt);
 	spin_unlock(&zcrypt_list_lock);
 
 out_free:
 	kfree(targets);
 out:
 	ap_release_message(&ap_msg);
+	if (tr) {
+		tr->last_rc = rc;
+		tr->last_qid = qid;
+	}
 	trace_s390_zcrypt_rep(xcrb, func_code, rc,
 			      AP_QID_CARD(qid), AP_QID_QUEUE(qid));
 	return rc;
 }
 
+long zcrypt_send_ep11_cprb(struct ep11_urb *xcrb)
+{
+	return _zcrypt_send_ep11_cprb(false, &ap_perms, NULL, xcrb);
+}
+EXPORT_SYMBOL(zcrypt_send_ep11_cprb);
+
 static long zcrypt_rng(char *buffer)
 {
 	struct zcrypt_card *zc, *pref_zc;
 	struct zcrypt_queue *zq, *pref_zq;
-	unsigned int weight, pref_weight;
+	unsigned int wgt = 0, pref_wgt = 0;
 	unsigned int func_code;
 	struct ap_message ap_msg;
 	unsigned int domain;
@@ -1048,26 +1170,27 @@
 	pref_zq = NULL;
 	spin_lock(&zcrypt_list_lock);
 	for_each_zcrypt_card(zc) {
-		/* Check for online CCA cards */
-		if (!zc->online || !(zc->card->functions & 0x10000000))
+		/* Check for useable CCA card */
+		if (!zc->online || !zc->card->config ||
+		    !(zc->card->functions & 0x10000000))
 			continue;
 		/* get weight index of the card device	*/
-		weight = zc->speed_rating[func_code];
-		if (zcrypt_card_compare(zc, pref_zc, weight, pref_weight))
+		wgt = zc->speed_rating[func_code];
+		if (!zcrypt_card_compare(zc, pref_zc, wgt, pref_wgt))
 			continue;
 		for_each_zcrypt_queue(zq, zc) {
-			/* check if device is online and eligible */
-			if (!zq->online || !zq->ops->rng)
+			/* check if device is useable and eligible */
+			if (!zq->online || !zq->ops->rng ||
+			    !zq->queue->config)
 				continue;
-			if (zcrypt_queue_compare(zq, pref_zq,
-						 weight, pref_weight))
+			if (!zcrypt_queue_compare(zq, pref_zq, wgt, pref_wgt))
 				continue;
 			pref_zc = zc;
 			pref_zq = zq;
-			pref_weight = weight;
+			pref_wgt = wgt;
 		}
 	}
-	pref_zq = zcrypt_pick_queue(pref_zc, pref_zq, &mod, weight);
+	pref_zq = zcrypt_pick_queue(pref_zc, pref_zq, &mod, wgt);
 	spin_unlock(&zcrypt_list_lock);
 
 	if (!pref_zq) {
@@ -1079,7 +1202,7 @@
 	rc = pref_zq->ops->rng(pref_zq, buffer, &ap_msg);
 
 	spin_lock(&zcrypt_list_lock);
-	zcrypt_drop_queue(pref_zc, pref_zq, mod, weight);
+	zcrypt_drop_queue(pref_zc, pref_zq, mod, wgt);
 	spin_unlock(&zcrypt_list_lock);
 
 out:
@@ -1216,11 +1339,12 @@
 	spin_unlock(&zcrypt_list_lock);
 }
 
-static void zcrypt_perdev_reqcnt(int reqcnt[], size_t max_adapters)
+static void zcrypt_perdev_reqcnt(u32 reqcnt[], size_t max_adapters)
 {
 	struct zcrypt_card *zc;
 	struct zcrypt_queue *zq;
 	int card;
+	u64 cnt;
 
 	memset(reqcnt, 0, sizeof(int) * max_adapters);
 	spin_lock(&zcrypt_list_lock);
@@ -1232,8 +1356,9 @@
 			    || card >= max_adapters)
 				continue;
 			spin_lock(&zq->queue->lock);
-			reqcnt[card] = zq->queue->total_request_count;
+			cnt = zq->queue->total_request_count;
 			spin_unlock(&zq->queue->lock);
+			reqcnt[card] = (cnt < UINT_MAX) ? (u32) cnt : UINT_MAX;
 		}
 	}
 	local_bh_enable();
@@ -1286,99 +1411,207 @@
 	return requestq_count;
 }
 
-static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd,
-				  unsigned long arg)
+static int icarsamodexpo_ioctl(struct ap_perms *perms, unsigned long arg)
 {
 	int rc;
-	struct ap_perms *perms =
-		(struct ap_perms *) filp->private_data;
+	struct zcrypt_track tr;
+	struct ica_rsa_modexpo mex;
+	struct ica_rsa_modexpo __user *umex = (void __user *) arg;
 
-	rc = zcrypt_check_ioctl(perms, cmd);
-	if (rc)
-		return rc;
+	memset(&tr, 0, sizeof(tr));
+	if (copy_from_user(&mex, umex, sizeof(mex)))
+		return -EFAULT;
 
-	switch (cmd) {
-	case ICARSAMODEXPO: {
-		struct ica_rsa_modexpo __user *umex = (void __user *) arg;
-		struct ica_rsa_modexpo mex;
+#ifdef CONFIG_ZCRYPT_DEBUG
+	if (mex.inputdatalength & (1U << 31)) {
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		tr.fi.cmd = (u16)(mex.inputdatalength >> 16);
+	}
+	mex.inputdatalength &= 0x0000FFFF;
+#endif
 
-		if (copy_from_user(&mex, umex, sizeof(mex)))
-			return -EFAULT;
+	do {
+		rc = zcrypt_rsa_modexpo(perms, &tr, &mex);
+		if (rc == -EAGAIN)
+			tr.again_counter++;
+#ifdef CONFIG_ZCRYPT_DEBUG
+		if (rc == -EAGAIN && (tr.fi.flags & AP_FI_FLAG_NO_RETRY))
+			break;
+#endif
+	} while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX);
+	/* on failure: retry once again after a requested rescan */
+	if ((rc == -ENODEV) && (zcrypt_process_rescan()))
 		do {
-			rc = zcrypt_rsa_modexpo(perms, &mex);
-		} while (rc == -EAGAIN);
-		/* on failure: retry once again after a requested rescan */
-		if ((rc == -ENODEV) && (zcrypt_process_rescan()))
-			do {
-				rc = zcrypt_rsa_modexpo(perms, &mex);
-			} while (rc == -EAGAIN);
-		if (rc) {
-			ZCRYPT_DBF(DBF_DEBUG, "ioctl ICARSAMODEXPO rc=%d\n", rc);
-			return rc;
-		}
-		return put_user(mex.outputdatalength, &umex->outputdatalength);
+			rc = zcrypt_rsa_modexpo(perms, &tr, &mex);
+			if (rc == -EAGAIN)
+				tr.again_counter++;
+		} while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX);
+	if (rc == -EAGAIN && tr.again_counter >= TRACK_AGAIN_MAX)
+		rc = -EIO;
+	if (rc) {
+		ZCRYPT_DBF(DBF_DEBUG, "ioctl ICARSAMODEXPO rc=%d\n", rc);
+		return rc;
 	}
-	case ICARSACRT: {
-		struct ica_rsa_modexpo_crt __user *ucrt = (void __user *) arg;
-		struct ica_rsa_modexpo_crt crt;
+	return put_user(mex.outputdatalength, &umex->outputdatalength);
+}
 
-		if (copy_from_user(&crt, ucrt, sizeof(crt)))
-			return -EFAULT;
-		do {
-			rc = zcrypt_rsa_crt(perms, &crt);
-		} while (rc == -EAGAIN);
-		/* on failure: retry once again after a requested rescan */
-		if ((rc == -ENODEV) && (zcrypt_process_rescan()))
-			do {
-				rc = zcrypt_rsa_crt(perms, &crt);
-			} while (rc == -EAGAIN);
-		if (rc) {
-			ZCRYPT_DBF(DBF_DEBUG, "ioctl ICARSACRT rc=%d\n", rc);
-			return rc;
-		}
-		return put_user(crt.outputdatalength, &ucrt->outputdatalength);
+static int icarsacrt_ioctl(struct ap_perms *perms, unsigned long arg)
+{
+	int rc;
+	struct zcrypt_track tr;
+	struct ica_rsa_modexpo_crt crt;
+	struct ica_rsa_modexpo_crt __user *ucrt = (void __user *) arg;
+
+	memset(&tr, 0, sizeof(tr));
+	if (copy_from_user(&crt, ucrt, sizeof(crt)))
+		return -EFAULT;
+
+#ifdef CONFIG_ZCRYPT_DEBUG
+	if (crt.inputdatalength & (1U << 31)) {
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		tr.fi.cmd = (u16)(crt.inputdatalength >> 16);
 	}
-	case ZSECSENDCPRB: {
-		struct ica_xcRB __user *uxcRB = (void __user *) arg;
-		struct ica_xcRB xcRB;
+	crt.inputdatalength &= 0x0000FFFF;
+#endif
 
-		if (copy_from_user(&xcRB, uxcRB, sizeof(xcRB)))
-			return -EFAULT;
+	do {
+		rc = zcrypt_rsa_crt(perms, &tr, &crt);
+		if (rc == -EAGAIN)
+			tr.again_counter++;
+#ifdef CONFIG_ZCRYPT_DEBUG
+		if (rc == -EAGAIN && (tr.fi.flags & AP_FI_FLAG_NO_RETRY))
+			break;
+#endif
+	} while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX);
+	/* on failure: retry once again after a requested rescan */
+	if ((rc == -ENODEV) && (zcrypt_process_rescan()))
 		do {
-			rc = _zcrypt_send_cprb(perms, &xcRB);
-		} while (rc == -EAGAIN);
-		/* on failure: retry once again after a requested rescan */
-		if ((rc == -ENODEV) && (zcrypt_process_rescan()))
-			do {
-				rc = _zcrypt_send_cprb(perms, &xcRB);
-			} while (rc == -EAGAIN);
-		if (rc)
-			ZCRYPT_DBF(DBF_DEBUG, "ioctl ZSENDCPRB rc=%d status=0x%x\n",
-				   rc, xcRB.status);
-		if (copy_to_user(uxcRB, &xcRB, sizeof(xcRB)))
-			return -EFAULT;
+			rc = zcrypt_rsa_crt(perms, &tr, &crt);
+			if (rc == -EAGAIN)
+				tr.again_counter++;
+		} while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX);
+	if (rc == -EAGAIN && tr.again_counter >= TRACK_AGAIN_MAX)
+		rc = -EIO;
+	if (rc) {
+		ZCRYPT_DBF(DBF_DEBUG, "ioctl ICARSACRT rc=%d\n", rc);
 		return rc;
 	}
-	case ZSENDEP11CPRB: {
-		struct ep11_urb __user *uxcrb = (void __user *)arg;
-		struct ep11_urb xcrb;
+	return put_user(crt.outputdatalength, &ucrt->outputdatalength);
+}
 
-		if (copy_from_user(&xcrb, uxcrb, sizeof(xcrb)))
-			return -EFAULT;
+static int zsecsendcprb_ioctl(struct ap_perms *perms, unsigned long arg)
+{
+	int rc;
+	struct ica_xcRB xcRB;
+	struct zcrypt_track tr;
+	struct ica_xcRB __user *uxcRB = (void __user *) arg;
+
+	memset(&tr, 0, sizeof(tr));
+	if (copy_from_user(&xcRB, uxcRB, sizeof(xcRB)))
+		return -EFAULT;
+
+#ifdef CONFIG_ZCRYPT_DEBUG
+	if (xcRB.status & (1U << 31)) {
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		tr.fi.cmd = (u16)(xcRB.status >> 16);
+	}
+	xcRB.status &= 0x0000FFFF;
+#endif
+
+	do {
+		rc = _zcrypt_send_cprb(true, perms, &tr, &xcRB);
+		if (rc == -EAGAIN)
+			tr.again_counter++;
+#ifdef CONFIG_ZCRYPT_DEBUG
+		if (rc == -EAGAIN && (tr.fi.flags & AP_FI_FLAG_NO_RETRY))
+			break;
+#endif
+	} while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX);
+	/* on failure: retry once again after a requested rescan */
+	if ((rc == -ENODEV) && (zcrypt_process_rescan()))
 		do {
-			rc = zcrypt_send_ep11_cprb(perms, &xcrb);
-		} while (rc == -EAGAIN);
-		/* on failure: retry once again after a requested rescan */
-		if ((rc == -ENODEV) && (zcrypt_process_rescan()))
-			do {
-				rc = zcrypt_send_ep11_cprb(perms, &xcrb);
-			} while (rc == -EAGAIN);
-		if (rc)
-			ZCRYPT_DBF(DBF_DEBUG, "ioctl ZSENDEP11CPRB rc=%d\n", rc);
-		if (copy_to_user(uxcrb, &xcrb, sizeof(xcrb)))
-			return -EFAULT;
-		return rc;
+			rc = _zcrypt_send_cprb(true, perms, &tr, &xcRB);
+			if (rc == -EAGAIN)
+				tr.again_counter++;
+		} while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX);
+	if (rc == -EAGAIN && tr.again_counter >= TRACK_AGAIN_MAX)
+		rc = -EIO;
+	if (rc)
+		ZCRYPT_DBF(DBF_DEBUG, "ioctl ZSENDCPRB rc=%d status=0x%x\n",
+			   rc, xcRB.status);
+	if (copy_to_user(uxcRB, &xcRB, sizeof(xcRB)))
+		return -EFAULT;
+	return rc;
+}
+
+static int zsendep11cprb_ioctl(struct ap_perms *perms, unsigned long arg)
+{
+	int rc;
+	struct ep11_urb xcrb;
+	struct zcrypt_track tr;
+	struct ep11_urb __user *uxcrb = (void __user *)arg;
+
+	memset(&tr, 0, sizeof(tr));
+	if (copy_from_user(&xcrb, uxcrb, sizeof(xcrb)))
+		return -EFAULT;
+
+#ifdef CONFIG_ZCRYPT_DEBUG
+	if (xcrb.req_len & (1ULL << 63)) {
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		tr.fi.cmd = (u16)(xcrb.req_len >> 48);
 	}
+	xcrb.req_len &= 0x0000FFFFFFFFFFFFULL;
+#endif
+
+	do {
+		rc = _zcrypt_send_ep11_cprb(true, perms, &tr, &xcrb);
+		if (rc == -EAGAIN)
+			tr.again_counter++;
+#ifdef CONFIG_ZCRYPT_DEBUG
+		if (rc == -EAGAIN && (tr.fi.flags & AP_FI_FLAG_NO_RETRY))
+			break;
+#endif
+	} while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX);
+	/* on failure: retry once again after a requested rescan */
+	if ((rc == -ENODEV) && (zcrypt_process_rescan()))
+		do {
+			rc = _zcrypt_send_ep11_cprb(true, perms, &tr, &xcrb);
+			if (rc == -EAGAIN)
+				tr.again_counter++;
+		} while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX);
+	if (rc == -EAGAIN && tr.again_counter >= TRACK_AGAIN_MAX)
+		rc = -EIO;
+	if (rc)
+		ZCRYPT_DBF(DBF_DEBUG, "ioctl ZSENDEP11CPRB rc=%d\n", rc);
+	if (copy_to_user(uxcrb, &xcrb, sizeof(xcrb)))
+		return -EFAULT;
+	return rc;
+}
+
+static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd,
+				  unsigned long arg)
+{
+	int rc;
+	struct ap_perms *perms =
+		(struct ap_perms *) filp->private_data;
+
+	rc = zcrypt_check_ioctl(perms, cmd);
+	if (rc)
+		return rc;
+
+	switch (cmd) {
+	case ICARSAMODEXPO:
+		return icarsamodexpo_ioctl(perms, arg);
+	case ICARSACRT:
+		return icarsacrt_ioctl(perms, arg);
+	case ZSECSENDCPRB:
+		return zsecsendcprb_ioctl(perms, arg);
+	case ZSENDEP11CPRB:
+		return zsendep11cprb_ioctl(perms, arg);
 	case ZCRYPT_DEVICE_STATUS: {
 		struct zcrypt_device_status_ext *device_status;
 		size_t total_size = MAX_ZDEV_ENTRIES_EXT
@@ -1411,13 +1644,14 @@
 		return 0;
 	}
 	case ZCRYPT_PERDEV_REQCNT: {
-		int *reqcnt;
+		u32 *reqcnt;
 
-		reqcnt = kcalloc(AP_DEVICES, sizeof(int), GFP_KERNEL);
+		reqcnt = kcalloc(AP_DEVICES, sizeof(u32), GFP_KERNEL);
 		if (!reqcnt)
 			return -ENOMEM;
 		zcrypt_perdev_reqcnt(reqcnt, AP_DEVICES);
-		if (copy_to_user((int __user *) arg, reqcnt, sizeof(reqcnt)))
+		if (copy_to_user((int __user *) arg, reqcnt,
+				 sizeof(u32) * AP_DEVICES))
 			rc = -EFAULT;
 		kfree(reqcnt);
 		return rc;
@@ -1470,7 +1704,7 @@
 	}
 	case Z90STAT_PERDEV_REQCNT: {
 		/* the old ioctl supports only 64 adapters */
-		int reqcnt[MAX_ZDEV_CARDIDS];
+		u32 reqcnt[MAX_ZDEV_CARDIDS];
 
 		zcrypt_perdev_reqcnt(reqcnt, MAX_ZDEV_CARDIDS);
 		if (copy_to_user((int __user *) arg, reqcnt, sizeof(reqcnt)))
@@ -1503,8 +1737,10 @@
 	struct compat_ica_rsa_modexpo __user *umex32 = compat_ptr(arg);
 	struct compat_ica_rsa_modexpo mex32;
 	struct ica_rsa_modexpo mex64;
+	struct zcrypt_track tr;
 	long rc;
 
+	memset(&tr, 0, sizeof(tr));
 	if (copy_from_user(&mex32, umex32, sizeof(mex32)))
 		return -EFAULT;
 	mex64.inputdata = compat_ptr(mex32.inputdata);
@@ -1514,13 +1750,19 @@
 	mex64.b_key = compat_ptr(mex32.b_key);
 	mex64.n_modulus = compat_ptr(mex32.n_modulus);
 	do {
-		rc = zcrypt_rsa_modexpo(perms, &mex64);
-	} while (rc == -EAGAIN);
+		rc = zcrypt_rsa_modexpo(perms, &tr, &mex64);
+		if (rc == -EAGAIN)
+			tr.again_counter++;
+	} while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX);
 	/* on failure: retry once again after a requested rescan */
 	if ((rc == -ENODEV) && (zcrypt_process_rescan()))
 		do {
-			rc = zcrypt_rsa_modexpo(perms, &mex64);
-		} while (rc == -EAGAIN);
+			rc = zcrypt_rsa_modexpo(perms, &tr, &mex64);
+			if (rc == -EAGAIN)
+				tr.again_counter++;
+		} while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX);
+	if (rc == -EAGAIN && tr.again_counter >= TRACK_AGAIN_MAX)
+		rc = -EIO;
 	if (rc)
 		return rc;
 	return put_user(mex64.outputdatalength,
@@ -1545,8 +1787,10 @@
 	struct compat_ica_rsa_modexpo_crt __user *ucrt32 = compat_ptr(arg);
 	struct compat_ica_rsa_modexpo_crt crt32;
 	struct ica_rsa_modexpo_crt crt64;
+	struct zcrypt_track tr;
 	long rc;
 
+	memset(&tr, 0, sizeof(tr));
 	if (copy_from_user(&crt32, ucrt32, sizeof(crt32)))
 		return -EFAULT;
 	crt64.inputdata = compat_ptr(crt32.inputdata);
@@ -1559,13 +1803,19 @@
 	crt64.nq_prime = compat_ptr(crt32.nq_prime);
 	crt64.u_mult_inv = compat_ptr(crt32.u_mult_inv);
 	do {
-		rc = zcrypt_rsa_crt(perms, &crt64);
-	} while (rc == -EAGAIN);
+		rc = zcrypt_rsa_crt(perms, &tr, &crt64);
+		if (rc == -EAGAIN)
+			tr.again_counter++;
+	} while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX);
 	/* on failure: retry once again after a requested rescan */
 	if ((rc == -ENODEV) && (zcrypt_process_rescan()))
 		do {
-			rc = zcrypt_rsa_crt(perms, &crt64);
-		} while (rc == -EAGAIN);
+			rc = zcrypt_rsa_crt(perms, &tr, &crt64);
+			if (rc == -EAGAIN)
+				tr.again_counter++;
+		} while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX);
+	if (rc == -EAGAIN && tr.again_counter >= TRACK_AGAIN_MAX)
+		rc = -EIO;
 	if (rc)
 		return rc;
 	return put_user(crt64.outputdatalength,
@@ -1597,9 +1847,11 @@
 {
 	struct compat_ica_xcRB __user *uxcRB32 = compat_ptr(arg);
 	struct compat_ica_xcRB xcRB32;
+	struct zcrypt_track tr;
 	struct ica_xcRB xcRB64;
 	long rc;
 
+	memset(&tr, 0, sizeof(tr));
 	if (copy_from_user(&xcRB32, uxcRB32, sizeof(xcRB32)))
 		return -EFAULT;
 	xcRB64.agent_ID = xcRB32.agent_ID;
@@ -1623,13 +1875,19 @@
 	xcRB64.priority_window = xcRB32.priority_window;
 	xcRB64.status = xcRB32.status;
 	do {
-		rc = _zcrypt_send_cprb(perms, &xcRB64);
-	} while (rc == -EAGAIN);
+		rc = _zcrypt_send_cprb(true, perms, &tr, &xcRB64);
+		if (rc == -EAGAIN)
+			tr.again_counter++;
+	} while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX);
 	/* on failure: retry once again after a requested rescan */
 	if ((rc == -ENODEV) && (zcrypt_process_rescan()))
 		do {
-			rc = _zcrypt_send_cprb(perms, &xcRB64);
-		} while (rc == -EAGAIN);
+			rc = _zcrypt_send_cprb(true, perms, &tr, &xcRB64);
+			if (rc == -EAGAIN)
+				tr.again_counter++;
+		} while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX);
+	if (rc == -EAGAIN && tr.again_counter >= TRACK_AGAIN_MAX)
+		rc = -EIO;
 	xcRB32.reply_control_blk_length = xcRB64.reply_control_blk_length;
 	xcRB32.reply_data_length = xcRB64.reply_data_length;
 	xcRB32.status = xcRB64.status;
@@ -1885,6 +2143,7 @@
 	zcrypt_msgtype6_exit();
 	zcrypt_msgtype50_exit();
 	zcrypt_ccamisc_exit();
+	zcrypt_ep11misc_exit();
 	zcrypt_debug_exit();
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/crypto/zcrypt_api.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/crypto/zcrypt_api.h
@@ -55,13 +55,30 @@
 
 struct zcrypt_queue;
 
+/* struct to hold tracking information for a userspace request/response */
+struct zcrypt_track {
+	int again_counter;		/* retry attempts counter */
+	int last_qid;			/* last qid used */
+	int last_rc;			/* last return code */
+#ifdef CONFIG_ZCRYPT_DEBUG
+	struct ap_fi fi;		/* failure injection cmd */
+#endif
+};
+
+/* defines related to message tracking */
+#define TRACK_AGAIN_MAX 10
+#define TRACK_AGAIN_CARD_WEIGHT_PENALTY  1000
+#define TRACK_AGAIN_QUEUE_WEIGHT_PENALTY 10000
+
 struct zcrypt_ops {
-	long (*rsa_modexpo)(struct zcrypt_queue *, struct ica_rsa_modexpo *);
+	long (*rsa_modexpo)(struct zcrypt_queue *, struct ica_rsa_modexpo *,
+			    struct ap_message *);
 	long (*rsa_modexpo_crt)(struct zcrypt_queue *,
-				struct ica_rsa_modexpo_crt *);
-	long (*send_cprb)(struct zcrypt_queue *, struct ica_xcRB *,
+				struct ica_rsa_modexpo_crt *,
+				struct ap_message *);
+	long (*send_cprb)(bool userspace, struct zcrypt_queue *, struct ica_xcRB *,
 			  struct ap_message *);
-	long (*send_ep11_cprb)(struct zcrypt_queue *, struct ep11_urb *,
+	long (*send_ep11_cprb)(bool userspace, struct zcrypt_queue *, struct ep11_urb *,
 			       struct ap_message *);
 	long (*rng)(struct zcrypt_queue *, char *, struct ap_message *);
 	struct list_head list;		/* zcrypt ops list. */
@@ -82,7 +99,7 @@
 	int min_mod_size;		/* Min number of bits. */
 	int max_mod_size;		/* Max number of bits. */
 	int max_exp_bit_length;
-	int speed_rating[NUM_OPS];	/* Speed idx of crypto ops. */
+	const int *speed_rating;	/* Speed idx of crypto ops. */
 	atomic_t load;			/* Utilization of the crypto device */
 
 	int request_count;		/* # current requests. */
@@ -140,8 +157,31 @@
 int zcrypt_api_init(void);
 void zcrypt_api_exit(void);
 long zcrypt_send_cprb(struct ica_xcRB *xcRB);
+long zcrypt_send_ep11_cprb(struct ep11_urb *urb);
 void zcrypt_device_status_mask_ext(struct zcrypt_device_status_ext *devstatus);
 int zcrypt_device_status_ext(int card, int queue,
 			     struct zcrypt_device_status_ext *devstatus);
 
+static inline unsigned long z_copy_from_user(bool userspace,
+					     void *to,
+					     const void __user *from,
+					     unsigned long n)
+{
+	if (likely(userspace))
+		return copy_from_user(to, from, n);
+	memcpy(to, (void __force *) from, n);
+	return 0;
+}
+
+static inline unsigned long z_copy_to_user(bool userspace,
+					   void __user *to,
+					   const void *from,
+					   unsigned long n)
+{
+	if (likely(userspace))
+		return copy_to_user(to, from, n);
+	memcpy((void __force *) to, from, n);
+	return 0;
+}
+
 #endif /* _ZCRYPT_API_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/crypto/zcrypt_card.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/crypto/zcrypt_card.c
@@ -41,7 +41,7 @@
 {
 	struct zcrypt_card *zc = to_ap_card(dev)->private;
 
-	return snprintf(buf, PAGE_SIZE, "%s\n", zc->type_string);
+	return scnprintf(buf, PAGE_SIZE, "%s\n", zc->type_string);
 }
 
 static DEVICE_ATTR_RO(type);
@@ -50,22 +50,28 @@
 			   struct device_attribute *attr,
 			   char *buf)
 {
-	struct zcrypt_card *zc = to_ap_card(dev)->private;
+	struct ap_card *ac = to_ap_card(dev);
+	struct zcrypt_card *zc = ac->private;
+	int online = ac->config && zc->online ? 1 : 0;
 
-	return snprintf(buf, PAGE_SIZE, "%d\n", zc->online);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", online);
 }
 
 static ssize_t online_store(struct device *dev,
 			    struct device_attribute *attr,
 			    const char *buf, size_t count)
 {
-	struct zcrypt_card *zc = to_ap_card(dev)->private;
+	struct ap_card *ac = to_ap_card(dev);
+	struct zcrypt_card *zc = ac->private;
 	struct zcrypt_queue *zq;
 	int online, id;
 
 	if (sscanf(buf, "%d\n", &online) != 1 || online < 0 || online > 1)
 		return -EINVAL;
 
+	if (online && !ac->config)
+		return -ENODEV;
+
 	zc->online = online;
 	id = zc->card->id;
 
@@ -86,7 +92,7 @@
 {
 	struct zcrypt_card *zc = to_ap_card(dev)->private;
 
-	return snprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&zc->load));
+	return scnprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&zc->load));
 }
 
 static DEVICE_ATTR_RO(load);
@@ -151,11 +157,6 @@
 {
 	int rc;
 
-	rc = sysfs_create_group(&zc->card->ap_dev.device.kobj,
-				&zcrypt_card_attr_group);
-	if (rc)
-		return rc;
-
 	spin_lock(&zcrypt_list_lock);
 	list_add_tail(&zc->list, &zcrypt_card_list);
 	spin_unlock(&zcrypt_list_lock);
@@ -164,6 +165,14 @@
 
 	ZCRYPT_DBF(DBF_INFO, "card=%02x register online=1\n", zc->card->id);
 
+	rc = sysfs_create_group(&zc->card->ap_dev.device.kobj,
+				&zcrypt_card_attr_group);
+	if (rc) {
+		spin_lock(&zcrypt_list_lock);
+		list_del_init(&zc->list);
+		spin_unlock(&zcrypt_list_lock);
+	}
+
 	return rc;
 }
 EXPORT_SYMBOL(zcrypt_card_register);
@@ -183,5 +192,6 @@
 	spin_unlock(&zcrypt_list_lock);
 	sysfs_remove_group(&zc->card->ap_dev.device.kobj,
 			   &zcrypt_card_attr_group);
+	zcrypt_card_put(zc);
 }
 EXPORT_SYMBOL(zcrypt_card_unregister);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/crypto/zcrypt_ccamisc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/crypto/zcrypt_ccamisc.c
@@ -205,9 +205,9 @@
 	preqcblk->rpl_msgbl = cprbplusparamblen;
 	if (paramblen) {
 		preqcblk->req_parmb =
-			((u8 *) preqcblk) + sizeof(struct CPRBX);
+			((u8 __user *) preqcblk) + sizeof(struct CPRBX);
 		preqcblk->rpl_parmb =
-			((u8 *) prepcblk) + sizeof(struct CPRBX);
+			((u8 __user *) prepcblk) + sizeof(struct CPRBX);
 	}
 
 	*pcprbmem = cprbmem;
@@ -249,24 +249,6 @@
 }
 
 /*
- * Helper function which calls zcrypt_send_cprb with
- * memory management segment adjusted to kernel space
- * so that the copy_from_user called within this
- * function do in fact copy from kernel space.
- */
-static inline int _zcrypt_send_cprb(struct ica_xcRB *xcrb)
-{
-	int rc;
-	mm_segment_t old_fs = get_fs();
-
-	set_fs(KERNEL_DS);
-	rc = zcrypt_send_cprb(xcrb);
-	set_fs(old_fs);
-
-	return rc;
-}
-
-/*
  * Generate (random) CCA AES DATA secure key.
  */
 int cca_genseckey(u16 cardnr, u16 domain,
@@ -274,7 +256,7 @@
 {
 	int i, rc, keysize;
 	int seckeysize;
-	u8 *mem;
+	u8 *mem, *ptr;
 	struct CPRBX *preqcblk, *prepcblk;
 	struct ica_xcRB xcrb;
 	struct kgreqparm {
@@ -320,7 +302,7 @@
 	preqcblk->domain = domain;
 
 	/* fill request cprb param block with KG request */
-	preqparm = (struct kgreqparm *) preqcblk->req_parmb;
+	preqparm = (struct kgreqparm __force *) preqcblk->req_parmb;
 	memcpy(preqparm->subfunc_code, "KG", 2);
 	preqparm->rule_array_len = sizeof(preqparm->rule_array_len);
 	preqparm->lv1.len = sizeof(struct lv1);
@@ -359,7 +341,7 @@
 	prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk);
 
 	/* forward xcrb with request CPRB and reply CPRB to zcrypt dd */
-	rc = _zcrypt_send_cprb(&xcrb);
+	rc = zcrypt_send_cprb(&xcrb);
 	if (rc) {
 		DEBUG_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, errno %d\n",
 			  __func__, (int) cardnr, (int) domain, rc);
@@ -377,8 +359,9 @@
 	}
 
 	/* process response cprb param block */
-	prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX);
-	prepparm = (struct kgrepparm *) prepcblk->rpl_parmb;
+	ptr =  ((u8 *) prepcblk) + sizeof(struct CPRBX);
+	prepcblk->rpl_parmb = (u8 __user *) ptr;
+	prepparm = (struct kgrepparm *) ptr;
 
 	/* check length of the returned secure key token */
 	seckeysize = prepparm->lv3.keyblock.toklen
@@ -415,7 +398,7 @@
 		   const u8 *clrkey, u8 seckey[SECKEYBLOBSIZE])
 {
 	int rc, keysize, seckeysize;
-	u8 *mem;
+	u8 *mem, *ptr;
 	struct CPRBX *preqcblk, *prepcblk;
 	struct ica_xcRB xcrb;
 	struct cmreqparm {
@@ -460,7 +443,7 @@
 	preqcblk->domain = domain;
 
 	/* fill request cprb param block with CM request */
-	preqparm = (struct cmreqparm *) preqcblk->req_parmb;
+	preqparm = (struct cmreqparm __force *) preqcblk->req_parmb;
 	memcpy(preqparm->subfunc_code, "CM", 2);
 	memcpy(preqparm->rule_array, "AES     ", 8);
 	preqparm->rule_array_len =
@@ -496,7 +479,7 @@
 	prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk);
 
 	/* forward xcrb with request CPRB and reply CPRB to zcrypt dd */
-	rc = _zcrypt_send_cprb(&xcrb);
+	rc = zcrypt_send_cprb(&xcrb);
 	if (rc) {
 		DEBUG_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n",
 			  __func__, (int) cardnr, (int) domain, rc);
@@ -514,8 +497,9 @@
 	}
 
 	/* process response cprb param block */
-	prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX);
-	prepparm = (struct cmrepparm *) prepcblk->rpl_parmb;
+	ptr = ((u8 *) prepcblk) + sizeof(struct CPRBX);
+	prepcblk->rpl_parmb = (u8 __user *) ptr;
+	prepparm = (struct cmrepparm *) ptr;
 
 	/* check length of the returned secure key token */
 	seckeysize = prepparm->lv3.keyblock.toklen
@@ -554,7 +538,7 @@
 		    u8 *protkey, u32 *protkeylen, u32 *protkeytype)
 {
 	int rc;
-	u8 *mem;
+	u8 *mem, *ptr;
 	struct CPRBX *preqcblk, *prepcblk;
 	struct ica_xcRB xcrb;
 	struct uskreqparm {
@@ -592,7 +576,7 @@
 				u8  pad2[1];
 				u8  vptype;
 				u8  vp[32];  /* verification pattern */
-			} keyblock;
+			} ckb;
 		} lv3;
 	} __packed * prepparm;
 
@@ -605,7 +589,7 @@
 	preqcblk->domain = domain;
 
 	/* fill request cprb param block with USK request */
-	preqparm = (struct uskreqparm *) preqcblk->req_parmb;
+	preqparm = (struct uskreqparm __force *) preqcblk->req_parmb;
 	memcpy(preqparm->subfunc_code, "US", 2);
 	preqparm->rule_array_len = sizeof(preqparm->rule_array_len);
 	preqparm->lv1.len = sizeof(struct lv1);
@@ -622,7 +606,7 @@
 	prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk);
 
 	/* forward xcrb with request CPRB and reply CPRB to zcrypt dd */
-	rc = _zcrypt_send_cprb(&xcrb);
+	rc = zcrypt_send_cprb(&xcrb);
 	if (rc) {
 		DEBUG_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n",
 			  __func__, (int) cardnr, (int) domain, rc);
@@ -646,19 +630,21 @@
 	}
 
 	/* process response cprb param block */
-	prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX);
-	prepparm = (struct uskrepparm *) prepcblk->rpl_parmb;
+	ptr = ((u8 *) prepcblk) + sizeof(struct CPRBX);
+	prepcblk->rpl_parmb = (u8 __user *) ptr;
+	prepparm = (struct uskrepparm *) ptr;
 
 	/* check the returned keyblock */
-	if (prepparm->lv3.keyblock.version != 0x01) {
-		DEBUG_ERR("%s reply param keyblock version mismatch 0x%02x != 0x01\n",
-			  __func__, (int) prepparm->lv3.keyblock.version);
+	if (prepparm->lv3.ckb.version != 0x01 &&
+	    prepparm->lv3.ckb.version != 0x02) {
+		DEBUG_ERR("%s reply param keyblock version mismatch 0x%02x\n",
+			  __func__, (int) prepparm->lv3.ckb.version);
 		rc = -EIO;
 		goto out;
 	}
 
 	/* copy the tanslated protected key */
-	switch (prepparm->lv3.keyblock.len) {
+	switch (prepparm->lv3.ckb.len) {
 	case 16+32:
 		/* AES 128 protected key */
 		if (protkeytype)
@@ -676,13 +662,13 @@
 		break;
 	default:
 		DEBUG_ERR("%s unknown/unsupported keylen %d\n",
-			  __func__, prepparm->lv3.keyblock.len);
+			  __func__, prepparm->lv3.ckb.len);
 		rc = -EIO;
 		goto out;
 	}
-	memcpy(protkey, prepparm->lv3.keyblock.key, prepparm->lv3.keyblock.len);
+	memcpy(protkey, prepparm->lv3.ckb.key, prepparm->lv3.ckb.len);
 	if (protkeylen)
-		*protkeylen = prepparm->lv3.keyblock.len;
+		*protkeylen = prepparm->lv3.ckb.len;
 
 out:
 	free_cprbmem(mem, PARMBSIZE, 0);
@@ -713,7 +699,7 @@
 		     u8 *keybuf, size_t *keybufsize)
 {
 	int rc;
-	u8 *mem;
+	u8 *mem, *ptr;
 	struct CPRBX *preqcblk, *prepcblk;
 	struct ica_xcRB xcrb;
 	struct gkreqparm {
@@ -795,7 +781,7 @@
 	preqcblk->req_parml = sizeof(struct gkreqparm);
 
 	/* prepare request param block with GK request */
-	preqparm = (struct gkreqparm *) preqcblk->req_parmb;
+	preqparm = (struct gkreqparm __force *) preqcblk->req_parmb;
 	memcpy(preqparm->subfunc_code, "GK", 2);
 	preqparm->rule_array_len =  sizeof(uint16_t) + 2 * 8;
 	memcpy(preqparm->rule_array, "AES     OP      ", 2*8);
@@ -846,7 +832,7 @@
 	prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk);
 
 	/* forward xcrb with request CPRB and reply CPRB to zcrypt dd */
-	rc = _zcrypt_send_cprb(&xcrb);
+	rc = zcrypt_send_cprb(&xcrb);
 	if (rc) {
 		DEBUG_ERR(
 			"%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n",
@@ -866,8 +852,9 @@
 	}
 
 	/* process response cprb param block */
-	prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX);
-	prepparm = (struct gkrepparm *) prepcblk->rpl_parmb;
+	ptr = ((u8 *) prepcblk) + sizeof(struct CPRBX);
+	prepcblk->rpl_parmb = (u8 __user *) ptr;
+	prepparm = (struct gkrepparm *) ptr;
 
 	/* do some plausibility checks on the key block */
 	if (prepparm->kb.len < 120 + 5 * sizeof(uint16_t) ||
@@ -916,7 +903,7 @@
 			   int *key_token_size)
 {
 	int rc, n;
-	u8 *mem;
+	u8 *mem, *ptr;
 	struct CPRBX *preqcblk, *prepcblk;
 	struct ica_xcRB xcrb;
 	struct rule_array_block {
@@ -973,7 +960,7 @@
 	preqcblk->req_parml = 0;
 
 	/* prepare request param block with IP request */
-	preq_ra_block = (struct rule_array_block *) preqcblk->req_parmb;
+	preq_ra_block = (struct rule_array_block __force *) preqcblk->req_parmb;
 	memcpy(preq_ra_block->subfunc_code, "IP", 2);
 	preq_ra_block->rule_array_len =  sizeof(uint16_t) + 2 * 8;
 	memcpy(preq_ra_block->rule_array, rule_array_1, 8);
@@ -986,7 +973,7 @@
 	}
 
 	/* prepare vud block */
-	preq_vud_block = (struct vud_block *)
+	preq_vud_block = (struct vud_block __force *)
 		(preqcblk->req_parmb + preqcblk->req_parml);
 	n = complete ? 0 : (clr_key_bit_size + 7) / 8;
 	preq_vud_block->len = sizeof(struct vud_block) + n;
@@ -1000,7 +987,7 @@
 	preqcblk->req_parml += preq_vud_block->len;
 
 	/* prepare key block */
-	preq_key_block = (struct key_block *)
+	preq_key_block = (struct key_block __force *)
 		(preqcblk->req_parmb + preqcblk->req_parml);
 	n = *key_token_size;
 	preq_key_block->len = sizeof(struct key_block) + n;
@@ -1013,7 +1000,7 @@
 	prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk);
 
 	/* forward xcrb with request CPRB and reply CPRB to zcrypt dd */
-	rc = _zcrypt_send_cprb(&xcrb);
+	rc = zcrypt_send_cprb(&xcrb);
 	if (rc) {
 		DEBUG_ERR(
 			"%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n",
@@ -1033,12 +1020,13 @@
 	}
 
 	/* process response cprb param block */
-	prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX);
-	prepparm = (struct iprepparm *) prepcblk->rpl_parmb;
+	ptr = ((u8 *) prepcblk) + sizeof(struct CPRBX);
+	prepcblk->rpl_parmb = (u8 __user *) ptr;
+	prepparm = (struct iprepparm *) ptr;
 
 	/* do some plausibility checks on the key block */
-	if (prepparm->kb.len < 120 + 5 * sizeof(uint16_t) ||
-	    prepparm->kb.len > 136 + 5 * sizeof(uint16_t)) {
+	if (prepparm->kb.len < 120 + 3 * sizeof(uint16_t) ||
+	    prepparm->kb.len > 136 + 3 * sizeof(uint16_t)) {
 		DEBUG_ERR("%s reply with invalid or unknown key block\n",
 			  __func__);
 		rc = -EIO;
@@ -1150,7 +1138,7 @@
 		       u8 *protkey, u32 *protkeylen, u32 *protkeytype)
 {
 	int rc;
-	u8 *mem;
+	u8 *mem, *ptr;
 	struct CPRBX *preqcblk, *prepcblk;
 	struct ica_xcRB xcrb;
 	struct aureqparm {
@@ -1207,7 +1195,7 @@
 	preqcblk->domain = domain;
 
 	/* fill request cprb param block with AU request */
-	preqparm = (struct aureqparm *) preqcblk->req_parmb;
+	preqparm = (struct aureqparm __force *) preqcblk->req_parmb;
 	memcpy(preqparm->subfunc_code, "AU", 2);
 	preqparm->rule_array_len =
 		sizeof(preqparm->rule_array_len)
@@ -1229,7 +1217,7 @@
 	prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk);
 
 	/* forward xcrb with request CPRB and reply CPRB to zcrypt dd */
-	rc = _zcrypt_send_cprb(&xcrb);
+	rc = zcrypt_send_cprb(&xcrb);
 	if (rc) {
 		DEBUG_ERR(
 			"%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n",
@@ -1256,14 +1244,15 @@
 	}
 
 	/* process response cprb param block */
-	prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX);
-	prepparm = (struct aurepparm *) prepcblk->rpl_parmb;
+	ptr = ((u8 *) prepcblk) + sizeof(struct CPRBX);
+	prepcblk->rpl_parmb = (u8 __user *) ptr;
+	prepparm = (struct aurepparm *) ptr;
 
 	/* check the returned keyblock */
-	if (prepparm->vud.ckb.version != 0x01) {
-		DEBUG_ERR(
-			"%s reply param keyblock version mismatch 0x%02x != 0x01\n",
-			__func__, (int) prepparm->vud.ckb.version);
+	if (prepparm->vud.ckb.version != 0x01 &&
+	    prepparm->vud.ckb.version != 0x02) {
+		DEBUG_ERR("%s reply param keyblock version mismatch 0x%02x\n",
+			  __func__, (int) prepparm->vud.ckb.version);
 		rc = -EIO;
 		goto out;
 	}
@@ -1346,7 +1335,7 @@
 	preqcblk->domain = domain;
 
 	/* fill request cprb param block with FQ request */
-	preqparm = (struct fqreqparm *) preqcblk->req_parmb;
+	preqparm = (struct fqreqparm __force *) preqcblk->req_parmb;
 	memcpy(preqparm->subfunc_code, "FQ", 2);
 	memcpy(preqparm->rule_array, keyword, sizeof(preqparm->rule_array));
 	preqparm->rule_array_len =
@@ -1359,7 +1348,7 @@
 	prep_xcrb(&xcrb, cardnr, preqcblk, prepcblk);
 
 	/* forward xcrb with request CPRB and reply CPRB to zcrypt dd */
-	rc = _zcrypt_send_cprb(&xcrb);
+	rc = zcrypt_send_cprb(&xcrb);
 	if (rc) {
 		DEBUG_ERR("%s zcrypt_send_cprb (cardnr=%d domain=%d) failed, rc=%d\n",
 			  __func__, (int) cardnr, (int) domain, rc);
@@ -1377,8 +1366,9 @@
 	}
 
 	/* process response cprb param block */
-	prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX);
-	prepparm = (struct fqrepparm *) prepcblk->rpl_parmb;
+	ptr = ((u8 *) prepcblk) + sizeof(struct CPRBX);
+	prepcblk->rpl_parmb = (u8 __user *) ptr;
+	prepparm = (struct fqrepparm *) ptr;
 	ptr = prepparm->lvdata;
 
 	/* check and possibly copy reply rule array */
@@ -1516,21 +1506,38 @@
 				       rarray, &rlen, varray, &vlen);
 	if (rc == 0 && rlen >= 10*8 && vlen >= 204) {
 		memcpy(ci->serial, rarray, 8);
-		ci->new_mk_state = (char) rarray[7*8];
-		ci->cur_mk_state = (char) rarray[8*8];
-		ci->old_mk_state = (char) rarray[9*8];
-		if (ci->old_mk_state == '2')
-			memcpy(&ci->old_mkvp, varray + 172, 8);
-		if (ci->cur_mk_state == '2')
-			memcpy(&ci->cur_mkvp, varray + 184, 8);
-		if (ci->new_mk_state == '3')
-			memcpy(&ci->new_mkvp, varray + 196, 8);
-		found = 1;
+		ci->new_aes_mk_state = (char) rarray[7*8];
+		ci->cur_aes_mk_state = (char) rarray[8*8];
+		ci->old_aes_mk_state = (char) rarray[9*8];
+		if (ci->old_aes_mk_state == '2')
+			memcpy(&ci->old_aes_mkvp, varray + 172, 8);
+		if (ci->cur_aes_mk_state == '2')
+			memcpy(&ci->cur_aes_mkvp, varray + 184, 8);
+		if (ci->new_aes_mk_state == '3')
+			memcpy(&ci->new_aes_mkvp, varray + 196, 8);
+		found++;
+	}
+	if (!found)
+		goto out;
+	rlen = vlen = PAGE_SIZE/2;
+	rc = cca_query_crypto_facility(cardnr, domain, "STATICSB",
+				       rarray, &rlen, varray, &vlen);
+	if (rc == 0 && rlen >= 10*8 && vlen >= 240) {
+		ci->new_apka_mk_state = (char) rarray[7*8];
+		ci->cur_apka_mk_state = (char) rarray[8*8];
+		ci->old_apka_mk_state = (char) rarray[9*8];
+		if (ci->old_apka_mk_state == '2')
+			memcpy(&ci->old_apka_mkvp, varray + 208, 8);
+		if (ci->cur_apka_mk_state == '2')
+			memcpy(&ci->cur_apka_mkvp, varray + 220, 8);
+		if (ci->new_apka_mk_state == '3')
+			memcpy(&ci->new_apka_mkvp, varray + 232, 8);
+		found++;
 	}
 
+out:
 	free_page((unsigned long) pg);
-
-	return found ? 0 : -ENOENT;
+	return found == 2 ? 0 : -ENOENT;
 }
 
 /*
@@ -1568,9 +1575,9 @@
 		return -EINVAL;
 
 	/* fetch status of all crypto cards */
-	device_status = kmalloc_array(MAX_ZDEV_ENTRIES_EXT,
-				      sizeof(struct zcrypt_device_status_ext),
-				      GFP_KERNEL);
+	device_status = kvmalloc_array(MAX_ZDEV_ENTRIES_EXT,
+				       sizeof(struct zcrypt_device_status_ext),
+				       GFP_KERNEL);
 	if (!device_status)
 		return -ENOMEM;
 	zcrypt_device_status_mask_ext(device_status);
@@ -1584,16 +1591,16 @@
 			/* enabled CCA card, check current mkvp from cache */
 			if (cca_info_cache_fetch(card, dom, &ci) == 0 &&
 			    ci.hwtype >= minhwtype &&
-			    ci.cur_mk_state == '2' &&
-			    ci.cur_mkvp == mkvp) {
+			    ci.cur_aes_mk_state == '2' &&
+			    ci.cur_aes_mkvp == mkvp) {
 				if (!verify)
 					break;
 				/* verify: refresh card info */
 				if (fetch_cca_info(card, dom, &ci) == 0) {
 					cca_info_cache_update(card, dom, &ci);
 					if (ci.hwtype >= minhwtype &&
-					    ci.cur_mk_state == '2' &&
-					    ci.cur_mkvp == mkvp)
+					    ci.cur_aes_mk_state == '2' &&
+					    ci.cur_aes_mkvp == mkvp)
 						break;
 				}
 			}
@@ -1615,12 +1622,12 @@
 			if (fetch_cca_info(card, dom, &ci) == 0) {
 				cca_info_cache_update(card, dom, &ci);
 				if (ci.hwtype >= minhwtype &&
-				    ci.cur_mk_state == '2' &&
-				    ci.cur_mkvp == mkvp)
+				    ci.cur_aes_mk_state == '2' &&
+				    ci.cur_aes_mkvp == mkvp)
 					break;
 				if (ci.hwtype >= minhwtype &&
-				    ci.old_mk_state == '2' &&
-				    ci.old_mkvp == mkvp &&
+				    ci.old_aes_mk_state == '2' &&
+				    ci.old_aes_mkvp == mkvp &&
 				    oi < 0)
 					oi = i;
 			}
@@ -1640,7 +1647,7 @@
 	} else
 		rc = -ENODEV;
 
-	kfree(device_status);
+	kvfree(device_status);
 	return rc;
 }
 
@@ -1674,87 +1681,92 @@
 EXPORT_SYMBOL(cca_findcard);
 
 int cca_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
-		  int minhwtype, u64 cur_mkvp, u64 old_mkvp, int verify)
+		  int minhwtype, int mktype, u64 cur_mkvp, u64 old_mkvp,
+		  int verify)
 {
 	struct zcrypt_device_status_ext *device_status;
-	int i, n, card, dom, curmatch, oldmatch, rc = 0;
+	u32 *_apqns = NULL, _nr_apqns = 0;
+	int i, card, dom, curmatch, oldmatch, rc = 0;
 	struct cca_info ci;
 
-	*apqns = NULL;
-	*nr_apqns = 0;
-
 	/* fetch status of all crypto cards */
-	device_status = kmalloc_array(MAX_ZDEV_ENTRIES_EXT,
-				      sizeof(struct zcrypt_device_status_ext),
-				      GFP_KERNEL);
+	device_status = kvmalloc_array(MAX_ZDEV_ENTRIES_EXT,
+				       sizeof(struct zcrypt_device_status_ext),
+				       GFP_KERNEL);
 	if (!device_status)
 		return -ENOMEM;
 	zcrypt_device_status_mask_ext(device_status);
 
-	/* loop two times: first gather eligible apqns, then store them */
-	while (1) {
-		n = 0;
-		/* walk through all the crypto cards */
-		for (i = 0; i < MAX_ZDEV_ENTRIES_EXT; i++) {
-			card = AP_QID_CARD(device_status[i].qid);
-			dom = AP_QID_QUEUE(device_status[i].qid);
-			/* check online state */
-			if (!device_status[i].online)
-				continue;
-			/* check for cca functions */
-			if (!(device_status[i].functions & 0x04))
-				continue;
-			/* check cardnr */
-			if (cardnr != 0xFFFF && card != cardnr)
-				continue;
-			/* check domain */
-			if (domain != 0xFFFF && dom != domain)
-				continue;
-			/* get cca info on this apqn */
-			if (cca_get_info(card, dom, &ci, verify))
-				continue;
-			/* current master key needs to be valid */
-			if (ci.cur_mk_state != '2')
-				continue;
-			/* check min hardware type */
-			if (minhwtype > 0 && minhwtype > ci.hwtype)
-				continue;
-			if (cur_mkvp || old_mkvp) {
-				/* check mkvps */
-				curmatch = oldmatch = 0;
-				if (cur_mkvp && cur_mkvp == ci.cur_mkvp)
+	/* allocate 1k space for up to 256 apqns */
+	_apqns = kmalloc_array(256, sizeof(u32), GFP_KERNEL);
+	if (!_apqns) {
+		kvfree(device_status);
+		return -ENOMEM;
+	}
+
+	/* walk through all the crypto apqnss */
+	for (i = 0; i < MAX_ZDEV_ENTRIES_EXT; i++) {
+		card = AP_QID_CARD(device_status[i].qid);
+		dom = AP_QID_QUEUE(device_status[i].qid);
+		/* check online state */
+		if (!device_status[i].online)
+			continue;
+		/* check for cca functions */
+		if (!(device_status[i].functions & 0x04))
+			continue;
+		/* check cardnr */
+		if (cardnr != 0xFFFF && card != cardnr)
+			continue;
+		/* check domain */
+		if (domain != 0xFFFF && dom != domain)
+			continue;
+		/* get cca info on this apqn */
+		if (cca_get_info(card, dom, &ci, verify))
+			continue;
+		/* current master key needs to be valid */
+		if (mktype == AES_MK_SET && ci.cur_aes_mk_state != '2')
+			continue;
+		if (mktype == APKA_MK_SET && ci.cur_apka_mk_state != '2')
+			continue;
+		/* check min hardware type */
+		if (minhwtype > 0 && minhwtype > ci.hwtype)
+			continue;
+		if (cur_mkvp || old_mkvp) {
+			/* check mkvps */
+			curmatch = oldmatch = 0;
+			if (mktype == AES_MK_SET) {
+				if (cur_mkvp && cur_mkvp == ci.cur_aes_mkvp)
+					curmatch = 1;
+				if (old_mkvp && ci.old_aes_mk_state == '2' &&
+				    old_mkvp == ci.old_aes_mkvp)
+					oldmatch = 1;
+			} else {
+				if (cur_mkvp && cur_mkvp == ci.cur_apka_mkvp)
 					curmatch = 1;
-				if (old_mkvp && ci.old_mk_state == '2' &&
-				    old_mkvp == ci.old_mkvp)
+				if (old_mkvp && ci.old_apka_mk_state == '2' &&
+				    old_mkvp == ci.old_apka_mkvp)
 					oldmatch = 1;
-				if ((cur_mkvp || old_mkvp) &&
-				    (curmatch + oldmatch < 1))
-					continue;
 			}
-			/* apqn passed all filtering criterons */
-			if (*apqns && n < *nr_apqns)
-				(*apqns)[n] = (((u16)card) << 16) | ((u16) dom);
-			n++;
-		}
-		/* loop 2nd time: array has been filled */
-		if (*apqns)
-			break;
-		/* loop 1st time: have # of eligible apqns in n */
-		if (!n) {
-			rc = -ENODEV; /* no eligible apqns found */
-			break;
-		}
-		*nr_apqns = n;
-		/* allocate array to store n apqns into */
-		*apqns = kmalloc_array(n, sizeof(u32), GFP_KERNEL);
-		if (!*apqns) {
-			rc = -ENOMEM;
-			break;
+			if (curmatch + oldmatch < 1)
+				continue;
 		}
-		verify = 0;
+		/* apqn passed all filtering criterons, add to the array */
+		if (_nr_apqns < 256)
+			_apqns[_nr_apqns++] = (((u16)card) << 16) | ((u16) dom);
+	}
+
+	/* nothing found ? */
+	if (!_nr_apqns) {
+		kfree(_apqns);
+		rc = -ENODEV;
+	} else {
+		/* no re-allocation, simple return the _apqns array */
+		*apqns = _apqns;
+		*nr_apqns = _nr_apqns;
+		rc = 0;
 	}
 
-	kfree(device_status);
+	kvfree(device_status);
 	return rc;
 }
 EXPORT_SYMBOL(cca_findcard2);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/crypto/zcrypt_ccamisc.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/crypto/zcrypt_ccamisc.h
@@ -19,6 +19,7 @@
 
 /* For TOKTYPE_NON_CCA: */
 #define TOKVER_PROTECTED_KEY	0x01 /* Protected key token */
+#define TOKVER_CLEAR_KEY	0x02 /* Clear key token */
 
 /* For TOKTYPE_CCA_INTERNAL: */
 #define TOKVER_CCA_AES		0x04 /* CCA AES key token */
@@ -89,7 +90,7 @@
 	u16 kmf1;     /* key management field 1 */
 	u16 kmf2;     /* key management field 2 */
 	u16 kmf3;     /* key management field 3 */
-	u8  vdata[0]; /* variable part data follows */
+	u8  vdata[]; /* variable part data follows */
 } __packed;
 
 /* Some defines for the CCA AES cipherkeytoken kmf1 field */
@@ -185,6 +186,8 @@
  * - if verify is enabled and a cur_mkvp and/or old_mkvp
  *   value is given, then refetch the cca_info and make sure the current
  *   cur_mkvp or old_mkvp values of the apqn are used.
+ * The mktype determines which set of master keys to use:
+ *   0 = AES_MK_SET - AES MK set, 1 = APKA MK_SET - APKA MK set
  * The array of apqn entries is allocated with kmalloc and returned in *apqns;
  * the number of apqns stored into the list is returned in *nr_apqns. One apqn
  * entry is simple a 32 bit value with 16 bit cardnr and 16 bit domain nr and
@@ -193,18 +196,28 @@
  * -ENODEV is returned.
  */
 int cca_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
-		  int minhwtype, u64 cur_mkvp, u64 old_mkvp, int verify);
+		  int minhwtype, int mktype, u64 cur_mkvp, u64 old_mkvp,
+		  int verify);
+
+#define AES_MK_SET  0
+#define APKA_MK_SET 1
 
 /* struct to hold info for each CCA queue */
 struct cca_info {
-	int  hwtype;	    /* one of the defined AP_DEVICE_TYPE_* */
-	char new_mk_state;  /* '1' empty, '2' partially full, '3' full */
-	char cur_mk_state;  /* '1' invalid, '2' valid */
-	char old_mk_state;  /* '1' invalid, '2' valid */
-	u64  new_mkvp;	    /* truncated sha256 hash of new master key */
-	u64  cur_mkvp;	    /* truncated sha256 hash of current master key */
-	u64  old_mkvp;	    /* truncated sha256 hash of old master key */
-	char serial[9];     /* serial number string (8 ascii numbers + 0x00) */
+	int  hwtype;		/* one of the defined AP_DEVICE_TYPE_* */
+	char new_aes_mk_state;	/* '1' empty, '2' partially full, '3' full */
+	char cur_aes_mk_state;	/* '1' invalid, '2' valid */
+	char old_aes_mk_state;	/* '1' invalid, '2' valid */
+	char new_apka_mk_state; /* '1' empty, '2' partially full, '3' full */
+	char cur_apka_mk_state; /* '1' invalid, '2' valid */
+	char old_apka_mk_state; /* '1' invalid, '2' valid */
+	u64  new_aes_mkvp;	/* truncated sha256 of new aes master key */
+	u64  cur_aes_mkvp;	/* truncated sha256 of current aes master key */
+	u64  old_aes_mkvp;	/* truncated sha256 of old aes master key */
+	u64  new_apka_mkvp;	/* truncated sha256 of new apka master key */
+	u64  cur_apka_mkvp;	/* truncated sha256 of current apka mk */
+	u64  old_apka_mkvp;	/* truncated sha256 of old apka mk */
+	char serial[9];		/* serial number (8 ascii numbers + 0x00) */
 };
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/crypto/zcrypt_cex2a.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/crypto/zcrypt_cex2a.c
@@ -94,8 +94,7 @@
 	if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX2A) {
 		zc->min_mod_size = CEX2A_MIN_MOD_SIZE;
 		zc->max_mod_size = CEX2A_MAX_MOD_SIZE;
-		memcpy(zc->speed_rating, CEX2A_SPEED_IDX,
-		       sizeof(CEX2A_SPEED_IDX));
+		zc->speed_rating = CEX2A_SPEED_IDX;
 		zc->max_exp_bit_length = CEX2A_MAX_MOD_SIZE;
 		zc->type_string = "CEX2A";
 		zc->user_space_type = ZCRYPT_CEX2A;
@@ -108,8 +107,7 @@
 			zc->max_mod_size = CEX3A_MAX_MOD_SIZE;
 			zc->max_exp_bit_length = CEX3A_MAX_MOD_SIZE;
 		}
-		memcpy(zc->speed_rating, CEX3A_SPEED_IDX,
-		       sizeof(CEX3A_SPEED_IDX));
+		zc->speed_rating = CEX3A_SPEED_IDX;
 		zc->type_string = "CEX3A";
 		zc->user_space_type = ZCRYPT_CEX3A;
 	} else {
@@ -175,6 +173,7 @@
 	zq->queue = aq;
 	zq->online = 1;
 	atomic_set(&zq->load, 0);
+	ap_queue_init_state(aq);
 	ap_queue_init_reply(aq, &zq->reply);
 	aq->request_timeout = CEX2A_CLEANUP_TIME,
 	aq->private = zq;
@@ -203,8 +202,6 @@
 static struct ap_driver zcrypt_cex2a_queue_driver = {
 	.probe = zcrypt_cex2a_queue_probe,
 	.remove = zcrypt_cex2a_queue_remove,
-	.suspend = ap_queue_suspend,
-	.resume = ap_queue_resume,
 	.ids = zcrypt_cex2a_queue_ids,
 	.flags = AP_DRIVER_FLAG_DEFAULT,
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/crypto/zcrypt_cex2c.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/crypto/zcrypt_cex2c.c
@@ -25,6 +25,7 @@
 #include "zcrypt_msgtype6.h"
 #include "zcrypt_cex2c.h"
 #include "zcrypt_cca_key.h"
+#include "zcrypt_ccamisc.h"
 
 #define CEX2C_MIN_MOD_SIZE	 16	/*  128 bits	*/
 #define CEX2C_MAX_MOD_SIZE	256	/* 2048 bits	*/
@@ -58,6 +59,118 @@
 
 MODULE_DEVICE_TABLE(ap, zcrypt_cex2c_queue_ids);
 
+/*
+ * CCA card additional device attributes
+ */
+static ssize_t cca_serialnr_show(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	struct cca_info ci;
+	struct ap_card *ac = to_ap_card(dev);
+	struct zcrypt_card *zc = ac->private;
+
+	memset(&ci, 0, sizeof(ci));
+
+	if (ap_domain_index >= 0)
+		cca_get_info(ac->id, ap_domain_index, &ci, zc->online);
+
+	return scnprintf(buf, PAGE_SIZE, "%s\n", ci.serial);
+}
+
+static struct device_attribute dev_attr_cca_serialnr =
+	__ATTR(serialnr, 0444, cca_serialnr_show, NULL);
+
+static struct attribute *cca_card_attrs[] = {
+	&dev_attr_cca_serialnr.attr,
+	NULL,
+};
+
+static const struct attribute_group cca_card_attr_grp = {
+	.attrs = cca_card_attrs,
+};
+
+ /*
+  * CCA queue additional device attributes
+  */
+static ssize_t cca_mkvps_show(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
+{
+	int n = 0;
+	struct cca_info ci;
+	struct zcrypt_queue *zq = to_ap_queue(dev)->private;
+	static const char * const cao_state[] = { "invalid", "valid" };
+	static const char * const new_state[] = { "empty", "partial", "full" };
+
+	memset(&ci, 0, sizeof(ci));
+
+	cca_get_info(AP_QID_CARD(zq->queue->qid),
+		     AP_QID_QUEUE(zq->queue->qid),
+		     &ci, zq->online);
+
+	if (ci.new_aes_mk_state >= '1' && ci.new_aes_mk_state <= '3')
+		n = scnprintf(buf, PAGE_SIZE, "AES NEW: %s 0x%016llx\n",
+			      new_state[ci.new_aes_mk_state - '1'],
+			      ci.new_aes_mkvp);
+	else
+		n = scnprintf(buf, PAGE_SIZE, "AES NEW: - -\n");
+
+	if (ci.cur_aes_mk_state >= '1' && ci.cur_aes_mk_state <= '2')
+		n += scnprintf(buf + n, PAGE_SIZE - n,
+			       "AES CUR: %s 0x%016llx\n",
+			       cao_state[ci.cur_aes_mk_state - '1'],
+			       ci.cur_aes_mkvp);
+	else
+		n += scnprintf(buf + n, PAGE_SIZE - n, "AES CUR: - -\n");
+
+	if (ci.old_aes_mk_state >= '1' && ci.old_aes_mk_state <= '2')
+		n += scnprintf(buf + n, PAGE_SIZE - n,
+			       "AES OLD: %s 0x%016llx\n",
+			       cao_state[ci.old_aes_mk_state - '1'],
+			       ci.old_aes_mkvp);
+	else
+		n += scnprintf(buf + n, PAGE_SIZE - n, "AES OLD: - -\n");
+
+	if (ci.new_apka_mk_state >= '1' && ci.new_apka_mk_state <= '3')
+		n += scnprintf(buf + n, PAGE_SIZE - n,
+			       "APKA NEW: %s 0x%016llx\n",
+			       new_state[ci.new_apka_mk_state - '1'],
+			       ci.new_apka_mkvp);
+	else
+		n += scnprintf(buf + n, PAGE_SIZE - n, "APKA NEW: - -\n");
+
+	if (ci.cur_apka_mk_state >= '1' && ci.cur_apka_mk_state <= '2')
+		n += scnprintf(buf + n, PAGE_SIZE - n,
+			       "APKA CUR: %s 0x%016llx\n",
+			       cao_state[ci.cur_apka_mk_state - '1'],
+			       ci.cur_apka_mkvp);
+	else
+		n += scnprintf(buf + n, PAGE_SIZE - n, "APKA CUR: - -\n");
+
+	if (ci.old_apka_mk_state >= '1' && ci.old_apka_mk_state <= '2')
+		n += scnprintf(buf + n, PAGE_SIZE - n,
+			       "APKA OLD: %s 0x%016llx\n",
+			       cao_state[ci.old_apka_mk_state - '1'],
+			       ci.old_apka_mkvp);
+	else
+		n += scnprintf(buf + n, PAGE_SIZE - n, "APKA OLD: - -\n");
+
+	return n;
+}
+
+static struct device_attribute dev_attr_cca_mkvps =
+	__ATTR(mkvps, 0444, cca_mkvps_show, NULL);
+
+static struct attribute *cca_queue_attrs[] = {
+	&dev_attr_cca_mkvps.attr,
+	NULL,
+};
+
+static const struct attribute_group cca_queue_attr_grp = {
+	.attrs = cca_queue_attrs,
+};
+
 /**
  * Large random number detection function. Its sends a message to a CEX2C/CEX3C
  * card to find out if large random numbers are supported.
@@ -87,24 +200,23 @@
 	int rc, i;
 
 	ap_init_message(&ap_msg);
-	ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
-	if (!ap_msg.message)
+	ap_msg.msg = (void *) get_zeroed_page(GFP_KERNEL);
+	if (!ap_msg.msg)
 		return -ENOMEM;
 
 	rng_type6CPRB_msgX(&ap_msg, 4, &domain);
 
-	msg = ap_msg.message;
+	msg = ap_msg.msg;
 	msg->cprbx.domain = AP_QID_QUEUE(aq->qid);
 
-	rc = ap_send(aq->qid, 0x0102030405060708ULL, ap_msg.message,
-		     ap_msg.length);
+	rc = ap_send(aq->qid, 0x0102030405060708ULL, ap_msg.msg, ap_msg.len);
 	if (rc)
 		goto out_free;
 
 	/* Wait for the test message to complete. */
 	for (i = 0; i < 2 * HZ; i++) {
 		msleep(1000 / HZ);
-		rc = ap_recv(aq->qid, &psmid, ap_msg.message, 4096);
+		rc = ap_recv(aq->qid, &psmid, ap_msg.msg, 4096);
 		if (rc == 0 && psmid == 0x0102030405060708ULL)
 			break;
 	}
@@ -115,13 +227,13 @@
 		goto out_free;
 	}
 
-	reply = ap_msg.message;
+	reply = ap_msg.msg;
 	if (reply->cprbx.ccp_rtcode == 0 && reply->cprbx.ccp_rscode == 0)
 		rc = 1;
 	else
 		rc = 0;
 out_free:
-	free_page((unsigned long) ap_msg.message);
+	free_page((unsigned long) ap_msg.msg);
 	return rc;
 }
 
@@ -154,8 +266,7 @@
 	case AP_DEVICE_TYPE_CEX2C:
 		zc->user_space_type = ZCRYPT_CEX2C;
 		zc->type_string = "CEX2C";
-		memcpy(zc->speed_rating, CEX2C_SPEED_IDX,
-		       sizeof(CEX2C_SPEED_IDX));
+		zc->speed_rating = CEX2C_SPEED_IDX;
 		zc->min_mod_size = CEX2C_MIN_MOD_SIZE;
 		zc->max_mod_size = CEX2C_MAX_MOD_SIZE;
 		zc->max_exp_bit_length = CEX2C_MAX_MOD_SIZE;
@@ -163,8 +274,7 @@
 	case AP_DEVICE_TYPE_CEX3C:
 		zc->user_space_type = ZCRYPT_CEX3C;
 		zc->type_string = "CEX3C";
-		memcpy(zc->speed_rating, CEX3C_SPEED_IDX,
-		       sizeof(CEX3C_SPEED_IDX));
+		zc->speed_rating = CEX3C_SPEED_IDX;
 		zc->min_mod_size = CEX3C_MIN_MOD_SIZE;
 		zc->max_mod_size = CEX3C_MAX_MOD_SIZE;
 		zc->max_exp_bit_length = CEX3C_MAX_MOD_SIZE;
@@ -179,6 +289,17 @@
 	if (rc) {
 		ac->private = NULL;
 		zcrypt_card_free(zc);
+		return rc;
+	}
+
+	if (ap_test_bit(&ac->functions, AP_FUNC_COPRO)) {
+		rc = sysfs_create_group(&ap_dev->device.kobj,
+					&cca_card_attr_grp);
+		if (rc) {
+			zcrypt_card_unregister(zc);
+			ac->private = NULL;
+			zcrypt_card_free(zc);
+		}
 	}
 
 	return rc;
@@ -190,8 +311,11 @@
  */
 static void zcrypt_cex2c_card_remove(struct ap_device *ap_dev)
 {
+	struct ap_card *ac = to_ap_card(&ap_dev->device);
 	struct zcrypt_card *zc = to_ap_card(&ap_dev->device)->private;
 
+	if (ap_test_bit(&ac->functions, AP_FUNC_COPRO))
+		sysfs_remove_group(&ap_dev->device.kobj, &cca_card_attr_grp);
 	if (zc)
 		zcrypt_card_unregister(zc);
 }
@@ -220,6 +344,7 @@
 	zq->queue = aq;
 	zq->online = 1;
 	atomic_set(&zq->load, 0);
+	ap_rapq(aq->qid);
 	rc = zcrypt_cex2c_rng_supported(aq);
 	if (rc < 0) {
 		zcrypt_queue_free(zq);
@@ -231,6 +356,7 @@
 	else
 		zq->ops = zcrypt_msgtype(MSGTYPE06_NAME,
 					 MSGTYPE06_VARIANT_NORNG);
+	ap_queue_init_state(aq);
 	ap_queue_init_reply(aq, &zq->reply);
 	aq->request_timeout = CEX2C_CLEANUP_TIME;
 	aq->private = zq;
@@ -238,7 +364,19 @@
 	if (rc) {
 		aq->private = NULL;
 		zcrypt_queue_free(zq);
+		return rc;
 	}
+
+	if (ap_test_bit(&aq->card->functions, AP_FUNC_COPRO)) {
+		rc = sysfs_create_group(&ap_dev->device.kobj,
+					&cca_queue_attr_grp);
+		if (rc) {
+			zcrypt_queue_unregister(zq);
+			aq->private = NULL;
+			zcrypt_queue_free(zq);
+		}
+	}
+
 	return rc;
 }
 
@@ -251,6 +389,8 @@
 	struct ap_queue *aq = to_ap_queue(&ap_dev->device);
 	struct zcrypt_queue *zq = aq->private;
 
+	if (ap_test_bit(&aq->card->functions, AP_FUNC_COPRO))
+		sysfs_remove_group(&ap_dev->device.kobj, &cca_queue_attr_grp);
 	if (zq)
 		zcrypt_queue_unregister(zq);
 }
@@ -258,8 +398,6 @@
 static struct ap_driver zcrypt_cex2c_queue_driver = {
 	.probe = zcrypt_cex2c_queue_probe,
 	.remove = zcrypt_cex2c_queue_remove,
-	.suspend = ap_queue_suspend,
-	.resume = ap_queue_resume,
 	.ids = zcrypt_cex2c_queue_ids,
 	.flags = AP_DRIVER_FLAG_DEFAULT,
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/crypto/zcrypt_cex4.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/crypto/zcrypt_cex4.c
@@ -19,6 +19,7 @@
 #include "zcrypt_error.h"
 #include "zcrypt_cex4.h"
 #include "zcrypt_ccamisc.h"
+#include "zcrypt_ep11misc.h"
 
 #define CEX4A_MIN_MOD_SIZE	  1	/*    8 bits	*/
 #define CEX4A_MAX_MOD_SIZE_2K	256	/* 2048 bits	*/
@@ -27,9 +28,6 @@
 #define CEX4C_MIN_MOD_SIZE	 16	/*  256 bits	*/
 #define CEX4C_MAX_MOD_SIZE	512	/* 4096 bits	*/
 
-#define CEX4A_MAX_MESSAGE_SIZE	MSGTYPE50_CRB3_MAX_MSG_SIZE
-#define CEX4C_MAX_MESSAGE_SIZE	MSGTYPE06_MAX_MSG_SIZE
-
 /* Waiting time for requests to be processed.
  * Currently there are some types of request which are not deterministic.
  * But the maximum time limit managed by the stomper code is set to 60sec.
@@ -71,11 +69,11 @@
 MODULE_DEVICE_TABLE(ap, zcrypt_cex4_queue_ids);
 
 /*
- * CCA card addditional device attributes
+ * CCA card additional device attributes
  */
-static ssize_t serialnr_show(struct device *dev,
-			     struct device_attribute *attr,
-			     char *buf)
+static ssize_t cca_serialnr_show(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
 {
 	struct cca_info ci;
 	struct ap_card *ac = to_ap_card(dev);
@@ -86,25 +84,27 @@
 	if (ap_domain_index >= 0)
 		cca_get_info(ac->id, ap_domain_index, &ci, zc->online);
 
-	return snprintf(buf, PAGE_SIZE, "%s\n", ci.serial);
+	return scnprintf(buf, PAGE_SIZE, "%s\n", ci.serial);
 }
-static DEVICE_ATTR_RO(serialnr);
+
+static struct device_attribute dev_attr_cca_serialnr =
+	__ATTR(serialnr, 0444, cca_serialnr_show, NULL);
 
 static struct attribute *cca_card_attrs[] = {
-	&dev_attr_serialnr.attr,
+	&dev_attr_cca_serialnr.attr,
 	NULL,
 };
 
-static const struct attribute_group cca_card_attr_group = {
+static const struct attribute_group cca_card_attr_grp = {
 	.attrs = cca_card_attrs,
 };
 
-/*
- * CCA queue addditional device attributes
- */
-static ssize_t mkvps_show(struct device *dev,
-			  struct device_attribute *attr,
-			  char *buf)
+ /*
+  * CCA queue additional device attributes
+  */
+static ssize_t cca_mkvps_show(struct device *dev,
+			      struct device_attribute *attr,
+			      char *buf)
 {
 	int n = 0;
 	struct cca_info ci;
@@ -118,37 +118,282 @@
 		     AP_QID_QUEUE(zq->queue->qid),
 		     &ci, zq->online);
 
-	if (ci.new_mk_state >= '1' && ci.new_mk_state <= '3')
-		n = snprintf(buf, PAGE_SIZE, "AES NEW: %s 0x%016llx\n",
-			     new_state[ci.new_mk_state - '1'], ci.new_mkvp);
+	if (ci.new_aes_mk_state >= '1' && ci.new_aes_mk_state <= '3')
+		n = scnprintf(buf, PAGE_SIZE, "AES NEW: %s 0x%016llx\n",
+			      new_state[ci.new_aes_mk_state - '1'],
+			      ci.new_aes_mkvp);
 	else
-		n = snprintf(buf, PAGE_SIZE, "AES NEW: - -\n");
+		n = scnprintf(buf, PAGE_SIZE, "AES NEW: - -\n");
 
-	if (ci.cur_mk_state >= '1' && ci.cur_mk_state <= '2')
-		n += snprintf(buf + n, PAGE_SIZE - n, "AES CUR: %s 0x%016llx\n",
-			      cao_state[ci.cur_mk_state - '1'], ci.cur_mkvp);
+	if (ci.cur_aes_mk_state >= '1' && ci.cur_aes_mk_state <= '2')
+		n += scnprintf(buf + n, PAGE_SIZE - n,
+			       "AES CUR: %s 0x%016llx\n",
+			       cao_state[ci.cur_aes_mk_state - '1'],
+			       ci.cur_aes_mkvp);
 	else
-		n += snprintf(buf + n, PAGE_SIZE - n, "AES CUR: - -\n");
+		n += scnprintf(buf + n, PAGE_SIZE - n, "AES CUR: - -\n");
 
-	if (ci.old_mk_state >= '1' && ci.old_mk_state <= '2')
-		n += snprintf(buf + n, PAGE_SIZE - n, "AES OLD: %s 0x%016llx\n",
-			      cao_state[ci.old_mk_state - '1'], ci.old_mkvp);
+	if (ci.old_aes_mk_state >= '1' && ci.old_aes_mk_state <= '2')
+		n += scnprintf(buf + n, PAGE_SIZE - n,
+			       "AES OLD: %s 0x%016llx\n",
+			       cao_state[ci.old_aes_mk_state - '1'],
+			       ci.old_aes_mkvp);
 	else
-		n += snprintf(buf + n, PAGE_SIZE - n, "AES OLD: - -\n");
+		n += scnprintf(buf + n, PAGE_SIZE - n, "AES OLD: - -\n");
+
+	if (ci.new_apka_mk_state >= '1' && ci.new_apka_mk_state <= '3')
+		n += scnprintf(buf + n, PAGE_SIZE - n,
+			       "APKA NEW: %s 0x%016llx\n",
+			       new_state[ci.new_apka_mk_state - '1'],
+			       ci.new_apka_mkvp);
+	else
+		n += scnprintf(buf + n, PAGE_SIZE - n, "APKA NEW: - -\n");
+
+	if (ci.cur_apka_mk_state >= '1' && ci.cur_apka_mk_state <= '2')
+		n += scnprintf(buf + n, PAGE_SIZE - n,
+			       "APKA CUR: %s 0x%016llx\n",
+			       cao_state[ci.cur_apka_mk_state - '1'],
+			       ci.cur_apka_mkvp);
+	else
+		n += scnprintf(buf + n, PAGE_SIZE - n, "APKA CUR: - -\n");
+
+	if (ci.old_apka_mk_state >= '1' && ci.old_apka_mk_state <= '2')
+		n += scnprintf(buf + n, PAGE_SIZE - n,
+			       "APKA OLD: %s 0x%016llx\n",
+			       cao_state[ci.old_apka_mk_state - '1'],
+			       ci.old_apka_mkvp);
+	else
+		n += scnprintf(buf + n, PAGE_SIZE - n, "APKA OLD: - -\n");
 
 	return n;
 }
-static DEVICE_ATTR_RO(mkvps);
+
+static struct device_attribute dev_attr_cca_mkvps =
+	__ATTR(mkvps, 0444, cca_mkvps_show, NULL);
 
 static struct attribute *cca_queue_attrs[] = {
-	&dev_attr_mkvps.attr,
+	&dev_attr_cca_mkvps.attr,
 	NULL,
 };
 
-static const struct attribute_group cca_queue_attr_group = {
+static const struct attribute_group cca_queue_attr_grp = {
 	.attrs = cca_queue_attrs,
 };
 
+/*
+ * EP11 card additional device attributes
+ */
+static ssize_t ep11_api_ordinalnr_show(struct device *dev,
+				       struct device_attribute *attr,
+				       char *buf)
+{
+	struct ep11_card_info ci;
+	struct ap_card *ac = to_ap_card(dev);
+	struct zcrypt_card *zc = ac->private;
+
+	memset(&ci, 0, sizeof(ci));
+
+	ep11_get_card_info(ac->id, &ci, zc->online);
+
+	if (ci.API_ord_nr > 0)
+		return scnprintf(buf, PAGE_SIZE, "%u\n", ci.API_ord_nr);
+	else
+		return scnprintf(buf, PAGE_SIZE, "\n");
+}
+
+static struct device_attribute dev_attr_ep11_api_ordinalnr =
+	__ATTR(API_ordinalnr, 0444, ep11_api_ordinalnr_show, NULL);
+
+static ssize_t ep11_fw_version_show(struct device *dev,
+				    struct device_attribute *attr,
+				    char *buf)
+{
+	struct ep11_card_info ci;
+	struct ap_card *ac = to_ap_card(dev);
+	struct zcrypt_card *zc = ac->private;
+
+	memset(&ci, 0, sizeof(ci));
+
+	ep11_get_card_info(ac->id, &ci, zc->online);
+
+	if (ci.FW_version > 0)
+		return scnprintf(buf, PAGE_SIZE, "%d.%d\n",
+				 (int)(ci.FW_version >> 8),
+				 (int)(ci.FW_version & 0xFF));
+	else
+		return scnprintf(buf, PAGE_SIZE, "\n");
+}
+
+static struct device_attribute dev_attr_ep11_fw_version =
+	__ATTR(FW_version, 0444, ep11_fw_version_show, NULL);
+
+static ssize_t ep11_serialnr_show(struct device *dev,
+				  struct device_attribute *attr,
+				  char *buf)
+{
+	struct ep11_card_info ci;
+	struct ap_card *ac = to_ap_card(dev);
+	struct zcrypt_card *zc = ac->private;
+
+	memset(&ci, 0, sizeof(ci));
+
+	ep11_get_card_info(ac->id, &ci, zc->online);
+
+	if (ci.serial[0])
+		return scnprintf(buf, PAGE_SIZE, "%16.16s\n", ci.serial);
+	else
+		return scnprintf(buf, PAGE_SIZE, "\n");
+}
+
+static struct device_attribute dev_attr_ep11_serialnr =
+	__ATTR(serialnr, 0444, ep11_serialnr_show, NULL);
+
+static const struct {
+	int	    mode_bit;
+	const char *mode_txt;
+} ep11_op_modes[] = {
+	{ 0, "FIPS2009" },
+	{ 1, "BSI2009" },
+	{ 2, "FIPS2011" },
+	{ 3, "BSI2011" },
+	{ 6, "BSICC2017" },
+	{ 0, NULL }
+};
+
+static ssize_t ep11_card_op_modes_show(struct device *dev,
+				       struct device_attribute *attr,
+				       char *buf)
+{
+	int i, n = 0;
+	struct ep11_card_info ci;
+	struct ap_card *ac = to_ap_card(dev);
+	struct zcrypt_card *zc = ac->private;
+
+	memset(&ci, 0, sizeof(ci));
+
+	ep11_get_card_info(ac->id, &ci, zc->online);
+
+	for (i = 0; ep11_op_modes[i].mode_txt; i++) {
+		if (ci.op_mode & (1ULL << ep11_op_modes[i].mode_bit)) {
+			if (n > 0)
+				buf[n++] = ' ';
+			n += scnprintf(buf + n, PAGE_SIZE - n,
+				       "%s", ep11_op_modes[i].mode_txt);
+		}
+	}
+	n += scnprintf(buf + n, PAGE_SIZE - n, "\n");
+
+	return n;
+}
+
+static struct device_attribute dev_attr_ep11_card_op_modes =
+	__ATTR(op_modes, 0444, ep11_card_op_modes_show, NULL);
+
+static struct attribute *ep11_card_attrs[] = {
+	&dev_attr_ep11_api_ordinalnr.attr,
+	&dev_attr_ep11_fw_version.attr,
+	&dev_attr_ep11_serialnr.attr,
+	&dev_attr_ep11_card_op_modes.attr,
+	NULL,
+};
+
+static const struct attribute_group ep11_card_attr_grp = {
+	.attrs = ep11_card_attrs,
+};
+
+/*
+ * EP11 queue additional device attributes
+ */
+
+static ssize_t ep11_mkvps_show(struct device *dev,
+			       struct device_attribute *attr,
+			       char *buf)
+{
+	int n = 0;
+	struct ep11_domain_info di;
+	struct zcrypt_queue *zq = to_ap_queue(dev)->private;
+	static const char * const cwk_state[] = { "invalid", "valid" };
+	static const char * const nwk_state[] = { "empty", "uncommitted",
+						  "committed" };
+
+	memset(&di, 0, sizeof(di));
+
+	if (zq->online)
+		ep11_get_domain_info(AP_QID_CARD(zq->queue->qid),
+				     AP_QID_QUEUE(zq->queue->qid),
+				     &di);
+
+	if (di.cur_wk_state == '0') {
+		n = scnprintf(buf, PAGE_SIZE, "WK CUR: %s -\n",
+			      cwk_state[di.cur_wk_state - '0']);
+	} else if (di.cur_wk_state == '1') {
+		n = scnprintf(buf, PAGE_SIZE, "WK CUR: %s 0x",
+			      cwk_state[di.cur_wk_state - '0']);
+		bin2hex(buf + n, di.cur_wkvp, sizeof(di.cur_wkvp));
+		n += 2 * sizeof(di.cur_wkvp);
+		n += scnprintf(buf + n, PAGE_SIZE - n, "\n");
+	} else
+		n = scnprintf(buf, PAGE_SIZE, "WK CUR: - -\n");
+
+	if (di.new_wk_state == '0') {
+		n += scnprintf(buf + n, PAGE_SIZE - n, "WK NEW: %s -\n",
+			       nwk_state[di.new_wk_state - '0']);
+	} else if (di.new_wk_state >= '1' && di.new_wk_state <= '2') {
+		n += scnprintf(buf + n, PAGE_SIZE - n, "WK NEW: %s 0x",
+			       nwk_state[di.new_wk_state - '0']);
+		bin2hex(buf + n, di.new_wkvp, sizeof(di.new_wkvp));
+		n += 2 * sizeof(di.new_wkvp);
+		n += scnprintf(buf + n, PAGE_SIZE - n, "\n");
+	} else
+		n += scnprintf(buf + n, PAGE_SIZE - n, "WK NEW: - -\n");
+
+	return n;
+}
+
+static struct device_attribute dev_attr_ep11_mkvps =
+	__ATTR(mkvps, 0444, ep11_mkvps_show, NULL);
+
+static ssize_t ep11_queue_op_modes_show(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	int i, n = 0;
+	struct ep11_domain_info di;
+	struct zcrypt_queue *zq = to_ap_queue(dev)->private;
+
+	memset(&di, 0, sizeof(di));
+
+	if (zq->online)
+		ep11_get_domain_info(AP_QID_CARD(zq->queue->qid),
+				     AP_QID_QUEUE(zq->queue->qid),
+				     &di);
+
+	for (i = 0; ep11_op_modes[i].mode_txt; i++) {
+		if (di.op_mode & (1ULL << ep11_op_modes[i].mode_bit)) {
+			if (n > 0)
+				buf[n++] = ' ';
+			n += scnprintf(buf + n, PAGE_SIZE - n,
+				       "%s", ep11_op_modes[i].mode_txt);
+		}
+	}
+	n += scnprintf(buf + n, PAGE_SIZE - n, "\n");
+
+	return n;
+}
+
+static struct device_attribute dev_attr_ep11_queue_op_modes =
+	__ATTR(op_modes, 0444, ep11_queue_op_modes_show, NULL);
+
+static struct attribute *ep11_queue_attrs[] = {
+	&dev_attr_ep11_mkvps.attr,
+	&dev_attr_ep11_queue_op_modes.attr,
+	NULL,
+};
+
+static const struct attribute_group ep11_queue_attr_grp = {
+	.attrs = ep11_queue_attrs,
+};
+
 /**
  * Probe function for CEX4/CEX5/CEX6/CEX7 card device. It always
  * accepts the AP device since the bus_match already checked
@@ -161,31 +406,31 @@
 	 * Normalized speed ratings per crypto adapter
 	 * MEX_1k, MEX_2k, MEX_4k, CRT_1k, CRT_2k, CRT_4k, RNG, SECKEY
 	 */
-	static const int CEX4A_SPEED_IDX[] = {
+	static const int CEX4A_SPEED_IDX[NUM_OPS] = {
 		 14,  19, 249, 42, 228, 1458, 0, 0};
-	static const int CEX5A_SPEED_IDX[] = {
+	static const int CEX5A_SPEED_IDX[NUM_OPS] = {
 		  8,   9,  20, 18,  66,	 458, 0, 0};
-	static const int CEX6A_SPEED_IDX[] = {
+	static const int CEX6A_SPEED_IDX[NUM_OPS] = {
 		  6,   9,  20, 17,  65,	 438, 0, 0};
-	static const int CEX7A_SPEED_IDX[] = {
+	static const int CEX7A_SPEED_IDX[NUM_OPS] = {
 		  6,   8,  17, 15,  54,	 362, 0, 0};
 
-	static const int CEX4C_SPEED_IDX[] = {
+	static const int CEX4C_SPEED_IDX[NUM_OPS] = {
 		 59,  69, 308, 83, 278, 2204, 209, 40};
 	static const int CEX5C_SPEED_IDX[] = {
 		 24,  31,  50, 37,  90,	 479,  27, 10};
-	static const int CEX6C_SPEED_IDX[] = {
+	static const int CEX6C_SPEED_IDX[NUM_OPS] = {
 		 16,  20,  32, 27,  77,	 455,  24,  9};
-	static const int CEX7C_SPEED_IDX[] = {
+	static const int CEX7C_SPEED_IDX[NUM_OPS] = {
 		 14,  16,  26, 23,  64,	 376,  23,  8};
 
-	static const int CEX4P_SPEED_IDX[] = {
+	static const int CEX4P_SPEED_IDX[NUM_OPS] = {
 		  0,   0,   0,	 0,   0,   0,	0,  50};
-	static const int CEX5P_SPEED_IDX[] = {
+	static const int CEX5P_SPEED_IDX[NUM_OPS] = {
 		  0,   0,   0,	 0,   0,   0,	0,  10};
-	static const int CEX6P_SPEED_IDX[] = {
+	static const int CEX6P_SPEED_IDX[NUM_OPS] = {
 		  0,   0,   0,	 0,   0,   0,	0,   9};
-	static const int CEX7P_SPEED_IDX[] = {
+	static const int CEX7P_SPEED_IDX[NUM_OPS] = {
 		  0,   0,   0,	 0,   0,   0,	0,   8};
 
 	struct ap_card *ac = to_ap_card(&ap_dev->device);
@@ -201,26 +446,22 @@
 		if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX4) {
 			zc->type_string = "CEX4A";
 			zc->user_space_type = ZCRYPT_CEX4;
-			memcpy(zc->speed_rating, CEX4A_SPEED_IDX,
-			       sizeof(CEX4A_SPEED_IDX));
+			zc->speed_rating = CEX4A_SPEED_IDX;
 		} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX5) {
 			zc->type_string = "CEX5A";
 			zc->user_space_type = ZCRYPT_CEX5;
-			memcpy(zc->speed_rating, CEX5A_SPEED_IDX,
-			       sizeof(CEX5A_SPEED_IDX));
+			zc->speed_rating = CEX5A_SPEED_IDX;
 		} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX6) {
 			zc->type_string = "CEX6A";
 			zc->user_space_type = ZCRYPT_CEX6;
-			memcpy(zc->speed_rating, CEX6A_SPEED_IDX,
-			       sizeof(CEX6A_SPEED_IDX));
+			zc->speed_rating = CEX6A_SPEED_IDX;
 		} else {
 			zc->type_string = "CEX7A";
 			/* wrong user space type, just for compatibility
 			 * with the ZCRYPT_STATUS_MASK ioctl.
 			 */
 			zc->user_space_type = ZCRYPT_CEX6;
-			memcpy(zc->speed_rating, CEX7A_SPEED_IDX,
-			       sizeof(CEX7A_SPEED_IDX));
+			zc->speed_rating = CEX7A_SPEED_IDX;
 		}
 		zc->min_mod_size = CEX4A_MIN_MOD_SIZE;
 		if (ap_test_bit(&ac->functions, AP_FUNC_MEX4K) &&
@@ -240,32 +481,28 @@
 			 * just keep it for cca compatibility
 			 */
 			zc->user_space_type = ZCRYPT_CEX3C;
-			memcpy(zc->speed_rating, CEX4C_SPEED_IDX,
-			       sizeof(CEX4C_SPEED_IDX));
+			zc->speed_rating = CEX4C_SPEED_IDX;
 		} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX5) {
 			zc->type_string = "CEX5C";
 			/* wrong user space type, must be CEX5
 			 * just keep it for cca compatibility
 			 */
 			zc->user_space_type = ZCRYPT_CEX3C;
-			memcpy(zc->speed_rating, CEX5C_SPEED_IDX,
-			       sizeof(CEX5C_SPEED_IDX));
+			zc->speed_rating = CEX5C_SPEED_IDX;
 		} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX6) {
 			zc->type_string = "CEX6C";
 			/* wrong user space type, must be CEX6
 			 * just keep it for cca compatibility
 			 */
 			zc->user_space_type = ZCRYPT_CEX3C;
-			memcpy(zc->speed_rating, CEX6C_SPEED_IDX,
-			       sizeof(CEX6C_SPEED_IDX));
+			zc->speed_rating = CEX6C_SPEED_IDX;
 		} else {
 			zc->type_string = "CEX7C";
 			/* wrong user space type, must be CEX7
 			 * just keep it for cca compatibility
 			 */
 			zc->user_space_type = ZCRYPT_CEX3C;
-			memcpy(zc->speed_rating, CEX7C_SPEED_IDX,
-			       sizeof(CEX7C_SPEED_IDX));
+			zc->speed_rating = CEX7C_SPEED_IDX;
 		}
 		zc->min_mod_size = CEX4C_MIN_MOD_SIZE;
 		zc->max_mod_size = CEX4C_MAX_MOD_SIZE;
@@ -274,26 +511,22 @@
 		if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX4) {
 			zc->type_string = "CEX4P";
 			zc->user_space_type = ZCRYPT_CEX4;
-			memcpy(zc->speed_rating, CEX4P_SPEED_IDX,
-			       sizeof(CEX4P_SPEED_IDX));
+			zc->speed_rating = CEX4P_SPEED_IDX;
 		} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX5) {
 			zc->type_string = "CEX5P";
 			zc->user_space_type = ZCRYPT_CEX5;
-			memcpy(zc->speed_rating, CEX5P_SPEED_IDX,
-			       sizeof(CEX5P_SPEED_IDX));
+			zc->speed_rating = CEX5P_SPEED_IDX;
 		} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX6) {
 			zc->type_string = "CEX6P";
 			zc->user_space_type = ZCRYPT_CEX6;
-			memcpy(zc->speed_rating, CEX6P_SPEED_IDX,
-			       sizeof(CEX6P_SPEED_IDX));
+			zc->speed_rating = CEX6P_SPEED_IDX;
 		} else {
 			zc->type_string = "CEX7P";
 			/* wrong user space type, just for compatibility
 			 * with the ZCRYPT_STATUS_MASK ioctl.
 			 */
 			zc->user_space_type = ZCRYPT_CEX6;
-			memcpy(zc->speed_rating, CEX7P_SPEED_IDX,
-			       sizeof(CEX7P_SPEED_IDX));
+			zc->speed_rating = CEX7P_SPEED_IDX;
 		}
 		zc->min_mod_size = CEX4C_MIN_MOD_SIZE;
 		zc->max_mod_size = CEX4C_MAX_MOD_SIZE;
@@ -308,17 +541,27 @@
 	if (rc) {
 		ac->private = NULL;
 		zcrypt_card_free(zc);
-		goto out;
+		return rc;
 	}
 
 	if (ap_test_bit(&ac->functions, AP_FUNC_COPRO)) {
 		rc = sysfs_create_group(&ap_dev->device.kobj,
-					&cca_card_attr_group);
-		if (rc)
+					&cca_card_attr_grp);
+		if (rc) {
+			zcrypt_card_unregister(zc);
+			ac->private = NULL;
+			zcrypt_card_free(zc);
+		}
+	} else if (ap_test_bit(&ac->functions, AP_FUNC_EP11)) {
+		rc = sysfs_create_group(&ap_dev->device.kobj,
+					&ep11_card_attr_grp);
+		if (rc) {
 			zcrypt_card_unregister(zc);
+			ac->private = NULL;
+			zcrypt_card_free(zc);
+		}
 	}
 
-out:
 	return rc;
 }
 
@@ -332,7 +575,9 @@
 	struct zcrypt_card *zc = ac->private;
 
 	if (ap_test_bit(&ac->functions, AP_FUNC_COPRO))
-		sysfs_remove_group(&ap_dev->device.kobj, &cca_card_attr_group);
+		sysfs_remove_group(&ap_dev->device.kobj, &cca_card_attr_grp);
+	else if (ap_test_bit(&ac->functions, AP_FUNC_EP11))
+		sysfs_remove_group(&ap_dev->device.kobj, &ep11_card_attr_grp);
 	if (zc)
 		zcrypt_card_unregister(zc);
 }
@@ -357,19 +602,19 @@
 	int rc;
 
 	if (ap_test_bit(&aq->card->functions, AP_FUNC_ACCEL)) {
-		zq = zcrypt_queue_alloc(CEX4A_MAX_MESSAGE_SIZE);
+		zq = zcrypt_queue_alloc(aq->card->maxmsgsize);
 		if (!zq)
 			return -ENOMEM;
 		zq->ops = zcrypt_msgtype(MSGTYPE50_NAME,
 					 MSGTYPE50_VARIANT_DEFAULT);
 	} else if (ap_test_bit(&aq->card->functions, AP_FUNC_COPRO)) {
-		zq = zcrypt_queue_alloc(CEX4C_MAX_MESSAGE_SIZE);
+		zq = zcrypt_queue_alloc(aq->card->maxmsgsize);
 		if (!zq)
 			return -ENOMEM;
 		zq->ops = zcrypt_msgtype(MSGTYPE06_NAME,
 					 MSGTYPE06_VARIANT_DEFAULT);
 	} else if (ap_test_bit(&aq->card->functions, AP_FUNC_EP11)) {
-		zq = zcrypt_queue_alloc(CEX4C_MAX_MESSAGE_SIZE);
+		zq = zcrypt_queue_alloc(aq->card->maxmsgsize);
 		if (!zq)
 			return -ENOMEM;
 		zq->ops = zcrypt_msgtype(MSGTYPE06_NAME,
@@ -381,6 +626,7 @@
 	zq->queue = aq;
 	zq->online = 1;
 	atomic_set(&zq->load, 0);
+	ap_queue_init_state(aq);
 	ap_queue_init_reply(aq, &zq->reply);
 	aq->request_timeout = CEX4_CLEANUP_TIME,
 	aq->private = zq;
@@ -388,17 +634,27 @@
 	if (rc) {
 		aq->private = NULL;
 		zcrypt_queue_free(zq);
-		goto out;
+		return rc;
 	}
 
 	if (ap_test_bit(&aq->card->functions, AP_FUNC_COPRO)) {
 		rc = sysfs_create_group(&ap_dev->device.kobj,
-					&cca_queue_attr_group);
-		if (rc)
+					&cca_queue_attr_grp);
+		if (rc) {
+			zcrypt_queue_unregister(zq);
+			aq->private = NULL;
+			zcrypt_queue_free(zq);
+		}
+	} else if (ap_test_bit(&aq->card->functions, AP_FUNC_EP11)) {
+		rc = sysfs_create_group(&ap_dev->device.kobj,
+					&ep11_queue_attr_grp);
+		if (rc) {
 			zcrypt_queue_unregister(zq);
+			aq->private = NULL;
+			zcrypt_queue_free(zq);
+		}
 	}
 
-out:
 	return rc;
 }
 
@@ -412,7 +668,9 @@
 	struct zcrypt_queue *zq = aq->private;
 
 	if (ap_test_bit(&aq->card->functions, AP_FUNC_COPRO))
-		sysfs_remove_group(&ap_dev->device.kobj, &cca_queue_attr_group);
+		sysfs_remove_group(&ap_dev->device.kobj, &cca_queue_attr_grp);
+	else if (ap_test_bit(&aq->card->functions, AP_FUNC_EP11))
+		sysfs_remove_group(&ap_dev->device.kobj, &ep11_queue_attr_grp);
 	if (zq)
 		zcrypt_queue_unregister(zq);
 }
@@ -420,8 +678,6 @@
 static struct ap_driver zcrypt_cex4_queue_driver = {
 	.probe = zcrypt_cex4_queue_probe,
 	.remove = zcrypt_cex4_queue_remove,
-	.suspend = ap_queue_suspend,
-	.resume = ap_queue_resume,
 	.ids = zcrypt_cex4_queue_ids,
 	.flags = AP_DRIVER_FLAG_DEFAULT,
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/crypto/zcrypt_debug.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/crypto/zcrypt_debug.h
@@ -21,6 +21,14 @@
 
 #define ZCRYPT_DBF(...)					\
 	debug_sprintf_event(zcrypt_dbf_info, ##__VA_ARGS__)
+#define ZCRYPT_DBF_ERR(...)					\
+	debug_sprintf_event(zcrypt_dbf_info, DBF_ERR, ##__VA_ARGS__)
+#define ZCRYPT_DBF_WARN(...)					\
+	debug_sprintf_event(zcrypt_dbf_info, DBF_WARN, ##__VA_ARGS__)
+#define ZCRYPT_DBF_INFO(...)					\
+	debug_sprintf_event(zcrypt_dbf_info, DBF_INFO, ##__VA_ARGS__)
+#define ZCRYPT_DBF_DBG(...)					\
+	debug_sprintf_event(zcrypt_dbf_info, DBF_DEBUG, ##__VA_ARGS__)
 
 extern debug_info_t *zcrypt_dbf_info;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/crypto/zcrypt_ep11misc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/crypto/zcrypt_ep11misc.c
@@ -0,0 +1,1274 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ *  Copyright IBM Corp. 2019
+ *  Author(s): Harald Freudenberger <freude@linux.ibm.com>
+ *
+ *  Collection of EP11 misc functions used by zcrypt and pkey
+ */
+
+#define KMSG_COMPONENT "zcrypt"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <asm/zcrypt.h>
+#include <asm/pkey.h>
+
+#include "ap_bus.h"
+#include "zcrypt_api.h"
+#include "zcrypt_debug.h"
+#include "zcrypt_msgtype6.h"
+#include "zcrypt_ep11misc.h"
+#include "zcrypt_ccamisc.h"
+
+#define DEBUG_DBG(...)	ZCRYPT_DBF(DBF_DEBUG, ##__VA_ARGS__)
+#define DEBUG_INFO(...) ZCRYPT_DBF(DBF_INFO, ##__VA_ARGS__)
+#define DEBUG_WARN(...) ZCRYPT_DBF(DBF_WARN, ##__VA_ARGS__)
+#define DEBUG_ERR(...)	ZCRYPT_DBF(DBF_ERR, ##__VA_ARGS__)
+
+/* default iv used here */
+static const u8 def_iv[16] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+			       0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
+
+/* ep11 card info cache */
+struct card_list_entry {
+	struct list_head list;
+	u16 cardnr;
+	struct ep11_card_info info;
+};
+static LIST_HEAD(card_list);
+static DEFINE_SPINLOCK(card_list_lock);
+
+static int card_cache_fetch(u16 cardnr, struct ep11_card_info *ci)
+{
+	int rc = -ENOENT;
+	struct card_list_entry *ptr;
+
+	spin_lock_bh(&card_list_lock);
+	list_for_each_entry(ptr, &card_list, list) {
+		if (ptr->cardnr == cardnr) {
+			memcpy(ci, &ptr->info, sizeof(*ci));
+			rc = 0;
+			break;
+		}
+	}
+	spin_unlock_bh(&card_list_lock);
+
+	return rc;
+}
+
+static void card_cache_update(u16 cardnr, const struct ep11_card_info *ci)
+{
+	int found = 0;
+	struct card_list_entry *ptr;
+
+	spin_lock_bh(&card_list_lock);
+	list_for_each_entry(ptr, &card_list, list) {
+		if (ptr->cardnr == cardnr) {
+			memcpy(&ptr->info, ci, sizeof(*ci));
+			found = 1;
+			break;
+		}
+	}
+	if (!found) {
+		ptr = kmalloc(sizeof(*ptr), GFP_ATOMIC);
+		if (!ptr) {
+			spin_unlock_bh(&card_list_lock);
+			return;
+		}
+		ptr->cardnr = cardnr;
+		memcpy(&ptr->info, ci, sizeof(*ci));
+		list_add(&ptr->list, &card_list);
+	}
+	spin_unlock_bh(&card_list_lock);
+}
+
+static void card_cache_scrub(u16 cardnr)
+{
+	struct card_list_entry *ptr;
+
+	spin_lock_bh(&card_list_lock);
+	list_for_each_entry(ptr, &card_list, list) {
+		if (ptr->cardnr == cardnr) {
+			list_del(&ptr->list);
+			kfree(ptr);
+			break;
+		}
+	}
+	spin_unlock_bh(&card_list_lock);
+}
+
+static void __exit card_cache_free(void)
+{
+	struct card_list_entry *ptr, *pnext;
+
+	spin_lock_bh(&card_list_lock);
+	list_for_each_entry_safe(ptr, pnext, &card_list, list) {
+		list_del(&ptr->list);
+		kfree(ptr);
+	}
+	spin_unlock_bh(&card_list_lock);
+}
+
+/*
+ * Simple check if the key blob is a valid EP11 secure AES key.
+ */
+int ep11_check_aeskeyblob(debug_info_t *dbg, int dbflvl,
+			  const u8 *key, int keybitsize,
+			  int checkcpacfexport)
+{
+	struct ep11keyblob *kb = (struct ep11keyblob *) key;
+
+#define DBF(...) debug_sprintf_event(dbg, dbflvl, ##__VA_ARGS__)
+
+	if (kb->head.type != TOKTYPE_NON_CCA) {
+		if (dbg)
+			DBF("%s key check failed, type 0x%02x != 0x%02x\n",
+			    __func__, (int) kb->head.type, TOKTYPE_NON_CCA);
+		return -EINVAL;
+	}
+	if (kb->head.version != TOKVER_EP11_AES) {
+		if (dbg)
+			DBF("%s key check failed, version 0x%02x != 0x%02x\n",
+			    __func__, (int) kb->head.version, TOKVER_EP11_AES);
+		return -EINVAL;
+	}
+	if (kb->version != EP11_STRUCT_MAGIC) {
+		if (dbg)
+			DBF("%s key check failed, magic 0x%04x != 0x%04x\n",
+			    __func__, (int) kb->version, EP11_STRUCT_MAGIC);
+		return -EINVAL;
+	}
+	switch (kb->head.keybitlen) {
+	case 128:
+	case 192:
+	case 256:
+		break;
+	default:
+		if (dbg)
+			DBF("%s key check failed, keybitlen %d invalid\n",
+			    __func__, (int) kb->head.keybitlen);
+		return -EINVAL;
+	}
+	if (keybitsize > 0 && keybitsize != (int) kb->head.keybitlen) {
+		DBF("%s key check failed, keybitsize %d\n",
+		    __func__, keybitsize);
+		return -EINVAL;
+	}
+	if (checkcpacfexport && !(kb->attr & EP11_BLOB_PKEY_EXTRACTABLE)) {
+		if (dbg)
+			DBF("%s key check failed, PKEY_EXTRACTABLE is 0\n",
+			    __func__);
+		return -EINVAL;
+	}
+#undef DBF
+
+	return 0;
+}
+EXPORT_SYMBOL(ep11_check_aeskeyblob);
+
+/*
+ * Allocate and prepare ep11 cprb plus additional payload.
+ */
+static inline struct ep11_cprb *alloc_cprb(size_t payload_len)
+{
+	size_t len = sizeof(struct ep11_cprb) + payload_len;
+	struct ep11_cprb *cprb;
+
+	cprb = kzalloc(len, GFP_KERNEL);
+	if (!cprb)
+		return NULL;
+
+	cprb->cprb_len = sizeof(struct ep11_cprb);
+	cprb->cprb_ver_id = 0x04;
+	memcpy(cprb->func_id, "T4", 2);
+	cprb->ret_code = 0xFFFFFFFF;
+	cprb->payload_len = payload_len;
+
+	return cprb;
+}
+
+/*
+ * Some helper functions related to ASN1 encoding.
+ * Limited to length info <= 2 byte.
+ */
+
+#define ASN1TAGLEN(x) (2 + (x) + ((x) > 127 ? 1 : 0) + ((x) > 255 ? 1 : 0))
+
+static int asn1tag_write(u8 *ptr, u8 tag, const u8 *pvalue, u16 valuelen)
+{
+	ptr[0] = tag;
+	if (valuelen > 255) {
+		ptr[1] = 0x82;
+		*((u16 *)(ptr + 2)) = valuelen;
+		memcpy(ptr + 4, pvalue, valuelen);
+		return 4 + valuelen;
+	}
+	if (valuelen > 127) {
+		ptr[1] = 0x81;
+		ptr[2] = (u8) valuelen;
+		memcpy(ptr + 3, pvalue, valuelen);
+		return 3 + valuelen;
+	}
+	ptr[1] = (u8) valuelen;
+	memcpy(ptr + 2, pvalue, valuelen);
+	return 2 + valuelen;
+}
+
+/* EP11 payload > 127 bytes starts with this struct */
+struct pl_head {
+	u8  tag;
+	u8  lenfmt;
+	u16 len;
+	u8  func_tag;
+	u8  func_len;
+	u32 func;
+	u8  dom_tag;
+	u8  dom_len;
+	u32 dom;
+} __packed;
+
+/* prep ep11 payload head helper function */
+static inline void prep_head(struct pl_head *h,
+			     size_t pl_size, int api, int func)
+{
+	h->tag = 0x30;
+	h->lenfmt = 0x82;
+	h->len = pl_size - 4;
+	h->func_tag = 0x04;
+	h->func_len = sizeof(u32);
+	h->func = (api << 16) + func;
+	h->dom_tag = 0x04;
+	h->dom_len = sizeof(u32);
+}
+
+/* prep urb helper function */
+static inline void prep_urb(struct ep11_urb *u,
+			    struct ep11_target_dev *t, int nt,
+			    struct ep11_cprb *req, size_t req_len,
+			    struct ep11_cprb *rep, size_t rep_len)
+{
+	u->targets = (u8 __user *) t;
+	u->targets_num = nt;
+	u->req = (u8 __user *) req;
+	u->req_len = req_len;
+	u->resp = (u8 __user *) rep;
+	u->resp_len = rep_len;
+}
+
+/* Check ep11 reply payload, return 0 or suggested errno value. */
+static int check_reply_pl(const u8 *pl, const char *func)
+{
+	int len;
+	u32 ret;
+
+	/* start tag */
+	if (*pl++ != 0x30) {
+		DEBUG_ERR("%s reply start tag mismatch\n", func);
+		return -EIO;
+	}
+
+	/* payload length format */
+	if (*pl < 127) {
+		len = *pl;
+		pl++;
+	} else if (*pl == 0x81) {
+		pl++;
+		len = *pl;
+		pl++;
+	} else if (*pl == 0x82) {
+		pl++;
+		len = *((u16 *)pl);
+		pl += 2;
+	} else {
+		DEBUG_ERR("%s reply start tag lenfmt mismatch 0x%02hhx\n",
+			  func, *pl);
+		return -EIO;
+	}
+
+	/* len should cover at least 3 fields with 32 bit value each */
+	if (len < 3 * 6) {
+		DEBUG_ERR("%s reply length %d too small\n", func, len);
+		return -EIO;
+	}
+
+	/* function tag, length and value */
+	if (pl[0] != 0x04 || pl[1] != 0x04) {
+		DEBUG_ERR("%s function tag or length mismatch\n", func);
+		return -EIO;
+	}
+	pl += 6;
+
+	/* dom tag, length and value */
+	if (pl[0] != 0x04 || pl[1] != 0x04) {
+		DEBUG_ERR("%s dom tag or length mismatch\n", func);
+		return -EIO;
+	}
+	pl += 6;
+
+	/* return value tag, length and value */
+	if (pl[0] != 0x04 || pl[1] != 0x04) {
+		DEBUG_ERR("%s return value tag or length mismatch\n", func);
+		return -EIO;
+	}
+	pl += 2;
+	ret = *((u32 *)pl);
+	if (ret != 0) {
+		DEBUG_ERR("%s return value 0x%04x != 0\n", func, ret);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+
+/*
+ * Helper function which does an ep11 query with given query type.
+ */
+static int ep11_query_info(u16 cardnr, u16 domain, u32 query_type,
+			   size_t buflen, u8 *buf)
+{
+	struct ep11_info_req_pl {
+		struct pl_head head;
+		u8  query_type_tag;
+		u8  query_type_len;
+		u32 query_type;
+		u8  query_subtype_tag;
+		u8  query_subtype_len;
+		u32 query_subtype;
+	} __packed * req_pl;
+	struct ep11_info_rep_pl {
+		struct pl_head head;
+		u8  rc_tag;
+		u8  rc_len;
+		u32 rc;
+		u8  data_tag;
+		u8  data_lenfmt;
+		u16 data_len;
+	} __packed * rep_pl;
+	struct ep11_cprb *req = NULL, *rep = NULL;
+	struct ep11_target_dev target;
+	struct ep11_urb *urb = NULL;
+	int api = 1, rc = -ENOMEM;
+
+	/* request cprb and payload */
+	req = alloc_cprb(sizeof(struct ep11_info_req_pl));
+	if (!req)
+		goto out;
+	req_pl = (struct ep11_info_req_pl *) (((u8 *) req) + sizeof(*req));
+	prep_head(&req_pl->head, sizeof(*req_pl), api, 38); /* get xcp info */
+	req_pl->query_type_tag = 0x04;
+	req_pl->query_type_len = sizeof(u32);
+	req_pl->query_type = query_type;
+	req_pl->query_subtype_tag = 0x04;
+	req_pl->query_subtype_len = sizeof(u32);
+
+	/* reply cprb and payload */
+	rep = alloc_cprb(sizeof(struct ep11_info_rep_pl) + buflen);
+	if (!rep)
+		goto out;
+	rep_pl = (struct ep11_info_rep_pl *) (((u8 *) rep) + sizeof(*rep));
+
+	/* urb and target */
+	urb = kmalloc(sizeof(struct ep11_urb), GFP_KERNEL);
+	if (!urb)
+		goto out;
+	target.ap_id = cardnr;
+	target.dom_id = domain;
+	prep_urb(urb, &target, 1,
+		 req, sizeof(*req) + sizeof(*req_pl),
+		 rep, sizeof(*rep) + sizeof(*rep_pl) + buflen);
+
+	rc = zcrypt_send_ep11_cprb(urb);
+	if (rc) {
+		DEBUG_ERR(
+			"%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n",
+			__func__, (int) cardnr, (int) domain, rc);
+		goto out;
+	}
+
+	rc = check_reply_pl((u8 *)rep_pl, __func__);
+	if (rc)
+		goto out;
+	if (rep_pl->data_tag != 0x04 || rep_pl->data_lenfmt != 0x82) {
+		DEBUG_ERR("%s unknown reply data format\n", __func__);
+		rc = -EIO;
+		goto out;
+	}
+	if (rep_pl->data_len > buflen) {
+		DEBUG_ERR("%s mismatch between reply data len and buffer len\n",
+			  __func__);
+		rc = -ENOSPC;
+		goto out;
+	}
+
+	memcpy(buf, ((u8 *) rep_pl) + sizeof(*rep_pl), rep_pl->data_len);
+
+out:
+	kfree(req);
+	kfree(rep);
+	kfree(urb);
+	return rc;
+}
+
+/*
+ * Provide information about an EP11 card.
+ */
+int ep11_get_card_info(u16 card, struct ep11_card_info *info, int verify)
+{
+	int rc;
+	struct ep11_module_query_info {
+		u32 API_ord_nr;
+		u32 firmware_id;
+		u8  FW_major_vers;
+		u8  FW_minor_vers;
+		u8  CSP_major_vers;
+		u8  CSP_minor_vers;
+		u8  fwid[32];
+		u8  xcp_config_hash[32];
+		u8  CSP_config_hash[32];
+		u8  serial[16];
+		u8  module_date_time[16];
+		u64 op_mode;
+		u32 PKCS11_flags;
+		u32 ext_flags;
+		u32 domains;
+		u32 sym_state_bytes;
+		u32 digest_state_bytes;
+		u32 pin_blob_bytes;
+		u32 SPKI_bytes;
+		u32 priv_key_blob_bytes;
+		u32 sym_blob_bytes;
+		u32 max_payload_bytes;
+		u32 CP_profile_bytes;
+		u32 max_CP_index;
+	} __packed * pmqi = NULL;
+
+	rc = card_cache_fetch(card, info);
+	if (rc || verify) {
+		pmqi = kmalloc(sizeof(*pmqi), GFP_KERNEL);
+		if (!pmqi)
+			return -ENOMEM;
+		rc = ep11_query_info(card, AUTOSEL_DOM,
+				     0x01 /* module info query */,
+				     sizeof(*pmqi), (u8 *) pmqi);
+		if (rc) {
+			if (rc == -ENODEV)
+				card_cache_scrub(card);
+			goto out;
+		}
+		memset(info, 0, sizeof(*info));
+		info->API_ord_nr = pmqi->API_ord_nr;
+		info->FW_version =
+			(pmqi->FW_major_vers << 8) + pmqi->FW_minor_vers;
+		memcpy(info->serial, pmqi->serial, sizeof(info->serial));
+		info->op_mode = pmqi->op_mode;
+		card_cache_update(card, info);
+	}
+
+out:
+	kfree(pmqi);
+	return rc;
+}
+EXPORT_SYMBOL(ep11_get_card_info);
+
+/*
+ * Provide information about a domain within an EP11 card.
+ */
+int ep11_get_domain_info(u16 card, u16 domain, struct ep11_domain_info *info)
+{
+	int rc;
+	struct ep11_domain_query_info {
+		u32 dom_index;
+		u8  cur_WK_VP[32];
+		u8  new_WK_VP[32];
+		u32 dom_flags;
+		u64 op_mode;
+	} __packed * p_dom_info;
+
+	p_dom_info = kmalloc(sizeof(*p_dom_info), GFP_KERNEL);
+	if (!p_dom_info)
+		return -ENOMEM;
+
+	rc = ep11_query_info(card, domain, 0x03 /* domain info query */,
+			     sizeof(*p_dom_info), (u8 *) p_dom_info);
+	if (rc)
+		goto out;
+
+	memset(info, 0, sizeof(*info));
+	info->cur_wk_state = '0';
+	info->new_wk_state = '0';
+	if (p_dom_info->dom_flags & 0x10 /* left imprint mode */) {
+		if (p_dom_info->dom_flags & 0x02 /* cur wk valid */) {
+			info->cur_wk_state = '1';
+			memcpy(info->cur_wkvp, p_dom_info->cur_WK_VP, 32);
+		}
+		if (p_dom_info->dom_flags & 0x04 /* new wk present */
+		    || p_dom_info->dom_flags & 0x08 /* new wk committed */) {
+			info->new_wk_state =
+				p_dom_info->dom_flags & 0x08 ? '2' : '1';
+			memcpy(info->new_wkvp, p_dom_info->new_WK_VP, 32);
+		}
+	}
+	info->op_mode = p_dom_info->op_mode;
+
+out:
+	kfree(p_dom_info);
+	return rc;
+}
+EXPORT_SYMBOL(ep11_get_domain_info);
+
+/*
+ * Default EP11 AES key generate attributes, used when no keygenflags given:
+ * XCP_BLOB_ENCRYPT | XCP_BLOB_DECRYPT | XCP_BLOB_PROTKEY_EXTRACTABLE
+ */
+#define KEY_ATTR_DEFAULTS 0x00200c00
+
+int ep11_genaeskey(u16 card, u16 domain, u32 keybitsize, u32 keygenflags,
+		   u8 *keybuf, size_t *keybufsize)
+{
+	struct keygen_req_pl {
+		struct pl_head head;
+		u8  var_tag;
+		u8  var_len;
+		u32 var;
+		u8  keybytes_tag;
+		u8  keybytes_len;
+		u32 keybytes;
+		u8  mech_tag;
+		u8  mech_len;
+		u32 mech;
+		u8  attr_tag;
+		u8  attr_len;
+		u32 attr_header;
+		u32 attr_bool_mask;
+		u32 attr_bool_bits;
+		u32 attr_val_len_type;
+		u32 attr_val_len_value;
+		u8  pin_tag;
+		u8  pin_len;
+	} __packed * req_pl;
+	struct keygen_rep_pl {
+		struct pl_head head;
+		u8  rc_tag;
+		u8  rc_len;
+		u32 rc;
+		u8  data_tag;
+		u8  data_lenfmt;
+		u16 data_len;
+		u8  data[512];
+	} __packed * rep_pl;
+	struct ep11_cprb *req = NULL, *rep = NULL;
+	struct ep11_target_dev target;
+	struct ep11_urb *urb = NULL;
+	struct ep11keyblob *kb;
+	int api, rc = -ENOMEM;
+
+	switch (keybitsize) {
+	case 128:
+	case 192:
+	case 256:
+		break;
+	default:
+		DEBUG_ERR(
+			"%s unknown/unsupported keybitsize %d\n",
+			__func__, keybitsize);
+		rc = -EINVAL;
+		goto out;
+	}
+
+	/* request cprb and payload */
+	req = alloc_cprb(sizeof(struct keygen_req_pl));
+	if (!req)
+		goto out;
+	req_pl = (struct keygen_req_pl *) (((u8 *) req) + sizeof(*req));
+	api = (!keygenflags || keygenflags & 0x00200000) ? 4 : 1;
+	prep_head(&req_pl->head, sizeof(*req_pl), api, 21); /* GenerateKey */
+	req_pl->var_tag = 0x04;
+	req_pl->var_len = sizeof(u32);
+	req_pl->keybytes_tag = 0x04;
+	req_pl->keybytes_len = sizeof(u32);
+	req_pl->keybytes = keybitsize / 8;
+	req_pl->mech_tag = 0x04;
+	req_pl->mech_len = sizeof(u32);
+	req_pl->mech = 0x00001080; /* CKM_AES_KEY_GEN */
+	req_pl->attr_tag = 0x04;
+	req_pl->attr_len = 5 * sizeof(u32);
+	req_pl->attr_header = 0x10010000;
+	req_pl->attr_bool_mask = keygenflags ? keygenflags : KEY_ATTR_DEFAULTS;
+	req_pl->attr_bool_bits = keygenflags ? keygenflags : KEY_ATTR_DEFAULTS;
+	req_pl->attr_val_len_type = 0x00000161; /* CKA_VALUE_LEN */
+	req_pl->attr_val_len_value = keybitsize / 8;
+	req_pl->pin_tag = 0x04;
+
+	/* reply cprb and payload */
+	rep = alloc_cprb(sizeof(struct keygen_rep_pl));
+	if (!rep)
+		goto out;
+	rep_pl = (struct keygen_rep_pl *) (((u8 *) rep) + sizeof(*rep));
+
+	/* urb and target */
+	urb = kmalloc(sizeof(struct ep11_urb), GFP_KERNEL);
+	if (!urb)
+		goto out;
+	target.ap_id = card;
+	target.dom_id = domain;
+	prep_urb(urb, &target, 1,
+		 req, sizeof(*req) + sizeof(*req_pl),
+		 rep, sizeof(*rep) + sizeof(*rep_pl));
+
+	rc = zcrypt_send_ep11_cprb(urb);
+	if (rc) {
+		DEBUG_ERR(
+			"%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n",
+			__func__, (int) card, (int) domain, rc);
+		goto out;
+	}
+
+	rc = check_reply_pl((u8 *)rep_pl, __func__);
+	if (rc)
+		goto out;
+	if (rep_pl->data_tag != 0x04 || rep_pl->data_lenfmt != 0x82) {
+		DEBUG_ERR("%s unknown reply data format\n", __func__);
+		rc = -EIO;
+		goto out;
+	}
+	if (rep_pl->data_len > *keybufsize) {
+		DEBUG_ERR("%s mismatch reply data len / key buffer len\n",
+			  __func__);
+		rc = -ENOSPC;
+		goto out;
+	}
+
+	/* copy key blob and set header values */
+	memcpy(keybuf, rep_pl->data, rep_pl->data_len);
+	*keybufsize = rep_pl->data_len;
+	kb = (struct ep11keyblob *) keybuf;
+	kb->head.type = TOKTYPE_NON_CCA;
+	kb->head.len = rep_pl->data_len;
+	kb->head.version = TOKVER_EP11_AES;
+	kb->head.keybitlen = keybitsize;
+
+out:
+	kfree(req);
+	kfree(rep);
+	kfree(urb);
+	return rc;
+}
+EXPORT_SYMBOL(ep11_genaeskey);
+
+static int ep11_cryptsingle(u16 card, u16 domain,
+			    u16 mode, u32 mech, const u8 *iv,
+			    const u8 *key, size_t keysize,
+			    const u8 *inbuf, size_t inbufsize,
+			    u8 *outbuf, size_t *outbufsize)
+{
+	struct crypt_req_pl {
+		struct pl_head head;
+		u8  var_tag;
+		u8  var_len;
+		u32 var;
+		u8  mech_tag;
+		u8  mech_len;
+		u32 mech;
+		/*
+		 * maybe followed by iv data
+		 * followed by key tag + key blob
+		 * followed by plaintext tag + plaintext
+		 */
+	} __packed * req_pl;
+	struct crypt_rep_pl {
+		struct pl_head head;
+		u8  rc_tag;
+		u8  rc_len;
+		u32 rc;
+		u8  data_tag;
+		u8  data_lenfmt;
+		/* data follows */
+	} __packed * rep_pl;
+	struct ep11_cprb *req = NULL, *rep = NULL;
+	struct ep11_target_dev target;
+	struct ep11_urb *urb = NULL;
+	size_t req_pl_size, rep_pl_size;
+	int n, api = 1, rc = -ENOMEM;
+	u8 *p;
+
+	/* the simple asn1 coding used has length limits */
+	if (keysize > 0xFFFF || inbufsize > 0xFFFF)
+		return -EINVAL;
+
+	/* request cprb and payload */
+	req_pl_size = sizeof(struct crypt_req_pl) + (iv ? 16 : 0)
+		+ ASN1TAGLEN(keysize) + ASN1TAGLEN(inbufsize);
+	req = alloc_cprb(req_pl_size);
+	if (!req)
+		goto out;
+	req_pl = (struct crypt_req_pl *) (((u8 *) req) + sizeof(*req));
+	prep_head(&req_pl->head, req_pl_size, api, (mode ? 20 : 19));
+	req_pl->var_tag = 0x04;
+	req_pl->var_len = sizeof(u32);
+	/* mech is mech + mech params (iv here) */
+	req_pl->mech_tag = 0x04;
+	req_pl->mech_len = sizeof(u32) + (iv ? 16 : 0);
+	req_pl->mech = (mech ? mech : 0x00001085); /* CKM_AES_CBC_PAD */
+	p = ((u8 *) req_pl) + sizeof(*req_pl);
+	if (iv) {
+		memcpy(p, iv, 16);
+		p += 16;
+	}
+	/* key and input data */
+	p += asn1tag_write(p, 0x04, key, keysize);
+	p += asn1tag_write(p, 0x04, inbuf, inbufsize);
+
+	/* reply cprb and payload, assume out data size <= in data size + 32 */
+	rep_pl_size = sizeof(struct crypt_rep_pl) + ASN1TAGLEN(inbufsize + 32);
+	rep = alloc_cprb(rep_pl_size);
+	if (!rep)
+		goto out;
+	rep_pl = (struct crypt_rep_pl *) (((u8 *) rep) + sizeof(*rep));
+
+	/* urb and target */
+	urb = kmalloc(sizeof(struct ep11_urb), GFP_KERNEL);
+	if (!urb)
+		goto out;
+	target.ap_id = card;
+	target.dom_id = domain;
+	prep_urb(urb, &target, 1,
+		 req, sizeof(*req) + req_pl_size,
+		 rep, sizeof(*rep) + rep_pl_size);
+
+	rc = zcrypt_send_ep11_cprb(urb);
+	if (rc) {
+		DEBUG_ERR(
+			"%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n",
+			__func__, (int) card, (int) domain, rc);
+		goto out;
+	}
+
+	rc = check_reply_pl((u8 *)rep_pl, __func__);
+	if (rc)
+		goto out;
+	if (rep_pl->data_tag != 0x04) {
+		DEBUG_ERR("%s unknown reply data format\n", __func__);
+		rc = -EIO;
+		goto out;
+	}
+	p = ((u8 *) rep_pl) + sizeof(*rep_pl);
+	if (rep_pl->data_lenfmt <= 127)
+		n = rep_pl->data_lenfmt;
+	else if (rep_pl->data_lenfmt == 0x81)
+		n = *p++;
+	else if (rep_pl->data_lenfmt == 0x82) {
+		n = *((u16 *) p);
+		p += 2;
+	} else {
+		DEBUG_ERR("%s unknown reply data length format 0x%02hhx\n",
+			  __func__, rep_pl->data_lenfmt);
+		rc = -EIO;
+		goto out;
+	}
+	if (n > *outbufsize) {
+		DEBUG_ERR("%s mismatch reply data len %d / output buffer %zu\n",
+			  __func__, n, *outbufsize);
+		rc = -ENOSPC;
+		goto out;
+	}
+
+	memcpy(outbuf, p, n);
+	*outbufsize = n;
+
+out:
+	kfree(req);
+	kfree(rep);
+	kfree(urb);
+	return rc;
+}
+
+static int ep11_unwrapkey(u16 card, u16 domain,
+			  const u8 *kek, size_t keksize,
+			  const u8 *enckey, size_t enckeysize,
+			  u32 mech, const u8 *iv,
+			  u32 keybitsize, u32 keygenflags,
+			  u8 *keybuf, size_t *keybufsize)
+{
+	struct uw_req_pl {
+		struct pl_head head;
+		u8  attr_tag;
+		u8  attr_len;
+		u32 attr_header;
+		u32 attr_bool_mask;
+		u32 attr_bool_bits;
+		u32 attr_key_type;
+		u32 attr_key_type_value;
+		u32 attr_val_len;
+		u32 attr_val_len_value;
+		u8  mech_tag;
+		u8  mech_len;
+		u32 mech;
+		/*
+		 * maybe followed by iv data
+		 * followed by kek tag + kek blob
+		 * followed by empty mac tag
+		 * followed by empty pin tag
+		 * followed by encryted key tag + bytes
+		 */
+	} __packed * req_pl;
+	struct uw_rep_pl {
+		struct pl_head head;
+		u8  rc_tag;
+		u8  rc_len;
+		u32 rc;
+		u8  data_tag;
+		u8  data_lenfmt;
+		u16 data_len;
+		u8  data[512];
+	} __packed * rep_pl;
+	struct ep11_cprb *req = NULL, *rep = NULL;
+	struct ep11_target_dev target;
+	struct ep11_urb *urb = NULL;
+	struct ep11keyblob *kb;
+	size_t req_pl_size;
+	int api, rc = -ENOMEM;
+	u8 *p;
+
+	/* request cprb and payload */
+	req_pl_size = sizeof(struct uw_req_pl) + (iv ? 16 : 0)
+		+ ASN1TAGLEN(keksize) + 4 + ASN1TAGLEN(enckeysize);
+	req = alloc_cprb(req_pl_size);
+	if (!req)
+		goto out;
+	req_pl = (struct uw_req_pl *) (((u8 *) req) + sizeof(*req));
+	api = (!keygenflags || keygenflags & 0x00200000) ? 4 : 1;
+	prep_head(&req_pl->head, req_pl_size, api, 34); /* UnwrapKey */
+	req_pl->attr_tag = 0x04;
+	req_pl->attr_len = 7 * sizeof(u32);
+	req_pl->attr_header = 0x10020000;
+	req_pl->attr_bool_mask = keygenflags ? keygenflags : KEY_ATTR_DEFAULTS;
+	req_pl->attr_bool_bits = keygenflags ? keygenflags : KEY_ATTR_DEFAULTS;
+	req_pl->attr_key_type = 0x00000100; /* CKA_KEY_TYPE */
+	req_pl->attr_key_type_value = 0x0000001f; /* CKK_AES */
+	req_pl->attr_val_len = 0x00000161; /* CKA_VALUE_LEN */
+	req_pl->attr_val_len_value = keybitsize / 8;
+	/* mech is mech + mech params (iv here) */
+	req_pl->mech_tag = 0x04;
+	req_pl->mech_len = sizeof(u32) + (iv ? 16 : 0);
+	req_pl->mech = (mech ? mech : 0x00001085); /* CKM_AES_CBC_PAD */
+	p = ((u8 *) req_pl) + sizeof(*req_pl);
+	if (iv) {
+		memcpy(p, iv, 16);
+		p += 16;
+	}
+	/* kek */
+	p += asn1tag_write(p, 0x04, kek, keksize);
+	/* empty mac key tag */
+	*p++ = 0x04;
+	*p++ = 0;
+	/* empty pin tag */
+	*p++ = 0x04;
+	*p++ = 0;
+	/* encrytped key value tag and bytes */
+	p += asn1tag_write(p, 0x04, enckey, enckeysize);
+
+	/* reply cprb and payload */
+	rep = alloc_cprb(sizeof(struct uw_rep_pl));
+	if (!rep)
+		goto out;
+	rep_pl = (struct uw_rep_pl *) (((u8 *) rep) + sizeof(*rep));
+
+	/* urb and target */
+	urb = kmalloc(sizeof(struct ep11_urb), GFP_KERNEL);
+	if (!urb)
+		goto out;
+	target.ap_id = card;
+	target.dom_id = domain;
+	prep_urb(urb, &target, 1,
+		 req, sizeof(*req) + req_pl_size,
+		 rep, sizeof(*rep) + sizeof(*rep_pl));
+
+	rc = zcrypt_send_ep11_cprb(urb);
+	if (rc) {
+		DEBUG_ERR(
+			"%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n",
+			__func__, (int) card, (int) domain, rc);
+		goto out;
+	}
+
+	rc = check_reply_pl((u8 *)rep_pl, __func__);
+	if (rc)
+		goto out;
+	if (rep_pl->data_tag != 0x04 || rep_pl->data_lenfmt != 0x82) {
+		DEBUG_ERR("%s unknown reply data format\n", __func__);
+		rc = -EIO;
+		goto out;
+	}
+	if (rep_pl->data_len > *keybufsize) {
+		DEBUG_ERR("%s mismatch reply data len / key buffer len\n",
+			  __func__);
+		rc = -ENOSPC;
+		goto out;
+	}
+
+	/* copy key blob and set header values */
+	memcpy(keybuf, rep_pl->data, rep_pl->data_len);
+	*keybufsize = rep_pl->data_len;
+	kb = (struct ep11keyblob *) keybuf;
+	kb->head.type = TOKTYPE_NON_CCA;
+	kb->head.len = rep_pl->data_len;
+	kb->head.version = TOKVER_EP11_AES;
+	kb->head.keybitlen = keybitsize;
+
+out:
+	kfree(req);
+	kfree(rep);
+	kfree(urb);
+	return rc;
+}
+
+static int ep11_wrapkey(u16 card, u16 domain,
+			const u8 *key, size_t keysize,
+			u32 mech, const u8 *iv,
+			u8 *databuf, size_t *datasize)
+{
+	struct wk_req_pl {
+		struct pl_head head;
+		u8  var_tag;
+		u8  var_len;
+		u32 var;
+		u8  mech_tag;
+		u8  mech_len;
+		u32 mech;
+		/*
+		 * followed by iv data
+		 * followed by key tag + key blob
+		 * followed by dummy kek param
+		 * followed by dummy mac param
+		 */
+	} __packed * req_pl;
+	struct wk_rep_pl {
+		struct pl_head head;
+		u8  rc_tag;
+		u8  rc_len;
+		u32 rc;
+		u8  data_tag;
+		u8  data_lenfmt;
+		u16 data_len;
+		u8  data[512];
+	} __packed * rep_pl;
+	struct ep11_cprb *req = NULL, *rep = NULL;
+	struct ep11_target_dev target;
+	struct ep11_urb *urb = NULL;
+	struct ep11keyblob *kb;
+	size_t req_pl_size;
+	int api, rc = -ENOMEM;
+	u8 *p;
+
+	/* request cprb and payload */
+	req_pl_size = sizeof(struct wk_req_pl) + (iv ? 16 : 0)
+		+ ASN1TAGLEN(keysize) + 4;
+	req = alloc_cprb(req_pl_size);
+	if (!req)
+		goto out;
+	if (!mech || mech == 0x80060001)
+		req->flags |= 0x20; /* CPACF_WRAP needs special bit */
+	req_pl = (struct wk_req_pl *) (((u8 *) req) + sizeof(*req));
+	api = (!mech || mech == 0x80060001) ? 4 : 1; /* CKM_IBM_CPACF_WRAP */
+	prep_head(&req_pl->head, req_pl_size, api, 33); /* WrapKey */
+	req_pl->var_tag = 0x04;
+	req_pl->var_len = sizeof(u32);
+	/* mech is mech + mech params (iv here) */
+	req_pl->mech_tag = 0x04;
+	req_pl->mech_len = sizeof(u32) + (iv ? 16 : 0);
+	req_pl->mech = (mech ? mech : 0x80060001); /* CKM_IBM_CPACF_WRAP */
+	p = ((u8 *) req_pl) + sizeof(*req_pl);
+	if (iv) {
+		memcpy(p, iv, 16);
+		p += 16;
+	}
+	/* key blob */
+	p += asn1tag_write(p, 0x04, key, keysize);
+	/* maybe the key argument needs the head data cleaned out */
+	kb = (struct ep11keyblob *)(p - keysize);
+	if (kb->head.version == TOKVER_EP11_AES)
+		memset(&kb->head, 0, sizeof(kb->head));
+	/* empty kek tag */
+	*p++ = 0x04;
+	*p++ = 0;
+	/* empty mac tag */
+	*p++ = 0x04;
+	*p++ = 0;
+
+	/* reply cprb and payload */
+	rep = alloc_cprb(sizeof(struct wk_rep_pl));
+	if (!rep)
+		goto out;
+	rep_pl = (struct wk_rep_pl *) (((u8 *) rep) + sizeof(*rep));
+
+	/* urb and target */
+	urb = kmalloc(sizeof(struct ep11_urb), GFP_KERNEL);
+	if (!urb)
+		goto out;
+	target.ap_id = card;
+	target.dom_id = domain;
+	prep_urb(urb, &target, 1,
+		 req, sizeof(*req) + req_pl_size,
+		 rep, sizeof(*rep) + sizeof(*rep_pl));
+
+	rc = zcrypt_send_ep11_cprb(urb);
+	if (rc) {
+		DEBUG_ERR(
+			"%s zcrypt_send_ep11_cprb(card=%d dom=%d) failed, rc=%d\n",
+			__func__, (int) card, (int) domain, rc);
+		goto out;
+	}
+
+	rc = check_reply_pl((u8 *)rep_pl, __func__);
+	if (rc)
+		goto out;
+	if (rep_pl->data_tag != 0x04 || rep_pl->data_lenfmt != 0x82) {
+		DEBUG_ERR("%s unknown reply data format\n", __func__);
+		rc = -EIO;
+		goto out;
+	}
+	if (rep_pl->data_len > *datasize) {
+		DEBUG_ERR("%s mismatch reply data len / data buffer len\n",
+			  __func__);
+		rc = -ENOSPC;
+		goto out;
+	}
+
+	/* copy the data from the cprb to the data buffer */
+	memcpy(databuf, rep_pl->data, rep_pl->data_len);
+	*datasize = rep_pl->data_len;
+
+out:
+	kfree(req);
+	kfree(rep);
+	kfree(urb);
+	return rc;
+}
+
+int ep11_clr2keyblob(u16 card, u16 domain, u32 keybitsize, u32 keygenflags,
+		     const u8 *clrkey, u8 *keybuf, size_t *keybufsize)
+{
+	int rc;
+	struct ep11keyblob *kb;
+	u8 encbuf[64], *kek = NULL;
+	size_t clrkeylen, keklen, encbuflen = sizeof(encbuf);
+
+	if (keybitsize == 128 || keybitsize == 192 || keybitsize == 256)
+		clrkeylen = keybitsize / 8;
+	else {
+		DEBUG_ERR(
+			"%s unknown/unsupported keybitsize %d\n",
+			__func__, keybitsize);
+		return -EINVAL;
+	}
+
+	/* allocate memory for the temp kek */
+	keklen = MAXEP11AESKEYBLOBSIZE;
+	kek = kmalloc(keklen, GFP_ATOMIC);
+	if (!kek) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	/* Step 1: generate AES 256 bit random kek key */
+	rc = ep11_genaeskey(card, domain, 256,
+			    0x00006c00, /* EN/DECRYTP, WRAP/UNWRAP */
+			    kek, &keklen);
+	if (rc) {
+		DEBUG_ERR(
+			"%s generate kek key failed, rc=%d\n",
+			__func__, rc);
+		goto out;
+	}
+	kb = (struct ep11keyblob *) kek;
+	memset(&kb->head, 0, sizeof(kb->head));
+
+	/* Step 2: encrypt clear key value with the kek key */
+	rc = ep11_cryptsingle(card, domain, 0, 0, def_iv, kek, keklen,
+			      clrkey, clrkeylen, encbuf, &encbuflen);
+	if (rc) {
+		DEBUG_ERR(
+			"%s encrypting key value with kek key failed, rc=%d\n",
+			__func__, rc);
+		goto out;
+	}
+
+	/* Step 3: import the encrypted key value as a new key */
+	rc = ep11_unwrapkey(card, domain, kek, keklen,
+			    encbuf, encbuflen, 0, def_iv,
+			    keybitsize, 0, keybuf, keybufsize);
+	if (rc) {
+		DEBUG_ERR(
+			"%s importing key value as new key failed,, rc=%d\n",
+			__func__, rc);
+		goto out;
+	}
+
+out:
+	kfree(kek);
+	return rc;
+}
+EXPORT_SYMBOL(ep11_clr2keyblob);
+
+int ep11_key2protkey(u16 card, u16 dom, const u8 *key, size_t keylen,
+		     u8 *protkey, u32 *protkeylen, u32 *protkeytype)
+{
+	int rc = -EIO;
+	u8 *wkbuf = NULL;
+	size_t wkbuflen = 256;
+	struct wk_info {
+		u16 version;
+		u8  res1[16];
+		u32 pkeytype;
+		u32 pkeybitsize;
+		u64 pkeysize;
+		u8  res2[8];
+		u8  pkey[0];
+	} __packed * wki;
+
+	/* alloc temp working buffer */
+	wkbuf = kmalloc(wkbuflen, GFP_ATOMIC);
+	if (!wkbuf)
+		return -ENOMEM;
+
+	/* ep11 secure key -> protected key + info */
+	rc = ep11_wrapkey(card, dom, key, keylen,
+			  0, def_iv, wkbuf, &wkbuflen);
+	if (rc) {
+		DEBUG_ERR(
+			"%s rewrapping ep11 key to pkey failed, rc=%d\n",
+			__func__, rc);
+		goto out;
+	}
+	wki = (struct wk_info *) wkbuf;
+
+	/* check struct version and pkey type */
+	if (wki->version != 1 || wki->pkeytype != 1) {
+		DEBUG_ERR("%s wk info version %d or pkeytype %d mismatch.\n",
+			  __func__, (int) wki->version, (int) wki->pkeytype);
+		rc = -EIO;
+		goto out;
+	}
+
+	/* copy the tanslated protected key */
+	switch (wki->pkeysize) {
+	case 16+32:
+		/* AES 128 protected key */
+		if (protkeytype)
+			*protkeytype = PKEY_KEYTYPE_AES_128;
+		break;
+	case 24+32:
+		/* AES 192 protected key */
+		if (protkeytype)
+			*protkeytype = PKEY_KEYTYPE_AES_192;
+		break;
+	case 32+32:
+		/* AES 256 protected key */
+		if (protkeytype)
+			*protkeytype = PKEY_KEYTYPE_AES_256;
+		break;
+	default:
+		DEBUG_ERR("%s unknown/unsupported pkeysize %d\n",
+			  __func__, (int) wki->pkeysize);
+		rc = -EIO;
+		goto out;
+	}
+	memcpy(protkey, wki->pkey, wki->pkeysize);
+	if (protkeylen)
+		*protkeylen = (u32) wki->pkeysize;
+	rc = 0;
+
+out:
+	kfree(wkbuf);
+	return rc;
+}
+EXPORT_SYMBOL(ep11_key2protkey);
+
+int ep11_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
+		   int minhwtype, int minapi, const u8 *wkvp)
+{
+	struct zcrypt_device_status_ext *device_status;
+	u32 *_apqns = NULL, _nr_apqns = 0;
+	int i, card, dom, rc = -ENOMEM;
+	struct ep11_domain_info edi;
+	struct ep11_card_info eci;
+
+	/* fetch status of all crypto cards */
+	device_status = kvmalloc_array(MAX_ZDEV_ENTRIES_EXT,
+				       sizeof(struct zcrypt_device_status_ext),
+				       GFP_KERNEL);
+	if (!device_status)
+		return -ENOMEM;
+	zcrypt_device_status_mask_ext(device_status);
+
+	/* allocate 1k space for up to 256 apqns */
+	_apqns = kmalloc_array(256, sizeof(u32), GFP_KERNEL);
+	if (!_apqns) {
+		kvfree(device_status);
+		return -ENOMEM;
+	}
+
+	/* walk through all the crypto apqnss */
+	for (i = 0; i < MAX_ZDEV_ENTRIES_EXT; i++) {
+		card = AP_QID_CARD(device_status[i].qid);
+		dom = AP_QID_QUEUE(device_status[i].qid);
+		/* check online state */
+		if (!device_status[i].online)
+			continue;
+		/* check for ep11 functions */
+		if (!(device_status[i].functions & 0x01))
+			continue;
+		/* check cardnr */
+		if (cardnr != 0xFFFF && card != cardnr)
+			continue;
+		/* check domain */
+		if (domain != 0xFFFF && dom != domain)
+			continue;
+		/* check min hardware type */
+		if (minhwtype && device_status[i].hwtype < minhwtype)
+			continue;
+		/* check min api version if given */
+		if (minapi > 0) {
+			if (ep11_get_card_info(card, &eci, 0))
+				continue;
+			if (minapi > eci.API_ord_nr)
+				continue;
+		}
+		/* check wkvp if given */
+		if (wkvp) {
+			if (ep11_get_domain_info(card, dom, &edi))
+				continue;
+			if (edi.cur_wk_state != '1')
+				continue;
+			if (memcmp(wkvp, edi.cur_wkvp, 16))
+				continue;
+		}
+		/* apqn passed all filtering criterons, add to the array */
+		if (_nr_apqns < 256)
+			_apqns[_nr_apqns++] = (((u16)card) << 16) | ((u16) dom);
+	}
+
+	/* nothing found ? */
+	if (!_nr_apqns) {
+		kfree(_apqns);
+		rc = -ENODEV;
+	} else {
+		/* no re-allocation, simple return the _apqns array */
+		*apqns = _apqns;
+		*nr_apqns = _nr_apqns;
+		rc = 0;
+	}
+
+	kvfree(device_status);
+	return rc;
+}
+EXPORT_SYMBOL(ep11_findcard2);
+
+void __exit zcrypt_ep11misc_exit(void)
+{
+	card_cache_free();
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/crypto/zcrypt_ep11misc.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/crypto/zcrypt_ep11misc.h
@@ -0,0 +1,124 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ *  Copyright IBM Corp. 2019
+ *  Author(s): Harald Freudenberger <freude@linux.ibm.com>
+ *
+ *  Collection of EP11 misc functions used by zcrypt and pkey
+ */
+
+#ifndef _ZCRYPT_EP11MISC_H_
+#define _ZCRYPT_EP11MISC_H_
+
+#include <asm/zcrypt.h>
+#include <asm/pkey.h>
+
+#define TOKVER_EP11_AES  0x03  /* EP11 AES key blob */
+
+#define EP11_API_V 4  /* highest known and supported EP11 API version */
+
+#define EP11_STRUCT_MAGIC 0x1234
+#define EP11_BLOB_PKEY_EXTRACTABLE 0x200000
+
+/* inside view of an EP11 secure key blob */
+struct ep11keyblob {
+	union {
+		u8 session[32];
+		struct {
+			u8  type;      /* 0x00 (TOKTYPE_NON_CCA) */
+			u8  res0;      /* unused */
+			u16 len;       /* total length in bytes of this blob */
+			u8  version;   /* 0x06 (TOKVER_EP11_AES) */
+			u8  res1;      /* unused */
+			u16 keybitlen; /* clear key bit len, 0 for unknown */
+		} head;
+	};
+	u8  wkvp[16];  /* wrapping key verification pattern */
+	u64 attr;      /* boolean key attributes */
+	u64 mode;      /* mode bits */
+	u16 version;   /* 0x1234, EP11_STRUCT_MAGIC */
+	u8  iv[14];
+	u8  encrypted_key_data[144];
+	u8  mac[32];
+} __packed;
+
+/*
+ * Simple check if the key blob is a valid EP11 secure AES key.
+ * If keybitsize is given, the bitsize of the key is also checked.
+ * If checkcpacfexport is enabled, the key is also checked for the
+ * attributes needed to export this key for CPACF use.
+ * Returns 0 on success or errno value on failure.
+ */
+int ep11_check_aeskeyblob(debug_info_t *dbg, int dbflvl,
+			  const u8 *key, int keybitsize,
+			  int checkcpacfexport);
+
+/* EP11 card info struct */
+struct ep11_card_info {
+	u32  API_ord_nr;    /* API ordinal number */
+	u16  FW_version;    /* Firmware major and minor version */
+	char serial[16];    /* serial number string (16 ascii, no 0x00 !) */
+	u64  op_mode;	    /* card operational mode(s) */
+};
+
+/* EP11 domain info struct */
+struct ep11_domain_info {
+	char cur_wk_state;  /* '0' invalid, '1' valid */
+	char new_wk_state;  /* '0' empty, '1' uncommitted, '2' committed */
+	u8   cur_wkvp[32];  /* current wrapping key verification pattern */
+	u8   new_wkvp[32];  /* new wrapping key verification pattern */
+	u64  op_mode;	    /* domain operational mode(s) */
+};
+
+/*
+ * Provide information about an EP11 card.
+ */
+int ep11_get_card_info(u16 card, struct ep11_card_info *info, int verify);
+
+/*
+ * Provide information about a domain within an EP11 card.
+ */
+int ep11_get_domain_info(u16 card, u16 domain, struct ep11_domain_info *info);
+
+/*
+ * Generate (random) EP11 AES secure key.
+ */
+int ep11_genaeskey(u16 card, u16 domain, u32 keybitsize, u32 keygenflags,
+		   u8 *keybuf, size_t *keybufsize);
+
+/*
+ * Generate EP11 AES secure key with given clear key value.
+ */
+int ep11_clr2keyblob(u16 cardnr, u16 domain, u32 keybitsize, u32 keygenflags,
+		     const u8 *clrkey, u8 *keybuf, size_t *keybufsize);
+
+/*
+ * Derive proteced key from EP11 AES secure key blob.
+ */
+int ep11_key2protkey(u16 cardnr, u16 domain, const u8 *key, size_t keylen,
+		     u8 *protkey, u32 *protkeylen, u32 *protkeytype);
+
+/*
+ * Build a list of ep11 apqns meeting the following constrains:
+ * - apqn is online and is in fact an EP11 apqn
+ * - if cardnr is not FFFF only apqns with this cardnr
+ * - if domain is not FFFF only apqns with this domainnr
+ * - if minhwtype > 0 only apqns with hwtype >= minhwtype
+ * - if minapi > 0 only apqns with API_ord_nr >= minapi
+ * - if wkvp != NULL only apqns where the wkvp (EP11_WKVPLEN bytes) matches
+ *   to the first EP11_WKVPLEN bytes of the wkvp of the current wrapping
+ *   key for this domain. When a wkvp is given there will aways be a re-fetch
+ *   of the domain info for the potential apqn - so this triggers an request
+ *   reply to each apqn eligible.
+ * The array of apqn entries is allocated with kmalloc and returned in *apqns;
+ * the number of apqns stored into the list is returned in *nr_apqns. One apqn
+ * entry is simple a 32 bit value with 16 bit cardnr and 16 bit domain nr and
+ * may be casted to struct pkey_apqn. The return value is either 0 for success
+ * or a negative errno value. If no apqn meeting the criterias is found,
+ * -ENODEV is returned.
+ */
+int ep11_findcard2(u32 **apqns, u32 *nr_apqns, u16 cardnr, u16 domain,
+		   int minhwtype, int minapi, const u8 *wkvp);
+
+void zcrypt_ep11misc_exit(void);
+
+#endif /* _ZCRYPT_EP11MISC_H_ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/crypto/zcrypt_error.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/crypto/zcrypt_error.h
@@ -52,7 +52,6 @@
 #define REP82_ERROR_INVALID_COMMAND	    0x30
 #define REP82_ERROR_MALFORMED_MSG	    0x40
 #define REP82_ERROR_INVALID_SPECIAL_CMD	    0x41
-#define REP82_ERROR_INVALID_DOMAIN_PRECHECK 0x42
 #define REP82_ERROR_RESERVED_FIELDO	    0x50 /* old value	*/
 #define REP82_ERROR_WORD_ALIGNMENT	    0x60
 #define REP82_ERROR_MESSAGE_LENGTH	    0x80
@@ -61,12 +60,12 @@
 #define REP82_ERROR_EVEN_MOD_IN_OPND	    0x85
 #define REP82_ERROR_RESERVED_FIELD	    0x88
 #define REP82_ERROR_INVALID_DOMAIN_PENDING  0x8A
+#define REP82_ERROR_FILTERED_BY_HYPERVISOR  0x8B
 #define REP82_ERROR_TRANSPORT_FAIL	    0x90
 #define REP82_ERROR_PACKET_TRUNCATED	    0xA0
 #define REP82_ERROR_ZERO_BUFFER_LEN	    0xB0
 
 #define REP88_ERROR_MODULE_FAILURE	    0x10
-
 #define REP88_ERROR_MESSAGE_TYPE	    0x20
 #define REP88_ERROR_MESSAGE_MALFORMD	    0x22
 #define REP88_ERROR_MESSAGE_LENGTH	    0x23
@@ -79,82 +78,61 @@
 static inline int convert_error(struct zcrypt_queue *zq,
 				struct ap_message *reply)
 {
-	struct error_hdr *ehdr = reply->message;
+	struct error_hdr *ehdr = reply->msg;
 	int card = AP_QID_CARD(zq->queue->qid);
 	int queue = AP_QID_QUEUE(zq->queue->qid);
 
 	switch (ehdr->reply_code) {
-	case REP82_ERROR_OPERAND_INVALID:
-	case REP82_ERROR_OPERAND_SIZE:
-	case REP82_ERROR_EVEN_MOD_IN_OPND:
-	case REP88_ERROR_MESSAGE_MALFORMD:
-	case REP82_ERROR_INVALID_DOMAIN_PRECHECK:
-	case REP82_ERROR_INVALID_DOMAIN_PENDING:
-	case REP82_ERROR_INVALID_SPECIAL_CMD:
-	//   REP88_ERROR_INVALID_KEY		// '82' CEX2A
-	//   REP88_ERROR_OPERAND		// '84' CEX2A
-	//   REP88_ERROR_OPERAND_EVEN_MOD	// '85' CEX2A
-		/* Invalid input data. */
+	case REP82_ERROR_INVALID_MSG_LEN:	 /* 0x23 */
+	case REP82_ERROR_RESERVD_FIELD:		 /* 0x24 */
+	case REP82_ERROR_FORMAT_FIELD:		 /* 0x29 */
+	case REP82_ERROR_MALFORMED_MSG:		 /* 0x40 */
+	case REP82_ERROR_INVALID_SPECIAL_CMD:	 /* 0x41 */
+	case REP82_ERROR_MESSAGE_LENGTH:	 /* 0x80 */
+	case REP82_ERROR_OPERAND_INVALID:	 /* 0x82 */
+	case REP82_ERROR_OPERAND_SIZE:		 /* 0x84 */
+	case REP82_ERROR_EVEN_MOD_IN_OPND:	 /* 0x85 */
+	case REP82_ERROR_INVALID_DOMAIN_PENDING: /* 0x8A */
+	case REP82_ERROR_FILTERED_BY_HYPERVISOR: /* 0x8B */
+	case REP82_ERROR_PACKET_TRUNCATED:	 /* 0xA0 */
+	case REP88_ERROR_MESSAGE_MALFORMD:	 /* 0x22 */
+	case REP88_ERROR_KEY_TYPE:		 /* 0x34 */
+		/* RY indicates malformed request */
 		ZCRYPT_DBF(DBF_WARN,
-			   "device=%02x.%04x reply=0x%02x => rc=EINVAL\n",
+			   "dev=%02x.%04x RY=0x%02x => rc=EINVAL\n",
 			   card, queue, ehdr->reply_code);
 		return -EINVAL;
-	case REP82_ERROR_MESSAGE_TYPE:
-	//   REP88_ERROR_MESSAGE_TYPE		// '20' CEX2A
+	case REP82_ERROR_MACHINE_FAILURE:	 /* 0x10 */
+	case REP82_ERROR_MESSAGE_TYPE:		 /* 0x20 */
+	case REP82_ERROR_TRANSPORT_FAIL:	 /* 0x90 */
 		/*
-		 * To sent a message of the wrong type is a bug in the
-		 * device driver. Send error msg, disable the device
-		 * and then repeat the request.
+		 * Msg to wrong type or card/infrastructure failure.
+		 * Trigger rescan of the ap bus, trigger retry request.
 		 */
 		atomic_set(&zcrypt_rescan_req, 1);
-		zq->online = 0;
-		pr_err("Cryptographic device %02x.%04x failed and was set offline\n",
-		       card, queue);
-		ZCRYPT_DBF(DBF_ERR,
-			   "device=%02x.%04x reply=0x%02x => online=0 rc=EAGAIN\n",
-			   card, queue, ehdr->reply_code);
-		return -EAGAIN;
-	case REP82_ERROR_TRANSPORT_FAIL:
-		/* Card or infrastructure failure, disable card */
-		atomic_set(&zcrypt_rescan_req, 1);
-		zq->online = 0;
-		pr_err("Cryptographic device %02x.%04x failed and was set offline\n",
-		       card, queue);
 		/* For type 86 response show the apfs value (failure reason) */
-		if (ehdr->type == TYPE86_RSP_CODE) {
+		if (ehdr->reply_code == REP82_ERROR_TRANSPORT_FAIL &&
+		    ehdr->type == TYPE86_RSP_CODE) {
 			struct {
 				struct type86_hdr hdr;
 				struct type86_fmt2_ext fmt2;
-			} __packed * head = reply->message;
+			} __packed * head = reply->msg;
 			unsigned int apfs = *((u32 *)head->fmt2.apfs);
 
-			ZCRYPT_DBF(DBF_ERR,
-				   "device=%02x.%04x reply=0x%02x apfs=0x%x => online=0 rc=EAGAIN\n",
-				   card, queue, apfs, ehdr->reply_code);
+			ZCRYPT_DBF(DBF_WARN,
+				   "dev=%02x.%04x RY=0x%02x apfs=0x%x => bus rescan, rc=EAGAIN\n",
+				   card, queue, ehdr->reply_code, apfs);
 		} else
-			ZCRYPT_DBF(DBF_ERR,
-				   "device=%02x.%04x reply=0x%02x => online=0 rc=EAGAIN\n",
+			ZCRYPT_DBF(DBF_WARN,
+				   "dev=%02x.%04x RY=0x%02x => bus rescan, rc=EAGAIN\n",
 				   card, queue, ehdr->reply_code);
 		return -EAGAIN;
-	case REP82_ERROR_MACHINE_FAILURE:
-	//   REP88_ERROR_MODULE_FAILURE		// '10' CEX2A
-		/* If a card fails disable it and repeat the request. */
-		atomic_set(&zcrypt_rescan_req, 1);
-		zq->online = 0;
-		pr_err("Cryptographic device %02x.%04x failed and was set offline\n",
-		       card, queue);
-		ZCRYPT_DBF(DBF_ERR,
-			   "device=%02x.%04x reply=0x%02x => online=0 rc=EAGAIN\n",
-			   card, queue, ehdr->reply_code);
-		return -EAGAIN;
 	default:
-		zq->online = 0;
-		pr_err("Cryptographic device %02x.%04x failed and was set offline\n",
-		       card, queue);
-		ZCRYPT_DBF(DBF_ERR,
-			   "device=%02x.%04x reply=0x%02x => online=0 rc=EAGAIN\n",
+		/* Assume request is valid and a retry will be worth it */
+		ZCRYPT_DBF(DBF_WARN,
+			   "dev=%02x.%04x RY=0x%02x => rc=EAGAIN\n",
 			   card, queue, ehdr->reply_code);
-		return -EAGAIN;	/* repeat the request on a different device. */
+		return -EAGAIN;
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/crypto/zcrypt_msgtype50.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/crypto/zcrypt_msgtype50.c
@@ -207,10 +207,10 @@
 	mod_len = mex->inputdatalength;
 
 	if (mod_len <= 128) {
-		struct type50_meb1_msg *meb1 = ap_msg->message;
+		struct type50_meb1_msg *meb1 = ap_msg->msg;
 
 		memset(meb1, 0, sizeof(*meb1));
-		ap_msg->length = sizeof(*meb1);
+		ap_msg->len = sizeof(*meb1);
 		meb1->header.msg_type_code = TYPE50_TYPE_CODE;
 		meb1->header.msg_len = sizeof(*meb1);
 		meb1->keyblock_type = TYPE50_MEB1_FMT;
@@ -218,10 +218,10 @@
 		exp = meb1->exponent + sizeof(meb1->exponent) - mod_len;
 		inp = meb1->message + sizeof(meb1->message) - mod_len;
 	} else if (mod_len <= 256) {
-		struct type50_meb2_msg *meb2 = ap_msg->message;
+		struct type50_meb2_msg *meb2 = ap_msg->msg;
 
 		memset(meb2, 0, sizeof(*meb2));
-		ap_msg->length = sizeof(*meb2);
+		ap_msg->len = sizeof(*meb2);
 		meb2->header.msg_type_code = TYPE50_TYPE_CODE;
 		meb2->header.msg_len = sizeof(*meb2);
 		meb2->keyblock_type = TYPE50_MEB2_FMT;
@@ -229,10 +229,10 @@
 		exp = meb2->exponent + sizeof(meb2->exponent) - mod_len;
 		inp = meb2->message + sizeof(meb2->message) - mod_len;
 	} else if (mod_len <= 512) {
-		struct type50_meb3_msg *meb3 = ap_msg->message;
+		struct type50_meb3_msg *meb3 = ap_msg->msg;
 
 		memset(meb3, 0, sizeof(*meb3));
-		ap_msg->length = sizeof(*meb3);
+		ap_msg->len = sizeof(*meb3);
 		meb3->header.msg_type_code = TYPE50_TYPE_CODE;
 		meb3->header.msg_len = sizeof(*meb3);
 		meb3->keyblock_type = TYPE50_MEB3_FMT;
@@ -246,6 +246,12 @@
 	    copy_from_user(exp, mex->b_key, mod_len) ||
 	    copy_from_user(inp, mex->inputdata, mod_len))
 		return -EFAULT;
+
+#ifdef CONFIG_ZCRYPT_DEBUG
+	if (ap_msg->fi.flags & AP_FI_FLAG_TOGGLE_SPECIAL)
+		ap_msg->flags ^= AP_MSG_FLAG_SPECIAL;
+#endif
+
 	return 0;
 }
 
@@ -275,10 +281,10 @@
 	 * 512 byte modulus (4k keys).
 	 */
 	if (mod_len <= 128) {		/* up to 1024 bit key size */
-		struct type50_crb1_msg *crb1 = ap_msg->message;
+		struct type50_crb1_msg *crb1 = ap_msg->msg;
 
 		memset(crb1, 0, sizeof(*crb1));
-		ap_msg->length = sizeof(*crb1);
+		ap_msg->len = sizeof(*crb1);
 		crb1->header.msg_type_code = TYPE50_TYPE_CODE;
 		crb1->header.msg_len = sizeof(*crb1);
 		crb1->keyblock_type = TYPE50_CRB1_FMT;
@@ -289,10 +295,10 @@
 		u = crb1->u + sizeof(crb1->u) - short_len;
 		inp = crb1->message + sizeof(crb1->message) - mod_len;
 	} else if (mod_len <= 256) {	/* up to 2048 bit key size */
-		struct type50_crb2_msg *crb2 = ap_msg->message;
+		struct type50_crb2_msg *crb2 = ap_msg->msg;
 
 		memset(crb2, 0, sizeof(*crb2));
-		ap_msg->length = sizeof(*crb2);
+		ap_msg->len = sizeof(*crb2);
 		crb2->header.msg_type_code = TYPE50_TYPE_CODE;
 		crb2->header.msg_len = sizeof(*crb2);
 		crb2->keyblock_type = TYPE50_CRB2_FMT;
@@ -304,10 +310,10 @@
 		inp = crb2->message + sizeof(crb2->message) - mod_len;
 	} else if ((mod_len <= 512) &&	/* up to 4096 bit key size */
 		   (zq->zcard->max_mod_size == CEX3A_MAX_MOD_SIZE)) {
-		struct type50_crb3_msg *crb3 = ap_msg->message;
+		struct type50_crb3_msg *crb3 = ap_msg->msg;
 
 		memset(crb3, 0, sizeof(*crb3));
-		ap_msg->length = sizeof(*crb3);
+		ap_msg->len = sizeof(*crb3);
 		crb3->header.msg_type_code = TYPE50_TYPE_CODE;
 		crb3->header.msg_len = sizeof(*crb3);
 		crb3->keyblock_type = TYPE50_CRB3_FMT;
@@ -332,6 +338,11 @@
 	    copy_from_user(inp, crt->inputdata, mod_len))
 		return -EFAULT;
 
+#ifdef CONFIG_ZCRYPT_DEBUG
+	if (ap_msg->fi.flags & AP_FI_FLAG_TOGGLE_SPECIAL)
+		ap_msg->flags ^= AP_MSG_FLAG_SPECIAL;
+#endif
+
 	return 0;
 }
 
@@ -350,39 +361,39 @@
 			  char __user *outputdata,
 			  unsigned int outputdatalength)
 {
-	struct type80_hdr *t80h = reply->message;
+	struct type80_hdr *t80h = reply->msg;
 	unsigned char *data;
 
 	if (t80h->len < sizeof(*t80h) + outputdatalength) {
 		/* The result is too short, the CEXxA card may not do that.. */
 		zq->online = 0;
-		pr_err("Cryptographic device %02x.%04x failed and was set offline\n",
+		pr_err("Crypto dev=%02x.%04x code=0x%02x => online=0 rc=EAGAIN\n",
 		       AP_QID_CARD(zq->queue->qid),
-		       AP_QID_QUEUE(zq->queue->qid));
-		ZCRYPT_DBF(DBF_ERR,
-			   "device=%02x.%04x code=0x%02x => online=0 rc=EAGAIN\n",
-			   AP_QID_CARD(zq->queue->qid),
-			   AP_QID_QUEUE(zq->queue->qid),
-			   t80h->code);
-		return -EAGAIN;	/* repeat the request on a different device. */
+		       AP_QID_QUEUE(zq->queue->qid),
+		       t80h->code);
+		ZCRYPT_DBF_ERR("dev=%02x.%04x code=0x%02x => online=0 rc=EAGAIN\n",
+			       AP_QID_CARD(zq->queue->qid),
+			       AP_QID_QUEUE(zq->queue->qid),
+			       t80h->code);
+		return -EAGAIN;
 	}
 	if (zq->zcard->user_space_type == ZCRYPT_CEX2A)
 		BUG_ON(t80h->len > CEX2A_MAX_RESPONSE_SIZE);
 	else
 		BUG_ON(t80h->len > CEX3A_MAX_RESPONSE_SIZE);
-	data = reply->message + t80h->len - outputdatalength;
+	data = reply->msg + t80h->len - outputdatalength;
 	if (copy_to_user(outputdata, data, outputdatalength))
 		return -EFAULT;
 	return 0;
 }
 
-static int convert_response(struct zcrypt_queue *zq,
-			    struct ap_message *reply,
-			    char __user *outputdata,
-			    unsigned int outputdatalength)
+static int convert_response_cex2a(struct zcrypt_queue *zq,
+				  struct ap_message *reply,
+				  char __user *outputdata,
+				  unsigned int outputdatalength)
 {
 	/* Response type byte is the second byte in the response. */
-	unsigned char rtype = ((unsigned char *) reply->message)[1];
+	unsigned char rtype = ((unsigned char *) reply->msg)[1];
 
 	switch (rtype) {
 	case TYPE82_RSP_CODE:
@@ -393,15 +404,15 @@
 				      outputdata, outputdatalength);
 	default: /* Unknown response type, this should NEVER EVER happen */
 		zq->online = 0;
-		pr_err("Cryptographic device %02x.%04x failed and was set offline\n",
+		pr_err("Crypto dev=%02x.%04x unknown response type 0x%02x => online=0 rc=EAGAIN\n",
 		       AP_QID_CARD(zq->queue->qid),
-		       AP_QID_QUEUE(zq->queue->qid));
-		ZCRYPT_DBF(DBF_ERR,
-			   "device=%02x.%04x rtype=0x%02x => online=0 rc=EAGAIN\n",
-			   AP_QID_CARD(zq->queue->qid),
-			   AP_QID_QUEUE(zq->queue->qid),
-			   (unsigned int) rtype);
-		return -EAGAIN;	/* repeat the request on a different device. */
+		       AP_QID_QUEUE(zq->queue->qid),
+		       (int) rtype);
+		ZCRYPT_DBF_ERR("dev=%02x.%04x unknown response type 0x%02x => online=0 rc=EAGAIN\n",
+			       AP_QID_CARD(zq->queue->qid),
+			       AP_QID_QUEUE(zq->queue->qid),
+			       (int) rtype);
+		return -EAGAIN;
 	}
 }
 
@@ -422,22 +433,22 @@
 		.reply_code = REP82_ERROR_MACHINE_FAILURE,
 	};
 	struct type80_hdr *t80h;
-	int length;
+	int len;
 
 	/* Copy the reply message to the request message buffer. */
 	if (!reply)
 		goto out;	/* ap_msg->rc indicates the error */
-	t80h = reply->message;
+	t80h = reply->msg;
 	if (t80h->type == TYPE80_RSP_CODE) {
-		if (aq->ap_dev.device_type == AP_DEVICE_TYPE_CEX2A)
-			length = min_t(int,
-				       CEX2A_MAX_RESPONSE_SIZE, t80h->len);
-		else
-			length = min_t(int,
-				       CEX3A_MAX_RESPONSE_SIZE, t80h->len);
-		memcpy(msg->message, reply->message, length);
+		len = t80h->len;
+		if (len > reply->bufsize || len > msg->bufsize) {
+			msg->rc = -EMSGSIZE;
+		} else {
+			memcpy(msg->msg, reply->msg, len);
+			msg->len = len;
+		}
 	} else
-		memcpy(msg->message, reply->message, sizeof(error_reply));
+		memcpy(msg->msg, reply->msg, sizeof(error_reply));
 out:
 	complete((struct completion *) msg->private);
 }
@@ -452,41 +463,40 @@
  * @mex: pointer to the modexpo request buffer
  */
 static long zcrypt_cex2a_modexpo(struct zcrypt_queue *zq,
-				 struct ica_rsa_modexpo *mex)
+				 struct ica_rsa_modexpo *mex,
+				 struct ap_message *ap_msg)
 {
-	struct ap_message ap_msg;
 	struct completion work;
 	int rc;
 
-	ap_init_message(&ap_msg);
-	if (zq->zcard->user_space_type == ZCRYPT_CEX2A)
-		ap_msg.message = kmalloc(MSGTYPE50_CRB2_MAX_MSG_SIZE,
-					 GFP_KERNEL);
-	else
-		ap_msg.message = kmalloc(MSGTYPE50_CRB3_MAX_MSG_SIZE,
-					 GFP_KERNEL);
-	if (!ap_msg.message)
+	ap_msg->bufsize = (zq->zcard->user_space_type == ZCRYPT_CEX2A) ?
+		MSGTYPE50_CRB2_MAX_MSG_SIZE : MSGTYPE50_CRB3_MAX_MSG_SIZE;
+	ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
+	if (!ap_msg->msg)
 		return -ENOMEM;
-	ap_msg.receive = zcrypt_cex2a_receive;
-	ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
-				atomic_inc_return(&zcrypt_step);
-	ap_msg.private = &work;
-	rc = ICAMEX_msg_to_type50MEX_msg(zq, &ap_msg, mex);
+	ap_msg->receive = zcrypt_cex2a_receive;
+	ap_msg->psmid = (((unsigned long long) current->pid) << 32) +
+		atomic_inc_return(&zcrypt_step);
+	ap_msg->private = &work;
+	rc = ICAMEX_msg_to_type50MEX_msg(zq, ap_msg, mex);
 	if (rc)
-		goto out_free;
+		goto out;
 	init_completion(&work);
-	ap_queue_message(zq->queue, &ap_msg);
+	rc = ap_queue_message(zq->queue, ap_msg);
+	if (rc)
+		goto out;
 	rc = wait_for_completion_interruptible(&work);
 	if (rc == 0) {
-		rc = ap_msg.rc;
+		rc = ap_msg->rc;
 		if (rc == 0)
-			rc = convert_response(zq, &ap_msg, mex->outputdata,
-					      mex->outputdatalength);
+			rc = convert_response_cex2a(zq, ap_msg,
+						    mex->outputdata,
+						    mex->outputdatalength);
 	} else
 		/* Signal pending. */
-		ap_cancel_message(zq->queue, &ap_msg);
-out_free:
-	kfree(ap_msg.message);
+		ap_cancel_message(zq->queue, ap_msg);
+out:
+	ap_msg->private = NULL;
 	return rc;
 }
 
@@ -498,41 +508,40 @@
  * @crt: pointer to the modexpoc_crt request buffer
  */
 static long zcrypt_cex2a_modexpo_crt(struct zcrypt_queue *zq,
-				     struct ica_rsa_modexpo_crt *crt)
+				     struct ica_rsa_modexpo_crt *crt,
+				     struct ap_message *ap_msg)
 {
-	struct ap_message ap_msg;
 	struct completion work;
 	int rc;
 
-	ap_init_message(&ap_msg);
-	if (zq->zcard->user_space_type == ZCRYPT_CEX2A)
-		ap_msg.message = kmalloc(MSGTYPE50_CRB2_MAX_MSG_SIZE,
-					 GFP_KERNEL);
-	else
-		ap_msg.message = kmalloc(MSGTYPE50_CRB3_MAX_MSG_SIZE,
-					 GFP_KERNEL);
-	if (!ap_msg.message)
+	ap_msg->bufsize = (zq->zcard->user_space_type == ZCRYPT_CEX2A) ?
+		MSGTYPE50_CRB2_MAX_MSG_SIZE : MSGTYPE50_CRB3_MAX_MSG_SIZE;
+	ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
+	if (!ap_msg->msg)
 		return -ENOMEM;
-	ap_msg.receive = zcrypt_cex2a_receive;
-	ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
-				atomic_inc_return(&zcrypt_step);
-	ap_msg.private = &work;
-	rc = ICACRT_msg_to_type50CRT_msg(zq, &ap_msg, crt);
+	ap_msg->receive = zcrypt_cex2a_receive;
+	ap_msg->psmid = (((unsigned long long) current->pid) << 32) +
+		atomic_inc_return(&zcrypt_step);
+	ap_msg->private = &work;
+	rc = ICACRT_msg_to_type50CRT_msg(zq, ap_msg, crt);
 	if (rc)
-		goto out_free;
+		goto out;
 	init_completion(&work);
-	ap_queue_message(zq->queue, &ap_msg);
+	rc = ap_queue_message(zq->queue, ap_msg);
+	if (rc)
+		goto out;
 	rc = wait_for_completion_interruptible(&work);
 	if (rc == 0) {
-		rc = ap_msg.rc;
+		rc = ap_msg->rc;
 		if (rc == 0)
-			rc = convert_response(zq, &ap_msg, crt->outputdata,
-					      crt->outputdatalength);
+			rc = convert_response_cex2a(zq, ap_msg,
+						    crt->outputdata,
+						    crt->outputdatalength);
 	} else
 		/* Signal pending. */
-		ap_cancel_message(zq->queue, &ap_msg);
-out_free:
-	kfree(ap_msg.message);
+		ap_cancel_message(zq->queue, ap_msg);
+out:
+	ap_msg->private = NULL;
 	return rc;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/crypto/zcrypt_msgtype6.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/crypto/zcrypt_msgtype6.c
@@ -266,7 +266,7 @@
 		struct function_and_rules_block fr;
 		unsigned short length;
 		char text[0];
-	} __packed * msg = ap_msg->message;
+	} __packed * msg = ap_msg->msg;
 	int size;
 
 	/*
@@ -301,7 +301,7 @@
 
 	msg->cprbx.req_parml = size - sizeof(msg->hdr) - sizeof(msg->cprbx);
 
-	ap_msg->length = size;
+	ap_msg->len = size;
 	return 0;
 }
 
@@ -336,7 +336,7 @@
 		struct function_and_rules_block fr;
 		unsigned short length;
 		char text[0];
-	} __packed * msg = ap_msg->message;
+	} __packed * msg = ap_msg->msg;
 	int size;
 
 	/*
@@ -370,7 +370,7 @@
 
 	msg->fr = static_pkd_fnr;
 
-	ap_msg->length = size;
+	ap_msg->len = size;
 	return 0;
 }
 
@@ -388,7 +388,7 @@
 	struct type86_fmt2_ext fmt2;
 } __packed;
 
-static int XCRB_msg_to_type6CPRB_msgX(struct ap_message *ap_msg,
+static int XCRB_msg_to_type6CPRB_msgX(bool userspace, struct ap_message *ap_msg,
 				      struct ica_xcRB *xcRB,
 				      unsigned int *fcode,
 				      unsigned short **dom)
@@ -400,11 +400,11 @@
 	struct {
 		struct type6_hdr hdr;
 		struct CPRBX cprbx;
-	} __packed * msg = ap_msg->message;
+	} __packed * msg = ap_msg->msg;
 
 	int rcblen = CEIL4(xcRB->request_control_blk_length);
-	int replylen, req_sumlen, resp_sumlen;
-	char *req_data = ap_msg->message + sizeof(struct type6_hdr) + rcblen;
+	int req_sumlen, resp_sumlen;
+	char *req_data = ap_msg->msg + sizeof(struct type6_hdr) + rcblen;
 	char *function_code;
 
 	if (CEIL4(xcRB->request_control_blk_length) <
@@ -412,10 +412,10 @@
 		return -EINVAL; /* overflow after alignment*/
 
 	/* length checks */
-	ap_msg->length = sizeof(struct type6_hdr) +
+	ap_msg->len = sizeof(struct type6_hdr) +
 		CEIL4(xcRB->request_control_blk_length) +
 		xcRB->request_data_length;
-	if (ap_msg->length > MSGTYPE06_MAX_MSG_SIZE)
+	if (ap_msg->len > ap_msg->bufsize)
 		return -EINVAL;
 
 	/*
@@ -435,12 +435,6 @@
 			xcRB->reply_control_blk_length)
 		return -EINVAL; /* overflow after alignment*/
 
-	replylen = sizeof(struct type86_fmt2_msg) +
-		CEIL4(xcRB->reply_control_blk_length) +
-		xcRB->reply_data_length;
-	if (replylen > MSGTYPE06_MAX_MSG_SIZE)
-		return -EINVAL;
-
 	/*
 	 * Overflow check
 	 * sum must be greater (or equal) than the largest operand
@@ -465,8 +459,8 @@
 	msg->hdr.FromCardLen2 = xcRB->reply_data_length;
 
 	/* prepare CPRB */
-	if (copy_from_user(&(msg->cprbx), xcRB->request_control_blk_addr,
-		    xcRB->request_control_blk_length))
+	if (z_copy_from_user(userspace, &(msg->cprbx), xcRB->request_control_blk_addr,
+			     xcRB->request_control_blk_length))
 		return -EFAULT;
 	if (msg->cprbx.cprb_len + sizeof(msg->hdr.function_code) >
 	    xcRB->request_control_blk_length)
@@ -480,22 +474,25 @@
 
 	if (memcmp(function_code, "US", 2) == 0
 	    || memcmp(function_code, "AU", 2) == 0)
-		ap_msg->special = 1;
-	else
-		ap_msg->special = 0;
+		ap_msg->flags |= AP_MSG_FLAG_SPECIAL;
+
+#ifdef CONFIG_ZCRYPT_DEBUG
+	if (ap_msg->fi.flags & AP_FI_FLAG_TOGGLE_SPECIAL)
+		ap_msg->flags ^= AP_MSG_FLAG_SPECIAL;
+#endif
 
 	/* copy data block */
 	if (xcRB->request_data_length &&
-	    copy_from_user(req_data, xcRB->request_data_address,
-		xcRB->request_data_length))
+	    z_copy_from_user(userspace, req_data, xcRB->request_data_address,
+			     xcRB->request_data_length))
 		return -EFAULT;
 
 	return 0;
 }
 
-static int xcrb_msg_to_type6_ep11cprb_msgx(struct ap_message *ap_msg,
-				       struct ep11_urb *xcRB,
-				       unsigned int *fcode)
+static int xcrb_msg_to_type6_ep11cprb_msgx(bool userspace, struct ap_message *ap_msg,
+					   struct ep11_urb *xcRB,
+					   unsigned int *fcode)
 {
 	unsigned int lfmt;
 	static struct type6_hdr static_type6_ep11_hdr = {
@@ -512,7 +509,7 @@
 		struct ep11_cprb cprbx;
 		unsigned char	pld_tag;	/* fixed value 0x30 */
 		unsigned char	pld_lenfmt;	/* payload length format */
-	} __packed * msg = ap_msg->message;
+	} __packed * msg = ap_msg->msg;
 
 	struct pld_hdr {
 		unsigned char	func_tag;	/* fixed value 0x4 */
@@ -527,26 +524,21 @@
 		return -EINVAL; /* overflow after alignment*/
 
 	/* length checks */
-	ap_msg->length = sizeof(struct type6_hdr) + xcRB->req_len;
-	if (CEIL4(xcRB->req_len) > MSGTYPE06_MAX_MSG_SIZE -
-				   (sizeof(struct type6_hdr)))
+	ap_msg->len = sizeof(struct type6_hdr) + CEIL4(xcRB->req_len);
+	if (ap_msg->len > ap_msg->bufsize)
 		return -EINVAL;
 
 	if (CEIL4(xcRB->resp_len) < xcRB->resp_len)
 		return -EINVAL; /* overflow after alignment*/
 
-	if (CEIL4(xcRB->resp_len) > MSGTYPE06_MAX_MSG_SIZE -
-				    (sizeof(struct type86_fmt2_msg)))
-		return -EINVAL;
-
 	/* prepare type6 header */
 	msg->hdr = static_type6_ep11_hdr;
 	msg->hdr.ToCardLen1   = xcRB->req_len;
 	msg->hdr.FromCardLen1 = xcRB->resp_len;
 
 	/* Import CPRB data from the ioctl input parameter */
-	if (copy_from_user(&(msg->cprbx.cprb_len),
-			   (char __force __user *)xcRB->req, xcRB->req_len)) {
+	if (z_copy_from_user(userspace, &(msg->cprbx.cprb_len),
+			     (char __force __user *)xcRB->req, xcRB->req_len)) {
 		return -EFAULT;
 	}
 
@@ -569,7 +561,12 @@
 
 	/* enable special processing based on the cprbs flags special bit */
 	if (msg->cprbx.flags & 0x20)
-		ap_msg->special = 1;
+		ap_msg->flags |= AP_MSG_FLAG_SPECIAL;
+
+#ifdef CONFIG_ZCRYPT_DEBUG
+	if (ap_msg->fi.flags & AP_FI_FLAG_TOGGLE_SPECIAL)
+		ap_msg->flags ^= AP_MSG_FLAG_SPECIAL;
+#endif
 
 	return 0;
 }
@@ -590,7 +587,7 @@
 	struct CPRBX cprbx;
 	unsigned char pad[4];	/* 4 byte function code/rules block ? */
 	unsigned short length;
-	char text[0];
+	char text[];
 } __packed;
 
 struct type86_ep11_reply {
@@ -639,7 +636,7 @@
 		0x35, 0x9D, 0xD3, 0xD3, 0xA7, 0x9D, 0x5D, 0x41,
 		0x6F, 0x65, 0x1B, 0xCF, 0xA9, 0x87, 0x91, 0x09
 	};
-	struct type86x_reply *msg = reply->message;
+	struct type86x_reply *msg = reply->msg;
 	unsigned short service_rc, service_rs;
 	unsigned int reply_len, pad_len;
 	char *data;
@@ -652,23 +649,22 @@
 		    (service_rc == 8 && service_rs == 72) ||
 		    (service_rc == 8 && service_rs == 770) ||
 		    (service_rc == 12 && service_rs == 769)) {
-			ZCRYPT_DBF(DBF_DEBUG,
-				   "device=%02x.%04x rc/rs=%d/%d => rc=EINVAL\n",
-				   AP_QID_CARD(zq->queue->qid),
-				   AP_QID_QUEUE(zq->queue->qid),
-				   (int) service_rc, (int) service_rs);
+			ZCRYPT_DBF_WARN("dev=%02x.%04x rc/rs=%d/%d => rc=EINVAL\n",
+					AP_QID_CARD(zq->queue->qid),
+					AP_QID_QUEUE(zq->queue->qid),
+					(int) service_rc, (int) service_rs);
 			return -EINVAL;
 		}
 		zq->online = 0;
-		pr_err("Cryptographic device %02x.%04x failed and was set offline\n",
+		pr_err("Crypto dev=%02x.%04x rc/rs=%d/%d online=0 rc=EAGAIN\n",
 		       AP_QID_CARD(zq->queue->qid),
-		       AP_QID_QUEUE(zq->queue->qid));
-		ZCRYPT_DBF(DBF_ERR,
-			   "device=%02x.%04x rc/rs=%d/%d => online=0 rc=EAGAIN\n",
-			   AP_QID_CARD(zq->queue->qid),
-			   AP_QID_QUEUE(zq->queue->qid),
-			   (int) service_rc, (int) service_rs);
-		return -EAGAIN;	/* repeat the request on a different device. */
+		       AP_QID_QUEUE(zq->queue->qid),
+		       (int) service_rc, (int) service_rs);
+		ZCRYPT_DBF_ERR("dev=%02x.%04x rc/rs=%d/%d => online=0 rc=EAGAIN\n",
+			       AP_QID_CARD(zq->queue->qid),
+			       AP_QID_QUEUE(zq->queue->qid),
+			       (int) service_rc, (int) service_rs);
+		return -EAGAIN;
 	}
 	data = msg->text;
 	reply_len = msg->length - 2;
@@ -709,23 +705,23 @@
  *
  * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
  */
-static int convert_type86_xcrb(struct zcrypt_queue *zq,
+static int convert_type86_xcrb(bool userspace, struct zcrypt_queue *zq,
 			       struct ap_message *reply,
 			       struct ica_xcRB *xcRB)
 {
-	struct type86_fmt2_msg *msg = reply->message;
-	char *data = reply->message;
+	struct type86_fmt2_msg *msg = reply->msg;
+	char *data = reply->msg;
 
 	/* Copy CPRB to user */
-	if (copy_to_user(xcRB->reply_control_blk_addr,
-		data + msg->fmt2.offset1, msg->fmt2.count1))
+	if (z_copy_to_user(userspace, xcRB->reply_control_blk_addr,
+			   data + msg->fmt2.offset1, msg->fmt2.count1))
 		return -EFAULT;
 	xcRB->reply_control_blk_length = msg->fmt2.count1;
 
 	/* Copy data buffer to user */
 	if (msg->fmt2.count2)
-		if (copy_to_user(xcRB->reply_data_addr,
-			data + msg->fmt2.offset2, msg->fmt2.count2))
+		if (z_copy_to_user(userspace, xcRB->reply_data_addr,
+				   data + msg->fmt2.offset2, msg->fmt2.count2))
 			return -EFAULT;
 	xcRB->reply_data_length = msg->fmt2.count2;
 	return 0;
@@ -740,19 +736,19 @@
  *
  * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
  */
-static int convert_type86_ep11_xcrb(struct zcrypt_queue *zq,
+static int convert_type86_ep11_xcrb(bool userspace, struct zcrypt_queue *zq,
 				    struct ap_message *reply,
 				    struct ep11_urb *xcRB)
 {
-	struct type86_fmt2_msg *msg = reply->message;
-	char *data = reply->message;
+	struct type86_fmt2_msg *msg = reply->msg;
+	char *data = reply->msg;
 
 	if (xcRB->resp_len < msg->fmt2.count1)
 		return -EINVAL;
 
 	/* Copy response CPRB to user */
-	if (copy_to_user((char __force __user *)xcRB->resp,
-			 data + msg->fmt2.offset1, msg->fmt2.count1))
+	if (z_copy_to_user(userspace, (char __force __user *)xcRB->resp,
+			   data + msg->fmt2.offset1, msg->fmt2.count1))
 		return -EFAULT;
 	xcRB->resp_len = msg->fmt2.count1;
 	return 0;
@@ -766,8 +762,8 @@
 		struct type86_hdr hdr;
 		struct type86_fmt2_ext fmt2;
 		struct CPRBX cprbx;
-	} __packed * msg = reply->message;
-	char *data = reply->message;
+	} __packed * msg = reply->msg;
+	char *data = reply->msg;
 
 	if (msg->cprbx.ccp_rtcode != 0 || msg->cprbx.ccp_rscode != 0)
 		return -EINVAL;
@@ -780,7 +776,7 @@
 			    char __user *outputdata,
 			    unsigned int outputdatalength)
 {
-	struct type86x_reply *msg = reply->message;
+	struct type86x_reply *msg = reply->msg;
 
 	switch (msg->hdr.type) {
 	case TYPE82_RSP_CODE:
@@ -801,26 +797,27 @@
 		if (msg->cprbx.cprb_ver_id == 0x02)
 			return convert_type86_ica(zq, reply,
 						  outputdata, outputdatalength);
-		/* fall through - wrong cprb version is an unknown response */
-	default: /* Unknown response type, this should NEVER EVER happen */
+		fallthrough;	/* wrong cprb version is an unknown response */
+	default:
+		/* Unknown response type, this should NEVER EVER happen */
 		zq->online = 0;
-		pr_err("Cryptographic device %02x.%04x failed and was set offline\n",
+		pr_err("Crypto dev=%02x.%04x unknown response type 0x%02x => online=0 rc=EAGAIN\n",
 		       AP_QID_CARD(zq->queue->qid),
-		       AP_QID_QUEUE(zq->queue->qid));
-		ZCRYPT_DBF(DBF_ERR,
-			   "device=%02x.%04x rtype=0x%02x => online=0 rc=EAGAIN\n",
-			   AP_QID_CARD(zq->queue->qid),
-			   AP_QID_QUEUE(zq->queue->qid),
-			   (int) msg->hdr.type);
-		return -EAGAIN;	/* repeat the request on a different device. */
+		       AP_QID_QUEUE(zq->queue->qid),
+		       (int) msg->hdr.type);
+		ZCRYPT_DBF_ERR("dev=%02x.%04x unknown response type 0x%02x => online=0 rc=EAGAIN\n",
+			       AP_QID_CARD(zq->queue->qid),
+			       AP_QID_QUEUE(zq->queue->qid),
+			       (int) msg->hdr.type);
+		return -EAGAIN;
 	}
 }
 
-static int convert_response_xcrb(struct zcrypt_queue *zq,
-			    struct ap_message *reply,
-			    struct ica_xcRB *xcRB)
+static int convert_response_xcrb(bool userspace, struct zcrypt_queue *zq,
+				 struct ap_message *reply,
+				 struct ica_xcRB *xcRB)
 {
-	struct type86x_reply *msg = reply->message;
+	struct type86x_reply *msg = reply->msg;
 
 	switch (msg->hdr.type) {
 	case TYPE82_RSP_CODE:
@@ -833,27 +830,27 @@
 			return convert_error(zq, reply);
 		}
 		if (msg->cprbx.cprb_ver_id == 0x02)
-			return convert_type86_xcrb(zq, reply, xcRB);
-		/* fall through - wrong cprb version is an unknown response */
+			return convert_type86_xcrb(userspace, zq, reply, xcRB);
+		fallthrough;	/* wrong cprb version is an unknown response */
 	default: /* Unknown response type, this should NEVER EVER happen */
 		xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
 		zq->online = 0;
-		pr_err("Cryptographic device %02x.%04x failed and was set offline\n",
+		pr_err("Crypto dev=%02x.%04x unknown response type 0x%02x => online=0 rc=EAGAIN\n",
 		       AP_QID_CARD(zq->queue->qid),
-		       AP_QID_QUEUE(zq->queue->qid));
-		ZCRYPT_DBF(DBF_ERR,
-			   "device=%02x.%04x rtype=0x%02x => online=0 rc=EAGAIN\n",
-			   AP_QID_CARD(zq->queue->qid),
-			   AP_QID_QUEUE(zq->queue->qid),
-			   (int) msg->hdr.type);
-		return -EAGAIN;	/* repeat the request on a different device. */
+		       AP_QID_QUEUE(zq->queue->qid),
+		       (int) msg->hdr.type);
+		ZCRYPT_DBF_ERR("dev=%02x.%04x unknown response type 0x%02x => online=0 rc=EAGAIN\n",
+			       AP_QID_CARD(zq->queue->qid),
+			       AP_QID_QUEUE(zq->queue->qid),
+			       (int) msg->hdr.type);
+		return -EAGAIN;
 	}
 }
 
-static int convert_response_ep11_xcrb(struct zcrypt_queue *zq,
-	struct ap_message *reply, struct ep11_urb *xcRB)
+static int convert_response_ep11_xcrb(bool userspace, struct zcrypt_queue *zq,
+				      struct ap_message *reply, struct ep11_urb *xcRB)
 {
-	struct type86_ep11_reply *msg = reply->message;
+	struct type86_ep11_reply *msg = reply->msg;
 
 	switch (msg->hdr.type) {
 	case TYPE82_RSP_CODE:
@@ -863,19 +860,19 @@
 		if (msg->hdr.reply_code)
 			return convert_error(zq, reply);
 		if (msg->cprbx.cprb_ver_id == 0x04)
-			return convert_type86_ep11_xcrb(zq, reply, xcRB);
-		/* fall through - wrong cprb version is an unknown resp */
+			return convert_type86_ep11_xcrb(userspace, zq, reply, xcRB);
+		fallthrough;	/* wrong cprb version is an unknown resp */
 	default: /* Unknown response type, this should NEVER EVER happen */
 		zq->online = 0;
-		pr_err("Cryptographic device %02x.%04x failed and was set offline\n",
+		pr_err("Crypto dev=%02x.%04x unknown response type 0x%02x => online=0 rc=EAGAIN\n",
 		       AP_QID_CARD(zq->queue->qid),
-		       AP_QID_QUEUE(zq->queue->qid));
-		ZCRYPT_DBF(DBF_ERR,
-			   "device=%02x.%04x rtype=0x%02x => online=0 rc=EAGAIN\n",
-			   AP_QID_CARD(zq->queue->qid),
-			   AP_QID_QUEUE(zq->queue->qid),
-			   (int) msg->hdr.type);
-		return -EAGAIN; /* repeat the request on a different device. */
+		       AP_QID_QUEUE(zq->queue->qid),
+		       (int) msg->hdr.type);
+		ZCRYPT_DBF_ERR("dev=%02x.%04x unknown response type 0x%02x => online=0 rc=EAGAIN\n",
+			       AP_QID_CARD(zq->queue->qid),
+			       AP_QID_QUEUE(zq->queue->qid),
+			       (int) msg->hdr.type);
+		return -EAGAIN;
 	}
 }
 
@@ -883,7 +880,7 @@
 				 struct ap_message *reply,
 				 char *data)
 {
-	struct type86x_reply *msg = reply->message;
+	struct type86x_reply *msg = reply->msg;
 
 	switch (msg->hdr.type) {
 	case TYPE82_RSP_CODE:
@@ -894,18 +891,18 @@
 			return -EINVAL;
 		if (msg->cprbx.cprb_ver_id == 0x02)
 			return convert_type86_rng(zq, reply, data);
-		/* fall through - wrong cprb version is an unknown response */
+		fallthrough;	/* wrong cprb version is an unknown response */
 	default: /* Unknown response type, this should NEVER EVER happen */
 		zq->online = 0;
-		pr_err("Cryptographic device %02x.%04x failed and was set offline\n",
+		pr_err("Crypto dev=%02x.%04x unknown response type 0x%02x => online=0 rc=EAGAIN\n",
 		       AP_QID_CARD(zq->queue->qid),
-		       AP_QID_QUEUE(zq->queue->qid));
-		ZCRYPT_DBF(DBF_ERR,
-			   "device=%02x.%04x rtype=0x%02x => online=0 rc=EAGAIN\n",
-			   AP_QID_CARD(zq->queue->qid),
-			   AP_QID_QUEUE(zq->queue->qid),
-			   (int) msg->hdr.type);
-		return -EAGAIN;	/* repeat the request on a different device. */
+		       AP_QID_QUEUE(zq->queue->qid),
+		       (int) msg->hdr.type);
+		ZCRYPT_DBF_ERR("dev=%02x.%04x unknown response type 0x%02x => online=0 rc=EAGAIN\n",
+			       AP_QID_CARD(zq->queue->qid),
+			       AP_QID_QUEUE(zq->queue->qid),
+			       (int) msg->hdr.type);
+		return -EAGAIN;
 	}
 }
 
@@ -928,32 +925,38 @@
 	struct response_type *resp_type =
 		(struct response_type *) msg->private;
 	struct type86x_reply *t86r;
-	int length;
+	int len;
 
 	/* Copy the reply message to the request message buffer. */
 	if (!reply)
 		goto out;	/* ap_msg->rc indicates the error */
-	t86r = reply->message;
+	t86r = reply->msg;
 	if (t86r->hdr.type == TYPE86_RSP_CODE &&
 		 t86r->cprbx.cprb_ver_id == 0x02) {
 		switch (resp_type->type) {
 		case CEXXC_RESPONSE_TYPE_ICA:
-			length = sizeof(struct type86x_reply)
-				+ t86r->length - 2;
-			length = min(CEXXC_MAX_ICA_RESPONSE_SIZE, length);
-			memcpy(msg->message, reply->message, length);
+			len = sizeof(struct type86x_reply) + t86r->length - 2;
+			if (len > reply->bufsize || len > msg->bufsize) {
+				msg->rc = -EMSGSIZE;
+			} else {
+				memcpy(msg->msg, reply->msg, len);
+				msg->len = len;
+			}
 			break;
 		case CEXXC_RESPONSE_TYPE_XCRB:
-			length = t86r->fmt2.offset2 + t86r->fmt2.count2;
-			length = min(MSGTYPE06_MAX_MSG_SIZE, length);
-			memcpy(msg->message, reply->message, length);
+			len = t86r->fmt2.offset2 + t86r->fmt2.count2;
+			if (len > reply->bufsize || len > msg->bufsize) {
+				msg->rc = -EMSGSIZE;
+			} else {
+				memcpy(msg->msg, reply->msg, len);
+				msg->len = len;
+			}
 			break;
 		default:
-			memcpy(msg->message, &error_reply,
-			       sizeof(error_reply));
+			memcpy(msg->msg, &error_reply, sizeof(error_reply));
 		}
 	} else
-		memcpy(msg->message, reply->message, sizeof(error_reply));
+		memcpy(msg->msg, reply->msg, sizeof(error_reply));
 out:
 	complete(&(resp_type->work));
 }
@@ -977,25 +980,29 @@
 	struct response_type *resp_type =
 		(struct response_type *)msg->private;
 	struct type86_ep11_reply *t86r;
-	int length;
+	int len;
 
 	/* Copy the reply message to the request message buffer. */
 	if (!reply)
 		goto out;	/* ap_msg->rc indicates the error */
-	t86r = reply->message;
+	t86r = reply->msg;
 	if (t86r->hdr.type == TYPE86_RSP_CODE &&
 	    t86r->cprbx.cprb_ver_id == 0x04) {
 		switch (resp_type->type) {
 		case CEXXC_RESPONSE_TYPE_EP11:
-			length = t86r->fmt2.offset1 + t86r->fmt2.count1;
-			length = min(MSGTYPE06_MAX_MSG_SIZE, length);
-			memcpy(msg->message, reply->message, length);
+			len = t86r->fmt2.offset1 + t86r->fmt2.count1;
+			if (len > reply->bufsize || len > msg->bufsize) {
+				msg->rc = -EMSGSIZE;
+			} else {
+				memcpy(msg->msg, reply->msg, len);
+				msg->len = len;
+			}
 			break;
 		default:
-			memcpy(msg->message, &error_reply, sizeof(error_reply));
+			memcpy(msg->msg, &error_reply, sizeof(error_reply));
 		}
 	} else {
-		memcpy(msg->message, reply->message, sizeof(error_reply));
+		memcpy(msg->msg, reply->msg, sizeof(error_reply));
 	}
 out:
 	complete(&(resp_type->work));
@@ -1011,39 +1018,43 @@
  * @mex: pointer to the modexpo request buffer
  */
 static long zcrypt_msgtype6_modexpo(struct zcrypt_queue *zq,
-				  struct ica_rsa_modexpo *mex)
+				    struct ica_rsa_modexpo *mex,
+				    struct ap_message *ap_msg)
 {
-	struct ap_message ap_msg;
 	struct response_type resp_type = {
 		.type = CEXXC_RESPONSE_TYPE_ICA,
 	};
 	int rc;
 
-	ap_init_message(&ap_msg);
-	ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
-	if (!ap_msg.message)
+	ap_msg->msg = (void *) get_zeroed_page(GFP_KERNEL);
+	if (!ap_msg->msg)
 		return -ENOMEM;
-	ap_msg.receive = zcrypt_msgtype6_receive;
-	ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
-				atomic_inc_return(&zcrypt_step);
-	ap_msg.private = &resp_type;
-	rc = ICAMEX_msg_to_type6MEX_msgX(zq, &ap_msg, mex);
+	ap_msg->bufsize = PAGE_SIZE;
+	ap_msg->receive = zcrypt_msgtype6_receive;
+	ap_msg->psmid = (((unsigned long long) current->pid) << 32) +
+		atomic_inc_return(&zcrypt_step);
+	ap_msg->private = &resp_type;
+	rc = ICAMEX_msg_to_type6MEX_msgX(zq, ap_msg, mex);
 	if (rc)
 		goto out_free;
 	init_completion(&resp_type.work);
-	ap_queue_message(zq->queue, &ap_msg);
+	rc = ap_queue_message(zq->queue, ap_msg);
+	if (rc)
+		goto out_free;
 	rc = wait_for_completion_interruptible(&resp_type.work);
 	if (rc == 0) {
-		rc = ap_msg.rc;
+		rc = ap_msg->rc;
 		if (rc == 0)
-			rc = convert_response_ica(zq, &ap_msg,
+			rc = convert_response_ica(zq, ap_msg,
 						  mex->outputdata,
 						  mex->outputdatalength);
 	} else
 		/* Signal pending. */
-		ap_cancel_message(zq->queue, &ap_msg);
+		ap_cancel_message(zq->queue, ap_msg);
 out_free:
-	free_page((unsigned long) ap_msg.message);
+	free_page((unsigned long) ap_msg->msg);
+	ap_msg->private = NULL;
+	ap_msg->msg = NULL;
 	return rc;
 }
 
@@ -1055,40 +1066,44 @@
  * @crt: pointer to the modexpoc_crt request buffer
  */
 static long zcrypt_msgtype6_modexpo_crt(struct zcrypt_queue *zq,
-				      struct ica_rsa_modexpo_crt *crt)
+					struct ica_rsa_modexpo_crt *crt,
+					struct ap_message *ap_msg)
 {
-	struct ap_message ap_msg;
 	struct response_type resp_type = {
 		.type = CEXXC_RESPONSE_TYPE_ICA,
 	};
 	int rc;
 
-	ap_init_message(&ap_msg);
-	ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
-	if (!ap_msg.message)
+	ap_msg->msg = (void *) get_zeroed_page(GFP_KERNEL);
+	if (!ap_msg->msg)
 		return -ENOMEM;
-	ap_msg.receive = zcrypt_msgtype6_receive;
-	ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
-				atomic_inc_return(&zcrypt_step);
-	ap_msg.private = &resp_type;
-	rc = ICACRT_msg_to_type6CRT_msgX(zq, &ap_msg, crt);
+	ap_msg->bufsize = PAGE_SIZE;
+	ap_msg->receive = zcrypt_msgtype6_receive;
+	ap_msg->psmid = (((unsigned long long) current->pid) << 32) +
+		atomic_inc_return(&zcrypt_step);
+	ap_msg->private = &resp_type;
+	rc = ICACRT_msg_to_type6CRT_msgX(zq, ap_msg, crt);
 	if (rc)
 		goto out_free;
 	init_completion(&resp_type.work);
-	ap_queue_message(zq->queue, &ap_msg);
+	rc = ap_queue_message(zq->queue, ap_msg);
+	if (rc)
+		goto out_free;
 	rc = wait_for_completion_interruptible(&resp_type.work);
 	if (rc == 0) {
-		rc = ap_msg.rc;
+		rc = ap_msg->rc;
 		if (rc == 0)
-			rc = convert_response_ica(zq, &ap_msg,
+			rc = convert_response_ica(zq, ap_msg,
 						  crt->outputdata,
 						  crt->outputdatalength);
 	} else {
 		/* Signal pending. */
-		ap_cancel_message(zq->queue, &ap_msg);
+		ap_cancel_message(zq->queue, ap_msg);
 	}
 out_free:
-	free_page((unsigned long) ap_msg.message);
+	free_page((unsigned long) ap_msg->msg);
+	ap_msg->private = NULL;
+	ap_msg->msg = NULL;
 	return rc;
 }
 
@@ -1099,16 +1114,17 @@
  * by the caller with ap_init_message(). Also the caller has to
  * make sure ap_release_message() is always called even on failure.
  */
-unsigned int get_cprb_fc(struct ica_xcRB *xcRB,
-				struct ap_message *ap_msg,
-				unsigned int *func_code, unsigned short **dom)
+unsigned int get_cprb_fc(bool userspace, struct ica_xcRB *xcRB,
+			 struct ap_message *ap_msg,
+			 unsigned int *func_code, unsigned short **dom)
 {
 	struct response_type resp_type = {
 		.type = CEXXC_RESPONSE_TYPE_XCRB,
 	};
 
-	ap_msg->message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL);
-	if (!ap_msg->message)
+	ap_msg->bufsize = atomic_read(&ap_max_msg_size);
+	ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
+	if (!ap_msg->msg)
 		return -ENOMEM;
 	ap_msg->receive = zcrypt_msgtype6_receive;
 	ap_msg->psmid = (((unsigned long long) current->pid) << 32) +
@@ -1116,7 +1132,7 @@
 	ap_msg->private = kmemdup(&resp_type, sizeof(resp_type), GFP_KERNEL);
 	if (!ap_msg->private)
 		return -ENOMEM;
-	return XCRB_msg_to_type6CPRB_msgX(ap_msg, xcRB, func_code, dom);
+	return XCRB_msg_to_type6CPRB_msgX(userspace, ap_msg, xcRB, func_code, dom);
 }
 
 /**
@@ -1126,24 +1142,26 @@
  *	CEXxC device to the request distributor
  * @xcRB: pointer to the send_cprb request buffer
  */
-static long zcrypt_msgtype6_send_cprb(struct zcrypt_queue *zq,
-				    struct ica_xcRB *xcRB,
-				    struct ap_message *ap_msg)
+static long zcrypt_msgtype6_send_cprb(bool userspace, struct zcrypt_queue *zq,
+				      struct ica_xcRB *xcRB,
+				      struct ap_message *ap_msg)
 {
 	int rc;
 	struct response_type *rtype = (struct response_type *)(ap_msg->private);
 
 	init_completion(&rtype->work);
-	ap_queue_message(zq->queue, ap_msg);
+	rc = ap_queue_message(zq->queue, ap_msg);
+	if (rc)
+		goto out;
 	rc = wait_for_completion_interruptible(&rtype->work);
 	if (rc == 0) {
 		rc = ap_msg->rc;
 		if (rc == 0)
-			rc = convert_response_xcrb(zq, ap_msg, xcRB);
+			rc = convert_response_xcrb(userspace, zq, ap_msg, xcRB);
 	} else
 		/* Signal pending. */
 		ap_cancel_message(zq->queue, ap_msg);
-
+out:
 	return rc;
 }
 
@@ -1154,16 +1172,17 @@
  * by the caller with ap_init_message(). Also the caller has to
  * make sure ap_release_message() is always called even on failure.
  */
-unsigned int get_ep11cprb_fc(struct ep11_urb *xcrb,
-				    struct ap_message *ap_msg,
-				    unsigned int *func_code)
+unsigned int get_ep11cprb_fc(bool userspace, struct ep11_urb *xcrb,
+			     struct ap_message *ap_msg,
+			     unsigned int *func_code)
 {
 	struct response_type resp_type = {
 		.type = CEXXC_RESPONSE_TYPE_EP11,
 	};
 
-	ap_msg->message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL);
-	if (!ap_msg->message)
+	ap_msg->bufsize = atomic_read(&ap_max_msg_size);
+	ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
+	if (!ap_msg->msg)
 		return -ENOMEM;
 	ap_msg->receive = zcrypt_msgtype6_receive_ep11;
 	ap_msg->psmid = (((unsigned long long) current->pid) << 32) +
@@ -1171,7 +1190,7 @@
 	ap_msg->private = kmemdup(&resp_type, sizeof(resp_type), GFP_KERNEL);
 	if (!ap_msg->private)
 		return -ENOMEM;
-	return xcrb_msg_to_type6_ep11cprb_msgx(ap_msg, xcrb, func_code);
+	return xcrb_msg_to_type6_ep11cprb_msgx(userspace, ap_msg, xcrb, func_code);
 }
 
 /**
@@ -1181,7 +1200,7 @@
  *	  CEX4P device to the request distributor
  * @xcRB: pointer to the ep11 user request block
  */
-static long zcrypt_msgtype6_send_ep11_cprb(struct zcrypt_queue *zq,
+static long zcrypt_msgtype6_send_ep11_cprb(bool userspace, struct zcrypt_queue *zq,
 					   struct ep11_urb *xcrb,
 					   struct ap_message *ap_msg)
 {
@@ -1193,7 +1212,7 @@
 		struct ep11_cprb cprbx;
 		unsigned char	pld_tag;	/* fixed value 0x30 */
 		unsigned char	pld_lenfmt;	/* payload length format */
-	} __packed * msg = ap_msg->message;
+	} __packed * msg = ap_msg->msg;
 	struct pld_hdr {
 		unsigned char	func_tag;	/* fixed value 0x4 */
 		unsigned char	func_len;	/* fixed value 0x4 */
@@ -1236,16 +1255,18 @@
 	}
 
 	init_completion(&rtype->work);
-	ap_queue_message(zq->queue, ap_msg);
+	rc = ap_queue_message(zq->queue, ap_msg);
+	if (rc)
+		goto out;
 	rc = wait_for_completion_interruptible(&rtype->work);
 	if (rc == 0) {
 		rc = ap_msg->rc;
 		if (rc == 0)
-			rc = convert_response_ep11_xcrb(zq, ap_msg, xcrb);
+			rc = convert_response_ep11_xcrb(userspace, zq, ap_msg, xcrb);
 	} else
 		/* Signal pending. */
 		ap_cancel_message(zq->queue, ap_msg);
-
+out:
 	return rc;
 }
 
@@ -1256,8 +1277,9 @@
 		.type = CEXXC_RESPONSE_TYPE_XCRB,
 	};
 
-	ap_msg->message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL);
-	if (!ap_msg->message)
+	ap_msg->bufsize = AP_DEFAULT_MAX_MSG_SIZE;
+	ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL);
+	if (!ap_msg->msg)
 		return -ENOMEM;
 	ap_msg->receive = zcrypt_msgtype6_receive;
 	ap_msg->psmid = (((unsigned long long) current->pid) << 32) +
@@ -1290,14 +1312,16 @@
 		char rule[8];
 		short int verb_length;
 		short int key_length;
-	} __packed * msg = ap_msg->message;
+	} __packed * msg = ap_msg->msg;
 	struct response_type *rtype = (struct response_type *)(ap_msg->private);
 	int rc;
 
 	msg->cprbx.domain = AP_QID_QUEUE(zq->queue->qid);
 
 	init_completion(&rtype->work);
-	ap_queue_message(zq->queue, ap_msg);
+	rc = ap_queue_message(zq->queue, ap_msg);
+	if (rc)
+		goto out;
 	rc = wait_for_completion_interruptible(&rtype->work);
 	if (rc == 0) {
 		rc = ap_msg->rc;
@@ -1306,7 +1330,7 @@
 	} else
 		/* Signal pending. */
 		ap_cancel_message(zq->queue, ap_msg);
-
+out:
 	return rc;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/crypto/zcrypt_msgtype6.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/crypto/zcrypt_msgtype6.h
@@ -19,8 +19,6 @@
 #define MSGTYPE06_VARIANT_NORNG		1
 #define MSGTYPE06_VARIANT_EP11		2
 
-#define MSGTYPE06_MAX_MSG_SIZE		(12*1024)
-
 /**
  * The type 6 message family is associated with CEXxC/CEXxP cards.
  *
@@ -96,9 +94,9 @@
 	unsigned int	  offset4;	/* 0x00000000			*/
 } __packed;
 
-unsigned int get_cprb_fc(struct ica_xcRB *, struct ap_message *,
+unsigned int get_cprb_fc(bool userspace, struct ica_xcRB *, struct ap_message *,
 			 unsigned int *, unsigned short **);
-unsigned int get_ep11cprb_fc(struct ep11_urb *, struct ap_message *,
+unsigned int get_ep11cprb_fc(bool userspace, struct ep11_urb *, struct ap_message *,
 			     unsigned int *);
 unsigned int get_rng_fc(struct ap_message *, int *, unsigned int *);
 
@@ -127,7 +125,7 @@
 		char rule[8];
 		short int verb_length;
 		short int key_length;
-	} __packed * msg = ap_msg->message;
+	} __packed * msg = ap_msg->msg;
 	static struct type6_hdr static_type6_hdrX = {
 		.type		= 0x06,
 		.offset1	= 0x00000058,
@@ -154,7 +152,7 @@
 	memcpy(msg->rule, "RANDOM  ", 8);
 	msg->verb_length = 0x02;
 	msg->key_length = 0x02;
-	ap_msg->length = sizeof(*msg);
+	ap_msg->len = sizeof(*msg);
 	*domain = (unsigned short)msg->cprbx.domain;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/crypto/zcrypt_queue.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/crypto/zcrypt_queue.c
@@ -40,22 +40,27 @@
 			   struct device_attribute *attr,
 			   char *buf)
 {
-	struct zcrypt_queue *zq = to_ap_queue(dev)->private;
+	struct ap_queue *aq = to_ap_queue(dev);
+	struct zcrypt_queue *zq = aq->private;
+	int online = aq->config && zq->online ? 1 : 0;
 
-	return snprintf(buf, PAGE_SIZE, "%d\n", zq->online);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", online);
 }
 
 static ssize_t online_store(struct device *dev,
 			    struct device_attribute *attr,
 			    const char *buf, size_t count)
 {
-	struct zcrypt_queue *zq = to_ap_queue(dev)->private;
+	struct ap_queue *aq = to_ap_queue(dev);
+	struct zcrypt_queue *zq = aq->private;
 	struct zcrypt_card *zc = zq->zcard;
 	int online;
 
 	if (sscanf(buf, "%d\n", &online) != 1 || online < 0 || online > 1)
 		return -EINVAL;
 
+	if (online && (!aq->config || !aq->card->config))
+		return -ENODEV;
 	if (online && !zc->online)
 		return -EINVAL;
 	zq->online = online;
@@ -78,7 +83,7 @@
 {
 	struct zcrypt_queue *zq = to_ap_queue(dev)->private;
 
-	return snprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&zq->load));
+	return scnprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&zq->load));
 }
 
 static DEVICE_ATTR_RO(load);
@@ -100,17 +105,17 @@
 		ap_flush_queue(zq->queue);
 }
 
-struct zcrypt_queue *zcrypt_queue_alloc(size_t max_response_size)
+struct zcrypt_queue *zcrypt_queue_alloc(size_t reply_buf_size)
 {
 	struct zcrypt_queue *zq;
 
 	zq = kzalloc(sizeof(struct zcrypt_queue), GFP_KERNEL);
 	if (!zq)
 		return NULL;
-	zq->reply.message = kmalloc(max_response_size, GFP_KERNEL);
-	if (!zq->reply.message)
+	zq->reply.msg = kmalloc(reply_buf_size, GFP_KERNEL);
+	if (!zq->reply.msg)
 		goto out_free;
-	zq->reply.length = max_response_size;
+	zq->reply.bufsize = reply_buf_size;
 	INIT_LIST_HEAD(&zq->list);
 	kref_init(&zq->refcount);
 	return zq;
@@ -123,7 +128,7 @@
 
 void zcrypt_queue_free(struct zcrypt_queue *zq)
 {
-	kfree(zq->reply.message);
+	kfree(zq->reply.msg);
 	kfree(zq);
 }
 EXPORT_SYMBOL(zcrypt_queue_free);
@@ -175,7 +180,6 @@
 				&zcrypt_queue_attr_group);
 	if (rc)
 		goto out;
-	get_device(&zq->queue->ap_dev.device);
 
 	if (zq->ops->rng) {
 		rc = zcrypt_rng_device_add();
@@ -187,7 +191,6 @@
 out_unregister:
 	sysfs_remove_group(&zq->queue->ap_dev.device.kobj,
 			   &zcrypt_queue_attr_group);
-	put_device(&zq->queue->ap_dev.device);
 out:
 	spin_lock(&zcrypt_list_lock);
 	list_del_init(&zq->list);
@@ -215,12 +218,11 @@
 	list_del_init(&zq->list);
 	zcrypt_device_count--;
 	spin_unlock(&zcrypt_list_lock);
-	zcrypt_card_put(zc);
 	if (zq->ops->rng)
 		zcrypt_rng_device_remove();
 	sysfs_remove_group(&zq->queue->ap_dev.device.kobj,
 			   &zcrypt_queue_attr_group);
-	put_device(&zq->queue->ap_dev.device);
+	zcrypt_card_put(zc);
 	zcrypt_queue_put(zq);
 }
 EXPORT_SYMBOL(zcrypt_queue_unregister);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/net/ctcm_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/net/ctcm_main.c
@@ -865,16 +865,9 @@
 /**
  * Start transmission of a packet.
  * Called from generic network device layer.
- *
- *  skb		Pointer to buffer containing the packet.
- *  dev		Pointer to interface struct.
- *
- * returns 0 if packet consumed, !0 if packet rejected.
- *         Note: If we return !0, then the packet is free'd by
- *               the generic network layer.
  */
 /* first merge version - leaving both functions separated */
-static int ctcm_tx(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t ctcm_tx(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ctcm_priv *priv = dev->ml_priv;
 
@@ -917,7 +910,7 @@
 }
 
 /* unmerged MPC variant of ctcm_tx */
-static int ctcmpc_tx(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t ctcmpc_tx(struct sk_buff *skb, struct net_device *dev)
 {
 	int len = 0;
 	struct ctcm_priv *priv = dev->ml_priv;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/net/ctcm_mpc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/net/ctcm_mpc.c
@@ -626,8 +626,6 @@
 		ctcm_clear_busy_do(dev);
 	}
 
-	kfree(mpcginfo);
-
 	return;
 
 }
@@ -1206,10 +1204,10 @@
 						CTCM_FUNTAIL, dev->name);
 			priv->stats.rx_dropped++;
 			/* mpcginfo only used for non-data transfers */
-			kfree(mpcginfo);
 			if (do_debug_data)
 				ctcmpc_dump_skb(pskb, -8);
 		}
+		kfree(mpcginfo);
 	}
 done:
 
@@ -1991,7 +1989,6 @@
 		}
 		break;
 	}
-	kfree(mpcginfo);
 
 	CTCM_PR_DEBUG("ctcmpc:%s() %s xid2:%i xid7:%i xidt_p2:%i \n",
 		__func__, ch->id, grp->outstanding_xid2,
@@ -2052,7 +2049,6 @@
 		mpc_validate_xid(mpcginfo);
 		break;
 	}
-	kfree(mpcginfo);
 	return;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/net/ctcm_sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/net/ctcm_sysfs.c
@@ -39,11 +39,12 @@
 	struct ctcm_priv *priv = dev_get_drvdata(dev);
 	int rc;
 
-	ndev = priv->channel[CTCM_READ]->netdev;
-	if (!(priv && priv->channel[CTCM_READ] && ndev)) {
+	if (!(priv && priv->channel[CTCM_READ] &&
+	      priv->channel[CTCM_READ]->netdev)) {
 		CTCM_DBF_TEXT(SETUP, CTC_DBF_ERROR, "bfnondev");
 		return -ENODEV;
 	}
+	ndev = priv->channel[CTCM_READ]->netdev;
 
 	rc = kstrtouint(buf, 0, &bs1);
 	if (rc)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/net/ism_drv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/net/ism_drv.c
@@ -521,8 +521,10 @@
 
 	ism->smcd = smcd_alloc_dev(&pdev->dev, dev_name(&pdev->dev), &ism_ops,
 				   ISM_NR_DMBS);
-	if (!ism->smcd)
+	if (!ism->smcd) {
+		ret = -ENOMEM;
 		goto err_resource;
+	}
 
 	ism->smcd->priv = ism;
 	ret = ism_dev_init(ism);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/net/lcs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/net/lcs.c
@@ -1518,9 +1518,8 @@
 /**
  * Packet transmit function called by network stack
  */
-static int
-__lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb,
-		 struct net_device *dev)
+static netdev_tx_t __lcs_start_xmit(struct lcs_card *card, struct sk_buff *skb,
+				    struct net_device *dev)
 {
 	struct lcs_header *header;
 	int rc = NETDEV_TX_OK;
@@ -1581,8 +1580,7 @@
 	return rc;
 }
 
-static int
-lcs_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t lcs_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct lcs_card *card;
 	int rc;
@@ -1735,10 +1733,11 @@
 			lcs_schedule_recovery(card);
 			break;
 		case LCS_CMD_STOPLAN:
-			pr_warn("Stoplan for %s initiated by LGW\n",
-				card->dev->name);
-			if (card->dev)
+			if (card->dev) {
+				pr_warn("Stoplan for %s initiated by LGW\n",
+					card->dev->name);
 				netif_carrier_off(card->dev);
+			}
 			break;
 		default:
 			LCS_DBF_TEXT(5, trace, "noLGWcmd");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/net/netiucv.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/net/netiucv.c
@@ -1344,15 +1344,8 @@
 /**
  * Start transmission of a packet.
  * Called from generic network device layer.
- *
- * @param skb Pointer to buffer containing the packet.
- * @param dev Pointer to interface struct.
- *
- * @return 0 if packet consumed, !0 if packet rejected.
- *         Note: If we return !0, then the packet is free'd by
- *               the generic network layer.
  */
-static int netiucv_tx(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t netiucv_tx(struct sk_buff *skb, struct net_device *dev)
 {
 	struct netiucv_priv *privptr = netdev_priv(dev);
 	int rc;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/net/qeth_core.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/net/qeth_core.h
@@ -436,10 +436,13 @@
 	QETH_QDIO_BUF_EMPTY,
 	/* Filled by driver; owned by hardware in order to be sent. */
 	QETH_QDIO_BUF_PRIMED,
-	/* Identified to be pending in TPQ. */
+	/* Discovered by the TX completion code: */
 	QETH_QDIO_BUF_PENDING,
-	/* Found in completion queue. */
-	QETH_QDIO_BUF_IN_CQ,
+	/* Finished by the TX completion code: */
+	QETH_QDIO_BUF_NEED_QAOB,
+	/* Received QAOB notification on CQ: */
+	QETH_QDIO_BUF_QAOB_OK,
+	QETH_QDIO_BUF_QAOB_ERROR,
 	/* Handled via transfer pending / completion queue. */
 	QETH_QDIO_BUF_HANDLED_DELAYED,
 };
@@ -532,6 +535,8 @@
 	struct timer_list timer;
 	struct qeth_hdr *prev_hdr;
 	u8 bulk_start;
+	u8 bulk_count;
+	u8 bulk_max;
 };
 
 #define qeth_for_each_output_queue(card, q, i)		\
@@ -620,6 +625,7 @@
 
 struct qeth_channel {
 	struct ccw_device *ccwdev;
+	struct qeth_cmd_buffer *active_cmd;
 	enum qeth_channel_states state;
 	atomic_t irq_pending;
 };
@@ -879,6 +885,13 @@
 	return txq;
 }
 
+static inline bool qeth_iqd_is_mcast_queue(struct qeth_card *card,
+					   struct qeth_qdio_out_q *queue)
+{
+	return qeth_iqd_translate_txq(card->dev, queue->queue_no) ==
+	       QETH_IQD_MCAST_TXQ;
+}
+
 static inline void qeth_scrub_qdio_buffer(struct qdio_buffer *buf,
 					  unsigned int elements)
 {
@@ -1024,6 +1037,8 @@
 void qeth_clear_thread_start_bit(struct qeth_card *, unsigned long);
 void qeth_clear_thread_running_bit(struct qeth_card *, unsigned long);
 int qeth_core_hardsetup_card(struct qeth_card *card, bool *carrier_ok);
+int qeth_stop_channel(struct qeth_channel *channel);
+
 void qeth_print_status_message(struct qeth_card *);
 int qeth_init_qdio_queues(struct qeth_card *);
 int qeth_send_ipa_cmd(struct qeth_card *, struct qeth_cmd_buffer *,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/net/qeth_core_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/net/qeth_core_main.c
@@ -31,6 +31,7 @@
 
 #include <net/iucv/af_iucv.h>
 #include <net/dsfield.h>
+#include <net/sock.h>
 
 #include <asm/ebcdic.h>
 #include <asm/chpid.h>
@@ -226,7 +227,7 @@
 			return -ENOMEM;
 		}
 		for (j = 0; j < QETH_MAX_BUFFER_ELEMENTS(card); ++j) {
-			ptr = (void *) __get_free_page(GFP_KERNEL);
+			ptr = (void *) __get_free_page(GFP_KERNEL|__GFP_MEMALLOC);
 			if (!ptr) {
 				while (j > 0)
 					free_page((unsigned long)
@@ -425,18 +426,13 @@
 
 		}
 	}
-	if (forced_cleanup && (atomic_read(&(q->bufs[bidx]->state)) ==
-					QETH_QDIO_BUF_HANDLED_DELAYED)) {
-		/* for recovery situations */
-		qeth_init_qdio_out_buf(q, bidx);
-		QETH_CARD_TEXT(q->card, 2, "clprecov");
-	}
 }
 
 
 static void qeth_qdio_handle_aob(struct qeth_card *card,
 				 unsigned long phys_aob_addr)
 {
+	enum qeth_qdio_out_buffer_state new_state = QETH_QDIO_BUF_QAOB_OK;
 	struct qaob *aob;
 	struct qeth_qdio_out_buffer *buffer;
 	enum iucv_tx_notify notification;
@@ -448,22 +444,6 @@
 	buffer = (struct qeth_qdio_out_buffer *) aob->user1;
 	QETH_CARD_TEXT_(card, 5, "%lx", aob->user1);
 
-	if (atomic_cmpxchg(&buffer->state, QETH_QDIO_BUF_PRIMED,
-			   QETH_QDIO_BUF_IN_CQ) == QETH_QDIO_BUF_PRIMED) {
-		notification = TX_NOTIFY_OK;
-	} else {
-		WARN_ON_ONCE(atomic_read(&buffer->state) !=
-							QETH_QDIO_BUF_PENDING);
-		atomic_set(&buffer->state, QETH_QDIO_BUF_IN_CQ);
-		notification = TX_NOTIFY_DELAYED_OK;
-	}
-
-	if (aob->aorc != 0)  {
-		QETH_CARD_TEXT_(card, 2, "aorc%02X", aob->aorc);
-		notification = qeth_compute_cq_notification(aob->aorc, 1);
-	}
-	qeth_notify_skbs(buffer->q, buffer, notification);
-
 	/* Free dangling allocations. The attached skbs are handled by
 	 * qeth_cleanup_handled_pending().
 	 */
@@ -474,7 +454,33 @@
 			kmem_cache_free(qeth_core_header_cache,
 					(void *) aob->sba[i]);
 	}
-	atomic_set(&buffer->state, QETH_QDIO_BUF_HANDLED_DELAYED);
+
+	if (aob->aorc) {
+		QETH_CARD_TEXT_(card, 2, "aorc%02X", aob->aorc);
+		new_state = QETH_QDIO_BUF_QAOB_ERROR;
+	}
+
+	switch (atomic_xchg(&buffer->state, new_state)) {
+	case QETH_QDIO_BUF_PRIMED:
+		/* Faster than TX completion code. */
+		notification = qeth_compute_cq_notification(aob->aorc, 0);
+		qeth_notify_skbs(buffer->q, buffer, notification);
+		atomic_set(&buffer->state, QETH_QDIO_BUF_HANDLED_DELAYED);
+		break;
+	case QETH_QDIO_BUF_PENDING:
+		/* TX completion code is active and will handle the async
+		 * completion for us.
+		 */
+		break;
+	case QETH_QDIO_BUF_NEED_QAOB:
+		/* TX completion code is already finished. */
+		notification = qeth_compute_cq_notification(aob->aorc, 1);
+		qeth_notify_skbs(buffer->q, buffer, notification);
+		atomic_set(&buffer->state, QETH_QDIO_BUF_HANDLED_DELAYED);
+		break;
+	default:
+		WARN_ON_ONCE(1);
+	}
 
 	qdio_release_aob(aob);
 }
@@ -515,7 +521,9 @@
 
 	QETH_CARD_TEXT(card, 6, "noirqpnd");
 	rc = ccw_device_start(channel->ccwdev, ccw, (addr_t) iob, 0, 0);
-	if (rc) {
+	if (!rc) {
+		channel->active_cmd = iob;
+	} else {
 		QETH_DBF_MESSAGE(2, "error %i on device %x when starting next read ccw!\n",
 				 rc, CARD_DEVID(card));
 		atomic_set(&channel->irq_pending, 0);
@@ -653,17 +661,17 @@
 	unsigned char *buffer)
 {
 	QETH_DBF_HEX(CTRL, 2, buffer, QETH_DBF_CTRL_LEN);
-	if ((buffer[2] & 0xc0) == 0xc0) {
+	if ((buffer[2] & QETH_IDX_TERMINATE_MASK) == QETH_IDX_TERMINATE) {
 		QETH_DBF_MESSAGE(2, "received an IDX TERMINATE with cause code %#04x\n",
 				 buffer[4]);
 		QETH_CARD_TEXT(card, 2, "ckidxres");
 		QETH_CARD_TEXT(card, 2, " idxterm");
-		QETH_CARD_TEXT_(card, 2, "  rc%d", -EIO);
-		if (buffer[4] == 0xf6) {
+		QETH_CARD_TEXT_(card, 2, "rc%x", buffer[4]);
+		if (buffer[4] == QETH_IDX_TERM_BAD_TRANSPORT ||
+		    buffer[4] == QETH_IDX_TERM_BAD_TRANSPORT_VM) {
 			dev_err(&card->gdev->dev,
-			"The qeth device is not configured "
-			"for the OSI layer required by z/VM\n");
-			return -EPERM;
+				"The device does not support the configured transport mode\n");
+			return -EPROTONOSUPPORT;
 		}
 		return -EIO;
 	}
@@ -740,10 +748,10 @@
 	case 0:
 		break;
 	case -EIO:
-		qeth_clear_ipacmd_list(card);
 		qeth_schedule_recovery(card);
 		/* fall through */
 	default:
+		qeth_clear_ipacmd_list(card);
 		goto out;
 	}
 
@@ -986,8 +994,21 @@
 		QETH_CARD_TEXT(card, 5, "data");
 	}
 
-	if (qeth_intparm_is_iob(intparm))
-		iob = (struct qeth_cmd_buffer *) __va((addr_t)intparm);
+	if (intparm == 0) {
+		QETH_CARD_TEXT(card, 5, "irqunsol");
+	} else if ((addr_t)intparm != (addr_t)channel->active_cmd) {
+		QETH_CARD_TEXT(card, 5, "irqunexp");
+
+		dev_err(&cdev->dev,
+			"Received IRQ with intparm %lx, expected %px\n",
+			intparm, channel->active_cmd);
+		if (channel->active_cmd)
+			qeth_cancel_cmd(channel->active_cmd, -EIO);
+	} else {
+		iob = (struct qeth_cmd_buffer *) (addr_t)intparm;
+	}
+
+	channel->active_cmd = NULL;
 
 	rc = qeth_check_irb_error(card, cdev, irb);
 	if (rc) {
@@ -1007,15 +1028,10 @@
 	if (irb->scsw.cmd.fctl & (SCSW_FCTL_HALT_FUNC))
 		channel->state = CH_STATE_HALTED;
 
-	if (intparm == QETH_CLEAR_CHANNEL_PARM) {
-		QETH_CARD_TEXT(card, 6, "clrchpar");
-		/* we don't have to handle this further */
-		intparm = 0;
-	}
-	if (intparm == QETH_HALT_CHANNEL_PARM) {
-		QETH_CARD_TEXT(card, 6, "hltchpar");
-		/* we don't have to handle this further */
-		intparm = 0;
+	if (iob && (irb->scsw.cmd.fctl & (SCSW_FCTL_CLEAR_FUNC |
+					  SCSW_FCTL_HALT_FUNC))) {
+		qeth_cancel_cmd(iob, -ECANCELED);
+		iob = NULL;
 	}
 
 	cstat = irb->scsw.cmd.cstat;
@@ -1073,7 +1089,7 @@
 	skb_queue_walk(&buf->skb_list, skb) {
 		QETH_CARD_TEXT_(q->card, 5, "skbn%d", notification);
 		QETH_CARD_TEXT_(q->card, 5, "%lx", (long) skb);
-		if (skb->protocol == htons(ETH_P_AF_IUCV) && skb->sk)
+		if (skb->sk && skb->sk->sk_family == PF_IUCV)
 			iucv_sk(skb->sk)->sk_txnotify(skb, notification);
 	}
 }
@@ -1084,9 +1100,6 @@
 	struct qeth_qdio_out_q *queue = buf->q;
 	struct sk_buff *skb;
 
-	/* release may never happen from within CQ tasklet scope */
-	WARN_ON_ONCE(atomic_read(&buf->state) == QETH_QDIO_BUF_IN_CQ);
-
 	if (atomic_read(&buf->state) == QETH_QDIO_BUF_PENDING)
 		qeth_notify_skbs(queue, buf, TX_NOTIFY_GENERALERROR);
 
@@ -1234,7 +1247,6 @@
 	if (count == 1)
 		dev_info(&card->gdev->dev, "Priority Queueing not supported\n");
 
-	card->qdio.default_out_queue = single ? 0 : QETH_DEFAULT_QUEUE;
 	card->qdio.no_out_queues = count;
 	return 0;
 }
@@ -1408,7 +1420,7 @@
 
 	QETH_CARD_TEXT(card, 3, "clearch");
 	spin_lock_irq(get_ccwdev_lock(channel->ccwdev));
-	rc = ccw_device_clear(channel->ccwdev, QETH_CLEAR_CHANNEL_PARM);
+	rc = ccw_device_clear(channel->ccwdev, (addr_t)channel->active_cmd);
 	spin_unlock_irq(get_ccwdev_lock(channel->ccwdev));
 
 	if (rc)
@@ -1430,7 +1442,7 @@
 
 	QETH_CARD_TEXT(card, 3, "haltch");
 	spin_lock_irq(get_ccwdev_lock(channel->ccwdev));
-	rc = ccw_device_halt(channel->ccwdev, QETH_HALT_CHANNEL_PARM);
+	rc = ccw_device_halt(channel->ccwdev, (addr_t)channel->active_cmd);
 	spin_unlock_irq(get_ccwdev_lock(channel->ccwdev));
 
 	if (rc)
@@ -1444,6 +1456,25 @@
 	return 0;
 }
 
+int qeth_stop_channel(struct qeth_channel *channel)
+{
+	struct ccw_device *cdev = channel->ccwdev;
+	int rc;
+
+	rc = ccw_device_set_offline(cdev);
+
+	spin_lock_irq(get_ccwdev_lock(cdev));
+	if (channel->active_cmd) {
+		dev_err(&cdev->dev, "Stopped channel while cmd %px was still active\n",
+			channel->active_cmd);
+		channel->active_cmd = NULL;
+	}
+	spin_unlock_irq(get_ccwdev_lock(cdev));
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(qeth_stop_channel);
+
 static int qeth_halt_channels(struct qeth_card *card)
 {
 	int rc1 = 0, rc2 = 0, rc3 = 0;
@@ -1747,6 +1778,8 @@
 	spin_lock_irq(get_ccwdev_lock(channel->ccwdev));
 	rc = ccw_device_start_timeout(channel->ccwdev, __ccw_from_cmd(iob),
 				      (addr_t) iob, 0, 0, timeout);
+	if (!rc)
+		channel->active_cmd = iob;
 	spin_unlock_irq(get_ccwdev_lock(channel->ccwdev));
 	if (rc) {
 		QETH_DBF_MESSAGE(2, "qeth_send_control_data on device %x: ccw_device_start rc = %i\n",
@@ -2451,50 +2484,46 @@
 	rc = qeth_cm_enable(card);
 	if (rc) {
 		QETH_CARD_TEXT_(card, 2, "2err%d", rc);
-		goto out_qdio;
+		return rc;
 	}
 	rc = qeth_cm_setup(card);
 	if (rc) {
 		QETH_CARD_TEXT_(card, 2, "3err%d", rc);
-		goto out_qdio;
+		return rc;
 	}
 	rc = qeth_ulp_enable(card);
 	if (rc) {
 		QETH_CARD_TEXT_(card, 2, "4err%d", rc);
-		goto out_qdio;
+		return rc;
 	}
 	rc = qeth_ulp_setup(card);
 	if (rc) {
 		QETH_CARD_TEXT_(card, 2, "5err%d", rc);
-		goto out_qdio;
+		return rc;
 	}
 	rc = qeth_alloc_qdio_queues(card);
 	if (rc) {
 		QETH_CARD_TEXT_(card, 2, "5err%d", rc);
-		goto out_qdio;
+		return rc;
 	}
 	rc = qeth_qdio_establish(card);
 	if (rc) {
 		QETH_CARD_TEXT_(card, 2, "6err%d", rc);
 		qeth_free_qdio_queues(card);
-		goto out_qdio;
+		return rc;
 	}
 	rc = qeth_qdio_activate(card);
 	if (rc) {
 		QETH_CARD_TEXT_(card, 2, "7err%d", rc);
-		goto out_qdio;
+		return rc;
 	}
 	rc = qeth_dm_act(card);
 	if (rc) {
 		QETH_CARD_TEXT_(card, 2, "8err%d", rc);
-		goto out_qdio;
+		return rc;
 	}
 
 	return 0;
-out_qdio:
-	qeth_qdio_clear_card(card, !IS_IQD(card));
-	qdio_free(CARD_DDEV(card));
-	return rc;
 }
 
 void qeth_print_status_message(struct qeth_card *card)
@@ -2583,7 +2612,7 @@
 			struct qeth_buffer_pool_entry, list);
 	for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i) {
 		if (page_count(virt_to_page(entry->elements[i])) > 1) {
-			page = alloc_page(GFP_ATOMIC);
+			page = dev_alloc_page();
 			if (!page) {
 				return NULL;
 			} else {
@@ -2607,12 +2636,12 @@
 		buf->rx_skb = netdev_alloc_skb(card->dev,
 					       QETH_RX_PULL_LEN + ETH_HLEN);
 		if (!buf->rx_skb)
-			return 1;
+			return -ENOMEM;
 	}
 
 	pool_entry = qeth_find_free_buffer_pool_entry(card);
 	if (!pool_entry)
-		return 1;
+		return -ENOBUFS;
 
 	/*
 	 * since the buffer is accessed only from the input_tasklet
@@ -2634,6 +2663,18 @@
 	return 0;
 }
 
+static unsigned int qeth_tx_select_bulk_max(struct qeth_card *card,
+					    struct qeth_qdio_out_q *queue)
+{
+	if (!IS_IQD(card) ||
+	    qeth_iqd_is_mcast_queue(card, queue) ||
+	    card->options.cq == QETH_CQ_ENABLED ||
+	    qdio_get_ssqd_desc(CARD_DDEV(card), &card->ssqd))
+		return 1;
+
+	return card->ssqd.mmwc ? card->ssqd.mmwc : 1;
+}
+
 int qeth_init_qdio_queues(struct qeth_card *card)
 {
 	unsigned int i;
@@ -2644,10 +2685,15 @@
 	/* inbound queue */
 	qdio_reset_buffers(card->qdio.in_q->qdio_bufs, QDIO_MAX_BUFFERS_PER_Q);
 	memset(&card->rx, 0, sizeof(struct qeth_rx));
+
 	qeth_initialize_working_pool_list(card);
 	/*give only as many buffers to hardware as we have buffer pool entries*/
-	for (i = 0; i < card->qdio.in_buf_pool.buf_count - 1; ++i)
-		qeth_init_input_buffer(card, &card->qdio.in_q->bufs[i]);
+	for (i = 0; i < card->qdio.in_buf_pool.buf_count - 1; i++) {
+		rc = qeth_init_input_buffer(card, &card->qdio.in_q->bufs[i]);
+		if (rc)
+			return rc;
+	}
+
 	card->qdio.in_q->next_buf_to_init =
 		card->qdio.in_buf_pool.buf_count - 1;
 	rc = do_QDIO(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT, 0, 0,
@@ -2673,6 +2719,8 @@
 		queue->do_pack = 0;
 		queue->prev_hdr = NULL;
 		queue->bulk_start = 0;
+		queue->bulk_count = 0;
+		queue->bulk_max = qeth_tx_select_bulk_max(card, queue);
 		atomic_set(&queue->used_buffers, 0);
 		atomic_set(&queue->set_pci_flags_count, 0);
 		atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
@@ -3318,10 +3366,11 @@
 
 static void qeth_flush_queue(struct qeth_qdio_out_q *queue)
 {
-	qeth_flush_buffers(queue, queue->bulk_start, 1);
+	qeth_flush_buffers(queue, queue->bulk_start, queue->bulk_count);
 
-	queue->bulk_start = QDIO_BUFNR(queue->bulk_start + 1);
+	queue->bulk_start = QDIO_BUFNR(queue->bulk_start + queue->bulk_count);
 	queue->prev_hdr = NULL;
+	queue->bulk_count = 0;
 }
 
 static void qeth_check_outbound_queue(struct qeth_qdio_out_q *queue)
@@ -3382,11 +3431,6 @@
 			goto out;
 		}
 
-		if (card->state != CARD_STATE_DOWN) {
-			rc = -1;
-			goto out;
-		}
-
 		qeth_free_qdio_queues(card);
 		card->options.cq = cq;
 		rc = 0;
@@ -3680,10 +3724,10 @@
 }
 
 static bool qeth_iqd_may_bulk(struct qeth_qdio_out_q *queue,
-			      struct qeth_qdio_out_buffer *buffer,
 			      struct sk_buff *curr_skb,
 			      struct qeth_hdr *curr_hdr)
 {
+	struct qeth_qdio_out_buffer *buffer = queue->bufs[queue->bulk_start];
 	struct qeth_hdr *prev_hdr = queue->prev_hdr;
 
 	if (!prev_hdr)
@@ -3803,13 +3847,14 @@
 		       struct qeth_hdr *hdr, unsigned int offset,
 		       unsigned int hd_len)
 {
-	struct qeth_qdio_out_buffer *buffer = queue->bufs[queue->bulk_start];
 	unsigned int bytes = qdisc_pkt_len(skb);
+	struct qeth_qdio_out_buffer *buffer;
 	unsigned int next_element;
 	struct netdev_queue *txq;
 	bool stopped = false;
 	bool flush;
 
+	buffer = queue->bufs[QDIO_BUFNR(queue->bulk_start + queue->bulk_count)];
 	txq = netdev_get_tx_queue(card->dev, skb_get_queue_mapping(skb));
 
 	/* Just a sanity check, the wake/stop logic should ensure that we always
@@ -3818,11 +3863,23 @@
 	if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY)
 		return -EBUSY;
 
-	if ((buffer->next_element_to_fill + elements > queue->max_elements) ||
-	    !qeth_iqd_may_bulk(queue, buffer, skb, hdr)) {
-		atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED);
-		qeth_flush_queue(queue);
-		buffer = queue->bufs[queue->bulk_start];
+	flush = !qeth_iqd_may_bulk(queue, skb, hdr);
+
+	if (flush ||
+	    (buffer->next_element_to_fill + elements > queue->max_elements)) {
+		if (buffer->next_element_to_fill > 0) {
+			atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED);
+			queue->bulk_count++;
+		}
+
+		if (queue->bulk_count >= queue->bulk_max)
+			flush = true;
+
+		if (flush)
+			qeth_flush_queue(queue);
+
+		buffer = queue->bufs[QDIO_BUFNR(queue->bulk_start +
+						queue->bulk_count)];
 
 		/* Sanity-check again: */
 		if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY)
@@ -3848,7 +3905,13 @@
 
 	if (flush || next_element >= queue->max_elements) {
 		atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED);
-		qeth_flush_queue(queue);
+		queue->bulk_count++;
+
+		if (queue->bulk_count >= queue->bulk_max)
+			flush = true;
+
+		if (flush)
+			qeth_flush_queue(queue);
 	}
 
 	if (stopped && !qeth_out_queue_is_full(queue))
@@ -4137,9 +4200,6 @@
 	int fallback = *(int *)reply->param;
 
 	QETH_CARD_TEXT(card, 4, "setaccb");
-	if (cmd->hdr.return_code)
-		return -EIO;
-	qeth_setadpparms_inspect_rc(cmd);
 
 	access_ctrl_req = &cmd->data.setadapterparms.data.set_access_ctrl;
 	QETH_CARD_TEXT_(card, 2, "rc=%d",
@@ -4149,7 +4209,7 @@
 		QETH_DBF_MESSAGE(3, "ERR:SET_ACCESS_CTRL(%#x) on device %x: %#x\n",
 				 access_ctrl_req->subcmd_code, CARD_DEVID(card),
 				 cmd->data.setadapterparms.hdr.return_code);
-	switch (cmd->data.setadapterparms.hdr.return_code) {
+	switch (qeth_setadpparms_inspect_rc(cmd)) {
 	case SET_ACCESS_CTRL_RC_SUCCESS:
 		if (card->options.isolation == ISOLATION_MODE_NONE) {
 			dev_info(&card->gdev->dev,
@@ -4634,12 +4694,12 @@
 
 static void qeth_determine_capabilities(struct qeth_card *card)
 {
+	struct qeth_channel *channel = &card->data;
+	struct ccw_device *ddev = channel->ccwdev;
 	int rc;
-	struct ccw_device *ddev;
 	int ddev_offline = 0;
 
 	QETH_CARD_TEXT(card, 2, "detcapab");
-	ddev = CARD_DDEV(card);
 	if (!ddev->online) {
 		ddev_offline = 1;
 		rc = ccw_device_set_online(ddev);
@@ -4678,7 +4738,7 @@
 
 out_offline:
 	if (ddev_offline == 1)
-		ccw_device_set_offline(ddev);
+		qeth_stop_channel(channel);
 out:
 	return;
 }
@@ -4694,10 +4754,10 @@
 	if (card->options.cq == QETH_CQ_ENABLED) {
 		int offset = QDIO_MAX_BUFFERS_PER_Q *
 			     (card->qdio.no_in_queues - 1);
-		for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) {
-			in_sbal_ptrs[offset + i] = (struct qdio_buffer *)
-				virt_to_phys(card->qdio.c_q->bufs[i].buffer);
-		}
+
+		for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++)
+			in_sbal_ptrs[offset + i] =
+				card->qdio.c_q->bufs[i].buffer;
 
 		queue_start_poll[card->qdio.no_in_queues - 1] = NULL;
 	}
@@ -4731,10 +4791,9 @@
 		rc = -ENOMEM;
 		goto out_free_qib_param;
 	}
-	for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; ++i) {
-		in_sbal_ptrs[i] = (struct qdio_buffer *)
-			virt_to_phys(card->qdio.in_q->bufs[i].buffer);
-	}
+
+	for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++)
+		in_sbal_ptrs[i] = card->qdio.in_q->bufs[i].buffer;
 
 	queue_start_poll = kcalloc(card->qdio.no_in_queues, sizeof(void *),
 				   GFP_KERNEL);
@@ -4755,11 +4814,11 @@
 		rc = -ENOMEM;
 		goto out_free_queue_start_poll;
 	}
+
 	for (i = 0, k = 0; i < card->qdio.no_out_queues; ++i)
-		for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j, ++k) {
-			out_sbal_ptrs[k] = (struct qdio_buffer *)virt_to_phys(
-				card->qdio.out_qs[i]->bufs[j]->buffer);
-		}
+		for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++, k++)
+			out_sbal_ptrs[k] =
+				card->qdio.out_qs[i]->bufs[j]->buffer;
 
 	memset(&init_data, 0, sizeof(struct qdio_initialize));
 	init_data.cdev                   = CARD_DDEV(card);
@@ -4879,9 +4938,9 @@
 		QETH_DBF_MESSAGE(2, "Retrying to do IDX activates on device %x.\n",
 				 CARD_DEVID(card));
 	rc = qeth_qdio_clear_card(card, !IS_IQD(card));
-	ccw_device_set_offline(CARD_DDEV(card));
-	ccw_device_set_offline(CARD_WDEV(card));
-	ccw_device_set_offline(CARD_RDEV(card));
+	qeth_stop_channel(&card->data);
+	qeth_stop_channel(&card->write);
+	qeth_stop_channel(&card->read);
 	qdio_free(CARD_DDEV(card));
 	rc = ccw_device_set_online(CARD_RDEV(card));
 	if (rc)
@@ -4972,10 +5031,8 @@
 	}
 	if (qeth_adp_supported(card, IPA_SETADP_SET_DIAG_ASSIST)) {
 		rc = qeth_query_setdiagass(card);
-		if (rc < 0) {
+		if (rc)
 			QETH_CARD_TEXT_(card, 2, "8err%d", rc);
-			goto out;
-		}
 	}
 	return 0;
 out:
@@ -5203,9 +5260,32 @@
 
 		if (atomic_cmpxchg(&buffer->state, QETH_QDIO_BUF_PRIMED,
 						   QETH_QDIO_BUF_PENDING) ==
-		    QETH_QDIO_BUF_PRIMED)
+		    QETH_QDIO_BUF_PRIMED) {
 			qeth_notify_skbs(queue, buffer, TX_NOTIFY_PENDING);
 
+			/* Handle race with qeth_qdio_handle_aob(): */
+			switch (atomic_xchg(&buffer->state,
+					    QETH_QDIO_BUF_NEED_QAOB)) {
+			case QETH_QDIO_BUF_PENDING:
+				/* No concurrent QAOB notification. */
+				break;
+			case QETH_QDIO_BUF_QAOB_OK:
+				qeth_notify_skbs(queue, buffer,
+						 TX_NOTIFY_DELAYED_OK);
+				atomic_set(&buffer->state,
+					   QETH_QDIO_BUF_HANDLED_DELAYED);
+				break;
+			case QETH_QDIO_BUF_QAOB_ERROR:
+				qeth_notify_skbs(queue, buffer,
+						 TX_NOTIFY_DELAYED_GENERALERROR);
+				atomic_set(&buffer->state,
+					   QETH_QDIO_BUF_HANDLED_DELAYED);
+				break;
+			default:
+				WARN_ON_ONCE(1);
+			}
+		}
+
 		QETH_CARD_TEXT_(card, 5, "pel%u", bidx);
 
 		/* prepare the queue slot for re-use: */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/net/qeth_core_mpc.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/net/qeth_core_mpc.h
@@ -28,20 +28,6 @@
 #define QETH_TIMEOUT		(10 * HZ)
 #define QETH_IPA_TIMEOUT	(45 * HZ)
 
-#define QETH_CLEAR_CHANNEL_PARM	-10
-#define QETH_HALT_CHANNEL_PARM	-11
-
-static inline bool qeth_intparm_is_iob(unsigned long intparm)
-{
-	switch (intparm) {
-	case QETH_CLEAR_CHANNEL_PARM:
-	case QETH_HALT_CHANNEL_PARM:
-	case 0:
-		return false;
-	}
-	return true;
-}
-
 /*****************************************************************************/
 /* IP Assist related definitions                                             */
 /*****************************************************************************/
@@ -912,6 +898,11 @@
 #define QETH_IDX_ACT_ERR_AUTH		0x1E
 #define QETH_IDX_ACT_ERR_AUTH_USER	0x20
 
+#define QETH_IDX_TERMINATE		0xc0
+#define QETH_IDX_TERMINATE_MASK		0xc0
+#define QETH_IDX_TERM_BAD_TRANSPORT	0x41
+#define QETH_IDX_TERM_BAD_TRANSPORT_VM	0xf6
+
 #define PDU_ENCAPSULATION(buffer) \
 	(buffer + *(buffer + (*(buffer + 0x0b)) + \
 	 *(buffer + *(buffer + 0x0b) + 0x11) + 0x07))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/net/qeth_core_sys.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/net/qeth_core_sys.c
@@ -227,7 +227,7 @@
 		card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
 	} else if (sysfs_streq(buf, "prio_queueing_vlan")) {
 		if (IS_LAYER3(card)) {
-			rc = -ENOTSUPP;
+			rc = -EOPNOTSUPP;
 			goto out;
 		}
 		card->qdio.do_prio_queueing = QETH_PRIO_Q_ING_VLAN;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/net/qeth_l2_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/net/qeth_l2_main.c
@@ -287,14 +287,15 @@
 		card->state = CARD_STATE_HARDSETUP;
 	}
 	if (card->state == CARD_STATE_HARDSETUP) {
-		qeth_qdio_clear_card(card, 0);
 		qeth_drain_output_queues(card);
 		qeth_clear_working_pool_list(card);
 		card->state = CARD_STATE_DOWN;
 	}
 
+	qeth_qdio_clear_card(card, 0);
 	flush_workqueue(card->event_wq);
 	card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
+	card->info.promisc_mode = 0;
 }
 
 static int qeth_l2_process_inbound_buffer(struct qeth_card *card,
@@ -876,9 +877,9 @@
 
 out_remove:
 	qeth_l2_stop_card(card);
-	ccw_device_set_offline(CARD_DDEV(card));
-	ccw_device_set_offline(CARD_WDEV(card));
-	ccw_device_set_offline(CARD_RDEV(card));
+	qeth_stop_channel(&card->data);
+	qeth_stop_channel(&card->write);
+	qeth_stop_channel(&card->read);
 	qdio_free(CARD_DDEV(card));
 
 	mutex_unlock(&card->conf_mutex);
@@ -909,9 +910,9 @@
 	rtnl_unlock();
 
 	qeth_l2_stop_card(card);
-	rc  = ccw_device_set_offline(CARD_DDEV(card));
-	rc2 = ccw_device_set_offline(CARD_WDEV(card));
-	rc3 = ccw_device_set_offline(CARD_RDEV(card));
+	rc  = qeth_stop_channel(&card->data);
+	rc2 = qeth_stop_channel(&card->write);
+	rc3 = qeth_stop_channel(&card->read);
 	if (!rc)
 		rc = (rc2) ? rc2 : rc3;
 	if (rc)
@@ -1167,12 +1168,6 @@
 		NULL
 	};
 
-	/* Role should not change by itself, but if it did, */
-	/* information from the hardware is authoritative.  */
-	mutex_lock(&data->card->sbp_lock);
-	data->card->options.sbp.role = entry->role;
-	mutex_unlock(&data->card->sbp_lock);
-
 	snprintf(env_locrem, sizeof(env_locrem), "BRIDGEPORT=statechange");
 	snprintf(env_role, sizeof(env_role), "ROLE=%s",
 		(entry->role == QETH_SBP_ROLE_NONE) ? "none" :
@@ -1198,6 +1193,10 @@
 	int extrasize;
 
 	QETH_CARD_TEXT(card, 2, "brstchng");
+	if (qports->num_entries == 0) {
+		QETH_CARD_TEXT(card, 2, "BPempty");
+		return;
+	}
 	if (qports->entry_length != sizeof(struct qeth_sbp_port_entry)) {
 		QETH_CARD_TEXT_(card, 2, "BPsz%04x", qports->entry_length);
 		return;
@@ -1845,15 +1844,14 @@
 
 	QETH_CARD_TEXT(card, 2, "vniccsch");
 
-	/* do not change anything if BridgePort is enabled */
-	if (qeth_bridgeport_is_in_use(card))
-		return -EBUSY;
-
 	/* check if characteristic and enable/disable are supported */
 	if (!(card->options.vnicc.sup_chars & vnicc) ||
 	    !(card->options.vnicc.set_char_sup & vnicc))
 		return -EOPNOTSUPP;
 
+	if (qeth_bridgeport_is_in_use(card))
+		return -EBUSY;
+
 	/* set enable/disable command and store wanted characteristic */
 	if (state) {
 		cmd = IPA_VNICC_ENABLE;
@@ -1899,14 +1897,13 @@
 
 	QETH_CARD_TEXT(card, 2, "vniccgch");
 
-	/* do not get anything if BridgePort is enabled */
-	if (qeth_bridgeport_is_in_use(card))
-		return -EBUSY;
-
 	/* check if characteristic is supported */
 	if (!(card->options.vnicc.sup_chars & vnicc))
 		return -EOPNOTSUPP;
 
+	if (qeth_bridgeport_is_in_use(card))
+		return -EBUSY;
+
 	/* if card is ready, query current VNICC state */
 	if (qeth_card_hw_is_reachable(card))
 		rc = qeth_l2_vnicc_query_chars(card);
@@ -1924,15 +1921,14 @@
 
 	QETH_CARD_TEXT(card, 2, "vniccsto");
 
-	/* do not change anything if BridgePort is enabled */
-	if (qeth_bridgeport_is_in_use(card))
-		return -EBUSY;
-
 	/* check if characteristic and set_timeout are supported */
 	if (!(card->options.vnicc.sup_chars & QETH_VNICC_LEARNING) ||
 	    !(card->options.vnicc.getset_timeout_sup & QETH_VNICC_LEARNING))
 		return -EOPNOTSUPP;
 
+	if (qeth_bridgeport_is_in_use(card))
+		return -EBUSY;
+
 	/* do we need to do anything? */
 	if (card->options.vnicc.learning_timeout == timeout)
 		return rc;
@@ -1961,14 +1957,14 @@
 
 	QETH_CARD_TEXT(card, 2, "vniccgto");
 
-	/* do not get anything if BridgePort is enabled */
-	if (qeth_bridgeport_is_in_use(card))
-		return -EBUSY;
-
 	/* check if characteristic and get_timeout are supported */
 	if (!(card->options.vnicc.sup_chars & QETH_VNICC_LEARNING) ||
 	    !(card->options.vnicc.getset_timeout_sup & QETH_VNICC_LEARNING))
 		return -EOPNOTSUPP;
+
+	if (qeth_bridgeport_is_in_use(card))
+		return -EBUSY;
+
 	/* if card is ready, get timeout. Otherwise, just return stored value */
 	*timeout = card->options.vnicc.learning_timeout;
 	if (qeth_card_hw_is_reachable(card))
@@ -1982,8 +1978,7 @@
 /* check if VNICC is currently enabled */
 bool qeth_l2_vnicc_is_in_use(struct qeth_card *card)
 {
-	/* if everything is turned off, VNICC is not active */
-	if (!card->options.vnicc.cur_chars)
+	if (!card->options.vnicc.sup_chars)
 		return false;
 	/* default values are only OK if rx_bcast was not enabled by user
 	 * or the card is offline.
@@ -2070,8 +2065,9 @@
 	/* enforce assumed default values and recover settings, if changed  */
 	error |= qeth_l2_vnicc_recover_timeout(card, QETH_VNICC_LEARNING,
 					       timeout);
-	chars_tmp = card->options.vnicc.wanted_chars ^ QETH_VNICC_DEFAULT;
-	chars_tmp |= QETH_VNICC_BRIDGE_INVISIBLE;
+	/* Change chars, if necessary  */
+	chars_tmp = card->options.vnicc.wanted_chars ^
+		    card->options.vnicc.cur_chars;
 	chars_len = sizeof(card->options.vnicc.wanted_chars) * BITS_PER_BYTE;
 	for_each_set_bit(i, &chars_tmp, chars_len) {
 		vnicc = BIT(i);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/net/qeth_l2_sys.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/net/qeth_l2_sys.c
@@ -279,7 +279,8 @@
 		return;
 
 	mutex_lock(&card->sbp_lock);
-	if (card->options.sbp.role != QETH_SBP_ROLE_NONE) {
+	if (!card->options.sbp.reflect_promisc &&
+	    card->options.sbp.role != QETH_SBP_ROLE_NONE) {
 		/* Conditional to avoid spurious error messages */
 		qeth_bridgeport_setrole(card, card->options.sbp.role);
 		/* Let the callback function refresh the stored role value. */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/net/qeth_l3_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/net/qeth_l3_main.c
@@ -305,9 +305,10 @@
 		if (!recover) {
 			hash_del(&addr->hnode);
 			kfree(addr);
-			continue;
+		} else {
+			/* prepare for recovery */
+			addr->disp_flag = QETH_DISP_ADDR_ADD;
 		}
-		addr->disp_flag = QETH_DISP_ADDR_ADD;
 	}
 
 	mutex_unlock(&card->ip_lock);
@@ -335,11 +336,13 @@
 			} else
 				rc = qeth_l3_register_addr_entry(card, addr);
 
-			if (!rc) {
+			if (!rc || rc == -EADDRINUSE || rc == -ENETDOWN) {
+				/* keep it in the records */
 				addr->disp_flag = QETH_DISP_ADDR_DO_NOTHING;
 				if (addr->ref_counter < 1)
 					qeth_l3_delete_ip(card, addr);
 			} else {
+				/* bad address */
 				hash_del(&addr->hnode);
 				kfree(addr);
 			}
@@ -1426,13 +1429,14 @@
 		card->state = CARD_STATE_HARDSETUP;
 	}
 	if (card->state == CARD_STATE_HARDSETUP) {
-		qeth_qdio_clear_card(card, 0);
 		qeth_drain_output_queues(card);
 		qeth_clear_working_pool_list(card);
 		card->state = CARD_STATE_DOWN;
 	}
 
+	qeth_qdio_clear_card(card, 0);
 	flush_workqueue(card->event_wq);
+	card->info.promisc_mode = 0;
 }
 
 static void qeth_l3_set_promisc_mode(struct qeth_card *card)
@@ -2113,7 +2117,7 @@
 						    struct net_device *dev,
 						    netdev_features_t features)
 {
-	if (qeth_get_ip_version(skb) != 4)
+	if (vlan_get_protocol(skb) != htons(ETH_P_IP))
 		features &= ~NETIF_F_HW_VLAN_CTAG_TX;
 	return qeth_features_check(skb, dev, features);
 }
@@ -2382,9 +2386,9 @@
 	return 0;
 out_remove:
 	qeth_l3_stop_card(card);
-	ccw_device_set_offline(CARD_DDEV(card));
-	ccw_device_set_offline(CARD_WDEV(card));
-	ccw_device_set_offline(CARD_RDEV(card));
+	qeth_stop_channel(&card->data);
+	qeth_stop_channel(&card->write);
+	qeth_stop_channel(&card->read);
 	qdio_free(CARD_DDEV(card));
 
 	mutex_unlock(&card->conf_mutex);
@@ -2420,9 +2424,10 @@
 		call_netdevice_notifiers(NETDEV_REBOOT, card->dev);
 		rtnl_unlock();
 	}
-	rc  = ccw_device_set_offline(CARD_DDEV(card));
-	rc2 = ccw_device_set_offline(CARD_WDEV(card));
-	rc3 = ccw_device_set_offline(CARD_RDEV(card));
+
+	rc  = qeth_stop_channel(&card->data);
+	rc2 = qeth_stop_channel(&card->write);
+	rc3 = qeth_stop_channel(&card->read);
 	if (!rc)
 		rc = (rc2) ? rc2 : rc3;
 	if (rc)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/net/qeth_l3_sys.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/net/qeth_l3_sys.c
@@ -270,24 +270,36 @@
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct qeth_card *card = dev_get_drvdata(dev);
+	int rc = 0;
 	char *tmp;
-	int rc;
 
 	if (!card)
 		return -EINVAL;
 
 	if (!IS_IQD(card))
 		return -EPERM;
-	if (card->state != CARD_STATE_DOWN)
-		return -EPERM;
-	if (card->options.sniffer)
-		return -EPERM;
-	if (card->options.cq == QETH_CQ_NOTAVAILABLE)
-		return -EPERM;
+
+	mutex_lock(&card->conf_mutex);
+	if (card->state != CARD_STATE_DOWN) {
+		rc = -EPERM;
+		goto out;
+	}
+
+	if (card->options.sniffer) {
+		rc = -EPERM;
+		goto out;
+	}
+
+	if (card->options.cq == QETH_CQ_NOTAVAILABLE) {
+		rc = -EPERM;
+		goto out;
+	}
 
 	tmp = strsep((char **)&buf, "\n");
-	if (strlen(tmp) > 8)
-		return -EINVAL;
+	if (strlen(tmp) > 8) {
+		rc = -EINVAL;
+		goto out;
+	}
 
 	if (card->options.hsuid[0])
 		/* delete old ip address */
@@ -298,11 +310,13 @@
 		card->options.hsuid[0] = '\0';
 		memcpy(card->dev->perm_addr, card->options.hsuid, 9);
 		qeth_configure_cq(card, QETH_CQ_DISABLED);
-		return count;
+		goto out;
 	}
 
-	if (qeth_configure_cq(card, QETH_CQ_ENABLED))
-		return -EPERM;
+	if (qeth_configure_cq(card, QETH_CQ_ENABLED)) {
+		rc = -EPERM;
+		goto out;
+	}
 
 	snprintf(card->options.hsuid, sizeof(card->options.hsuid),
 		 "%-8s", tmp);
@@ -311,6 +325,8 @@
 
 	rc = qeth_l3_modify_hsuid(card, true);
 
+out:
+	mutex_unlock(&card->conf_mutex);
 	return rc ? rc : count;
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/scsi/Makefile
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/scsi/Makefile
@@ -5,6 +5,6 @@
 
 zfcp-objs := zfcp_aux.o zfcp_ccw.o zfcp_dbf.o zfcp_erp.o \
 	     zfcp_fc.o zfcp_fsf.o zfcp_qdio.o zfcp_scsi.o zfcp_sysfs.o \
-	     zfcp_unit.o
+	     zfcp_unit.o zfcp_diag.o
 
 obj-$(CONFIG_ZFCP) += zfcp.o
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/scsi/zfcp_aux.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/scsi/zfcp_aux.c
@@ -4,7 +4,7 @@
  *
  * Module interface and handling of zfcp data structures.
  *
- * Copyright IBM Corp. 2002, 2017
+ * Copyright IBM Corp. 2002, 2020
  */
 
 /*
@@ -25,6 +25,7 @@
  *            Martin Petermann
  *            Sven Schuetz
  *            Steffen Maier
+ *	      Benjamin Block
  */
 
 #define KMSG_COMPONENT "zfcp"
@@ -36,6 +37,7 @@
 #include "zfcp_ext.h"
 #include "zfcp_fc.h"
 #include "zfcp_reqlist.h"
+#include "zfcp_diag.h"
 
 #define ZFCP_BUS_ID_SIZE	20
 
@@ -356,6 +358,9 @@
 
 	adapter->erp_action.adapter = adapter;
 
+	if (zfcp_diag_adapter_setup(adapter))
+		goto failed;
+
 	if (zfcp_qdio_setup(adapter))
 		goto failed;
 
@@ -402,13 +407,15 @@
 			       &zfcp_sysfs_adapter_attrs))
 		goto failed;
 
+	if (zfcp_diag_sysfs_setup(adapter))
+		goto failed;
+
 	/* report size limit per scatter-gather segment */
 	adapter->ccw_device->dev.dma_parms = &adapter->dma_parms;
 
 	adapter->stat_read_buf_num = FSF_STATUS_READS_RECOM;
 
-	if (!zfcp_scsi_adapter_register(adapter))
-		return adapter;
+	return adapter;
 
 failed:
 	zfcp_adapter_unregister(adapter);
@@ -426,6 +433,7 @@
 
 	zfcp_fc_wka_ports_force_offline(adapter->gs);
 	zfcp_scsi_adapter_unregister(adapter);
+	zfcp_diag_sysfs_destroy(adapter);
 	sysfs_remove_group(&cdev->dev.kobj, &zfcp_sysfs_adapter_attrs);
 
 	zfcp_erp_thread_kill(adapter);
@@ -449,6 +457,7 @@
 	dev_set_drvdata(&adapter->ccw_device->dev, NULL);
 	zfcp_fc_gs_destroy(adapter);
 	zfcp_free_low_mem_buffers(adapter);
+	zfcp_diag_adapter_free(adapter);
 	kfree(adapter->req_list);
 	kfree(adapter->fc_stats);
 	kfree(adapter->stats_reset_data);
@@ -488,12 +497,12 @@
 	if (port) {
 		put_device(&port->dev);
 		retval = -EEXIST;
-		goto err_out;
+		goto err_put;
 	}
 
 	port = kzalloc(sizeof(struct zfcp_port), GFP_KERNEL);
 	if (!port)
-		goto err_out;
+		goto err_put;
 
 	rwlock_init(&port->unit_list_lock);
 	INIT_LIST_HEAD(&port->unit_list);
@@ -516,7 +525,7 @@
 
 	if (dev_set_name(&port->dev, "0x%016llx", (unsigned long long)wwpn)) {
 		kfree(port);
-		goto err_out;
+		goto err_put;
 	}
 	retval = -EINVAL;
 
@@ -533,7 +542,8 @@
 
 	return port;
 
-err_out:
+err_put:
 	zfcp_ccw_adapter_put(adapter);
+err_out:
 	return ERR_PTR(retval);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/scsi/zfcp_dbf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/scsi/zfcp_dbf.c
@@ -4,7 +4,7 @@
  *
  * Debug traces for zfcp.
  *
- * Copyright IBM Corp. 2002, 2018
+ * Copyright IBM Corp. 2002, 2020
  */
 
 #define KMSG_COMPONENT "zfcp"
@@ -95,11 +95,51 @@
 	memcpy(rec->u.res.fsf_status_qual, &q_head->fsf_status_qual,
 	       FSF_STATUS_QUALIFIER_SIZE);
 
-	if (q_head->fsf_command != FSF_QTCB_FCP_CMND) {
-		rec->pl_len = q_head->log_length;
-		zfcp_dbf_pl_write(dbf, (char *)q_pref + q_head->log_start,
-				  rec->pl_len, "fsf_res", req->req_id);
-	}
+	rec->pl_len = q_head->log_length;
+	zfcp_dbf_pl_write(dbf, (char *)q_pref + q_head->log_start,
+			  rec->pl_len, "fsf_res", req->req_id);
+
+	debug_event(dbf->hba, level, rec, sizeof(*rec));
+	spin_unlock_irqrestore(&dbf->hba_lock, flags);
+}
+
+/**
+ * zfcp_dbf_hba_fsf_fces - trace event for fsf responses related to
+ *			   FC Endpoint Security (FCES)
+ * @tag: tag indicating which kind of FC Endpoint Security event has occurred
+ * @req: request for which a response was received
+ * @wwpn: remote port or ZFCP_DBF_INVALID_WWPN
+ * @fc_security_old: old FC Endpoint Security of FCP device or connection
+ * @fc_security_new: new FC Endpoint Security of FCP device or connection
+ */
+void zfcp_dbf_hba_fsf_fces(char *tag, const struct zfcp_fsf_req *req, u64 wwpn,
+			   u32 fc_security_old, u32 fc_security_new)
+{
+	struct zfcp_dbf *dbf = req->adapter->dbf;
+	struct fsf_qtcb_prefix *q_pref = &req->qtcb->prefix;
+	struct fsf_qtcb_header *q_head = &req->qtcb->header;
+	struct zfcp_dbf_hba *rec = &dbf->hba_buf;
+	static int const level = 3;
+	unsigned long flags;
+
+	if (unlikely(!debug_level_enabled(dbf->hba, level)))
+		return;
+
+	spin_lock_irqsave(&dbf->hba_lock, flags);
+	memset(rec, 0, sizeof(*rec));
+
+	memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN);
+	rec->id = ZFCP_DBF_HBA_FCES;
+	rec->fsf_req_id = req->req_id;
+	rec->fsf_req_status = req->status;
+	rec->fsf_cmd = q_head->fsf_command;
+	rec->fsf_seq_no = q_pref->req_seq_no;
+	rec->u.fces.req_issued = req->issued;
+	rec->u.fces.fsf_status = q_head->fsf_status;
+	rec->u.fces.port_handle = q_head->port_handle;
+	rec->u.fces.wwpn = wwpn;
+	rec->u.fces.fc_security_old = fc_security_old;
+	rec->u.fces.fc_security_new = fc_security_new;
 
 	debug_event(dbf->hba, level, rec, sizeof(*rec));
 	spin_unlock_irqrestore(&dbf->hba_lock, flags);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/scsi/zfcp_dbf.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/scsi/zfcp_dbf.h
@@ -3,7 +3,7 @@
  * zfcp device driver
  * debug feature declarations
  *
- * Copyright IBM Corp. 2008, 2017
+ * Copyright IBM Corp. 2008, 2020
  */
 
 #ifndef ZFCP_DBF_H
@@ -16,6 +16,7 @@
 
 #define ZFCP_DBF_TAG_LEN       7
 
+#define ZFCP_DBF_INVALID_WWPN	0x0000000000000000ull
 #define ZFCP_DBF_INVALID_LUN	0xFFFFFFFFFFFFFFFFull
 
 enum zfcp_dbf_pseudo_erp_act_type {
@@ -158,17 +159,38 @@
 } __packed;
 
 /**
+ * struct zfcp_dbf_hba_fces - trace record for FC Endpoint Security
+ * @req_issued: timestamp when request was issued
+ * @fsf_status: fsf status
+ * @port_handle: handle for port
+ * @wwpn: remote FC port WWPN
+ * @fc_security_old: old FC Endpoint Security
+ * @fc_security_new: new FC Endpoint Security
+ *
+ */
+struct zfcp_dbf_hba_fces {
+	u64 req_issued;
+	u32 fsf_status;
+	u32 port_handle;
+	u64 wwpn;
+	u32 fc_security_old;
+	u32 fc_security_new;
+} __packed;
+
+/**
  * enum zfcp_dbf_hba_id - HBA trace record identifier
  * @ZFCP_DBF_HBA_RES: response trace record
  * @ZFCP_DBF_HBA_USS: unsolicited status trace record
  * @ZFCP_DBF_HBA_BIT: bit error trace record
  * @ZFCP_DBF_HBA_BASIC: basic adapter event, only trace tag, no other data
+ * @ZFCP_DBF_HBA_FCES: FC Endpoint Security trace record
  */
 enum zfcp_dbf_hba_id {
 	ZFCP_DBF_HBA_RES	= 1,
 	ZFCP_DBF_HBA_USS	= 2,
 	ZFCP_DBF_HBA_BIT	= 3,
 	ZFCP_DBF_HBA_BASIC	= 4,
+	ZFCP_DBF_HBA_FCES	= 5,
 };
 
 /**
@@ -181,9 +203,10 @@
  * @fsf_seq_no: fsf sequence number
  * @pl_len: length of payload stored as zfcp_dbf_pay
  * @u: record type specific data
- * @u.res: data for fsf responses
- * @u.uss: data for unsolicited status buffer
- * @u.be:  data for bit error unsolicited status buffer
+ * @u.res:  data for fsf responses
+ * @u.uss:  data for unsolicited status buffer
+ * @u.be:   data for bit error unsolicited status buffer
+ * @u.fces: data for FC Endpoint Security
  */
 struct zfcp_dbf_hba {
 	u8 id;
@@ -197,6 +220,7 @@
 		struct zfcp_dbf_hba_res res;
 		struct zfcp_dbf_hba_uss uss;
 		struct fsf_bit_error_payload be;
+		struct zfcp_dbf_hba_fces fces;
 	} u;
 } __packed;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/scsi/zfcp_def.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/scsi/zfcp_def.h
@@ -4,7 +4,7 @@
  *
  * Global definitions for the zfcp device driver.
  *
- * Copyright IBM Corp. 2002, 2017
+ * Copyright IBM Corp. 2002, 2020
  */
 
 #ifndef ZFCP_DEF_H
@@ -86,6 +86,7 @@
 #define ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED       0x00000080
 #define ZFCP_STATUS_FSFREQ_TMFUNCFAILED         0x00000200
 #define ZFCP_STATUS_FSFREQ_DISMISSED            0x00001000
+#define ZFCP_STATUS_FSFREQ_XDATAINCOMPLETE	0x00020000
 
 /************************* STRUCTURE DEFINITIONS *****************************/
 
@@ -157,6 +158,8 @@
 	u32			adapter_features;  /* FCP channel features */
 	u32			connection_features; /* host connection features */
         u32			hardware_version;  /* of FCP channel */
+	u32			fc_security_algorithms; /* of FCP channel */
+	u32			fc_security_algorithms_old; /* of FCP channel */
 	u16			timer_ticks;       /* time int for a tick */
 	struct Scsi_Host	*scsi_host;	   /* Pointer to mid-layer */
 	struct list_head	port_list;	   /* remote port list */
@@ -197,6 +200,7 @@
 	struct device_dma_parameters dma_parms;
 	struct zfcp_fc_events events;
 	unsigned long		next_port_scan;
+	struct zfcp_diag_adapter	*diagnostics;
 };
 
 struct zfcp_port {
@@ -216,6 +220,8 @@
         atomic_t               erp_counter;
 	u32                    maxframe_size;
 	u32                    supported_classes;
+	u32                    connection_info;
+	u32                    connection_info_old;
 	struct work_struct     gid_pn_work;
 	struct work_struct     test_link_work;
 	struct work_struct     rport_work;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/scsi/zfcp_diag.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/scsi/zfcp_diag.c
@@ -0,0 +1,305 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * zfcp device driver
+ *
+ * Functions to handle diagnostics.
+ *
+ * Copyright IBM Corp. 2018
+ */
+
+#include <linux/spinlock.h>
+#include <linux/jiffies.h>
+#include <linux/string.h>
+#include <linux/kernfs.h>
+#include <linux/sysfs.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+#include "zfcp_diag.h"
+#include "zfcp_ext.h"
+#include "zfcp_def.h"
+
+static DECLARE_WAIT_QUEUE_HEAD(__zfcp_diag_publish_wait);
+
+/**
+ * zfcp_diag_adapter_setup() - Setup storage for adapter diagnostics.
+ * @adapter: the adapter to setup diagnostics for.
+ *
+ * Creates the data-structures to store the diagnostics for an adapter. This
+ * overwrites whatever was stored before at &zfcp_adapter->diagnostics!
+ *
+ * Return:
+ * * 0	     - Everyting is OK
+ * * -ENOMEM - Could not allocate all/parts of the data-structures;
+ *	       &zfcp_adapter->diagnostics remains unchanged
+ */
+int zfcp_diag_adapter_setup(struct zfcp_adapter *const adapter)
+{
+	struct zfcp_diag_adapter *diag;
+	struct zfcp_diag_header *hdr;
+
+	diag = kzalloc(sizeof(*diag), GFP_KERNEL);
+	if (diag == NULL)
+		return -ENOMEM;
+
+	diag->max_age = (5 * 1000); /* default value: 5 s */
+
+	/* setup header for port_data */
+	hdr = &diag->port_data.header;
+
+	spin_lock_init(&hdr->access_lock);
+	hdr->buffer = &diag->port_data.data;
+	hdr->buffer_size = sizeof(diag->port_data.data);
+	/* set the timestamp so that the first test on age will always fail */
+	hdr->timestamp = jiffies - msecs_to_jiffies(diag->max_age);
+
+	/* setup header for config_data */
+	hdr = &diag->config_data.header;
+
+	spin_lock_init(&hdr->access_lock);
+	hdr->buffer = &diag->config_data.data;
+	hdr->buffer_size = sizeof(diag->config_data.data);
+	/* set the timestamp so that the first test on age will always fail */
+	hdr->timestamp = jiffies - msecs_to_jiffies(diag->max_age);
+
+	adapter->diagnostics = diag;
+	return 0;
+}
+
+/**
+ * zfcp_diag_adapter_free() - Frees all adapter diagnostics allocations.
+ * @adapter: the adapter whose diagnostic structures should be freed.
+ *
+ * Frees all data-structures in the given adapter that store diagnostics
+ * information. Can savely be called with partially setup diagnostics.
+ */
+void zfcp_diag_adapter_free(struct zfcp_adapter *const adapter)
+{
+	kfree(adapter->diagnostics);
+	adapter->diagnostics = NULL;
+}
+
+/**
+ * zfcp_diag_sysfs_setup() - Setup the sysfs-group for adapter-diagnostics.
+ * @adapter: target adapter to which the group should be added.
+ *
+ * Return: 0 on success; Something else otherwise (see sysfs_create_group()).
+ */
+int zfcp_diag_sysfs_setup(struct zfcp_adapter *const adapter)
+{
+	int rc = sysfs_create_group(&adapter->ccw_device->dev.kobj,
+				    &zfcp_sysfs_diag_attr_group);
+	if (rc == 0)
+		adapter->diagnostics->sysfs_established = 1;
+
+	return rc;
+}
+
+/**
+ * zfcp_diag_sysfs_destroy() - Remove the sysfs-group for adapter-diagnostics.
+ * @adapter: target adapter from which the group should be removed.
+ */
+void zfcp_diag_sysfs_destroy(struct zfcp_adapter *const adapter)
+{
+	if (adapter->diagnostics == NULL ||
+	    !adapter->diagnostics->sysfs_established)
+		return;
+
+	/*
+	 * We need this state-handling so we can prevent warnings being printed
+	 * on the kernel-console in case we have to abort a halfway done
+	 * zfcp_adapter_enqueue(), in which the sysfs-group was not yet
+	 * established. sysfs_remove_group() does this checking as well, but
+	 * still prints a warning in case we try to remove a group that has not
+	 * been established before
+	 */
+	adapter->diagnostics->sysfs_established = 0;
+	sysfs_remove_group(&adapter->ccw_device->dev.kobj,
+			   &zfcp_sysfs_diag_attr_group);
+}
+
+
+/**
+ * zfcp_diag_update_xdata() - Update a diagnostics buffer.
+ * @hdr: the meta data to update.
+ * @data: data to use for the update.
+ * @incomplete: flag stating whether the data in @data is incomplete.
+ */
+void zfcp_diag_update_xdata(struct zfcp_diag_header *const hdr,
+			    const void *const data, const bool incomplete)
+{
+	const unsigned long capture_timestamp = jiffies;
+	unsigned long flags;
+
+	spin_lock_irqsave(&hdr->access_lock, flags);
+
+	/* make sure we never go into the past with an update */
+	if (!time_after_eq(capture_timestamp, hdr->timestamp))
+		goto out;
+
+	hdr->timestamp = capture_timestamp;
+	hdr->incomplete = incomplete;
+	memcpy(hdr->buffer, data, hdr->buffer_size);
+out:
+	spin_unlock_irqrestore(&hdr->access_lock, flags);
+}
+
+/**
+ * zfcp_diag_update_port_data_buffer() - Implementation of
+ *					 &typedef zfcp_diag_update_buffer_func
+ *					 to collect and update Port Data.
+ * @adapter: Adapter to collect Port Data from.
+ *
+ * This call is SYNCHRONOUS ! It blocks till the respective command has
+ * finished completely, or has failed in some way.
+ *
+ * Return:
+ * * 0		- Successfully retrieved new Diagnostics and Updated the buffer;
+ *		  this also includes cases where data was retrieved, but
+ *		  incomplete; you'll have to check the flag ``incomplete``
+ *		  of &struct zfcp_diag_header.
+ * * see zfcp_fsf_exchange_port_data_sync() for possible error-codes (
+ *   excluding -EAGAIN)
+ */
+int zfcp_diag_update_port_data_buffer(struct zfcp_adapter *const adapter)
+{
+	int rc;
+
+	rc = zfcp_fsf_exchange_port_data_sync(adapter->qdio, NULL);
+	if (rc == -EAGAIN)
+		rc = 0; /* signaling incomplete via struct zfcp_diag_header */
+
+	/* buffer-data was updated in zfcp_fsf_exchange_port_data_handler() */
+
+	return rc;
+}
+
+/**
+ * zfcp_diag_update_config_data_buffer() - Implementation of
+ *					   &typedef zfcp_diag_update_buffer_func
+ *					   to collect and update Config Data.
+ * @adapter: Adapter to collect Config Data from.
+ *
+ * This call is SYNCHRONOUS ! It blocks till the respective command has
+ * finished completely, or has failed in some way.
+ *
+ * Return:
+ * * 0		- Successfully retrieved new Diagnostics and Updated the buffer;
+ *		  this also includes cases where data was retrieved, but
+ *		  incomplete; you'll have to check the flag ``incomplete``
+ *		  of &struct zfcp_diag_header.
+ * * see zfcp_fsf_exchange_config_data_sync() for possible error-codes (
+ *   excluding -EAGAIN)
+ */
+int zfcp_diag_update_config_data_buffer(struct zfcp_adapter *const adapter)
+{
+	int rc;
+
+	rc = zfcp_fsf_exchange_config_data_sync(adapter->qdio, NULL);
+	if (rc == -EAGAIN)
+		rc = 0; /* signaling incomplete via struct zfcp_diag_header */
+
+	/* buffer-data was updated in zfcp_fsf_exchange_config_data_handler() */
+
+	return rc;
+}
+
+static int __zfcp_diag_update_buffer(struct zfcp_adapter *const adapter,
+				     struct zfcp_diag_header *const hdr,
+				     zfcp_diag_update_buffer_func buffer_update,
+				     unsigned long *const flags)
+	__must_hold(hdr->access_lock)
+{
+	int rc;
+
+	if (hdr->updating == 1) {
+		rc = wait_event_interruptible_lock_irq(__zfcp_diag_publish_wait,
+						       hdr->updating == 0,
+						       hdr->access_lock);
+		rc = (rc == 0 ? -EAGAIN : -EINTR);
+	} else {
+		hdr->updating = 1;
+		spin_unlock_irqrestore(&hdr->access_lock, *flags);
+
+		/* unlocked, because update function sleeps */
+		rc = buffer_update(adapter);
+
+		spin_lock_irqsave(&hdr->access_lock, *flags);
+		hdr->updating = 0;
+
+		/*
+		 * every thread waiting here went via an interruptible wait,
+		 * so its fine to only wake those
+		 */
+		wake_up_interruptible_all(&__zfcp_diag_publish_wait);
+	}
+
+	return rc;
+}
+
+static bool
+__zfcp_diag_test_buffer_age_isfresh(const struct zfcp_diag_adapter *const diag,
+				    const struct zfcp_diag_header *const hdr)
+	__must_hold(hdr->access_lock)
+{
+	const unsigned long now = jiffies;
+
+	/*
+	 * Should not happen (data is from the future).. if it does, still
+	 * signal that it needs refresh
+	 */
+	if (!time_after_eq(now, hdr->timestamp))
+		return false;
+
+	if (jiffies_to_msecs(now - hdr->timestamp) >= diag->max_age)
+		return false;
+
+	return true;
+}
+
+/**
+ * zfcp_diag_update_buffer_limited() - Collect diagnostics and update a
+ *				       diagnostics buffer rate limited.
+ * @adapter: Adapter to collect the diagnostics from.
+ * @hdr: buffer-header for which to update with the collected diagnostics.
+ * @buffer_update: Specific implementation for collecting and updating.
+ *
+ * This function will cause an update of the given @hdr by calling the also
+ * given @buffer_update function. If called by multiple sources at the same
+ * time, it will synchornize the update by only allowing one source to call
+ * @buffer_update and the others to wait for that source to complete instead
+ * (the wait is interruptible).
+ *
+ * Additionally this version is rate-limited and will only exit if either the
+ * buffer is fresh enough (within the limit) - it will do nothing if the buffer
+ * is fresh enough to begin with -, or if the source/thread that started this
+ * update is the one that made the update (to prevent endless loops).
+ *
+ * Return:
+ * * 0		- If the update was successfully published and/or the buffer is
+ *		  fresh enough
+ * * -EINTR	- If the thread went into the wait-state and was interrupted
+ * * whatever @buffer_update returns
+ */
+int zfcp_diag_update_buffer_limited(struct zfcp_adapter *const adapter,
+				    struct zfcp_diag_header *const hdr,
+				    zfcp_diag_update_buffer_func buffer_update)
+{
+	unsigned long flags;
+	int rc;
+
+	spin_lock_irqsave(&hdr->access_lock, flags);
+
+	for (rc = 0;
+	     !__zfcp_diag_test_buffer_age_isfresh(adapter->diagnostics, hdr);
+	     rc = 0) {
+		rc = __zfcp_diag_update_buffer(adapter, hdr, buffer_update,
+					       &flags);
+		if (rc != -EAGAIN)
+			break;
+	}
+
+	spin_unlock_irqrestore(&hdr->access_lock, flags);
+
+	return rc;
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/scsi/zfcp_diag.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/scsi/zfcp_diag.h
@@ -0,0 +1,101 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * zfcp device driver
+ *
+ * Definitions for handling diagnostics in the the zfcp device driver.
+ *
+ * Copyright IBM Corp. 2018, 2020
+ */
+
+#ifndef ZFCP_DIAG_H
+#define ZFCP_DIAG_H
+
+#include <linux/spinlock.h>
+
+#include "zfcp_fsf.h"
+#include "zfcp_def.h"
+
+/**
+ * struct zfcp_diag_header - general part of a diagnostic buffer.
+ * @access_lock: lock protecting all the data in this buffer.
+ * @updating: flag showing that an update for this buffer is currently running.
+ * @incomplete: flag showing that the data in @buffer is incomplete.
+ * @timestamp: time in jiffies when the data of this buffer was last captured.
+ * @buffer: implementation-depending data of this buffer
+ * @buffer_size: size of @buffer
+ */
+struct zfcp_diag_header {
+	spinlock_t	access_lock;
+
+	/* Flags */
+	u64		updating	:1;
+	u64		incomplete	:1;
+
+	unsigned long	timestamp;
+
+	void		*buffer;
+	size_t		buffer_size;
+};
+
+/**
+ * struct zfcp_diag_adapter - central storage for all diagnostics concerning an
+ *			      adapter.
+ * @sysfs_established: flag showing that the associated sysfs-group was created
+ *		       during run of zfcp_adapter_enqueue().
+ * @max_age: maximum age of data in diagnostic buffers before they need to be
+ *	     refreshed (in ms).
+ * @port_data: data retrieved using exchange port data.
+ * @port_data.header: header with metadata for the cache in @port_data.data.
+ * @port_data.data: cached QTCB Bottom of command exchange port data.
+ * @config_data: data retrieved using exchange config data.
+ * @config_data.header: header with metadata for the cache in @config_data.data.
+ * @config_data.data: cached QTCB Bottom of command exchange config data.
+ */
+struct zfcp_diag_adapter {
+	u64	sysfs_established	:1;
+
+	unsigned long	max_age;
+
+	struct zfcp_diag_adapter_port_data {
+		struct zfcp_diag_header		header;
+		struct fsf_qtcb_bottom_port	data;
+	} port_data;
+	struct zfcp_diag_adapter_config_data {
+		struct zfcp_diag_header		header;
+		struct fsf_qtcb_bottom_config	data;
+	} config_data;
+};
+
+int zfcp_diag_adapter_setup(struct zfcp_adapter *const adapter);
+void zfcp_diag_adapter_free(struct zfcp_adapter *const adapter);
+
+int zfcp_diag_sysfs_setup(struct zfcp_adapter *const adapter);
+void zfcp_diag_sysfs_destroy(struct zfcp_adapter *const adapter);
+
+void zfcp_diag_update_xdata(struct zfcp_diag_header *const hdr,
+			    const void *const data, const bool incomplete);
+
+/*
+ * Function-Type used in zfcp_diag_update_buffer_limited() for the function
+ * that does the buffer-implementation dependent work.
+ */
+typedef int (*zfcp_diag_update_buffer_func)(struct zfcp_adapter *const adapter);
+
+int zfcp_diag_update_config_data_buffer(struct zfcp_adapter *const adapter);
+int zfcp_diag_update_port_data_buffer(struct zfcp_adapter *const adapter);
+int zfcp_diag_update_buffer_limited(struct zfcp_adapter *const adapter,
+				    struct zfcp_diag_header *const hdr,
+				    zfcp_diag_update_buffer_func buffer_update);
+
+/**
+ * zfcp_diag_support_sfp() - Return %true if the @adapter supports reporting
+ *			     SFP Data.
+ * @adapter: adapter to test the availability of SFP Data reporting for.
+ */
+static inline bool
+zfcp_diag_support_sfp(const struct zfcp_adapter *const adapter)
+{
+	return !!(adapter->adapter_features & FSF_FEATURE_REPORT_SFP_DATA);
+}
+
+#endif /* ZFCP_DIAG_H */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/scsi/zfcp_erp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/scsi/zfcp_erp.c
@@ -4,7 +4,7 @@
  *
  * Error Recovery Procedures (ERP).
  *
- * Copyright IBM Corp. 2002, 2017
+ * Copyright IBM Corp. 2002, 2020
  */
 
 #define KMSG_COMPONENT "zfcp"
@@ -14,6 +14,7 @@
 #include <linux/bug.h>
 #include "zfcp_ext.h"
 #include "zfcp_reqlist.h"
+#include "zfcp_diag.h"
 
 #define ZFCP_MAX_ERPS                   3
 
@@ -174,29 +175,29 @@
 			return 0;
 		p_status = atomic_read(&port->status);
 		if (!(p_status & ZFCP_STATUS_COMMON_RUNNING) ||
-		      p_status & ZFCP_STATUS_COMMON_ERP_FAILED)
+		    p_status & ZFCP_STATUS_COMMON_ERP_FAILED)
 			return 0;
 		if (!(p_status & ZFCP_STATUS_COMMON_UNBLOCKED))
 			need = ZFCP_ERP_ACTION_REOPEN_PORT;
-		/* fall through */
+		fallthrough;
 	case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
 		p_status = atomic_read(&port->status);
 		if (!(p_status & ZFCP_STATUS_COMMON_OPEN))
 			need = ZFCP_ERP_ACTION_REOPEN_PORT;
-		/* fall through */
+		fallthrough;
 	case ZFCP_ERP_ACTION_REOPEN_PORT:
 		p_status = atomic_read(&port->status);
 		if (p_status & ZFCP_STATUS_COMMON_ERP_INUSE)
 			return 0;
 		a_status = atomic_read(&adapter->status);
 		if (!(a_status & ZFCP_STATUS_COMMON_RUNNING) ||
-		      a_status & ZFCP_STATUS_COMMON_ERP_FAILED)
+		    a_status & ZFCP_STATUS_COMMON_ERP_FAILED)
 			return 0;
 		if (p_status & ZFCP_STATUS_COMMON_NOESC)
 			return need;
 		if (!(a_status & ZFCP_STATUS_COMMON_UNBLOCKED))
 			need = ZFCP_ERP_ACTION_REOPEN_ADAPTER;
-		/* fall through */
+		fallthrough;
 	case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
 		a_status = atomic_read(&adapter->status);
 		if (a_status & ZFCP_STATUS_COMMON_ERP_INUSE)
@@ -576,7 +577,10 @@
 				   ZFCP_STATUS_ERP_TIMEDOUT)) {
 			req->status |= ZFCP_STATUS_FSFREQ_DISMISSED;
 			zfcp_dbf_rec_run("erscf_1", act);
-			req->erp_action = NULL;
+			/* lock-free concurrent access with
+			 * zfcp_erp_timeout_handler()
+			 */
+			WRITE_ONCE(req->erp_action, NULL);
 		}
 		if (act->status & ZFCP_STATUS_ERP_TIMEDOUT)
 			zfcp_dbf_rec_run("erscf_2", act);
@@ -612,8 +616,14 @@
 void zfcp_erp_timeout_handler(struct timer_list *t)
 {
 	struct zfcp_fsf_req *fsf_req = from_timer(fsf_req, t, timer);
-	struct zfcp_erp_action *act = fsf_req->erp_action;
+	struct zfcp_erp_action *act;
 
+	if (fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED)
+		return;
+	/* lock-free concurrent access with zfcp_erp_strategy_check_fsfreq() */
+	act = READ_ONCE(fsf_req->erp_action);
+	if (!act)
+		return;
 	zfcp_erp_notify(act, ZFCP_STATUS_ERP_TIMEDOUT);
 }
 
@@ -725,7 +735,7 @@
 				 adapter->peer_d_id);
 	if (IS_ERR(port)) /* error or port already attached */
 		return;
-	_zfcp_erp_port_reopen(port, 0, "ereptp1");
+	zfcp_erp_port_reopen(port, 0, "ereptp1");
 }
 
 static enum zfcp_erp_act_result zfcp_erp_adapter_strat_fsf_xconf(
@@ -768,10 +778,14 @@
 	if (!(atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_XCONFIG_OK))
 		return ZFCP_ERP_FAILED;
 
+	return ZFCP_ERP_SUCCEEDED;
+}
+
+static void
+zfcp_erp_adapter_strategy_open_ptp_port(struct zfcp_adapter *const adapter)
+{
 	if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP)
 		zfcp_erp_enqueue_ptp_port(adapter);
-
-	return ZFCP_ERP_SUCCEEDED;
 }
 
 static enum zfcp_erp_act_result zfcp_erp_adapter_strategy_open_fsf_xport(
@@ -800,6 +814,59 @@
 	return ZFCP_ERP_SUCCEEDED;
 }
 
+static enum zfcp_erp_act_result
+zfcp_erp_adapter_strategy_alloc_shost(struct zfcp_adapter *const adapter)
+{
+	struct zfcp_diag_adapter_config_data *const config_data =
+		&adapter->diagnostics->config_data;
+	struct zfcp_diag_adapter_port_data *const port_data =
+		&adapter->diagnostics->port_data;
+	unsigned long flags;
+	int rc;
+
+	rc = zfcp_scsi_adapter_register(adapter);
+	if (rc == -EEXIST)
+		return ZFCP_ERP_SUCCEEDED;
+	else if (rc)
+		return ZFCP_ERP_FAILED;
+
+	/*
+	 * We allocated the shost for the first time. Before it was NULL,
+	 * and so we deferred all updates in the xconf- and xport-data
+	 * handlers. We need to make up for that now, and make all the updates
+	 * that would have been done before.
+	 *
+	 * We can be sure that xconf- and xport-data succeeded, because
+	 * otherwise this function is not called. But they might have been
+	 * incomplete.
+	 */
+
+	spin_lock_irqsave(&config_data->header.access_lock, flags);
+	zfcp_scsi_shost_update_config_data(adapter, &config_data->data,
+					   !!config_data->header.incomplete);
+	spin_unlock_irqrestore(&config_data->header.access_lock, flags);
+
+	if (adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT) {
+		spin_lock_irqsave(&port_data->header.access_lock, flags);
+		zfcp_scsi_shost_update_port_data(adapter, &port_data->data);
+		spin_unlock_irqrestore(&port_data->header.access_lock, flags);
+	}
+
+	/*
+	 * There is a remote possibility that the 'Exchange Port Data' request
+	 * reports a different connectivity status than 'Exchange Config Data'.
+	 * But any change to the connectivity status of the local optic that
+	 * happens after the initial xconf request is expected to be reported
+	 * to us, as soon as we post Status Read Buffers to the FCP channel
+	 * firmware after this function. So any resulting inconsistency will
+	 * only be momentary.
+	 */
+	if (config_data->header.incomplete)
+		zfcp_fsf_fc_host_link_down(adapter);
+
+	return ZFCP_ERP_SUCCEEDED;
+}
+
 static enum zfcp_erp_act_result zfcp_erp_adapter_strategy_open_fsf(
 	struct zfcp_erp_action *act)
 {
@@ -809,6 +876,12 @@
 	if (zfcp_erp_adapter_strategy_open_fsf_xport(act) == ZFCP_ERP_FAILED)
 		return ZFCP_ERP_FAILED;
 
+	if (zfcp_erp_adapter_strategy_alloc_shost(act->adapter) ==
+	    ZFCP_ERP_FAILED)
+		return ZFCP_ERP_FAILED;
+
+	zfcp_erp_adapter_strategy_open_ptp_port(act->adapter);
+
 	if (mempool_resize(act->adapter->pool.sr_data,
 			   act->adapter->stat_read_buf_num))
 		return ZFCP_ERP_FAILED;
@@ -1086,7 +1159,7 @@
 		if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_OPEN)
 			return zfcp_erp_lun_strategy_close(erp_action);
 		/* already closed */
-		/* fall through */
+		fallthrough;
 	case ZFCP_ERP_STEP_LUN_CLOSING:
 		if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_OPEN)
 			return ZFCP_ERP_FAILED;
@@ -1415,7 +1488,7 @@
 		if (act->step != ZFCP_ERP_STEP_UNINITIALIZED)
 			if (result == ZFCP_ERP_SUCCEEDED)
 				zfcp_erp_try_rport_unblock(port);
-		/* fall through */
+		fallthrough;
 	case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
 		put_device(&port->dev);
 		break;
@@ -1636,6 +1709,13 @@
 		atomic_or(common_mask, &port->status);
 	read_unlock_irqrestore(&adapter->port_list_lock, flags);
 
+	/*
+	 * if `scsi_host` is missing, xconfig/xport data has never completed
+	 * yet, so we can't access it, but there are also no SDEVs yet
+	 */
+	if (adapter->scsi_host == NULL)
+		return;
+
 	spin_lock_irqsave(adapter->scsi_host->host_lock, flags);
 	__shost_for_each_device(sdev, adapter->scsi_host)
 		atomic_or(common_mask, &sdev_to_zfcp(sdev)->status);
@@ -1673,6 +1753,13 @@
 	}
 	read_unlock_irqrestore(&adapter->port_list_lock, flags);
 
+	/*
+	 * if `scsi_host` is missing, xconfig/xport data has never completed
+	 * yet, so we can't access it, but there are also no SDEVs yet
+	 */
+	if (adapter->scsi_host == NULL)
+		return;
+
 	spin_lock_irqsave(adapter->scsi_host->host_lock, flags);
 	__shost_for_each_device(sdev, adapter->scsi_host) {
 		atomic_andnot(common_mask, &sdev_to_zfcp(sdev)->status);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/scsi/zfcp_ext.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/scsi/zfcp_ext.h
@@ -4,7 +4,7 @@
  *
  * External function declarations.
  *
- * Copyright IBM Corp. 2002, 2018
+ * Copyright IBM Corp. 2002, 2020
  */
 
 #ifndef ZFCP_EXT_H
@@ -44,6 +44,9 @@
 extern void zfcp_dbf_rec_run_wka(char *, struct zfcp_fc_wka_port *, u64);
 extern void zfcp_dbf_hba_fsf_uss(char *, struct zfcp_fsf_req *);
 extern void zfcp_dbf_hba_fsf_res(char *, int, struct zfcp_fsf_req *);
+extern void zfcp_dbf_hba_fsf_fces(char *tag, const struct zfcp_fsf_req *req,
+				  u64 wwpn, u32 fc_security_old,
+				  u32 fc_security_new);
 extern void zfcp_dbf_hba_bit_err(char *, struct zfcp_fsf_req *);
 extern void zfcp_dbf_hba_def_err(struct zfcp_adapter *, u64, u16, void **);
 extern void zfcp_dbf_hba_basic(char *, struct zfcp_adapter *);
@@ -122,6 +125,7 @@
 extern int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *);
 extern int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *,
 					    struct fsf_qtcb_bottom_port *);
+extern u32 zfcp_fsf_convert_portspeed(u32 fsf_speed);
 extern void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *);
 extern int zfcp_fsf_status_read(struct zfcp_qdio *);
 extern int zfcp_status_read_refill(struct zfcp_adapter *adapter);
@@ -131,10 +135,18 @@
 			     struct zfcp_fsf_ct_els *, unsigned int);
 extern int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *);
 extern void zfcp_fsf_req_free(struct zfcp_fsf_req *);
+extern void zfcp_fsf_fc_host_link_down(struct zfcp_adapter *adapter);
 extern struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_device *sdev,
 						   u8 tm_flags);
 extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_cmnd(struct scsi_cmnd *);
 extern void zfcp_fsf_reqid_check(struct zfcp_qdio *, int);
+enum zfcp_fsf_print_fmt {
+	ZFCP_FSF_PRINT_FMT_LIST,
+	ZFCP_FSF_PRINT_FMT_SINGLEITEM,
+};
+extern ssize_t zfcp_fsf_scnprint_fc_security(char *buf, size_t size,
+					     u32 fc_security,
+					     enum zfcp_fsf_print_fmt fmt);
 
 /* zfcp_qdio.c */
 extern int zfcp_qdio_setup(struct zfcp_adapter *);
@@ -143,6 +155,8 @@
 extern int zfcp_qdio_send(struct zfcp_qdio *, struct zfcp_qdio_req *);
 extern int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *, struct zfcp_qdio_req *,
 				   struct scatterlist *);
+extern void zfcp_qdio_shost_update(struct zfcp_adapter *const adapter,
+				   const struct zfcp_qdio *const qdio);
 extern int zfcp_qdio_open(struct zfcp_qdio *);
 extern void zfcp_qdio_close(struct zfcp_qdio *);
 extern void zfcp_qdio_siosl(struct zfcp_adapter *);
@@ -159,6 +173,13 @@
 extern void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *);
 extern void zfcp_scsi_set_prot(struct zfcp_adapter *);
 extern void zfcp_scsi_dif_sense_error(struct scsi_cmnd *, int);
+extern void zfcp_scsi_shost_update_config_data(
+	struct zfcp_adapter *const adapter,
+	const struct fsf_qtcb_bottom_config *const bottom,
+	const bool bottom_incomplete);
+extern void zfcp_scsi_shost_update_port_data(
+	struct zfcp_adapter *const adapter,
+	const struct fsf_qtcb_bottom_port *const bottom);
 
 /* zfcp_sysfs.c */
 extern const struct attribute_group *zfcp_unit_attr_groups[];
@@ -167,6 +188,7 @@
 extern struct mutex zfcp_sysfs_port_units_mutex;
 extern struct device_attribute *zfcp_sysfs_sdev_attrs[];
 extern struct device_attribute *zfcp_sysfs_shost_attrs[];
+extern const struct attribute_group zfcp_sysfs_diag_attr_group;
 bool zfcp_sysfs_port_is_removing(const struct zfcp_port *const port);
 
 /* zfcp_unit.c */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/scsi/zfcp_fc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/scsi/zfcp_fc.c
@@ -145,27 +145,33 @@
 
 static int zfcp_fc_wka_port_get(struct zfcp_fc_wka_port *wka_port)
 {
+	int ret = -EIO;
+
 	if (mutex_lock_interruptible(&wka_port->mutex))
 		return -ERESTARTSYS;
 
 	if (wka_port->status == ZFCP_FC_WKA_PORT_OFFLINE ||
 	    wka_port->status == ZFCP_FC_WKA_PORT_CLOSING) {
 		wka_port->status = ZFCP_FC_WKA_PORT_OPENING;
-		if (zfcp_fsf_open_wka_port(wka_port))
+		if (zfcp_fsf_open_wka_port(wka_port)) {
+			/* could not even send request, nothing to wait for */
 			wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE;
+			goto out;
+		}
 	}
 
-	mutex_unlock(&wka_port->mutex);
-
-	wait_event(wka_port->completion_wq,
+	wait_event(wka_port->opened,
 		   wka_port->status == ZFCP_FC_WKA_PORT_ONLINE ||
 		   wka_port->status == ZFCP_FC_WKA_PORT_OFFLINE);
 
 	if (wka_port->status == ZFCP_FC_WKA_PORT_ONLINE) {
 		atomic_inc(&wka_port->refcount);
-		return 0;
+		ret = 0;
+		goto out;
 	}
-	return -EIO;
+out:
+	mutex_unlock(&wka_port->mutex);
+	return ret;
 }
 
 static void zfcp_fc_wka_port_offline(struct work_struct *work)
@@ -181,9 +187,12 @@
 
 	wka_port->status = ZFCP_FC_WKA_PORT_CLOSING;
 	if (zfcp_fsf_close_wka_port(wka_port)) {
+		/* could not even send request, nothing to wait for */
 		wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE;
-		wake_up(&wka_port->completion_wq);
+		goto out;
 	}
+	wait_event(wka_port->closed,
+		   wka_port->status == ZFCP_FC_WKA_PORT_OFFLINE);
 out:
 	mutex_unlock(&wka_port->mutex);
 }
@@ -193,13 +202,15 @@
 	if (atomic_dec_return(&wka_port->refcount) != 0)
 		return;
 	/* wait 10 milliseconds, other reqs might pop in */
-	schedule_delayed_work(&wka_port->work, HZ / 100);
+	queue_delayed_work(wka_port->adapter->work_queue, &wka_port->work,
+			   msecs_to_jiffies(10));
 }
 
 static void zfcp_fc_wka_port_init(struct zfcp_fc_wka_port *wka_port, u32 d_id,
 				  struct zfcp_adapter *adapter)
 {
-	init_waitqueue_head(&wka_port->completion_wq);
+	init_waitqueue_head(&wka_port->opened);
+	init_waitqueue_head(&wka_port->closed);
 
 	wka_port->adapter = adapter;
 	wka_port->d_id = d_id;
@@ -521,8 +532,9 @@
 		goto out;
 	}
 
-	/* port is good, unblock rport without going through erp */
-	zfcp_scsi_schedule_rport_register(port);
+	/* re-init to undo drop from zfcp_fc_adisc() */
+	port->d_id = ntoh24(adisc_resp->adisc_port_id);
+	/* port is still good, nothing to do */
  out:
 	atomic_andnot(ZFCP_STATUS_PORT_LINK_TEST, &port->status);
 	put_device(&port->dev);
@@ -534,6 +546,7 @@
 	struct zfcp_fc_req *fc_req;
 	struct zfcp_adapter *adapter = port->adapter;
 	struct Scsi_Host *shost = adapter->scsi_host;
+	u32 d_id;
 	int ret;
 
 	fc_req = kmem_cache_zalloc(zfcp_fc_req_cache, GFP_ATOMIC);
@@ -558,7 +571,15 @@
 	fc_req->u.adisc.req.adisc_cmd = ELS_ADISC;
 	hton24(fc_req->u.adisc.req.adisc_port_id, fc_host_port_id(shost));
 
-	ret = zfcp_fsf_send_els(adapter, port->d_id, &fc_req->ct_els,
+	d_id = port->d_id; /* remember as destination for send els below */
+	/*
+	 * Force fresh GID_PN lookup on next port recovery.
+	 * Must happen after request setup and before sending request,
+	 * to prevent race with port->d_id re-init in zfcp_fc_adisc_handler().
+	 */
+	port->d_id = 0;
+
+	ret = zfcp_fsf_send_els(adapter, d_id, &fc_req->ct_els,
 				ZFCP_FC_CTELS_TMO);
 	if (ret)
 		kmem_cache_free(zfcp_fc_req_cache, fc_req);
@@ -573,9 +594,6 @@
 	int retval;
 
 	set_worker_desc("zadisc%16llx", port->wwpn); /* < WORKER_DESC_LEN=24 */
-	get_device(&port->dev);
-	port->rport_task = RPORT_DEL;
-	zfcp_scsi_rport_work(&port->rport_work);
 
 	/* only issue one test command at one time per port */
 	if (atomic_read(&port->status) & ZFCP_STATUS_PORT_LINK_TEST)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/scsi/zfcp_fc.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/scsi/zfcp_fc.h
@@ -185,7 +185,8 @@
 /**
  * struct zfcp_fc_wka_port - representation of well-known-address (WKA) FC port
  * @adapter: Pointer to adapter structure this WKA port belongs to
- * @completion_wq: Wait for completion of open/close command
+ * @opened: Wait for completion of open command
+ * @closed: Wait for completion of close command
  * @status: Current status of WKA port
  * @refcount: Reference count to keep port open as long as it is in use
  * @d_id: FC destination id or well-known-address
@@ -195,7 +196,8 @@
  */
 struct zfcp_fc_wka_port {
 	struct zfcp_adapter	*adapter;
-	wait_queue_head_t	completion_wq;
+	wait_queue_head_t	opened;
+	wait_queue_head_t	closed;
 	enum zfcp_fc_wka_status	status;
 	atomic_t		refcount;
 	u32			d_id;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/scsi/zfcp_fsf.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/scsi/zfcp_fsf.c
@@ -4,13 +4,14 @@
  *
  * Implementation of FSF commands.
  *
- * Copyright IBM Corp. 2002, 2018
+ * Copyright IBM Corp. 2002, 2020
  */
 
 #define KMSG_COMPONENT "zfcp"
 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
 #include <linux/blktrace_api.h>
+#include <linux/jiffies.h>
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <scsi/fc/fc_els.h>
@@ -19,6 +20,7 @@
 #include "zfcp_dbf.h"
 #include "zfcp_qdio.h"
 #include "zfcp_reqlist.h"
+#include "zfcp_diag.h"
 
 /* timeout for FSF requests sent during scsi_eh: abort or FCP TMF */
 #define ZFCP_FSF_SCSI_ER_TIMEOUT (10*HZ)
@@ -118,6 +120,27 @@
 	read_unlock_irqrestore(&adapter->port_list_lock, flags);
 }
 
+void zfcp_fsf_fc_host_link_down(struct zfcp_adapter *adapter)
+{
+	struct Scsi_Host *shost = adapter->scsi_host;
+
+	adapter->hydra_version = 0;
+	adapter->peer_wwpn = 0;
+	adapter->peer_wwnn = 0;
+	adapter->peer_d_id = 0;
+
+	/* if there is no shost yet, we have nothing to zero-out */
+	if (shost == NULL)
+		return;
+
+	fc_host_port_id(shost) = 0;
+	fc_host_fabric_name(shost) = 0;
+	fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
+	fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
+	snprintf(fc_host_model(shost), FC_SYMBOLIC_NAME_SIZE, "0x%04x", 0);
+	memset(fc_host_active_fc4s(shost), 0, FC_FC4_LIST_SIZE);
+}
+
 static void zfcp_fsf_link_down_info_eval(struct zfcp_fsf_req *req,
 					 struct fsf_link_down_info *link_down)
 {
@@ -130,6 +153,8 @@
 
 	zfcp_scsi_schedule_rports_block(adapter);
 
+	zfcp_fsf_fc_host_link_down(adapter);
+
 	if (!link_down)
 		goto out;
 
@@ -409,7 +434,7 @@
 		return;
 	}
 
-	del_timer(&req->timer);
+	del_timer_sync(&req->timer);
 	zfcp_fsf_protstatus_eval(req);
 	zfcp_fsf_fsfstatus_eval(req);
 	req->handler(req);
@@ -458,7 +483,7 @@
 #define ZFCP_FSF_PORTSPEED_128GBIT	(1 <<  8)
 #define ZFCP_FSF_PORTSPEED_NOT_NEGOTIATED (1 << 15)
 
-static u32 zfcp_fsf_convert_portspeed(u32 fsf_speed)
+u32 zfcp_fsf_convert_portspeed(u32 fsf_speed)
 {
 	u32 fdmi_speed = 0;
 	if (fsf_speed & ZFCP_FSF_PORTSPEED_1GBIT)
@@ -488,40 +513,24 @@
 {
 	struct fsf_qtcb_bottom_config *bottom = &req->qtcb->bottom.config;
 	struct zfcp_adapter *adapter = req->adapter;
-	struct Scsi_Host *shost = adapter->scsi_host;
-	struct fc_els_flogi *nsp, *plogi;
+	struct fc_els_flogi *plogi;
 
 	/* adjust pointers for missing command code */
-	nsp = (struct fc_els_flogi *) ((u8 *)&bottom->nport_serv_param
-					- sizeof(u32));
 	plogi = (struct fc_els_flogi *) ((u8 *)&bottom->plogi_payload
 					- sizeof(u32));
 
 	if (req->data)
 		memcpy(req->data, bottom, sizeof(*bottom));
 
-	fc_host_port_name(shost) = be64_to_cpu(nsp->fl_wwpn);
-	fc_host_node_name(shost) = be64_to_cpu(nsp->fl_wwnn);
-	fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3;
-
 	adapter->timer_ticks = bottom->timer_interval & ZFCP_FSF_TIMER_INT_MASK;
 	adapter->stat_read_buf_num = max(bottom->status_read_buf_num,
 					 (u16)FSF_STATUS_READS_RECOM);
 
-	if (fc_host_permanent_port_name(shost) == -1)
-		fc_host_permanent_port_name(shost) = fc_host_port_name(shost);
-
-	zfcp_scsi_set_prot(adapter);
-
 	/* no error return above here, otherwise must fix call chains */
 	/* do not evaluate invalid fields */
 	if (req->qtcb->header.fsf_status == FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE)
 		return 0;
 
-	fc_host_port_id(shost) = ntoh24(bottom->s_id);
-	fc_host_speed(shost) =
-		zfcp_fsf_convert_portspeed(bottom->fc_link_speed);
-
 	adapter->hydra_version = bottom->adapter_type;
 
 	switch (bottom->fc_topology) {
@@ -529,17 +538,10 @@
 		adapter->peer_d_id = ntoh24(bottom->peer_d_id);
 		adapter->peer_wwpn = be64_to_cpu(plogi->fl_wwpn);
 		adapter->peer_wwnn = be64_to_cpu(plogi->fl_wwnn);
-		fc_host_port_type(shost) = FC_PORTTYPE_PTP;
 		break;
 	case FSF_TOPO_FABRIC:
-		if (bottom->connection_features & FSF_FEATURE_NPIV_MODE)
-			fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
-		else
-			fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
 		break;
 	case FSF_TOPO_AL:
-		fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
-		/* fall through */
 	default:
 		dev_err(&adapter->ccw_device->dev,
 			"Unknown or unsupported arbitrated loop "
@@ -554,9 +556,10 @@
 static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req)
 {
 	struct zfcp_adapter *adapter = req->adapter;
+	struct zfcp_diag_header *const diag_hdr =
+		&adapter->diagnostics->config_data.header;
 	struct fsf_qtcb *qtcb = req->qtcb;
 	struct fsf_qtcb_bottom_config *bottom = &qtcb->bottom.config;
-	struct Scsi_Host *shost = adapter->scsi_host;
 
 	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
 		return;
@@ -570,6 +573,13 @@
 
 	switch (qtcb->header.fsf_status) {
 	case FSF_GOOD:
+		/*
+		 * usually we wait with an update till the cache is too old,
+		 * but because we have the data available, update it anyway
+		 */
+		zfcp_diag_update_xdata(diag_hdr, bottom, false);
+
+		zfcp_scsi_shost_update_config_data(adapter, bottom, false);
 		if (zfcp_fsf_exchange_config_evaluate(req))
 			return;
 
@@ -585,12 +595,8 @@
 				&adapter->status);
 		break;
 	case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
-		fc_host_node_name(shost) = 0;
-		fc_host_port_name(shost) = 0;
-		fc_host_port_id(shost) = 0;
-		fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
-		fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
-		adapter->hydra_version = 0;
+		zfcp_diag_update_xdata(diag_hdr, bottom, true);
+		req->status |= ZFCP_STATUS_FSFREQ_XDATAINCOMPLETE;
 
 		/* avoids adapter shutdown to be able to recognize
 		 * events such as LINK UP */
@@ -598,6 +604,8 @@
 				&adapter->status);
 		zfcp_fsf_link_down_info_eval(req,
 			&qtcb->header.fsf_status_qual.link_down_info);
+
+		zfcp_scsi_shost_update_config_data(adapter, bottom, true);
 		if (zfcp_fsf_exchange_config_evaluate(req))
 			return;
 		break;
@@ -606,13 +614,8 @@
 		return;
 	}
 
-	if (adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT) {
+	if (adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)
 		adapter->hardware_version = bottom->hardware_version;
-		memcpy(fc_host_serial_number(shost), bottom->serial_number,
-		       min(FC_SERIAL_NUMBER_SIZE, 17));
-		EBCASC(fc_host_serial_number(shost),
-		       min(FC_SERIAL_NUMBER_SIZE, 17));
-	}
 
 	if (FSF_QTCB_CURRENT_VERSION < bottom->low_qtcb_version) {
 		dev_err(&adapter->ccw_device->dev,
@@ -629,43 +632,145 @@
 	}
 }
 
+/*
+ * Mapping of FC Endpoint Security flag masks to mnemonics
+ *
+ * NOTE: Update macro ZFCP_FSF_MAX_FC_SECURITY_MNEMONIC_LENGTH when making any
+ *       changes.
+ */
+static const struct {
+	u32	mask;
+	char	*name;
+} zfcp_fsf_fc_security_mnemonics[] = {
+	{ FSF_FC_SECURITY_AUTH,		"Authentication" },
+	{ FSF_FC_SECURITY_ENC_FCSP2 |
+	  FSF_FC_SECURITY_ENC_ERAS,	"Encryption" },
+};
+
+/* maximum strlen(zfcp_fsf_fc_security_mnemonics[...].name) + 1 */
+#define ZFCP_FSF_MAX_FC_SECURITY_MNEMONIC_LENGTH 15
+
+/**
+ * zfcp_fsf_scnprint_fc_security() - translate FC Endpoint Security flags into
+ *                                   mnemonics and place in a buffer
+ * @buf        : the buffer to place the translated FC Endpoint Security flag(s)
+ *               into
+ * @size       : the size of the buffer, including the trailing null space
+ * @fc_security: one or more FC Endpoint Security flags, or zero
+ * @fmt        : specifies whether a list or a single item is to be put into the
+ *               buffer
+ *
+ * The Fibre Channel (FC) Endpoint Security flags are translated into mnemonics.
+ * If the FC Endpoint Security flags are zero "none" is placed into the buffer.
+ *
+ * With ZFCP_FSF_PRINT_FMT_LIST the mnemonics are placed as a list separated by
+ * a comma followed by a space into the buffer. If one or more FC Endpoint
+ * Security flags cannot be translated into a mnemonic, as they are undefined
+ * in zfcp_fsf_fc_security_mnemonics, their bitwise ORed value in hexadecimal
+ * representation is placed into the buffer.
+ *
+ * With ZFCP_FSF_PRINT_FMT_SINGLEITEM only one single mnemonic is placed into
+ * the buffer. If the FC Endpoint Security flag cannot be translated, as it is
+ * undefined in zfcp_fsf_fc_security_mnemonics, its value in hexadecimal
+ * representation is placed into the buffer. If more than one FC Endpoint
+ * Security flag was specified, their value in hexadecimal representation is
+ * placed into the buffer. The macro ZFCP_FSF_MAX_FC_SECURITY_MNEMONIC_LENGTH
+ * can be used to define a buffer that is large enough to hold one mnemonic.
+ *
+ * Return: The number of characters written into buf not including the trailing
+ *         '\0'. If size is == 0 the function returns 0.
+ */
+ssize_t zfcp_fsf_scnprint_fc_security(char *buf, size_t size, u32 fc_security,
+				      enum zfcp_fsf_print_fmt fmt)
+{
+	const char *prefix = "";
+	ssize_t len = 0;
+	int i;
+
+	if (fc_security == 0)
+		return scnprintf(buf, size, "none");
+	if (fmt == ZFCP_FSF_PRINT_FMT_SINGLEITEM && hweight32(fc_security) != 1)
+		return scnprintf(buf, size, "0x%08x", fc_security);
+
+	for (i = 0; i < ARRAY_SIZE(zfcp_fsf_fc_security_mnemonics); i++) {
+		if (!(fc_security & zfcp_fsf_fc_security_mnemonics[i].mask))
+			continue;
+
+		len += scnprintf(buf + len, size - len, "%s%s", prefix,
+				 zfcp_fsf_fc_security_mnemonics[i].name);
+		prefix = ", ";
+		fc_security &= ~zfcp_fsf_fc_security_mnemonics[i].mask;
+	}
+
+	if (fc_security != 0)
+		len += scnprintf(buf + len, size - len, "%s0x%08x",
+				 prefix, fc_security);
+
+	return len;
+}
+
+static void zfcp_fsf_dbf_adapter_fc_security(struct zfcp_adapter *adapter,
+					     struct zfcp_fsf_req *req)
+{
+	if (adapter->fc_security_algorithms ==
+	    adapter->fc_security_algorithms_old) {
+		/* no change, no trace */
+		return;
+	}
+
+	zfcp_dbf_hba_fsf_fces("fsfcesa", req, ZFCP_DBF_INVALID_WWPN,
+			      adapter->fc_security_algorithms_old,
+			      adapter->fc_security_algorithms);
+
+	adapter->fc_security_algorithms_old = adapter->fc_security_algorithms;
+}
+
 static void zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *req)
 {
 	struct zfcp_adapter *adapter = req->adapter;
 	struct fsf_qtcb_bottom_port *bottom = &req->qtcb->bottom.port;
-	struct Scsi_Host *shost = adapter->scsi_host;
 
 	if (req->data)
 		memcpy(req->data, bottom, sizeof(*bottom));
 
-	if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) {
-		fc_host_permanent_port_name(shost) = bottom->wwpn;
-	} else
-		fc_host_permanent_port_name(shost) = fc_host_port_name(shost);
-	fc_host_maxframe_size(shost) = bottom->maximum_frame_size;
-	fc_host_supported_speeds(shost) =
-		zfcp_fsf_convert_portspeed(bottom->supported_speed);
-	memcpy(fc_host_supported_fc4s(shost), bottom->supported_fc4_types,
-	       FC_FC4_LIST_SIZE);
-	memcpy(fc_host_active_fc4s(shost), bottom->active_fc4_types,
-	       FC_FC4_LIST_SIZE);
+	if (adapter->adapter_features & FSF_FEATURE_FC_SECURITY)
+		adapter->fc_security_algorithms =
+			bottom->fc_security_algorithms;
+	else
+		adapter->fc_security_algorithms = 0;
+	zfcp_fsf_dbf_adapter_fc_security(adapter, req);
 }
 
 static void zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *req)
 {
+	struct zfcp_diag_header *const diag_hdr =
+		&req->adapter->diagnostics->port_data.header;
 	struct fsf_qtcb *qtcb = req->qtcb;
+	struct fsf_qtcb_bottom_port *bottom = &qtcb->bottom.port;
 
 	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
 		return;
 
 	switch (qtcb->header.fsf_status) {
 	case FSF_GOOD:
+		/*
+		 * usually we wait with an update till the cache is too old,
+		 * but because we have the data available, update it anyway
+		 */
+		zfcp_diag_update_xdata(diag_hdr, bottom, false);
+
+		zfcp_scsi_shost_update_port_data(req->adapter, bottom);
 		zfcp_fsf_exchange_port_evaluate(req);
 		break;
 	case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
-		zfcp_fsf_exchange_port_evaluate(req);
+		zfcp_diag_update_xdata(diag_hdr, bottom, true);
+		req->status |= ZFCP_STATUS_FSFREQ_XDATAINCOMPLETE;
+
 		zfcp_fsf_link_down_info_eval(req,
 			&qtcb->header.fsf_status_qual.link_down_info);
+
+		zfcp_scsi_shost_update_port_data(req->adapter, bottom);
+		zfcp_fsf_exchange_port_evaluate(req);
 		break;
 	}
 }
@@ -755,14 +860,14 @@
 	const bool is_srb = zfcp_fsf_req_is_status_read_buffer(req);
 	struct zfcp_adapter *adapter = req->adapter;
 	struct zfcp_qdio *qdio = adapter->qdio;
-	int req_id = req->req_id;
+	unsigned long req_id = req->req_id;
 
 	zfcp_reqlist_add(adapter->req_list, req);
 
 	req->qdio_req.qdio_outb_usage = atomic_read(&qdio->req_q_free);
 	req->issued = get_tod_clock();
 	if (zfcp_qdio_send(qdio, &req->qdio_req)) {
-		del_timer(&req->timer);
+		del_timer_sync(&req->timer);
 		/* lookup request again, list might have changed */
 		zfcp_reqlist_find_rm(adapter->req_list, req_id);
 		zfcp_erp_adapter_reopen(adapter, 0, "fsrs__1");
@@ -889,7 +994,7 @@
 		switch (fsq->word[0]) {
 		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
 			zfcp_fc_test_link(zfcp_sdev->port);
-			/* fall through */
+			fallthrough;
 		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
 			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 			break;
@@ -984,7 +1089,7 @@
 		break;
 	case FSF_PORT_HANDLE_NOT_VALID:
 		zfcp_erp_adapter_reopen(adapter, 0, "fsscth1");
-		/* fall through */
+		fallthrough;
 	case FSF_GENERIC_COMMAND_REJECTED:
 	case FSF_PAYLOAD_SIZE_MISMATCH:
 	case FSF_REQUEST_SIZE_TOO_LARGE:
@@ -1170,7 +1275,7 @@
 		break;
 	case FSF_SBAL_MISMATCH:
 		/* should never occur, avoided in zfcp_fsf_send_els */
-		/* fall through */
+		fallthrough;
 	default:
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
@@ -1261,7 +1366,9 @@
 
 	req->qtcb->bottom.config.feature_selection =
 			FSF_FEATURE_NOTIFICATION_LOST |
-			FSF_FEATURE_UPDATE_ALERT;
+			FSF_FEATURE_UPDATE_ALERT |
+			FSF_FEATURE_REQUEST_SFP_DATA |
+			FSF_FEATURE_FC_SECURITY;
 	req->erp_action = erp_action;
 	req->handler = zfcp_fsf_exchange_config_data_handler;
 	erp_action->fsf_req_id = req->req_id;
@@ -1278,6 +1385,19 @@
 	return retval;
 }
 
+
+/**
+ * zfcp_fsf_exchange_config_data_sync() - Request information about FCP channel.
+ * @qdio: pointer to the QDIO-Queue to use for sending the command.
+ * @data: pointer to the QTCB-Bottom for storing the result of the command,
+ *	  might be %NULL.
+ *
+ * Returns:
+ * * 0		- Exchange Config Data was successful, @data is complete
+ * * -EIO	- Exchange Config Data was not successful, @data is invalid
+ * * -EAGAIN	- @data contains incomplete data
+ * * -ENOMEM	- Some memory allocation failed along the way
+ */
 int zfcp_fsf_exchange_config_data_sync(struct zfcp_qdio *qdio,
 				       struct fsf_qtcb_bottom_config *data)
 {
@@ -1301,7 +1421,9 @@
 
 	req->qtcb->bottom.config.feature_selection =
 			FSF_FEATURE_NOTIFICATION_LOST |
-			FSF_FEATURE_UPDATE_ALERT;
+			FSF_FEATURE_UPDATE_ALERT |
+			FSF_FEATURE_REQUEST_SFP_DATA |
+			FSF_FEATURE_FC_SECURITY;
 
 	if (data)
 		req->data = data;
@@ -1309,9 +1431,16 @@
 	zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
 	retval = zfcp_fsf_req_send(req);
 	spin_unlock_irq(&qdio->req_q_lock);
+
 	if (!retval) {
 		/* NOTE: ONLY TOUCH SYNC req AGAIN ON req->completion. */
 		wait_for_completion(&req->completion);
+
+		if (req->status &
+		    (ZFCP_STATUS_FSFREQ_ERROR | ZFCP_STATUS_FSFREQ_DISMISSED))
+			retval = -EIO;
+		else if (req->status & ZFCP_STATUS_FSFREQ_XDATAINCOMPLETE)
+			retval = -EAGAIN;
 	}
 
 	zfcp_fsf_req_free(req);
@@ -1369,10 +1498,17 @@
 }
 
 /**
- * zfcp_fsf_exchange_port_data_sync - request information about local port
- * @qdio: pointer to struct zfcp_qdio
- * @data: pointer to struct fsf_qtcb_bottom_port
- * Returns: 0 on success, error otherwise
+ * zfcp_fsf_exchange_port_data_sync() - Request information about local port.
+ * @qdio: pointer to the QDIO-Queue to use for sending the command.
+ * @data: pointer to the QTCB-Bottom for storing the result of the command,
+ *	  might be %NULL.
+ *
+ * Returns:
+ * * 0		- Exchange Port Data was successful, @data is complete
+ * * -EIO	- Exchange Port Data was not successful, @data is invalid
+ * * -EAGAIN	- @data contains incomplete data
+ * * -ENOMEM	- Some memory allocation failed along the way
+ * * -EOPNOTSUPP	- This operation is not supported
  */
 int zfcp_fsf_exchange_port_data_sync(struct zfcp_qdio *qdio,
 				     struct fsf_qtcb_bottom_port *data)
@@ -1408,10 +1544,15 @@
 	if (!retval) {
 		/* NOTE: ONLY TOUCH SYNC req AGAIN ON req->completion. */
 		wait_for_completion(&req->completion);
+
+		if (req->status &
+		    (ZFCP_STATUS_FSFREQ_ERROR | ZFCP_STATUS_FSFREQ_DISMISSED))
+			retval = -EIO;
+		else if (req->status & ZFCP_STATUS_FSFREQ_XDATAINCOMPLETE)
+			retval = -EAGAIN;
 	}
 
 	zfcp_fsf_req_free(req);
-
 	return retval;
 
 out_unlock:
@@ -1419,10 +1560,117 @@
 	return retval;
 }
 
+static void zfcp_fsf_log_port_fc_security(struct zfcp_port *port,
+					  struct zfcp_fsf_req *req)
+{
+	char mnemonic_old[ZFCP_FSF_MAX_FC_SECURITY_MNEMONIC_LENGTH];
+	char mnemonic_new[ZFCP_FSF_MAX_FC_SECURITY_MNEMONIC_LENGTH];
+
+	if (port->connection_info == port->connection_info_old) {
+		/* no change, no log nor trace */
+		return;
+	}
+
+	zfcp_dbf_hba_fsf_fces("fsfcesp", req, port->wwpn,
+			      port->connection_info_old,
+			      port->connection_info);
+
+	zfcp_fsf_scnprint_fc_security(mnemonic_old, sizeof(mnemonic_old),
+				      port->connection_info_old,
+				      ZFCP_FSF_PRINT_FMT_SINGLEITEM);
+	zfcp_fsf_scnprint_fc_security(mnemonic_new, sizeof(mnemonic_new),
+				      port->connection_info,
+				      ZFCP_FSF_PRINT_FMT_SINGLEITEM);
+
+	if (strncmp(mnemonic_old, mnemonic_new,
+		    ZFCP_FSF_MAX_FC_SECURITY_MNEMONIC_LENGTH) == 0) {
+		/* no change in string representation, no log */
+		goto out;
+	}
+
+	if (port->connection_info_old == 0) {
+		/* activation */
+		dev_info(&port->adapter->ccw_device->dev,
+			 "FC Endpoint Security of connection to remote port 0x%16llx enabled: %s\n",
+			 port->wwpn, mnemonic_new);
+	} else if (port->connection_info == 0) {
+		/* deactivation */
+		dev_warn(&port->adapter->ccw_device->dev,
+			 "FC Endpoint Security of connection to remote port 0x%16llx disabled: was %s\n",
+			 port->wwpn, mnemonic_old);
+	} else {
+		/* change */
+		dev_warn(&port->adapter->ccw_device->dev,
+			 "FC Endpoint Security of connection to remote port 0x%16llx changed: from %s to %s\n",
+			 port->wwpn, mnemonic_old, mnemonic_new);
+	}
+
+out:
+	port->connection_info_old = port->connection_info;
+}
+
+static void zfcp_fsf_log_security_error(const struct device *dev, u32 fsf_sqw0,
+					u64 wwpn)
+{
+	switch (fsf_sqw0) {
+
+	/*
+	 * Open Port command error codes
+	 */
+
+	case FSF_SQ_SECURITY_REQUIRED:
+		dev_warn_ratelimited(dev,
+				     "FC Endpoint Security error: FC security is required but not supported or configured on remote port 0x%016llx\n",
+				     wwpn);
+		break;
+	case FSF_SQ_SECURITY_TIMEOUT:
+		dev_warn_ratelimited(dev,
+				     "FC Endpoint Security error: a timeout prevented opening remote port 0x%016llx\n",
+				     wwpn);
+		break;
+	case FSF_SQ_SECURITY_KM_UNAVAILABLE:
+		dev_warn_ratelimited(dev,
+				     "FC Endpoint Security error: opening remote port 0x%016llx failed because local and external key manager cannot communicate\n",
+				     wwpn);
+		break;
+	case FSF_SQ_SECURITY_RKM_UNAVAILABLE:
+		dev_warn_ratelimited(dev,
+				     "FC Endpoint Security error: opening remote port 0x%016llx failed because it cannot communicate with the external key manager\n",
+				     wwpn);
+		break;
+	case FSF_SQ_SECURITY_AUTH_FAILURE:
+		dev_warn_ratelimited(dev,
+				     "FC Endpoint Security error: the device could not verify the identity of remote port 0x%016llx\n",
+				     wwpn);
+		break;
+
+	/*
+	 * Send FCP command error codes
+	 */
+
+	case FSF_SQ_SECURITY_ENC_FAILURE:
+		dev_warn_ratelimited(dev,
+				     "FC Endpoint Security error: FC connection to remote port 0x%016llx closed because encryption broke down\n",
+				     wwpn);
+		break;
+
+	/*
+	 * Unknown error codes
+	 */
+
+	default:
+		dev_warn_ratelimited(dev,
+				     "FC Endpoint Security error: the device issued an unknown error code 0x%08x related to the FC connection to remote port 0x%016llx\n",
+				     fsf_sqw0, wwpn);
+	}
+}
+
 static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req)
 {
+	struct zfcp_adapter *adapter = req->adapter;
 	struct zfcp_port *port = req->data;
 	struct fsf_qtcb_header *header = &req->qtcb->header;
+	struct fsf_qtcb_bottom_support *bottom = &req->qtcb->bottom.support;
 	struct fc_els_flogi *plogi;
 
 	if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
@@ -1432,7 +1680,7 @@
 	case FSF_PORT_ALREADY_OPEN:
 		break;
 	case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED:
-		dev_warn(&req->adapter->ccw_device->dev,
+		dev_warn(&adapter->ccw_device->dev,
 			 "Not enough FCP adapter resources to open "
 			 "remote port 0x%016Lx\n",
 			 (unsigned long long)port->wwpn);
@@ -1440,11 +1688,17 @@
 					 ZFCP_STATUS_COMMON_ERP_FAILED);
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
+	case FSF_SECURITY_ERROR:
+		zfcp_fsf_log_security_error(&req->adapter->ccw_device->dev,
+					    header->fsf_status_qual.word[0],
+					    port->wwpn);
+		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		break;
 	case FSF_ADAPTER_STATUS_AVAILABLE:
 		switch (header->fsf_status_qual.word[0]) {
 		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
 			/* no zfcp_fc_test_link() with failed open port */
-			/* fall through */
+			fallthrough;
 		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
 		case FSF_SQ_NO_RETRY_POSSIBLE:
 			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -1453,6 +1707,11 @@
 		break;
 	case FSF_GOOD:
 		port->handle = header->port_handle;
+		if (adapter->adapter_features & FSF_FEATURE_FC_SECURITY)
+			port->connection_info = bottom->connection_info;
+		else
+			port->connection_info = 0;
+		zfcp_fsf_log_port_fc_security(port, req);
 		atomic_or(ZFCP_STATUS_COMMON_OPEN |
 				ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
 		atomic_andnot(ZFCP_STATUS_COMMON_ACCESS_BOXED,
@@ -1472,10 +1731,9 @@
 		 * another GID_PN straight after a port has been opened.
 		 * Alternately, an ADISC/PDISC ELS should suffice, as well.
 		 */
-		plogi = (struct fc_els_flogi *) req->qtcb->bottom.support.els;
-		if (req->qtcb->bottom.support.els1_length >=
-		    FSF_PLOGI_MIN_LEN)
-				zfcp_fc_plogi_evaluate(port, plogi);
+		plogi = (struct fc_els_flogi *) bottom->els;
+		if (bottom->els1_length >= FSF_PLOGI_MIN_LEN)
+			zfcp_fc_plogi_evaluate(port, plogi);
 		break;
 	case FSF_UNKNOWN_OP_SUBTYPE:
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -1613,19 +1871,19 @@
 	case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED:
 		dev_warn(&req->adapter->ccw_device->dev,
 			 "Opening WKA port 0x%x failed\n", wka_port->d_id);
-		/* fall through */
+		fallthrough;
 	case FSF_ADAPTER_STATUS_AVAILABLE:
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE;
 		break;
 	case FSF_GOOD:
 		wka_port->handle = header->port_handle;
-		/* fall through */
+		fallthrough;
 	case FSF_PORT_ALREADY_OPEN:
 		wka_port->status = ZFCP_FC_WKA_PORT_ONLINE;
 	}
 out:
-	wake_up(&wka_port->completion_wq);
+	wake_up(&wka_port->opened);
 }
 
 /**
@@ -1684,7 +1942,7 @@
 	}
 
 	wka_port->status = ZFCP_FC_WKA_PORT_OFFLINE;
-	wake_up(&wka_port->completion_wq);
+	wake_up(&wka_port->closed);
 }
 
 /**
@@ -1763,7 +2021,6 @@
 	case FSF_ADAPTER_STATUS_AVAILABLE:
 		switch (header->fsf_status_qual.word[0]) {
 		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
-			/* fall through */
 		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
 			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 			break;
@@ -1848,7 +2105,7 @@
 
 	case FSF_PORT_HANDLE_NOT_VALID:
 		zfcp_erp_adapter_reopen(adapter, 0, "fsouh_1");
-		/* fall through */
+		fallthrough;
 	case FSF_LUN_ALREADY_OPEN:
 		break;
 	case FSF_PORT_BOXED:
@@ -1879,7 +2136,7 @@
 			 (unsigned long long)zfcp_scsi_dev_lun(sdev),
 			 (unsigned long long)zfcp_sdev->port->wwpn);
 		zfcp_erp_set_lun_status(sdev, ZFCP_STATUS_COMMON_ERP_FAILED);
-		/* fall through */
+		fallthrough;
 	case FSF_INVALID_COMMAND_OPTION:
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
@@ -1887,7 +2144,7 @@
 		switch (header->fsf_status_qual.word[0]) {
 		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
 			zfcp_fc_test_link(zfcp_sdev->port);
-			/* fall through */
+			fallthrough;
 		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
 			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 			break;
@@ -1981,7 +2238,7 @@
 		switch (req->qtcb->header.fsf_status_qual.word[0]) {
 		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
 			zfcp_fc_test_link(zfcp_sdev->port);
-			/* fall through */
+			fallthrough;
 		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
 			req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 			break;
@@ -2166,6 +2423,13 @@
 			zfcp_fc_test_link(zfcp_sdev->port);
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
+	case FSF_SECURITY_ERROR:
+		zfcp_fsf_log_security_error(&req->adapter->ccw_device->dev,
+					    header->fsf_status_qual.word[0],
+					    zfcp_sdev->port->wwpn);
+		zfcp_erp_port_forced_reopen(zfcp_sdev->port, 0, "fssfch7");
+		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+		break;
 	}
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/scsi/zfcp_fsf.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/scsi/zfcp_fsf.h
@@ -4,7 +4,7 @@
  *
  * Interface to the FSF support functions.
  *
- * Copyright IBM Corp. 2002, 2018
+ * Copyright IBM Corp. 2002, 2020
  */
 
 #ifndef FSF_H
@@ -78,6 +78,7 @@
 #define FSF_BLOCK_GUARD_CHECK_FAILURE		0x00000081
 #define FSF_APP_TAG_CHECK_FAILURE		0x00000082
 #define FSF_REF_TAG_CHECK_FAILURE		0x00000083
+#define FSF_SECURITY_ERROR			0x00000090
 #define FSF_ADAPTER_STATUS_AVAILABLE		0x000000AD
 #define FSF_FCP_RSP_AVAILABLE			0x000000AF
 #define FSF_UNKNOWN_COMMAND			0x000000E2
@@ -110,6 +111,14 @@
 #define FSF_PSQ_LINK_MODE_TABLE_CURRUPTED	0x00004000
 #define FSF_PSQ_LINK_NO_WWPN_ASSIGNMENT		0x00008000
 
+/* FSF status qualifier, security error */
+#define FSF_SQ_SECURITY_REQUIRED		0x00000001
+#define FSF_SQ_SECURITY_TIMEOUT			0x00000002
+#define FSF_SQ_SECURITY_KM_UNAVAILABLE		0x00000003
+#define FSF_SQ_SECURITY_RKM_UNAVAILABLE		0x00000004
+#define FSF_SQ_SECURITY_AUTH_FAILURE		0x00000005
+#define FSF_SQ_SECURITY_ENC_FAILURE		0x00000010
+
 /* payload size in status read buffer */
 #define FSF_STATUS_READ_PAYLOAD_SIZE		4032
 
@@ -163,6 +172,9 @@
 #define FSF_FEATURE_ELS_CT_CHAINED_SBALS	0x00000020
 #define FSF_FEATURE_UPDATE_ALERT		0x00000100
 #define FSF_FEATURE_MEASUREMENT_DATA		0x00000200
+#define FSF_FEATURE_REQUEST_SFP_DATA		0x00000200
+#define FSF_FEATURE_REPORT_SFP_DATA		0x00000800
+#define FSF_FEATURE_FC_SECURITY			0x00001000
 #define FSF_FEATURE_DIF_PROT_TYPE1		0x00010000
 #define FSF_FEATURE_DIX_PROT_TCPIP		0x00020000
 
@@ -172,6 +184,11 @@
 /* option */
 #define FSF_OPEN_LUN_SUPPRESS_BOXING		0x00000001
 
+/* FC security algorithms */
+#define FSF_FC_SECURITY_AUTH			0x00000001
+#define FSF_FC_SECURITY_ENC_FCSP2		0x00000002
+#define FSF_FC_SECURITY_ENC_ERAS		0x00000004
+
 struct fsf_queue_designator {
 	u8  cssid;
 	u8  chpid;
@@ -336,7 +353,8 @@
 	u8  res3[3];
 	u8  timeout;
         u32 lun_access_info;
-        u8  res4[180];
+	u32 connection_info;
+	u8  res4[176];
 	u32 els1_length;
 	u32 els2_length;
 	u32 req_buf_length;
@@ -407,7 +425,25 @@
 	u8 cp_util;
 	u8 cb_util;
 	u8 a_util;
-	u8 res2[253];
+	u8 res2;
+	s16 temperature;
+	u16 vcc;
+	u16 tx_bias;
+	u16 tx_power;
+	u16 rx_power;
+	union {
+		u16 raw;
+		struct {
+			u16 fec_active		:1;
+			u16:7;
+			u16 connector_type	:2;
+			u16 sfp_invalid		:1;
+			u16 optical_port	:1;
+			u16 port_tx_type	:4;
+		};
+	} sfp_flags;
+	u32 fc_security_algorithms;
+	u8 res3[236];
 } __attribute__ ((packed));
 
 union fsf_qtcb_bottom {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/scsi/zfcp_qdio.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/scsi/zfcp_qdio.c
@@ -4,7 +4,7 @@
  *
  * Setup and helper functions to access QDIO.
  *
- * Copyright IBM Corp. 2002, 2017
+ * Copyright IBM Corp. 2002, 2020
  */
 
 #define KMSG_COMPONENT "zfcp"
@@ -367,6 +367,18 @@
 	atomic_set(&qdio->req_q_free, 0);
 }
 
+void zfcp_qdio_shost_update(struct zfcp_adapter *const adapter,
+			    const struct zfcp_qdio *const qdio)
+{
+	struct Scsi_Host *const shost = adapter->scsi_host;
+
+	if (shost == NULL)
+		return;
+
+	shost->sg_tablesize = qdio->max_sbale_per_req;
+	shost->max_sectors = qdio->max_sbale_per_req * 8;
+}
+
 /**
  * zfcp_qdio_open - prepare and initialize response queue
  * @qdio: pointer to struct zfcp_qdio
@@ -429,10 +441,7 @@
 	atomic_set(&qdio->req_q_free, QDIO_MAX_BUFFERS_PER_Q);
 	atomic_or(ZFCP_STATUS_ADAPTER_QDIOUP, &qdio->adapter->status);
 
-	if (adapter->scsi_host) {
-		adapter->scsi_host->sg_tablesize = qdio->max_sbale_per_req;
-		adapter->scsi_host->max_sectors = qdio->max_sbale_per_req * 8;
-	}
+	zfcp_qdio_shost_update(adapter, qdio);
 
 	return 0;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/scsi/zfcp_scsi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/scsi/zfcp_scsi.c
@@ -4,7 +4,7 @@
  *
  * Interface to Linux SCSI midlayer.
  *
- * Copyright IBM Corp. 2002, 2018
+ * Copyright IBM Corp. 2002, 2020
  */
 
 #define KMSG_COMPONENT "zfcp"
@@ -451,26 +451,39 @@
 };
 
 /**
- * zfcp_scsi_adapter_register - Register SCSI and FC host with SCSI midlayer
+ * zfcp_scsi_adapter_register() - Allocate and register SCSI and FC host with
+ *				  SCSI midlayer
  * @adapter: The zfcp adapter to register with the SCSI midlayer
+ *
+ * Allocates the SCSI host object for the given adapter, sets basic properties
+ * (such as the transport template, QDIO limits, ...), and registers it with
+ * the midlayer.
+ *
+ * During registration with the midlayer the corresponding FC host object for
+ * the referenced transport class is also implicitely allocated.
+ *
+ * Upon success adapter->scsi_host is set, and upon failure it remains NULL. If
+ * adapter->scsi_host is already set, nothing is done.
+ *
+ * Return:
+ * * 0	     - Allocation and registration was successful
+ * * -EEXIST - SCSI and FC host did already exist, nothing was done, nothing
+ *	       was changed
+ * * -EIO    - Allocation or registration failed
  */
 int zfcp_scsi_adapter_register(struct zfcp_adapter *adapter)
 {
 	struct ccw_dev_id dev_id;
 
 	if (adapter->scsi_host)
-		return 0;
+		return -EEXIST;
 
 	ccw_device_get_id(adapter->ccw_device, &dev_id);
 	/* register adapter as SCSI host with mid layer of SCSI stack */
 	adapter->scsi_host = scsi_host_alloc(&zfcp_scsi_host_template,
 					     sizeof (struct zfcp_adapter *));
-	if (!adapter->scsi_host) {
-		dev_err(&adapter->ccw_device->dev,
-			"Registering the FCP device with the "
-			"SCSI stack failed\n");
-		return -EIO;
-	}
+	if (!adapter->scsi_host)
+		goto err_out;
 
 	/* tell the SCSI stack some characteristics of this adapter */
 	adapter->scsi_host->max_id = 511;
@@ -480,14 +493,23 @@
 	adapter->scsi_host->max_cmd_len = 16; /* in struct fcp_cmnd */
 	adapter->scsi_host->transportt = zfcp_scsi_transport_template;
 
+	/* make all basic properties known at registration time */
+	zfcp_qdio_shost_update(adapter, adapter->qdio);
+	zfcp_scsi_set_prot(adapter);
+
 	adapter->scsi_host->hostdata[0] = (unsigned long) adapter;
 
 	if (scsi_add_host(adapter->scsi_host, &adapter->ccw_device->dev)) {
 		scsi_host_put(adapter->scsi_host);
-		return -EIO;
+		goto err_out;
 	}
 
 	return 0;
+err_out:
+	adapter->scsi_host = NULL;
+	dev_err(&adapter->ccw_device->dev,
+		"Registering the FCP device with the SCSI stack failed\n");
+	return -EIO;
 }
 
 /**
@@ -605,7 +627,7 @@
 		return NULL;
 
 	ret = zfcp_fsf_exchange_port_data_sync(adapter->qdio, data);
-	if (ret) {
+	if (ret != 0 && ret != -EAGAIN) {
 		kfree(data);
 		return NULL;
 	}
@@ -634,7 +656,7 @@
 		return;
 
 	ret = zfcp_fsf_exchange_port_data_sync(adapter->qdio, data);
-	if (ret)
+	if (ret != 0 && ret != -EAGAIN)
 		kfree(data);
 	else {
 		adapter->stats_reset = jiffies/HZ;
@@ -841,6 +863,95 @@
 	set_host_byte(scmd, DID_SOFT_ERROR);
 }
 
+void zfcp_scsi_shost_update_config_data(
+	struct zfcp_adapter *const adapter,
+	const struct fsf_qtcb_bottom_config *const bottom,
+	const bool bottom_incomplete)
+{
+	struct Scsi_Host *const shost = adapter->scsi_host;
+	const struct fc_els_flogi *nsp, *plogi;
+
+	if (shost == NULL)
+		return;
+
+	snprintf(fc_host_firmware_version(shost), FC_VERSION_STRING_SIZE,
+		 "0x%08x", bottom->lic_version);
+
+	if (adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT) {
+		snprintf(fc_host_hardware_version(shost),
+			 FC_VERSION_STRING_SIZE,
+			 "0x%08x", bottom->hardware_version);
+		memcpy(fc_host_serial_number(shost), bottom->serial_number,
+		       min(FC_SERIAL_NUMBER_SIZE, 17));
+		EBCASC(fc_host_serial_number(shost),
+		       min(FC_SERIAL_NUMBER_SIZE, 17));
+	}
+
+	/* adjust pointers for missing command code */
+	nsp = (struct fc_els_flogi *) ((u8 *)&bottom->nport_serv_param
+					- sizeof(u32));
+	plogi = (struct fc_els_flogi *) ((u8 *)&bottom->plogi_payload
+					- sizeof(u32));
+
+	snprintf(fc_host_manufacturer(shost), FC_SERIAL_NUMBER_SIZE, "%s",
+		 "IBM");
+	fc_host_port_name(shost) = be64_to_cpu(nsp->fl_wwpn);
+	fc_host_node_name(shost) = be64_to_cpu(nsp->fl_wwnn);
+	fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3;
+
+	zfcp_scsi_set_prot(adapter);
+
+	/* do not evaluate invalid fields */
+	if (bottom_incomplete)
+		return;
+
+	fc_host_port_id(shost) = ntoh24(bottom->s_id);
+	fc_host_speed(shost) =
+		zfcp_fsf_convert_portspeed(bottom->fc_link_speed);
+
+	snprintf(fc_host_model(shost), FC_SYMBOLIC_NAME_SIZE, "0x%04x",
+		 bottom->adapter_type);
+
+	switch (bottom->fc_topology) {
+	case FSF_TOPO_P2P:
+		fc_host_port_type(shost) = FC_PORTTYPE_PTP;
+		fc_host_fabric_name(shost) = 0;
+		break;
+	case FSF_TOPO_FABRIC:
+		fc_host_fabric_name(shost) = be64_to_cpu(plogi->fl_wwnn);
+		if (bottom->connection_features & FSF_FEATURE_NPIV_MODE)
+			fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
+		else
+			fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
+		break;
+	case FSF_TOPO_AL:
+		fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
+		fallthrough;
+	default:
+		fc_host_fabric_name(shost) = 0;
+		break;
+	}
+}
+
+void zfcp_scsi_shost_update_port_data(
+	struct zfcp_adapter *const adapter,
+	const struct fsf_qtcb_bottom_port *const bottom)
+{
+	struct Scsi_Host *const shost = adapter->scsi_host;
+
+	if (shost == NULL)
+		return;
+
+	fc_host_permanent_port_name(shost) = bottom->wwpn;
+	fc_host_maxframe_size(shost) = bottom->maximum_frame_size;
+	fc_host_supported_speeds(shost) =
+		zfcp_fsf_convert_portspeed(bottom->supported_speed);
+	memcpy(fc_host_supported_fc4s(shost), bottom->supported_fc4_types,
+	       FC_FC4_LIST_SIZE);
+	memcpy(fc_host_active_fc4s(shost), bottom->active_fc4_types,
+	       FC_FC4_LIST_SIZE);
+}
+
 struct fc_function_template zfcp_transport_functions = {
 	.show_starget_port_id = 1,
 	.show_starget_port_name = 1,
@@ -856,6 +967,10 @@
 	.show_host_supported_speeds = 1,
 	.show_host_maxframe_size = 1,
 	.show_host_serial_number = 1,
+	.show_host_manufacturer = 1,
+	.show_host_model = 1,
+	.show_host_hardware_version = 1,
+	.show_host_firmware_version = 1,
 	.get_fc_host_stats = zfcp_scsi_get_fc_host_stats,
 	.reset_fc_host_stats = zfcp_scsi_reset_fc_host_stats,
 	.set_rport_dev_loss_tmo = zfcp_scsi_set_rport_dev_loss_tmo,
@@ -871,5 +986,6 @@
 	.show_host_symbolic_name = 1,
 	.show_host_speed = 1,
 	.show_host_port_id = 1,
+	.show_host_fabric_name = 1,
 	.dd_bsg_size = sizeof(struct zfcp_fsf_ct_els),
 };
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/scsi/zfcp_sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/scsi/zfcp_sysfs.c
@@ -4,13 +4,14 @@
  *
  * sysfs attributes.
  *
- * Copyright IBM Corp. 2008, 2010
+ * Copyright IBM Corp. 2008, 2020
  */
 
 #define KMSG_COMPONENT "zfcp"
 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
 #include <linux/slab.h>
+#include "zfcp_diag.h"
 #include "zfcp_ext.h"
 
 #define ZFCP_DEV_ATTR(_feat, _name, _mode, _show, _store) \
@@ -215,20 +216,32 @@
 {
 	struct ccw_device *cdev = to_ccwdev(dev);
 	struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
+	int retval = 0;
 
 	if (!adapter)
 		return -ENODEV;
 
 	/*
+	 * If `scsi_host` is missing, we can't schedule `scan_work`, as it
+	 * makes use of the corresponding fc_host object. But this state is
+	 * only possible if xconfig/xport data has never completed yet,
+	 * and we couldn't successfully scan for ports anyway.
+	 */
+	if (adapter->scsi_host == NULL) {
+		retval = -ENODEV;
+		goto out;
+	}
+
+	/*
 	 * Users wish is our command: immediately schedule and flush a
 	 * worker to conduct a synchronous port scan, that is, neither
 	 * a random delay nor a rate limit is applied here.
 	 */
 	queue_delayed_work(adapter->work_queue, &adapter->scan_work, 0);
 	flush_delayed_work(&adapter->scan_work);
+out:
 	zfcp_ccw_adapter_put(adapter);
-
-	return (ssize_t) count;
+	return retval ? retval : (ssize_t) count;
 }
 static ZFCP_DEV_ATTR(adapter, port_rescan, S_IWUSR, NULL,
 		     zfcp_sysfs_port_rescan_store);
@@ -325,6 +338,86 @@
 static ZFCP_DEV_ATTR(adapter, port_remove, S_IWUSR, NULL,
 		     zfcp_sysfs_port_remove_store);
 
+static ssize_t
+zfcp_sysfs_adapter_diag_max_age_show(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(to_ccwdev(dev));
+	ssize_t rc;
+
+	if (!adapter)
+		return -ENODEV;
+
+	/* ceil(log(2^64 - 1) / log(10)) = 20 */
+	rc = scnprintf(buf, 20 + 2, "%lu\n", adapter->diagnostics->max_age);
+
+	zfcp_ccw_adapter_put(adapter);
+	return rc;
+}
+
+static ssize_t
+zfcp_sysfs_adapter_diag_max_age_store(struct device *dev,
+				      struct device_attribute *attr,
+				      const char *buf, size_t count)
+{
+	struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(to_ccwdev(dev));
+	unsigned long max_age;
+	ssize_t rc;
+
+	if (!adapter)
+		return -ENODEV;
+
+	rc = kstrtoul(buf, 10, &max_age);
+	if (rc != 0)
+		goto out;
+
+	adapter->diagnostics->max_age = max_age;
+
+	rc = count;
+out:
+	zfcp_ccw_adapter_put(adapter);
+	return rc;
+}
+static ZFCP_DEV_ATTR(adapter, diag_max_age, 0644,
+		     zfcp_sysfs_adapter_diag_max_age_show,
+		     zfcp_sysfs_adapter_diag_max_age_store);
+
+static ssize_t zfcp_sysfs_adapter_fc_security_show(
+	struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct ccw_device *cdev = to_ccwdev(dev);
+	struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
+	unsigned int status;
+	int i;
+
+	if (!adapter)
+		return -ENODEV;
+
+	/*
+	 * Adapter status COMMON_OPEN implies xconf data and xport data
+	 * was done. Adapter FC Endpoint Security capability remains
+	 * unchanged in case of COMMON_ERP_FAILED (e.g. due to local link
+	 * down).
+	 */
+	status = atomic_read(&adapter->status);
+	if (0 == (status & ZFCP_STATUS_COMMON_OPEN))
+		i = sprintf(buf, "unknown\n");
+	else if (!(adapter->adapter_features & FSF_FEATURE_FC_SECURITY))
+		i = sprintf(buf, "unsupported\n");
+	else {
+		i = zfcp_fsf_scnprint_fc_security(
+			buf, PAGE_SIZE - 1, adapter->fc_security_algorithms,
+			ZFCP_FSF_PRINT_FMT_LIST);
+		i += scnprintf(buf + i, PAGE_SIZE - i, "\n");
+	}
+
+	zfcp_ccw_adapter_put(adapter);
+	return i;
+}
+static ZFCP_DEV_ATTR(adapter, fc_security, S_IRUGO,
+		     zfcp_sysfs_adapter_fc_security_show,
+		     NULL);
+
 static struct attribute *zfcp_adapter_attrs[] = {
 	&dev_attr_adapter_failed.attr,
 	&dev_attr_adapter_in_recovery.attr,
@@ -337,6 +430,8 @@
 	&dev_attr_adapter_lic_version.attr,
 	&dev_attr_adapter_status.attr,
 	&dev_attr_adapter_hardware_version.attr,
+	&dev_attr_adapter_diag_max_age.attr,
+	&dev_attr_adapter_fc_security.attr,
 	NULL
 };
 
@@ -380,6 +475,36 @@
 }
 static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store);
 
+static ssize_t zfcp_sysfs_port_fc_security_show(struct device *dev,
+						struct device_attribute *attr,
+						char *buf)
+{
+	struct zfcp_port *port = container_of(dev, struct zfcp_port, dev);
+	struct zfcp_adapter *adapter = port->adapter;
+	unsigned int status = atomic_read(&port->status);
+	int i;
+
+	if (0 == (status & ZFCP_STATUS_COMMON_OPEN) ||
+	    0 == (status & ZFCP_STATUS_COMMON_UNBLOCKED) ||
+	    0 == (status & ZFCP_STATUS_PORT_PHYS_OPEN) ||
+	    0 != (status & ZFCP_STATUS_COMMON_ERP_FAILED) ||
+	    0 != (status & ZFCP_STATUS_COMMON_ACCESS_BOXED))
+		i = sprintf(buf, "unknown\n");
+	else if (!(adapter->adapter_features & FSF_FEATURE_FC_SECURITY))
+		i = sprintf(buf, "unsupported\n");
+	else {
+		i = zfcp_fsf_scnprint_fc_security(
+			buf, PAGE_SIZE - 1, port->connection_info,
+			ZFCP_FSF_PRINT_FMT_SINGLEITEM);
+		i += scnprintf(buf + i, PAGE_SIZE - i, "\n");
+	}
+
+	return i;
+}
+static ZFCP_DEV_ATTR(port, fc_security, S_IRUGO,
+		     zfcp_sysfs_port_fc_security_show,
+		     NULL);
+
 static struct attribute *zfcp_port_attrs[] = {
 	&dev_attr_unit_add.attr,
 	&dev_attr_unit_remove.attr,
@@ -387,6 +512,7 @@
 	&dev_attr_port_in_recovery.attr,
 	&dev_attr_port_status.attr,
 	&dev_attr_port_access_denied.attr,
+	&dev_attr_port_fc_security.attr,
 	NULL
 };
 static struct attribute_group zfcp_port_attr_group = {
@@ -577,7 +703,7 @@
 		return -ENOMEM;
 
 	retval = zfcp_fsf_exchange_port_data_sync(adapter->qdio, qtcb_port);
-	if (!retval)
+	if (retval == 0 || retval == -EAGAIN)
 		retval = sprintf(buf, "%u %u %u\n", qtcb_port->cp_util,
 				 qtcb_port->cb_util, qtcb_port->a_util);
 	kfree(qtcb_port);
@@ -603,7 +729,7 @@
 		return -ENOMEM;
 
 	retval = zfcp_fsf_exchange_config_data_sync(adapter->qdio, qtcb_config);
-	if (!retval)
+	if (retval == 0 || retval == -EAGAIN)
 		*stat_inf = qtcb_config->stat_info;
 
 	kfree(qtcb_config);
@@ -664,3 +790,123 @@
 	&dev_attr_queue_full,
 	NULL
 };
+
+static ssize_t zfcp_sysfs_adapter_diag_b2b_credit_show(
+	struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(to_ccwdev(dev));
+	struct zfcp_diag_header *diag_hdr;
+	struct fc_els_flogi *nsp;
+	ssize_t rc = -ENOLINK;
+	unsigned long flags;
+	unsigned int status;
+
+	if (!adapter)
+		return -ENODEV;
+
+	status = atomic_read(&adapter->status);
+	if (0 == (status & ZFCP_STATUS_COMMON_OPEN) ||
+	    0 == (status & ZFCP_STATUS_COMMON_UNBLOCKED) ||
+	    0 != (status & ZFCP_STATUS_COMMON_ERP_FAILED))
+		goto out;
+
+	diag_hdr = &adapter->diagnostics->config_data.header;
+
+	rc = zfcp_diag_update_buffer_limited(
+		adapter, diag_hdr, zfcp_diag_update_config_data_buffer);
+	if (rc != 0)
+		goto out;
+
+	spin_lock_irqsave(&diag_hdr->access_lock, flags);
+	/* nport_serv_param doesn't contain the ELS_Command code */
+	nsp = (struct fc_els_flogi *)((unsigned long)
+					      adapter->diagnostics->config_data
+						      .data.nport_serv_param -
+				      sizeof(u32));
+
+	rc = scnprintf(buf, 5 + 2, "%hu\n",
+		       be16_to_cpu(nsp->fl_csp.sp_bb_cred));
+	spin_unlock_irqrestore(&diag_hdr->access_lock, flags);
+
+out:
+	zfcp_ccw_adapter_put(adapter);
+	return rc;
+}
+static ZFCP_DEV_ATTR(adapter_diag, b2b_credit, 0400,
+		     zfcp_sysfs_adapter_diag_b2b_credit_show, NULL);
+
+#define ZFCP_DEFINE_DIAG_SFP_ATTR(_name, _qtcb_member, _prtsize, _prtfmt)      \
+	static ssize_t zfcp_sysfs_adapter_diag_sfp_##_name##_show(	       \
+		struct device *dev, struct device_attribute *attr, char *buf)  \
+	{								       \
+		struct zfcp_adapter *const adapter =			       \
+			zfcp_ccw_adapter_by_cdev(to_ccwdev(dev));	       \
+		struct zfcp_diag_header *diag_hdr;			       \
+		ssize_t rc = -ENOLINK;					       \
+		unsigned long flags;					       \
+		unsigned int status;					       \
+									       \
+		if (!adapter)						       \
+			return -ENODEV;					       \
+									       \
+		status = atomic_read(&adapter->status);			       \
+		if (0 == (status & ZFCP_STATUS_COMMON_OPEN) ||		       \
+		    0 == (status & ZFCP_STATUS_COMMON_UNBLOCKED) ||	       \
+		    0 != (status & ZFCP_STATUS_COMMON_ERP_FAILED))	       \
+			goto out;					       \
+									       \
+		if (!zfcp_diag_support_sfp(adapter)) {			       \
+			rc = -EOPNOTSUPP;				       \
+			goto out;					       \
+		}							       \
+									       \
+		diag_hdr = &adapter->diagnostics->port_data.header;	       \
+									       \
+		rc = zfcp_diag_update_buffer_limited(			       \
+			adapter, diag_hdr, zfcp_diag_update_port_data_buffer); \
+		if (rc != 0)						       \
+			goto out;					       \
+									       \
+		spin_lock_irqsave(&diag_hdr->access_lock, flags);	       \
+		rc = scnprintf(						       \
+			buf, (_prtsize) + 2, _prtfmt "\n",		       \
+			adapter->diagnostics->port_data.data._qtcb_member);    \
+		spin_unlock_irqrestore(&diag_hdr->access_lock, flags);	       \
+									       \
+	out:								       \
+		zfcp_ccw_adapter_put(adapter);				       \
+		return rc;						       \
+	}								       \
+	static ZFCP_DEV_ATTR(adapter_diag_sfp, _name, 0400,		       \
+			     zfcp_sysfs_adapter_diag_sfp_##_name##_show, NULL)
+
+ZFCP_DEFINE_DIAG_SFP_ATTR(temperature, temperature, 6, "%hd");
+ZFCP_DEFINE_DIAG_SFP_ATTR(vcc, vcc, 5, "%hu");
+ZFCP_DEFINE_DIAG_SFP_ATTR(tx_bias, tx_bias, 5, "%hu");
+ZFCP_DEFINE_DIAG_SFP_ATTR(tx_power, tx_power, 5, "%hu");
+ZFCP_DEFINE_DIAG_SFP_ATTR(rx_power, rx_power, 5, "%hu");
+ZFCP_DEFINE_DIAG_SFP_ATTR(port_tx_type, sfp_flags.port_tx_type, 2, "%hu");
+ZFCP_DEFINE_DIAG_SFP_ATTR(optical_port, sfp_flags.optical_port, 1, "%hu");
+ZFCP_DEFINE_DIAG_SFP_ATTR(sfp_invalid, sfp_flags.sfp_invalid, 1, "%hu");
+ZFCP_DEFINE_DIAG_SFP_ATTR(connector_type, sfp_flags.connector_type, 1, "%hu");
+ZFCP_DEFINE_DIAG_SFP_ATTR(fec_active, sfp_flags.fec_active, 1, "%hu");
+
+static struct attribute *zfcp_sysfs_diag_attrs[] = {
+	&dev_attr_adapter_diag_sfp_temperature.attr,
+	&dev_attr_adapter_diag_sfp_vcc.attr,
+	&dev_attr_adapter_diag_sfp_tx_bias.attr,
+	&dev_attr_adapter_diag_sfp_tx_power.attr,
+	&dev_attr_adapter_diag_sfp_rx_power.attr,
+	&dev_attr_adapter_diag_sfp_port_tx_type.attr,
+	&dev_attr_adapter_diag_sfp_optical_port.attr,
+	&dev_attr_adapter_diag_sfp_sfp_invalid.attr,
+	&dev_attr_adapter_diag_sfp_connector_type.attr,
+	&dev_attr_adapter_diag_sfp_fec_active.attr,
+	&dev_attr_adapter_diag_b2b_credit.attr,
+	NULL,
+};
+
+const struct attribute_group zfcp_sysfs_diag_attr_group = {
+	.name = "diagnostics",
+	.attrs = zfcp_sysfs_diag_attrs,
+};
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/s390/virtio/virtio_ccw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/s390/virtio/virtio_ccw.c
@@ -117,7 +117,7 @@
 };
 
 /* the highest virtio-ccw revision we support */
-#define VIRTIO_CCW_REV_MAX 1
+#define VIRTIO_CCW_REV_MAX 2
 
 struct virtio_ccw_vq_info {
 	struct virtqueue *vq;
@@ -952,7 +952,7 @@
 	u8 old_status = vcdev->dma_area->status;
 	struct ccw1 *ccw;
 
-	if (vcdev->revision < 1)
+	if (vcdev->revision < 2)
 		return vcdev->dma_area->status;
 
 	ccw = ccw_device_dma_zalloc(vcdev->cdev, sizeof(*ccw));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/3w-9xxx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/3w-9xxx.c
@@ -2014,7 +2014,7 @@
 	retval = pci_enable_device(pdev);
 	if (retval) {
 		TW_PRINTK(host, TW_DRIVER, 0x34, "Failed to enable pci device");
-		goto out_disable_device;
+		return -ENODEV;
 	}
 
 	pci_set_master(pdev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/3w-xxxx.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/3w-xxxx.c
@@ -2310,8 +2310,10 @@
 	TW_DISABLE_INTERRUPTS(tw_dev);
 
 	/* Initialize the card */
-	if (tw_reset_sequence(tw_dev))
+	if (tw_reset_sequence(tw_dev)) {
+		retval = -EINVAL;
 		goto out_release_mem_region;
+	}
 
 	/* Set host specific parameters */
 	host->max_id = TW_MAX_UNITS;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/53c700.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/53c700.c
@@ -1581,7 +1581,7 @@
 				printk("scsi%d (%d:%d) PHASE MISMATCH IN SEND MESSAGE %d remain, return %p[%04x], phase %s\n", host->host_no, pun, lun, count, (void *)temp, temp - hostdata->pScript, sbcl_to_string(NCR_700_readb(host, SBCL_REG)));
 #endif
 				resume_offset = hostdata->pScript + Ent_SendMessagePhaseMismatch;
-			} else if(dsp >= to32bit(&slot->pSG[0].ins) &&
+			} else if (slot && dsp >= to32bit(&slot->pSG[0].ins) &&
 				  dsp <= to32bit(&slot->pSG[NCR_700_SG_SEGMENTS].ins)) {
 				int data_transfer = NCR_700_readl(host, DBC_REG) & 0xffffff;
 				int SGcount = (dsp - to32bit(&slot->pSG[0].ins))/sizeof(struct NCR_700_SG_List);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/BusLogic.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/BusLogic.c
@@ -3077,11 +3077,11 @@
 		ccb->opcode = BLOGIC_INITIATOR_CCB_SG;
 		ccb->datalen = count * sizeof(struct blogic_sg_seg);
 		if (blogic_multimaster_type(adapter))
-			ccb->data = (void *)((unsigned int) ccb->dma_handle +
+			ccb->data = (unsigned int) ccb->dma_handle +
 					((unsigned long) &ccb->sglist -
-					(unsigned long) ccb));
+					(unsigned long) ccb);
 		else
-			ccb->data = ccb->sglist;
+			ccb->data = virt_to_32bit_virt(ccb->sglist);
 
 		scsi_for_each_sg(command, sg, count, i) {
 			ccb->sglist[i].segbytes = sg_dma_len(sg);
@@ -3601,7 +3601,7 @@
 			if (buf[0] != '\n' || len > 1)
 				printk("%sscsi%d: %s", blogic_msglevelmap[msglevel], adapter->host_no, buf);
 		} else
-			printk("%s", buf);
+			pr_cont("%s", buf);
 	} else {
 		if (begin) {
 			if (adapter != NULL && adapter->adapter_initd)
@@ -3609,7 +3609,7 @@
 			else
 				printk("%s%s", blogic_msglevelmap[msglevel], buf);
 		} else
-			printk("%s", buf);
+			pr_cont("%s", buf);
 	}
 	begin = (buf[len - 1] == '\n');
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/BusLogic.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/BusLogic.h
@@ -814,7 +814,7 @@
 	unsigned char cdblen;				/* Byte 2 */
 	unsigned char sense_datalen;			/* Byte 3 */
 	u32 datalen;					/* Bytes 4-7 */
-	void *data;					/* Bytes 8-11 */
+	u32 data;					/* Bytes 8-11 */
 	unsigned char:8;				/* Byte 12 */
 	unsigned char:8;				/* Byte 13 */
 	enum blogic_adapter_status adapter_status;	/* Byte 14 */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/FlashPoint.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/FlashPoint.c
@@ -40,7 +40,7 @@
 	u16 si_per_targ_ultra_nego;
 	u16 si_per_targ_no_disc;
 	u16 si_per_targ_wide_nego;
-	u16 si_flags;
+	u16 si_mflags;
 	unsigned char si_card_family;
 	unsigned char si_bustype;
 	unsigned char si_card_model[3];
@@ -1070,22 +1070,22 @@
 		ScamFlg =
 		    (unsigned char)FPT_utilEERead(ioport, SCAM_CONFIG / 2);
 
-	pCardInfo->si_flags = 0x0000;
+	pCardInfo->si_mflags = 0x0000;
 
 	if (i & 0x01)
-		pCardInfo->si_flags |= SCSI_PARITY_ENA;
+		pCardInfo->si_mflags |= SCSI_PARITY_ENA;
 
 	if (!(i & 0x02))
-		pCardInfo->si_flags |= SOFT_RESET;
+		pCardInfo->si_mflags |= SOFT_RESET;
 
 	if (i & 0x10)
-		pCardInfo->si_flags |= EXTENDED_TRANSLATION;
+		pCardInfo->si_mflags |= EXTENDED_TRANSLATION;
 
 	if (ScamFlg & SCAM_ENABLED)
-		pCardInfo->si_flags |= FLAG_SCAM_ENABLED;
+		pCardInfo->si_mflags |= FLAG_SCAM_ENABLED;
 
 	if (ScamFlg & SCAM_LEVEL2)
-		pCardInfo->si_flags |= FLAG_SCAM_LEVEL2;
+		pCardInfo->si_mflags |= FLAG_SCAM_LEVEL2;
 
 	j = (RD_HARPOON(ioport + hp_bm_ctrl) & ~SCSI_TERM_ENA_L);
 	if (i & 0x04) {
@@ -1101,7 +1101,7 @@
 
 	if (!(RD_HARPOON(ioport + hp_page_ctrl) & NARROW_SCSI_CARD))
 
-		pCardInfo->si_flags |= SUPPORT_16TAR_32LUN;
+		pCardInfo->si_mflags |= SUPPORT_16TAR_32LUN;
 
 	pCardInfo->si_card_family = HARPOON_FAMILY;
 	pCardInfo->si_bustype = BUSTYPE_PCI;
@@ -1137,15 +1137,15 @@
 
 	if (pCardInfo->si_card_model[1] == '3') {
 		if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
-			pCardInfo->si_flags |= LOW_BYTE_TERM;
+			pCardInfo->si_mflags |= LOW_BYTE_TERM;
 	} else if (pCardInfo->si_card_model[2] == '0') {
 		temp = RD_HARPOON(ioport + hp_xfer_pad);
 		WR_HARPOON(ioport + hp_xfer_pad, (temp & ~BIT(4)));
 		if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
-			pCardInfo->si_flags |= LOW_BYTE_TERM;
+			pCardInfo->si_mflags |= LOW_BYTE_TERM;
 		WR_HARPOON(ioport + hp_xfer_pad, (temp | BIT(4)));
 		if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
-			pCardInfo->si_flags |= HIGH_BYTE_TERM;
+			pCardInfo->si_mflags |= HIGH_BYTE_TERM;
 		WR_HARPOON(ioport + hp_xfer_pad, temp);
 	} else {
 		temp = RD_HARPOON(ioport + hp_ee_ctrl);
@@ -1163,9 +1163,9 @@
 		WR_HARPOON(ioport + hp_ee_ctrl, temp);
 		WR_HARPOON(ioport + hp_xfer_pad, temp2);
 		if (!(temp3 & BIT(7)))
-			pCardInfo->si_flags |= LOW_BYTE_TERM;
+			pCardInfo->si_mflags |= LOW_BYTE_TERM;
 		if (!(temp3 & BIT(6)))
-			pCardInfo->si_flags |= HIGH_BYTE_TERM;
+			pCardInfo->si_mflags |= HIGH_BYTE_TERM;
 	}
 
 	ARAM_ACCESS(ioport);
@@ -1272,7 +1272,7 @@
 	WR_HARPOON(ioport + hp_arb_id, pCardInfo->si_id);
 	CurrCard->ourId = pCardInfo->si_id;
 
-	i = (unsigned char)pCardInfo->si_flags;
+	i = (unsigned char)pCardInfo->si_mflags;
 	if (i & SCSI_PARITY_ENA)
 		WR_HARPOON(ioport + hp_portctrl_1, (HOST_MODE8 | CHK_SCSI_P));
 
@@ -1286,14 +1286,14 @@
 		j |= SCSI_TERM_ENA_H;
 	WR_HARPOON(ioport + hp_ee_ctrl, j);
 
-	if (!(pCardInfo->si_flags & SOFT_RESET)) {
+	if (!(pCardInfo->si_mflags & SOFT_RESET)) {
 
 		FPT_sresb(ioport, thisCard);
 
 		FPT_scini(thisCard, pCardInfo->si_id, 0);
 	}
 
-	if (pCardInfo->si_flags & POST_ALL_UNDERRRUNS)
+	if (pCardInfo->si_mflags & POST_ALL_UNDERRRUNS)
 		CurrCard->globalFlags |= F_NO_FILTER;
 
 	if (pCurrNvRam) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/Kconfig
@@ -114,15 +114,6 @@
 	  <file:Documentation/scsi/scsi.txt>.
 	  The module will be called sr_mod.
 
-config BLK_DEV_SR_VENDOR
-	bool "Enable vendor-specific extensions (for SCSI CDROM)"
-	depends on BLK_DEV_SR
-	help
-	  This enables the usage of vendor specific SCSI commands. This is
-	  required to support multisession CDs with old NEC/TOSHIBA cdrom
-	  drives (and HP Writers). If you have such a drive and get the first
-	  session only, try saying Y here; everybody else says N.
-
 config CHR_DEV_SG
 	tristate "SCSI generic support"
 	depends on SCSI
@@ -452,7 +443,7 @@
 
 config SCSI_DPT_I2O
 	tristate "Adaptec I2O RAID support "
-	depends on SCSI && PCI && VIRT_TO_BUS
+	depends on SCSI && PCI
 	help
 	  This driver supports all of Adaptec's I2O based RAID controllers as 
 	  well as the DPT SmartRaid V cards.  This is an Adaptec maintained
@@ -1295,7 +1286,7 @@
 
 config JAZZ_ESP
 	bool "MIPS JAZZ FAS216 SCSI support"
-	depends on MACH_JAZZ && SCSI
+	depends on MACH_JAZZ && SCSI=y
 	select SCSI_SPI_ATTRS
 	help
 	  This is the driver for the onboard SCSI host adapter of MIPS Magnum
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/NCR5380.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/NCR5380.c
@@ -129,6 +129,9 @@
 #define NCR5380_release_dma_irq(x)
 #endif
 
+static unsigned int disconnect_mask = ~0;
+module_param(disconnect_mask, int, 0444);
+
 static int do_abort(struct Scsi_Host *);
 static void do_reset(struct Scsi_Host *);
 static void bus_reset_cleanup(struct Scsi_Host *);
@@ -954,7 +957,8 @@
 	int err;
 	bool ret = true;
 	bool can_disconnect = instance->irq != NO_IRQ &&
-			      cmd->cmnd[0] != REQUEST_SENSE;
+			      cmd->cmnd[0] != REQUEST_SENSE &&
+			      (disconnect_mask & BIT(scmd_id(cmd)));
 
 	NCR5380_dprint(NDEBUG_ARBITRATION, instance);
 	dsprintk(NDEBUG_ARBITRATION, instance, "starting arbitration, id = %d\n",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/aacraid/aachba.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/aacraid/aachba.c
@@ -2467,13 +2467,13 @@
 		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 |
 			SAM_STAT_CHECK_CONDITION;
 		set_sense(&dev->fsa_dev[cid].sense_data,
-			  HARDWARE_ERROR, SENCODE_INTERNAL_TARGET_FAILURE,
+			  ILLEGAL_REQUEST, SENCODE_LBA_OUT_OF_RANGE,
 			  ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0);
 		memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
 		       min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data),
 			     SCSI_SENSE_BUFFERSIZE));
 		scsicmd->scsi_done(scsicmd);
-		return 1;
+		return 0;
 	}
 
 	dprintk((KERN_DEBUG "aac_read[cpu %d]: lba = %llu, t = %ld.\n",
@@ -2559,13 +2559,13 @@
 		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 |
 			SAM_STAT_CHECK_CONDITION;
 		set_sense(&dev->fsa_dev[cid].sense_data,
-			  HARDWARE_ERROR, SENCODE_INTERNAL_TARGET_FAILURE,
+			  ILLEGAL_REQUEST, SENCODE_LBA_OUT_OF_RANGE,
 			  ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0);
 		memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
 		       min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data),
 			     SCSI_SENSE_BUFFERSIZE));
 		scsicmd->scsi_done(scsicmd);
-		return 1;
+		return 0;
 	}
 
 	dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %llu, t = %ld.\n",
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/aacraid/aacraid.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/aacraid/aacraid.h
@@ -2024,8 +2024,8 @@
 };
 
 struct aac_srb_unit {
-	struct aac_srb		srb;
 	struct aac_srb_reply	srb_reply;
+	struct aac_srb		srb;
 };
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/aacraid/comminit.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/aacraid/comminit.c
@@ -638,6 +638,7 @@
 
 	if (aac_comm_init(dev)<0){
 		kfree(dev->queues);
+		dev->queues = NULL;
 		return NULL;
 	}
 	/*
@@ -645,6 +646,7 @@
 	 */
 	if (aac_fib_setup(dev) < 0) {
 		kfree(dev->queues);
+		dev->queues = NULL;
 		return NULL;
 	}
 		
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/aacraid/commsup.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/aacraid/commsup.c
@@ -728,7 +728,7 @@
 		hbacmd->request_id =
 			cpu_to_le32((((u32)(fibptr - dev->fibs)) << 2) + 1);
 		fibptr->flags |= FIB_CONTEXT_FLAG_SCSI_CMD;
-	} else if (command != HBA_IU_TYPE_SCSI_TM_REQ)
+	} else
 		return -EINVAL;
 
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/aacraid/linit.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/aacraid/linit.c
@@ -723,7 +723,11 @@
 		status = aac_hba_send(HBA_IU_TYPE_SCSI_TM_REQ, fib,
 				  (fib_callback) aac_hba_callback,
 				  (void *) cmd);
-
+		if (status != -EINPROGRESS) {
+			aac_fib_complete(fib);
+			aac_fib_free(fib);
+			return ret;
+		}
 		/* Wait up to 15 secs for completion */
 		for (count = 0; count < 15; ++count) {
 			if (cmd->SCp.sent_command) {
@@ -902,11 +906,11 @@
 
 	info = &aac->hba_map[bus][cid];
 
-	if (info->devtype != AAC_DEVTYPE_NATIVE_RAW &&
-	    info->reset_state > 0)
+	if (!(info->devtype == AAC_DEVTYPE_NATIVE_RAW &&
+	 !(info->reset_state > 0)))
 		return FAILED;
 
-	pr_err("%s: Host adapter reset request. SCSI hang ?\n",
+	pr_err("%s: Host device reset request. SCSI hang ?\n",
 	       AAC_DRIVERNAME);
 
 	fib = aac_fib_alloc(aac);
@@ -921,7 +925,12 @@
 	status = aac_hba_send(command, fib,
 			      (fib_callback) aac_tmf_callback,
 			      (void *) info);
-
+	if (status != -EINPROGRESS) {
+		info->reset_state = 0;
+		aac_fib_complete(fib);
+		aac_fib_free(fib);
+		return ret;
+	}
 	/* Wait up to 15 seconds for completion */
 	for (count = 0; count < 15; ++count) {
 		if (info->reset_state == 0) {
@@ -960,11 +969,11 @@
 
 	info = &aac->hba_map[bus][cid];
 
-	if (info->devtype != AAC_DEVTYPE_NATIVE_RAW &&
-	    info->reset_state > 0)
+	if (!(info->devtype == AAC_DEVTYPE_NATIVE_RAW &&
+	 !(info->reset_state > 0)))
 		return FAILED;
 
-	pr_err("%s: Host adapter reset request. SCSI hang ?\n",
+	pr_err("%s: Host target reset request. SCSI hang ?\n",
 	       AAC_DRIVERNAME);
 
 	fib = aac_fib_alloc(aac);
@@ -981,6 +990,13 @@
 			      (fib_callback) aac_tmf_callback,
 			      (void *) info);
 
+	if (status != -EINPROGRESS) {
+		info->reset_state = 0;
+		aac_fib_complete(fib);
+		aac_fib_free(fib);
+		return ret;
+	}
+
 	/* Wait up to 15 seconds for completion */
 	for (count = 0; count < 15; ++count) {
 		if (info->reset_state <= 0) {
@@ -1033,7 +1049,7 @@
 		}
 	}
 
-	pr_err("%s: Host adapter reset request. SCSI hang ?\n", AAC_DRIVERNAME);
+	pr_err("%s: Host bus reset request. SCSI hang ?\n", AAC_DRIVERNAME);
 
 	/*
 	 * Check the health of the controller
@@ -1591,7 +1607,7 @@
 	struct Scsi_Host *shost;
 	struct aac_dev *aac;
 	struct list_head *insert = &aac_devices;
-	int error = -ENODEV;
+	int error;
 	int unique_id = 0;
 	u64 dmamask;
 	int mask_bits = 0;
@@ -1616,7 +1632,6 @@
 	error = pci_enable_device(pdev);
 	if (error)
 		goto out;
-	error = -ENODEV;
 
 	if (!(aac_drivers[index].quirks & AAC_QUIRK_SRC)) {
 		error = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
@@ -1648,8 +1663,10 @@
 	pci_set_master(pdev);
 
 	shost = scsi_host_alloc(&aac_driver_template, sizeof(struct aac_dev));
-	if (!shost)
+	if (!shost) {
+		error = -ENOMEM;
 		goto out_disable_pdev;
+	}
 
 	shost->irq = pdev->irq;
 	shost->unique_id = unique_id;
@@ -1674,8 +1691,11 @@
 	aac->fibs = kcalloc(shost->can_queue + AAC_NUM_MGT_FIB,
 			    sizeof(struct fib),
 			    GFP_KERNEL);
-	if (!aac->fibs)
+	if (!aac->fibs) {
+		error = -ENOMEM;
 		goto out_free_host;
+	}
+
 	spin_lock_init(&aac->fib_lock);
 
 	mutex_init(&aac->ioctl_mutex);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/advansys.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/advansys.c
@@ -3366,8 +3366,8 @@
 		   shost->host_no);
 
 	seq_printf(m,
-		   " iop_base 0x%lx, cable_detect: %X, err_code %u\n",
-		   (unsigned long)v->iop_base,
+		   " iop_base 0x%p, cable_detect: %X, err_code %u\n",
+		   v->iop_base,
 		   AdvReadWordRegister(iop_base,IOPW_SCSI_CFG1) & CABLE_DETECT,
 		   v->err_code);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/aha152x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/aha152x.c
@@ -3368,13 +3368,11 @@
 	setup[setup_count].synchronous = ints[0] >= 6 ? ints[6] : 1;
 	setup[setup_count].delay       = ints[0] >= 7 ? ints[7] : DELAY_DEFAULT;
 	setup[setup_count].ext_trans   = ints[0] >= 8 ? ints[8] : 0;
-	if (ints[0] > 8) {                                                /*}*/
+	if (ints[0] > 8)
 		printk(KERN_NOTICE "aha152x: usage: aha152x=<IOBASE>[,<IRQ>[,<SCSI ID>"
 		       "[,<RECONNECT>[,<PARITY>[,<SYNCHRONOUS>[,<DELAY>[,<EXT_TRANS>]]]]]]]\n");
-	} else {
+	else
 		setup_count++;
-		return 0;
-	}
 
 	return 1;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/aic7xxx/aic7xxx_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/aic7xxx/aic7xxx_core.c
@@ -493,7 +493,7 @@
 	return ((ahc_inb(ahc, port))
 	      | (ahc_inb(ahc, port+1) << 8)
 	      | (ahc_inb(ahc, port+2) << 16)
-	      | (ahc_inb(ahc, port+3) << 24)
+	      | (((uint64_t)ahc_inb(ahc, port+3)) << 24)
 	      | (((uint64_t)ahc_inb(ahc, port+4)) << 32)
 	      | (((uint64_t)ahc_inb(ahc, port+5)) << 40)
 	      | (((uint64_t)ahc_inb(ahc, port+6)) << 48)
@@ -2314,7 +2314,7 @@
 			 * At some speeds, we only support
 			 * ST transfers.
 			 */
-		 	if ((syncrate->sxfr_u2 & ST_SXFR) != 0)
+			if ((syncrate->sxfr_u2 & ST_SXFR) != 0)
 				*ppr_options &= ~MSG_EXT_PPR_DT_REQ;
 			break;
 		}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/aic94xx/aic94xx_init.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/aic94xx/aic94xx_init.c
@@ -52,6 +52,7 @@
 	.max_sectors		= SCSI_DEFAULT_MAX_SECTORS,
 	.eh_device_reset_handler	= sas_eh_device_reset_handler,
 	.eh_target_reset_handler	= sas_eh_target_reset_handler,
+	.slave_alloc		= sas_slave_alloc,
 	.target_destroy		= sas_target_destroy,
 	.ioctl			= sas_ioctl,
 	.track_queue_depth	= 1,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/aic94xx/aic94xx_task.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/aic94xx/aic94xx_task.c
@@ -50,6 +50,9 @@
 		dma_addr_t dma = dma_map_single(&asd_ha->pcidev->dev, p,
 						task->total_xfer_len,
 						task->data_dir);
+		if (dma_mapping_error(&asd_ha->pcidev->dev, dma))
+			return -ENOMEM;
+
 		sg_arr[0].bus_addr = cpu_to_le64((u64)dma);
 		sg_arr[0].size = cpu_to_le32(task->total_xfer_len);
 		sg_arr[0].flags |= ASD_SG_EL_LIST_EOL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/arm/acornscsi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/arm/acornscsi.c
@@ -2911,8 +2911,10 @@
 
 	ashost->base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0);
 	ashost->fast = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
-	if (!ashost->base || !ashost->fast)
+	if (!ashost->base || !ashost->fast) {
+		ret = -ENOMEM;
 		goto out_put;
+	}
 
 	host->irq = ec->irq;
 	ashost->host = host;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/arm/cumana_2.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/arm/cumana_2.c
@@ -450,7 +450,7 @@
 
 	if (info->info.scsi.dma != NO_DMA)
 		free_dma(info->info.scsi.dma);
-	free_irq(ec->irq, host);
+	free_irq(ec->irq, info);
 
  out_release:
 	fas216_release(host);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/arm/eesox.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/arm/eesox.c
@@ -571,7 +571,7 @@
 
 	if (info->info.scsi.dma != NO_DMA)
 		free_dma(info->info.scsi.dma);
-	free_irq(ec->irq, host);
+	free_irq(ec->irq, info);
 
  out_remove:
 	fas216_remove(host);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/arm/powertec.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/arm/powertec.c
@@ -378,7 +378,7 @@
 
 	if (info->info.scsi.dma != NO_DMA)
 		free_dma(info->info.scsi.dma);
-	free_irq(ec->irq, host);
+	free_irq(ec->irq, info);
 
  out_release:
 	fas216_release(host);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/atari_scsi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/atari_scsi.c
@@ -742,7 +742,7 @@
 		atari_scsi_template.sg_tablesize = SG_ALL;
 	} else {
 		atari_scsi_template.can_queue    = 1;
-		atari_scsi_template.sg_tablesize = SG_NONE;
+		atari_scsi_template.sg_tablesize = 1;
 	}
 
 	if (setup_can_queue > 0)
@@ -751,8 +751,8 @@
 	if (setup_cmd_per_lun > 0)
 		atari_scsi_template.cmd_per_lun = setup_cmd_per_lun;
 
-	/* Leave sg_tablesize at 0 on a Falcon! */
-	if (ATARIHW_PRESENT(TT_SCSI) && setup_sg_tablesize >= 0)
+	/* Don't increase sg_tablesize on Falcon! */
+	if (ATARIHW_PRESENT(TT_SCSI) && setup_sg_tablesize > 0)
 		atari_scsi_template.sg_tablesize = setup_sg_tablesize;
 
 	if (setup_hostid >= 0) {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/be2iscsi/be_iscsi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/be2iscsi/be_iscsi.c
@@ -441,6 +441,10 @@
 	}
 
 	nla_for_each_attr(attrib, data, dt_len, rm_len) {
+		/* ignore nla_type as it is never used */
+		if (nla_len(attrib) < sizeof(*iface_param))
+			return -EINVAL;
+
 		iface_param = nla_data(attrib);
 
 		if (iface_param->param_type != ISCSI_NET_PARAM)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/be2iscsi/be_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/be2iscsi/be_main.c
@@ -416,7 +416,7 @@
 			"beiscsi_hba_alloc - iscsi_host_alloc failed\n");
 		return NULL;
 	}
-	shost->max_id = BE2_MAX_SESSIONS;
+	shost->max_id = BE2_MAX_SESSIONS - 1;
 	shost->max_channel = 0;
 	shost->max_cmd_len = BEISCSI_MAX_CMD_LEN;
 	shost->max_lun = BEISCSI_NUM_MAX_LUN;
@@ -2694,6 +2694,7 @@
 		kfree(pwrb_context->pwrb_handle_base);
 		kfree(pwrb_context->pwrb_handle_basestd);
 	}
+	kfree(phwi_ctxt->be_wrbq);
 	return -ENOMEM;
 }
 
@@ -5318,7 +5319,7 @@
 	/* Re-enable UER. If different TPE occurs then it is recoverable. */
 	beiscsi_set_uer_feature(phba);
 
-	phba->shost->max_id = phba->params.cxns_per_ctrl;
+	phba->shost->max_id = phba->params.cxns_per_ctrl - 1;
 	phba->shost->can_queue = phba->params.ios_per_ctrl;
 	ret = beiscsi_init_port(phba);
 	if (ret < 0) {
@@ -5745,6 +5746,7 @@
 	pci_disable_msix(phba->pcidev);
 	pci_dev_put(phba->pcidev);
 	iscsi_host_free(phba->shost);
+	pci_disable_pcie_error_reporting(pcidev);
 	pci_set_drvdata(pcidev, NULL);
 disable_pci:
 	pci_release_regions(pcidev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/bfa/bfa.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/bfa/bfa.h
@@ -20,7 +20,6 @@
 struct bfa_s;
 
 typedef void (*bfa_isr_func_t) (struct bfa_s *bfa, struct bfi_msg_s *m);
-typedef void (*bfa_cb_cbfn_status_t) (void *cbarg, bfa_status_t status);
 
 /*
  * Interrupt message handlers
@@ -435,6 +434,14 @@
 	(__qe)->hcb_qe.cbarg = (__cbarg);			\
 	(__qe)->hcb_qe.pre_rmv = BFA_TRUE;			\
 	(__qe)->data = (__data);				\
+} while (0)
+
+#define bfa_pending_q_init_status(__qe, __cbfn, __cbarg, __data) do {	\
+	bfa_q_qe_init(&((__qe)->hcb_qe.qe));			\
+	(__qe)->hcb_qe.cbfn_status = (__cbfn);			\
+	(__qe)->hcb_qe.cbarg = (__cbarg);			\
+	(__qe)->hcb_qe.pre_rmv = BFA_TRUE;			\
+	(__qe)->data = (__data);				\
 } while (0)
 
 #endif /* __BFA_H__ */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/bfa/bfa_core.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/bfa/bfa_core.c
@@ -1907,15 +1907,13 @@
 	struct list_head		*qe;
 	struct list_head		*qen;
 	struct bfa_cb_qe_s	*hcb_qe;
-	bfa_cb_cbfn_status_t	cbfn;
 
 	list_for_each_safe(qe, qen, comp_q) {
 		hcb_qe = (struct bfa_cb_qe_s *) qe;
 		if (hcb_qe->pre_rmv) {
 			/* qe is invalid after return, dequeue before cbfn() */
 			list_del(qe);
-			cbfn = (bfa_cb_cbfn_status_t)(hcb_qe->cbfn);
-			cbfn(hcb_qe->cbarg, hcb_qe->fw_status);
+			hcb_qe->cbfn_status(hcb_qe->cbarg, hcb_qe->fw_status);
 		} else
 			hcb_qe->cbfn(hcb_qe->cbarg, BFA_TRUE);
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/bfa/bfa_ioc.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/bfa/bfa_ioc.h
@@ -361,14 +361,18 @@
 	void	*cbarg;
 };
 
-typedef void	(*bfa_cb_cbfn_t) (void *cbarg, bfa_boolean_t complete);
+typedef void (*bfa_cb_cbfn_t) (void *cbarg, bfa_boolean_t complete);
+typedef void (*bfa_cb_cbfn_status_t) (void *cbarg, bfa_status_t status);
 
 /*
  * Generic BFA callback element.
  */
 struct bfa_cb_qe_s {
 	struct list_head	qe;
-	bfa_cb_cbfn_t	cbfn;
+	union {
+		bfa_cb_cbfn_status_t	cbfn_status;
+		bfa_cb_cbfn_t		cbfn;
+	};
 	bfa_boolean_t	once;
 	bfa_boolean_t	pre_rmv;	/* set for stack based qe(s) */
 	bfa_status_t	fw_status;	/* to access fw status in comp proc */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/bfa/bfad.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/bfa/bfad.c
@@ -749,6 +749,7 @@
 
 	if (bfad->pci_bar0_kva == NULL) {
 		printk(KERN_ERR "Fail to map bar0\n");
+		rc = -ENODEV;
 		goto out_release_region;
 	}
 
@@ -1705,9 +1706,8 @@
 
 	error = bfad_im_module_init();
 	if (error) {
-		error = -ENOMEM;
 		printk(KERN_WARNING "bfad_im_module_init failure\n");
-		goto ext;
+		return -ENOMEM;
 	}
 
 	if (strcmp(FCPI_NAME, " fcpim") == 0)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/bfa/bfad_attr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/bfa/bfad_attr.c
@@ -275,8 +275,10 @@
 	rc = bfa_port_get_stats(BFA_FCPORT(&bfad->bfa),
 				fcstats, bfad_hcb_comp, &fcomp);
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
-	if (rc != BFA_STATUS_OK)
+	if (rc != BFA_STATUS_OK) {
+		kfree(fcstats);
 		return NULL;
+	}
 
 	wait_for_completion(&fcomp.comp);
 
@@ -709,7 +711,7 @@
 	char serial_num[BFA_ADAPTER_SERIAL_NUM_LEN];
 
 	bfa_get_adapter_serial_num(&bfad->bfa, serial_num);
-	return snprintf(buf, PAGE_SIZE, "%s\n", serial_num);
+	return sysfs_emit(buf, "%s\n", serial_num);
 }
 
 static ssize_t
@@ -723,7 +725,7 @@
 	char model[BFA_ADAPTER_MODEL_NAME_LEN];
 
 	bfa_get_adapter_model(&bfad->bfa, model);
-	return snprintf(buf, PAGE_SIZE, "%s\n", model);
+	return sysfs_emit(buf, "%s\n", model);
 }
 
 static ssize_t
@@ -803,7 +805,7 @@
 		snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN,
 			"Invalid Model");
 
-	return snprintf(buf, PAGE_SIZE, "%s\n", model_descr);
+	return sysfs_emit(buf, "%s\n", model_descr);
 }
 
 static ssize_t
@@ -817,7 +819,7 @@
 	u64        nwwn;
 
 	nwwn = bfa_fcs_lport_get_nwwn(port->fcs_port);
-	return snprintf(buf, PAGE_SIZE, "0x%llx\n", cpu_to_be64(nwwn));
+	return sysfs_emit(buf, "0x%llx\n", cpu_to_be64(nwwn));
 }
 
 static ssize_t
@@ -834,7 +836,7 @@
 	bfa_fcs_lport_get_attr(&bfad->bfa_fcs.fabric.bport, &port_attr);
 	strlcpy(symname, port_attr.port_cfg.sym_name.symname,
 			BFA_SYMNAME_MAXLEN);
-	return snprintf(buf, PAGE_SIZE, "%s\n", symname);
+	return sysfs_emit(buf, "%s\n", symname);
 }
 
 static ssize_t
@@ -848,14 +850,14 @@
 	char hw_ver[BFA_VERSION_LEN];
 
 	bfa_get_pci_chip_rev(&bfad->bfa, hw_ver);
-	return snprintf(buf, PAGE_SIZE, "%s\n", hw_ver);
+	return sysfs_emit(buf, "%s\n", hw_ver);
 }
 
 static ssize_t
 bfad_im_drv_version_show(struct device *dev, struct device_attribute *attr,
 				char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "%s\n", BFAD_DRIVER_VERSION);
+	return sysfs_emit(buf, "%s\n", BFAD_DRIVER_VERSION);
 }
 
 static ssize_t
@@ -869,7 +871,7 @@
 	char optrom_ver[BFA_VERSION_LEN];
 
 	bfa_get_adapter_optrom_ver(&bfad->bfa, optrom_ver);
-	return snprintf(buf, PAGE_SIZE, "%s\n", optrom_ver);
+	return sysfs_emit(buf, "%s\n", optrom_ver);
 }
 
 static ssize_t
@@ -883,7 +885,7 @@
 	char fw_ver[BFA_VERSION_LEN];
 
 	bfa_get_adapter_fw_ver(&bfad->bfa, fw_ver);
-	return snprintf(buf, PAGE_SIZE, "%s\n", fw_ver);
+	return sysfs_emit(buf, "%s\n", fw_ver);
 }
 
 static ssize_t
@@ -895,7 +897,7 @@
 			(struct bfad_im_port_s *) shost->hostdata[0];
 	struct bfad_s *bfad = im_port->bfad;
 
-	return snprintf(buf, PAGE_SIZE, "%d\n",
+	return sysfs_emit(buf, "%d\n",
 			bfa_get_nports(&bfad->bfa));
 }
 
@@ -903,7 +905,7 @@
 bfad_im_drv_name_show(struct device *dev, struct device_attribute *attr,
 				char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "%s\n", BFAD_DRIVER_NAME);
+	return sysfs_emit(buf, "%s\n", BFAD_DRIVER_NAME);
 }
 
 static ssize_t
@@ -922,14 +924,14 @@
 	rports = kcalloc(nrports, sizeof(struct bfa_rport_qualifier_s),
 			 GFP_ATOMIC);
 	if (rports == NULL)
-		return snprintf(buf, PAGE_SIZE, "Failed\n");
+		return sysfs_emit(buf, "Failed\n");
 
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 	bfa_fcs_lport_get_rport_quals(port->fcs_port, rports, &nrports);
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
 	kfree(rports);
 
-	return snprintf(buf, PAGE_SIZE, "%d\n", nrports);
+	return sysfs_emit(buf, "%d\n", nrports);
 }
 
 static          DEVICE_ATTR(serial_number, S_IRUGO,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/bfa/bfad_bsg.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/bfa/bfad_bsg.c
@@ -2135,8 +2135,7 @@
 	struct bfa_cb_pending_q_s cb_qe;
 
 	init_completion(&fcomp.comp);
-	bfa_pending_q_init(&cb_qe, (bfa_cb_cbfn_t)bfad_hcb_comp,
-			   &fcomp, &iocmd->stats);
+	bfa_pending_q_init_status(&cb_qe, bfad_hcb_comp, &fcomp, &iocmd->stats);
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 	iocmd->status = bfa_fcport_get_stats(&bfad->bfa, &cb_qe);
 	spin_unlock_irqrestore(&bfad->bfad_lock, flags);
@@ -2159,7 +2158,7 @@
 	struct bfa_cb_pending_q_s cb_qe;
 
 	init_completion(&fcomp.comp);
-	bfa_pending_q_init(&cb_qe, (bfa_cb_cbfn_t)bfad_hcb_comp, &fcomp, NULL);
+	bfa_pending_q_init_status(&cb_qe, bfad_hcb_comp, &fcomp, NULL);
 
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 	iocmd->status = bfa_fcport_clear_stats(&bfad->bfa, &cb_qe);
@@ -2443,8 +2442,7 @@
 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa);
 
 	init_completion(&fcomp.comp);
-	bfa_pending_q_init(&cb_qe, (bfa_cb_cbfn_t)bfad_hcb_comp,
-			   &fcomp, &iocmd->stats);
+	bfa_pending_q_init_status(&cb_qe, bfad_hcb_comp, &fcomp, &iocmd->stats);
 
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 	WARN_ON(!bfa_ioc_get_fcmode(&bfad->bfa.ioc));
@@ -2474,8 +2472,7 @@
 	struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa);
 
 	init_completion(&fcomp.comp);
-	bfa_pending_q_init(&cb_qe, (bfa_cb_cbfn_t)bfad_hcb_comp,
-			   &fcomp, NULL);
+	bfa_pending_q_init_status(&cb_qe, bfad_hcb_comp, &fcomp, NULL);
 
 	spin_lock_irqsave(&bfad->bfad_lock, flags);
 	WARN_ON(!bfa_ioc_get_fcmode(&bfad->bfa.ioc));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/bfa/bfad_debugfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/bfa/bfad_debugfs.c
@@ -250,7 +250,7 @@
 	unsigned long flags;
 	void *kern_buf;
 
-	kern_buf = memdup_user(buf, nbytes);
+	kern_buf = memdup_user_nul(buf, nbytes);
 	if (IS_ERR(kern_buf))
 		return PTR_ERR(kern_buf);
 
@@ -317,7 +317,7 @@
 	unsigned long flags;
 	void *kern_buf;
 
-	kern_buf = memdup_user(buf, nbytes);
+	kern_buf = memdup_user_nul(buf, nbytes);
 	if (IS_ERR(kern_buf))
 		return PTR_ERR(kern_buf);
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/bnx2fc/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/bnx2fc/Kconfig
@@ -5,6 +5,7 @@
 	depends on (IPV6 || IPV6=n)
 	depends on LIBFC
 	depends on LIBFCOE
+	depends on MMU
 	select NETDEVICES
 	select ETHERNET
 	select NET_VENDOR_BROADCOM
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
@@ -80,7 +80,7 @@
 static void bnx2fc_unbind_pcidev(struct bnx2fc_hba *hba);
 static struct fc_lport *bnx2fc_if_create(struct bnx2fc_interface *interface,
 				  struct device *parent, int npiv);
-static void bnx2fc_destroy_work(struct work_struct *work);
+static void bnx2fc_port_destroy(struct fcoe_port *port);
 
 static struct bnx2fc_hba *bnx2fc_hba_lookup(struct net_device *phys_dev);
 static struct bnx2fc_interface *bnx2fc_interface_lookup(struct net_device
@@ -430,7 +430,6 @@
 	struct fcoe_ctlr *ctlr;
 	struct fcoe_rcv_info *fr;
 	struct fcoe_percpu_s *bg;
-	struct sk_buff *tmp_skb;
 
 	interface = container_of(ptype, struct bnx2fc_interface,
 				 fcoe_packet_type);
@@ -442,11 +441,9 @@
 		goto err;
 	}
 
-	tmp_skb = skb_share_check(skb, GFP_ATOMIC);
-	if (!tmp_skb)
-		goto err;
-
-	skb = tmp_skb;
+	skb = skb_share_check(skb, GFP_ATOMIC);
+	if (!skb)
+		return -1;
 
 	if (unlikely(eth_hdr(skb)->h_proto != htons(ETH_P_FCOE))) {
 		printk(KERN_ERR PFX "bnx2fc_rcv: Wrong FC type frame\n");
@@ -506,7 +503,8 @@
 
 static void bnx2fc_recv_frame(struct sk_buff *skb)
 {
-	u32 fr_len;
+	u64 crc_err;
+	u32 fr_len, fr_crc;
 	struct fc_lport *lport;
 	struct fcoe_rcv_info *fr;
 	struct fc_stats *stats;
@@ -540,6 +538,11 @@
 	skb_pull(skb, sizeof(struct fcoe_hdr));
 	fr_len = skb->len - sizeof(struct fcoe_crc_eof);
 
+	stats = per_cpu_ptr(lport->stats, get_cpu());
+	stats->RxFrames++;
+	stats->RxWords += fr_len / FCOE_WORD_TO_BYTE;
+	put_cpu();
+
 	fp = (struct fc_frame *)skb;
 	fc_frame_init(fp);
 	fr_dev(fp) = lport;
@@ -622,16 +625,15 @@
 		return;
 	}
 
-	stats = per_cpu_ptr(lport->stats, smp_processor_id());
-	stats->RxFrames++;
-	stats->RxWords += fr_len / FCOE_WORD_TO_BYTE;
+	fr_crc = le32_to_cpu(fr_crc(fp));
 
-	if (le32_to_cpu(fr_crc(fp)) !=
-			~crc32(~0, skb->data, fr_len)) {
-		if (stats->InvalidCRCCount < 5)
+	if (unlikely(fr_crc != ~crc32(~0, skb->data, fr_len))) {
+		stats = per_cpu_ptr(lport->stats, get_cpu());
+		crc_err = (stats->InvalidCRCCount++);
+		put_cpu();
+		if (crc_err < 5)
 			printk(KERN_WARNING PFX "dropping frame with "
 			       "CRC error\n");
-		stats->InvalidCRCCount++;
 		kfree_skb(skb);
 		return;
 	}
@@ -902,9 +904,6 @@
 				__bnx2fc_destroy(interface);
 		}
 		mutex_unlock(&bnx2fc_dev_lock);
-
-		/* Ensure ALL destroy work has been completed before return */
-		flush_workqueue(bnx2fc_wq);
 		return;
 
 	default:
@@ -1211,8 +1210,8 @@
 	mutex_unlock(&n_port->lp_mutex);
 	bnx2fc_free_vport(interface->hba, port->lport);
 	bnx2fc_port_shutdown(port->lport);
+	bnx2fc_port_destroy(port);
 	bnx2fc_interface_put(interface);
-	queue_work(bnx2fc_wq, &port->destroy_work);
 	return 0;
 }
 
@@ -1521,7 +1520,6 @@
 	port->lport = lport;
 	port->priv = interface;
 	port->get_netdev = bnx2fc_netdev;
-	INIT_WORK(&port->destroy_work, bnx2fc_destroy_work);
 
 	/* Configure fcoe_port */
 	rc = bnx2fc_lport_config(lport);
@@ -1649,8 +1647,8 @@
 	bnx2fc_interface_cleanup(interface);
 	bnx2fc_stop(interface);
 	list_del(&interface->list);
+	bnx2fc_port_destroy(port);
 	bnx2fc_interface_put(interface);
-	queue_work(bnx2fc_wq, &port->destroy_work);
 }
 
 /**
@@ -1691,15 +1689,12 @@
 	return rc;
 }
 
-static void bnx2fc_destroy_work(struct work_struct *work)
+static void bnx2fc_port_destroy(struct fcoe_port *port)
 {
-	struct fcoe_port *port;
 	struct fc_lport *lport;
 
-	port = container_of(work, struct fcoe_port, destroy_work);
 	lport = port->lport;
-
-	BNX2FC_HBA_DBG(lport, "Entered bnx2fc_destroy_work\n");
+	BNX2FC_HBA_DBG(lport, "Entered %s, destroying lport %p\n", __func__, lport);
 
 	bnx2fc_if_destroy(lport);
 }
@@ -2553,9 +2548,6 @@
 			__bnx2fc_destroy(interface);
 	mutex_unlock(&bnx2fc_dev_lock);
 
-	/* Ensure ALL destroy work has been completed before return */
-	flush_workqueue(bnx2fc_wq);
-
 	bnx2fc_ulp_stop(hba);
 	/* unregister cnic device */
 	if (test_and_clear_bit(BNX2FC_CNIC_REGISTERED, &hba->reg_with_cnic))
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/bnx2fc/bnx2fc_io.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/bnx2fc/bnx2fc_io.c
@@ -1219,6 +1219,7 @@
 		   was a result from the ABTS request rather than the CLEANUP
 		   request */
 		set_bit(BNX2FC_FLAG_IO_CLEANUP,	&io_req->req_flags);
+		rc = FAILED;
 		goto done;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/bnx2fc/bnx2fc_tgt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/bnx2fc/bnx2fc_tgt.c
@@ -834,7 +834,6 @@
 
 	BNX2FC_TGT_DBG(tgt, "Freeing up session resources\n");
 
-	spin_lock_bh(&tgt->cq_lock);
 	ctx_base_ptr = tgt->ctx_base;
 	tgt->ctx_base = NULL;
 
@@ -890,7 +889,6 @@
 				    tgt->sq, tgt->sq_dma);
 		tgt->sq = NULL;
 	}
-	spin_unlock_bh(&tgt->cq_lock);
 
 	if (ctx_base_ptr)
 		iounmap(ctx_base_ptr);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/bnx2i/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/bnx2i/Kconfig
@@ -4,6 +4,7 @@
 	depends on NET
 	depends on PCI
 	depends on (IPV6 || IPV6=n)
+	depends on MMU
 	select SCSI_ISCSI_ATTRS
 	select NETDEVICES
 	select ETHERNET
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/bnx2i/bnx2i_iscsi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/bnx2i/bnx2i_iscsi.c
@@ -793,7 +793,7 @@
 		return NULL;
 	shost->dma_boundary = cnic->pcidev->dma_mask;
 	shost->transportt = bnx2i_scsi_xport_template;
-	shost->max_id = ISCSI_MAX_CONNS_PER_HBA;
+	shost->max_id = ISCSI_MAX_CONNS_PER_HBA - 1;
 	shost->max_channel = 0;
 	shost->max_lun = 512;
 	shost->max_cmd_len = 16;
@@ -915,12 +915,12 @@
 	INIT_LIST_HEAD(&hba->ep_ofld_list);
 	INIT_LIST_HEAD(&hba->ep_active_list);
 	INIT_LIST_HEAD(&hba->ep_destroy_list);
-	pci_dev_put(hba->pcidev);
 
 	if (hba->regview) {
 		pci_iounmap(hba->pcidev, hba->regview);
 		hba->regview = NULL;
 	}
+	pci_dev_put(hba->pcidev);
 	bnx2i_free_mp_bdt(hba);
 	bnx2i_release_free_cid_que(hba);
 	iscsi_host_free(shost);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/csiostor/csio_defs.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/csiostor/csio_defs.h
@@ -73,7 +73,21 @@
 #define csio_list_prev(elem)	(((struct list_head *)(elem))->prev)
 
 /* State machine */
-typedef void (*csio_sm_state_t)(void *, uint32_t);
+struct csio_lnode;
+
+/* State machine evets */
+enum csio_ln_ev {
+	CSIO_LNE_NONE = (uint32_t)0,
+	CSIO_LNE_LINKUP,
+	CSIO_LNE_FAB_INIT_DONE,
+	CSIO_LNE_LINK_DOWN,
+	CSIO_LNE_DOWN_LINK,
+	CSIO_LNE_LOGO,
+	CSIO_LNE_CLOSE,
+	CSIO_LNE_MAX_EVENT,
+};
+
+typedef void (*csio_sm_state_t)(struct csio_lnode *ln, enum csio_ln_ev evt);
 
 struct csio_sm {
 	struct list_head	sm_list;
@@ -83,7 +97,7 @@
 static inline void
 csio_set_state(void *smp, void *state)
 {
-	((struct csio_sm *)smp)->sm_state = (csio_sm_state_t)state;
+	((struct csio_sm *)smp)->sm_state = state;
 }
 
 static inline void
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/csiostor/csio_hw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/csiostor/csio_hw.c
@@ -2384,7 +2384,7 @@
 			FW_HDR_FW_VER_MICRO_G(c), FW_HDR_FW_VER_BUILD_G(c),
 			FW_HDR_FW_VER_MAJOR_G(k), FW_HDR_FW_VER_MINOR_G(k),
 			FW_HDR_FW_VER_MICRO_G(k), FW_HDR_FW_VER_BUILD_G(k));
-		ret = EINVAL;
+		ret = -EINVAL;
 		goto bye;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/csiostor/csio_init.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/csiostor/csio_init.c
@@ -1257,3 +1257,4 @@
 MODULE_VERSION(CSIO_DRV_VERSION);
 MODULE_FIRMWARE(FW_FNAME_T5);
 MODULE_FIRMWARE(FW_FNAME_T6);
+MODULE_SOFTDEP("pre: cxgb4");
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/csiostor/csio_lnode.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/csiostor/csio_lnode.c
@@ -301,6 +301,7 @@
 	struct fc_fdmi_port_name *port_name;
 	uint8_t buf[64];
 	uint8_t *fc4_type;
+	unsigned long flags;
 
 	if (fdmi_req->wr_status != FW_SUCCESS) {
 		csio_ln_dbg(ln, "WR error:%x in processing fdmi rhba cmd\n",
@@ -385,13 +386,13 @@
 	len = (uint32_t)(pld - (uint8_t *)cmd);
 
 	/* Submit FDMI RPA request */
-	spin_lock_irq(&hw->lock);
+	spin_lock_irqsave(&hw->lock, flags);
 	if (csio_ln_mgmt_submit_req(fdmi_req, csio_ln_fdmi_done,
 				FCOE_CT, &fdmi_req->dma_buf, len)) {
 		CSIO_INC_STATS(ln, n_fdmi_err);
 		csio_ln_dbg(ln, "Failed to issue fdmi rpa req\n");
 	}
-	spin_unlock_irq(&hw->lock);
+	spin_unlock_irqrestore(&hw->lock, flags);
 }
 
 /*
@@ -412,6 +413,7 @@
 	struct fc_fdmi_rpl *reg_pl;
 	struct fs_fdmi_attrs *attrib_blk;
 	uint8_t buf[64];
+	unsigned long flags;
 
 	if (fdmi_req->wr_status != FW_SUCCESS) {
 		csio_ln_dbg(ln, "WR error:%x in processing fdmi dprt cmd\n",
@@ -491,13 +493,13 @@
 	attrib_blk->numattrs = htonl(numattrs);
 
 	/* Submit FDMI RHBA request */
-	spin_lock_irq(&hw->lock);
+	spin_lock_irqsave(&hw->lock, flags);
 	if (csio_ln_mgmt_submit_req(fdmi_req, csio_ln_fdmi_rhba_cbfn,
 				FCOE_CT, &fdmi_req->dma_buf, len)) {
 		CSIO_INC_STATS(ln, n_fdmi_err);
 		csio_ln_dbg(ln, "Failed to issue fdmi rhba req\n");
 	}
-	spin_unlock_irq(&hw->lock);
+	spin_unlock_irqrestore(&hw->lock, flags);
 }
 
 /*
@@ -512,6 +514,7 @@
 	void *cmd;
 	struct fc_fdmi_port_name *port_name;
 	uint32_t len;
+	unsigned long flags;
 
 	if (fdmi_req->wr_status != FW_SUCCESS) {
 		csio_ln_dbg(ln, "WR error:%x in processing fdmi dhba cmd\n",
@@ -542,13 +545,13 @@
 	len += sizeof(*port_name);
 
 	/* Submit FDMI request */
-	spin_lock_irq(&hw->lock);
+	spin_lock_irqsave(&hw->lock, flags);
 	if (csio_ln_mgmt_submit_req(fdmi_req, csio_ln_fdmi_dprt_cbfn,
 				FCOE_CT, &fdmi_req->dma_buf, len)) {
 		CSIO_INC_STATS(ln, n_fdmi_err);
 		csio_ln_dbg(ln, "Failed to issue fdmi dprt req\n");
 	}
-	spin_unlock_irq(&hw->lock);
+	spin_unlock_irqrestore(&hw->lock, flags);
 }
 
 /**
@@ -616,7 +619,7 @@
 	struct fc_els_csp *csp;
 	struct fc_els_cssp *clsp;
 	enum fw_retval retval;
-	__be32 nport_id;
+	__be32 nport_id = 0;
 
 	retval = FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16));
 	if (retval != FW_SUCCESS) {
@@ -1092,7 +1095,7 @@
 int
 csio_is_lnode_ready(struct csio_lnode *ln)
 {
-	return (csio_get_state(ln) == ((csio_sm_state_t)csio_lns_ready));
+	return (csio_get_state(ln) == csio_lns_ready);
 }
 
 /*****************************************************************************/
@@ -1364,15 +1367,15 @@
 void
 csio_lnode_state_to_str(struct csio_lnode *ln, int8_t *str)
 {
-	if (csio_get_state(ln) == ((csio_sm_state_t)csio_lns_uninit)) {
+	if (csio_get_state(ln) == csio_lns_uninit) {
 		strcpy(str, "UNINIT");
 		return;
 	}
-	if (csio_get_state(ln) == ((csio_sm_state_t)csio_lns_ready)) {
+	if (csio_get_state(ln) == csio_lns_ready) {
 		strcpy(str, "READY");
 		return;
 	}
-	if (csio_get_state(ln) == ((csio_sm_state_t)csio_lns_offline)) {
+	if (csio_get_state(ln) == csio_lns_offline) {
 		strcpy(str, "OFFLINE");
 		return;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/csiostor/csio_lnode.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/csiostor/csio_lnode.h
@@ -53,19 +53,6 @@
 extern int csio_fcoe_rnodes;
 extern int csio_fdmi_enable;
 
-/* State machine evets */
-enum csio_ln_ev {
-	CSIO_LNE_NONE = (uint32_t)0,
-	CSIO_LNE_LINKUP,
-	CSIO_LNE_FAB_INIT_DONE,
-	CSIO_LNE_LINK_DOWN,
-	CSIO_LNE_DOWN_LINK,
-	CSIO_LNE_LOGO,
-	CSIO_LNE_CLOSE,
-	CSIO_LNE_MAX_EVENT,
-};
-
-
 struct csio_fcf_info {
 	struct list_head	list;
 	uint8_t			priority;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/csiostor/csio_scsi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/csiostor/csio_scsi.c
@@ -1383,7 +1383,7 @@
 		return -EINVAL;
 
 	/* Delete NPIV lnodes */
-	 csio_lnodes_exit(hw, 1);
+	csio_lnodes_exit(hw, 1);
 
 	/* Block upper IOs */
 	csio_lnodes_block_request(hw);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
@@ -959,6 +959,7 @@
 	struct net_device *ndev = cdev->ports[csk->port_id];
 	struct cxgbi_hba *chba = cdev->hbas[csk->port_id];
 	struct sk_buff *skb = NULL;
+	int ret;
 
 	log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
 		"csk 0x%p,%u,0x%lx.\n", csk, csk->state, csk->flags);
@@ -979,16 +980,16 @@
 	csk->atid = cxgb3_alloc_atid(t3dev, &t3_client, csk);
 	if (csk->atid < 0) {
 		pr_err("NO atid available.\n");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto put_sock;
 	}
 	cxgbi_sock_set_flag(csk, CTPF_HAS_ATID);
 	cxgbi_sock_get(csk);
 
 	skb = alloc_wr(sizeof(struct cpl_act_open_req), 0, GFP_KERNEL);
 	if (!skb) {
-		cxgb3_free_atid(t3dev, csk->atid);
-		cxgbi_sock_put(csk);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto free_atid;
 	}
 	skb->sk = (struct sock *)csk;
 	set_arp_failure_handler(skb, act_open_arp_failure);
@@ -1010,6 +1011,15 @@
 	cxgbi_sock_set_state(csk, CTP_ACTIVE_OPEN);
 	send_act_open_req(csk, skb, csk->l2t);
 	return 0;
+
+free_atid:
+	cxgb3_free_atid(t3dev, csk->atid);
+put_sock:
+	cxgbi_sock_put(csk);
+	l2t_release(t3dev, csk->l2t);
+	csk->l2t = NULL;
+
+	return ret;
 }
 
 cxgb3_cpl_handler_func cxgb3i_cpl_handlers[NUM_CPL_CMDS] = {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/cxgbi/cxgb4i/Kconfig
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/cxgbi/cxgb4i/Kconfig
@@ -4,6 +4,7 @@
 	depends on PCI && INET && (IPV6 || IPV6=n)
 	depends on THERMAL || !THERMAL
 	depends on ETHERNET
+	depends on TLS || TLS=n
 	select NET_VENDOR_CHELSIO
 	select CHELSIO_T4
 	select CHELSIO_LIB
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/cxgbi/libcxgbi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/cxgbi/libcxgbi.c
@@ -121,7 +121,8 @@
 		"cdev 0x%p, p# %u.\n", cdev, cdev->nports);
 	cxgbi_hbas_remove(cdev);
 	cxgbi_device_portmap_cleanup(cdev);
-	cxgbi_ppm_release(cdev->cdev2ppm(cdev));
+	if (cdev->cdev2ppm)
+		cxgbi_ppm_release(cdev->cdev2ppm(cdev));
 	if (cdev->pmap.max_connect)
 		cxgbi_free_big_mem(cdev->pmap.port_csk);
 	kfree(cdev);
@@ -336,7 +337,7 @@
 EXPORT_SYMBOL_GPL(cxgbi_hbas_remove);
 
 int cxgbi_hbas_add(struct cxgbi_device *cdev, u64 max_lun,
-		unsigned int max_id, struct scsi_host_template *sht,
+		unsigned int max_conns, struct scsi_host_template *sht,
 		struct scsi_transport_template *stt)
 {
 	struct cxgbi_hba *chba;
@@ -356,7 +357,7 @@
 
 		shost->transportt = stt;
 		shost->max_lun = max_lun;
-		shost->max_id = max_id;
+		shost->max_id = max_conns - 1;
 		shost->max_channel = 0;
 		shost->max_cmd_len = 16;
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/cxlflash/main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/cxlflash/main.c
@@ -3746,6 +3746,7 @@
 	cfg->afu_cookie = cfg->ops->create_afu(pdev);
 	if (unlikely(!cfg->afu_cookie)) {
 		dev_err(dev, "%s: create_afu failed\n", __func__);
+		rc = -ENOMEM;
 		goto out_remove;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/dc395x.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/dc395x.c
@@ -3664,10 +3664,19 @@
 #endif
 	if (dcb->target_lun != 0) {
 		/* Copy settings */
-		struct DeviceCtlBlk *p;
-		list_for_each_entry(p, &acb->dcb_list, list)
-			if (p->target_id == dcb->target_id)
+		struct DeviceCtlBlk *p = NULL, *iter;
+
+		list_for_each_entry(iter, &acb->dcb_list, list)
+			if (iter->target_id == dcb->target_id) {
+				p = iter;
 				break;
+			}
+
+		if (!p) {
+			kfree(dcb);
+			return NULL;
+		}
+
 		dprintkdbg(DBG_1, 
 		       "device_alloc: <%02i-%i> copy from <%02i-%i>\n",
 		       dcb->target_id, dcb->target_lun,
@@ -4159,7 +4168,7 @@
 	const unsigned srbs_per_page = PAGE_SIZE/SEGMENTX_LEN;
 	int srb_idx = 0;
 	unsigned i = 0;
-	struct SGentry *uninitialized_var(ptr);
+	struct SGentry *ptr;
 
 	for (i = 0; i < DC395x_MAX_SRB_CNT; i++)
 		acb->srb_array[i].segment_x = NULL;
@@ -4698,6 +4707,7 @@
 	/* initialise the adapter and everything we need */
  	if (adapter_init(acb, io_port_base, io_port_len, irq)) {
 		dprintkl(KERN_INFO, "adapter init failed\n");
+		acb = NULL;
 		goto fail;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/device_handler/scsi_dh_alua.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -508,7 +508,8 @@
 	struct alua_port_group *tmp_pg;
 	int len, k, off, bufflen = ALUA_RTPG_SIZE;
 	unsigned char *desc, *buff;
-	unsigned err, retval;
+	unsigned err;
+	int retval;
 	unsigned int tpg_desc_tbl_off;
 	unsigned char orig_transition_tmo;
 	unsigned long flags;
@@ -548,12 +549,12 @@
 			kfree(buff);
 			return SCSI_DH_OK;
 		}
-		if (!scsi_sense_valid(&sense_hdr)) {
+		if (retval < 0 || !scsi_sense_valid(&sense_hdr)) {
 			sdev_printk(KERN_INFO, sdev,
 				    "%s: rtpg failed, result %d\n",
 				    ALUA_DH_NAME, retval);
 			kfree(buff);
-			if (driver_byte(retval) == DRIVER_ERROR)
+			if (retval < 0)
 				return SCSI_DH_DEV_TEMP_BUSY;
 			return SCSI_DH_IO;
 		}
@@ -565,10 +566,11 @@
 		 * even though it shouldn't according to T10.
 		 * The retry without rtpg_ext_hdr_req set
 		 * handles this.
+		 * Note:  some arrays return a sense key of ILLEGAL_REQUEST
+		 * with ASC 00h if they don't support the extended header.
 		 */
 		if (!(pg->flags & ALUA_RTPG_EXT_HDR_UNSUPP) &&
-		    sense_hdr.sense_key == ILLEGAL_REQUEST &&
-		    sense_hdr.asc == 0x24 && sense_hdr.ascq == 0) {
+		    sense_hdr.sense_key == ILLEGAL_REQUEST) {
 			pg->flags |= ALUA_RTPG_EXT_HDR_UNSUPP;
 			goto retry;
 		}
@@ -658,8 +660,8 @@
 					rcu_read_lock();
 					list_for_each_entry_rcu(h,
 						&tmp_pg->dh_list, node) {
-						/* h->sdev should always be valid */
-						BUG_ON(!h->sdev);
+						if (!h->sdev)
+							continue;
 						h->sdev->access_state = desc[0];
 					}
 					rcu_read_unlock();
@@ -705,7 +707,8 @@
 			pg->expiry = 0;
 			rcu_read_lock();
 			list_for_each_entry_rcu(h, &pg->dh_list, node) {
-				BUG_ON(!h->sdev);
+				if (!h->sdev)
+					continue;
 				h->sdev->access_state =
 					(pg->state & SCSI_ACCESS_STATE_MASK);
 				if (pg->pref)
@@ -773,11 +776,11 @@
 	retval = submit_stpg(sdev, pg->group_id, &sense_hdr);
 
 	if (retval) {
-		if (!scsi_sense_valid(&sense_hdr)) {
+		if (retval < 0 || !scsi_sense_valid(&sense_hdr)) {
 			sdev_printk(KERN_INFO, sdev,
 				    "%s: stpg failed, result %d",
 				    ALUA_DH_NAME, retval);
-			if (driver_byte(retval) == DRIVER_ERROR)
+			if (retval < 0)
 				return SCSI_DH_DEV_TEMP_BUSY;
 		} else {
 			sdev_printk(KERN_INFO, sdev, "%s: stpg failed\n",
@@ -1033,10 +1036,12 @@
 	rcu_read_unlock();
 	mutex_unlock(&h->init_mutex);
 
-	if (alua_rtpg_queue(pg, sdev, qdata, true))
+	if (alua_rtpg_queue(pg, sdev, qdata, true)) {
 		fn = NULL;
-	else
+	} else {
+		kfree(qdata);
 		err = SCSI_DH_DEV_OFFLINED;
+	}
 	kref_put(&pg->kref, release_port_group);
 out:
 	if (fn)
@@ -1147,7 +1152,6 @@
 	spin_lock(&h->pg_lock);
 	pg = rcu_dereference_protected(h->pg, lockdep_is_held(&h->pg_lock));
 	rcu_assign_pointer(h->pg, NULL);
-	h->sdev = NULL;
 	spin_unlock(&h->pg_lock);
 	if (pg) {
 		spin_lock_irq(&pg->lock);
@@ -1156,6 +1160,7 @@
 		kref_put(&pg->kref, release_port_group);
 	}
 	sdev->handler_data = NULL;
+	synchronize_rcu();
 	kfree(h);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/device_handler/scsi_dh_rdac.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/device_handler/scsi_dh_rdac.c
@@ -453,8 +453,8 @@
 		if (!h->ctlr)
 			err = SCSI_DH_RES_TEMP_UNAVAIL;
 		else {
-			list_add_rcu(&h->node, &h->ctlr->dh_list);
 			h->sdev = sdev;
+			list_add_rcu(&h->node, &h->ctlr->dh_list);
 		}
 		spin_unlock(&list_lock);
 		err = SCSI_DH_OK;
@@ -778,11 +778,11 @@
 	spin_lock(&list_lock);
 	if (h->ctlr) {
 		list_del_rcu(&h->node);
-		h->sdev = NULL;
 		kref_put(&h->ctlr->kref, release_controller);
 	}
 	spin_unlock(&list_lock);
 	sdev->handler_data = NULL;
+	synchronize_rcu();
 	kfree(h);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/dpt_i2o.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/dpt_i2o.c
@@ -56,7 +56,7 @@
 
 #include <asm/processor.h>	/* for boot_cpu_data */
 #include <asm/pgtable.h>
-#include <asm/io.h>		/* for virt_to_bus, etc. */
+#include <asm/io.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
@@ -585,51 +585,6 @@
 	return 0;
 }
 
-/*
- *	Turn a pointer to ioctl reply data into an u32 'context'
- */
-static u32 adpt_ioctl_to_context(adpt_hba * pHba, void *reply)
-{
-#if BITS_PER_LONG == 32
-	return (u32)(unsigned long)reply;
-#else
-	ulong flags = 0;
-	u32 nr, i;
-
-	spin_lock_irqsave(pHba->host->host_lock, flags);
-	nr = ARRAY_SIZE(pHba->ioctl_reply_context);
-	for (i = 0; i < nr; i++) {
-		if (pHba->ioctl_reply_context[i] == NULL) {
-			pHba->ioctl_reply_context[i] = reply;
-			break;
-		}
-	}
-	spin_unlock_irqrestore(pHba->host->host_lock, flags);
-	if (i >= nr) {
-		printk(KERN_WARNING"%s: Too many outstanding "
-				"ioctl commands\n", pHba->name);
-		return (u32)-1;
-	}
-
-	return i;
-#endif
-}
-
-/*
- *	Go from an u32 'context' to a pointer to ioctl reply data.
- */
-static void *adpt_ioctl_from_context(adpt_hba *pHba, u32 context)
-{
-#if BITS_PER_LONG == 32
-	return (void *)(unsigned long)context;
-#else
-	void *p = pHba->ioctl_reply_context[context];
-	pHba->ioctl_reply_context[context] = NULL;
-
-	return p;
-#endif
-}
-
 /*===========================================================================
  * Error Handling routines
  *===========================================================================
@@ -1652,208 +1607,6 @@
 	return 0;
 }
 
-
-static int adpt_i2o_passthru(adpt_hba* pHba, u32 __user *arg)
-{
-	u32 msg[MAX_MESSAGE_SIZE];
-	u32* reply = NULL;
-	u32 size = 0;
-	u32 reply_size = 0;
-	u32 __user *user_msg = arg;
-	u32 __user * user_reply = NULL;
-	void **sg_list = NULL;
-	u32 sg_offset = 0;
-	u32 sg_count = 0;
-	int sg_index = 0;
-	u32 i = 0;
-	u32 rcode = 0;
-	void *p = NULL;
-	dma_addr_t addr;
-	ulong flags = 0;
-
-	memset(&msg, 0, MAX_MESSAGE_SIZE*4);
-	// get user msg size in u32s 
-	if(get_user(size, &user_msg[0])){
-		return -EFAULT;
-	}
-	size = size>>16;
-
-	user_reply = &user_msg[size];
-	if(size > MAX_MESSAGE_SIZE){
-		return -EFAULT;
-	}
-	size *= 4; // Convert to bytes
-
-	/* Copy in the user's I2O command */
-	if(copy_from_user(msg, user_msg, size)) {
-		return -EFAULT;
-	}
-	get_user(reply_size, &user_reply[0]);
-	reply_size = reply_size>>16;
-	if(reply_size > REPLY_FRAME_SIZE){
-		reply_size = REPLY_FRAME_SIZE;
-	}
-	reply_size *= 4;
-	reply = kzalloc(REPLY_FRAME_SIZE*4, GFP_KERNEL);
-	if(reply == NULL) {
-		printk(KERN_WARNING"%s: Could not allocate reply buffer\n",pHba->name);
-		return -ENOMEM;
-	}
-	sg_offset = (msg[0]>>4)&0xf;
-	msg[2] = 0x40000000; // IOCTL context
-	msg[3] = adpt_ioctl_to_context(pHba, reply);
-	if (msg[3] == (u32)-1) {
-		rcode = -EBUSY;
-		goto free;
-	}
-
-	sg_list = kcalloc(pHba->sg_tablesize, sizeof(*sg_list), GFP_KERNEL);
-	if (!sg_list) {
-		rcode = -ENOMEM;
-		goto free;
-	}
-	if(sg_offset) {
-		// TODO add 64 bit API
-		struct sg_simple_element *sg =  (struct sg_simple_element*) (msg+sg_offset);
-		sg_count = (size - sg_offset*4) / sizeof(struct sg_simple_element);
-		if (sg_count > pHba->sg_tablesize){
-			printk(KERN_DEBUG"%s:IOCTL SG List too large (%u)\n", pHba->name,sg_count);
-			rcode = -EINVAL;
-			goto free;
-		}
-
-		for(i = 0; i < sg_count; i++) {
-			int sg_size;
-
-			if (!(sg[i].flag_count & 0x10000000 /*I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT*/)) {
-				printk(KERN_DEBUG"%s:Bad SG element %d - not simple (%x)\n",pHba->name,i,  sg[i].flag_count);
-				rcode = -EINVAL;
-				goto cleanup;
-			}
-			sg_size = sg[i].flag_count & 0xffffff;      
-			/* Allocate memory for the transfer */
-			p = dma_alloc_coherent(&pHba->pDev->dev, sg_size, &addr, GFP_KERNEL);
-			if(!p) {
-				printk(KERN_DEBUG"%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
-						pHba->name,sg_size,i,sg_count);
-				rcode = -ENOMEM;
-				goto cleanup;
-			}
-			sg_list[sg_index++] = p; // sglist indexed with input frame, not our internal frame.
-			/* Copy in the user's SG buffer if necessary */
-			if(sg[i].flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR*/) {
-				// sg_simple_element API is 32 bit
-				if (copy_from_user(p,(void __user *)(ulong)sg[i].addr_bus, sg_size)) {
-					printk(KERN_DEBUG"%s: Could not copy SG buf %d FROM user\n",pHba->name,i);
-					rcode = -EFAULT;
-					goto cleanup;
-				}
-			}
-			/* sg_simple_element API is 32 bit, but addr < 4GB */
-			sg[i].addr_bus = addr;
-		}
-	}
-
-	do {
-		/*
-		 * Stop any new commands from enterring the
-		 * controller while processing the ioctl
-		 */
-		if (pHba->host) {
-			scsi_block_requests(pHba->host);
-			spin_lock_irqsave(pHba->host->host_lock, flags);
-		}
-		rcode = adpt_i2o_post_wait(pHba, msg, size, FOREVER);
-		if (rcode != 0)
-			printk("adpt_i2o_passthru: post wait failed %d %p\n",
-					rcode, reply);
-		if (pHba->host) {
-			spin_unlock_irqrestore(pHba->host->host_lock, flags);
-			scsi_unblock_requests(pHba->host);
-		}
-	} while (rcode == -ETIMEDOUT);
-
-	if(rcode){
-		goto cleanup;
-	}
-
-	if(sg_offset) {
-	/* Copy back the Scatter Gather buffers back to user space */
-		u32 j;
-		// TODO add 64 bit API
-		struct sg_simple_element* sg;
-		int sg_size;
-
-		// re-acquire the original message to handle correctly the sg copy operation
-		memset(&msg, 0, MAX_MESSAGE_SIZE*4); 
-		// get user msg size in u32s 
-		if(get_user(size, &user_msg[0])){
-			rcode = -EFAULT; 
-			goto cleanup; 
-		}
-		size = size>>16;
-		size *= 4;
-		if (size > MAX_MESSAGE_SIZE) {
-			rcode = -EINVAL;
-			goto cleanup;
-		}
-		/* Copy in the user's I2O command */
-		if (copy_from_user (msg, user_msg, size)) {
-			rcode = -EFAULT;
-			goto cleanup;
-		}
-		sg_count = (size - sg_offset*4) / sizeof(struct sg_simple_element);
-
-		// TODO add 64 bit API
-		sg 	 = (struct sg_simple_element*)(msg + sg_offset);
-		for (j = 0; j < sg_count; j++) {
-			/* Copy out the SG list to user's buffer if necessary */
-			if(! (sg[j].flag_count & 0x4000000 /*I2O_SGL_FLAGS_DIR*/)) {
-				sg_size = sg[j].flag_count & 0xffffff; 
-				// sg_simple_element API is 32 bit
-				if (copy_to_user((void __user *)(ulong)sg[j].addr_bus,sg_list[j], sg_size)) {
-					printk(KERN_WARNING"%s: Could not copy %p TO user %x\n",pHba->name, sg_list[j], sg[j].addr_bus);
-					rcode = -EFAULT;
-					goto cleanup;
-				}
-			}
-		}
-	} 
-
-	/* Copy back the reply to user space */
-	if (reply_size) {
-		// we wrote our own values for context - now restore the user supplied ones
-		if(copy_from_user(reply+2, user_msg+2, sizeof(u32)*2)) {
-			printk(KERN_WARNING"%s: Could not copy message context FROM user\n",pHba->name);
-			rcode = -EFAULT;
-		}
-		if(copy_to_user(user_reply, reply, reply_size)) {
-			printk(KERN_WARNING"%s: Could not copy reply TO user\n",pHba->name);
-			rcode = -EFAULT;
-		}
-	}
-
-
-cleanup:
-	if (rcode != -ETIME && rcode != -EINTR) {
-		struct sg_simple_element *sg =
-				(struct sg_simple_element*) (msg +sg_offset);
-		while(sg_index) {
-			if(sg_list[--sg_index]) {
-				dma_free_coherent(&pHba->pDev->dev,
-					sg[sg_index].flag_count & 0xffffff,
-					sg_list[sg_index],
-					sg[sg_index].addr_bus);
-			}
-		}
-	}
-
-free:
-	kfree(sg_list);
-	kfree(reply);
-	return rcode;
-}
-
 #if defined __ia64__ 
 static void adpt_ia64_info(sysInfo_S* si)
 {
@@ -1980,8 +1733,6 @@
 			return -EFAULT;
 		}
 		break;
-	case I2OUSRCMD:
-		return adpt_i2o_passthru(pHba, argp);
 
 	case DPT_CTRLINFO:{
 		drvrHBAinfo_S HbaInfo;
@@ -2118,7 +1869,7 @@
 		} else {
 			/* Ick, we should *never* be here */
 			printk(KERN_ERR "dpti: reply frame not from pool\n");
-			reply = (u8 *)bus_to_virt(m);
+			continue;
 		}
 
 		if (readl(reply) & MSG_FAIL) {
@@ -2138,13 +1889,6 @@
 			adpt_send_nop(pHba, old_m);
 		} 
 		context = readl(reply+8);
-		if(context & 0x40000000){ // IOCTL
-			void *p = adpt_ioctl_from_context(pHba, readl(reply+12));
-			if( p != NULL) {
-				memcpy_fromio(p, reply, REPLY_FRAME_SIZE * 4);
-			}
-			// All IOCTLs will also be post wait
-		}
 		if(context & 0x80000000){ // Post wait message
 			status = readl(reply+16);
 			if(status  >> 24){
@@ -2152,16 +1896,14 @@
 			} else {
 				status = I2O_POST_WAIT_OK;
 			}
-			if(!(context & 0x40000000)) {
-				/*
-				 * The request tag is one less than the command tag
-				 * as the firmware might treat a 0 tag as invalid
-				 */
-				cmd = scsi_host_find_tag(pHba->host,
-							 readl(reply + 12) - 1);
-				if(cmd != NULL) {
-					printk(KERN_WARNING"%s: Apparent SCSI cmd in Post Wait Context - cmd=%p context=%x\n", pHba->name, cmd, context);
-				}
+			/*
+			 * The request tag is one less than the command tag
+			 * as the firmware might treat a 0 tag as invalid
+			 */
+			cmd = scsi_host_find_tag(pHba->host,
+						 readl(reply + 12) - 1);
+			if(cmd != NULL) {
+				printk(KERN_WARNING"%s: Apparent SCSI cmd in Post Wait Context - cmd=%p context=%x\n", pHba->name, cmd, context);
 			}
 			adpt_i2o_post_wait_complete(context, status);
 		} else { // SCSI message
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/dpti.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/dpti.h
@@ -248,7 +248,6 @@
 	void __iomem *FwDebugBLEDflag_P;// Virtual Addr Of FW Debug BLED
 	void __iomem *FwDebugBLEDvalue_P;// Virtual Addr Of FW Debug BLED
 	u32 FwDebugFlags;
-	u32 *ioctl_reply_context[4];
 } adpt_hba;
 
 struct sg_simple_element {
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/esas2r/esas2r_flash.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/esas2r/esas2r_flash.c
@@ -1197,6 +1197,7 @@
 	if (!esas2r_read_flash_block(a, a->nvram, FLS_OFFSET_NVR,
 				     sizeof(struct esas2r_sas_nvram))) {
 		esas2r_hdebug("NVRAM read failed, using defaults");
+		up(&a->nvram_semaphore);
 		return false;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/fcoe/fcoe.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/fcoe/fcoe.c
@@ -2506,6 +2506,7 @@
 
 out_free:
 	mutex_unlock(&fcoe_config_mutex);
+	fcoe_transport_detach(&fcoe_sw_transport);
 out_destroy:
 	destroy_workqueue(fcoe_wq);
 	return rc;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/fcoe/fcoe_ctlr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/fcoe/fcoe_ctlr.c
@@ -255,9 +255,9 @@
 		WARN_ON(!fcf_dev);
 		new->fcf_dev = NULL;
 		fcoe_fcf_device_delete(fcf_dev);
-		kfree(new);
 		mutex_unlock(&cdev->lock);
 	}
+	kfree(new);
 }
 
 /**
@@ -1966,7 +1966,7 @@
  *
  * Returns: u64 fc world wide name
  */
-u64 fcoe_wwn_from_mac(unsigned char mac[MAX_ADDR_LEN],
+u64 fcoe_wwn_from_mac(unsigned char mac[ETH_ALEN],
 		      unsigned int scheme, unsigned int port)
 {
 	u64 wwn;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/fcoe/fcoe_sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/fcoe/fcoe_sysfs.c
@@ -830,14 +830,15 @@
 
 	dev_set_name(&ctlr->dev, "ctlr_%d", ctlr->id);
 	error = device_register(&ctlr->dev);
-	if (error)
-		goto out_del_q2;
+	if (error) {
+		destroy_workqueue(ctlr->devloss_work_q);
+		destroy_workqueue(ctlr->work_q);
+		put_device(&ctlr->dev);
+		return NULL;
+	}
 
 	return ctlr;
 
-out_del_q2:
-	destroy_workqueue(ctlr->devloss_work_q);
-	ctlr->devloss_work_q = NULL;
 out_del_q:
 	destroy_workqueue(ctlr->work_q);
 	ctlr->work_q = NULL;
@@ -1036,16 +1037,16 @@
 	fcf->selected = new_fcf->selected;
 
 	error = device_register(&fcf->dev);
-	if (error)
-		goto out_del;
+	if (error) {
+		put_device(&fcf->dev);
+		goto out;
+	}
 
 	fcf->state = FCOE_FCF_STATE_CONNECTED;
 	list_add_tail(&fcf->peers, &ctlr->fcfs);
 
 	return fcf;
 
-out_del:
-	kfree(fcf);
 out:
 	return NULL;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/fnic/fnic.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/fnic/fnic.h
@@ -39,7 +39,7 @@
 
 #define DRV_NAME		"fnic"
 #define DRV_DESCRIPTION		"Cisco FCoE HBA Driver"
-#define DRV_VERSION		"1.6.0.47"
+#define DRV_VERSION		"1.6.0.53"
 #define PFX			DRV_NAME ": "
 #define DFX                     DRV_NAME "%d: "
 
@@ -245,6 +245,7 @@
 	u32 vlan_hw_insert:1;	        /* let hw insert the tag */
 	u32 in_remove:1;                /* fnic device in removal */
 	u32 stop_rx_link_events:1;      /* stop proc. rx frames, link events */
+	u32 link_events:1;              /* set when we get any link event*/
 
 	struct completion *remove_wait; /* device remove thread blocks */
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/fnic/fnic_debugfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/fnic/fnic_debugfs.c
@@ -67,9 +67,10 @@
 		fc_trc_flag->fnic_trace = 2;
 		fc_trc_flag->fc_trace = 3;
 		fc_trc_flag->fc_clear = 4;
+		return 0;
 	}
 
-	return 0;
+	return -ENOMEM;
 }
 
 /*
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/fnic/fnic_fcs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/fnic/fnic_fcs.c
@@ -56,6 +56,8 @@
 
 	spin_lock_irqsave(&fnic->fnic_lock, flags);
 
+	fnic->link_events = 1;      /* less work to just set everytime*/
+
 	if (fnic->stop_rx_link_events) {
 		spin_unlock_irqrestore(&fnic->fnic_lock, flags);
 		return;
@@ -73,7 +75,7 @@
 	atomic64_set(&fnic->fnic_stats.misc_stats.current_port_speed,
 			new_port_speed);
 	if (old_port_speed != new_port_speed)
-		shost_printk(KERN_INFO, fnic->lport->host,
+		FNIC_MAIN_DBG(KERN_INFO, fnic->lport->host,
 				"Current vnic speed set to :  %llu\n",
 				new_port_speed);
 
@@ -1358,7 +1360,7 @@
 	}
 
 	vlan = list_first_entry(&fnic->vlans, struct fcoe_vlan, list);
-	shost_printk(KERN_DEBUG, fnic->lport->host,
+	FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
 		  "fip_timer: vlan %d state %d sol_count %d\n",
 		  vlan->vid, vlan->state, vlan->sol_count);
 	switch (vlan->state) {
@@ -1381,7 +1383,7 @@
 			 * no response on this vlan, remove  from the list.
 			 * Try the next vlan
 			 */
-			shost_printk(KERN_INFO, fnic->lport->host,
+			FNIC_FCS_DBG(KERN_INFO, fnic->lport->host,
 				  "Dequeue this VLAN ID %d from list\n",
 				  vlan->vid);
 			list_del(&vlan->list);
@@ -1391,7 +1393,7 @@
 				/* we exhausted all vlans, restart vlan disc */
 				spin_unlock_irqrestore(&fnic->vlans_lock,
 							flags);
-				shost_printk(KERN_INFO, fnic->lport->host,
+				FNIC_FCS_DBG(KERN_INFO, fnic->lport->host,
 					  "fip_timer: vlan list empty, "
 					  "trigger vlan disc\n");
 				fnic_event_enq(fnic, FNIC_EVT_START_VLAN_DISC);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/fnic/fnic_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/fnic/fnic_main.c
@@ -581,6 +581,8 @@
 	fnic->lport = lp;
 	fnic->ctlr.lp = lp;
 
+	fnic->link_events = 0;
+
 	snprintf(fnic->name, sizeof(fnic->name) - 1, "%s%d", DRV_NAME,
 		 host->host_no);
 
@@ -741,6 +743,7 @@
 	for (i = 0; i < FNIC_IO_LOCKS; i++)
 		spin_lock_init(&fnic->io_req_lock[i]);
 
+	err = -ENOMEM;
 	fnic->io_req_pool = mempool_create_slab_pool(2, fnic_io_req_cache);
 	if (!fnic->io_req_pool)
 		goto err_out_free_resources;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/fnic/fnic_scsi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/fnic/fnic_scsi.c
@@ -439,6 +439,9 @@
 	if (unlikely(fnic_chk_state_flags_locked(fnic, FNIC_FLAGS_IO_BLOCKED)))
 		return SCSI_MLQUEUE_HOST_BUSY;
 
+	if (unlikely(fnic_chk_state_flags_locked(fnic, FNIC_FLAGS_FWRESET)))
+		return SCSI_MLQUEUE_HOST_BUSY;
+
 	rport = starget_to_rport(scsi_target(sc->device));
 	if (!rport) {
 		FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
@@ -917,10 +920,11 @@
 	case FCPIO_SUCCESS:
 		sc->result = (DID_OK << 16) | icmnd_cmpl->scsi_status;
 		xfer_len = scsi_bufflen(sc);
-		scsi_set_resid(sc, icmnd_cmpl->residual);
 
-		if (icmnd_cmpl->flags & FCPIO_ICMND_CMPL_RESID_UNDER)
+		if (icmnd_cmpl->flags & FCPIO_ICMND_CMPL_RESID_UNDER) {
 			xfer_len -= icmnd_cmpl->residual;
+			scsi_set_resid(sc, icmnd_cmpl->residual);
+		}
 
 		if (icmnd_cmpl->scsi_status == SAM_STAT_CHECK_CONDITION)
 			atomic64_inc(&fnic_stats->misc_stats.check_condition);
@@ -1024,7 +1028,8 @@
 		atomic64_inc(&fnic_stats->io_stats.io_completions);
 
 
-	io_duration_time = jiffies_to_msecs(jiffies) - jiffies_to_msecs(io_req->start_time);
+	io_duration_time = jiffies_to_msecs(jiffies) -
+						jiffies_to_msecs(start_time);
 
 	if(io_duration_time <= 10)
 		atomic64_inc(&fnic_stats->io_stats.io_btw_0_to_10_msec);
@@ -1397,7 +1402,7 @@
 		}
 		if (!io_req) {
 			spin_unlock_irqrestore(io_lock, flags);
-			goto cleanup_scsi_cmd;
+			continue;
 		}
 
 		CMD_SP(sc) = NULL;
@@ -1412,7 +1417,6 @@
 		fnic_release_ioreq_buf(fnic, io_req, sc);
 		mempool_free(io_req, fnic->io_req_pool);
 
-cleanup_scsi_cmd:
 		sc->result = DID_TRANSPORT_DISRUPTED << 16;
 		FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
 			      "%s: tag:0x%x : sc:0x%p duration = %lu DID_TRANSPORT_DISRUPTED\n",
@@ -1730,15 +1734,14 @@
 			continue;
 		}
 
-		cmd_rport = starget_to_rport(scsi_target(sc->device));
-		if (rport != cmd_rport) {
+		io_req = (struct fnic_io_req *)CMD_SP(sc);
+		if (!io_req) {
 			spin_unlock_irqrestore(io_lock, flags);
 			continue;
 		}
 
-		io_req = (struct fnic_io_req *)CMD_SP(sc);
-
-		if (!io_req || rport != cmd_rport) {
+		cmd_rport = starget_to_rport(scsi_target(sc->device));
+		if (rport != cmd_rport) {
 			spin_unlock_irqrestore(io_lock, flags);
 			continue;
 		}
@@ -2669,7 +2672,8 @@
 	/* Issue firmware reset for fnic, wait for reset to complete */
 retry_fw_reset:
 	spin_lock_irqsave(&fnic->fnic_lock, flags);
-	if (unlikely(fnic->state == FNIC_IN_FC_TRANS_ETH_MODE)) {
+	if (unlikely(fnic->state == FNIC_IN_FC_TRANS_ETH_MODE) &&
+		     fnic->link_events) {
 		/* fw reset is in progress, poll for its completion */
 		spin_unlock_irqrestore(&fnic->fnic_lock, flags);
 		schedule_timeout(msecs_to_jiffies(100));
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/fnic/vnic_dev.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/fnic/vnic_dev.c
@@ -444,7 +444,8 @@
 	fetch_index = ioread32(&vdev->devcmd2->wq.ctrl->fetch_index);
 	if (fetch_index == 0xFFFFFFFF) { /* check for hardware gone  */
 		pr_err("error in devcmd2 init");
-		return -ENODEV;
+		err = -ENODEV;
+		goto err_free_wq;
 	}
 
 	/*
@@ -460,7 +461,7 @@
 	err = vnic_dev_alloc_desc_ring(vdev, &vdev->devcmd2->results_ring,
 			DEVCMD2_RING_SIZE, DEVCMD2_DESC_SIZE);
 	if (err)
-		goto err_free_wq;
+		goto err_disable_wq;
 
 	vdev->devcmd2->result =
 		(struct devcmd2_result *) vdev->devcmd2->results_ring.descs;
@@ -481,8 +482,9 @@
 
 err_free_desc_ring:
 	vnic_dev_free_desc_ring(vdev, &vdev->devcmd2->results_ring);
-err_free_wq:
+err_disable_wq:
 	vnic_wq_disable(&vdev->devcmd2->wq);
+err_free_wq:
 	vnic_wq_free(&vdev->devcmd2->wq);
 err_free_devcmd2:
 	kfree(vdev->devcmd2);
@@ -688,26 +690,26 @@
 
 int vnic_dev_hang_notify(struct vnic_dev *vdev)
 {
-	u64 a0, a1;
+	u64 a0 = 0, a1 = 0;
 	int wait = 1000;
 	return vnic_dev_cmd(vdev, CMD_HANG_NOTIFY, &a0, &a1, wait);
 }
 
 int vnic_dev_mac_addr(struct vnic_dev *vdev, u8 *mac_addr)
 {
-	u64 a0, a1;
+	u64 a[2] = {};
 	int wait = 1000;
 	int err, i;
 
 	for (i = 0; i < ETH_ALEN; i++)
 		mac_addr[i] = 0;
 
-	err = vnic_dev_cmd(vdev, CMD_MAC_ADDR, &a0, &a1, wait);
+	err = vnic_dev_cmd(vdev, CMD_MAC_ADDR, &a[0], &a[1], wait);
 	if (err)
 		return err;
 
 	for (i = 0; i < ETH_ALEN; i++)
-		mac_addr[i] = ((u8 *)&a0)[i];
+		mac_addr[i] = ((u8 *)&a)[i];
 
 	return 0;
 }
@@ -732,30 +734,30 @@
 
 void vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr)
 {
-	u64 a0 = 0, a1 = 0;
+	u64 a[2] = {};
 	int wait = 1000;
 	int err;
 	int i;
 
 	for (i = 0; i < ETH_ALEN; i++)
-		((u8 *)&a0)[i] = addr[i];
+		((u8 *)&a)[i] = addr[i];
 
-	err = vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait);
+	err = vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a[0], &a[1], wait);
 	if (err)
 		pr_err("Can't add addr [%pM], %d\n", addr, err);
 }
 
 void vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr)
 {
-	u64 a0 = 0, a1 = 0;
+	u64 a[2] = {};
 	int wait = 1000;
 	int err;
 	int i;
 
 	for (i = 0; i < ETH_ALEN; i++)
-		((u8 *)&a0)[i] = addr[i];
+		((u8 *)&a)[i] = addr[i];
 
-	err = vnic_dev_cmd(vdev, CMD_ADDR_DEL, &a0, &a1, wait);
+	err = vnic_dev_cmd(vdev, CMD_ADDR_DEL, &a[0], &a[1], wait);
 	if (err)
 		pr_err("Can't del addr [%pM], %d\n", addr, err);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/hisi_sas/hisi_sas.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/hisi_sas/hisi_sas.h
@@ -21,6 +21,7 @@
 #include <linux/platform_device.h>
 #include <linux/property.h>
 #include <linux/regmap.h>
+#include <linux/timer.h>
 #include <scsi/sas_ata.h>
 #include <scsi/libsas.h>
 
@@ -84,6 +85,7 @@
 #define HISI_SAS_PROT_MASK (HISI_SAS_DIF_PROT_MASK | HISI_SAS_DIX_PROT_MASK)
 
 #define HISI_SAS_WAIT_PHYUP_TIMEOUT 20
+#define CLEAR_ITCT_TIMEOUT	20
 
 struct hisi_hba;
 
@@ -167,6 +169,7 @@
 	enum sas_linkrate	minimum_linkrate;
 	enum sas_linkrate	maximum_linkrate;
 	int enable;
+	atomic_t down_cnt;
 };
 
 struct hisi_sas_port {
@@ -177,10 +180,10 @@
 
 struct hisi_sas_cq {
 	struct hisi_hba *hisi_hba;
-	const struct cpumask *pci_irq_mask;
-	struct tasklet_struct tasklet;
+	const struct cpumask *irq_mask;
 	int	rd_point;
 	int	id;
+	int	irq_no;
 };
 
 struct hisi_sas_dq {
@@ -296,8 +299,8 @@
 	void (*phy_set_linkrate)(struct hisi_hba *hisi_hba, int phy_no,
 			struct sas_phy_linkrates *linkrates);
 	enum sas_linkrate (*phy_get_max_linkrate)(void);
-	void (*clear_itct)(struct hisi_hba *hisi_hba,
-			    struct hisi_sas_device *dev);
+	int (*clear_itct)(struct hisi_hba *hisi_hba,
+			  struct hisi_sas_device *dev);
 	void (*free_device)(struct hisi_sas_device *sas_dev);
 	int (*get_wideport_bitmap)(struct hisi_hba *hisi_hba, int port_id);
 	void (*dereg_device)(struct hisi_hba *hisi_hba,
@@ -321,6 +324,44 @@
 	const struct hisi_sas_debugfs_reg *debugfs_reg_port;
 };
 
+#define HISI_SAS_MAX_DEBUGFS_DUMP (50)
+
+struct hisi_sas_debugfs_cq {
+	struct hisi_sas_cq *cq;
+	void *complete_hdr;
+};
+
+struct hisi_sas_debugfs_dq {
+	struct hisi_sas_dq *dq;
+	struct hisi_sas_cmd_hdr *hdr;
+};
+
+struct hisi_sas_debugfs_regs {
+	struct hisi_hba *hisi_hba;
+	u32 *data;
+};
+
+struct hisi_sas_debugfs_port {
+	struct hisi_sas_phy *phy;
+	u32 *data;
+};
+
+struct hisi_sas_debugfs_iost {
+	struct hisi_sas_iost *iost;
+};
+
+struct hisi_sas_debugfs_itct {
+	struct hisi_sas_itct *itct;
+};
+
+struct hisi_sas_debugfs_iost_cache {
+	struct hisi_sas_iost_itct_cache *cache;
+};
+
+struct hisi_sas_debugfs_itct_cache {
+	struct hisi_sas_iost_itct_cache *cache;
+};
+
 struct hisi_hba {
 	/* This must be the first element, used by SHOST_TO_SAS_HA */
 	struct sas_ha_struct *p;
@@ -402,19 +443,20 @@
 
 	/* debugfs memories */
 	/* Put Global AXI and RAS Register into register array */
-	u32 *debugfs_regs[DEBUGFS_REGS_NUM];
-	u32 *debugfs_port_reg[HISI_SAS_MAX_PHYS];
-	void *debugfs_complete_hdr[HISI_SAS_MAX_QUEUES];
-	struct hisi_sas_cmd_hdr	*debugfs_cmd_hdr[HISI_SAS_MAX_QUEUES];
-	struct hisi_sas_iost *debugfs_iost;
-	struct hisi_sas_itct *debugfs_itct;
-	u64 *debugfs_iost_cache;
-	u64 *debugfs_itct_cache;
+	struct hisi_sas_debugfs_regs debugfs_regs[HISI_SAS_MAX_DEBUGFS_DUMP][DEBUGFS_REGS_NUM];
+	struct hisi_sas_debugfs_port debugfs_port_reg[HISI_SAS_MAX_DEBUGFS_DUMP][HISI_SAS_MAX_PHYS];
+	struct hisi_sas_debugfs_cq debugfs_cq[HISI_SAS_MAX_DEBUGFS_DUMP][HISI_SAS_MAX_QUEUES];
+	struct hisi_sas_debugfs_dq debugfs_dq[HISI_SAS_MAX_DEBUGFS_DUMP][HISI_SAS_MAX_QUEUES];
+	struct hisi_sas_debugfs_iost debugfs_iost[HISI_SAS_MAX_DEBUGFS_DUMP];
+	struct hisi_sas_debugfs_itct debugfs_itct[HISI_SAS_MAX_DEBUGFS_DUMP];
+	struct hisi_sas_debugfs_iost_cache debugfs_iost_cache[HISI_SAS_MAX_DEBUGFS_DUMP];
+	struct hisi_sas_debugfs_itct_cache debugfs_itct_cache[HISI_SAS_MAX_DEBUGFS_DUMP];
 
+	u64 debugfs_timestamp[HISI_SAS_MAX_DEBUGFS_DUMP];
+	int debugfs_dump_index;
 	struct dentry *debugfs_dir;
 	struct dentry *debugfs_dump_dentry;
 	struct dentry *debugfs_bist_dentry;
-	bool debugfs_snapshot;
 };
 
 /* Generic HW DMA host memory structures */
@@ -556,6 +598,7 @@
 extern struct scsi_transport_template *hisi_sas_stt;
 
 extern bool hisi_sas_debugfs_enable;
+extern u32 hisi_sas_debugfs_dump_count;
 extern struct dentry *hisi_sas_debugfs_dir;
 
 extern void hisi_sas_stop_phys(struct hisi_hba *hisi_hba);
@@ -584,7 +627,7 @@
 extern void hisi_sas_init_mem(struct hisi_hba *hisi_hba);
 extern void hisi_sas_rst_work_handler(struct work_struct *work);
 extern void hisi_sas_sync_rst_work_handler(struct work_struct *work);
-extern void hisi_sas_kill_tasklets(struct hisi_hba *hisi_hba);
+extern void hisi_sas_sync_irqs(struct hisi_hba *hisi_hba);
 extern void hisi_sas_phy_oob_ready(struct hisi_hba *hisi_hba, int phy_no);
 extern bool hisi_sas_notify_phy_event(struct hisi_sas_phy *phy,
 				enum hisi_sas_phy_event event);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -163,13 +163,11 @@
 
 static void hisi_sas_slot_index_free(struct hisi_hba *hisi_hba, int slot_idx)
 {
-	unsigned long flags;
-
 	if (hisi_hba->hw->slot_index_alloc ||
 	    slot_idx >= HISI_SAS_UNRESERVED_IPTT) {
-		spin_lock_irqsave(&hisi_hba->lock, flags);
+		spin_lock(&hisi_hba->lock);
 		hisi_sas_slot_index_clear(hisi_hba, slot_idx);
-		spin_unlock_irqrestore(&hisi_hba->lock, flags);
+		spin_unlock(&hisi_hba->lock);
 	}
 }
 
@@ -185,12 +183,11 @@
 {
 	int index;
 	void *bitmap = hisi_hba->slot_index_tags;
-	unsigned long flags;
 
 	if (scsi_cmnd)
 		return scsi_cmnd->request->tag;
 
-	spin_lock_irqsave(&hisi_hba->lock, flags);
+	spin_lock(&hisi_hba->lock);
 	index = find_next_zero_bit(bitmap, hisi_hba->slot_index_count,
 				   hisi_hba->last_slot_index + 1);
 	if (index >= hisi_hba->slot_index_count) {
@@ -198,13 +195,13 @@
 				hisi_hba->slot_index_count,
 				HISI_SAS_UNRESERVED_IPTT);
 		if (index >= hisi_hba->slot_index_count) {
-			spin_unlock_irqrestore(&hisi_hba->lock, flags);
+			spin_unlock(&hisi_hba->lock);
 			return -SAS_QUEUE_FULL;
 		}
 	}
 	hisi_sas_slot_index_set(hisi_hba, index);
 	hisi_hba->last_slot_index = index;
-	spin_unlock_irqrestore(&hisi_hba->lock, flags);
+	spin_unlock(&hisi_hba->lock);
 
 	return index;
 }
@@ -220,7 +217,6 @@
 void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task,
 			     struct hisi_sas_slot *slot)
 {
-	unsigned long flags;
 	int device_id = slot->device_id;
 	struct hisi_sas_device *sas_dev = &hisi_hba->devices[device_id];
 
@@ -247,9 +243,9 @@
 		}
 	}
 
-	spin_lock_irqsave(&sas_dev->lock, flags);
+	spin_lock(&sas_dev->lock);
 	list_del_init(&slot->entry);
-	spin_unlock_irqrestore(&sas_dev->lock, flags);
+	spin_unlock(&sas_dev->lock);
 
 	memset(slot, 0, offsetof(struct hisi_sas_slot, buf));
 
@@ -489,14 +485,14 @@
 	slot_idx = rc;
 	slot = &hisi_hba->slot_info[slot_idx];
 
-	spin_lock_irqsave(&dq->lock, flags);
+	spin_lock(&dq->lock);
 	wr_q_index = dq->wr_point;
 	dq->wr_point = (dq->wr_point + 1) % HISI_SAS_QUEUE_SLOTS;
 	list_add_tail(&slot->delivery, &dq->list);
-	spin_unlock_irqrestore(&dq->lock, flags);
-	spin_lock_irqsave(&sas_dev->lock, flags);
+	spin_unlock(&dq->lock);
+	spin_lock(&sas_dev->lock);
 	list_add_tail(&slot->entry, &sas_dev->list);
-	spin_unlock_irqrestore(&sas_dev->lock, flags);
+	spin_unlock(&sas_dev->lock);
 
 	dlvry_queue = dq->id;
 	dlvry_queue_slot = wr_q_index;
@@ -562,7 +558,6 @@
 {
 	u32 rc;
 	u32 pass = 0;
-	unsigned long flags;
 	struct hisi_hba *hisi_hba;
 	struct device *dev;
 	struct domain_device *device = task->dev;
@@ -587,7 +582,13 @@
 	dev = hisi_hba->dev;
 
 	if (unlikely(test_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags))) {
-		if (in_softirq())
+		/*
+		 * For IOs from upper layer, it may already disable preempt
+		 * in the IO path, if disable preempt again in down(),
+		 * function schedule() will report schedule_bug(), so check
+		 * preemptible() before goto down().
+		 */
+		if (!preemptible())
 			return -EINVAL;
 
 		down(&hisi_hba->sem);
@@ -600,9 +601,9 @@
 		dev_err(dev, "task exec: failed[%d]!\n", rc);
 
 	if (likely(pass)) {
-		spin_lock_irqsave(&dq->lock, flags);
+		spin_lock(&dq->lock);
 		hisi_hba->hw->start_delivery(dq);
-		spin_unlock_irqrestore(&dq->lock, flags);
+		spin_unlock(&dq->lock);
 	}
 
 	return rc;
@@ -653,12 +654,11 @@
 {
 	struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
 	struct hisi_sas_device *sas_dev = NULL;
-	unsigned long flags;
 	int last = hisi_hba->last_dev_id;
 	int first = (hisi_hba->last_dev_id + 1) % HISI_SAS_MAX_DEVICES;
 	int i;
 
-	spin_lock_irqsave(&hisi_hba->lock, flags);
+	spin_lock(&hisi_hba->lock);
 	for (i = first; i != last; i %= HISI_SAS_MAX_DEVICES) {
 		if (hisi_hba->devices[i].dev_type == SAS_PHY_UNUSED) {
 			int queue = i % hisi_hba->queue_count;
@@ -678,7 +678,7 @@
 		i++;
 	}
 	hisi_hba->last_dev_id = i;
-	spin_unlock_irqrestore(&hisi_hba->lock, flags);
+	spin_unlock(&hisi_hba->lock);
 
 	return sas_dev;
 }
@@ -898,8 +898,11 @@
 	struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
 	struct device *dev = hisi_hba->dev;
 
+	dev_dbg(dev, "phy%d OOB ready\n", phy_no);
+	if (phy->phy_attached)
+		return;
+
 	if (!timer_pending(&phy->timer)) {
-		dev_dbg(dev, "phy%d OOB ready\n", phy_no);
 		phy->timer.expires = jiffies + HISI_SAS_WAIT_PHYUP_TIMEOUT * HZ;
 		add_timer(&phy->timer);
 	}
@@ -968,12 +971,13 @@
 	struct hisi_hba *hisi_hba = sas_ha->lldd_ha;
 	struct hisi_sas_phy *phy = sas_phy->lldd_phy;
 	struct asd_sas_port *sas_port = sas_phy->port;
-	struct hisi_sas_port *port = to_hisi_sas_port(sas_port);
+	struct hisi_sas_port *port;
 	unsigned long flags;
 
 	if (!sas_port)
 		return;
 
+	port = to_hisi_sas_port(sas_port);
 	spin_lock_irqsave(&hisi_hba->lock, flags);
 	port->port_attached = 1;
 	port->id = phy->port_id;
@@ -1045,6 +1049,7 @@
 	struct hisi_sas_device *sas_dev = device->lldd_dev;
 	struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
 	struct device *dev = hisi_hba->dev;
+	int ret = 0;
 
 	dev_info(dev, "dev[%d:%x] is gone\n",
 		 sas_dev->device_id, sas_dev->dev_type);
@@ -1056,13 +1061,16 @@
 
 		hisi_sas_dereg_device(hisi_hba, device);
 
-		hisi_hba->hw->clear_itct(hisi_hba, sas_dev);
+		ret = hisi_hba->hw->clear_itct(hisi_hba, sas_dev);
 		device->lldd_dev = NULL;
 	}
 
 	if (hisi_hba->hw->free_device)
 		hisi_hba->hw->free_device(sas_dev);
-	sas_dev->dev_type = SAS_PHY_UNUSED;
+
+	/* Don't mark it as SAS_PHY_UNUSED if failed to clear ITCT */
+	if (!ret)
+		sas_dev->dev_type = SAS_PHY_UNUSED;
 	sas_dev->sas_device = NULL;
 	up(&hisi_hba->sem);
 }
@@ -1222,10 +1230,10 @@
 					struct hisi_sas_cq *cq =
 					       &hisi_hba->cq[slot->dlvry_queue];
 					/*
-					 * flush tasklet to avoid free'ing task
+					 * sync irq to avoid free'ing task
 					 * before using task in IO completion
 					 */
-					tasklet_kill(&cq->tasklet);
+					synchronize_irq(cq->irq_no);
 					slot->task = NULL;
 				}
 
@@ -1387,7 +1395,7 @@
 				device->linkrate = phy->sas_phy.linkrate;
 
 			hisi_hba->hw->setup_itct(hisi_hba, sas_dev);
-		} else
+		} else if (!port->port_attached)
 			port->id = 0xff;
 	}
 }
@@ -1563,14 +1571,14 @@
 	struct Scsi_Host *shost = hisi_hba->shost;
 	int rc;
 
-	if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct)
+	if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct[0].itct)
 		queue_work(hisi_hba->wq, &hisi_hba->debugfs_work);
 
 	if (!hisi_hba->hw->soft_reset)
-		return -1;
+		return -ENOENT;
 
 	if (test_and_set_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags))
-		return -1;
+		return -EPERM;
 
 	dev_info(dev, "controller resetting...\n");
 	hisi_sas_controller_reset_prepare(hisi_hba);
@@ -1615,11 +1623,11 @@
 
 		if (slot) {
 			/*
-			 * flush tasklet to avoid free'ing task
+			 * sync irq to avoid free'ing task
 			 * before using task in IO completion
 			 */
 			cq = &hisi_hba->cq[slot->dlvry_queue];
-			tasklet_kill(&cq->tasklet);
+			synchronize_irq(cq->irq_no);
 		}
 		spin_unlock_irqrestore(&task->task_state_lock, flags);
 		rc = TMF_RESP_FUNC_COMPLETE;
@@ -1683,10 +1691,10 @@
 		if (((rc < 0) || (rc == TMF_RESP_FUNC_FAILED)) &&
 					task->lldd_task) {
 			/*
-			 * flush tasklet to avoid free'ing task
+			 * sync irq to avoid free'ing task
 			 * before using task in IO completion
 			 */
-			tasklet_kill(&cq->tasklet);
+			synchronize_irq(cq->irq_no);
 			slot->task = NULL;
 		}
 	}
@@ -1954,14 +1962,14 @@
 	slot_idx = rc;
 	slot = &hisi_hba->slot_info[slot_idx];
 
-	spin_lock_irqsave(&dq->lock, flags);
+	spin_lock(&dq->lock);
 	wr_q_index = dq->wr_point;
 	dq->wr_point = (dq->wr_point + 1) % HISI_SAS_QUEUE_SLOTS;
 	list_add_tail(&slot->delivery, &dq->list);
-	spin_unlock_irqrestore(&dq->lock, flags);
-	spin_lock_irqsave(&sas_dev->lock, flags);
+	spin_unlock(&dq->lock);
+	spin_lock(&sas_dev->lock);
 	list_add_tail(&slot->entry, &sas_dev->list);
-	spin_unlock_irqrestore(&sas_dev->lock, flags);
+	spin_unlock(&sas_dev->lock);
 
 	dlvry_queue = dq->id;
 	dlvry_queue_slot = wr_q_index;
@@ -1990,9 +1998,9 @@
 	spin_unlock_irqrestore(&task->task_state_lock, flags);
 	WRITE_ONCE(slot->ready, 1);
 	/* send abort command to the chip */
-	spin_lock_irqsave(&dq->lock, flags);
+	spin_lock(&dq->lock);
 	hisi_hba->hw->start_delivery(dq);
-	spin_unlock_irqrestore(&dq->lock, flags);
+	spin_unlock(&dq->lock);
 
 	return 0;
 
@@ -2055,7 +2063,7 @@
 
 	/* Internal abort timed out */
 	if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
-		if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct)
+		if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct[0].itct)
 			queue_work(hisi_hba->wq, &hisi_hba->debugfs_work);
 
 		if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
@@ -2065,10 +2073,10 @@
 				struct hisi_sas_cq *cq =
 					&hisi_hba->cq[slot->dlvry_queue];
 				/*
-				 * flush tasklet to avoid free'ing task
+				 * sync irq to avoid free'ing task
 				 * before using task in IO completion
 				 */
-				tasklet_kill(&cq->tasklet);
+				synchronize_irq(cq->irq_no);
 				slot->task = NULL;
 			}
 			dev_err(dev, "internal task abort: timeout and not done.\n");
@@ -2120,7 +2128,7 @@
 	case HISI_SAS_INT_ABT_DEV:
 		for (i = 0; i < hisi_hba->cq_nvecs; i++) {
 			struct hisi_sas_cq *cq = &hisi_hba->cq[i];
-			const struct cpumask *mask = cq->pci_irq_mask;
+			const struct cpumask *mask = cq->irq_mask;
 
 			if (mask && !cpumask_intersects(cpu_online_mask, mask))
 				continue;
@@ -2214,17 +2222,17 @@
 }
 EXPORT_SYMBOL_GPL(hisi_sas_phy_down);
 
-void hisi_sas_kill_tasklets(struct hisi_hba *hisi_hba)
+void hisi_sas_sync_irqs(struct hisi_hba *hisi_hba)
 {
 	int i;
 
 	for (i = 0; i < hisi_hba->cq_nvecs; i++) {
 		struct hisi_sas_cq *cq = &hisi_hba->cq[i];
 
-		tasklet_kill(&cq->tasklet);
+		synchronize_irq(cq->irq_no);
 	}
 }
-EXPORT_SYMBOL_GPL(hisi_sas_kill_tasklets);
+EXPORT_SYMBOL_GPL(hisi_sas_sync_irqs);
 
 int hisi_sas_host_reset(struct Scsi_Host *shost, int reset_type)
 {
@@ -2676,6 +2684,7 @@
 err_out_register_ha:
 	scsi_remove_host(shost);
 err_out_ha:
+	hisi_sas_debugfs_exit(hisi_hba);
 	hisi_sas_free(hisi_hba);
 	scsi_host_put(shost);
 	return rc;
@@ -2687,10 +2696,11 @@
 static void hisi_sas_debugfs_snapshot_cq_reg(struct hisi_hba *hisi_hba)
 {
 	int queue_entry_size = hisi_hba->hw->complete_hdr_size;
+	int dump_index = hisi_hba->debugfs_dump_index;
 	int i;
 
 	for (i = 0; i < hisi_hba->queue_count; i++)
-		memcpy(hisi_hba->debugfs_complete_hdr[i],
+		memcpy(hisi_hba->debugfs_cq[dump_index][i].complete_hdr,
 		       hisi_hba->complete_hdr[i],
 		       HISI_SAS_QUEUE_SLOTS * queue_entry_size);
 }
@@ -2698,13 +2708,14 @@
 static void hisi_sas_debugfs_snapshot_dq_reg(struct hisi_hba *hisi_hba)
 {
 	int queue_entry_size = sizeof(struct hisi_sas_cmd_hdr);
+	int dump_index = hisi_hba->debugfs_dump_index;
 	int i;
 
 	for (i = 0; i < hisi_hba->queue_count; i++) {
-		struct hisi_sas_cmd_hdr	*debugfs_cmd_hdr, *cmd_hdr;
+		struct hisi_sas_cmd_hdr *debugfs_cmd_hdr, *cmd_hdr;
 		int j;
 
-		debugfs_cmd_hdr = hisi_hba->debugfs_cmd_hdr[i];
+		debugfs_cmd_hdr = hisi_hba->debugfs_dq[dump_index][i].hdr;
 		cmd_hdr = hisi_hba->cmd_hdr[i];
 
 		for (j = 0; j < HISI_SAS_QUEUE_SLOTS; j++)
@@ -2715,6 +2726,7 @@
 
 static void hisi_sas_debugfs_snapshot_port_reg(struct hisi_hba *hisi_hba)
 {
+	int dump_index = hisi_hba->debugfs_dump_index;
 	const struct hisi_sas_debugfs_reg *port =
 		hisi_hba->hw->debugfs_reg_port;
 	int i, phy_cnt;
@@ -2722,7 +2734,7 @@
 	u32 *databuf;
 
 	for (phy_cnt = 0; phy_cnt < hisi_hba->n_phy; phy_cnt++) {
-		databuf = (u32 *)hisi_hba->debugfs_port_reg[phy_cnt];
+		databuf = hisi_hba->debugfs_port_reg[dump_index][phy_cnt].data;
 		for (i = 0; i < port->count; i++, databuf++) {
 			offset = port->base_off + 4 * i;
 			*databuf = port->read_port_reg(hisi_hba, phy_cnt,
@@ -2733,7 +2745,8 @@
 
 static void hisi_sas_debugfs_snapshot_global_reg(struct hisi_hba *hisi_hba)
 {
-	u32 *databuf = hisi_hba->debugfs_regs[DEBUGFS_GLOBAL];
+	int dump_index = hisi_hba->debugfs_dump_index;
+	u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_GLOBAL].data;
 	const struct hisi_sas_hw *hw = hisi_hba->hw;
 	const struct hisi_sas_debugfs_reg *global =
 			hw->debugfs_reg_array[DEBUGFS_GLOBAL];
@@ -2745,7 +2758,8 @@
 
 static void hisi_sas_debugfs_snapshot_axi_reg(struct hisi_hba *hisi_hba)
 {
-	u32 *databuf = hisi_hba->debugfs_regs[DEBUGFS_AXI];
+	int dump_index = hisi_hba->debugfs_dump_index;
+	u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_AXI].data;
 	const struct hisi_sas_hw *hw = hisi_hba->hw;
 	const struct hisi_sas_debugfs_reg *axi =
 			hw->debugfs_reg_array[DEBUGFS_AXI];
@@ -2758,7 +2772,8 @@
 
 static void hisi_sas_debugfs_snapshot_ras_reg(struct hisi_hba *hisi_hba)
 {
-	u32 *databuf = hisi_hba->debugfs_regs[DEBUGFS_RAS];
+	int dump_index = hisi_hba->debugfs_dump_index;
+	u32 *databuf = hisi_hba->debugfs_regs[dump_index][DEBUGFS_RAS].data;
 	const struct hisi_sas_hw *hw = hisi_hba->hw;
 	const struct hisi_sas_debugfs_reg *ras =
 			hw->debugfs_reg_array[DEBUGFS_RAS];
@@ -2771,8 +2786,9 @@
 
 static void hisi_sas_debugfs_snapshot_itct_reg(struct hisi_hba *hisi_hba)
 {
-	void *cachebuf = hisi_hba->debugfs_itct_cache;
-	void *databuf = hisi_hba->debugfs_itct;
+	int dump_index = hisi_hba->debugfs_dump_index;
+	void *cachebuf = hisi_hba->debugfs_itct_cache[dump_index].cache;
+	void *databuf = hisi_hba->debugfs_itct[dump_index].itct;
 	struct hisi_sas_itct *itct;
 	int i;
 
@@ -2789,9 +2805,10 @@
 
 static void hisi_sas_debugfs_snapshot_iost_reg(struct hisi_hba *hisi_hba)
 {
+	int dump_index = hisi_hba->debugfs_dump_index;
 	int max_command_entries = HISI_SAS_MAX_COMMANDS;
-	void *cachebuf = hisi_hba->debugfs_iost_cache;
-	void *databuf = hisi_hba->debugfs_iost;
+	void *cachebuf = hisi_hba->debugfs_iost_cache[dump_index].cache;
+	void *databuf = hisi_hba->debugfs_iost[dump_index].iost;
 	struct hisi_sas_iost *iost;
 	int i;
 
@@ -2842,11 +2859,12 @@
 
 static int hisi_sas_debugfs_global_show(struct seq_file *s, void *p)
 {
-	struct hisi_hba *hisi_hba = s->private;
+	struct hisi_sas_debugfs_regs *global = s->private;
+	struct hisi_hba *hisi_hba = global->hisi_hba;
 	const struct hisi_sas_hw *hw = hisi_hba->hw;
 	const void *reg_global = hw->debugfs_reg_array[DEBUGFS_GLOBAL];
 
-	hisi_sas_debugfs_print_reg(hisi_hba->debugfs_regs[DEBUGFS_GLOBAL],
+	hisi_sas_debugfs_print_reg(global->data,
 				   reg_global, s);
 
 	return 0;
@@ -2868,11 +2886,12 @@
 
 static int hisi_sas_debugfs_axi_show(struct seq_file *s, void *p)
 {
-	struct hisi_hba *hisi_hba = s->private;
+	struct hisi_sas_debugfs_regs *axi = s->private;
+	struct hisi_hba *hisi_hba = axi->hisi_hba;
 	const struct hisi_sas_hw *hw = hisi_hba->hw;
 	const void *reg_axi = hw->debugfs_reg_array[DEBUGFS_AXI];
 
-	hisi_sas_debugfs_print_reg(hisi_hba->debugfs_regs[DEBUGFS_AXI],
+	hisi_sas_debugfs_print_reg(axi->data,
 				   reg_axi, s);
 
 	return 0;
@@ -2894,11 +2913,12 @@
 
 static int hisi_sas_debugfs_ras_show(struct seq_file *s, void *p)
 {
-	struct hisi_hba *hisi_hba = s->private;
+	struct hisi_sas_debugfs_regs *ras = s->private;
+	struct hisi_hba *hisi_hba = ras->hisi_hba;
 	const struct hisi_sas_hw *hw = hisi_hba->hw;
 	const void *reg_ras = hw->debugfs_reg_array[DEBUGFS_RAS];
 
-	hisi_sas_debugfs_print_reg(hisi_hba->debugfs_regs[DEBUGFS_RAS],
+	hisi_sas_debugfs_print_reg(ras->data,
 				   reg_ras, s);
 
 	return 0;
@@ -2920,13 +2940,13 @@
 
 static int hisi_sas_debugfs_port_show(struct seq_file *s, void *p)
 {
-	struct hisi_sas_phy *phy = s->private;
+	struct hisi_sas_debugfs_port *port = s->private;
+	struct hisi_sas_phy *phy = port->phy;
 	struct hisi_hba *hisi_hba = phy->hisi_hba;
 	const struct hisi_sas_hw *hw = hisi_hba->hw;
 	const struct hisi_sas_debugfs_reg *reg_port = hw->debugfs_reg_port;
-	u32 *databuf = hisi_hba->debugfs_port_reg[phy->sas_phy.id];
 
-	hisi_sas_debugfs_print_reg(databuf, reg_port, s);
+	hisi_sas_debugfs_print_reg(port->data, reg_port, s);
 
 	return 0;
 }
@@ -2975,13 +2995,13 @@
 	seq_puts(s, "\n");
 }
 
-static void hisi_sas_cq_show_slot(struct seq_file *s, int slot, void *cq_ptr)
+static void hisi_sas_cq_show_slot(struct seq_file *s, int slot,
+				  struct hisi_sas_debugfs_cq *debugfs_cq)
 {
-	struct hisi_sas_cq *cq = cq_ptr;
+	struct hisi_sas_cq *cq = debugfs_cq->cq;
 	struct hisi_hba *hisi_hba = cq->hisi_hba;
-	void *complete_queue = hisi_hba->debugfs_complete_hdr[cq->id];
-	__le32 *complete_hdr = complete_queue +
-			(hisi_hba->hw->complete_hdr_size * slot);
+	__le32 *complete_hdr = debugfs_cq->complete_hdr +
+			       (hisi_hba->hw->complete_hdr_size * slot);
 
 	hisi_sas_show_row_32(s, slot,
 			     hisi_hba->hw->complete_hdr_size,
@@ -2990,11 +3010,11 @@
 
 static int hisi_sas_debugfs_cq_show(struct seq_file *s, void *p)
 {
-	struct hisi_sas_cq *cq = s->private;
+	struct hisi_sas_debugfs_cq *debugfs_cq = s->private;
 	int slot;
 
 	for (slot = 0; slot < HISI_SAS_QUEUE_SLOTS; slot++) {
-		hisi_sas_cq_show_slot(s, slot, cq);
+		hisi_sas_cq_show_slot(s, slot, debugfs_cq);
 	}
 	return 0;
 }
@@ -3014,9 +3034,8 @@
 
 static void hisi_sas_dq_show_slot(struct seq_file *s, int slot, void *dq_ptr)
 {
-	struct hisi_sas_dq *dq = dq_ptr;
-	struct hisi_hba *hisi_hba = dq->hisi_hba;
-	void *cmd_queue = hisi_hba->debugfs_cmd_hdr[dq->id];
+	struct hisi_sas_debugfs_dq *debugfs_dq = dq_ptr;
+	void *cmd_queue = debugfs_dq->hdr;
 	__le32 *cmd_hdr = cmd_queue +
 		sizeof(struct hisi_sas_cmd_hdr) * slot;
 
@@ -3048,14 +3067,14 @@
 
 static int hisi_sas_debugfs_iost_show(struct seq_file *s, void *p)
 {
-	struct hisi_hba *hisi_hba = s->private;
-	struct hisi_sas_iost *debugfs_iost = hisi_hba->debugfs_iost;
+	struct hisi_sas_debugfs_iost *debugfs_iost = s->private;
+	struct hisi_sas_iost *iost = debugfs_iost->iost;
 	int i, max_command_entries = HISI_SAS_MAX_COMMANDS;
 
-	for (i = 0; i < max_command_entries; i++, debugfs_iost++) {
-		__le64 *iost = &debugfs_iost->qw0;
+	for (i = 0; i < max_command_entries; i++, iost++) {
+		__le64 *data = &iost->qw0;
 
-		hisi_sas_show_row_64(s, i, sizeof(*debugfs_iost), iost);
+		hisi_sas_show_row_64(s, i, sizeof(*iost), data);
 	}
 
 	return 0;
@@ -3076,9 +3095,8 @@
 
 static int hisi_sas_debugfs_iost_cache_show(struct seq_file *s, void *p)
 {
-	struct hisi_hba *hisi_hba = s->private;
-	struct hisi_sas_iost_itct_cache *iost_cache =
-		(struct hisi_sas_iost_itct_cache *)hisi_hba->debugfs_iost_cache;
+	struct hisi_sas_debugfs_iost_cache *debugfs_iost_cache = s->private;
+	struct hisi_sas_iost_itct_cache *iost_cache = debugfs_iost_cache->cache;
 	u32 cache_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * 4;
 	int i, tab_idx;
 	__le64 *iost;
@@ -3117,13 +3135,13 @@
 static int hisi_sas_debugfs_itct_show(struct seq_file *s, void *p)
 {
 	int i;
-	struct hisi_hba *hisi_hba = s->private;
-	struct hisi_sas_itct *debugfs_itct = hisi_hba->debugfs_itct;
+	struct hisi_sas_debugfs_itct *debugfs_itct = s->private;
+	struct hisi_sas_itct *itct = debugfs_itct->itct;
 
-	for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, debugfs_itct++) {
-		__le64 *itct = &debugfs_itct->qw0;
+	for (i = 0; i < HISI_SAS_MAX_ITCT_ENTRIES; i++, itct++) {
+		__le64 *data = &itct->qw0;
 
-		hisi_sas_show_row_64(s, i, sizeof(*debugfs_itct), itct);
+		hisi_sas_show_row_64(s, i, sizeof(*itct), data);
 	}
 
 	return 0;
@@ -3144,9 +3162,8 @@
 
 static int hisi_sas_debugfs_itct_cache_show(struct seq_file *s, void *p)
 {
-	struct hisi_hba *hisi_hba = s->private;
-	struct hisi_sas_iost_itct_cache *itct_cache =
-		(struct hisi_sas_iost_itct_cache *)hisi_hba->debugfs_itct_cache;
+	struct hisi_sas_debugfs_itct_cache *debugfs_itct_cache = s->private;
+	struct hisi_sas_iost_itct_cache *itct_cache = debugfs_itct_cache->cache;
 	u32 cache_size = HISI_SAS_IOST_ITCT_CACHE_DW_SZ * 4;
 	int i, tab_idx;
 	__le64 *itct;
@@ -3184,6 +3201,8 @@
 
 static void hisi_sas_debugfs_create_files(struct hisi_hba *hisi_hba)
 {
+	u64 *debugfs_timestamp;
+	int dump_index = hisi_hba->debugfs_dump_index;
 	struct dentry *dump_dentry;
 	struct dentry *dentry;
 	char name[256];
@@ -3191,19 +3210,26 @@
 	int c;
 	int d;
 
-	/* Create dump dir inside device dir */
-	dump_dentry = debugfs_create_dir("dump", hisi_hba->debugfs_dir);
-	hisi_hba->debugfs_dump_dentry = dump_dentry;
+	snprintf(name, 256, "%d", dump_index);
+
+	dump_dentry = debugfs_create_dir(name, hisi_hba->debugfs_dump_dentry);
 
-	debugfs_create_file("global", 0400, dump_dentry, hisi_hba,
-			    &hisi_sas_debugfs_global_fops);
+	debugfs_timestamp = &hisi_hba->debugfs_timestamp[dump_index];
+
+	debugfs_create_u64("timestamp", 0400, dump_dentry,
+			   debugfs_timestamp);
+
+	debugfs_create_file("global", 0400, dump_dentry,
+			   &hisi_hba->debugfs_regs[dump_index][DEBUGFS_GLOBAL],
+			   &hisi_sas_debugfs_global_fops);
 
 	/* Create port dir and files */
 	dentry = debugfs_create_dir("port", dump_dentry);
 	for (p = 0; p < hisi_hba->n_phy; p++) {
 		snprintf(name, 256, "%d", p);
 
-		debugfs_create_file(name, 0400, dentry, &hisi_hba->phy[p],
+		debugfs_create_file(name, 0400, dentry,
+				    &hisi_hba->debugfs_port_reg[dump_index][p],
 				    &hisi_sas_debugfs_port_fops);
 	}
 
@@ -3212,7 +3238,8 @@
 	for (c = 0; c < hisi_hba->queue_count; c++) {
 		snprintf(name, 256, "%d", c);
 
-		debugfs_create_file(name, 0400, dentry, &hisi_hba->cq[c],
+		debugfs_create_file(name, 0400, dentry,
+				    &hisi_hba->debugfs_cq[dump_index][c],
 				    &hisi_sas_debugfs_cq_fops);
 	}
 
@@ -3221,26 +3248,33 @@
 	for (d = 0; d < hisi_hba->queue_count; d++) {
 		snprintf(name, 256, "%d", d);
 
-		debugfs_create_file(name, 0400, dentry, &hisi_hba->dq[d],
+		debugfs_create_file(name, 0400, dentry,
+				    &hisi_hba->debugfs_dq[dump_index][d],
 				    &hisi_sas_debugfs_dq_fops);
 	}
 
-	debugfs_create_file("iost", 0400, dump_dentry, hisi_hba,
+	debugfs_create_file("iost", 0400, dump_dentry,
+			    &hisi_hba->debugfs_iost[dump_index],
 			    &hisi_sas_debugfs_iost_fops);
 
-	debugfs_create_file("iost_cache", 0400, dump_dentry, hisi_hba,
+	debugfs_create_file("iost_cache", 0400, dump_dentry,
+			    &hisi_hba->debugfs_iost_cache[dump_index],
 			    &hisi_sas_debugfs_iost_cache_fops);
 
-	debugfs_create_file("itct", 0400, dump_dentry, hisi_hba,
+	debugfs_create_file("itct", 0400, dump_dentry,
+			    &hisi_hba->debugfs_itct[dump_index],
 			    &hisi_sas_debugfs_itct_fops);
 
-	debugfs_create_file("itct_cache", 0400, dump_dentry, hisi_hba,
+	debugfs_create_file("itct_cache", 0400, dump_dentry,
+			    &hisi_hba->debugfs_itct_cache[dump_index],
 			    &hisi_sas_debugfs_itct_cache_fops);
 
-	debugfs_create_file("axi", 0400, dump_dentry, hisi_hba,
+	debugfs_create_file("axi", 0400, dump_dentry,
+			    &hisi_hba->debugfs_regs[dump_index][DEBUGFS_AXI],
 			    &hisi_sas_debugfs_axi_fops);
 
-	debugfs_create_file("ras", 0400, dump_dentry, hisi_hba,
+	debugfs_create_file("ras", 0400, dump_dentry,
+			    &hisi_hba->debugfs_regs[dump_index][DEBUGFS_RAS],
 			    &hisi_sas_debugfs_ras_fops);
 
 	return;
@@ -3271,8 +3305,7 @@
 	struct hisi_hba *hisi_hba = file->f_inode->i_private;
 	char buf[8];
 
-	/* A bit racy, but don't care too much since it's only debugfs */
-	if (hisi_hba->debugfs_snapshot)
+	if (hisi_hba->debugfs_dump_index >= hisi_sas_debugfs_dump_count)
 		return -EFAULT;
 
 	if (count > 8)
@@ -3670,132 +3703,201 @@
 	.owner = THIS_MODULE,
 };
 
+static ssize_t hisi_sas_debugfs_phy_down_cnt_write(struct file *filp,
+						   const char __user *buf,
+						   size_t count, loff_t *ppos)
+{
+	struct seq_file *s = filp->private_data;
+	struct hisi_sas_phy *phy = s->private;
+	unsigned int set_val;
+	int res;
+
+	res = kstrtouint_from_user(buf, count, 0, &set_val);
+	if (res)
+		return res;
+
+	if (set_val > 0)
+		return -EINVAL;
+
+	atomic_set(&phy->down_cnt, 0);
+
+	return count;
+}
+
+static int hisi_sas_debugfs_phy_down_cnt_show(struct seq_file *s, void *p)
+{
+	struct hisi_sas_phy *phy = s->private;
+
+	seq_printf(s, "%d\n", atomic_read(&phy->down_cnt));
+
+	return 0;
+}
+
+static int hisi_sas_debugfs_phy_down_cnt_open(struct inode *inode,
+					      struct file *filp)
+{
+	return single_open(filp, hisi_sas_debugfs_phy_down_cnt_show,
+			   inode->i_private);
+}
+
+static const struct file_operations hisi_sas_debugfs_phy_down_cnt_ops = {
+	.open = hisi_sas_debugfs_phy_down_cnt_open,
+	.read = seq_read,
+	.write = hisi_sas_debugfs_phy_down_cnt_write,
+	.llseek = seq_lseek,
+	.release = single_release,
+	.owner = THIS_MODULE,
+};
+
 void hisi_sas_debugfs_work_handler(struct work_struct *work)
 {
 	struct hisi_hba *hisi_hba =
 		container_of(work, struct hisi_hba, debugfs_work);
+	int debugfs_dump_index = hisi_hba->debugfs_dump_index;
+	struct device *dev = hisi_hba->dev;
+	u64 timestamp = local_clock();
 
-	if (hisi_hba->debugfs_snapshot)
+	if (debugfs_dump_index >= hisi_sas_debugfs_dump_count) {
+		dev_warn(dev, "dump count exceeded!\n");
 		return;
-	hisi_hba->debugfs_snapshot = true;
+	}
+
+	do_div(timestamp, NSEC_PER_MSEC);
+	hisi_hba->debugfs_timestamp[debugfs_dump_index] = timestamp;
 
 	hisi_sas_debugfs_snapshot_regs(hisi_hba);
+	hisi_hba->debugfs_dump_index++;
 }
 EXPORT_SYMBOL_GPL(hisi_sas_debugfs_work_handler);
 
-static void hisi_sas_debugfs_release(struct hisi_hba *hisi_hba)
+static void hisi_sas_debugfs_release(struct hisi_hba *hisi_hba, int dump_index)
 {
 	struct device *dev = hisi_hba->dev;
 	int i;
 
-	devm_kfree(dev, hisi_hba->debugfs_iost_cache);
-	devm_kfree(dev, hisi_hba->debugfs_itct_cache);
-	devm_kfree(dev, hisi_hba->debugfs_iost);
+	devm_kfree(dev, hisi_hba->debugfs_iost_cache[dump_index].cache);
+	devm_kfree(dev, hisi_hba->debugfs_itct_cache[dump_index].cache);
+	devm_kfree(dev, hisi_hba->debugfs_iost[dump_index].iost);
+	devm_kfree(dev, hisi_hba->debugfs_itct[dump_index].itct);
 
 	for (i = 0; i < hisi_hba->queue_count; i++)
-		devm_kfree(dev, hisi_hba->debugfs_cmd_hdr[i]);
+		devm_kfree(dev, hisi_hba->debugfs_dq[dump_index][i].hdr);
 
 	for (i = 0; i < hisi_hba->queue_count; i++)
-		devm_kfree(dev, hisi_hba->debugfs_complete_hdr[i]);
+		devm_kfree(dev,
+			   hisi_hba->debugfs_cq[dump_index][i].complete_hdr);
 
 	for (i = 0; i < DEBUGFS_REGS_NUM; i++)
-		devm_kfree(dev, hisi_hba->debugfs_regs[i]);
+		devm_kfree(dev, hisi_hba->debugfs_regs[dump_index][i].data);
 
 	for (i = 0; i < hisi_hba->n_phy; i++)
-		devm_kfree(dev, hisi_hba->debugfs_port_reg[i]);
+		devm_kfree(dev, hisi_hba->debugfs_port_reg[dump_index][i].data);
 }
 
-static int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba)
+static int hisi_sas_debugfs_alloc(struct hisi_hba *hisi_hba, int dump_index)
 {
 	const struct hisi_sas_hw *hw = hisi_hba->hw;
 	struct device *dev = hisi_hba->dev;
-	int p, c, d;
+	int p, c, d, r, i;
 	size_t sz;
 
-	hisi_hba->debugfs_dump_dentry =
-			debugfs_create_dir("dump", hisi_hba->debugfs_dir);
-
-	sz = hw->debugfs_reg_array[DEBUGFS_GLOBAL]->count * 4;
-	hisi_hba->debugfs_regs[DEBUGFS_GLOBAL] =
-				devm_kmalloc(dev, sz, GFP_KERNEL);
-
-	if (!hisi_hba->debugfs_regs[DEBUGFS_GLOBAL])
-		goto fail;
+	for (r = 0; r < DEBUGFS_REGS_NUM; r++) {
+		struct hisi_sas_debugfs_regs *regs =
+				&hisi_hba->debugfs_regs[dump_index][r];
+
+		sz = hw->debugfs_reg_array[r]->count * 4;
+		regs->data = devm_kmalloc(dev, sz, GFP_KERNEL);
+		if (!regs->data)
+			goto fail;
+		regs->hisi_hba = hisi_hba;
+	}
 
 	sz = hw->debugfs_reg_port->count * 4;
 	for (p = 0; p < hisi_hba->n_phy; p++) {
-		hisi_hba->debugfs_port_reg[p] =
-			devm_kmalloc(dev, sz, GFP_KERNEL);
+		struct hisi_sas_debugfs_port *port =
+				&hisi_hba->debugfs_port_reg[dump_index][p];
 
-		if (!hisi_hba->debugfs_port_reg[p])
+		port->data = devm_kmalloc(dev, sz, GFP_KERNEL);
+		if (!port->data)
 			goto fail;
+		port->phy = &hisi_hba->phy[p];
 	}
 
-	sz = hw->debugfs_reg_array[DEBUGFS_AXI]->count * 4;
-	hisi_hba->debugfs_regs[DEBUGFS_AXI] =
-		devm_kmalloc(dev, sz, GFP_KERNEL);
-
-	if (!hisi_hba->debugfs_regs[DEBUGFS_AXI])
-		goto fail;
-
-	sz = hw->debugfs_reg_array[DEBUGFS_RAS]->count * 4;
-	hisi_hba->debugfs_regs[DEBUGFS_RAS] =
-		devm_kmalloc(dev, sz, GFP_KERNEL);
-
-	if (!hisi_hba->debugfs_regs[DEBUGFS_RAS])
-		goto fail;
-
 	sz = hw->complete_hdr_size * HISI_SAS_QUEUE_SLOTS;
 	for (c = 0; c < hisi_hba->queue_count; c++) {
-		hisi_hba->debugfs_complete_hdr[c] =
-			devm_kmalloc(dev, sz, GFP_KERNEL);
+		struct hisi_sas_debugfs_cq *cq =
+				&hisi_hba->debugfs_cq[dump_index][c];
 
-		if (!hisi_hba->debugfs_complete_hdr[c])
+		cq->complete_hdr = devm_kmalloc(dev, sz, GFP_KERNEL);
+		if (!cq->complete_hdr)
 			goto fail;
+		cq->cq = &hisi_hba->cq[c];
 	}
 
 	sz = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS;
 	for (d = 0; d < hisi_hba->queue_count; d++) {
-		hisi_hba->debugfs_cmd_hdr[d] =
-			devm_kmalloc(dev, sz, GFP_KERNEL);
+		struct hisi_sas_debugfs_dq *dq =
+				&hisi_hba->debugfs_dq[dump_index][d];
 
-		if (!hisi_hba->debugfs_cmd_hdr[d])
+		dq->hdr = devm_kmalloc(dev, sz, GFP_KERNEL);
+		if (!dq->hdr)
 			goto fail;
+		dq->dq = &hisi_hba->dq[d];
 	}
 
 	sz = HISI_SAS_MAX_COMMANDS * sizeof(struct hisi_sas_iost);
 
-	hisi_hba->debugfs_iost = devm_kmalloc(dev, sz, GFP_KERNEL);
-	if (!hisi_hba->debugfs_iost)
+	hisi_hba->debugfs_iost[dump_index].iost =
+				devm_kmalloc(dev, sz, GFP_KERNEL);
+	if (!hisi_hba->debugfs_iost[dump_index].iost)
 		goto fail;
 
 	sz = HISI_SAS_IOST_ITCT_CACHE_NUM *
 	     sizeof(struct hisi_sas_iost_itct_cache);
 
-	hisi_hba->debugfs_iost_cache = devm_kmalloc(dev, sz, GFP_KERNEL);
-	if (!hisi_hba->debugfs_iost_cache)
+	hisi_hba->debugfs_iost_cache[dump_index].cache =
+				devm_kmalloc(dev, sz, GFP_KERNEL);
+	if (!hisi_hba->debugfs_iost_cache[dump_index].cache)
 		goto fail;
 
 	sz = HISI_SAS_IOST_ITCT_CACHE_NUM *
 	     sizeof(struct hisi_sas_iost_itct_cache);
 
-	hisi_hba->debugfs_itct_cache = devm_kmalloc(dev, sz, GFP_KERNEL);
-	if (!hisi_hba->debugfs_itct_cache)
+	hisi_hba->debugfs_itct_cache[dump_index].cache =
+				devm_kmalloc(dev, sz, GFP_KERNEL);
+	if (!hisi_hba->debugfs_itct_cache[dump_index].cache)
 		goto fail;
 
 	/* New memory allocation must be locate before itct */
 	sz = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct);
 
-	hisi_hba->debugfs_itct = devm_kmalloc(dev, sz, GFP_KERNEL);
-	if (!hisi_hba->debugfs_itct)
+	hisi_hba->debugfs_itct[dump_index].itct =
+				devm_kmalloc(dev, sz, GFP_KERNEL);
+	if (!hisi_hba->debugfs_itct[dump_index].itct)
 		goto fail;
 
 	return 0;
 fail:
-	hisi_sas_debugfs_release(hisi_hba);
+	for (i = 0; i < hisi_sas_debugfs_dump_count; i++)
+		hisi_sas_debugfs_release(hisi_hba, i);
 	return -ENOMEM;
 }
 
+static void hisi_sas_debugfs_phy_down_cnt_init(struct hisi_hba *hisi_hba)
+{
+	struct dentry *dir = debugfs_create_dir("phy_down_cnt",
+						hisi_hba->debugfs_dir);
+	char name[16];
+	int phy_no;
+
+	for (phy_no = 0; phy_no < hisi_hba->n_phy; phy_no++) {
+		snprintf(name, 16, "%d", phy_no);
+		debugfs_create_file(name, 0600, dir,
+				    &hisi_hba->phy[phy_no],
+				    &hisi_sas_debugfs_phy_down_cnt_ops);
+	}
+}
+
 static void hisi_sas_debugfs_bist_init(struct hisi_hba *hisi_hba)
 {
 	hisi_hba->debugfs_bist_dentry =
@@ -3827,10 +3929,11 @@
 void hisi_sas_debugfs_init(struct hisi_hba *hisi_hba)
 {
 	struct device *dev = hisi_hba->dev;
+	int i;
 
 	hisi_hba->debugfs_dir = debugfs_create_dir(dev_name(dev),
 						   hisi_sas_debugfs_dir);
-	debugfs_create_file("trigger_dump", 0600,
+	debugfs_create_file("trigger_dump", 0200,
 			    hisi_hba->debugfs_dir,
 			    hisi_hba,
 			    &hisi_sas_debugfs_trigger_dump_fops);
@@ -3838,9 +3941,17 @@
 	/* create bist structures */
 	hisi_sas_debugfs_bist_init(hisi_hba);
 
-	if (hisi_sas_debugfs_alloc(hisi_hba)) {
-		debugfs_remove_recursive(hisi_hba->debugfs_dir);
-		dev_dbg(dev, "failed to init debugfs!\n");
+	hisi_hba->debugfs_dump_dentry =
+			debugfs_create_dir("dump", hisi_hba->debugfs_dir);
+
+	hisi_sas_debugfs_phy_down_cnt_init(hisi_hba);
+
+	for (i = 0; i < hisi_sas_debugfs_dump_count; i++) {
+		if (hisi_sas_debugfs_alloc(hisi_hba, i)) {
+			debugfs_remove_recursive(hisi_hba->debugfs_dir);
+			dev_dbg(dev, "failed to init debugfs!\n");
+			break;
+		}
 	}
 }
 EXPORT_SYMBOL_GPL(hisi_sas_debugfs_init);
@@ -3874,14 +3985,24 @@
 module_param_named(debugfs_enable, hisi_sas_debugfs_enable, bool, 0444);
 MODULE_PARM_DESC(hisi_sas_debugfs_enable, "Enable driver debugfs (default disabled)");
 
+u32 hisi_sas_debugfs_dump_count = 1;
+EXPORT_SYMBOL_GPL(hisi_sas_debugfs_dump_count);
+module_param_named(debugfs_dump_count, hisi_sas_debugfs_dump_count, uint, 0444);
+MODULE_PARM_DESC(hisi_sas_debugfs_dump_count, "Number of debugfs dumps to allow");
+
 static __init int hisi_sas_init(void)
 {
 	hisi_sas_stt = sas_domain_attach_transport(&hisi_sas_transport_ops);
 	if (!hisi_sas_stt)
 		return -ENOMEM;
 
-	if (hisi_sas_debugfs_enable)
+	if (hisi_sas_debugfs_enable) {
 		hisi_sas_debugfs_dir = debugfs_create_dir("hisi_sas", NULL);
+		if (hisi_sas_debugfs_dump_count > HISI_SAS_MAX_DEBUGFS_DUMP) {
+			pr_info("hisi_sas: Limiting debugfs dump count\n");
+			hisi_sas_debugfs_dump_count = HISI_SAS_MAX_DEBUGFS_DUMP;
+		}
+	}
 
 	return 0;
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
@@ -531,8 +531,8 @@
 				(0xff00ULL << ITCT_HDR_REJ_OPEN_TL_OFF));
 }
 
-static void clear_itct_v1_hw(struct hisi_hba *hisi_hba,
-			      struct hisi_sas_device *sas_dev)
+static int clear_itct_v1_hw(struct hisi_hba *hisi_hba,
+			    struct hisi_sas_device *sas_dev)
 {
 	u64 dev_id = sas_dev->device_id;
 	struct hisi_sas_itct *itct = &hisi_hba->itct[dev_id];
@@ -551,6 +551,8 @@
 	qw0 = le64_to_cpu(itct->qw0);
 	qw0 &= ~ITCT_HDR_VALID_MSK;
 	itct->qw0 = cpu_to_le64(qw0);
+
+	return 0;
 }
 
 static int reset_hw_v1_hw(struct hisi_hba *hisi_hba)
@@ -1645,10 +1647,10 @@
 		idx = i * HISI_SAS_PHY_INT_NR;
 		for (j = 0; j < HISI_SAS_PHY_INT_NR; j++, idx++) {
 			irq = platform_get_irq(pdev, idx);
-			if (!irq) {
+			if (irq < 0) {
 				dev_err(dev, "irq init: fail map phy interrupt %d\n",
 					idx);
-				return -ENOENT;
+				return irq;
 			}
 
 			rc = devm_request_irq(dev, irq, phy_interrupts[j], 0,
@@ -1656,7 +1658,7 @@
 			if (rc) {
 				dev_err(dev, "irq init: could not request phy interrupt %d, rc=%d\n",
 					irq, rc);
-				return -ENOENT;
+				return rc;
 			}
 		}
 	}
@@ -1664,10 +1666,10 @@
 	idx = hisi_hba->n_phy * HISI_SAS_PHY_INT_NR;
 	for (i = 0; i < hisi_hba->queue_count; i++, idx++) {
 		irq = platform_get_irq(pdev, idx);
-		if (!irq) {
+		if (irq < 0) {
 			dev_err(dev, "irq init: could not map cq interrupt %d\n",
 				idx);
-			return -ENOENT;
+			return irq;
 		}
 
 		rc = devm_request_irq(dev, irq, cq_interrupt_v1_hw, 0,
@@ -1675,17 +1677,17 @@
 		if (rc) {
 			dev_err(dev, "irq init: could not request cq interrupt %d, rc=%d\n",
 				irq, rc);
-			return -ENOENT;
+			return rc;
 		}
 	}
 
 	idx = (hisi_hba->n_phy * HISI_SAS_PHY_INT_NR) + hisi_hba->queue_count;
 	for (i = 0; i < HISI_SAS_FATAL_INT_NR; i++, idx++) {
 		irq = platform_get_irq(pdev, idx);
-		if (!irq) {
+		if (irq < 0) {
 			dev_err(dev, "irq init: could not map fatal interrupt %d\n",
 				idx);
-			return -ENOENT;
+			return irq;
 		}
 
 		rc = devm_request_irq(dev, irq, fatal_interrupts[i], 0,
@@ -1693,7 +1695,7 @@
 		if (rc) {
 			dev_err(dev, "irq init: could not request fatal interrupt %d, rc=%d\n",
 				irq, rc);
-			return -ENOENT;
+			return rc;
 		}
 	}
 
@@ -1768,6 +1770,7 @@
 	.max_sectors		= SCSI_DEFAULT_MAX_SECTORS,
 	.eh_device_reset_handler = sas_eh_device_reset_handler,
 	.eh_target_reset_handler = sas_eh_target_reset_handler,
+	.slave_alloc		= sas_slave_alloc,
 	.target_destroy		= sas_target_destroy,
 	.ioctl			= sas_ioctl,
 	.shost_attrs		= host_attrs_v1_hw,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -773,7 +773,6 @@
 	struct hisi_sas_device *sas_dev = device->lldd_dev;
 	int sata_idx = sas_dev->sata_idx;
 	int start, end;
-	unsigned long flags;
 
 	if (!sata_dev) {
 		/*
@@ -797,12 +796,12 @@
 		end = 64 * (sata_idx + 2);
 	}
 
-	spin_lock_irqsave(&hisi_hba->lock, flags);
+	spin_lock(&hisi_hba->lock);
 	while (1) {
 		start = find_next_zero_bit(bitmap,
 					hisi_hba->slot_index_count, start);
 		if (start >= end) {
-			spin_unlock_irqrestore(&hisi_hba->lock, flags);
+			spin_unlock(&hisi_hba->lock);
 			return -SAS_QUEUE_FULL;
 		}
 		/*
@@ -814,7 +813,7 @@
 	}
 
 	set_bit(start, bitmap);
-	spin_unlock_irqrestore(&hisi_hba->lock, flags);
+	spin_unlock(&hisi_hba->lock);
 	return start;
 }
 
@@ -843,9 +842,8 @@
 	struct hisi_sas_device *sas_dev = NULL;
 	int i, sata_dev = dev_is_sata(device);
 	int sata_idx = -1;
-	unsigned long flags;
 
-	spin_lock_irqsave(&hisi_hba->lock, flags);
+	spin_lock(&hisi_hba->lock);
 
 	if (sata_dev)
 		if (!sata_index_alloc_v2_hw(hisi_hba, &sata_idx))
@@ -876,7 +874,7 @@
 	}
 
 out:
-	spin_unlock_irqrestore(&hisi_hba->lock, flags);
+	spin_unlock(&hisi_hba->lock);
 
 	return sas_dev;
 }
@@ -974,13 +972,14 @@
 					(0x1ULL << ITCT_HDR_RTOLT_OFF));
 }
 
-static void clear_itct_v2_hw(struct hisi_hba *hisi_hba,
-			      struct hisi_sas_device *sas_dev)
+static int clear_itct_v2_hw(struct hisi_hba *hisi_hba,
+			    struct hisi_sas_device *sas_dev)
 {
 	DECLARE_COMPLETION_ONSTACK(completion);
 	u64 dev_id = sas_dev->device_id;
 	struct hisi_sas_itct *itct = &hisi_hba->itct[dev_id];
 	u32 reg_val = hisi_sas_read32(hisi_hba, ENT_INT_SRC3);
+	struct device *dev = hisi_hba->dev;
 	int i;
 
 	sas_dev->completion = &completion;
@@ -990,13 +989,19 @@
 		hisi_sas_write32(hisi_hba, ENT_INT_SRC3,
 				 ENT_INT_SRC3_ITC_INT_MSK);
 
+	/* need to set register twice to clear ITCT for v2 hw */
 	for (i = 0; i < 2; i++) {
 		reg_val = ITCT_CLR_EN_MSK | (dev_id & ITCT_DEV_MSK);
 		hisi_sas_write32(hisi_hba, ITCT_CLR, reg_val);
-		wait_for_completion(sas_dev->completion);
+		if (!wait_for_completion_timeout(sas_dev->completion,
+						 CLEAR_ITCT_TIMEOUT * HZ)) {
+			dev_warn(dev, "failed to clear ITCT\n");
+			return -ETIMEDOUT;
+		}
 
 		memset(itct, 0, sizeof(struct hisi_sas_itct));
 	}
+	return 0;
 }
 
 static void free_device_v2_hw(struct hisi_sas_device *sas_dev)
@@ -3104,9 +3109,9 @@
 	return IRQ_HANDLED;
 }
 
-static void cq_tasklet_v2_hw(unsigned long val)
+static irqreturn_t  cq_thread_v2_hw(int irq_no, void *p)
 {
-	struct hisi_sas_cq *cq = (struct hisi_sas_cq *)val;
+	struct hisi_sas_cq *cq = p;
 	struct hisi_hba *hisi_hba = cq->hisi_hba;
 	struct hisi_sas_slot *slot;
 	struct hisi_sas_itct *itct;
@@ -3174,6 +3179,8 @@
 	/* update rd_point */
 	cq->rd_point = rd_point;
 	hisi_sas_write32(hisi_hba, COMPL_Q_0_RD_PTR + (0x14 * queue), rd_point);
+
+	return IRQ_HANDLED;
 }
 
 static irqreturn_t cq_interrupt_v2_hw(int irq_no, void *p)
@@ -3184,9 +3191,7 @@
 
 	hisi_sas_write32(hisi_hba, OQ_INT_SRC, 1 << queue);
 
-	tasklet_schedule(&cq->tasklet);
-
-	return IRQ_HANDLED;
+	return IRQ_WAKE_THREAD;
 }
 
 static irqreturn_t sata_int_v2_hw(int irq_no, void *p)
@@ -3353,18 +3358,18 @@
 
 	for (queue_no = 0; queue_no < hisi_hba->queue_count; queue_no++) {
 		struct hisi_sas_cq *cq = &hisi_hba->cq[queue_no];
-		struct tasklet_struct *t = &cq->tasklet;
 
-		irq = irq_map[queue_no + 96];
-		rc = devm_request_irq(dev, irq, cq_interrupt_v2_hw, 0,
-				      DRV_NAME " cq", cq);
+		cq->irq_no = irq_map[queue_no + 96];
+		rc = devm_request_threaded_irq(dev, cq->irq_no,
+					       cq_interrupt_v2_hw,
+					       cq_thread_v2_hw, IRQF_ONESHOT,
+					       DRV_NAME " cq", cq);
 		if (rc) {
 			dev_err(dev, "irq init: could not request cq interrupt %d, rc=%d\n",
 				irq, rc);
 			rc = -ENOENT;
 			goto err_out;
 		}
-		tasklet_init(t, cq_tasklet_v2_hw, (unsigned long)cq);
 	}
 
 	hisi_hba->cq_nvecs = hisi_hba->queue_count;
@@ -3425,7 +3430,6 @@
 
 	interrupt_disable_v2_hw(hisi_hba);
 	hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, 0x0);
-	hisi_sas_kill_tasklets(hisi_hba);
 
 	hisi_sas_stop_phys(hisi_hba);
 
@@ -3542,6 +3546,7 @@
 	.max_sectors		= SCSI_DEFAULT_MAX_SECTORS,
 	.eh_device_reset_handler = sas_eh_device_reset_handler,
 	.eh_target_reset_handler = sas_eh_target_reset_handler,
+	.slave_alloc		= sas_slave_alloc,
 	.target_destroy		= sas_target_destroy,
 	.ioctl			= sas_ioctl,
 	.shost_attrs		= host_attrs_v2_hw,
@@ -3596,11 +3601,6 @@
 
 static int hisi_sas_v2_remove(struct platform_device *pdev)
 {
-	struct sas_ha_struct *sha = platform_get_drvdata(pdev);
-	struct hisi_hba *hisi_hba = sha->lldd_ha;
-
-	hisi_sas_kill_tasklets(hisi_hba);
-
 	return hisi_sas_remove(pdev);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -495,6 +495,13 @@
 #define BASE_VECTORS_V3_HW  16
 #define MIN_AFFINE_VECTORS_V3_HW  (BASE_VECTORS_V3_HW + 1)
 
+#define CHNL_INT_STS_MSK	0xeeeeeeee
+#define CHNL_INT_STS_PHY_MSK	0xe
+#define CHNL_INT_STS_INT0_MSK BIT(1)
+#define CHNL_INT_STS_INT1_MSK BIT(2)
+#define CHNL_INT_STS_INT2_MSK BIT(3)
+#define CHNL_WIDTH 4
+
 enum {
 	DSM_FUNC_ERR_HANDLE_MSI = 0,
 };
@@ -504,7 +511,7 @@
 
 /* permit overriding the host protection capabilities mask (EEDP/T10 PI) */
 static int prot_mask;
-module_param(prot_mask, int, 0);
+module_param(prot_mask, int, 0444);
 MODULE_PARM_DESC(prot_mask, " host protection capabilities mask, def=0x0 ");
 
 static bool auto_affine_msi_experimental;
@@ -795,13 +802,14 @@
 					(0x1ULL << ITCT_HDR_RTOLT_OFF));
 }
 
-static void clear_itct_v3_hw(struct hisi_hba *hisi_hba,
-			      struct hisi_sas_device *sas_dev)
+static int clear_itct_v3_hw(struct hisi_hba *hisi_hba,
+			    struct hisi_sas_device *sas_dev)
 {
 	DECLARE_COMPLETION_ONSTACK(completion);
 	u64 dev_id = sas_dev->device_id;
 	struct hisi_sas_itct *itct = &hisi_hba->itct[dev_id];
 	u32 reg_val = hisi_sas_read32(hisi_hba, ENT_INT_SRC3);
+	struct device *dev = hisi_hba->dev;
 
 	sas_dev->completion = &completion;
 
@@ -814,8 +822,14 @@
 	reg_val = ITCT_CLR_EN_MSK | (dev_id & ITCT_DEV_MSK);
 	hisi_sas_write32(hisi_hba, ITCT_CLR, reg_val);
 
-	wait_for_completion(sas_dev->completion);
+	if (!wait_for_completion_timeout(sas_dev->completion,
+					 CLEAR_ITCT_TIMEOUT * HZ)) {
+		dev_warn(dev, "failed to clear ITCT\n");
+		return -ETIMEDOUT;
+	}
+
 	memset(itct, 0, sizeof(struct hisi_sas_itct));
+	return 0;
 }
 
 static void dereg_device_v3_hw(struct hisi_hba *hisi_hba,
@@ -1542,6 +1556,8 @@
 	u32 phy_state, sl_ctrl, txid_auto;
 	struct device *dev = hisi_hba->dev;
 
+	atomic_inc(&phy->down_cnt);
+
 	del_timer(&phy->timer);
 	hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_NOT_RDY_MSK, 1);
 
@@ -1810,19 +1826,19 @@
 	int phy_no = 0;
 
 	irq_msk = hisi_sas_read32(hisi_hba, CHNL_INT_STATUS)
-				& 0xeeeeeeee;
+		  & CHNL_INT_STS_MSK;
 
 	while (irq_msk) {
-		if (irq_msk & (2 << (phy_no * 4)))
+		if (irq_msk & (CHNL_INT_STS_INT0_MSK << (phy_no * CHNL_WIDTH)))
 			handle_chl_int0_v3_hw(hisi_hba, phy_no);
 
-		if (irq_msk & (4 << (phy_no * 4)))
+		if (irq_msk & (CHNL_INT_STS_INT1_MSK << (phy_no * CHNL_WIDTH)))
 			handle_chl_int1_v3_hw(hisi_hba, phy_no);
 
-		if (irq_msk & (8 << (phy_no * 4)))
+		if (irq_msk & (CHNL_INT_STS_INT2_MSK << (phy_no * CHNL_WIDTH)))
 			handle_chl_int2_v3_hw(hisi_hba, phy_no);
 
-		irq_msk &= ~(0xe << (phy_no * 4));
+		irq_msk &= ~(CHNL_INT_STS_PHY_MSK << (phy_no * CHNL_WIDTH));
 		phy_no++;
 	}
 
@@ -2290,9 +2306,9 @@
 	return sts;
 }
 
-static void cq_tasklet_v3_hw(unsigned long val)
+static irqreturn_t  cq_thread_v3_hw(int irq_no, void *p)
 {
-	struct hisi_sas_cq *cq = (struct hisi_sas_cq *)val;
+	struct hisi_sas_cq *cq = p;
 	struct hisi_hba *hisi_hba = cq->hisi_hba;
 	struct hisi_sas_slot *slot;
 	struct hisi_sas_complete_v3_hdr *complete_queue;
@@ -2329,6 +2345,8 @@
 	/* update rd_point */
 	cq->rd_point = rd_point;
 	hisi_sas_write32(hisi_hba, COMPL_Q_0_RD_PTR + (0x14 * queue), rd_point);
+
+	return IRQ_HANDLED;
 }
 
 static irqreturn_t cq_interrupt_v3_hw(int irq_no, void *p)
@@ -2339,9 +2357,7 @@
 
 	hisi_sas_write32(hisi_hba, OQ_INT_SRC, 1 << queue);
 
-	tasklet_schedule(&cq->tasklet);
-
-	return IRQ_HANDLED;
+	return IRQ_WAKE_THREAD;
 }
 
 static void setup_reply_map_v3_hw(struct hisi_hba *hisi_hba, int nvecs)
@@ -2356,7 +2372,7 @@
 					    BASE_VECTORS_V3_HW);
 		if (!mask)
 			goto fallback;
-		cq->pci_irq_mask = mask;
+		cq->irq_mask = mask;
 		for_each_cpu(cpu, mask)
 			hisi_hba->reply_map[cpu] = queue;
 	}
@@ -2380,6 +2396,8 @@
 			.pre_vectors = BASE_VECTORS_V3_HW,
 		};
 
+		dev_info(dev, "Enable MSI auto-affinity\n");
+
 		min_msi = MIN_AFFINE_VECTORS_V3_HW;
 
 		hisi_hba->reply_map = devm_kcalloc(dev, nr_cpu_ids,
@@ -2432,15 +2450,20 @@
 		goto free_irq_vectors;
 	}
 
-	/* Init tasklets for cq only */
+	if (hisi_sas_intr_conv)
+		dev_info(dev, "Enable interrupt converge\n");
+
 	for (i = 0; i < hisi_hba->cq_nvecs; i++) {
 		struct hisi_sas_cq *cq = &hisi_hba->cq[i];
-		struct tasklet_struct *t = &cq->tasklet;
 		int nr = hisi_sas_intr_conv ? 16 : 16 + i;
-		unsigned long irqflags = hisi_sas_intr_conv ? IRQF_SHARED : 0;
+		unsigned long irqflags = hisi_sas_intr_conv ? IRQF_SHARED :
+							      IRQF_ONESHOT;
 
-		rc = devm_request_irq(dev, pci_irq_vector(pdev, nr),
-				      cq_interrupt_v3_hw, irqflags,
+		cq->irq_no = pci_irq_vector(pdev, nr);
+		rc = devm_request_threaded_irq(dev, cq->irq_no,
+				      cq_interrupt_v3_hw,
+				      cq_thread_v3_hw,
+				      irqflags,
 				      DRV_NAME " cq", cq);
 		if (rc) {
 			dev_err(dev, "could not request cq%d interrupt, rc=%d\n",
@@ -2448,8 +2471,6 @@
 			rc = -ENOENT;
 			goto free_irq_vectors;
 		}
-
-		tasklet_init(t, cq_tasklet_v3_hw, (unsigned long)cq);
 	}
 
 	return 0;
@@ -2525,7 +2546,6 @@
 
 	interrupt_disable_v3_hw(hisi_hba);
 	hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, 0x0);
-	hisi_sas_kill_tasklets(hisi_hba);
 
 	hisi_sas_stop_phys(hisi_hba);
 
@@ -2901,7 +2921,7 @@
 
 	wait_cmds_complete_timeout_v3_hw(hisi_hba, 100, 5000);
 
-	hisi_sas_kill_tasklets(hisi_hba);
+	hisi_sas_sync_irqs(hisi_hba);
 }
 
 static void debugfs_snapshot_restore_v3_hw(struct hisi_hba *hisi_hba)
@@ -3022,11 +3042,6 @@
 		hisi_sas_phy_write32(hisi_hba, phy_id,
 				     SAS_PHY_BIST_CTRL, reg_val);
 
-		mdelay(100);
-		reg_val |= (CFG_RX_BIST_EN_MSK | CFG_TX_BIST_EN_MSK);
-		hisi_sas_phy_write32(hisi_hba, phy_id,
-				     SAS_PHY_BIST_CTRL, reg_val);
-
 		/* set the bist init value */
 		hisi_sas_phy_write32(hisi_hba, phy_id,
 				     SAS_PHY_BIST_CODE,
@@ -3035,6 +3050,11 @@
 				     SAS_PHY_BIST_CODE1,
 				     SAS_PHY_BIST_CODE1_INIT);
 
+		mdelay(100);
+		reg_val |= (CFG_RX_BIST_EN_MSK | CFG_TX_BIST_EN_MSK);
+		hisi_sas_phy_write32(hisi_hba, phy_id,
+				     SAS_PHY_BIST_CTRL, reg_val);
+
 		/* clear error bit */
 		mdelay(100);
 		hisi_sas_phy_read32(hisi_hba, phy_id, SAS_BIST_ERR_CNT);
@@ -3064,6 +3084,7 @@
 	.max_sectors		= SCSI_DEFAULT_MAX_SECTORS,
 	.eh_device_reset_handler = sas_eh_device_reset_handler,
 	.eh_target_reset_handler = sas_eh_target_reset_handler,
+	.slave_alloc		= sas_slave_alloc,
 	.target_destroy		= sas_target_destroy,
 	.ioctl			= sas_ioctl,
 	.shost_attrs		= host_attrs_v3_hw,
@@ -3259,6 +3280,7 @@
 err_out_register_ha:
 	scsi_remove_host(shost);
 err_out_ha:
+	hisi_sas_debugfs_exit(hisi_hba);
 	scsi_host_put(shost);
 err_out_regions:
 	pci_release_regions(pdev);
@@ -3273,14 +3295,14 @@
 {
 	int i;
 
-	free_irq(pci_irq_vector(pdev, 1), hisi_hba);
-	free_irq(pci_irq_vector(pdev, 2), hisi_hba);
-	free_irq(pci_irq_vector(pdev, 11), hisi_hba);
+	devm_free_irq(&pdev->dev, pci_irq_vector(pdev, 1), hisi_hba);
+	devm_free_irq(&pdev->dev, pci_irq_vector(pdev, 2), hisi_hba);
+	devm_free_irq(&pdev->dev, pci_irq_vector(pdev, 11), hisi_hba);
 	for (i = 0; i < hisi_hba->cq_nvecs; i++) {
 		struct hisi_sas_cq *cq = &hisi_hba->cq[i];
 		int nr = hisi_sas_intr_conv ? 16 : 16 + i;
 
-		free_irq(pci_irq_vector(pdev, nr), cq);
+		devm_free_irq(&pdev->dev, pci_irq_vector(pdev, nr), cq);
 	}
 	pci_free_irq_vectors(pdev);
 }
@@ -3292,8 +3314,6 @@
 	struct hisi_hba *hisi_hba = sha->lldd_ha;
 	struct Scsi_Host *shost = sha->core.shost;
 
-	hisi_sas_debugfs_exit(hisi_hba);
-
 	if (timer_pending(&hisi_hba->timer))
 		del_timer(&hisi_hba->timer);
 
@@ -3301,10 +3321,10 @@
 	sas_remove_host(sha->core.shost);
 
 	hisi_sas_v3_destroy_irqs(pdev, hisi_hba);
-	hisi_sas_kill_tasklets(hisi_hba);
 	pci_release_regions(pdev);
 	pci_disable_device(pdev);
 	hisi_sas_free(hisi_hba);
+	hisi_sas_debugfs_exit(hisi_hba);
 	scsi_host_put(shost);
 }
 
@@ -3363,7 +3383,7 @@
 	}
 
 	if (test_and_set_bit(HISI_SAS_RESET_BIT, &hisi_hba->flags))
-		return -1;
+		return -EPERM;
 
 	scsi_block_requests(shost);
 	set_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags);
@@ -3422,6 +3442,7 @@
 	if (rc) {
 		scsi_remove_host(shost);
 		pci_disable_device(pdev);
+		return rc;
 	}
 	hisi_hba->hw->phys_init(hisi_hba);
 	sas_resume_ha(sha);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/hosts.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/hosts.c
@@ -179,6 +179,7 @@
 	scsi_forget_host(shost);
 	mutex_unlock(&shost->scan_mutex);
 	scsi_proc_host_rm(shost);
+	scsi_proc_hostdir_rm(shost->hostt);
 
 	spin_lock_irqsave(shost->host_lock, flags);
 	if (scsi_host_set_state(shost, SHOST_DEL))
@@ -219,6 +220,10 @@
 		goto fail;
 	}
 
+	/* Use min_t(int, ...) in case shost->can_queue exceeds SHRT_MAX */
+	shost->cmd_per_lun = min_t(int, shost->cmd_per_lun,
+				   shost->can_queue);
+
 	error = scsi_init_sense_cache(shost);
 	if (error)
 		goto fail;
@@ -253,12 +258,11 @@
 
 	device_enable_async_suspend(&shost->shost_dev);
 
+	get_device(&shost->shost_gendev);
 	error = device_add(&shost->shost_dev);
 	if (error)
 		goto out_del_gendev;
 
-	get_device(&shost->shost_gendev);
-
 	if (shost->transportt->host_size) {
 		shost->shost_data = kzalloc(shost->transportt->host_size,
 					 GFP_KERNEL);
@@ -275,33 +279,36 @@
 					shost->work_q_name);
 		if (!shost->work_q) {
 			error = -EINVAL;
-			goto out_free_shost_data;
+			goto out_del_dev;
 		}
 	}
 
 	error = scsi_sysfs_add_host(shost);
 	if (error)
-		goto out_destroy_host;
+		goto out_del_dev;
 
 	scsi_proc_host_add(shost);
 	scsi_autopm_put_host(shost);
 	return error;
 
- out_destroy_host:
-	if (shost->work_q)
-		destroy_workqueue(shost->work_q);
- out_free_shost_data:
-	kfree(shost->shost_data);
+	/*
+	 * Any host allocation in this function will be freed in
+	 * scsi_host_dev_release().
+	 */
  out_del_dev:
 	device_del(&shost->shost_dev);
  out_del_gendev:
+	/*
+	 * Host state is SHOST_RUNNING so we have to explicitly release
+	 * ->shost_dev.
+	 */
+	put_device(&shost->shost_dev);
 	device_del(&shost->shost_gendev);
  out_disable_runtime_pm:
 	device_disable_async_suspend(&shost->shost_gendev);
 	pm_runtime_disable(&shost->shost_gendev);
 	pm_runtime_set_suspended(&shost->shost_gendev);
 	pm_runtime_put_noidle(&shost->shost_gendev);
-	scsi_mq_destroy_tags(shost);
  fail:
 	return error;
 }
@@ -312,9 +319,7 @@
 	struct Scsi_Host *shost = dev_to_shost(dev);
 	struct device *parent = dev->parent;
 
-	scsi_proc_hostdir_rm(shost->hostt);
-
-	/* Wait for functions invoked through call_rcu(&shost->rcu, ...) */
+	/* Wait for functions invoked through call_rcu(&scmd->rcu, ...) */
 	rcu_barrier();
 
 	if (shost->tmf_work_q)
@@ -326,12 +331,13 @@
 
 	if (shost->shost_state == SHOST_CREATED) {
 		/*
-		 * Free the shost_dev device name here if scsi_host_alloc()
-		 * and scsi_host_put() have been called but neither
+		 * Free the shost_dev device name and remove the proc host dir
+		 * here if scsi_host_{alloc,put}() have been called but neither
 		 * scsi_host_add() nor scsi_host_remove() has been called.
 		 * This avoids that the memory allocated for the shost_dev
-		 * name is leaked.
+		 * name as well as the proc dir structure are leaked.
 		 */
+		scsi_proc_hostdir_rm(shost->hostt);
 		kfree(dev_name(&shost->shost_dev));
 	}
 
@@ -342,7 +348,7 @@
 
 	ida_simple_remove(&host_index_ida, shost->host_no);
 
-	if (parent)
+	if (shost->shost_state != SHOST_CREATED)
 		put_device(parent);
 	kfree(shost);
 }
@@ -389,8 +395,10 @@
 	mutex_init(&shost->scan_mutex);
 
 	index = ida_simple_get(&host_index_ida, 0, 0, GFP_KERNEL);
-	if (index < 0)
-		goto fail_kfree;
+	if (index < 0) {
+		kfree(shost);
+		return NULL;
+	}
 	shost->host_no = index;
 
 	shost->dma_channel = 0xff;
@@ -482,7 +490,8 @@
 		shost_printk(KERN_WARNING, shost,
 			"error handler thread failed to spawn, error = %ld\n",
 			PTR_ERR(shost->ehandler));
-		goto fail_index_remove;
+		shost->ehandler = NULL;
+		goto fail;
 	}
 
 	shost->tmf_work_q = alloc_workqueue("scsi_tmf_%d",
@@ -491,17 +500,18 @@
 	if (!shost->tmf_work_q) {
 		shost_printk(KERN_WARNING, shost,
 			     "failed to create tmf workq\n");
-		goto fail_kthread;
+		goto fail;
 	}
 	scsi_proc_hostdir_add(shost->hostt);
 	return shost;
+ fail:
+	/*
+	 * Host state is still SHOST_CREATED and that is enough to release
+	 * ->shost_gendev. scsi_host_dev_release() will free
+	 * dev_name(&shost->shost_dev).
+	 */
+	put_device(&shost->shost_gendev);
 
- fail_kthread:
-	kthread_stop(shost->ehandler);
- fail_index_remove:
-	ida_simple_remove(&host_index_ida, shost->host_no);
- fail_kfree:
-	kfree(shost);
 	return NULL;
 }
 EXPORT_SYMBOL(scsi_host_alloc);
@@ -509,7 +519,7 @@
 static int __scsi_host_match(struct device *dev, const void *data)
 {
 	struct Scsi_Host *p;
-	const unsigned short *hostnum = data;
+	const unsigned int *hostnum = data;
 
 	p = class_to_shost(dev);
 	return p->host_no == *hostnum;
@@ -526,7 +536,7 @@
  *	that scsi_host_get() took. The put_device() below dropped
  *	the reference from class_find_device().
  **/
-struct Scsi_Host *scsi_host_lookup(unsigned short hostnum)
+struct Scsi_Host *scsi_host_lookup(unsigned int hostnum)
 {
 	struct device *cdev;
 	struct Scsi_Host *shost = NULL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/hpsa.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/hpsa.c
@@ -504,6 +504,12 @@
 	return count;
 }
 
+static void hpsa_turn_off_ioaccel_for_device(struct hpsa_scsi_dev_t *device)
+{
+	device->offload_enabled = 0;
+	device->offload_to_be_enabled = 0;
+}
+
 static ssize_t host_show_firmware_revision(struct device *dev,
 	     struct device_attribute *attr, char *buf)
 {
@@ -1738,8 +1744,7 @@
 				__func__,
 				h->scsi_host->host_no, logical_drive->bus,
 				logical_drive->target, logical_drive->lun);
-			logical_drive->offload_enabled = 0;
-			logical_drive->offload_to_be_enabled = 0;
+			hpsa_turn_off_ioaccel_for_device(logical_drive);
 			logical_drive->queue_depth = 8;
 		}
 	}
@@ -2499,8 +2504,7 @@
 			IOACCEL2_SERV_RESPONSE_FAILURE) {
 		if (c2->error_data.status ==
 			IOACCEL2_STATUS_SR_IOACCEL_DISABLED) {
-			dev->offload_enabled = 0;
-			dev->offload_to_be_enabled = 0;
+			hpsa_turn_off_ioaccel_for_device(dev);
 		}
 
 		if (dev->in_reset) {
@@ -3670,10 +3674,17 @@
 	this_device->offload_config =
 		!!(ioaccel_status & OFFLOAD_CONFIGURED_BIT);
 	if (this_device->offload_config) {
-		this_device->offload_to_be_enabled =
+		bool offload_enabled =
 			!!(ioaccel_status & OFFLOAD_ENABLED_BIT);
-		if (hpsa_get_raid_map(h, scsi3addr, this_device))
-			this_device->offload_to_be_enabled = 0;
+		/*
+		 * Check to see if offload can be enabled.
+		 */
+		if (offload_enabled) {
+			rc = hpsa_get_raid_map(h, scsi3addr, this_device);
+			if (rc) /* could not load raid_map */
+				goto out;
+			this_device->offload_to_be_enabled = 1;
+		}
 	}
 
 out:
@@ -3996,8 +4007,7 @@
 	} else {
 		this_device->raid_level = RAID_UNKNOWN;
 		this_device->offload_config = 0;
-		this_device->offload_enabled = 0;
-		this_device->offload_to_be_enabled = 0;
+		hpsa_turn_off_ioaccel_for_device(this_device);
 		this_device->hba_ioaccel_enabled = 0;
 		this_device->volume_offline = 0;
 		this_device->queue_depth = h->nr_cmds;
@@ -5230,8 +5240,12 @@
 		/* Handles load balance across RAID 1 members.
 		 * (2-drive R1 and R10 with even # of drives.)
 		 * Appropriate for SSDs, not optimal for HDDs
+		 * Ensure we have the correct raid_map.
 		 */
-		BUG_ON(le16_to_cpu(map->layout_map_count) != 2);
+		if (le16_to_cpu(map->layout_map_count) != 2) {
+			hpsa_turn_off_ioaccel_for_device(dev);
+			return IO_ACCEL_INELIGIBLE;
+		}
 		if (dev->offload_to_mirror)
 			map_index += le16_to_cpu(map->data_disks_per_row);
 		dev->offload_to_mirror = !dev->offload_to_mirror;
@@ -5239,8 +5253,12 @@
 	case HPSA_RAID_ADM:
 		/* Handles N-way mirrors  (R1-ADM)
 		 * and R10 with # of drives divisible by 3.)
+		 * Ensure we have the correct raid_map.
 		 */
-		BUG_ON(le16_to_cpu(map->layout_map_count) != 3);
+		if (le16_to_cpu(map->layout_map_count) != 3) {
+			hpsa_turn_off_ioaccel_for_device(dev);
+			return IO_ACCEL_INELIGIBLE;
+		}
 
 		offload_to_mirror = dev->offload_to_mirror;
 		raid_map_helper(map, offload_to_mirror,
@@ -5265,7 +5283,10 @@
 		r5or6_blocks_per_row =
 			le16_to_cpu(map->strip_size) *
 			le16_to_cpu(map->data_disks_per_row);
-		BUG_ON(r5or6_blocks_per_row == 0);
+		if (r5or6_blocks_per_row == 0) {
+			hpsa_turn_off_ioaccel_for_device(dev);
+			return IO_ACCEL_INELIGIBLE;
+		}
 		stripesize = r5or6_blocks_per_row *
 			le16_to_cpu(map->layout_map_count);
 #if BITS_PER_LONG == 32
@@ -5789,7 +5810,7 @@
 {
 	struct Scsi_Host *sh;
 
-	sh = scsi_host_alloc(&hpsa_driver_template, sizeof(h));
+	sh = scsi_host_alloc(&hpsa_driver_template, sizeof(struct ctlr_info *));
 	if (sh == NULL) {
 		dev_err(&h->pdev->dev, "scsi_host_alloc failed\n");
 		return -ENOMEM;
@@ -8285,7 +8306,7 @@
  *
  * Called from monitor controller worker (hpsa_event_monitor_worker)
  *
- * A Volume (or Volumes that comprise an Array set may be undergoing a
+ * A Volume (or Volumes that comprise an Array set) may be undergoing a
  * transformation, so we will be turning off ioaccel for all volumes that
  * make up the Array.
  */
@@ -8308,6 +8329,9 @@
 	 * Run through current device list used during I/O requests.
 	 */
 	for (i = 0; i < h->ndevices; i++) {
+		int offload_to_be_enabled = 0;
+		int offload_config = 0;
+
 		device = h->dev[i];
 
 		if (!device)
@@ -8325,25 +8349,35 @@
 			continue;
 
 		ioaccel_status = buf[IOACCEL_STATUS_BYTE];
-		device->offload_config =
+
+		/*
+		 * Check if offload is still configured on
+		 */
+		offload_config =
 				!!(ioaccel_status & OFFLOAD_CONFIGURED_BIT);
-		if (device->offload_config)
-			device->offload_to_be_enabled =
+		/*
+		 * If offload is configured on, check to see if ioaccel
+		 * needs to be enabled.
+		 */
+		if (offload_config)
+			offload_to_be_enabled =
 				!!(ioaccel_status & OFFLOAD_ENABLED_BIT);
 
 		/*
+		 * If ioaccel is to be re-enabled, re-enable later during the
+		 * scan operation so the driver can get a fresh raidmap
+		 * before turning ioaccel back on.
+		 */
+		if (offload_to_be_enabled)
+			continue;
+
+		/*
 		 * Immediately turn off ioaccel for any volume the
 		 * controller tells us to. Some of the reasons could be:
 		 *    transformation - change to the LVs of an Array.
 		 *    degraded volume - component failure
-		 *
-		 * If ioaccel is to be re-enabled, re-enable later during the
-		 * scan operation so the driver can get a fresh raidmap
-		 * before turning ioaccel back on.
-		 *
 		 */
-		if (!device->offload_to_be_enabled)
-			device->offload_enabled = 0;
+		hpsa_turn_off_ioaccel_for_device(device);
 	}
 
 	kfree(buf);
@@ -8820,7 +8854,7 @@
 	/* hook into SCSI subsystem */
 	rc = hpsa_scsi_add_host(h);
 	if (rc)
-		goto clean7; /* perf, sg, cmd, irq, shost, pci, lu, aer/h */
+		goto clean8; /* lastlogicals, perf, sg, cmd, irq, shost, pci, lu, aer/h */
 
 	/* Monitor the controller for firmware lockups */
 	h->heartbeat_sample_interval = HEARTBEAT_SAMPLE_INTERVAL;
@@ -8835,6 +8869,8 @@
 				HPSA_EVENT_MONITOR_INTERVAL);
 	return 0;
 
+clean8: /* lastlogicals, perf, sg, cmd, irq, shost, pci, lu, aer/h */
+	kfree(h->lastlogicals);
 clean7: /* perf, sg, cmd, irq, shost, pci, lu, aer/h */
 	hpsa_free_performant_mode(h);
 	h->access.set_intr_mask(h, HPSA_INTR_OFF);
@@ -8867,7 +8903,7 @@
 		destroy_workqueue(h->monitor_ctlr_wq);
 		h->monitor_ctlr_wq = NULL;
 	}
-	kfree(h);
+	hpda_free_ctlr_info(h);
 	return rc;
 }
 
@@ -9727,7 +9763,8 @@
 	return 0;
 
 free_sas_phy:
-	hpsa_free_sas_phy(hpsa_sas_phy);
+	sas_phy_free(hpsa_sas_phy->phy);
+	kfree(hpsa_sas_phy);
 free_sas_port:
 	hpsa_free_sas_port(hpsa_sas_port);
 free_sas_node:
@@ -9763,10 +9800,12 @@
 
 	rc = hpsa_sas_port_add_rphy(hpsa_sas_port, rphy);
 	if (rc)
-		goto free_sas_port;
+		goto free_sas_rphy;
 
 	return 0;
 
+free_sas_rphy:
+	sas_rphy_free(rphy);
 free_sas_port:
 	hpsa_free_sas_port(hpsa_sas_port);
 	device->sas_port = NULL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/ibmvscsi/ibmvfc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -493,8 +493,17 @@
 		if (vhost->action == IBMVFC_HOST_ACTION_ALLOC_TGTS)
 			vhost->action = action;
 		break;
+	case IBMVFC_HOST_ACTION_REENABLE:
+	case IBMVFC_HOST_ACTION_RESET:
+		vhost->action = action;
+		break;
 	case IBMVFC_HOST_ACTION_INIT:
 	case IBMVFC_HOST_ACTION_TGT_DEL:
+	case IBMVFC_HOST_ACTION_LOGO:
+	case IBMVFC_HOST_ACTION_QUERY_TGTS:
+	case IBMVFC_HOST_ACTION_TGT_DEL_FAILED:
+	case IBMVFC_HOST_ACTION_NONE:
+	default:
 		switch (vhost->action) {
 		case IBMVFC_HOST_ACTION_RESET:
 		case IBMVFC_HOST_ACTION_REENABLE:
@@ -504,15 +513,6 @@
 			break;
 		}
 		break;
-	case IBMVFC_HOST_ACTION_LOGO:
-	case IBMVFC_HOST_ACTION_QUERY_TGTS:
-	case IBMVFC_HOST_ACTION_TGT_DEL_FAILED:
-	case IBMVFC_HOST_ACTION_NONE:
-	case IBMVFC_HOST_ACTION_RESET:
-	case IBMVFC_HOST_ACTION_REENABLE:
-	default:
-		vhost->action = action;
-		break;
 	}
 }
 
@@ -2881,8 +2881,10 @@
 	unsigned long flags = 0;
 
 	spin_lock_irqsave(shost->host_lock, flags);
-	if (sdev->type == TYPE_DISK)
+	if (sdev->type == TYPE_DISK) {
 		sdev->allow_restart = 1;
+		blk_queue_rq_timeout(sdev->request_queue, 120 * HZ);
+	}
 	spin_unlock_irqrestore(shost->host_lock, flags);
 	return 0;
 }
@@ -4337,26 +4339,45 @@
 	case IBMVFC_HOST_ACTION_INIT_WAIT:
 		break;
 	case IBMVFC_HOST_ACTION_RESET:
-		vhost->action = IBMVFC_HOST_ACTION_TGT_DEL;
 		spin_unlock_irqrestore(vhost->host->host_lock, flags);
 		rc = ibmvfc_reset_crq(vhost);
+
 		spin_lock_irqsave(vhost->host->host_lock, flags);
-		if (rc == H_CLOSED)
+		if (!rc || rc == H_CLOSED)
 			vio_enable_interrupts(to_vio_dev(vhost->dev));
-		if (rc || (rc = ibmvfc_send_crq_init(vhost)) ||
-		    (rc = vio_enable_interrupts(to_vio_dev(vhost->dev)))) {
-			ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD);
-			dev_err(vhost->dev, "Error after reset (rc=%d)\n", rc);
+		if (vhost->action == IBMVFC_HOST_ACTION_RESET) {
+			/*
+			 * The only action we could have changed to would have
+			 * been reenable, in which case, we skip the rest of
+			 * this path and wait until we've done the re-enable
+			 * before sending the crq init.
+			 */
+			vhost->action = IBMVFC_HOST_ACTION_TGT_DEL;
+
+			if (rc || (rc = ibmvfc_send_crq_init(vhost)) ||
+			    (rc = vio_enable_interrupts(to_vio_dev(vhost->dev)))) {
+				ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD);
+				dev_err(vhost->dev, "Error after reset (rc=%d)\n", rc);
+			}
 		}
 		break;
 	case IBMVFC_HOST_ACTION_REENABLE:
-		vhost->action = IBMVFC_HOST_ACTION_TGT_DEL;
 		spin_unlock_irqrestore(vhost->host->host_lock, flags);
 		rc = ibmvfc_reenable_crq_queue(vhost);
+
 		spin_lock_irqsave(vhost->host->host_lock, flags);
-		if (rc || (rc = ibmvfc_send_crq_init(vhost))) {
-			ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD);
-			dev_err(vhost->dev, "Error after enable (rc=%d)\n", rc);
+		if (vhost->action == IBMVFC_HOST_ACTION_REENABLE) {
+			/*
+			 * The only action we could have changed to would have
+			 * been reset, in which case, we skip the rest of this
+			 * path and wait until we've done the reset before
+			 * sending the crq init.
+			 */
+			vhost->action = IBMVFC_HOST_ACTION_TGT_DEL;
+			if (rc || (rc = ibmvfc_send_crq_init(vhost))) {
+				ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD);
+				dev_err(vhost->dev, "Error after enable (rc=%d)\n", rc);
+			}
 		}
 		break;
 	case IBMVFC_HOST_ACTION_LOGO:
@@ -4788,6 +4809,7 @@
 	if (IS_ERR(vhost->work_thread)) {
 		dev_err(dev, "Couldn't create kernel thread: %ld\n",
 			PTR_ERR(vhost->work_thread));
+		rc = PTR_ERR(vhost->work_thread);
 		goto free_host_mem;
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -415,6 +415,8 @@
 	int rc = 0;
 	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
 
+	set_adapter_info(hostdata);
+
 	/* Re-enable the CRQ */
 	do {
 		if (rc)
@@ -805,13 +807,29 @@
 }
 
 /**
+ * ibmvscsi_set_request_limit - Set the adapter request_limit in response to
+ * an adapter failure, reset, or SRP Login. Done under host lock to prevent
+ * race with SCSI command submission.
+ * @hostdata:	adapter to adjust
+ * @limit:	new request limit
+ */
+static void ibmvscsi_set_request_limit(struct ibmvscsi_host_data *hostdata, int limit)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(hostdata->host->host_lock, flags);
+	atomic_set(&hostdata->request_limit, limit);
+	spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+}
+
+/**
  * ibmvscsi_reset_host - Reset the connection to the server
  * @hostdata:	struct ibmvscsi_host_data to reset
 */
 static void ibmvscsi_reset_host(struct ibmvscsi_host_data *hostdata)
 {
 	scsi_block_requests(hostdata->host);
-	atomic_set(&hostdata->request_limit, 0);
+	ibmvscsi_set_request_limit(hostdata, 0);
 
 	purge_requests(hostdata, DID_ERROR);
 	hostdata->action = IBMVSCSI_HOST_ACTION_RESET;
@@ -1144,13 +1162,13 @@
 		dev_info(hostdata->dev, "SRP_LOGIN_REJ reason %u\n",
 			 evt_struct->xfer_iu->srp.login_rej.reason);
 		/* Login failed.  */
-		atomic_set(&hostdata->request_limit, -1);
+		ibmvscsi_set_request_limit(hostdata, -1);
 		return;
 	default:
 		dev_err(hostdata->dev, "Invalid login response typecode 0x%02x!\n",
 			evt_struct->xfer_iu->srp.login_rsp.opcode);
 		/* Login failed.  */
-		atomic_set(&hostdata->request_limit, -1);
+		ibmvscsi_set_request_limit(hostdata, -1);
 		return;
 	}
 
@@ -1161,7 +1179,7 @@
 	 * This value is set rather than added to request_limit because
 	 * request_limit could have been set to -1 by this client.
 	 */
-	atomic_set(&hostdata->request_limit,
+	ibmvscsi_set_request_limit(hostdata,
 		   be32_to_cpu(evt_struct->xfer_iu->srp.login_rsp.req_lim_delta));
 
 	/* If we had any pending I/Os, kick them */
@@ -1193,13 +1211,13 @@
 	login->req_buf_fmt = cpu_to_be16(SRP_BUF_FORMAT_DIRECT |
 					 SRP_BUF_FORMAT_INDIRECT);
 
-	spin_lock_irqsave(hostdata->host->host_lock, flags);
 	/* Start out with a request limit of 0, since this is negotiated in
 	 * the login request we are just sending and login requests always
 	 * get sent by the driver regardless of request_limit.
 	 */
-	atomic_set(&hostdata->request_limit, 0);
+	ibmvscsi_set_request_limit(hostdata, 0);
 
+	spin_lock_irqsave(hostdata->host->host_lock, flags);
 	rc = ibmvscsi_send_srp_event(evt_struct, hostdata, login_timeout * 2);
 	spin_unlock_irqrestore(hostdata->host->host_lock, flags);
 	dev_info(hostdata->dev, "sent SRP login\n");
@@ -1779,7 +1797,7 @@
 		return;
 	case VIOSRP_CRQ_XPORT_EVENT:	/* Hypervisor telling us the connection is closed */
 		scsi_block_requests(hostdata->host);
-		atomic_set(&hostdata->request_limit, 0);
+		ibmvscsi_set_request_limit(hostdata, 0);
 		if (crq->format == 0x06) {
 			/* We need to re-setup the interpartition connection */
 			dev_info(hostdata->dev, "Re-enabling adapter!\n");
@@ -2135,12 +2153,12 @@
 	}
 
 	hostdata->action = IBMVSCSI_HOST_ACTION_NONE;
+	spin_unlock_irqrestore(hostdata->host->host_lock, flags);
 
 	if (rc) {
-		atomic_set(&hostdata->request_limit, -1);
+		ibmvscsi_set_request_limit(hostdata, -1);
 		dev_err(hostdata->dev, "error after %s\n", action);
 	}
-	spin_unlock_irqrestore(hostdata->host->host_lock, flags);
 
 	scsi_unblock_requests(hostdata->host);
 }
@@ -2224,7 +2242,7 @@
 	init_waitqueue_head(&hostdata->work_wait_q);
 	hostdata->host = host;
 	hostdata->dev = dev;
-	atomic_set(&hostdata->request_limit, -1);
+	ibmvscsi_set_request_limit(hostdata, -1);
 	hostdata->host->max_sectors = IBMVSCSI_MAX_SECTORS_DEFAULT;
 
 	if (map_persist_bufs(hostdata)) {
@@ -2320,16 +2338,12 @@
 static int ibmvscsi_remove(struct vio_dev *vdev)
 {
 	struct ibmvscsi_host_data *hostdata = dev_get_drvdata(&vdev->dev);
-	unsigned long flags;
 
 	srp_remove_host(hostdata->host);
 	scsi_remove_host(hostdata->host);
 
 	purge_requests(hostdata, DID_ERROR);
-
-	spin_lock_irqsave(hostdata->host->host_lock, flags);
 	release_event_pool(&hostdata->pool, hostdata);
-	spin_unlock_irqrestore(hostdata->host->host_lock, flags);
 
 	ibmvscsi_release_crq_queue(&hostdata->queue, hostdata,
 					max_events);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
@@ -35,7 +35,7 @@
 
 #define IBMVSCSIS_VERSION	"v0.2"
 
-#define	INITIAL_SRP_LIMIT	800
+#define	INITIAL_SRP_LIMIT	1024
 #define	DEFAULT_MAX_SECTORS	256
 #define MAX_TXU			1024 * 1024
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/ipr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/ipr.c
@@ -1517,23 +1517,22 @@
 }
 
 /**
- * strip_and_pad_whitespace - Strip and pad trailing whitespace.
- * @i:		index into buffer
- * @buf:		string to modify
+ * strip_whitespace - Strip and pad trailing whitespace.
+ * @i:		size of buffer
+ * @buf:	string to modify
  *
- * This function will strip all trailing whitespace, pad the end
- * of the string with a single space, and NULL terminate the string.
+ * This function will strip all trailing whitespace and
+ * NUL terminate the string.
  *
- * Return value:
- * 	new length of string
  **/
-static int strip_and_pad_whitespace(int i, char *buf)
+static void strip_whitespace(int i, char *buf)
 {
+	if (i < 1)
+		return;
+	i--;
 	while (i && buf[i] == ' ')
 		i--;
-	buf[i+1] = ' ';
-	buf[i+2] = '\0';
-	return i + 2;
+	buf[i+1] = '\0';
 }
 
 /**
@@ -1548,19 +1547,21 @@
 static void ipr_log_vpd_compact(char *prefix, struct ipr_hostrcb *hostrcb,
 				struct ipr_vpd *vpd)
 {
-	char buffer[IPR_VENDOR_ID_LEN + IPR_PROD_ID_LEN + IPR_SERIAL_NUM_LEN + 3];
-	int i = 0;
+	char vendor_id[IPR_VENDOR_ID_LEN + 1];
+	char product_id[IPR_PROD_ID_LEN + 1];
+	char sn[IPR_SERIAL_NUM_LEN + 1];
 
-	memcpy(buffer, vpd->vpids.vendor_id, IPR_VENDOR_ID_LEN);
-	i = strip_and_pad_whitespace(IPR_VENDOR_ID_LEN - 1, buffer);
+	memcpy(vendor_id, vpd->vpids.vendor_id, IPR_VENDOR_ID_LEN);
+	strip_whitespace(IPR_VENDOR_ID_LEN, vendor_id);
 
-	memcpy(&buffer[i], vpd->vpids.product_id, IPR_PROD_ID_LEN);
-	i = strip_and_pad_whitespace(i + IPR_PROD_ID_LEN - 1, buffer);
+	memcpy(product_id, vpd->vpids.product_id, IPR_PROD_ID_LEN);
+	strip_whitespace(IPR_PROD_ID_LEN, product_id);
 
-	memcpy(&buffer[i], vpd->sn, IPR_SERIAL_NUM_LEN);
-	buffer[IPR_SERIAL_NUM_LEN + i] = '\0';
+	memcpy(sn, vpd->sn, IPR_SERIAL_NUM_LEN);
+	strip_whitespace(IPR_SERIAL_NUM_LEN, sn);
 
-	ipr_hcam_err(hostrcb, "%s VPID/SN: %s\n", prefix, buffer);
+	ipr_hcam_err(hostrcb, "%s VPID/SN: %s %s %s\n", prefix,
+		     vendor_id, product_id, sn);
 }
 
 /**
@@ -9772,7 +9773,7 @@
 					GFP_KERNEL);
 
 		if (!ioa_cfg->hrrq[i].host_rrq)  {
-			while (--i > 0)
+			while (--i >= 0)
 				dma_free_coherent(&pdev->dev,
 					sizeof(u32) * ioa_cfg->hrrq[i].size,
 					ioa_cfg->hrrq[i].host_rrq,
@@ -9947,6 +9948,7 @@
 	ioa_cfg->max_devs_supported = ipr_max_devs;
 
 	if (ioa_cfg->sis64) {
+		host->max_channel = IPR_MAX_SIS64_BUSES;
 		host->max_id = IPR_MAX_SIS64_TARGETS_PER_BUS;
 		host->max_lun = IPR_MAX_SIS64_LUNS_PER_TARGET;
 		if (ipr_max_devs > IPR_MAX_SIS64_DEVS)
@@ -9955,6 +9957,7 @@
 					   + ((sizeof(struct ipr_config_table_entry64)
 					       * ioa_cfg->max_devs_supported)));
 	} else {
+		host->max_channel = IPR_VSET_BUS;
 		host->max_id = IPR_MAX_NUM_TARGETS_PER_BUS;
 		host->max_lun = IPR_MAX_NUM_LUNS_PER_TARGET;
 		if (ipr_max_devs > IPR_MAX_PHYSICAL_DEVS)
@@ -9964,7 +9967,6 @@
 					       * ioa_cfg->max_devs_supported)));
 	}
 
-	host->max_channel = IPR_VSET_BUS;
 	host->unique_id = host->host_no;
 	host->max_cmd_len = IPR_MAX_CDB_LEN;
 	host->can_queue = ioa_cfg->max_cmds;
@@ -10044,7 +10046,7 @@
 			ioa_cfg->vectors_info[i].desc,
 			&ioa_cfg->hrrq[i]);
 		if (rc) {
-			while (--i >= 0)
+			while (--i > 0)
 				free_irq(pci_irq_vector(pdev, i),
 					&ioa_cfg->hrrq[i]);
 			return rc;
@@ -10842,11 +10844,19 @@
  **/
 static int __init ipr_init(void)
 {
+	int rc;
+
 	ipr_info("IBM Power RAID SCSI Device Driver version: %s %s\n",
 		 IPR_DRIVER_VERSION, IPR_DRIVER_DATE);
 
 	register_reboot_notifier(&ipr_notifier);
-	return pci_register_driver(&ipr_driver);
+	rc = pci_register_driver(&ipr_driver);
+	if (rc) {
+		unregister_reboot_notifier(&ipr_notifier);
+		return rc;
+	}
+
+	return 0;
 }
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/ipr.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/ipr.h
@@ -1300,6 +1300,7 @@
 #define IPR_ARRAY_VIRTUAL_BUS			0x1
 #define IPR_VSET_VIRTUAL_BUS			0x2
 #define IPR_IOAFP_VIRTUAL_BUS			0x3
+#define IPR_MAX_SIS64_BUSES			0x4
 
 #define IPR_GET_RES_PHYS_LOC(res) \
 	(((res)->bus << 24) | ((res)->target << 8) | (res)->lun)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/isci/init.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/isci/init.c
@@ -166,6 +166,7 @@
 	.eh_abort_handler		= sas_eh_abort_handler,
 	.eh_device_reset_handler        = sas_eh_device_reset_handler,
 	.eh_target_reset_handler        = sas_eh_target_reset_handler,
+	.slave_alloc			= sas_slave_alloc,
 	.target_destroy			= sas_target_destroy,
 	.ioctl				= sas_ioctl,
 	.shost_attrs			= isci_host_attrs,
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/isci/request.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/isci/request.c
@@ -3398,7 +3398,7 @@
 		return SCI_FAILURE;
 	}
 
-	return SCI_SUCCESS;
+	return status;
 }
 
 static struct isci_request *isci_request_from_tag(struct isci_host *ihost, u16 tag)
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/iscsi_boot_sysfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/iscsi_boot_sysfs.c
@@ -352,7 +352,7 @@
 	boot_kobj->kobj.kset = boot_kset->kset;
 	if (kobject_init_and_add(&boot_kobj->kobj, &iscsi_boot_ktype,
 				 NULL, name, index)) {
-		kfree(boot_kobj);
+		kobject_put(&boot_kobj->kobj);
 		return NULL;
 	}
 	boot_kobj->data = data;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/iscsi_tcp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/iscsi_tcp.c
@@ -369,8 +369,16 @@
 {
 	struct iscsi_conn *conn = task->conn;
 	unsigned int noreclaim_flag;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
 	int rc = 0;
 
+	if (!tcp_sw_conn->sock) {
+		iscsi_conn_printk(KERN_ERR, conn,
+				  "Transport not bound to socket!\n");
+		return -EINVAL;
+	}
+
 	noreclaim_flag = memalloc_noreclaim_save();
 
 	while (iscsi_sw_tcp_xmit_qlen(conn)) {
@@ -762,7 +770,7 @@
 				       enum iscsi_host_param param, char *buf)
 {
 	struct iscsi_sw_tcp_host *tcp_sw_host = iscsi_host_priv(shost);
-	struct iscsi_session *session = tcp_sw_host->session;
+	struct iscsi_session *session;
 	struct iscsi_conn *conn;
 	struct iscsi_tcp_conn *tcp_conn;
 	struct iscsi_sw_tcp_conn *tcp_sw_conn;
@@ -771,6 +779,7 @@
 
 	switch (param) {
 	case ISCSI_HOST_PARAM_IPADDRESS:
+		session = tcp_sw_host->session;
 		if (!session)
 			return -ENOTCONN;
 
@@ -859,12 +868,14 @@
 	if (!cls_session)
 		goto remove_host;
 	session = cls_session->dd_data;
-	tcp_sw_host = iscsi_host_priv(shost);
-	tcp_sw_host->session = session;
 
 	shost->can_queue = session->scsi_cmds_max;
 	if (iscsi_tcp_r2tpool_alloc(session))
 		goto remove_session;
+
+	/* We are now fully setup so expose the session to sysfs. */
+	tcp_sw_host = iscsi_host_priv(shost);
+	tcp_sw_host->session = session;
 	return cls_session;
 
 remove_session:
@@ -879,11 +890,22 @@
 static void iscsi_sw_tcp_session_destroy(struct iscsi_cls_session *cls_session)
 {
 	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
+	struct iscsi_session *session = cls_session->dd_data;
 
-	iscsi_tcp_r2tpool_free(cls_session->dd_data);
-	iscsi_session_teardown(cls_session);
+	if (WARN_ON_ONCE(session->leadconn))
+		return;
 
+	iscsi_session_remove(cls_session);
+	/*
+	 * Our get_host_param needs to access the session, so remove the
+	 * host from sysfs before freeing the session to make sure userspace
+	 * is no longer accessing the callout.
+	 */
 	iscsi_host_remove(shost);
+
+	iscsi_tcp_r2tpool_free(cls_session->dd_data);
+
+	iscsi_session_free(cls_session);
 	iscsi_host_free(shost);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/jazz_esp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/jazz_esp.c
@@ -143,7 +143,9 @@
 	if (!esp->command_block)
 		goto fail_unmap_regs;
 
-	host->irq = platform_get_irq(dev, 0);
+	host->irq = err = platform_get_irq(dev, 0);
+	if (err < 0)
+		goto fail_unmap_command_block;
 	err = request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "ESP", esp);
 	if (err < 0)
 		goto fail_unmap_command_block;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/libfc/fc_disc.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/libfc/fc_disc.c
@@ -581,8 +581,12 @@
 
 	if (PTR_ERR(fp) == -FC_EX_CLOSED)
 		goto out;
-	if (IS_ERR(fp))
-		goto redisc;
+	if (IS_ERR(fp)) {
+		mutex_lock(&disc->disc_mutex);
+		fc_disc_restart(disc);
+		mutex_unlock(&disc->disc_mutex);
+		goto out;
+	}
 
 	cp = fc_frame_payload_get(fp, sizeof(*cp));
 	if (!cp)
@@ -609,7 +613,7 @@
 				new_rdata->disc_id = disc->disc_id;
 				fc_rport_login(new_rdata);
 			}
-			goto out;
+			goto free_fp;
 		}
 		rdata->disc_id = disc->disc_id;
 		mutex_unlock(&rdata->rp_mutex);
@@ -626,6 +630,8 @@
 		fc_disc_restart(disc);
 		mutex_unlock(&disc->disc_mutex);
 	}
+free_fp:
+	fc_frame_free(fp);
 out:
 	kref_put(&rdata->kref, fc_rport_destroy);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/libfc/fc_exch.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/libfc/fc_exch.c
@@ -1619,8 +1619,13 @@
 		rc = fc_exch_done_locked(ep);
 		WARN_ON(fc_seq_exch(sp) != ep);
 		spin_unlock_bh(&ep->ex_lock);
-		if (!rc)
+		if (!rc) {
 			fc_exch_delete(ep);
+		} else {
+			FC_EXCH_DBG(ep, "ep is completed already,"
+					"hence skip calling the resp\n");
+			goto skip_resp;
+		}
 	}
 
 	/*
@@ -1639,6 +1644,7 @@
 	if (!fc_invoke_resp(ep, sp, fp))
 		fc_frame_free(fp);
 
+skip_resp:
 	fc_exch_release(ep);
 	return;
 rel:
@@ -1691,6 +1697,7 @@
 	if (cancel_delayed_work_sync(&ep->timeout_work)) {
 		FC_EXCH_DBG(ep, "Exchange timer canceled due to ABTS response\n");
 		fc_exch_release(ep);	/* release from pending timer hold */
+		return;
 	}
 
 	spin_lock_bh(&ep->ex_lock);
@@ -1895,10 +1902,16 @@
 
 	fc_exch_hold(ep);
 
-	if (!rc)
+	if (!rc) {
 		fc_exch_delete(ep);
+	} else {
+		FC_EXCH_DBG(ep, "ep is completed already,"
+				"hence skip calling the resp\n");
+		goto skip_resp;
+	}
 
 	fc_invoke_resp(ep, sp, ERR_PTR(-FC_EX_CLOSED));
+skip_resp:
 	fc_seq_set_resp(sp, NULL, ep->arg);
 	fc_exch_release(ep);
 }
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/libfc/fc_fcp.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/libfc/fc_fcp.c
@@ -270,6 +270,11 @@
 	if (!fsp->seq_ptr)
 		return -EINVAL;
 
+	if (fsp->state & FC_SRB_ABORT_PENDING) {
+		FC_FCP_DBG(fsp, "abort already pending\n");
+		return -EBUSY;
+	}
+
 	per_cpu_ptr(fsp->lp->stats, get_cpu())->FcpPktAborts++;
 	put_cpu();
 
@@ -1680,7 +1685,7 @@
 		if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY)
 			fc_fcp_rec(fsp);
 		else
-			fc_fcp_recovery(fsp, FC_ERROR);
+			fc_fcp_recovery(fsp, FC_TIMED_OUT);
 		break;
 	}
 	fc_fcp_unlock_pkt(fsp);
@@ -1698,11 +1703,12 @@
 	fsp->status_code = code;
 	fsp->cdb_status = 0;
 	fsp->io_status = 0;
-	/*
-	 * if this fails then we let the scsi command timer fire and
-	 * scsi-ml escalate.
-	 */
-	fc_fcp_send_abort(fsp);
+	if (!fsp->cmd)
+		/*
+		 * Only abort non-scsi commands; otherwise let the
+		 * scsi command timer fire and scsi-ml escalate.
+		 */
+		fc_fcp_send_abort(fsp);
 }
 
 /**
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/libfc/fc_lport.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/libfc/fc_lport.c
@@ -238,6 +238,12 @@
 	}
 	mutex_lock(&lport->disc.disc_mutex);
 	lport->ptp_rdata = fc_rport_create(lport, remote_fid);
+	if (!lport->ptp_rdata) {
+		printk(KERN_WARNING "libfc: Failed to setup lport 0x%x\n",
+			lport->port_id);
+		mutex_unlock(&lport->disc.disc_mutex);
+		return;
+	}
 	kref_get(&lport->ptp_rdata->kref);
 	lport->ptp_rdata->ids.port_name = remote_wwpn;
 	lport->ptp_rdata->ids.node_name = remote_wwnn;
@@ -1729,7 +1735,7 @@
 
 	if (mfs < FC_SP_MIN_MAX_PAYLOAD || mfs > FC_SP_MAX_MAX_PAYLOAD) {
 		FC_LPORT_DBG(lport, "FLOGI bad mfs:%hu response, "
-			     "lport->mfs:%hu\n", mfs, lport->mfs);
+			     "lport->mfs:%u\n", mfs, lport->mfs);
 		fc_lport_error(lport, fp);
 		goto out;
 	}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/libfc/fc_rport.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/libfc/fc_rport.c
@@ -133,8 +133,10 @@
 	lockdep_assert_held(&lport->disc.disc_mutex);
 
 	rdata = fc_rport_lookup(lport, port_id);
-	if (rdata)
+	if (rdata) {
+		kref_put(&rdata->kref, fc_rport_destroy);
 		return rdata;
+	}
 
 	if (lport->rport_priv_size > 0)
 		rport_priv_size = lport->rport_priv_size;
@@ -481,10 +483,11 @@
 
 	fc_rport_state_enter(rdata, RPORT_ST_DELETE);
 
-	kref_get(&rdata->kref);
-	if (rdata->event == RPORT_EV_NONE &&
-	    !queue_work(rport_event_queue, &rdata->event_work))
-		kref_put(&rdata->kref, fc_rport_destroy);
+	if (rdata->event == RPORT_EV_NONE) {
+		kref_get(&rdata->kref);
+		if (!queue_work(rport_event_queue, &rdata->event_work))
+			kref_put(&rdata->kref, fc_rport_destroy);
+	}
 
 	rdata->event = event;
 }
@@ -1157,6 +1160,7 @@
 		resp_code = (pp->spp.spp_flags & FC_SPP_RESP_MASK);
 		FC_RPORT_DBG(rdata, "PRLI spp_flags = 0x%x spp_type 0x%x\n",
 			     pp->spp.spp_flags, pp->spp.spp_type);
+
 		rdata->spp_type = pp->spp.spp_type;
 		if (resp_code != FC_SPP_RESP_ACK) {
 			if (resp_code == FC_SPP_RESP_CONF)
@@ -1179,11 +1183,13 @@
 		/*
 		 * Call prli provider if we should act as a target
 		 */
-		prov = fc_passive_prov[rdata->spp_type];
-		if (prov) {
-			memset(&temp_spp, 0, sizeof(temp_spp));
-			prov->prli(rdata, pp->prli.prli_spp_len,
-				   &pp->spp, &temp_spp);
+		if (rdata->spp_type < FC_FC4_PROV_SIZE) {
+			prov = fc_passive_prov[rdata->spp_type];
+			if (prov) {
+				memset(&temp_spp, 0, sizeof(temp_spp));
+				prov->prli(rdata, pp->prli.prli_spp_len,
+					   &pp->spp, &temp_spp);
+			}
 		}
 		/*
 		 * Check if the image pair could be established
@@ -1208,9 +1214,15 @@
 		rjt = fc_frame_payload_get(fp, sizeof(*rjt));
 		if (!rjt)
 			FC_RPORT_DBG(rdata, "PRLI bad response\n");
-		else
+		else {
 			FC_RPORT_DBG(rdata, "PRLI ELS rejected, reason %x expl %x\n",
 				     rjt->er_reason, rjt->er_explan);
+			if (rjt->er_reason == ELS_RJT_UNAB &&
+			    rjt->er_explan == ELS_EXPL_PLOGI_REQD) {
+				fc_rport_enter_plogi(rdata);
+				goto out;
+			}
+		}
 		fc_rport_error_retry(rdata, FC_EX_ELS_RJT);
 	}
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/libiscsi.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/libiscsi.c
@@ -230,11 +230,11 @@
  */
 static int iscsi_check_tmf_restrictions(struct iscsi_task *task, int opcode)
 {
-	struct iscsi_conn *conn = task->conn;
-	struct iscsi_tm *tmf = &conn->tmhdr;
+	struct iscsi_session *session = task->conn->session;
+	struct iscsi_tm *tmf = &session->tmhdr;
 	u64 hdr_lun;
 
-	if (conn->tmf_state == TMF_INITIAL)
+	if (session->tmf_state == TMF_INITIAL)
 		return 0;
 
 	if ((tmf->opcode & ISCSI_OPCODE_MASK) != ISCSI_OP_SCSI_TMFUNC)
@@ -254,24 +254,19 @@
 		 * Fail all SCSI cmd PDUs
 		 */
 		if (opcode != ISCSI_OP_SCSI_DATA_OUT) {
-			iscsi_conn_printk(KERN_INFO, conn,
-					  "task [op %x itt "
-					  "0x%x/0x%x] "
-					  "rejected.\n",
-					  opcode, task->itt,
-					  task->hdr_itt);
+			iscsi_session_printk(KERN_INFO, session,
+					     "task [op %x itt 0x%x/0x%x] rejected.\n",
+					     opcode, task->itt, task->hdr_itt);
 			return -EACCES;
 		}
 		/*
 		 * And also all data-out PDUs in response to R2T
 		 * if fast_abort is set.
 		 */
-		if (conn->session->fast_abort) {
-			iscsi_conn_printk(KERN_INFO, conn,
-					  "task [op %x itt "
-					  "0x%x/0x%x] fast abort.\n",
-					  opcode, task->itt,
-					  task->hdr_itt);
+		if (session->fast_abort) {
+			iscsi_session_printk(KERN_INFO, session,
+					     "task [op %x itt 0x%x/0x%x] fast abort.\n",
+					     opcode, task->itt, task->hdr_itt);
 			return -EACCES;
 		}
 		break;
@@ -284,7 +279,7 @@
 		 */
 		if (opcode == ISCSI_OP_SCSI_DATA_OUT &&
 		    task->hdr_itt == tmf->rtt) {
-			ISCSI_DBG_SESSION(conn->session,
+			ISCSI_DBG_SESSION(session,
 					  "Preventing task %x/%x from sending "
 					  "data-out due to abort task in "
 					  "progress\n", task->itt,
@@ -533,8 +528,8 @@
 	if (conn->task == task)
 		conn->task = NULL;
 
-	if (conn->ping_task == task)
-		conn->ping_task = NULL;
+	if (READ_ONCE(conn->ping_task) == task)
+		WRITE_ONCE(conn->ping_task, NULL);
 
 	/* release get from queueing */
 	__iscsi_put_task(task);
@@ -738,6 +733,9 @@
 						   task->conn->session->age);
 	}
 
+	if (unlikely(READ_ONCE(conn->ping_task) == INVALID_SCSI_TASK))
+		WRITE_ONCE(conn->ping_task, task);
+
 	if (!ihost->workq) {
 		if (iscsi_prep_mgmt_task(conn, task))
 			goto free_task;
@@ -920,20 +918,21 @@
 static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
 {
 	struct iscsi_tm_rsp *tmf = (struct iscsi_tm_rsp *)hdr;
+	struct iscsi_session *session = conn->session;
 
 	conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
 	conn->tmfrsp_pdus_cnt++;
 
-	if (conn->tmf_state != TMF_QUEUED)
+	if (session->tmf_state != TMF_QUEUED)
 		return;
 
 	if (tmf->response == ISCSI_TMF_RSP_COMPLETE)
-		conn->tmf_state = TMF_SUCCESS;
+		session->tmf_state = TMF_SUCCESS;
 	else if (tmf->response == ISCSI_TMF_RSP_NO_TASK)
-		conn->tmf_state = TMF_NOT_FOUND;
+		session->tmf_state = TMF_NOT_FOUND;
 	else
-		conn->tmf_state = TMF_FAILED;
-	wake_up(&conn->ehwait);
+		session->tmf_state = TMF_FAILED;
+	wake_up(&session->ehwait);
 }
 
 static int iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr)
@@ -941,8 +940,11 @@
         struct iscsi_nopout hdr;
 	struct iscsi_task *task;
 
-	if (!rhdr && conn->ping_task)
-		return -EINVAL;
+	if (!rhdr) {
+		if (READ_ONCE(conn->ping_task))
+			return -EINVAL;
+		WRITE_ONCE(conn->ping_task, INVALID_SCSI_TASK);
+	}
 
 	memset(&hdr, 0, sizeof(struct iscsi_nopout));
 	hdr.opcode = ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE;
@@ -957,11 +959,12 @@
 
 	task = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0);
 	if (!task) {
+		if (!rhdr)
+			WRITE_ONCE(conn->ping_task, NULL);
 		iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout\n");
 		return -EIO;
 	} else if (!rhdr) {
 		/* only track our nops */
-		conn->ping_task = task;
 		conn->last_ping = jiffies;
 	}
 
@@ -984,7 +987,7 @@
 	struct iscsi_conn *conn = task->conn;
 	int rc = 0;
 
-	if (conn->ping_task != task) {
+	if (READ_ONCE(conn->ping_task) != task) {
 		/*
 		 * If this is not in response to one of our
 		 * nops then it must be from userspace.
@@ -1341,7 +1344,6 @@
 			   enum iscsi_err err)
 {
 	struct iscsi_conn *conn;
-	struct device *dev;
 
 	spin_lock_bh(&session->frwd_lock);
 	conn = session->leadconn;
@@ -1350,10 +1352,8 @@
 		return;
 	}
 
-	dev = get_device(&conn->cls_conn->dev);
+	iscsi_get_conn(conn->cls_conn);
 	spin_unlock_bh(&session->frwd_lock);
-	if (!dev)
-	        return;
 	/*
 	 * if the host is being removed bypass the connection
 	 * recovery initialization because we are going to kill
@@ -1363,7 +1363,7 @@
 		iscsi_conn_error_event(conn->cls_conn, err);
 	else
 		iscsi_conn_failure(conn, err);
-	put_device(dev);
+	iscsi_put_conn(conn->cls_conn);
 }
 EXPORT_SYMBOL_GPL(iscsi_session_failure);
 
@@ -1525,14 +1525,9 @@
 		}
 		rc = iscsi_prep_scsi_cmd_pdu(conn->task);
 		if (rc) {
-			if (rc == -ENOMEM || rc == -EACCES) {
-				spin_lock_bh(&conn->taskqueuelock);
-				list_add_tail(&conn->task->running,
-					      &conn->cmdqueue);
-				conn->task = NULL;
-				spin_unlock_bh(&conn->taskqueuelock);
-				goto done;
-			} else
+			if (rc == -ENOMEM || rc == -EACCES)
+				fail_scsi_task(conn->task, DID_IMM_RETRY);
+			else
 				fail_scsi_task(conn->task, DID_ABORT);
 			spin_lock_bh(&conn->taskqueuelock);
 			continue;
@@ -1785,15 +1780,14 @@
 
 static void iscsi_tmf_timedout(struct timer_list *t)
 {
-	struct iscsi_conn *conn = from_timer(conn, t, tmf_timer);
-	struct iscsi_session *session = conn->session;
+	struct iscsi_session *session = from_timer(session, t, tmf_timer);
 
 	spin_lock(&session->frwd_lock);
-	if (conn->tmf_state == TMF_QUEUED) {
-		conn->tmf_state = TMF_TIMEDOUT;
+	if (session->tmf_state == TMF_QUEUED) {
+		session->tmf_state = TMF_TIMEDOUT;
 		ISCSI_DBG_EH(session, "tmf timedout\n");
 		/* unblock eh_abort() */
-		wake_up(&conn->ehwait);
+		wake_up(&session->ehwait);
 	}
 	spin_unlock(&session->frwd_lock);
 }
@@ -1816,8 +1810,8 @@
 		return -EPERM;
 	}
 	conn->tmfcmd_pdus_cnt++;
-	conn->tmf_timer.expires = timeout * HZ + jiffies;
-	add_timer(&conn->tmf_timer);
+	session->tmf_timer.expires = timeout * HZ + jiffies;
+	add_timer(&session->tmf_timer);
 	ISCSI_DBG_EH(session, "tmf set timeout\n");
 
 	spin_unlock_bh(&session->frwd_lock);
@@ -1831,12 +1825,12 @@
 	 * 3) session is terminated or restarted or userspace has
 	 * given up on recovery
 	 */
-	wait_event_interruptible(conn->ehwait, age != session->age ||
+	wait_event_interruptible(session->ehwait, age != session->age ||
 				 session->state != ISCSI_STATE_LOGGED_IN ||
-				 conn->tmf_state != TMF_QUEUED);
+				 session->tmf_state != TMF_QUEUED);
 	if (signal_pending(current))
 		flush_signals(current);
-	del_timer_sync(&conn->tmf_timer);
+	del_timer_sync(&session->tmf_timer);
 
 	mutex_lock(&session->eh_mutex);
 	spin_lock_bh(&session->frwd_lock);
@@ -1923,7 +1917,7 @@
  */
 static int iscsi_has_ping_timed_out(struct iscsi_conn *conn)
 {
-	if (conn->ping_task &&
+	if (READ_ONCE(conn->ping_task) &&
 	    time_before_eq(conn->last_recv + (conn->recv_timeout * HZ) +
 			   (conn->ping_timeout * HZ), jiffies))
 		return 1;
@@ -1945,7 +1939,7 @@
 
 	ISCSI_DBG_EH(session, "scsi cmd %p timedout\n", sc);
 
-	spin_lock(&session->frwd_lock);
+	spin_lock_bh(&session->frwd_lock);
 	task = (struct iscsi_task *)sc->SCp.ptr;
 	if (!task) {
 		/*
@@ -2058,7 +2052,7 @@
 	 * Checking the transport already or nop from a cmd timeout still
 	 * running
 	 */
-	if (conn->ping_task) {
+	if (READ_ONCE(conn->ping_task)) {
 		task->have_checked_conn = true;
 		rc = BLK_EH_RESET_TIMER;
 		goto done;
@@ -2072,7 +2066,7 @@
 done:
 	if (task)
 		task->last_timeout = jiffies;
-	spin_unlock(&session->frwd_lock);
+	spin_unlock_bh(&session->frwd_lock);
 	ISCSI_DBG_EH(session, "return %s\n", rc == BLK_EH_RESET_TIMER ?
 		     "timer reset" : "shutdown or nh");
 	return rc;
@@ -2196,17 +2190,17 @@
 	}
 
 	/* only have one tmf outstanding at a time */
-	if (conn->tmf_state != TMF_INITIAL)
+	if (session->tmf_state != TMF_INITIAL)
 		goto failed;
-	conn->tmf_state = TMF_QUEUED;
+	session->tmf_state = TMF_QUEUED;
 
-	hdr = &conn->tmhdr;
+	hdr = &session->tmhdr;
 	iscsi_prep_abort_task_pdu(task, hdr);
 
 	if (iscsi_exec_task_mgmt_fn(conn, hdr, age, session->abort_timeout))
 		goto failed;
 
-	switch (conn->tmf_state) {
+	switch (session->tmf_state) {
 	case TMF_SUCCESS:
 		spin_unlock_bh(&session->frwd_lock);
 		/*
@@ -2221,7 +2215,7 @@
 		 */
 		spin_lock_bh(&session->frwd_lock);
 		fail_scsi_task(task, DID_ABORT);
-		conn->tmf_state = TMF_INITIAL;
+		session->tmf_state = TMF_INITIAL;
 		memset(hdr, 0, sizeof(*hdr));
 		spin_unlock_bh(&session->frwd_lock);
 		iscsi_start_tx(conn);
@@ -2232,7 +2226,7 @@
 		goto failed_unlocked;
 	case TMF_NOT_FOUND:
 		if (!sc->SCp.ptr) {
-			conn->tmf_state = TMF_INITIAL;
+			session->tmf_state = TMF_INITIAL;
 			memset(hdr, 0, sizeof(*hdr));
 			/* task completed before tmf abort response */
 			ISCSI_DBG_EH(session, "sc completed while abort	in "
@@ -2241,7 +2235,7 @@
 		}
 		/* fall through */
 	default:
-		conn->tmf_state = TMF_INITIAL;
+		session->tmf_state = TMF_INITIAL;
 		goto failed;
 	}
 
@@ -2298,11 +2292,11 @@
 	conn = session->leadconn;
 
 	/* only have one tmf outstanding at a time */
-	if (conn->tmf_state != TMF_INITIAL)
+	if (session->tmf_state != TMF_INITIAL)
 		goto unlock;
-	conn->tmf_state = TMF_QUEUED;
+	session->tmf_state = TMF_QUEUED;
 
-	hdr = &conn->tmhdr;
+	hdr = &session->tmhdr;
 	iscsi_prep_lun_reset_pdu(sc, hdr);
 
 	if (iscsi_exec_task_mgmt_fn(conn, hdr, session->age,
@@ -2311,7 +2305,7 @@
 		goto unlock;
 	}
 
-	switch (conn->tmf_state) {
+	switch (session->tmf_state) {
 	case TMF_SUCCESS:
 		break;
 	case TMF_TIMEDOUT:
@@ -2319,7 +2313,7 @@
 		iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST);
 		goto done;
 	default:
-		conn->tmf_state = TMF_INITIAL;
+		session->tmf_state = TMF_INITIAL;
 		goto unlock;
 	}
 
@@ -2331,7 +2325,7 @@
 	spin_lock_bh(&session->frwd_lock);
 	memset(hdr, 0, sizeof(*hdr));
 	fail_scsi_tasks(conn, sc->device->lun, DID_ERROR);
-	conn->tmf_state = TMF_INITIAL;
+	session->tmf_state = TMF_INITIAL;
 	spin_unlock_bh(&session->frwd_lock);
 
 	iscsi_start_tx(conn);
@@ -2354,8 +2348,7 @@
 	spin_lock_bh(&session->frwd_lock);
 	if (session->state != ISCSI_STATE_LOGGED_IN) {
 		session->state = ISCSI_STATE_RECOVERY_FAILED;
-		if (session->leadconn)
-			wake_up(&session->leadconn->ehwait);
+		wake_up(&session->ehwait);
 	}
 	spin_unlock_bh(&session->frwd_lock);
 }
@@ -2400,7 +2393,7 @@
 	iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST);
 
 	ISCSI_DBG_EH(session, "wait for relogin\n");
-	wait_event_interruptible(conn->ehwait,
+	wait_event_interruptible(session->ehwait,
 				 session->state == ISCSI_STATE_TERMINATE ||
 				 session->state == ISCSI_STATE_LOGGED_IN ||
 				 session->state == ISCSI_STATE_RECOVERY_FAILED);
@@ -2461,11 +2454,11 @@
 	conn = session->leadconn;
 
 	/* only have one tmf outstanding at a time */
-	if (conn->tmf_state != TMF_INITIAL)
+	if (session->tmf_state != TMF_INITIAL)
 		goto unlock;
-	conn->tmf_state = TMF_QUEUED;
+	session->tmf_state = TMF_QUEUED;
 
-	hdr = &conn->tmhdr;
+	hdr = &session->tmhdr;
 	iscsi_prep_tgt_reset_pdu(sc, hdr);
 
 	if (iscsi_exec_task_mgmt_fn(conn, hdr, session->age,
@@ -2474,7 +2467,7 @@
 		goto unlock;
 	}
 
-	switch (conn->tmf_state) {
+	switch (session->tmf_state) {
 	case TMF_SUCCESS:
 		break;
 	case TMF_TIMEDOUT:
@@ -2482,7 +2475,7 @@
 		iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST);
 		goto done;
 	default:
-		conn->tmf_state = TMF_INITIAL;
+		session->tmf_state = TMF_INITIAL;
 		goto unlock;
 	}
 
@@ -2494,7 +2487,7 @@
 	spin_lock_bh(&session->frwd_lock);
 	memset(hdr, 0, sizeof(*hdr));
 	fail_scsi_tasks(conn, -1, DID_ERROR);
-	conn->tmf_state = TMF_INITIAL;
+	session->tmf_state = TMF_INITIAL;
 	spin_unlock_bh(&session->frwd_lock);
 
 	iscsi_start_tx(conn);
@@ -2799,7 +2792,10 @@
 	session->tt = iscsit;
 	session->dd_data = cls_session->dd_data + sizeof(*session);
 
+	session->tmf_state = TMF_INITIAL;
+	timer_setup(&session->tmf_timer, iscsi_tmf_timedout, 0);
 	mutex_init(&session->eh_mutex);
+
 	spin_lock_init(&session->frwd_lock);
 	spin_lock_init(&session->back_lock);
 
@@ -2840,20 +2836,34 @@
 }
 EXPORT_SYMBOL_GPL(iscsi_session_setup);
 
+/*
+ * issi_session_remove - Remove session from iSCSI class.
+ */
+void iscsi_session_remove(struct iscsi_cls_session *cls_session)
+{
+	struct iscsi_session *session = cls_session->dd_data;
+	struct Scsi_Host *shost = session->host;
+
+	iscsi_remove_session(cls_session);
+	/*
+	 * host removal only has to wait for its children to be removed from
+	 * sysfs, and iscsi_tcp needs to do iscsi_host_remove before freeing
+	 * the session, so drop the session count here.
+	 */
+	iscsi_host_dec_session_cnt(shost);
+}
+EXPORT_SYMBOL_GPL(iscsi_session_remove);
+
 /**
- * iscsi_session_teardown - destroy session, host, and cls_session
+ * iscsi_session_free - Free iscsi session and it's resources
  * @cls_session: iscsi session
  */
-void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
+void iscsi_session_free(struct iscsi_cls_session *cls_session)
 {
 	struct iscsi_session *session = cls_session->dd_data;
 	struct module *owner = cls_session->transport->owner;
-	struct Scsi_Host *shost = session->host;
 
 	iscsi_pool_free(&session->cmdpool);
-
-	iscsi_remove_session(cls_session);
-
 	kfree(session->password);
 	kfree(session->password_in);
 	kfree(session->username);
@@ -2869,10 +2879,19 @@
 	kfree(session->discovery_parent_type);
 
 	iscsi_free_session(cls_session);
-
-	iscsi_host_dec_session_cnt(shost);
 	module_put(owner);
 }
+EXPORT_SYMBOL_GPL(iscsi_session_free);
+
+/**
+ * iscsi_session_teardown - destroy session and cls_session
+ * @cls_session: iscsi session
+ */
+void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
+{
+	iscsi_session_remove(cls_session);
+	iscsi_session_free(cls_session);
+}
 EXPORT_SYMBOL_GPL(iscsi_session_teardown);
 
 /**
@@ -2903,7 +2922,6 @@
 	conn->c_stage = ISCSI_CONN_INITIAL_STAGE;
 	conn->id = conn_idx;
 	conn->exp_statsn = 0;
-	conn->tmf_state = TMF_INITIAL;
 
 	timer_setup(&conn->transport_timer, iscsi_check_transport_timeouts, 0);
 
@@ -2929,8 +2947,7 @@
 		goto login_task_data_alloc_fail;
 	conn->login_task->data = conn->data = data;
 
-	timer_setup(&conn->tmf_timer, iscsi_tmf_timedout, 0);
-	init_waitqueue_head(&conn->ehwait);
+	init_waitqueue_head(&session->ehwait);
 
 	return cls_conn;
 
@@ -2954,6 +2971,8 @@
 {
 	struct iscsi_conn *conn = cls_conn->dd_data;
 	struct iscsi_session *session = conn->session;
+	char *tmp_persistent_address = conn->persistent_address;
+	char *tmp_local_ipaddr = conn->local_ipaddr;
 
 	del_timer_sync(&conn->transport_timer);
 
@@ -2965,7 +2984,7 @@
 		 * leading connection? then give up on recovery.
 		 */
 		session->state = ISCSI_STATE_TERMINATE;
-		wake_up(&conn->ehwait);
+		wake_up(&session->ehwait);
 	}
 	spin_unlock_bh(&session->frwd_lock);
 
@@ -2975,8 +2994,6 @@
 	spin_lock_bh(&session->frwd_lock);
 	free_pages((unsigned long) conn->data,
 		   get_order(ISCSI_DEF_MAX_RECV_SEG_LEN));
-	kfree(conn->persistent_address);
-	kfree(conn->local_ipaddr);
 	/* regular RX path uses back_lock */
 	spin_lock_bh(&session->back_lock);
 	kfifo_in(&session->cmdpool.queue, (void*)&conn->login_task,
@@ -2988,6 +3005,8 @@
 	mutex_unlock(&session->eh_mutex);
 
 	iscsi_destroy_conn(cls_conn);
+	kfree(tmp_persistent_address);
+	kfree(tmp_local_ipaddr);
 }
 EXPORT_SYMBOL_GPL(iscsi_conn_teardown);
 
@@ -3040,7 +3059,7 @@
 		 * commands after successful recovery
 		 */
 		conn->stop_stage = 0;
-		conn->tmf_state = TMF_INITIAL;
+		session->tmf_state = TMF_INITIAL;
 		session->age++;
 		if (session->age == 16)
 			session->age = 0;
@@ -3054,7 +3073,7 @@
 	spin_unlock_bh(&session->frwd_lock);
 
 	iscsi_unblock_session(session->cls_session);
-	wake_up(&conn->ehwait);
+	wake_up(&session->ehwait);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(iscsi_conn_start);
@@ -3141,7 +3160,7 @@
 	spin_lock_bh(&session->frwd_lock);
 	fail_scsi_tasks(conn, -1, DID_TRANSPORT_DISRUPTED);
 	fail_mgmt_tasks(session, conn);
-	memset(&conn->tmhdr, 0, sizeof(conn->tmhdr));
+	memset(&session->tmhdr, 0, sizeof(session->tmhdr));
 	spin_unlock_bh(&session->frwd_lock);
 	mutex_unlock(&session->eh_mutex);
 }
@@ -3324,125 +3343,125 @@
 
 	switch(param) {
 	case ISCSI_PARAM_FAST_ABORT:
-		len = sprintf(buf, "%d\n", session->fast_abort);
+		len = sysfs_emit(buf, "%d\n", session->fast_abort);
 		break;
 	case ISCSI_PARAM_ABORT_TMO:
-		len = sprintf(buf, "%d\n", session->abort_timeout);
+		len = sysfs_emit(buf, "%d\n", session->abort_timeout);
 		break;
 	case ISCSI_PARAM_LU_RESET_TMO:
-		len = sprintf(buf, "%d\n", session->lu_reset_timeout);
+		len = sysfs_emit(buf, "%d\n", session->lu_reset_timeout);
 		break;
 	case ISCSI_PARAM_TGT_RESET_TMO:
-		len = sprintf(buf, "%d\n", session->tgt_reset_timeout);
+		len = sysfs_emit(buf, "%d\n", session->tgt_reset_timeout);
 		break;
 	case ISCSI_PARAM_INITIAL_R2T_EN:
-		len = sprintf(buf, "%d\n", session->initial_r2t_en);
+		len = sysfs_emit(buf, "%d\n", session->initial_r2t_en);
 		break;
 	case ISCSI_PARAM_MAX_R2T:
-		len = sprintf(buf, "%hu\n", session->max_r2t);
+		len = sysfs_emit(buf, "%hu\n", session->max_r2t);
 		break;
 	case ISCSI_PARAM_IMM_DATA_EN:
-		len = sprintf(buf, "%d\n", session->imm_data_en);
+		len = sysfs_emit(buf, "%d\n", session->imm_data_en);
 		break;
 	case ISCSI_PARAM_FIRST_BURST:
-		len = sprintf(buf, "%u\n", session->first_burst);
+		len = sysfs_emit(buf, "%u\n", session->first_burst);
 		break;
 	case ISCSI_PARAM_MAX_BURST:
-		len = sprintf(buf, "%u\n", session->max_burst);
+		len = sysfs_emit(buf, "%u\n", session->max_burst);
 		break;
 	case ISCSI_PARAM_PDU_INORDER_EN:
-		len = sprintf(buf, "%d\n", session->pdu_inorder_en);
+		len = sysfs_emit(buf, "%d\n", session->pdu_inorder_en);
 		break;
 	case ISCSI_PARAM_DATASEQ_INORDER_EN:
-		len = sprintf(buf, "%d\n", session->dataseq_inorder_en);
+		len = sysfs_emit(buf, "%d\n", session->dataseq_inorder_en);
 		break;
 	case ISCSI_PARAM_DEF_TASKMGMT_TMO:
-		len = sprintf(buf, "%d\n", session->def_taskmgmt_tmo);
+		len = sysfs_emit(buf, "%d\n", session->def_taskmgmt_tmo);
 		break;
 	case ISCSI_PARAM_ERL:
-		len = sprintf(buf, "%d\n", session->erl);
+		len = sysfs_emit(buf, "%d\n", session->erl);
 		break;
 	case ISCSI_PARAM_TARGET_NAME:
-		len = sprintf(buf, "%s\n", session->targetname);
+		len = sysfs_emit(buf, "%s\n", session->targetname);
 		break;
 	case ISCSI_PARAM_TARGET_ALIAS:
-		len = sprintf(buf, "%s\n", session->targetalias);
+		len = sysfs_emit(buf, "%s\n", session->targetalias);
 		break;
 	case ISCSI_PARAM_TPGT:
-		len = sprintf(buf, "%d\n", session->tpgt);
+		len = sysfs_emit(buf, "%d\n", session->tpgt);
 		break;
 	case ISCSI_PARAM_USERNAME:
-		len = sprintf(buf, "%s\n", session->username);
+		len = sysfs_emit(buf, "%s\n", session->username);
 		break;
 	case ISCSI_PARAM_USERNAME_IN:
-		len = sprintf(buf, "%s\n", session->username_in);
+		len = sysfs_emit(buf, "%s\n", session->username_in);
 		break;
 	case ISCSI_PARAM_PASSWORD:
-		len = sprintf(buf, "%s\n", session->password);
+		len = sysfs_emit(buf, "%s\n", session->password);
 		break;
 	case ISCSI_PARAM_PASSWORD_IN:
-		len = sprintf(buf, "%s\n", session->password_in);
+		len = sysfs_emit(buf, "%s\n", session->password_in);
 		break;
 	case ISCSI_PARAM_IFACE_NAME:
-		len = sprintf(buf, "%s\n", session->ifacename);
+		len = sysfs_emit(buf, "%s\n", session->ifacename);
 		break;
 	case ISCSI_PARAM_INITIATOR_NAME:
-		len = sprintf(buf, "%s\n", session->initiatorname);
+		len = sysfs_emit(buf, "%s\n", session->initiatorname);
 		break;
 	case ISCSI_PARAM_BOOT_ROOT:
-		len = sprintf(buf, "%s\n", session->boot_root);
+		len = sysfs_emit(buf, "%s\n", session->boot_root);
 		break;
 	case ISCSI_PARAM_BOOT_NIC:
-		len = sprintf(buf, "%s\n", session->boot_nic);
+		len = sysfs_emit(buf, "%s\n", session->boot_nic);
 		break;
 	case ISCSI_PARAM_BOOT_TARGET:
-		len = sprintf(buf, "%s\n", session->boot_target);
+		len = sysfs_emit(buf, "%s\n", session->boot_target);
 		break;
 	case ISCSI_PARAM_AUTO_SND_TGT_DISABLE:
-		len = sprintf(buf, "%u\n", session->auto_snd_tgt_disable);
+		len = sysfs_emit(buf, "%u\n", session->auto_snd_tgt_disable);
 		break;
 	case ISCSI_PARAM_DISCOVERY_SESS:
-		len = sprintf(buf, "%u\n", session->discovery_sess);
+		len = sysfs_emit(buf, "%u\n", session->discovery_sess);
 		break;
 	case ISCSI_PARAM_PORTAL_TYPE:
-		len = sprintf(buf, "%s\n", session->portal_type);
+		len = sysfs_emit(buf, "%s\n", session->portal_type);
 		break;
 	case ISCSI_PARAM_CHAP_AUTH_EN:
-		len = sprintf(buf, "%u\n", session->chap_auth_en);
+		len = sysfs_emit(buf, "%u\n", session->chap_auth_en);
 		break;
 	case ISCSI_PARAM_DISCOVERY_LOGOUT_EN:
-		len = sprintf(buf, "%u\n", session->discovery_logout_en);
+		len = sysfs_emit(buf, "%u\n", session->discovery_logout_en);
 		break;
 	case ISCSI_PARAM_BIDI_CHAP_EN:
-		len = sprintf(buf, "%u\n", session->bidi_chap_en);
+		len = sysfs_emit(buf, "%u\n", session->bidi_chap_en);
 		break;
 	case ISCSI_PARAM_DISCOVERY_AUTH_OPTIONAL:
-		len = sprintf(buf, "%u\n", session->discovery_auth_optional);
+		len = sysfs_emit(buf, "%u\n", session->discovery_auth_optional);
 		break;
 	case ISCSI_PARAM_DEF_TIME2WAIT:
-		len = sprintf(buf, "%d\n", session->time2wait);
+		len = sysfs_emit(buf, "%d\n", session->time2wait);
 		break;
 	case ISCSI_PARAM_DEF_TIME2RETAIN:
-		len = sprintf(buf, "%d\n", session->time2retain);
+		len = sysfs_emit(buf, "%d\n", session->time2retain);
 		break;
 	case ISCSI_PARAM_TSID:
-		len = sprintf(buf, "%u\n", session->tsid);
+		len = sysfs_emit(buf, "%u\n", session->tsid);
 		break;
 	case ISCSI_PARAM_ISID:
-		len = sprintf(buf, "%02x%02x%02x%02x%02x%02x\n",
+		len = sysfs_emit(buf, "%02x%02x%02x%02x%02x%02x\n",
 			      session->isid[0], session->isid[1],
 			      session->isid[2], session->isid[3],
 			      session->isid[4], session->isid[5]);
 		break;
 	case ISCSI_PARAM_DISCOVERY_PARENT_IDX:
-		len = sprintf(buf, "%u\n", session->discovery_parent_idx);
+		len = sysfs_emit(buf, "%u\n", session->discovery_parent_idx);
 		break;
 	case ISCSI_PARAM_DISCOVERY_PARENT_TYPE:
 		if (session->discovery_parent_type)
-			len = sprintf(buf, "%s\n",
+			len = sysfs_emit(buf, "%s\n",
 				      session->discovery_parent_type);
 		else
-			len = sprintf(buf, "\n");
+			len = sysfs_emit(buf, "\n");
 		break;
 	default:
 		return -ENOSYS;
@@ -3474,16 +3493,16 @@
 	case ISCSI_PARAM_CONN_ADDRESS:
 	case ISCSI_HOST_PARAM_IPADDRESS:
 		if (sin)
-			len = sprintf(buf, "%pI4\n", &sin->sin_addr.s_addr);
+			len = sysfs_emit(buf, "%pI4\n", &sin->sin_addr.s_addr);
 		else
-			len = sprintf(buf, "%pI6\n", &sin6->sin6_addr);
+			len = sysfs_emit(buf, "%pI6\n", &sin6->sin6_addr);
 		break;
 	case ISCSI_PARAM_CONN_PORT:
 	case ISCSI_PARAM_LOCAL_PORT:
 		if (sin)
-			len = sprintf(buf, "%hu\n", be16_to_cpu(sin->sin_port));
+			len = sysfs_emit(buf, "%hu\n", be16_to_cpu(sin->sin_port));
 		else
-			len = sprintf(buf, "%hu\n",
+			len = sysfs_emit(buf, "%hu\n",
 				      be16_to_cpu(sin6->sin6_port));
 		break;
 	default:
@@ -3502,88 +3521,88 @@
 
 	switch(param) {
 	case ISCSI_PARAM_PING_TMO:
-		len = sprintf(buf, "%u\n", conn->ping_timeout);
+		len = sysfs_emit(buf, "%u\n", conn->ping_timeout);
 		break;
 	case ISCSI_PARAM_RECV_TMO:
-		len = sprintf(buf, "%u\n", conn->recv_timeout);
+		len = sysfs_emit(buf, "%u\n", conn->recv_timeout);
 		break;
 	case ISCSI_PARAM_MAX_RECV_DLENGTH:
-		len = sprintf(buf, "%u\n", conn->max_recv_dlength);
+		len = sysfs_emit(buf, "%u\n", conn->max_recv_dlength);
 		break;
 	case ISCSI_PARAM_MAX_XMIT_DLENGTH:
-		len = sprintf(buf, "%u\n", conn->max_xmit_dlength);
+		len = sysfs_emit(buf, "%u\n", conn->max_xmit_dlength);
 		break;
 	case ISCSI_PARAM_HDRDGST_EN:
-		len = sprintf(buf, "%d\n", conn->hdrdgst_en);
+		len = sysfs_emit(buf, "%d\n", conn->hdrdgst_en);
 		break;
 	case ISCSI_PARAM_DATADGST_EN:
-		len = sprintf(buf, "%d\n", conn->datadgst_en);
+		len = sysfs_emit(buf, "%d\n", conn->datadgst_en);
 		break;
 	case ISCSI_PARAM_IFMARKER_EN:
-		len = sprintf(buf, "%d\n", conn->ifmarker_en);
+		len = sysfs_emit(buf, "%d\n", conn->ifmarker_en);
 		break;
 	case ISCSI_PARAM_OFMARKER_EN:
-		len = sprintf(buf, "%d\n", conn->ofmarker_en);
+		len = sysfs_emit(buf, "%d\n", conn->ofmarker_en);
 		break;
 	case ISCSI_PARAM_EXP_STATSN:
-		len = sprintf(buf, "%u\n", conn->exp_statsn);
+		len = sysfs_emit(buf, "%u\n", conn->exp_statsn);
 		break;
 	case ISCSI_PARAM_PERSISTENT_PORT:
-		len = sprintf(buf, "%d\n", conn->persistent_port);
+		len = sysfs_emit(buf, "%d\n", conn->persistent_port);
 		break;
 	case ISCSI_PARAM_PERSISTENT_ADDRESS:
-		len = sprintf(buf, "%s\n", conn->persistent_address);
+		len = sysfs_emit(buf, "%s\n", conn->persistent_address);
 		break;
 	case ISCSI_PARAM_STATSN:
-		len = sprintf(buf, "%u\n", conn->statsn);
+		len = sysfs_emit(buf, "%u\n", conn->statsn);
 		break;
 	case ISCSI_PARAM_MAX_SEGMENT_SIZE:
-		len = sprintf(buf, "%u\n", conn->max_segment_size);
+		len = sysfs_emit(buf, "%u\n", conn->max_segment_size);
 		break;
 	case ISCSI_PARAM_KEEPALIVE_TMO:
-		len = sprintf(buf, "%u\n", conn->keepalive_tmo);
+		len = sysfs_emit(buf, "%u\n", conn->keepalive_tmo);
 		break;
 	case ISCSI_PARAM_LOCAL_PORT:
-		len = sprintf(buf, "%u\n", conn->local_port);
+		len = sysfs_emit(buf, "%u\n", conn->local_port);
 		break;
 	case ISCSI_PARAM_TCP_TIMESTAMP_STAT:
-		len = sprintf(buf, "%u\n", conn->tcp_timestamp_stat);
+		len = sysfs_emit(buf, "%u\n", conn->tcp_timestamp_stat);
 		break;
 	case ISCSI_PARAM_TCP_NAGLE_DISABLE:
-		len = sprintf(buf, "%u\n", conn->tcp_nagle_disable);
+		len = sysfs_emit(buf, "%u\n", conn->tcp_nagle_disable);
 		break;
 	case ISCSI_PARAM_TCP_WSF_DISABLE:
-		len = sprintf(buf, "%u\n", conn->tcp_wsf_disable);
+		len = sysfs_emit(buf, "%u\n", conn->tcp_wsf_disable);
 		break;
 	case ISCSI_PARAM_TCP_TIMER_SCALE:
-		len = sprintf(buf, "%u\n", conn->tcp_timer_scale);
+		len = sysfs_emit(buf, "%u\n", conn->tcp_timer_scale);
 		break;
 	case ISCSI_PARAM_TCP_TIMESTAMP_EN:
-		len = sprintf(buf, "%u\n", conn->tcp_timestamp_en);
+		len = sysfs_emit(buf, "%u\n", conn->tcp_timestamp_en);
 		break;
 	case ISCSI_PARAM_IP_FRAGMENT_DISABLE:
-		len = sprintf(buf, "%u\n", conn->fragment_disable);
+		len = sysfs_emit(buf, "%u\n", conn->fragment_disable);
 		break;
 	case ISCSI_PARAM_IPV4_TOS:
-		len = sprintf(buf, "%u\n", conn->ipv4_tos);
+		len = sysfs_emit(buf, "%u\n", conn->ipv4_tos);
 		break;
 	case ISCSI_PARAM_IPV6_TC:
-		len = sprintf(buf, "%u\n", conn->ipv6_traffic_class);
+		len = sysfs_emit(buf, "%u\n", conn->ipv6_traffic_class);
 		break;
 	case ISCSI_PARAM_IPV6_FLOW_LABEL:
-		len = sprintf(buf, "%u\n", conn->ipv6_flow_label);
+		len = sysfs_emit(buf, "%u\n", conn->ipv6_flow_label);
 		break;
 	case ISCSI_PARAM_IS_FW_ASSIGNED_IPV6:
-		len = sprintf(buf, "%u\n", conn->is_fw_assigned_ipv6);
+		len = sysfs_emit(buf, "%u\n", conn->is_fw_assigned_ipv6);
 		break;
 	case ISCSI_PARAM_TCP_XMIT_WSF:
-		len = sprintf(buf, "%u\n", conn->tcp_xmit_wsf);
+		len = sysfs_emit(buf, "%u\n", conn->tcp_xmit_wsf);
 		break;
 	case ISCSI_PARAM_TCP_RECV_WSF:
-		len = sprintf(buf, "%u\n", conn->tcp_recv_wsf);
+		len = sysfs_emit(buf, "%u\n", conn->tcp_recv_wsf);
 		break;
 	case ISCSI_PARAM_LOCAL_IPADDR:
-		len = sprintf(buf, "%s\n", conn->local_ipaddr);
+		len = sysfs_emit(buf, "%s\n", conn->local_ipaddr);
 		break;
 	default:
 		return -ENOSYS;
@@ -3601,13 +3620,13 @@
 
 	switch (param) {
 	case ISCSI_HOST_PARAM_NETDEV_NAME:
-		len = sprintf(buf, "%s\n", ihost->netdev);
+		len = sysfs_emit(buf, "%s\n", ihost->netdev);
 		break;
 	case ISCSI_HOST_PARAM_HWADDRESS:
-		len = sprintf(buf, "%s\n", ihost->hwaddress);
+		len = sysfs_emit(buf, "%s\n", ihost->hwaddress);
 		break;
 	case ISCSI_HOST_PARAM_INITIATOR_NAME:
-		len = sprintf(buf, "%s\n", ihost->initiatorname);
+		len = sysfs_emit(buf, "%s\n", ihost->initiatorname);
 		break;
 	default:
 		return -ENOSYS;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/libsas/sas_ata.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/libsas/sas_ata.c
@@ -200,15 +200,17 @@
 		memcpy(task->ata_task.atapi_packet, qc->cdb, qc->dev->cdb_len);
 		task->total_xfer_len = qc->nbytes;
 		task->num_scatter = qc->n_elem;
+		task->data_dir = qc->dma_dir;
+	} else if (!ata_is_data(qc->tf.protocol)) {
+		task->data_dir = DMA_NONE;
 	} else {
 		for_each_sg(qc->sg, sg, qc->n_elem, si)
 			xfer += sg_dma_len(sg);
 
 		task->total_xfer_len = xfer;
 		task->num_scatter = si;
+		task->data_dir = qc->dma_dir;
 	}
-
-	task->data_dir = qc->dma_dir;
 	task->scatter = qc->sg;
 	task->ata_task.retry_count = 1;
 	task->task_state_flags = SAS_TASK_STATE_PENDING;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/libsas/sas_discover.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/libsas/sas_discover.c
@@ -81,12 +81,21 @@
 		else
 			dev->dev_type = SAS_SATA_DEV;
 		dev->tproto = SAS_PROTOCOL_SATA;
-	} else {
+	} else if (port->oob_mode == SAS_OOB_MODE) {
 		struct sas_identify_frame *id =
 			(struct sas_identify_frame *) dev->frame_rcvd;
 		dev->dev_type = id->dev_type;
 		dev->iproto = id->initiator_bits;
 		dev->tproto = id->target_bits;
+	} else {
+		/* If the oob mode is OOB_NOT_CONNECTED, the port is
+		 * disconnected due to race with PHY down. We cannot
+		 * continue to discover this port
+		 */
+		sas_put_device(dev);
+		pr_warn("Port %016llx is disconnected when discovering\n",
+			SAS_ADDR(port->attached_sas_addr));
+		return -ENODEV;
 	}
 
 	sas_init_dev(dev);
@@ -173,10 +182,11 @@
 		pr_warn("driver on host %s cannot handle device %llx, error:%d\n",
 			dev_name(sas_ha->dev),
 			SAS_ADDR(dev->sas_addr), res);
+		return res;
 	}
 	set_bit(SAS_DEV_FOUND, &dev->state);
 	kref_get(&dev->kref);
-	return res;
+	return 0;
 }
 
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/libsas/sas_expander.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/libsas/sas_expander.c
@@ -85,7 +85,7 @@
 		res = i->dft->lldd_execute_task(task, GFP_KERNEL);
 
 		if (res) {
-			del_timer(&task->slow_task->timer);
+			del_timer_sync(&task->slow_task->timer);
 			pr_notice("executing SMP task failed:%d\n", res);
 			break;
 		}
@@ -256,8 +256,7 @@
 	/* help some expanders that fail to zero sas_address in the 'no
 	 * device' case
 	 */
-	if (phy->attached_dev_type == SAS_PHY_UNUSED ||
-	    phy->linkrate < SAS_LINK_RATE_1_5_GBPS)
+	if (phy->attached_dev_type == SAS_PHY_UNUSED)
 		memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE);
 	else
 		memcpy(phy->attached_sas_addr, dr->attached_sas_addr, SAS_ADDR_SIZE);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/libsas/sas_internal.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/libsas/sas_internal.h
@@ -111,6 +111,20 @@
 		func, dev->parent ? "exp-attached" :
 		"direct-attached",
 		SAS_ADDR(dev->sas_addr), err);
+
+	/*
+	 * If the device probe failed, the expander phy attached address
+	 * needs to be reset so that the phy will not be treated as flutter
+	 * in the next revalidation
+	 */
+	if (dev->parent && !dev_is_expander(dev->dev_type)) {
+		struct sas_phy *phy = dev->phy;
+		struct domain_device *parent = dev->parent;
+		struct ex_phy *ex_phy = &parent->ex_dev.ex_phy[phy->number];
+
+		memset(ex_phy->attached_sas_addr, 0, SAS_ADDR_SIZE);
+	}
+
 	sas_unregister_dev(dev->port, dev);
 }
 
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/libsas/sas_port.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/libsas/sas_port.c
@@ -25,7 +25,7 @@
 
 static void sas_resume_port(struct asd_sas_phy *phy)
 {
-	struct domain_device *dev;
+	struct domain_device *dev, *n;
 	struct asd_sas_port *port = phy->port;
 	struct sas_ha_struct *sas_ha = phy->ha;
 	struct sas_internal *si = to_sas_internal(sas_ha->core.shost->transportt);
@@ -44,7 +44,7 @@
 	 * 1/ presume every device came back
 	 * 2/ force the next revalidation to check all expander phys
 	 */
-	list_for_each_entry(dev, &port->dev_list, dev_list_node) {
+	list_for_each_entry_safe(dev, n, &port->dev_list, dev_list_node) {
 		int i, rc;
 
 		rc = sas_notify_lldd_dev_found(dev);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/libsas/sas_scsi_host.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/libsas/sas_scsi_host.c
@@ -466,6 +466,9 @@
 	struct sas_internal *i = to_sas_internal(host->transportt);
 	unsigned long flags;
 
+	if (current != host->ehandler)
+		return FAILED;
+
 	if (!i->dft->lldd_abort_task)
 		return FAILED;
 
@@ -911,6 +914,14 @@
 		blk_abort_request(sc->request);
 }
 
+int sas_slave_alloc(struct scsi_device *sdev)
+{
+	if (dev_is_sata(sdev_to_domain_dev(sdev)) && sdev->lun)
+		return -ENXIO;
+
+	return 0;
+}
+
 void sas_target_destroy(struct scsi_target *starget)
 {
 	struct domain_device *found_dev = starget->hostdata;
@@ -957,5 +968,6 @@
 EXPORT_SYMBOL_GPL(sas_phy_reset);
 EXPORT_SYMBOL_GPL(sas_eh_device_reset_handler);
 EXPORT_SYMBOL_GPL(sas_eh_target_reset_handler);
+EXPORT_SYMBOL_GPL(sas_slave_alloc);
 EXPORT_SYMBOL_GPL(sas_target_destroy);
 EXPORT_SYMBOL_GPL(sas_ioctl);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/lpfc/lpfc.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/lpfc/lpfc.h
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term *
  * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.     *
  * Copyright (C) 2004-2016 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
@@ -32,6 +32,7 @@
 struct lpfc_sli2_slim;
 
 #define ELX_MODEL_NAME_SIZE	80
+#define ELX_FW_NAME_SIZE	84
 
 #define LPFC_PCI_DEV_LP		0x1
 #define LPFC_PCI_DEV_OC		0x2
@@ -262,7 +263,6 @@
 	uint32_t elsRcvPRLI;
 	uint32_t elsRcvLIRR;
 	uint32_t elsRcvRLS;
-	uint32_t elsRcvRPS;
 	uint32_t elsRcvRPL;
 	uint32_t elsRcvRRQ;
 	uint32_t elsRcvRTV;
@@ -377,6 +377,7 @@
 #define FC_VPORT_LOGO_RCVD      0x200    /* LOGO received on vport */
 #define FC_RSCN_DISCOVERY       0x400	 /* Auth all devices after RSCN */
 #define FC_LOGO_RCVD_DID_CHNG   0x800    /* FDISC on phys port detect DID chng*/
+#define FC_PT2PT_NO_NVME        0x1000   /* Don't send NVME PRLI */
 #define FC_SCSI_SCAN_TMO        0x4000	 /* scsi scan timer running */
 #define FC_ABORT_DISCOVERY      0x8000	 /* we want to abort discovery */
 #define FC_NDISC_ACTIVE         0x10000	 /* NPort discovery active */
@@ -605,6 +606,12 @@
 	spinlock_t lock;	/* lock for expedite pool */
 };
 
+enum ras_state {
+	INACTIVE,
+	REG_INPROGRESS,
+	ACTIVE
+};
+
 struct lpfc_ras_fwlog {
 	uint8_t *fwlog_buff;
 	uint32_t fw_buffcount; /* Buffer size posted to FW */
@@ -621,7 +628,7 @@
 	bool ras_enabled;   /* Ras Enabled for the function */
 #define LPFC_RAS_DISABLE_LOGGING 0x00
 #define LPFC_RAS_ENABLE_LOGGING 0x01
-	bool ras_active;    /* RAS logging running state */
+	enum ras_state state;    /* RAS logging running state */
 };
 
 struct lpfc_hba {
@@ -725,6 +732,7 @@
 #define HBA_FCOE_MODE		0x4 /* HBA function in FCoE Mode */
 #define HBA_SP_QUEUE_EVT	0x8 /* Slow-path qevt posted to worker thread*/
 #define HBA_POST_RECEIVE_BUFFER 0x10 /* Rcv buffers need to be posted */
+#define HBA_PERSISTENT_TOPO	0x20 /* Persistent topology support in hba */
 #define ELS_XRI_ABORT_EVENT	0x40
 #define ASYNC_EVENT		0x80
 #define LINK_DISABLED		0x100 /* Link disabled by user */
@@ -735,14 +743,15 @@
 #define HBA_DEVLOSS_TMO         0x2000 /* HBA in devloss timeout */
 #define HBA_RRQ_ACTIVE		0x4000 /* process the rrq active list */
 #define HBA_IOQ_FLUSH		0x8000 /* FCP/NVME I/O queues being flushed */
-#define HBA_FW_DUMP_OP		0x10000 /* Skips fn reset before FW dump */
 #define HBA_RECOVERABLE_UE	0x20000 /* Firmware supports recoverable UE */
 #define HBA_FORCED_LINK_SPEED	0x40000 /*
 					 * Firmware supports Forced Link Speed
 					 * capability
 					 */
 #define HBA_FLOGI_ISSUED	0x100000 /* FLOGI was issued */
+#define HBA_DEFER_FLOGI		0x800000 /* Defer FLOGI till read_sparm cmpl */
 
+	struct completion *fw_dump_cmpl; /* cmpl event tracker for fw_dump */
 	uint32_t fcp_ring_in_use; /* When polling test if intr-hndlr active*/
 	struct lpfc_dmabuf slim2p;
 
@@ -830,6 +839,7 @@
 	uint32_t cfg_fcp_mq_threshold;
 	uint32_t cfg_hdw_queue;
 	uint32_t cfg_irq_chann;
+	uint32_t cfg_irq_numa;
 	uint32_t cfg_suppress_rsp;
 	uint32_t cfg_nvme_oas;
 	uint32_t cfg_nvme_embed_cmd;
@@ -869,10 +879,19 @@
 	uint32_t cfg_hostmem_hgp;
 	uint32_t cfg_log_verbose;
 	uint32_t cfg_enable_fc4_type;
+#define LPFC_ENABLE_FCP  1
+#define LPFC_ENABLE_NVME 2
+#define LPFC_ENABLE_BOTH 3
+#if (IS_ENABLED(CONFIG_NVME_FC))
+#define LPFC_MAX_ENBL_FC4_TYPE LPFC_ENABLE_BOTH
+#define LPFC_DEF_ENBL_FC4_TYPE LPFC_ENABLE_BOTH
+#else
+#define LPFC_MAX_ENBL_FC4_TYPE LPFC_ENABLE_FCP
+#define LPFC_DEF_ENBL_FC4_TYPE LPFC_ENABLE_FCP
+#endif
 	uint32_t cfg_aer_support;
 	uint32_t cfg_sriov_nr_virtfn;
 	uint32_t cfg_request_firmware_upgrade;
-	uint32_t cfg_iocb_cnt;
 	uint32_t cfg_suppress_link_up;
 	uint32_t cfg_rrq_xri_bitmap_sz;
 	uint32_t cfg_delay_discovery;
@@ -891,9 +910,6 @@
 	uint32_t cfg_ras_fwlog_func;
 	uint32_t cfg_enable_bbcr;	/* Enable BB Credit Recovery */
 	uint32_t cfg_enable_dpp;	/* Enable Direct Packet Push */
-#define LPFC_ENABLE_FCP  1
-#define LPFC_ENABLE_NVME 2
-#define LPFC_ENABLE_BOTH 3
 	uint32_t cfg_enable_pbde;
 	struct nvmet_fc_target_port *targetport;
 	lpfc_vpd_t vpd;		/* vital product data */
@@ -990,7 +1006,6 @@
 	struct dma_pool *lpfc_drb_pool; /* data receive buffer pool */
 	struct dma_pool *lpfc_nvmet_drb_pool; /* data receive buffer pool */
 	struct dma_pool *lpfc_hbq_pool;	/* SLI3 hbq buffer pool */
-	struct dma_pool *txrdy_payload_pool;
 	struct dma_pool *lpfc_cmd_rsp_buf_pool;
 	struct lpfc_dma_pool lpfc_mbuf_safety_pool;
 
@@ -1029,7 +1044,6 @@
 	unsigned long bit_flags;
 #define	FABRIC_COMANDS_BLOCKED	0
 	atomic_t num_rsrc_err;
-	atomic_t num_cmd_success;
 	unsigned long last_rsrc_error_time;
 	unsigned long last_ramp_down_time;
 #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
@@ -1055,6 +1069,7 @@
 #ifdef LPFC_HDWQ_LOCK_STAT
 	struct dentry *debug_lockstat;
 #endif
+	struct dentry *debug_ras_log;
 	atomic_t nvmeio_trc_cnt;
 	uint32_t nvmeio_trc_size;
 	uint32_t nvmeio_trc_output_idx;
@@ -1209,6 +1224,15 @@
 	uint64_t ktime_seg10_min;
 	uint64_t ktime_seg10_max;
 #endif
+
+	struct hlist_node cpuhp;	/* used for cpuhp per hba callback */
+	struct timer_list cpuhp_poll_timer;
+	struct list_head poll_list;	/* slowpath eq polling list */
+#define LPFC_POLL_HB	1		/* slowpath heartbeat */
+#define LPFC_POLL_FASTPATH	0	/* called from fastpath */
+#define LPFC_POLL_SLOWPATH	1	/* called from slowpath */
+
+	char os_host_name[MAXHOSTNAMELEN];
 };
 
 static inline struct Scsi_Host *
@@ -1299,6 +1323,26 @@
 }
 
 /**
+ * lpfc_next_online_numa_cpu - Finds next online CPU on NUMA node
+ * @numa_mask: Pointer to phba's numa_mask member.
+ * @start: starting cpu index
+ *
+ * Note: If no valid cpu found, then nr_cpu_ids is returned.
+ *
+ **/
+static inline unsigned int
+lpfc_next_online_numa_cpu(const struct cpumask *numa_mask, unsigned int start)
+{
+	unsigned int cpu_it;
+
+	for_each_cpu_wrap(cpu_it, numa_mask, start) {
+		if (cpu_online(cpu_it))
+			break;
+	}
+
+	return cpu_it;
+}
+/**
  * lpfc_sli4_mod_hba_eq_delay - update EQ delay
  * @phba: Pointer to HBA context object.
  * @q: The Event Queue to update.
@@ -1317,3 +1361,32 @@
 	writel(reg_data.word0, phba->sli4_hba.u.if_type2.EQDregaddr);
 	eq->q_mode = delay;
 }
+
+
+/*
+ * Macro that declares tables and a routine to perform enum type to
+ * ascii string lookup.
+ *
+ * Defines a <key,value> table for an enum. Uses xxx_INIT defines for
+ * the enum to populate the table.  Macro defines a routine (named
+ * by caller) that will search all elements of the table for the key
+ * and return the name string if found or "Unrecognized" if not found.
+ */
+#define DECLARE_ENUM2STR_LOOKUP(routine, enum_name, enum_init)		\
+static struct {								\
+	enum enum_name		value;					\
+	char			*name;					\
+} fc_##enum_name##_e2str_names[] = enum_init;				\
+static const char *routine(enum enum_name table_key)			\
+{									\
+	int i;								\
+	char *name = "Unrecognized";					\
+									\
+	for (i = 0; i < ARRAY_SIZE(fc_##enum_name##_e2str_names); i++) {\
+		if (fc_##enum_name##_e2str_names[i].value == table_key) {\
+			name = fc_##enum_name##_e2str_names[i].name;	\
+			break;						\
+		}							\
+	}								\
+	return name;							\
+}
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/lpfc/lpfc_attr.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/lpfc/lpfc_attr.c
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term *
  * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.  *
  * Copyright (C) 2004-2016 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
@@ -176,7 +176,6 @@
 	int i;
 	int len = 0;
 	char tmp[LPFC_MAX_NVME_INFO_TMP_LEN] = {0};
-	unsigned long iflags = 0;
 
 	if (!(vport->cfg_enable_fc4_type & LPFC_ENABLE_NVME)) {
 		len = scnprintf(buf, PAGE_SIZE, "NVME Disabled\n");
@@ -347,7 +346,6 @@
 	if (strlcat(buf, "\nNVME Initiator Enabled\n", PAGE_SIZE) >= PAGE_SIZE)
 		goto buffer_done;
 
-	rcu_read_lock();
 	scnprintf(tmp, sizeof(tmp),
 		  "XRI Dist lpfc%d Total %d IO %d ELS %d\n",
 		  phba->brd_no,
@@ -355,7 +353,7 @@
 		  phba->sli4_hba.io_xri_max,
 		  lpfc_sli4_get_els_iocb_cnt(phba));
 	if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
-		goto rcu_unlock_buf_done;
+		goto buffer_done;
 
 	/* Port state is only one of two values for now. */
 	if (localport->port_id)
@@ -371,15 +369,17 @@
 		  wwn_to_u64(vport->fc_nodename.u.wwn),
 		  localport->port_id, statep);
 	if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
-		goto rcu_unlock_buf_done;
+		goto buffer_done;
+
+	spin_lock_irq(shost->host_lock);
 
 	list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
 		nrport = NULL;
-		spin_lock_irqsave(&vport->phba->hbalock, iflags);
+		spin_lock(&vport->phba->hbalock);
 		rport = lpfc_ndlp_get_nrport(ndlp);
 		if (rport)
 			nrport = rport->remoteport;
-		spin_unlock_irqrestore(&vport->phba->hbalock, iflags);
+		spin_unlock(&vport->phba->hbalock);
 		if (!nrport)
 			continue;
 
@@ -398,39 +398,39 @@
 
 		/* Tab in to show lport ownership. */
 		if (strlcat(buf, "NVME RPORT       ", PAGE_SIZE) >= PAGE_SIZE)
-			goto rcu_unlock_buf_done;
+			goto unlock_buf_done;
 		if (phba->brd_no >= 10) {
 			if (strlcat(buf, " ", PAGE_SIZE) >= PAGE_SIZE)
-				goto rcu_unlock_buf_done;
+				goto unlock_buf_done;
 		}
 
 		scnprintf(tmp, sizeof(tmp), "WWPN x%llx ",
 			  nrport->port_name);
 		if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
-			goto rcu_unlock_buf_done;
+			goto unlock_buf_done;
 
 		scnprintf(tmp, sizeof(tmp), "WWNN x%llx ",
 			  nrport->node_name);
 		if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
-			goto rcu_unlock_buf_done;
+			goto unlock_buf_done;
 
 		scnprintf(tmp, sizeof(tmp), "DID x%06x ",
 			  nrport->port_id);
 		if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
-			goto rcu_unlock_buf_done;
+			goto unlock_buf_done;
 
 		/* An NVME rport can have multiple roles. */
 		if (nrport->port_role & FC_PORT_ROLE_NVME_INITIATOR) {
 			if (strlcat(buf, "INITIATOR ", PAGE_SIZE) >= PAGE_SIZE)
-				goto rcu_unlock_buf_done;
+				goto unlock_buf_done;
 		}
 		if (nrport->port_role & FC_PORT_ROLE_NVME_TARGET) {
 			if (strlcat(buf, "TARGET ", PAGE_SIZE) >= PAGE_SIZE)
-				goto rcu_unlock_buf_done;
+				goto unlock_buf_done;
 		}
 		if (nrport->port_role & FC_PORT_ROLE_NVME_DISCOVERY) {
 			if (strlcat(buf, "DISCSRVC ", PAGE_SIZE) >= PAGE_SIZE)
-				goto rcu_unlock_buf_done;
+				goto unlock_buf_done;
 		}
 		if (nrport->port_role & ~(FC_PORT_ROLE_NVME_INITIATOR |
 					  FC_PORT_ROLE_NVME_TARGET |
@@ -438,14 +438,14 @@
 			scnprintf(tmp, sizeof(tmp), "UNKNOWN ROLE x%x",
 				  nrport->port_role);
 			if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
-				goto rcu_unlock_buf_done;
+				goto unlock_buf_done;
 		}
 
 		scnprintf(tmp, sizeof(tmp), "%s\n", statep);
 		if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
-			goto rcu_unlock_buf_done;
+			goto unlock_buf_done;
 	}
-	rcu_read_unlock();
+	spin_unlock_irq(shost->host_lock);
 
 	if (!lport)
 		goto buffer_done;
@@ -505,11 +505,11 @@
 		  atomic_read(&lport->cmpl_fcp_err));
 	strlcat(buf, tmp, PAGE_SIZE);
 
-	/* RCU is already unlocked. */
+	/* host_lock is already unlocked. */
 	goto buffer_done;
 
- rcu_unlock_buf_done:
-	rcu_read_unlock();
+ unlock_buf_done:
+	spin_unlock_irq(shost->host_lock);
 
  buffer_done:
 	len = strnlen(buf, PAGE_SIZE);
@@ -1145,6 +1145,9 @@
 	pmboxq->u.mb.mbxCommand = MBX_DOWN_LINK;
 	pmboxq->u.mb.mbxOwner = OWN_HOST;
 
+	if ((vport->fc_flag & FC_PT2PT) && (vport->fc_flag & FC_PT2PT_NO_NVME))
+		vport->fc_flag &= ~FC_PT2PT_NO_NVME;
+
 	mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, LPFC_MBOX_TMO * 2);
 
 	if ((mbxstatus == MBX_SUCCESS) &&
@@ -1475,8 +1478,9 @@
 	int i;
 
 	msleep(100);
-	lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
-		   &portstat_reg.word0);
+	if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
+		       &portstat_reg.word0))
+		return -EIO;
 
 	/* verify if privileged for the request operation */
 	if (!bf_get(lpfc_sliport_status_rn, &portstat_reg) &&
@@ -1486,8 +1490,9 @@
 	/* wait for the SLI port firmware ready after firmware reset */
 	for (i = 0; i < LPFC_FW_RESET_MAXIMUM_WAIT_10MS_CNT; i++) {
 		msleep(10);
-		lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
-			   &portstat_reg.word0);
+		if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
+			       &portstat_reg.word0))
+			continue;
 		if (!bf_get(lpfc_sliport_status_err, &portstat_reg))
 			continue;
 		if (!bf_get(lpfc_sliport_status_rn, &portstat_reg))
@@ -1537,25 +1542,25 @@
 	before_fc_flag = phba->pport->fc_flag;
 	sriov_nr_virtfn = phba->cfg_sriov_nr_virtfn;
 
-	/* Disable SR-IOV virtual functions if enabled */
-	if (phba->cfg_sriov_nr_virtfn) {
-		pci_disable_sriov(pdev);
-		phba->cfg_sriov_nr_virtfn = 0;
-	}
+	if (opcode == LPFC_FW_DUMP) {
+		init_completion(&online_compl);
+		phba->fw_dump_cmpl = &online_compl;
+	} else {
+		/* Disable SR-IOV virtual functions if enabled */
+		if (phba->cfg_sriov_nr_virtfn) {
+			pci_disable_sriov(pdev);
+			phba->cfg_sriov_nr_virtfn = 0;
+		}
 
-	if (opcode == LPFC_FW_DUMP)
-		phba->hba_flag |= HBA_FW_DUMP_OP;
+		status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
 
-	status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
+		if (status != 0)
+			return status;
 
-	if (status != 0) {
-		phba->hba_flag &= ~HBA_FW_DUMP_OP;
-		return status;
+		/* wait for the device to be quiesced before firmware reset */
+		msleep(100);
 	}
 
-	/* wait for the device to be quiesced before firmware reset */
-	msleep(100);
-
 	reg_val = readl(phba->sli4_hba.conf_regs_memmap_p +
 			LPFC_CTL_PDEV_CTL_OFFSET);
 
@@ -1584,24 +1589,42 @@
 		lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
 				"3153 Fail to perform the requested "
 				"access: x%x\n", reg_val);
+		if (phba->fw_dump_cmpl)
+			phba->fw_dump_cmpl = NULL;
 		return rc;
 	}
 
 	/* keep the original port state */
-	if (before_fc_flag & FC_OFFLINE_MODE)
-		goto out;
-
-	init_completion(&online_compl);
-	job_posted = lpfc_workq_post_event(phba, &status, &online_compl,
-					   LPFC_EVT_ONLINE);
-	if (!job_posted)
+	if (before_fc_flag & FC_OFFLINE_MODE) {
+		if (phba->fw_dump_cmpl)
+			phba->fw_dump_cmpl = NULL;
 		goto out;
+	}
 
-	wait_for_completion(&online_compl);
+	/* Firmware dump will trigger an HA_ERATT event, and
+	 * lpfc_handle_eratt_s4 routine already handles bringing the port back
+	 * online.
+	 */
+	if (opcode == LPFC_FW_DUMP) {
+		wait_for_completion(phba->fw_dump_cmpl);
+	} else  {
+		init_completion(&online_compl);
+		job_posted = lpfc_workq_post_event(phba, &status, &online_compl,
+						   LPFC_EVT_ONLINE);
+		if (!job_posted)
+			goto out;
 
+		wait_for_completion(&online_compl);
+	}
 out:
 	/* in any case, restore the virtual functions enabled as before */
 	if (sriov_nr_virtfn) {
+		/* If fw_dump was performed, first disable to clean up */
+		if (opcode == LPFC_FW_DUMP) {
+			pci_disable_sriov(pdev);
+			phba->cfg_sriov_nr_virtfn = 0;
+		}
+
 		sriov_err =
 			lpfc_sli_probe_sriov_nr_virtfn(phba, sriov_nr_virtfn);
 		if (!sriov_err)
@@ -1642,7 +1665,7 @@
 {
 	LPFC_MBOXQ_t *mbox = NULL;
 	unsigned long val = 0;
-	char *pval = 0;
+	char *pval = NULL;
 	int rc = 0;
 
 	if (!strncmp("enable", buff_out,
@@ -1691,8 +1714,7 @@
 		lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
 				"0071 Set trunk mode failed with status: %d",
 				rc);
-	if (rc != MBX_TIMEOUT)
-		mempool_free(mbox, phba->mbox_mem_pool);
+	mempool_free(mbox, phba->mbox_mem_pool);
 
 	return 0;
 }
@@ -3533,6 +3555,31 @@
 LPFC_ATTR_R(suppress_link_up, LPFC_INITIALIZE_LINK, LPFC_INITIALIZE_LINK,
 		LPFC_DELAY_INIT_LINK_INDEFINITELY,
 		"Suppress Link Up at initialization");
+
+static ssize_t
+lpfc_pls_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct Scsi_Host  *shost = class_to_shost(dev);
+	struct lpfc_hba   *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
+
+	return scnprintf(buf, PAGE_SIZE, "%d\n",
+			 phba->sli4_hba.pc_sli4_params.pls);
+}
+static DEVICE_ATTR(pls, 0444,
+			 lpfc_pls_show, NULL);
+
+static ssize_t
+lpfc_pt_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct Scsi_Host  *shost = class_to_shost(dev);
+	struct lpfc_hba   *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
+
+	return scnprintf(buf, PAGE_SIZE, "%d\n",
+			 (phba->hba_flag & HBA_PERSISTENT_TOPO) ? 1 : 0);
+}
+static DEVICE_ATTR(pt, 0444,
+			 lpfc_pt_show, NULL);
+
 /*
 # lpfc_cnt: Number of IOCBs allocated for ELS, CT, and ABTS
 #       1 - (1024)
@@ -3580,9 +3627,6 @@
 static DEVICE_ATTR(txcmplq_hw, S_IRUGO,
 			 lpfc_txcmplq_hw_show, NULL);
 
-LPFC_ATTR_R(iocb_cnt, 2, 1, 5,
-	"Number of IOCBs alloc for ELS, CT, and ABTS: 1k to 5k IOCBs");
-
 /*
 # lpfc_nodev_tmo: If set, it will hold all I/O errors on devices that disappear
 # until the timer expires. Value range is [0,255]. Default value is 30.
@@ -3822,8 +3866,8 @@
  *                    3 - register both FCP and NVME
  * Supported values are [1,3]. Default value is 3
  */
-LPFC_ATTR_R(enable_fc4_type, LPFC_ENABLE_BOTH,
-	    LPFC_ENABLE_FCP, LPFC_ENABLE_BOTH,
+LPFC_ATTR_R(enable_fc4_type, LPFC_DEF_ENBL_FC4_TYPE,
+	    LPFC_ENABLE_FCP, LPFC_MAX_ENBL_FC4_TYPE,
 	    "Enable FC4 Protocol support - FCP / NVME");
 
 /*
@@ -3845,9 +3889,6 @@
 /*
 # lun_queue_depth:  This parameter is used to limit the number of outstanding
 # commands per FCP LUN. Value range is [1,512]. Default value is 30.
-# If this parameter value is greater than 1/8th the maximum number of exchanges
-# supported by the HBA port, then the lun queue depth will be reduced to
-# 1/8th the maximum number of exchanges.
 */
 LPFC_VPORT_ATTR_R(lun_queue_depth, 30, 1, 512,
 		  "Max number of FCP commands we can queue to a specific LUN");
@@ -4096,8 +4137,16 @@
 				val);
 			return -EINVAL;
 		}
-		if ((phba->pcidev->device == PCI_DEVICE_ID_LANCER_G6_FC ||
-		     phba->pcidev->device == PCI_DEVICE_ID_LANCER_G7_FC) &&
+		/*
+		 * The 'topology' is not a configurable parameter if :
+		 *   - persistent topology enabled
+		 *   - G7/G6 with no private loop support
+		 */
+
+		if ((phba->hba_flag & HBA_PERSISTENT_TOPO ||
+		     (!phba->sli4_hba.pc_sli4_params.pls &&
+		     (phba->pcidev->device == PCI_DEVICE_ID_LANCER_G6_FC ||
+		     phba->pcidev->device == PCI_DEVICE_ID_LANCER_G7_FC))) &&
 		    val == 4) {
 			lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
 				"3114 Loop mode not supported\n");
@@ -5298,7 +5347,7 @@
 			len += scnprintf(buf + len, PAGE_SIZE - len,
 					"CPU %02d not present\n",
 					phba->sli4_hba.curr_disp_cpu);
-		else if (cpup->irq == LPFC_VECTOR_MAP_EMPTY) {
+		else if (cpup->eq == LPFC_VECTOR_MAP_EMPTY) {
 			if (cpup->hdwq == LPFC_VECTOR_MAP_EMPTY)
 				len += scnprintf(
 					buf + len, PAGE_SIZE - len,
@@ -5311,10 +5360,10 @@
 			else
 				len += scnprintf(
 					buf + len, PAGE_SIZE - len,
-					"CPU %02d EQ %04d hdwq %04d "
+					"CPU %02d EQ None hdwq %04d "
 					"physid %d coreid %d ht %d ua %d\n",
 					phba->sli4_hba.curr_disp_cpu,
-					cpup->eq, cpup->hdwq, cpup->phys_id,
+					cpup->hdwq, cpup->phys_id,
 					cpup->core_id,
 					(cpup->flag & LPFC_CPU_MAP_HYPER),
 					(cpup->flag & LPFC_CPU_MAP_UNASSIGN));
@@ -5329,7 +5378,7 @@
 					cpup->core_id,
 					(cpup->flag & LPFC_CPU_MAP_HYPER),
 					(cpup->flag & LPFC_CPU_MAP_UNASSIGN),
-					cpup->irq);
+					lpfc_get_irq(cpup->eq));
 			else
 				len += scnprintf(
 					buf + len, PAGE_SIZE - len,
@@ -5340,7 +5389,7 @@
 					cpup->core_id,
 					(cpup->flag & LPFC_CPU_MAP_HYPER),
 					(cpup->flag & LPFC_CPU_MAP_UNASSIGN),
-					cpup->irq);
+					lpfc_get_irq(cpup->eq));
 		}
 
 		phba->sli4_hba.curr_disp_cpu++;
@@ -5711,7 +5760,7 @@
  * the driver will advertise it supports to the SCSI layer.
  *
  *      0    = Set nr_hw_queues by the number of CPUs or HW queues.
- *      1,128 = Manually specify the maximum nr_hw_queue value to be set,
+ *      1,256 = Manually specify nr_hw_queue value to be advertised,
  *
  * Value range is [0,256]. Default value is 8.
  */
@@ -5729,30 +5778,130 @@
  * A hardware IO queue maps (qidx) to a specific driver CQ/WQ.
  *
  *      0    = Configure the number of hdw queues to the number of active CPUs.
- *      1,128 = Manually specify how many hdw queues to use.
+ *      1,256 = Manually specify how many hdw queues to use.
  *
- * Value range is [0,128]. Default value is 0.
+ * Value range is [0,256]. Default value is 0.
  */
 LPFC_ATTR_R(hdw_queue,
 	    LPFC_HBA_HDWQ_DEF,
 	    LPFC_HBA_HDWQ_MIN, LPFC_HBA_HDWQ_MAX,
 	    "Set the number of I/O Hardware Queues");
 
+static inline void
+lpfc_assign_default_irq_numa(struct lpfc_hba *phba)
+{
+#if IS_ENABLED(CONFIG_X86)
+	/* If AMD architecture, then default is LPFC_IRQ_CHANN_NUMA */
+	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
+		phba->cfg_irq_numa = 1;
+	else
+		phba->cfg_irq_numa = 0;
+#else
+	phba->cfg_irq_numa = 0;
+#endif
+}
+
 /*
  * lpfc_irq_chann: Set the number of IRQ vectors that are available
  * for Hardware Queues to utilize.  This also will map to the number
  * of EQ / MSI-X vectors the driver will create. This should never be
  * more than the number of Hardware Queues
  *
- *      0     = Configure number of IRQ Channels to the number of active CPUs.
- *      1,128 = Manually specify how many IRQ Channels to use.
+ *	0		= Configure number of IRQ Channels to:
+ *			  if AMD architecture, number of CPUs on HBA's NUMA node
+ *			  otherwise, number of active CPUs.
+ *	[1,256]		= Manually specify how many IRQ Channels to use.
  *
- * Value range is [0,128]. Default value is 0.
+ * Value range is [0,256]. Default value is [0].
  */
-LPFC_ATTR_R(irq_chann,
-	    LPFC_HBA_HDWQ_DEF,
-	    LPFC_HBA_HDWQ_MIN, LPFC_HBA_HDWQ_MAX,
-	    "Set the number of I/O IRQ Channels");
+static uint lpfc_irq_chann = LPFC_IRQ_CHANN_DEF;
+module_param(lpfc_irq_chann, uint, 0444);
+MODULE_PARM_DESC(lpfc_irq_chann, "Set number of interrupt vectors to allocate");
+
+/* lpfc_irq_chann_init - Set the hba irq_chann initial value
+ * @phba: lpfc_hba pointer.
+ * @val: contains the initial value
+ *
+ * Description:
+ * Validates the initial value is within range and assigns it to the
+ * adapter. If not in range, an error message is posted and the
+ * default value is assigned.
+ *
+ * Returns:
+ * zero if value is in range and is set
+ * -EINVAL if value was out of range
+ **/
+static int
+lpfc_irq_chann_init(struct lpfc_hba *phba, uint32_t val)
+{
+	const struct cpumask *numa_mask;
+
+	if (phba->cfg_use_msi != 2) {
+		lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+				"8532 use_msi = %u ignoring cfg_irq_numa\n",
+				phba->cfg_use_msi);
+		phba->cfg_irq_numa = 0;
+		phba->cfg_irq_chann = LPFC_IRQ_CHANN_MIN;
+		return 0;
+	}
+
+	/* Check if default setting was passed */
+	if (val == LPFC_IRQ_CHANN_DEF)
+		lpfc_assign_default_irq_numa(phba);
+
+	if (phba->cfg_irq_numa) {
+		numa_mask = &phba->sli4_hba.numa_mask;
+
+		if (cpumask_empty(numa_mask)) {
+			lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+					"8533 Could not identify NUMA node, "
+					"ignoring cfg_irq_numa\n");
+			phba->cfg_irq_numa = 0;
+			phba->cfg_irq_chann = LPFC_IRQ_CHANN_MIN;
+		} else {
+			phba->cfg_irq_chann = cpumask_weight(numa_mask);
+			lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+					"8543 lpfc_irq_chann set to %u "
+					"(numa)\n", phba->cfg_irq_chann);
+		}
+	} else {
+		if (val > LPFC_IRQ_CHANN_MAX) {
+			lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+					"8545 lpfc_irq_chann attribute cannot "
+					"be set to %u, allowed range is "
+					"[%u,%u]\n",
+					val,
+					LPFC_IRQ_CHANN_MIN,
+					LPFC_IRQ_CHANN_MAX);
+			phba->cfg_irq_chann = LPFC_IRQ_CHANN_MIN;
+			return -EINVAL;
+		}
+		phba->cfg_irq_chann = val;
+	}
+
+	return 0;
+}
+
+/**
+ * lpfc_irq_chann_show - Display value of irq_chann
+ * @dev: class converted to a Scsi_host structure.
+ * @attr: device attribute, not used.
+ * @buf: on return contains a string with the list sizes
+ *
+ * Returns: size of formatted string.
+ **/
+static ssize_t
+lpfc_irq_chann_show(struct device *dev, struct device_attribute *attr,
+		    char *buf)
+{
+	struct Scsi_Host *shost = class_to_shost(dev);
+	struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
+	struct lpfc_hba *phba = vport->phba;
+
+	return scnprintf(buf, PAGE_SIZE, "%u\n", phba->cfg_irq_chann);
+}
+
+static DEVICE_ATTR_RO(lpfc_irq_chann);
 
 /*
 # lpfc_enable_hba_reset: Allow or prevent HBA resets to the hardware.
@@ -5882,7 +6031,8 @@
 	len = scnprintf(buf, PAGE_SIZE, "SGL sz: %d  total SGEs: %d\n",
 		       phba->cfg_sg_dma_buf_size, phba->cfg_total_seg_cnt);
 
-	len += scnprintf(buf + len, PAGE_SIZE, "Cfg: %d  SCSI: %d  NVME: %d\n",
+	len += scnprintf(buf + len, PAGE_SIZE - len,
+			"Cfg: %d  SCSI: %d  NVME: %d\n",
 			phba->cfg_sg_seg_cnt, phba->cfg_scsi_seg_cnt,
 			phba->cfg_nvme_seg_cnt);
 	return len;
@@ -5933,7 +6083,53 @@
  *	[1-4] = Multiple of 1/4th Mb of host memory for FW logging
  * Value range [0..4]. Default value is 0
  */
-LPFC_ATTR_RW(ras_fwlog_buffsize, 0, 0, 4, "Host memory for FW logging");
+LPFC_ATTR(ras_fwlog_buffsize, 0, 0, 4, "Host memory for FW logging");
+lpfc_param_show(ras_fwlog_buffsize);
+
+static ssize_t
+lpfc_ras_fwlog_buffsize_set(struct lpfc_hba  *phba, uint val)
+{
+	int ret = 0;
+	enum ras_state state;
+
+	if (!lpfc_rangecheck(val, 0, 4))
+		return -EINVAL;
+
+	if (phba->cfg_ras_fwlog_buffsize == val)
+		return 0;
+
+	if (phba->cfg_ras_fwlog_func != PCI_FUNC(phba->pcidev->devfn))
+		return -EINVAL;
+
+	spin_lock_irq(&phba->hbalock);
+	state = phba->ras_fwlog.state;
+	spin_unlock_irq(&phba->hbalock);
+
+	if (state == REG_INPROGRESS) {
+		lpfc_printf_log(phba, KERN_ERR, LOG_SLI, "6147 RAS Logging "
+				"registration is in progress\n");
+		return -EBUSY;
+	}
+
+	/* For disable logging: stop the logs and free the DMA.
+	 * For ras_fwlog_buffsize size change we still need to free and
+	 * reallocate the DMA in lpfc_sli4_ras_fwlog_init.
+	 */
+	phba->cfg_ras_fwlog_buffsize = val;
+	if (state == ACTIVE) {
+		lpfc_ras_stop_fwlog(phba);
+		lpfc_sli4_ras_dma_free(phba);
+	}
+
+	lpfc_sli4_ras_init(phba);
+	if (phba->ras_fwlog.ras_enabled)
+		ret = lpfc_sli4_ras_fwlog_init(phba, phba->cfg_ras_fwlog_level,
+					       LPFC_RAS_ENABLE_LOGGING);
+	return ret;
+}
+
+lpfc_param_store(ras_fwlog_buffsize);
+static DEVICE_ATTR_RW(lpfc_ras_fwlog_buffsize);
 
 /*
  * lpfc_ras_fwlog_level: Firmware logging verbosity level
@@ -6071,8 +6267,9 @@
 	&dev_attr_lpfc_sriov_nr_virtfn,
 	&dev_attr_lpfc_req_fw_upgrade,
 	&dev_attr_lpfc_suppress_link_up,
-	&dev_attr_lpfc_iocb_cnt,
 	&dev_attr_iocb_hw,
+	&dev_attr_pls,
+	&dev_attr_pt,
 	&dev_attr_txq_hw,
 	&dev_attr_txcmplq_hw,
 	&dev_attr_lpfc_fips_level,
@@ -6608,15 +6805,19 @@
 	pmboxq->ctx_buf = NULL;
 	pmboxq->vport = vport;
 
-	if (vport->fc_flag & FC_OFFLINE_MODE)
+	if (vport->fc_flag & FC_OFFLINE_MODE) {
 		rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
-	else
-		rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
-
-	if (rc != MBX_SUCCESS) {
-		if (rc != MBX_TIMEOUT)
+		if (rc != MBX_SUCCESS) {
 			mempool_free(pmboxq, phba->mbox_mem_pool);
-		return NULL;
+			return NULL;
+		}
+	} else {
+		rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
+		if (rc != MBX_SUCCESS) {
+			if (rc != MBX_TIMEOUT)
+				mempool_free(pmboxq, phba->mbox_mem_pool);
+			return NULL;
+		}
 	}
 
 	memset(hs, 0, sizeof (struct fc_host_statistics));
@@ -6640,15 +6841,19 @@
 	pmboxq->ctx_buf = NULL;
 	pmboxq->vport = vport;
 
-	if (vport->fc_flag & FC_OFFLINE_MODE)
+	if (vport->fc_flag & FC_OFFLINE_MODE) {
 		rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
-	else
-		rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
-
-	if (rc != MBX_SUCCESS) {
-		if (rc != MBX_TIMEOUT)
+		if (rc != MBX_SUCCESS) {
 			mempool_free(pmboxq, phba->mbox_mem_pool);
-		return NULL;
+			return NULL;
+		}
+	} else {
+		rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
+		if (rc != MBX_SUCCESS) {
+			if (rc != MBX_TIMEOUT)
+				mempool_free(pmboxq, phba->mbox_mem_pool);
+			return NULL;
+		}
 	}
 
 	hs->link_failure_count = pmb->un.varRdLnk.linkFailureCnt;
@@ -6721,15 +6926,19 @@
 	pmboxq->vport = vport;
 
 	if ((vport->fc_flag & FC_OFFLINE_MODE) ||
-		(!(psli->sli_flag & LPFC_SLI_ACTIVE)))
+		(!(psli->sli_flag & LPFC_SLI_ACTIVE))) {
 		rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
-	else
-		rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
-
-	if (rc != MBX_SUCCESS) {
-		if (rc != MBX_TIMEOUT)
+		if (rc != MBX_SUCCESS) {
 			mempool_free(pmboxq, phba->mbox_mem_pool);
-		return;
+			return;
+		}
+	} else {
+		rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
+		if (rc != MBX_SUCCESS) {
+			if (rc != MBX_TIMEOUT)
+				mempool_free(pmboxq, phba->mbox_mem_pool);
+			return;
+		}
 	}
 
 	memset(pmboxq, 0, sizeof(LPFC_MBOXQ_t));
@@ -6739,15 +6948,19 @@
 	pmboxq->vport = vport;
 
 	if ((vport->fc_flag & FC_OFFLINE_MODE) ||
-	    (!(psli->sli_flag & LPFC_SLI_ACTIVE)))
+	    (!(psli->sli_flag & LPFC_SLI_ACTIVE))) {
 		rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL);
-	else
+		if (rc != MBX_SUCCESS) {
+			mempool_free(pmboxq, phba->mbox_mem_pool);
+			return;
+		}
+	} else {
 		rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2);
-
-	if (rc != MBX_SUCCESS) {
-		if (rc != MBX_TIMEOUT)
-			mempool_free( pmboxq, phba->mbox_mem_pool);
-		return;
+		if (rc != MBX_SUCCESS) {
+			if (rc != MBX_TIMEOUT)
+				mempool_free(pmboxq, phba->mbox_mem_pool);
+			return;
+		}
 	}
 
 	lso->link_failure_count = pmb->un.varRdLnk.linkFailureCnt;
@@ -7085,11 +7298,22 @@
 static void
 lpfc_get_hba_function_mode(struct lpfc_hba *phba)
 {
-	/* If it's a SkyHawk FCoE adapter */
-	if (phba->pcidev->device == PCI_DEVICE_ID_SKYHAWK)
+	/* If the adapter supports FCoE mode */
+	switch (phba->pcidev->device) {
+	case PCI_DEVICE_ID_SKYHAWK:
+	case PCI_DEVICE_ID_SKYHAWK_VF:
+	case PCI_DEVICE_ID_LANCER_FCOE:
+	case PCI_DEVICE_ID_LANCER_FCOE_VF:
+	case PCI_DEVICE_ID_ZEPHYR_DCSP:
+	case PCI_DEVICE_ID_HORNET:
+	case PCI_DEVICE_ID_TIGERSHARK:
+	case PCI_DEVICE_ID_TOMCAT:
 		phba->hba_flag |= HBA_FCOE_MODE;
-	else
+		break;
+	default:
+	/* for others, clear the flag */
 		phba->hba_flag &= ~HBA_FCOE_MODE;
+	}
 }
 
 /**
@@ -7099,6 +7323,7 @@
 void
 lpfc_get_cfgparam(struct lpfc_hba *phba)
 {
+	lpfc_hba_log_verbose_init(phba, lpfc_log_verbose);
 	lpfc_fcp_io_sched_init(phba, lpfc_fcp_io_sched);
 	lpfc_ns_query_init(phba, lpfc_ns_query);
 	lpfc_fcp2_no_tgt_reset_init(phba, lpfc_fcp2_no_tgt_reset);
@@ -7205,12 +7430,10 @@
 	phba->cfg_soft_wwpn = 0L;
 	lpfc_sg_seg_cnt_init(phba, lpfc_sg_seg_cnt);
 	lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth);
-	lpfc_hba_log_verbose_init(phba, lpfc_log_verbose);
 	lpfc_aer_support_init(phba, lpfc_aer_support);
 	lpfc_sriov_nr_virtfn_init(phba, lpfc_sriov_nr_virtfn);
 	lpfc_request_firmware_upgrade_init(phba, lpfc_req_fw_upgrade);
 	lpfc_suppress_link_up_init(phba, lpfc_suppress_link_up);
-	lpfc_iocb_cnt_init(phba, lpfc_iocb_cnt);
 	lpfc_delay_discovery_init(phba, lpfc_delay_discovery);
 	lpfc_sli_mode_init(phba, lpfc_sli_mode);
 	phba->cfg_enable_dss = 1;
@@ -7256,11 +7479,11 @@
 		}
 
 		if (!phba->cfg_nvmet_mrq)
-			phba->cfg_nvmet_mrq = phba->cfg_irq_chann;
+			phba->cfg_nvmet_mrq = phba->cfg_hdw_queue;
 
 		/* Adjust lpfc_nvmet_mrq to avoid running out of WQE slots */
-		if (phba->cfg_nvmet_mrq > phba->cfg_irq_chann) {
-			phba->cfg_nvmet_mrq = phba->cfg_irq_chann;
+		if (phba->cfg_nvmet_mrq > phba->cfg_hdw_queue) {
+			phba->cfg_nvmet_mrq = phba->cfg_hdw_queue;
 			lpfc_printf_log(phba, KERN_ERR, LOG_NVME_DISC,
 					"6018 Adjust lpfc_nvmet_mrq to %d\n",
 					phba->cfg_nvmet_mrq);
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/lpfc/lpfc_bsg.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/lpfc/lpfc_bsg.c
@@ -4489,12 +4489,6 @@
 	phba->mbox_ext_buf_ctx.seqNum++;
 	nemb_tp = phba->mbox_ext_buf_ctx.nembType;
 
-	dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);
-	if (!dd_data) {
-		rc = -ENOMEM;
-		goto job_error;
-	}
-
 	pbuf = (uint8_t *)dmabuf->virt;
 	size = job->request_payload.payload_len;
 	sg_copy_to_buffer(job->request_payload.sg_list,
@@ -4531,6 +4525,13 @@
 				"2968 SLI_CONFIG ext-buffer wr all %d "
 				"ebuffers received\n",
 				phba->mbox_ext_buf_ctx.numBuf);
+
+		dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);
+		if (!dd_data) {
+			rc = -ENOMEM;
+			goto job_error;
+		}
+
 		/* mailbox command structure for base driver */
 		pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
 		if (!pmboxq) {
@@ -4579,6 +4580,8 @@
 	return SLI_CONFIG_HANDLED;
 
 job_error:
+	if (pmboxq)
+		mempool_free(pmboxq, phba->mbox_mem_pool);
 	lpfc_bsg_dma_page_free(phba, dmabuf);
 	kfree(dd_data);
 
@@ -5435,10 +5438,12 @@
 		bsg_reply->reply_data.vendor_reply.vendor_rsp;
 
 	/* Current logging state */
-	if (ras_fwlog->ras_active == true)
+	spin_lock_irq(&phba->hbalock);
+	if (ras_fwlog->state == ACTIVE)
 		ras_reply->state = LPFC_RASLOG_STATE_RUNNING;
 	else
 		ras_reply->state = LPFC_RASLOG_STATE_STOPPED;
+	spin_unlock_irq(&phba->hbalock);
 
 	ras_reply->log_level = phba->ras_fwlog.fw_loglevel;
 	ras_reply->log_buff_sz = phba->cfg_ras_fwlog_buffsize;
@@ -5495,10 +5500,13 @@
 
 	if (action == LPFC_RASACTION_STOP_LOGGING) {
 		/* Check if already disabled */
-		if (ras_fwlog->ras_active == false) {
+		spin_lock_irq(&phba->hbalock);
+		if (ras_fwlog->state != ACTIVE) {
+			spin_unlock_irq(&phba->hbalock);
 			rc = -ESRCH;
 			goto ras_job_error;
 		}
+		spin_unlock_irq(&phba->hbalock);
 
 		/* Disable logging */
 		lpfc_ras_stop_fwlog(phba);
@@ -5509,8 +5517,10 @@
 		 * FW-logging with new log-level. Return status
 		 * "Logging already Running" to caller.
 		 **/
-		if (ras_fwlog->ras_active)
+		spin_lock_irq(&phba->hbalock);
+		if (ras_fwlog->state != INACTIVE)
 			action_status = -EINPROGRESS;
+		spin_unlock_irq(&phba->hbalock);
 
 		/* Enable logging */
 		rc = lpfc_sli4_ras_fwlog_init(phba, log_level,
@@ -5626,10 +5636,13 @@
 		goto ras_job_error;
 
 	/* Logging to be stopped before reading */
-	if (ras_fwlog->ras_active == true) {
+	spin_lock_irq(&phba->hbalock);
+	if (ras_fwlog->state == ACTIVE) {
+		spin_unlock_irq(&phba->hbalock);
 		rc = -EINPROGRESS;
 		goto ras_job_error;
 	}
+	spin_unlock_irq(&phba->hbalock);
 
 	if (job->request_len <
 	    sizeof(struct fc_bsg_request) +
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/lpfc/lpfc_crtn.h
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/lpfc/lpfc_crtn.h
@@ -56,9 +56,6 @@
 void lpfc_unreg_vpi(struct lpfc_hba *, uint16_t, LPFC_MBOXQ_t *);
 void lpfc_init_link(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t);
 void lpfc_request_features(struct lpfc_hba *, struct lpfcMboxq *);
-void lpfc_supported_pages(struct lpfcMboxq *);
-void lpfc_pc_sli4_params(struct lpfcMboxq *);
-int lpfc_pc_sli4_params_get(struct lpfc_hba *, LPFC_MBOXQ_t *);
 int lpfc_sli4_mbox_rsrc_extent(struct lpfc_hba *, struct lpfcMboxq *,
 			   uint16_t, uint16_t, bool);
 int lpfc_get_sli4_parameters(struct lpfc_hba *, LPFC_MBOXQ_t *);
@@ -140,9 +137,10 @@
 int lpfc_issue_els_adisc(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t);
 int lpfc_issue_els_logo(struct lpfc_vport *, struct lpfc_nodelist *, uint8_t);
 int lpfc_issue_els_npiv_logo(struct lpfc_vport *, struct lpfc_nodelist *);
-int lpfc_issue_els_scr(struct lpfc_vport *, uint32_t, uint8_t);
+int lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry);
 int lpfc_issue_els_rscn(struct lpfc_vport *vport, uint8_t retry);
 int lpfc_issue_fabric_reglogin(struct lpfc_vport *);
+int lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry);
 int lpfc_els_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *);
 int lpfc_ct_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *);
 int lpfc_els_rsp_acc(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *,
@@ -180,7 +178,7 @@
 int lpfc_get_gidft_type(struct lpfc_vport *vport, struct lpfc_iocbq *iocbq);
 int lpfc_ns_cmd(struct lpfc_vport *, int, uint8_t, uint32_t);
 int lpfc_fdmi_cmd(struct lpfc_vport *, struct lpfc_nodelist *, int, uint32_t);
-void lpfc_fdmi_num_disc_check(struct lpfc_vport *);
+void lpfc_fdmi_change_check(struct lpfc_vport *vport);
 void lpfc_delayed_disc_tmo(struct timer_list *);
 void lpfc_delayed_disc_timeout_handler(struct lpfc_vport *);
 
@@ -215,6 +213,12 @@
 irqreturn_t lpfc_sli4_intr_handler(int, void *);
 irqreturn_t lpfc_sli4_hba_intr_handler(int, void *);
 
+void lpfc_sli4_cleanup_poll_list(struct lpfc_hba *phba);
+int lpfc_sli4_poll_eq(struct lpfc_queue *q, uint8_t path);
+void lpfc_sli4_poll_hbtimer(struct timer_list *t);
+void lpfc_sli4_start_polling(struct lpfc_queue *q);
+void lpfc_sli4_stop_polling(struct lpfc_queue *q);
+
 void lpfc_read_rev(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_sli4_swap_str(struct lpfc_hba *, LPFC_MBOXQ_t *);
 void lpfc_config_ring(struct lpfc_hba *, int, LPFC_MBOXQ_t *);
@@ -586,6 +590,7 @@
 void lpfc_nvme_cmd_template(void);
 void lpfc_nvmet_cmd_template(void);
 void lpfc_nvme_cancel_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn);
+void lpfc_nvme_prep_abort_wqe(struct lpfc_iocbq *pwqeq, u16 xritag, u8 opt);
 extern int lpfc_enable_nvmet_cnt;
 extern unsigned long long lpfc_enable_nvmet[];
 extern int lpfc_no_hba_reset_cnt;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/lpfc/lpfc_ct.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/lpfc/lpfc_ct.c
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term *
  * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.     *
  * Copyright (C) 2004-2016 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
@@ -462,7 +462,6 @@
 	struct lpfc_nodelist *ndlp;
 
 	if ((vport->port_type != LPFC_NPIV_PORT) ||
-	    (fc4_type == FC_TYPE_FCP) ||
 	    !(vport->ct_flags & FC_CT_RFF_ID) || !vport->cfg_restrict_login) {
 
 		ndlp = lpfc_setup_disc_node(vport, Did);
@@ -763,9 +762,11 @@
 		    cpu_to_be16(SLI_CT_RESPONSE_FS_ACC)) {
 			lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
 					 "0208 NameServer Rsp Data: x%x x%x "
-					 "sz x%x\n",
+					 "x%x x%x sz x%x\n",
 					 vport->fc_flag,
 					 CTreq->un.gid.Fc4Type,
+					 vport->num_disc_nodes,
+					 vport->gidft_inp,
 					 irsp->un.genreq64.bdl.bdeSize);
 
 			lpfc_ns_rsp(vport,
@@ -961,9 +962,13 @@
 		if (CTrsp->CommandResponse.bits.CmdRsp ==
 		    cpu_to_be16(SLI_CT_RESPONSE_FS_ACC)) {
 			lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
-					 "4105 NameServer Rsp Data: x%x x%x\n",
+					 "4105 NameServer Rsp Data: x%x x%x "
+					 "x%x x%x sz x%x\n",
 					 vport->fc_flag,
-					 CTreq->un.gid.Fc4Type);
+					 CTreq->un.gid.Fc4Type,
+					 vport->num_disc_nodes,
+					 vport->gidft_inp,
+					 irsp->un.genreq64.bdl.bdeSize);
 
 			lpfc_ns_rsp(vport,
 				    outp,
@@ -1025,6 +1030,11 @@
 		}
 		vport->gidft_inp--;
 	}
+
+	lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+			 "6450 GID_PT cmpl inp %d disc %d\n",
+			 vport->gidft_inp, vport->num_disc_nodes);
+
 	/* Link up / RSCN discovery */
 	if ((vport->num_disc_nodes == 0) &&
 	    (vport->gidft_inp == 0)) {
@@ -1159,6 +1169,11 @@
 	/* Link up / RSCN discovery */
 	if (vport->num_disc_nodes)
 		vport->num_disc_nodes--;
+
+	lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+			 "6451 GFF_ID cmpl inp %d disc %d\n",
+			 vport->gidft_inp, vport->num_disc_nodes);
+
 	if (vport->num_disc_nodes == 0) {
 		/*
 		 * The driver has cycled through all Nports in the RSCN payload.
@@ -1477,33 +1492,35 @@
 lpfc_vport_symbolic_node_name(struct lpfc_vport *vport, char *symbol,
 	size_t size)
 {
-	char fwrev[FW_REV_STR_SIZE];
-	int n;
+	char fwrev[FW_REV_STR_SIZE] = {0};
+	char tmp[MAXHOSTNAMELEN] = {0};
 
-	lpfc_decode_firmware_rev(vport->phba, fwrev, 0);
+	memset(symbol, 0, size);
+
+	scnprintf(tmp, sizeof(tmp), "Emulex %s", vport->phba->ModelName);
+	if (strlcat(symbol, tmp, size) >= size)
+		goto buffer_done;
 
-	n = scnprintf(symbol, size, "Emulex %s", vport->phba->ModelName);
-	if (size < n)
-		return n;
-
-	n += scnprintf(symbol + n, size - n, " FV%s", fwrev);
-	if (size < n)
-		return n;
-
-	n += scnprintf(symbol + n, size - n, " DV%s.",
-		      lpfc_release_version);
-	if (size < n)
-		return n;
-
-	n += scnprintf(symbol + n, size - n, " HN:%s.",
-		      init_utsname()->nodename);
-	if (size < n)
-		return n;
+	lpfc_decode_firmware_rev(vport->phba, fwrev, 0);
+	scnprintf(tmp, sizeof(tmp), " FV%s", fwrev);
+	if (strlcat(symbol, tmp, size) >= size)
+		goto buffer_done;
+
+	scnprintf(tmp, sizeof(tmp), " DV%s", lpfc_release_version);
+	if (strlcat(symbol, tmp, size) >= size)
+		goto buffer_done;
+
+	scnprintf(tmp, sizeof(tmp), " HN:%s", vport->phba->os_host_name);
+	if (strlcat(symbol, tmp, size) >= size)
+		goto buffer_done;
 
 	/* Note :- OS name is "Linux" */
-	n += scnprintf(symbol + n, size - n, " OS:%s",
-		      init_utsname()->sysname);
-	return n;
+	scnprintf(tmp, sizeof(tmp), " OS:%s", init_utsname()->sysname);
+	strlcat(symbol, tmp, size);
+
+buffer_done:
+	return strnlen(symbol, size);
+
 }
 
 static uint32_t
@@ -1868,6 +1885,12 @@
 		if (irsp->ulpStatus == IOSTAT_LOCAL_REJECT) {
 			switch ((irsp->un.ulpWord[4] & IOERR_PARAM_MASK)) {
 			case IOERR_SLI_ABORTED:
+			case IOERR_SLI_DOWN:
+				/* Driver aborted this IO.  No retry as error
+				 * is likely Offline->Online or some adapter
+				 * error.  Recovery will try again.
+				 */
+				break;
 			case IOERR_ABORT_IN_PROGRESS:
 			case IOERR_SEQUENCE_TIMEOUT:
 			case IOERR_ILLEGAL_FRAME:
@@ -1976,14 +1999,16 @@
 
 
 /**
- * lpfc_fdmi_num_disc_check - Check how many mapped NPorts we are connected to
+ * lpfc_fdmi_change_check - Check for changed FDMI parameters
  * @vport: pointer to a host virtual N_Port data structure.
  *
- * Called from hbeat timeout routine to check if the number of discovered
- * ports has changed. If so, re-register thar port Attribute.
+ * Check how many mapped NPorts we are connected to
+ * Check if our hostname changed
+ * Called from hbeat timeout routine to check if any FDMI parameters
+ * changed. If so, re-register those Attributes.
  */
 void
-lpfc_fdmi_num_disc_check(struct lpfc_vport *vport)
+lpfc_fdmi_change_check(struct lpfc_vport *vport)
 {
 	struct lpfc_hba *phba = vport->phba;
 	struct lpfc_nodelist *ndlp;
@@ -1996,17 +2021,41 @@
 	if (!(vport->fc_flag & FC_FABRIC))
 		return;
 
+	ndlp = lpfc_findnode_did(vport, FDMI_DID);
+	if (!ndlp || !NLP_CHK_NODE_ACT(ndlp))
+		return;
+
+	/* Check if system hostname changed */
+	if (strcmp(phba->os_host_name, init_utsname()->nodename)) {
+		memset(phba->os_host_name, 0, sizeof(phba->os_host_name));
+		scnprintf(phba->os_host_name, sizeof(phba->os_host_name), "%s",
+			  init_utsname()->nodename);
+		lpfc_ns_cmd(vport, SLI_CTNS_RSNN_NN, 0, 0);
+
+		/* Since this effects multiple HBA and PORT attributes, we need
+		 * de-register and go thru the whole FDMI registration cycle.
+		 * DHBA -> DPRT -> RHBA -> RPA  (physical port)
+		 * DPRT -> RPRT (vports)
+		 */
+		if (vport->port_type == LPFC_PHYSICAL_PORT)
+			lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DHBA, 0);
+		else
+			lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DPRT, 0);
+
+		/* Since this code path registers all the port attributes
+		 * we can just return without further checking.
+		 */
+		return;
+	}
+
 	if (!(vport->fdmi_port_mask & LPFC_FDMI_PORT_ATTR_num_disc))
 		return;
 
+	/* Check if the number of mapped NPorts changed */
 	cnt = lpfc_find_map_node(vport);
 	if (cnt == vport->fdmi_num_disc)
 		return;
 
-	ndlp = lpfc_findnode_did(vport, FDMI_DID);
-	if (!ndlp || !NLP_CHK_NODE_ACT(ndlp))
-		return;
-
 	if (vport->port_type == LPFC_PHYSICAL_PORT) {
 		lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RPA,
 			      LPFC_FDMI_PORT_ATTR_num_disc);
@@ -2023,8 +2072,8 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
-	memset(ae, 0, sizeof(struct lpfc_name));
+	ae = &ad->AttrValue;
+	memset(ae, 0, sizeof(*ae));
 
 	memcpy(&ae->un.AttrWWN, &vport->fc_sparam.nodeName,
 	       sizeof(struct lpfc_name));
@@ -2040,8 +2089,8 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t len, size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
-	memset(ae, 0, 256);
+	ae = &ad->AttrValue;
+	memset(ae, 0, sizeof(*ae));
 
 	/* This string MUST be consistent with other FC platforms
 	 * supported by Broadcom.
@@ -2065,8 +2114,8 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t len, size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
-	memset(ae, 0, 256);
+	ae = &ad->AttrValue;
+	memset(ae, 0, sizeof(*ae));
 
 	strncpy(ae->un.AttrString, phba->SerialNumber,
 		sizeof(ae->un.AttrString));
@@ -2087,8 +2136,8 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t len, size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
-	memset(ae, 0, 256);
+	ae = &ad->AttrValue;
+	memset(ae, 0, sizeof(*ae));
 
 	strncpy(ae->un.AttrString, phba->ModelName,
 		sizeof(ae->un.AttrString));
@@ -2108,8 +2157,8 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t len, size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
-	memset(ae, 0, 256);
+	ae = &ad->AttrValue;
+	memset(ae, 0, sizeof(*ae));
 
 	strncpy(ae->un.AttrString, phba->ModelDesc,
 		sizeof(ae->un.AttrString));
@@ -2131,8 +2180,8 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t i, j, incr, size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
-	memset(ae, 0, 256);
+	ae = &ad->AttrValue;
+	memset(ae, 0, sizeof(*ae));
 
 	/* Convert JEDEC ID to ascii for hardware version */
 	incr = vp->rev.biuRev;
@@ -2161,8 +2210,8 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t len, size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
-	memset(ae, 0, 256);
+	ae = &ad->AttrValue;
+	memset(ae, 0, sizeof(*ae));
 
 	strncpy(ae->un.AttrString, lpfc_release_version,
 		sizeof(ae->un.AttrString));
@@ -2183,8 +2232,8 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t len, size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
-	memset(ae, 0, 256);
+	ae = &ad->AttrValue;
+	memset(ae, 0, sizeof(*ae));
 
 	if (phba->sli_rev == LPFC_SLI_REV4)
 		lpfc_decode_firmware_rev(phba, ae->un.AttrString, 1);
@@ -2208,8 +2257,8 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t len, size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
-	memset(ae, 0, 256);
+	ae = &ad->AttrValue;
+	memset(ae, 0, sizeof(*ae));
 
 	lpfc_decode_firmware_rev(phba, ae->un.AttrString, 1);
 	len = strnlen(ae->un.AttrString,
@@ -2228,8 +2277,8 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t len, size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
-	memset(ae, 0, 256);
+	ae = &ad->AttrValue;
+	memset(ae, 0, sizeof(*ae));
 
 	snprintf(ae->un.AttrString, sizeof(ae->un.AttrString), "%s %s %s",
 		 init_utsname()->sysname,
@@ -2251,7 +2300,7 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
+	ae = &ad->AttrValue;
 
 	ae->un.AttrInt =  cpu_to_be32(LPFC_MAX_CT_SIZE);
 	size = FOURBYTES + sizeof(uint32_t);
@@ -2267,8 +2316,8 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t len, size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
-	memset(ae, 0, 256);
+	ae = &ad->AttrValue;
+	memset(ae, 0, sizeof(*ae));
 
 	len = lpfc_vport_symbolic_node_name(vport,
 				ae->un.AttrString, 256);
@@ -2286,7 +2335,7 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
+	ae = &ad->AttrValue;
 
 	/* Nothing is defined for this currently */
 	ae->un.AttrInt =  cpu_to_be32(0);
@@ -2303,7 +2352,7 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
+	ae = &ad->AttrValue;
 
 	/* Each driver instance corresponds to a single port */
 	ae->un.AttrInt =  cpu_to_be32(1);
@@ -2320,8 +2369,8 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
-	memset(ae, 0, sizeof(struct lpfc_name));
+	ae = &ad->AttrValue;
+	memset(ae, 0, sizeof(*ae));
 
 	memcpy(&ae->un.AttrWWN, &vport->fabric_nodename,
 	       sizeof(struct lpfc_name));
@@ -2339,8 +2388,8 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t len, size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
-	memset(ae, 0, 256);
+	ae = &ad->AttrValue;
+	memset(ae, 0, sizeof(*ae));
 
 	strlcat(ae->un.AttrString, phba->BIOSVersion,
 		sizeof(ae->un.AttrString));
@@ -2360,7 +2409,7 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
+	ae = &ad->AttrValue;
 
 	/* Driver doesn't have access to this information */
 	ae->un.AttrInt =  cpu_to_be32(0);
@@ -2377,8 +2426,8 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t len, size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
-	memset(ae, 0, 256);
+	ae = &ad->AttrValue;
+	memset(ae, 0, sizeof(*ae));
 
 	strncpy(ae->un.AttrString, "EMULEX",
 		sizeof(ae->un.AttrString));
@@ -2400,10 +2449,9 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
-	memset(ae, 0, 32);
+	ae = &ad->AttrValue;
+	memset(ae, 0, sizeof(*ae));
 
-	ae->un.AttrTypes[3] = 0x02; /* Type 0x1 - ELS */
 	ae->un.AttrTypes[2] = 0x01; /* Type 0x8 - FCP */
 	ae->un.AttrTypes[7] = 0x01; /* Type 0x20 - CT */
 
@@ -2426,7 +2474,7 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
+	ae = &ad->AttrValue;
 
 	ae->un.AttrInt = 0;
 	if (!(phba->hba_flag & HBA_FCOE_MODE)) {
@@ -2480,7 +2528,7 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
+	ae = &ad->AttrValue;
 
 	if (!(phba->hba_flag & HBA_FCOE_MODE)) {
 		switch (phba->fc_linkspeed) {
@@ -2550,7 +2598,7 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
+	ae = &ad->AttrValue;
 
 	hsp = (struct serv_parm *)&vport->fc_sparam;
 	ae->un.AttrInt = (((uint32_t) hsp->cmn.bbRcvSizeMsb & 0x0F) << 8) |
@@ -2570,8 +2618,8 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t len, size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
-	memset(ae, 0, 256);
+	ae = &ad->AttrValue;
+	memset(ae, 0, sizeof(*ae));
 
 	snprintf(ae->un.AttrString, sizeof(ae->un.AttrString),
 		 "/sys/class/scsi_host/host%d", shost->host_no);
@@ -2591,11 +2639,11 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t len, size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
-	memset(ae, 0, 256);
+	ae = &ad->AttrValue;
+	memset(ae, 0, sizeof(*ae));
 
-	snprintf(ae->un.AttrString, sizeof(ae->un.AttrString), "%s",
-		 init_utsname()->nodename);
+	scnprintf(ae->un.AttrString, sizeof(ae->un.AttrString), "%s",
+		  vport->phba->os_host_name);
 
 	len = strnlen(ae->un.AttrString, sizeof(ae->un.AttrString));
 	len += (len & 3) ? (4 - (len & 3)) : 4;
@@ -2612,8 +2660,8 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
-	memset(ae, 0,  sizeof(struct lpfc_name));
+	ae = &ad->AttrValue;
+	memset(ae, 0, sizeof(*ae));
 
 	memcpy(&ae->un.AttrWWN, &vport->fc_sparam.nodeName,
 	       sizeof(struct lpfc_name));
@@ -2630,8 +2678,8 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
-	memset(ae, 0,  sizeof(struct lpfc_name));
+	ae = &ad->AttrValue;
+	memset(ae, 0, sizeof(*ae));
 
 	memcpy(&ae->un.AttrWWN, &vport->fc_sparam.portName,
 	       sizeof(struct lpfc_name));
@@ -2648,8 +2696,8 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t len, size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
-	memset(ae, 0, 256);
+	ae = &ad->AttrValue;
+	memset(ae, 0, sizeof(*ae));
 
 	len = lpfc_vport_symbolic_port_name(vport, ae->un.AttrString, 256);
 	len += (len & 3) ? (4 - (len & 3)) : 4;
@@ -2667,7 +2715,7 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
+	ae = &ad->AttrValue;
 	if (phba->fc_topology == LPFC_TOPOLOGY_LOOP)
 		ae->un.AttrInt =  cpu_to_be32(LPFC_FDMI_PORTTYPE_NLPORT);
 	else
@@ -2685,7 +2733,7 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
+	ae = &ad->AttrValue;
 	ae->un.AttrInt = cpu_to_be32(FC_COS_CLASS2 | FC_COS_CLASS3);
 	size = FOURBYTES + sizeof(uint32_t);
 	ad->AttrLen = cpu_to_be16(size);
@@ -2700,8 +2748,8 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
-	memset(ae, 0,  sizeof(struct lpfc_name));
+	ae = &ad->AttrValue;
+	memset(ae, 0, sizeof(*ae));
 
 	memcpy(&ae->un.AttrWWN, &vport->fabric_portname,
 	       sizeof(struct lpfc_name));
@@ -2718,10 +2766,9 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
-	memset(ae, 0, 32);
+	ae = &ad->AttrValue;
+	memset(ae, 0, sizeof(*ae));
 
-	ae->un.AttrTypes[3] = 0x02; /* Type 0x1 - ELS */
 	ae->un.AttrTypes[2] = 0x01; /* Type 0x8 - FCP */
 	ae->un.AttrTypes[7] = 0x01; /* Type 0x20 - CT */
 
@@ -2742,7 +2789,7 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
+	ae = &ad->AttrValue;
 	/* Link Up - operational */
 	ae->un.AttrInt =  cpu_to_be32(LPFC_FDMI_PORTSTATE_ONLINE);
 	size = FOURBYTES + sizeof(uint32_t);
@@ -2758,7 +2805,7 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
+	ae = &ad->AttrValue;
 	vport->fdmi_num_disc = lpfc_find_map_node(vport);
 	ae->un.AttrInt = cpu_to_be32(vport->fdmi_num_disc);
 	size = FOURBYTES + sizeof(uint32_t);
@@ -2774,7 +2821,7 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
+	ae = &ad->AttrValue;
 	ae->un.AttrInt =  cpu_to_be32(vport->fc_myDID);
 	size = FOURBYTES + sizeof(uint32_t);
 	ad->AttrLen = cpu_to_be16(size);
@@ -2789,8 +2836,8 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t len, size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
-	memset(ae, 0, 256);
+	ae = &ad->AttrValue;
+	memset(ae, 0, sizeof(*ae));
 
 	strncpy(ae->un.AttrString, "Smart SAN Initiator",
 		sizeof(ae->un.AttrString));
@@ -2810,8 +2857,8 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
-	memset(ae, 0, 256);
+	ae = &ad->AttrValue;
+	memset(ae, 0, sizeof(*ae));
 
 	memcpy(&ae->un.AttrString, &vport->fc_sparam.nodeName,
 	       sizeof(struct lpfc_name));
@@ -2831,8 +2878,8 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t len, size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
-	memset(ae, 0, 256);
+	ae = &ad->AttrValue;
+	memset(ae, 0, sizeof(*ae));
 
 	strncpy(ae->un.AttrString, "Smart SAN Version 2.0",
 		sizeof(ae->un.AttrString));
@@ -2853,8 +2900,8 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t len, size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
-	memset(ae, 0, 256);
+	ae = &ad->AttrValue;
+	memset(ae, 0, sizeof(*ae));
 
 	strncpy(ae->un.AttrString, phba->ModelName,
 		sizeof(ae->un.AttrString));
@@ -2873,7 +2920,7 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
+	ae = &ad->AttrValue;
 
 	/* SRIOV (type 3) is not supported */
 	if (vport->vpi)
@@ -2893,7 +2940,7 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
+	ae = &ad->AttrValue;
 	ae->un.AttrInt =  cpu_to_be32(0);
 	size = FOURBYTES + sizeof(uint32_t);
 	ad->AttrLen = cpu_to_be16(size);
@@ -2908,7 +2955,7 @@
 	struct lpfc_fdmi_attr_entry *ae;
 	uint32_t size;
 
-	ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
+	ae = &ad->AttrValue;
 	ae->un.AttrInt =  cpu_to_be32(1);
 	size = FOURBYTES + sizeof(uint32_t);
 	ad->AttrLen = cpu_to_be16(size);
@@ -3056,7 +3103,8 @@
 			/* Registered Port List */
 			/* One entry (port) per adapter */
 			rh->rpl.EntryCnt = cpu_to_be32(1);
-			memcpy(&rh->rpl.pe, &phba->pport->fc_sparam.portName,
+			memcpy(&rh->rpl.pe.PortName,
+			       &phba->pport->fc_sparam.portName,
 			       sizeof(struct lpfc_name));
 
 			/* point to the HBA attribute block */
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/lpfc/lpfc_debugfs.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -31,6 +31,7 @@
 #include <linux/pci.h>
 #include <linux/spinlock.h>
 #include <linux/ctype.h>
+#include <linux/vmalloc.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_device.h>
@@ -2046,6 +2047,7 @@
 	char mybuf[64];
 	char *pbuf;
 	int i;
+	size_t bsize;
 
 	/* Protect copy from user */
 	if (!access_ok(buf, nbytes))
@@ -2053,7 +2055,9 @@
 
 	memset(mybuf, 0, sizeof(mybuf));
 
-	if (copy_from_user(mybuf, buf, nbytes))
+	bsize = min(nbytes, (sizeof(mybuf) - 1));
+
+	if (copy_from_user(mybuf, buf, bsize))
 		return -EFAULT;
 	pbuf = &mybuf[0];
 
@@ -2074,10 +2078,107 @@
 			qp->lock_conflict.wq_access = 0;
 		}
 	}
-	return nbytes;
+	return bsize;
 }
 #endif
 
+static int lpfc_debugfs_ras_log_data(struct lpfc_hba *phba,
+				     char *buffer, int size)
+{
+	int copied = 0;
+	struct lpfc_dmabuf *dmabuf, *next;
+
+	memset(buffer, 0, size);
+
+	spin_lock_irq(&phba->hbalock);
+	if (phba->ras_fwlog.state != ACTIVE) {
+		spin_unlock_irq(&phba->hbalock);
+		return -EINVAL;
+	}
+	spin_unlock_irq(&phba->hbalock);
+
+	list_for_each_entry_safe(dmabuf, next,
+				 &phba->ras_fwlog.fwlog_buff_list, list) {
+		/* Check if copying will go over size and a '\0' char */
+		if ((copied + LPFC_RAS_MAX_ENTRY_SIZE) >= (size - 1)) {
+			memcpy(buffer + copied, dmabuf->virt,
+			       size - copied - 1);
+			copied += size - copied - 1;
+			break;
+		}
+		memcpy(buffer + copied, dmabuf->virt, LPFC_RAS_MAX_ENTRY_SIZE);
+		copied += LPFC_RAS_MAX_ENTRY_SIZE;
+	}
+	return copied;
+}
+
+static int
+lpfc_debugfs_ras_log_release(struct inode *inode, struct file *file)
+{
+	struct lpfc_debug *debug = file->private_data;
+
+	vfree(debug->buffer);
+	kfree(debug);
+
+	return 0;
+}
+
+/**
+ * lpfc_debugfs_ras_log_open - Open the RAS log debugfs buffer
+ * @inode: The inode pointer that contains a vport pointer.
+ * @file: The file pointer to attach the log output.
+ *
+ * Description:
+ * This routine is the entry point for the debugfs open file operation. It gets
+ * the vport from the i_private field in @inode, allocates the necessary buffer
+ * for the log, fills the buffer from the in-memory log for this vport, and then
+ * returns a pointer to that log in the private_data field in @file.
+ *
+ * Returns:
+ * This function returns zero if successful. On error it will return a negative
+ * error value.
+ **/
+static int
+lpfc_debugfs_ras_log_open(struct inode *inode, struct file *file)
+{
+	struct lpfc_hba *phba = inode->i_private;
+	struct lpfc_debug *debug;
+	int size;
+	int rc = -ENOMEM;
+
+	spin_lock_irq(&phba->hbalock);
+	if (phba->ras_fwlog.state != ACTIVE) {
+		spin_unlock_irq(&phba->hbalock);
+		rc = -EINVAL;
+		goto out;
+	}
+	spin_unlock_irq(&phba->hbalock);
+	debug = kmalloc(sizeof(*debug), GFP_KERNEL);
+	if (!debug)
+		goto out;
+
+	size = LPFC_RAS_MIN_BUFF_POST_SIZE * phba->cfg_ras_fwlog_buffsize;
+	debug->buffer = vmalloc(size);
+	if (!debug->buffer)
+		goto free_debug;
+
+	debug->len = lpfc_debugfs_ras_log_data(phba, debug->buffer, size);
+	if (debug->len < 0) {
+		rc = -EINVAL;
+		goto free_buffer;
+	}
+	file->private_data = debug;
+
+	return 0;
+
+free_buffer:
+	vfree(debug->buffer);
+free_debug:
+	kfree(debug);
+out:
+	return rc;
+}
+
 /**
  * lpfc_debugfs_dumpHBASlim_open - Open the Dump HBA SLIM debugfs buffer
  * @inode: The inode pointer that contains a vport pointer.
@@ -2217,7 +2318,7 @@
 	memset(dstbuf, 0, 33);
 	size = (nbytes < 32) ? nbytes : 32;
 	if (copy_from_user(dstbuf, buf, size))
-		return 0;
+		return -EFAULT;
 
 	if (dent == phba->debug_InjErrLBA) {
 		if ((buf[0] == 'o') && (buf[1] == 'f') && (buf[2] == 'f'))
@@ -2225,7 +2326,7 @@
 	}
 
 	if ((tmp == 0) && (kstrtoull(dstbuf, 0, &tmp)))
-		return 0;
+		return -EINVAL;
 
 	if (dent == phba->debug_writeGuard)
 		phba->lpfc_injerr_wgrd_cnt = (uint32_t)tmp;
@@ -2402,8 +2503,8 @@
 	struct lpfc_sli4_hdw_queue *qp;
 	struct lpfc_multixri_pool *multixri_pool;
 
-	if (nbytes > 64)
-		nbytes = 64;
+	if (nbytes > sizeof(mybuf) - 1)
+		nbytes = sizeof(mybuf) - 1;
 
 	/* Protect copy from user */
 	if (!access_ok(buf, nbytes))
@@ -2487,8 +2588,8 @@
 	if (!phba->targetport)
 		return -ENXIO;
 
-	if (nbytes > 64)
-		nbytes = 64;
+	if (nbytes > sizeof(mybuf) - 1)
+		nbytes = sizeof(mybuf) - 1;
 
 	memset(mybuf, 0, sizeof(mybuf));
 
@@ -2629,8 +2730,8 @@
 	char mybuf[64];
 	char *pbuf;
 
-	if (nbytes > 64)
-		nbytes = 64;
+	if (nbytes > sizeof(mybuf) - 1)
+		nbytes = sizeof(mybuf) - 1;
 
 	memset(mybuf, 0, sizeof(mybuf));
 
@@ -2757,8 +2858,8 @@
 	char mybuf[64];
 	char *pbuf;
 
-	if (nbytes > 64)
-		nbytes = 64;
+	if (nbytes > sizeof(mybuf) - 1)
+		nbytes = sizeof(mybuf) - 1;
 
 	memset(mybuf, 0, sizeof(mybuf));
 
@@ -2863,8 +2964,8 @@
 	char *pbuf;
 	int i, j;
 
-	if (nbytes > 64)
-		nbytes = 64;
+	if (nbytes > sizeof(mybuf) - 1)
+		nbytes = sizeof(mybuf) - 1;
 
 	memset(mybuf, 0, sizeof(mybuf));
 
@@ -5286,6 +5387,16 @@
 };
 #endif
 
+#undef lpfc_debugfs_ras_log
+static const struct file_operations lpfc_debugfs_ras_log = {
+	.owner =        THIS_MODULE,
+	.open =         lpfc_debugfs_ras_log_open,
+	.llseek =       lpfc_debugfs_lseek,
+	.read =         lpfc_debugfs_read,
+	.release =      lpfc_debugfs_ras_log_release,
+};
+#endif
+
 #undef lpfc_debugfs_op_dumpHBASlim
 static const struct file_operations lpfc_debugfs_op_dumpHBASlim = {
 	.owner =        THIS_MODULE,
@@ -5457,7 +5568,6 @@
 	.release =      lpfc_idiag_cmd_release,
 };
 
-#endif
 
 /* lpfc_idiag_mbxacc_dump_bsg_mbox - idiag debugfs dump bsg mailbox command
  * @phba: Pointer to HBA context object.
@@ -5707,6 +5817,19 @@
 			goto debug_failed;
 		}
 
+		/* RAS log */
+		snprintf(name, sizeof(name), "ras_log");
+		phba->debug_ras_log =
+			debugfs_create_file(name, 0644,
+					    phba->hba_debugfs_root,
+					    phba, &lpfc_debugfs_ras_log);
+		if (!phba->debug_ras_log) {
+			lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+					 "6148 Cannot create debugfs"
+					 " ras_log\n");
+			goto debug_failed;
+		}
+
 		/* Setup hbqinfo */
 		snprintf(name, sizeof(name), "hbqinfo");
 		phba->debug_hbqinfo =
@@ -6117,6 +6240,9 @@
 		debugfs_remove(phba->debug_hbqinfo); /* hbqinfo */
 		phba->debug_hbqinfo = NULL;
 
+		debugfs_remove(phba->debug_ras_log);
+		phba->debug_ras_log = NULL;
+
 #ifdef LPFC_HDWQ_LOCK_STAT
 		debugfs_remove(phba->debug_lockstat); /* lockstat */
 		phba->debug_lockstat = NULL;
--- linux-xilinx-zynqmp-5.4.0.orig/drivers/scsi/lpfc/lpfc_els.c
+++ linux-xilinx-zynqmp-5.4.0/drivers/scsi/lpfc/lpfc_els.c
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term *
  * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.     *
  * Copyright (C) 2004-2016 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
@@ -1066,7 +1066,8 @@
 
 		/* FLOGI failed, so there is no fabric */
 		spin_lock_irq(shost->host_lock);
-		vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
+		vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP |
+				    FC_PT2PT_NO_NVME);
 		spin_unlock_irq(shost->host_lock);
 
 		/* If private loop, then allow max outstanding els to be
@@ -1179,6 +1180,15 @@
 			phba->fcf.fcf_redisc_attempted = 0; /* reset */
 			goto out;
 		}
+	} else if (vport->port_state > LPFC_FLOGI &&
+		   vport->fc_flag & FC_PT2PT) {
+		/*
+		 * In a p2p topology, it is possible that discovery has
+		 * already progressed, and this completion can be ignored.
+		 * Recheck the indicated topology.
+		 */
+		if (!sp->cmn.fPort)
+			goto out;
 	}
 
 flogifail:
@@ -2236,6 +2246,7 @@
 	struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
 	IOCB_t *irsp;
 	struct lpfc_nodelist *ndlp;
+	char *mode;
 
 	/* we pass cmdiocb to state machine which needs rspiocb as well */
 	cmdiocb->context_un.rsp_iocb = rspiocb;
@@ -2273,8 +2284,17 @@
 			goto out;
 		}
 
+		/* If we don't send GFT_ID to Fabric, a PRLI error
+		 * could be expected.
+		 */
+		if ((vport->fc_flag & FC_FABRIC) ||
+		    (vport->cfg_enable_fc4_type != LPFC_ENABLE_BOTH))
+			mode = KERN_ERR;
+		else
+			mode = KERN_INFO;
+
 		/* PRLI failed */
-		lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+		lpfc_printf_vlog(vport, mode, LOG_ELS,
 				 "2754 PRLI failure DID:%06X Status:x%x/x%x, "
 				 "data: x%x\n",
 				 ndlp->nlp_DID, irsp->ulpStatus,
@@ -2998,10 +3018,9 @@
  * This routine is a generic completion callback function for ELS commands.
  * Specifically, it is the callback function which does not need to perform
  * any command specific operations. It is currently used by the ELS command
- * issuing routines for the ELS State Change  Request (SCR),
- * lpfc_issue_els_scr(), and the ELS Fibre Channel Address Resolution
- * Protocol Response (FARPR) routine, lpfc_issue_els_farpr(). Other than
- * certain debug loggings, this callback function simply invokes the
+ * issuing routines for RSCN, lpfc_issue_els_rscn, and the ELS Fibre Channel
+ * Address Resolution Protocol Response (FARPR) routine, lpfc_issue_els_farpr().
+ * Other than certain debug loggings, this callback function simply invokes the
  * lpfc_els_chk_latt() routine to check whether link went down during the
  * discovery process.
  **/
@@ -3015,14 +3034,117 @@
 	irsp = &rspiocb->iocb;
 
 	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+			      "ELS cmd cmpl:    status:x%x/x%x did:x%x",
+			      irsp->ulpStatus, irsp->un.ulpWord[4],
+			      irsp->un.elsreq64.remoteID);
+
+	/* ELS cmd tag <ulpIoTag> completes */
+	lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+			 "0106 ELS cmd tag x%x completes Data: x%x x%x x%x\n",
+			 irsp->ulpIoTag, irsp->ulpStatus,
+			 irsp->un.ulpWord[4], irsp->ulpTimeout);
+
+	/* Check to see if link went down during discovery */
+	lpfc_els_chk_latt(vport);
+	lpfc_els_free_iocb(phba, cmdiocb);
+}
+
+/**
+ * lpfc_cmpl_els_disc_cmd - Completion callback function for Discovery ELS cmd
+ * @phba: pointer to lpfc hba data structure.
+ * @cmdiocb: pointer to lpfc command iocb data structure.
+ * @rspiocb: pointer to lpfc response iocb data structure.
+ *
+ * This routine is a generic completion callback function for Discovery ELS cmd.
+ * Currently used by the ELS command issuing routines for the ELS State Change
+ * Request (SCR), lpfc_issue_els_scr() and the ELS RDF, lpfc_issue_els_rdf().
+ * These commands will be retried once only for ELS timeout errors.
+ **/
+static void
+lpfc_cmpl_els_disc_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+		       struct lpfc_iocbq *rspiocb)
+{
+	struct lpfc_vport *vport = cmdiocb->vport;
+	IOCB_t *irsp;
+	struct lpfc_els_rdf_rsp *prdf;
+	struct lpfc_dmabuf *pcmd, *prsp;
+	u32 *pdata;
+	u32 cmd;
+
+	irsp = &rspiocb->iocb;
+
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
 		"ELS cmd cmpl:    status:x%x/x%x did:x%x",
 		irsp->ulpStatus, irsp->un.ulpWord[4],
 		irsp->un.elsreq64.remoteID);
 	/* ELS cmd tag <ulpIoTag> completes */
 	lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
-			 "0106 ELS cmd tag x%x completes Data: x%x x%x x%x\n",
+			 "0217 ELS cmd tag x%x completes Data: x%x x%x x%x "
+			 "x%x\n",
 			 irsp->ulpIoTag, irsp->ulpStatus,
-			 irsp->un.ulpWord[4], irsp->ulpTimeout);
+			 irsp->un.ulpWord[4], irsp->ulpTimeout,
+			 cmdiocb->retry);
+
+	pcmd = (struct lpfc_dmabuf *)cmdiocb->context2;
+	if (!pcmd)
+		goto out;
+
+	pdata = (u32 *)pcmd->virt;
+	if (!pdata)
+		goto out;
+	cmd = *pdata;
+
+	/* Only 1 retry for ELS Timeout only */
+	if (irsp->ulpStatus == IOSTAT_LOCAL_REJECT &&
+	    ((irsp->un.ulpWord[4] & IOERR_PARAM_MASK) ==
+	    IOERR_SEQUENCE_TIMEOUT)) {
+		cmdiocb->retry++;
+		if (cmdiocb->retry <= 1) {
+			switch (cmd) {
+			case ELS_CMD_SCR:
+				lpfc_issue_els_scr(vport, cmdiocb->retry);
+				break;
+			case ELS_CMD_RDF:
+				cmdiocb->context1 = NULL; /* save ndlp refcnt */
+				lpfc_issue_els_rdf(vport, cmdiocb->retry);
+				break;
+			}
+			goto out;
+		}
+		phba->fc_stat.elsRetryExceeded++;
+	}
+	if (irsp->ulpStatus) {
+		/* ELS discovery cmd completes with error */
+		lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS,
+				 "4203 ELS cmd x%x error: x%x x%X\n", cmd,
+				 irsp->ulpStatus, irsp->un.ulpWord[4]);
+		goto out;
+	}
+
+	/* The RDF response doesn't have any impact on the running driver
+	 * but the notification descriptors are dumped here for support.
+	 */
+	if (cmd == ELS_CMD_RDF) {
+		int i;
+
+		prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf, list);
+		if (!prsp)
+			goto out;
+
+		prdf = (struct lpfc_els_rdf_rsp *)prsp->virt;
+		if (!prdf)
+			goto out;
+
+		for (i = 0; i < ELS_RDF_REG_TAG_CNT &&
+			    i < be32_to_cpu(prdf->reg_d1.reg_desc.count); i++)
+			lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+				 "4677 Fabric RDF Notication Grant Data: "
+				 "0x%08x\n",
+				 be32_to_cpu(
+					prdf->reg_d1.desc_tags[i]));
+	}
+
+out:
 	/* Check to see if link went down during discovery */
 	lpfc_els_chk_latt(vport);
 	lpfc_els_free_iocb(phba, cmdiocb);
@@ -3032,11 +3154,10 @@
 /**
  * lpfc_issue_els_scr - Issue a scr to an node on a vport
  * @vport: pointer to a host virtual N_Port data structure.
- * @nportid: N_Port identifier to the remote node.
- * @retry: number of retries to the command IOCB.
+ * @retry: retry counter for the command IOCB.
  *
  * This routine issues a State Change Request (SCR) to a fabric node
- * on a @vport. The remote node @nportid is passed into the function. It
+ * on a @vport. The remote node is Fabric Controller (0xfffffd). It
  * first search the @vport node list to find the matching ndlp. If no such
  * ndlp is found, a new ndlp shall be created for this (SCR) purpose. An
  * IOCB is allocated, payload prepared, and the lpfc_sli_issue_iocb()
@@ -3052,7 +3173,7 @@
  *   1 - Failed to issue scr command
  **/
 int
-lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
+lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry)
 {
 	struct lpfc_hba  *phba = vport->phba;
 	struct lpfc_iocbq *elsiocb;
@@ -3062,9 +3183,9 @@
 
 	cmdsize = (sizeof(uint32_t) + sizeof(SCR));
 
-	ndlp = lpfc_findnode_did(vport, nportid);
+	ndlp = lpfc_findnode_did(vport, Fabric_Cntl_DID);
 	if (!ndlp) {
-		ndlp = lpfc_nlp_init(vport, nportid);
+		ndlp = lpfc_nlp_init(vport, Fabric_Cntl_DID);
 		if (!ndlp)
 			return 1;
 		lpfc_enqueue_node(vport, ndlp);
@@ -3099,7 +3220,7 @@
 		ndlp->nlp_DID, 0, 0);
 
 	phba->fc_stat.elsXmitSCR++;
-	elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd;
+	elsiocb->iocb_cmpl = lpfc_cmpl_els_disc_cmd;
 	if (lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0) ==
 	    IOCB_ERROR) {
 		/* The additional lpfc_nlp_put will cause the following
@@ -3329,6 +3450,102 @@
 	/* This will cause the callback-function lpfc_cmpl_els_cmd to
 	 * trigger the release of the node.
 	 */
+	/* Don't release reference count as RDF is likely outstanding */
+	return 0;
+}
+
+/**
+ * lpfc_issue_els_rdf - Register for diagnostic functions from the fabric.
+ * @vport: pointer to a host virtual N_Port data structure.
+ * @retry: retry counter for the command IOCB.
+ *
+ * This routine issues an ELS RDF to the Fabric Controller to register
+ * for diagnostic functions.
+ *
+ * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
+ * will be incremented by 1 for holding the ndlp and the reference to ndlp
+ * will be stored into the context1 field of the IOCB for the completion
+ * callback function to the RDF ELS command.
+ *
+ * Return code
+ *   0 - Successfully issued rdf command
+ *   1 - Failed to issue rdf command
+ **/
+int
+lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry)
+{
+	struct lpfc_hba *phba = vport->phba;
+	struct lpfc_iocbq *elsiocb;
+	struct lpfc_els_rdf_req *prdf;
+	struct lpfc_nodelist *ndlp;
+	uint16_t cmdsize;
+
+	cmdsize = sizeof(*prdf);
+
+	ndlp = lpfc_findnode_did(vport, Fabric_Cntl_DID);
+	if (!ndlp) {
+		ndlp = lpfc_nlp_init(vport, Fabric_Cntl_DID);
+		if (!ndlp)
+			return -ENODEV;
+		lpfc_enqueue_node(vport, ndlp);
+	} else if (!NLP_CHK_NODE_ACT(ndlp)) {
+		ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE);
+		if (!ndlp)
+			return -ENODEV;
+	}
+
+	/* RDF ELS is not required on an NPIV VN_Port.  */
+	if (vport->port_type == LPFC_NPIV_PORT) {
+		lpfc_nlp_put(ndlp);
+		return -EACCES;
+	}
+
+	elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
+				     ndlp->nlp_DID, ELS_CMD_RDF);
+	if (!elsiocb) {
+		/* This will trigger the release of the node just
+		 * allocated
+		 */
+		lpfc_nlp_put(ndlp);
+		return -ENOMEM;
+	}
+
+	/* Configure the payload for the supported FPIN events. */
+	prdf = (struct lpfc_els_rdf_req *)
+		(((struct lpfc_dmabuf *)elsiocb->context2)->virt);
+	memset(prdf, 0, cmdsize);
+	prdf->rdf.fpin_cmd = ELS_RDF;
+	prdf->rdf.desc_len = cpu_to_be32(sizeof(struct lpfc_els_rdf_req) -
+					 sizeof(struct fc_els_rdf));
+	prdf->reg_d1.reg_desc.desc_tag = cpu_to_be32(ELS_DTAG_FPIN_REGISTER);
+	prdf->reg_d1.reg_desc.desc_len = cpu_to_be32(
+				FC_TLV_DESC_LENGTH_FROM_SZ(prdf->reg_d1));
+	prdf->reg_d1.reg_desc.count = cpu_to_be32(ELS_RDF_REG_TAG_CNT);
+	prdf->reg_d1.desc_tags[0] = cpu_to_be32(ELS_DTAG_LNK_INTEGRITY);
+
+	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+			      "Issue RDF:       did:x%x",
+			      ndlp->nlp_DID, 0, 0);
+
+	lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+			 "6444 Xmit RDF to remote NPORT x%x\n",
+			 ndlp->nlp_DID);
+
+	elsiocb->iocb_cmpl = lpfc_cmpl_els_disc_cmd;
+	if (lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0) ==
+	    IOCB_ERROR) {
+		/* The additional lpfc_nlp_put will cause the following
+		 * lpfc_els_free_iocb routine to trigger the rlease of
+		 * the node.
+		 */
+		lpfc_nlp_put(ndlp);
+		lpfc_els_free_iocb(phba, elsiocb);
+		return -EIO;
+	}
+
+	/* An RDF was issued - this put ensures the ndlp is cleaned up
+	 * when the RDF completes.
+	 */
 	lpfc_nlp_put(ndlp);
 	return 0;
 }
@@ -3721,6 +3938,23 @@
 		/* Added for Vendor specifc support
 		 * Just keep retrying for these Rsn / Exp codes
 		 */
+		if ((vport->fc_flag & FC_PT2PT) &&
+		    cmd == ELS_CMD_NVMEPRLI) {
+			switch (stat.un.b.lsRjtRsnCode) {
+			case LSRJT_UNABLE_TPC:
+			case LSRJT_INVALID_CMD:
+			case LSRJT_LOGICAL_ERR:
+			case LSRJT_CMD_UNSUPPORTED:
+				lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS,
+						 "0168 NVME PRLI LS_RJT "
+						 "reason %x port doesn't "
+						 "support NVME, disabling NVME\n",
+						 stat.un.b.lsRjtRsnCode);
+				retry = 0;
+				vport->fc_flag |= FC_PT2PT_NO_NVME;
+				goto out_retry;
+			}
+		}
 		switch (stat.un.b.lsRjtRsnCode) {
 		case LSRJT_UNABLE_TPC:
 			/* The driver has a VALID PLOGI but the rport has
@@ -4291,6 +4525,11 @@
 
 	irsp = &rspiocb->iocb;
 
+	if (!vport) {
+		lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+				"3177 ELS response failed\n");
+		goto out;
+	}
 	if (cmdiocb->context_un.
[file cut: first 33554432 bytes kept]
[document cut: first 30977494 of 33554004 characters kept]
